summaryrefslogtreecommitdiff
path: root/chromium/tools
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/tools
downloadqtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz
Initial import.
Diffstat (limited to 'chromium/tools')
-rw-r--r--chromium/tools/DEPS6
-rw-r--r--chromium/tools/OWNERS3
-rw-r--r--chromium/tools/PRESUBMIT.py48
-rw-r--r--chromium/tools/android/OWNERS6
-rw-r--r--chromium/tools/android/adb_reboot/adb_reboot.c43
-rw-r--r--chromium/tools/android/adb_reboot/adb_reboot.gyp14
-rw-r--r--chromium/tools/android/android_tools.gyp27
-rwxr-xr-xchromium/tools/android/asan/asanwrapper.sh9
-rw-r--r--chromium/tools/android/common/adb_connection.cc107
-rw-r--r--chromium/tools/android/common/adb_connection.h18
-rw-r--r--chromium/tools/android/common/common.gyp26
-rw-r--r--chromium/tools/android/common/daemon.cc75
-rw-r--r--chromium/tools/android/common/daemon.h28
-rw-r--r--chromium/tools/android/common/net.cc40
-rw-r--r--chromium/tools/android/common/net.h25
-rw-r--r--chromium/tools/android/device_stats_monitor/device_stats_monitor.cc108
-rw-r--r--chromium/tools/android/device_stats_monitor/device_stats_monitor.gyp41
-rw-r--r--chromium/tools/android/fake_dns/DEPS3
-rw-r--r--chromium/tools/android/fake_dns/fake_dns.cc238
-rw-r--r--chromium/tools/android/fake_dns/fake_dns.gyp44
-rwxr-xr-xchromium/tools/android/find_unused_resources.py126
-rw-r--r--chromium/tools/android/findbugs_plugin/README15
-rw-r--r--chromium/tools/android/findbugs_plugin/build.xml48
-rw-r--r--chromium/tools/android/findbugs_plugin/findbugs.xml18
-rw-r--r--chromium/tools/android/findbugs_plugin/findbugs_plugin.gyp16
-rw-r--r--chromium/tools/android/findbugs_plugin/lib/chromiumPlugin.jarbin0 -> 3913 bytes
-rw-r--r--chromium/tools/android/findbugs_plugin/messages.xml56
-rw-r--r--chromium/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedMethodDetector.java38
-rw-r--r--chromium/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedThisDetector.java73
-rw-r--r--chromium/tools/android/forwarder/forwarder.cc426
-rw-r--r--chromium/tools/android/forwarder/forwarder.gyp43
-rw-r--r--chromium/tools/android/forwarder2/command.cc96
-rw-r--r--chromium/tools/android/forwarder2/command.h48
-rw-r--r--chromium/tools/android/forwarder2/common.cc28
-rw-r--r--chromium/tools/android/forwarder2/common.h89
-rw-r--r--chromium/tools/android/forwarder2/daemon.cc288
-rw-r--r--chromium/tools/android/forwarder2/daemon.h75
-rw-r--r--chromium/tools/android/forwarder2/device_controller.cc154
-rw-r--r--chromium/tools/android/forwarder2/device_controller.h66
-rw-r--r--chromium/tools/android/forwarder2/device_forwarder_main.cc169
-rw-r--r--chromium/tools/android/forwarder2/device_listener.cc148
-rw-r--r--chromium/tools/android/forwarder2/device_listener.h114
-rw-r--r--chromium/tools/android/forwarder2/forwarder.cc171
-rw-r--r--chromium/tools/android/forwarder2/forwarder.gyp85
-rw-r--r--chromium/tools/android/forwarder2/forwarder.h19
-rw-r--r--chromium/tools/android/forwarder2/host_controller.cc186
-rw-r--r--chromium/tools/android/forwarder2/host_controller.h99
-rw-r--r--chromium/tools/android/forwarder2/host_forwarder_main.cc414
-rw-r--r--chromium/tools/android/forwarder2/pipe_notifier.cc43
-rw-r--r--chromium/tools/android/forwarder2/pipe_notifier.h35
-rw-r--r--chromium/tools/android/forwarder2/socket.cc422
-rw-r--r--chromium/tools/android/forwarder2/socket.h145
-rw-r--r--chromium/tools/android/md5sum/md5sum.cc93
-rw-r--r--chromium/tools/android/md5sum/md5sum.gyp77
-rw-r--r--chromium/tools/android/memdump/memdump.cc555
-rw-r--r--chromium/tools/android/memdump/memdump.gyp31
-rwxr-xr-xchromium/tools/android/memdump/memreport.py122
-rwxr-xr-xchromium/tools/android/memdump/memsymbols.py152
-rwxr-xr-xchromium/tools/android/remove_strings.py49
-rw-r--r--chromium/tools/bash-completion25
-rwxr-xr-xchromium/tools/bisect-builds.py718
-rwxr-xr-xchromium/tools/bisect-manual-test.py52
-rwxr-xr-xchromium/tools/bisect-perf-regression.py2456
-rw-r--r--chromium/tools/bisect_test.py53
-rw-r--r--chromium/tools/bisect_utils.py402
-rwxr-xr-xchromium/tools/checkbins/checkbins.py109
-rw-r--r--chromium/tools/checkdeps/DEPS3
-rw-r--r--chromium/tools/checkdeps/PRESUBMIT.py25
-rwxr-xr-xchromium/tools/checkdeps/checkdeps.py526
-rwxr-xr-xchromium/tools/checkdeps/checkdeps_test.py177
-rw-r--r--chromium/tools/checkdeps/cpp_checker.py113
-rw-r--r--chromium/tools/checkdeps/java_checker.py107
-rw-r--r--chromium/tools/checkdeps/results.py140
-rw-r--r--chromium/tools/checkdeps/rules.py151
-rw-r--r--chromium/tools/checkdeps/testdata/DEPS8
-rw-r--r--chromium/tools/checkdeps/testdata/allowed/DEPS12
-rw-r--r--chromium/tools/checkdeps/testdata/allowed/foo_unittest.cc5
-rw-r--r--chromium/tools/checkdeps/testdata/allowed/not_a_test.cc5
-rw-r--r--chromium/tools/checkdeps/testdata/allowed/test.h11
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/DEPS5
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/allowed/DEPS11
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/allowed/foo_unittest.cc5
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/allowed/not_a_test.cc5
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/allowed/test.h11
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/DEPS3
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/skipped/test.h5
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/test.h11
-rw-r--r--chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/test.h12
-rw-r--r--chromium/tools/checkdeps/testdata/disallowed/allowed/DEPS3
-rw-r--r--chromium/tools/checkdeps/testdata/disallowed/allowed/skipped/test.h5
-rw-r--r--chromium/tools/checkdeps/testdata/disallowed/allowed/test.h11
-rw-r--r--chromium/tools/checkdeps/testdata/disallowed/foo_unittest.cc10
-rw-r--r--chromium/tools/checkdeps/testdata/disallowed/test.h12
-rw-r--r--chromium/tools/checklicenses/OWNERS3
-rwxr-xr-xchromium/tools/checklicenses/checklicenses.py548
-rw-r--r--chromium/tools/checkperms/OWNERS1
-rw-r--r--chromium/tools/checkperms/PRESUBMIT.py27
-rwxr-xr-xchromium/tools/checkperms/checkperms.py508
-rw-r--r--chromium/tools/clang/OWNERS2
-rw-r--r--chromium/tools/clang/empty_string/EmptyStringConverter.cpp200
-rw-r--r--chromium/tools/clang/empty_string/Makefile23
-rw-r--r--chromium/tools/clang/plugins/ChromeClassTester.cpp303
-rw-r--r--chromium/tools/clang/plugins/ChromeClassTester.h88
-rw-r--r--chromium/tools/clang/plugins/FindBadConstructs.cpp668
-rw-r--r--chromium/tools/clang/plugins/Makefile19
-rw-r--r--chromium/tools/clang/plugins/OWNERS1
-rw-r--r--chromium/tools/clang/plugins/README.chromium4
-rw-r--r--chromium/tools/clang/rewrite_scoped_array/Makefile23
-rw-r--r--chromium/tools/clang/rewrite_scoped_array/RewriteScopedArray.cpp96
-rw-r--r--chromium/tools/clang/rewrite_scoped_ptr_ctor_null/Makefile23
-rw-r--r--chromium/tools/clang/rewrite_scoped_ptr_ctor_null/RewriteScopedPtrCtorNull.cpp198
-rwxr-xr-xchromium/tools/clang/scripts/package.sh98
-rwxr-xr-xchromium/tools/clang/scripts/plugin_flags.sh20
-rwxr-xr-xchromium/tools/clang/scripts/run_tool.py303
-rwxr-xr-xchromium/tools/clang/scripts/test_tool.py120
-rwxr-xr-xchromium/tools/clang/scripts/update.py34
-rwxr-xr-xchromium/tools/clang/scripts/update.sh350
-rwxr-xr-xchromium/tools/code_coverage/coverage.py359
-rwxr-xr-xchromium/tools/code_coverage/coverage_posix.py1266
-rwxr-xr-xchromium/tools/code_coverage/coverage_posix_unittest.py142
-rw-r--r--chromium/tools/code_coverage/croc.css102
-rwxr-xr-xchromium/tools/code_coverage/croc.py722
-rw-r--r--chromium/tools/code_coverage/croc_html.py451
-rw-r--r--chromium/tools/code_coverage/croc_scan.py164
-rwxr-xr-xchromium/tools/code_coverage/croc_scan_test.py187
-rwxr-xr-xchromium/tools/code_coverage/croc_test.py758
-rw-r--r--chromium/tools/code_coverage/example.croc197
-rwxr-xr-xchromium/tools/code_coverage/process_coverage.py413
-rw-r--r--chromium/tools/code_coverage/third_party/README.chromium11
-rw-r--r--chromium/tools/code_coverage/third_party/sorttable.js494
-rwxr-xr-xchromium/tools/compile_test/compile_test.py65
-rwxr-xr-xchromium/tools/coverity/coverity.py308
-rw-r--r--chromium/tools/crx_id/PRESUBMIT.py27
-rw-r--r--chromium/tools/crx_id/__init__.py8
-rwxr-xr-xchromium/tools/crx_id/crx_id.py151
-rwxr-xr-xchromium/tools/crx_id/crx_id_unittest.py85
-rw-r--r--chromium/tools/crx_id/jebgalgnebhfojomionfpkfelancnnkf.crxbin0 -> 1843 bytes
-rw-r--r--chromium/tools/cygprofile/cygprofile.cc401
-rw-r--r--chromium/tools/cygprofile/cygprofile.gyp19
-rwxr-xr-xchromium/tools/cygprofile/mergetraces.py186
-rwxr-xr-xchromium/tools/cygprofile/patch_orderfile.py117
-rwxr-xr-xchromium/tools/cygprofile/symbolize.py251
-rw-r--r--chromium/tools/deep_memory_profiler/OWNERS1
-rw-r--r--chromium/tools/deep_memory_profiler/PRESUBMIT.py45
-rw-r--r--chromium/tools/deep_memory_profiler/README.policy56
-rwxr-xr-xchromium/tools/deep_memory_profiler/dmprof12
-rw-r--r--chromium/tools/deep_memory_profiler/dmprof.py81
-rwxr-xr-xchromium/tools/deep_memory_profiler/download.sh7
-rwxr-xr-xchromium/tools/deep_memory_profiler/graph.py68
-rw-r--r--chromium/tools/deep_memory_profiler/lib/__init__.py3
-rw-r--r--chromium/tools/deep_memory_profiler/lib/bucket.py191
-rw-r--r--chromium/tools/deep_memory_profiler/lib/dump.py487
-rw-r--r--chromium/tools/deep_memory_profiler/lib/exceptions.py22
-rw-r--r--chromium/tools/deep_memory_profiler/lib/ordered_dict.py19
-rw-r--r--chromium/tools/deep_memory_profiler/lib/pageframe.py163
-rw-r--r--chromium/tools/deep_memory_profiler/lib/policy.py404
-rw-r--r--chromium/tools/deep_memory_profiler/lib/range_dict.py144
-rw-r--r--chromium/tools/deep_memory_profiler/lib/sorter.py470
-rw-r--r--chromium/tools/deep_memory_profiler/lib/subcommand.py160
-rw-r--r--chromium/tools/deep_memory_profiler/lib/symbol.py189
-rw-r--r--chromium/tools/deep_memory_profiler/policies.json34
-rw-r--r--chromium/tools/deep_memory_profiler/policy.android.browser.json301
-rw-r--r--chromium/tools/deep_memory_profiler/policy.android.renderer.json579
-rw-r--r--chromium/tools/deep_memory_profiler/policy.android.webview.json639
-rw-r--r--chromium/tools/deep_memory_profiler/policy.l0.json162
-rw-r--r--chromium/tools/deep_memory_profiler/policy.l1.json204
-rw-r--r--chromium/tools/deep_memory_profiler/policy.l2.json490
-rw-r--r--chromium/tools/deep_memory_profiler/policy.sourcefile.json186
-rw-r--r--chromium/tools/deep_memory_profiler/policy.t0.json205
-rw-r--r--chromium/tools/deep_memory_profiler/sorter.malloc-component.json261
-rw-r--r--chromium/tools/deep_memory_profiler/sorter.malloc-type.json38
-rw-r--r--chromium/tools/deep_memory_profiler/sorter.vm-map.json107
-rw-r--r--chromium/tools/deep_memory_profiler/sorter.vm-sharing.json25
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/__init__.py14
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/buckets.py35
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/cat.py179
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/expand.py104
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/map.py102
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/policies.py375
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/pprof.py161
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/stacktrace.py41
-rw-r--r--chromium/tools/deep_memory_profiler/subcommands/upload.py79
-rw-r--r--chromium/tools/deep_memory_profiler/templates.json12
-rw-r--r--chromium/tools/deep_memory_profiler/visualizer/main.css9
-rw-r--r--chromium/tools/deep_memory_profiler/visualizer/main.html17
-rw-r--r--chromium/tools/deep_memory_profiler/visualizer/main.js160
-rw-r--r--chromium/tools/deps2git/PRESUBMIT.py32
-rw-r--r--chromium/tools/deps2git/WATCHLISTS23
-rw-r--r--chromium/tools/deps2git/codereview.settings4
-rwxr-xr-xchromium/tools/deps2git/deps2git.py220
-rw-r--r--chromium/tools/deps2git/deps2submodules.py165
-rwxr-xr-xchromium/tools/deps2git/deps2submodules_unittest.py84
-rw-r--r--chromium/tools/deps2git/deps_utils.py135
-rw-r--r--chromium/tools/deps2git/git_tools.py183
-rwxr-xr-xchromium/tools/deps2git/svn_to_git_public.py172
-rwxr-xr-xchromium/tools/diagnose-me.py95
-rwxr-xr-xchromium/tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py266
-rw-r--r--chromium/tools/emacs/chrome-filetypes.el16
-rw-r--r--chromium/tools/emacs/flymake-chromium.el122
-rw-r--r--chromium/tools/emacs/trybot-linux.txt6
-rw-r--r--chromium/tools/emacs/trybot-mac.txt1985
-rw-r--r--chromium/tools/emacs/trybot-windows.txt72
-rw-r--r--chromium/tools/emacs/trybot.el176
-rwxr-xr-xchromium/tools/export_tarball/export_tarball.py172
-rwxr-xr-xchromium/tools/export_tarball/export_v8_tarball.py108
-rw-r--r--chromium/tools/find_depot_tools.py40
-rw-r--r--chromium/tools/find_runtime_symbols/OWNERS1
-rw-r--r--chromium/tools/find_runtime_symbols/PRESUBMIT.py45
-rw-r--r--chromium/tools/find_runtime_symbols/README24
-rwxr-xr-xchromium/tools/find_runtime_symbols/find_runtime_symbols.py207
-rwxr-xr-xchromium/tools/find_runtime_symbols/prepare_symbol_info.py226
-rw-r--r--chromium/tools/find_runtime_symbols/proc_maps.py125
-rwxr-xr-xchromium/tools/find_runtime_symbols/reduce_debugline.py68
-rw-r--r--chromium/tools/find_runtime_symbols/static_symbols.py277
-rwxr-xr-xchromium/tools/flakiness/find_flakiness.py179
-rw-r--r--chromium/tools/gdb/gdb_chrome.py296
-rwxr-xr-xchromium/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py529
-rwxr-xr-xchromium/tools/generate_library_loader/generate_library_loader.py256
-rwxr-xr-xchromium/tools/generate_shim_headers/generate_shim_headers.py107
-rwxr-xr-xchromium/tools/generate_stubs/generate_stubs.py1131
-rwxr-xr-xchromium/tools/generate_stubs/generate_stubs_unittest.py297
-rw-r--r--chromium/tools/git/README16
-rwxr-xr-xchromium/tools/git/for-all-touched-files.py114
-rwxr-xr-xchromium/tools/git/git-diff-ide.py93
-rwxr-xr-xchromium/tools/git/git-utils.sh17
-rwxr-xr-xchromium/tools/git/graph.sh42
-rwxr-xr-xchromium/tools/git/mass-rename.py50
-rwxr-xr-xchromium/tools/git/mass-rename.sh17
-rwxr-xr-xchromium/tools/git/mffr.py169
-rwxr-xr-xchromium/tools/git/move_source_file.bat6
-rwxr-xr-xchromium/tools/git/move_source_file.py191
-rwxr-xr-xchromium/tools/git/post-checkout22
-rwxr-xr-xchromium/tools/git/post-merge12
-rwxr-xr-xchromium/tools/git/update-copyrights.sh7
-rw-r--r--chromium/tools/gn/BUILD.gn174
-rw-r--r--chromium/tools/gn/OWNERS1
-rw-r--r--chromium/tools/gn/README.txt7
-rw-r--r--chromium/tools/gn/binary_target_generator.cc36
-rw-r--r--chromium/tools/gn/binary_target_generator.h32
-rw-r--r--chromium/tools/gn/build_settings.cc44
-rw-r--r--chromium/tools/gn/build_settings.h110
-rw-r--r--chromium/tools/gn/command_desc.cc344
-rw-r--r--chromium/tools/gn/command_gen.cc82
-rw-r--r--chromium/tools/gn/command_help.cc156
-rw-r--r--chromium/tools/gn/commands.cc97
-rw-r--r--chromium/tools/gn/commands.h67
-rw-r--r--chromium/tools/gn/config.cc80
-rw-r--r--chromium/tools/gn/config.h45
-rw-r--r--chromium/tools/gn/config_values.cc11
-rw-r--r--chromium/tools/gn/config_values.h51
-rw-r--r--chromium/tools/gn/config_values_extractors.cc35
-rw-r--r--chromium/tools/gn/config_values_extractors.h58
-rw-r--r--chromium/tools/gn/config_values_generator.cc73
-rw-r--r--chromium/tools/gn/config_values_generator.h43
-rw-r--r--chromium/tools/gn/copy_target_generator.cc47
-rw-r--r--chromium/tools/gn/copy_target_generator.h30
-rw-r--r--chromium/tools/gn/err.cc196
-rw-r--r--chromium/tools/gn/err.h85
-rw-r--r--chromium/tools/gn/escape.cc77
-rw-r--r--chromium/tools/gn/escape.h53
-rw-r--r--chromium/tools/gn/escape_unittest.cc4
-rw-r--r--chromium/tools/gn/file_template.cc125
-rw-r--r--chromium/tools/gn/file_template.h74
-rw-r--r--chromium/tools/gn/file_template_unittest.cc45
-rw-r--r--chromium/tools/gn/filesystem_utils.cc371
-rw-r--r--chromium/tools/gn/filesystem_utils.h115
-rw-r--r--chromium/tools/gn/filesystem_utils_unittest.cc146
-rw-r--r--chromium/tools/gn/function_define_rule.cc44
-rw-r--r--chromium/tools/gn/function_exec_script.cc355
-rw-r--r--chromium/tools/gn/function_process_file_template.cc72
-rw-r--r--chromium/tools/gn/function_read_file.cc72
-rw-r--r--chromium/tools/gn/function_set_default_toolchain.cc75
-rw-r--r--chromium/tools/gn/function_template.cc113
-rw-r--r--chromium/tools/gn/function_toolchain.cc143
-rw-r--r--chromium/tools/gn/function_write_file.cc89
-rw-r--r--chromium/tools/gn/functions.cc548
-rw-r--r--chromium/tools/gn/functions.h303
-rw-r--r--chromium/tools/gn/functions_target.cc277
-rw-r--r--chromium/tools/gn/generate_test_gn_data.cc129
-rw-r--r--chromium/tools/gn/gn.gyp191
-rw-r--r--chromium/tools/gn/gn_main.cc62
-rw-r--r--chromium/tools/gn/group_target_generator.cc21
-rw-r--r--chromium/tools/gn/group_target_generator.h28
-rw-r--r--chromium/tools/gn/import_manager.cc83
-rw-r--r--chromium/tools/gn/import_manager.h41
-rw-r--r--chromium/tools/gn/input_conversion.cc205
-rw-r--r--chromium/tools/gn/input_conversion.h28
-rw-r--r--chromium/tools/gn/input_conversion_unittest.cc81
-rw-r--r--chromium/tools/gn/input_file.cc31
-rw-r--r--chromium/tools/gn/input_file.h58
-rw-r--r--chromium/tools/gn/input_file_manager.cc252
-rw-r--r--chromium/tools/gn/input_file_manager.h124
-rw-r--r--chromium/tools/gn/item.cc31
-rw-r--r--chromium/tools/gn/item.h45
-rw-r--r--chromium/tools/gn/item_node.cc119
-rw-r--r--chromium/tools/gn/item_node.h159
-rw-r--r--chromium/tools/gn/item_tree.cc200
-rw-r--r--chromium/tools/gn/item_tree.h92
-rw-r--r--chromium/tools/gn/label.cc263
-rw-r--r--chromium/tools/gn/label.h116
-rw-r--r--chromium/tools/gn/label_unittest.cc88
-rw-r--r--chromium/tools/gn/location.h77
-rw-r--r--chromium/tools/gn/ninja_binary_target_writer.cc346
-rw-r--r--chromium/tools/gn/ninja_binary_target_writer.h39
-rw-r--r--chromium/tools/gn/ninja_build_writer.cc162
-rw-r--r--chromium/tools/gn/ninja_build_writer.h53
-rw-r--r--chromium/tools/gn/ninja_copy_target_writer.cc64
-rw-r--r--chromium/tools/gn/ninja_copy_target_writer.h23
-rw-r--r--chromium/tools/gn/ninja_group_target_writer.cc37
-rw-r--r--chromium/tools/gn/ninja_group_target_writer.h23
-rw-r--r--chromium/tools/gn/ninja_helper.cc177
-rw-r--r--chromium/tools/gn/ninja_helper.h71
-rw-r--r--chromium/tools/gn/ninja_helper_unittest.cc73
-rw-r--r--chromium/tools/gn/ninja_script_target_writer.cc207
-rw-r--r--chromium/tools/gn/ninja_script_target_writer.h49
-rw-r--r--chromium/tools/gn/ninja_target_writer.cc83
-rw-r--r--chromium/tools/gn/ninja_target_writer.h47
-rw-r--r--chromium/tools/gn/ninja_toolchain_writer.cc92
-rw-r--r--chromium/tools/gn/ninja_toolchain_writer.h46
-rw-r--r--chromium/tools/gn/ninja_writer.cc78
-rw-r--r--chromium/tools/gn/ninja_writer.h28
-rw-r--r--chromium/tools/gn/operators.cc573
-rw-r--r--chromium/tools/gn/operators.h35
-rw-r--r--chromium/tools/gn/output_file.h41
-rw-r--r--chromium/tools/gn/output_stream.h42
-rw-r--r--chromium/tools/gn/parse_tree.cc473
-rw-r--r--chromium/tools/gn/parse_tree.h366
-rw-r--r--chromium/tools/gn/parser.cc470
-rw-r--r--chromium/tools/gn/parser.h81
-rw-r--r--chromium/tools/gn/parser_unittest.cc329
-rw-r--r--chromium/tools/gn/path_output.cc116
-rw-r--r--chromium/tools/gn/path_output.h80
-rw-r--r--chromium/tools/gn/path_output_unittest.cc193
-rw-r--r--chromium/tools/gn/pattern.cc185
-rw-r--r--chromium/tools/gn/pattern.h86
-rw-r--r--chromium/tools/gn/pattern_unittest.cc61
-rw-r--r--chromium/tools/gn/scheduler.cc130
-rw-r--r--chromium/tools/gn/scheduler.h91
-rw-r--r--chromium/tools/gn/scope.cc372
-rw-r--r--chromium/tools/gn/scope.h260
-rw-r--r--chromium/tools/gn/scope_per_file_provider.cc151
-rw-r--r--chromium/tools/gn/scope_per_file_provider.h59
-rw-r--r--chromium/tools/gn/script_target_generator.cc82
-rw-r--r--chromium/tools/gn/script_target_generator.h32
-rw-r--r--chromium/tools/gn/script_values.cc11
-rw-r--r--chromium/tools/gn/script_values.h41
-rw-r--r--chromium/tools/gn/secondary/BUILD.gn10
-rw-r--r--chromium/tools/gn/secondary/base/BUILD.gn990
-rw-r--r--chromium/tools/gn/secondary/base/allocator/BUILD.gn10
-rw-r--r--chromium/tools/gn/secondary/base/third_party/dynamic_annotations/BUILD.gn11
-rw-r--r--chromium/tools/gn/secondary/base/third_party/nspr/BUILD.gn19
-rw-r--r--chromium/tools/gn/secondary/base/third_party/symbolize/BUILD.gn19
-rw-r--r--chromium/tools/gn/secondary/base/third_party/xdg_mime/BUILD.gn27
-rw-r--r--chromium/tools/gn/secondary/base/third_party/xdg_user_dirs/BUILD.gn10
-rw-r--r--chromium/tools/gn/secondary/build/config/BUILD.gn52
-rw-r--r--chromium/tools/gn/secondary/build/config/BUILDCONFIG.gn210
-rw-r--r--chromium/tools/gn/secondary/build/config/clang/BUILD.gn18
-rw-r--r--chromium/tools/gn/secondary/build/config/compiler/BUILD.gn338
-rw-r--r--chromium/tools/gn/secondary/build/config/linux/BUILD.gn14
-rw-r--r--chromium/tools/gn/secondary/build/config/linux/system/BUILD.gn31
-rw-r--r--chromium/tools/gn/secondary/build/config/linux/system/pkg-config.py8
-rw-r--r--chromium/tools/gn/secondary/build/config/linux/toolchain/BUILD.gn47
-rw-r--r--chromium/tools/gn/secondary/build/config/mac/BUILD.gn76
-rw-r--r--chromium/tools/gn/secondary/build/config/win/BUILD.gn184
-rw-r--r--chromium/tools/gn/secondary/build/config/win/get_msvc_config.py77
-rw-r--r--chromium/tools/gn/secondary/build/config/win/get_msvc_config_real.py575
-rw-r--r--chromium/tools/gn/secondary/ipc/BUILD.gn168
-rw-r--r--chromium/tools/gn/secondary/testing/BUILD.gn44
-rw-r--r--chromium/tools/gn/secondary/third_party/icu/BUILD.gn5
-rw-r--r--chromium/tools/gn/secondary/third_party/libevent/BUILD.gn42
-rw-r--r--chromium/tools/gn/secondary/third_party/mach_override/BUILD.gn10
-rw-r--r--chromium/tools/gn/secondary/third_party/modp_b64/BUILD.gn11
-rw-r--r--chromium/tools/gn/settings.cc50
-rw-r--r--chromium/tools/gn/settings.h121
-rw-r--r--chromium/tools/gn/setup.cc232
-rw-r--r--chromium/tools/gn/setup.h71
-rw-r--r--chromium/tools/gn/source_dir.cc98
-rw-r--r--chromium/tools/gn/source_dir.h104
-rw-r--r--chromium/tools/gn/source_dir_unittest.cc45
-rw-r--r--chromium/tools/gn/source_file.cc67
-rw-r--r--chromium/tools/gn/source_file.h97
-rw-r--r--chromium/tools/gn/standard_out.cc84
-rw-r--r--chromium/tools/gn/standard_out.h22
-rw-r--r--chromium/tools/gn/string_utils.cc168
-rw-r--r--chromium/tools/gn/string_utils.h51
-rw-r--r--chromium/tools/gn/string_utils_unittest.cc71
-rw-r--r--chromium/tools/gn/target.cc92
-rw-r--r--chromium/tools/gn/target.h140
-rw-r--r--chromium/tools/gn/target_generator.cc229
-rw-r--r--chromium/tools/gn/target_generator.h82
-rw-r--r--chromium/tools/gn/target_generator_unittest.cc8
-rw-r--r--chromium/tools/gn/target_manager.cc130
-rw-r--r--chromium/tools/gn/target_manager.h69
-rw-r--r--chromium/tools/gn/target_manager_unittest.cc95
-rw-r--r--chromium/tools/gn/token.cc60
-rw-r--r--chromium/tools/gn/token.h52
-rw-r--r--chromium/tools/gn/tokenizer.cc309
-rw-r--r--chromium/tools/gn/tokenizer.h86
-rw-r--r--chromium/tools/gn/tokenizer_unittest.cc162
-rw-r--r--chromium/tools/gn/toolchain.cc82
-rw-r--r--chromium/tools/gn/toolchain.h96
-rw-r--r--chromium/tools/gn/toolchain_manager.cc497
-rw-r--r--chromium/tools/gn/toolchain_manager.h168
-rw-r--r--chromium/tools/gn/value.cc126
-rw-r--r--chromium/tools/gn/value.h91
-rw-r--r--chromium/tools/gn/value_extractors.cc102
-rw-r--r--chromium/tools/gn/value_extractors.h57
-rw-r--r--chromium/tools/gn/variables.cc364
-rw-r--r--chromium/tools/gn/variables.h126
-rw-r--r--chromium/tools/grit/LICENSE25
-rw-r--r--chromium/tools/grit/PRESUBMIT.py22
-rw-r--r--chromium/tools/grit/README2
-rw-r--r--chromium/tools/grit/codereview.settings6
-rwxr-xr-xchromium/tools/grit/grit.py16
-rw-r--r--chromium/tools/grit/grit/__init__.py10
-rw-r--r--chromium/tools/grit/grit/clique.py483
-rw-r--r--chromium/tools/grit/grit/clique_unittest.py261
-rw-r--r--chromium/tools/grit/grit/constants.py18
-rw-r--r--chromium/tools/grit/grit/exception.py138
-rw-r--r--chromium/tools/grit/grit/extern/BogoFP.py22
-rw-r--r--chromium/tools/grit/grit/extern/FP.py71
-rw-r--r--chromium/tools/grit/grit/extern/__init__.py0
-rw-r--r--chromium/tools/grit/grit/extern/tclib.py503
-rw-r--r--chromium/tools/grit/grit/format/__init__.py10
-rw-r--r--chromium/tools/grit/grit/format/android_xml.py158
-rw-r--r--chromium/tools/grit/grit/format/android_xml_unittest.py111
-rw-r--r--chromium/tools/grit/grit/format/c_format.py86
-rw-r--r--chromium/tools/grit/grit/format/c_format_unittest.py78
-rw-r--r--chromium/tools/grit/grit/format/chrome_messages_json.py38
-rw-r--r--chromium/tools/grit/grit/format/chrome_messages_json_unittest.py116
-rwxr-xr-xchromium/tools/grit/grit/format/data_pack.py171
-rw-r--r--chromium/tools/grit/grit/format/data_pack_unittest.py37
-rwxr-xr-xchromium/tools/grit/grit/format/html_inline.py421
-rwxr-xr-xchromium/tools/grit/grit/format/html_inline_unittest.py328
-rw-r--r--chromium/tools/grit/grit/format/js_map_format.py44
-rw-r--r--chromium/tools/grit/grit/format/js_map_format_unittest.py92
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/PRESUBMIT.py28
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/__init__.py10
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/policy_template_generator.py177
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py372
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/template_formatter.py73
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writer_configuration.py57
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/__init__.py10
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/adm_writer.py252
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py844
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/adml_writer.py180
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py329
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/admx_writer.py372
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py411
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/doc_writer.py654
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py556
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/json_writer.py95
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py340
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/mock_writer.py30
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/plist_helper.py15
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py73
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py279
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/plist_writer.py128
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py409
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/reg_writer.py105
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py318
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/template_writer.py287
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py84
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py83
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py87
-rw-r--r--chromium/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py40
-rw-r--r--chromium/tools/grit/grit/format/rc.py473
-rw-r--r--chromium/tools/grit/grit/format/rc_header.py198
-rw-r--r--chromium/tools/grit/grit/format/rc_header_unittest.py159
-rw-r--r--chromium/tools/grit/grit/format/rc_unittest.py409
-rwxr-xr-xchromium/tools/grit/grit/format/repack.py27
-rw-r--r--chromium/tools/grit/grit/format/resource_map.py126
-rw-r--r--chromium/tools/grit/grit/format/resource_map_unittest.py99
-rw-r--r--chromium/tools/grit/grit/gather/__init__.py9
-rw-r--r--chromium/tools/grit/grit/gather/admin_template.py61
-rw-r--r--chromium/tools/grit/grit/gather/admin_template_unittest.py117
-rw-r--r--chromium/tools/grit/grit/gather/chrome_html.py331
-rw-r--r--chromium/tools/grit/grit/gather/chrome_html_unittest.py408
-rw-r--r--chromium/tools/grit/grit/gather/chrome_scaled_image.py140
-rw-r--r--chromium/tools/grit/grit/gather/chrome_scaled_image_unittest.py174
-rw-r--r--chromium/tools/grit/grit/gather/igoogle_strings.py123
-rw-r--r--chromium/tools/grit/grit/gather/igoogle_strings_unittest.py29
-rw-r--r--chromium/tools/grit/grit/gather/interface.py171
-rw-r--r--chromium/tools/grit/grit/gather/json_loader.py26
-rw-r--r--chromium/tools/grit/grit/gather/muppet_strings.py133
-rw-r--r--chromium/tools/grit/grit/gather/muppet_strings_unittest.py67
-rw-r--r--chromium/tools/grit/grit/gather/policy_json.py251
-rw-r--r--chromium/tools/grit/grit/gather/policy_json_unittest.py190
-rw-r--r--chromium/tools/grit/grit/gather/rc.py343
-rw-r--r--chromium/tools/grit/grit/gather/rc_unittest.py370
-rw-r--r--chromium/tools/grit/grit/gather/regexp.py85
-rw-r--r--chromium/tools/grit/grit/gather/skeleton_gatherer.py147
-rw-r--r--chromium/tools/grit/grit/gather/tr_html.py745
-rw-r--r--chromium/tools/grit/grit/gather/tr_html_unittest.py522
-rw-r--r--chromium/tools/grit/grit/gather/txt.py37
-rw-r--r--chromium/tools/grit/grit/gather/txt_unittest.py34
-rw-r--r--chromium/tools/grit/grit/grd_reader.py217
-rw-r--r--chromium/tools/grit/grit/grd_reader_unittest.py290
-rw-r--r--chromium/tools/grit/grit/grit-todo.xml62
-rw-r--r--chromium/tools/grit/grit/grit_runner.py272
-rw-r--r--chromium/tools/grit/grit/grit_runner_unittest.py40
-rw-r--r--chromium/tools/grit/grit/lazy_re.py45
-rw-r--r--chromium/tools/grit/grit/lazy_re_unittest.py38
-rw-r--r--chromium/tools/grit/grit/node/__init__.py9
-rw-r--r--chromium/tools/grit/grit/node/base.py567
-rw-r--r--chromium/tools/grit/grit/node/base_unittest.py197
-rw-r--r--chromium/tools/grit/grit/node/custom/__init__.py9
-rw-r--r--chromium/tools/grit/grit/node/custom/filename.py28
-rw-r--r--chromium/tools/grit/grit/node/custom/filename_unittest.py34
-rw-r--r--chromium/tools/grit/grit/node/empty.py64
-rw-r--r--chromium/tools/grit/grit/node/include.py138
-rw-r--r--chromium/tools/grit/grit/node/include_unittest.py74
-rw-r--r--chromium/tools/grit/grit/node/io.py112
-rw-r--r--chromium/tools/grit/grit/node/io_unittest.py151
-rw-r--r--chromium/tools/grit/grit/node/mapping.py61
-rw-r--r--chromium/tools/grit/grit/node/message.py294
-rw-r--r--chromium/tools/grit/grit/node/message_unittest.py90
-rwxr-xr-xchromium/tools/grit/grit/node/misc.py523
-rw-r--r--chromium/tools/grit/grit/node/misc_unittest.py419
-rw-r--r--chromium/tools/grit/grit/node/structure.py358
-rw-r--r--chromium/tools/grit/grit/node/structure_unittest.py69
-rw-r--r--chromium/tools/grit/grit/node/variant.py42
-rw-r--r--chromium/tools/grit/grit/pseudo.py128
-rw-r--r--chromium/tools/grit/grit/pseudo_rtl.py103
-rw-r--r--chromium/tools/grit/grit/pseudo_unittest.py53
-rwxr-xr-xchromium/tools/grit/grit/scons.py255
-rw-r--r--chromium/tools/grit/grit/shortcuts.py93
-rw-r--r--chromium/tools/grit/grit/shortcuts_unittests.py80
-rw-r--r--chromium/tools/grit/grit/tclib.py235
-rw-r--r--chromium/tools/grit/grit/tclib_unittest.py179
-rw-r--r--chromium/tools/grit/grit/test_suite_all.py150
-rw-r--r--chromium/tools/grit/grit/testdata/GoogleDesktop.adm945
-rw-r--r--chromium/tools/grit/grit/testdata/README.txt87
-rw-r--r--chromium/tools/grit/grit/testdata/about.html45
-rw-r--r--chromium/tools/grit/grit/testdata/android.xml24
-rw-r--r--chromium/tools/grit/grit/testdata/bad_browser.html16
-rw-r--r--chromium/tools/grit/grit/testdata/browser.html42
-rw-r--r--chromium/tools/grit/grit/testdata/buildinfo.grd46
-rw-r--r--chromium/tools/grit/grit/testdata/cache_prefix.html24
-rw-r--r--chromium/tools/grit/grit/testdata/cache_prefix_file.html25
-rw-r--r--chromium/tools/grit/grit/testdata/chat_result.html24
-rw-r--r--chromium/tools/grit/grit/testdata/chrome/app/generated_resources.grd199
-rw-r--r--chromium/tools/grit/grit/testdata/chrome_html.html6
-rw-r--r--chromium/tools/grit/grit/testdata/del_footer.html8
-rw-r--r--chromium/tools/grit/grit/testdata/del_header.html60
-rw-r--r--chromium/tools/grit/grit/testdata/deleted.html21
-rw-r--r--chromium/tools/grit/grit/testdata/details.html10
-rw-r--r--chromium/tools/grit/grit/testdata/duplicate-name-input.xml26
-rw-r--r--chromium/tools/grit/grit/testdata/email_result.html34
-rw-r--r--chromium/tools/grit/grit/testdata/email_thread.html10
-rw-r--r--chromium/tools/grit/grit/testdata/error.html8
-rw-r--r--chromium/tools/grit/grit/testdata/explicit_web.html11
-rw-r--r--chromium/tools/grit/grit/testdata/footer.html14
-rw-r--r--chromium/tools/grit/grit/testdata/generated_resources_fr.xtb3090
-rw-r--r--chromium/tools/grit/grit/testdata/header.html39
-rw-r--r--chromium/tools/grit/grit/testdata/homepage.html37
-rw-r--r--chromium/tools/grit/grit/testdata/hover.html177
-rw-r--r--chromium/tools/grit/grit/testdata/include_test.html31
-rw-r--r--chromium/tools/grit/grit/testdata/included_sample.html1
-rw-r--r--chromium/tools/grit/grit/testdata/indexing_speed.html58
-rw-r--r--chromium/tools/grit/grit/testdata/install_prefs.html92
-rw-r--r--chromium/tools/grit/grit/testdata/install_prefs2.html52
-rw-r--r--chromium/tools/grit/grit/testdata/klonk-alternate-skeleton.rcbin0 -> 1088 bytes
-rw-r--r--chromium/tools/grit/grit/testdata/klonk.icobin0 -> 766 bytes
-rw-r--r--chromium/tools/grit/grit/testdata/klonk.rcbin0 -> 9824 bytes
-rw-r--r--chromium/tools/grit/grit/testdata/ko_oem_enable_bug.html1
-rw-r--r--chromium/tools/grit/grit/testdata/ko_oem_non_admin_bug.html1
-rw-r--r--chromium/tools/grit/grit/testdata/mini.html36
-rw-r--r--chromium/tools/grit/grit/testdata/oem_enable.html106
-rw-r--r--chromium/tools/grit/grit/testdata/oem_non_admin.html39
-rw-r--r--chromium/tools/grit/grit/testdata/onebox.html21
-rw-r--r--chromium/tools/grit/grit/testdata/oneclick.html34
-rw-r--r--chromium/tools/grit/grit/testdata/password.html37
-rw-r--r--chromium/tools/grit/grit/testdata/preferences.html234
-rw-r--r--chromium/tools/grit/grit/testdata/privacy.html35
-rw-r--r--chromium/tools/grit/grit/testdata/quit_apps.html49
-rw-r--r--chromium/tools/grit/grit/testdata/recrawl.html30
-rw-r--r--chromium/tools/grit/grit/testdata/resource_ids10
-rw-r--r--chromium/tools/grit/grit/testdata/script.html38
-rw-r--r--chromium/tools/grit/grit/testdata/searchbox.html22
-rw-r--r--chromium/tools/grit/grit/testdata/sidebar_h.html82
-rw-r--r--chromium/tools/grit/grit/testdata/sidebar_v.html267
-rw-r--r--chromium/tools/grit/grit/testdata/simple-input.xml52
-rw-r--r--chromium/tools/grit/grit/testdata/simple.html3
-rw-r--r--chromium/tools/grit/grit/testdata/source.rc57
-rw-r--r--chromium/tools/grit/grit/testdata/status.html44
-rw-r--r--chromium/tools/grit/grit/testdata/structure_variables.html4
-rw-r--r--chromium/tools/grit/grit/testdata/substitute.grd31
-rw-r--r--chromium/tools/grit/grit/testdata/substitute.xmb10
-rw-r--r--chromium/tools/grit/grit/testdata/time_related.html11
-rw-r--r--chromium/tools/grit/grit/testdata/toolbar_about.html138
-rw-r--r--chromium/tools/grit/grit/testdata/tools/grit/resource_ids175
-rw-r--r--chromium/tools/grit/grit/testdata/transl.rc56
-rw-r--r--chromium/tools/grit/grit/testdata/versions.html7
-rw-r--r--chromium/tools/grit/grit/tool/__init__.py10
-rw-r--r--chromium/tools/grit/grit/tool/android2grd.py499
-rw-r--r--chromium/tools/grit/grit/tool/android2grd_unittest.py188
-rw-r--r--chromium/tools/grit/grit/tool/build.py306
-rw-r--r--chromium/tools/grit/grit/tool/build_unittest.py38
-rw-r--r--chromium/tools/grit/grit/tool/buildinfo.py68
-rw-r--r--chromium/tools/grit/grit/tool/buildinfo_unittest.py87
-rw-r--r--chromium/tools/grit/grit/tool/count.py35
-rw-r--r--chromium/tools/grit/grit/tool/diff_structures.py114
-rw-r--r--chromium/tools/grit/grit/tool/interface.py58
-rw-r--r--chromium/tools/grit/grit/tool/menu_from_parts.py79
-rw-r--r--chromium/tools/grit/grit/tool/newgrd.py70
-rw-r--r--chromium/tools/grit/grit/tool/postprocess_interface.py32
-rw-r--r--chromium/tools/grit/grit/tool/postprocess_unittest.py63
-rw-r--r--chromium/tools/grit/grit/tool/preprocess_interface.py28
-rw-r--r--chromium/tools/grit/grit/tool/preprocess_unittest.py49
-rw-r--r--chromium/tools/grit/grit/tool/rc2grd.py409
-rw-r--r--chromium/tools/grit/grit/tool/rc2grd_unittest.py137
-rw-r--r--chromium/tools/grit/grit/tool/resize.py289
-rw-r--r--chromium/tools/grit/grit/tool/test.py24
-rw-r--r--chromium/tools/grit/grit/tool/toolbar_postprocess.py126
-rw-r--r--chromium/tools/grit/grit/tool/toolbar_preprocess.py61
-rw-r--r--chromium/tools/grit/grit/tool/transl2tc.py252
-rw-r--r--chromium/tools/grit/grit/tool/transl2tc_unittest.py131
-rw-r--r--chromium/tools/grit/grit/tool/unit.py26
-rw-r--r--chromium/tools/grit/grit/tool/xmb.py291
-rw-r--r--chromium/tools/grit/grit/tool/xmb_unittest.py103
-rw-r--r--chromium/tools/grit/grit/util.py661
-rw-r--r--chromium/tools/grit/grit/util_unittest.py119
-rw-r--r--chromium/tools/grit/grit/xtb_reader.py141
-rw-r--r--chromium/tools/grit/grit/xtb_reader_unittest.py106
-rwxr-xr-xchromium/tools/grit/grit_info.py180
-rw-r--r--chromium/tools/gritsettings/resource_ids221
-rw-r--r--chromium/tools/gtk_clipboard_dump/gtk_clipboard_dump.cc85
-rw-r--r--chromium/tools/gtk_clipboard_dump/gtk_clipboard_dump.gyp14
-rwxr-xr-xchromium/tools/gyp-explain.py119
-rw-r--r--chromium/tools/gyp/AUTHORS9
-rw-r--r--chromium/tools/gyp/DEPS24
-rw-r--r--chromium/tools/gyp/LICENSE27
-rw-r--r--chromium/tools/gyp/MANIFEST19
-rw-r--r--chromium/tools/gyp/OWNERS1
-rw-r--r--chromium/tools/gyp/PRESUBMIT.py115
-rwxr-xr-xchromium/tools/gyp/buildbot/buildbot_run.py148
-rw-r--r--chromium/tools/gyp/codereview.settings10
-rw-r--r--chromium/tools/gyp/data/win/large-pdb-shim.cc12
-rwxr-xr-xchromium/tools/gyp/gyp7
-rwxr-xr-xchromium/tools/gyp/gyp.bat5
-rw-r--r--chromium/tools/gyp/gyp_dummy.c7
-rwxr-xr-xchromium/tools/gyp/gyp_main.py18
-rwxr-xr-xchromium/tools/gyp/gyptest.py267
-rw-r--r--chromium/tools/gyp/pylib/gyp/MSVSNew.py339
-rw-r--r--chromium/tools/gyp/pylib/gyp/MSVSProject.py208
-rw-r--r--chromium/tools/gyp/pylib/gyp/MSVSSettings.py1051
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/MSVSSettings_test.py1482
-rw-r--r--chromium/tools/gyp/pylib/gyp/MSVSToolFile.py58
-rw-r--r--chromium/tools/gyp/pylib/gyp/MSVSUserFile.py147
-rw-r--r--chromium/tools/gyp/pylib/gyp/MSVSUtil.py267
-rw-r--r--chromium/tools/gyp/pylib/gyp/MSVSVersion.py399
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/__init__.py546
-rw-r--r--chromium/tools/gyp/pylib/gyp/common.py498
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/common_test.py72
-rw-r--r--chromium/tools/gyp/pylib/gyp/easy_xml.py157
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/easy_xml_test.py103
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/__init__.py0
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/android.py1069
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/dump_dependency_json.py93
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/eclipse.py277
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/gypd.py87
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/gypsh.py56
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/make.py2159
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/msvs.py3236
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/generator/msvs_test.py37
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/ninja.py2055
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/ninja_test.py44
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/xcode.py1245
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/xcode_test.py23
-rw-r--r--chromium/tools/gyp/pylib/gyp/input.py2683
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/mac_tool.py231
-rw-r--r--chromium/tools/gyp/pylib/gyp/msvs_emulation.py846
-rw-r--r--chromium/tools/gyp/pylib/gyp/ninja_syntax.py160
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/sun_tool.py51
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/win_tool.py176
-rw-r--r--chromium/tools/gyp/pylib/gyp/xcode_emulation.py1136
-rw-r--r--chromium/tools/gyp/pylib/gyp/xcodeproj_file.py2870
-rw-r--r--chromium/tools/gyp/pylib/gyp/xml_fix.py69
-rw-r--r--chromium/tools/gyp/pylintrc307
-rwxr-xr-xchromium/tools/gyp/samples/samples81
-rw-r--r--chromium/tools/gyp/samples/samples.bat5
-rwxr-xr-xchromium/tools/gyp/setup.py26
-rw-r--r--chromium/tools/gyp/test/actions-bare/src/bare.gyp25
-rw-r--r--chromium/tools/gyp/test/actions-multiple/src/actions.gyp226
-rw-r--r--chromium/tools/gyp/test/actions-none/src/none_with_source_files.gyp35
-rw-r--r--chromium/tools/gyp/test/actions-subdir/src/none.gyp31
-rw-r--r--chromium/tools/gyp/test/actions-subdir/src/subdir/subdir.gyp28
-rw-r--r--chromium/tools/gyp/test/actions/generated-header/test.gyp34
-rw-r--r--chromium/tools/gyp/test/actions/src/action_missing_name.gyp24
-rw-r--r--chromium/tools/gyp/test/actions/src/actions.gyp114
-rw-r--r--chromium/tools/gyp/test/actions/src/subdir1/executable.gyp74
-rw-r--r--chromium/tools/gyp/test/actions/src/subdir2/none.gyp33
-rw-r--r--chromium/tools/gyp/test/actions/src/subdir3/null_input.gyp29
-rw-r--r--chromium/tools/gyp/test/additional-targets/src/all.gyp13
-rw-r--r--chromium/tools/gyp/test/additional-targets/src/dir1/actions.gyp56
-rw-r--r--chromium/tools/gyp/test/assembly/src/assembly.gyp62
-rw-r--r--chromium/tools/gyp/test/assembly/src/override.gyp34
-rw-r--r--chromium/tools/gyp/test/build-option/hello.gyp15
-rw-r--r--chromium/tools/gyp/test/builddir/src/builddir.gypi18
-rw-r--r--chromium/tools/gyp/test/builddir/src/prog1.gyp30
-rw-r--r--chromium/tools/gyp/test/builddir/src/subdir2/prog2.gyp19
-rw-r--r--chromium/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp19
-rw-r--r--chromium/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp19
-rw-r--r--chromium/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp19
-rw-r--r--chromium/tools/gyp/test/cflags/cflags.gyp16
-rw-r--r--chromium/tools/gyp/test/compilable/src/headers.gyp26
-rw-r--r--chromium/tools/gyp/test/compiler-override/compiler-host.gyp17
-rw-r--r--chromium/tools/gyp/test/compiler-override/compiler.gyp16
-rw-r--r--chromium/tools/gyp/test/configurations/basics/configurations.gyp32
-rw-r--r--chromium/tools/gyp/test/configurations/inheritance/configurations.gyp40
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/actions.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/configurations.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/dependencies.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/libraries.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/link_settings.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/sources.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/standalone_static_library.gyp17
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/target_name.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/invalid/type.gyp18
-rw-r--r--chromium/tools/gyp/test/configurations/target_platform/configurations.gyp58
-rw-r--r--chromium/tools/gyp/test/configurations/x64/configurations.gyp38
-rw-r--r--chromium/tools/gyp/test/copies/src/copies-samedir.gyp37
-rw-r--r--chromium/tools/gyp/test/copies/src/copies-slash.gyp36
-rw-r--r--chromium/tools/gyp/test/copies/src/copies-updir.gyp21
-rw-r--r--chromium/tools/gyp/test/copies/src/copies.gyp70
-rw-r--r--chromium/tools/gyp/test/custom-generator/test.gyp15
-rw-r--r--chromium/tools/gyp/test/cxxflags/cxxflags.gyp16
-rw-r--r--chromium/tools/gyp/test/defines-escaping/defines-escaping.gyp19
-rw-r--r--chromium/tools/gyp/test/defines/defines-env.gyp22
-rw-r--r--chromium/tools/gyp/test/defines/defines.gyp38
-rwxr-xr-xchromium/tools/gyp/test/dependencies/b/b.gyp22
-rw-r--r--chromium/tools/gyp/test/dependencies/c/c.gyp22
-rw-r--r--chromium/tools/gyp/test/dependencies/double_dependency.gyp23
-rw-r--r--chromium/tools/gyp/test/dependencies/double_dependent.gyp12
-rw-r--r--chromium/tools/gyp/test/dependencies/extra_targets.gyp18
-rwxr-xr-xchromium/tools/gyp/test/dependencies/lib_only.gyp16
-rwxr-xr-xchromium/tools/gyp/test/dependencies/none_traversal.gyp46
-rw-r--r--chromium/tools/gyp/test/dependency-copy/src/copies.gyp25
-rw-r--r--chromium/tools/gyp/test/errors/duplicate_basenames.gyp13
-rw-r--r--chromium/tools/gyp/test/errors/duplicate_node.gyp12
-rw-r--r--chromium/tools/gyp/test/errors/duplicate_rule.gyp22
-rw-r--r--chromium/tools/gyp/test/errors/duplicate_targets.gyp14
-rw-r--r--chromium/tools/gyp/test/errors/missing_dep.gyp15
-rw-r--r--chromium/tools/gyp/test/errors/missing_targets.gyp8
-rw-r--r--chromium/tools/gyp/test/escaping/colon/test.gyp21
-rw-r--r--chromium/tools/gyp/test/exclusion/exclusion.gyp23
-rw-r--r--chromium/tools/gyp/test/external-cross-compile/src/cross.gyp83
-rw-r--r--chromium/tools/gyp/test/external-cross-compile/src/cross_compile.gypi23
-rw-r--r--chromium/tools/gyp/test/generator-output/actions/actions.gyp16
-rw-r--r--chromium/tools/gyp/test/generator-output/actions/subdir1/executable.gyp44
-rw-r--r--chromium/tools/gyp/test/generator-output/actions/subdir2/none.gyp31
-rw-r--r--chromium/tools/gyp/test/generator-output/copies/copies.gyp50
-rw-r--r--chromium/tools/gyp/test/generator-output/copies/subdir/subdir.gyp32
-rw-r--r--chromium/tools/gyp/test/generator-output/mac-bundle/test.gyp25
-rw-r--r--chromium/tools/gyp/test/generator-output/rules/rules.gyp16
-rw-r--r--chromium/tools/gyp/test/generator-output/rules/subdir1/executable.gyp59
-rw-r--r--chromium/tools/gyp/test/generator-output/rules/subdir2/none.gyp49
-rw-r--r--chromium/tools/gyp/test/generator-output/src/prog1.gyp28
-rw-r--r--chromium/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp18
-rw-r--r--chromium/tools/gyp/test/generator-output/src/subdir2/prog2.gyp28
-rw-r--r--chromium/tools/gyp/test/generator-output/src/subdir3/prog3.gyp25
-rw-r--r--chromium/tools/gyp/test/generator-output/src/symroot.gypi16
-rw-r--r--chromium/tools/gyp/test/gyp-defines/defines.gyp26
-rw-r--r--chromium/tools/gyp/test/hard_dependency/src/hard_dependency.gyp78
-rw-r--r--chromium/tools/gyp/test/hello/hello.gyp15
-rw-r--r--chromium/tools/gyp/test/hello/hello2.gyp15
-rw-r--r--chromium/tools/gyp/test/home_dot_gyp/home/.gyp/include.gypi5
-rw-r--r--chromium/tools/gyp/test/home_dot_gyp/home2/.gyp/include.gypi5
-rw-r--r--chromium/tools/gyp/test/home_dot_gyp/home2/.gyp_new/include.gypi5
-rw-r--r--chromium/tools/gyp/test/home_dot_gyp/src/all.gyp22
-rw-r--r--chromium/tools/gyp/test/include_dirs/src/includes.gyp27
-rw-r--r--chromium/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp20
-rw-r--r--chromium/tools/gyp/test/intermediate_dir/src/test.gyp42
-rw-r--r--chromium/tools/gyp/test/intermediate_dir/src/test2.gyp42
-rw-r--r--chromium/tools/gyp/test/ios/app-bundle/test.gyp44
-rw-r--r--chromium/tools/gyp/test/ios/deployment-target/deployment-target.gyp58
-rw-r--r--chromium/tools/gyp/test/library/src/library.gyp58
-rw-r--r--chromium/tools/gyp/test/library/src/shared_dependency.gyp33
-rw-r--r--chromium/tools/gyp/test/library_dirs/subdir/test.gyp68
-rw-r--r--chromium/tools/gyp/test/link-objects/link-objects.gyp24
-rw-r--r--chromium/tools/gyp/test/linux/implicit-rpath/test.gyp47
-rw-r--r--chromium/tools/gyp/test/mac/action-envvars/action/action.gyp34
-rw-r--r--chromium/tools/gyp/test/mac/app-bundle/test-error.gyp31
-rw-r--r--chromium/tools/gyp/test/mac/app-bundle/test.gyp39
-rw-r--r--chromium/tools/gyp/test/mac/archs/test-archs-multiarch.gyp60
-rw-r--r--chromium/tools/gyp/test/mac/archs/test-archs-x86_64.gyp27
-rw-r--r--chromium/tools/gyp/test/mac/archs/test-no-archs.gyp21
-rw-r--r--chromium/tools/gyp/test/mac/cflags/test.gyp132
-rw-r--r--chromium/tools/gyp/test/mac/clang-cxx-language-standard/clang-cxx-language-standard.gyp30
-rw-r--r--chromium/tools/gyp/test/mac/clang-cxx-library/clang-cxx-library.gyp32
-rw-r--r--chromium/tools/gyp/test/mac/copy-dylib/test.gyp31
-rw-r--r--chromium/tools/gyp/test/mac/debuginfo/test.gyp82
-rw-r--r--chromium/tools/gyp/test/mac/depend-on-bundle/test.gyp28
-rw-r--r--chromium/tools/gyp/test/mac/deployment-target/deployment-target.gyp28
-rw-r--r--chromium/tools/gyp/test/mac/framework-dirs/framework-dirs.gyp21
-rw-r--r--chromium/tools/gyp/test/mac/framework-headers/test.gyp44
-rw-r--r--chromium/tools/gyp/test/mac/framework/framework.gyp74
-rw-r--r--chromium/tools/gyp/test/mac/global-settings/src/dir1/dir1.gyp11
-rw-r--r--chromium/tools/gyp/test/mac/global-settings/src/dir2/dir2.gyp22
-rw-r--r--chromium/tools/gyp/test/mac/gyptest-postbuild-static-library.gyp28
-rw-r--r--chromium/tools/gyp/test/mac/gyptest-sourceless-module.gyp46
-rw-r--r--chromium/tools/gyp/test/mac/infoplist-process/test1.gyp25
-rw-r--r--chromium/tools/gyp/test/mac/infoplist-process/test2.gyp25
-rw-r--r--chromium/tools/gyp/test/mac/infoplist-process/test3.gyp25
-rw-r--r--chromium/tools/gyp/test/mac/installname/test.gyp93
-rw-r--r--chromium/tools/gyp/test/mac/ldflags-libtool/test.gyp17
-rw-r--r--chromium/tools/gyp/test/mac/ldflags/subdirectory/test.gyp66
-rw-r--r--chromium/tools/gyp/test/mac/libraries/subdir/test.gyp65
-rw-r--r--chromium/tools/gyp/test/mac/loadable-module/test.gyp18
-rw-r--r--chromium/tools/gyp/test/mac/missing-cfbundlesignature/test.gyp34
-rw-r--r--chromium/tools/gyp/test/mac/non-strs-flattened-to-env/test.gyp27
-rw-r--r--chromium/tools/gyp/test/mac/objc-arc/test.gyp45
-rw-r--r--chromium/tools/gyp/test/mac/objc-gc/test.gyp102
-rw-r--r--chromium/tools/gyp/test/mac/postbuild-copy-bundle/test.gyp49
-rw-r--r--chromium/tools/gyp/test/mac/postbuild-defaults/test.gyp26
-rw-r--r--chromium/tools/gyp/test/mac/postbuild-fail/test.gyp38
-rw-r--r--chromium/tools/gyp/test/mac/postbuild-multiple-configurations/test.gyp26
-rw-r--r--chromium/tools/gyp/test/mac/postbuild-static-library/test.gyp34
-rw-r--r--chromium/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp53
-rw-r--r--chromium/tools/gyp/test/mac/postbuilds/test.gyp93
-rw-r--r--chromium/tools/gyp/test/mac/prefixheader/test.gyp82
-rw-r--r--chromium/tools/gyp/test/mac/rebuild/test.gyp56
-rw-r--r--chromium/tools/gyp/test/mac/rpath/test.gyp48
-rw-r--r--chromium/tools/gyp/test/mac/sdkroot/test.gyp35
-rw-r--r--chromium/tools/gyp/test/mac/sourceless-module/test.gyp39
-rw-r--r--chromium/tools/gyp/test/mac/strip/subdirectory/subdirectory.gyp38
-rw-r--r--chromium/tools/gyp/test/mac/strip/test.gyp119
-rw-r--r--chromium/tools/gyp/test/mac/type_envvars/test.gyp100
-rw-r--r--chromium/tools/gyp/test/mac/xcode-env-order/test.gyp121
-rw-r--r--chromium/tools/gyp/test/mac/xcode-gcc/test-clang.gyp42
-rw-r--r--chromium/tools/gyp/test/mac/xcode-gcc/test.gyp60
-rw-r--r--chromium/tools/gyp/test/make/dependencies.gyp15
-rw-r--r--chromium/tools/gyp/test/make/noload/all.gyp18
-rw-r--r--chromium/tools/gyp/test/make/noload/lib/shared.gyp16
-rw-r--r--chromium/tools/gyp/test/make_global_settings/basics/make_global_settings.gyp17
-rw-r--r--chromium/tools/gyp/test/make_global_settings/env-wrapper/wrapper.gyp18
-rw-r--r--chromium/tools/gyp/test/make_global_settings/wrapper/wrapper.gyp21
-rw-r--r--chromium/tools/gyp/test/many-actions/many-actions-unsorted.gyp154
-rw-r--r--chromium/tools/gyp/test/many-actions/many-actions.gyp1817
-rw-r--r--chromium/tools/gyp/test/module/src/module.gyp55
-rw-r--r--chromium/tools/gyp/test/msvs/config_attrs/hello.gyp21
-rw-r--r--chromium/tools/gyp/test/msvs/express/base/base.gyp22
-rw-r--r--chromium/tools/gyp/test/msvs/express/express.gyp19
-rw-r--r--chromium/tools/gyp/test/msvs/external_builder/external.gyp68
-rw-r--r--chromium/tools/gyp/test/msvs/list_excluded/hello_exclude.gyp19
-rw-r--r--chromium/tools/gyp/test/msvs/missing_sources/hello_missing.gyp15
-rw-r--r--chromium/tools/gyp/test/msvs/props/hello.gyp22
-rw-r--r--chromium/tools/gyp/test/msvs/shared_output/common.gypi17
-rw-r--r--chromium/tools/gyp/test/msvs/shared_output/hello.gyp21
-rw-r--r--chromium/tools/gyp/test/msvs/shared_output/there/there.gyp16
-rw-r--r--chromium/tools/gyp/test/msvs/uldi2010/hello.gyp26
-rw-r--r--chromium/tools/gyp/test/multiple-targets/src/multiple.gyp24
-rw-r--r--chromium/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp88
-rw-r--r--chromium/tools/gyp/test/ninja/chained-dependency/chained-dependency.gyp53
-rw-r--r--chromium/tools/gyp/test/ninja/normalize-paths-win/normalize-paths.gyp56
-rw-r--r--chromium/tools/gyp/test/ninja/s-needs-no-depfiles/s-needs-no-depfiles.gyp13
-rw-r--r--chromium/tools/gyp/test/ninja/solibs_avoid_relinking/solibs_avoid_relinking.gyp38
-rw-r--r--chromium/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.gyp15
-rw-r--r--chromium/tools/gyp/test/no-output/src/nooutput.gyp17
-rw-r--r--chromium/tools/gyp/test/product/product.gyp128
-rw-r--r--chromium/tools/gyp/test/relative/foo/a/a.gyp13
-rw-r--r--chromium/tools/gyp/test/relative/foo/a/c/c.gyp12
-rw-r--r--chromium/tools/gyp/test/relative/foo/b/b.gyp9
-rw-r--r--chromium/tools/gyp/test/rename/filecase/test-casesensitive.gyp15
-rw-r--r--chromium/tools/gyp/test/rename/filecase/test.gyp14
-rw-r--r--chromium/tools/gyp/test/restat/src/restat.gyp50
-rw-r--r--chromium/tools/gyp/test/rules-dirname/src/actions.gyp15
-rw-r--r--chromium/tools/gyp/test/rules-dirname/src/subdir/input-rule-dirname.gyp92
-rw-r--r--chromium/tools/gyp/test/rules-rebuild/src/same_target.gyp31
-rw-r--r--chromium/tools/gyp/test/rules-use-built-dependencies/src/use-built-dependencies-rule.gyp42
-rw-r--r--chromium/tools/gyp/test/rules-variables/src/variables.gyp40
-rw-r--r--chromium/tools/gyp/test/rules/src/actions.gyp22
-rw-r--r--chromium/tools/gyp/test/rules/src/external/external.gyp66
-rw-r--r--chromium/tools/gyp/test/rules/src/input-root.gyp24
-rw-r--r--chromium/tools/gyp/test/rules/src/noaction/no_action_with_rules_fails.gyp37
-rw-r--r--chromium/tools/gyp/test/rules/src/special-variables.gyp35
-rw-r--r--chromium/tools/gyp/test/rules/src/subdir1/executable.gyp37
-rw-r--r--chromium/tools/gyp/test/rules/src/subdir2/never_used.gyp31
-rw-r--r--chromium/tools/gyp/test/rules/src/subdir2/no_action.gyp38
-rw-r--r--chromium/tools/gyp/test/rules/src/subdir2/no_inputs.gyp32
-rw-r--r--chromium/tools/gyp/test/rules/src/subdir2/none.gyp33
-rw-r--r--chromium/tools/gyp/test/rules/src/subdir3/executable2.gyp37
-rw-r--r--chromium/tools/gyp/test/rules/src/subdir4/build-asm.gyp49
-rw-r--r--chromium/tools/gyp/test/same-gyp-name/library/one/sub.gyp11
-rw-r--r--chromium/tools/gyp/test/same-gyp-name/library/test.gyp15
-rw-r--r--chromium/tools/gyp/test/same-gyp-name/library/two/sub.gyp11
-rw-r--r--chromium/tools/gyp/test/same-gyp-name/src/all.gyp16
-rw-r--r--chromium/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp15
-rw-r--r--chromium/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp15
-rw-r--r--chromium/tools/gyp/test/same-rule-output-file-name/src/subdir1/subdir1.gyp30
-rw-r--r--chromium/tools/gyp/test/same-rule-output-file-name/src/subdir2/subdir2.gyp30
-rw-r--r--chromium/tools/gyp/test/same-rule-output-file-name/src/subdirs.gyp16
-rw-r--r--chromium/tools/gyp/test/same-source-file-name/src/all.gyp30
-rw-r--r--chromium/tools/gyp/test/same-source-file-name/src/double-executable.gyp21
-rw-r--r--chromium/tools/gyp/test/same-source-file-name/src/double-shared.gyp21
-rw-r--r--chromium/tools/gyp/test/same-source-file-name/src/double-static.gyp21
-rw-r--r--chromium/tools/gyp/test/same-target-name-different-directory/src/subdir1/subdir1.gyp66
-rw-r--r--chromium/tools/gyp/test/same-target-name-different-directory/src/subdir2/subdir2.gyp66
-rw-r--r--chromium/tools/gyp/test/same-target-name-different-directory/src/subdirs.gyp16
-rw-r--r--chromium/tools/gyp/test/same-target-name/src/all.gyp16
-rw-r--r--chromium/tools/gyp/test/same-target-name/src/executable1.gyp15
-rw-r--r--chromium/tools/gyp/test/same-target-name/src/executable2.gyp15
-rw-r--r--chromium/tools/gyp/test/sanitize-rule-names/sanitize-rule-names.gyp27
-rw-r--r--chromium/tools/gyp/test/self-dependency/common.gypi13
-rw-r--r--chromium/tools/gyp/test/self-dependency/dep.gyp23
-rw-r--r--chromium/tools/gyp/test/self-dependency/self_dependency.gyp15
-rw-r--r--chromium/tools/gyp/test/sibling/src/build/all.gyp16
-rw-r--r--chromium/tools/gyp/test/sibling/src/prog1/prog1.gyp15
-rw-r--r--chromium/tools/gyp/test/sibling/src/prog2/prog2.gyp15
-rw-r--r--chromium/tools/gyp/test/standalone-static-library/invalid.gyp16
-rw-r--r--chromium/tools/gyp/test/standalone-static-library/mylib.gyp26
-rw-r--r--chromium/tools/gyp/test/standalone/standalone.gyp12
-rw-r--r--chromium/tools/gyp/test/subdirectory/src/prog1.gyp21
-rw-r--r--chromium/tools/gyp/test/subdirectory/src/subdir/prog2.gyp18
-rw-r--r--chromium/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp18
-rw-r--r--chromium/tools/gyp/test/subdirectory/src/symroot.gypi16
-rw-r--r--chromium/tools/gyp/test/toolsets/toolsets.gyp62
-rw-r--r--chromium/tools/gyp/test/toplevel-dir/src/sub1/main.gyp18
-rw-r--r--chromium/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp15
-rw-r--r--chromium/tools/gyp/test/variables/commands/commands-repeated.gyp128
-rw-r--r--chromium/tools/gyp/test/variables/commands/commands.gyp91
-rw-r--r--chromium/tools/gyp/test/variables/commands/commands.gypi23
-rw-r--r--chromium/tools/gyp/test/variables/filelist/src/filelist.gyp93
-rw-r--r--chromium/tools/gyp/test/variables/latelate/src/latelate.gyp34
-rw-r--r--chromium/tools/gyp/test/variables/variable-in-path/variable-in-path.gyp31
-rw-r--r--chromium/tools/gyp/test/win/asm-files/asm-files.gyp17
-rw-r--r--chromium/tools/gyp/test/win/batch-file-action/batch-file-action.gyp21
-rw-r--r--chromium/tools/gyp/test/win/command-quote/command-quote.gyp84
-rw-r--r--chromium/tools/gyp/test/win/command-quote/subdir/and/another/in-subdir.gyp28
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/additional-include-dirs.gyp20
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/additional-options.gyp31
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/analysis.gyp40
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/buffer-security-check.gyp51
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/character-set.gyp35
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/debug-format.gyp48
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.gyp20
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/exception-handling.gyp46
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/force-include-files.gyp20
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/function-level-linking.gyp28
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/optimizations.gyp207
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/pdbname-override.gyp26
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/pdbname.gyp24
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/rtti.gyp37
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/runtime-checks.gyp29
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/runtime-library.gyp48
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type.gyp33
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/warning-as-error.gyp37
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/warning-level.gyp115
-rw-r--r--chromium/tools/gyp/test/win/generator-output-different-drive/prog.gyp15
-rw-r--r--chromium/tools/gyp/test/win/idl-rules/basic-idl.gyp42
-rw-r--r--chromium/tools/gyp/test/win/importlib/importlib.gyp30
-rw-r--r--chromium/tools/gyp/test/win/large-pdb/large-pdb.gyp98
-rw-r--r--chromium/tools/gyp/test/win/lib-flags/ltcg.gyp21
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/additional-deps.gyp30
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/additional-options.gyp29
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/aslr.gyp35
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/debug-info.gyp28
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/deffile-multiple.gyp17
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/deffile.gyp38
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/delay-load-dlls.gyp35
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/embed-manifest.gyp109
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/enable-uac.gyp45
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/entrypointsymbol.gyp28
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/fixed-base.gyp52
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/generate-manifest.gyp64
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/incremental.gyp65
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/large-address-aware.gyp28
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/library-adjust.gyp16
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/library-directories.gyp42
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/mapfile.gyp45
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/no-default-libs.gyp13
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/nodefaultlib.gyp30
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/nxcompat.gyp35
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/opt-icf.gyp63
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/opt-ref.gyp56
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/outputfile.gyp58
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/profile.gyp50
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/program-database.gyp39
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/subdir/library.gyp13
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/subsystem.gyp48
-rw-r--r--chromium/tools/gyp/test/win/linker-flags/tsaware.gyp28
-rw-r--r--chromium/tools/gyp/test/win/long-command-line/long-command-line.gyp54
-rw-r--r--chromium/tools/gyp/test/win/precompiled/hello.gyp28
-rw-r--r--chromium/tools/gyp/test/win/rc-build/hello.gyp66
-rw-r--r--chromium/tools/gyp/test/win/shard/shard.gyp20
-rw-r--r--chromium/tools/gyp/test/win/uldi/uldi.gyp45
-rw-r--r--chromium/tools/gyp/test/win/vs-macros/containing-gyp.gyp40
-rw-r--r--chromium/tools/gyp/test/win/vs-macros/input-output-macros.gyp33
-rw-r--r--chromium/tools/gyp/test/win/vs-macros/projectname.gyp29
-rw-r--r--chromium/tools/gyp/test/win/vs-macros/targetname.gyp52
-rw-r--r--chromium/tools/gyp/test/win/vs-macros/vcinstalldir.gyp41
-rw-r--r--chromium/tools/gyp/tools/README15
-rw-r--r--chromium/tools/gyp/tools/Xcode/README5
-rw-r--r--chromium/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec27
-rw-r--r--chromium/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec226
-rw-r--r--chromium/tools/gyp/tools/emacs/README12
-rw-r--r--chromium/tools/gyp/tools/emacs/gyp-tests.el63
-rw-r--r--chromium/tools/gyp/tools/emacs/gyp.el251
-rwxr-xr-xchromium/tools/gyp/tools/emacs/run-unit-tests.sh7
-rw-r--r--chromium/tools/gyp/tools/emacs/testdata/media.gyp1105
-rw-r--r--chromium/tools/gyp/tools/emacs/testdata/media.gyp.fontified1107
-rwxr-xr-xchromium/tools/gyp/tools/graphviz.py100
-rwxr-xr-xchromium/tools/gyp/tools/pretty_gyp.py155
-rwxr-xr-xchromium/tools/gyp/tools/pretty_sln.py168
-rwxr-xr-xchromium/tools/gyp/tools/pretty_vcproj.py329
-rwxr-xr-xchromium/tools/gypv8sh.py55
-rw-r--r--chromium/tools/heapcheck/PRESUBMIT.py63
-rw-r--r--chromium/tools/heapcheck/base_unittests.gtest-heapcheck.txt3
-rwxr-xr-xchromium/tools/heapcheck/chrome_tests.py499
-rwxr-xr-xchromium/tools/heapcheck/chrome_tests.sh8
-rw-r--r--chromium/tools/heapcheck/content_unittests.gtest-heapcheck.txt1
-rw-r--r--chromium/tools/heapcheck/gpu_unittests.gtest-heapcheck.txt2
-rwxr-xr-xchromium/tools/heapcheck/heapcheck_std.sh5
-rw-r--r--chromium/tools/heapcheck/heapcheck_test.py250
-rw-r--r--chromium/tools/heapcheck/ipc_tests.gtest-heapcheck.txt4
-rw-r--r--chromium/tools/heapcheck/net_unittests.gtest-heapcheck.txt30
-rwxr-xr-xchromium/tools/heapcheck/suppressions.py170
-rw-r--r--chromium/tools/heapcheck/suppressions.txt854
-rw-r--r--chromium/tools/heapcheck/sync_unit_tests.gtest-heapcheck.txt3
-rw-r--r--chromium/tools/heapcheck/unit_tests.gtest-heapcheck.txt38
-rw-r--r--chromium/tools/idl_parser/PRESUBMIT.py15
-rw-r--r--chromium/tools/idl_parser/__init__.py0
-rwxr-xr-xchromium/tools/idl_parser/idl_lexer.py285
-rwxr-xr-xchromium/tools/idl_parser/idl_lexer_test.py99
-rwxr-xr-xchromium/tools/idl_parser/idl_node.py217
-rwxr-xr-xchromium/tools/idl_parser/idl_parser.py1053
-rwxr-xr-xchromium/tools/idl_parser/idl_parser_test.py106
-rwxr-xr-xchromium/tools/idl_parser/idl_ppapi_lexer.py70
-rwxr-xr-xchromium/tools/idl_parser/idl_ppapi_parser.py304
-rwxr-xr-xchromium/tools/idl_parser/run_tests.py20
-rw-r--r--chromium/tools/idl_parser/test_lexer/keywords.in37
-rw-r--r--chromium/tools/idl_parser/test_lexer/keywords_ppapi.in44
-rw-r--r--chromium/tools/idl_parser/test_lexer/values.in55
-rw-r--r--chromium/tools/idl_parser/test_lexer/values_ppapi.in50
-rw-r--r--chromium/tools/idl_parser/test_parser/callback_web.idl116
-rw-r--r--chromium/tools/idl_parser/test_parser/dictionary_web.idl95
-rw-r--r--chromium/tools/idl_parser/test_parser/enum_ppapi.idl126
-rw-r--r--chromium/tools/idl_parser/test_parser/enum_web.idl119
-rw-r--r--chromium/tools/idl_parser/test_parser/exception_web.idl87
-rw-r--r--chromium/tools/idl_parser/test_parser/extattr_ppapi.idl91
-rw-r--r--chromium/tools/idl_parser/test_parser/implements_web.idl52
-rw-r--r--chromium/tools/idl_parser/test_parser/inline_ppapi.idl46
-rw-r--r--chromium/tools/idl_parser/test_parser/interface_web.idl127
-rw-r--r--chromium/tools/idl_parser/test_parser/label_ppapi.idl48
-rw-r--r--chromium/tools/idl_parser/test_parser/struct_ppapi.idl52
-rw-r--r--chromium/tools/idl_parser/test_parser/typedef_ppapi.idl92
-rw-r--r--chromium/tools/idl_parser/test_parser/typedef_web.idl190
-rw-r--r--chromium/tools/imagediff/DEPS4
-rw-r--r--chromium/tools/imagediff/image_diff.cc381
-rw-r--r--chromium/tools/imagediff/image_diff.gyp39
-rw-r--r--chromium/tools/imagediff/image_diff_png.cc650
-rw-r--r--chromium/tools/imagediff/image_diff_png.h35
-rwxr-xr-xchromium/tools/include_tracer.py202
-rwxr-xr-xchromium/tools/ipc_messages_log.py168
-rw-r--r--chromium/tools/json_comment_eater/everything.json13
-rw-r--r--chromium/tools/json_comment_eater/everything_expected.json13
-rw-r--r--chromium/tools/json_comment_eater/json_comment_eater.py60
-rwxr-xr-xchromium/tools/json_comment_eater/json_comment_eater_test.py26
-rw-r--r--chromium/tools/json_schema_compiler/PRESUBMIT.py20
-rw-r--r--chromium/tools/json_schema_compiler/api_gen_util.gyp20
-rw-r--r--chromium/tools/json_schema_compiler/cc_generator.py943
-rw-r--r--chromium/tools/json_schema_compiler/code.py141
-rwxr-xr-xchromium/tools/json_schema_compiler/code_test.py165
-rwxr-xr-xchromium/tools/json_schema_compiler/compiler.py159
-rw-r--r--chromium/tools/json_schema_compiler/cpp_bundle_generator.py291
-rw-r--r--chromium/tools/json_schema_compiler/cpp_generator.py11
-rw-r--r--chromium/tools/json_schema_compiler/cpp_type_generator.py276
-rwxr-xr-xchromium/tools/json_schema_compiler/cpp_type_generator_test.py167
-rw-r--r--chromium/tools/json_schema_compiler/cpp_util.py113
-rwxr-xr-xchromium/tools/json_schema_compiler/cpp_util_test.py31
-rw-r--r--chromium/tools/json_schema_compiler/dart_generator.py762
-rwxr-xr-xchromium/tools/json_schema_compiler/dart_generator_test.py85
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/comments.dart31
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/comments.idl32
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/dictionaries.dart235
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/dictionaries.idl61
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/empty_namespace.dart19
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/empty_namespace.idl7
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/empty_type.dart37
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/empty_type.idl10
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/enums.idl12
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/events.dart282
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/events.idl56
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/functions.dart93
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/functions.idl55
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/operatable_type.dart94
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/operatable_type.idl32
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/tags.dart116
-rw-r--r--chromium/tools/json_schema_compiler/dart_test/tags.idl33
-rw-r--r--chromium/tools/json_schema_compiler/h_generator.py397
-rw-r--r--chromium/tools/json_schema_compiler/highlighters/__init__.py0
-rw-r--r--chromium/tools/json_schema_compiler/highlighters/hilite_me_highlighter.py30
-rw-r--r--chromium/tools/json_schema_compiler/highlighters/none_highlighter.py20
-rw-r--r--chromium/tools/json_schema_compiler/highlighters/pygments_highlighter.py37
-rw-r--r--chromium/tools/json_schema_compiler/idl_schema.py417
-rwxr-xr-xchromium/tools/json_schema_compiler/idl_schema_test.py159
-rw-r--r--chromium/tools/json_schema_compiler/json_parse.py61
-rw-r--r--chromium/tools/json_schema_compiler/json_schema.py50
-rwxr-xr-xchromium/tools/json_schema_compiler/json_schema_test.py83
-rw-r--r--chromium/tools/json_schema_compiler/memoize.py13
-rw-r--r--chromium/tools/json_schema_compiler/model.py492
-rwxr-xr-xchromium/tools/json_schema_compiler/model_test.py104
-rwxr-xr-xchromium/tools/json_schema_compiler/preview.py366
-rw-r--r--chromium/tools/json_schema_compiler/schema_loader.py53
-rw-r--r--chromium/tools/json_schema_compiler/schema_util.py37
-rwxr-xr-xchromium/tools/json_schema_compiler/schema_util_test.py25
-rw-r--r--chromium/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp44
-rw-r--r--chromium/tools/json_schema_compiler/util.cc97
-rw-r--r--chromium/tools/json_schema_compiler/util.h181
-rw-r--r--chromium/tools/json_schema_compiler/util_cc_helper.py85
-rw-r--r--chromium/tools/json_to_struct/PRESUBMIT.py20
-rw-r--r--chromium/tools/json_to_struct/element_generator.py122
-rwxr-xr-xchromium/tools/json_to_struct/element_generator_test.py160
-rwxr-xr-xchromium/tools/json_to_struct/json_to_struct.py211
-rw-r--r--chromium/tools/json_to_struct/struct_generator.py43
-rwxr-xr-xchromium/tools/json_to_struct/struct_generator_test.py58
-rwxr-xr-xchromium/tools/licenses.py477
-rwxr-xr-xchromium/tools/linux/dump-static-initializers.py231
-rw-r--r--chromium/tools/lsan/suppressions.txt51
-rwxr-xr-xchromium/tools/mac/symbolicate_crash.py504
-rw-r--r--chromium/tools/measure_page_load_time/ff_ext/chrome.manifest2
-rw-r--r--chromium/tools/measure_page_load_time/ff_ext/content/firefoxOverlay.xul7
-rw-r--r--chromium/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js209
-rw-r--r--chromium/tools/measure_page_load_time/ff_ext/install.rdf17
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.cpp72
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.def9
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.idl40
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rc121
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rgs29
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.vcproj320
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.cpp292
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.h87
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.rgs27
-rw-r--r--chromium/tools/measure_page_load_time/ie_bho/resource.h18
-rw-r--r--chromium/tools/memory_watcher/DEPS4
-rw-r--r--chromium/tools/memory_watcher/README17
-rw-r--r--chromium/tools/memory_watcher/call_stack.cc399
-rw-r--r--chromium/tools/memory_watcher/call_stack.h168
-rw-r--r--chromium/tools/memory_watcher/dllmain.cc155
-rw-r--r--chromium/tools/memory_watcher/hotkey.h48
-rw-r--r--chromium/tools/memory_watcher/ia32_modrm_map.cc94
-rw-r--r--chromium/tools/memory_watcher/ia32_opcode_map.cc1161
-rw-r--r--chromium/tools/memory_watcher/memory_hook.cc562
-rw-r--r--chromium/tools/memory_watcher/memory_hook.h153
-rw-r--r--chromium/tools/memory_watcher/memory_watcher.cc255
-rw-r--r--chromium/tools/memory_watcher/memory_watcher.gyp43
-rw-r--r--chromium/tools/memory_watcher/memory_watcher.h95
-rw-r--r--chromium/tools/memory_watcher/mini_disassembler.cc392
-rw-r--r--chromium/tools/memory_watcher/mini_disassembler.h163
-rw-r--r--chromium/tools/memory_watcher/mini_disassembler_types.h199
-rw-r--r--chromium/tools/memory_watcher/preamble_patcher.cc228
-rw-r--r--chromium/tools/memory_watcher/preamble_patcher.h293
-rw-r--r--chromium/tools/memory_watcher/preamble_patcher_with_stub.cc174
-rwxr-xr-xchromium/tools/memory_watcher/scripts/finditem.pl56
-rwxr-xr-xchromium/tools/memory_watcher/scripts/memprof.pl116
-rwxr-xr-xchromium/tools/memory_watcher/scripts/memtrace.pl146
-rwxr-xr-xchromium/tools/memory_watcher/scripts/summary.pl156
-rw-r--r--chromium/tools/metrics/OWNERS10
-rw-r--r--chromium/tools/metrics/actions/OWNERS2
-rw-r--r--chromium/tools/metrics/actions/chromeactions.txt1640
-rwxr-xr-xchromium/tools/metrics/actions/extract_actions.py608
-rwxr-xr-xchromium/tools/metrics/actions/extract_actions.sh13
-rw-r--r--chromium/tools/metrics/histograms/PRESUBMIT.py39
-rw-r--r--chromium/tools/metrics/histograms/diffutil.py47
-rw-r--r--chromium/tools/metrics/histograms/extract_histograms.py368
-rw-r--r--chromium/tools/metrics/histograms/find_unmapped_histograms.py227
-rw-r--r--chromium/tools/metrics/histograms/histograms.xml24865
-rwxr-xr-xchromium/tools/metrics/histograms/pretty_print.py358
-rw-r--r--chromium/tools/metrics/histograms/update_extension_functions.py148
-rw-r--r--chromium/tools/metrics/histograms/update_policies.py132
-rw-r--r--chromium/tools/metrics/histograms/validate_format.py17
-rwxr-xr-xchromium/tools/nocompile_driver.py472
-rwxr-xr-xchromium/tools/omahaproxy.py90
-rw-r--r--chromium/tools/oopif/OWNERS4
-rw-r--r--chromium/tools/oopif/iframe_server.py224
-rw-r--r--chromium/tools/page_cycler/acid3/LICENSE1
-rw-r--r--chromium/tools/page_cycler/acid3/README.chromium14
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.css8
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.html1
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.pngbin0 -> 260 bytes
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.txt1
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.xml6
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/favicon.ico0
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/font.svg1
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/font.ttfbin0 -> 12480 bytes
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/head.js139
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/index.html3493
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/reference.html21
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/support-b.png1
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/support-c.pngbin0 -> 2312 bytes
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/svg.svg3
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.1.xhtml11
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.2.xhtml11
-rw-r--r--chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.3.xhtml11
-rw-r--r--chromium/tools/page_cycler/acid3/pages.js31
-rw-r--r--chromium/tools/page_cycler/acid3/start.html7
-rw-r--r--chromium/tools/page_cycler/common/head.js128
-rw-r--r--chromium/tools/page_cycler/common/report.html183
-rw-r--r--chromium/tools/page_cycler/common/start.js82
-rw-r--r--chromium/tools/page_cycler/database/common.js109
-rw-r--r--chromium/tools/page_cycler/database/delete-transactions/index.html26
-rw-r--r--chromium/tools/page_cycler/database/delete-transactions/start.html9
-rw-r--r--chromium/tools/page_cycler/database/head.js125
-rw-r--r--chromium/tools/page_cycler/database/insert-transactions/index.html28
-rw-r--r--chromium/tools/page_cycler/database/insert-transactions/start.html9
-rw-r--r--chromium/tools/page_cycler/database/pseudo-random-transactions/index.html103
-rw-r--r--chromium/tools/page_cycler/database/pseudo-random-transactions/start.html9
-rw-r--r--chromium/tools/page_cycler/database/select-readtransactions-read-results/index.html33
-rw-r--r--chromium/tools/page_cycler/database/select-readtransactions-read-results/start.html9
-rw-r--r--chromium/tools/page_cycler/database/select-readtransactions/index.html26
-rw-r--r--chromium/tools/page_cycler/database/select-readtransactions/start.html9
-rw-r--r--chromium/tools/page_cycler/database/select-transactions/index.html25
-rw-r--r--chromium/tools/page_cycler/database/select-transactions/start.html9
-rw-r--r--chromium/tools/page_cycler/database/update-transactions/index.html28
-rw-r--r--chromium/tools/page_cycler/database/update-transactions/start.html9
-rw-r--r--chromium/tools/page_cycler/indexed_db/basic_insert/index.html91
-rw-r--r--chromium/tools/page_cycler/indexed_db/basic_insert/start.html9
-rw-r--r--chromium/tools/page_cycler/indexed_db/common.js32
-rw-r--r--chromium/tools/page_cycler/indexed_db/head.js125
-rw-r--r--chromium/tools/page_cycler/sample/page1/index.html9
-rw-r--r--chromium/tools/page_cycler/sample/page2/index.html9
-rw-r--r--chromium/tools/page_cycler/sample/page3/index.html9
-rw-r--r--chromium/tools/page_cycler/sample/page4/index.html9
-rw-r--r--chromium/tools/page_cycler/sample/pages.js10
-rw-r--r--chromium/tools/page_cycler/sample/start.html7
-rw-r--r--chromium/tools/page_cycler/startup_test_common/README4
-rw-r--r--chromium/tools/page_cycler/startup_test_common/blank.html5
-rw-r--r--chromium/tools/page_cycler/startup_test_common/head.js7
-rw-r--r--chromium/tools/page_cycler/webpagereplay/README15
-rw-r--r--chromium/tools/page_cycler/webpagereplay/extension/background.html2
-rw-r--r--chromium/tools/page_cycler/webpagereplay/extension/background.js328
-rw-r--r--chromium/tools/page_cycler/webpagereplay/extension/content.js14
-rw-r--r--chromium/tools/page_cycler/webpagereplay/extension/manifest.json29
-rw-r--r--chromium/tools/page_cycler/webpagereplay/extension/page_cycler.js54
-rw-r--r--chromium/tools/page_cycler/webpagereplay/extension/start.js88
-rw-r--r--chromium/tools/page_cycler/webpagereplay/start.html26
-rw-r--r--chromium/tools/page_cycler/webpagereplay/start.js123
-rw-r--r--chromium/tools/perf/OWNERS6
-rw-r--r--chromium/tools/perf/PRESUBMIT.py35
-rw-r--r--chromium/tools/perf/benchmarks/__init__.py0
-rw-r--r--chromium/tools/perf/benchmarks/blink_perf.py19
-rw-r--r--chromium/tools/perf/benchmarks/dom_perf.py91
-rw-r--r--chromium/tools/perf/benchmarks/dromaeo.py76
-rw-r--r--chromium/tools/perf/benchmarks/image_decoding.py12
-rw-r--r--chromium/tools/perf/benchmarks/jsgamebench.py39
-rw-r--r--chromium/tools/perf/benchmarks/kraken.py52
-rw-r--r--chromium/tools/perf/benchmarks/media.py11
-rw-r--r--chromium/tools/perf/benchmarks/memory.py16
-rw-r--r--chromium/tools/perf/benchmarks/octane.py56
-rw-r--r--chromium/tools/perf/benchmarks/page_cycler.py91
-rw-r--r--chromium/tools/perf/benchmarks/pica.py20
-rw-r--r--chromium/tools/perf/benchmarks/robohornet_pro.py40
-rw-r--r--chromium/tools/perf/benchmarks/smoothness.py15
-rw-r--r--chromium/tools/perf/benchmarks/spaceport.py66
-rw-r--r--chromium/tools/perf/benchmarks/startup.py20
-rw-r--r--chromium/tools/perf/benchmarks/sunspider.py52
-rw-r--r--chromium/tools/perf/clear_system_cache/clear_system_cache.gyp23
-rw-r--r--chromium/tools/perf/clear_system_cache/clear_system_cache_main.cc55
-rw-r--r--chromium/tools/perf/measurements/__init__.py0
-rw-r--r--chromium/tools/perf/measurements/blink_perf.js20
-rw-r--r--chromium/tools/perf/measurements/blink_perf.py104
-rw-r--r--chromium/tools/perf/measurements/dromaeo.py30
-rw-r--r--chromium/tools/perf/measurements/image_decoding.py53
-rwxr-xr-xchromium/tools/perf/measurements/loading_measurement_analyzer.py183
-rw-r--r--chromium/tools/perf/measurements/loading_measurement_analyzer_unittest.py54
-rw-r--r--chromium/tools/perf/measurements/loading_profile.py58
-rw-r--r--chromium/tools/perf/measurements/loading_timeline.py34
-rw-r--r--chromium/tools/perf/measurements/loading_trace.py34
-rw-r--r--chromium/tools/perf/measurements/media.py30
-rw-r--r--chromium/tools/perf/measurements/memory.py80
-rw-r--r--chromium/tools/perf/measurements/page_cycler.js61
-rw-r--r--chromium/tools/perf/measurements/page_cycler.py104
-rw-r--r--chromium/tools/perf/measurements/rasterize_and_record.py192
-rw-r--r--chromium/tools/perf/measurements/skpicture_printer.py33
-rw-r--r--chromium/tools/perf/measurements/smoothness.py75
-rw-r--r--chromium/tools/perf/measurements/startup.py74
-rw-r--r--chromium/tools/perf/measurements/tab_switching.py64
-rw-r--r--chromium/tools/perf/measurements/test_data/loading_profile.csv10
-rw-r--r--chromium/tools/perf/measurements/test_data/loading_timeline.csv10
-rw-r--r--chromium/tools/perf/metrics/__init__.py41
-rw-r--r--chromium/tools/perf/metrics/gpu_rendering_stats.py47
-rw-r--r--chromium/tools/perf/metrics/histogram.py40
-rw-r--r--chromium/tools/perf/metrics/histogram_util.py50
-rw-r--r--chromium/tools/perf/metrics/histogram_util_unittest.py27
-rw-r--r--chromium/tools/perf/metrics/io.py57
-rw-r--r--chromium/tools/perf/metrics/loading.py26
-rw-r--r--chromium/tools/perf/metrics/media.js176
-rw-r--r--chromium/tools/perf/metrics/media.py68
-rw-r--r--chromium/tools/perf/metrics/memory.py79
-rw-r--r--chromium/tools/perf/metrics/smoothness.js161
-rw-r--r--chromium/tools/perf/metrics/smoothness.py157
-rw-r--r--chromium/tools/perf/metrics/smoothness_unittest.py113
-rw-r--r--chromium/tools/perf/metrics/timeline.py67
-rw-r--r--chromium/tools/perf/page_sets/2012Q3.json228
-rw-r--r--chromium/tools/perf/page_sets/PRESUBMIT.py63
-rw-r--r--chromium/tools/perf/page_sets/__init__.py15
-rw-r--r--chromium/tools/perf/page_sets/blank_page.json6
-rw-r--r--chromium/tools/perf/page_sets/blank_page/blank_page.html0
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/domcoreattr.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/domcoremodify.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/domcorequery.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/domcoretraverse.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibattrjquery.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibattrprototype.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibeventjquery.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibeventprototype.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibmodifyjquery.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibmodifyprototype.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibstylejquery.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibstyleprototype.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibtraversejquery.json8
-rw-r--r--chromium/tools/perf/page_sets/dromaeo/jslibtraverseprototype.json8
-rw-r--r--chromium/tools/perf/page_sets/image_decoding_measurement.json12
-rw-r--r--chromium/tools/perf/page_sets/intl_ar_fa_he.json32
-rw-r--r--chromium/tools/perf/page_sets/intl_es_fr_pt-BR.json40
-rw-r--r--chromium/tools/perf/page_sets/intl_hi_ru.json46
-rw-r--r--chromium/tools/perf/page_sets/intl_ja_zh.json73
-rw-r--r--chromium/tools/perf/page_sets/intl_ko_th_vi.json52
-rw-r--r--chromium/tools/perf/page_sets/key_desktop_sites.json749
-rw-r--r--chromium/tools/perf/page_sets/key_mobile_sites.json232
-rw-r--r--chromium/tools/perf/page_sets/mobile_memory.json14
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/alexa_us.json26
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/bloat.json7
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/dhtml.json23
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/dom.json15
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/indexed_db/basic_insert.json8
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/intl1.json62
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/intl2.json36
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/morejs.json15
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/morejsnp.json15
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/moz.json47
-rw-r--r--chromium/tools/perf/page_sets/page_cycler/moz2.json47
-rw-r--r--chromium/tools/perf/page_sets/pica.json16
-rw-r--r--chromium/tools/perf/page_sets/top_10.json62
-rw-r--r--chromium/tools/perf/page_sets/top_25.json413
-rw-r--r--chromium/tools/perf/page_sets/tough_animation_cases.json22
-rw-r--r--chromium/tools/perf/page_sets/tough_animation_cases/keyframed_animations.html160
-rw-r--r--chromium/tools/perf/page_sets/tough_animation_cases/transform_transition_js_block.html45
-rw-r--r--chromium/tools/perf/page_sets/tough_animation_cases/transform_transitions.html130
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases.json40
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas-animation-no-clear.html38
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html29
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.js176
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_aligned_canvas.js18
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_aligned_image_data.js19
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_canvas.js18
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_gradient.js16
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_image.js13
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_white.js13
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_canvas_sprite.js41
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_filled_path.js31
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_image.js20
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_image_with_shadow.js24
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_rect.js18
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_text.js21
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/chromium.pngbin0 -> 1790 bytes
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/kiddie_logo.pngbin0 -> 1801 bytes
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/parse_url.js26
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/compositing_huge_div/index.html46
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/many_images/bench.js29
-rwxr-xr-xchromium/tools/perf/page_sets/tough_canvas_cases/many_images/images/generate_images.sh25
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/many_images/many_images.html443
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/many_images/single_image.html44
-rw-r--r--chromium/tools/perf/page_sets/tough_canvas_cases/many_images/sprites.js41
-rw-r--r--chromium/tools/perf/page_sets/tough_image_cases.json8
-rw-r--r--chromium/tools/perf/page_sets/tough_layer_cases.json6
-rw-r--r--chromium/tools/perf/page_sets/tough_layer_cases/opacity.html42
-rw-r--r--chromium/tools/perf/page_sets/tough_layout_cases.json39
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases.json15
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/background_fixed.html50
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/busy.js40
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/cust_scrollbar.html56
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/div_scrolls.html52
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/fixed_nonstacking.html52
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/fixed_stacking.html52
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/iframe_scrolls.html50
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/image.pngbin0 -> 10502 bytes
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/simple.html49
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/wheel_body_prevdefault.html54
-rw-r--r--chromium/tools/perf/page_sets/tough_scrolling_cases/wheel_div_prevdefault.html57
-rw-r--r--chromium/tools/perf/page_sets/tough_texture_upload_cases.json10
-rw-r--r--chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation.html42
-rw-r--r--chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_and_transform_animation.html67
-rw-r--r--chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_with_gradient.html50
-rw-r--r--chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_with_gradient_and_transform_animation.html75
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases.json75
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/bear.webmbin0 -> 219229 bytes
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd.ogg.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd.wav.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd1080.mp4.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd1080.ogv.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd1080.webm.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd2160.mp4.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd2160.ogv.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd2160.webm.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd360.mp4.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd360.ogv.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd360.webm.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd480.webm.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/crowd720.webm.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/tulip2.m4a.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/tulip2.mp3.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/tulip2.mp4.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/tulip2.ogg.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/tulip2.ogv.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/tulip2.wav.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/tulip2.webm.sha11
-rw-r--r--chromium/tools/perf/page_sets/tough_video_cases/video.html37
-rw-r--r--chromium/tools/perf/page_sets/typical_25.json92
-rw-r--r--chromium/tools/perf/perf_tools/__init__.py39
-rw-r--r--chromium/tools/perf/perf_tools/bootstrap_deps29
-rw-r--r--chromium/tools/perf/profile_creators/__init__.py4
-rw-r--r--chromium/tools/perf/profile_creators/small_profile_creator.py23
-rwxr-xr-xchromium/tools/perf/record_wpr17
-rwxr-xr-xchromium/tools/perf/run_benchmark13
-rwxr-xr-xchromium/tools/perf/run_measurement102
-rwxr-xr-xchromium/tools/perf/run_multipage_benchmarks16
-rwxr-xr-xchromium/tools/perf/run_tests35
-rw-r--r--chromium/tools/perf/test-info.json295
-rw-r--r--chromium/tools/perf/trace-info.json342
-rw-r--r--chromium/tools/perf/unit-info.json94
-rw-r--r--chromium/tools/perf/utils/results_viewer/src/base.js84
-rw-r--r--chromium/tools/perf/utils/results_viewer/src/main.css13
-rw-r--r--chromium/tools/perf/utils/results_viewer/src/main.js293
-rw-r--r--chromium/tools/perf/utils/results_viewer/src/results_viewer.html39
-rw-r--r--chromium/tools/perf/utils/results_viewer/src/results_viewer.js51
-rw-r--r--chromium/tools/perf/utils/results_viewer/src/ui.js83
-rw-r--r--chromium/tools/perf_expectations/PRESUBMIT.py42
-rw-r--r--chromium/tools/perf_expectations/README.txt2
-rw-r--r--chromium/tools/perf_expectations/chromium_perf_expectations.cfg4
-rwxr-xr-xchromium/tools/perf_expectations/make_expectations.py375
-rw-r--r--chromium/tools/perf_expectations/perf_expectations.json746
-rw-r--r--chromium/tools/perf_expectations/sample_test_cases.json28
-rwxr-xr-xchromium/tools/perf_expectations/update_perf_expectations.py263
-rwxr-xr-xchromium/tools/perf_expectations/update_perf_expectations_unittest.py204
-rw-r--r--chromium/tools/playback_benchmark/common.js320
-rw-r--r--chromium/tools/playback_benchmark/playback.js258
-rw-r--r--chromium/tools/playback_benchmark/playback_driver.py195
-rw-r--r--chromium/tools/playback_benchmark/proxy_handler.py122
-rwxr-xr-xchromium/tools/playback_benchmark/run.py44
-rwxr-xr-xchromium/tools/prepare-bisect-perf-regression.py64
-rwxr-xr-xchromium/tools/protoc_wrapper/protoc_wrapper.py110
-rw-r--r--chromium/tools/python/google/__init__.py1
-rwxr-xr-xchromium/tools/python/google/gethash_timer.py149
-rw-r--r--chromium/tools/python/google/httpd_config/httpd.conf734
-rw-r--r--chromium/tools/python/google/httpd_config/httpd2.conf280
-rw-r--r--chromium/tools/python/google/httpd_config/httpd2.pem110
-rw-r--r--chromium/tools/python/google/httpd_config/httpd2_linux.conf144
-rw-r--r--chromium/tools/python/google/httpd_config/httpd2_mac.conf229
-rw-r--r--chromium/tools/python/google/httpd_config/mime.types599
-rw-r--r--chromium/tools/python/google/httpd_config/root_ca_cert.pem102
-rwxr-xr-xchromium/tools/python/google/httpd_utils.py200
-rw-r--r--chromium/tools/python/google/logging_utils.py82
-rw-r--r--chromium/tools/python/google/path_utils.py84
-rw-r--r--chromium/tools/python/google/platform_utils.py23
-rw-r--r--chromium/tools/python/google/platform_utils_linux.py148
-rw-r--r--chromium/tools/python/google/platform_utils_mac.py145
-rw-r--r--chromium/tools/python/google/platform_utils_win.py194
-rw-r--r--chromium/tools/python/google/process_utils.py221
-rwxr-xr-xchromium/tools/run-bisect-manual-test.py113
-rw-r--r--chromium/tools/run-bisect-perf-regression.cfg89
-rwxr-xr-xchromium/tools/run-bisect-perf-regression.py179
-rwxr-xr-xchromium/tools/safely-roll-blink.py127
-rw-r--r--chromium/tools/set_default_handler/DEPS4
-rw-r--r--chromium/tools/set_default_handler/set_default_handler.gyp25
-rw-r--r--chromium/tools/set_default_handler/set_default_handler_main.cc67
-rw-r--r--chromium/tools/sharding_supervisor/PRESUBMIT.py24
-rw-r--r--chromium/tools/sharding_supervisor/data/gtest_results.xml023
-rw-r--r--chromium/tools/sharding_supervisor/data/gtest_results.xml119
-rw-r--r--chromium/tools/sharding_supervisor/data/gtest_results_expected.xml22
-rwxr-xr-xchromium/tools/sharding_supervisor/dummy_test.py12
-rwxr-xr-xchromium/tools/sharding_supervisor/sharding_supervisor.py84
-rw-r--r--chromium/tools/sharding_supervisor/stdio_buffer.py52
-rwxr-xr-xchromium/tools/site_compare/command_line.py802
-rw-r--r--chromium/tools/site_compare/commands/__init__.py0
-rw-r--r--chromium/tools/site_compare/commands/compare2.py170
-rw-r--r--chromium/tools/site_compare/commands/maskmaker.py272
-rw-r--r--chromium/tools/site_compare/commands/measure.py52
-rw-r--r--chromium/tools/site_compare/commands/scrape.py59
-rw-r--r--chromium/tools/site_compare/commands/timeload.py144
-rw-r--r--chromium/tools/site_compare/drivers/__init__.py13
-rw-r--r--chromium/tools/site_compare/drivers/win32/__init__.py0
-rwxr-xr-xchromium/tools/site_compare/drivers/win32/keyboard.py201
-rwxr-xr-xchromium/tools/site_compare/drivers/win32/mouse.py222
-rwxr-xr-xchromium/tools/site_compare/drivers/win32/windowing.py366
-rw-r--r--chromium/tools/site_compare/operators/__init__.py23
-rw-r--r--chromium/tools/site_compare/operators/equals.py37
-rw-r--r--chromium/tools/site_compare/operators/equals_with_mask.py57
-rwxr-xr-xchromium/tools/site_compare/scrapers/__init__.py33
-rwxr-xr-xchromium/tools/site_compare/scrapers/chrome/__init__.py36
-rw-r--r--chromium/tools/site_compare/scrapers/chrome/chrome011010.py42
-rw-r--r--chromium/tools/site_compare/scrapers/chrome/chrome01970.py42
-rwxr-xr-xchromium/tools/site_compare/scrapers/chrome/chromebase.py199
-rwxr-xr-xchromium/tools/site_compare/scrapers/firefox/__init__.py28
-rwxr-xr-xchromium/tools/site_compare/scrapers/firefox/firefox2.py249
-rwxr-xr-xchromium/tools/site_compare/scrapers/ie/__init__.py28
-rwxr-xr-xchromium/tools/site_compare/scrapers/ie/ie7.py210
-rwxr-xr-xchromium/tools/site_compare/site_compare.py176
-rw-r--r--chromium/tools/site_compare/utils/__init__.py0
-rw-r--r--chromium/tools/site_compare/utils/browser_iterate.py199
-rwxr-xr-xchromium/tools/sort-headers.py185
-rw-r--r--chromium/tools/stats_viewer/OpenDialog.Designer.cs88
-rw-r--r--chromium/tools/stats_viewer/OpenDialog.cs45
-rw-r--r--chromium/tools/stats_viewer/OpenDialog.resx120
-rw-r--r--chromium/tools/stats_viewer/Properties/AssemblyInfo.cs33
-rw-r--r--chromium/tools/stats_viewer/Properties/Resources.Designer.cs71
-rw-r--r--chromium/tools/stats_viewer/Properties/Resources.resx117
-rw-r--r--chromium/tools/stats_viewer/Properties/Settings.Designer.cs30
-rw-r--r--chromium/tools/stats_viewer/Properties/Settings.settings7
-rw-r--r--chromium/tools/stats_viewer/Resources.Designer.cs77
-rw-r--r--chromium/tools/stats_viewer/Resources.resx127
-rw-r--r--chromium/tools/stats_viewer/Resources/kitten.pngbin0 -> 36163 bytes
-rw-r--r--chromium/tools/stats_viewer/Resources/kittenbackground.pngbin0 -> 1275 bytes
-rw-r--r--chromium/tools/stats_viewer/program.cs23
-rw-r--r--chromium/tools/stats_viewer/stats_table.cs546
-rw-r--r--chromium/tools/stats_viewer/stats_viewer.Designer.cs392
-rw-r--r--chromium/tools/stats_viewer/stats_viewer.cs510
-rw-r--r--chromium/tools/stats_viewer/stats_viewer.csproj107
-rw-r--r--chromium/tools/stats_viewer/stats_viewer.resx1129
-rw-r--r--chromium/tools/stats_viewer/win32.cs50
-rw-r--r--chromium/tools/swarm_client/PRESUBMIT.py62
-rwxr-xr-xchromium/tools/swarm_client/README.py58
-rwxr-xr-xchromium/tools/swarm_client/WATCHLISTS24
-rw-r--r--chromium/tools/swarm_client/codereview.settings4
-rw-r--r--chromium/tools/swarm_client/example/hello_world.isolate40
-rwxr-xr-xchromium/tools/swarm_client/example/hello_world.py17
-rwxr-xr-xchromium/tools/swarm_client/example/run_example_cad.py84
-rwxr-xr-xchromium/tools/swarm_client/example/run_example_local.py81
-rwxr-xr-xchromium/tools/swarm_client/example/run_example_swarm.py106
-rwxr-xr-xchromium/tools/swarm_client/googletest/README.py32
-rwxr-xr-xchromium/tools/swarm_client/googletest/fix_test_cases.py244
-rwxr-xr-xchromium/tools/swarm_client/googletest/isolate_test_cases.py174
-rwxr-xr-xchromium/tools/swarm_client/googletest/list_test_cases.py57
-rwxr-xr-xchromium/tools/swarm_client/googletest/run_test_cases.py1736
-rwxr-xr-xchromium/tools/swarm_client/googletest/shard_test_cases.py46
-rwxr-xr-xchromium/tools/swarm_client/googletest/trace_test_cases.py204
-rwxr-xr-xchromium/tools/swarm_client/isolate.py2393
-rwxr-xr-xchromium/tools/swarm_client/isolate_merge.py71
-rwxr-xr-xchromium/tools/swarm_client/isolateserver_archive.py400
-rwxr-xr-xchromium/tools/swarm_client/run_isolated.py2206
-rw-r--r--chromium/tools/swarm_client/short_expression_finder.py176
-rwxr-xr-xchromium/tools/swarm_client/swarm_get_results.py210
-rwxr-xr-xchromium/tools/swarm_client/swarm_trigger_and_get_results.py142
-rwxr-xr-xchromium/tools/swarm_client/swarm_trigger_step.py317
-rw-r--r--chromium/tools/swarm_client/third_party/README.chromium11
-rw-r--r--chromium/tools/swarm_client/third_party/__init__.py0
-rwxr-xr-xchromium/tools/swarm_client/third_party/upload.py2394
-rwxr-xr-xchromium/tools/swarm_client/tools/harvest_buildbot.py101
-rw-r--r--chromium/tools/swarm_client/tools/run_a_test.isolate13
-rwxr-xr-xchromium/tools/swarm_client/tools/run_swarm_tests_on_swarm.py245
-rwxr-xr-xchromium/tools/swarm_client/tools/swarm_cleanup.py126
-rwxr-xr-xchromium/tools/swarm_client/tools/zip_profiler.py123
-rwxr-xr-xchromium/tools/swarm_client/trace_inputs.py3868
-rwxr-xr-xchromium/tools/swig/swig.py45
-rw-r--r--chromium/tools/symsrc/COPYING-pefile27
-rw-r--r--chromium/tools/symsrc/README.chromium14
-rwxr-xr-xchromium/tools/symsrc/img_fingerprint.py34
-rwxr-xr-xchromium/tools/symsrc/pdb_fingerprint_from_img.py64
-rw-r--r--chromium/tools/symsrc/pefile.py3729
-rwxr-xr-xchromium/tools/symsrc/source_index.py226
-rwxr-xr-xchromium/tools/sync-webkit-git.py221
-rwxr-xr-xchromium/tools/tcmalloc/print-live-objects.py91
-rw-r--r--chromium/tools/telemetry/OWNERS11
-rw-r--r--chromium/tools/telemetry/PRESUBMIT.py53
-rw-r--r--chromium/tools/telemetry/README5
-rw-r--r--chromium/tools/telemetry/build/__init__.py3
-rw-r--r--chromium/tools/telemetry/build/update_docs.py148
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.browser.html176
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.browser_credentials.html78
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.browser_finder.html179
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.browser_options.html79
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.adb_commands.html173
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.android_browser_backend.html318
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.android_browser_finder.html102
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.browser_backend.html218
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.cros_browser_backend.html177
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.cros_browser_finder.html94
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.cros_interface.html250
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.crx_id.html41
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.desktop_browser_backend.html140
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.desktop_browser_finder.html100
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.extension_dict_backend.html133
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.facebook_credentials_backend.html88
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.form_based_credentials_backend.html79
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.form_based_credentials_backend_unittest_base.html343
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.google_credentials_backend.html88
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.html65
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_backend.html198
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_console.html60
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_memory.html133
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_network.html51
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_page.html74
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_runtime.html72
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_timeline.html133
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.misc_web_contents_backend.html68
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.png_bitmap.html100
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.tab_list_backend.html85
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.trace_result.html54
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.tracing_backend.html160
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.chrome.websocket.html40
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.discover.html55
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.exceptions.html338
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.extension_dict.html64
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.extension_page.html103
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.extension_to_load.html194
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.html57
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.memory_cache_http_server.html560
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.android_platform_backend.html102
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.cros_platform_backend.html101
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.html108
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.linux_platform_backend.html97
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.mac_platform_backend.html98
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.platform_backend.html77
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.posix_platform_backend.html94
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.profiler.html73
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.profiler.iprofiler_profiler.html76
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.profiler.java_heap_profiler.html77
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.profiler.perf_profiler.html76
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.profiler.profiler_finder.html38
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.profiler.sample_profiler.html76
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.profiler.tcmalloc_heap_profiler.html76
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.profiler.trace_profiler.html72
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.platform.win_platform_backend.html108
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.possible_browser.html63
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.profile_creator.html53
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.profile_types.html51
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.tab.html168
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.tab_list.html61
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.temporary_http_server.html76
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.async_slice.html77
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.bounds.html71
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.counter.html113
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.event.html55
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.event_container.html55
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.html39
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.importer.html61
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.inspector_importer.html76
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.model.html85
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.process.html87
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.sample.html77
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.slice.html90
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.thread.html118
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.timeline.trace_event_importer.html78
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.user_agent.html33
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.util.html138
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.web_contents.html94
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.wpr_modes.html25
-rw-r--r--chromium/tools/telemetry/docs/telemetry.core.wpr_server.html74
-rw-r--r--chromium/tools/telemetry/docs/telemetry.html491
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.all_page_actions.html36
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.click_element.html99
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.html33
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.js_collect_garbage.html96
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.page_action.html205
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.play.html107
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.reload.html97
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.scroll.html85
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.actions.wait.html98
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.block_page_measurement_results.html144
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.buildbot_page_measurement_results.html147
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.cloud_storage.html40
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.csv_page_measurement_results.html144
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.gtest_test_results.html125
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.html54
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page.html79
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_filter.html66
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_measurement.html248
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_measurement_results.html177
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_measurement_runner.html106
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_measurement_unittest_base.html346
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_measurement_value.html61
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_runner.html84
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_set.html82
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_set_archive_info.html71
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_test.html194
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_test_results.html120
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.page_test_runner.html104
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.perf_tests_helper.html41
-rw-r--r--chromium/tools/telemetry/docs/telemetry.page.record_wpr.html140
-rw-r--r--chromium/tools/telemetry/docs/telemetry.test.html74
-rw-r--r--chromium/tools/telemetry/docs/telemetry.test_runner.html229
-rw-r--r--chromium/tools/telemetry/docs/telemetry.unittest.gtest_testrunner.html121
-rw-r--r--chromium/tools/telemetry/docs/telemetry.unittest.html41
-rw-r--r--chromium/tools/telemetry/docs/telemetry.unittest.options_for_unittests.html31
-rw-r--r--chromium/tools/telemetry/docs/telemetry.unittest.run_tests.html42
-rw-r--r--chromium/tools/telemetry/docs/telemetry.unittest.simple_mock.html106
-rw-r--r--chromium/tools/telemetry/docs/telemetry.unittest.system_stub.html164
-rw-r--r--chromium/tools/telemetry/docs/telemetry.unittest.tab_test_case.html334
-rw-r--r--chromium/tools/telemetry/examples/credentials_example.json10
-rwxr-xr-xchromium/tools/telemetry/examples/list_available_browsers21
-rwxr-xr-xchromium/tools/telemetry/examples/telemetry_perf_test.py44
-rw-r--r--chromium/tools/telemetry/examples/top1k999
-rwxr-xr-xchromium/tools/telemetry/run_tests21
-rw-r--r--chromium/tools/telemetry/support/html_output/results-template.html598
-rw-r--r--chromium/tools/telemetry/telemetry/__init__.py51
-rw-r--r--chromium/tools/telemetry/telemetry/core/__init__.py3
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/__init__.py3
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/browser_backend.py96
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/chrome/__init__.py3
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py231
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/webdriver/__init__.py3
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_browser_backend.py70
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_desktop_browser_finder.py103
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_backend.py120
-rw-r--r--chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_list_backend.py47
-rw-r--r--chromium/tools/telemetry/telemetry/core/browser.py319
-rw-r--r--chromium/tools/telemetry/telemetry/core/browser_credentials.py145
-rw-r--r--chromium/tools/telemetry/telemetry/core/browser_credentials_unittest.py71
-rw-r--r--chromium/tools/telemetry/telemetry/core/browser_finder.py106
-rw-r--r--chromium/tools/telemetry/telemetry/core/browser_options.py242
-rw-r--r--chromium/tools/telemetry/telemetry/core/browser_options_unittest.py99
-rw-r--r--chromium/tools/telemetry/telemetry/core/browser_unittest.py125
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/__init__.py3
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/adb_commands.py182
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/android_browser_backend.py304
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder.py185
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder_unittest.py89
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/main.html9
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/main.js17
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/manifest.json16
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py407
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/cros_browser_finder.py110
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/cros_browser_finder_unittest.py11
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/cros_interface.py345
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/cros_interface_unittest.py158
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/crx_id.py18
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_backend.py190
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder.py254
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder_unittest.py188
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/extension_dict_backend.py71
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/facebook_credentials_backend.py32
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/facebook_credentials_backend_unittest.py16
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/form_based_credentials_backend.py110
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/form_based_credentials_backend_unittest_base.py128
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/google_credentials_backend.py31
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/google_credentials_backend_unittest.py16
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_backend.py326
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_console.py61
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_console_unittest.py37
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_memory.py50
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_memory_unittest.py25
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_network.py17
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_page.py114
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_page_unittest.py55
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_runtime.py56
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_runtime_unittest.py31
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_timeline.py71
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/inspector_timeline_unittest.py37
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/misc_web_contents_backend.py38
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/png_bitmap.py72
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/png_bitmap_unittest.py27
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/tab_list_backend.py135
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/trace_result.py16
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/tracing_backend.py161
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/tracing_backend_unittest.py92
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/websocket.py19
-rw-r--r--chromium/tools/telemetry/telemetry/core/chrome/websocket_unittest.py10
-rw-r--r--chromium/tools/telemetry/telemetry/core/discover.py73
-rw-r--r--chromium/tools/telemetry/telemetry/core/discover_unittest.py26
-rw-r--r--chromium/tools/telemetry/telemetry/core/exceptions.py26
-rw-r--r--chromium/tools/telemetry/telemetry/core/extension_dict.py25
-rw-r--r--chromium/tools/telemetry/telemetry/core/extension_page.py12
-rw-r--r--chromium/tools/telemetry/telemetry/core/extension_to_load.py65
-rw-r--r--chromium/tools/telemetry/telemetry/core/extension_unittest.py162
-rw-r--r--chromium/tools/telemetry/telemetry/core/memory_cache_http_server.py192
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/__init__.py123
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/android_platform_backend.py134
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/cros_platform_backend.py75
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/desktop_platform_backend.py54
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/linux_platform_backend.py50
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/mac_platform_backend.py72
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/platform_backend.py59
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend.py51
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend_unittest.py34
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/proc_util.py65
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/__init__.py48
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/iprofiler_profiler.py100
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py72
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py128
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/perf_profiler_unittest.py31
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/profiler_finder.py27
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/sample_profiler.py90
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py251
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py125
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py111
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/testdata/perf.profilebin0 -> 157980 bytes
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py41
-rw-r--r--chromium/tools/telemetry/telemetry/core/platform/win_platform_backend.py167
-rw-r--r--chromium/tools/telemetry/telemetry/core/possible_browser.py30
-rw-r--r--chromium/tools/telemetry/telemetry/core/profile_creator.py13
-rw-r--r--chromium/tools/telemetry/telemetry/core/profile_types.py71
-rw-r--r--chromium/tools/telemetry/telemetry/core/profile_types_unittest.py32
-rw-r--r--chromium/tools/telemetry/telemetry/core/repeat_options.py61
-rw-r--r--chromium/tools/telemetry/telemetry/core/tab.py104
-rw-r--r--chromium/tools/telemetry/telemetry/core/tab_list.py18
-rw-r--r--chromium/tools/telemetry/telemetry/core/tab_unittest.py84
-rw-r--r--chromium/tools/telemetry/telemetry/core/temporary_http_server.py69
-rw-r--r--chromium/tools/telemetry/telemetry/core/temporary_http_server_unittest.py25
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/OWNERS2
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/__init__.py0
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/async_slice.py28
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/bounds.py71
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/counter.py82
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/event.py28
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/event_container.py15
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/event_unittest.py8
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/importer.py25
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/inspector_importer.py69
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/inspector_importer_unittest.py112
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/model.py128
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/model_unittest.py8
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/process.py72
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/sample.py19
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/slice.py52
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/slice_unittest.py26
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/thread.py207
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/trace_event_importer.py349
-rw-r--r--chromium/tools/telemetry/telemetry/core/timeline/trace_event_importer_unittest.py921
-rw-r--r--chromium/tools/telemetry/telemetry/core/user_agent.py28
-rw-r--r--chromium/tools/telemetry/telemetry/core/user_agent_unittest.py15
-rw-r--r--chromium/tools/telemetry/telemetry/core/util.py108
-rw-r--r--chromium/tools/telemetry/telemetry/core/util_unittest.py18
-rw-r--r--chromium/tools/telemetry/telemetry/core/web_contents.py73
-rw-r--r--chromium/tools/telemetry/telemetry/core/wpr_modes.py7
-rw-r--r--chromium/tools/telemetry/telemetry/core/wpr_server.py82
-rw-r--r--chromium/tools/telemetry/telemetry/page/__init__.py3
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/__init__.py0
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/all_page_actions.py21
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/click_element.py42
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/click_element_unittest.py46
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/js_collect_garbage.py11
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/media_action.js38
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/media_action.py46
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/page_action.py61
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/play.js42
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/play.py42
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/play_unittest.py108
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/reload.py14
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/scroll.js182
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/scroll.py82
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/scroll_unittest.py98
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/seek.js63
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/seek.py47
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/seek_unittest.py76
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/tap_element.py45
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/wait.py61
-rw-r--r--chromium/tools/telemetry/telemetry/page/actions/wait_unittest.py26
-rw-r--r--chromium/tools/telemetry/telemetry/page/block_page_measurement_results.py33
-rw-r--r--chromium/tools/telemetry/telemetry/page/block_page_measurement_results_unittest.py63
-rw-r--r--chromium/tools/telemetry/telemetry/page/buildbot_page_measurement_results.py119
-rw-r--r--chromium/tools/telemetry/telemetry/page/buildbot_page_measurement_results_unittest.py270
-rw-r--r--chromium/tools/telemetry/telemetry/page/cloud_storage.py128
-rw-r--r--chromium/tools/telemetry/telemetry/page/csv_page_measurement_results.py85
-rw-r--r--chromium/tools/telemetry/telemetry/page/csv_page_measurement_results_unittest.py127
-rw-r--r--chromium/tools/telemetry/telemetry/page/gtest_test_results.py75
-rw-r--r--chromium/tools/telemetry/telemetry/page/html_page_measurement_results.py112
-rw-r--r--chromium/tools/telemetry/telemetry/page/html_page_measurement_results_unittest.py203
-rw-r--r--chromium/tools/telemetry/telemetry/page/page.py140
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_filter.py41
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_measurement.py143
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_measurement_results.py112
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_measurement_results_unittest.py105
-rwxr-xr-xchromium/tools/telemetry/telemetry/page/page_measurement_runner.py26
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_measurement_unittest.py147
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_measurement_unittest_base.py48
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_measurement_value.py32
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_runner.py447
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_runner_repeat.py61
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_runner_unittest.py280
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_set.py122
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_set_archive_info.py145
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_set_archive_info_unittest.py161
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_set_unittest.py59
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_test.py220
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_test_results.py66
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_test_runner.py177
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_test_unittest.py117
-rw-r--r--chromium/tools/telemetry/telemetry/page/page_unittest.py141
-rw-r--r--chromium/tools/telemetry/telemetry/page/perf_tests_helper.py27
-rwxr-xr-xchromium/tools/telemetry/telemetry/page/record_wpr.py122
-rw-r--r--chromium/tools/telemetry/telemetry/page/test_expectations.py72
-rw-r--r--chromium/tools/telemetry/telemetry/page/test_expectations_unittest.py85
-rw-r--r--chromium/tools/telemetry/telemetry/test.py74
-rw-r--r--chromium/tools/telemetry/telemetry/test_runner.py162
-rw-r--r--chromium/tools/telemetry/telemetry/unittest/__init__.py12
-rwxr-xr-xchromium/tools/telemetry/telemetry/unittest/gtest_testrunner.py51
-rw-r--r--chromium/tools/telemetry/telemetry/unittest/options_for_unittests.py33
-rw-r--r--chromium/tools/telemetry/telemetry/unittest/run_tests.py142
-rw-r--r--chromium/tools/telemetry/telemetry/unittest/simple_mock.py98
-rw-r--r--chromium/tools/telemetry/telemetry/unittest/simple_mock_unittest.py84
-rw-r--r--chromium/tools/telemetry/telemetry/unittest/system_stub.py165
-rw-r--r--chromium/tools/telemetry/telemetry/unittest/tab_test_case.py44
-rw-r--r--chromium/tools/telemetry/third_party/davclient/README.chromium17
-rw-r--r--chromium/tools/telemetry/third_party/davclient/davclient.py312
-rw-r--r--chromium/tools/telemetry/third_party/png/README.chromium17
-rwxr-xr-xchromium/tools/telemetry/third_party/png/png.py3857
-rw-r--r--chromium/tools/telemetry/third_party/websocket-client/LICENSE506
-rw-r--r--chromium/tools/telemetry/third_party/websocket-client/README.chromium20
-rw-r--r--chromium/tools/telemetry/third_party/websocket-client/README.rst140
-rw-r--r--chromium/tools/telemetry/third_party/websocket-client/websocket.py756
-rw-r--r--chromium/tools/telemetry/unittest_data/bear.webmbin0 -> 219229 bytes
-rw-r--r--chromium/tools/telemetry/unittest_data/blank.html8
-rw-r--r--chromium/tools/telemetry/unittest_data/component_extension/background.js8
-rw-r--r--chromium/tools/telemetry/unittest_data/component_extension/manifest.json10
-rw-r--r--chromium/tools/telemetry/unittest_data/discoverable_classes/__init__.py3
-rw-r--r--chromium/tools/telemetry/unittest_data/discoverable_classes/discover_dummyclass.py8
-rw-r--r--chromium/tools/telemetry/unittest_data/discoverable_classes/dummy_profile_creator.py9
-rw-r--r--chromium/tools/telemetry/unittest_data/dom_counter_sample.html12
-rw-r--r--chromium/tools/telemetry/unittest_data/green_rect.html19
-rw-r--r--chromium/tools/telemetry/unittest_data/image.pngbin0 -> 10502 bytes
-rw-r--r--chromium/tools/telemetry/unittest_data/image_decoding.html8
-rw-r--r--chromium/tools/telemetry/unittest_data/non_scrollable_page.html10
-rw-r--r--chromium/tools/telemetry/unittest_data/page_that_logs_to_console.html14
-rw-r--r--chromium/tools/telemetry/unittest_data/page_with_link.html8
-rw-r--r--chromium/tools/telemetry/unittest_data/scrollable_page.html9
-rw-r--r--chromium/tools/telemetry/unittest_data/simple_extension/background.js8
-rw-r--r--chromium/tools/telemetry/unittest_data/simple_extension/manifest.json9
-rw-r--r--chromium/tools/telemetry/unittest_data/video_test.html7
-rwxr-xr-xchromium/tools/telemetry/update_docs11
-rw-r--r--chromium/tools/telemetry_tools/__init__.py4
-rw-r--r--chromium/tools/telemetry_tools/bootstrap_deps35
-rw-r--r--chromium/tools/telemetry_tools/telemetry_bootstrap.py162
-rw-r--r--chromium/tools/trace/trace.html287
-rw-r--r--chromium/tools/trace/trace_data.js1050
-rw-r--r--chromium/tools/traceline/svgui/README12
-rw-r--r--chromium/tools/traceline/svgui/startup-release.json178
-rw-r--r--chromium/tools/traceline/svgui/traceline.css73
-rw-r--r--chromium/tools/traceline/svgui/traceline.js693
-rw-r--r--chromium/tools/traceline/svgui/traceline.xml11
-rw-r--r--chromium/tools/traceline/traceline/Makefile30
-rw-r--r--chromium/tools/traceline/traceline/README21
-rw-r--r--chromium/tools/traceline/traceline/assembler.h576
-rw-r--r--chromium/tools/traceline/traceline/assembler_unittest.cc83
-rwxr-xr-xchromium/tools/traceline/traceline/assembler_unittest.sh7
-rw-r--r--chromium/tools/traceline/traceline/assembler_unittest.sh.expected54
-rwxr-xr-xchromium/tools/traceline/traceline/dump_syscalls_idarub.rb32
-rw-r--r--chromium/tools/traceline/traceline/logging.h28
-rw-r--r--chromium/tools/traceline/traceline/main.cc1339
-rw-r--r--chromium/tools/traceline/traceline/rdtsc.h43
-rw-r--r--chromium/tools/traceline/traceline/scripts/__init__.py0
-rwxr-xr-xchromium/tools/traceline/traceline/scripts/alloc.py27
-rw-r--r--chromium/tools/traceline/traceline/scripts/crit_sec.js87
-rwxr-xr-xchromium/tools/traceline/traceline/scripts/crit_sec.py57
-rwxr-xr-xchromium/tools/traceline/traceline/scripts/filter_short.py34
-rwxr-xr-xchromium/tools/traceline/traceline/scripts/filter_split.sh14
-rw-r--r--chromium/tools/traceline/traceline/scripts/heap.js69
-rwxr-xr-xchromium/tools/traceline/traceline/scripts/scstats.py32
-rwxr-xr-xchromium/tools/traceline/traceline/scripts/split.py31
-rw-r--r--chromium/tools/traceline/traceline/scripts/syscalls.py942
-rw-r--r--chromium/tools/traceline/traceline/sidestep/ia32_modrm_map.cc92
-rw-r--r--chromium/tools/traceline/traceline/sidestep/ia32_opcode_map.cc1159
-rw-r--r--chromium/tools/traceline/traceline/sidestep/mini_disassembler.cc416
-rw-r--r--chromium/tools/traceline/traceline/sidestep/mini_disassembler.h156
-rw-r--r--chromium/tools/traceline/traceline/sidestep/mini_disassembler_types.h197
-rw-r--r--chromium/tools/traceline/traceline/stubs.asm132
-rw-r--r--chromium/tools/traceline/traceline/sym_resolver.h167
-rw-r--r--chromium/tools/traceline/traceline/syscall_map.h2116
-rwxr-xr-xchromium/tools/unused-symbols-report.py171
-rwxr-xr-xchromium/tools/update_reference_build.py231
-rw-r--r--chromium/tools/usb_ids/usb_ids.py110
-rw-r--r--chromium/tools/valgrind/OWNERS5
-rwxr-xr-xchromium/tools/valgrind/asan/asan_symbolize.py24
-rwxr-xr-xchromium/tools/valgrind/asan/asan_wrapper.sh16
-rw-r--r--chromium/tools/valgrind/asan/third_party/README.chromium6
-rw-r--r--chromium/tools/valgrind/asan/third_party/__init__.py0
-rwxr-xr-xchromium/tools/valgrind/asan/third_party/asan_symbolize.py365
-rw-r--r--chromium/tools/valgrind/browser_wrapper_win.py49
-rwxr-xr-xchromium/tools/valgrind/chrome_tests.bat70
-rwxr-xr-xchromium/tools/valgrind/chrome_tests.py626
-rwxr-xr-xchromium/tools/valgrind/chrome_tests.sh122
-rw-r--r--chromium/tools/valgrind/common.py252
-rwxr-xr-xchromium/tools/valgrind/drmemory.bat5
-rw-r--r--chromium/tools/valgrind/drmemory/OWNERS1
-rw-r--r--chromium/tools/valgrind/drmemory/PRESUBMIT.py35
-rw-r--r--chromium/tools/valgrind/drmemory/suppressions.txt456
-rw-r--r--chromium/tools/valgrind/drmemory/suppressions_full.txt1323
-rwxr-xr-xchromium/tools/valgrind/drmemory_analyze.py196
-rw-r--r--chromium/tools/valgrind/gdb_helper.py87
-rw-r--r--chromium/tools/valgrind/gtest_exclude/OWNERS1
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt26
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan.txt10
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan_mac.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan_win32.txt23
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt26
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt18
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_win-8.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_win32.txt12
-rw-r--r--chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt50
-rw-r--r--chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-memcheck.txt60
-rw-r--r--chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-tsan.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/content_unittests.gtest.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt52
-rw-r--r--chromium/tools/valgrind/gtest_exclude/crypto_unittests.gtest-tsan_win32.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/interactive_ui_tests.gtest.txt34
-rw-r--r--chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest-drmemory_win32.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest-tsan_win32.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest.txt6
-rw-r--r--chromium/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory_win32.txt4
-rw-r--r--chromium/tools/valgrind/gtest_exclude/media_unittests.gtest-tsan_win32.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/media_unittests.gtest.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/message_center_unittests.gtest.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win-xp.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt24
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-memcheck.txt26
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan.txt27
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan_mac.txt11
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan_win32.txt40
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest.txt17
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest_linux.txt5
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest_mac.txt6
-rw-r--r--chromium/tools/valgrind/gtest_exclude/printing_unittests.gtest-drmemory_win32.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt9
-rw-r--r--chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-tsan_win32.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest_win-8.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/safe_browsing_tests.gtest_mac.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/suppressions.txt39
-rw-r--r--chromium/tools/valgrind/gtest_exclude/sync_unit_tests.gtest-asan.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/sync_unit_tests.gtest-tsan.txt5
-rw-r--r--chromium/tools/valgrind/gtest_exclude/ui_unittests.gtest-memcheck.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/ui_unittests.gtest-tsan.txt2
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win-xp.txt7
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt69
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt12
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-tsan.txt12
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-tsan_mac.txt5
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest.txt36
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt37
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest_mac.txt39
-rwxr-xr-xchromium/tools/valgrind/locate_valgrind.sh77
-rw-r--r--chromium/tools/valgrind/memcheck/OWNERS1
-rw-r--r--chromium/tools/valgrind/memcheck/PRESUBMIT.py81
-rw-r--r--chromium/tools/valgrind/memcheck/suppressions.txt7231
-rw-r--r--chromium/tools/valgrind/memcheck/suppressions_linux.txt35
-rw-r--r--chromium/tools/valgrind/memcheck/suppressions_mac.txt2597
-rwxr-xr-xchromium/tools/valgrind/memcheck_analyze.py634
-rwxr-xr-xchromium/tools/valgrind/regrind.sh138
-rw-r--r--chromium/tools/valgrind/reliability/url_list.txt11
-rwxr-xr-xchromium/tools/valgrind/scan-build.py227
-rwxr-xr-xchromium/tools/valgrind/shard-all-tests.sh128
-rwxr-xr-xchromium/tools/valgrind/suppressions.py1018
-rwxr-xr-xchromium/tools/valgrind/test_suppressions.py177
-rw-r--r--chromium/tools/valgrind/tsan/OWNERS1
-rw-r--r--chromium/tools/valgrind/tsan/PRESUBMIT.py35
-rw-r--r--chromium/tools/valgrind/tsan/ignores.txt188
-rw-r--r--chromium/tools/valgrind/tsan/ignores_mac.txt38
-rw-r--r--chromium/tools/valgrind/tsan/ignores_win32.txt64
-rw-r--r--chromium/tools/valgrind/tsan/suppressions.txt1138
-rw-r--r--chromium/tools/valgrind/tsan/suppressions_mac.txt270
-rw-r--r--chromium/tools/valgrind/tsan/suppressions_win32.txt225
-rwxr-xr-xchromium/tools/valgrind/tsan_analyze.py278
-rw-r--r--chromium/tools/valgrind/tsan_v2/ignores.txt16
-rw-r--r--chromium/tools/valgrind/tsan_v2/suppressions.txt121
-rwxr-xr-xchromium/tools/valgrind/unused_suppressions.py24
-rwxr-xr-xchromium/tools/valgrind/valgrind.sh124
-rw-r--r--chromium/tools/valgrind/valgrind_test.py1228
-rwxr-xr-xchromium/tools/valgrind/waterfall.sh222
-rw-r--r--chromium/tools/vim/chromium.ycm_extra_conf.py203
-rw-r--r--chromium/tools/vim/filetypes.vim9
-rw-r--r--chromium/tools/vim/ninja-build.vim129
-rw-r--r--chromium/tools/webrtc_perf_expectations/README13
-rw-r--r--chromium/tools/webrtc_perf_expectations/perf_expectations.json8
-rw-r--r--chromium/tools/webrtc_perf_expectations/webrtc_perf_expectations.cfg4
-rwxr-xr-xchromium/tools/win/copy-installer.bat134
-rwxr-xr-xchromium/tools/win/link_limiter/build_link_limiter.py99
-rw-r--r--chromium/tools/win/link_limiter/limiter.cc337
-rw-r--r--chromium/tools/win/sizeviewer/README.chromium2
-rwxr-xr-xchromium/tools/win/sizeviewer/code_tally.exebin0 -> 281088 bytes
-rw-r--r--chromium/tools/win/sizeviewer/sizeviewer.py95
-rw-r--r--chromium/tools/win/sizeviewer/template.html199
-rw-r--r--chromium/tools/win/split_link/check_installed.py46
-rw-r--r--chromium/tools/win/split_link/graph_dependencies.py89
-rw-r--r--chromium/tools/win/split_link/install_split_link.py100
-rw-r--r--chromium/tools/win/split_link/split_link.cc258
-rw-r--r--chromium/tools/win/split_link/split_link.py420
-rw-r--r--chromium/tools/win/split_link/viz.js/COPYING129
-rw-r--r--chromium/tools/win/split_link/viz.js/viz.js201588
-rwxr-xr-xchromium/tools/win/toolchain/7z/7z.dllbin0 -> 1422336 bytes
-rwxr-xr-xchromium/tools/win/toolchain/7z/7z.exebin0 -> 284160 bytes
-rw-r--r--chromium/tools/win/toolchain/7z/LICENSE57
-rw-r--r--chromium/tools/win/toolchain/toolchain.py711
-rw-r--r--chromium/tools/xdisplaycheck/xdisplaycheck.cc115
-rw-r--r--chromium/tools/xdisplaycheck/xdisplaycheck.gyp18
2086 files changed, 511614 insertions, 0 deletions
diff --git a/chromium/tools/DEPS b/chromium/tools/DEPS
new file mode 100644
index 00000000000..dc04e3dfc6b
--- /dev/null
+++ b/chromium/tools/DEPS
@@ -0,0 +1,6 @@
+# checkdeps.py shouldn't check include paths for files in these dirs:
+skip_child_includes = [
+ "clang",
+ "gyp",
+ "traceline",
+]
diff --git a/chromium/tools/OWNERS b/chromium/tools/OWNERS
new file mode 100644
index 00000000000..4cd808f0409
--- /dev/null
+++ b/chromium/tools/OWNERS
@@ -0,0 +1,3 @@
+*
+
+per-file bisect-builds.py=rsesek@chromium.org
diff --git a/chromium/tools/PRESUBMIT.py b/chromium/tools/PRESUBMIT.py
new file mode 100644
index 00000000000..01572314c06
--- /dev/null
+++ b/chromium/tools/PRESUBMIT.py
@@ -0,0 +1,48 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for bisect trybot.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+import imp
+
+def _ExamineBisectConfigFile(input_api, output_api):
+ for f in input_api.AffectedFiles():
+ if not f.LocalPath().endswith('run-bisect-perf-regression.cfg'):
+ continue
+
+ try:
+ cfg_file = imp.load_source('config', 'run-bisect-perf-regression.cfg')
+
+ for k, v in cfg_file.config.iteritems():
+ if v:
+ return f.LocalPath()
+ except (IOError, AttributeError, TypeError):
+ return f.LocalPath()
+
+ return None
+
+def _CheckNoChangesToBisectConfigFile(input_api, output_api):
+ results = _ExamineBisectConfigFile(input_api, output_api)
+ if results:
+ return [output_api.PresubmitError(
+ 'The bisection config file should only contain a config dict with '
+ 'empty fields. Changes to this file should never be submitted.',
+ items=[results])]
+
+ return []
+
+def CommonChecks(input_api, output_api):
+ results = []
+ results.extend(_CheckNoChangesToBisectConfigFile(input_api, output_api))
+ return results
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/chromium/tools/android/OWNERS b/chromium/tools/android/OWNERS
new file mode 100644
index 00000000000..e911c595c56
--- /dev/null
+++ b/chromium/tools/android/OWNERS
@@ -0,0 +1,6 @@
+bulach@chromium.org
+digit@chromium.org
+michaelbai@chromium.org
+pliard@chromium.org
+wangxianzhu@chromium.org
+yfriedman@chromium.org
diff --git a/chromium/tools/android/adb_reboot/adb_reboot.c b/chromium/tools/android/adb_reboot/adb_reboot.c
new file mode 100644
index 00000000000..48c5cbe58f2
--- /dev/null
+++ b/chromium/tools/android/adb_reboot/adb_reboot.c
@@ -0,0 +1,43 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+int main(int argc, char ** argv) {
+ int i = fork();
+ struct stat ft;
+ time_t ct;
+
+ if (i < 0) {
+ printf("fork error");
+ return 1;
+ }
+ if (i > 0)
+ return 0;
+
+ /* child (daemon) continues */
+ int j;
+ for (j = 0; j < getdtablesize(); j++)
+ close(j);
+
+ setsid(); /* obtain a new process group */
+
+ while (1) {
+ sleep(120);
+
+ stat("/sdcard/host_heartbeat", &ft);
+ time(&ct);
+ if (ct - ft.st_mtime > 120) {
+ /* File was not touched for some time. */
+ system("su -c reboot");
+ }
+ }
+
+ return 0;
+}
diff --git a/chromium/tools/android/adb_reboot/adb_reboot.gyp b/chromium/tools/android/adb_reboot/adb_reboot.gyp
new file mode 100644
index 00000000000..85134b9906a
--- /dev/null
+++ b/chromium/tools/android/adb_reboot/adb_reboot.gyp
@@ -0,0 +1,14 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'adb_reboot',
+ 'type': 'executable',
+ 'sources': [
+ 'adb_reboot.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/android/android_tools.gyp b/chromium/tools/android/android_tools.gyp
new file mode 100644
index 00000000000..c38cd70d58a
--- /dev/null
+++ b/chromium/tools/android/android_tools.gyp
@@ -0,0 +1,27 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Intermediate target grouping the android tools needed to run native
+ # unittests and instrumentation test apks.
+ {
+ 'target_name': 'android_tools',
+ 'type': 'none',
+ 'dependencies': [
+ 'fake_dns/fake_dns.gyp:fake_dns',
+ 'forwarder2/forwarder.gyp:forwarder2',
+ 'md5sum/md5sum.gyp:md5sum',
+ 'adb_reboot/adb_reboot.gyp:adb_reboot',
+ ],
+ },
+ {
+ 'target_name': 'memdump',
+ 'type': 'none',
+ 'dependencies': [
+ 'memdump/memdump.gyp:memdump',
+ ],
+ }
+ ],
+}
diff --git a/chromium/tools/android/asan/asanwrapper.sh b/chromium/tools/android/asan/asanwrapper.sh
new file mode 100755
index 00000000000..2392d2ca44e
--- /dev/null
+++ b/chromium/tools/android/asan/asanwrapper.sh
@@ -0,0 +1,9 @@
+#!/system/bin/sh
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+ASAN_OPTIONS=debug=1,verbosity=1,strict_memcmp=0 \
+LD_LIBRARY_PATH=/data/local/tmp/asan:$LD_LIBRARY_PATH \
+LD_PRELOAD=libclang_rt.asan-arm-android.so \
+exec $@
diff --git a/chromium/tools/android/common/adb_connection.cc b/chromium/tools/android/common/adb_connection.cc
new file mode 100644
index 00000000000..91c25fed20c
--- /dev/null
+++ b/chromium/tools/android/common/adb_connection.cc
@@ -0,0 +1,107 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/common/adb_connection.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "tools/android/common/net.h"
+
+namespace tools {
+namespace {
+
+void CloseSocket(int fd) {
+ if (fd >= 0) {
+ int old_errno = errno;
+ (void) HANDLE_EINTR(close(fd));
+ errno = old_errno;
+ }
+}
+
+} // namespace
+
+int ConnectAdbHostSocket(const char* forward_to) {
+ // ADB port forward request format: HHHHtcp:port:address.
+ // HHHH is the hexidecimal length of the "tcp:port:address" part.
+ const size_t kBufferMaxLength = 30;
+ const size_t kLengthOfLength = 4;
+ const size_t kAddressMaxLength = kBufferMaxLength - kLengthOfLength;
+
+ const char kAddressPrefix[] = { 't', 'c', 'p', ':' };
+ size_t address_length = arraysize(kAddressPrefix) + strlen(forward_to);
+ if (address_length > kBufferMaxLength - kLengthOfLength) {
+ LOG(ERROR) << "Forward to address is too long: " << forward_to;
+ return -1;
+ }
+
+ char request[kBufferMaxLength];
+ memcpy(request + kLengthOfLength, kAddressPrefix, arraysize(kAddressPrefix));
+ memcpy(request + kLengthOfLength + arraysize(kAddressPrefix),
+ forward_to, strlen(forward_to));
+
+ char length_buffer[kLengthOfLength + 1];
+ snprintf(length_buffer, arraysize(length_buffer), "%04X",
+ static_cast<int>(address_length));
+ memcpy(request, length_buffer, kLengthOfLength);
+
+ int host_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (host_socket < 0) {
+ LOG(ERROR) << "Failed to create adb socket: " << strerror(errno);
+ return -1;
+ }
+
+ DisableNagle(host_socket);
+
+ const int kAdbPort = 5037;
+ sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_port = htons(kAdbPort);
+ if (HANDLE_EINTR(connect(host_socket, reinterpret_cast<sockaddr*>(&addr),
+ sizeof(addr))) < 0) {
+ LOG(ERROR) << "Failed to connect adb socket: " << strerror(errno);
+ CloseSocket(host_socket);
+ return -1;
+ }
+
+ size_t bytes_remaining = address_length + kLengthOfLength;
+ size_t bytes_sent = 0;
+ while (bytes_remaining > 0) {
+ int ret = HANDLE_EINTR(send(host_socket, request + bytes_sent,
+ bytes_remaining, 0));
+ if (ret < 0) {
+ LOG(ERROR) << "Failed to send request: " << strerror(errno);
+ CloseSocket(host_socket);
+ return -1;
+ }
+
+ bytes_sent += ret;
+ bytes_remaining -= ret;
+ }
+
+ const size_t kAdbStatusLength = 4;
+ char response[kBufferMaxLength];
+ int response_length = HANDLE_EINTR(recv(host_socket, response,
+ kBufferMaxLength, 0));
+ if (response_length < kAdbStatusLength ||
+ strncmp("OKAY", response, kAdbStatusLength) != 0) {
+ LOG(ERROR) << "Bad response from ADB: length: " << response_length
+ << " data: " << DumpBinary(response, response_length);
+ CloseSocket(host_socket);
+ return -1;
+ }
+
+ return host_socket;
+}
+
+} // namespace tools
diff --git a/chromium/tools/android/common/adb_connection.h b/chromium/tools/android/common/adb_connection.h
new file mode 100644
index 00000000000..3fa0fb396f5
--- /dev/null
+++ b/chromium/tools/android/common/adb_connection.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_COMMON_ADB_CONNECTION_H_
+#define TOOLS_ANDROID_COMMON_ADB_CONNECTION_H_
+
+namespace tools {
+
+// Creates a socket that can forward to a host socket through ADB.
+// The format of forward_to is <port>:<ip_address>.
+// Returns the socket handle, or -1 on any error.
+int ConnectAdbHostSocket(const char* forward_to);
+
+} // namespace tools
+
+#endif // TOOLS_ANDROID_COMMON_ADB_CONNECTION_H_
+
diff --git a/chromium/tools/android/common/common.gyp b/chromium/tools/android/common/common.gyp
new file mode 100644
index 00000000000..86226258446
--- /dev/null
+++ b/chromium/tools/android/common/common.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'android_tools_common',
+ 'type': 'static_library',
+ 'toolsets': ['host', 'target'],
+ 'include_dirs': [
+ '..',
+ '../../..',
+ ],
+ 'sources': [
+ 'adb_connection.cc',
+ 'adb_connection.h',
+ 'daemon.cc',
+ 'daemon.h',
+ 'net.cc',
+ 'net.h',
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/android/common/daemon.cc b/chromium/tools/android/common/daemon.cc
new file mode 100644
index 00000000000..9eafdbce052
--- /dev/null
+++ b/chromium/tools/android/common/daemon.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/common/daemon.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+
+namespace {
+
+const char kNoSpawnDaemon[] = "D";
+
+int g_exit_status = 0;
+
+void Exit(int unused) {
+ _exit(g_exit_status);
+}
+
+void CloseFileDescriptor(int fd) {
+ int old_errno = errno;
+ (void) HANDLE_EINTR(close(fd));
+ errno = old_errno;
+}
+
+} // namespace
+
+namespace tools {
+
+bool HasHelpSwitch(const CommandLine& command_line) {
+ return command_line.HasSwitch("h") || command_line.HasSwitch("help");
+}
+
+bool HasNoSpawnDaemonSwitch(const CommandLine& command_line) {
+ return command_line.HasSwitch(kNoSpawnDaemon);
+}
+
+void ShowHelp(const char* program,
+ const char* extra_title,
+ const char* extra_descriptions) {
+ printf("Usage: %s [-%s] %s\n"
+ " -%s stops from spawning a daemon process\n%s",
+ program, kNoSpawnDaemon, extra_title, kNoSpawnDaemon,
+ extra_descriptions);
+}
+
+void SpawnDaemon(int exit_status) {
+ g_exit_status = exit_status;
+ signal(SIGUSR1, Exit);
+
+ if (fork()) {
+ // In parent process.
+ sleep(10); // Wait for the child process to finish setsid().
+ NOTREACHED();
+ }
+
+ // In child process.
+ setsid(); // Detach the child process from its parent.
+ kill(getppid(), SIGUSR1); // Inform the parent process to exit.
+
+ // Close the standard input and outputs, otherwise the process may block
+ // adbd when the shell exits.
+ // Comment out these lines if you want to see outputs for debugging.
+ CloseFileDescriptor(0);
+ CloseFileDescriptor(1);
+ CloseFileDescriptor(2);
+}
+
+} // namespace tools
diff --git a/chromium/tools/android/common/daemon.h b/chromium/tools/android/common/daemon.h
new file mode 100644
index 00000000000..0c1640107d7
--- /dev/null
+++ b/chromium/tools/android/common/daemon.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_COMMON_DAEMON_H_
+#define TOOLS_ANDROID_COMMON_DAEMON_H_
+
+class CommandLine;
+
+namespace tools {
+
+bool HasHelpSwitch(const CommandLine& command_line);
+
+bool HasNoSpawnDaemonSwitch(const CommandLine& command_line);
+
+void ShowHelp(const char* program,
+ const char* extra_title,
+ const char* extra_descriptions);
+
+// Spawns a daemon process and exits the current process with exit_status.
+// Any code executed after this function returns will be executed in the
+// spawned daemon process.
+void SpawnDaemon(int exit_status);
+
+} // namespace tools
+
+#endif // TOOLS_ANDROID_COMMON_DAEMON_H_
+
diff --git a/chromium/tools/android/common/net.cc b/chromium/tools/android/common/net.cc
new file mode 100644
index 00000000000..3b9ef15bc39
--- /dev/null
+++ b/chromium/tools/android/common/net.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/common/net.h"
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include "base/strings/stringprintf.h"
+
+namespace tools {
+
+int DisableNagle(int socket) {
+ int on = 1;
+ return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+}
+
+int DeferAccept(int socket) {
+ int on = 1;
+ return setsockopt(socket, IPPROTO_TCP, TCP_DEFER_ACCEPT, &on, sizeof(on));
+}
+
+std::string DumpBinary(const char* buffer, size_t length) {
+ std::string result = "[";
+ for (int i = 0; i < length; ++i) {
+ base::StringAppendF(&result, "%02x,",
+ static_cast<unsigned char>(buffer[i]));
+ }
+
+ if (length)
+ result.erase(result.length() - 1);
+
+ return result + "]";
+}
+
+} // namespace tools
+
diff --git a/chromium/tools/android/common/net.h b/chromium/tools/android/common/net.h
new file mode 100644
index 00000000000..e3619548abb
--- /dev/null
+++ b/chromium/tools/android/common/net.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_COMMON_NET_H_
+#define TOOLS_ANDROID_COMMON_NET_H_
+
+#include <string>
+
+namespace tools {
+
+// DisableNagle can improve TCP transmission performance. Both Chrome net stack
+// and adb tool use it.
+int DisableNagle(int socket);
+
+// Wake up listener only when data arrive.
+int DeferAccept(int socket);
+
+// Dumps a binary buffer into a string in a human-readable format.
+std::string DumpBinary(const char* buffer, size_t length);
+
+} // namespace tools
+
+#endif // TOOLS_ANDROID_COMMON_NET_H_
+
diff --git a/chromium/tools/android/device_stats_monitor/device_stats_monitor.cc b/chromium/tools/android/device_stats_monitor/device_stats_monitor.cc
new file mode 100644
index 00000000000..6388cdaf436
--- /dev/null
+++ b/chromium/tools/android/device_stats_monitor/device_stats_monitor.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Dumps CPU and IO stats to a file at a regular interval.
+//
+// Output may be post processed by host to get top/iotop style information.
+
+#include <signal.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/strings/string_split.h"
+
+namespace {
+
+const char kIOStatsPath[] = "/proc/diskstats";
+const char kCPUStatsPath[] = "/proc/stat";
+
+class DeviceStatsMonitor {
+ public:
+ explicit DeviceStatsMonitor(const std::string& out_path)
+ : out_path_(out_path),
+ record_(true) {
+ CHECK(!out_path_.empty());
+ samples_.reserve(1024 * 1024);
+ }
+
+ // Records stats continuously at |hz| cycles per second util
+ // StopRecordingAndDumpStats() is called.
+ //
+ // Yes, this buffers everything in memory, so it cannot be used for extended
+ // durations without OOM. But that beats writing during the trace which
+ // would affect the results.
+ void Start(int hz) {
+ const int sample_interval = 1000000 / hz;
+ const base::FilePath io_stats_path(kIOStatsPath);
+ const base::FilePath cpu_stats_path(kCPUStatsPath);
+ std::string out;
+ while (record_) {
+ out.clear();
+ CHECK(file_util::ReadFileToString(io_stats_path, &out));
+ CHECK(file_util::ReadFileToString(cpu_stats_path, &out));
+ samples_.push_back(out);
+ usleep(sample_interval);
+ }
+ }
+
+ // Stops recording and saves samples to file.
+ void StopAndDumpStats() {
+ record_ = false;
+ usleep(250 * 1000);
+ std::ofstream out_stream;
+ out_stream.open(out_path_.value().c_str(), std::ios::out);
+ for (std::vector<std::string>::const_iterator i = samples_.begin();
+ i != samples_.end(); ++i) {
+ out_stream << i->c_str() << std::endl;
+ }
+ out_stream.close();
+ }
+
+ private:
+ const base::FilePath out_path_;
+ std::vector<std::string> samples_;
+ bool record_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceStatsMonitor);
+};
+
+DeviceStatsMonitor* g_device_stats_monitor = NULL;
+
+void SigTermHandler(int unused) {
+ printf("Stopping device stats monitor\n");
+ g_device_stats_monitor->StopAndDumpStats();
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ const int kDefaultHz = 20;
+
+ CommandLine command_line(argc, argv);
+ CommandLine::StringVector args = command_line.GetArgs();
+ if (command_line.HasSwitch("h") || command_line.HasSwitch("help") ||
+ args.size() != 1) {
+ printf("Usage: %s OUTPUT_FILE\n"
+ " --hz=HZ Number of samples/second. default=%d\n",
+ argv[0], kDefaultHz);
+ return 1;
+ }
+
+ int hz = command_line.HasSwitch("hz") ?
+ atoi(command_line.GetSwitchValueNative("hz").c_str()) :
+ kDefaultHz;
+
+ printf("Starting device stats monitor\n");
+ g_device_stats_monitor = new DeviceStatsMonitor(args[0]);
+ signal(SIGTERM, SigTermHandler);
+ g_device_stats_monitor->Start(hz);
+ delete g_device_stats_monitor;
+
+ return 0;
+}
diff --git a/chromium/tools/android/device_stats_monitor/device_stats_monitor.gyp b/chromium/tools/android/device_stats_monitor/device_stats_monitor.gyp
new file mode 100644
index 00000000000..f9bd9e8e4bb
--- /dev/null
+++ b/chromium/tools/android/device_stats_monitor/device_stats_monitor.gyp
@@ -0,0 +1,41 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'device_stats_monitor',
+ 'type': 'none',
+ 'dependencies': [
+ 'device_stats_monitor_symbols',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'strip_device_stats_monitor',
+ 'inputs': ['<(PRODUCT_DIR)/device_stats_monitor_symbols'],
+ 'outputs': ['<(PRODUCT_DIR)/device_stats_monitor'],
+ 'action': [
+ '<(android_strip)',
+ '--strip-unneeded',
+ '<@(_inputs)',
+ '-o',
+ '<@(_outputs)',
+ ],
+ },
+ ],
+ }, {
+ 'target_name': 'device_stats_monitor_symbols',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ 'sources': [
+ 'device_stats_monitor.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/android/fake_dns/DEPS b/chromium/tools/android/fake_dns/DEPS
new file mode 100644
index 00000000000..8fa9d48d882
--- /dev/null
+++ b/chromium/tools/android/fake_dns/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+net",
+]
diff --git a/chromium/tools/android/fake_dns/fake_dns.cc b/chromium/tools/android/fake_dns/fake_dns.cc
new file mode 100644
index 00000000000..9a055bfd376
--- /dev/null
+++ b/chromium/tools/android/fake_dns/fake_dns.cc
@@ -0,0 +1,238 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/safe_strerror_posix.h"
+#include "net/base/big_endian.h"
+#include "net/base/net_util.h"
+#include "net/dns/dns_protocol.h"
+#include "tools/android/common/daemon.h"
+#include "tools/android/common/net.h"
+
+namespace {
+
+// Mininum request size: 1 question containing 1 QNAME, 1 TYPE and 1 CLASS.
+const size_t kMinRequestSize = sizeof(net::dns_protocol::Header) + 6;
+
+// The name reference in the answer pointing to the name in the query.
+// Its format is: highest two bits set to 1, then the offset of the name
+// which just follows the header.
+const uint16 kPointerToQueryName =
+ static_cast<uint16>(0xc000 | sizeof(net::dns_protocol::Header));
+
+const uint32 kTTL = 86400; // One day.
+
+void PError(const char* msg) {
+ int current_errno = errno;
+ LOG(ERROR) << "ERROR: " << msg << ": " << safe_strerror(current_errno);
+}
+
+void SendTo(int sockfd, const void* buf, size_t len, int flags,
+ const sockaddr* dest_addr, socklen_t addrlen) {
+ if (HANDLE_EINTR(sendto(sockfd, buf, len, flags, dest_addr, addrlen)) == -1)
+ PError("sendto()");
+}
+
+void CloseFileDescriptor(int fd) {
+ int old_errno = errno;
+ (void) HANDLE_EINTR(close(fd));
+ errno = old_errno;
+}
+
+void SendRefusedResponse(int sock, const sockaddr_in& client_addr, uint16 id) {
+ net::dns_protocol::Header response;
+ response.id = htons(id);
+ response.flags = htons(net::dns_protocol::kFlagResponse |
+ net::dns_protocol::kFlagAA |
+ net::dns_protocol::kFlagRD |
+ net::dns_protocol::kFlagRA |
+ net::dns_protocol::kRcodeREFUSED);
+ response.qdcount = 0;
+ response.ancount = 0;
+ response.nscount = 0;
+ response.arcount = 0;
+ SendTo(sock, &response, sizeof(response), 0,
+ reinterpret_cast<const sockaddr*>(&client_addr), sizeof(client_addr));
+}
+
+void SendResponse(int sock, const sockaddr_in& client_addr, uint16 id,
+ uint16 qtype, const char* question, size_t question_length) {
+ net::dns_protocol::Header header;
+ header.id = htons(id);
+ header.flags = htons(net::dns_protocol::kFlagResponse |
+ net::dns_protocol::kFlagAA |
+ net::dns_protocol::kFlagRD |
+ net::dns_protocol::kFlagRA |
+ net::dns_protocol::kRcodeNOERROR);
+ header.qdcount = htons(1);
+ header.ancount = htons(1);
+ header.nscount = 0;
+ header.arcount = 0;
+
+ // Size of RDATA which is a IPv4 or IPv6 address.
+ size_t rdata_size = qtype == net::dns_protocol::kTypeA ?
+ net::kIPv4AddressSize : net::kIPv6AddressSize;
+
+ // Size of the whole response which contains the header, the question and
+ // the answer. 12 is the sum of sizes of the compressed name reference, TYPE,
+ // CLASS, TTL and RDLENGTH.
+ size_t response_size = sizeof(header) + question_length + 12 + rdata_size;
+
+ if (response_size > net::dns_protocol::kMaxUDPSize) {
+ LOG(ERROR) << "Response is too large: " << response_size;
+ SendRefusedResponse(sock, client_addr, id);
+ return;
+ }
+
+ char response[net::dns_protocol::kMaxUDPSize];
+ net::BigEndianWriter writer(response, arraysize(response));
+ writer.WriteBytes(&header, sizeof(header));
+
+ // Repeat the question in the response. Some clients (e.g. ping) needs this.
+ writer.WriteBytes(question, question_length);
+
+ // Construct the answer.
+ writer.WriteU16(kPointerToQueryName);
+ writer.WriteU16(qtype);
+ writer.WriteU16(net::dns_protocol::kClassIN);
+ writer.WriteU32(kTTL);
+ writer.WriteU16(rdata_size);
+ if (qtype == net::dns_protocol::kTypeA)
+ writer.WriteU32(INADDR_LOOPBACK);
+ else
+ writer.WriteBytes(&in6addr_loopback, sizeof(in6_addr));
+ DCHECK(writer.ptr() - response == response_size);
+
+ SendTo(sock, response, response_size, 0,
+ reinterpret_cast<const sockaddr*>(&client_addr), sizeof(client_addr));
+}
+
+void HandleRequest(int sock, const char* request, size_t size,
+ const sockaddr_in& client_addr) {
+ if (size < kMinRequestSize) {
+ LOG(ERROR) << "Request is too small " << size
+ << "\n" << tools::DumpBinary(request, size);
+ return;
+ }
+
+ net::BigEndianReader reader(request, size);
+ net::dns_protocol::Header header;
+ reader.ReadBytes(&header, sizeof(header));
+ uint16 id = ntohs(header.id);
+ uint16 flags = ntohs(header.flags);
+ uint16 qdcount = ntohs(header.qdcount);
+ uint16 ancount = ntohs(header.ancount);
+ uint16 nscount = ntohs(header.nscount);
+ uint16 arcount = ntohs(header.arcount);
+
+ const uint16 kAllowedFlags = 0x07ff;
+ if ((flags & ~kAllowedFlags) ||
+ qdcount != 1 || ancount || nscount || arcount) {
+ LOG(ERROR) << "Unsupported request: FLAGS=" << flags
+ << " QDCOUNT=" << qdcount
+ << " ANCOUNT=" << ancount
+ << " NSCOUNT=" << nscount
+ << " ARCOUNT=" << arcount
+ << "\n" << tools::DumpBinary(request, size);
+ SendRefusedResponse(sock, client_addr, id);
+ return;
+ }
+
+ // request[size - 5] should be the end of the QNAME (a zero byte).
+ // We don't care about the validity of QNAME because we don't parse it.
+ const char* qname_end = &request[size - 5];
+ if (*qname_end) {
+ LOG(ERROR) << "Error parsing QNAME\n" << tools::DumpBinary(request, size);
+ SendRefusedResponse(sock, client_addr, id);
+ return;
+ }
+
+ reader.Skip(qname_end - reader.ptr() + 1);
+
+ uint16 qtype;
+ uint16 qclass;
+ reader.ReadU16(&qtype);
+ reader.ReadU16(&qclass);
+ if ((qtype != net::dns_protocol::kTypeA &&
+ qtype != net::dns_protocol::kTypeAAAA) ||
+ qclass != net::dns_protocol::kClassIN) {
+ LOG(ERROR) << "Unsupported query: QTYPE=" << qtype << " QCLASS=" << qclass
+ << "\n" << tools::DumpBinary(request, size);
+ SendRefusedResponse(sock, client_addr, id);
+ return;
+ }
+
+ SendResponse(sock, client_addr, id, qtype,
+ request + sizeof(header), size - sizeof(header));
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ printf("Fake DNS server\n");
+
+ CommandLine command_line(argc, argv);
+ if (tools::HasHelpSwitch(command_line) || command_line.GetArgs().size()) {
+ tools::ShowHelp(argv[0], "", "");
+ return 0;
+ }
+
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ PError("create socket");
+ return 1;
+ }
+
+ sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_port = htons(53);
+ int reuse_addr = 1;
+ if (HANDLE_EINTR(bind(sock, reinterpret_cast<sockaddr*>(&addr),
+ sizeof(addr))) < 0) {
+ PError("server bind");
+ CloseFileDescriptor(sock);
+ return 1;
+ }
+
+ if (!tools::HasNoSpawnDaemonSwitch(command_line))
+ tools::SpawnDaemon(0);
+
+ while (true) {
+ sockaddr_in client_addr;
+ socklen_t client_addr_len = sizeof(client_addr);
+ char request[net::dns_protocol::kMaxUDPSize];
+ int size = HANDLE_EINTR(recvfrom(sock, request, sizeof(request),
+ MSG_WAITALL,
+ reinterpret_cast<sockaddr*>(&client_addr),
+ &client_addr_len));
+ if (size < 0) {
+ // Unrecoverable error, can only exit.
+ LOG(ERROR) << "Failed to receive a request: " << strerror(errno);
+ CloseFileDescriptor(sock);
+ return 1;
+ }
+
+ if (size > 0)
+ HandleRequest(sock, request, size, client_addr);
+ }
+}
+
diff --git a/chromium/tools/android/fake_dns/fake_dns.gyp b/chromium/tools/android/fake_dns/fake_dns.gyp
new file mode 100644
index 00000000000..0edacfadf07
--- /dev/null
+++ b/chromium/tools/android/fake_dns/fake_dns.gyp
@@ -0,0 +1,44 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'fake_dns',
+ 'type': 'none',
+ 'dependencies': [
+ 'fake_dns_symbols',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'strip_fake_dns',
+ 'inputs': ['<(PRODUCT_DIR)/fake_dns_symbols'],
+ 'outputs': ['<(PRODUCT_DIR)/fake_dns'],
+ 'action': [
+ '<(android_strip)',
+ '--strip-unneeded',
+ '<@(_inputs)',
+ '-o',
+ '<@(_outputs)',
+ ],
+ },
+ ],
+ }, {
+ 'target_name': 'fake_dns_symbols',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../net/net.gyp:net',
+ '../common/common.gyp:android_tools_common',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ 'sources': [
+ 'fake_dns.cc',
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/android/find_unused_resources.py b/chromium/tools/android/find_unused_resources.py
new file mode 100755
index 00000000000..da86e734152
--- /dev/null
+++ b/chromium/tools/android/find_unused_resources.py
@@ -0,0 +1,126 @@
+#!/usr/bin/python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Lists unused Java strings and other resources."""
+
+import optparse
+import re
+import subprocess
+import sys
+
+
+def GetApkResources(apk_path):
+ """Returns the types and names of resources packaged in an APK.
+
+ Args:
+ apk_path: path to the APK.
+
+ Returns:
+ The resources in the APK as a list of tuples (type, name). Example:
+ [('drawable', 'arrow'), ('layout', 'month_picker'), ...]
+ """
+ p = subprocess.Popen(
+ ['aapt', 'dump', 'resources', apk_path],
+ stdout=subprocess.PIPE)
+ dump_out, _ = p.communicate()
+ assert p.returncode == 0, 'aapt dump failed'
+ matches = re.finditer(
+ r'^\s+spec resource 0x[0-9a-fA-F]+ [\w.]+:(?P<type>\w+)/(?P<name>\w+)',
+ dump_out, re.MULTILINE)
+ return [m.group('type', 'name') for m in matches]
+
+
+def GetUsedResources(source_paths, resource_types):
+ """Returns the types and names of resources used in Java or resource files.
+
+ Args:
+ source_paths: a list of files or folders collectively containing all the
+ Java files, resource files, and the AndroidManifest.xml.
+ resource_types: a list of resource types to look for. Example:
+ ['string', 'drawable']
+
+ Returns:
+ The resources referenced by the Java and resource files as a list of tuples
+ (type, name). Example:
+ [('drawable', 'app_icon'), ('layout', 'month_picker'), ...]
+ """
+ type_regex = '|'.join(map(re.escape, resource_types))
+ patterns = [r'@(())(%s)/(\w+)' % type_regex,
+ r'\b((\w+\.)*)R\.(%s)\.(\w+)' % type_regex]
+ resources = []
+ for pattern in patterns:
+ p = subprocess.Popen(
+ ['grep', '-REIhoe', pattern] + source_paths,
+ stdout=subprocess.PIPE)
+ grep_out, grep_err = p.communicate()
+ # Check stderr instead of return code, since return code is 1 when no
+ # matches are found.
+ assert not grep_err, 'grep failed'
+ matches = re.finditer(pattern, grep_out)
+ for match in matches:
+ package = match.group(1)
+ if package == 'android.':
+ continue
+ type_ = match.group(3)
+ name = match.group(4)
+ resources.append((type_, name))
+ return resources
+
+
+def FormatResources(resources):
+ """Formats a list of resources for printing.
+
+ Args:
+ resources: a list of resources, given as (type, name) tuples.
+ """
+ return '\n'.join(['%-12s %s' % (t, n) for t, n in sorted(resources)])
+
+
+def ParseArgs(args):
+ usage = 'usage: %prog [-v] APK_PATH SOURCE_PATH...'
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option('-v', help='Show verbose output', action='store_true')
+ options, args = parser.parse_args(args=args)
+ if len(args) < 2:
+ parser.error('must provide APK_PATH and SOURCE_PATH arguments')
+ return options.v, args[0], args[1:]
+
+
+def main(args=None):
+ verbose, apk_path, source_paths = ParseArgs(args)
+ apk_resources = GetApkResources(apk_path)
+ resource_types = list(set([r[0] for r in apk_resources]))
+ used_resources = GetUsedResources(source_paths, resource_types)
+ unused_resources = set(apk_resources) - set(used_resources)
+ undefined_resources = set(used_resources) - set(apk_resources)
+
+ # aapt dump fails silently. Notify the user if things look wrong.
+ if not apk_resources:
+ print >> sys.stderr, (
+ 'Warning: No resources found in the APK. Did you provide the correct '
+ 'APK path?')
+ if not used_resources:
+ print >> sys.stderr, (
+ 'Warning: No resources references from Java or resource files. Did you '
+ 'provide the correct source paths?')
+ if undefined_resources:
+ print >> sys.stderr, (
+ 'Warning: found %d "undefined" resources that are referenced by Java '
+ 'files or by other resources, but are not in the APK. Run with -v to '
+ 'see them.' % len(undefined_resources))
+
+ if verbose:
+ print '%d undefined resources:' % len(undefined_resources)
+ print FormatResources(undefined_resources), '\n'
+ print '%d resources packaged into the APK:' % len(apk_resources)
+ print FormatResources(apk_resources), '\n'
+ print '%d used resources:' % len(used_resources)
+ print FormatResources(used_resources), '\n'
+ print '%d unused resources:' % len(unused_resources)
+ print FormatResources(unused_resources)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/android/findbugs_plugin/README b/chromium/tools/android/findbugs_plugin/README
new file mode 100644
index 00000000000..3ba3f53085b
--- /dev/null
+++ b/chromium/tools/android/findbugs_plugin/README
@@ -0,0 +1,15 @@
+This is the FindBugs plugin for chrome on android.
+
+Currently it detects:
+- synchronized method
+- synchronized 'this'
+
+We don't want the synchronized method and synchronized 'this' to be
+used, the exception is the synchronized method defined in Android
+API.
+
+The plugin jar file was prebuilt and checked in, to rebuild the
+plugin, you need ant, and run below command, the new jar file will
+be in lib directory.
+
+ant install
diff --git a/chromium/tools/android/findbugs_plugin/build.xml b/chromium/tools/android/findbugs_plugin/build.xml
new file mode 100644
index 00000000000..09ee13c41fd
--- /dev/null
+++ b/chromium/tools/android/findbugs_plugin/build.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<project name="findbugs_plugin" basedir=".">
+
+ <description>
+ Build findbugs_plugin for Chromium Android
+ </description>
+ <property name="src.dir" location="src" />
+ <property name="lib.dir" location="../../../third_party/findbugs/lib" />
+ <property name="bin.dir" location="lib" />
+ <property name="intermediate.dir" location="intermediate" />
+ <property name="jar.name" value="chromiumPlugin.jar" />
+
+ <path id="classpath.id">
+ <fileset dir="${lib.dir}">
+ <include name="**/*.jar" />
+ </fileset>
+ </path>
+
+ <target name="makedir">
+ <mkdir dir="${intermediate.dir}" />
+ <mkdir dir="${bin.dir}" />
+ </target>
+
+ <target name="findbugs_plugin_classes" depends="makedir">
+ <javac srcdir="${src.dir}" destdir="${intermediate.dir}"
+ classpathref="classpath.id" includeantruntime="false" />
+ </target>
+
+ <target name="copy_xml_files" depends="makedir">
+ <copy file="messages.xml" todir="${intermediate.dir}" />
+ <copy file="findbugs.xml" todir="${intermediate.dir}" />
+ </target>
+
+ <target name="findbugs_plugin_jar" depends="findbugs_plugin_classes, copy_xml_files">
+ <jar destfile="${bin.dir}/${jar.name}" basedir="${intermediate.dir}">
+ </jar>
+ </target>
+
+ <target name="install" depends="findbugs_plugin_jar">
+ <delete dir="${intermediate.dir}" />
+ </target>
+</project>
diff --git a/chromium/tools/android/findbugs_plugin/findbugs.xml b/chromium/tools/android/findbugs_plugin/findbugs.xml
new file mode 100644
index 00000000000..43b1f3417dc
--- /dev/null
+++ b/chromium/tools/android/findbugs_plugin/findbugs.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<FindbugsPlugin xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="findbugsplugin.xsd"
+ pluginid="SynchronizedThisDetector"
+ provider="chromium"
+ website="http://code.google.com/p/chromium/wiki/UseFindBugsForAndroid">
+ <Detector class="org.chromium.tools.findbugs.plugin.SynchronizedThisDetector" reports="CHROMIUM_SYNCHRONIZED_THIS" />
+ <BugPattern type="CHROMIUM_SYNCHRONIZED_THIS" abbrev="CST" category="CORRECTNESS"/>
+
+ <Detector class="org.chromium.tools.findbugs.plugin.SynchronizedMethodDetector" reports="CHROMIUM_SYNCHRONIZED_METHOD" />
+ <BugPattern type="CHROMIUM_SYNCHRONIZED_METHOD" abbrev="CSM" category="CORRECTNESS"/>
+</FindbugsPlugin>
diff --git a/chromium/tools/android/findbugs_plugin/findbugs_plugin.gyp b/chromium/tools/android/findbugs_plugin/findbugs_plugin.gyp
new file mode 100644
index 00000000000..16d06e6c254
--- /dev/null
+++ b/chromium/tools/android/findbugs_plugin/findbugs_plugin.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'findbugs_plugin_test',
+ 'type': 'none',
+ 'variables': {
+ 'java_in_dir': 'test/java/',
+ },
+ 'includes': [ '../../../build/java.gypi' ],
+ }
+ ]
+}
diff --git a/chromium/tools/android/findbugs_plugin/lib/chromiumPlugin.jar b/chromium/tools/android/findbugs_plugin/lib/chromiumPlugin.jar
new file mode 100644
index 00000000000..6ccf61b4303
--- /dev/null
+++ b/chromium/tools/android/findbugs_plugin/lib/chromiumPlugin.jar
Binary files differ
diff --git a/chromium/tools/android/findbugs_plugin/messages.xml b/chromium/tools/android/findbugs_plugin/messages.xml
new file mode 100644
index 00000000000..aea983bc24a
--- /dev/null
+++ b/chromium/tools/android/findbugs_plugin/messages.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<MessageCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="messagecollection.xsd">
+
+ <Plugin>
+ <ShortDescription>Chromium FindBugs Plugin </ShortDescription>
+ <Details>Adds style checks enforced in the chromium project.</Details>
+ </Plugin>
+
+ <Detector class="org.chromium.tools.findbugs.plugin.SynchronizedThisDetector">
+ <Details>
+ <![CDATA[
+ Shouldn't use synchronized(this).
+ ]]>
+ </Details>
+
+ </Detector>
+
+ <BugPattern type="CHROMIUM_SYNCHRONIZED_THIS">
+ <ShortDescription>Shouldn't use synchronized(this)</ShortDescription>
+ <LongDescription>Shouldn't use synchronized(this), please narrow down the synchronization scope.</LongDescription>
+ <Details>
+<![CDATA[
+<p>Shouldn't use synchronized(this), please narrow down the synchronization scope.</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <Detector class="org.chromium.tools.findbugs.plugin.SynchronizedMethodDetector">
+ <Details>
+ <![CDATA[
+ Shouldn't use synchronized method.
+ ]]>
+ </Details>
+
+ </Detector>
+
+ <BugPattern type="CHROMIUM_SYNCHRONIZED_METHOD">
+ <ShortDescription>Shouldn't use synchronized method</ShortDescription>
+ <LongDescription>Shouldn't use synchronized method, please narrow down the synchronization scope.</LongDescription>
+ <Details>
+<![CDATA[
+<p>Shouldn't use synchronized method, please narrow down the synchronization scope.</p>
+]]>
+ </Details>
+ </BugPattern>
+
+ <BugCode abbrev="CHROMIUM">CHROMIUM</BugCode>
+</MessageCollection>
diff --git a/chromium/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedMethodDetector.java b/chromium/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedMethodDetector.java
new file mode 100644
index 00000000000..7a879f66447
--- /dev/null
+++ b/chromium/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedMethodDetector.java
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.tools.findbugs.plugin;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+
+import org.apache.bcel.classfile.Code;
+
+/**
+ * This class detects the synchronized method.
+ */
+public class SynchronizedMethodDetector extends OpcodeStackDetector {
+
+ private BugReporter mBugReporter;
+
+ public SynchronizedMethodDetector(BugReporter bugReporter) {
+ this.mBugReporter = bugReporter;
+ }
+
+ @Override
+ public void visit(Code code) {
+ if (getMethod().isSynchronized()) {
+ mBugReporter.reportBug(new BugInstance(this, "CHROMIUM_SYNCHRONIZED_METHOD",
+ NORMAL_PRIORITY)
+ .addClassAndMethod(this)
+ .addSourceLine(this));
+ }
+ super.visit(code);
+ }
+
+ @Override
+ public void sawOpcode(int arg0) {
+ }
+}
diff --git a/chromium/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedThisDetector.java b/chromium/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedThisDetector.java
new file mode 100644
index 00000000000..330431ba7cd
--- /dev/null
+++ b/chromium/tools/android/findbugs_plugin/src/org/chromium/tools/findbugs/plugin/SynchronizedThisDetector.java
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.tools.findbugs.plugin;
+
+import org.apache.bcel.classfile.Code;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;
+
+/**
+ * This class detects the synchronized(this).
+ *
+ * The pattern of byte code of synchronized(this) is
+ * aload_0 # Load the 'this' pointer on top of stack
+ * dup # Duplicate the 'this' pointer
+ * astore_x # Store this for late use, it might be astore.
+ * monitorenter
+ */
+public class SynchronizedThisDetector extends OpcodeStackDetector {
+ private final int PATTERN[] = {ALOAD_0, DUP, 0xff, 0xff, MONITORENTER};
+
+ private int mStep = 0;
+ private BugReporter mBugReporter;
+
+ public SynchronizedThisDetector(BugReporter bugReporter) {
+ mBugReporter = bugReporter;
+ }
+
+ @Override
+ public void visit(Code code) {
+ mStep = 0;
+ super.visit(code);
+ }
+
+ @Override
+ public void sawOpcode(int seen) {
+ if (PATTERN[mStep] == seen) {
+ mStep++;
+ if (mStep == PATTERN.length) {
+ mBugReporter.reportBug(new BugInstance(this, "CHROMIUM_SYNCHRONIZED_THIS",
+ NORMAL_PRIORITY)
+ .addClassAndMethod(this)
+ .addSourceLine(this));
+ mStep = 0;
+ return;
+ }
+ } else if (mStep == 2) {
+ // This could be astore_x
+ switch (seen) {
+ case ASTORE_0:
+ case ASTORE_1:
+ case ASTORE_2:
+ case ASTORE_3:
+ mStep += 2;
+ break;
+ case ASTORE:
+ mStep++;
+ break;
+ default:
+ mStep = 0;
+ break;
+ }
+ } else if (mStep == 3) {
+ // Could be any byte following the ASTORE.
+ mStep++;
+ } else {
+ mStep = 0;
+ }
+ }
+}
diff --git a/chromium/tools/android/forwarder/forwarder.cc b/chromium/tools/android/forwarder/forwarder.cc
new file mode 100644
index 00000000000..e77c8065ff6
--- /dev/null
+++ b/chromium/tools/android/forwarder/forwarder.cc
@@ -0,0 +1,426 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "tools/android/common/adb_connection.h"
+#include "tools/android/common/daemon.h"
+#include "tools/android/common/net.h"
+
+namespace {
+
+const pthread_t kInvalidThread = static_cast<pthread_t>(-1);
+volatile bool g_killed = false;
+
+void CloseSocket(int fd) {
+ if (fd >= 0) {
+ int old_errno = errno;
+ (void) HANDLE_EINTR(close(fd));
+ errno = old_errno;
+ }
+}
+
+class Buffer {
+ public:
+ Buffer()
+ : bytes_read_(0),
+ write_offset_(0) {
+ }
+
+ bool CanRead() {
+ return bytes_read_ == 0;
+ }
+
+ bool CanWrite() {
+ return write_offset_ < bytes_read_;
+ }
+
+ int Read(int fd) {
+ int ret = -1;
+ if (CanRead()) {
+ ret = HANDLE_EINTR(read(fd, buffer_, kBufferSize));
+ if (ret > 0)
+ bytes_read_ = ret;
+ }
+ return ret;
+ }
+
+ int Write(int fd) {
+ int ret = -1;
+ if (CanWrite()) {
+ ret = HANDLE_EINTR(write(fd, buffer_ + write_offset_,
+ bytes_read_ - write_offset_));
+ if (ret > 0) {
+ write_offset_ += ret;
+ if (write_offset_ == bytes_read_) {
+ write_offset_ = 0;
+ bytes_read_ = 0;
+ }
+ }
+ }
+ return ret;
+ }
+
+ private:
+ // A big buffer to let our file-over-http bridge work more like real file.
+ static const int kBufferSize = 1024 * 128;
+ int bytes_read_;
+ int write_offset_;
+ char buffer_[kBufferSize];
+
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
+};
+
+class Server;
+
+struct ForwarderThreadInfo {
+ ForwarderThreadInfo(Server* a_server, int a_forwarder_index)
+ : server(a_server),
+ forwarder_index(a_forwarder_index) {
+ }
+ Server* server;
+ int forwarder_index;
+};
+
+struct ForwarderInfo {
+ time_t start_time;
+ int socket1;
+ time_t socket1_last_byte_time;
+ size_t socket1_bytes;
+ int socket2;
+ time_t socket2_last_byte_time;
+ size_t socket2_bytes;
+};
+
+class Server {
+ public:
+ Server()
+ : thread_(kInvalidThread),
+ socket_(-1) {
+ memset(forward_to_, 0, sizeof(forward_to_));
+ memset(&forwarders_, 0, sizeof(forwarders_));
+ }
+
+ int GetFreeForwarderIndex() {
+ for (int i = 0; i < kMaxForwarders; i++) {
+ if (forwarders_[i].start_time == 0)
+ return i;
+ }
+ return -1;
+ }
+
+ void DisposeForwarderInfo(int index) {
+ forwarders_[index].start_time = 0;
+ }
+
+ ForwarderInfo* GetForwarderInfo(int index) {
+ return &forwarders_[index];
+ }
+
+ void DumpInformation() {
+ LOG(INFO) << "Server information: " << forward_to_;
+ LOG(INFO) << "No.: age up(bytes,idle) down(bytes,idle)";
+ int count = 0;
+ time_t now = time(NULL);
+ for (int i = 0; i < kMaxForwarders; i++) {
+ const ForwarderInfo& info = forwarders_[i];
+ if (info.start_time) {
+ count++;
+ LOG(INFO) << count << ": " << now - info.start_time << " up("
+ << info.socket1_bytes << ","
+ << now - info.socket1_last_byte_time << " down("
+ << info.socket2_bytes << ","
+ << now - info.socket2_last_byte_time << ")";
+ }
+ }
+ }
+
+ void Shutdown() {
+ if (socket_ >= 0)
+ shutdown(socket_, SHUT_RDWR);
+ }
+
+ bool InitSocket(const char* arg);
+
+ void StartThread() {
+ pthread_create(&thread_, NULL, ServerThread, this);
+ }
+
+ void JoinThread() {
+ if (thread_ != kInvalidThread)
+ pthread_join(thread_, NULL);
+ }
+
+ private:
+ static void* ServerThread(void* arg);
+
+ // There are 3 kinds of threads that will access the array:
+ // 1. Server thread will get a free ForwarderInfo and initialize it;
+ // 2. Forwarder threads will dispose the ForwarderInfo when it finishes;
+ // 3. Main thread will iterate and print the forwarders.
+ // Using an array is not optimal, but can avoid locks or other complex
+ // inter-thread communication.
+ static const int kMaxForwarders = 512;
+ ForwarderInfo forwarders_[kMaxForwarders];
+
+ pthread_t thread_;
+ int socket_;
+ char forward_to_[40];
+
+ DISALLOW_COPY_AND_ASSIGN(Server);
+};
+
+// Forwards all outputs from one socket to another socket.
+void* ForwarderThread(void* arg) {
+ ForwarderThreadInfo* thread_info =
+ reinterpret_cast<ForwarderThreadInfo*>(arg);
+ Server* server = thread_info->server;
+ int index = thread_info->forwarder_index;
+ delete thread_info;
+ ForwarderInfo* info = server->GetForwarderInfo(index);
+ int socket1 = info->socket1;
+ int socket2 = info->socket2;
+ int nfds = socket1 > socket2 ? socket1 + 1 : socket2 + 1;
+ fd_set read_fds;
+ fd_set write_fds;
+ Buffer buffer1;
+ Buffer buffer2;
+
+ while (!g_killed) {
+ FD_ZERO(&read_fds);
+ if (buffer1.CanRead())
+ FD_SET(socket1, &read_fds);
+ if (buffer2.CanRead())
+ FD_SET(socket2, &read_fds);
+
+ FD_ZERO(&write_fds);
+ if (buffer1.CanWrite())
+ FD_SET(socket2, &write_fds);
+ if (buffer2.CanWrite())
+ FD_SET(socket1, &write_fds);
+
+ if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, NULL)) <= 0) {
+ LOG(ERROR) << "Select error: " << strerror(errno);
+ break;
+ }
+
+ int now = time(NULL);
+ if (FD_ISSET(socket1, &read_fds)) {
+ info->socket1_last_byte_time = now;
+ int bytes = buffer1.Read(socket1);
+ if (bytes <= 0)
+ break;
+ info->socket1_bytes += bytes;
+ }
+ if (FD_ISSET(socket2, &read_fds)) {
+ info->socket2_last_byte_time = now;
+ int bytes = buffer2.Read(socket2);
+ if (bytes <= 0)
+ break;
+ info->socket2_bytes += bytes;
+ }
+ if (FD_ISSET(socket1, &write_fds)) {
+ if (buffer2.Write(socket1) <= 0)
+ break;
+ }
+ if (FD_ISSET(socket2, &write_fds)) {
+ if (buffer1.Write(socket2) <= 0)
+ break;
+ }
+ }
+
+ CloseSocket(socket1);
+ CloseSocket(socket2);
+ server->DisposeForwarderInfo(index);
+ return NULL;
+}
+
+// Listens to a server socket. On incoming request, forward it to the host.
+// static
+void* Server::ServerThread(void* arg) {
+ Server* server = reinterpret_cast<Server*>(arg);
+ while (!g_killed) {
+ int forwarder_index = server->GetFreeForwarderIndex();
+ if (forwarder_index < 0) {
+ LOG(ERROR) << "Too many forwarders";
+ continue;
+ }
+
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+ int socket = HANDLE_EINTR(accept(server->socket_,
+ reinterpret_cast<sockaddr*>(&addr),
+ &addr_len));
+ if (socket < 0) {
+ LOG(ERROR) << "Failed to accept: " << strerror(errno);
+ break;
+ }
+ tools::DisableNagle(socket);
+
+ int host_socket = tools::ConnectAdbHostSocket(server->forward_to_);
+ if (host_socket >= 0) {
+ // Set NONBLOCK flag because we use select().
+ fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK);
+ fcntl(host_socket, F_SETFL, fcntl(host_socket, F_GETFL) | O_NONBLOCK);
+
+ ForwarderInfo* forwarder_info = server->GetForwarderInfo(forwarder_index);
+ time_t now = time(NULL);
+ forwarder_info->start_time = now;
+ forwarder_info->socket1 = socket;
+ forwarder_info->socket1_last_byte_time = now;
+ forwarder_info->socket1_bytes = 0;
+ forwarder_info->socket2 = host_socket;
+ forwarder_info->socket2_last_byte_time = now;
+ forwarder_info->socket2_bytes = 0;
+
+ pthread_t thread;
+ pthread_create(&thread, NULL, ForwarderThread,
+ new ForwarderThreadInfo(server, forwarder_index));
+ } else {
+ // Close the unused client socket which is failed to connect to host.
+ CloseSocket(socket);
+ }
+ }
+
+ CloseSocket(server->socket_);
+ server->socket_ = -1;
+ return NULL;
+}
+
+// Format of arg: <Device port>[:<Forward to port>:<Forward to address>]
+bool Server::InitSocket(const char* arg) {
+ char* endptr;
+ int local_port = static_cast<int>(strtol(arg, &endptr, 10));
+ if (local_port < 0)
+ return false;
+
+ if (*endptr != ':') {
+ snprintf(forward_to_, sizeof(forward_to_), "%d:127.0.0.1", local_port);
+ } else {
+ strncpy(forward_to_, endptr + 1, sizeof(forward_to_) - 1);
+ }
+
+ socket_ = socket(AF_INET, SOCK_STREAM, 0);
+ if (socket_ < 0) {
+ perror("server socket");
+ return false;
+ }
+ tools::DisableNagle(socket_);
+
+ sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_port = htons(local_port);
+ int reuse_addr = 1;
+ setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
+ &reuse_addr, sizeof(reuse_addr));
+ tools::DeferAccept(socket_);
+ if (HANDLE_EINTR(bind(socket_, reinterpret_cast<sockaddr*>(&addr),
+ sizeof(addr))) < 0 ||
+ HANDLE_EINTR(listen(socket_, 5)) < 0) {
+ perror("server bind");
+ CloseSocket(socket_);
+ socket_ = -1;
+ return false;
+ }
+
+ if (local_port == 0) {
+ socklen_t addrlen = sizeof(addr);
+ if (getsockname(socket_, reinterpret_cast<sockaddr*>(&addr), &addrlen)
+ != 0) {
+ perror("get listen address");
+ CloseSocket(socket_);
+ socket_ = -1;
+ return false;
+ }
+ local_port = ntohs(addr.sin_port);
+ }
+
+ printf("Forwarding device port %d to host %s\n", local_port, forward_to_);
+ return true;
+}
+
+int g_server_count = 0;
+Server* g_servers = NULL;
+
+void KillHandler(int unused) {
+ g_killed = true;
+ for (int i = 0; i < g_server_count; i++)
+ g_servers[i].Shutdown();
+}
+
+void DumpInformation(int unused) {
+ for (int i = 0; i < g_server_count; i++)
+ g_servers[i].DumpInformation();
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ printf("Android device to host TCP forwarder\n");
+ printf("Like 'adb forward' but in the reverse direction\n");
+
+ CommandLine command_line(argc, argv);
+ CommandLine::StringVector server_args = command_line.GetArgs();
+ if (tools::HasHelpSwitch(command_line) || server_args.empty()) {
+ tools::ShowHelp(
+ argv[0],
+ "<Device port>[:<Forward to port>:<Forward to address>] ...",
+ " <Forward to port> default is <Device port>\n"
+ " <Forward to address> default is 127.0.0.1\n"
+ "If <Device port> is 0, a port will by dynamically allocated.\n");
+ return 0;
+ }
+
+ g_servers = new Server[server_args.size()];
+ g_server_count = 0;
+ int failed_count = 0;
+ for (size_t i = 0; i < server_args.size(); i++) {
+ if (!g_servers[g_server_count].InitSocket(server_args[i].c_str())) {
+ printf("Couldn't start forwarder server for port spec: %s\n",
+ server_args[i].c_str());
+ ++failed_count;
+ } else {
+ ++g_server_count;
+ }
+ }
+
+ if (g_server_count == 0) {
+ printf("No forwarder servers could be started. Exiting.\n");
+ delete [] g_servers;
+ return failed_count;
+ }
+
+ if (!tools::HasNoSpawnDaemonSwitch(command_line))
+ tools::SpawnDaemon(failed_count);
+
+ signal(SIGTERM, KillHandler);
+ signal(SIGUSR2, DumpInformation);
+
+ for (int i = 0; i < g_server_count; i++)
+ g_servers[i].StartThread();
+ for (int i = 0; i < g_server_count; i++)
+ g_servers[i].JoinThread();
+ g_server_count = 0;
+ delete [] g_servers;
+
+ return 0;
+}
+
diff --git a/chromium/tools/android/forwarder/forwarder.gyp b/chromium/tools/android/forwarder/forwarder.gyp
new file mode 100644
index 00000000000..1df518b1bb6
--- /dev/null
+++ b/chromium/tools/android/forwarder/forwarder.gyp
@@ -0,0 +1,43 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'forwarder',
+ 'type': 'none',
+ 'dependencies': [
+ 'forwarder_symbols',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'strip_forwarder',
+ 'inputs': ['<(PRODUCT_DIR)/forwarder_symbols'],
+ 'outputs': ['<(PRODUCT_DIR)/forwarder'],
+ 'action': [
+ '<(android_strip)',
+ '--strip-unneeded',
+ '<@(_inputs)',
+ '-o',
+ '<@(_outputs)',
+ ],
+ },
+ ],
+ }, {
+ 'target_name': 'forwarder_symbols',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../common/common.gyp:android_tools_common',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ 'sources': [
+ 'forwarder.cc',
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/android/forwarder2/command.cc b/chromium/tools/android/forwarder2/command.cc
new file mode 100644
index 00000000000..9b0aa24cfb6
--- /dev/null
+++ b/chromium/tools/android/forwarder2/command.cc
@@ -0,0 +1,96 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/command.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/logging.h"
+#include "base/safe_strerror_posix.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "tools/android/forwarder2/socket.h"
+
+using base::StringPiece;
+
+namespace {
+
+
+// Command format:
+// <port>:<type>
+//
+// Where:
+// <port> is a 5-chars zero-padded ASCII decimal integer
+// matching the target port for the command (e.g.
+// '08080' for port 8080)
+// <type> is a 3-char zero-padded ASCII decimal integer
+// matching a command::Type value (e.g. 002 for
+// ACK).
+// The column (:) is used as a separator for easier reading.
+const int kPortStringSize = 5;
+const int kCommandTypeStringSize = 2;
+// Command string size also includes the ':' separator char.
+const int kCommandStringSize = kPortStringSize + kCommandTypeStringSize + 1;
+
+} // namespace
+
+namespace forwarder2 {
+
+bool ReadCommand(Socket* socket,
+ int* port_out,
+ command::Type* command_type_out) {
+ char command_buffer[kCommandStringSize + 1];
+ // To make logging easier.
+ command_buffer[kCommandStringSize] = '\0';
+
+ int bytes_read = socket->ReadNumBytes(command_buffer, kCommandStringSize);
+ if (bytes_read != kCommandStringSize) {
+ if (bytes_read < 0)
+ LOG(ERROR) << "Read() error: " << safe_strerror(errno);
+ else if (!bytes_read)
+ LOG(ERROR) << "Read() error, endpoint was unexpectedly closed.";
+ else
+ LOG(ERROR) << "Read() error, not enough data received from the socket.";
+ return false;
+ }
+
+ StringPiece port_str(command_buffer, kPortStringSize);
+ if (!StringToInt(port_str, port_out)) {
+ LOG(ERROR) << "Could not parse the command port string: "
+ << port_str;
+ return false;
+ }
+
+ StringPiece command_type_str(
+ &command_buffer[kPortStringSize + 1], kCommandTypeStringSize);
+ int command_type;
+ if (!StringToInt(command_type_str, &command_type)) {
+ LOG(ERROR) << "Could not parse the command type string: "
+ << command_type_str;
+ return false;
+ }
+ *command_type_out = static_cast<command::Type>(command_type);
+ return true;
+}
+
+bool SendCommand(command::Type command, int port, Socket* socket) {
+ char buffer[kCommandStringSize + 1];
+ int len = snprintf(buffer, sizeof(buffer), "%05d:%02d", port, command);
+ CHECK_EQ(len, kCommandStringSize);
+ // Write the full command minus the leading \0 char.
+ return socket->WriteNumBytes(buffer, len) == len;
+}
+
+bool ReceivedCommand(command::Type command, Socket* socket) {
+ int port;
+ command::Type received_command;
+ if (!ReadCommand(socket, &port, &received_command))
+ return false;
+ return received_command == command;
+}
+
+} // namespace forwarder
diff --git a/chromium/tools/android/forwarder2/command.h b/chromium/tools/android/forwarder2/command.h
new file mode 100644
index 00000000000..8e222ef7bb9
--- /dev/null
+++ b/chromium/tools/android/forwarder2/command.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_COMMAND_H_
+#define TOOLS_ANDROID_FORWARDER2_COMMAND_H_
+
+#include "base/basictypes.h"
+
+namespace forwarder2 {
+
+class Socket;
+
+namespace command {
+
+enum Type {
+ ACCEPT_ERROR = 0,
+ ACCEPT_SUCCESS,
+ ACK,
+ ADB_DATA_SOCKET_ERROR,
+ ADB_DATA_SOCKET_SUCCESS,
+ BIND_ERROR,
+ BIND_SUCCESS,
+ DATA_CONNECTION,
+ HOST_SERVER_ERROR,
+ HOST_SERVER_SUCCESS,
+ KILL_ALL_LISTENERS,
+ LISTEN,
+ UNLISTEN,
+ UNLISTEN_ERROR,
+ UNLISTEN_SUCCESS,
+};
+
+} // namespace command
+
+bool ReadCommand(Socket* socket,
+ int* port_out,
+ command::Type* command_type_out);
+
+// Helper function to read the command from the |socket| and return true if the
+// |command| is equal to the given command parameter.
+bool ReceivedCommand(command::Type command, Socket* socket);
+
+bool SendCommand(command::Type command, int port, Socket* socket);
+
+} // namespace forwarder
+
+#endif // TOOLS_ANDROID_FORWARDER2_COMMAND_H_
diff --git a/chromium/tools/android/forwarder2/common.cc b/chromium/tools/android/forwarder2/common.cc
new file mode 100644
index 00000000000..c97ed8056b7
--- /dev/null
+++ b/chromium/tools/android/forwarder2/common.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/common.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/safe_strerror_posix.h"
+
+namespace forwarder2 {
+
+void PError(const char* msg) {
+ LOG(ERROR) << msg << ": " << safe_strerror(errno);
+}
+
+void CloseFD(int fd) {
+ const int errno_copy = errno;
+ if (HANDLE_EINTR(close(fd)) < 0) {
+ PError("close");
+ errno = errno_copy;
+ }
+}
+
+} // namespace forwarder2
diff --git a/chromium/tools/android/forwarder2/common.h b/chromium/tools/android/forwarder2/common.h
new file mode 100644
index 00000000000..43de57b1605
--- /dev/null
+++ b/chromium/tools/android/forwarder2/common.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Common helper functions/classes used both in the host and device forwarder.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_COMMON_H_
+#define TOOLS_ANDROID_FORWARDER2_COMMON_H_
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+
+// Preserving errno for Close() is important because the function is very often
+// used in cleanup code, after an error occurred, and it is very easy to pass an
+// invalid file descriptor to close() in this context, or more rarely, a
+// spurious signal might make close() return -1 + setting errno to EINTR,
+// masking the real reason for the original error. This leads to very unpleasant
+// debugging sessions.
+#define PRESERVE_ERRNO_HANDLE_EINTR(Func) \
+ do { \
+ int local_errno = errno; \
+ (void) HANDLE_EINTR(Func); \
+ errno = local_errno; \
+ } while (false);
+
+// Wrapper around RAW_LOG() which is signal-safe. The only purpose of this macro
+// is to avoid documenting uses of RawLog().
+#define SIGNAL_SAFE_LOG(Level, Msg) \
+ RAW_LOG(Level, Msg);
+
+namespace forwarder2 {
+
+// Note that the two following functions are not signal-safe.
+
+// Chromium logging-aware implementation of libc's perror().
+void PError(const char* msg);
+
+// Closes the provided file descriptor and logs an error if it failed.
+void CloseFD(int fd);
+
+// Helps build a formatted C-string allocated in a fixed-size array. This is
+// useful in signal handlers where base::StringPrintf() can't be used safely
+// (due to its use of LOG()).
+template <int BufferSize>
+class FixedSizeStringBuilder {
+ public:
+ FixedSizeStringBuilder() {
+ Reset();
+ }
+
+ const char* buffer() const { return buffer_; }
+
+ void Reset() {
+ buffer_[0] = 0;
+ write_ptr_ = buffer_;
+ }
+
+ // Returns the number of bytes appended to the underlying buffer or -1 if it
+ // failed.
+ int Append(const char* format, ...) PRINTF_FORMAT(/* + 1 for 'this' */ 2, 3) {
+ if (write_ptr_ >= buffer_ + BufferSize)
+ return -1;
+ va_list ap;
+ va_start(ap, format);
+ const int bytes_written = vsnprintf(
+ write_ptr_, BufferSize - (write_ptr_ - buffer_), format, ap);
+ va_end(ap);
+ if (bytes_written > 0)
+ write_ptr_ += bytes_written;
+ return bytes_written;
+ }
+
+ private:
+ char* write_ptr_;
+ char buffer_[BufferSize];
+
+ COMPILE_ASSERT(BufferSize >= 1, Size_of_buffer_must_be_at_least_one);
+ DISALLOW_COPY_AND_ASSIGN(FixedSizeStringBuilder);
+};
+
+} // namespace forwarder2
+
+#endif // TOOLS_ANDROID_FORWARDER2_COMMON_H_
diff --git a/chromium/tools/android/forwarder2/daemon.cc b/chromium/tools/android/forwarder2/daemon.cc
new file mode 100644
index 00000000000..0ca89d1a5fd
--- /dev/null
+++ b/chromium/tools/android/forwarder2/daemon.cc
@@ -0,0 +1,288 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/daemon.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/safe_strerror_posix.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "tools/android/forwarder2/common.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace forwarder2 {
+namespace {
+
+const int kBufferSize = 256;
+
+// Timeout constant used for polling when connecting to the daemon's Unix Domain
+// Socket and also when waiting for its death when it is killed.
+const int kNumTries = 100;
+const int kIdleTimeMSec = 20;
+
+void InitLoggingForDaemon(const std::string& log_file) {
+ logging::LoggingSettings settings;
+ settings.logging_dest =
+ log_file.empty() ?
+ logging::LOG_TO_SYSTEM_DEBUG_LOG : logging::LOG_TO_FILE;
+ settings.log_file = log_file.c_str();
+ settings.lock_log = logging::DONT_LOCK_LOG_FILE;
+ settings.dcheck_state =
+ logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
+ CHECK(logging::InitLogging(settings));
+}
+
+bool RunServerAcceptLoop(const std::string& welcome_message,
+ Socket* server_socket,
+ Daemon::ServerDelegate* server_delegate) {
+ bool failed = false;
+ for (;;) {
+ scoped_ptr<Socket> client_socket(new Socket());
+ if (!server_socket->Accept(client_socket.get())) {
+ if (server_socket->DidReceiveEvent())
+ break;
+ PError("Accept()");
+ failed = true;
+ break;
+ }
+ if (!client_socket->Write(welcome_message.c_str(),
+ welcome_message.length() + 1)) {
+ PError("Write()");
+ failed = true;
+ continue;
+ }
+ server_delegate->OnClientConnected(client_socket.Pass());
+ }
+ return !failed;
+}
+
+void SigChildHandler(int signal_number) {
+ DCHECK_EQ(signal_number, SIGCHLD);
+ int status;
+ pid_t child_pid = waitpid(-1 /* any child */, &status, WNOHANG);
+ if (child_pid < 0) {
+ PError("waitpid");
+ return;
+ }
+ if (child_pid == 0)
+ return;
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ return;
+ // Avoid using StringAppendF() since it's unsafe in a signal handler due to
+ // its use of LOG().
+ FixedSizeStringBuilder<256> string_builder;
+ string_builder.Append("Daemon (pid=%d) died unexpectedly with ", child_pid);
+ if (WIFEXITED(status))
+ string_builder.Append("status %d.", WEXITSTATUS(status));
+ else if (WIFSIGNALED(status))
+ string_builder.Append("signal %d.", WTERMSIG(status));
+ else
+ string_builder.Append("unknown reason.");
+ SIGNAL_SAFE_LOG(ERROR, string_builder.buffer());
+}
+
+// Note that 0 is written to |lock_owner_pid| in case the file is not locked.
+bool GetFileLockOwnerPid(int fd, pid_t* lock_owner_pid) {
+ struct flock lock_info = {};
+ lock_info.l_type = F_WRLCK;
+ lock_info.l_whence = SEEK_CUR;
+ const int ret = HANDLE_EINTR(fcntl(fd, F_GETLK, &lock_info));
+ if (ret < 0) {
+ if (errno == EBADF) {
+ // Assume that the provided file descriptor corresponding to the PID file
+ // was valid until the daemon removed this file.
+ *lock_owner_pid = 0;
+ return true;
+ }
+ PError("fcntl");
+ return false;
+ }
+ if (lock_info.l_type == F_UNLCK) {
+ *lock_owner_pid = 0;
+ return true;
+ }
+ CHECK_EQ(F_WRLCK /* exclusive lock */, lock_info.l_type);
+ *lock_owner_pid = lock_info.l_pid;
+ return true;
+}
+
+scoped_ptr<Socket> ConnectToUnixDomainSocket(
+ const std::string& socket_name,
+ int tries_count,
+ int idle_time_msec,
+ const std::string& expected_welcome_message) {
+ for (int i = 0; i < tries_count; ++i) {
+ scoped_ptr<Socket> socket(new Socket());
+ if (!socket->ConnectUnix(socket_name)) {
+ if (idle_time_msec)
+ usleep(idle_time_msec * 1000);
+ continue;
+ }
+ char buf[kBufferSize];
+ DCHECK(expected_welcome_message.length() + 1 <= sizeof(buf));
+ memset(buf, 0, sizeof(buf));
+ if (socket->Read(buf, expected_welcome_message.length() + 1) < 0) {
+ perror("read");
+ continue;
+ }
+ if (expected_welcome_message != buf) {
+ LOG(ERROR) << "Unexpected message read from daemon: " << buf;
+ break;
+ }
+ return socket.Pass();
+ }
+ return scoped_ptr<Socket>();
+}
+
+} // namespace
+
+Daemon::Daemon(const std::string& log_file_path,
+ const std::string& identifier,
+ ClientDelegate* client_delegate,
+ ServerDelegate* server_delegate,
+ GetExitNotifierFDCallback get_exit_fd_callback)
+ : log_file_path_(log_file_path),
+ identifier_(identifier),
+ client_delegate_(client_delegate),
+ server_delegate_(server_delegate),
+ get_exit_fd_callback_(get_exit_fd_callback) {
+ DCHECK(client_delegate_);
+ DCHECK(server_delegate_);
+ DCHECK(get_exit_fd_callback_);
+}
+
+Daemon::~Daemon() {}
+
+bool Daemon::SpawnIfNeeded() {
+ const int kSingleTry = 1;
+ const int kNoIdleTime = 0;
+ scoped_ptr<Socket> client_socket = ConnectToUnixDomainSocket(
+ identifier_, kSingleTry, kNoIdleTime, identifier_);
+ if (!client_socket) {
+ switch (fork()) {
+ case -1:
+ PError("fork()");
+ return false;
+ // Child.
+ case 0: {
+ if (setsid() < 0) { // Detach the child process from its parent.
+ PError("setsid()");
+ exit(1);
+ }
+ InitLoggingForDaemon(log_file_path_);
+ CloseFD(STDIN_FILENO);
+ CloseFD(STDOUT_FILENO);
+ CloseFD(STDERR_FILENO);
+ const int null_fd = open("/dev/null", O_RDWR);
+ CHECK_EQ(null_fd, STDIN_FILENO);
+ CHECK_EQ(dup(null_fd), STDOUT_FILENO);
+ CHECK_EQ(dup(null_fd), STDERR_FILENO);
+ Socket command_socket;
+ if (!command_socket.BindUnix(identifier_)) {
+ scoped_ptr<Socket> client_socket = ConnectToUnixDomainSocket(
+ identifier_, kSingleTry, kNoIdleTime, identifier_);
+ if (client_socket.get()) {
+ // The daemon was spawned by a concurrent process.
+ exit(0);
+ }
+ PError("bind()");
+ exit(1);
+ }
+ server_delegate_->Init();
+ command_socket.AddEventFd(get_exit_fd_callback_());
+ return RunServerAcceptLoop(
+ identifier_, &command_socket, server_delegate_);
+ }
+ default:
+ break;
+ }
+ }
+ // Parent.
+ // Install the custom SIGCHLD handler.
+ sigset_t blocked_signals_set;
+ if (sigprocmask(0 /* first arg ignored */, NULL, &blocked_signals_set) < 0) {
+ PError("sigprocmask()");
+ return false;
+ }
+ struct sigaction old_action;
+ struct sigaction new_action;
+ memset(&new_action, 0, sizeof(new_action));
+ new_action.sa_handler = SigChildHandler;
+ new_action.sa_flags = SA_NOCLDSTOP;
+ sigemptyset(&new_action.sa_mask);
+ if (sigaction(SIGCHLD, &new_action, &old_action) < 0) {
+ PError("sigaction()");
+ return false;
+ }
+ // Connect to the daemon's Unix Domain Socket.
+ bool failed = false;
+ if (!client_socket) {
+ client_socket = ConnectToUnixDomainSocket(
+ identifier_, kNumTries, kIdleTimeMSec, identifier_);
+ if (!client_socket) {
+ LOG(ERROR) << "Could not connect to daemon's Unix Daemon socket";
+ failed = true;
+ }
+ }
+ if (!failed)
+ client_delegate_->OnDaemonReady(client_socket.get());
+ // Restore the previous signal action for SIGCHLD.
+ if (sigaction(SIGCHLD, &old_action, NULL) < 0) {
+ PError("sigaction");
+ failed = true;
+ }
+ return !failed;
+}
+
+bool Daemon::Kill() {
+ pid_t daemon_pid = Socket::GetUnixDomainSocketProcessOwner(identifier_);
+ if (daemon_pid < 0)
+ return true; // No daemon running.
+ if (kill(daemon_pid, SIGTERM) < 0) {
+ if (errno == ESRCH /* invalid PID */)
+ // The daemon exited for some reason (e.g. kill by a process other than
+ // us) right before the call to kill() above.
+ return true;
+ PError("kill");
+ return false;
+ }
+ for (int i = 0; i < kNumTries; ++i) {
+ const pid_t previous_pid = daemon_pid;
+ daemon_pid = Socket::GetUnixDomainSocketProcessOwner(identifier_);
+ if (daemon_pid < 0)
+ return true;
+ // Since we are polling we might not see the 'daemon exited' event if
+ // another daemon was spawned during our idle period.
+ if (daemon_pid != previous_pid) {
+ LOG(WARNING) << "Daemon (pid=" << previous_pid
+ << ") was successfully killed but a new daemon (pid="
+ << daemon_pid << ") seems to be running now.";
+ return true;
+ }
+ usleep(kIdleTimeMSec * 1000);
+ }
+ LOG(ERROR) << "Timed out while killing daemon. "
+ "It might still be tearing down.";
+ return false;
+}
+
+} // namespace forwarder2
diff --git a/chromium/tools/android/forwarder2/daemon.h b/chromium/tools/android/forwarder2/daemon.h
new file mode 100644
index 00000000000..4b05ea423c0
--- /dev/null
+++ b/chromium/tools/android/forwarder2/daemon.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_DAEMON_H_
+#define TOOLS_ANDROID_FORWARDER2_DAEMON_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace forwarder2 {
+
+class Socket;
+
+// Provides a way to spawn a daemon and communicate with it.
+class Daemon {
+ public:
+ // Callback used by the daemon to shutdown properly. See pipe_notifier.h for
+ // more details.
+ typedef int (*GetExitNotifierFDCallback)();
+
+ class ClientDelegate {
+ public:
+ virtual ~ClientDelegate() {}
+
+ // Called after the daemon is ready to receive commands.
+ virtual void OnDaemonReady(Socket* daemon_socket) = 0;
+ };
+
+ class ServerDelegate {
+ public:
+ virtual ~ServerDelegate() {}
+
+ // Called after the daemon bound its Unix Domain Socket. This can be used to
+ // setup signal handlers or perform global initialization.
+ virtual void Init() = 0;
+
+ virtual void OnClientConnected(scoped_ptr<Socket> client_socket) = 0;
+ };
+
+ // |identifier| should be a unique string identifier. It is used to
+ // bind/connect the underlying Unix Domain Socket.
+ // Note that this class does not take ownership of |client_delegate| and
+ // |server_delegate|.
+ Daemon(const std::string& log_file_path,
+ const std::string& identifier,
+ ClientDelegate* client_delegate,
+ ServerDelegate* server_delegate,
+ GetExitNotifierFDCallback get_exit_fd_callback);
+
+ ~Daemon();
+
+ // Returns whether the daemon was successfully spawned. Note that this does
+ // not necessarily mean that the current process was forked in case the daemon
+ // is already running.
+ bool SpawnIfNeeded();
+
+ // Kills the daemon and blocks until it exited. Returns whether it succeeded.
+ bool Kill();
+
+ private:
+ const std::string log_file_path_;
+ const std::string identifier_;
+ ClientDelegate* const client_delegate_;
+ ServerDelegate* const server_delegate_;
+ const GetExitNotifierFDCallback get_exit_fd_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(Daemon);
+};
+
+} // namespace forwarder2
+
+#endif // TOOLS_ANDROID_FORWARDER2_DAEMON_H_
diff --git a/chromium/tools/android/forwarder2/device_controller.cc b/chromium/tools/android/forwarder2/device_controller.cc
new file mode 100644
index 00000000000..87d0e17143d
--- /dev/null
+++ b/chromium/tools/android/forwarder2/device_controller.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/device_controller.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/single_thread_task_runner.h"
+#include "tools/android/forwarder2/command.h"
+#include "tools/android/forwarder2/device_listener.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace forwarder2 {
+
+// static
+scoped_ptr<DeviceController> DeviceController::Create(
+ const std::string& adb_unix_socket,
+ int exit_notifier_fd) {
+ scoped_ptr<DeviceController> device_controller;
+ scoped_ptr<Socket> host_socket(new Socket());
+ if (!host_socket->BindUnix(adb_unix_socket)) {
+ PLOG(ERROR) << "Could not BindAndListen DeviceController socket on port "
+ << adb_unix_socket << ": ";
+ return device_controller.Pass();
+ }
+ LOG(INFO) << "Listening on Unix Domain Socket " << adb_unix_socket;
+ device_controller.reset(
+ new DeviceController(host_socket.Pass(), exit_notifier_fd));
+ return device_controller.Pass();
+}
+
+DeviceController::~DeviceController() {
+ DCHECK(construction_task_runner_->RunsTasksOnCurrentThread());
+}
+
+void DeviceController::Start() {
+ AcceptHostCommandSoon();
+}
+
+DeviceController::DeviceController(scoped_ptr<Socket> host_socket,
+ int exit_notifier_fd)
+ : host_socket_(host_socket.Pass()),
+ exit_notifier_fd_(exit_notifier_fd),
+ construction_task_runner_(base::MessageLoopProxy::current()),
+ weak_ptr_factory_(this) {
+ host_socket_->AddEventFd(exit_notifier_fd);
+}
+
+void DeviceController::AcceptHostCommandSoon() {
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeviceController::AcceptHostCommandInternal,
+ base::Unretained(this)));
+}
+
+void DeviceController::AcceptHostCommandInternal() {
+ scoped_ptr<Socket> socket(new Socket);
+ if (!host_socket_->Accept(socket.get())) {
+ if (!host_socket_->DidReceiveEvent())
+ PLOG(ERROR) << "Could not Accept DeviceController socket";
+ else
+ LOG(INFO) << "Received exit notification";
+ return;
+ }
+ base::ScopedClosureRunner accept_next_client(
+ base::Bind(&DeviceController::AcceptHostCommandSoon,
+ base::Unretained(this)));
+ // So that |socket| doesn't block on read if it has notifications.
+ socket->AddEventFd(exit_notifier_fd_);
+ int port;
+ command::Type command;
+ if (!ReadCommand(socket.get(), &port, &command)) {
+ LOG(ERROR) << "Invalid command received.";
+ return;
+ }
+ const ListenersMap::iterator listener_it = listeners_.find(port);
+ DeviceListener* const listener = listener_it == listeners_.end()
+ ? static_cast<DeviceListener*>(NULL) : listener_it->second.get();
+ switch (command) {
+ case command::LISTEN: {
+ if (listener != NULL) {
+ LOG(WARNING) << "Already forwarding port " << port
+ << ". Attempting to restart the listener.\n";
+ // Note that this deletes the listener object.
+ listeners_.erase(listener_it);
+ }
+ scoped_ptr<DeviceListener> new_listener(
+ DeviceListener::Create(
+ socket.Pass(), port, base::Bind(&DeviceController::DeleteListener,
+ weak_ptr_factory_.GetWeakPtr())));
+ if (!new_listener)
+ return;
+ new_listener->Start();
+ // |port| can be zero, to allow dynamically allocated port, so instead, we
+ // call DeviceListener::listener_port() to retrieve the currently
+ // allocated port to this new listener.
+ const int listener_port = new_listener->listener_port();
+ listeners_.insert(
+ std::make_pair(listener_port,
+ linked_ptr<DeviceListener>(new_listener.release())));
+ LOG(INFO) << "Forwarding device port " << listener_port << " to host.";
+ break;
+ }
+ case command::DATA_CONNECTION:
+ if (listener == NULL) {
+ LOG(ERROR) << "Data Connection command received, but "
+ << "listener has not been set up yet for port " << port;
+ // After this point it is assumed that, once we close our Adb Data
+ // socket, the Adb forwarder command will propagate the closing of
+ // sockets all the way to the host side.
+ break;
+ }
+ listener->SetAdbDataSocket(socket.Pass());
+ break;
+ case command::UNLISTEN:
+ if (!listener) {
+ SendCommand(command::UNLISTEN_ERROR, port, socket.get());
+ break;
+ }
+ listeners_.erase(listener_it);
+ SendCommand(command::UNLISTEN_SUCCESS, port, socket.get());
+ break;
+ default:
+ // TODO(felipeg): add a KillAllListeners command.
+ LOG(ERROR) << "Invalid command received. Port: " << port
+ << " Command: " << command;
+ }
+}
+
+// static
+void DeviceController::DeleteListener(
+ const base::WeakPtr<DeviceController>& device_controller_ptr,
+ int listener_port) {
+ DeviceController* const controller = device_controller_ptr.get();
+ if (!controller)
+ return;
+ DCHECK(controller->construction_task_runner_->RunsTasksOnCurrentThread());
+ const ListenersMap::iterator listener_it = controller->listeners_.find(
+ listener_port);
+ if (listener_it == controller->listeners_.end())
+ return;
+ const linked_ptr<DeviceListener> listener = listener_it->second;
+ // Note that the listener is removed from the map before it gets destroyed in
+ // case its destructor would access the map.
+ controller->listeners_.erase(listener_it);
+}
+
+} // namespace forwarder
diff --git a/chromium/tools/android/forwarder2/device_controller.h b/chromium/tools/android/forwarder2/device_controller.h
new file mode 100644
index 00000000000..3daedb3688a
--- /dev/null
+++ b/chromium/tools/android/forwarder2/device_controller.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_DEVICE_CONTROLLER_H_
+#define TOOLS_ANDROID_FORWARDER2_DEVICE_CONTROLLER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace forwarder2 {
+
+class DeviceListener;
+
+// There is a single DeviceController per device_forwarder process, and it is in
+// charge of managing all active redirections on the device side (one
+// DeviceListener each).
+class DeviceController {
+ public:
+ static scoped_ptr<DeviceController> Create(const std::string& adb_unix_socket,
+ int exit_notifier_fd);
+ ~DeviceController();
+
+ void Start();
+
+ private:
+ typedef base::hash_map<
+ int /* port */, linked_ptr<DeviceListener> > ListenersMap;
+
+ DeviceController(scoped_ptr<Socket> host_socket, int exit_notifier_fd);
+
+ void AcceptHostCommandSoon();
+ void AcceptHostCommandInternal();
+
+ // Note that this can end up being called after the DeviceController is
+ // destroyed which is why a weak pointer is used.
+ static void DeleteListener(
+ const base::WeakPtr<DeviceController>& device_controller_ptr,
+ int listener_port);
+
+ const scoped_ptr<Socket> host_socket_;
+ // Used to notify the controller to exit.
+ const int exit_notifier_fd_;
+ // Lets ensure DeviceListener instances are deleted on the thread they were
+ // created on.
+ const scoped_refptr<base::SingleThreadTaskRunner> construction_task_runner_;
+ base::WeakPtrFactory<DeviceController> weak_ptr_factory_;
+ ListenersMap listeners_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceController);
+};
+
+} // namespace forwarder
+
+#endif // TOOLS_ANDROID_FORWARDER2_DEVICE_CONTROLLER_H_
diff --git a/chromium/tools/android/forwarder2/device_forwarder_main.cc b/chromium/tools/android/forwarder2/device_forwarder_main.cc
new file mode 100644
index 00000000000..cad46f465a6
--- /dev/null
+++ b/chromium/tools/android/forwarder2/device_forwarder_main.cc
@@ -0,0 +1,169 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <signal.h>
+#include <stdlib.h>
+
+#include <iostream>
+#include <string>
+
+#include "base/at_exit.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread.h"
+#include "tools/android/forwarder2/common.h"
+#include "tools/android/forwarder2/daemon.h"
+#include "tools/android/forwarder2/device_controller.h"
+#include "tools/android/forwarder2/pipe_notifier.h"
+
+namespace forwarder2 {
+namespace {
+
+// Leaky global instance, accessed from the signal handler.
+forwarder2::PipeNotifier* g_notifier = NULL;
+
+const int kBufSize = 256;
+
+const char kUnixDomainSocketPath[] = "chrome_device_forwarder";
+const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon";
+
+void KillHandler(int /* unused */) {
+ CHECK(g_notifier);
+ if (!g_notifier->Notify())
+ exit(1);
+}
+
+// Lets the daemon fetch the exit notifier file descriptor.
+int GetExitNotifierFD() {
+ DCHECK(g_notifier);
+ return g_notifier->receiver_fd();
+}
+
+class ServerDelegate : public Daemon::ServerDelegate {
+ public:
+ ServerDelegate() : initialized_(false) {}
+
+ virtual ~ServerDelegate() {
+ if (!controller_thread_.get())
+ return;
+ // The DeviceController instance, if any, is constructed on the controller
+ // thread. Make sure that it gets deleted on that same thread. Note that
+ // DeleteSoon() is not used here since it would imply reading |controller_|
+ // from the main thread while it's set on the internal thread.
+ controller_thread_->message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&ServerDelegate::DeleteControllerOnInternalThread,
+ base::Unretained(this)));
+ }
+
+ void DeleteControllerOnInternalThread() {
+ DCHECK(
+ controller_thread_->message_loop_proxy()->RunsTasksOnCurrentThread());
+ controller_.reset();
+ }
+
+ // Daemon::ServerDelegate:
+ virtual void Init() OVERRIDE {
+ DCHECK(!g_notifier);
+ g_notifier = new forwarder2::PipeNotifier();
+ signal(SIGTERM, KillHandler);
+ signal(SIGINT, KillHandler);
+ controller_thread_.reset(new base::Thread("controller_thread"));
+ controller_thread_->Start();
+ }
+
+ virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE {
+ if (initialized_) {
+ client_socket->WriteString("OK");
+ return;
+ }
+ controller_thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&ServerDelegate::StartController, base::Unretained(this),
+ GetExitNotifierFD(), base::Passed(&client_socket)));
+ initialized_ = true;
+ }
+
+ private:
+ void StartController(int exit_notifier_fd, scoped_ptr<Socket> client_socket) {
+ DCHECK(!controller_.get());
+ scoped_ptr<DeviceController> controller(
+ DeviceController::Create(kUnixDomainSocketPath, exit_notifier_fd));
+ if (!controller.get()) {
+ client_socket->WriteString(
+ base::StringPrintf("ERROR: Could not initialize device controller "
+ "with ADB socket path: %s",
+ kUnixDomainSocketPath));
+ return;
+ }
+ controller_.swap(controller);
+ controller_->Start();
+ client_socket->WriteString("OK");
+ client_socket->Close();
+ }
+
+ scoped_ptr<DeviceController> controller_;
+ scoped_ptr<base::Thread> controller_thread_;
+ bool initialized_;
+};
+
+class ClientDelegate : public Daemon::ClientDelegate {
+ public:
+ ClientDelegate() : has_failed_(false) {}
+
+ bool has_failed() const { return has_failed_; }
+
+ // Daemon::ClientDelegate:
+ virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE {
+ char buf[kBufSize];
+ const int bytes_read = daemon_socket->Read(
+ buf, sizeof(buf) - 1 /* leave space for null terminator */);
+ CHECK_GT(bytes_read, 0);
+ DCHECK(bytes_read < sizeof(buf));
+ buf[bytes_read] = 0;
+ base::StringPiece msg(buf, bytes_read);
+ if (msg.starts_with("ERROR")) {
+ LOG(ERROR) << msg;
+ has_failed_ = true;
+ return;
+ }
+ }
+
+ private:
+ bool has_failed_;
+};
+
+int RunDeviceForwarder(int argc, char** argv) {
+ CommandLine::Init(argc, argv); // Needed by logging.
+ const bool kill_server = CommandLine::ForCurrentProcess()->HasSwitch(
+ "kill-server");
+ if ((kill_server && argc != 2) || (!kill_server && argc != 1)) {
+ std::cerr << "Usage: device_forwarder [--kill-server]" << std::endl;
+ return 1;
+ }
+ base::AtExitManager at_exit_manager; // Used by base::Thread.
+ ClientDelegate client_delegate;
+ ServerDelegate daemon_delegate;
+ const char kLogFilePath[] = ""; // Log to logcat.
+ Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate,
+ &daemon_delegate, &GetExitNotifierFD);
+
+ if (kill_server)
+ return !daemon.Kill();
+
+ if (!daemon.SpawnIfNeeded())
+ return 1;
+ return client_delegate.has_failed();
+}
+
+} // namespace
+} // namespace forwarder2
+
+int main(int argc, char** argv) {
+ return forwarder2::RunDeviceForwarder(argc, argv);
+}
diff --git a/chromium/tools/android/forwarder2/device_listener.cc b/chromium/tools/android/forwarder2/device_listener.cc
new file mode 100644
index 00000000000..1819a8a6edf
--- /dev/null
+++ b/chromium/tools/android/forwarder2/device_listener.cc
@@ -0,0 +1,148 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/device_listener.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/single_thread_task_runner.h"
+#include "tools/android/forwarder2/command.h"
+#include "tools/android/forwarder2/forwarder.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace forwarder2 {
+
+// static
+scoped_ptr<DeviceListener> DeviceListener::Create(
+ scoped_ptr<Socket> host_socket,
+ int listener_port,
+ const DeleteCallback& delete_callback) {
+ scoped_ptr<Socket> listener_socket(new Socket());
+ scoped_ptr<DeviceListener> device_listener;
+ if (!listener_socket->BindTcp("", listener_port)) {
+ LOG(ERROR) << "Device could not bind and listen to local port "
+ << listener_port;
+ SendCommand(command::BIND_ERROR, listener_port, host_socket.get());
+ return device_listener.Pass();
+ }
+ // In case the |listener_port_| was zero, GetPort() will return the
+ // currently (non-zero) allocated port for this socket.
+ listener_port = listener_socket->GetPort();
+ SendCommand(command::BIND_SUCCESS, listener_port, host_socket.get());
+ device_listener.reset(
+ new DeviceListener(
+ scoped_ptr<PipeNotifier>(new PipeNotifier()), listener_socket.Pass(),
+ host_socket.Pass(), listener_port, delete_callback));
+ return device_listener.Pass();
+}
+
+DeviceListener::~DeviceListener() {
+ DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread());
+ exit_notifier_->Notify();
+}
+
+void DeviceListener::Start() {
+ thread_.Start();
+ AcceptNextClientSoon();
+}
+
+void DeviceListener::SetAdbDataSocket(scoped_ptr<Socket> adb_data_socket) {
+ thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeviceListener::OnAdbDataSocketReceivedOnInternalThread,
+ base::Unretained(this), base::Passed(&adb_data_socket)));
+}
+
+DeviceListener::DeviceListener(scoped_ptr<PipeNotifier> pipe_notifier,
+ scoped_ptr<Socket> listener_socket,
+ scoped_ptr<Socket> host_socket,
+ int port,
+ const DeleteCallback& delete_callback)
+ : exit_notifier_(pipe_notifier.Pass()),
+ listener_socket_(listener_socket.Pass()),
+ host_socket_(host_socket.Pass()),
+ listener_port_(port),
+ delete_callback_(delete_callback),
+ deletion_task_runner_(base::MessageLoopProxy::current()),
+ thread_("DeviceListener") {
+ CHECK(host_socket_.get());
+ DCHECK(deletion_task_runner_.get());
+ DCHECK(exit_notifier_.get());
+ host_socket_->AddEventFd(exit_notifier_->receiver_fd());
+ listener_socket_->AddEventFd(exit_notifier_->receiver_fd());
+}
+
+void DeviceListener::AcceptNextClientSoon() {
+ thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeviceListener::AcceptClientOnInternalThread,
+ base::Unretained(this)));
+}
+
+void DeviceListener::AcceptClientOnInternalThread() {
+ device_data_socket_.reset(new Socket());
+ if (!listener_socket_->Accept(device_data_socket_.get())) {
+ if (listener_socket_->DidReceiveEvent()) {
+ LOG(INFO) << "Received exit notification, stopped accepting clients.";
+ SelfDelete();
+ return;
+ }
+ LOG(WARNING) << "Could not Accept in ListenerSocket.";
+ SendCommand(command::ACCEPT_ERROR, listener_port_, host_socket_.get());
+ SelfDelete();
+ return;
+ }
+ SendCommand(command::ACCEPT_SUCCESS, listener_port_, host_socket_.get());
+ if (!ReceivedCommand(command::HOST_SERVER_SUCCESS,
+ host_socket_.get())) {
+ SendCommand(command::ACK, listener_port_, host_socket_.get());
+ LOG(ERROR) << "Host could not connect to server.";
+ device_data_socket_->Close();
+ if (host_socket_->has_error()) {
+ LOG(ERROR) << "Adb Control connection lost. "
+ << "Listener port: " << listener_port_;
+ SelfDelete();
+ return;
+ }
+ // It can continue if the host forwarder could not connect to the host
+ // server but the control connection is still alive (no errors). The device
+ // acknowledged that (above), and it can re-try later.
+ AcceptNextClientSoon();
+ return;
+ }
+}
+
+void DeviceListener::OnAdbDataSocketReceivedOnInternalThread(
+ scoped_ptr<Socket> adb_data_socket) {
+ adb_data_socket_.swap(adb_data_socket);
+ SendCommand(command::ADB_DATA_SOCKET_SUCCESS, listener_port_,
+ host_socket_.get());
+ CHECK(adb_data_socket_.get());
+ StartForwarder(device_data_socket_.Pass(), adb_data_socket_.Pass());
+ AcceptNextClientSoon();
+}
+
+void DeviceListener::SelfDelete() {
+ if (!deletion_task_runner_->RunsTasksOnCurrentThread()) {
+ deletion_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DeviceListener::SelfDeleteOnDeletionTaskRunner,
+ delete_callback_, listener_port_));
+ return;
+ }
+ SelfDeleteOnDeletionTaskRunner(delete_callback_, listener_port_);
+}
+
+// static
+void DeviceListener::SelfDeleteOnDeletionTaskRunner(
+ const DeleteCallback& delete_callback,
+ int listener_port) {
+ delete_callback.Run(listener_port);
+}
+
+} // namespace forwarder
diff --git a/chromium/tools/android/forwarder2/device_listener.h b/chromium/tools/android/forwarder2/device_listener.h
new file mode 100644
index 00000000000..2a698231963
--- /dev/null
+++ b/chromium/tools/android/forwarder2/device_listener.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_
+#define TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
+#include "tools/android/forwarder2/pipe_notifier.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace forwarder2 {
+
+class Forwarder;
+
+// A DeviceListener instance is used in the device_forwarder program to bind to
+// a specific device-side |port| and wait for client connections. When a
+// connection happens, it informs the corresponding HostController instance
+// running on the host, through |host_socket|. Then the class expects a call to
+// its SetAdbDataSocket() method (performed by the device controller) once the
+// host opened a new connection to the device. When this happens, a new internal
+// Forwarder instance is started.
+// Note that instances of this class are owned by the device controller which
+// creates and destroys them on the same thread. In case an internal error
+// happens on the DeviceListener's internal thread, the DeviceListener
+// can also self-delete by executing the user-provided callback on the thread
+// the DeviceListener was created on.
+// Note that the DeviceListener's destructor joins its internal thread (i.e.
+// waits for its completion) which means that the internal thread is guaranteed
+// not to be running anymore once the object is deleted.
+class DeviceListener {
+ public:
+ // Callback that is used for self-deletion as a way to let the device
+ // controller perform some additional cleanup work (e.g. removing the device
+ // listener instance from its internal map before deleting it).
+ typedef base::Callback<void (int /* listener port */)> DeleteCallback;
+
+ static scoped_ptr<DeviceListener> Create(
+ scoped_ptr<Socket> host_socket,
+ int port,
+ const DeleteCallback& delete_callback);
+
+ ~DeviceListener();
+
+ void Start();
+
+ void SetAdbDataSocket(scoped_ptr<Socket> adb_data_socket);
+
+ int listener_port() const { return listener_port_; }
+
+ private:
+ DeviceListener(scoped_ptr<PipeNotifier> pipe_notifier,
+ scoped_ptr<Socket> listener_socket,
+ scoped_ptr<Socket> host_socket,
+ int port,
+ const DeleteCallback& delete_callback);
+
+ // Pushes an AcceptClientOnInternalThread() task to the internal thread's
+ // message queue in order to wait for a new client soon.
+ void AcceptNextClientSoon();
+
+ void AcceptClientOnInternalThread();
+
+ void OnAdbDataSocketReceivedOnInternalThread(
+ scoped_ptr<Socket> adb_data_socket);
+
+ void SelfDelete();
+
+ // Note that this can be called after the DeviceListener instance gets deleted
+ // which is why this method is static.
+ static void SelfDeleteOnDeletionTaskRunner(
+ const DeleteCallback& delete_callback,
+ int listener_port);
+
+ // Used for the listener thread to be notified on destruction. We have one
+ // notifier per Listener thread since each Listener thread may be requested to
+ // exit for different reasons independently from each other and independent
+ // from the main program, ex. when the host requests to forward/listen the
+ // same port again. Both the |host_socket_| and |listener_socket_|
+ // must share the same receiver file descriptor from |exit_notifier_| and it
+ // is set in the constructor.
+ const scoped_ptr<PipeNotifier> exit_notifier_;
+ // The local device listener socket for accepting connections from the local
+ // port (listener_port_).
+ const scoped_ptr<Socket> listener_socket_;
+ // The listener socket for sending control commands.
+ const scoped_ptr<Socket> host_socket_;
+ scoped_ptr<Socket> device_data_socket_;
+ // This is the adb connection to transport the actual data, used for creating
+ // the forwarder. Ownership transferred to the Forwarder.
+ scoped_ptr<Socket> adb_data_socket_;
+ const int listener_port_;
+ const DeleteCallback delete_callback_;
+ // Task runner used for deletion set at construction time (i.e. the object is
+ // deleted on the same thread it is created on).
+ scoped_refptr<base::SingleThreadTaskRunner> deletion_task_runner_;
+ base::Thread thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceListener);
+};
+
+} // namespace forwarder
+
+#endif // TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_
diff --git a/chromium/tools/android/forwarder2/forwarder.cc b/chromium/tools/android/forwarder2/forwarder.cc
new file mode 100644
index 00000000000..df4c29cf9ff
--- /dev/null
+++ b/chromium/tools/android/forwarder2/forwarder.cc
@@ -0,0 +1,171 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/forwarder.h"
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/single_thread_task_runner.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace forwarder2 {
+namespace {
+
+// Helper class to buffer reads and writes from one socket to another.
+class BufferedCopier {
+ public:
+ // Does NOT own the pointers.
+ BufferedCopier(Socket* socket_from,
+ Socket* socket_to)
+ : socket_from_(socket_from),
+ socket_to_(socket_to),
+ bytes_read_(0),
+ write_offset_(0) {
+ }
+
+ bool AddToReadSet(fd_set* read_fds) {
+ if (bytes_read_ == 0)
+ return socket_from_->AddFdToSet(read_fds);
+ return false;
+ }
+
+ bool AddToWriteSet(fd_set* write_fds) {
+ if (write_offset_ < bytes_read_)
+ return socket_to_->AddFdToSet(write_fds);
+ return false;
+ }
+
+ bool TryRead(const fd_set& read_fds) {
+ if (!socket_from_->IsFdInSet(read_fds))
+ return false;
+ if (bytes_read_ != 0) // Can't read.
+ return false;
+ int ret = socket_from_->Read(buffer_, kBufferSize);
+ if (ret > 0) {
+ bytes_read_ = ret;
+ return true;
+ }
+ return false;
+ }
+
+ bool TryWrite(const fd_set& write_fds) {
+ if (!socket_to_->IsFdInSet(write_fds))
+ return false;
+ if (write_offset_ >= bytes_read_) // Nothing to write.
+ return false;
+ int ret = socket_to_->Write(buffer_ + write_offset_,
+ bytes_read_ - write_offset_);
+ if (ret > 0) {
+ write_offset_ += ret;
+ if (write_offset_ == bytes_read_) {
+ write_offset_ = 0;
+ bytes_read_ = 0;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ // Not owned.
+ Socket* socket_from_;
+ Socket* socket_to_;
+
+ // A big buffer to let our file-over-http bridge work more like real file.
+ static const int kBufferSize = 1024 * 128;
+ int bytes_read_;
+ int write_offset_;
+ char buffer_[kBufferSize];
+
+ DISALLOW_COPY_AND_ASSIGN(BufferedCopier);
+};
+
+// Internal class that wraps a helper thread to forward traffic between
+// |socket1| and |socket2|. After creating a new instance, call its Start()
+// method to launch operations. Thread stops automatically if one of the socket
+// disconnects, but ensures that all buffered writes to the other, still alive,
+// socket, are written first. When this happens, the instance will delete itself
+// automatically.
+// Note that the instance will always be destroyed on the same thread that
+// created it.
+class Forwarder {
+ public:
+ Forwarder(scoped_ptr<Socket> socket1, scoped_ptr<Socket> socket2)
+ : socket1_(socket1.Pass()),
+ socket2_(socket2.Pass()),
+ destructor_runner_(base::MessageLoopProxy::current()),
+ thread_("ForwarderThread") {
+ }
+
+ void Start() {
+ thread_.Start();
+ thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&Forwarder::ThreadHandler, base::Unretained(this)));
+ }
+
+ private:
+ void ThreadHandler() {
+ const int nfds = Socket::GetHighestFileDescriptor(*socket1_, *socket2_) + 1;
+ fd_set read_fds;
+ fd_set write_fds;
+
+ // Copy from socket1 to socket2
+ BufferedCopier buffer1(socket1_.get(), socket2_.get());
+ // Copy from socket2 to socket1
+ BufferedCopier buffer2(socket2_.get(), socket1_.get());
+
+ bool run = true;
+ while (run) {
+ FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
+
+ buffer1.AddToReadSet(&read_fds);
+ buffer2.AddToReadSet(&read_fds);
+ buffer1.AddToWriteSet(&write_fds);
+ buffer2.AddToWriteSet(&write_fds);
+
+ if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, NULL)) <= 0) {
+ PLOG(ERROR) << "select";
+ break;
+ }
+ // When a socket in the read set closes the connection, select() returns
+ // with that socket descriptor set as "ready to read". When we call
+ // TryRead() below, it will return false, but the while loop will continue
+ // to run until all the write operations are finished, to make sure the
+ // buffers are completely flushed out.
+
+ // Keep running while we have some operation to do.
+ run = buffer1.TryRead(read_fds);
+ run = run || buffer2.TryRead(read_fds);
+ run = run || buffer1.TryWrite(write_fds);
+ run = run || buffer2.TryWrite(write_fds);
+ }
+
+ // Note that the thread that |destruction_runner_| runs tasks on could be
+ // temporarily blocked on I/O (e.g. select()) therefore it is safer to close
+ // the sockets now rather than relying on the destructor.
+ socket1_.reset();
+ socket2_.reset();
+
+ // Note that base::Thread must be destroyed on the thread it was created on.
+ destructor_runner_->DeleteSoon(FROM_HERE, this);
+ }
+
+ scoped_ptr<Socket> socket1_;
+ scoped_ptr<Socket> socket2_;
+ scoped_refptr<base::SingleThreadTaskRunner> destructor_runner_;
+ base::Thread thread_;
+};
+
+} // namespace
+
+void StartForwarder(scoped_ptr<Socket> socket1, scoped_ptr<Socket> socket2) {
+ (new Forwarder(socket1.Pass(), socket2.Pass()))->Start();
+}
+
+} // namespace forwarder2
diff --git a/chromium/tools/android/forwarder2/forwarder.gyp b/chromium/tools/android/forwarder2/forwarder.gyp
new file mode 100644
index 00000000000..fdc19aa4cef
--- /dev/null
+++ b/chromium/tools/android/forwarder2/forwarder.gyp
@@ -0,0 +1,85 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'forwarder2',
+ 'type': 'none',
+ 'dependencies': [
+ 'device_forwarder',
+ 'host_forwarder#host',
+ ],
+ # For the component build, ensure dependent shared libraries are stripped
+ # and put alongside forwarder to simplify pushing to the device.
+ 'variables': {
+ 'output_dir': '<(PRODUCT_DIR)/forwarder_dist/',
+ 'native_binary': '<(PRODUCT_DIR)/device_forwarder',
+ },
+ 'includes': ['../../../build/android/native_app_dependencies.gypi'],
+ },
+ {
+ 'target_name': 'device_forwarder',
+ 'type': 'executable',
+ 'toolsets': ['target'],
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../common/common.gyp:android_tools_common',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ 'conditions': [
+ # Warning: A PIE tool cannot run on ICS 4.0.4, so only
+ # build it as position-independent when ASAN
+ # is activated. See b/6587214 for details.
+ [ 'asan==1', {
+ 'cflags': [
+ '-fPIE',
+ ],
+ 'ldflags': [
+ '-pie',
+ ],
+ }],
+ ],
+ 'sources': [
+ 'command.cc',
+ 'common.cc',
+ 'daemon.cc',
+ 'device_controller.cc',
+ 'device_forwarder_main.cc',
+ 'device_listener.cc',
+ 'forwarder.cc',
+ 'pipe_notifier.cc',
+ 'socket.cc',
+ ],
+ },
+ {
+ 'target_name': 'host_forwarder',
+ 'type': 'executable',
+ 'toolsets': ['host'],
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../common/common.gyp:android_tools_common',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ 'sources': [
+ 'command.cc',
+ 'common.cc',
+ 'daemon.cc',
+ 'forwarder.cc',
+ 'host_controller.cc',
+ 'host_forwarder_main.cc',
+ 'pipe_notifier.cc',
+ 'socket.cc',
+ # TODO(pliard): Remove this. This is needed to avoid undefined
+ # references at link time.
+ '../../../base/message_loop/message_pump_glib.cc',
+ '../../../base/message_loop/message_pump_gtk.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/android/forwarder2/forwarder.h b/chromium/tools/android/forwarder2/forwarder.h
new file mode 100644
index 00000000000..651b5e80f71
--- /dev/null
+++ b/chromium/tools/android/forwarder2/forwarder.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_FORWARDER_H_
+#define TOOLS_ANDROID_FORWARDER2_FORWARDER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
+
+namespace forwarder2 {
+
+class Socket;
+
+void StartForwarder(scoped_ptr<Socket> socket1, scoped_ptr<Socket> socket2);
+
+} // namespace forwarder2
+
+#endif // TOOLS_ANDROID_FORWARDER2_FORWARDER_H_
diff --git a/chromium/tools/android/forwarder2/host_controller.cc b/chromium/tools/android/forwarder2/host_controller.cc
new file mode 100644
index 00000000000..1588e7291b2
--- /dev/null
+++ b/chromium/tools/android/forwarder2/host_controller.cc
@@ -0,0 +1,186 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/host_controller.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "tools/android/forwarder2/command.h"
+#include "tools/android/forwarder2/forwarder.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace forwarder2 {
+
+// static
+scoped_ptr<HostController> HostController::Create(
+ int device_port,
+ int host_port,
+ int adb_port,
+ int exit_notifier_fd,
+ const DeletionCallback& deletion_callback) {
+ scoped_ptr<HostController> host_controller;
+ scoped_ptr<PipeNotifier> delete_controller_notifier(new PipeNotifier());
+ scoped_ptr<Socket> adb_control_socket(new Socket());
+ adb_control_socket->AddEventFd(exit_notifier_fd);
+ adb_control_socket->AddEventFd(delete_controller_notifier->receiver_fd());
+ if (!adb_control_socket->ConnectTcp(std::string(), adb_port)) {
+ LOG(ERROR) << "Could not connect HostController socket on port: "
+ << adb_port;
+ return host_controller.Pass();
+ }
+ // Send the command to the device start listening to the "device_forward_port"
+ bool send_command_success = SendCommand(
+ command::LISTEN, device_port, adb_control_socket.get());
+ CHECK(send_command_success);
+ int device_port_allocated;
+ command::Type command;
+ if (!ReadCommand(
+ adb_control_socket.get(), &device_port_allocated, &command) ||
+ command != command::BIND_SUCCESS) {
+ LOG(ERROR) << "Device binding error using port " << device_port;
+ return host_controller.Pass();
+ }
+ host_controller.reset(
+ new HostController(
+ device_port_allocated, host_port, adb_port, exit_notifier_fd,
+ deletion_callback, adb_control_socket.Pass(),
+ delete_controller_notifier.Pass()));
+ return host_controller.Pass();
+}
+
+HostController::~HostController() {
+ DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread());
+ delete_controller_notifier_->Notify();
+ // Note that the Forwarder instance (that also received a delete notification)
+ // might still be running on its own thread at this point. This is not a
+ // problem since it will self-delete once the socket that it is operating on
+ // is closed.
+}
+
+void HostController::Start() {
+ thread_.Start();
+ ReadNextCommandSoon();
+}
+
+HostController::HostController(
+ int device_port,
+ int host_port,
+ int adb_port,
+ int exit_notifier_fd,
+ const DeletionCallback& deletion_callback,
+ scoped_ptr<Socket> adb_control_socket,
+ scoped_ptr<PipeNotifier> delete_controller_notifier)
+ : device_port_(device_port),
+ host_port_(host_port),
+ adb_port_(adb_port),
+ global_exit_notifier_fd_(exit_notifier_fd),
+ deletion_callback_(deletion_callback),
+ adb_control_socket_(adb_control_socket.Pass()),
+ delete_controller_notifier_(delete_controller_notifier.Pass()),
+ deletion_task_runner_(base::MessageLoopProxy::current()),
+ thread_("HostControllerThread") {
+}
+
+void HostController::ReadNextCommandSoon() {
+ thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&HostController::ReadCommandOnInternalThread,
+ base::Unretained(this)));
+}
+
+void HostController::ReadCommandOnInternalThread() {
+ if (!ReceivedCommand(command::ACCEPT_SUCCESS, adb_control_socket_.get())) {
+ SelfDelete();
+ return;
+ }
+ // Try to connect to host server.
+ scoped_ptr<Socket> host_server_data_socket(CreateSocket());
+ if (!host_server_data_socket->ConnectTcp(std::string(), host_port_)) {
+ LOG(ERROR) << "Could not Connect HostServerData socket on port: "
+ << host_port_;
+ SendCommand(
+ command::HOST_SERVER_ERROR, device_port_, adb_control_socket_.get());
+ if (ReceivedCommand(command::ACK, adb_control_socket_.get())) {
+ // It can continue if the host forwarder could not connect to the host
+ // server but the device acknowledged that, so that the device could
+ // re-try later.
+ ReadNextCommandSoon();
+ return;
+ }
+ SelfDelete();
+ return;
+ }
+ SendCommand(
+ command::HOST_SERVER_SUCCESS, device_port_, adb_control_socket_.get());
+ StartForwarder(host_server_data_socket.Pass());
+ ReadNextCommandSoon();
+}
+
+void HostController::StartForwarder(
+ scoped_ptr<Socket> host_server_data_socket) {
+ scoped_ptr<Socket> adb_data_socket(CreateSocket());
+ if (!adb_data_socket->ConnectTcp("", adb_port_)) {
+ LOG(ERROR) << "Could not connect AdbDataSocket on port: " << adb_port_;
+ SelfDelete();
+ return;
+ }
+ // Open the Adb data connection, and send a command with the
+ // |device_forward_port| as a way for the device to identify the connection.
+ SendCommand(command::DATA_CONNECTION, device_port_, adb_data_socket.get());
+
+ // Check that the device received the new Adb Data Connection. Note that this
+ // check is done through the |adb_control_socket_| that is handled in the
+ // DeviceListener thread just after the call to WaitForAdbDataSocket().
+ if (!ReceivedCommand(command::ADB_DATA_SOCKET_SUCCESS,
+ adb_control_socket_.get())) {
+ LOG(ERROR) << "Device could not handle the new Adb Data Connection.";
+ SelfDelete();
+ return;
+ }
+ forwarder2::StartForwarder(
+ host_server_data_socket.Pass(), adb_data_socket.Pass());
+}
+
+scoped_ptr<Socket> HostController::CreateSocket() {
+ scoped_ptr<Socket> socket(new Socket());
+ socket->AddEventFd(global_exit_notifier_fd_);
+ socket->AddEventFd(delete_controller_notifier_->receiver_fd());
+ return socket.Pass();
+}
+
+void HostController::SelfDelete() {
+ scoped_ptr<HostController> self_deleter(this);
+ deletion_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&HostController::SelfDeleteOnDeletionTaskRunner,
+ deletion_callback_, base::Passed(&self_deleter)));
+ // Tell the device to delete its corresponding controller instance before we
+ // self-delete.
+ Socket socket;
+ if (!socket.ConnectTcp("", adb_port_)) {
+ LOG(ERROR) << "Could not connect to device on port " << adb_port_;
+ return;
+ }
+ if (!SendCommand(command::UNLISTEN, device_port_, &socket)) {
+ LOG(ERROR) << "Could not send unmap command for port " << device_port_;
+ return;
+ }
+ if (!ReceivedCommand(command::UNLISTEN_SUCCESS, &socket)) {
+ LOG(ERROR) << "Unamp command failed for port " << device_port_;
+ return;
+ }
+}
+
+// static
+void HostController::SelfDeleteOnDeletionTaskRunner(
+ const DeletionCallback& deletion_callback,
+ scoped_ptr<HostController> controller) {
+ deletion_callback.Run(controller.Pass());
+}
+
+} // namespace forwarder2
diff --git a/chromium/tools/android/forwarder2/host_controller.h b/chromium/tools/android/forwarder2/host_controller.h
new file mode 100644
index 00000000000..aaedb945e8e
--- /dev/null
+++ b/chromium/tools/android/forwarder2/host_controller.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_HOST_CONTROLLER_H_
+#define TOOLS_ANDROID_FORWARDER2_HOST_CONTROLLER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
+#include "tools/android/forwarder2/pipe_notifier.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace forwarder2 {
+
+// This class partners with DeviceController and has the same lifetime and
+// threading characteristics as DeviceListener. In a nutshell, this class
+// operates on its own thread and is destroyed on the thread it was constructed
+// on. The class' deletion can happen in two different ways:
+// - Its destructor was called by its owner (HostControllersManager).
+// - Its internal thread requested self-deletion after an error happened. In
+// this case the owner (HostControllersManager) is notified on the
+// construction thread through the provided DeletionCallback invoked with the
+// HostController instance. When this callback is invoked, it's up to the
+// owner to delete the instance.
+class HostController {
+ public:
+ // Callback used for self-deletion that lets the client perform some cleanup
+ // work before deleting the HostController instance.
+ typedef base::Callback<void (scoped_ptr<HostController>)> DeletionCallback;
+
+ // If |device_port| is zero then a dynamic port is allocated (and retrievable
+ // through device_port() below).
+ static scoped_ptr<HostController> Create(
+ int device_port,
+ int host_port,
+ int adb_port,
+ int exit_notifier_fd,
+ const DeletionCallback& deletion_callback);
+
+ ~HostController();
+
+ // Starts the internal controller thread.
+ void Start();
+
+ int adb_port() const { return adb_port_; }
+
+ int device_port() const { return device_port_; }
+
+ private:
+ HostController(int device_port,
+ int host_port,
+ int adb_port,
+ int exit_notifier_fd,
+ const DeletionCallback& deletion_callback,
+ scoped_ptr<Socket> adb_control_socket,
+ scoped_ptr<PipeNotifier> delete_controller_notifier);
+
+ void ReadNextCommandSoon();
+ void ReadCommandOnInternalThread();
+
+ void StartForwarder(scoped_ptr<Socket> host_server_data_socket);
+
+ // Helper method that creates a socket and adds the appropriate event file
+ // descriptors.
+ scoped_ptr<Socket> CreateSocket();
+
+ void SelfDelete();
+
+ static void SelfDeleteOnDeletionTaskRunner(
+ const DeletionCallback& deletion_callback,
+ scoped_ptr<HostController> controller);
+
+ const int device_port_;
+ const int host_port_;
+ const int adb_port_;
+ // Used to notify the controller when the process is killed.
+ const int global_exit_notifier_fd_;
+ // Used to let the client delete the instance in case an error happened.
+ const DeletionCallback deletion_callback_;
+ scoped_ptr<Socket> adb_control_socket_;
+ scoped_ptr<PipeNotifier> delete_controller_notifier_;
+ // Used to cancel the pending blocking IO operations when the host controller
+ // instance is deleted.
+ // Task runner used for deletion set at construction time (i.e. the object is
+ // deleted on the same thread it is created on).
+ const scoped_refptr<base::SingleThreadTaskRunner> deletion_task_runner_;
+ base::Thread thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostController);
+};
+
+} // namespace forwarder2
+
+#endif // TOOLS_ANDROID_FORWARDER2_HOST_CONTROLLER_H_
diff --git a/chromium/tools/android/forwarder2/host_forwarder_main.cc b/chromium/tools/android/forwarder2/host_forwarder_main.cc
new file mode 100644
index 00000000000..1071aa7dd42
--- /dev/null
+++ b/chromium/tools/android/forwarder2/host_forwarder_main.cc
@@ -0,0 +1,414 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <cstdio>
+#include <iostream>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/at_exit.h"
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/containers/hash_tables.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/memory/weak_ptr.h"
+#include "base/pickle.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/safe_strerror_posix.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/task_runner.h"
+#include "base/threading/thread.h"
+#include "tools/android/forwarder2/common.h"
+#include "tools/android/forwarder2/daemon.h"
+#include "tools/android/forwarder2/host_controller.h"
+#include "tools/android/forwarder2/pipe_notifier.h"
+#include "tools/android/forwarder2/socket.h"
+
+namespace forwarder2 {
+namespace {
+
+const char kLogFilePath[] = "/tmp/host_forwarder_log";
+const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon";
+
+const char kKillServerCommand[] = "kill-server";
+const char kForwardCommand[] = "forward";
+
+const int kBufSize = 256;
+
+// Needs to be global to be able to be accessed from the signal handler.
+PipeNotifier* g_notifier = NULL;
+
+// Lets the daemon fetch the exit notifier file descriptor.
+int GetExitNotifierFD() {
+ DCHECK(g_notifier);
+ return g_notifier->receiver_fd();
+}
+
+void KillHandler(int signal_number) {
+ char buf[kBufSize];
+ if (signal_number != SIGTERM && signal_number != SIGINT) {
+ snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number);
+ SIGNAL_SAFE_LOG(WARNING, buf);
+ return;
+ }
+ snprintf(buf, sizeof(buf), "Received signal %d.", signal_number);
+ SIGNAL_SAFE_LOG(WARNING, buf);
+ static int s_kill_handler_count = 0;
+ CHECK(g_notifier);
+ // If for some reason the forwarder get stuck in any socket waiting forever,
+ // we can send a SIGKILL or SIGINT three times to force it die
+ // (non-nicely). This is useful when debugging.
+ ++s_kill_handler_count;
+ if (!g_notifier->Notify() || s_kill_handler_count > 2)
+ exit(1);
+}
+
+// Manages HostController instances. There is one HostController instance for
+// each connection being forwarded. Note that forwarding can happen with many
+// devices (identified with a serial id).
+class HostControllersManager {
+ public:
+ HostControllersManager()
+ : weak_ptr_factory_(this),
+ controllers_(new HostControllerMap()),
+ has_failed_(false) {
+ }
+
+ ~HostControllersManager() {
+ if (!thread_.get())
+ return;
+ // Delete the controllers on the thread they were created on.
+ thread_->message_loop_proxy()->DeleteSoon(
+ FROM_HERE, controllers_.release());
+ }
+
+ void HandleRequest(const std::string& device_serial,
+ int device_port,
+ int host_port,
+ scoped_ptr<Socket> client_socket) {
+ // Lazy initialize so that the CLI process doesn't get this thread created.
+ InitOnce();
+ thread_->message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &HostControllersManager::HandleRequestOnInternalThread,
+ base::Unretained(this), device_serial, device_port, host_port,
+ base::Passed(&client_socket)));
+ }
+
+ bool has_failed() const { return has_failed_; }
+
+ private:
+ typedef base::hash_map<
+ std::string, linked_ptr<HostController> > HostControllerMap;
+
+ static std::string MakeHostControllerMapKey(int adb_port, int device_port) {
+ return base::StringPrintf("%d:%d", adb_port, device_port);
+ }
+
+ void InitOnce() {
+ if (thread_.get())
+ return;
+ at_exit_manager_.reset(new base::AtExitManager());
+ thread_.reset(new base::Thread("HostControllersManagerThread"));
+ thread_->Start();
+ }
+
+ // Invoked when a HostController instance reports an error (e.g. due to a
+ // device connectivity issue). Note that this could be called after the
+ // controller manager was destroyed which is why a weak pointer is used.
+ static void DeleteHostController(
+ const base::WeakPtr<HostControllersManager>& manager_ptr,
+ scoped_ptr<HostController> host_controller) {
+ HostController* const controller = host_controller.release();
+ HostControllersManager* const manager = manager_ptr.get();
+ if (!manager) {
+ // Note that |controller| is not leaked in this case since the host
+ // controllers manager owns the controllers. If the manager was deleted
+ // then all the controllers (including |controller|) were also deleted.
+ return;
+ }
+ DCHECK(manager->thread_->message_loop_proxy()->RunsTasksOnCurrentThread());
+ // Note that this will delete |controller| which is owned by the map.
+ manager->controllers_->erase(
+ MakeHostControllerMapKey(controller->adb_port(),
+ controller->device_port()));
+ }
+
+ void HandleRequestOnInternalThread(const std::string& device_serial,
+ int device_port,
+ int host_port,
+ scoped_ptr<Socket> client_socket) {
+ const int adb_port = GetAdbPortForDevice(device_serial);
+ if (adb_port < 0) {
+ SendMessage(
+ "ERROR: could not get adb port for device. You might need to add "
+ "'adb' to your PATH or provide the device serial id.",
+ client_socket.get());
+ return;
+ }
+ if (device_port < 0) {
+ // Remove the previously created host controller.
+ const std::string controller_key = MakeHostControllerMapKey(
+ adb_port, -device_port);
+ const HostControllerMap::size_type removed_elements = controllers_->erase(
+ controller_key);
+ SendMessage(
+ !removed_elements ? "ERROR: could not unmap port" : "OK",
+ client_socket.get());
+ return;
+ }
+ if (host_port < 0) {
+ SendMessage("ERROR: missing host port", client_socket.get());
+ return;
+ }
+ const bool use_dynamic_port_allocation = device_port == 0;
+ if (!use_dynamic_port_allocation) {
+ const std::string controller_key = MakeHostControllerMapKey(
+ adb_port, device_port);
+ if (controllers_->find(controller_key) != controllers_->end()) {
+ LOG(INFO) << "Already forwarding device port " << device_port
+ << " to host port " << host_port;
+ SendMessage(base::StringPrintf("%d:%d", device_port, host_port),
+ client_socket.get());
+ return;
+ }
+ }
+ // Create a new host controller.
+ scoped_ptr<HostController> host_controller(
+ HostController::Create(
+ device_port, host_port, adb_port, GetExitNotifierFD(),
+ base::Bind(&HostControllersManager::DeleteHostController,
+ weak_ptr_factory_.GetWeakPtr())));
+ if (!host_controller.get()) {
+ has_failed_ = true;
+ SendMessage("ERROR: Connection to device failed.", client_socket.get());
+ return;
+ }
+ // Get the current allocated port.
+ device_port = host_controller->device_port();
+ LOG(INFO) << "Forwarding device port " << device_port << " to host port "
+ << host_port;
+ const std::string msg = base::StringPrintf("%d:%d", device_port, host_port);
+ if (!SendMessage(msg, client_socket.get()))
+ return;
+ host_controller->Start();
+ controllers_->insert(
+ std::make_pair(MakeHostControllerMapKey(adb_port, device_port),
+ linked_ptr<HostController>(host_controller.release())));
+ }
+
+ int GetAdbPortForDevice(const std::string& device_serial) {
+ base::hash_map<std::string, int>::const_iterator it =
+ device_serial_to_adb_port_map_.find(device_serial);
+ if (it != device_serial_to_adb_port_map_.end())
+ return it->second;
+ Socket bind_socket;
+ CHECK(bind_socket.BindTcp("127.0.0.1", 0));
+ const int port = bind_socket.GetPort();
+ bind_socket.Close();
+ const std::string serial_part = device_serial.empty() ?
+ std::string() : std::string("-s ") + device_serial;
+ const std::string command = base::StringPrintf(
+ "adb %s forward tcp:%d localabstract:chrome_device_forwarder",
+ device_serial.empty() ? "" : serial_part.c_str(),
+ port);
+ LOG(INFO) << command;
+ const int ret = system(command.c_str());
+ if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
+ return -1;
+ device_serial_to_adb_port_map_[device_serial] = port;
+ return port;
+ }
+
+ bool SendMessage(const std::string& msg, Socket* client_socket) {
+ bool result = client_socket->WriteString(msg);
+ DCHECK(result);
+ if (!result)
+ has_failed_ = true;
+ return result;
+ }
+
+ base::WeakPtrFactory<HostControllersManager> weak_ptr_factory_;
+ base::hash_map<std::string, int> device_serial_to_adb_port_map_;
+ scoped_ptr<HostControllerMap> controllers_;
+ bool has_failed_;
+ scoped_ptr<base::AtExitManager> at_exit_manager_; // Needed by base::Thread.
+ scoped_ptr<base::Thread> thread_;
+};
+
+class ServerDelegate : public Daemon::ServerDelegate {
+ public:
+ ServerDelegate() : has_failed_(false) {}
+
+ bool has_failed() const {
+ return has_failed_ || controllers_manager_.has_failed();
+ }
+
+ // Daemon::ServerDelegate:
+ virtual void Init() OVERRIDE {
+ LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
+ DCHECK(!g_notifier);
+ g_notifier = new PipeNotifier();
+ signal(SIGTERM, KillHandler);
+ signal(SIGINT, KillHandler);
+ }
+
+ virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE {
+ char buf[kBufSize];
+ const int bytes_read = client_socket->Read(buf, sizeof(buf));
+ if (bytes_read <= 0) {
+ if (client_socket->DidReceiveEvent())
+ return;
+ PError("Read()");
+ has_failed_ = true;
+ return;
+ }
+ const Pickle command_pickle(buf, bytes_read);
+ PickleIterator pickle_it(command_pickle);
+ std::string device_serial;
+ CHECK(pickle_it.ReadString(&device_serial));
+ int device_port;
+ if (!pickle_it.ReadInt(&device_port)) {
+ client_socket->WriteString("ERROR: missing device port");
+ return;
+ }
+ int host_port;
+ if (!pickle_it.ReadInt(&host_port))
+ host_port = -1;
+ controllers_manager_.HandleRequest(
+ device_serial, device_port, host_port, client_socket.Pass());
+ }
+
+ private:
+ bool has_failed_;
+ HostControllersManager controllers_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServerDelegate);
+};
+
+class ClientDelegate : public Daemon::ClientDelegate {
+ public:
+ ClientDelegate(const Pickle& command_pickle)
+ : command_pickle_(command_pickle),
+ has_failed_(false) {
+ }
+
+ bool has_failed() const { return has_failed_; }
+
+ // Daemon::ClientDelegate:
+ virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE {
+ // Send the forward command to the daemon.
+ CHECK_EQ(command_pickle_.size(),
+ daemon_socket->WriteNumBytes(command_pickle_.data(),
+ command_pickle_.size()));
+ char buf[kBufSize];
+ const int bytes_read = daemon_socket->Read(
+ buf, sizeof(buf) - 1 /* leave space for null terminator */);
+ CHECK_GT(bytes_read, 0);
+ DCHECK(bytes_read < sizeof(buf));
+ buf[bytes_read] = 0;
+ base::StringPiece msg(buf, bytes_read);
+ if (msg.starts_with("ERROR")) {
+ LOG(ERROR) << msg;
+ has_failed_ = true;
+ return;
+ }
+ printf("%s\n", buf);
+ }
+
+ private:
+ const Pickle command_pickle_;
+ bool has_failed_;
+};
+
+void ExitWithUsage() {
+ std::cerr << "Usage: host_forwarder [options]\n\n"
+ "Options:\n"
+ " --serial-id=[0-9A-Z]{16}]\n"
+ " --map DEVICE_PORT HOST_PORT\n"
+ " --unmap DEVICE_PORT\n"
+ " --kill-server\n";
+ exit(1);
+}
+
+int PortToInt(const std::string& s) {
+ int value;
+ // Note that 0 is a valid port (used for dynamic port allocation).
+ if (!base::StringToInt(s, &value) || value < 0 ||
+ value > std::numeric_limits<uint16>::max()) {
+ LOG(ERROR) << "Could not convert string " << s << " to port";
+ ExitWithUsage();
+ }
+ return value;
+}
+
+int RunHostForwarder(int argc, char** argv) {
+ CommandLine::Init(argc, argv);
+ const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
+ bool kill_server = false;
+
+ Pickle pickle;
+ pickle.WriteString(
+ cmd_line.HasSwitch("serial-id") ?
+ cmd_line.GetSwitchValueASCII("serial-id") : std::string());
+
+ const std::vector<std::string> args = cmd_line.GetArgs();
+ if (cmd_line.HasSwitch("kill-server")) {
+ kill_server = true;
+ } else if (cmd_line.HasSwitch("unmap")) {
+ if (args.size() != 1)
+ ExitWithUsage();
+ // Note the minus sign below.
+ pickle.WriteInt(-PortToInt(args[0]));
+ } else if (cmd_line.HasSwitch("map")) {
+ if (args.size() != 2)
+ ExitWithUsage();
+ pickle.WriteInt(PortToInt(args[0]));
+ pickle.WriteInt(PortToInt(args[1]));
+ } else {
+ ExitWithUsage();
+ }
+
+ if (kill_server && args.size() > 0)
+ ExitWithUsage();
+
+ ClientDelegate client_delegate(pickle);
+ ServerDelegate daemon_delegate;
+ Daemon daemon(
+ kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate,
+ &GetExitNotifierFD);
+
+ if (kill_server)
+ return !daemon.Kill();
+ if (!daemon.SpawnIfNeeded())
+ return 1;
+
+ return client_delegate.has_failed() || daemon_delegate.has_failed();
+}
+
+} // namespace
+} // namespace forwarder2
+
+int main(int argc, char** argv) {
+ return forwarder2::RunHostForwarder(argc, argv);
+}
diff --git a/chromium/tools/android/forwarder2/pipe_notifier.cc b/chromium/tools/android/forwarder2/pipe_notifier.cc
new file mode 100644
index 00000000000..3aba18b0d02
--- /dev/null
+++ b/chromium/tools/android/forwarder2/pipe_notifier.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/pipe_notifier.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/safe_strerror_posix.h"
+
+namespace forwarder2 {
+
+PipeNotifier::PipeNotifier() {
+ int pipe_fd[2];
+ int ret = pipe(pipe_fd);
+ CHECK_EQ(0, ret);
+ receiver_fd_ = pipe_fd[0];
+ sender_fd_ = pipe_fd[1];
+ fcntl(sender_fd_, F_SETFL, O_NONBLOCK);
+}
+
+PipeNotifier::~PipeNotifier() {
+ (void) HANDLE_EINTR(close(receiver_fd_));
+ (void) HANDLE_EINTR(close(sender_fd_));
+}
+
+bool PipeNotifier::Notify() {
+ CHECK_NE(-1, sender_fd_);
+ errno = 0;
+ int ret = HANDLE_EINTR(write(sender_fd_, "1", 1));
+ if (ret < 0) {
+ LOG(WARNING) << "Error while notifying pipe. " << safe_strerror(errno);
+ return false;
+ }
+ return true;
+}
+
+} // namespace forwarder
diff --git a/chromium/tools/android/forwarder2/pipe_notifier.h b/chromium/tools/android/forwarder2/pipe_notifier.h
new file mode 100644
index 00000000000..efe303b2c12
--- /dev/null
+++ b/chromium/tools/android/forwarder2/pipe_notifier.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_PIPE_NOTIFIER_H_
+#define TOOLS_ANDROID_FORWARDER2_PIPE_NOTIFIER_H_
+
+#include "base/basictypes.h"
+
+namespace forwarder2 {
+
+// Helper class used to create a unix pipe that sends notifications to the
+// |receiver_fd_| file descriptor when called |Notify()|. This should be used
+// by the main thread to notify other threads that it must exit.
+// The |receiver_fd_| can be put into a fd_set and used in a select together
+// with a socket waiting to accept or read.
+class PipeNotifier {
+ public:
+ PipeNotifier();
+ ~PipeNotifier();
+
+ bool Notify();
+
+ int receiver_fd() const { return receiver_fd_; }
+
+ private:
+ int sender_fd_;
+ int receiver_fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(PipeNotifier);
+};
+
+} // namespace forwarder
+
+#endif // TOOLS_ANDROID_FORWARDER2_PIPE_NOTIFIER_H_
diff --git a/chromium/tools/android/forwarder2/socket.cc b/chromium/tools/android/forwarder2/socket.cc
new file mode 100644
index 00000000000..9564e986347
--- /dev/null
+++ b/chromium/tools/android/forwarder2/socket.cc
@@ -0,0 +1,422 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/android/forwarder2/socket.h"
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/safe_strerror_posix.h"
+#include "tools/android/common/net.h"
+#include "tools/android/forwarder2/common.h"
+
+namespace {
+const int kNoTimeout = -1;
+const int kConnectTimeOut = 10; // Seconds.
+
+bool FamilyIsTCP(int family) {
+ return family == AF_INET || family == AF_INET6;
+}
+} // namespace
+
+namespace forwarder2 {
+
+bool Socket::BindUnix(const std::string& path) {
+ errno = 0;
+ if (!InitUnixSocket(path) || !BindAndListen()) {
+ Close();
+ return false;
+ }
+ return true;
+}
+
+bool Socket::BindTcp(const std::string& host, int port) {
+ errno = 0;
+ if (!InitTcpSocket(host, port) || !BindAndListen()) {
+ Close();
+ return false;
+ }
+ return true;
+}
+
+bool Socket::ConnectUnix(const std::string& path) {
+ errno = 0;
+ if (!InitUnixSocket(path) || !Connect()) {
+ Close();
+ return false;
+ }
+ return true;
+}
+
+bool Socket::ConnectTcp(const std::string& host, int port) {
+ errno = 0;
+ if (!InitTcpSocket(host, port) || !Connect()) {
+ Close();
+ return false;
+ }
+ return true;
+}
+
+Socket::Socket()
+ : socket_(-1),
+ port_(0),
+ socket_error_(false),
+ family_(AF_INET),
+ addr_ptr_(reinterpret_cast<sockaddr*>(&addr_.addr4)),
+ addr_len_(sizeof(sockaddr)) {
+ memset(&addr_, 0, sizeof(addr_));
+}
+
+Socket::~Socket() {
+ Close();
+}
+
+void Socket::Shutdown() {
+ if (!IsClosed()) {
+ PRESERVE_ERRNO_HANDLE_EINTR(shutdown(socket_, SHUT_RDWR));
+ }
+}
+
+void Socket::Close() {
+ if (!IsClosed()) {
+ CloseFD(socket_);
+ socket_ = -1;
+ }
+}
+
+bool Socket::InitSocketInternal() {
+ socket_ = socket(family_, SOCK_STREAM, 0);
+ if (socket_ < 0)
+ return false;
+ tools::DisableNagle(socket_);
+ int reuse_addr = 1;
+ setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
+ &reuse_addr, sizeof(reuse_addr));
+ return true;
+}
+
+bool Socket::InitUnixSocket(const std::string& path) {
+ static const size_t kPathMax = sizeof(addr_.addr_un.sun_path);
+ // For abstract sockets we need one extra byte for the leading zero.
+ if (path.size() + 2 /* '\0' */ > kPathMax) {
+ LOG(ERROR) << "The provided path is too big to create a unix "
+ << "domain socket: " << path;
+ return false;
+ }
+ family_ = PF_UNIX;
+ addr_.addr_un.sun_family = family_;
+ // Copied from net/socket/unix_domain_socket_posix.cc
+ // Convert the path given into abstract socket name. It must start with
+ // the '\0' character, so we are adding it. |addr_len| must specify the
+ // length of the structure exactly, as potentially the socket name may
+ // have '\0' characters embedded (although we don't support this).
+ // Note that addr_.addr_un.sun_path is already zero initialized.
+ memcpy(addr_.addr_un.sun_path + 1, path.c_str(), path.size());
+ addr_len_ = path.size() + offsetof(struct sockaddr_un, sun_path) + 1;
+ addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr_un);
+ return InitSocketInternal();
+}
+
+bool Socket::InitTcpSocket(const std::string& host, int port) {
+ port_ = port;
+ if (host.empty()) {
+ // Use localhost: INADDR_LOOPBACK
+ family_ = AF_INET;
+ addr_.addr4.sin_family = family_;
+ addr_.addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ } else if (!Resolve(host)) {
+ return false;
+ }
+ CHECK(FamilyIsTCP(family_)) << "Invalid socket family.";
+ if (family_ == AF_INET) {
+ addr_.addr4.sin_port = htons(port_);
+ addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr4);
+ addr_len_ = sizeof(addr_.addr4);
+ } else if (family_ == AF_INET6) {
+ addr_.addr6.sin6_port = htons(port_);
+ addr_ptr_ = reinterpret_cast<sockaddr*>(&addr_.addr6);
+ addr_len_ = sizeof(addr_.addr6);
+ }
+ return InitSocketInternal();
+}
+
+bool Socket::BindAndListen() {
+ errno = 0;
+ if (HANDLE_EINTR(bind(socket_, addr_ptr_, addr_len_)) < 0 ||
+ HANDLE_EINTR(listen(socket_, SOMAXCONN)) < 0) {
+ SetSocketError();
+ return false;
+ }
+ if (port_ == 0 && FamilyIsTCP(family_)) {
+ SockAddr addr;
+ memset(&addr, 0, sizeof(addr));
+ socklen_t addrlen = 0;
+ sockaddr* addr_ptr = NULL;
+ uint16* port_ptr = NULL;
+ if (family_ == AF_INET) {
+ addr_ptr = reinterpret_cast<sockaddr*>(&addr.addr4);
+ port_ptr = &addr.addr4.sin_port;
+ addrlen = sizeof(addr.addr4);
+ } else if (family_ == AF_INET6) {
+ addr_ptr = reinterpret_cast<sockaddr*>(&addr.addr6);
+ port_ptr = &addr.addr6.sin6_port;
+ addrlen = sizeof(addr.addr6);
+ }
+ errno = 0;
+ if (getsockname(socket_, addr_ptr, &addrlen) != 0) {
+ LOG(ERROR) << "getsockname error: " << safe_strerror(errno);;
+ SetSocketError();
+ return false;
+ }
+ port_ = ntohs(*port_ptr);
+ }
+ return true;
+}
+
+bool Socket::Accept(Socket* new_socket) {
+ DCHECK(new_socket != NULL);
+ if (!WaitForEvent(READ, kNoTimeout)) {
+ SetSocketError();
+ return false;
+ }
+ errno = 0;
+ int new_socket_fd = HANDLE_EINTR(accept(socket_, NULL, NULL));
+ if (new_socket_fd < 0) {
+ SetSocketError();
+ return false;
+ }
+
+ tools::DisableNagle(new_socket_fd);
+ new_socket->socket_ = new_socket_fd;
+ return true;
+}
+
+bool Socket::Connect() {
+ // Set non-block because we use select for connect.
+ const int kFlags = fcntl(socket_, F_GETFL);
+ DCHECK(!(kFlags & O_NONBLOCK));
+ fcntl(socket_, F_SETFL, kFlags | O_NONBLOCK);
+ errno = 0;
+ if (HANDLE_EINTR(connect(socket_, addr_ptr_, addr_len_)) < 0 &&
+ errno != EINPROGRESS) {
+ SetSocketError();
+ PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags));
+ return false;
+ }
+ // Wait for connection to complete, or receive a notification.
+ if (!WaitForEvent(WRITE, kConnectTimeOut)) {
+ SetSocketError();
+ PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags));
+ return false;
+ }
+ int socket_errno;
+ socklen_t opt_len = sizeof(socket_errno);
+ if (getsockopt(socket_, SOL_SOCKET, SO_ERROR, &socket_errno, &opt_len) < 0) {
+ LOG(ERROR) << "getsockopt(): " << safe_strerror(errno);
+ SetSocketError();
+ PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags));
+ return false;
+ }
+ if (socket_errno != 0) {
+ LOG(ERROR) << "Could not connect to host: " << safe_strerror(socket_errno);
+ SetSocketError();
+ PRESERVE_ERRNO_HANDLE_EINTR(fcntl(socket_, F_SETFL, kFlags));
+ return false;
+ }
+ fcntl(socket_, F_SETFL, kFlags);
+ return true;
+}
+
+bool Socket::Resolve(const std::string& host) {
+ struct addrinfo hints;
+ struct addrinfo* res;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags |= AI_CANONNAME;
+
+ int errcode = getaddrinfo(host.c_str(), NULL, &hints, &res);
+ if (errcode != 0) {
+ SetSocketError();
+ freeaddrinfo(res);
+ return false;
+ }
+ family_ = res->ai_family;
+ switch (res->ai_family) {
+ case AF_INET:
+ memcpy(&addr_.addr4,
+ reinterpret_cast<sockaddr_in*>(res->ai_addr),
+ sizeof(sockaddr_in));
+ break;
+ case AF_INET6:
+ memcpy(&addr_.addr6,
+ reinterpret_cast<sockaddr_in6*>(res->ai_addr),
+ sizeof(sockaddr_in6));
+ break;
+ }
+ freeaddrinfo(res);
+ return true;
+}
+
+int Socket::GetPort() {
+ if (!FamilyIsTCP(family_)) {
+ LOG(ERROR) << "Can't call GetPort() on an unix domain socket.";
+ return 0;
+ }
+ return port_;
+}
+
+bool Socket::IsFdInSet(const fd_set& fds) const {
+ if (IsClosed())
+ return false;
+ return FD_ISSET(socket_, &fds);
+}
+
+bool Socket::AddFdToSet(fd_set* fds) const {
+ if (IsClosed())
+ return false;
+ FD_SET(socket_, fds);
+ return true;
+}
+
+int Socket::ReadNumBytes(void* buffer, size_t num_bytes) {
+ int bytes_read = 0;
+ int ret = 1;
+ while (bytes_read < num_bytes && ret > 0) {
+ ret = Read(static_cast<char*>(buffer) + bytes_read, num_bytes - bytes_read);
+ if (ret >= 0)
+ bytes_read += ret;
+ }
+ return bytes_read;
+}
+
+void Socket::SetSocketError() {
+ socket_error_ = true;
+ // We never use non-blocking socket.
+ DCHECK(errno != EAGAIN && errno != EWOULDBLOCK);
+ Close();
+}
+
+int Socket::Read(void* buffer, size_t buffer_size) {
+ if (!WaitForEvent(READ, kNoTimeout)) {
+ SetSocketError();
+ return 0;
+ }
+ int ret = HANDLE_EINTR(read(socket_, buffer, buffer_size));
+ if (ret < 0)
+ SetSocketError();
+ return ret;
+}
+
+int Socket::Write(const void* buffer, size_t count) {
+ int ret = HANDLE_EINTR(send(socket_, buffer, count, MSG_NOSIGNAL));
+ if (ret < 0)
+ SetSocketError();
+ return ret;
+}
+
+int Socket::WriteString(const std::string& buffer) {
+ return WriteNumBytes(buffer.c_str(), buffer.size());
+}
+
+void Socket::AddEventFd(int event_fd) {
+ Event event;
+ event.fd = event_fd;
+ event.was_fired = false;
+ events_.push_back(event);
+}
+
+bool Socket::DidReceiveEventOnFd(int fd) const {
+ for (size_t i = 0; i < events_.size(); ++i)
+ if (events_[i].fd == fd)
+ return events_[i].was_fired;
+ return false;
+}
+
+bool Socket::DidReceiveEvent() const {
+ for (size_t i = 0; i < events_.size(); ++i)
+ if (events_[i].was_fired)
+ return true;
+ return false;
+}
+
+int Socket::WriteNumBytes(const void* buffer, size_t num_bytes) {
+ int bytes_written = 0;
+ int ret = 1;
+ while (bytes_written < num_bytes && ret > 0) {
+ ret = Write(static_cast<const char*>(buffer) + bytes_written,
+ num_bytes - bytes_written);
+ if (ret >= 0)
+ bytes_written += ret;
+ }
+ return bytes_written;
+}
+
+bool Socket::WaitForEvent(EventType type, int timeout_secs) {
+ if (events_.empty() || socket_ == -1)
+ return true;
+ fd_set read_fds;
+ fd_set write_fds;
+ FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
+ if (type == READ)
+ FD_SET(socket_, &read_fds);
+ else
+ FD_SET(socket_, &write_fds);
+ for (size_t i = 0; i < events_.size(); ++i)
+ FD_SET(events_[i].fd, &read_fds);
+ timeval tv = {};
+ timeval* tv_ptr = NULL;
+ if (timeout_secs > 0) {
+ tv.tv_sec = timeout_secs;
+ tv.tv_usec = 0;
+ tv_ptr = &tv;
+ }
+ int max_fd = socket_;
+ for (size_t i = 0; i < events_.size(); ++i)
+ if (events_[i].fd > max_fd)
+ max_fd = events_[i].fd;
+ if (HANDLE_EINTR(
+ select(max_fd + 1, &read_fds, &write_fds, NULL, tv_ptr)) <= 0) {
+ return false;
+ }
+ bool event_was_fired = false;
+ for (size_t i = 0; i < events_.size(); ++i) {
+ if (FD_ISSET(events_[i].fd, &read_fds)) {
+ events_[i].was_fired = true;
+ event_was_fired = true;
+ }
+ }
+ return !event_was_fired;
+}
+
+// static
+int Socket::GetHighestFileDescriptor(const Socket& s1, const Socket& s2) {
+ return std::max(s1.socket_, s2.socket_);
+}
+
+// static
+pid_t Socket::GetUnixDomainSocketProcessOwner(const std::string& path) {
+ Socket socket;
+ if (!socket.ConnectUnix(path))
+ return -1;
+ ucred ucred;
+ socklen_t len = sizeof(ucred);
+ if (getsockopt(socket.socket_, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) {
+ CHECK_NE(ENOPROTOOPT, errno);
+ return -1;
+ }
+ return ucred.pid;
+}
+
+} // namespace forwarder2
diff --git a/chromium/tools/android/forwarder2/socket.h b/chromium/tools/android/forwarder2/socket.h
new file mode 100644
index 00000000000..b86fd9e7aa6
--- /dev/null
+++ b/chromium/tools/android/forwarder2/socket.h
@@ -0,0 +1,145 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_ANDROID_FORWARDER2_SOCKET_H_
+#define TOOLS_ANDROID_FORWARDER2_SOCKET_H_
+
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+
+namespace forwarder2 {
+
+// Wrapper class around unix socket api. Can be used to create, bind or
+// connect to both Unix domain sockets and TCP sockets.
+// TODO(pliard): Split this class into TCPSocket and UnixDomainSocket.
+class Socket {
+ public:
+ Socket();
+ ~Socket();
+
+ bool BindUnix(const std::string& path);
+ bool BindTcp(const std::string& host, int port);
+ bool ConnectUnix(const std::string& path);
+ bool ConnectTcp(const std::string& host, int port);
+
+ // Just a wrapper around unix socket shutdown(), see man 2 shutdown.
+ void Shutdown();
+
+ // Just a wrapper around unix socket close(), see man 2 close.
+ void Close();
+ bool IsClosed() const { return socket_ < 0; }
+
+ bool Accept(Socket* new_socket);
+
+ // Returns the port allocated to this socket or zero on error.
+ int GetPort();
+
+ bool IsFdInSet(const fd_set& fds) const;
+ bool AddFdToSet(fd_set* fds) const;
+
+ // Just a wrapper around unix read() function.
+ // Reads up to buffer_size, but may read less then buffer_size.
+ // Returns the number of bytes read.
+ int Read(void* buffer, size_t buffer_size);
+
+ // Same as Read(), just a wrapper around write().
+ int Write(const void* buffer, size_t count);
+
+ // Calls Read() multiple times until num_bytes is written to the provided
+ // buffer. No bounds checking is performed.
+ // Returns number of bytes read, which can be different from num_bytes in case
+ // of errror.
+ int ReadNumBytes(void* buffer, size_t num_bytes);
+
+ // Calls Write() multiple times until num_bytes is written. No bounds checking
+ // is performed. Returns number of bytes written, which can be different from
+ // num_bytes in case of errror.
+ int WriteNumBytes(const void* buffer, size_t num_bytes);
+
+ // Calls WriteNumBytes for the given std::string. Note that the null
+ // terminator is not written to the socket.
+ int WriteString(const std::string& buffer);
+
+ bool has_error() const { return socket_error_; }
+
+ // |event_fd| must be a valid pipe file descriptor created from the
+ // PipeNotifier and must live (not be closed) at least as long as this socket
+ // is alive.
+ void AddEventFd(int event_fd);
+
+ // Returns whether Accept() or Connect() was interrupted because the socket
+ // received an external event fired through the provided fd.
+ bool DidReceiveEventOnFd(int fd) const;
+
+ bool DidReceiveEvent() const;
+
+ static int GetHighestFileDescriptor(const Socket& s1, const Socket& s2);
+
+ static pid_t GetUnixDomainSocketProcessOwner(const std::string& path);
+
+ private:
+ enum EventType {
+ READ,
+ WRITE
+ };
+
+ union SockAddr {
+ // IPv4 sockaddr
+ sockaddr_in addr4;
+ // IPv6 sockaddr
+ sockaddr_in6 addr6;
+ // Unix Domain sockaddr
+ sockaddr_un addr_un;
+ };
+
+ struct Event {
+ int fd;
+ bool was_fired;
+ };
+
+ // If |host| is empty, use localhost.
+ bool InitTcpSocket(const std::string& host, int port);
+ bool InitUnixSocket(const std::string& path);
+ bool BindAndListen();
+ bool Connect();
+
+ bool Resolve(const std::string& host);
+ bool InitSocketInternal();
+ void SetSocketError();
+
+ // Waits until either the Socket or the |exit_notifier_fd_| has received an
+ // event.
+ bool WaitForEvent(EventType type, int timeout_secs);
+
+ int socket_;
+ int port_;
+ bool socket_error_;
+
+ // Family of the socket (PF_INET, PF_INET6 or PF_UNIX).
+ int family_;
+
+ SockAddr addr_;
+
+ // Points to one of the members of the above union depending on the family.
+ sockaddr* addr_ptr_;
+ // Length of one of the members of the above union depending on the family.
+ socklen_t addr_len_;
+
+ // Used to listen for external events (e.g. process received a SIGTERM) while
+ // blocking on I/O operations.
+ std::vector<Event> events_;
+
+ DISALLOW_COPY_AND_ASSIGN(Socket);
+};
+
+} // namespace forwarder
+
+#endif // TOOLS_ANDROID_FORWARDER2_SOCKET_H_
diff --git a/chromium/tools/android/md5sum/md5sum.cc b/chromium/tools/android/md5sum/md5sum.cc
new file mode 100644
index 00000000000..bc4ca071b8c
--- /dev/null
+++ b/chromium/tools/android/md5sum/md5sum.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Md5sum implementation for Android. This version handles files as well as
+// directories. Its output is sorted by file path.
+
+#include <fstream>
+#include <iostream>
+#include <set>
+#include <string>
+
+#include "base/file_util.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/md5.h"
+
+namespace {
+
+const int kBufferSize = 1024;
+
+// Returns whether |path|'s MD5 was successfully written to |digest_string|.
+bool MD5Sum(const char* path, std::string* digest_string) {
+ std::ifstream stream(path);
+ if (!stream.good()) {
+ LOG(ERROR) << "Could not open file " << path;
+ return false;
+ }
+ base::MD5Context ctx;
+ base::MD5Init(&ctx);
+ char buf[kBufferSize];
+ while (stream.good()) {
+ std::streamsize bytes_read = stream.readsome(buf, sizeof(buf));
+ if (bytes_read == 0)
+ break;
+ base::MD5Update(&ctx, base::StringPiece(buf, bytes_read));
+ }
+ if (stream.fail()) {
+ LOG(ERROR) << "Error reading file " << path;
+ return false;
+ }
+ base::MD5Digest digest;
+ base::MD5Final(&digest, &ctx);
+ *digest_string = base::MD5DigestToBase16(digest);
+ return true;
+}
+
+// Returns the set of all files contained in |files|. This handles directories
+// by walking them recursively. Excludes, .svn directories and file under them.
+std::set<std::string> MakeFileSet(const char** files) {
+ const std::string svn_dir_component = FILE_PATH_LITERAL("/.svn/");
+ std::set<std::string> file_set;
+ for (const char** file = files; *file; ++file) {
+ base::FilePath file_path(*file);
+ if (base::DirectoryExists(file_path)) {
+ base::FileEnumerator file_enumerator(
+ file_path, true /* recurse */, base::FileEnumerator::FILES);
+ for (base::FilePath child, empty;
+ (child = file_enumerator.Next()) != empty; ) {
+ // If the path contains /.svn/, ignore it.
+ if (child.value().find(svn_dir_component) == std::string::npos) {
+ child = base::MakeAbsoluteFilePath(child);
+ file_set.insert(child.value());
+ }
+ }
+ } else {
+ file_set.insert(*file);
+ }
+ }
+ return file_set;
+}
+
+} // namespace
+
+int main(int argc, const char* argv[]) {
+ if (argc < 2) {
+ LOG(ERROR) << "Usage: md5sum <path/to/file_or_dir>...";
+ return 1;
+ }
+ const std::set<std::string> files = MakeFileSet(argv + 1);
+ bool failed = false;
+ std::string digest;
+ for (std::set<std::string>::const_iterator it = files.begin();
+ it != files.end(); ++it) {
+ if (!MD5Sum(it->c_str(), &digest))
+ failed = true;
+ base::FilePath file_path(*it);
+ std::cout << digest << " "
+ << base::MakeAbsoluteFilePath(file_path).value() << std::endl;
+ }
+ return failed;
+}
diff --git a/chromium/tools/android/md5sum/md5sum.gyp b/chromium/tools/android/md5sum/md5sum.gyp
new file mode 100644
index 00000000000..2c4ccc84dde
--- /dev/null
+++ b/chromium/tools/android/md5sum/md5sum.gyp
@@ -0,0 +1,77 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'md5sum',
+ 'type': 'none',
+ 'dependencies': [
+ 'md5sum_stripped_device_bin',
+ 'md5sum_bin_host#host',
+ ],
+ # For the component build, ensure dependent shared libraries are stripped
+ # and put alongside md5sum to simplify pushing to the device.
+ 'variables': {
+ 'output_dir': '<(PRODUCT_DIR)/md5sum_dist/',
+ 'native_binary': '<(PRODUCT_DIR)/md5sum_bin',
+ },
+ 'includes': ['../../../build/android/native_app_dependencies.gypi'],
+ },
+ {
+ 'target_name': 'md5sum_device_bin',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ 'sources': [
+ 'md5sum.cc',
+ ],
+ 'conditions': [
+ [ 'order_profiling!=0 and OS=="android"', {
+ 'dependencies': [ '../../../tools/cygprofile/cygprofile.gyp:cygprofile', ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'md5sum_stripped_device_bin',
+ 'type': 'none',
+ 'dependencies': [
+ 'md5sum_device_bin',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'strip_md5sum_device_bin',
+ 'inputs': ['<(PRODUCT_DIR)/md5sum_device_bin'],
+ 'outputs': ['<(PRODUCT_DIR)/md5sum_bin'],
+ 'action': [
+ '<(android_strip)',
+ '--strip-unneeded',
+ '<@(_inputs)',
+ '-o',
+ '<@(_outputs)',
+ ],
+ },
+ ],
+ },
+ # Same binary but for the host rather than the device.
+ {
+ 'target_name': 'md5sum_bin_host',
+ 'toolsets': ['host'],
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ 'sources': [
+ 'md5sum.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/android/memdump/memdump.cc b/chromium/tools/android/memdump/memdump.cc
new file mode 100644
index 00000000000..26035b29b0b
--- /dev/null
+++ b/chromium/tools/android/memdump/memdump.cc
@@ -0,0 +1,555 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+#include <iostream>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/base64.h"
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/containers/hash_tables.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
+
+namespace {
+
+class BitSet {
+ public:
+ void resize(size_t nbits) {
+ data_.resize((nbits + 7) / 8);
+ }
+
+ void set(uint32 bit) {
+ const uint32 byte_idx = bit / 8;
+ CHECK(byte_idx < data_.size());
+ data_[byte_idx] |= (1 << (bit & 7));
+ }
+
+ std::string AsB64String() const {
+ std::string bits(&data_[0], data_.size());
+ std::string b64_string;
+ base::Base64Encode(bits, &b64_string);
+ return b64_string;
+ }
+
+ private:
+ std::vector<char> data_;
+};
+
+// An entry in /proc/<pid>/pagemap.
+struct PageMapEntry {
+ uint64 page_frame_number : 55;
+ uint unused : 8;
+ uint present : 1;
+};
+
+// Describes a memory page.
+struct PageInfo {
+ int64 page_frame_number; // Physical page id, also known as PFN.
+ int64 flags;
+ int32 times_mapped;
+};
+
+struct MemoryMap {
+ std::string name;
+ std::string flags;
+ uint start_address;
+ uint end_address;
+ uint offset;
+ int private_count;
+ int unevictable_private_count;
+ int other_shared_count;
+ int unevictable_other_shared_count;
+ // app_shared_counts[i] contains the number of pages mapped in i+2 processes
+ // (only among the processes that are being analyzed).
+ std::vector<int> app_shared_counts;
+ std::vector<PageInfo> committed_pages;
+ // committed_pages_bits is a bitset reflecting the present bit for all the
+ // virtual pages of the mapping.
+ BitSet committed_pages_bits;
+};
+
+struct ProcessMemory {
+ pid_t pid;
+ std::vector<MemoryMap> memory_maps;
+};
+
+bool PageIsUnevictable(const PageInfo& page_info) {
+ // These constants are taken from kernel-page-flags.h.
+ const int KPF_DIRTY = 4; // Note that only file-mapped pages can be DIRTY.
+ const int KPF_ANON = 12; // Anonymous pages are dirty per definition.
+ const int KPF_UNEVICTABLE = 18;
+ const int KPF_MLOCKED = 33;
+
+ return (page_info.flags & ((1ll << KPF_DIRTY) |
+ (1ll << KPF_ANON) |
+ (1ll << KPF_UNEVICTABLE) |
+ (1ll << KPF_MLOCKED))) ?
+ true : false;
+}
+
+// Number of times a physical page is mapped in a process.
+typedef base::hash_map<uint64, int> PFNMap;
+
+// Parses lines from /proc/<PID>/maps, e.g.:
+// 401e7000-401f5000 r-xp 00000000 103:02 158 /system/bin/linker
+bool ParseMemoryMapLine(const std::string& line,
+ std::vector<std::string>* tokens,
+ MemoryMap* memory_map) {
+ tokens->clear();
+ base::SplitString(line, ' ', tokens);
+ if (tokens->size() < 2)
+ return false;
+ const int addr_len = 8;
+ const std::string& addr_range = tokens->at(0);
+ if (addr_range.length() != addr_len + 1 + addr_len)
+ return false;
+ uint64 tmp = 0;
+ if (!base::HexStringToUInt64(
+ base::StringPiece(
+ addr_range.begin(), addr_range.begin() + addr_len),
+ &tmp)) {
+ return false;
+ }
+ memory_map->start_address = static_cast<uint>(tmp);
+ const int end_addr_start_pos = addr_len + 1;
+ if (!base::HexStringToUInt64(
+ base::StringPiece(
+ addr_range.begin() + end_addr_start_pos,
+ addr_range.begin() + end_addr_start_pos + addr_len),
+ &tmp)) {
+ return false;
+ }
+ memory_map->end_address = static_cast<uint>(tmp);
+ if (tokens->at(1).size() != strlen("rwxp"))
+ return false;
+ memory_map->flags.swap(tokens->at(1));
+ if (!base::HexStringToUInt64(tokens->at(2), &tmp))
+ return false;
+ memory_map->offset = static_cast<uint>(tmp);
+ memory_map->committed_pages_bits.resize(
+ (memory_map->end_address - memory_map->start_address) / PAGE_SIZE);
+ const int map_name_index = 5;
+ if (tokens->size() >= map_name_index + 1) {
+ for (std::vector<std::string>::const_iterator it =
+ tokens->begin() + map_name_index; it != tokens->end(); ++it) {
+ if (!it->empty()) {
+ if (!memory_map->name.empty())
+ memory_map->name.append(" ");
+ memory_map->name.append(*it);
+ }
+ }
+ }
+ return true;
+}
+
+// Reads sizeof(T) bytes from file |fd| at |offset|.
+template <typename T>
+bool ReadFromFileAtOffset(int fd, off_t offset, T* value) {
+ if (lseek64(fd, offset * sizeof(*value), SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek";
+ return false;
+ }
+ ssize_t bytes = read(fd, value, sizeof(*value));
+ if (bytes != sizeof(*value) && bytes != 0) {
+ PLOG(ERROR) << "read";
+ return false;
+ }
+ return true;
+}
+
+// Fills |process_maps| in with the process memory maps identified by |pid|.
+bool GetProcessMaps(pid_t pid, std::vector<MemoryMap>* process_maps) {
+ std::ifstream maps_file(base::StringPrintf("/proc/%d/maps", pid).c_str());
+ if (!maps_file.good()) {
+ PLOG(ERROR) << "open";
+ return false;
+ }
+ std::string line;
+ std::vector<std::string> tokens;
+ while (std::getline(maps_file, line) && !line.empty()) {
+ MemoryMap memory_map = {};
+ if (!ParseMemoryMapLine(line, &tokens, &memory_map)) {
+ LOG(ERROR) << "Could not parse line: " << line;
+ return false;
+ }
+ process_maps->push_back(memory_map);
+ }
+ return true;
+}
+
+// Fills |committed_pages| in with the set of committed pages contained in the
+// provided memory map.
+bool GetPagesForMemoryMap(int pagemap_fd,
+ const MemoryMap& memory_map,
+ std::vector<PageInfo>* committed_pages,
+ BitSet* committed_pages_bits) {
+ for (uint addr = memory_map.start_address, page_index = 0;
+ addr < memory_map.end_address;
+ addr += PAGE_SIZE, ++page_index) {
+ DCHECK_EQ(0, addr % PAGE_SIZE);
+ PageMapEntry page_map_entry = {};
+ COMPILE_ASSERT(sizeof(PageMapEntry) == sizeof(uint64), unexpected_size);
+ const off64_t offset = addr / PAGE_SIZE;
+ if (!ReadFromFileAtOffset(pagemap_fd, offset, &page_map_entry))
+ return false;
+ if (page_map_entry.present) { // Ignore non-committed pages.
+ if (page_map_entry.page_frame_number == 0)
+ continue;
+ PageInfo page_info = {};
+ page_info.page_frame_number = page_map_entry.page_frame_number;
+ committed_pages->push_back(page_info);
+ committed_pages_bits->set(page_index);
+ }
+ }
+ return true;
+}
+
+// Fills |committed_pages| with mapping count and flags information gathered
+// looking-up /proc/kpagecount and /proc/kpageflags.
+bool SetPagesInfo(int pagecount_fd,
+ int pageflags_fd,
+ std::vector<PageInfo>* pages) {
+ for (std::vector<PageInfo>::iterator it = pages->begin();
+ it != pages->end(); ++it) {
+ PageInfo* const page_info = &*it;
+
+ int64 times_mapped;
+ if (!ReadFromFileAtOffset(
+ pagecount_fd, page_info->page_frame_number, &times_mapped)) {
+ return false;
+ }
+ DCHECK(times_mapped <= std::numeric_limits<int32_t>::max());
+ page_info->times_mapped = static_cast<int32>(times_mapped);
+
+ int64 page_flags;
+ if (!ReadFromFileAtOffset(
+ pageflags_fd, page_info->page_frame_number, &page_flags)) {
+ return false;
+ }
+ page_info->flags = page_flags;
+ }
+ return true;
+}
+
+// Fills in the provided vector of Page Frame Number maps. This lets
+// ClassifyPages() know how many times each page is mapped in the processes.
+void FillPFNMaps(const std::vector<ProcessMemory>& processes_memory,
+ std::vector<PFNMap>* pfn_maps) {
+ int current_process_index = 0;
+ for (std::vector<ProcessMemory>::const_iterator it = processes_memory.begin();
+ it != processes_memory.end(); ++it, ++current_process_index) {
+ const std::vector<MemoryMap>& memory_maps = it->memory_maps;
+ for (std::vector<MemoryMap>::const_iterator it = memory_maps.begin();
+ it != memory_maps.end(); ++it) {
+ const std::vector<PageInfo>& pages = it->committed_pages;
+ for (std::vector<PageInfo>::const_iterator it = pages.begin();
+ it != pages.end(); ++it) {
+ const PageInfo& page_info = *it;
+ PFNMap* const pfn_map = &(*pfn_maps)[current_process_index];
+ const std::pair<PFNMap::iterator, bool> result = pfn_map->insert(
+ std::make_pair(page_info.page_frame_number, 0));
+ ++result.first->second;
+ }
+ }
+ }
+}
+
+// Sets the private_count/app_shared_counts/other_shared_count fields of the
+// provided memory maps for each process.
+void ClassifyPages(std::vector<ProcessMemory>* processes_memory) {
+ std::vector<PFNMap> pfn_maps(processes_memory->size());
+ FillPFNMaps(*processes_memory, &pfn_maps);
+ // Hash set keeping track of the physical pages mapped in a single process so
+ // that they can be counted only once.
+ std::hash_set<uint64> physical_pages_mapped_in_process;
+
+ for (std::vector<ProcessMemory>::iterator it = processes_memory->begin();
+ it != processes_memory->end(); ++it) {
+ std::vector<MemoryMap>* const memory_maps = &it->memory_maps;
+ physical_pages_mapped_in_process.clear();
+ for (std::vector<MemoryMap>::iterator it = memory_maps->begin();
+ it != memory_maps->end(); ++it) {
+ MemoryMap* const memory_map = &*it;
+ const size_t processes_count = processes_memory->size();
+ memory_map->app_shared_counts.resize(processes_count - 1, 0);
+ const std::vector<PageInfo>& pages = memory_map->committed_pages;
+ for (std::vector<PageInfo>::const_iterator it = pages.begin();
+ it != pages.end(); ++it) {
+ const PageInfo& page_info = *it;
+ if (page_info.times_mapped == 1) {
+ ++memory_map->private_count;
+ if (PageIsUnevictable(page_info))
+ ++memory_map->unevictable_private_count;
+ continue;
+ }
+ const uint64 page_frame_number = page_info.page_frame_number;
+ const std::pair<std::hash_set<uint64>::iterator, bool> result =
+ physical_pages_mapped_in_process.insert(page_frame_number);
+ const bool did_insert = result.second;
+ if (!did_insert) {
+ // This physical page (mapped multiple times in the same process) was
+ // already counted.
+ continue;
+ }
+ // See if the current physical page is also mapped in the other
+ // processes that are being analyzed.
+ int times_mapped = 0;
+ int mapped_in_processes_count = 0;
+ for (std::vector<PFNMap>::const_iterator it = pfn_maps.begin();
+ it != pfn_maps.end(); ++it) {
+ const PFNMap& pfn_map = *it;
+ const PFNMap::const_iterator found_it = pfn_map.find(
+ page_frame_number);
+ if (found_it == pfn_map.end())
+ continue;
+ ++mapped_in_processes_count;
+ times_mapped += found_it->second;
+ }
+ if (times_mapped == page_info.times_mapped) {
+ // The physical page is only mapped in the processes that are being
+ // analyzed.
+ if (mapped_in_processes_count > 1) {
+ // The physical page is mapped in multiple processes.
+ ++memory_map->app_shared_counts[mapped_in_processes_count - 2];
+ } else {
+ // The physical page is mapped multiple times in the same process.
+ ++memory_map->private_count;
+ if (PageIsUnevictable(page_info))
+ ++memory_map->unevictable_private_count;
+ }
+ } else {
+ ++memory_map->other_shared_count;
+ if (PageIsUnevictable(page_info))
+ ++memory_map->unevictable_other_shared_count;
+
+ }
+ }
+ }
+ }
+}
+
+void AppendAppSharedField(const std::vector<int>& app_shared_counts,
+ std::string* out) {
+ out->append("[");
+ for (std::vector<int>::const_iterator it = app_shared_counts.begin();
+ it != app_shared_counts.end(); ++it) {
+ out->append(base::IntToString(*it * PAGE_SIZE));
+ if (it + 1 != app_shared_counts.end())
+ out->append(",");
+ }
+ out->append("]");
+}
+
+void DumpProcessesMemoryMaps(
+ const std::vector<ProcessMemory>& processes_memory) {
+ std::string buf;
+ std::string app_shared_buf;
+ for (std::vector<ProcessMemory>::const_iterator it = processes_memory.begin();
+ it != processes_memory.end(); ++it) {
+ const ProcessMemory& process_memory = *it;
+ std::cout << "[ PID=" << process_memory.pid << "]" << '\n';
+ const std::vector<MemoryMap>& memory_maps = process_memory.memory_maps;
+ for (std::vector<MemoryMap>::const_iterator it = memory_maps.begin();
+ it != memory_maps.end(); ++it) {
+ const MemoryMap& memory_map = *it;
+ app_shared_buf.clear();
+ AppendAppSharedField(memory_map.app_shared_counts, &app_shared_buf);
+ base::SStringPrintf(
+ &buf,
+ "%x-%x %s private_unevictable=%d private=%d shared_app=%s "
+ "shared_other_unevictable=%d shared_other=%d %s\n",
+ memory_map.start_address,
+ memory_map.end_address, memory_map.flags.c_str(),
+ memory_map.unevictable_private_count * PAGE_SIZE,
+ memory_map.private_count * PAGE_SIZE,
+ app_shared_buf.c_str(),
+ memory_map.unevictable_other_shared_count * PAGE_SIZE,
+ memory_map.other_shared_count * PAGE_SIZE,
+ memory_map.name.c_str());
+ std::cout << buf;
+ }
+ }
+}
+
+void DumpProcessesMemoryMapsInShortFormat(
+ const std::vector<ProcessMemory>& processes_memory) {
+ const int KB_PER_PAGE = PAGE_SIZE >> 10;
+ std::vector<int> totals_app_shared(processes_memory.size());
+ std::string buf;
+ std::cout << "pid\tprivate\t\tshared_app\tshared_other (KB)\n";
+ for (std::vector<ProcessMemory>::const_iterator it = processes_memory.begin();
+ it != processes_memory.end(); ++it) {
+ const ProcessMemory& process_memory = *it;
+ std::fill(totals_app_shared.begin(), totals_app_shared.end(), 0);
+ int total_private = 0, total_other_shared = 0;
+ const std::vector<MemoryMap>& memory_maps = process_memory.memory_maps;
+ for (std::vector<MemoryMap>::const_iterator it = memory_maps.begin();
+ it != memory_maps.end(); ++it) {
+ const MemoryMap& memory_map = *it;
+ total_private += memory_map.private_count;
+ for (size_t i = 0; i < memory_map.app_shared_counts.size(); ++i)
+ totals_app_shared[i] += memory_map.app_shared_counts[i];
+ total_other_shared += memory_map.other_shared_count;
+ }
+ double total_app_shared = 0;
+ for (size_t i = 0; i < totals_app_shared.size(); ++i)
+ total_app_shared += static_cast<double>(totals_app_shared[i]) / (i + 2);
+ base::SStringPrintf(
+ &buf, "%d\t%d\t\t%d\t\t%d\n",
+ process_memory.pid,
+ total_private * KB_PER_PAGE,
+ static_cast<int>(total_app_shared) * KB_PER_PAGE,
+ total_other_shared * KB_PER_PAGE);
+ std::cout << buf;
+ }
+}
+
+void DumpProcessesMemoryMapsInExtendedFormat(
+ const std::vector<ProcessMemory>& processes_memory) {
+ std::string buf;
+ std::string app_shared_buf;
+ for (std::vector<ProcessMemory>::const_iterator it = processes_memory.begin();
+ it != processes_memory.end(); ++it) {
+ const ProcessMemory& process_memory = *it;
+ std::cout << "[ PID=" << process_memory.pid << "]" << '\n';
+ const std::vector<MemoryMap>& memory_maps = process_memory.memory_maps;
+ for (std::vector<MemoryMap>::const_iterator it = memory_maps.begin();
+ it != memory_maps.end(); ++it) {
+ const MemoryMap& memory_map = *it;
+ app_shared_buf.clear();
+ AppendAppSharedField(memory_map.app_shared_counts, &app_shared_buf);
+ base::SStringPrintf(
+ &buf,
+ "%x-%x %s %x private_unevictable=%d private=%d shared_app=%s "
+ "shared_other_unevictable=%d shared_other=%d \"%s\" [%s]\n",
+ memory_map.start_address,
+ memory_map.end_address,
+ memory_map.flags.c_str(),
+ memory_map.offset,
+ memory_map.unevictable_private_count * PAGE_SIZE,
+ memory_map.private_count * PAGE_SIZE,
+ app_shared_buf.c_str(),
+ memory_map.unevictable_other_shared_count * PAGE_SIZE,
+ memory_map.other_shared_count * PAGE_SIZE,
+ memory_map.name.c_str(),
+ memory_map.committed_pages_bits.AsB64String().c_str());
+ std::cout << buf;
+ }
+ }
+}
+
+bool CollectProcessMemoryInformation(int page_count_fd,
+ int page_flags_fd,
+ ProcessMemory* process_memory) {
+ const pid_t pid = process_memory->pid;
+ int pagemap_fd = open(
+ base::StringPrintf("/proc/%d/pagemap", pid).c_str(), O_RDONLY);
+ if (pagemap_fd < 0) {
+ PLOG(ERROR) << "open";
+ return false;
+ }
+ file_util::ScopedFD auto_closer(&pagemap_fd);
+ std::vector<MemoryMap>* const process_maps = &process_memory->memory_maps;
+ if (!GetProcessMaps(pid, process_maps))
+ return false;
+ for (std::vector<MemoryMap>::iterator it = process_maps->begin();
+ it != process_maps->end(); ++it) {
+ std::vector<PageInfo>* const committed_pages = &it->committed_pages;
+ BitSet* const pages_bits = &it->committed_pages_bits;
+ GetPagesForMemoryMap(pagemap_fd, *it, committed_pages, pages_bits);
+ SetPagesInfo(page_count_fd, page_flags_fd, committed_pages);
+ }
+ return true;
+}
+
+void KillAll(const std::vector<pid_t>& pids, int signal_number) {
+ for (std::vector<pid_t>::const_iterator it = pids.begin(); it != pids.end();
+ ++it) {
+ kill(*it, signal_number);
+ }
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ if (argc == 1) {
+ LOG(ERROR) << "Usage: " << argv[0] << " [-a|-x] <PID1>... <PIDN>";
+ return EXIT_FAILURE;
+ }
+ const bool short_output = !strncmp(argv[1], "-a", 2);
+ const bool extended_output = !strncmp(argv[1], "-x", 2);
+ if (short_output || extended_output) {
+ if (argc == 2) {
+ LOG(ERROR) << "Usage: " << argv[0] << " [-a|-x] <PID1>... <PIDN>";
+ return EXIT_FAILURE;
+ }
+ ++argv;
+ }
+ std::vector<pid_t> pids;
+ for (const char* const* ptr = argv + 1; *ptr; ++ptr) {
+ pid_t pid;
+ if (!base::StringToInt(*ptr, &pid))
+ return EXIT_FAILURE;
+ pids.push_back(pid);
+ }
+
+ std::vector<ProcessMemory> processes_memory(pids.size());
+ {
+ int page_count_fd = open("/proc/kpagecount", O_RDONLY);
+ if (page_count_fd < 0) {
+ PLOG(ERROR) << "open /proc/kpagecount";
+ return EXIT_FAILURE;
+ }
+
+ int page_flags_fd = open("/proc/kpageflags", O_RDONLY);
+ if (page_flags_fd < 0) {
+ PLOG(ERROR) << "open /proc/kpageflags";
+ return EXIT_FAILURE;
+ }
+
+ file_util::ScopedFD page_count_fd_closer(&page_count_fd);
+ file_util::ScopedFD page_flags_fd_closer(&page_flags_fd);
+
+ base::ScopedClosureRunner auto_resume_processes(
+ base::Bind(&KillAll, pids, SIGCONT));
+ KillAll(pids, SIGSTOP);
+ for (std::vector<pid_t>::const_iterator it = pids.begin(); it != pids.end();
+ ++it) {
+ ProcessMemory* const process_memory =
+ &processes_memory[it - pids.begin()];
+ process_memory->pid = *it;
+ if (!CollectProcessMemoryInformation(page_count_fd,
+ page_flags_fd,
+ process_memory))
+ return EXIT_FAILURE;
+ }
+ }
+
+ ClassifyPages(&processes_memory);
+ if (short_output)
+ DumpProcessesMemoryMapsInShortFormat(processes_memory);
+ else if (extended_output)
+ DumpProcessesMemoryMapsInExtendedFormat(processes_memory);
+ else
+ DumpProcessesMemoryMaps(processes_memory);
+ return EXIT_SUCCESS;
+}
diff --git a/chromium/tools/android/memdump/memdump.gyp b/chromium/tools/android/memdump/memdump.gyp
new file mode 100644
index 00000000000..faa24d0737b
--- /dev/null
+++ b/chromium/tools/android/memdump/memdump.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'memdump',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ ],
+ 'conditions': [
+ # Warning: A PIE tool cannot run on ICS 4.0.4, so only
+ # build it as position-independent when ASAN
+ # is activated. See b/6587214 for details.
+ [ 'asan==1', {
+ 'cflags': [
+ '-fPIE',
+ ],
+ 'ldflags': [
+ '-pie',
+ ],
+ }],
+ ],
+ 'sources': [
+ 'memdump.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/android/memdump/memreport.py b/chromium/tools/android/memdump/memreport.py
new file mode 100755
index 00000000000..1db1cb6b5ee
--- /dev/null
+++ b/chromium/tools/android/memdump/memreport.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import sys
+
+from sets import Set
+
+
+_ENTRIES = [
+ ('Total', '.* r... .*'),
+ ('Read-only', '.* r--. .*'),
+ ('Read-write', '.* rw.. .*'),
+ ('Executable', '.* ..x. .*'),
+ ('Anonymous total', '.* .... .* .*other=[0-9]+ ($|.*chromium:.*)'),
+ ('Anonymous read-write', '.* rw.. .* .*other=[0-9]+ ($|.*chromium:.*)'),
+ ('Anonymous executable (JIT\'ed code)', '.* ..x. .* shared_other=[0-9]+ $'),
+ ('File total', '.* .... .* /.*'),
+ ('File read-write', '.* rw.. .* /.*'),
+ ('File executable', '.* ..x. .* /.*'),
+ ('chromium mmap', '.* r... .*chromium:.*'),
+ ('chromium TransferBuffer', '.* r... .*chromium:.*CreateTransferBuffer.*'),
+ ('Galaxy Nexus GL driver', '.* r... .*pvrsrvkm.*'),
+ ('Dalvik', '.* rw.. .* /.*dalvik.*'),
+ ('Dalvik heap', '.* rw.. .* /.*dalvik-heap.*'),
+ ('Native heap (jemalloc)', '.* r... .* /.*jemalloc.*'),
+ ('System heap', '.* r... .* \\[heap\\]'),
+ ('Ashmem', '.* rw.. .* /dev/ashmem .*'),
+ ('libchromeview.so total', '.* r... .* /.*libchromeview.so'),
+ ('libchromeview.so read-only', '.* r--. .* /.*libchromeview.so'),
+ ('libchromeview.so read-write', '.* rw-. .* /.*libchromeview.so'),
+ ('libchromeview.so executable', '.* r.x. .* /.*libchromeview.so'),
+]
+
+
+def _CollectMemoryStats(memdump, region_filters):
+ processes = []
+ mem_usage_for_regions = None
+ regexps = {}
+ for region_filter in region_filters:
+ regexps[region_filter] = re.compile(region_filter)
+ for line in memdump:
+ if 'PID=' in line:
+ mem_usage_for_regions = {}
+ processes.append(mem_usage_for_regions)
+ continue
+ matched_regions = Set([])
+ for region_filter in region_filters:
+ if regexps[region_filter].match(line.rstrip('\r\n')):
+ matched_regions.add(region_filter)
+ if not region_filter in mem_usage_for_regions:
+ mem_usage_for_regions[region_filter] = {
+ 'private_unevictable': 0,
+ 'private': 0,
+ 'shared_app': 0.0,
+ 'shared_other_unevictable': 0,
+ 'shared_other': 0,
+ }
+ for matched_region in matched_regions:
+ mem_usage = mem_usage_for_regions[matched_region]
+ for key in mem_usage:
+ for token in line.split(' '):
+ if (key + '=') in token:
+ field = token.split('=')[1]
+ if key != 'shared_app':
+ mem_usage[key] += int(field)
+ else: # shared_app=[\d,\d...]
+ array = eval(field)
+ for i in xrange(len(array)):
+ mem_usage[key] += float(array[i]) / (i + 2)
+ break
+ return processes
+
+
+def _ConvertMemoryField(field):
+ return str(field / (1024.0 * 1024))
+
+
+def _DumpCSV(processes_stats):
+ total_map = {}
+ i = 0
+ for process in processes_stats:
+ i += 1
+ print (',Process ' + str(i) + ',private,private_unevictable,shared_app,' +
+ 'shared_other,shared_other_unevictable,')
+ for (k, v) in _ENTRIES:
+ if not v in process:
+ print ',' + k + ',0,0,0,0,'
+ continue
+ if not v in total_map:
+ total_map[v] = {'resident':0, 'unevictable':0}
+ total_map[v]['resident'] += (process[v]['private'] +
+ process[v]['shared_app'])
+ total_map[v]['unevictable'] += process[v]['private_unevictable']
+ print (
+ ',' + k + ',' +
+ _ConvertMemoryField(process[v]['private']) + ',' +
+ _ConvertMemoryField(process[v]['private_unevictable']) + ',' +
+ _ConvertMemoryField(process[v]['shared_app']) + ',' +
+ _ConvertMemoryField(process[v]['shared_other']) + ',' +
+ _ConvertMemoryField(process[v]['shared_other_unevictable']) + ','
+ )
+ print ''
+
+ for (k, v) in _ENTRIES:
+ if not v in total_map:
+ print ',' + k + ',0,0,'
+ continue
+ print (',' + k + ',' + _ConvertMemoryField(total_map[v]['resident']) + ',' +
+ _ConvertMemoryField(total_map[v]['unevictable']) + ',')
+ print ''
+
+
+def main(argv):
+ _DumpCSV(_CollectMemoryStats(sys.stdin, [value for (key, value) in _ENTRIES]))
+
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/chromium/tools/android/memdump/memsymbols.py b/chromium/tools/android/memdump/memsymbols.py
new file mode 100755
index 00000000000..372196303ba
--- /dev/null
+++ b/chromium/tools/android/memdump/memsymbols.py
@@ -0,0 +1,152 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import base64
+import os
+import sys
+import re
+
+from optparse import OptionParser
+
+"""Extracts the list of resident symbols of a library loaded in a process.
+
+This scripts combines the extended output of memdump for a given process
+(obtained through memdump -x PID) and the symbol table of a .so loaded in that
+process (obtained through nm -C lib-with-symbols.so), filtering out only those
+symbols that, at the time of the snapshot, were resident in memory (that are,
+the symbols which start address belongs to a mapped page of the .so which was
+resident at the time of the snapshot).
+The aim is to perform a "code coverage"-like profiling of a binary, intersecting
+run-time information (list of resident pages) and debug symbols.
+"""
+
+_PAGE_SIZE = 4096
+
+
+def _TestBit(word, bit):
+ assert(bit >= 0 and bit < 8)
+ return not not ((word >> bit) & 1)
+
+
+def _HexAddr(addr):
+ return hex(addr)[2:].zfill(8)
+
+
+def _GetResidentPagesSet(memdump_contents, lib_name, verbose):
+ """Parses the memdump output and extracts the resident page set for lib_name.
+ Args:
+ memdump_contents: Array of strings (lines) of a memdump output.
+ lib_name: A string containing the name of the library.so to be matched.
+ verbose: Print a verbose header for each mapping matched.
+
+ Returns:
+ A set of resident pages (the key is the page index) for all the
+ mappings matching .*lib_name.
+ """
+ resident_pages = set()
+ MAP_RX = re.compile(
+ r'^([0-9a-f]+)-([0-9a-f]+) ([\w-]+) ([0-9a-f]+) .* "(.*)" \[(.*)\]$')
+ for line in memdump_contents:
+ line = line.rstrip('\r\n')
+ if line.startswith('[ PID'):
+ continue
+
+ r = MAP_RX.match(line)
+ if not r:
+ sys.stderr.write('Skipping %s from %s\n' % (line, memdump_file))
+ continue
+
+ map_start = int(r.group(1), 16)
+ map_end = int(r.group(2), 16)
+ prot = r.group(3)
+ offset = int(r.group(4), 16)
+ assert(offset % _PAGE_SIZE == 0)
+ lib = r.group(5)
+ enc_bitmap = r.group(6)
+
+ if not lib.endswith(lib_name):
+ continue
+
+ bitmap = base64.b64decode(enc_bitmap)
+ map_pages_count = (map_end - map_start + 1) / _PAGE_SIZE
+ bitmap_pages_count = len(bitmap) * 8
+
+ if verbose:
+ print 'Found %s: mapped %d pages in mode %s @ offset %s.' % (
+ lib, map_pages_count, prot, _HexAddr(offset))
+ print ' Map range in the process VA: [%s - %s]. Len: %s' % (
+ _HexAddr(map_start),
+ _HexAddr(map_end),
+ _HexAddr(map_pages_count * _PAGE_SIZE))
+ print ' Corresponding addresses in the binary: [%s - %s]. Len: %s' % (
+ _HexAddr(offset),
+ _HexAddr(offset + map_end - map_start),
+ _HexAddr(map_pages_count * _PAGE_SIZE))
+ print ' Bitmap: %d pages' % bitmap_pages_count
+ print ''
+
+ assert(bitmap_pages_count >= map_pages_count)
+ for i in xrange(map_pages_count):
+ bitmap_idx = i / 8
+ bitmap_off = i % 8
+ if (bitmap_idx < len(bitmap) and
+ _TestBit(ord(bitmap[bitmap_idx]), bitmap_off)):
+ resident_pages.add(offset / _PAGE_SIZE + i)
+ return resident_pages
+
+
+def main(argv):
+ NM_RX = re.compile(r'^([0-9a-f]+)\s+.*$')
+
+ parser = OptionParser()
+ parser.add_option("-r", "--reverse",
+ action="store_true", dest="reverse", default=False,
+ help="Print out non present symbols")
+ parser.add_option("-v", "--verbose",
+ action="store_true", dest="verbose", default=False,
+ help="Print out verbose debug information.")
+
+ (options, args) = parser.parse_args()
+
+ if len(args) != 3:
+ print 'Usage: %s [-v] memdump.file nm.file library.so' % (
+ os.path.basename(argv[0]))
+ return 1
+
+ memdump_file = args[0]
+ nm_file = args[1]
+ lib_name = args[2]
+
+ if memdump_file == '-':
+ memdump_contents = sys.stdin.readlines()
+ else:
+ memdump_contents = open(memdump_file, 'r').readlines()
+ resident_pages = _GetResidentPagesSet(memdump_contents,
+ lib_name,
+ options.verbose)
+
+ # Process the nm symbol table, filtering out the resident symbols.
+ nm_fh = open(nm_file, 'r')
+ for line in nm_fh:
+ line = line.rstrip('\r\n')
+ # Skip undefined symbols (lines with no address).
+ if line.startswith(' '):
+ continue
+
+ r = NM_RX.match(line)
+ if not r:
+ sys.stderr.write('Skipping %s from %s\n' % (line, nm_file))
+ continue
+
+ sym_addr = int(r.group(1), 16)
+ sym_page = sym_addr / _PAGE_SIZE
+ last_sym_matched = (sym_page in resident_pages)
+ if (sym_page in resident_pages) != options.reverse:
+ print line
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/tools/android/remove_strings.py b/chromium/tools/android/remove_strings.py
new file mode 100755
index 00000000000..b8c4807d88e
--- /dev/null
+++ b/chromium/tools/android/remove_strings.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Remove strings by name from a GRD file."""
+
+import optparse
+import re
+import sys
+
+
+def RemoveStrings(grd_path, string_names):
+ """Removes strings with the given names from a GRD file. Overwrites the file.
+
+ Args:
+ grd_path: path to the GRD file.
+ string_names: a list of string names to be removed.
+ """
+ with open(grd_path, 'r') as f:
+ grd = f.read()
+ names_pattern = '|'.join(map(re.escape, string_names))
+ pattern = r'<message [^>]*name="(%s)".*?</message>\s*' % names_pattern
+ grd = re.sub(pattern, '', grd, flags=re.DOTALL)
+ with open(grd_path, 'w') as f:
+ f.write(grd)
+
+
+def ParseArgs(args):
+ usage = 'usage: %prog GRD_PATH...'
+ parser = optparse.OptionParser(
+ usage=usage, description='Remove strings from GRD files. Reads string '
+ 'names from stdin, and removes strings with those names from the listed '
+ 'GRD files.')
+ options, args = parser.parse_args(args=args)
+ if not args:
+ parser.error('must provide GRD_PATH argument(s)')
+ return args
+
+
+def main(args=None):
+ grd_paths = ParseArgs(args)
+ strings_to_remove = filter(None, map(str.strip, sys.stdin.readlines()))
+ for grd_path in grd_paths:
+ RemoveStrings(grd_path, strings_to_remove)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/bash-completion b/chromium/tools/bash-completion
new file mode 100644
index 00000000000..19172dab145
--- /dev/null
+++ b/chromium/tools/bash-completion
@@ -0,0 +1,25 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Flag completion rule for bash.
+# To load in your shell, "source path/to/this/file".
+
+chrome_source=$(cd $(dirname $BASH_SOURCE)/.. && pwd)
+
+_chrome_flag() {
+ local cur targets
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ targets=$(cd $chrome_source; \
+ git ls-files '*switches*' | \
+ xargs sed -ne 's/^[^/]*"\([^" /]\{1,\}\)".*/--\1/p')
+ COMPREPLY=($(compgen -W "$targets" -- "$cur"))
+ return 0
+}
+
+complete -F _chrome_flag google-chrome
+complete -F _chrome_flag chrome
+if [ $(uname) = "Darwin" ]
+then
+ complete -F _chrome_flag Chromium
+fi
diff --git a/chromium/tools/bisect-builds.py b/chromium/tools/bisect-builds.py
new file mode 100755
index 00000000000..d9f394736ba
--- /dev/null
+++ b/chromium/tools/bisect-builds.py
@@ -0,0 +1,718 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Snapshot Build Bisect Tool
+
+This script bisects a snapshot archive using binary search. It starts at
+a bad revision (it will try to guess HEAD) and asks for a last known-good
+revision. It will then binary search across this revision range by downloading,
+unzipping, and opening Chromium for you. After testing the specific revision,
+it will ask you whether it is good or bad before continuing the search.
+"""
+
+# The root URL for storage.
+BASE_URL = 'http://commondatastorage.googleapis.com/chromium-browser-snapshots'
+
+# The root URL for official builds.
+OFFICIAL_BASE_URL = 'http://master.chrome.corp.google.com/official_builds'
+
+# Changelogs URL.
+CHANGELOG_URL = 'http://build.chromium.org/f/chromium/' \
+ 'perf/dashboard/ui/changelog.html?' \
+ 'url=/trunk/src&range=%d%%3A%d'
+
+# Official Changelogs URL.
+OFFICIAL_CHANGELOG_URL = 'http://omahaproxy.appspot.com/'\
+ 'changelog?old_version=%s&new_version=%s'
+
+# DEPS file URL.
+DEPS_FILE= 'http://src.chromium.org/viewvc/chrome/trunk/src/DEPS?revision=%d'
+# Blink Changelogs URL.
+BLINK_CHANGELOG_URL = 'http://build.chromium.org/f/chromium/' \
+ 'perf/dashboard/ui/changelog_blink.html?' \
+ 'url=/trunk&range=%d%%3A%d'
+
+DONE_MESSAGE_GOOD_MIN = 'You are probably looking for a change made after %s ' \
+ '(known good), but no later than %s (first known bad).'
+DONE_MESSAGE_GOOD_MAX = 'You are probably looking for a change made after %s ' \
+ '(known bad), but no later than %s (first known good).'
+
+###############################################################################
+
+import math
+import optparse
+import os
+import pipes
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+import threading
+import urllib
+from distutils.version import LooseVersion
+from xml.etree import ElementTree
+import zipfile
+
+
+class PathContext(object):
+ """A PathContext is used to carry the information used to construct URLs and
+ paths when dealing with the storage server and archives."""
+ def __init__(self, platform, good_revision, bad_revision, is_official):
+ super(PathContext, self).__init__()
+ # Store off the input parameters.
+ self.platform = platform # What's passed in to the '-a/--archive' option.
+ self.good_revision = good_revision
+ self.bad_revision = bad_revision
+ self.is_official = is_official
+
+ # The name of the ZIP file in a revision directory on the server.
+ self.archive_name = None
+
+ # Set some internal members:
+ # _listing_platform_dir = Directory that holds revisions. Ends with a '/'.
+ # _archive_extract_dir = Uncompressed directory in the archive_name file.
+ # _binary_name = The name of the executable to run.
+ if self.platform in ('linux', 'linux64', 'linux-arm'):
+ self._binary_name = 'chrome'
+ elif self.platform == 'mac':
+ self.archive_name = 'chrome-mac.zip'
+ self._archive_extract_dir = 'chrome-mac'
+ elif self.platform == 'win':
+ self.archive_name = 'chrome-win32.zip'
+ self._archive_extract_dir = 'chrome-win32'
+ self._binary_name = 'chrome.exe'
+ else:
+ raise Exception('Invalid platform: %s' % self.platform)
+
+ if is_official:
+ if self.platform == 'linux':
+ self._listing_platform_dir = 'lucid32bit/'
+ self.archive_name = 'chrome-lucid32bit.zip'
+ self._archive_extract_dir = 'chrome-lucid32bit'
+ elif self.platform == 'linux64':
+ self._listing_platform_dir = 'lucid64bit/'
+ self.archive_name = 'chrome-lucid64bit.zip'
+ self._archive_extract_dir = 'chrome-lucid64bit'
+ elif self.platform == 'mac':
+ self._listing_platform_dir = 'mac/'
+ self._binary_name = 'Google Chrome.app/Contents/MacOS/Google Chrome'
+ elif self.platform == 'win':
+ self._listing_platform_dir = 'win/'
+ else:
+ if self.platform in ('linux', 'linux64', 'linux-arm'):
+ self.archive_name = 'chrome-linux.zip'
+ self._archive_extract_dir = 'chrome-linux'
+ if self.platform == 'linux':
+ self._listing_platform_dir = 'Linux/'
+ elif self.platform == 'linux64':
+ self._listing_platform_dir = 'Linux_x64/'
+ elif self.platform == 'linux-arm':
+ self._listing_platform_dir = 'Linux_ARM_Cross-Compile/'
+ elif self.platform == 'mac':
+ self._listing_platform_dir = 'Mac/'
+ self._binary_name = 'Chromium.app/Contents/MacOS/Chromium'
+ elif self.platform == 'win':
+ self._listing_platform_dir = 'Win/'
+
+ def GetListingURL(self, marker=None):
+ """Returns the URL for a directory listing, with an optional marker."""
+ marker_param = ''
+ if marker:
+ marker_param = '&marker=' + str(marker)
+ return BASE_URL + '/?delimiter=/&prefix=' + self._listing_platform_dir + \
+ marker_param
+
+ def GetDownloadURL(self, revision):
+ """Gets the download URL for a build archive of a specific revision."""
+ if self.is_official:
+ return "%s/%s/%s%s" % (
+ OFFICIAL_BASE_URL, revision, self._listing_platform_dir,
+ self.archive_name)
+ else:
+ return "%s/%s%s/%s" % (
+ BASE_URL, self._listing_platform_dir, revision, self.archive_name)
+
+ def GetLastChangeURL(self):
+ """Returns a URL to the LAST_CHANGE file."""
+ return BASE_URL + '/' + self._listing_platform_dir + 'LAST_CHANGE'
+
+ def GetLaunchPath(self):
+ """Returns a relative path (presumably from the archive extraction location)
+ that is used to run the executable."""
+ return os.path.join(self._archive_extract_dir, self._binary_name)
+
+ def ParseDirectoryIndex(self):
+ """Parses the Google Storage directory listing into a list of revision
+ numbers."""
+
+ def _FetchAndParse(url):
+ """Fetches a URL and returns a 2-Tuple of ([revisions], next-marker). If
+ next-marker is not None, then the listing is a partial listing and another
+ fetch should be performed with next-marker being the marker= GET
+ parameter."""
+ handle = urllib.urlopen(url)
+ document = ElementTree.parse(handle)
+
+ # All nodes in the tree are namespaced. Get the root's tag name to extract
+ # the namespace. Etree does namespaces as |{namespace}tag|.
+ root_tag = document.getroot().tag
+ end_ns_pos = root_tag.find('}')
+ if end_ns_pos == -1:
+ raise Exception("Could not locate end namespace for directory index")
+ namespace = root_tag[:end_ns_pos + 1]
+
+ # Find the prefix (_listing_platform_dir) and whether or not the list is
+ # truncated.
+ prefix_len = len(document.find(namespace + 'Prefix').text)
+ next_marker = None
+ is_truncated = document.find(namespace + 'IsTruncated')
+ if is_truncated is not None and is_truncated.text.lower() == 'true':
+ next_marker = document.find(namespace + 'NextMarker').text
+
+ # Get a list of all the revisions.
+ all_prefixes = document.findall(namespace + 'CommonPrefixes/' +
+ namespace + 'Prefix')
+ # The <Prefix> nodes have content of the form of
+ # |_listing_platform_dir/revision/|. Strip off the platform dir and the
+ # trailing slash to just have a number.
+ revisions = []
+ for prefix in all_prefixes:
+ revnum = prefix.text[prefix_len:-1]
+ try:
+ revnum = int(revnum)
+ revisions.append(revnum)
+ except ValueError:
+ pass
+ return (revisions, next_marker)
+
+ # Fetch the first list of revisions.
+ (revisions, next_marker) = _FetchAndParse(self.GetListingURL())
+
+ # If the result list was truncated, refetch with the next marker. Do this
+ # until an entire directory listing is done.
+ while next_marker:
+ next_url = self.GetListingURL(next_marker)
+ (new_revisions, next_marker) = _FetchAndParse(next_url)
+ revisions.extend(new_revisions)
+ return revisions
+
+ def GetRevList(self):
+ """Gets the list of revision numbers between self.good_revision and
+ self.bad_revision."""
+ # Download the revlist and filter for just the range between good and bad.
+ minrev = min(self.good_revision, self.bad_revision)
+ maxrev = max(self.good_revision, self.bad_revision)
+ revlist = map(int, self.ParseDirectoryIndex())
+ revlist = [x for x in revlist if x >= int(minrev) and x <= int(maxrev)]
+ revlist.sort()
+ return revlist
+
+ def GetOfficialBuildsList(self):
+ """Gets the list of official build numbers between self.good_revision and
+ self.bad_revision."""
+ # Download the revlist and filter for just the range between good and bad.
+ minrev = min(self.good_revision, self.bad_revision)
+ maxrev = max(self.good_revision, self.bad_revision)
+ handle = urllib.urlopen(OFFICIAL_BASE_URL)
+ dirindex = handle.read()
+ handle.close()
+ build_numbers = re.findall(r'<a href="([0-9][0-9].*)/">', dirindex)
+ final_list = []
+ i = 0
+ parsed_build_numbers = [LooseVersion(x) for x in build_numbers]
+ for build_number in sorted(parsed_build_numbers):
+ path = OFFICIAL_BASE_URL + '/' + str(build_number) + '/' + \
+ self._listing_platform_dir + self.archive_name
+ i = i + 1
+ try:
+ connection = urllib.urlopen(path)
+ connection.close()
+ if build_number > maxrev:
+ break
+ if build_number >= minrev:
+ final_list.append(str(build_number))
+ except urllib.HTTPError, e:
+ pass
+ return final_list
+
+def UnzipFilenameToDir(filename, dir):
+ """Unzip |filename| to directory |dir|."""
+ cwd = os.getcwd()
+ if not os.path.isabs(filename):
+ filename = os.path.join(cwd, filename)
+ zf = zipfile.ZipFile(filename)
+ # Make base.
+ if not os.path.isdir(dir):
+ os.mkdir(dir)
+ os.chdir(dir)
+ # Extract files.
+ for info in zf.infolist():
+ name = info.filename
+ if name.endswith('/'): # dir
+ if not os.path.isdir(name):
+ os.makedirs(name)
+ else: # file
+ dir = os.path.dirname(name)
+ if not os.path.isdir(dir):
+ os.makedirs(dir)
+ out = open(name, 'wb')
+ out.write(zf.read(name))
+ out.close()
+ # Set permissions. Permission info in external_attr is shifted 16 bits.
+ os.chmod(name, info.external_attr >> 16L)
+ os.chdir(cwd)
+
+
+def FetchRevision(context, rev, filename, quit_event=None, progress_event=None):
+ """Downloads and unzips revision |rev|.
+ @param context A PathContext instance.
+ @param rev The Chromium revision number/tag to download.
+ @param filename The destination for the downloaded file.
+ @param quit_event A threading.Event which will be set by the master thread to
+ indicate that the download should be aborted.
+ @param progress_event A threading.Event which will be set by the master thread
+ to indicate that the progress of the download should be
+ displayed.
+ """
+ def ReportHook(blocknum, blocksize, totalsize):
+ if quit_event and quit_event.isSet():
+ raise RuntimeError("Aborting download of revision %s" % str(rev))
+ if progress_event and progress_event.isSet():
+ size = blocknum * blocksize
+ if totalsize == -1: # Total size not known.
+ progress = "Received %d bytes" % size
+ else:
+ size = min(totalsize, size)
+ progress = "Received %d of %d bytes, %.2f%%" % (
+ size, totalsize, 100.0 * size / totalsize)
+ # Send a \r to let all progress messages use just one line of output.
+ sys.stdout.write("\r" + progress)
+ sys.stdout.flush()
+
+ download_url = context.GetDownloadURL(rev)
+ try:
+ urllib.urlretrieve(download_url, filename, ReportHook)
+ if progress_event and progress_event.isSet():
+ print
+ except RuntimeError, e:
+ pass
+
+
+def RunRevision(context, revision, zipfile, profile, num_runs, command, args):
+ """Given a zipped revision, unzip it and run the test."""
+ print "Trying revision %s..." % str(revision)
+
+ # Create a temp directory and unzip the revision into it.
+ cwd = os.getcwd()
+ tempdir = tempfile.mkdtemp(prefix='bisect_tmp')
+ UnzipFilenameToDir(zipfile, tempdir)
+ os.chdir(tempdir)
+
+ # Run the build as many times as specified.
+ testargs = ['--user-data-dir=%s' % profile] + args
+ # The sandbox must be run as root on Official Chrome, so bypass it.
+ if context.is_official and context.platform.startswith('linux'):
+ testargs.append('--no-sandbox')
+
+ runcommand = []
+ for token in command.split():
+ if token == "%a":
+ runcommand.extend(testargs)
+ else:
+ runcommand.append( \
+ token.replace('%p', context.GetLaunchPath()) \
+ .replace('%s', ' '.join(testargs)))
+
+ for i in range(0, num_runs):
+ subproc = subprocess.Popen(runcommand,
+ bufsize=-1,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ (stdout, stderr) = subproc.communicate()
+
+ os.chdir(cwd)
+ try:
+ shutil.rmtree(tempdir, True)
+ except Exception, e:
+ pass
+
+ return (subproc.returncode, stdout, stderr)
+
+
+def AskIsGoodBuild(rev, official_builds, status, stdout, stderr):
+ """Ask the user whether build |rev| is good or bad."""
+ # Loop until we get a response that we can parse.
+ while True:
+ response = raw_input('Revision %s is [(g)ood/(b)ad/(u)nknown/(q)uit]: ' %
+ str(rev))
+ if response and response in ('g', 'b', 'u'):
+ return response
+ if response and response == 'q':
+ raise SystemExit()
+
+
+class DownloadJob(object):
+ """DownloadJob represents a task to download a given Chromium revision."""
+ def __init__(self, context, name, rev, zipfile):
+ super(DownloadJob, self).__init__()
+ # Store off the input parameters.
+ self.context = context
+ self.name = name
+ self.rev = rev
+ self.zipfile = zipfile
+ self.quit_event = threading.Event()
+ self.progress_event = threading.Event()
+
+ def Start(self):
+ """Starts the download."""
+ fetchargs = (self.context,
+ self.rev,
+ self.zipfile,
+ self.quit_event,
+ self.progress_event)
+ self.thread = threading.Thread(target=FetchRevision,
+ name=self.name,
+ args=fetchargs)
+ self.thread.start()
+
+ def Stop(self):
+ """Stops the download which must have been started previously."""
+ self.quit_event.set()
+ self.thread.join()
+ os.unlink(self.zipfile)
+
+ def WaitFor(self):
+ """Prints a message and waits for the download to complete. The download
+ must have been started previously."""
+ print "Downloading revision %s..." % str(self.rev)
+ self.progress_event.set() # Display progress of download.
+ self.thread.join()
+
+
+def Bisect(platform,
+ official_builds,
+ good_rev=0,
+ bad_rev=0,
+ num_runs=1,
+ command="%p %a",
+ try_args=(),
+ profile=None,
+ evaluate=AskIsGoodBuild):
+ """Given known good and known bad revisions, run a binary search on all
+ archived revisions to determine the last known good revision.
+
+ @param platform Which build to download/run ('mac', 'win', 'linux64', etc.).
+ @param official_builds Specify build type (Chromium or Official build).
+ @param good_rev Number/tag of the known good revision.
+ @param bad_rev Number/tag of the known bad revision.
+ @param num_runs Number of times to run each build for asking good/bad.
+ @param try_args A tuple of arguments to pass to the test application.
+ @param profile The name of the user profile to run with.
+ @param evaluate A function which returns 'g' if the argument build is good,
+ 'b' if it's bad or 'u' if unknown.
+
+ Threading is used to fetch Chromium revisions in the background, speeding up
+ the user's experience. For example, suppose the bounds of the search are
+ good_rev=0, bad_rev=100. The first revision to be checked is 50. Depending on
+ whether revision 50 is good or bad, the next revision to check will be either
+ 25 or 75. So, while revision 50 is being checked, the script will download
+ revisions 25 and 75 in the background. Once the good/bad verdict on rev 50 is
+ known:
+
+ - If rev 50 is good, the download of rev 25 is cancelled, and the next test
+ is run on rev 75.
+
+ - If rev 50 is bad, the download of rev 75 is cancelled, and the next test
+ is run on rev 25.
+ """
+
+ if not profile:
+ profile = 'profile'
+
+ context = PathContext(platform, good_rev, bad_rev, official_builds)
+ cwd = os.getcwd()
+
+
+
+ print "Downloading list of known revisions..."
+ _GetDownloadPath = lambda rev: os.path.join(cwd,
+ '%s-%s' % (str(rev), context.archive_name))
+ if official_builds:
+ revlist = context.GetOfficialBuildsList()
+ else:
+ revlist = context.GetRevList()
+
+ # Get a list of revisions to bisect across.
+ if len(revlist) < 2: # Don't have enough builds to bisect.
+ msg = 'We don\'t have enough builds to bisect. revlist: %s' % revlist
+ raise RuntimeError(msg)
+
+ # Figure out our bookends and first pivot point; fetch the pivot revision.
+ minrev = 0
+ maxrev = len(revlist) - 1
+ pivot = maxrev / 2
+ rev = revlist[pivot]
+ zipfile = _GetDownloadPath(rev)
+ fetch = DownloadJob(context, 'initial_fetch', rev, zipfile)
+ fetch.Start()
+ fetch.WaitFor()
+
+ # Binary search time!
+ while fetch and fetch.zipfile and maxrev - minrev > 1:
+ if bad_rev < good_rev:
+ min_str, max_str = "bad", "good"
+ else:
+ min_str, max_str = "good", "bad"
+ print 'Bisecting range [%s (%s), %s (%s)].' % (revlist[minrev], min_str, \
+ revlist[maxrev], max_str)
+
+ # Pre-fetch next two possible pivots
+ # - down_pivot is the next revision to check if the current revision turns
+ # out to be bad.
+ # - up_pivot is the next revision to check if the current revision turns
+ # out to be good.
+ down_pivot = int((pivot - minrev) / 2) + minrev
+ down_fetch = None
+ if down_pivot != pivot and down_pivot != minrev:
+ down_rev = revlist[down_pivot]
+ down_fetch = DownloadJob(context, 'down_fetch', down_rev,
+ _GetDownloadPath(down_rev))
+ down_fetch.Start()
+
+ up_pivot = int((maxrev - pivot) / 2) + pivot
+ up_fetch = None
+ if up_pivot != pivot and up_pivot != maxrev:
+ up_rev = revlist[up_pivot]
+ up_fetch = DownloadJob(context, 'up_fetch', up_rev,
+ _GetDownloadPath(up_rev))
+ up_fetch.Start()
+
+ # Run test on the pivot revision.
+ status = None
+ stdout = None
+ stderr = None
+ try:
+ (status, stdout, stderr) = RunRevision(context,
+ rev,
+ fetch.zipfile,
+ profile,
+ num_runs,
+ command,
+ try_args)
+ except Exception, e:
+ print >>sys.stderr, e
+ fetch.Stop()
+ fetch = None
+
+ # Call the evaluate function to see if the current revision is good or bad.
+ # On that basis, kill one of the background downloads and complete the
+ # other, as described in the comments above.
+ try:
+ answer = evaluate(rev, official_builds, status, stdout, stderr)
+ if answer == 'g' and good_rev < bad_rev or \
+ answer == 'b' and bad_rev < good_rev:
+ minrev = pivot
+ if down_fetch:
+ down_fetch.Stop() # Kill the download of the older revision.
+ if up_fetch:
+ up_fetch.WaitFor()
+ pivot = up_pivot
+ fetch = up_fetch
+ elif answer == 'b' and good_rev < bad_rev or \
+ answer == 'g' and bad_rev < good_rev:
+ maxrev = pivot
+ if up_fetch:
+ up_fetch.Stop() # Kill the download of the newer revision.
+ if down_fetch:
+ down_fetch.WaitFor()
+ pivot = down_pivot
+ fetch = down_fetch
+ elif answer == 'u':
+ # Nuke the revision from the revlist and choose a new pivot.
+ revlist.pop(pivot)
+ maxrev -= 1 # Assumes maxrev >= pivot.
+
+ if maxrev - minrev > 1:
+ # Alternate between using down_pivot or up_pivot for the new pivot
+ # point, without affecting the range. Do this instead of setting the
+ # pivot to the midpoint of the new range because adjacent revisions
+ # are likely affected by the same issue that caused the (u)nknown
+ # response.
+ if up_fetch and down_fetch:
+ fetch = [up_fetch, down_fetch][len(revlist) % 2]
+ elif up_fetch:
+ fetch = up_fetch
+ else:
+ fetch = down_fetch
+ fetch.WaitFor()
+ if fetch == up_fetch:
+ pivot = up_pivot - 1 # Subtracts 1 because revlist was resized.
+ else:
+ pivot = down_pivot
+ zipfile = fetch.zipfile
+
+ if down_fetch and fetch != down_fetch:
+ down_fetch.Stop()
+ if up_fetch and fetch != up_fetch:
+ up_fetch.Stop()
+ else:
+ assert False, "Unexpected return value from evaluate(): " + answer
+ except SystemExit:
+ print "Cleaning up..."
+ for f in [_GetDownloadPath(revlist[down_pivot]),
+ _GetDownloadPath(revlist[up_pivot])]:
+ try:
+ os.unlink(f)
+ except OSError:
+ pass
+ sys.exit(0)
+
+ rev = revlist[pivot]
+
+ return (revlist[minrev], revlist[maxrev])
+
+
+def GetBlinkRevisionForChromiumRevision(rev):
+ """Returns the blink revision that was in chromium's DEPS file at
+ chromium revision |rev|."""
+ # . doesn't match newlines without re.DOTALL, so this is safe.
+ blink_re = re.compile(r'webkit_revision.:\D*(\d+)')
+ url = urllib.urlopen(DEPS_FILE % rev)
+ m = blink_re.search(url.read())
+ url.close()
+ if m:
+ return int(m.group(1))
+ else:
+ raise Exception('Could not get blink revision for cr rev %d' % rev)
+
+
+def GetChromiumRevision(url):
+ """Returns the chromium revision read from given URL."""
+ try:
+ # Location of the latest build revision number
+ return int(urllib.urlopen(url).read())
+ except Exception, e:
+ print('Could not determine latest revision. This could be bad...')
+ return 999999999
+
+
+def main():
+ usage = ('%prog [options] [-- chromium-options]\n'
+ 'Perform binary search on the snapshot builds to find a minimal\n'
+ 'range of revisions where a behavior change happened. The\n'
+ 'behaviors are described as "good" and "bad".\n'
+ 'It is NOT assumed that the behavior of the later revision is\n'
+ 'the bad one.\n'
+ '\n'
+ 'Revision numbers should use\n'
+ ' Official versions (e.g. 1.0.1000.0) for official builds. (-o)\n'
+ ' SVN revisions (e.g. 123456) for chromium builds, from trunk.\n'
+ ' Use base_trunk_revision from http://omahaproxy.appspot.com/\n'
+ ' for earlier revs.\n'
+ ' Chrome\'s about: build number and omahaproxy branch_revision\n'
+ ' are incorrect, they are from branches.\n'
+ '\n'
+ 'Tip: add "-- --no-first-run" to bypass the first run prompts.')
+ parser = optparse.OptionParser(usage=usage)
+ # Strangely, the default help output doesn't include the choice list.
+ choices = ['mac', 'win', 'linux', 'linux64', 'linux-arm']
+ # linux-chromiumos lacks a continuous archive http://crbug.com/78158
+ parser.add_option('-a', '--archive',
+ choices = choices,
+ help = 'The buildbot archive to bisect [%s].' %
+ '|'.join(choices))
+ parser.add_option('-o', action="store_true", dest='official_builds',
+ help = 'Bisect across official ' +
+ 'Chrome builds (internal only) instead of ' +
+ 'Chromium archives.')
+ parser.add_option('-b', '--bad', type = 'str',
+ help = 'A bad revision to start bisection. ' +
+ 'May be earlier or later than the good revision. ' +
+ 'Default is HEAD.')
+ parser.add_option('-g', '--good', type = 'str',
+ help = 'A good revision to start bisection. ' +
+ 'May be earlier or later than the bad revision. ' +
+ 'Default is 0.')
+ parser.add_option('-p', '--profile', '--user-data-dir', type = 'str',
+ help = 'Profile to use; this will not reset every run. ' +
+ 'Defaults to a clean profile.', default = 'profile')
+ parser.add_option('-t', '--times', type = 'int',
+ help = 'Number of times to run each build before asking ' +
+ 'if it\'s good or bad. Temporary profiles are reused.',
+ default = 1)
+ parser.add_option('-c', '--command', type = 'str',
+ help = 'Command to execute. %p and %a refer to Chrome ' +
+ 'executable and specified extra arguments respectively. ' +
+ 'Use %s to specify all extra arguments as one string. ' +
+ 'Defaults to "%p %a". Note that any extra paths ' +
+ 'specified should be absolute.',
+ default = '%p %a');
+ (opts, args) = parser.parse_args()
+
+ if opts.archive is None:
+ print 'Error: missing required parameter: --archive'
+ print
+ parser.print_help()
+ return 1
+
+ # Create the context. Initialize 0 for the revisions as they are set below.
+ context = PathContext(opts.archive, 0, 0, opts.official_builds)
+ # Pick a starting point, try to get HEAD for this.
+ if opts.bad:
+ bad_rev = opts.bad
+ else:
+ bad_rev = '999.0.0.0'
+ if not opts.official_builds:
+ bad_rev = GetChromiumRevision(context.GetLastChangeURL())
+
+ # Find out when we were good.
+ if opts.good:
+ good_rev = opts.good
+ else:
+ good_rev = '0.0.0.0' if opts.official_builds else 0
+
+ if opts.official_builds:
+ good_rev = LooseVersion(good_rev)
+ bad_rev = LooseVersion(bad_rev)
+ else:
+ good_rev = int(good_rev)
+ bad_rev = int(bad_rev)
+
+ if opts.times < 1:
+ print('Number of times to run (%d) must be greater than or equal to 1.' %
+ opts.times)
+ parser.print_help()
+ return 1
+
+ (min_chromium_rev, max_chromium_rev) = Bisect(
+ opts.archive, opts.official_builds, good_rev, bad_rev, opts.times,
+ opts.command, args, opts.profile)
+
+ # Get corresponding blink revisions.
+ try:
+ min_blink_rev = GetBlinkRevisionForChromiumRevision(min_chromium_rev)
+ max_blink_rev = GetBlinkRevisionForChromiumRevision(max_chromium_rev)
+ except Exception, e:
+ # Silently ignore the failure.
+ min_blink_rev, max_blink_rev = 0, 0
+
+ # We're done. Let the user know the results in an official manner.
+ if good_rev > bad_rev:
+ print DONE_MESSAGE_GOOD_MAX % (str(min_chromium_rev), str(max_chromium_rev))
+ else:
+ print DONE_MESSAGE_GOOD_MIN % (str(min_chromium_rev), str(max_chromium_rev))
+
+ if min_blink_rev != max_blink_rev:
+ print 'BLINK CHANGELOG URL:'
+ print ' ' + BLINK_CHANGELOG_URL % (max_blink_rev, min_blink_rev)
+ print 'CHANGELOG URL:'
+ if opts.official_builds:
+ print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)
+ else:
+ print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/bisect-manual-test.py b/chromium/tools/bisect-manual-test.py
new file mode 100755
index 00000000000..62aa072c035
--- /dev/null
+++ b/chromium/tools/bisect-manual-test.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Simple script which asks user to manually check result of bisection.
+
+Typically used as by the run-bisect-manual-test.py script.
+"""
+
+import os
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), 'telemetry'))
+from telemetry.core import browser_finder
+from telemetry.core import browser_options
+
+
+def _StartManualTest(options):
+ """Start browser then ask the user whether build is good or bad."""
+ browser_to_create = browser_finder.FindBrowser(options)
+ print 'Starting browser: %s.' % options.browser_type
+ with browser_to_create.Create() as browser:
+
+ # Loop until we get a response that we can parse.
+ while True:
+ sys.stderr.write('Revision is [(g)ood/(b)ad]: ')
+ response = raw_input()
+ if response and response in ('g', 'b'):
+ if response in ('g'):
+ print "RESULT manual_test: manual_test= 1"
+ else:
+ print "RESULT manual_test: manual_test= 0"
+ break
+
+ browser.Close()
+
+
+def main():
+ usage = ('%prog [options]\n'
+ 'Starts browser with an optional url and asks user whether '
+ 'revision is good or bad.\n')
+
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser(usage)
+ options, args = parser.parse_args()
+
+ _StartManualTest(options)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/bisect-perf-regression.py b/chromium/tools/bisect-perf-regression.py
new file mode 100755
index 00000000000..4947ece6571
--- /dev/null
+++ b/chromium/tools/bisect-perf-regression.py
@@ -0,0 +1,2456 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Performance Test Bisect Tool
+
+This script bisects a series of changelists using binary search. It starts at
+a bad revision where a performance metric has regressed, and asks for a last
+known-good revision. It will then binary search across this revision range by
+syncing, building, and running a performance test. If the change is
+suspected to occur as a result of WebKit/V8 changes, the script will
+further bisect changes to those depots and attempt to narrow down the revision
+range.
+
+
+An example usage (using svn cl's):
+
+./tools/bisect-perf-regression.py -c\
+"out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\
+-g 168222 -b 168232 -m shutdown/simple-user-quit
+
+Be aware that if you're using the git workflow and specify an svn revision,
+the script will attempt to find the git SHA1 where svn changes up to that
+revision were merged in.
+
+
+An example usage (using git hashes):
+
+./tools/bisect-perf-regression.py -c\
+"out/Release/performance_ui_tests --gtest_filter=ShutdownTest.SimpleUserQuit"\
+-g 1f6e67861535121c5c819c16a666f2436c207e7b\
+-b b732f23b4f81c382db0b23b9035f3dadc7d925bb\
+-m shutdown/simple-user-quit
+
+"""
+
+import errno
+import imp
+import math
+import optparse
+import os
+import re
+import shlex
+import shutil
+import subprocess
+import sys
+import threading
+import time
+
+import bisect_utils
+
+
+# The additional repositories that might need to be bisected.
+# If the repository has any dependant repositories (such as skia/src needs
+# skia/include and skia/gyp to be updated), specify them in the 'depends'
+# so that they're synced appropriately.
+# Format is:
+# src: path to the working directory.
+# recurse: True if this repositry will get bisected.
+# depends: A list of other repositories that are actually part of the same
+# repository in svn.
+# svn: Needed for git workflow to resolve hashes to svn revisions.
+# from: Parent depot that must be bisected before this is bisected.
+DEPOT_DEPS_NAME = {
+ 'chromium' : {
+ "src" : "src/",
+ "recurse" : True,
+ "depends" : None,
+ "from" : 'cros'
+ },
+ 'webkit' : {
+ "src" : "src/third_party/WebKit",
+ "recurse" : True,
+ "depends" : None,
+ "from" : 'chromium'
+ },
+ 'v8' : {
+ "src" : "src/v8",
+ "recurse" : True,
+ "depends" : None,
+ "build_with": 'v8_bleeding_edge',
+ "from" : 'chromium',
+ "custom_deps": bisect_utils.GCLIENT_CUSTOM_DEPS_V8
+ },
+ 'v8_bleeding_edge' : {
+ "src" : "src/v8_bleeding_edge",
+ "recurse" : False,
+ "depends" : None,
+ "svn": "https://v8.googlecode.com/svn/branches/bleeding_edge",
+ "from" : 'chromium'
+ },
+ 'skia/src' : {
+ "src" : "src/third_party/skia/src",
+ "recurse" : True,
+ "svn" : "http://skia.googlecode.com/svn/trunk/src",
+ "depends" : ['skia/include', 'skia/gyp'],
+ "from" : 'chromium'
+ },
+ 'skia/include' : {
+ "src" : "src/third_party/skia/include",
+ "recurse" : False,
+ "svn" : "http://skia.googlecode.com/svn/trunk/include",
+ "depends" : None,
+ "from" : 'chromium'
+ },
+ 'skia/gyp' : {
+ "src" : "src/third_party/skia/gyp",
+ "recurse" : False,
+ "svn" : "http://skia.googlecode.com/svn/trunk/gyp",
+ "depends" : None,
+ "from" : 'chromium'
+ }
+}
+
+DEPOT_NAMES = DEPOT_DEPS_NAME.keys()
+CROS_SDK_PATH = os.path.join('..', 'cros', 'chromite', 'bin', 'cros_sdk')
+CROS_VERSION_PATTERN = 'new version number from %s'
+CROS_CHROMEOS_PATTERN = 'chromeos-base/chromeos-chrome'
+CROS_TEST_KEY_PATH = os.path.join('..', 'cros', 'chromite', 'ssh_keys',
+ 'testing_rsa')
+CROS_SCRIPT_KEY_PATH = os.path.join('..', 'cros', 'src', 'scripts',
+ 'mod_for_test_scripts', 'ssh_keys',
+ 'testing_rsa')
+
+BUILD_RESULT_SUCCEED = 0
+BUILD_RESULT_FAIL = 1
+BUILD_RESULT_SKIPPED = 2
+
+def CalculateTruncatedMean(data_set, truncate_percent):
+ """Calculates the truncated mean of a set of values.
+
+ Args:
+ data_set: Set of values to use in calculation.
+ truncate_percent: The % from the upper/lower portions of the data set to
+ discard, expressed as a value in [0, 1].
+
+ Returns:
+ The truncated mean as a float.
+ """
+ if len(data_set) > 2:
+ data_set = sorted(data_set)
+
+ discard_num_float = len(data_set) * truncate_percent
+ discard_num_int = int(math.floor(discard_num_float))
+ kept_weight = len(data_set) - discard_num_float * 2
+
+ data_set = data_set[discard_num_int:len(data_set)-discard_num_int]
+
+ weight_left = 1.0 - (discard_num_float - discard_num_int)
+
+ if weight_left < 1:
+ # If the % to discard leaves a fractional portion, need to weight those
+ # values.
+ unweighted_vals = data_set[1:len(data_set)-1]
+ weighted_vals = [data_set[0], data_set[len(data_set)-1]]
+ weighted_vals = [w * weight_left for w in weighted_vals]
+ data_set = weighted_vals + unweighted_vals
+ else:
+ kept_weight = len(data_set)
+
+ truncated_mean = reduce(lambda x, y: float(x) + float(y),
+ data_set) / kept_weight
+
+ return truncated_mean
+
+
+def CalculateStandardDeviation(v):
+ if len(v) == 1:
+ return 0.0
+
+ mean = CalculateTruncatedMean(v, 0.0)
+ variances = [float(x) - mean for x in v]
+ variances = [x * x for x in variances]
+ variance = reduce(lambda x, y: float(x) + float(y), variances) / (len(v) - 1)
+ std_dev = math.sqrt(variance)
+
+ return std_dev
+
+
+def IsStringFloat(string_to_check):
+ """Checks whether or not the given string can be converted to a floating
+ point number.
+
+ Args:
+ string_to_check: Input string to check if it can be converted to a float.
+
+ Returns:
+ True if the string can be converted to a float.
+ """
+ try:
+ float(string_to_check)
+
+ return True
+ except ValueError:
+ return False
+
+
+def IsStringInt(string_to_check):
+ """Checks whether or not the given string can be converted to a integer.
+
+ Args:
+ string_to_check: Input string to check if it can be converted to an int.
+
+ Returns:
+ True if the string can be converted to an int.
+ """
+ try:
+ int(string_to_check)
+
+ return True
+ except ValueError:
+ return False
+
+
+def IsWindows():
+ """Checks whether or not the script is running on Windows.
+
+ Returns:
+ True if running on Windows.
+ """
+ return os.name == 'nt'
+
+
+def RunProcess(command):
+ """Run an arbitrary command. If output from the call is needed, use
+ RunProcessAndRetrieveOutput instead.
+
+ Args:
+ command: A list containing the command and args to execute.
+
+ Returns:
+ The return code of the call.
+ """
+ # On Windows, use shell=True to get PATH interpretation.
+ shell = IsWindows()
+ return subprocess.call(command, shell=shell)
+
+
+def RunProcessAndRetrieveOutput(command):
+ """Run an arbitrary command, returning its output and return code. Since
+ output is collected via communicate(), there will be no output until the
+ call terminates. If you need output while the program runs (ie. so
+ that the buildbot doesn't terminate the script), consider RunProcess().
+
+ Args:
+ command: A list containing the command and args to execute.
+ print_output: Optional parameter to write output to stdout as it's
+ being collected.
+
+ Returns:
+ A tuple of the output and return code.
+ """
+ # On Windows, use shell=True to get PATH interpretation.
+ shell = IsWindows()
+ proc = subprocess.Popen(command,
+ shell=shell,
+ stdout=subprocess.PIPE)
+
+ (output, _) = proc.communicate()
+
+ return (output, proc.returncode)
+
+
+def RunGit(command):
+ """Run a git subcommand, returning its output and return code.
+
+ Args:
+ command: A list containing the args to git.
+
+ Returns:
+ A tuple of the output and return code.
+ """
+ command = ['git'] + command
+
+ return RunProcessAndRetrieveOutput(command)
+
+
+def CheckRunGit(command):
+ """Run a git subcommand, returning its output and return code. Asserts if
+ the return code of the call is non-zero.
+
+ Args:
+ command: A list containing the args to git.
+
+ Returns:
+ A tuple of the output and return code.
+ """
+ (output, return_code) = RunGit(command)
+
+ assert not return_code, 'An error occurred while running'\
+ ' "git %s"' % ' '.join(command)
+ return output
+
+
+def BuildWithMake(threads, targets):
+ cmd = ['make', 'BUILDTYPE=Release']
+
+ if threads:
+ cmd.append('-j%d' % threads)
+
+ cmd += targets
+
+ return_code = RunProcess(cmd)
+
+ return not return_code
+
+
+def BuildWithNinja(threads, targets):
+ cmd = ['ninja', '-C', os.path.join('out', 'Release')]
+
+ if threads:
+ cmd.append('-j%d' % threads)
+
+ cmd += targets
+
+ return_code = RunProcess(cmd)
+
+ return not return_code
+
+
+def BuildWithVisualStudio(targets):
+ path_to_devenv = os.path.abspath(
+ os.path.join(os.environ['VS100COMNTOOLS'], '..', 'IDE', 'devenv.com'))
+ path_to_sln = os.path.join(os.getcwd(), 'chrome', 'chrome.sln')
+ cmd = [path_to_devenv, '/build', 'Release', path_to_sln]
+
+ for t in targets:
+ cmd.extend(['/Project', t])
+
+ return_code = RunProcess(cmd)
+
+ return not return_code
+
+
+class Builder(object):
+ """Builder is used by the bisect script to build relevant targets and deploy.
+ """
+ def Build(self, depot, opts):
+ raise NotImplementedError()
+
+
+class DesktopBuilder(Builder):
+ """DesktopBuilder is used to build Chromium on linux/mac/windows."""
+ def Build(self, depot, opts):
+ """Builds chrome and performance_ui_tests using options passed into
+ the script.
+
+ Args:
+ depot: Current depot being bisected.
+ opts: The options parsed from the command line.
+
+ Returns:
+ True if build was successful.
+ """
+ targets = ['chrome', 'performance_ui_tests']
+
+ threads = None
+ if opts.use_goma:
+ threads = 64
+
+ build_success = False
+ if opts.build_preference == 'make':
+ build_success = BuildWithMake(threads, targets)
+ elif opts.build_preference == 'ninja':
+ if IsWindows():
+ targets = [t + '.exe' for t in targets]
+ build_success = BuildWithNinja(threads, targets)
+ elif opts.build_preference == 'msvs':
+ assert IsWindows(), 'msvs is only supported on Windows.'
+ build_success = BuildWithVisualStudio(targets)
+ else:
+ assert False, 'No build system defined.'
+ return build_success
+
+
+class AndroidBuilder(Builder):
+ """AndroidBuilder is used to build on android."""
+ def InstallAPK(self, opts):
+ """Installs apk to device.
+
+ Args:
+ opts: The options parsed from the command line.
+
+ Returns:
+ True if successful.
+ """
+ path_to_tool = os.path.join('build', 'android', 'adb_install_apk.py')
+ cmd = [path_to_tool, '--apk', 'ChromiumTestShell.apk', '--apk_package',
+ 'org.chromium.chrome.testshell', '--release']
+ return_code = RunProcess(cmd)
+
+ return not return_code
+
+ def Build(self, depot, opts):
+ """Builds the android content shell and other necessary tools using options
+ passed into the script.
+
+ Args:
+ depot: Current depot being bisected.
+ opts: The options parsed from the command line.
+
+ Returns:
+ True if build was successful.
+ """
+ targets = ['chromium_testshell', 'forwarder2', 'md5sum']
+ threads = None
+ if opts.use_goma:
+ threads = 64
+
+ build_success = False
+ if opts.build_preference == 'ninja':
+ build_success = BuildWithNinja(threads, targets)
+ else:
+ assert False, 'No build system defined.'
+
+ if build_success:
+ build_success = self.InstallAPK(opts)
+
+ return build_success
+
+
+class CrosBuilder(Builder):
+ """CrosBuilder is used to build and image ChromeOS/Chromium when cros is the
+ target platform."""
+ def ImageToTarget(self, opts):
+ """Installs latest image to target specified by opts.cros_remote_ip.
+
+ Args:
+ opts: Program options containing cros_board and cros_remote_ip.
+
+ Returns:
+ True if successful.
+ """
+ try:
+ # Keys will most likely be set to 0640 after wiping the chroot.
+ os.chmod(CROS_SCRIPT_KEY_PATH, 0600)
+ os.chmod(CROS_TEST_KEY_PATH, 0600)
+ cmd = [CROS_SDK_PATH, '--', './bin/cros_image_to_target.py',
+ '--remote=%s' % opts.cros_remote_ip,
+ '--board=%s' % opts.cros_board, '--test', '--verbose']
+
+ return_code = RunProcess(cmd)
+ return not return_code
+ except OSError, e:
+ return False
+
+ def BuildPackages(self, opts, depot):
+ """Builds packages for cros.
+
+ Args:
+ opts: Program options containing cros_board.
+ depot: The depot being bisected.
+
+ Returns:
+ True if successful.
+ """
+ cmd = [CROS_SDK_PATH]
+
+ if depot != 'cros':
+ path_to_chrome = os.path.join(os.getcwd(), '..')
+ cmd += ['--chrome_root=%s' % path_to_chrome]
+
+ cmd += ['--']
+
+ if depot != 'cros':
+ cmd += ['CHROME_ORIGIN=LOCAL_SOURCE']
+
+ cmd += ['BUILDTYPE=Release', './build_packages',
+ '--board=%s' % opts.cros_board]
+ return_code = RunProcess(cmd)
+
+ return not return_code
+
+ def BuildImage(self, opts, depot):
+ """Builds test image for cros.
+
+ Args:
+ opts: Program options containing cros_board.
+ depot: The depot being bisected.
+
+ Returns:
+ True if successful.
+ """
+ cmd = [CROS_SDK_PATH]
+
+ if depot != 'cros':
+ path_to_chrome = os.path.join(os.getcwd(), '..')
+ cmd += ['--chrome_root=%s' % path_to_chrome]
+
+ cmd += ['--']
+
+ if depot != 'cros':
+ cmd += ['CHROME_ORIGIN=LOCAL_SOURCE']
+
+ cmd += ['BUILDTYPE=Release', '--', './build_image',
+ '--board=%s' % opts.cros_board, 'test']
+
+ return_code = RunProcess(cmd)
+
+ return not return_code
+
+ def Build(self, depot, opts):
+ """Builds targets using options passed into the script.
+
+ Args:
+ depot: Current depot being bisected.
+ opts: The options parsed from the command line.
+
+ Returns:
+ True if build was successful.
+ """
+ if self.BuildPackages(opts, depot):
+ if self.BuildImage(opts, depot):
+ return self.ImageToTarget(opts)
+ return False
+
+
+class SourceControl(object):
+ """SourceControl is an abstraction over the underlying source control
+ system used for chromium. For now only git is supported, but in the
+ future, the svn workflow could be added as well."""
+ def __init__(self):
+ super(SourceControl, self).__init__()
+
+ def SyncToRevisionWithGClient(self, revision):
+ """Uses gclient to sync to the specified revision.
+
+ ie. gclient sync --revision <revision>
+
+ Args:
+ revision: The git SHA1 or svn CL (depending on workflow).
+
+ Returns:
+ The return code of the call.
+ """
+ return bisect_utils.RunGClient(['sync', '--revision',
+ revision, '--verbose', '--nohooks', '--reset', '--force'])
+
+ def SyncToRevisionWithRepo(self, timestamp):
+ """Uses repo to sync all the underlying git depots to the specified
+ time.
+
+ Args:
+ timestamp: The unix timestamp to sync to.
+
+ Returns:
+ The return code of the call.
+ """
+ return bisect_utils.RunRepoSyncAtTimestamp(timestamp)
+
+
+class GitSourceControl(SourceControl):
+ """GitSourceControl is used to query the underlying source control. """
+ def __init__(self, opts):
+ super(GitSourceControl, self).__init__()
+ self.opts = opts
+
+ def IsGit(self):
+ return True
+
+ def GetRevisionList(self, revision_range_end, revision_range_start):
+ """Retrieves a list of revisions between |revision_range_start| and
+ |revision_range_end|.
+
+ Args:
+ revision_range_end: The SHA1 for the end of the range.
+ revision_range_start: The SHA1 for the beginning of the range.
+
+ Returns:
+ A list of the revisions between |revision_range_start| and
+ |revision_range_end| (inclusive).
+ """
+ revision_range = '%s..%s' % (revision_range_start, revision_range_end)
+ cmd = ['log', '--format=%H', '-10000', '--first-parent', revision_range]
+ log_output = CheckRunGit(cmd)
+
+ revision_hash_list = log_output.split()
+ revision_hash_list.append(revision_range_start)
+
+ return revision_hash_list
+
+ def SyncToRevision(self, revision, sync_client=None):
+ """Syncs to the specified revision.
+
+ Args:
+ revision: The revision to sync to.
+ use_gclient: Specifies whether or not we should sync using gclient or
+ just use source control directly.
+
+ Returns:
+ True if successful.
+ """
+
+ if not sync_client:
+ results = RunGit(['checkout', revision])[1]
+ elif sync_client == 'gclient':
+ results = self.SyncToRevisionWithGClient(revision)
+ elif sync_client == 'repo':
+ results = self.SyncToRevisionWithRepo(revision)
+
+ return not results
+
+ def ResolveToRevision(self, revision_to_check, depot, search):
+ """If an SVN revision is supplied, try to resolve it to a git SHA1.
+
+ Args:
+ revision_to_check: The user supplied revision string that may need to be
+ resolved to a git SHA1.
+ depot: The depot the revision_to_check is from.
+ search: The number of changelists to try if the first fails to resolve
+ to a git hash. If the value is negative, the function will search
+ backwards chronologically, otherwise it will search forward.
+
+ Returns:
+ A string containing a git SHA1 hash, otherwise None.
+ """
+ if depot != 'cros':
+ if not IsStringInt(revision_to_check):
+ return revision_to_check
+
+ depot_svn = 'svn://svn.chromium.org/chrome/trunk/src'
+
+ if depot != 'chromium':
+ depot_svn = DEPOT_DEPS_NAME[depot]['svn']
+
+ svn_revision = int(revision_to_check)
+ git_revision = None
+
+ if search > 0:
+ search_range = xrange(svn_revision, svn_revision + search, 1)
+ else:
+ search_range = xrange(svn_revision, svn_revision + search, -1)
+
+ for i in search_range:
+ svn_pattern = 'git-svn-id: %s@%d' % (depot_svn, i)
+ cmd = ['log', '--format=%H', '-1', '--grep', svn_pattern,
+ 'origin/master']
+
+ (log_output, return_code) = RunGit(cmd)
+
+ assert not return_code, 'An error occurred while running'\
+ ' "git %s"' % ' '.join(cmd)
+
+ if not return_code:
+ log_output = log_output.strip()
+
+ if log_output:
+ git_revision = log_output
+
+ break
+
+ return git_revision
+ else:
+ if IsStringInt(revision_to_check):
+ return int(revision_to_check)
+ else:
+ cwd = os.getcwd()
+ os.chdir(os.path.join(os.getcwd(), 'src', 'third_party',
+ 'chromiumos-overlay'))
+ pattern = CROS_VERSION_PATTERN % revision_to_check
+ cmd = ['log', '--format=%ct', '-1', '--grep', pattern]
+
+ git_revision = None
+
+ log_output = CheckRunGit(cmd)
+ if log_output:
+ git_revision = log_output
+ git_revision = int(log_output.strip())
+ os.chdir(cwd)
+
+ return git_revision
+
+ def IsInProperBranch(self):
+ """Confirms they're in the master branch for performing the bisection.
+ This is needed or gclient will fail to sync properly.
+
+ Returns:
+ True if the current branch on src is 'master'
+ """
+ cmd = ['rev-parse', '--abbrev-ref', 'HEAD']
+ log_output = CheckRunGit(cmd)
+ log_output = log_output.strip()
+
+ return log_output == "master"
+
+ def SVNFindRev(self, revision):
+ """Maps directly to the 'git svn find-rev' command.
+
+ Args:
+ revision: The git SHA1 to use.
+
+ Returns:
+ An integer changelist #, otherwise None.
+ """
+
+ cmd = ['svn', 'find-rev', revision]
+
+ output = CheckRunGit(cmd)
+ svn_revision = output.strip()
+
+ if IsStringInt(svn_revision):
+ return int(svn_revision)
+
+ return None
+
+ def QueryRevisionInfo(self, revision):
+ """Gathers information on a particular revision, such as author's name,
+ email, subject, and date.
+
+ Args:
+ revision: Revision you want to gather information on.
+ Returns:
+ A dict in the following format:
+ {
+ 'author': %s,
+ 'email': %s,
+ 'date': %s,
+ 'subject': %s,
+ }
+ """
+ commit_info = {}
+
+ formats = ['%cN', '%cE', '%s', '%cD']
+ targets = ['author', 'email', 'subject', 'date']
+
+ for i in xrange(len(formats)):
+ cmd = ['log', '--format=%s' % formats[i], '-1', revision]
+ output = CheckRunGit(cmd)
+ commit_info[targets[i]] = output.rstrip()
+
+ return commit_info
+
+ def CheckoutFileAtRevision(self, file_name, revision):
+ """Performs a checkout on a file at the given revision.
+
+ Returns:
+ True if successful.
+ """
+ return not RunGit(['checkout', revision, file_name])[1]
+
+ def RevertFileToHead(self, file_name):
+ """Unstages a file and returns it to HEAD.
+
+ Returns:
+ True if successful.
+ """
+ # Reset doesn't seem to return 0 on success.
+ RunGit(['reset', 'HEAD', bisect_utils.FILE_DEPS_GIT])
+
+ return not RunGit(['checkout', bisect_utils.FILE_DEPS_GIT])[1]
+
+ def QueryFileRevisionHistory(self, filename, revision_start, revision_end):
+ """Returns a list of commits that modified this file.
+
+ Args:
+ filename: Name of file.
+ revision_start: Start of revision range.
+ revision_end: End of revision range.
+
+ Returns:
+ Returns a list of commits that touched this file.
+ """
+ cmd = ['log', '--format=%H', '%s~1..%s' % (revision_start, revision_end),
+ filename]
+ output = CheckRunGit(cmd)
+
+ return [o for o in output.split('\n') if o]
+
+class BisectPerformanceMetrics(object):
+ """BisectPerformanceMetrics performs a bisection against a list of range
+ of revisions to narrow down where performance regressions may have
+ occurred."""
+
+ def __init__(self, source_control, opts):
+ super(BisectPerformanceMetrics, self).__init__()
+
+ self.opts = opts
+ self.source_control = source_control
+ self.src_cwd = os.getcwd()
+ self.cros_cwd = os.path.join(os.getcwd(), '..', 'cros')
+ self.depot_cwd = {}
+ self.cleanup_commands = []
+ self.warnings = []
+ self.builder = None
+
+ if opts.target_platform == 'cros':
+ self.builder = CrosBuilder()
+ elif opts.target_platform == 'android':
+ self.builder = AndroidBuilder()
+ else:
+ self.builder = DesktopBuilder()
+
+ # This always starts true since the script grabs latest first.
+ self.was_blink = True
+
+ for d in DEPOT_NAMES:
+ # The working directory of each depot is just the path to the depot, but
+ # since we're already in 'src', we can skip that part.
+
+ self.depot_cwd[d] = self.src_cwd + DEPOT_DEPS_NAME[d]['src'][3:]
+
+ def PerformCleanup(self):
+ """Performs cleanup when script is finished."""
+ os.chdir(self.src_cwd)
+ for c in self.cleanup_commands:
+ if c[0] == 'mv':
+ shutil.move(c[1], c[2])
+ else:
+ assert False, 'Invalid cleanup command.'
+
+ def GetRevisionList(self, depot, bad_revision, good_revision):
+ """Retrieves a list of all the commits between the bad revision and
+ last known good revision."""
+
+ revision_work_list = []
+
+ if depot == 'cros':
+ revision_range_start = good_revision
+ revision_range_end = bad_revision
+
+ cwd = os.getcwd()
+ self.ChangeToDepotWorkingDirectory('cros')
+
+ # Print the commit timestamps for every commit in the revision time
+ # range. We'll sort them and bisect by that. There is a remote chance that
+ # 2 (or more) commits will share the exact same timestamp, but it's
+ # probably safe to ignore that case.
+ cmd = ['repo', 'forall', '-c',
+ 'git log --format=%%ct --before=%d --after=%d' % (
+ revision_range_end, revision_range_start)]
+ (output, return_code) = RunProcessAndRetrieveOutput(cmd)
+
+ assert not return_code, 'An error occurred while running'\
+ ' "%s"' % ' '.join(cmd)
+
+ os.chdir(cwd)
+
+ revision_work_list = list(set(
+ [int(o) for o in output.split('\n') if IsStringInt(o)]))
+ revision_work_list = sorted(revision_work_list, reverse=True)
+ else:
+ revision_work_list = self.source_control.GetRevisionList(bad_revision,
+ good_revision)
+
+ return revision_work_list
+
+ def Get3rdPartyRevisionsFromCurrentRevision(self, depot):
+ """Parses the DEPS file to determine WebKit/v8/etc... versions.
+
+ Returns:
+ A dict in the format {depot:revision} if successful, otherwise None.
+ """
+
+ cwd = os.getcwd()
+ self.ChangeToDepotWorkingDirectory(depot)
+
+ results = {}
+
+ if depot == 'chromium':
+ locals = {'Var': lambda _: locals["vars"][_],
+ 'From': lambda *args: None}
+ execfile(bisect_utils.FILE_DEPS_GIT, {}, locals)
+
+ os.chdir(cwd)
+
+ rxp = re.compile(".git@(?P<revision>[a-fA-F0-9]+)")
+
+ for d in DEPOT_NAMES:
+ if DEPOT_DEPS_NAME[d]['recurse'] and\
+ DEPOT_DEPS_NAME[d]['from'] == depot:
+ if locals['deps'].has_key(DEPOT_DEPS_NAME[d]['src']):
+ re_results = rxp.search(locals['deps'][DEPOT_DEPS_NAME[d]['src']])
+
+ if re_results:
+ results[d] = re_results.group('revision')
+ else:
+ return None
+ else:
+ return None
+ elif depot == 'cros':
+ cmd = [CROS_SDK_PATH, '--', 'portageq-%s' % self.opts.cros_board,
+ 'best_visible', '/build/%s' % self.opts.cros_board, 'ebuild',
+ CROS_CHROMEOS_PATTERN]
+ (output, return_code) = RunProcessAndRetrieveOutput(cmd)
+
+ assert not return_code, 'An error occurred while running'\
+ ' "%s"' % ' '.join(cmd)
+
+ if len(output) > CROS_CHROMEOS_PATTERN:
+ output = output[len(CROS_CHROMEOS_PATTERN):]
+
+ if len(output) > 1:
+ output = output.split('_')[0]
+
+ if len(output) > 3:
+ contents = output.split('.')
+
+ version = contents[2]
+
+ if contents[3] != '0':
+ warningText = 'Chrome version: %s.%s but using %s.0 to bisect.' %\
+ (version, contents[3], version)
+ if not warningText in self.warnings:
+ self.warnings.append(warningText)
+
+ cwd = os.getcwd()
+ self.ChangeToDepotWorkingDirectory('chromium')
+ return_code = CheckRunGit(['log', '-1', '--format=%H',
+ '--author=chrome-release@google.com', '--grep=to %s' % version,
+ 'origin/master'])
+ os.chdir(cwd)
+
+ results['chromium'] = output.strip()
+
+ return results
+
+ def BuildCurrentRevision(self, depot):
+ """Builds chrome and performance_ui_tests on the current revision.
+
+ Returns:
+ True if the build was successful.
+ """
+ if self.opts.debug_ignore_build:
+ return True
+
+ cwd = os.getcwd()
+ os.chdir(self.src_cwd)
+
+ build_success = self.builder.Build(depot, self.opts)
+
+ os.chdir(cwd)
+
+ return build_success
+
+ def RunGClientHooks(self):
+ """Runs gclient with runhooks command.
+
+ Returns:
+ True if gclient reports no errors.
+ """
+
+ if self.opts.debug_ignore_build:
+ return True
+
+ return not bisect_utils.RunGClient(['runhooks'])
+
+ def TryParseHistogramValuesFromOutput(self, metric, text):
+ """Attempts to parse a metric in the format HISTOGRAM <graph: <trace>.
+
+ Args:
+ metric: The metric as a list of [<trace>, <value>] strings.
+ text: The text to parse the metric values from.
+
+ Returns:
+ A list of floating point numbers found.
+ """
+ metric_formatted = 'HISTOGRAM %s: %s= ' % (metric[0], metric[1])
+
+ text_lines = text.split('\n')
+ values_list = []
+
+ for current_line in text_lines:
+ if metric_formatted in current_line:
+ current_line = current_line[len(metric_formatted):]
+
+ try:
+ histogram_values = eval(current_line)
+
+ for b in histogram_values['buckets']:
+ average_for_bucket = float(b['high'] + b['low']) * 0.5
+ # Extends the list with N-elements with the average for that bucket.
+ values_list.extend([average_for_bucket] * b['count'])
+ except:
+ pass
+
+ return values_list
+
+ def TryParseResultValuesFromOutput(self, metric, text):
+ """Attempts to parse a metric in the format RESULT <graph: <trace>.
+
+ Args:
+ metric: The metric as a list of [<trace>, <value>] strings.
+ text: The text to parse the metric values from.
+
+ Returns:
+ A list of floating point numbers found.
+ """
+ # Format is: RESULT <graph>: <trace>= <value> <units>
+ metric_formatted = re.escape('RESULT %s: %s=' % (metric[0], metric[1]))
+
+ text_lines = text.split('\n')
+ values_list = []
+
+ for current_line in text_lines:
+ # Parse the output from the performance test for the metric we're
+ # interested in.
+ metric_re = metric_formatted +\
+ "(\s)*(?P<values>[0-9]+(\.[0-9]*)?)"
+ metric_re = re.compile(metric_re)
+ regex_results = metric_re.search(current_line)
+
+ if not regex_results is None:
+ values_list += [regex_results.group('values')]
+ else:
+ metric_re = metric_formatted +\
+ "(\s)*\[(\s)*(?P<values>[0-9,.]+)\]"
+ metric_re = re.compile(metric_re)
+ regex_results = metric_re.search(current_line)
+
+ if not regex_results is None:
+ metric_values = regex_results.group('values')
+
+ values_list += metric_values.split(',')
+
+ values_list = [float(v) for v in values_list if IsStringFloat(v)]
+
+ # If the metric is times/t, we need to sum the timings in order to get
+ # similar regression results as the try-bots.
+
+ if metric == ['times', 't']:
+ if values_list:
+ values_list = [reduce(lambda x, y: float(x) + float(y), values_list)]
+
+ return values_list
+
+ def ParseMetricValuesFromOutput(self, metric, text):
+ """Parses output from performance_ui_tests and retrieves the results for
+ a given metric.
+
+ Args:
+ metric: The metric as a list of [<trace>, <value>] strings.
+ text: The text to parse the metric values from.
+
+ Returns:
+ A list of floating point numbers found.
+ """
+ metric_values = self.TryParseResultValuesFromOutput(metric, text)
+
+ if not metric_values:
+ metric_values = self.TryParseHistogramValuesFromOutput(metric, text)
+
+ return metric_values
+
+ def RunPerformanceTestAndParseResults(self, command_to_run, metric):
+ """Runs a performance test on the current revision by executing the
+ 'command_to_run' and parses the results.
+
+ Args:
+ command_to_run: The command to be run to execute the performance test.
+ metric: The metric to parse out from the results of the performance test.
+
+ Returns:
+ On success, it will return a tuple of the average value of the metric,
+ and a success code of 0.
+ """
+
+ if self.opts.debug_ignore_perf_test:
+ return ({'mean': 0.0, 'std_dev': 0.0}, 0)
+
+ if IsWindows():
+ command_to_run = command_to_run.replace('/', r'\\')
+
+ args = shlex.split(command_to_run)
+
+ # If running a telemetry test for cros, insert the remote ip, and
+ # identity parameters.
+ if self.opts.target_platform == 'cros':
+ if 'tools/perf/run_' in args[0]:
+ args.append('--remote=%s' % self.opts.cros_remote_ip)
+ args.append('--identity=%s' % CROS_TEST_KEY_PATH)
+
+ cwd = os.getcwd()
+ os.chdir(self.src_cwd)
+
+ start_time = time.time()
+
+ metric_values = []
+ for i in xrange(self.opts.repeat_test_count):
+ # Can ignore the return code since if the tests fail, it won't return 0.
+ try:
+ (output, return_code) = RunProcessAndRetrieveOutput(args)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ err_text = ("Something went wrong running the performance test. "
+ "Please review the command line:\n\n")
+ if 'src/' in ' '.join(args):
+ err_text += ("Check that you haven't accidentally specified a path "
+ "with src/ in the command.\n\n")
+ err_text += ' '.join(args)
+ err_text += '\n'
+
+ return (err_text, -1)
+ raise
+
+ if self.opts.output_buildbot_annotations:
+ print output
+
+ metric_values += self.ParseMetricValuesFromOutput(metric, output)
+
+ elapsed_minutes = (time.time() - start_time) / 60.0
+
+ if elapsed_minutes >= self.opts.repeat_test_max_time or not metric_values:
+ break
+
+ os.chdir(cwd)
+
+ # Need to get the average value if there were multiple values.
+ if metric_values:
+ truncated_mean = CalculateTruncatedMean(metric_values,
+ self.opts.truncate_percent)
+ standard_dev = CalculateStandardDeviation(metric_values)
+
+ values = {
+ 'mean': truncated_mean,
+ 'std_dev': standard_dev,
+ }
+
+ print 'Results of performance test: %12f %12f' % (
+ truncated_mean, standard_dev)
+ print
+ return (values, 0)
+ else:
+ return ('Invalid metric specified, or no values returned from '
+ 'performance test.', -1)
+
+ def FindAllRevisionsToSync(self, revision, depot):
+ """Finds all dependant revisions and depots that need to be synced for a
+ given revision. This is only useful in the git workflow, as an svn depot
+ may be split into multiple mirrors.
+
+ ie. skia is broken up into 3 git mirrors over skia/src, skia/gyp, and
+ skia/include. To sync skia/src properly, one has to find the proper
+ revisions in skia/gyp and skia/include.
+
+ Args:
+ revision: The revision to sync to.
+ depot: The depot in use at the moment (probably skia).
+
+ Returns:
+ A list of [depot, revision] pairs that need to be synced.
+ """
+ revisions_to_sync = [[depot, revision]]
+
+ is_base = (depot == 'chromium') or (depot == 'cros')
+
+ # Some SVN depots were split into multiple git depots, so we need to
+ # figure out for each mirror which git revision to grab. There's no
+ # guarantee that the SVN revision will exist for each of the dependant
+ # depots, so we have to grep the git logs and grab the next earlier one.
+ if not is_base and\
+ DEPOT_DEPS_NAME[depot]['depends'] and\
+ self.source_control.IsGit():
+ svn_rev = self.source_control.SVNFindRev(revision)
+
+ for d in DEPOT_DEPS_NAME[depot]['depends']:
+ self.ChangeToDepotWorkingDirectory(d)
+
+ dependant_rev = self.source_control.ResolveToRevision(svn_rev, d, -1000)
+
+ if dependant_rev:
+ revisions_to_sync.append([d, dependant_rev])
+
+ num_resolved = len(revisions_to_sync)
+ num_needed = len(DEPOT_DEPS_NAME[depot]['depends'])
+
+ self.ChangeToDepotWorkingDirectory(depot)
+
+ if not ((num_resolved - 1) == num_needed):
+ return None
+
+ return revisions_to_sync
+
+ def PerformPreBuildCleanup(self):
+ """Performs necessary cleanup between runs."""
+ print 'Cleaning up between runs.'
+ print
+
+ # Having these pyc files around between runs can confuse the
+ # perf tests and cause them to crash.
+ for (path, dir, files) in os.walk(self.src_cwd):
+ for cur_file in files:
+ if cur_file.endswith('.pyc'):
+ path_to_file = os.path.join(path, cur_file)
+ os.remove(path_to_file)
+
+ def PerformWebkitDirectoryCleanup(self, revision):
+ """If the script is switching between Blink and WebKit during bisect,
+ its faster to just delete the directory rather than leave it up to git
+ to sync.
+
+ Returns:
+ True if successful.
+ """
+ if not self.source_control.CheckoutFileAtRevision(
+ bisect_utils.FILE_DEPS_GIT, revision):
+ return False
+
+ cwd = os.getcwd()
+ os.chdir(self.src_cwd)
+
+ is_blink = bisect_utils.IsDepsFileBlink()
+
+ os.chdir(cwd)
+
+ if not self.source_control.RevertFileToHead(
+ bisect_utils.FILE_DEPS_GIT):
+ return False
+
+ if self.was_blink != is_blink:
+ self.was_blink = is_blink
+ return bisect_utils.RemoveThirdPartyWebkitDirectory()
+ return True
+
+ def PerformCrosChrootCleanup(self):
+ """Deletes the chroot.
+
+ Returns:
+ True if successful.
+ """
+ cwd = os.getcwd()
+ self.ChangeToDepotWorkingDirectory('cros')
+ cmd = [CROS_SDK_PATH, '--delete']
+ return_code = RunProcess(cmd)
+ os.chdir(cwd)
+ return not return_code
+
+ def CreateCrosChroot(self):
+ """Creates a new chroot.
+
+ Returns:
+ True if successful.
+ """
+ cwd = os.getcwd()
+ self.ChangeToDepotWorkingDirectory('cros')
+ cmd = [CROS_SDK_PATH, '--create']
+ return_code = RunProcess(cmd)
+ os.chdir(cwd)
+ return not return_code
+
+ def PerformPreSyncCleanup(self, revision, depot):
+ """Performs any necessary cleanup before syncing.
+
+ Returns:
+ True if successful.
+ """
+ if depot == 'chromium':
+ return self.PerformWebkitDirectoryCleanup(revision)
+ elif depot == 'cros':
+ return self.PerformCrosChrootCleanup()
+ return True
+
+ def RunPostSync(self, depot):
+ """Performs any work after syncing.
+
+ Returns:
+ True if successful.
+ """
+ if self.opts.target_platform == 'android':
+ cwd = os.getcwd()
+ os.chdir(os.path.join(self.src_cwd, '..'))
+ if not bisect_utils.SetupAndroidBuildEnvironment(self.opts):
+ return False
+ os.chdir(cwd)
+
+ if depot == 'cros':
+ return self.CreateCrosChroot()
+ else:
+ return self.RunGClientHooks()
+ return True
+
+ def ShouldSkipRevision(self, depot, revision):
+ """Some commits can be safely skipped (such as a DEPS roll), since the tool
+ is git based those changes would have no effect.
+
+ Args:
+ depot: The depot being bisected.
+ revision: Current revision we're synced to.
+
+ Returns:
+ True if we should skip building/testing this revision.
+ """
+ if depot == 'chromium':
+ if self.source_control.IsGit():
+ cmd = ['diff-tree', '--no-commit-id', '--name-only', '-r', revision]
+ output = CheckRunGit(cmd)
+
+ files = output.splitlines()
+
+ if len(files) == 1 and files[0] == 'DEPS':
+ return True
+
+ return False
+
+ def SyncBuildAndRunRevision(self, revision, depot, command_to_run, metric,
+ skippable=False):
+ """Performs a full sync/build/run of the specified revision.
+
+ Args:
+ revision: The revision to sync to.
+ depot: The depot that's being used at the moment (src, webkit, etc.)
+ command_to_run: The command to execute the performance test.
+ metric: The performance metric being tested.
+
+ Returns:
+ On success, a tuple containing the results of the performance test.
+ Otherwise, a tuple with the error message.
+ """
+ sync_client = None
+ if depot == 'chromium':
+ sync_client = 'gclient'
+ elif depot == 'cros':
+ sync_client = 'repo'
+
+ revisions_to_sync = self.FindAllRevisionsToSync(revision, depot)
+
+ if not revisions_to_sync:
+ return ('Failed to resolve dependant depots.', BUILD_RESULT_FAIL)
+
+ if not self.PerformPreSyncCleanup(revision, depot):
+ return ('Failed to perform pre-sync cleanup.', BUILD_RESULT_FAIL)
+
+ success = True
+
+ if not self.opts.debug_ignore_sync:
+ for r in revisions_to_sync:
+ self.ChangeToDepotWorkingDirectory(r[0])
+
+ if sync_client:
+ self.PerformPreBuildCleanup()
+
+ if not self.source_control.SyncToRevision(r[1], sync_client):
+ success = False
+
+ break
+
+ if success:
+ success = self.RunPostSync(depot)
+
+ if success:
+ if skippable and self.ShouldSkipRevision(depot, revision):
+ return ('Skipped revision: [%s]' % str(revision),
+ BUILD_RESULT_SKIPPED)
+
+ if self.BuildCurrentRevision(depot):
+ results = self.RunPerformanceTestAndParseResults(command_to_run,
+ metric)
+
+ if results[1] == 0 and sync_client:
+ external_revisions = self.Get3rdPartyRevisionsFromCurrentRevision(
+ depot)
+
+ if external_revisions:
+ return (results[0], results[1], external_revisions)
+ else:
+ return ('Failed to parse DEPS file for external revisions.',
+ BUILD_RESULT_FAIL)
+ else:
+ return results
+ else:
+ return ('Failed to build revision: [%s]' % (str(revision, )),
+ BUILD_RESULT_FAIL)
+ else:
+ return ('Failed to run [gclient runhooks].', BUILD_RESULT_FAIL)
+ else:
+ return ('Failed to sync revision: [%s]' % (str(revision, )),
+ BUILD_RESULT_FAIL)
+
+ def CheckIfRunPassed(self, current_value, known_good_value, known_bad_value):
+ """Given known good and bad values, decide if the current_value passed
+ or failed.
+
+ Args:
+ current_value: The value of the metric being checked.
+ known_bad_value: The reference value for a "failed" run.
+ known_good_value: The reference value for a "passed" run.
+
+ Returns:
+ True if the current_value is closer to the known_good_value than the
+ known_bad_value.
+ """
+ dist_to_good_value = abs(current_value['mean'] - known_good_value['mean'])
+ dist_to_bad_value = abs(current_value['mean'] - known_bad_value['mean'])
+
+ return dist_to_good_value < dist_to_bad_value
+
+ def ChangeToDepotWorkingDirectory(self, depot_name):
+ """Given a depot, changes to the appropriate working directory.
+
+ Args:
+ depot_name: The name of the depot (see DEPOT_NAMES).
+ """
+ if depot_name == 'chromium':
+ os.chdir(self.src_cwd)
+ elif depot_name == 'cros':
+ os.chdir(self.cros_cwd)
+ elif depot_name in DEPOT_NAMES:
+ os.chdir(self.depot_cwd[depot_name])
+ else:
+ assert False, 'Unknown depot [ %s ] encountered. Possibly a new one'\
+ ' was added without proper support?' %\
+ (depot_name,)
+
+ def PrepareToBisectOnDepot(self,
+ current_depot,
+ end_revision,
+ start_revision,
+ previous_depot,
+ previous_revision):
+ """Changes to the appropriate directory and gathers a list of revisions
+ to bisect between |start_revision| and |end_revision|.
+
+ Args:
+ current_depot: The depot we want to bisect.
+ end_revision: End of the revision range.
+ start_revision: Start of the revision range.
+ previous_depot: The depot we were previously bisecting.
+ previous_revision: The last revision we synced to on |previous_depot|.
+
+ Returns:
+ A list containing the revisions between |start_revision| and
+ |end_revision| inclusive.
+ """
+ # Change into working directory of external library to run
+ # subsequent commands.
+ old_cwd = os.getcwd()
+ os.chdir(self.depot_cwd[current_depot])
+
+ # V8 (and possibly others) is merged in periodically. Bisecting
+ # this directory directly won't give much good info.
+ if DEPOT_DEPS_NAME[current_depot].has_key('build_with'):
+ if (DEPOT_DEPS_NAME[current_depot].has_key('custom_deps') and
+ previous_depot == 'chromium'):
+ config_path = os.path.join(self.src_cwd, '..')
+ if bisect_utils.RunGClientAndCreateConfig(self.opts,
+ DEPOT_DEPS_NAME[current_depot]['custom_deps'], cwd=config_path):
+ return []
+ if bisect_utils.RunGClient(
+ ['sync', '--revision', previous_revision], cwd=self.src_cwd):
+ return []
+
+ new_depot = DEPOT_DEPS_NAME[current_depot]['build_with']
+
+ svn_start_revision = self.source_control.SVNFindRev(start_revision)
+ svn_end_revision = self.source_control.SVNFindRev(end_revision)
+ os.chdir(self.depot_cwd[new_depot])
+
+ start_revision = self.source_control.ResolveToRevision(
+ svn_start_revision, new_depot, -1000)
+ end_revision = self.source_control.ResolveToRevision(
+ svn_end_revision, new_depot, -1000)
+
+ old_name = DEPOT_DEPS_NAME[current_depot]['src'][4:]
+ new_name = DEPOT_DEPS_NAME[new_depot]['src'][4:]
+
+ os.chdir(self.src_cwd)
+
+ shutil.move(old_name, old_name + '.bak')
+ shutil.move(new_name, old_name)
+ os.chdir(self.depot_cwd[current_depot])
+
+ self.cleanup_commands.append(['mv', old_name, new_name])
+ self.cleanup_commands.append(['mv', old_name + '.bak', old_name])
+
+ os.chdir(self.depot_cwd[current_depot])
+
+ depot_revision_list = self.GetRevisionList(current_depot,
+ end_revision,
+ start_revision)
+
+ os.chdir(old_cwd)
+
+ return depot_revision_list
+
+ def GatherReferenceValues(self, good_rev, bad_rev, cmd, metric, target_depot):
+ """Gathers reference values by running the performance tests on the
+ known good and bad revisions.
+
+ Args:
+ good_rev: The last known good revision where the performance regression
+ has not occurred yet.
+ bad_rev: A revision where the performance regression has already occurred.
+ cmd: The command to execute the performance test.
+ metric: The metric being tested for regression.
+
+ Returns:
+ A tuple with the results of building and running each revision.
+ """
+ bad_run_results = self.SyncBuildAndRunRevision(bad_rev,
+ target_depot,
+ cmd,
+ metric)
+
+ good_run_results = None
+
+ if not bad_run_results[1]:
+ good_run_results = self.SyncBuildAndRunRevision(good_rev,
+ target_depot,
+ cmd,
+ metric)
+
+ return (bad_run_results, good_run_results)
+
+ def AddRevisionsIntoRevisionData(self, revisions, depot, sort, revision_data):
+ """Adds new revisions to the revision_data dict and initializes them.
+
+ Args:
+ revisions: List of revisions to add.
+ depot: Depot that's currently in use (src, webkit, etc...)
+ sort: Sorting key for displaying revisions.
+ revision_data: A dict to add the new revisions into. Existing revisions
+ will have their sort keys offset.
+ """
+
+ num_depot_revisions = len(revisions)
+
+ for k, v in revision_data.iteritems():
+ if v['sort'] > sort:
+ v['sort'] += num_depot_revisions
+
+ for i in xrange(num_depot_revisions):
+ r = revisions[i]
+
+ revision_data[r] = {'revision' : r,
+ 'depot' : depot,
+ 'value' : None,
+ 'passed' : '?',
+ 'sort' : i + sort + 1}
+
+ def PrintRevisionsToBisectMessage(self, revision_list, depot):
+ if self.opts.output_buildbot_annotations:
+ step_name = 'Bisection Range: [%s - %s]' % (
+ revision_list[len(revision_list)-1], revision_list[0])
+ bisect_utils.OutputAnnotationStepStart(step_name)
+
+ print
+ print 'Revisions to bisect on [%s]:' % depot
+ for revision_id in revision_list:
+ print ' -> %s' % (revision_id, )
+ print
+
+ if self.opts.output_buildbot_annotations:
+ bisect_utils.OutputAnnotationStepClosed()
+
+ def NudgeRevisionsIfDEPSChange(self, bad_revision, good_revision):
+ """Checks to see if changes to DEPS file occurred, and that the revision
+ range also includes the change to .DEPS.git. If it doesn't, attempts to
+ expand the revision range to include it.
+
+ Args:
+ bad_rev: First known bad revision.
+ good_revision: Last known good revision.
+
+ Returns:
+ A tuple with the new bad and good revisions.
+ """
+ if self.source_control.IsGit() and self.opts.target_platform == 'chromium':
+ changes_to_deps = self.source_control.QueryFileRevisionHistory(
+ 'DEPS', good_revision, bad_revision)
+
+ if changes_to_deps:
+ # DEPS file was changed, search from the oldest change to DEPS file to
+ # bad_revision to see if there are matching .DEPS.git changes.
+ oldest_deps_change = changes_to_deps[-1]
+ changes_to_gitdeps = self.source_control.QueryFileRevisionHistory(
+ bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision)
+
+ if len(changes_to_deps) != len(changes_to_gitdeps):
+ # Grab the timestamp of the last DEPS change
+ cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]]
+ output = CheckRunGit(cmd)
+ commit_time = int(output)
+
+ # Try looking for a commit that touches the .DEPS.git file in the
+ # next 15 minutes after the DEPS file change.
+ cmd = ['log', '--format=%H', '-1',
+ '--before=%d' % (commit_time + 900), '--after=%d' % commit_time,
+ 'origin/master', bisect_utils.FILE_DEPS_GIT]
+ output = CheckRunGit(cmd)
+ output = output.strip()
+ if output:
+ self.warnings.append('Detected change to DEPS and modified '
+ 'revision range to include change to .DEPS.git')
+ return (output, good_revision)
+ else:
+ self.warnings.append('Detected change to DEPS but couldn\'t find '
+ 'matching change to .DEPS.git')
+ return (bad_revision, good_revision)
+
+ def CheckIfRevisionsInProperOrder(self,
+ target_depot,
+ good_revision,
+ bad_revision):
+ """Checks that |good_revision| is an earlier revision than |bad_revision|.
+
+ Args:
+ good_revision: Number/tag of the known good revision.
+ bad_revision: Number/tag of the known bad revision.
+
+ Returns:
+ True if the revisions are in the proper order (good earlier than bad).
+ """
+ if self.source_control.IsGit() and target_depot != 'cros':
+ cmd = ['log', '--format=%ct', '-1', good_revision]
+ output = CheckRunGit(cmd)
+ good_commit_time = int(output)
+
+ cmd = ['log', '--format=%ct', '-1', bad_revision]
+ output = CheckRunGit(cmd)
+ bad_commit_time = int(output)
+
+ return good_commit_time <= bad_commit_time
+ else:
+ # Cros/svn use integers
+ return int(good_revision) <= int(bad_revision)
+
+ def Run(self, command_to_run, bad_revision_in, good_revision_in, metric):
+ """Given known good and bad revisions, run a binary search on all
+ intermediate revisions to determine the CL where the performance regression
+ occurred.
+
+ Args:
+ command_to_run: Specify the command to execute the performance test.
+ good_revision: Number/tag of the known good revision.
+ bad_revision: Number/tag of the known bad revision.
+ metric: The performance metric to monitor.
+
+ Returns:
+ A dict with 2 members, 'revision_data' and 'error'. On success,
+ 'revision_data' will contain a dict mapping revision ids to
+ data about that revision. Each piece of revision data consists of a
+ dict with the following keys:
+
+ 'passed': Represents whether the performance test was successful at
+ that revision. Possible values include: 1 (passed), 0 (failed),
+ '?' (skipped), 'F' (build failed).
+ 'depot': The depot that this revision is from (ie. WebKit)
+ 'external': If the revision is a 'src' revision, 'external' contains
+ the revisions of each of the external libraries.
+ 'sort': A sort value for sorting the dict in order of commits.
+
+ For example:
+ {
+ 'error':None,
+ 'revision_data':
+ {
+ 'CL #1':
+ {
+ 'passed':False,
+ 'depot':'chromium',
+ 'external':None,
+ 'sort':0
+ }
+ }
+ }
+
+ If an error occurred, the 'error' field will contain the message and
+ 'revision_data' will be empty.
+ """
+
+ results = {'revision_data' : {},
+ 'error' : None}
+
+ # Choose depot to bisect first
+ target_depot = 'chromium'
+ if self.opts.target_platform == 'cros':
+ target_depot = 'cros'
+
+ cwd = os.getcwd()
+ self.ChangeToDepotWorkingDirectory(target_depot)
+
+ # If they passed SVN CL's, etc... we can try match them to git SHA1's.
+ bad_revision = self.source_control.ResolveToRevision(bad_revision_in,
+ target_depot, 100)
+ good_revision = self.source_control.ResolveToRevision(good_revision_in,
+ target_depot, -100)
+
+ os.chdir(cwd)
+
+
+ if bad_revision is None:
+ results['error'] = 'Could\'t resolve [%s] to SHA1.' % (bad_revision_in,)
+ return results
+
+ if good_revision is None:
+ results['error'] = 'Could\'t resolve [%s] to SHA1.' % (good_revision_in,)
+ return results
+
+ # Check that they didn't accidentally swap good and bad revisions.
+ if not self.CheckIfRevisionsInProperOrder(
+ target_depot, good_revision, bad_revision):
+ results['error'] = 'bad_revision < good_revision, did you swap these '\
+ 'by mistake?'
+ return results
+
+ (bad_revision, good_revision) = self.NudgeRevisionsIfDEPSChange(
+ bad_revision, good_revision)
+
+ if self.opts.output_buildbot_annotations:
+ bisect_utils.OutputAnnotationStepStart('Gathering Revisions')
+
+ print 'Gathering revision range for bisection.'
+
+ # Retrieve a list of revisions to do bisection on.
+ src_revision_list = self.GetRevisionList(target_depot,
+ bad_revision,
+ good_revision)
+
+ if self.opts.output_buildbot_annotations:
+ bisect_utils.OutputAnnotationStepClosed()
+
+ if src_revision_list:
+ # revision_data will store information about a revision such as the
+ # depot it came from, the webkit/V8 revision at that time,
+ # performance timing, build state, etc...
+ revision_data = results['revision_data']
+
+ # revision_list is the list we're binary searching through at the moment.
+ revision_list = []
+
+ sort_key_ids = 0
+
+ for current_revision_id in src_revision_list:
+ sort_key_ids += 1
+
+ revision_data[current_revision_id] = {'value' : None,
+ 'passed' : '?',
+ 'depot' : target_depot,
+ 'external' : None,
+ 'sort' : sort_key_ids}
+ revision_list.append(current_revision_id)
+
+ min_revision = 0
+ max_revision = len(revision_list) - 1
+
+ self.PrintRevisionsToBisectMessage(revision_list, target_depot)
+
+ if self.opts.output_buildbot_annotations:
+ bisect_utils.OutputAnnotationStepStart('Gathering Reference Values')
+
+ print 'Gathering reference values for bisection.'
+
+ # Perform the performance tests on the good and bad revisions, to get
+ # reference values.
+ (bad_results, good_results) = self.GatherReferenceValues(good_revision,
+ bad_revision,
+ command_to_run,
+ metric,
+ target_depot)
+
+ if self.opts.output_buildbot_annotations:
+ bisect_utils.OutputAnnotationStepClosed()
+
+ if bad_results[1]:
+ results['error'] = bad_results[0]
+ return results
+
+ if good_results[1]:
+ results['error'] = good_results[0]
+ return results
+
+
+ # We need these reference values to determine if later runs should be
+ # classified as pass or fail.
+ known_bad_value = bad_results[0]
+ known_good_value = good_results[0]
+
+ # Can just mark the good and bad revisions explicitly here since we
+ # already know the results.
+ bad_revision_data = revision_data[revision_list[0]]
+ bad_revision_data['external'] = bad_results[2]
+ bad_revision_data['passed'] = 0
+ bad_revision_data['value'] = known_bad_value
+
+ good_revision_data = revision_data[revision_list[max_revision]]
+ good_revision_data['external'] = good_results[2]
+ good_revision_data['passed'] = 1
+ good_revision_data['value'] = known_good_value
+
+ next_revision_depot = target_depot
+
+ while True:
+ if not revision_list:
+ break
+
+ min_revision_data = revision_data[revision_list[min_revision]]
+ max_revision_data = revision_data[revision_list[max_revision]]
+
+ if max_revision - min_revision <= 1:
+ if min_revision_data['passed'] == '?':
+ next_revision_index = min_revision
+ elif max_revision_data['passed'] == '?':
+ next_revision_index = max_revision
+ elif min_revision_data['depot'] == 'chromium' or\
+ min_revision_data['depot'] == 'cros':
+ # If there were changes to any of the external libraries we track,
+ # should bisect the changes there as well.
+ external_depot = None
+
+ for current_depot in DEPOT_NAMES:
+ if DEPOT_DEPS_NAME[current_depot]["recurse"] and\
+ DEPOT_DEPS_NAME[current_depot]['from'] ==\
+ min_revision_data['depot']:
+ if min_revision_data['external'][current_depot] !=\
+ max_revision_data['external'][current_depot]:
+ external_depot = current_depot
+ break
+
+ # If there was no change in any of the external depots, the search
+ # is over.
+ if not external_depot:
+ break
+
+ previous_revision = revision_list[min_revision]
+
+ earliest_revision = max_revision_data['external'][external_depot]
+ latest_revision = min_revision_data['external'][external_depot]
+
+ new_revision_list = self.PrepareToBisectOnDepot(external_depot,
+ latest_revision,
+ earliest_revision,
+ next_revision_depot,
+ previous_revision)
+
+ if not new_revision_list:
+ results['error'] = 'An error occurred attempting to retrieve'\
+ ' revision range: [%s..%s]' %\
+ (depot_rev_range[1], depot_rev_range[0])
+ return results
+
+ self.AddRevisionsIntoRevisionData(new_revision_list,
+ external_depot,
+ min_revision_data['sort'],
+ revision_data)
+
+ # Reset the bisection and perform it on the newly inserted
+ # changelists.
+ revision_list = new_revision_list
+ min_revision = 0
+ max_revision = len(revision_list) - 1
+ sort_key_ids += len(revision_list)
+
+ print 'Regression in metric:%s appears to be the result of changes'\
+ ' in [%s].' % (metric, external_depot)
+
+ self.PrintRevisionsToBisectMessage(revision_list, external_depot)
+
+ continue
+ else:
+ break
+ else:
+ next_revision_index = int((max_revision - min_revision) / 2) +\
+ min_revision
+
+ next_revision_id = revision_list[next_revision_index]
+ next_revision_data = revision_data[next_revision_id]
+ next_revision_depot = next_revision_data['depot']
+
+ self.ChangeToDepotWorkingDirectory(next_revision_depot)
+
+ if self.opts.output_buildbot_annotations:
+ step_name = 'Working on [%s]' % next_revision_id
+ bisect_utils.OutputAnnotationStepStart(step_name)
+
+ print 'Working on revision: [%s]' % next_revision_id
+
+ run_results = self.SyncBuildAndRunRevision(next_revision_id,
+ next_revision_depot,
+ command_to_run,
+ metric, skippable=True)
+
+ # If the build is successful, check whether or not the metric
+ # had regressed.
+ if not run_results[1]:
+ if len(run_results) > 2:
+ next_revision_data['external'] = run_results[2]
+
+ passed_regression = self.CheckIfRunPassed(run_results[0],
+ known_good_value,
+ known_bad_value)
+
+ next_revision_data['passed'] = passed_regression
+ next_revision_data['value'] = run_results[0]
+
+ if passed_regression:
+ max_revision = next_revision_index
+ else:
+ min_revision = next_revision_index
+ else:
+ if run_results[1] == BUILD_RESULT_SKIPPED:
+ next_revision_data['passed'] = 'Skipped'
+ elif run_results[1] == BUILD_RESULT_FAIL:
+ next_revision_data['passed'] = 'Failed'
+
+ print run_results[0]
+
+ # If the build is broken, remove it and redo search.
+ revision_list.pop(next_revision_index)
+
+ max_revision -= 1
+
+ if self.opts.output_buildbot_annotations:
+ bisect_utils.OutputAnnotationStepClosed()
+ else:
+ # Weren't able to sync and retrieve the revision range.
+ results['error'] = 'An error occurred attempting to retrieve revision '\
+ 'range: [%s..%s]' % (good_revision, bad_revision)
+
+ return results
+
+ def FormatAndPrintResults(self, bisect_results):
+ """Prints the results from a bisection run in a readable format.
+
+ Args
+ bisect_results: The results from a bisection test run.
+ """
+ revision_data = bisect_results['revision_data']
+ revision_data_sorted = sorted(revision_data.iteritems(),
+ key = lambda x: x[1]['sort'])
+
+ if self.opts.output_buildbot_annotations:
+ bisect_utils.OutputAnnotationStepStart('Results')
+
+ print
+ print 'Full results of bisection:'
+ for current_id, current_data in revision_data_sorted:
+ build_status = current_data['passed']
+
+ if type(build_status) is bool:
+ build_status = int(build_status)
+
+ print ' %8s %40s %s' % (current_data['depot'],
+ current_id, build_status)
+ print
+
+ print
+ print 'Tested commits:'
+ for current_id, current_data in revision_data_sorted:
+ if current_data['value']:
+ print ' %8s %40s %12f %12f' % (
+ current_data['depot'], current_id,
+ current_data['value']['mean'], current_data['value']['std_dev'])
+ print
+
+ # Find range where it possibly broke.
+ first_working_revision = None
+ last_broken_revision = None
+ last_broken_revision_index = -1
+
+ for i in xrange(len(revision_data_sorted)):
+ k, v = revision_data_sorted[i]
+ if v['passed'] == 1:
+ if not first_working_revision:
+ first_working_revision = k
+
+ if not v['passed']:
+ last_broken_revision = k
+ last_broken_revision_index = i
+
+ if last_broken_revision != None and first_working_revision != None:
+ print 'Results: Regression may have occurred in range:'
+ print ' -> First Bad Revision: [%40s] [%s]' %\
+ (last_broken_revision,
+ revision_data[last_broken_revision]['depot'])
+ print ' -> Last Good Revision: [%40s] [%s]' %\
+ (first_working_revision,
+ revision_data[first_working_revision]['depot'])
+
+ cwd = os.getcwd()
+ self.ChangeToDepotWorkingDirectory(
+ revision_data[last_broken_revision]['depot'])
+
+ if revision_data[last_broken_revision]['depot'] == 'cros':
+ # Want to get a list of all the commits and what depots they belong
+ # to so that we can grab info about each.
+ cmd = ['repo', 'forall', '-c',
+ 'pwd ; git log --pretty=oneline --before=%d --after=%d' % (
+ last_broken_revision, first_working_revision + 1)]
+ (output, return_code) = RunProcessAndRetrieveOutput(cmd)
+
+ changes = []
+
+ assert not return_code, 'An error occurred while running'\
+ ' "%s"' % ' '.join(cmd)
+
+ last_depot = None
+ cwd = os.getcwd()
+ for l in output.split('\n'):
+ if l:
+ # Output will be in form:
+ # /path_to_depot
+ # /path_to_other_depot
+ # <SHA1>
+ # /path_again
+ # <SHA1>
+ # etc.
+ if l[0] == '/':
+ last_depot = l
+ else:
+ contents = l.split(' ')
+ if len(contents) > 1:
+ changes.append([last_depot, contents[0]])
+
+ print
+ for c in changes:
+ os.chdir(c[0])
+ info = self.source_control.QueryRevisionInfo(c[1])
+
+ print
+ print 'Commit : %s' % c[1]
+ print 'Author : %s' % info['author']
+ print 'Email : %s' % info['email']
+ print 'Date : %s' % info['date']
+ print 'Subject : %s' % info['subject']
+ print
+ else:
+ multiple_commits = 0
+ for i in xrange(last_broken_revision_index, len(revision_data_sorted)):
+ k, v = revision_data_sorted[i]
+ if k == first_working_revision:
+ break
+
+ self.ChangeToDepotWorkingDirectory(v['depot'])
+
+ info = self.source_control.QueryRevisionInfo(k)
+
+ print
+ print 'Commit : %s' % k
+ print 'Author : %s' % info['author']
+ print 'Email : %s' % info['email']
+ print 'Date : %s' % info['date']
+ print 'Subject : %s' % info['subject']
+
+ multiple_commits += 1
+ if multiple_commits > 1:
+ self.warnings.append('Due to build errors, regression range could'
+ ' not be narrowed down to a single commit.')
+ print
+ os.chdir(cwd)
+
+ # Give a warning if the values were very close together
+ good_std_dev = revision_data[first_working_revision]['value']['std_dev']
+ good_mean = revision_data[first_working_revision]['value']['mean']
+ bad_mean = revision_data[last_broken_revision]['value']['mean']
+
+ # A standard deviation of 0 could indicate either insufficient runs
+ # or a test that consistently returns the same value.
+ if good_std_dev > 0:
+ deviations = math.fabs(bad_mean - good_mean) / good_std_dev
+
+ if deviations < 1.5:
+ self.warnings.append('Regression was less than 1.5 standard '
+ 'deviations from "good" value. Results may not be accurate.')
+ elif self.opts.repeat_test_count == 1:
+ self.warnings.append('Tests were only set to run once. This '
+ 'may be insufficient to get meaningful results.')
+
+ # Check for any other possible regression ranges
+ prev_revision_data = revision_data_sorted[0][1]
+ prev_revision_id = revision_data_sorted[0][0]
+ possible_regressions = []
+ for current_id, current_data in revision_data_sorted:
+ if current_data['value']:
+ prev_mean = prev_revision_data['value']['mean']
+ cur_mean = current_data['value']['mean']
+
+ if good_std_dev:
+ deviations = math.fabs(prev_mean - cur_mean) / good_std_dev
+ else:
+ deviations = None
+
+ if good_mean:
+ percent_change = (prev_mean - cur_mean) / good_mean
+
+ # If the "good" valuse are supposed to be higher than the "bad"
+ # values (ie. scores), flip the sign of the percent change so that
+ # a positive value always represents a regression.
+ if bad_mean < good_mean:
+ percent_change *= -1.0
+ else:
+ percent_change = None
+
+ if deviations >= 1.5 or percent_change > 0.01:
+ if current_id != first_working_revision:
+ possible_regressions.append(
+ [current_id, prev_revision_id, percent_change, deviations])
+ prev_revision_data = current_data
+ prev_revision_id = current_id
+
+ if possible_regressions:
+ print
+ print 'Other regressions may have occurred:'
+ print
+ for p in possible_regressions:
+ current_id = p[0]
+ percent_change = p[2]
+ deviations = p[3]
+ current_data = revision_data[current_id]
+ previous_id = p[1]
+ previous_data = revision_data[previous_id]
+
+ if deviations is None:
+ deviations = 'N/A'
+ else:
+ deviations = '%.2f' % deviations
+
+ if percent_change is None:
+ percent_change = 0
+
+ print ' %8s %s [%.2f%%, %s x std.dev]' % (
+ previous_data['depot'], previous_id, 100 * percent_change,
+ deviations)
+ print ' %8s %s' % (
+ current_data['depot'], current_id)
+ print
+
+ if self.warnings:
+ print
+ print 'The following warnings were generated:'
+ print
+ for w in self.warnings:
+ print ' - %s' % w
+ print
+
+ if self.opts.output_buildbot_annotations:
+ bisect_utils.OutputAnnotationStepClosed()
+
+
+def DetermineAndCreateSourceControl(opts):
+ """Attempts to determine the underlying source control workflow and returns
+ a SourceControl object.
+
+ Returns:
+ An instance of a SourceControl object, or None if the current workflow
+ is unsupported.
+ """
+
+ (output, return_code) = RunGit(['rev-parse', '--is-inside-work-tree'])
+
+ if output.strip() == 'true':
+ return GitSourceControl(opts)
+
+ return None
+
+
+def SetNinjaBuildSystemDefault():
+ """Makes ninja the default build system to be used by
+ the bisection script."""
+ gyp_var = os.getenv('GYP_GENERATORS')
+
+ if not gyp_var or not 'ninja' in gyp_var:
+ if gyp_var:
+ os.environ['GYP_GENERATORS'] = gyp_var + ',ninja'
+ else:
+ os.environ['GYP_GENERATORS'] = 'ninja'
+
+ if IsWindows():
+ os.environ['GYP_DEFINES'] = 'component=shared_library '\
+ 'incremental_chrome_dll=1 disable_nacl=1 fastbuild=1 '\
+ 'chromium_win_pch=0'
+
+
+def SetMakeBuildSystemDefault():
+ """Makes make the default build system to be used by
+ the bisection script."""
+ os.environ['GYP_GENERATORS'] = 'make'
+
+
+def CheckPlatformSupported(opts):
+ """Checks that this platform and build system are supported.
+
+ Args:
+ opts: The options parsed from the command line.
+
+ Returns:
+ True if the platform and build system are supported.
+ """
+ # Haven't tested the script out on any other platforms yet.
+ supported = ['posix', 'nt']
+ if not os.name in supported:
+ print "Sorry, this platform isn't supported yet."
+ print
+ return False
+
+ if IsWindows():
+ if not opts.build_preference:
+ opts.build_preference = 'msvs'
+
+ if opts.build_preference == 'msvs':
+ if not os.getenv('VS100COMNTOOLS'):
+ print 'Error: Path to visual studio could not be determined.'
+ print
+ return False
+ elif opts.build_preference == 'ninja':
+ SetNinjaBuildSystemDefault()
+ else:
+ assert False, 'Error: %s build not supported' % opts.build_preference
+ else:
+ if not opts.build_preference:
+ if 'ninja' in os.getenv('GYP_GENERATORS'):
+ opts.build_preference = 'ninja'
+ else:
+ opts.build_preference = 'make'
+
+ if opts.build_preference == 'ninja':
+ SetNinjaBuildSystemDefault()
+ elif opts.build_preference == 'make':
+ SetMakeBuildSystemDefault()
+ elif opts.build_preference != 'make':
+ assert False, 'Error: %s build not supported' % opts.build_preference
+
+ bisect_utils.RunGClient(['runhooks'])
+
+ return True
+
+
+def RmTreeAndMkDir(path_to_dir):
+ """Removes the directory tree specified, and then creates an empty
+ directory in the same location.
+
+ Args:
+ path_to_dir: Path to the directory tree.
+
+ Returns:
+ True if successful, False if an error occurred.
+ """
+ try:
+ if os.path.exists(path_to_dir):
+ shutil.rmtree(path_to_dir)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ return False
+
+ try:
+ os.makedirs(path_to_dir)
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ return False
+
+ return True
+
+
+def RemoveBuildFiles():
+ """Removes build files from previous runs."""
+ if RmTreeAndMkDir(os.path.join('out', 'Release')):
+ if RmTreeAndMkDir(os.path.join('build', 'Release')):
+ return True
+ return False
+
+
+def main():
+
+ usage = ('%prog [options] [-- chromium-options]\n'
+ 'Perform binary search on revision history to find a minimal '
+ 'range of revisions where a peformance metric regressed.\n')
+
+ parser = optparse.OptionParser(usage=usage)
+
+ parser.add_option('-c', '--command',
+ type='str',
+ help='A command to execute your performance test at' +
+ ' each point in the bisection.')
+ parser.add_option('-b', '--bad_revision',
+ type='str',
+ help='A bad revision to start bisection. ' +
+ 'Must be later than good revision. May be either a git' +
+ ' or svn revision.')
+ parser.add_option('-g', '--good_revision',
+ type='str',
+ help='A revision to start bisection where performance' +
+ ' test is known to pass. Must be earlier than the ' +
+ 'bad revision. May be either a git or svn revision.')
+ parser.add_option('-m', '--metric',
+ type='str',
+ help='The desired metric to bisect on. For example ' +
+ '"vm_rss_final_b/vm_rss_f_b"')
+ parser.add_option('-w', '--working_directory',
+ type='str',
+ help='Path to the working directory where the script will '
+ 'do an initial checkout of the chromium depot. The '
+ 'files will be placed in a subdirectory "bisect" under '
+ 'working_directory and that will be used to perform the '
+ 'bisection. This parameter is optional, if it is not '
+ 'supplied, the script will work from the current depot.')
+ parser.add_option('-r', '--repeat_test_count',
+ type='int',
+ default=20,
+ help='The number of times to repeat the performance test. '
+ 'Values will be clamped to range [1, 100]. '
+ 'Default value is 20.')
+ parser.add_option('--repeat_test_max_time',
+ type='int',
+ default=20,
+ help='The maximum time (in minutes) to take running the '
+ 'performance tests. The script will run the performance '
+ 'tests according to --repeat_test_count, so long as it '
+ 'doesn\'t exceed --repeat_test_max_time. Values will be '
+ 'clamped to range [1, 60].'
+ 'Default value is 20.')
+ parser.add_option('-t', '--truncate_percent',
+ type='int',
+ default=25,
+ help='The highest/lowest % are discarded to form a '
+ 'truncated mean. Values will be clamped to range [0, 25]. '
+ 'Default value is 25 (highest/lowest 25% will be '
+ 'discarded).')
+ parser.add_option('--build_preference',
+ type='choice',
+ choices=['msvs', 'ninja', 'make'],
+ help='The preferred build system to use. On linux/mac '
+ 'the options are make/ninja. On Windows, the options '
+ 'are msvs/ninja.')
+ parser.add_option('--target_platform',
+ type='choice',
+ choices=['chromium', 'cros', 'android'],
+ default='chromium',
+ help='The target platform. Choices are "chromium" (current '
+ 'platform), "cros", or "android". If you specify something '
+ 'other than "chromium", you must be properly set up to '
+ 'build that platform.')
+ parser.add_option('--cros_board',
+ type='str',
+ help='The cros board type to build.')
+ parser.add_option('--cros_remote_ip',
+ type='str',
+ help='The remote machine to image to.')
+ parser.add_option('--use_goma',
+ action="store_true",
+ help='Add a bunch of extra threads for goma.')
+ parser.add_option('--output_buildbot_annotations',
+ action="store_true",
+ help='Add extra annotation output for buildbot.')
+ parser.add_option('--debug_ignore_build',
+ action="store_true",
+ help='DEBUG: Don\'t perform builds.')
+ parser.add_option('--debug_ignore_sync',
+ action="store_true",
+ help='DEBUG: Don\'t perform syncs.')
+ parser.add_option('--debug_ignore_perf_test',
+ action="store_true",
+ help='DEBUG: Don\'t perform performance tests.')
+ (opts, args) = parser.parse_args()
+
+ if not opts.command:
+ print 'Error: missing required parameter: --command'
+ print
+ parser.print_help()
+ return 1
+
+ if not opts.good_revision:
+ print 'Error: missing required parameter: --good_revision'
+ print
+ parser.print_help()
+ return 1
+
+ if not opts.bad_revision:
+ print 'Error: missing required parameter: --bad_revision'
+ print
+ parser.print_help()
+ return 1
+
+ if not opts.metric:
+ print 'Error: missing required parameter: --metric'
+ print
+ parser.print_help()
+ return 1
+
+ if opts.target_platform == 'cros':
+ # Run sudo up front to make sure credentials are cached for later.
+ print 'Sudo is required to build cros:'
+ print
+ RunProcess(['sudo', 'true'])
+
+ if not opts.cros_board:
+ print 'Error: missing required parameter: --cros_board'
+ print
+ parser.print_help()
+ return 1
+
+ if not opts.cros_remote_ip:
+ print 'Error: missing required parameter: --cros_remote_ip'
+ print
+ parser.print_help()
+ return 1
+
+ if not opts.working_directory:
+ print 'Error: missing required parameter: --working_directory'
+ print
+ parser.print_help()
+ return 1
+
+ opts.repeat_test_count = min(max(opts.repeat_test_count, 1), 100)
+ opts.repeat_test_max_time = min(max(opts.repeat_test_max_time, 1), 60)
+ opts.truncate_percent = min(max(opts.truncate_percent, 0), 25)
+ opts.truncate_percent = opts.truncate_percent / 100.0
+
+ metric_values = opts.metric.split('/')
+ if len(metric_values) != 2:
+ print "Invalid metric specified: [%s]" % (opts.metric,)
+ print
+ return 1
+
+ if opts.working_directory:
+ if bisect_utils.CreateBisectDirectoryAndSetupDepot(opts):
+ return 1
+
+ if not bisect_utils.SetupPlatformBuildEnvironment(opts):
+ print 'Error: Failed to set platform environment.'
+ print
+ return 1
+
+ os.chdir(os.path.join(os.getcwd(), 'src'))
+
+ if not RemoveBuildFiles():
+ print "Something went wrong removing the build files."
+ print
+ return 1
+
+ if not CheckPlatformSupported(opts):
+ return 1
+
+ # Check what source control method they're using. Only support git workflow
+ # at the moment.
+ source_control = DetermineAndCreateSourceControl(opts)
+
+ if not source_control:
+ print "Sorry, only the git workflow is supported at the moment."
+ print
+ return 1
+
+ # gClient sync seems to fail if you're not in master branch.
+ if not source_control.IsInProperBranch() and not opts.debug_ignore_sync:
+ print "You must switch to master branch to run bisection."
+ print
+ return 1
+
+ bisect_test = BisectPerformanceMetrics(source_control, opts)
+ try:
+ bisect_results = bisect_test.Run(opts.command,
+ opts.bad_revision,
+ opts.good_revision,
+ metric_values)
+ if not(bisect_results['error']):
+ bisect_test.FormatAndPrintResults(bisect_results)
+ finally:
+ bisect_test.PerformCleanup()
+
+ if not(bisect_results['error']):
+ return 0
+ else:
+ print 'Error: ' + bisect_results['error']
+ print
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/bisect_test.py b/chromium/tools/bisect_test.py
new file mode 100644
index 00000000000..b970f84e36d
--- /dev/null
+++ b/chromium/tools/bisect_test.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+bisect_builds = __import__('bisect-builds')
+
+
+class BisectTest(unittest.TestCase):
+
+ patched = []
+ max_rev = 10000
+
+ def monkey_patch(self, obj, name, new):
+ self.patched.append((obj, name, getattr(obj, name)))
+ setattr(obj, name, new)
+
+ def clear_patching(self):
+ for obj, name, old in self.patched:
+ setattr(obj, name, old)
+ self.patched = []
+
+ def setUp(self):
+ self.monkey_patch(bisect_builds.DownloadJob, 'Start', lambda *args: None)
+ self.monkey_patch(bisect_builds.DownloadJob, 'Stop', lambda *args: None)
+ self.monkey_patch(bisect_builds.DownloadJob, 'WaitFor', lambda *args: None)
+ self.monkey_patch(bisect_builds, 'RunRevision', lambda *args: (0, "", ""))
+ self.monkey_patch(bisect_builds.PathContext, 'ParseDirectoryIndex',
+ lambda *args: range(self.max_rev))
+
+ def tearDown(self):
+ self.clear_patching()
+
+ def bisect(self, good_rev, bad_rev, evaluate):
+ return bisect_builds.Bisect(good_rev=good_rev,
+ bad_rev=bad_rev,
+ evaluate=evaluate,
+ num_runs=1,
+ official_builds=False,
+ platform='linux',
+ profile=None,
+ try_args=())
+
+ def testBisectConsistentAnswer(self):
+ self.assertEqual(self.bisect(1000, 100, lambda *args: 'g'), (100, 101))
+ self.assertEqual(self.bisect(100, 1000, lambda *args: 'b'), (100, 101))
+ self.assertEqual(self.bisect(2000, 200, lambda *args: 'b'), (1999, 2000))
+ self.assertEqual(self.bisect(200, 2000, lambda *args: 'g'), (1999, 2000))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/bisect_utils.py b/chromium/tools/bisect_utils.py
new file mode 100644
index 00000000000..37869df7911
--- /dev/null
+++ b/chromium/tools/bisect_utils.py
@@ -0,0 +1,402 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Set of operations/utilities related to checking out the depot, and
+outputting annotations on the buildbot waterfall. These are intended to be
+used by the bisection scripts."""
+
+import errno
+import os
+import shutil
+import subprocess
+import sys
+
+GCLIENT_SPEC_DATA = [
+ { "name" : "src",
+ "url" : "https://chromium.googlesource.com/chromium/src.git",
+ "deps_file" : ".DEPS.git",
+ "managed" : True,
+ "custom_deps" : {
+ "src/data/page_cycler": "https://chrome-internal.googlesource.com/"
+ "chrome/data/page_cycler/.git",
+ "src/data/dom_perf": "https://chrome-internal.googlesource.com/"
+ "chrome/data/dom_perf/.git",
+ "src/data/mach_ports": "https://chrome-internal.googlesource.com/"
+ "chrome/data/mach_ports/.git",
+ "src/tools/perf/data": "https://chrome-internal.googlesource.com/"
+ "chrome/tools/perf/data/.git",
+ "src/third_party/adobe/flash/binaries/ppapi/linux":
+ "https://chrome-internal.googlesource.com/"
+ "chrome/deps/adobe/flash/binaries/ppapi/linux/.git",
+ "src/third_party/adobe/flash/binaries/ppapi/linux_x64":
+ "https://chrome-internal.googlesource.com/"
+ "chrome/deps/adobe/flash/binaries/ppapi/linux_x64/.git",
+ "src/third_party/adobe/flash/binaries/ppapi/mac":
+ "https://chrome-internal.googlesource.com/"
+ "chrome/deps/adobe/flash/binaries/ppapi/mac/.git",
+ "src/third_party/adobe/flash/binaries/ppapi/mac_64":
+ "https://chrome-internal.googlesource.com/"
+ "chrome/deps/adobe/flash/binaries/ppapi/mac_64/.git",
+ "src/third_party/adobe/flash/binaries/ppapi/win":
+ "https://chrome-internal.googlesource.com/"
+ "chrome/deps/adobe/flash/binaries/ppapi/win/.git",
+ "src/third_party/adobe/flash/binaries/ppapi/win_x64":
+ "https://chrome-internal.googlesource.com/"
+ "chrome/deps/adobe/flash/binaries/ppapi/win_x64/.git",
+ },
+ "safesync_url": "",
+ },
+]
+GCLIENT_SPEC_ANDROID = "\ntarget_os = ['android']"
+GCLIENT_CUSTOM_DEPS_V8 = {"src/v8_bleeding_edge": "git://github.com/v8/v8.git"}
+FILE_DEPS_GIT = '.DEPS.git'
+
+REPO_PARAMS = [
+ 'https://chrome-internal.googlesource.com/chromeos/manifest-internal/',
+ '--repo-url',
+ 'https://git.chromium.org/external/repo.git'
+]
+
+REPO_SYNC_COMMAND = 'git checkout -f $(git rev-list --max-count=1 '\
+ '--before=%d remotes/m/master)'
+
+ORIGINAL_ENV = {}
+
+def OutputAnnotationStepStart(name):
+ """Outputs appropriate annotation to signal the start of a step to
+ a trybot.
+
+ Args:
+ name: The name of the step.
+ """
+ print
+ print '@@@SEED_STEP %s@@@' % name
+ print '@@@STEP_CURSOR %s@@@' % name
+ print '@@@STEP_STARTED@@@'
+ print
+ sys.stdout.flush()
+
+
+def OutputAnnotationStepClosed():
+ """Outputs appropriate annotation to signal the closing of a step to
+ a trybot."""
+ print
+ print '@@@STEP_CLOSED@@@'
+ print
+ sys.stdout.flush()
+
+
+def CreateAndChangeToSourceDirectory(working_directory):
+ """Creates a directory 'bisect' as a subdirectory of 'working_directory'. If
+ the function is successful, the current working directory will change to that
+ of the new 'bisect' directory.
+
+ Returns:
+ True if the directory was successfully created (or already existed).
+ """
+ cwd = os.getcwd()
+ os.chdir(working_directory)
+ try:
+ os.mkdir('bisect')
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ return False
+ os.chdir('bisect')
+ return True
+
+
+def SubprocessCall(cmd, cwd=None):
+ """Runs a subprocess with specified parameters.
+
+ Args:
+ params: A list of parameters to pass to gclient.
+ cwd: Working directory to run from.
+
+ Returns:
+ The return code of the call.
+ """
+ if os.name == 'nt':
+ # "HOME" isn't normally defined on windows, but is needed
+ # for git to find the user's .netrc file.
+ if not os.getenv('HOME'):
+ os.environ['HOME'] = os.environ['USERPROFILE']
+ shell = os.name == 'nt'
+ return subprocess.call(cmd, shell=shell, cwd=cwd)
+
+
+def RunGClient(params, cwd=None):
+ """Runs gclient with the specified parameters.
+
+ Args:
+ params: A list of parameters to pass to gclient.
+ cwd: Working directory to run from.
+
+ Returns:
+ The return code of the call.
+ """
+ cmd = ['gclient'] + params
+
+ return SubprocessCall(cmd, cwd=cwd)
+
+
+def RunRepo(params):
+ """Runs cros repo command with specified parameters.
+
+ Args:
+ params: A list of parameters to pass to gclient.
+
+ Returns:
+ The return code of the call.
+ """
+ cmd = ['repo'] + params
+
+ return SubprocessCall(cmd)
+
+
+def RunRepoSyncAtTimestamp(timestamp):
+ """Syncs all git depots to the timestamp specified using repo forall.
+
+ Args:
+ params: Unix timestamp to sync to.
+
+ Returns:
+ The return code of the call.
+ """
+ repo_sync = REPO_SYNC_COMMAND % timestamp
+ cmd = ['forall', '-c', REPO_SYNC_COMMAND % timestamp]
+ return RunRepo(cmd)
+
+
+def RunGClientAndCreateConfig(opts, custom_deps=None, cwd=None):
+ """Runs gclient and creates a config containing both src and src-internal.
+
+ Args:
+ opts: The options parsed from the command line through parse_args().
+ custom_deps: A dictionary of additional dependencies to add to .gclient.
+ cwd: Working directory to run from.
+
+ Returns:
+ The return code of the call.
+ """
+ spec = GCLIENT_SPEC_DATA
+
+ if custom_deps:
+ for k, v in custom_deps.iteritems():
+ spec[0]['custom_deps'][k] = v
+
+ # Cannot have newlines in string on windows
+ spec = 'solutions =' + str(spec)
+ spec = ''.join([l for l in spec.splitlines()])
+
+ if opts.target_platform == 'android':
+ spec += GCLIENT_SPEC_ANDROID
+
+ return_code = RunGClient(
+ ['config', '--spec=%s' % spec, '--git-deps'], cwd=cwd)
+ return return_code
+
+
+def IsDepsFileBlink():
+ """Reads .DEPS.git and returns whether or not we're using blink.
+
+ Returns:
+ True if blink, false if webkit.
+ """
+ locals = {'Var': lambda _: locals["vars"][_],
+ 'From': lambda *args: None}
+ execfile(FILE_DEPS_GIT, {}, locals)
+ return 'blink.git' in locals['vars']['webkit_url']
+
+
+def RemoveThirdPartyWebkitDirectory():
+ """Removes third_party/WebKit.
+
+ Returns:
+ True on success.
+ """
+ try:
+ path_to_dir = os.path.join(os.getcwd(), 'third_party', 'WebKit')
+ if os.path.exists(path_to_dir):
+ shutil.rmtree(path_to_dir)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ return False
+ return True
+
+
+def RunGClientAndSync(cwd=None):
+ """Runs gclient and does a normal sync.
+
+ Args:
+ cwd: Working directory to run from.
+
+ Returns:
+ The return code of the call.
+ """
+ params = ['sync', '--verbose', '--nohooks', '--reset', '--force']
+ return RunGClient(params, cwd=cwd)
+
+
+def SetupGitDepot(opts):
+ """Sets up the depot for the bisection. The depot will be located in a
+ subdirectory called 'bisect'.
+
+ Args:
+ opts: The options parsed from the command line through parse_args().
+
+ Returns:
+ True if gclient successfully created the config file and did a sync, False
+ otherwise.
+ """
+ name = 'Setting up Bisection Depot'
+
+ if opts.output_buildbot_annotations:
+ OutputAnnotationStepStart(name)
+
+ passed = False
+
+ if not RunGClientAndCreateConfig(opts):
+ passed_deps_check = True
+ if os.path.isfile(os.path.join('src', FILE_DEPS_GIT)):
+ cwd = os.getcwd()
+ os.chdir('src')
+ if not IsDepsFileBlink():
+ passed_deps_check = RemoveThirdPartyWebkitDirectory()
+ else:
+ passed_deps_check = True
+ os.chdir(cwd)
+
+ if passed_deps_check:
+ RunGClient(['revert'])
+ if not RunGClientAndSync():
+ passed = True
+
+ if opts.output_buildbot_annotations:
+ print
+ OutputAnnotationStepClosed()
+
+ return passed
+
+
+def SetupCrosRepo():
+ """Sets up cros repo for bisecting chromeos.
+
+ Returns:
+ Returns 0 on success.
+ """
+ cwd = os.getcwd()
+ try:
+ os.mkdir('cros')
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ return False
+ os.chdir('cros')
+
+ cmd = ['init', '-u'] + REPO_PARAMS
+
+ passed = False
+
+ if not RunRepo(cmd):
+ if not RunRepo(['sync']):
+ passed = True
+ os.chdir(cwd)
+
+ return passed
+
+
+def CopyAndSaveOriginalEnvironmentVars():
+ """Makes a copy of the current environment variables."""
+ # TODO: Waiting on crbug.com/255689, will remove this after.
+ vars_to_remove = []
+ for k, v in os.environ.iteritems():
+ if 'ANDROID' in k:
+ vars_to_remove.append(k)
+ vars_to_remove.append('CHROME_SRC')
+ vars_to_remove.append('CHROMIUM_GYP_FILE')
+ vars_to_remove.append('GYP_CROSSCOMPILE')
+ vars_to_remove.append('GYP_DEFINES')
+ vars_to_remove.append('GYP_GENERATORS')
+ vars_to_remove.append('GYP_GENERATOR_FLAGS')
+ vars_to_remove.append('OBJCOPY')
+ for k in vars_to_remove:
+ if os.environ.has_key(k):
+ del os.environ[k]
+
+ global ORIGINAL_ENV
+ ORIGINAL_ENV = os.environ.copy()
+
+
+def SetupAndroidBuildEnvironment(opts):
+ """Sets up the android build environment.
+
+ Args:
+ opts: The options parsed from the command line through parse_args().
+ path_to_file: Path to the bisect script's directory.
+
+ Returns:
+ True if successful.
+ """
+
+ # Revert the environment variables back to default before setting them up
+ # with envsetup.sh.
+ env_vars = os.environ.copy()
+ for k, _ in env_vars.iteritems():
+ del os.environ[k]
+ for k, v in ORIGINAL_ENV.iteritems():
+ os.environ[k] = v
+
+ path_to_file = os.path.join('build', 'android', 'envsetup.sh')
+ proc = subprocess.Popen(['bash', '-c', 'source %s && env' % path_to_file],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ cwd='src')
+ (out, _) = proc.communicate()
+
+ for line in out.splitlines():
+ (k, _, v) = line.partition('=')
+ os.environ[k] = v
+ return not proc.returncode
+
+
+def SetupPlatformBuildEnvironment(opts):
+ """Performs any platform specific setup.
+
+ Args:
+ opts: The options parsed from the command line through parse_args().
+ path_to_file: Path to the bisect script's directory.
+
+ Returns:
+ True if successful.
+ """
+ if opts.target_platform == 'android':
+ CopyAndSaveOriginalEnvironmentVars()
+ return SetupAndroidBuildEnvironment(opts)
+ elif opts.target_platform == 'cros':
+ return SetupCrosRepo()
+
+ return True
+
+
+def CreateBisectDirectoryAndSetupDepot(opts):
+ """Sets up a subdirectory 'bisect' and then retrieves a copy of the depot
+ there using gclient.
+
+ Args:
+ opts: The options parsed from the command line through parse_args().
+ reset: Whether to reset any changes to the depot.
+
+ Returns:
+ Returns 0 on success, otherwise 1.
+ """
+ if not CreateAndChangeToSourceDirectory(opts.working_directory):
+ print 'Error: Could not create bisect directory.'
+ print
+ return 1
+
+ if not SetupGitDepot(opts):
+ print 'Error: Failed to grab source.'
+ print
+ return 1
+
+ return 0
diff --git a/chromium/tools/checkbins/checkbins.py b/chromium/tools/checkbins/checkbins.py
new file mode 100755
index 00000000000..e166eec5514
--- /dev/null
+++ b/chromium/tools/checkbins/checkbins.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Makes sure that all EXE and DLL files in the provided directory were built
+correctly.
+
+In essense it runs a subset of BinScope tests ensuring that binaries have
+/NXCOMPAT, /DYNAMICBASE and /SAFESEH.
+"""
+
+import os
+import optparse
+import sys
+
+# Find /third_party/pefile based on current directory and script path.
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..',
+ 'third_party', 'pefile'))
+import pefile
+
+PE_FILE_EXTENSIONS = ['.exe', '.dll']
+DYNAMICBASE_FLAG = 0x0040
+NXCOMPAT_FLAG = 0x0100
+NO_SEH_FLAG = 0x0400
+MACHINE_TYPE_AMD64 = 0x8664
+
+# Please do not add your file here without confirming that it indeed doesn't
+# require /NXCOMPAT and /DYNAMICBASE. Contact cpu@chromium.org or your local
+# Windows guru for advice.
+EXCLUDED_FILES = ['chrome_frame_mini_installer.exe',
+ 'mini_installer.exe',
+ 'wow_helper.exe',
+ 'xinput1_3.dll' # Microsoft DirectX redistributable.
+ ]
+
+def IsPEFile(path):
+ return (os.path.isfile(path) and
+ os.path.splitext(path)[1].lower() in PE_FILE_EXTENSIONS and
+ os.path.basename(path) not in EXCLUDED_FILES)
+
+def main(options, args):
+ directory = args[0]
+ pe_total = 0
+ pe_passed = 0
+
+ for file in os.listdir(directory):
+ path = os.path.abspath(os.path.join(directory, file))
+ if not IsPEFile(path):
+ continue
+ pe = pefile.PE(path, fast_load=True)
+ pe.parse_data_directories(directories=[
+ pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG']])
+ pe_total = pe_total + 1
+ success = True
+
+ # Check for /DYNAMICBASE.
+ if pe.OPTIONAL_HEADER.DllCharacteristics & DYNAMICBASE_FLAG:
+ if options.verbose:
+ print "Checking %s for /DYNAMICBASE... PASS" % path
+ else:
+ success = False
+ print "Checking %s for /DYNAMICBASE... FAIL" % path
+
+ # Check for /NXCOMPAT.
+ if pe.OPTIONAL_HEADER.DllCharacteristics & NXCOMPAT_FLAG:
+ if options.verbose:
+ print "Checking %s for /NXCOMPAT... PASS" % path
+ else:
+ success = False
+ print "Checking %s for /NXCOMPAT... FAIL" % path
+
+ # Check for /SAFESEH. Binaries should meet one of the following
+ # criteria:
+ # 1) Have no SEH table as indicated by the DLL characteristics
+ # 2) Have a LOAD_CONFIG section containing a valid SEH table
+ # 3) Be a 64-bit binary, in which case /SAFESEH isn't required
+ #
+ # Refer to the following MSDN article for more information:
+ # http://msdn.microsoft.com/en-us/library/9a89h429.aspx
+ if (pe.OPTIONAL_HEADER.DllCharacteristics & NO_SEH_FLAG or
+ (hasattr(pe, "DIRECTORY_ENTRY_LOAD_CONFIG") and
+ pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerCount > 0 and
+ pe.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable != 0) or
+ pe.FILE_HEADER.Machine == MACHINE_TYPE_AMD64):
+ if options.verbose:
+ print "Checking %s for /SAFESEH... PASS" % path
+ else:
+ success = False
+ print "Checking %s for /SAFESEH... FAIL" % path
+
+ # Update tally.
+ if success:
+ pe_passed = pe_passed + 1
+
+ print "Result: %d files found, %d files passed" % (pe_total, pe_passed)
+ if pe_passed != pe_total:
+ sys.exit(1)
+
+if __name__ == '__main__':
+ usage = "Usage: %prog [options] DIRECTORY"
+ option_parser = optparse.OptionParser(usage=usage)
+ option_parser.add_option("-v", "--verbose", action="store_true",
+ default=False, help="Print debug logging")
+ options, args = option_parser.parse_args()
+ if not args:
+ option_parser.print_help()
+ sys.exit(0)
+ main(options, args)
diff --git a/chromium/tools/checkdeps/DEPS b/chromium/tools/checkdeps/DEPS
new file mode 100644
index 00000000000..7a57b0bcc8e
--- /dev/null
+++ b/chromium/tools/checkdeps/DEPS
@@ -0,0 +1,3 @@
+skip_child_includes = [
+ "testdata",
+]
diff --git a/chromium/tools/checkdeps/PRESUBMIT.py b/chromium/tools/checkdeps/PRESUBMIT.py
new file mode 100644
index 00000000000..10ef63212fa
--- /dev/null
+++ b/chromium/tools/checkdeps/PRESUBMIT.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit script for checkdeps tool.
+"""
+
+
+def CheckChange(input_api, output_api):
+ results = []
+ results.extend(input_api.canned_checks.RunUnitTests(
+ input_api, output_api,
+ [input_api.os_path.join(input_api.PresubmitLocalPath(),
+ 'checkdeps_test.py')]))
+ return results
+
+
+# Mandatory entrypoint.
+def CheckChangeOnUpload(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+
+# Mandatory entrypoint.
+def CheckChangeOnCommit(input_api, output_api):
+ return CheckChange(input_api, output_api)
diff --git a/chromium/tools/checkdeps/checkdeps.py b/chromium/tools/checkdeps/checkdeps.py
new file mode 100755
index 00000000000..5bfde13b4d2
--- /dev/null
+++ b/chromium/tools/checkdeps/checkdeps.py
@@ -0,0 +1,526 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Makes sure that files include headers from allowed directories.
+
+Checks DEPS files in the source tree for rules, and applies those rules to
+"#include" commands in source files. Any source file including something not
+permitted by the DEPS files will fail.
+
+The format of the deps file:
+
+First you have the normal module-level deps. These are the ones used by
+gclient. An example would be:
+
+ deps = {
+ "base":"http://foo.bar/trunk/base"
+ }
+
+DEPS files not in the top-level of a module won't need this. Then you
+have any additional include rules. You can add (using "+") or subtract
+(using "-") from the previously specified rules (including
+module-level deps). You can also specify a path that is allowed for
+now but that we intend to remove, using "!"; this is treated the same
+as "+" when check_deps is run by our bots, but a presubmit step will
+show a warning if you add a new include of a file that is only allowed
+by "!".
+
+Note that for .java files, there is currently no difference between
+"+" and "!", even in the presubmit step.
+
+ include_rules = {
+ # Code should be able to use base (it's specified in the module-level
+ # deps above), but nothing in "base/evil" because it's evil.
+ "-base/evil",
+
+ # But this one subdirectory of evil is OK.
+ "+base/evil/not",
+
+ # And it can include files from this other directory even though there is
+ # no deps rule for it.
+ "+tools/crime_fighter",
+
+ # This dependency is allowed for now but work is ongoing to remove it,
+ # so you shouldn't add further dependencies on it.
+ "!base/evil/ok_for_now.h",
+ }
+
+If you have certain include rules that should only be applied for some
+files within this directory and subdirectories, you can write a
+section named specific_include_rules that is a hash map of regular
+expressions to the list of rules that should apply to files matching
+them. Note that such rules will always be applied before the rules
+from 'include_rules' have been applied, but the order in which rules
+associated with different regular expressions is applied is arbitrary.
+
+ specific_include_rules = {
+ ".*_(unit|browser|api)test\.cc": [
+ "+libraries/testsupport",
+ ],
+ }
+
+DEPS files may be placed anywhere in the tree. Each one applies to all
+subdirectories, where there may be more DEPS files that provide additions or
+subtractions for their own sub-trees.
+
+There is an implicit rule for the current directory (where the DEPS file lives)
+and all of its subdirectories. This prevents you from having to explicitly
+allow the current directory everywhere. This implicit rule is applied first,
+so you can modify or remove it using the normal include rules.
+
+The rules are processed in order. This means you can explicitly allow a higher
+directory and then take away permissions from sub-parts, or the reverse.
+
+Note that all directory separators must be slashes (Unix-style) and not
+backslashes. All directories should be relative to the source root and use
+only lowercase.
+"""
+
+import os
+import optparse
+import re
+import subprocess
+import sys
+import copy
+
+import cpp_checker
+import java_checker
+import results
+from rules import Rule, Rules
+
+
+# Variable name used in the DEPS file to add or subtract include files from
+# the module-level deps.
+INCLUDE_RULES_VAR_NAME = 'include_rules'
+
+# Variable name used in the DEPS file to add or subtract include files
+# from module-level deps specific to files whose basename (last
+# component of path) matches a given regular expression.
+SPECIFIC_INCLUDE_RULES_VAR_NAME = 'specific_include_rules'
+
+# Optionally present in the DEPS file to list subdirectories which should not
+# be checked. This allows us to skip third party code, for example.
+SKIP_SUBDIRS_VAR_NAME = 'skip_child_includes'
+
+
+def NormalizePath(path):
+ """Returns a path normalized to how we write DEPS rules and compare paths.
+ """
+ return path.lower().replace('\\', '/')
+
+
+def _IsTestFile(filename):
+ """Does a rudimentary check to try to skip test files; this could be
+ improved but is good enough for now.
+ """
+ return re.match('(test|mock|dummy)_.*|.*_[a-z]*test\.(cc|mm|java)', filename)
+
+
+class DepsChecker(object):
+ """Parses include_rules from DEPS files and can verify files in the
+ source tree against them.
+ """
+
+ def __init__(self,
+ base_directory=None,
+ verbose=False,
+ being_tested=False,
+ ignore_temp_rules=False,
+ skip_tests=False):
+ """Creates a new DepsChecker.
+
+ Args:
+ base_directory: OS-compatible path to root of checkout, e.g. C:\chr\src.
+ verbose: Set to true for debug output.
+ being_tested: Set to true to ignore the DEPS file at tools/checkdeps/DEPS.
+ """
+ self.base_directory = base_directory
+ self.verbose = verbose
+ self._under_test = being_tested
+ self._ignore_temp_rules = ignore_temp_rules
+ self._skip_tests = skip_tests
+
+ if not base_directory:
+ self.base_directory = os.path.abspath(
+ os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', '..'))
+
+ self.results_formatter = results.NormalResultsFormatter(verbose)
+
+ self.git_source_directories = set()
+ self._AddGitSourceDirectories()
+
+ # Map of normalized directory paths to rules to use for those
+ # directories, or None for directories that should be skipped.
+ self.directory_rules = {}
+ self._ApplyDirectoryRulesAndSkipSubdirs(Rules(), self.base_directory)
+
+ def Report(self):
+ """Prints a report of results, and returns an exit code for the process."""
+ if self.results_formatter.GetResults():
+ self.results_formatter.PrintResults()
+ return 1
+ print '\nSUCCESS\n'
+ return 0
+
+ def _ApplyRules(self, existing_rules, includes, specific_includes, cur_dir):
+ """Applies the given include rules, returning the new rules.
+
+ Args:
+ existing_rules: A set of existing rules that will be combined.
+ include: The list of rules from the "include_rules" section of DEPS.
+ specific_includes: E.g. {'.*_unittest\.cc': ['+foo', '-blat']} rules
+ from the "specific_include_rules" section of DEPS.
+ cur_dir: The current directory, normalized path. We will create an
+ implicit rule that allows inclusion from this directory.
+
+ Returns: A new set of rules combining the existing_rules with the other
+ arguments.
+ """
+ rules = copy.deepcopy(existing_rules)
+
+ # First apply the implicit "allow" rule for the current directory.
+ if cur_dir.startswith(
+ NormalizePath(os.path.normpath(self.base_directory))):
+ relative_dir = cur_dir[len(self.base_directory) + 1:]
+
+ source = relative_dir
+ if len(source) == 0:
+ source = 'top level' # Make the help string a little more meaningful.
+ rules.AddRule('+' + relative_dir, 'Default rule for ' + source)
+ else:
+ raise Exception('Internal error: base directory is not at the beginning' +
+ ' for\n %s and base dir\n %s' %
+ (cur_dir, self.base_directory))
+
+ def ApplyOneRule(rule_str, dependee_regexp=None):
+ """Deduces a sensible description for the rule being added, and
+ adds the rule with its description to |rules|.
+
+ If we are ignoring temporary rules, this function does nothing
+ for rules beginning with the Rule.TEMP_ALLOW character.
+ """
+ if self._ignore_temp_rules and rule_str.startswith(Rule.TEMP_ALLOW):
+ return
+
+ rule_block_name = 'include_rules'
+ if dependee_regexp:
+ rule_block_name = 'specific_include_rules'
+ if not relative_dir:
+ rule_description = 'the top level %s' % rule_block_name
+ else:
+ rule_description = relative_dir + "'s %s" % rule_block_name
+ rules.AddRule(rule_str, rule_description, dependee_regexp)
+
+ # Apply the additional explicit rules.
+ for (_, rule_str) in enumerate(includes):
+ ApplyOneRule(rule_str)
+
+ # Finally, apply the specific rules.
+ for regexp, specific_rules in specific_includes.iteritems():
+ for rule_str in specific_rules:
+ ApplyOneRule(rule_str, regexp)
+
+ return rules
+
+ def _ApplyDirectoryRules(self, existing_rules, dir_name):
+ """Combines rules from the existing rules and the new directory.
+
+ Any directory can contain a DEPS file. Toplevel DEPS files can contain
+ module dependencies which are used by gclient. We use these, along with
+ additional include rules and implicit rules for the given directory, to
+ come up with a combined set of rules to apply for the directory.
+
+ Args:
+ existing_rules: The rules for the parent directory. We'll add-on to these.
+ dir_name: The directory name that the deps file may live in (if
+ it exists). This will also be used to generate the
+ implicit rules. This is a non-normalized path.
+
+ Returns: A tuple containing: (1) the combined set of rules to apply to the
+ sub-tree, and (2) a list of all subdirectories that should NOT be
+ checked, as specified in the DEPS file (if any).
+ """
+ norm_dir_name = NormalizePath(dir_name)
+
+ # Check for a .svn directory in this directory or check this directory is
+ # contained in git source direcotries. This will tell us if it's a source
+ # directory and should be checked.
+ if not (os.path.exists(os.path.join(dir_name, ".svn")) or
+ (norm_dir_name in self.git_source_directories)):
+ return (None, [])
+
+ # Check the DEPS file in this directory.
+ if self.verbose:
+ print 'Applying rules from', dir_name
+ def FromImpl(_unused, _unused2):
+ pass # NOP function so "From" doesn't fail.
+
+ def FileImpl(_unused):
+ pass # NOP function so "File" doesn't fail.
+
+ class _VarImpl:
+ def __init__(self, local_scope):
+ self._local_scope = local_scope
+
+ def Lookup(self, var_name):
+ """Implements the Var syntax."""
+ if var_name in self._local_scope.get('vars', {}):
+ return self._local_scope['vars'][var_name]
+ raise Exception('Var is not defined: %s' % var_name)
+
+ local_scope = {}
+ global_scope = {
+ 'File': FileImpl,
+ 'From': FromImpl,
+ 'Var': _VarImpl(local_scope).Lookup,
+ }
+ deps_file = os.path.join(dir_name, 'DEPS')
+
+ # The second conditional here is to disregard the
+ # tools/checkdeps/DEPS file while running tests. This DEPS file
+ # has a skip_child_includes for 'testdata' which is necessary for
+ # running production tests, since there are intentional DEPS
+ # violations under the testdata directory. On the other hand when
+ # running tests, we absolutely need to verify the contents of that
+ # directory to trigger those intended violations and see that they
+ # are handled correctly.
+ if os.path.isfile(deps_file) and (
+ not self._under_test or not os.path.split(dir_name)[1] == 'checkdeps'):
+ execfile(deps_file, global_scope, local_scope)
+ elif self.verbose:
+ print ' No deps file found in', dir_name
+
+ # Even if a DEPS file does not exist we still invoke ApplyRules
+ # to apply the implicit "allow" rule for the current directory
+ include_rules = local_scope.get(INCLUDE_RULES_VAR_NAME, [])
+ specific_include_rules = local_scope.get(SPECIFIC_INCLUDE_RULES_VAR_NAME,
+ {})
+ skip_subdirs = local_scope.get(SKIP_SUBDIRS_VAR_NAME, [])
+
+ return (self._ApplyRules(existing_rules, include_rules,
+ specific_include_rules, norm_dir_name),
+ skip_subdirs)
+
+ def _ApplyDirectoryRulesAndSkipSubdirs(self, parent_rules, dir_path):
+ """Given |parent_rules| and a subdirectory |dir_path| from the
+ directory that owns the |parent_rules|, add |dir_path|'s rules to
+ |self.directory_rules|, and add None entries for any of its
+ subdirectories that should be skipped.
+ """
+ directory_rules, excluded_subdirs = self._ApplyDirectoryRules(parent_rules,
+ dir_path)
+ self.directory_rules[NormalizePath(dir_path)] = directory_rules
+ for subdir in excluded_subdirs:
+ self.directory_rules[NormalizePath(
+ os.path.normpath(os.path.join(dir_path, subdir)))] = None
+
+ def GetDirectoryRules(self, dir_path):
+ """Returns a Rules object to use for the given directory, or None
+ if the given directory should be skipped. This takes care of
+ first building rules for parent directories (up to
+ self.base_directory) if needed.
+
+ Args:
+ dir_path: A real (non-normalized) path to the directory you want
+ rules for.
+ """
+ norm_dir_path = NormalizePath(dir_path)
+
+ if not norm_dir_path.startswith(
+ NormalizePath(os.path.normpath(self.base_directory))):
+ dir_path = os.path.join(self.base_directory, dir_path)
+ norm_dir_path = NormalizePath(dir_path)
+
+ parent_dir = os.path.dirname(dir_path)
+ parent_rules = None
+ if not norm_dir_path in self.directory_rules:
+ parent_rules = self.GetDirectoryRules(parent_dir)
+
+ # We need to check for an entry for our dir_path again, in case we
+ # are at a path e.g. A/B/C where A/B/DEPS specifies the C
+ # subdirectory to be skipped; in this case, the invocation to
+ # GetDirectoryRules(parent_dir) has already filled in an entry for
+ # A/B/C.
+ if not norm_dir_path in self.directory_rules:
+ if not parent_rules:
+ # If the parent directory should be skipped, then the current
+ # directory should also be skipped.
+ self.directory_rules[norm_dir_path] = None
+ else:
+ self._ApplyDirectoryRulesAndSkipSubdirs(parent_rules, dir_path)
+ return self.directory_rules[norm_dir_path]
+
+ def CheckDirectory(self, start_dir):
+ """Checks all relevant source files in the specified directory and
+ its subdirectories for compliance with DEPS rules throughout the
+ tree (starting at |self.base_directory|). |start_dir| must be a
+ subdirectory of |self.base_directory|.
+
+ On completion, self.results_formatter has the results of
+ processing, and calling Report() will print a report of results.
+ """
+ java = java_checker.JavaChecker(self.base_directory, self.verbose)
+ cpp = cpp_checker.CppChecker(self.verbose)
+ checkers = dict(
+ (extension, checker)
+ for checker in [java, cpp] for extension in checker.EXTENSIONS)
+ self._CheckDirectoryImpl(checkers, start_dir)
+
+ def _CheckDirectoryImpl(self, checkers, dir_name):
+ rules = self.GetDirectoryRules(dir_name)
+ if rules == None:
+ return
+
+ # Collect a list of all files and directories to check.
+ files_to_check = []
+ dirs_to_check = []
+ contents = os.listdir(dir_name)
+ for cur in contents:
+ full_name = os.path.join(dir_name, cur)
+ if os.path.isdir(full_name):
+ dirs_to_check.append(full_name)
+ elif os.path.splitext(full_name)[1] in checkers:
+ if not self._skip_tests or not _IsTestFile(cur):
+ files_to_check.append(full_name)
+
+ # First check all files in this directory.
+ for cur in files_to_check:
+ checker = checkers[os.path.splitext(cur)[1]]
+ file_status = checker.CheckFile(rules, cur)
+ if file_status.HasViolations():
+ self.results_formatter.AddError(file_status)
+
+ # Next recurse into the subdirectories.
+ for cur in dirs_to_check:
+ self._CheckDirectoryImpl(checkers, cur)
+
+ def CheckAddedCppIncludes(self, added_includes):
+ """This is used from PRESUBMIT.py to check new #include statements added in
+ the change being presubmit checked.
+
+ Args:
+ added_includes: ((file_path, (include_line, include_line, ...), ...)
+
+ Return:
+ A list of tuples, (bad_file_path, rule_type, rule_description)
+ where rule_type is one of Rule.DISALLOW or Rule.TEMP_ALLOW and
+ rule_description is human-readable. Empty if no problems.
+ """
+ cpp = cpp_checker.CppChecker(self.verbose)
+ problems = []
+ for file_path, include_lines in added_includes:
+ if not cpp.IsCppFile(file_path):
+ pass
+ rules_for_file = self.GetDirectoryRules(os.path.dirname(file_path))
+ if rules_for_file:
+ for line in include_lines:
+ is_include, violation = cpp.CheckLine(
+ rules_for_file, line, file_path, True)
+ if violation:
+ rule_type = violation.violated_rule.allow
+ if rule_type != Rule.ALLOW:
+ violation_text = results.NormalResultsFormatter.FormatViolation(
+ violation, self.verbose)
+ problems.append((file_path, rule_type, violation_text))
+ return problems
+
+ def _AddGitSourceDirectories(self):
+ """Adds any directories containing sources managed by git to
+ self.git_source_directories.
+ """
+ if not os.path.exists(os.path.join(self.base_directory, '.git')):
+ return
+
+ popen_out = os.popen('cd %s && git ls-files --full-name .' %
+ subprocess.list2cmdline([self.base_directory]))
+ for line in popen_out.readlines():
+ dir_name = os.path.join(self.base_directory, os.path.dirname(line))
+ # Add the directory as well as all the parent directories. Use
+ # forward slashes and lower case to normalize paths.
+ while dir_name != self.base_directory:
+ self.git_source_directories.add(NormalizePath(dir_name))
+ dir_name = os.path.dirname(dir_name)
+ self.git_source_directories.add(NormalizePath(self.base_directory))
+
+
+def PrintUsage():
+ print """Usage: python checkdeps.py [--root <root>] [tocheck]
+
+ --root ROOT Specifies the repository root. This defaults to "../../.."
+ relative to the script file. This will be correct given the
+ normal location of the script in "<root>/tools/checkdeps".
+
+ --(others) There are a few lesser-used options; run with --help to show them.
+
+ tocheck Specifies the directory, relative to root, to check. This defaults
+ to "." so it checks everything.
+
+Examples:
+ python checkdeps.py
+ python checkdeps.py --root c:\\source chrome"""
+
+
+def main():
+ option_parser = optparse.OptionParser()
+ option_parser.add_option(
+ '', '--root',
+ default='', dest='base_directory',
+ help='Specifies the repository root. This defaults '
+ 'to "../../.." relative to the script file, which '
+ 'will normally be the repository root.')
+ option_parser.add_option(
+ '', '--ignore-temp-rules',
+ action='store_true', dest='ignore_temp_rules', default=False,
+ help='Ignore !-prefixed (temporary) rules.')
+ option_parser.add_option(
+ '', '--generate-temp-rules',
+ action='store_true', dest='generate_temp_rules', default=False,
+ help='Print rules to temporarily allow files that fail '
+ 'dependency checking.')
+ option_parser.add_option(
+ '', '--count-violations',
+ action='store_true', dest='count_violations', default=False,
+ help='Count #includes in violation of intended rules.')
+ option_parser.add_option(
+ '', '--skip-tests',
+ action='store_true', dest='skip_tests', default=False,
+ help='Skip checking test files (best effort).')
+ option_parser.add_option(
+ '-v', '--verbose',
+ action='store_true', default=False,
+ help='Print debug logging')
+ options, args = option_parser.parse_args()
+
+ deps_checker = DepsChecker(options.base_directory,
+ verbose=options.verbose,
+ ignore_temp_rules=options.ignore_temp_rules,
+ skip_tests=options.skip_tests)
+
+ # Figure out which directory we have to check.
+ start_dir = deps_checker.base_directory
+ if len(args) == 1:
+ # Directory specified. Start here. It's supposed to be relative to the
+ # base directory.
+ start_dir = os.path.abspath(
+ os.path.join(deps_checker.base_directory, args[0]))
+ elif len(args) >= 2 or (options.generate_temp_rules and
+ options.count_violations):
+ # More than one argument, or incompatible flags, we don't handle this.
+ PrintUsage()
+ return 1
+
+ print 'Using base directory:', deps_checker.base_directory
+ print 'Checking:', start_dir
+
+ if options.generate_temp_rules:
+ deps_checker.results_formatter = results.TemporaryRulesFormatter()
+ elif options.count_violations:
+ deps_checker.results_formatter = results.CountViolationsFormatter()
+ deps_checker.CheckDirectory(start_dir)
+ return deps_checker.Report()
+
+
+if '__main__' == __name__:
+ sys.exit(main())
diff --git a/chromium/tools/checkdeps/checkdeps_test.py b/chromium/tools/checkdeps/checkdeps_test.py
new file mode 100755
index 00000000000..e8835a5ca8f
--- /dev/null
+++ b/chromium/tools/checkdeps/checkdeps_test.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for checkdeps.
+"""
+
+import os
+import unittest
+
+
+import checkdeps
+import results
+
+
+class CheckDepsTest(unittest.TestCase):
+
+ def setUp(self):
+ self.deps_checker = checkdeps.DepsChecker(being_tested=True)
+
+ def ImplTestRegularCheckDepsRun(self, ignore_temp_rules, skip_tests):
+ self.deps_checker._ignore_temp_rules = ignore_temp_rules
+ self.deps_checker._skip_tests = skip_tests
+ self.deps_checker.CheckDirectory(
+ os.path.join(self.deps_checker.base_directory,
+ 'tools/checkdeps/testdata'))
+
+ problems = self.deps_checker.results_formatter.GetResults()
+ if skip_tests:
+ self.failUnlessEqual(3, len(problems))
+ else:
+ self.failUnlessEqual(4, len(problems))
+
+ def VerifySubstringsInProblems(key_path, substrings_in_sequence):
+ """Finds the problem in |problems| that contains |key_path|,
+ then verifies that each of |substrings_in_sequence| occurs in
+ that problem, in the order they appear in
+ |substrings_in_sequence|.
+ """
+ found = False
+ key_path = os.path.normpath(key_path)
+ for problem in problems:
+ index = problem.find(key_path)
+ if index != -1:
+ for substring in substrings_in_sequence:
+ index = problem.find(substring, index + 1)
+ self.failUnless(index != -1, '%s in %s' % (substring, problem))
+ found = True
+ break
+ if not found:
+ self.fail('Found no problem for file %s' % key_path)
+
+ if ignore_temp_rules:
+ VerifySubstringsInProblems('testdata/allowed/test.h',
+ ['-tools/checkdeps/testdata/disallowed',
+ 'temporarily_allowed.h',
+ '-third_party/explicitly_disallowed',
+ 'Because of no rule applying'])
+ else:
+ VerifySubstringsInProblems('testdata/allowed/test.h',
+ ['-tools/checkdeps/testdata/disallowed',
+ '-third_party/explicitly_disallowed',
+ 'Because of no rule applying'])
+
+ VerifySubstringsInProblems('testdata/disallowed/test.h',
+ ['-third_party/explicitly_disallowed',
+ 'Because of no rule applying',
+ 'Because of no rule applying'])
+ VerifySubstringsInProblems('disallowed/allowed/test.h',
+ ['-third_party/explicitly_disallowed',
+ 'Because of no rule applying',
+ 'Because of no rule applying'])
+
+ if not skip_tests:
+ VerifySubstringsInProblems('allowed/not_a_test.cc',
+ ['-tools/checkdeps/testdata/disallowed'])
+
+ def testRegularCheckDepsRun(self):
+ self.ImplTestRegularCheckDepsRun(False, False)
+
+ def testRegularCheckDepsRunIgnoringTempRules(self):
+ self.ImplTestRegularCheckDepsRun(True, False)
+
+ def testRegularCheckDepsRunSkipTests(self):
+ self.ImplTestRegularCheckDepsRun(False, True)
+
+ def testRegularCheckDepsRunIgnoringTempRulesSkipTests(self):
+ self.ImplTestRegularCheckDepsRun(True, True)
+
+ def CountViolations(self, ignore_temp_rules):
+ self.deps_checker._ignore_temp_rules = ignore_temp_rules
+ self.deps_checker.results_formatter = results.CountViolationsFormatter()
+ self.deps_checker.CheckDirectory(
+ os.path.join(self.deps_checker.base_directory,
+ 'tools/checkdeps/testdata'))
+ return self.deps_checker.results_formatter.GetResults()
+
+ def testCountViolations(self):
+ self.failUnlessEqual('10', self.CountViolations(False))
+
+ def testCountViolationsIgnoringTempRules(self):
+ self.failUnlessEqual('11', self.CountViolations(True))
+
+ def testTempRulesGenerator(self):
+ self.deps_checker.results_formatter = results.TemporaryRulesFormatter()
+ self.deps_checker.CheckDirectory(
+ os.path.join(self.deps_checker.base_directory,
+ 'tools/checkdeps/testdata/allowed'))
+ temp_rules = self.deps_checker.results_formatter.GetResults()
+ expected = [u' "!third_party/explicitly_disallowed/bad.h",',
+ u' "!third_party/no_rule/bad.h",',
+ u' "!tools/checkdeps/testdata/disallowed/bad.h",',
+ u' "!tools/checkdeps/testdata/disallowed/teststuff/bad.h",']
+ self.failUnlessEqual(expected, temp_rules)
+
+ def testCheckAddedIncludesAllGood(self):
+ problems = self.deps_checker.CheckAddedCppIncludes(
+ [['tools/checkdeps/testdata/allowed/test.cc',
+ ['#include "tools/checkdeps/testdata/allowed/good.h"',
+ '#include "tools/checkdeps/testdata/disallowed/allowed/good.h"']
+ ]])
+ self.failIf(problems)
+
+ def testCheckAddedIncludesManyGarbageLines(self):
+ garbage_lines = ["My name is Sam%d\n" % num for num in range(50)]
+ problems = self.deps_checker.CheckAddedCppIncludes(
+ [['tools/checkdeps/testdata/allowed/test.cc', garbage_lines]])
+ self.failIf(problems)
+
+ def testCheckAddedIncludesNoRule(self):
+ problems = self.deps_checker.CheckAddedCppIncludes(
+ [['tools/checkdeps/testdata/allowed/test.cc',
+ ['#include "no_rule_for_this/nogood.h"']
+ ]])
+ self.failUnless(problems)
+
+ def testCheckAddedIncludesSkippedDirectory(self):
+ problems = self.deps_checker.CheckAddedCppIncludes(
+ [['tools/checkdeps/testdata/disallowed/allowed/skipped/test.cc',
+ ['#include "whatever/whocares.h"']
+ ]])
+ self.failIf(problems)
+
+ def testCheckAddedIncludesTempAllowed(self):
+ problems = self.deps_checker.CheckAddedCppIncludes(
+ [['tools/checkdeps/testdata/allowed/test.cc',
+ ['#include "tools/checkdeps/testdata/disallowed/temporarily_allowed.h"']
+ ]])
+ self.failUnless(problems)
+
+ def testCopyIsDeep(self):
+ # Regression test for a bug where we were making shallow copies of
+ # Rules objects and therefore all Rules objects shared the same
+ # dictionary for specific rules.
+ #
+ # The first pair should bring in a rule from testdata/allowed/DEPS
+ # into that global dictionary that allows the
+ # temp_allowed_for_tests.h file to be included in files ending
+ # with _unittest.cc, and the second pair should completely fail
+ # once the bug is fixed, but succeed (with a temporary allowance)
+ # if the bug is in place.
+ problems = self.deps_checker.CheckAddedCppIncludes(
+ [['tools/checkdeps/testdata/allowed/test.cc',
+ ['#include "tools/checkdeps/testdata/disallowed/temporarily_allowed.h"']
+ ],
+ ['tools/checkdeps/testdata/disallowed/foo_unittest.cc',
+ ['#include "tools/checkdeps/testdata/bongo/temp_allowed_for_tests.h"']
+ ]])
+ # With the bug in place, there would be two problems reported, and
+ # the second would be for foo_unittest.cc.
+ self.failUnless(len(problems) == 1)
+ self.failUnless(problems[0][0].endswith('/test.cc'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/checkdeps/cpp_checker.py b/chromium/tools/checkdeps/cpp_checker.py
new file mode 100644
index 00000000000..9bcd14d75cc
--- /dev/null
+++ b/chromium/tools/checkdeps/cpp_checker.py
@@ -0,0 +1,113 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Checks C++ and Objective-C files for illegal includes."""
+
+import codecs
+import os
+import re
+
+import results
+from rules import Rule, MessageRule
+
+
+class CppChecker(object):
+
+ EXTENSIONS = [
+ '.h',
+ '.cc',
+ '.cpp',
+ '.m',
+ '.mm',
+ ]
+
+ # The maximum number of non-include lines we can see before giving up.
+ _MAX_UNINTERESTING_LINES = 50
+
+ # The maximum line length, this is to be efficient in the case of very long
+ # lines (which can't be #includes).
+ _MAX_LINE_LENGTH = 128
+
+ # This regular expression will be used to extract filenames from include
+ # statements.
+ _EXTRACT_INCLUDE_PATH = re.compile(
+ '[ \t]*#[ \t]*(?:include|import)[ \t]+"(.*)"')
+
+ def __init__(self, verbose):
+ self._verbose = verbose
+
+ def CheckLine(self, rules, line, dependee_path, fail_on_temp_allow=False):
+ """Checks the given line with the given rule set.
+
+ Returns a tuple (is_include, dependency_violation) where
+ is_include is True only if the line is an #include or #import
+ statement, and dependency_violation is an instance of
+ results.DependencyViolation if the line violates a rule, or None
+ if it does not.
+ """
+ found_item = self._EXTRACT_INCLUDE_PATH.match(line)
+ if not found_item:
+ return False, None # Not a match
+
+ include_path = found_item.group(1)
+
+ if '\\' in include_path:
+ return True, results.DependencyViolation(
+ include_path,
+ MessageRule('Include paths may not include backslashes.'),
+ rules)
+
+ if '/' not in include_path:
+ # Don't fail when no directory is specified. We may want to be more
+ # strict about this in the future.
+ if self._verbose:
+ print ' WARNING: directory specified with no path: ' + include_path
+ return True, None
+
+ rule = rules.RuleApplyingTo(include_path, dependee_path)
+ if (rule.allow == Rule.DISALLOW or
+ (fail_on_temp_allow and rule.allow == Rule.TEMP_ALLOW)):
+ return True, results.DependencyViolation(include_path, rule, rules)
+ return True, None
+
+ def CheckFile(self, rules, filepath):
+ if self._verbose:
+ print 'Checking: ' + filepath
+
+ dependee_status = results.DependeeStatus(filepath)
+ ret_val = '' # We'll collect the error messages in here
+ last_include = 0
+ with codecs.open(filepath, encoding='utf-8') as f:
+ in_if0 = 0
+ for line_num, line in enumerate(f):
+ if line_num - last_include > self._MAX_UNINTERESTING_LINES:
+ break
+
+ line = line.strip()
+
+ # Check to see if we're at / inside a #if 0 block
+ if line.startswith('#if 0'):
+ in_if0 += 1
+ continue
+ if in_if0 > 0:
+ if line.startswith('#if'):
+ in_if0 += 1
+ elif line.startswith('#endif'):
+ in_if0 -= 1
+ continue
+
+ is_include, violation = self.CheckLine(rules, line, filepath)
+ if is_include:
+ last_include = line_num
+ if violation:
+ dependee_status.AddViolation(violation)
+
+ return dependee_status
+
+ @staticmethod
+ def IsCppFile(file_path):
+ """Returns True iff the given path ends in one of the extensions
+ handled by this checker.
+ """
+ return os.path.splitext(file_path)[1] in CppChecker.EXTENSIONS
diff --git a/chromium/tools/checkdeps/java_checker.py b/chromium/tools/checkdeps/java_checker.py
new file mode 100644
index 00000000000..670eac21645
--- /dev/null
+++ b/chromium/tools/checkdeps/java_checker.py
@@ -0,0 +1,107 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Checks Java files for illegal imports."""
+
+import codecs
+import os
+import re
+
+import results
+from rules import Rule
+
+
+class JavaChecker(object):
+ """Import checker for Java files.
+
+ The CheckFile method uses real filesystem paths, but Java imports work in
+ terms of package names. To deal with this, we have an extra "prescan" pass
+ that reads all the .java files and builds a mapping of class name -> filepath.
+ In CheckFile, we convert each import statement into a real filepath, and check
+ that against the rules in the DEPS files.
+
+ Note that in Java you can always use classes in the same directory without an
+ explicit import statement, so these imports can't be blocked with DEPS files.
+ But that shouldn't be a problem, because same-package imports are pretty much
+ always correct by definition. (If we find a case where this is *not* correct,
+ it probably means the package is too big and needs to be split up.)
+
+ Properties:
+ _classmap: dict of fully-qualified Java class name -> filepath
+ """
+
+ EXTENSIONS = ['.java']
+
+ def __init__(self, base_directory, verbose):
+ self._base_directory = base_directory
+ self._verbose = verbose
+ self._classmap = {}
+ self._PrescanFiles()
+
+ def _PrescanFiles(self):
+ for root, dirs, files in os.walk(self._base_directory):
+ # Skip unwanted subdirectories. TODO(husky): it would be better to do
+ # this via the skip_child_includes flag in DEPS files. Maybe hoist this
+ # prescan logic into checkdeps.py itself?
+ for d in dirs:
+ # Skip hidden directories.
+ if d.startswith('.'):
+ dirs.remove(d)
+ # Skip the "out" directory, as dealing with generated files is awkward.
+ # We don't want paths like "out/Release/lib.java" in our DEPS files.
+ # TODO(husky): We need some way of determining the "real" path to
+ # a generated file -- i.e., where it would be in source control if
+ # it weren't generated.
+ if d == 'out':
+ dirs.remove(d)
+ # Skip third-party directories.
+ if d == 'third_party':
+ dirs.remove(d)
+ for f in files:
+ if f.endswith('.java'):
+ self._PrescanFile(os.path.join(root, f))
+
+ def _PrescanFile(self, filepath):
+ if self._verbose:
+ print 'Prescanning: ' + filepath
+ with codecs.open(filepath, encoding='utf-8') as f:
+ short_class_name, _ = os.path.splitext(os.path.basename(filepath))
+ for line in f:
+ for package in re.findall('^package ([\w\.]+);', line):
+ full_class_name = package + '.' + short_class_name
+ if full_class_name in self._classmap:
+ print 'WARNING: multiple definitions of %s:' % full_class_name
+ print ' ' + filepath
+ print ' ' + self._classmap[full_class_name]
+ print
+ else:
+ self._classmap[full_class_name] = filepath
+ return
+ print 'WARNING: no package definition found in %s' % filepath
+
+ def CheckFile(self, rules, filepath):
+ if self._verbose:
+ print 'Checking: ' + filepath
+
+ dependee_status = results.DependeeStatus(filepath)
+ with codecs.open(filepath, encoding='utf-8') as f:
+ for line in f:
+ for clazz in re.findall('^import\s+(?:static\s+)?([\w\.]+)\s*;', line):
+ if clazz not in self._classmap:
+ # Importing a class from outside the Chromium tree. That's fine --
+ # it's probably a Java or Android system class.
+ continue
+ include_path = os.path.relpath(
+ self._classmap[clazz], self._base_directory)
+ # Convert Windows paths to Unix style, as used in DEPS files.
+ include_path = include_path.replace(os.path.sep, '/')
+ rule = rules.RuleApplyingTo(include_path, filepath)
+ if rule.allow == Rule.DISALLOW:
+ dependee_status.AddViolation(
+ results.DependencyViolation(include_path, rule, rules))
+ if '{' in line:
+ # This is code, so we're finished reading imports for this file.
+ break
+
+ return dependee_status
diff --git a/chromium/tools/checkdeps/results.py b/chromium/tools/checkdeps/results.py
new file mode 100644
index 00000000000..8f9c1898549
--- /dev/null
+++ b/chromium/tools/checkdeps/results.py
@@ -0,0 +1,140 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Results object and results formatters for checkdeps tool."""
+
+
+class DependencyViolation(object):
+ """A single dependency violation."""
+
+ def __init__(self, include_path, violated_rule, rules):
+ # The include or import path that is in violation of a rule.
+ self.include_path = include_path
+
+ # The violated rule.
+ self.violated_rule = violated_rule
+
+ # The set of rules containing self.violated_rule.
+ self.rules = rules
+
+
+class DependeeStatus(object):
+ """Results object for a dependee file."""
+
+ def __init__(self, dependee_path):
+ # Path of the file whose nonconforming dependencies are listed in
+ # self.violations.
+ self.dependee_path = dependee_path
+
+ # List of DependencyViolation objects that apply to the dependee
+ # file. May be empty.
+ self.violations = []
+
+ def AddViolation(self, violation):
+ """Adds a violation."""
+ self.violations.append(violation)
+
+ def HasViolations(self):
+ """Returns True if this dependee is violating one or more rules."""
+ return not not self.violations
+
+
+class ResultsFormatter(object):
+ """Base class for results formatters."""
+
+ def AddError(self, dependee_status):
+ """Add a formatted result to |self.results| for |dependee_status|,
+ which is guaranteed to return True for
+ |dependee_status.HasViolations|.
+ """
+ raise NotImplementedError()
+
+ def GetResults(self):
+ """Returns the results. May be overridden e.g. to process the
+ results that have been accumulated.
+ """
+ raise NotImplementedError()
+
+ def PrintResults(self):
+ """Prints the results to stdout."""
+ raise NotImplementedError()
+
+
+class NormalResultsFormatter(ResultsFormatter):
+ """A results formatting object that produces the classical,
+ detailed, human-readable output of the checkdeps tool.
+ """
+
+ def __init__(self, verbose):
+ self.results = []
+ self.verbose = verbose
+
+ def AddError(self, dependee_status):
+ lines = []
+ lines.append('\nERROR in %s' % dependee_status.dependee_path)
+ for violation in dependee_status.violations:
+ lines.append(self.FormatViolation(violation, self.verbose))
+ self.results.append('\n'.join(lines))
+
+ @staticmethod
+ def FormatViolation(violation, verbose=False):
+ lines = []
+ if verbose:
+ lines.append(' For %s' % violation.rules)
+ lines.append(
+ ' Illegal include: "%s"\n Because of %s' %
+ (violation.include_path, str(violation.violated_rule)))
+ return '\n'.join(lines)
+
+ def GetResults(self):
+ return self.results
+
+ def PrintResults(self):
+ for result in self.results:
+ print result
+ if self.results:
+ print '\nFAILED\n'
+
+
+class TemporaryRulesFormatter(ResultsFormatter):
+ """A results formatter that produces a single line per nonconforming
+ include. The combined output is suitable for directly pasting into a
+ DEPS file as a list of temporary-allow rules.
+ """
+
+ def __init__(self):
+ self.violations = set()
+
+ def AddError(self, dependee_status):
+ for violation in dependee_status.violations:
+ self.violations.add(violation.include_path)
+
+ def GetResults(self):
+ return [' "!%s",' % path for path in sorted(self.violations)]
+
+ def PrintResults(self):
+ for result in self.GetResults():
+ print result
+
+
+class CountViolationsFormatter(ResultsFormatter):
+ """A results formatter that produces a number, the count of #include
+ statements that are in violation of the dependency rules.
+
+ Note that you normally want to instantiate DepsChecker with
+ ignore_temp_rules=True when you use this formatter.
+ """
+
+ def __init__(self):
+ self.count = 0
+
+ def AddError(self, dependee_status):
+ self.count += len(dependee_status.violations)
+
+ def GetResults(self):
+ return '%d' % self.count
+
+ def PrintResults(self):
+ print self.count
diff --git a/chromium/tools/checkdeps/rules.py b/chromium/tools/checkdeps/rules.py
new file mode 100644
index 00000000000..09d718c7234
--- /dev/null
+++ b/chromium/tools/checkdeps/rules.py
@@ -0,0 +1,151 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Base classes to represent dependency rules, used by checkdeps.py"""
+
+
+import os
+import re
+
+
+class Rule(object):
+ """Specifies a single rule for an include, which can be one of
+ ALLOW, DISALLOW and TEMP_ALLOW.
+ """
+
+ # These are the prefixes used to indicate each type of rule. These
+ # are also used as values for self.allow to indicate which type of
+ # rule this is.
+ ALLOW = '+'
+ DISALLOW = '-'
+ TEMP_ALLOW = '!'
+
+ def __init__(self, allow, directory, source):
+ self.allow = allow
+ self._dir = directory
+ self._source = source
+
+ def __str__(self):
+ return '"%s%s" from %s.' % (self.allow, self._dir, self._source)
+
+ def ParentOrMatch(self, other):
+ """Returns true if the input string is an exact match or is a parent
+ of the current rule. For example, the input "foo" would match "foo/bar"."""
+ return self._dir == other or self._dir.startswith(other + '/')
+
+ def ChildOrMatch(self, other):
+ """Returns true if the input string would be covered by this rule. For
+ example, the input "foo/bar" would match the rule "foo"."""
+ return self._dir == other or other.startswith(self._dir + '/')
+
+
+class MessageRule(Rule):
+ """A rule that has a simple message as the reason for failing,
+ unrelated to directory or source.
+ """
+
+ def __init__(self, reason):
+ super(MessageRule, self).__init__(Rule.DISALLOW, '', '')
+ self._reason = reason
+
+ def __str__(self):
+ return self._reason
+
+
+def ParseRuleString(rule_string, source):
+ """Returns a tuple of a character indicating what type of rule this
+ is, and a string holding the path the rule applies to.
+ """
+ if not rule_string:
+ raise Exception('The rule string "%s" is empty\nin %s' %
+ (rule_string, source))
+
+ if not rule_string[0] in [Rule.ALLOW, Rule.DISALLOW, Rule.TEMP_ALLOW]:
+ raise Exception(
+ 'The rule string "%s" does not begin with a "+", "-" or "!".' %
+ rule_string)
+
+ return (rule_string[0], rule_string[1:])
+
+
+class Rules(object):
+ """Sets of rules for files in a directory.
+
+ By default, rules are added to the set of rules applicable to all
+ dependee files in the directory. Rules may also be added that apply
+ only to dependee files whose filename (last component of their path)
+ matches a given regular expression; hence there is one additional
+ set of rules per unique regular expression.
+ """
+
+ def __init__(self):
+ """Initializes the current rules with an empty rule list for all
+ files.
+ """
+ # We keep the general rules out of the specific rules dictionary,
+ # as we need to always process them last.
+ self._general_rules = []
+
+ # Keys are regular expression strings, values are arrays of rules
+ # that apply to dependee files whose basename matches the regular
+ # expression. These are applied before the general rules, but
+ # their internal order is arbitrary.
+ self._specific_rules = {}
+
+ def __str__(self):
+ result = ['Rules = {\n (apply to all files): [\n%s\n ],' % '\n'.join(
+ ' %s' % x for x in self._general_rules)]
+ for regexp, rules in self._specific_rules.iteritems():
+ result.append(' (limited to files matching %s): [\n%s\n ]' % (
+ regexp, '\n'.join(' %s' % x for x in rules)))
+ result.append(' }')
+ return '\n'.join(result)
+
+ def AddRule(self, rule_string, source, dependee_regexp=None):
+ """Adds a rule for the given rule string.
+
+ Args:
+ rule_string: The include_rule string read from the DEPS file to apply.
+ source: A string representing the location of that string (filename, etc.)
+ so that we can give meaningful errors.
+ dependee_regexp: The rule will only be applied to dependee files
+ whose filename (last component of their path)
+ matches the expression. None to match all
+ dependee files.
+ """
+ (rule_type, rule_dir) = ParseRuleString(rule_string, source)
+
+ if not dependee_regexp:
+ rules_to_update = self._general_rules
+ else:
+ if dependee_regexp in self._specific_rules:
+ rules_to_update = self._specific_rules[dependee_regexp]
+ else:
+ rules_to_update = []
+
+ # Remove any existing rules or sub-rules that apply. For example, if we're
+ # passed "foo", we should remove "foo", "foo/bar", but not "foobar".
+ rules_to_update = [x for x in rules_to_update
+ if not x.ParentOrMatch(rule_dir)]
+ rules_to_update.insert(0, Rule(rule_type, rule_dir, source))
+
+ if not dependee_regexp:
+ self._general_rules = rules_to_update
+ else:
+ self._specific_rules[dependee_regexp] = rules_to_update
+
+ def RuleApplyingTo(self, include_path, dependee_path):
+ """Returns the rule that applies to |include_path| for a dependee
+ file located at |dependee_path|.
+ """
+ dependee_filename = os.path.basename(dependee_path)
+ for regexp, specific_rules in self._specific_rules.iteritems():
+ if re.match(regexp, dependee_filename):
+ for rule in specific_rules:
+ if rule.ChildOrMatch(include_path):
+ return rule
+ for rule in self._general_rules:
+ if rule.ChildOrMatch(include_path):
+ return rule
+ return MessageRule('no rule applying.')
diff --git a/chromium/tools/checkdeps/testdata/DEPS b/chromium/tools/checkdeps/testdata/DEPS
new file mode 100644
index 00000000000..f0657f5bc3d
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/DEPS
@@ -0,0 +1,8 @@
+include_rules = [
+ "-tools/checkdeps/testdata/disallowed",
+ "+tools/checkdeps/testdata/allowed",
+ "-third_party/explicitly_disallowed",
+]
+skip_child_includes = [
+ "checkdeps_test",
+]
diff --git a/chromium/tools/checkdeps/testdata/allowed/DEPS b/chromium/tools/checkdeps/testdata/allowed/DEPS
new file mode 100644
index 00000000000..8fb09053c19
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/allowed/DEPS
@@ -0,0 +1,12 @@
+include_rules = [
+ "+tools/checkdeps/testdata/disallowed/allowed",
+ "!tools/checkdeps/testdata/disallowed/temporarily_allowed.h",
+ "+third_party/allowed_may_use",
+]
+
+specific_include_rules = {
+ ".*_unittest\.cc": [
+ "+tools/checkdeps/testdata/disallowed/teststuff",
+ "!tools/checkdeps/testdata/bongo/temp_allowed_for_tests.h",
+ ]
+}
diff --git a/chromium/tools/checkdeps/testdata/allowed/foo_unittest.cc b/chromium/tools/checkdeps/testdata/allowed/foo_unittest.cc
new file mode 100644
index 00000000000..754f295eb50
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/allowed/foo_unittest.cc
@@ -0,0 +1,5 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/checkdeps/testdata/disallowed/teststuff/good.h"
diff --git a/chromium/tools/checkdeps/testdata/allowed/not_a_test.cc b/chromium/tools/checkdeps/testdata/allowed/not_a_test.cc
new file mode 100644
index 00000000000..7b2a105d53f
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/allowed/not_a_test.cc
@@ -0,0 +1,5 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/checkdeps/testdata/disallowed/teststuff/bad.h"
diff --git a/chromium/tools/checkdeps/testdata/allowed/test.h b/chromium/tools/checkdeps/testdata/allowed/test.h
new file mode 100644
index 00000000000..ea330900509
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/allowed/test.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/checkdeps/testdata/allowed/good.h"
+#include "tools/checkdeps/testdata/disallowed/bad.h"
+#include "tools/checkdeps/testdata/disallowed/allowed/good.h"
+#include "tools/checkdeps/testdata/disallowed/temporarily_allowed.h"
+#include "third_party/explicitly_disallowed/bad.h"
+#include "third_party/allowed_may_use/good.h"
+#include "third_party/no_rule/bad.h"
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/DEPS b/chromium/tools/checkdeps/testdata/checkdeps_test/DEPS
new file mode 100644
index 00000000000..91a9b990c32
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "-disallowed",
+ "+allowed",
+ "-third_party/explicitly_disallowed",
+]
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/DEPS b/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/DEPS
new file mode 100644
index 00000000000..14aa4d4516d
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/DEPS
@@ -0,0 +1,11 @@
+include_rules = [
+ "+disallowed/allowed",
+ "!disallowed/temporarily_allowed.h",
+ "+third_party/allowed_may_use",
+]
+
+specific_include_rules = {
+ ".*_unittest\.cc": [
+ "+disallowed/teststuff",
+ ]
+}
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/foo_unittest.cc b/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/foo_unittest.cc
new file mode 100644
index 00000000000..1a507eca4ec
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/foo_unittest.cc
@@ -0,0 +1,5 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "disallowed/teststuff/good.h"
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/not_a_test.cc b/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/not_a_test.cc
new file mode 100644
index 00000000000..4278d647634
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/not_a_test.cc
@@ -0,0 +1,5 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "disallowed/teststuff/bad.h"
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/test.h b/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/test.h
new file mode 100644
index 00000000000..2dbd7a38b49
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/allowed/test.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "allowed/good.h"
+#include "disallowed/bad.h"
+#include "disallowed/allowed/good.h"
+#include "disallowed/temporarily_allowed.h"
+#include "third_party/explicitly_disallowed/bad.h"
+#include "third_party/allowed_may_use/good.h"
+#include "third_party/no_rule/bad.h"
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/DEPS b/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/DEPS
new file mode 100644
index 00000000000..2be72b80188
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/DEPS
@@ -0,0 +1,3 @@
+skip_child_includes = [
+ "skipped",
+]
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/skipped/test.h b/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/skipped/test.h
new file mode 100644
index 00000000000..80105968e2d
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/skipped/test.h
@@ -0,0 +1,5 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "whatever/whocares/ok.h"
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/test.h b/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/test.h
new file mode 100644
index 00000000000..aa5013d25d0
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/allowed/test.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "allowed/good.h"
+// Always allowed to include self and parents.
+#include "disallowed/good.h"
+#include "disallowed/allowed/good.h"
+#include "third_party/explicitly_disallowed/bad.h"
+#include "third_party/allowed_may_use/bad.h"
+#include "third_party/no_rule/bad.h"
diff --git a/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/test.h b/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/test.h
new file mode 100644
index 00000000000..5520a68c8f5
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/checkdeps_test/disallowed/test.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "allowed/good.h"
+// Always allowed to include self.
+#include "disallowed/good.h"
+#include "disallowed/allowed/good.h"
+#include "third_party/explicitly_disallowed/bad.h"
+// Only allowed for code under allowed/.
+#include "third_party/allowed_may_use/bad.h"
+#include "third_party/no_rule/bad.h"
diff --git a/chromium/tools/checkdeps/testdata/disallowed/allowed/DEPS b/chromium/tools/checkdeps/testdata/disallowed/allowed/DEPS
new file mode 100644
index 00000000000..2be72b80188
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/disallowed/allowed/DEPS
@@ -0,0 +1,3 @@
+skip_child_includes = [
+ "skipped",
+]
diff --git a/chromium/tools/checkdeps/testdata/disallowed/allowed/skipped/test.h b/chromium/tools/checkdeps/testdata/disallowed/allowed/skipped/test.h
new file mode 100644
index 00000000000..80105968e2d
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/disallowed/allowed/skipped/test.h
@@ -0,0 +1,5 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "whatever/whocares/ok.h"
diff --git a/chromium/tools/checkdeps/testdata/disallowed/allowed/test.h b/chromium/tools/checkdeps/testdata/disallowed/allowed/test.h
new file mode 100644
index 00000000000..f7dc822c4ba
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/disallowed/allowed/test.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/checkdeps/testdata/allowed/good.h"
+// Always allowed to include self and parents.
+#include "tools/checkdeps/testdata/disallowed/good.h"
+#include "tools/checkdeps/testdata/disallowed/allowed/good.h"
+#include "third_party/explicitly_disallowed/bad.h"
+#include "third_party/allowed_may_use/bad.h"
+#include "third_party/no_rule/bad.h"
diff --git a/chromium/tools/checkdeps/testdata/disallowed/foo_unittest.cc b/chromium/tools/checkdeps/testdata/disallowed/foo_unittest.cc
new file mode 100644
index 00000000000..144c05eb368
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/disallowed/foo_unittest.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Not allowed for code under disallowed/ but temporarily allowed
+// specifically for test code under allowed/. This regression tests a
+// bug where we were taking shallow copies of rules when generating
+// rules for subdirectories, so all rule objects were getting the same
+// dictionary for specific rules.
+#include "tools/checkdeps/testdata/disallowed/temp_allowed_for_tests.h"
diff --git a/chromium/tools/checkdeps/testdata/disallowed/test.h b/chromium/tools/checkdeps/testdata/disallowed/test.h
new file mode 100644
index 00000000000..d0128e3a964
--- /dev/null
+++ b/chromium/tools/checkdeps/testdata/disallowed/test.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/checkdeps/testdata/allowed/good.h"
+// Always allowed to include self.
+#include "tools/checkdeps/testdata/disallowed/good.h"
+#include "tools/checkdeps/testdata/disallowed/allowed/good.h"
+#include "third_party/explicitly_disallowed/bad.h"
+// Only allowed for code under allowed/.
+#include "third_party/allowed_may_use/bad.h"
+#include "third_party/no_rule/bad.h"
diff --git a/chromium/tools/checklicenses/OWNERS b/chromium/tools/checklicenses/OWNERS
new file mode 100644
index 00000000000..2abfa66e8a9
--- /dev/null
+++ b/chromium/tools/checklicenses/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+phajdan.jr@chromium.org
+thestig@chromium.org
diff --git a/chromium/tools/checklicenses/checklicenses.py b/chromium/tools/checklicenses/checklicenses.py
new file mode 100755
index 00000000000..25dedc29749
--- /dev/null
+++ b/chromium/tools/checklicenses/checklicenses.py
@@ -0,0 +1,548 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Makes sure that all files contain proper licensing information."""
+
+
+import optparse
+import os.path
+import subprocess
+import sys
+
+
+def PrintUsage():
+ print """Usage: python checklicenses.py [--root <root>] [tocheck]
+ --root Specifies the repository root. This defaults to "../.." relative
+ to the script file. This will be correct given the normal location
+ of the script in "<root>/tools/checklicenses".
+
+ --ignore-suppressions Ignores path-specific license whitelist. Useful when
+ trying to remove a suppression/whitelist entry.
+
+ tocheck Specifies the directory, relative to root, to check. This defaults
+ to "." so it checks everything.
+
+Examples:
+ python checklicenses.py
+ python checklicenses.py --root ~/chromium/src third_party"""
+
+
+WHITELISTED_LICENSES = [
+ 'Apache (v2.0)',
+ 'Apache (v2.0) BSD (2 clause)',
+ 'Apache (v2.0) GPL (v2)',
+ 'Apple MIT', # https://fedoraproject.org/wiki/Licensing/Apple_MIT_License
+ 'APSL (v2)',
+ 'APSL (v2) BSD (4 clause)',
+ 'BSD',
+ 'BSD (2 clause)',
+ 'BSD (2 clause) ISC',
+ 'BSD (2 clause) MIT/X11 (BSD like)',
+ 'BSD (3 clause)',
+ 'BSD (3 clause) GPL (v2)',
+ 'BSD (3 clause) ISC',
+ 'BSD (3 clause) LGPL (v2 or later)',
+ 'BSD (3 clause) LGPL (v2.1 or later)',
+ 'BSD (3 clause) MIT/X11 (BSD like)',
+ 'BSD (4 clause)',
+ 'BSD-like',
+
+ # TODO(phajdan.jr): Make licensecheck not print BSD-like twice.
+ 'BSD-like MIT/X11 (BSD like)',
+
+ 'BSL (v1.0)',
+ 'GPL (v2) LGPL (v2.1 or later)',
+ 'GPL (v2 or later) with Bison parser exception',
+ 'GPL (v2 or later) with libtool exception',
+ 'GPL (v3 or later) with Bison parser exception',
+ 'GPL with Bison parser exception',
+ 'ISC',
+ 'LGPL (unversioned/unknown version)',
+ 'LGPL (v2)',
+ 'LGPL (v2 or later)',
+ 'LGPL (v2.1)',
+ 'LGPL (v2.1 or later)',
+ 'LGPL (v3 or later)',
+ 'MIT/X11 (BSD like)',
+ 'MPL (v1.0) LGPL (v2 or later)',
+ 'MPL (v1.1)',
+ 'MPL (v1.1) BSD (3 clause) GPL (v2) LGPL (v2.1 or later)',
+ 'MPL (v1.1) BSD (3 clause) LGPL (v2.1 or later)',
+ 'MPL (v1.1) BSD-like',
+ 'MPL (v1.1) BSD-like GPL (unversioned/unknown version)',
+ 'MPL (v1.1) BSD-like GPL (v2) LGPL (v2.1 or later)',
+ 'MPL (v1.1) GPL (v2)',
+ 'MPL (v1.1) GPL (v2) LGPL (v2 or later)',
+ 'MPL (v1.1) GPL (v2) LGPL (v2.1 or later)',
+ 'MPL (v1.1) GPL (unversioned/unknown version)',
+ 'MPL (v1.1) LGPL (v2 or later)',
+ 'MPL (v1.1) LGPL (v2.1 or later)',
+ 'MPL (v2.0)',
+ 'Ms-PL',
+ 'Public domain',
+ 'Public domain BSD',
+ 'Public domain BSD (3 clause)',
+ 'Public domain BSD-like',
+ 'Public domain LGPL (v2.1 or later)',
+ 'libpng',
+ 'zlib/libpng',
+ 'SGI Free Software License B',
+ 'University of Illinois/NCSA Open Source License (BSD like)',
+]
+
+
+PATH_SPECIFIC_WHITELISTED_LICENSES = {
+ 'base/hash.cc': [ # http://crbug.com/98100
+ 'UNKNOWN',
+ ],
+ 'base/third_party/icu': [ # http://crbug.com/98087
+ 'UNKNOWN',
+ ],
+
+ # http://code.google.com/p/google-breakpad/issues/detail?id=450
+ 'breakpad/src': [
+ 'UNKNOWN',
+ ],
+
+ 'chrome/common/extensions/docs/examples': [ # http://crbug.com/98092
+ 'UNKNOWN',
+ ],
+ 'chrome/test/data/gpu/vt': [
+ 'UNKNOWN',
+ ],
+ 'chrome/test/data/layout_tests/LayoutTests': [
+ 'UNKNOWN',
+ ],
+ 'courgette/third_party/bsdiff_create.cc': [ # http://crbug.com/98095
+ 'UNKNOWN',
+ ],
+ 'data/mozilla_js_tests': [
+ 'UNKNOWN',
+ ],
+ 'data/page_cycler': [
+ 'UNKNOWN',
+ 'GPL (v2 or later)',
+ ],
+ 'data/tab_switching': [
+ 'UNKNOWN',
+ ],
+ 'native_client': [ # http://crbug.com/98099
+ 'UNKNOWN',
+ ],
+ 'native_client/toolchain': [
+ 'BSD GPL (v2 or later)',
+ 'BSD (2 clause) GPL (v2 or later)',
+ 'BSD (3 clause) GPL (v2 or later)',
+ 'BSL (v1.0) GPL',
+ 'BSL (v1.0) GPL (v3.1)',
+ 'GPL',
+ 'GPL (unversioned/unknown version)',
+ 'GPL (v2)',
+ 'GPL (v2 or later)',
+ 'GPL (v3.1)',
+ 'GPL (v3 or later)',
+ ],
+ 'net/tools/spdyshark': [
+ 'GPL (v2 or later)',
+ 'UNKNOWN',
+ ],
+ 'third_party/WebKit': [
+ 'UNKNOWN',
+ ],
+ 'third_party/WebKit/Websites/webkit.org/blog/wp-content/plugins/'
+ 'akismet/akismet.php': [
+ 'GPL (v2 or later)'
+ ],
+ 'third_party/WebKit/Source/JavaScriptCore/tests/mozilla': [
+ 'GPL',
+ 'GPL (v2 or later)',
+ 'GPL (unversioned/unknown version)',
+ ],
+ 'third_party/active_doc': [ # http://crbug.com/98113
+ 'UNKNOWN',
+ ],
+
+ # http://code.google.com/p/angleproject/issues/detail?id=217
+ 'third_party/angle': [
+ 'UNKNOWN',
+ ],
+
+ 'third_party/bsdiff/mbsdiff.cc': [
+ 'UNKNOWN',
+ ],
+ 'third_party/bzip2': [
+ 'UNKNOWN',
+ ],
+
+ # http://crbug.com/222828
+ # http://bugs.python.org/issue17514
+ 'third_party/chromite/third_party/argparse.py': [
+ 'UNKNOWN',
+ ],
+
+ # Not used. http://crbug.com/156020
+ # Using third_party/cros_dbus_cplusplus/cros_dbus_cplusplus.gyp instead.
+ 'third_party/cros_dbus_cplusplus/source/autogen.sh': [
+ 'UNKNOWN',
+ ],
+ # Included in the source tree but not built. http://crbug.com/156020
+ 'third_party/cros_dbus_cplusplus/source/examples': [
+ 'UNKNOWN',
+ ],
+ 'third_party/devscripts': [
+ 'GPL (v2 or later)',
+ ],
+ 'third_party/expat/files/lib': [ # http://crbug.com/98121
+ 'UNKNOWN',
+ ],
+ 'third_party/ffmpeg': [
+ 'GPL',
+ 'GPL (v2)',
+ 'GPL (v2 or later)',
+ 'UNKNOWN', # http://crbug.com/98123
+ ],
+ 'third_party/findbugs/doc': [ # http://crbug.com/157206
+ 'UNKNOWN',
+ ],
+ 'third_party/freetype2': [ # http://crbug.com/177319
+ 'UNKNOWN',
+ ],
+ 'third_party/gles2_book': [ # http://crbug.com/98130
+ 'UNKNOWN',
+ ],
+ 'third_party/gles2_conform/GTF_ES': [ # http://crbug.com/98131
+ 'UNKNOWN',
+ ],
+ 'third_party/harfbuzz': [ # http://crbug.com/98133
+ 'UNKNOWN',
+ ],
+ 'third_party/hunspell': [ # http://crbug.com/98134
+ 'UNKNOWN',
+ ],
+ 'third_party/hyphen/hyphen.tex': [ # http://crbug.com/157375
+ 'UNKNOWN',
+ ],
+ 'third_party/iccjpeg': [ # http://crbug.com/98137
+ 'UNKNOWN',
+ ],
+ 'third_party/icu': [ # http://crbug.com/98301
+ 'UNKNOWN',
+ ],
+ 'third_party/jemalloc': [ # http://crbug.com/98302
+ 'UNKNOWN',
+ ],
+ 'third_party/JSON': [
+ 'Perl', # Build-only.
+ # License missing upstream on 3 minor files.
+ 'UNKNOWN', # https://rt.cpan.org/Public/Bug/Display.html?id=85915
+ ],
+ 'third_party/lcov': [ # http://crbug.com/98304
+ 'UNKNOWN',
+ ],
+ 'third_party/lcov/contrib/galaxy/genflat.pl': [
+ 'GPL (v2 or later)',
+ ],
+ 'third_party/lcov-1.9/contrib/galaxy/genflat.pl': [
+ 'GPL (v2 or later)',
+ ],
+ 'third_party/libevent': [ # http://crbug.com/98309
+ 'UNKNOWN',
+ ],
+ 'third_party/libjingle/source/talk': [ # http://crbug.com/98310
+ 'UNKNOWN',
+ ],
+ 'third_party/libjingle/source_internal/talk': [ # http://crbug.com/98310
+ 'UNKNOWN',
+ ],
+ 'third_party/libjpeg': [ # http://crbug.com/98313
+ 'UNKNOWN',
+ ],
+ 'third_party/libjpeg_turbo': [ # http://crbug.com/98314
+ 'UNKNOWN',
+ ],
+ 'third_party/libpng': [ # http://crbug.com/98318
+ 'UNKNOWN',
+ ],
+
+ # The following files lack license headers, but are trivial.
+ 'third_party/libusb/src/libusb/os/poll_posix.h': [
+ 'UNKNOWN',
+ ],
+ 'third_party/libusb/src/libusb/version.h': [
+ 'UNKNOWN',
+ ],
+ 'third_party/libusb/src/autogen.sh': [
+ 'UNKNOWN',
+ ],
+ 'third_party/libusb/src/config.h': [
+ 'UNKNOWN',
+ ],
+ 'third_party/libusb/src/msvc/config.h': [
+ 'UNKNOWN',
+ ],
+
+ 'third_party/libvpx/source': [ # http://crbug.com/98319
+ 'UNKNOWN',
+ ],
+ 'third_party/libvpx/source/libvpx/examples/includes': [
+ 'GPL (v2 or later)',
+ ],
+ 'third_party/libxml': [
+ 'UNKNOWN',
+ ],
+ 'third_party/libxslt': [
+ 'UNKNOWN',
+ ],
+ 'third_party/lzma_sdk': [
+ 'UNKNOWN',
+ ],
+ 'third_party/mesa/src': [
+ 'GPL (v2)',
+ 'GPL (v3 or later)',
+ 'MIT/X11 (BSD like) GPL (v3 or later) with Bison parser exception',
+ 'UNKNOWN', # http://crbug.com/98450
+ ],
+ 'third_party/modp_b64': [
+ 'UNKNOWN',
+ ],
+ 'third_party/npapi/npspy/extern/java': [
+ 'GPL (unversioned/unknown version)',
+ ],
+ 'third_party/openmax_dl/dl' : [
+ 'Khronos Group',
+ ],
+ 'third_party/openssl': [ # http://crbug.com/98451
+ 'UNKNOWN',
+ ],
+ 'third_party/ots/tools/ttf-checksum.py': [ # http://code.google.com/p/ots/issues/detail?id=2
+ 'UNKNOWN',
+ ],
+ 'third_party/molokocacao': [ # http://crbug.com/98453
+ 'UNKNOWN',
+ ],
+ 'third_party/npapi/npspy': [
+ 'UNKNOWN',
+ ],
+ 'third_party/ocmock/OCMock': [ # http://crbug.com/98454
+ 'UNKNOWN',
+ ],
+ 'third_party/ply/__init__.py': [
+ 'UNKNOWN',
+ ],
+ 'third_party/protobuf': [ # http://crbug.com/98455
+ 'UNKNOWN',
+ ],
+
+ # http://crbug.com/222831
+ # https://bitbucket.org/eliben/pyelftools/issue/12
+ 'third_party/pyelftools': [
+ 'UNKNOWN',
+ ],
+
+ 'third_party/pylib': [
+ 'UNKNOWN',
+ ],
+ 'third_party/scons-2.0.1/engine/SCons': [ # http://crbug.com/98462
+ 'UNKNOWN',
+ ],
+ 'third_party/simplejson': [
+ 'UNKNOWN',
+ ],
+ 'third_party/skia': [ # http://crbug.com/98463
+ 'UNKNOWN',
+ ],
+ 'third_party/snappy/src': [ # http://crbug.com/98464
+ 'UNKNOWN',
+ ],
+ 'third_party/smhasher/src': [ # http://crbug.com/98465
+ 'UNKNOWN',
+ ],
+ 'third_party/speech-dispatcher/libspeechd.h': [
+ 'GPL (v2 or later)',
+ ],
+ 'third_party/sqlite': [
+ 'UNKNOWN',
+ ],
+ 'third_party/swig/Lib/linkruntime.c': [ # http://crbug.com/98585
+ 'UNKNOWN',
+ ],
+ 'third_party/talloc': [
+ 'GPL (v3 or later)',
+ 'UNKNOWN', # http://crbug.com/98588
+ ],
+ 'third_party/tcmalloc': [
+ 'UNKNOWN', # http://crbug.com/98589
+ ],
+ 'third_party/tlslite': [
+ 'UNKNOWN',
+ ],
+ 'third_party/webdriver': [ # http://crbug.com/98590
+ 'UNKNOWN',
+ ],
+ 'third_party/webrtc': [ # http://crbug.com/98592
+ 'UNKNOWN',
+ ],
+ 'third_party/xdg-utils': [ # http://crbug.com/98593
+ 'UNKNOWN',
+ ],
+ 'third_party/yasm/source': [ # http://crbug.com/98594
+ 'UNKNOWN',
+ ],
+ 'third_party/zlib/contrib/minizip': [
+ 'UNKNOWN',
+ ],
+ 'third_party/zlib/trees.h': [
+ 'UNKNOWN',
+ ],
+ 'tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py': [
+ 'UNKNOWN',
+ ],
+ 'tools/emacs': [ # http://crbug.com/98595
+ 'UNKNOWN',
+ ],
+ 'tools/grit/grit/node/custom/__init__.py': [
+ 'UNKNOWN',
+ ],
+ 'tools/gyp/test': [
+ 'UNKNOWN',
+ ],
+ 'tools/histograms': [
+ 'UNKNOWN',
+ ],
+ 'tools/memory_watcher': [
+ 'UNKNOWN',
+ ],
+ 'tools/playback_benchmark': [
+ 'UNKNOWN',
+ ],
+ 'tools/python/google/__init__.py': [
+ 'UNKNOWN',
+ ],
+ 'tools/site_compare': [
+ 'UNKNOWN',
+ ],
+ 'tools/stats_viewer/Properties/AssemblyInfo.cs': [
+ 'UNKNOWN',
+ ],
+ 'tools/symsrc/pefile.py': [
+ 'UNKNOWN',
+ ],
+ 'v8/test/cctest': [ # http://crbug.com/98597
+ 'UNKNOWN',
+ ],
+ 'webkit/data/ico_decoder': [
+ 'UNKNOWN',
+ ],
+}
+
+
+def check_licenses(options, args):
+ # Figure out which directory we have to check.
+ if len(args) == 0:
+ # No directory to check specified, use the repository root.
+ start_dir = options.base_directory
+ elif len(args) == 1:
+ # Directory specified. Start here. It's supposed to be relative to the
+ # base directory.
+ start_dir = os.path.abspath(os.path.join(options.base_directory, args[0]))
+ else:
+ # More than one argument, we don't handle this.
+ PrintUsage()
+ return 1
+
+ print "Using base directory:", options.base_directory
+ print "Checking:", start_dir
+ print
+
+ licensecheck_path = os.path.abspath(os.path.join(options.base_directory,
+ 'third_party',
+ 'devscripts',
+ 'licensecheck.pl'))
+
+ licensecheck = subprocess.Popen([licensecheck_path,
+ '-l', '100',
+ '-r', start_dir],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = licensecheck.communicate()
+ if options.verbose:
+ print '----------- licensecheck stdout -----------'
+ print stdout
+ print '--------- end licensecheck stdout ---------'
+ if licensecheck.returncode != 0 or stderr:
+ print '----------- licensecheck stderr -----------'
+ print stderr
+ print '--------- end licensecheck stderr ---------'
+ print "\nFAILED\n"
+ return 1
+
+ success = True
+ for line in stdout.splitlines():
+ filename, license = line.split(':', 1)
+ filename = os.path.relpath(filename.strip(), options.base_directory)
+
+ # All files in the build output directory are generated one way or another.
+ # There's no need to check them.
+ if filename.startswith('out/') or filename.startswith('sconsbuild/'):
+ continue
+
+ # For now we're just interested in the license.
+ license = license.replace('*No copyright*', '').strip()
+
+ # Skip generated files.
+ if 'GENERATED FILE' in license:
+ continue
+
+ if license in WHITELISTED_LICENSES:
+ continue
+
+ if not options.ignore_suppressions:
+ found_path_specific = False
+ for prefix in PATH_SPECIFIC_WHITELISTED_LICENSES:
+ if (filename.startswith(prefix) and
+ license in PATH_SPECIFIC_WHITELISTED_LICENSES[prefix]):
+ found_path_specific = True
+ break
+ if found_path_specific:
+ continue
+
+ print "'%s' has non-whitelisted license '%s'" % (filename, license)
+ success = False
+
+ if success:
+ print "\nSUCCESS\n"
+ return 0
+ else:
+ print "\nFAILED\n"
+ print "Please read",
+ print "http://www.chromium.org/developers/adding-3rd-party-libraries"
+ print "for more info how to handle the failure."
+ print
+ print "Please respect OWNERS of checklicenses.py. Changes violating"
+ print "this requirement may be reverted."
+ return 1
+
+
+def main():
+ default_root = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..', '..'))
+ option_parser = optparse.OptionParser()
+ option_parser.add_option('--root', default=default_root,
+ dest='base_directory',
+ help='Specifies the repository root. This defaults '
+ 'to "../.." relative to the script file, which '
+ 'will normally be the repository root.')
+ option_parser.add_option('-v', '--verbose', action='store_true',
+ default=False, help='Print debug logging')
+ option_parser.add_option('--ignore-suppressions',
+ action='store_true',
+ default=False,
+ help='Ignore path-specific license whitelist.')
+ options, args = option_parser.parse_args()
+ return check_licenses(options, args)
+
+
+if '__main__' == __name__:
+ sys.exit(main())
diff --git a/chromium/tools/checkperms/OWNERS b/chromium/tools/checkperms/OWNERS
new file mode 100644
index 00000000000..1967bf567e8
--- /dev/null
+++ b/chromium/tools/checkperms/OWNERS
@@ -0,0 +1 @@
+thestig@chromium.org
diff --git a/chromium/tools/checkperms/PRESUBMIT.py b/chromium/tools/checkperms/PRESUBMIT.py
new file mode 100644
index 00000000000..c2f93567da3
--- /dev/null
+++ b/chromium/tools/checkperms/PRESUBMIT.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for checkperms.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+
+def CommonChecks(input_api, output_api):
+ output = []
+ output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+ # Run it like if it were a unit test.
+ output.extend(
+ input_api.canned_checks.RunUnitTests(
+ input_api, output_api, ['./checkperms.py']))
+ return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/chromium/tools/checkperms/checkperms.py b/chromium/tools/checkperms/checkperms.py
new file mode 100755
index 00000000000..f07103e3797
--- /dev/null
+++ b/chromium/tools/checkperms/checkperms.py
@@ -0,0 +1,508 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Makes sure files have the right permissions.
+
+Some developers have broken SCM configurations that flip the svn:executable
+permission on for no good reason. Unix developers who run ls --color will then
+see .cc files in green and get confused.
+
+- For file extensions that must be executable, add it to EXECUTABLE_EXTENSIONS.
+- For file extensions that must not be executable, add it to
+ NOT_EXECUTABLE_EXTENSIONS.
+- To ignore all the files inside a directory, add it to IGNORED_PATHS.
+- For file base name with ambiguous state and that should not be checked for
+ shebang, add it to IGNORED_FILENAMES.
+
+Any file not matching the above will be opened and looked if it has a shebang.
+It this doesn't match the executable bit on the file, the file will be flagged.
+
+Note that all directory separators must be slashes (Unix-style) and not
+backslashes. All directories should be relative to the source root and all
+file paths should be only lowercase.
+"""
+
+import logging
+import optparse
+import os
+import stat
+import subprocess
+import sys
+
+#### USER EDITABLE SECTION STARTS HERE ####
+
+# Files with these extensions must have executable bit set.
+EXECUTABLE_EXTENSIONS = (
+ 'bat',
+ 'dll',
+ 'dylib',
+ 'exe',
+)
+
+# These files must have executable bit set.
+EXECUTABLE_PATHS = (
+ # TODO(maruel): Detect ELF files.
+ 'chrome/installer/mac/sign_app.sh.in',
+ 'chrome/installer/mac/sign_versioned_dir.sh.in',
+)
+
+# These files must not have the executable bit set. This is mainly a performance
+# optimization as these files are not checked for shebang. The list was
+# partially generated from:
+# git ls-files | grep "\\." | sed 's/.*\.//' | sort | uniq -c | sort -b -g
+NON_EXECUTABLE_EXTENSIONS = (
+ '1',
+ '3ds',
+ 'S',
+ 'am',
+ 'applescript',
+ 'asm',
+ 'c',
+ 'cc',
+ 'cfg',
+ 'chromium',
+ 'cpp',
+ 'crx',
+ 'cs',
+ 'css',
+ 'cur',
+ 'def',
+ 'der',
+ 'expected',
+ 'gif',
+ 'grd',
+ 'gyp',
+ 'gypi',
+ 'h',
+ 'hh',
+ 'htm',
+ 'html',
+ 'hyph',
+ 'ico',
+ 'idl',
+ 'java',
+ 'jpg',
+ 'js',
+ 'json',
+ 'm',
+ 'm4',
+ 'mm',
+ 'mms',
+ 'mock-http-headers',
+ 'nmf',
+ 'onc',
+ 'pat',
+ 'patch',
+ 'pdf',
+ 'pem',
+ 'plist',
+ 'png',
+ 'proto',
+ 'rc',
+ 'rfx',
+ 'rgs',
+ 'rules',
+ 'spec',
+ 'sql',
+ 'srpc',
+ 'svg',
+ 'tcl',
+ 'test',
+ 'tga',
+ 'txt',
+ 'vcproj',
+ 'vsprops',
+ 'webm',
+ 'word',
+ 'xib',
+ 'xml',
+ 'xtb',
+ 'zip',
+)
+
+# File names that are always whitelisted. (These are all autoconf spew.)
+IGNORED_FILENAMES = (
+ 'config.guess',
+ 'config.sub',
+ 'configure',
+ 'depcomp',
+ 'install-sh',
+ 'missing',
+ 'mkinstalldirs',
+ 'naclsdk',
+ 'scons',
+)
+
+# File paths starting with one of these will be ignored as well.
+# Please consider fixing your file permissions, rather than adding to this list.
+IGNORED_PATHS = (
+ # TODO(maruel): Detect ELF files.
+ 'chrome/test/data/extensions/uitest/plugins/plugin.plugin/contents/'
+ 'macos/testnetscapeplugin',
+ 'chrome/test/data/extensions/uitest/plugins_private/plugin.plugin/contents/'
+ 'macos/testnetscapeplugin',
+ 'chrome/installer/mac/sign_app.sh.in',
+ 'chrome/installer/mac/sign_versioned_dir.sh.in',
+ 'native_client_sdk/src/build_tools/sdk_tools/third_party/',
+ 'out/',
+ # TODO(maruel): Fix these.
+ 'third_party/android_testrunner/',
+ 'third_party/bintrees/',
+ 'third_party/closure_linter/',
+ 'third_party/devscripts/licensecheck.pl.vanilla',
+ 'third_party/hyphen/',
+ 'third_party/jemalloc/',
+ 'third_party/lcov-1.9/contrib/galaxy/conglomerate_functions.pl',
+ 'third_party/lcov-1.9/contrib/galaxy/gen_makefile.sh',
+ 'third_party/lcov/contrib/galaxy/conglomerate_functions.pl',
+ 'third_party/lcov/contrib/galaxy/gen_makefile.sh',
+ 'third_party/libevent/autogen.sh',
+ 'third_party/libevent/test/test.sh',
+ 'third_party/libxml/linux/xml2-config',
+ 'third_party/libxml/src/ltmain.sh',
+ 'third_party/mesa/',
+ 'third_party/protobuf/',
+ 'third_party/python_gflags/gflags.py',
+ 'third_party/sqlite/',
+ 'third_party/talloc/script/mksyms.sh',
+ 'third_party/tcmalloc/',
+ 'third_party/tlslite/setup.py',
+)
+
+#### USER EDITABLE SECTION ENDS HERE ####
+
+assert set(EXECUTABLE_EXTENSIONS) & set(NON_EXECUTABLE_EXTENSIONS) == set()
+
+
+def capture(cmd, cwd):
+ """Returns the output of a command.
+
+ Ignores the error code or stderr.
+ """
+ logging.debug('%s; cwd=%s' % (' '.join(cmd), cwd))
+ env = os.environ.copy()
+ env['LANGUAGE'] = 'en_US.UTF-8'
+ p = subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd, env=env)
+ return p.communicate()[0]
+
+
+def get_svn_info(dir_path):
+ """Returns svn meta-data for a svn checkout."""
+ if not os.path.isdir(dir_path):
+ return {}
+ out = capture(['svn', 'info', '.', '--non-interactive'], dir_path)
+ return dict(l.split(': ', 1) for l in out.splitlines() if l)
+
+
+def get_svn_url(dir_path):
+ return get_svn_info(dir_path).get('URL')
+
+
+def get_svn_root(dir_path):
+ """Returns the svn checkout root or None."""
+ svn_url = get_svn_url(dir_path)
+ if not svn_url:
+ return None
+ logging.info('svn url: %s' % svn_url)
+ while True:
+ parent = os.path.dirname(dir_path)
+ if parent == dir_path:
+ return None
+ svn_url = svn_url.rsplit('/', 1)[0]
+ if svn_url != get_svn_url(parent):
+ return dir_path
+ dir_path = parent
+
+
+def get_git_root(dir_path):
+ """Returns the git checkout root or None."""
+ root = capture(['git', 'rev-parse', '--show-toplevel'], dir_path).strip()
+ if root:
+ return root
+
+
+def is_ignored(rel_path):
+ """Returns True if rel_path is in our whitelist of files to ignore."""
+ rel_path = rel_path.lower()
+ return (
+ os.path.basename(rel_path) in IGNORED_FILENAMES or
+ rel_path.startswith(IGNORED_PATHS))
+
+
+def must_be_executable(rel_path):
+ """The file name represents a file type that must have the executable bit
+ set.
+ """
+ return (
+ os.path.splitext(rel_path)[1][1:].lower() in EXECUTABLE_EXTENSIONS or
+ rel_path in EXECUTABLE_PATHS)
+
+
+def must_not_be_executable(rel_path):
+ """The file name represents a file type that must not have the executable
+ bit set.
+ """
+ return os.path.splitext(rel_path)[1][1:].lower() in NON_EXECUTABLE_EXTENSIONS
+
+
+def has_executable_bit(full_path):
+ """Returns if any executable bit is set."""
+ permission = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
+ return bool(permission & os.stat(full_path).st_mode)
+
+
+def has_shebang(full_path):
+ """Returns if the file starts with #!/.
+
+ file_path is the absolute path to the file.
+ """
+ with open(full_path, 'rb') as f:
+ return f.read(3) == '#!/'
+
+def check_file(full_path, bare_output):
+ """Checks file_path's permissions and returns an error if it is
+ inconsistent.
+
+ It is assumed that the file is not ignored by is_ignored().
+
+ If the file name is matched with must_be_executable() or
+ must_not_be_executable(), only its executable bit is checked.
+ Otherwise, the 3 first bytes of the file are read to verify if it has a
+ shebang and compares this with the executable bit on the file.
+ """
+ try:
+ bit = has_executable_bit(full_path)
+ except OSError:
+ # It's faster to catch exception than call os.path.islink(). Chromium
+ # tree happens to have invalid symlinks under
+ # third_party/openssl/openssl/test/.
+ return None
+
+ if must_be_executable(full_path):
+ if not bit:
+ if bare_output:
+ return full_path
+ return '%s: Must have executable bit set' % full_path
+ return
+ if must_not_be_executable(full_path):
+ if bit:
+ if bare_output:
+ return full_path
+ return '%s: Must not have executable bit set' % full_path
+ return
+
+ # For the others, it depends on the shebang.
+ shebang = has_shebang(full_path)
+ if bit != shebang:
+ if bare_output:
+ return full_path
+ if bit:
+ return '%s: Has executable bit but not shebang' % full_path
+ else:
+ return '%s: Has shebang but not executable bit' % full_path
+
+
+def check_files(root, files, bare_output):
+ errors = []
+ for file_path in files:
+ if is_ignored(file_path):
+ continue
+
+ full_file_path = os.path.join(root, file_path)
+
+ error = check_file(full_file_path, bare_output)
+ if error:
+ errors.append(error)
+
+ return errors
+
+class ApiBase(object):
+ def __init__(self, root_dir, bare_output):
+ self.root_dir = root_dir
+ self.bare_output = bare_output
+ self.count = 0
+ self.count_shebang = 0
+
+ def check_file(self, rel_path):
+ logging.debug('check_file(%s)' % rel_path)
+ self.count += 1
+
+ if (not must_be_executable(rel_path) and
+ not must_not_be_executable(rel_path)):
+ self.count_shebang += 1
+
+ full_path = os.path.join(self.root_dir, rel_path)
+ return check_file(full_path, self.bare_output)
+
+ def check_dir(self, rel_path):
+ return self.check(rel_path)
+
+ def check(self, start_dir):
+ """Check the files in start_dir, recursively check its subdirectories."""
+ errors = []
+ items = self.list_dir(start_dir)
+ logging.info('check(%s) -> %d' % (start_dir, len(items)))
+ for item in items:
+ full_path = os.path.join(self.root_dir, start_dir, item)
+ rel_path = full_path[len(self.root_dir) + 1:]
+ if is_ignored(rel_path):
+ continue
+ if os.path.isdir(full_path):
+ # Depth first.
+ errors.extend(self.check_dir(rel_path))
+ else:
+ error = self.check_file(rel_path)
+ if error:
+ errors.append(error)
+ return errors
+
+ def list_dir(self, start_dir):
+ """Lists all the files and directory inside start_dir."""
+ return sorted(
+ x for x in os.listdir(os.path.join(self.root_dir, start_dir))
+ if not x.startswith('.')
+ )
+
+
+class ApiSvnQuick(ApiBase):
+ """Returns all files in svn-versioned directories, independent of the fact if
+ they are versionned.
+
+ Uses svn info in each directory to determine which directories should be
+ crawled.
+ """
+ def __init__(self, *args):
+ super(ApiSvnQuick, self).__init__(*args)
+ self.url = get_svn_url(self.root_dir)
+
+ def check_dir(self, rel_path):
+ url = self.url + '/' + rel_path
+ if get_svn_url(os.path.join(self.root_dir, rel_path)) != url:
+ return []
+ return super(ApiSvnQuick, self).check_dir(rel_path)
+
+
+class ApiAllFilesAtOnceBase(ApiBase):
+ _files = None
+
+ def list_dir(self, start_dir):
+ """Lists all the files and directory inside start_dir."""
+ if self._files is None:
+ self._files = sorted(self._get_all_files())
+ if not self.bare_output:
+ print 'Found %s files' % len(self._files)
+ start_dir = start_dir[len(self.root_dir) + 1:]
+ return [
+ x[len(start_dir):] for x in self._files if x.startswith(start_dir)
+ ]
+
+ def _get_all_files(self):
+ """Lists all the files and directory inside self._root_dir."""
+ raise NotImplementedError()
+
+
+class ApiSvn(ApiAllFilesAtOnceBase):
+ """Returns all the subversion controlled files.
+
+ Warning: svn ls is abnormally slow.
+ """
+ def _get_all_files(self):
+ cmd = ['svn', 'ls', '--non-interactive', '--recursive']
+ return (
+ x for x in capture(cmd, self.root_dir).splitlines()
+ if not x.endswith(os.path.sep))
+
+
+class ApiGit(ApiAllFilesAtOnceBase):
+ def _get_all_files(self):
+ return capture(['git', 'ls-files'], cwd=self.root_dir).splitlines()
+
+
+def get_scm(dir_path, bare):
+ """Returns a properly configured ApiBase instance."""
+ cwd = os.getcwd()
+ root = get_svn_root(dir_path or cwd)
+ if root:
+ if not bare:
+ print('Found subversion checkout at %s' % root)
+ return ApiSvnQuick(dir_path or root, bare)
+ root = get_git_root(dir_path or cwd)
+ if root:
+ if not bare:
+ print('Found git repository at %s' % root)
+ return ApiGit(dir_path or root, bare)
+
+ # Returns a non-scm aware checker.
+ if not bare:
+ print('Failed to determine the SCM for %s' % dir_path)
+ return ApiBase(dir_path or cwd, bare)
+
+
+def main():
+ usage = """Usage: python %prog [--root <root>] [tocheck]
+ tocheck Specifies the directory, relative to root, to check. This defaults
+ to "." so it checks everything.
+
+Examples:
+ python %prog
+ python %prog --root /path/to/source chrome"""
+
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option(
+ '--root',
+ help='Specifies the repository root. This defaults '
+ 'to the checkout repository root')
+ parser.add_option(
+ '-v', '--verbose', action='count', default=0, help='Print debug logging')
+ parser.add_option(
+ '--bare',
+ action='store_true',
+ default=False,
+ help='Prints the bare filename triggering the checks')
+ parser.add_option(
+ '--file', action='append', dest='files',
+ help='Specifics a list of files to check the permissions of. Only these '
+ 'files will be checked')
+ options, args = parser.parse_args()
+
+ levels = [logging.ERROR, logging.INFO, logging.DEBUG]
+ logging.basicConfig(level=levels[min(len(levels) - 1, options.verbose)])
+
+ if len(args) > 1:
+ parser.error('Too many arguments used')
+
+ if options.root:
+ options.root = os.path.abspath(options.root)
+
+ if options.files:
+ errors = check_files(options.root, options.files, options.bare)
+ print '\n'.join(errors)
+ return bool(errors)
+
+ api = get_scm(options.root, options.bare)
+ if args:
+ start_dir = args[0]
+ else:
+ start_dir = api.root_dir
+
+ errors = api.check(start_dir)
+
+ if not options.bare:
+ print 'Processed %s files, %d files where tested for shebang' % (
+ api.count, api.count_shebang)
+
+ if errors:
+ if not options.bare:
+ print '\nFAILED\n'
+ print '\n'.join(errors)
+ return 1
+ if not options.bare:
+ print '\nSUCCESS\n'
+ return 0
+
+
+if '__main__' == __name__:
+ sys.exit(main())
diff --git a/chromium/tools/clang/OWNERS b/chromium/tools/clang/OWNERS
new file mode 100644
index 00000000000..d86ef9424a0
--- /dev/null
+++ b/chromium/tools/clang/OWNERS
@@ -0,0 +1,2 @@
+hans@chromium.org
+thakis@chromium.org
diff --git a/chromium/tools/clang/empty_string/EmptyStringConverter.cpp b/chromium/tools/clang/empty_string/EmptyStringConverter.cpp
new file mode 100644
index 00000000000..421f964bbd6
--- /dev/null
+++ b/chromium/tools/clang/empty_string/EmptyStringConverter.cpp
@@ -0,0 +1,200 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This implements a Clang tool to convert all instances of std::string("") to
+// std::string(). The latter is more efficient (as std::string doesn't have to
+// take a copy of an empty string) and generates fewer instructions as well. It
+// should be run using the tools/clang/scripts/run_tool.py helper.
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+
+using clang::ast_matchers::MatchFinder;
+using clang::ast_matchers::argumentCountIs;
+using clang::ast_matchers::bindTemporaryExpr;
+using clang::ast_matchers::constructorDecl;
+using clang::ast_matchers::constructExpr;
+using clang::ast_matchers::defaultArgExpr;
+using clang::ast_matchers::expr;
+using clang::ast_matchers::forEach;
+using clang::ast_matchers::has;
+using clang::ast_matchers::hasArgument;
+using clang::ast_matchers::hasDeclaration;
+using clang::ast_matchers::hasName;
+using clang::ast_matchers::id;
+using clang::ast_matchers::methodDecl;
+using clang::ast_matchers::newExpr;
+using clang::ast_matchers::ofClass;
+using clang::ast_matchers::stringLiteral;
+using clang::ast_matchers::varDecl;
+using clang::tooling::CommonOptionsParser;
+using clang::tooling::Replacement;
+using clang::tooling::Replacements;
+
+namespace {
+
+// Handles replacements for stack and heap-allocated instances, e.g.:
+// std::string a("");
+// std::string* b = new std::string("");
+class ConstructorCallback : public MatchFinder::MatchCallback {
+ public:
+ ConstructorCallback(Replacements* replacements)
+ : replacements_(replacements) {}
+
+ virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
+
+ private:
+ Replacements* const replacements_;
+};
+
+// Handles replacements for invocations of std::string("") in an initializer
+// list.
+class InitializerCallback : public MatchFinder::MatchCallback {
+ public:
+ InitializerCallback(Replacements* replacements)
+ : replacements_(replacements) {}
+
+ virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
+
+ private:
+ Replacements* const replacements_;
+};
+
+// Handles replacements for invocations of std::string("") in a temporary
+// context, e.g. FunctionThatTakesString(std::string("")). Note that this
+// handles implicits construction of std::string as well.
+class TemporaryCallback : public MatchFinder::MatchCallback {
+ public:
+ TemporaryCallback(Replacements* replacements) : replacements_(replacements) {}
+
+ virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
+
+ private:
+ Replacements* const replacements_;
+};
+
+class EmptyStringConverter {
+ public:
+ explicit EmptyStringConverter(Replacements* replacements)
+ : constructor_callback_(replacements),
+ initializer_callback_(replacements),
+ temporary_callback_(replacements) {}
+
+ void SetupMatchers(MatchFinder* match_finder);
+
+ private:
+ ConstructorCallback constructor_callback_;
+ InitializerCallback initializer_callback_;
+ TemporaryCallback temporary_callback_;
+};
+
+void EmptyStringConverter::SetupMatchers(MatchFinder* match_finder) {
+ const clang::ast_matchers::StatementMatcher& constructor_call =
+ id("call",
+ constructExpr(
+ hasDeclaration(methodDecl(ofClass(hasName("std::basic_string")))),
+ argumentCountIs(2),
+ hasArgument(0, id("literal", stringLiteral())),
+ hasArgument(1, defaultArgExpr())));
+
+ // Note that expr(has()) in the matcher is significant; the Clang AST wraps
+ // calls to the std::string constructor with exprWithCleanups nodes. Without
+ // the expr(has()) matcher, the first and last rules would not match anything!
+ match_finder->addMatcher(varDecl(forEach(expr(has(constructor_call)))),
+ &constructor_callback_);
+ match_finder->addMatcher(newExpr(has(constructor_call)),
+ &constructor_callback_);
+ match_finder->addMatcher(bindTemporaryExpr(has(constructor_call)),
+ &temporary_callback_);
+ match_finder->addMatcher(
+ constructorDecl(forEach(expr(has(constructor_call)))),
+ &initializer_callback_);
+}
+
+void ConstructorCallback::run(const MatchFinder::MatchResult& result) {
+ const clang::StringLiteral* literal =
+ result.Nodes.getNodeAs<clang::StringLiteral>("literal");
+ if (literal->getLength() > 0)
+ return;
+
+ const clang::CXXConstructExpr* call =
+ result.Nodes.getNodeAs<clang::CXXConstructExpr>("call");
+ clang::CharSourceRange range =
+ clang::CharSourceRange::getTokenRange(call->getParenRange());
+ replacements_->insert(Replacement(*result.SourceManager, range, ""));
+}
+
+void InitializerCallback::run(const MatchFinder::MatchResult& result) {
+ const clang::StringLiteral* literal =
+ result.Nodes.getNodeAs<clang::StringLiteral>("literal");
+ if (literal->getLength() > 0)
+ return;
+
+ const clang::CXXConstructExpr* call =
+ result.Nodes.getNodeAs<clang::CXXConstructExpr>("call");
+ replacements_->insert(Replacement(*result.SourceManager, call, ""));
+}
+
+void TemporaryCallback::run(const MatchFinder::MatchResult& result) {
+ const clang::StringLiteral* literal =
+ result.Nodes.getNodeAs<clang::StringLiteral>("literal");
+ if (literal->getLength() > 0)
+ return;
+
+ const clang::CXXConstructExpr* call =
+ result.Nodes.getNodeAs<clang::CXXConstructExpr>("call");
+ // Differentiate between explicit and implicit calls to std::string's
+ // constructor. An implicitly generated constructor won't have a valid
+ // source range for the parenthesis. We do this because the matched expression
+ // for |call| in the explicit case doesn't include the closing parenthesis.
+ clang::SourceRange range = call->getParenRange();
+ if (range.isValid()) {
+ replacements_->insert(Replacement(*result.SourceManager, literal, ""));
+ } else {
+ replacements_->insert(
+ Replacement(*result.SourceManager,
+ call,
+ literal->isWide() ? "std::wstring()" : "std::string()"));
+ }
+}
+
+} // namespace
+
+static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
+
+int main(int argc, const char* argv[]) {
+ CommonOptionsParser options(argc, argv);
+ clang::tooling::ClangTool tool(options.getCompilations(),
+ options.getSourcePathList());
+
+ Replacements replacements;
+ EmptyStringConverter converter(&replacements);
+ MatchFinder match_finder;
+ converter.SetupMatchers(&match_finder);
+
+ int result =
+ tool.run(clang::tooling::newFrontendActionFactory(&match_finder));
+ if (result != 0)
+ return result;
+
+ // Each replacement line should have the following format:
+ // r:<file path>:<offset>:<length>:<replacement text>
+ // Only the <replacement text> field can contain embedded ":" characters.
+ // TODO(dcheng): Use a more clever serialization.
+ llvm::outs() << "==== BEGIN EDITS ====\n";
+ for (Replacements::const_iterator it = replacements.begin();
+ it != replacements.end(); ++it) {
+ llvm::outs() << "r:" << it->getFilePath() << ":" << it->getOffset() << ":"
+ << it->getLength() << ":" << it->getReplacementText() << "\n";
+ }
+ llvm::outs() << "==== END EDITS ====\n";
+
+ return 0;
+}
diff --git a/chromium/tools/clang/empty_string/Makefile b/chromium/tools/clang/empty_string/Makefile
new file mode 100644
index 00000000000..d44641216e1
--- /dev/null
+++ b/chromium/tools/clang/empty_string/Makefile
@@ -0,0 +1,23 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This Makefile requires the LLVM build system. In order to build this tool,
+# please run tools/clang/scripts/build_tool.py.
+
+CLANG_LEVEL := ../..
+
+TOOLNAME = empty_string
+
+NO_INSTALL = 1
+
+include $(CLANG_LEVEL)/../../Makefile.config
+
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+ clangRewriteFrontend.a clangRewriteCore.a clangParse.a clangSema.a \
+ clangAnalysis.a clangAST.a clangASTMatchers.a clangEdit.a \
+ clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/Makefile
+
diff --git a/chromium/tools/clang/plugins/ChromeClassTester.cpp b/chromium/tools/clang/plugins/ChromeClassTester.cpp
new file mode 100644
index 00000000000..ee8452dbc1e
--- /dev/null
+++ b/chromium/tools/clang/plugins/ChromeClassTester.cpp
@@ -0,0 +1,303 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A general interface for filtering and only acting on classes in Chromium C++
+// code.
+
+#include "ChromeClassTester.h"
+
+#include <sys/param.h>
+
+#include "clang/AST/AST.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+
+using namespace clang;
+
+namespace {
+
+bool starts_with(const std::string& one, const std::string& two) {
+ return one.compare(0, two.size(), two) == 0;
+}
+
+std::string lstrip(const std::string& one, const std::string& two) {
+ if (starts_with(one, two))
+ return one.substr(two.size());
+ return one;
+}
+
+bool ends_with(const std::string& one, const std::string& two) {
+ if (two.size() > one.size())
+ return false;
+
+ return one.compare(one.size() - two.size(), two.size(), two) == 0;
+}
+
+} // namespace
+
+ChromeClassTester::ChromeClassTester(CompilerInstance& instance,
+ bool check_url_directory)
+ : instance_(instance),
+ diagnostic_(instance.getDiagnostics()),
+ check_url_directory_(check_url_directory) {
+ BuildBannedLists();
+}
+
+ChromeClassTester::~ChromeClassTester() {}
+
+void ChromeClassTester::HandleTagDeclDefinition(TagDecl* tag) {
+ pending_class_decls_.push_back(tag);
+}
+
+bool ChromeClassTester::HandleTopLevelDecl(DeclGroupRef group_ref) {
+ for (size_t i = 0; i < pending_class_decls_.size(); ++i)
+ CheckTag(pending_class_decls_[i]);
+ pending_class_decls_.clear();
+
+ return true; // true means continue parsing.
+}
+
+void ChromeClassTester::CheckTag(TagDecl* tag) {
+ // We handle class types here where we have semantic information. We can only
+ // check structs/classes/enums here, but we get a bunch of nice semantic
+ // information instead of just parsing information.
+
+ if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) {
+ // If this is a POD or a class template or a type dependent on a
+ // templated class, assume there's no ctor/dtor/virtual method
+ // optimization that we can do.
+ if (record->isPOD() ||
+ record->getDescribedClassTemplate() ||
+ record->getTemplateSpecializationKind() ||
+ record->isDependentType())
+ return;
+
+ if (InBannedNamespace(record))
+ return;
+
+ SourceLocation record_location = record->getInnerLocStart();
+ if (InBannedDirectory(record_location))
+ return;
+
+ // We sadly need to maintain a blacklist of types that violate these
+ // rules, but do so for good reason or due to limitations of this
+ // checker (i.e., we don't handle extern templates very well).
+ std::string base_name = record->getNameAsString();
+ if (IsIgnoredType(base_name))
+ return;
+
+ // We ignore all classes that end with "Matcher" because they're probably
+ // GMock artifacts.
+ if (ends_with(base_name, "Matcher"))
+ return;
+
+ CheckChromeClass(record_location, record);
+ }
+}
+
+void ChromeClassTester::emitWarning(SourceLocation loc,
+ const char* raw_error) {
+ FullSourceLoc full(loc, instance().getSourceManager());
+ std::string err;
+ err = "[chromium-style] ";
+ err += raw_error;
+ DiagnosticsEngine::Level level =
+ diagnostic().getWarningsAsErrors() ?
+ DiagnosticsEngine::Error :
+ DiagnosticsEngine::Warning;
+ unsigned id = diagnostic().getCustomDiagID(level, err);
+ DiagnosticBuilder builder = diagnostic().Report(full, id);
+}
+
+bool ChromeClassTester::InBannedNamespace(const Decl* record) {
+ std::string n = GetNamespace(record);
+ if (!n.empty()) {
+ return std::find(banned_namespaces_.begin(), banned_namespaces_.end(), n)
+ != banned_namespaces_.end();
+ }
+
+ return false;
+}
+
+std::string ChromeClassTester::GetNamespace(const Decl* record) {
+ return GetNamespaceImpl(record->getDeclContext(), "");
+}
+
+bool ChromeClassTester::InImplementationFile(SourceLocation record_location) {
+ std::string filename;
+ if (!GetFilename(record_location, &filename))
+ return false;
+
+ if (ends_with(filename, ".cc") || ends_with(filename, ".cpp") ||
+ ends_with(filename, ".mm")) {
+ return true;
+ }
+
+ return false;
+}
+
+void ChromeClassTester::BuildBannedLists() {
+ banned_namespaces_.push_back("std");
+ banned_namespaces_.push_back("__gnu_cxx");
+ banned_namespaces_.push_back("WebKit");
+ banned_namespaces_.push_back("WebTestRunner");
+
+ banned_directories_.push_back("third_party/");
+ banned_directories_.push_back("native_client/");
+ banned_directories_.push_back("breakpad/");
+ banned_directories_.push_back("courgette/");
+ banned_directories_.push_back("pdf/");
+ banned_directories_.push_back("ppapi/");
+ banned_directories_.push_back("usr/");
+ banned_directories_.push_back("testing/");
+ banned_directories_.push_back("v8/");
+ banned_directories_.push_back("dart/");
+ banned_directories_.push_back("sdch/");
+ banned_directories_.push_back("icu4c/");
+ banned_directories_.push_back("frameworks/");
+
+ if (!check_url_directory_)
+ banned_directories_.push_back("url/");
+
+ // Don't check autogenerated headers.
+ // Make puts them below $(builddir_name)/.../gen and geni.
+ // Ninja puts them below OUTPUT_DIR/.../gen
+ // Xcode has a fixed output directory for everything.
+ banned_directories_.push_back("gen/");
+ banned_directories_.push_back("geni/");
+ banned_directories_.push_back("xcodebuild/");
+
+ // You are standing in a mazy of twisty dependencies, all resolved by
+ // putting everything in the header.
+ banned_directories_.push_back("automation/");
+
+ // Don't check system headers.
+ banned_directories_.push_back("/Developer/");
+
+ // Used in really low level threading code that probably shouldn't be out of
+ // lined.
+ ignored_record_names_.insert("ThreadLocalBoolean");
+
+ // A complicated pickle derived struct that is all packed integers.
+ ignored_record_names_.insert("Header");
+
+ // Part of the GPU system that uses multiple included header
+ // weirdness. Never getting this right.
+ ignored_record_names_.insert("Validators");
+
+ // Has a UNIT_TEST only constructor. Isn't *terribly* complex...
+ ignored_record_names_.insert("AutocompleteController");
+ ignored_record_names_.insert("HistoryURLProvider");
+
+ // Because of chrome frame
+ ignored_record_names_.insert("ReliabilityTestSuite");
+
+ // Used over in the net unittests. A large enough bundle of integers with 1
+ // non-pod class member. Probably harmless.
+ ignored_record_names_.insert("MockTransaction");
+
+ // Used heavily in ui_unittests and once in views_unittests. Fixing this
+ // isn't worth the overhead of an additional library.
+ ignored_record_names_.insert("TestAnimationDelegate");
+
+ // Part of our public interface that nacl and friends use. (Arguably, this
+ // should mean that this is a higher priority but fixing this looks hard.)
+ ignored_record_names_.insert("PluginVersionInfo");
+
+ // Measured performance improvement on cc_perftests. See
+ // https://codereview.chromium.org/11299290/
+ ignored_record_names_.insert("QuadF");
+}
+
+std::string ChromeClassTester::GetNamespaceImpl(const DeclContext* context,
+ const std::string& candidate) {
+ switch (context->getDeclKind()) {
+ case Decl::TranslationUnit: {
+ return candidate;
+ }
+ case Decl::Namespace: {
+ const NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context);
+ std::string name_str;
+ llvm::raw_string_ostream OS(name_str);
+ if (decl->isAnonymousNamespace())
+ OS << "<anonymous namespace>";
+ else
+ OS << *decl;
+ return GetNamespaceImpl(context->getParent(),
+ OS.str());
+ }
+ default: {
+ return GetNamespaceImpl(context->getParent(), candidate);
+ }
+ }
+}
+
+bool ChromeClassTester::InBannedDirectory(SourceLocation loc) {
+ std::string filename;
+ if (!GetFilename(loc, &filename)) {
+ // If the filename cannot be determined, simply treat this as a banned
+ // location, instead of going through the full lookup process.
+ return true;
+ }
+
+ // We need to special case scratch space; which is where clang does its
+ // macro expansion. We explicitly want to allow people to do otherwise bad
+ // things through macros that were defined due to third party libraries.
+ if (filename == "<scratch space>")
+ return true;
+
+ // Don't complain about autogenerated protobuf files.
+ if (ends_with(filename, ".pb.h")) {
+ return true;
+ }
+
+ // We need to munge the paths so that they are relative to the repository
+ // srcroot. We first resolve the symlinktastic relative path and then
+ // remove our known srcroot from it if needed.
+ char resolvedPath[MAXPATHLEN];
+ if (realpath(filename.c_str(), resolvedPath)) {
+ filename = resolvedPath;
+ }
+
+ // On linux, chrome is often checked out to /usr/local/google. Due to the
+ // "usr" rule in banned_directories_, all diagnostics would be suppressed
+ // in that case. As a workaround, strip that prefix.
+ filename = lstrip(filename, "/usr/local/google");
+
+ for (std::vector<std::string>::const_iterator it =
+ banned_directories_.begin();
+ it != banned_directories_.end(); ++it) {
+ // If we can find any of the banned path components in this path, then
+ // this file is rejected.
+ size_t index = filename.find(*it);
+ if (index != std::string::npos) {
+ bool matches_full_dir_name = index == 0 || filename[index - 1] == '/';
+ if ((*it)[0] == '/')
+ matches_full_dir_name = true;
+ if (matches_full_dir_name)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ChromeClassTester::IsIgnoredType(const std::string& base_name) {
+ return ignored_record_names_.find(base_name) != ignored_record_names_.end();
+}
+
+bool ChromeClassTester::GetFilename(SourceLocation loc,
+ std::string* filename) {
+ const SourceManager& source_manager = instance_.getSourceManager();
+ SourceLocation spelling_location = source_manager.getSpellingLoc(loc);
+ PresumedLoc ploc = source_manager.getPresumedLoc(spelling_location);
+ if (ploc.isInvalid()) {
+ // If we're in an invalid location, we're looking at things that aren't
+ // actually stated in the source.
+ return false;
+ }
+
+ *filename = ploc.getFilename();
+ return true;
+}
diff --git a/chromium/tools/clang/plugins/ChromeClassTester.h b/chromium/tools/clang/plugins/ChromeClassTester.h
new file mode 100644
index 00000000000..541341de539
--- /dev/null
+++ b/chromium/tools/clang/plugins/ChromeClassTester.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_CLANG_PLUGINS_CHROMECLASSTESTER_H_
+#define TOOLS_CLANG_PLUGINS_CHROMECLASSTESTER_H_
+
+#include <set>
+#include <vector>
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Frontend/CompilerInstance.h"
+
+// A class on top of ASTConsumer that forwards classes defined in Chromium
+// headers to subclasses which implement CheckChromeClass().
+class ChromeClassTester : public clang::ASTConsumer {
+ public:
+ explicit ChromeClassTester(clang::CompilerInstance& instance,
+ bool check_url_directory);
+ virtual ~ChromeClassTester();
+
+ // clang::ASTConsumer:
+ virtual void HandleTagDeclDefinition(clang::TagDecl* tag);
+ virtual bool HandleTopLevelDecl(clang::DeclGroupRef group_ref);
+
+ protected:
+ clang::CompilerInstance& instance() { return instance_; }
+ clang::DiagnosticsEngine& diagnostic() { return diagnostic_; }
+
+ // Emits a simple warning; this shouldn't be used if you require printf-style
+ // printing.
+ void emitWarning(clang::SourceLocation loc, const char* error);
+
+ // Utility method for subclasses to check if this class is in a banned
+ // namespace.
+ bool InBannedNamespace(const clang::Decl* record);
+
+ // Utility method for subclasses to determine the namespace of the
+ // specified record, if any. Unnamed namespaces will be identified as
+ // "<anonymous namespace>".
+ std::string GetNamespace(const clang::Decl* record);
+
+ // Utility method for subclasses to check if this class is within an
+ // implementation (.cc, .cpp, .mm) file.
+ bool InImplementationFile(clang::SourceLocation location);
+
+ private:
+ void BuildBannedLists();
+
+ void CheckTag(clang::TagDecl*);
+
+ // Filtered versions of tags that are only called with things defined in
+ // chrome header files.
+ virtual void CheckChromeClass(clang::SourceLocation record_location,
+ clang::CXXRecordDecl* record) = 0;
+
+ // Utility methods used for filtering out non-chrome classes (and ones we
+ // deliberately ignore) in HandleTagDeclDefinition().
+ std::string GetNamespaceImpl(const clang::DeclContext* context,
+ const std::string& candidate);
+ bool InBannedDirectory(clang::SourceLocation loc);
+ bool IsIgnoredType(const std::string& base_name);
+
+ // Attempts to determine the filename for the given SourceLocation.
+ // Returns false if the filename could not be determined.
+ bool GetFilename(clang::SourceLocation loc, std::string* filename);
+
+ clang::CompilerInstance& instance_;
+ clang::DiagnosticsEngine& diagnostic_;
+
+ // List of banned namespaces.
+ std::vector<std::string> banned_namespaces_;
+
+ // List of banned directories.
+ std::vector<std::string> banned_directories_;
+
+ // List of types that we don't check.
+ std::set<std::string> ignored_record_names_;
+
+ // List of decls to check once the current top-level decl is parsed.
+ std::vector<clang::TagDecl*> pending_class_decls_;
+
+ // TODO(tfarina): Remove once url/ directory compiles without warnings.
+ bool check_url_directory_;
+};
+
+#endif // TOOLS_CLANG_PLUGINS_CHROMECLASSTESTER_H_
diff --git a/chromium/tools/clang/plugins/FindBadConstructs.cpp b/chromium/tools/clang/plugins/FindBadConstructs.cpp
new file mode 100644
index 00000000000..9697c5f2110
--- /dev/null
+++ b/chromium/tools/clang/plugins/FindBadConstructs.cpp
@@ -0,0 +1,668 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file defines a bunch of recurring problems in the Chromium C++ code.
+//
+// Checks that are implemented:
+// - Constructors/Destructors should not be inlined if they are of a complex
+// class type.
+// - Missing "virtual" keywords on methods that should be virtual.
+// - Non-annotated overriding virtual methods.
+// - Virtual methods with nonempty implementations in their headers.
+// - Classes that derive from base::RefCounted / base::RefCountedThreadSafe
+// should have protected or private destructors.
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "ChromeClassTester.h"
+
+using namespace clang;
+
+namespace {
+
+const char kMethodRequiresOverride[] =
+ "[chromium-style] Overriding method must be marked with OVERRIDE.";
+const char kMethodRequiresVirtual[] =
+ "[chromium-style] Overriding method must have \"virtual\" keyword.";
+const char kNoExplicitDtor[] =
+ "[chromium-style] Classes that are ref-counted should have explicit "
+ "destructors that are declared protected or private.";
+const char kPublicDtor[] =
+ "[chromium-style] Classes that are ref-counted should have "
+ "destructors that are declared protected or private.";
+const char kProtectedNonVirtualDtor[] =
+ "[chromium-style] Classes that are ref-counted and have non-private "
+ "destructors should declare their destructor virtual.";
+const char kNoteInheritance[] =
+ "[chromium-style] %0 inherits from %1 here";
+const char kNoteImplicitDtor[] =
+ "[chromium-style] No explicit destructor for %0 defined";
+const char kNotePublicDtor[] =
+ "[chromium-style] Public destructor declared here";
+const char kNoteProtectedNonVirtualDtor[] =
+ "[chromium-style] Protected non-virtual destructor declared here";
+
+bool TypeHasNonTrivialDtor(const Type* type) {
+ if (const CXXRecordDecl* cxx_r = type->getPointeeCXXRecordDecl())
+ return cxx_r->hasTrivialDestructor();
+
+ return false;
+}
+
+// Returns the underlying Type for |type| by expanding typedefs and removing
+// any namespace qualifiers. This is similar to desugaring, except that for
+// ElaboratedTypes, desugar will unwrap too much.
+const Type* UnwrapType(const Type* type) {
+ if (const ElaboratedType* elaborated = dyn_cast<ElaboratedType>(type))
+ return UnwrapType(elaborated->getNamedType().getTypePtr());
+ if (const TypedefType* typedefed = dyn_cast<TypedefType>(type))
+ return UnwrapType(typedefed->desugar().getTypePtr());
+ return type;
+}
+
+// Searches for constructs that we know we don't want in the Chromium code base.
+class FindBadConstructsConsumer : public ChromeClassTester {
+ public:
+ FindBadConstructsConsumer(CompilerInstance& instance,
+ bool check_base_classes,
+ bool check_virtuals_in_implementations,
+ bool check_url_directory)
+ : ChromeClassTester(instance, check_url_directory),
+ check_base_classes_(check_base_classes),
+ check_virtuals_in_implementations_(check_virtuals_in_implementations) {
+ // Register warning/error messages.
+ diag_method_requires_override_ = diagnostic().getCustomDiagID(
+ getErrorLevel(), kMethodRequiresOverride);
+ diag_method_requires_virtual_ = diagnostic().getCustomDiagID(
+ getErrorLevel(), kMethodRequiresVirtual);
+ diag_no_explicit_dtor_ = diagnostic().getCustomDiagID(
+ getErrorLevel(), kNoExplicitDtor);
+ diag_public_dtor_ = diagnostic().getCustomDiagID(
+ getErrorLevel(), kPublicDtor);
+ diag_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID(
+ getErrorLevel(), kProtectedNonVirtualDtor);
+
+ // Registers notes to make it easier to interpret warnings.
+ diag_note_inheritance_ = diagnostic().getCustomDiagID(
+ DiagnosticsEngine::Note, kNoteInheritance);
+ diag_note_implicit_dtor_ = diagnostic().getCustomDiagID(
+ DiagnosticsEngine::Note, kNoteImplicitDtor);
+ diag_note_public_dtor_ = diagnostic().getCustomDiagID(
+ DiagnosticsEngine::Note, kNotePublicDtor);
+ diag_note_protected_non_virtual_dtor_ = diagnostic().getCustomDiagID(
+ DiagnosticsEngine::Note, kNoteProtectedNonVirtualDtor);
+ }
+
+ virtual void CheckChromeClass(SourceLocation record_location,
+ CXXRecordDecl* record) {
+ bool implementation_file = InImplementationFile(record_location);
+
+ if (!implementation_file) {
+ // Only check for "heavy" constructors/destructors in header files;
+ // within implementation files, there is no performance cost.
+ CheckCtorDtorWeight(record_location, record);
+ }
+
+ if (!implementation_file || check_virtuals_in_implementations_) {
+ bool warn_on_inline_bodies = !implementation_file;
+
+ // Check that all virtual methods are marked accordingly with both
+ // virtual and OVERRIDE.
+ CheckVirtualMethods(record_location, record, warn_on_inline_bodies);
+ }
+
+ CheckRefCountedDtors(record_location, record);
+ }
+
+ private:
+ // The type of problematic ref-counting pattern that was encountered.
+ enum RefcountIssue {
+ None,
+ ImplicitDestructor,
+ PublicDestructor
+ };
+
+ bool check_base_classes_;
+ bool check_virtuals_in_implementations_;
+
+ unsigned diag_method_requires_override_;
+ unsigned diag_method_requires_virtual_;
+ unsigned diag_no_explicit_dtor_;
+ unsigned diag_public_dtor_;
+ unsigned diag_protected_non_virtual_dtor_;
+ unsigned diag_note_inheritance_;
+ unsigned diag_note_implicit_dtor_;
+ unsigned diag_note_public_dtor_;
+ unsigned diag_note_protected_non_virtual_dtor_;
+
+ // Prints errors if the constructor/destructor weight is too heavy.
+ void CheckCtorDtorWeight(SourceLocation record_location,
+ CXXRecordDecl* record) {
+ // We don't handle anonymous structs. If this record doesn't have a
+ // name, it's of the form:
+ //
+ // struct {
+ // ...
+ // } name_;
+ if (record->getIdentifier() == NULL)
+ return;
+
+ // Count the number of templated base classes as a feature of whether the
+ // destructor can be inlined.
+ int templated_base_classes = 0;
+ for (CXXRecordDecl::base_class_const_iterator it = record->bases_begin();
+ it != record->bases_end(); ++it) {
+ if (it->getTypeSourceInfo()->getTypeLoc().getTypeLocClass() ==
+ TypeLoc::TemplateSpecialization) {
+ ++templated_base_classes;
+ }
+ }
+
+ // Count the number of trivial and non-trivial member variables.
+ int trivial_member = 0;
+ int non_trivial_member = 0;
+ int templated_non_trivial_member = 0;
+ for (RecordDecl::field_iterator it = record->field_begin();
+ it != record->field_end(); ++it) {
+ CountType(it->getType().getTypePtr(),
+ &trivial_member,
+ &non_trivial_member,
+ &templated_non_trivial_member);
+ }
+
+ // Check to see if we need to ban inlined/synthesized constructors. Note
+ // that the cutoffs here are kind of arbitrary. Scores over 10 break.
+ int dtor_score = 0;
+ // Deriving from a templated base class shouldn't be enough to trigger
+ // the ctor warning, but if you do *anything* else, it should.
+ //
+ // TODO(erg): This is motivated by templated base classes that don't have
+ // any data members. Somehow detect when templated base classes have data
+ // members and treat them differently.
+ dtor_score += templated_base_classes * 9;
+ // Instantiating a template is an insta-hit.
+ dtor_score += templated_non_trivial_member * 10;
+ // The fourth normal class member should trigger the warning.
+ dtor_score += non_trivial_member * 3;
+
+ int ctor_score = dtor_score;
+ // You should be able to have 9 ints before we warn you.
+ ctor_score += trivial_member;
+
+ if (ctor_score >= 10) {
+ if (!record->hasUserDeclaredConstructor()) {
+ emitWarning(record_location,
+ "Complex class/struct needs an explicit out-of-line "
+ "constructor.");
+ } else {
+ // Iterate across all the constructors in this file and yell if we
+ // find one that tries to be inline.
+ for (CXXRecordDecl::ctor_iterator it = record->ctor_begin();
+ it != record->ctor_end(); ++it) {
+ if (it->hasInlineBody()) {
+ if (it->isCopyConstructor() &&
+ !record->hasUserDeclaredCopyConstructor()) {
+ emitWarning(record_location,
+ "Complex class/struct needs an explicit out-of-line "
+ "copy constructor.");
+ } else {
+ emitWarning(it->getInnerLocStart(),
+ "Complex constructor has an inlined body.");
+ }
+ }
+ }
+ }
+ }
+
+ // The destructor side is equivalent except that we don't check for
+ // trivial members; 20 ints don't need a destructor.
+ if (dtor_score >= 10 && !record->hasTrivialDestructor()) {
+ if (!record->hasUserDeclaredDestructor()) {
+ emitWarning(
+ record_location,
+ "Complex class/struct needs an explicit out-of-line "
+ "destructor.");
+ } else if (CXXDestructorDecl* dtor = record->getDestructor()) {
+ if (dtor->hasInlineBody()) {
+ emitWarning(dtor->getInnerLocStart(),
+ "Complex destructor has an inline body.");
+ }
+ }
+ }
+ }
+
+ void CheckVirtualMethod(const CXXMethodDecl* method,
+ bool warn_on_inline_bodies) {
+ if (!method->isVirtual())
+ return;
+
+ if (!method->isVirtualAsWritten()) {
+ SourceLocation loc = method->getTypeSpecStartLoc();
+ if (isa<CXXDestructorDecl>(method))
+ loc = method->getInnerLocStart();
+ SourceManager& manager = instance().getSourceManager();
+ FullSourceLoc full_loc(loc, manager);
+ SourceLocation spelling_loc = manager.getSpellingLoc(loc);
+ diagnostic().Report(full_loc, diag_method_requires_virtual_)
+ << FixItHint::CreateInsertion(spelling_loc, "virtual ");
+ }
+
+ // Virtual methods should not have inline definitions beyond "{}". This
+ // only matters for header files.
+ if (warn_on_inline_bodies && method->hasBody() &&
+ method->hasInlineBody()) {
+ if (CompoundStmt* cs = dyn_cast<CompoundStmt>(method->getBody())) {
+ if (cs->size()) {
+ emitWarning(
+ cs->getLBracLoc(),
+ "virtual methods with non-empty bodies shouldn't be "
+ "declared inline.");
+ }
+ }
+ }
+ }
+
+ bool InTestingNamespace(const Decl* record) {
+ return GetNamespace(record).find("testing") != std::string::npos;
+ }
+
+ bool IsMethodInBannedOrTestingNamespace(const CXXMethodDecl* method) {
+ if (InBannedNamespace(method))
+ return true;
+ for (CXXMethodDecl::method_iterator i = method->begin_overridden_methods();
+ i != method->end_overridden_methods();
+ ++i) {
+ const CXXMethodDecl* overridden = *i;
+ if (IsMethodInBannedOrTestingNamespace(overridden) ||
+ InTestingNamespace(overridden)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void CheckOverriddenMethod(const CXXMethodDecl* method) {
+ if (!method->size_overridden_methods() || method->getAttr<OverrideAttr>())
+ return;
+
+ if (isa<CXXDestructorDecl>(method) || method->isPure())
+ return;
+
+ if (IsMethodInBannedOrTestingNamespace(method))
+ return;
+
+ SourceManager& manager = instance().getSourceManager();
+ SourceRange type_info_range =
+ method->getTypeSourceInfo()->getTypeLoc().getSourceRange();
+ FullSourceLoc loc(type_info_range.getBegin(), manager);
+
+ // Build the FixIt insertion point after the end of the method definition,
+ // including any const-qualifiers and attributes, and before the opening
+ // of the l-curly-brace (if inline) or the semi-color (if a declaration).
+ SourceLocation spelling_end =
+ manager.getSpellingLoc(type_info_range.getEnd());
+ if (spelling_end.isValid()) {
+ SourceLocation token_end = Lexer::getLocForEndOfToken(
+ spelling_end, 0, manager, LangOptions());
+ diagnostic().Report(token_end, diag_method_requires_override_)
+ << FixItHint::CreateInsertion(token_end, " OVERRIDE");
+ } else {
+ diagnostic().Report(loc, diag_method_requires_override_);
+ }
+ }
+
+ // Makes sure there is a "virtual" keyword on virtual methods.
+ //
+ // Gmock objects trigger these for each MOCK_BLAH() macro used. So we have a
+ // trick to get around that. If a class has member variables whose types are
+ // in the "testing" namespace (which is how gmock works behind the scenes),
+ // there's a really high chance we won't care about these errors
+ void CheckVirtualMethods(SourceLocation record_location,
+ CXXRecordDecl* record,
+ bool warn_on_inline_bodies) {
+ for (CXXRecordDecl::field_iterator it = record->field_begin();
+ it != record->field_end(); ++it) {
+ CXXRecordDecl* record_type =
+ it->getTypeSourceInfo()->getTypeLoc().getTypePtr()->
+ getAsCXXRecordDecl();
+ if (record_type) {
+ if (InTestingNamespace(record_type)) {
+ return;
+ }
+ }
+ }
+
+ for (CXXRecordDecl::method_iterator it = record->method_begin();
+ it != record->method_end(); ++it) {
+ if (it->isCopyAssignmentOperator() || isa<CXXConstructorDecl>(*it)) {
+ // Ignore constructors and assignment operators.
+ } else if (isa<CXXDestructorDecl>(*it) &&
+ !record->hasUserDeclaredDestructor()) {
+ // Ignore non-user-declared destructors.
+ } else {
+ CheckVirtualMethod(*it, warn_on_inline_bodies);
+ CheckOverriddenMethod(*it);
+ }
+ }
+ }
+
+ void CountType(const Type* type,
+ int* trivial_member,
+ int* non_trivial_member,
+ int* templated_non_trivial_member) {
+ switch (type->getTypeClass()) {
+ case Type::Record: {
+ // Simplifying; the whole class isn't trivial if the dtor is, but
+ // we use this as a signal about complexity.
+ if (TypeHasNonTrivialDtor(type))
+ (*trivial_member)++;
+ else
+ (*non_trivial_member)++;
+ break;
+ }
+ case Type::TemplateSpecialization: {
+ TemplateName name =
+ dyn_cast<TemplateSpecializationType>(type)->getTemplateName();
+ bool whitelisted_template = false;
+
+ // HACK: I'm at a loss about how to get the syntax checker to get
+ // whether a template is exterened or not. For the first pass here,
+ // just do retarded string comparisons.
+ if (TemplateDecl* decl = name.getAsTemplateDecl()) {
+ std::string base_name = decl->getNameAsString();
+ if (base_name == "basic_string")
+ whitelisted_template = true;
+ }
+
+ if (whitelisted_template)
+ (*non_trivial_member)++;
+ else
+ (*templated_non_trivial_member)++;
+ break;
+ }
+ case Type::Elaborated: {
+ CountType(
+ dyn_cast<ElaboratedType>(type)->getNamedType().getTypePtr(),
+ trivial_member, non_trivial_member, templated_non_trivial_member);
+ break;
+ }
+ case Type::Typedef: {
+ while (const TypedefType* TT = dyn_cast<TypedefType>(type)) {
+ type = TT->getDecl()->getUnderlyingType().getTypePtr();
+ }
+ CountType(type, trivial_member, non_trivial_member,
+ templated_non_trivial_member);
+ break;
+ }
+ default: {
+ // Stupid assumption: anything we see that isn't the above is one of
+ // the 20 integer types.
+ (*trivial_member)++;
+ break;
+ }
+ }
+ }
+
+ // Check |record| for issues that are problematic for ref-counted types.
+ // Note that |record| may not be a ref-counted type, but a base class for
+ // a type that is.
+ // If there are issues, update |loc| with the SourceLocation of the issue
+ // and returns appropriately, or returns None if there are no issues.
+ static RefcountIssue CheckRecordForRefcountIssue(
+ const CXXRecordDecl* record,
+ SourceLocation &loc) {
+ if (!record->hasUserDeclaredDestructor()) {
+ loc = record->getLocation();
+ return ImplicitDestructor;
+ }
+
+ if (CXXDestructorDecl* dtor = record->getDestructor()) {
+ if (dtor->getAccess() == AS_public) {
+ loc = dtor->getInnerLocStart();
+ return PublicDestructor;
+ }
+ }
+
+ return None;
+ }
+
+ // Adds either a warning or error, based on the current handling of
+ // -Werror.
+ DiagnosticsEngine::Level getErrorLevel() {
+ return diagnostic().getWarningsAsErrors() ?
+ DiagnosticsEngine::Error : DiagnosticsEngine::Warning;
+ }
+
+ // Returns true if |base| specifies one of the Chromium reference counted
+ // classes (base::RefCounted / base::RefCountedThreadSafe).
+ static bool IsRefCountedCallback(const CXXBaseSpecifier* base,
+ CXXBasePath& path,
+ void* user_data) {
+ FindBadConstructsConsumer* self =
+ static_cast<FindBadConstructsConsumer*>(user_data);
+
+ const TemplateSpecializationType* base_type =
+ dyn_cast<TemplateSpecializationType>(
+ UnwrapType(base->getType().getTypePtr()));
+ if (!base_type) {
+ // Base-most definition is not a template, so this cannot derive from
+ // base::RefCounted. However, it may still be possible to use with a
+ // scoped_refptr<> and support ref-counting, so this is not a perfect
+ // guarantee of safety.
+ return false;
+ }
+
+ TemplateName name = base_type->getTemplateName();
+ if (TemplateDecl* decl = name.getAsTemplateDecl()) {
+ std::string base_name = decl->getNameAsString();
+
+ // Check for both base::RefCounted and base::RefCountedThreadSafe.
+ if (base_name.compare(0, 10, "RefCounted") == 0 &&
+ self->GetNamespace(decl) == "base") {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Returns true if |base| specifies a class that has a public destructor,
+ // either explicitly or implicitly.
+ static bool HasPublicDtorCallback(const CXXBaseSpecifier* base,
+ CXXBasePath& path,
+ void* user_data) {
+ // Only examine paths that have public inheritance, as they are the
+ // only ones which will result in the destructor potentially being
+ // exposed. This check is largely redundant, as Chromium code should be
+ // exclusively using public inheritance.
+ if (path.Access != AS_public)
+ return false;
+
+ CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(
+ base->getType()->getAs<RecordType>()->getDecl());
+ SourceLocation unused;
+ return None != CheckRecordForRefcountIssue(record, unused);
+ }
+
+ // Outputs a C++ inheritance chain as a diagnostic aid.
+ void PrintInheritanceChain(const CXXBasePath& path) {
+ for (CXXBasePath::const_iterator it = path.begin(); it != path.end();
+ ++it) {
+ diagnostic().Report(it->Base->getLocStart(), diag_note_inheritance_)
+ << it->Class << it->Base->getType();
+ }
+ }
+
+ unsigned DiagnosticForIssue(RefcountIssue issue) {
+ switch (issue) {
+ case ImplicitDestructor:
+ return diag_no_explicit_dtor_;
+ case PublicDestructor:
+ return diag_public_dtor_;
+ case None:
+ assert(false && "Do not call DiagnosticForIssue with issue None");
+ return 0;
+ }
+ }
+
+ // Check |record| to determine if it has any problematic refcounting
+ // issues and, if so, print them as warnings/errors based on the current
+ // value of getErrorLevel().
+ //
+ // If |record| is a C++ class, and if it inherits from one of the Chromium
+ // ref-counting classes (base::RefCounted / base::RefCountedThreadSafe),
+ // ensure that there are no public destructors in the class hierarchy. This
+ // is to guard against accidentally stack-allocating a RefCounted class or
+ // sticking it in a non-ref-counted container (like scoped_ptr<>).
+ void CheckRefCountedDtors(SourceLocation record_location,
+ CXXRecordDecl* record) {
+ // Skip anonymous structs.
+ if (record->getIdentifier() == NULL)
+ return;
+
+ // Determine if the current type is even ref-counted.
+ CXXBasePaths refcounted_path;
+ if (!record->lookupInBases(
+ &FindBadConstructsConsumer::IsRefCountedCallback, this,
+ refcounted_path)) {
+ return; // Class does not derive from a ref-counted base class.
+ }
+
+ // Easy check: Check to see if the current type is problematic.
+ SourceLocation loc;
+ RefcountIssue issue = CheckRecordForRefcountIssue(record, loc);
+ if (issue != None) {
+ diagnostic().Report(loc, DiagnosticForIssue(issue));
+ PrintInheritanceChain(refcounted_path.front());
+ return;
+ }
+ if (CXXDestructorDecl* dtor =
+ refcounted_path.begin()->back().Class->getDestructor()) {
+ if (dtor->getAccess() == AS_protected &&
+ !dtor->isVirtual()) {
+ loc = dtor->getInnerLocStart();
+ diagnostic().Report(loc, diag_protected_non_virtual_dtor_);
+ return;
+ }
+ }
+
+ // Long check: Check all possible base classes for problematic
+ // destructors. This checks for situations involving multiple
+ // inheritance, where the ref-counted class may be implementing an
+ // interface that has a public or implicit destructor.
+ //
+ // struct SomeInterface {
+ // virtual void DoFoo();
+ // };
+ //
+ // struct RefCountedInterface
+ // : public base::RefCounted<RefCountedInterface>,
+ // public SomeInterface {
+ // private:
+ // friend class base::Refcounted<RefCountedInterface>;
+ // virtual ~RefCountedInterface() {}
+ // };
+ //
+ // While RefCountedInterface is "safe", in that its destructor is
+ // private, it's possible to do the following "unsafe" code:
+ // scoped_refptr<RefCountedInterface> some_class(
+ // new RefCountedInterface);
+ // // Calls SomeInterface::~SomeInterface(), which is unsafe.
+ // delete static_cast<SomeInterface*>(some_class.get());
+ if (!check_base_classes_)
+ return;
+
+ // Find all public destructors. This will record the class hierarchy
+ // that leads to the public destructor in |dtor_paths|.
+ CXXBasePaths dtor_paths;
+ if (!record->lookupInBases(
+ &FindBadConstructsConsumer::HasPublicDtorCallback, this,
+ dtor_paths)) {
+ return;
+ }
+
+ for (CXXBasePaths::const_paths_iterator it = dtor_paths.begin();
+ it != dtor_paths.end(); ++it) {
+ // The record with the problem will always be the last record
+ // in the path, since it is the record that stopped the search.
+ const CXXRecordDecl* problem_record = dyn_cast<CXXRecordDecl>(
+ it->back().Base->getType()->getAs<RecordType>()->getDecl());
+
+ issue = CheckRecordForRefcountIssue(problem_record, loc);
+
+ if (issue == ImplicitDestructor) {
+ diagnostic().Report(record_location, diag_no_explicit_dtor_);
+ PrintInheritanceChain(refcounted_path.front());
+ diagnostic().Report(loc, diag_note_implicit_dtor_) << problem_record;
+ PrintInheritanceChain(*it);
+ } else if (issue == PublicDestructor) {
+ diagnostic().Report(record_location, diag_public_dtor_);
+ PrintInheritanceChain(refcounted_path.front());
+ diagnostic().Report(loc, diag_note_public_dtor_);
+ PrintInheritanceChain(*it);
+ }
+ }
+ }
+};
+
+class FindBadConstructsAction : public PluginASTAction {
+ public:
+ FindBadConstructsAction()
+ : check_base_classes_(false),
+ check_virtuals_in_implementations_(true),
+ check_url_directory_(false) {
+ }
+
+ protected:
+ // Overridden from PluginASTAction:
+ virtual ASTConsumer* CreateASTConsumer(CompilerInstance& instance,
+ llvm::StringRef ref) {
+ return new FindBadConstructsConsumer(
+ instance, check_base_classes_, check_virtuals_in_implementations_,
+ check_url_directory_);
+ }
+
+ virtual bool ParseArgs(const CompilerInstance& instance,
+ const std::vector<std::string>& args) {
+ bool parsed = true;
+
+ for (size_t i = 0; i < args.size() && parsed; ++i) {
+ if (args[i] == "skip-virtuals-in-implementations") {
+ // TODO(rsleevi): Remove this once http://crbug.com/115047 is fixed.
+ check_virtuals_in_implementations_ = false;
+ } else if (args[i] == "check-base-classes") {
+ // TODO(rsleevi): Remove this once http://crbug.com/123295 is fixed.
+ check_base_classes_ = true;
+ } else if (args[i] == "check-url-directory") {
+ // TODO(tfarina): Remove this once http://crbug.com/229660 is fixed.
+ check_url_directory_ = true;
+ } else {
+ parsed = false;
+ llvm::errs() << "Unknown clang plugin argument: " << args[i] << "\n";
+ }
+ }
+
+ return parsed;
+ }
+
+ private:
+ bool check_base_classes_;
+ bool check_virtuals_in_implementations_;
+ bool check_url_directory_;
+};
+
+} // namespace
+
+static FrontendPluginRegistry::Add<FindBadConstructsAction>
+X("find-bad-constructs", "Finds bad C++ constructs");
diff --git a/chromium/tools/clang/plugins/Makefile b/chromium/tools/clang/plugins/Makefile
new file mode 100644
index 00000000000..0cfec71159c
--- /dev/null
+++ b/chromium/tools/clang/plugins/Makefile
@@ -0,0 +1,19 @@
+# This file requires the clang build system, at least for now. So to use this
+# Makefile, you should execute the following commands to copy this directory
+# into a clang checkout:
+#
+# cp -R <this directory> third_party/llvm/tools/clang/tools/chrome-plugin
+# cd third_party/llvm/tools/clang/tools/chrome-plugin
+# make
+
+CLANG_LEVEL := ../..
+LIBRARYNAME = FindBadConstructs
+
+LINK_LIBS_IN_SHARED = 0
+SHARED_LIBRARY = 1
+
+include $(CLANG_LEVEL)/Makefile
+
+ifeq ($(OS),Darwin)
+ LDFLAGS=-Wl,-undefined,dynamic_lookup
+endif
diff --git a/chromium/tools/clang/plugins/OWNERS b/chromium/tools/clang/plugins/OWNERS
new file mode 100644
index 00000000000..4733a4f06bf
--- /dev/null
+++ b/chromium/tools/clang/plugins/OWNERS
@@ -0,0 +1 @@
+erg@chromium.org
diff --git a/chromium/tools/clang/plugins/README.chromium b/chromium/tools/clang/plugins/README.chromium
new file mode 100644
index 00000000000..a2ce0ff5575
--- /dev/null
+++ b/chromium/tools/clang/plugins/README.chromium
@@ -0,0 +1,4 @@
+Documentation for this code is:
+
+- http://code.google.com/p/chromium/wiki/Clang
+- http://code.google.com/p/chromium/wiki/WritingClangPlugins
diff --git a/chromium/tools/clang/rewrite_scoped_array/Makefile b/chromium/tools/clang/rewrite_scoped_array/Makefile
new file mode 100644
index 00000000000..d79329cd563
--- /dev/null
+++ b/chromium/tools/clang/rewrite_scoped_array/Makefile
@@ -0,0 +1,23 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This Makefile requires the LLVM build system. In order to build this tool,
+# please run tools/clang/scripts/build_tool.py.
+
+CLANG_LEVEL := ../..
+
+TOOLNAME = rewrite_scoped_array
+
+NO_INSTALL = 1
+
+include $(CLANG_LEVEL)/../../Makefile.config
+
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+ clangRewriteFrontend.a clangRewriteCore.a clangParse.a clangSema.a \
+ clangAnalysis.a clangAST.a clangASTMatchers.a clangEdit.a \
+ clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/Makefile
+
diff --git a/chromium/tools/clang/rewrite_scoped_array/RewriteScopedArray.cpp b/chromium/tools/clang/rewrite_scoped_array/RewriteScopedArray.cpp
new file mode 100644
index 00000000000..a09d5358ede
--- /dev/null
+++ b/chromium/tools/clang/rewrite_scoped_array/RewriteScopedArray.cpp
@@ -0,0 +1,96 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This implements a Clang tool to rewrite all instances of scoped_array<T> to
+// scoped_ptr<T[]>. The former is being deprecated in favor of the latter, to
+// allow for an eventual transition from scoped_ptr to unique_ptr.
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+
+using clang::ast_matchers::MatchFinder;
+using clang::ast_matchers::hasDeclaration;
+using clang::ast_matchers::hasName;
+using clang::ast_matchers::id;
+using clang::ast_matchers::loc;
+using clang::ast_matchers::qualType;
+using clang::ast_matchers::recordDecl;
+using clang::tooling::CommonOptionsParser;
+using clang::tooling::Replacement;
+using clang::tooling::Replacements;
+using llvm::StringRef;
+
+namespace {
+
+class RewriterCallback : public MatchFinder::MatchCallback {
+ public:
+ RewriterCallback(Replacements* replacements) : replacements_(replacements) {}
+ virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
+
+ private:
+ Replacements* const replacements_;
+};
+
+void RewriterCallback::run(const MatchFinder::MatchResult& result) {
+ const clang::TypeLoc type_location =
+ *result.Nodes.getNodeAs<clang::TypeLoc>("loc");
+ clang::CharSourceRange range = clang::CharSourceRange::getTokenRange(
+ result.SourceManager->getSpellingLoc(type_location.getLocStart()),
+ result.SourceManager->getSpellingLoc(type_location.getLocEnd()));
+ // TODO(dcheng): Log an error?
+ if (!range.isValid())
+ return;
+ std::string replacement_text = clang::Lexer::getSourceText(
+ range, *result.SourceManager, result.Context->getLangOpts());
+ // TODO(dcheng): Log errors?
+ if (!StringRef(replacement_text).startswith("scoped_array<") ||
+ !StringRef(replacement_text).endswith(">"))
+ return;
+ replacement_text.replace(strlen("scoped_"), strlen("array"), "ptr");
+ replacement_text.insert(replacement_text.size() - 1, "[]");
+ replacements_->insert(
+ Replacement(*result.SourceManager, range, replacement_text));
+}
+
+} // namespace
+
+static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
+
+int main(int argc, const char* argv[]) {
+ CommonOptionsParser options(argc, argv);
+ clang::tooling::ClangTool tool(options.getCompilations(),
+ options.getSourcePathList());
+
+ Replacements replacements;
+ RewriterCallback callback(&replacements);
+ MatchFinder match_finder;
+ match_finder.addMatcher(
+ id("loc",
+ loc(qualType(hasDeclaration(recordDecl(hasName("::scoped_array")))))),
+ &callback);
+
+ int result =
+ tool.run(clang::tooling::newFrontendActionFactory(&match_finder));
+ if (result != 0)
+ return result;
+
+ // Serialization format is documented in tools/clang/scripts/run_tool.py
+ llvm::outs() << "==== BEGIN EDITS ====\n";
+ for (Replacements::const_iterator it = replacements.begin();
+ it != replacements.end(); ++it) {
+ llvm::outs() << "r:" << it->getFilePath() << ":" << it->getOffset() << ":"
+ << it->getLength() << ":" << it->getReplacementText() << "\n";
+ }
+ llvm::outs() << "==== END EDITS ====\n";
+
+ return 0;
+}
diff --git a/chromium/tools/clang/rewrite_scoped_ptr_ctor_null/Makefile b/chromium/tools/clang/rewrite_scoped_ptr_ctor_null/Makefile
new file mode 100644
index 00000000000..f807d89c9ae
--- /dev/null
+++ b/chromium/tools/clang/rewrite_scoped_ptr_ctor_null/Makefile
@@ -0,0 +1,23 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This Makefile requires the LLVM build system. In order to build this tool,
+# please run tools/clang/scripts/build_tool.py.
+
+CLANG_LEVEL := ../..
+
+TOOLNAME = rewrite_scoped_ptr_ctor_null
+
+NO_INSTALL = 1
+
+include $(CLANG_LEVEL)/../../Makefile.config
+
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+ clangRewriteFrontend.a clangRewriteCore.a clangParse.a clangSema.a \
+ clangAnalysis.a clangAST.a clangASTMatchers.a clangEdit.a \
+ clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/Makefile
+
diff --git a/chromium/tools/clang/rewrite_scoped_ptr_ctor_null/RewriteScopedPtrCtorNull.cpp b/chromium/tools/clang/rewrite_scoped_ptr_ctor_null/RewriteScopedPtrCtorNull.cpp
new file mode 100644
index 00000000000..26813eba48d
--- /dev/null
+++ b/chromium/tools/clang/rewrite_scoped_ptr_ctor_null/RewriteScopedPtrCtorNull.cpp
@@ -0,0 +1,198 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This implements a Clang tool to convert all instances of std::string("") to
+// std::string(). The latter is more efficient (as std::string doesn't have to
+// take a copy of an empty string) and generates fewer instructions as well. It
+// should be run using the tools/clang/scripts/run_tool.py helper.
+
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+
+using clang::ast_matchers::MatchFinder;
+using clang::ast_matchers::argumentCountIs;
+using clang::ast_matchers::bindTemporaryExpr;
+using clang::ast_matchers::constructorDecl;
+using clang::ast_matchers::constructExpr;
+using clang::ast_matchers::defaultArgExpr;
+using clang::ast_matchers::expr;
+using clang::ast_matchers::forEach;
+using clang::ast_matchers::has;
+using clang::ast_matchers::hasArgument;
+using clang::ast_matchers::hasDeclaration;
+using clang::ast_matchers::matchesName;
+using clang::ast_matchers::id;
+using clang::ast_matchers::methodDecl;
+using clang::ast_matchers::newExpr;
+using clang::ast_matchers::ofClass;
+using clang::ast_matchers::unless;
+using clang::ast_matchers::varDecl;
+using clang::tooling::CommonOptionsParser;
+using clang::tooling::Replacement;
+using clang::tooling::Replacements;
+
+namespace {
+
+bool IsNullConstant(const clang::Expr& expr, clang::ASTContext* context) {
+ return expr.isNullPointerConstant(*context,
+ clang::Expr::NPC_ValueDependentIsNotNull) !=
+ clang::Expr::NPCK_NotNull;
+}
+
+// Handles replacements for stack and heap-allocated instances, e.g.:
+// scoped_ptr<T> a(NULL);
+// scoped_ptr<T>* b = new scoped_ptr<T>(NULL);
+// ...though the latter should be pretty rare.
+class ConstructorCallback : public MatchFinder::MatchCallback {
+ public:
+ ConstructorCallback(Replacements* replacements)
+ : replacements_(replacements) {}
+
+ virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
+
+ private:
+ Replacements* const replacements_;
+};
+
+// Handles replacements for invocations of scoped_ptr<T>(NULL) in an initializer
+// list.
+class InitializerCallback : public MatchFinder::MatchCallback {
+ public:
+ InitializerCallback(Replacements* replacements)
+ : replacements_(replacements) {}
+
+ virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
+
+ private:
+ Replacements* const replacements_;
+};
+
+// Handles replacements for invocations of scoped_ptr<T>(NULL) in a temporary
+// context, e.g. return scoped_ptr<T>(NULL).
+class TemporaryCallback : public MatchFinder::MatchCallback {
+ public:
+ TemporaryCallback(Replacements* replacements) : replacements_(replacements) {}
+
+ virtual void run(const MatchFinder::MatchResult& result) LLVM_OVERRIDE;
+
+ private:
+ Replacements* const replacements_;
+};
+
+class EmptyStringConverter {
+ public:
+ explicit EmptyStringConverter(Replacements* replacements)
+ : constructor_callback_(replacements),
+ initializer_callback_(replacements),
+ temporary_callback_(replacements) {}
+
+ void SetupMatchers(MatchFinder* match_finder);
+
+ private:
+ ConstructorCallback constructor_callback_;
+ InitializerCallback initializer_callback_;
+ TemporaryCallback temporary_callback_;
+};
+
+void EmptyStringConverter::SetupMatchers(MatchFinder* match_finder) {
+ const char kPattern[] = "^::(scoped_ptr|scoped_ptr_malloc)$";
+ const clang::ast_matchers::StatementMatcher& constructor_call = id(
+ "call",
+ constructExpr(hasDeclaration(methodDecl(ofClass(matchesName(kPattern)))),
+ argumentCountIs(1),
+ hasArgument(0, id("arg", expr())),
+ unless(hasArgument(0, defaultArgExpr()))));
+
+ match_finder->addMatcher(varDecl(forEach(constructor_call)),
+ &constructor_callback_);
+ match_finder->addMatcher(newExpr(has(constructor_call)),
+ &constructor_callback_);
+ match_finder->addMatcher(bindTemporaryExpr(has(constructor_call)),
+ &temporary_callback_);
+ match_finder->addMatcher(constructorDecl(forEach(constructor_call)),
+ &initializer_callback_);
+}
+
+void ConstructorCallback::run(const MatchFinder::MatchResult& result) {
+ const clang::Expr* arg = result.Nodes.getNodeAs<clang::Expr>("arg");
+ if (!IsNullConstant(*arg, result.Context))
+ return;
+
+ const clang::CXXConstructExpr* call =
+ result.Nodes.getNodeAs<clang::CXXConstructExpr>("call");
+ clang::CharSourceRange range =
+ clang::CharSourceRange::getTokenRange(call->getParenRange());
+ replacements_->insert(Replacement(*result.SourceManager, range, ""));
+}
+
+void InitializerCallback::run(const MatchFinder::MatchResult& result) {
+ const clang::Expr* arg = result.Nodes.getNodeAs<clang::Expr>("arg");
+ if (!IsNullConstant(*arg, result.Context))
+ return;
+
+ const clang::CXXConstructExpr* call =
+ result.Nodes.getNodeAs<clang::CXXConstructExpr>("call");
+ replacements_->insert(Replacement(*result.SourceManager, call, ""));
+}
+
+void TemporaryCallback::run(const MatchFinder::MatchResult& result) {
+ const clang::Expr* arg = result.Nodes.getNodeAs<clang::Expr>("arg");
+ if (!IsNullConstant(*arg, result.Context))
+ return;
+
+ // TODO(dcheng): File a bug with clang. There should be an easier way to do
+ // this replacement, but getTokenRange(call->getParenRange()) and the obvious
+ // (but incorrect) arg both don't work. The former is presumably just buggy,
+ // while the latter probably has to do with the fact that NULL is actually a
+ // macro which expands to a built-in.
+ clang::SourceRange range = arg->getSourceRange();
+ clang::SourceRange expansion_range(
+ result.SourceManager->getExpansionLoc(range.getBegin()),
+ result.SourceManager->getExpansionLoc(range.getEnd()));
+ replacements_->insert(
+ Replacement(*result.SourceManager,
+ clang::CharSourceRange::getTokenRange(expansion_range),
+ ""));
+}
+
+} // namespace
+
+static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
+
+int main(int argc, const char* argv[]) {
+ CommonOptionsParser options(argc, argv);
+ clang::tooling::ClangTool tool(options.getCompilations(),
+ options.getSourcePathList());
+
+ Replacements replacements;
+ EmptyStringConverter converter(&replacements);
+ MatchFinder match_finder;
+ converter.SetupMatchers(&match_finder);
+
+ int result =
+ tool.run(clang::tooling::newFrontendActionFactory(&match_finder));
+ if (result != 0)
+ return result;
+
+ // Each replacement line should have the following format:
+ // r:<file path>:<offset>:<length>:<replacement text>
+ // Only the <replacement text> field can contain embedded ":" characters.
+ // TODO(dcheng): Use a more clever serialization.
+ llvm::outs() << "==== BEGIN EDITS ====\n";
+ for (Replacements::const_iterator it = replacements.begin();
+ it != replacements.end();
+ ++it) {
+ llvm::outs() << "r:" << it->getFilePath() << ":" << it->getOffset() << ":"
+ << it->getLength() << ":" << it->getReplacementText() << "\n";
+ }
+ llvm::outs() << "==== END EDITS ====\n";
+
+ return 0;
+}
diff --git a/chromium/tools/clang/scripts/package.sh b/chromium/tools/clang/scripts/package.sh
new file mode 100755
index 00000000000..582125b52f7
--- /dev/null
+++ b/chromium/tools/clang/scripts/package.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script will check out llvm and clang, and then package the results up
+# to a tgz file.
+
+THIS_DIR="$(dirname "${0}")"
+LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
+LLVM_BOOTSTRAP_DIR="${THIS_DIR}/../../../third_party/llvm-bootstrap"
+LLVM_BUILD_DIR="${THIS_DIR}/../../../third_party/llvm-build"
+LLVM_BIN_DIR="${LLVM_BUILD_DIR}/Release+Asserts/bin"
+LLVM_LIB_DIR="${LLVM_BUILD_DIR}/Release+Asserts/lib"
+
+echo "Diff in llvm:" | tee buildlog.txt
+svn stat "${LLVM_DIR}" 2>&1 | tee -a buildlog.txt
+svn diff "${LLVM_DIR}" 2>&1 | tee -a buildlog.txt
+echo "Diff in llvm/tools/clang:" | tee -a buildlog.txt
+svn stat "${LLVM_DIR}/tools/clang" 2>&1 | tee -a buildlog.txt
+svn diff "${LLVM_DIR}/tools/clang" 2>&1 | tee -a buildlog.txt
+echo "Diff in llvm/projects/compiler-rt:" | tee -a buildlog.txt
+svn stat "${LLVM_DIR}/projects/compiler-rt" 2>&1 | tee -a buildlog.txt
+svn diff "${LLVM_DIR}/projects/compiler-rt" 2>&1 | tee -a buildlog.txt
+
+echo "Starting build" | tee -a buildlog.txt
+
+set -ex
+
+# Do a clobber build.
+rm -rf "${LLVM_BOOTSTRAP_DIR}"
+rm -rf "${LLVM_BUILD_DIR}"
+"${THIS_DIR}"/update.sh --run-tests --bootstrap --force-local-build 2>&1 | \
+ tee -a buildlog.txt
+
+R=$("${LLVM_BIN_DIR}/clang" --version | \
+ sed -ne 's/clang version .*(trunk \([0-9]*\))/\1/p')
+
+PDIR=clang-$R
+rm -rf $PDIR
+mkdir $PDIR
+mkdir $PDIR/bin
+mkdir $PDIR/lib
+
+if [ "$(uname -s)" = "Darwin" ]; then
+ SO_EXT="dylib"
+else
+ SO_EXT="so"
+fi
+
+# Copy buildlog over.
+cp buildlog.txt $PDIR/
+
+# Copy clang into pdir, symlink clang++ to it.
+cp "${LLVM_BIN_DIR}/clang" $PDIR/bin/
+(cd $PDIR/bin && ln -sf clang clang++ && cd -)
+cp "${LLVM_BIN_DIR}/llvm-symbolizer" $PDIR/bin/
+
+# Copy plugins. Some of the dylibs are pretty big, so copy only the ones we
+# care about.
+cp "${LLVM_LIB_DIR}/libFindBadConstructs.${SO_EXT}" $PDIR/lib
+cp "${LLVM_LIB_DIR}/libprofile_rt.${SO_EXT}" $PDIR/lib
+
+# Copy built-in headers (lib/clang/3.2/include).
+# libcompiler-rt puts all kinds of libraries there too, but we want only ASan.
+if [ "$(uname -s)" = "Darwin" ]; then
+ # Keep only Release+Asserts/lib/clang/3.2/lib/darwin/libclang_rt.asan_osx.a
+ find "${LLVM_LIB_DIR}/clang" -type f -path '*lib/darwin*' | grep -v asan | \
+ xargs rm
+ # Fix LC_ID_DYLIB for the ASan dynamic library to be relative to
+ # @executable_path.
+ # TODO(glider): this is transitional. We'll need to fix the dylib name
+ # either in our build system, or in Clang. See also http://crbug.com/170629.
+ ASAN_DYLIB_NAME=libclang_rt.asan_osx_dynamic.dylib
+ ASAN_DYLIB=$(find "${LLVM_LIB_DIR}/clang" -type f -path "*${ASAN_DYLIB_NAME}")
+ install_name_tool -id @executable_path/${ASAN_DYLIB_NAME} "${ASAN_DYLIB}"
+else
+ # Keep only
+ # Release+Asserts/lib/clang/3.2/lib/linux/libclang_rt.{a,t,m}san-x86_64.a
+ # TODO(thakis): Make sure the 32bit version of ASan runtime is kept too once
+ # that's built. TSan and MSan runtimes exist only for 64 bits.
+ find "${LLVM_LIB_DIR}/clang" -type f -path '*lib/linux*' | \
+ grep -v "asan\|tsan\|msan" | xargs rm
+fi
+
+cp -R "${LLVM_LIB_DIR}/clang" $PDIR/lib
+
+tar zcf $PDIR.tgz -C $PDIR bin lib buildlog.txt
+
+if [ "$(uname -s)" = "Darwin" ]; then
+ PLATFORM=Mac
+else
+ PLATFORM=Linux_x64
+fi
+
+echo To upload, run:
+echo gsutil cp -a public-read $PDIR.tgz \
+ gs://chromium-browser-clang/$PLATFORM/$PDIR.tgz
diff --git a/chromium/tools/clang/scripts/plugin_flags.sh b/chromium/tools/clang/scripts/plugin_flags.sh
new file mode 100755
index 00000000000..0d8dea566bf
--- /dev/null
+++ b/chromium/tools/clang/scripts/plugin_flags.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script returns the flags that should be used when GYP_DEFINES contains
+# clang_use_chrome_plugins. The flags are stored in a script so that they can
+# be changed on the bots without requiring a master restart.
+
+THIS_ABS_DIR=$(cd $(dirname $0) && echo $PWD)
+CLANG_LIB_PATH=$THIS_ABS_DIR/../../../third_party/llvm-build/Release+Asserts/lib
+
+if uname -s | grep -q Darwin; then
+ LIBSUFFIX=dylib
+else
+ LIBSUFFIX=so
+fi
+
+echo -Xclang -load -Xclang $CLANG_LIB_PATH/libFindBadConstructs.$LIBSUFFIX \
+ -Xclang -add-plugin -Xclang find-bad-constructs
diff --git a/chromium/tools/clang/scripts/run_tool.py b/chromium/tools/clang/scripts/run_tool.py
new file mode 100755
index 00000000000..903235d43db
--- /dev/null
+++ b/chromium/tools/clang/scripts/run_tool.py
@@ -0,0 +1,303 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Wrapper script to help run clang tools across Chromium code.
+
+How to use this tool:
+If you want to run the tool across all Chromium code:
+run_tool.py <tool> <path/to/compiledb>
+
+If you only want to run the tool across just chrome/browser and content/browser:
+run_tool.py <tool> <path/to/compiledb> chrome/browser content/browser
+
+Please see https://code.google.com/p/chromium/wiki/ClangToolRefactoring for more
+information, which documents the entire automated refactoring flow in Chromium.
+
+Why use this tool:
+The clang tool implementation doesn't take advantage of multiple cores, and if
+it fails mysteriously in the middle, all the generated replacements will be
+lost.
+
+Unfortunately, if the work is simply sharded across multiple cores by running
+multiple RefactoringTools, problems arise when they attempt to rewrite a file at
+the same time. To work around that, clang tools that are run using this tool
+should output edits to stdout in the following format:
+
+==== BEGIN EDITS ====
+r:<file path>:<offset>:<length>:<replacement text>
+r:<file path>:<offset>:<length>:<replacement text>
+...etc...
+==== END EDITS ====
+
+Any generated edits are applied once the clang tool has finished running
+across Chromium, regardless of whether some instances failed or not.
+"""
+
+import collections
+import functools
+import multiprocessing
+import os.path
+import subprocess
+import sys
+
+
+Edit = collections.namedtuple(
+ 'Edit', ('edit_type', 'offset', 'length', 'replacement'))
+
+
+def _GetFilesFromGit(paths = None):
+ """Gets the list of files in the git repository.
+
+ Args:
+ paths: Prefix filter for the returned paths. May contain multiple entries.
+ """
+ args = ['git', 'ls-files']
+ if paths:
+ args.extend(paths)
+ command = subprocess.Popen(args, stdout=subprocess.PIPE)
+ output, _ = command.communicate()
+ return output.splitlines()
+
+
+def _ExtractEditsFromStdout(build_directory, stdout):
+ """Extracts generated list of edits from the tool's stdout.
+
+ The expected format is documented at the top of this file.
+
+ Args:
+ build_directory: Directory that contains the compile database. Used to
+ normalize the filenames.
+ stdout: The stdout from running the clang tool.
+
+ Returns:
+ A dictionary mapping filenames to the associated edits.
+ """
+ lines = stdout.splitlines()
+ start_index = lines.index('==== BEGIN EDITS ====')
+ end_index = lines.index('==== END EDITS ====')
+ edits = collections.defaultdict(list)
+ for line in lines[start_index + 1:end_index]:
+ try:
+ edit_type, path, offset, length, replacement = line.split(':', 4)
+ # Normalize the file path emitted by the clang tool to be relative to the
+ # current working directory.
+ path = os.path.relpath(os.path.join(build_directory, path))
+ edits[path].append(Edit(edit_type, int(offset), int(length), replacement))
+ except ValueError:
+ print 'Unable to parse edit: %s' % line
+ return edits
+
+
+def _ExecuteTool(toolname, build_directory, filename):
+ """Executes the tool.
+
+ This is defined outside the class so it can be pickled for the multiprocessing
+ module.
+
+ Args:
+ toolname: Path to the tool to execute.
+ build_directory: Directory that contains the compile database.
+ filename: The file to run the tool over.
+
+ Returns:
+ A dictionary that must contain the key "status" and a boolean value
+ associated with it.
+
+ If status is True, then the generated edits are stored with the key "edits"
+ in the dictionary.
+
+ Otherwise, the filename and the output from stderr are associated with the
+ keys "filename" and "stderr" respectively.
+ """
+ command = subprocess.Popen((toolname, '-p', build_directory, filename),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = command.communicate()
+ if command.returncode != 0:
+ return {'status': False, 'filename': filename, 'stderr': stderr}
+ else:
+ return {'status': True,
+ 'edits': _ExtractEditsFromStdout(build_directory, stdout)}
+
+
+class _CompilerDispatcher(object):
+ """Multiprocessing controller for running clang tools in parallel."""
+
+ def __init__(self, toolname, build_directory, filenames):
+ """Initializer method.
+
+ Args:
+ toolname: Path to the tool to execute.
+ build_directory: Directory that contains the compile database.
+ filenames: The files to run the tool over.
+ """
+ self.__toolname = toolname
+ self.__build_directory = build_directory
+ self.__filenames = filenames
+ self.__success_count = 0
+ self.__failed_count = 0
+ self.__edits = collections.defaultdict(list)
+
+ @property
+ def edits(self):
+ return self.__edits
+
+ @property
+ def failed_count(self):
+ return self.__failed_count
+
+ def Run(self):
+ """Does the grunt work."""
+ pool = multiprocessing.Pool()
+ result_iterator = pool.imap_unordered(
+ functools.partial(_ExecuteTool, self.__toolname,
+ self.__build_directory),
+ self.__filenames)
+ for result in result_iterator:
+ self.__ProcessResult(result)
+ sys.stdout.write('\n')
+ sys.stdout.flush()
+
+ def __ProcessResult(self, result):
+ """Handles result processing.
+
+ Args:
+ result: The result dictionary returned by _ExecuteTool.
+ """
+ if result['status']:
+ self.__success_count += 1
+ for k, v in result['edits'].iteritems():
+ self.__edits[k].extend(v)
+ else:
+ self.__failed_count += 1
+ sys.stdout.write('\nFailed to process %s\n' % result['filename'])
+ sys.stdout.write(result['stderr'])
+ sys.stdout.write('\n')
+ percentage = (
+ float(self.__success_count + self.__failed_count) /
+ len(self.__filenames)) * 100
+ sys.stdout.write('Succeeded: %d, Failed: %d [%.2f%%]\r' % (
+ self.__success_count, self.__failed_count, percentage))
+ sys.stdout.flush()
+
+
+def _ApplyEdits(edits, clang_format_diff_path):
+ """Apply the generated edits.
+
+ Args:
+ edits: A dict mapping filenames to Edit instances that apply to that file.
+ clang_format_diff_path: Path to the clang-format-diff.py helper to help
+ automatically reformat diffs to avoid style violations. Pass None if the
+ clang-format step should be skipped.
+ """
+ edit_count = 0
+ for k, v in edits.iteritems():
+ # Sort the edits and iterate through them in reverse order. Sorting allows
+ # duplicate edits to be quickly skipped, while reversing means that
+ # subsequent edits don't need to have their offsets updated with each edit
+ # applied.
+ v.sort()
+ last_edit = None
+ with open(k, 'rb+') as f:
+ contents = bytearray(f.read())
+ for edit in reversed(v):
+ if edit == last_edit:
+ continue
+ last_edit = edit
+ contents[edit.offset:edit.offset + edit.length] = edit.replacement
+ if not edit.replacement:
+ _ExtendDeletionIfElementIsInList(contents, edit.offset)
+ edit_count += 1
+ f.seek(0)
+ f.truncate()
+ f.write(contents)
+ if clang_format_diff_path:
+ if subprocess.call('git diff -U0 %s | python %s -style=Chromium' % (
+ k, clang_format_diff_path), shell=True) != 0:
+ print 'clang-format failed for %s' % k
+ print 'Applied %d edits to %d files' % (edit_count, len(edits))
+
+
+_WHITESPACE_BYTES = frozenset((ord('\t'), ord('\n'), ord('\r'), ord(' ')))
+
+
+def _ExtendDeletionIfElementIsInList(contents, offset):
+ """Extends the range of a deletion if the deleted element was part of a list.
+
+ This rewriter helper makes it easy for refactoring tools to remove elements
+ from a list. Even if a matcher callback knows that it is removing an element
+ from a list, it may not have enough information to accurately remove the list
+ element; for example, another matcher callback may end up removing an adjacent
+ list element, or all the list elements may end up being removed.
+
+ With this helper, refactoring tools can simply remove the list element and not
+ worry about having to include the comma in the replacement.
+
+ Args:
+ contents: A bytearray with the deletion already applied.
+ offset: The offset in the bytearray where the deleted range used to be.
+ """
+ char_before = char_after = None
+ left_trim_count = 0
+ for byte in reversed(contents[:offset]):
+ left_trim_count += 1
+ if byte in _WHITESPACE_BYTES:
+ continue
+ if byte in (ord(','), ord(':'), ord('('), ord('{')):
+ char_before = chr(byte)
+ break
+
+ right_trim_count = 0
+ for byte in contents[offset:]:
+ right_trim_count += 1
+ if byte in _WHITESPACE_BYTES:
+ continue
+ if byte == ord(','):
+ char_after = chr(byte)
+ break
+
+ if char_before:
+ if char_after:
+ del contents[offset:offset + right_trim_count]
+ elif char_before in (',', ':'):
+ del contents[offset - left_trim_count:offset]
+
+
+def main(argv):
+ if len(argv) < 2:
+ print 'Usage: run_tool.py <clang tool> <compile DB> <path 1> <path 2> ...'
+ print ' <clang tool> is the clang tool that should be run.'
+ print ' <compile db> is the directory that contains the compile database'
+ print ' <path 1> <path2> ... can be used to filter what files are edited'
+ return 1
+
+ clang_format_diff_path = os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ '../../../third_party/llvm/tools/clang/tools/clang-format',
+ 'clang-format-diff.py')
+ # TODO(dcheng): Allow this to be controlled with a flag as well.
+ if not os.path.isfile(clang_format_diff_path):
+ clang_format_diff_path = None
+
+ filenames = frozenset(_GetFilesFromGit(argv[2:]))
+ # Filter out files that aren't C/C++/Obj-C/Obj-C++.
+ extensions = frozenset(('.c', '.cc', '.m', '.mm'))
+ dispatcher = _CompilerDispatcher(argv[0], argv[1],
+ [f for f in filenames
+ if os.path.splitext(f)[1] in extensions])
+ dispatcher.Run()
+ # Filter out edits to files that aren't in the git repository, since it's not
+ # useful to modify files that aren't under source control--typically, these
+ # are generated files or files in a git submodule that's not part of Chromium.
+ _ApplyEdits({k : v for k, v in dispatcher.edits.iteritems()
+ if k in filenames},
+ clang_format_diff_path)
+ if dispatcher.failed_count != 0:
+ return 2
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/clang/scripts/test_tool.py b/chromium/tools/clang/scripts/test_tool.py
new file mode 100755
index 00000000000..a99e9f48ae3
--- /dev/null
+++ b/chromium/tools/clang/scripts/test_tool.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Test harness for chromium clang tools."""
+
+import difflib
+import glob
+import json
+import os
+import os.path
+import subprocess
+import shutil
+import sys
+
+
+def _GenerateCompileCommands(files, include_paths):
+ """Returns a JSON string containing a compilation database for the input."""
+ include_path_flags = ''.join('-I %s' % include_path
+ for include_path in include_paths)
+ return json.dumps([{'directory': '.',
+ 'command': 'clang++ -fsyntax-only %s -c %s' % (
+ include_path_flags, f),
+ 'file': f} for f in files], indent=2)
+
+
+def _NumberOfTestsToString(tests):
+ """Returns an English describing the number of tests."""
+ return "%d test%s" % (tests, 's' if tests != 1 else '')
+
+
+def main(argv):
+ if len(argv) < 1:
+ print 'Usage: test_tool.py <clang tool>'
+ print ' <clang tool> is the clang tool to be tested.'
+ sys.exit(1)
+
+ tool_to_test = argv[0]
+ tools_clang_scripts_directory = os.path.dirname(os.path.realpath(__file__))
+ tools_clang_directory = os.path.dirname(tools_clang_scripts_directory)
+ test_directory_for_tool = os.path.join(
+ tools_clang_directory, tool_to_test, 'tests')
+ compile_database = os.path.join(test_directory_for_tool,
+ 'compile_commands.json')
+ source_files = glob.glob(os.path.join(test_directory_for_tool,
+ '*-original.cc'))
+ actual_files = ['-'.join([source_file.rsplit('-', 2)[0], 'actual.cc'])
+ for source_file in source_files]
+ expected_files = ['-'.join([source_file.rsplit('-', 2)[0], 'expected.cc'])
+ for source_file in source_files]
+ include_paths = []
+ include_paths.append(
+ os.path.realpath(os.path.join(tools_clang_directory, '../..')))
+
+ try:
+ # Set up the test environment.
+ for source, actual in zip(source_files, actual_files):
+ shutil.copyfile(source, actual)
+ # Stage the test files in the git index. If they aren't staged, then
+ # run_tools.py will skip them when applying replacements.
+ args = ['git', 'add']
+ args.extend(actual_files)
+ subprocess.check_call(args)
+ # Generate a temporary compilation database to run the tool over.
+ with open(compile_database, 'w') as f:
+ f.write(_GenerateCompileCommands(actual_files, include_paths))
+
+ args = ['python',
+ os.path.join(tools_clang_scripts_directory, 'run_tool.py'),
+ tool_to_test,
+ test_directory_for_tool]
+ args.extend(actual_files)
+ run_tool = subprocess.Popen(args, stdout=subprocess.PIPE)
+ stdout, _ = run_tool.communicate()
+ if run_tool.returncode != 0:
+ print 'run_tool failed:\n%s' % stdout
+ sys.exit(1)
+
+ passed = 0
+ failed = 0
+ for expected, actual in zip(expected_files, actual_files):
+ print '[ RUN ] %s' % os.path.relpath(actual)
+ expected_output = actual_output = None
+ with open(expected, 'r') as f:
+ expected_output = f.readlines()
+ with open(actual, 'r') as f:
+ actual_output = f.readlines()
+ if actual_output != expected_output:
+ print '[ FAILED ] %s' % os.path.relpath(actual)
+ failed += 1
+ for line in difflib.unified_diff(expected_output, actual_output,
+ fromfile=os.path.relpath(expected),
+ tofile=os.path.relpath(actual)):
+ sys.stdout.write(line)
+ # Don't clean up the file on failure, so the results can be referenced
+ # more easily.
+ continue
+ print '[ OK ] %s' % os.path.relpath(actual)
+ passed += 1
+ os.remove(actual)
+
+ if failed == 0:
+ os.remove(compile_database)
+
+ print '[==========] %s ran.' % _NumberOfTestsToString(len(source_files))
+ if passed > 0:
+ print '[ PASSED ] %s.' % _NumberOfTestsToString(passed)
+ if failed > 0:
+ print '[ FAILED ] %s.' % _NumberOfTestsToString(failed)
+ finally:
+ # No matter what, unstage the git changes we made earlier to avoid polluting
+ # the index.
+ args = ['git', 'reset', '--quiet', 'HEAD']
+ args.extend(actual_files)
+ subprocess.call(args)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/clang/scripts/update.py b/chromium/tools/clang/scripts/update.py
new file mode 100755
index 00000000000..bdc781f715b
--- /dev/null
+++ b/chromium/tools/clang/scripts/update.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Windows can't run .sh files, so this is a small python wrapper around
+update.sh.
+"""
+
+import os
+import subprocess
+import sys
+
+
+def main():
+ if sys.platform in ['win32', 'cygwin']:
+ return 0
+
+ # This script is called by gclient. gclient opens its hooks subprocesses with
+ # (stdout=subprocess.PIPE, stderr=subprocess.STDOUT) and then does custom
+ # output processing that breaks printing '\r' characters for single-line
+ # updating status messages as printed by curl and wget.
+ # Work around this by setting stderr of the update.sh process to stdin (!):
+ # gclient doesn't redirect stdin, and while stdin itself is read-only, a
+ # dup()ed sys.stdin is writable, try
+ # fd2 = os.dup(sys.stdin.fileno()); os.write(fd2, 'hi')
+ # TODO: Fix gclient instead, http://crbug.com/95350
+ return subprocess.call(
+ [os.path.join(os.path.dirname(__file__), 'update.sh')] + sys.argv[1:],
+ stderr=os.fdopen(os.dup(sys.stdin.fileno())))
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/clang/scripts/update.sh b/chromium/tools/clang/scripts/update.sh
new file mode 100755
index 00000000000..ea6f2b21b3d
--- /dev/null
+++ b/chromium/tools/clang/scripts/update.sh
@@ -0,0 +1,350 @@
+#!/usr/bin/env bash
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script will check out llvm and clang into third_party/llvm and build it.
+
+# Do NOT CHANGE this if you don't know what you're doing -- see
+# https://code.google.com/p/chromium/wiki/UpdatingClang
+# Reverting problematic clang rolls is safe, though.
+CLANG_REVISION=186332
+
+THIS_DIR="$(dirname "${0}")"
+LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
+LLVM_BUILD_DIR="${LLVM_DIR}/../llvm-build"
+LLVM_BOOTSTRAP_DIR="${LLVM_DIR}/../llvm-bootstrap"
+CLANG_DIR="${LLVM_DIR}/tools/clang"
+CLANG_TOOLS_EXTRA_DIR="${CLANG_DIR}/tools/extra"
+COMPILER_RT_DIR="${LLVM_DIR}/projects/compiler-rt"
+ANDROID_NDK_DIR="${LLVM_DIR}/../android_tools/ndk"
+STAMP_FILE="${LLVM_BUILD_DIR}/cr_build_revision"
+
+# ${A:-a} returns $A if it's set, a else.
+LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project}
+
+# Die if any command dies.
+set -e
+
+OS="$(uname -s)"
+
+# Parse command line options.
+force_local_build=
+mac_only=
+run_tests=
+bootstrap=
+with_android=yes
+chrome_tools="plugins"
+
+if [[ "${OS}" = "Darwin" ]]; then
+ with_android=
+fi
+
+while [[ $# > 0 ]]; do
+ case $1 in
+ --bootstrap)
+ bootstrap=yes
+ ;;
+ --force-local-build)
+ force_local_build=yes
+ ;;
+ --mac-only)
+ mac_only=yes
+ ;;
+ --run-tests)
+ run_tests=yes
+ ;;
+ --without-android)
+ with_android=
+ ;;
+ --with-chrome-tools)
+ shift
+ if [[ $# == 0 ]]; then
+ echo "--with-chrome-tools requires an argument."
+ exit 1
+ fi
+ chrome_tools=$1
+ ;;
+ --help)
+ echo "usage: $0 [--force-local-build] [--mac-only] [--run-tests] "
+ echo "--bootstrap: First build clang with CC, then with itself."
+ echo "--force-local-build: Don't try to download prebuilt binaries."
+ echo "--mac-only: Do initial download only on Mac systems."
+ echo "--run-tests: Run tests after building. Only for local builds."
+ echo "--without-android: Don't build ASan Android runtime library."
+ echo "--with-chrome-tools: Select which chrome tools to build." \
+ "Defaults to plugins."
+ echo " Example: --with-chrome-tools 'plugins empty-string'"
+ echo
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+# --mac-only prevents the initial download on non-mac systems, but if clang has
+# already been downloaded in the past, this script keeps it up to date even if
+# --mac-only is passed in and the system isn't a mac. People who don't like this
+# can just delete their third_party/llvm-build directory.
+if [[ -n "$mac_only" ]] && [[ "${OS}" != "Darwin" ]] &&
+ [[ ! ( "$GYP_DEFINES" =~ .*(clang|tsan|asan)=1.* ) ]] &&
+ ! [[ -d "${LLVM_BUILD_DIR}" ]]; then
+ exit 0
+fi
+
+# Xcode and clang don't get along when predictive compilation is enabled.
+# http://crbug.com/96315
+if [[ "${OS}" = "Darwin" ]] && xcodebuild -version | grep -q 'Xcode 3.2' ; then
+ XCONF=com.apple.Xcode
+ if [[ "${GYP_GENERATORS}" != "make" ]] && \
+ [ "$(defaults read "${XCONF}" EnablePredictiveCompilation)" != "0" ]; then
+ echo
+ echo " HEARKEN!"
+ echo "You're using Xcode3 and you have 'Predictive Compilation' enabled."
+ echo "This does not work well with clang (http://crbug.com/96315)."
+ echo "Disable it in Preferences->Building (lower right), or run"
+ echo " defaults write ${XCONF} EnablePredictiveCompilation -boolean NO"
+ echo "while Xcode is not running."
+ echo
+ fi
+
+ SUB_VERSION=$(xcodebuild -version | sed -Ene 's/Xcode 3\.2\.([0-9]+)/\1/p')
+ if [[ "${SUB_VERSION}" < 6 ]]; then
+ echo
+ echo " YOUR LD IS BUGGY!"
+ echo "Please upgrade Xcode to at least 3.2.6."
+ echo
+ fi
+fi
+
+
+# Check if there's anything to be done, exit early if not.
+if [[ -f "${STAMP_FILE}" ]]; then
+ PREVIOUSLY_BUILT_REVISON=$(cat "${STAMP_FILE}")
+ if [[ -z "$force_local_build" ]] && \
+ [[ "${PREVIOUSLY_BUILT_REVISON}" = "${CLANG_REVISION}" ]]; then
+ echo "Clang already at ${CLANG_REVISION}"
+ exit 0
+ fi
+fi
+# To always force a new build if someone interrupts their build half way.
+rm -f "${STAMP_FILE}"
+
+# Clobber pch files, since they only work with the compiler version that
+# created them. Also clobber .o files, to make sure everything will be built
+# with the new compiler.
+if [[ "${OS}" = "Darwin" ]]; then
+ XCODEBUILD_DIR="${THIS_DIR}/../../../xcodebuild"
+
+ # Xcode groups .o files by project first, configuration second.
+ if [[ -d "${XCODEBUILD_DIR}" ]]; then
+ echo "Clobbering .o files for Xcode build"
+ find "${XCODEBUILD_DIR}" -name '*.o' -exec rm {} +
+ fi
+fi
+
+MAKE_DIR="${THIS_DIR}/../../../out"
+
+for CONFIG in Debug Release; do
+ if [[ -d "${MAKE_DIR}/${CONFIG}/obj.target" ||
+ -d "${MAKE_DIR}/${CONFIG}/obj.host" ]]; then
+ echo "Clobbering ${CONFIG} PCH and .o files for make build"
+ if [[ -d "${MAKE_DIR}/${CONFIG}/obj.target" ]]; then
+ find "${MAKE_DIR}/${CONFIG}/obj.target" -name '*.gch' -exec rm {} +
+ find "${MAKE_DIR}/${CONFIG}/obj.target" -name '*.o' -exec rm {} +
+ fi
+ if [[ -d "${MAKE_DIR}/${CONFIG}/obj.host" ]]; then
+ find "${MAKE_DIR}/${CONFIG}/obj.host" -name '*.o' -exec rm {} +
+ fi
+ fi
+
+ # ninja puts its output below ${MAKE_DIR} as well.
+ if [[ -d "${MAKE_DIR}/${CONFIG}/obj" ]]; then
+ echo "Clobbering ${CONFIG} PCH and .o files for ninja build"
+ find "${MAKE_DIR}/${CONFIG}/obj" -name '*.gch' -exec rm {} +
+ find "${MAKE_DIR}/${CONFIG}/obj" -name '*.o' -exec rm {} +
+ find "${MAKE_DIR}/${CONFIG}/obj" -name '*.o.d' -exec rm {} +
+ fi
+
+ if [[ "${OS}" = "Darwin" ]]; then
+ if [[ -d "${XCODEBUILD_DIR}/${CONFIG}/SharedPrecompiledHeaders" ]]; then
+ echo "Clobbering ${CONFIG} PCH files for Xcode build"
+ rm -rf "${XCODEBUILD_DIR}/${CONFIG}/SharedPrecompiledHeaders"
+ fi
+ fi
+done
+
+# Clobber NaCl toolchain stamp files, see http://crbug.com/159793
+if [[ -d "${MAKE_DIR}" ]]; then
+ find "${MAKE_DIR}" -name 'stamp.untar' -exec rm {} +
+fi
+if [[ "${OS}" = "Darwin" ]]; then
+ if [[ -d "${XCODEBUILD_DIR}" ]]; then
+ find "${XCODEBUILD_DIR}" -name 'stamp.untar' -exec rm {} +
+ fi
+fi
+
+if [[ -z "$force_local_build" ]]; then
+ # Check if there's a prebuilt binary and if so just fetch that. That's faster,
+ # and goma relies on having matching binary hashes on client and server too.
+ CDS_URL=https://commondatastorage.googleapis.com/chromium-browser-clang
+ CDS_FILE="clang-${CLANG_REVISION}.tgz"
+ CDS_OUT_DIR=$(mktemp -d -t clang_download.XXXXXX)
+ CDS_OUTPUT="${CDS_OUT_DIR}/${CDS_FILE}"
+ if [ "${OS}" = "Linux" ]; then
+ CDS_FULL_URL="${CDS_URL}/Linux_x64/${CDS_FILE}"
+ elif [ "${OS}" = "Darwin" ]; then
+ CDS_FULL_URL="${CDS_URL}/Mac/${CDS_FILE}"
+ fi
+ echo Trying to download prebuilt clang
+ if which curl > /dev/null; then
+ curl -L --fail "${CDS_FULL_URL}" -o "${CDS_OUTPUT}" || \
+ rm -rf "${CDS_OUT_DIR}"
+ elif which wget > /dev/null; then
+ wget "${CDS_FULL_URL}" -O "${CDS_OUTPUT}" || rm -rf "${CDS_OUT_DIR}"
+ else
+ echo "Neither curl nor wget found. Please install one of these."
+ exit 1
+ fi
+ if [ -f "${CDS_OUTPUT}" ]; then
+ rm -rf "${LLVM_BUILD_DIR}/Release+Asserts"
+ mkdir -p "${LLVM_BUILD_DIR}/Release+Asserts"
+ tar -xzf "${CDS_OUTPUT}" -C "${LLVM_BUILD_DIR}/Release+Asserts"
+ echo clang "${CLANG_REVISION}" unpacked
+ echo "${CLANG_REVISION}" > "${STAMP_FILE}"
+ rm -rf "${CDS_OUT_DIR}"
+ exit 0
+ else
+ echo Did not find prebuilt clang at r"${CLANG_REVISION}", building
+ fi
+fi
+
+if [[ -n "${with_android}" ]] && ! [[ -d "${ANDROID_NDK_DIR}" ]]; then
+ echo "Android NDK not found at ${ANDROID_NDK_DIR}"
+ echo "The Android NDK is needed to build a Clang whose -fsanitize=address"
+ echo "works on Android. See "
+ echo "http://code.google.com/p/chromium/wiki/AndroidBuildInstructions for how"
+ echo "to install the NDK, or pass --without-android."
+ exit 1
+fi
+
+echo Getting LLVM r"${CLANG_REVISION}" in "${LLVM_DIR}"
+if ! svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" \
+ "${LLVM_DIR}"; then
+ echo Checkout failed, retrying
+ rm -rf "${LLVM_DIR}"
+ svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" "${LLVM_DIR}"
+fi
+
+echo Getting clang r"${CLANG_REVISION}" in "${CLANG_DIR}"
+svn co --force "${LLVM_REPO_URL}/cfe/trunk@${CLANG_REVISION}" "${CLANG_DIR}"
+
+echo Getting compiler-rt r"${CLANG_REVISION}" in "${COMPILER_RT_DIR}"
+svn co --force "${LLVM_REPO_URL}/compiler-rt/trunk@${CLANG_REVISION}" \
+ "${COMPILER_RT_DIR}"
+
+# Echo all commands.
+set -x
+
+NUM_JOBS=3
+if [[ "${OS}" = "Linux" ]]; then
+ NUM_JOBS="$(grep -c "^processor" /proc/cpuinfo)"
+elif [ "${OS}" = "Darwin" ]; then
+ NUM_JOBS="$(sysctl -n hw.ncpu)"
+fi
+
+# Build bootstrap clang if requested.
+if [[ -n "${bootstrap}" ]]; then
+ echo "Building bootstrap compiler"
+ mkdir -p "${LLVM_BOOTSTRAP_DIR}"
+ cd "${LLVM_BOOTSTRAP_DIR}"
+ if [[ ! -f ./config.status ]]; then
+ # The bootstrap compiler only needs to be able to build the real compiler,
+ # so it needs no cross-compiler output support. In general, the host
+ # compiler should be as similar to the final compiler as possible, so do
+ # keep --disable-threads & co.
+ ../llvm/configure \
+ --enable-optimized \
+ --enable-targets=host-only \
+ --disable-threads \
+ --disable-pthreads \
+ --without-llvmgcc \
+ --without-llvmgxx
+ fi
+ MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}"
+ if [[ -n "${run_tests}" ]]; then
+ make check-all
+ fi
+ cd -
+ export CC="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang"
+ export CXX="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang++"
+ echo "Building final compiler"
+fi
+
+# Build clang (in a separate directory).
+# The clang bots have this path hardcoded in built/scripts/slave/compile.py,
+# so if you change it you also need to change these links.
+mkdir -p "${LLVM_BUILD_DIR}"
+cd "${LLVM_BUILD_DIR}"
+if [[ ! -f ./config.status ]]; then
+ ../llvm/configure \
+ --enable-optimized \
+ --disable-threads \
+ --disable-pthreads \
+ --without-llvmgcc \
+ --without-llvmgxx
+fi
+
+MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}"
+STRIP_FLAGS=
+if [ "${OS}" = "Darwin" ]; then
+ # See http://crbug.com/256342
+ STRIP_FLAGS=-x
+fi
+strip ${STRIP_FLAGS} Release+Asserts/bin/clang
+cd -
+
+if [[ -n "${with_android}" ]]; then
+ # Make a standalone Android toolchain.
+ ${ANDROID_NDK_DIR}/build/tools/make-standalone-toolchain.sh \
+ --platform=android-14 \
+ --install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
+ --system=linux-x86_64 \
+ --stl=stlport
+
+ # Build ASan runtime for Android.
+ # Note: LLVM_ANDROID_TOOLCHAIN_DIR is not relative to PWD, but to where we
+ # build the runtime, i.e. third_party/llvm/projects/compiler-rt.
+ cd "${LLVM_BUILD_DIR}"
+ make -C tools/clang/runtime/ \
+ LLVM_ANDROID_TOOLCHAIN_DIR="../../../llvm-build/android-toolchain"
+ cd -
+fi
+
+# Build Chrome-specific clang tools. Paths in this list should be relative to
+# tools/clang.
+# For each tool directory, copy it into the clang tree and use clang's build
+# system to compile it.
+for CHROME_TOOL_DIR in ${chrome_tools}; do
+ TOOL_SRC_DIR="${THIS_DIR}/../${CHROME_TOOL_DIR}"
+ TOOL_DST_DIR="${LLVM_DIR}/tools/clang/tools/chrome-${CHROME_TOOL_DIR}"
+ TOOL_BUILD_DIR="${LLVM_BUILD_DIR}/tools/clang/tools/chrome-${CHROME_TOOL_DIR}"
+ rm -rf "${TOOL_DST_DIR}"
+ cp -R "${TOOL_SRC_DIR}" "${TOOL_DST_DIR}"
+ rm -rf "${TOOL_BUILD_DIR}"
+ mkdir -p "${TOOL_BUILD_DIR}"
+ cp "${TOOL_SRC_DIR}/Makefile" "${TOOL_BUILD_DIR}"
+ MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}" -C "${TOOL_BUILD_DIR}"
+done
+
+if [[ -n "$run_tests" ]]; then
+ # Run a few tests.
+ PLUGIN_SRC_DIR="${THIS_DIR}/../plugins"
+ "${PLUGIN_SRC_DIR}/tests/test.sh" "${LLVM_BUILD_DIR}/Release+Asserts"
+ cd "${LLVM_BUILD_DIR}"
+ make check-all
+ cd -
+fi
+
+# After everything is done, log success for this revision.
+echo "${CLANG_REVISION}" > "${STAMP_FILE}"
diff --git a/chromium/tools/code_coverage/coverage.py b/chromium/tools/code_coverage/coverage.py
new file mode 100755
index 00000000000..a1496d7418d
--- /dev/null
+++ b/chromium/tools/code_coverage/coverage.py
@@ -0,0 +1,359 @@
+#!/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Module to setup and generate code coverage data
+
+This module first sets up the environment for code coverage, instruments the
+binaries, runs the tests and collects the code coverage data.
+
+
+Usage:
+ coverage.py --upload=<upload_location>
+ --revision=<revision_number>
+ --src_root=<root_of_source_tree>
+ [--tools_path=<tools_path>]
+"""
+
+import logging
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+import google.logging_utils
+import google.process_utils as proc
+
+
+# The list of binaries that will be instrumented for code coverage
+# TODO(niranjan): Re-enable instrumentation of chrome.exe and chrome.dll once we
+# resolve the issue where vsinstr.exe is confused while reading symbols.
+windows_binaries = [#'chrome.exe',
+ #'chrome.dll',
+ 'unit_tests.exe',
+ 'automated_ui_tests.exe',
+ 'installer_util_unittests.exe',
+ 'ipc_tests.exe',
+ 'memory_test.exe',
+ 'page_cycler_tests.exe',
+ 'perf_tests.exe',
+ 'reliability_tests.exe',
+ 'security_tests.dll',
+ 'startup_tests.exe',
+ 'tab_switching_test.exe',
+ 'test_shell.exe']
+
+# The list of [tests, args] that will be run.
+# Failing tests have been commented out.
+# TODO(niranjan): Need to add layout tests that excercise the test shell.
+windows_tests = [
+ ['unit_tests.exe', ''],
+# ['automated_ui_tests.exe', ''],
+ ['installer_util_unittests.exe', ''],
+ ['ipc_tests.exe', ''],
+ ['page_cycler_tests.exe', '--gtest_filter=*File --no-sandbox'],
+ ['reliability_tests.exe', '--no-sandbox'],
+ ['startup_tests.exe', '--no-sandbox'],
+ ['tab_switching_test.exe', '--no-sandbox'],
+ ]
+
+
+def IsWindows():
+ """Checks if the current platform is Windows.
+ """
+ return sys.platform[:3] == 'win'
+
+
+class Coverage(object):
+ """Class to set up and generate code coverage.
+
+ This class contains methods that are useful to set up the environment for
+ code coverage.
+
+ Attributes:
+ instrumented: A boolean indicating if all the binaries have been
+ instrumented.
+ """
+
+ def __init__(self,
+ revision,
+ src_path = None,
+ tools_path = None,
+ archive=None):
+ """Init method for the Coverage class.
+
+ Args:
+ revision: Revision number of the Chromium source tree.
+ src_path: Location of the Chromium source base.
+ tools_path: Location of the Visual Studio Team Tools. (Win32 only)
+ archive: Archive location for the intermediate .coverage results.
+ """
+ google.logging_utils.config_root()
+ self.revision = revision
+ self.instrumented = False
+ self.tools_path = tools_path
+ self.src_path = src_path
+ self._dir = tempfile.mkdtemp()
+ self._archive = archive
+
+ def SetUp(self, binaries):
+ """Set up the platform specific environment and instrument the binaries for
+ coverage.
+
+ This method sets up the environment, instruments all the compiled binaries
+ and sets up the code coverage counters.
+
+ Args:
+ binaries: List of binaries that need to be instrumented.
+
+ Returns:
+ True on success.
+ False on error.
+ """
+ if self.instrumented:
+ logging.error('Binaries already instrumented')
+ return False
+ if IsWindows():
+ # Stop all previous instance of VSPerfMon counters
+ counters_command = ('%s -shutdown' %
+ (os.path.join(self.tools_path, 'vsperfcmd.exe')))
+ (retcode, output) = proc.RunCommandFull(counters_command,
+ collect_output=True)
+ # TODO(niranjan): Add a check that to verify that the binaries were built
+ # using the /PROFILE linker flag.
+ if self.tools_path == None:
+ logging.error('Could not locate Visual Studio Team Server tools')
+ return False
+ # Remove trailing slashes
+ self.tools_path = self.tools_path.rstrip('\\')
+ # Add this to the env PATH.
+ os.environ['PATH'] = os.environ['PATH'] + ';' + self.tools_path
+ instrument_command = '%s /COVERAGE ' % (os.path.join(self.tools_path,
+ 'vsinstr.exe'))
+ for binary in binaries:
+ logging.info('binary = %s' % (binary))
+ logging.info('instrument_command = %s' % (instrument_command))
+ # Instrument each binary in the list
+ binary = os.path.join(self.src_path, 'chrome', 'Release', binary)
+ (retcode, output) = proc.RunCommandFull(instrument_command + binary,
+ collect_output=True)
+ # Check if the file has been instrumented correctly.
+ if output.pop().rfind('Successfully instrumented') == -1:
+ logging.error('Error instrumenting %s' % (binary))
+ return False
+ # We are now ready to run tests and measure code coverage.
+ self.instrumented = True
+ return True
+
+ def TearDown(self):
+ """Tear down method.
+
+ This method shuts down the counters, and cleans up all the intermediate
+ artifacts.
+ """
+ if self.instrumented == False:
+ return
+
+ if IsWindows():
+ # Stop counters
+ counters_command = ('%s -shutdown' %
+ (os.path.join(self.tools_path, 'vsperfcmd.exe')))
+ (retcode, output) = proc.RunCommandFull(counters_command,
+ collect_output=True)
+ logging.info('Counters shut down: %s' % (output))
+ # TODO(niranjan): Revert the instrumented binaries to their original
+ # versions.
+ else:
+ return
+ if self._archive:
+ shutil.copytree(self._dir, os.path.join(self._archive, self.revision))
+ logging.info('Archived the .coverage files')
+ # Delete all the temp files and folders
+ if self._dir != None:
+ shutil.rmtree(self._dir, ignore_errors=True)
+ logging.info('Cleaned up temporary files and folders')
+ # Reset the instrumented flag.
+ self.instrumented = False
+
+ def RunTest(self, src_root, test):
+ """Run tests and collect the .coverage file
+
+ Args:
+ src_root: Path to the root of the source.
+ test: Path to the test to be run.
+
+ Returns:
+ Path of the intermediate .coverage file on success.
+ None on error.
+ """
+ # Generate the intermediate file name for the coverage results
+ test_name = os.path.split(test[0])[1].strip('.exe')
+ # test_command = binary + args
+ test_command = '%s %s' % (os.path.join(src_root,
+ 'chrome',
+ 'Release',
+ test[0]),
+ test[1])
+
+ coverage_file = os.path.join(self._dir, '%s_win32_%s.coverage' %
+ (test_name, self.revision))
+ logging.info('.coverage file for test %s: %s' % (test_name, coverage_file))
+
+ # After all the binaries have been instrumented, we start the counters.
+ counters_command = ('%s -start:coverage -output:%s' %
+ (os.path.join(self.tools_path, 'vsperfcmd.exe'),
+ coverage_file))
+ # Here we use subprocess.call() instead of the RunCommandFull because the
+ # VSPerfCmd spawns another process before terminating and this confuses
+ # the subprocess.Popen() used by RunCommandFull.
+ retcode = subprocess.call(counters_command)
+
+ # Run the test binary
+ logging.info('Executing test %s: ' % test_command)
+ (retcode, output) = proc.RunCommandFull(test_command, collect_output=True)
+ if retcode != 0: # Return error if the tests fail
+ logging.error('One or more tests failed in %s.' % test_command)
+ return None
+
+ # Stop the counters
+ counters_command = ('%s -shutdown' %
+ (os.path.join(self.tools_path, 'vsperfcmd.exe')))
+ (retcode, output) = proc.RunCommandFull(counters_command,
+ collect_output=True)
+ logging.info('Counters shut down: %s' % (output))
+ # Return the intermediate .coverage file
+ return coverage_file
+
+ def Upload(self, list_coverage, upload_path, sym_path=None, src_root=None):
+ """Upload the results to the dashboard.
+
+ This method uploads the coverage data to a dashboard where it will be
+ processed. On Windows, this method will first convert the .coverage file to
+ the lcov format. This method needs to be called before the TearDown method.
+
+ Args:
+ list_coverage: The list of coverage data files to consoliate and upload.
+ upload_path: Destination where the coverage data will be processed.
+ sym_path: Symbol path for the build (Win32 only)
+ src_root: Root folder of the source tree (Win32 only)
+
+ Returns:
+ True on success.
+ False on failure.
+ """
+ if upload_path == None:
+ logging.info('Upload path not specified. Will not convert to LCOV')
+ return True
+
+ if IsWindows():
+ # Stop counters
+ counters_command = ('%s -shutdown' %
+ (os.path.join(self.tools_path, 'vsperfcmd.exe')))
+ (retcode, output) = proc.RunCommandFull(counters_command,
+ collect_output=True)
+ logging.info('Counters shut down: %s' % (output))
+ lcov_file = os.path.join(upload_path, 'chrome_win32_%s.lcov' %
+ (self.revision))
+ lcov = open(lcov_file, 'w')
+ for coverage_file in list_coverage:
+ # Convert the intermediate .coverage file to lcov format
+ if self.tools_path == None:
+ logging.error('Lcov converter tool not found')
+ return False
+ self.tools_path = self.tools_path.rstrip('\\')
+ convert_command = ('%s -sym_path=%s -src_root=%s %s' %
+ (os.path.join(self.tools_path,
+ 'coverage_analyzer.exe'),
+ sym_path,
+ src_root,
+ coverage_file))
+ (retcode, output) = proc.RunCommandFull(convert_command,
+ collect_output=True)
+ # TODO(niranjan): Fix this to check for the correct return code.
+# if output != 0:
+# logging.error('Conversion to LCOV failed. Exiting.')
+ tmp_lcov_file = coverage_file + '.lcov'
+ logging.info('Conversion to lcov complete for %s' % (coverage_file))
+ # Now append this .lcov file to the cumulative lcov file
+ logging.info('Consolidating LCOV file: %s' % (tmp_lcov_file))
+ tmp_lcov = open(tmp_lcov_file, 'r')
+ lcov.write(tmp_lcov.read())
+ tmp_lcov.close()
+ lcov.close()
+ logging.info('LCOV file uploaded to %s' % (upload_path))
+
+
+def main():
+ # Command line parsing
+ parser = optparse.OptionParser()
+ # Path where the .coverage to .lcov converter tools are stored.
+ parser.add_option('-t',
+ '--tools_path',
+ dest='tools_path',
+ default=None,
+ help='Location of the coverage tools (windows only)')
+ parser.add_option('-u',
+ '--upload',
+ dest='upload_path',
+ default=None,
+ help='Location where the results should be uploaded')
+ # We need the revision number so that we can generate the output file of the
+ # format chrome_<platform>_<revision>.lcov
+ parser.add_option('-r',
+ '--revision',
+ dest='revision',
+ default=None,
+ help='Revision number of the Chromium source repo')
+ # Root of the source tree. Needed for converting the generated .coverage file
+ # on Windows to the open source lcov format.
+ parser.add_option('-s',
+ '--src_root',
+ dest='src_root',
+ default=None,
+ help='Root of the source repository')
+ parser.add_option('-a',
+ '--archive',
+ dest='archive',
+ default=None,
+ help='Archive location of the intermediate .coverage data')
+
+ (options, args) = parser.parse_args()
+
+ if options.revision == None:
+ parser.error('Revision number not specified')
+ if options.src_root == None:
+ parser.error('Source root not specified')
+
+ if IsWindows():
+ # Initialize coverage
+ cov = Coverage(options.revision,
+ options.src_root,
+ options.tools_path,
+ options.archive)
+ list_coverage = []
+ # Instrument the binaries
+ if cov.SetUp(windows_binaries):
+ # Run all the tests
+ for test in windows_tests:
+ coverage = cov.RunTest(options.src_root, test)
+ if coverage == None: # Indicate failure to the buildbots.
+ return 1
+ # Collect the intermediate file
+ list_coverage.append(coverage)
+ else:
+ logging.error('Error during instrumentation.')
+ sys.exit(1)
+
+ cov.Upload(list_coverage,
+ options.upload_path,
+ os.path.join(options.src_root, 'chrome', 'Release'),
+ options.src_root)
+ cov.TearDown()
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/code_coverage/coverage_posix.py b/chromium/tools/code_coverage/coverage_posix.py
new file mode 100755
index 00000000000..f4fa56caa10
--- /dev/null
+++ b/chromium/tools/code_coverage/coverage_posix.py
@@ -0,0 +1,1266 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generate and process code coverage.
+
+TODO(jrg): rename this from coverage_posix.py to coverage_all.py!
+
+Written for and tested on Mac, Linux, and Windows. To use this script
+to generate coverage numbers, please run from within a gyp-generated
+project.
+
+All platforms, to set up coverage:
+ cd ...../chromium ; src/tools/gyp/gyp_dogfood -Dcoverage=1 src/build/all.gyp
+
+Run coverage on...
+Mac:
+ ( cd src/chrome ; xcodebuild -configuration Debug -target coverage )
+Linux:
+ ( cd src/chrome ; hammer coverage )
+ # In particular, don't try and run 'coverage' from src/build
+
+
+--directory=DIR: specify directory that contains gcda files, and where
+ a "coverage" directory will be created containing the output html.
+ Example name: ..../chromium/src/xcodebuild/Debug.
+ If not specified (e.g. buildbot) we will try and figure it out based on
+ other options (e.g. --target and --build-dir; see below).
+
+--genhtml: generate html output. If not specified only lcov is generated.
+
+--all_unittests: if present, run all files named *_unittests that we
+ can find.
+
+--fast_test: make the tests run real fast (just for testing)
+
+--strict: if a test fails, we continue happily. --strict will cause
+ us to die immediately.
+
+--trim=False: by default we trim away tests known to be problematic on
+ specific platforms. If set to false we do NOT trim out tests.
+
+--xvfb=True: By default we use Xvfb to make sure DISPLAY is valid
+ (Linux only). if set to False, do not use Xvfb. TODO(jrg): convert
+ this script from the compile stage of a builder to a
+ RunPythonCommandInBuildDir() command to avoid the need for this
+ step.
+
+--timeout=SECS: if a subprocess doesn't have output within SECS,
+ assume it's a hang. Kill it and give up.
+
+--bundles=BUNDLEFILE: a file containing a python list of coverage
+ bundles to be eval'd. Example contents of the bundlefile:
+ ['../base/base.gyp:base_unittests']
+ This is used as part of the coverage bot.
+ If no other bundlefile-finding args are used (--target,
+ --build-dir), this is assumed to be an absolute path.
+ If those args are used, find BUNDLEFILE in a way consistent with
+ other scripts launched by buildbot. Example of another script
+ launched by buildbot:
+ http://src.chromium.org/viewvc/chrome/trunk/tools/buildbot/scripts/slave/runtest.py
+
+--target=NAME: specify the build target (e.g. 'Debug' or 'Release').
+ This is used by buildbot scripts to help us find the output directory.
+ Must be used with --build-dir.
+
+--build-dir=DIR: According to buildbot comments, this is the name of
+ the directory within the buildbot working directory in which the
+ solution, Debug, and Release directories are found.
+ It's usually "src/build", but on mac it's $DIR/../xcodebuild and on
+ Linux it's $DIR/out.
+ This is used by buildbot scripts to help us find the output directory.
+ Must be used with --target.
+
+--no_exclusions: Do NOT use the exclusion list. This script keeps a
+ list of tests known to be problematic under coverage. For example,
+ ProcessUtilTest.SpawnChild will crash inside __gcov_fork() when
+ using the MacOS 10.6 SDK. Use of --no_exclusions prevents the use
+ of this exclusion list.
+
+--dont-clear-coverage-data: Normally we clear coverage data from
+ previous runs. If this arg is used we do NOT clear the coverage
+ data.
+
+Strings after all options are considered tests to run. Test names
+have all text before a ':' stripped to help with gyp compatibility.
+For example, ../base/base.gyp:base_unittests is interpreted as a test
+named "base_unittests".
+"""
+
+import glob
+import logging
+import optparse
+import os
+import Queue
+import re
+import shutil
+import signal
+import subprocess
+import sys
+import tempfile
+import threading
+import time
+import traceback
+
+"""Global list of child PIDs to kill when we die."""
+gChildPIDs = []
+
+"""Exclusion list. Format is
+ { platform: { testname: (exclusion1, exclusion2, ... ), ... } }
+
+ Platform is a match for sys.platform and can be a list.
+ Matching code does an 'if sys.platform in (the key):'.
+ Similarly, matching does an 'if testname in thefulltestname:'
+
+ The Chromium convention has traditionally been to place the
+ exclusion list in a distinct file. Unlike valgrind (which has
+ frequent changes when things break and are fixed), the expectation
+ here is that exclusions remain relatively constant (e.g. OS bugs).
+ If that changes, revisit the decision to place inclusions in this
+ script.
+
+ Details:
+ ProcessUtilTest.SpawnChild: chokes in __gcov_fork on 10.6
+ IPCFuzzingTest.MsgBadPayloadArgs: ditto
+ PanelBrowserNavigatorTest.NavigateFromCrashedPanel: Fails on coverage bot.
+ WebGLConformanceTests.conformance_attribs_gl_enable_vertex_attrib: Fails
+ with timeout (45000 ms) exceeded error. crbug.com/143248
+ WebGLConformanceTests.conformance_attribs_gl_disabled_vertex_attrib:
+ ditto.
+ WebGLConformanceTests.conformance_attribs_gl_vertex_attrib_zero_issues:
+ ditto.
+ WebGLConformanceTests.conformance_attribs_gl_vertex_attrib: ditto.
+ WebGLConformanceTests.conformance_attribs_gl_vertexattribpointer_offsets:
+ ditto.
+ WebGLConformanceTests.conformance_attribs_gl_vertexattribpointer: ditto.
+ WebGLConformanceTests.conformance_buffers_buffer_bind_test: After
+ disabling WebGLConformanceTests specified above, this test fails when run
+ on local machine.
+ WebGLConformanceTests.conformance_buffers_buffer_data_array_buffer: ditto.
+ WebGLConformanceTests.conformance_buffers_index_validation_copies_indices:
+ ditto.
+ WebGLConformanceTests.
+ conformance_buffers_index_validation_crash_with_buffer_sub_data: ditto.
+ WebGLConformanceTests.
+ conformance_buffers_index_validation_verifies_too_many_indices: ditto.
+ WebGLConformanceTests.
+ conformance_buffers_index_validation_with_resized_buffer: ditto.
+ WebGLConformanceTests.conformance_canvas_buffer_offscreen_test: ditto.
+ WebGLConformanceTests.conformance_canvas_buffer_preserve_test: ditto.
+ WebGLConformanceTests.conformance_canvas_canvas_test: ditto.
+ WebGLConformanceTests.conformance_canvas_canvas_zero_size: ditto.
+ WebGLConformanceTests.
+ conformance_canvas_drawingbuffer_static_canvas_test: ditto.
+ WebGLConformanceTests.conformance_canvas_drawingbuffer_test: ditto.
+ PageCycler*.*: Fails on coverage bot with "Missing test directory
+ /....../slave/coverage-dbg-linux/build/src/data/page_cycler/moz" error.
+ *FrameRateCompositingTest.*: Fails with
+ "FATAL:chrome_content_browser_client.cc(893)] Check failed:
+ command_line->HasSwitch(switches::kEnableStatsTable)."
+ *FrameRateNoVsyncCanvasInternalTest.*: ditto.
+ *FrameRateGpuCanvasInternalTest.*: ditto.
+ IndexedDBTest.Perf: Fails with 'Timeout reached in WaitUntilCookieValue'
+ error.
+ TwoClientPasswordsSyncTest.DeleteAll: Fails on coverage bot.
+ MigrationTwoClientTest.MigrationHellWithoutNigori: Fails with timeout
+ (45000 ms) exceeded error.
+ TwoClientSessionsSyncTest.DeleteActiveSession: ditto.
+ MultipleClientSessionsSyncTest.EncryptedAndChanged: ditto.
+ MigrationSingleClientTest.AllTypesIndividuallyTriggerNotification: ditto.
+ *OldPanelResizeBrowserTest.*: crbug.com/143247
+ *OldPanelDragBrowserTest.*: ditto.
+ *OldPanelBrowserTest.*: ditto.
+ *OldPanelAndDesktopNotificationTest.*: ditto.
+ *OldDockedPanelBrowserTest.*: ditto.
+ *OldDetachedPanelBrowserTest.*: ditto.
+ PanelDragBrowserTest.AttachWithSqueeze: ditto.
+ *PanelBrowserTest.*: ditto.
+ *DockedPanelBrowserTest.*: ditto.
+ *DetachedPanelBrowserTest.*: ditto.
+ AutomatedUITest.TheOneAndOnlyTest: crbug.com/143419
+ AutomatedUITestBase.DragOut: ditto
+
+"""
+gTestExclusions = {
+ 'darwin2': { 'base_unittests': ('ProcessUtilTest.SpawnChild',),
+ 'ipc_tests': ('IPCFuzzingTest.MsgBadPayloadArgs',), },
+ 'linux2': {
+ 'gpu_tests':
+ ('WebGLConformanceTests.conformance_attribs_gl_enable_vertex_attrib',
+ 'WebGLConformanceTests.'
+ 'conformance_attribs_gl_disabled_vertex_attrib',
+ 'WebGLConformanceTests.'
+ 'conformance_attribs_gl_vertex_attrib_zero_issues',
+ 'WebGLConformanceTests.conformance_attribs_gl_vertex_attrib',
+ 'WebGLConformanceTests.'
+ 'conformance_attribs_gl_vertexattribpointer_offsets',
+ 'WebGLConformanceTests.conformance_attribs_gl_vertexattribpointer',
+ 'WebGLConformanceTests.conformance_buffers_buffer_bind_test',
+ 'WebGLConformanceTests.'
+ 'conformance_buffers_buffer_data_array_buffer',
+ 'WebGLConformanceTests.'
+ 'conformance_buffers_index_validation_copies_indices',
+ 'WebGLConformanceTests.'
+ 'conformance_buffers_index_validation_crash_with_buffer_sub_data',
+ 'WebGLConformanceTests.'
+ 'conformance_buffers_index_validation_verifies_too_many_indices',
+ 'WebGLConformanceTests.'
+ 'conformance_buffers_index_validation_with_resized_buffer',
+ 'WebGLConformanceTests.conformance_canvas_buffer_offscreen_test',
+ 'WebGLConformanceTests.conformance_canvas_buffer_preserve_test',
+ 'WebGLConformanceTests.conformance_canvas_canvas_test',
+ 'WebGLConformanceTests.conformance_canvas_canvas_zero_size',
+ 'WebGLConformanceTests.'
+ 'conformance_canvas_drawingbuffer_static_canvas_test',
+ 'WebGLConformanceTests.conformance_canvas_drawingbuffer_test',),
+ 'performance_ui_tests':
+ ('*PageCycler*.*',
+ '*FrameRateCompositingTest.*',
+ '*FrameRateNoVsyncCanvasInternalTest.*',
+ '*FrameRateGpuCanvasInternalTest.*',
+ 'IndexedDBTest.Perf',),
+ 'sync_integration_tests':
+ ('TwoClientPasswordsSyncTest.DeleteAll',
+ 'MigrationTwoClientTest.MigrationHellWithoutNigori',
+ 'TwoClientSessionsSyncTest.DeleteActiveSession',
+ 'MultipleClientSessionsSyncTest.EncryptedAndChanged',
+ 'MigrationSingleClientTest.'
+ 'AllTypesIndividuallyTriggerNotification',),
+ 'interactive_ui_tests':
+ ('*OldPanelResizeBrowserTest.*',
+ '*OldPanelDragBrowserTest.*',
+ '*OldPanelBrowserTest.*',
+ '*OldPanelAndDesktopNotificationTest.*',
+ '*OldDockedPanelBrowserTest.*',
+ '*OldDetachedPanelBrowserTest.*',
+ 'PanelDragBrowserTest.AttachWithSqueeze',
+ '*PanelBrowserTest.*',
+ '*DockedPanelBrowserTest.*',
+ '*DetachedPanelBrowserTest.*',),
+ 'automated_ui_tests':
+ ('AutomatedUITest.TheOneAndOnlyTest',
+ 'AutomatedUITestBase.DragOut',), },
+}
+
+"""Since random tests are failing/hanging on coverage bot, we are enabling
+ tests feature by feature. crbug.com/159748
+"""
+gTestInclusions = {
+ 'linux2': {
+ 'browser_tests':
+ (# 'src/chrome/browser/downloads'
+ 'SavePageBrowserTest.*',
+ 'SavePageAsMHTMLBrowserTest.*',
+ 'DownloadQueryTest.*',
+ 'DownloadDangerPromptTest.*',
+ 'DownloadTest.*',
+ # 'src/chrome/browser/net'
+ 'CookiePolicyBrowserTest.*',
+ 'FtpBrowserTest.*',
+ 'LoadTimingObserverTest.*',
+ 'PredictorBrowserTest.*',
+ 'ProxyBrowserTest.*',
+ # 'src/chrome/browser/extensions'
+ 'Extension*.*',
+ 'WindowOpenPanelDisabledTest.*',
+ 'WindowOpenPanelTest.*',
+ 'WebstoreStandalone*.*',
+ 'CommandLineWebstoreInstall.*',
+ 'WebViewTest.*',
+ 'RequirementsCheckerBrowserTest.*',
+ 'ProcessManagementTest.*',
+ 'PlatformAppBrowserTest.*',
+ 'PlatformAppDevToolsBrowserTest.*',
+ 'LazyBackgroundPageApiTest.*',
+ 'IsolatedAppTest.*',
+ 'PanelMessagingTest.*',
+ 'GeolocationApiTest.*',
+ 'ClipboardApiTest.*',
+ 'ExecuteScriptApiTest.*',
+ 'CalculatorBrowserTest.*',
+ 'ChromeAppAPITest.*',
+ 'AppApiTest.*',
+ 'BlockedAppApiTest.*',
+ 'AppBackgroundPageApiTest.*',
+ 'WebNavigationApiTest.*',
+ 'UsbApiTest.*',
+ 'TabCaptureApiTest.*',
+ 'SystemInfo*.*',
+ 'SyncFileSystemApiTest.*',
+ 'SocketApiTest.*',
+ 'SerialApiTest.*',
+ 'RecordApiTest.*',
+ 'PushMessagingApiTest.*',
+ 'ProxySettingsApiTest.*',
+ 'ExperimentalApiTest.*',
+ 'OmniboxApiTest.*',
+ 'OffscreenTabsApiTest.*',
+ 'NotificationApiTest.*',
+ 'MediaGalleriesPrivateApiTest.*',
+ 'PlatformAppMediaGalleriesBrowserTest.*',
+ 'GetAuthTokenFunctionTest.*',
+ 'LaunchWebAuthFlowFunctionTest.*',
+ 'FileSystemApiTest.*',
+ 'ScriptBadgeApiTest.*',
+ 'PageAsBrowserActionApiTest.*',
+ 'PageActionApiTest.*',
+ 'BrowserActionApiTest.*',
+ 'DownloadExtensionTest.*',
+ 'DnsApiTest.*',
+ 'DeclarativeApiTest.*',
+ 'BluetoothApiTest.*',
+ 'AllUrlsApiTest.*',
+ # 'src/chrome/browser/nacl_host'
+ 'nacl_host.*',
+ # 'src/chrome/browser/automation'
+ 'AutomationMiscBrowserTest.*',
+ # 'src/chrome/browser/autofill'
+ 'FormStructureBrowserTest.*',
+ 'AutofillPopupViewBrowserTest.*',
+ 'AutofillTest.*',
+ # 'src/chrome/browser/autocomplete'
+ 'AutocompleteBrowserTest.*',
+ # 'src/chrome/browser/captive_portal'
+ 'CaptivePortalBrowserTest.*',
+ # 'src/chrome/browser/geolocation'
+ 'GeolocationAccessTokenStoreTest.*',
+ 'GeolocationBrowserTest.*',
+ # 'src/chrome/browser/nacl_host'
+ 'NaClGdbTest.*',
+ # 'src/chrome/browser/devtools'
+ 'DevToolsSanityTest.*',
+ 'DevToolsExtensionTest.*',
+ 'DevToolsExperimentalExtensionTest.*',
+ 'WorkerDevToolsSanityTest.*',
+ # 'src/chrome/browser/first_run'
+ 'FirstRunBrowserTest.*',
+ # 'src/chrome/browser/importer'
+ 'ToolbarImporterUtilsTest.*',
+ # 'src/chrome/browser/page_cycler'
+ 'PageCyclerBrowserTest.*',
+ 'PageCyclerCachedBrowserTest.*',
+ # 'src/chrome/browser/performance_monitor'
+ 'PerformanceMonitorBrowserTest.*',
+ 'PerformanceMonitorUncleanExitBrowserTest.*',
+ 'PerformanceMonitorSessionRestoreBrowserTest.*',
+ # 'src/chrome/browser/prerender'
+ 'PrerenderBrowserTest.*',
+ 'PrerenderBrowserTestWithNaCl.*',
+ 'PrerenderBrowserTestWithExtensions.*',
+ 'PrefetchBrowserTest.*',
+ 'PrefetchBrowserTestNoPrefetching.*', ),
+ },
+}
+
+
+def TerminateSignalHandler(sig, stack):
+ """When killed, try and kill our child processes."""
+ signal.signal(sig, signal.SIG_DFL)
+ for pid in gChildPIDs:
+ if 'kill' in os.__all__: # POSIX
+ os.kill(pid, sig)
+ else:
+ subprocess.call(['taskkill.exe', '/PID', str(pid)])
+ sys.exit(0)
+
+
+class RunTooLongException(Exception):
+ """Thrown when a command runs too long without output."""
+ pass
+
+class BadUserInput(Exception):
+ """Thrown when arguments from the user are incorrectly formatted."""
+ pass
+
+
+class RunProgramThread(threading.Thread):
+ """A thread to run a subprocess.
+
+ We want to print the output of our subprocess in real time, but also
+ want a timeout if there has been no output for a certain amount of
+ time. Normal techniques (e.g. loop in select()) aren't cross
+ platform enough. the function seems simple: "print output of child, kill it
+ if there is no output by timeout. But it was tricky to get this right
+ in a x-platform way (see warnings about deadlock on the python
+ subprocess doc page).
+
+ """
+ # Constants in our queue
+ PROGRESS = 0
+ DONE = 1
+
+ def __init__(self, cmd):
+ super(RunProgramThread, self).__init__()
+ self._cmd = cmd
+ self._process = None
+ self._queue = Queue.Queue()
+ self._retcode = None
+
+ def run(self):
+ if sys.platform in ('win32', 'cygwin'):
+ return self._run_windows()
+ else:
+ self._run_posix()
+
+ def _run_windows(self):
+ # We need to save stdout to a temporary file because of a bug on the
+ # windows implementation of python which can deadlock while waiting
+ # for the IO to complete while writing to the PIPE and the pipe waiting
+ # on us and us waiting on the child process.
+ stdout_file = tempfile.TemporaryFile()
+ try:
+ self._process = subprocess.Popen(self._cmd,
+ stdin=subprocess.PIPE,
+ stdout=stdout_file,
+ stderr=subprocess.STDOUT)
+ gChildPIDs.append(self._process.pid)
+ try:
+ # To make sure that the buildbot don't kill us if we run too long
+ # without any activity on the console output, we look for progress in
+ # the length of the temporary file and we print what was accumulated so
+ # far to the output console to make the buildbot know we are making some
+ # progress.
+ previous_tell = 0
+ # We will poll the process until we get a non-None return code.
+ self._retcode = None
+ while self._retcode is None:
+ self._retcode = self._process.poll()
+ current_tell = stdout_file.tell()
+ if current_tell > previous_tell:
+ # Report progress to our main thread so we don't timeout.
+ self._queue.put(RunProgramThread.PROGRESS)
+ # And print what was accumulated to far.
+ stdout_file.seek(previous_tell)
+ print stdout_file.read(current_tell - previous_tell),
+ previous_tell = current_tell
+ # Don't be selfish, let other threads do stuff while we wait for
+ # the process to complete.
+ time.sleep(0.5)
+ # OK, the child process has exited, let's print its output to our
+ # console to create debugging logs in case they get to be needed.
+ stdout_file.flush()
+ stdout_file.seek(previous_tell)
+ print stdout_file.read(stdout_file.tell() - previous_tell)
+ except IOError, e:
+ logging.exception('%s', e)
+ pass
+ finally:
+ stdout_file.close()
+
+ # If we get here the process is done.
+ gChildPIDs.remove(self._process.pid)
+ self._queue.put(RunProgramThread.DONE)
+
+ def _run_posix(self):
+ """No deadlock problem so use the simple answer. The windows solution
+ appears to add extra buffering which we don't want on other platforms."""
+ self._process = subprocess.Popen(self._cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ gChildPIDs.append(self._process.pid)
+ try:
+ while True:
+ line = self._process.stdout.readline()
+ if not line: # EOF
+ break
+ print line,
+ self._queue.put(RunProgramThread.PROGRESS, True)
+ except IOError:
+ pass
+ # If we get here the process is done.
+ gChildPIDs.remove(self._process.pid)
+ self._queue.put(RunProgramThread.DONE)
+
+ def stop(self):
+ self.kill()
+
+ def kill(self):
+ """Kill our running process if needed. Wait for kill to complete.
+
+ Should be called in the PARENT thread; we do not self-kill.
+ Returns the return code of the process.
+ Safe to call even if the process is dead.
+ """
+ if not self._process:
+ return self.retcode()
+ if 'kill' in os.__all__: # POSIX
+ os.kill(self._process.pid, signal.SIGKILL)
+ else:
+ subprocess.call(['taskkill.exe', '/PID', str(self._process.pid)])
+ return self.retcode()
+
+ def retcode(self):
+ """Return the return value of the subprocess.
+
+ Waits for process to die but does NOT kill it explicitly.
+ """
+ if self._retcode == None: # must be none, not 0/False
+ self._retcode = self._process.wait()
+ return self._retcode
+
+ def RunUntilCompletion(self, timeout):
+ """Run thread until completion or timeout (in seconds).
+
+ Start the thread. Let it run until completion, or until we've
+ spent TIMEOUT without seeing output. On timeout throw
+ RunTooLongException.
+ """
+ self.start()
+ while True:
+ try:
+ x = self._queue.get(True, timeout)
+ if x == RunProgramThread.DONE:
+ return self.retcode()
+ except Queue.Empty, e: # timed out
+ logging.info('TIMEOUT (%d seconds exceeded with no output): killing' %
+ timeout)
+ self.kill()
+ raise RunTooLongException()
+
+
+class Coverage(object):
+ """Doitall class for code coverage."""
+
+ def __init__(self, options, args):
+ super(Coverage, self).__init__()
+ logging.basicConfig(level=logging.DEBUG)
+ self.directory = options.directory
+ self.options = options
+ self.args = args
+ self.ConfirmDirectory()
+ self.directory_parent = os.path.dirname(self.directory)
+ self.output_directory = os.path.join(self.directory, 'coverage')
+ if not os.path.exists(self.output_directory):
+ os.mkdir(self.output_directory)
+ # The "final" lcov-format file
+ self.coverage_info_file = os.path.join(self.directory, 'coverage.info')
+ # If needed, an intermediate VSTS-format file
+ self.vsts_output = os.path.join(self.directory, 'coverage.vsts')
+ # Needed for Windows.
+ self.src_root = options.src_root
+ self.FindPrograms()
+ self.ConfirmPlatformAndPaths()
+ self.tests = [] # This can be a list of strings, lists or both.
+ self.xvfb_pid = 0
+ self.test_files = [] # List of files with test specifications.
+ self.test_filters = {} # Mapping from testname->--gtest_filter arg.
+ logging.info('self.directory: ' + self.directory)
+ logging.info('self.directory_parent: ' + self.directory_parent)
+
+ def FindInPath(self, program):
+ """Find program in our path. Return abs path to it, or None."""
+ if not 'PATH' in os.environ:
+ logging.fatal('No PATH environment variable?')
+ sys.exit(1)
+ paths = os.environ['PATH'].split(os.pathsep)
+ for path in paths:
+ fullpath = os.path.join(path, program)
+ if os.path.exists(fullpath):
+ return fullpath
+ return None
+
+ def FindPrograms(self):
+ """Find programs we may want to run."""
+ if self.IsPosix():
+ self.lcov_directory = os.path.join(sys.path[0],
+ '../../third_party/lcov/bin')
+ self.lcov = os.path.join(self.lcov_directory, 'lcov')
+ self.mcov = os.path.join(self.lcov_directory, 'mcov')
+ self.genhtml = os.path.join(self.lcov_directory, 'genhtml')
+ self.programs = [self.lcov, self.mcov, self.genhtml]
+ else:
+ # Hack to get the buildbot working.
+ os.environ['PATH'] += r';c:\coverage\coverage_analyzer'
+ os.environ['PATH'] += r';c:\coverage\performance_tools'
+ # (end hack)
+ commands = ['vsperfcmd.exe', 'vsinstr.exe', 'coverage_analyzer.exe']
+ self.perf = self.FindInPath('vsperfcmd.exe')
+ self.instrument = self.FindInPath('vsinstr.exe')
+ self.analyzer = self.FindInPath('coverage_analyzer.exe')
+ if not self.perf or not self.instrument or not self.analyzer:
+ logging.fatal('Could not find Win performance commands.')
+ logging.fatal('Commands needed in PATH: ' + str(commands))
+ sys.exit(1)
+ self.programs = [self.perf, self.instrument, self.analyzer]
+
+ def PlatformBuildPrefix(self):
+ """Return a platform specific build directory prefix.
+
+ This prefix is prepended to the build target (Debug, Release) to
+ identify output as relative to the build directory.
+ These values are specific to Chromium's use of gyp.
+ """
+ if self.IsMac():
+ return '../xcodebuild'
+ if self.IsWindows():
+ return ''
+ else: # Linux
+ return '../out' # assumes make, unlike runtest.py
+
+ def ConfirmDirectory(self):
+ """Confirm correctness of self.directory.
+
+ If it exists, happiness. If not, try and figure it out in a
+ manner similar to FindBundlesFile(). The 'figure it out' case
+ happens with buildbot where the directory isn't specified
+ explicitly.
+ """
+ if (not self.directory and
+ not (self.options.target and self.options.build_dir)):
+ logging.fatal('Must use --directory or (--target and --build-dir)')
+ sys.exit(1)
+
+ if not self.directory:
+ self.directory = os.path.join(self.options.build_dir,
+ self.PlatformBuildPrefix(),
+ self.options.target)
+
+ if os.path.exists(self.directory):
+ logging.info('Directory: ' + self.directory)
+ return
+ else:
+ logging.fatal('Directory ' +
+ self.directory + ' doesn\'t exist')
+ sys.exit(1)
+
+
+ def FindBundlesFile(self):
+ """Find the bundlesfile.
+
+ The 'bundles' file can be either absolute path, or (if we are run
+ from buildbot) we need to find it based on other hints (--target,
+ --build-dir, etc).
+ """
+ # If no bundle file, no problem!
+ if not self.options.bundles:
+ return
+ # If true, we're buildbot. Form a path.
+ # Else assume absolute.
+ if self.options.target and self.options.build_dir:
+ fullpath = os.path.join(self.options.build_dir,
+ self.PlatformBuildPrefix(),
+ self.options.target,
+ self.options.bundles)
+ self.options.bundles = fullpath
+
+ if os.path.exists(self.options.bundles):
+ logging.info('BundlesFile: ' + self.options.bundles)
+ return
+ else:
+ logging.fatal('bundlefile ' +
+ self.options.bundles + ' doesn\'t exist')
+ sys.exit(1)
+
+
+ def FindTests(self):
+ """Find unit tests to run; set self.tests to this list.
+
+ Assume all non-option items in the arg list are tests to be run.
+ """
+ # Before we begin, find the bundles file if not an absolute path.
+ self.FindBundlesFile()
+
+ # Small tests: can be run in the "chromium" directory.
+ # If asked, run all we can find.
+ if self.options.all_unittests:
+ self.tests += glob.glob(os.path.join(self.directory, '*_unittests'))
+ self.tests += glob.glob(os.path.join(self.directory, '*unit_tests'))
+ elif self.options.all_browsertests:
+ # Run all tests in browser_tests and content_browsertests.
+ self.tests += glob.glob(os.path.join(self.directory, 'browser_tests'))
+ self.tests += glob.glob(os.path.join(self.directory,
+ 'content_browsertests'))
+
+ # Tests can come in as args directly, indirectly (through a file
+ # of test lists) or as a file of bundles.
+ all_testnames = self.args[:] # Copy since we might modify
+
+ for test_file in self.options.test_files:
+ f = open(test_file)
+ for line in f:
+ line = re.sub(r"#.*$", "", line)
+ line = re.sub(r"\s*", "", line)
+ if re.match("\s*$"):
+ continue
+ all_testnames.append(line)
+ f.close()
+
+ tests_from_bundles = None
+ if self.options.bundles:
+ try:
+ tests_from_bundles = eval(open(self.options.bundles).read())
+ except IOError:
+ logging.fatal('IO error in bundle file ' +
+ self.options.bundles + ' (doesn\'t exist?)')
+ except (NameError, SyntaxError):
+ logging.fatal('Parse or syntax error in bundle file ' +
+ self.options.bundles)
+ if hasattr(tests_from_bundles, '__iter__'):
+ all_testnames += tests_from_bundles
+ else:
+ logging.fatal('Fatal error with bundle file; could not get list from' +
+ self.options.bundles)
+ sys.exit(1)
+
+ # If told explicit tests, run those (after stripping the name as
+ # appropriate)
+ for testname in all_testnames:
+ mo = re.search(r"(.*)\[(.*)\]$", testname)
+ gtest_filter = None
+ if mo:
+ gtest_filter = mo.group(2)
+ testname = mo.group(1)
+ if ':' in testname:
+ testname = testname.split(':')[1]
+ # We need 'pyautolib' to run pyauto tests and 'pyautolib' itself is not an
+ # executable. So skip this test from adding into coverage_bundles.py.
+ if testname == 'pyautolib':
+ continue
+ self.tests += [os.path.join(self.directory, testname)]
+ if gtest_filter:
+ self.test_filters[testname] = gtest_filter
+
+ # Add 'src/test/functional/pyauto_functional.py' to self.tests.
+ # This file with '-v --suite=CODE_COVERAGE' arguments runs all pyauto tests.
+ # Pyauto tests are failing randomly on coverage bots. So excluding them.
+ # self.tests += [['src/chrome/test/functional/pyauto_functional.py',
+ # '-v',
+ # '--suite=CODE_COVERAGE']]
+
+ # Medium tests?
+ # Not sure all of these work yet (e.g. page_cycler_tests)
+ # self.tests += glob.glob(os.path.join(self.directory, '*_tests'))
+
+ # If needed, append .exe to tests since vsinstr.exe likes it that
+ # way.
+ if self.IsWindows():
+ for ind in range(len(self.tests)):
+ test = self.tests[ind]
+ test_exe = test + '.exe'
+ if not test.endswith('.exe') and os.path.exists(test_exe):
+ self.tests[ind] = test_exe
+
+ def TrimTests(self):
+ """Trim specific tests for each platform."""
+ if self.IsWindows():
+ return
+ # TODO(jrg): remove when not needed
+ inclusion = ['unit_tests']
+ keep = []
+ for test in self.tests:
+ for i in inclusion:
+ if i in test:
+ keep.append(test)
+ self.tests = keep
+ logging.info('After trimming tests we have ' + ' '.join(self.tests))
+ return
+ if self.IsLinux():
+ # self.tests = filter(lambda t: t.endswith('base_unittests'), self.tests)
+ return
+ if self.IsMac():
+ exclusion = ['automated_ui_tests']
+ punted = []
+ for test in self.tests:
+ for e in exclusion:
+ if test.endswith(e):
+ punted.append(test)
+ self.tests = filter(lambda t: t not in punted, self.tests)
+ if punted:
+ logging.info('Tests trimmed out: ' + str(punted))
+
+ def ConfirmPlatformAndPaths(self):
+ """Confirm OS and paths (e.g. lcov)."""
+ for program in self.programs:
+ if not os.path.exists(program):
+ logging.fatal('Program missing: ' + program)
+ sys.exit(1)
+
+ def Run(self, cmdlist, ignore_error=False, ignore_retcode=None,
+ explanation=None):
+ """Run the command list; exit fatally on error.
+
+ Args:
+ cmdlist: a list of commands (e.g. to pass to subprocess.call)
+ ignore_error: if True log an error; if False then exit.
+ ignore_retcode: if retcode is non-zero, exit unless we ignore.
+
+ Returns: process return code.
+ Throws: RunTooLongException if the process does not produce output
+ within TIMEOUT seconds; timeout is specified as a command line
+ option to the Coverage class and is set on init.
+ """
+ logging.info('Running ' + str(cmdlist))
+ t = RunProgramThread(cmdlist)
+ retcode = t.RunUntilCompletion(self.options.timeout)
+
+ if retcode:
+ if ignore_error or retcode == ignore_retcode:
+ logging.warning('COVERAGE: %s unhappy but errors ignored %s' %
+ (str(cmdlist), explanation or ''))
+ else:
+ logging.fatal('COVERAGE: %s failed; return code: %d' %
+ (str(cmdlist), retcode))
+ sys.exit(retcode)
+ return retcode
+
+ def IsPosix(self):
+ """Return True if we are POSIX."""
+ return self.IsMac() or self.IsLinux()
+
+ def IsMac(self):
+ return sys.platform == 'darwin'
+
+ def IsLinux(self):
+ return sys.platform.startswith('linux')
+
+ def IsWindows(self):
+ """Return True if we are Windows."""
+ return sys.platform in ('win32', 'cygwin')
+
+ def ClearData(self):
+ """Clear old gcda files and old coverage info files."""
+ if self.options.dont_clear_coverage_data:
+ print 'Clearing of coverage data NOT performed.'
+ return
+ print 'Clearing coverage data from previous runs.'
+ if os.path.exists(self.coverage_info_file):
+ os.remove(self.coverage_info_file)
+ if self.IsPosix():
+ subprocess.call([self.lcov,
+ '--directory', self.directory_parent,
+ '--zerocounters'])
+ shutil.rmtree(os.path.join(self.directory, 'coverage'))
+ if self.options.all_unittests:
+ if os.path.exists(os.path.join(self.directory, 'unittests_coverage')):
+ shutil.rmtree(os.path.join(self.directory, 'unittests_coverage'))
+ elif self.options.all_browsertests:
+ if os.path.exists(os.path.join(self.directory,
+ 'browsertests_coverage')):
+ shutil.rmtree(os.path.join(self.directory, 'browsertests_coverage'))
+ else:
+ if os.path.exists(os.path.join(self.directory, 'total_coverage')):
+ shutil.rmtree(os.path.join(self.directory, 'total_coverage'))
+
+ def BeforeRunOneTest(self, testname):
+ """Do things before running each test."""
+ if not self.IsWindows():
+ return
+ # Stop old counters if needed
+ cmdlist = [self.perf, '-shutdown']
+ self.Run(cmdlist, ignore_error=True)
+ # Instrument binaries
+ for fulltest in self.tests:
+ if os.path.exists(fulltest):
+ # See http://support.microsoft.com/kb/939818 for details on args
+ cmdlist = [self.instrument, '/d:ignorecverr', '/COVERAGE', fulltest]
+ self.Run(cmdlist, ignore_retcode=4,
+ explanation='OK with a multiple-instrument')
+ # Start new counters
+ cmdlist = [self.perf, '-start:coverage', '-output:' + self.vsts_output]
+ self.Run(cmdlist)
+
+ def BeforeRunAllTests(self):
+ """Called right before we run all tests."""
+ if self.IsLinux() and self.options.xvfb:
+ self.StartXvfb()
+
+ def GtestFilter(self, fulltest, excl=None):
+ """Return a --gtest_filter=BLAH for this test.
+
+ Args:
+ fulltest: full name of test executable
+ exclusions: the exclusions list. Only set in a unit test;
+ else uses gTestExclusions.
+ Returns:
+ String of the form '--gtest_filter=BLAH', or None.
+ """
+ positive_gfilter_list = []
+ negative_gfilter_list = []
+
+ # Exclude all flaky, failing, disabled and maybe tests;
+ # they don't count for code coverage.
+ negative_gfilter_list += ('*.FLAKY_*', '*.FAILS_*',
+ '*.DISABLED_*', '*.MAYBE_*')
+
+ if not self.options.no_exclusions:
+ exclusions = excl or gTestExclusions
+ excldict = exclusions.get(sys.platform)
+ if excldict:
+ for test in excldict.keys():
+ # example: if base_unittests in ../blah/blah/base_unittests.exe
+ if test in fulltest:
+ negative_gfilter_list += excldict[test]
+
+ inclusions = gTestInclusions
+ include_dict = inclusions.get(sys.platform)
+ if include_dict:
+ for test in include_dict.keys():
+ if test in fulltest:
+ positive_gfilter_list += include_dict[test]
+
+ fulltest_basename = os.path.basename(fulltest)
+ if fulltest_basename in self.test_filters:
+ specific_test_filters = self.test_filters[fulltest_basename].split('-')
+ if len(specific_test_filters) > 2:
+ logging.error('Multiple "-" symbols in filter list: %s' %
+ self.test_filters[fulltest_basename])
+ raise BadUserInput()
+ if len(specific_test_filters) == 2:
+ # Remove trailing ':'
+ specific_test_filters[0] = specific_test_filters[0][:-1]
+
+ if specific_test_filters[0]: # Test for no positive filters.
+ positive_gfilter_list += specific_test_filters[0].split(':')
+ if len(specific_test_filters) > 1:
+ negative_gfilter_list += specific_test_filters[1].split(':')
+
+ if not positive_gfilter_list and not negative_gfilter_list:
+ return None
+
+ result = '--gtest_filter='
+ if positive_gfilter_list:
+ result += ':'.join(positive_gfilter_list)
+ if negative_gfilter_list:
+ if positive_gfilter_list: result += ':'
+ result += '-' + ':'.join(negative_gfilter_list)
+ return result
+
+ def RunTests(self):
+ """Run all unit tests and generate appropriate lcov files."""
+ self.BeforeRunAllTests()
+ for fulltest in self.tests:
+ if type(fulltest) is str:
+ if not os.path.exists(fulltest):
+ logging.info(fulltest + ' does not exist')
+ if self.options.strict:
+ sys.exit(2)
+ else:
+ logging.info('%s path exists' % fulltest)
+ cmdlist = [fulltest, '--gtest_print_time']
+
+ # If asked, make this REAL fast for testing.
+ if self.options.fast_test:
+ logging.info('Running as a FAST test for testing')
+ # cmdlist.append('--gtest_filter=RenderWidgetHost*')
+ # cmdlist.append('--gtest_filter=CommandLine*')
+ cmdlist.append('--gtest_filter=C*')
+
+ # Possibly add a test-specific --gtest_filter
+ filter = self.GtestFilter(fulltest)
+ if filter:
+ cmdlist.append(filter)
+ elif type(fulltest) is list:
+ cmdlist = fulltest
+
+ self.BeforeRunOneTest(fulltest)
+ logging.info('Running test ' + str(cmdlist))
+ try:
+ retcode = self.Run(cmdlist, ignore_retcode=True)
+ except SystemExit: # e.g. sys.exit() was called somewhere in here
+ raise
+ except: # can't "except WindowsError" since script runs on non-Windows
+ logging.info('EXCEPTION while running a unit test')
+ logging.info(traceback.format_exc())
+ retcode = 999
+ self.AfterRunOneTest(fulltest)
+
+ if retcode:
+ logging.info('COVERAGE: test %s failed; return code: %d.' %
+ (fulltest, retcode))
+ if self.options.strict:
+ logging.fatal('Test failure is fatal.')
+ sys.exit(retcode)
+ self.AfterRunAllTests()
+
+ def AfterRunOneTest(self, testname):
+ """Do things right after running each test."""
+ if not self.IsWindows():
+ return
+ # Stop counters
+ cmdlist = [self.perf, '-shutdown']
+ self.Run(cmdlist)
+ full_output = self.vsts_output + '.coverage'
+ shutil.move(full_output, self.vsts_output)
+ # generate lcov!
+ self.GenerateLcovWindows(testname)
+
+ def AfterRunAllTests(self):
+ """Do things right after running ALL tests."""
+ # On POSIX we can do it all at once without running out of memory.
+ # This contrasts with Windows where we must do it after each test.
+ if self.IsPosix():
+ self.GenerateLcovPosix()
+ # Only on Linux do we have the Xvfb step.
+ if self.IsLinux() and self.options.xvfb:
+ self.StopXvfb()
+
+ def StartXvfb(self):
+ """Start Xvfb and set an appropriate DISPLAY environment. Linux only.
+
+ Copied from http://src.chromium.org/viewvc/chrome/trunk/tools/buildbot/
+ scripts/slave/slave_utils.py?view=markup
+ with some simplifications (e.g. no need to use xdisplaycheck, save
+ pid in var not file, etc)
+ """
+ logging.info('Xvfb: starting')
+ proc = subprocess.Popen(["Xvfb", ":9", "-screen", "0", "1024x768x24",
+ "-ac"],
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ self.xvfb_pid = proc.pid
+ if not self.xvfb_pid:
+ logging.info('Could not start Xvfb')
+ return
+ os.environ['DISPLAY'] = ":9"
+ # Now confirm, giving a chance for it to start if needed.
+ logging.info('Xvfb: confirming')
+ for test in range(10):
+ proc = subprocess.Popen('xdpyinfo >/dev/null', shell=True)
+ pid, retcode = os.waitpid(proc.pid, 0)
+ if retcode == 0:
+ break
+ time.sleep(0.5)
+ if retcode != 0:
+ logging.info('Warning: could not confirm Xvfb happiness')
+ else:
+ logging.info('Xvfb: OK')
+
+ def StopXvfb(self):
+ """Stop Xvfb if needed. Linux only."""
+ if self.xvfb_pid:
+ logging.info('Xvfb: killing')
+ try:
+ os.kill(self.xvfb_pid, signal.SIGKILL)
+ except:
+ pass
+ del os.environ['DISPLAY']
+ self.xvfb_pid = 0
+
+ def CopyCoverageFileToDestination(self, coverage_folder):
+ coverage_dir = os.path.join(self.directory, coverage_folder)
+ if not os.path.exists(coverage_dir):
+ os.makedirs(coverage_dir)
+ shutil.copyfile(self.coverage_info_file, os.path.join(coverage_dir,
+ 'coverage.info'))
+
+ def GenerateLcovPosix(self):
+ """Convert profile data to lcov on Mac or Linux."""
+ start_dir = os.getcwd()
+ logging.info('GenerateLcovPosix: start_dir=' + start_dir)
+ if self.IsLinux():
+ # With Linux/make (e.g. the coverage_run target), the current
+ # directory for this command is .../build/src/chrome but we need
+ # to be in .../build/src for the relative path of source files
+ # to be correct. However, when run from buildbot, the current
+ # directory is .../build. Accommodate.
+ # On Mac source files are compiled with abs paths so this isn't
+ # a problem.
+ # This is a bit of a hack. The best answer is to require this
+ # script be run in a specific directory for all cases (from
+ # Makefile or from buildbot).
+ if start_dir.endswith('chrome'):
+ logging.info('coverage_posix.py: doing a "cd .." '
+ 'to accomodate Linux/make PWD')
+ os.chdir('..')
+ elif start_dir.endswith('build'):
+ logging.info('coverage_posix.py: doing a "cd src" '
+ 'to accomodate buildbot PWD')
+ os.chdir('src')
+ else:
+ logging.info('coverage_posix.py: NOT changing directory.')
+ elif self.IsMac():
+ pass
+
+ command = [self.mcov,
+ '--directory',
+ os.path.join(start_dir, self.directory_parent),
+ '--output',
+ os.path.join(start_dir, self.coverage_info_file)]
+ logging.info('Assembly command: ' + ' '.join(command))
+ retcode = subprocess.call(command)
+ if retcode:
+ logging.fatal('COVERAGE: %s failed; return code: %d' %
+ (command[0], retcode))
+ if self.options.strict:
+ sys.exit(retcode)
+ if self.IsLinux():
+ os.chdir(start_dir)
+
+ # Copy the unittests coverage information to a different folder.
+ if self.options.all_unittests:
+ self.CopyCoverageFileToDestination('unittests_coverage')
+ elif self.options.all_browsertests:
+ # Save browsertests only coverage information.
+ self.CopyCoverageFileToDestination('browsertests_coverage')
+ else:
+ # Save the overall coverage information.
+ self.CopyCoverageFileToDestination('total_coverage')
+
+ if not os.path.exists(self.coverage_info_file):
+ logging.fatal('%s was not created. Coverage run failed.' %
+ self.coverage_info_file)
+ sys.exit(1)
+
+ def GenerateLcovWindows(self, testname=None):
+ """Convert VSTS format to lcov. Appends coverage data to sum file."""
+ lcov_file = self.vsts_output + '.lcov'
+ if os.path.exists(lcov_file):
+ os.remove(lcov_file)
+ # generates the file (self.vsts_output + ".lcov")
+
+ cmdlist = [self.analyzer,
+ '-sym_path=' + self.directory,
+ '-src_root=' + self.src_root,
+ '-noxml',
+ self.vsts_output]
+ self.Run(cmdlist)
+ if not os.path.exists(lcov_file):
+ logging.fatal('Output file %s not created' % lcov_file)
+ sys.exit(1)
+ logging.info('Appending lcov for test %s to %s' %
+ (testname, self.coverage_info_file))
+ size_before = 0
+ if os.path.exists(self.coverage_info_file):
+ size_before = os.stat(self.coverage_info_file).st_size
+ src = open(lcov_file, 'r')
+ dst = open(self.coverage_info_file, 'a')
+ dst.write(src.read())
+ src.close()
+ dst.close()
+ size_after = os.stat(self.coverage_info_file).st_size
+ logging.info('Lcov file growth for %s: %d --> %d' %
+ (self.coverage_info_file, size_before, size_after))
+
+ def GenerateHtml(self):
+ """Convert lcov to html."""
+ # TODO(jrg): This isn't happy when run with unit_tests since V8 has a
+ # different "base" so V8 includes can't be found in ".". Fix.
+ command = [self.genhtml,
+ self.coverage_info_file,
+ '--output-directory',
+ self.output_directory]
+ print >>sys.stderr, 'html generation command: ' + ' '.join(command)
+ retcode = subprocess.call(command)
+ if retcode:
+ logging.fatal('COVERAGE: %s failed; return code: %d' %
+ (command[0], retcode))
+ if self.options.strict:
+ sys.exit(retcode)
+
+def CoverageOptionParser():
+ """Return an optparse.OptionParser() suitable for Coverage object creation."""
+ parser = optparse.OptionParser()
+ parser.add_option('-d',
+ '--directory',
+ dest='directory',
+ default=None,
+ help='Directory of unit test files')
+ parser.add_option('-a',
+ '--all_unittests',
+ dest='all_unittests',
+ default=False,
+ help='Run all tests we can find (*_unittests)')
+ parser.add_option('-b',
+ '--all_browsertests',
+ dest='all_browsertests',
+ default=False,
+ help='Run all tests in browser_tests '
+ 'and content_browsertests')
+ parser.add_option('-g',
+ '--genhtml',
+ dest='genhtml',
+ default=False,
+ help='Generate html from lcov output')
+ parser.add_option('-f',
+ '--fast_test',
+ dest='fast_test',
+ default=False,
+ help='Make the tests run REAL fast by doing little.')
+ parser.add_option('-s',
+ '--strict',
+ dest='strict',
+ default=False,
+ help='Be strict and die on test failure.')
+ parser.add_option('-S',
+ '--src_root',
+ dest='src_root',
+ default='.',
+ help='Source root (only used on Windows)')
+ parser.add_option('-t',
+ '--trim',
+ dest='trim',
+ default=True,
+ help='Trim out tests? Default True.')
+ parser.add_option('-x',
+ '--xvfb',
+ dest='xvfb',
+ default=True,
+ help='Use Xvfb for tests? Default True.')
+ parser.add_option('-T',
+ '--timeout',
+ dest='timeout',
+ default=5.0 * 60.0,
+ type="int",
+ help='Timeout before bailing if a subprocess has no output.'
+ ' Default is 5min (Buildbot is 10min.)')
+ parser.add_option('-B',
+ '--bundles',
+ dest='bundles',
+ default=None,
+ help='Filename of bundles for coverage.')
+ parser.add_option('--build-dir',
+ dest='build_dir',
+ default=None,
+ help=('Working directory for buildbot build.'
+ 'used for finding bundlefile.'))
+ parser.add_option('--target',
+ dest='target',
+ default=None,
+ help=('Buildbot build target; '
+ 'used for finding bundlefile (e.g. Debug)'))
+ parser.add_option('--no_exclusions',
+ dest='no_exclusions',
+ default=None,
+ help=('Disable the exclusion list.'))
+ parser.add_option('--dont-clear-coverage-data',
+ dest='dont_clear_coverage_data',
+ default=False,
+ action='store_true',
+ help=('Turn off clearing of cov data from a prev run'))
+ parser.add_option('-F',
+ '--test-file',
+ dest="test_files",
+ default=[],
+ action='append',
+ help=('Specify a file from which tests to be run will ' +
+ 'be extracted'))
+ return parser
+
+
+def main():
+ # Print out the args to help someone do it by hand if needed
+ print >>sys.stderr, sys.argv
+
+ # Try and clean up nice if we're killed by buildbot, Ctrl-C, ...
+ signal.signal(signal.SIGINT, TerminateSignalHandler)
+ signal.signal(signal.SIGTERM, TerminateSignalHandler)
+
+ parser = CoverageOptionParser()
+ (options, args) = parser.parse_args()
+ if options.all_unittests and options.all_browsertests:
+ print 'Error! Can not have all_unittests and all_browsertests together!'
+ sys.exit(1)
+ coverage = Coverage(options, args)
+ coverage.ClearData()
+ coverage.FindTests()
+ if options.trim:
+ coverage.TrimTests()
+ coverage.RunTests()
+ if options.genhtml:
+ coverage.GenerateHtml()
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/code_coverage/coverage_posix_unittest.py b/chromium/tools/code_coverage/coverage_posix_unittest.py
new file mode 100755
index 00000000000..3164cd3359a
--- /dev/null
+++ b/chromium/tools/code_coverage/coverage_posix_unittest.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for coverage_posix.py.
+
+Run a single test with a command such as:
+ ./coverage_posix_unittest.py CoveragePosixTest.testFindTestsAsArgs
+
+Waring that running a single test like that may interfere with the arg
+parsing tests, since coverage_posix.py uses optparse.OptionParser()
+which references globals.
+"""
+
+import coverage_posix as coverage
+import os
+import sys
+import tempfile
+import unittest
+
+class CoveragePosixTest(unittest.TestCase):
+
+
+ def setUp(self):
+ self.parseArgs()
+ self.sample_test_names = ['zippy_tests', '../base/base.gyp:base_unittests']
+
+ def confirmSampleTestsArePresent(self, tests):
+ """Confirm the tests in self.sample_test_names are in some form in 'tests'.
+
+ The Coverage object can munge them (e.g. add .exe to the end as needed.
+ Helper function for arg parsing, bundle file tests.
+
+ Args:
+ tests: the parsed tests from a Coverage object.
+ """
+ for simple_test_name in ('zippy_tests', 'base_unittests'):
+ found = False
+ for item in tests:
+ if simple_test_name in item:
+ found = True
+ break
+ self.assertTrue(found)
+ for not_test_name in ('kablammo', 'not_a_unittest'):
+ found = False
+ for item in tests:
+ if not_test_name in item:
+ found = True
+ break
+ self.assertFalse(found)
+
+ def parseArgs(self):
+ """Setup and process arg parsing."""
+ self.parser = coverage.CoverageOptionParser()
+ (self.options, self.args) = self.parser.parse_args()
+ self.options.directory = '.'
+
+ def testSanity(self):
+ """Sanity check we're able to actually run the tests.
+
+ Simply creating a Coverage instance checks a few things (e.g. on
+ Windows that the coverage tools can be found)."""
+ c = coverage.Coverage(self.options, self.args)
+
+ def testRunBasicProcess(self):
+ """Test a simple run of a subprocess."""
+ c = coverage.Coverage(self.options, self.args)
+ for code in range(2):
+ retcode = c.Run([sys.executable, '-u', '-c',
+ 'import sys; sys.exit(%d)' % code],
+ ignore_error=True)
+ self.assertEqual(code, retcode)
+
+ def testRunSlowProcess(self):
+ """Test program which prints slowly but doesn't hit our timeout.
+
+ Overall runtime is longer than the timeout but output lines
+ trickle in keeping things alive.
+ """
+ self.options.timeout = 2.5
+ c = coverage.Coverage(self.options, self.args)
+ slowscript = ('import sys, time\n'
+ 'for x in range(10):\n'
+ ' time.sleep(0.5)\n'
+ ' print "hi mom"\n'
+ 'sys.exit(0)\n')
+ retcode = c.Run([sys.executable, '-u', '-c', slowscript])
+ self.assertEqual(0, retcode)
+
+ def testRunExcessivelySlowProcess(self):
+ """Test program which DOES hit our timeout.
+
+ Initial lines should print but quickly it takes too long and
+ should be killed.
+ """
+ self.options.timeout = 2.5
+ c = coverage.Coverage(self.options, self.args)
+ slowscript = ('import time\n'
+ 'for x in range(1,10):\n'
+ ' print "sleeping for %d" % x\n'
+ ' time.sleep(x)\n')
+ self.assertRaises(Exception,
+ c.Run,
+ [sys.executable, '-u', '-c', slowscript])
+
+ def testFindTestsAsArgs(self):
+ """Test finding of tests passed as args."""
+ self.args += '--'
+ self.args += self.sample_test_names
+ c = coverage.Coverage(self.options, self.args)
+ c.FindTests()
+ self.confirmSampleTestsArePresent(c.tests)
+
+ def testFindTestsFromBundleFile(self):
+ """Test finding of tests from a bundlefile."""
+ (fd, filename) = tempfile.mkstemp()
+ f = os.fdopen(fd, 'w')
+ f.write(str(self.sample_test_names))
+ f.close()
+ self.options.bundles = filename
+ c = coverage.Coverage(self.options, self.args)
+ c.FindTests()
+ self.confirmSampleTestsArePresent(c.tests)
+ os.unlink(filename)
+
+ def testExclusionList(self):
+ """Test the gtest_filter exclusion list."""
+ c = coverage.Coverage(self.options, self.args)
+ self.assertFalse(c.GtestFilter('doesnotexist_test'))
+ fake_exclusions = { sys.platform: { 'foobar':
+ ('a','b'),
+ 'doesnotexist_test':
+ ('Evil.Crash','Naughty.Test') } }
+ self.assertFalse(c.GtestFilter('barfoo'))
+ filter = c.GtestFilter('doesnotexist_test', fake_exclusions)
+ self.assertEquals('--gtest_filter=-Evil.Crash:-Naughty.Test', filter)
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/code_coverage/croc.css b/chromium/tools/code_coverage/croc.css
new file mode 100644
index 00000000000..071822dafad
--- /dev/null
+++ b/chromium/tools/code_coverage/croc.css
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/*
+ * croc.css - styles for croc HTML output
+ */
+
+body {
+ font-family:arial;
+}
+
+table {
+ border-collapse:collapse;
+ border-width:0px;
+ border-style:solid;
+}
+
+thead {
+ background-color:#C0C0E0;
+ text-align:center;
+}
+
+td {
+ padding-right:10px;
+ padding-left:10px;
+ font-size:small;
+ border-width:1px;
+ border-style:solid;
+ border-color:black;
+}
+
+td.secdesc {
+ text-align:center;
+ font-size:medium;
+ font-weight:bold;
+ border-width:0px;
+ border-style:none;
+ padding-top:10px;
+ padding-bottom:5px;
+}
+
+td.section {
+ background-color:#D0D0F0;
+ text-align:center;
+}
+
+td.stat {
+ text-align:center;
+}
+
+td.number {
+ text-align:right;
+}
+
+td.graph {
+ /* Hide the dummy character */
+ color:#FFFFFF;
+ padding-left:6px;
+}
+
+td.high_pct {
+ text-align:right;
+ background-color:#B0FFB0;
+}
+td.mid_pct {
+ text-align:right;
+ background-color:#FFFF90;
+}
+td.low_pct {
+ text-align:right;
+ background-color:#FFB0B0;
+}
+
+
+span.missing {
+ background-color:#FFB0B0;
+}
+span.instr {
+ background-color:#FFFF90;
+}
+span.covered {
+ background-color:#B0FFB0;
+}
+
+span.g_missing {
+ background-color:#FF4040;
+}
+span.g_instr {
+ background-color:#FFFF00;
+}
+span.g_covered {
+ background-color:#40FF40;
+}
+
+p.time {
+ padding-top:10px;
+ font-size:small;
+ font-style:italic;
+}
diff --git a/chromium/tools/code_coverage/croc.py b/chromium/tools/code_coverage/croc.py
new file mode 100755
index 00000000000..1b9908a5f89
--- /dev/null
+++ b/chromium/tools/code_coverage/croc.py
@@ -0,0 +1,722 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Crocodile - compute coverage numbers for Chrome coverage dashboard."""
+
+import optparse
+import os
+import platform
+import re
+import sys
+import croc_html
+import croc_scan
+
+
+class CrocError(Exception):
+ """Coverage error."""
+
+
+class CrocStatError(CrocError):
+ """Error evaluating coverage stat."""
+
+#------------------------------------------------------------------------------
+
+
+class CoverageStats(dict):
+ """Coverage statistics."""
+
+ # Default dictionary values for this stat.
+ DEFAULTS = { 'files_covered': 0,
+ 'files_instrumented': 0,
+ 'files_executable': 0,
+ 'lines_covered': 0,
+ 'lines_instrumented': 0,
+ 'lines_executable': 0 }
+
+ def Add(self, coverage_stats):
+ """Adds a contribution from another coverage stats dict.
+
+ Args:
+ coverage_stats: Statistics to add to this one.
+ """
+ for k, v in coverage_stats.iteritems():
+ if k in self:
+ self[k] += v
+ else:
+ self[k] = v
+
+ def AddDefaults(self):
+ """Add some default stats which might be assumed present.
+
+ Do not clobber if already present. Adds resilience when evaling a
+ croc file which expects certain stats to exist."""
+ for k, v in self.DEFAULTS.iteritems():
+ if not k in self:
+ self[k] = v
+
+#------------------------------------------------------------------------------
+
+
+class CoveredFile(object):
+ """Information about a single covered file."""
+
+ def __init__(self, filename, **kwargs):
+ """Constructor.
+
+ Args:
+ filename: Full path to file, '/'-delimited.
+ kwargs: Keyword args are attributes for file.
+ """
+ self.filename = filename
+ self.attrs = dict(kwargs)
+
+ # Move these to attrs?
+ self.local_path = None # Local path to file
+ self.in_lcov = False # Is file instrumented?
+
+ # No coverage data for file yet
+ self.lines = {} # line_no -> None=executable, 0=instrumented, 1=covered
+ self.stats = CoverageStats()
+
+ def UpdateCoverage(self):
+ """Updates the coverage summary based on covered lines."""
+ exe = instr = cov = 0
+ for l in self.lines.itervalues():
+ exe += 1
+ if l is not None:
+ instr += 1
+ if l == 1:
+ cov += 1
+
+ # Add stats that always exist
+ self.stats = CoverageStats(lines_executable=exe,
+ lines_instrumented=instr,
+ lines_covered=cov,
+ files_executable=1)
+
+ # Add conditional stats
+ if cov:
+ self.stats['files_covered'] = 1
+ if instr or self.in_lcov:
+ self.stats['files_instrumented'] = 1
+
+#------------------------------------------------------------------------------
+
+
+class CoveredDir(object):
+ """Information about a directory containing covered files."""
+
+ def __init__(self, dirpath):
+ """Constructor.
+
+ Args:
+ dirpath: Full path of directory, '/'-delimited.
+ """
+ self.dirpath = dirpath
+
+ # List of covered files directly in this dir, indexed by filename (not
+ # full path)
+ self.files = {}
+
+ # List of subdirs, indexed by filename (not full path)
+ self.subdirs = {}
+
+ # Dict of CoverageStats objects summarizing all children, indexed by group
+ self.stats_by_group = {'all': CoverageStats()}
+ # TODO: by language
+
+ def GetTree(self, indent=''):
+ """Recursively gets stats for the directory and its children.
+
+ Args:
+ indent: indent prefix string.
+
+ Returns:
+ The tree as a string.
+ """
+ dest = []
+
+ # Compile all groupstats
+ groupstats = []
+ for group in sorted(self.stats_by_group):
+ s = self.stats_by_group[group]
+ if not s.get('lines_executable'):
+ continue # Skip groups with no executable lines
+ groupstats.append('%s:%d/%d/%d' % (
+ group, s.get('lines_covered', 0),
+ s.get('lines_instrumented', 0),
+ s.get('lines_executable', 0)))
+
+ outline = '%s%-30s %s' % (indent,
+ os.path.split(self.dirpath)[1] + '/',
+ ' '.join(groupstats))
+ dest.append(outline.rstrip())
+
+ for d in sorted(self.subdirs):
+ dest.append(self.subdirs[d].GetTree(indent=indent + ' '))
+
+ return '\n'.join(dest)
+
+#------------------------------------------------------------------------------
+
+
+class Coverage(object):
+ """Code coverage for a group of files."""
+
+ def __init__(self):
+ """Constructor."""
+ self.files = {} # Map filename --> CoverageFile
+ self.root_dirs = [] # (root, altname)
+ self.rules = [] # (regexp, dict of RHS attrs)
+ self.tree = CoveredDir('')
+ self.print_stats = [] # Dicts of args to PrintStat()
+
+ # Functions which need to be replaced for unit testing
+ self.add_files_walk = os.walk # Walk function for AddFiles()
+ self.scan_file = croc_scan.ScanFile # Source scanner for AddFiles()
+
+ def CleanupFilename(self, filename):
+ """Cleans up a filename.
+
+ Args:
+ filename: Input filename.
+
+ Returns:
+ The cleaned up filename.
+
+ Changes all path separators to '/'.
+ Makes relative paths (those starting with '../' or './' absolute.
+ Replaces all instances of root dirs with alternate names.
+ """
+ # Change path separators
+ filename = filename.replace('\\', '/')
+
+ # Windows doesn't care about case sensitivity.
+ if platform.system() in ['Windows', 'Microsoft']:
+ filename = filename.lower()
+
+ # If path is relative, make it absolute
+ # TODO: Perhaps we should default to relative instead, and only understand
+ # absolute to be files starting with '\', '/', or '[A-Za-z]:'?
+ if filename.split('/')[0] in ('.', '..'):
+ filename = os.path.abspath(filename).replace('\\', '/')
+
+ # Replace alternate roots
+ for root, alt_name in self.root_dirs:
+ # Windows doesn't care about case sensitivity.
+ if platform.system() in ['Windows', 'Microsoft']:
+ root = root.lower()
+ filename = re.sub('^' + re.escape(root) + '(?=(/|$))',
+ alt_name, filename)
+ return filename
+
+ def ClassifyFile(self, filename):
+ """Applies rules to a filename, to see if we care about it.
+
+ Args:
+ filename: Input filename.
+
+ Returns:
+ A dict of attributes for the file, accumulated from the right hand sides
+ of rules which fired.
+ """
+ attrs = {}
+
+ # Process all rules
+ for regexp, rhs_dict in self.rules:
+ if regexp.match(filename):
+ attrs.update(rhs_dict)
+
+ return attrs
+ # TODO: Files can belong to multiple groups?
+ # (test/source)
+ # (mac/pc/win)
+ # (media_test/all_tests)
+ # (small/med/large)
+ # How to handle that?
+
+ def AddRoot(self, root_path, alt_name='_'):
+ """Adds a root directory.
+
+ Args:
+ root_path: Root directory to add.
+ alt_name: If specified, name of root dir. Otherwise, defaults to '_'.
+
+ Raises:
+ ValueError: alt_name was blank.
+ """
+ # Alt name must not be blank. If it were, there wouldn't be a way to
+ # reverse-resolve from a root-replaced path back to the local path, since
+ # '' would always match the beginning of the candidate filename, resulting
+ # in an infinite loop.
+ if not alt_name:
+ raise ValueError('AddRoot alt_name must not be blank.')
+
+ # Clean up root path based on existing rules
+ self.root_dirs.append([self.CleanupFilename(root_path), alt_name])
+
+ def AddRule(self, path_regexp, **kwargs):
+ """Adds a rule.
+
+ Args:
+ path_regexp: Regular expression to match for filenames. These are
+ matched after root directory replacement.
+ kwargs: Keyword arguments are attributes to set if the rule applies.
+
+ Keyword arguments currently supported:
+ include: If True, includes matches; if False, excludes matches. Ignored
+ if None.
+ group: If not None, sets group to apply to matches.
+ language: If not None, sets file language to apply to matches.
+ """
+
+ # Compile regexp ahead of time
+ self.rules.append([re.compile(path_regexp), dict(kwargs)])
+
+ def GetCoveredFile(self, filename, add=False):
+ """Gets the CoveredFile object for the filename.
+
+ Args:
+ filename: Name of file to find.
+ add: If True, will add the file if it's not present. This applies the
+ transformations from AddRoot() and AddRule(), and only adds the file
+ if a rule includes it, and it has a group and language.
+
+ Returns:
+ The matching CoveredFile object, or None if not present.
+ """
+ # Clean filename
+ filename = self.CleanupFilename(filename)
+
+ # Check for existing match
+ if filename in self.files:
+ return self.files[filename]
+
+ # File isn't one we know about. If we can't add it, give up.
+ if not add:
+ return None
+
+ # Check rules to see if file can be added. Files must be included and
+ # have a group and language.
+ attrs = self.ClassifyFile(filename)
+ if not (attrs.get('include')
+ and attrs.get('group')
+ and attrs.get('language')):
+ return None
+
+ # Add the file
+ f = CoveredFile(filename, **attrs)
+ self.files[filename] = f
+
+ # Return the newly covered file
+ return f
+
+ def RemoveCoveredFile(self, cov_file):
+ """Removes the file from the covered file list.
+
+ Args:
+ cov_file: A file object returned by GetCoveredFile().
+ """
+ self.files.pop(cov_file.filename)
+
+ def ParseLcovData(self, lcov_data):
+ """Adds coverage from LCOV-formatted data.
+
+ Args:
+ lcov_data: An iterable returning lines of data in LCOV format. For
+ example, a file or list of strings.
+ """
+ cov_file = None
+ cov_lines = None
+ for line in lcov_data:
+ line = line.strip()
+ if line.startswith('SF:'):
+ # Start of data for a new file; payload is filename
+ cov_file = self.GetCoveredFile(line[3:], add=True)
+ if cov_file:
+ cov_lines = cov_file.lines
+ cov_file.in_lcov = True # File was instrumented
+ elif not cov_file:
+ # Inside data for a file we don't care about - so skip it
+ pass
+ elif line.startswith('DA:'):
+ # Data point - that is, an executable line in current file
+ line_no, is_covered = map(int, line[3:].split(','))
+ if is_covered:
+ # Line is covered
+ cov_lines[line_no] = 1
+ elif cov_lines.get(line_no) != 1:
+ # Line is not covered, so track it as uncovered
+ cov_lines[line_no] = 0
+ elif line == 'end_of_record':
+ cov_file.UpdateCoverage()
+ cov_file = None
+ # (else ignore other line types)
+
+ def ParseLcovFile(self, input_filename):
+ """Adds coverage data from a .lcov file.
+
+ Args:
+ input_filename: Input filename.
+ """
+ # TODO: All manner of error checking
+ lcov_file = None
+ try:
+ lcov_file = open(input_filename, 'rt')
+ self.ParseLcovData(lcov_file)
+ finally:
+ if lcov_file:
+ lcov_file.close()
+
+ def GetStat(self, stat, group='all', default=None):
+ """Gets a statistic from the coverage object.
+
+ Args:
+ stat: Statistic to get. May also be an evaluatable python expression,
+ using the stats. For example, 'stat1 - stat2'.
+ group: File group to match; if 'all', matches all groups.
+ default: Value to return if there was an error evaluating the stat. For
+ example, if the stat does not exist. If None, raises
+ CrocStatError.
+
+ Returns:
+ The evaluated stat, or None if error.
+
+ Raises:
+ CrocStatError: Error evaluating stat.
+ """
+ # TODO: specify a subdir to get the stat from, then walk the tree to
+ # print the stats from just that subdir
+
+ # Make sure the group exists
+ if group not in self.tree.stats_by_group:
+ if default is None:
+ raise CrocStatError('Group %r not found.' % group)
+ else:
+ return default
+
+ stats = self.tree.stats_by_group[group]
+ # Unit tests use real dicts, not CoverageStats objects,
+ # so we can't AddDefaults() on them.
+ if group == 'all' and hasattr(stats, 'AddDefaults'):
+ stats.AddDefaults()
+ try:
+ return eval(stat, {'__builtins__': {'S': self.GetStat}}, stats)
+ except Exception, e:
+ if default is None:
+ raise CrocStatError('Error evaluating stat %r: %s' % (stat, e))
+ else:
+ return default
+
+ def PrintStat(self, stat, format=None, outfile=sys.stdout, **kwargs):
+ """Prints a statistic from the coverage object.
+
+ Args:
+ stat: Statistic to get. May also be an evaluatable python expression,
+ using the stats. For example, 'stat1 - stat2'.
+ format: Format string to use when printing stat. If None, prints the
+ stat and its evaluation.
+ outfile: File stream to output stat to; defaults to stdout.
+ kwargs: Additional args to pass to GetStat().
+ """
+ s = self.GetStat(stat, **kwargs)
+ if format is None:
+ outfile.write('GetStat(%r) = %s\n' % (stat, s))
+ else:
+ outfile.write(format % s + '\n')
+
+ def AddFiles(self, src_dir):
+ """Adds files to coverage information.
+
+ LCOV files only contains files which are compiled and instrumented as part
+ of running coverage. This function finds missing files and adds them.
+
+ Args:
+ src_dir: Directory on disk at which to start search. May be a relative
+ path on disk starting with '.' or '..', or an absolute path, or a
+ path relative to an alt_name for one of the roots
+ (for example, '_/src'). If the alt_name matches more than one root,
+ all matches will be attempted.
+
+ Note that dirs not underneath one of the root dirs and covered by an
+ inclusion rule will be ignored.
+ """
+ # Check for root dir alt_names in the path and replace with the actual
+ # root dirs, then recurse.
+ found_root = False
+ for root, alt_name in self.root_dirs:
+ replaced_root = re.sub('^' + re.escape(alt_name) + '(?=(/|$))', root,
+ src_dir)
+ if replaced_root != src_dir:
+ found_root = True
+ self.AddFiles(replaced_root)
+ if found_root:
+ return # Replaced an alt_name with a root_dir, so already recursed.
+
+ for (dirpath, dirnames, filenames) in self.add_files_walk(src_dir):
+ # Make a copy of the dirnames list so we can modify the original to
+ # prune subdirs we don't need to walk.
+ for d in list(dirnames):
+ # Add trailing '/' to directory names so dir-based regexps can match
+ # '/' instead of needing to specify '(/|$)'.
+ dpath = self.CleanupFilename(dirpath + '/' + d) + '/'
+ attrs = self.ClassifyFile(dpath)
+ if not attrs.get('include'):
+ # Directory has been excluded, so don't traverse it
+ # TODO: Document the slight weirdness caused by this: If you
+ # AddFiles('./A'), and the rules include 'A/B/C/D' but not 'A/B',
+ # then it won't recurse into './A/B' so won't find './A/B/C/D'.
+ # Workarounds are to AddFiles('./A/B/C/D') or AddFiles('./A/B/C').
+ # The latter works because it explicitly walks the contents of the
+ # path passed to AddFiles(), so it finds './A/B/C/D'.
+ dirnames.remove(d)
+
+ for f in filenames:
+ local_path = dirpath + '/' + f
+
+ covf = self.GetCoveredFile(local_path, add=True)
+ if not covf:
+ continue
+
+ # Save where we found the file, for generating line-by-line HTML output
+ covf.local_path = local_path
+
+ if covf.in_lcov:
+ # File already instrumented and doesn't need to be scanned
+ continue
+
+ if not covf.attrs.get('add_if_missing', 1):
+ # Not allowed to add the file
+ self.RemoveCoveredFile(covf)
+ continue
+
+ # Scan file to find potentially-executable lines
+ lines = self.scan_file(covf.local_path, covf.attrs.get('language'))
+ if lines:
+ for l in lines:
+ covf.lines[l] = None
+ covf.UpdateCoverage()
+ else:
+ # File has no executable lines, so don't count it
+ self.RemoveCoveredFile(covf)
+
+ def AddConfig(self, config_data, lcov_queue=None, addfiles_queue=None):
+ """Adds JSON-ish config data.
+
+ Args:
+ config_data: Config data string.
+ lcov_queue: If not None, object to append lcov_files to instead of
+ parsing them immediately.
+ addfiles_queue: If not None, object to append add_files to instead of
+ processing them immediately.
+ """
+ # TODO: All manner of error checking
+ cfg = eval(config_data, {'__builtins__': {}}, {})
+
+ for rootdict in cfg.get('roots', []):
+ self.AddRoot(rootdict['root'], alt_name=rootdict.get('altname', '_'))
+
+ for ruledict in cfg.get('rules', []):
+ regexp = ruledict.pop('regexp')
+ self.AddRule(regexp, **ruledict)
+
+ for add_lcov in cfg.get('lcov_files', []):
+ if lcov_queue is not None:
+ lcov_queue.append(add_lcov)
+ else:
+ self.ParseLcovFile(add_lcov)
+
+ for add_path in cfg.get('add_files', []):
+ if addfiles_queue is not None:
+ addfiles_queue.append(add_path)
+ else:
+ self.AddFiles(add_path)
+
+ self.print_stats += cfg.get('print_stats', [])
+
+ def ParseConfig(self, filename, **kwargs):
+ """Parses a configuration file.
+
+ Args:
+ filename: Config filename.
+ kwargs: Additional parameters to pass to AddConfig().
+ """
+ # TODO: All manner of error checking
+ f = None
+ try:
+ f = open(filename, 'rt')
+ # Need to strip CR's from CRLF-terminated lines or posix systems can't
+ # eval the data.
+ config_data = f.read().replace('\r\n', '\n')
+ # TODO: some sort of include syntax.
+ #
+ # Needs to be done at string-time rather than at eval()-time, so that
+ # it's possible to include parts of dicts. Path from a file to its
+ # include should be relative to the dir containing the file.
+ #
+ # Or perhaps it could be done after eval. In that case, there'd be an
+ # 'include' section with a list of files to include. Those would be
+ # eval()'d and recursively pre- or post-merged with the including file.
+ #
+ # Or maybe just don't worry about it, since multiple configs can be
+ # specified on the command line.
+ self.AddConfig(config_data, **kwargs)
+ finally:
+ if f:
+ f.close()
+
+ def UpdateTreeStats(self):
+ """Recalculates the tree stats from the currently covered files.
+
+ Also calculates coverage summary for files.
+ """
+ self.tree = CoveredDir('')
+ for cov_file in self.files.itervalues():
+ # Add the file to the tree
+ fdirs = cov_file.filename.split('/')
+ parent = self.tree
+ ancestors = [parent]
+ for d in fdirs[:-1]:
+ if d not in parent.subdirs:
+ if parent.dirpath:
+ parent.subdirs[d] = CoveredDir(parent.dirpath + '/' + d)
+ else:
+ parent.subdirs[d] = CoveredDir(d)
+ parent = parent.subdirs[d]
+ ancestors.append(parent)
+ # Final subdir actually contains the file
+ parent.files[fdirs[-1]] = cov_file
+
+ # Now add file's contribution to coverage by dir
+ for a in ancestors:
+ # Add to 'all' group
+ a.stats_by_group['all'].Add(cov_file.stats)
+
+ # Add to group file belongs to
+ group = cov_file.attrs.get('group')
+ if group not in a.stats_by_group:
+ a.stats_by_group[group] = CoverageStats()
+ cbyg = a.stats_by_group[group]
+ cbyg.Add(cov_file.stats)
+
+ def PrintTree(self):
+ """Prints the tree stats."""
+ # Print the tree
+ print 'Lines of code coverage by directory:'
+ print self.tree.GetTree()
+
+#------------------------------------------------------------------------------
+
+
+def Main(argv):
+ """Main routine.
+
+ Args:
+ argv: list of arguments
+
+ Returns:
+ exit code, 0 for normal exit.
+ """
+ # Parse args
+ parser = optparse.OptionParser()
+ parser.add_option(
+ '-i', '--input', dest='inputs', type='string', action='append',
+ metavar='FILE',
+ help='read LCOV input from FILE')
+ parser.add_option(
+ '-r', '--root', dest='roots', type='string', action='append',
+ metavar='ROOT[=ALTNAME]',
+ help='add ROOT directory, optionally map in coverage results as ALTNAME')
+ parser.add_option(
+ '-c', '--config', dest='configs', type='string', action='append',
+ metavar='FILE',
+ help='read settings from configuration FILE')
+ parser.add_option(
+ '-a', '--addfiles', dest='addfiles', type='string', action='append',
+ metavar='PATH',
+ help='add files from PATH to coverage data')
+ parser.add_option(
+ '-t', '--tree', dest='tree', action='store_true',
+ help='print tree of code coverage by group')
+ parser.add_option(
+ '-u', '--uninstrumented', dest='uninstrumented', action='store_true',
+ help='list uninstrumented files')
+ parser.add_option(
+ '-m', '--html', dest='html_out', type='string', metavar='PATH',
+ help='write HTML output to PATH')
+ parser.add_option(
+ '-b', '--base_url', dest='base_url', type='string', metavar='URL',
+ help='include URL in base tag of HTML output')
+
+ parser.set_defaults(
+ inputs=[],
+ roots=[],
+ configs=[],
+ addfiles=[],
+ tree=False,
+ html_out=None,
+ )
+
+ options = parser.parse_args(args=argv)[0]
+
+ cov = Coverage()
+
+ # Set root directories for coverage
+ for root_opt in options.roots:
+ if '=' in root_opt:
+ cov.AddRoot(*root_opt.split('='))
+ else:
+ cov.AddRoot(root_opt)
+
+ # Read config files
+ for config_file in options.configs:
+ cov.ParseConfig(config_file, lcov_queue=options.inputs,
+ addfiles_queue=options.addfiles)
+
+ # Parse lcov files
+ for input_filename in options.inputs:
+ cov.ParseLcovFile(input_filename)
+
+ # Add missing files
+ for add_path in options.addfiles:
+ cov.AddFiles(add_path)
+
+ # Print help if no files specified
+ if not cov.files:
+ print 'No covered files found.'
+ parser.print_help()
+ return 1
+
+ # Update tree stats
+ cov.UpdateTreeStats()
+
+ # Print uninstrumented filenames
+ if options.uninstrumented:
+ print 'Uninstrumented files:'
+ for f in sorted(cov.files):
+ covf = cov.files[f]
+ if not covf.in_lcov:
+ print ' %-6s %-6s %s' % (covf.attrs.get('group'),
+ covf.attrs.get('language'), f)
+
+ # Print tree stats
+ if options.tree:
+ cov.PrintTree()
+
+ # Print stats
+ for ps_args in cov.print_stats:
+ cov.PrintStat(**ps_args)
+
+ # Generate HTML
+ if options.html_out:
+ html = croc_html.CrocHtml(cov, options.html_out, options.base_url)
+ html.Write()
+
+ # Normal exit
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/chromium/tools/code_coverage/croc_html.py b/chromium/tools/code_coverage/croc_html.py
new file mode 100644
index 00000000000..7866f472f7b
--- /dev/null
+++ b/chromium/tools/code_coverage/croc_html.py
@@ -0,0 +1,451 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Crocodile HTML output."""
+
+import os
+import shutil
+import time
+import xml.dom
+
+
+class CrocHtmlError(Exception):
+ """Coverage HTML error."""
+
+
+class HtmlElement(object):
+ """Node in a HTML file."""
+
+ def __init__(self, doc, element):
+ """Constructor.
+
+ Args:
+ doc: XML document object.
+ element: XML element.
+ """
+ self.doc = doc
+ self.element = element
+
+ def E(self, name, **kwargs):
+ """Adds a child element.
+
+ Args:
+ name: Name of element.
+ kwargs: Attributes for element. To use an attribute which is a python
+ reserved word (i.e. 'class'), prefix the attribute name with 'e_'.
+
+ Returns:
+ The child element.
+ """
+ he = HtmlElement(self.doc, self.doc.createElement(name))
+ element = he.element
+ self.element.appendChild(element)
+
+ for k, v in kwargs.iteritems():
+ if k.startswith('e_'):
+ # Remove prefix
+ element.setAttribute(k[2:], str(v))
+ else:
+ element.setAttribute(k, str(v))
+
+ return he
+
+ def Text(self, text):
+ """Adds a text node.
+
+ Args:
+ text: Text to add.
+
+ Returns:
+ self.
+ """
+ t = self.doc.createTextNode(str(text))
+ self.element.appendChild(t)
+ return self
+
+
+class HtmlFile(object):
+ """HTML file."""
+
+ def __init__(self, xml_impl, filename):
+ """Constructor.
+
+ Args:
+ xml_impl: DOMImplementation to use to create document.
+ filename: Path to file.
+ """
+ self.xml_impl = xml_impl
+ doctype = xml_impl.createDocumentType(
+ 'HTML', '-//W3C//DTD HTML 4.01//EN',
+ 'http://www.w3.org/TR/html4/strict.dtd')
+ self.doc = xml_impl.createDocument(None, 'html', doctype)
+ self.filename = filename
+
+ # Create head and body elements
+ root = HtmlElement(self.doc, self.doc.documentElement)
+ self.head = root.E('head')
+ self.body = root.E('body')
+
+ def Write(self, cleanup=True):
+ """Writes the file.
+
+ Args:
+ cleanup: If True, calls unlink() on the internal xml document. This
+ frees up memory, but means that you can't use this file for anything
+ else.
+ """
+ f = open(self.filename, 'wt')
+ self.doc.writexml(f, encoding='UTF-8')
+ f.close()
+
+ if cleanup:
+ self.doc.unlink()
+ # Prevent future uses of the doc now that we've unlinked it
+ self.doc = None
+
+#------------------------------------------------------------------------------
+
+COV_TYPE_STRING = {None: 'm', 0: 'i', 1: 'E', 2: ' '}
+COV_TYPE_CLASS = {None: 'missing', 0: 'instr', 1: 'covered', 2: ''}
+
+
+class CrocHtml(object):
+ """Crocodile HTML output class."""
+
+ def __init__(self, cov, output_root, base_url=None):
+ """Constructor."""
+ self.cov = cov
+ self.output_root = output_root
+ self.base_url = base_url
+ self.xml_impl = xml.dom.getDOMImplementation()
+ self.time_string = 'Coverage information generated %s.' % time.asctime()
+
+ def CreateHtmlDoc(self, filename, title):
+ """Creates a new HTML document.
+
+ Args:
+ filename: Filename to write to, relative to self.output_root.
+ title: Title of page
+
+ Returns:
+ The document.
+ """
+ f = HtmlFile(self.xml_impl, self.output_root + '/' + filename)
+
+ f.head.E('title').Text(title)
+
+ if self.base_url:
+ css_href = self.base_url + 'croc.css'
+ base_href = self.base_url + os.path.dirname(filename)
+ if not base_href.endswith('/'):
+ base_href += '/'
+ f.head.E('base', href=base_href)
+ else:
+ css_href = '../' * (len(filename.split('/')) - 1) + 'croc.css'
+
+ f.head.E('link', rel='stylesheet', type='text/css', href=css_href)
+
+ return f
+
+ def AddCaptionForFile(self, body, path):
+ """Adds a caption for the file, with links to each parent dir.
+
+ Args:
+ body: Body elemement.
+ path: Path to file.
+ """
+ # This is slightly different that for subdir, because it needs to have a
+ # link to the current directory's index.html.
+ hdr = body.E('h2')
+ hdr.Text('Coverage for ')
+ dirs = [''] + path.split('/')
+ num_dirs = len(dirs)
+ for i in range(num_dirs - 1):
+ hdr.E('a', href=(
+ '../' * (num_dirs - i - 2) + 'index.html')).Text(dirs[i] + '/')
+ hdr.Text(dirs[-1])
+
+ def AddCaptionForSubdir(self, body, path):
+ """Adds a caption for the subdir, with links to each parent dir.
+
+ Args:
+ body: Body elemement.
+ path: Path to subdir.
+ """
+ # Link to parent dirs
+ hdr = body.E('h2')
+ hdr.Text('Coverage for ')
+ dirs = [''] + path.split('/')
+ num_dirs = len(dirs)
+ for i in range(num_dirs - 1):
+ hdr.E('a', href=(
+ '../' * (num_dirs - i - 1) + 'index.html')).Text(dirs[i] + '/')
+ hdr.Text(dirs[-1] + '/')
+
+ def AddSectionHeader(self, table, caption, itemtype, is_file=False):
+ """Adds a section header to the coverage table.
+
+ Args:
+ table: Table to add rows to.
+ caption: Caption for section, if not None.
+ itemtype: Type of items in this section, if not None.
+ is_file: Are items in this section files?
+ """
+
+ if caption is not None:
+ table.E('tr').E('th', e_class='secdesc', colspan=8).Text(caption)
+
+ sec_hdr = table.E('tr')
+
+ if itemtype is not None:
+ sec_hdr.E('th', e_class='section').Text(itemtype)
+
+ sec_hdr.E('th', e_class='section').Text('Coverage')
+ sec_hdr.E('th', e_class='section', colspan=3).Text(
+ 'Lines executed / instrumented / missing')
+
+ graph = sec_hdr.E('th', e_class='section')
+ graph.E('span', style='color:#00FF00').Text('exe')
+ graph.Text(' / ')
+ graph.E('span', style='color:#FFFF00').Text('inst')
+ graph.Text(' / ')
+ graph.E('span', style='color:#FF0000').Text('miss')
+
+ if is_file:
+ sec_hdr.E('th', e_class='section').Text('Language')
+ sec_hdr.E('th', e_class='section').Text('Group')
+ else:
+ sec_hdr.E('th', e_class='section', colspan=2)
+
+ def AddItem(self, table, itemname, stats, attrs, link=None):
+ """Adds a bar graph to the element. This is a series of <td> elements.
+
+ Args:
+ table: Table to add item to.
+ itemname: Name of item.
+ stats: Stats object.
+ attrs: Attributes dictionary; if None, no attributes will be printed.
+ link: Destination for itemname hyperlink, if not None.
+ """
+ row = table.E('tr')
+
+ # Add item name
+ if itemname is not None:
+ item_elem = row.E('td')
+ if link is not None:
+ item_elem = item_elem.E('a', href=link)
+ item_elem.Text(itemname)
+
+ # Get stats
+ stat_exe = stats.get('lines_executable', 0)
+ stat_ins = stats.get('lines_instrumented', 0)
+ stat_cov = stats.get('lines_covered', 0)
+
+ percent = row.E('td')
+
+ # Add text
+ row.E('td', e_class='number').Text(stat_cov)
+ row.E('td', e_class='number').Text(stat_ins)
+ row.E('td', e_class='number').Text(stat_exe - stat_ins)
+
+ # Add percent and graph; only fill in if there's something in there
+ graph = row.E('td', e_class='graph', width=100)
+ if stat_exe:
+ percent_cov = 100.0 * stat_cov / stat_exe
+ percent_ins = 100.0 * stat_ins / stat_exe
+
+ # Color percent based on thresholds
+ percent.Text('%.1f%%' % percent_cov)
+ if percent_cov >= 80:
+ percent.element.setAttribute('class', 'high_pct')
+ elif percent_cov >= 60:
+ percent.element.setAttribute('class', 'mid_pct')
+ else:
+ percent.element.setAttribute('class', 'low_pct')
+
+ # Graphs use integer values
+ percent_cov = int(percent_cov)
+ percent_ins = int(percent_ins)
+
+ graph.Text('.')
+ graph.E('span', style='padding-left:%dpx' % percent_cov,
+ e_class='g_covered')
+ graph.E('span', style='padding-left:%dpx' % (percent_ins - percent_cov),
+ e_class='g_instr')
+ graph.E('span', style='padding-left:%dpx' % (100 - percent_ins),
+ e_class='g_missing')
+
+ if attrs:
+ row.E('td', e_class='stat').Text(attrs.get('language'))
+ row.E('td', e_class='stat').Text(attrs.get('group'))
+ else:
+ row.E('td', colspan=2)
+
+ def WriteFile(self, cov_file):
+ """Writes the HTML for a file.
+
+ Args:
+ cov_file: croc.CoveredFile to write.
+ """
+ print ' ' + cov_file.filename
+ title = 'Coverage for ' + cov_file.filename
+
+ f = self.CreateHtmlDoc(cov_file.filename + '.html', title)
+ body = f.body
+
+ # Write header section
+ self.AddCaptionForFile(body, cov_file.filename)
+
+ # Summary for this file
+ table = body.E('table')
+ self.AddSectionHeader(table, None, None, is_file=True)
+ self.AddItem(table, None, cov_file.stats, cov_file.attrs)
+
+ body.E('h2').Text('Line-by-line coverage:')
+
+ # Print line-by-line coverage
+ if cov_file.local_path:
+ code_table = body.E('table').E('tr').E('td').E('pre')
+
+ flines = open(cov_file.local_path, 'rt')
+ lineno = 0
+
+ for line in flines:
+ lineno += 1
+ line_cov = cov_file.lines.get(lineno, 2)
+ e_class = COV_TYPE_CLASS.get(line_cov)
+
+ code_table.E('span', e_class=e_class).Text('%4d %s : %s\n' % (
+ lineno,
+ COV_TYPE_STRING.get(line_cov),
+ line.rstrip()
+ ))
+
+ else:
+ body.Text('Line-by-line coverage not available. Make sure the directory'
+ ' containing this file has been scanned via ')
+ body.E('B').Text('add_files')
+ body.Text(' in a configuration file, or the ')
+ body.E('B').Text('--addfiles')
+ body.Text(' command line option.')
+
+ # TODO: if file doesn't have a local path, try to find it by
+ # reverse-mapping roots and searching for the file.
+
+ body.E('p', e_class='time').Text(self.time_string)
+ f.Write()
+
+ def WriteSubdir(self, cov_dir):
+ """Writes the index.html for a subdirectory.
+
+ Args:
+ cov_dir: croc.CoveredDir to write.
+ """
+ print ' ' + cov_dir.dirpath + '/'
+
+ # Create the subdir if it doesn't already exist
+ subdir = self.output_root + '/' + cov_dir.dirpath
+ if not os.path.exists(subdir):
+ os.mkdir(subdir)
+
+ if cov_dir.dirpath:
+ title = 'Coverage for ' + cov_dir.dirpath + '/'
+ f = self.CreateHtmlDoc(cov_dir.dirpath + '/index.html', title)
+ else:
+ title = 'Coverage summary'
+ f = self.CreateHtmlDoc('index.html', title)
+
+ body = f.body
+
+ dirs = [''] + cov_dir.dirpath.split('/')
+ num_dirs = len(dirs)
+ sort_jsfile = '../' * (num_dirs - 1) + 'sorttable.js'
+ script = body.E('script', src=sort_jsfile)
+ body.E('/script')
+
+ # Write header section
+ if cov_dir.dirpath:
+ self.AddCaptionForSubdir(body, cov_dir.dirpath)
+ else:
+ body.E('h2').Text(title)
+
+ table = body.E('table', e_class='sortable')
+ table.E('h3').Text('Coverage by Group')
+ # Coverage by group
+ self.AddSectionHeader(table, None, 'Group')
+
+ for group in sorted(cov_dir.stats_by_group):
+ self.AddItem(table, group, cov_dir.stats_by_group[group], None)
+
+ # List subdirs
+ if cov_dir.subdirs:
+ table = body.E('table', e_class='sortable')
+ table.E('h3').Text('Subdirectories')
+ self.AddSectionHeader(table, None, 'Subdirectory')
+
+ for d in sorted(cov_dir.subdirs):
+ self.AddItem(table, d + '/', cov_dir.subdirs[d].stats_by_group['all'],
+ None, link=d + '/index.html')
+
+ # List files
+ if cov_dir.files:
+ table = body.E('table', e_class='sortable')
+ table.E('h3').Text('Files in This Directory')
+ self.AddSectionHeader(table, None, 'Filename',
+ is_file=True)
+
+ for filename in sorted(cov_dir.files):
+ cov_file = cov_dir.files[filename]
+ self.AddItem(table, filename, cov_file.stats, cov_file.attrs,
+ link=filename + '.html')
+
+ body.E('p', e_class='time').Text(self.time_string)
+ f.Write()
+
+ def WriteRoot(self):
+ """Writes the files in the output root."""
+ # Find ourselves
+ src_dir = os.path.split(self.WriteRoot.func_code.co_filename)[0]
+
+ # Files to copy into output root
+ copy_files = ['croc.css']
+ # Third_party files to copy into output root
+ third_party_files = ['sorttable.js']
+
+ # Copy files from our directory into the output directory
+ for copy_file in copy_files:
+ print ' Copying %s' % copy_file
+ shutil.copyfile(os.path.join(src_dir, copy_file),
+ os.path.join(self.output_root, copy_file))
+ # Copy third party files from third_party directory into
+ # the output directory
+ src_dir = os.path.join(src_dir, 'third_party')
+ for third_party_file in third_party_files:
+ print ' Copying %s' % third_party_file
+ shutil.copyfile(os.path.join(src_dir, third_party_file),
+ os.path.join(self.output_root, third_party_file))
+
+ def Write(self):
+ """Writes HTML output."""
+
+ print 'Writing HTML to %s...' % self.output_root
+
+ # Loop through the tree and write subdirs, breadth-first
+ # TODO: switch to depth-first and sort values - makes nicer output?
+ todo = [self.cov.tree]
+ while todo:
+ cov_dir = todo.pop(0)
+
+ # Append subdirs to todo list
+ todo += cov_dir.subdirs.values()
+
+ # Write this subdir
+ self.WriteSubdir(cov_dir)
+
+ # Write files in this subdir
+ for cov_file in cov_dir.files.itervalues():
+ self.WriteFile(cov_file)
+
+ # Write files in root directory
+ self.WriteRoot()
diff --git a/chromium/tools/code_coverage/croc_scan.py b/chromium/tools/code_coverage/croc_scan.py
new file mode 100644
index 00000000000..8d0e2e8df2a
--- /dev/null
+++ b/chromium/tools/code_coverage/croc_scan.py
@@ -0,0 +1,164 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Crocodile source scanners."""
+
+
+import re
+
+
+class Scanner(object):
+ """Generic source scanner."""
+
+ def __init__(self):
+ """Constructor."""
+
+ self.re_token = re.compile('#')
+ self.comment_to_eol = ['#']
+ self.comment_start = None
+ self.comment_end = None
+
+ def ScanLines(self, lines):
+ """Scans the lines for executable statements.
+
+ Args:
+ lines: Iterator returning source lines.
+
+ Returns:
+ An array of line numbers which are executable.
+ """
+ exe_lines = []
+ lineno = 0
+
+ in_string = None
+ in_comment = None
+ comment_index = None
+
+ for line in lines:
+ lineno += 1
+ in_string_at_start = in_string
+
+ for t in self.re_token.finditer(line):
+ tokenstr = t.groups()[0]
+
+ if in_comment:
+ # Inside a multi-line comment, so look for end token
+ if tokenstr == in_comment:
+ in_comment = None
+ # Replace comment with spaces
+ line = (line[:comment_index]
+ + ' ' * (t.end(0) - comment_index)
+ + line[t.end(0):])
+
+ elif in_string:
+ # Inside a string, so look for end token
+ if tokenstr == in_string:
+ in_string = None
+
+ elif tokenstr in self.comment_to_eol:
+ # Single-line comment, so truncate line at start of token
+ line = line[:t.start(0)]
+ break
+
+ elif tokenstr == self.comment_start:
+ # Multi-line comment start - end token is comment_end
+ in_comment = self.comment_end
+ comment_index = t.start(0)
+
+ else:
+ # Starting a string - end token is same as start
+ in_string = tokenstr
+
+ # If still in comment at end of line, remove comment
+ if in_comment:
+ line = line[:comment_index]
+ # Next line, delete from the beginnine
+ comment_index = 0
+
+ # If line-sans-comments is not empty, claim it may be executable
+ if line.strip() or in_string_at_start:
+ exe_lines.append(lineno)
+
+ # Return executable lines
+ return exe_lines
+
+ def Scan(self, filename):
+ """Reads the file and scans its lines.
+
+ Args:
+ filename: Path to file to scan.
+
+ Returns:
+ An array of line numbers which are executable.
+ """
+
+ # TODO: All manner of error checking
+ f = None
+ try:
+ f = open(filename, 'rt')
+ return self.ScanLines(f)
+ finally:
+ if f:
+ f.close()
+
+
+class PythonScanner(Scanner):
+ """Python source scanner."""
+
+ def __init__(self):
+ """Constructor."""
+ Scanner.__init__(self)
+
+ # TODO: This breaks for strings ending in more than 2 backslashes. Need
+ # a pattern which counts only an odd number of backslashes, so the last
+ # one thus escapes the quote.
+ self.re_token = re.compile(r'(#|\'\'\'|"""|(?<!(?<!\\)\\)["\'])')
+ self.comment_to_eol = ['#']
+ self.comment_start = None
+ self.comment_end = None
+
+
+class CppScanner(Scanner):
+ """C / C++ / ObjC / ObjC++ source scanner."""
+
+ def __init__(self):
+ """Constructor."""
+ Scanner.__init__(self)
+
+ # TODO: This breaks for strings ending in more than 2 backslashes. Need
+ # a pattern which counts only an odd number of backslashes, so the last
+ # one thus escapes the quote.
+ self.re_token = re.compile(r'(^\s*#|//|/\*|\*/|(?<!(?<!\\)\\)["\'])')
+
+ # TODO: Treat '\' at EOL as a token, and handle it as continuing the
+ # previous line. That is, if in a comment-to-eol, this line is a comment
+ # too.
+
+ # Note that we treat # at beginning of line as a comment, so that we ignore
+ # preprocessor definitions
+ self.comment_to_eol = ['//', '#']
+
+ self.comment_start = '/*'
+ self.comment_end = '*/'
+
+
+def ScanFile(filename, language):
+ """Scans a file for executable lines.
+
+ Args:
+ filename: Path to file to scan.
+ language: Language for file ('C', 'C++', 'python', 'ObjC', 'ObjC++')
+
+ Returns:
+ A list of executable lines, or an empty list if the file was not a handled
+ language.
+ """
+
+ if language == 'python':
+ return PythonScanner().Scan(filename)
+ elif language in ['C', 'C++', 'ObjC', 'ObjC++']:
+ return CppScanner().Scan(filename)
+
+ # Something we don't handle
+ return []
diff --git a/chromium/tools/code_coverage/croc_scan_test.py b/chromium/tools/code_coverage/croc_scan_test.py
new file mode 100755
index 00000000000..a69b28aac5c
--- /dev/null
+++ b/chromium/tools/code_coverage/croc_scan_test.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for croc_scan.py."""
+
+import re
+import unittest
+import croc_scan
+
+
+class TestScanner(unittest.TestCase):
+ """Tests for croc_scan.Scanner."""
+
+ def testInit(self):
+ """Test __init()__."""
+ s = croc_scan.Scanner()
+
+ self.assertEqual(s.re_token.pattern, '#')
+ self.assertEqual(s.comment_to_eol, ['#'])
+ self.assertEqual(s.comment_start, None)
+ self.assertEqual(s.comment_end, None)
+
+ def testScanLines(self):
+ """Test ScanLines()."""
+ s = croc_scan.Scanner()
+ # Set up imaginary language:
+ # ':' = comment to EOL
+ # '"' = string start/end
+ # '(' = comment start
+ # ')' = comment end
+ s.re_token = re.compile(r'([\:\"\(\)])')
+ s.comment_to_eol = [':']
+ s.comment_start = '('
+ s.comment_end = ')'
+
+ # No input file = no output lines
+ self.assertEqual(s.ScanLines([]), [])
+
+ # Empty lines and lines with only whitespace are ignored
+ self.assertEqual(s.ScanLines([
+ '', # 1
+ 'line', # 2 exe
+ ' \t ', # 3
+ ]), [2])
+
+ # Comments to EOL are stripped, but not inside strings
+ self.assertEqual(s.ScanLines([
+ 'test', # 1 exe
+ ' : A comment', # 2
+ '"a : in a string"', # 3 exe
+ 'test2 : with comment to EOL', # 4 exe
+ 'foo = "a multiline string with an empty line', # 5 exe
+ '', # 6 exe
+ ': and a comment-to-EOL character"', # 7 exe
+ ': done', # 8
+ ]), [1, 3, 4, 5, 6, 7])
+
+ # Test Comment start/stop detection
+ self.assertEqual(s.ScanLines([
+ '( a comment on one line)', # 1
+ 'text (with a comment)', # 2 exe
+ '( a comment with a : in the middle)', # 3
+ '( a multi-line', # 4
+ ' comment)', # 5
+ 'a string "with a ( in it"', # 6 exe
+ 'not in a multi-line comment', # 7 exe
+ '(a comment with a " in it)', # 8
+ ': not in a string, so this gets stripped', # 9
+ 'more text "with an uninteresting string"', # 10 exe
+ ]), [2, 6, 7, 10])
+
+ # TODO: Test Scan(). Low priority, since it just wraps ScanLines().
+
+
+class TestPythonScanner(unittest.TestCase):
+ """Tests for croc_scan.PythonScanner."""
+
+ def testScanLines(self):
+ """Test ScanLines()."""
+ s = croc_scan.PythonScanner()
+
+ # No input file = no output lines
+ self.assertEqual(s.ScanLines([]), [])
+
+ self.assertEqual(s.ScanLines([
+ '# a comment', # 1
+ '', # 2
+ '"""multi-line string', # 3 exe
+ '# not a comment', # 4 exe
+ 'end of multi-line string"""', # 5 exe
+ ' ', # 6
+ '"single string with #comment"', # 7 exe
+ '', # 8
+ '\'\'\'multi-line string, single-quote', # 9 exe
+ '# not a comment', # 10 exe
+ 'end of multi-line string\'\'\'', # 11 exe
+ '', # 12
+ '"string with embedded \\" is handled"', # 13 exe
+ '# quoted "', # 14
+ '"\\""', # 15 exe
+ '# quoted backslash', # 16
+ '"\\\\"', # 17 exe
+ 'main()', # 18 exe
+ '# end', # 19
+ ]), [3, 4, 5, 7, 9, 10, 11, 13, 15, 17, 18])
+
+
+class TestCppScanner(unittest.TestCase):
+ """Tests for croc_scan.CppScanner."""
+
+ def testScanLines(self):
+ """Test ScanLines()."""
+ s = croc_scan.CppScanner()
+
+ # No input file = no output lines
+ self.assertEqual(s.ScanLines([]), [])
+
+ self.assertEqual(s.ScanLines([
+ '// a comment', # 1
+ '# a preprocessor define', # 2
+ '', # 3
+ '\'#\', \'"\'', # 4 exe
+ '', # 5
+ '/* a multi-line comment', # 6
+ 'with a " in it', # 7
+ '*/', # 8
+ '', # 9
+ '"a string with /* and \' in it"', # 10 exe
+ '', # 11
+ '"a multi-line string\\', # 12 exe
+ '// not a comment\\', # 13 exe
+ 'ending here"', # 14 exe
+ '', # 15
+ '"string with embedded \\" is handled"', # 16 exe
+ '', # 17
+ 'main()', # 18 exe
+ '// end', # 19
+ ]), [4, 10, 12, 13, 14, 16, 18])
+
+
+class TestScanFile(unittest.TestCase):
+ """Tests for croc_scan.ScanFile()."""
+
+ class MockScanner(object):
+ """Mock scanner."""
+
+ def __init__(self, language):
+ """Constructor."""
+ self.language = language
+
+ def Scan(self, filename):
+ """Mock Scan() method."""
+ return 'scan %s %s' % (self.language, filename)
+
+ def MockPythonScanner(self):
+ return self.MockScanner('py')
+
+ def MockCppScanner(self):
+ return self.MockScanner('cpp')
+
+ def setUp(self):
+ """Per-test setup."""
+ # Hook scanners
+ self.old_python_scanner = croc_scan.PythonScanner
+ self.old_cpp_scanner = croc_scan.CppScanner
+ croc_scan.PythonScanner = self.MockPythonScanner
+ croc_scan.CppScanner = self.MockCppScanner
+
+ def tearDown(self):
+ """Per-test cleanup."""
+ croc_scan.PythonScanner = self.old_python_scanner
+ croc_scan.CppScanner = self.old_cpp_scanner
+
+ def testScanFile(self):
+ """Test ScanFile()."""
+ self.assertEqual(croc_scan.ScanFile('foo', 'python'), 'scan py foo')
+ self.assertEqual(croc_scan.ScanFile('bar1', 'C'), 'scan cpp bar1')
+ self.assertEqual(croc_scan.ScanFile('bar2', 'C++'), 'scan cpp bar2')
+ self.assertEqual(croc_scan.ScanFile('bar3', 'ObjC'), 'scan cpp bar3')
+ self.assertEqual(croc_scan.ScanFile('bar4', 'ObjC++'), 'scan cpp bar4')
+ self.assertEqual(croc_scan.ScanFile('bar', 'fortran'), [])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/code_coverage/croc_test.py b/chromium/tools/code_coverage/croc_test.py
new file mode 100755
index 00000000000..7c2521ca3df
--- /dev/null
+++ b/chromium/tools/code_coverage/croc_test.py
@@ -0,0 +1,758 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for Crocodile."""
+
+import os
+import StringIO
+import unittest
+import croc
+
+
+class TestCoverageStats(unittest.TestCase):
+ """Tests for croc.CoverageStats."""
+
+ def testAdd(self):
+ """Test Add()."""
+ c = croc.CoverageStats()
+
+ # Initially empty
+ self.assertEqual(c, {})
+
+ # Add items
+ c['a'] = 1
+ c['b'] = 0
+ self.assertEqual(c, {'a': 1, 'b': 0})
+
+ # Add dict with non-overlapping items
+ c.Add({'c': 5})
+ self.assertEqual(c, {'a': 1, 'b': 0, 'c': 5})
+
+ # Add dict with overlapping items
+ c.Add({'a': 4, 'd': 3})
+ self.assertEqual(c, {'a': 5, 'b': 0, 'c': 5, 'd': 3})
+
+
+class TestCoveredFile(unittest.TestCase):
+ """Tests for croc.CoveredFile."""
+
+ def setUp(self):
+ self.cov_file = croc.CoveredFile('bob.cc', group='source', language='C++')
+
+ def testInit(self):
+ """Test init."""
+ f = self.cov_file
+
+ # Check initial values
+ self.assertEqual(f.filename, 'bob.cc')
+ self.assertEqual(f.attrs, {'group': 'source', 'language': 'C++'})
+ self.assertEqual(f.lines, {})
+ self.assertEqual(f.stats, {})
+ self.assertEqual(f.local_path, None)
+ self.assertEqual(f.in_lcov, False)
+
+ def testUpdateCoverageEmpty(self):
+ """Test updating coverage when empty."""
+ f = self.cov_file
+ f.UpdateCoverage()
+ self.assertEqual(f.stats, {
+ 'lines_executable': 0,
+ 'lines_instrumented': 0,
+ 'lines_covered': 0,
+ 'files_executable': 1,
+ })
+
+ def testUpdateCoverageExeOnly(self):
+ """Test updating coverage when no lines are instrumented."""
+ f = self.cov_file
+ f.lines = {1: None, 2: None, 4: None}
+ f.UpdateCoverage()
+ self.assertEqual(f.stats, {
+ 'lines_executable': 3,
+ 'lines_instrumented': 0,
+ 'lines_covered': 0,
+ 'files_executable': 1,
+ })
+
+ # Now mark the file instrumented via in_lcov
+ f.in_lcov = True
+ f.UpdateCoverage()
+ self.assertEqual(f.stats, {
+ 'lines_executable': 3,
+ 'lines_instrumented': 0,
+ 'lines_covered': 0,
+ 'files_executable': 1,
+ 'files_instrumented': 1,
+ })
+
+ def testUpdateCoverageExeAndInstr(self):
+ """Test updating coverage when no lines are covered."""
+ f = self.cov_file
+ f.lines = {1: None, 2: None, 4: 0, 5: 0, 7: None}
+ f.UpdateCoverage()
+ self.assertEqual(f.stats, {
+ 'lines_executable': 5,
+ 'lines_instrumented': 2,
+ 'lines_covered': 0,
+ 'files_executable': 1,
+ 'files_instrumented': 1,
+ })
+
+ def testUpdateCoverageWhenCovered(self):
+ """Test updating coverage when lines are covered."""
+ f = self.cov_file
+ f.lines = {1: None, 2: None, 3: 1, 4: 0, 5: 0, 6: 1, 7: None}
+ f.UpdateCoverage()
+ self.assertEqual(f.stats, {
+ 'lines_executable': 7,
+ 'lines_instrumented': 4,
+ 'lines_covered': 2,
+ 'files_executable': 1,
+ 'files_instrumented': 1,
+ 'files_covered': 1,
+ })
+
+
+class TestCoveredDir(unittest.TestCase):
+ """Tests for croc.CoveredDir."""
+
+ def setUp(self):
+ self.cov_dir = croc.CoveredDir('/a/b/c')
+
+ def testInit(self):
+ """Test init."""
+ d = self.cov_dir
+
+ # Check initial values
+ self.assertEqual(d.dirpath, '/a/b/c')
+ self.assertEqual(d.files, {})
+ self.assertEqual(d.subdirs, {})
+ self.assertEqual(d.stats_by_group, {'all': {}})
+
+ def testGetTreeEmpty(self):
+ """Test getting empty tree."""
+ d = self.cov_dir
+ self.assertEqual(d.GetTree(), 'c/')
+
+ def testGetTreeStats(self):
+ """Test getting tree with stats."""
+ d = self.cov_dir
+ d.stats_by_group['all'] = croc.CoverageStats(
+ lines_executable=50, lines_instrumented=30, lines_covered=20)
+ d.stats_by_group['bar'] = croc.CoverageStats(
+ lines_executable=0, lines_instrumented=0, lines_covered=0)
+ d.stats_by_group['foo'] = croc.CoverageStats(
+ lines_executable=33, lines_instrumented=22, lines_covered=11)
+ # 'bar' group is skipped because it has no executable lines
+ self.assertEqual(
+ d.GetTree(),
+ 'c/ all:20/30/50 foo:11/22/33')
+
+ def testGetTreeSubdir(self):
+ """Test getting tree with subdirs."""
+ d1 = self.cov_dir = croc.CoveredDir('/a')
+ d2 = self.cov_dir = croc.CoveredDir('/a/b')
+ d3 = self.cov_dir = croc.CoveredDir('/a/c')
+ d4 = self.cov_dir = croc.CoveredDir('/a/b/d')
+ d5 = self.cov_dir = croc.CoveredDir('/a/b/e')
+ d1.subdirs = {'/a/b': d2, '/a/c': d3}
+ d2.subdirs = {'/a/b/d': d4, '/a/b/e': d5}
+ self.assertEqual(d1.GetTree(), 'a/\n b/\n d/\n e/\n c/')
+
+
+class TestCoverage(unittest.TestCase):
+ """Tests for croc.Coverage."""
+
+ def MockWalk(self, src_dir):
+ """Mock for os.walk().
+
+ Args:
+ src_dir: Source directory to walk.
+
+ Returns:
+ A list of (dirpath, dirnames, filenames) tuples.
+ """
+ self.mock_walk_calls.append(src_dir)
+ return self.mock_walk_return
+
+ def MockScanFile(self, filename, language):
+ """Mock for croc_scan.ScanFile().
+
+ Args:
+ filename: Path to file to scan.
+ language: Language for file.
+
+ Returns:
+ A list of executable lines.
+ """
+ self.mock_scan_calls.append([filename, language])
+ if filename in self.mock_scan_return:
+ return self.mock_scan_return[filename]
+ else:
+ return self.mock_scan_return['default']
+
+ def setUp(self):
+ """Per-test setup."""
+
+ # Empty coverage object
+ self.cov = croc.Coverage()
+
+ # Coverage object with minimal setup
+ self.cov_minimal = croc.Coverage()
+ self.cov_minimal.AddRoot('/src')
+ self.cov_minimal.AddRoot('c:\\source')
+ self.cov_minimal.AddRule('^_/', include=1, group='my')
+ self.cov_minimal.AddRule('.*\\.c$', language='C')
+ self.cov_minimal.AddRule('.*\\.c##$', language='C##') # sharper than thou
+
+ # Data for MockWalk()
+ self.mock_walk_calls = []
+ self.mock_walk_return = []
+
+ # Data for MockScanFile()
+ self.mock_scan_calls = []
+ self.mock_scan_return = {'default': [1]}
+
+ def testInit(self):
+ """Test init."""
+ c = self.cov
+ self.assertEqual(c.files, {})
+ self.assertEqual(c.root_dirs, [])
+ self.assertEqual(c.print_stats, [])
+ self.assertEqual(c.rules, [])
+
+ def testAddRoot(self):
+ """Test AddRoot() and CleanupFilename()."""
+ c = self.cov
+
+ # Check for identity on already-clean filenames
+ self.assertEqual(c.CleanupFilename(''), '')
+ self.assertEqual(c.CleanupFilename('a'), 'a')
+ self.assertEqual(c.CleanupFilename('.a'), '.a')
+ self.assertEqual(c.CleanupFilename('..a'), '..a')
+ self.assertEqual(c.CleanupFilename('a.b'), 'a.b')
+ self.assertEqual(c.CleanupFilename('a/b/c'), 'a/b/c')
+ self.assertEqual(c.CleanupFilename('a/b/c/'), 'a/b/c/')
+
+ # Backslash to forward slash
+ self.assertEqual(c.CleanupFilename('a\\b\\c'), 'a/b/c')
+
+ # Handle relative paths
+ self.assertEqual(c.CleanupFilename('.'),
+ c.CleanupFilename(os.path.abspath('.')))
+ self.assertEqual(c.CleanupFilename('..'),
+ c.CleanupFilename(os.path.abspath('..')))
+ self.assertEqual(c.CleanupFilename('./foo/bar'),
+ c.CleanupFilename(os.path.abspath('./foo/bar')))
+ self.assertEqual(c.CleanupFilename('../../a/b/c'),
+ c.CleanupFilename(os.path.abspath('../../a/b/c')))
+
+ # Replace alt roots
+ c.AddRoot('foo')
+ self.assertEqual(c.CleanupFilename('foo'), '_')
+ self.assertEqual(c.CleanupFilename('foo/bar/baz'), '_/bar/baz')
+ self.assertEqual(c.CleanupFilename('aaa/foo'), 'aaa/foo')
+
+ # Alt root replacement is applied for all roots
+ c.AddRoot('foo/bar', '_B')
+ self.assertEqual(c.CleanupFilename('foo/bar/baz'), '_B/baz')
+
+ # Can use previously defined roots in cleanup
+ c.AddRoot('_/nom/nom/nom', '_CANHAS')
+ self.assertEqual(c.CleanupFilename('foo/nom/nom/nom/cheezburger'),
+ '_CANHAS/cheezburger')
+
+ # Verify roots starting with UNC paths or drive letters work, and that
+ # more than one root can point to the same alt_name
+ c.AddRoot('/usr/local/foo', '_FOO')
+ c.AddRoot('D:\\my\\foo', '_FOO')
+ self.assertEqual(c.CleanupFilename('/usr/local/foo/a/b'), '_FOO/a/b')
+ self.assertEqual(c.CleanupFilename('D:\\my\\foo\\c\\d'), '_FOO/c/d')
+
+ # Cannot specify a blank alt_name
+ self.assertRaises(ValueError, c.AddRoot, 'some_dir', '')
+
+ def testAddRule(self):
+ """Test AddRule() and ClassifyFile()."""
+ c = self.cov
+
+ # With only the default rule, nothing gets kept
+ self.assertEqual(c.ClassifyFile('_/src/'), {})
+ self.assertEqual(c.ClassifyFile('_/src/a.c'), {})
+
+ # Add rules to include a tree and set a default group
+ c.AddRule('^_/src/', include=1, group='source')
+ self.assertEqual(c.ClassifyFile('_/src/'),
+ {'include': 1, 'group': 'source'})
+ self.assertEqual(c.ClassifyFile('_/notsrc/'), {})
+ self.assertEqual(c.ClassifyFile('_/src/a.c'),
+ {'include': 1, 'group': 'source'})
+
+ # Define some languages and groups
+ c.AddRule('.*\\.(c|h)$', language='C')
+ c.AddRule('.*\\.py$', language='Python')
+ c.AddRule('.*_test\\.', group='test')
+ self.assertEqual(c.ClassifyFile('_/src/a.c'),
+ {'include': 1, 'group': 'source', 'language': 'C'})
+ self.assertEqual(c.ClassifyFile('_/src/a.h'),
+ {'include': 1, 'group': 'source', 'language': 'C'})
+ self.assertEqual(c.ClassifyFile('_/src/a.cpp'),
+ {'include': 1, 'group': 'source'})
+ self.assertEqual(c.ClassifyFile('_/src/a_test.c'),
+ {'include': 1, 'group': 'test', 'language': 'C'})
+ self.assertEqual(c.ClassifyFile('_/src/test_a.c'),
+ {'include': 1, 'group': 'source', 'language': 'C'})
+ self.assertEqual(c.ClassifyFile('_/src/foo/bar.py'),
+ {'include': 1, 'group': 'source', 'language': 'Python'})
+ self.assertEqual(c.ClassifyFile('_/src/test.py'),
+ {'include': 1, 'group': 'source', 'language': 'Python'})
+
+ # Exclude a path (for example, anything in a build output dir)
+ c.AddRule('.*/build/', include=0)
+ # But add back in a dir which matched the above rule but isn't a build
+ # output dir
+ c.AddRule('_/src/tools/build/', include=1)
+ self.assertEqual(c.ClassifyFile('_/src/build.c').get('include'), 1)
+ self.assertEqual(c.ClassifyFile('_/src/build/').get('include'), 0)
+ self.assertEqual(c.ClassifyFile('_/src/build/a.c').get('include'), 0)
+ self.assertEqual(c.ClassifyFile('_/src/tools/build/').get('include'), 1)
+ self.assertEqual(c.ClassifyFile('_/src/tools/build/t.c').get('include'), 1)
+
+ def testGetCoveredFile(self):
+ """Test GetCoveredFile()."""
+ c = self.cov_minimal
+
+ # Not currently any covered files
+ self.assertEqual(c.GetCoveredFile('_/a.c'), None)
+
+ # Add some files
+ a_c = c.GetCoveredFile('_/a.c', add=True)
+ b_c = c.GetCoveredFile('_/b.c##', add=True)
+ self.assertEqual(a_c.filename, '_/a.c')
+ self.assertEqual(a_c.attrs, {'include': 1, 'group': 'my', 'language': 'C'})
+ self.assertEqual(b_c.filename, '_/b.c##')
+ self.assertEqual(b_c.attrs,
+ {'include': 1, 'group': 'my', 'language': 'C##'})
+
+ # Specifying the same filename should return the existing object
+ self.assertEqual(c.GetCoveredFile('_/a.c'), a_c)
+ self.assertEqual(c.GetCoveredFile('_/a.c', add=True), a_c)
+
+ # Filenames get cleaned on the way in, as do root paths
+ self.assertEqual(c.GetCoveredFile('/src/a.c'), a_c)
+ self.assertEqual(c.GetCoveredFile('c:\\source\\a.c'), a_c)
+
+ # TODO: Make sure that covered files require language, group, and include
+ # (since that checking is now done in GetCoveredFile() rather than
+ # ClassifyFile())
+
+ def testRemoveCoveredFile(self):
+ """Test RemoveCoveredFile()."""
+ # TODO: TEST ME!
+
+ def testParseLcov(self):
+ """Test ParseLcovData()."""
+ c = self.cov_minimal
+
+ c.ParseLcovData([
+ '# Ignore unknown lines',
+ # File we should include'
+ 'SF:/src/a.c',
+ 'DA:10,1',
+ 'DA:11,0',
+ 'DA:12,1 \n', # Trailing whitespace should get stripped
+ 'end_of_record',
+ # File we should ignore
+ 'SF:/not_src/a.c',
+ 'DA:20,1',
+ 'end_of_record',
+ # Same as first source file, but alternate root
+ 'SF:c:\\source\\a.c',
+ 'DA:30,1',
+ 'end_of_record',
+ # Ignore extra end of record
+ 'end_of_record',
+ # Ignore data points after end of record
+ 'DA:40,1',
+ # Instrumented but uncovered file
+ 'SF:/src/b.c',
+ 'DA:50,0',
+ 'end_of_record',
+ # Empty file (instrumented but no executable lines)
+ 'SF:c:\\source\\c.c',
+ 'end_of_record',
+ ])
+
+ # We should know about three files
+ self.assertEqual(sorted(c.files), ['_/a.c', '_/b.c', '_/c.c'])
+
+ # Check expected contents
+ a_c = c.GetCoveredFile('_/a.c')
+ self.assertEqual(a_c.lines, {10: 1, 11: 0, 12: 1, 30: 1})
+ self.assertEqual(a_c.stats, {
+ 'files_executable': 1,
+ 'files_instrumented': 1,
+ 'files_covered': 1,
+ 'lines_instrumented': 4,
+ 'lines_executable': 4,
+ 'lines_covered': 3,
+ })
+ self.assertEqual(a_c.in_lcov, True)
+
+ b_c = c.GetCoveredFile('_/b.c')
+ self.assertEqual(b_c.lines, {50: 0})
+ self.assertEqual(b_c.stats, {
+ 'files_executable': 1,
+ 'files_instrumented': 1,
+ 'lines_instrumented': 1,
+ 'lines_executable': 1,
+ 'lines_covered': 0,
+ })
+ self.assertEqual(b_c.in_lcov, True)
+
+ c_c = c.GetCoveredFile('_/c.c')
+ self.assertEqual(c_c.lines, {})
+ self.assertEqual(c_c.stats, {
+ 'files_executable': 1,
+ 'files_instrumented': 1,
+ 'lines_instrumented': 0,
+ 'lines_executable': 0,
+ 'lines_covered': 0,
+ })
+ self.assertEqual(c_c.in_lcov, True)
+
+ # TODO: Test that files are marked as instrumented if they come from lcov,
+ # even if they don't have any instrumented lines. (and that in_lcov is set
+ # for those files - probably should set that via some method rather than
+ # directly...)
+
+ def testGetStat(self):
+ """Test GetStat() and PrintStat()."""
+ c = self.cov
+
+ # Add some stats, so there's something to report
+ c.tree.stats_by_group = {
+ 'all': {
+ 'count_a': 10,
+ 'count_b': 4,
+ 'foo': 'bar',
+ },
+ 'tests': {
+ 'count_a': 2,
+ 'count_b': 5,
+ 'baz': 'bob',
+ },
+ }
+
+ # Test missing stats and groups
+ self.assertRaises(croc.CrocStatError, c.GetStat, 'nosuch')
+ self.assertRaises(croc.CrocStatError, c.GetStat, 'baz')
+ self.assertRaises(croc.CrocStatError, c.GetStat, 'foo', group='tests')
+ self.assertRaises(croc.CrocStatError, c.GetStat, 'foo', group='nosuch')
+
+ # Test returning defaults
+ self.assertEqual(c.GetStat('nosuch', default=13), 13)
+ self.assertEqual(c.GetStat('baz', default='aaa'), 'aaa')
+ self.assertEqual(c.GetStat('foo', group='tests', default=0), 0)
+ self.assertEqual(c.GetStat('foo', group='nosuch', default=''), '')
+
+ # Test getting stats
+ self.assertEqual(c.GetStat('count_a'), 10)
+ self.assertEqual(c.GetStat('count_a', group='tests'), 2)
+ self.assertEqual(c.GetStat('foo', default='baz'), 'bar')
+
+ # Test stat math (eval)
+ self.assertEqual(c.GetStat('count_a - count_b'), 6)
+ self.assertEqual(c.GetStat('100.0 * count_a / count_b', group='tests'),
+ 40.0)
+ # Should catch eval errors
+ self.assertRaises(croc.CrocStatError, c.GetStat, '100 / 0')
+ self.assertRaises(croc.CrocStatError, c.GetStat, 'count_a -')
+
+ # Test nested stats via S()
+ self.assertEqual(c.GetStat('count_a - S("count_a", group="tests")'), 8)
+ self.assertRaises(croc.CrocStatError, c.GetStat, 'S()')
+ self.assertRaises(croc.CrocStatError, c.GetStat, 'S("nosuch")')
+
+ # Test PrintStat()
+ # We won't see the first print, but at least verify it doesn't assert
+ c.PrintStat('count_a', format='(test to stdout: %s)')
+ # Send subsequent prints to a file
+ f = StringIO.StringIO()
+ c.PrintStat('count_b', outfile=f)
+ # Test specifying output format
+ c.PrintStat('count_a', format='Count A = %05d', outfile=f)
+ # Test specifing additional keyword args
+ c.PrintStat('count_a', group='tests', outfile=f)
+ c.PrintStat('nosuch', default=42, outfile=f)
+ self.assertEqual(f.getvalue(), ("""\
+GetStat('count_b') = 4
+Count A = 00010
+GetStat('count_a') = 2
+GetStat('nosuch') = 42
+"""))
+ f.close()
+
+ def testAddConfigEmpty(self):
+ """Test AddConfig() with empty config."""
+ c = self.cov
+ # Most minimal config is an empty dict; should do nothing
+ c.AddConfig('{} # And we ignore comments')
+
+ def testAddConfig(self):
+ """Test AddConfig()."""
+ c = self.cov
+ lcov_queue = []
+ addfiles_queue = []
+
+ c.AddConfig("""{
+ 'roots' : [
+ {'root' : '/foo'},
+ {'root' : '/bar', 'altname' : 'BAR'},
+ ],
+ 'rules' : [
+ {'regexp' : '^_/', 'group' : 'apple'},
+ {'regexp' : 're2', 'include' : 1, 'language' : 'elvish'},
+ ],
+ 'lcov_files' : ['a.lcov', 'b.lcov'],
+ 'add_files' : ['/src', 'BAR/doo'],
+ 'print_stats' : [
+ {'stat' : 'count_a'},
+ {'stat' : 'count_b', 'group' : 'tests'},
+ ],
+ 'extra_key' : 'is ignored',
+ }""", lcov_queue=lcov_queue, addfiles_queue=addfiles_queue)
+
+ self.assertEqual(lcov_queue, ['a.lcov', 'b.lcov'])
+ self.assertEqual(addfiles_queue, ['/src', 'BAR/doo'])
+ self.assertEqual(c.root_dirs, [['/foo', '_'], ['/bar', 'BAR']])
+ self.assertEqual(c.print_stats, [
+ {'stat': 'count_a'},
+ {'stat': 'count_b', 'group': 'tests'},
+ ])
+ # Convert compiled re's back to patterns for comparison
+ rules = [[r[0].pattern] + r[1:] for r in c.rules]
+ self.assertEqual(rules, [
+ ['^_/', {'group': 'apple'}],
+ ['re2', {'include': 1, 'language': 'elvish'}],
+ ])
+
+ def testAddFilesSimple(self):
+ """Test AddFiles() simple call."""
+ c = self.cov_minimal
+ c.add_files_walk = self.MockWalk
+ c.scan_file = self.MockScanFile
+
+ c.AddFiles('/a/b/c')
+ self.assertEqual(self.mock_walk_calls, ['/a/b/c'])
+ self.assertEqual(self.mock_scan_calls, [])
+ self.assertEqual(c.files, {})
+
+ def testAddFilesRootMap(self):
+ """Test AddFiles() with root mappings."""
+ c = self.cov_minimal
+ c.add_files_walk = self.MockWalk
+ c.scan_file = self.MockScanFile
+
+ c.AddRoot('_/subdir', 'SUBDIR')
+
+ # AddFiles() should replace the 'SUBDIR' alt_name, then match both
+ # possible roots for the '_' alt_name.
+ c.AddFiles('SUBDIR/foo')
+ self.assertEqual(self.mock_walk_calls,
+ ['/src/subdir/foo', 'c:/source/subdir/foo'])
+ self.assertEqual(self.mock_scan_calls, [])
+ self.assertEqual(c.files, {})
+
+ def testAddFilesNonEmpty(self):
+ """Test AddFiles() where files are returned."""
+
+ c = self.cov_minimal
+ c.add_files_walk = self.MockWalk
+ c.scan_file = self.MockScanFile
+
+ # Add a rule to exclude a subdir
+ c.AddRule('^_/proj1/excluded/', include=0)
+
+ # Add a rule to exclude adding some fiels
+ c.AddRule('.*noscan.c$', add_if_missing=0)
+
+ # Set data for mock walk and scan
+ self.mock_walk_return = [
+ [
+ '/src/proj1',
+ ['excluded', 'subdir'],
+ ['a.c', 'no.f', 'yes.c', 'noexe.c', 'bob_noscan.c'],
+ ],
+ [
+ '/src/proj1/subdir',
+ [],
+ ['cherry.c'],
+ ],
+ ]
+
+ # Add a file with no executable lines; it should be scanned but not added
+ self.mock_scan_return['/src/proj1/noexe.c'] = []
+
+ c.AddFiles('/src/proj1')
+
+ self.assertEqual(self.mock_walk_calls, ['/src/proj1'])
+ self.assertEqual(self.mock_scan_calls, [
+ ['/src/proj1/a.c', 'C'],
+ ['/src/proj1/yes.c', 'C'],
+ ['/src/proj1/noexe.c', 'C'],
+ ['/src/proj1/subdir/cherry.c', 'C'],
+ ])
+
+ # Include files from the main dir and subdir
+ self.assertEqual(sorted(c.files), [
+ '_/proj1/a.c',
+ '_/proj1/subdir/cherry.c',
+ '_/proj1/yes.c'])
+
+ # Excluded dir should have been pruned from the mock walk data dirnames.
+ # In the real os.walk() call this prunes the walk.
+ self.assertEqual(self.mock_walk_return[0][1], ['subdir'])
+
+
+ def testEmptyTreeStats(self):
+ """Make sure we don't choke when absolutely nothing happened.
+
+ How we might hit this: bot compile error."""
+ c = self.cov_minimal
+ t = c.tree
+ t.stats_by_group['all'].AddDefaults()
+ self.assertEqual(t.stats_by_group, {
+ 'all': { 'files_covered': 0,
+ 'files_instrumented': 0,
+ 'files_executable': 0,
+ 'lines_covered': 0,
+ 'lines_instrumented': 0,
+ 'lines_executable': 0 }})
+
+ def testUpdateTreeStats(self):
+ """Test UpdateTreeStats()."""
+
+ c = self.cov_minimal
+ c.AddRule('.*_test', group='test')
+
+ # Fill the files list
+ c.ParseLcovData([
+ 'SF:/src/a.c',
+ 'DA:10,1', 'DA:11,1', 'DA:20,0',
+ 'end_of_record',
+ 'SF:/src/a_test.c',
+ 'DA:10,1', 'DA:11,1', 'DA:12,1',
+ 'end_of_record',
+ 'SF:/src/foo/b.c',
+ 'DA:10,1', 'DA:11,1', 'DA:20,0', 'DA:21,0', 'DA:30,0',
+ 'end_of_record',
+ 'SF:/src/foo/b_test.c',
+ 'DA:20,0', 'DA:21,0', 'DA:22,0',
+ 'end_of_record',
+ ])
+ c.UpdateTreeStats()
+
+ t = c.tree
+ self.assertEqual(t.dirpath, '')
+ self.assertEqual(sorted(t.files), [])
+ self.assertEqual(sorted(t.subdirs), ['_'])
+ self.assertEqual(t.stats_by_group, {
+ 'all': {
+ 'files_covered': 3,
+ 'files_executable': 4,
+ 'lines_executable': 14,
+ 'lines_covered': 7,
+ 'lines_instrumented': 14,
+ 'files_instrumented': 4,
+ },
+ 'my': {
+ 'files_covered': 2,
+ 'files_executable': 2,
+ 'lines_executable': 8,
+ 'lines_covered': 4,
+ 'lines_instrumented': 8,
+ 'files_instrumented': 2,
+ },
+ 'test': {
+ 'files_covered': 1,
+ 'files_executable': 2,
+ 'lines_executable': 6,
+ 'lines_covered': 3,
+ 'lines_instrumented': 6,
+ 'files_instrumented': 2,
+ },
+ })
+
+ t = t.subdirs['_']
+ self.assertEqual(t.dirpath, '_')
+ self.assertEqual(sorted(t.files), ['a.c', 'a_test.c'])
+ self.assertEqual(sorted(t.subdirs), ['foo'])
+ self.assertEqual(t.stats_by_group, {
+ 'all': {
+ 'files_covered': 3,
+ 'files_executable': 4,
+ 'lines_executable': 14,
+ 'lines_covered': 7,
+ 'lines_instrumented': 14,
+ 'files_instrumented': 4,
+ },
+ 'my': {
+ 'files_covered': 2,
+ 'files_executable': 2,
+ 'lines_executable': 8,
+ 'lines_covered': 4,
+ 'lines_instrumented': 8,
+ 'files_instrumented': 2,
+ },
+ 'test': {
+ 'files_covered': 1,
+ 'files_executable': 2,
+ 'lines_executable': 6,
+ 'lines_covered': 3,
+ 'lines_instrumented': 6,
+ 'files_instrumented': 2,
+ },
+ })
+
+ t = t.subdirs['foo']
+ self.assertEqual(t.dirpath, '_/foo')
+ self.assertEqual(sorted(t.files), ['b.c', 'b_test.c'])
+ self.assertEqual(sorted(t.subdirs), [])
+ self.assertEqual(t.stats_by_group, {
+ 'test': {
+ 'files_executable': 1,
+ 'files_instrumented': 1,
+ 'lines_executable': 3,
+ 'lines_instrumented': 3,
+ 'lines_covered': 0,
+ },
+ 'all': {
+ 'files_covered': 1,
+ 'files_executable': 2,
+ 'lines_executable': 8,
+ 'lines_covered': 2,
+ 'lines_instrumented': 8,
+ 'files_instrumented': 2,
+ },
+ 'my': {
+ 'files_covered': 1,
+ 'files_executable': 1,
+ 'lines_executable': 5,
+ 'lines_covered': 2,
+ 'lines_instrumented': 5,
+ 'files_instrumented': 1,
+ }
+ })
+
+ # TODO: test: less important, since these are thin wrappers around other
+ # tested methods.
+ # ParseConfig()
+ # ParseLcovFile()
+ # PrintTree()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/code_coverage/example.croc b/chromium/tools/code_coverage/example.croc
new file mode 100644
index 00000000000..4e8ca2bc888
--- /dev/null
+++ b/chromium/tools/code_coverage/example.croc
@@ -0,0 +1,197 @@
+# -*- python -*-
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Example configuration file for Croc
+
+# Basic formatting rules:
+# * It looks like JSON.
+# * It's really python.
+# * Dictionaries are wrapped in {}. Order does not matter. Entries are of
+# the form:
+# 'key':value,
+# Note the trailing comma, which will help save you from python's built-in
+# string concatenation.
+# * Lists are wrapped in []. Order does matter. Entries should be followed
+# with a trailing comma, which will help save you from python's built-in
+# string concatenation.
+# * Comments start with # and extend to end of line.
+# * Strings are wrapped in ''. Backslashes must be escaped ('foo\\bar', not
+# 'foo\bar') - this is particularly important in rule regular expressions.
+
+
+# What follows is the main configuration dictionary.
+{
+ # List of root directories, applied in order.
+ #
+ # Typically, coverage data files contain absolute paths to the sources.
+ # What you care about is usually a relative path from the top of your source
+ # tree (referred to here as a 'source root') to the sources.
+ #
+ # Roots may also be specified on the command line via the --root option.
+ # Roots specified by --root are applied before those specified in config
+ # files.
+ 'roots' : [
+ # Each entry is a dict.
+ # * It must contain a 'root' entry, which is the start of a path.
+ # * Root entries may be absolute paths
+ # * Root entries starting with './' or '../' are relative paths, and
+ # are taken relative to the current directory where you run croc.
+ # * Root entries may start with previously defined altnames.
+ # * Use '/' as a path separator, even on Windows.
+ # * It may contain a 'altname' entry. If the root matches the start of
+ # a filename, that start is replaced with the 'altname', or with '_'
+ # if no default is specified.
+ # * Multiple root entries may share the same altname. This is commonly
+ # used when combining LCOV files from different platforms into one
+ # coverage report, when each platform checks out source code into a
+ # different source tree.
+ {'root' : 'c:/P4/EarthHammer'},
+ {'root' : 'd:/pulse/recipes/330137642/base'},
+ {'root' : '/Volumes/BuildData/PulseData/data/recipes/330137640/base'},
+ {'root' : '/usr/local/google/builder/.pulse-agent/data/recipes/330137641/base'},
+
+ # Sub-paths we specifically care about and want to call out. Note that
+ # these are relative to the default '_' altname.
+ {
+ 'root' : '_/googleclient/third_party/software_construction_toolkit/files',
+ 'altname' : 'SCT',
+ },
+ {
+ 'root' : '_/googleclient/tools/hammer',
+ 'altname' : 'HAMMER',
+ },
+ ],
+
+ # List of rules, applied in order.
+ 'rules' : [
+ # Each rule is a dict.
+ # * It must contaihn a 'regexp' entry. Filenames which match this
+ # regular expression (after applying mappings from 'roots') are
+ # affected by the rule.
+ #
+ # * Other entries in the dict are attributes to apply to matching files.
+ #
+ # Allowed attributes:
+ #
+ # 'include' : If 1, the file will be included in coverage reports. If 0,
+ # it won't be included in coverage reports.
+ #
+ # 'group' : Name of the group the file belongs to. The most common
+ # group names are 'source' and 'test'. Files must belong to
+ # a group to be included in coverage reports.
+ #
+ # 'language' : Programming language for the file. The most common
+ # languages are 'C', 'C++', 'python', 'ObjC', 'ObjC++'.
+ # Files must have a language to be included in coverage
+ # reports.
+ #
+ # 'add_if_missing' : If 1, and the file was not referenced by any LCOV
+ # files, it will be be scanned for executable lines
+ # and added to the coverage report. If 0, if the
+ # file is not referenced by any LCOV files, it will
+ # simply be ignored and not present in coverage
+ # reports.
+
+ # Files/paths to include
+ {
+ 'regexp' : '^(SCT|HAMMER)/',
+ 'include' : 1,
+ 'add_if_missing': 1,
+ },
+ {
+ 'regexp' : '.*/(\\.svn|\\.hg)/',
+ 'include' : 0,
+ },
+
+ # Groups
+ {
+ 'regexp' : '',
+ 'group' : 'source',
+ },
+ {
+ 'regexp' : '.*_(test|test_mac|unittest)\\.',
+ 'group' : 'test',
+ },
+
+ # Languages
+ {
+ 'regexp' : '.*\\.py$',
+ 'language' : 'python',
+ },
+ ],
+
+ # List of paths to add source from.
+ #
+ # Each entry is a path. It may be a local path, or one relative to a root
+ # altname (see 'roots' above).
+ #
+ # If more than one root's altname matches the start of this path, all matches
+ # will be attempted; matches where the candidate directory doesn't exist will
+ # be ignored. For example, if you're combining data from multiple platforms'
+ # LCOV files, you probably defined at least one root per LCOV, but only have
+ # one copy of the source on your local platform. That's fine; Croc will use
+ # the source it can find and not worry about the source it can't.
+ #
+ # Source files must be added via 'add_files' to generate line-by-line HTML
+ # output (via the --html option) and/or to scan for missing executable lines
+ # (if 'add_if_missing' is 1).
+ 'add_files' : [
+ 'SCT',
+ 'HAMMER',
+ ],
+
+ # Statistics to print.
+ #
+ 'print_stats' : [
+ # Each entry is a dict.
+ #
+ # It must have a 'stat' entry, which is the statistic to print. This may
+ # be one of the following stats:
+ #
+ # * files_executable
+ # * files_instrumented
+ # * files_covered
+ # * lines_executable
+ # * lines_instrumented
+ # * lines_covered
+ #
+ # or an expression using those stats.
+ #
+ # It may have a 'format' entry, which is a python formatting string (very
+ # printf-like) for the statistic.
+ #
+ # It may have a 'group' entry. If this is specified, only files from the
+ # matching group will be included in the statistic. If not specified, the
+ # group defaults to 'all', which means all groups.
+ {
+ 'stat' : 'files_executable',
+ 'format' : '*RESULT FilesKnown: files_executable= %d files',
+ },
+ {
+ 'stat' : 'files_instrumented',
+ 'format' : '*RESULT FilesInstrumented: files_instrumented= %d files',
+ },
+ {
+ 'stat' : '100.0 * files_instrumented / files_executable',
+ 'format' : '*RESULT FilesInstrumentedPercent: files_instrumented_percent= %g',
+ },
+ {
+ 'stat' : 'lines_instrumented',
+ 'format' : '*RESULT LinesInstrumented: lines_instrumented= %d lines',
+ },
+ {
+ 'stat' : 'lines_covered',
+ 'format' : '*RESULT LinesCoveredSource: lines_covered_source= %d lines',
+ 'group' : 'source',
+ },
+ {
+ 'stat' : 'lines_covered',
+ 'format' : '*RESULT LinesCoveredTest: lines_covered_test= %d lines',
+ 'group' : 'test',
+ },
+ ],
+
+}
diff --git a/chromium/tools/code_coverage/process_coverage.py b/chromium/tools/code_coverage/process_coverage.py
new file mode 100755
index 00000000000..07d83ac2c35
--- /dev/null
+++ b/chromium/tools/code_coverage/process_coverage.py
@@ -0,0 +1,413 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Script to clean the lcov files and convert it to HTML
+
+TODO(niranjan): Add usage information here
+"""
+
+
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+import urllib2
+
+
+# These are source files that were generated during compile time. We want to
+# remove references to these files from the lcov file otherwise genhtml will
+# throw an error.
+win32_srcs_exclude = ['parse.y',
+ 'xpathgrammar.cpp',
+ 'cssgrammar.cpp',
+ 'csspropertynames.gperf']
+
+# Number of lines of a new coverage data set
+# to send at a time to the dashboard.
+POST_CHUNK_SIZE = 50
+
+# Number of post request failures to allow before exiting.
+MAX_FAILURES = 5
+
+def CleanPathNames(dir):
+ """Clean the pathnames of the HTML generated by genhtml.
+
+ This method is required only for code coverage on Win32. Due to a known issue
+ with reading from CIFS shares mounted on Linux, genhtml appends a ^M to every
+ file name it reads from the Windows share, causing corrupt filenames in
+ genhtml's output folder.
+
+ Args:
+ dir: Output folder of the genhtml output.
+
+ Returns:
+ None
+ """
+ # Stip off the ^M characters that get appended to the file name
+ for dirpath, dirname, filenames in os.walk(dir):
+ for file in filenames:
+ file_clean = file.replace('\r', '')
+ if file_clean != file:
+ os.rename(file, file_clean)
+
+
+def GenerateHtml(lcov_path, dash_root):
+ """Runs genhtml to convert lcov data to human readable HTML.
+
+ This script expects the LCOV file name to be in the format:
+ chrome_<platform>_<revision#>.lcov.
+ This method parses the file name and then sets up the correct folder
+ hierarchy for the coverage data and then runs genhtml to get the actual HTML
+ formatted coverage data.
+
+ Args:
+ lcov_path: Path of the lcov data file.
+ dash_root: Root location of the dashboard.
+
+ Returns:
+ Code coverage percentage on sucess.
+ None on failure.
+ """
+ # Parse the LCOV file name.
+ filename = os.path.basename(lcov_path).split('.')[0]
+ buffer = filename.split('_')
+ dash_root = dash_root.rstrip('/') # Remove trailing '/'
+
+ # Set up correct folder hierarchy in the dashboard root
+ # TODO(niranjan): Check the formatting using a regexp
+ if len(buffer) >= 3: # Check if filename has right formatting
+ platform = buffer[len(buffer) - 2]
+ revision = buffer[len(buffer) - 1]
+ if os.path.exists(os.path.join(dash_root, platform)) == False:
+ os.mkdir(os.path.join(dash_root, platform))
+ output_dir = os.path.join(dash_root, platform, revision)
+ os.mkdir(output_dir)
+ else:
+ # TODO(niranjan): Add failure logging here.
+ return None # File not formatted correctly
+
+ # Run genhtml
+ os.system('/usr/bin/genhtml -o %s %s' % (output_dir, lcov_path))
+ # TODO(niranjan): Check the exit status of the genhtml command.
+ # TODO(niranjan): Parse the stdout and return coverage percentage.
+ CleanPathNames(output_dir)
+ return 'dummy' # TODO(niranjan): Return actual percentage.
+
+
+def CleanWin32Lcov(lcov_path, src_root):
+ """Cleanup the lcov data generated on Windows.
+
+ This method fixes up the paths inside the lcov file from the Win32 specific
+ paths to the actual paths of the mounted CIFS share. The lcov files generated
+ on Windows have the following format:
+
+ SF:c:\chrome_src\src\skia\sgl\skscan_antihair.cpp
+ DA:97,0
+ DA:106,0
+ DA:107,0
+ DA:109,0
+ ...
+ end_of_record
+
+ This method changes the source-file (SF) lines to a format compatible with
+ genhtml on Linux by fixing paths. This method also removes references to
+ certain dynamically generated files to be excluded from the code ceverage.
+
+ Args:
+ lcov_path: Path of the Win32 lcov file to be cleaned.
+ src_root: Location of the source and symbols dir.
+ Returns:
+ None
+ """
+ strip_flag = False
+ lcov = open(lcov_path, 'r')
+ loc_csv_file = open(lcov_path + '.csv', 'w')
+ (tmpfile_id, tmpfile_name) = tempfile.mkstemp()
+ tmpfile = open(tmpfile_name, 'w')
+ src_root = src_root.rstrip('/') # Remove trailing '/'
+ for line in lcov:
+ if line.startswith('SF'):
+ # We want to exclude certain auto-generated files otherwise genhtml will
+ # fail to convert lcov to HTML.
+ for exp in win32_srcs_exclude:
+ if line.rfind(exp) != -1:
+ strip_flag = True # Indicates that we want to remove this section
+
+ # Now we normalize the paths
+ # e.g. Change SF:c:\foo\src\... to SF:/chrome_src/...
+ parse_buffer = line.split(':')
+ buffer = '%s:%s%s' % (parse_buffer[0],
+ src_root,
+ parse_buffer[2])
+ buffer = buffer.replace('\\', '/')
+ line = buffer.replace('\r', '')
+
+ # We want an accurate count of the lines of code in a given file so that
+ # we can estimate the code coverage perscentage accurately. We use a
+ # third party script cloc.pl which gives that count and then just parse
+ # its command line output to filter out the other unnecessary data.
+ # TODO(niranjan): Find out a better way of doing this.
+ buffer = buffer.lstrip('SF:')
+ file_for_loc = buffer.replace('\r\n', '')
+ # TODO(niranjan): Add a check to see if cloc is present on the machine.
+ command = ["perl",
+ "cloc.pl",
+ file_for_loc]
+ output = subprocess.Popen(command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT).communicate()[0]
+ if output.rfind('error:'):
+ return None
+
+ tmp_buf1 = output.split('=')
+ tmp_buf2 = tmp_buf1[len(tmp_buf1) - 2].split('x')[0].split(' ')
+ loc = tmp_buf2[len(tmp_buf2) - 2]
+ loc_csv_file.write('%s,%s\r\n' % (file_for_loc, loc))
+
+ # Write to the temp file if the section to write is valid
+ if strip_flag == False:
+ # Also write this to the 'clean' LCOV file
+ tmpfile.write('%s' % (line))
+
+ # Reset the strip flag
+ if line.endswith('end_of_record'):
+ strip_flag = False
+
+ # Close the files and replace the lcov file by the 'clean' tmpfile
+ tmpfile.close()
+ lcov.close()
+ loc_csv_file.close()
+ shutil.move(tmpfile_name, lcov_path)
+
+
+def ParseCoverageDataForDashboard(lcov_path):
+ """Parse code coverage data into coverage results per source node.
+
+ Use lcov and linecount data to create a map of source nodes to
+ corresponding total and tested line counts.
+
+ Args:
+ lcov_path: File path to lcov coverage data.
+
+ Returns:
+ List of strings with comma separated source node and coverage.
+ """
+ results = {}
+ linecount_path = lcov_path + '.csv'
+ assert(os.path.exists(linecount_path),
+ 'linecount csv does not exist at: %s' % linecount_path)
+ csv_file = open(linecount_path, 'r')
+ linecounts = csv_file.readlines()
+ csv_file.close()
+ lcov_file = open(lcov_path, 'r')
+ srcfile_index = 0
+ for line in lcov_file:
+ line = line.strip()
+
+ # Set the current srcfile name for a new src file declaration.
+ if line[:len('SF:')] == 'SF:':
+ instrumented_set = {}
+ executed_set = {}
+ srcfile_name = line[len('SF:'):]
+
+ # Mark coverage data points hashlist style for the current src file.
+ if line[:len('DA:')] == 'DA:':
+ line_info = line[len('DA:'):].split(',')
+ assert(len(line_info) == 2, 'DA: line format unexpected - %s' % line)
+ (line_num, line_was_executed) = line_info
+ instrumented_set[line_num] = True
+ # line_was_executed is '0' or '1'
+ if int(line_was_executed):
+ executed_set[line_num] = True
+
+ # Update results for the current src file at record end.
+ if line == 'end_of_record':
+ instrumented = len(instrumented_set.keys())
+ executed = len(executed_set.keys())
+ parent_directory = srcfile_name[:srcfile_name.rfind('/') + 1]
+ linecount_point = linecounts[srcfile_index].strip().split(',')
+ assert(len(linecount_point) == 2,
+ 'lintcount format unexpected - %s' % linecounts[srcfile_index])
+ (linecount_path, linecount_count) = linecount_point
+ srcfile_index += 1
+
+ # Sanity check that path names in the lcov and linecount are lined up.
+ if linecount_path[-10:] != srcfile_name[-10:]:
+ print 'NAME MISMATCH: %s :: %s' % (srcfile_name, linecount_path)
+ if instrumented > int(linecount_count):
+ linecount_count = instrumented
+
+ # Keep counts the same way that it is done in the genhtml utility.
+ # Count the coverage of a file towards the file,
+ # the parent directory, and the source root.
+ AddResults(results, srcfile_name, int(linecount_count), executed)
+ AddResults(results, parent_directory, int(linecount_count), executed)
+ AddResults(results, '/', instrumented, executed)
+
+ lcov_file.close()
+ keys = results.keys()
+ keys.sort()
+ # The first key (sorted) will be the base directory '/'
+ # but its full path may be '/mnt/chrome_src/src/'
+ # using this offset will ignore the part '/mnt/chrome_src/src'.
+ # Offset is the last '/' that isn't the last character for the
+ # first directory name in results (position 1 in keys).
+ offset = len(keys[1][:keys[1][:-1].rfind('/')])
+ lines = []
+ for key in keys:
+ if len(key) > offset:
+ node_path = key[offset:]
+ else:
+ node_path = key
+ (total, covered) = results[key]
+ percent = float(covered) * 100 / total
+ lines.append('%s,%.2f' % (node_path, percent))
+ return lines
+
+
+def AddResults(results, location, lines_total, lines_executed):
+ """Add resulting line tallies to a location's total.
+
+ Args:
+ results: Map of node location to corresponding coverage data.
+ location: Source node string.
+ lines_total: Number of lines to add to the total count for this node.
+ lines_executed: Number of lines to add to the executed count for this node.
+ """
+ if results.has_key(location):
+ (i, e) = results[location]
+ results[location] = (i + lines_total, e + lines_executed)
+ else:
+ results[location] = (lines_total, lines_executed)
+
+
+def PostResultsToDashboard(lcov_path, results, post_url):
+ """Post coverage results to coverage dashboard.
+
+ Args:
+ lcov_path: File path for lcov data in the expected format:
+ <project>_<platform>_<cl#>.coverage.lcov
+ results: string list in the appropriate posting format.
+ """
+ project_platform_cl = lcov_path.split('.')[0].split('_')
+ assert(len(project_platform_cl) == 3,
+ 'lcov_path not in expected format: %s' % lcov_path)
+ (project, platform, cl_string) = project_platform_cl
+ project_name = '%s-%s' % (project, platform)
+ url = '%s/newdata.do?project=%s&cl=%s' % (post_url, project_name, cl_string)
+
+ # Send POSTs of POST_CHUNK_SIZE lines of the result set until
+ # there is no more data and last_loop is set to True.
+ last_loop = False
+ cur_line = 0
+ while not last_loop:
+ body = '\n'.join(results[cur_line:cur_line + POST_CHUNK_SIZE])
+ cur_line += POST_CHUNK_SIZE
+ last_loop = (cur_line >= len(results))
+ req = urllib2.Request('%s&last=%s' % (url, str(last_loop)), body)
+ req.add_header('Content-Type', 'text/plain')
+ SendPost(req)
+
+
+# Global counter for the current number of request failures.
+num_fails = 0
+
+def SendPost(req):
+ """Execute a post request and retry for up to MAX_FAILURES.
+
+ Args:
+ req: A urllib2 request object.
+
+ Raises:
+ URLError: If urlopen throws after too many retries.
+ HTTPError: If urlopen throws after too many retries.
+ """
+ global num_fails
+ try:
+ urllib2.urlopen(req)
+ # Reset failure count.
+ num_fails = 0
+ except (urllib2.URLError, urllib2.HTTPError):
+ num_fails += 1
+ if num_fails < MAX_FAILURES:
+ print 'fail, retrying (%d)' % num_fails
+ time.sleep(5)
+ SendPost(req)
+ else:
+ print 'POST request exceeded allowed retries.'
+ raise
+
+
+def main():
+ if not sys.platform.startswith('linux'):
+ print 'This script is supported only on Linux'
+ return 0
+
+ # Command line parsing
+ parser = optparse.OptionParser()
+ parser.add_option('-p',
+ '--platform',
+ dest='platform',
+ default=None,
+ help=('Platform that the locv file was generated on. Must'
+ 'be one of {win32, linux2, linux3, macosx}'))
+ parser.add_option('-s',
+ '--source',
+ dest='src_dir',
+ default=None,
+ help='Path to the source code and symbols')
+ parser.add_option('-d',
+ '--dash_root',
+ dest='dash_root',
+ default=None,
+ help='Root directory for the dashboard')
+ parser.add_option('-l',
+ '--lcov',
+ dest='lcov_path',
+ default=None,
+ help='Location of the LCOV file to process')
+ parser.add_option('-u',
+ '--post_url',
+ dest='post_url',
+ default=None,
+ help='Base URL of the coverage dashboard')
+ (options, args) = parser.parse_args()
+
+ if options.platform == None:
+ parser.error('Platform not specified')
+ if options.lcov_path == None:
+ parser.error('lcov file path not specified')
+ if options.src_dir == None:
+ parser.error('Source directory not specified')
+ if options.dash_root == None:
+ parser.error('Dashboard root not specified')
+ if options.post_url == None:
+ parser.error('Post URL not specified')
+ if options.platform == 'win32':
+ CleanWin32Lcov(options.lcov_path, options.src_dir)
+ percent = GenerateHtml(options.lcov_path, options.dash_root)
+ if percent == None:
+ # TODO(niranjan): Add logging.
+ print 'Failed to generate code coverage'
+ return 1
+ else:
+ # TODO(niranjan): Do something with the code coverage numbers
+ pass
+ else:
+ print 'Unsupported platform'
+ return 1
+
+ # Prep coverage results for dashboard and post new set.
+ parsed_data = ParseCoverageDataForDashboard(options.lcov_path)
+ PostResultsToDashboard(options.lcov_path, parsed_data, options.post_url)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/code_coverage/third_party/README.chromium b/chromium/tools/code_coverage/third_party/README.chromium
new file mode 100644
index 00000000000..a4925525c89
--- /dev/null
+++ b/chromium/tools/code_coverage/third_party/README.chromium
@@ -0,0 +1,11 @@
+Name: SortTable
+Short Name: sorttable.js
+URL: http://www.kryogenix.org/code/browser/sorttable/
+Version: 2
+Date: 7th April 2007
+License: Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
+
+Description:
+Add <script src="sorttable.js"></script> to your HTML
+Add class="sortable" to any table you'd like to make sortable
+Click on the headers to sort
diff --git a/chromium/tools/code_coverage/third_party/sorttable.js b/chromium/tools/code_coverage/third_party/sorttable.js
new file mode 100644
index 00000000000..16ef551497b
--- /dev/null
+++ b/chromium/tools/code_coverage/third_party/sorttable.js
@@ -0,0 +1,494 @@
+/*
+ SortTable
+ version 2
+ 7th April 2007
+ Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
+
+ Instructions:
+ Download this file
+ Add <script src="sorttable.js"></script> to your HTML
+ Add class="sortable" to any table you'd like to make sortable
+ Click on the headers to sort
+
+ Thanks to many, many people for contributions and suggestions.
+ Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
+ This basically means: do what you want with it.
+*/
+
+
+var stIsIE = /*@cc_on!@*/false;
+
+sorttable = {
+ init: function() {
+ // quit if this function has already been called
+ if (arguments.callee.done) return;
+ // flag this function so we don't do the same thing twice
+ arguments.callee.done = true;
+ // kill the timer
+ if (_timer) clearInterval(_timer);
+
+ if (!document.createElement || !document.getElementsByTagName) return;
+
+ sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
+
+ forEach(document.getElementsByTagName('table'), function(table) {
+ if (table.className.search(/\bsortable\b/) != -1) {
+ sorttable.makeSortable(table);
+ }
+ });
+
+ },
+
+ makeSortable: function(table) {
+ if (table.getElementsByTagName('thead').length == 0) {
+ // table doesn't have a tHead. Since it should have, create one and
+ // put the first table row in it.
+ the = document.createElement('thead');
+ the.appendChild(table.rows[0]);
+ table.insertBefore(the,table.firstChild);
+ }
+ // Safari doesn't support table.tHead, sigh
+ if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
+
+ if (table.tHead.rows.length != 1) return; // can't cope with two header rows
+
+ // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
+ // "total" rows, for example). This is B&R, since what you're supposed
+ // to do is put them in a tfoot. So, if there are sortbottom rows,
+ // for backwards compatibility, move them to tfoot (creating it if needed).
+ sortbottomrows = [];
+ for (var i=0; i<table.rows.length; i++) {
+ if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
+ sortbottomrows[sortbottomrows.length] = table.rows[i];
+ }
+ }
+ if (sortbottomrows) {
+ if (table.tFoot == null) {
+ // table doesn't have a tfoot. Create one.
+ tfo = document.createElement('tfoot');
+ table.appendChild(tfo);
+ }
+ for (var i=0; i<sortbottomrows.length; i++) {
+ tfo.appendChild(sortbottomrows[i]);
+ }
+ delete sortbottomrows;
+ }
+
+ // work through each column and calculate its type
+ headrow = table.tHead.rows[0].cells;
+ for (var i=0; i<headrow.length; i++) {
+ // manually override the type with a sorttable_type attribute
+ if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col
+ mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
+ if (mtch) { override = mtch[1]; }
+ if (mtch && typeof sorttable["sort_"+override] == 'function') {
+ headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
+ } else {
+ headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
+ }
+ // make it clickable to sort
+ headrow[i].sorttable_columnindex = i;
+ headrow[i].sorttable_tbody = table.tBodies[0];
+ dean_addEvent(headrow[i],"click", function(e) {
+
+ if (this.className.search(/\bsorttable_sorted\b/) != -1) {
+ // if we're already sorted by this column, just
+ // reverse the table, which is quicker
+ sorttable.reverse(this.sorttable_tbody);
+ this.className = this.className.replace('sorttable_sorted',
+ 'sorttable_sorted_reverse');
+ this.removeChild(document.getElementById('sorttable_sortfwdind'));
+ sortrevind = document.createElement('span');
+ sortrevind.id = "sorttable_sortrevind";
+ sortrevind.innerHTML = stIsIE ? '&nbsp<font face="webdings">5</font>' : '&nbsp;&#x25B4;';
+ this.appendChild(sortrevind);
+ return;
+ }
+ if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
+ // if we're already sorted by this column in reverse, just
+ // re-reverse the table, which is quicker
+ sorttable.reverse(this.sorttable_tbody);
+ this.className = this.className.replace('sorttable_sorted_reverse',
+ 'sorttable_sorted');
+ this.removeChild(document.getElementById('sorttable_sortrevind'));
+ sortfwdind = document.createElement('span');
+ sortfwdind.id = "sorttable_sortfwdind";
+ sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
+ this.appendChild(sortfwdind);
+ return;
+ }
+
+ // remove sorttable_sorted classes
+ theadrow = this.parentNode;
+ forEach(theadrow.childNodes, function(cell) {
+ if (cell.nodeType == 1) { // an element
+ cell.className = cell.className.replace('sorttable_sorted_reverse','');
+ cell.className = cell.className.replace('sorttable_sorted','');
+ }
+ });
+ sortfwdind = document.getElementById('sorttable_sortfwdind');
+ if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
+ sortrevind = document.getElementById('sorttable_sortrevind');
+ if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
+
+ this.className += ' sorttable_sorted';
+ sortfwdind = document.createElement('span');
+ sortfwdind.id = "sorttable_sortfwdind";
+ sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
+ this.appendChild(sortfwdind);
+
+ // build an array to sort. This is a Schwartzian transform thing,
+ // i.e., we "decorate" each row with the actual sort key,
+ // sort based on the sort keys, and then put the rows back in order
+ // which is a lot faster because you only do getInnerText once per row
+ row_array = [];
+ col = this.sorttable_columnindex;
+ rows = this.sorttable_tbody.rows;
+ for (var j=0; j<rows.length; j++) {
+ row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
+ }
+ /* If you want a stable sort, uncomment the following line */
+ //sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
+ /* and comment out this one */
+ row_array.sort(this.sorttable_sortfunction);
+
+ tb = this.sorttable_tbody;
+ for (var j=0; j<row_array.length; j++) {
+ tb.appendChild(row_array[j][1]);
+ }
+
+ delete row_array;
+ });
+ }
+ }
+ },
+
+ guessType: function(table, column) {
+ // guess the type of a column based on its first non-blank row
+ sortfn = sorttable.sort_alpha;
+ for (var i=0; i<table.tBodies[0].rows.length; i++) {
+ text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
+ if (text != '') {
+ if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) {
+ return sorttable.sort_numeric;
+ }
+ // check for a date: dd/mm/yyyy or dd/mm/yy
+ // can have / or . or - as separator
+ // can be mm/dd as well
+ possdate = text.match(sorttable.DATE_RE)
+ if (possdate) {
+ // looks like a date
+ first = parseInt(possdate[1]);
+ second = parseInt(possdate[2]);
+ if (first > 12) {
+ // definitely dd/mm
+ return sorttable.sort_ddmm;
+ } else if (second > 12) {
+ return sorttable.sort_mmdd;
+ } else {
+ // looks like a date, but we can't tell which, so assume
+ // that it's dd/mm (English imperialism!) and keep looking
+ sortfn = sorttable.sort_ddmm;
+ }
+ }
+ }
+ }
+ return sortfn;
+ },
+
+ getInnerText: function(node) {
+ // gets the text we want to use for sorting for a cell.
+ // strips leading and trailing whitespace.
+ // this is *not* a generic getInnerText function; it's special to sorttable.
+ // for example, you can override the cell text with a customkey attribute.
+ // it also gets .value for <input> fields.
+
+ if (!node) return "";
+
+ hasInputs = (typeof node.getElementsByTagName == 'function') &&
+ node.getElementsByTagName('input').length;
+
+ if (node.getAttribute("sorttable_customkey") != null) {
+ return node.getAttribute("sorttable_customkey");
+ }
+ else if (typeof node.textContent != 'undefined' && !hasInputs) {
+ return node.textContent.replace(/^\s+|\s+$/g, '');
+ }
+ else if (typeof node.innerText != 'undefined' && !hasInputs) {
+ return node.innerText.replace(/^\s+|\s+$/g, '');
+ }
+ else if (typeof node.text != 'undefined' && !hasInputs) {
+ return node.text.replace(/^\s+|\s+$/g, '');
+ }
+ else {
+ switch (node.nodeType) {
+ case 3:
+ if (node.nodeName.toLowerCase() == 'input') {
+ return node.value.replace(/^\s+|\s+$/g, '');
+ }
+ case 4:
+ return node.nodeValue.replace(/^\s+|\s+$/g, '');
+ break;
+ case 1:
+ case 11:
+ var innerText = '';
+ for (var i = 0; i < node.childNodes.length; i++) {
+ innerText += sorttable.getInnerText(node.childNodes[i]);
+ }
+ return innerText.replace(/^\s+|\s+$/g, '');
+ break;
+ default:
+ return '';
+ }
+ }
+ },
+
+ reverse: function(tbody) {
+ // reverse the rows in a tbody
+ newrows = [];
+ for (var i=0; i<tbody.rows.length; i++) {
+ newrows[newrows.length] = tbody.rows[i];
+ }
+ for (var i=newrows.length-1; i>=0; i--) {
+ tbody.appendChild(newrows[i]);
+ }
+ delete newrows;
+ },
+
+ /* sort functions
+ each sort function takes two parameters, a and b
+ you are comparing a[0] and b[0] */
+ sort_numeric: function(a,b) {
+ aa = parseFloat(a[0].replace(/[^0-9.-]/g,''));
+ if (isNaN(aa)) aa = 0;
+ bb = parseFloat(b[0].replace(/[^0-9.-]/g,''));
+ if (isNaN(bb)) bb = 0;
+ return aa-bb;
+ },
+ sort_alpha: function(a,b) {
+ if (a[0]==b[0]) return 0;
+ if (a[0]<b[0]) return -1;
+ return 1;
+ },
+ sort_ddmm: function(a,b) {
+ mtch = a[0].match(sorttable.DATE_RE);
+ y = mtch[3]; m = mtch[2]; d = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt1 = y+m+d;
+ mtch = b[0].match(sorttable.DATE_RE);
+ y = mtch[3]; m = mtch[2]; d = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt2 = y+m+d;
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+ },
+ sort_mmdd: function(a,b) {
+ mtch = a[0].match(sorttable.DATE_RE);
+ y = mtch[3]; d = mtch[2]; m = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt1 = y+m+d;
+ mtch = b[0].match(sorttable.DATE_RE);
+ y = mtch[3]; d = mtch[2]; m = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt2 = y+m+d;
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+ },
+
+ shaker_sort: function(list, comp_func) {
+ // A stable sort function to allow multi-level sorting of data
+ // see: http://en.wikipedia.org/wiki/Cocktail_sort
+ // thanks to Joseph Nahmias
+ var b = 0;
+ var t = list.length - 1;
+ var swap = true;
+
+ while(swap) {
+ swap = false;
+ for(var i = b; i < t; ++i) {
+ if ( comp_func(list[i], list[i+1]) > 0 ) {
+ var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
+ swap = true;
+ }
+ } // for
+ t--;
+
+ if (!swap) break;
+
+ for(var i = t; i > b; --i) {
+ if ( comp_func(list[i], list[i-1]) < 0 ) {
+ var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
+ swap = true;
+ }
+ } // for
+ b++;
+
+ } // while(swap)
+ }
+}
+
+/* ******************************************************************
+ Supporting functions: bundled here to avoid depending on a library
+ ****************************************************************** */
+
+// Dean Edwards/Matthias Miller/John Resig
+
+/* for Mozilla/Opera9 */
+if (document.addEventListener) {
+ document.addEventListener("DOMContentLoaded", sorttable.init, false);
+}
+
+/* for Internet Explorer */
+/*@cc_on @*/
+/*@if (@_win32)
+ document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
+ var script = document.getElementById("__ie_onload");
+ script.onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ sorttable.init(); // call the onload handler
+ }
+ };
+/*@end @*/
+
+/* for Safari */
+if (/WebKit/i.test(navigator.userAgent)) { // sniff
+ var _timer = setInterval(function() {
+ if (/loaded|complete/.test(document.readyState)) {
+ sorttable.init(); // call the onload handler
+ }
+ }, 10);
+}
+
+/* for other browsers */
+window.onload = sorttable.init;
+
+// written by Dean Edwards, 2005
+// with input from Tino Zijdel, Matthias Miller, Diego Perini
+
+// http://dean.edwards.name/weblog/2005/10/add-event/
+
+function dean_addEvent(element, type, handler) {
+ if (element.addEventListener) {
+ element.addEventListener(type, handler, false);
+ } else {
+ // assign each event handler a unique ID
+ if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
+ // create a hash table of event types for the element
+ if (!element.events) element.events = {};
+ // create a hash table of event handlers for each element/event pair
+ var handlers = element.events[type];
+ if (!handlers) {
+ handlers = element.events[type] = {};
+ // store the existing event handler (if there is one)
+ if (element["on" + type]) {
+ handlers[0] = element["on" + type];
+ }
+ }
+ // store the event handler in the hash table
+ handlers[handler.$$guid] = handler;
+ // assign a global event handler to do all the work
+ element["on" + type] = handleEvent;
+ }
+};
+// a counter used to create unique IDs
+dean_addEvent.guid = 1;
+
+function removeEvent(element, type, handler) {
+ if (element.removeEventListener) {
+ element.removeEventListener(type, handler, false);
+ } else {
+ // delete the event handler from the hash table
+ if (element.events && element.events[type]) {
+ delete element.events[type][handler.$$guid];
+ }
+ }
+};
+
+function handleEvent(event) {
+ var returnValue = true;
+ // grab the event object (IE uses a global event object)
+ event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
+ // get a reference to the hash table of event handlers
+ var handlers = this.events[event.type];
+ // execute each event handler
+ for (var i in handlers) {
+ this.$$handleEvent = handlers[i];
+ if (this.$$handleEvent(event) === false) {
+ returnValue = false;
+ }
+ }
+ return returnValue;
+};
+
+function fixEvent(event) {
+ // add W3C standard event methods
+ event.preventDefault = fixEvent.preventDefault;
+ event.stopPropagation = fixEvent.stopPropagation;
+ return event;
+};
+fixEvent.preventDefault = function() {
+ this.returnValue = false;
+};
+fixEvent.stopPropagation = function() {
+ this.cancelBubble = true;
+}
+
+// Dean's forEach: http://dean.edwards.name/base/forEach.js
+/*
+ forEach, version 1.0
+ Copyright 2006, Dean Edwards
+ License: http://www.opensource.org/licenses/mit-license.php
+*/
+
+// array-like enumeration
+if (!Array.forEach) { // mozilla already supports this
+ Array.forEach = function(array, block, context) {
+ for (var i = 0; i < array.length; i++) {
+ block.call(context, array[i], i, array);
+ }
+ };
+}
+
+// generic enumeration
+Function.prototype.forEach = function(object, block, context) {
+ for (var key in object) {
+ if (typeof this.prototype[key] == "undefined") {
+ block.call(context, object[key], key, object);
+ }
+ }
+};
+
+// character enumeration
+String.forEach = function(string, block, context) {
+ Array.forEach(string.split(""), function(chr, index) {
+ block.call(context, chr, index, string);
+ });
+};
+
+// globally resolve forEach enumeration
+var forEach = function(object, block, context) {
+ if (object) {
+ var resolve = Object; // default
+ if (object instanceof Function) {
+ // functions have a "length" property
+ resolve = Function;
+ } else if (object.forEach instanceof Function) {
+ // the object implements a custom forEach method so use that
+ object.forEach(block, context);
+ return;
+ } else if (typeof object == "string") {
+ // the object is a string
+ resolve = String;
+ } else if (typeof object.length == "number") {
+ // the object is array-like
+ resolve = Array;
+ }
+ resolve.forEach(object, block, context);
+ }
+};
diff --git a/chromium/tools/compile_test/compile_test.py b/chromium/tools/compile_test/compile_test.py
new file mode 100755
index 00000000000..bbda4abfe54
--- /dev/null
+++ b/chromium/tools/compile_test/compile_test.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Tries to compile given code, produces different output depending on success.
+
+This is similar to checks done by ./configure scripts.
+"""
+
+
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+
+def DoMain(argv):
+ parser = optparse.OptionParser()
+ parser.add_option('--code')
+ parser.add_option('--run-linker', action='store_true')
+ parser.add_option('--on-success', default='')
+ parser.add_option('--on-failure', default='')
+
+ options, args = parser.parse_args(argv)
+
+ if not options.code:
+ parser.error('Missing required --code switch.')
+
+ # The environment variable might expand to a string with spaces,
+ # e.g. "ccache g++". Convert it to a list suitable for argv.
+ cxx = os.environ.get('CXX', 'g++').split()
+
+ tmpdir = tempfile.mkdtemp()
+ try:
+ cxx_path = os.path.join(tmpdir, 'test.cc')
+ with open(cxx_path, 'w') as f:
+ f.write(options.code.decode('string-escape'))
+
+ o_path = os.path.join(tmpdir, 'test.o')
+
+ cxx_cmdline = cxx + [cxx_path, '-o', o_path]
+ if not options.run_linker:
+ cxx_cmdline.append('-c')
+ # Pass remaining arguments to the compiler.
+ cxx_cmdline += args
+ cxx_popen = subprocess.Popen(cxx_cmdline,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ cxx_stdout, cxx_stderr = cxx_popen.communicate()
+ if cxx_popen.returncode == 0:
+ print options.on_success
+ else:
+ print options.on_failure
+ finally:
+ shutil.rmtree(tmpdir)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(DoMain(sys.argv[1:]))
diff --git a/chromium/tools/coverity/coverity.py b/chromium/tools/coverity/coverity.py
new file mode 100755
index 00000000000..6fed7ca8cfa
--- /dev/null
+++ b/chromium/tools/coverity/coverity.py
@@ -0,0 +1,308 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Runs Coverity Prevent on a build of Chromium.
+
+This script should be run in a Visual Studio Command Prompt, so that the
+INCLUDE, LIB, and PATH environment variables are set properly for Visual
+Studio.
+
+Usage examples:
+ coverity.py
+ coverity.py --dry-run
+ coverity.py --target=debug
+ %comspec% /c ""C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"
+ x86 && C:\Python24\python.exe C:\coverity.py"
+
+For a full list of options, pass the '--help' switch.
+
+See http://support.microsoft.com/kb/308569 for running this script as a
+Scheduled Task on Windows XP.
+
+"""
+
+import optparse
+import os
+import os.path
+import shutil
+import subprocess
+import sys
+import time
+
+# These constants provide default values, but are exposed as command-line
+# flags. See the --help for more info. Note that for historical reasons
+# (the script started out as Windows-only and has legacy usages which pre-date
+# these switches), the constants are all tuned for Windows.
+# Usage of this script on Linux pretty much requires explicit
+# --source-dir, --coverity-bin-dir, --coverity-intermediate-dir, and
+# --coverity-target command line flags.
+
+CHROMIUM_SOURCE_DIR = 'C:\\chromium.latest'
+
+# Relative to CHROMIUM_SOURCE_DIR.
+CHROMIUM_SOLUTION_FILE = 'src\\chrome\\chrome.sln'
+
+# Relative to CHROMIUM_SOURCE_DIR.
+CHROMIUM_SOLUTION_DIR = 'src\\chrome'
+
+COVERITY_BIN_DIR = 'C:\\coverity\\prevent-win32-4.5.1\\bin'
+
+COVERITY_INTERMEDIATE_DIR = 'C:\\coverity\\cvbuild\\cr_int'
+
+COVERITY_ANALYZE_OPTIONS = ('--cxx --security --concurrency '
+ '--enable ATOMICITY '
+ '--enable MISSING_LOCK '
+ '--enable DELETE_VOID '
+ '--checker-option PASS_BY_VALUE:size_threshold:16 '
+ '--checker-option '
+ 'USE_AFTER_FREE:allow_simple_use:false '
+ '--enable-constraint-fpp '
+ '--enable-callgraph-metrics')
+
+# Might need to be changed to FQDN
+COVERITY_REMOTE = 'chromecoverity-linux1'
+
+COVERITY_PORT = '5467'
+
+COVERITY_PRODUCT = 'Chromium'
+
+COVERITY_TARGET = 'Windows'
+
+COVERITY_USER = 'admin'
+# looking for a PASSWORD constant? Look at --coverity-password-file instead.
+
+# Relative to CHROMIUM_SOURCE_DIR. Contains the pid of this script.
+LOCK_FILE = 'coverity.lock'
+
+
+def _ReadPassword(pwfilename):
+ """Reads the coverity password in from a file where it was stashed"""
+ pwfile = open(pwfilename, 'r')
+ password = pwfile.readline()
+ pwfile.close()
+ return password.rstrip()
+
+
+def _RunCommand(cmd, dry_run, shell=False, echo_cmd=True):
+ """Runs the command if dry_run is false, otherwise just prints the command."""
+ if echo_cmd:
+ print cmd
+ if not dry_run:
+ return subprocess.call(cmd, shell=shell)
+ else:
+ return 0
+
+
+def _ReleaseLock(lock_file, lock_filename):
+ """Removes the lockfile. Function-ized so we can bail from anywhere"""
+ os.close(lock_file)
+ os.remove(lock_filename)
+
+
+def run_coverity(options, args):
+ """Runs all the selected tests for the given build type and target."""
+ # Create the lock file to prevent another instance of this script from
+ # running.
+ lock_filename = os.path.join(options.source_dir, LOCK_FILE)
+ try:
+ lock_file = os.open(lock_filename,
+ os.O_CREAT | os.O_EXCL | os.O_TRUNC | os.O_RDWR)
+ except OSError, err:
+ print 'Failed to open lock file:\n ' + str(err)
+ return 1
+
+ # Write the pid of this script (the python.exe process) to the lock file.
+ os.write(lock_file, str(os.getpid()))
+
+ options.target = options.target.title()
+
+ start_time = time.time()
+
+ print 'Change directory to ' + options.source_dir
+ os.chdir(options.source_dir)
+
+ # The coverity-password filename may have been a relative path.
+ # If so, assume it's relative to the source directory, which means
+ # the time to read the password is after we do the chdir().
+ coverity_password = _ReadPassword(options.coverity_password_file)
+
+ cmd = 'gclient sync'
+ gclient_exit = _RunCommand(cmd, options.dry_run, shell=True)
+ if gclient_exit != 0:
+ print 'gclient aborted with status %s' % gclient_exit
+ _ReleaseLock(lock_file, lock_filename)
+ return 1
+
+ print 'Elapsed time: %ds' % (time.time() - start_time)
+
+ # Do a clean build. Remove the build output directory first.
+ if sys.platform.startswith('linux'):
+ rm_path = os.path.join(options.source_dir,'src','out',options.target)
+ elif sys.platform == 'win32':
+ rm_path = os.path.join(options.source_dir,options.solution_dir,
+ options.target)
+ elif sys.platform == 'darwin':
+ rm_path = os.path.join(options.source_dir,'src','xcodebuild')
+ else:
+ print 'Platform "%s" unrecognized, aborting' % sys.platform
+ _ReleaseLock(lock_file, lock_filename)
+ return 1
+
+ if options.dry_run:
+ print 'shutil.rmtree(%s)' % repr(rm_path)
+ else:
+ shutil.rmtree(rm_path,True)
+
+ if options.preserve_intermediate_dir:
+ print 'Preserving intermediate directory.'
+ else:
+ if options.dry_run:
+ print 'shutil.rmtree(%s)' % repr(options.coverity_intermediate_dir)
+ print 'os.mkdir(%s)' % repr(options.coverity_intermediate_dir)
+ else:
+ shutil.rmtree(options.coverity_intermediate_dir,True)
+ os.mkdir(options.coverity_intermediate_dir)
+
+ print 'Elapsed time: %ds' % (time.time() - start_time)
+
+ use_shell_during_make = False
+ if sys.platform.startswith('linux'):
+ use_shell_during_make = True
+ os.chdir('src')
+ _RunCommand('pwd', options.dry_run, shell=True)
+ cmd = '%s/cov-build --dir %s make BUILDTYPE=%s chrome' % (
+ options.coverity_bin_dir, options.coverity_intermediate_dir,
+ options.target)
+ elif sys.platform == 'win32':
+ cmd = ('%s\\cov-build.exe --dir %s devenv.com %s\\%s /build %s '
+ '/project chrome.vcproj') % (
+ options.coverity_bin_dir, options.coverity_intermediate_dir,
+ options.source_dir, options.solution_file, options.target)
+ elif sys.platform == 'darwin':
+ use_shell_during_make = True
+ os.chdir('src/chrome')
+ _RunCommand('pwd', options.dry_run, shell=True)
+ cmd = ('%s/cov-build --dir %s xcodebuild -project chrome.xcodeproj '
+ '-configuration %s -target chrome') % (
+ options.coverity_bin_dir, options.coverity_intermediate_dir,
+ options.target)
+
+
+ _RunCommand(cmd, options.dry_run, shell=use_shell_during_make)
+ print 'Elapsed time: %ds' % (time.time() - start_time)
+
+ cov_analyze_exe = os.path.join(options.coverity_bin_dir,'cov-analyze')
+ cmd = '%s --dir %s %s' % (cov_analyze_exe,
+ options.coverity_intermediate_dir,
+ options.coverity_analyze_options)
+ _RunCommand(cmd, options.dry_run, shell=use_shell_during_make)
+ print 'Elapsed time: %ds' % (time.time() - start_time)
+
+ cov_commit_exe = os.path.join(options.coverity_bin_dir,'cov-commit-defects')
+
+ # On Linux we have started using a Target with a space in it, so we want
+ # to quote it. On the other hand, Windows quoting doesn't work quite the
+ # same way. To be conservative, I'd like to avoid quoting an argument
+ # that doesn't need quoting and which we haven't historically been quoting
+ # on that platform. So, only quote the target if we have to.
+ coverity_target = options.coverity_target
+ if sys.platform != 'win32':
+ coverity_target = '"%s"' % coverity_target
+
+ cmd = ('%s --dir %s --remote %s --port %s '
+ '--product %s '
+ '--target %s '
+ '--user %s '
+ '--password %s') % (cov_commit_exe,
+ options.coverity_intermediate_dir,
+ options.coverity_dbhost,
+ options.coverity_port,
+ options.coverity_product,
+ coverity_target,
+ options.coverity_user,
+ coverity_password)
+ # Avoid echoing the Commit command because it has a password in it
+ _RunCommand(cmd, options.dry_run, shell=use_shell_during_make, echo_cmd=False)
+
+ print 'Total time: %ds' % (time.time() - start_time)
+
+ _ReleaseLock(lock_file, lock_filename)
+
+ return 0
+
+
+def main():
+ option_parser = optparse.OptionParser()
+ option_parser.add_option('', '--dry-run', action='store_true', default=False,
+ help='print but don\'t run the commands')
+
+ option_parser.add_option('', '--target', default='Release',
+ help='build target (Debug or Release)')
+
+ option_parser.add_option('', '--source-dir', dest='source_dir',
+ help='full path to directory ABOVE "src"',
+ default=CHROMIUM_SOURCE_DIR)
+
+ option_parser.add_option('', '--solution-file', dest='solution_file',
+ default=CHROMIUM_SOLUTION_FILE)
+
+ option_parser.add_option('', '--solution-dir', dest='solution_dir',
+ default=CHROMIUM_SOLUTION_DIR)
+
+ option_parser.add_option('', '--coverity-bin-dir', dest='coverity_bin_dir',
+ default=COVERITY_BIN_DIR)
+
+ option_parser.add_option('', '--coverity-intermediate-dir',
+ dest='coverity_intermediate_dir',
+ default=COVERITY_INTERMEDIATE_DIR)
+
+ option_parser.add_option('', '--coverity-analyze-options',
+ dest='coverity_analyze_options',
+ help=('all cov-analyze options, e.g. "%s"'
+ % COVERITY_ANALYZE_OPTIONS),
+ default=COVERITY_ANALYZE_OPTIONS)
+
+ option_parser.add_option('', '--coverity-db-host',
+ dest='coverity_dbhost',
+ help=('coverity defect db server hostname, e.g. %s'
+ % COVERITY_REMOTE),
+ default=COVERITY_REMOTE)
+
+ option_parser.add_option('', '--coverity-db-port', dest='coverity_port',
+ help=('port # of coverity web/db server, e.g. %s'
+ % COVERITY_PORT),
+ default=COVERITY_PORT)
+
+ option_parser.add_option('', '--coverity-product', dest='coverity_product',
+ help=('Product name reported to coverity, e.g. %s'
+ % COVERITY_PRODUCT),
+ default=COVERITY_PRODUCT)
+
+ option_parser.add_option('', '--coverity-target', dest='coverity_target',
+ help='Platform Target reported to coverity',
+ default=COVERITY_TARGET)
+
+ option_parser.add_option('', '--coverity-user', dest='coverity_user',
+ help='Username used to log into coverity',
+ default=COVERITY_USER)
+
+ option_parser.add_option('', '--coverity-password-file',
+ dest='coverity_password_file',
+ help='file containing the coverity password',
+ default='coverity-password')
+
+ helpmsg = ('By default, the intermediate dir is emptied before analysis. '
+ 'This switch disables that behavior.')
+ option_parser.add_option('', '--preserve-intermediate-dir',
+ action='store_true', help=helpmsg,
+ default=False)
+
+ options, args = option_parser.parse_args()
+ return run_coverity(options, args)
+
+
+if '__main__' == __name__:
+ sys.exit(main())
diff --git a/chromium/tools/crx_id/PRESUBMIT.py b/chromium/tools/crx_id/PRESUBMIT.py
new file mode 100644
index 00000000000..e8daa889a5a
--- /dev/null
+++ b/chromium/tools/crx_id/PRESUBMIT.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit script for crx_id.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+UNIT_TESTS = [
+ 'crx_id_unittest',
+]
+
+def CheckChangeOnUpload(input_api, output_api):
+ return input_api.canned_checks.RunPythonUnitTests(input_api,
+ output_api,
+ UNIT_TESTS)
+
+def CheckChangeOnCommit(input_api, output_api):
+ output = []
+ output.extend(input_api.canned_checks.RunPythonUnitTests(input_api,
+ output_api,
+ UNIT_TESTS))
+ output.extend(input_api.canned_checks.CheckDoNotSubmit(input_api,
+ output_api))
+ return output
diff --git a/chromium/tools/crx_id/__init__.py b/chromium/tools/crx_id/__init__.py
new file mode 100644
index 00000000000..b2e61d30f09
--- /dev/null
+++ b/chromium/tools/crx_id/__init__.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Module crx_id
+'''
+
+pass
diff --git a/chromium/tools/crx_id/crx_id.py b/chromium/tools/crx_id/crx_id.py
new file mode 100755
index 00000000000..dc30b736dc6
--- /dev/null
+++ b/chromium/tools/crx_id/crx_id.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Read a CRX file and write out the App ID and the Full Hash of the ID.
+See: http://code.google.com/chrome/extensions/crx.html
+and 'http://stackoverflow.com/questions/'
+ + '1882981/google-chrome-alphanumeric-hashes-to-identify-extensions'
+for docs on the format.
+"""
+
+import base64
+import os
+import sys
+import hashlib
+
+try:
+ import json
+except Exception:
+ import simplejson as json
+
+EXPECTED_CRX_MAGIC_NUM = 'Cr24'
+EXPECTED_CRX_VERSION = 2
+
+def usage(argv):
+ print "%s: crx_file" % argv[0]
+
+def HexToInt(hex_chars):
+ """ Convert bytes like \xab -> 171 """
+ val = 0
+ for i in xrange(len(hex_chars)):
+ val += pow(256, i) * ord(hex_chars[i])
+ return val
+
+def HexToMPDecimal(hex_chars):
+ """ Convert bytes to an MPDecimal string. Example \x00 -> "aa"
+ This gives us the AppID for a chrome extension.
+ """
+ result = ''
+ base = ord('a')
+ for i in xrange(len(hex_chars)):
+ value = ord(hex_chars[i])
+ dig1 = value / 16
+ dig2 = value % 16
+ result += chr(dig1 + base)
+ result += chr(dig2 + base)
+ return result
+
+def HexTo256(hex_chars):
+ """ Convert bytes to pairs of hex digits. E.g., \x00\x11 -> "{0x00, 0x11}"
+ The format is taylored for copy and paste into C code:
+ const uint8 sha256_hash[] = { ... }; """
+ result = []
+ for i in xrange(len(hex_chars)):
+ value = ord(hex_chars[i])
+ dig1 = value / 16
+ dig2 = value % 16
+ result.append('0x' + hex(dig1)[2:] + hex(dig2)[2:])
+ return '{%s}' % ', '.join(result)
+
+def GetPublicKeyPacked(f):
+ magic_num = f.read(4)
+ if magic_num != EXPECTED_CRX_MAGIC_NUM:
+ raise Exception('Invalid magic number: %s (expecting %s)' %
+ (magic_num,
+ EXPECTED_CRX_MAGIC_NUM))
+ version = f.read(4)
+ if not version[0] != EXPECTED_CRX_VERSION:
+ raise Exception('Invalid version number: %s (expecting %s)' %
+ (version,
+ EXPECTED_CRX_VERSION))
+ pub_key_len_bytes = HexToInt(f.read(4))
+ sig_len_bytes = HexToInt(f.read(4))
+ pub_key = f.read(pub_key_len_bytes)
+ return pub_key
+
+def GetPublicKeyFromPath(filepath, is_win_path=False):
+ # Normalize the path for windows to have capital drive letters.
+ # We intentionally don't check if sys.platform == 'win32' and just
+ # check if this looks like drive letter so that we can test this
+ # even on posix systems.
+ if (len(filepath) >= 2 and
+ filepath[0].islower() and
+ filepath[1] == ':'):
+ filepath = filepath[0].upper() + filepath[1:]
+
+ # On Windows, filepaths are encoded using UTF-16, little endian byte order,
+ # using "wide characters" that are 16 bits in size. On POSIX systems, the
+ # encoding is generally UTF-8, which has the property of being equivalent to
+ # ASCII when only ASCII characters are in the path.
+ if is_win_path:
+ filepath = filepath.encode('utf-16le')
+
+ return filepath
+
+def GetPublicKeyUnpacked(f, filepath):
+ manifest = json.load(f)
+ if 'key' not in manifest:
+ # Use the path as the public key.
+ # See Extension::GenerateIdForPath in extension.cc
+ return GetPublicKeyFromPath(filepath)
+ else:
+ return base64.standard_b64decode(manifest['key'])
+
+def HasPublicKey(filename):
+ if os.path.isdir(filename):
+ with open(os.path.join(filename, 'manifest.json'), 'rb') as f:
+ manifest = json.load(f)
+ return 'key' in manifest
+ return False
+
+def GetPublicKey(filename, from_file_path, is_win_path=False):
+ if from_file_path:
+ return GetPublicKeyFromPath(
+ filename, is_win_path=is_win_path)
+
+ pub_key = ''
+ if os.path.isdir(filename):
+ # Assume it's an unpacked extension
+ f = open(os.path.join(filename, 'manifest.json'), 'rb')
+ pub_key = GetPublicKeyUnpacked(f, filename)
+ f.close()
+ else:
+ # Assume it's a packed extension.
+ f = open(filename, 'rb')
+ pub_key = GetPublicKeyPacked(f)
+ f.close()
+ return pub_key
+
+def GetCRXHash(filename, from_file_path=False, is_win_path=False):
+ pub_key = GetPublicKey(filename, from_file_path, is_win_path=is_win_path)
+ pub_key_hash = hashlib.sha256(pub_key).digest()
+ return HexTo256(pub_key_hash)
+
+def GetCRXAppID(filename, from_file_path=False, is_win_path=False):
+ pub_key = GetPublicKey(filename, from_file_path, is_win_path=is_win_path)
+ pub_key_hash = hashlib.sha256(pub_key).digest()
+ # AppID is the MPDecimal of only the first 128 bits of the hash.
+ return HexToMPDecimal(pub_key_hash[:128/8])
+
+def main(argv):
+ if len(argv) != 2:
+ usage(argv)
+ return 1
+ print 'Raw Bytes: %s' % GetCRXHash(sys.argv[1])
+ print 'AppID: %s' % GetCRXAppID(sys.argv[1])
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/tools/crx_id/crx_id_unittest.py b/chromium/tools/crx_id/crx_id_unittest.py
new file mode 100755
index 00000000000..4d0f80f7534
--- /dev/null
+++ b/chromium/tools/crx_id/crx_id_unittest.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Verify that crx_id.py generates a reasonable string for a canned CRX file.
+"""
+
+import crx_id
+import os
+import shutil
+import sys
+import unittest
+import tempfile
+
+class CrxIdUnittest(unittest.TestCase):
+ CRX_ID_DIR = os.path.abspath(os.path.dirname(sys.argv[0]))
+ PACKED_CRX = os.path.join(CRX_ID_DIR,
+ 'jebgalgnebhfojomionfpkfelancnnkf.crx')
+
+ PACKED_APP_ID = 'jebgalgnebhfojomionfpkfelancnnkf'
+ PACKED_HASH_BYTES = \
+ '{0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec,' \
+ ' 0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5,' \
+ ' 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4,' \
+ ' 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40}'
+
+ def testPackedHashAppId(self):
+ """ Test the output generated for a canned, packed CRX. """
+ self.assertEqual(crx_id.GetCRXAppID(self.PACKED_CRX),
+ self.PACKED_APP_ID)
+ self.assertEqual(crx_id.GetCRXHash(self.PACKED_CRX),
+ self.PACKED_HASH_BYTES)
+
+ UNPACKED_APP_ID = 'cbcdidchbppangcjoddlpdjlenngjldk'
+ UNPACKED_HASH_BYTES = \
+ '{0x21, 0x23, 0x83, 0x27, 0x1f, 0xf0, 0xd6, 0x29,' \
+ ' 0xe3, 0x3b, 0xf3, 0x9b, 0x4d, 0xd6, 0x9b, 0x3a,' \
+ ' 0xff, 0x7d, 0x6b, 0xc4, 0x78, 0x30, 0x47, 0xa6,' \
+ ' 0x23, 0x12, 0x72, 0x84, 0x9b, 0x9a, 0xf6, 0x3c}'
+
+ def testUnpackedHashAppId(self):
+ """ Test the output generated for a canned, unpacked extension. """
+ # Copy ../../chrome/test/data/extensions/unpacked/manifest_with_key.json
+ # to a temporary location.
+ unpacked_test_manifest_path = os.path.join(
+ self.CRX_ID_DIR,
+ '..', '..', 'chrome', 'test', 'data', 'extensions', 'unpacked',
+ 'manifest_with_key.json')
+ temp_unpacked_crx = tempfile.mkdtemp()
+ shutil.copy2(unpacked_test_manifest_path,
+ os.path.join(temp_unpacked_crx, 'manifest.json'))
+ self.assertEqual(crx_id.GetCRXAppID(temp_unpacked_crx),
+ self.UNPACKED_APP_ID)
+ self.assertEqual(crx_id.GetCRXHash(temp_unpacked_crx),
+ self.UNPACKED_HASH_BYTES)
+ self.assertTrue(crx_id.HasPublicKey(temp_unpacked_crx))
+ shutil.rmtree(temp_unpacked_crx)
+
+ def testFromFilePath(self):
+ """ Test calculation of extension id from file paths. """
+ self.assertEqual(crx_id.GetCRXAppID('/tmp/temp_extension',
+ from_file_path=True),
+ 'ajbbicncdkdlchpjplgjaglppbcbmaji')
+
+ def testFromWindowsPath(self):
+ self.assertEqual(crx_id.GetCRXAppID(r'D:\Documents\chrome\test_extension',
+ from_file_path=True,
+ is_win_path=True),
+ 'fegemedmbnhglnecjgbdhekaghkccplm')
+
+ # Test drive letter normalization.
+ kWinPathId = 'aiinlcdagjihibappcdnnhcccdokjlaf'
+ self.assertEqual(crx_id.GetCRXAppID(r'c:\temp_extension',
+ from_file_path=True,
+ is_win_path=True),
+ kWinPathId)
+ self.assertEqual(crx_id.GetCRXAppID(r'C:\temp_extension',
+ from_file_path=True,
+ is_win_path=True),
+ kWinPathId)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/crx_id/jebgalgnebhfojomionfpkfelancnnkf.crx b/chromium/tools/crx_id/jebgalgnebhfojomionfpkfelancnnkf.crx
new file mode 100644
index 00000000000..4fb2a3b87b4
--- /dev/null
+++ b/chromium/tools/crx_id/jebgalgnebhfojomionfpkfelancnnkf.crx
Binary files differ
diff --git a/chromium/tools/cygprofile/cygprofile.cc b/chromium/tools/cygprofile/cygprofile.cc
new file mode 100644
index 00000000000..06e74b84629
--- /dev/null
+++ b/chromium/tools/cygprofile/cygprofile.cc
@@ -0,0 +1,401 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Tool to log the execution of the process (Chrome). Writes logs containing
+// time and address of the callback being called for the first time.
+//
+// To speed up the logging, buffering logs is implemented. Every thread have its
+// own buffer and log file so the contention between threads is minimal. As a
+// side-effect, functions called might be mentioned in many thread logs.
+//
+// Special thread is created in the process to periodically flushes logs for all
+// threads for the case the thread has stopped before flushing its logs.
+//
+// Use this profiler with linux_use_tcmalloc=0.
+//
+// Note for the ChromeOS Chrome. Remove renderer process from the sandbox (add
+// --no-sandbox option to running Chrome in /sbin/session_manager_setup.sh).
+// Otherwise renderer will not be able to write logs (and will assert on that).
+//
+// Also note that the instrumentation code is self-activated. It begins to
+// record the log data when it is called first, including the run-time startup.
+// Have it in mind when modifying it, in particular do not use global objects
+// with constructors as they are called during startup (too late for us).
+
+#include <fcntl.h>
+#include <fstream>
+#include <pthread.h>
+#include <stdarg.h>
+#include <string>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/synchronization/lock.h"
+
+namespace cygprofile {
+
+extern "C" {
+
+// Note that these are linked internally by the compiler. Don't call
+// them directly!
+void __cyg_profile_func_enter(void* this_fn, void* call_site)
+ __attribute__((no_instrument_function));
+void __cyg_profile_func_exit(void* this_fn, void* call_site)
+ __attribute__((no_instrument_function));
+
+}
+
+// Single log entry layout.
+struct CygLogEntry {
+ time_t seconds;
+ long int usec;
+ pid_t pid;
+ pthread_t tid;
+ const void* this_fn;
+ CygLogEntry(time_t seconds, long int usec,
+ pid_t pid, pthread_t tid, const void* this_fn)
+ : seconds(seconds), usec(usec),
+ pid(pid), tid(tid), this_fn(this_fn) {}
+};
+
+// Common data for the process. Singleton.
+class CygCommon {
+ public:
+ static CygCommon* GetInstance();
+ std::string header() const { return header_line_; }
+ private:
+ CygCommon();
+ std::string header_line_;
+ friend struct DefaultSingletonTraits<CygCommon>;
+
+ DISALLOW_COPY_AND_ASSIGN(CygCommon);
+};
+
+// Returns light-weight process ID. On linux, this is a system-wide
+// unique thread id.
+static pid_t GetLwp() {
+ return syscall(__NR_gettid);
+}
+
+// A per-thread structure representing the log itself.
+class CygTlsLog {
+ public:
+ CygTlsLog()
+ : in_use_(false), lwp_(GetLwp()), pthread_self_(pthread_self()) { }
+
+ // Enter a log entity.
+ void LogEnter(void* this_fn);
+
+ // Add newly created CygTlsLog object to the list of all such objects.
+ // Needed for the timer callback: it will enumerate each object and flush.
+ static void AddNewLog(CygTlsLog* newlog);
+
+ // Starts a thread in this process that periodically flushes all the threads.
+ // Must be called once per process.
+ static void StartFlushLogThread();
+
+ private:
+ static const int kBufMaxSize;
+ static const char kLogFilenameFmt[];
+ static const char kLogFileNamePrefix[];
+
+ // Flush the log to file. Create file if needed.
+ // Must be called with locked log_mutex_.
+ void FlushLog();
+
+ // Fork hooks. Needed to keep data in consistent state during fork().
+ static void AtForkPrepare();
+ static void AtForkParent();
+ static void AtForkChild();
+
+ // Thread callback to flush all logs periodically.
+ static void* FlushLogThread(void*);
+
+ std::string log_filename_;
+ std::vector<CygLogEntry> buf_;
+
+ // A lock that guards buf_ usage between per-thread instrumentation
+ // routine and timer flush callback. So the contention could happen
+ // only during the flush, every 30 secs.
+ base::Lock log_mutex_;
+
+ // Current thread is inside the instrumentation routine.
+ bool in_use_;
+
+ // Keeps track of all functions that have been logged on this thread
+ // so we do not record dublicates.
+ std::hash_set<void*> functions_called_;
+
+ // Thread identifier as Linux kernel shows it. For debugging purposes.
+ // LWP (light-weight process) is a unique ID of the thread in the system,
+ // unlike pthread_self() which is the same for fork()-ed threads.
+ pid_t lwp_;
+ pthread_t pthread_self_;
+
+ DISALLOW_COPY_AND_ASSIGN(CygTlsLog);
+};
+
+// Storage for logs for all threads in the process.
+// Using std::list may be better, but it fails when used before main().
+struct AllLogs {
+ std::vector<CygTlsLog*> logs;
+ base::Lock mutex;
+};
+
+base::LazyInstance<AllLogs>::Leaky all_logs_ = LAZY_INSTANCE_INITIALIZER;
+
+// Per-thread pointer to the current log object.
+static __thread CygTlsLog* tls_current_log = NULL;
+
+// Magic value of above to prevent the instrumentation. Used when CygTlsLog is
+// being constructed (to prevent reentering by malloc, for example) and by
+// the FlushLogThread (to prevent it being logged - see comment in its code).
+CygTlsLog* const kMagicBeingConstructed = reinterpret_cast<CygTlsLog*>(1);
+
+// Number of entries in the per-thread log buffer before we flush.
+// Note, that we also flush by timer so not all thread logs may grow up to this.
+const int CygTlsLog::kBufMaxSize = 3000;
+
+#if defined(OS_ANDROID)
+const char CygTlsLog::kLogFileNamePrefix[] =
+ "/data/local/tmp/chrome/cyglog/";
+#else
+const char CygTlsLog::kLogFileNamePrefix[] = "/var/log/chrome/";
+#endif
+
+// "cyglog.PID.LWP.pthread_self.PPID"
+const char CygTlsLog::kLogFilenameFmt[] = "%scyglog.%d.%d.%ld-%d";
+
+CygCommon* CygCommon::GetInstance() {
+ return Singleton<CygCommon>::get();
+}
+
+CygCommon::CygCommon() {
+ // Determine our module addresses.
+ std::ifstream mapsfile("/proc/self/maps");
+ CHECK(mapsfile.good());
+ static const int kMaxLineSize = 512;
+ char line[kMaxLineSize];
+ void (*this_fn)(void) =
+ reinterpret_cast<void(*)()>(__cyg_profile_func_enter);
+ while (mapsfile.getline(line, kMaxLineSize)) {
+ const std::string str_line = line;
+ size_t permindex = str_line.find("r-xp");
+ if (permindex != std::string::npos) {
+ int dashindex = str_line.find("-");
+ int spaceindex = str_line.find(" ");
+ char* p;
+ void* start = reinterpret_cast<void*>
+ (strtol((str_line.substr(0, dashindex)).c_str(),
+ &p, 16));
+ CHECK(*p == 0); // Could not determine start address.
+ void* end = reinterpret_cast<void*>
+ (strtol((str_line.substr(dashindex + 1,
+ spaceindex - dashindex - 1)).c_str(),
+ &p, 16));
+ CHECK(*p == 0); // Could not determine end address.
+
+ if (this_fn >= start && this_fn < end)
+ header_line_ = str_line;
+ }
+ }
+ mapsfile.close();
+ header_line_.append("\nsecs\tmsecs\tpid:threadid\tfunc\n");
+}
+
+void CygTlsLog::LogEnter(void* this_fn) {
+ if (in_use_)
+ return;
+ in_use_ = true;
+
+ if (functions_called_.find(this_fn) ==
+ functions_called_.end()) {
+ functions_called_.insert(this_fn);
+ base::AutoLock lock(log_mutex_);
+ if (buf_.capacity() < kBufMaxSize)
+ buf_.reserve(kBufMaxSize);
+ struct timeval timestamp;
+ gettimeofday(&timestamp, NULL);
+ buf_.push_back(CygLogEntry(time(NULL), timestamp.tv_usec,
+ getpid(), pthread_self(), this_fn));
+ if (buf_.size() == kBufMaxSize) {
+ FlushLog();
+ }
+ }
+
+ in_use_ = false;
+}
+
+void CygTlsLog::AtForkPrepare() {
+ CHECK(tls_current_log);
+ CHECK(tls_current_log->lwp_ == GetLwp());
+ CHECK(tls_current_log->pthread_self_ == pthread_self());
+ all_logs_.Get().mutex.Acquire();
+}
+
+void CygTlsLog::AtForkParent() {
+ CHECK(tls_current_log);
+ CHECK(tls_current_log->lwp_ == GetLwp());
+ CHECK(tls_current_log->pthread_self_ == pthread_self());
+ all_logs_.Get().mutex.Release();
+}
+
+void CygTlsLog::AtForkChild() {
+ CHECK(tls_current_log);
+
+ // Update the IDs of this new thread of the new process.
+ // Note that the process may (and Chrome main process forks zygote this way)
+ // call exec(self) after we return (to launch new shiny self). If done like
+ // that, PID and LWP will remain the same, but pthread_self() changes.
+ pid_t lwp = GetLwp();
+ CHECK(tls_current_log->lwp_ != lwp); // LWP is system-wide unique thread ID.
+ tls_current_log->lwp_ = lwp;
+
+ CHECK(tls_current_log->pthread_self_ == pthread_self());
+
+ // Leave the only current thread tls object because fork() clones only the
+ // current thread (the one that called fork) to the child process.
+ AllLogs& all_logs = all_logs_.Get();
+ all_logs.logs.clear();
+ all_logs.logs.push_back(tls_current_log);
+ CHECK(all_logs.logs.size() == 1);
+
+ // Clear log filename so it will be re-calculated with the new PIDs.
+ tls_current_log->log_filename_.clear();
+
+ // Create the thread that will periodically flush all logs for this process.
+ StartFlushLogThread();
+
+ // We do not update log header line (CygCommon data) as it will be the same
+ // because the new process is just a forked copy.
+ all_logs.mutex.Release();
+}
+
+void CygTlsLog::StartFlushLogThread() {
+ pthread_t tid;
+ CHECK(!pthread_create(&tid, NULL, &CygTlsLog::FlushLogThread, NULL));
+}
+
+void CygTlsLog::AddNewLog(CygTlsLog* newlog) {
+ CHECK(tls_current_log == kMagicBeingConstructed);
+ AllLogs& all_logs = all_logs_.Get();
+ base::AutoLock lock(all_logs.mutex);
+ if (all_logs.logs.empty()) {
+
+ // An Android app never fork, it always starts with a pre-defined number of
+ // process descibed by the android manifest file. In fact, there is not
+ // support for pthread_atfork at the android system libraries. All chrome
+ // for android processes will start as independent processs and each one
+ // will generate its own logs that will later have to be merged as usual.
+#if !defined(OS_ANDROID)
+ CHECK(!pthread_atfork(CygTlsLog::AtForkPrepare,
+ CygTlsLog::AtForkParent,
+ CygTlsLog::AtForkChild));
+#endif
+
+ // The very first process starts its flush thread here. Forked processes
+ // will do it in AtForkChild().
+ StartFlushLogThread();
+ }
+ all_logs.logs.push_back(newlog);
+}
+
+// Printf-style routine to write to open file.
+static void WriteLogLine(int fd, const char* fmt, ...) {
+ va_list arg_ptr;
+ va_start(arg_ptr, fmt);
+ char msg[160];
+ int len = vsnprintf(msg, sizeof(msg), fmt, arg_ptr);
+ int rc = write(fd, msg, (len > sizeof(msg))? sizeof(msg): len);
+ va_end(arg_ptr);
+};
+
+void CygTlsLog::FlushLog() {
+ bool first_log_write = false;
+ if (log_filename_.empty()) {
+ first_log_write = true;
+ char buf[80];
+ snprintf(buf, sizeof(buf), kLogFilenameFmt,
+ kLogFileNamePrefix, getpid(), lwp_, pthread_self_, getppid());
+ log_filename_ = buf;
+ unlink(log_filename_.c_str());
+ }
+
+ int file = open(log_filename_.c_str(), O_CREAT | O_WRONLY | O_APPEND, 00600);
+ CHECK(file != -1);
+
+ if (first_log_write)
+ WriteLogLine(file, "%s", CygCommon::GetInstance()->header().c_str());
+
+ for (int i = 0; i != buf_.size(); ++i) {
+ const CygLogEntry& p = buf_[i];
+ WriteLogLine(file, "%ld %ld\t%d:%ld\t%p\n",
+ p.seconds, p.usec, p.pid, p.tid, p.this_fn);
+ }
+
+ close(file);
+ buf_.clear();
+}
+
+void* CygTlsLog::FlushLogThread(void*) {
+ // Disable logging this thread. Although this routine is not instrumented
+ // (cygprofile.gyp provides that), the called routines are and thus will
+ // call instrumentation.
+ CHECK(tls_current_log == NULL); // Must be 0 as this is a new thread.
+ tls_current_log = kMagicBeingConstructed;
+
+ // Run this loop infinitely: sleep 30 secs and the flush all thread's
+ // buffers. There is a danger that, when quitting Chrome, this thread may
+ // see unallocated data and segfault. We do not care because we need logs
+ // when Chrome is working.
+ while (true) {
+ for(int secs_to_sleep = 30; secs_to_sleep != 0;)
+ secs_to_sleep = sleep(secs_to_sleep);
+
+ AllLogs& all_logs = all_logs_.Get();
+ base::AutoLock lock(all_logs.mutex);
+ for (int i = 0; i != all_logs.logs.size(); ++i) {
+ CygTlsLog* current_log = all_logs.logs[i];
+ base::AutoLock current_lock(current_log->log_mutex_);
+ if (current_log->buf_.size()) {
+ current_log->FlushLog();
+ } else {
+ // The thread's log is still empty. Probably the thread finished prior
+ // to previous timer fired - deallocate its buffer. Even if the thread
+ // ever resumes, it will allocate its buffer again in
+ // std::vector::push_back().
+ current_log->buf_.clear();
+ }
+ }
+ }
+}
+
+// Gcc Compiler callback, called on every function invocation providing
+// addresses of caller and callee codes.
+void __cyg_profile_func_enter(void* this_fn, void* callee_unused) {
+ if (tls_current_log == NULL) {
+ tls_current_log = kMagicBeingConstructed;
+ CygTlsLog* newlog = new CygTlsLog;
+ CHECK(newlog);
+ CygTlsLog::AddNewLog(newlog);
+ tls_current_log = newlog;
+ }
+ if (tls_current_log != kMagicBeingConstructed) {
+ tls_current_log->LogEnter(this_fn);
+ }
+}
+
+// Gcc Compiler callback, called after every function invocation providing
+// addresses of caller and callee codes.
+void __cyg_profile_func_exit(void* this_fn, void* call_site) {
+}
+
+} // namespace cygprofile
diff --git a/chromium/tools/cygprofile/cygprofile.gyp b/chromium/tools/cygprofile/cygprofile.gyp
new file mode 100644
index 00000000000..1e7c751ae47
--- /dev/null
+++ b/chromium/tools/cygprofile/cygprofile.gyp
@@ -0,0 +1,19 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ },
+ 'targets': [
+ {
+ 'target_name': 'cygprofile',
+ 'type': 'static_library',
+ 'include_dirs': [ '../..', ],
+ 'sources': [
+ 'cygprofile.cc',
+ ],
+ 'cflags!': [ '-finstrument-functions' ],
+ },
+ ],
+}
diff --git a/chromium/tools/cygprofile/mergetraces.py b/chromium/tools/cygprofile/mergetraces.py
new file mode 100755
index 00000000000..5d85920beb6
--- /dev/null
+++ b/chromium/tools/cygprofile/mergetraces.py
@@ -0,0 +1,186 @@
+#!/usr/bin/python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Use: ../mergetraces.py `ls cyglog.* -Sr` > merged_cyglog
+
+""""Merge multiple logs files from different processes into a single log.
+
+Given two log files of execution traces, merge the traces into a single trace.
+Merging will use timestamps (i.e. the first two columns of logged calls) to
+create a single log that is an ordered trace of calls by both processes.
+"""
+
+import optparse
+import os
+import string
+import subprocess
+import sys
+
+def ParseLogLines(lines):
+ """Parse log file lines.
+
+ Args:
+ lines: lines from log file produced by profiled run
+
+ Below is an example of a small log file:
+ 5086e000-52e92000 r-xp 00000000 b3:02 51276 libchromeview.so
+ secs msecs pid:threadid func
+ START
+ 1314897086 795828 3587:1074648168 0x509e105c
+ 1314897086 795874 3587:1074648168 0x509e0eb4
+ 1314897086 796326 3587:1074648168 0x509e0e3c
+ 1314897086 796552 3587:1074648168 0x509e07bc
+ END
+
+ Returns:
+ tuple conisiting of 1) an ordered list of the logged calls, as an array of
+ fields, 2) the virtual start address of the library, used to compute the
+ offset of the symbol in the library and 3) the virtual end address
+ """
+ call_lines = []
+ vm_start = 0
+ vm_end = 0
+ dash_index = lines[0].find ('-')
+ space_index = lines[0].find (' ')
+ vm_start = int (lines[0][:dash_index], 16)
+ vm_end = int (lines[0][dash_index+1:space_index], 16)
+ for line in lines[2:]:
+ line = line.strip()
+ # print hex (vm_start)
+ fields = line.split()
+ call_lines.append (fields)
+
+ return (call_lines, vm_start, vm_end)
+
+def HasDuplicates(calls):
+ """Funcition is a sanity check to make sure that calls are only logged once.
+
+ Args:
+ calls: list of calls logged
+
+ Returns:
+ boolean indicating if calls has duplicate calls
+ """
+ seen = []
+ for call in calls:
+ if call[3] in seen:
+ return true
+ else:
+ seen.append(call[3])
+
+def CheckTimestamps(calls):
+ """Prints warning to stderr if the call timestamps are not in order.
+
+ Args:
+ calls: list of calls logged
+ """
+ index = 0
+ last_timestamp_secs = -1
+ last_timestamp_ms = -1
+ while (index < len (calls)):
+ timestamp_secs = int (calls[index][0])
+ timestamp_ms = int (calls[index][1])
+ timestamp = (timestamp_secs * 1000000) + timestamp_ms
+ last_timestamp = (last_timestamp_secs * 1000000) + last_timestamp_ms
+ if (timestamp < last_timestamp):
+ sys.stderr.write("WARNING: last_timestamp: " + str(last_timestamp_secs)
+ + " " + str(last_timestamp_ms) + " timestamp: "
+ + str(timestamp_secs) + " " + str(timestamp_ms) + "\n")
+ last_timestamp_secs = timestamp_secs
+ last_timestamp_ms = timestamp_ms
+ index = index + 1
+
+def Convert (call_lines, startAddr, endAddr):
+ """Converts the call addresses to static offsets and removes invalid calls.
+
+ Removes profiled calls not in shared library using start and end virtual
+ addresses, converts strings to integer values, coverts virtual addresses to
+ address in shared library.
+
+ Returns:
+ list of calls as tuples (sec, msec, pid:tid, callee)
+ """
+ converted_calls = []
+ call_addresses = []
+ for fields in call_lines:
+ secs = int (fields[0])
+ msecs = int (fields[1])
+ callee = int (fields[3], 16)
+ # print ("callee: " + hex (callee) + " start: " + hex (startAddr) + " end: "
+ # + hex (endAddr))
+ if (callee >= startAddr and callee < endAddr
+ and (not callee in call_addresses)):
+ converted_calls.append((secs, msecs, fields[2], (callee - startAddr)))
+ call_addresses.append(callee)
+ return converted_calls
+
+def Timestamp(trace_entry):
+ return int (trace_entry[0]) * 1000000 + int(trace_entry[1])
+
+def AddTrace (tracemap, trace):
+ """Adds a trace to the tracemap.
+
+ Adds entries in the trace to the tracemap. All new calls will be added to
+ the tracemap. If the calls already exist in the tracemap then they will be
+ replaced if they happened sooner in the new trace.
+
+ Args:
+ tracemap: the tracemap
+ trace: the trace
+
+ """
+ for trace_entry in trace:
+ call = trace_entry[3]
+ if (not call in tracemap) or (
+ Timestamp(tracemap[call]) > Timestamp(trace_entry)):
+ tracemap[call] = trace_entry
+
+def main():
+ """Merge two traces for code in specified library and write to stdout.
+
+ Merges the two traces and coverts the virtual addresses to the offsets in the
+ library. First line of merged trace has dummy virtual address of 0-ffffffff
+ so that symbolizing the addresses uses the addresses in the log, since the
+ addresses have already been converted to static offsets.
+ """
+ parser = optparse.OptionParser('usage: %prog trace1 ... traceN')
+ (_, args) = parser.parse_args()
+ if len(args) <= 1:
+ parser.error('expected at least the following args: trace1 trace2')
+
+ step = 0
+ tracemap = dict()
+ for trace_file in args:
+ step += 1
+ sys.stderr.write(" " + str(step) + "/" + str(len(args)) +
+ ": " + trace_file + ":\n")
+
+ trace_lines = map(string.rstrip, open(trace_file).readlines())
+ (trace_calls, trace_start, trace_end) = ParseLogLines(trace_lines)
+ CheckTimestamps(trace_calls)
+ sys.stderr.write("Len: " + str(len(trace_calls)) +
+ ". Start: " + hex(trace_start) +
+ ", end: " + hex(trace_end) + '\n')
+
+ trace_calls = Convert(trace_calls, trace_start, trace_end)
+ sys.stderr.write("Converted len: " + str(len(trace_calls)) + "\n")
+
+ AddTrace(tracemap, trace_calls)
+ sys.stderr.write("Merged len: " + str(len(tracemap)) + "\n")
+
+ # Extract the resulting trace from the tracemap
+ merged_trace = []
+ for call in tracemap:
+ merged_trace.append(tracemap[call])
+ merged_trace.sort(key=Timestamp)
+
+ print "0-ffffffff r-xp 00000000 xx:00 00000 ./"
+ print "secs\tmsecs\tpid:threadid\tfunc"
+ for call in merged_trace:
+ print (str(call[0]) + "\t" + str(call[1]) + "\t" + call[2] + "\t" +
+ hex(call[3]))
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/cygprofile/patch_orderfile.py b/chromium/tools/cygprofile/patch_orderfile.py
new file mode 100755
index 00000000000..17cde76b96e
--- /dev/null
+++ b/chromium/tools/cygprofile/patch_orderfile.py
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import commands
+import os
+import sys
+
+orderfile = sys.argv[1]
+uninstrumented_shlib = sys.argv[2]
+
+nmlines_uninstrumented = commands.getoutput ('nm -S -n ' +
+ uninstrumented_shlib + ' | egrep "( t )|( W )|( T )"').split('\n')
+
+nmlines = []
+for nmline in nmlines_uninstrumented:
+ if (len(nmline.split()) == 4):
+ nmlines.append(nmline)
+
+# Map addresses to list of functions at that address. There are multiple
+# functions at an address because of aliasing.
+nm_index = 0
+uniqueAddrs = []
+addressMap = {}
+while nm_index < len(nmlines):
+ if (len(nmlines[nm_index].split()) == 4):
+ nm_int = int (nmlines[nm_index].split()[0], 16)
+ size = int (nmlines[nm_index].split()[1], 16)
+ fnames = [nmlines[nm_index].split()[3]]
+ nm_index = nm_index + 1
+ while nm_index < len(nmlines) and nm_int == int (
+ nmlines[nm_index].split()[0], 16):
+ fnames.append(nmlines[nm_index].split()[3])
+ nm_index = nm_index + 1
+ addressMap[nm_int] = fnames
+ uniqueAddrs.append((nm_int, size))
+ else:
+ nm_index = nm_index + 1
+
+def binary_search (addr, start, end):
+ # print "addr: " + str(addr) + " start: " + str(start) + " end: " + str(end)
+ if start >= end or start == end - 1:
+ (nm_addr, size) = uniqueAddrs[start]
+ if not (addr >= nm_addr and addr < nm_addr + size):
+ sys.stderr.write ("ERROR: did not find function in binary: addr: " +
+ hex(addr) + " nm_addr: " + str(nm_addr) + " start: " + str(start) +
+ " end: " + str(end) + "\n")
+ raise Error("error")
+ return (addressMap[nm_addr], size)
+ else:
+ halfway = start + ((end - start) / 2)
+ (nm_addr, size) = uniqueAddrs[halfway]
+ # print "nm_addr: " + str(nm_addr) + " halfway: " + str(halfway)
+ if (addr >= nm_addr and addr < nm_addr + size):
+ return (addressMap[nm_addr], size)
+ elif (addr < nm_addr):
+ return binary_search (addr, start, halfway)
+ elif (addr >= nm_addr + size):
+ return binary_search (addr, halfway, end)
+ else:
+ raise "ERROR: did not expect this case"
+
+f = open (orderfile)
+lines = f.readlines()
+profiled_list = []
+for line in lines:
+ if (line.strip() == ''):
+ continue
+ functionName = line.replace('.text.', '').split('.clone.')[0].strip()
+ profiled_list.append (functionName)
+
+# Symbol names are not unique. Since the order file uses symbol names, the
+# patched order file pulls in all symbols with the same name. Multiple function
+# addresses for the same function name may also be due to ".clone" symbols,
+# since the substring is stripped.
+functions = []
+functionAddressMap = {}
+for line in nmlines:
+ try:
+ functionName = line.split()[3]
+ except:
+ functionName = line.split()[2]
+ functionName = functionName.split('.clone.')[0]
+ functionAddress = int (line.split()[0].strip(), 16)
+ try:
+ functionAddressMap[functionName].append(functionAddress)
+ except:
+ functionAddressMap[functionName] = [functionAddress]
+ functions.append(functionName)
+
+sys.stderr.write ("profiled list size: " + str(len(profiled_list)) + "\n")
+addresses = []
+symbols_found = 0
+for function in profiled_list:
+ try:
+ addrs = functionAddressMap[function]
+ symbols_found = symbols_found + 1
+ except:
+ addrs = []
+ # sys.stderr.write ("WARNING: could not find symbol " + function + "\n")
+ for addr in addrs:
+ if not (addr in addresses):
+ addresses.append(addr)
+sys.stderr.write ("symbols found: " + str(symbols_found) + "\n")
+
+sys.stderr.write ("number of addresses: " + str(len(addresses)) + "\n")
+total_size = 0
+for addr in addresses:
+ # if (count % 500 == 0):
+ # print "current count: " + str(count)
+ (functions, size) = binary_search (addr, 0, len(uniqueAddrs))
+ total_size = total_size + size
+ for function in functions:
+ print ".text." + function
+ print ""
+sys.stderr.write ("total_size: " + str(total_size) + "\n")
diff --git a/chromium/tools/cygprofile/symbolize.py b/chromium/tools/cygprofile/symbolize.py
new file mode 100755
index 00000000000..694ae54f9b0
--- /dev/null
+++ b/chromium/tools/cygprofile/symbolize.py
@@ -0,0 +1,251 @@
+#!/usr/bin/python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Symbolize log file produced by cypgofile instrumentation.
+
+Given a log file and the binary being profiled (e.g. executable, shared
+library), the script can produce three different outputs: 1) symbols for the
+addresses, 2) function and line numbers for the addresses, or 3) an order file.
+"""
+
+import optparse
+import os
+import string
+import subprocess
+import sys
+
+
+def ParseLogLines(log_file_lines):
+ """Parse a log file produced by the profiled run of clank.
+
+ Args:
+ log_file_lines: array of lines in log file produced by profiled run
+ lib_name: library or executable containing symbols
+
+ Below is an example of a small log file:
+ 5086e000-52e92000 r-xp 00000000 b3:02 51276 libchromeview.so
+ secs msecs pid:threadid func
+ START
+ 1314897086 795828 3587:1074648168 0x509e105c
+ 1314897086 795874 3587:1074648168 0x509e0eb4
+ 1314897086 796326 3587:1074648168 0x509e0e3c
+ 1314897086 796552 3587:1074648168 0x509e07bc
+ END
+
+ Returns:
+ call_info list with list of tuples of the format (sec, msec, call id,
+ function address called)
+ """
+ call_lines = []
+ has_started = False
+ vm_start = 0
+ line = log_file_lines[0]
+ assert("r-xp" in line)
+ end_index = line.find('-')
+ vm_start = int(line[:end_index], 16)
+ for line in log_file_lines[2:]:
+ # print hex(vm_start)
+ fields = line.split()
+ if len(fields) == 4:
+ call_lines.append(fields)
+
+ # Convert strings to int in fields.
+ call_info = []
+ for call_line in call_lines:
+ (sec_timestamp, msec_timestamp) = map(int, call_line[0:2])
+ callee_id = call_line[2]
+ addr = int(call_line[3], 16)
+ if vm_start < addr:
+ addr -= vm_start
+ call_info.append((sec_timestamp, msec_timestamp, callee_id, addr))
+
+ return call_info
+
+
+def ParseLibSymbols(lib_file):
+ """Get output from running nm and greping for text symbols.
+
+ Args:
+ lib_file: the library or executable that contains the profiled code
+
+ Returns:
+ list of sorted unique addresses and corresponding size of function symbols
+ in lib_file and map of addresses to all symbols at a particular address
+ """
+ cmd = ['nm', '-S', '-n', lib_file]
+ nm_p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ output = nm_p.communicate()[0]
+ nm_lines = output.split('\n')
+
+ nm_symbols = []
+ for nm_line in nm_lines:
+ if any(str in nm_line for str in (' t ', ' W ', ' T ')):
+ nm_symbols.append(nm_line)
+
+ nm_index = 0
+ unique_addrs = []
+ address_map = {}
+ while nm_index < len(nm_symbols):
+
+ # If the length of the split line is not 4, then it does not contain all the
+ # information needed to symbolize (i.e. address, size and symbol name).
+ if len(nm_symbols[nm_index].split()) == 4:
+ (addr, size) = [int(x, 16) for x in nm_symbols[nm_index].split()[0:2]]
+
+ # Multiple symbols may be at the same address. This is do to aliasing
+ # done by the compiler. Since there is no way to be sure which one was
+ # called in profiled run, we will symbolize to include all symbol names at
+ # a particular address.
+ fnames = []
+ while (nm_index < len(nm_symbols) and
+ addr == int(nm_symbols[nm_index].split()[0], 16)):
+ if len(nm_symbols[nm_index].split()) == 4:
+ fnames.append(nm_symbols[nm_index].split()[3])
+ nm_index += 1
+ address_map[addr] = fnames
+ unique_addrs.append((addr, size))
+ else:
+ nm_index += 1
+
+ return (unique_addrs, address_map)
+
+class SymbolNotFoundException(Exception):
+ def __init__(self,value):
+ self.value = value
+ def __str__(self):
+ return repr(self.value)
+
+def BinarySearchAddresses(addr, start, end, arr):
+ """Find starting address of a symbol at a particular address.
+
+ The reason we can not directly use the address provided by the log file is
+ that the log file may give an address after the start of the symbol. The
+ logged address is often one byte after the start. By using this search
+ function rather than just subtracting one from the logged address allows
+ the logging instrumentation to log any address in a function.
+
+ Args:
+ addr: the address being searched for
+ start: the starting index for the binary search
+ end: the ending index for the binary search
+ arr: the list being searched containing tuple of address and size
+
+ Returns:
+ the starting address of the symbol at address addr
+
+ Raises:
+ Exception: if address not found. Functions expects all logged addresses
+ to be found
+ """
+ # print "addr: " + str(addr) + " start: " + str(start) + " end: " + str(end)
+ if start >= end or start == end - 1:
+ # arr[i] is a tuple of address and size. Check if addr inside range
+ if addr >= arr[start][0] and addr < arr[start][0] + arr[start][1]:
+ return arr[start][0]
+ elif addr >= arr[end][0] and addr < arr[end][0] + arr[end][1]:
+ return arr[end][0]
+ else:
+ raise SymbolNotFoundException(addr)
+ else:
+ halfway = (start + end) / 2
+ (nm_addr, size) = arr[halfway]
+ # print "nm_addr: " + str(nm_addr) + " halfway: " + str(halfway)
+ if addr >= nm_addr and addr < nm_addr + size:
+ return nm_addr
+ elif addr < nm_addr:
+ return BinarySearchAddresses(addr, start, halfway-1, arr)
+ else:
+ # Condition (addr >= nm_addr + size) must be true.
+ return BinarySearchAddresses(addr, halfway+1, end, arr)
+
+
+def FindFunctions(addr, unique_addrs, address_map):
+ """Find function symbol names at address addr."""
+ return address_map[BinarySearchAddresses(addr, 0, len(unique_addrs) - 1,
+ unique_addrs)]
+
+
+def AddrToLine(addr, lib_file):
+ """Use addr2line to determine line info of a particular address."""
+ cmd = ['addr2line', '-f', '-e', lib_file, hex(addr)]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ output = (p.communicate()[0]).split('\n')
+ line = output[0]
+ index = 1
+ while index < len(output):
+ line = line + ':' + output[index]
+ index += 1
+ return line
+
+
+def main():
+ """Write output for profiled run to standard out.
+
+ The format of the output depends on the output type specified as the third
+ command line argument. The default output type is to symbolize the addresses
+ of the functions called.
+ """
+ parser = optparse.OptionParser('usage: %prog [options] log_file lib_file')
+ parser.add_option('-t', '--outputType', dest='output_type',
+ default='symbolize', type='string',
+ help='lineize or symbolize or orderfile')
+
+ # Option for output type. The log file and lib file arguments are required
+ # by the script and therefore are not options.
+ (options, args) = parser.parse_args()
+ if len(args) != 2:
+ parser.error('expected 2 args: log_file lib_file')
+
+ (log_file, lib_file) = args
+ output_type = options.output_type
+
+ lib_name = lib_file.split('/')[-1].strip()
+ log_file_lines = map(string.rstrip, open(log_file).readlines())
+ call_info = ParseLogLines(log_file_lines)
+ (unique_addrs, address_map) = ParseLibSymbols(lib_file)
+
+ # Check for duplicate addresses in the log file, and print a warning if
+ # duplicates are found. The instrumentation that produces the log file
+ # should only print the first time a function is entered.
+ addr_list = []
+ for call in call_info:
+ addr = call[3]
+ if addr not in addr_list:
+ addr_list.append(addr)
+ else:
+ print('WARNING: Address ' + hex(addr) + ' (line= ' +
+ AddrToLine(addr, lib_file) + ') already profiled.')
+
+ for call in call_info:
+ if output_type == 'lineize':
+ symbol = AddrToLine(call[3], lib_file)
+ print(str(call[0]) + ' ' + str(call[1]) + '\t' + str(call[2]) + '\t'
+ + symbol)
+ elif output_type == 'orderfile':
+ try:
+ symbols = FindFunctions(call[3], unique_addrs, address_map)
+ for symbol in symbols:
+ print '.text.' + symbol
+ print ''
+ except SymbolNotFoundException as e:
+ sys.stderr.write('WARNING: Did not find function in binary. addr: '
+ + hex(addr) + '\n')
+ else:
+ try:
+ symbols = FindFunctions(call[3], unique_addrs, address_map)
+ print(str(call[0]) + ' ' + str(call[1]) + '\t' + str(call[2]) + '\t'
+ + symbols[0])
+ first_symbol = True
+ for symbol in symbols:
+ if not first_symbol:
+ print '\t\t\t\t\t' + symbol
+ else:
+ first_symbol = False
+ except SymbolNotFoundException as e:
+ sys.stderr.write('WARNING: Did not find function in binary. addr: '
+ + hex(addr) + '\n')
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/deep_memory_profiler/OWNERS b/chromium/tools/deep_memory_profiler/OWNERS
new file mode 100644
index 00000000000..aeea00ec3e0
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/OWNERS
@@ -0,0 +1 @@
+dmikurube@chromium.org
diff --git a/chromium/tools/deep_memory_profiler/PRESUBMIT.py b/chromium/tools/deep_memory_profiler/PRESUBMIT.py
new file mode 100644
index 00000000000..965fad9beda
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/PRESUBMIT.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for deep_memory_profiler.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+
+def CommonChecks(input_api, output_api):
+ import sys
+ def join(*args):
+ return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
+
+ output = []
+ sys_path_backup = sys.path
+ try:
+ sys.path = [
+ join('..', 'find_runtime_symbols'),
+ ] + sys.path
+ output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+ finally:
+ sys.path = sys_path_backup
+
+ output.extend(
+ input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api,
+ input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'),
+ whitelist=[r'.+_test\.py$']))
+
+ if input_api.is_committing:
+ output.extend(input_api.canned_checks.PanProjectChecks(input_api,
+ output_api,
+ owners_check=False))
+ return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/chromium/tools/deep_memory_profiler/README.policy b/chromium/tools/deep_memory_profiler/README.policy
new file mode 100644
index 00000000000..48ad9579cc3
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/README.policy
@@ -0,0 +1,56 @@
+Policy files contains a classification policy for dmprof.py.
+
+Each line indicates a group to be classified and conditions for classifying
+in the following format.
+ Format: <group-name> <region-type> <pattern>
+
+<group-name> is a name for the group to be classified. Same names can appear
+in the same policy file multiple times. <region-type> represents a type of
+the memory region. It's one of {malloc, mmap, default, optional}. <pattern>
+is a Python-style regular expression to match with calling stack frames.
+
+For each memory chunks allocated by malloc, its calling stack frame of malloc
+is compared with these classification policies whose <region-type> is 'malloc'
+from the top. If <pattern> of the policy matches the frame, the memory chunk
+is classified into <group-name>. The same way for 'mmap'.
+
+Policy lines whose <region-type>s are 'optional' and 'default' are used by
+dmprof.py internally. 'optional' policies can be disabled by removing or
+commenting-out.
+
+
+Guidelines to write a new policy.
+
+Better policies would classify memory on a single layer, or simple combination
+of layers. For example,
+- Large-level components (V8, WebKit, ...)
+- Mid-level components (Font, FileAPI, ...)
+- Low-level libraries (StringImpl, HashTable, ...)
+- Mid-level libraries (SharedBuf, XHR, ...)
+
+For example of combinations,
+- How about SharedBuf in Font API v.s. other APIs?
+- How about Strings in IndexedDB v.s. File APIs?
+
+
+Deprecated policies for references.
+
+total-vm optional optional
+anonymous-vm optional optional
+filemapped-vm optional optional
+other-vm optional optional
+vm-profiler optional optional
+vm-total optional optional
+mmap-v8-heap-new mmap .*v8::.*::ReserveInitialChunk.*
+mmap-v8-heap-coderange mmap .*v8::.*::CodeRange::Setup.*
+mmap-v8-heap-old-evacuate mmap .*v8::.*::OldSpace::.* v8::internal::ScavengingVisitor::EvacuateObject.*
+mmap-v8-heap-old mmap .*v8::.*::OldSpace::.*
+mmap-v8-heap-largeobj mmap .*v8::.*::LargeObjectChunk::New.*
+mmap-v8-heap-other mmap .*VirtualMemory.*
+mmap-v8-heap-other mmap .*v8::internal::OS::Allocate.*
+mmap-v8-nonheap mmap .*v8::.*
+mmap-webkit mmap .*(WTF::|WebCore::|WebKit::).*
+mmap-sqlite mmap .*sqlite3MemMalloc.*
+mmap-pl-arena mmap .*PL_ArenaAllocate.*
+mmap-sk mmap .*sk_malloc_flags.*
+mmap-total-record-vm default default
diff --git a/chromium/tools/deep_memory_profiler/dmprof b/chromium/tools/deep_memory_profiler/dmprof
new file mode 100755
index 00000000000..a43f9f663af
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/dmprof
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Re-direct the arguments to dmprof.py.
+
+BASEDIR=`dirname $0`
+ARGV="$@"
+
+PYTHONPATH=$BASEDIR/../python/google python \
+ "$BASEDIR/dmprof.py" $ARGV
diff --git a/chromium/tools/deep_memory_profiler/dmprof.py b/chromium/tools/deep_memory_profiler/dmprof.py
new file mode 100644
index 00000000000..0cb030a32fe
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/dmprof.py
@@ -0,0 +1,81 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The Deep Memory Profiler analyzer script.
+
+See http://dev.chromium.org/developers/deep-memory-profiler for details.
+"""
+
+import logging
+import sys
+
+from lib.exceptions import ParsingException
+import subcommands
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+def main():
+ COMMANDS = {
+ 'buckets': subcommands.BucketsCommand,
+ 'cat': subcommands.CatCommand,
+ 'csv': subcommands.CSVCommand,
+ 'expand': subcommands.ExpandCommand,
+ 'json': subcommands.JSONCommand,
+ 'list': subcommands.ListCommand,
+ 'map': subcommands.MapCommand,
+ 'pprof': subcommands.PProfCommand,
+ 'stacktrace': subcommands.StacktraceCommand,
+ 'upload': subcommands.UploadCommand,
+ }
+
+ if len(sys.argv) < 2 or (not sys.argv[1] in COMMANDS):
+ sys.stderr.write("""Usage: dmprof <command> [options] [<args>]
+
+Commands:
+ buckets Dump a bucket list with resolving symbols
+ cat Categorize memory usage (under development)
+ csv Classify memory usage in CSV
+ expand Show all stacktraces contained in the specified component
+ json Classify memory usage in JSON
+ list Classify memory usage in simple listing format
+ map Show history of mapped regions
+ pprof Format the profile dump so that it can be processed by pprof
+ stacktrace Convert runtime addresses to symbol names
+ upload Upload dumped files
+
+Quick Reference:
+ dmprof buckets <first-dump>
+ dmprof cat <first-dump>
+ dmprof csv [-p POLICY] <first-dump>
+ dmprof expand <dump> <policy> <component> <depth>
+ dmprof json [-p POLICY] <first-dump>
+ dmprof list [-p POLICY] <first-dump>
+ dmprof map <first-dump> <policy>
+ dmprof pprof [-c COMPONENT] <dump> <policy>
+ dmprof stacktrace <dump>
+ dmprof upload [--gsutil path/to/gsutil] <first-dump> <destination-gs-path>
+""")
+ sys.exit(1)
+ action = sys.argv.pop(1)
+
+ LOGGER.setLevel(logging.DEBUG)
+ handler = logging.StreamHandler()
+ handler.setLevel(logging.INFO)
+ formatter = logging.Formatter('%(message)s')
+ handler.setFormatter(formatter)
+ LOGGER.addHandler(handler)
+
+ try:
+ errorcode = COMMANDS[action]().do(sys.argv)
+ except ParsingException, e:
+ errorcode = 1
+ sys.stderr.write('Exit by parsing error: %s\n' % e)
+
+ return errorcode
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/deep_memory_profiler/download.sh b/chromium/tools/deep_memory_profiler/download.sh
new file mode 100755
index 00000000000..c11bdfc5a9f
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/download.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+svn checkout --force \
+ http://src.chromium.org/chrome/trunk/src/tools/deep_memory_profiler \
+ deep_memory_profiler
diff --git a/chromium/tools/deep_memory_profiler/graph.py b/chromium/tools/deep_memory_profiler/graph.py
new file mode 100755
index 00000000000..4d5d3fe7cc2
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/graph.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import sys
+from string import Template
+
+
+_HTML_TEMPLATE = """
+<html>
+ <head>
+ <script type='text/javascript' src='https://www.google.com/jsapi'></script>
+ <script type='text/javascript'>
+ google.load('visualization', '1', {packages:['corechart', 'table']});
+ google.setOnLoadCallback(drawVisualization);
+ function drawVisualization() {
+ var data = google.visualization.arrayToDataTable(
+ $JSON_ARRAY
+ );
+
+ var charOptions = {
+ title: 'DMP Graph',
+ vAxis: {title: 'Timestamp', titleTextStyle: {color: 'red'}},
+ isStacked : true
+ };
+
+ var chart = new google.visualization.BarChart(
+ document.getElementById('chart_div'));
+ chart.draw(data, charOptions);
+
+ var table = new google.visualization.Table(
+ document.getElementById('table_div'));
+ table.draw(data);
+ }
+ </script>
+ </head>
+ <body>
+ <div id='chart_div' style="width: 1024px; height: 800px;"></div>
+ <div id='table_div' style="width: 1024px; height: 640px;"></div>
+ </body>
+</html>
+"""
+
+def _GenerateGraph(json_data, policy):
+ legends = list(json_data['policies'][policy]['legends'])
+ legends = ['second'] + legends[legends.index('FROM_HERE_FOR_TOTAL') + 1:
+ legends.index('UNTIL_HERE_FOR_TOTAL')]
+ data = []
+ for snapshot in json_data['policies'][policy]['snapshots']:
+ data.append([0] * len(legends))
+ for k, v in snapshot.iteritems():
+ if k in legends:
+ data[-1][legends.index(k)] = v
+ print Template(_HTML_TEMPLATE).safe_substitute(
+ {'JSON_ARRAY': json.dumps([legends] + data)})
+
+
+def main(argv):
+ _GenerateGraph(json.load(file(argv[1], 'r')), argv[2])
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
+
+
diff --git a/chromium/tools/deep_memory_profiler/lib/__init__.py b/chromium/tools/deep_memory_profiler/lib/__init__.py
new file mode 100644
index 00000000000..9228df89b0e
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/deep_memory_profiler/lib/bucket.py b/chromium/tools/deep_memory_profiler/lib/bucket.py
new file mode 100644
index 00000000000..51af5b2ddd8
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/bucket.py
@@ -0,0 +1,191 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+
+from lib.symbol import FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS, TYPEINFO_SYMBOLS
+
+
+LOGGER = logging.getLogger('dmprof')
+
+# Indexes in dumped heap profile dumps.
+VIRTUAL, COMMITTED, ALLOC_COUNT, FREE_COUNT, _, BUCKET_ID = range(6)
+
+
+class Bucket(object):
+ """Represents a bucket, which is a unit of memory block classification."""
+
+ def __init__(self, stacktrace, allocator_type, typeinfo, typeinfo_name):
+ self._stacktrace = stacktrace
+ self._allocator_type = allocator_type
+ self._typeinfo = typeinfo
+ self._typeinfo_name = typeinfo_name
+
+ self._symbolized_stackfunction = stacktrace
+ self._symbolized_joined_stackfunction = ''
+ self._symbolized_stacksourcefile = stacktrace
+ self._symbolized_joined_stacksourcefile = ''
+ self._symbolized_typeinfo = typeinfo_name
+
+ self.component_cache = ''
+
+ def __str__(self):
+ result = []
+ result.append(self._allocator_type)
+ if self._symbolized_typeinfo == 'no typeinfo':
+ result.append('tno_typeinfo')
+ else:
+ result.append('t' + self._symbolized_typeinfo)
+ result.append('n' + self._typeinfo_name)
+ result.extend(['%s(@%s)' % (function, sourcefile)
+ for function, sourcefile
+ in zip(self._symbolized_stackfunction,
+ self._symbolized_stacksourcefile)])
+ return ' '.join(result)
+
+ def symbolize(self, symbol_mapping_cache):
+ """Makes a symbolized stacktrace and typeinfo with |symbol_mapping_cache|.
+
+ Args:
+ symbol_mapping_cache: A SymbolMappingCache object.
+ """
+ # TODO(dmikurube): Fill explicitly with numbers if symbol not found.
+ self._symbolized_stackfunction = [
+ symbol_mapping_cache.lookup(FUNCTION_SYMBOLS, address)
+ for address in self._stacktrace]
+ self._symbolized_joined_stackfunction = ' '.join(
+ self._symbolized_stackfunction)
+ self._symbolized_stacksourcefile = [
+ symbol_mapping_cache.lookup(SOURCEFILE_SYMBOLS, address)
+ for address in self._stacktrace]
+ self._symbolized_joined_stacksourcefile = ' '.join(
+ self._symbolized_stacksourcefile)
+ if not self._typeinfo:
+ self._symbolized_typeinfo = 'no typeinfo'
+ else:
+ self._symbolized_typeinfo = symbol_mapping_cache.lookup(
+ TYPEINFO_SYMBOLS, self._typeinfo)
+ if not self._symbolized_typeinfo:
+ self._symbolized_typeinfo = 'no typeinfo'
+
+ def clear_component_cache(self):
+ self.component_cache = ''
+
+ @property
+ def stacktrace(self):
+ return self._stacktrace
+
+ @property
+ def allocator_type(self):
+ return self._allocator_type
+
+ @property
+ def typeinfo(self):
+ return self._typeinfo
+
+ @property
+ def typeinfo_name(self):
+ return self._typeinfo_name
+
+ @property
+ def symbolized_stackfunction(self):
+ return self._symbolized_stackfunction
+
+ @property
+ def symbolized_joined_stackfunction(self):
+ return self._symbolized_joined_stackfunction
+
+ @property
+ def symbolized_stacksourcefile(self):
+ return self._symbolized_stacksourcefile
+
+ @property
+ def symbolized_joined_stacksourcefile(self):
+ return self._symbolized_joined_stacksourcefile
+
+ @property
+ def symbolized_typeinfo(self):
+ return self._symbolized_typeinfo
+
+
+class BucketSet(object):
+ """Represents a set of bucket."""
+ def __init__(self):
+ self._buckets = {}
+ self._code_addresses = set()
+ self._typeinfo_addresses = set()
+
+ def load(self, prefix):
+ """Loads all related bucket files.
+
+ Args:
+ prefix: A prefix string for bucket file names.
+ """
+ LOGGER.info('Loading bucket files.')
+
+ n = 0
+ skipped = 0
+ while True:
+ path = '%s.%04d.buckets' % (prefix, n)
+ if not os.path.exists(path) or not os.stat(path).st_size:
+ if skipped > 10:
+ break
+ n += 1
+ skipped += 1
+ continue
+ LOGGER.info(' %s' % path)
+ with open(path, 'r') as f:
+ self._load_file(f)
+ n += 1
+ skipped = 0
+
+ def _load_file(self, bucket_f):
+ for line in bucket_f:
+ words = line.split()
+ typeinfo = None
+ typeinfo_name = ''
+ stacktrace_begin = 2
+ for index, word in enumerate(words):
+ if index < 2:
+ continue
+ if word[0] == 't':
+ typeinfo = int(word[1:], 16)
+ self._typeinfo_addresses.add(typeinfo)
+ elif word[0] == 'n':
+ typeinfo_name = word[1:]
+ else:
+ stacktrace_begin = index
+ break
+ stacktrace = [int(address, 16) for address in words[stacktrace_begin:]]
+ for frame in stacktrace:
+ self._code_addresses.add(frame)
+ self._buckets[int(words[0])] = Bucket(
+ stacktrace, words[1], typeinfo, typeinfo_name)
+
+ def __iter__(self):
+ for bucket_id, bucket_content in self._buckets.iteritems():
+ yield bucket_id, bucket_content
+
+ def __getitem__(self, bucket_id):
+ return self._buckets[bucket_id]
+
+ def get(self, bucket_id):
+ return self._buckets.get(bucket_id)
+
+ def symbolize(self, symbol_mapping_cache):
+ for bucket_content in self._buckets.itervalues():
+ bucket_content.symbolize(symbol_mapping_cache)
+
+ def clear_component_cache(self):
+ for bucket_content in self._buckets.itervalues():
+ bucket_content.clear_component_cache()
+
+ def iter_addresses(self, symbol_type):
+ if symbol_type in [FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS]:
+ for function in self._code_addresses:
+ yield function
+ else:
+ for function in self._typeinfo_addresses:
+ yield function
diff --git a/chromium/tools/deep_memory_profiler/lib/dump.py b/chromium/tools/deep_memory_profiler/lib/dump.py
new file mode 100644
index 00000000000..115979e0f6a
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/dump.py
@@ -0,0 +1,487 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import datetime
+import logging
+import os
+import re
+import time
+
+from lib.bucket import BUCKET_ID
+from lib.exceptions import EmptyDumpException, InvalidDumpException
+from lib.exceptions import ObsoleteDumpVersionException, ParsingException
+from lib.pageframe import PageFrame
+from lib.range_dict import ExclusiveRangeDict
+from lib.symbol import proc_maps
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+# Heap Profile Dump versions
+
+# DUMP_DEEP_[1-4] are obsolete.
+# DUMP_DEEP_2+ distinct mmap regions and malloc chunks.
+# DUMP_DEEP_3+ don't include allocation functions in their stack dumps.
+# DUMP_DEEP_4+ support comments with '#' and global stats "nonprofiled-*".
+# DUMP_DEEP_[1-2] should be processed by POLICY_DEEP_1.
+# DUMP_DEEP_[3-4] should be processed by POLICY_DEEP_2 or POLICY_DEEP_3.
+DUMP_DEEP_1 = 'DUMP_DEEP_1'
+DUMP_DEEP_2 = 'DUMP_DEEP_2'
+DUMP_DEEP_3 = 'DUMP_DEEP_3'
+DUMP_DEEP_4 = 'DUMP_DEEP_4'
+
+DUMP_DEEP_OBSOLETE = (DUMP_DEEP_1, DUMP_DEEP_2, DUMP_DEEP_3, DUMP_DEEP_4)
+
+# DUMP_DEEP_5 doesn't separate sections for malloc and mmap.
+# malloc and mmap are identified in bucket files.
+# DUMP_DEEP_5 should be processed by POLICY_DEEP_4.
+DUMP_DEEP_5 = 'DUMP_DEEP_5'
+
+# DUMP_DEEP_6 adds a mmap list to DUMP_DEEP_5.
+DUMP_DEEP_6 = 'DUMP_DEEP_6'
+
+
+class Dump(object):
+ """Represents a heap profile dump."""
+
+ _PATH_PATTERN = re.compile(r'^(.*)\.([0-9]+)\.([0-9]+)\.heap$')
+
+ _HOOK_PATTERN = re.compile(
+ r'^ ([ \(])([a-f0-9]+)([ \)])-([ \(])([a-f0-9]+)([ \)])\s+'
+ r'(hooked|unhooked)\s+(.+)$', re.IGNORECASE)
+
+ _HOOKED_PATTERN = re.compile(r'(?P<TYPE>.+ )?(?P<COMMITTED>[0-9]+) / '
+ '(?P<RESERVED>[0-9]+) @ (?P<BUCKETID>[0-9]+)')
+ _UNHOOKED_PATTERN = re.compile(r'(?P<TYPE>.+ )?(?P<COMMITTED>[0-9]+) / '
+ '(?P<RESERVED>[0-9]+)')
+
+ _OLD_HOOKED_PATTERN = re.compile(r'(?P<TYPE>.+) @ (?P<BUCKETID>[0-9]+)')
+ _OLD_UNHOOKED_PATTERN = re.compile(r'(?P<TYPE>.+) (?P<COMMITTED>[0-9]+)')
+
+ _TIME_PATTERN_FORMAT = re.compile(
+ r'^Time: ([0-9]+/[0-9]+/[0-9]+ [0-9]+:[0-9]+:[0-9]+)(\.[0-9]+)?')
+ _TIME_PATTERN_SECONDS = re.compile(r'^Time: ([0-9]+)$')
+
+ def __init__(self, path, modified_time):
+ self._path = path
+ matched = self._PATH_PATTERN.match(path)
+ self._pid = int(matched.group(2))
+ self._count = int(matched.group(3))
+ self._time = modified_time
+ self._map = {}
+ self._procmaps = ExclusiveRangeDict(ProcMapsEntryAttribute)
+ self._stacktrace_lines = []
+ self._global_stats = {} # used only in apply_policy
+
+ self._run_id = ''
+ self._pagesize = 4096
+ self._pageframe_length = 0
+ self._pageframe_encoding = ''
+ self._has_pagecount = False
+
+ self._version = ''
+ self._lines = []
+
+ @property
+ def path(self):
+ return self._path
+
+ @property
+ def count(self):
+ return self._count
+
+ @property
+ def time(self):
+ return self._time
+
+ @property
+ def iter_map(self):
+ for region in sorted(self._map.iteritems()):
+ yield region[0], region[1]
+
+ def iter_procmaps(self):
+ for begin, end, attr in self._map.iter_range():
+ yield begin, end, attr
+
+ @property
+ def iter_stacktrace(self):
+ for line in self._stacktrace_lines:
+ yield line
+
+ def global_stat(self, name):
+ return self._global_stats[name]
+
+ @property
+ def run_id(self):
+ return self._run_id
+
+ @property
+ def pagesize(self):
+ return self._pagesize
+
+ @property
+ def pageframe_length(self):
+ return self._pageframe_length
+
+ @property
+ def pageframe_encoding(self):
+ return self._pageframe_encoding
+
+ @property
+ def has_pagecount(self):
+ return self._has_pagecount
+
+ @staticmethod
+ def load(path, log_header='Loading a heap profile dump: '):
+ """Loads a heap profile dump.
+
+ Args:
+ path: A file path string to load.
+ log_header: A preceding string for log messages.
+
+ Returns:
+ A loaded Dump object.
+
+ Raises:
+ ParsingException for invalid heap profile dumps.
+ """
+ dump = Dump(path, os.stat(path).st_mtime)
+ with open(path, 'r') as f:
+ dump.load_file(f, log_header)
+ return dump
+
+ def load_file(self, f, log_header):
+ self._lines = [line for line in f
+ if line and not line.startswith('#')]
+
+ try:
+ self._version, ln = self._parse_version()
+ self._parse_meta_information()
+ if self._version == DUMP_DEEP_6:
+ self._parse_mmap_list()
+ self._parse_global_stats()
+ self._extract_stacktrace_lines(ln)
+ except EmptyDumpException:
+ LOGGER.info('%s%s ...ignored an empty dump.' % (log_header, self._path))
+ except ParsingException, e:
+ LOGGER.error('%s%s ...error %s' % (log_header, self._path, e))
+ raise
+ else:
+ LOGGER.info('%s%s (version:%s)' % (log_header, self._path, self._version))
+
+ def _parse_version(self):
+ """Parses a version string in self._lines.
+
+ Returns:
+ A pair of (a string representing a version of the stacktrace dump,
+ and an integer indicating a line number next to the version string).
+
+ Raises:
+ ParsingException for invalid dump versions.
+ """
+ version = ''
+
+ # Skip until an identifiable line.
+ headers = ('STACKTRACES:\n', 'MMAP_STACKTRACES:\n', 'heap profile: ')
+ if not self._lines:
+ raise EmptyDumpException('Empty heap dump file.')
+ (ln, found) = skip_while(
+ 0, len(self._lines),
+ lambda n: not self._lines[n].startswith(headers))
+ if not found:
+ raise InvalidDumpException('No version header.')
+
+ # Identify a version.
+ if self._lines[ln].startswith('heap profile: '):
+ version = self._lines[ln][13:].strip()
+ if version in (DUMP_DEEP_5, DUMP_DEEP_6):
+ (ln, _) = skip_while(
+ ln, len(self._lines),
+ lambda n: self._lines[n] != 'STACKTRACES:\n')
+ elif version in DUMP_DEEP_OBSOLETE:
+ raise ObsoleteDumpVersionException(version)
+ else:
+ raise InvalidDumpException('Invalid version: %s' % version)
+ elif self._lines[ln] == 'STACKTRACES:\n':
+ raise ObsoleteDumpVersionException(DUMP_DEEP_1)
+ elif self._lines[ln] == 'MMAP_STACKTRACES:\n':
+ raise ObsoleteDumpVersionException(DUMP_DEEP_2)
+
+ return (version, ln)
+
+ def _parse_global_stats(self):
+ """Parses lines in self._lines as global stats."""
+ (ln, _) = skip_while(
+ 0, len(self._lines),
+ lambda n: self._lines[n] != 'GLOBAL_STATS:\n')
+
+ global_stat_names = [
+ 'total', 'absent', 'file-exec', 'file-nonexec', 'anonymous', 'stack',
+ 'other', 'nonprofiled-absent', 'nonprofiled-anonymous',
+ 'nonprofiled-file-exec', 'nonprofiled-file-nonexec',
+ 'nonprofiled-stack', 'nonprofiled-other',
+ 'profiled-mmap', 'profiled-malloc']
+
+ for prefix in global_stat_names:
+ (ln, _) = skip_while(
+ ln, len(self._lines),
+ lambda n: self._lines[n].split()[0] != prefix)
+ words = self._lines[ln].split()
+ self._global_stats[prefix + '_virtual'] = int(words[-2])
+ self._global_stats[prefix + '_committed'] = int(words[-1])
+
+ def _parse_meta_information(self):
+ """Parses lines in self._lines for meta information."""
+ (ln, found) = skip_while(
+ 0, len(self._lines),
+ lambda n: self._lines[n] != 'META:\n')
+ if not found:
+ return
+ ln += 1
+
+ while True:
+ if self._lines[ln].startswith('Time:'):
+ matched_seconds = self._TIME_PATTERN_SECONDS.match(self._lines[ln])
+ matched_format = self._TIME_PATTERN_FORMAT.match(self._lines[ln])
+ if matched_format:
+ self._time = time.mktime(datetime.datetime.strptime(
+ matched_format.group(1), '%Y/%m/%d %H:%M:%S').timetuple())
+ if matched_format.group(2):
+ self._time += float(matched_format.group(2)[1:]) / 1000.0
+ elif matched_seconds:
+ self._time = float(matched_seconds.group(1))
+ elif self._lines[ln].startswith('Reason:'):
+ pass # Nothing to do for 'Reason:'
+ elif self._lines[ln].startswith('PageSize: '):
+ self._pagesize = int(self._lines[ln][10:])
+ elif self._lines[ln].startswith('CommandLine:'):
+ pass
+ elif (self._lines[ln].startswith('PageFrame: ') or
+ self._lines[ln].startswith('PFN: ')):
+ if self._lines[ln].startswith('PageFrame: '):
+ words = self._lines[ln][11:].split(',')
+ else:
+ words = self._lines[ln][5:].split(',')
+ for word in words:
+ if word == '24':
+ self._pageframe_length = 24
+ elif word == 'Base64':
+ self._pageframe_encoding = 'base64'
+ elif word == 'PageCount':
+ self._has_pagecount = True
+ elif self._lines[ln].startswith('RunID: '):
+ self._run_id = self._lines[ln][7:].strip()
+ elif (self._lines[ln].startswith('MMAP_LIST:') or
+ self._lines[ln].startswith('GLOBAL_STATS:')):
+ # Skip until "MMAP_LIST:" or "GLOBAL_STATS" is found.
+ break
+ else:
+ pass
+ ln += 1
+
+ def _parse_mmap_list(self):
+ """Parses lines in self._lines as a mmap list."""
+ (ln, found) = skip_while(
+ 0, len(self._lines),
+ lambda n: self._lines[n] != 'MMAP_LIST:\n')
+ if not found:
+ return {}
+
+ ln += 1
+ self._map = {}
+ current_vma = {}
+ pageframe_list = []
+ while True:
+ entry = proc_maps.ProcMaps.parse_line(self._lines[ln])
+ if entry:
+ current_vma = {}
+ for _, _, attr in self._procmaps.iter_range(entry.begin, entry.end):
+ for key, value in entry.as_dict().iteritems():
+ attr[key] = value
+ current_vma[key] = value
+ ln += 1
+ continue
+
+ if self._lines[ln].startswith(' PF: '):
+ for pageframe in self._lines[ln][5:].split():
+ pageframe_list.append(PageFrame.parse(pageframe, self._pagesize))
+ ln += 1
+ continue
+
+ matched = self._HOOK_PATTERN.match(self._lines[ln])
+ if not matched:
+ break
+ # 2: starting address
+ # 5: end address
+ # 7: hooked or unhooked
+ # 8: additional information
+ if matched.group(7) == 'hooked':
+ submatched = self._HOOKED_PATTERN.match(matched.group(8))
+ if not submatched:
+ submatched = self._OLD_HOOKED_PATTERN.match(matched.group(8))
+ elif matched.group(7) == 'unhooked':
+ submatched = self._UNHOOKED_PATTERN.match(matched.group(8))
+ if not submatched:
+ submatched = self._OLD_UNHOOKED_PATTERN.match(matched.group(8))
+ else:
+ assert matched.group(7) in ['hooked', 'unhooked']
+
+ submatched_dict = submatched.groupdict()
+ region_info = { 'vma': current_vma }
+ if submatched_dict.get('TYPE'):
+ region_info['type'] = submatched_dict['TYPE'].strip()
+ if submatched_dict.get('COMMITTED'):
+ region_info['committed'] = int(submatched_dict['COMMITTED'])
+ if submatched_dict.get('RESERVED'):
+ region_info['reserved'] = int(submatched_dict['RESERVED'])
+ if submatched_dict.get('BUCKETID'):
+ region_info['bucket_id'] = int(submatched_dict['BUCKETID'])
+
+ if matched.group(1) == '(':
+ start = current_vma['begin']
+ else:
+ start = int(matched.group(2), 16)
+ if matched.group(4) == '(':
+ end = current_vma['end']
+ else:
+ end = int(matched.group(5), 16)
+
+ if pageframe_list and pageframe_list[0].start_truncated:
+ pageframe_list[0].set_size(
+ pageframe_list[0].size - start % self._pagesize)
+ if pageframe_list and pageframe_list[-1].end_truncated:
+ pageframe_list[-1].set_size(
+ pageframe_list[-1].size - (self._pagesize - end % self._pagesize))
+ region_info['pageframe'] = pageframe_list
+ pageframe_list = []
+
+ self._map[(start, end)] = (matched.group(7), region_info)
+ ln += 1
+
+ def _extract_stacktrace_lines(self, line_number):
+ """Extracts the position of stacktrace lines.
+
+ Valid stacktrace lines are stored into self._stacktrace_lines.
+
+ Args:
+ line_number: A line number to start parsing in lines.
+
+ Raises:
+ ParsingException for invalid dump versions.
+ """
+ if self._version in (DUMP_DEEP_5, DUMP_DEEP_6):
+ (line_number, _) = skip_while(
+ line_number, len(self._lines),
+ lambda n: not self._lines[n].split()[0].isdigit())
+ stacktrace_start = line_number
+ (line_number, _) = skip_while(
+ line_number, len(self._lines),
+ lambda n: self._check_stacktrace_line(self._lines[n]))
+ self._stacktrace_lines = self._lines[stacktrace_start:line_number]
+
+ elif self._version in DUMP_DEEP_OBSOLETE:
+ raise ObsoleteDumpVersionException(self._version)
+
+ else:
+ raise InvalidDumpException('Invalid version: %s' % self._version)
+
+ @staticmethod
+ def _check_stacktrace_line(stacktrace_line):
+ """Checks if a given stacktrace_line is valid as stacktrace.
+
+ Args:
+ stacktrace_line: A string to be checked.
+
+ Returns:
+ True if the given stacktrace_line is valid.
+ """
+ words = stacktrace_line.split()
+ if len(words) < BUCKET_ID + 1:
+ return False
+ if words[BUCKET_ID - 1] != '@':
+ return False
+ return True
+
+
+class DumpList(object):
+ """Represents a sequence of heap profile dumps."""
+
+ def __init__(self, dump_list):
+ self._dump_list = dump_list
+
+ @staticmethod
+ def load(path_list):
+ LOGGER.info('Loading heap dump profiles.')
+ dump_list = []
+ for path in path_list:
+ dump_list.append(Dump.load(path, ' '))
+ return DumpList(dump_list)
+
+ def __len__(self):
+ return len(self._dump_list)
+
+ def __iter__(self):
+ for dump in self._dump_list:
+ yield dump
+
+ def __getitem__(self, index):
+ return self._dump_list[index]
+
+
+class ProcMapsEntryAttribute(ExclusiveRangeDict.RangeAttribute):
+ """Represents an entry of /proc/maps in range_dict.ExclusiveRangeDict."""
+ _DUMMY_ENTRY = proc_maps.ProcMapsEntry(
+ 0, # begin
+ 0, # end
+ '-', # readable
+ '-', # writable
+ '-', # executable
+ '-', # private
+ 0, # offset
+ '00', # major
+ '00', # minor
+ 0, # inode
+ '' # name
+ )
+
+ def __init__(self):
+ super(ProcMapsEntryAttribute, self).__init__()
+ self._entry = self._DUMMY_ENTRY.as_dict()
+
+ def __str__(self):
+ return str(self._entry)
+
+ def __repr__(self):
+ return 'ProcMapsEntryAttribute' + str(self._entry)
+
+ def __getitem__(self, key):
+ return self._entry[key]
+
+ def __setitem__(self, key, value):
+ if key not in self._entry:
+ raise KeyError(key)
+ self._entry[key] = value
+
+ def copy(self):
+ new_entry = ProcMapsEntryAttribute()
+ for key, value in self._entry.iteritems():
+ new_entry[key] = copy.deepcopy(value)
+ return new_entry
+
+
+def skip_while(index, max_index, skipping_condition):
+ """Increments |index| until |skipping_condition|(|index|) is False.
+
+ Returns:
+ A pair of an integer indicating a line number after skipped, and a
+ boolean value which is True if found a line which skipping_condition
+ is False for.
+ """
+ while skipping_condition(index):
+ index += 1
+ if index >= max_index:
+ return index, False
+ return index, True
diff --git a/chromium/tools/deep_memory_profiler/lib/exceptions.py b/chromium/tools/deep_memory_profiler/lib/exceptions.py
new file mode 100644
index 00000000000..2c68af72cc2
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/exceptions.py
@@ -0,0 +1,22 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class EmptyDumpException(Exception):
+ def __str__(self):
+ return repr(self.args[0])
+
+
+class ParsingException(Exception):
+ def __str__(self):
+ return repr(self.args[0])
+
+
+class InvalidDumpException(ParsingException):
+ def __str__(self):
+ return "invalid heap profile dump: %s" % repr(self.args[0])
+
+
+class ObsoleteDumpVersionException(ParsingException):
+ def __str__(self):
+ return "obsolete heap profile dump version: %s" % repr(self.args[0])
diff --git a/chromium/tools/deep_memory_profiler/lib/ordered_dict.py b/chromium/tools/deep_memory_profiler/lib/ordered_dict.py
new file mode 100644
index 00000000000..f7d053bd349
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/ordered_dict.py
@@ -0,0 +1,19 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(dmikurube): Remove this file once Python 2.7 is required.
+
+import os
+import sys
+
+try:
+ from collections import OrderedDict # pylint: disable=E0611,W0611
+except ImportError:
+ _BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ _SIMPLEJSON_PATH = os.path.join(_BASE_PATH,
+ os.pardir,
+ os.pardir,
+ 'third_party')
+ sys.path.insert(0, _SIMPLEJSON_PATH)
+ from simplejson import OrderedDict # pylint: disable=W0611
diff --git a/chromium/tools/deep_memory_profiler/lib/pageframe.py b/chromium/tools/deep_memory_profiler/lib/pageframe.py
new file mode 100644
index 00000000000..8722243baf6
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/pageframe.py
@@ -0,0 +1,163 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import re
+import struct
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class PageFrame(object):
+ """Represents a pageframe and maybe its shared count."""
+ def __init__(self, pfn, size, pagecount, start_truncated, end_truncated):
+ self._pfn = pfn
+ self._size = size
+ self._pagecount = pagecount
+ self._start_truncated = start_truncated
+ self._end_truncated = end_truncated
+
+ def __str__(self):
+ result = str()
+ if self._start_truncated:
+ result += '<'
+ result += '%06x#%d' % (self._pfn, self._pagecount)
+ if self._end_truncated:
+ result += '>'
+ return result
+
+ def __repr__(self):
+ return str(self)
+
+ @staticmethod
+ def parse(encoded_pfn, size):
+ start = 0
+ end = len(encoded_pfn)
+ end_truncated = False
+ if encoded_pfn.endswith('>'):
+ end = len(encoded_pfn) - 1
+ end_truncated = True
+ pagecount_found = encoded_pfn.find('#')
+ pagecount = None
+ if pagecount_found >= 0:
+ encoded_pagecount = 'AAA' + encoded_pfn[pagecount_found+1 : end]
+ pagecount = struct.unpack(
+ '>I', '\x00' + encoded_pagecount.decode('base64'))[0]
+ end = pagecount_found
+ start_truncated = False
+ if encoded_pfn.startswith('<'):
+ start = 1
+ start_truncated = True
+
+ pfn = struct.unpack(
+ '>I', '\x00' + (encoded_pfn[start:end]).decode('base64'))[0]
+
+ return PageFrame(pfn, size, pagecount, start_truncated, end_truncated)
+
+ @property
+ def pfn(self):
+ return self._pfn
+
+ @property
+ def size(self):
+ return self._size
+
+ def set_size(self, size):
+ self._size = size
+
+ @property
+ def pagecount(self):
+ return self._pagecount
+
+ @property
+ def start_truncated(self):
+ return self._start_truncated
+
+ @property
+ def end_truncated(self):
+ return self._end_truncated
+
+
+class PFNCounts(object):
+ """Represents counts of PFNs in a process."""
+
+ _PATH_PATTERN = re.compile(r'^(.*)\.([0-9]+)\.([0-9]+)\.heap$')
+
+ def __init__(self, path, modified_time):
+ matched = self._PATH_PATTERN.match(path)
+ if matched:
+ self._pid = int(matched.group(2))
+ else:
+ self._pid = 0
+ self._command_line = ''
+ self._pagesize = 4096
+ self._path = path
+ self._pfn_meta = ''
+ self._pfnset = {}
+ self._reason = ''
+ self._time = modified_time
+
+ @staticmethod
+ def load(path, log_header='Loading PFNs from a heap profile dump: '):
+ pfnset = PFNCounts(path, float(os.stat(path).st_mtime))
+ LOGGER.info('%s%s' % (log_header, path))
+
+ with open(path, 'r') as pfnset_f:
+ pfnset.load_file(pfnset_f)
+
+ return pfnset
+
+ @property
+ def path(self):
+ return self._path
+
+ @property
+ def pid(self):
+ return self._pid
+
+ @property
+ def time(self):
+ return self._time
+
+ @property
+ def reason(self):
+ return self._reason
+
+ @property
+ def iter_pfn(self):
+ for pfn, count in self._pfnset.iteritems():
+ yield pfn, count
+
+ def load_file(self, pfnset_f):
+ prev_pfn_end_truncated = None
+ for line in pfnset_f:
+ line = line.strip()
+ if line.startswith('GLOBAL_STATS:') or line.startswith('STACKTRACES:'):
+ break
+ elif line.startswith('PF: '):
+ for encoded_pfn in line[3:].split():
+ page_frame = PageFrame.parse(encoded_pfn, self._pagesize)
+ if page_frame.start_truncated and (
+ not prev_pfn_end_truncated or
+ prev_pfn_end_truncated != page_frame.pfn):
+ LOGGER.error('Broken page frame number: %s.' % encoded_pfn)
+ self._pfnset[page_frame.pfn] = self._pfnset.get(page_frame.pfn, 0) + 1
+ if page_frame.end_truncated:
+ prev_pfn_end_truncated = page_frame.pfn
+ else:
+ prev_pfn_end_truncated = None
+ elif line.startswith('PageSize: '):
+ self._pagesize = int(line[10:])
+ elif line.startswith('PFN: '):
+ self._pfn_meta = line[5:]
+ elif line.startswith('PageFrame: '):
+ self._pfn_meta = line[11:]
+ elif line.startswith('Time: '):
+ self._time = float(line[6:])
+ elif line.startswith('CommandLine: '):
+ self._command_line = line[13:]
+ elif line.startswith('Reason: '):
+ self._reason = line[8:]
diff --git a/chromium/tools/deep_memory_profiler/lib/policy.py b/chromium/tools/deep_memory_profiler/lib/policy.py
new file mode 100644
index 00000000000..d7a38977eb7
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/policy.py
@@ -0,0 +1,404 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import logging
+import os
+import re
+
+
+LOGGER = logging.getLogger('dmprof')
+
+BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+POLICIES_JSON_PATH = os.path.join(BASE_PATH, 'policies.json')
+
+# Heap Profile Policy versions
+
+# POLICY_DEEP_1 DOES NOT include allocation_type columns.
+# mmap regions are distincted w/ mmap frames in the pattern column.
+POLICY_DEEP_1 = 'POLICY_DEEP_1'
+
+# POLICY_DEEP_2 DOES include allocation_type columns.
+# mmap regions are distincted w/ the allocation_type column.
+POLICY_DEEP_2 = 'POLICY_DEEP_2'
+
+# POLICY_DEEP_3 is in JSON format.
+POLICY_DEEP_3 = 'POLICY_DEEP_3'
+
+# POLICY_DEEP_3 contains typeinfo.
+POLICY_DEEP_4 = 'POLICY_DEEP_4'
+
+
+class Rule(object):
+ """Represents one matching rule in a policy file."""
+
+ def __init__(self,
+ name,
+ allocator_type,
+ stackfunction_pattern=None,
+ stacksourcefile_pattern=None,
+ typeinfo_pattern=None,
+ mappedpathname_pattern=None,
+ mappedpermission_pattern=None,
+ sharedwith=None):
+ self._name = name
+ self._allocator_type = allocator_type
+
+ self._stackfunction_pattern = None
+ if stackfunction_pattern:
+ self._stackfunction_pattern = re.compile(
+ stackfunction_pattern + r'\Z')
+
+ self._stacksourcefile_pattern = None
+ if stacksourcefile_pattern:
+ self._stacksourcefile_pattern = re.compile(
+ stacksourcefile_pattern + r'\Z')
+
+ self._typeinfo_pattern = None
+ if typeinfo_pattern:
+ self._typeinfo_pattern = re.compile(typeinfo_pattern + r'\Z')
+
+ self._mappedpathname_pattern = None
+ if mappedpathname_pattern:
+ self._mappedpathname_pattern = re.compile(mappedpathname_pattern + r'\Z')
+
+ self._mappedpermission_pattern = None
+ if mappedpermission_pattern:
+ self._mappedpermission_pattern = re.compile(
+ mappedpermission_pattern + r'\Z')
+
+ self._sharedwith = []
+ if sharedwith:
+ self._sharedwith = sharedwith
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def allocator_type(self):
+ return self._allocator_type
+
+ @property
+ def stackfunction_pattern(self):
+ return self._stackfunction_pattern
+
+ @property
+ def stacksourcefile_pattern(self):
+ return self._stacksourcefile_pattern
+
+ @property
+ def typeinfo_pattern(self):
+ return self._typeinfo_pattern
+
+ @property
+ def mappedpathname_pattern(self):
+ return self._mappedpathname_pattern
+
+ @property
+ def mappedpermission_pattern(self):
+ return self._mappedpermission_pattern
+
+ @property
+ def sharedwith(self):
+ return self._sharedwith
+
+
+class Policy(object):
+ """Represents a policy, a content of a policy file."""
+
+ def __init__(self, rules, version, components):
+ self._rules = rules
+ self._version = version
+ self._components = components
+
+ @property
+ def rules(self):
+ return self._rules
+
+ @property
+ def version(self):
+ return self._version
+
+ @property
+ def components(self):
+ return self._components
+
+ def find_rule(self, component_name):
+ """Finds a rule whose name is |component_name|. """
+ for rule in self._rules:
+ if rule.name == component_name:
+ return rule
+ return None
+
+ def find_malloc(self, bucket):
+ """Finds a matching component name which a given |bucket| belongs to.
+
+ Args:
+ bucket: A Bucket object to be searched for.
+
+ Returns:
+ A string representing a component name.
+ """
+ assert not bucket or bucket.allocator_type == 'malloc'
+
+ if not bucket:
+ return 'no-bucket'
+ if bucket.component_cache:
+ return bucket.component_cache
+
+ stackfunction = bucket.symbolized_joined_stackfunction
+ stacksourcefile = bucket.symbolized_joined_stacksourcefile
+ typeinfo = bucket.symbolized_typeinfo
+ if typeinfo.startswith('0x'):
+ typeinfo = bucket.typeinfo_name
+
+ for rule in self._rules:
+ if (rule.allocator_type == 'malloc' and
+ (not rule.stackfunction_pattern or
+ rule.stackfunction_pattern.match(stackfunction)) and
+ (not rule.stacksourcefile_pattern or
+ rule.stacksourcefile_pattern.match(stacksourcefile)) and
+ (not rule.typeinfo_pattern or rule.typeinfo_pattern.match(typeinfo))):
+ bucket.component_cache = rule.name
+ return rule.name
+
+ assert False
+
+ def find_mmap(self, region, bucket_set,
+ pageframe=None, group_pfn_counts=None):
+ """Finds a matching component which a given mmap |region| belongs to.
+
+ It uses |bucket_set| to match with backtraces. If |pageframe| is given,
+ it considers memory sharing among processes.
+
+ NOTE: Don't use Bucket's |component_cache| for mmap regions because they're
+ classified not only with bucket information (mappedpathname for example).
+
+ Args:
+ region: A tuple representing a memory region.
+ bucket_set: A BucketSet object to look up backtraces.
+ pageframe: A PageFrame object representing a pageframe maybe including
+ a pagecount.
+ group_pfn_counts: A dict mapping a PFN to the number of times the
+ the pageframe is mapped by the known "group (Chrome)" processes.
+
+ Returns:
+ A string representing a component name.
+ """
+ assert region[0] == 'hooked'
+ bucket = bucket_set.get(region[1]['bucket_id'])
+ assert not bucket or bucket.allocator_type == 'mmap'
+
+ if not bucket:
+ return 'no-bucket', None
+
+ stackfunction = bucket.symbolized_joined_stackfunction
+ stacksourcefile = bucket.symbolized_joined_stacksourcefile
+ sharedwith = self._categorize_pageframe(pageframe, group_pfn_counts)
+
+ for rule in self._rules:
+ if (rule.allocator_type == 'mmap' and
+ (not rule.stackfunction_pattern or
+ rule.stackfunction_pattern.match(stackfunction)) and
+ (not rule.stacksourcefile_pattern or
+ rule.stacksourcefile_pattern.match(stacksourcefile)) and
+ (not rule.mappedpathname_pattern or
+ rule.mappedpathname_pattern.match(region[1]['vma']['name'])) and
+ (not rule.mappedpermission_pattern or
+ rule.mappedpermission_pattern.match(
+ region[1]['vma']['readable'] +
+ region[1]['vma']['writable'] +
+ region[1]['vma']['executable'] +
+ region[1]['vma']['private'])) and
+ (not rule.sharedwith or
+ not pageframe or sharedwith in rule.sharedwith)):
+ return rule.name, bucket
+
+ assert False
+
+ def find_unhooked(self, region, pageframe=None, group_pfn_counts=None):
+ """Finds a matching component which a given unhooked |region| belongs to.
+
+ If |pageframe| is given, it considers memory sharing among processes.
+
+ Args:
+ region: A tuple representing a memory region.
+ pageframe: A PageFrame object representing a pageframe maybe including
+ a pagecount.
+ group_pfn_counts: A dict mapping a PFN to the number of times the
+ the pageframe is mapped by the known "group (Chrome)" processes.
+
+ Returns:
+ A string representing a component name.
+ """
+ assert region[0] == 'unhooked'
+ sharedwith = self._categorize_pageframe(pageframe, group_pfn_counts)
+
+ for rule in self._rules:
+ if (rule.allocator_type == 'unhooked' and
+ (not rule.mappedpathname_pattern or
+ rule.mappedpathname_pattern.match(region[1]['vma']['name'])) and
+ (not rule.mappedpermission_pattern or
+ rule.mappedpermission_pattern.match(
+ region[1]['vma']['readable'] +
+ region[1]['vma']['writable'] +
+ region[1]['vma']['executable'] +
+ region[1]['vma']['private'])) and
+ (not rule.sharedwith or
+ not pageframe or sharedwith in rule.sharedwith)):
+ return rule.name
+
+ assert False
+
+ @staticmethod
+ def load(filename, filetype):
+ """Loads a policy file of |filename| in a |format|.
+
+ Args:
+ filename: A filename to be loaded.
+ filetype: A string to specify a type of the file. Only 'json' is
+ supported for now.
+
+ Returns:
+ A loaded Policy object.
+ """
+ with open(os.path.join(BASE_PATH, filename)) as policy_f:
+ return Policy.parse(policy_f, filetype)
+
+ @staticmethod
+ def parse(policy_f, filetype):
+ """Parses a policy file content in a |format|.
+
+ Args:
+ policy_f: An IO object to be loaded.
+ filetype: A string to specify a type of the file. Only 'json' is
+ supported for now.
+
+ Returns:
+ A loaded Policy object.
+ """
+ if filetype == 'json':
+ return Policy._parse_json(policy_f)
+ else:
+ return None
+
+ @staticmethod
+ def _parse_json(policy_f):
+ """Parses policy file in json format.
+
+ A policy file contains component's names and their stacktrace pattern
+ written in regular expression. Those patterns are matched against each
+ symbols of each stacktraces in the order written in the policy file
+
+ Args:
+ policy_f: A File/IO object to read.
+
+ Returns:
+ A loaded policy object.
+ """
+ policy = json.load(policy_f)
+
+ rules = []
+ for rule in policy['rules']:
+ stackfunction = rule.get('stackfunction') or rule.get('stacktrace')
+ stacksourcefile = rule.get('stacksourcefile')
+ rules.append(Rule(
+ rule['name'],
+ rule['allocator'], # allocator_type
+ stackfunction,
+ stacksourcefile,
+ rule['typeinfo'] if 'typeinfo' in rule else None,
+ rule.get('mappedpathname'),
+ rule.get('mappedpermission'),
+ rule.get('sharedwith')))
+
+ return Policy(rules, policy['version'], policy['components'])
+
+ @staticmethod
+ def _categorize_pageframe(pageframe, group_pfn_counts):
+ """Categorizes a pageframe based on its sharing status.
+
+ Returns:
+ 'private' if |pageframe| is not shared with other processes. 'group'
+ if |pageframe| is shared only with group (Chrome-related) processes.
+ 'others' if |pageframe| is shared with non-group processes.
+ """
+ if not pageframe:
+ return 'private'
+
+ if pageframe.pagecount:
+ if pageframe.pagecount == 1:
+ return 'private'
+ elif pageframe.pagecount <= group_pfn_counts.get(pageframe.pfn, 0) + 1:
+ return 'group'
+ else:
+ return 'others'
+ else:
+ if pageframe.pfn in group_pfn_counts:
+ return 'group'
+ else:
+ return 'private'
+
+
+class PolicySet(object):
+ """Represents a set of policies."""
+
+ def __init__(self, policy_directory):
+ self._policy_directory = policy_directory
+
+ @staticmethod
+ def load(labels=None):
+ """Loads a set of policies via the "default policy directory".
+
+ The "default policy directory" contains pairs of policies and their labels.
+ For example, a policy "policy.l0.json" is labeled "l0" in the default
+ policy directory "policies.json".
+
+ All policies in the directory are loaded by default. Policies can be
+ limited by |labels|.
+
+ Args:
+ labels: An array that contains policy labels to be loaded.
+
+ Returns:
+ A PolicySet object.
+ """
+ default_policy_directory = PolicySet._load_default_policy_directory()
+ if labels:
+ specified_policy_directory = {}
+ for label in labels:
+ if label in default_policy_directory:
+ specified_policy_directory[label] = default_policy_directory[label]
+ # TODO(dmikurube): Load an un-labeled policy file.
+ return PolicySet._load_policies(specified_policy_directory)
+ else:
+ return PolicySet._load_policies(default_policy_directory)
+
+ def __len__(self):
+ return len(self._policy_directory)
+
+ def __iter__(self):
+ for label in self._policy_directory:
+ yield label
+
+ def __getitem__(self, label):
+ return self._policy_directory[label]
+
+ @staticmethod
+ def _load_default_policy_directory():
+ with open(POLICIES_JSON_PATH, mode='r') as policies_f:
+ default_policy_directory = json.load(policies_f)
+ return default_policy_directory
+
+ @staticmethod
+ def _load_policies(directory):
+ LOGGER.info('Loading policy files.')
+ policies = {}
+ for label in directory:
+ LOGGER.info(' %s: %s' % (label, directory[label]['file']))
+ loaded = Policy.load(directory[label]['file'], directory[label]['format'])
+ if loaded:
+ policies[label] = loaded
+ return PolicySet(policies)
diff --git a/chromium/tools/deep_memory_profiler/lib/range_dict.py b/chromium/tools/deep_memory_profiler/lib/range_dict.py
new file mode 100644
index 00000000000..565789d561a
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/range_dict.py
@@ -0,0 +1,144 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+_BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+_BINTREES_PATH = os.path.join(
+ _BASE_PATH, os.pardir, os.pardir, 'third_party', 'bintrees')
+sys.path.insert(0, _BINTREES_PATH)
+
+from bintrees import FastRBTree # pylint: disable=F0401
+
+
+class ExclusiveRangeDict(object):
+ """A class like dict whose key is a range [begin, end) of integers.
+
+ It has an attribute for each range of integers, for example:
+ [10, 20) => Attribute(0),
+ [20, 40) => Attribute(1),
+ [40, 50) => Attribute(2),
+ ...
+
+ An instance of this class is accessed only via iter_range(begin, end).
+ The instance is accessed as follows:
+
+ 1) If the given range [begin, end) is not covered by the instance,
+ the range is newly created and iterated.
+
+ 2) If the given range [begin, end) exactly covers ranges in the instance,
+ the ranges are iterated.
+ (See test_set() in tests/range_dict_tests.py.)
+
+ 3) If the given range [begin, end) starts at and/or ends at a mid-point of
+ an existing range, the existing range is split by the given range, and
+ ranges in the given range are iterated. For example, consider a case that
+ [25, 45) is given to an instance of [20, 30), [30, 40), [40, 50). In this
+ case, [20, 30) is split into [20, 25) and [25, 30), and [40, 50) into
+ [40, 45) and [45, 50). Then, [25, 30), [30, 40), [40, 45) are iterated.
+ (See test_split() in tests/range_dict_tests.py.)
+
+ 4) If the given range [begin, end) includes non-existing ranges in an
+ instance, the gaps are filled with new ranges, and all ranges are iterated.
+ For example, consider a case that [25, 50) is given to an instance of
+ [30, 35) and [40, 45). In this case, [25, 30), [35, 40) and [45, 50) are
+ created in the instance, and then [25, 30), [30, 35), [35, 40), [40, 45)
+ and [45, 50) are iterated.
+ (See test_fill() in tests/range_dict_tests.py.)
+ """
+ class RangeAttribute(object):
+ def __init__(self):
+ pass
+
+ def __str__(self):
+ return '<RangeAttribute>'
+
+ def __repr__(self):
+ return '<RangeAttribute>'
+
+ def copy(self): # pylint: disable=R0201
+ return ExclusiveRangeDict.RangeAttribute()
+
+ def __init__(self, attr=RangeAttribute):
+ self._tree = FastRBTree()
+ self._attr = attr
+
+ def iter_range(self, begin=None, end=None):
+ if not begin:
+ begin = self._tree.min_key()
+ if not end:
+ end = self._tree.max_item()[1][0]
+
+ # Assume that self._tree has at least one element.
+ if self._tree.is_empty():
+ self._tree[begin] = (end, self._attr())
+
+ # Create a beginning range (border)
+ try:
+ bound_begin, bound_value = self._tree.floor_item(begin)
+ bound_end = bound_value[0]
+ if begin >= bound_end:
+ # Create a blank range.
+ try:
+ new_end, _ = self._tree.succ_item(bound_begin)
+ except KeyError:
+ new_end = end
+ self._tree[begin] = (min(end, new_end), self._attr())
+ elif bound_begin < begin and begin < bound_end:
+ # Split the existing range.
+ new_end = bound_value[0]
+ new_value = bound_value[1]
+ self._tree[bound_begin] = (begin, new_value.copy())
+ self._tree[begin] = (new_end, new_value.copy())
+ else: # bound_begin == begin
+ # Do nothing (just saying it clearly since this part is confusing)
+ pass
+ except KeyError: # begin is less than the smallest element.
+ # Create a blank range.
+ # Note that we can assume self._tree has at least one element.
+ self._tree[begin] = (min(end, self._tree.min_key()), self._attr())
+
+ # Create an ending range (border)
+ try:
+ bound_begin, bound_value = self._tree.floor_item(end)
+ bound_end = bound_value[0]
+ if end > bound_end:
+ # Create a blank range.
+ new_begin = bound_end
+ self._tree[new_begin] = (end, self._attr())
+ elif bound_begin < end and end < bound_end:
+ # Split the existing range.
+ new_end = bound_value[0]
+ new_value = bound_value[1]
+ self._tree[bound_begin] = (end, new_value.copy())
+ self._tree[end] = (new_end, new_value.copy())
+ else: # bound_begin == begin
+ # Do nothing (just saying it clearly since this part is confusing)
+ pass
+ except KeyError: # end is less than the smallest element.
+ # It must not happen. A blank range [begin,end) has already been created
+ # even if [begin,end) is less than the smallest range.
+ # Do nothing (just saying it clearly since this part is confusing)
+ raise
+
+ missing_ranges = []
+
+ prev_end = None
+ for range_begin, range_value in self._tree.itemslice(begin, end):
+ range_end = range_value[0]
+ # Note that we can assume that we have a range beginning with |begin|
+ # and a range ending with |end| (they may be the same range).
+ if prev_end and prev_end != range_begin:
+ missing_ranges.append((prev_end, range_begin))
+ prev_end = range_end
+
+ for missing_begin, missing_end in missing_ranges:
+ self._tree[missing_begin] = (missing_end, self._attr())
+
+ for range_begin, range_value in self._tree.itemslice(begin, end):
+ yield range_begin, range_value[0], range_value[1]
+
+ def __str__(self):
+ return str(self._tree)
diff --git a/chromium/tools/deep_memory_profiler/lib/sorter.py b/chromium/tools/deep_memory_profiler/lib/sorter.py
new file mode 100644
index 00000000000..64e0851e17c
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/sorter.py
@@ -0,0 +1,470 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import cStringIO
+import json
+import logging
+import os
+import re
+
+
+LOGGER = logging.getLogger('dmprof')
+
+BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+DEFAULT_SORTERS = [
+ os.path.join(BASE_PATH, 'sorter.malloc-component.json'),
+ os.path.join(BASE_PATH, 'sorter.malloc-type.json'),
+ os.path.join(BASE_PATH, 'sorter.vm-map.json'),
+ os.path.join(BASE_PATH, 'sorter.vm-sharing.json'),
+ ]
+
+DEFAULT_TEMPLATES = os.path.join(BASE_PATH, 'templates.json')
+
+
+class Unit(object):
+ """Represents a minimum unit of memory usage categorization.
+
+ It is supposed to be inherited for some different spaces like the entire
+ virtual memory and malloc arena. Such different spaces are called "worlds"
+ in dmprof. (For example, the "vm" world and the "malloc" world.)
+ """
+ def __init__(self, unit_id, size):
+ self._unit_id = unit_id
+ self._size = size
+
+ @property
+ def unit_id(self):
+ return self._unit_id
+
+ @property
+ def size(self):
+ return self._size
+
+
+class VMUnit(Unit):
+ """Represents a Unit for a memory region on virtual memory."""
+ def __init__(self, unit_id, committed, reserved, mmap, region,
+ pageframe=None, group_pfn_counts=None):
+ super(VMUnit, self).__init__(unit_id, committed)
+ self._reserved = reserved
+ self._mmap = mmap
+ self._region = region
+ self._pageframe = pageframe
+ self._group_pfn_counts = group_pfn_counts
+
+ @property
+ def committed(self):
+ return self._size
+
+ @property
+ def reserved(self):
+ return self._reserved
+
+ @property
+ def mmap(self):
+ return self._mmap
+
+ @property
+ def region(self):
+ return self._region
+
+ @property
+ def pageframe(self):
+ return self._pageframe
+
+ @property
+ def group_pfn_counts(self):
+ return self._group_pfn_counts
+
+
+class MMapUnit(VMUnit):
+ """Represents a Unit for a mmap'ed region."""
+ def __init__(self, unit_id, committed, reserved, region, bucket_set,
+ pageframe=None, group_pfn_counts=None):
+ super(MMapUnit, self).__init__(unit_id, committed, reserved, True,
+ region, pageframe, group_pfn_counts)
+ self._bucket_set = bucket_set
+
+ def __repr__(self):
+ return str(self.region)
+
+ @property
+ def bucket_set(self):
+ return self._bucket_set
+
+
+class UnhookedUnit(VMUnit):
+ """Represents a Unit for a non-mmap'ed memory region on virtual memory."""
+ def __init__(self, unit_id, committed, reserved, region,
+ pageframe=None, group_pfn_counts=None):
+ super(UnhookedUnit, self).__init__(unit_id, committed, reserved, False,
+ region, pageframe, group_pfn_counts)
+
+ def __repr__(self):
+ return str(self.region)
+
+
+class MallocUnit(Unit):
+ """Represents a Unit for a malloc'ed memory block."""
+ def __init__(self, unit_id, size, alloc_count, free_count, bucket):
+ super(MallocUnit, self).__init__(unit_id, size)
+ self._bucket = bucket
+ self._alloc_count = alloc_count
+ self._free_count = free_count
+
+ def __repr__(self):
+ return str(self.bucket)
+
+ @property
+ def bucket(self):
+ return self._bucket
+
+ @property
+ def alloc_count(self):
+ return self._alloc_count
+
+ @property
+ def free_count(self):
+ return self._free_count
+
+
+class UnitSet(object):
+ """Represents an iterable set of Units."""
+ def __init__(self, world):
+ self._units = {}
+ self._world = world
+
+ def __repr__(self):
+ return str(self._units)
+
+ def __iter__(self):
+ for unit_id in sorted(self._units):
+ yield self._units[unit_id]
+
+ def append(self, unit, overwrite=False):
+ if not overwrite and unit.unit_id in self._units:
+ LOGGER.error('The unit id=%s already exists.' % str(unit.unit_id))
+ self._units[unit.unit_id] = unit
+
+
+class AbstractRule(object):
+ """An abstract class for rules to be matched with units."""
+ def __init__(self, dct):
+ self._name = dct['name']
+ self._hidden = dct.get('hidden', False)
+ self._subs = dct.get('subs', [])
+
+ def match(self, unit):
+ raise NotImplementedError()
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def hidden(self):
+ return self._hidden
+
+ def iter_subs(self):
+ for sub in self._subs:
+ yield sub
+
+
+class VMRule(AbstractRule):
+ """Represents a Rule to match with virtual memory regions."""
+ def __init__(self, dct):
+ super(VMRule, self).__init__(dct)
+ self._backtrace_function = dct.get('backtrace_function', None)
+ if self._backtrace_function:
+ self._backtrace_function = re.compile(self._backtrace_function)
+ self._backtrace_sourcefile = dct.get('backtrace_sourcefile', None)
+ if self._backtrace_sourcefile:
+ self._backtrace_sourcefile = re.compile(self._backtrace_sourcefile)
+ self._mmap = dct.get('mmap', None)
+ self._sharedwith = dct.get('sharedwith', [])
+ self._mapped_pathname = dct.get('mapped_pathname', None)
+ if self._mapped_pathname:
+ self._mapped_pathname = re.compile(self._mapped_pathname)
+ self._mapped_permission = dct.get('mapped_permission', None)
+ if self._mapped_permission:
+ self._mapped_permission = re.compile(self._mapped_permission)
+
+ def __repr__(self):
+ result = cStringIO.StringIO()
+ result.write('{"%s"=>' % self._name)
+ attributes = []
+ attributes.append('mmap: %s' % self._mmap)
+ if self._backtrace_function:
+ attributes.append('backtrace_function: "%s"' %
+ self._backtrace_function.pattern)
+ if self._sharedwith:
+ attributes.append('sharedwith: "%s"' % self._sharedwith)
+ if self._mapped_pathname:
+ attributes.append('mapped_pathname: "%s"' % self._mapped_pathname.pattern)
+ if self._mapped_permission:
+ attributes.append('mapped_permission: "%s"' %
+ self._mapped_permission.pattern)
+ result.write('%s}' % ', '.join(attributes))
+ return result.getvalue()
+
+ def match(self, unit):
+ if unit.mmap:
+ assert unit.region[0] == 'hooked'
+ bucket = unit.bucket_set.get(unit.region[1]['bucket_id'])
+ assert bucket
+ assert bucket.allocator_type == 'mmap'
+
+ stackfunction = bucket.symbolized_joined_stackfunction
+ stacksourcefile = bucket.symbolized_joined_stacksourcefile
+
+ # TODO(dmikurube): Support shared memory.
+ sharedwith = None
+
+ if self._mmap == False: # (self._mmap == None) should go through.
+ return False
+ if (self._backtrace_function and
+ not self._backtrace_function.match(stackfunction)):
+ return False
+ if (self._backtrace_sourcefile and
+ not self._backtrace_sourcefile.match(stacksourcefile)):
+ return False
+ if (self._mapped_pathname and
+ not self._mapped_pathname.match(unit.region[1]['vma']['name'])):
+ return False
+ if (self._mapped_permission and
+ not self._mapped_permission.match(
+ unit.region[1]['vma']['readable'] +
+ unit.region[1]['vma']['writable'] +
+ unit.region[1]['vma']['executable'] +
+ unit.region[1]['vma']['private'])):
+ return False
+ if (self._sharedwith and
+ unit.pageframe and sharedwith not in self._sharedwith):
+ return False
+
+ return True
+
+ else:
+ assert unit.region[0] == 'unhooked'
+
+ # TODO(dmikurube): Support shared memory.
+ sharedwith = None
+
+ if self._mmap == True: # (self._mmap == None) should go through.
+ return False
+ if (self._mapped_pathname and
+ not self._mapped_pathname.match(unit.region[1]['vma']['name'])):
+ return False
+ if (self._mapped_permission and
+ not self._mapped_permission.match(
+ unit.region[1]['vma']['readable'] +
+ unit.region[1]['vma']['writable'] +
+ unit.region[1]['vma']['executable'] +
+ unit.region[1]['vma']['private'])):
+ return False
+ if (self._sharedwith and
+ unit.pageframe and sharedwith not in self._sharedwith):
+ return False
+
+ return True
+
+
+class MallocRule(AbstractRule):
+ """Represents a Rule to match with malloc'ed blocks."""
+ def __init__(self, dct):
+ super(MallocRule, self).__init__(dct)
+ self._backtrace_function = dct.get('backtrace_function', None)
+ if self._backtrace_function:
+ self._backtrace_function = re.compile(self._backtrace_function)
+ self._backtrace_sourcefile = dct.get('backtrace_sourcefile', None)
+ if self._backtrace_sourcefile:
+ self._backtrace_sourcefile = re.compile(self._backtrace_sourcefile)
+ self._typeinfo = dct.get('typeinfo', None)
+ if self._typeinfo:
+ self._typeinfo = re.compile(self._typeinfo)
+
+ def __repr__(self):
+ result = cStringIO.StringIO()
+ result.write('{"%s"=>' % self._name)
+ attributes = []
+ if self._backtrace_function:
+ attributes.append('backtrace_function: "%s"' % self._backtrace_function)
+ if self._typeinfo:
+ attributes.append('typeinfo: "%s"' % self._typeinfo)
+ result.write('%s}' % ', '.join(attributes))
+ return result.getvalue()
+
+ def match(self, unit):
+ assert unit.bucket.allocator_type == 'malloc'
+
+ stackfunction = unit.bucket.symbolized_joined_stackfunction
+ stacksourcefile = unit.bucket.symbolized_joined_stacksourcefile
+ typeinfo = unit.bucket.symbolized_typeinfo
+ if typeinfo.startswith('0x'):
+ typeinfo = unit.bucket.typeinfo_name
+
+ return ((not self._backtrace_function or
+ self._backtrace_function.match(stackfunction)) and
+ (not self._backtrace_sourcefile or
+ self._backtrace_sourcefile.match(stacksourcefile)) and
+ (not self._typeinfo or self._typeinfo.match(typeinfo)))
+
+
+class NoBucketMallocRule(MallocRule):
+ """Represents a Rule that small ignorable units match with."""
+ def __init__(self):
+ super(NoBucketMallocRule, self).__init__({'name': 'tc-no-bucket'})
+ self._no_bucket = True
+
+ @property
+ def no_bucket(self):
+ return self._no_bucket
+
+
+class AbstractSorter(object):
+ """An abstract class for classifying Units with a set of Rules."""
+ def __init__(self, dct):
+ self._type = 'sorter'
+ self._version = dct['version']
+ self._world = dct['world']
+ self._name = dct['name']
+ self._root = dct.get('root', False)
+ self._order = dct['order']
+
+ self._rules = []
+ for rule in dct['rules']:
+ if dct['world'] == 'vm':
+ self._rules.append(VMRule(rule))
+ elif dct['world'] == 'malloc':
+ self._rules.append(MallocRule(rule))
+ else:
+ LOGGER.error('Unknown sorter world type')
+
+ def __repr__(self):
+ result = cStringIO.StringIO()
+ result.write('world=%s' % self._world)
+ result.write('order=%s' % self._order)
+ result.write('rules:')
+ for rule in self._rules:
+ result.write(' %s' % rule)
+ return result.getvalue()
+
+ @staticmethod
+ def load(filename):
+ with open(filename) as sorter_f:
+ sorter_dict = json.load(sorter_f)
+ if sorter_dict['world'] == 'vm':
+ return VMSorter(sorter_dict)
+ elif sorter_dict['world'] == 'malloc':
+ return MallocSorter(sorter_dict)
+ else:
+ LOGGER.error('Unknown sorter world type')
+ return None
+
+ @property
+ def world(self):
+ return self._world
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def root(self):
+ return self._root
+
+ def find(self, unit):
+ raise NotImplementedError()
+
+ def find_rule(self, name):
+ """Finds a rule whose name is |name|. """
+ for rule in self._rules:
+ if rule.name == name:
+ return rule
+ return None
+
+
+class VMSorter(AbstractSorter):
+ """Represents a Sorter for memory regions on virtual memory."""
+ def __init__(self, dct):
+ assert dct['world'] == 'vm'
+ super(VMSorter, self).__init__(dct)
+
+ def find(self, unit):
+ for rule in self._rules:
+ if rule.match(unit):
+ return rule
+ assert False
+
+
+class MallocSorter(AbstractSorter):
+ """Represents a Sorter for malloc'ed blocks."""
+ def __init__(self, dct):
+ assert dct['world'] == 'malloc'
+ super(MallocSorter, self).__init__(dct)
+ self._no_bucket_rule = NoBucketMallocRule()
+
+ def find(self, unit):
+ if not unit.bucket:
+ return self._no_bucket_rule
+ assert unit.bucket.allocator_type == 'malloc'
+
+ if unit.bucket.component_cache:
+ return unit.bucket.component_cache
+
+ for rule in self._rules:
+ if rule.match(unit):
+ unit.bucket.component_cache = rule
+ return rule
+ assert False
+
+
+class SorterTemplates(object):
+ """Represents a template for sorters."""
+ def __init__(self, dct):
+ self._dict = dct
+
+ def as_dict(self):
+ return self._dict
+
+ @staticmethod
+ def load(filename):
+ with open(filename) as templates_f:
+ templates_dict = json.load(templates_f)
+ return SorterTemplates(templates_dict)
+
+
+class SorterSet(object):
+ """Represents an iterable set of Sorters."""
+ def __init__(self, additional=None, default=None):
+ if not additional:
+ additional = []
+ if not default:
+ default = DEFAULT_SORTERS
+ self._sorters = {}
+ for filename in default + additional:
+ sorter = AbstractSorter.load(filename)
+ if sorter.world not in self._sorters:
+ self._sorters[sorter.world] = []
+ self._sorters[sorter.world].append(sorter)
+ self._templates = SorterTemplates.load(DEFAULT_TEMPLATES)
+
+ def __repr__(self):
+ result = cStringIO.StringIO()
+ result.write(self._sorters)
+ return result.getvalue()
+
+ def __iter__(self):
+ for sorters in self._sorters.itervalues():
+ for sorter in sorters:
+ yield sorter
+
+ def iter_world(self, world):
+ for sorter in self._sorters.get(world, []):
+ yield sorter
+
+ @property
+ def templates(self):
+ return self._templates
diff --git a/chromium/tools/deep_memory_profiler/lib/subcommand.py b/chromium/tools/deep_memory_profiler/lib/subcommand.py
new file mode 100644
index 00000000000..25416f6ee39
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/subcommand.py
@@ -0,0 +1,160 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import optparse
+import os
+import re
+
+from lib.bucket import BucketSet
+from lib.dump import Dump, DumpList
+from lib.symbol import SymbolDataSources, SymbolMappingCache, SymbolFinder
+from lib.symbol import proc_maps
+from lib.symbol import FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS, TYPEINFO_SYMBOLS
+
+
+LOGGER = logging.getLogger('dmprof')
+
+BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+CHROME_SRC_PATH = os.path.join(BASE_PATH, os.pardir, os.pardir)
+
+
+class SubCommand(object):
+ """Subclasses are a subcommand for this executable.
+
+ See COMMANDS in main() in dmprof.py.
+ """
+ _DEVICE_BINDIRS = ['/data/data/', '/data/app-lib/', '/data/local/tmp']
+
+ def __init__(self, usage):
+ self._parser = optparse.OptionParser(usage)
+
+ @staticmethod
+ def load_basic_files(
+ dump_path, multiple, no_dump=False, alternative_dirs=None):
+ prefix = SubCommand._find_prefix(dump_path)
+ # If the target process is estimated to be working on Android, converts
+ # a path in the Android device to a path estimated to be corresponding in
+ # the host. Use --alternative-dirs to specify the conversion manually.
+ if not alternative_dirs:
+ alternative_dirs = SubCommand._estimate_alternative_dirs(prefix)
+ if alternative_dirs:
+ for device, host in alternative_dirs.iteritems():
+ LOGGER.info('Assuming %s on device as %s on host' % (device, host))
+ symbol_data_sources = SymbolDataSources(prefix, alternative_dirs)
+ symbol_data_sources.prepare()
+ bucket_set = BucketSet()
+ bucket_set.load(prefix)
+ if not no_dump:
+ if multiple:
+ dump_list = DumpList.load(SubCommand._find_all_dumps(dump_path))
+ else:
+ dump = Dump.load(dump_path)
+ symbol_mapping_cache = SymbolMappingCache()
+ with open(prefix + '.cache.function', 'a+') as cache_f:
+ symbol_mapping_cache.update(
+ FUNCTION_SYMBOLS, bucket_set,
+ SymbolFinder(FUNCTION_SYMBOLS, symbol_data_sources), cache_f)
+ with open(prefix + '.cache.typeinfo', 'a+') as cache_f:
+ symbol_mapping_cache.update(
+ TYPEINFO_SYMBOLS, bucket_set,
+ SymbolFinder(TYPEINFO_SYMBOLS, symbol_data_sources), cache_f)
+ with open(prefix + '.cache.sourcefile', 'a+') as cache_f:
+ symbol_mapping_cache.update(
+ SOURCEFILE_SYMBOLS, bucket_set,
+ SymbolFinder(SOURCEFILE_SYMBOLS, symbol_data_sources), cache_f)
+ bucket_set.symbolize(symbol_mapping_cache)
+ if no_dump:
+ return bucket_set
+ elif multiple:
+ return (bucket_set, dump_list)
+ else:
+ return (bucket_set, dump)
+
+ @staticmethod
+ def _find_prefix(path):
+ return re.sub('\.[0-9][0-9][0-9][0-9]\.heap', '', path)
+
+ @staticmethod
+ def _estimate_alternative_dirs(prefix):
+ """Estimates a path in host from a corresponding path in target device.
+
+ For Android, dmprof.py should find symbol information from binaries in
+ the host instead of the Android device because dmprof.py doesn't run on
+ the Android device. This method estimates a path in the host
+ corresponding to a path in the Android device.
+
+ Returns:
+ A dict that maps a path in the Android device to a path in the host.
+ If a file in SubCommand._DEVICE_BINDIRS is found in /proc/maps, it
+ assumes the process was running on Android and maps the path to
+ "out/Debug/lib" in the Chromium directory. An empty dict is returned
+ unless Android.
+ """
+ device_lib_path_candidates = set()
+
+ with open(prefix + '.maps') as maps_f:
+ maps = proc_maps.ProcMaps.load(maps_f)
+ for entry in maps:
+ name = entry.as_dict()['name']
+ if any([base_dir in name for base_dir in SubCommand._DEVICE_BINDIRS]):
+ device_lib_path_candidates.add(os.path.dirname(name))
+
+ if len(device_lib_path_candidates) == 1:
+ return {device_lib_path_candidates.pop(): os.path.join(
+ CHROME_SRC_PATH, 'out', 'Debug', 'lib')}
+ else:
+ return {}
+
+ @staticmethod
+ def _find_all_dumps(dump_path):
+ prefix = SubCommand._find_prefix(dump_path)
+ dump_path_list = [dump_path]
+
+ n = int(dump_path[len(dump_path) - 9 : len(dump_path) - 5])
+ n += 1
+ skipped = 0
+ while True:
+ p = '%s.%04d.heap' % (prefix, n)
+ if os.path.exists(p) and os.stat(p).st_size:
+ dump_path_list.append(p)
+ else:
+ if skipped > 10:
+ break
+ skipped += 1
+ n += 1
+
+ return dump_path_list
+
+ @staticmethod
+ def _find_all_buckets(dump_path):
+ prefix = SubCommand._find_prefix(dump_path)
+ bucket_path_list = []
+
+ n = 0
+ while True:
+ path = '%s.%04d.buckets' % (prefix, n)
+ if not os.path.exists(path):
+ if n > 10:
+ break
+ n += 1
+ continue
+ bucket_path_list.append(path)
+ n += 1
+
+ return bucket_path_list
+
+ def _parse_args(self, sys_argv, required):
+ options, args = self._parser.parse_args(sys_argv)
+ if len(args) < required + 1:
+ self._parser.error('needs %d argument(s).\n' % required)
+ return None
+ return (options, args)
+
+ @staticmethod
+ def _parse_policy_list(options_policy):
+ if options_policy:
+ return options_policy.split(',')
+ else:
+ return None
diff --git a/chromium/tools/deep_memory_profiler/lib/symbol.py b/chromium/tools/deep_memory_profiler/lib/symbol.py
new file mode 100644
index 00000000000..897d4098d56
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/lib/symbol.py
@@ -0,0 +1,189 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import sys
+
+_BASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+_FIND_RUNTIME_SYMBOLS_PATH = os.path.join(_BASE_PATH,
+ os.pardir,
+ 'find_runtime_symbols')
+sys.path.append(_FIND_RUNTIME_SYMBOLS_PATH)
+
+import find_runtime_symbols
+import prepare_symbol_info
+import proc_maps # pylint: disable=W0611
+
+LOGGER = logging.getLogger('dmprof')
+
+FUNCTION_SYMBOLS = find_runtime_symbols.FUNCTION_SYMBOLS
+SOURCEFILE_SYMBOLS = find_runtime_symbols.SOURCEFILE_SYMBOLS
+TYPEINFO_SYMBOLS = find_runtime_symbols.TYPEINFO_SYMBOLS
+
+
+class SymbolDataSources(object):
+ """Manages symbol data sources in a process.
+
+ The symbol data sources consist of maps (/proc/<pid>/maps), nm, readelf and
+ so on. They are collected into a directory '|prefix|.symmap' from the binary
+ files by 'prepare()' with tools/find_runtime_symbols/prepare_symbol_info.py.
+
+ Binaries are not mandatory to profile. The prepared data sources work in
+ place of the binary even if the binary has been overwritten with another
+ binary.
+
+ Note that loading the symbol data sources takes a long time. They are often
+ very big. So, the 'dmprof' profiler is designed to use 'SymbolMappingCache'
+ which caches actually used symbols.
+ """
+ def __init__(self, prefix, alternative_dirs=None):
+ self._prefix = prefix
+ self._prepared_symbol_data_sources_path = None
+ self._loaded_symbol_data_sources = None
+ self._alternative_dirs = alternative_dirs or {}
+
+ def prepare(self):
+ """Prepares symbol data sources by extracting mapping from a binary.
+
+ The prepared symbol data sources are stored in a directory. The directory
+ name is stored in |self._prepared_symbol_data_sources_path|.
+
+ Returns:
+ True if succeeded.
+ """
+ LOGGER.info('Preparing symbol mapping...')
+ self._prepared_symbol_data_sources_path, used_tempdir = (
+ prepare_symbol_info.prepare_symbol_info(
+ self._prefix + '.maps',
+ output_dir_path=self._prefix + '.symmap',
+ alternative_dirs=self._alternative_dirs,
+ use_tempdir=True,
+ use_source_file_name=True))
+ if self._prepared_symbol_data_sources_path:
+ LOGGER.info(' Prepared symbol mapping.')
+ if used_tempdir:
+ LOGGER.warn(' Using a temporary directory for symbol mapping.')
+ LOGGER.warn(' Delete it by yourself.')
+ LOGGER.warn(' Or, move the directory by yourself to use it later.')
+ return True
+ else:
+ LOGGER.warn(' Failed to prepare symbol mapping.')
+ return False
+
+ def get(self):
+ """Returns the prepared symbol data sources.
+
+ Returns:
+ The prepared symbol data sources. None if failed.
+ """
+ if not self._prepared_symbol_data_sources_path and not self.prepare():
+ return None
+ if not self._loaded_symbol_data_sources:
+ LOGGER.info('Loading symbol mapping...')
+ self._loaded_symbol_data_sources = (
+ find_runtime_symbols.RuntimeSymbolsInProcess.load(
+ self._prepared_symbol_data_sources_path))
+ return self._loaded_symbol_data_sources
+
+ def path(self):
+ """Returns the path of the prepared symbol data sources if possible."""
+ if not self._prepared_symbol_data_sources_path and not self.prepare():
+ return None
+ return self._prepared_symbol_data_sources_path
+
+
+class SymbolFinder(object):
+ """Finds corresponding symbols from addresses.
+
+ This class does only 'find()' symbols from a specified |address_list|.
+ It is introduced to make a finder mockable.
+ """
+ def __init__(self, symbol_type, symbol_data_sources):
+ self._symbol_type = symbol_type
+ self._symbol_data_sources = symbol_data_sources
+
+ def find(self, address_list):
+ return find_runtime_symbols.find_runtime_symbols(
+ self._symbol_type, self._symbol_data_sources.get(), address_list)
+
+
+class SymbolMappingCache(object):
+ """Caches mapping from actually used addresses to symbols.
+
+ 'update()' updates the cache from the original symbol data sources via
+ 'SymbolFinder'. Symbols can be looked up by the method 'lookup()'.
+ """
+ def __init__(self):
+ self._symbol_mapping_caches = {
+ FUNCTION_SYMBOLS: {},
+ SOURCEFILE_SYMBOLS: {},
+ TYPEINFO_SYMBOLS: {},
+ }
+
+ def update(self, symbol_type, bucket_set, symbol_finder, cache_f):
+ """Updates symbol mapping cache on memory and in a symbol cache file.
+
+ It reads cached symbol mapping from a symbol cache file |cache_f| if it
+ exists. Unresolved addresses are then resolved and added to the cache
+ both on memory and in the symbol cache file with using 'SymbolFinder'.
+
+ A cache file is formatted as follows:
+ <Address> <Symbol>
+ <Address> <Symbol>
+ <Address> <Symbol>
+ ...
+
+ Args:
+ symbol_type: A type of symbols to update. It should be one of
+ FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS and TYPEINFO_SYMBOLS.
+ bucket_set: A BucketSet object.
+ symbol_finder: A SymbolFinder object to find symbols.
+ cache_f: A readable and writable IO object of the symbol cache file.
+ """
+ cache_f.seek(0, os.SEEK_SET)
+ self._load(cache_f, symbol_type)
+
+ unresolved_addresses = sorted(
+ address for address in bucket_set.iter_addresses(symbol_type)
+ if address not in self._symbol_mapping_caches[symbol_type])
+
+ if not unresolved_addresses:
+ LOGGER.info('No need to resolve any more addresses.')
+ return
+
+ cache_f.seek(0, os.SEEK_END)
+ LOGGER.info('Loading %d unresolved addresses.' %
+ len(unresolved_addresses))
+ symbol_dict = symbol_finder.find(unresolved_addresses)
+
+ for address, symbol in symbol_dict.iteritems():
+ stripped_symbol = symbol.strip() or '?'
+ self._symbol_mapping_caches[symbol_type][address] = stripped_symbol
+ cache_f.write('%x %s\n' % (address, stripped_symbol))
+
+ def lookup(self, symbol_type, address):
+ """Looks up a symbol for a given |address|.
+
+ Args:
+ symbol_type: A type of symbols to update. It should be one of
+ FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS and TYPEINFO_SYMBOLS.
+ address: An integer that represents an address.
+
+ Returns:
+ A string that represents a symbol.
+ """
+ return self._symbol_mapping_caches[symbol_type].get(address)
+
+ def _load(self, cache_f, symbol_type):
+ try:
+ for line in cache_f:
+ items = line.rstrip().split(None, 1)
+ if len(items) == 1:
+ items.append('??')
+ self._symbol_mapping_caches[symbol_type][int(items[0], 16)] = items[1]
+ LOGGER.info('Loaded %d entries from symbol cache.' %
+ len(self._symbol_mapping_caches[symbol_type]))
+ except IOError as e:
+ LOGGER.info('The symbol cache file is invalid: %s' % e)
diff --git a/chromium/tools/deep_memory_profiler/policies.json b/chromium/tools/deep_memory_profiler/policies.json
new file mode 100644
index 00000000000..775045a8c2a
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policies.json
@@ -0,0 +1,34 @@
+{
+ "android.browser": {
+ "file": "policy.android.browser.json",
+ "format": "json"
+ },
+ "android.renderer": {
+ "file": "policy.android.renderer.json",
+ "format": "json"
+ },
+ "android.webview": {
+ "file": "policy.android.webview.json",
+ "format": "json"
+ },
+ "sourcefile": {
+ "file": "policy.sourcefile.json",
+ "format": "json"
+ },
+ "l0": {
+ "file": "policy.l0.json",
+ "format": "json"
+ },
+ "l1": {
+ "file": "policy.l1.json",
+ "format": "json"
+ },
+ "l2": {
+ "file": "policy.l2.json",
+ "format": "json"
+ },
+ "t0": {
+ "file": "policy.t0.json",
+ "format": "json"
+ }
+} \ No newline at end of file
diff --git a/chromium/tools/deep_memory_profiler/policy.android.browser.json b/chromium/tools/deep_memory_profiler/policy.android.browser.json
new file mode 100644
index 00000000000..e34fee72532
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policy.android.browser.json
@@ -0,0 +1,301 @@
+{
+ "components": [
+ "second",
+ "mmap-profiler",
+ "mmap-type-profiler",
+ "mmap-tcmalloc",
+ "FROM_HERE_FOR_TOTAL",
+ "mustbezero",
+ "unhooked-absent",
+ "unhooked-ashmem-dalvik-heap",
+ "unhooked-ashmem-dalvik-LinearAlloc",
+ "unhooked-ashmem-dalvik-aux-structure",
+ "unhooked-ashmem-dalvik-bitmap",
+ "unhooked-ashmem-dalvik-other",
+ "unhooked-pvrsrvkm",
+ "unhooked-system-dex",
+ "unhooked-chrome-dex",
+ "unhooked-other-ashmem",
+ "unhooked-anonymous",
+ "unhooked-file-exec-lib-chrome",
+ "unhooked-file-exec",
+ "unhooked-file-nonexec-lib-chrome",
+ "unhooked-file-nonexec",
+ "unhooked-stack",
+ "unhooked-other",
+ "no-bucket",
+ "mmap-gpu-transferbuffer",
+ "mmap-gpu-ringbuffer",
+ "mmap-catch-all",
+ "tc-disk_cache-backing",
+ "tc-disk_cache-other",
+ "tc-sqlite3MemAlloc",
+ "tc-angle",
+ "tc-crypto",
+ "tc-net-iobuffer",
+ "tc-stl-string",
+ "tc-stl-rbtree",
+ "tc-stl-vector",
+ "tc-stl-hashtable",
+ "tc-stl-node",
+ "tc-catch-all",
+ "tc-unused",
+ "UNTIL_HERE_FOR_TOTAL",
+ "total-exclude-profiler",
+ "total",
+ "absent",
+ "anonymous",
+ "file-exec",
+ "file-nonexec",
+ "stack",
+ "other",
+ "mmap-total-log",
+ "mmap-no-log",
+ "mmap-total-record",
+ "other-total-log",
+ "tc-total-log",
+ "tc-no-log",
+ "tc-total-record",
+ "tc-total"
+ ],
+ "rules": [
+ {
+ "name": "second",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mmap-profiler",
+ "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-type-profiler",
+ "stacktrace": ".*(TypeProfilerMalloc).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "FROM_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mustbezero",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-heap",
+ "mappedpathname": "/dev/ashmem/dalvik-heap.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-LinearAlloc",
+ "mappedpathname": "/dev/ashmem/dalvik-LinearAlloc.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-aux-structure",
+ "mappedpathname": "/dev/ashmem/dalvik-aux-structure.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-bitmap",
+ "mappedpathname": "/dev/ashmem/dalvik-bitmap.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-other",
+ "mappedpathname": "/dev/ashmem/dalvik.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-pvrsrvkm",
+ "mappedpathname": "/dev/pvrsrvkm.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-system-dex",
+ "mappedpathname": "/data/dalvik-cache/system.*.dex.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-chrome-dex",
+ "mappedpathname": "^/.*?(chrome|content).*?apk@classes.dex",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other-ashmem",
+ "mappedpathname": "/dev/ashmem/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mappedpathname": "^$",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec-lib-chrome",
+ "mappedpathname": "^/.*?(chromeview|content).*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mappedpathname": "^/.*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec-lib-chrome",
+ "mappedpathname": "^/.*?(chromeview|content).*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-stack",
+ "mappedpathname": ".stack.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other",
+ "mappedpathname": ".*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "mmap-gpu-transferbuffer",
+ "stacktrace": ".*gpu::TransferBufferManager::RegisterTransferBuffer.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-ringbuffer",
+ "stacktrace": ".*gpu::CommandBufferHelper::AllocateRingBuffer.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-catch-all",
+ "stacktrace": ".*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "tc-disk_cache-backing",
+ "stacktrace": ".*disk_cache::BackendImpl::InitBackingStore.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-disk_cache-other",
+ "stacktrace": ".*disk_cache::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-sqlite3MemAlloc",
+ "stacktrace": ".*sqlite3MemMalloc.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-angle",
+ "stacktrace": ".*TPoolAllocator::allocate.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-crypto",
+ "stacktrace": ".*(CRYPTO_malloc|CRYPTO_realloc).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-net-iobuffer",
+ "stacktrace": ".*net::IOBuffer::IOBuffer.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-string",
+ "stacktrace": ".*std::basic_string::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-rbtree",
+ "stacktrace": ".*std::priv::_Rb_tree::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-vector",
+ "stacktrace": ".*std::priv::_Impl_vector::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-hashtable",
+ "stacktrace": ".*std::hashtable::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-node",
+ "stacktrace": ".*std::priv::_Impl_vector::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-catch-all",
+ "stacktrace": ".*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "UNTIL_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total-exclude-profiler",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "anonymous",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-exec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-nonexec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "stack",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "other",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ }
+ ],
+ "version": "POLICY_DEEP_3"
+}
diff --git a/chromium/tools/deep_memory_profiler/policy.android.renderer.json b/chromium/tools/deep_memory_profiler/policy.android.renderer.json
new file mode 100644
index 00000000000..c039c6f97a6
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policy.android.renderer.json
@@ -0,0 +1,579 @@
+{
+ "components": [
+ "second",
+ "mmap-profiler",
+ "mmap-type-profiler",
+ "mmap-tcmalloc",
+ "FROM_HERE_FOR_TOTAL",
+ "mustbezero",
+ "unhooked-absent",
+ "unhooked-ashmem-dalvik-heap",
+ "unhooked-ashmem-dalvik-LinearAlloc",
+ "unhooked-ashmem-dalvik-aux-structure",
+ "unhooked-ashmem-dalvik-bitmap",
+ "unhooked-ashmem-dalvik-other",
+ "unhooked-pvrsrvkm",
+ "unhooked-system-dex",
+ "unhooked-chrome-dex",
+ "unhooked-other-ashmem",
+ "unhooked-anonymous",
+ "unhooked-file-exec-lib-chrome",
+ "unhooked-file-exec",
+ "unhooked-file-nonexec-lib-chrome",
+ "unhooked-file-nonexec",
+ "unhooked-stack",
+ "unhooked-other",
+ "no-bucket",
+ "mmap-v8-heap-newspace",
+ "mmap-v8-heap-coderange",
+ "mmap-v8-heap-pagedspace",
+ "mmap-v8-other",
+ "mmap-gpu-mappedmemorymanager",
+ "mmap-gpu-command-ringbuffer",
+ "mmap-gpu-transfer-ringbuffer",
+ "mmap-gpu-gles2-createbuffer",
+ "mmap-skia-font",
+ "mmap-catch-all",
+ "tc-webcore-fontcache",
+ "tc-skia",
+ "tc-renderobject",
+ "tc-renderstyle",
+ "tc-webcore-sharedbuf",
+ "tc-webcore-XHRcreate",
+ "tc-webcore-XHRreceived",
+ "tc-webcore-docwriter-add",
+ "tc-webcore-node-and-doc",
+ "tc-webcore-node-factory",
+ "tc-webcore-element-wrapper",
+ "tc-webcore-stylepropertyset",
+ "tc-webcore-style-createsheet",
+ "tc-webcore-cachedresource",
+ "tc-webcore-script-execute",
+ "tc-webcore-events-related",
+ "tc-webcore-document-write",
+ "tc-webcore-node-create-renderer",
+ "tc-webcore-image-frame-generator",
+ "tc-webcore-render-catch-all",
+ "tc-webcore-setInnerHTML-except-node",
+ "tc-wtf-StringImpl-user-catch-all",
+ "tc-wtf-HashTable-user-catch-all",
+ "tc-webcore-everything-create",
+ "tc-webkit-from-v8-catch-all",
+ "tc-webkit-catch-all",
+ "tc-v8-catch-all",
+ "tc-toplevel-string",
+ "tc-std-treemap",
+ "tc-std-hashmap",
+ "tc-std-vector",
+ "tc-std-other",
+ "tc-catch-all",
+ "tc-unused",
+ "UNTIL_HERE_FOR_TOTAL",
+ "total-exclude-profiler",
+ "total",
+ "absent",
+ "anonymous",
+ "file-exec",
+ "file-nonexec",
+ "stack",
+ "other",
+ "mmap-total-log",
+ "mmap-no-log",
+ "mmap-total-record",
+ "other-total-log",
+ "tc-total-log",
+ "tc-no-log",
+ "tc-total-record",
+ "tc-total"
+ ],
+ "rules": [
+ {
+ "name": "second",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mmap-profiler",
+ "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-type-profiler",
+ "stacktrace": ".*(TypeProfilerMalloc).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "FROM_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mustbezero",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-heap",
+ "mappedpathname": "/dev/ashmem/dalvik-heap.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-LinearAlloc",
+ "mappedpathname": "/dev/ashmem/dalvik-LinearAlloc.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-aux-structure",
+ "mappedpathname": "/dev/ashmem/dalvik-aux-structure.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-bitmap",
+ "mappedpathname": "/dev/ashmem/dalvik-bitmap.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-other",
+ "mappedpathname": "/dev/ashmem/dalvik.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-pvrsrvkm",
+ "mappedpathname": "/dev/pvrsrvkm.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-system-dex",
+ "mappedpathname": "/data/dalvik-cache/system.*.dex.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-chrome-dex",
+ "mappedpathname": "^/.*?(chrome|content).*?apk@classes.dex",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other-ashmem",
+ "mappedpathname": "/dev/ashmem/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mappedpathname": "^$",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec-lib-chrome",
+ "mappedpathname": "^/.*?(chromeview|content).*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mappedpathname": "^/.*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec-lib-chrome",
+ "mappedpathname": "^/.*?(chromeview|content).*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-stack",
+ "mappedpathname": ".stack.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other",
+ "mappedpathname": ".*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "mmap-v8-heap-newspace",
+ "stacktrace": ".*v8::internal::NewSpace::SetUp.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-heap-coderange",
+ "stacktrace": ".*v8::internal::CodeRange::SetUp.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-heap-pagedspace",
+ "stacktrace": ".*v8::internal::PagedSpace::AllocateRaw.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-other",
+ "stacktrace": ".*v8::.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-mappedmemorymanager",
+ "stacktrace": ".*gpu::MappedMemoryManager::Alloc.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-command-ringbuffer",
+ "stacktrace": ".*gpu::CommandBufferHelper::AllocateRingBuffer.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-transfer-ringbuffer",
+ "stacktrace": ".*gpu::TransferBuffer::AllocateRingBuffer.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-gles2-createbuffer",
+ "stacktrace": ".*gpu::gles2::BufferTracker::CreateBuffer.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-skia-font",
+ "stacktrace": ".*SkTypeface::openStream.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-catch-all",
+ "stacktrace": ".*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "tc-webcore-fontcache",
+ "stacktrace": ".*WebCore::FontCache::getCachedFontData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-skia",
+ "stacktrace": ".* Sk[A-Za-z_]+::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderobject",
+ "stacktrace": ".*WebCore::RenderArena::allocate.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderstyle",
+ "stacktrace": ".*WebCore::RenderStyle::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderstyle",
+ "stacktrace": ".*WebCore::RenderStyle::clone.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::buffer.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::append.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-XHRcreate",
+ "stacktrace": ".*WebCore::XMLHttpRequest::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-XHRreceived",
+ "stacktrace": ".*WebCore::XMLHttpRequest::didReceiveData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-docwriter-add",
+ "stacktrace": ".*WebCore::DocumentWriter::addData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Element::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Text::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Comment::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::HTMLDocument::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::CSSStyleRule::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Attribute::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::DOMWindow::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-factory",
+ "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Factory::create[a-zA-Z0-9_]*Element.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-element-wrapper",
+ "stacktrace": ".*WebCore::createHTML[a-zA-Z0-9_]*ElementWrapper.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-stylepropertyset",
+ "stacktrace": ".*WebCore::StylePropertySet::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-style-createsheet",
+ "stacktrace": ".*WebCore::StyleElement::createSheet.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-cachedresource",
+ "stacktrace": ".*WebCore::CachedResource::data .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-cachedresource",
+ "stacktrace": ".*WebCore::CachedResource::load .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-script-execute",
+ "stacktrace": ".*WebCore::ScriptElement::execute.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::createAttributeEventListener.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::V8LazyEventListener::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::V8EventListener::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::Event::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::EventListener::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-document-write",
+ "stacktrace": ".*WebCore::Document::write.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-create-renderer",
+ "stacktrace": ".*WebCore::Node::createRendererIfNeeded.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-image-frame-generator",
+ "stacktrace": ".*WebCore::ImageFrameGenerator.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderLayer.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderBlock.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderWidget.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderView.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderViewImpl.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderStyle.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderText.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".* RendererMain .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-setInnerHTML-except-node",
+ "stacktrace": ".*WebCore::HTMLElement::setInnerHTML.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-StringImpl-user-catch-all",
+ "stacktrace": ".*WTF::StringImpl::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-StringImpl-user-catch-all",
+ "stacktrace": ".*WTF::StringImpl::createUninitialized.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-HashTable-user-catch-all",
+ "stacktrace": ".*WTF::HashTable::allocateTable.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-everything-create",
+ "stacktrace": ".*WebCore::[a-zA-Z0-9_]*::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webkit-from-v8-catch-all",
+ "stacktrace": ".*(WTF::|WebCore::|WebKit::).*v8::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webkit-catch-all",
+ "stacktrace": ".*(WTF::|WebCore::|WebKit::).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-v8-catch-all",
+ "stacktrace": ".*v8::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-toplevel-string",
+ "stacktrace": "std::basic_string::_Rep::_S_create",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-treemap",
+ "stacktrace": ".*::allocate std::(_Rb_tree|__1::__tree).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-hashmap",
+ "stacktrace": ".*(std::vector::reserve __gnu_cxx::hashtable|::allocate std::_Hashtable|::allocate std::__1::__hash_table).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-vector",
+ "stacktrace": ".*std::(_Vector_base::_M_allocate|__1::vector::allocate).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-other",
+ "stacktrace": ".*(__gnu_cxx::new_allocator::allocate|std::__1::allocator::allocate).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-catch-all",
+ "stacktrace": ".*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "UNTIL_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total-exclude-profiler",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "anonymous",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-exec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-nonexec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "stack",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "other",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ }
+ ],
+ "version": "POLICY_DEEP_3"
+}
diff --git a/chromium/tools/deep_memory_profiler/policy.android.webview.json b/chromium/tools/deep_memory_profiler/policy.android.webview.json
new file mode 100644
index 00000000000..d3611ce8431
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policy.android.webview.json
@@ -0,0 +1,639 @@
+{
+ "components": [
+ "second",
+ "mmap-profiler",
+ "mmap-type-profiler",
+ "mmap-tcmalloc",
+ "FROM_HERE_FOR_TOTAL",
+ "mustbezero",
+ "unhooked-absent",
+ "unhooked-ashmem-dalvik-heap",
+ "unhooked-ashmem-dalvik-LinearAlloc",
+ "unhooked-ashmem-dalvik-aux-structure",
+ "unhooked-ashmem-dalvik-bitmap",
+ "unhooked-ashmem-dalvik-other",
+ "unhooked-pvrsrvkm",
+ "unhooked-system-dex",
+ "unhooked-chrome-dex",
+ "unhooked-other-ashmem",
+ "unhooked-anonymous",
+ "unhooked-file-exec-lib-chrome",
+ "unhooked-file-exec",
+ "unhooked-file-nonexec-lib-chrome",
+ "unhooked-file-nonexec",
+ "unhooked-stack",
+ "unhooked-other",
+ "no-bucket",
+ "mmap-v8-heap-newspace",
+ "mmap-v8-heap-coderange",
+ "mmap-v8-heap-pagedspace",
+ "mmap-v8-other",
+ "mmap-gpu-mappedmemorymanager",
+ "mmap-gpu-command-ringbuffer",
+ "mmap-gpu-transfer-ringbuffer",
+ "mmap-gpu-gles2-createbuffer",
+ "mmap-skia-font",
+ "mmap-catch-all",
+ "tc-disk_cache-backing",
+ "tc-disk_cache-other",
+ "tc-sqlite3MemAlloc",
+ "tc-angle",
+ "tc-crypto",
+ "tc-net-iobuffer",
+ "tc-stl-string",
+ "tc-stl-rbtree",
+ "tc-stl-vector",
+ "tc-stl-hashtable",
+ "tc-stl-node",
+ "tc-webcore-fontcache",
+ "tc-skia",
+ "tc-renderobject",
+ "tc-renderstyle",
+ "tc-webcore-sharedbuf",
+ "tc-webcore-XHRcreate",
+ "tc-webcore-XHRreceived",
+ "tc-webcore-docwriter-add",
+ "tc-webcore-node-and-doc",
+ "tc-webcore-node-factory",
+ "tc-webcore-element-wrapper",
+ "tc-webcore-stylepropertyset",
+ "tc-webcore-style-createsheet",
+ "tc-webcore-cachedresource",
+ "tc-webcore-script-execute",
+ "tc-webcore-events-related",
+ "tc-webcore-document-write",
+ "tc-webcore-node-create-renderer",
+ "tc-webcore-render-catch-all",
+ "tc-webcore-setInnerHTML-except-node",
+ "tc-wtf-StringImpl-user-catch-all",
+ "tc-wtf-HashTable-user-catch-all",
+ "tc-webcore-everything-create",
+ "tc-webkit-from-v8-catch-all",
+ "tc-webkit-catch-all",
+ "tc-v8-catch-all",
+ "tc-toplevel-string",
+ "tc-std-treemap",
+ "tc-std-hashmap",
+ "tc-std-vector",
+ "tc-std-other",
+ "tc-catch-all",
+ "tc-unused",
+ "UNTIL_HERE_FOR_TOTAL",
+ "total-exclude-profiler",
+ "total",
+ "absent",
+ "anonymous",
+ "file-exec",
+ "file-nonexec",
+ "stack",
+ "other",
+ "mmap-total-log",
+ "mmap-no-log",
+ "mmap-total-record",
+ "other-total-log",
+ "tc-total-log",
+ "tc-no-log",
+ "tc-total-record",
+ "tc-total"
+ ],
+ "rules": [
+ {
+ "name": "second",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mmap-profiler",
+ "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-type-profiler",
+ "stacktrace": ".*(TypeProfilerMalloc).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "FROM_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mustbezero",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-heap",
+ "mappedpathname": "/dev/ashmem/dalvik-heap.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-LinearAlloc",
+ "mappedpathname": "/dev/ashmem/dalvik-LinearAlloc.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-aux-structure",
+ "mappedpathname": "/dev/ashmem/dalvik-aux-structure.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-bitmap",
+ "mappedpathname": "/dev/ashmem/dalvik-bitmap.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-ashmem-dalvik-other",
+ "mappedpathname": "/dev/ashmem/dalvik.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-pvrsrvkm",
+ "mappedpathname": "/dev/pvrsrvkm.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-system-dex",
+ "mappedpathname": "/data/dalvik-cache/system.*.dex.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-chrome-dex",
+ "mappedpathname": "^/.*?(chrome|content).*?apk@classes.dex",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other-ashmem",
+ "mappedpathname": "/dev/ashmem/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mappedpathname": "^$",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec-lib-chrome",
+ "mappedpathname": "^/.*?(chromeview|content).*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mappedpathname": "^/.*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec-lib-chrome",
+ "mappedpathname": "^/.*?(chromeview|content).*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-stack",
+ "mappedpathname": ".stack.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other",
+ "mappedpathname": ".*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "mmap-v8-heap-newspace",
+ "stacktrace": ".*v8::internal::NewSpace::SetUp.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-heap-coderange",
+ "stacktrace": ".*v8::internal::CodeRange::SetUp.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-heap-pagedspace",
+ "stacktrace": ".*v8::internal::PagedSpace::AllocateRaw.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-other",
+ "stacktrace": ".*v8::.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-mappedmemorymanager",
+ "stacktrace": ".*gpu::MappedMemoryManager::Alloc.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-command-ringbuffer",
+ "stacktrace": ".*gpu::CommandBufferHelper::AllocateRingBuffer.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-transfer-ringbuffer",
+ "stacktrace": ".*gpu::TransferBuffer::AllocateRingBuffer.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-gpu-gles2-createbuffer",
+ "stacktrace": ".*gpu::gles2::BufferTracker::CreateBuffer.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-skia-font",
+ "stacktrace": ".*SkTypeface::openStream.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-catch-all",
+ "stacktrace": ".*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "tc-disk_cache-backing",
+ "stacktrace": ".*disk_cache::BackendImpl::InitBackingStore.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-disk_cache-other",
+ "stacktrace": ".*disk_cache::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-sqlite3MemAlloc",
+ "stacktrace": ".*sqlite3MemMalloc.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-angle",
+ "stacktrace": ".*TPoolAllocator::allocate.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-crypto",
+ "stacktrace": ".*(CRYPTO_malloc|CRYPTO_realloc).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-net-iobuffer",
+ "stacktrace": ".*net::IOBuffer::IOBuffer.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-string",
+ "stacktrace": ".*std::basic_string::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-rbtree",
+ "stacktrace": ".*std::priv::_Rb_tree::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-vector",
+ "stacktrace": ".*std::priv::_Impl_vector::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-hashtable",
+ "stacktrace": ".*std::hashtable::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-stl-node",
+ "stacktrace": ".*std::priv::_Impl_vector::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-fontcache",
+ "stacktrace": ".*WebCore::FontCache::getCachedFontData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-skia",
+ "stacktrace": ".* Sk[A-Za-z_]+::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderobject",
+ "stacktrace": ".*WebCore::RenderArena::allocate.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderstyle",
+ "stacktrace": ".*WebCore::RenderStyle::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderstyle",
+ "stacktrace": ".*WebCore::RenderStyle::clone.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::buffer.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::append.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-XHRcreate",
+ "stacktrace": ".*WebCore::XMLHttpRequest::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-XHRreceived",
+ "stacktrace": ".*WebCore::XMLHttpRequest::didReceiveData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-docwriter-add",
+ "stacktrace": ".*WebCore::DocumentWriter::addData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Element::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Text::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Comment::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::HTMLDocument::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::CSSStyleRule::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Attribute::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::DOMWindow::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-factory",
+ "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Factory::create[a-zA-Z0-9_]*Element.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-element-wrapper",
+ "stacktrace": ".*WebCore::createHTML[a-zA-Z0-9_]*ElementWrapper.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-stylepropertyset",
+ "stacktrace": ".*WebCore::StylePropertySet::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-style-createsheet",
+ "stacktrace": ".*WebCore::StyleElement::createSheet.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-cachedresource",
+ "stacktrace": ".*WebCore::CachedResource::data .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-cachedresource",
+ "stacktrace": ".*WebCore::CachedResource::load .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-script-execute",
+ "stacktrace": ".*WebCore::ScriptElement::execute.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::createAttributeEventListener.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::V8LazyEventListener::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::V8EventListener::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::Event::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::EventListener::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-document-write",
+ "stacktrace": ".*WebCore::Document::write.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-create-renderer",
+ "stacktrace": ".*WebCore::Node::createRendererIfNeeded.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderLayer.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderBlock.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderWidget.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderView.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderViewImpl.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderStyle.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderText.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".* RendererMain .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-setInnerHTML-except-node",
+ "stacktrace": ".*WebCore::HTMLElement::setInnerHTML.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-StringImpl-user-catch-all",
+ "stacktrace": ".*WTF::StringImpl::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-StringImpl-user-catch-all",
+ "stacktrace": ".*WTF::StringImpl::createUninitialized.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-HashTable-user-catch-all",
+ "stacktrace": ".*WTF::HashTable::allocateTable.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-everything-create",
+ "stacktrace": ".*WebCore::[a-zA-Z0-9_]*::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webkit-from-v8-catch-all",
+ "stacktrace": ".*(WTF::|WebCore::|WebKit::).*v8::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webkit-catch-all",
+ "stacktrace": ".*(WTF::|WebCore::|WebKit::).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-v8-catch-all",
+ "stacktrace": ".*v8::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-toplevel-string",
+ "stacktrace": "std::basic_string::_Rep::_S_create",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-treemap",
+ "stacktrace": ".*::allocate std::(_Rb_tree|__1::__tree).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-hashmap",
+ "stacktrace": ".*(std::vector::reserve __gnu_cxx::hashtable|::allocate std::_Hashtable|::allocate std::__1::__hash_table).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-vector",
+ "stacktrace": ".*std::(_Vector_base::_M_allocate|__1::vector::allocate).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-other",
+ "stacktrace": ".*(__gnu_cxx::new_allocator::allocate|std::__1::allocator::allocate).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-catch-all",
+ "stacktrace": ".*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "UNTIL_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total-exclude-profiler",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "anonymous",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-exec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-nonexec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "stack",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "other",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ }
+ ],
+ "version": "POLICY_DEEP_3"
+}
diff --git a/chromium/tools/deep_memory_profiler/policy.l0.json b/chromium/tools/deep_memory_profiler/policy.l0.json
new file mode 100644
index 00000000000..14eeb9f3ec7
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policy.l0.json
@@ -0,0 +1,162 @@
+{
+ "components": [
+ "second",
+ "mmap-profiler",
+ "mmap-type-profiler",
+ "mmap-tcmalloc",
+ "FROM_HERE_FOR_TOTAL",
+ "mustbezero",
+ "unhooked-absent",
+ "unhooked-anonymous",
+ "unhooked-file-exec",
+ "unhooked-file-nonexec",
+ "unhooked-stack",
+ "unhooked-other",
+ "no-bucket",
+ "mmap-v8",
+ "mmap-catch-all",
+ "tc-used-all",
+ "tc-unused",
+ "UNTIL_HERE_FOR_TOTAL",
+ "total-exclude-profiler",
+ "total",
+ "absent",
+ "anonymous",
+ "file-exec",
+ "file-nonexec",
+ "stack",
+ "other",
+ "mmap-total-log",
+ "mmap-no-log",
+ "mmap-total-record",
+ "other-total-log",
+ "tc-total-log",
+ "tc-no-log",
+ "tc-total-record",
+ "tc-total"
+ ],
+ "rules": [
+ {
+ "name": "second",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mmap-profiler",
+ "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-type-profiler",
+ "stacktrace": ".*(TypeProfilerMalloc).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "FROM_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mustbezero",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mappedpathname": "^$",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mappedpathname": "^/.*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-stack",
+ "mappedpathname": ".stack.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other",
+ "mappedpathname": ".*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "mmap-v8",
+ "stacktrace": ".*v8::.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-catch-all",
+ "stacktrace": ".*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "tc-used-all",
+ "stacktrace": ".*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "UNTIL_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total-exclude-profiler",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "anonymous",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-exec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-nonexec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "stack",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "other",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ }
+ ],
+ "version": "POLICY_DEEP_3"
+}
diff --git a/chromium/tools/deep_memory_profiler/policy.l1.json b/chromium/tools/deep_memory_profiler/policy.l1.json
new file mode 100644
index 00000000000..599c540693e
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policy.l1.json
@@ -0,0 +1,204 @@
+{
+ "components": [
+ "second",
+ "mmap-profiler",
+ "mmap-type-profiler",
+ "mmap-tcmalloc",
+ "FROM_HERE_FOR_TOTAL",
+ "mustbezero",
+ "unhooked-absent",
+ "unhooked-anonymous",
+ "unhooked-file-exec",
+ "unhooked-file-nonexec",
+ "unhooked-stack",
+ "unhooked-other",
+ "no-bucket",
+ "mmap-v8-heap-newspace",
+ "mmap-v8-heap-coderange",
+ "mmap-v8-heap-pagedspace",
+ "mmap-v8-other",
+ "mmap-catch-all",
+ "tc-v8",
+ "tc-skia",
+ "tc-webkit-catch-all",
+ "tc-unknown-string",
+ "tc-catch-all",
+ "tc-unused",
+ "UNTIL_HERE_FOR_TOTAL",
+ "total-exclude-profiler",
+ "total",
+ "absent",
+ "anonymous",
+ "file-exec",
+ "file-nonexec",
+ "stack",
+ "other",
+ "mmap-total-log",
+ "mmap-no-log",
+ "mmap-total-record",
+ "other-total-log",
+ "tc-total-log",
+ "tc-no-log",
+ "tc-total-record",
+ "tc-total"
+ ],
+ "rules": [
+ {
+ "name": "second",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mmap-profiler",
+ "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-type-profiler",
+ "stacktrace": ".*(TypeProfilerMalloc).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "FROM_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mustbezero",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mappedpathname": "^$",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mappedpathname": "^/.*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-stack",
+ "mappedpathname": ".stack.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other",
+ "mappedpathname": ".*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "mmap-v8-heap-newspace",
+ "stacktrace": ".*v8::internal::NewSpace::SetUp.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-heap-coderange",
+ "stacktrace": ".*v8::internal::CodeRange::SetUp.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-heap-pagedspace",
+ "stacktrace": ".*v8::internal::PagedSpace::AllocateRaw.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-other",
+ "stacktrace": ".*v8::.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-catch-all",
+ "stacktrace": ".*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "tc-v8",
+ "stacktrace": ".*v8::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-skia",
+ "stacktrace": ".*Sk[A-Za-z_]+::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webkit-catch-all",
+ "stacktrace": ".*(WTF::|WebCore::|WebKit::).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-unknown-string",
+ "stacktrace": ".*std::basic_string::_Rep::_S_create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-catch-all",
+ "stacktrace": ".*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "UNTIL_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total-exclude-profiler",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "anonymous",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-exec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-nonexec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "stack",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "other",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ }
+ ],
+ "version": "POLICY_DEEP_3"
+}
diff --git a/chromium/tools/deep_memory_profiler/policy.l2.json b/chromium/tools/deep_memory_profiler/policy.l2.json
new file mode 100644
index 00000000000..f0a007b133d
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policy.l2.json
@@ -0,0 +1,490 @@
+{
+ "components": [
+ "second",
+ "mmap-profiler",
+ "mmap-type-profiler",
+ "mmap-tcmalloc",
+ "FROM_HERE_FOR_TOTAL",
+ "mustbezero",
+ "unhooked-absent",
+ "unhooked-anonymous",
+ "unhooked-file-exec",
+ "unhooked-file-nonexec-others",
+ "unhooked-file-nonexec-group",
+ "unhooked-file-nonexec",
+ "unhooked-stack",
+ "unhooked-other",
+ "no-bucket",
+ "mmap-v8-heap-newspace",
+ "mmap-v8-heap-coderange",
+ "mmap-v8-heap-pagedspace",
+ "mmap-v8-other",
+ "mmap-catch-all",
+ "tc-webcore-fontcache",
+ "tc-skia",
+ "tc-renderobject",
+ "tc-renderstyle",
+ "tc-webcore-sharedbuf",
+ "tc-webcore-XHRcreate",
+ "tc-webcore-XHRreceived",
+ "tc-webcore-docwriter-add",
+ "tc-webcore-node-and-doc",
+ "tc-webcore-node-factory",
+ "tc-webcore-element-wrapper",
+ "tc-webcore-stylepropertyset",
+ "tc-webcore-style-createsheet",
+ "tc-webcore-cachedresource",
+ "tc-webcore-script-execute",
+ "tc-webcore-events-related",
+ "tc-webcore-document-write",
+ "tc-webcore-node-create-renderer",
+ "tc-webcore-render-catch-all",
+ "tc-webcore-setInnerHTML-except-node",
+ "tc-wtf-StringImpl-user-catch-all",
+ "tc-wtf-HashTable-user-catch-all",
+ "tc-webcore-everything-create",
+ "tc-webkit-from-v8-catch-all",
+ "tc-webkit-catch-all",
+ "tc-v8-catch-all",
+ "tc-toplevel-string",
+ "tc-std-treemap",
+ "tc-std-hashmap",
+ "tc-std-vector",
+ "tc-std-other",
+ "tc-catch-all",
+ "tc-unused",
+ "UNTIL_HERE_FOR_TOTAL",
+ "total-exclude-profiler",
+ "total",
+ "absent",
+ "anonymous",
+ "file-exec",
+ "file-nonexec",
+ "stack",
+ "other",
+ "mmap-total-log",
+ "mmap-no-log",
+ "mmap-total-record",
+ "other-total-log",
+ "tc-total-log",
+ "tc-no-log",
+ "tc-total-record",
+ "tc-total"
+ ],
+ "rules": [
+ {
+ "name": "second",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mmap-profiler",
+ "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-type-profiler",
+ "stacktrace": ".*(TypeProfilerMalloc).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "FROM_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mustbezero",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mappedpathname": "^$",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mappedpathname": "^/.*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec-others",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked",
+ "sharedwith": ["others"]
+ },
+ {
+ "name": "unhooked-file-nonexec-group",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked",
+ "sharedwith": ["group"]
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-stack",
+ "mappedpathname": ".stack.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other",
+ "mappedpathname": ".*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "mmap-v8-heap-newspace",
+ "stacktrace": ".*v8::internal::NewSpace::SetUp.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-heap-coderange",
+ "stacktrace": ".*v8::internal::CodeRange::SetUp.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-heap-pagedspace",
+ "stacktrace": ".*v8::internal::PagedSpace::AllocateRaw.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-v8-other",
+ "stacktrace": ".*v8::.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-catch-all",
+ "stacktrace": ".*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "tc-webcore-fontcache",
+ "stacktrace": ".*WebCore::FontCache::getCachedFontData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-skia",
+ "stacktrace": ".* Sk[A-Za-z_]+::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderobject",
+ "stacktrace": ".*WebCore::RenderArena::allocate.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderstyle",
+ "stacktrace": ".*WebCore::RenderStyle::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-renderstyle",
+ "stacktrace": ".*WebCore::RenderStyle::clone.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::buffer.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "stacktrace": ".*WebCore::SharedBuffer::append.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-XHRcreate",
+ "stacktrace": ".*WebCore::XMLHttpRequest::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-XHRreceived",
+ "stacktrace": ".*WebCore::XMLHttpRequest::didReceiveData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-docwriter-add",
+ "stacktrace": ".*WebCore::DocumentWriter::addData.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Element::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Text::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Comment::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::HTMLDocument::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::CSSStyleRule::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::Attribute::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "stacktrace": ".*WebCore::DOMWindow::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-factory",
+ "stacktrace": ".*WebCore::HTML[a-zA-Z0-9_]*Factory::create[a-zA-Z0-9_]*Element.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-element-wrapper",
+ "stacktrace": ".*WebCore::createHTML[a-zA-Z0-9_]*ElementWrapper.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-stylepropertyset",
+ "stacktrace": ".*WebCore::StylePropertySet::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-style-createsheet",
+ "stacktrace": ".*WebCore::StyleElement::createSheet.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-cachedresource",
+ "stacktrace": ".*WebCore::CachedResource::data .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-cachedresource",
+ "stacktrace": ".*WebCore::CachedResource::load .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-script-execute",
+ "stacktrace": ".*WebCore::ScriptElement::execute.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::createAttributeEventListener.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::V8LazyEventListener::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::V8EventListener::create.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::Event::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "stacktrace": ".*WebCore::EventListener::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-document-write",
+ "stacktrace": ".*WebCore::Document::write.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-node-create-renderer",
+ "stacktrace": ".*WebCore::Node::createRendererIfNeeded.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderLayer.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderBlock.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderWidget.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderView.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderViewImpl.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderStyle.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".*WebCore::RenderText.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "stacktrace": ".* RendererMain .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-setInnerHTML-except-node",
+ "stacktrace": ".*WebCore::HTMLElement::setInnerHTML.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-StringImpl-user-catch-all",
+ "stacktrace": ".*WTF::StringImpl::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-StringImpl-user-catch-all",
+ "stacktrace": ".*WTF::StringImpl::createUninitialized.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-wtf-HashTable-user-catch-all",
+ "stacktrace": ".*WTF::HashTable::allocateTable.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore-everything-create",
+ "stacktrace": ".*WebCore::[a-zA-Z0-9_]*::create .*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webkit-from-v8-catch-all",
+ "stacktrace": ".*(WTF::|WebCore::|WebKit::).*v8::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webkit-catch-all",
+ "stacktrace": ".*(WTF::|WebCore::|WebKit::).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-v8-catch-all",
+ "stacktrace": ".*v8::.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-toplevel-string",
+ "stacktrace": "std::basic_string::_Rep::_S_create",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-treemap",
+ "stacktrace": ".*::allocate std::(_Rb_tree|__1::__tree).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-hashmap",
+ "stacktrace": ".*(std::vector::reserve __gnu_cxx::hashtable|::allocate std::_Hashtable|::allocate std::__1::__hash_table).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-vector",
+ "stacktrace": ".*std::(_Vector_base::_M_allocate|__1::vector::allocate).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-std-other",
+ "stacktrace": ".*(__gnu_cxx::new_allocator::allocate|std::__1::allocator::allocate).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-catch-all",
+ "stacktrace": ".*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "UNTIL_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total-exclude-profiler",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "anonymous",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-exec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-nonexec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "stack",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "other",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ }
+ ],
+ "version": "POLICY_DEEP_3"
+}
diff --git a/chromium/tools/deep_memory_profiler/policy.sourcefile.json b/chromium/tools/deep_memory_profiler/policy.sourcefile.json
new file mode 100644
index 00000000000..7a037e5973f
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policy.sourcefile.json
@@ -0,0 +1,186 @@
+{
+ "components": [
+ "second",
+ "mmap-profiler",
+ "mmap-type-profiler",
+ "mmap-tcmalloc",
+ "FROM_HERE_FOR_TOTAL",
+ "mustbezero",
+ "unhooked-absent",
+ "unhooked-anonymous",
+ "unhooked-file-exec",
+ "unhooked-file-nonexec",
+ "unhooked-stack",
+ "unhooked-other",
+ "no-bucket",
+ "mmap-v8",
+ "mmap-catch-all",
+ "tc-v8",
+ "tc-skia",
+ "tc-webcore",
+ "tc-webkit",
+ "tc-catch-all",
+ "tc-unused",
+ "UNTIL_HERE_FOR_TOTAL",
+ "total-exclude-profiler",
+ "total",
+ "absent",
+ "anonymous",
+ "file-exec",
+ "file-nonexec",
+ "stack",
+ "other",
+ "mmap-total-log",
+ "mmap-no-log",
+ "mmap-total-record",
+ "other-total-log",
+ "tc-total-log",
+ "tc-no-log",
+ "tc-total-record",
+ "tc-total"
+ ],
+ "rules": [
+ {
+ "name": "second",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mmap-profiler",
+ "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-type-profiler",
+ "stacktrace": ".*(TypeProfilerMalloc).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "FROM_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mustbezero",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mappedpathname": "^$",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mappedpathname": "^/.*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-stack",
+ "mappedpathname": ".stack.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other",
+ "mappedpathname": ".*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "mmap-v8",
+ "stacksourcefile": ".*\\.\\./\\.\\./v8/src/.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-catch-all",
+ "stacksourcefile": ".*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "tc-v8",
+ "stacksourcefile": ".*\\.\\./\\.\\./v8/src/.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-skia",
+ "stacksourcefile": ".*\\.\\./\\.\\./third_party/skia/src/.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webcore",
+ "stacksourcefile": ".*\\.\\./\\.\\./third_party/WebKit/Source/WebCore/.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-webkit",
+ "stacksourcefile": ".*\\.\\./\\.\\./third_party/WebKit/Source/.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-catch-all",
+ "stacksourcefile": ".*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "UNTIL_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total-exclude-profiler",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "anonymous",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-exec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-nonexec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "stack",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "other",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ }
+ ],
+ "version": "POLICY_DEEP_3"
+}
diff --git a/chromium/tools/deep_memory_profiler/policy.t0.json b/chromium/tools/deep_memory_profiler/policy.t0.json
new file mode 100644
index 00000000000..fd716babe0a
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/policy.t0.json
@@ -0,0 +1,205 @@
+{
+ "components": [
+ "second",
+ "mmap-profiler",
+ "mmap-type-profiler",
+ "mmap-tcmalloc",
+ "FROM_HERE_FOR_TOTAL",
+ "mustbezero",
+ "unhooked-absent",
+ "unhooked-anonymous",
+ "unhooked-file-exec",
+ "unhooked-file-nonexec",
+ "unhooked-stack",
+ "unhooked-other",
+ "no-bucket",
+ "mmap-v8",
+ "mmap-catch-all",
+ "tc-std-string",
+ "tc-WTF-String",
+ "tc-no-typeinfo-StringImpl",
+ "tc-Skia",
+ "tc-WebCore-Style",
+ "tc-no-typeinfo-other",
+ "tc-other",
+ "tc-unused",
+ "UNTIL_HERE_FOR_TOTAL",
+ "total-exclude-profiler",
+ "total",
+ "absent",
+ "anonymous",
+ "file-exec",
+ "file-nonexec",
+ "stack",
+ "other",
+ "mmap-total-log",
+ "mmap-no-log",
+ "mmap-total-record",
+ "other-total-log",
+ "tc-total-log",
+ "tc-no-log",
+ "tc-total-record",
+ "tc-total"
+ ],
+ "rules": [
+ {
+ "name": "second",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mmap-profiler",
+ "stacktrace": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-type-profiler",
+ "stacktrace": ".*(TypeProfilerMalloc).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "stacktrace": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "FROM_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "mustbezero",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mappedpathname": "^$",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mappedpathname": "^/.*",
+ "mappedpermission": "..x.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mappedpathname": "^/.*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-stack",
+ "mappedpathname": ".stack.",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "unhooked-other",
+ "mappedpathname": ".*",
+ "allocator": "unhooked"
+ },
+ {
+ "name": "mmap-v8",
+ "stacktrace": ".*v8::.*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "mmap-catch-all",
+ "stacktrace": ".*",
+ "allocator": "mmap"
+ },
+ {
+ "name": "tc-std-string",
+ "stacktrace": ".*",
+ "typeinfo": "std::basic_string.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-WTF-String",
+ "stacktrace": ".*",
+ "typeinfo": "WTF::String.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-no-typeinfo-StringImpl",
+ "stacktrace": ".*WTF::StringImpl::getData16SlowCase.*",
+ "typeinfo": "no typeinfo",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-Skia",
+ "stacktrace": ".*",
+ "typeinfo": "(skia::|SkGlyph).*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-WebCore-Style",
+ "stacktrace": ".*",
+ "typeinfo": "WebCore::Style.*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-no-typeinfo-other",
+ "stacktrace": ".*",
+ "typeinfo": "no typeinfo",
+ "allocator": "malloc"
+ },
+ {
+ "name": "tc-other",
+ "stacktrace": ".*",
+ "typeinfo": ".*",
+ "allocator": "malloc"
+ },
+ {
+ "name": "UNTIL_HERE_FOR_TOTAL",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total-exclude-profiler",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "total",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "absent",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "anonymous",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-exec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "file-nonexec",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "stack",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ },
+ {
+ "name": "other",
+ "stacktrace": "optional",
+ "allocator": "optional"
+ }
+ ],
+ "version": "POLICY_DEEP_4"
+}
diff --git a/chromium/tools/deep_memory_profiler/sorter.malloc-component.json b/chromium/tools/deep_memory_profiler/sorter.malloc-component.json
new file mode 100644
index 00000000000..c5c809507ae
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/sorter.malloc-component.json
@@ -0,0 +1,261 @@
+{
+ "type": "sorter",
+ "version": 1,
+ "world": "malloc",
+ "name": "component",
+ "order": {
+ "preset1": [
+ "tc-webcore-fontcache",
+ "tc-skia",
+ "tc-renderobject",
+ "tc-renderstyle",
+ "tc-webcore-sharedbuf",
+ "tc-webcore-XHRcreate",
+ "tc-webcore-XHRreceived",
+ "tc-webcore-docwriter-add",
+ "tc-webcore-node-and-doc",
+ "tc-webcore-node-factory",
+ "tc-webcore-element-wrapper",
+ "tc-webcore-stylepropertyset",
+ "tc-webcore-style-createsheet",
+ "tc-webcore-cachedresource",
+ "tc-webcore-script-execute",
+ "tc-webcore-events-related",
+ "tc-webcore-document-write",
+ "tc-webcore-node-create-renderer",
+ "tc-webcore-render-catch-all",
+ "tc-webcore-setInnerHTML-except-node",
+ "tc-wtf-StringImpl-user-catch-all",
+ "tc-wtf-HashTable-user-catch-all",
+ "tc-webcore-everything-create",
+ "tc-webkit-from-v8-catch-all",
+ "tc-webkit-catch-all",
+ "tc-v8-catch-all",
+ "tc-toplevel-string",
+ "tc-std-treemap",
+ "tc-std-hashmap",
+ "tc-std-vector",
+ "tc-std-other",
+ "tc-catch-all",
+ "tc-unused"
+ ]
+ },
+ "rules": [
+ {
+ "name": "tc-webcore-fontcache",
+ "backtrace_function": ".*WebCore::FontCache::getCachedFontData.*"
+ },
+ {
+ "name": "tc-skia",
+ "backtrace_function": ".* Sk[A-Za-z_]+::.*"
+ },
+ {
+ "name": "tc-renderobject",
+ "backtrace_function": ".*WebCore::RenderArena::allocate.*"
+ },
+ {
+ "name": "tc-renderstyle",
+ "backtrace_function": ".*WebCore::RenderStyle::create.*"
+ },
+ {
+ "name": "tc-renderstyle",
+ "backtrace_function": ".*WebCore::RenderStyle::clone.*"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "backtrace_function": ".*WebCore::SharedBuffer::create.*"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "backtrace_function": ".*WebCore::SharedBuffer::buffer.*"
+ },
+ {
+ "name": "tc-webcore-sharedbuf",
+ "backtrace_function": ".*WebCore::SharedBuffer::append.*"
+ },
+ {
+ "name": "tc-webcore-XHRcreate",
+ "backtrace_function": ".*WebCore::XMLHttpRequest::create .*"
+ },
+ {
+ "name": "tc-webcore-XHRreceived",
+ "backtrace_function": ".*WebCore::XMLHttpRequest::didReceiveData.*"
+ },
+ {
+ "name": "tc-webcore-docwriter-add",
+ "backtrace_function": ".*WebCore::DocumentWriter::addData.*"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "backtrace_function": ".*WebCore::HTML[a-zA-Z0-9_]*Element::create .*"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "backtrace_function": ".*WebCore::Text::create .*"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "backtrace_function": ".*WebCore::Comment::create .*"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "backtrace_function": ".*WebCore::HTMLDocument::create .*"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "backtrace_function": ".*WebCore::CSSStyleRule::create .*"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "backtrace_function": ".*WebCore::Attribute::create .*"
+ },
+ {
+ "name": "tc-webcore-node-and-doc",
+ "backtrace_function": ".*WebCore::DOMWindow::create .*"
+ },
+ {
+ "name": "tc-webcore-node-factory",
+ "backtrace_function": ".*WebCore::HTML[a-zA-Z0-9_]*Factory::create[a-zA-Z0-9_]*Element.*"
+ },
+ {
+ "name": "tc-webcore-element-wrapper",
+ "backtrace_function": ".*WebCore::createHTML[a-zA-Z0-9_]*ElementWrapper.*"
+ },
+ {
+ "name": "tc-webcore-stylepropertyset",
+ "backtrace_function": ".*WebCore::StylePropertySet::create .*"
+ },
+ {
+ "name": "tc-webcore-style-createsheet",
+ "backtrace_function": ".*WebCore::StyleElement::createSheet.*"
+ },
+ {
+ "name": "tc-webcore-cachedresource",
+ "backtrace_function": ".*WebCore::CachedResource::data .*"
+ },
+ {
+ "name": "tc-webcore-cachedresource",
+ "backtrace_function": ".*WebCore::CachedResource::load .*"
+ },
+ {
+ "name": "tc-webcore-script-execute",
+ "backtrace_function": ".*WebCore::ScriptElement::execute.*"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "backtrace_function": ".*WebCore::createAttributeEventListener.*"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "backtrace_function": ".*WebCore::V8LazyEventListener::create.*"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "backtrace_function": ".*WebCore::V8EventListener::create.*"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "backtrace_function": ".*WebCore::Event::create .*"
+ },
+ {
+ "name": "tc-webcore-events-related",
+ "backtrace_function": ".*WebCore::EventListener::create .*"
+ },
+ {
+ "name": "tc-webcore-document-write",
+ "backtrace_function": ".*WebCore::Document::write.*"
+ },
+ {
+ "name": "tc-webcore-node-create-renderer",
+ "backtrace_function": ".*WebCore::Node::createRendererIfNeeded.*"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "backtrace_function": ".*WebCore::RenderLayer.*"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "backtrace_function": ".*WebCore::RenderBlock.*"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "backtrace_function": ".*WebCore::RenderWidget.*"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "backtrace_function": ".*WebCore::RenderView.*"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "backtrace_function": ".*WebCore::RenderViewImpl.*"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "backtrace_function": ".*WebCore::RenderStyle.*"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "backtrace_function": ".*WebCore::RenderText.*"
+ },
+ {
+ "name": "tc-webcore-render-catch-all",
+ "backtrace_function": ".* RendererMain .*"
+ },
+ {
+ "name": "tc-webcore-setInnerHTML-except-node",
+ "backtrace_function": ".*WebCore::HTMLElement::setInnerHTML.*"
+ },
+ {
+ "name": "tc-wtf-StringImpl-user-catch-all",
+ "backtrace_function": ".*WTF::StringImpl::create .*"
+ },
+ {
+ "name": "tc-wtf-StringImpl-user-catch-all",
+ "backtrace_function": ".*WTF::StringImpl::createUninitialized.*"
+ },
+ {
+ "name": "tc-wtf-HashTable-user-catch-all",
+ "backtrace_function": ".*WTF::HashTable::allocateTable.*"
+ },
+ {
+ "name": "tc-webcore-everything-create",
+ "backtrace_function": ".*WebCore::[a-zA-Z0-9_]*::create .*"
+ },
+ {
+ "name": "tc-webkit-from-v8-catch-all",
+ "backtrace_function": ".*(WTF::|WebCore::|WebKit::).*v8::.*"
+ },
+ {
+ "name": "tc-webkit-catch-all",
+ "backtrace_function": ".*(WTF::|WebCore::|WebKit::).*"
+ },
+ {
+ "name": "tc-v8-catch-all",
+ "backtrace_function": ".*v8::.*"
+ },
+ {
+ "name": "tc-toplevel-string",
+ "backtrace_function": "std::basic_string::_Rep::_S_create"
+ },
+ {
+ "name": "tc-std-treemap",
+ "backtrace_function": ".*::allocate std::(_Rb_tree|__1::__tree).*"
+ },
+ {
+ "name": "tc-std-hashmap",
+ "backtrace_function": ".*(std::vector::reserve __gnu_cxx::hashtable|::allocate std::_Hashtable|::allocate std::__1::__hash_table).*"
+ },
+ {
+ "name": "tc-std-vector",
+ "backtrace_function": ".*std::(_Vector_base::_M_allocate|__1::vector::allocate).*"
+ },
+ {
+ "name": "tc-std-other",
+ "backtrace_function": ".*(__gnu_cxx::new_allocator::allocate|std::__1::allocator::allocate).*"
+ },
+ {
+ "name": "tc-catch-all",
+ "backtrace_function": ".*"
+ }
+ ]
+}
diff --git a/chromium/tools/deep_memory_profiler/sorter.malloc-type.json b/chromium/tools/deep_memory_profiler/sorter.malloc-type.json
new file mode 100644
index 00000000000..cc8ee65c6a0
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/sorter.malloc-type.json
@@ -0,0 +1,38 @@
+{
+ "type": "sorter",
+ "version": 1,
+ "world": "malloc",
+ "name": "type",
+ "order": {},
+ "rules": [
+ {
+ "name": "tc-std-string",
+ "typeinfo": "std::basic_string.*"
+ },
+ {
+ "name": "tc-WTF-String",
+ "typeinfo": "WTF::String.*"
+ },
+ {
+ "name": "tc-no-typeinfo-StringImpl",
+ "backtrace_function": ".*WTF::StringImpl::getData16SlowCase.*",
+ "typeinfo": "no typeinfo"
+ },
+ {
+ "name": "tc-Skia",
+ "typeinfo": "(skia::|SkGlyph).*"
+ },
+ {
+ "name": "tc-WebCore-Style",
+ "typeinfo": "WebCore::Style.*"
+ },
+ {
+ "name": "tc-no-typeinfo-other",
+ "typeinfo": "no typeinfo"
+ },
+ {
+ "name": "tc-other",
+ "typeinfo": ".*"
+ }
+ ]
+}
diff --git a/chromium/tools/deep_memory_profiler/sorter.vm-map.json b/chromium/tools/deep_memory_profiler/sorter.vm-map.json
new file mode 100644
index 00000000000..7fc4d27785f
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/sorter.vm-map.json
@@ -0,0 +1,107 @@
+{
+ "type": "sorter",
+ "version": 1,
+ "world": "vm",
+ "name": "map",
+ "root": true,
+ "order": {},
+ "rules": [
+ {
+ "name": "mmap-profiler",
+ "backtrace_function": ".*(ProfilerMalloc|MemoryRegionMap::).*",
+ "mmap": true,
+ "hidden": true
+ },
+ {
+ "name": "mmap-type-profiler",
+ "backtrace_function": ".*(TypeProfilerMalloc).*",
+ "mmap": true,
+ "hidden": true
+ },
+ {
+ "name": "unhooked-anonymous",
+ "mapped_pathname": "^$",
+ "mmap": false
+ },
+ {
+ "name": "unhooked-file-exec",
+ "mapped_pathname": "^/.*",
+ "mapped_permission": "..x.",
+ "mmap": false
+ },
+ {
+ "name": "unhooked-file-nonexec",
+ "mapped_pathname": "^/.*",
+ "mmap": false
+ },
+ {
+ "name": "unhooked-stack",
+ "mapped_pathname": ".stack.",
+ "mmap": false
+ },
+ {
+ "name": "unhooked-other",
+ "mapped_pathname": ".*",
+ "mmap": false
+ },
+ {
+ "name": "mmap-tcmalloc",
+ "backtrace_function": ".*(DoAllocWithArena|SbrkSysAllocator::Alloc|MmapSysAllocator::Alloc|LowLevelAlloc::Alloc|LowLevelAlloc::AllocWithArena).*",
+ "subs": [
+ [ "malloc", "component" ],
+ [ "malloc", "type" ]
+ ],
+ "mmap": true
+ },
+ {
+ "name": "mmap-v8-heap-newspace",
+ "backtrace_function": ".*v8::internal::NewSpace::SetUp.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-v8-heap-coderange",
+ "backtrace_function": ".*v8::internal::CodeRange::SetUp.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-v8-heap-pagedspace",
+ "backtrace_function": ".*v8::internal::PagedSpace::AllocateRaw.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-v8-other",
+ "backtrace_function": ".*v8::.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-gpu-mappedmemorymanager",
+ "backtrace_function": ".*gpu::MappedMemoryManager::Alloc.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-gpu-command-ringbuffer",
+ "backtrace_function": ".*gpu::CommandBufferHelper::AllocateRingBuffer.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-gpu-transfer-ringbuffer",
+ "backtrace_function": ".*gpu::TransferBuffer::AllocateRingBuffer.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-gpu-gles2-createbuffer",
+ "backtrace_function": ".*gpu::gles2::BufferTracker::CreateBuffer.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-skia-font",
+ "backtrace_function": ".*SkTypeface::openStream.*",
+ "mmap": true
+ },
+ {
+ "name": "mmap-catch-all",
+ "backtrace_function": ".*",
+ "mmap": true
+ }
+ ]
+}
diff --git a/chromium/tools/deep_memory_profiler/sorter.vm-sharing.json b/chromium/tools/deep_memory_profiler/sorter.vm-sharing.json
new file mode 100644
index 00000000000..4cb52a61f30
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/sorter.vm-sharing.json
@@ -0,0 +1,25 @@
+{
+ "type": "sorter",
+ "version": 1,
+ "world": "vm",
+ "name": "sharing",
+ "root": true,
+ "order": {},
+ "rules": [
+ {
+ "name": "others",
+ "sharedwith": ["others"]
+ },
+ {
+ "name": "chrome",
+ "sharedwith": ["group"]
+ },
+ {
+ "name": "private",
+ "sharedwith": ["private"]
+ },
+ {
+ "name": "any"
+ }
+ ]
+}
diff --git a/chromium/tools/deep_memory_profiler/subcommands/__init__.py b/chromium/tools/deep_memory_profiler/subcommands/__init__.py
new file mode 100644
index 00000000000..4fb29d0c375
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from subcommands.buckets import BucketsCommand
+from subcommands.cat import CatCommand
+from subcommands.expand import ExpandCommand
+from subcommands.map import MapCommand
+from subcommands.policies import CSVCommand
+from subcommands.policies import JSONCommand
+from subcommands.policies import ListCommand
+from subcommands.pprof import PProfCommand
+from subcommands.stacktrace import StacktraceCommand
+from subcommands.upload import UploadCommand
diff --git a/chromium/tools/deep_memory_profiler/subcommands/buckets.py b/chromium/tools/deep_memory_profiler/subcommands/buckets.py
new file mode 100644
index 00000000000..4ea8640ca9d
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/buckets.py
@@ -0,0 +1,35 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import sys
+
+from lib.subcommand import SubCommand
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class BucketsCommand(SubCommand):
+ def __init__(self):
+ super(BucketsCommand, self).__init__('Usage: %prog buckets <first-dump>')
+
+ def do(self, sys_argv, out=sys.stdout):
+ _, args = self._parse_args(sys_argv, 1)
+ dump_path = args[1]
+ bucket_set = SubCommand.load_basic_files(dump_path, True, True)
+
+ BucketsCommand._output(bucket_set, out)
+ return 0
+
+ @staticmethod
+ def _output(bucket_set, out):
+ """Prints all buckets with resolving symbols.
+
+ Args:
+ bucket_set: A BucketSet object.
+ out: An IO object to output.
+ """
+ for bucket_id, bucket in sorted(bucket_set):
+ out.write('%d: %s\n' % (bucket_id, bucket))
diff --git a/chromium/tools/deep_memory_profiler/subcommands/cat.py b/chromium/tools/deep_memory_profiler/subcommands/cat.py
new file mode 100644
index 00000000000..1e9e5b39d8a
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/cat.py
@@ -0,0 +1,179 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import logging
+import sys
+
+from lib.bucket import BUCKET_ID, COMMITTED, ALLOC_COUNT, FREE_COUNT
+from lib.ordered_dict import OrderedDict
+from lib.subcommand import SubCommand
+from lib.sorter import MallocUnit, MMapUnit, SorterSet, UnhookedUnit, UnitSet
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class CatCommand(SubCommand):
+ def __init__(self):
+ super(CatCommand, self).__init__('Usage: %prog cat <first-dump>')
+ self._parser.add_option('--alternative-dirs', dest='alternative_dirs',
+ metavar='/path/on/target@/path/on/host[:...]',
+ help='Read files in /path/on/host/ instead of '
+ 'files in /path/on/target/.')
+ self._parser.add_option('--indent', dest='indent', action='store_true',
+ help='Indent the output.')
+
+ def do(self, sys_argv):
+ options, args = self._parse_args(sys_argv, 1)
+ dump_path = args[1]
+ # TODO(dmikurube): Support shared memory.
+ alternative_dirs_dict = {}
+ if options.alternative_dirs:
+ for alternative_dir_pair in options.alternative_dirs.split(':'):
+ target_path, host_path = alternative_dir_pair.split('@', 1)
+ alternative_dirs_dict[target_path] = host_path
+ (bucket_set, dumps) = SubCommand.load_basic_files(
+ dump_path, True, alternative_dirs=alternative_dirs_dict)
+
+ # Load all sorters.
+ sorters = SorterSet()
+
+ json_root = OrderedDict()
+ json_root['version'] = 1
+ json_root['run_id'] = None
+ for dump in dumps:
+ if json_root['run_id'] and json_root['run_id'] != dump.run_id:
+ LOGGER.error('Inconsistent heap profile dumps.')
+ json_root['run_id'] = ''
+ break
+ json_root['run_id'] = dump.run_id
+ json_root['roots'] = []
+ for sorter in sorters:
+ if sorter.root:
+ json_root['roots'].append([sorter.world, sorter.name])
+ json_root['default_template'] = 'l2'
+ json_root['templates'] = sorters.templates.as_dict()
+
+ json_root['snapshots'] = []
+
+ for dump in dumps:
+ json_root['snapshots'].append(
+ self._fill_snapshot(dump, bucket_set, sorters))
+
+ if options.indent:
+ json.dump(json_root, sys.stdout, indent=2)
+ else:
+ json.dump(json_root, sys.stdout)
+ print ''
+
+ @staticmethod
+ def _fill_snapshot(dump, bucket_set, sorters):
+ root = OrderedDict()
+ root['time'] = dump.time
+ root['worlds'] = OrderedDict()
+ root['worlds']['vm'] = CatCommand._fill_world(
+ dump, bucket_set, sorters, 'vm')
+ root['worlds']['malloc'] = CatCommand._fill_world(
+ dump, bucket_set, sorters, 'malloc')
+ return root
+
+ @staticmethod
+ def _fill_world(dump, bucket_set, sorters, world):
+ root = OrderedDict()
+
+ root['name'] = world
+ if world == 'vm':
+ root['unit_fields'] = ['size', 'reserved']
+ elif world == 'malloc':
+ root['unit_fields'] = ['size', 'alloc_count', 'free_count']
+
+ # Make { vm | malloc } units with their sizes.
+ root['units'] = OrderedDict()
+ unit_set = UnitSet(world)
+ if world == 'vm':
+ for unit in CatCommand._iterate_vm_unit(dump, None, bucket_set):
+ unit_set.append(unit)
+ for unit in unit_set:
+ root['units'][unit.unit_id] = [unit.committed, unit.reserved]
+ elif world == 'malloc':
+ for unit in CatCommand._iterate_malloc_unit(dump, bucket_set):
+ unit_set.append(unit)
+ for unit in unit_set:
+ root['units'][unit.unit_id] = [
+ unit.size, unit.alloc_count, unit.free_count]
+
+ # Iterate for { vm | malloc } sorters.
+ root['breakdown'] = OrderedDict()
+ for sorter in sorters.iter_world(world):
+ breakdown = OrderedDict()
+ for unit in unit_set:
+ found = sorter.find(unit)
+ if found.name not in breakdown:
+ category = OrderedDict()
+ category['name'] = found.name
+ category['color'] = 'random'
+ subs = []
+ for sub_world, sub_breakdown in found.iter_subs():
+ subs.append([sub_world, sub_breakdown])
+ if subs:
+ category['subs'] = subs
+ if found.hidden:
+ category['hidden'] = True
+ category['units'] = []
+ breakdown[found.name] = category
+ breakdown[found.name]['units'].append(unit.unit_id)
+ root['breakdown'][sorter.name] = breakdown
+
+ return root
+
+ @staticmethod
+ def _iterate_vm_unit(dump, pfn_dict, bucket_set):
+ unit_id = 0
+ for _, region in dump.iter_map:
+ unit_id += 1
+ if region[0] == 'unhooked':
+ if pfn_dict and dump.pageframe_length:
+ for pageframe in region[1]['pageframe']:
+ yield UnhookedUnit(unit_id, pageframe.size, pageframe.size,
+ region, pageframe, pfn_dict)
+ else:
+ yield UnhookedUnit(unit_id,
+ int(region[1]['committed']),
+ int(region[1]['reserved']),
+ region)
+ elif region[0] == 'hooked':
+ if pfn_dict and dump.pageframe_length:
+ for pageframe in region[1]['pageframe']:
+ yield MMapUnit(unit_id,
+ pageframe.size,
+ pageframe.size,
+ region, bucket_set, pageframe, pfn_dict)
+ else:
+ yield MMapUnit(unit_id,
+ int(region[1]['committed']),
+ int(region[1]['reserved']),
+ region,
+ bucket_set)
+ else:
+ LOGGER.error('Unrecognized mapping status: %s' % region[0])
+
+ @staticmethod
+ def _iterate_malloc_unit(dump, bucket_set):
+ for line in dump.iter_stacktrace:
+ words = line.split()
+ bucket = bucket_set.get(int(words[BUCKET_ID]))
+ if bucket and bucket.allocator_type == 'malloc':
+ yield MallocUnit(int(words[BUCKET_ID]),
+ int(words[COMMITTED]),
+ int(words[ALLOC_COUNT]),
+ int(words[FREE_COUNT]),
+ bucket)
+ elif not bucket:
+ # 'Not-found' buckets are all assumed as malloc buckets.
+ yield MallocUnit(int(words[BUCKET_ID]),
+ int(words[COMMITTED]),
+ int(words[ALLOC_COUNT]),
+ int(words[FREE_COUNT]),
+ None)
diff --git a/chromium/tools/deep_memory_profiler/subcommands/expand.py b/chromium/tools/deep_memory_profiler/subcommands/expand.py
new file mode 100644
index 00000000000..4058a001807
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/expand.py
@@ -0,0 +1,104 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import sys
+
+from lib.bucket import BUCKET_ID, COMMITTED, ALLOC_COUNT, FREE_COUNT
+from lib.policy import PolicySet
+from lib.subcommand import SubCommand
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class ExpandCommand(SubCommand):
+ def __init__(self):
+ super(ExpandCommand, self).__init__(
+ 'Usage: %prog expand <dump> <policy> <component> <depth>')
+
+ def do(self, sys_argv):
+ _, args = self._parse_args(sys_argv, 4)
+ dump_path = args[1]
+ target_policy = args[2]
+ component_name = args[3]
+ depth = args[4]
+ (bucket_set, dump) = SubCommand.load_basic_files(dump_path, False)
+ policy_set = PolicySet.load(SubCommand._parse_policy_list(target_policy))
+
+ ExpandCommand._output(dump, policy_set[target_policy], bucket_set,
+ component_name, int(depth), sys.stdout)
+ return 0
+
+ @staticmethod
+ def _output(dump, policy, bucket_set, component_name, depth, out):
+ """Prints all stacktraces in a given component of given depth.
+
+ Args:
+ dump: A Dump object.
+ policy: A Policy object.
+ bucket_set: A BucketSet object.
+ component_name: A name of component for filtering.
+ depth: An integer representing depth to be printed.
+ out: An IO object to output.
+ """
+ sizes = {}
+
+ ExpandCommand._accumulate(
+ dump, policy, bucket_set, component_name, depth, sizes)
+
+ sorted_sizes_list = sorted(
+ sizes.iteritems(), key=(lambda x: x[1]), reverse=True)
+ total = 0
+ # TODO(dmikurube): Better formatting.
+ for size_pair in sorted_sizes_list:
+ out.write('%10d %s\n' % (size_pair[1], size_pair[0]))
+ total += size_pair[1]
+ LOGGER.info('total: %d\n' % total)
+
+ @staticmethod
+ def _add_size(precedence, bucket, depth, committed, sizes):
+ stacktrace_sequence = precedence
+ for function, sourcefile in zip(
+ bucket.symbolized_stackfunction[
+ 0 : min(len(bucket.symbolized_stackfunction), 1 + depth)],
+ bucket.symbolized_stacksourcefile[
+ 0 : min(len(bucket.symbolized_stacksourcefile), 1 + depth)]):
+ stacktrace_sequence += '%s(@%s) ' % (function, sourcefile)
+ if not stacktrace_sequence in sizes:
+ sizes[stacktrace_sequence] = 0
+ sizes[stacktrace_sequence] += committed
+
+ @staticmethod
+ def _accumulate(dump, policy, bucket_set, component_name, depth, sizes):
+ rule = policy.find_rule(component_name)
+ if not rule:
+ pass
+ elif rule.allocator_type == 'malloc':
+ for line in dump.iter_stacktrace:
+ words = line.split()
+ bucket = bucket_set.get(int(words[BUCKET_ID]))
+ if not bucket or bucket.allocator_type == 'malloc':
+ component_match = policy.find_malloc(bucket)
+ elif bucket.allocator_type == 'mmap':
+ continue
+ else:
+ assert False
+ if component_match == component_name:
+ precedence = ''
+ precedence += '(alloc=%d) ' % int(words[ALLOC_COUNT])
+ precedence += '(free=%d) ' % int(words[FREE_COUNT])
+ if bucket.typeinfo:
+ precedence += '(type=%s) ' % bucket.symbolized_typeinfo
+ precedence += '(type.name=%s) ' % bucket.typeinfo_name
+ ExpandCommand._add_size(precedence, bucket, depth,
+ int(words[COMMITTED]), sizes)
+ elif rule.allocator_type == 'mmap':
+ for _, region in dump.iter_map:
+ if region[0] != 'hooked':
+ continue
+ component_match, bucket = policy.find_mmap(region, bucket_set)
+ if component_match == component_name:
+ ExpandCommand._add_size('', bucket, depth,
+ region[1]['committed'], sizes)
diff --git a/chromium/tools/deep_memory_profiler/subcommands/map.py b/chromium/tools/deep_memory_profiler/subcommands/map.py
new file mode 100644
index 00000000000..2237d6f200b
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/map.py
@@ -0,0 +1,102 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import logging
+import sys
+
+from lib.range_dict import ExclusiveRangeDict
+from lib.policy import PolicySet
+from lib.subcommand import SubCommand
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class MapCommand(SubCommand):
+ def __init__(self):
+ super(MapCommand, self).__init__('Usage: %prog map <first-dump> <policy>')
+
+ def do(self, sys_argv, out=sys.stdout):
+ _, args = self._parse_args(sys_argv, 2)
+ dump_path = args[1]
+ target_policy = args[2]
+ (bucket_set, dumps) = SubCommand.load_basic_files(dump_path, True)
+ policy_set = PolicySet.load(SubCommand._parse_policy_list(target_policy))
+
+ MapCommand._output(dumps, bucket_set, policy_set[target_policy], out)
+ return 0
+
+ @staticmethod
+ def _output(dumps, bucket_set, policy, out):
+ """Prints all stacktraces in a given component of given depth.
+
+ Args:
+ dumps: A list of Dump objects.
+ bucket_set: A BucketSet object.
+ policy: A Policy object.
+ out: An IO object to output.
+ """
+ max_dump_count = 0
+ range_dict = ExclusiveRangeDict(ListAttribute)
+ for dump in dumps:
+ max_dump_count = max(max_dump_count, dump.count)
+ for key, value in dump.iter_map:
+ for begin, end, attr in range_dict.iter_range(key[0], key[1]):
+ attr[dump.count] = value
+
+ max_dump_count_digit = len(str(max_dump_count))
+ for begin, end, attr in range_dict.iter_range():
+ out.write('%x-%x\n' % (begin, end))
+ if len(attr) < max_dump_count:
+ attr[max_dump_count] = None
+ for index, value in enumerate(attr[1:]):
+ out.write(' #%0*d: ' % (max_dump_count_digit, index + 1))
+ if not value:
+ out.write('None\n')
+ elif value[0] == 'hooked':
+ component_match, _ = policy.find_mmap(value, bucket_set)
+ out.write('%s @ %d\n' % (component_match, value[1]['bucket_id']))
+ else:
+ component_match = policy.find_unhooked(value)
+ region_info = value[1]
+ size = region_info['committed']
+ out.write('%s [%d bytes] %s%s%s%s %s\n' % (
+ component_match, size, value[1]['vma']['readable'],
+ value[1]['vma']['writable'], value[1]['vma']['executable'],
+ value[1]['vma']['private'], value[1]['vma']['name']))
+
+
+class ListAttribute(ExclusiveRangeDict.RangeAttribute):
+ """Represents a list for an attribute in range_dict.ExclusiveRangeDict."""
+ def __init__(self):
+ super(ListAttribute, self).__init__()
+ self._list = []
+
+ def __str__(self):
+ return str(self._list)
+
+ def __repr__(self):
+ return 'ListAttribute' + str(self._list)
+
+ def __len__(self):
+ return len(self._list)
+
+ def __iter__(self):
+ for x in self._list:
+ yield x
+
+ def __getitem__(self, index):
+ return self._list[index]
+
+ def __setitem__(self, index, value):
+ if index >= len(self._list):
+ self._list.extend([None] * (index + 1 - len(self._list)))
+ self._list[index] = value
+
+ def copy(self):
+ new_list = ListAttribute()
+ for index, item in enumerate(self._list):
+ new_list[index] = copy.deepcopy(item)
+ return new_list
diff --git a/chromium/tools/deep_memory_profiler/subcommands/policies.py b/chromium/tools/deep_memory_profiler/subcommands/policies.py
new file mode 100644
index 00000000000..182959b10f0
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/policies.py
@@ -0,0 +1,375 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import datetime
+import json
+import logging
+import sys
+
+from lib.bucket import BUCKET_ID, COMMITTED
+from lib.pageframe import PFNCounts
+from lib.policy import PolicySet
+from lib.subcommand import SubCommand
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class PolicyCommands(SubCommand):
+ def __init__(self, command):
+ super(PolicyCommands, self).__init__(
+ 'Usage: %%prog %s [-p POLICY] <first-dump> [shared-first-dumps...]' %
+ command)
+ self._parser.add_option('-p', '--policy', type='string', dest='policy',
+ help='profile with POLICY', metavar='POLICY')
+ self._parser.add_option('--alternative-dirs', dest='alternative_dirs',
+ metavar='/path/on/target@/path/on/host[:...]',
+ help='Read files in /path/on/host/ instead of '
+ 'files in /path/on/target/.')
+
+ def _set_up(self, sys_argv):
+ options, args = self._parse_args(sys_argv, 1)
+ dump_path = args[1]
+ shared_first_dump_paths = args[2:]
+ alternative_dirs_dict = {}
+ if options.alternative_dirs:
+ for alternative_dir_pair in options.alternative_dirs.split(':'):
+ target_path, host_path = alternative_dir_pair.split('@', 1)
+ alternative_dirs_dict[target_path] = host_path
+ (bucket_set, dumps) = SubCommand.load_basic_files(
+ dump_path, True, alternative_dirs=alternative_dirs_dict)
+
+ pfn_counts_dict = {}
+ for shared_first_dump_path in shared_first_dump_paths:
+ shared_dumps = SubCommand._find_all_dumps(shared_first_dump_path)
+ for shared_dump in shared_dumps:
+ pfn_counts = PFNCounts.load(shared_dump)
+ if pfn_counts.pid not in pfn_counts_dict:
+ pfn_counts_dict[pfn_counts.pid] = []
+ pfn_counts_dict[pfn_counts.pid].append(pfn_counts)
+
+ policy_set = PolicySet.load(SubCommand._parse_policy_list(options.policy))
+ return policy_set, dumps, pfn_counts_dict, bucket_set
+
+ @staticmethod
+ def _apply_policy(dump, pfn_counts_dict, policy, bucket_set, first_dump_time):
+ """Aggregates the total memory size of each component.
+
+ Iterate through all stacktraces and attribute them to one of the components
+ based on the policy. It is important to apply policy in right order.
+
+ Args:
+ dump: A Dump object.
+ pfn_counts_dict: A dict mapping a pid to a list of PFNCounts.
+ policy: A Policy object.
+ bucket_set: A BucketSet object.
+ first_dump_time: An integer representing time when the first dump is
+ dumped.
+
+ Returns:
+ A dict mapping components and their corresponding sizes.
+ """
+ LOGGER.info(' %s' % dump.path)
+ all_pfn_dict = {}
+ if pfn_counts_dict:
+ LOGGER.info(' shared with...')
+ for pid, pfnset_list in pfn_counts_dict.iteritems():
+ closest_pfnset_index = None
+ closest_pfnset_difference = 1024.0
+ for index, pfnset in enumerate(pfnset_list):
+ time_difference = pfnset.time - dump.time
+ if time_difference >= 3.0:
+ break
+ elif ((time_difference < 0.0 and pfnset.reason != 'Exiting') or
+ (0.0 <= time_difference and time_difference < 3.0)):
+ closest_pfnset_index = index
+ closest_pfnset_difference = time_difference
+ elif time_difference < 0.0 and pfnset.reason == 'Exiting':
+ closest_pfnset_index = None
+ break
+ if closest_pfnset_index:
+ for pfn, count in pfnset_list[closest_pfnset_index].iter_pfn:
+ all_pfn_dict[pfn] = all_pfn_dict.get(pfn, 0) + count
+ LOGGER.info(' %s (time difference = %f)' %
+ (pfnset_list[closest_pfnset_index].path,
+ closest_pfnset_difference))
+ else:
+ LOGGER.info(' (no match with pid:%d)' % pid)
+
+ sizes = dict((c, 0) for c in policy.components)
+
+ PolicyCommands._accumulate_malloc(dump, policy, bucket_set, sizes)
+ verify_global_stats = PolicyCommands._accumulate_maps(
+ dump, all_pfn_dict, policy, bucket_set, sizes)
+
+ # TODO(dmikurube): Remove the verifying code when GLOBAL_STATS is removed.
+ # http://crbug.com/245603.
+ for verify_key, verify_value in verify_global_stats.iteritems():
+ dump_value = dump.global_stat('%s_committed' % verify_key)
+ if dump_value != verify_value:
+ LOGGER.warn('%25s: %12d != %d (%d)' % (
+ verify_key, dump_value, verify_value, dump_value - verify_value))
+
+ sizes['mmap-no-log'] = (
+ dump.global_stat('profiled-mmap_committed') -
+ sizes['mmap-total-log'])
+ sizes['mmap-total-record'] = dump.global_stat('profiled-mmap_committed')
+ sizes['mmap-total-record-vm'] = dump.global_stat('profiled-mmap_virtual')
+
+ sizes['tc-no-log'] = (
+ dump.global_stat('profiled-malloc_committed') -
+ sizes['tc-total-log'])
+ sizes['tc-total-record'] = dump.global_stat('profiled-malloc_committed')
+ sizes['tc-unused'] = (
+ sizes['mmap-tcmalloc'] -
+ dump.global_stat('profiled-malloc_committed'))
+ if sizes['tc-unused'] < 0:
+ LOGGER.warn(' Assuming tc-unused=0 as it is negative: %d (bytes)' %
+ sizes['tc-unused'])
+ sizes['tc-unused'] = 0
+ sizes['tc-total'] = sizes['mmap-tcmalloc']
+
+ # TODO(dmikurube): global_stat will be deprecated.
+ # See http://crbug.com/245603.
+ for key, value in {
+ 'total': 'total_committed',
+ 'filemapped': 'file_committed',
+ 'absent': 'absent_committed',
+ 'file-exec': 'file-exec_committed',
+ 'file-nonexec': 'file-nonexec_committed',
+ 'anonymous': 'anonymous_committed',
+ 'stack': 'stack_committed',
+ 'other': 'other_committed',
+ 'unhooked-absent': 'nonprofiled-absent_committed',
+ 'total-vm': 'total_virtual',
+ 'filemapped-vm': 'file_virtual',
+ 'anonymous-vm': 'anonymous_virtual',
+ 'other-vm': 'other_virtual' }.iteritems():
+ if key in sizes:
+ sizes[key] = dump.global_stat(value)
+
+ if 'mustbezero' in sizes:
+ removed_list = (
+ 'profiled-mmap_committed',
+ 'nonprofiled-absent_committed',
+ 'nonprofiled-anonymous_committed',
+ 'nonprofiled-file-exec_committed',
+ 'nonprofiled-file-nonexec_committed',
+ 'nonprofiled-stack_committed',
+ 'nonprofiled-other_committed')
+ sizes['mustbezero'] = (
+ dump.global_stat('total_committed') -
+ sum(dump.global_stat(removed) for removed in removed_list))
+ if 'total-exclude-profiler' in sizes:
+ sizes['total-exclude-profiler'] = (
+ dump.global_stat('total_committed') -
+ (sizes['mmap-profiler'] + sizes['mmap-type-profiler']))
+ if 'hour' in sizes:
+ sizes['hour'] = (dump.time - first_dump_time) / 60.0 / 60.0
+ if 'minute' in sizes:
+ sizes['minute'] = (dump.time - first_dump_time) / 60.0
+ if 'second' in sizes:
+ sizes['second'] = dump.time - first_dump_time
+
+ return sizes
+
+ @staticmethod
+ def _accumulate_malloc(dump, policy, bucket_set, sizes):
+ for line in dump.iter_stacktrace:
+ words = line.split()
+ bucket = bucket_set.get(int(words[BUCKET_ID]))
+ if not bucket or bucket.allocator_type == 'malloc':
+ component_match = policy.find_malloc(bucket)
+ elif bucket.allocator_type == 'mmap':
+ continue
+ else:
+ assert False
+ sizes[component_match] += int(words[COMMITTED])
+
+ assert not component_match.startswith('mmap-')
+ if component_match.startswith('tc-'):
+ sizes['tc-total-log'] += int(words[COMMITTED])
+ else:
+ sizes['other-total-log'] += int(words[COMMITTED])
+
+ @staticmethod
+ def _accumulate_maps(dump, pfn_dict, policy, bucket_set, sizes):
+ # TODO(dmikurube): Remove the dict when GLOBAL_STATS is removed.
+ # http://crbug.com/245603.
+ global_stats = {
+ 'total': 0,
+ 'file-exec': 0,
+ 'file-nonexec': 0,
+ 'anonymous': 0,
+ 'stack': 0,
+ 'other': 0,
+ 'nonprofiled-file-exec': 0,
+ 'nonprofiled-file-nonexec': 0,
+ 'nonprofiled-anonymous': 0,
+ 'nonprofiled-stack': 0,
+ 'nonprofiled-other': 0,
+ 'profiled-mmap': 0,
+ }
+
+ for key, value in dump.iter_map:
+ # TODO(dmikurube): Remove the subtotal code when GLOBAL_STATS is removed.
+ # It's temporary verification code for transition described in
+ # http://crbug.com/245603.
+ committed = 0
+ if 'committed' in value[1]:
+ committed = value[1]['committed']
+ global_stats['total'] += committed
+ key = 'other'
+ name = value[1]['vma']['name']
+ if name.startswith('/'):
+ if value[1]['vma']['executable'] == 'x':
+ key = 'file-exec'
+ else:
+ key = 'file-nonexec'
+ elif name == '[stack]':
+ key = 'stack'
+ elif name == '':
+ key = 'anonymous'
+ global_stats[key] += committed
+ if value[0] == 'unhooked':
+ global_stats['nonprofiled-' + key] += committed
+ if value[0] == 'hooked':
+ global_stats['profiled-mmap'] += committed
+
+ if value[0] == 'unhooked':
+ if pfn_dict and dump.pageframe_length:
+ for pageframe in value[1]['pageframe']:
+ component_match = policy.find_unhooked(value, pageframe, pfn_dict)
+ sizes[component_match] += pageframe.size
+ else:
+ component_match = policy.find_unhooked(value)
+ sizes[component_match] += int(value[1]['committed'])
+ elif value[0] == 'hooked':
+ if pfn_dict and dump.pageframe_length:
+ for pageframe in value[1]['pageframe']:
+ component_match, _ = policy.find_mmap(
+ value, bucket_set, pageframe, pfn_dict)
+ sizes[component_match] += pageframe.size
+ assert not component_match.startswith('tc-')
+ if component_match.startswith('mmap-'):
+ sizes['mmap-total-log'] += pageframe.size
+ else:
+ sizes['other-total-log'] += pageframe.size
+ else:
+ component_match, _ = policy.find_mmap(value, bucket_set)
+ sizes[component_match] += int(value[1]['committed'])
+ if component_match.startswith('mmap-'):
+ sizes['mmap-total-log'] += int(value[1]['committed'])
+ else:
+ sizes['other-total-log'] += int(value[1]['committed'])
+ else:
+ LOGGER.error('Unrecognized mapping status: %s' % value[0])
+
+ return global_stats
+
+
+class CSVCommand(PolicyCommands):
+ def __init__(self):
+ super(CSVCommand, self).__init__('csv')
+
+ def do(self, sys_argv):
+ policy_set, dumps, pfn_counts_dict, bucket_set = self._set_up(sys_argv)
+ return CSVCommand._output(
+ policy_set, dumps, pfn_counts_dict, bucket_set, sys.stdout)
+
+ @staticmethod
+ def _output(policy_set, dumps, pfn_counts_dict, bucket_set, out):
+ max_components = 0
+ for label in policy_set:
+ max_components = max(max_components, len(policy_set[label].components))
+
+ for label in sorted(policy_set):
+ components = policy_set[label].components
+ if len(policy_set) > 1:
+ out.write('%s%s\n' % (label, ',' * (max_components - 1)))
+ out.write('%s%s\n' % (
+ ','.join(components), ',' * (max_components - len(components))))
+
+ LOGGER.info('Applying a policy %s to...' % label)
+ for dump in dumps:
+ component_sizes = PolicyCommands._apply_policy(
+ dump, pfn_counts_dict, policy_set[label], bucket_set, dumps[0].time)
+ s = []
+ for c in components:
+ if c in ('hour', 'minute', 'second'):
+ s.append('%05.5f' % (component_sizes[c]))
+ else:
+ s.append('%05.5f' % (component_sizes[c] / 1024.0 / 1024.0))
+ out.write('%s%s\n' % (
+ ','.join(s), ',' * (max_components - len(components))))
+
+ bucket_set.clear_component_cache()
+
+ return 0
+
+
+class JSONCommand(PolicyCommands):
+ def __init__(self):
+ super(JSONCommand, self).__init__('json')
+
+ def do(self, sys_argv):
+ policy_set, dumps, pfn_counts_dict, bucket_set = self._set_up(sys_argv)
+ return JSONCommand._output(
+ policy_set, dumps, pfn_counts_dict, bucket_set, sys.stdout)
+
+ @staticmethod
+ def _output(policy_set, dumps, pfn_counts_dict, bucket_set, out):
+ json_base = {
+ 'version': 'JSON_DEEP_2',
+ 'policies': {},
+ }
+
+ for label in sorted(policy_set):
+ json_base['policies'][label] = {
+ 'legends': policy_set[label].components,
+ 'snapshots': [],
+ }
+
+ LOGGER.info('Applying a policy %s to...' % label)
+ for dump in dumps:
+ component_sizes = PolicyCommands._apply_policy(
+ dump, pfn_counts_dict, policy_set[label], bucket_set, dumps[0].time)
+ component_sizes['dump_path'] = dump.path
+ component_sizes['dump_time'] = datetime.datetime.fromtimestamp(
+ dump.time).strftime('%Y-%m-%d %H:%M:%S')
+ json_base['policies'][label]['snapshots'].append(component_sizes)
+
+ bucket_set.clear_component_cache()
+
+ json.dump(json_base, out, indent=2, sort_keys=True)
+
+ return 0
+
+
+class ListCommand(PolicyCommands):
+ def __init__(self):
+ super(ListCommand, self).__init__('list')
+
+ def do(self, sys_argv):
+ policy_set, dumps, pfn_counts_dict, bucket_set = self._set_up(sys_argv)
+ return ListCommand._output(
+ policy_set, dumps, pfn_counts_dict, bucket_set, sys.stdout)
+
+ @staticmethod
+ def _output(policy_set, dumps, pfn_counts_dict, bucket_set, out):
+ for label in sorted(policy_set):
+ LOGGER.info('Applying a policy %s to...' % label)
+ for dump in dumps:
+ component_sizes = PolicyCommands._apply_policy(
+ dump, pfn_counts_dict, policy_set[label], bucket_set, dump.time)
+ out.write('%s for %s:\n' % (label, dump.path))
+ for c in policy_set[label].components:
+ if c in ['hour', 'minute', 'second']:
+ out.write('%40s %12.3f\n' % (c, component_sizes[c]))
+ else:
+ out.write('%40s %12d\n' % (c, component_sizes[c]))
+
+ bucket_set.clear_component_cache()
+
+ return 0
diff --git a/chromium/tools/deep_memory_profiler/subcommands/pprof.py b/chromium/tools/deep_memory_profiler/subcommands/pprof.py
new file mode 100644
index 00000000000..506d8117119
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/pprof.py
@@ -0,0 +1,161 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import sys
+
+from lib.bucket import BUCKET_ID, COMMITTED, ALLOC_COUNT, FREE_COUNT
+from lib.policy import PolicySet
+from lib.subcommand import SubCommand
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class PProfCommand(SubCommand):
+ def __init__(self):
+ super(PProfCommand, self).__init__(
+ 'Usage: %prog pprof [-c COMPONENT] <dump> <policy>')
+ self._parser.add_option('-c', '--component', type='string',
+ dest='component',
+ help='restrict to COMPONENT', metavar='COMPONENT')
+
+ def do(self, sys_argv):
+ options, args = self._parse_args(sys_argv, 2)
+
+ dump_path = args[1]
+ target_policy = args[2]
+ component = options.component
+
+ (bucket_set, dump) = SubCommand.load_basic_files(dump_path, False)
+ policy_set = PolicySet.load(SubCommand._parse_policy_list(target_policy))
+
+ with open(SubCommand._find_prefix(dump_path) + '.maps', 'r') as maps_f:
+ maps_lines = maps_f.readlines()
+ PProfCommand._output(
+ dump, policy_set[target_policy], bucket_set, maps_lines, component,
+ sys.stdout)
+
+ return 0
+
+ @staticmethod
+ def _output(dump, policy, bucket_set, maps_lines, component_name, out):
+ """Converts the heap profile dump so it can be processed by pprof.
+
+ Args:
+ dump: A Dump object.
+ policy: A Policy object.
+ bucket_set: A BucketSet object.
+ maps_lines: A list of strings containing /proc/.../maps.
+ component_name: A name of component for filtering.
+ out: An IO object to output.
+ """
+ out.write('heap profile: ')
+ com_committed, com_allocs = PProfCommand._accumulate(
+ dump, policy, bucket_set, component_name)
+
+ out.write('%6d: %8s [%6d: %8s] @ heapprofile\n' % (
+ com_allocs, com_committed, com_allocs, com_committed))
+
+ PProfCommand._output_stacktrace_lines(
+ dump, policy, bucket_set, component_name, out)
+
+ out.write('MAPPED_LIBRARIES:\n')
+ for line in maps_lines:
+ out.write(line)
+
+ @staticmethod
+ def _accumulate(dump, policy, bucket_set, component_name):
+ """Accumulates size of committed chunks and the number of allocated chunks.
+
+ Args:
+ dump: A Dump object.
+ policy: A Policy object.
+ bucket_set: A BucketSet object.
+ component_name: A name of component for filtering.
+
+ Returns:
+ Two integers which are the accumulated size of committed regions and the
+ number of allocated chunks, respectively.
+ """
+ com_committed = 0
+ com_allocs = 0
+
+ for _, region in dump.iter_map:
+ if region[0] != 'hooked':
+ continue
+ component_match, bucket = policy.find_mmap(region, bucket_set)
+
+ if (component_name and component_name != component_match) or (
+ region[1]['committed'] == 0):
+ continue
+
+ com_committed += region[1]['committed']
+ com_allocs += 1
+
+ for line in dump.iter_stacktrace:
+ words = line.split()
+ bucket = bucket_set.get(int(words[BUCKET_ID]))
+ if not bucket or bucket.allocator_type == 'malloc':
+ component_match = policy.find_malloc(bucket)
+ elif bucket.allocator_type == 'mmap':
+ continue
+ else:
+ assert False
+ if (not bucket or
+ (component_name and component_name != component_match)):
+ continue
+
+ com_committed += int(words[COMMITTED])
+ com_allocs += int(words[ALLOC_COUNT]) - int(words[FREE_COUNT])
+
+ return com_committed, com_allocs
+
+ @staticmethod
+ def _output_stacktrace_lines(dump, policy, bucket_set, component_name, out):
+ """Prints information of stacktrace lines for pprof.
+
+ Args:
+ dump: A Dump object.
+ policy: A Policy object.
+ bucket_set: A BucketSet object.
+ component_name: A name of component for filtering.
+ out: An IO object to output.
+ """
+ for _, region in dump.iter_map:
+ if region[0] != 'hooked':
+ continue
+ component_match, bucket = policy.find_mmap(region, bucket_set)
+
+ if (component_name and component_name != component_match) or (
+ region[1]['committed'] == 0):
+ continue
+
+ out.write(' 1: %8s [ 1: %8s] @' % (
+ region[1]['committed'], region[1]['committed']))
+ for address in bucket.stacktrace:
+ out.write(' 0x%016x' % address)
+ out.write('\n')
+
+ for line in dump.iter_stacktrace:
+ words = line.split()
+ bucket = bucket_set.get(int(words[BUCKET_ID]))
+ if not bucket or bucket.allocator_type == 'malloc':
+ component_match = policy.find_malloc(bucket)
+ elif bucket.allocator_type == 'mmap':
+ continue
+ else:
+ assert False
+ if (not bucket or
+ (component_name and component_name != component_match)):
+ continue
+
+ out.write('%6d: %8s [%6d: %8s] @' % (
+ int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]),
+ words[COMMITTED],
+ int(words[ALLOC_COUNT]) - int(words[FREE_COUNT]),
+ words[COMMITTED]))
+ for address in bucket.stacktrace:
+ out.write(' 0x%016x' % address)
+ out.write('\n')
diff --git a/chromium/tools/deep_memory_profiler/subcommands/stacktrace.py b/chromium/tools/deep_memory_profiler/subcommands/stacktrace.py
new file mode 100644
index 00000000000..72b850981a0
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/stacktrace.py
@@ -0,0 +1,41 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+from lib.bucket import BUCKET_ID
+from lib.subcommand import SubCommand
+
+
+class StacktraceCommand(SubCommand):
+ def __init__(self):
+ super(StacktraceCommand, self).__init__(
+ 'Usage: %prog stacktrace <dump>')
+
+ def do(self, sys_argv):
+ _, args = self._parse_args(sys_argv, 1)
+ dump_path = args[1]
+ (bucket_set, dump) = SubCommand.load_basic_files(dump_path, False)
+
+ StacktraceCommand._output(dump, bucket_set, sys.stdout)
+ return 0
+
+ @staticmethod
+ def _output(dump, bucket_set, out):
+ """Outputs a given stacktrace.
+
+ Args:
+ bucket_set: A BucketSet object.
+ out: A file object to output.
+ """
+ for line in dump.iter_stacktrace:
+ words = line.split()
+ bucket = bucket_set.get(int(words[BUCKET_ID]))
+ if not bucket:
+ continue
+ for i in range(0, BUCKET_ID - 1):
+ out.write(words[i] + ' ')
+ for frame in bucket.symbolized_stackfunction:
+ out.write(frame + ' ')
+ out.write('\n')
diff --git a/chromium/tools/deep_memory_profiler/subcommands/upload.py b/chromium/tools/deep_memory_profiler/subcommands/upload.py
new file mode 100644
index 00000000000..de34a8a715e
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/subcommands/upload.py
@@ -0,0 +1,79 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import subprocess
+import tempfile
+import zipfile
+
+from lib.subcommand import SubCommand
+from lib.symbol import SymbolDataSources
+
+
+LOGGER = logging.getLogger('dmprof')
+
+
+class UploadCommand(SubCommand):
+ def __init__(self):
+ super(UploadCommand, self).__init__(
+ 'Usage: %prog upload [--gsutil path/to/gsutil] '
+ '<first-dump> <destination-gs-path>')
+ self._parser.add_option('--gsutil', default='gsutil',
+ help='path to GSUTIL', metavar='GSUTIL')
+
+ def do(self, sys_argv):
+ options, args = self._parse_args(sys_argv, 2)
+ dump_path = args[1]
+ gs_path = args[2]
+
+ dump_files = SubCommand._find_all_dumps(dump_path)
+ bucket_files = SubCommand._find_all_buckets(dump_path)
+ prefix = SubCommand._find_prefix(dump_path)
+ symbol_data_sources = SymbolDataSources(prefix)
+ symbol_data_sources.prepare()
+ symbol_path = symbol_data_sources.path()
+
+ handle_zip, filename_zip = tempfile.mkstemp('.zip', 'dmprof')
+ os.close(handle_zip)
+
+ try:
+ file_zip = zipfile.ZipFile(filename_zip, 'w', zipfile.ZIP_DEFLATED)
+ for filename in dump_files:
+ file_zip.write(filename, os.path.basename(os.path.abspath(filename)))
+ for filename in bucket_files:
+ file_zip.write(filename, os.path.basename(os.path.abspath(filename)))
+
+ symbol_basename = os.path.basename(os.path.abspath(symbol_path))
+ for filename in os.listdir(symbol_path):
+ if not filename.startswith('.'):
+ file_zip.write(os.path.join(symbol_path, filename),
+ os.path.join(symbol_basename, os.path.basename(
+ os.path.abspath(filename))))
+ file_zip.close()
+
+ returncode = UploadCommand._run_gsutil(
+ options.gsutil, 'cp', '-a', 'public-read', filename_zip, gs_path)
+ finally:
+ os.remove(filename_zip)
+
+ return returncode
+
+ @staticmethod
+ def _run_gsutil(gsutil, *args):
+ """Run gsutil as a subprocess.
+
+ Args:
+ *args: Arguments to pass to gsutil. The first argument should be an
+ operation such as ls, cp or cat.
+ Returns:
+ The return code from the process.
+ """
+ command = [gsutil] + list(args)
+ LOGGER.info("Running: %s", command)
+
+ try:
+ return subprocess.call(command)
+ except OSError, e:
+ LOGGER.error('Error to run gsutil: %s', e)
diff --git a/chromium/tools/deep_memory_profiler/templates.json b/chromium/tools/deep_memory_profiler/templates.json
new file mode 100644
index 00000000000..b4d9a4eb608
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/templates.json
@@ -0,0 +1,12 @@
+{
+ "l2": ["vm", "map", {
+ "mmap-tcmalloc": ["malloc", "component", {}]
+ }],
+ "details": ["vm", "map", {
+ "mmap-tcmalloc": ["malloc", "component", {
+ "webkit": ["malloc", "webkit-details", {}],
+ "skia": ["malloc", "skia-details", {}]
+ }],
+ "mmap-v8-heap": ["javascript", "type", {}]
+ }]
+}
diff --git a/chromium/tools/deep_memory_profiler/visualizer/main.css b/chromium/tools/deep_memory_profiler/visualizer/main.css
new file mode 100644
index 00000000000..5d9ed53f48d
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/visualizer/main.css
@@ -0,0 +1,9 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+.plot-container {
+ width: 1240px;
+ height: 720px;
+ margin: 30px auto 30px auto;
+} \ No newline at end of file
diff --git a/chromium/tools/deep_memory_profiler/visualizer/main.html b/chromium/tools/deep_memory_profiler/visualizer/main.html
new file mode 100644
index 00000000000..fdd78745910
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/visualizer/main.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!--
+Copyright 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<meta charset="utf-8">
+<link rel="stylesheet" href="main.css">
+<script src="../../../third_party/flot/jquery.min.js"></script>
+<script src="../../../third_party/flot/jquery.flot.min.js"></script>
+<script src="../../../third_party/flot/jquery.flot.stack.min.js"></script>
+<script src="main.js"></script>
+
+<body>
+ <h2>Deep Memory Profiler Visulaizer</h2>
+ <div id="plot" class="plot-container"></div>
+</body>
diff --git a/chromium/tools/deep_memory_profiler/visualizer/main.js b/chromium/tools/deep_memory_profiler/visualizer/main.js
new file mode 100644
index 00000000000..8c4dff84c4b
--- /dev/null
+++ b/chromium/tools/deep_memory_profiler/visualizer/main.js
@@ -0,0 +1,160 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * This class provides data access interface for dump file profiler
+ * @constructor
+ */
+var Profiler = function(jsonData) {
+ this._jsonData = jsonData;
+};
+
+/**
+ * Get units of a snapshot in a world.
+ * Exception will be thrown when no world of given name exists.
+ * @param {string} worldName
+ * @param {number} snapshotIndex
+ * @return {Object.<string, number>}
+ */
+Profiler.prototype.getUnits = function(worldName, snapshotIndex) {
+ var snapshot = this._jsonData.snapshots[snapshotIndex];
+ if (!snapshot.worlds[worldName])
+ throw 'no world ' + worldName + ' in snapshot ' + index;
+
+ // Return units.
+ var world = snapshot.worlds[worldName];
+ var units = {};
+ for (var unitName in world.units)
+ units[unitName] = world.units[unitName][0];
+ return units;
+};
+
+/**
+ * Get first-level breakdowns of a snapshot in a world.
+ * Exception will be thrown when no world of given name exists.
+ * @param {string} worldName
+ * @param {number} snapshotIndex
+ * @return {Object.<string, Object>}
+ */
+Profiler.prototype.getBreakdowns = function(worldName, snapshotIndex) {
+ var snapshot = this._jsonData.snapshots[snapshotIndex];
+ if (!snapshot.worlds[worldName])
+ throw 'no world ' + worldName + ' in snapshot ' + index;
+
+ // Return breakdowns.
+ // TODO(junjianx): handle breakdown with arbitrary-level structure.
+ return snapshot.worlds[worldName].breakdown;
+};
+
+/**
+ * Get categories from fixed hard-coded worlds and breakdowns temporarily.
+ * TODO(junjianx): remove the hard-code and support general cases.
+ * @return {Array.<Object>}
+ */
+Profiler.prototype.getCategories = function() {
+ var categories = [];
+ var snapshotNum = this._jsonData.snapshots.length;
+
+ for (var snapshotIndex = 0; snapshotIndex < snapshotNum; ++snapshotIndex) {
+ // Initial categories object for one snapshot.
+ categories.push({});
+
+ // Handle breakdowns in malloc world.
+ var mallocBreakdown = this.getBreakdowns('malloc', snapshotIndex);
+ var mallocUnits = this.getUnits('malloc', snapshotIndex);
+ if (!mallocBreakdown['component'])
+ throw 'no breakdown ' + 'component' + ' in snapshot ' + snapshotIndex;
+
+ var componentBreakdown = mallocBreakdown['component'];
+ var componentMemory = 0;
+ Object.keys(componentBreakdown).forEach(function(breakdownName) {
+ var breakdown = componentBreakdown[breakdownName];
+ var memory = breakdown.units.reduce(function(previous, current) {
+ return previous + mallocUnits[current];
+ }, 0);
+ componentMemory += memory;
+
+ if (componentBreakdown['hidden'] === true)
+ return;
+ else
+ categories[snapshotIndex][breakdownName] = memory;
+ });
+
+ // Handle breakdowns in vm world.
+ var vmBreakdown = this.getBreakdowns('vm', snapshotIndex);
+ var vmUnits = this.getUnits('vm', snapshotIndex);
+ if (!vmBreakdown['map'])
+ throw 'no breakdown ' + 'map' + ' in snapshot ' + snapshotIndex;
+
+ var mapBreakdown = vmBreakdown['map'];
+
+ Object.keys(mapBreakdown).forEach(function(breakdownName) {
+ var breakdown = mapBreakdown[breakdownName];
+ var memory = breakdown.units.reduce(function(previous, current) {
+ return previous + vmUnits[current];
+ }, 0);
+
+ if (vmBreakdown['hidden'] === true)
+ return;
+ else if (breakdownName === 'mmap-tcmalloc')
+ categories[snapshotIndex]['tc-unused'] = memory - componentMemory;
+ else
+ categories[snapshotIndex][breakdownName] = memory;
+ });
+ }
+
+ return categories;
+};
+
+/**
+ * Generate lines for flot plotting.
+ * @param {Array.<Object>} categories
+ * @return {Array.<Object>}
+ */
+var generateLines = function(categories) {
+ var lines = {};
+ var snapshotNum = categories.length;
+
+ // Initialize lines with all zero.
+ categories.forEach(function(categories) {
+ Object.keys(categories).forEach(function(breakdownName) {
+ if (lines[breakdownName])
+ return;
+ lines[breakdownName] = [];
+ for (var i = 0; i < snapshotNum; ++i)
+ lines[breakdownName].push([i, 0]);
+ });
+ });
+
+ // Assignment lines with values of categories.
+ categories.forEach(function(categories, index) {
+ Object.keys(categories).forEach(function(breakdownName) {
+ lines[breakdownName][index] = [index, categories[breakdownName]];
+ });
+ });
+
+ return Object.keys(lines).map(function(breakdownName) {
+ return {
+ label: breakdownName,
+ data: lines[breakdownName]
+ };
+ });
+};
+
+$(function() {
+ // Read original data and plot.
+ $.getJSON('data/result.json', function(jsonData) {
+ var profiler = new Profiler(jsonData);
+ var categories = profiler.getCategories();
+ var lines = generateLines(categories);
+
+ // Plot stack graph.
+ $.plot('#plot', lines, {
+ series: {
+ stack: true,
+ lines: { show: true, fill: true }
+ }
+ });
+ });
+}); \ No newline at end of file
diff --git a/chromium/tools/deps2git/PRESUBMIT.py b/chromium/tools/deps2git/PRESUBMIT.py
new file mode 100644
index 00000000000..e6730abfb56
--- /dev/null
+++ b/chromium/tools/deps2git/PRESUBMIT.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for deps2git.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+def CommonChecks(input_api, output_api):
+ output = []
+ output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+ output.extend(
+ input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api,
+ input_api.PresubmitLocalPath(),
+ whitelist=[r'.+_unittest\.py$']))
+
+ if input_api.is_committing:
+ output.extend(input_api.canned_checks.PanProjectChecks(input_api,
+ output_api,
+ owners_check=False))
+ return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/chromium/tools/deps2git/WATCHLISTS b/chromium/tools/deps2git/WATCHLISTS
new file mode 100644
index 00000000000..01b17c60f44
--- /dev/null
+++ b/chromium/tools/deps2git/WATCHLISTS
@@ -0,0 +1,23 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Watchlist Rules
+# Refer: http://dev.chromium.org/developers/contributing-code/watchlists
+
+{
+
+ 'WATCHLIST_DEFINITIONS': {
+ 'this_file': {
+ 'filepath': '^WATCHLISTS$',
+ },
+ 'all': {
+ 'filepath': '.+',
+ },
+ },
+
+ 'WATCHLISTS': {
+ 'all': ['cmp-cc@chromium.org'],
+ },
+
+}
diff --git a/chromium/tools/deps2git/codereview.settings b/chromium/tools/deps2git/codereview.settings
new file mode 100644
index 00000000000..888dfc74a1f
--- /dev/null
+++ b/chromium/tools/deps2git/codereview.settings
@@ -0,0 +1,4 @@
+# This file is used by gcl to get repository specific information.
+CODE_REVIEW_SERVER: https://codereview.chromium.org
+CC_LIST: chromium-reviews@chromium.org
+VIEW_VC: https://src.chromium.org/viewvc/chrome?view=rev&revision=
diff --git a/chromium/tools/deps2git/deps2git.py b/chromium/tools/deps2git/deps2git.py
new file mode 100755
index 00000000000..e9a0102f361
--- /dev/null
+++ b/chromium/tools/deps2git/deps2git.py
@@ -0,0 +1,220 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Convert SVN based DEPS into .DEPS.git for use with NewGit."""
+
+import optparse
+import os
+import sys
+
+import deps_utils
+import git_tools
+import svn_to_git_public
+
+
+def SplitScmUrl(url):
+ """Given a repository, return a set containing the URL and the revision."""
+ url_split = url.split('@')
+ scm_url = url_split[0]
+ scm_rev = 'HEAD'
+ if len(url_split) == 2:
+ scm_rev = url_split[1]
+ return (scm_url, scm_rev)
+
+
+def SvnRevToGitHash(svn_rev, git_url, repos_path, workspace, dep_path,
+ git_host, svn_branch_name=None):
+ """Convert a SVN revision to a Git commit id."""
+ git_repo = None
+ if git_url.startswith(git_host):
+ git_repo = git_url.replace(git_host, '')
+ else:
+ raise Exception('Unknown git server %s, host %s' % (git_url, git_host))
+ if repos_path is None and workspace is None:
+ # We're running without a repository directory (i.e. no -r option).
+ # We cannot actually find the commit id, but this mode is useful
+ # just for testing the URL mappings. Produce an output file that
+ # can't actually be used, but can be eyeballed for correct URLs.
+ return 'xxx-r%s' % svn_rev
+ if repos_path:
+ git_repo_path = os.path.join(repos_path, git_repo)
+ mirror = True
+ else:
+ git_repo_path = os.path.join(workspace, dep_path)
+ mirror = False
+ if not os.path.exists(git_repo_path):
+ git_tools.Clone(git_url, git_repo_path, mirror)
+
+ if svn_branch_name:
+ # svn branches are mirrored with:
+ # branches = branches/*:refs/remotes/branch-heads/*
+ if mirror:
+ refspec = 'refs/branch-heads/' + svn_branch_name
+ else:
+ refspec = 'refs/remotes/branch-heads/' + svn_branch_name
+ else:
+ if mirror:
+ refspec = 'refs/heads/master'
+ else:
+ refspec = 'refs/remotes/origin/master'
+
+ return git_tools.Search(git_repo_path, svn_rev, mirror, refspec, git_url)
+
+
+def ConvertDepsToGit(deps, options, deps_vars, svn_deps_vars):
+ """Convert a 'deps' section in a DEPS file from SVN to Git."""
+ new_deps = {}
+ bad_git_urls = set([])
+
+ svn_to_git_objs = [svn_to_git_public]
+ if options.extra_rules:
+ rules_dir, rules_file = os.path.split(options.extra_rules)
+ rules_file_base = os.path.splitext(rules_file)[0]
+ sys.path.insert(0, rules_dir)
+ svn_to_git_objs.insert(0, __import__(rules_file_base))
+
+ deps_overrides = {}
+ # Allow extra_rules file to override rules in public file.
+ for svn_to_git_obj in reversed(svn_to_git_objs):
+ deps_overrides.update(getattr(svn_to_git_obj, 'DEPS_OVERRIDES', {}))
+
+ for dep in deps:
+ if not deps[dep]: # dep is 'None' and emitted to exclude the dep
+ new_deps[dep] = None
+ continue
+
+ # Get the URL and the revision/hash for this dependency.
+ dep_url, dep_rev = SplitScmUrl(deps[dep])
+
+ path = dep
+ git_url = dep_url
+ svn_branch = None
+
+ if not dep_url.endswith('.git'):
+ # Convert this SVN URL to a Git URL.
+ for svn_git_converter in svn_to_git_objs:
+ converted_data = svn_git_converter.SvnUrlToGitUrl(dep, dep_url)
+ if converted_data:
+ path, git_url, git_host = converted_data[:3]
+ if len(converted_data) > 3:
+ svn_branch = converted_data[3]
+ break
+ else:
+ # We skip this path, this must not be required with Git.
+ continue
+
+ if options.verify:
+ print >> sys.stderr, 'checking ' + git_url + '...',
+ if git_tools.Ping(git_url):
+ print >> sys.stderr, ' success'
+ else:
+ print >> sys.stderr, ' failure'
+ bad_git_urls.update([git_url])
+
+ # Get the Git hash based off the SVN rev.
+ git_hash = ''
+ if dep_rev != 'HEAD':
+ if dep in deps_overrides:
+ # Transfer any required variables over from SVN DEPS.
+ if not deps_overrides[dep] in svn_deps_vars:
+ raise Exception('Missing DEPS variable: %s' % deps_overrides[dep])
+ deps_vars[deps_overrides[dep]] = (
+ '@' + svn_deps_vars[deps_overrides[dep]].lstrip('@'))
+ # Tag this variable as needing a transform by Varify() later.
+ git_hash = '%s_%s' % (deps_utils.VARIFY_MARKER_TAG_PREFIX,
+ deps_overrides[dep])
+ else:
+ # Pass-through the hash for Git repositories. Resolve the hash for
+ # subversion repositories.
+ if dep_url.endswith('.git'):
+ git_hash = '@%s' % dep_rev
+ else:
+ git_hash = '@%s' % SvnRevToGitHash(
+ dep_rev, git_url, options.repos, options.workspace, path,
+ git_host, svn_branch)
+
+ # If this is webkit, we need to add the var for the hash.
+ if dep == 'src/third_party/WebKit' and dep_rev:
+ deps_vars['webkit_rev'] = git_hash
+ git_hash = 'VAR_WEBKIT_REV'
+
+ # Add this Git dep to the new deps.
+ new_deps[path] = '%s%s' % (git_url, git_hash)
+
+ return new_deps, bad_git_urls
+
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option('-d', '--deps', default='DEPS',
+ help='path to the DEPS file to convert')
+ parser.add_option('-o', '--out',
+ help='path to the converted DEPS file (default: stdout)')
+ parser.add_option('-t', '--type',
+ help='[DEPRECATED] type of DEPS file (public, etc)')
+ parser.add_option('-x', '--extra-rules',
+ help='Path to file with additional conversion rules.')
+ parser.add_option('-r', '--repos',
+ help='path to the directory holding all the Git repos')
+ parser.add_option('-w', '--workspace', metavar='PATH',
+ help='top level of a git-based gclient checkout')
+ parser.add_option('--verify', action='store_true',
+ help='ping each Git repo to make sure it exists')
+ options = parser.parse_args()[0]
+
+ # Get the content of the DEPS file.
+ deps_content = deps_utils.GetDepsContent(options.deps)
+ (deps, deps_os, include_rules, skip_child_includes, hooks,
+ svn_deps_vars) = deps_content
+
+ if options.extra_rules and options.type:
+ parser.error('Can\'t specify type and extra-rules at the same time.')
+ elif options.type:
+ options.extra_rules = os.path.join(
+ os.path.abspath(os.path.dirname(__file__)),
+ 'svn_to_git_%s.py' % options.type)
+
+ if options.extra_rules and not os.path.exists(options.extra_rules):
+ raise Exception('Can\'t locate rules file "%s".' % options.extra_rules)
+
+ # Create a var containing the Git and Webkit URL, this will make it easy for
+ # people to use a mirror instead.
+ git_url = 'https://chromium.googlesource.com'
+ deps_vars = {
+ 'git_url': git_url,
+ 'webkit_url': git_url + '/chromium/blink.git',
+ }
+
+ # Convert the DEPS file to Git.
+ deps, baddeps = ConvertDepsToGit(deps, options, deps_vars, svn_deps_vars)
+ for os_dep in deps_os:
+ deps_os[os_dep], os_bad_deps = ConvertDepsToGit(
+ deps_os[os_dep], options, deps_vars, svn_deps_vars)
+ baddeps = baddeps.union(os_bad_deps)
+
+ if baddeps:
+ print >> sys.stderr, ('\nUnable to resolve the following repositories. '
+ 'Please make sure\nthat any svn URLs have a git mirror associated with '
+ 'them.\nTo see the exact error, run `git ls-remote [repository]` where'
+ '\n[repository] is the URL ending in .git (strip off the @revision\n'
+ 'number.) For more information, visit http://code.google.com\n'
+ '/p/chromium/wiki/UsingNewGit#Adding_new_repositories_to_DEPS.\n')
+ for dep in baddeps:
+ print >> sys.stderr, ' ' + dep
+ return 2
+ else:
+ if options.verify:
+ print >> sys.stderr, ('\nAll referenced repositories were successfully '
+ 'resolved.')
+ return 0
+
+ # Write the DEPS file to disk.
+ deps_utils.WriteDeps(options.out, deps_vars, deps, deps_os, include_rules,
+ skip_child_includes, hooks)
+ return 0
+
+
+if '__main__' == __name__:
+ sys.exit(main())
diff --git a/chromium/tools/deps2git/deps2submodules.py b/chromium/tools/deps2git/deps2submodules.py
new file mode 100644
index 00000000000..8e8a1475955
--- /dev/null
+++ b/chromium/tools/deps2git/deps2submodules.py
@@ -0,0 +1,165 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Read .DEPS.git and use the information to update git submodules"""
+
+import optparse
+import os
+import re
+import subprocess
+import sys
+
+from deps_utils import GetDepsContent
+
+
+SHA1_RE = re.compile('[0-9a-fA-F]{40}')
+
+
+def SanitizeDeps(submods):
+ """
+ Look for conflicts (primarily nested submodules) in submodule data. In the
+ case of a conflict, the higher-level (shallower) submodule takes precedence.
+ Modifies the submods argument in-place.
+ """
+ for submod_name in submods.keys():
+ parts = submod_name.split('/')[:-1]
+ while parts:
+ may_conflict = '/'.join(parts)
+ if may_conflict in submods:
+ msg = ('Warning: dropping submodule "%s", because '
+ 'it is nested in submodule "%s".' % (submod_name, may_conflict))
+ print >> sys.stderr, msg
+ submods.pop(submod_name)
+ break
+ parts.pop()
+ return submods
+
+
+def CollateDeps(deps_content):
+ """
+ Take the output of deps_utils.GetDepsContent and return a hash of:
+
+ { submod_name : [ [ submod_os, ... ], submod_url, submod_sha1 ], ... }
+ """
+ fixdep = lambda x: x[4:] if x.startswith('src/') else x
+ spliturl = lambda x: list(x.partition('@')[0::2]) if x else [None, None]
+ submods = {}
+ # Non-OS-specific DEPS always override OS-specific deps. This is an interim
+ # hack until there is a better way to handle OS-specific DEPS.
+ for (deps_os, val) in deps_content[1].iteritems():
+ for (dep, url) in val.iteritems():
+ submod_data = submods.setdefault(fixdep(dep), [[]] + spliturl(url))
+ submod_data[0].append(deps_os)
+ for (dep, url) in deps_content[0].iteritems():
+ submods[fixdep(dep)] = [['all']] + spliturl(url)
+ return submods
+
+
+def WriteGitmodules(submods, gitless=False, rewrite_rules=None):
+ """
+ Take the output of CollateDeps, use it to write a .gitmodules file and
+ add submodules to the git index.
+ """
+ if not rewrite_rules:
+ rewrite_rules = []
+ def _rewrite(url):
+ if not url:
+ return url
+ for rule in rewrite_rules:
+ if url.startswith(rule[0]):
+ return rule[1] + url[len(rule[0]):]
+ return url
+ fh = open('.gitmodules', 'w')
+ for submod in sorted(submods.keys()):
+ [submod_os, submod_url, submod_sha1] = submods[submod]
+ submod_url = _rewrite(submod_url)
+ print >> fh, '[submodule "%s"]' % submod
+ print >> fh, '\tpath = %s' % submod
+ print >> fh, '\turl = %s' % (submod_url if submod_url else '')
+ print >> fh, '\tos = %s' % ','.join(submod_os)
+ if submod_sha1 and not SHA1_RE.match(submod_sha1):
+ raise RuntimeError('sha1 hash "%s" for submodule "%s" is malformed' %
+ (submod_sha1, submod))
+ if gitless or not submod_url:
+ continue
+ if not submod_sha1:
+ # We don't know what sha1 to register, so we have to infer it from the
+ # submodule's origin/master.
+ if not os.path.exists(os.path.join(submod, '.git')):
+ # Not cloned yet
+ subprocess.check_call(['git', 'clone', '-n', submod_url, submod])
+ else:
+ # Already cloned; let's fetch
+ subprocess.check_call(['git', 'fetch', 'origin'], cwd=submod)
+ sub = subprocess.Popen(['git', 'rev-list', 'origin/HEAD^!'],
+ cwd=submod, stdout=subprocess.PIPE)
+ submod_sha1 = sub.communicate()[0].rstrip()
+ subprocess.check_call(['git', 'update-index', '--add',
+ '--cacheinfo', '160000', submod_sha1, submod])
+ fh.close()
+ if gitless:
+ return
+ subprocess.check_call(['git', 'add', '.gitmodules'])
+
+
+def RemoveObsoleteSubmodules():
+ """
+ Delete from the git repository any submodules which aren't in .gitmodules.
+ """
+ lsfiles_proc = subprocess.Popen(['git', 'ls-files', '-s'],
+ stdout=subprocess.PIPE)
+ grep_proc = subprocess.Popen(['grep', '^160000'],
+ stdin = lsfiles_proc.stdout,
+ stdout=subprocess.PIPE)
+ (grep_out, _) = grep_proc.communicate() or ('', '')
+ lsfiles_proc.communicate()
+ with open(os.devnull, 'w') as nullpipe:
+ for line in grep_out.splitlines():
+ [_, _, _, path] = line.split()
+ cmd = ['git', 'config', '-f', '.gitmodules',
+ '--get-regexp', 'submodule\..*\.path', path]
+ try:
+ subprocess.check_call(cmd, stdout=nullpipe)
+ except subprocess.CalledProcessError:
+ subprocess.check_call(['git', 'update-index', '--force-remove', path])
+
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option('--gitless', action='store_true',
+ help='Skip all actions that assume a git working copy '
+ '(to support presubmit checks)')
+ parser.add_option('--rewrite-url', action='append', metavar='OLD_URL=NEW_URL',
+ default=[], help='Translate urls according to this rule')
+ options, args = parser.parse_args()
+ if args:
+ deps_file = args[0]
+ else:
+ deps_file = '.DEPS.git'
+
+ rewrite_rules = []
+ for rule in options.rewrite_url:
+ (old_url, new_url) = rule.split('=', 1)
+ if not old_url or not new_url:
+ print 'Bad url rewrite rule: "%s"' % rule
+ parser.print_help()
+ return 1
+ rewrite_rules.append((old_url, new_url))
+
+
+ # 9/18/2012 -- HACK to fix try bots without restarting
+ hack_deps_file = os.path.join('src', '.DEPS.git')
+ if not os.path.exists(deps_file) and os.path.exists(hack_deps_file):
+ deps_file = hack_deps_file
+
+ WriteGitmodules(SanitizeDeps(CollateDeps(GetDepsContent(deps_file))),
+ rewrite_rules=rewrite_rules, gitless=options.gitless)
+ if not options.gitless:
+ RemoveObsoleteSubmodules()
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/deps2git/deps2submodules_unittest.py b/chromium/tools/deps2git/deps2submodules_unittest.py
new file mode 100755
index 00000000000..4f4114c804a
--- /dev/null
+++ b/chromium/tools/deps2git/deps2submodules_unittest.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+import deps2submodules
+
+
+class Deps2SubmodulesCollateDepsTest(unittest.TestCase):
+ def testBasic(self):
+ arg = ({
+ 'src/monkeypatch': 'http://git.chromium.org/monkepatch.git@abc123',
+ 'src/third_party/monkeyfood':
+ 'http://git.chromium.org/monkeyfood@def456',
+ }, {}) # No OS-specific DEPS.
+ expected = {
+ 'monkeypatch':
+ [['all'], 'http://git.chromium.org/monkepatch.git', 'abc123'],
+ 'third_party/monkeyfood':
+ [['all'], 'http://git.chromium.org/monkeyfood', 'def456'],
+ }
+ self.assertEqual(expected, deps2submodules.CollateDeps(arg))
+
+ def testSrcPrefixStrip(self):
+ arg = ({
+ 'src/in_src': 'http://git.chromium.org/src.git@f00bad',
+ 'not_in_src/foo': 'http://other.git.something/main.git@123456',
+ }, {}) # No OS-specific DEPS.
+ expected = {
+ 'in_src': [['all'], 'http://git.chromium.org/src.git', 'f00bad'],
+ 'not_in_src/foo':
+ [['all'], 'http://other.git.something/main.git', '123456'],
+ }
+ self.assertEqual(expected, deps2submodules.CollateDeps(arg))
+
+ def testOSDeps(self):
+ arg = ({
+ 'src/hotp': 'http://hmac.org/hotp.git@7fffffff',
+ }, {
+ 'linux': {
+ 'src/third_party/selinux': 'http://kernel.org/selinux.git@abc123',
+ 'src/multios': 'http://git.chromium.org/multi.git@000005',
+ },
+ 'mac': {
+ 'src/third_party/security':
+ 'http://opensource.apple.com/security.git@def456',
+ },
+ 'win': {
+ 'src/multios': 'http://git.chromium.org/multi.git@000005',
+ },
+ })
+ expected = {
+ 'hotp': [['all'], 'http://hmac.org/hotp.git', '7fffffff'],
+ 'third_party/selinux':
+ [['linux'], 'http://kernel.org/selinux.git', 'abc123'],
+ 'third_party/security':
+ [['mac'], 'http://opensource.apple.com/security.git', 'def456'],
+ 'multios':
+ [['win', 'linux'], 'http://git.chromium.org/multi.git', '000005'],
+ }
+ self.assertEqual(expected, deps2submodules.CollateDeps(arg))
+
+ def testOSDepsWithNone(self):
+ arg = ({
+ 'src/skia': 'http://git.chromium.org/skia.git@abc123',
+ 'src/aura': 'http://git.chromium.org/aura.git',
+ }, {
+ 'ios': {
+ 'src/skia': None,
+ 'src/apple': 'http://git.chromium.org/apple.git@def456',
+ }
+ })
+ expected = {
+ 'skia': [['all'], 'http://git.chromium.org/skia.git', 'abc123'],
+ 'aura': [['all'], 'http://git.chromium.org/aura.git', ''],
+ 'apple': [['ios'], 'http://git.chromium.org/apple.git', 'def456'],
+ }
+ self.assertEqual(expected, deps2submodules.CollateDeps(arg))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/deps2git/deps_utils.py b/chromium/tools/deps2git/deps_utils.py
new file mode 100644
index 00000000000..80c5b6e12d7
--- /dev/null
+++ b/chromium/tools/deps2git/deps_utils.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utilities for formatting and writing DEPS files."""
+
+import re
+import sys
+
+# Used by Varify() to automatically convert variable names tagged with this
+# prefix into Var('<variable name>').
+VARIFY_MARKER_TAG_PREFIX = 'VARIFY_MARKER_TAG_'
+
+
+class VarImpl(object):
+ """Implement the Var function used within the DEPS file."""
+
+ def __init__(self, local_scope):
+ self._local_scope = local_scope
+
+ def Lookup(self, var_name):
+ """Implements the Var syntax."""
+ if var_name in self._local_scope.get('vars', {}):
+ return self._local_scope['vars'][var_name]
+ raise Exception('Var is not defined: %s' % var_name)
+
+
+def GetDepsContent(deps_path):
+ """Read a DEPS file and return all the sections."""
+ deps_file = open(deps_path, 'rU')
+ content = deps_file.read()
+ local_scope = {}
+ var = VarImpl(local_scope)
+ global_scope = {
+ 'Var': var.Lookup,
+ 'deps': {},
+ 'deps_os': {},
+ 'include_rules': [],
+ 'skip_child_includes': [],
+ 'hooks': [],
+ }
+ exec(content, global_scope, local_scope)
+ local_scope.setdefault('deps', {})
+ local_scope.setdefault('deps_os', {})
+ local_scope.setdefault('include_rules', [])
+ local_scope.setdefault('skip_child_includes', [])
+ local_scope.setdefault('hooks', [])
+ local_scope.setdefault('vars', {})
+
+ return (local_scope['deps'], local_scope['deps_os'],
+ local_scope['include_rules'], local_scope['skip_child_includes'],
+ local_scope['hooks'], local_scope['vars'])
+
+
+def PrettyDeps(deps, indent=0):
+ """Stringify a deps dictionary in a pretty way."""
+ pretty = ' ' * indent
+ pretty += '{\n'
+
+ indent += 4
+
+ for item in sorted(deps):
+ if type(deps[item]) == dict:
+ value = PrettyDeps(deps[item], indent)
+ else:
+ value = ' ' * (indent + 4)
+ if deps[item] is None:
+ value += str(deps[item])
+ else:
+ value += '\'%s\'' % str(deps[item])
+ pretty += ' ' * indent
+ pretty += '\'%s\':\n' % item
+ pretty += '%s,\n' % value
+
+ indent -= 4
+ pretty += ' ' * indent
+ pretty += '}'
+ return pretty
+
+
+def PrettyObj(obj):
+ """Stringify an object in a pretty way."""
+ pretty = str(obj).replace('{', '{\n ')
+ pretty = pretty.replace('}', '\n}')
+ pretty = pretty.replace('[', '[\n ')
+ pretty = pretty.replace(']', '\n]')
+ pretty = pretty.replace('\':', '\':\n ')
+ pretty = pretty.replace(', ', ',\n ')
+ return pretty
+
+
+def Varify(deps):
+ """Replace all instances of our git server with a git_url var."""
+ deps = deps.replace(
+ '\'https://chromium.googlesource.com/chromium/blink.git',
+ 'Var(\'webkit_url\')')
+ deps = deps.replace(
+ '\'https://chromium.googlesource.com', 'Var(\'git_url\') + \'')
+ deps = deps.replace(
+ '\'https://git.chromium.org', 'Var(\'git_url\') + \'')
+ deps = deps.replace('VAR_WEBKIT_REV\'', ' + Var(\'webkit_rev\')')
+
+ # Try to replace all instances of form "marker_prefix_<name>'" with
+ # "' + Var('<name>')". If there are no matches, nothing is done.
+ deps = re.sub(VARIFY_MARKER_TAG_PREFIX + '_(\w+)\'',
+ lambda match: '\' + Var(\'%s\')' % match.group(1), deps)
+ return deps
+
+
+def WriteDeps(deps_file_name, deps_vars, deps, deps_os, include_rules,
+ skip_child_includes, hooks):
+ """Given all the sections in a DEPS file, write it to disk."""
+ new_deps = ('# DO NOT EDIT EXCEPT FOR LOCAL TESTING.\n'
+ '# THIS IS A GENERATED FILE.\n',
+ '# ALL MANUAL CHANGES WILL BE OVERWRITTEN.\n',
+ '# SEE http://code.google.com/p/chromium/wiki/UsingNewGit\n',
+ '# FOR HOW TO ROLL DEPS\n'
+ 'vars = %s\n\n' % PrettyObj(deps_vars),
+ 'deps = %s\n\n' % Varify(PrettyDeps(deps)),
+ 'deps_os = %s\n\n' % Varify(PrettyDeps(deps_os)),
+ 'include_rules = %s\n\n' % PrettyObj(include_rules),
+ 'skip_child_includes = %s\n\n' % PrettyObj(skip_child_includes),
+ 'hooks = %s\n' % PrettyObj(hooks))
+ new_deps = ''.join(new_deps)
+ if deps_file_name:
+ deps_file = open(deps_file_name, 'w')
+ else:
+ deps_file = sys.stdout
+
+ try:
+ deps_file.write(new_deps)
+ finally:
+ if deps_file_name:
+ deps_file.close()
diff --git a/chromium/tools/deps2git/git_tools.py b/chromium/tools/deps2git/git_tools.py
new file mode 100644
index 00000000000..525b9b8f187
--- /dev/null
+++ b/chromium/tools/deps2git/git_tools.py
@@ -0,0 +1,183 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import os
+import re
+import subprocess
+import threading
+
+
+# Show more information about the commands being executed.
+VERBOSE = False
+
+# The longest any single subprocess will be allowed to run.
+TIMEOUT = 20 * 60
+
+
+def GetStatusOutput(cmd, cwd=None):
+ """Return (status, output) of executing cmd in a shell."""
+ if VERBOSE:
+ print ''
+ print '[DEBUG] Running "%s"' % cmd
+
+ def _thread_main():
+ thr = threading.current_thread()
+ thr.status = -1
+ thr.stdout = ''
+ thr.stderr = '<timeout>'
+ try:
+ proc = subprocess.Popen(cmd, shell=True, universal_newlines=True, cwd=cwd,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ (stdout, _) = proc.communicate()
+ except Exception, e:
+ thr.status = -1
+ thr.stdout = ''
+ thr.stderr = repr(e)
+ else:
+ thr.status = proc.returncode
+ thr.stdout = stdout
+ thr.stderr = ''
+
+ thr = threading.Thread(target=_thread_main)
+ thr.daemon = True
+ thr.start()
+ thr.join(TIMEOUT)
+
+ # pylint: disable=E1101
+ if VERBOSE:
+ short_output = ' '.join(thr.stdout.splitlines())
+ short_output = short_output.strip(' \t\n\r')
+ print '[DEBUG] Output: %d, %-60s' % (thr.status, short_output)
+
+ return (thr.status, thr.stdout)
+
+
+def Git(git_repo, command, is_mirror=False):
+ """Execute a git command within a local git repo."""
+ if is_mirror:
+ cmd = 'git --git-dir=%s %s' % (git_repo, command)
+ cwd = None
+ else:
+ cmd = 'git %s' % command
+ cwd = git_repo
+ (status, output) = GetStatusOutput(cmd, cwd)
+ if status != 0:
+ raise Exception('Failed to run %s. error %d. output %s' % (cmd, status,
+ output))
+ return (status, output)
+
+
+def Clone(git_url, git_repo, is_mirror):
+ """Clone a repository."""
+ cmd = 'clone%s %s %s' % (' --mirror' if is_mirror else '', git_url, git_repo)
+ if not is_mirror and not os.path.exists(git_repo):
+ os.makedirs(git_repo)
+ return Git(git_repo, cmd, is_mirror)
+
+
+def Fetch(git_repo, git_url, is_mirror):
+ """Fetch the latest objects for a given git repository."""
+ # Always update the upstream url
+ Git(git_repo, 'config remote.origin.url %s' % git_url)
+ Git(git_repo, 'fetch origin', is_mirror)
+
+
+def Ping(git_repo):
+ """Confirm that a remote repository URL is valid."""
+ status, _ = GetStatusOutput('git ls-remote ' + git_repo)
+ return status == 0
+
+
+def CreateLessThanOrEqualRegex(number):
+ """ Return a regular expression to test whether an integer less than or equal
+ to 'number' is present in a given string.
+ """
+
+ # In three parts, build a regular expression that match any numbers smaller
+ # than 'number'.
+ # For example, 78656 would give a regular expression that looks like:
+ # Part 1
+ # (78356| # 78356
+ # Part 2
+ # 7835[0-5]| # 78350-78355
+ # 783[0-4][0-9]| # 78300-78349
+ # 78[0-2][0-9][0-9]| # 78000-78299
+ # 7[0-7][0-9][0-9][0-9]| # 70000-77999
+ # [0-6][0-9][0-9][0-9][0-9]| # 10000-69999
+ # Part 3
+ # [0-9][0-9][0-9][0-9]| # 1000-9999
+ # [0-9][0-9][0-9]| # 100-999
+ # [0-9][0-9]| # 10-99
+ # [0-9]) # 0-9
+
+ # Part 1: Create an array with all the regexes, as described above.
+ # Prepopulate it with the number itself.
+ number = str(number)
+ expressions = [number]
+
+ # Convert the number to a list, so we can translate digits in it to
+ # expressions.
+ num_list = list(number)
+ num_len = len(num_list)
+
+ # Part 2: Go through all the digits in the number, starting from the end.
+ # Each iteration appends a line to 'expressions'.
+ for index in range (num_len - 1, -1, -1):
+ # Convert this digit back to an integer.
+ digit = int(num_list[index])
+
+ # Part 2.1: No processing if this digit is a zero.
+ if digit == 0:
+ continue
+
+ # Part 2.2: We switch the current digit X by a range "[0-(X-1)]".
+ num_list[index] = '[0-%d]' % (digit - 1)
+
+ # Part 2.3: We set all following digits to be "[0-9]".
+ # Since we just decrementented a digit in a most important position, all
+ # following digits don't matter. The possible numbers will always be smaller
+ # than before we decremented.
+ for next_digit in range(index + 1, num_len):
+ num_list[next_digit] = '[0-9]'
+
+ # Part 2.4: Add this new sub-expression to the list.
+ expressions.append(''.join(num_list))
+
+ # Part 3: We add all the full ranges to match all numbers that are at least
+ # one order of magnitude smaller than the original numbers.
+ for index in range(1, num_len):
+ expressions.append('[0-9]'*index)
+
+ # All done. We now have our final regular expression.
+ regex = '(%s)' % ('|'.join(expressions))
+ return regex
+
+
+def Search(git_repo, svn_rev, is_mirror, refspec='FETCH_HEAD', fetch_url=None):
+ """Return the Git commit id fuzzy matching the given SVN revision.
+
+ If fetch_url is not None, will update repo if revision is not found."""
+ _, output = Git(git_repo, 'cat-file commit %s' % refspec, is_mirror)
+ match = re.match(r'git-svn-id: [^\s@]+@(\d+) \S+$', output.splitlines()[-1])
+ assert match, 'no match on %s' % output
+ if int(match.group(1)) < int(svn_rev) and fetch_url:
+ if VERBOSE:
+ print 'Fetching %s %s [%s < %s]' % (git_repo, refspec,
+ match.group(1), svn_rev)
+ Fetch(git_repo, fetch_url, is_mirror)
+
+ regex = CreateLessThanOrEqualRegex(svn_rev)
+ _, output = Git(
+ git_repo,
+ ('log -E --grep="^git-svn-id: [^@]*@%s [A-Za-z0-9-]*$" '
+ '-1 --format="%%H" %s') % (regex, refspec),
+ is_mirror)
+ output = output.strip()
+
+ print '%s: %s <-> %s' % (git_repo, output, svn_rev)
+ if re.match('^[0-9a-fA-F]{40}$', output):
+ return output
+ raise Exception('Cannot find revision %s in %s' % (svn_rev, git_repo))
diff --git a/chromium/tools/deps2git/svn_to_git_public.py b/chromium/tools/deps2git/svn_to_git_public.py
new file mode 100755
index 00000000000..a1f3baa9cdc
--- /dev/null
+++ b/chromium/tools/deps2git/svn_to_git_public.py
@@ -0,0 +1,172 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""SVN to GIT mapping for the public Chromium repositories."""
+
+import re
+
+
+GIT_HOST = 'https://chromium.googlesource.com/'
+
+BLINK_TRUNK = 'http://src.chromium.org/blink/trunk'
+
+# Used by deps2git.ConvertDepsToGit() as overrides for SVN DEPS. Each entry
+# maps a DEPS path to a DEPS variable identifying the Git hash for its
+# respective repository. Variables are automatically transferred from SVN DEPS
+# to .DEPS.git and converted into variables by deps_utils.Varify().
+DEPS_OVERRIDES = {
+ 'src/third_party/ffmpeg': 'ffmpeg_hash'
+}
+
+
+def SvnUrlToGitUrl(path, svn_url):
+ """Convert a chromium SVN URL to a chromium Git URL."""
+
+ match = re.match(
+ '(http://src.chromium.org/svn|svn://svn.chromium.org/chrome)(/.*)',
+ svn_url)
+ if match:
+ svn_url = match.group(2)
+
+ # A few special cases.
+ if (svn_url ==
+ 'http://sctp-refimpl.googlecode.com/svn/trunk/KERN/usrsctp/usrsctplib'):
+ return (path, GIT_HOST + 'external/usrsctplib.git', GIT_HOST)
+
+ if svn_url == '/trunk/deps/page_cycler/acid3':
+ return (path, GIT_HOST + 'chromium/deps/acid3.git', GIT_HOST)
+
+ if svn_url == '/trunk/deps/canvas_bench':
+ return (path, GIT_HOST + 'chromium/canvas_bench.git', GIT_HOST)
+
+ if svn_url == '/trunk/deps/gpu/software_rendering_list':
+ return (path, GIT_HOST + 'chromium/deps/gpu/software_rendering_list.git',
+ GIT_HOST)
+
+ if svn_url == '/trunk/tools/third_party/python_26':
+ return (path, GIT_HOST + 'chromium/deps/python_26.git', GIT_HOST)
+
+ if svn_url == '/trunk/deps/support':
+ return (path, GIT_HOST + 'chromium/support.git', GIT_HOST)
+
+ if svn_url == '/trunk/deps/frame_rate/content':
+ return (path, GIT_HOST + 'chromium/frame_rate/content.git', GIT_HOST)
+
+ if svn_url == 'svn://svn.chromium.org/boto':
+ return (path, GIT_HOST + 'external/boto.git', GIT_HOST)
+
+ if svn_url == 'svn://svn.chromium.org/gsutil/trunk/src':
+ return (path, GIT_HOST + 'external/gsutil/src.git', GIT_HOST)
+
+ if svn_url == 'svn://svn.chromium.org/jsoncpp/trunk/jsoncpp':
+ return (path, GIT_HOST + 'external/jsoncpp/jsoncpp.git', GIT_HOST)
+
+ if svn_url == '/trunk/deps/third_party/ffmpeg':
+ return (path, GIT_HOST + 'chromium/third_party/ffmpeg.git', GIT_HOST)
+
+ if svn_url == '/trunk/deps/cdm':
+ return (path, GIT_HOST + 'chromium/cdm.git', GIT_HOST)
+
+ if svn_url == 'http://webrtc.googlecode.com/svn/stable/webrtc':
+ return (path, GIT_HOST + 'external/webrtc/stable/webrtc.git', GIT_HOST)
+
+ if svn_url == 'http://webrtc.googlecode.com/svn/stable/talk':
+ return (path, GIT_HOST + 'external/webrtc/stable/talk.git', GIT_HOST)
+
+ if svn_url == 'http://webrtc.googlecode.com/svn/stable/src':
+ return (path, GIT_HOST + 'external/webrtc/stable/src.git', GIT_HOST)
+
+ if svn_url == 'http://webrtc.googlecode.com/svn/deps/third_party/openmax':
+ return (path, GIT_HOST + 'external/webrtc/deps/third_party/openmax.git',
+ GIT_HOST)
+
+ if svn_url in ('http://selenium.googlecode.com/svn/trunk/py/test',
+ '/trunk/deps/reference_builds/chrome'):
+ # Those can't be git svn cloned. Skipping for now.
+ return
+
+ # Projects on sourceforge using trunk
+ match = re.match('http?://(.*).svn.sourceforge.net/svnroot/(.*)/trunk(.*)',
+ svn_url)
+ if match:
+ repo = '%s%s.git' % (match.group(2), match.group(3))
+ return (path, GIT_HOST + 'external/%s' % repo, GIT_HOST)
+
+ # Projects on googlecode.com using trunk.
+ match = re.match('http?://(.*).googlecode.com/svn/trunk(.*)', svn_url)
+ if match:
+ repo = '%s%s.git' % (match.group(1), match.group(2))
+ return (path, GIT_HOST + 'external/%s' % repo, GIT_HOST)
+
+ # Projects on googlecode.com using branches.
+ # Branches should be automatically included in the projects corresponding
+ # 'trunk' mirror as 'branch-heads' refspecs.
+ # This makes some broad assumptions about a "standard" branch layout , i.e.:
+ # svn/branches/<branch_name>/<optional_sub_path>
+ # This layout can't really be enforced, though it appears to apply to most
+ # repos. Outliers will have to be special-cased.
+ match = re.match('http://(.*).googlecode.com/svn/branches/([^/]+)(.*)',
+ svn_url)
+ if match:
+ repo = '%s%s.git' % (match.group(1), match.group(3))
+ branch_name = match.group(2)
+ return (path, GIT_HOST + 'external/%s' % repo, branch_name, GIT_HOST)
+
+ # Projects that are subdirectories of the native_client repository.
+ match = re.match('http://src.chromium.org/native_client/trunk/(.*)', svn_url)
+ if match:
+ repo = '%s.git' % match.group(1)
+ return (path, GIT_HOST + 'native_client/%s' % repo, GIT_HOST)
+
+ # Projects that are subdirectories of the chromium/{src,tools} repository.
+ match = re.match('/trunk/((src|tools)/.*)', svn_url)
+ if match:
+ repo = '%s.git' % match.group(1)
+ return (path, GIT_HOST + 'chromium/%s' % repo, GIT_HOST)
+
+ # Public-header-only blink directory for iOS.
+ if svn_url == (BLINK_TRUNK + '/public'):
+ return (path, GIT_HOST + 'chromium/blink-public.git', GIT_HOST)
+
+ # Main blink directory.
+ if svn_url == BLINK_TRUNK:
+ return (path, GIT_HOST + 'chromium/blink.git', GIT_HOST)
+
+ # Minimal header-only webkit directories for iOS.
+ if svn_url == ('http://svn.webkit.org/repository/webkit/trunk/Source/' +
+ 'WebKit/chromium/public'):
+ return (path,
+ GIT_HOST + 'external/WebKit/Source/WebKit/chromium/public.git',
+ GIT_HOST)
+ if svn_url == ('http://svn.webkit.org/repository/webkit/trunk/Source/' +
+ 'Platform/chromium/public'):
+ return (path,
+ GIT_HOST + 'external/WebKit/Source/Platform/chromium/public.git',
+ GIT_HOST)
+
+ # Ignore all webkit directories (other than the above), since we fetch the
+ # whole thing directly for all but iOS.
+ if svn_url == '/trunk/deps/third_party/WebKit':
+ return
+
+ if svn_url.startswith(BLINK_TRUNK):
+ return
+
+ # blink
+
+ # Subdirectories of the chromium deps/third_party directory.
+ match = re.match('/trunk/deps/third_party/(.*)', svn_url)
+ if match:
+ repo = '%s.git' % match.group(1)
+ return (path, GIT_HOST + 'chromium/deps/%s' % repo, GIT_HOST)
+
+ # Subdirectories of the chromium deps/reference_builds directory.
+ match = re.match('/trunk/deps/reference_builds/(.*)', svn_url)
+ if match:
+ repo = '%s.git' % match.group(1)
+ return (path, GIT_HOST + 'chromium/reference_builds/%s' % repo, GIT_HOST)
+
+ # Nothing yet? Oops.
+ print 'No match for %s' % svn_url
diff --git a/chromium/tools/diagnose-me.py b/chromium/tools/diagnose-me.py
new file mode 100755
index 00000000000..bbd9429cb1e
--- /dev/null
+++ b/chromium/tools/diagnose-me.py
@@ -0,0 +1,95 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Diagnose some common system configuration problems on Linux, and
+suggest fixes."""
+
+import os
+import subprocess
+import sys
+
+all_checks = []
+
+def Check(name):
+ """Decorator that defines a diagnostic check."""
+ def wrap(func):
+ all_checks.append((name, func))
+ return func
+ return wrap
+
+
+@Check("/usr/bin/ld is not gold")
+def CheckSystemLd():
+ proc = subprocess.Popen(['/usr/bin/ld', '-v'], stdout=subprocess.PIPE)
+ stdout = proc.communicate()[0]
+ if 'GNU gold' in stdout:
+ return ("When /usr/bin/ld is gold, system updates can silently\n"
+ "corrupt your graphics drivers.\n"
+ "Try 'sudo apt-get remove binutils-gold'.\n")
+ return None
+
+
+@Check("random lds are not in the $PATH")
+def CheckPathLd():
+ proc = subprocess.Popen(['which', '-a', 'ld'], stdout=subprocess.PIPE)
+ stdout = proc.communicate()[0]
+ instances = stdout.split()
+ if len(instances) > 1:
+ return ("You have multiple 'ld' binaries in your $PATH:\n"
+ + '\n'.join(' - ' + i for i in instances) + "\n"
+ "You should delete all of them but your system one.\n"
+ "gold is hooked into your build via gyp.\n")
+ return None
+
+
+@Check("/usr/bin/ld doesn't point to gold")
+def CheckLocalGold():
+ # Check /usr/bin/ld* symlinks.
+ for path in ('ld.bfd', 'ld'):
+ path = '/usr/bin/' + path
+ try:
+ target = os.readlink(path)
+ except OSError, e:
+ if e.errno == 2:
+ continue # No such file
+ if e.errno == 22:
+ continue # Not a symlink
+ raise
+ if '/usr/local/gold' in target:
+ return ("%s is a symlink into /usr/local/gold.\n"
+ "It's difficult to make a recommendation, because you\n"
+ "probably set this up yourself. But you should make\n"
+ "/usr/bin/ld be the standard linker, which you likely\n"
+ "renamed /usr/bin/ld.bfd or something like that.\n" % path)
+
+ return None
+
+
+@Check("random ninja binaries are not in the $PATH")
+def CheckPathNinja():
+ proc = subprocess.Popen(['which', 'ninja'], stdout=subprocess.PIPE)
+ stdout = proc.communicate()[0]
+ if not 'depot_tools' in stdout:
+ return ("The ninja binary in your path isn't from depot_tools:\n"
+ + " " + stdout +
+ "Remove custom ninjas from your path so that the one\n"
+ "in depot_tools is used.\n")
+ return None
+
+
+def RunChecks():
+ for name, check in all_checks:
+ sys.stdout.write("* Checking %s: " % name)
+ sys.stdout.flush()
+ error = check()
+ if not error:
+ print "ok"
+ else:
+ print "FAIL"
+ print error
+
+
+if __name__ == '__main__':
+ RunChecks()
diff --git a/chromium/tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py b/chromium/tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py
new file mode 100755
index 00000000000..5c4be81c37d
--- /dev/null
+++ b/chromium/tools/dromaeo_benchmark_runner/dromaeo_benchmark_runner.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Dromaeo benchmark automation script.
+
+Script runs dromaeo tests in browsers specified by --browser switch and saves
+results to a spreadsheet on docs.google.com.
+
+Prerequisites:
+1. Install Google Data APIs Python Client Library from
+ http://code.google.com/p/gdata-python-client.
+2. Checkout Dromaeo benchmark from
+ http://src.chromium.org/svn/trunk/src/chrome/test/data/dromaeo and provide
+ local path to it in --dromaeo_home switch.
+3. Create a spreadsheet at http://docs.google.com and specify its name in
+ --spreadsheet switch
+
+Benchmark results are presented in the following format:
+browser | date time
+test 1 name|m11|...|m1n|test 1 average mean| |e11|...|e1n|test 1 average error
+test 2 name|m21|...|m2n|test 2 average mean| |e21|...|e2n|test 2 average error
+...
+
+Here mij is mean run/s in individual dromaeo test i during benchmark run j,
+eij is error in individual dromaeo test i during benchmark run j.
+
+Example usage:
+dromaeo_benchmark_runner.py -b "E:\chromium\src\chrome\Release\chrome.exe"
+ -b "C:\Program Files (x86)\Safari\safari.exe"
+ -b "C:\Program Files (x86)\Opera 10.50 pre-alpha\opera.exe" -n 1
+ -d "E:\chromium\src\chrome\test\data\dromaeo" -f dom -e example@gmail.com
+
+"""
+
+import getpass
+import json
+import os
+import re
+import subprocess
+import time
+import urlparse
+from optparse import OptionParser
+from BaseHTTPServer import HTTPServer
+import SimpleHTTPServer
+import gdata.spreadsheet.service
+
+max_spreadsheet_columns = 20
+test_props = ['mean', 'error']
+
+
+def ParseArguments():
+ parser = OptionParser()
+ parser.add_option("-b", "--browser",
+ action="append", dest="browsers",
+ help="list of browsers to test")
+ parser.add_option("-n", "--run_count", dest="run_count", type="int",
+ default=5, help="number of runs")
+ parser.add_option("-d", "--dromaeo_home", dest="dromaeo_home",
+ help="directory with your dromaeo files")
+ parser.add_option("-p", "--port", dest="port", type="int",
+ default=8080, help="http server port")
+ parser.add_option("-f", "--filter", dest="filter",
+ default="dom", help="dromaeo suite filter")
+ parser.add_option("-e", "--email", dest="email",
+ help="your google docs account")
+ parser.add_option("-s", "--spreadsheet", dest="spreadsheet_title",
+ default="dromaeo",
+ help="your google docs spreadsheet name")
+
+ options = parser.parse_args()[0]
+
+ if not options.dromaeo_home:
+ raise Exception('please specify dromaeo_home')
+
+ return options
+
+
+def KillProcessByName(process_name):
+ process = subprocess.Popen('wmic process get processid, executablepath',
+ stdout=subprocess.PIPE)
+ stdout = str(process.communicate()[0])
+ match = re.search(re.escape(process_name) + '\s+(\d+)', stdout)
+ if match:
+ pid = match.group(1)
+ subprocess.call('taskkill /pid %s' % pid)
+
+
+class SpreadsheetWriter(object):
+ "Utility class for storing benchmarking results in Google spreadsheets."
+
+ def __init__(self, email, spreadsheet_title):
+ '''Login to google docs and search for spreadsheet'''
+
+ self.token_file = os.path.expanduser("~/.dromaeo_bot_auth_token")
+ self.gd_client = gdata.spreadsheet.service.SpreadsheetsService()
+
+ authenticated = False
+ if os.path.exists(self.token_file):
+ token = ''
+ try:
+ file = open(self.token_file, 'r')
+ token = file.read()
+ file.close()
+ self.gd_client.SetClientLoginToken(token)
+ self.gd_client.GetSpreadsheetsFeed()
+ authenticated = True
+ except (IOError, gdata.service.RequestError):
+ pass
+ if not authenticated:
+ self.gd_client.email = email
+ self.gd_client.password = getpass.getpass('Password for %s: ' % email)
+ self.gd_client.source = 'python robot for dromaeo'
+ self.gd_client.ProgrammaticLogin()
+ token = self.gd_client.GetClientLoginToken()
+ try:
+ file = open(self.token_file, 'w')
+ file.write(token)
+ file.close()
+ except (IOError):
+ pass
+ os.chmod(self.token_file, 0600)
+
+ # Search for the spreadsheet with title = spreadsheet_title.
+ spreadsheet_feed = self.gd_client.GetSpreadsheetsFeed()
+ for spreadsheet in spreadsheet_feed.entry:
+ if spreadsheet.title.text == spreadsheet_title:
+ self.spreadsheet_key = spreadsheet.id.text.rsplit('/', 1)[1]
+ if not self.spreadsheet_key:
+ raise Exception('Spreadsheet %s not found' % spreadsheet_title)
+
+ # Get the key of the first worksheet in spreadsheet.
+ worksheet_feed = self.gd_client.GetWorksheetsFeed(self.spreadsheet_key)
+ self.worksheet_key = worksheet_feed.entry[0].id.text.rsplit('/', 1)[1]
+
+ def _InsertRow(self, row):
+ row = dict([('c' + str(i), row[i]) for i in xrange(len(row))])
+ self.gd_client.InsertRow(row, self.spreadsheet_key, self.worksheet_key)
+
+ def _InsertBlankRow(self):
+ self._InsertRow('-' * self.columns_count)
+
+ def PrepareSpreadsheet(self, run_count):
+ """Update cells in worksheet topmost row with service information.
+
+ Calculate column count corresponding to run_count and create worksheet
+ column titles [c0, c1, ...] in the topmost row to speed up spreadsheet
+ updates (it allows to insert a whole row with a single request)
+ """
+
+ # Calculate the number of columns we need to present all test results.
+ self.columns_count = (run_count + 2) * len(test_props)
+ if self.columns_count > max_spreadsheet_columns:
+ # Google spreadsheet has just max_spreadsheet_columns columns.
+ max_run_count = max_spreadsheet_columns / len(test_props) - 2
+ raise Exception('maximum run count is %i' % max_run_count)
+ # Create worksheet column titles [c0, c1, ..., cn].
+ for i in xrange(self.columns_count):
+ self.gd_client.UpdateCell(1, i + 1, 'c' + str(i), self.spreadsheet_key,
+ self.worksheet_key)
+
+ def WriteColumnTitles(self, run_count):
+ "Create titles for test results (mean 1, mean 2, ..., average mean, ...)"
+ row = []
+ for prop in test_props:
+ row.append('')
+ for i in xrange(run_count):
+ row.append('%s %i' % (prop, i + 1))
+ row.append('average ' + prop)
+ self._InsertRow(row)
+
+ def WriteBrowserBenchmarkTitle(self, browser_name):
+ "Create browser benchmark title (browser name, date time)"
+ self._InsertBlankRow()
+ self._InsertRow([browser_name, time.strftime('%d.%m.%Y %H:%M:%S')])
+
+ def WriteBrowserBenchmarkResults(self, test_name, test_data):
+ "Insert a row with single test results"
+ row = []
+ for prop in test_props:
+ if not row:
+ row.append(test_name)
+ else:
+ row.append('')
+ row.extend([str(x) for x in test_data[prop]])
+ row.append(str(sum(test_data[prop]) / len(test_data[prop])))
+ self._InsertRow(row)
+
+
+class DromaeoHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+
+ def do_POST(self):
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write("<HTML>POST OK.<BR><BR>");
+ length = int(self.headers.getheader('content-length'))
+ parameters = urlparse.parse_qs(self.rfile.read(length))
+ self.server.got_post = True
+ self.server.post_data = parameters['data']
+
+
+class BenchmarkResults(object):
+ "Storage class for dromaeo benchmark results"
+
+ def __init__(self):
+ self.data = {}
+
+ def ProcessBrowserPostData(self, data):
+ "Convert dromaeo test results in internal format"
+ tests = json.loads(data[0])
+ for test in tests:
+ test_name = test['name']
+ if test_name not in self.data:
+ # Test is encountered for the first time.
+ self.data[test_name] = dict([(prop, []) for prop in test_props])
+ # Append current run results.
+ for prop in test_props:
+ value = -1
+ if prop in test: value = test[prop] # workaround for Opera 10.5
+ self.data[test_name][prop].append(value)
+
+
+def main():
+ options = ParseArguments()
+
+ # Start sever with dromaeo.
+ os.chdir(options.dromaeo_home)
+ server = HTTPServer(('', options.port), DromaeoHandler)
+
+ # Open and prepare spreadsheet on google docs.
+ spreadsheet_writer = SpreadsheetWriter(options.email,
+ options.spreadsheet_title)
+ spreadsheet_writer.PrepareSpreadsheet(options.run_count)
+ spreadsheet_writer.WriteColumnTitles(options.run_count)
+
+ for browser in options.browsers:
+ browser_name = os.path.splitext(os.path.basename(browser))[0]
+ spreadsheet_writer.WriteBrowserBenchmarkTitle(browser_name)
+ benchmark_results = BenchmarkResults()
+ for run_number in xrange(options.run_count):
+ print '%s run %i' % (browser_name, run_number + 1)
+ # Run browser.
+ test_page = 'http://localhost:%i/index.html?%s&automated&post_json' % (
+ options.port, options.filter)
+ browser_process = subprocess.Popen('%s "%s"' % (browser, test_page))
+ server.got_post = False
+ server.post_data = None
+ # Wait until POST request from browser.
+ while not server.got_post:
+ server.handle_request()
+ benchmark_results.ProcessBrowserPostData(server.post_data)
+ # Kill browser.
+ KillProcessByName(browser)
+ browser_process.wait()
+
+ # Insert test results into spreadsheet.
+ for (test_name, test_data) in benchmark_results.data.iteritems():
+ spreadsheet_writer.WriteBrowserBenchmarkResults(test_name, test_data)
+
+ server.socket.close()
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/emacs/chrome-filetypes.el b/chromium/tools/emacs/chrome-filetypes.el
new file mode 100644
index 00000000000..14fc6bbaef3
--- /dev/null
+++ b/chromium/tools/emacs/chrome-filetypes.el
@@ -0,0 +1,16 @@
+; To get syntax highlighting and tab settings for gyp(i) files, add the
+; following to init.el:
+; (setq-default chrome-root "/path/to/chrome/src/")
+; (add-to-list 'load-path (concat chrome-root "tools/emacs"))
+; (require 'chrome-filetypes)
+
+(define-derived-mode gyp-mode python-mode "Gyp"
+ "Major mode for editing Generate Your Project files."
+ (setq indent-tabs-mode nil
+ tab-width 2
+ python-indent 2))
+
+(add-to-list 'auto-mode-alist '("\\.gyp$" . gyp-mode))
+(add-to-list 'auto-mode-alist '("\\.gypi$" . gyp-mode))
+
+(provide 'chrome-filetypes)
diff --git a/chromium/tools/emacs/flymake-chromium.el b/chromium/tools/emacs/flymake-chromium.el
new file mode 100644
index 00000000000..8adb0dbe56a
--- /dev/null
+++ b/chromium/tools/emacs/flymake-chromium.el
@@ -0,0 +1,122 @@
+;; Copyright (c) 2011 The Chromium Authors. All rights reserved.
+;; Use of this source code is governed by a BSD-style license that can be
+;; found in the LICENSE file.
+
+;; Set up flymake for use with chromium code. Uses ninja (since none of the
+;; other chromium build systems have latency that allows interactive use).
+;;
+;; Requires a modern emacs (GNU Emacs >= 23) and that gyp has already generated
+;; the build.ninja file(s). See defcustoms below for settable knobs.
+
+
+(require 'flymake)
+
+(defcustom cr-flymake-ninja-build-file "out/Debug/build.ninja"
+ "Relative path from chromium's src/ directory to the
+ build.ninja file to use.")
+
+(defcustom cr-flymake-ninja-executable "ninja"
+ "Ninja executable location; either in $PATH or explicitly given.")
+
+(defun cr-flymake-absbufferpath ()
+ "Return the absolute path to the current buffer, or nil if the
+ current buffer has no path."
+ (when buffer-file-truename
+ (expand-file-name buffer-file-truename)))
+
+(defun cr-flymake-chromium-src ()
+ "Return chromium's src/ directory, or nil on failure."
+ (let ((srcdir (locate-dominating-file
+ (cr-flymake-absbufferpath) cr-flymake-ninja-build-file)))
+ (when srcdir (expand-file-name srcdir))))
+
+(defun cr-flymake-string-prefix-p (prefix str)
+ "Return non-nil if PREFIX is a prefix of STR (23.2 has string-prefix-p but
+ that's case insensitive and also 23.1 doesn't have it)."
+ (string= prefix (substring str 0 (length prefix))))
+
+(defun cr-flymake-current-file-name ()
+ "Return the relative path from chromium's src/ directory to the
+ file backing the current buffer or nil if it doesn't look like
+ we're under chromium/src/."
+ (when (and (cr-flymake-chromium-src)
+ (cr-flymake-string-prefix-p
+ (cr-flymake-chromium-src) (cr-flymake-absbufferpath)))
+ (substring (cr-flymake-absbufferpath) (length (cr-flymake-chromium-src)))))
+
+(defun cr-flymake-from-build-to-src-root ()
+ "Return a path fragment for getting from the build.ninja file to src/."
+ (replace-regexp-in-string
+ "[^/]+" ".."
+ (substring
+ (file-name-directory
+ (file-truename (or (and (cr-flymake-string-prefix-p
+ "/" cr-flymake-ninja-build-file)
+ cr-flymake-ninja-build-file)
+ (concat (cr-flymake-chromium-src)
+ cr-flymake-ninja-build-file))))
+ (length (cr-flymake-chromium-src)))))
+
+(defun cr-flymake-getfname (file-name-from-error-message)
+ "Strip cruft from the passed-in filename to help flymake find the real file."
+ (file-name-nondirectory file-name-from-error-message))
+
+(defun cr-flymake-ninja-command-line ()
+ "Return the command-line for running ninja, as a list of strings, or nil if
+ we're not during a save"
+ (unless (buffer-modified-p)
+ (list cr-flymake-ninja-executable
+ (list "-C"
+ (concat (cr-flymake-chromium-src)
+ (file-name-directory cr-flymake-ninja-build-file))
+ (concat (cr-flymake-from-build-to-src-root)
+ (cr-flymake-current-file-name) "^")))))
+
+(defun cr-flymake-kick-off-check-after-save ()
+ "Kick off a syntax check after file save, if flymake-mode is on."
+ (when flymake-mode (flymake-start-syntax-check)))
+
+(defadvice next-error (around cr-flymake-next-error activate)
+ "If flymake has something to say, let it say it; otherwise
+ revert to normal next-error behavior."
+ (if (not flymake-err-info)
+ (condition-case msg
+ ad-do-it
+ (error (message "%s" (prin1-to-string msg))))
+ (flymake-goto-next-error)
+ ;; copy/pasted from flymake-display-err-menu-for-current-line because I
+ ;; couldn't find a way to have it tell me what the relevant error for this
+ ;; line was in a single call:
+ (let* ((line-no (flymake-current-line-no))
+ (line-err-info-list
+ (nth 0 (flymake-find-err-info flymake-err-info line-no)))
+ (menu-data (flymake-make-err-menu-data line-no line-err-info-list)))
+ (prin1 (car (car (car (cdr menu-data)))) t))))
+
+(defun cr-flymake-find-file ()
+ "Enable flymake, but only if it makes sense, and immediately
+ disable timer-based execution."
+ (when (and (not flymake-mode)
+ (not buffer-read-only)
+ (cr-flymake-current-file-name))
+ ;; Since flymake-allowed-file-name-masks requires static regexps to match
+ ;; against, can't use cr-flymake-chromium-src here. Instead we add a
+ ;; generic regexp, but only to a buffer-local version of the variable.
+ (set (make-local-variable 'flymake-allowed-file-name-masks)
+ (list (list "\\.c\\(\\|c\\|pp\\)"
+ 'cr-flymake-ninja-command-line
+ 'ignore
+ 'cr-flymake-getfname)))
+ (flymake-find-file-hook)
+ (if flymake-mode
+ (cancel-timer flymake-timer)
+ (kill-local-variable 'flymake-allowed-file-name-masks))))
+
+(add-hook 'find-file-hook 'cr-flymake-find-file 'append)
+(add-hook 'after-save-hook 'cr-flymake-kick-off-check-after-save)
+
+;; Show flymake infrastructure ERRORs in hopes of fixing them. Set to 3 for
+;; DEBUG-level output from flymake.el.
+(setq flymake-log-level 0)
+
+(provide 'flymake-chromium)
diff --git a/chromium/tools/emacs/trybot-linux.txt b/chromium/tools/emacs/trybot-linux.txt
new file mode 100644
index 00000000000..ad3ada8de5d
--- /dev/null
+++ b/chromium/tools/emacs/trybot-linux.txt
@@ -0,0 +1,6 @@
+A snippet of Linux trybot output (note UTF-8 quotes).
+
+ AR(target) out/Debug/obj.target/printing/libprinting.a
+app/l10n_util_unittest.cc: In member function ‘virtual void L10nUtilTest_TruncateString_Test::TestBody()’:
+app/l10n_util_unittest.cc:67: error: invalid initialization of reference of type ‘const string16&’ from expression of type ‘std::wstring’
+./app/l10n_util.h:166: error: in passing argument 1 of ‘string16 l10n_util::TruncateString(const string16&, size_t)’
diff --git a/chromium/tools/emacs/trybot-mac.txt b/chromium/tools/emacs/trybot-mac.txt
new file mode 100644
index 00000000000..87d7f26212c
--- /dev/null
+++ b/chromium/tools/emacs/trybot-mac.txt
@@ -0,0 +1,1985 @@
+/b/build/third_party/zope/__init__.py:19: UserWarning: Module twisted was already imported from /b/build/third_party/twisted_8_1/twisted/__init__.pyc, but /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python is being added to sys.path
+ import pkg_resources
+/b/build/third_party/zope/__init__.py:19: UserWarning: Module zope was already imported from /b/build/third_party/zope/__init__.pyc, but /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python is being added to sys.path
+ import pkg_resources
+
+pump xcodebuild -configuration Debug -project all.xcodeproj -buildhostsfile /b/build/scripts/slave/mac_distcc_hosts/golo_mini-10_6
+__________Using distcc-pump from /usr/bin
+__________Using 1 distcc server in pump mode
+
+=== BUILD AGGREGATE TARGET app_resources OF PROJECT app WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET app_strings OF PROJECT app WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"grit\"" ../xcodebuild/app.build/Debug/app_strings.build/Script-3555EADE2A4F7996024F949F.sh
+ cd /b/build/slave/mac/build/src/app
+ /bin/sh -c /b/build/slave/mac/build/src/app/../xcodebuild/app.build/Debug/app_strings.build/Script-3555EADE2A4F7996024F949F.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET app_base Support OF PROJECT app WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET app_base OF PROJECT app WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET test_support_base OF PROJECT base WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET protobuf_full_do_not_use OF PROJECT protobuf WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET protobuf_lite OF PROJECT protobuf WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET protoc OF PROJECT protobuf WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/protobuf.build/Debug/protoc.build/Script-7AC9923F7CDD2087661C69AB.sh
+ cd /b/build/slave/mac/build/src/third_party/protobuf
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/protobuf/../../xcodebuild/protobuf.build/Debug/protoc.build/Script-7AC9923F7CDD2087661C69AB.sh
+
+
+=== BUILD AGGREGATE TARGET sync_proto OF PROJECT sync_proto WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../../../../xcodebuild/sync_proto.build/Debug/sync_proto.build/Script-237DAA9DBF3380A9B7228EAF.sh
+ cd /b/build/slave/mac/build/src/chrome/browser/sync/protocol
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/browser/sync/protocol/../../../../xcodebuild/sync_proto.build/Debug/sync_proto.build/Script-237DAA9DBF3380A9B7228EAF.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET device_management_proto OF PROJECT device_management_proto WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../../../../xcodebuild/device_management_proto.build/Debug/device_management_proto.build/Script-7D8C1925B70AD3724821C80A.sh
+ cd /b/build/slave/mac/build/src/chrome/browser/policy/proto
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/browser/policy/proto/../../../../xcodebuild/device_management_proto.build/Debug/device_management_proto.build/Script-7D8C1925B70AD3724821C80A.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET py_proto OF PROJECT protobuf WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET net_test_support OF PROJECT net WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET skia OF PROJECT skia WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET gmock OF PROJECT gmock WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET gtest OF PROJECT gtest WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET icui18n OF PROJECT icu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET icuuc OF PROJECT icu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET libpng OF PROJECT libpng WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET zlib OF PROJECT zlib WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET libjpeg OF PROJECT libjpeg WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET base OF PROJECT base WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET modp_b64 OF PROJECT modp_b64 WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET dynamic_annotations OF PROJECT dynamic_annotations WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET nss OF PROJECT nss WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET nspr OF PROJECT nss WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET sqlite OF PROJECT sqlite WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET icudata OF PROJECT icu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET libevent OF PROJECT libevent WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET base_i18n OF PROJECT base WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET gfx_resources OF PROJECT gfx WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET gfx OF PROJECT gfx WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET skia_opts OF PROJECT skia WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET net_resources OF PROJECT net WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"grit\"" ../xcodebuild/net.build/Debug/net_resources.build/Script-D3210C5A91652E9B8F9DF7BD.sh
+ cd /b/build/slave/mac/build/src/net
+ /bin/sh -c /b/build/slave/mac/build/src/net/../xcodebuild/net.build/Debug/net_resources.build/Script-D3210C5A91652E9B8F9DF7BD.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET js2c OF PROJECT v8 WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET v8_nosnapshot OF PROJECT v8 WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET v8_base OF PROJECT v8 WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET mksnapshot OF PROJECT v8 WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../../xcodebuild/v8.build/Debug/mksnapshot.build/Script-759699424E9CDB8D5A56B17D.sh
+ cd /b/build/slave/mac/build/src/v8/tools/gyp
+ /bin/sh -c /b/build/slave/mac/build/src/v8/tools/gyp/../../../xcodebuild/v8.build/Debug/mksnapshot.build/Script-759699424E9CDB8D5A56B17D.sh
+
+
+=== BUILD AGGREGATE TARGET v8_snapshot Support OF PROJECT v8 WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET v8_snapshot OF PROJECT v8 WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET v8 OF PROJECT v8 WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET net OF PROJECT net WITH CONFIGURATION Debug ===
+Check dependencies
+Distributed-CompileC ../xcodebuild/net.build/Debug/net.build/Objects-normal/i386/spdy_session.o spdy/spdy_session.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/net
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS localhost
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNO_NSPR_10_SUPPORT -DNSS_USE_STATIC_LIBS -DUSE_UTIL_DIRECTLY -DNSS_PLATFORM_CLIENT_AUTH -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/net/../xcodebuild/Debug -I/b/build/slave/mac/build/src/net/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../sdch/open-vcdiff/src -I../third_party/zlib -I/b/build/slave/mac/build/src/net/../xcodebuild/DerivedSources/Debug/net -I../v8/include -I../third_party/nss/mozilla/nsprpub/pr/include -I../third_party/nss/mozilla/nsprpub/lib/ds -I../third_party/nss/mozilla/nsprpub/lib/libc/include -I../third_party/nss/mozilla/security/nss/lib/base -I../third_party/nss/mozilla/security/nss/lib/certdb -I../third_party/nss/mozilla/security/nss/lib/certhigh -I../third_party/nss/mozilla/security/nss/lib/cryptohi -I../third_party/nss/mozilla/security/nss/lib/dev -I../third_party/nss/mozilla/security/nss/lib/freebl -I../third_party/nss/mozilla/security/nss/lib/freebl/ecl -I../third_party/nss/mozilla/security/nss/lib/nss -I../third_party/nss/mozilla/security/nss/lib/pk11wrap -I../third_party/nss/mozilla/security/nss/lib/pkcs7 -I../third_party/nss/mozilla/security/nss/lib/pki -I../third_party/nss/mozilla/security/nss/lib/smime -I../third_party/nss/mozilla/security/nss/lib/softoken -I../third_party/nss/mozilla/security/nss/lib/util -Ithird_party/nss/ssl -I/b/build/slave/mac/build/src/net/../xcodebuild/net.build/Debug/net.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/net/../xcodebuild/net.build/Debug/net.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/net/spdy/spdy_session.cc -o /b/build/slave/mac/build/src/net/../xcodebuild/net.build/Debug/net.build/Objects-normal/i386/spdy_session.o
+
+Libtool ../xcodebuild/Debug/libnet.a normal i386
+ cd /b/build/slave/mac/build/src/net
+ setenv DISTCC_HOSTS "distcc4.golo.chromium.org:3632,lzo,cpp/0 distcc7.golo.chromium.org:3632,lzo,cpp/0 distcc8.golo.chromium.org:3632,lzo,cpp/0 distcc10.golo.chromium.org:3632,lzo,cpp/0 distcc6.golo.chromium.org:3632,lzo,cpp/0 distcc3.golo.chromium.org:3632,lzo,cpp/0 distcc2.golo.chromium.org:3632,lzo,cpp/0 distcc1.golo.chromium.org:3632,lzo,cpp/0 distcc9.golo.chromium.org:3632,lzo,cpp/0 distcc5.golo.chromium.org:3632,lzo,cpp/0"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv MACOSX_DEPLOYMENT_TARGET 10.5
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/libtool -static -arch_only i386 -syslibroot /Developer/SDKs/MacOSX10.5.sdk -L/b/build/slave/mac/build/src/net/../xcodebuild/Debug -filelist /b/build/slave/mac/build/src/net/../xcodebuild/net.build/Debug/net.build/Objects-normal/i386/net.LinkFileList -o /b/build/slave/mac/build/src/net/../xcodebuild/Debug/libnet.a
+
+
+=== BUILD NATIVE TARGET googleurl OF PROJECT googleurl WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET sdch OF PROJECT sdch WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET ssl_false_start_blacklist_process OF PROJECT net WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../xcodebuild/net.build/Debug/ssl_false_start_blacklist_process.build/Script-5AC333953C6BB680BA591B7D.sh
+ cd /b/build/slave/mac/build/src/net
+ /bin/sh -c /b/build/slave/mac/build/src/net/../xcodebuild/net.build/Debug/ssl_false_start_blacklist_process.build/Script-5AC333953C6BB680BA591B7D.sh
+
+
+=== BUILD AGGREGATE TARGET net_base Support OF PROJECT net WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET net_base OF PROJECT net WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET ssl_host_info Support OF PROJECT net WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" "../xcodebuild/net.build/Debug/ssl_host_info Support.build/Script-2ECF060B764178F116E30CEF.sh"
+ cd /b/build/slave/mac/build/src/net
+ /bin/sh -c "\"/b/build/slave/mac/build/src/net/../xcodebuild/net.build/Debug/ssl_host_info Support.build/Script-2ECF060B764178F116E30CEF.sh\""
+
+make: Nothing to be done for `all'.
+
+=== BUILD NATIVE TARGET ssl_host_info OF PROJECT net WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET ssl OF PROJECT ssl WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET app_unittests OF PROJECT app WITH CONFIGURATION Debug ===
+Check dependencies
+Ld ../xcodebuild/Debug/app_unittests normal i386
+ cd /b/build/slave/mac/build/src/app
+ setenv DISTCC_HOSTS "distcc4.golo.chromium.org:3632,lzo,cpp/0 distcc7.golo.chromium.org:3632,lzo,cpp/0 distcc8.golo.chromium.org:3632,lzo,cpp/0 distcc10.golo.chromium.org:3632,lzo,cpp/0 distcc6.golo.chromium.org:3632,lzo,cpp/0 distcc3.golo.chromium.org:3632,lzo,cpp/0 distcc2.golo.chromium.org:3632,lzo,cpp/0 distcc1.golo.chromium.org:3632,lzo,cpp/0 distcc9.golo.chromium.org:3632,lzo,cpp/0 distcc5.golo.chromium.org:3632,lzo,cpp/0"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv MACOSX_DEPLOYMENT_TARGET 10.5
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/g++-4.2 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk -L/b/build/slave/mac/build/src/app/../xcodebuild/Debug -F/b/build/slave/mac/build/src/app/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -filelist /b/build/slave/mac/build/src/app/../xcodebuild/app.build/Debug/app_unittests.build/Objects-normal/i386/app_unittests.LinkFileList -mmacosx-version-min=10.5 -Wl,-search_paths_first -lapp_base /b/build/slave/mac/build/src/xcodebuild/Debug/libtest_support_base.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnet_test_support.a /b/build/slave/mac/build/src/xcodebuild/Debug/libskia.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgmock.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgtest.a /b/build/slave/mac/build/src/xcodebuild/Debug/libicui18n.a /b/build/slave/mac/build/src/xcodebuild/Debug/libicuuc.a /b/build/slave/mac/build/src/xcodebuild/Debug/libpng.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchrome_zlib.a /b/build/slave/mac/build/src/xcodebuild/Debug/libjpeg.a /b/build/slave/mac/build/src/xcodebuild/Debug/libbase.a /b/build/slave/mac/build/src/xcodebuild/Debug/libmodp_b64.a /b/build/slave/mac/build/src/xcodebuild/Debug/libdynamic_annotations.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnss.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnspr.a /b/build/slave/mac/build/src/xcodebuild/Debug/libsqlite3.a /b/build/slave/mac/build/src/xcodebuild/Debug/libicudata.a /b/build/slave/mac/build/src/xcodebuild/Debug/libevent.a /b/build/slave/mac/build/src/xcodebuild/Debug/libbase_i18n.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgfx.a /b/build/slave/mac/build/src/xcodebuild/Debug/libskia_opts.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnet.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgoogleurl.a /b/build/slave/mac/build/src/xcodebuild/Debug/libsdch.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnet_base.a /b/build/slave/mac/build/src/xcodebuild/Debug/libssl_host_info.a /b/build/slave/mac/build/src/xcodebuild/Debug/libprotobuf_lite.a /b/build/slave/mac/build/src/xcodebuild/Debug/libv8_snapshot.a /b/build/slave/mac/build/src/xcodebuild/Debug/libv8_base.a /b/build/slave/mac/build/src/xcodebuild/Debug/libssl.a -framework OpenGL -framework AppKit -framework Carbon -framework CoreFoundation -framework Foundation -framework IOKit -framework Security -framework SystemConfiguration -lresolv -o /b/build/slave/mac/build/src/app/../xcodebuild/Debug/app_unittests
+
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../xcodebuild/app.build/Debug/app_unittests.build/Script-07E688F6B96AA35A01000844.sh
+ cd /b/build/slave/mac/build/src/app
+ /bin/sh -c /b/build/slave/mac/build/src/app/../xcodebuild/app.build/Debug/app_unittests.build/Script-07E688F6B96AA35A01000844.sh
+
+
+=== BUILD NATIVE TARGET base_unittests OF PROJECT base WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../xcodebuild/base.build/Debug/base_unittests.build/Script-25445A6E87471CA82F7A2A04.sh
+ cd /b/build/slave/mac/build/src/base
+ /bin/sh -c /b/build/slave/mac/build/src/base/../xcodebuild/base.build/Debug/base_unittests.build/Script-25445A6E87471CA82F7A2A04.sh
+
+
+=== BUILD NATIVE TARGET test_support_perf OF PROJECT base WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET common_constants Support OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET common_constants OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET cacheinvalidation_proto OF PROJECT cacheinvalidation WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../../xcodebuild/cacheinvalidation.build/Debug/cacheinvalidation_proto.build/Script-F6284ABD289942E92747985A.sh
+ cd /b/build/slave/mac/build/src/third_party/cacheinvalidation
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/cacheinvalidation/../../xcodebuild/cacheinvalidation.build/Debug/cacheinvalidation_proto.build/Script-F6284ABD289942E92747985A.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD NATIVE TARGET cacheinvalidation OF PROJECT cacheinvalidation WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET sync_notifier OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET notifier OF PROJECT jingle WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET libjingle OF PROJECT libjingle WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET sync_proto_cpp OF PROJECT sync_proto WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET sync OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET chrome_resources OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"grit\"" ../xcodebuild/chrome.build/Debug/chrome_resources.build/Script-9CA0E2FB3E57937086B90B01.sh
+ cd /b/build/slave/mac/build/src/chrome
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/chrome_resources.build/Script-9CA0E2FB3E57937086B90B01.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET chrome_strings OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"grit\"" ../xcodebuild/chrome.build/Debug/chrome_strings.build/Script-E0610D9F312AEECB2F90C4E3.sh
+ cd /b/build/slave/mac/build/src/chrome
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/chrome_strings.build/Script-E0610D9F312AEECB2F90C4E3.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET theme_resources OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET npapi OF PROJECT npapi WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET ppapi_c OF PROJECT ppapi WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET webkit_resources OF PROJECT webkit_support WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET webkit_strings OF PROJECT webkit_support WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET webkit_user_agent Support OF PROJECT webkit_support WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET webkit_user_agent OF PROJECT webkit_support WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET glue OF PROJECT webkit_support WITH CONFIGURATION Debug ===
+Check dependencies
+Distributed-CompileC ../../xcodebuild/webkit_support.build/Debug/glue.build/Objects-normal/i386/context_menu.o ../glue/context_menu.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/webkit/support
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS localhost
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/webkit/support/../../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/webkit/support/../../xcodebuild/Debug/include -I../../third_party/icu/public/common -I../../third_party/icu/public/i18n -I/b/build/slave/mac/build/src/webkit/support/../../xcodebuild/webkit_support.build/DerivedSources/Debug -I/b/build/slave/mac/build/src/webkit/support/../../xcodebuild/DerivedSources/Debug/webkit -I../../gpu -I../.. -I../../third_party -I../../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/webkit/support/../../xcodebuild/DerivedSources/Debug/app -I../../skia/config -I../../third_party/skia/include/config -I../../third_party/skia/include/core -I../../third_party/skia/include/effects -I../../skia/ext -I../../third_party/npapi -I../../third_party/npapi/bindings -I/b/build/slave/mac/build/src/webkit/support/../../xcodebuild/webkit_support.build/Debug/glue.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/webkit/support/../../xcodebuild/webkit_support.build/Debug/glue.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/webkit/support/../glue/context_menu.cc -o /b/build/slave/mac/build/src/webkit/support/../../xcodebuild/webkit_support.build/Debug/glue.build/Objects-normal/i386/context_menu.o
+
+Libtool ../../xcodebuild/Debug/libglue.a normal i386
+ cd /b/build/slave/mac/build/src/webkit/support
+ setenv DISTCC_HOSTS "distcc4.golo.chromium.org:3632,lzo,cpp/0 distcc7.golo.chromium.org:3632,lzo,cpp/0 distcc8.golo.chromium.org:3632,lzo,cpp/0 distcc10.golo.chromium.org:3632,lzo,cpp/0 distcc6.golo.chromium.org:3632,lzo,cpp/0 distcc3.golo.chromium.org:3632,lzo,cpp/0 distcc2.golo.chromium.org:3632,lzo,cpp/0 distcc1.golo.chromium.org:3632,lzo,cpp/0 distcc9.golo.chromium.org:3632,lzo,cpp/0 distcc5.golo.chromium.org:3632,lzo,cpp/0"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv MACOSX_DEPLOYMENT_TARGET 10.5
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/libtool -static -arch_only i386 -syslibroot /Developer/SDKs/MacOSX10.5.sdk -L/b/build/slave/mac/build/src/webkit/support/../../xcodebuild/Debug -filelist /b/build/slave/mac/build/src/webkit/support/../../xcodebuild/webkit_support.build/Debug/glue.build/Objects-normal/i386/glue.LinkFileList -o /b/build/slave/mac/build/src/webkit/support/../../xcodebuild/Debug/libglue.a
+
+
+=== BUILD NATIVE TARGET common OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/appcache_backend_proxy.o common/appcache/appcache_backend_proxy.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/appcache/appcache_backend_proxy.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/appcache_backend_proxy.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/web_database_observer_impl.o common/web_database_observer_impl.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/web_database_observer_impl.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/web_database_observer_impl.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/database_util.o common/database_util.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/database_util.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/database_util.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/appcache_dispatcher.o common/appcache/appcache_dispatcher.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/appcache/appcache_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/appcache_dispatcher.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/db_message_filter.o common/db_message_filter.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/db_message_filter.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/db_message_filter.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/file_system_dispatcher.o common/file_system/file_system_dispatcher.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/file_system/file_system_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/file_system_dispatcher.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/extension_localization_peer.o common/extensions/extension_localization_peer.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/extensions/extension_localization_peer.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/extension_localization_peer.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/render_messages.o common/render_messages.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/render_messages.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/render_messages.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/socket_stream_dispatcher.o common/socket_stream_dispatcher.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/socket_stream_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/socket_stream_dispatcher.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/render_messages_params.o common/render_messages_params.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/render_messages_params.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/render_messages_params.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/resource_dispatcher.o common/resource_dispatcher.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/resource_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/resource_dispatcher.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/webblobregistry_impl.o common/webblobregistry_impl.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/webblobregistry_impl.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/webblobregistry_impl.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/logging_chrome.o common/logging_chrome.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DLIBXML_STATIC -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I../gpu -I.. -I../third_party -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/sqlite -I../third_party/zlib -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/common/logging_chrome.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/logging_chrome.o
+
+Libtool ../xcodebuild/Debug/libcommon.a normal i386
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_HOSTS "distcc4.golo.chromium.org:3632,lzo,cpp/0 distcc7.golo.chromium.org:3632,lzo,cpp/0 distcc8.golo.chromium.org:3632,lzo,cpp/0 distcc10.golo.chromium.org:3632,lzo,cpp/0 distcc6.golo.chromium.org:3632,lzo,cpp/0 distcc3.golo.chromium.org:3632,lzo,cpp/0 distcc2.golo.chromium.org:3632,lzo,cpp/0 distcc1.golo.chromium.org:3632,lzo,cpp/0 distcc9.golo.chromium.org:3632,lzo,cpp/0 distcc5.golo.chromium.org:3632,lzo,cpp/0"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv MACOSX_DEPLOYMENT_TARGET 10.5
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/libtool -static -arch_only i386 -syslibroot /Developer/SDKs/MacOSX10.5.sdk -L/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -filelist /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/common.build/Objects-normal/i386/common.LinkFileList -o /b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/libcommon.a
+
+
+=== BUILD NATIVE TARGET common_net OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET default_plugin_resources OF PROJECT default_plugin WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET default_plugin OF PROJECT default_plugin WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET libxml OF PROJECT libxml WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET ipc OF PROJECT ipc WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET printing OF PROJECT printing WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET bzip2 OF PROJECT bzip2 WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET appcache OF PROJECT webkit_support WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET blob OF PROJECT webkit_support WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET gles2_implementation OF PROJECT gpu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET gles2_cmd_helper OF PROJECT gpu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET command_buffer_client OF PROJECT gpu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET command_buffer_common OF PROJECT gpu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET ppapi_shared_impl OF PROJECT ppapi WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET gpu_plugin OF PROJECT gpu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET command_buffer_service OF PROJECT gpu WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET translator_glsl OF PROJECT build_angle WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET translator_common OF PROJECT build_angle WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET libvpx_include OF PROJECT libvpx WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET chromotocol_proto OF PROJECT chromotocol WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../../xcodebuild/chromotocol.build/Debug/chromotocol_proto.build/Script-FC778EC6151CD2300601907F.sh
+ cd /b/build/slave/mac/build/src/remoting/proto
+ /bin/sh -c /b/build/slave/mac/build/src/remoting/proto/../../xcodebuild/chromotocol.build/Debug/chromotocol_proto.build/Script-FC778EC6151CD2300601907F.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD NATIVE TARGET chromotocol_proto_lib OF PROJECT chromotocol WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET trace_proto OF PROJECT trace WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../../xcodebuild/trace.build/Debug/trace_proto.build/Script-1767794B043163548BD577A7.sh
+ cd /b/build/slave/mac/build/src/remoting/proto
+ /bin/sh -c /b/build/slave/mac/build/src/remoting/proto/../../xcodebuild/trace.build/Debug/trace_proto.build/Script-1767794B043163548BD577A7.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD NATIVE TARGET trace_proto_lib OF PROJECT trace WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET chromoting_base OF PROJECT remoting WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET chromoting_plugin OF PROJECT remoting WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET config_sources OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET genmacro OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/yasm.build/Debug/genmacro.build/Script-4C7889A20E677CE959D733D8.sh
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/genmacro.build/Script-4C7889A20E677CE959D733D8.sh
+
+
+=== BUILD NATIVE TARGET genmodule OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/yasm.build/Debug/genmodule.build/Script-4889D2DFD6E02E6FD4E5DD23.sh
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/genmodule.build/Script-4889D2DFD6E02E6FD4E5DD23.sh
+
+
+=== BUILD NATIVE TARGET genperf_libs OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET genperf OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/yasm.build/Debug/genperf.build/Script-1D9F9DCA8B66106271900FD2.sh
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/genperf.build/Script-1D9F9DCA8B66106271900FD2.sh
+
+
+=== BUILD NATIVE TARGET genversion OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/yasm.build/Debug/genversion.build/Script-86C7D43B641DD7FA312A063A.sh
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/genversion.build/Script-86C7D43B641DD7FA312A063A.sh
+
+
+=== BUILD AGGREGATE TARGET generate_files OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"generate_gperf\"" ../../xcodebuild/yasm.build/Debug/generate_files.build/Script-17643966799E5C48ACBBC76C.sh
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/generate_files.build/Script-17643966799E5C48ACBBC76C.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD NATIVE TARGET genstring OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/yasm.build/Debug/genstring.build/Script-8C8DB269C91395EE620901FA.sh
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/genstring.build/Script-8C8DB269C91395EE620901FA.sh
+
+
+=== BUILD NATIVE TARGET re2c OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/yasm.build/Debug/re2c.build/Script-80CBF3376FF074DC264D0801.sh
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/re2c.build/Script-80CBF3376FF074DC264D0801.sh
+
+
+=== BUILD AGGREGATE TARGET yasm Support OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"generate_gperf\"" "../../xcodebuild/yasm.build/Debug/yasm Support.build/Script-01D2B874063C3CD35D7BB021.sh"
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c "\"/b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/yasm Support.build/Script-01D2B874063C3CD35D7BB021.sh\""
+
+make: Nothing to be done for `all'.
+PhaseScriptExecution "Rule \"generate_re2c\"" "../../xcodebuild/yasm.build/Debug/yasm Support.build/Script-78F98A3A8E7B6F2F3A9E27E4.sh"
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c "\"/b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/yasm Support.build/Script-78F98A3A8E7B6F2F3A9E27E4.sh\""
+
+make: Nothing to be done for `all'.
+
+=== BUILD NATIVE TARGET yasm OF PROJECT yasm WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/yasm.build/Debug/yasm.build/Script-553C58D6C5752DBCAC66E158.sh
+ cd /b/build/slave/mac/build/src/third_party/yasm
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/yasm/../../xcodebuild/yasm.build/Debug/yasm.build/Script-553C58D6C5752DBCAC66E158.sh
+
+
+=== BUILD AGGREGATE TARGET assemble_ffmpeg_asm OF PROJECT ffmpeg WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"assemble\"" ../../xcodebuild/ffmpeg.build/Debug/assemble_ffmpeg_asm.build/Script-CC0AEB08A28175BFCADB3230.sh
+ cd /b/build/slave/mac/build/src/third_party/ffmpeg
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/ffmpeg/../../xcodebuild/ffmpeg.build/Debug/assemble_ffmpeg_asm.build/Script-CC0AEB08A28175BFCADB3230.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET make_ffmpeg_asm_lib OF PROJECT ffmpeg WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET ffmpegsumo Support OF PROJECT ffmpeg WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET ffmpegsumo OF PROJECT ffmpeg WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/ffmpeg.build/Debug/ffmpegsumo.build/Script-5F4EE13F45F454D1CDFA2E81.sh
+ cd /b/build/slave/mac/build/src/third_party/ffmpeg
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/ffmpeg/../../xcodebuild/ffmpeg.build/Debug/ffmpegsumo.build/Script-5F4EE13F45F454D1CDFA2E81.sh
+
+
+=== BUILD NATIVE TARGET ffmpegsumo_nolink OF PROJECT ffmpeg WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../xcodebuild/ffmpeg.build/Debug/ffmpegsumo_nolink.build/Script-5FDA933F15D46D3AB0B441AC.sh
+ cd /b/build/slave/mac/build/src/third_party/ffmpeg
+ /bin/sh -c /b/build/slave/mac/build/src/third_party/ffmpeg/../../xcodebuild/ffmpeg.build/Debug/ffmpegsumo_nolink.build/Script-5FDA933F15D46D3AB0B441AC.sh
+
+
+=== BUILD AGGREGATE TARGET ffmpeg Support OF PROJECT ffmpeg WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET ffmpeg OF PROJECT ffmpeg WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET media OF PROJECT media WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET chromoting_jingle_glue OF PROJECT remoting WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET expat OF PROJECT expat WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET libjingle_p2p OF PROJECT libjingle WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET libsrtp OF PROJECT libsrtp WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET chromoting_client OF PROJECT remoting WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET chromoting_protocol OF PROJECT remoting WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET ppapi_cpp_objects OF PROJECT ppapi WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET sync_listen_notifications OF PROJECT sync_tools WITH CONFIGURATION Debug ===
+Check dependencies
+Ld ../../../../xcodebuild/Debug/sync_listen_notifications normal i386
+ cd /b/build/slave/mac/build/src/chrome/browser/sync/tools
+ setenv DISTCC_HOSTS "distcc4.golo.chromium.org:3632,lzo,cpp/0 distcc7.golo.chromium.org:3632,lzo,cpp/0 distcc8.golo.chromium.org:3632,lzo,cpp/0 distcc10.golo.chromium.org:3632,lzo,cpp/0 distcc6.golo.chromium.org:3632,lzo,cpp/0 distcc3.golo.chromium.org:3632,lzo,cpp/0 distcc2.golo.chromium.org:3632,lzo,cpp/0 distcc1.golo.chromium.org:3632,lzo,cpp/0 distcc9.golo.chromium.org:3632,lzo,cpp/0 distcc5.golo.chromium.org:3632,lzo,cpp/0"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv MACOSX_DEPLOYMENT_TARGET 10.5
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/g++-4.2 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk -L/b/build/slave/mac/build/src/chrome/browser/sync/tools/../../../../xcodebuild/Debug -F/b/build/slave/mac/build/src/chrome/browser/sync/tools/../../../../xcodebuild/Debug -filelist /b/build/slave/mac/build/src/chrome/browser/sync/tools/../../../../xcodebuild/sync_tools.build/Debug/sync_listen_notifications.build/Objects-normal/i386/sync_listen_notifications.LinkFileList -mmacosx-version-min=10.5 -Wl,-search_paths_first /b/build/slave/mac/build/src/xcodebuild/Debug/libbase.a /b/build/slave/mac/build/src/xcodebuild/Debug/libcommon_constants.a /b/build/slave/mac/build/src/xcodebuild/Debug/libsync_notifier.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnotifier.a /b/build/slave/mac/build/src/xcodebuild/Debug/libjingle.a /b/build/slave/mac/build/src/xcodebuild/Debug/libmodp_b64.a /b/build/slave/mac/build/src/xcodebuild/Debug/libdynamic_annotations.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnss.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnspr.a /b/build/slave/mac/build/src/xcodebuild/Debug/libsqlite3.a /b/build/slave/mac/build/src/xcodebuild/Debug/libicui18n.a /b/build/slave/mac/build/src/xcodebuild/Debug/libicuuc.a /b/build/slave/mac/build/src/xcodebuild/Debug/libicudata.a /b/build/slave/mac/build/src/xcodebuild/Debug/libevent.a /b/build/slave/mac/build/src/xcodebuild/Debug/libsync.a /b/build/slave/mac/build/src/xcodebuild/Debug/libcommon.a /b/build/slave/mac/build/src/xcodebuild/Debug/libcommon_net.a /b/build/slave/mac/build/src/xcodebuild/Debug/libapp_base.a /b/build/slave/mac/build/src/xcodebuild/Debug/libbase_i18n.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgfx.a /b/build/slave/mac/build/src/xcodebuild/Debug/libskia.a /b/build/slave/mac/build/src/xcodebuild/Debug/libskia_opts.a /b/build/slave/mac/build/src/xcodebuild/Debug/libpng.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchrome_zlib.a /b/build/slave/mac/build/src/xcodebuild/Debug/libjpeg.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnet.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgoogleurl.a /b/build/slave/mac/build/src/xcodebuild/Debug/libsdch.a /b/build/slave/mac/build/src/xcodebuild/Debug/libnet_base.a /b/build/slave/mac/build/src/xcodebuild/Debug/libssl_host_info.a /b/build/slave/mac/build/src/xcodebuild/Debug/libprotobuf_lite.a /b/build/slave/mac/build/src/xcodebuild/Debug/libv8_snapshot.a /b/build/slave/mac/build/src/xcodebuild/Debug/libv8_base.a /b/build/slave/mac/build/src/xcodebuild/Debug/libssl.a /b/build/slave/mac/build/src/xcodebuild/Debug/libdefault_plugin.a /b/build/slave/mac/build/src/xcodebuild/Debug/libxml2.a /b/build/slave/mac/build/src/xcodebuild/Debug/libipc.a /b/build/slave/mac/build/src/xcodebuild/Debug/libprinting.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchrome_bz2.a /b/build/slave/mac/build/src/xcodebuild/Debug/libappcache.a /b/build/slave/mac/build/src/xcodebuild/Debug/libblob.a /b/build/slave/mac/build/src/xcodebuild/Debug/libglue.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgles2_implementation.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgles2_cmd_helper.a /b/build/slave/mac/build/src/xcodebuild/Debug/libcommand_buffer_client.a /b/build/slave/mac/build/src/xcodebuild/Debug/libcommand_buffer_common.a /b/build/slave/mac/build/src/xcodebuild/Debug/libppapi_shared_impl.a /b/build/slave/mac/build/src/xcodebuild/Debug/libwebkit_user_agent.a /b/build/slave/mac/build/src/xcodebuild/Debug/libgpu_plugin.a /b/build/slave/mac/build/src/xcodebuild/Debug/libcommand_buffer_service.a /b/build/slave/mac/build/src/xcodebuild/Debug/libtranslator_glsl.a /b/build/slave/mac/build/src/xcodebuild/Debug/libtranslator_common.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchromoting_plugin.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchromoting_base.a /b/build/slave/mac/build/src/xcodebuild/Debug/libmedia.a /b/build/slave/mac/build/src/xcodebuild/Debug/libffmpeg.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchromoting_jingle_glue.a /b/build/slave/mac/build/src/xcodebuild/Debug/libexpat.a /b/build/slave/mac/build/src/xcodebuild/Debug/libjingle_p2p.a /b/build/slave/mac/build/src/xcodebuild/Debug/libsrtp.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchromotocol_proto_lib.a /b/build/slave/mac/build/src/xcodebuild/Debug/libtrace_proto_lib.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchromoting_client.a /b/build/slave/mac/build/src/xcodebuild/Debug/libchromoting_protocol.a /b/build/slave/mac/build/src/xcodebuild/Debug/libppapi_cpp_objects.a /b/build/slave/mac/build/src/xcodebuild/Debug/libcacheinvalidation.a -framework AppKit -framework Carbon -framework CoreFoundation -framework Foundation -framework IOKit -framework Security -framework OpenGL -framework SystemConfiguration -lresolv -lcups -framework QuartzCore -framework AudioToolbox -framework CoreAudio -o /b/build/slave/mac/build/src/chrome/browser/sync/tools/../../../../xcodebuild/Debug/sync_listen_notifications
+
+PhaseScriptExecution "Postbuild \"Strip If Needed\"" ../../../../xcodebuild/sync_tools.build/Debug/sync_listen_notifications.build/Script-577A6588CCA38D4E2CF91DDA.sh
+ cd /b/build/slave/mac/build/src/chrome/browser/sync/tools
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/browser/sync/tools/../../../../xcodebuild/sync_tools.build/Debug/sync_listen_notifications.build/Script-577A6588CCA38D4E2CF91DDA.sh
+
+
+=== BUILD AGGREGATE TARGET platform_locale_settings OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET chrome_extra_resources OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"grit\"" ../xcodebuild/chrome.build/Debug/chrome_extra_resources.build/Script-3DF0B99B7073177A35D87914.sh
+ cd /b/build/slave/mac/build/src/chrome
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/chrome_extra_resources.build/Script-3DF0B99B7073177A35D87914.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET default_extensions OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET debugger OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/debugger.build/Objects-normal/i386/debugger_remote_service.o browser/debugger/debugger_remote_service.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/debugger/debugger_remote_service.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/Objects-normal/i386/debugger_remote_service.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/debugger.build/Objects-normal/i386/extension_ports_remote_service.o browser/debugger/extension_ports_remote_service.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/debugger/extension_ports_remote_service.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/Objects-normal/i386/extension_ports_remote_service.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/debugger.build/Objects-normal/i386/devtools_window.o browser/debugger/devtools_window.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/debugger/devtools_window.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/Objects-normal/i386/devtools_window.o
+
+Libtool ../xcodebuild/Debug/libdebugger.a normal i386
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_HOSTS "distcc4.golo.chromium.org:3632,lzo,cpp/0 distcc7.golo.chromium.org:3632,lzo,cpp/0 distcc8.golo.chromium.org:3632,lzo,cpp/0 distcc10.golo.chromium.org:3632,lzo,cpp/0 distcc6.golo.chromium.org:3632,lzo,cpp/0 distcc3.golo.chromium.org:3632,lzo,cpp/0 distcc2.golo.chromium.org:3632,lzo,cpp/0 distcc1.golo.chromium.org:3632,lzo,cpp/0 distcc9.golo.chromium.org:3632,lzo,cpp/0 distcc5.golo.chromium.org:3632,lzo,cpp/0"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv MACOSX_DEPLOYMENT_TARGET 10.5
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/libtool -static -arch_only i386 -syslibroot /Developer/SDKs/MacOSX10.5.sdk -L/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -filelist /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/debugger.build/Objects-normal/i386/debugger.LinkFileList -o /b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/libdebugger.a
+
+
+=== BUILD NATIVE TARGET plugin OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/plugin.build/Objects-normal/i386/plugin_thread.o plugin/plugin_thread.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS localhost
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../gpu -I.. -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/plugin.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/plugin.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/plugin/plugin_thread.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/plugin.build/Objects-normal/i386/plugin_thread.o
+
+Libtool ../xcodebuild/Debug/libplugin.a normal i386
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_HOSTS "distcc4.golo.chromium.org:3632,lzo,cpp/0 distcc7.golo.chromium.org:3632,lzo,cpp/0 distcc8.golo.chromium.org:3632,lzo,cpp/0 distcc10.golo.chromium.org:3632,lzo,cpp/0 distcc6.golo.chromium.org:3632,lzo,cpp/0 distcc3.golo.chromium.org:3632,lzo,cpp/0 distcc2.golo.chromium.org:3632,lzo,cpp/0 distcc1.golo.chromium.org:3632,lzo,cpp/0 distcc9.golo.chromium.org:3632,lzo,cpp/0 distcc5.golo.chromium.org:3632,lzo,cpp/0"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv MACOSX_DEPLOYMENT_TARGET 10.5
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/libtool -static -arch_only i386 -syslibroot /Developer/SDKs/MacOSX10.5.sdk -L/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -filelist /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/plugin.build/Objects-normal/i386/plugin.LinkFileList -o /b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/libplugin.a
+
+
+=== BUILD NATIVE TARGET utility OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET profile_import OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET chrome_gpu OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET ppapi_plugin OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET worker OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/worker.build/Objects-normal/i386/worker_webkitclient_impl.o worker/worker_webkitclient_impl.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS localhost
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I.. -I../gpu -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/worker.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/worker.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/worker/worker_webkitclient_impl.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/worker.build/Objects-normal/i386/worker_webkitclient_impl.o
+
+Libtool ../xcodebuild/Debug/libworker.a normal i386
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_HOSTS "distcc4.golo.chromium.org:3632,lzo,cpp/0 distcc7.golo.chromium.org:3632,lzo,cpp/0 distcc8.golo.chromium.org:3632,lzo,cpp/0 distcc10.golo.chromium.org:3632,lzo,cpp/0 distcc6.golo.chromium.org:3632,lzo,cpp/0 distcc3.golo.chromium.org:3632,lzo,cpp/0 distcc2.golo.chromium.org:3632,lzo,cpp/0 distcc1.golo.chromium.org:3632,lzo,cpp/0 distcc9.golo.chromium.org:3632,lzo,cpp/0 distcc5.golo.chromium.org:3632,lzo,cpp/0"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv MACOSX_DEPLOYMENT_TARGET 10.5
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/libtool -static -arch_only i386 -syslibroot /Developer/SDKs/MacOSX10.5.sdk -L/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -filelist /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/worker.build/Objects-normal/i386/worker.LinkFileList -o /b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/libworker.a
+
+
+=== BUILD NATIVE TARGET syncapi OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET service OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET device_management_proto_cpp OF PROJECT device_management_proto WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD AGGREGATE TARGET safe_browsing_csd_proto OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../xcodebuild/chrome.build/Debug/safe_browsing_csd_proto.build/Script-A64480A7A7F73B68D5D0EBFB.sh
+ cd /b/build/slave/mac/build/src/chrome
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/safe_browsing_csd_proto.build/Script-A64480A7A7F73B68D5D0EBFB.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET safe_browsing_report_proto OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../xcodebuild/chrome.build/Debug/safe_browsing_report_proto.build/Script-6B102C7C9773962E1B26CF1B.sh
+ cd /b/build/slave/mac/build/src/chrome
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/safe_browsing_report_proto.build/Script-6B102C7C9773962E1B26CF1B.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET userfeedback_proto OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../xcodebuild/chrome.build/Debug/userfeedback_proto.build/Script-E9D8DD8102F83FCBC3F0768B.sh
+ cd /b/build/slave/mac/build/src/chrome
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/userfeedback_proto.build/Script-E9D8DD8102F83FCBC3F0768B.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD AGGREGATE TARGET browser Support OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+
+=== BUILD NATIVE TARGET browser OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/appcache_dispatcher_host.o browser/appcache/appcache_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/appcache/appcache_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/appcache_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/appcache_frontend_proxy.o browser/appcache/appcache_frontend_proxy.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/appcache/appcache_frontend_proxy.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/appcache_frontend_proxy.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/dom_ui.o browser/dom_ui/dom_ui.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/dom_ui/dom_ui.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/dom_ui.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_port_container.o browser/automation/extension_port_container.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/automation/extension_port_container.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_port_container.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/browser_about_handler.o browser/browser_about_handler.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/browser_about_handler.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/browser_about_handler.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/browser_main.o browser/browser_main.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/browser_main.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/browser_main.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/devtools_ui.o browser/dom_ui/devtools_ui.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/dom_ui/devtools_ui.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/devtools_ui.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/dispatcher_host.o browser/device_orientation/dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/device_orientation/dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_browser_actions_api.o browser/extensions/extension_browser_actions_api.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_browser_actions_api.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_browser_actions_api.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/dom_storage_dispatcher_host.o browser/in_process_webkit/dom_storage_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/in_process_webkit/dom_storage_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/dom_storage_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/indexed_db_callbacks.o browser/in_process_webkit/indexed_db_callbacks.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/in_process_webkit/indexed_db_callbacks.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/indexed_db_callbacks.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_menu_manager.o browser/extensions/extension_menu_manager.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_menu_manager.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_menu_manager.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/browser_process_impl.o browser/browser_process_impl.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/browser_process_impl.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/browser_process_impl.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/instant_loader.o browser/instant/instant_loader.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/instant/instant_loader.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/instant_loader.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_event_router.o browser/extensions/extension_event_router.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_event_router.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_event_router.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/memory_purger.o browser/memory_purger.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/memory_purger.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/memory_purger.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_message_service.o browser/extensions/extension_message_service.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_message_service.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_message_service.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_sidebar_api.o browser/extensions/extension_sidebar_api.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_sidebar_api.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_sidebar_api.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_process_manager.o browser/extensions/extension_process_manager.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_process_manager.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_process_manager.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_host.o browser/extensions/extension_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/histogram_synchronizer.o browser/metrics/histogram_synchronizer.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/metrics/histogram_synchronizer.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/histogram_synchronizer.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/dom_storage_area.o browser/in_process_webkit/dom_storage_area.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/in_process_webkit/dom_storage_area.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/dom_storage_area.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/indexed_db_dispatcher_host.o browser/in_process_webkit/indexed_db_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/in_process_webkit/indexed_db_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/indexed_db_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_page_actions_module.o browser/extensions/extension_page_actions_module.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_page_actions_module.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_page_actions_module.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/mime_registry_dispatcher.o browser/mime_registry_dispatcher.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/mime_registry_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/mime_registry_dispatcher.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/file_system_dispatcher_host.o browser/file_system/file_system_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/file_system/file_system_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/file_system_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/geolocation_dispatcher_host_old.o browser/geolocation/geolocation_dispatcher_host_old.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/geolocation/geolocation_dispatcher_host_old.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/geolocation_dispatcher_host_old.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/balloon_host.o browser/notifications/balloon_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/notifications/balloon_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/balloon_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/gpu_process_host.o browser/gpu_process_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/gpu_process_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/gpu_process_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/notification_object_proxy.o browser/notifications/notification_object_proxy.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/notifications/notification_object_proxy.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/notification_object_proxy.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_function_dispatcher.o browser/extensions/extension_function_dispatcher.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/extensions/extension_function_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/extension_function_dispatcher.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/geolocation_permission_context.o browser/geolocation/geolocation_permission_context.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/geolocation/geolocation_permission_context.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/geolocation_permission_context.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/plugin_process_host.o browser/plugin_process_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/plugin_process_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/plugin_process_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/desktop_notification_service.o browser/notifications/desktop_notification_service.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/notifications/desktop_notification_service.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/desktop_notification_service.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/ppapi_plugin_process_host.o browser/ppapi_plugin_process_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/ppapi_plugin_process_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/ppapi_plugin_process_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/web_cache_manager.o browser/renderer_host/web_cache_manager.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/web_cache_manager.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/web_cache_manager.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/plugin_service.o browser/plugin_service.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/plugin_service.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/plugin_service.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/nacl_process_host.o browser/nacl_host/nacl_process_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/nacl_host/nacl_process_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/nacl_process_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/metrics_service.o browser/metrics/metrics_service.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/metrics/metrics_service.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/metrics_service.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/profile.o browser/profiles/profile.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/profiles/profile.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/profile.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_host_delegate.o browser/renderer_host/render_view_host_delegate.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/render_view_host_delegate.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_host_delegate.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/async_resource_handler.o browser/renderer_host/async_resource_handler.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/async_resource_handler.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/async_resource_handler.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/audio_renderer_host.o browser/renderer_host/audio_renderer_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/audio_renderer_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/audio_renderer_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/task_manager_resource_providers.o browser/task_manager/task_manager_resource_providers.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/task_manager/task_manager_resource_providers.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/task_manager_resource_providers.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_widget_host.o browser/renderer_host/render_widget_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/render_widget_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_widget_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_host.o browser/renderer_host/render_view_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/render_view_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/profile_impl.o browser/profiles/profile_impl.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/profiles/profile_impl.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/profile_impl.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/sync_resource_handler.o browser/renderer_host/sync_resource_handler.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/sync_resource_handler.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/sync_resource_handler.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/socket_stream_host.o browser/renderer_host/socket_stream_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/socket_stream_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/socket_stream_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/speech_input_dispatcher_host.o browser/speech/speech_input_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/speech/speech_input_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/speech_input_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/file_utilities_dispatcher_host.o browser/renderer_host/file_utilities_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/file_utilities_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/file_utilities_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_widget_host_view_mac.o browser/renderer_host/render_widget_host_view_mac.mm normal i386 objective-c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x objective-c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/render_widget_host_view_mac.mm -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_widget_host_view_mac.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/database_dispatcher_host.o browser/renderer_host/database_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/database_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/database_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/browser_render_process_host.o browser/renderer_host/browser_render_process_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/browser_render_process_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/browser_render_process_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/search_provider_install_state_dispatcher_host.o browser/search_engines/search_provider_install_state_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/search_engines/search_provider_install_state_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/search_provider_install_state_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_context_menu.o browser/tab_contents/render_view_context_menu.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_context_menu.o
+
+distcc[1299] ERROR: compile /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu.cc on distcc4.golo.chromium.org:3632,lzo,cpp/18 failed
+distcc[1299] (dcc_build_somewhere) Warning: remote compilation of '/b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu.cc' failed, retrying locally
+distcc[1299] Warning: failed to distribute /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu.cc to distcc4.golo.chromium.org:3632,lzo,cpp/18, running locally instead
+/b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu.cc: In member function 'string16 RenderViewContextMenu::PrintableSelectionText()':
+/b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu.cc:1436: error: invalid initialization of reference of type 'const std::wstring&' from expression of type 'string16'
+../app/l10n_util.h:166: error: in passing argument 1 of 'std::wstring l10n_util::TruncateString(const std::wstring&, size_t)'
+distcc[1299] ERROR: compile /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu.cc on localhost failed
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_host_manager.o browser/tab_contents/render_view_host_manager.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_host_manager.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_host_manager.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/blob_dispatcher_host.o browser/renderer_host/blob_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/blob_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/blob_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/tab_contents_view_mac.o browser/tab_contents/tab_contents_view_mac.mm normal i386 objective-c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x objective-c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/tab_contents/tab_contents_view_mac.mm -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/tab_contents_view_mac.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/worker_service.o browser/worker_host/worker_service.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/worker_host/worker_service.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/worker_service.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/pepper_file_message_filter.o browser/renderer_host/pepper_file_message_filter.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/pepper_file_message_filter.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/pepper_file_message_filter.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/worker_process_host.o browser/worker_host/worker_process_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/worker_host/worker_process_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/worker_process_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/socket_stream_dispatcher_host.o browser/renderer_host/socket_stream_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/socket_stream_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/socket_stream_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/tab_contents.o browser/tab_contents/tab_contents.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/tab_contents/tab_contents.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/tab_contents.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_context_menu_mac.o browser/tab_contents/render_view_context_menu_mac.mm normal i386 objective-c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x objective-c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu_mac.mm -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_context_menu_mac.o
+
+distcc[1301] ERROR: compile /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu_mac.mm on distcc9.golo.chromium.org:3632,lzo,cpp/18 failed
+distcc[1301] (dcc_build_somewhere) Warning: remote compilation of '/b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu_mac.mm' failed, retrying locally
+distcc[1301] Warning: failed to distribute /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu_mac.mm to distcc9.golo.chromium.org:3632,lzo,cpp/18, running locally instead
+/b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu_mac.mm: In member function 'virtual void RenderViewContextMenuMac::LookUpInDictionary()':
+/b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu_mac.mm:78: error: invalid initialization of reference of type 'const std::wstring&' from expression of type 'string16'
+../base/sys_string_conversions.h:68: error: in passing argument 1 of 'NSString* base::SysWideToNSString(const std::wstring&)'
+distcc[1301] ERROR: compile /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_context_menu_mac.mm on localhost failed
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/resource_dispatcher_host.o browser/renderer_host/resource_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/resource_dispatcher_host.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/resource_dispatcher_host.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/resource_message_filter.o browser/renderer_host/resource_message_filter.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/renderer_host/resource_message_filter.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/resource_message_filter.o
+
+
+=== BUILD AGGREGATE TARGET safe_browsing_proto OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+PhaseScriptExecution "Rule \"genproto\"" ../xcodebuild/chrome.build/Debug/safe_browsing_proto.build/Script-04EB001E8DD6896C5E67BFBB.sh
+ cd /b/build/slave/mac/build/src/chrome
+ /bin/sh -c /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/safe_browsing_proto.build/Script-04EB001E8DD6896C5E67BFBB.sh
+
+make: Nothing to be done for `all'.
+
+=== BUILD NATIVE TARGET renderer OF PROJECT chrome WITH CONFIGURATION Debug ===
+Check dependencies
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/autofill_helper.o renderer/autofill_helper.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/autofill_helper.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/autofill_helper.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/dom_automation_controller.o renderer/automation/dom_automation_controller.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/automation/dom_automation_controller.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/dom_automation_controller.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/chrome_app_bindings.o renderer/extensions/chrome_app_bindings.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/extensions/chrome_app_bindings.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/chrome_app_bindings.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/password_autocomplete_manager.o renderer/password_autocomplete_manager.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/password_autocomplete_manager.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/password_autocomplete_manager.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/bindings_utils.o renderer/extensions/bindings_utils.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/extensions/bindings_utils.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/bindings_utils.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/renderer_net_predictor.o renderer/net/renderer_net_predictor.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/net/renderer_net_predictor.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/renderer_net_predictor.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/audio_renderer_impl.o renderer/media/audio_renderer_impl.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/media/audio_renderer_impl.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/audio_renderer_impl.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/cookie_message_filter.o renderer/cookie_message_filter.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/cookie_message_filter.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/cookie_message_filter.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/event_bindings.o renderer/extensions/event_bindings.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/extensions/event_bindings.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/event_bindings.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/external_popup_menu.o renderer/external_popup_menu.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/external_popup_menu.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/external_popup_menu.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/renderer_extension_bindings.o renderer/extensions/renderer_extension_bindings.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/extensions/renderer_extension_bindings.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/renderer_extension_bindings.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/extension_process_bindings.o renderer/extensions/extension_process_bindings.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/extensions/extension_process_bindings.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/extension_process_bindings.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/device_orientation_dispatcher.o renderer/device_orientation_dispatcher.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/device_orientation_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/device_orientation_dispatcher.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/audio_message_filter.o renderer/audio_message_filter.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/audio_message_filter.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/audio_message_filter.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/blocked_plugin.o renderer/blocked_plugin.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/blocked_plugin.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/blocked_plugin.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/page_load_histograms.o renderer/page_load_histograms.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/page_load_histograms.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/page_load_histograms.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/devtools_agent.o renderer/devtools_agent.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/devtools_agent.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/devtools_agent.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/devtools_agent_filter.o renderer/devtools_agent_filter.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/devtools_agent_filter.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/devtools_agent_filter.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/dom_ui_bindings.o renderer/dom_ui_bindings.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/dom_ui_bindings.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/dom_ui_bindings.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/devtools_client.o renderer/devtools_client.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/devtools_client.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/devtools_client.o
+
+Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/indexed_db_dispatcher.o renderer/indexed_db_dispatcher.cc normal i386 c++ com.apple.compilers.gcc.4_2
+ cd /b/build/slave/mac/build/src/chrome
+ setenv DISTCC_COMPILER "gcc version 4.2.1 (Apple Inc. build 5659)"
+ setenv DISTCC_HOSTS "--randomize distcc5.golo.chromium.org:3632,lzo,cpp/18 distcc9.golo.chromium.org:3632,lzo,cpp/18 distcc1.golo.chromium.org:3632,lzo,cpp/18 distcc2.golo.chromium.org:3632,lzo,cpp/18 distcc3.golo.chromium.org:3632,lzo,cpp/18 distcc6.golo.chromium.org:3632,lzo,cpp/18 distcc10.golo.chromium.org:3632,lzo,cpp/18 distcc7.golo.chromium.org:3632,lzo,cpp/18 distcc8.golo.chromium.org:3632,lzo,cpp/18 distcc4.golo.chromium.org:3632,lzo,cpp/18"
+ setenv DISTCC_SYSTEM "10.6.4 (10F2025, i386)"
+ setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
+ setenv INCLUDE_SERVER_PID 983
+ setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
+ setenv LANG en_US.US-ASCII
+ setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/indexed_db_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/indexed_db_dispatcher.o
+
diff --git a/chromium/tools/emacs/trybot-windows.txt b/chromium/tools/emacs/trybot-windows.txt
new file mode 100644
index 00000000000..b3ee27fcedb
--- /dev/null
+++ b/chromium/tools/emacs/trybot-windows.txt
@@ -0,0 +1,72 @@
+This file contains sample trybot output from a Windows trybot run.
+It contains a warning and an error but has otherwise been shortened
+for length.
+
+"C:\Program Files (x86)\Xoreax\IncrediBuild\BuildConsole.exe" e:\b\build\slave\win\build\src\build\all.sln "/Cfg=Debug|Win32"
+
+-----------------------------------------------------------------
+IncrediBuild Console 3.60 Internal (build 1156)
+Copyright (C) 2001-2010 Xoreax Software Ltd. All rights reserved.
+-----------------------------------------------------------------
+--------------------Configuration: toolband_proxy_lib - Debug|Win32------------
+Compiling...
+toolband_p.c
+toolband_proxy.cc
+toolband_dlldata.c
+Creating library...
+
+toolband_proxy_lib - 0 error(s), 0 warning(s)
+--------------------Configuration: webcore_bindings - Debug|Win32--------------
+Compiling...
+CSSGrammar.cpp
+e:\b\build\slave\win\build\src\third_party\webkit\javascriptcore\wtf\text\StringImpl.h(90) : warning C4355: 'this' : used in base member initializer list with a gratuitous backslash \ for testing
+e:\b\build\slave\win\build\src\third_party\webkit\webcore\dom\ViewportArguments.h(78) : warning C4305: 'initializing' : truncation from '' to 'bool'
+e:\b\build\slave\win\build\src\build\Debug\obj\global_intermediate\webkit\CSSGrammar.cpp(1930) : warning C4065: switch statement contains 'default' but no 'case' labels
+V8DerivedSources1.cpp
+--------------------Configuration: run_testserver - Debug|Win32----------------
+Compiling...
+run_testserver.cc
+Linking...
+Embedding manifest...
+Embedding manifest... (rc.exe)
+Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
+
+Copyright (C) Microsoft Corporation. All rights reserved.
+
+Embedding manifest... (link.exe)
+
+run_testserver - 0 error(s), 0 warning(s)
+--------------------Configuration: browser - Debug|Win32-----------------------
+Compiling...
+bookmark_manager_resources_map.cc
+theme_resources_map.cc
+shared_resources_map.cc
+process_singleton_win.cc
+e:\b\build\slave\win\build\src\chrome\browser\process_singleton_win.cc(95) : error C2664: 'PathService::Get' : cannot convert parameter 2 from 'std::wstring *' to 'FilePath *'
+ Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
+gpu_process_host.cc
+ntp_background_util.cc
+
+browser - 6 error(s), 0 warning(s)
+
+1 build system warning(s):
+ - PDB instance limit is enabled
+
+---------------------- Done ----------------------
+
+ Build: 244 succeeded, 1 failed, 233 up-to-date, 42 skipped
+
+
+We also see weird paths with mixed slashes like this:
+
+--------------------Configuration: inspector_protocol_sources - Debug|Win32----
+--------------------Configuration: installer_util_nacl_win64 - Debug|x64-------
+Compiling...
+google_chrome_distribution_dummy.cc
+helper.cc
+installation_state.cc
+self_reg_work_item.cc
+..\chrome/installer/util/work_item.h(67) : error C2514: 'FilePath' : class has no constructors
+ ..\chrome/installer/util/work_item.h(26) : see declaration of 'FilePath'
+delete_tree_work_item.cc
+delete_reg_key_work_item.cc
diff --git a/chromium/tools/emacs/trybot.el b/chromium/tools/emacs/trybot.el
new file mode 100644
index 00000000000..970ffc085d9
--- /dev/null
+++ b/chromium/tools/emacs/trybot.el
@@ -0,0 +1,176 @@
+; To use this,
+; 1) Add to init.el:
+; (setq-default chrome-root "/path/to/chrome/src/")
+; (add-to-list 'load-path (concat chrome-root "tools/emacs"))
+; (require 'trybot)
+; 2) Run on trybot output:
+; M-x trybot
+;
+; To hack on this,
+; M-x eval-buffer
+; M-x trybot-test-win or M-x trybot-test-mac
+
+(defvar chrome-root nil
+ "Path to the src/ directory of your Chrome checkout.")
+
+(defun get-chrome-root ()
+ (or chrome-root default-directory))
+
+; Hunt down from the top, case correcting each path component as needed.
+; Currently does not keep a cache. Returns nil if no matching file can be
+; figured out.
+(defun case-corrected-filename (filename)
+ (save-match-data
+ (let ((path-components (split-string filename "/"))
+ (corrected-path (file-name-as-directory (get-chrome-root))))
+ (mapc
+ (function
+ (lambda (elt)
+ (if corrected-path
+ (let ((next-component
+ (car (member-ignore-case
+ elt (directory-files corrected-path)))))
+ (setq corrected-path
+ (and next-component
+ (file-name-as-directory
+ (concat corrected-path next-component))))))))
+ path-components)
+ (if corrected-path
+ (file-relative-name (directory-file-name corrected-path)
+ (get-chrome-root))
+ nil))))
+
+(defun trybot-fixup-win ()
+ "Fix up Windows-specific output."
+
+ ; Fix Windows paths ("d:\...\src\").
+ (save-excursion
+ ; This regexp is subtle and rather hard to read. :~(
+ ; Use regexp-builder when making changes to it.
+ (while (re-search-forward
+ (concat
+ ; First part: path leader, either of the form
+ ; e:\...src\ or ..\
+ "\\(^.:\\\\.*\\\\src\\\\\\|\\.\\.\\\\\\)"
+ ; Second part: path, followed by error message marker.
+ "\\(.*?\\)[(:]") nil t)
+ (replace-match "" nil t nil 1)
+ ; Line now looks like:
+ ; foo\bar\baz.cc error message here
+ ; We want to fixup backslashes in path into forward slashes,
+ ; without modifying the error message - by matching up to the
+ ; first colon above (which will be just beyond the end of the
+ ; filename) we can use the end of the match as a limit.
+ (subst-char-in-region (point) (match-end 0) ?\\ ?/)
+ ; See if we can correct the file name casing.
+ (let ((filename (buffer-substring (match-beginning 2) (match-end 2))))
+ (if (and (not (file-exists-p filename))
+ (setq filename (case-corrected-filename filename)))
+ (replace-match filename t t nil 2))))))
+
+(defun trybot-fixup-maclin ()
+ "Fix up Mac/Linux output."
+ (save-excursion
+ (while (re-search-forward "^/b/build/[^ ]*/src/" nil t)
+ (replace-match ""))))
+
+(defun trybot-fixup (type-hint)
+ "Parse and fixup the contents of the current buffer as trybot output."
+
+ ; XXX is there something I should so so this stuff doesn't end up on the
+ ; undo stack?
+
+ ;; Fixup paths.
+ (cd (get-chrome-root))
+
+ (goto-char (point-min))
+
+ ;; Fix up path references.
+ (cond ((eq type-hint 'win) (trybot-fixup-win))
+ ((eq type-hint 'mac) (trybot-fixup-maclin))
+ ((eq type-hint 'linux) (trybot-fixup-maclin))
+ (t (trybot-fixup-win) (trybot-fixup-maclin)))
+
+ (compilation-mode))
+
+(defun trybot-get-new-buffer ()
+ "Get a new clean buffer for trybot output."
+ ; Use trybot-buffer-name if available; otherwise, "*trybot*".
+ (let ((buffer-name (if (boundp 'trybot-buffer-name)
+ trybot-buffer-name
+ "*trybot*")))
+ (let ((old (get-buffer buffer-name)))
+ (when old (kill-buffer old)))
+ (get-buffer-create buffer-name)))
+
+(defun trybot-fetch (type-hint url)
+ "Fetch a URL and postprocess it as trybot output."
+
+ (let ((on-fetch-completion
+ (lambda (process state)
+ (switch-to-buffer (process-buffer process))
+ (when (equal state "finished\n")
+ (trybot-fixup (process-get process 'type-hint)))))
+ (command (concat "curl -s " (shell-quote-argument url)
+ ; Pipe it through the output shortener.
+ (cond
+ ((eq type-hint 'win)
+ (concat " | " (get-chrome-root)
+ "build/sanitize-win-build-log.sh"))
+ ((eq type-hint 'mac)
+ (concat " | " (get-chrome-root)
+ "build/sanitize-mac-build-log.sh"))))))
+
+ ; Start up the subprocess.
+ (let* ((coding-system-for-read 'utf-8-dos)
+ (buffer (trybot-get-new-buffer))
+ (process (start-process-shell-command "curl" buffer command)))
+ ; Attach the type hint to the process so we can get it back when
+ ; the process completes.
+ (process-put process 'type-hint type-hint)
+ (set-process-query-on-exit-flag process nil)
+ (set-process-sentinel process on-fetch-completion))))
+
+(defun trybot-test (type-hint filename)
+ "Load the given test data filename and do the trybot parse on it."
+
+ (let ((trybot-buffer-name "*trybot-test*")
+ (url (concat "file://" (get-chrome-root) "tools/emacs/" filename)))
+ (trybot-fetch type-hint url)))
+
+(defun trybot-test-win ()
+ "Load the Windows test data and do the trybot parse on it."
+ (interactive)
+ (trybot-test 'win "trybot-windows.txt"))
+(defun trybot-test-mac ()
+ "Load the Mac test data and do the trybot parse on it."
+ (interactive)
+ (trybot-test 'mac "trybot-mac.txt"))
+(defun trybot-test-linux ()
+ "Load the Linux test data and do the trybot parse on it."
+ (interactive)
+ (trybot-test 'linux "trybot-linux.txt"))
+
+(defun trybot (url)
+ "Fetch a trybot URL and fix up the output into a compilation-mode buffer."
+ (interactive "sURL to trybot stdout (leave empty to use clipboard): ")
+
+ ;; Yank URL from clipboard if necessary.
+ (when (= (length url) 0)
+ (with-temp-buffer
+ (clipboard-yank)
+ (setq url (buffer-string))))
+
+ ;; Append /text to the URL to get plain text output in the common
+ ;; case of getting a URL to the HTML build log.
+ (when (equal "stdio" (car (last (split-string url "/"))))
+ (setq url (concat url "/text")))
+
+ (let ((type-hint (cond ((string-match "/[Ww]in" url) 'win)
+ ((string-match "/mac/" url) 'mac)
+ ; Match /linux, /linux_view, etc.
+ ((string-match "/linux" url) 'linux)
+ (t 'unknown))))
+ (trybot-fetch type-hint url)))
+
+(provide 'trybot)
diff --git a/chromium/tools/export_tarball/export_tarball.py b/chromium/tools/export_tarball/export_tarball.py
new file mode 100755
index 00000000000..36a98268ffe
--- /dev/null
+++ b/chromium/tools/export_tarball/export_tarball.py
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This tool creates a tarball with all the sources, but without .svn directories.
+
+It can also remove files which are not strictly required for build, so that
+the resulting tarball can be reasonably small (last time it was ~110 MB).
+
+Example usage:
+
+export_tarball.py /foo/bar
+
+The above will create file /foo/bar.tar.bz2.
+"""
+
+import optparse
+import os
+import subprocess
+import sys
+import tarfile
+
+
+NONESSENTIAL_DIRS = (
+ 'breakpad/src/processor/testdata',
+ 'chrome/browser/resources/tracing/tests',
+ 'chrome/common/extensions/docs',
+ 'chrome/tools/test/reference_build',
+ 'courgette/testdata',
+ 'data',
+ 'native_client/src/trusted/service_runtime/testdata',
+ 'src/chrome/test/data',
+ 'o3d/documentation',
+ 'o3d/samples',
+ 'o3d/tests',
+ 'ppapi/examples',
+ 'ppapi/native_client/tests',
+ 'third_party/angle/samples/gles2_book',
+ 'third_party/findbugs',
+ 'third_party/hunspell_dictionaries',
+ 'third_party/hunspell/tests',
+ 'third_party/lighttpd',
+ 'third_party/sqlite/src/test',
+ 'third_party/sqlite/test',
+ 'third_party/vc_80',
+ 'third_party/xdg-utils/tests',
+ 'third_party/yasm/source/patched-yasm/modules/arch/x86/tests',
+ 'third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/tests',
+ 'third_party/yasm/source/patched-yasm/modules/objfmts/bin/tests',
+ 'third_party/yasm/source/patched-yasm/modules/objfmts/coff/tests',
+ 'third_party/yasm/source/patched-yasm/modules/objfmts/elf/tests',
+ 'third_party/yasm/source/patched-yasm/modules/objfmts/macho/tests',
+ 'third_party/yasm/source/patched-yasm/modules/objfmts/rdf/tests',
+ 'third_party/yasm/source/patched-yasm/modules/objfmts/win32/tests',
+ 'third_party/yasm/source/patched-yasm/modules/objfmts/win64/tests',
+ 'third_party/yasm/source/patched-yasm/modules/objfmts/xdf/tests',
+ 'third_party/WebKit/LayoutTests',
+ 'third_party/WebKit/Source/JavaScriptCore/tests',
+ 'third_party/WebKit/Source/WebCore/ChangeLog',
+ 'third_party/WebKit/Source/WebKit2',
+ 'third_party/WebKit/Tools/Scripts',
+ 'tools/gyp/test',
+ 'v8/test',
+ 'webkit/data/layout_tests',
+ 'webkit/tools/test/reference_build',
+)
+
+TESTDIRS = (
+ 'chrome/test/data',
+ 'content/test/data',
+ 'media/test/data',
+ 'net/data',
+)
+
+PRUNEDDIRS = (
+ 'courgette',
+)
+
+
+def GetSourceDirectory():
+ return os.path.realpath(
+ os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src'))
+
+
+# Workaround lack of the exclude parameter in add method in python-2.4.
+# TODO(phajdan.jr): remove the workaround when it's not needed on the bot.
+class MyTarFile(tarfile.TarFile):
+ def set_remove_nonessential_files(self, remove):
+ self.__remove_nonessential_files = remove
+
+ def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
+ head, tail = os.path.split(name)
+ if tail in ('.svn', '.git'):
+ return
+
+ if self.__remove_nonessential_files:
+ # WebKit change logs take quite a lot of space. This saves ~10 MB
+ # in a bzip2-compressed tarball.
+ if 'ChangeLog' in name:
+ return
+
+ # Remove contents of non-essential directories, but preserve gyp files,
+ # so that build/gyp_chromium can work.
+ for nonessential_dir in (NONESSENTIAL_DIRS + TESTDIRS + PRUNEDDIRS):
+ dir_path = os.path.join(GetSourceDirectory(), nonessential_dir)
+ if (name.startswith(dir_path) and
+ os.path.isfile(name) and
+ 'gyp' not in name):
+ return
+
+ tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive)
+
+
+def main(argv):
+ parser = optparse.OptionParser()
+ parser.add_option("--basename")
+ parser.add_option("--remove-nonessential-files",
+ dest="remove_nonessential_files",
+ action="store_true", default=False)
+ parser.add_option("--test-data", action="store_true")
+ # TODO(phajdan.jr): Remove --xz option when it's not needed for compatibility.
+ parser.add_option("--xz", action="store_true")
+
+ options, args = parser.parse_args(argv)
+
+ if len(args) != 1:
+ print 'You must provide only one argument: output file name'
+ print '(without .tar.xz extension).'
+ return 1
+
+ if not os.path.exists(GetSourceDirectory()):
+ print 'Cannot find the src directory ' + GetSourceDirectory()
+ return 1
+
+ # These two commands are from src/DEPS; please keep them in sync.
+ if subprocess.call(['python', 'build/util/lastchange.py', '-o',
+ 'build/util/LASTCHANGE'], cwd=GetSourceDirectory()) != 0:
+ print 'Could not run build/util/lastchange.py to update LASTCHANGE.'
+ return 1
+ if subprocess.call(['python', 'build/util/lastchange.py', '-s',
+ 'third_party/WebKit', '-o',
+ 'build/util/LASTCHANGE.blink'],
+ cwd=GetSourceDirectory()) != 0:
+ print 'Could not run build/util/lastchange.py to update LASTCHANGE.blink.'
+ return 1
+
+ output_fullname = args[0] + '.tar'
+ output_basename = options.basename or os.path.basename(args[0])
+
+ archive = MyTarFile.open(output_fullname, 'w')
+ archive.set_remove_nonessential_files(options.remove_nonessential_files)
+ try:
+ if options.test_data:
+ for directory in TESTDIRS:
+ archive.add(os.path.join(GetSourceDirectory(), directory),
+ arcname=os.path.join(output_basename, directory))
+ else:
+ archive.add(GetSourceDirectory(), arcname=output_basename)
+ finally:
+ archive.close()
+
+ if subprocess.call(['xz', '-9', output_fullname]) != 0:
+ print 'xz -9 failed!'
+ return 1
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/export_tarball/export_v8_tarball.py b/chromium/tools/export_tarball/export_v8_tarball.py
new file mode 100755
index 00000000000..30767b6287b
--- /dev/null
+++ b/chromium/tools/export_tarball/export_v8_tarball.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Creates a tarball with V8 sources, but without .svn directories.
+
+This allows easy packaging of V8, synchronized with browser releases.
+
+Example usage:
+
+export_v8_tarball.py /foo/bar
+
+The above will create file /foo/bar/v8-VERSION.tar.bz2 if it doesn't exist.
+"""
+
+import optparse
+import os
+import re
+import subprocess
+import sys
+import tarfile
+
+_V8_MAJOR_VERSION_PATTERN = re.compile(r'#define\s+MAJOR_VERSION\s+(.*)')
+_V8_MINOR_VERSION_PATTERN = re.compile(r'#define\s+MINOR_VERSION\s+(.*)')
+_V8_BUILD_NUMBER_PATTERN = re.compile(r'#define\s+BUILD_NUMBER\s+(.*)')
+_V8_PATCH_LEVEL_PATTERN = re.compile(r'#define\s+PATCH_LEVEL\s+(.*)')
+
+_V8_PATTERNS = [
+ _V8_MAJOR_VERSION_PATTERN,
+ _V8_MINOR_VERSION_PATTERN,
+ _V8_BUILD_NUMBER_PATTERN,
+ _V8_PATCH_LEVEL_PATTERN]
+
+
+def GetV8Version(v8_directory):
+ """
+ Returns version number as string based on the string
+ contents of version.cc file.
+ """
+ with open(os.path.join(v8_directory, 'src', 'version.cc')) as version_file:
+ version_contents = version_file.read()
+
+ version_components = []
+ for pattern in _V8_PATTERNS:
+ version_components.append(pattern.search(version_contents).group(1).strip())
+
+ if version_components[len(version_components) - 1] == '0':
+ version_components.pop()
+
+ return '.'.join(version_components)
+
+
+def GetSourceDirectory():
+ return os.path.realpath(
+ os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src'))
+
+
+def GetV8Directory():
+ return os.path.join(GetSourceDirectory(), 'v8')
+
+
+# Workaround lack of the exclude parameter in add method in python-2.4.
+# TODO(phajdan.jr): remove the workaround when it's not needed on the bot.
+class MyTarFile(tarfile.TarFile):
+ def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
+ head, tail = os.path.split(name)
+ if tail in ('.svn', '.git'):
+ return
+
+ tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive)
+
+
+def main(argv):
+ parser = optparse.OptionParser()
+ options, args = parser.parse_args(argv)
+
+ if len(args) != 1:
+ print 'You must provide only one argument: output file directory'
+ return 1
+
+ v8_directory = GetV8Directory()
+ if not os.path.exists(v8_directory):
+ print 'Cannot find the v8 directory.'
+ return 1
+
+ v8_version = GetV8Version(v8_directory)
+ print 'Packaging V8 version %s...' % v8_version
+ output_basename = 'v8-%s' % v8_version
+ output_fullname = os.path.join(args[0], output_basename + '.tar.bz2')
+
+ if os.path.exists(output_fullname):
+ print 'Already packaged, exiting.'
+ return 0
+
+ subprocess.check_call(["make", "dependencies"], cwd=v8_directory)
+
+ archive = MyTarFile.open(output_fullname, 'w:bz2')
+ try:
+ archive.add(v8_directory, arcname=output_basename)
+ finally:
+ archive.close()
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/find_depot_tools.py b/chromium/tools/find_depot_tools.py
new file mode 100644
index 00000000000..0fa151b162c
--- /dev/null
+++ b/chromium/tools/find_depot_tools.py
@@ -0,0 +1,40 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Small utility function to find depot_tools and add it to the python path.
+
+Will throw an ImportError exception if depot_tools can't be found since it
+imports breakpad.
+"""
+
+import os
+import sys
+
+def add_depot_tools_to_path():
+ """Search for depot_tools and add it to sys.path."""
+ # First look if depot_tools is already in PYTHONPATH.
+ for i in sys.path:
+ if i.rstrip(os.sep).endswith('depot_tools'):
+ return i
+ # Then look if depot_tools is in PATH, common case.
+ for i in os.environ['PATH'].split(os.pathsep):
+ if i.rstrip(os.sep).endswith('depot_tools'):
+ sys.path.append(i.rstrip(os.sep))
+ return i
+ # Rare case, it's not even in PATH, look upward up to root.
+ root_dir = os.path.dirname(os.path.abspath(__file__))
+ previous_dir = os.path.abspath(__file__)
+ while root_dir and root_dir != previous_dir:
+ if os.path.isfile(os.path.join(root_dir, 'depot_tools', 'breakpad.py')):
+ i = os.path.join(root_dir, 'depot_tools')
+ sys.path.append(i)
+ return i
+ previous_dir = root_dir
+ root_dir = os.path.dirname(root_dir)
+ print >> sys.stderr, 'Failed to find depot_tools'
+ return None
+
+add_depot_tools_to_path()
+
+# pylint: disable=W0611
+import breakpad
diff --git a/chromium/tools/find_runtime_symbols/OWNERS b/chromium/tools/find_runtime_symbols/OWNERS
new file mode 100644
index 00000000000..aeea00ec3e0
--- /dev/null
+++ b/chromium/tools/find_runtime_symbols/OWNERS
@@ -0,0 +1 @@
+dmikurube@chromium.org
diff --git a/chromium/tools/find_runtime_symbols/PRESUBMIT.py b/chromium/tools/find_runtime_symbols/PRESUBMIT.py
new file mode 100644
index 00000000000..8d6889ce3f9
--- /dev/null
+++ b/chromium/tools/find_runtime_symbols/PRESUBMIT.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for find_runtime_symbols.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+
+def CommonChecks(input_api, output_api):
+ import sys
+ def join(*args):
+ return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
+
+ output = []
+ sys_path_backup = sys.path
+ try:
+ sys.path = [
+ join('..', 'find_runtime_symbols'),
+ ] + sys.path
+ output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+ finally:
+ sys.path = sys_path_backup
+
+ output.extend(
+ input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api,
+ input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'),
+ whitelist=[r'.+_test\.py$']))
+
+ if input_api.is_committing:
+ output.extend(input_api.canned_checks.PanProjectChecks(input_api,
+ output_api,
+ owners_check=False))
+ return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/chromium/tools/find_runtime_symbols/README b/chromium/tools/find_runtime_symbols/README
new file mode 100644
index 00000000000..ee5c2ac88ca
--- /dev/null
+++ b/chromium/tools/find_runtime_symbols/README
@@ -0,0 +1,24 @@
+This script maps runtime addresses to symbol names. It is robust over
+Address Space Layout Randomization (ASLR) since it uses runtime addresses with
+runtime mapping information (/proc/.../maps).
+Like 'pprof --symbols' in gperftools <http://code.google.com/p/gperftools/>.
+
+
+Step 1: Prepare symbol information.
+
+It is required to collect symbol information before mapping runtime addresses
+to symbol names.
+
+./prepare_symbol_info.py /path/to/maps [/another/path/to/symbol_info_dir]
+
+The required 'maps' file is /proc/.../maps of the process at runtime.
+
+
+Step 2: Find symbols.
+
+./find_runtime_symbols.py /path/to/symbol_info_dir < addresses.txt
+
+'symbol_info_dir' is the result of the Step 1.
+The stdin should be a list of hex addresses to map, one per line.
+
+The results will be printed to stdout like 'pprof --symbols'.
diff --git a/chromium/tools/find_runtime_symbols/find_runtime_symbols.py b/chromium/tools/find_runtime_symbols/find_runtime_symbols.py
new file mode 100755
index 00000000000..bed9e800b17
--- /dev/null
+++ b/chromium/tools/find_runtime_symbols/find_runtime_symbols.py
@@ -0,0 +1,207 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Find symbols in a binary corresponding to given runtime virtual addresses.
+
+Note that source file names are treated as symbols in this script while they
+are actually not.
+"""
+
+import json
+import logging
+import os
+import sys
+
+from static_symbols import StaticSymbolsInFile
+from proc_maps import ProcMaps
+
+try:
+ from collections import OrderedDict # pylint: disable=E0611
+except ImportError:
+ BASE_PATH = os.path.dirname(os.path.abspath(__file__))
+ SIMPLEJSON_PATH = os.path.join(BASE_PATH, os.pardir, os.pardir, 'third_party')
+ sys.path.insert(0, SIMPLEJSON_PATH)
+ from simplejson import OrderedDict
+
+
+FUNCTION_SYMBOLS = 0
+SOURCEFILE_SYMBOLS = 1
+TYPEINFO_SYMBOLS = 2
+
+_MAPS_FILENAME = 'maps'
+_FILES_FILENAME = 'files.json'
+
+
+class RuntimeSymbolsInProcess(object):
+ def __init__(self):
+ self._maps = None
+ self._static_symbols_in_filse = {}
+
+ def find_procedure(self, runtime_address):
+ for vma in self._maps.iter(ProcMaps.executable):
+ if vma.begin <= runtime_address < vma.end:
+ static_symbols = self._static_symbols_in_filse.get(vma.name)
+ if static_symbols:
+ return static_symbols.find_procedure_by_runtime_address(
+ runtime_address, vma)
+ else:
+ return None
+ return None
+
+ def find_sourcefile(self, runtime_address):
+ for vma in self._maps.iter(ProcMaps.executable):
+ if vma.begin <= runtime_address < vma.end:
+ static_symbols = self._static_symbols_in_filse.get(vma.name)
+ if static_symbols:
+ return static_symbols.find_sourcefile_by_runtime_address(
+ runtime_address, vma)
+ else:
+ return None
+ return None
+
+ def find_typeinfo(self, runtime_address):
+ for vma in self._maps.iter(ProcMaps.constants):
+ if vma.begin <= runtime_address < vma.end:
+ static_symbols = self._static_symbols_in_filse.get(vma.name)
+ if static_symbols:
+ return static_symbols.find_typeinfo_by_runtime_address(
+ runtime_address, vma)
+ else:
+ return None
+ return None
+
+ @staticmethod
+ def load(prepared_data_dir):
+ symbols_in_process = RuntimeSymbolsInProcess()
+
+ with open(os.path.join(prepared_data_dir, _MAPS_FILENAME), mode='r') as f:
+ symbols_in_process._maps = ProcMaps.load(f)
+ with open(os.path.join(prepared_data_dir, _FILES_FILENAME), mode='r') as f:
+ files = json.load(f)
+
+ # pylint: disable=W0212
+ for vma in symbols_in_process._maps.iter(ProcMaps.executable_and_constants):
+ file_entry = files.get(vma.name)
+ if not file_entry:
+ continue
+
+ static_symbols = StaticSymbolsInFile(vma.name)
+
+ nm_entry = file_entry.get('nm')
+ if nm_entry and nm_entry['format'] == 'bsd':
+ with open(os.path.join(prepared_data_dir, nm_entry['file']), 'r') as f:
+ static_symbols.load_nm_bsd(f, nm_entry['mangled'])
+
+ readelf_entry = file_entry.get('readelf-e')
+ if readelf_entry:
+ with open(os.path.join(prepared_data_dir, readelf_entry['file']),
+ 'r') as f:
+ static_symbols.load_readelf_ew(f)
+
+ decodedline_file_entry = file_entry.get('readelf-debug-decodedline-file')
+ if decodedline_file_entry:
+ with open(os.path.join(prepared_data_dir,
+ decodedline_file_entry['file']), 'r') as f:
+ static_symbols.load_readelf_debug_decodedline_file(f)
+
+ symbols_in_process._static_symbols_in_filse[vma.name] = static_symbols
+
+ return symbols_in_process
+
+
+def _find_runtime_function_symbols(symbols_in_process, addresses):
+ result = OrderedDict()
+ for address in addresses:
+ if isinstance(address, basestring):
+ address = int(address, 16)
+ found = symbols_in_process.find_procedure(address)
+ if found:
+ result[address] = found.name
+ else:
+ result[address] = '0x%016x' % address
+ return result
+
+
+def _find_runtime_sourcefile_symbols(symbols_in_process, addresses):
+ result = OrderedDict()
+ for address in addresses:
+ if isinstance(address, basestring):
+ address = int(address, 16)
+ found = symbols_in_process.find_sourcefile(address)
+ if found:
+ result[address] = found
+ else:
+ result[address] = ''
+ return result
+
+
+def _find_runtime_typeinfo_symbols(symbols_in_process, addresses):
+ result = OrderedDict()
+ for address in addresses:
+ if isinstance(address, basestring):
+ address = int(address, 16)
+ if address == 0:
+ result[address] = 'no typeinfo'
+ else:
+ found = symbols_in_process.find_typeinfo(address)
+ if found:
+ if found.startswith('typeinfo for '):
+ result[address] = found[13:]
+ else:
+ result[address] = found
+ else:
+ result[address] = '0x%016x' % address
+ return result
+
+
+_INTERNAL_FINDERS = {
+ FUNCTION_SYMBOLS: _find_runtime_function_symbols,
+ SOURCEFILE_SYMBOLS: _find_runtime_sourcefile_symbols,
+ TYPEINFO_SYMBOLS: _find_runtime_typeinfo_symbols,
+ }
+
+
+def find_runtime_symbols(symbol_type, symbols_in_process, addresses):
+ return _INTERNAL_FINDERS[symbol_type](symbols_in_process, addresses)
+
+
+def main():
+ # FIX: Accept only .pre data
+ if len(sys.argv) < 2:
+ sys.stderr.write("""Usage:
+%s /path/to/prepared_data_dir/ < addresses.txt
+""" % sys.argv[0])
+ return 1
+
+ log = logging.getLogger('find_runtime_symbols')
+ log.setLevel(logging.WARN)
+ handler = logging.StreamHandler()
+ handler.setLevel(logging.WARN)
+ formatter = logging.Formatter('%(message)s')
+ handler.setFormatter(formatter)
+ log.addHandler(handler)
+
+ prepared_data_dir = sys.argv[1]
+ if not os.path.exists(prepared_data_dir):
+ log.warn("Nothing found: %s" % prepared_data_dir)
+ return 1
+ if not os.path.isdir(prepared_data_dir):
+ log.warn("Not a directory: %s" % prepared_data_dir)
+ return 1
+
+ symbols_in_process = RuntimeSymbolsInProcess.load(prepared_data_dir)
+ symbols_dict = find_runtime_symbols(FUNCTION_SYMBOLS,
+ symbols_in_process,
+ sys.stdin)
+ for address, symbol in symbols_dict:
+ if symbol:
+ print '%016x %s' % (address, symbol)
+ else:
+ print '%016x' % address
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/find_runtime_symbols/prepare_symbol_info.py b/chromium/tools/find_runtime_symbols/prepare_symbol_info.py
new file mode 100755
index 00000000000..d5503881a1c
--- /dev/null
+++ b/chromium/tools/find_runtime_symbols/prepare_symbol_info.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import hashlib
+import json
+import logging
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+
+from proc_maps import ProcMaps
+
+
+BASE_PATH = os.path.dirname(os.path.abspath(__file__))
+REDUCE_DEBUGLINE_PATH = os.path.join(BASE_PATH, 'reduce_debugline.py')
+LOGGER = logging.getLogger('prepare_symbol_info')
+
+
+def _dump_command_result(command, output_dir_path, basename, suffix):
+ handle_out, filename_out = tempfile.mkstemp(
+ suffix=suffix, prefix=basename + '.', dir=output_dir_path)
+ handle_err, filename_err = tempfile.mkstemp(
+ suffix=suffix + '.err', prefix=basename + '.', dir=output_dir_path)
+ error = False
+ try:
+ subprocess.check_call(
+ command, stdout=handle_out, stderr=handle_err, shell=True)
+ except (OSError, subprocess.CalledProcessError):
+ error = True
+ finally:
+ os.close(handle_err)
+ os.close(handle_out)
+
+ if os.path.exists(filename_err):
+ if LOGGER.getEffectiveLevel() <= logging.DEBUG:
+ with open(filename_err, 'r') as f:
+ for line in f:
+ LOGGER.debug(line.rstrip())
+ os.remove(filename_err)
+
+ if os.path.exists(filename_out) and (
+ os.path.getsize(filename_out) == 0 or error):
+ os.remove(filename_out)
+ return None
+
+ if not os.path.exists(filename_out):
+ return None
+
+ return filename_out
+
+
+def prepare_symbol_info(maps_path,
+ output_dir_path=None,
+ alternative_dirs=None,
+ use_tempdir=False,
+ use_source_file_name=False):
+ """Prepares (collects) symbol information files for find_runtime_symbols.
+
+ 1) If |output_dir_path| is specified, it tries collecting symbol information
+ files in the given directory |output_dir_path|.
+ 1-a) If |output_dir_path| doesn't exist, create the directory and use it.
+ 1-b) If |output_dir_path| is an empty directory, use it.
+ 1-c) If |output_dir_path| is a directory which has 'files.json', assumes that
+ files are already collected and just ignores it.
+ 1-d) Otherwise, depends on |use_tempdir|.
+
+ 2) If |output_dir_path| is not specified, it tries to create a new directory
+ depending on 'maps_path'.
+
+ If it cannot create a new directory, creates a temporary directory depending
+ on |use_tempdir|. If |use_tempdir| is False, returns None.
+
+ Args:
+ maps_path: A path to a file which contains '/proc/<pid>/maps'.
+ alternative_dirs: A mapping from a directory '/path/on/target' where the
+ target process runs to a directory '/path/on/host' where the script
+ reads the binary. Considered to be used for Android binaries.
+ output_dir_path: A path to a directory where files are prepared.
+ use_tempdir: If True, it creates a temporary directory when it cannot
+ create a new directory.
+ use_source_file_name: If True, it adds reduced result of 'readelf -wL'
+ to find source file names.
+
+ Returns:
+ A pair of a path to the prepared directory and a boolean representing
+ if it created a temporary directory or not.
+ """
+ alternative_dirs = alternative_dirs or {}
+ if not output_dir_path:
+ matched = re.match('^(.*)\.maps$', os.path.basename(maps_path))
+ if matched:
+ output_dir_path = matched.group(1) + '.pre'
+ if not output_dir_path:
+ matched = re.match('^/proc/(.*)/maps$', os.path.realpath(maps_path))
+ if matched:
+ output_dir_path = matched.group(1) + '.pre'
+ if not output_dir_path:
+ output_dir_path = os.path.basename(maps_path) + '.pre'
+ # TODO(dmikurube): Find another candidate for output_dir_path.
+
+ used_tempdir = False
+ LOGGER.info('Data for profiling will be collected in "%s".' % output_dir_path)
+ if os.path.exists(output_dir_path):
+ if os.path.isdir(output_dir_path) and not os.listdir(output_dir_path):
+ LOGGER.warn('Using an empty existing directory "%s".' % output_dir_path)
+ else:
+ LOGGER.warn('A file or a directory exists at "%s".' % output_dir_path)
+ if os.path.exists(os.path.join(output_dir_path, 'files.json')):
+ LOGGER.warn('Using the existing directory "%s".' % output_dir_path)
+ return output_dir_path, used_tempdir
+ else:
+ if use_tempdir:
+ output_dir_path = tempfile.mkdtemp()
+ used_tempdir = True
+ LOGGER.warn('Using a temporary directory "%s".' % output_dir_path)
+ else:
+ LOGGER.warn('The directory "%s" is not available.' % output_dir_path)
+ return None, used_tempdir
+ else:
+ LOGGER.info('Creating a new directory "%s".' % output_dir_path)
+ try:
+ os.mkdir(output_dir_path)
+ except OSError:
+ LOGGER.warn('A directory "%s" cannot be created.' % output_dir_path)
+ if use_tempdir:
+ output_dir_path = tempfile.mkdtemp()
+ used_tempdir = True
+ LOGGER.warn('Using a temporary directory "%s".' % output_dir_path)
+ else:
+ LOGGER.warn('The directory "%s" is not available.' % output_dir_path)
+ return None, used_tempdir
+
+ shutil.copyfile(maps_path, os.path.join(output_dir_path, 'maps'))
+
+ with open(maps_path, mode='r') as f:
+ maps = ProcMaps.load(f)
+
+ LOGGER.debug('Listing up symbols.')
+ files = {}
+ for entry in maps.iter(ProcMaps.executable):
+ LOGGER.debug(' %016x-%016x +%06x %s' % (
+ entry.begin, entry.end, entry.offset, entry.name))
+ binary_path = entry.name
+ for target_path, host_path in alternative_dirs.iteritems():
+ if entry.name.startswith(target_path):
+ binary_path = entry.name.replace(target_path, host_path, 1)
+ nm_filename = _dump_command_result(
+ 'nm -n --format bsd %s | c++filt' % binary_path,
+ output_dir_path, os.path.basename(binary_path), '.nm')
+ if not nm_filename:
+ continue
+ readelf_e_filename = _dump_command_result(
+ 'readelf -eW %s' % binary_path,
+ output_dir_path, os.path.basename(binary_path), '.readelf-e')
+ if not readelf_e_filename:
+ continue
+ readelf_debug_decodedline_file = None
+ if use_source_file_name:
+ readelf_debug_decodedline_file = _dump_command_result(
+ 'readelf -wL %s | %s' % (binary_path, REDUCE_DEBUGLINE_PATH),
+ output_dir_path, os.path.basename(binary_path), '.readelf-wL')
+
+ files[entry.name] = {}
+ files[entry.name]['nm'] = {
+ 'file': os.path.basename(nm_filename),
+ 'format': 'bsd',
+ 'mangled': False}
+ files[entry.name]['readelf-e'] = {
+ 'file': os.path.basename(readelf_e_filename)}
+ if readelf_debug_decodedline_file:
+ files[entry.name]['readelf-debug-decodedline-file'] = {
+ 'file': os.path.basename(readelf_debug_decodedline_file)}
+
+ files[entry.name]['size'] = os.stat(binary_path).st_size
+
+ with open(binary_path, 'rb') as entry_f:
+ md5 = hashlib.md5()
+ sha1 = hashlib.sha1()
+ chunk = entry_f.read(1024 * 1024)
+ while chunk:
+ md5.update(chunk)
+ sha1.update(chunk)
+ chunk = entry_f.read(1024 * 1024)
+ files[entry.name]['sha1'] = sha1.hexdigest()
+ files[entry.name]['md5'] = md5.hexdigest()
+
+ with open(os.path.join(output_dir_path, 'files.json'), 'w') as f:
+ json.dump(files, f, indent=2, sort_keys=True)
+
+ LOGGER.info('Collected symbol information at "%s".' % output_dir_path)
+ return output_dir_path, used_tempdir
+
+
+def main():
+ if not sys.platform.startswith('linux'):
+ sys.stderr.write('This script work only on Linux.')
+ return 1
+
+ LOGGER.setLevel(logging.DEBUG)
+ handler = logging.StreamHandler()
+ handler.setLevel(logging.INFO)
+ formatter = logging.Formatter('%(message)s')
+ handler.setFormatter(formatter)
+ LOGGER.addHandler(handler)
+
+ # TODO(dmikurube): Specify |alternative_dirs| from command line.
+ if len(sys.argv) < 2:
+ sys.stderr.write("""Usage:
+%s /path/to/maps [/path/to/output_data_dir/]
+""" % sys.argv[0])
+ return 1
+ elif len(sys.argv) == 2:
+ result, _ = prepare_symbol_info(sys.argv[1])
+ else:
+ result, _ = prepare_symbol_info(sys.argv[1], sys.argv[2])
+
+ return not result
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/find_runtime_symbols/proc_maps.py b/chromium/tools/find_runtime_symbols/proc_maps.py
new file mode 100644
index 00000000000..2d917b32124
--- /dev/null
+++ b/chromium/tools/find_runtime_symbols/proc_maps.py
@@ -0,0 +1,125 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+
+
+_MAPS_PATTERN = re.compile(
+ r'^([a-f0-9]+)-([a-f0-9]+)\s+(.)(.)(.)(.)\s+([a-f0-9]+)\s+(\S+):(\S+)\s+'
+ r'(\d+)\s*(.*)$', re.IGNORECASE)
+
+
+class ProcMapsEntry(object):
+ """A class representing one line in /proc/.../maps."""
+
+ def __init__(
+ self, begin, end, readable, writable, executable, private, offset,
+ major, minor, inode, name):
+ self.begin = begin
+ self.end = end
+ self.readable = readable
+ self.writable = writable
+ self.executable = executable
+ self.private = private
+ self.offset = offset
+ self.major = major
+ self.minor = minor
+ self.inode = inode
+ self.name = name
+
+ def as_dict(self):
+ return {
+ 'begin': self.begin,
+ 'end': self.end,
+ 'readable': self.readable,
+ 'writable': self.writable,
+ 'executable': self.executable,
+ 'private': self.private,
+ 'offset': self.offset,
+ 'major': self.major,
+ 'minor': self.minor,
+ 'inode': self.inode,
+ 'name': self.name,
+ }
+
+
+class ProcMaps(object):
+ """A class representing contents in /proc/.../maps."""
+
+ def __init__(self):
+ self._sorted_indexes = []
+ self._dictionary = {}
+ self._sorted = True
+
+ def iter(self, condition):
+ if not self._sorted:
+ self._sorted_indexes.sort()
+ self._sorted = True
+ for index in self._sorted_indexes:
+ if not condition or condition(self._dictionary[index]):
+ yield self._dictionary[index]
+
+ def __iter__(self):
+ if not self._sorted:
+ self._sorted_indexes.sort()
+ self._sorted = True
+ for index in self._sorted_indexes:
+ yield self._dictionary[index]
+
+ @staticmethod
+ def load(f):
+ table = ProcMaps()
+ for line in f:
+ table.append_line(line)
+ return table
+
+ def append_line(self, line):
+ entry = self.parse_line(line)
+ if entry:
+ self._append_entry(entry)
+
+ @staticmethod
+ def parse_line(line):
+ matched = _MAPS_PATTERN.match(line)
+ if matched:
+ return ProcMapsEntry( # pylint: disable=W0212
+ int(matched.group(1), 16), # begin
+ int(matched.group(2), 16), # end
+ matched.group(3), # readable
+ matched.group(4), # writable
+ matched.group(5), # executable
+ matched.group(6), # private
+ int(matched.group(7), 16), # offset
+ matched.group(8), # major
+ matched.group(9), # minor
+ int(matched.group(10), 10), # inode
+ matched.group(11) # name
+ )
+ else:
+ return None
+
+ @staticmethod
+ def constants(entry):
+ return (entry.writable == '-' and entry.executable == '-' and re.match(
+ '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?',
+ entry.name))
+
+ @staticmethod
+ def executable(entry):
+ return (entry.executable == 'x' and re.match(
+ '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?',
+ entry.name))
+
+ @staticmethod
+ def executable_and_constants(entry):
+ return (((entry.writable == '-' and entry.executable == '-') or
+ entry.executable == 'x') and re.match(
+ '\S+(\.(so|dll|dylib|bundle)|chrome)((\.\d+)+\w*(\.\d+){0,3})?',
+ entry.name))
+
+ def _append_entry(self, entry):
+ if self._sorted_indexes and self._sorted_indexes[-1] > entry.begin:
+ self._sorted = False
+ self._sorted_indexes.append(entry.begin)
+ self._dictionary[entry.begin] = entry
diff --git a/chromium/tools/find_runtime_symbols/reduce_debugline.py b/chromium/tools/find_runtime_symbols/reduce_debugline.py
new file mode 100755
index 00000000000..75c8c8578d7
--- /dev/null
+++ b/chromium/tools/find_runtime_symbols/reduce_debugline.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Reduces result of 'readelf -wL' to just a list of starting addresses.
+
+It lists up all addresses where the corresponding source files change. The
+list is sorted in ascending order. See tests/reduce_debugline_test.py for
+examples.
+
+This script assumes that the result of 'readelf -wL' ends with an empty line.
+
+Note: the option '-wL' has the same meaning with '--debug-dump=decodedline'.
+"""
+
+import re
+import sys
+
+
+_FILENAME_PATTERN = re.compile('(CU: |)(.+)\:')
+
+
+def reduce_decoded_debugline(input_file):
+ filename = ''
+ starting_dict = {}
+ started = False
+
+ for line in input_file:
+ line = line.strip()
+ unpacked = line.split(None, 2)
+
+ if len(unpacked) == 3 and unpacked[2].startswith('0x'):
+ if not started and filename:
+ started = True
+ starting_dict[int(unpacked[2], 16)] = filename
+ else:
+ started = False
+ if line.endswith(':'):
+ matched = _FILENAME_PATTERN.match(line)
+ if matched:
+ filename = matched.group(2)
+
+ starting_list = []
+ prev_filename = ''
+ for address in sorted(starting_dict):
+ curr_filename = starting_dict[address]
+ if prev_filename != curr_filename:
+ starting_list.append((address, starting_dict[address]))
+ prev_filename = curr_filename
+ return starting_list
+
+
+def main():
+ if len(sys.argv) != 1:
+ print >> sys.stderr, 'Unsupported arguments'
+ return 1
+
+ starting_list = reduce_decoded_debugline(sys.stdin)
+ bits64 = starting_list[-1][0] > 0xffffffff
+ for address, filename in starting_list:
+ if bits64:
+ print '%016x %s' % (address, filename)
+ else:
+ print '%08x %s' % (address, filename)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/find_runtime_symbols/static_symbols.py b/chromium/tools/find_runtime_symbols/static_symbols.py
new file mode 100644
index 00000000000..cd57bacd99a
--- /dev/null
+++ b/chromium/tools/find_runtime_symbols/static_symbols.py
@@ -0,0 +1,277 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import bisect
+import re
+
+
+_ARGUMENT_TYPE_PATTERN = re.compile('\([^()]*\)(\s*const)?')
+_TEMPLATE_ARGUMENT_PATTERN = re.compile('<[^<>]*>')
+_LEADING_TYPE_PATTERN = re.compile('^.*\s+(\w+::)')
+_READELF_SECTION_HEADER_PATTER = re.compile(
+ '^\s*\[\s*(Nr|\d+)\]\s+(|\S+)\s+([A-Z_]+)\s+([0-9a-f]+)\s+'
+ '([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9]+)\s+([WAXMSILGxOop]*)\s+'
+ '([0-9]+)\s+([0-9]+)\s+([0-9]+)')
+
+
+class ParsingException(Exception):
+ def __str__(self):
+ return repr(self.args[0])
+
+
+class AddressMapping(object):
+ def __init__(self):
+ self._symbol_map = {}
+
+ def append(self, start, entry):
+ self._symbol_map[start] = entry
+
+ def find(self, address):
+ return self._symbol_map.get(address)
+
+
+class RangeAddressMapping(AddressMapping):
+ def __init__(self):
+ super(RangeAddressMapping, self).__init__()
+ self._sorted_start_list = []
+ self._is_sorted = True
+
+ def append(self, start, entry):
+ if self._sorted_start_list:
+ if self._sorted_start_list[-1] > start:
+ self._is_sorted = False
+ elif self._sorted_start_list[-1] == start:
+ return
+ self._sorted_start_list.append(start)
+ self._symbol_map[start] = entry
+
+ def find(self, address):
+ if not self._sorted_start_list:
+ return None
+ if not self._is_sorted:
+ self._sorted_start_list.sort()
+ self._is_sorted = True
+ found_index = bisect.bisect_left(self._sorted_start_list, address)
+ found_start_address = self._sorted_start_list[found_index - 1]
+ return self._symbol_map[found_start_address]
+
+
+class Procedure(object):
+ """A class for a procedure symbol and an address range for the symbol."""
+
+ def __init__(self, start, end, name):
+ self.start = start
+ self.end = end
+ self.name = name
+
+ def __eq__(self, other):
+ return (self.start == other.start and
+ self.end == other.end and
+ self.name == other.name)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __str__(self):
+ return '%x-%x: %s' % (self.start, self.end, self.name)
+
+
+class ElfSection(object):
+ """A class for an elf section header."""
+
+ def __init__(
+ self, number, name, stype, address, offset, size, es, flg, lk, inf, al):
+ self.number = number
+ self.name = name
+ self.stype = stype
+ self.address = address
+ self.offset = offset
+ self.size = size
+ self.es = es
+ self.flg = flg
+ self.lk = lk
+ self.inf = inf
+ self.al = al
+
+ def __eq__(self, other):
+ return (self.number == other.number and
+ self.name == other.name and
+ self.stype == other.stype and
+ self.address == other.address and
+ self.offset == other.offset and
+ self.size == other.size and
+ self.es == other.es and
+ self.flg == other.flg and
+ self.lk == other.lk and
+ self.inf == other.inf and
+ self.al == other.al)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def __str__(self):
+ return '%x+%x(%x) %s' % (self.address, self.size, self.offset, self.name)
+
+
+class StaticSymbolsInFile(object):
+ """Represents static symbol information in a binary file."""
+
+ def __init__(self, my_name):
+ self.my_name = my_name
+ self._elf_sections = []
+ self._procedures = RangeAddressMapping()
+ self._sourcefiles = RangeAddressMapping()
+ self._typeinfos = AddressMapping()
+
+ def _append_elf_section(self, elf_section):
+ self._elf_sections.append(elf_section)
+
+ def _append_procedure(self, start, procedure):
+ self._procedures.append(start, procedure)
+
+ def _append_sourcefile(self, start, sourcefile):
+ self._sourcefiles.append(start, sourcefile)
+
+ def _append_typeinfo(self, start, typeinfo):
+ self._typeinfos.append(start, typeinfo)
+
+ def _find_symbol_by_runtime_address(self, address, vma, target):
+ if not (vma.begin <= address < vma.end):
+ return None
+
+ if vma.name != self.my_name:
+ return None
+
+ file_offset = address - (vma.begin - vma.offset)
+ elf_address = None
+ for section in self._elf_sections:
+ if section.offset <= file_offset < (section.offset + section.size):
+ elf_address = section.address + file_offset - section.offset
+ if not elf_address:
+ return None
+
+ return target.find(elf_address)
+
+ def find_procedure_by_runtime_address(self, address, vma):
+ return self._find_symbol_by_runtime_address(address, vma, self._procedures)
+
+ def find_sourcefile_by_runtime_address(self, address, vma):
+ return self._find_symbol_by_runtime_address(address, vma, self._sourcefiles)
+
+ def find_typeinfo_by_runtime_address(self, address, vma):
+ return self._find_symbol_by_runtime_address(address, vma, self._typeinfos)
+
+ def load_readelf_ew(self, f):
+ found_header = False
+ for line in f:
+ if line.rstrip() == 'Section Headers:':
+ found_header = True
+ break
+ if not found_header:
+ return None
+
+ for line in f:
+ line = line.rstrip()
+ matched = _READELF_SECTION_HEADER_PATTER.match(line)
+ if matched:
+ self._append_elf_section(ElfSection(
+ int(matched.group(1), 10), # number
+ matched.group(2), # name
+ matched.group(3), # stype
+ int(matched.group(4), 16), # address
+ int(matched.group(5), 16), # offset
+ int(matched.group(6), 16), # size
+ matched.group(7), # es
+ matched.group(8), # flg
+ matched.group(9), # lk
+ matched.group(10), # inf
+ matched.group(11) # al
+ ))
+ else:
+ if line in ('Key to Flags:', 'Program Headers:'):
+ break
+
+ def load_readelf_debug_decodedline_file(self, input_file):
+ for line in input_file:
+ splitted = line.rstrip().split(None, 2)
+ self._append_sourcefile(int(splitted[0], 16), splitted[1])
+
+ @staticmethod
+ def _parse_nm_bsd_line(line):
+ if line[8] == ' ':
+ return line[0:8], line[9], line[11:]
+ elif line[16] == ' ':
+ return line[0:16], line[17], line[19:]
+ raise ParsingException('Invalid nm output.')
+
+ @staticmethod
+ def _get_short_function_name(function):
+ while True:
+ function, number = _ARGUMENT_TYPE_PATTERN.subn('', function)
+ if not number:
+ break
+ while True:
+ function, number = _TEMPLATE_ARGUMENT_PATTERN.subn('', function)
+ if not number:
+ break
+ return _LEADING_TYPE_PATTERN.sub('\g<1>', function)
+
+ def load_nm_bsd(self, f, mangled=False):
+ last_start = 0
+ routine = ''
+
+ for line in f:
+ line = line.rstrip()
+ sym_value, sym_type, sym_name = self._parse_nm_bsd_line(line)
+
+ if sym_value[0] == ' ':
+ continue
+
+ start_val = int(sym_value, 16)
+
+ if (sym_type in ('r', 'R', 'D', 'U', 'd', 'V') and
+ (not mangled and sym_name.startswith('typeinfo'))):
+ self._append_typeinfo(start_val, sym_name)
+
+ # It's possible for two symbols to share the same address, if
+ # one is a zero-length variable (like __start_google_malloc) or
+ # one symbol is a weak alias to another (like __libc_malloc).
+ # In such cases, we want to ignore all values except for the
+ # actual symbol, which in nm-speak has type "T". The logic
+ # below does this, though it's a bit tricky: what happens when
+ # we have a series of lines with the same address, is the first
+ # one gets queued up to be processed. However, it won't
+ # *actually* be processed until later, when we read a line with
+ # a different address. That means that as long as we're reading
+ # lines with the same address, we have a chance to replace that
+ # item in the queue, which we do whenever we see a 'T' entry --
+ # that is, a line with type 'T'. If we never see a 'T' entry,
+ # we'll just go ahead and process the first entry (which never
+ # got touched in the queue), and ignore the others.
+ if start_val == last_start and (sym_type == 't' or sym_type == 'T'):
+ # We are the 'T' symbol at this address, replace previous symbol.
+ routine = sym_name
+ continue
+ elif start_val == last_start:
+ # We're not the 'T' symbol at this address, so ignore us.
+ continue
+
+ # Tag this routine with the starting address in case the image
+ # has multiple occurrences of this routine. We use a syntax
+ # that resembles template paramters that are automatically
+ # stripped out by ShortFunctionName()
+ sym_name += "<%016x>" % start_val
+
+ if not mangled:
+ routine = self._get_short_function_name(routine)
+ self._append_procedure(
+ last_start, Procedure(last_start, start_val, routine))
+
+ last_start = start_val
+ routine = sym_name
+
+ if not mangled:
+ routine = self._get_short_function_name(routine)
+ self._append_procedure(
+ last_start, Procedure(last_start, last_start, routine))
diff --git a/chromium/tools/flakiness/find_flakiness.py b/chromium/tools/flakiness/find_flakiness.py
new file mode 100755
index 00000000000..21629e4a7a6
--- /dev/null
+++ b/chromium/tools/flakiness/find_flakiness.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Contains two functions that run different test cases and the same test
+case in parallel repeatedly to identify flaky tests.
+"""
+
+
+import os
+import re
+import subprocess
+import time
+
+
+# Defaults for FindShardingFlakiness().
+FF_DATA_SUFFIX = '_flakies'
+FF_SLEEP_INTERVAL = 10.0
+FF_NUM_ITERATIONS = 100
+FF_SUPERVISOR_ARGS = ['-r3', '--random-seed']
+
+# Defaults for FindUnaryFlakiness().
+FF_OUTPUT_SUFFIX = '_purges'
+FF_NUM_PROCS = 20
+FF_NUM_REPEATS = 10
+FF_TIMEOUT = 600
+
+
+def FindShardingFlakiness(test_path, data_path, supervisor_args):
+ """Finds flaky test cases by sharding and running a test for the specified
+ number of times. The data file is read at the beginning of each run to find
+ the last known counts and is overwritten at the end of each run with the new
+ counts. There is an optional sleep interval between each run so the script can
+ be killed without losing the data, useful for overnight (or weekend!) runs.
+ """
+
+ failed_tests = {}
+ # Read a previously written data file.
+ if os.path.exists(data_path):
+ data_file = open(data_path, 'r')
+ num_runs = int(data_file.readline().split(' ')[0])
+ num_passes = int(data_file.readline().split(' ')[0])
+ for line in data_file:
+ if line:
+ split_line = line.split(' -> ')
+ failed_tests[split_line[0]] = int(split_line[1])
+ data_file.close()
+ # No data file found.
+ else:
+ num_runs = 0
+ num_passes = 0
+
+ log_lines = False
+ args = ['python', '../sharding_supervisor/sharding_supervisor.py']
+ args.extend(supervisor_args + [test_path])
+ proc = subprocess.Popen(args, stderr=subprocess.PIPE)
+
+ # Shard the test and collect failures.
+ while True:
+ line = proc.stderr.readline()
+ if not line:
+ if proc.poll() is not None:
+ break
+ continue
+ print line.rstrip()
+ if log_lines:
+ line = line.rstrip()
+ if line in failed_tests:
+ failed_tests[line] += 1
+ else:
+ failed_tests[line] = 1
+ elif line.find('FAILED TESTS:') >= 0:
+ log_lines = True
+ num_runs += 1
+ if proc.returncode == 0:
+ num_passes += 1
+
+ # Write the data file and print results.
+ data_file = open(data_path, 'w')
+ print '%i runs' % num_runs
+ data_file.write('%i runs\n' % num_runs)
+ print '%i passes' % num_passes
+ data_file.write('%i passes\n' % num_passes)
+ for (test, count) in failed_tests.iteritems():
+ print '%s -> %i' % (test, count)
+ data_file.write('%s -> %i\n' % (test, count))
+ data_file.close()
+
+
+def FindUnaryFlakiness(test_path, output_path, num_procs, num_repeats, timeout):
+ """Runs all the test cases in a given test in parallel with itself, to get at
+ those that hold on to shared resources. The idea is that if a test uses a
+ unary resource, then running many instances of this test will purge out some
+ of them as failures or timeouts.
+ """
+
+ test_name_regex = r'((\w+/)?\w+\.\w+(/\d+)?)'
+ test_start = re.compile('\[\s+RUN\s+\] ' + test_name_regex)
+ test_list = []
+
+ # Run the test to discover all the test cases.
+ proc = subprocess.Popen([test_path], stdout=subprocess.PIPE)
+ while True:
+ line = proc.stdout.readline()
+ if not line:
+ if proc.poll() is not None:
+ break
+ continue
+ print line.rstrip()
+ results = test_start.search(line)
+ if results:
+ test_list.append(results.group(1))
+
+ failures = []
+ index = 0
+ total = len(test_list)
+
+ # Run each test case in parallel with itself.
+ for test_name in test_list:
+ num_fails = 0
+ num_terminated = 0
+ procs = []
+ args = [test_path, '--gtest_filter=' + test_name,
+ '--gtest_repeat=%i' % num_repeats]
+ while len(procs) < num_procs:
+ procs.append(subprocess.Popen(args))
+ seconds = 0
+ while procs:
+ for proc in procs:
+ if proc.poll() is not None:
+ if proc.returncode != 0:
+ ++num_fails
+ procs.remove(proc)
+ # Timeout exceeded, kill the remaining processes and make a note.
+ if seconds > timeout:
+ num_fails += len(procs)
+ num_terminated = len(procs)
+ while procs:
+ procs.pop().terminate()
+ time.sleep(1.0)
+ seconds += 1
+ if num_fails:
+ line = '%s: %i failed' % (test_name, num_fails)
+ if num_terminated:
+ line += ' (%i terminated)' % num_terminated
+ failures.append(line)
+ print '%s (%i / %i): %i failed' % (test_name, index, total, num_fails)
+ index += 1
+ time.sleep(1.0)
+
+ # Print the results and write the data file.
+ print failures
+ data_file = open(output_path, 'w')
+ for line in failures:
+ data_file.write(line + '\n')
+ data_file.close()
+
+
+def main():
+ if not args:
+ parser.error('You must specify a path to test!')
+ if not os.path.exists(args[0]):
+ parser.error('%s does not exist!' % args[0])
+
+ data_path = os.path.basename(args[0]) + FF_DATA_SUFFIX
+ output_path = os.path.basename(args[0]) + FF_OUTPUT_SUFFIX
+
+ for i in range(FF_NUM_ITERATIONS):
+ FindShardingFlakiness(args[0], data_path, FF_SUPERVISOR_ARGS)
+ print 'That was just iteration %i of %i.' % (i + 1, FF_NUM_ITERATIONS)
+ time.sleep(FF_SLEEP_INTERVAL)
+
+ FindUnaryFlakiness(
+ args[0], output_path, FF_NUM_PROCS, FF_NUM_REPEATS, FF_TIMEOUT)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/gdb/gdb_chrome.py b/chromium/tools/gdb/gdb_chrome.py
new file mode 100644
index 00000000000..8173fa15a54
--- /dev/null
+++ b/chromium/tools/gdb/gdb_chrome.py
@@ -0,0 +1,296 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""GDB support for Chrome types.
+
+Add this to your gdb by amending your ~/.gdbinit as follows:
+ python
+ import sys
+ sys.path.insert(0, "/path/to/tools/gdb/")
+ import gdb_chrome
+ end
+
+This module relies on the WebKit gdb module already existing in
+your Python path.
+
+Use
+ (gdb) p /r any_variable
+to print |any_variable| without using any printers.
+"""
+
+import datetime
+import gdb
+import webkit
+
+# When debugging this module, set the below variable to True, and then use
+# (gdb) python del sys.modules['gdb_chrome']
+# (gdb) python import gdb_chrome
+# to reload.
+_DEBUGGING = False
+
+
+pp_set = gdb.printing.RegexpCollectionPrettyPrinter("chromium")
+
+
+def typed_ptr(ptr):
+ """Prints a pointer along with its exact type.
+
+ By default, gdb would print just the address, which takes more
+ steps to interpret.
+ """
+ # Returning this as a cast expression surrounded by parentheses
+ # makes it easier to cut+paste inside of gdb.
+ return '((%s)%s)' % (ptr.dynamic_type, ptr)
+
+
+class Printer(object):
+ def __init__(self, val):
+ self.val = val
+
+
+class StringPrinter(Printer):
+ def display_hint(self):
+ return 'string'
+
+
+class String16Printer(StringPrinter):
+ def to_string(self):
+ return webkit.ustring_to_string(self.val['_M_dataplus']['_M_p'])
+pp_set.add_printer(
+ 'string16',
+ '^string16|std::basic_string<(unsigned short|char16|base::char16).*>$',
+ String16Printer);
+
+
+class GURLPrinter(StringPrinter):
+ def to_string(self):
+ return self.val['spec_']
+pp_set.add_printer('GURL', '^GURL$', GURLPrinter)
+
+
+class FilePathPrinter(StringPrinter):
+ def to_string(self):
+ return self.val['path_']['_M_dataplus']['_M_p']
+pp_set.add_printer('FilePath', '^FilePath$', FilePathPrinter)
+
+
+class SizePrinter(Printer):
+ def to_string(self):
+ return '%sx%s' % (self.val['width_'], self.val['height_'])
+pp_set.add_printer('gfx::Size', '^gfx::(Size|SizeF|SizeBase<.*>)$', SizePrinter)
+
+
+class PointPrinter(Printer):
+ def to_string(self):
+ return '%s,%s' % (self.val['x_'], self.val['y_'])
+pp_set.add_printer('gfx::Point', '^gfx::(Point|PointF|PointBase<.*>)$',
+ PointPrinter)
+
+
+class RectPrinter(Printer):
+ def to_string(self):
+ return '%s %s' % (self.val['origin_'], self.val['size_'])
+pp_set.add_printer('gfx::Rect', '^gfx::(Rect|RectF|RectBase<.*>)$',
+ RectPrinter)
+
+
+class SmartPtrPrinter(Printer):
+ def to_string(self):
+ return '%s%s' % (self.typename, typed_ptr(self.ptr()))
+
+
+class ScopedRefPtrPrinter(SmartPtrPrinter):
+ typename = 'scoped_refptr'
+ def ptr(self):
+ return self.val['ptr_']
+pp_set.add_printer('scoped_refptr', '^scoped_refptr<.*>$', ScopedRefPtrPrinter)
+
+
+class LinkedPtrPrinter(SmartPtrPrinter):
+ typename = 'linked_ptr'
+ def ptr(self):
+ return self.val['value_']
+pp_set.add_printer('linked_ptr', '^linked_ptr<.*>$', LinkedPtrPrinter)
+
+
+class WeakPtrPrinter(SmartPtrPrinter):
+ typename = 'base::WeakPtr'
+ def ptr(self):
+ flag = ScopedRefPtrPrinter(self.val['ref_']['flag_']).ptr()
+ if flag and flag['is_valid_']:
+ return self.val['ptr_']
+ return gdb.Value(0).cast(self.val['ptr_'].type)
+pp_set.add_printer('base::WeakPtr', '^base::WeakPtr<.*>$', WeakPtrPrinter)
+
+
+class CallbackPrinter(Printer):
+ """Callbacks provide no usable information so reduce the space they take."""
+ def to_string(self):
+ return '...'
+pp_set.add_printer('base::Callback', '^base::Callback<.*>$', CallbackPrinter)
+
+
+class LocationPrinter(Printer):
+ def to_string(self):
+ return '%s()@%s:%s' % (self.val['function_name_'].string(),
+ self.val['file_name_'].string(),
+ self.val['line_number_'])
+pp_set.add_printer('tracked_objects::Location', '^tracked_objects::Location$',
+ LocationPrinter)
+
+
+class LockPrinter(Printer):
+ def to_string(self):
+ try:
+ if self.val['owned_by_thread_']:
+ return 'Locked by thread %s' % self.val['owning_thread_id_']
+ else:
+ return 'Unlocked'
+ except gdb.error:
+ return 'Unknown state'
+pp_set.add_printer('base::Lock', '^base::Lock$', LockPrinter)
+
+
+class TimeDeltaPrinter(object):
+ def __init__(self, val):
+ self._timedelta = datetime.timedelta(microseconds=int(val['delta_']))
+
+ def timedelta(self):
+ return self._timedelta
+
+ def to_string(self):
+ return str(self._timedelta)
+pp_set.add_printer('base::TimeDelta', '^base::TimeDelta$', TimeDeltaPrinter)
+
+
+class TimeTicksPrinter(TimeDeltaPrinter):
+ def __init__(self, val):
+ self._timedelta = datetime.timedelta(microseconds=int(val['ticks_']))
+pp_set.add_printer('base::TimeTicks', '^base::TimeTicks$', TimeTicksPrinter)
+
+
+class TimePrinter(object):
+ def __init__(self, val):
+ timet_offset = gdb.parse_and_eval(
+ 'base::Time::kTimeTToMicrosecondsOffset')
+ self._datetime = (datetime.datetime.fromtimestamp(0) +
+ datetime.timedelta(microseconds=
+ int(val['us_'] - timet_offset)))
+
+ def datetime(self):
+ return self._datetime
+
+ def to_string(self):
+ return str(self._datetime)
+pp_set.add_printer('base::Time', '^base::Time$', TimePrinter)
+
+
+class IpcMessagePrinter(Printer):
+ def header(self):
+ return self.val['header_'].cast(
+ gdb.lookup_type('IPC::Message::Header').pointer())
+
+ def to_string(self):
+ message_type = self.header()['type']
+ return '%s of kind %s line %s' % (
+ self.val.dynamic_type,
+ (message_type >> 16).cast(gdb.lookup_type('IPCMessageStart')),
+ message_type & 0xffff)
+
+ def children(self):
+ yield ('header_', self.header().dereference())
+ yield ('capacity_', self.val['capacity_'])
+ yield ('variable_buffer_offset_', self.val['variable_buffer_offset_'])
+ for field in self.val.type.fields():
+ if field.is_base_class:
+ continue
+ yield (field.name, self.val[field.name])
+pp_set.add_printer('IPC::Message', '^IPC::Message$', IpcMessagePrinter)
+
+
+class NotificationRegistrarPrinter(Printer):
+ def to_string(self):
+ try:
+ registrations = self.val['registered_']
+ vector_finish = registrations['_M_impl']['_M_finish']
+ vector_start = registrations['_M_impl']['_M_start']
+ if vector_start == vector_finish:
+ return 'Not watching notifications'
+ if vector_start.dereference().type.sizeof == 0:
+ # Incomplete type: b/8242773
+ return 'Watching some notifications'
+ return ('Watching %s notifications; '
+ 'print %s->registered_ for details') % (
+ int(vector_finish - vector_start),
+ typed_ptr(self.val.address))
+ except gdb.error:
+ return 'NotificationRegistrar'
+pp_set.add_printer('content::NotificationRegistrar',
+ '^content::NotificationRegistrar$',
+ NotificationRegistrarPrinter)
+
+
+class SiteInstanceImplPrinter(object):
+ def __init__(self, val):
+ self.val = val.cast(val.dynamic_type)
+
+ def to_string(self):
+ return 'SiteInstanceImpl@%s for %s' % (
+ self.val.address, self.val['site_'])
+
+ def children(self):
+ yield ('id_', self.val['id_'])
+ yield ('has_site_', self.val['has_site_'])
+ if self.val['browsing_instance_']['ptr_']:
+ yield ('browsing_instance_', self.val['browsing_instance_']['ptr_'])
+ if self.val['process_']:
+ yield ('process_', typed_ptr(self.val['process_']))
+ if self.val['render_process_host_factory_']:
+ yield ('render_process_host_factory_',
+ self.val['render_process_host_factory_'])
+pp_set.add_printer('content::SiteInstanceImpl', '^content::SiteInstanceImpl$',
+ SiteInstanceImplPrinter)
+
+
+class RenderProcessHostImplPrinter(object):
+ def __init__(self, val):
+ self.val = val.cast(val.dynamic_type)
+
+ def to_string(self):
+ pid = ''
+ try:
+ child_process_launcher_ptr = (
+ self.val['child_process_launcher_']['impl_']['data_']['ptr'])
+ if child_process_launcher_ptr:
+ context = (child_process_launcher_ptr['context_']['ptr_'])
+ if context:
+ pid = ' PID %s' % str(context['process_']['process_'])
+ except gdb.error:
+ # The definition of the Context type may not be available.
+ # b/8242773
+ pass
+ return 'RenderProcessHostImpl@%s%s' % (self.val.address, pid)
+
+ def children(self):
+ yield ('id_', self.val['id_'])
+ yield ('render_widget_hosts_',
+ self.val['render_widget_hosts_']['data_'])
+ yield ('fast_shutdown_started_', self.val['fast_shutdown_started_'])
+ yield ('deleting_soon_', self.val['deleting_soon_'])
+ yield ('pending_views_', self.val['pending_views_'])
+ yield ('visible_widgets_', self.val['visible_widgets_'])
+ yield ('backgrounded_', self.val['backgrounded_'])
+ yield ('widget_helper_', self.val['widget_helper_'])
+ yield ('is_initialized_', self.val['is_initialized_'])
+ yield ('browser_context_', typed_ptr(self.val['browser_context_']))
+ yield ('sudden_termination_allowed_',
+ self.val['sudden_termination_allowed_'])
+ yield ('ignore_input_events_', self.val['ignore_input_events_'])
+ yield ('is_guest_', self.val['is_guest_'])
+pp_set.add_printer('content::RenderProcessHostImpl',
+ '^content::RenderProcessHostImpl$',
+ RenderProcessHostImplPrinter)
+
+
+gdb.printing.register_pretty_printer(gdb, pp_set, replace=_DEBUGGING)
diff --git a/chromium/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py b/chromium/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py
new file mode 100755
index 00000000000..8531241f280
--- /dev/null
+++ b/chromium/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py
@@ -0,0 +1,529 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generate keyboard layout and hotkey data for the keyboard overlay.
+
+This script fetches data from the keyboard layout and hotkey data spreadsheet,
+and output the data depending on the option.
+
+ --cc: Rewrites a part of C++ code in
+ chrome/browser/chromeos/webui/keyboard_overlay_ui.cc
+
+ --grd: Rewrites a part of grd messages in
+ chrome/app/generated_resources.grd
+
+ --js: Rewrites the entire JavaScript code in
+ chrome/browser/resources/keyboard_overlay/keyboard_overlay_data.js
+
+These options can be specified at the same time.
+
+e.g.
+python gen_keyboard_overlay_data.py --cc --grd --js
+
+The output directory of the generated files can be changed with --outdir.
+
+e.g. (This will generate tmp/keyboard_overlay.js)
+python gen_keyboard_overlay_data.py --outdir=tmp --js
+"""
+
+import cStringIO
+import datetime
+import gdata.spreadsheet.service
+import getpass
+import json
+import optparse
+import os
+import re
+import sys
+
+MODIFIER_SHIFT = 1 << 0
+MODIFIER_CTRL = 1 << 1
+MODIFIER_ALT = 1 << 2
+
+KEYBOARD_GLYPH_SPREADSHEET_KEY = '0Ao3KldW9piwEdExLbGR6TmZ2RU9aUjFCMmVxWkVqVmc'
+HOTKEY_SPREADSHEET_KEY = '0AqzoqbAMLyEPdE1RQXdodk1qVkFyTWtQbUxROVM1cXc'
+CC_OUTDIR = 'chrome/browser/ui/webui/chromeos'
+CC_FILENAME = 'keyboard_overlay_ui.cc'
+GRD_OUTDIR = 'chrome/app'
+GRD_FILENAME = 'chromeos_strings.grdp'
+JS_OUTDIR = 'chrome/browser/resources/chromeos'
+JS_FILENAME = 'keyboard_overlay_data.js'
+CC_START = r'IDS_KEYBOARD_OVERLAY_INSTRUCTIONS_HIDE },'
+CC_END = r'};'
+GRD_START = r' <!-- BEGIN GENERATED KEYBOARD OVERLAY STRINGS -->'
+GRD_END = r' <!-- END GENERATED KEYBOARD OVERLAY STRINGS -->'
+
+LABEL_MAP = {
+ 'glyph_arrow_down': 'down',
+ 'glyph_arrow_left': 'left',
+ 'glyph_arrow_right': 'right',
+ 'glyph_arrow_up': 'up',
+ 'glyph_back': 'back',
+ 'glyph_backspace': 'backspace',
+ 'glyph_brightness_down': 'bright down',
+ 'glyph_brightness_up': 'bright up',
+ 'glyph_enter': 'enter',
+ 'glyph_forward': 'forward',
+ 'glyph_fullscreen': 'full screen',
+ # Kana/Eisu key on Japanese keyboard
+ 'glyph_ime': u'\u304b\u306a\u0020\u002f\u0020\u82f1\u6570',
+ 'glyph_lock': 'lock',
+ 'glyph_overview': 'switch window',
+ 'glyph_power': 'power',
+ 'glyph_right': 'right',
+ 'glyph_reload': 'reload',
+ 'glyph_search': 'search',
+ 'glyph_shift': 'shift',
+ 'glyph_tab': 'tab',
+ 'glyph_tools': 'tools',
+ 'glyph_volume_down': 'vol. down',
+ 'glyph_volume_mute': 'mute',
+ 'glyph_volume_up': 'vol. up',
+};
+
+INPUT_METHOD_ID_TO_OVERLAY_ID = {
+ 'm17n:ar:kbd': 'ar',
+ 'm17n:fa:isiri': 'ar',
+ 'm17n:hi:itrans': 'hi',
+ 'm17n:th:kesmanee': 'th',
+ 'm17n:th:pattachote': 'th',
+ 'm17n:th:tis820': 'th',
+ 'm17n:vi:tcvn': 'vi',
+ 'm17n:vi:telex': 'vi',
+ 'm17n:vi:viqr': 'vi',
+ 'm17n:vi:vni': 'vi',
+ 'm17n:zh:cangjie': 'zh_TW',
+ 'm17n:zh:quick': 'zh_TW',
+ 'mozc': 'en_US',
+ 'mozc-chewing': 'zh_TW',
+ 'mozc-dv': 'en_US_dvorak',
+ 'mozc-hangul': 'ko',
+ 'mozc-jp': 'ja',
+ 'pinyin': 'zh_CN',
+ 'pinyin-dv': 'en_US_dvorak',
+ 'xkb:be::fra': 'fr',
+ 'xkb:be::ger': 'de',
+ 'xkb:be::nld': 'nl',
+ 'xkb:bg::bul': 'bg',
+ 'xkb:bg:phonetic:bul': 'bg',
+ 'xkb:br::por': 'pt_BR',
+ 'xkb:ca::fra': 'fr_CA',
+ 'xkb:ca:eng:eng': 'ca',
+ 'xkb:ch::ger': 'de',
+ 'xkb:ch:fr:fra': 'fr',
+ 'xkb:cz::cze': 'cs',
+ 'xkb:de::ger': 'de',
+ 'xkb:de:neo:ger': 'de_neo',
+ 'xkb:dk::dan': 'da',
+ 'xkb:ee::est': 'et',
+ 'xkb:es::spa': 'es',
+ 'xkb:es:cat:cat': 'ca',
+ 'xkb:fi::fin': 'fi',
+ 'xkb:fr::fra': 'fr',
+ 'xkb:gb:dvorak:eng': 'en_GB_dvorak',
+ 'xkb:gb:extd:eng': 'en_GB',
+ 'xkb:gr::gre': 'el',
+ 'xkb:hr::scr': 'hr',
+ 'xkb:hu::hun': 'hu',
+ 'xkb:il::heb': 'iw',
+ 'xkb:it::ita': 'it',
+ 'xkb:jp::jpn': 'ja',
+ 'xkb:kr:kr104:kor': 'ko',
+ 'xkb:latam::spa': 'es_419',
+ 'xkb:lt::lit': 'lt',
+ 'xkb:lv:apostrophe:lav': 'lv',
+ 'xkb:no::nob': 'no',
+ 'xkb:pl::pol': 'pl',
+ 'xkb:pt::por': 'pt_PT',
+ 'xkb:ro::rum': 'ro',
+ 'xkb:rs::srp': 'sr',
+ 'xkb:ru::rus': 'ru',
+ 'xkb:ru:phonetic:rus': 'ru',
+ 'xkb:se::swe': 'sv',
+ 'xkb:si::slv': 'sl',
+ 'xkb:sk::slo': 'sk',
+ 'xkb:tr::tur': 'tr',
+ 'xkb:ua::ukr': 'uk',
+ 'xkb:us::eng': 'en_US',
+ 'xkb:us:altgr-intl:eng': 'en_US_altgr_intl',
+ 'xkb:us:colemak:eng': 'en_US_colemak',
+ 'xkb:us:dvorak:eng': 'en_US_dvorak',
+ 'xkb:us:intl:eng': 'en_US_intl',
+ 'zinnia-japanese': 'ja',
+}
+
+# The file was first generated in 2012 and we have a policy of not updating
+# copyright dates.
+COPYRIGHT_HEADER=\
+"""// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is a generated file but may contain local modifications. See
+// src/tools/gen_keyboard_overlay_data/gen_keyboard_overlay_data.py --help
+"""
+
+# A snippet for grd file
+GRD_SNIPPET_TEMPLATE=""" <message name="%s" desc="%s">
+ %s
+ </message>
+"""
+
+# A snippet for C++ file
+CC_SNIPPET_TEMPLATE=""" { "%s", %s },
+"""
+
+
+def SplitBehavior(behavior):
+ """Splits the behavior to compose a message or i18n-content value.
+
+ Examples:
+ 'Activate last tab' => ['Activate', 'last', 'tab']
+ 'Close tab' => ['Close', 'tab']
+ """
+ return [x for x in re.split('[ ()"-.,]', behavior) if len(x) > 0]
+
+
+def ToMessageName(behavior):
+ """Composes a message name for grd file.
+
+ Examples:
+ 'Activate last tab' => IDS_KEYBOARD_OVERLAY_ACTIVATE_LAST_TAB
+ 'Close tab' => IDS_KEYBOARD_OVERLAY_CLOSE_TAB
+ """
+ segments = [segment.upper() for segment in SplitBehavior(behavior)]
+ return 'IDS_KEYBOARD_OVERLAY_' + ('_'.join(segments))
+
+
+def ToMessageDesc(description):
+ """Composes a message description for grd file."""
+ message_desc = 'The text in the keyboard overlay to explain the shortcut'
+ if description:
+ message_desc = '%s (%s).' % (message_desc, description)
+ else:
+ message_desc += '.'
+ return message_desc
+
+
+def Toi18nContent(behavior):
+ """Composes a i18n-content value for HTML/JavaScript files.
+
+ Examples:
+ 'Activate last tab' => keyboardOverlayActivateLastTab
+ 'Close tab' => keyboardOverlayCloseTab
+ """
+ segments = [segment.lower() for segment in SplitBehavior(behavior)]
+ result = 'keyboardOverlay'
+ for segment in segments:
+ result += segment[0].upper() + segment[1:]
+ return result
+
+
+def ToKeys(hotkey):
+ """Converts the action value to shortcut keys used from JavaScript.
+
+ Examples:
+ 'Ctrl - 9' => '9<>CTRL'
+ 'Ctrl - Shift - Tab' => 'tab<>CTRL<>SHIFT'
+ """
+ values = hotkey.split(' - ')
+ modifiers = sorted(value.upper() for value in values
+ if value in ['Shift', 'Ctrl', 'Alt', 'Search'])
+ keycode = [value.lower() for value in values
+ if value not in ['Shift', 'Ctrl', 'Alt', 'Search']]
+ # The keys which are highlighted even without modifier keys.
+ base_keys = ['backspace', 'power']
+ if not modifiers and (keycode and keycode[0] not in base_keys):
+ return None
+ return '<>'.join(keycode + modifiers)
+
+
+def ParseOptions():
+ """Parses the input arguemnts and returns options."""
+ # default_username = os.getusername() + '@google.com';
+ default_username = '%s@google.com' % os.environ.get('USER')
+ parser = optparse.OptionParser()
+ parser.add_option('--key', dest='key',
+ help='The key of the spreadsheet (required).')
+ parser.add_option('--username', dest='username',
+ default=default_username,
+ help='Your user name (default: %s).' % default_username)
+ parser.add_option('--password', dest='password',
+ help='Your password.')
+ parser.add_option('--account_type', default='GOOGLE', dest='account_type',
+ help='Account type used for gdata login (default: GOOGLE)')
+ parser.add_option('--js', dest='js', default=False, action='store_true',
+ help='Output js file.')
+ parser.add_option('--grd', dest='grd', default=False, action='store_true',
+ help='Output resource file.')
+ parser.add_option('--cc', dest='cc', default=False, action='store_true',
+ help='Output cc file.')
+ parser.add_option('--outdir', dest='outdir', default=None,
+ help='Specify the directory files are generated.')
+ (options, unused_args) = parser.parse_args()
+
+ if not options.username.endswith('google.com'):
+ print 'google.com account is necessary to use this script.'
+ sys.exit(-1)
+
+ if (not (options.js or options.grd or options.cc)):
+ print 'Either --js, --grd, or --cc needs to be specified.'
+ sys.exit(-1)
+
+ # Get the password from the terminal, if needed.
+ if not options.password:
+ options.password = getpass.getpass(
+ 'Application specific password for %s: ' % options.username)
+ return options
+
+
+def InitClient(options):
+ """Initializes the spreadsheet client."""
+ client = gdata.spreadsheet.service.SpreadsheetsService()
+ client.email = options.username
+ client.password = options.password
+ client.source = 'Spread Sheet'
+ client.account_type = options.account_type
+ print 'Logging in as %s (%s)' % (client.email, client.account_type)
+ client.ProgrammaticLogin()
+ return client
+
+
+def PrintDiffs(message, lhs, rhs):
+ """Prints the differences between |lhs| and |rhs|."""
+ dif = set(lhs).difference(rhs)
+ if dif:
+ print message, ', '.join(dif)
+
+
+def FetchSpreadsheetFeeds(client, key, sheets, cols):
+ """Fetch feeds from the spreadsheet.
+
+ Args:
+ client: A spreadsheet client to be used for fetching data.
+ key: A key string of the spreadsheet to be fetched.
+ sheets: A list of the sheet names to read data from.
+ cols: A list of columns to read data from.
+ """
+ worksheets_feed = client.GetWorksheetsFeed(key)
+ print 'Fetching data from the worksheet: %s' % worksheets_feed.title.text
+ worksheets_data = {}
+ titles = []
+ for entry in worksheets_feed.entry:
+ worksheet_id = entry.id.text.split('/')[-1]
+ list_feed = client.GetListFeed(key, worksheet_id)
+ list_data = []
+ # Hack to deal with sheet names like 'sv (Copy of fl)'
+ title = list_feed.title.text.split('(')[0].strip()
+ titles.append(title)
+ if title not in sheets:
+ continue
+ print 'Reading data from the sheet: %s' % list_feed.title.text
+ for i, entry in enumerate(list_feed.entry):
+ line_data = {}
+ for k in entry.custom:
+ if (k not in cols) or (not entry.custom[k].text):
+ continue
+ line_data[k] = entry.custom[k].text
+ list_data.append(line_data)
+ worksheets_data[title] = list_data
+ PrintDiffs('Exist only on the spreadsheet: ', titles, sheets)
+ PrintDiffs('Specified but do not exist on the spreadsheet: ', sheets, titles)
+ return worksheets_data
+
+
+def FetchKeyboardGlyphData(client):
+ """Fetches the keyboard glyph data from the spreadsheet."""
+ glyph_cols = ['scancode', 'p0', 'p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7',
+ 'p8', 'p9', 'label', 'format', 'notes']
+ keyboard_glyph_data = FetchSpreadsheetFeeds(
+ client, KEYBOARD_GLYPH_SPREADSHEET_KEY,
+ INPUT_METHOD_ID_TO_OVERLAY_ID.values(), glyph_cols)
+ ret = {}
+ for lang in keyboard_glyph_data:
+ ret[lang] = {}
+ keys = {}
+ for line in keyboard_glyph_data[lang]:
+ scancode = line.get('scancode')
+ if (not scancode) and line.get('notes'):
+ ret[lang]['layoutName'] = line['notes']
+ continue
+ del line['scancode']
+ if 'notes' in line:
+ del line['notes']
+ if 'label' in line:
+ line['label'] = LABEL_MAP.get(line['label'], line['label'])
+ keys[scancode] = line
+ # Add a label to space key
+ if '39' not in keys:
+ keys['39'] = {'label': 'space'}
+ ret[lang]['keys'] = keys
+ return ret
+
+
+def FetchLayoutsData(client):
+ """Fetches the keyboard glyph data from the spreadsheet."""
+ layout_names = ['U_layout', 'J_layout', 'E_layout', 'B_layout']
+ cols = ['scancode', 'x', 'y', 'w', 'h']
+ layouts = FetchSpreadsheetFeeds(client, KEYBOARD_GLYPH_SPREADSHEET_KEY,
+ layout_names, cols)
+ ret = {}
+ for layout_name, layout in layouts.items():
+ ret[layout_name[0]] = []
+ for row in layout:
+ line = []
+ for col in cols:
+ value = row.get(col)
+ if not value:
+ line.append('')
+ else:
+ if col != 'scancode':
+ value = float(value)
+ line.append(value)
+ ret[layout_name[0]].append(line)
+ return ret
+
+
+def FetchHotkeyData(client):
+ """Fetches the hotkey data from the spreadsheet."""
+ hotkey_sheet = ['Cross Platform Behaviors']
+ hotkey_cols = ['behavior', 'context', 'kind', 'actionctrlctrlcmdonmac',
+ 'chromeos', 'descriptionfortranslation']
+ hotkey_data = FetchSpreadsheetFeeds(client, HOTKEY_SPREADSHEET_KEY,
+ hotkey_sheet, hotkey_cols)
+ action_to_id = {}
+ id_to_behavior = {}
+ # (behavior, action)
+ result = []
+ for line in hotkey_data['Cross Platform Behaviors']:
+ if (not line.get('chromeos')) or (line.get('kind') != 'Key'):
+ continue
+ action = ToKeys(line['actionctrlctrlcmdonmac'])
+ if not action:
+ continue
+ behavior = line['behavior'].strip()
+ description = line.get('descriptionfortranslation')
+ result.append((behavior, action, description))
+ return result
+
+
+def UniqueBehaviors(hotkey_data):
+ """Retrieves a sorted list of unique behaviors from |hotkey_data|."""
+ return sorted(set((behavior, description) for (behavior, _, description)
+ in hotkey_data),
+ cmp=lambda x, y: cmp(ToMessageName(x[0]), ToMessageName(y[0])))
+
+
+def GetPath(path_from_src):
+ """Returns the absolute path of the specified path."""
+ path = os.path.join(os.path.dirname(__file__), '../..', path_from_src)
+ if not os.path.isfile(path):
+ print 'WARNING: %s does not exist. Maybe moved or renamed?' % path
+ return path
+
+
+def OutputFile(outpath, snippet):
+ """Output the snippet into the specified path."""
+ out = file(outpath, 'w')
+ out.write(COPYRIGHT_HEADER + '\n')
+ out.write(snippet)
+ print 'Output ' + os.path.normpath(outpath)
+
+
+def RewriteFile(start, end, original_dir, original_filename, snippet,
+ outdir=None):
+ """Replaces a part of the specified file with snippet and outputs it."""
+ original_path = GetPath(os.path.join(original_dir, original_filename))
+ original = file(original_path, 'r')
+ original_content = original.read()
+ original.close()
+ if outdir:
+ outpath = os.path.join(outdir, original_filename)
+ else:
+ outpath = original_path
+ out = file(outpath, 'w')
+ rx = re.compile(r'%s\n.*?%s\n' % (re.escape(start), re.escape(end)),
+ re.DOTALL)
+ new_content = re.sub(rx, '%s\n%s%s\n' % (start, snippet, end),
+ original_content)
+ out.write(new_content)
+ out.close()
+ print 'Output ' + os.path.normpath(outpath)
+
+
+def OutputJson(keyboard_glyph_data, hotkey_data, layouts, var_name, outdir):
+ """Outputs the keyboard overlay data as a JSON file."""
+ action_to_id = {}
+ for (behavior, action, _) in hotkey_data:
+ i18nContent = Toi18nContent(behavior)
+ action_to_id[action] = i18nContent
+ data = {'keyboardGlyph': keyboard_glyph_data,
+ 'shortcut': action_to_id,
+ 'layouts': layouts,
+ 'inputMethodIdToOverlayId': INPUT_METHOD_ID_TO_OVERLAY_ID}
+
+ if not outdir:
+ outdir = JS_OUTDIR
+ outpath = GetPath(os.path.join(outdir, JS_FILENAME))
+ json_data = json.dumps(data, sort_keys=True, indent=2)
+ # Remove redundant spaces after ','
+ json_data = json_data.replace(', \n', ',\n')
+ # Replace double quotes with single quotes to avoid lint warnings.
+ json_data = json_data.replace('\"', '\'')
+ snippet = 'var %s = %s;\n' % (var_name, json_data)
+ OutputFile(outpath, snippet)
+
+
+def OutputGrd(hotkey_data, outdir):
+ """Outputs a part of messages in the grd file."""
+ snippet = cStringIO.StringIO()
+ for (behavior, description) in UniqueBehaviors(hotkey_data):
+ # Do not generate message for 'Show wrench menu'. It is handled manually
+ # based on branding.
+ if behavior == 'Show wrench menu':
+ continue
+ snippet.write(GRD_SNIPPET_TEMPLATE %
+ (ToMessageName(behavior), ToMessageDesc(description),
+ behavior))
+
+ RewriteFile(GRD_START, GRD_END, GRD_OUTDIR, GRD_FILENAME, snippet.getvalue(),
+ outdir)
+
+
+def OutputCC(hotkey_data, outdir):
+ """Outputs a part of code in the C++ file."""
+ snippet = cStringIO.StringIO()
+ for (behavior, _) in UniqueBehaviors(hotkey_data):
+ message_name = ToMessageName(behavior)
+ output = CC_SNIPPET_TEMPLATE % (Toi18nContent(behavior), message_name)
+ # Break the line if the line is longer than 80 characters
+ if len(output) > 80:
+ output = output.replace(' ' + message_name, '\n %s' % message_name)
+ snippet.write(output)
+
+ RewriteFile(CC_START, CC_END, CC_OUTDIR, CC_FILENAME, snippet.getvalue(),
+ outdir)
+
+
+def main():
+ options = ParseOptions()
+ client = InitClient(options)
+ hotkey_data = FetchHotkeyData(client)
+
+ if options.js:
+ keyboard_glyph_data = FetchKeyboardGlyphData(client)
+
+ if options.js:
+ layouts = FetchLayoutsData(client)
+ OutputJson(keyboard_glyph_data, hotkey_data, layouts, 'keyboardOverlayData',
+ options.outdir)
+ if options.grd:
+ OutputGrd(hotkey_data, options.outdir)
+ if options.cc:
+ OutputCC(hotkey_data, options.outdir)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/generate_library_loader/generate_library_loader.py b/chromium/tools/generate_library_loader/generate_library_loader.py
new file mode 100755
index 00000000000..866e005547d
--- /dev/null
+++ b/chromium/tools/generate_library_loader/generate_library_loader.py
@@ -0,0 +1,256 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Creates a library loader (a header and implementation file),
+which is a wrapper for dlopen or direct linking with given library.
+
+The loader makes it possible to have the same client code for both cases,
+and also makes it easier to write code using dlopen (and also provides
+a standard way to do so, and limits the ugliness just to generated files).
+
+For more info refer to http://crbug.com/162733 .
+"""
+
+
+import optparse
+import os.path
+import re
+import sys
+
+
+HEADER_TEMPLATE = """// This is generated file. Do not modify directly.
+// Path to the code generator: %(generator_path)s .
+
+#ifndef %(unique_prefix)s
+#define %(unique_prefix)s
+
+%(wrapped_header_include)s
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#if defined(%(unique_prefix)s_DLOPEN)
+#include "base/native_library.h"
+#endif
+
+class %(class_name)s {
+ public:
+ %(class_name)s();
+ ~%(class_name)s();
+
+ bool Load(const std::string& library_name) WARN_UNUSED_RESULT;
+
+ bool loaded() const { return loaded_; }
+
+%(member_decls)s
+
+ private:
+ void CleanUp(bool unload);
+
+#if defined(%(unique_prefix)s_DLOPEN)
+ base::NativeLibrary library_;
+#endif
+
+ bool loaded_;
+
+ DISALLOW_COPY_AND_ASSIGN(%(class_name)s);
+};
+
+#endif // %(unique_prefix)s
+"""
+
+
+HEADER_MEMBER_TEMPLATE = """ typeof(&::%(function_name)s) %(function_name)s;
+"""
+
+
+IMPL_TEMPLATE = """// This is generated file. Do not modify directly.
+// Path to the code generator: %(generator_path)s .
+
+#include "%(generated_header_name)s"
+
+// Put these sanity checks here so that they fire at most once
+// (to avoid cluttering the build output).
+#if !defined(%(unique_prefix)s_DLOPEN) && !defined(%(unique_prefix)s_DT_NEEDED)
+#error neither %(unique_prefix)s_DLOPEN nor %(unique_prefix)s_DT_NEEDED defined
+#endif
+#if defined(%(unique_prefix)s_DLOPEN) && defined(%(unique_prefix)s_DT_NEEDED)
+#error both %(unique_prefix)s_DLOPEN and %(unique_prefix)s_DT_NEEDED defined
+#endif
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+
+%(class_name)s::%(class_name)s() : loaded_(false) {
+}
+
+%(class_name)s::~%(class_name)s() {
+ CleanUp(loaded_);
+}
+
+bool %(class_name)s::Load(const std::string& library_name) {
+ if (loaded_) {
+ NOTREACHED();
+ return false;
+ }
+
+#if defined(%(unique_prefix)s_DLOPEN)
+ library_ = base::LoadNativeLibrary(base::FilePath(library_name), NULL);
+ if (!library_)
+ return false;
+#endif
+
+%(member_init)s
+
+ loaded_ = true;
+ return true;
+}
+
+void %(class_name)s::CleanUp(bool unload) {
+#if defined(%(unique_prefix)s_DLOPEN)
+ if (unload) {
+ base::UnloadNativeLibrary(library_);
+ library_ = NULL;
+ }
+#endif
+ loaded_ = false;
+%(member_cleanup)s
+}
+"""
+
+IMPL_MEMBER_INIT_TEMPLATE = """
+#if defined(%(unique_prefix)s_DLOPEN)
+ %(function_name)s =
+ reinterpret_cast<typeof(this->%(function_name)s)>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library_, "%(function_name)s"));
+#endif
+#if defined(%(unique_prefix)s_DT_NEEDED)
+ %(function_name)s = &::%(function_name)s;
+#endif
+ if (!%(function_name)s) {
+ CleanUp(true);
+ return false;
+ }
+"""
+
+IMPL_MEMBER_CLEANUP_TEMPLATE = """ %(function_name)s = NULL;
+"""
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option('--name')
+ parser.add_option('--output-cc')
+ parser.add_option('--output-h')
+ parser.add_option('--header')
+
+ parser.add_option('--bundled-header')
+ parser.add_option('--use-extern-c', action='store_true', default=False)
+ parser.add_option('--link-directly', type=int, default=0)
+
+ options, args = parser.parse_args()
+
+ if not options.name:
+ parser.error('Missing --name parameter')
+ if not options.output_cc:
+ parser.error('Missing --output-cc parameter')
+ if not options.output_h:
+ parser.error('Missing --output-h parameter')
+ if not options.header:
+ parser.error('Missing --header paramater')
+ if not args:
+ parser.error('No function names specified')
+
+ # Make sure we are always dealing with paths relative to source tree root
+ # to avoid issues caused by different relative path roots.
+ source_tree_root = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..', '..'))
+ options.output_cc = os.path.relpath(options.output_cc, source_tree_root)
+ options.output_h = os.path.relpath(options.output_h, source_tree_root)
+
+ # Create a unique prefix, e.g. for header guards.
+ # Stick a known string at the beginning to ensure this doesn't begin
+ # with an underscore, which is reserved for the C++ implementation.
+ unique_prefix = ('LIBRARY_LOADER_' +
+ re.sub(r'[\W]', '_', options.output_h).upper())
+
+ member_decls = []
+ member_init = []
+ member_cleanup = []
+ for fn in args:
+ member_decls.append(HEADER_MEMBER_TEMPLATE % {
+ 'function_name': fn,
+ 'unique_prefix': unique_prefix
+ })
+ member_init.append(IMPL_MEMBER_INIT_TEMPLATE % {
+ 'function_name': fn,
+ 'unique_prefix': unique_prefix
+ })
+ member_cleanup.append(IMPL_MEMBER_CLEANUP_TEMPLATE % {
+ 'function_name': fn,
+ 'unique_prefix': unique_prefix
+ })
+
+ header = options.header
+ if options.link_directly == 0 and options.bundled_header:
+ header = options.bundled_header
+ wrapped_header_include = '#include %s\n' % header
+
+ # Some libraries (e.g. libpci) have headers that cannot be included
+ # without extern "C", otherwise they cause the link to fail.
+ # TODO(phajdan.jr): This is a workaround for broken headers. Remove it.
+ if options.use_extern_c:
+ wrapped_header_include = 'extern "C" {\n%s\n}\n' % wrapped_header_include
+
+ # It seems cleaner just to have a single #define here and #ifdefs in bunch
+ # of places, rather than having a different set of templates, duplicating
+ # or complicating more code.
+ if options.link_directly == 0:
+ wrapped_header_include += '#define %s_DLOPEN\n' % unique_prefix
+ elif options.link_directly == 1:
+ wrapped_header_include += '#define %s_DT_NEEDED\n' % unique_prefix
+ else:
+ parser.error('Invalid value for --link-directly. Should be 0 or 1.')
+
+ # Make it easier for people to find the code generator just in case.
+ # Doing it this way is more maintainable, because it's going to work
+ # even if file gets moved without updating the contents.
+ generator_path = os.path.relpath(__file__, source_tree_root)
+
+ header_contents = HEADER_TEMPLATE % {
+ 'generator_path': generator_path,
+ 'unique_prefix': unique_prefix,
+ 'wrapped_header_include': wrapped_header_include,
+ 'class_name': options.name,
+ 'member_decls': ''.join(member_decls),
+ }
+
+ impl_contents = IMPL_TEMPLATE % {
+ 'generator_path': generator_path,
+ 'unique_prefix': unique_prefix,
+ 'generated_header_name': options.output_h,
+ 'class_name': options.name,
+ 'member_init': ''.join(member_init),
+ 'member_cleanup': ''.join(member_cleanup),
+ }
+
+ header_file = open(os.path.join(source_tree_root, options.output_h), 'w')
+ try:
+ header_file.write(header_contents)
+ finally:
+ header_file.close()
+
+ impl_file = open(os.path.join(source_tree_root, options.output_cc), 'w')
+ try:
+ impl_file.write(impl_contents)
+ finally:
+ impl_file.close()
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/generate_shim_headers/generate_shim_headers.py b/chromium/tools/generate_shim_headers/generate_shim_headers.py
new file mode 100755
index 00000000000..81c531b2e6a
--- /dev/null
+++ b/chromium/tools/generate_shim_headers/generate_shim_headers.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Generates shim headers that mirror the directory structure of bundled headers,
+but just forward to the system ones.
+
+This allows seamless compilation against system headers with no changes
+to our source code.
+"""
+
+
+import optparse
+import os.path
+import sys
+
+
+SHIM_TEMPLATE = """
+#if defined(OFFICIAL_BUILD)
+#error shim headers must not be used in official builds!
+#endif
+"""
+
+
+def GeneratorMain(argv):
+ parser = optparse.OptionParser()
+ parser.add_option('--headers-root', action='append')
+ parser.add_option('--define', action='append')
+ parser.add_option('--output-directory')
+ parser.add_option('--prefix', default='')
+ parser.add_option('--use-include-next', action='store_true')
+ parser.add_option('--outputs', action='store_true')
+ parser.add_option('--generate', action='store_true')
+
+ options, args = parser.parse_args(argv)
+
+ if not options.headers_root:
+ parser.error('Missing --headers-root parameter.')
+ if not options.output_directory:
+ parser.error('Missing --output-directory parameter.')
+ if not args:
+ parser.error('Missing arguments - header file names.')
+
+ source_tree_root = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..', '..'))
+
+ for root in options.headers_root:
+ target_directory = os.path.join(
+ options.output_directory,
+ os.path.relpath(root, source_tree_root))
+ if options.generate and not os.path.exists(target_directory):
+ os.makedirs(target_directory)
+
+ for header_spec in args:
+ if ';' in header_spec:
+ (header_filename,
+ include_before,
+ include_after) = header_spec.split(';', 2)
+ else:
+ header_filename = header_spec
+ include_before = ''
+ include_after = ''
+ if options.outputs:
+ yield os.path.join(target_directory, header_filename)
+ if options.generate:
+ with open(os.path.join(target_directory, header_filename), 'w') as f:
+ f.write(SHIM_TEMPLATE)
+
+ if options.define:
+ for define in options.define:
+ key, value = define.split('=', 1)
+ # This non-standard push_macro extension is supported
+ # by compilers we support (GCC, clang).
+ f.write('#pragma push_macro("%s")\n' % key)
+ f.write('#undef %s\n' % key)
+ f.write('#define %s %s\n' % (key, value))
+
+ if include_before:
+ for header in include_before.split(':'):
+ f.write('#include %s\n' % header)
+
+ include_target = options.prefix + header_filename
+ if options.use_include_next:
+ f.write('#include_next <%s>\n' % include_target)
+ else:
+ f.write('#include <%s>\n' % include_target)
+
+ if include_after:
+ for header in include_after.split(':'):
+ f.write('#include %s\n' % header)
+
+ if options.define:
+ for define in options.define:
+ key, value = define.split('=', 1)
+ # This non-standard pop_macro extension is supported
+ # by compilers we support (GCC, clang).
+ f.write('#pragma pop_macro("%s")\n' % key)
+
+
+def DoMain(argv):
+ return '\n'.join(GeneratorMain(argv))
+
+
+if __name__ == '__main__':
+ DoMain(sys.argv[1:])
diff --git a/chromium/tools/generate_stubs/generate_stubs.py b/chromium/tools/generate_stubs/generate_stubs.py
new file mode 100755
index 00000000000..27f8d5a05d3
--- /dev/null
+++ b/chromium/tools/generate_stubs/generate_stubs.py
@@ -0,0 +1,1131 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Creates windows and posix stub files for a given set of signatures.
+
+For libraries that need to be loaded outside of the standard executable startup
+path mechanism, stub files need to be generated for the wanted functions. In
+windows, this is done via "def" files and the delay load mechanism. On a posix
+system, a set of stub functions need to be generated that dispatch to functions
+found via dlsym.
+
+This script takes a set of files, where each file is a list of C-style
+signatures (one signature per line). The output is either a windows def file,
+or a header + implementation file of stubs suitable for use in a posix system.
+
+This script also handles varidiac functions, e.g.
+void printf(const char* s, ...);
+
+TODO(hclam): Fix the situation for varidiac functions.
+Stub for the above function will be generated and inside the stub function it
+is translated to:
+void printf(const char* s, ...) {
+ printf_ptr(s, (void*)arg1);
+}
+
+Only one argument from the varidiac arguments is used and it will be used as
+type void*.
+"""
+
+__author__ = 'ajwong@chromium.org (Albert J. Wong)'
+
+import optparse
+import os
+import re
+import string
+import subprocess
+import sys
+
+
+class Error(Exception):
+ pass
+
+
+class BadSignatureError(Error):
+ pass
+
+
+class SubprocessError(Error):
+ def __init__(self, message, error_code):
+ Error.__init__(self)
+ self.message = message
+ self.error_code = error_code
+
+ def __str__(self):
+ return 'Failed with code %s: %s' % (self.message, repr(self.error_code))
+
+
+# Regular expression used to parse function signatures in the input files.
+# The regex is built around identifying the "identifier" for the function name.
+# We consider the identifier to be the string that follows these constraints:
+#
+# 1) Starts with [_a-ZA-Z] (C++ spec 2.10).
+# 2) Continues with [_a-ZA-Z0-9] (C++ spec 2.10).
+# 3) Preceeds an opening parenthesis by 0 or more whitespace chars.
+#
+# From that, all preceeding characters are considered the return value.
+# Trailing characters should have a substring matching the form (.*). That
+# is considered the arguments.
+SIGNATURE_REGEX = re.compile('(?P<return_type>.+?)'
+ '(?P<name>[_a-zA-Z][_a-zA-Z0-9]+)\s*'
+ '\((?P<params>.*?)\)')
+
+# Used for generating C++ identifiers.
+INVALID_C_IDENT_CHARS = re.compile('[^_a-zA-Z0-9]')
+
+# Constants defning the supported file types options.
+FILE_TYPE_WIN_X86 = 'windows_lib'
+FILE_TYPE_WIN_X64 = 'windows_lib_x64'
+FILE_TYPE_POSIX_STUB = 'posix_stubs'
+FILE_TYPE_WIN_DEF = 'windows_def'
+
+# Template for generating a stub function definition. Includes a forward
+# declaration marking the symbol as weak. This template takes the following
+# named parameters.
+# return_type: The return type.
+# name: The name of the function.
+# params: The parameters to the function.
+# return_prefix: 'return ' if this function is not void. '' otherwise.
+# arg_list: The arguments used to call the stub function.
+STUB_FUNCTION_DEFINITION = (
+ """extern %(return_type)s %(name)s(%(params)s) __attribute__((weak));
+%(return_type)s %(name)s(%(params)s) {
+ %(return_prefix)s%(name)s_ptr(%(arg_list)s);
+}""")
+
+# Template for generating a variadic stub function definition with return
+# value.
+# Includes a forward declaration marking the symbol as weak.
+# This template takes the following named parameters.
+# return_type: The return type.
+# name: The name of the function.
+# params: The parameters to the function.
+# arg_list: The arguments used to call the stub function without the
+# variadic argument.
+# last_named_arg: Name of the last named argument before the variadic
+# argument.
+VARIADIC_STUB_FUNCTION_DEFINITION = (
+ """extern %(return_type)s %(name)s(%(params)s) __attribute__((weak));
+%(return_type)s %(name)s(%(params)s) {
+ va_list args___;
+ va_start(args___, %(last_named_arg)s);
+ %(return_type)s ret___ = %(name)s_ptr(%(arg_list)s, va_arg(args___, void*));
+ va_end(args___);
+ return ret___;
+}""")
+
+# Template for generating a variadic stub function definition without
+# return value.
+# Includes a forward declaration marking the symbol as weak.
+# This template takes the following named parameters.
+# name: The name of the function.
+# params: The parameters to the function.
+# arg_list: The arguments used to call the stub function without the
+# variadic argument.
+# last_named_arg: Name of the last named argument before the variadic
+# argument.
+VOID_VARIADIC_STUB_FUNCTION_DEFINITION = (
+ """extern void %(name)s(%(params)s) __attribute__((weak));
+void %(name)s(%(params)s) {
+ va_list args___;
+ va_start(args___, %(last_named_arg)s);
+ %(name)s_ptr(%(arg_list)s, va_arg(args___, void*));
+ va_end(args___);
+}""")
+
+# Template for the preamble for the stub header file with the header guards,
+# standard set of includes, and namespace opener. This template takes the
+# following named parameters:
+# guard_name: The macro to use as the header guard.
+# namespace: The namespace for the stub functions.
+STUB_HEADER_PREAMBLE = """// This is generated file. Do not modify directly.
+
+#ifndef %(guard_name)s
+#define %(guard_name)s
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+
+namespace %(namespace)s {
+"""
+
+# Template for the end of the stub header. This closes the namespace and the
+# header guards. This template takes the following named parameters:
+# guard_name: The macro to use as the header guard.
+# namespace: The namespace for the stub functions.
+STUB_HEADER_CLOSER = """} // namespace %(namespace)s
+
+#endif // %(guard_name)s
+"""
+
+# The standard includes needed for the stub implementation file. Takes one
+# string substition with the path to the associated stub header file.
+IMPLEMENTATION_PREAMBLE = """// This is generated file. Do not modify directly.
+
+#include "%s"
+
+#include <stdlib.h> // For NULL.
+#include <dlfcn.h> // For dysym, dlopen.
+
+#include <map>
+#include <vector>
+"""
+
+# The start and end templates for the enum definitions used by the Umbrella
+# initializer.
+UMBRELLA_ENUM_START = """// Enum and typedef for umbrella initializer.
+enum StubModules {
+"""
+UMBRELLA_ENUM_END = """ kNumStubModules
+};
+
+"""
+
+# Start and end of the extern "C" section for the implementation contents.
+IMPLEMENTATION_CONTENTS_C_START = """extern "C" {
+
+"""
+IMPLEMENTATION_CONTENTS_C_END = """
+} // extern "C"
+
+
+"""
+
+# Templates for the start and end of a namespace. Takes one parameter, the
+# namespace name.
+NAMESPACE_START = """namespace %s {
+
+"""
+NAMESPACE_END = """} // namespace %s
+
+"""
+
+# Comment to include before the section declaring all the function pointers
+# used by the stub functions.
+FUNCTION_POINTER_SECTION_COMMENT = (
+ """// Static pointers that will hold the location of the real function
+// implementations after the module has been loaded.
+""")
+
+# Template for the module initialization check function. This template
+# takes two parameteres: the function name, and the conditional used to
+# verify the module's initialization.
+MODULE_INITIALIZATION_CHECK_FUNCTION = (
+ """// Returns true if all stubs have been properly initialized.
+bool %s() {
+ if (%s) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+""")
+
+# Template for the line that initialize the stub pointer. This template takes
+# the following named parameters:
+# name: The name of the function.
+# return_type: The return type.
+# params: The parameters to the function.
+STUB_POINTER_INITIALIZER = """ %(name)s_ptr =
+ reinterpret_cast<%(return_type)s (*)(%(parameters)s)>(
+ dlsym(module, "%(name)s"));
+ VLOG_IF(1, !%(name)s_ptr) << "Couldn't load %(name)s, dlerror() says:\\n"
+ << dlerror();
+"""
+
+# Template for module initializer function start and end. This template takes
+# one parameter which is the initializer function name.
+MODULE_INITIALIZE_START = """// Initializes the module stubs.
+void %s(void* module) {
+"""
+MODULE_INITIALIZE_END = """}
+
+"""
+
+# Template for module uninitializer function start and end. This template
+# takes one parameter which is the initializer function name.
+MODULE_UNINITIALIZE_START = (
+ """// Uninitialize the module stubs. Reset pointers to NULL.
+void %s() {
+""")
+MODULE_UNINITIALIZE_END = """}
+
+"""
+
+
+# Open namespace and add typedef for internal data structures used by the
+# umbrella initializer.
+UMBRELLA_INITIALIZER_START = """namespace %s {
+typedef std::map<StubModules, void*> StubHandleMap;
+"""
+
+# Function close DSOs on error and clean up dangling references.
+UMBRELLA_INITIALIZER_CLEANUP_FUNCTION = (
+ """static void CloseLibraries(StubHandleMap* stub_handles) {
+ for (StubHandleMap::const_iterator it = stub_handles->begin();
+ it != stub_handles->end();
+ ++it) {
+ dlclose(it->second);
+ }
+
+ stub_handles->clear();
+}
+""")
+
+# Function to initialize each DSO for the given paths.
+UMBRELLA_INITIALIZER_INITIALIZE_FUNCTION_START = (
+ """bool InitializeStubs(const StubPathMap& path_map) {
+ StubHandleMap opened_libraries;
+ for (int i = 0; i < kNumStubModules; ++i) {
+ StubModules cur_module = static_cast<StubModules>(i);
+ // If a module is missing, we fail.
+ StubPathMap::const_iterator it = path_map.find(cur_module);
+ if (it == path_map.end()) {
+ CloseLibraries(&opened_libraries);
+ return false;
+ }
+
+ // Otherwise, attempt to dlopen the library.
+ const std::vector<std::string>& paths = it->second;
+ bool module_opened = false;
+ for (std::vector<std::string>::const_iterator dso_path = paths.begin();
+ !module_opened && dso_path != paths.end();
+ ++dso_path) {
+ void* handle = dlopen(dso_path->c_str(), RTLD_LAZY);
+ if (handle != NULL) {
+ module_opened = true;
+ opened_libraries[cur_module] = handle;
+ } else {
+ VLOG(1) << "dlopen(" << dso_path->c_str() << ") failed, "
+ << "dlerror() says:\\n" << dlerror();
+ }
+ }
+
+ if (!module_opened) {
+ CloseLibraries(&opened_libraries);
+ return false;
+ }
+ }
+""")
+
+# Template to generate code to check if each module initializer correctly
+# completed, and cleanup on failures. This template takes the following
+# named parameters.
+# conditional: The conditional expression for successful initialization.
+# uninitializers: The statements needed to uninitialize the modules.
+UMBRELLA_INITIALIZER_CHECK_AND_CLEANUP = (
+ """ // Check that each module is initialized correctly.
+ // Close all previously opened libraries on failure.
+ if (%(conditional)s) {
+ %(uninitializers)s;
+ CloseLibraries(&opened_libraries);
+ return false;
+ }
+
+ return true;
+}
+""")
+
+# Template for Initialize, Unininitialize, and IsInitialized functions for each
+# module. This template takes the following named parameters:
+# initialize: Name of the Initialize function.
+# uninitialize: Name of the Uninitialize function.
+# is_initialized: Name of the IsInitialized function.
+MODULE_FUNCTION_PROTOTYPES = """bool %(is_initialized)s();
+void %(initialize)s(void* module);
+void %(uninitialize)s();
+
+"""
+
+# Template for umbrella initializer declaration and associated datatypes.
+UMBRELLA_INITIALIZER_PROTOTYPE = (
+ """typedef std::map<StubModules, std::vector<std::string> > StubPathMap;
+
+// Umbrella initializer for all the modules in this stub file.
+bool InitializeStubs(const StubPathMap& path_map);
+""")
+
+
+def ExtractModuleName(infile_path):
+ """Infers the module name from the input file path.
+
+ The input filename is supposed to be in the form "ModuleName.sigs".
+ This function splits the filename from the extention on that basename of
+ the path and returns that as the module name.
+
+ Args:
+ infile_path: String holding the path to the input file.
+
+ Returns:
+ The module name as a string.
+ """
+ basename = os.path.basename(infile_path)
+
+ # This loop continously removes suffixes of the filename separated by a "."
+ # character.
+ while 1:
+ new_basename = os.path.splitext(basename)[0]
+ if basename == new_basename:
+ break
+ else:
+ basename = new_basename
+ return basename
+
+
+def ParseSignatures(infile):
+ """Parses function signatures in the input file.
+
+ This function parses a file of signatures into a list of dictionaries that
+ represent the function signatures in the input file. Each dictionary has
+ the following keys:
+ return_type: A string with the return type.
+ name: A string with the name of the function.
+ params: A list of each function parameter declaration (type + name)
+
+ The format of the input file is one C-style function signature per line, no
+ trailing semicolon. Empty lines are allowed. An empty line is a line that
+ consists purely of whitespace. Lines that begin with a # are considered
+ comment lines and are ignored.
+
+ We assume that "int foo(void)" is the same as "int foo()", which is not
+ true in C where "int foo()" is equivalent to "int foo(...)". Our generated
+ code is C++, and we do not handle varargs, so this is a case that can be
+ ignored for now.
+
+ Args:
+ infile: File object holding a text file of function signatures.
+
+ Returns:
+ A list of dictionaries, where each dictionary represents one function
+ signature.
+
+ Raises:
+ BadSignatureError: A line could not be parsed as a signature.
+ """
+ signatures = []
+ for line in infile:
+ line = line.strip()
+ if line and line[0] != '#':
+ m = SIGNATURE_REGEX.match(line)
+ if m is None:
+ raise BadSignatureError('Unparsable line: %s' % line)
+ signatures.append(
+ {'return_type': m.group('return_type').strip(),
+ 'name': m.group('name').strip(),
+ 'params': [arg.strip() for arg in m.group('params').split(',')]})
+ return signatures
+
+
+def WriteWindowsDefFile(module_name, signatures, outfile):
+ """Writes a windows def file to the given output file object.
+
+ The def file format is basically a list of function names. Generation is
+ simple. After outputting the LIBRARY and EXPORTS lines, print out each
+ function name, one to a line, preceeded by 2 spaces.
+
+ Args:
+ module_name: The name of the module we are writing a stub for.
+ signatures: The list of signature hashes, as produced by ParseSignatures,
+ to create stubs for.
+ outfile: File handle to populate with definitions.
+ """
+ outfile.write('LIBRARY %s\n' % module_name)
+ outfile.write('EXPORTS\n')
+
+ for sig in signatures:
+ outfile.write(' %s\n' % sig['name'])
+
+
+def QuietRun(args, filter=None, write_to=sys.stdout):
+ """Invoke |args| as command via subprocess.Popen, filtering lines starting
+ with |filter|."""
+ popen = subprocess.Popen(args, stdout=subprocess.PIPE)
+ out, _ = popen.communicate()
+ for line in out.splitlines():
+ if not filter or not line.startswith(filter):
+ write_to.write(line + '\n')
+ return popen.returncode
+
+
+def CreateWindowsLib(module_name, signatures, intermediate_dir, outdir_path,
+ machine):
+ """Creates a windows library file.
+
+ Calling this function will create a lib file in the outdir_path that exports
+ the signatures passed into the object. A temporary def file will be created
+ in the intermediate_dir.
+
+ Args:
+ module_name: The name of the module we are writing a stub for.
+ signatures: The list of signature hashes, as produced by ParseSignatures,
+ to create stubs for.
+ intermediate_dir: The directory where the generated .def files should go.
+ outdir_path: The directory where generated .lib files should go.
+ machine: String holding the machine type, 'X86' or 'X64'.
+
+ Raises:
+ SubprocessError: If invoking the windows "lib" tool fails, this is raised
+ with the error code.
+ """
+ def_file_path = os.path.join(intermediate_dir,
+ module_name + '.def')
+ lib_file_path = os.path.join(outdir_path,
+ module_name + '.lib')
+ outfile = open(def_file_path, 'w')
+ try:
+ WriteWindowsDefFile(module_name, signatures, outfile)
+ finally:
+ outfile.close()
+
+ # Invoke the "lib" program on Windows to create stub .lib files for the
+ # generated definitions. These .lib files can then be used during
+ # delayloading of the dynamic libraries.
+ ret = QuietRun(['lib', '/nologo',
+ '/machine:' + machine,
+ '/def:' + def_file_path,
+ '/out:' + lib_file_path],
+ filter=' Creating library')
+ if ret != 0:
+ raise SubprocessError(
+ 'Failed creating %s for %s' % (lib_file_path, def_file_path),
+ ret)
+
+
+class PosixStubWriter(object):
+ """Creates a file of stub functions for a library that is opened via dlopen.
+
+ Windows provides a function in their compiler known as delay loading, which
+ effectively generates a set of stub functions for a dynamic library that
+ delays loading of the dynamic library/resolution of the symbols until one of
+ the needed functions are accessed.
+
+ In posix, RTLD_LAZY does something similar with DSOs. This is the default
+ link mode for DSOs. However, even though the symbol is not resolved until
+ first usage, the DSO must be present at load time of the main binary.
+
+ To simulate the windows delay load procedure, we need to create a set of
+ stub functions that allow for correct linkage of the main binary, but
+ dispatch to the dynamically resolved symbol when the module is initialized.
+
+ This class takes a list of function signatures, and generates a set of stub
+ functions plus initialization code for them.
+ """
+
+ def __init__(self, module_name, signatures):
+ """Initializes PosixStubWriter for this set of signatures and module_name.
+
+ Args:
+ module_name: The name of the module we are writing a stub for.
+ signatures: The list of signature hashes, as produced by ParseSignatures,
+ to create stubs for.
+ """
+ self.signatures = signatures
+ self.module_name = module_name
+
+ @classmethod
+ def CStyleIdentifier(cls, identifier):
+ """Generates a C style identifier.
+
+ The module_name has all invalid identifier characters removed (anything
+ that's not [_a-zA-Z0-9]) and is run through string.capwords to try
+ and approximate camel case.
+
+ Args:
+ identifier: The string with the module name to turn to C-style.
+
+ Returns:
+ A string that can be used as part of a C identifier.
+ """
+ return string.capwords(re.sub(INVALID_C_IDENT_CHARS, '', identifier))
+
+ @classmethod
+ def EnumName(cls, module_name):
+ """Gets the enum name for the module.
+
+ Takes the module name and creates a suitable enum name. The module_name
+ is munged to be a valid C identifier then prefixed with the string
+ "kModule" to generate a Google style enum name.
+
+ Args:
+ module_name: The name of the module to generate an enum name for.
+
+ Returns:
+ A string with the name of the enum value representing this module.
+ """
+ return 'kModule%s' % PosixStubWriter.CStyleIdentifier(module_name)
+
+ @classmethod
+ def IsInitializedName(cls, module_name):
+ """Gets the name of function that checks initialization of this module.
+
+ The name is in the format IsModuleInitialized. Where "Module" is replaced
+ with the module name, munged to be a valid C identifier.
+
+ Args:
+ module_name: The name of the module to generate the function name for.
+
+ Returns:
+ A string with the name of the initialization check function.
+ """
+ return 'Is%sInitialized' % PosixStubWriter.CStyleIdentifier(module_name)
+
+ @classmethod
+ def InitializeModuleName(cls, module_name):
+ """Gets the name of the function that initializes this module.
+
+ The name is in the format InitializeModule. Where "Module" is replaced
+ with the module name, munged to be a valid C identifier.
+
+ Args:
+ module_name: The name of the module to generate the function name for.
+
+ Returns:
+ A string with the name of the initialization function.
+ """
+ return 'Initialize%s' % PosixStubWriter.CStyleIdentifier(module_name)
+
+ @classmethod
+ def UninitializeModuleName(cls, module_name):
+ """Gets the name of the function that uninitializes this module.
+
+ The name is in the format UninitializeModule. Where "Module" is replaced
+ with the module name, munged to be a valid C identifier.
+
+ Args:
+ module_name: The name of the module to generate the function name for.
+
+ Returns:
+ A string with the name of the uninitialization function.
+ """
+ return 'Uninitialize%s' % PosixStubWriter.CStyleIdentifier(module_name)
+
+ @classmethod
+ def StubFunctionPointer(cls, signature):
+ """Generates a function pointer declaration for the given signature.
+
+ Args:
+ signature: A signature hash, as produced by ParseSignatures,
+ representating the function signature.
+
+ Returns:
+ A string with the declaration of the function pointer for the signature.
+ """
+ return 'static %s (*%s_ptr)(%s) = NULL;' % (signature['return_type'],
+ signature['name'],
+ ', '.join(signature['params']))
+
+ @classmethod
+ def StubFunction(cls, signature):
+ """Generates a stub function definition for the given signature.
+
+ The function definitions are created with __attribute__((weak)) so that
+ they may be overridden by a real static link or mock versions to be used
+ when testing.
+
+ Args:
+ signature: A signature hash, as produced by ParseSignatures,
+ representating the function signature.
+
+ Returns:
+ A string with the stub function definition.
+ """
+ return_prefix = ''
+ if signature['return_type'] != 'void':
+ return_prefix = 'return '
+
+ # Generate the argument list.
+ arguments = [re.split('[\*& ]', arg)[-1].strip() for arg in
+ signature['params']]
+ arg_list = ', '.join(arguments)
+ if arg_list == 'void':
+ arg_list = ''
+
+ if arg_list != '' and len(arguments) > 1 and arguments[-1] == '...':
+ # If the last argment is ... then this is a variadic function.
+ if return_prefix != '':
+ return VARIADIC_STUB_FUNCTION_DEFINITION % {
+ 'return_type': signature['return_type'],
+ 'name': signature['name'],
+ 'params': ', '.join(signature['params']),
+ 'arg_list': ', '.join(arguments[0:-1]),
+ 'last_named_arg': arguments[-2]}
+ else:
+ return VOID_VARIADIC_STUB_FUNCTION_DEFINITION % {
+ 'name': signature['name'],
+ 'params': ', '.join(signature['params']),
+ 'arg_list': ', '.join(arguments[0:-1]),
+ 'last_named_arg': arguments[-2]}
+ else:
+ # This is a regular function.
+ return STUB_FUNCTION_DEFINITION % {
+ 'return_type': signature['return_type'],
+ 'name': signature['name'],
+ 'params': ', '.join(signature['params']),
+ 'return_prefix': return_prefix,
+ 'arg_list': arg_list}
+
+ @classmethod
+ def WriteImplementationPreamble(cls, header_path, outfile):
+ """Write the necessary includes for the implementation file.
+
+ Args:
+ header_path: The path to the header file.
+ outfile: The file handle to populate.
+ """
+ outfile.write(IMPLEMENTATION_PREAMBLE % header_path)
+
+ @classmethod
+ def WriteUmbrellaInitializer(cls, module_names, namespace, outfile):
+ """Writes a single function that will open + initialize each module.
+
+ This intializer will take in an stl map of that lists the correct
+ dlopen target for each module. The map type is
+ std::map<enum StubModules, vector<std::string>> which matches one module
+ to a list of paths to try in dlopen.
+
+ This function is an all-or-nothing function. If any module fails to load,
+ all other modules are dlclosed, and the function returns. Though it is
+ not enforced, this function should only be called once.
+
+ Args:
+ module_names: A list with the names of the modules in this stub file.
+ namespace: The namespace these functions should be in.
+ outfile: The file handle to populate with pointer definitions.
+ """
+ outfile.write(UMBRELLA_INITIALIZER_START % namespace)
+ outfile.write(UMBRELLA_INITIALIZER_CLEANUP_FUNCTION)
+
+ # Create the initializaiton function that calls all module initializers,
+ # checks if they succeeded, and backs out module loads on an error.
+ outfile.write(UMBRELLA_INITIALIZER_INITIALIZE_FUNCTION_START)
+ outfile.write(
+ '\n // Initialize each module if we have not already failed.\n')
+ for module in module_names:
+ outfile.write(' %s(opened_libraries[%s]);\n' %
+ (PosixStubWriter.InitializeModuleName(module),
+ PosixStubWriter.EnumName(module)))
+ outfile.write('\n')
+
+ # Output code to check the initialization status, clean up on error.
+ initializer_checks = ['!%s()' % PosixStubWriter.IsInitializedName(name)
+ for name in module_names]
+ uninitializers = ['%s()' % PosixStubWriter.UninitializeModuleName(name)
+ for name in module_names]
+ outfile.write(UMBRELLA_INITIALIZER_CHECK_AND_CLEANUP % {
+ 'conditional': ' ||\n '.join(initializer_checks),
+ 'uninitializers': ';\n '.join(uninitializers)})
+ outfile.write('\n} // namespace %s\n' % namespace)
+
+ @classmethod
+ def WriteHeaderContents(cls, module_names, namespace, header_guard, outfile):
+ """Writes a header file for the stub file generated for module_names.
+
+ The header file exposes the following:
+ 1) An enum, StubModules, listing with an entry for each enum.
+ 2) A typedef for a StubPathMap allowing for specification of paths to
+ search for each module.
+ 3) The IsInitialized/Initialize/Uninitialize functions for each module.
+ 4) An umbrella initialize function for all modules.
+
+ Args:
+ module_names: A list with the names of each module in this stub file.
+ namespace: The namespace these functions should be in.
+ header_guard: The macro to use as our header guard.
+ outfile: The output handle to populate.
+ """
+ outfile.write(STUB_HEADER_PREAMBLE %
+ {'guard_name': header_guard, 'namespace': namespace})
+
+ # Generate the Initializer protoypes for each module.
+ outfile.write('// Individual module initializer functions.\n')
+ for name in module_names:
+ outfile.write(MODULE_FUNCTION_PROTOTYPES % {
+ 'is_initialized': PosixStubWriter.IsInitializedName(name),
+ 'initialize': PosixStubWriter.InitializeModuleName(name),
+ 'uninitialize': PosixStubWriter.UninitializeModuleName(name)})
+
+ # Generate the enum for umbrella initializer.
+ outfile.write(UMBRELLA_ENUM_START)
+ outfile.write(' %s = 0,\n' % PosixStubWriter.EnumName(module_names[0]))
+ for name in module_names[1:]:
+ outfile.write(' %s,\n' % PosixStubWriter.EnumName(name))
+ outfile.write(UMBRELLA_ENUM_END)
+
+ outfile.write(UMBRELLA_INITIALIZER_PROTOTYPE)
+ outfile.write(STUB_HEADER_CLOSER % {
+ 'namespace': namespace, 'guard_name':
+ header_guard})
+
+ def WriteImplementationContents(self, namespace, outfile):
+ """Given a file handle, write out the stub definitions for this module.
+
+ Args:
+ namespace: The namespace these functions should be in.
+ outfile: The file handle to populate.
+ """
+ outfile.write(IMPLEMENTATION_CONTENTS_C_START)
+ self.WriteFunctionPointers(outfile)
+ self.WriteStubFunctions(outfile)
+ outfile.write(IMPLEMENTATION_CONTENTS_C_END)
+
+ outfile.write(NAMESPACE_START % namespace)
+ self.WriteModuleInitializeFunctions(outfile)
+ outfile.write(NAMESPACE_END % namespace)
+
+ def WriteFunctionPointers(self, outfile):
+ """Write the function pointer declarations needed by the stubs.
+
+ We need function pointers to hold the actual location of the function
+ implementation returned by dlsym. This function outputs a pointer
+ definition for each signature in the module.
+
+ Pointers will be named with the following pattern "FuntionName_ptr".
+
+ Args:
+ outfile: The file handle to populate with pointer definitions.
+ """
+ outfile.write(FUNCTION_POINTER_SECTION_COMMENT)
+
+ for sig in self.signatures:
+ outfile.write('%s\n' % PosixStubWriter.StubFunctionPointer(sig))
+ outfile.write('\n')
+
+ def WriteStubFunctions(self, outfile):
+ """Write the function stubs to handle dispatching to real implementations.
+
+ Functions that have a return type other than void will look as follows:
+
+ ReturnType FunctionName(A a) {
+ return FunctionName_ptr(a);
+ }
+
+ Functions with a return type of void will look as follows:
+
+ void FunctionName(A a) {
+ FunctionName_ptr(a);
+ }
+
+ Args:
+ outfile: The file handle to populate.
+ """
+ outfile.write('// Stubs that dispatch to the real implementations.\n')
+ for sig in self.signatures:
+ outfile.write('%s\n' % PosixStubWriter.StubFunction(sig))
+
+ def WriteModuleInitializeFunctions(self, outfile):
+ """Write functions to initialize/query initlialization of the module.
+
+ This creates 2 functions IsModuleInitialized and InitializeModule where
+ "Module" is replaced with the module name, first letter capitalized.
+
+ The InitializeModule function takes a handle that is retrieved from dlopen
+ and attempts to assign each function pointer above via dlsym.
+
+ The IsModuleInitialized returns true if none of the required functions
+ pointers are NULL.
+
+ Args:
+ outfile: The file handle to populate.
+ """
+ ptr_names = ['%s_ptr' % sig['name'] for sig in self.signatures]
+
+ # Construct the conditional expression to check the initialization of
+ # all the function pointers above. It should generate a conjuntion
+ # with each pointer on its own line, indented by six spaces to match
+ # the indentation level of MODULE_INITIALIZATION_CHECK_FUNCTION.
+ initialization_conditional = ' &&\n '.join(ptr_names)
+
+ outfile.write(MODULE_INITIALIZATION_CHECK_FUNCTION % (
+ PosixStubWriter.IsInitializedName(self.module_name),
+ initialization_conditional))
+
+ # Create function that initializes the module.
+ outfile.write(MODULE_INITIALIZE_START %
+ PosixStubWriter.InitializeModuleName(self.module_name))
+ for sig in self.signatures:
+ outfile.write(STUB_POINTER_INITIALIZER % {
+ 'name': sig['name'],
+ 'return_type': sig['return_type'],
+ 'parameters': ', '.join(sig['params'])})
+ outfile.write(MODULE_INITIALIZE_END)
+
+ # Create function that uninitializes the module (sets all pointers to
+ # NULL).
+ outfile.write(MODULE_UNINITIALIZE_START %
+ PosixStubWriter.UninitializeModuleName(self.module_name))
+ for sig in self.signatures:
+ outfile.write(' %s_ptr = NULL;\n' % sig['name'])
+ outfile.write(MODULE_UNINITIALIZE_END)
+
+
+def CreateOptionParser():
+ """Creates an OptionParser for the configuration options of script.
+
+ Returns:
+ A OptionParser object.
+ """
+ parser = optparse.OptionParser(usage='usage: %prog [options] input')
+ parser.add_option('-o',
+ '--output',
+ dest='out_dir',
+ default=None,
+ help='Output location.')
+ parser.add_option('-i',
+ '--intermediate_dir',
+ dest='intermediate_dir',
+ default=None,
+ help=('Location of intermediate files. Ignored for %s type'
+ % FILE_TYPE_WIN_DEF))
+ parser.add_option('-t',
+ '--type',
+ dest='type',
+ default=None,
+ help=('Type of file. Valid types are "%s" or "%s" or "%s" '
+ 'or "%s"' %
+ (FILE_TYPE_POSIX_STUB, FILE_TYPE_WIN_X86,
+ FILE_TYPE_WIN_X64, FILE_TYPE_WIN_DEF)))
+ parser.add_option('-s',
+ '--stubfile_name',
+ dest='stubfile_name',
+ default=None,
+ help=('Name of posix_stubs output file. Only valid with '
+ '%s type.' % FILE_TYPE_POSIX_STUB))
+ parser.add_option('-p',
+ '--path_from_source',
+ dest='path_from_source',
+ default=None,
+ help=('The relative path from the project root that the '
+ 'generated file should consider itself part of (eg. '
+ 'third_party/ffmpeg). This is used to generate the '
+ 'header guard and namespace for our initializer '
+ 'functions and does NOT affect the physical output '
+ 'location of the file like -o does. Ignored for '
+ '%s and %s types.' %
+ (FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64)))
+ parser.add_option('-e',
+ '--extra_stub_header',
+ dest='extra_stub_header',
+ default=None,
+ help=('File to insert after the system includes in the '
+ 'generated stub implemenation file. Ignored for '
+ '%s and %s types.' %
+ (FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64)))
+ parser.add_option('-m',
+ '--module_name',
+ dest='module_name',
+ default=None,
+ help=('Name of output DLL or LIB for DEF creation using '
+ '%s type.' % FILE_TYPE_WIN_DEF))
+
+ return parser
+
+
+def ParseOptions():
+ """Parses the options and terminates program if they are not sane.
+
+ Returns:
+ The pair (optparse.OptionValues, [string]), that is the output of
+ a successful call to parser.parse_args().
+ """
+ parser = CreateOptionParser()
+ options, args = parser.parse_args()
+
+ if not args:
+ parser.error('No inputs specified')
+
+ if options.out_dir is None:
+ parser.error('Output location not specified')
+
+ if (options.type not in
+ [FILE_TYPE_WIN_X86, FILE_TYPE_WIN_X64, FILE_TYPE_POSIX_STUB,
+ FILE_TYPE_WIN_DEF]):
+ parser.error('Invalid output file type: %s' % options.type)
+
+ if options.type == FILE_TYPE_POSIX_STUB:
+ if options.stubfile_name is None:
+ parser.error('Output file name needed for %s' % FILE_TYPE_POSIX_STUB)
+ if options.path_from_source is None:
+ parser.error('Path from source needed for %s' % FILE_TYPE_POSIX_STUB)
+
+ if options.type == FILE_TYPE_WIN_DEF:
+ if options.module_name is None:
+ parser.error('Module name needed for %s' % FILE_TYPE_WIN_DEF)
+
+ return options, args
+
+
+def EnsureDirExists(dir):
+ """Creates a directory. Does not use the more obvious 'if not exists: create'
+ to avoid race with other invocations of the same code, which will error out
+ on makedirs if another invocation has succeeded in creating the directory
+ since the existence check."""
+ try:
+ os.makedirs(dir)
+ except:
+ if not os.path.isdir(dir):
+ raise
+
+
+def CreateOutputDirectories(options):
+ """Creates the intermediate and final output directories.
+
+ Given the parsed options, create the intermediate and final output
+ directories if they do not exist. Returns the paths to both directories
+ as a pair.
+
+ Args:
+ options: An OptionParser.OptionValues object with the parsed options.
+
+ Returns:
+ The pair (out_dir, intermediate_dir), both of which are strings.
+ """
+ out_dir = os.path.normpath(options.out_dir)
+ intermediate_dir = os.path.normpath(options.intermediate_dir)
+ if intermediate_dir is None:
+ intermediate_dir = out_dir
+
+ EnsureDirExists(out_dir)
+ EnsureDirExists(intermediate_dir)
+
+ return out_dir, intermediate_dir
+
+
+def CreateWindowsLibForSigFiles(sig_files, out_dir, intermediate_dir, machine):
+ """For each signature file, create a windows lib.
+
+ Args:
+ sig_files: Array of strings with the paths to each signature file.
+ out_dir: String holding path to directory where the generated libs go.
+ intermediate_dir: String holding path to directory generated intermdiate
+ artifacts.
+ machine: String holding the machine type, 'X86' or 'X64'.
+ """
+ for input_path in sig_files:
+ infile = open(input_path, 'r')
+ try:
+ signatures = ParseSignatures(infile)
+ module_name = ExtractModuleName(os.path.basename(input_path))
+ CreateWindowsLib(module_name, signatures, intermediate_dir, out_dir,
+ machine)
+ finally:
+ infile.close()
+
+
+def CreateWindowsDefForSigFiles(sig_files, out_dir, module_name):
+ """For all signature files, create a single windows def file.
+
+ Args:
+ sig_files: Array of strings with the paths to each signature file.
+ out_dir: String holding path to directory where the generated def goes.
+ module_name: Name of the output DLL or LIB which will link in the def file.
+ """
+ signatures = []
+ for input_path in sig_files:
+ infile = open(input_path, 'r')
+ try:
+ signatures += ParseSignatures(infile)
+ finally:
+ infile.close()
+
+ def_file_path = os.path.join(
+ out_dir, os.path.splitext(os.path.basename(module_name))[0] + '.def')
+ outfile = open(def_file_path, 'w')
+
+ try:
+ WriteWindowsDefFile(module_name, signatures, outfile)
+ finally:
+ outfile.close()
+
+
+def CreatePosixStubsForSigFiles(sig_files, stub_name, out_dir,
+ intermediate_dir, path_from_source,
+ extra_stub_header):
+ """Create a posix stub library with a module for each signature file.
+
+ Args:
+ sig_files: Array of strings with the paths to each signature file.
+ stub_name: String with the basename of the generated stub file.
+ out_dir: String holding path to directory for the .h files.
+ intermediate_dir: String holding path to directory for the .cc files.
+ path_from_source: String with relative path of generated files from the
+ project root.
+ extra_stub_header: String with path to file of extra lines to insert
+ into the generated header for the stub library.
+ """
+ header_base_name = stub_name + '.h'
+ header_path = os.path.join(out_dir, header_base_name)
+ impl_path = os.path.join(intermediate_dir, stub_name + '.cc')
+
+ module_names = [ExtractModuleName(path) for path in sig_files]
+ namespace = path_from_source.replace('/', '_').lower()
+ header_guard = '%s_' % namespace.upper()
+ header_include_path = os.path.join(path_from_source, header_base_name)
+
+ # First create the implementation file.
+ impl_file = open(impl_path, 'w')
+ try:
+ # Open the file, and create the preamble which consists of a file
+ # header plus any necessary includes.
+ PosixStubWriter.WriteImplementationPreamble(header_include_path,
+ impl_file)
+ if extra_stub_header is not None:
+ extra_header_file = open(extra_stub_header, 'r')
+ try:
+ impl_file.write('\n')
+ for line in extra_header_file:
+ impl_file.write(line)
+ impl_file.write('\n')
+ finally:
+ extra_header_file.close()
+
+ # For each signature file, generate the stub population functions
+ # for that file. Each file represents one module.
+ for input_path in sig_files:
+ name = ExtractModuleName(input_path)
+ infile = open(input_path, 'r')
+ try:
+ signatures = ParseSignatures(infile)
+ finally:
+ infile.close()
+ writer = PosixStubWriter(name, signatures)
+ writer.WriteImplementationContents(namespace, impl_file)
+
+ # Lastly, output the umbrella function for the file.
+ PosixStubWriter.WriteUmbrellaInitializer(module_names, namespace,
+ impl_file)
+ finally:
+ impl_file.close()
+
+ # Then create the associated header file.
+ header_file = open(header_path, 'w')
+ try:
+ PosixStubWriter.WriteHeaderContents(module_names, namespace,
+ header_guard, header_file)
+ finally:
+ header_file.close()
+
+
+def main():
+ options, args = ParseOptions()
+ out_dir, intermediate_dir = CreateOutputDirectories(options)
+
+ if options.type == FILE_TYPE_WIN_X86:
+ CreateWindowsLibForSigFiles(args, out_dir, intermediate_dir, 'X86')
+ elif options.type == FILE_TYPE_WIN_X64:
+ CreateWindowsLibForSigFiles(args, out_dir, intermediate_dir, 'X64')
+ elif options.type == FILE_TYPE_POSIX_STUB:
+ CreatePosixStubsForSigFiles(args, options.stubfile_name, out_dir,
+ intermediate_dir, options.path_from_source,
+ options.extra_stub_header)
+ elif options.type == FILE_TYPE_WIN_DEF:
+ CreateWindowsDefForSigFiles(args, out_dir, options.module_name)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/generate_stubs/generate_stubs_unittest.py b/chromium/tools/generate_stubs/generate_stubs_unittest.py
new file mode 100755
index 00000000000..13a2bc15e59
--- /dev/null
+++ b/chromium/tools/generate_stubs/generate_stubs_unittest.py
@@ -0,0 +1,297 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unittest for the generate_stubs.py.
+
+Since generate_stubs.py is a code generator, it is hard to do a very good
+test. Instead of creating a golden-file test, which might be flakey, this
+test elects instead to verify that various components "exist" within the
+generated file as a sanity check. In particular, there is a simple hit
+test to make sure that umbrella functions, etc., do try and include every
+function they are responsible for invoking. Missing an invocation is quite
+easily missed.
+
+There is no attempt to verify ordering of different components, or whether
+or not those components are going to parse incorrectly because of prior
+errors or positioning. Most of that should be caught really fast anyways
+during any attempt to use a badly behaving script.
+"""
+
+import generate_stubs as gs
+import re
+import StringIO
+import sys
+import unittest
+
+
+def _MakeSignature(return_type, name, params):
+ return {'return_type': return_type,
+ 'name': name,
+ 'params': params}
+
+
+SIMPLE_SIGNATURES = [
+ ('int foo(int a)', _MakeSignature('int', 'foo', ['int a'])),
+ ('int bar(int a, double b)', _MakeSignature('int', 'bar',
+ ['int a', 'double b'])),
+ ('int baz(void)', _MakeSignature('int', 'baz', ['void'])),
+ ('void quux(void)', _MakeSignature('void', 'quux', ['void'])),
+ ('void waldo(void);', _MakeSignature('void', 'waldo', ['void'])),
+ ('int corge(void);', _MakeSignature('int', 'corge', ['void'])),
+ ]
+
+TRICKY_SIGNATURES = [
+ ('const struct name *foo(int a, struct Test* b); ',
+ _MakeSignature('const struct name *',
+ 'foo',
+ ['int a', 'struct Test* b'])),
+ ('const struct name &foo(int a, struct Test* b);',
+ _MakeSignature('const struct name &',
+ 'foo',
+ ['int a', 'struct Test* b'])),
+ ('const struct name &_foo(int a, struct Test* b);',
+ _MakeSignature('const struct name &',
+ '_foo',
+ ['int a', 'struct Test* b'])),
+ ('struct name const * const _foo(int a, struct Test* b) '
+ '__attribute__((inline));',
+ _MakeSignature('struct name const * const',
+ '_foo',
+ ['int a', 'struct Test* b']))
+ ]
+
+INVALID_SIGNATURES = ['I am bad', 'Seriously bad(', ';;;']
+
+
+class GenerateStubModuleFunctionsUnittest(unittest.TestCase):
+ def testExtractModuleName(self):
+ self.assertEqual('somefile-2', gs.ExtractModuleName('somefile-2.ext'))
+
+ def testParseSignatures_EmptyFile(self):
+ # Empty file just generates empty signatures.
+ infile = StringIO.StringIO()
+ signatures = gs.ParseSignatures(infile)
+ self.assertEqual(0, len(signatures))
+
+ def testParseSignatures_SimpleSignatures(self):
+ file_contents = '\n'.join([x[0] for x in SIMPLE_SIGNATURES])
+ infile = StringIO.StringIO(file_contents)
+ signatures = gs.ParseSignatures(infile)
+ self.assertEqual(len(SIMPLE_SIGNATURES), len(signatures))
+
+ # We assume signatures are in order.
+ for i in xrange(len(SIMPLE_SIGNATURES)):
+ self.assertEqual(SIMPLE_SIGNATURES[i][1], signatures[i],
+ msg='Expected %s\nActual %s\nFor %s' %
+ (SIMPLE_SIGNATURES[i][1],
+ signatures[i],
+ SIMPLE_SIGNATURES[i][0]))
+
+ def testParseSignatures_TrickySignatures(self):
+ file_contents = '\n'.join([x[0] for x in TRICKY_SIGNATURES])
+ infile = StringIO.StringIO(file_contents)
+ signatures = gs.ParseSignatures(infile)
+ self.assertEqual(len(TRICKY_SIGNATURES), len(signatures))
+
+ # We assume signatures are in order.
+ for i in xrange(len(TRICKY_SIGNATURES)):
+ self.assertEqual(TRICKY_SIGNATURES[i][1], signatures[i],
+ msg='Expected %s\nActual %s\nFor %s' %
+ (TRICKY_SIGNATURES[i][1],
+ signatures[i],
+ TRICKY_SIGNATURES[i][0]))
+
+ def testParseSignatures_InvalidSignatures(self):
+ for i in INVALID_SIGNATURES:
+ infile = StringIO.StringIO(i)
+ self.assertRaises(gs.BadSignatureError, gs.ParseSignatures, infile)
+
+ def testParseSignatures_CommentsIgnored(self):
+ my_sigs = []
+ my_sigs.append('# a comment')
+ my_sigs.append(SIMPLE_SIGNATURES[0][0])
+ my_sigs.append('# another comment')
+ my_sigs.append(SIMPLE_SIGNATURES[0][0])
+ my_sigs.append('# a third comment')
+ my_sigs.append(SIMPLE_SIGNATURES[0][0])
+
+ file_contents = '\n'.join(my_sigs)
+ infile = StringIO.StringIO(file_contents)
+ signatures = gs.ParseSignatures(infile)
+ self.assertEqual(3, len(signatures))
+
+
+class WindowsLibUnittest(unittest.TestCase):
+ def testWriteWindowsDefFile(self):
+ module_name = 'my_module-1'
+ signatures = [sig[1] for sig in SIMPLE_SIGNATURES]
+ outfile = StringIO.StringIO()
+ gs.WriteWindowsDefFile(module_name, signatures, outfile)
+ contents = outfile.getvalue()
+
+ # Check that the file header is correct.
+ self.assertTrue(contents.startswith("""LIBRARY %s
+EXPORTS
+""" % module_name))
+
+ # Check that the signatures were exported.
+ for sig in signatures:
+ pattern = '\n %s\n' % sig['name']
+ self.assertTrue(re.search(pattern, contents),
+ msg='Expected match of "%s" in %s' % (pattern, contents))
+
+ def testQuietRun(self):
+ output = StringIO.StringIO()
+ gs.QuietRun([sys.executable,
+ '-c', 'print "line 1 and suffix\\nline 2"'],
+ write_to=output)
+ self.assertEqual('line 1 and suffix\nline 2\n', output.getvalue())
+
+ output = StringIO.StringIO()
+ gs.QuietRun([sys.executable,
+ '-c', 'print "line 1 and suffix\\nline 2"'],
+ filter='line 1', write_to=output)
+ self.assertEqual('line 2\n', output.getvalue())
+
+
+class PosixStubWriterUnittest(unittest.TestCase):
+ def setUp(self):
+ self.module_name = 'my_module-1'
+ self.signatures = [sig[1] for sig in SIMPLE_SIGNATURES]
+ self.out_dir = 'out_dir'
+ self.writer = gs.PosixStubWriter(self.module_name, self.signatures)
+
+ def testEnumName(self):
+ self.assertEqual('kModuleMy_module1',
+ gs.PosixStubWriter.EnumName(self.module_name))
+
+ def testIsInitializedName(self):
+ self.assertEqual('IsMy_module1Initialized',
+ gs.PosixStubWriter.IsInitializedName(self.module_name))
+
+ def testInitializeModuleName(self):
+ self.assertEqual(
+ 'InitializeMy_module1',
+ gs.PosixStubWriter.InitializeModuleName(self.module_name))
+
+ def testUninitializeModuleName(self):
+ self.assertEqual(
+ 'UninitializeMy_module1',
+ gs.PosixStubWriter.UninitializeModuleName(self.module_name))
+
+ def testStubFunctionPointer(self):
+ self.assertEqual(
+ 'static int (*foo_ptr)(int a) = NULL;',
+ gs.PosixStubWriter.StubFunctionPointer(SIMPLE_SIGNATURES[0][1]))
+
+ def testStubFunction(self):
+ # Test for a signature with a return value and a parameter.
+ self.assertEqual("""extern int foo(int a) __attribute__((weak));
+int foo(int a) {
+ return foo_ptr(a);
+}""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[0][1]))
+
+ # Test for a signature with a void return value and no parameters.
+ self.assertEqual("""extern void waldo(void) __attribute__((weak));
+void waldo(void) {
+ waldo_ptr();
+}""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[4][1]))
+
+ def testWriteImplemenationContents(self):
+ outfile = StringIO.StringIO()
+ self.writer.WriteImplementationContents('my_namespace', outfile)
+ contents = outfile.getvalue()
+
+ # Verify namespace exists somewhere.
+ self.assertTrue(contents.find('namespace my_namespace {') != -1)
+
+ # Verify that each signature has an _ptr and a function call in the file.
+ # Check that the signatures were exported.
+ for sig in self.signatures:
+ decl = gs.PosixStubWriter.StubFunctionPointer(sig)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ # Verify that each signature has an stub function generated for it.
+ for sig in self.signatures:
+ decl = gs.PosixStubWriter.StubFunction(sig)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ # Find module initializer functions. Make sure all 3 exist.
+ decl = gs.PosixStubWriter.InitializeModuleName(self.module_name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.UninitializeModuleName(self.module_name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.IsInitializedName(self.module_name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ def testWriteHeaderContents(self):
+ # Data for header generation.
+ module_names = ['oneModule', 'twoModule']
+
+ # Make the header.
+ outfile = StringIO.StringIO()
+ self.writer.WriteHeaderContents(module_names, 'my_namespace', 'GUARD_',
+ outfile)
+ contents = outfile.getvalue()
+
+ # Check for namespace and header guard.
+ self.assertTrue(contents.find('namespace my_namespace {') != -1)
+ self.assertTrue(contents.find('#ifndef GUARD_') != -1)
+
+ # Check for umbrella initializer.
+ self.assertTrue(contents.find('InitializeStubs(') != -1)
+
+ # Check per-module declarations.
+ for name in module_names:
+ # Check for enums.
+ decl = gs.PosixStubWriter.EnumName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ # Check for module initializer functions.
+ decl = gs.PosixStubWriter.IsInitializedName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.InitializeModuleName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.UninitializeModuleName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ def testWriteUmbrellaInitializer(self):
+ # Data for header generation.
+ module_names = ['oneModule', 'twoModule']
+
+ # Make the header.
+ outfile = StringIO.StringIO()
+ self.writer.WriteUmbrellaInitializer(module_names, 'my_namespace', outfile)
+ contents = outfile.getvalue()
+
+ # Check for umbrella initializer declaration.
+ self.assertTrue(contents.find('bool InitializeStubs(') != -1)
+
+ # If the umbrella initializer is correctly written, each module will have
+ # its initializer called, checked, and uninitialized on failure. Sanity
+ # check that here.
+ for name in module_names:
+ # Check for module initializer functions.
+ decl = gs.PosixStubWriter.IsInitializedName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.InitializeModuleName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.UninitializeModuleName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/git/README b/chromium/tools/git/README
new file mode 100644
index 00000000000..7f8e363dee0
--- /dev/null
+++ b/chromium/tools/git/README
@@ -0,0 +1,16 @@
+This directory contains some helpful Git tools.
+
+post-checkout and post-merge
+============================
+These hooks warn you about DEPS modifications so you will remember
+to run "gclient sync".
+
+To install these Git hooks, create symlinks like so:
+ ln -s $(pwd)/post-checkout $(git rev-parse --git-dir)/hooks
+ ln -s $(pwd)/post-merge $(git rev-parse --git-dir)/hooks
+
+
+git-graph
+=========
+Create a graph of the recent history of occurences of a grep
+expression in the project.
diff --git a/chromium/tools/git/for-all-touched-files.py b/chromium/tools/git/for-all-touched-files.py
new file mode 100755
index 00000000000..a7e784ade3e
--- /dev/null
+++ b/chromium/tools/git/for-all-touched-files.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+ Invokes the specified (quoted) command for all files modified
+ between the current git branch and the specified branch or commit.
+
+ The special token [[FILENAME]] (or whatever you choose using the -t
+ flag) is replaced with each of the filenames of new or modified files.
+
+ Deleted files are not included. Neither are untracked files.
+
+Synopsis:
+ %prog [-b BRANCH] [-d] [-x EXTENSIONS|-c] [-t TOKEN] QUOTED_COMMAND
+
+Examples:
+ %prog -x gyp,gypi "tools/format_xml.py [[FILENAME]]"
+ %prog -c "tools/sort-headers.py [[FILENAME]]"
+ %prog -t "~~BINGO~~" "echo I modified ~~BINGO~~"
+"""
+
+import optparse
+import os
+import subprocess
+import sys
+
+
+# List of C++-like source file extensions.
+_CPP_EXTENSIONS = ('h', 'hh', 'hpp', 'c', 'cc', 'cpp', 'cxx', 'mm',)
+
+
+def GitShell(args, ignore_return=False):
+ """A shell invocation suitable for communicating with git. Returns
+ output as list of lines, raises exception on error.
+ """
+ job = subprocess.Popen(args,
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ (out, err) = job.communicate()
+ if job.returncode != 0 and not ignore_return:
+ print out
+ raise Exception("Error %d running command %s" % (
+ job.returncode, args))
+ return out.split('\n')
+
+
+def FilenamesFromGit(branch_name, extensions):
+ """Provides a list of all new and modified files listed by [git diff
+ branch_name] where branch_name can be blank to get a diff of the
+ workspace.
+
+ Excludes deleted files.
+
+ If extensions is not an empty list, include only files with one of
+ the extensions on the list.
+ """
+ lines = GitShell('git diff --stat=600,500 %s' % branch_name)
+ filenames = []
+ for line in lines:
+ line = line.lstrip()
+ # Avoid summary line, and files that have been deleted (no plus).
+ if line.find('|') != -1 and line.find('+') != -1:
+ filename = line.split()[0]
+ if filename:
+ filename = filename.rstrip()
+ ext = filename.rsplit('.')[-1]
+ if not extensions or ext in extensions:
+ filenames.append(filename)
+ return filenames
+
+
+def ForAllTouchedFiles(branch_name, extensions, token, command):
+ """For each new or modified file output by [git diff branch_name],
+ run command with token replaced with the filename. If extensions is
+ not empty, do this only for files with one of the extensions in that
+ list.
+ """
+ filenames = FilenamesFromGit(branch_name, extensions)
+ for filename in filenames:
+ os.system(command.replace(token, filename))
+
+
+def main():
+ parser = optparse.OptionParser(usage=__doc__)
+ parser.add_option('-x', '--extensions', default='', dest='extensions',
+ help='Limits to files with given extensions '
+ '(comma-separated).')
+ parser.add_option('-c', '--cpp', default=False, action='store_true',
+ dest='cpp_only',
+ help='Runs your command only on C++-like source files.')
+ parser.add_option('-t', '--token', default='[[FILENAME]]', dest='token',
+ help='Sets the token to be replaced for each file '
+ 'in your command (default [[FILENAME]]).')
+ parser.add_option('-b', '--branch', default='origin/master', dest='branch',
+ help='Sets what to diff to (default origin/master). Set '
+ 'to empty to diff workspace against HEAD.')
+ opts, args = parser.parse_args()
+
+ if not args:
+ parser.print_help()
+ sys.exit(1)
+
+ extensions = opts.extensions
+ if opts.cpp_only:
+ extensions = _CPP_EXTENSIONS
+
+ ForAllTouchedFiles(opts.branch, extensions, opts.token, args[0])
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/git/git-diff-ide.py b/chromium/tools/git/git-diff-ide.py
new file mode 100755
index 00000000000..405d270eba3
--- /dev/null
+++ b/chromium/tools/git/git-diff-ide.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+ Invokes git diff [args...] and inserts file:line in front of each line of diff
+ output where possible.
+
+ This is useful from an IDE that allows you to double-click lines that begin
+ with file:line to open and jump to that point in the file.
+
+Synopsis:
+ %prog [git diff args...]
+
+Examples:
+ %prog
+ %prog HEAD
+"""
+
+import subprocess
+import sys
+
+
+def GitShell(args, ignore_return=False):
+ """A shell invocation suitable for communicating with git. Returns
+ output as list of lines, raises exception on error.
+ """
+ job = subprocess.Popen(args,
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ (out, err) = job.communicate()
+ if job.returncode != 0 and not ignore_return:
+ print out
+ raise Exception("Error %d running command %s" % (
+ job.returncode, args))
+ return out.split('\n')
+
+
+def PrintGitDiff(extra_args):
+ """Outputs git diff extra_args with file:line inserted into relevant lines."""
+ current_file = '';
+ line_num = 0;
+ lines = GitShell('git diff %s' % ' '.join(extra_args))
+ for line in lines:
+ # Pass-through lines:
+ # diff --git a/file.c b/file.c
+ # index 0e38c2d..8cd69ae 100644
+ # --- a/file.c
+ if (line.startswith('diff ') or
+ line.startswith('index ') or
+ line.startswith('--- ')):
+ print line
+ continue
+
+ # Get the filename from the +++ line:
+ # +++ b/file.c
+ if line.startswith('+++ '):
+ # Filename might be /dev/null or a/file or b/file.
+ # Skip the first two characters unless it starts with /.
+ current_file = line[4:] if line[4] == '/' else line[6:]
+ print line
+ continue
+
+ # Update line number from the @@ lines:
+ # @@ -41,9 +41,9 @@ def MyFunc():
+ # ^^
+ if line.startswith('@@ '):
+ _, old_nr, new_nr, _ = line.split(' ', 3)
+ line_num = int(new_nr.split(',')[0])
+ print line
+ continue
+ print current_file + ':' + repr(line_num) + ':' + line
+
+ # Increment line number for lines that start with ' ' or '+':
+ # @@ -41,4 +41,4 @@ def MyFunc():
+ # file.c:41: // existing code
+ # file.c:42: // existing code
+ # file.c:43:-// deleted code
+ # file.c:43:-// deleted code
+ # file.c:43:+// inserted code
+ # file.c:44:+// inserted code
+ if line.startswith(' ') or line.startswith('+'):
+ line_num += 1
+
+
+def main():
+ PrintGitDiff(sys.argv[1:])
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/git/git-utils.sh b/chromium/tools/git/git-utils.sh
new file mode 100755
index 00000000000..608d27aa26b
--- /dev/null
+++ b/chromium/tools/git/git-utils.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+TPUT=$(which tput 2>/dev/null)
+if test -x "$TPUT" && $TPUT setaf 1 >/dev/null ; then
+ RED="$($TPUT setaf 1)"
+ NORMAL="$($TPUT op)"
+else
+ RED=
+ NORMAL=
+fi
+
+warn() {
+ echo "${RED}WARNING:${NORMAL} $@"
+}
diff --git a/chromium/tools/git/graph.sh b/chromium/tools/git/graph.sh
new file mode 100755
index 00000000000..800a52b86c8
--- /dev/null
+++ b/chromium/tools/git/graph.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+about="Given a grep expression, creates a graph of occurrences of that
+expression in the recent history of the tree.
+
+Prerequisites: git and GNU R (apt-get install r-base).
+"
+
+set -e
+
+target="$1"
+
+if [ -z $target ]; then
+ echo "usage: $0 <grep-compatible expression>"
+ echo
+ echo "$about"
+ exit 1
+fi
+
+datafile=$(mktemp -t tmp.XXXXXXXXXX)
+trap "rm -f $datafile" EXIT
+
+echo 'ago count' > $datafile
+for ago in {90..0}; do
+ commit=$(git rev-list -1 --until="$ago days ago" origin/trunk)
+ git checkout -q -f $commit
+ count=$(git grep -E "$target" -- '*.cc' '*.h' '*.m' '*.mm' | wc -l)
+ echo "-$ago $count" >> $datafile
+ echo -n '.'
+done
+
+R CMD BATCH <(cat <<EOF
+data = read.delim("$datafile", sep=' ')
+png(width=600, height=300)
+plot(count ~ ago, type="l", main="$target", xlab='days ago', data=data)
+EOF
+) /dev/null
+
+echo done. # Primarily to add a newline after all the dots.
diff --git a/chromium/tools/git/mass-rename.py b/chromium/tools/git/mass-rename.py
new file mode 100755
index 00000000000..21fbef76b72
--- /dev/null
+++ b/chromium/tools/git/mass-rename.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+mass-rename: update source files (gyp lists, #includes) to reflect
+a rename. Expects "git diff --cached -M" to list a bunch of renames.
+
+To use:
+ 1) git mv foo1 bar1; git mv foo2 bar2; etc.
+ 2) *without committing*, ./tools/git/mass-rename.py
+ 3) look at git diff (without --cached) to see what the damage is
+"""
+
+
+import os
+import subprocess
+import sys
+
+
+BASE_DIR = os.path.abspath(os.path.dirname(__file__))
+
+
+def main():
+ popen = subprocess.Popen('git diff --cached --raw -M',
+ shell=True, stdout=subprocess.PIPE)
+ out, _ = popen.communicate()
+ if popen.returncode != 0:
+ return 1
+ for line in out.splitlines():
+ parts = line.split('\t')
+ if len(parts) != 3:
+ print 'Skipping: %s -- not a rename?' % parts
+ continue
+ attrs, fro, to = parts
+ if attrs.split()[4].startswith('R'):
+ subprocess.check_call([
+ sys.executable,
+ os.path.join(BASE_DIR, 'move_source_file.py'),
+ '--already_moved',
+ '--no_error_for_non_source_file',
+ fro, to])
+ else:
+ print 'Skipping: %s -- not a rename?' % fro
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/git/mass-rename.sh b/chromium/tools/git/mass-rename.sh
new file mode 100755
index 00000000000..f92814e70bb
--- /dev/null
+++ b/chromium/tools/git/mass-rename.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# mass-rename: update source files (gyp lists, #includes) to reflect
+# a rename. Expects "git diff --cached -M" to list a bunch of renames.
+#
+# To use:
+# 1) git mv foo1 bar1; git mv foo2 bar2; etc.
+# 2) *without committing*, ./tools/git/mass-rename.sh
+# 3) look at git diff (without --cached) to see what the damage is
+# 4) commit, then use tools/sort-headers.py to fix #include ordering:
+# for f in $(git diff --name-only origin); do ./tools/sort-headers.py $f; done
+
+DIR="$( cd "$( dirname "$0" )" && pwd )"
+python $DIR/mass-rename.py "$*"
diff --git a/chromium/tools/git/mffr.py b/chromium/tools/git/mffr.py
new file mode 100755
index 00000000000..d5b67c8c3f1
--- /dev/null
+++ b/chromium/tools/git/mffr.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Usage: mffr.py [-d] [-g *.h] [-g *.cc] REGEXP REPLACEMENT
+
+This tool performs a fast find-and-replace operation on files in
+the current git repository.
+
+The -d flag selects a default set of globs (C++ and Objective-C/C++
+source files). The -g flag adds a single glob to the list and may
+be used multiple times. If neither -d nor -g is specified, the tool
+searches all files (*.*).
+
+REGEXP uses full Python regexp syntax. REPLACEMENT can use
+back-references.
+"""
+
+import optparse
+import re
+import subprocess
+import sys
+
+
+# We need to use shell=True with subprocess on Windows so that it
+# finds 'git' from the path, but can lead to undesired behavior on
+# Linux.
+_USE_SHELL = (sys.platform == 'win32')
+
+
+def MultiFileFindReplace(original, replacement, file_globs):
+ """Implements fast multi-file find and replace.
+
+ Given an |original| string and a |replacement| string, find matching
+ files by running git grep on |original| in files matching any
+ pattern in |file_globs|.
+
+ Once files are found, |re.sub| is run to replace |original| with
+ |replacement|. |replacement| may use capture group back-references.
+
+ Args:
+ original: '(#(include|import)\s*["<])chrome/browser/ui/browser.h([>"])'
+ replacement: '\1chrome/browser/ui/browser/browser.h\3'
+ file_globs: ['*.cc', '*.h', '*.m', '*.mm']
+
+ Returns the list of files modified.
+
+ Raises an exception on error.
+ """
+ # Posix extended regular expressions do not reliably support the "\s"
+ # shorthand.
+ posix_ere_original = re.sub(r"\\s", "[[:space:]]", original)
+ if sys.platform == 'win32':
+ posix_ere_original = posix_ere_original.replace('"', '""')
+ out, err = subprocess.Popen(
+ ['git', 'grep', '-E', '--name-only', posix_ere_original,
+ '--'] + file_globs,
+ stdout=subprocess.PIPE,
+ shell=_USE_SHELL).communicate()
+ referees = out.splitlines()
+
+ for referee in referees:
+ with open(referee) as f:
+ original_contents = f.read()
+ contents = re.sub(original, replacement, original_contents)
+ if contents == original_contents:
+ raise Exception('No change in file %s although matched in grep' %
+ referee)
+ with open(referee, 'wb') as f:
+ f.write(contents)
+
+ return referees
+
+
+def main():
+ parser = optparse.OptionParser(usage='''
+(1) %prog <options> REGEXP REPLACEMENT
+REGEXP uses full Python regexp syntax. REPLACEMENT can use back-references.
+
+(2) %prog <options> -i <file>
+<file> should contain a list (in Python syntax) of
+[REGEXP, REPLACEMENT, [GLOBS]] lists, e.g.:
+[
+ [r"(foo|bar)", r"\1baz", ["*.cc", "*.h"]],
+ ["54", "42"],
+]
+As shown above, [GLOBS] can be omitted for a given search-replace list, in which
+case the corresponding search-replace will use the globs specified on the
+command line.''')
+ parser.add_option('-d', action='store_true',
+ dest='use_default_glob',
+ help='Perform the change on C++ and Objective-C(++) source '
+ 'and header files.')
+ parser.add_option('-f', action='store_true',
+ dest='force_unsafe_run',
+ help='Perform the run even if there are uncommitted local '
+ 'changes.')
+ parser.add_option('-g', action='append',
+ type='string',
+ default=[],
+ metavar="<glob>",
+ dest='user_supplied_globs',
+ help='Perform the change on the specified glob. Can be '
+ 'specified multiple times, in which case the globs are '
+ 'unioned.')
+ parser.add_option('-i', "--input_file",
+ type='string',
+ action='store',
+ default='',
+ metavar="<file>",
+ dest='input_filename',
+ help='Read arguments from <file> rather than the command '
+ 'line. NOTE: To be sure of regular expressions being '
+ 'interpreted correctly, use raw strings.')
+ opts, args = parser.parse_args()
+ if opts.use_default_glob and opts.user_supplied_globs:
+ print '"-d" and "-g" cannot be used together'
+ parser.print_help()
+ return 1
+
+ from_file = opts.input_filename != ""
+ if (from_file and len(args) != 0) or (not from_file and len(args) != 2):
+ parser.print_help()
+ return 1
+
+ if not opts.force_unsafe_run:
+ out, err = subprocess.Popen(['git', 'status', '--porcelain'],
+ stdout=subprocess.PIPE,
+ shell=_USE_SHELL).communicate()
+ if out:
+ print 'ERROR: This tool does not print any confirmation prompts,'
+ print 'so you should only run it with a clean staging area and cache'
+ print 'so that reverting a bad find/replace is as easy as running'
+ print ' git checkout -- .'
+ print ''
+ print 'To override this safeguard, pass the -f flag.'
+ return 1
+
+ global_file_globs = ['*.*']
+ if opts.use_default_glob:
+ global_file_globs = ['*.cc', '*.h', '*.m', '*.mm']
+ elif opts.user_supplied_globs:
+ global_file_globs = opts.user_supplied_globs
+
+ # Construct list of search-replace tasks.
+ search_replace_tasks = []
+ if opts.input_filename == '':
+ original = args[0]
+ replacement = args[1]
+ search_replace_tasks.append([original, replacement, global_file_globs])
+ else:
+ f = open(opts.input_filename)
+ search_replace_tasks = eval("".join(f.readlines()))
+ for task in search_replace_tasks:
+ if len(task) == 2:
+ task.append(global_file_globs)
+ f.close()
+
+ for (original, replacement, file_globs) in search_replace_tasks:
+ print 'File globs: %s' % file_globs
+ print 'Original: %s' % original
+ print 'Replacement: %s' % replacement
+ MultiFileFindReplace(original, replacement, file_globs)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/git/move_source_file.bat b/chromium/tools/git/move_source_file.bat
new file mode 100755
index 00000000000..bc3d7978e01
--- /dev/null
+++ b/chromium/tools/git/move_source_file.bat
@@ -0,0 +1,6 @@
+@echo off
+setlocal
+:: This is required with cygwin only.
+PATH=%~dp0;%PATH%
+set PYTHONDONTWRITEBYTECODE=1
+call python "%~dp0move_source_file.py" %*
diff --git a/chromium/tools/git/move_source_file.py b/chromium/tools/git/move_source_file.py
new file mode 100755
index 00000000000..1a953f3c42b
--- /dev/null
+++ b/chromium/tools/git/move_source_file.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Moves C++ files to a new location, updating any include paths that
+point to them, and re-ordering headers as needed. If multiple source
+files are specified, the destination must be a directory (and must end
+in a slash). Updates include guards in moved header files. Assumes
+Chromium coding style.
+
+Attempts to update paths used in .gyp(i) files, but does not reorder
+or restructure .gyp(i) files in any way.
+
+Updates full-path references to files in // comments in source files.
+
+Must run in a git checkout, as it relies on git grep for a fast way to
+find files that reference the moved file.
+"""
+
+
+import optparse
+import os
+import re
+import subprocess
+import sys
+
+import mffr
+
+if __name__ == '__main__':
+ # Need to add the directory containing sort-headers.py to the Python
+ # classpath.
+ sys.path.append(os.path.abspath(os.path.join(sys.path[0], '..')))
+sort_headers = __import__('sort-headers')
+
+
+HANDLED_EXTENSIONS = ['.cc', '.mm', '.h', '.hh']
+
+
+def IsHandledFile(path):
+ return os.path.splitext(path)[1] in HANDLED_EXTENSIONS
+
+def MakeDestinationPath(from_path, to_path):
+ """Given the from and to paths, return a correct destination path.
+
+ The initial destination path may either a full path or a directory,
+ in which case the path must end with /. Also does basic sanity
+ checks.
+ """
+ if not IsHandledFile(from_path):
+ raise Exception('Only intended to move individual source files. (%s)' %
+ from_path)
+ dest_extension = os.path.splitext(to_path)[1]
+ if dest_extension not in HANDLED_EXTENSIONS:
+ if to_path.endswith('/') or to_path.endswith('\\'):
+ to_path += os.path.basename(from_path)
+ else:
+ raise Exception('Destination must be either full path or end with /.')
+ return to_path
+
+
+def MoveFile(from_path, to_path):
+ """Performs a git mv command to move a file from |from_path| to |to_path|.
+ """
+ if not os.system('git mv %s %s' % (from_path, to_path)) == 0:
+ raise Exception('Fatal: Failed to run git mv command.')
+
+
+def UpdatePostMove(from_path, to_path):
+ """Given a file that has moved from |from_path| to |to_path|,
+ updates the moved file's include guard to match the new path and
+ updates all references to the file in other source files. Also tries
+ to update references in .gyp(i) files using a heuristic.
+ """
+ # Include paths always use forward slashes.
+ from_path = from_path.replace('\\', '/')
+ to_path = to_path.replace('\\', '/')
+
+ if os.path.splitext(from_path)[1] in ['.h', '.hh']:
+ UpdateIncludeGuard(from_path, to_path)
+
+ # Update include/import references.
+ files_with_changed_includes = mffr.MultiFileFindReplace(
+ r'(#(include|import)\s*["<])%s([>"])' % re.escape(from_path),
+ r'\1%s\3' % to_path,
+ ['*.cc', '*.h', '*.m', '*.mm'])
+
+ # Reorder headers in files that changed.
+ for changed_file in files_with_changed_includes:
+ def AlwaysConfirm(a, b): return True
+ sort_headers.FixFileWithConfirmFunction(changed_file, AlwaysConfirm, True)
+
+ # Update comments; only supports // comments, which are primarily
+ # used in our code.
+ #
+ # This work takes a bit of time. If this script starts feeling too
+ # slow, one good way to speed it up is to make the comment handling
+ # optional under a flag.
+ mffr.MultiFileFindReplace(
+ r'(//.*)%s' % re.escape(from_path),
+ r'\1%s' % to_path,
+ ['*.cc', '*.h', '*.m', '*.mm'])
+
+ # Update references in .gyp(i) files.
+ def PathMinusFirstComponent(path):
+ """foo/bar/baz -> bar/baz"""
+ parts = re.split(r"[/\\]", path, 1)
+ if len(parts) == 2:
+ return parts[1]
+ else:
+ return parts[0]
+ mffr.MultiFileFindReplace(
+ r'([\'"])%s([\'"])' % re.escape(PathMinusFirstComponent(from_path)),
+ r'\1%s\2' % PathMinusFirstComponent(to_path),
+ ['*.gyp*'])
+
+
+def MakeIncludeGuardName(path_from_root):
+ """Returns an include guard name given a path from root."""
+ guard = path_from_root.replace('/', '_')
+ guard = guard.replace('\\', '_')
+ guard = guard.replace('.', '_')
+ guard += '_'
+ return guard.upper()
+
+
+def UpdateIncludeGuard(old_path, new_path):
+ """Updates the include guard in a file now residing at |new_path|,
+ previously residing at |old_path|, with an up-to-date include guard.
+
+ Prints a warning if the update could not be completed successfully (e.g.,
+ because the old include guard was not formatted correctly per Chromium style).
+ """
+ old_guard = MakeIncludeGuardName(old_path)
+ new_guard = MakeIncludeGuardName(new_path)
+
+ with open(new_path) as f:
+ contents = f.read()
+
+ new_contents = contents.replace(old_guard, new_guard)
+ # The file should now have three instances of the new guard: two at the top
+ # of the file plus one at the bottom for the comment on the #endif.
+ if new_contents.count(new_guard) != 3:
+ print ('WARNING: Could not successfully update include guard; perhaps '
+ 'old guard is not per style guide? You will have to update the '
+ 'include guard manually. (%s)' % new_path)
+
+ with open(new_path, 'w') as f:
+ f.write(new_contents)
+
+
+def main():
+ if not os.path.isdir('.git'):
+ print 'Fatal: You must run from the root of a git checkout.'
+ return 1
+
+ parser = optparse.OptionParser(usage='%prog FROM_PATH... TO_PATH')
+ parser.add_option('--already_moved', action='store_true',
+ dest='already_moved',
+ help='Causes the script to skip moving the file.')
+ parser.add_option('--no_error_for_non_source_file', action='store_false',
+ default='True',
+ dest='error_for_non_source_file',
+ help='Causes the script to simply print a warning on '
+ 'encountering a non-source file rather than raising an '
+ 'error.')
+ opts, args = parser.parse_args()
+
+ if len(args) < 2:
+ parser.print_help()
+ return 1
+
+ if len(args) > 2 and not args[-1].endswith('/'):
+ print 'Target %s is not a directory.' % args[-1]
+ print
+ parser.print_help()
+ return 1
+
+ for from_path in args[:len(args)-1]:
+ if not opts.error_for_non_source_file and not IsHandledFile(from_path):
+ print '%s does not appear to be a source file, skipping' % (from_path)
+ continue
+ to_path = MakeDestinationPath(from_path, args[-1])
+ if not opts.already_moved:
+ MoveFile(from_path, to_path)
+ UpdatePostMove(from_path, to_path)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/git/post-checkout b/chromium/tools/git/post-checkout
new file mode 100755
index 00000000000..452eb48eb45
--- /dev/null
+++ b/chromium/tools/git/post-checkout
@@ -0,0 +1,22 @@
+#!/bin/bash
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+script=$(readlink $0)
+source $(dirname ${script:-$0})/git-utils.sh
+
+old_ref=$1 # Previous HEAD.
+new_ref=$2 # Current HEAD.
+branch_switch=$3 # Whether we switched branches.
+
+if [ $old_ref == $new_ref ]; then
+ if ! git diff-index --quiet HEAD $(git rev-parse --show-cdup)DEPS; then
+ warn "DEPS has local modifications; do you need to re-run gclient sync?"
+ fi
+else
+ if git diff-tree $old_ref $new_ref | grep -qs $'\tDEPS$'; then
+ warn "DEPS has changed; you probably need to re-run gclient sync."
+ fi
+fi
+
diff --git a/chromium/tools/git/post-merge b/chromium/tools/git/post-merge
new file mode 100755
index 00000000000..8b774ce6593
--- /dev/null
+++ b/chromium/tools/git/post-merge
@@ -0,0 +1,12 @@
+#!/bin/bash
+# Copyright (c) 2010 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+script=$(readlink $0)
+source $(dirname ${script:-$0})/git-utils.sh
+
+if git diff-tree ORIG_HEAD HEAD | grep -qs $'\tDEPS$'; then
+ warn "DEPS has changed; you probably need to re-run gclient sync."
+fi
+
diff --git a/chromium/tools/git/update-copyrights.sh b/chromium/tools/git/update-copyrights.sh
new file mode 100755
index 00000000000..ac69bd53e64
--- /dev/null
+++ b/chromium/tools/git/update-copyrights.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+echo 'Updating copyrights is no longer necessary.'
+echo 'See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/8p4JKV76kig/OiFYFjuZ6nAJ'
diff --git a/chromium/tools/gn/BUILD.gn b/chromium/tools/gn/BUILD.gn
new file mode 100644
index 00000000000..17be36c0f4f
--- /dev/null
+++ b/chromium/tools/gn/BUILD.gn
@@ -0,0 +1,174 @@
+static_library("gn_lib") {
+ sources = [
+ "binary_target_generator.cc",
+ "binary_target_generator.h",
+ "build_settings.cc",
+ "build_settings.h",
+ "command_desc.cc",
+ "command_gen.cc",
+ "command_help.cc",
+ "commands.cc",
+ "commands.h",
+ "config.cc",
+ "config.h",
+ "config_values.cc",
+ "config_values.h",
+ "config_values_extractors.cc",
+ "config_values_extractors.h",
+ "config_values_generator.cc",
+ "config_values_generator.h",
+ "copy_target_generator.cc",
+ "copy_target_generator.h",
+ "err.cc",
+ "err.h",
+ "escape.cc",
+ "escape.h",
+ "file_template.cc",
+ "file_template.h",
+ "filesystem_utils.cc",
+ "filesystem_utils.h",
+ "functions.cc",
+ "functions.h",
+ "functions_target.cc",
+ "function_exec_script.cc",
+ "function_process_file_template.cc",
+ "function_read_file.cc",
+ "function_set_default_toolchain.cc",
+ "function_template.cc",
+ "function_toolchain.cc",
+ "function_write_file.cc",
+ "group_target_generator.cc",
+ "group_target_generator.h",
+ "import_manager.cc",
+ "import_manager.h",
+ "input_conversion.cc",
+ "input_conversion.h",
+ "input_file.cc",
+ "input_file.h",
+ "input_file_manager.cc",
+ "input_file_manager.h",
+ "item.cc",
+ "item.h",
+ "item_node.cc",
+ "item_node.h",
+ "item_tree.cc",
+ "item_tree.h",
+ "label.cc",
+ "label.h",
+ "location.h",
+ "ninja_binary_target_writer.cc",
+ "ninja_binary_target_writer.h",
+ "ninja_build_writer.cc",
+ "ninja_build_writer.h",
+ "ninja_copy_target_writer.cc",
+ "ninja_copy_target_writer.h",
+ "ninja_group_target_writer.cc",
+ "ninja_group_target_writer.h",
+ "ninja_helper.cc",
+ "ninja_helper.h",
+ "ninja_script_target_writer.cc",
+ "ninja_script_target_writer.h",
+ "ninja_target_writer.cc",
+ "ninja_target_writer.h",
+ "ninja_toolchain_writer.cc",
+ "ninja_toolchain_writer.h",
+ "ninja_writer.cc",
+ "ninja_writer.h",
+ "operators.cc",
+ "operators.h",
+ "output_file.h",
+ "parse_tree.cc",
+ "parse_tree.h",
+ "parser.cc",
+ "parser.h",
+ "path_output.cc",
+ "path_output.h",
+ "pattern.cc",
+ "pattern.h",
+ "scheduler.cc",
+ "scheduler.h",
+ "scope.cc",
+ "scope.h",
+ "scope_per_file_provider.cc",
+ "scope_per_file_provider.h",
+ "script_target_generator.cc",
+ "script_target_generator.h",
+ "script_values.cc",
+ "script_values.h",
+ "settings.cc",
+ "settings.h",
+ "setup.cc",
+ "setup.h",
+ "source_dir.cc",
+ "source_dir.h",
+ "source_file.cc",
+ "source_file.h",
+ "standard_out.cc",
+ "standard_out.h",
+ "string_utils.cc",
+ "string_utils.h",
+ "target.cc",
+ "target.h",
+ "target_generator.cc",
+ "target_generator.h",
+ "target_manager.cc",
+ "target_manager.h",
+ "token.cc",
+ "token.h",
+ "tokenizer.cc",
+ "tokenizer.h",
+ "toolchain.cc",
+ "toolchain.h",
+ "toolchain_manager.cc",
+ "toolchain_manager.h",
+ "value.cc",
+ "value.h",
+ "value_extractors.cc",
+ "value_extractors.h",
+ "variables.cc",
+ "variables.h",
+ ]
+ deps = [
+ "//base",
+ "//base/third_party/dynamic_annotations",
+ ]
+}
+
+executable("gn") {
+ sources = [
+ "gn_main.cc",
+ ]
+ deps = [
+ ":gn_lib",
+ ]
+}
+
+test("gn_unittests") {
+ sources = [
+ "escape_unittest.cc",
+ "file_template_unittest.cc",
+ "filesystem_utils_unittest.cc",
+ "input_conversion_unittest.cc",
+ "label_unittest.cc",
+ "ninja_helper_unittest.cc",
+ "parser_unittest.cc",
+ "path_output_unittest.cc",
+ "pattern_unittest.cc",
+ "source_dir_unittest.cc",
+ "string_utils_unittest.cc",
+ "target_generator_unittest.cc",
+ "target_manager_unittest.cc",
+ "tokenizer_unittest.cc",
+ ]
+ deps = [
+ ":gn_lib",
+ "//base:run_all_unittests",
+ "//base:test_support_base",
+ "//testing:gtest",
+ ]
+}
+
+executable("generate_test_gn_data") {
+ sources = [ "generate_test_gn_data.cc" ]
+ deps = [ "//base" ]
+}
diff --git a/chromium/tools/gn/OWNERS b/chromium/tools/gn/OWNERS
new file mode 100644
index 00000000000..06fefbf4ecc
--- /dev/null
+++ b/chromium/tools/gn/OWNERS
@@ -0,0 +1 @@
+brettw@chromium.org
diff --git a/chromium/tools/gn/README.txt b/chromium/tools/gn/README.txt
new file mode 100644
index 00000000000..0a637bf4772
--- /dev/null
+++ b/chromium/tools/gn/README.txt
@@ -0,0 +1,7 @@
+GN "Generate Ninja"
+
+This tool is an experimental metabuildsystem. It is not currently in a state
+where it is ready for public consumption.
+
+It is not currently used in the build and there are currently no plans to
+replace GYP.
diff --git a/chromium/tools/gn/binary_target_generator.cc b/chromium/tools/gn/binary_target_generator.cc
new file mode 100644
index 00000000000..d7e488a5a6c
--- /dev/null
+++ b/chromium/tools/gn/binary_target_generator.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/binary_target_generator.h"
+
+#include "tools/gn/config_values_generator.h"
+#include "tools/gn/err.h"
+
+BinaryTargetGenerator::BinaryTargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Target::OutputType type,
+ Err* err)
+ : TargetGenerator(target, scope, function_token, err),
+ output_type_(type) {
+}
+
+BinaryTargetGenerator::~BinaryTargetGenerator() {
+}
+
+void BinaryTargetGenerator::DoRun() {
+ target_->set_output_type(output_type_);
+
+ FillSources();
+ FillConfigs();
+
+ // Config values (compiler flags, etc.) set directly on this target.
+ ConfigValuesGenerator gen(&target_->config_values(), scope_,
+ function_token_, input_directory_, err_);
+ gen.Run();
+ if (err_->has_error())
+ return;
+
+ SetToolchainDependency();
+}
diff --git a/chromium/tools/gn/binary_target_generator.h b/chromium/tools/gn/binary_target_generator.h
new file mode 100644
index 00000000000..dacb4974bd5
--- /dev/null
+++ b/chromium/tools/gn/binary_target_generator.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_BINARY_TARGET_GENERATOR_H_
+#define TOOLS_GN_BINARY_TARGET_GENERATOR_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/target_generator.h"
+
+// Populates a Target with the values from a binary rule (executable, shared
+// library, or static library).
+class BinaryTargetGenerator : public TargetGenerator {
+ public:
+ BinaryTargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Target::OutputType type,
+ Err* err);
+ virtual ~BinaryTargetGenerator();
+
+ protected:
+ virtual void DoRun() OVERRIDE;
+
+ private:
+ Target::OutputType output_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(BinaryTargetGenerator);
+};
+
+#endif // TOOLS_GN_BINARY_TARGET_GENERATOR_H_
+
diff --git a/chromium/tools/gn/build_settings.cc b/chromium/tools/gn/build_settings.cc
new file mode 100644
index 00000000000..09b4c99589c
--- /dev/null
+++ b/chromium/tools/gn/build_settings.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/build_settings.h"
+
+#include "tools/gn/filesystem_utils.h"
+
+BuildSettings::BuildSettings()
+ : item_tree_(),
+ target_manager_(this),
+ toolchain_manager_(this) {
+}
+
+BuildSettings::~BuildSettings() {
+}
+
+void BuildSettings::SetSecondarySourcePath(const SourceDir& d) {
+ secondary_source_path_ = GetFullPath(d);
+}
+
+void BuildSettings::SetBuildDir(const SourceDir& d) {
+ build_dir_ = d;
+ build_to_source_dir_string_ = InvertDir(d);
+}
+
+base::FilePath BuildSettings::GetFullPath(const SourceFile& file) const {
+ return file.Resolve(root_path_);
+}
+
+base::FilePath BuildSettings::GetFullPath(const SourceDir& dir) const {
+ return dir.Resolve(root_path_);
+}
+
+base::FilePath BuildSettings::GetFullPathSecondary(
+ const SourceFile& file) const {
+ return file.Resolve(secondary_source_path_);
+}
+
+base::FilePath BuildSettings::GetFullPathSecondary(
+ const SourceDir& dir) const {
+ return dir.Resolve(secondary_source_path_);
+}
+
diff --git a/chromium/tools/gn/build_settings.h b/chromium/tools/gn/build_settings.h
new file mode 100644
index 00000000000..fe0426674be
--- /dev/null
+++ b/chromium/tools/gn/build_settings.h
@@ -0,0 +1,110 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_BUILD_SETTINGS_H_
+#define TOOLS_GN_BUILD_SETTINGS_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "tools/gn/item_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/source_dir.h"
+#include "tools/gn/source_file.h"
+#include "tools/gn/target_manager.h"
+#include "tools/gn/toolchain_manager.h"
+
+// Settings for one build, which is one toplevel output directory. There
+// may be multiple Settings objects that refer to this, one for each toolchain.
+class BuildSettings {
+ public:
+ typedef base::Callback<void(const Target*)> TargetResolvedCallback;
+
+ BuildSettings();
+ ~BuildSettings();
+
+ // Absolute path of the source root on the local system. Everything is
+ // relative to this.
+ const base::FilePath& root_path() const { return root_path_; }
+ void set_root_path(const base::FilePath& r) { root_path_ = r; }
+
+ // When nonempty, specifies a parallel directory higherarchy in which to
+ // search for buildfiles if they're not found in the root higherarchy. This
+ // allows us to keep buildfiles in a separate tree during development.
+ const base::FilePath& secondary_source_path() const {
+ return secondary_source_path_;
+ }
+ void SetSecondarySourcePath(const SourceDir& d);
+
+ // Path of the python executable to run scripts with.
+ base::FilePath python_path() const { return python_path_; }
+ void set_python_path(const base::FilePath& p) { python_path_ = p; }
+
+ const SourceFile& build_config_file() const { return build_config_file_; }
+ void set_build_config_file(const SourceFile& f) { build_config_file_ = f; }
+
+ // The build directory is the root of all output files. The default toolchain
+ // files go into here, and non-default toolchains will have separate
+ // toolchain-specific root directories inside this.
+ const SourceDir& build_dir() const { return build_dir_; }
+ void SetBuildDir(const SourceDir& dir);
+
+ // The inverse of relative_build_dir, ending with a separator.
+ // Example: relative_build_dir_ = "out/Debug/" this will be "../../"
+ const std::string& build_to_source_dir_string() const {
+ return build_to_source_dir_string_;
+ }
+
+ // These accessors do not return const objects since the resulting objects
+ // are threadsafe. In this setting, we use constness primarily to ensure
+ // that the Settings object is used in a threadsafe manner. Although this
+ // violates the concept of logical constness, that's less important in our
+ // application, and actually implementing this in a way that preserves
+ // logical constness is cumbersome.
+ ItemTree& item_tree() const { return item_tree_; }
+ TargetManager& target_manager() const { return target_manager_; }
+ ToolchainManager& toolchain_manager() const { return toolchain_manager_; }
+
+ // Returns the full absolute OS path cooresponding to the given file in the
+ // root source tree.
+ base::FilePath GetFullPath(const SourceFile& file) const;
+ base::FilePath GetFullPath(const SourceDir& dir) const;
+
+ // Returns the absolute OS path inside the secondary source path. Will return
+ // an empty FilePath if the secondary source path is empty. When loading a
+ // buildfile, the GetFullPath should always be consulted first.
+ base::FilePath GetFullPathSecondary(const SourceFile& file) const;
+ base::FilePath GetFullPathSecondary(const SourceDir& dir) const;
+
+ // This is the callback to execute when a target is marked resolved. If we
+ // don't need to do anything, this will be null. When a target is resolved,
+ // this callback should be posted to the scheduler pool so the work is
+ // distributed properly.
+ const TargetResolvedCallback& target_resolved_callback() const {
+ return target_resolved_callback_;
+ }
+ void set_target_resolved_callback(const TargetResolvedCallback& cb) {
+ target_resolved_callback_ = cb;
+ }
+
+ private:
+ base::FilePath root_path_;
+ base::FilePath secondary_source_path_;
+ base::FilePath python_path_;
+
+ SourceFile build_config_file_;
+ SourceDir build_dir_;
+ std::string build_to_source_dir_string_;
+
+ TargetResolvedCallback target_resolved_callback_;
+
+ // See getters above.
+ mutable ItemTree item_tree_;
+ mutable TargetManager target_manager_;
+ mutable ToolchainManager toolchain_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(BuildSettings);
+};
+
+#endif // TOOLS_GN_BUILD_SETTINGS_H_
diff --git a/chromium/tools/gn/command_desc.cc b/chromium/tools/gn/command_desc.cc
new file mode 100644
index 00000000000..dd78b84b7ee
--- /dev/null
+++ b/chromium/tools/gn/command_desc.cc
@@ -0,0 +1,344 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <set>
+#include <sstream>
+
+#include "base/command_line.h"
+#include "tools/gn/commands.h"
+#include "tools/gn/config.h"
+#include "tools/gn/config_values_extractors.h"
+#include "tools/gn/item.h"
+#include "tools/gn/item_node.h"
+#include "tools/gn/label.h"
+#include "tools/gn/setup.h"
+#include "tools/gn/standard_out.h"
+#include "tools/gn/target.h"
+
+namespace commands {
+
+namespace {
+
+struct CompareTargetLabel {
+ bool operator()(const Target* a, const Target* b) const {
+ return a->label() < b->label();
+ }
+};
+
+void RecursiveCollectDeps(const Target* target, std::set<Label>* result) {
+ if (result->find(target->label()) != result->end())
+ return; // Already did this target.
+ result->insert(target->label());
+
+ const std::vector<const Target*>& deps = target->deps();
+ for (size_t i = 0; i < deps.size(); i++)
+ RecursiveCollectDeps(deps[i], result);
+
+ const std::vector<const Target*>& datadeps = target->datadeps();
+ for (size_t i = 0; i < datadeps.size(); i++)
+ RecursiveCollectDeps(datadeps[i], result);
+}
+
+// Prints dependencies of the given target (not the target itself).
+void RecursivePrintDeps(const Target* target,
+ const Label& default_toolchain,
+ int indent_level) {
+ std::vector<const Target*> sorted_deps = target->deps();
+ const std::vector<const Target*> datadeps = target->datadeps();
+ for (size_t i = 0; i < datadeps.size(); i++)
+ sorted_deps.push_back(datadeps[i]);
+ std::sort(sorted_deps.begin(), sorted_deps.end(), CompareTargetLabel());
+
+ std::string indent(indent_level * 2, ' ');
+ for (size_t i = 0; i < sorted_deps.size(); i++) {
+ OutputString(indent +
+ sorted_deps[i]->label().GetUserVisibleName(default_toolchain) + "\n");
+ RecursivePrintDeps(sorted_deps[i], default_toolchain, indent_level + 1);
+ }
+}
+
+void PrintDeps(const Target* target, bool display_header) {
+ const CommandLine* cmdline = CommandLine::ForCurrentProcess();
+ Label toolchain_label = target->label().GetToolchainLabel();
+
+ // Tree mode is separate.
+ if (cmdline->HasSwitch("tree")) {
+ if (display_header)
+ OutputString("\nDependency tree:\n");
+ RecursivePrintDeps(target, toolchain_label, 1);
+ return;
+ }
+
+ // Collect the deps to display.
+ std::vector<Label> deps;
+ if (cmdline->HasSwitch("all")) {
+ if (display_header)
+ OutputString("\nAll recursive dependencies:\n");
+
+ std::set<Label> all_deps;
+ RecursiveCollectDeps(target, &all_deps);
+ for (std::set<Label>::iterator i = all_deps.begin();
+ i != all_deps.end(); ++i)
+ deps.push_back(*i);
+ } else {
+ if (display_header) {
+ OutputString("\nDirect dependencies "
+ "(try also \"--all\" and \"--tree\"):\n");
+ }
+
+ const std::vector<const Target*>& target_deps = target->deps();
+ for (size_t i = 0; i < target_deps.size(); i++)
+ deps.push_back(target_deps[i]->label());
+
+ const std::vector<const Target*>& target_datadeps = target->datadeps();
+ for (size_t i = 0; i < target_datadeps.size(); i++)
+ deps.push_back(target_datadeps[i]->label());
+ }
+
+ std::sort(deps.begin(), deps.end());
+ for (size_t i = 0; i < deps.size(); i++)
+ OutputString(" " + deps[i].GetUserVisibleName(toolchain_label) + "\n");
+}
+
+void PrintConfigs(const Target* target, bool display_header) {
+ // Configs (don't sort since the order determines how things are processed).
+ if (display_header)
+ OutputString("\nConfigs (in order applying):\n");
+
+ Label toolchain_label = target->label().GetToolchainLabel();
+ const std::vector<const Config*>& configs = target->configs();
+ for (size_t i = 0; i < configs.size(); i++) {
+ OutputString(" " +
+ configs[i]->label().GetUserVisibleName(toolchain_label) + "\n");
+ }
+}
+
+void PrintSources(const Target* target, bool display_header) {
+ if (display_header)
+ OutputString("\nSources:\n");
+
+ Target::FileList sources = target->sources();
+ std::sort(sources.begin(), sources.end());
+ for (size_t i = 0; i < sources.size(); i++)
+ OutputString(" " + sources[i].value() + "\n");
+}
+
+// Attempts to attribute the gen dependency of the given target to some source
+// code and outputs the string to the output stream.
+//
+// The attribution of the source of the dependencies is stored in the ItemNode
+// which is the parallel structure to the target dependency map, so we have
+// to jump through a few loops to find everything.
+void OutputSourceOfDep(const Target* target,
+ const Label& dep_label,
+ std::ostream& out) {
+ ItemTree& item_tree = target->settings()->build_settings()->item_tree();
+ base::AutoLock lock(item_tree.lock());
+
+ ItemNode* target_node = item_tree.GetExistingNodeLocked(target->label());
+ CHECK(target_node);
+ ItemNode* dep_node = item_tree.GetExistingNodeLocked(dep_label);
+ CHECK(dep_node);
+
+ const ItemNode::ItemNodeMap& direct_deps = target_node->direct_dependencies();
+ ItemNode::ItemNodeMap::const_iterator found = direct_deps.find(dep_node);
+ if (found == direct_deps.end())
+ return;
+
+ const Location& location = found->second.begin();
+ out << " (Added by " + location.file()->name().value() << ":"
+ << location.line_number() << ")\n";
+}
+
+// Templatized writer for writing out different config value types.
+template<typename T> struct DescValueWriter {};
+template<> struct DescValueWriter<std::string> {
+ void operator()(const std::string& str, std::ostream& out) const {
+ out << " " << str << "\n";
+ }
+};
+template<> struct DescValueWriter<SourceFile> {
+ void operator()(const SourceFile& file, std::ostream& out) const {
+ out << " " << file.value() << "\n";
+ }
+};
+template<> struct DescValueWriter<SourceDir> {
+ void operator()(const SourceDir& dir, std::ostream& out) const {
+ out << " " << dir.value() << "\n";
+ }
+};
+
+// Writes a given config value type to the string, optionally with attribution.
+// This should match RecursiveTargetConfigToStream in the order it traverses.
+template<typename T> void OutputRecursiveTargetConfig(
+ const Target* target,
+ const char* header_name,
+ const std::vector<T>& (ConfigValues::* getter)() const) {
+ bool display_blame = CommandLine::ForCurrentProcess()->HasSwitch("blame");
+
+ DescValueWriter<T> writer;
+ std::ostringstream out;
+
+ // First write the values from the config itself.
+ if (!(target->config_values().*getter)().empty()) {
+ if (display_blame)
+ out << " From " << target->label().GetUserVisibleName(false) << "\n";
+ ConfigValuesToStream(target->config_values(), getter, writer, out);
+ }
+
+ // TODO(brettw) annotate where forced config includes came from!
+
+ // Then write the configs in order.
+ for (size_t i = 0; i < target->configs().size(); i++) {
+ const Config* config = target->configs()[i];
+ const ConfigValues& values = config->config_values();
+
+ if (!(values.*getter)().empty()) {
+ if (display_blame) {
+ out << " From " << config->label().GetUserVisibleName(false) << "\n";
+ OutputSourceOfDep(target, config->label(), out);
+ }
+ ConfigValuesToStream(values, getter, writer, out);
+ }
+ }
+
+ std::string out_str = out.str();
+ if (!out_str.empty()) {
+ OutputString(std::string(header_name) + "\n");
+ OutputString(out_str);
+ }
+}
+
+} // namespace
+
+// desc ------------------------------------------------------------------------
+
+const char kDesc[] = "desc";
+const char kDesc_HelpShort[] =
+ "desc: Show lots of insightful information about a target.";
+const char kDesc_Help[] =
+ "gn desc <target label> [<what to show>] [--blame] [--all | --tree]\n"
+ " Displays information about a given labeled target.\n"
+ "\n"
+ "Possibilities for <what to show>:\n"
+ " (If unspecified an overall summary will be displayed.)\n"
+ "\n"
+ " sources\n"
+ " Source files.\n"
+ "\n"
+ " configs\n"
+ " Shows configs applied to the given target, sorted in the order\n"
+ " they're specified. This includes both configs specified in the\n"
+ " \"configs\" variable, as well as configs pushed onto this target\n"
+ " via dependencies specifying \"all\" or \"direct\" dependent\n"
+ " configs.\n"
+ "\n"
+ " deps [--all | --tree]\n"
+ " Show immediate (or, when \"--all\" or \"--tree\" is specified,\n"
+ " recursive) dependencies of the given target. \"--tree\" shows them\n"
+ " in a tree format. Otherwise, they will be sorted alphabetically.\n"
+ " Both \"deps\" and \"datadeps\" will be included.\n"
+ "\n"
+ " defines [--blame]\n"
+ " includes [--blame]\n"
+ " cflags [--blame]\n"
+ " cflags_cc [--blame]\n"
+ " cflags_cxx [--blame]\n"
+ " ldflags [--blame]\n"
+ " Shows the given values taken from the target and all configs\n"
+ " applying. See \"--blame\" below.\n"
+ "\n"
+ " --blame\n"
+ " Used with any value specified by a config, this will name\n"
+ " the config that specified the value.\n"
+ "\n"
+ "Note:\n"
+ " This command will show the full name of directories and source files,\n"
+ " but when directories and source paths are written to the build file,\n"
+ " they will be adjusted to be relative to the build directory. So the\n"
+ " values for paths displayed by this command won't match (but should\n"
+ " mean the same thing.\n"
+ "\n"
+ "Examples:\n"
+ " gn desc //base:base\n"
+ " Summarizes the given target.\n"
+ "\n"
+ " gn desc :base_unittests deps --tree\n"
+ " Shows a dependency tree of the \"base_unittests\" project in\n"
+ " the current directory.\n"
+ "\n"
+ " gn desc //base defines --blame\n"
+ " Shows defines set for the //base:base target, annotated by where\n"
+ " each one was set from.\n";
+
+int RunDesc(const std::vector<std::string>& args) {
+ if (args.size() != 1 && args.size() != 2) {
+ Err(Location(), "You're holding it wrong.",
+ "Usage: \"gn desc <target_name> <what to display>\"").PrintToStdout();
+ return 1;
+ }
+
+ const Target* target = GetTargetForDesc(args);
+ if (!target)
+ return 1;
+
+#define CONFIG_VALUE_HANDLER(name) \
+ } else if (what == #name) { \
+ OutputRecursiveTargetConfig(target, #name, &ConfigValues::name);
+
+ if (args.size() == 2) {
+ // User specified one thing to display.
+ const std::string& what = args[1];
+ if (what == "configs") {
+ PrintConfigs(target, false);
+ } else if (what == "sources") {
+ PrintSources(target, false);
+ } else if (what == "deps") {
+ PrintDeps(target, false);
+
+ CONFIG_VALUE_HANDLER(defines)
+ CONFIG_VALUE_HANDLER(includes)
+ CONFIG_VALUE_HANDLER(cflags)
+ CONFIG_VALUE_HANDLER(cflags_c)
+ CONFIG_VALUE_HANDLER(cflags_cc)
+ CONFIG_VALUE_HANDLER(ldflags)
+
+ } else {
+ OutputString("Don't know how to display \"" + what + "\".\n");
+ return 1;
+ }
+
+#undef CONFIG_VALUE_HANDLER
+ return 0;
+ }
+
+ // Display summary.
+
+ // Generally we only want to display toolchains on labels when the toolchain
+ // is different than the default one for this target (which we always print
+ // in the header).
+ Label target_toolchain = target->label().GetToolchainLabel();
+
+ // Header.
+ std::string title_target =
+ "Target: " + target->label().GetUserVisibleName(false);
+ std::string title_toolchain =
+ "Toolchain: " + target_toolchain.GetUserVisibleName(false);
+ OutputString(title_target + "\n", DECORATION_YELLOW);
+ OutputString(title_toolchain + "\n", DECORATION_YELLOW);
+ OutputString(std::string(
+ std::max(title_target.size(), title_toolchain.size()), '=') + "\n");
+
+ PrintSources(target, true);
+ PrintConfigs(target, true);
+ OutputString("\n (Use \"gn desc <label> <thing you want to see>\" to show "
+ "the actual values\n applied by the different configs. "
+ "See \"gn help desc\" for more.)\n");
+ PrintDeps(target, true);
+
+ return 0;
+}
+
+} // namespace commands
diff --git a/chromium/tools/gn/command_gen.cc b/chromium/tools/gn/command_gen.cc
new file mode 100644
index 00000000000..7d8203d267f
--- /dev/null
+++ b/chromium/tools/gn/command_gen.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/atomicops.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/commands.h"
+#include "tools/gn/ninja_target_writer.h"
+#include "tools/gn/ninja_writer.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/setup.h"
+#include "tools/gn/standard_out.h"
+
+namespace commands {
+
+namespace {
+
+// Suppress output on success.
+const char kSwitchQuiet[] = "q";
+
+void TargetResolvedCallback(base::subtle::Atomic32* write_counter,
+ const Target* target) {
+ base::subtle::NoBarrier_AtomicIncrement(write_counter, 1);
+ NinjaTargetWriter::RunAndWriteFile(target);
+}
+
+} // namespace
+
+const char kGen[] = "gen";
+const char kGen_HelpShort[] =
+ "gen: Generate ninja files.";
+const char kGen_Help[] =
+ "gn gen\n"
+ " Generates ninja files from the current tree.\n"
+ "\n"
+ " See \"gn help\" for the common command-line switches.\n";
+
+int RunGen(const std::vector<std::string>& args) {
+ base::TimeTicks begin_time = base::TimeTicks::Now();
+
+ // Deliberately leaked to avoid expensive process teardown.
+ Setup* setup = new Setup;
+ if (!setup->DoSetup())
+ return 1;
+
+ // Cause the load to also generate the ninja files for each target. We wrap
+ // the writing to maintain a counter.
+ base::subtle::Atomic32 write_counter = 0;
+ setup->build_settings().set_target_resolved_callback(
+ base::Bind(&TargetResolvedCallback, &write_counter));
+
+ // Do the actual load. This will also write out the target ninja files.
+ if (!setup->Run())
+ return 1;
+
+ // Write the root ninja files.
+ if (!NinjaWriter::RunAndWriteFiles(&setup->build_settings()))
+ return 1;
+
+ base::TimeTicks end_time = base::TimeTicks::Now();
+
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(kSwitchQuiet)) {
+ OutputString("Done. ", DECORATION_GREEN);
+
+ std::string stats = "Wrote " +
+ base::IntToString(static_cast<int>(write_counter)) +
+ " targets from " +
+ base::IntToString(
+ setup->scheduler().input_file_manager()->GetInputFileCount()) +
+ " files in " +
+ base::IntToString((end_time - begin_time).InMilliseconds()) + "ms\n";
+ OutputString(stats);
+ }
+
+ return 0;
+}
+
+} // namespace commands
diff --git a/chromium/tools/gn/command_help.cc b/chromium/tools/gn/command_help.cc
new file mode 100644
index 00000000000..2abef9fcd90
--- /dev/null
+++ b/chromium/tools/gn/command_help.cc
@@ -0,0 +1,156 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <iostream>
+
+#include "tools/gn/commands.h"
+#include "tools/gn/err.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/input_conversion.h"
+#include "tools/gn/setup.h"
+#include "tools/gn/standard_out.h"
+#include "tools/gn/variables.h"
+
+namespace commands {
+
+namespace {
+
+// Prints a line for a command, assuming there is a colon. Everything before
+// the colon is the command (and is highlighted) and everything after it is
+// normal.
+void PrintShortHelp(const std::string& line) {
+ size_t colon_offset = line.find(':');
+ size_t first_normal = 0;
+ if (colon_offset != std::string::npos) {
+ OutputString(" " + line.substr(0, colon_offset), DECORATION_YELLOW);
+ first_normal = colon_offset;
+ }
+ OutputString(line.substr(first_normal) + "\n");
+}
+
+void PrintToplevelHelp() {
+ OutputString("Commands (type \"gn help <command>\" for more details):\n");
+
+ const commands::CommandInfoMap& command_map = commands::GetCommands();
+ for (commands::CommandInfoMap::const_iterator i = command_map.begin();
+ i != command_map.end(); ++i)
+ PrintShortHelp(i->second.help_short);
+
+ OutputString(
+ "\n"
+ " When run with no arguments \"gn gen\" is assumed.\n"
+ "\n"
+ "Common switches:\n"
+ " -q: Quiet mode, don't print anything on success.\n"
+ " --root: Specifies source root (overrides .gn file).\n"
+ " --secondary: Specifies secondary source root (overrides .gn file).\n"
+ " -v: Verbose mode, print lots of logging.\n");
+
+ // Functions.
+ OutputString("\nBuildfile functions (type \"gn help <function>\" for more "
+ "details):\n");
+ const functions::FunctionInfoMap& function_map = functions::GetFunctions();
+ std::vector<std::string> sorted_functions;
+ for (functions::FunctionInfoMap::const_iterator i = function_map.begin();
+ i != function_map.end(); ++i)
+ sorted_functions.push_back(i->first.as_string());
+ std::sort(sorted_functions.begin(), sorted_functions.end());
+ for (size_t i = 0; i < sorted_functions.size(); i++)
+ OutputString(" " + sorted_functions[i] + "\n", DECORATION_YELLOW);
+
+ // Built-in variables.
+ OutputString("\nBuilt-in predefined variables (type \"gn help <variable>\" "
+ "for more details):\n");
+ const variables::VariableInfoMap& builtin_vars =
+ variables::GetBuiltinVariables();
+ for (variables::VariableInfoMap::const_iterator i = builtin_vars.begin();
+ i != builtin_vars.end(); ++i)
+ PrintShortHelp(i->second.help_short);
+
+ // Target variables.
+ OutputString("\nVariables you set in targets (type \"gn help <variable>\" "
+ "for more details):\n");
+ const variables::VariableInfoMap& target_vars =
+ variables::GetTargetVariables();
+ for (variables::VariableInfoMap::const_iterator i = target_vars.begin();
+ i != target_vars.end(); ++i)
+ PrintShortHelp(i->second.help_short);
+
+ OutputString("\nOther help topics:\n");
+ PrintShortHelp("dotfile: Info about the toplevel .gn file.");
+ PrintShortHelp(
+ "input_conversion: Processing input from exec_script and read_file.");
+}
+
+} // namespace
+
+const char kHelp[] = "help";
+const char kHelp_HelpShort[] =
+ "help: Does what you think.";
+const char kHelp_Help[] =
+ "gn help <anything>\n"
+ " Yo dawg, I heard you like help on your help so I put help on the help\n"
+ " in the help.\n";
+
+int RunHelp(const std::vector<std::string>& args) {
+ if (args.size() == 0) {
+ PrintToplevelHelp();
+ return 0;
+ }
+
+ // Check commands.
+ const commands::CommandInfoMap& command_map = commands::GetCommands();
+ commands::CommandInfoMap::const_iterator found_command =
+ command_map.find(args[0]);
+ if (found_command != command_map.end()) {
+ OutputString(found_command->second.help);
+ return 0;
+ }
+
+ // Check functions.
+ const functions::FunctionInfoMap& function_map = functions::GetFunctions();
+ functions::FunctionInfoMap::const_iterator found_function =
+ function_map.find(args[0]);
+ if (found_function != function_map.end()) {
+ OutputString(found_function->second.help);
+ return 0;
+ }
+
+ // Builtin variables.
+ const variables::VariableInfoMap& builtin_vars =
+ variables::GetBuiltinVariables();
+ variables::VariableInfoMap::const_iterator found_builtin_var =
+ builtin_vars.find(args[0]);
+ if (found_builtin_var != builtin_vars.end()) {
+ OutputString(found_builtin_var->second.help);
+ return 0;
+ }
+
+ // Target variables.
+ const variables::VariableInfoMap& target_vars =
+ variables::GetTargetVariables();
+ variables::VariableInfoMap::const_iterator found_target_var =
+ target_vars.find(args[0]);
+ if (found_target_var != target_vars.end()) {
+ OutputString(found_target_var->second.help);
+ return 0;
+ }
+
+ // Random other topics.
+ if (args[0] == "input_conversion") {
+ OutputString(kInputConversion_Help);
+ return 0;
+ } if (args[0] == "dotfile") {
+ OutputString(kDotfile_Help);
+ return 0;
+ }
+
+ // No help on this.
+ Err(Location(), "No help on \"" + args[0] + "\".").PrintToStdout();
+ RunHelp(std::vector<std::string>());
+ return 1;
+}
+
+} // namespace commands
diff --git a/chromium/tools/gn/commands.cc b/chromium/tools/gn/commands.cc
new file mode 100644
index 00000000000..cfa55cb2c82
--- /dev/null
+++ b/chromium/tools/gn/commands.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/commands.h"
+
+#include "tools/gn/item.h"
+#include "tools/gn/item_node.h"
+#include "tools/gn/label.h"
+#include "tools/gn/setup.h"
+#include "tools/gn/standard_out.h"
+#include "tools/gn/target.h"
+
+namespace commands {
+
+CommandInfo::CommandInfo()
+ : help_short(NULL),
+ help(NULL),
+ runner(NULL) {
+}
+
+CommandInfo::CommandInfo(const char* in_help_short,
+ const char* in_help,
+ CommandRunner in_runner)
+ : help_short(in_help_short),
+ help(in_help),
+ runner(in_runner) {
+}
+
+const CommandInfoMap& GetCommands() {
+ static CommandInfoMap info_map;
+ if (info_map.empty()) {
+ #define INSERT_COMMAND(cmd) \
+ info_map[k##cmd] = CommandInfo(k##cmd##_HelpShort, \
+ k##cmd##_Help, \
+ &Run##cmd);
+
+ INSERT_COMMAND(Desc)
+ INSERT_COMMAND(Gen)
+ INSERT_COMMAND(Help)
+
+ #undef INSERT_COMMAND
+ }
+ return info_map;
+}
+
+const Target* GetTargetForDesc(const std::vector<std::string>& args) {
+ // Deliberately leaked to avoid expensive process teardown.
+ Setup* setup = new Setup;
+ if (!setup->DoSetup())
+ return NULL;
+
+ // FIXME(brettw): set the output dir to be a sandbox one to avoid polluting
+ // the real output dir with files written by the build scripts.
+
+ // Do the actual load. This will also write out the target ninja files.
+ if (!setup->Run())
+ return NULL;
+
+ // Need to resolve the label after we know the default toolchain.
+ // TODO(brettw) find the current directory and resolve the input label
+ // relative to that.
+ Label default_toolchain = setup->build_settings().toolchain_manager()
+ .GetDefaultToolchainUnlocked();
+ Value arg_value(NULL, args[0]);
+ Err err;
+ Label label = Label::Resolve(SourceDir(), default_toolchain, arg_value, &err);
+ if (err.has_error()) {
+ err.PrintToStdout();
+ return NULL;
+ }
+
+ ItemNode* node;
+ {
+ base::AutoLock lock(setup->build_settings().item_tree().lock());
+ node = setup->build_settings().item_tree().GetExistingNodeLocked(label);
+ }
+ if (!node) {
+ Err(Location(), "",
+ "I don't know about this \"" + label.GetUserVisibleName(false) +
+ "\"").PrintToStdout();
+ return NULL;
+ }
+
+ const Target* target = node->item()->AsTarget();
+ if (!target) {
+ Err(Location(), "Not a target.",
+ "The \"" + label.GetUserVisibleName(false) + "\" thing\n"
+ "is not a target. Somebody should probably implement this command for "
+ "other\nitem types.");
+ return NULL;
+ }
+
+ return target;
+}
+
+} // namespace commands
diff --git a/chromium/tools/gn/commands.h b/chromium/tools/gn/commands.h
new file mode 100644
index 00000000000..1a303898762
--- /dev/null
+++ b/chromium/tools/gn/commands.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_COMMANDS_H_
+#define TOOLS_GN_COMMANDS_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/strings/string_piece.h"
+
+class Target;
+
+// Each "Run" command returns the value we should return from main().
+
+namespace commands {
+
+typedef int (*CommandRunner)(const std::vector<std::string>&);
+
+extern const char kDesc[];
+extern const char kDesc_HelpShort[];
+extern const char kDesc_Help[];
+int RunDesc(const std::vector<std::string>& args);
+
+extern const char kGen[];
+extern const char kGen_HelpShort[];
+extern const char kGen_Help[];
+int RunGen(const std::vector<std::string>& args);
+
+extern const char kHelp[];
+extern const char kHelp_HelpShort[];
+extern const char kHelp_Help[];
+int RunHelp(const std::vector<std::string>& args);
+
+// -----------------------------------------------------------------------------
+
+struct CommandInfo {
+ CommandInfo();
+ CommandInfo(const char* in_help_short,
+ const char* in_help,
+ CommandRunner in_runner);
+
+ const char* help_short;
+ const char* help;
+ CommandRunner runner;
+};
+
+typedef std::map<base::StringPiece, CommandInfo> CommandInfoMap;
+
+const CommandInfoMap& GetCommands();
+
+// Helper functions for some commands ------------------------------------------
+
+// Runs a build for the given command line, returning the target identified by
+// the first non-switch command line parameter.
+//
+// Note that a lot of memory is leaked to avoid proper teardown under the
+// assumption that you will only run this once and exit.
+//
+// On failure, prints an error message and returns NULL.
+const Target* GetTargetForDesc(const std::vector<std::string>& args);
+
+} // namespace commands
+
+#endif // TOOLS_GN_COMMANDS_H_
diff --git a/chromium/tools/gn/config.cc b/chromium/tools/gn/config.cc
new file mode 100644
index 00000000000..6edba24a7ca
--- /dev/null
+++ b/chromium/tools/gn/config.cc
@@ -0,0 +1,80 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/config.h"
+
+#include "tools/gn/err.h"
+#include "tools/gn/input_file_manager.h"
+#include "tools/gn/item_node.h"
+#include "tools/gn/item_tree.h"
+#include "tools/gn/scheduler.h"
+
+Config::Config(const Label& label) : Item(label) {
+}
+
+Config::~Config() {
+}
+
+Config* Config::AsConfig() {
+ return this;
+}
+
+const Config* Config::AsConfig() const {
+ return this;
+}
+
+// static
+Config* Config::GetConfig(const Settings* settings,
+ const LocationRange& specified_from_here,
+ const Label& label,
+ Item* dep_from,
+ Err* err) {
+ DCHECK(!label.is_null());
+
+ ItemTree* tree = &settings->build_settings()->item_tree();
+ base::AutoLock lock(tree->lock());
+
+ ItemNode* node = tree->GetExistingNodeLocked(label);
+ Config* config = NULL;
+ if (!node) {
+ config = new Config(label);
+ node = new ItemNode(config);
+ tree->AddNodeLocked(node);
+
+ // Only schedule loading the given target if somebody is depending on it
+ // (and we optimize by not re-asking it to run the current file).
+ // Otherwise, we're probably generating it right now.
+ if (dep_from && dep_from->label().dir() != label.dir()) {
+ settings->build_settings()->toolchain_manager().ScheduleInvocationLocked(
+ specified_from_here, label.GetToolchainLabel(), label.dir(),
+ err);
+ }
+ } else if ((config = node->item()->AsConfig())) {
+ // Previously saw this item as a config.
+
+ // If we have no dep_from, we're generating it. In this case, it had better
+ // not already be generated.
+ if (!dep_from && node->state() != ItemNode::REFERENCED) {
+ *err = Err(specified_from_here, "Duplicate config definition.",
+ "You already told me about a config with this name.");
+ return NULL;
+ }
+ } else {
+ // Previously saw this thing as a non-config.
+ *err = Err(specified_from_here,
+ "Config name already used.",
+ "Previously you specified a " +
+ node->item()->GetItemTypeName() + " with this name instead.");
+ return NULL;
+ }
+
+ // Keep a record of the guy asking us for this dependency. We know if
+ // somebody is adding a dependency, that guy it himself not resolved.
+ if (dep_from) {
+ if (!tree->GetExistingNodeLocked(dep_from->label())->AddDependency(
+ settings->build_settings(), specified_from_here, node, err))
+ return NULL;
+ }
+ return config;
+}
diff --git a/chromium/tools/gn/config.h b/chromium/tools/gn/config.h
new file mode 100644
index 00000000000..0ee9b7ba36a
--- /dev/null
+++ b/chromium/tools/gn/config.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_CONFIG_H_
+#define TOOLS_GN_CONFIG_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/config_values.h"
+#include "tools/gn/item.h"
+
+class Err;
+class ItemTree;
+class LocationRange;
+class Settings;
+
+// Represents a named config in the dependency graph.
+class Config : public Item {
+ public:
+ Config(const Label& label);
+ virtual ~Config();
+
+ virtual Config* AsConfig() OVERRIDE;
+ virtual const Config* AsConfig() const OVERRIDE;
+
+ ConfigValues& config_values() { return config_values_; }
+ const ConfigValues& config_values() const { return config_values_; }
+
+ // Gets or creates a config.
+ //
+ // This is like the TargetManager is for Targets, but Configs are so much
+ // simpler that this one function is all we need.
+ static Config* GetConfig(const Settings* settings,
+ const LocationRange& specified_from_here,
+ const Label& label,
+ Item* dep_from,
+ Err* err);
+
+ private:
+ ConfigValues config_values_;
+
+ DISALLOW_COPY_AND_ASSIGN(Config);
+};
+
+#endif // TOOLS_GN_CONFIG_H_
diff --git a/chromium/tools/gn/config_values.cc b/chromium/tools/gn/config_values.cc
new file mode 100644
index 00000000000..53466dfd791
--- /dev/null
+++ b/chromium/tools/gn/config_values.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/config_values.h"
+
+ConfigValues::ConfigValues() {
+}
+
+ConfigValues::~ConfigValues() {
+}
diff --git a/chromium/tools/gn/config_values.h b/chromium/tools/gn/config_values.h
new file mode 100644
index 00000000000..9a0aad25f91
--- /dev/null
+++ b/chromium/tools/gn/config_values.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_CONFIG_VALUES_H_
+#define TOOLS_GN_CONFIG_VALUES_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "tools/gn/source_dir.h"
+
+// Holds the values (includes, defines, compiler flags, etc.) for a given
+// config or target.
+class ConfigValues {
+ public:
+ ConfigValues();
+ ~ConfigValues();
+
+ const std::vector<SourceDir>& includes() const { return includes_; }
+ void swap_in_includes(std::vector<SourceDir>* lo) { includes_.swap(*lo); }
+
+#define VALUES_ACCESSOR(name) \
+ const std::vector<std::string>& name() const { return name##_; } \
+ void swap_in_##name(std::vector<std::string>* v) { name##_.swap(*v); }
+
+ VALUES_ACCESSOR(defines)
+ VALUES_ACCESSOR(cflags)
+ VALUES_ACCESSOR(cflags_c)
+ VALUES_ACCESSOR(cflags_cc)
+ VALUES_ACCESSOR(cflags_objc)
+ VALUES_ACCESSOR(cflags_objcc)
+ VALUES_ACCESSOR(ldflags)
+
+#undef VALUES_ACCESSOR
+
+ private:
+ std::vector<SourceDir> includes_;
+ std::vector<std::string> defines_;
+ std::vector<std::string> cflags_;
+ std::vector<std::string> cflags_c_;
+ std::vector<std::string> cflags_cc_;
+ std::vector<std::string> cflags_objc_;
+ std::vector<std::string> cflags_objcc_;
+ std::vector<std::string> ldflags_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfigValues);
+};
+
+#endif // TOOLS_GN_CONFIG_VALUES_H_
diff --git a/chromium/tools/gn/config_values_extractors.cc b/chromium/tools/gn/config_values_extractors.cc
new file mode 100644
index 00000000000..646e2d7bb2e
--- /dev/null
+++ b/chromium/tools/gn/config_values_extractors.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/config_values_extractors.h"
+
+#include "tools/gn/escape.h"
+
+namespace {
+
+class EscapedStringWriter {
+ public:
+ EscapedStringWriter(const EscapeOptions& escape_options)
+ : escape_options_(escape_options) {
+ }
+
+ void operator()(const std::string& s, std::ostream& out) const {
+ out << " ";
+ EscapeStringToStream(out, s, escape_options_);
+ }
+
+ private:
+ const EscapeOptions& escape_options_;
+};
+
+} // namespace
+
+void RecursiveTargetConfigStringsToStream(
+ const Target* target,
+ const std::vector<std::string>& (ConfigValues::* getter)() const,
+ const EscapeOptions& escape_options,
+ std::ostream& out) {
+ RecursiveTargetConfigToStream(target, getter,
+ EscapedStringWriter(escape_options), out);
+}
diff --git a/chromium/tools/gn/config_values_extractors.h b/chromium/tools/gn/config_values_extractors.h
new file mode 100644
index 00000000000..1b3e52c4469
--- /dev/null
+++ b/chromium/tools/gn/config_values_extractors.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_
+#define TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_
+
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "tools/gn/config.h"
+#include "tools/gn/config_values.h"
+#include "tools/gn/target.h"
+
+struct EscapeOptions;
+
+template<typename T, class Writer>
+inline void ConfigValuesToStream(
+ const ConfigValues& values,
+ const std::vector<T>& (ConfigValues::* getter)() const,
+ const Writer& writer,
+ std::ostream& out) {
+ const std::vector<T>& v = (values.*getter)();
+ for (size_t i = 0; i < v.size(); i++)
+ writer(v[i], out);
+};
+
+// Writes a given config value that applies to a given target. This collects
+// all values from the target itself and all configs that apply, and writes
+// then in order.
+template<typename T, class Writer>
+inline void RecursiveTargetConfigToStream(
+ const Target* target,
+ const std::vector<T>& (ConfigValues::* getter)() const,
+ const Writer& writer,
+ std::ostream& out) {
+ // Note: if you make any changes to this, also change the writer in the
+ // implementation of the "desc" command.
+
+ // First write the values from the config itself.
+ ConfigValuesToStream(target->config_values(), getter, writer, out);
+
+ // Then write the configs in order.
+ for (size_t i = 0; i < target->configs().size(); i++) {
+ ConfigValuesToStream(target->configs()[i]->config_values(), getter,
+ writer, out);
+ }
+}
+
+// Writes the values out as strings with no transformation.
+void RecursiveTargetConfigStringsToStream(
+ const Target* target,
+ const std::vector<std::string>& (ConfigValues::* getter)() const,
+ const EscapeOptions& escape_options,
+ std::ostream& out);
+
+#endif // TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_
diff --git a/chromium/tools/gn/config_values_generator.cc b/chromium/tools/gn/config_values_generator.cc
new file mode 100644
index 00000000000..46c9e88cb7d
--- /dev/null
+++ b/chromium/tools/gn/config_values_generator.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/config_values_generator.h"
+
+#include "tools/gn/config_values.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/value.h"
+#include "tools/gn/value_extractors.h"
+
+namespace {
+
+void GetStringList(
+ Scope* scope,
+ const char* var_name,
+ ConfigValues* config_values,
+ void (ConfigValues::* swapper_inner)(std::vector<std::string>*),
+ Err* err) {
+ const Value* value = scope->GetValue(var_name, true);
+ if (!value)
+ return; // No value, empty input and succeed.
+
+ std::vector<std::string> result;
+ ExtractListOfStringValues(*value, &result, err);
+ (config_values->*swapper_inner)(&result);
+}
+
+} // namespace
+
+ConfigValuesGenerator::ConfigValuesGenerator(ConfigValues* dest_values,
+ Scope* scope,
+ const Token& function_token,
+ const SourceDir& input_dir,
+ Err* err)
+ : config_values_(dest_values),
+ scope_(scope),
+ function_token_(function_token),
+ input_dir_(input_dir),
+ err_(err) {
+}
+
+ConfigValuesGenerator::~ConfigValuesGenerator() {
+}
+
+void ConfigValuesGenerator::Run() {
+ FillIncludes();
+
+#define FILL_CONFIG_VALUE(name) \
+ GetStringList(scope_, #name, config_values_, \
+ &ConfigValues::swap_in_##name, err_);
+
+ FILL_CONFIG_VALUE(defines)
+ FILL_CONFIG_VALUE(cflags)
+ FILL_CONFIG_VALUE(cflags_c)
+ FILL_CONFIG_VALUE(cflags_cc)
+ FILL_CONFIG_VALUE(cflags_objc)
+ FILL_CONFIG_VALUE(cflags_objcc)
+ FILL_CONFIG_VALUE(ldflags)
+
+#undef FILL_CONFIG_VALUE
+}
+
+void ConfigValuesGenerator::FillIncludes() {
+ const Value* value = scope_->GetValue("includes", true);
+ if (!value)
+ return; // No value, empty input and succeed.
+
+ std::vector<SourceDir> includes;
+ if (!ExtractListOfRelativeDirs(*value, input_dir_, &includes, err_))
+ return;
+ config_values_->swap_in_includes(&includes);
+}
diff --git a/chromium/tools/gn/config_values_generator.h b/chromium/tools/gn/config_values_generator.h
new file mode 100644
index 00000000000..fb5bf750cea
--- /dev/null
+++ b/chromium/tools/gn/config_values_generator.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_CONFIG_VALUES_GENERATOR_H_
+#define TOOLS_GN_CONFIG_VALUES_GENERATOR_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "tools/gn/source_dir.h"
+
+class ConfigValues;
+class Err;
+class Scope;
+class Token;
+
+class ConfigValuesGenerator {
+ public:
+ ConfigValuesGenerator(ConfigValues* dest_values,
+ Scope* scope,
+ const Token& function_token,
+ const SourceDir& input_dir,
+ Err* err);
+ ~ConfigValuesGenerator();
+
+ // Sets the error passed to the constructor on failure.
+ void Run();
+
+ private:
+ void FillIncludes();
+
+ ConfigValues* config_values_;
+ Scope* scope_;
+ const Token& function_token_;
+ const SourceDir input_dir_;
+ Err* err_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfigValuesGenerator);
+};
+
+#endif // TOOLS_GN_CONFIG_VALUES_GENERATOR_H_
diff --git a/chromium/tools/gn/copy_target_generator.cc b/chromium/tools/gn/copy_target_generator.cc
new file mode 100644
index 00000000000..6347ca23ac8
--- /dev/null
+++ b/chromium/tools/gn/copy_target_generator.cc
@@ -0,0 +1,47 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/copy_target_generator.h"
+
+#include "tools/gn/build_settings.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/value.h"
+
+CopyTargetGenerator::CopyTargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Err* err)
+ : TargetGenerator(target, scope, function_token, err) {
+}
+
+CopyTargetGenerator::~CopyTargetGenerator() {
+}
+
+void CopyTargetGenerator::DoRun() {
+ target_->set_output_type(Target::COPY_FILES);
+
+ FillSources();
+ FillDestDir();
+
+ SetToolchainDependency();
+}
+
+void CopyTargetGenerator::FillDestDir() {
+ // Destdir is required for all targets that use it.
+ const Value* value = scope_->GetValue("destdir", true);
+ if (!value) {
+ *err_ = Err(function_token_, "This target type requires a \"destdir\".");
+ return;
+ }
+ if (!value->VerifyTypeIs(Value::STRING, err_))
+ return;
+
+ if (!EnsureStringIsInOutputDir(
+ GetBuildSettings()->build_dir(),
+ value->string_value(), *value, err_))
+ return;
+ target_->set_destdir(SourceDir(value->string_value()));
+}
+
diff --git a/chromium/tools/gn/copy_target_generator.h b/chromium/tools/gn/copy_target_generator.h
new file mode 100644
index 00000000000..b6f7e14b2b1
--- /dev/null
+++ b/chromium/tools/gn/copy_target_generator.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_COPY_TARGET_GENERATOR_H_
+#define TOOLS_GN_COPY_TARGET_GENERATOR_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/target_generator.h"
+
+// Populates a Target with the values from a copy rule.
+class CopyTargetGenerator : public TargetGenerator {
+ public:
+ CopyTargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Err* err);
+ virtual ~CopyTargetGenerator();
+
+ protected:
+ virtual void DoRun() OVERRIDE;
+
+ private:
+ void FillDestDir();
+
+ DISALLOW_COPY_AND_ASSIGN(CopyTargetGenerator);
+};
+
+#endif // TOOLS_GN_COPY_TARGET_GENERATOR_H_
+
diff --git a/chromium/tools/gn/err.cc b/chromium/tools/gn/err.cc
new file mode 100644
index 00000000000..068ea6ddce4
--- /dev/null
+++ b/chromium/tools/gn/err.cc
@@ -0,0 +1,196 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/err.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/standard_out.h"
+#include "tools/gn/tokenizer.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+std::string GetNthLine(const base::StringPiece& data, int n) {
+ size_t line_off = Tokenizer::ByteOffsetOfNthLine(data, n);
+ size_t end = line_off + 1;
+ while (end < data.size() && !Tokenizer::IsNewline(data, end))
+ end++;
+ return data.substr(line_off, end - line_off).as_string();
+}
+
+void FillRangeOnLine(const LocationRange& range, int line_number,
+ std::string* line) {
+ // Only bother if the range's begin or end overlaps the line. If the entire
+ // line is highlighted as a result of this range, it's not very helpful.
+ if (range.begin().line_number() != line_number &&
+ range.end().line_number() != line_number)
+ return;
+
+ // Watch out, the char offsets in the location are 1-based, so we have to
+ // subtract 1.
+ int begin_char;
+ if (range.begin().line_number() < line_number)
+ begin_char = 0;
+ else
+ begin_char = range.begin().char_offset() - 1;
+
+ int end_char;
+ if (range.end().line_number() > line_number)
+ end_char = line->size(); // Ending is non-inclusive.
+ else
+ end_char = range.end().char_offset() - 1;
+
+ CHECK(end_char >= begin_char);
+ CHECK(begin_char >= 0 && begin_char <= static_cast<int>(line->size()));
+ CHECK(end_char >= 0 && end_char <= static_cast<int>(line->size()));
+ for (int i = begin_char; i < end_char; i++)
+ line->at(i) = '-';
+}
+
+// The line length is used to clip the maximum length of the markers we'll
+// make if the error spans more than one line (like unterminated literals).
+void OutputHighlighedPosition(const Location& location,
+ const Err::RangeList& ranges,
+ size_t line_length) {
+ // Make a buffer of the line in spaces.
+ std::string highlight;
+ highlight.resize(line_length);
+ for (size_t i = 0; i < line_length; i++)
+ highlight[i] = ' ';
+
+ // Highlight all the ranges on the line.
+ for (size_t i = 0; i < ranges.size(); i++)
+ FillRangeOnLine(ranges[i], location.line_number(), &highlight);
+
+ // Allow the marker to be one past the end of the line for marking the end.
+ highlight.push_back(' ');
+ CHECK(location.char_offset() - 1 >= 0 &&
+ location.char_offset() - 1 < static_cast<int>(highlight.size()));
+ highlight[location.char_offset() - 1] = '^';
+
+ // Trim unused spaces from end of line.
+ while (!highlight.empty() && highlight[highlight.size() - 1] == ' ')
+ highlight.resize(highlight.size() - 1);
+
+ highlight += "\n";
+ OutputString(highlight, DECORATION_BLUE);
+}
+
+} // namespace
+
+Err::Err() : has_error_(false) {
+}
+
+Err::Err(const Location& location,
+ const std::string& msg,
+ const std::string& help)
+ : has_error_(true),
+ location_(location),
+ message_(msg),
+ help_text_(help) {
+}
+
+Err::Err(const LocationRange& range,
+ const std::string& msg,
+ const std::string& help)
+ : has_error_(true),
+ location_(range.begin()),
+ message_(msg),
+ help_text_(help) {
+ ranges_.push_back(range);
+}
+
+Err::Err(const Token& token,
+ const std::string& msg,
+ const std::string& help)
+ : has_error_(true),
+ location_(token.location()),
+ message_(msg),
+ help_text_(help) {
+ ranges_.push_back(token.range());
+}
+
+Err::Err(const ParseNode* node,
+ const std::string& msg,
+ const std::string& help_text)
+ : has_error_(true),
+ message_(msg),
+ help_text_(help_text) {
+ // Node will be null in certain tests.
+ if (node) {
+ LocationRange range = node->GetRange();
+ location_ = range.begin();
+ ranges_.push_back(range);
+ }
+}
+
+Err::Err(const Value& value,
+ const std::string msg,
+ const std::string& help_text)
+ : has_error_(true),
+ message_(msg),
+ help_text_(help_text) {
+ if (value.origin()) {
+ LocationRange range = value.origin()->GetRange();
+ location_ = range.begin();
+ ranges_.push_back(range);
+ }
+}
+
+Err::~Err() {
+}
+
+void Err::PrintToStdout() const {
+ InternalPrintToStdout(false);
+}
+
+void Err::AppendSubErr(const Err& err) {
+ sub_errs_.push_back(err);
+}
+
+void Err::InternalPrintToStdout(bool is_sub_err) const {
+ DCHECK(has_error_);
+
+ if (!is_sub_err)
+ OutputString("ERROR ", DECORATION_RED);
+
+ // File name and location.
+ const InputFile* input_file = location_.file();
+ std::string loc_str;
+ if (input_file) {
+ std::string path8;
+ path8.assign(input_file->name().value());
+
+ if (is_sub_err)
+ loc_str = "See ";
+ else
+ loc_str = "at ";
+ loc_str += path8 + ": " +
+ base::IntToString(location_.line_number()) + ":" +
+ base::IntToString(location_.char_offset()) + ": ";
+ }
+ OutputString(loc_str + message_ + "\n");
+
+ // Quoted line.
+ if (input_file) {
+ std::string line = GetNthLine(input_file->contents(),
+ location_.line_number());
+ if (!ContainsOnlyWhitespaceASCII(line)) {
+ OutputString(line + "\n", DECORATION_BOLD);
+ OutputHighlighedPosition(location_, ranges_, line.size());
+ }
+ }
+
+ // Optional help text.
+ if (!help_text_.empty())
+ OutputString(help_text_ + "\n");
+
+ // Sub errors.
+ for (size_t i = 0; i < sub_errs_.size(); i++)
+ sub_errs_[i].InternalPrintToStdout(true);
+}
diff --git a/chromium/tools/gn/err.h b/chromium/tools/gn/err.h
new file mode 100644
index 00000000000..3e077e9fb89
--- /dev/null
+++ b/chromium/tools/gn/err.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_ERR_H_
+#define TOOLS_GN_ERR_H_
+
+#include <string>
+#include <vector>
+
+#include "tools/gn/location.h"
+#include "tools/gn/token.h"
+
+class ParseNode;
+class Value;
+
+// Result of doing some operation. Check has_error() to see if an error
+// occurred.
+//
+// An error has a location and a message. Below that, is some optional help
+// text to go with the annotation of the location.
+//
+// An error can also have sub-errors which are additionally printed out
+// below. They can provide additional context.
+class Err {
+ public:
+ typedef std::vector<LocationRange> RangeList;
+
+ // Indicates no error.
+ Err();
+
+ // Error at a single point.
+ Err(const Location& location,
+ const std::string& msg,
+ const std::string& help = std::string());
+
+ // Error at a given range.
+ Err(const LocationRange& range,
+ const std::string& msg,
+ const std::string& help = std::string());
+
+ // Error at a given token.
+ Err(const Token& token,
+ const std::string& msg,
+ const std::string& help_text = std::string());
+
+ // Error at a given node.
+ Err(const ParseNode* node,
+ const std::string& msg,
+ const std::string& help_text = std::string());
+
+ // Error at a given value.
+ Err(const Value& value,
+ const std::string msg,
+ const std::string& help_text = std::string());
+
+ ~Err();
+
+ bool has_error() const { return has_error_; }
+ const Location& location() const { return location_; }
+ const std::string& message() const { return message_; }
+ const std::string& help_text() const { return help_text_; }
+
+ void AppendRange(const LocationRange& range) { ranges_.push_back(range); }
+ const RangeList& ranges() const { return ranges_; }
+
+ void AppendSubErr(const Err& err);
+
+ void PrintToStdout() const;
+
+ private:
+ void InternalPrintToStdout(bool is_sub_err) const;
+
+ bool has_error_;
+ Location location_;
+
+ std::vector<LocationRange> ranges_;
+
+ std::string message_;
+ std::string help_text_;
+
+ std::vector<Err> sub_errs_;
+};
+
+#endif // TOOLS_GN_ERR_H_
diff --git a/chromium/tools/gn/escape.cc b/chromium/tools/gn/escape.cc
new file mode 100644
index 00000000000..5fc7b6f6a83
--- /dev/null
+++ b/chromium/tools/gn/escape.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/escape.h"
+
+#include "base/containers/stack_container.h"
+
+namespace {
+
+template<typename DestString>
+void EscapeStringToString(const base::StringPiece& str,
+ const EscapeOptions& options,
+ DestString* dest) {
+ bool used_quotes = false;
+
+ for (size_t i = 0; i < str.size(); i++) {
+ if (str[i] == '$' && options.mode == ESCAPE_NINJA) {
+ // Escape dollars signs since ninja treats these specially.
+ dest->push_back('$');
+ dest->push_back('$');
+ } else if (str[i] == '"' && options.mode == ESCAPE_SHELL) {
+ // Escape quotes with backslashes for the command-line (Ninja doesn't
+ // care).
+ dest->push_back('\\');
+ dest->push_back('"');
+ } else if (str[i] == ' ') {
+ if (options.mode == ESCAPE_NINJA) {
+ // For ninja just escape spaces with $.
+ dest->push_back('$');
+ } else if (options.mode == ESCAPE_SHELL && !options.inhibit_quoting) {
+ // For the shell, quote the whole string.
+ if (!used_quotes) {
+ used_quotes = true;
+ dest->insert(dest->begin(), '"');
+ }
+ }
+ dest->push_back(' ');
+#if defined(OS_WIN)
+ } else if (str[i] == '/' && options.convert_slashes) {
+ // Convert slashes on Windows if requested.
+ dest->push_back('\\');
+#else
+ } else if (str[i] == '\\' && options.mode == ESCAPE_SHELL) {
+ // For non-Windows shell, escape backslashes.
+ dest->push_back('\\');
+ dest->push_back('\\');
+#endif
+ } else {
+ dest->push_back(str[i]);
+ }
+ }
+
+ if (used_quotes)
+ dest->push_back('"');
+}
+
+} // namespace
+
+std::string EscapeString(const base::StringPiece& str,
+ const EscapeOptions& options) {
+ std::string result;
+ result.reserve(str.size() + 4); // Guess we'll add a couple of extra chars.
+ EscapeStringToString(str, options, &result);
+ return result;
+}
+
+void EscapeStringToStream(std::ostream& out,
+ const base::StringPiece& str,
+ const EscapeOptions& options) {
+ // Escape to a stack buffer and then write out to the stream.
+ base::StackVector<char, 256> result;
+ result->reserve(str.size() + 4); // Guess we'll add a couple of extra chars.
+ EscapeStringToString(str, options, &result.container());
+ if (!result->empty())
+ out.write(result->data(), result->size());
+}
diff --git a/chromium/tools/gn/escape.h b/chromium/tools/gn/escape.h
new file mode 100644
index 00000000000..17911613b20
--- /dev/null
+++ b/chromium/tools/gn/escape.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_ESCAPE_H_
+#define TOOLS_GN_ESCAPE_H_
+
+#include <iosfwd>
+
+#include "base/strings/string_piece.h"
+
+// TODO(brettw) we may need to make this a bitfield. If we want to write a
+// shell command in a ninja file, we need the shell characters to be escaped,
+// and THEN the ninja characters. Or maybe we require the caller to do two
+// passes.
+enum EscapingMode {
+ ESCAPE_NONE, // No escaping.
+ ESCAPE_NINJA, // Ninja string escaping.
+ ESCAPE_SHELL, // Shell string escaping.
+};
+
+struct EscapeOptions {
+ EscapeOptions()
+ : mode(ESCAPE_NONE),
+ convert_slashes(false),
+ inhibit_quoting(false) {
+ }
+
+ EscapingMode mode;
+
+ // When set, converts forward-slashes to system-specific path separators.
+ bool convert_slashes;
+
+ // When the escaping mode is ESCAPE_SHELL, the escaper will normally put
+ // quotes around things with spaces. If this value is set to true, we'll
+ // disable the quoting feature and just add the spaces.
+ //
+ // This mode is for when quoting is done at some higher-level. Defaults to
+ // false.
+ bool inhibit_quoting;
+};
+
+// Escapes the given input, returnining the result.
+std::string EscapeString(const base::StringPiece& str,
+ const EscapeOptions& options);
+
+// Same as EscapeString but writes the results to the given stream, saving a
+// copy.
+void EscapeStringToStream(std::ostream& out,
+ const base::StringPiece& str,
+ const EscapeOptions& options);
+
+#endif // TOOLS_GN_ESCAPE_H_
diff --git a/chromium/tools/gn/escape_unittest.cc b/chromium/tools/gn/escape_unittest.cc
new file mode 100644
index 00000000000..a7c19b3245e
--- /dev/null
+++ b/chromium/tools/gn/escape_unittest.cc
@@ -0,0 +1,4 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
diff --git a/chromium/tools/gn/file_template.cc b/chromium/tools/gn/file_template.cc
new file mode 100644
index 00000000000..8b5d09f2400
--- /dev/null
+++ b/chromium/tools/gn/file_template.cc
@@ -0,0 +1,125 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/file_template.h"
+
+#include "tools/gn/filesystem_utils.h"
+
+const char FileTemplate::kSource[] = "{{source}}";
+const char FileTemplate::kSourceNamePart[] = "{{source_name_part}}";
+
+FileTemplate::FileTemplate(const Value& t, Err* err) {
+ ParseInput(t, err);
+}
+
+FileTemplate::FileTemplate(const std::vector<std::string>& t) {
+ for (size_t i = 0; i < t.size(); i++)
+ ParseOneTemplateString(t[i]);
+}
+
+FileTemplate::~FileTemplate() {
+}
+
+void FileTemplate::Apply(const Value& sources,
+ const ParseNode* origin,
+ std::vector<Value>* dest,
+ Err* err) const {
+ if (!sources.VerifyTypeIs(Value::LIST, err))
+ return;
+ dest->reserve(sources.list_value().size() * templates_.container().size());
+
+ // Temporary holding place, allocate outside to re-use- buffer.
+ std::vector<std::string> string_output;
+
+ const std::vector<Value>& sources_list = sources.list_value();
+ for (size_t i = 0; i < sources_list.size(); i++) {
+ if (!sources_list[i].VerifyTypeIs(Value::STRING, err))
+ return;
+
+ ApplyString(sources_list[i].string_value(), &string_output);
+ for (size_t out_i = 0; out_i < string_output.size(); out_i++)
+ dest->push_back(Value(origin, string_output[i]));
+ }
+}
+
+void FileTemplate::ApplyString(const std::string& str,
+ std::vector<std::string>* output) const {
+ // Compute all substitutions needed so we can just do substitutions below.
+ // We skip the LITERAL one since that varies each time.
+ std::string subst[Subrange::NUM_TYPES];
+ if (types_required_[Subrange::SOURCE])
+ subst[Subrange::SOURCE] = str;
+ if (types_required_[Subrange::NAME_PART])
+ subst[Subrange::NAME_PART] = FindFilenameNoExtension(&str).as_string();
+
+ output->resize(templates_.container().size());
+ for (size_t template_i = 0;
+ template_i < templates_.container().size(); template_i++) {
+ const Template& t = templates_[template_i];
+ (*output)[template_i].clear();
+ for (size_t subrange_i = 0; subrange_i < t.container().size();
+ subrange_i++) {
+ if (t[subrange_i].type == Subrange::LITERAL)
+ (*output)[template_i].append(t[subrange_i].literal);
+ else
+ (*output)[template_i].append(subst[t[subrange_i].type]);
+ }
+ }
+}
+
+void FileTemplate::ParseInput(const Value& value, Err* err) {
+ switch (value.type()) {
+ case Value::STRING:
+ ParseOneTemplateString(value.string_value());
+ break;
+ case Value::LIST:
+ for (size_t i = 0; i < value.list_value().size(); i++) {
+ if (!value.list_value()[i].VerifyTypeIs(Value::STRING, err))
+ return;
+ ParseOneTemplateString(value.list_value()[i].string_value());
+ }
+ break;
+ default:
+ *err = Err(value, "File template must be a string or list.",
+ "A sarcastic comment about your skills goes here.");
+ }
+}
+
+void FileTemplate::ParseOneTemplateString(const std::string& str) {
+ templates_.container().resize(templates_.container().size() + 1);
+ Template& t = templates_[templates_.container().size() - 1];
+
+ size_t cur = 0;
+ while (true) {
+ size_t next = str.find("{{", cur);
+
+ // Pick up everything from the previous spot to here as a literal.
+ if (next == std::string::npos) {
+ if (cur != str.size())
+ t.container().push_back(Subrange(Subrange::LITERAL, str.substr(cur)));
+ break;
+ } else if (next > cur) {
+ t.container().push_back(
+ Subrange(Subrange::LITERAL, str.substr(cur, next - cur)));
+ }
+
+ // Decode the template param.
+ if (str.compare(next, arraysize(kSource) - 1, kSource) == 0) {
+ t.container().push_back(Subrange(Subrange::SOURCE));
+ types_required_[Subrange::SOURCE] = true;
+ cur = next + arraysize(kSource) - 1;
+ } else if (str.compare(next, arraysize(kSourceNamePart) - 1,
+ kSourceNamePart) == 0) {
+ t.container().push_back(Subrange(Subrange::NAME_PART));
+ types_required_[Subrange::NAME_PART] = true;
+ cur = next + arraysize(kSourceNamePart) - 1;
+ } else {
+ // If it's not a match, treat it like a one-char literal (this will be
+ // rare, so it's not worth the bother to add to the previous literal) so
+ // we can keep going.
+ t.container().push_back(Subrange(Subrange::LITERAL, "{"));
+ cur = next + 1;
+ }
+ }
+}
diff --git a/chromium/tools/gn/file_template.h b/chromium/tools/gn/file_template.h
new file mode 100644
index 00000000000..25d22517dc6
--- /dev/null
+++ b/chromium/tools/gn/file_template.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_FILE_TEMPLATE_H_
+#define TOOLS_GN_FILE_TEMPLATE_H_
+
+#include "base/basictypes.h"
+#include "base/containers/stack_container.h"
+#include "tools/gn/err.h"
+#include "tools/gn/value.h"
+
+class ParseNode;
+
+class FileTemplate {
+ public:
+ struct Subrange {
+ enum Type {
+ LITERAL = 0,
+ SOURCE,
+ NAME_PART,
+ NUM_TYPES // Must be last
+ };
+ Subrange(Type t, const std::string& l = std::string())
+ : type(t),
+ literal(l) {
+ }
+
+ Type type;
+
+ // When type_ == LITERAL, this specifies the literal.
+ std::string literal;
+ };
+
+ // Constructs a template from the given value. On error, the err will be
+ // set. In this case you should not use this object.
+ FileTemplate(const Value& t, Err* err);
+ FileTemplate(const std::vector<std::string>& t);
+ ~FileTemplate();
+
+ // Applies this template to the given list of sources, appending all
+ // results to the given dest list. The sources must be a list for the
+ // one that takes a value as an input, otherwise the given error will be set.
+ void Apply(const Value& sources,
+ const ParseNode* origin,
+ std::vector<Value>* dest,
+ Err* err) const;
+ void ApplyString(const std::string& input,
+ std::vector<std::string>* output) const;
+
+ // Known template types.
+ static const char kSource[];
+ static const char kSourceNamePart[];
+
+ private:
+ typedef base::StackVector<Subrange, 8> Template;
+ typedef base::StackVector<Template, 8> TemplateVector;
+
+ void ParseInput(const Value& value, Err* err);
+
+ // Parses a template string and adds it to the templates_ list.
+ void ParseOneTemplateString(const std::string& str);
+
+ TemplateVector templates_;
+
+ // The corresponding value is set to true if the given subrange type is
+ // required. This allows us to precompute these types whem applying them
+ // to a given source file.
+ bool types_required_[Subrange::NUM_TYPES];
+
+ DISALLOW_COPY_AND_ASSIGN(FileTemplate);
+};
+
+#endif // TOOLS_GN_FILE_TEMPLATE_H_
diff --git a/chromium/tools/gn/file_template_unittest.cc b/chromium/tools/gn/file_template_unittest.cc
new file mode 100644
index 00000000000..47c84f0ae52
--- /dev/null
+++ b/chromium/tools/gn/file_template_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/file_template.h"
+
+TEST(FileTemplate, Static) {
+ std::vector<std::string> templates;
+ templates.push_back("something_static");
+ FileTemplate t(templates);
+
+ std::vector<std::string> result;
+ t.ApplyString("", &result);
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ("something_static", result[0]);
+
+ t.ApplyString("lalala", &result);
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ("something_static", result[0]);
+}
+
+TEST(FileTemplate, Typical) {
+ std::vector<std::string> templates;
+ templates.push_back("foo/{{source_name_part}}.cc");
+ templates.push_back("foo/{{source_name_part}}.h");
+ FileTemplate t(templates);
+
+ std::vector<std::string> result;
+ t.ApplyString("sources/ha.idl", &result);
+ ASSERT_EQ(2u, result.size());
+ EXPECT_EQ("foo/ha.cc", result[0]);
+ EXPECT_EQ("foo/ha.h", result[1]);
+}
+
+TEST(FileTemplate, Weird) {
+ std::vector<std::string> templates;
+ templates.push_back("{{{source}}{{source}}{{");
+ FileTemplate t(templates);
+
+ std::vector<std::string> result;
+ t.ApplyString("foo/lalala.c", &result);
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ("{foo/lalala.cfoo/lalala.c{{", result[0]);
+}
diff --git a/chromium/tools/gn/filesystem_utils.cc b/chromium/tools/gn/filesystem_utils.cc
new file mode 100644
index 00000000000..230a12a2909
--- /dev/null
+++ b/chromium/tools/gn/filesystem_utils.cc
@@ -0,0 +1,371 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/filesystem_utils.h"
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "tools/gn/location.h"
+#include "tools/gn/source_dir.h"
+
+namespace {
+
+enum DotDisposition {
+ // The given dot is just part of a filename and is not special.
+ NOT_A_DIRECTORY,
+
+ // The given dot is the current directory.
+ DIRECTORY_CUR,
+
+ // The given dot is the first of a double dot that should take us up one.
+ DIRECTORY_UP
+};
+
+// When we find a dot, this function is called with the character following
+// that dot to see what it is. The return value indicates what type this dot is
+// (see above). This code handles the case where the dot is at the end of the
+// input.
+//
+// |*consumed_len| will contain the number of characters in the input that
+// express what we found.
+DotDisposition ClassifyAfterDot(const std::string& path,
+ size_t after_dot,
+ size_t* consumed_len) {
+ if (after_dot == path.size()) {
+ // Single dot at the end.
+ *consumed_len = 1;
+ return DIRECTORY_CUR;
+ }
+ if (path[after_dot] == '/') {
+ // Single dot followed by a slash.
+ *consumed_len = 2; // Consume the slash
+ return DIRECTORY_CUR;
+ }
+
+ if (path[after_dot] == '.') {
+ // Two dots.
+ if (after_dot + 1 == path.size()) {
+ // Double dot at the end.
+ *consumed_len = 2;
+ return DIRECTORY_UP;
+ }
+ if (path[after_dot + 1] == '/') {
+ // Double dot folowed by a slash.
+ *consumed_len = 3;
+ return DIRECTORY_UP;
+ }
+ }
+
+ // The dots are followed by something else, not a directory.
+ *consumed_len = 1;
+ return NOT_A_DIRECTORY;
+}
+
+} // namesapce
+
+SourceFileType GetSourceFileType(const SourceFile& file,
+ Settings::TargetOS os) {
+ base::StringPiece extension = FindExtension(&file.value());
+ if (extension == "cc" || extension == "cpp" || extension == "cxx")
+ return SOURCE_CC;
+ if (extension == "h")
+ return SOURCE_H;
+ if (extension == "c")
+ return SOURCE_C;
+
+ switch (os) {
+ case Settings::MAC:
+ if (extension == "m")
+ return SOURCE_M;
+ if (extension == "mm")
+ return SOURCE_MM;
+ break;
+
+ case Settings::WIN:
+ if (extension == "rc")
+ return SOURCE_RC;
+ break;
+
+ default:
+ break;
+ }
+
+ // TODO(brettw) asm files.
+ // TODO(brettw) weird thing with .S on non-Windows platforms.
+ return SOURCE_UNKNOWN;
+}
+
+const char* GetExtensionForOutputType(Target::OutputType type,
+ Settings::TargetOS os) {
+ switch (os) {
+ case Settings::MAC:
+ switch (type) {
+ case Target::EXECUTABLE:
+ return "";
+ case Target::SHARED_LIBRARY:
+ return "dylib";
+ case Target::STATIC_LIBRARY:
+ return "a";
+ default:
+ NOTREACHED();
+ }
+ break;
+
+ case Settings::WIN:
+ switch (type) {
+ case Target::EXECUTABLE:
+ return "exe";
+ case Target::SHARED_LIBRARY:
+ return "dll.lib"; // Extension of import library.
+ case Target::STATIC_LIBRARY:
+ return "lib";
+ default:
+ NOTREACHED();
+ }
+ break;
+
+ case Settings::LINUX:
+ switch (type) {
+ case Target::EXECUTABLE:
+ return "";
+ case Target::SHARED_LIBRARY:
+ return "so";
+ case Target::STATIC_LIBRARY:
+ return "a";
+ default:
+ NOTREACHED();
+ }
+ break;
+
+ default:
+ NOTREACHED();
+ }
+ return "";
+}
+
+std::string FilePathToUTF8(const base::FilePath& path) {
+#if defined(OS_WIN)
+ return WideToUTF8(path.value());
+#else
+ return path.value();
+#endif
+}
+
+base::FilePath UTF8ToFilePath(const base::StringPiece& sp) {
+#if defined(OS_WIN)
+ return base::FilePath(UTF8ToWide(sp));
+#else
+ return base::FilePath(sp.as_string());
+#endif
+}
+
+size_t FindExtensionOffset(const std::string& path) {
+ for (int i = static_cast<int>(path.size()); i >= 0; i--) {
+ if (path[i] == '/')
+ break;
+ if (path[i] == '.')
+ return i + 1;
+ }
+ return std::string::npos;
+}
+
+base::StringPiece FindExtension(const std::string* path) {
+ size_t extension_offset = FindExtensionOffset(*path);
+ if (extension_offset == std::string::npos)
+ return base::StringPiece();
+ return base::StringPiece(&path->data()[extension_offset],
+ path->size() - extension_offset);
+}
+
+size_t FindFilenameOffset(const std::string& path) {
+ for (int i = static_cast<int>(path.size()) - 1; i >= 0; i--) {
+ if (path[i] == '/')
+ return i + 1;
+ }
+ return 0; // No filename found means everything was the filename.
+}
+
+base::StringPiece FindFilename(const std::string* path) {
+ size_t filename_offset = FindFilenameOffset(*path);
+ if (filename_offset == 0)
+ return base::StringPiece(*path); // Everything is the file name.
+ return base::StringPiece(&(*path).data()[filename_offset],
+ path->size() - filename_offset);
+}
+
+base::StringPiece FindFilenameNoExtension(const std::string* path) {
+ if (path->empty())
+ return base::StringPiece();
+ size_t filename_offset = FindFilenameOffset(*path);
+ size_t extension_offset = FindExtensionOffset(*path);
+
+ size_t name_len;
+ if (extension_offset == std::string::npos)
+ name_len = path->size() - filename_offset;
+ else
+ name_len = extension_offset - filename_offset - 1;
+
+ return base::StringPiece(&(*path).data()[filename_offset], name_len);
+}
+
+void RemoveFilename(std::string* path) {
+ path->resize(FindFilenameOffset(*path));
+}
+
+bool EndsWithSlash(const std::string& s) {
+ return !s.empty() && s[s.size() - 1] == '/';
+}
+
+base::StringPiece FindDir(const std::string* path) {
+ size_t filename_offset = FindFilenameOffset(*path);
+ if (filename_offset == 0u)
+ return base::StringPiece();
+ return base::StringPiece(path->data(), filename_offset);
+}
+
+bool EnsureStringIsInOutputDir(const SourceDir& dir,
+ const std::string& str,
+ const Value& originating,
+ Err* err) {
+ // The last char of the dir will be a slash. We don't care if the input ends
+ // in a slash or not, so just compare up until there.
+ //
+ // This check will be wrong for all proper prefixes "e.g. "/output" will
+ // match "/out" but we don't really care since this is just a sanity check.
+ const std::string& dir_str = dir.value();
+ if (str.compare(0, dir_str.length() - 1, dir_str, 0, dir_str.length() - 1)
+ != 0) {
+ *err = Err(originating, "File not inside output directory.",
+ "The given file should be in the output directory. Normally you would "
+ "specify\n\"$target_output_dir/foo\" or "
+ "\"$target_gen_dir/foo\". I interpreted this as\n\""
+ + str + "\".");
+ return false;
+ }
+ return true;
+}
+
+std::string InvertDir(const SourceDir& path) {
+ const std::string value = path.value();
+ if (value.empty())
+ return std::string();
+
+ DCHECK(value[0] == '/');
+ size_t begin_index = 1;
+
+ // If the input begins with two slashes, skip over both (this is a
+ // source-relative dir).
+ if (value.size() > 1 && value[1] == '/')
+ begin_index = 2;
+
+ std::string ret;
+ for (size_t i = begin_index; i < value.size(); i++) {
+ if (value[i] == '/')
+ ret.append("../");
+ }
+ return ret;
+}
+
+void NormalizePath(std::string* path) {
+ char* pathbuf = path->empty() ? NULL : &(*path)[0];
+
+ // top_index is the first character we can modify in the path. Anything
+ // before this indicates where the path is relative to.
+ size_t top_index = 0;
+ bool is_relative = true;
+ if (!path->empty() && pathbuf[0] == '/') {
+ is_relative = false;
+
+ if (path->size() > 1 && pathbuf[1] == '/') {
+ // Two leading slashes, this is a path into the source dir.
+ top_index = 2;
+ } else {
+ // One leading slash, this is a system-absolute path.
+ top_index = 1;
+ }
+ }
+
+ size_t dest_i = top_index;
+ for (size_t src_i = top_index; src_i < path->size(); /* nothing */) {
+ if (pathbuf[src_i] == '.') {
+ if (src_i == 0 || pathbuf[src_i - 1] == '/') {
+ // Slash followed by a dot, see if it's something special.
+ size_t consumed_len;
+ switch (ClassifyAfterDot(*path, src_i + 1, &consumed_len)) {
+ case NOT_A_DIRECTORY:
+ // Copy the dot to the output, it means nothing special.
+ pathbuf[dest_i++] = pathbuf[src_i++];
+ break;
+ case DIRECTORY_CUR:
+ // Current directory, just skip the input.
+ src_i += consumed_len;
+ break;
+ case DIRECTORY_UP:
+ // Back up over previous directory component. If we're already
+ // at the top, preserve the "..".
+ if (dest_i > top_index) {
+ // The previous char was a slash, remove it.
+ dest_i--;
+ }
+
+ if (dest_i == top_index) {
+ if (is_relative) {
+ // We're already at the beginning of a relative input, copy the
+ // ".." and continue. We need the trailing slash if there was
+ // one before (otherwise we're at the end of the input).
+ pathbuf[dest_i++] = '.';
+ pathbuf[dest_i++] = '.';
+ if (consumed_len == 3)
+ pathbuf[dest_i++] = '/';
+
+ // This also makes a new "root" that we can't delete by going
+ // up more levels. Otherwise "../.." would collapse to
+ // nothing.
+ top_index = dest_i;
+ }
+ // Otherwise we're at the beginning of an absolute path. Don't
+ // allow ".." to go up another level and just eat it.
+ } else {
+ // Just find the previous slash or the beginning of input.
+ while (dest_i > 0 && pathbuf[dest_i - 1] != '/')
+ dest_i--;
+ }
+ src_i += consumed_len;
+ }
+ } else {
+ // Dot not preceeded by a slash, copy it literally.
+ pathbuf[dest_i++] = pathbuf[src_i++];
+ }
+ } else if (pathbuf[src_i] == '/') {
+ if (src_i > 0 && pathbuf[src_i - 1] == '/') {
+ // Two slashes in a row, skip over it.
+ src_i++;
+ } else {
+ // Just one slash, copy it.
+ pathbuf[dest_i++] = pathbuf[src_i++];
+ }
+ } else {
+ // Input nothing special, just copy it.
+ pathbuf[dest_i++] = pathbuf[src_i++];
+ }
+ }
+ path->resize(dest_i);
+}
+
+void ConvertPathToSystem(std::string* path) {
+#if defined(OS_WIN)
+ for (size_t i = 0; i < path->size(); i++) {
+ if ((*path)[i] == '/')
+ (*path)[i] = '\\';
+ }
+#endif
+}
+
+std::string PathToSystem(const std::string& path) {
+ std::string ret(path);
+ ConvertPathToSystem(&ret);
+ return ret;
+}
+
diff --git a/chromium/tools/gn/filesystem_utils.h b/chromium/tools/gn/filesystem_utils.h
new file mode 100644
index 00000000000..19139f826de
--- /dev/null
+++ b/chromium/tools/gn/filesystem_utils.h
@@ -0,0 +1,115 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_FILESYSTEM_UTILS_H_
+#define TOOLS_GN_FILESYSTEM_UTILS_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/strings/string_piece.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/target.h"
+
+class Err;
+class Location;
+class Value;
+
+enum SourceFileType {
+ SOURCE_UNKNOWN,
+ SOURCE_ASM,
+ SOURCE_C,
+ SOURCE_CC,
+ SOURCE_H,
+ SOURCE_M,
+ SOURCE_MM,
+ //SOURCE_S, // TODO(brettw) what is this?
+ SOURCE_RC,
+};
+
+SourceFileType GetSourceFileType(const SourceFile& file,
+ Settings::TargetOS os);
+
+// Returns the extension, not including the dot, for the given file type on the
+// given system.
+//
+// Some targets make multiple files (like a .dll and an import library). This
+// function returns the name of the file other targets should depend on and
+// link to (so in this example, the import library).
+const char* GetExtensionForOutputType(Target::OutputType type,
+ Settings::TargetOS os);
+
+std::string FilePathToUTF8(const base::FilePath& path);
+base::FilePath UTF8ToFilePath(const base::StringPiece& sp);
+
+// Extensions -----------------------------------------------------------------
+
+// Returns the index of the extension (character after the last dot not after a
+// slash). Returns std::string::npos if not found. Returns path.size() if the
+// file ends with a dot.
+size_t FindExtensionOffset(const std::string& path);
+
+// Returns a string piece pointing into the input string identifying the
+// extension. Note that the input pointer must outlive the output.
+base::StringPiece FindExtension(const std::string* path);
+
+// Filename parts -------------------------------------------------------------
+
+// Returns the offset of the character following the last slash, or
+// 0 if no slash was found. Returns path.size() if the path ends with a slash.
+// Note that the input pointer must outlive the output.
+size_t FindFilenameOffset(const std::string& path);
+
+// Returns a string piece pointing into the input string identifying the
+// file name (following the last slash, including the extension). Note that the
+// input pointer must outlive the output.
+base::StringPiece FindFilename(const std::string* path);
+
+// Like FindFilename but does not include the extension.
+base::StringPiece FindFilenameNoExtension(const std::string* path);
+
+// Removes everything after the last slash. The last slash, if any, will be
+// preserved.
+void RemoveFilename(std::string* path);
+
+// Returns true if the given path ends with a slash.
+bool EndsWithSlash(const std::string& s);
+
+// Path parts -----------------------------------------------------------------
+
+// Returns a string piece pointing into the input string identifying the
+// directory name of the given path, including the last slash. Note that the
+// input pointer must outlive the output.
+base::StringPiece FindDir(const std::string* path);
+
+// Verifies that the given string references a file inside of the given
+// directory. This is pretty stupid and doesn't handle "." and "..", etc.,
+// it is designed for a sanity check to keep people from writing output files
+// to the source directory accidentally.
+//
+// The originating value will be blamed in the error.
+//
+// If the file isn't in the dir, returns false and sets the error. Otherwise
+// returns true and leaves the error untouched.
+bool EnsureStringIsInOutputDir(const SourceDir& dir,
+ const std::string& str,
+ const Value& originating,
+ Err* err);
+
+// ----------------------------------------------------------------------------
+
+// Converts a directory to its inverse (e.g. "/foo/bar/" -> "../../").
+// This will be the empty string for the root directories ("/" and "//"), and
+// in all other cases, this is guaranteed to end in a slash.
+std::string InvertDir(const SourceDir& dir);
+
+// Collapses "." and sequential "/"s and evaluates "..".
+void NormalizePath(std::string* path);
+
+// Converts slashes to backslashes for Windows. Keeps the string unchanged
+// for other systems.
+void ConvertPathToSystem(std::string* path);
+std::string PathToSystem(const std::string& path);
+
+#endif // TOOLS_GN_FILESYSTEM_UTILS_H_
diff --git a/chromium/tools/gn/filesystem_utils_unittest.cc b/chromium/tools/gn/filesystem_utils_unittest.cc
new file mode 100644
index 00000000000..75bf7cdb3a3
--- /dev/null
+++ b/chromium/tools/gn/filesystem_utils_unittest.cc
@@ -0,0 +1,146 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/filesystem_utils.h"
+
+TEST(FilesystemUtils, FileExtensionOffset) {
+ EXPECT_EQ(std::string::npos, FindExtensionOffset(""));
+ EXPECT_EQ(std::string::npos, FindExtensionOffset("foo/bar/baz"));
+ EXPECT_EQ(4u, FindExtensionOffset("foo."));
+ EXPECT_EQ(4u, FindExtensionOffset("f.o.bar"));
+ EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/"));
+ EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/baz"));
+}
+
+TEST(FilesystemUtils, FindExtension) {
+ std::string input;
+ EXPECT_EQ("", FindExtension(&input).as_string());
+ input = "foo/bar/baz";
+ EXPECT_EQ("", FindExtension(&input).as_string());
+ input = "foo.";
+ EXPECT_EQ("", FindExtension(&input).as_string());
+ input = "f.o.bar";
+ EXPECT_EQ("bar", FindExtension(&input).as_string());
+ input = "foo.bar/";
+ EXPECT_EQ("", FindExtension(&input).as_string());
+ input = "foo.bar/baz";
+ EXPECT_EQ("", FindExtension(&input).as_string());
+}
+
+TEST(FilesystemUtils, FindFilenameOffset) {
+ EXPECT_EQ(0u, FindFilenameOffset(""));
+ EXPECT_EQ(0u, FindFilenameOffset("foo"));
+ EXPECT_EQ(4u, FindFilenameOffset("foo/"));
+ EXPECT_EQ(4u, FindFilenameOffset("foo/bar"));
+}
+
+TEST(FilesystemUtils, RemoveFilename) {
+ std::string s;
+
+ RemoveFilename(&s);
+ EXPECT_STREQ("", s.c_str());
+
+ s = "foo";
+ RemoveFilename(&s);
+ EXPECT_STREQ("", s.c_str());
+
+ s = "/";
+ RemoveFilename(&s);
+ EXPECT_STREQ("/", s.c_str());
+
+ s = "foo/bar";
+ RemoveFilename(&s);
+ EXPECT_STREQ("foo/", s.c_str());
+
+ s = "foo/bar/baz.cc";
+ RemoveFilename(&s);
+ EXPECT_STREQ("foo/bar/", s.c_str());
+}
+
+TEST(FilesystemUtils, FindDir) {
+ std::string input;
+ EXPECT_EQ("", FindDir(&input));
+ input = "/";
+ EXPECT_EQ("/", FindDir(&input));
+ input = "foo/";
+ EXPECT_EQ("foo/", FindDir(&input));
+ input = "foo/bar/baz";
+ EXPECT_EQ("foo/bar/", FindDir(&input));
+}
+
+TEST(FilesystemUtils, InvertDir) {
+ EXPECT_TRUE(InvertDir(SourceDir()) == "");
+ EXPECT_TRUE(InvertDir(SourceDir("/")) == "");
+ EXPECT_TRUE(InvertDir(SourceDir("//")) == "");
+
+ EXPECT_TRUE(InvertDir(SourceDir("//foo/bar")) == "../../");
+ EXPECT_TRUE(InvertDir(SourceDir("/foo/bar/")) == "../../");
+}
+
+TEST(FilesystemUtils, NormalizePath) {
+ std::string input;
+
+ NormalizePath(&input);
+ EXPECT_EQ("", input);
+
+ input = "foo/bar.txt";
+ NormalizePath(&input);
+ EXPECT_EQ("foo/bar.txt", input);
+
+ input = ".";
+ NormalizePath(&input);
+ EXPECT_EQ("", input);
+
+ input = "..";
+ NormalizePath(&input);
+ EXPECT_EQ("..", input);
+
+ input = "foo//bar";
+ NormalizePath(&input);
+ EXPECT_EQ("foo/bar", input);
+
+ input = "//foo";
+ NormalizePath(&input);
+ EXPECT_EQ("//foo", input);
+
+ input = "foo/..//bar";
+ NormalizePath(&input);
+ EXPECT_EQ("bar", input);
+
+ input = "foo/../../bar";
+ NormalizePath(&input);
+ EXPECT_EQ("../bar", input);
+
+ input = "/../foo"; // Don't go aboe the root dir.
+ NormalizePath(&input);
+ EXPECT_EQ("/foo", input);
+
+ input = "//../foo"; // Don't go aboe the root dir.
+ NormalizePath(&input);
+ EXPECT_EQ("//foo", input);
+
+ input = "../foo";
+ NormalizePath(&input);
+ EXPECT_EQ("../foo", input);
+
+ input = "..";
+ NormalizePath(&input);
+ EXPECT_EQ("..", input);
+
+ input = "./././.";
+ NormalizePath(&input);
+ EXPECT_EQ("", input);
+
+ input = "../../..";
+ NormalizePath(&input);
+ EXPECT_EQ("../../..", input);
+
+ input = "../";
+ NormalizePath(&input);
+ EXPECT_EQ("../", input);
+}
diff --git a/chromium/tools/gn/function_define_rule.cc b/chromium/tools/gn/function_define_rule.cc
new file mode 100644
index 00000000000..07fce7c8ddb
--- /dev/null
+++ b/chromium/tools/gn/function_define_rule.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/functions.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/value.h"
+
+namespace functions {
+
+const char kDefineRule[] = "define_rule";
+const char kDefileRule_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunDefineRule(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ // TODO(brettw) determine if the function is built-in and throw an error if
+ // it is.
+ if (args.size() != 1) {
+ *err = Err(function->function(),
+ "Need exactly one string arg to define_rule.");
+ return Value();
+ }
+ if (!args[0].VerifyTypeIs(Value::STRING, err))
+ return Value();
+ std::string rule_name = args[0].string_value();
+
+ const FunctionCallNode* existing_rule = scope->GetRule(rule_name);
+ if (existing_rule) {
+ *err = Err(function, "Duplicate rule definition.",
+ "A rule with this name was already defined.");
+ err->AppendSubErr(Err(existing_rule->function(), "Previous definition."));
+ return Value();
+ }
+
+ scope->AddRule(rule_name, function);
+ return Value();
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/function_exec_script.cc b/chromium/tools/gn/function_exec_script.cc
new file mode 100644
index 00000000000..4121324f8ed
--- /dev/null
+++ b/chromium/tools/gn/function_exec_script.cc
@@ -0,0 +1,355 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/process/kill.h"
+#include "base/process/launch.h"
+#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
+#include "tools/gn/err.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/input_conversion.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/value.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+
+#include "base/win/scoped_handle.h"
+#include "base/win/scoped_process_information.h"
+#endif
+
+#if defined(OS_POSIX)
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "base/posix/file_descriptor_shuffle.h"
+#endif
+
+namespace functions {
+
+namespace {
+
+#if defined(OS_WIN)
+bool ExecProcess(const CommandLine& cmdline,
+ const base::FilePath& startup_dir,
+ std::string* std_out,
+ std::string* std_err,
+ int* exit_code) {
+ SECURITY_ATTRIBUTES sa_attr;
+ // Set the bInheritHandle flag so pipe handles are inherited.
+ sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa_attr.bInheritHandle = TRUE;
+ sa_attr.lpSecurityDescriptor = NULL;
+
+ // Create the pipe for the child process's STDOUT.
+ HANDLE out_read = NULL;
+ HANDLE out_write = NULL;
+ if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) {
+ NOTREACHED() << "Failed to create pipe";
+ return false;
+ }
+ base::win::ScopedHandle scoped_out_read(out_read);
+ base::win::ScopedHandle scoped_out_write(out_write);
+
+ // Create the pipe for the child process's STDERR.
+ HANDLE err_read = NULL;
+ HANDLE err_write = NULL;
+ if (!CreatePipe(&err_read, &err_write, &sa_attr, 0)) {
+ NOTREACHED() << "Failed to create pipe";
+ return false;
+ }
+ base::win::ScopedHandle scoped_err_read(err_read);
+ base::win::ScopedHandle scoped_err_write(err_write);
+
+ // Ensure the read handle to the pipe for STDOUT/STDERR is not inherited.
+ if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
+ NOTREACHED() << "Failed to disabled pipe inheritance";
+ return false;
+ }
+ if (!SetHandleInformation(err_read, HANDLE_FLAG_INHERIT, 0)) {
+ NOTREACHED() << "Failed to disabled pipe inheritance";
+ return false;
+ }
+
+ base::FilePath::StringType cmdline_str(cmdline.GetCommandLineString());
+
+ base::win::ScopedProcessInformation proc_info;
+ STARTUPINFO start_info = { 0 };
+
+ start_info.cb = sizeof(STARTUPINFO);
+ start_info.hStdOutput = out_write;
+ // Keep the normal stdin.
+ start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ // FIXME(brettw) set stderr here when we actually read it below.
+ //start_info.hStdError = err_write;
+ start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ start_info.dwFlags |= STARTF_USESTDHANDLES;
+
+ // Create the child process.
+ if (!CreateProcess(NULL,
+ &cmdline_str[0],
+ NULL, NULL,
+ TRUE, // Handles are inherited.
+ 0, NULL,
+ startup_dir.value().c_str(),
+ &start_info, proc_info.Receive())) {
+ return false;
+ }
+
+ // Close our writing end of pipes now. Otherwise later read would not be able
+ // to detect end of child's output.
+ scoped_out_write.Close();
+ scoped_err_write.Close();
+
+ // Read output from the child process's pipe for STDOUT
+ const int kBufferSize = 1024;
+ char buffer[kBufferSize];
+
+ // FIXME(brettw) read from stderr here! This is complicated because we want
+ // to read both of them at the same time, probably need overlapped I/O.
+ // Also uncomment start_info code above.
+ for (;;) {
+ DWORD bytes_read = 0;
+ BOOL success = ReadFile(out_read, buffer, kBufferSize, &bytes_read, NULL);
+ if (!success || bytes_read == 0)
+ break;
+ std_out->append(buffer, bytes_read);
+ }
+
+ // Let's wait for the process to finish.
+ WaitForSingleObject(proc_info.process_handle(), INFINITE);
+
+ DWORD dw_exit_code;
+ GetExitCodeProcess(proc_info.process_handle(), &dw_exit_code);
+ *exit_code = static_cast<int>(dw_exit_code);
+
+ return true;
+}
+#else
+bool ExecProcess(const CommandLine& cmdline,
+ const base::FilePath& startup_dir,
+ std::string* std_out,
+ std::string* std_err,
+ int* exit_code) {
+ *exit_code = EXIT_FAILURE;
+
+ std::vector<std::string> argv = cmdline.argv();
+
+ int pipe_fd[2];
+ pid_t pid;
+ base::InjectiveMultimap fd_shuffle1, fd_shuffle2;
+ scoped_ptr<char*[]> argv_cstr(new char*[argv.size() + 1]);
+
+ fd_shuffle1.reserve(3);
+ fd_shuffle2.reserve(3);
+
+ if (pipe(pipe_fd) < 0)
+ return false;
+
+ switch (pid = fork()) {
+ case -1: // error
+ close(pipe_fd[0]);
+ close(pipe_fd[1]);
+ return false;
+ case 0: // child
+ {
+#if defined(OS_MACOSX)
+ base::RestoreDefaultExceptionHandler();
+#endif
+ // DANGER: no calls to malloc are allowed from now on:
+ // http://crbug.com/36678
+
+ // Obscure fork() rule: in the child, if you don't end up doing exec*(),
+ // you call _exit() instead of exit(). This is because _exit() does not
+ // call any previously-registered (in the parent) exit handlers, which
+ // might do things like block waiting for threads that don't even exist
+ // in the child.
+ int dev_null = open("/dev/null", O_WRONLY);
+ if (dev_null < 0)
+ _exit(127);
+
+ fd_shuffle1.push_back(
+ base::InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
+ fd_shuffle1.push_back(
+ base::InjectionArc(dev_null, STDERR_FILENO, true));
+ fd_shuffle1.push_back(
+ base::InjectionArc(dev_null, STDIN_FILENO, true));
+ // Adding another element here? Remeber to increase the argument to
+ // reserve(), above.
+
+ std::copy(fd_shuffle1.begin(), fd_shuffle1.end(),
+ std::back_inserter(fd_shuffle2));
+
+ if (!ShuffleFileDescriptors(&fd_shuffle1))
+ _exit(127);
+
+ chdir(startup_dir.value().c_str());
+
+ // TODO(brettw) the base version GetAppOutput does a
+ // CloseSuperfluousFds call here. Do we need this?
+
+ for (size_t i = 0; i < argv.size(); i++)
+ argv_cstr[i] = const_cast<char*>(argv[i].c_str());
+ argv_cstr[argv.size()] = NULL;
+ execvp(argv_cstr[0], argv_cstr.get());
+ _exit(127);
+ }
+ default: // parent
+ {
+ // Close our writing end of pipe now. Otherwise later read would not
+ // be able to detect end of child's output (in theory we could still
+ // write to the pipe).
+ close(pipe_fd[1]);
+
+ char buffer[256];
+ ssize_t bytes_read = 0;
+
+ while (true) {
+ bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer)));
+ if (bytes_read <= 0)
+ break;
+ std_out->append(buffer, bytes_read);
+ }
+ close(pipe_fd[0]);
+
+ return base::WaitForExitCode(pid, exit_code);
+ }
+ }
+
+ return false;
+}
+#endif
+
+} // namespace
+
+const char kExecScript[] = "exec_script";
+const char kExecScript_Help[] =
+ "exec_script: Synchronously run a script and return the output.\n"
+ "\n"
+ " exec_script(filename, arguments, input_conversion,\n"
+ " [file_dependencies])\n"
+ "\n"
+ " Runs the given script, returning the stdout of the script. The build\n"
+ " generation will fail if the script does not exist or returns a nonzero\n"
+ " exit code.\n"
+ "\n"
+ "Arguments:\n"
+ "\n"
+ " filename:\n"
+ " File name of python script to execute, relative to the build file.\n"
+ "\n"
+ " arguments:\n"
+ " A list of strings to be passed to the script as arguments.\n"
+ "\n"
+ " input_conversion:\n"
+ " Controls how the file is read and parsed.\n"
+ " See \"gn help input_conversion\".\n"
+ "\n"
+ " dependencies:\n"
+ " (Optional) A list of files that this script reads or otherwise\n"
+ " depends on. These dependencies will be added to the build result\n"
+ " such that if any of them change, the build will be regenerated and\n"
+ " the script will be re-run.\n"
+ "\n"
+ " The script itself will be an implicit dependency so you do not\n"
+ " need to list it.\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ " all_lines = exec_script(\"myscript.py\", [some_input], \"list lines\",\n"
+ " [\"data_file.txt\"])\n";
+
+Value RunExecScript(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (args.size() != 3 && args.size() != 4) {
+ *err = Err(function->function(), "Wrong number of args to write_file",
+ "I expected three or four arguments.");
+ return Value();
+ }
+
+ const Settings* settings = scope->settings();
+ const BuildSettings* build_settings = settings->build_settings();
+ const SourceDir& cur_dir = SourceDirForFunctionCall(function);
+
+ // Find the python script to run.
+ if (!args[0].VerifyTypeIs(Value::STRING, err))
+ return Value();
+ SourceFile script_source =
+ cur_dir.ResolveRelativeFile(args[0].string_value());
+ base::FilePath script_path = build_settings->GetFullPath(script_source);
+ if (!build_settings->secondary_source_path().empty() &&
+ !base::PathExists(script_path)) {
+ // Fall back to secondary source root when the file doesn't exist.
+ script_path = build_settings->GetFullPathSecondary(script_source);
+ }
+
+ // Add all dependencies of this script, including the script itself, to the
+ // build deps.
+ g_scheduler->AddGenDependency(script_path);
+ if (args.size() == 4) {
+ const Value& deps_value = args[3];
+ if (!deps_value.VerifyTypeIs(Value::LIST, err))
+ return Value();
+
+ for (size_t i = 0; i < deps_value.list_value().size(); i++) {
+ if (!deps_value.list_value()[0].VerifyTypeIs(Value::STRING, err))
+ return Value();
+ g_scheduler->AddGenDependency(
+ build_settings->GetFullPath(cur_dir.ResolveRelativeFile(
+ deps_value.list_value()[0].string_value())));
+ }
+ }
+
+ // Make the command line.
+ const base::FilePath& python_path = build_settings->python_path();
+ CommandLine cmdline(python_path);
+ cmdline.AppendArgPath(script_path);
+
+ const Value& script_args = args[1];
+ if (!script_args.VerifyTypeIs(Value::LIST, err))
+ return Value();
+ for (size_t i = 0; i < script_args.list_value().size(); i++) {
+ if (!script_args.list_value()[i].VerifyTypeIs(Value::STRING, err))
+ return Value();
+ cmdline.AppendArg(script_args.list_value()[i].string_value());
+ }
+
+ // Execute the process.
+ // TODO(brettw) set the environment block.
+ std::string output;
+ std::string stderr_output; // TODO(brettw) not hooked up, see above.
+ int exit_code = 0;
+ if (!ExecProcess(cmdline, build_settings->GetFullPath(cur_dir),
+ &output, &stderr_output, &exit_code)) {
+ *err = Err(function->function(), "Could not execute python.",
+ "I was trying to execute \"" + FilePathToUTF8(python_path) + "\".");
+ return Value();
+ }
+
+ // TODO(brettw) maybe we need stderr also for reasonable stack dumps.
+ if (exit_code != 0) {
+ std::string msg =
+ std::string("I was running \"") + FilePathToUTF8(script_path) + "\"\n"
+ "and it returned " + base::IntToString(exit_code);
+ if (!output.empty())
+ msg += " and printed out:\n\n" + output;
+ else
+ msg += ".";
+ *err = Err(function->function(), "Script returned non-zero exit code.",
+ msg);
+ return Value();
+ }
+
+ return ConvertInputToValue(output, function, args[2], err);
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/function_process_file_template.cc b/chromium/tools/gn/function_process_file_template.cc
new file mode 100644
index 00000000000..94836408401
--- /dev/null
+++ b/chromium/tools/gn/function_process_file_template.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/file_template.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/parse_tree.h"
+
+namespace functions {
+
+const char kProcessFileTemplate[] = "process_file_template";
+const char kProcessFileTemplate_Help[] =
+ "process_file_template: Do template expansion over a list of files.\n"
+ "\n"
+ " process_file_template(source_list, template)\n"
+ "\n"
+ " process_file_template applies a template list to a source file list,\n"
+ " returning the result of applying each template to each source. This is\n"
+ " typically used for computing output file names from input files.\n"
+ "\n"
+ "Arguments:\n"
+ "\n"
+ " The source_list is a list of file names.\n"
+ "\n"
+ " The template can be a string or a list. If it is a list, multiple\n"
+ " output strings are generated for each input.\n"
+ "\n"
+ " The following template substrings are used in the template arguments\n"
+ " and are replaced with the corresponding part of the input file name:\n"
+ "\n"
+ " {{source}}\n"
+ " The entire source name.\n"
+ "\n"
+ " {{source_name_part}}\n"
+ " The source name with no path or extension.\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ " sources = [\n"
+ " \"foo.idl\",\n"
+ " \"bar.idl\",\n"
+ " ]\n"
+ " myoutputs = process_file_template(\n"
+ " sources,\n"
+ " [ \"$target_gen_dir/{{source_name_part}}.cc\",\n"
+ " \"$target_gen_dir/{{source_name_part}}.h\" ])\n"
+ "\n"
+ " The result in this case will be:\n"
+ " [ \"//out/Debug/foo.cc\"\n"
+ " \"//out/Debug/foo.h\"\n"
+ " \"//out/Debug/bar.cc\"\n"
+ " \"//out/Debug/bar.h\" ]\n";
+
+Value RunProcessFileTemplate(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (args.size() != 2) {
+ *err = Err(function->function(), "Expected two arguments");
+ return Value();
+ }
+
+ FileTemplate file_template(args[1], err);
+ if (err->has_error())
+ return Value();
+
+ Value ret(function, Value::LIST);
+ file_template.Apply(args[0], function, &ret.list_value(), err);
+ return ret;
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/function_read_file.cc b/chromium/tools/gn/function_read_file.cc
new file mode 100644
index 00000000000..01de7c8baf0
--- /dev/null
+++ b/chromium/tools/gn/function_read_file.cc
@@ -0,0 +1,72 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_util.h"
+#include "tools/gn/err.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/input_conversion.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/scheduler.h"
+
+// TODO(brettw) consider removing this. I originally wrote it for making the
+// WebKit bindings but misundersood what was required, and didn't need to
+// use this. This seems to have a high potential for misuse.
+
+namespace functions {
+
+const char kReadFile[] = "read_file";
+const char kReadFile_Help[] =
+ "read_file: Read a file into a variable.\n"
+ "\n"
+ " read_file(filename, how_to_read)\n"
+ "\n"
+ " Whitespace will be trimmed from the end of the file. Throws an error\n"
+ " if the file can not be opened.\n"
+ "\n"
+ "Arguments:\n"
+ "\n"
+ " filename\n"
+ " Filename to read, relative to the build file.\n"
+ "\n"
+ " input_conversion\n"
+ " Controls how the file is read and parsed.\n"
+ " See \"gn help input_conversion\".\n"
+ "\n"
+ "Example:\n"
+ " lines = read_file(\"foo.txt\", \"list lines\")\n";
+
+Value RunReadFile(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (args.size() != 2) {
+ *err = Err(function->function(), "Wrong number of args to read_file",
+ "I expected two arguments.");
+ return Value();
+ }
+ if (!args[0].VerifyTypeIs(Value::STRING, err))
+ return Value();
+
+ // Compute the file name.
+ const SourceDir& cur_dir = SourceDirForFunctionCall(function);
+ SourceFile source_file = cur_dir.ResolveRelativeFile(args[0].string_value());
+ base::FilePath file_path =
+ scope->settings()->build_settings()->GetFullPath(source_file);
+
+ // Ensure that everything is recomputed if the read file changes.
+ g_scheduler->AddGenDependency(file_path);
+
+ // Read contents.
+ std::string file_contents;
+ if (!file_util::ReadFileToString(file_path, &file_contents)) {
+ *err = Err(args[0], "Could not read file.",
+ "I resolved this to \"" + FilePathToUTF8(file_path) + "\".");
+ return Value();
+ }
+
+ return ConvertInputToValue(file_contents, function, args[1], err);
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/function_set_default_toolchain.cc b/chromium/tools/gn/function_set_default_toolchain.cc
new file mode 100644
index 00000000000..f6ece072fa4
--- /dev/null
+++ b/chromium/tools/gn/function_set_default_toolchain.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/build_settings.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/toolchain_manager.h"
+
+namespace functions {
+
+const char kSetDefaultToolchain[] = "set_default_toolchain";
+const char kSetDefaultToolchain_Help[] =
+ "set_default_toolchain: Sets the default toolchain name.\n"
+ "\n"
+ " set_default_toolchain(toolchain_label)\n"
+ "\n"
+ " The given label should identify a toolchain definition (see\n"
+ " \"help toolchain\"). This toolchain will be used for all targets\n"
+ " unless otherwise specified.\n"
+ "\n"
+ " This function is only valid to call during the processing of the build\n"
+ " configuration file. Since the build configuration file is processed\n"
+ " separately for each toolchain, this function will be a no-op when\n"
+ " called under any non-default toolchains.\n"
+ "\n"
+ " For example, the default toolchain should be appropriate for the\n"
+ " current environment. If the current environment is 32-bit and \n"
+ " somebody references a target with a 64-bit toolchain, we wouldn't\n"
+ " want processing of the build config file for the 64-bit toolchain to\n"
+ " reset the default toolchain to 64-bit, we want to keep it 32-bits.\n"
+ "\n"
+ "Argument:\n"
+ "\n"
+ " toolchain_label\n"
+ " Toolchain name.\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ " set_default_toolchain(\"//build/config/win:vs32\")";
+
+Value RunSetDefaultToolchain(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (!scope->IsProcessingBuildConfig()) {
+ *err = Err(function->function(), "Must be called from build config.",
+ "set_default_toolchain can only be called from the build configuration "
+ "file.");
+ return Value();
+ }
+
+ // Ignore non-default-build-config invocations.
+ if (!scope->IsProcessingDefaultBuildConfig())
+ return Value();
+
+ const SourceDir& current_dir = SourceDirForFunctionCall(function);
+ const Label& default_toolchain = ToolchainLabelForScope(scope);
+
+ if (!EnsureSingleStringArg(function, args, err))
+ return Value();
+ Label toolchain_label(
+ Label::Resolve(current_dir, default_toolchain, args[0], err));
+ if (toolchain_label.is_null())
+ return Value();
+
+ ToolchainManager& mgr =
+ scope->settings()->build_settings()->toolchain_manager();
+ mgr.SetDefaultToolchainUnlocked(toolchain_label, function->GetRange(), err);
+ return Value();
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/function_template.cc b/chromium/tools/gn/function_template.cc
new file mode 100644
index 00000000000..9e78432408e
--- /dev/null
+++ b/chromium/tools/gn/function_template.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/functions.h"
+
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/value.h"
+
+namespace functions {
+
+const char kTemplate[] = "template";
+const char kTemplate_Help[] =
+ "template: Define a template rule.\n"
+ "\n"
+ " A template defines a custom rule name that can expand to one or more\n"
+ " other rules (typically built-in rules like \"static_library\"). It\n"
+ " provides a way to add to the built-in target types.\n"
+ "\n"
+ " The template() function is used to declare a template. To invoke the\n"
+ " template, just use the name of the template like any other target\n"
+ " type.\n"
+ "\n"
+ "More details:\n"
+ "\n"
+ " Semantically, the code in the template is stored. When a function\n"
+ " with the name is called, the block following the invocation is\n"
+ " executed, *then* your template code is executed. So if the invocation\n"
+ " sets the |source| variable, for example, that variable will be\n"
+ " accessible to you when the template code runs.\n"
+ "\n"
+ " The template() function does not generate a closure, so the\n"
+ " environment, current directory, etc. will all be the same as from\n"
+ " the template is invoked.\n"
+ "\n"
+ "Hints:\n"
+ "\n"
+ " If your template expands to more than one target, be sure to name\n"
+ " the intermediate targets based on the name of the template\n"
+ " instantiation so that the names are globally unique. The variable\n"
+ " |target_name| will be this name.\n"
+ "\n"
+ " Likewise, you will always want to generate a target in your template\n"
+ " with the original |target_name|. Otherwise, invoking your template\n"
+ " will not actually generate a node in the dependency graph that other\n"
+ " targets can reference.\n"
+ "\n"
+ " Often you will want to declare your template in a special file that\n"
+ " other files will import (see \"gn help import\") so your template\n"
+ " rule can be shared across build files.\n"
+ "\n"
+ "Example of defining a template:\n"
+ "\n"
+ " template(\"my_idl\") {\n"
+ " # Maps input files to output files, used in both targets below.\n"
+ " filter = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n"
+ " \"$target_gen_dir/{{source_name_part}}.h\" ]\n"
+ "\n"
+ " # Intermediate target to compile IDL to C source.\n"
+ " custom(\"${target_name}_code_gen\") {\n"
+ " # The |sources| will be inherited from the surrounding scope so\n"
+ " # we don't need to redefine it.\n"
+ " script = \"foo.py\"\n"
+ " outputs = filter # Variable from above.\n"
+ " }\n"
+ "\n"
+ " # Name the static library the same as the template invocation so\n"
+ " # instanting this template produces something that other targets\n"
+ " # can link to in their deps.\n"
+ " static_library(target_name) {\n"
+ " # Generates the list of sources.\n"
+ " # See \"gn help process_file_template\"\n"
+ " sources = process_file_template(sources, filter)\n"
+ " }\n"
+ " }\n"
+ "\n"
+ "Example of invoking the resulting template:\n"
+ "\n"
+ " my_idl(\"foo_idl_files\") {\n"
+ " sources = [ \"foo.idl\", \"bar.idl\" ]\n"
+ " }\n";
+
+Value RunTemplate(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ // TODO(brettw) determine if the function is built-in and throw an error if
+ // it is.
+ if (args.size() != 1) {
+ *err = Err(function->function(),
+ "Need exactly one string arg to template.");
+ return Value();
+ }
+ if (!args[0].VerifyTypeIs(Value::STRING, err))
+ return Value();
+ std::string template_name = args[0].string_value();
+
+ const FunctionCallNode* existing_template = scope->GetTemplate(template_name);
+ if (existing_template) {
+ *err = Err(function, "Duplicate template definition.",
+ "A template with this name was already defined.");
+ err->AppendSubErr(Err(existing_template->function(),
+ "Previous definition."));
+ return Value();
+ }
+
+ scope->AddTemplate(template_name, function);
+ return Value();
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/function_toolchain.cc b/chromium/tools/gn/function_toolchain.cc
new file mode 100644
index 00000000000..f8b9094f01f
--- /dev/null
+++ b/chromium/tools/gn/function_toolchain.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/err.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/toolchain.h"
+
+namespace functions {
+
+namespace {
+
+// This is jsut a unique value to take the address of to use as the key for
+// the toolchain property on a scope.
+const int kToolchainPropertyKey = 0;
+
+// Reads the given string from the scope (if present) and puts the result into
+// dest. If the value is not a string, sets the error and returns false.
+bool ReadString(Scope& scope, const char* var, std::string* dest, Err* err) {
+ const Value* v = scope.GetValue(var, true);
+ if (!v)
+ return true; // Not present is fine.
+
+ if (!v->VerifyTypeIs(Value::STRING, err))
+ return false;
+ *dest = v->string_value();
+ return true;
+}
+
+} // namespace
+
+// toolchain -------------------------------------------------------------------
+
+const char kToolchain[] = "toolchain";
+const char kToolchain_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunToolchain(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ if (!EnsureNotProcessingImport(function, scope, err) ||
+ !EnsureNotProcessingBuildConfig(function, scope, err))
+ return Value();
+
+ // Note that we don't want to use MakeLabelForScope since that will include
+ // the toolchain name in the label, and toolchain labels don't themselves
+ // have toolchain names.
+ const SourceDir& input_dir = SourceDirForFunctionCall(function);
+ Label label(input_dir, args[0].string_value(), SourceDir(), std::string());
+ if (g_scheduler->verbose_logging())
+ g_scheduler->Log("Generating toolchain", label.GetUserVisibleName(false));
+
+ // This object will actually be copied into the one owned by the toolchain
+ // manager, but that has to be done in the lock.
+ Toolchain toolchain(label);
+
+ Scope block_scope(scope);
+ block_scope.SetProperty(&kToolchainPropertyKey, &toolchain);
+ block->ExecuteBlockInScope(&block_scope, err);
+ block_scope.SetProperty(&kToolchainPropertyKey, NULL);
+ if (err->has_error())
+ return Value();
+ if (!block_scope.CheckForUnusedVars(err))
+ return Value();
+
+ const BuildSettings* build_settings = scope->settings()->build_settings();
+ {
+ // Save the toolchain definition in the toolchain manager and mark the
+ // corresponding item in the dependency tree resolved so that targets
+ // that depend on this toolchain know it's ready.
+ base::AutoLock lock(build_settings->item_tree().lock());
+ build_settings->toolchain_manager().SetToolchainDefinitionLocked(
+ toolchain, function->GetRange(), err);
+ build_settings->item_tree().MarkItemDefinedLocked(build_settings, label,
+ err);
+ }
+ return Value();
+}
+
+// tool ------------------------------------------------------------------------
+
+const char kTool[] = "tool";
+const char kTool_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunTool(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ // Find the toolchain definition we're executing inside of. The toolchain
+ // function will set a property pointing to it that we'll pick up.
+ Toolchain* toolchain = reinterpret_cast<Toolchain*>(
+ scope->GetProperty(&kToolchainPropertyKey, NULL));
+ if (!toolchain) {
+ *err = Err(function->function(), "tool() called outside of toolchain().",
+ "The tool() function can only be used inside a toolchain() "
+ "definition.");
+ return Value();
+ }
+
+ if (!EnsureSingleStringArg(function, args, err))
+ return Value();
+ const std::string& tool_name = args[0].string_value();
+ Toolchain::ToolType tool_type = Toolchain::ToolNameToType(tool_name);
+ if (tool_type == Toolchain::TYPE_NONE) {
+ *err = Err(args[0], "Unknown tool type");
+ return Value();
+ }
+
+ // Run the tool block.
+ Scope block_scope(scope);
+ block->ExecuteBlockInScope(&block_scope, err);
+ if (err->has_error())
+ return Value();
+
+ // Extract the stuff we need.
+ Toolchain::Tool t;
+ if (!ReadString(block_scope, "command", &t.command, err) ||
+ !ReadString(block_scope, "depfile", &t.depfile, err) ||
+ !ReadString(block_scope, "deps", &t.deps, err) ||
+ !ReadString(block_scope, "description", &t.description, err) ||
+ !ReadString(block_scope, "pool", &t.pool, err) ||
+ !ReadString(block_scope, "restat", &t.restat, err) ||
+ !ReadString(block_scope, "rspfile", &t.rspfile, err) ||
+ !ReadString(block_scope, "rspfile_content", &t.rspfile_content, err))
+ return Value();
+
+ // Make sure there weren't any vars set in this tool that were unused.
+ if (!block_scope.CheckForUnusedVars(err))
+ return Value();
+
+ toolchain->SetTool(tool_type, t);
+ return Value();
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/function_write_file.cc b/chromium/tools/gn/function_write_file.cc
new file mode 100644
index 00000000000..90d50741d61
--- /dev/null
+++ b/chromium/tools/gn/function_write_file.cc
@@ -0,0 +1,89 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <iostream>
+#include <sstream>
+
+#include "base/file_util.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "tools/gn/err.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scheduler.h"
+
+namespace functions {
+
+const char kWriteFile[] = "write_file";
+const char kWriteFile_Help[] =
+ "write_file: Write a file to disk.\n"
+ "\n"
+ " write_file(filename, data)\n"
+ "\n"
+ " If data is a list, the list will be written one-item-per-line with no\n"
+ " quoting or brackets.\n"
+ "\n"
+ " TODO(brettw) we probably need an optional third argument to control\n"
+ " list formatting.\n"
+ "\n"
+ "Arguments:\n"
+ "\n"
+ " filename\n"
+ " Filename to write. This must be within the output directory.\n"
+ "\n"
+ " data:\n"
+ " The list or string to write.\n";
+
+Value RunWriteFile(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (args.size() != 2) {
+ *err = Err(function->function(), "Wrong number of args to write_file",
+ "I expected two arguments.");
+ return Value();
+ }
+
+ // Compute the file name and make sure it's in the output dir.
+ if (!args[0].VerifyTypeIs(Value::STRING, err))
+ return Value();
+ const SourceDir& cur_dir = SourceDirForFunctionCall(function);
+ SourceFile source_file = cur_dir.ResolveRelativeFile(args[0].string_value());
+ if (!EnsureStringIsInOutputDir(
+ scope->settings()->build_settings()->build_dir(),
+ source_file.value(), args[0], err))
+ return Value();
+
+ // Compute output.
+ std::ostringstream contents;
+ if (args[1].type() == Value::LIST) {
+ const std::vector<Value>& list = args[1].list_value();
+ for (size_t i = 0; i < list.size(); i++)
+ contents << list[i].ToString() << std::endl;
+ } else {
+ contents << args[1].ToString();
+ }
+
+ // Write file, creating the directory if necessary.
+ base::FilePath file_path =
+ scope->settings()->build_settings()->GetFullPath(source_file);
+ const std::string& contents_string = contents.str();
+ if (!file_util::CreateDirectory(file_path.DirName())) {
+ *err = Err(function->function(), "Unable to create directory.",
+ "I was using \"" + FilePathToUTF8(file_path.DirName()) + "\".");
+ return Value();
+ }
+ if (file_util::WriteFile(file_path,
+ contents_string.c_str(), contents_string.size())
+ != static_cast<int>(contents_string.size())) {
+ *err = Err(function->function(), "Unable to write file.",
+ "I was writing \"" + FilePathToUTF8(file_path) + "\".");
+ return Value();
+ }
+ return Value();
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/functions.cc b/chromium/tools/gn/functions.cc
new file mode 100644
index 00000000000..de3ddcc2248
--- /dev/null
+++ b/chromium/tools/gn/functions.cc
@@ -0,0 +1,548 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/functions.h"
+
+#include <iostream>
+
+#include "base/strings/string_util.h"
+#include "tools/gn/config.h"
+#include "tools/gn/config_values_generator.h"
+#include "tools/gn/err.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/item_tree.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/target_manager.h"
+#include "tools/gn/token.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+void FillNeedsBlockError(const FunctionCallNode* function, Err* err) {
+ *err = Err(function->function(), "This function call requires a block.",
+ "The block's \"{\" must be on the same line as the function "
+ "call's \")\".");
+}
+
+// This is called when a template is invoked. When we see a template
+// declaration, that funciton is RunTemplate.
+Value RunTemplateInvocation(Scope* scope,
+ const FunctionCallNode* invocation,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ const FunctionCallNode* rule,
+ Err* err) {
+ if (!EnsureNotProcessingImport(invocation, scope, err))
+ return Value();
+ Scope block_scope(scope);
+ if (!FillTargetBlockScope(scope, invocation,
+ invocation->function().value().data(),
+ block, args, &block_scope, err))
+ return Value();
+
+ // Run the block for the rule invocation.
+ block->ExecuteBlockInScope(&block_scope, err);
+ if (err->has_error())
+ return Value();
+
+ // Now run the rule itself with that block as the current scope.
+ rule->block()->ExecuteBlockInScope(&block_scope, err);
+ if (err->has_error())
+ return Value();
+
+ return Value();
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+bool EnsureNotProcessingImport(const ParseNode* node,
+ const Scope* scope,
+ Err* err) {
+ if (scope->IsProcessingImport()) {
+ *err = Err(node, "Not valid from an import.",
+ "We need to talk about this thing you are doing here. Doing this\n"
+ "kind of thing from an imported file makes me feel like you are\n"
+ "abusing me. Imports are for defining defaults, variables, and rules.\n"
+ "The appropriate place for this kind of thing is really in a normal\n"
+ "BUILD file.");
+ return false;
+ }
+ return true;
+}
+
+bool EnsureNotProcessingBuildConfig(const ParseNode* node,
+ const Scope* scope,
+ Err* err) {
+ if (scope->IsProcessingBuildConfig()) {
+ *err = Err(node, "Not valid from the build config.",
+ "You can't do this kind of thing from the build config script, "
+ "silly!\nPut it in a regular BUILD file.");
+ return false;
+ }
+ return true;
+}
+
+bool FillTargetBlockScope(const Scope* scope,
+ const FunctionCallNode* function,
+ const char* target_type,
+ const BlockNode* block,
+ const std::vector<Value>& args,
+ Scope* block_scope,
+ Err* err) {
+ if (!block) {
+ FillNeedsBlockError(function, err);
+ return false;
+ }
+
+ // Copy the target defaults, if any, into the scope we're going to execute
+ // the block in.
+ const Scope* default_scope = scope->GetTargetDefaults(target_type);
+ if (default_scope) {
+ if (!default_scope->NonRecursiveMergeTo(block_scope, function,
+ "target defaults", err))
+ return false;
+ }
+
+ // The name is the single argument to the target function.
+ if (!EnsureSingleStringArg(function, args, err))
+ return false;
+
+ // Set the target name variable to the current target, and mark it used
+ // because we don't want to issue an error if the script ignores it.
+ const base::StringPiece target_name("target_name");
+ block_scope->SetValue(target_name, Value(function, args[0].string_value()),
+ function);
+ block_scope->MarkUsed(target_name);
+ return true;
+}
+
+bool EnsureSingleStringArg(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (args.size() != 1) {
+ *err = Err(function->function(), "Incorrect arguments.",
+ "This function requires a single string argument.");
+ return false;
+ }
+ return args[0].VerifyTypeIs(Value::STRING, err);
+}
+
+const SourceDir& SourceDirForFunctionCall(const FunctionCallNode* function) {
+ return function->function().location().file()->dir();
+}
+
+const Label& ToolchainLabelForScope(const Scope* scope) {
+ return scope->settings()->toolchain()->label();
+}
+
+Label MakeLabelForScope(const Scope* scope,
+ const FunctionCallNode* function,
+ const std::string& name) {
+ const SourceDir& input_dir = SourceDirForFunctionCall(function);
+ const Label& toolchain_label = ToolchainLabelForScope(scope);
+ return Label(input_dir, name, toolchain_label.dir(), toolchain_label.name());
+}
+
+namespace functions {
+
+// assert ----------------------------------------------------------------------
+
+const char kAssert[] = "assert";
+const char kAssert_Help[] =
+ "TODO(brettw) WRITE ME";
+
+Value RunAssert(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (args.size() != 1) {
+ *err = Err(function->function(), "Wrong number of arguments.",
+ "assert() takes one argument, "
+ "were you expecting somethig else?");
+ } else if (args[0].InterpretAsInt() == 0) {
+ *err = Err(function->function(), "Assertion failed.");
+ if (args[0].origin()) {
+ // If you do "assert(foo)" we'd ideally like to show you where foo was
+ // set, and in this case the origin of the args will tell us that.
+ // However, if you do "assert(foo && bar)" the source of the value will
+ // be the assert like, which isn't so helpful.
+ //
+ // So we try to see if the args are from the same line or not. This will
+ // break if you do "assert(\nfoo && bar)" and we may show the second line
+ // as the source, oh well. The way around this is to check to see if the
+ // origin node is inside our function call block.
+ Location origin_location = args[0].origin()->GetRange().begin();
+ if (origin_location.file() != function->function().location().file() ||
+ origin_location.line_number() !=
+ function->function().location().line_number()) {
+ err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
+ "This is where it was set."));
+ }
+ }
+ }
+ return Value();
+}
+
+// config ----------------------------------------------------------------------
+
+const char kConfig[] = "config";
+const char kConfig_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunConfig(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Scope* scope,
+ Err* err) {
+ if (!EnsureSingleStringArg(function, args, err) ||
+ !EnsureNotProcessingImport(function, scope, err))
+ return Value();
+
+ Label label(MakeLabelForScope(scope, function, args[0].string_value()));
+
+ if (g_scheduler->verbose_logging())
+ g_scheduler->Log("Generating config", label.GetUserVisibleName(true));
+
+ // Create the empty config object.
+ ItemTree* tree = &scope->settings()->build_settings()->item_tree();
+ Config* config = Config::GetConfig(scope->settings(), function->GetRange(),
+ label, NULL, err);
+ if (err->has_error())
+ return Value();
+
+ // Fill it.
+ const SourceDir input_dir = SourceDirForFunctionCall(function);
+ ConfigValuesGenerator gen(&config->config_values(), scope,
+ function->function(), input_dir, err);
+ gen.Run();
+ if (err->has_error())
+ return Value();
+
+ // Mark as complete.
+ {
+ base::AutoLock lock(tree->lock());
+ tree->MarkItemDefinedLocked(scope->settings()->build_settings(), label,
+ err);
+ }
+ return Value();
+}
+
+// declare_args ----------------------------------------------------------------
+
+const char kDeclareArgs[] = "declare_args";
+const char kDeclareArgs_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunDeclareArgs(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Scope* scope,
+ Err* err) {
+ // Only allow this to be called once. We use a variable in the current scope
+ // with a name the parser will reject if the user tried to type it.
+ const char did_declare_args_var[] = "@@declared_args";
+ if (scope->GetValue(did_declare_args_var)) {
+ *err = Err(function->function(), "Duplicate call to declared_args.");
+ err->AppendSubErr(
+ Err(scope->GetValue(did_declare_args_var)->origin()->GetRange(),
+ "See the original call."));
+ return Value();
+ }
+
+ // Find the root scope where the values will be set.
+ Scope* root = scope->mutable_containing();
+ if (!root || root->containing() || !scope->IsProcessingBuildConfig()) {
+ *err = Err(function->function(), "declare_args called incorrectly."
+ "It must be called only from the build config script and in the "
+ "root scope.");
+ return Value();
+ }
+
+ // Take all variables set in the current scope as default values and put
+ // them in the parent scope. The values in the current scope are the defaults,
+ // then we apply the external args to this list.
+ Scope::KeyValueVector values;
+ scope->GetCurrentScopeValues(&values);
+ for (size_t i = 0; i < values.size(); i++) {
+ // TODO(brettw) actually import the arguments from the command line rather
+ // than only using the defaults.
+ root->SetValue(values[i].first, values[i].second,
+ values[i].second.origin());
+ }
+
+ scope->SetValue(did_declare_args_var, Value(function, 1), NULL);
+ return Value();
+}
+
+// import ----------------------------------------------------------------------
+
+const char kImport[] = "import";
+const char kImport_Help[] =
+ "import: Import a file into the current scope.\n"
+ "\n"
+ " The import command loads the rules and variables resulting from\n"
+ " executing the given file into the current scope.\n"
+ "\n"
+ " By convention, imported files are named with a .gni extension.\n"
+ "\n"
+ " It does not do an \"include\". The imported file is executed in a\n"
+ " standalone environment from the caller of the import command. The\n"
+ " results of this execution are cached for other files that import the\n"
+ " same .gni file.\n"
+ "\n"
+ " Note that you can not import a BUILD.gn file that's otherwise used\n"
+ " in the build. Files must either be imported or implicitly loaded as\n"
+ " a result of deps rules, but not both.\n"
+ "\n"
+ " The imported file's scope will be merged with the scope at the point\n"
+ " import was called. If there is a conflict (both the current scope and\n"
+ " the imported file define some variable or rule with the same name)\n"
+ " a runtime error will be thrown. Therefore, it's good practice to\n"
+ " minimize the stuff that an imported file defines.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ " import(\"//build/rules/idl_compilation_rule.gni\")\n"
+ "\n"
+ " # Looks in the current directory.\n"
+ " import(\"my_vars.gni\")\n";
+
+Value RunImport(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (!EnsureSingleStringArg(function, args, err) ||
+ !EnsureNotProcessingImport(function, scope, err))
+ return Value();
+
+ const SourceDir input_dir = SourceDirForFunctionCall(function);
+ SourceFile import_file =
+ input_dir.ResolveRelativeFile(args[0].string_value());
+ scope->settings()->import_manager().DoImport(import_file, function,
+ scope, err);
+ return Value();
+}
+
+// set_defaults ----------------------------------------------------------------
+
+const char kSetDefaults[] = "set_defaults";
+const char kSetDefaults_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunSetDefaults(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ if (!EnsureSingleStringArg(function, args, err))
+ return Value();
+ const std::string& target_type(args[0].string_value());
+
+ // Ensure there aren't defaults already set.
+ if (scope->GetTargetDefaults(target_type)) {
+ *err = Err(function->function(),
+ "This target type defaults were already set.");
+ return Value();
+ }
+
+ // Execute the block in a new scope that has a parent of the containing
+ // scope.
+ Scope block_scope(scope);
+ if (!FillTargetBlockScope(scope, function,
+ function->function().value().data(),
+ block, args, &block_scope, err))
+ return Value();
+
+ // Run the block for the rule invocation.
+ block->ExecuteBlockInScope(&block_scope, err);
+ if (err->has_error())
+ return Value();
+
+ // Now copy the values set on the scope we made into the free-floating one
+ // (with no containing scope) used to hold the target defaults.
+ Scope* dest = scope->MakeTargetDefaults(target_type);
+ block_scope.NonRecursiveMergeTo(dest, function, "<SHOULD NOT FAIL>", err);
+ return Value();
+}
+
+// set_sources_assignment_filter -----------------------------------------------
+
+const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
+const char kSetSourcesAssignmentFilter_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunSetSourcesAssignmentFilter(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ if (args.size() != 1) {
+ *err = Err(function, "set_sources_assignment_filter takes one argument.");
+ } else {
+ scoped_ptr<PatternList> f(new PatternList);
+ f->SetFromValue(args[0], err);
+ if (!err->has_error())
+ scope->set_sources_assignment_filter(f.Pass());
+ }
+ return Value();
+}
+
+// print -----------------------------------------------------------------------
+
+const char kPrint[] = "print";
+const char kPrint_Help[] =
+ "print(...)\n"
+ " Prints all arguments to the console separated by spaces. A newline is\n"
+ " automatically appended to the end.\n"
+ "\n"
+ " This function is intended for debugging. Note that build files are run\n"
+ " in parallel so you may get interleaved prints. A buildfile may also\n"
+ " be executed more than once in parallel in the context of different\n"
+ " toolchains so the prints from one file may be duplicated or\n"
+ " interleaved with itself.\n"
+ "\n"
+ "Examples:\n"
+ " print(\"Hello world\")\n"
+ "\n"
+ " print(sources, deps)\n";
+
+Value RunPrint(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err) {
+ for (size_t i = 0; i < args.size(); i++) {
+ if (i != 0)
+ std::cout << " ";
+ std::cout << args[i].ToString();
+ }
+ std::cout << std::endl;
+ return Value();
+}
+
+// -----------------------------------------------------------------------------
+
+FunctionInfo::FunctionInfo()
+ : generic_block_runner(NULL),
+ executed_block_runner(NULL),
+ no_block_runner(NULL),
+ help(NULL) {
+}
+
+FunctionInfo::FunctionInfo(GenericBlockFunction gbf, const char* in_help)
+ : generic_block_runner(gbf),
+ executed_block_runner(NULL),
+ no_block_runner(NULL),
+ help(in_help) {
+}
+
+FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf, const char* in_help)
+ : generic_block_runner(NULL),
+ executed_block_runner(ebf),
+ no_block_runner(NULL),
+ help(in_help) {
+}
+
+FunctionInfo::FunctionInfo(NoBlockFunction nbf, const char* in_help)
+ : generic_block_runner(NULL),
+ executed_block_runner(NULL),
+ no_block_runner(nbf),
+ help(in_help) {
+}
+
+// Setup the function map via a static initializer. We use this because it
+// avoids race conditions without having to do some global setup function or
+// locking-heavy singleton checks at runtime. In practice, we always need this
+// before we can do anything interesting, so it's OK to wait for the
+// initializer.
+struct FunctionInfoInitializer {
+ FunctionInfoMap map;
+
+ FunctionInfoInitializer() {
+ #define INSERT_FUNCTION(command) \
+ map[k##command] = FunctionInfo(&Run##command, k##command##_Help);
+
+ INSERT_FUNCTION(Assert)
+ INSERT_FUNCTION(Component)
+ INSERT_FUNCTION(Config)
+ INSERT_FUNCTION(Copy)
+ INSERT_FUNCTION(Custom)
+ INSERT_FUNCTION(DeclareArgs)
+ INSERT_FUNCTION(ExecScript)
+ INSERT_FUNCTION(Executable)
+ INSERT_FUNCTION(Group)
+ INSERT_FUNCTION(Import)
+ INSERT_FUNCTION(Print)
+ INSERT_FUNCTION(ProcessFileTemplate)
+ INSERT_FUNCTION(ReadFile)
+ INSERT_FUNCTION(SetDefaults)
+ INSERT_FUNCTION(SetDefaultToolchain)
+ INSERT_FUNCTION(SetSourcesAssignmentFilter)
+ INSERT_FUNCTION(SharedLibrary)
+ INSERT_FUNCTION(StaticLibrary)
+ INSERT_FUNCTION(Template)
+ INSERT_FUNCTION(Test)
+ INSERT_FUNCTION(Tool)
+ INSERT_FUNCTION(Toolchain)
+ INSERT_FUNCTION(WriteFile)
+
+ #undef INSERT_FUNCTION
+ }
+};
+const FunctionInfoInitializer function_info;
+
+const FunctionInfoMap& GetFunctions() {
+ return function_info.map;
+}
+
+Value RunFunction(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ const Token& name = function->function();
+
+ const FunctionInfoMap& function_map = GetFunctions();
+ FunctionInfoMap::const_iterator found_function =
+ function_map.find(name.value());
+ if (found_function == function_map.end()) {
+ // No build-in function matching this, check for a template.
+ const FunctionCallNode* rule =
+ scope->GetTemplate(function->function().value().as_string());
+ if (rule)
+ return RunTemplateInvocation(scope, function, args, block, rule, err);
+
+ *err = Err(name, "Unknown function.");
+ return Value();
+ }
+
+ if (found_function->second.generic_block_runner) {
+ if (!block) {
+ FillNeedsBlockError(function, err);
+ return Value();
+ }
+ return found_function->second.generic_block_runner(
+ scope, function, args, block, err);
+ }
+
+ if (found_function->second.executed_block_runner) {
+ if (!block) {
+ FillNeedsBlockError(function, err);
+ return Value();
+ }
+
+ Scope block_scope(scope);
+ block->ExecuteBlockInScope(&block_scope, err);
+ if (err->has_error())
+ return Value();
+ return found_function->second.executed_block_runner(
+ function, args, &block_scope, err);
+ }
+
+ // Otherwise it's a no-block function.
+ return found_function->second.no_block_runner(scope, function, args, err);
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/functions.h b/chromium/tools/gn/functions.h
new file mode 100644
index 00000000000..d28804dab07
--- /dev/null
+++ b/chromium/tools/gn/functions.h
@@ -0,0 +1,303 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_FUNCTIONS_H_
+#define TOOLS_GN_FUNCTIONS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "base/strings/string_piece.h"
+
+class Err;
+class BlockNode;
+class FunctionCallNode;
+class Label;
+class ListNode;
+class ParseNode;
+class Scope;
+class SourceDir;
+class Token;
+class Value;
+
+// -----------------------------------------------------------------------------
+
+namespace functions {
+
+// This type of function invocation takes a block node that it will execute.
+typedef Value (*GenericBlockFunction)(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+// This type of function takes a block, but does not need to control execution
+// of it. The dispatch function will pre-execute the block and pass the
+// resulting block_scope to the function.
+typedef Value(*ExecutedBlockFunction)(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Scope* block_scope,
+ Err* err);
+
+// This type of function does not take a block. It just has arguments.
+typedef Value (*NoBlockFunction)(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kAssert[];
+extern const char kAssert_Help[];
+Value RunAssert(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kComponent[];
+extern const char kComponent_Help[];
+Value RunComponent(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kConfig[];
+extern const char kConfig_Help[];
+Value RunConfig(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Scope* block_scope,
+ Err* err);
+
+extern const char kCopy[];
+extern const char kCopy_Help[];
+Value RunCopy(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Scope* block_scope,
+ Err* err);
+
+extern const char kCustom[];
+extern const char kCustom_Help[];
+Value RunCustom(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kDeclareArgs[];
+extern const char kDeclareArgs_Help[];
+Value RunDeclareArgs(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Scope* block_scope,
+ Err* err);
+
+extern const char kExecScript[];
+extern const char kExecScript_Help[];
+Value RunExecScript(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kExecutable[];
+extern const char kExecutable_Help[];
+Value RunExecutable(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kGroup[];
+extern const char kGroup_Help[];
+Value RunGroup(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kImport[];
+extern const char kImport_Help[];
+Value RunImport(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kPrint[];
+extern const char kPrint_Help[];
+Value RunPrint(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kProcessFileTemplate[];
+extern const char kProcessFileTemplate_Help[];
+Value RunProcessFileTemplate(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kReadFile[];
+extern const char kReadFile_Help[];
+Value RunReadFile(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kSetDefaults[];
+extern const char kSetDefaults_Help[];
+Value RunSetDefaults(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kSetDefaultToolchain[];
+extern const char kSetDefaultToolchain_Help[];
+Value RunSetDefaultToolchain(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kSetSourcesAssignmentFilter[];
+extern const char kSetSourcesAssignmentFilter_Help[];
+Value RunSetSourcesAssignmentFilter(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+extern const char kSharedLibrary[];
+extern const char kSharedLibrary_Help[];
+Value RunSharedLibrary(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kStaticLibrary[];
+extern const char kStaticLibrary_Help[];
+Value RunStaticLibrary(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kTemplate[];
+extern const char kTemplate_Help[];
+Value RunTemplate(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kTest[];
+extern const char kTest_Help[];
+Value RunTest(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kTool[];
+extern const char kTool_Help[];
+Value RunTool(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kToolchain[];
+extern const char kToolchain_Help[];
+Value RunToolchain(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err);
+
+extern const char kWriteFile[];
+extern const char kWriteFile_Help[];
+Value RunWriteFile(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+// -----------------------------------------------------------------------------
+
+// One function record. Only one of the given runner types will be non-null
+// which indicates the type of function it is.
+struct FunctionInfo {
+ FunctionInfo();
+ FunctionInfo(GenericBlockFunction gbf, const char* in_help);
+ FunctionInfo(ExecutedBlockFunction ebf, const char* in_help);
+ FunctionInfo(NoBlockFunction nbf, const char* in_help);
+
+ GenericBlockFunction generic_block_runner;
+ ExecutedBlockFunction executed_block_runner;
+ NoBlockFunction no_block_runner;
+
+ const char* help;
+};
+
+typedef base::hash_map<base::StringPiece, FunctionInfo> FunctionInfoMap;
+
+// Returns the mapping of all built-in functions.
+const FunctionInfoMap& GetFunctions();
+
+// Runs the given function.
+Value RunFunction(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block, // Optional.
+ Err* err);
+
+} // namespace functions
+
+// Helper functions -----------------------------------------------------------
+
+// Verifies that the current scope is not processing an import. If it is, it
+// will set the error, blame the given parse node for it, and return false.
+bool EnsureNotProcessingImport(const ParseNode* node,
+ const Scope* scope,
+ Err* err);
+
+// Like EnsureNotProcessingImport but checks for running the build config.
+bool EnsureNotProcessingBuildConfig(const ParseNode* node,
+ const Scope* scope,
+ Err* err);
+
+// Sets up the |block_scope| for executing a target (or something like it).
+// The |scope| is the containing scope. It should have been already set as the
+// parent for the |block_scope| when the |block_scope| was created.
+//
+// This will set up the target defaults and set the |target_name| variable in
+// the block scope to the current target name, which is assumed to be the first
+// argument to the function.
+//
+// On success, returns true. On failure, sets the error and returns false.
+bool FillTargetBlockScope(const Scope* scope,
+ const FunctionCallNode* function,
+ const char* target_type,
+ const BlockNode* block,
+ const std::vector<Value>& args,
+ Scope* block_scope,
+ Err* err);
+
+// Validates that the given function call has one string argument. This is
+// the most common function signature, so it saves space to have this helper.
+// Returns false and sets the error on failure.
+bool EnsureSingleStringArg(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Err* err);
+
+// Returns the source directory for the file comtaining the given function
+// invocation.
+const SourceDir& SourceDirForFunctionCall(const FunctionCallNode* function);
+
+// Returns the name of the toolchain for the given scope.
+const Label& ToolchainLabelForScope(const Scope* scope);
+
+// Generates a label for the given scope, using the current directory and
+// toolchain, and the given name.
+Label MakeLabelForScope(const Scope* scope,
+ const FunctionCallNode* function,
+ const std::string& name);
+
+#endif // TOOLS_GN_FUNCTIONS_H_
diff --git a/chromium/tools/gn/functions_target.cc b/chromium/tools/gn/functions_target.cc
new file mode 100644
index 00000000000..a4808b3ad60
--- /dev/null
+++ b/chromium/tools/gn/functions_target.cc
@@ -0,0 +1,277 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/functions.h"
+
+#include "tools/gn/err.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/target_generator.h"
+#include "tools/gn/value.h"
+
+namespace functions {
+
+namespace {
+
+Value ExecuteGenericTarget(const char* target_type,
+ Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ if (!EnsureNotProcessingImport(function, scope, err) ||
+ !EnsureNotProcessingBuildConfig(function, scope, err))
+ return Value();
+ Scope block_scope(scope);
+ if (!FillTargetBlockScope(scope, function, target_type, block,
+ args, &block_scope, err))
+ return Value();
+
+ block->ExecuteBlockInScope(&block_scope, err);
+ if (err->has_error())
+ return Value();
+
+ TargetGenerator::GenerateTarget(&block_scope, function->function(), args,
+ target_type, err);
+
+ block_scope.CheckForUnusedVars(err);
+ return Value();
+}
+
+} // namespace
+
+// component -------------------------------------------------------------------
+
+const char kComponent[] = "component";
+const char kComponent_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunComponent(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ // A component is either a shared or static library, depending on the value
+ // of |component_mode|.
+ const Value* component_mode_value = scope->GetValue("component_mode");
+
+ static const char helptext[] =
+ "You're declaring a component here but have not defined "
+ "\"component_mode\" to\neither \"shared_library\" or \"static_library\".";
+ if (!component_mode_value) {
+ *err = Err(function->function(), "No component mode set.", helptext);
+ return Value();
+ }
+ if (component_mode_value->type() != Value::STRING ||
+ (component_mode_value->string_value() != functions::kSharedLibrary &&
+ component_mode_value->string_value() != functions::kStaticLibrary)) {
+ *err = Err(function->function(), "Invalid component mode set.", helptext);
+ return Value();
+ }
+ const std::string& component_mode = component_mode_value->string_value();
+
+ if (!EnsureNotProcessingImport(function, scope, err))
+ return Value();
+ Scope block_scope(scope);
+ if (!FillTargetBlockScope(scope, function, component_mode.c_str(), block,
+ args, &block_scope, err))
+ return Value();
+
+ block->ExecuteBlockInScope(&block_scope, err);
+ if (err->has_error())
+ return Value();
+
+ TargetGenerator::GenerateTarget(&block_scope, function->function(), args,
+ component_mode, err);
+ return Value();
+}
+
+// copy ------------------------------------------------------------------------
+
+const char kCopy[] = "copy";
+const char kCopy_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunCopy(const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ Scope* scope,
+ Err* err) {
+ if (!EnsureNotProcessingImport(function, scope, err) ||
+ !EnsureNotProcessingBuildConfig(function, scope, err))
+ return Value();
+ TargetGenerator::GenerateTarget(scope, function->function(), args,
+ functions::kCopy, err);
+ return Value();
+}
+
+// custom ----------------------------------------------------------------------
+
+const char kCustom[] = "custom";
+const char kCustom_Help[] =
+ "custom: Declare a script-generated target.\n"
+ "\n"
+ " This target type allows you to run a script over a set of source\n"
+ " files and generate a set of output files.\n"
+ "\n"
+ " The script will be executed with the given arguments with the current\n"
+ " directory being that of the current BUILD file.\n"
+ "\n"
+ " There are two modes. The first mode is the \"per-file\" mode where you\n"
+ " specify a list of sources and the script is run once for each one as a\n"
+ " build rule. In this case, each file specified in the |outputs|\n"
+ " variable must be unique when applied to each source file (normally you\n"
+ " would reference |{{source_name_part}}| from within each one) or the\n"
+ " build system will get confused about how to build those files. You\n"
+ " should use the |data| variable to list all additional dependencies of\n"
+ " your script: these will be added as dependencies for each build step.\n"
+ "\n"
+ " The second mode is when you just want to run a script once rather than\n"
+ " as a general rule over a set of files. In this case you don't list any\n"
+ " sources. Dependencies of your script are specified only in the |data|\n"
+ " variable and your |outputs| variable should just list all outputs.\n"
+ "\n"
+ "Variables:\n"
+ "\n"
+ " args, data, deps, outputs, script*, sources\n"
+ " * = required\n"
+ "\n"
+ " There are some special substrings that will be searched for when\n"
+ " processing some variables:\n"
+ "\n"
+ " {{source}}\n"
+ " Expanded in |args|, this is the name of the source file relative\n"
+ " to the current directory when running the script. This is how\n"
+ " you specify the current input file to your script.\n"
+ "\n"
+ " {{source_name_part}}\n"
+ " Expanded in |args| and |outputs|, this is just the filename part\n"
+ " of the current source file with no directory or extension. This\n"
+ " is how you specify a name transformation to the output. Normally\n"
+ " you would write an output as\n"
+ " \"$target_output_dir/{{source_name_part}}.o\".\n"
+ "\n"
+ " All |outputs| files must be inside the output directory of the build.\n"
+ " You would generally use |$target_output_dir| or |$target_gen_dir| to\n"
+ " reference the output or generated intermediate file directories,\n"
+ " respectively.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ " custom(\"general_rule\") {\n"
+ " script = \"do_processing.py\"\n"
+ " sources = [ \"foo.idl\" ]\n"
+ " data = [ \"my_configuration.txt\" ]\n"
+ " outputs = [ \"$target_gen_dir/{{source_name_part}}.h\" ]\n"
+ " args = [ \"{{source}}\",\n"
+ " \"-o\",\n"
+ " \"$relative_target_gen_dir/{{source_name_part}}.h\" ]\n"
+ " }\n"
+ "\n"
+ " custom(\"just_run_this_guy_once\") {\n"
+ " script = \"doprocessing.py\"\n"
+ " data = [ \"my_configuration.txt\" ]\n"
+ " outputs = [ \"$target_gen_dir/insightful_output.txt\" ]\n"
+ " args = [ \"--output_dir\", $target_gen_dir ]\n"
+ " }\n";
+
+Value RunCustom(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ return ExecuteGenericTarget(functions::kCustom, scope, function, args,
+ block, err);
+}
+
+// executable ------------------------------------------------------------------
+
+const char kExecutable[] = "executable";
+const char kExecutable_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunExecutable(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ return ExecuteGenericTarget(functions::kExecutable, scope, function, args,
+ block, err);
+}
+
+// group -----------------------------------------------------------------------
+
+const char kGroup[] = "group";
+const char kGroup_Help[] =
+ "group: Declare a named group of targets.\n"
+ "\n"
+ " This target type allows you to create meta-targets that just collect a\n"
+ " set of dependencies into one named target.\n"
+ "\n"
+ "Variables:\n"
+ "\n"
+ " deps\n"
+ "\n"
+ "Example:\n"
+ " group(\"all\") {\n"
+ " deps = [\n"
+ " \"//project:runner\",\n"
+ " \"//project:unit_tests\",\n"
+ " ]\n"
+ " }";
+
+Value RunGroup(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ return ExecuteGenericTarget(functions::kGroup, scope, function, args,
+ block, err);
+}
+
+// shared_library --------------------------------------------------------------
+
+const char kSharedLibrary[] = "shared_library";
+const char kSharedLibrary_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunSharedLibrary(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ return ExecuteGenericTarget(functions::kSharedLibrary, scope, function, args,
+ block, err);
+}
+
+// static_library --------------------------------------------------------------
+
+const char kStaticLibrary[] = "static_library";
+const char kStaticLibrary_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunStaticLibrary(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ return ExecuteGenericTarget(functions::kStaticLibrary, scope, function, args,
+ block, err);
+}
+
+// test ------------------------------------------------------------------------
+
+const char kTest[] = "test";
+const char kTest_Help[] =
+ "TODO(brettw) write this.";
+
+Value RunTest(Scope* scope,
+ const FunctionCallNode* function,
+ const std::vector<Value>& args,
+ BlockNode* block,
+ Err* err) {
+ return ExecuteGenericTarget(functions::kExecutable, scope, function, args,
+ block, err);
+}
+
+} // namespace functions
diff --git a/chromium/tools/gn/generate_test_gn_data.cc b/chromium/tools/gn/generate_test_gn_data.cc
new file mode 100644
index 00000000000..017c4c44319
--- /dev/null
+++ b/chromium/tools/gn/generate_test_gn_data.cc
@@ -0,0 +1,129 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <fstream>
+#include <iostream>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+
+// Usage: just run in the directory where you want your test source root to be.
+
+int files_written = 0;
+int targets_written = 0;
+
+base::FilePath UTF8ToFilePath(const std::string& s) {
+#if defined(OS_WIN)
+ return base::FilePath(UTF8ToWide(s));
+#else
+ return base::FilePath(s);
+#endif
+}
+
+std::string FilePathToUTF8(const base::FilePath& path) {
+#if defined(OS_WIN)
+ return WideToUTF8(path.value());
+#else
+ return path.value();
+#endif
+}
+
+base::FilePath RepoPathToPathName(const std::vector<int>& repo_path) {
+ base::FilePath ret;
+ for (size_t i = 0; i < repo_path.size(); i++) {
+ ret = ret.Append(UTF8ToFilePath(base::IntToString(repo_path[i])));
+ }
+ return ret;
+}
+
+std::string TargetIndexToLetter(int target_index) {
+ char ret[2];
+ ret[0] = 'a' + target_index;
+ ret[1] = 0;
+ return ret;
+}
+
+std::string RepoPathToTargetName(const std::vector<int>& repo_path,
+ int target_index) {
+ std::string ret;
+ for (size_t i = 0; i < repo_path.size(); i++) {
+ if (i != 0)
+ ret.push_back('_');
+ ret.append(base::IntToString(repo_path[i]));
+ }
+ ret += TargetIndexToLetter(target_index);
+ return ret;
+}
+
+std::string RepoPathToFullTargetName(const std::vector<int>& repo_path,
+ int target_index) {
+ std::string ret;
+ for (size_t i = 0; i < repo_path.size(); i++) {
+ ret.push_back('/');
+ ret.append(base::IntToString(repo_path[i]));
+ }
+
+ ret += ":" + RepoPathToTargetName(repo_path, target_index);
+ return ret;
+}
+
+void WriteLevel(const std::vector<int>& repo_path,
+ int spread,
+ int max_depth,
+ int targets_per_level,
+ int files_per_target) {
+ base::FilePath dirname = RepoPathToPathName(repo_path);
+ base::FilePath filename = dirname.AppendASCII("BUILD.gn");
+ std::cout << "Writing " << FilePathToUTF8(filename) << "\n";
+
+ // Don't keep the file open while recursing.
+ {
+ file_util::CreateDirectory(dirname);
+
+ std::ofstream file;
+ file.open(FilePathToUTF8(filename).c_str(),
+ std::ios_base::out | std::ios_base::binary);
+ files_written++;
+
+ for (int i = 0; i < targets_per_level; i++) {
+ targets_written++;
+ file << "executable(\"" << RepoPathToTargetName(repo_path, i)
+ << "\") {\n";
+ file << " sources = [\n";
+ for (int f = 0; f < files_per_target; f++)
+ file << " \"" << base::IntToString(f) << ".cc\",\n";
+
+ if (repo_path.size() < (size_t)max_depth) {
+ file << " ]\n";
+ file << " deps = [\n";
+ for (int d = 0; d < spread; d++) {
+ std::vector<int> cur = repo_path;
+ cur.push_back(d);
+ for (int t = 0; t < targets_per_level; t++)
+ file << " \"" << RepoPathToFullTargetName(cur, t) << "\",\n";
+ }
+ }
+ file << " ]\n}\n\n";
+ }
+ }
+ if (repo_path.size() < (size_t)max_depth) {
+ // Recursively generate subdirs.
+ for (int i = 0; i < spread; i++) {
+ std::vector<int> cur = repo_path;
+ cur.push_back(i);
+ WriteLevel(cur, spread, max_depth, targets_per_level, files_per_target);
+ }
+ }
+}
+
+int main() {
+ WriteLevel(std::vector<int>(), 5, 4, 3, 50); // 781 files, 2343 targets
+ //WriteLevel(std::vector<int>(), 6, 4, 2, 50);
+ std::cout << "Wrote " << files_written << " files and "
+ << targets_written << " targets.\n";
+ return 0;
+}
diff --git a/chromium/tools/gn/gn.gyp b/chromium/tools/gn/gn.gyp
new file mode 100644
index 00000000000..14267ddf6fa
--- /dev/null
+++ b/chromium/tools/gn/gn.gyp
@@ -0,0 +1,191 @@
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ 'target_name': 'gn_lib',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ ],
+ 'sources': [
+ 'binary_target_generator.cc',
+ 'binary_target_generator.h',
+ 'build_settings.cc',
+ 'build_settings.h',
+ 'command_desc.cc',
+ 'command_gen.cc',
+ 'command_help.cc',
+ 'commands.cc',
+ 'commands.h',
+ 'config.cc',
+ 'config.h',
+ 'config_values.cc',
+ 'config_values.h',
+ 'config_values_extractors.cc',
+ 'config_values_extractors.h',
+ 'config_values_generator.cc',
+ 'config_values_generator.h',
+ 'copy_target_generator.cc',
+ 'copy_target_generator.h',
+ 'err.cc',
+ 'err.h',
+ 'escape.cc',
+ 'escape.h',
+ 'file_template.cc',
+ 'file_template.h',
+ 'filesystem_utils.cc',
+ 'filesystem_utils.h',
+ 'functions_target.cc',
+ 'functions.cc',
+ 'functions.h',
+ 'function_exec_script.cc',
+ 'function_process_file_template.cc',
+ 'function_read_file.cc',
+ 'function_set_default_toolchain.cc',
+ 'function_template.cc',
+ 'function_toolchain.cc',
+ 'function_write_file.cc',
+ 'group_target_generator.cc',
+ 'group_target_generator.h',
+ 'import_manager.cc',
+ 'import_manager.h',
+ 'input_conversion.cc',
+ 'input_conversion.h',
+ 'input_file.cc',
+ 'input_file.h',
+ 'input_file_manager.cc',
+ 'input_file_manager.h',
+ 'item.cc',
+ 'item.h',
+ 'item_node.cc',
+ 'item_node.h',
+ 'item_tree.cc',
+ 'item_tree.h',
+ 'label.cc',
+ 'label.h',
+ 'location.h',
+ 'ninja_binary_target_writer.cc',
+ 'ninja_binary_target_writer.h',
+ 'ninja_build_writer.cc',
+ 'ninja_build_writer.h',
+ 'ninja_copy_target_writer.cc',
+ 'ninja_copy_target_writer.h',
+ 'ninja_group_target_writer.cc',
+ 'ninja_group_target_writer.h',
+ 'ninja_helper.cc',
+ 'ninja_helper.h',
+ 'ninja_script_target_writer.cc',
+ 'ninja_script_target_writer.h',
+ 'ninja_target_writer.cc',
+ 'ninja_target_writer.h',
+ 'ninja_toolchain_writer.cc',
+ 'ninja_toolchain_writer.h',
+ 'ninja_writer.cc',
+ 'ninja_writer.h',
+ 'operators.cc',
+ 'operators.h',
+ 'output_file.h',
+ 'parse_tree.cc',
+ 'parse_tree.h',
+ 'parser.cc',
+ 'parser.h',
+ 'path_output.cc',
+ 'path_output.h',
+ 'pattern.cc',
+ 'pattern.h',
+ 'scheduler.cc',
+ 'scheduler.h',
+ 'scope.cc',
+ 'scope.h',
+ 'scope_per_file_provider.cc',
+ 'scope_per_file_provider.h',
+ 'script_target_generator.cc',
+ 'script_target_generator.h',
+ 'script_values.cc',
+ 'script_values.h',
+ 'settings.cc',
+ 'settings.h',
+ 'setup.cc',
+ 'setup.h',
+ 'source_dir.cc',
+ 'source_dir.h',
+ 'source_file.cc',
+ 'source_file.h',
+ 'standard_out.cc',
+ 'standard_out.h',
+ 'string_utils.cc',
+ 'string_utils.h',
+ 'target.cc',
+ 'target.h',
+ 'target_generator.cc',
+ 'target_generator.h',
+ 'target_manager.cc',
+ 'target_manager.h',
+ 'token.cc',
+ 'token.h',
+ 'tokenizer.cc',
+ 'tokenizer.h',
+ 'toolchain.cc',
+ 'toolchain.h',
+ 'toolchain_manager.cc',
+ 'toolchain_manager.h',
+ 'value.cc',
+ 'value.h',
+ 'value_extractors.cc',
+ 'value_extractors.h',
+ 'variables.cc',
+ 'variables.h',
+ ],
+ },
+ {
+ 'target_name': 'gn',
+ 'type': 'executable',
+ 'sources': [
+ 'gn_main.cc',
+ ],
+ 'dependencies': [
+ 'gn_lib',
+ '../../base/base.gyp:base',
+ '../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ ],
+ },
+ {
+ 'target_name': 'gn_unittests',
+ 'type': '<(gtest_target_type)',
+ 'sources': [
+ 'escape_unittest.cc',
+ 'file_template_unittest.cc',
+ 'filesystem_utils_unittest.cc',
+ 'input_conversion_unittest.cc',
+ 'label_unittest.cc',
+ 'ninja_helper_unittest.cc',
+ 'parser_unittest.cc',
+ 'path_output_unittest.cc',
+ 'pattern_unittest.cc',
+ 'source_dir_unittest.cc',
+ 'string_utils_unittest.cc',
+ 'target_generator_unittest.cc',
+ 'target_manager_unittest.cc',
+ 'tokenizer_unittest.cc',
+ ],
+ 'dependencies': [
+ 'gn_lib',
+ '../../base/base.gyp:run_all_unittests',
+ '../../base/base.gyp:test_support_base',
+ '../../testing/gtest.gyp:gtest',
+ ],
+ },
+ {
+ 'target_name': 'generate_test_gn_data',
+ 'type': 'executable',
+ 'sources': [
+ 'generate_test_gn_data.cc',
+ ],
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ ],
+ }
+ ],
+}
diff --git a/chromium/tools/gn/gn_main.cc b/chromium/tools/gn/gn_main.cc
new file mode 100644
index 00000000000..c0300caff81
--- /dev/null
+++ b/chromium/tools/gn/gn_main.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "tools/gn/commands.h"
+#include "tools/gn/err.h"
+#include "tools/gn/location.h"
+
+namespace {
+
+std::vector<std::string> GetArgs(const CommandLine& cmdline) {
+ CommandLine::StringVector in_args = cmdline.GetArgs();
+#if defined(OS_WIN)
+ std::vector<std::string> out_args;
+ for (size_t i = 0; i < in_args.size(); i++)
+ out_args.push_back(base::WideToUTF8(in_args[i]));
+ return out_args;
+#else
+ return in_args;
+#endif
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ base::AtExitManager at_exit;
+ CommandLine::Init(argc, argv);
+
+ const CommandLine& cmdline = *CommandLine::ForCurrentProcess();
+ std::vector<std::string> args = GetArgs(cmdline);
+
+ std::string command;
+ if (cmdline.HasSwitch("help")) {
+ // Make "--help" default to help command.
+ command = commands::kHelp;
+ } else if (args.empty()) {
+ command = commands::kGen;
+ } else {
+ command = args[0];
+ args.erase(args.begin());
+ }
+
+ const commands::CommandInfoMap& command_map = commands::GetCommands();
+ commands::CommandInfoMap::const_iterator found_command =
+ command_map.find(command);
+
+ int retval;
+ if (found_command != command_map.end()) {
+ retval = found_command->second.runner(args);
+ } else {
+ Err(Location(),
+ "Command \"" + command + "\" unknown.").PrintToStdout();
+ commands::RunHelp(std::vector<std::string>());
+ retval = 1;
+ }
+
+ exit(retval); // Don't free memory, it can be really slow!
+ return retval;
+}
diff --git a/chromium/tools/gn/group_target_generator.cc b/chromium/tools/gn/group_target_generator.cc
new file mode 100644
index 00000000000..6f6fe32b355
--- /dev/null
+++ b/chromium/tools/gn/group_target_generator.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/group_target_generator.h"
+
+GroupTargetGenerator::GroupTargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Err* err)
+ : TargetGenerator(target, scope, function_token, err) {
+}
+
+GroupTargetGenerator::~GroupTargetGenerator() {
+}
+
+void GroupTargetGenerator::DoRun() {
+ target_->set_output_type(Target::GROUP);
+ // Groups only have the default types filled in by the target generator
+ // base class.
+}
diff --git a/chromium/tools/gn/group_target_generator.h b/chromium/tools/gn/group_target_generator.h
new file mode 100644
index 00000000000..a88ec03c881
--- /dev/null
+++ b/chromium/tools/gn/group_target_generator.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_GROUP_TARGET_GENERATOR_H_
+#define TOOLS_GN_GROUP_TARGET_GENERATOR_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/target_generator.h"
+
+// Populates a Target with the values for a group rule.
+class GroupTargetGenerator : public TargetGenerator {
+ public:
+ GroupTargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Err* err);
+ virtual ~GroupTargetGenerator();
+
+ protected:
+ virtual void DoRun() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GroupTargetGenerator);
+};
+
+#endif // TOOLS_GN_GROUP_TARGET_GENERATOR_H_
+
diff --git a/chromium/tools/gn/import_manager.cc b/chromium/tools/gn/import_manager.cc
new file mode 100644
index 00000000000..774f866334a
--- /dev/null
+++ b/chromium/tools/gn/import_manager.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/import_manager.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scheduler.h"
+
+namespace {
+
+// Returns a newly-allocated scope on success, null on failure.
+Scope* UncachedImport(const Settings* settings,
+ const SourceFile& file,
+ const ParseNode* node_for_err,
+ Err* err) {
+ const ParseNode* node = g_scheduler->input_file_manager()->SyncLoadFile(
+ node_for_err->GetRange(), settings->build_settings(), file, err);
+ if (!node)
+ return NULL;
+ const BlockNode* block = node->AsBlock();
+ CHECK(block);
+
+ scoped_ptr<Scope> scope(new Scope(settings->base_config()));
+ scope->SetProcessingImport();
+ block->ExecuteBlockInScope(scope.get(), err);
+ if (err->has_error())
+ return NULL;
+ scope->ClearProcessingImport();
+
+ return scope.release();
+}
+
+} // namesapce
+
+ImportManager::ImportManager() {
+}
+
+ImportManager::~ImportManager() {
+ STLDeleteContainerPairSecondPointers(imports_.begin(), imports_.end());
+}
+
+bool ImportManager::DoImport(const SourceFile& file,
+ const ParseNode* node_for_err,
+ Scope* scope,
+ Err* err) {
+ // See if we have a cached import, but be careful to actually do the scope
+ // copying outside of the lock.
+ const Scope* imported_scope = NULL;
+ {
+ base::AutoLock lock(lock_);
+ ImportMap::const_iterator found = imports_.find(file);
+ if (found != imports_.end())
+ imported_scope = found->second;
+ }
+
+ if (!imported_scope) {
+ // Do a new import of the file.
+ imported_scope = UncachedImport(scope->settings(), file,
+ node_for_err, err);
+ if (!imported_scope)
+ return false;
+
+ // We loaded the file outside the lock. This means that there could be a
+ // race and the file was already loaded on a background thread. Recover
+ // from this and use the existing one if that happens.
+ {
+ base::AutoLock lock(lock_);
+ ImportMap::const_iterator found = imports_.find(file);
+ if (found != imports_.end()) {
+ delete imported_scope;
+ imported_scope = found->second;
+ } else {
+ imports_[file] = imported_scope;
+ }
+ }
+ }
+
+ return imported_scope->NonRecursiveMergeTo(scope, node_for_err,
+ "import", err);
+}
diff --git a/chromium/tools/gn/import_manager.h b/chromium/tools/gn/import_manager.h
new file mode 100644
index 00000000000..725a5b28a0b
--- /dev/null
+++ b/chromium/tools/gn/import_manager.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_IMPORT_MANAGER_H_
+#define TOOLS_GN_IMPORT_MANAGER_H_
+
+#include <map>
+
+#include "base/synchronization/lock.h"
+
+class Err;
+class ParseNode;
+class Scope;
+class SourceFile;
+
+// Provides a cache of the results of importing scopes so the results can
+// be re-used rather than running the imported files multiple times.
+class ImportManager {
+ public:
+ ImportManager();
+ ~ImportManager();
+
+ // Does an import of the given file into the given scope. On error, sets the
+ // error and returns false.
+ bool DoImport(const SourceFile& file,
+ const ParseNode* node_for_err,
+ Scope* scope,
+ Err* err);
+
+ private:
+ base::Lock lock_;
+
+ // Owning pointers to the scopes.
+ typedef std::map<SourceFile, const Scope*> ImportMap;
+ ImportMap imports_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImportManager);
+};
+
+#endif // TOOLS_GN_IMPORT_MANAGER_H_
diff --git a/chromium/tools/gn/input_conversion.cc b/chromium/tools/gn/input_conversion.cc
new file mode 100644
index 00000000000..19a8047e882
--- /dev/null
+++ b/chromium/tools/gn/input_conversion.cc
@@ -0,0 +1,205 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "input_conversion.h"
+
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/err.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/label.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/parser.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/tokenizer.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+// Returns the "first bit" of some script output for writing to error messages.
+std::string GetExampleOfBadInput(const std::string& input) {
+ std::string result(input);
+
+ // Maybe the result starts with a blank line or something, which we don't
+ // want.
+ TrimWhitespaceASCII(result, TRIM_ALL, &result);
+
+ // Now take the first line, or the first set of chars, whichever is shorter.
+ bool trimmed = false;
+ size_t newline_offset = result.find('\n');
+ if (newline_offset != std::string::npos) {
+ trimmed = true;
+ result.resize(newline_offset);
+ }
+ TrimWhitespaceASCII(result, TRIM_ALL, &result);
+
+ const size_t kMaxSize = 50;
+ if (result.size() > kMaxSize) {
+ trimmed = true;
+ result.resize(kMaxSize);
+ }
+
+ if (trimmed)
+ result.append("...");
+ return result;
+}
+
+// When parsing the result as a value, we may get various types of errors.
+// This creates an error message for this case with an optional nested error
+// message to reference. If there is no nested err, pass Err().
+//
+// This code also takes care to rewrite the original error which will reference
+// the temporary InputFile which won't exist when the error is propogated
+// out to a higher level.
+Err MakeParseErr(const std::string& input,
+ const ParseNode* origin,
+ const Err& nested) {
+ std::string help_text =
+ "When parsing a result as a \"value\" it should look like a list:\n"
+ " [ \"a\", \"b\", 5 ]\n"
+ "or a single literal:\n"
+ " \"my result\"\n"
+ "but instead I got this, which I find very confusing:\n";
+ help_text.append(input);
+ if (nested.has_error())
+ help_text.append("\nThe exact error was:");
+
+ Err result(origin, "Script result wasn't a valid value.", help_text);
+ if (nested.has_error()) {
+ result.AppendSubErr(Err(LocationRange(), nested.message(),
+ nested.help_text()));
+ }
+ return result;
+}
+
+// Sets the origin of the value and any nested values with the given node.
+void RecursivelySetOrigin(Value* value, const ParseNode* origin) {
+ value->set_origin(origin);
+ if (value->type() == Value::LIST) {
+ std::vector<Value>& list_value = value->list_value();
+ for (size_t i = 0; i < list_value.size(); i++)
+ RecursivelySetOrigin(&list_value[i], origin);
+ }
+}
+
+Value ParseString(const std::string& input,
+ const ParseNode* origin,
+ Err* err) {
+ SourceFile empty_source_for_most_vexing_parse;
+ InputFile input_file(empty_source_for_most_vexing_parse);
+ input_file.SetContents(input);
+
+ std::vector<Token> tokens = Tokenizer::Tokenize(&input_file, err);
+ if (err->has_error()) {
+ *err = MakeParseErr(input, origin, *err);
+ return Value();
+ }
+
+ scoped_ptr<ParseNode> expression = Parser::ParseExpression(tokens, err);
+ if (err->has_error()) {
+ *err = MakeParseErr(input, origin, *err);
+ return Value();
+ }
+
+ // It's valid for the result to be a null pointer, this just means that the
+ // script returned nothing.
+ if (!expression)
+ return Value();
+
+ // The result should either be a list or a literal, anything else is
+ // invalid.
+ if (!expression->AsList() && !expression->AsLiteral()) {
+ *err = MakeParseErr(input, origin, Err());
+ return Value();
+ }
+
+ BuildSettings build_settings;
+ Label empty_label;
+ Toolchain toolchain(empty_label);
+ Settings settings(&build_settings, &toolchain, std::string());
+ Scope scope(&settings);
+
+ Err nested_err;
+ Value result = expression->Execute(&scope, &nested_err);
+ if (nested_err.has_error()) {
+ *err = MakeParseErr(input, origin, nested_err);
+ return Value();
+ }
+
+ // The returned value will have references to the temporary parse nodes we
+ // made on the stack. If the values are used in an error message in the
+ // future, this will crash. Reset the origin of all values to be our
+ // containing origin.
+ RecursivelySetOrigin(&result, origin);
+ return result;
+}
+
+Value ParseList(const std::string& input,
+ const ParseNode* origin,
+ Err* err) {
+ Value ret(origin, Value::LIST);
+ std::vector<std::string> as_lines;
+ base::SplitString(input, '\n', &as_lines);
+
+ // Trim empty lines from the end.
+ // Do we want to make this configurable?
+ while (!as_lines.empty() && as_lines[as_lines.size() - 1].empty())
+ as_lines.resize(as_lines.size() - 1);
+
+ ret.list_value().reserve(as_lines.size());
+ for (size_t i = 0; i < as_lines.size(); i++)
+ ret.list_value().push_back(Value(origin, as_lines[i]));
+ return ret;
+}
+
+} // namespace
+
+extern const char kInputConversion_Help[] =
+ "input_conversion: Specifies how to transform input to a variable.\n"
+ "\n"
+ " input_conversion is an argument to read_file and exec_script that\n"
+ " specifies how the result of the read operation should be converted\n"
+ " into a variable.\n"
+ "\n"
+ " \"list lines\"\n"
+ " Return the file contents as a list, with a string for each line.\n"
+ " The newlines will not be present in the result. Empty newlines\n"
+ " will be trimmed from the trailing end of the returned list.\n"
+ "\n"
+ " \"value\"\n"
+ " Parse the input as if it was a literal rvalue in a buildfile.\n"
+ " Examples of typical program output using this mode:\n"
+ " [ \"foo\", \"bar\" ] (result will be a list)\n"
+ " or\n"
+ " \"foo bar\" (result will be a string)\n"
+ " or\n"
+ " 5 (result will be an integer)\n"
+ "\n"
+ " Note that if the input is empty, the result will be a null value\n"
+ " which will produce an error if assigned to a variable.\n"
+ "\n"
+ " \"string\"\n"
+ " Return the file contents into a single string.\n";
+
+Value ConvertInputToValue(const std::string& input,
+ const ParseNode* origin,
+ const Value& input_conversion_value,
+ Err* err) {
+ if (!input_conversion_value.VerifyTypeIs(Value::STRING, err))
+ return Value();
+ const std::string& input_conversion = input_conversion_value.string_value();
+
+ if (input_conversion == "value")
+ return ParseString(input, origin, err);
+ if (input_conversion == "string")
+ return Value(origin, input);
+ if (input_conversion == "list lines")
+ return ParseList(input, origin, err);
+
+ *err = Err(input_conversion_value, "Not a valid read file mode.",
+ "Have you considered a career in retail?");
+ return Value();
+}
diff --git a/chromium/tools/gn/input_conversion.h b/chromium/tools/gn/input_conversion.h
new file mode 100644
index 00000000000..129609b9181
--- /dev/null
+++ b/chromium/tools/gn/input_conversion.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_INPUT_CONVERSION_H_
+#define TOOLS_GN_INPUT_CONVERSION_H_
+
+#include <string>
+
+class Err;
+class ParseNode;
+class Value;
+
+extern const char kInputConversion_Help[];
+
+// Converts the given input string (is read from a file or output from a
+// script) to a Value. Conversions as specified in the input_conversion string
+// will be performed. The given origin will be used for constructing the
+// resulting Value.
+//
+// If the conversion string is invalid, the error will be set and an empty
+// value will be returned.
+Value ConvertInputToValue(const std::string& input,
+ const ParseNode* origin,
+ const Value& input_conversion_value,
+ Err* err);
+
+#endif // TOOLS_GN_INPUT_CONVERSION_H_
diff --git a/chromium/tools/gn/input_conversion_unittest.cc b/chromium/tools/gn/input_conversion_unittest.cc
new file mode 100644
index 00000000000..59c012344c9
--- /dev/null
+++ b/chromium/tools/gn/input_conversion_unittest.cc
@@ -0,0 +1,81 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/err.h"
+#include "tools/gn/input_conversion.h"
+#include "tools/gn/value.h"
+
+TEST(InputConversion, String) {
+ Err err;
+ std::string input("\nfoo bar \n");
+ Value result = ConvertInputToValue(input, NULL, Value(NULL, "string"), &err);
+ EXPECT_FALSE(err.has_error());
+ EXPECT_EQ(Value::STRING, result.type());
+ EXPECT_EQ(input, result.string_value());
+}
+
+TEST(InputConversion, ListLines) {
+ Err err;
+ std::string input("\nfoo\nbar \n");
+ Value result = ConvertInputToValue(input, NULL, Value(NULL, "list lines"),
+ &err);
+ EXPECT_FALSE(err.has_error());
+ EXPECT_EQ(Value::LIST, result.type());
+ ASSERT_EQ(3u, result.list_value().size());
+ EXPECT_EQ("", result.list_value()[0].string_value());
+ EXPECT_EQ("foo", result.list_value()[1].string_value());
+ EXPECT_EQ("bar", result.list_value()[2].string_value());
+}
+
+TEST(InputConversion, ValueString) {
+ Err err;
+ std::string input("\"str\"");
+ Value result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err);
+ EXPECT_FALSE(err.has_error());
+ EXPECT_EQ(Value::STRING, result.type());
+ EXPECT_EQ("str", result.string_value());
+}
+
+TEST(InputConversion, ValueInt) {
+ Err err;
+ std::string input("\n\n 6 \n ");
+ Value result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err);
+ EXPECT_FALSE(err.has_error());
+ EXPECT_EQ(Value::INTEGER, result.type());
+ EXPECT_EQ(6, result.int_value());
+}
+
+TEST(InputConversion, ValueList) {
+ Err err;
+ std::string input("\n [ \"a\", 5]");
+ Value result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err);
+ EXPECT_FALSE(err.has_error());
+ ASSERT_EQ(Value::LIST, result.type());
+ ASSERT_EQ(2u, result.list_value().size());
+ EXPECT_EQ("a", result.list_value()[0].string_value());
+ EXPECT_EQ(5, result.list_value()[1].int_value());
+}
+
+TEST(InputConversion, ValueEmpty) {
+ Err err;
+ ConvertInputToValue("", NULL, Value(NULL, "value"), &err);
+}
+
+TEST(InputConversion, ValueError) {
+ Err err;
+ std::string input("\n [ \"a\", 5\nfoo bar");
+ Value result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err);
+ EXPECT_TRUE(err.has_error());
+
+ // Blocks not allowed.
+ input = "{ foo = 5 }";
+ result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err);
+ EXPECT_TRUE(err.has_error());
+
+ // Function calls not allowed.
+ input = "print(5)";
+ result = ConvertInputToValue(input, NULL, Value(NULL, "value"), &err);
+ EXPECT_TRUE(err.has_error());
+}
diff --git a/chromium/tools/gn/input_file.cc b/chromium/tools/gn/input_file.cc
new file mode 100644
index 00000000000..231dfbc855c
--- /dev/null
+++ b/chromium/tools/gn/input_file.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/input_file.h"
+
+#include "base/file_util.h"
+
+InputFile::InputFile(const SourceFile& name)
+ : name_(name),
+ dir_(name_.GetDir()),
+ contents_loaded_(false) {
+}
+
+InputFile::~InputFile() {
+}
+
+void InputFile::SetContents(const std::string& c) {
+ contents_loaded_ = true;
+ contents_ = c;
+}
+
+bool InputFile::Load(const base::FilePath& system_path) {
+ if (file_util::ReadFileToString(system_path, &contents_)) {
+ contents_loaded_ = true;
+ physical_name_ = system_path;
+ return true;
+ }
+ return false;
+}
+
diff --git a/chromium/tools/gn/input_file.h b/chromium/tools/gn/input_file.h
new file mode 100644
index 00000000000..edf39ff856d
--- /dev/null
+++ b/chromium/tools/gn/input_file.h
@@ -0,0 +1,58 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_INPUT_FILE_H_
+#define TOOLS_GN_INPUT_FILE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "tools/gn/source_dir.h"
+#include "tools/gn/source_file.h"
+
+class InputFile {
+ public:
+ InputFile(const SourceFile& name);
+
+ ~InputFile();
+
+ // The virtual name passed into the constructor. This does not take into
+ // account whether the file was loaded from the secondary source tree (see
+ // BuildSettings secondary_source_path).
+ const SourceFile& name() const { return name_; }
+
+ // The directory is just a cached version of name()->GetDir() but we get this
+ // a lot so computing it once up front saves a bunch of work.
+ const SourceDir& dir() const { return dir_; }
+
+ // The physical name tells the actual name on disk, if there is one.
+ const base::FilePath& physical_name() const { return physical_name_; }
+
+ const std::string& contents() const {
+ DCHECK(contents_loaded_);
+ return contents_;
+ }
+
+ // For testing and in cases where this input doesn't actually refer to
+ // "a file".
+ void SetContents(const std::string& c);
+
+ // Loads the given file synchronously, returning true on success. This
+ bool Load(const base::FilePath& system_path);
+
+ private:
+ SourceFile name_;
+ SourceDir dir_;
+
+ base::FilePath physical_name_;
+
+ bool contents_loaded_;
+ std::string contents_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputFile);
+};
+
+#endif // TOOLS_GN_INPUT_FILE_H_
diff --git a/chromium/tools/gn/input_file_manager.cc b/chromium/tools/gn/input_file_manager.cc
new file mode 100644
index 00000000000..33ab16abe38
--- /dev/null
+++ b/chromium/tools/gn/input_file_manager.cc
@@ -0,0 +1,252 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/input_file_manager.h"
+
+#include "base/bind.h"
+#include "base/stl_util.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/parser.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/scope_per_file_provider.h"
+#include "tools/gn/tokenizer.h"
+
+namespace {
+
+void InvokeFileLoadCallback(const InputFileManager::FileLoadCallback& cb,
+ const ParseNode* node) {
+ cb.Run(node);
+}
+
+} // namespace
+
+InputFileManager::InputFileData::InputFileData(const SourceFile& file_name)
+ : file(file_name),
+ loaded(false),
+ sync_invocation(false) {
+}
+
+InputFileManager::InputFileData::~InputFileData() {
+}
+
+InputFileManager::InputFileManager() {
+}
+
+InputFileManager::~InputFileManager() {
+ // Should be single-threaded by now.
+ STLDeleteContainerPairSecondPointers(input_files_.begin(),
+ input_files_.end());
+}
+
+bool InputFileManager::AsyncLoadFile(const LocationRange& origin,
+ const BuildSettings* build_settings,
+ const SourceFile& file_name,
+ const FileLoadCallback& callback,
+ Err* err) {
+ // Try not to schedule callbacks while holding the lock. All cases that don't
+ // want to schedule should return early. Otherwise, this will be scheduled
+ // after we leave the lock.
+ base::Closure schedule_this;
+ {
+ base::AutoLock lock(lock_);
+
+ InputFileMap::const_iterator found = input_files_.find(file_name);
+ if (found == input_files_.end()) {
+ // New file, schedule load.
+ InputFileData* data = new InputFileData(file_name);
+ data->scheduled_callbacks.push_back(callback);
+ input_files_[file_name] = data;
+
+ schedule_this = base::Bind(&InputFileManager::BackgroundLoadFile,
+ this,
+ origin,
+ build_settings,
+ file_name,
+ &data->file);
+ } else {
+ InputFileData* data = found->second;
+
+ // Prevent mixing async and sync loads. See SyncLoadFile for discussion.
+ if (data->sync_invocation) {
+ g_scheduler->FailWithError(Err(
+ origin, "Load type mismatch.",
+ "The file \"" + file_name.value() + "\" was previously loaded\n"
+ "synchronously (via an import) and now you're trying to load it "
+ "asynchronously\n(via a deps rule). This is a class 2 misdemeanor: "
+ "a single input file must\nbe loaded the same way each time to "
+ "avoid blowing my tiny, tiny mind."));
+ return false;
+ }
+
+ if (data->loaded) {
+ // Can just directly issue the callback on the background thread.
+ schedule_this = base::Bind(&InvokeFileLoadCallback, callback,
+ data->parsed_root.get());
+ } else {
+ // Load is pending on this file, schedule the invoke.
+ data->scheduled_callbacks.push_back(callback);
+ return true;
+ }
+ }
+ }
+ g_scheduler->pool()->PostWorkerTaskWithShutdownBehavior(
+ FROM_HERE, schedule_this,
+ base::SequencedWorkerPool::BLOCK_SHUTDOWN);
+ return true;
+}
+
+const ParseNode* InputFileManager::SyncLoadFile(
+ const LocationRange& origin,
+ const BuildSettings* build_settings,
+ const SourceFile& file_name,
+ Err* err) {
+ base::AutoLock lock(lock_);
+
+ InputFileData* data = NULL;
+ InputFileMap::iterator found = input_files_.find(file_name);
+ if (found == input_files_.end()) {
+ base::AutoUnlock unlock(lock_);
+
+ // Haven't seen this file yet, start loading right now.
+ data = new InputFileData(file_name);
+ data->sync_invocation = true;
+ input_files_[file_name] = data;
+
+ if (!LoadFile(origin, build_settings, file_name, &data->file, err))
+ return NULL;
+ } else {
+ // This file has either been loaded or is pending loading.
+ data = found->second;
+
+ if (!data->sync_invocation) {
+ // Don't allow mixing of sync and async loads. If an async load is
+ // scheduled and then a bunch of threads need to load it synchronously
+ // and block on it loading, it could deadlock or at least cause a lot
+ // of wasted CPU while those threads wait for the load to complete (which
+ // may be far back in the input queue).
+ //
+ // We could work around this by promoting the load to a sync load. This
+ // requires a bunch of extra code to either check flags and likely do
+ // extra locking (bad) or to just do both types of load on the file and
+ // deal with the race condition.
+ //
+ // I have no practical way to test this, and generally we should have
+ // all include files processed synchronously and all build files
+ // processed asynchronously, so it doesn't happen in practice.
+ *err = Err(
+ origin, "Load type mismatch.",
+ "The file \"" + file_name.value() + "\" was previously loaded\n"
+ "asynchronously (via a deps rule) and now you're trying to load it "
+ "synchronously.\nThis is a class 2 misdemeanor: a single input file "
+ "must be loaded the same way\neach time to avoid blowing my tiny, "
+ "tiny mind.");
+ return NULL;
+ }
+
+ if (!data->loaded) {
+ // Wait for the already-pending sync load to complete.
+ if (!data->completion_event)
+ data->completion_event.reset(new base::WaitableEvent(false, false));
+ {
+ base::AutoUnlock unlock(lock_);
+ data->completion_event->Wait();
+ }
+ }
+ }
+
+ // The other load could have failed. In this case that error will be printed
+ // to the console, but we need to return something here, so make up a
+ // dummy error.
+ if (!data->parsed_root)
+ *err = Err(origin, "File parse failed");
+ return data->parsed_root.get();
+}
+
+int InputFileManager::GetInputFileCount() const {
+ base::AutoLock lock(lock_);
+ return input_files_.size();
+}
+
+void InputFileManager::GetAllPhysicalInputFileNames(
+ std::vector<base::FilePath>* result) const {
+ base::AutoLock lock(lock_);
+ result->reserve(input_files_.size());
+ for (InputFileMap::const_iterator i = input_files_.begin();
+ i != input_files_.end(); ++i) {
+ if (!i->second->file.physical_name().empty())
+ result->push_back(i->second->file.physical_name());
+ }
+}
+
+void InputFileManager::BackgroundLoadFile(const LocationRange& origin,
+ const BuildSettings* build_settings,
+ const SourceFile& name,
+ InputFile* file) {
+ Err err;
+ if (!LoadFile(origin, build_settings, name, file, &err))
+ g_scheduler->FailWithError(err);
+}
+
+bool InputFileManager::LoadFile(const LocationRange& origin,
+ const BuildSettings* build_settings,
+ const SourceFile& name,
+ InputFile* file,
+ Err* err) {
+ // Do all of this stuff outside the lock. We should not give out file
+ // pointers until the read is complete.
+ if (g_scheduler->verbose_logging())
+ g_scheduler->Log("Loading", name.value());
+
+ // Read.
+ base::FilePath primary_path = build_settings->GetFullPath(name);
+ if (!file->Load(primary_path)) {
+ if (!build_settings->secondary_source_path().empty()) {
+ // Fall back to secondary source tree.
+ base::FilePath secondary_path =
+ build_settings->GetFullPathSecondary(name);
+ if (!file->Load(secondary_path)) {
+ *err = Err(origin, "Can't load input file.",
+ "Unable to load either \n" +
+ FilePathToUTF8(primary_path) + " or \n" +
+ FilePathToUTF8(secondary_path));
+ return false;
+ }
+ } else {
+ *err = Err(origin,
+ "Unable to load \"" + FilePathToUTF8(primary_path) + "\".");
+ return false;
+ }
+ }
+
+ // Tokenize.
+ std::vector<Token> tokens = Tokenizer::Tokenize(file, err);
+ if (err->has_error())
+ return false;
+
+ // Parse.
+ scoped_ptr<ParseNode> root = Parser::Parse(tokens, err);
+ if (err->has_error())
+ return false;
+ ParseNode* unowned_root = root.get();
+
+ std::vector<FileLoadCallback> callbacks;
+ {
+ base::AutoLock lock(lock_);
+ DCHECK(input_files_.find(name) != input_files_.end());
+
+ InputFileData* data = input_files_[name];
+ data->loaded = true;
+ data->tokens.swap(tokens);
+ data->parsed_root = root.Pass();
+
+ callbacks.swap(data->scheduled_callbacks);
+ }
+
+ // Run pending invocations. Theoretically we could schedule each of these
+ // separately to get some parallelism. But normally there will only be one
+ // item in the list, so that's extra overhead and complexity for no gain.
+ for (size_t i = 0; i < callbacks.size(); i++)
+ callbacks[i].Run(unowned_root);
+ return true;
+}
diff --git a/chromium/tools/gn/input_file_manager.h b/chromium/tools/gn/input_file_manager.h
new file mode 100644
index 00000000000..ae6533a6bf7
--- /dev/null
+++ b/chromium/tools/gn/input_file_manager.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_INPUT_FILE_MANAGER_H_
+#define TOOLS_GN_INPUT_FILE_MANAGER_H_
+
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/containers/hash_tables.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/settings.h"
+
+class Err;
+class LocationRange;
+class ParseNode;
+class Token;
+
+// Manages loading and parsing files from disk. This doesn't actually have
+// any context for executing the results, so potentially multiple configs
+// could use the same input file (saving parsing).
+//
+// This class is threadsafe.
+//
+// InputFile objects must never be deleted while the program is running since
+// various state points into them.
+class InputFileManager : public base::RefCountedThreadSafe<InputFileManager> {
+ public:
+ // Callback issued when a file is laoded. On auccess, the parse node will
+ // refer to the root block of the file. On failure, this will be NULL.
+ typedef base::Callback<void(const ParseNode*)> FileLoadCallback;
+
+ InputFileManager();
+
+ // Loads the given file and executes the callback on the worker pool.
+ //
+ // There are two types of errors. For errors known synchronously, the error
+ // will be set, it will return false, and no work will be scheduled.
+ //
+ // For parse errors and such that happen in the future, the error will be
+ // logged to the scheduler and the callback will be invoked with a null
+ // ParseNode pointer. The given |origin| will be blamed for the invocation.
+ bool AsyncLoadFile(const LocationRange& origin,
+ const BuildSettings* build_settings,
+ const SourceFile& file_name,
+ const FileLoadCallback& callback,
+ Err* err);
+
+ // Loads and parses the given file synchronously, returning the root block
+ // corresponding to the parsed result. On error, return NULL and the given
+ // Err is set.
+ const ParseNode* SyncLoadFile(const LocationRange& origin,
+ const BuildSettings* build_settings,
+ const SourceFile& file_name,
+ Err* err);
+
+ int GetInputFileCount() const;
+
+ // Fills the vector with all input files.
+ void GetAllPhysicalInputFileNames(std::vector<base::FilePath>* result) const;
+
+ private:
+ friend class base::RefCountedThreadSafe<InputFileManager>;
+
+ struct InputFileData {
+ InputFileData(const SourceFile& file_name);
+ ~InputFileData();
+
+ // Don't touch this outside the lock until it's marked loaded.
+ InputFile file;
+
+ bool loaded;
+
+ bool sync_invocation;
+
+ // Lists all invocations that need to be executed when the file completes
+ // loading.
+ std::vector<FileLoadCallback> scheduled_callbacks;
+
+ // Event to signal when the load is complete (or fails). This is lazily
+ // created only when a thread is synchronously waiting for this load (which
+ // only happens for imports).
+ scoped_ptr<base::WaitableEvent> completion_event;
+
+ std::vector<Token> tokens;
+
+ // Null before the file is loaded or if loading failed.
+ scoped_ptr<ParseNode> parsed_root;
+ };
+
+ virtual ~InputFileManager();
+
+ void BackgroundLoadFile(const LocationRange& origin,
+ const BuildSettings* build_settings,
+ const SourceFile& name,
+ InputFile* file);
+
+ // Loads the given file. On error, sets the Err and return false.
+ bool LoadFile(const LocationRange& origin,
+ const BuildSettings* build_settings,
+ const SourceFile& name,
+ InputFile* file,
+ Err* err);
+
+ mutable base::Lock lock_;
+
+ // Maps repo-relative filenames to the corresponding owned pointer.
+ typedef base::hash_map<SourceFile, InputFileData*> InputFileMap;
+ InputFileMap input_files_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputFileManager);
+};
+
+#endif // TOOLS_GN_INPUT_FILE_MANAGER_H_
diff --git a/chromium/tools/gn/item.cc b/chromium/tools/gn/item.cc
new file mode 100644
index 00000000000..747183cbd08
--- /dev/null
+++ b/chromium/tools/gn/item.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/item.h"
+
+#include "base/logging.h"
+
+Item::Item(const Label& label) : label_(label) {
+}
+
+Item::~Item() {
+}
+
+Config* Item::AsConfig() { return NULL; }
+const Config* Item::AsConfig() const { return NULL; }
+Target* Item::AsTarget() { return NULL; }
+const Target* Item::AsTarget() const { return NULL; }
+Toolchain* Item::AsToolchain() { return NULL; }
+const Toolchain* Item::AsToolchain() const { return NULL; }
+
+std::string Item::GetItemTypeName() const {
+ if (AsConfig())
+ return "config";
+ if (AsTarget())
+ return "target";
+ if (AsToolchain())
+ return "toolchain";
+ NOTREACHED();
+ return "this thing that I have no idea what it is";
+}
diff --git a/chromium/tools/gn/item.h b/chromium/tools/gn/item.h
new file mode 100644
index 00000000000..aa715442e35
--- /dev/null
+++ b/chromium/tools/gn/item.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_ITEM_H_
+#define TOOLS_GN_ITEM_H_
+
+#include <string>
+
+#include "tools/gn/label.h"
+
+class Config;
+class Target;
+class Toolchain;
+
+// A named item (target, config, etc.) that participates in the dependency
+// graph.
+class Item {
+ public:
+ Item(const Label& label);
+ virtual ~Item();
+
+ const Label& label() const { return label_; }
+
+ // Manual RTTI.
+ virtual Config* AsConfig();
+ virtual const Config* AsConfig() const;
+ virtual Target* AsTarget();
+ virtual const Target* AsTarget() const;
+ virtual Toolchain* AsToolchain();
+ virtual const Toolchain* AsToolchain() const;
+
+ // Returns a name like "target" or "config" for the type of item this is, to
+ // be used in logging and error messages.
+ std::string GetItemTypeName() const;
+
+ // Called when this item is resolved, meaning it and all of its dependents
+ // have no unresolved deps.
+ virtual void OnResolved() {}
+
+ private:
+ Label label_;
+};
+
+#endif // TOOLS_GN_ITEM_H_
diff --git a/chromium/tools/gn/item_node.cc b/chromium/tools/gn/item_node.cc
new file mode 100644
index 00000000000..f10bada584d
--- /dev/null
+++ b/chromium/tools/gn/item_node.cc
@@ -0,0 +1,119 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/item_node.h"
+
+#include <algorithm>
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/item.h"
+
+ItemNode::ItemNode(Item* i)
+ : state_(REFERENCED),
+ item_(i),
+ should_generate_(false) {
+}
+
+ItemNode::~ItemNode() {
+}
+
+bool ItemNode::SetShouldGenerate(const BuildSettings* build_settings,
+ Err* err) {
+ if (should_generate_)
+ return true;
+ should_generate_ = true;
+
+ if (state_ == DEFINED) {
+ if (!ScheduleDepsLoad(build_settings, err))
+ return false;
+ } else if (state_ == RESOLVED) {
+ // The item may have been resolved even if we didn't set the generate bit
+ // if all of its deps were loaded some other way. In this case, we need
+ // to run the closure which we skipped when it became resolved.
+ if (!resolved_closure_.is_null())
+ resolved_closure_.Run();
+ }
+
+ // Pass the generate bit to all deps.
+ for (ItemNodeMap::iterator i = direct_dependencies_.begin();
+ i != direct_dependencies_.end(); ++i) {
+ if (!i->first->SetShouldGenerate(build_settings, err))
+ return false;
+ }
+ return true;
+}
+
+bool ItemNode::AddDependency(const BuildSettings* build_settings,
+ const LocationRange& specified_from_here,
+ ItemNode* node,
+ Err* err) {
+ // Can't add more deps once it's been defined.
+ DCHECK(state_ == REFERENCED);
+
+ if (direct_dependencies_.find(node) != direct_dependencies_.end())
+ return true; // Already have this dep.
+
+ direct_dependencies_[node] = specified_from_here;
+
+ if (node->state() != RESOLVED) {
+ // Wire up the pending resolution info.
+ unresolved_dependencies_[node] = specified_from_here;
+ node->waiting_on_resolution_[this] = specified_from_here;
+ }
+
+ if (should_generate_) {
+ if (!node->SetShouldGenerate(build_settings, err))
+ return false;
+ }
+ return true;
+}
+
+void ItemNode::MarkDirectDependencyResolved(ItemNode* node) {
+ DCHECK(unresolved_dependencies_.find(node) != unresolved_dependencies_.end());
+ unresolved_dependencies_.erase(node);
+}
+
+void ItemNode::SwapOutWaitingDependencySet(ItemNodeMap* out_map) {
+ waiting_on_resolution_.swap(*out_map);
+ DCHECK(waiting_on_resolution_.empty());
+}
+
+bool ItemNode::SetDefined(const BuildSettings* build_settings, Err* err) {
+ DCHECK(state_ == REFERENCED);
+ state_ = DEFINED;
+
+ if (should_generate_)
+ return ScheduleDepsLoad(build_settings, err);
+ return true;
+}
+
+void ItemNode::SetResolved() {
+ DCHECK(state_ != RESOLVED);
+ state_ = RESOLVED;
+
+ if (should_generate_ && !resolved_closure_.is_null())
+ resolved_closure_.Run();
+}
+
+bool ItemNode::ScheduleDepsLoad(const BuildSettings* build_settings,
+ Err* err) {
+ DCHECK(state_ == DEFINED);
+ DCHECK(should_generate_); // Shouldn't be requesting deps for ungenerated
+ // items.
+
+ for (ItemNodeMap::const_iterator i = unresolved_dependencies_.begin();
+ i != unresolved_dependencies_.end(); ++i) {
+ Label toolchain_label = i->first->item()->label().GetToolchainLabel();
+ SourceDir dir_to_load = i->first->item()->label().dir();
+
+ if (!build_settings->toolchain_manager().ScheduleInvocationLocked(
+ i->second, toolchain_label, dir_to_load, err))
+ return false;
+ }
+
+ state_ = PENDING_DEPS;
+ return true;
+}
diff --git a/chromium/tools/gn/item_node.h b/chromium/tools/gn/item_node.h
new file mode 100644
index 00000000000..dbee141b737
--- /dev/null
+++ b/chromium/tools/gn/item_node.h
@@ -0,0 +1,159 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_ITEM_NODE_H_
+#define TOOLS_GN_ITEM_NODE_H_
+
+#include <map>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "tools/gn/location.h"
+
+class BuildSettings;
+class Err;
+class Item;
+
+// Represents a node in the depdency tree. It references an Item which is
+// the actual thing.
+//
+// The items and nodes are split apart so that the ItemTree can manipulate
+// the dependencies one one thread while the Item itself is been modified on
+// another.
+class ItemNode {
+ public:
+ // The state of this node. As more of the load progresses, we'll move
+ // downward in this list toward the resolved state.
+ enum State {
+ // Another item has referenced this one by name, but we have not yet
+ // encountered its definition.
+ REFERENCED = 0,
+
+ // We've seen the definition of this item but have not requested that its
+ // dependencies be loaded. In non-greedy generation mode (see item_tree.h)
+ // some nodes will stay in this state forever as long as they're not needed
+ // for anything that is required.
+ DEFINED,
+
+ // The item has been defined and we've requested that all of the
+ // dependencies be loaded. Not all of the dependencies have been resolved,
+ // however, and we're still waiting on some build files to be run (or
+ // perhaps there are undefined dependencies).
+ PENDING_DEPS,
+
+ // All of this item's transitive dependencies have been found and
+ // resolved.
+ RESOLVED,
+ };
+
+ // Stores a set of ItemNodes and the associated range that the dependency
+ // was added from.
+ typedef std::map<ItemNode*, LocationRange> ItemNodeMap;
+
+ // Takes ownership of the pointer.
+ // Initial state will be REFERENCED.
+ ItemNode(Item* i);
+ ~ItemNode();
+
+ State state() const { return state_; }
+
+ // This closure will be executed when the item is resolved and it has the
+ // should_generate flag set.
+ void set_resolved_closure(const base::Closure& closure) {
+ resolved_closure_ = closure;
+ }
+
+ const Item* item() const { return item_.get(); }
+ Item* item() { return item_.get(); }
+
+ // True if this item should be generated. In greedy mode, this will alwyas
+ // be set. Otherwise, this bit will be "pushed" through the tree to
+ // generate the minimum set of targets required for some special base target.
+ // Initialized to false.
+ //
+ // If this item has been defined, setting this flag will schedule the load
+ // of dependent nodes and also set their should_generate bits.
+ bool should_generate() const { return should_generate_; }
+ bool SetShouldGenerate(const BuildSettings* build_settings, Err* err);
+
+ // Where this was created from, which might be when it was generated or
+ // when it was first referenced from another target.
+ const LocationRange& originally_referenced_from_here() const {
+ return originally_referenced_from_here_;
+ }
+ void set_originally_referenced_from_here(const LocationRange& r) {
+ originally_referenced_from_here_ = r;
+ }
+
+ // Where this was generated from. This will be empty for items that have
+ // been referenced but not generated. Note that this has to be one the
+ // ItemNode because it can be changing from multiple threads and we need
+ // to be sure that access is serialized.
+ const LocationRange& generated_from_here() const {
+ return generated_from_here_;
+ }
+ void set_generated_from_here(const LocationRange& r) {
+ generated_from_here_ = r;
+ }
+
+ const ItemNodeMap& direct_dependencies() const {
+ return direct_dependencies_;
+ }
+ const ItemNodeMap& unresolved_dependencies() const {
+ return unresolved_dependencies_;
+ }
+
+ bool AddDependency(const BuildSettings* build_settings,
+ const LocationRange& specified_from_here,
+ ItemNode* node,
+ Err* err);
+
+ // Removes the given dependency from the unresolved list. Does not do
+ // anything else to update waiters.
+ void MarkDirectDependencyResolved(ItemNode* node);
+
+ // Destructively retrieve the set of waiting nodes.
+ void SwapOutWaitingDependencySet(ItemNodeMap* out_map);
+
+ // Marks this item state as defined (see above). If the should generate
+ // flag is set, this will schedule a load of the dependencies and
+ // automatically transition to the PENDING_DEPS state.
+ bool SetDefined(const BuildSettings* build_settings, Err* err);
+
+ // Marks this item state as resolved (see above).
+ void SetResolved();
+
+ private:
+ // Schedules loading the dependencies of this node. The current state must
+ // be DEFINED, and this call will transition the state to PENDING_DEPS.
+ //
+ // Requesting deps can fail. On failure returns false and sets the err.
+ bool ScheduleDepsLoad(const BuildSettings* build_settings, Err* err);
+
+ State state_;
+ scoped_ptr<Item> item_;
+ bool should_generate_; // See getter above.
+
+ LocationRange originally_referenced_from_here_;
+ LocationRange generated_from_here_;
+
+ // What to run when this item is resolved.
+ base::Closure resolved_closure_;
+
+ // Everything this item directly depends on.
+ ItemNodeMap direct_dependencies_;
+
+ // Unresolved things this item directly depends on.
+ ItemNodeMap unresolved_dependencies_;
+
+ // These items are waiting on us to be resolved before they can be
+ // resolved. This is the backpointer for unresolved_dependencies_.
+ ItemNodeMap waiting_on_resolution_;
+
+ DISALLOW_COPY_AND_ASSIGN(ItemNode);
+};
+
+#endif // TOOLS_GN_ITEM_NODE_H_
diff --git a/chromium/tools/gn/item_tree.cc b/chromium/tools/gn/item_tree.cc
new file mode 100644
index 00000000000..054403dfee4
--- /dev/null
+++ b/chromium/tools/gn/item_tree.cc
@@ -0,0 +1,200 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/item_tree.h"
+
+#include <algorithm>
+
+#include "base/stl_util.h"
+#include "tools/gn/err.h"
+#include "tools/gn/item.h"
+#include "tools/gn/item_node.h"
+
+namespace {
+
+// Recursively looks in the tree for a given node, returning true if it
+// was found in the dependecy graph. This is used to see if a given node
+// participates in a cycle.
+//
+// Note that "look_for" and "search_in" will be the same node when starting the
+// search, so we don't want to return true in that case.
+//
+// If a cycle is found, the return value will be true and the cycle vector will
+// be filled with the path (in reverse order).
+bool RecursiveFindCycle(const ItemNode* look_for,
+ const ItemNode* search_in,
+ std::vector<const ItemNode*>* cycle) {
+ const ItemNode::ItemNodeMap& unresolved =
+ search_in->unresolved_dependencies();
+ for (ItemNode::ItemNodeMap::const_iterator i = unresolved.begin();
+ i != unresolved.end(); ++i) {
+ ItemNode* cur = i->first;
+ if (cur == look_for) {
+ cycle->push_back(cur);
+ return true;
+ }
+
+ if (RecursiveFindCycle(look_for, cur, cycle)) {
+ // Found a cycle inside this one, record our path and return.
+ cycle->push_back(cur);
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+ItemTree::ItemTree() {
+}
+
+ItemTree::~ItemTree() {
+ STLDeleteContainerPairSecondPointers(items_.begin(), items_.end());
+}
+
+ItemNode* ItemTree::GetExistingNodeLocked(const Label& label) {
+ lock_.AssertAcquired();
+ StringToNodeHash::iterator found = items_.find(label);
+ if (found == items_.end())
+ return NULL;
+ return found->second;
+}
+
+void ItemTree::AddNodeLocked(ItemNode* node) {
+ lock_.AssertAcquired();
+ DCHECK(items_.find(node->item()->label()) == items_.end());
+ items_[node->item()->label()] = node;
+}
+
+bool ItemTree::MarkItemDefinedLocked(const BuildSettings* build_settings,
+ const Label& label,
+ Err* err) {
+ lock_.AssertAcquired();
+ DCHECK(items_.find(label) != items_.end());
+
+ ItemNode* node = items_[label];
+
+ if (!node->unresolved_dependencies().empty()) {
+ // Still some pending dependencies, wait for those to be resolved.
+ if (!node->SetDefined(build_settings, err))
+ return false;
+ return true;
+ }
+
+ // No more pending deps.
+ MarkItemResolvedLocked(node);
+ return true;
+}
+
+void ItemTree::GetAllItemsLocked(std::vector<const Item*>* dest) const {
+ lock_.AssertAcquired();
+ dest->reserve(items_.size());
+ for (StringToNodeHash::const_iterator i = items_.begin();
+ i != items_.end(); ++i) {
+ dest->push_back(i->second->item());
+ }
+}
+
+Err ItemTree::CheckForBadItems() const {
+ base::AutoLock lock(lock_);
+
+ // Look for errors where we find a GENERATED node that refers to a REFERENCED
+ // one. There may be other nodes depending on the GENERATED one, but listing
+ // all of those isn't helpful, we want to find the broken link.
+ //
+ // This finds normal "missing dependency" errors but does not find circular
+ // dependencies because in this case all items in the cycle will be GENERATED
+ // but none will be resolved. If this happens, we'll check explicitly for
+ // that below.
+ std::vector<const ItemNode*> bad_nodes;
+ std::string depstring;
+ for (StringToNodeHash::const_iterator i = items_.begin();
+ i != items_.end(); ++i) {
+ const ItemNode* src = i->second;
+ if (!src->should_generate())
+ continue; // Skip ungenerated nodes.
+
+ if (src->state() == ItemNode::DEFINED ||
+ src->state() == ItemNode::PENDING_DEPS) {
+ bad_nodes.push_back(src);
+
+ // Check dependencies.
+ for (ItemNode::ItemNodeMap::const_iterator dest =
+ src->unresolved_dependencies().begin();
+ dest != src->unresolved_dependencies().end();
+ ++dest) {
+ const ItemNode* dest_node = dest->first;
+ if (dest_node->state() == ItemNode::REFERENCED) {
+ depstring += "\"" + src->item()->label().GetUserVisibleName(false) +
+ "\" needs " + dest_node->item()->GetItemTypeName() +
+ " \"" + dest_node->item()->label().GetUserVisibleName(false) +
+ "\"\n";
+ }
+ }
+ }
+ }
+
+ if (!bad_nodes.empty() && depstring.empty()) {
+ // Our logic above found a bad node but didn't identify the problem. This
+ // normally means a circular dependency.
+ depstring = CheckForCircularDependenciesLocked(bad_nodes);
+ if (depstring.empty()) {
+ // Something's very wrong, just dump out the bad nodes.
+ depstring = "I have no idea what went wrong, but these are unresolved, "
+ "possible due to an\ninternal error:";
+ for (size_t i = 0; i < bad_nodes.size(); i++) {
+ depstring += "\n\"" +
+ bad_nodes[i]->item()->label().GetUserVisibleName(false) + "\"";
+ }
+ }
+ }
+
+ if (depstring.empty())
+ return Err();
+ return Err(Location(), "Unresolved dependencies.", depstring);
+}
+
+void ItemTree::MarkItemResolvedLocked(ItemNode* node) {
+ node->SetResolved();
+ node->item()->OnResolved();
+
+ // Now update our waiters, pushing the "resolved" bit.
+ ItemNode::ItemNodeMap waiting;
+ node->SwapOutWaitingDependencySet(&waiting);
+ for (ItemNode::ItemNodeMap::iterator i = waiting.begin();
+ i != waiting.end(); ++i) {
+ ItemNode* waiter = i->first;
+
+ // Our node should be unresolved in the waiter.
+ DCHECK(waiter->unresolved_dependencies().find(node) !=
+ waiter->unresolved_dependencies().end());
+ waiter->MarkDirectDependencyResolved(node);
+
+ // Recursively mark nodes as resolved.
+ if ((waiter->state() == ItemNode::DEFINED ||
+ waiter->state() == ItemNode::PENDING_DEPS) &&
+ waiter->unresolved_dependencies().empty())
+ MarkItemResolvedLocked(waiter);
+ }
+}
+
+std::string ItemTree::CheckForCircularDependenciesLocked(
+ const std::vector<const ItemNode*>& bad_nodes) const {
+ std::vector<const ItemNode*> cycle;
+ if (!RecursiveFindCycle(bad_nodes[0], bad_nodes[0], &cycle))
+ return std::string(); // Didn't find a cycle, something else is wrong.
+
+ cycle.push_back(bad_nodes[0]);
+ std::string ret = "There is a dependency cycle:";
+
+ // Walk backwards since the dependency arrows point in the reverse direction.
+ for (int i = static_cast<int>(cycle.size()) - 1; i >= 0; i--) {
+ ret += "\n \"" + cycle[i]->item()->label().GetUserVisibleName(false) +
+ "\"";
+ if (i != 0)
+ ret += " ->";
+ }
+
+ return ret;
+}
diff --git a/chromium/tools/gn/item_tree.h b/chromium/tools/gn/item_tree.h
new file mode 100644
index 00000000000..4a8f9fb9762
--- /dev/null
+++ b/chromium/tools/gn/item_tree.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_ITEM_TREE_H_
+#define TOOLS_GN_ITEM_TREE_H_
+
+#include "base/containers/hash_tables.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "tools/gn/label.h"
+
+class BuildSettings;
+class Err;
+class Item;
+class ItemNode;
+
+// Represents the full dependency tree if labeled items in the system.
+// Generally you will interact with this through the target manager, etc.
+//
+// There are two modes for filling out the dependency tree:
+//
+// - In greedy mode, every target we encounter will be generated. This means
+// that we'll recursively load all of its subdependencies. So if you have
+// a build file that's loaded for any reason, all targets in that build file
+// will be generated.
+//
+// - In non-greedy mode, we'll only generate and load dependncies for targets
+// that have the should_generate bit set. This allows us to load the minimal
+// set of buildfiles required for one or more targets.
+//
+// The main build is generally run in greedy mode, since people expect to be
+// be able to write random tests and have them show up in the output. We'll
+// switch into non-greed mode when doing diagnostics (like displaying the
+// dependency tree on the command line) and for dependencies on targets in
+// other toolchains. The toolchain behavior is important, if target A depends
+// on B with an alternate toolchain, it doesn't mean we should recursively
+// generate all targets in the buildfile just to get B: we should generate the
+// and load the minimum number of files in order to resolve B.
+class ItemTree {
+ public:
+ ItemTree();
+ ~ItemTree();
+
+ // This lock must be held when calling the "Locked" functions below.
+ base::Lock& lock() const { return lock_; }
+
+ // Returns NULL if the item is not found.
+ //
+ // The lock must be held.
+ ItemNode* GetExistingNodeLocked(const Label& label);
+
+ // There must not be an item with this label in the tree already. Takes
+ // ownership of the pointer.
+ //
+ // The lock must be held.
+ void AddNodeLocked(ItemNode* node);
+
+ // Mark the given item as being defined. If it has no unresolved
+ // dependencies, it will be marked resolved, and the resolved state will be
+ // recursively pushed into the dependency tree. Returns an error if there was
+ // an error.
+ bool MarkItemDefinedLocked(const BuildSettings* build_settings,
+ const Label& label,
+ Err* err);
+
+ // Fills the given vector with all known items.
+ void GetAllItemsLocked(std::vector<const Item*>* dest) const;
+
+ // Returns an error if there are unresolved dependencies, or no error if
+ // there aren't.
+ //
+ // The lock should not be held.
+ Err CheckForBadItems() const;
+
+ private:
+ void MarkItemResolvedLocked(ItemNode* node);
+
+ // Given a set of unresolved nodes, looks for cycles and returns the error
+ // message describing any cycles it found.
+ std::string CheckForCircularDependenciesLocked(
+ const std::vector<const ItemNode*>& bad_nodes) const;
+
+ mutable base::Lock lock_;
+
+ typedef base::hash_map<Label, ItemNode*> StringToNodeHash;
+ StringToNodeHash items_; // Owning pointer.
+
+ DISALLOW_COPY_AND_ASSIGN(ItemTree);
+};
+
+#endif // TOOLS_GN_ITEM_TREE_H_
diff --git a/chromium/tools/gn/label.cc b/chromium/tools/gn/label.cc
new file mode 100644
index 00000000000..f9b48da3c77
--- /dev/null
+++ b/chromium/tools/gn/label.cc
@@ -0,0 +1,263 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/label.h"
+
+#include "base/logging.h"
+#include "tools/gn/err.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+// We print user visible label names with no trailing slash after the
+// directory name.
+std::string DirWithNoTrailingSlash(const SourceDir& dir) {
+ // Be careful not to trim if the input is just "/" or "//".
+ if (dir.value().size() > 2)
+ return dir.value().substr(0, dir.value().size() - 1);
+ return dir.value();
+}
+
+// Given the separate-out input (everything before the colon) in the dep rule,
+// computes the final build rule. Sets err on failure. On success,
+// |*used_implicit| will be set to whether the implicit current directory was
+// used. The value is used only for generating error messages.
+bool ComputeBuildLocationFromDep(const Value& input_value,
+ const SourceDir& current_dir,
+ const base::StringPiece& input,
+ SourceDir* result,
+ Err* err) {
+ // No rule, use the current locaton.
+ if (input.empty()) {
+ *result = current_dir;
+ return true;
+ }
+
+ // Don't allow directories to start with a single slash. All labels must be
+ // in the source root.
+ if (input[0] == '/' && (input.size() == 1 || input[1] != '/')) {
+ *err = Err(input_value, "Label can't start with a single slash",
+ "Labels must be either relative (no slash at the beginning) or be "
+ "absolute\ninside the source root (two slashes at the beginning).");
+ return false;
+ }
+
+ *result = current_dir.ResolveRelativeDir(input);
+ return true;
+}
+
+// Given the separated-out target name (after the colon) computes the final
+// name, using the implicit name from the previously-generated
+// computed_location if necessary. The input_value is used only for generating
+// error messages.
+bool ComputeTargetNameFromDep(const Value& input_value,
+ const SourceDir& computed_location,
+ const base::StringPiece& input,
+ std::string* result,
+ Err* err) {
+ if (!input.empty()) {
+ // Easy case: input is specified, just use it.
+ result->assign(input.data(), input.size());
+ return true;
+ }
+
+ const std::string& loc = computed_location.value();
+
+ // Use implicit name. The path will be "//", "//base/", "//base/i18n/", etc.
+ if (loc.size() <= 1) {
+ *err = Err(input_value, "This dependency name is empty");
+ return false;
+ }
+
+ size_t next_to_last_slash = loc.rfind('/', loc.size() - 2);
+ DCHECK(next_to_last_slash != std::string::npos);
+ result->assign(&loc[next_to_last_slash + 1],
+ loc.size() - next_to_last_slash - 2);
+ return true;
+}
+
+// The original value is used only for error reporting, use the |input| as the
+// input to this function (which may be a substring of the original value when
+// we're parsing toolchains.
+//
+// If the output toolchain vars are NULL, then we'll report an error if we
+// find a toolchain specified (this is used when recursively parsing toolchain
+// labels which themselves can't have toolchain specs).
+//
+// We assume that the output variables are initialized to empty so we don't
+// write them unless we need them to contain something.
+//
+// Returns true on success. On failure, the out* variables might be written to
+// but shouldn't be used.
+bool Resolve(const SourceDir& current_dir,
+ const Label& current_toolchain,
+ const Value& original_value,
+ const base::StringPiece& input,
+ SourceDir* out_dir,
+ std::string* out_name,
+ SourceDir* out_toolchain_dir,
+ std::string* out_toolchain_name,
+ Err* err) {
+ // To workaround the problem that StringPiece operator[] doesn't return a ref.
+ const char* input_str = input.data();
+
+ size_t path_separator = input.find_first_of(":(");
+ base::StringPiece location_piece;
+ base::StringPiece name_piece;
+ base::StringPiece toolchain_piece;
+ if (path_separator == std::string::npos) {
+ location_piece = input;
+ // Leave name & toolchain piece null.
+ } else {
+ location_piece = base::StringPiece(&input_str[0], path_separator);
+
+ size_t toolchain_separator = input.find('(', path_separator);
+ if (toolchain_separator == std::string::npos) {
+ name_piece = base::StringPiece(&input_str[path_separator + 1],
+ input.size() - path_separator - 1);
+ // Leave location piece null.
+ } else if (!out_toolchain_dir) {
+ // Toolchain specified but not allows in this context.
+ *err = Err(original_value, "Toolchain has a toolchain.",
+ "Your toolchain definition (inside the parens) seems to itself "
+ "have a\ntoolchain. Don't do this.");
+ return false;
+ } else {
+ // Name piece is everything between the two separators. Note that the
+ // separators may be the same (e.g. "//foo(bar)" which means empty name.
+ if (toolchain_separator > path_separator) {
+ name_piece = base::StringPiece(
+ &input_str[path_separator + 1],
+ toolchain_separator - path_separator - 1);
+ }
+
+ // Toolchain name should end in a ) and this should be the end of the
+ // string.
+ if (input[input.size() - 1] != ')') {
+ *err = Err(original_value, "Bad toolchain name.",
+ "Toolchain name must end in a \")\" at the end of the label.");
+ return false;
+ }
+
+ // Subtract off the two parens to just get the toolchain name.
+ toolchain_piece = base::StringPiece(
+ &input_str[toolchain_separator + 1],
+ input.size() - toolchain_separator - 2);
+ }
+ }
+
+ // Everything before the separator is the filename.
+ // We allow three cases:
+ // Absolute: "//foo:bar" -> /foo:bar
+ // Target in current file: ":foo" -> <currentdir>:foo
+ // Path with implicit name: "/foo" -> /foo:foo
+ if (location_piece.empty() && name_piece.empty()) {
+ // Can't use both implicit filename and name (":").
+ *err = Err(original_value, "This doesn't specify a dependency.");
+ return false;
+ }
+
+ if (!ComputeBuildLocationFromDep(original_value, current_dir, location_piece,
+ out_dir, err))
+ return false;
+
+ if (!ComputeTargetNameFromDep(original_value, *out_dir, name_piece,
+ out_name, err))
+ return false;
+
+ // Last, do the toolchains.
+ if (out_toolchain_dir) {
+ // Handle empty toolchain strings. We don't allow normal labels to be
+ // empty so we can't allow the recursive call of this function to do this
+ // check.
+ if (toolchain_piece.empty()) {
+ *out_toolchain_dir = current_toolchain.dir();
+ *out_toolchain_name = current_toolchain.name();
+ return true;
+ } else {
+ return Resolve(current_dir, current_toolchain,
+ original_value, toolchain_piece,
+ out_toolchain_dir, out_toolchain_name, NULL, NULL, err);
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+Label::Label() {
+}
+
+Label::Label(const SourceDir& dir,
+ const base::StringPiece& name,
+ const SourceDir& toolchain_dir,
+ const base::StringPiece& toolchain_name)
+ : dir_(dir),
+ toolchain_dir_(toolchain_dir) {
+ name_.assign(name.data(), name.size());
+ toolchain_name_.assign(toolchain_name.data(), toolchain_name.size());
+}
+
+Label::~Label() {
+}
+
+// static
+Label Label::Resolve(const SourceDir& current_dir,
+ const Label& current_toolchain,
+ const Value& input,
+ Err* err) {
+ Label ret;
+ if (input.type() != Value::STRING) {
+ *err = Err(input, "Dependency is not a string.");
+ return ret;
+ }
+ const std::string& input_string = input.string_value();
+ if (input_string.empty()) {
+ *err = Err(input, "Dependency string is empty.");
+ return ret;
+ }
+
+ if (!::Resolve(current_dir, current_toolchain, input, input_string,
+ &ret.dir_, &ret.name_,
+ &ret.toolchain_dir_, &ret.toolchain_name_,
+ err))
+ return Label();
+ return ret;
+}
+
+Label Label::GetToolchainLabel() const {
+ return Label(toolchain_dir_, toolchain_name_,
+ SourceDir(), base::StringPiece());
+}
+
+std::string Label::GetUserVisibleName(bool include_toolchain) const {
+ std::string ret;
+ ret.reserve(dir_.value().size() + name_.size() + 1);
+
+ if (dir_.is_null())
+ return ret;
+
+ ret = DirWithNoTrailingSlash(dir_);
+ ret.push_back(':');
+ ret.append(name_);
+
+ if (include_toolchain) {
+ ret.push_back('(');
+ if (!toolchain_dir_.is_null() && !toolchain_name_.empty()) {
+ ret.append(DirWithNoTrailingSlash(toolchain_dir_));
+ ret.push_back(':');
+ ret.append(toolchain_name_);
+ }
+ ret.push_back(')');
+ }
+ return ret;
+}
+
+std::string Label::GetUserVisibleName(const Label& default_toolchain) const {
+ bool include_toolchain =
+ default_toolchain.dir() != toolchain_dir_ ||
+ default_toolchain.name() != toolchain_name_;
+ return GetUserVisibleName(include_toolchain);
+}
diff --git a/chromium/tools/gn/label.h b/chromium/tools/gn/label.h
new file mode 100644
index 00000000000..b31117a2b9b
--- /dev/null
+++ b/chromium/tools/gn/label.h
@@ -0,0 +1,116 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_LABEL_H_
+#define TOOLS_GN_LABEL_H_
+
+#include "base/containers/hash_tables.h"
+#include "build/build_config.h"
+#include "tools/gn/source_dir.h"
+
+class Err;
+class Value;
+
+// A label represents the name of a target or some other named thing in
+// the source path. The label is always absolute and always includes a name
+// part, so it starts with a slash, and has one colon.
+class Label {
+ public:
+ Label();
+
+ // Makes a label given an already-separate out path and name.
+ // See also Resolve().
+ Label(const SourceDir& dir,
+ const base::StringPiece& name,
+ const SourceDir& toolchain_dir,
+ const base::StringPiece& toolchain_name);
+ ~Label();
+
+ // Resolives a string from a build file that may be relative to the
+ // current directory into a fully qualified label. On failure returns an
+ // is_null() label and sets the error.
+ static Label Resolve(const SourceDir& current_dir,
+ const Label& current_toolchain,
+ const Value& input,
+ Err* err);
+
+ bool is_null() const { return dir_.is_null(); }
+
+ const SourceDir& dir() const { return dir_; }
+ const std::string& name() const { return name_; }
+
+ const SourceDir& toolchain_dir() const { return toolchain_dir_; }
+ const std::string& toolchain_name() const { return toolchain_name_; }
+ Label GetToolchainLabel() const;
+
+ // Formats this label in a way that we can present to the user or expose to
+ // other parts of the system. SourceDirs end in slashes, but the user
+ // expects names like "//chrome/renderer:renderer_config" when printed. The
+ // toolchain is optionally included.
+ std::string GetUserVisibleName(bool include_toolchain) const;
+
+ // Like the above version, but automatically includes the toolchain if it's
+ // not the default one. Normally the user only cares about the toolchain for
+ // non-default ones, so this can make certain output more clear.
+ std::string GetUserVisibleName(const Label& default_toolchain) const;
+
+ bool operator==(const Label& other) const {
+ return name_ == other.name_ && dir_ == other.dir_ &&
+ toolchain_dir_ == other.toolchain_dir_ &&
+ toolchain_name_ == other.toolchain_name_;
+ }
+ bool operator!=(const Label& other) const {
+ return !operator==(other);
+ }
+ bool operator<(const Label& other) const {
+ // TODO(brettw) could be optimized to avoid an extra full string check
+ // (one for operator==, one for <).
+ if (dir_ != other.dir_)
+ return dir_ < other.dir_;
+ if (name_ != other.name_)
+ return name_ < other.name_;
+ if (toolchain_dir_ != other.toolchain_dir_)
+ return toolchain_dir_ < other.toolchain_dir_;
+ return toolchain_name_ < other.toolchain_name_;
+ }
+
+ // Returns true if the toolchain dir/name of this object matches some
+ // other object.
+ bool ToolchainsEqual(const Label& other) const {
+ return toolchain_dir_ == other.toolchain_dir_ &&
+ toolchain_name_ == other.toolchain_name_;
+ }
+
+ private:
+ SourceDir dir_;
+ std::string name_;
+
+ SourceDir toolchain_dir_;
+ std::string toolchain_name_;
+};
+
+namespace BASE_HASH_NAMESPACE {
+
+#if defined(COMPILER_GCC)
+template<> struct hash<Label> {
+ std::size_t operator()(const Label& v) const {
+ hash<std::string> stringhash;
+ return ((stringhash(v.dir().value()) * 131 +
+ stringhash(v.name())) * 131 +
+ stringhash(v.toolchain_dir().value())) * 131 +
+ stringhash(v.toolchain_name());
+ }
+};
+#elif defined(COMPILER_MSVC)
+inline size_t hash_value(const Label& v) {
+ return ((hash_value(v.dir().value()) * 131 +
+ hash_value(v.name())) * 131 +
+ hash_value(v.toolchain_dir().value())) * 131 +
+ hash_value(v.toolchain_name());
+}
+#endif // COMPILER...
+
+} // namespace BASE_HASH_NAMESPACE
+
+#endif // TOOLS_GN_LABEL_H_
diff --git a/chromium/tools/gn/label_unittest.cc b/chromium/tools/gn/label_unittest.cc
new file mode 100644
index 00000000000..74eb3da9e80
--- /dev/null
+++ b/chromium/tools/gn/label_unittest.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/err.h"
+#include "tools/gn/label.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+struct ParseDepStringCase {
+ const char* cur_dir;
+ const char* str;
+ bool success;
+ const char* expected_dir;
+ const char* expected_name;
+ const char* expected_toolchain_dir;
+ const char* expected_toolchain_name;
+};
+
+} // namespace
+
+TEST(Label, Resolve) {
+ ParseDepStringCase cases[] = {
+ // cur input succ expected dir name tc dir tc name
+ { "//chrome/", "", false, "", "", "", "" },
+ { "//chrome/", "/", false, "", "", "", "" },
+ { "//chrome/", ":", false, "", "", "", "" },
+ { "//chrome/", "/:", false, "", "", "", "" },
+ { "//chrome/", "blah", true, "//chrome/blah/", "blah", "//t/", "d" },
+ { "//chrome/", "blah:bar", true, "//chrome/blah/", "bar", "//t/", "d" },
+ // No single-leading slash.
+ { "//chrome/", "/chrome:bar", false, "", "", "", "" },
+ // No trailing slash.
+ { "//chrome/", "/chrome/:bar", false, "", "", "", "" },
+ // Refers to root dir.
+ { "//chrome/", "//:bar", true, "//", "bar", "//t/", "d" },
+ // Implicit directory
+ { "//chrome/", ":bar", true, "//chrome/", "bar", "//t/", "d" },
+ { "//chrome/renderer/", ":bar", true, "//chrome/renderer/", "bar", "//t/", "d" },
+ // Implicit names.
+ { "//chrome/", "//base", true, "//base/", "base", "//t/", "d" },
+ { "//chrome/", "//base/i18n", true, "//base/i18n/", "i18n", "//t/", "d" },
+ { "//chrome/", "//base/i18n:foo", true, "//base/i18n/", "foo", "//t/", "d" },
+ // Toolchain parsing.
+ { "//chrome/", "//chrome:bar(//t:n)", true, "//chrome/", "bar", "//t/", "n" },
+ { "//chrome/", "//chrome:bar(//t)", true, "//chrome/", "bar", "//t/", "t" },
+ { "//chrome/", "//chrome:bar(//t:)", true, "//chrome/", "bar", "//t/", "t" },
+ { "//chrome/", "//chrome:bar()", true, "//chrome/", "bar", "//t/", "d" },
+ { "//chrome/", "//chrome:bar(foo)", true, "//chrome/", "bar", "//chrome/foo/", "foo" },
+ { "//chrome/", "//chrome:bar(:foo)", true, "//chrome/", "bar", "//chrome/", "foo" },
+ // TODO(brettw) it might be nice to make this an error:
+ //{ "//chrome/", "//chrome:bar())", false, "", "", "", "" },
+ { "//chrome/", "//chrome:bar(//t:bar(tc))", false, "", "", "", "" },
+ { "//chrome/", "//chrome:bar(()", false, "", "", "", "" },
+ { "//chrome/", "(t:b)", false, "", "", "", "" },
+ { "//chrome/", ":bar(//t/b)", true, "//chrome/", "bar", "//t/b/", "b" },
+ { "//chrome/", ":bar(/t/b)", false, "", "", "", "" },
+ { "//chrome/", ":bar(t/b)", true, "//chrome/", "bar", "//chrome/t/b/", "b" },
+ };
+
+ Label default_toolchain(SourceDir("//t/"), "d",
+ SourceDir(), std::string());
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
+ const ParseDepStringCase& cur = cases[i];
+
+ std::string location, name;
+ Err err;
+ Value v(NULL, Value::STRING);
+ v.string_value() = cur.str;
+ Label result =
+ Label::Resolve(SourceDir(cur.cur_dir), default_toolchain, v, &err);
+ EXPECT_EQ(cur.success, !err.has_error()) << i << " " << cur.str;
+ if (!err.has_error() && cur.success) {
+ EXPECT_EQ(cur.expected_dir, result.dir().value())
+ << i << " " << cur.str;
+ EXPECT_EQ(cur.expected_name, result.name())
+ << i << " " << cur.str;
+ EXPECT_EQ(cur.expected_toolchain_dir,
+ result.toolchain_dir().value())
+ << i << " " << cur.str;
+ EXPECT_EQ(cur.expected_toolchain_name, result.toolchain_name())
+ << i << " " << cur.str;
+ }
+ }
+}
diff --git a/chromium/tools/gn/location.h b/chromium/tools/gn/location.h
new file mode 100644
index 00000000000..20551256e14
--- /dev/null
+++ b/chromium/tools/gn/location.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_LOCATION_H_
+#define TOOLS_GN_LOCATION_H_
+
+#include <algorithm>
+
+#include "base/logging.h"
+
+class InputFile;
+
+// Represents a place in a source file. Used for error reporting.
+class Location {
+ public:
+ Location()
+ : file_(NULL),
+ line_number_(-1),
+ char_offset_(-1) {
+ }
+ Location(const InputFile* file, int line_number, int char_offset)
+ : file_(file),
+ line_number_(line_number),
+ char_offset_(char_offset) {
+ }
+
+ const InputFile* file() const { return file_; }
+ int line_number() const { return line_number_; }
+ int char_offset() const { return char_offset_; }
+
+ bool operator==(const Location& other) const {
+ return other.file_ == file_ &&
+ other.line_number_ == line_number_ &&
+ other.char_offset_ == char_offset_;
+ }
+
+ bool operator<(const Location& other) const {
+ DCHECK(file_ == other.file_);
+ if (line_number_ != other.line_number_)
+ return line_number_ < other.line_number_;
+ return char_offset_ < other.char_offset_;
+ }
+
+ private:
+ const InputFile* file_; // Null when unset.
+ int line_number_; // -1 when unset.
+ int char_offset_; // -1 when unset.
+};
+
+// Represents a range in a source file. Used for error reporting.
+// The end is exclusive i.e. [begin, end)
+class LocationRange {
+ public:
+ LocationRange() {}
+ LocationRange(const Location& begin, const Location& end)
+ : begin_(begin),
+ end_(end) {
+ DCHECK(begin_.file() == end_.file());
+ }
+
+ const Location& begin() const { return begin_; }
+ const Location& end() const { return end_; }
+
+ LocationRange Union(const LocationRange& other) const {
+ DCHECK(begin_.file() == other.begin_.file());
+ return LocationRange(
+ begin_ < other.begin_ ? begin_ : other.begin_,
+ end_ < other.end_ ? other.end_ : end_);
+ }
+
+ private:
+ Location begin_;
+ Location end_;
+};
+
+#endif // TOOLS_GN_LOCATION_H_
diff --git a/chromium/tools/gn/ninja_binary_target_writer.cc b/chromium/tools/gn/ninja_binary_target_writer.cc
new file mode 100644
index 00000000000..3ca925477b4
--- /dev/null
+++ b/chromium/tools/gn/ninja_binary_target_writer.cc
@@ -0,0 +1,346 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_binary_target_writer.h"
+
+#include "tools/gn/config_values_extractors.h"
+#include "tools/gn/err.h"
+#include "tools/gn/escape.h"
+#include "tools/gn/string_utils.h"
+
+namespace {
+
+// Returns the proper escape options for writing compiler and linker flags.
+EscapeOptions GetFlagOptions() {
+ EscapeOptions opts;
+ opts.mode = ESCAPE_NINJA;
+
+ // Some flag strings are actually multiple flags that expect to be just
+ // added to the command line. We assume that quoting is done by the
+ // buildfiles if it wants such things quoted.
+ opts.inhibit_quoting = true;
+
+ return opts;
+}
+
+struct DefineWriter {
+ void operator()(const std::string& s, std::ostream& out) const {
+ out << " -D" << s;
+ }
+};
+
+struct IncludeWriter {
+ IncludeWriter(PathOutput& path_output,
+ const NinjaHelper& h)
+ : helper(h),
+ path_output_(path_output),
+ old_inhibit_quoting_(path_output.inhibit_quoting()) {
+ // Inhibit quoting since we'll put quotes around the whole thing ourselves.
+ // Since we're writing in NINJA escaping mode, this won't actually do
+ // anything, but I think we may need to change to shell-and-then-ninja
+ // escaping for this in the future.
+ path_output_.set_inhibit_quoting(true);
+ }
+ ~IncludeWriter() {
+ path_output_.set_inhibit_quoting(old_inhibit_quoting_);
+ }
+
+ void operator()(const SourceDir& d, std::ostream& out) const {
+ out << " \"-I";
+ // It's important not to include the trailing slash on directories or on
+ // Windows it will be a backslash and the compiler might think we're
+ // escaping the quote!
+ path_output_.WriteDir(out, d, PathOutput::DIR_NO_LAST_SLASH);
+ out << "\"";
+ }
+
+ const NinjaHelper& helper;
+ PathOutput& path_output_;
+ bool old_inhibit_quoting_; // So we can put the PathOutput back.
+};
+
+} // namespace
+
+NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target,
+ std::ostream& out)
+ : NinjaTargetWriter(target, out) {
+}
+
+NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() {
+}
+
+void NinjaBinaryTargetWriter::Run() {
+ WriteEnvironment();
+
+ WriteCompilerVars();
+
+ std::vector<OutputFile> obj_files;
+ WriteSources(&obj_files);
+
+ WriteLinkerStuff(obj_files);
+}
+
+void NinjaBinaryTargetWriter::WriteCompilerVars() {
+ // Defines.
+ out_ << "defines =";
+ RecursiveTargetConfigToStream(target_, &ConfigValues::defines,
+ DefineWriter(), out_);
+ out_ << std::endl;
+
+ // Includes.
+ out_ << "includes =";
+ RecursiveTargetConfigToStream(target_, &ConfigValues::includes,
+ IncludeWriter(path_output_, helper_), out_);
+
+ out_ << std::endl;
+
+ // C flags and friends.
+ EscapeOptions flag_escape_options = GetFlagOptions();
+#define WRITE_FLAGS(name) \
+ out_ << #name " ="; \
+ RecursiveTargetConfigStringsToStream(target_, &ConfigValues::name, \
+ flag_escape_options, out_); \
+ out_ << std::endl;
+
+ WRITE_FLAGS(cflags)
+ WRITE_FLAGS(cflags_c)
+ WRITE_FLAGS(cflags_cc)
+ WRITE_FLAGS(cflags_objc)
+ WRITE_FLAGS(cflags_objcc)
+
+#undef WRITE_FLAGS
+
+ out_ << std::endl;
+}
+
+void NinjaBinaryTargetWriter::WriteSources(
+ std::vector<OutputFile>* object_files) {
+ const Target::FileList& sources = target_->sources();
+ object_files->reserve(sources.size());
+
+ for (size_t i = 0; i < sources.size(); i++) {
+ const SourceFile& input_file = sources[i];
+
+ SourceFileType input_file_type = GetSourceFileType(input_file,
+ settings_->target_os());
+ if (input_file_type == SOURCE_UNKNOWN)
+ continue; // Skip unknown file types.
+ const char* command = GetCommandForSourceType(input_file_type);
+ if (!command)
+ continue; // Skip files not needing compilation.
+
+ OutputFile output_file = helper_.GetOutputFileForSource(
+ target_, input_file, input_file_type);
+ object_files->push_back(output_file);
+
+ out_ << "build ";
+ path_output_.WriteFile(out_, output_file);
+ out_ << ": " << command << " ";
+ path_output_.WriteFile(out_, input_file);
+ out_ << std::endl;
+ }
+ out_ << std::endl;
+}
+
+void NinjaBinaryTargetWriter::WriteLinkerStuff(
+ const std::vector<OutputFile>& object_files) {
+ // Manifest file on Windows.
+ // TODO(brettw) this seems not to be necessary for static libs, skip in
+ // that case?
+ OutputFile windows_manifest;
+ if (settings_->IsWin()) {
+ windows_manifest.value().assign(helper_.GetTargetOutputDir(target_));
+ windows_manifest.value().append(target_->label().name());
+ windows_manifest.value().append(".intermediate.manifest");
+ out_ << "manifests = ";
+ path_output_.WriteFile(out_, windows_manifest);
+ out_ << std::endl;
+ }
+
+ // Linker flags, append manifest flag on Windows to reference our file.
+ out_ << "ldflags =";
+ RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags,
+ GetFlagOptions(), out_);
+ // HACK ERASEME BRETTW FIXME
+ if (settings_->IsWin()) {
+ out_ << " /MANIFEST /ManifestFile:";
+ path_output_.WriteFile(out_, windows_manifest);
+ out_ << " /DEBUG /MACHINE:X86 /LIBPATH:\"C:\\Program Files (x86)\\Windows Kits\\8.0\\Lib\\win8\\um\\x86\" /DELAYLOAD:dbghelp.dll /DELAYLOAD:dwmapi.dll /DELAYLOAD:shell32.dll /DELAYLOAD:uxtheme.dll /safeseh /dynamicbase /ignore:4199 /ignore:4221 /nxcompat /SUBSYSTEM:CONSOLE /INCREMENTAL /FIXED:NO /DYNAMICBASE:NO wininet.lib dnsapi.lib version.lib msimg32.lib ws2_32.lib usp10.lib psapi.lib dbghelp.lib winmm.lib shlwapi.lib kernel32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib user32.lib uuid.lib odbc32.lib odbccp32.lib delayimp.lib /NXCOMPAT";
+ }
+ out_ << std::endl;
+
+ // Libraries to link.
+ out_ << "libs =";
+ if (settings_->IsMac()) {
+ // TODO(brettw) fix this.
+ out_ << " -framework AppKit -framework ApplicationServices -framework Carbon -framework CoreFoundation -framework Foundation -framework IOKit -framework Security";
+ }
+ out_ << std::endl;
+
+ // The external output file is the one that other libs depend on.
+ OutputFile external_output_file = helper_.GetTargetOutputFile(target_);
+
+ // The internal output file is the "main thing" we think we're making. In
+ // the case of shared libraries, this is the shared library and the external
+ // output file is the import library. In other cases, the internal one and
+ // the external one are the same.
+ OutputFile internal_output_file;
+ if (target_->output_type() == Target::SHARED_LIBRARY) {
+ if (settings_->IsWin()) {
+ internal_output_file = OutputFile(target_->label().name() + ".dll");
+ } else {
+ internal_output_file = external_output_file;
+ }
+ } else {
+ internal_output_file = external_output_file;
+ }
+
+ // In Python see "self.ninja.build(output, command, input,"
+ WriteLinkCommand(external_output_file, internal_output_file, object_files);
+
+ if (target_->output_type() == Target::SHARED_LIBRARY) {
+ // The shared object name doesn't include a path.
+ out_ << " soname = ";
+ out_ << FindFilename(&internal_output_file.value());
+ out_ << std::endl;
+
+ out_ << " lib = ";
+ path_output_.WriteFile(out_, internal_output_file);
+ out_ << std::endl;
+
+ if (settings_->IsWin()) {
+ out_ << " dll = ";
+ path_output_.WriteFile(out_, internal_output_file);
+ out_ << std::endl;
+ }
+
+ if (settings_->IsWin()) {
+ out_ << " implibflag = /IMPLIB:";
+ path_output_.WriteFile(out_, external_output_file);
+ out_ << std::endl;
+ }
+
+ // TODO(brettw) postbuild steps.
+ if (settings_->IsMac())
+ out_ << " postbuilds = $ && (export BUILT_PRODUCTS_DIR=/Users/brettw/prj/src/out/gn; export CONFIGURATION=Debug; export DYLIB_INSTALL_NAME_BASE=@rpath; export EXECUTABLE_NAME=libbase.dylib; export EXECUTABLE_PATH=libbase.dylib; export FULL_PRODUCT_NAME=libbase.dylib; export LD_DYLIB_INSTALL_NAME=@rpath/libbase.dylib; export MACH_O_TYPE=mh_dylib; export PRODUCT_NAME=base; export PRODUCT_TYPE=com.apple.product-type.library.dynamic; export SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk; export SRCROOT=/Users/brettw/prj/src/out/gn/../../base; export SOURCE_ROOT=\"$${SRCROOT}\"; export TARGET_BUILD_DIR=/Users/brettw/prj/src/out/gn; export TEMP_DIR=\"$${TMPDIR}\"; (cd ../../base && ../build/mac/strip_from_xcode); G=$$?; ((exit $$G) || rm -rf libbase.dylib) && exit $$G)";
+ }
+
+ out_ << std::endl;
+}
+
+void NinjaBinaryTargetWriter::WriteLinkCommand(
+ const OutputFile& external_output_file,
+ const OutputFile& internal_output_file,
+ const std::vector<OutputFile>& object_files) {
+ out_ << "build ";
+ path_output_.WriteFile(out_, internal_output_file);
+ if (external_output_file != internal_output_file) {
+ out_ << " ";
+ path_output_.WriteFile(out_, external_output_file);
+ }
+ out_ << ": " << GetCommandForTargetType();
+
+ // Object files.
+ for (size_t i = 0; i < object_files.size(); i++) {
+ out_ << " ";
+ path_output_.WriteFile(out_, object_files[i]);
+ }
+
+ // Library inputs (deps and inherited static libraries).
+ //
+ // Static libraries since they're just a collection of the object files so
+ // don't need libraries linked with them, but we still need to go through
+ // the list and find non-linkable data deps in the "deps" section. We'll
+ // collect all non-linkable deps and put it in the order-only deps below.
+ std::vector<const Target*> extra_data_deps;
+ const std::vector<const Target*>& deps = target_->deps();
+ const std::set<const Target*>& inherited = target_->inherited_libraries();
+ for (size_t i = 0; i < deps.size(); i++) {
+ if (inherited.find(deps[i]) != inherited.end())
+ continue;
+ if (target_->output_type() != Target::STATIC_LIBRARY &&
+ deps[i]->IsLinkable()) {
+ out_ << " ";
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(deps[i]));
+ } else {
+ extra_data_deps.push_back(deps[i]);
+ }
+ }
+ for (std::set<const Target*>::const_iterator i = inherited.begin();
+ i != inherited.end(); ++i) {
+ if (target_->output_type() == Target::STATIC_LIBRARY) {
+ extra_data_deps.push_back(*i);
+ } else {
+ out_ << " ";
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(*i));
+ }
+ }
+
+ // Append data dependencies as order-only dependencies.
+ const std::vector<const Target*>& datadeps = target_->datadeps();
+ const std::vector<SourceFile>& data = target_->data();
+ if (!extra_data_deps.empty() || !datadeps.empty() || !data.empty()) {
+ out_ << " ||";
+
+ // Non-linkable deps in the deps section above.
+ for (size_t i = 0; i < extra_data_deps.size(); i++) {
+ out_ << " ";
+ path_output_.WriteFile(out_,
+ helper_.GetTargetOutputFile(extra_data_deps[i]));
+ }
+
+ // Data deps.
+ for (size_t i = 0; i < datadeps.size(); i++) {
+ out_ << " ";
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(datadeps[i]));
+ }
+
+ // Data files.
+ const std::vector<SourceFile>& data = target_->data();
+ for (size_t i = 0; i < data.size(); i++) {
+ out_ << " ";
+ path_output_.WriteFile(out_, data[i]);
+ }
+ }
+
+ out_ << std::endl;
+}
+
+const char* NinjaBinaryTargetWriter::GetCommandForSourceType(
+ SourceFileType type) const {
+ if (type == SOURCE_C)
+ return "cc";
+ if (type == SOURCE_CC)
+ return "cxx";
+
+ // TODO(brettw) asm files.
+
+ if (settings_->IsMac()) {
+ if (type == SOURCE_M)
+ return "objc";
+ if (type == SOURCE_MM)
+ return "objcxx";
+ }
+
+ if (settings_->IsWin()) {
+ if (type == SOURCE_RC)
+ return "rc";
+ }
+
+ // TODO(brettw) stuff about "S" files on non-Windows.
+ return NULL;
+}
+
+const char* NinjaBinaryTargetWriter::GetCommandForTargetType() const {
+ if (target_->output_type() == Target::STATIC_LIBRARY) {
+ // TODO(brettw) stuff about standalong static libraryes on Unix in
+ // WriteTarget in the Python one, and lots of postbuild steps.
+ return "alink";
+ }
+
+ if (target_->output_type() == Target::SHARED_LIBRARY)
+ return "solink";
+
+ return "link";
+}
diff --git a/chromium/tools/gn/ninja_binary_target_writer.h b/chromium/tools/gn/ninja_binary_target_writer.h
new file mode 100644
index 00000000000..f21e11d8ec8
--- /dev/null
+++ b/chromium/tools/gn/ninja_binary_target_writer.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_BINARY_TARGET_WRITER_H_
+#define TOOLS_GN_NINJA_BINARY_TARGET_WRITER_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/ninja_target_writer.h"
+
+// Writes a .ninja file for a binary target type (an executable, a shared
+// library, or a static library).
+class NinjaBinaryTargetWriter : public NinjaTargetWriter {
+ public:
+ NinjaBinaryTargetWriter(const Target* target, std::ostream& out);
+ virtual ~NinjaBinaryTargetWriter();
+
+ virtual void Run() OVERRIDE;
+
+ private:
+ void WriteCompilerVars();
+ void WriteSources(std::vector<OutputFile>* object_files);
+ void WriteLinkerStuff(const std::vector<OutputFile>& object_files);
+
+ // Writes the build line for linking the target. Includes newline.
+ void WriteLinkCommand(const OutputFile& external_output_file,
+ const OutputFile& internal_output_file,
+ const std::vector<OutputFile>& object_files);
+
+ // Returns NULL if the source type should not be compiled on this target.
+ const char* GetCommandForSourceType(SourceFileType type) const;
+
+ const char* GetCommandForTargetType() const;
+
+ DISALLOW_COPY_AND_ASSIGN(NinjaBinaryTargetWriter);
+};
+
+#endif // TOOLS_GN_NINJA_BINARY_TARGET_WRITER_H_
+
diff --git a/chromium/tools/gn/ninja_build_writer.cc b/chromium/tools/gn/ninja_build_writer.cc
new file mode 100644
index 00000000000..bcbd48c8be5
--- /dev/null
+++ b/chromium/tools/gn/ninja_build_writer.cc
@@ -0,0 +1,162 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_build_writer.h"
+
+#include <fstream>
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/process/process_handle.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/escape.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/input_file_manager.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/target.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+namespace {
+
+std::string GetSelfInvocationCommand(const BuildSettings* build_settings) {
+#if defined(OS_WIN)
+ wchar_t module[MAX_PATH];
+ GetModuleFileName(NULL, module, MAX_PATH);
+ //result = "\"" + WideToUTF8(module) + "\"";
+ base::FilePath executable(module);
+#elif defined(OS_MACOSX)
+ // FIXME(brettw) write this on Mac!
+ base::FilePath executable("../Debug/gn");
+#else
+ base::FilePath executable =
+ base::GetProcessExecutablePath(base::GetCurrentProcessHandle());
+#endif
+
+/*
+ // Append the root path.
+ CommandLine* cmdline = CommandLine::ForCurrentProcess();
+ result += " --root=\"" + FilePathToUTF8(settings->root_path()) + "\"";
+*/
+
+ CommandLine cmdline(executable);
+ cmdline.AppendSwitchPath("--root", build_settings->root_path());
+
+ // TODO(brettw) append other parameters.
+
+#if defined(OS_WIN)
+ return WideToUTF8(cmdline.GetCommandLineString());
+#else
+ return cmdline.GetCommandLineString();
+#endif
+}
+
+} // namespace
+
+NinjaBuildWriter::NinjaBuildWriter(
+ const BuildSettings* build_settings,
+ const std::vector<const Settings*>& all_settings,
+ const std::vector<const Target*>& default_toolchain_targets,
+ std::ostream& out)
+ : build_settings_(build_settings),
+ all_settings_(all_settings),
+ default_toolchain_targets_(default_toolchain_targets),
+ out_(out),
+ path_output_(build_settings->build_dir(), ESCAPE_NINJA, true),
+ helper_(build_settings) {
+}
+
+NinjaBuildWriter::~NinjaBuildWriter() {
+}
+
+void NinjaBuildWriter::Run() {
+ WriteNinjaRules();
+ WriteSubninjas();
+ WritePhonyAndAllRules();
+}
+
+// static
+bool NinjaBuildWriter::RunAndWriteFile(
+ const BuildSettings* build_settings,
+ const std::vector<const Settings*>& all_settings,
+ const std::vector<const Target*>& default_toolchain_targets) {
+ base::FilePath ninja_file(build_settings->GetFullPath(
+ SourceFile(build_settings->build_dir().value() + "build.ninja")));
+ file_util::CreateDirectory(ninja_file.DirName());
+
+ std::ofstream file;
+ file.open(FilePathToUTF8(ninja_file).c_str(),
+ std::ios_base::out | std::ios_base::binary);
+ if (file.fail())
+ return false;
+
+ NinjaBuildWriter gen(build_settings, all_settings,
+ default_toolchain_targets, file);
+ gen.Run();
+ return true;
+}
+
+void NinjaBuildWriter::WriteNinjaRules() {
+ out_ << "rule gn\n";
+ out_ << " command = " << GetSelfInvocationCommand(build_settings_) << "\n";
+ out_ << " description = GN the world\n\n";
+
+ out_ << "build build.ninja: gn";
+
+ // Input build files.
+ std::vector<base::FilePath> input_files;
+ g_scheduler->input_file_manager()->GetAllPhysicalInputFileNames(&input_files);
+ EscapeOptions ninja_options;
+ ninja_options.mode = ESCAPE_NINJA;
+ for (size_t i = 0; i < input_files.size(); i++)
+ out_ << " " << EscapeString(FilePathToUTF8(input_files[i]), ninja_options);
+
+ // Other files read by the build.
+ std::vector<base::FilePath> other_files = g_scheduler->GetGenDependencies();
+ for (size_t i = 0; i < other_files.size(); i++)
+ out_ << " " << EscapeString(FilePathToUTF8(other_files[i]), ninja_options);
+
+ out_ << std::endl << std::endl;
+}
+
+void NinjaBuildWriter::WriteSubninjas() {
+ for (size_t i = 0; i < all_settings_.size(); i++) {
+ out_ << "subninja ";
+ path_output_.WriteFile(out_,
+ helper_.GetNinjaFileForToolchain(all_settings_[i]));
+ out_ << std::endl;
+ }
+ out_ << std::endl;
+}
+
+void NinjaBuildWriter::WritePhonyAndAllRules() {
+ std::string all_rules;
+
+ // Write phony rules for the default toolchain (don't do other toolchains or
+ // we'll get naming conflicts).
+ for (size_t i = 0; i < default_toolchain_targets_.size(); i++) {
+ const Target* target = default_toolchain_targets_[i];
+
+ OutputFile target_file = helper_.GetTargetOutputFile(target);
+ if (target_file.value() != target->label().name()) {
+ out_ << "build " << target->label().name() << ": phony ";
+ path_output_.WriteFile(out_, target_file);
+ out_ << std::endl;
+ }
+
+ if (!all_rules.empty())
+ all_rules.append(" $\n ");
+ all_rules.append(target_file.value());
+ }
+
+ if (!all_rules.empty()) {
+ out_ << "\nbuild all: phony " << all_rules << std::endl;
+ out_ << "default all" << std::endl;
+ }
+}
+
diff --git a/chromium/tools/gn/ninja_build_writer.h b/chromium/tools/gn/ninja_build_writer.h
new file mode 100644
index 00000000000..85548df7697
--- /dev/null
+++ b/chromium/tools/gn/ninja_build_writer.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_BUILD_WRITER_H_
+#define TOOLS_GN_NINJA_BUILD_WRITER_H_
+
+#include <iosfwd>
+#include <vector>
+
+#include "tools/gn/ninja_helper.h"
+#include "tools/gn/path_output.h"
+
+class BuildSettings;
+class Settings;
+class Target;
+
+// Generates the toplevel "build.ninja" file. This references the individual
+// toolchain files and lists all input .gn files as dependencies of the
+// build itself.
+class NinjaBuildWriter {
+ public:
+ static bool RunAndWriteFile(
+ const BuildSettings* settings,
+ const std::vector<const Settings*>& all_settings,
+ const std::vector<const Target*>& default_toolchain_targets);
+
+ private:
+ NinjaBuildWriter(const BuildSettings* settings,
+ const std::vector<const Settings*>& all_settings,
+ const std::vector<const Target*>& default_toolchain_targets,
+ std::ostream& out);
+ ~NinjaBuildWriter();
+
+ void Run();
+
+ void WriteNinjaRules();
+ void WriteSubninjas();
+ void WritePhonyAndAllRules();
+
+ const BuildSettings* build_settings_;
+ std::vector<const Settings*> all_settings_;
+ std::vector<const Target*> default_toolchain_targets_;
+ std::ostream& out_;
+ PathOutput path_output_;
+
+ NinjaHelper helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(NinjaBuildWriter);
+};
+
+#endif // TOOLS_GN_NINJA_BUILD_GENERATOR_H_
+
diff --git a/chromium/tools/gn/ninja_copy_target_writer.cc b/chromium/tools/gn/ninja_copy_target_writer.cc
new file mode 100644
index 00000000000..4d2ebe07684
--- /dev/null
+++ b/chromium/tools/gn/ninja_copy_target_writer.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_copy_target_writer.h"
+
+#include "base/strings/string_util.h"
+#include "tools/gn/string_utils.h"
+
+NinjaCopyTargetWriter::NinjaCopyTargetWriter(const Target* target,
+ std::ostream& out)
+ : NinjaTargetWriter(target, out) {
+}
+
+NinjaCopyTargetWriter::~NinjaCopyTargetWriter() {
+}
+
+void NinjaCopyTargetWriter::Run() {
+ // The dest dir should be inside the output dir so we can just remove the
+ // prefix and get ninja-relative paths.
+ const std::string& output_dir =
+ settings_->build_settings()->build_dir().value();
+ const std::string& dest_dir = target_->destdir().value();
+ DCHECK(StartsWithASCII(dest_dir, output_dir, true));
+ std::string relative_dest_dir(&dest_dir[output_dir.size()],
+ dest_dir.size() - output_dir.size());
+
+ const Target::FileList& sources = target_->sources();
+ std::vector<OutputFile> dest_files;
+ dest_files.reserve(sources.size());
+
+ // Write out rules for each file copied.
+ for (size_t i = 0; i < sources.size(); i++) {
+ const SourceFile& input_file = sources[i];
+
+ // The files should have the same name but in the dest dir.
+ base::StringPiece name_part = FindFilename(&input_file.value());
+ OutputFile dest_file(relative_dest_dir);
+ AppendStringPiece(&dest_file.value(), name_part);
+
+ dest_files.push_back(dest_file);
+
+ out_ << "build ";
+ path_output_.WriteFile(out_, dest_file);
+ out_ << ": copy ";
+ path_output_.WriteFile(out_, input_file);
+ out_ << std::endl;
+ }
+
+ // Write out the rule for the target to copy all of them.
+ out_ << std::endl << "build ";
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_));
+ out_ << ": stamp";
+ for (size_t i = 0; i < dest_files.size(); i++) {
+ out_ << " ";
+ path_output_.WriteFile(out_, dest_files[i]);
+ }
+ out_ << std::endl;
+
+ // TODO(brettw) need some kind of stamp file for depending on this, as well
+ // as order_only=prebuild.
+ // TODO(brettw) also need to write out the dependencies of this rule (maybe
+ // we're copying output files around).
+}
diff --git a/chromium/tools/gn/ninja_copy_target_writer.h b/chromium/tools/gn/ninja_copy_target_writer.h
new file mode 100644
index 00000000000..99bbaffd8b5
--- /dev/null
+++ b/chromium/tools/gn/ninja_copy_target_writer.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_COPY_TARGET_WRITER_H_
+#define TOOLS_GN_NINJA_COPY_TARGET_WRITER_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/ninja_target_writer.h"
+
+// Writes a .ninja file for a copy target type.
+class NinjaCopyTargetWriter : public NinjaTargetWriter {
+ public:
+ NinjaCopyTargetWriter(const Target* target, std::ostream& out);
+ virtual ~NinjaCopyTargetWriter();
+
+ virtual void Run() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NinjaCopyTargetWriter);
+};
+
+#endif // TOOLS_GN_NINJA_COPY_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_group_target_writer.cc b/chromium/tools/gn/ninja_group_target_writer.cc
new file mode 100644
index 00000000000..f31bf1a0ae5
--- /dev/null
+++ b/chromium/tools/gn/ninja_group_target_writer.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_group_target_writer.h"
+
+#include "base/strings/string_util.h"
+#include "tools/gn/string_utils.h"
+
+NinjaGroupTargetWriter::NinjaGroupTargetWriter(const Target* target,
+ std::ostream& out)
+ : NinjaTargetWriter(target, out) {
+}
+
+NinjaGroupTargetWriter::~NinjaGroupTargetWriter() {
+}
+
+void NinjaGroupTargetWriter::Run() {
+ // A group rule just generates a stamp file with dependencies on each of
+ // the deps in the group.
+ out_ << std::endl << "build ";
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_));
+ out_ << ": stamp";
+
+ const std::vector<const Target*>& deps = target_->deps();
+ for (size_t i = 0; i < deps.size(); i++) {
+ out_ << " ";
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(deps[i]));
+ }
+
+ const std::vector<const Target*>& datadeps = target_->datadeps();
+ for (size_t i = 0; i < datadeps.size(); i++) {
+ out_ << " ";
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(datadeps[i]));
+ }
+ out_ << std::endl;
+}
diff --git a/chromium/tools/gn/ninja_group_target_writer.h b/chromium/tools/gn/ninja_group_target_writer.h
new file mode 100644
index 00000000000..31625f8f5f4
--- /dev/null
+++ b/chromium/tools/gn/ninja_group_target_writer.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_GROUP_TARGET_WRITER_H_
+#define TOOLS_GN_NINJA_GROUP_TARGET_WRITER_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/ninja_target_writer.h"
+
+// Writes a .ninja file for a group target type.
+class NinjaGroupTargetWriter : public NinjaTargetWriter {
+ public:
+ NinjaGroupTargetWriter(const Target* target, std::ostream& out);
+ virtual ~NinjaGroupTargetWriter();
+
+ virtual void Run() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NinjaGroupTargetWriter);
+};
+
+#endif // TOOLS_GN_NINJA_GROUP_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_helper.cc b/chromium/tools/gn/ninja_helper.cc
new file mode 100644
index 00000000000..b9f15da5766
--- /dev/null
+++ b/chromium/tools/gn/ninja_helper.cc
@@ -0,0 +1,177 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_helper.h"
+
+#include "base/logging.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/string_utils.h"
+#include "tools/gn/target.h"
+
+namespace {
+
+const char kLibDirWithSlash[] = "lib/";
+const char kObjectDirNoSlash[] = "obj";
+
+} // namespace
+
+NinjaHelper::NinjaHelper(const BuildSettings* build_settings)
+ : build_settings_(build_settings) {
+ build_to_src_no_last_slash_ = build_settings->build_to_source_dir_string();
+ if (!build_to_src_no_last_slash_.empty() &&
+ build_to_src_no_last_slash_[build_to_src_no_last_slash_.size() - 1] ==
+ '/')
+ build_to_src_no_last_slash_.resize(build_to_src_no_last_slash_.size() - 1);
+
+ build_to_src_system_no_last_slash_ = build_to_src_no_last_slash_;
+ ConvertPathToSystem(&build_to_src_system_no_last_slash_);
+}
+
+NinjaHelper::~NinjaHelper() {
+}
+
+std::string NinjaHelper::GetTopleveOutputDir() const {
+ return kObjectDirNoSlash;
+}
+
+std::string NinjaHelper::GetTargetOutputDir(const Target* target) const {
+ return kObjectDirNoSlash + target->label().dir().SourceAbsoluteWithOneSlash();
+}
+
+OutputFile NinjaHelper::GetNinjaFileForTarget(const Target* target) const {
+ OutputFile ret(target->settings()->toolchain_output_subdir());
+ ret.value().append(kObjectDirNoSlash);
+ AppendStringPiece(&ret.value(),
+ target->label().dir().SourceAbsoluteWithOneSlash());
+ ret.value().append(target->label().name());
+ ret.value().append(".ninja");
+ return ret;
+}
+
+OutputFile NinjaHelper::GetNinjaFileForToolchain(
+ const Settings* settings) const {
+ OutputFile ret;
+ ret.value().append(settings->toolchain_output_subdir().value());
+ ret.value().append("toolchain.ninja");
+ return ret;
+}
+
+// In Python, GypPathToUniqueOutput does the qualification. The only case where
+// the Python version doesn't qualify the name is for target outputs, which we
+// handle in a separate function.
+OutputFile NinjaHelper::GetOutputFileForSource(
+ const Target* target,
+ const SourceFile& source,
+ SourceFileType type) const {
+ // Extract the filename and remove the extension (keep the dot).
+ base::StringPiece filename = FindFilename(&source.value());
+ std::string name(filename.data(), filename.size());
+ size_t extension_offset = FindExtensionOffset(name);
+ CHECK(extension_offset != std::string::npos);
+ name.resize(extension_offset);
+
+ // Append the new extension.
+ switch (type) {
+ case SOURCE_ASM:
+ case SOURCE_C:
+ case SOURCE_CC:
+ case SOURCE_M:
+ case SOURCE_MM:
+ name.append(target->settings()->IsWin() ? "obj" : "o");
+ break;
+
+ case SOURCE_RC:
+ name.append("res");
+ break;
+
+ case SOURCE_H:
+ case SOURCE_UNKNOWN:
+ NOTREACHED();
+ return OutputFile();
+ }
+
+ // Use the scheme <path>/<target>.<name>.<extension> so that all output
+ // names are unique to different targets.
+ OutputFile ret(kObjectDirNoSlash);
+
+ // Find the directory, assume it starts with two slashes, and trim to one.
+ base::StringPiece dir = FindDir(&source.value());
+ CHECK(dir.size() >= 2 && dir[0] == '/' && dir[1] == '/')
+ << "Source file isn't in the source repo: " << dir;
+ AppendStringPiece(&ret.value(), dir.substr(1));
+
+ ret.value().append(target->label().name());
+ ret.value().append(".");
+ ret.value().append(name);
+ return ret;
+}
+
+OutputFile NinjaHelper::GetTargetOutputFile(const Target* target) const {
+ OutputFile ret;
+
+ // This is prepended to the output file name.
+ const char* prefix;
+ if (!target->settings()->IsWin() &&
+ (target->output_type() == Target::SHARED_LIBRARY ||
+ target->output_type() == Target::STATIC_LIBRARY))
+ prefix = "lib";
+ else
+ prefix = "";
+
+ const char* extension;
+ if (target->output_type() == Target::GROUP ||
+ target->output_type() == Target::COPY_FILES ||
+ target->output_type() == Target::CUSTOM) {
+ extension = "stamp";
+ } else {
+ extension = GetExtensionForOutputType(target->output_type(),
+ target->settings()->target_os());
+ }
+
+ // Everything goes into the toolchain directory (which will be empty for the
+ // default toolchain, and will end in a slash otherwise).
+ ret.value().append(target->settings()->toolchain_output_subdir().value());
+
+ // Binaries and loadable libraries go into the toolchain root.
+ if (target->output_type() == Target::EXECUTABLE ||
+ (target->settings()->IsMac() &&
+ (target->output_type() == Target::SHARED_LIBRARY ||
+ target->output_type() == Target::STATIC_LIBRARY)) ||
+ (target->settings()->IsWin() &&
+ target->output_type() == Target::SHARED_LIBRARY)) {
+ // Generate a name like "<toolchain>/<prefix><name>.<extension>".
+ ret.value().append(prefix);
+ ret.value().append(target->label().name());
+ if (extension[0]) {
+ ret.value().push_back('.');
+ ret.value().append(extension);
+ }
+ return ret;
+ }
+
+ // Libraries go into the library subdirectory like
+ // "<toolchain>/lib/<prefix><name>.<extension>".
+ if (target->output_type() == Target::SHARED_LIBRARY) {
+ ret.value().append(kLibDirWithSlash);
+ ret.value().append(prefix);
+ ret.value().append(target->label().name());
+ if (extension[0]) {
+ ret.value().push_back('.');
+ ret.value().append(extension);
+ }
+ return ret;
+ }
+
+ // Everything else goes next to the target's .ninja file like
+ // "<toolchain>/obj/<path>/<name>.<extension>".
+ ret.value().append(kObjectDirNoSlash);
+ AppendStringPiece(&ret.value(),
+ target->label().dir().SourceAbsoluteWithOneSlash());
+ ret.value().append(target->label().name());
+ if (extension[0]) {
+ ret.value().push_back('.');
+ ret.value().append(extension);
+ }
+ return ret;
+}
diff --git a/chromium/tools/gn/ninja_helper.h b/chromium/tools/gn/ninja_helper.h
new file mode 100644
index 00000000000..5bea29ed214
--- /dev/null
+++ b/chromium/tools/gn/ninja_helper.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_HELPER_H_
+#define TOOLS_GN_NINJA_HELPER_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/output_file.h"
+
+class BuildSettings;
+class SourceDir;
+class SourceFile;
+class Target;
+
+// NinjaHelper -----------------------------------------------------------------
+
+class NinjaHelper {
+ public:
+ NinjaHelper(const BuildSettings* build_settings);
+ ~NinjaHelper();
+
+ // Ends in a slash.
+ std::string GetTopleveOutputDir() const;
+
+ // Ends in a slash.
+ std::string GetTargetOutputDir(const Target* target) const;
+
+ // Example: "base/base.ninja". The string version will not be escaped, and
+ // will always have slashes for path separators.
+ OutputFile GetNinjaFileForTarget(const Target* target) const;
+
+ // Returns the name of the root .ninja file for the given toolchain.
+ OutputFile GetNinjaFileForToolchain(const Settings* settings) const;
+
+ // Given a source file relative to the source root, returns the output
+ // filename.
+ OutputFile GetOutputFileForSource(const Target* target,
+ const SourceFile& source,
+ SourceFileType type) const;
+
+ // Returns the filename produced by the given output.
+ //
+ // Some targets make multiple files (like a .dll and an import library). This
+ // function returns the name of the file other targets should depend on and
+ // link to (so in this example, the import library).
+ OutputFile GetTargetOutputFile(const Target* target) const;
+
+ // Returns the relative directory in either slashes or the system separator
+ // from the ninja directory (e.g. "out/Debug") to the source root (e.g.
+ // "../.."). It has no terminating slash.
+ const std::string& build_to_src_no_last_slash() const {
+ return build_to_src_no_last_slash_;
+ }
+ const std::string& build_to_src_system_no_last_slash() const {
+ return build_to_src_system_no_last_slash_;
+ }
+
+ private:
+ const BuildSettings* build_settings_;
+
+ std::string build_to_src_no_last_slash_;
+ std::string build_to_src_system_no_last_slash_;
+
+ DISALLOW_COPY_AND_ASSIGN(NinjaHelper);
+};
+
+#endif // TOOLS_GN_NINJA_HELPER_H_
diff --git a/chromium/tools/gn/ninja_helper_unittest.cc b/chromium/tools/gn/ninja_helper_unittest.cc
new file mode 100644
index 00000000000..4aec0325bc8
--- /dev/null
+++ b/chromium/tools/gn/ninja_helper_unittest.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/ninja_helper.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/target.h"
+#include "tools/gn/toolchain.h"
+
+namespace {
+
+class HelperSetterUpper {
+ public:
+ HelperSetterUpper()
+ : build_settings(),
+ toolchain(Label(SourceDir("//"), "tc", SourceDir(), std::string())),
+ settings(&build_settings, &toolchain, std::string()),
+ target(&settings,
+ Label(SourceDir("//tools/gn/"), "name",
+ SourceDir(), std::string())) {
+ settings.set_target_os(Settings::WIN);
+
+ // Output going to "out/Debug".
+ build_settings.SetBuildDir(SourceDir("/out/Debug/"));
+
+ // Our source target is in "tools/gn".
+ target.set_output_type(Target::EXECUTABLE);
+ }
+
+ BuildSettings build_settings;
+ Toolchain toolchain;
+ Settings settings;
+ Target target;
+};
+
+} // namespace
+
+TEST(NinjaHelper, GetNinjaFileForTarget) {
+ HelperSetterUpper setup;
+ NinjaHelper helper(&setup.build_settings);
+
+ // Default toolchain.
+ EXPECT_EQ(OutputFile("obj/tools/gn/name.ninja").value(),
+ helper.GetNinjaFileForTarget(&setup.target).value());
+}
+
+TEST(NinjaHelper, GetOutputFileForSource) {
+ HelperSetterUpper setup;
+ NinjaHelper helper(&setup.build_settings);
+
+ // On Windows, expect ".obj"
+ EXPECT_EQ(OutputFile("obj/tools/gn/name.foo.obj").value(),
+ helper.GetOutputFileForSource(&setup.target,
+ SourceFile("//tools/gn/foo.cc"),
+ SOURCE_CC).value());
+}
+
+TEST(NinjaHelper, GetTargetOutputFile) {
+ HelperSetterUpper setup;
+ NinjaHelper helper(&setup.build_settings);
+ EXPECT_EQ(OutputFile("name.exe"),
+ helper.GetTargetOutputFile(&setup.target));
+
+ // Static library on Windows goes alongside the object files.
+ setup.target.set_output_type(Target::STATIC_LIBRARY);
+ EXPECT_EQ(OutputFile("obj/tools/gn/name.lib"),
+ helper.GetTargetOutputFile(&setup.target));
+
+ // TODO(brettw) test output to library and other OS types.
+}
diff --git a/chromium/tools/gn/ninja_script_target_writer.cc b/chromium/tools/gn/ninja_script_target_writer.cc
new file mode 100644
index 00000000000..44e13c67794
--- /dev/null
+++ b/chromium/tools/gn/ninja_script_target_writer.cc
@@ -0,0 +1,207 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_script_target_writer.h"
+
+#include "base/strings/string_util.h"
+#include "tools/gn/err.h"
+#include "tools/gn/file_template.h"
+#include "tools/gn/string_utils.h"
+#include "tools/gn/target.h"
+
+NinjaScriptTargetWriter::NinjaScriptTargetWriter(const Target* target,
+ std::ostream& out)
+ : NinjaTargetWriter(target, out) {
+}
+
+NinjaScriptTargetWriter::~NinjaScriptTargetWriter() {
+}
+
+void NinjaScriptTargetWriter::Run() {
+ WriteEnvironment();
+
+ // Run the script from the dir of the BUILD file. This has no trailing
+ // slash.
+ const SourceDir& script_cd = target_->label().dir();
+ std::string script_cd_to_root = InvertDir(script_cd);
+ if (script_cd_to_root.empty()) {
+ script_cd_to_root = ".";
+ } else {
+ // Remove trailing slash
+ DCHECK(script_cd_to_root[script_cd_to_root.size() - 1] == '/');
+ script_cd_to_root.resize(script_cd_to_root.size() - 1);
+ }
+ std::string script_relative_to_cd =
+ script_cd_to_root + target_->script_values().script().value();
+
+ std::string custom_rule_name = WriteRuleDefinition(script_relative_to_cd);
+
+ // Precompute the common dependencies for each step. This includes the
+ // script itself (changing the script should force a rebuild) and any data
+ // files.
+ //
+ // TODO(brettw) this needs to be re-thought. "data" is supposed to be runtime
+ // data (i.e. for tests and such) rather than compile-time dependencies for
+ // each target. If we really need this, we need to have a different way to
+ // express it.
+ //
+ // One idea: add an "inputs" variable to specify this kind of thing. We
+ // should probably make it an error to specify data but no inputs for a
+ // script as a way to catch people doing the wrong way.
+ std::ostringstream common_deps_stream;
+ path_output_.WriteFile(common_deps_stream, target_->script_values().script());
+ const Target::FileList& datas = target_->data();
+ for (size_t i = 0; i < datas.size(); i++) {
+ common_deps_stream << " ";
+ path_output_.WriteFile(common_deps_stream, datas[i]);
+ }
+ const std::string& common_deps = common_deps_stream.str();
+
+ // Collects all output files for writing below.
+ std::vector<OutputFile> output_files;
+
+ if (!has_sources()) {
+ // Write separate rules for each input source file.
+ WriteSourceRules(custom_rule_name, common_deps, script_cd,
+ script_cd_to_root, &output_files);
+ } else {
+ // No sources, write a rule that invokes the script once with the
+ // outputs as outputs, and the data as inputs.
+ out_ << "build";
+ const Target::FileList& outputs = target_->script_values().outputs();
+ for (size_t i = 0; i < outputs.size(); i++) {
+ OutputFile output_path(
+ RemovePrefix(outputs[i].value(),
+ settings_->build_settings()->build_dir().value()));
+ output_files.push_back(output_path);
+ out_ << " ";
+ path_output_.WriteFile(out_, output_path);
+ }
+ out_ << ": " << custom_rule_name << " " << common_deps << std::endl;
+ }
+ out_ << std::endl;
+
+ WriteStamp(output_files);
+}
+
+std::string NinjaScriptTargetWriter::WriteRuleDefinition(
+ const std::string& script_relative_to_cd) {
+ // Make a unique name for this rule.
+ std::string target_label = target_->label().GetUserVisibleName(true);
+ std::string custom_rule_name(target_label);
+ ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
+ custom_rule_name.append("_rule");
+
+ // Use a unique name for the response file when there are multiple build
+ // steps so that they don't stomp on each other. When there are no sources,
+ // there will be only one invocation so we can use a simple name.
+ std::string rspfile = custom_rule_name;
+ if (has_sources())
+ rspfile += ".$unique_name";
+ rspfile += ".rsp";
+
+ out_ << "rule " << custom_rule_name << std::endl;
+ out_ << " command = $pythonpath gyp-win-tool action-wrapper $arch "
+ << rspfile << " ";
+ path_output_.WriteDir(out_, target_->label().dir(),
+ PathOutput::DIR_NO_LAST_SLASH);
+ out_ << std::endl;
+ out_ << " description = CUSTOM " << target_label << std::endl;
+ out_ << " restat = 1" << std::endl;
+ out_ << " rspfile = " << rspfile << std::endl;
+
+ // The build command goes in the rsp file.
+ out_ << " rspfile_content = $pythonpath " << script_relative_to_cd;
+ for (size_t i = 0; i < target_->script_values().args().size(); i++) {
+ const std::string& arg = target_->script_values().args()[i];
+ out_ << " ";
+ WriteArg(arg);
+ }
+ out_ << std::endl;
+ return custom_rule_name;
+}
+
+void NinjaScriptTargetWriter::WriteArg(const std::string& arg) {
+ // This can be optimized if it's called a lot.
+ EscapeOptions options;
+ options.mode = ESCAPE_NINJA;
+ std::string output_str = EscapeString(arg, options);
+
+ // Do this substitution after escaping our our $ will be escaped (which we
+ // don't want).
+ ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSource,
+ "${source}");
+ ReplaceSubstringsAfterOffset(&output_str, 0, FileTemplate::kSourceNamePart,
+ "${source_name_part}");
+ out_ << output_str;
+}
+
+void NinjaScriptTargetWriter::WriteSourceRules(
+ const std::string& custom_rule_name,
+ const std::string& common_deps,
+ const SourceDir& script_cd,
+ const std::string& script_cd_to_root,
+ std::vector<OutputFile>* output_files) {
+ // Construct the template for generating the output files from each source.
+ const Target::FileList& outputs = target_->script_values().outputs();
+ std::vector<std::string> output_template_args;
+ for (size_t i = 0; i < outputs.size(); i++) {
+ // All outputs should be in the output dir.
+ output_template_args.push_back(
+ RemovePrefix(outputs[i].value(),
+ settings_->build_settings()->build_dir().value()));
+ }
+ FileTemplate output_template(output_template_args);
+
+ // Prevent re-allocating each time by initializing outside the loop.
+ std::vector<std::string> output_template_result;
+
+ // Path output formatter for wrigin source paths passed to the script.
+ PathOutput script_source_path_output(script_cd, ESCAPE_SHELL, true);
+
+ const Target::FileList& sources = target_->sources();
+ for (size_t i = 0; i < sources.size(); i++) {
+ // Write outputs for this source file computed by the template.
+ out_ << "build";
+ output_template.ApplyString(sources[i].value(), &output_template_result);
+ for (size_t out_i = 0; out_i < output_template_result.size(); out_i++) {
+ OutputFile output_path(output_template_result[out_i]);
+ output_files->push_back(output_path);
+ out_ << " ";
+ path_output_.WriteFile(out_, output_path);
+ }
+
+ out_ << ": " << custom_rule_name
+ << " " << common_deps
+ << " ";
+ path_output_.WriteFile(out_, sources[i]);
+ out_ << std::endl;
+
+ out_ << " unique_name = " << i << std::endl;
+
+ // The source file here should be relative to the script directory since
+ // this is the variable passed to the script. Here we slightly abuse the
+ // OutputFile object by putting a non-output-relative path in it to signal
+ // that the PathWriter should not prepend directories.
+ out_ << " source = ";
+ script_source_path_output.WriteFile(out_, sources[i]);
+ out_ << std::endl;
+
+ out_ << " source_name_part = "
+ << FindFilenameNoExtension(&sources[i].value()).as_string()
+ << std::endl;
+ }
+}
+
+void NinjaScriptTargetWriter::WriteStamp(
+ const std::vector<OutputFile>& output_files) {
+ out_ << "build ";
+ path_output_.WriteFile(out_, helper_.GetTargetOutputFile(target_));
+ out_ << ": stamp";
+ for (size_t i = 0; i < output_files.size(); i++) {
+ out_ << " ";
+ path_output_.WriteFile(out_, output_files[i]);
+ }
+ out_ << std::endl;
+}
diff --git a/chromium/tools/gn/ninja_script_target_writer.h b/chromium/tools/gn/ninja_script_target_writer.h
new file mode 100644
index 00000000000..27ba45d160c
--- /dev/null
+++ b/chromium/tools/gn/ninja_script_target_writer.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_SCRIPT_TARGET_WRITER_H_
+#define TOOLS_GN_NINJA_SCRIPT_TARGET_WRITER_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/ninja_target_writer.h"
+
+// Writes a .ninja file for a custom script target type.
+class NinjaScriptTargetWriter : public NinjaTargetWriter {
+ public:
+ NinjaScriptTargetWriter(const Target* target, std::ostream& out);
+ virtual ~NinjaScriptTargetWriter();
+
+ virtual void Run() OVERRIDE;
+
+ private:
+ bool has_sources() const { return !target_->sources().empty(); }
+
+ // Writes the Ninja rule for invoking the script.
+ //
+ // Returns the name of the custom rule generated. This will be based on the
+ // target name, and will include the string "$unique_name" if there are
+ // multiple inputs.
+ std::string WriteRuleDefinition(const std::string& script_relative_to_cd);
+
+ // Writes the rules for compiling each source, writing all output files
+ // to the given vector.
+ //
+ // common_deps is a precomputed string of all ninja files that are common
+ // to each build step. This is added to each one.
+ void WriteSourceRules(const std::string& custom_rule_name,
+ const std::string& common_deps,
+ const SourceDir& script_cd,
+ const std::string& script_cd_to_root,
+ std::vector<OutputFile>* output_files);
+
+ void WriteArg(const std::string& arg);
+
+ // Writes the .stamp rule that names this target and collects all invocations
+ // of the script into one thing that other targets can depend on.
+ void WriteStamp(const std::vector<OutputFile>& output_files);
+
+ DISALLOW_COPY_AND_ASSIGN(NinjaScriptTargetWriter);
+};
+
+#endif // TOOLS_GN_NINJA_SCRIPT_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_target_writer.cc b/chromium/tools/gn/ninja_target_writer.cc
new file mode 100644
index 00000000000..16a2f7d2268
--- /dev/null
+++ b/chromium/tools/gn/ninja_target_writer.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_target_writer.h"
+
+#include <fstream>
+#include <sstream>
+
+#include "base/file_util.h"
+#include "tools/gn/err.h"
+#include "tools/gn/ninja_binary_target_writer.h"
+#include "tools/gn/ninja_copy_target_writer.h"
+#include "tools/gn/ninja_group_target_writer.h"
+#include "tools/gn/ninja_script_target_writer.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/target.h"
+
+NinjaTargetWriter::NinjaTargetWriter(const Target* target, std::ostream& out)
+ : settings_(target->settings()),
+ target_(target),
+ out_(out),
+ path_output_(settings_->build_settings()->build_dir(),
+ ESCAPE_NINJA, true),
+ helper_(settings_->build_settings()) {
+}
+
+NinjaTargetWriter::~NinjaTargetWriter() {
+}
+
+// static
+void NinjaTargetWriter::RunAndWriteFile(const Target* target) {
+ const Settings* settings = target->settings();
+ NinjaHelper helper(settings->build_settings());
+
+ base::FilePath ninja_file(settings->build_settings()->GetFullPath(
+ helper.GetNinjaFileForTarget(target).GetSourceFile(
+ settings->build_settings())));
+
+ if (g_scheduler->verbose_logging())
+ g_scheduler->Log("Writing", FilePathToUTF8(ninja_file));
+
+ file_util::CreateDirectory(ninja_file.DirName());
+
+ // It's rediculously faster to write to a string and then write that to
+ // disk in one operation than to use an fstream here.
+ std::stringstream file;
+ if (file.fail()) {
+ g_scheduler->FailWithError(
+ Err(Location(), "Error writing ninja file.",
+ "Unable to open \"" + FilePathToUTF8(ninja_file) + "\"\n"
+ "for writing."));
+ return;
+ }
+
+ // Call out to the correct sub-type of writer.
+ if (target->output_type() == Target::COPY_FILES) {
+ NinjaCopyTargetWriter writer(target, file);
+ writer.Run();
+ } else if (target->output_type() == Target::CUSTOM) {
+ NinjaScriptTargetWriter writer(target, file);
+ writer.Run();
+ } else if (target->output_type() == Target::GROUP) {
+ NinjaGroupTargetWriter writer(target, file);
+ writer.Run();
+ } else if (target->output_type() == Target::EXECUTABLE ||
+ target->output_type() == Target::STATIC_LIBRARY ||
+ target->output_type() == Target::SHARED_LIBRARY) {
+ NinjaBinaryTargetWriter writer(target, file);
+ writer.Run();
+ } else {
+ CHECK(0);
+ }
+
+ std::string contents = file.str();
+ file_util::WriteFile(ninja_file, contents.c_str(), contents.size());
+}
+
+void NinjaTargetWriter::WriteEnvironment() {
+ // TODO(brettw) have a better way to do the environment setup on Windows.
+ if (target_->settings()->IsWin())
+ out_ << "arch = environment.x86\n";
+}
diff --git a/chromium/tools/gn/ninja_target_writer.h b/chromium/tools/gn/ninja_target_writer.h
new file mode 100644
index 00000000000..087a8b82117
--- /dev/null
+++ b/chromium/tools/gn/ninja_target_writer.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_TARGET_WRITER_H_
+#define TOOLS_GN_NINJA_TARGET_WRITER_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/ninja_helper.h"
+#include "tools/gn/path_output.h"
+#include "tools/gn/settings.h"
+
+class Target;
+
+// Generates one target's ".ninja" file. The toplevel "build.ninja" file is
+// generated by the NinjaBuildGenerator.
+class NinjaTargetWriter {
+ public:
+ NinjaTargetWriter(const Target* target, std::ostream& out);
+ virtual ~NinjaTargetWriter();
+
+ static void RunAndWriteFile(const Target* target);
+
+ virtual void Run() = 0;
+
+ protected:
+ void WriteEnvironment();
+
+ const Settings* settings_; // Non-owning.
+ const Target* target_; // Non-owning.
+ std::ostream& out_;
+ PathOutput path_output_;
+
+ NinjaHelper helper_;
+
+ private:
+ void WriteCopyRules();
+
+ DISALLOW_COPY_AND_ASSIGN(NinjaTargetWriter);
+};
+
+#endif // TOOLS_GN_NINJA_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_toolchain_writer.cc b/chromium/tools/gn/ninja_toolchain_writer.cc
new file mode 100644
index 00000000000..8dd2175c469
--- /dev/null
+++ b/chromium/tools/gn/ninja_toolchain_writer.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_toolchain_writer.h"
+
+#include <fstream>
+
+#include "base/file_util.h"
+#include "base/strings/stringize_macros.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/target.h"
+#include "tools/gn/toolchain.h"
+
+NinjaToolchainWriter::NinjaToolchainWriter(
+ const Settings* settings,
+ const std::vector<const Target*>& targets,
+ std::ostream& out)
+ : settings_(settings),
+ targets_(targets),
+ out_(out),
+ path_output_(settings_->build_settings()->build_dir(),
+ ESCAPE_NINJA, true),
+ helper_(settings->build_settings()) {
+}
+
+NinjaToolchainWriter::~NinjaToolchainWriter() {
+}
+
+void NinjaToolchainWriter::Run() {
+ WriteRules();
+ WriteSubninjas();
+}
+
+// static
+bool NinjaToolchainWriter::RunAndWriteFile(
+ const Settings* settings,
+ const std::vector<const Target*>& targets) {
+ NinjaHelper helper(settings->build_settings());
+ base::FilePath ninja_file(settings->build_settings()->GetFullPath(
+ helper.GetNinjaFileForToolchain(settings).GetSourceFile(
+ settings->build_settings())));
+ file_util::CreateDirectory(ninja_file.DirName());
+
+ std::ofstream file;
+ file.open(FilePathToUTF8(ninja_file).c_str(),
+ std::ios_base::out | std::ios_base::binary);
+ if (file.fail())
+ return false;
+
+ NinjaToolchainWriter gen(settings, targets, file);
+ gen.Run();
+ return true;
+}
+
+void NinjaToolchainWriter::WriteRules() {
+ const Toolchain* tc = settings_->toolchain();
+ std::string indent(" ");
+
+ for (int i = Toolchain::TYPE_NONE + 1; i < Toolchain::TYPE_NUMTYPES; i++) {
+ Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(i);
+ const Toolchain::Tool& tool = tc->GetTool(tool_type);
+ if (tool.empty())
+ continue;
+
+ out_ << "rule " << Toolchain::ToolTypeToName(tool_type) << std::endl;
+
+ #define WRITE_ARG(name) \
+ if (!tool.name.empty()) \
+ out_ << indent << " " STRINGIZE(name) " = " << tool.name << std::endl;
+ WRITE_ARG(command);
+ WRITE_ARG(depfile);
+ WRITE_ARG(deps);
+ WRITE_ARG(description);
+ WRITE_ARG(pool);
+ WRITE_ARG(restat);
+ WRITE_ARG(rspfile);
+ WRITE_ARG(rspfile_content);
+ #undef WRITE_ARG
+ }
+ out_ << std::endl;
+}
+
+void NinjaToolchainWriter::WriteSubninjas() {
+ for (size_t i = 0; i < targets_.size(); i++) {
+ out_ << "subninja ";
+ path_output_.WriteFile(out_, helper_.GetNinjaFileForTarget(targets_[i]));
+ out_ << std::endl;
+ }
+ out_ << std::endl;
+}
diff --git a/chromium/tools/gn/ninja_toolchain_writer.h b/chromium/tools/gn/ninja_toolchain_writer.h
new file mode 100644
index 00000000000..71759efa80b
--- /dev/null
+++ b/chromium/tools/gn/ninja_toolchain_writer.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_
+#define TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_
+
+#include <iosfwd>
+#include <vector>
+
+#include "tools/gn/ninja_helper.h"
+#include "tools/gn/path_output.h"
+
+class BuildSettings;
+class Settings;
+class Target;
+
+class NinjaToolchainWriter {
+ public:
+ // Takes the settings for the toolchain, as well as the list of all targets
+ // assicoated with the toolchain.
+ static bool RunAndWriteFile(const Settings* settings,
+ const std::vector<const Target*>& targets);
+
+ private:
+ NinjaToolchainWriter(const Settings* settings,
+ const std::vector<const Target*>& targets,
+ std::ostream& out);
+ ~NinjaToolchainWriter();
+
+ void Run();
+
+ void WriteRules();
+ void WriteSubninjas();
+
+ const Settings* settings_;
+ std::vector<const Target*> targets_;
+ std::ostream& out_;
+ PathOutput path_output_;
+
+ NinjaHelper helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(NinjaToolchainWriter);
+};
+
+#endif // TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_
diff --git a/chromium/tools/gn/ninja_writer.cc b/chromium/tools/gn/ninja_writer.cc
new file mode 100644
index 00000000000..9eec8654cf8
--- /dev/null
+++ b/chromium/tools/gn/ninja_writer.cc
@@ -0,0 +1,78 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/ninja_writer.h"
+
+#include "tools/gn/location.h"
+#include "tools/gn/ninja_build_writer.h"
+#include "tools/gn/ninja_toolchain_writer.h"
+
+
+NinjaWriter::NinjaWriter(const BuildSettings* build_settings)
+ : build_settings_(build_settings) {
+}
+
+NinjaWriter::~NinjaWriter() {
+}
+
+// static
+bool NinjaWriter::RunAndWriteFiles(const BuildSettings* build_settings) {
+ NinjaWriter writer(build_settings);
+ return writer.WriteRootBuildfiles();
+}
+
+bool NinjaWriter::WriteRootBuildfiles() {
+ // Categorize all targets by toolchain.
+ typedef std::map<Label, std::vector<const Target*> > CategorizedMap;
+ CategorizedMap categorized;
+
+ std::vector<const Target*> all_targets;
+ build_settings_->target_manager().GetAllTargets(&all_targets);
+ if (all_targets.empty()) {
+ Err(Location(), "No targets.",
+ "I could not find any targets to write, so I'm doing nothing.")
+ .PrintToStdout();
+ return false;
+ }
+ for (size_t i = 0; i < all_targets.size(); i++) {
+ categorized[all_targets[i]->label().GetToolchainLabel()].push_back(
+ all_targets[i]);
+ }
+
+ Label default_label =
+ build_settings_->toolchain_manager().GetDefaultToolchainUnlocked();
+
+ // Write out the toolchain buildfiles, and also accumulate the set of
+ // all settings and find the list of targets in the default toolchain.
+ std::vector<const Settings*> all_settings;
+ const std::vector<const Target*>* default_targets = NULL;
+ for (CategorizedMap::const_iterator i = categorized.begin();
+ i != categorized.end(); ++i) {
+ const Settings* settings;
+ {
+ base::AutoLock lock(build_settings_->item_tree().lock());
+ Err ignored;
+ settings =
+ build_settings_->toolchain_manager().GetSettingsForToolchainLocked(
+ LocationRange(), i->first, &ignored);
+ }
+ if (i->first == default_label)
+ default_targets = &i->second;
+ all_settings.push_back(settings);
+ if (!NinjaToolchainWriter::RunAndWriteFile(settings, i->second)) {
+ Err(Location(),
+ "Couldn't open toolchain buildfile(s) for writing").PrintToStdout();
+ return false;
+ }
+ }
+
+ // Write the root buildfile.
+ if (!NinjaBuildWriter::RunAndWriteFile(build_settings_, all_settings,
+ *default_targets)) {
+ Err(Location(),
+ "Couldn't open toolchain buildfile(s) for writing").PrintToStdout();
+ return false;
+ }
+ return true;
+}
diff --git a/chromium/tools/gn/ninja_writer.h b/chromium/tools/gn/ninja_writer.h
new file mode 100644
index 00000000000..a4050a83de1
--- /dev/null
+++ b/chromium/tools/gn/ninja_writer.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_NINJA_WRITER_H_
+#define TOOLS_GN_NINJA_WRITER_H_
+
+#include "base/basictypes.h"
+
+class BuildSettings;
+
+class NinjaWriter {
+ public:
+ // On failure will print an error and will return false.
+ static bool RunAndWriteFiles(const BuildSettings* build_settings);
+
+ private:
+ NinjaWriter(const BuildSettings* build_settings);
+ ~NinjaWriter();
+
+ bool WriteRootBuildfiles();
+
+ const BuildSettings* build_settings_;
+
+ DISALLOW_COPY_AND_ASSIGN(NinjaWriter);
+};
+
+#endif // TOOLS_GN_NINJA_WRITER_H_
diff --git a/chromium/tools/gn/operators.cc b/chromium/tools/gn/operators.cc
new file mode 100644
index 00000000000..afded9f887e
--- /dev/null
+++ b/chromium/tools/gn/operators.cc
@@ -0,0 +1,573 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/operators.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "tools/gn/err.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/token.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+const char kSourcesName[] = "sources";
+
+// Applies the sources assignment filter from the given scope to each element
+// of source (can be a list or a string), appending it to dest if it doesn't
+// match.
+void AppendFilteredSourcesToValue(const Scope* scope,
+ const Value& source,
+ Value* dest) {
+ const PatternList* filter = scope->GetSourcesAssignmentFilter();
+
+ const std::vector<Value>& source_list = source.list_value();
+
+ if (source.type() == Value::STRING) {
+ if (!filter || filter->is_empty() ||
+ !filter->MatchesValue(source))
+ dest->list_value().push_back(source);
+ return;
+ }
+
+ // Otherwise source is a list.
+ DCHECK(source.type() == Value::LIST);
+ if (!filter || filter->is_empty()) {
+ // No filter, append everything.
+ for (size_t i = 0; i < source_list.size(); i++)
+ dest->list_value().push_back(source_list[i]);
+ return;
+ }
+
+ // Note: don't reserve() the dest vector here since that actually hurts
+ // the allocation pattern when the build script is doing multiple small
+ // additions.
+ for (size_t i = 0; i < source_list.size(); i++) {
+ if (!filter->MatchesValue(source_list[i]))
+ dest->list_value().push_back(source_list[i]);
+ }
+}
+
+void RemoveMatchesFromList(const BinaryOpNode* op_node,
+ Value* list,
+ const Value& to_remove,
+ Err* err) {
+ std::vector<Value>& v = list->list_value();
+ switch (to_remove.type()) {
+ case Value::INTEGER: // Filter out the individual int/string.
+ case Value::STRING: {
+ bool found_match = false;
+ for (size_t i = 0; i < v.size(); /* nothing */) {
+ if (v[i] == to_remove) {
+ found_match = true;
+ v.erase(v.begin() + i);
+ } else {
+ i++;
+ }
+ }
+ if (!found_match) {
+ *err = Err(to_remove.origin()->GetRange(), "Item not found",
+ "You were trying to remove \"" + to_remove.ToString() +
+ "\"\nfrom the list but it wasn't there.");
+ }
+ break;
+ }
+
+ case Value::LIST: // Filter out each individual thing.
+ for (size_t i = 0; i < to_remove.list_value().size(); i++) {
+ // TODO(brettw) if the nested item is a list, we may want to search
+ // for the literal list rather than remote the items in it.
+ RemoveMatchesFromList(op_node, list, to_remove.list_value()[i], err);
+ if (err->has_error())
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+// Assignment -----------------------------------------------------------------
+
+Value ExecuteEquals(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Token& left,
+ const Value& right,
+ Err* err) {
+ const Value* old_value = scope->GetValue(left.value(), false);
+ if (old_value) {
+ if (scope->IsSetButUnused(left.value())) {
+ // Throw an error for re-assigning without using the value first. The
+ // exception is that you can overwrite an empty list with another list
+ // since this is the way to get around the "can't overwrite a nonempty
+ // list with another nonempty list" restriction.
+ if (old_value->type() != Value::LIST ||
+ !old_value->list_value().empty()) {
+ *err = Err(op_node->left()->GetRange(), "Overwriting unused variable.",
+ "This overwrites a previous assignment to \"" +
+ left.value().as_string() + "\" that had no effect.");
+ err->AppendSubErr(Err(*scope->GetValue(left.value()),
+ "Previously set here.",
+ "Maybe you wanted \"+=\" to append instead?"));
+ return Value();
+ }
+ } else {
+ // Throw an error when overwriting a nonempty list with another nonempty
+ // list item. This is to detect the case where you write
+ // defines = ["FOO"]
+ // and you overwrote inherited ones, when instead you mean to append:
+ // defines += ["FOO"]
+ if (old_value->type() == Value::LIST &&
+ !old_value->list_value().empty() &&
+ right.type() == Value::LIST &&
+ !right.list_value().empty()) {
+ *err = Err(op_node->left()->GetRange(), "Replacing nonempty list.",
+ std::string("This overwrites a previously-defined nonempty list ") +
+ "(length " + base::IntToString(old_value->list_value().size()) +
+ ").");
+ err->AppendSubErr(Err(*old_value, "for previous definition",
+ "with another one (length " +
+ base::IntToString(right.list_value().size()) + "). Did you mean " +
+ "\"+=\" to append instead? If you\nreally want to do this, do\n " +
+ left.value().as_string() + " = []\nbefore reassigning."));
+ return Value();
+ }
+ }
+ }
+ if (err->has_error())
+ return Value();
+
+ if (right.type() == Value::LIST && left.value() == kSourcesName) {
+ // Assigning to sources, filter the list. Here we do the filtering and
+ // copying in one step to save an extra list copy (the lists may be
+ // long).
+ Value* set_value = scope->SetValue(left.value(),
+ Value(op_node, Value::LIST), op_node);
+ set_value->list_value().reserve(right.list_value().size());
+ AppendFilteredSourcesToValue(scope, right, set_value);
+ } else {
+ // Normal value set, just copy it.
+ scope->SetValue(left.value(), right, op_node->right());
+ }
+ return Value();
+}
+
+// allow_type_conversion indicates if we're allowed to change the type of the
+// left value. This is set to true when doing +, and false when doing +=.
+void ValuePlusEquals(const Scope* scope,
+ const BinaryOpNode* op_node,
+ const Token& left_token,
+ Value* left,
+ const Value& right,
+ bool allow_type_conversion,
+ Err* err) {
+ switch (left->type()) {
+ // Left-hand-side int.
+ case Value::INTEGER:
+ switch (right.type()) {
+ case Value::INTEGER: // int + int -> addition.
+ left->int_value() += right.int_value();
+ return;
+
+ case Value::STRING: // int + string -> string concat.
+ if (allow_type_conversion) {
+ *left = Value(op_node,
+ base::Int64ToString(left->int_value()) + right.string_value());
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ // Left-hand-side string.
+ case Value::STRING:
+ switch (right.type()) {
+ case Value::INTEGER: // string + int -> string concat.
+ left->string_value().append(base::Int64ToString(right.int_value()));
+ return;
+
+ case Value::STRING: // string + string -> string contat.
+ left->string_value().append(right.string_value());
+ return;
+
+ default:
+ break;
+ }
+ break;
+
+ // Left-hand-side list.
+ case Value::LIST:
+ switch (right.type()) {
+ case Value::INTEGER: // list + integer -> list append.
+ case Value::STRING: // list + string -> list append.
+ if (left_token.value() == kSourcesName)
+ AppendFilteredSourcesToValue(scope, right, left);
+ else
+ left->list_value().push_back(right);
+ return;
+
+ case Value::LIST: // list + list -> list concat.
+ if (left_token.value() == kSourcesName) {
+ // Filter additions through the assignment filter.
+ AppendFilteredSourcesToValue(scope, right, left);
+ } else {
+ // Normal list concat.
+ for (size_t i = 0; i < right.list_value().size(); i++)
+ left->list_value().push_back(right.list_value()[i]);
+ }
+ return;
+
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ *err = Err(op_node->op(), "Incompatible types to add.",
+ std::string("I see a ") + Value::DescribeType(left->type()) + " and a " +
+ Value::DescribeType(right.type()) + ".");
+}
+
+Value ExecutePlusEquals(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Token& left,
+ const Value& right,
+ Err* err) {
+ // We modify in-place rather than doing read-modify-write to avoid
+ // copying large lists.
+ Value* left_value =
+ scope->GetValueForcedToCurrentScope(left.value(), op_node);
+ if (!left_value) {
+ *err = Err(left, "Undefined variable for +=.",
+ "I don't have something with this name in scope now.");
+ return Value();
+ }
+ ValuePlusEquals(scope, op_node, left, left_value, right, false, err);
+ left_value->set_origin(op_node);
+ scope->MarkUnused(left.value());
+ return Value();
+}
+
+void ValueMinusEquals(const BinaryOpNode* op_node,
+ Value* left,
+ const Value& right,
+ bool allow_type_conversion,
+ Err* err) {
+ switch (left->type()) {
+ // Left-hand-side int.
+ case Value::INTEGER:
+ switch (right.type()) {
+ case Value::INTEGER: // int - int -> subtraction.
+ left->int_value() -= right.int_value();
+ return;
+
+ default:
+ break;
+ }
+ break;
+
+ // Left-hand-side string.
+ case Value::STRING:
+ break; // All are errors.
+
+ // Left-hand-side list.
+ case Value::LIST:
+ RemoveMatchesFromList(op_node, left, right, err);
+ return;
+
+ default:
+ break;
+ }
+
+ *err = Err(op_node->op(), "Incompatible types to add.",
+ std::string("I see a ") + Value::DescribeType(left->type()) + " and a " +
+ Value::DescribeType(right.type()) + ".");
+}
+
+Value ExecuteMinusEquals(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Token& left,
+ const Value& right,
+ Err* err) {
+ Value* left_value =
+ scope->GetValueForcedToCurrentScope(left.value(), op_node);
+ if (!left_value) {
+ *err = Err(left, "Undefined variable for -=.",
+ "I don't have something with this name in scope now.");
+ return Value();
+ }
+ ValueMinusEquals(op_node, left_value, right, false, err);
+ left_value->set_origin(op_node);
+ scope->MarkUnused(left.value());
+ return Value();
+}
+
+// Plus/Minus -----------------------------------------------------------------
+
+Value ExecutePlus(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ Value ret = left;
+ ValuePlusEquals(scope, op_node, Token(), &ret, right, true, err);
+ ret.set_origin(op_node);
+ return ret;
+}
+
+Value ExecuteMinus(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ Value ret = left;
+ ValueMinusEquals(op_node, &ret, right, true, err);
+ ret.set_origin(op_node);
+ return ret;
+}
+
+// Comparison -----------------------------------------------------------------
+
+Value ExecuteEqualsEquals(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ if (left == right)
+ return Value(op_node, 1);
+ return Value(op_node, 0);
+}
+
+Value ExecuteNotEquals(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ // Evaluate in terms of ==.
+ Value result = ExecuteEqualsEquals(scope, op_node, left, right, err);
+ result.int_value() = static_cast<int64>(!result.int_value());
+ return result;
+}
+
+Value FillNeedsToIntegersError(const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ *err = Err(op_node, "Comparison requires two integers.",
+ "This operator can only compare two integers.");
+ err->AppendRange(left.origin()->GetRange());
+ err->AppendRange(right.origin()->GetRange());
+ return Value();
+}
+
+Value ExecuteLessEquals(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
+ return FillNeedsToIntegersError(op_node, left, right, err);
+ return Value(op_node, left.int_value() <= right.int_value());
+}
+
+Value ExecuteGreaterEquals(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
+ return FillNeedsToIntegersError(op_node, left, right, err);
+ return Value(op_node, left.int_value() >= right.int_value());
+}
+
+Value ExecuteGreater(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
+ return FillNeedsToIntegersError(op_node, left, right, err);
+ return Value(op_node, left.int_value() > right.int_value());
+}
+
+Value ExecuteLess(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
+ return FillNeedsToIntegersError(op_node, left, right, err);
+ return Value(op_node, left.int_value() < right.int_value());
+}
+
+// Binary ----------------------------------------------------------------------
+
+Value ExecuteOr(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ return Value(op_node,
+ static_cast<int64>(left.InterpretAsInt() || right.InterpretAsInt()));
+}
+
+Value ExecuteAnd(Scope* scope,
+ const BinaryOpNode* op_node,
+ const Value& left,
+ const Value& right,
+ Err* err) {
+ return Value(op_node,
+ static_cast<int64>(left.InterpretAsInt() && right.InterpretAsInt()));
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+bool IsUnaryOperator(const Token& token) {
+ if (token.type() != Token::OPERATOR)
+ return false;
+ return token.value() == "!";
+}
+
+bool IsBinaryOperator(const Token& token) {
+ if (token.type() != Token::OPERATOR)
+ return false;
+ return token.value() == "=" ||
+ token.value() == "+=" ||
+ token.value() == "-=" ||
+ token.value() == "+" ||
+ token.value() == "-" ||
+ token.value() == "==" ||
+ token.value() == "!=" ||
+ token.value() == "<=" ||
+ token.value() == ">=" ||
+ token.value() == "<" ||
+ token.value() == ">" ||
+ token.value() == "&&" ||
+ token.value() == "||";
+}
+
+bool IsFunctionCallArgBeginScoper(const Token& token) {
+ return token.IsScoperEqualTo("(");
+}
+
+bool IsFunctionCallArgEndScoper(const Token& token) {
+ return token.IsScoperEqualTo(")");
+}
+
+bool IsScopeBeginScoper(const Token& token) {
+ return token.IsScoperEqualTo("{");
+}
+
+bool IsScopeEndScoper(const Token& token) {
+ return token.IsScoperEqualTo("}");
+}
+
+Value ExecuteUnaryOperator(Scope* scope,
+ const UnaryOpNode* op_node,
+ const Value& expr,
+ Err* err) {
+ DCHECK(op_node->op().IsOperatorEqualTo("!"));
+ return Value(op_node, !expr.InterpretAsInt());
+}
+
+Value ExecuteBinaryOperator(Scope* scope,
+ const BinaryOpNode* op_node,
+ const ParseNode* left,
+ const ParseNode* right,
+ Err* err) {
+ const Token& op = op_node->op();
+
+ // First handle the ones that take an lvalue.
+ if (op.IsOperatorEqualTo("=") ||
+ op.IsOperatorEqualTo("+=") ||
+ op.IsOperatorEqualTo("-=")) {
+ const IdentifierNode* left_id = left->AsIdentifier();
+ if (!left_id) {
+ *err = Err(op, "Operator requires an lvalue.",
+ "This thing on the left is not an idenfitier.");
+ err->AppendRange(left->GetRange());
+ return Value();
+ }
+ const Token& dest = left_id->value();
+
+ Value right_value = right->Execute(scope, err);
+ if (err->has_error())
+ return Value();
+ if (right_value.type() == Value::NONE) {
+ *err = Err(op, "Operator requires an rvalue.",
+ "This thing on the right does not evaluate to a value.");
+ err->AppendRange(right->GetRange());
+ return Value();
+ }
+
+ if (op.IsOperatorEqualTo("="))
+ return ExecuteEquals(scope, op_node, dest, right_value, err);
+ if (op.IsOperatorEqualTo("+="))
+ return ExecutePlusEquals(scope, op_node, dest, right_value, err);
+ if (op.IsOperatorEqualTo("-="))
+ return ExecuteMinusEquals(scope, op_node, dest, right_value, err);
+ NOTREACHED();
+ return Value();
+ }
+
+ // Left value.
+ Value left_value = left->Execute(scope, err);
+ if (err->has_error())
+ return Value();
+ if (left_value.type() == Value::NONE) {
+ *err = Err(op, "Operator requires an value.",
+ "This thing on the left does not evaluate to a value.");
+ err->AppendRange(left->GetRange());
+ return Value();
+ }
+
+ // Right value. Note: don't move this above to share code with the lvalue
+ // version since in this case we want to execute the left side first.
+ Value right_value = right->Execute(scope, err);
+ if (err->has_error())
+ return Value();
+ if (right_value.type() == Value::NONE) {
+ *err = Err(op, "Operator requires an value.",
+ "This thing on the right does not evaluate to a value.");
+ err->AppendRange(right->GetRange());
+ return Value();
+ }
+
+ // +, -.
+ if (op.IsOperatorEqualTo("-"))
+ return ExecuteMinus(scope, op_node, left_value, right_value, err);
+ if (op.IsOperatorEqualTo("+"))
+ return ExecutePlus(scope, op_node, left_value, right_value, err);
+
+ // Comparisons.
+ if (op.IsOperatorEqualTo("=="))
+ return ExecuteEqualsEquals(scope, op_node, left_value, right_value, err);
+ if (op.IsOperatorEqualTo("!="))
+ return ExecuteNotEquals(scope, op_node, left_value, right_value, err);
+ if (op.IsOperatorEqualTo(">="))
+ return ExecuteGreaterEquals(scope, op_node, left_value, right_value, err);
+ if (op.IsOperatorEqualTo("<="))
+ return ExecuteLessEquals(scope, op_node, left_value, right_value, err);
+ if (op.IsOperatorEqualTo(">"))
+ return ExecuteGreater(scope, op_node, left_value, right_value, err);
+ if (op.IsOperatorEqualTo("<"))
+ return ExecuteLess(scope, op_node, left_value, right_value, err);
+
+ // ||, &&.
+ if (op.IsOperatorEqualTo("||"))
+ return ExecuteOr(scope, op_node, left_value, right_value, err);
+ if (op.IsOperatorEqualTo("&&"))
+ return ExecuteAnd(scope, op_node, left_value, right_value, err);
+
+ return Value();
+}
diff --git a/chromium/tools/gn/operators.h b/chromium/tools/gn/operators.h
new file mode 100644
index 00000000000..3401c225ba0
--- /dev/null
+++ b/chromium/tools/gn/operators.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_OPERATORS_H_
+#define TOOLS_GN_OPERATORS_H_
+
+class BinaryOpNode;
+class Err;
+class ParseNode;
+class Scope;
+class Token;
+class UnaryOpNode;
+class Value;
+
+bool IsUnaryOperator(const Token& token);
+bool IsBinaryOperator(const Token& token);
+
+bool IsFunctionCallArgBeginScoper(const Token& token); // "("
+bool IsFunctionCallArgEndScoper(const Token& token); // ")"
+
+bool IsScopeBeginScoper(const Token& token); // "{"
+bool IsScopeEndScoper(const Token& token); // "}"
+
+Value ExecuteUnaryOperator(Scope* scope,
+ const UnaryOpNode* op_node,
+ const Value& value,
+ Err* err);
+Value ExecuteBinaryOperator(Scope* scope,
+ const BinaryOpNode* op_node,
+ const ParseNode* left,
+ const ParseNode* right,
+ Err* err);
+
+#endif // TOOLS_GN_OPERATORS_H_
diff --git a/chromium/tools/gn/output_file.h b/chromium/tools/gn/output_file.h
new file mode 100644
index 00000000000..9c5e4b2c205
--- /dev/null
+++ b/chromium/tools/gn/output_file.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_OUTPUT_FILE_H_
+#define TOOLS_GN_OUTPUT_FILE_H_
+
+#include <string>
+
+#include "tools/gn/build_settings.h"
+#include "tools/gn/source_file.h"
+
+// A simple wrapper around a string that indicates the string is a path
+// relative to the output directory.
+class OutputFile {
+ public:
+ OutputFile() : value_() {}
+ explicit OutputFile(const base::StringPiece& str)
+ : value_(str.data(), str.size()) {
+ }
+
+ std::string& value() { return value_; }
+ const std::string& value() const { return value_; }
+
+ // Converts to a SourceFile by prepending the build directory to the file.
+ SourceFile GetSourceFile(const BuildSettings* build_settings) const {
+ return SourceFile(build_settings->build_dir().value() + value_);
+ }
+
+ bool operator==(const OutputFile& other) const {
+ return value_ == other.value_;
+ }
+ bool operator!=(const OutputFile& other) const {
+ return value_ != other.value_;
+ }
+
+ private:
+ std::string value_;
+};
+
+#endif
diff --git a/chromium/tools/gn/output_stream.h b/chromium/tools/gn/output_stream.h
new file mode 100644
index 00000000000..6f39c866612
--- /dev/null
+++ b/chromium/tools/gn/output_stream.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_OUTPUT_STREAM_H_
+#define TOOLS_GN_OUTPUT_STREAM_H_
+
+class OutputStream {
+ public:
+
+
+
+ OutputStream& WriteBuffer(const char* buf, size_t len);
+ OutputStream& WriteInt(int i);
+
+ // Write a literal.
+ // This template expansion prevents having to look for nulls.
+ template<size_t size> OutputStream& Write(const char (&buf)[size]) {
+ return WriteBuffer(buf, size);
+ }
+
+ // Write a literal string.
+ OutputStream& Write(const std::string& str) {
+ return WriteBuffer(str.c_str(), str.size());
+ }
+
+ // Quotes if necessary, and does necessary escaping. If more than one
+ // input is provided, the results will be concatenated together (useful
+ // for constructing paths without a temporary buffer).
+ OutputStream& WritePath(const std::string& s);
+ OutputStream& WritePath(const std::string& s0,
+ const std::string& s1);
+ OutputStream& WritePath(const std::string& s0,
+ const std::string& s1,
+ const std::string& s2);
+
+ OutputStream& EndLine() {
+ return WriteBuffer("\n", 1);
+ }
+};
+
+#endif // TOOLS_GN_OUTPUT_STREAM_H_
diff --git a/chromium/tools/gn/parse_tree.cc b/chromium/tools/gn/parse_tree.cc
new file mode 100644
index 00000000000..8e1adde47aa
--- /dev/null
+++ b/chromium/tools/gn/parse_tree.cc
@@ -0,0 +1,473 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/parse_tree.h"
+
+#include <string>
+
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/operators.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/string_utils.h"
+
+namespace {
+
+std::string IndentFor(int value) {
+ std::string ret;
+ for (int i = 0; i < value; i++)
+ ret.append(" ");
+ return ret;
+}
+
+} // namespace
+
+ParseNode::ParseNode() {
+}
+
+ParseNode::~ParseNode() {
+}
+
+const AccessorNode* ParseNode::AsAccessor() const { return NULL; }
+const BinaryOpNode* ParseNode::AsBinaryOp() const { return NULL; }
+const BlockNode* ParseNode::AsBlock() const { return NULL; }
+const ConditionNode* ParseNode::AsConditionNode() const { return NULL; }
+const FunctionCallNode* ParseNode::AsFunctionCall() const { return NULL; }
+const IdentifierNode* ParseNode::AsIdentifier() const { return NULL; }
+const ListNode* ParseNode::AsList() const { return NULL; }
+const LiteralNode* ParseNode::AsLiteral() const { return NULL; }
+const UnaryOpNode* ParseNode::AsUnaryOp() const { return NULL; }
+
+// AccessorNode ---------------------------------------------------------------
+
+AccessorNode::AccessorNode() {
+}
+
+AccessorNode::~AccessorNode() {
+}
+
+const AccessorNode* AccessorNode::AsAccessor() const {
+ return this;
+}
+
+Value AccessorNode::Execute(Scope* scope, Err* err) const {
+ Value index_value = index_->Execute(scope, err);
+ if (err->has_error())
+ return Value();
+ if (!index_value.VerifyTypeIs(Value::INTEGER, err))
+ return Value();
+
+ const Value* base_value = scope->GetValue(base_.value(), true);
+ if (!base_value) {
+ *err = MakeErrorDescribing("Undefined identifier.");
+ return Value();
+ }
+ if (!base_value->VerifyTypeIs(Value::LIST, err))
+ return Value();
+
+ int64 index_int = index_value.int_value();
+ if (index_int < 0) {
+ *err = Err(index_->GetRange(), "Negative array subscript.",
+ "You gave me " + base::Int64ToString(index_int) + ".");
+ return Value();
+ }
+ size_t index_sizet = static_cast<size_t>(index_int);
+ if (index_sizet >= base_value->list_value().size()) {
+ *err = Err(index_->GetRange(), "Array subscript out of range.",
+ "You gave me " + base::Int64ToString(index_int) +
+ " but I was expecting something from 0 to " +
+ base::Int64ToString(
+ static_cast<int64>(base_value->list_value().size()) - 1) +
+ ", inclusive.");
+ return Value();
+ }
+
+ // Doing this assumes that there's no way in the language to do anything
+ // between the time the reference is created and the time that the reference
+ // is used. If there is, this will crash! Currently, this is just used for
+ // array accesses where this "shouldn't" happen.
+ return base_value->list_value()[index_sizet];
+}
+
+LocationRange AccessorNode::GetRange() const {
+ return LocationRange(base_.location(), index_->GetRange().end());
+}
+
+Err AccessorNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(GetRange(), msg, help);
+}
+
+void AccessorNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "ACCESSOR\n";
+ out << IndentFor(indent + 1) << base_.value() << "\n";
+ index_->Print(out, indent + 1);
+}
+
+// BinaryOpNode ---------------------------------------------------------------
+
+BinaryOpNode::BinaryOpNode() {
+}
+
+BinaryOpNode::~BinaryOpNode() {
+}
+
+const BinaryOpNode* BinaryOpNode::AsBinaryOp() const {
+ return this;
+}
+
+Value BinaryOpNode::Execute(Scope* scope, Err* err) const {
+ return ExecuteBinaryOperator(scope, this, left_.get(), right_.get(), err);
+}
+
+LocationRange BinaryOpNode::GetRange() const {
+ return left_->GetRange().Union(right_->GetRange());
+}
+
+Err BinaryOpNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(op_, msg, help);
+}
+
+void BinaryOpNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "BINARY(" << op_.value() << ")\n";
+ left_->Print(out, indent + 1);
+ right_->Print(out, indent + 1);
+}
+
+// BlockNode ------------------------------------------------------------------
+
+BlockNode::BlockNode(bool has_scope)
+ : has_scope_(has_scope),
+ begin_token_(NULL),
+ end_token_(NULL) {
+}
+
+BlockNode::~BlockNode() {
+ STLDeleteContainerPointers(statements_.begin(), statements_.end());
+}
+
+const BlockNode* BlockNode::AsBlock() const {
+ return this;
+}
+
+Value BlockNode::Execute(Scope* containing_scope, Err* err) const {
+ if (has_scope_) {
+ Scope our_scope(containing_scope);
+ Value ret = ExecuteBlockInScope(&our_scope, err);
+ if (err->has_error())
+ return Value();
+
+ // Check for unused vars in the scope.
+ //our_scope.CheckForUnusedVars(err);
+ return ret;
+ }
+ return ExecuteBlockInScope(containing_scope, err);
+}
+
+LocationRange BlockNode::GetRange() const {
+ if (begin_token_ && end_token_) {
+ return begin_token_->range().Union(end_token_->range());
+ }
+ return LocationRange(); // TODO(brettw) indicate the entire file somehow.
+}
+
+Err BlockNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ if (begin_token_)
+ return Err(*begin_token_, msg, help);
+ // TODO(brettw) this should have the beginning of the file in it or something.
+ return Err(Location(NULL, 1, 1), msg, help);
+}
+
+void BlockNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "BLOCK\n";
+ for (size_t i = 0; i < statements_.size(); i++)
+ statements_[i]->Print(out, indent + 1);
+}
+
+Value BlockNode::ExecuteBlockInScope(Scope* our_scope, Err* err) const {
+ for (size_t i = 0; i < statements_.size() && !err->has_error(); i++) {
+ // Check for trying to execute things with no side effects in a block.
+ const ParseNode* cur = statements_[i];
+ if (cur->AsList() || cur->AsLiteral() || cur->AsUnaryOp() ||
+ cur->AsIdentifier()) {
+ *err = cur->MakeErrorDescribing(
+ "This statment has no effect.",
+ "Either delete it or do something with the result.");
+ return Value();
+ }
+ cur->Execute(our_scope, err);
+ }
+ return Value();
+}
+
+// ConditionNode --------------------------------------------------------------
+
+ConditionNode::ConditionNode() {
+}
+
+ConditionNode::~ConditionNode() {
+}
+
+const ConditionNode* ConditionNode::AsConditionNode() const {
+ return this;
+}
+
+Value ConditionNode::Execute(Scope* scope, Err* err) const {
+ Value condition_result = condition_->Execute(scope, err);
+ if (err->has_error())
+ return Value();
+ if (condition_result.type() == Value::NONE) {
+ *err = condition_->MakeErrorDescribing(
+ "This does not evaluate to a value.",
+ "Please give me something to work with for the if statement.");
+ err->AppendRange(if_token_.range());
+ return Value();
+ }
+
+ if (condition_result.InterpretAsInt()) {
+ if_true_->ExecuteBlockInScope(scope, err);
+ } else if (if_false_) {
+ // The else block is optional. It's either another condition (for an
+ // "else if" and we can just Execute it and the condition will handle
+ // the scoping) or it's a block indicating an "else" in which ase we
+ // need to be sure it inherits our scope.
+ const BlockNode* if_false_block = if_false_->AsBlock();
+ if (if_false_block)
+ if_false_block->ExecuteBlockInScope(scope, err);
+ else
+ if_false_->Execute(scope, err);
+ }
+
+ return Value();
+}
+
+LocationRange ConditionNode::GetRange() const {
+ if (if_false_)
+ return if_token_.range().Union(if_false_->GetRange());
+ return if_token_.range().Union(if_true_->GetRange());
+}
+
+Err ConditionNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(if_token_, msg, help);
+}
+
+void ConditionNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "CONDITION\n";
+ condition_->Print(out, indent + 1);
+ if_true_->Print(out, indent + 1);
+ if (if_false_)
+ if_false_->Print(out, indent + 1);
+}
+
+// FunctionCallNode -----------------------------------------------------------
+
+FunctionCallNode::FunctionCallNode() {
+}
+
+FunctionCallNode::~FunctionCallNode() {
+}
+
+const FunctionCallNode* FunctionCallNode::AsFunctionCall() const {
+ return this;
+}
+
+Value FunctionCallNode::Execute(Scope* scope, Err* err) const {
+ Value args = args_->Execute(scope, err);
+ if (err->has_error())
+ return Value();
+ return functions::RunFunction(scope, this, args.list_value(), block_.get(),
+ err);
+}
+
+LocationRange FunctionCallNode::GetRange() const {
+ if (block_)
+ return function_.range().Union(block_->GetRange());
+ return function_.range().Union(args_->GetRange());
+}
+
+Err FunctionCallNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(function_, msg, help);
+}
+
+void FunctionCallNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "FUNCTION(" << function_.value() << ")\n";
+ args_->Print(out, indent + 1);
+ if (block_)
+ block_->Print(out, indent + 1);
+}
+
+// IdentifierNode --------------------------------------------------------------
+
+IdentifierNode::IdentifierNode() {
+}
+
+IdentifierNode::IdentifierNode(const Token& token) : value_(token) {
+}
+
+IdentifierNode::~IdentifierNode() {
+}
+
+const IdentifierNode* IdentifierNode::AsIdentifier() const {
+ return this;
+}
+
+Value IdentifierNode::Execute(Scope* scope, Err* err) const {
+ const Value* result = scope->GetValue(value_.value(), true);
+ if (!result) {
+ *err = MakeErrorDescribing("Undefined identifier");
+ return Value();
+ }
+ return *result;
+}
+
+LocationRange IdentifierNode::GetRange() const {
+ return value_.range();
+}
+
+Err IdentifierNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(value_, msg, help);
+}
+
+void IdentifierNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "IDENTIFIER(" << value_.value() << ")\n";
+}
+
+// ListNode -------------------------------------------------------------------
+
+ListNode::ListNode() {
+}
+
+ListNode::~ListNode() {
+ STLDeleteContainerPointers(contents_.begin(), contents_.end());
+}
+
+const ListNode* ListNode::AsList() const {
+ return this;
+}
+
+Value ListNode::Execute(Scope* scope, Err* err) const {
+ Value result_value(this, Value::LIST);
+ std::vector<Value>& results = result_value.list_value();
+ results.resize(contents_.size());
+
+ for (size_t i = 0; i < contents_.size(); i++) {
+ const ParseNode* cur = contents_[i];
+ results[i] = cur->Execute(scope, err);
+ if (err->has_error())
+ return Value();
+ if (results[i].type() == Value::NONE) {
+ *err = cur->MakeErrorDescribing(
+ "This does not evaluate to a value.",
+ "I can't do something with nothing.");
+ return Value();
+ }
+ }
+ return result_value;
+}
+
+LocationRange ListNode::GetRange() const {
+ return LocationRange(begin_token_.location(), end_token_.location());
+}
+
+Err ListNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(begin_token_, msg, help);
+}
+
+void ListNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "LIST\n";
+ for (size_t i = 0; i < contents_.size(); i++)
+ contents_[i]->Print(out, indent + 1);
+}
+
+// LiteralNode -----------------------------------------------------------------
+
+LiteralNode::LiteralNode() {
+}
+
+LiteralNode::LiteralNode(const Token& token) : value_(token) {
+}
+
+LiteralNode::~LiteralNode() {
+}
+
+const LiteralNode* LiteralNode::AsLiteral() const {
+ return this;
+}
+
+Value LiteralNode::Execute(Scope* scope, Err* err) const {
+ switch (value_.type()) {
+ case Token::INTEGER: {
+ int64 result_int;
+ if (!base::StringToInt64(value_.value(), &result_int)) {
+ *err = MakeErrorDescribing("This does not look like an integer");
+ return Value();
+ }
+ return Value(this, result_int);
+ }
+ case Token::STRING: {
+ // TODO(brettw) Unescaping probably needs to be moved & improved.
+ // The input value includes the quotes around the string, strip those
+ // off and unescape.
+ Value v(this, Value::STRING);
+ ExpandStringLiteral(scope, value_, &v, err);
+ return v;
+ }
+ default:
+ NOTREACHED();
+ return Value();
+ }
+}
+
+LocationRange LiteralNode::GetRange() const {
+ return value_.range();
+}
+
+Err LiteralNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(value_, msg, help);
+}
+
+void LiteralNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "LITERAL(" << value_.value() << ")\n";
+}
+
+// UnaryOpNode ----------------------------------------------------------------
+
+UnaryOpNode::UnaryOpNode() {
+}
+
+UnaryOpNode::~UnaryOpNode() {
+}
+
+const UnaryOpNode* UnaryOpNode::AsUnaryOp() const {
+ return this;
+}
+
+Value UnaryOpNode::Execute(Scope* scope, Err* err) const {
+ Value operand_value = operand_->Execute(scope, err);
+ if (err->has_error())
+ return Value();
+ return ExecuteUnaryOperator(scope, this, operand_value, err);
+}
+
+LocationRange UnaryOpNode::GetRange() const {
+ return op_.range().Union(operand_->GetRange());
+}
+
+Err UnaryOpNode::MakeErrorDescribing(const std::string& msg,
+ const std::string& help) const {
+ return Err(op_, msg, help);
+}
+
+void UnaryOpNode::Print(std::ostream& out, int indent) const {
+ out << IndentFor(indent) << "UNARY(" << op_.value() << ")\n";
+ operand_->Print(out, indent + 1);
+}
diff --git a/chromium/tools/gn/parse_tree.h b/chromium/tools/gn/parse_tree.h
new file mode 100644
index 00000000000..09646e51ac4
--- /dev/null
+++ b/chromium/tools/gn/parse_tree.h
@@ -0,0 +1,366 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_PARSE_TREE_H_
+#define TOOLS_GN_PARSE_TREE_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "tools/gn/err.h"
+#include "tools/gn/token.h"
+#include "tools/gn/value.h"
+
+class AccessorNode;
+class BinaryOpNode;
+class BlockNode;
+class ConditionNode;
+class FunctionCallNode;
+class IdentifierNode;
+class ListNode;
+class LiteralNode;
+class Scope;
+class UnaryOpNode;
+
+// ParseNode -------------------------------------------------------------------
+
+// A node in the AST.
+class ParseNode {
+ public:
+ ParseNode();
+ virtual ~ParseNode();
+
+ virtual const AccessorNode* AsAccessor() const;
+ virtual const BinaryOpNode* AsBinaryOp() const;
+ virtual const BlockNode* AsBlock() const;
+ virtual const ConditionNode* AsConditionNode() const;
+ virtual const FunctionCallNode* AsFunctionCall() const;
+ virtual const IdentifierNode* AsIdentifier() const;
+ virtual const ListNode* AsList() const;
+ virtual const LiteralNode* AsLiteral() const;
+ virtual const UnaryOpNode* AsUnaryOp() const;
+
+ virtual Value Execute(Scope* scope, Err* err) const = 0;
+
+ virtual LocationRange GetRange() const = 0;
+
+ // Returns an error with the given messages and the range set to something
+ // that indicates this node.
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const = 0;
+
+ // Prints a representation of this node to the given string, indenting
+ // by the given number of spaces.
+ virtual void Print(std::ostream& out, int indent) const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ParseNode);
+};
+
+// AccessorNode ----------------------------------------------------------------
+
+// Access an array element.
+//
+// If we need to add support for member variables like "variable.len" I was
+// thinking this would also handle that case.
+class AccessorNode : public ParseNode {
+ public:
+ AccessorNode();
+ virtual ~AccessorNode();
+
+ virtual const AccessorNode* AsAccessor() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ // Base is the thing on the left of the [], currently always required to be
+ // an identifier token.
+ const Token& base() const { return base_; }
+ void set_base(const Token& b) { base_ = b; }
+
+ // Index is the expression inside the [].
+ const ParseNode* index() const { return index_.get(); }
+ void set_index(scoped_ptr<ParseNode> i) { index_ = i.Pass(); }
+
+ private:
+ Token base_;
+ scoped_ptr<ParseNode> index_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessorNode);
+};
+
+// BinaryOpNode ----------------------------------------------------------------
+
+class BinaryOpNode : public ParseNode {
+ public:
+ BinaryOpNode();
+ virtual ~BinaryOpNode();
+
+ virtual const BinaryOpNode* AsBinaryOp() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ const Token& op() const { return op_; }
+ void set_op(const Token& t) { op_ = t; }
+
+ const ParseNode* left() const { return left_.get(); }
+ void set_left(scoped_ptr<ParseNode> left) {
+ left_ = left.Pass();
+ }
+
+ const ParseNode* right() const { return right_.get(); }
+ void set_right(scoped_ptr<ParseNode> right) {
+ right_ = right.Pass();
+ }
+
+ private:
+ scoped_ptr<ParseNode> left_;
+ Token op_;
+ scoped_ptr<ParseNode> right_;
+
+ DISALLOW_COPY_AND_ASSIGN(BinaryOpNode);
+};
+
+// BlockNode -------------------------------------------------------------------
+
+class BlockNode : public ParseNode {
+ public:
+ // Set has_scope if this block introduces a nested scope.
+ BlockNode(bool has_scope);
+ virtual ~BlockNode();
+
+ virtual const BlockNode* AsBlock() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ void set_begin_token(const Token* t) { begin_token_ = t; }
+ void set_end_token(const Token* t) { end_token_ = t; }
+
+ const std::vector<ParseNode*>& statements() const { return statements_; }
+ void append_statement(scoped_ptr<ParseNode> s) {
+ statements_.push_back(s.release());
+ }
+
+ // Doesn't create a nested scope.
+ Value ExecuteBlockInScope(Scope* our_scope, Err* err) const;
+
+ private:
+ bool has_scope_;
+
+ // Tokens corresponding to { and }, if any (may be NULL).
+ const Token* begin_token_;
+ const Token* end_token_;
+
+ // Owning pointers, use unique_ptr when we can use C++11.
+ std::vector<ParseNode*> statements_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlockNode);
+};
+
+// ConditionNode ---------------------------------------------------------------
+
+class ConditionNode : public ParseNode {
+ public:
+ ConditionNode();
+ virtual ~ConditionNode();
+
+ virtual const ConditionNode* AsConditionNode() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ void set_if_token(const Token& token) { if_token_ = token; }
+
+ const ParseNode* condition() const { return condition_.get(); }
+ void set_condition(scoped_ptr<ParseNode> c) {
+ condition_ = c.Pass();
+ }
+
+ const BlockNode* if_true() const { return if_true_.get(); }
+ void set_if_true(scoped_ptr<BlockNode> t) {
+ if_true_ = t.Pass();
+ }
+
+ // This is either empty, a block (for the else clause), or another
+ // condition.
+ const ParseNode* if_false() const { return if_false_.get(); }
+ void set_if_false(scoped_ptr<ParseNode> f) {
+ if_false_ = f.Pass();
+ }
+
+ private:
+ // Token corresponding to the "if" string.
+ Token if_token_;
+
+ scoped_ptr<ParseNode> condition_; // Always non-null.
+ scoped_ptr<BlockNode> if_true_; // Always non-null.
+ scoped_ptr<ParseNode> if_false_; // May be null.
+
+ DISALLOW_COPY_AND_ASSIGN(ConditionNode);
+};
+
+// FunctionCallNode ------------------------------------------------------------
+
+class FunctionCallNode : public ParseNode {
+ public:
+ FunctionCallNode();
+ virtual ~FunctionCallNode();
+
+ virtual const FunctionCallNode* AsFunctionCall() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ const Token& function() const { return function_; }
+ void set_function(Token t) { function_ = t; }
+
+ const ListNode* args() const { return args_.get(); }
+ void set_args(scoped_ptr<ListNode> a) { args_ = a.Pass(); }
+
+ const BlockNode* block() const { return block_.get(); }
+ void set_block(scoped_ptr<BlockNode> b) { block_ = b.Pass(); }
+
+ private:
+ Token function_;
+ scoped_ptr<ListNode> args_;
+ scoped_ptr<BlockNode> block_; // May be null.
+
+ DISALLOW_COPY_AND_ASSIGN(FunctionCallNode);
+};
+
+// IdentifierNode --------------------------------------------------------------
+
+class IdentifierNode : public ParseNode {
+ public:
+ IdentifierNode();
+ IdentifierNode(const Token& token);
+ virtual ~IdentifierNode();
+
+ virtual const IdentifierNode* AsIdentifier() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ const Token& value() const { return value_; }
+ void set_value(const Token& t) { value_ = t; }
+
+ private:
+ Token value_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdentifierNode);
+};
+
+// ListNode --------------------------------------------------------------------
+
+class ListNode : public ParseNode {
+ public:
+ ListNode();
+ virtual ~ListNode();
+
+ virtual const ListNode* AsList() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ void set_begin_token(const Token& t) { begin_token_ = t; }
+ void set_end_token(const Token& t) { end_token_ = t; }
+
+ void append_item(scoped_ptr<ParseNode> s) {
+ contents_.push_back(s.release());
+ }
+ const std::vector<ParseNode*>& contents() const { return contents_; }
+
+ private:
+ // Tokens corresponding to the [ and ].
+ Token begin_token_;
+ Token end_token_;
+
+ // Owning pointers, use unique_ptr when we can use C++11.
+ std::vector<ParseNode*> contents_;
+
+ DISALLOW_COPY_AND_ASSIGN(ListNode);
+};
+
+// LiteralNode -----------------------------------------------------------------
+
+class LiteralNode : public ParseNode {
+ public:
+ LiteralNode();
+ LiteralNode(const Token& token);
+ virtual ~LiteralNode();
+
+ virtual const LiteralNode* AsLiteral() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ const Token& value() const { return value_; }
+ void set_value(const Token& t) { value_ = t; }
+
+ private:
+ Token value_;
+
+ DISALLOW_COPY_AND_ASSIGN(LiteralNode);
+};
+
+// UnaryOpNode -----------------------------------------------------------------
+
+class UnaryOpNode : public ParseNode {
+ public:
+ UnaryOpNode();
+ virtual ~UnaryOpNode();
+
+ virtual const UnaryOpNode* AsUnaryOp() const OVERRIDE;
+ virtual Value Execute(Scope* scope, Err* err) const OVERRIDE;
+ virtual LocationRange GetRange() const OVERRIDE;
+ virtual Err MakeErrorDescribing(
+ const std::string& msg,
+ const std::string& help = std::string()) const OVERRIDE;
+ virtual void Print(std::ostream& out, int indent) const OVERRIDE;
+
+ const Token& op() const { return op_; }
+ void set_op(const Token& t) { op_ = t; }
+
+ const ParseNode* operand() const { return operand_.get(); }
+ void set_operand(scoped_ptr<ParseNode> operand) {
+ operand_ = operand.Pass();
+ }
+
+ private:
+ Token op_;
+ scoped_ptr<ParseNode> operand_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnaryOpNode);
+};
+
+#endif // TOOLS_GN_PARSE_TREE_H_
diff --git a/chromium/tools/gn/parser.cc b/chromium/tools/gn/parser.cc
new file mode 100644
index 00000000000..385aa346f61
--- /dev/null
+++ b/chromium/tools/gn/parser.cc
@@ -0,0 +1,470 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/parser.h"
+
+#include "base/logging.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/operators.h"
+#include "tools/gn/token.h"
+
+namespace {
+
+// Returns true if the two tokens are on the same line. We assume they're in
+// the same file.
+bool IsSameLine(const Token& a, const Token& b) {
+ DCHECK(a.location().file() == b.location().file());
+ return a.location().line_number() == b.location().line_number();
+}
+
+} // namespace
+
+Parser::Parser(const std::vector<Token>& tokens, Err* err)
+ : tokens_(tokens),
+ err_(err),
+ cur_(0) {
+}
+
+Parser::~Parser() {
+}
+
+// static
+scoped_ptr<ParseNode> Parser::Parse(const std::vector<Token>& tokens,
+ Err* err) {
+ Parser p(tokens, err);
+ return p.ParseBlock(false).PassAs<ParseNode>();
+}
+
+// static
+scoped_ptr<ParseNode> Parser::ParseExpression(const std::vector<Token>& tokens,
+ Err* err) {
+ Parser p(tokens, err);
+ return p.ParseExpression().Pass();
+}
+
+bool Parser::IsToken(Token::Type type, char* str) const {
+ if (at_end())
+ return false;
+ return cur_token().type() == type || cur_token().value() == str;
+}
+
+scoped_ptr<AccessorNode> Parser::ParseAccessor() {
+ scoped_ptr<AccessorNode> accessor(new AccessorNode);
+
+ DCHECK(cur_token().type() == Token::IDENTIFIER);
+ accessor->set_base(cur_token());
+ cur_++; // Skip identifier.
+ cur_++; // Skip "[" (we know this exists because the existance of this
+ // token is how the caller knows it's an accessor.
+
+ if (at_end()) {
+ *err_ = MakeEOFError("Got EOF when looking for list index.");
+ return scoped_ptr<AccessorNode>();
+ }
+
+ // Get the expression.
+ scoped_ptr<ParseNode> expr = ParseExpression().Pass();
+ if (has_error())
+ return scoped_ptr<AccessorNode>();
+ if (at_end()) {
+ *err_ = MakeEOFError("Got EOF when looking for list accessor ]");
+ return scoped_ptr<AccessorNode>();
+ }
+ accessor->set_index(expr.Pass());
+
+ // Skip over "]"
+ if (!cur_token().IsScoperEqualTo("]")) {
+ *err_ = Err(cur_token(), "Expecting ]",
+ "You started a list access but didn't terminate it, and instead "
+ "I fould this\nstupid thing.");
+ return scoped_ptr<AccessorNode>();
+ }
+ cur_++;
+
+ return accessor.Pass();
+}
+
+// Blocks at the file scope don't need {} so we have the option to ignore
+// them. When need_braces is set, we'll expect a begin an end brace.
+//
+// block := "{" block_contents "}"
+// block_contents := (expression | conditional | block)*
+scoped_ptr<BlockNode> Parser::ParseBlock(bool need_braces) {
+ scoped_ptr<BlockNode> block(new BlockNode(true));
+
+ // Eat initial { if necessary.
+ const Token* opening_curly_brace;
+ if (need_braces) {
+ if (at_end()) {
+ *err_ = MakeEOFError("Got EOF when looking for { for block.",
+ "It should have been after here.");
+ return scoped_ptr<BlockNode>();
+ } else if(!IsScopeBeginScoper(cur_token())) {
+ *err_ = Err(cur_token(), "Expecting { instead of this thing.",
+ "THOU SHALT USE CURLY BRACES FOR ALL BLOCKS.");
+ return scoped_ptr<BlockNode>();
+ }
+ opening_curly_brace = &cur_token();
+ block->set_begin_token(opening_curly_brace);
+ cur_++;
+ }
+
+ // Loop until EOF or end brace found.
+ while (!at_end() && !IsScopeEndScoper(cur_token())) {
+ if (cur_token().IsIdentifierEqualTo("if")) {
+ // Conditional.
+ block->append_statement(ParseCondition().PassAs<ParseNode>());
+ } else if (IsScopeBeginScoper(cur_token())) {
+ // Nested block.
+ block->append_statement(ParseBlock(true).PassAs<ParseNode>());
+ } else {
+ // Everything else is an expression.
+ block->append_statement(ParseExpression().PassAs<ParseNode>());
+ }
+ if (has_error())
+ return scoped_ptr<BlockNode>();
+ }
+
+ // Eat the ending "}" if necessary.
+ if (need_braces) {
+ if (at_end() || !IsScopeEndScoper(cur_token())) {
+ *err_ = Err(*opening_curly_brace, "Expecting }",
+ "I ran headlong into the end of the file looking for the "
+ "closing brace\ncorresponding to this one.");
+ return scoped_ptr<BlockNode>();
+ }
+ block->set_end_token(&cur_token());
+ cur_++; // Skip past "}".
+ }
+
+ return block.Pass();
+}
+
+// conditional := "if (" expression ")" block [else_conditional]
+// else_conditional := ("else" block) | ("else" conditional)
+scoped_ptr<ConditionNode> Parser::ParseCondition() {
+ scoped_ptr<ConditionNode> cond(new ConditionNode);
+
+ // Skip past "if".
+ const Token& if_token = cur_token();
+ cond->set_if_token(if_token);
+ DCHECK(if_token.IsIdentifierEqualTo("if"));
+ cur_++;
+
+ if (at_end() || !IsFunctionCallArgBeginScoper(cur_token())) {
+ *err_ = Err(if_token, "Expecting \"(\" after \"if\"",
+ "Did you think this was Python or something?");
+ return scoped_ptr<ConditionNode>();
+ }
+
+ // Skip over (.
+ const Token& open_paren_token = cur_token();
+ cur_++;
+ if (at_end()) {
+ *err_ = Err(if_token, "Unexpected EOF inside if condition");
+ return scoped_ptr<ConditionNode>();
+ }
+
+ // Condition inside ().
+ cond->set_condition(ParseExpression().Pass());
+ if (has_error())
+ return scoped_ptr<ConditionNode>();
+
+ if (at_end() || !IsFunctionCallArgEndScoper(cur_token())) {
+ *err_ = Err(open_paren_token, "Expecting \")\" for \"if\" condition",
+ "You didn't finish the thought you started here.");
+ return scoped_ptr<ConditionNode>();
+ }
+ cur_++; // Skip over )
+
+ // Contents of {}.
+ cond->set_if_true(ParseBlock(true).Pass());
+ if (has_error())
+ return scoped_ptr<ConditionNode>();
+
+ // Optional "else" at the end.
+ if (!at_end() && cur_token().IsIdentifierEqualTo("else")) {
+ cur_++;
+
+ // The else may be followed by an if or a block.
+ if (at_end()) {
+ *err_ = MakeEOFError("Ran into end of file after \"else\".",
+ "else, WHAT?!?!?");
+ return scoped_ptr<ConditionNode>();
+ }
+ if (cur_token().IsIdentifierEqualTo("if")) {
+ // "else if() {"
+ cond->set_if_false(ParseCondition().PassAs<ParseNode>());
+ } else if (IsScopeBeginScoper(cur_token())) {
+ // "else {"
+ cond->set_if_false(ParseBlock(true).PassAs<ParseNode>());
+ } else {
+ // else <anything else>
+ *err_ = Err(cur_token(), "Expected \"if\" or \"{\" after \"else\".",
+ "This is neither of those things.");
+ return scoped_ptr<ConditionNode>();
+ }
+ }
+
+ if (has_error())
+ return scoped_ptr<ConditionNode>();
+ return cond.Pass();
+}
+
+// expression := paren_expression | accessor | identifier | literal |
+// funccall | unary_expression | binary_expression
+//
+// accessor := identifier <non-newline-whitespace>* "[" expression "]"
+//
+// The "non-newline-whitespace is used to differentiate between this case:
+// a[1]
+// and this one:
+// a
+// [1]
+// The second one is kind of stupid (since it does nothing with the values)
+// but is still legal.
+scoped_ptr<ParseNode> Parser::ParseExpression() {
+ scoped_ptr<ParseNode> expr = ParseExpressionExceptBinaryOperators();
+ if (has_error())
+ return scoped_ptr<ParseNode>();
+
+ // That may have hit EOF, in which case we can't have any binary operators.
+ if (at_end())
+ return expr.Pass();
+
+ // TODO(brettw) handle operator precidence!
+ // Gobble up all subsequent expressions as long as there are binary
+ // operators.
+
+ if (IsBinaryOperator(cur_token())) {
+ scoped_ptr<BinaryOpNode> binary_op(new BinaryOpNode);
+ binary_op->set_left(expr.Pass());
+ const Token& operator_token = cur_token();
+ binary_op->set_op(operator_token);
+ cur_++;
+ if (at_end()) {
+ *err_ = Err(operator_token, "Unexpected EOF in expression.",
+ "I was looking for the right-hand-side of this operator.");
+ return scoped_ptr<ParseNode>();
+ }
+ binary_op->set_right(ParseExpression().Pass());
+ if (has_error())
+ return scoped_ptr<ParseNode>();
+ return binary_op.PassAs<ParseNode>();
+ }
+
+ return expr.Pass();
+}
+
+
+// This internal one does not handle binary operators, since it requires
+// looking at the "next" thing. The regular ParseExpression above handles it.
+scoped_ptr<ParseNode> Parser::ParseExpressionExceptBinaryOperators() {
+ if (at_end())
+ return scoped_ptr<ParseNode>();
+
+ const Token& token = cur_token();
+
+ // Unary expression.
+ if (IsUnaryOperator(token))
+ return ParseUnaryOp().PassAs<ParseNode>();
+
+ // Parenthesized expressions.
+ if (token.IsScoperEqualTo("("))
+ return ParseParenExpression();
+
+ // Function calls.
+ if (token.type() == Token::IDENTIFIER) {
+ if (has_next_token() && IsFunctionCallArgBeginScoper(next_token()))
+ return ParseFunctionCall().PassAs<ParseNode>();
+ }
+
+ // Lists.
+ if (token.IsScoperEqualTo("[")) {
+ return ParseList(Token(Location(), Token::SCOPER, "["),
+ Token(Location(), Token::SCOPER, "]")).PassAs<ParseNode>();
+ }
+
+ // Literals.
+ if (token.type() == Token::STRING || token.type() == Token::INTEGER) {
+ cur_++;
+ return scoped_ptr<ParseNode>(new LiteralNode(token));
+ }
+
+ // Accessors.
+ if (token.type() == Token::IDENTIFIER &&
+ has_next_token() && next_token().IsScoperEqualTo("[") &&
+ IsSameLine(token, next_token())) {
+ return ParseAccessor().PassAs<ParseNode>();
+ }
+
+ // Identifiers.
+ if (token.type() == Token::IDENTIFIER) {
+ cur_++;
+ return scoped_ptr<ParseNode>(new IdentifierNode(token));
+ }
+
+ // Handle errors.
+ if (token.type() == Token::SEPARATOR) {
+ *err_ = Err(token, "Unexpected comma.",
+ "You can't put a comma here, it must be in list separating "
+ "complete\nthoughts.");
+ } else if (IsScopeBeginScoper(token)) {
+ *err_ = Err(token, "Unexpected token.",
+ "You can't put a \"{\" scope here, it must be in a block.");
+ } else {
+ *err_ = Err(token, "Unexpected token.",
+ "I was really hoping for something else here and you let me down.");
+ }
+ return scoped_ptr<ParseNode>();
+}
+
+// function_call := identifier "(" list_contents ")"
+// [<non-newline-whitespace>* block]
+scoped_ptr<FunctionCallNode> Parser::ParseFunctionCall() {
+ scoped_ptr<FunctionCallNode> func(new FunctionCallNode);
+
+ const Token& function_token = cur_token();
+ func->set_function(function_token);
+
+ // This function should only get called when we know we have a function,
+ // which only happens when there is a paren following the name. Skip past it.
+ DCHECK(has_next_token());
+ cur_++; // Skip past function name to (.
+ const Token& open_paren_token = cur_token();
+ DCHECK(IsFunctionCallArgBeginScoper(open_paren_token));
+
+ if (at_end()) {
+ *err_ = Err(open_paren_token, "Unexpected EOF for function call.",
+ "You didn't finish the thought you started here.");
+ return scoped_ptr<FunctionCallNode>();
+ }
+
+ // Arguments.
+ func->set_args(ParseList(Token(Location(), Token::SCOPER, "("),
+ Token(Location(), Token::SCOPER, ")")));
+ if (has_error())
+ return scoped_ptr<FunctionCallNode>();
+
+ // Optional {} after function call for certain functions. The "{" must be on
+ // the same line as the ")" to disambiguate the case of a function followed
+ // by a random block just used for scoping purposes.
+ if (!at_end() && IsScopeBeginScoper(cur_token())) {
+ const Token& args_end_token = tokens_[cur_ - 1];
+ DCHECK(args_end_token.IsScoperEqualTo(")"));
+ if (IsSameLine(args_end_token, cur_token()))
+ func->set_block(ParseBlock(true).Pass());
+ }
+
+ if (has_error())
+ return scoped_ptr<FunctionCallNode>();
+ return func.Pass();
+}
+
+// list := "[" expression* "]"
+// list_contents := [(expression ",")* expression [","]]
+//
+// The list_contents is also used in function calls surrounded by parens, so
+// this function takes the tokens that are expected to surround the list.
+scoped_ptr<ListNode> Parser::ParseList(const Token& expected_begin,
+ const Token& expected_end) {
+ scoped_ptr<ListNode> list(new ListNode);
+
+ const Token& open_bracket_token = cur_token();
+ list->set_begin_token(open_bracket_token);
+ cur_++; // Skip "[" or "(".
+
+ bool need_separator = false;
+ while(true) {
+ if (at_end()) {
+ *err_ = Err(open_bracket_token, "EOF found when parsing list.",
+ "I expected a \"" + expected_end.value().as_string() +
+ "\" corresponding to this one.");
+ return scoped_ptr<ListNode>();
+ }
+ if (cur_token().type() == expected_end.type() &&
+ cur_token().value() == expected_end.value()) {
+ list->set_end_token(cur_token());
+ cur_++;
+ break;
+ }
+
+ if (need_separator) {
+ DCHECK(!list->contents().empty());
+ LocationRange prev_item_range =
+ list->contents().at(list->contents().size() - 1)->GetRange();
+ *err_ = Err(prev_item_range.end(),
+ "Need comma separating items in list.",
+ "You probably need a comma after this thingy.");
+ err_->AppendRange(prev_item_range);
+ return scoped_ptr<ListNode>();
+ }
+ scoped_ptr<ParseNode> expr = ParseExpression().Pass();
+ if (has_error())
+ return scoped_ptr<ListNode>();
+ list->append_item(expr.Pass());
+
+ need_separator = true;
+ if (!at_end()) {
+ // Skip over the separator, marking that we found it.
+ if (cur_token().type() == Token::SEPARATOR) {
+ cur_++;
+ need_separator = false;
+ }
+ }
+ }
+ return list.Pass();
+}
+
+// paren_expression := "(" expression ")"
+scoped_ptr<ParseNode> Parser::ParseParenExpression() {
+ const Token& open_paren_token = cur_token();
+ cur_++; // Skip over (
+
+ scoped_ptr<ParseNode> ret = ParseExpression();
+ if (has_error())
+ return scoped_ptr<ParseNode>();
+
+ if (at_end()) {
+ *err_ = Err(open_paren_token, "EOF found when parsing expression.",
+ "I was looking for a \")\" corresponding to this one.");
+ return scoped_ptr<ParseNode>();
+ }
+ if (!cur_token().IsScoperEqualTo(")")) {
+ *err_ = Err(open_paren_token, "Expected \")\" for expression",
+ "I was looking for a \")\" corresponding to this one.");
+ return scoped_ptr<ParseNode>();
+ }
+ cur_++; // Skip over )
+ return ret.Pass();
+}
+
+// unary_expression := "!" expression
+scoped_ptr<UnaryOpNode> Parser::ParseUnaryOp() {
+ scoped_ptr<UnaryOpNode> unary(new UnaryOpNode);
+
+ DCHECK(!at_end() && IsUnaryOperator(cur_token()));
+ const Token& op_token = cur_token();
+ unary->set_op(op_token);
+ cur_++;
+
+ if (at_end()) {
+ *err_ = Err(op_token, "Expected expression.",
+ "This operator needs something to operate on.");
+ return scoped_ptr<UnaryOpNode>();
+ }
+ unary->set_operand(ParseExpression().Pass());
+ if (has_error())
+ return scoped_ptr<UnaryOpNode>();
+ return unary.Pass();
+}
+
+Err Parser::MakeEOFError(const std::string& message,
+ const std::string& help) const {
+ if (tokens_.empty())
+ return Err(Location(NULL, 1, 1), message, help);
+
+ const Token& last = tokens_[tokens_.size() - 1];
+ return Err(last, message, help);
+}
diff --git a/chromium/tools/gn/parser.h b/chromium/tools/gn/parser.h
new file mode 100644
index 00000000000..252b801a682
--- /dev/null
+++ b/chromium/tools/gn/parser.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_PARSER_H_
+#define TOOLS_GN_PARSER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "tools/gn/err.h"
+#include "tools/gn/parse_tree.h"
+
+// Parses a series of tokens. The resulting AST will refer to the tokens passed
+// to the input, so the tokens an the file data they refer to must outlive your
+// use of the ParseNode.
+class Parser {
+ public:
+ // Will return a null pointer and set the err on error.
+ static scoped_ptr<ParseNode> Parse(const std::vector<Token>& tokens,
+ Err* err);
+
+ // Alternative to parsing that assumes the input is an expression.
+ static scoped_ptr<ParseNode> ParseExpression(const std::vector<Token>& tokens,
+ Err* err);
+
+ private:
+ // Vector must be valid for lifetime of call.
+ Parser(const std::vector<Token>& tokens, Err* err);
+ ~Parser();
+
+ scoped_ptr<AccessorNode> ParseAccessor();
+ scoped_ptr<BlockNode> ParseBlock(bool need_braces);
+ scoped_ptr<ConditionNode> ParseCondition();
+ scoped_ptr<ParseNode> ParseExpression();
+ scoped_ptr<ParseNode> ParseExpressionExceptBinaryOperators();
+ scoped_ptr<FunctionCallNode> ParseFunctionCall();
+ scoped_ptr<ListNode> ParseList(const Token& expected_begin,
+ const Token& expected_end);
+ scoped_ptr<ParseNode> ParseParenExpression();
+ scoped_ptr<UnaryOpNode> ParseUnaryOp();
+
+ bool IsToken(Token::Type type, char* str) const;
+
+ // Gets an error corresponding to the last token. When we hit an EOF
+ // usually we've already gone beyond the end (or maybe there are no tokens)
+ // so there is some tricky logic to report this.
+ Err MakeEOFError(const std::string& message,
+ const std::string& help = std::string()) const;
+
+ const Token& cur_token() const { return tokens_[cur_]; }
+
+ bool done() const { return at_end() || has_error(); }
+ bool at_end() const { return cur_ >= tokens_.size(); }
+ bool has_error() const { return err_->has_error(); }
+
+ const Token& next_token() const { return tokens_[cur_ + 1]; }
+ bool has_next_token() const { return cur_ + 1 < tokens_.size(); }
+
+ const std::vector<Token>& tokens_;
+
+ Err* err_;
+
+ // Current index into the tokens.
+ size_t cur_;
+
+ FRIEND_TEST_ALL_PREFIXES(Parser, BinaryOp);
+ FRIEND_TEST_ALL_PREFIXES(Parser, Block);
+ FRIEND_TEST_ALL_PREFIXES(Parser, Condition);
+ FRIEND_TEST_ALL_PREFIXES(Parser, Expression);
+ FRIEND_TEST_ALL_PREFIXES(Parser, FunctionCall);
+ FRIEND_TEST_ALL_PREFIXES(Parser, List);
+ FRIEND_TEST_ALL_PREFIXES(Parser, ParenExpression);
+ FRIEND_TEST_ALL_PREFIXES(Parser, UnaryOp);
+
+ DISALLOW_COPY_AND_ASSIGN(Parser);
+};
+
+#endif // TOOLS_GN_PARSER_H_
diff --git a/chromium/tools/gn/parser_unittest.cc b/chromium/tools/gn/parser_unittest.cc
new file mode 100644
index 00000000000..3fd8ebe28db
--- /dev/null
+++ b/chromium/tools/gn/parser_unittest.cc
@@ -0,0 +1,329 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <iostream>
+#include <sstream>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/parser.h"
+#include "tools/gn/tokenizer.h"
+
+namespace {
+
+bool GetTokens(const InputFile* input, std::vector<Token>* result) {
+ result->clear();
+ Err err;
+ *result = Tokenizer::Tokenize(input, &err);
+ return !err.has_error();
+}
+
+bool IsIdentifierEqual(const ParseNode* node, const char* val) {
+ if (!node)
+ return false;
+ const IdentifierNode* ident = node->AsIdentifier();
+ if (!ident)
+ return false;
+ return ident->value().value() == val;
+}
+
+bool IsLiteralEqual(const ParseNode* node, const char* val) {
+ if (!node)
+ return false;
+ const LiteralNode* lit = node->AsLiteral();
+ if (!lit)
+ return false;
+ return lit->value().value() == val;
+}
+
+// Returns true if the given node as a simple assignment to a given value.
+bool IsAssignment(const ParseNode* node, const char* ident, const char* value) {
+ if (!node)
+ return false;
+ const BinaryOpNode* binary = node->AsBinaryOp();
+ if (!binary)
+ return false;
+ return binary->op().IsOperatorEqualTo("=") &&
+ IsIdentifierEqual(binary->left(), ident) &&
+ IsLiteralEqual(binary->right(), value);
+}
+
+// Returns true if the given node is a block with one assignment statement.
+bool IsBlockWithAssignment(const ParseNode* node,
+ const char* ident, const char* value) {
+ if (!node)
+ return false;
+ const BlockNode* block = node->AsBlock();
+ if (!block)
+ return false;
+ if (block->statements().size() != 1)
+ return false;
+ return IsAssignment(block->statements()[0], ident, value);
+}
+
+void DoParserPrintTest(const char* input, const char* expected) {
+ std::vector<Token> tokens;
+ InputFile input_file(SourceFile("/test"));
+ input_file.SetContents(input);
+ ASSERT_TRUE(GetTokens(&input_file, &tokens));
+
+ Err err;
+ scoped_ptr<ParseNode> result = Parser::Parse(tokens, &err);
+ ASSERT_TRUE(result);
+
+ std::ostringstream collector;
+ result->Print(collector, 0);
+
+ EXPECT_EQ(expected, collector.str());
+}
+
+// Expects the tokenizer or parser to identify an error at the given line and
+// character.
+void DoParserErrorTest(const char* input, int err_line, int err_char) {
+ InputFile input_file(SourceFile("/test"));
+ input_file.SetContents(input);
+
+ Err err;
+ std::vector<Token> tokens = Tokenizer::Tokenize(&input_file, &err);
+ if (!err.has_error()) {
+ scoped_ptr<ParseNode> result = Parser::Parse(tokens, &err);
+ ASSERT_FALSE(result);
+ ASSERT_TRUE(err.has_error());
+ }
+
+ EXPECT_EQ(err_line, err.location().line_number());
+ EXPECT_EQ(err_char, err.location().char_offset());
+}
+
+} // namespace
+
+TEST(Parser, BinaryOp) {
+ std::vector<Token> tokens;
+
+ // Simple set expression.
+ InputFile expr_input(SourceFile("/test"));
+ expr_input.SetContents("a=2");
+ ASSERT_TRUE(GetTokens(&expr_input, &tokens));
+ Err err;
+ Parser set(tokens, &err);
+ scoped_ptr<ParseNode> expr = set.ParseExpression();
+ ASSERT_TRUE(expr);
+
+ const BinaryOpNode* binary_op = expr->AsBinaryOp();
+ ASSERT_TRUE(binary_op);
+
+ EXPECT_TRUE(binary_op->left()->AsIdentifier());
+
+ EXPECT_TRUE(binary_op->op().type() == Token::OPERATOR);
+ EXPECT_TRUE(binary_op->op().value() == "=");
+
+ EXPECT_TRUE(binary_op->right()->AsLiteral());
+}
+
+TEST(Parser, Condition) {
+ std::vector<Token> tokens;
+
+ InputFile cond_input(SourceFile("/test"));
+ cond_input.SetContents("if(1) { a = 2 }");
+ ASSERT_TRUE(GetTokens(&cond_input, &tokens));
+ Err err;
+ Parser simple_if(tokens, &err);
+ scoped_ptr<ConditionNode> cond = simple_if.ParseCondition();
+ ASSERT_TRUE(cond);
+
+ EXPECT_TRUE(IsLiteralEqual(cond->condition(), "1"));
+ EXPECT_FALSE(cond->if_false()); // No else block.
+ EXPECT_TRUE(IsBlockWithAssignment(cond->if_true(), "a", "2"));
+
+ // Now try a complicated if/else if/else one.
+ InputFile complex_if_input(SourceFile("/test"));
+ complex_if_input.SetContents(
+ "if(1) { a = 2 } else if (0) { a = 3 } else { a = 4 }");
+ ASSERT_TRUE(GetTokens(&complex_if_input, &tokens));
+ Parser complex_if(tokens, &err);
+ cond = complex_if.ParseCondition();
+ ASSERT_TRUE(cond);
+
+ EXPECT_TRUE(IsLiteralEqual(cond->condition(), "1"));
+ EXPECT_TRUE(IsBlockWithAssignment(cond->if_true(), "a", "2"));
+
+ ASSERT_TRUE(cond->if_false());
+ const ConditionNode* nested_cond = cond->if_false()->AsConditionNode();
+ ASSERT_TRUE(nested_cond);
+ EXPECT_TRUE(IsLiteralEqual(nested_cond->condition(), "0"));
+ EXPECT_TRUE(IsBlockWithAssignment(nested_cond->if_true(), "a", "3"));
+ EXPECT_TRUE(IsBlockWithAssignment(nested_cond->if_false(), "a", "4"));
+}
+
+TEST(Parser, FunctionCall) {
+ const char* input = "foo(a, 1, 2,) bar()";
+ const char* expected =
+ "BLOCK\n"
+ " FUNCTION(foo)\n"
+ " LIST\n"
+ " IDENTIFIER(a)\n"
+ " LITERAL(1)\n"
+ " LITERAL(2)\n"
+ " FUNCTION(bar)\n"
+ " LIST\n";
+ DoParserPrintTest(input, expected);
+}
+
+TEST(Parser, ParenExpression) {
+ const char* input = "(foo(1)) + (a + b)";
+ const char* expected =
+ "BLOCK\n"
+ " BINARY(+)\n"
+ " FUNCTION(foo)\n"
+ " LIST\n"
+ " LITERAL(1)\n"
+ " BINARY(+)\n"
+ " IDENTIFIER(a)\n"
+ " IDENTIFIER(b)\n";
+ DoParserPrintTest(input, expected);
+ DoParserErrorTest("(a +", 1, 4);
+}
+
+TEST(Parser, UnaryOp) {
+ std::vector<Token> tokens;
+
+ InputFile ident_input(SourceFile("/test"));
+ ident_input.SetContents("!foo");
+ ASSERT_TRUE(GetTokens(&ident_input, &tokens));
+ Err err;
+ Parser ident(tokens, &err);
+ scoped_ptr<UnaryOpNode> op = ident.ParseUnaryOp();
+
+ ASSERT_TRUE(op);
+ EXPECT_TRUE(op->op().type() == Token::OPERATOR);
+ EXPECT_TRUE(op->op().value() == "!");
+}
+
+TEST(Parser, CompleteFunction) {
+ const char* input =
+ "cc_test(\"foo\") {\n"
+ " sources = [\n"
+ " \"foo.cc\",\n"
+ " \"foo.h\"\n"
+ " ]\n"
+ " dependencies = [\n"
+ " \"base\"\n"
+ " ]\n"
+ "}\n";
+ const char* expected =
+ "BLOCK\n"
+ " FUNCTION(cc_test)\n"
+ " LIST\n"
+ " LITERAL(\"foo\")\n"
+ " BLOCK\n"
+ " BINARY(=)\n"
+ " IDENTIFIER(sources)\n"
+ " LIST\n"
+ " LITERAL(\"foo.cc\")\n"
+ " LITERAL(\"foo.h\")\n"
+ " BINARY(=)\n"
+ " IDENTIFIER(dependencies)\n"
+ " LIST\n"
+ " LITERAL(\"base\")\n";
+ DoParserPrintTest(input, expected);
+}
+
+TEST(Parser, FunctionWithConditional) {
+ const char* input =
+ "cc_test(\"foo\") {\n"
+ " sources = [\"foo.cc\"]\n"
+ " if (OS == \"mac\") {\n"
+ " sources += \"bar.cc\"\n"
+ " } else if (OS == \"win\") {\n"
+ " sources -= [\"asd.cc\", \"foo.cc\"]\n"
+ " } else {\n"
+ " dependencies += [\"bar.cc\"]\n"
+ " }\n"
+ "}\n";
+ const char* expected =
+ "BLOCK\n"
+ " FUNCTION(cc_test)\n"
+ " LIST\n"
+ " LITERAL(\"foo\")\n"
+ " BLOCK\n"
+ " BINARY(=)\n"
+ " IDENTIFIER(sources)\n"
+ " LIST\n"
+ " LITERAL(\"foo.cc\")\n"
+ " CONDITION\n"
+ " BINARY(==)\n"
+ " IDENTIFIER(OS)\n"
+ " LITERAL(\"mac\")\n"
+ " BLOCK\n"
+ " BINARY(+=)\n"
+ " IDENTIFIER(sources)\n"
+ " LITERAL(\"bar.cc\")\n"
+ " CONDITION\n"
+ " BINARY(==)\n"
+ " IDENTIFIER(OS)\n"
+ " LITERAL(\"win\")\n"
+ " BLOCK\n"
+ " BINARY(-=)\n"
+ " IDENTIFIER(sources)\n"
+ " LIST\n"
+ " LITERAL(\"asd.cc\")\n"
+ " LITERAL(\"foo.cc\")\n"
+ " BLOCK\n"
+ " BINARY(+=)\n"
+ " IDENTIFIER(dependencies)\n"
+ " LIST\n"
+ " LITERAL(\"bar.cc\")\n";
+ DoParserPrintTest(input, expected);
+}
+
+TEST(Parser, NestedBlocks) {
+ const char* input = "{cc_test(\"foo\") {{foo=1}{}}}";
+ const char* expected =
+ "BLOCK\n"
+ " BLOCK\n"
+ " FUNCTION(cc_test)\n"
+ " LIST\n"
+ " LITERAL(\"foo\")\n"
+ " BLOCK\n"
+ " BLOCK\n"
+ " BINARY(=)\n"
+ " IDENTIFIER(foo)\n"
+ " LITERAL(1)\n"
+ " BLOCK\n";
+ DoParserPrintTest(input, expected);
+}
+
+TEST(Parser, List) {
+ const char* input = "[] a = [1,asd,] b = [1, 2+3 - foo]";
+ const char* expected =
+ "BLOCK\n"
+ " LIST\n"
+ " BINARY(=)\n"
+ " IDENTIFIER(a)\n"
+ " LIST\n"
+ " LITERAL(1)\n"
+ " IDENTIFIER(asd)\n"
+ " BINARY(=)\n"
+ " IDENTIFIER(b)\n"
+ " LIST\n"
+ " LITERAL(1)\n"
+ " BINARY(+)\n"
+ " LITERAL(2)\n"
+ " BINARY(-)\n"
+ " LITERAL(3)\n"
+ " IDENTIFIER(foo)\n";
+ DoParserPrintTest(input, expected);
+
+ DoParserErrorTest("[a, 2+,]", 1, 7);
+ DoParserErrorTest("[,]", 1, 2);
+ DoParserErrorTest("[a,,]", 1, 4);
+}
+
+TEST(Parser, UnterminatedBlock) {
+ DoParserErrorTest("hello {", 1, 7);
+}
+
+TEST(Parser, BadlyTerminatedNumber) {
+ DoParserErrorTest("1234z", 1, 5);
+}
diff --git a/chromium/tools/gn/path_output.cc b/chromium/tools/gn/path_output.cc
new file mode 100644
index 00000000000..f67b3d4d64c
--- /dev/null
+++ b/chromium/tools/gn/path_output.cc
@@ -0,0 +1,116 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/path_output.h"
+
+#include "build/build_config.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/output_file.h"
+#include "tools/gn/string_utils.h"
+
+PathOutput::PathOutput(const SourceDir& current_dir,
+ EscapingMode escaping,
+ bool convert_slashes)
+ : current_dir_(current_dir) {
+ inverse_current_dir_ = InvertDir(current_dir_);
+
+ options_.mode = escaping;
+ options_.convert_slashes = convert_slashes;
+ options_.inhibit_quoting = false;
+
+ if (convert_slashes)
+ ConvertPathToSystem(&inverse_current_dir_);
+}
+
+PathOutput::~PathOutput() {
+}
+
+void PathOutput::WriteFile(std::ostream& out, const SourceFile& file) const {
+ WritePathStr(out, file.value());
+}
+
+void PathOutput::WriteDir(std::ostream& out,
+ const SourceDir& dir,
+ DirSlashEnding slash_ending) const {
+ if (dir.value() == "/") {
+ // Writing system root is always a slash (this will normally only come up
+ // on Posix systems).
+ out << "/";
+ } else if (dir.value() == "//") {
+ // Writing out the source root.
+ if (slash_ending == DIR_NO_LAST_SLASH) {
+ // The inverse_current_dir_ will contain a [back]slash at the end, so we
+ // can't just write it out.
+ if (inverse_current_dir_.empty()) {
+ out << ".";
+ } else {
+ out.write(inverse_current_dir_.c_str(),
+ inverse_current_dir_.size() - 1);
+ }
+ } else {
+ if (inverse_current_dir_.empty())
+ out << "./";
+ else
+ out << inverse_current_dir_;
+ }
+ } else if (slash_ending == DIR_INCLUDE_LAST_SLASH) {
+ WritePathStr(out, dir.value());
+ } else {
+ // DIR_NO_LAST_SLASH mode, just trim the last char.
+ WritePathStr(out, base::StringPiece(dir.value().data(),
+ dir.value().size() - 1));
+ }
+}
+
+void PathOutput::WriteFile(std::ostream& out, const OutputFile& file) const {
+ // Here we assume that the path is already preprocessed.
+ EscapeStringToStream(out, file.value(), options_);
+}
+
+void PathOutput::WriteSourceRelativeString(
+ std::ostream& out,
+ const base::StringPiece& str) const {
+ // Input begins with two slashes, is relative to source root. Strip off
+ // the two slashes when cat-ing it.
+ if (options_.mode == ESCAPE_SHELL) {
+ // Shell escaping needs an intermediate string since it may end up
+ // quoting the whole thing. On Windows, the slashes may already be
+ // converted to backslashes in inverse_current_dir_, but we assume that on
+ // Windows the escaper won't try to then escape the preconverted
+ // backslashes and will just pass them, so this is fine.
+ std::string intermediate;
+ intermediate.reserve(inverse_current_dir_.size() + str.size());
+ intermediate.assign(inverse_current_dir_.c_str(),
+ inverse_current_dir_.size());
+ intermediate.append(str.data(), str.size());
+
+ EscapeStringToStream(out,
+ base::StringPiece(intermediate.c_str(), intermediate.size()),
+ options_);
+ } else {
+ // Ninja (and none) escaping can avoid the intermediate string and
+ // reprocessing of the inverse_current_dir_.
+ out << inverse_current_dir_;
+ EscapeStringToStream(out, str, options_);
+ }
+}
+
+void PathOutput::WritePathStr(std::ostream& out,
+ const base::StringPiece& str) const {
+ DCHECK(str.size() > 0 && str[0] == '/');
+
+ if (str.size() >= 2 && str[1] == '/') {
+ WriteSourceRelativeString(out, str.substr(2));
+ } else {
+ // Input begins with one slash, don't write the current directory since
+ // it's system-absolute.
+#if defined(OS_WIN)
+ // On Windows, trim the leading slash, since the input for absolute
+ // paths will look like "/C:/foo/bar.txt".
+ EscapeStringToStream(out, str.substr(1), options_);
+#else
+ EscapeStringToStream(out, str, options_);
+#endif
+ }
+}
diff --git a/chromium/tools/gn/path_output.h b/chromium/tools/gn/path_output.h
new file mode 100644
index 00000000000..00bdbeece6e
--- /dev/null
+++ b/chromium/tools/gn/path_output.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_PATH_OUTPUT_H_
+#define TOOLS_GN_PATH_OUTPUT_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/strings/string_piece.h"
+#include "tools/gn/escape.h"
+#include "tools/gn/source_dir.h"
+
+class OutputFile;
+class SourceFile;
+
+// Writes file names to streams assuming a certain input directory and
+// escaping rules. This gives us a central place for managing this state.
+class PathOutput {
+ public:
+ // Controls whether writing directory names include the trailing slash.
+ // Often we don't want the trailing slash when writing out to a command line,
+ // especially on Windows where it's a backslash and might be interpreted as
+ // escaping the thing following it.
+ enum DirSlashEnding {
+ DIR_INCLUDE_LAST_SLASH,
+ DIR_NO_LAST_SLASH,
+ };
+
+ PathOutput(const SourceDir& current_dir,
+ EscapingMode escaping,
+ bool convert_slashes);
+ ~PathOutput();
+
+ // Read-only since inverse_current_dir_ is computed depending on this.
+ EscapingMode escaping_mode() const { return options_.mode; }
+
+ // When true, converts slashes to the system-type path separators (on
+ // Windows, this is a backslash, this is a NOP otherwise).
+ //
+ // Read-only since inverse_current_dir_ is computed depending on this.
+ bool convert_slashes_to_system() const { return options_.convert_slashes; }
+
+ // When the output escaping is ESCAPE_SHELL, the escaper will normally put
+ // quotes around suspect things. If this value is set to true, we'll disable
+ // the quoting feature. This means that in ESCAPE_SHELL mode, strings with
+ // spaces in them qon't be quoted. This mode is for when quoting is done at
+ // some higher-level. Defaults to false.
+ bool inhibit_quoting() const { return options_.inhibit_quoting; }
+ void set_inhibit_quoting(bool iq) { options_.inhibit_quoting = iq; }
+
+ void WriteFile(std::ostream& out, const SourceFile& file) const;
+ void WriteFile(std::ostream& out, const OutputFile& file) const;
+ void WriteDir(std::ostream& out,
+ const SourceDir& dir,
+ DirSlashEnding slash_ending) const;
+
+ // Backend for WriteFile and WriteDir. This appends the given file or
+ // directory string to the file.
+ void WritePathStr(std::ostream& out, const base::StringPiece& str) const;
+
+ private:
+ // Takes the given string and writes it out, appending to the inverse
+ // current dir. This assumes leading slashes have been trimmed.
+ void WriteSourceRelativeString(std::ostream& out,
+ const base::StringPiece& str) const;
+
+ SourceDir current_dir_;
+
+ // Uses system slashes if convert_slashes_to_system_.
+ std::string inverse_current_dir_;
+
+ // Since the inverse_current_dir_ depends on some of these, we don't expose
+ // this directly to modification.
+ EscapeOptions options_;
+};
+
+#endif // TOOLS_GN_PATH_OUTPUT_H_
diff --git a/chromium/tools/gn/path_output_unittest.cc b/chromium/tools/gn/path_output_unittest.cc
new file mode 100644
index 00000000000..5133b793fac
--- /dev/null
+++ b/chromium/tools/gn/path_output_unittest.cc
@@ -0,0 +1,193 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <sstream>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/path_output.h"
+#include "tools/gn/source_dir.h"
+#include "tools/gn/source_file.h"
+
+TEST(PathOutput, Basic) {
+ SourceDir build_dir("//out/Debug/");
+ PathOutput writer(build_dir, ESCAPE_NONE, false);
+ {
+ // Normal source-root path.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo/bar.cc"));
+ EXPECT_EQ("../../foo/bar.cc", out.str());
+ }
+ {
+ // File in the root dir.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo.cc"));
+ EXPECT_EQ("../../foo.cc", out.str());
+ }
+#if defined(OS_WIN)
+ {
+ // System-absolute path.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("/C:/foo/bar.cc"));
+ EXPECT_EQ("C:/foo/bar.cc", out.str());
+ }
+#else
+ {
+ // System-absolute path.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("/foo/bar.cc"));
+ EXPECT_EQ("/foo/bar.cc", out.str());
+ }
+#endif
+}
+
+// Same as basic but the output dir is the root.
+TEST(PathOutput, BasicInRoot) {
+ SourceDir build_dir("//");
+ PathOutput writer(build_dir, ESCAPE_NONE, false);
+ {
+ // Normal source-root path.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo/bar.cc"));
+ EXPECT_EQ("foo/bar.cc", out.str());
+ }
+ {
+ // File in the root dir.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo.cc"));
+ EXPECT_EQ("foo.cc", out.str());
+ }
+}
+
+TEST(PathOutput, NinjaEscaping) {
+ SourceDir build_dir("//out/Debug/");
+ PathOutput writer(build_dir, ESCAPE_NINJA, false);
+ {
+ // Spaces and $ in filenames.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo/foo bar$.cc"));
+ EXPECT_EQ("../../foo/foo$ bar$$.cc", out.str());
+ }
+ {
+ // Not other weird stuff
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo/\"foo\\bar\".cc"));
+ EXPECT_EQ("../../foo/\"foo\\bar\".cc", out.str());
+ }
+}
+
+TEST(PathOutput, ShellEscaping) {
+ SourceDir build_dir("//out/Debug/");
+ PathOutput writer(build_dir, ESCAPE_SHELL, false);
+ {
+ // Spaces in filenames should get quoted.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
+ EXPECT_EQ("\"../../foo/foo bar.cc\"", out.str());
+ }
+ {
+ // Quotes should get blackslash-escaped.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo/\"foobar\".cc"));
+ EXPECT_EQ("../../foo/\\\"foobar\\\".cc", out.str());
+ }
+ {
+ // Backslashes should get escaped on non-Windows and preserved on Windows.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo\\bar.cc"));
+#if defined(OS_WIN)
+ EXPECT_EQ("../../foo\\bar.cc", out.str());
+#else
+ EXPECT_EQ("../../foo\\\\bar.cc", out.str());
+#endif
+ }
+}
+
+TEST(PathOutput, SlashConversion) {
+ SourceDir build_dir("//out/Debug/");
+ PathOutput writer(build_dir, ESCAPE_NINJA, true);
+ {
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo/bar.cc"));
+#if defined(OS_WIN)
+ EXPECT_EQ("..\\..\\foo\\bar.cc", out.str());
+#else
+ EXPECT_EQ("../../foo/bar.cc", out.str());
+#endif
+ }
+}
+
+TEST(PathOutput, InhibitQuoting) {
+ SourceDir build_dir("//out/Debug/");
+ PathOutput writer(build_dir, ESCAPE_SHELL, false);
+ writer.set_inhibit_quoting(true);
+ {
+ // We should get unescaped spaces in the output with no quotes.
+ std::ostringstream out;
+ writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
+ EXPECT_EQ("../../foo/foo bar.cc", out.str());
+ }
+}
+
+TEST(PathOutput, WriteDir) {
+ {
+ SourceDir build_dir("//out/Debug/");
+ PathOutput writer(build_dir, ESCAPE_NINJA, false);
+ {
+ std::ostringstream out;
+ writer.WriteDir(out, SourceDir("//foo/bar/"),
+ PathOutput::DIR_INCLUDE_LAST_SLASH);
+ EXPECT_EQ("../../foo/bar/", out.str());
+ }
+ {
+ std::ostringstream out;
+ writer.WriteDir(out, SourceDir("//foo/bar/"),
+ PathOutput::DIR_NO_LAST_SLASH);
+ EXPECT_EQ("../../foo/bar", out.str());
+ }
+
+ // Output source root dir.
+ {
+ std::ostringstream out;
+ writer.WriteDir(out, SourceDir("//"),
+ PathOutput::DIR_INCLUDE_LAST_SLASH);
+ EXPECT_EQ("../../", out.str());
+ }
+ {
+ std::ostringstream out;
+ writer.WriteDir(out, SourceDir("//"),
+ PathOutput::DIR_NO_LAST_SLASH);
+ EXPECT_EQ("../..", out.str());
+ }
+
+ // Output system root dir.
+ {
+ std::ostringstream out;
+ writer.WriteDir(out, SourceDir("/"),
+ PathOutput::DIR_INCLUDE_LAST_SLASH);
+ EXPECT_EQ("/", out.str());
+ }
+ {
+ std::ostringstream out;
+ writer.WriteDir(out, SourceDir("/"),
+ PathOutput::DIR_NO_LAST_SLASH);
+ EXPECT_EQ("/", out.str());
+ }
+ }
+ {
+ // Empty build dir writer.
+ PathOutput root_writer(SourceDir("//"), ESCAPE_NINJA, false);
+ {
+ std::ostringstream out;
+ root_writer.WriteDir(out, SourceDir("//"),
+ PathOutput::DIR_INCLUDE_LAST_SLASH);
+ EXPECT_EQ("./", out.str());
+ }
+ {
+ std::ostringstream out;
+ root_writer.WriteDir(out, SourceDir("//"),
+ PathOutput::DIR_NO_LAST_SLASH);
+ EXPECT_EQ(".", out.str());
+ }
+ }
+}
diff --git a/chromium/tools/gn/pattern.cc b/chromium/tools/gn/pattern.cc
new file mode 100644
index 00000000000..cc08b2ce567
--- /dev/null
+++ b/chromium/tools/gn/pattern.cc
@@ -0,0 +1,185 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/pattern.h"
+
+#include "tools/gn/value.h"
+
+namespace {
+
+void ParsePattern(const std::string& s, std::vector<Pattern::Subrange>* out) {
+ // Set when the last subrange is a literal so we can just append when we
+ // find another literal.
+ Pattern::Subrange* last_literal = NULL;
+
+ for (size_t i = 0; i < s.size(); i++) {
+ if (s[i] == '*') {
+ // Don't allow two **.
+ if (out->size() == 0 ||
+ (*out)[out->size() - 1].type != Pattern::Subrange::ANYTHING)
+ out->push_back(Pattern::Subrange(Pattern::Subrange::ANYTHING));
+ last_literal = NULL;
+ } else if (s[i] == '\\') {
+ if (i < s.size() - 1 && s[i + 1] == 'b') {
+ // "\b" means path boundary.
+ i++;
+ out->push_back(Pattern::Subrange(Pattern::Subrange::PATH_BOUNDARY));
+ last_literal = NULL;
+ } else {
+ // Backslash + anything else means that literal char.
+ if (!last_literal) {
+ out->push_back(Pattern::Subrange(Pattern::Subrange::LITERAL));
+ last_literal = &(*out)[out->size() - 1];
+ }
+ if (i < s.size() - 1) {
+ i++;
+ last_literal->literal.push_back(s[i]);
+ } else {
+ // Single backslash at end, use literal backslash.
+ last_literal->literal.push_back('\\');
+ }
+ }
+ } else {
+ if (!last_literal) {
+ out->push_back(Pattern::Subrange(Pattern::Subrange::LITERAL));
+ last_literal = &(*out)[out->size() - 1];
+ }
+ last_literal->literal.push_back(s[i]);
+ }
+ }
+}
+
+} // namespace
+
+Pattern::Pattern(const std::string& s) {
+ ParsePattern(s, &subranges_);
+ is_suffix_ =
+ (subranges_.size() == 2 &&
+ subranges_[0].type == Subrange::ANYTHING &&
+ subranges_[1].type == Subrange::LITERAL);
+}
+
+Pattern::~Pattern() {
+}
+
+bool Pattern::MatchesString(const std::string& s) const {
+ // Empty pattern matches only empty string.
+ if (subranges_.empty())
+ return s.empty();
+
+ if (is_suffix_) {
+ const std::string& suffix = subranges_[1].literal;
+ if (suffix.size() > s.size())
+ return false; // Too short.
+ return s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
+ }
+
+ return RecursiveMatch(s, 0, 0, true);
+}
+
+// We assume the number of ranges is small so recursive is always reasonable.
+// Could be optimized to only be recursive for *.
+bool Pattern::RecursiveMatch(const std::string& s,
+ size_t begin_char,
+ size_t subrange_index,
+ bool allow_implicit_path_boundary) const {
+ if (subrange_index >= subranges_.size()) {
+ // Hit the end of our subranges, the text should also be at the end for a
+ // match.
+ return begin_char == s.size();
+ }
+
+ const Subrange& sr = subranges_[subrange_index];
+ switch (sr.type) {
+ case Subrange::LITERAL: {
+ if (s.size() - begin_char < sr.literal.size())
+ return false; // Not enough room.
+ if (s.compare(begin_char, sr.literal.size(), sr.literal) != 0)
+ return false; // Literal doesn't match.
+
+ // Recursively check the next one.
+ return RecursiveMatch(s, begin_char + sr.literal.size(),
+ subrange_index + 1, true);
+ }
+
+ case Subrange::PATH_BOUNDARY: {
+ // When we can accept an implicit path boundary, we have to check both
+ // a match of the literal and the implicit one.
+ if (allow_implicit_path_boundary &&
+ (begin_char == 0 || begin_char == s.size())) {
+ // At implicit path boundary, see if the rest of the pattern matches.
+ if (RecursiveMatch(s, begin_char, subrange_index + 1, false))
+ return true;
+ }
+
+ // Check for a literal "/".
+ if (begin_char < s.size() && s[begin_char] == '/') {
+ // At explicit boundary, see if the rest of the pattern matches.
+ if (RecursiveMatch(s, begin_char + 1, subrange_index + 1, true))
+ return true;
+ }
+ return false;
+ }
+
+ case Subrange::ANYTHING: {
+ if (subrange_index == subranges_.size() - 1)
+ return true; // * at the end, consider it matching.
+
+ size_t min_next_size = sr.MinSize();
+
+ // We don't care about exactly what matched as long as there was a match,
+ // so we can do this front-to-back. If we needed the match, we would
+ // normally want "*" to be greedy so would work backwards.
+ for (size_t i = begin_char; i < s.size() - min_next_size; i++) {
+ // Note: this could probably be faster by detecting the type of the
+ // next match in advance and checking for a match in this loop rather
+ // than doing a full recursive call for each character.
+ if (RecursiveMatch(s, i, subrange_index + 1, true))
+ return true;
+ }
+ return false;
+ }
+
+ default:
+ NOTREACHED();
+ }
+
+ return false;
+}
+
+PatternList::PatternList() {
+}
+
+PatternList::~PatternList() {
+}
+
+void PatternList::SetFromValue(const Value& v, Err* err) {
+ patterns_.clear();
+
+ if (v.type() != Value::LIST) {
+ *err = Err(v.origin(), "This value must be a list.");
+ return;
+ }
+
+ const std::vector<Value>& list = v.list_value();
+ for (size_t i = 0; i < list.size(); i++) {
+ if (!list[i].VerifyTypeIs(Value::STRING, err))
+ return;
+ patterns_.push_back(Pattern(list[i].string_value()));
+ }
+}
+
+bool PatternList::MatchesString(const std::string& s) const {
+ for (size_t i = 0; i < patterns_.size(); i++) {
+ if (patterns_[i].MatchesString(s))
+ return true;
+ }
+ return false;
+}
+
+bool PatternList::MatchesValue(const Value& v) const {
+ if (v.type() == Value::STRING)
+ return MatchesString(v.string_value());
+ return false;
+}
diff --git a/chromium/tools/gn/pattern.h b/chromium/tools/gn/pattern.h
new file mode 100644
index 00000000000..582cfeab8aa
--- /dev/null
+++ b/chromium/tools/gn/pattern.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_PATTERN_H_
+#define TOOLS_GN_PATTERN_H_
+
+#include <string>
+#include <vector>
+
+#include "tools/gn/value.h"
+
+class Pattern {
+ public:
+ struct Subrange {
+ enum Type {
+ LITERAL, // Matches exactly the contents of the string.
+ ANYTHING, // * (zero or more chars).
+ PATH_BOUNDARY // '/' or beginning of string.
+ };
+
+ Subrange(Type t, const std::string& l = std::string())
+ : type(t),
+ literal(l) {
+ }
+
+ // Returns the minimum number of chars that this subrange requires.
+ size_t MinSize() const {
+ switch (type) {
+ case LITERAL:
+ return literal.size();
+ case ANYTHING:
+ return 0;
+ case PATH_BOUNDARY:
+ return 0; // Can match beginning or end of string, which is 0 len.
+ default:
+ return 0;
+ }
+ }
+
+ Type type;
+
+ // When type == LITERAL this is the text to match.
+ std::string literal;
+ };
+
+ Pattern(const std::string& s);
+ ~Pattern();
+
+ // Returns true if the current pattern matches the given string.
+ bool MatchesString(const std::string& s) const;
+
+ private:
+ // allow_implicit_path_boundary determines if a path boundary should accept
+ // matches at the beginning or end of the string.
+ bool RecursiveMatch(const std::string& s,
+ size_t begin_char,
+ size_t subrange_index,
+ bool allow_implicit_path_boundary) const;
+
+ std::vector<Subrange> subranges_;
+
+ // Set to true when the subranges are "*foo" ("ANYTHING" followed by a
+ // literal). This covers most patterns so we optimize for this.
+ bool is_suffix_;
+};
+
+class PatternList {
+ public:
+ PatternList();
+ ~PatternList();
+
+ bool is_empty() const { return patterns_.empty(); }
+
+ // Initializes the pattern list from a give list of pattern strings. Sets
+ // |*err| on failure.
+ void SetFromValue(const Value& v, Err* err);
+
+ bool MatchesString(const std::string& s) const;
+ bool MatchesValue(const Value& v) const;
+
+ private:
+ std::vector<Pattern> patterns_;
+};
+
+#endif // TOOLS_GN_PATTERN_H_
diff --git a/chromium/tools/gn/pattern_unittest.cc b/chromium/tools/gn/pattern_unittest.cc
new file mode 100644
index 00000000000..e9ffea6c35f
--- /dev/null
+++ b/chromium/tools/gn/pattern_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/pattern.h"
+
+namespace {
+
+struct Case {
+ const char* pattern;
+ const char* candidate;
+ bool expected_match;
+};
+
+} // namespace
+
+TEST(Pattern, Matches) {
+ Case pattern_cases[] = {
+ // Empty pattern matches only empty string.
+ { "", "", true },
+ { "", "foo", false },
+ // Exact matches.
+ { "foo", "foo", true },
+ { "foo", "bar", false },
+ // Path boundaries.
+ { "\\b", "", true },
+ { "\\b", "/", true },
+ { "\\b\\b", "/", true },
+ { "\\b\\b\\b", "", false },
+ { "\\b\\b\\b", "/", true },
+ { "\\b", "//", false },
+ { "\\bfoo\\b", "foo", true },
+ { "\\bfoo\\b", "/foo/", true },
+ { "\\b\\bfoo", "/foo", true },
+ // *
+ { "*", "", true },
+ { "*", "foo", true },
+ { "*foo", "foo", true },
+ { "*foo", "gagafoo", true },
+ { "*foo", "gagafoob", false },
+ { "foo*bar", "foobar", true },
+ { "foo*bar", "foo-bar", true },
+ { "foo*bar", "foolalalalabar", true },
+ { "foo*bar", "foolalalalabaz", false },
+ { "*a*b*c*d*", "abcd", true },
+ { "*a*b*c*d*", "1a2b3c4d5", true },
+ { "*a*b*c*d*", "1a2b3c45", false },
+ { "*\\bfoo\\b*", "foo", true },
+ { "*\\bfoo\\b*", "/foo/", true },
+ { "*\\bfoo\\b*", "foob", false },
+ { "*\\bfoo\\b*", "lala/foo/bar/baz", true },
+ };
+ for (size_t i = 0; i < arraysize(pattern_cases); i++) {
+ const Case& c = pattern_cases[i];
+ Pattern pattern(c.pattern);
+ bool result = pattern.MatchesString(c.candidate);
+ EXPECT_EQ(c.expected_match, result) << i << ": \"" << c.pattern
+ << "\", \"" << c.candidate << "\"";
+ }
+}
diff --git a/chromium/tools/gn/scheduler.cc b/chromium/tools/gn/scheduler.cc
new file mode 100644
index 00000000000..05dd76fd60c
--- /dev/null
+++ b/chromium/tools/gn/scheduler.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/scheduler.h"
+
+#include "base/bind.h"
+#include "tools/gn/ninja_target_writer.h"
+#include "tools/gn/standard_out.h"
+
+Scheduler* g_scheduler = NULL;
+
+Scheduler::Scheduler()
+ : pool_(new base::SequencedWorkerPool(32, "worker_")),
+ input_file_manager_(new InputFileManager),
+ verbose_logging_(false),
+ work_count_(0),
+ is_failed_(false) {
+ g_scheduler = this;
+}
+
+Scheduler::~Scheduler() {
+ g_scheduler = NULL;
+}
+
+bool Scheduler::Run() {
+ runner_.Run();
+ pool_->Shutdown();
+ return !is_failed();
+}
+
+void Scheduler::Log(const std::string& verb, const std::string& msg) {
+ if (base::MessageLoop::current() == &main_loop_) {
+ LogOnMainThread(verb, msg);
+ } else {
+ // The run loop always joins on the sub threads, so the lifetime of this
+ // object outlives the invocations of this function, hence "unretained".
+ main_loop_.PostTask(FROM_HERE,
+ base::Bind(&Scheduler::LogOnMainThread,
+ base::Unretained(this), verb, msg));
+ }
+}
+
+void Scheduler::FailWithError(const Err& err) {
+ DCHECK(err.has_error());
+ {
+ base::AutoLock lock(lock_);
+
+ if (is_failed_)
+ return; // Ignore errors once we see one.
+ is_failed_ = true;
+ }
+
+ if (base::MessageLoop::current() == &main_loop_) {
+ FailWithErrorOnMainThread(err);
+ } else {
+ // The run loop always joins on the sub threads, so the lifetime of this
+ // object outlives the invocations of this function, hence "unretained".
+ main_loop_.PostTask(FROM_HERE,
+ base::Bind(&Scheduler::FailWithErrorOnMainThread,
+ base::Unretained(this), err));
+ }
+}
+
+void Scheduler::ScheduleWork(const base::Closure& work) {
+ IncrementWorkCount();
+ pool_->PostWorkerTaskWithShutdownBehavior(
+ FROM_HERE, base::Bind(&Scheduler::DoWork,
+ base::Unretained(this), work),
+ base::SequencedWorkerPool::BLOCK_SHUTDOWN);
+}
+
+void Scheduler::ScheduleTargetFileWrite(const Target* target) {
+ pool_->PostWorkerTaskWithShutdownBehavior(
+ FROM_HERE, base::Bind(&Scheduler::DoTargetFileWrite,
+ base::Unretained(this), target),
+ base::SequencedWorkerPool::BLOCK_SHUTDOWN);
+}
+
+void Scheduler::AddGenDependency(const base::FilePath& file) {
+ base::AutoLock lock(lock_);
+ gen_dependencies_.push_back(file);
+}
+
+std::vector<base::FilePath> Scheduler::GetGenDependencies() const {
+ base::AutoLock lock(lock_);
+ return gen_dependencies_;
+}
+
+void Scheduler::IncrementWorkCount() {
+ base::AtomicRefCountInc(&work_count_);
+}
+
+void Scheduler::DecrementWorkCount() {
+ if (!base::AtomicRefCountDec(&work_count_)) {
+ if (base::MessageLoop::current() == &main_loop_) {
+ OnComplete();
+ } else {
+ main_loop_.PostTask(FROM_HERE,
+ base::Bind(&Scheduler::OnComplete,
+ base::Unretained(this)));
+ }
+ }
+}
+
+void Scheduler::LogOnMainThread(const std::string& verb,
+ const std::string& msg) {
+ OutputString(verb, DECORATION_YELLOW);
+ OutputString(" " + msg + "\n");
+}
+
+void Scheduler::FailWithErrorOnMainThread(const Err& err) {
+ err.PrintToStdout();
+ runner_.Quit();
+}
+
+void Scheduler::DoTargetFileWrite(const Target* target) {
+ NinjaTargetWriter::RunAndWriteFile(target);
+}
+
+void Scheduler::DoWork(const base::Closure& closure) {
+ closure.Run();
+ DecrementWorkCount();
+}
+
+void Scheduler::OnComplete() {
+ // Should be called on the main thread.
+ DCHECK(base::MessageLoop::current() == main_loop());
+ runner_.Quit();
+}
diff --git a/chromium/tools/gn/scheduler.h b/chromium/tools/gn/scheduler.h
new file mode 100644
index 00000000000..4b2c0608742
--- /dev/null
+++ b/chromium/tools/gn/scheduler.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SCHEDULER_H_
+#define TOOLS_GN_SCHEDULER_H_
+
+#include "base/atomic_ref_count.h"
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "tools/gn/input_file_manager.h"
+
+class Target;
+
+// Maintains the thread pool and error state.
+class Scheduler {
+ public:
+ Scheduler();
+ ~Scheduler();
+
+ bool Run();
+
+ base::MessageLoop* main_loop() { return &main_loop_; }
+ base::SequencedWorkerPool* pool() { return pool_; }
+
+ InputFileManager* input_file_manager() { return input_file_manager_; }
+
+ bool verbose_logging() const { return verbose_logging_; }
+ void set_verbose_logging(bool v) { verbose_logging_ = v; }
+
+ // TODO(brettw) data race on this access (benign?).
+ bool is_failed() const { return is_failed_; }
+
+ void Log(const std::string& verb, const std::string& msg);
+ void FailWithError(const Err& err);
+
+ void ScheduleWork(const base::Closure& work);
+
+ void ScheduleTargetFileWrite(const Target* target);
+
+ // Declares that the given file was read and affected the build output.
+ //
+ // TODO(brettw) this is global rather than per-BuildSettings. If we
+ // start using >1 build settings, then we probably want this to take a
+ // BuildSettings object so we know the depdency on a per-build basis.
+ void AddGenDependency(const base::FilePath& file);
+ std::vector<base::FilePath> GetGenDependencies() const;
+
+ // We maintain a count of the things we need to do that works like a
+ // refcount. When this reaches 0, the program exits.
+ void IncrementWorkCount();
+ void DecrementWorkCount();
+
+ private:
+ void LogOnMainThread(const std::string& verb, const std::string& msg);
+ void FailWithErrorOnMainThread(const Err& err);
+
+ void DoTargetFileWrite(const Target* target);
+
+ void DoWork(const base::Closure& closure);
+
+ void OnComplete();
+
+ base::MessageLoop main_loop_;
+ scoped_refptr<base::SequencedWorkerPool> pool_;
+
+ scoped_refptr<InputFileManager> input_file_manager_;
+
+ base::RunLoop runner_;
+
+ bool verbose_logging_;
+
+ base::AtomicRefCount work_count_;
+
+ mutable base::Lock lock_;
+ bool is_failed_;
+
+ // Additional input dependencies. Protected by the lock.
+ std::vector<base::FilePath> gen_dependencies_;
+
+ DISALLOW_COPY_AND_ASSIGN(Scheduler);
+};
+
+extern Scheduler* g_scheduler;
+
+#endif // TOOLS_GN_SCHEDULER_H_
+
diff --git a/chromium/tools/gn/scope.cc b/chromium/tools/gn/scope.cc
new file mode 100644
index 00000000000..72664d7cc42
--- /dev/null
+++ b/chromium/tools/gn/scope.cc
@@ -0,0 +1,372 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/scope.h"
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "tools/gn/parse_tree.h"
+
+namespace {
+
+// FLags set in the mode_flags_ of a scope. If a bit is set, it applies
+// recursively to all dependent scopes.
+const unsigned kProcessingBuildConfigFlag = 1;
+const unsigned kProcessingDefaultBuildConfigFlag = 2;
+const unsigned kProcessingImportFlag = 4;
+
+} // namespace
+
+Scope::Scope(const Settings* settings)
+ : const_containing_(NULL),
+ mutable_containing_(NULL),
+ settings_(settings),
+ mode_flags_(0) {
+}
+
+Scope::Scope(Scope* parent)
+ : const_containing_(NULL),
+ mutable_containing_(parent),
+ settings_(parent->settings()),
+ mode_flags_(0) {
+}
+
+Scope::Scope(const Scope* parent)
+ : const_containing_(parent),
+ mutable_containing_(NULL),
+ settings_(parent->settings()),
+ mode_flags_(0) {
+}
+
+Scope::~Scope() {
+ STLDeleteContainerPairSecondPointers(target_defaults_.begin(),
+ target_defaults_.end());
+}
+
+const Value* Scope::GetValue(const base::StringPiece& ident,
+ bool counts_as_used) {
+ // First check for programatically-provided values.
+ for (ProviderSet::const_iterator i = programmatic_providers_.begin();
+ i != programmatic_providers_.end(); ++i) {
+ const Value* v = (*i)->GetProgrammaticValue(ident);
+ if (v)
+ return v;
+ }
+
+ RecordMap::iterator found = values_.find(ident);
+ if (found != values_.end()) {
+ if (counts_as_used)
+ found->second.used = true;
+ return &found->second.value;
+ }
+
+ // Search in the parent scope.
+ if (const_containing_)
+ return const_containing_->GetValue(ident);
+ if (mutable_containing_)
+ return mutable_containing_->GetValue(ident, counts_as_used);
+ return NULL;
+}
+
+Value* Scope::GetValueForcedToCurrentScope(const base::StringPiece& ident,
+ const ParseNode* set_node) {
+ RecordMap::iterator found = values_.find(ident);
+ if (found != values_.end())
+ return &found->second.value; // Already have in the current scope.
+
+ // Search in the parent scope.
+ if (containing()) {
+ const Value* in_containing = containing()->GetValue(ident);
+ if (in_containing) {
+ // Promote to current scope.
+ return SetValue(ident, *in_containing, set_node);
+ }
+ }
+ return NULL;
+}
+
+const Value* Scope::GetValue(const base::StringPiece& ident) const {
+ RecordMap::const_iterator found = values_.find(ident);
+ if (found != values_.end())
+ return &found->second.value;
+ if (containing())
+ return containing()->GetValue(ident);
+ return NULL;
+}
+
+Value* Scope::SetValue(const base::StringPiece& ident,
+ const Value& v,
+ const ParseNode* set_node) {
+ Record& r = values_[ident]; // Clears any existing value.
+ r.value = v;
+ r.value.set_origin(set_node);
+ return &r.value;
+}
+
+bool Scope::AddTemplate(const std::string& name, const FunctionCallNode* decl) {
+ if (GetTemplate(name))
+ return false;
+ templates_[name] = decl;
+ return true;
+}
+
+const FunctionCallNode* Scope::GetTemplate(const std::string& name) const {
+ TemplateMap::const_iterator found = templates_.find(name);
+ if (found != templates_.end())
+ return found->second;
+ if (containing())
+ return containing()->GetTemplate(name);
+ return NULL;
+}
+
+void Scope::MarkUsed(const base::StringPiece& ident) {
+ RecordMap::iterator found = values_.find(ident);
+ if (found == values_.end()) {
+ NOTREACHED();
+ return;
+ }
+ found->second.used = true;
+}
+
+void Scope::MarkUnused(const base::StringPiece& ident) {
+ RecordMap::iterator found = values_.find(ident);
+ if (found == values_.end()) {
+ NOTREACHED();
+ return;
+ }
+ found->second.used = false;
+}
+
+bool Scope::IsSetButUnused(const base::StringPiece& ident) const {
+ RecordMap::const_iterator found = values_.find(ident);
+ if (found != values_.end()) {
+ if (!found->second.used) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Scope::CheckForUnusedVars(Err* err) const {
+ for (RecordMap::const_iterator i = values_.begin();
+ i != values_.end(); ++i) {
+ if (!i->second.used) {
+ std::string help = "You set the variable \"" + i->first.as_string() +
+ "\" here and it was unused before it went\nout of scope.";
+
+ const BinaryOpNode* binary = i->second.value.origin()->AsBinaryOp();
+ if (binary) {
+ // Make a nicer error message for normal var sets.
+ *err = Err(binary->left()->GetRange(), "Assignment had no effect.",
+ help);
+ } else {
+ // This will happen for internally-generated variables.
+ *err = Err(i->second.value.origin(), "Assignment had no effect.", help);
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
+void Scope::GetCurrentScopeValues(KeyValueVector* output) const {
+ output->reserve(values_.size());
+ for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) {
+ output->push_back(std::make_pair(i->first, i->second.value));
+ }
+}
+
+bool Scope::NonRecursiveMergeTo(Scope* dest,
+ const ParseNode* node_for_err,
+ const char* desc_for_err,
+ Err* err) const {
+ // Values.
+ for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) {
+ const Value* existing_value = dest->GetValue(i->first);
+ if (existing_value) {
+ // Value present in both the source and the dest.
+ std::string desc_string(desc_for_err);
+ *err = Err(node_for_err, "Value collision.",
+ "This " + desc_string + " contains \"" + i->first.as_string() + "\"");
+ err->AppendSubErr(Err(i->second.value, "defined here.",
+ "Which would clobber the one in your current scope"));
+ err->AppendSubErr(Err(*existing_value, "defined here.",
+ "Executing " + desc_string + " should not conflict with anything "
+ "in the current\nscope."));
+ return false;
+ }
+ dest->values_[i->first] = i->second;
+ }
+
+ // Target defaults are owning pointers.
+ for (NamedScopeMap::const_iterator i = target_defaults_.begin();
+ i != target_defaults_.end(); ++i) {
+ if (dest->GetTargetDefaults(i->first)) {
+ // TODO(brettw) it would be nice to know the origin of a
+ // set_target_defaults so we can give locations for the colliding target
+ // defaults.
+ std::string desc_string(desc_for_err);
+ *err = Err(node_for_err, "Target defaults collision.",
+ "This " + desc_string + " contains target defaults for\n"
+ "\"" + i->first + "\" which would clobber one for the\n"
+ "same target type in your current scope. It's unfortunate that I'm "
+ "too stupid\nto tell you the location of where the target defaults "
+ "were set. Usually\nthis happens in the BUILDCONFIG.gn file.");
+ return false;
+ }
+
+ Scope* s = new Scope(settings_);
+ i->second->NonRecursiveMergeTo(s, node_for_err, "<SHOULDN'T HAPPEN>", err);
+ dest->target_defaults_[i->first] = s;
+ }
+
+ // Sources assignment filter.
+ if (sources_assignment_filter_) {
+ if (dest->GetSourcesAssignmentFilter()) {
+ // Sources assignment filter present in both the source and the dest.
+ std::string desc_string(desc_for_err);
+ *err = Err(node_for_err, "Assignment filter collision.",
+ "The " + desc_string + " contains a sources_assignment_filter which\n"
+ "would clobber the one in your current scope.");
+ return false;
+ }
+ dest->sources_assignment_filter_.reset(
+ new PatternList(*sources_assignment_filter_));
+ }
+
+ // Templates.
+ for (TemplateMap::const_iterator i = templates_.begin();
+ i != templates_.end(); ++i) {
+ const FunctionCallNode* existing_template = dest->GetTemplate(i->first);
+ if (existing_template) {
+ // Rule present in both the source and the dest.
+ std::string desc_string(desc_for_err);
+ *err = Err(node_for_err, "Template collision.",
+ "This " + desc_string + " contains a template \"" + i->first + "\"");
+ err->AppendSubErr(Err(i->second->function(), "defined here.",
+ "Which would clobber the one in your current scope"));
+ err->AppendSubErr(Err(existing_template->function(), "defined here.",
+ "Executing " + desc_string + " should not conflict with anything "
+ "in the current\nscope."));
+ return false;
+ }
+ dest->templates_.insert(*i);
+ }
+
+ return true;
+}
+
+Scope* Scope::MakeTargetDefaults(const std::string& target_type) {
+ if (GetTargetDefaults(target_type))
+ return NULL;
+
+ Scope** dest = &target_defaults_[target_type];
+ if (*dest) {
+ NOTREACHED(); // Already set.
+ return *dest;
+ }
+ *dest = new Scope(settings_);
+ return *dest;
+}
+
+const Scope* Scope::GetTargetDefaults(const std::string& target_type) const {
+ NamedScopeMap::const_iterator found = target_defaults_.find(target_type);
+ if (found != target_defaults_.end())
+ return found->second;
+ if (containing())
+ return containing()->GetTargetDefaults(target_type);
+ return NULL;
+}
+
+const PatternList* Scope::GetSourcesAssignmentFilter() const {
+ if (sources_assignment_filter_)
+ return sources_assignment_filter_.get();
+ if (containing())
+ return containing()->GetSourcesAssignmentFilter();
+ return NULL;
+}
+
+void Scope::SetProcessingBuildConfig() {
+ DCHECK((mode_flags_ & kProcessingBuildConfigFlag) == 0);
+ mode_flags_ |= kProcessingBuildConfigFlag;
+}
+
+void Scope::ClearProcessingBuildConfig() {
+ DCHECK(mode_flags_ & kProcessingBuildConfigFlag);
+ mode_flags_ &= ~(kProcessingBuildConfigFlag);
+}
+
+bool Scope::IsProcessingBuildConfig() const {
+ if (mode_flags_ & kProcessingBuildConfigFlag)
+ return true;
+ if (containing())
+ return containing()->IsProcessingBuildConfig();
+ return false;
+}
+
+void Scope::SetProcessingDefaultBuildConfig() {
+ DCHECK((mode_flags_ & kProcessingDefaultBuildConfigFlag) == 0);
+ mode_flags_ |= kProcessingDefaultBuildConfigFlag;
+}
+
+void Scope::ClearProcessingDefaultBuildConfig() {
+ DCHECK(mode_flags_ & kProcessingDefaultBuildConfigFlag);
+ mode_flags_ &= ~(kProcessingDefaultBuildConfigFlag);
+}
+
+bool Scope::IsProcessingDefaultBuildConfig() const {
+ if (mode_flags_ & kProcessingDefaultBuildConfigFlag)
+ return true;
+ if (containing())
+ return containing()->IsProcessingDefaultBuildConfig();
+ return false;
+}
+
+void Scope::SetProcessingImport() {
+ DCHECK((mode_flags_ & kProcessingImportFlag) == 0);
+ mode_flags_ |= kProcessingImportFlag;
+}
+
+void Scope::ClearProcessingImport() {
+ DCHECK(mode_flags_ & kProcessingImportFlag);
+ mode_flags_ &= ~(kProcessingImportFlag);
+}
+
+bool Scope::IsProcessingImport() const {
+ if (mode_flags_ & kProcessingImportFlag)
+ return true;
+ if (containing())
+ return containing()->IsProcessingImport();
+ return false;
+}
+
+void Scope::SetProperty(const void* key, void* value) {
+ if (!value) {
+ DCHECK(properties_.find(key) != properties_.end());
+ properties_.erase(key);
+ } else {
+ properties_[key] = value;
+ }
+}
+
+void* Scope::GetProperty(const void* key, const Scope** found_on_scope) const {
+ PropertyMap::const_iterator found = properties_.find(key);
+ if (found != properties_.end()) {
+ if (found_on_scope)
+ *found_on_scope = this;
+ return found->second;
+ }
+ if (containing())
+ return containing()->GetProperty(key, found_on_scope);
+ return NULL;
+}
+
+void Scope::AddProvider(ProgrammaticProvider* p) {
+ programmatic_providers_.insert(p);
+}
+
+void Scope::RemoveProvider(ProgrammaticProvider* p) {
+ DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end());
+ programmatic_providers_.erase(p);
+}
diff --git a/chromium/tools/gn/scope.h b/chromium/tools/gn/scope.h
new file mode 100644
index 00000000000..7d0547ed4d4
--- /dev/null
+++ b/chromium/tools/gn/scope.h
@@ -0,0 +1,260 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SCOPE_H_
+#define TOOLS_GN_SCOPE_H_
+
+#include <map>
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
+#include "base/memory/scoped_ptr.h"
+#include "tools/gn/err.h"
+#include "tools/gn/pattern.h"
+#include "tools/gn/value.h"
+
+class FunctionCallNode;
+class ImportManager;
+class ParseNode;
+class Settings;
+class TargetManager;
+
+// Scope for the script execution.
+//
+// Scopes are nested. Writing goes into the toplevel scope, reading checks
+// values resursively down the stack until a match is found or there are no
+// more containing scopes.
+//
+// A containing scope can be const or non-const. The const containing scope is
+// used primarily to refer to the master build config which is shared across
+// many invocations. A const containing scope, however, prevents us from
+// marking variables "used" which prevents us from issuing errors on unused
+// variables. So you should use a non-const containing scope whenever possible.
+class Scope {
+ public:
+ typedef std::vector<std::pair<base::StringPiece, Value> > KeyValueVector;
+
+ // Allows code to provide values for built-in variables. This class will
+ // automatically register itself on construction and deregister itself on
+ // destruction.
+ class ProgrammaticProvider {
+ public:
+ ProgrammaticProvider(Scope* scope) : scope_(scope) {
+ scope_->AddProvider(this);
+ }
+ ~ProgrammaticProvider() {
+ scope_->RemoveProvider(this);
+ }
+
+ // Returns a non-null value if the given value can be programmatically
+ // generated, or NULL if there is none.
+ virtual const Value* GetProgrammaticValue(
+ const base::StringPiece& ident) = 0;
+
+ protected:
+ Scope* scope_;
+ };
+
+ // Creates an empty toplevel scope.
+ Scope(const Settings* settings);
+
+ // Creates a dependent scope.
+ Scope(Scope* parent);
+ Scope(const Scope* parent);
+
+ ~Scope();
+
+ const Settings* settings() const { return settings_; }
+
+ // See the const_/mutable_containing_ var declaraions below. Yes, it's a
+ // bit weird that we can have a const pointer to the "mutable" one.
+ Scope* mutable_containing() { return mutable_containing_; }
+ const Scope* mutable_containing() const { return mutable_containing_; }
+ const Scope* const_containing() const { return const_containing_; }
+ const Scope* containing() const {
+ return mutable_containing_ ? mutable_containing_ : const_containing_;
+ }
+
+ // Returns NULL if there's no such value.
+ //
+ // counts_as_used should be set if the variable is being read in a way that
+ // should count for unused variable checking.
+ const Value* GetValue(const base::StringPiece& ident,
+ bool counts_as_used);
+ const Value* GetValue(const base::StringPiece& ident) const;
+
+ // Same as GetValue, but if the value exists in a parent scope, we'll copy
+ // it to the current scope. If the return value is non-null, the value is
+ // guaranteed to be set in the current scope. Generatlly this will be used
+ // if the calling code is planning on modifying the value in-place.
+ //
+ // Since this is used when doing read-modifies, we never count this access
+ // as reading the variable, since we assume it will be written to.
+ Value* GetValueForcedToCurrentScope(const base::StringPiece& ident,
+ const ParseNode* set_node);
+
+ // The set_node indicates the statement that caused the set, for displaying
+ // errors later. Returns a pointer to the value in the current scope (a copy
+ // is made for storage).
+ Value* SetValue(const base::StringPiece& ident,
+ const Value& v,
+ const ParseNode* set_node);
+
+ // Templates associated with this scope. A template can only be set once, so
+ // AddTemplate will fail and return NULL if a rule with that name already
+ // exists. GetTemplate returns NULL if the rule doesn't exist, and it will
+ // check all containing scoped rescursively.
+ bool AddTemplate(const std::string& name, const FunctionCallNode* decl);
+ const FunctionCallNode* GetTemplate(const std::string& name) const;
+
+ // Marks the given identifier as (un)used in the current scope.
+ void MarkUsed(const base::StringPiece& ident);
+ void MarkUnused(const base::StringPiece& ident);
+
+ // Checks to see if the scope has a var set that hasn't been used. This is
+ // called before replacing the var with a different one. It does not check
+ // containing scopes.
+ //
+ // If the identifier is present but hasnn't been used, return true.
+ bool IsSetButUnused(const base::StringPiece& ident) const;
+
+ // Checks the scope to see if any values were set but not used, and fills in
+ // the error and returns false if they were.
+ bool CheckForUnusedVars(Err* err) const;
+
+ // Returns all values set in the current scope, without going to the parent
+ // scopes.
+ void GetCurrentScopeValues(KeyValueVector* output) const;
+
+ // Copies this scope's values into the destination. Values from the
+ // containing scope(s) (normally shadowed into the current one) will not be
+ // copied, neither will the reference to the containing scope (this is why
+ // it's "non-recursive").
+ //
+ // It is an error to merge a variable into a scope that already has something
+ // with that name in scope (meaning in that scope or in any of its containing
+ // scopes). If this happens, the error will be set and the function will
+ // return false.
+ //
+ // This is used in different contexts. When generating the error, the given
+ // parse node will be blamed, and the given desc will be used to describe
+ // the operation that doesn't support doing this. For example, desc_for_err
+ // would be "import" when doing an import, and the error string would say
+ // something like "The import contains...".
+ bool NonRecursiveMergeTo(Scope* dest,
+ const ParseNode* node_for_err,
+ const char* desc_for_err,
+ Err* err) const;
+
+ // Makes an empty scope with the given name. Returns NULL if the name is
+ // already set.
+ Scope* MakeTargetDefaults(const std::string& target_type);
+
+ // Gets the scope associated with the given target name, or null if it hasn't
+ // been set.
+ const Scope* GetTargetDefaults(const std::string& target_type) const;
+
+ // Filter to apply when the sources variable is assigned. May return NULL.
+ const PatternList* GetSourcesAssignmentFilter() const;
+ void set_sources_assignment_filter(
+ scoped_ptr<PatternList> f) {
+ sources_assignment_filter_ = f.Pass();
+ }
+
+ // Indicates if we're currently processing the build configuration file.
+ // This is true when processing the config file for any toolchain. See also
+ // *ProcessingDefaultBuildConfig() below.
+ //
+ // To set or clear the flag, it must currently be in the opposite state in
+ // the current scope. Note that querying the state of the flag recursively
+ // checks all containing scopes until it reaches the top or finds the flag
+ // set.
+ void SetProcessingBuildConfig();
+ void ClearProcessingBuildConfig();
+ bool IsProcessingBuildConfig() const;
+
+ // Indicates we're currently processing the default toolchain's build
+ // configuration file.
+ void SetProcessingDefaultBuildConfig();
+ void ClearProcessingDefaultBuildConfig();
+ bool IsProcessingDefaultBuildConfig() const;
+
+ // Indicates if we're currently processing an import file.
+ //
+ // See SetProcessingBaseConfig for how flags work.
+ void SetProcessingImport();
+ void ClearProcessingImport();
+ bool IsProcessingImport() const;
+
+ // Properties are opaque pointers that code can use to set state on a Scope
+ // that it can retrieve later.
+ //
+ // The key should be a pointer to some use-case-specific object (to avoid
+ // collisions, otherwise it doesn't matter). Memory management is up to the
+ // setter. Setting the value to NULL will delete the property.
+ //
+ // Getting a property recursively searches all scopes, and the optional
+ // |found_on_scope| variable will be filled with the actual scope containing
+ // the key (if the pointer is non-NULL).
+ void SetProperty(const void* key, void* value);
+ void* GetProperty(const void* key, const Scope** found_on_scope) const;
+
+ private:
+ friend class ProgrammaticProvider;
+
+ struct Record {
+ Record() : used(false) {}
+ Record(const Value& v) : used(false), value(v) {}
+
+ bool used; // Set to true when the variable is used.
+ Value value;
+ };
+
+ void AddProvider(ProgrammaticProvider* p);
+ void RemoveProvider(ProgrammaticProvider* p);
+
+ // Scopes can have no containing scope (both null), a mutable containing
+ // scope, or a const containing scope. The reason is that when we're doing
+ // a new target, we want to refer to the base_config scope which will be read
+ // by multiple threads at the same time, so we REALLY want it to be const.
+ // When you jsut do a nested {}, however, we sometimes want to be able to
+ // change things (especially marking unused vars).
+ const Scope* const_containing_;
+ Scope* mutable_containing_;
+
+ const Settings* settings_;
+
+ // Bits set for different modes. See the flag definitions in the .cc file
+ // for more.
+ unsigned mode_flags_;
+
+ typedef base::hash_map<base::StringPiece, Record> RecordMap;
+ RecordMap values_;
+
+ // Owning pointers. Note that this can't use string pieces since the names
+ // are constructed from Values which might be deallocated before this goes
+ // out of scope.
+ typedef base::hash_map<std::string, Scope*> NamedScopeMap;
+ NamedScopeMap target_defaults_;
+
+ // Null indicates not set and that we should fallback to the containing
+ // scope's filter.
+ scoped_ptr<PatternList> sources_assignment_filter_;
+
+ // Non-owning pointers, the function calls are owned by the input file which
+ // should be kept around by the input file manager.
+ typedef std::map<std::string, const FunctionCallNode*> TemplateMap;
+ TemplateMap templates_;
+
+ typedef std::map<const void*, void*> PropertyMap;
+ PropertyMap properties_;
+
+ typedef std::set<ProgrammaticProvider*> ProviderSet;
+ ProviderSet programmatic_providers_;
+
+ DISALLOW_COPY_AND_ASSIGN(Scope);
+};
+
+#endif // TOOLS_GN_SCOPE_H_
diff --git a/chromium/tools/gn/scope_per_file_provider.cc b/chromium/tools/gn/scope_per_file_provider.cc
new file mode 100644
index 00000000000..87f921cb67e
--- /dev/null
+++ b/chromium/tools/gn/scope_per_file_provider.cc
@@ -0,0 +1,151 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/scope_per_file_provider.h"
+
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/source_file.h"
+#include "tools/gn/toolchain_manager.h"
+#include "tools/gn/value.h"
+#include "tools/gn/variables.h"
+
+ScopePerFileProvider::ScopePerFileProvider(Scope* scope,
+ const SourceFile& source_file)
+ : ProgrammaticProvider(scope),
+ source_file_(source_file) {
+}
+
+ScopePerFileProvider::~ScopePerFileProvider() {
+}
+
+const Value* ScopePerFileProvider::GetProgrammaticValue(
+ const base::StringPiece& ident) {
+ if (ident == variables::kCurrentToolchain)
+ return GetCurrentToolchain();
+ if (ident == variables::kDefaultToolchain)
+ return GetDefaultToolchain();
+ if (ident == variables::kPythonPath)
+ return GetPythonPath();
+
+ if (ident == variables::kRelativeBuildToSourceRootDir)
+ return GetRelativeBuildToSourceRootDir();
+ if (ident == variables::kRelativeRootOutputDir)
+ return GetRelativeRootOutputDir();
+ if (ident == variables::kRelativeRootGenDir)
+ return GetRelativeRootGenDir();
+ if (ident == variables::kRelativeTargetOutputDir)
+ return GetRelativeTargetOutputDir();
+ if (ident == variables::kRelativeTargetGenDir)
+ return GetRelativeTargetGenDir();
+ return NULL;
+}
+
+const Value* ScopePerFileProvider::GetCurrentToolchain() {
+ if (!current_toolchain_) {
+ current_toolchain_.reset(new Value(NULL,
+ scope_->settings()->toolchain()->label().GetUserVisibleName(false)));
+ }
+ return current_toolchain_.get();
+}
+
+const Value* ScopePerFileProvider::GetDefaultToolchain() {
+ if (!default_toolchain_) {
+ const ToolchainManager& toolchain_manager =
+ scope_->settings()->build_settings()->toolchain_manager();
+ default_toolchain_.reset(new Value(NULL,
+ toolchain_manager.GetDefaultToolchainUnlocked().GetUserVisibleName(
+ false)));
+ }
+ return default_toolchain_.get();
+}
+
+const Value* ScopePerFileProvider::GetPythonPath() {
+ if (!python_path_) {
+ python_path_.reset(new Value(NULL,
+ FilePathToUTF8(scope_->settings()->build_settings()->python_path())));
+ }
+ return python_path_.get();
+}
+
+const Value* ScopePerFileProvider::GetRelativeBuildToSourceRootDir() {
+ if (!relative_build_to_source_root_dir_) {
+ const SourceDir& build_dir =
+ scope_->settings()->build_settings()->build_dir();
+ relative_build_to_source_root_dir_.reset(
+ new Value(NULL, InvertDirWithNoLastSlash(build_dir)));
+ }
+ return relative_build_to_source_root_dir_.get();
+}
+
+const Value* ScopePerFileProvider::GetRelativeRootOutputDir() {
+ if (!relative_root_output_dir_) {
+ relative_root_output_dir_.reset(new Value(NULL,
+ GetRelativeRootWithNoLastSlash() +
+ GetRootOutputDirWithNoLastSlash(scope_->settings())));
+ }
+ return relative_root_output_dir_.get();
+}
+
+const Value* ScopePerFileProvider::GetRelativeRootGenDir() {
+ if (!relative_root_gen_dir_) {
+ relative_root_gen_dir_.reset(new Value(NULL,
+ GetRelativeRootWithNoLastSlash() +
+ GetRootGenDirWithNoLastSlash(scope_->settings())));
+ }
+ return relative_root_gen_dir_.get();
+}
+
+const Value* ScopePerFileProvider::GetRelativeTargetOutputDir() {
+ if (!relative_target_output_dir_) {
+ relative_target_output_dir_.reset(new Value(NULL,
+ GetRelativeRootWithNoLastSlash() +
+ GetRootOutputDirWithNoLastSlash(scope_->settings()) + "obj/" +
+ GetFileDirWithNoLastSlash()));
+ }
+ return relative_target_output_dir_.get();
+}
+
+const Value* ScopePerFileProvider::GetRelativeTargetGenDir() {
+ if (!relative_target_gen_dir_) {
+ relative_target_gen_dir_.reset(new Value(NULL,
+ GetRelativeRootWithNoLastSlash() +
+ GetRootGenDirWithNoLastSlash(scope_->settings()) +
+ GetFileDirWithNoLastSlash()));
+ }
+ return relative_target_gen_dir_.get();
+}
+
+// static
+std::string ScopePerFileProvider::GetRootOutputDirWithNoLastSlash(
+ const Settings* settings) {
+ const std::string& output_dir =
+ settings->build_settings()->build_dir().value();
+ CHECK(!output_dir.empty());
+ return output_dir.substr(1, output_dir.size() - 1);
+}
+
+// static
+std::string ScopePerFileProvider::GetRootGenDirWithNoLastSlash(
+ const Settings* settings) {
+ return GetRootOutputDirWithNoLastSlash(settings) + "/gen";
+}
+
+std::string ScopePerFileProvider::GetFileDirWithNoLastSlash() const {
+ std::string dir_value = source_file_.GetDir().value();
+ return dir_value.substr(0, dir_value.size() - 1);
+}
+
+std::string ScopePerFileProvider::GetRelativeRootWithNoLastSlash() const {
+ return InvertDirWithNoLastSlash(source_file_.GetDir());
+}
+
+// static
+std::string ScopePerFileProvider::InvertDirWithNoLastSlash(
+ const SourceDir& dir) {
+ std::string inverted = InvertDir(dir);
+ if (inverted.empty())
+ return ".";
+ return inverted.substr(0, inverted.size() - 1);
+}
diff --git a/chromium/tools/gn/scope_per_file_provider.h b/chromium/tools/gn/scope_per_file_provider.h
new file mode 100644
index 00000000000..9b6bb3477eb
--- /dev/null
+++ b/chromium/tools/gn/scope_per_file_provider.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_
+#define TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/source_file.h"
+
+// ProgrammaticProvider for a scope to provide it with per-file built-in
+// variable support.
+class ScopePerFileProvider : public Scope::ProgrammaticProvider {
+ public:
+ ScopePerFileProvider(Scope* scope, const SourceFile& source_file);
+ virtual ~ScopePerFileProvider();
+
+ // ProgrammaticProvider implementation.
+ virtual const Value* GetProgrammaticValue(
+ const base::StringPiece& ident) OVERRIDE;
+
+ private:
+ const Value* GetCurrentToolchain();
+ const Value* GetDefaultToolchain();
+ const Value* GetPythonPath();
+ const Value* GetRelativeBuildToSourceRootDir();
+ const Value* GetRelativeRootOutputDir();
+ const Value* GetRelativeRootGenDir();
+ const Value* GetRelativeTargetOutputDir();
+ const Value* GetRelativeTargetGenDir();
+
+ static std::string GetRootOutputDirWithNoLastSlash(const Settings* settings);
+ static std::string GetRootGenDirWithNoLastSlash(const Settings* settings);
+
+ std::string GetFileDirWithNoLastSlash() const;
+ std::string GetRelativeRootWithNoLastSlash() const;
+
+ // Inverts the given directory, returning it with no trailing slash. If the
+ // result would be empty, "." is returned to indicate the current dir.
+ static std::string InvertDirWithNoLastSlash(const SourceDir& dir);
+
+ SourceFile source_file_;
+
+ // All values are lazily created.
+ scoped_ptr<Value> current_toolchain_;
+ scoped_ptr<Value> default_toolchain_;
+ scoped_ptr<Value> python_path_;
+ scoped_ptr<Value> relative_build_to_source_root_dir_;
+ scoped_ptr<Value> relative_root_output_dir_;
+ scoped_ptr<Value> relative_root_gen_dir_;
+ scoped_ptr<Value> relative_target_output_dir_;
+ scoped_ptr<Value> relative_target_gen_dir_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopePerFileProvider);
+};
+
+#endif // TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_
diff --git a/chromium/tools/gn/script_target_generator.cc b/chromium/tools/gn/script_target_generator.cc
new file mode 100644
index 00000000000..58243d5df4f
--- /dev/null
+++ b/chromium/tools/gn/script_target_generator.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/script_target_generator.h"
+
+#include "tools/gn/err.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/value.h"
+#include "tools/gn/value_extractors.h"
+
+ScriptTargetGenerator::ScriptTargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Err* err)
+ : TargetGenerator(target, scope, function_token, err) {
+}
+
+ScriptTargetGenerator::~ScriptTargetGenerator() {
+}
+
+void ScriptTargetGenerator::DoRun() {
+ target_->set_output_type(Target::CUSTOM);
+
+ FillSources();
+ FillScript();
+ FillScriptArgs();
+ FillOutputs();
+
+ // Script outputs don't depend on the current toolchain so we can skip adding
+ // that dependency.
+}
+
+void ScriptTargetGenerator::FillScript() {
+ // If this gets called, the target type requires a script, so error out
+ // if it doesn't have one.
+ // TODO(brettw) hook up a constant in variables.h
+ const Value* value = scope_->GetValue("script", true);
+ if (!value) {
+ *err_ = Err(function_token_, "This target type requires a \"script\".");
+ return;
+ }
+ if (!value->VerifyTypeIs(Value::STRING, err_))
+ return;
+
+ target_->script_values().set_script(
+ input_directory_.ResolveRelativeFile(value->string_value()));
+}
+
+void ScriptTargetGenerator::FillScriptArgs() {
+ const Value* value = scope_->GetValue("args", true);
+ if (!value)
+ return;
+
+ std::vector<std::string> args;
+ if (!ExtractListOfStringValues(*value, &args, err_))
+ return;
+ target_->script_values().swap_in_args(&args);
+}
+
+void ScriptTargetGenerator::FillOutputs() {
+ // TODO(brettw) hook up a constant in variables.h
+ const Value* value = scope_->GetValue("outputs", true);
+ if (!value)
+ return;
+
+ Target::FileList outputs;
+ if (!ExtractListOfRelativeFiles(*value, input_directory_, &outputs, err_))
+ return;
+
+ // Validate that outputs are in the output dir.
+ CHECK(outputs.size() == value->list_value().size());
+ for (size_t i = 0; i < outputs.size(); i++) {
+ if (!EnsureStringIsInOutputDir(
+ GetBuildSettings()->build_dir(),
+ outputs[i].value(), value->list_value()[i], err_))
+ return;
+ }
+ target_->script_values().swap_in_outputs(&outputs);
+}
+
diff --git a/chromium/tools/gn/script_target_generator.h b/chromium/tools/gn/script_target_generator.h
new file mode 100644
index 00000000000..c5e18111dba
--- /dev/null
+++ b/chromium/tools/gn/script_target_generator.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SCRIPT_TARGET_GENERATOR_H_
+#define TOOLS_GN_SCRIPT_TARGET_GENERATOR_H_
+
+#include "base/compiler_specific.h"
+#include "tools/gn/target_generator.h"
+
+// Populates a Target with the values from a custom script rule.
+class ScriptTargetGenerator : public TargetGenerator {
+ public:
+ ScriptTargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Err* err);
+ virtual ~ScriptTargetGenerator();
+
+ protected:
+ virtual void DoRun() OVERRIDE;
+
+ private:
+ void FillScript();
+ void FillScriptArgs();
+ void FillOutputs();
+
+ DISALLOW_COPY_AND_ASSIGN(ScriptTargetGenerator);
+};
+
+#endif // TOOLS_GN_SCRIPT_TARGET_GENERATOR_H_
+
diff --git a/chromium/tools/gn/script_values.cc b/chromium/tools/gn/script_values.cc
new file mode 100644
index 00000000000..c5d7989f3f1
--- /dev/null
+++ b/chromium/tools/gn/script_values.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/script_values.h"
+
+ScriptValues::ScriptValues() {
+}
+
+ScriptValues::~ScriptValues() {
+}
diff --git a/chromium/tools/gn/script_values.h b/chromium/tools/gn/script_values.h
new file mode 100644
index 00000000000..4a874b9e065
--- /dev/null
+++ b/chromium/tools/gn/script_values.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SCRIPT_VALUES_H_
+#define TOOLS_GN_SCRIPT_VALUES_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "tools/gn/source_file.h"
+
+// Holds the values (outputs, args, script name, etc.) for a script-based
+// target.
+class ScriptValues {
+ public:
+ ScriptValues();
+ ~ScriptValues();
+
+ // Filename of the script to execute.
+ const SourceFile& script() const { return script_; }
+ void set_script(const SourceFile& s) { script_ = s; }
+
+ // Arguments to the script.
+ const std::vector<std::string>& args() const { return args_; }
+ void swap_in_args(std::vector<std::string>* a) { args_.swap(*a); }
+
+ // Files created by the script.
+ const std::vector<SourceFile>& outputs() const { return outputs_; }
+ void swap_in_outputs(std::vector<SourceFile>* op) { outputs_.swap(*op); }
+
+ private:
+ SourceFile script_;
+ std::vector<std::string> args_;
+ std::vector<SourceFile> outputs_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScriptValues);
+};
+
+#endif // TOOLS_GN_SCRIPT_VALUES_H_
diff --git a/chromium/tools/gn/secondary/BUILD.gn b/chromium/tools/gn/secondary/BUILD.gn
new file mode 100644
index 00000000000..5f7c1b53c37
--- /dev/null
+++ b/chromium/tools/gn/secondary/BUILD.gn
@@ -0,0 +1,10 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+group("root") {
+ deps = [
+ "//tools/gn",
+ "//ipc",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/base/BUILD.gn b/chromium/tools/gn/secondary/base/BUILD.gn
new file mode 100644
index 00000000000..2fe83ef62d4
--- /dev/null
+++ b/chromium/tools/gn/secondary/base/BUILD.gn
@@ -0,0 +1,990 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("base_libs") {
+ if (!is_win) {
+ ldflags = [ "-ldl" ]
+ }
+}
+
+component("base") {
+ sources = [
+ "../build/build_config.h",
+ "third_party/dmg_fp/dmg_fp.h",
+ "third_party/dmg_fp/g_fmt.cc",
+ "third_party/dmg_fp/dtoa_wrapper.cc",
+ "third_party/icu/icu_utf.cc",
+ "third_party/icu/icu_utf.h",
+ "allocator/allocator_extension.cc",
+ "allocator/allocator_extension.h",
+ "allocator/type_profiler_control.cc",
+ "allocator/type_profiler_control.h",
+ "android/activity_status.cc",
+ "android/activity_status.h",
+ "android/base_jni_registrar.cc",
+ "android/base_jni_registrar.h",
+ "android/build_info.cc",
+ "android/build_info.h",
+ "android/cpu_features.cc",
+ "android/fifo_utils.cc",
+ "android/fifo_utils.h",
+ "android/important_file_writer_android.cc",
+ "android/important_file_writer_android.h",
+ "android/scoped_java_ref.cc",
+ "android/scoped_java_ref.h",
+ "android/jni_android.cc",
+ "android/jni_android.h",
+ "android/jni_array.cc",
+ "android/jni_array.h",
+ "android/jni_helper.cc",
+ "android/jni_helper.h",
+ "android/jni_registrar.cc",
+ "android/jni_registrar.h",
+ "android/jni_string.cc",
+ "android/jni_string.h",
+ "android/memory_pressure_listener_android.cc",
+ "android/memory_pressure_listener_android.h",
+ "android/path_service_android.cc",
+ "android/path_service_android.h",
+ "android/path_utils.cc",
+ "android/path_utils.h",
+ "android/sys_utils.cc",
+ "android/sys_utils.h",
+ "android/thread_utils.h",
+ "at_exit.cc",
+ "at_exit.h",
+ "atomic_ref_count.h",
+ "atomic_sequence_num.h",
+ "atomicops.h",
+ "atomicops_internals_gcc.h",
+ "atomicops_internals_mac.h",
+ "atomicops_internals_tsan.h",
+ "atomicops_internals_x86_gcc.cc",
+ "atomicops_internals_x86_gcc.h",
+ "atomicops_internals_x86_msvc.h",
+ "base_export.h",
+ "base_paths.cc",
+ "base_paths.h",
+ "base_paths_android.cc",
+ "base_paths_android.h",
+ "base_paths_mac.h",
+ "base_paths_mac.mm",
+ "base_paths_posix.cc",
+ "base_paths_posix.h",
+ "base_paths_win.cc",
+ "base_paths_win.h",
+ "base_switches.h",
+ "base64.cc",
+ "base64.h",
+ "basictypes.h",
+ "bind.h",
+ "bind_helpers.cc",
+ "bind_helpers.h",
+ "bind_internal.h",
+ "bind_internal_win.h",
+ "bits.h",
+ "build_time.cc",
+ "build_time.h",
+ "callback.h",
+ "callback_helpers.h",
+ "callback_internal.cc",
+ "callback_internal.h",
+ "cancelable_callback.h",
+ "chromeos/chromeos_version.cc",
+ "chromeos/chromeos_version.h",
+ "command_line.cc",
+ "command_line.h",
+ "compiler_specific.h",
+ "containers/hash_tables.h",
+ "containers/linked_list.h",
+ "containers/mru_cache.h",
+ "containers/small_map.h",
+ "containers/stack_container.h",
+ "cpu.cc",
+ "cpu.h",
+ "critical_closure.h",
+ "critical_closure_ios.mm",
+ "debug/alias.cc",
+ "debug/alias.h",
+ "debug/crash_logging.cc",
+ "debug/crash_logging.h",
+ "debug/debug_on_start_win.cc",
+ "debug/debug_on_start_win.h",
+ "debug/debugger.cc",
+ "debug/debugger.h",
+ "debug/debugger_posix.cc",
+ "debug/debugger_win.cc",
+ # This file depends on files from the "allocator" target,
+ # but this target does not depend on "allocator" (see
+ # allocator.gyp for details).
+ "debug/leak_annotations.h",
+ "debug/leak_tracker.h",
+ "debug/proc_maps_linux.cc",
+ "debug/proc_maps_linux.h",
+ "debug/profiler.cc",
+ "debug/profiler.h",
+ "debug/stack_trace.cc",
+ "debug/stack_trace.h",
+ "debug/stack_trace_android.cc",
+ "debug/stack_trace_ios.mm",
+ "debug/stack_trace_posix.cc",
+ "debug/stack_trace_win.cc",
+ "debug/trace_event.h",
+ "debug/trace_event_android.cc",
+ "debug/trace_event_impl.cc",
+ "debug/trace_event_impl.h",
+ "debug/trace_event_impl_constants.cc",
+ "debug/trace_event_memory.cc",
+ "debug/trace_event_memory.h",
+ "debug/trace_event_win.cc",
+ "deferred_sequenced_task_runner.cc",
+ "deferred_sequenced_task_runner.h",
+ "environment.cc",
+ "environment.h",
+ "file_descriptor_posix.h",
+ "file_util.cc",
+ "file_util.h",
+ "file_util_android.cc",
+ "file_util_linux.cc",
+ "file_util_mac.mm",
+ "file_util_posix.cc",
+ "file_util_win.cc",
+ "file_version_info.h",
+ "file_version_info_mac.h",
+ "file_version_info_mac.mm",
+ "file_version_info_win.cc",
+ "file_version_info_win.h",
+ "files/dir_reader_fallback.h",
+ "files/dir_reader_linux.h",
+ "files/dir_reader_posix.h",
+ "files/file_enumerator.cc",
+ "files/file_enumerator.h",
+ "files/file_enumerator_posix.cc",
+ "files/file_enumerator_win.cc",
+ "files/file_path.cc",
+ "files/file_path.h",
+ "files/file_path_constants.cc",
+ "files/file_path_watcher.cc",
+ "files/file_path_watcher.h",
+ "files/file_path_watcher_kqueue.cc",
+ "files/file_path_watcher_linux.cc",
+ "files/file_path_watcher_stub.cc",
+ "files/file_path_watcher_win.cc",
+ "files/file_util_proxy.cc",
+ "files/file_util_proxy.h",
+ "files/important_file_writer.h",
+ "files/important_file_writer.cc",
+ "files/memory_mapped_file.cc",
+ "files/memory_mapped_file.h",
+ "files/memory_mapped_file_posix.cc",
+ "files/memory_mapped_file_win.cc",
+ "files/scoped_temp_dir.cc",
+ "files/scoped_temp_dir.h",
+ "float_util.h",
+ "format_macros.h",
+ "gtest_prod_util.h",
+ "guid.cc",
+ "guid.h",
+ "guid_posix.cc",
+ "guid_win.cc",
+ "hash.cc",
+ "hash.h",
+ "id_map.h",
+ "ini_parser.cc",
+ "ini_parser.h",
+ "ios/device_util.h",
+ "ios/device_util.mm",
+ "ios/ios_util.h",
+ "ios/ios_util.mm",
+ "ios/scoped_critical_action.h",
+ "ios/scoped_critical_action.mm",
+ "json/json_file_value_serializer.cc",
+ "json/json_file_value_serializer.h",
+ "json/json_parser.cc",
+ "json/json_parser.h",
+ "json/json_reader.cc",
+ "json/json_reader.h",
+ "json/json_string_value_serializer.cc",
+ "json/json_string_value_serializer.h",
+ "json/json_value_converter.h",
+ "json/json_writer.cc",
+ "json/json_writer.h",
+ "json/string_escape.cc",
+ "json/string_escape.h",
+ "lazy_instance.cc",
+ "lazy_instance.h",
+ "location.cc",
+ "location.h",
+ "logging.cc",
+ "logging.h",
+ "logging_win.cc",
+ "logging_win.h",
+ "mac/authorization_util.h",
+ "mac/authorization_util.mm",
+ "mac/bind_objc_block.h",
+ "mac/bundle_locations.h",
+ "mac/bundle_locations.mm",
+ "mac/cocoa_protocols.h",
+ "mac/foundation_util.h",
+ "mac/foundation_util.mm",
+ "mac/launch_services_util.cc",
+ "mac/launch_services_util.h",
+ "mac/launchd.cc",
+ "mac/launchd.h",
+ "mac/libdispatch_task_runner.cc",
+ "mac/libdispatch_task_runner.h",
+ "mac/mac_logging.h",
+ "mac/mac_logging.cc",
+ "mac/mac_util.h",
+ "mac/mac_util.mm",
+ "mac/objc_property_releaser.h",
+ "mac/objc_property_releaser.mm",
+ "mac/os_crash_dumps.cc",
+ "mac/os_crash_dumps.h",
+ "mac/scoped_aedesc.h",
+ "mac/scoped_authorizationref.h",
+ "mac/scoped_block.h",
+ "mac/scoped_cftyperef.h",
+ "mac/scoped_ioobject.h",
+ "mac/scoped_ioplugininterface.h",
+ "mac/scoped_launch_data.h",
+ "mac/scoped_mach_port.cc",
+ "mac/scoped_mach_port.h",
+ "mac/scoped_nsautorelease_pool.h",
+ "mac/scoped_nsautorelease_pool.mm",
+ "mac/scoped_nsexception_enabler.h",
+ "mac/scoped_nsexception_enabler.mm",
+ "mac/scoped_nsobject.h",
+ "mac/scoped_sending_event.h",
+ "mac/scoped_sending_event.mm",
+ "mac/sdk_forward_declarations.h",
+ "memory/aligned_memory.cc",
+ "memory/aligned_memory.h",
+ "memory/discardable_memory.cc",
+ "memory/discardable_memory.h",
+ "memory/discardable_memory_android.cc",
+ "memory/discardable_memory_mac.cc",
+ "memory/linked_ptr.h",
+ "memory/manual_constructor.h",
+ "memory/memory_pressure_listener.cc",
+ "memory/memory_pressure_listener.h",
+ "memory/raw_scoped_refptr_mismatch_checker.h",
+ "memory/ref_counted.cc",
+ "memory/ref_counted.h",
+ "memory/ref_counted_delete_on_message_loop.h",
+ "memory/ref_counted_memory.cc",
+ "memory/ref_counted_memory.h",
+ "memory/scoped_handle.h",
+ "memory/scoped_open_process.h",
+ "memory/scoped_policy.h",
+ "memory/scoped_ptr.h",
+ "memory/scoped_vector.h",
+ "memory/shared_memory.h",
+ "memory/shared_memory_android.cc",
+ "memory/shared_memory_nacl.cc",
+ "memory/shared_memory_posix.cc",
+ "memory/shared_memory_win.cc",
+ "memory/singleton.cc",
+ "memory/singleton.h",
+ "memory/weak_ptr.cc",
+ "memory/weak_ptr.h",
+ "message_loop/incoming_task_queue.cc",
+ "message_loop/incoming_task_queue.h",
+ "message_loop/message_loop.cc",
+ "message_loop/message_loop.h",
+ "message_loop/message_loop_proxy.cc",
+ "message_loop/message_loop_proxy.h",
+ "message_loop/message_loop_proxy_impl.cc",
+ "message_loop/message_loop_proxy_impl.h",
+ "message_loop/message_pump.cc",
+ "message_loop/message_pump.h",
+ "message_loop/message_pump_android.cc",
+ "message_loop/message_pump_android.h",
+ "message_loop/message_pump_aurax11.cc",
+ "message_loop/message_pump_aurax11.h",
+ "message_loop/message_pump_default.cc",
+ "message_loop/message_pump_default.h",
+ "message_loop/message_pump_glib.cc",
+ "message_loop/message_pump_glib.h",
+ "message_loop/message_pump_gtk.cc",
+ "message_loop/message_pump_gtk.h",
+ "message_loop/message_pump_io_ios.cc",
+ "message_loop/message_pump_io_ios.h",
+ "message_loop/message_pump_libevent.cc",
+ "message_loop/message_pump_libevent.h",
+ "message_loop/message_pump_mac.h",
+ "message_loop/message_pump_mac.mm",
+ "message_loop/message_pump_observer.h",
+ "message_loop/message_pump_ozone.cc",
+ "message_loop/message_pump_ozone.h",
+ "message_loop/message_pump_win.cc",
+ "message_loop/message_pump_win.h",
+ "metrics/field_trial.cc",
+ "metrics/field_trial.h",
+ "metrics/sample_map.cc",
+ "metrics/sample_map.h",
+ "metrics/sample_vector.cc",
+ "metrics/sample_vector.h",
+ "metrics/bucket_ranges.cc",
+ "metrics/bucket_ranges.h",
+ "metrics/histogram.cc",
+ "metrics/histogram.h",
+ "metrics/histogram_base.cc",
+ "metrics/histogram_base.h",
+ "metrics/histogram_flattener.h",
+ "metrics/histogram_samples.cc",
+ "metrics/histogram_samples.h",
+ "metrics/histogram_snapshot_manager.cc",
+ "metrics/histogram_snapshot_manager.h",
+ "metrics/sparse_histogram.cc",
+ "metrics/sparse_histogram.h",
+ "metrics/statistics_recorder.cc",
+ "metrics/statistics_recorder.h",
+ "metrics/stats_counters.cc",
+ "metrics/stats_counters.h",
+ "metrics/stats_table.cc",
+ "metrics/stats_table.h",
+ "move.h",
+ "native_library.h",
+ "native_library_mac.mm",
+ "native_library_posix.cc",
+ "native_library_win.cc",
+ "nix/mime_util_xdg.cc",
+ "nix/mime_util_xdg.h",
+ "nix/xdg_util.cc",
+ "nix/xdg_util.h",
+ "observer_list.h",
+ "observer_list_threadsafe.h",
+ "os_compat_android.cc",
+ "os_compat_android.h",
+ "os_compat_nacl.cc",
+ "os_compat_nacl.h",
+ "path_service.cc",
+ "path_service.h",
+ "pending_task.cc",
+ "pending_task.h",
+ "pickle.cc",
+ "pickle.h",
+ "platform_file.cc",
+ "platform_file.h",
+ "platform_file_posix.cc",
+ "platform_file_win.cc",
+ "port.h",
+ "posix/eintr_wrapper.h",
+ "posix/file_descriptor_shuffle.cc",
+ "posix/file_descriptor_shuffle.y",
+ "posix/global_descriptors.cc",
+ "posix/global_descriptors.h",
+ "posix/unix_domain_socket_linux.cc",
+ "posix/unix_domain_socket_linux.h",
+ "power_monitor/power_monitor.cc",
+ "power_monitor/power_monitor.h",
+ "power_monitor/power_monitor_device_source.cc",
+ "power_monitor/power_monitor_device_source.h",
+ "power_monitor/power_monitor_device_source_android.cc",
+ "power_monitor/power_monitor_device_source_android.h",
+ "power_monitor/power_monitor_device_source_ios.mm",
+ "power_monitor/power_monitor_device_source_mac.mm",
+ "power_monitor/power_monitor_device_source_posix.cc",
+ "power_monitor/power_monitor_device_source_win.cc",
+ "power_monitor/power_monitor_source.cc",
+ "power_monitor/power_monitor_source.h",
+ "power_monitor/power_observer.h",
+ "process/internal_linux.cc",
+ "process/internal_linux.h",
+ "process/kill.cc",
+ "process/kill.h",
+ "process/kill_mac.cc",
+ "process/kill_posix.cc",
+ "process/kill_win.cc",
+ "process/launch.h",
+ "process/launch_ios.cc",
+ "process/launch_mac.cc",
+ "process/launch_posix.cc",
+ "process/launch_win.cc",
+ "process/memory.h",
+ "process/memory_linux.cc",
+ "process/memory_mac.mm",
+ "process/memory_win.cc",
+ "process/process.h",
+ "process/process_handle_freebsd.cc",
+ "process/process_handle_linux.cc",
+ "process/process_handle_mac.cc",
+ "process/process_handle_openbsd.cc",
+ "process/process_handle_posix.cc",
+ "process/process_handle_win.cc",
+ "process/process_info.h",
+ "process/process_info_mac.cc",
+ "process/process_info_win.cc",
+ "process/process_iterator.cc",
+ "process/process_iterator.h",
+ "process/process_iterator_freebsd.cc",
+ "process/process_iterator_linux.cc",
+ "process/process_iterator_mac.cc",
+ "process/process_iterator_openbsd.cc",
+ "process/process_iterator_win.cc",
+ "process/process_linux.cc",
+ "process/process_metrics.h",
+ "process/process_metrics_freebsd.cc",
+ "process/process_metrics_ios.cc",
+ "process/process_metrics_linux.cc",
+ "process/process_metrics_mac.cc",
+ "process/process_metrics_openbsd.cc",
+ "process/process_metrics_posix.cc",
+ "process/process_metrics_win.cc",
+ "process/process_posix.cc",
+ "process/process_util.h",
+ "process/process_win.cc",
+ "profiler/scoped_profile.cc",
+ "profiler/scoped_profile.h",
+ "profiler/alternate_timer.cc",
+ "profiler/alternate_timer.h",
+ "profiler/tracked_time.cc",
+ "profiler/tracked_time.h",
+ "rand_util.cc",
+ "rand_util.h",
+ "rand_util_nacl.cc",
+ "rand_util_posix.cc",
+ "rand_util_win.cc",
+ "run_loop.cc",
+ "run_loop.h",
+ "safe_numerics.h",
+ "safe_strerror_posix.cc",
+ "safe_strerror_posix.h",
+ "scoped_native_library.cc",
+ "scoped_native_library.h",
+ "sequence_checker.h",
+ "sequence_checker_impl.cc",
+ "sequence_checker_impl.h",
+ "sequenced_task_runner.cc",
+ "sequenced_task_runner.h",
+ "sequenced_task_runner_helpers.h",
+ "sha1.h",
+ "sha1_portable.cc",
+ "sha1_win.cc",
+ "single_thread_task_runner.h",
+ "stl_util.h",
+ "strings/latin1_string_conversions.cc",
+ "strings/latin1_string_conversions.h",
+ "strings/nullable_string16.cc",
+ "strings/nullable_string16.h",
+ "strings/string16.cc",
+ "strings/string16.h",
+ "strings/string_number_conversions.cc",
+ "strings/string_split.cc",
+ "strings/string_split.h",
+ "strings/string_number_conversions.h",
+ "strings/string_piece.cc",
+ "strings/string_piece.h",
+ "strings/string_tokenizer.h",
+ "strings/string_util.cc",
+ "strings/string_util.h",
+ "strings/string_util_constants.cc",
+ "strings/string_util_posix.h",
+ "strings/string_util_win.h",
+ "strings/stringize_macros.h",
+ "strings/stringprintf.cc",
+ "strings/stringprintf.h",
+ "strings/sys_string_conversions.h",
+ "strings/sys_string_conversions_mac.mm",
+ "strings/sys_string_conversions_posix.cc",
+ "strings/sys_string_conversions_win.cc",
+ "strings/utf_offset_string_conversions.cc",
+ "strings/utf_offset_string_conversions.h",
+ "strings/utf_string_conversion_utils.cc",
+ "strings/utf_string_conversion_utils.h",
+ "strings/utf_string_conversions.cc",
+ "strings/utf_string_conversions.h",
+ "supports_user_data.cc",
+ "supports_user_data.h",
+ "sync_socket.h",
+ "sync_socket_posix.cc",
+ "sync_socket_win.cc",
+ "synchronization/cancellation_flag.cc",
+ "synchronization/cancellation_flag.h",
+ "synchronization/condition_variable.h",
+ "synchronization/condition_variable_posix.cc",
+ "synchronization/condition_variable_win.cc",
+ "synchronization/lock.cc",
+ "synchronization/lock.h",
+ "synchronization/lock_impl.h",
+ "synchronization/lock_impl_posix.cc",
+ "synchronization/lock_impl_win.cc",
+ "synchronization/spin_wait.h",
+ "synchronization/waitable_event.h",
+ "synchronization/waitable_event_posix.cc",
+ "synchronization/waitable_event_watcher.h",
+ "synchronization/waitable_event_watcher_posix.cc",
+ "synchronization/waitable_event_watcher_win.cc",
+ "synchronization/waitable_event_win.cc",
+ "system_monitor/system_monitor.cc",
+ "system_monitor/system_monitor.h",
+ "sys_byteorder.h",
+ "sys_info.cc",
+ "sys_info.h",
+ "sys_info_android.cc",
+ "sys_info_chromeos.cc",
+ "sys_info_freebsd.cc",
+ "sys_info_ios.mm",
+ "sys_info_linux.cc",
+ "sys_info_mac.cc",
+ "sys_info_openbsd.cc",
+ "sys_info_posix.cc",
+ "sys_info_win.cc",
+ "task_runner.cc",
+ "task_runner.h",
+ "task_runner_util.h",
+ "template_util.h",
+ "thread_task_runner_handle.cc",
+ "thread_task_runner_handle.h",
+ "threading/non_thread_safe.h",
+ "threading/non_thread_safe_impl.cc",
+ "threading/non_thread_safe_impl.h",
+ "threading/platform_thread.h",
+ "threading/platform_thread_android.cc",
+ "threading/platform_thread_linux.cc",
+ "threading/platform_thread_mac.mm",
+ "threading/platform_thread_posix.cc",
+ "threading/platform_thread_win.cc",
+ "threading/post_task_and_reply_impl.cc",
+ "threading/post_task_and_reply_impl.h",
+ "threading/sequenced_worker_pool.cc",
+ "threading/sequenced_worker_pool.h",
+ "threading/simple_thread.cc",
+ "threading/simple_thread.h",
+ "threading/thread.cc",
+ "threading/thread.h",
+ "threading/thread_checker.h",
+ "threading/thread_checker_impl.cc",
+ "threading/thread_checker_impl.h",
+ "threading/thread_collision_warner.cc",
+ "threading/thread_collision_warner.h",
+ "threading/thread_id_name_manager.cc",
+ "threading/thread_id_name_manager.h",
+ "threading/thread_local.h",
+ "threading/thread_local_posix.cc",
+ "threading/thread_local_storage.h",
+ "threading/thread_local_storage_posix.cc",
+ "threading/thread_local_storage_win.cc",
+ "threading/thread_local_win.cc",
+ "threading/thread_restrictions.h",
+ "threading/thread_restrictions.cc",
+ "threading/watchdog.cc",
+ "threading/watchdog.h",
+ "threading/worker_pool.h",
+ "threading/worker_pool.cc",
+ "threading/worker_pool_posix.cc",
+ "threading/worker_pool_posix.h",
+ "threading/worker_pool_win.cc",
+ "time/clock.cc",
+ "time/clock.h",
+ "time/default_clock.cc",
+ "time/default_clock.h",
+ "time/default_tick_clock.cc",
+ "time/default_tick_clock.h",
+ "time/tick_clock.cc",
+ "time/tick_clock.h",
+ "time/time.cc",
+ "time/time.h",
+ "time/time_mac.cc",
+ "time/time_posix.cc",
+ "time/time_win.cc",
+ "timer/hi_res_timer_manager_posix.cc",
+ "timer/hi_res_timer_manager_win.cc",
+ "timer/hi_res_timer_manager.h",
+ "timer/timer.cc",
+ "timer/timer.h",
+ "tracked_objects.cc",
+ "tracked_objects.h",
+ "tracking_info.cc",
+ "tracking_info.h",
+ "tuple.h",
+ "values.cc",
+ "values.h",
+ "value_conversions.cc",
+ "value_conversions.h",
+ "version.cc",
+ "version.h",
+ "vlog.cc",
+ "vlog.h",
+ "win/enum_variant.cc",
+ "win/enum_variant.h",
+ "win/event_trace_consumer.h",
+ "win/event_trace_controller.cc",
+ "win/event_trace_controller.h",
+ "win/event_trace_provider.cc",
+ "win/event_trace_provider.h",
+ "win/i18n.cc",
+ "win/i18n.h",
+ "win/iat_patch_function.cc",
+ "win/iat_patch_function.h",
+ "win/iunknown_impl.cc",
+ "win/iunknown_impl.h",
+ "win/message_window.cc",
+ "win/message_window.h",
+ "win/metro.cc",
+ "win/metro.h",
+ "win/object_watcher.cc",
+ "win/object_watcher.h",
+ "win/registry.cc",
+ "win/registry.h",
+ "win/resource_util.cc",
+ "win/resource_util.h",
+ "win/sampling_profiler.cc",
+ "win/sampling_profiler.h",
+ "win/scoped_bstr.cc",
+ "win/scoped_bstr.h",
+ "win/scoped_co_mem.h",
+ "win/scoped_com_initializer.h",
+ "win/scoped_comptr.h",
+ "win/scoped_gdi_object.h",
+ "win/scoped_handle.cc",
+ "win/scoped_handle.h",
+ "win/scoped_hdc.h",
+ "win/scoped_hglobal.h",
+ "win/scoped_process_information.cc",
+ "win/scoped_process_information.h",
+ "win/scoped_propvariant.h",
+ "win/scoped_select_object.h",
+ "win/scoped_variant.cc",
+ "win/scoped_variant.h",
+ "win/shortcut.cc",
+ "win/shortcut.h",
+ "win/startup_information.cc",
+ "win/startup_information.h",
+ "win/text_services_message_filter.cc",
+ "win/text_services_message_filter.h",
+ "win/win_util.cc",
+ "win/win_util.h",
+ "win/windows_version.cc",
+ "win/windows_version.h",
+ "win/wrapped_window_proc.cc",
+ "win/wrapped_window_proc.h",
+ ]
+
+ # TODO(brettw) I don't understand the conditions this file is used.
+ sources -= "files/file_path_watcher_stub.cc"
+
+ sources -= [
+ # TODO(brettw) do these properly.
+ "message_loop/message_pump_aurax11.cc",
+ "message_loop/message_pump_aurax11.h",
+ "message_loop/message_pump_ozone.cc",
+ "message_loop/message_pump_ozone.h",
+
+ "process/process_handle_freebsd.cc",
+ "process/process_handle_openbsd.cc",
+ "process/process_iterator_freebsd.cc",
+ "process/process_iterator_openbsd.cc",
+ "process/process_metrics_freebsd.cc",
+ "process/process_metrics_openbsd.cc",
+ "sys_info_freebsd.cc",
+ "sys_info_openbsd.cc",
+ ]
+
+ defines = [
+ "BASE_IMPLEMENTATION",
+ ]
+
+ deps = [
+ ":base_static",
+ "//base/allocator:allocator_extension_thunks",
+ "//base/third_party/dynamic_annotations",
+ "//base/third_party/nspr",
+ "//third_party/modp_b64",
+ ]
+
+ # So we can append below without worrying about whether it has been
+ # previously defined or not.
+ all_dependent_configs = [ ":base_libs" ]
+ ldflags = []
+
+ if (!is_chromeos) {
+ sources -= [
+ "sys_info_chromeos.cc",
+ ]
+ }
+
+ # Remove nacl stuff.
+ if (!is_nacl) {
+ sources -= [
+ "os_compat_nacl.cc",
+ "os_compat_nacl.h",
+ "rand_util_nacl.cc",
+ "memory/shared_memory_nacl.cc",
+ ]
+ }
+
+ # Windows.
+ if (is_win && !is_nacl) {
+ sources -= [
+ "strings/string16.cc",
+ # Not using sha1_win.cc because it may have caused a
+ # regression to page cycler moz.
+ "sha1_win.cc",
+ ]
+
+ if (is_component_build) {
+ sources -= "debug/debug_on_start_win.cc"
+ }
+ } else {
+ # Non-Windows.
+ deps += "//third_party/libevent"
+ }
+
+ # Mac.
+ if (is_mac) {
+ sources -= [
+ "base_paths_posix.cc",
+ "native_library_posix.cc",
+ "strings/sys_string_conversions_posix.cc",
+ ]
+ deps += "//third_party/mach_override"
+ } else {
+ # Non-Mac.
+ sources -= "files/file_path_watcher_kqueue.cc"
+ }
+
+ # Linux.
+ if (is_linux) {
+ # TODO(brettw) these will need to be parameterized at some point.
+ linux_configs = [
+ "//build/config/linux/system:glib",
+ "//build/config/linux/system:gtk",
+ "//build/config/linux/system:x11",
+ ]
+ configs += linux_configs
+ all_dependent_configs += linux_configs
+
+ deps += [
+ "//base/third_party/symbolize",
+ "//base/third_party/xdg_mime",
+ "//base/third_party/xdg_user_dirs",
+ ]
+ } else {
+ # Non-Linux.
+ sources -= [
+ "message_loop/message_pump_glib.cc",
+ "message_loop/message_pump_glib.h",
+ "message_loop/message_pump_gtk.cc",
+ "message_loop/message_pump_gtk.h",
+ ]
+ }
+
+ # Non-Mac Unix stuff.
+ if (is_mac) { #!is_posix || is_mac) {
+ sources -= [
+ "nix/mime_util_xdg.cc",
+ "nix/mime_util_xdg.h",
+ "nix/xdg_util.cc",
+ "nix/xdg_util.h",
+ "third_party/xdg_mime/xdgmime.h",
+ ]
+ }
+}
+
+# This is the subset of files from base that should not be used with a dynamic
+# library. Note that this library cannot depend on base because base depends on
+# base_static.
+static_library("base_static") {
+ sources = [
+ "base_switches.cc",
+ "base_switches.h",
+ "win/pe_image.cc",
+ "win/pe_image.h",
+ ]
+}
+
+component("base_i18n") {
+ sources = [
+ "i18n/base_i18n_export.h",
+ "i18n/bidi_line_iterator.cc",
+ "i18n/bidi_line_iterator.h",
+ "i18n/break_iterator.cc",
+ "i18n/break_iterator.h",
+ "i18n/char_iterator.cc",
+ "i18n/char_iterator.h",
+ "i18n/case_conversion.cc",
+ "i18n/case_conversion.h",
+ "i18n/file_util_icu.cc",
+ "i18n/file_util_icu.h",
+ "i18n/icu_encoding_detection.cc",
+ "i18n/icu_encoding_detection.h",
+ "i18n/icu_string_conversions.cc",
+ "i18n/icu_string_conversions.h",
+ "i18n/icu_util.cc",
+ "i18n/icu_util.h",
+ "i18n/number_formatting.cc",
+ "i18n/number_formatting.h",
+ "i18n/rtl.cc",
+ "i18n/rtl.h",
+ "i18n/string_compare.cc",
+ "i18n/string_compare.h",
+ "i18n/string_search.cc",
+ "i18n/string_search.h",
+ "i18n/time_formatting.cc",
+ "i18n/time_formatting.h",
+ ]
+ deps = [
+ ":base",
+ "//base/third_party/dynamic_annotations",
+ "//third_party/icu:icui18n",
+ "//third_party/icu:icuuc",
+ ]
+ defines = [
+ "BASE_I18N_IMPLEMENTATION",
+ ]
+ #'conditions': [
+ # ['toolkit_uses_gtk==1', {
+ # 'deps': [
+ # # i18n/rtl.cc uses gtk
+ # '../build/linux/system.gyp:gtk',
+ # ],
+ # }],
+ # ['OS == "win"', {
+ # # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ # 'msvs_disabled_warnings': [
+ # 4267,
+ # ],
+ # }],
+ #],
+ #'export_dependent_settings': [
+ # 'base',
+ #],
+ #'variables': {
+ # 'enable_wexit_time_destructors': 1,
+ # 'optimize': 'max',
+ #},
+}
+
+static_library("test_support_base") {
+ sources = [
+ "perftimer.cc",
+ "test/expectations/expectation.cc",
+ "test/expectations/expectation.h",
+ "test/expectations/parser.cc",
+ "test/expectations/parser.h",
+ "test/mock_chrome_application_mac.h",
+ "test/mock_chrome_application_mac.mm",
+ "test/mock_devices_changed_observer.cc",
+ "test/mock_devices_changed_observer.h",
+ "test/mock_time_provider.cc",
+ "test/mock_time_provider.h",
+ "test/multiprocess_test.cc",
+ "test/multiprocess_test.h",
+ "test/multiprocess_test_android.cc",
+ "test/null_task_runner.cc",
+ "test/null_task_runner.h",
+ "test/perf_test_suite.cc",
+ "test/perf_test_suite.h",
+ "test/scoped_locale.cc",
+ "test/scoped_locale.h",
+ "test/scoped_path_override.cc",
+ "test/scoped_path_override.h",
+ "test/sequenced_task_runner_test_template.cc",
+ "test/sequenced_task_runner_test_template.h",
+ "test/sequenced_worker_pool_owner.cc",
+ "test/sequenced_worker_pool_owner.h",
+ "test/simple_test_clock.cc",
+ "test/simple_test_clock.h",
+ "test/simple_test_tick_clock.cc",
+ "test/simple_test_tick_clock.h",
+ "test/task_runner_test_template.cc",
+ "test/task_runner_test_template.h",
+ "test/test_file_util.h",
+ "test/test_file_util_linux.cc",
+ "test/test_file_util_mac.cc",
+ "test/test_file_util_posix.cc",
+ "test/test_file_util_win.cc",
+ "test/test_listener_ios.h",
+ "test/test_listener_ios.mm",
+ "test/test_pending_task.cc",
+ "test/test_pending_task.h",
+ "test/test_process_killer_win.cc",
+ "test/test_process_killer_win.h",
+ "test/test_reg_util_win.cc",
+ "test/test_reg_util_win.h",
+ "test/test_shortcut_win.cc",
+ "test/test_shortcut_win.h",
+ "test/test_simple_task_runner.cc",
+ "test/test_simple_task_runner.h",
+ "test/test_suite.cc",
+ "test/test_suite.h",
+ "test/test_support_android.cc",
+ "test/test_support_android.h",
+ "test/test_support_ios.h",
+ "test/test_support_ios.mm",
+ "test/test_switches.cc",
+ "test/test_switches.h",
+ "test/test_timeouts.cc",
+ "test/test_timeouts.h",
+ "test/thread_test_helper.cc",
+ "test/thread_test_helper.h",
+ "test/trace_event_analyzer.cc",
+ "test/trace_event_analyzer.h",
+ "test/values_test_util.cc",
+ "test/values_test_util.h",
+ ]
+ deps = [
+ ":base",
+ ":base_static",
+ ":base_i18n",
+ "//testing:gmock",
+ "//testing:gtest",
+ ]
+
+ if (!is_posix) {
+ sources -= [
+ "test/scoped_locale.cc",
+ "test/scoped_locale.h",
+ ]
+ }
+ if (is_ios) {
+ # Pull in specific Mac files for iOS (which have been filtered out
+ # by file name rules).
+ { # Temporarily override the assignment filter in a new scope.
+ set_sources_assignment_filter([])
+ sources += "test/test_file_util_mac.cc"
+ }
+ }
+ #if (!is_bsd) {
+ # sources -= "test/test_file_util_linux.cc"
+ #}
+ #if (use_gtk) {
+ # deps += "/build/linux/system:gtk"
+ #}
+ #export_dependent_settings [
+ # 'base',
+ #]
+}
+
+config("perf_test_config") {
+ defines = [ "PERF_TEST" ]
+}
+
+static_library("test_support_perf") {
+ sources = [
+ "perftimer.cc",
+ "test/run_all_perftests.cc",
+ ]
+ deps = [
+ ":base",
+ "//testing:gtest",
+ ]
+
+ direct_dependent_configs = [ ":perf_test_config" ]
+
+ #if (toolkit_uses_gtk) {
+ # deps += "/build/linux/system:gtk",
+ #}
+}
+
+static_library("run_all_unittests") {
+ sources = [
+ "test/run_all_unittests.cc",
+ ]
+ deps = [
+ ":test_support_base",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/base/allocator/BUILD.gn b/chromium/tools/gn/secondary/base/allocator/BUILD.gn
new file mode 100644
index 00000000000..6766911463f
--- /dev/null
+++ b/chromium/tools/gn/secondary/base/allocator/BUILD.gn
@@ -0,0 +1,10 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("allocator_extension_thunks") {
+ sources = [
+ "allocator_extension_thunks.cc",
+ "allocator_extension_thunks.h",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/base/third_party/dynamic_annotations/BUILD.gn b/chromium/tools/gn/secondary/base/third_party/dynamic_annotations/BUILD.gn
new file mode 100644
index 00000000000..bf050bf7914
--- /dev/null
+++ b/chromium/tools/gn/secondary/base/third_party/dynamic_annotations/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("dynamic_annotations") {
+ sources = [
+ "dynamic_annotations.c",
+ "dynamic_annotations.h",
+ "../valgrind/valgrind.h",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/base/third_party/nspr/BUILD.gn b/chromium/tools/gn/secondary/base/third_party/nspr/BUILD.gn
new file mode 100644
index 00000000000..dafd9f19c3d
--- /dev/null
+++ b/chromium/tools/gn/secondary/base/third_party/nspr/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("nspr") {
+ sources = [
+ "prcpucfg.h",
+ "prcpucfg_freebsd.h",
+ "prcpucfg_linux.h",
+ "prcpucfg_mac.h",
+ "prcpucfg_nacl.h",
+ "prcpucfg_openbsd.h",
+ "prcpucfg_solaris.h",
+ "prcpucfg_win.h",
+ "prtime.cc",
+ "prtime.h",
+ "prtypes.h",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/base/third_party/symbolize/BUILD.gn b/chromium/tools/gn/secondary/base/third_party/symbolize/BUILD.gn
new file mode 100644
index 00000000000..c13c0d86f4f
--- /dev/null
+++ b/chromium/tools/gn/secondary/base/third_party/symbolize/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("symbolize") {
+ sources = [
+ "config.h",
+ "demangle.cc",
+ "demangle.h",
+ "glog/logging.h",
+ "glog/raw_logging.h",
+ "symbolize.cc",
+ "symbolize.h",
+ "utilities.h",
+ ]
+
+ configs -= "//build/config/compiler:chromium_code"
+ configs += "//build/config/compiler:no_chromium_code"
+}
diff --git a/chromium/tools/gn/secondary/base/third_party/xdg_mime/BUILD.gn b/chromium/tools/gn/secondary/base/third_party/xdg_mime/BUILD.gn
new file mode 100644
index 00000000000..9e51bc112ea
--- /dev/null
+++ b/chromium/tools/gn/secondary/base/third_party/xdg_mime/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("xdg_mime") {
+ sources = [
+ "xdgmime.c",
+ "xdgmime.h",
+ "xdgmimealias.c",
+ "xdgmimealias.h",
+ "xdgmimecache.c",
+ "xdgmimecache.h",
+ "xdgmimeglob.c",
+ "xdgmimeglob.h",
+ "xdgmimeicon.c",
+ "xdgmimeicon.h",
+ "xdgmimeint.c",
+ "xdgmimeint.h",
+ "xdgmimemagic.c",
+ "xdgmimemagic.h",
+ "xdgmimeparent.c",
+ "xdgmimeparent.h",
+ ]
+
+ configs -= "//build/config/compiler:chromium_code"
+ configs += "//build/config/compiler:no_chromium_code"
+}
diff --git a/chromium/tools/gn/secondary/base/third_party/xdg_user_dirs/BUILD.gn b/chromium/tools/gn/secondary/base/third_party/xdg_user_dirs/BUILD.gn
new file mode 100644
index 00000000000..f2145b7863f
--- /dev/null
+++ b/chromium/tools/gn/secondary/base/third_party/xdg_user_dirs/BUILD.gn
@@ -0,0 +1,10 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("xdg_user_dirs") {
+ sources = [
+ "xdg_user_dir_lookup.cc",
+ "xdg_user_dir_lookup.h",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/build/config/BUILD.gn b/chromium/tools/gn/secondary/build/config/BUILD.gn
new file mode 100644
index 00000000000..c9fc2e7d3d0
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/BUILD.gn
@@ -0,0 +1,52 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("my_msvs") {
+ defines = [
+ "CHROMIUM_BUILD",
+ "TOOLKIT_VIEWS=1",
+ "USE_LIBJPEG_TURBO=1",
+ "ENABLE_ONE_CLICK_SIGNIN",
+ "ENABLE_REMOTING=1",
+ "ENABLE_WEBRTC=1",
+ "ENABLE_CONFIGURATION_POLICY",
+ "ENABLE_INPUT_SPEECH",
+ "ENABLE_NOTIFICATIONS",
+ "ENABLE_GPU=1",
+ "ENABLE_EGLIMAGE=1",
+ "ENABLE_TASK_MANAGER=1",
+ "ENABLE_EXTENSIONS=1",
+ "ENABLE_PLUGIN_INSTALLATION=1",
+ "ENABLE_PLUGINS=1",
+ "ENABLE_SESSION_SERVICE=1",
+ "ENABLE_THEMES=1",
+ "ENABLE_AUTOFILL_DIALOG=1",
+ "ENABLE_BACKGROUND=1",
+ "ENABLE_AUTOMATION=1",
+ "ENABLE_GOOGLE_NOW=1",
+ "ENABLE_LANGUAGE_DETECTION=1",
+ "ENABLE_PRINTING=1",
+ "ENABLE_CAPTIVE_PORTAL_DETECTION=1",
+ "ENABLE_APP_LIST=1",
+ "ENABLE_MESSAGE_CENTER=1",
+ "ENABLE_SETTINGS_APP=1",
+ "ENABLE_MANAGED_USERS=1",
+ ]
+}
+
+config("feature_flags") {
+ #defines =
+}
+
+config("debug") {
+ defines = [
+ "_DEBUG",
+ "DYNAMIC_ANNOTATIONS_ENABLED=1",
+ "WTF_USE_DYNAMIC_ANNOTATIONS=1",
+ ]
+}
+
+config("release") {
+
+}
diff --git a/chromium/tools/gn/secondary/build/config/BUILDCONFIG.gn b/chromium/tools/gn/secondary/build/config/BUILDCONFIG.gn
new file mode 100644
index 00000000000..5756e84eb79
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/BUILDCONFIG.gn
@@ -0,0 +1,210 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# =============================================================================
+# BUILD FLAGS
+# =============================================================================
+#
+# This block lists input arguments to the build, along with their default
+# values. GN requires listing them explicitly so it can validate input and have
+# a central place to manage the build flags.
+#
+# If a value is specified on the command line, it will overwrite the defaults
+# given here, otherwise the default will be injected into the root scope.
+#
+# KEEP IN ALPHABETICAL ORDER and write a good description for everything.
+# Use "is_*" names for intrinsic platform descriptions and build modes, and
+# "use_*" names for optional features libraries, and configurations.
+declare_args() {
+ is_android = 0
+ is_component_build = 1
+ is_chromeos = 0
+ is_debug = 1
+ is_ios = 0
+ use_ash = 0
+ use_aura = 0
+ use_ozone = 0
+}
+
+# =============================================================================
+# SOURCES FILTERS
+# =============================================================================
+#
+# These patterns filter out platform-specific files when assigning to the
+# sources variable. The magic variable |sources_assignment_filter| is applied
+# to each assignment or appending to the sources variable and matches are
+# automatcally removed.
+#
+# We define lists of filters for each platform for all builds so they can
+# be used by individual targets if necessary (a target can always change
+# sources_assignment_filter on itself if it needs something more specific).
+#
+# Note that the patterns are NOT regular expressions. Only "*" and "\b" (path
+# boundary = end of string or slash) are supported, and the entire string
+# muct match the pattern (so you need "*.cc" to match all .cc files, for
+# example).
+
+windows_sources_filters = [
+ "*_win.cc",
+ "*_win.h",
+ "*_win_unittest.cc",
+ "*\bwin/*",
+]
+mac_sources_filters = [
+ "*_mac.h",
+ "*_mac.cc",
+ "*_mac.mm",
+ "*_mac_unittest.h",
+ "*_mac_unittest.cc",
+ "*_mac_unittest.mm",
+ "*\bmac/*",
+ "*_cocoa.h",
+ "*_cocoa.cc",
+ "*_cocoa.mm",
+ "*_cocoa_unittest.h",
+ "*_cocoa_unittest.cc",
+ "*_cocoa_unittest.mm",
+ "*\bcocoa/*",
+]
+ios_sources_filters = [
+ "*_ios.h",
+ "*_ios.cc",
+ "*_ios.mm",
+ "*_ios_unittest.h",
+ "*_ios_unittest.cc",
+ "*_ios_unittest.mm",
+ "*\bios/*",
+]
+objective_c_sources_filters = [
+ "*.mm",
+]
+linux_sources_filters = [
+ "*_linux.h",
+ "*_linux.cc",
+ "*_linux_unittest.h",
+ "*_linux_unittest.cc",
+ "*\blinux/*",
+]
+android_sources_filters = [
+ "*_android.h",
+ "*_android.cc",
+ "*_android_unittest.h",
+ "*_android_unittest.cc",
+ "*\bandroid/*",
+]
+posix_sources_filters = [
+ "*_posix.h",
+ "*_posix.cc",
+ "*_posix_unittest.h",
+ "*_posix_unittest.cc",
+ "*\bposix/*",
+]
+
+# Construct the full list of sources we're using for this platform.
+sources_assignment_filter = []
+if (is_win) {
+ sources_assignment_filter += posix_sources_filters
+} else {
+ sources_assignment_filter += windows_sources_filters
+}
+if (!is_mac) {
+ sources_assignment_filter += mac_sources_filters
+}
+if (!is_ios) {
+ sources_assignment_filter += ios_sources_filters
+}
+if (!is_mac && !is_ios) {
+ sources_assignment_filter += objective_c_sources_filters
+}
+if (!is_linux) {
+ sources_assignment_filter += linux_sources_filters
+}
+if (!is_android) {
+ sources_assignment_filter += android_sources_filters
+}
+
+# This is the actual set.
+set_sources_assignment_filter(sources_assignment_filter)
+
+# =============================================================================
+# SYSTEM CONFIG
+# =============================================================================
+
+is_nacl = 0
+
+# =============================================================================
+# BUILD OPTIONS
+# =============================================================================
+
+if (is_component_build) {
+ component_mode = "shared_library"
+} else {
+ component_mode = "static_library"
+}
+
+# =============================================================================
+# TARGET DEFAULTS
+# =============================================================================
+#
+# Set up the default configuration for every build target of the given type.
+# The values configured here will be automatically set on the scope of the
+# corresponding target. Target definitions can add or remove to the settings
+# here as needed.
+
+# Holds all configs used for making native executables and libraries, to avoid
+# duplication in each target below.
+native_compiler_configs = [
+ "//build/config:my_msvs", # TODO(brettw) eraseme
+
+ "//build/config/compiler:compiler",
+ "//build/config/compiler:chromium_code",
+ "//build/config/compiler:default_warnings",
+ "//build/config/compiler:no_rtti",
+ "//build/config/compiler:runtime_library",
+]
+if (is_win) {
+ native_compiler_configs += "//build/config/win:sdk"
+} else if (is_mac) {
+ # TODO(brettw) this should be in an if (is_clang) block instead but I haven't
+ # written an is_clang flag yet.
+ native_compiler_configs += "//build/config/clang:find_bad_constructs"
+}
+
+if (is_debug) {
+ native_compiler_configs += "//build/config:debug"
+} else {
+ native_compiler_configs += "//build/config:release"
+}
+
+set_defaults("executable") {
+ configs = native_compiler_configs
+ if (is_mac) {
+ configs += "//build/config/mac:mac_dynamic_flags"
+ } else if (is_linux) {
+ configs += "//build/config/linux:executable_ldconfig"
+ }
+}
+
+set_defaults("static_library") {
+ configs = native_compiler_configs
+}
+
+set_defaults("shared_library") {
+ configs = native_compiler_configs
+ if (is_mac) {
+ configs += "//build/config/mac:mac_dynamic_flags"
+ }
+}
+
+# ==============================================================================
+# TOOLCHAIN SETUP
+# ==============================================================================
+
+if (is_win) {
+ set_default_toolchain("//build/config/win:32")
+} else if (is_linux) {
+ set_default_toolchain("//build/config/linux/toolchain:gcc")
+} else if (is_mac) {
+ set_default_toolchain("//build/config/mac:clang")
+}
diff --git a/chromium/tools/gn/secondary/build/config/clang/BUILD.gn b/chromium/tools/gn/secondary/build/config/clang/BUILD.gn
new file mode 100644
index 00000000000..d083e86c11b
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/clang/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("find_bad_constructs") {
+ cflags = [
+ "-Xclang", "-load",
+ "-Xclang",
+
+ # TODO(brettw) express this in terms of a relative dir from the output.
+ # for now, assume the output dir is two levels deep under the source
+ # (like "out/Debug").
+ "../../third_party/llvm-build/Release+Asserts/lib/libFindBadConstructs.dylib",
+
+ "-Xclang", "-add-plugin",
+ "-Xclang", "find-bad-constructs",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/build/config/compiler/BUILD.gn b/chromium/tools/gn/secondary/build/config/compiler/BUILD.gn
new file mode 100644
index 00000000000..00ebe8f098c
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/compiler/BUILD.gn
@@ -0,0 +1,338 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Base compiler configuration.
+config("compiler") {
+ includes = [ "//" ]
+ if (is_win) {
+ cflags = [
+ # TODO(brettw) these probably need to be refactored.
+ "/Od", "/WX", "/Zi", "/Gy", "/GS", "/RTC1", "/EHsc",
+ ]
+ } else {
+ # Common GCC compiler flags setup.
+ # --------------------------------
+ cflags = [
+ "-fno-strict-aliasing", # See http://crbug.com/32204
+ "-fvisibility=hidden",
+ "-g", # Debug symbols.
+ ]
+ cflags_c = [
+ ]
+ cflags_cc = [
+ "-fno-exceptions",
+ "-fno-threadsafe-statics",
+ "-fvisibility-inlines-hidden",
+ ]
+ ldflags = [
+ "-Wl,-z,now",
+ "-Wl,-z,relro",
+ ]
+
+ # Optimization.
+ if (is_debug) {
+ cflags += [
+ "-O0" # No optimization.
+ ]
+ } else {
+ # TODO(brettw) release optimization.
+ }
+
+ # Stack protection.
+ # TODO(brettw) why do we have different values for all of these cases?
+ if (is_mac) {
+ cflags += "-fstack-protector-all"
+ } else if (is_chromeos) {
+ cflags += "-fstack-protector-strong"
+ } else if (is_linux) {
+ cflags += [ "-fstack-protector", "--param=ssp-buffer-size=4" ]
+ }
+
+ # Mac-specific compiler flags setup.
+ # ----------------------------------
+ if (is_mac) {
+ # These flags are shared between the C compiler and linker.
+ common_mac_flags = [
+ # TODO(brettw) obviously this arch flag needs to be parameterized.
+ "-arch i386",
+
+ # Set which SDK to use.
+ # TODO(brettw) this needs to be configurable somehow.
+ "-isysroot", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk",
+
+ "-mmacosx-version-min=10.6",
+ ]
+
+ cflags += common_mac_flags + [
+ # Without this, the constructors and destructors of a C++ object inside
+ # an Objective C struct won't be called, which is very bad.
+ "-fobjc-call-cxx-cdtors",
+ ]
+
+ cflags_c += [ "-std=c99" ]
+ cflags_cc += [ "-std=gnu++11" ]
+
+ ldflags += common_mac_flags + [
+ "-L.",
+
+ # TODO(brettW) I don't understand these options.
+ "-Wl,-rpath,@loader_path/.",
+ "-Wl,-rpath,@loader_path/../../..",
+ ]
+ }
+
+ # Linux-specific compiler flags setup.
+ # ------------------------------------
+ if (is_linux) {
+ cflags += [
+ "-fPIC",
+ "-pthread",
+ "-pipe", # Use pipes for communicating between sub-processes. Faster.
+ ]
+ ldflags += [
+ # Use Gold for linking: it is checked out in the source tree.
+ "-B$relative_build_to_source_root_dir/third_party/gold",
+
+ "-fPIC",
+ "-pthread",
+ "-Wl,-z,noexecstack",
+
+ # TODO(brettw) gold linker flags, only target.
+ # There seems to be a conflict of --icf and -pie in gold which can
+ # generate crashy binaries. As a security measure, -pie takes
+ # precendence for now.
+ # TODO(brettw) common.gypi has this only for target toolset.
+ #"-Wl,--icf=safe",
+ "-Wl,--icf=none",
+
+ # TODO(brettw) gold linker flags, only target.
+ # Experimentation found that using four linking threads
+ # saved ~20% of link time.
+ # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36
+ # Only apply this to the target linker, since the host
+ # linker might not be gold, but isn't used much anyway.
+ "-Wl,--threads",
+ "-Wl,--thread-count=4",
+ ]
+ }
+
+ # Clang-specific compiler flags setup.
+ # ------------------------------------
+ # TODO(brettw) these should be clang-only. For now, make it mac-only since
+ # that's where we always use clang.
+ if (is_mac) { # if (is_clang) {
+ cflags += [
+ "-fcolor-diagnostics",
+ ]
+ }
+ }
+}
+
+# runtime_library -------------------------------------------------------------
+#
+# Sets the runtime library and associated options.
+#
+# We don't bother making multiple versions that are toggle-able since there
+# is more than one axis of control (which makes it complicated) and there's
+# no practical reason for anybody to change this since the CRT must agree.
+
+config("runtime_library") {
+ if (is_component_build) {
+ # Component mode: dynamic CRT.
+ defines = [ "COMPONENT_BUILD" ]
+ if (is_win) {
+ # Since the library is shared, it requires exceptions or will give errors
+ # about things not matching, so keep exceptions on.
+ if (is_debug) {
+ cflags = [ "/MDd" ]
+ } else {
+ cflags = [ "/MD" ]
+ }
+ }
+ } else {
+ # Static CRT.
+ if (is_win) {
+ # We don't use exceptions, and when we link statically we can just get
+ # rid of them entirely.
+ defines = [ "_HAS_EXCEPTIONS=0" ]
+ if (is_debug) {
+ cflags = [ "/MTd" ]
+ } else {
+ cflags = [ "/MT" ]
+ }
+ }
+ }
+
+ if (is_win) {
+ defines += [
+ "__STD_C",
+ "__STDC_CONSTANT_MACROS",
+ "__STDC_FORMAT_MACROS",
+ "_CRT_RAND_S",
+ "_CRT_SECURE_NO_DEPRECATE",
+ "_SCL_SECURE_NO_DEPRECATE",
+ "_UNICODE",
+ "UNICODE",
+ ]
+ }
+}
+
+# chromium_code ---------------------------------------------------------------
+#
+# Toggles between higher and lower warnings for code that is (or isn't)
+# part of Chromium.
+
+config("chromium_code") {
+ if (is_win) {
+ cflags = [
+ "/W4", # Warning level 4.
+ ]
+ } else {
+ cflags = [
+ "-Wall",
+ "-Werror",
+
+ # GCC turns on -Wsign-compare for C++ under -Wall, but clang doesn't,
+ # so we specify it explicitly.
+ # TODO(fischman): remove this if http://llvm.org/PR10448 obsoletes it.
+ # http://code.google.com/p/chromium/issues/detail?id=90453
+ "-Wsign-compare",
+ ]
+
+ # In Chromium code, we define __STDC_foo_MACROS in order to get the
+ # C99 macros on Mac and Linux.
+ defines = [
+ "__STDC_CONSTANT_MACROS",
+ "__STDC_FORMAT_MACROS",
+ ]
+
+ # TODO(brettw) this should also be enabled on Linux but some files
+ # currently fail.
+ if (is_mac) {
+ cflags += "-Wextra"
+ }
+ }
+}
+config("no_chromium_code") {
+ if (is_win) {
+ cflags = [
+ "/W3", # Warning level 3.
+ "/wd4800", # Disable warning when forcing value to bool.
+ ]
+ defines = [
+ "_CRT_NONSTDC_NO_WARNINGS",
+ "_CRT_NONSTDC_NO_DEPRECATE",
+ ]
+ }
+}
+
+# rtti ------------------------------------------------------------------------
+#
+# Allows turning Run-Time Type Identification on or off.
+
+config("rtti") {
+ if (is_win) {
+ cflags_cc = [ "/GR" ]
+ }
+}
+config("no_rtti") {
+ if (is_win) {
+ cflags_cc = [ "/GR-" ]
+ } else {
+ cflags_cc = [ "-fno-rtti" ]
+ }
+}
+
+# Warnings ---------------------------------------------------------------------
+
+config("default_warnings") {
+ if (is_win) {
+ # Please keep ordered and add names if you add more.
+ cflags = [
+ "/wd4018", # Comparing signed and unsigned values.
+ "/wd4100", # Unreferenced formal function parameter.
+ "/wd4121", # Alignment of a member was sensitive to packing.
+ "/wd4125", # Decimal digit terminates octal escape sequence.
+ "/wd4127", # Conditional expression is constant.
+ "/wd4130", # Logical operation on address of string constant.
+ # TODO(brettw) is this necessary? If so, it should probably be on whoever
+ # is silly enough to be doing this rather than globally.
+ #"/wd4131", # Function uses old-style declarator.
+ "/wd4189", # A variable was declared and initialized but never used.
+ "/wd4201", # Nonstandard extension used: nameless struct/union.
+ "/wd4238", # Nonstandard extension used: class rvalue used as lvalue.
+ "/wd4244", # Conversion: possible loss of data.
+ "/wd4245", # Conversion: signed/unsigned mismatch,
+ "/wd4251", # Class needs to have dll-interface.
+ "/wd4310", # Cast truncates constant value.
+ "/wd4351", # Elements of array will be default initialized.
+ "/wd4355", # 'this' used in base member initializer list.
+ "/wd4396", # Inline friend template thing.
+ "/wd4428", # Universal character name encountered in source.
+ "/wd4481", # Nonstandard extension: override specifier.
+ "/wd4503", # Decorated name length exceeded, name was truncated.
+ "/wd4505", # Unreferenced local function has been removed.
+ "/wd4510", # Default constructor could not be generated.
+ "/wd4512", # Assignment operator could not be generated.
+ "/wd4530", # Exception handler used, but unwind semantics not enabled.
+ "/wd4610", # Class can never be instantiated, constructor required.
+ "/wd4611", # C++ object destruction and 'catch'.
+ "/wd4701", # Potentially uninitialized local variable name used.
+ "/wd4702", # Unreachable code.
+ "/wd4706", # Assignment within conditional expression.
+ "/wd4819", # Character not in the current code page.
+ ]
+ } else {
+ # Common GCC warning setup.
+ cflags = [
+ # Enables.
+ "-Wendif-labels", # Weird old-style text after an #endif.
+
+ # Disables.
+ "-Wno-missing-field-initializers", # "struct foo f = {0};"
+ "-Wno-unused-parameter", # Unused function parameters.
+ "-Wno-write-strings",
+ ]
+
+ if (is_mac) {
+ cflags += [
+ "-Wnewline-eof",
+ ]
+ }
+
+ # TODO(brettw) Ones below here should be clang-only when we have a flag
+ # for it.
+ if (is_mac) { #if (is_clang) {
+ cflags += [
+ "-Wheader-hygiene",
+
+ # This warns on using ints as initializers for floats in
+ # initializer lists (e.g. |int a = f(); CGSize s = { a, a };|),
+ # which happens in several places in chrome code. Not sure if
+ # this is worth fixing.
+ "-Wno-c++11-narrowing",
+
+ # Don't die on dtoa code that uses a char as an array index.
+ # This is required solely for base/third_party/dmg_fp/dtoa.cc.
+ # TODO(brettw) move this to that project then!
+ "-Wno-char-subscripts",
+
+ # Warns on switches on enums that cover all enum values but
+ # also contain a default: branch. Chrome is full of that.
+ "-Wno-covered-switch-default",
+
+ # Clang considers the `register` keyword as deprecated, but e.g.
+ # code generated by flex (used in angle) contains that keyword.
+ # http://crbug.com/255186
+ "-Wno-deprecated-register",
+
+ # Clang spots more unused functions.
+ "-Wno-unused-function",
+
+ # Warns when a const char[] is converted to bool.
+ "-Wstring-conversion",
+ ]
+ }
+ }
+}
diff --git a/chromium/tools/gn/secondary/build/config/linux/BUILD.gn b/chromium/tools/gn/secondary/build/config/linux/BUILD.gn
new file mode 100644
index 00000000000..74804cb483a
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/linux/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Sets up the dynamic library search path to include our "lib" directory.
+config("executable_ldconfig") {
+ ldflags = [
+ # Want to pass "\$". Need to escape both '\' and '$'. GN will re-escape as
+ # required for ninja.
+ "-Wl,-rpath=\\\$ORIGIN/lib/",
+
+ "-Wl,-rpath-link=lib/",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/build/config/linux/system/BUILD.gn b/chromium/tools/gn/secondary/build/config/linux/system/BUILD.gn
new file mode 100644
index 00000000000..3cecca8d4b3
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/linux/system/BUILD.gn
@@ -0,0 +1,31 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+pkg_script = "pkg-config.py"
+
+config("glib") {
+ glib_packages = "glib-2.0 gmodule-2.0 gobject-2.0 gthread-2.0"
+
+ cflags = exec_script(pkg_script, [ "--cflags", glib_packages ], "list lines")
+ ldflags = exec_script(pkg_script, [ "--libs", glib_packages ], "list lines")
+ # if (use_x11) { # TODO(brettw) need to add use_x11
+ ldflags += "-lXtst"
+ #}
+}
+
+config("gtk") {
+ # Gtk requires gmodule, but it does not list it as a dependency in some
+ # misconfigured systems.
+ gtk_packages = "gmodule-2.0 gtk+-2.0 gthread-2.0"
+
+ cflags = exec_script(pkg_script, [ "--cflags", gtk_packages ], "list lines")
+ ldflags = exec_script(pkg_script, [ "--libs", gtk_packages ], "list lines")
+}
+
+config("x11") {
+ x11_packages = "x11 xi"
+
+ cflags = exec_script(pkg_script, [ "--cflags", x11_packages ], "list lines")
+ ldflags = exec_script(pkg_script, [ "--libs", x11_packages ], "list lines")
+}
diff --git a/chromium/tools/gn/secondary/build/config/linux/system/pkg-config.py b/chromium/tools/gn/secondary/build/config/linux/system/pkg-config.py
new file mode 100644
index 00000000000..1cee44883e1
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/linux/system/pkg-config.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import subprocess
+import sys
+
+sys.exit(subprocess.call(["pkg-config"] + sys.argv[1:]))
diff --git a/chromium/tools/gn/secondary/build/config/linux/toolchain/BUILD.gn b/chromium/tools/gn/secondary/build/config/linux/toolchain/BUILD.gn
new file mode 100644
index 00000000000..b3aed22e450
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/linux/toolchain/BUILD.gn
@@ -0,0 +1,47 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+cc = "gcc"
+cxx = "g++"
+ld = cxx
+
+toolchain("gcc") {
+ tool("cc") {
+ # cflags_pch_c
+ command = "$cc -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_c -c \$in -o \$out"
+ description = "CC \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("cxx") {
+ # cflags_pch_cc
+ command = "$cxx -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_cc -c \$in -o \$out"
+ description = "CXX \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("alink") {
+ command = "rm -f \$out && ar rcs \$out \$in"
+ description = "AR \$out"
+ }
+ tool("solink") {
+ command = "if [ ! -e \$lib -o ! -e \${lib}.TOC ]; then $ld -shared \$ldflags -o \$lib -Wl,-soname=\$soname -Wl,--whole-archive \$in \$solibs -Wl,--no-whole-archive \$libs && { readelf -d \${lib} | grep SONAME ; nm -gD -f p \${lib} | cut -f1-2 -d' '; } > \${lib}.TOC; else $ld -shared \$ldflags -o \$lib -Wl,-soname=\$soname -Wl,--whole-archive \$in \$solibs -Wl,--no-whole-archive \$libs && { readelf -d \${lib} | grep SONAME ; nm -gD -f p \${lib} | cut -f1-2 -d' '; } > \${lib}.tmp && if ! cmp -s \${lib}.tmp \${lib}.TOC; then mv \${lib}.tmp \${lib}.TOC ; fi; fi"
+ description = "SOLINK \$lib"
+ #pool = "link_pool"
+ restat = "1"
+ }
+ tool("link") {
+ command = "$ld \$ldflags -o \$out -Wl,--start-group \$in \$solibs -Wl,--end-group \$libs"
+ description = "LINK \$out"
+ #pool = "link_pool"
+ }
+ tool("stamp") {
+ command = "\${postbuilds}touch \$out"
+ description = "STAMP \$out"
+ }
+ tool("copy") {
+ command = "ln -f \$in \$out 2>/dev/null || (rm -rf \$out && cp -af \$in \$out)"
+ description = "COPY \$in \$out"
+ }
+}
diff --git a/chromium/tools/gn/secondary/build/config/mac/BUILD.gn b/chromium/tools/gn/secondary/build/config/mac/BUILD.gn
new file mode 100644
index 00000000000..cc33e517a60
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/mac/BUILD.gn
@@ -0,0 +1,76 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# On Mac, this is usefor everything except static libraries.
+config("mac_dynamic_flags") {
+ ldflags = [
+ "-Wl,-search_paths_first",
+ ]
+}
+
+cc = "../../third_party/llvm-build/Release+Asserts/bin/clang"
+cxx = "../../third_party/llvm-build/Release+Asserts/bin/clang++"
+ld = cxx
+
+toolchain("clang") {
+ tool("cc") {
+ command = "$cc -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_c \$cflags_pch_c -c \$in -o \$out"
+ description = "CC \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("cxx") {
+ command = "$cxx -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_cc \$cflags_pch_cc -c \$in -o \$out"
+ description = "CXX \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("objc") {
+ command = "$cc -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_c \$cflags_objc \$cflags_pch_objc -c \$in -o \$out"
+ description = "OBJC \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("objcxx") {
+ command = "$cxx -MMD -MF \$out.d \$defines \$includes \$cflags \$cflags_cc \$cflags_objcc \$cflags_pch_objcc -c \$in -o \$out"
+ description = "OBJCXX \$out"
+ depfile = "\$out.d"
+ deps = "gcc"
+ }
+ tool("alink") {
+ command = "rm -f \$out && ./gyp-mac-tool filter-libtool libtool \$libtool_flags -static -o \$out \$in \$postbuilds"
+ description = "LIBTOOL-STATIC \$out, POSTBUILDS"
+ }
+ tool("solink") {
+ command = "if [ ! -e \$lib -o ! -e \${lib}.TOC ] || otool -l \$lib | grep -q LC_REEXPORT_DYLIB ; then $ld -shared \$ldflags -o \$lib \$in \$solibs \$libs \$postbuilds && { otool -l \$lib | grep LC_ID_DYLIB -A 5; nm -gP \$lib | cut -f1-2 -d' ' | grep -v U\$\$; true; } > \${lib}.TOC; else $ld -shared \$ldflags -o \$lib \$in \$solibs \$libs \$postbuilds && { otool -l \$lib | grep LC_ID_DYLIB -A 5; nm -gP \$lib | cut -f1-2 -d' ' | grep -v U\$\$; true; } > \${lib}.tmp && if ! cmp -s \${lib}.tmp \${lib}.TOC; then mv \${lib}.tmp \${lib}.TOC ; fi; fi"
+ description = "SOLINK \$lib, POSTBUILDS"
+ #pool = "link_pool"
+ restat = "1"
+ }
+ tool("link") {
+ command = "$ld \$ldflags -o \$out \$in \$solibs \$libs \$postbuilds"
+ description = "LINK \$out, POSTBUILDS"
+ #pool = "link_pool"
+ }
+ #tool("infoplist") {
+ # command = "$cc -E -P -Wno-trigraphs -x c \$defines \$in -o \$out && plutil -convert xml1 \$out \$out"
+ # description = "INFOPLIST \$out"
+ #}
+ #tool("mac_tool") {
+ # command = "\$env ./gyp-mac-tool \$mactool_cmd \$in \$out"
+ # description = "MACTOOL \$mactool_cmd \$in"
+ #}
+ #tool("package_framework") {
+ # command = "./gyp-mac-tool package-framework \$out \$version \$postbuilds && touch \$out"
+ # description = "PACKAGE FRAMEWORK \$out, POSTBUILDS"
+ #}
+ tool("stamp") {
+ command = "\${postbuilds}touch \$out"
+ description = "STAMP \$out"
+ }
+ tool("copy") {
+ command = "ln -f \$in \$out 2>/dev/null || (rm -rf \$out && cp -af \$in \$out)"
+ description = "COPY \$in \$out"
+ }
+}
diff --git a/chromium/tools/gn/secondary/build/config/win/BUILD.gn b/chromium/tools/gn/secondary/build/config/win/BUILD.gn
new file mode 100644
index 00000000000..95b1b307378
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/win/BUILD.gn
@@ -0,0 +1,184 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Should only be running on Windows.
+assert(is_win)
+
+# Setup the Visual Studio state.
+#
+# Its argument is the location to write the environment files.
+# It will write "environment.x86" and "environment.x64" to this directory,
+# and return a list to us.
+#
+# The list contains the include path as its only element. (I'm expecting to
+# add more so it's currently a list inside a list.)
+msvc_config = [["foo"]]
+#exec_script("get_msvc_config.py",
+ # [relative_root_output_dir],
+ # "value")
+
+# 32-bit toolchain -------------------------------------------------------------
+
+toolchain("32") {
+ tool("cc") {
+ command = "ninja -t msvc -e \$arch -- cl.exe /nologo /showIncludes /FC @\$out.rsp /c \$in /Fo\$out /Fd\$pdbname"
+ description = "CC \$out"
+ rspfile = "\$out.rsp"
+ rspfile_content = "\$defines \$includes \$cflags \$cflags_c"
+ deps = "msvc"
+ }
+ tool("cxx") {
+ command = "ninja -t msvc -e \$arch -- cl.exe /nologo /showIncludes /FC @\$out.rsp /c \$in /Fo\$out /Fd\$pdbname"
+ description = "CXX \$out"
+ rspfile = "\$out.rsp"
+ rspfile_content = "\$defines \$includes \$cflags \$cflags_cc"
+ deps = "msvc"
+ }
+ #tool("idl") {
+ # command = $python_path gyp-win-tool midl-wrapper \$arch \$outdir \$tlb \$h \$dlldata \$iid \$
+ # \$proxy \$in \$idlflags
+ # description = IDL \$in
+ #}
+ #tool("rc") {
+ # command = $python_path gyp-win-tool rc-wrapper \$arch rc.exe \$defines \$includes \$rcflags \$
+ # /fo\$out \$in
+ # description = RC \$in
+ #}
+ #tool("asm") {
+ # command = $python_path gyp-win-tool asm-wrapper \$arch ml.exe \$defines \$includes /c /Fo \$
+ # \$out \$in
+ # description = ASM \$in
+ #}
+ tool("alink") {
+ command = "$python_path gyp-win-tool link-wrapper \$arch lib.exe /nologo /ignore:4221 /OUT:\$out @\$out.rsp"
+ description = "LIB \$out"
+ rspfile = "\$out.rsp"
+ rspfile_content = "\$in_newline \$libflags"
+ }
+ #tool("solink_embed_inc") {
+ # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag \$
+ # /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool \$
+ # manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && \$
+ # $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests \$
+ # -out:\$dll.manifest && $python_path gyp-win-tool manifest-to-rc \$arch \$dll.manifest \$
+ # \$dll.manifest.rc 2 && $python_path gyp-win-tool rc-wrapper \$arch rc.exe \$
+ # \$dll.manifest.rc && $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$
+ # \$implibflag /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp \$dll.manifest.res
+ # description = LINK_EMBED_INC(DLL) \$dll
+ # restat = 1
+ # rspfile = \$dll.rsp
+ # rspfile_content = \$libs \$in_newline \$ldflags
+ #}
+ #tool("solink_module_embed_inc") {
+ # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag \$
+ # /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool \$
+ # manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && \$
+ # $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests \$
+ # -out:\$dll.manifest && $python_path gyp-win-tool manifest-to-rc \$arch \$dll.manifest \$
+ # \$dll.manifest.rc 2 && $python_path gyp-win-tool rc-wrapper \$arch rc.exe \$
+ # \$dll.manifest.rc && $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$
+ # \$implibflag /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp \$dll.manifest.res
+ # description = LINK_EMBED_INC(DLL) \$dll
+ # restat = 1
+ # rspfile = \$dll.rsp
+ # rspfile_content = \$libs \$in_newline \$ldflags
+ #}
+ #rule link_embed_inc
+ # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo /OUT:\$out \$
+ # /PDB:\$out.pdb @\$out.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c \$
+ # if exist \$out.manifest del \$out.manifest && $python_path gyp-win-tool \$
+ # manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -out:\$out.manifest && \$
+ # $python_path gyp-win-tool manifest-to-rc \$arch \$out.manifest \$out.manifest.rc 1 && \$
+ # $python_path gyp-win-tool rc-wrapper \$arch rc.exe \$out.manifest.rc && \$
+ # $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo /OUT:\$out /PDB:\$out.pdb \$
+ # @\$out.rsp \$out.manifest.res
+ # description = LINK_EMBED_INC \$out
+ # rspfile = \$out.rsp
+ # rspfile_content = \$in_newline \$libs \$ldflags
+ #rule solink_embed
+ # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag \$
+ # /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool \$
+ # manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && \$
+ # $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests \$
+ # -outputresource:\$dll;2
+ # description = LINK_EMBED(DLL) \$dll
+ # restat = 1
+ # rspfile = \$dll.rsp
+ # rspfile_content = \$libs \$in_newline \$ldflags
+ #rule solink_module_embed
+ # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag \$
+ # /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool \$
+ # manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && \$
+ # $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests \$
+ # -outputresource:\$dll;2
+ # description = LINK_EMBED(DLL) \$dll
+ # restat = 1
+ # rspfile = \$dll.rsp
+ # rspfile_content = \$libs \$in_newline \$ldflags
+ #rule link_embed
+ # command = cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo /OUT:\$out \$
+ # /PDB:\$out.pdb @\$out.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c \$
+ # if exist \$out.manifest del \$out.manifest && $python_path gyp-win-tool \$
+ # manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -outputresource:\$out;1
+ # description = LINK_EMBED \$out
+ # rspfile = \$out.rsp
+ # rspfile_content = \$in_newline \$libs \$ldflags
+ tool("solink") {
+ command = "cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -out:\$dll.manifest"
+ description = "LINK(DLL) \$dll"
+ restat = "1"
+ rspfile = "\$dll.rsp"
+ rspfile_content = "\$libs \$in_newline \$ldflags"
+ }
+ tool("solink_module") {
+ command = "cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo \$implibflag /DLL /OUT:\$dll /PDB:\$dll.pdb @\$dll.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c if exist \$dll.manifest del \$dll.manifest && $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -out:\$dll.manifet"
+ description = "LINK(DLL) \$dll"
+ restat = "1"
+ rspfile = "\$dll.rsp"
+ rspfile_content = "\$libs \$in_newline \$ldflags"
+ }
+ tool("link") {
+ command = "cmd /c $python_path gyp-win-tool link-wrapper \$arch link.exe /nologo /OUT:\$out /PDB:\$out.pdb @\$out.rsp && $python_path gyp-win-tool manifest-wrapper \$arch cmd /c if exist \$out.manifest del \$out.manifest && $python_path gyp-win-tool manifest-wrapper \$arch mt.exe -nologo -manifest \$manifests -out:\$out.manifest"
+ description = "LINK \$out"
+ rspfile = "\$out.rsp"
+ rspfile_content = "\$in_newline \$libs \$ldflags"
+ }
+ tool("stamp") {
+ command = "$python_path gyp-win-tool stamp \$out"
+ description = "STAMP \$out"
+ }
+ tool("copy") {
+ command = "$python_path gyp-win-tool recursive-mirror \$in \$out"
+ description = "COPY \$in \$out"
+ }
+}
+
+# 64-bit toolchain -------------------------------------------------------------
+
+toolchain("64") {
+}
+
+# SDK setup --------------------------------------------------------------------
+
+config("sdk") {
+ # The include path is the stuff returned by the script plus out own WTL
+ # checkout.
+ # TODO(brettw) should adding WTL be at this level or should it be more on
+ # a per-project basis?
+ includes = msvc_config[0] + "../../third_party/wtl/include"
+
+ defines = [
+ "_ATL_NO_OPENGL",
+ "_SECURE_ATL",
+ "_WIN32_WINNT=0x0602",
+ "_WINDOWS",
+ "CERT_CHAIN_PARA_HAS_EXTRA_FIELDS",
+ "NOMINMAX",
+ "NTDDI_VERSION=0x06020000",
+ "PSAPI_VERSION=1",
+ "WIN32",
+ "WIN32_LEAN_AND_MEAN",
+ "WINVER=0x0602",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/build/config/win/get_msvc_config.py b/chromium/tools/gn/secondary/build/config/win/get_msvc_config.py
new file mode 100644
index 00000000000..01380cd8954
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/win/get_msvc_config.py
@@ -0,0 +1,77 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file returns the MSVC config used by the Windows build.
+# It's a bit hardcoded right now. I suspect we want to build this functionality
+# into GN itself in the future.
+
+import sys
+
+# This script expects one parameter: the path to the root output directory.
+
+# TODO(brettw): do escaping.
+def FormatStringForGN(x):
+ return '"' + x + '"'
+
+def PrintListOfStrings(x):
+ print '['
+ for i in x:
+ print FormatStringForGN(i) + ', '
+ print ']'
+
+# GN wants system-absolutepaths to begin in slashes.
+sdk_root = '/C:\\Program Files (x86)\\Windows Kits\\8.0\\'
+vs_root = '/C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\'
+
+def GetIncludes():
+ return [
+ sdk_root + 'Include\\shared',
+ sdk_root + 'Include\\um',
+ sdk_root + 'Include\\winrt',
+ vs_root + 'VC\\atlmfc\\include'
+ ]
+
+def _FormatAsEnvironmentBlock(envvar_dict):
+ """Format as an 'environment block' directly suitable for CreateProcess.
+ Briefly this is a list of key=value\0, terminated by an additional \0. See
+ CreateProcess documentation for more details."""
+ block = ''
+ nul = '\0'
+ for key, value in envvar_dict.iteritems():
+ block += key + '=' + value + nul
+ block += nul
+ return block
+
+def WriteEnvFile(file_path, values):
+ f = open(file_path, "w")
+ f.write(_FormatAsEnvironmentBlock(values))
+
+includes = GetIncludes()
+
+# Write the environment files.
+WriteEnvFile(sys.argv[1] + '\\environment.x86',
+ { 'TMP': 'C:\\Users\\brettw\\AppData\\Local\\Temp',
+ 'SYSTEMROOT': 'C:\\Windows',
+ 'TEMP': 'C:\\Users\\brettw\\AppData\\Local\\Temp',
+ 'LIB': 'c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib;',
+ 'LIBPATH': 'C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;',
+ 'PATH': 'C:\\apps\\depot_tools\\python_bin;c:\\Program Files (x86)\\Microsoft F#\\v4.0\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VSTSDB\\Deploy;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\BIN;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Tools;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\VCPackages;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin;C:\\apps\\depot_tools\\python_bin;C:\\apps\\depot_tools\\;C:\\apps\\depot_tools\\;C:\\apps\\depot_tools\\;c:\\Program Files (x86)\\Microsoft F#\\v4.0\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VSTSDB\\Deploy;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\BIN;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Tools;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\VCPackages;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\windows\\corpam;C:\\python_26_amd64\\files;C:\\Windows\\ccmsetup;c:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;c:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;c:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;c:\\cygwin\\bin;C:\\apps\\;C:\\apps\\depot_tools;C:\\Program Files (x86)\\Windows Kits\\8.0\\Windows Performance Toolkit\\;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Google\\Cert Installer;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Google\\google_appengine\\',
+ 'PATHEXT': '=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC',
+ 'INCLUDE': 'c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\INCLUDE;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\INCLUDE;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;'})
+
+WriteEnvFile(sys.argv[1] + '\\environment.x64',
+ { 'TMP': 'C:\\Users\\brettw\\AppData\\Local\\Temp',
+ 'SYSTEMROOT': 'C:\\Windows',
+ 'TEMP': 'C:\\Users\\brettw\\AppData\\Local\\Temp',
+ 'LIB': 'c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB\\amd64;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB\\amd64;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib\\x64;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\lib;',
+ 'LIBPATH': 'C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework64\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB\\amd64;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB\\amd64;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\LIB;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\LIB;',
+ 'PATH': 'C:\\apps\\depot_tools\\python_bin;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\BIN\\amd64;C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework64\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\VCPackages;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Tools;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools\\x64;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\x64;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin;C:\\apps\\depot_tools\\python_bin;C:\\apps\\depot_tools\\;C:\\apps\\depot_tools\\;C:\\apps\\depot_tools\\;c:\\Program Files (x86)\\Microsoft F#\\v4.0\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VSTSDB\\Deploy;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\BIN;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\Tools;C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework\\v3.5;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\VCPackages;C:\\Program Files (x86)\\HTML Help Workshop;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\NETFX 4.0 Tools;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\windows\\corpam;C:\\python_26_amd64\\files;C:\\Windows\\ccmsetup;c:\\Program Files (x86)\\Microsoft SQL Server\\100\\Tools\\Binn\\;c:\\Program Files\\Microsoft SQL Server\\100\\Tools\\Binn\\;c:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;c:\\cygwin\\bin;C:\\apps\\;C:\\apps\\depot_tools;C:\\Program Files (x86)\\Windows Kits\\8.0\\Windows Performance Toolkit\\;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Google\\Cert Installer;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Google\\google_appengine\\',
+ 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC',
+ 'INCLUDE': 'c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\INCLUDE;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\INCLUDE;c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\ATLMFC\\INCLUDE;C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\include;'})
+
+# Return the includes and such.
+print '['
+PrintListOfStrings(includes)
+print ']'
+
diff --git a/chromium/tools/gn/secondary/build/config/win/get_msvc_config_real.py b/chromium/tools/gn/secondary/build/config/win/get_msvc_config_real.py
new file mode 100644
index 00000000000..a209d7ff8a1
--- /dev/null
+++ b/chromium/tools/gn/secondary/build/config/win/get_msvc_config_real.py
@@ -0,0 +1,575 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file copies the logic from GYP to find the MSVC configuration. It's not
+# currently used because it is too slow. We will probably build this
+# functionality into the C++ code in the future.
+
+"""Handle version information related to Visual Stuio."""
+
+import errno
+import os
+import re
+import subprocess
+import sys
+
+class VisualStudioVersion(object):
+ """Information regarding a version of Visual Studio."""
+
+ def __init__(self, short_name, description,
+ solution_version, project_version, flat_sln, uses_vcxproj,
+ path, sdk_based, default_toolset=None):
+ self.short_name = short_name
+ self.description = description
+ self.solution_version = solution_version
+ self.project_version = project_version
+ self.flat_sln = flat_sln
+ self.uses_vcxproj = uses_vcxproj
+ self.path = path
+ self.sdk_based = sdk_based
+ self.default_toolset = default_toolset
+
+ def ShortName(self):
+ return self.short_name
+
+ def Description(self):
+ """Get the full description of the version."""
+ return self.description
+
+ def SolutionVersion(self):
+ """Get the version number of the sln files."""
+ return self.solution_version
+
+ def ProjectVersion(self):
+ """Get the version number of the vcproj or vcxproj files."""
+ return self.project_version
+
+ def FlatSolution(self):
+ return self.flat_sln
+
+ def UsesVcxproj(self):
+ """Returns true if this version uses a vcxproj file."""
+ return self.uses_vcxproj
+
+ def ProjectExtension(self):
+ """Returns the file extension for the project."""
+ return self.uses_vcxproj and '.vcxproj' or '.vcproj'
+
+ def Path(self):
+ """Returns the path to Visual Studio installation."""
+ return self.path
+
+ def ToolPath(self, tool):
+ """Returns the path to a given compiler tool. """
+ return os.path.normpath(os.path.join(self.path, "VC/bin", tool))
+
+ def DefaultToolset(self):
+ """Returns the msbuild toolset version that will be used in the absence
+ of a user override."""
+ return self.default_toolset
+
+ def SetupScript(self, target_arch):
+ """Returns a command (with arguments) to be used to set up the
+ environment."""
+ # Check if we are running in the SDK command line environment and use
+ # the setup script from the SDK if so. |target_arch| should be either
+ # 'x86' or 'x64'.
+ assert target_arch in ('x86', 'x64')
+ sdk_dir = os.environ.get('WindowsSDKDir')
+ if self.sdk_based and sdk_dir:
+ return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')),
+ '/' + target_arch]
+ else:
+ # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls
+ # vcvars32, which it can only find if VS??COMNTOOLS is set, which it
+ # isn't always.
+ if target_arch == 'x86':
+ return [os.path.normpath(
+ os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))]
+ else:
+ assert target_arch == 'x64'
+ arg = 'x86_amd64'
+ if (os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or
+ os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'):
+ # Use the 64-on-64 compiler if we can.
+ arg = 'amd64'
+ return [os.path.normpath(
+ os.path.join(self.path, 'VC/vcvarsall.bat')), arg]
+
+
+def _RegistryQueryBase(sysdir, key, value):
+ """Use reg.exe to read a particular key.
+
+ While ideally we might use the win32 module, we would like gyp to be
+ python neutral, so for instance cygwin python lacks this module.
+
+ Arguments:
+ sysdir: The system subdirectory to attempt to launch reg.exe from.
+ key: The registry key to read from.
+ value: The particular value to read.
+ Return:
+ stdout from reg.exe, or None for failure.
+ """
+ # Skip if not on Windows or Python Win32 setup issue
+ if sys.platform not in ('win32', 'cygwin'):
+ return None
+ # Setup params to pass to and attempt to launch reg.exe
+ cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
+ 'query', key]
+ if value:
+ cmd.extend(['/v', value])
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
+ # Note that the error text may be in [1] in some cases
+ text = p.communicate()[0]
+ # Check return code from reg.exe; officially 0==success and 1==error
+ if p.returncode:
+ return None
+ return text
+
+
+def _RegistryQuery(key, value=None):
+ """Use reg.exe to read a particular key through _RegistryQueryBase.
+
+ First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
+ that fails, it falls back to System32. Sysnative is available on Vista and
+ up and available on Windows Server 2003 and XP through KB patch 942589. Note
+ that Sysnative will always fail if using 64-bit python due to it being a
+ virtual directory and System32 will work correctly in the first place.
+
+ KB 942589 - http://support.microsoft.com/kb/942589/en-us.
+
+ Arguments:
+ key: The registry key.
+ value: The particular registry value to read (optional).
+ Return:
+ stdout from reg.exe, or None for failure.
+ """
+ text = None
+ try:
+ text = _RegistryQueryBase('Sysnative', key, value)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ text = _RegistryQueryBase('System32', key, value)
+ else:
+ raise
+ return text
+
+
+def _RegistryGetValue(key, value):
+ """Use reg.exe to obtain the value of a registry key.
+
+ Args:
+ key: The registry key.
+ value: The particular registry value to read.
+ Return:
+ contents of the registry key's value, or None on failure.
+ """
+ text = _RegistryQuery(key, value)
+ if not text:
+ return None
+ # Extract value.
+ match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
+ if not match:
+ return None
+ return match.group(1)
+
+
+def _RegistryKeyExists(key):
+ """Use reg.exe to see if a key exists.
+
+ Args:
+ key: The registry key to check.
+ Return:
+ True if the key exists
+ """
+ if not _RegistryQuery(key):
+ return False
+ return True
+
+
+def _CreateVersion(name, path, sdk_based=False):
+ """Sets up MSVS project generation.
+
+ Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
+ autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
+ passed in that doesn't match a value in versions python will throw a error.
+ """
+ if path:
+ path = os.path.normpath(path)
+ versions = {
+ '2013': VisualStudioVersion('2013',
+ 'Visual Studio 2013',
+ solution_version='13.00',
+ project_version='4.0',
+ flat_sln=False,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based,
+ default_toolset='v110'),
+ '2013e': VisualStudioVersion('2013e',
+ 'Visual Studio 2013',
+ solution_version='13.00',
+ project_version='4.0',
+ flat_sln=True,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based,
+ default_toolset='v110'),
+ '2012': VisualStudioVersion('2012',
+ 'Visual Studio 2012',
+ solution_version='12.00',
+ project_version='4.0',
+ flat_sln=False,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based,
+ default_toolset='v110'),
+ '2012e': VisualStudioVersion('2012e',
+ 'Visual Studio 2012',
+ solution_version='12.00',
+ project_version='4.0',
+ flat_sln=True,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based,
+ default_toolset='v110'),
+ '2010': VisualStudioVersion('2010',
+ 'Visual Studio 2010',
+ solution_version='11.00',
+ project_version='4.0',
+ flat_sln=False,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based),
+ '2010e': VisualStudioVersion('2010e',
+ 'Visual Studio 2010',
+ solution_version='11.00',
+ project_version='4.0',
+ flat_sln=True,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based),
+ '2008': VisualStudioVersion('2008',
+ 'Visual Studio 2008',
+ solution_version='10.00',
+ project_version='9.00',
+ flat_sln=False,
+ uses_vcxproj=False,
+ path=path,
+ sdk_based=sdk_based),
+ '2008e': VisualStudioVersion('2008e',
+ 'Visual Studio 2008',
+ solution_version='10.00',
+ project_version='9.00',
+ flat_sln=True,
+ uses_vcxproj=False,
+ path=path,
+ sdk_based=sdk_based),
+ '2005': VisualStudioVersion('2005',
+ 'Visual Studio 2005',
+ solution_version='9.00',
+ project_version='8.00',
+ flat_sln=False,
+ uses_vcxproj=False,
+ path=path,
+ sdk_based=sdk_based),
+ '2005e': VisualStudioVersion('2005e',
+ 'Visual Studio 2005',
+ solution_version='9.00',
+ project_version='8.00',
+ flat_sln=True,
+ uses_vcxproj=False,
+ path=path,
+ sdk_based=sdk_based),
+ }
+ return versions[str(name)]
+
+
+def _ConvertToCygpath(path):
+ """Convert to cygwin path if we are using cygwin."""
+ if sys.platform == 'cygwin':
+ p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE)
+ path = p.communicate()[0].strip()
+ return path
+
+
+def _DetectVisualStudioVersions(versions_to_check, force_express):
+ """Collect the list of installed visual studio versions.
+
+ Returns:
+ A list of visual studio versions installed in descending order of
+ usage preference.
+ Base this on the registry and a quick check if devenv.exe exists.
+ Only versions 8-10 are considered.
+ Possibilities are:
+ 2005(e) - Visual Studio 2005 (8)
+ 2008(e) - Visual Studio 2008 (9)
+ 2010(e) - Visual Studio 2010 (10)
+ 2012(e) - Visual Studio 2012 (11)
+ 2013(e) - Visual Studio 2013 (11)
+ Where (e) is e for express editions of MSVS and blank otherwise.
+ """
+ version_to_year = {
+ '8.0': '2005',
+ '9.0': '2008',
+ '10.0': '2010',
+ '11.0': '2012',
+ '12.0': '2013',
+ }
+ versions = []
+ for version in versions_to_check:
+ # Old method of searching for which VS version is installed
+ # We don't use the 2010-encouraged-way because we also want to get the
+ # path to the binaries, which it doesn't offer.
+ keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
+ r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version,
+ r'HKLM\Software\Microsoft\VCExpress\%s' % version,
+ r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version]
+ for index in range(len(keys)):
+ path = _RegistryGetValue(keys[index], 'InstallDir')
+ if not path:
+ continue
+ path = _ConvertToCygpath(path)
+ # Check for full.
+ full_path = os.path.join(path, 'devenv.exe')
+ express_path = os.path.join(path, 'vcexpress.exe')
+ if not force_express and os.path.exists(full_path):
+ # Add this one.
+ versions.append(_CreateVersion(version_to_year[version],
+ os.path.join(path, '..', '..')))
+ # Check for express.
+ elif os.path.exists(express_path):
+ # Add this one.
+ versions.append(_CreateVersion(version_to_year[version] + 'e',
+ os.path.join(path, '..', '..')))
+
+ # The old method above does not work when only SDK is installed.
+ keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7',
+ r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7']
+ for index in range(len(keys)):
+ path = _RegistryGetValue(keys[index], version)
+ if not path:
+ continue
+ path = _ConvertToCygpath(path)
+ versions.append(_CreateVersion(version_to_year[version] + 'e',
+ os.path.join(path, '..'), sdk_based=True))
+
+ return versions
+
+
+def SelectVisualStudioVersion(version='auto'):
+ """Select which version of Visual Studio projects to generate.
+
+ Arguments:
+ version: Hook to allow caller to force a particular version (vs auto).
+ Returns:
+ An object representing a visual studio project format version.
+ """
+ # In auto mode, check environment variable for override.
+ if version == 'auto':
+ version = os.environ.get('GYP_MSVS_VERSION', 'auto')
+ version_map = {
+ 'auto': ('10.0', '9.0', '8.0', '11.0'),
+ '2005': ('8.0',),
+ '2005e': ('8.0',),
+ '2008': ('9.0',),
+ '2008e': ('9.0',),
+ '2010': ('10.0',),
+ '2010e': ('10.0',),
+ '2012': ('11.0',),
+ '2012e': ('11.0',),
+ '2013': ('12.0',),
+ '2013e': ('12.0',),
+ }
+ override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH')
+ if override_path:
+ msvs_version = os.environ.get('GYP_MSVS_VERSION')
+ if not msvs_version or 'e' not in msvs_version:
+ raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be '
+ 'set to an "e" version (e.g. 2010e)')
+ return _CreateVersion(msvs_version, override_path, sdk_based=True)
+ version = str(version)
+ versions = _DetectVisualStudioVersions(version_map[version], 'e' in version)
+ if not versions:
+ if version == 'auto':
+ # Default to 2005 if we couldn't find anything
+ return _CreateVersion('2005', None)
+ else:
+ return _CreateVersion(version, None)
+ return versions[0]
+
+def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out):
+ """It's not sufficient to have the absolute path to the compiler, linker,
+ etc. on Windows, as those tools rely on .dlls being in the PATH. We also
+ need to support both x86 and x64 compilers within the same build (to support
+ msvs_target_platform hackery). Different architectures require a different
+ compiler binary, and different supporting environment variables (INCLUDE,
+ LIB, LIBPATH). So, we extract the environment here, wrap all invocations
+ of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which
+ sets up the environment, and then we do not prefix the compiler with
+ an absolute path, instead preferring something like "cl.exe" in the rule
+ which will then run whichever the environment setup has put in the path.
+ When the following procedure to generate environment files does not
+ meet your requirement (e.g. for custom toolchains), you can pass
+ "-G ninja_use_custom_environment_files" to the gyp to suppress file
+ generation and use custom environment files prepared by yourself."""
+ archs = ('x86', 'x64')
+ if generator_flags.get('ninja_use_custom_environment_files', 0):
+ cl_paths = {}
+ for arch in archs:
+ cl_paths[arch] = 'cl.exe'
+ return cl_paths
+ vs = GetVSVersion(generator_flags)
+ cl_paths = {}
+ for arch in archs:
+ # Extract environment variables for subprocesses.
+ args = vs.SetupScript(arch)
+ args.extend(('&&', 'set'))
+ popen = subprocess.Popen(
+ args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ variables, _ = popen.communicate()
+ env = _ExtractImportantEnvironment(variables)
+ env_block = _FormatAsEnvironmentBlock(env)
+ f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb')
+ f.write(env_block)
+ f.close()
+
+ # Find cl.exe location for this architecture.
+ args = vs.SetupScript(arch)
+ args.extend(('&&',
+ 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i'))
+ popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE)
+ output, _ = popen.communicate()
+ cl_paths[arch] = _ExtractCLPath(output)
+ return cl_paths
+
+def OpenOutput(path, mode='w'):
+ """Open |path| for writing, creating directories if necessary."""
+ try:
+ os.makedirs(os.path.dirname(path))
+ except OSError:
+ pass
+ return open(path, mode)
+
+vs_version = None
+def GetVSVersion(generator_flags):
+ global vs_version
+ if not vs_version:
+ vs_version = SelectVisualStudioVersion(
+ generator_flags.get('msvs_version', 'auto'))
+ return vs_version
+
+def _ExtractImportantEnvironment(output_of_set):
+ """Extracts environment variables required for the toolchain to run from
+ a textual dump output by the cmd.exe 'set' command."""
+ envvars_to_save = (
+ 'goma_.*', # TODO(scottmg): This is ugly, but needed for goma.
+ 'include',
+ 'lib',
+ 'libpath',
+ 'path',
+ 'pathext',
+ 'systemroot',
+ 'temp',
+ 'tmp',
+ )
+ env = {}
+ for line in output_of_set.splitlines():
+ for envvar in envvars_to_save:
+ if re.match(envvar + '=', line.lower()):
+ var, setting = line.split('=', 1)
+ if envvar == 'path':
+ # Our own rules (for running gyp-win-tool) and other actions in
+ # Chromium rely on python being in the path. Add the path to this
+ # python here so that if it's not in the path when ninja is run
+ # later, python will still be found.
+ setting = os.path.dirname(sys.executable) + os.pathsep + setting
+ env[var.upper()] = setting
+ break
+ for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
+ if required not in env:
+ raise Exception('Environment variable "%s" '
+ 'required to be set to valid path' % required)
+ return env
+
+def _FormatAsEnvironmentBlock(envvar_dict):
+ """Format as an 'environment block' directly suitable for CreateProcess.
+ Briefly this is a list of key=value\0, terminated by an additional \0. See
+ CreateProcess documentation for more details."""
+ block = ''
+ nul = '\0'
+ for key, value in envvar_dict.iteritems():
+ block += key + '=' + value + nul
+ block += nul
+ return block
+
+
+def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags):
+ """It's not sufficient to have the absolute path to the compiler, linker,
+ etc. on Windows, as those tools rely on .dlls being in the PATH. We also
+ need to support both x86 and x64 compilers within the same build (to support
+ msvs_target_platform hackery). Different architectures require a different
+ compiler binary, and different supporting environment variables (INCLUDE,
+ LIB, LIBPATH). So, we extract the environment here, wrap all invocations
+ of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which
+ sets up the environment, and then we do not prefix the compiler with
+ an absolute path, instead preferring something like "cl.exe" in the rule
+ which will then run whichever the environment setup has put in the path.
+ When the following procedure to generate environment files does not
+ meet your requirement (e.g. for custom toolchains), you can pass
+ "-G ninja_use_custom_environment_files" to the gyp to suppress file
+ generation and use custom environment files prepared by yourself."""
+ archs = ('x86', 'x64')
+ if generator_flags.get('ninja_use_custom_environment_files', 0):
+ cl_paths = {}
+ for arch in archs:
+ cl_paths[arch] = 'cl.exe'
+ return cl_paths
+ vs = GetVSVersion(generator_flags)
+ cl_paths = {}
+ for arch in archs:
+ # Extract environment variables for subprocesses.
+ args = vs.SetupScript(arch)
+ args.extend(('&&', 'set'))
+ popen = subprocess.Popen(
+ args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ variables, _ = popen.communicate()
+ env = _ExtractImportantEnvironment(variables)
+ env_block = _FormatAsEnvironmentBlock(env)
+ f = OpenOutput(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb')
+ f.write(env_block)
+ f.close()
+
+ # Find cl.exe location for this architecture.
+ args = vs.SetupScript(arch)
+ args.extend(('&&',
+ 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i'))
+ popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE)
+ output, _ = popen.communicate()
+ cl_paths[arch] = _ExtractCLPath(output)
+ return cl_paths
+
+def _ExtractCLPath(output_of_where):
+ """Gets the path to cl.exe based on the output of calling the environment
+ setup batch file, followed by the equivalent of `where`."""
+ # Take the first line, as that's the first found in the PATH.
+ for line in output_of_where.strip().splitlines():
+ if line.startswith('LOC:'):
+ return line[len('LOC:'):].strip()
+
+#print SelectVisualStudioVersion().DefaultToolset()
+#GenerateEnvironmentFiles("D:\\src\\src1\\src\\out\\gn\\eraseme", {})
+#print '"', GetVSVersion({}).Path(), '"'
+print '"', GetVSVersion({}).sdk_based, '"'
+
+#-------------------------------------------------------------------------------
+
+version_info = {
+ '2010': {
+ 'includes': [
+ 'VC\\atlmfc\\include',
+ ],
+ },
+}
diff --git a/chromium/tools/gn/secondary/ipc/BUILD.gn b/chromium/tools/gn/secondary/ipc/BUILD.gn
new file mode 100644
index 00000000000..f85208886fd
--- /dev/null
+++ b/chromium/tools/gn/secondary/ipc/BUILD.gn
@@ -0,0 +1,168 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+component("ipc") {
+ sources = [
+ "file_descriptor_set_posix.cc",
+ "file_descriptor_set_posix.h",
+ "ipc_channel.cc",
+ "ipc_channel.h",
+ "ipc_channel_factory.cc",
+ "ipc_channel_factory.h",
+ "ipc_channel_handle.h",
+ "ipc_channel_nacl.cc",
+ "ipc_channel_nacl.h",
+ "ipc_channel_posix.cc",
+ "ipc_channel_posix.h",
+ "ipc_channel_proxy.cc",
+ "ipc_channel_proxy.h",
+ "ipc_channel_reader.cc",
+ "ipc_channel_reader.h",
+ "ipc_channel_win.cc",
+ "ipc_channel_win.h",
+ "ipc_descriptors.h",
+ "ipc_export.h",
+ "ipc_forwarding_message_filter.cc",
+ "ipc_forwarding_message_filter.h",
+ "ipc_listener.h",
+ "ipc_logging.cc",
+ "ipc_logging.h",
+ "ipc_message.cc",
+ "ipc_message.h",
+ "ipc_message_macros.h",
+ "ipc_message_start.h",
+ "ipc_message_utils.cc",
+ "ipc_message_utils.h",
+ "ipc_param_traits.h",
+ "ipc_platform_file.cc",
+ "ipc_platform_file.h",
+ "ipc_sender.h",
+ "ipc_switches.cc",
+ "ipc_switches.h",
+ "ipc_sync_channel.cc",
+ "ipc_sync_channel.h",
+ "ipc_sync_message.cc",
+ "ipc_sync_message.h",
+ "ipc_sync_message_filter.cc",
+ "ipc_sync_message_filter.h",
+ "param_traits_log_macros.h",
+ "param_traits_macros.h",
+ "param_traits_read_macros.h",
+ "param_traits_write_macros.h",
+ "struct_constructor_macros.h",
+ "struct_destructor_macros.h",
+ "unix_domain_socket_util.cc",
+ "unix_domain_socket_util.h",
+ ]
+
+ #if (!is_untrusted_nacl) {
+ sources -= [
+ "ipc_channel_nacl.cc",
+ "ipc_channel_nacl.h",
+ ]
+
+ if (is_win || is_ios) {
+ sources -= [
+ "ipc_channel_factory.cc",
+ "unix_domain_socket_util.cc",
+ ]
+ }
+
+ defines = [ "IPC_IMPLEMENTATION" ]
+
+ deps = [
+ "//base",
+ # TODO(viettrungluu): Needed for base/lazy_instance.h, which is suspect.
+ "//base/third_party/dynamic_annotations",
+ ]
+}
+
+test("ipc_tests") {
+ sources = [
+ "file_descriptor_set_posix_unittest.cc",
+ "ipc_channel_posix_unittest.cc",
+ "ipc_channel_unittest.cc",
+ "ipc_fuzzing_tests.cc",
+ "ipc_message_unittest.cc",
+ "ipc_message_utils_unittest.cc",
+ "ipc_send_fds_test.cc",
+ "ipc_sync_channel_unittest.cc",
+ "ipc_sync_message_unittest.cc",
+ "ipc_sync_message_unittest.h",
+ "ipc_test_base.cc",
+ "ipc_test_base.h",
+ "sync_socket_unittest.cc",
+ "unix_domain_socket_util_unittest.cc",
+ ]
+
+ #if (toolkit_uses_gtk) {
+ # deps += "/build/linux/system:gtk"
+ #}
+ if (is_win || is_ios) {
+ sources -= "unix_domain_socket_util_unittest.cc"
+ }
+ #if (is_android && gtest_target_type == "shared_library") {
+ # deps += "/testing/android/native_test.gyp:native_testNative_code"
+ #}
+ #if (is_posix && !is_mac && !is_android) {
+ # if (linux_use_tcmalloc) {
+ # deps += "/base/allocator"
+ # }
+ #}
+
+ deps = [
+ ":ipc",
+ ":test_support_ipc",
+ "//base",
+ "//base:base_i18n",
+ "//base:run_all_unittests",
+ "//base:test_support_base",
+ "//testing:gtest",
+ ]
+}
+
+test("ipc_perftests") {
+ sources = [
+ "ipc_perftests.cc",
+ "ipc_test_base.cc",
+ "ipc_test_base.h",
+ ]
+
+ #if (toolkit_uses_gtk) {
+ # deps += "/build/linux/system:gtk"
+ #}
+ #if (is_android && gtest_target_type == "shared_library") {
+ # deps += "/testing/android/native_test.gyp:native_testNative_code"
+ #}
+ #if (is_posix && !is_mac && !is_android) {
+ # if (linux_use_tcmalloc) {
+ # deps += "/base/allocator"
+ # }
+ #}
+
+ deps = [
+ ":ipc",
+ ":test_support_ipc",
+ "//base",
+ "//base:base_i18n",
+ "//base:test_support_base",
+ "//base:test_support_perf",
+ "//testing:gtest",
+ ]
+}
+
+static_library("test_support_ipc") {
+ sources = [
+ "ipc_multiprocess_test.cc",
+ "ipc_multiprocess_test.h",
+ "ipc_test_sink.cc",
+ "ipc_test_sink.h",
+ ]
+ deps = [
+ ":ipc",
+ "//base",
+ "//testing:gtest",
+ ]
+}
+
diff --git a/chromium/tools/gn/secondary/testing/BUILD.gn b/chromium/tools/gn/secondary/testing/BUILD.gn
new file mode 100644
index 00000000000..4e854b64e73
--- /dev/null
+++ b/chromium/tools/gn/secondary/testing/BUILD.gn
@@ -0,0 +1,44 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("gtest") {
+ sources = [
+ "gtest/include/gtest/gtest-death-test.h",
+ "gtest/include/gtest/gtest-message.h",
+ "gtest/include/gtest/gtest-param-test.h",
+ "gtest/include/gtest/gtest-printers.h",
+ "gtest/include/gtest/gtest-spi.h",
+ "gtest/include/gtest/gtest-test-part.h",
+ "gtest/include/gtest/gtest-typed-test.h",
+ "gtest/include/gtest/gtest.h",
+ "gtest/include/gtest/gtest_pred_impl.h",
+ "gtest/include/gtest/internal/gtest-death-test-internal.h",
+ "gtest/include/gtest/internal/gtest-filepath.h",
+ "gtest/include/gtest/internal/gtest-internal.h",
+ "gtest/include/gtest/internal/gtest-linked_ptr.h",
+ "gtest/include/gtest/internal/gtest-param-util-generated.h",
+ "gtest/include/gtest/internal/gtest-param-util.h",
+ "gtest/include/gtest/internal/gtest-port.h",
+ "gtest/include/gtest/internal/gtest-string.h",
+ "gtest/include/gtest/internal/gtest-tuple.h",
+ "gtest/include/gtest/internal/gtest-type-util.h",
+ #"gtest/src/gtest-all.cc", # Not needed by our build.
+ "gtest/src/gtest-death-test.cc",
+ "gtest/src/gtest-filepath.cc",
+ "gtest/src/gtest-internal-inl.h",
+ "gtest/src/gtest-port.cc",
+ "gtest/src/gtest-printers.cc",
+ "gtest/src/gtest-test-part.cc",
+ "gtest/src/gtest-typed-test.cc",
+ "gtest/src/gtest.cc",
+ "multiprocess_func_list.cc",
+ "multiprocess_func_list.h",
+ "platform_test.h",
+ ]
+
+}
+
+static_library("gmock") {
+
+}
diff --git a/chromium/tools/gn/secondary/third_party/icu/BUILD.gn b/chromium/tools/gn/secondary/third_party/icu/BUILD.gn
new file mode 100644
index 00000000000..3fa919ee590
--- /dev/null
+++ b/chromium/tools/gn/secondary/third_party/icu/BUILD.gn
@@ -0,0 +1,5 @@
+
+component("icui18n") {
+}
+component("icuuc") {
+}
diff --git a/chromium/tools/gn/secondary/third_party/libevent/BUILD.gn b/chromium/tools/gn/secondary/third_party/libevent/BUILD.gn
new file mode 100644
index 00000000000..afbd67de9f3
--- /dev/null
+++ b/chromium/tools/gn/secondary/third_party/libevent/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("libevent") {
+ sources = [
+ "buffer.c",
+ "epoll.c",
+ "epoll_sub.c",
+ "evbuffer.c",
+ "evdns.c",
+ "event.c",
+ "event_tagging.c",
+ "evrpc.c",
+ "evutil.c",
+ "http.c",
+ "kqueue.c",
+ "log.c",
+ "poll.c",
+ "select.c",
+ "signal.c",
+ "strlcpy.c",
+ ]
+
+ defines = [ "HAVE_CONFIG_H" ]
+
+ if (is_linux) {
+ ldflags = [ "-lrt" ]
+ } else {
+ sources -= [ "epoll.c", "epoll_sub.c" ]
+ }
+
+ if (is_mac) {
+ includes = [ "mac" ]
+ } else if (is_linux) {
+ includes = [ "linux" ]
+ sources -= [ "kqueue.c" ]
+ }
+
+ configs -= "//build/config/compiler:chromium_code"
+ configs += "//build/config/compiler:no_chromium_code"
+}
diff --git a/chromium/tools/gn/secondary/third_party/mach_override/BUILD.gn b/chromium/tools/gn/secondary/third_party/mach_override/BUILD.gn
new file mode 100644
index 00000000000..13317b1749b
--- /dev/null
+++ b/chromium/tools/gn/secondary/third_party/mach_override/BUILD.gn
@@ -0,0 +1,10 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("mach_override") {
+ sources = [
+ "mach_override.c",
+ "mach_override.h",
+ ]
+}
diff --git a/chromium/tools/gn/secondary/third_party/modp_b64/BUILD.gn b/chromium/tools/gn/secondary/third_party/modp_b64/BUILD.gn
new file mode 100644
index 00000000000..539abe1580a
--- /dev/null
+++ b/chromium/tools/gn/secondary/third_party/modp_b64/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+static_library("modp_b64") {
+ sources = [
+ "modp_b64.cc",
+ "modp_b64.h",
+ "modp_b64_data.h",
+ ]
+}
diff --git a/chromium/tools/gn/settings.cc b/chromium/tools/gn/settings.cc
new file mode 100644
index 00000000000..63b8afb88af
--- /dev/null
+++ b/chromium/tools/gn/settings.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/settings.h"
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "tools/gn/filesystem_utils.h"
+
+Settings::Settings(const BuildSettings* build_settings,
+ const Toolchain* toolchain,
+ const std::string& output_subdir_name)
+ : build_settings_(build_settings),
+ toolchain_(toolchain),
+ import_manager_(),
+ base_config_(this),
+ greedy_target_generation_(false) {
+ DCHECK(output_subdir_name.find('/') == std::string::npos);
+ if (output_subdir_name.empty()) {
+ toolchain_output_dir_ = build_settings->build_dir();
+ } else {
+ // We guarantee this ends in a slash.
+ toolchain_output_subdir_.value().append(output_subdir_name);
+ toolchain_output_subdir_.value().push_back('/');
+
+ toolchain_output_dir_ = SourceDir(build_settings->build_dir().value() +
+ toolchain_output_subdir_.value());
+ }
+ // The output dir will be null in some tests and when invoked to parsed
+ // one-off data without doing generation.
+ if (!toolchain_output_dir_.is_null())
+ toolchain_gen_dir_ = SourceDir(toolchain_output_dir_.value() + "gen/");
+
+
+#if defined(OS_WIN)
+ target_os_ = WIN;
+#elif defined(OS_MACOSX)
+ target_os_ = MAC;
+#elif defined(OS_LINUX)
+ target_os_ = LINUX;
+#else
+ #error implement me
+#endif
+}
+
+Settings::~Settings() {
+}
+
+
diff --git a/chromium/tools/gn/settings.h b/chromium/tools/gn/settings.h
new file mode 100644
index 00000000000..1305c5805c2
--- /dev/null
+++ b/chromium/tools/gn/settings.h
@@ -0,0 +1,121 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SETTINGS_H_
+#define TOOLS_GN_SETTINGS_H_
+
+#include "base/files/file_path.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/import_manager.h"
+#include "tools/gn/output_file.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/source_dir.h"
+#include "tools/gn/toolchain.h"
+
+// Holds the settings for one toolchain invocation. There will be one
+// Settings object for each toolchain type, each referring to the same
+// BuildSettings object for shared stuff.
+//
+// The Settings object is const once it is constructed, which allows us to
+// use it from multiple threads during target generation without locking (which
+// is important, because it gets used a lot).
+//
+// The Toolchain object holds the set of stuff that is set by the toolchain
+// declaration, which obviously needs to be set later when we actually parse
+// the file with the toolchain declaration in it.
+class Settings {
+ public:
+ enum TargetOS {
+ UNKNOWN,
+ LINUX,
+ MAC,
+ WIN
+ };
+
+ // Constructs a toolchain settings. The output_subdir_name is the name we
+ // should use for the subdirectory in the build output directory for this
+ // toolchain's outputs. It should have no slashes in it. The default
+ // toolchain should use an empty string.
+ Settings(const BuildSettings* build_settings,
+ const Toolchain* toolchain,
+ const std::string& output_subdir_name);
+ ~Settings();
+
+ const BuildSettings* build_settings() const { return build_settings_; }
+
+ // Danger: this must only be used for getting the toolchain label until the
+ // toolchain has been resolved. Otherwise, it will be modified on an
+ // arbitrary thread when the toolchain invocation is found. Generally, you
+ // will only read this from the target generation where we know everything
+ // has been resolved and won't change.
+ const Toolchain* toolchain() const { return toolchain_; }
+
+ bool IsMac() const { return target_os_ == MAC; }
+ bool IsLinux() const { return target_os_ == LINUX; }
+ bool IsWin() const { return target_os_ == WIN; }
+
+ TargetOS target_os() const { return target_os_; }
+ void set_target_os(TargetOS t) { target_os_ = t; }
+
+ const OutputFile& toolchain_output_subdir() const {
+ return toolchain_output_subdir_;
+ }
+ const SourceDir& toolchain_output_dir() const {
+ return toolchain_output_dir_;
+ }
+
+ // Directory for generated files.
+ const SourceDir& toolchain_gen_dir() const {
+ return toolchain_gen_dir_;
+ }
+
+ // The import manager caches the result of executing imported files in the
+ // context of a given settings object.
+ //
+ // See the ItemTree getter in GlobalSettings for why this doesn't return a
+ // const pointer.
+ ImportManager& import_manager() const { return import_manager_; }
+
+ const Scope* base_config() const { return &base_config_; }
+ Scope* base_config() { return &base_config_; }
+
+ // Set to true when every target we encounter should be generated. False
+ // means that only targets that have a dependency from (directly or
+ // indirectly) some magic root node are actually generated. See the comments
+ // on ItemTree for more.
+ bool greedy_target_generation() const {
+ return greedy_target_generation_;
+ }
+ void set_greedy_target_generation(bool gtg) {
+ greedy_target_generation_ = gtg;
+ }
+
+ private:
+ const BuildSettings* build_settings_;
+
+ const Toolchain* toolchain_;
+
+ TargetOS target_os_;
+
+ mutable ImportManager import_manager_;
+
+ // The subdirectory inside the build output for this toolchain. For the
+ // default toolchain, this will be empty (since the deafult toolchain's
+ // output directory is the same as the build directory). When nonempty, this
+ // is guaranteed to end in a slash.
+ OutputFile toolchain_output_subdir_;
+
+ // Full source file path to the toolchain output directory.
+ SourceDir toolchain_output_dir_;
+
+ SourceDir toolchain_gen_dir_;
+
+ Scope base_config_;
+
+ bool greedy_target_generation_;
+
+ DISALLOW_COPY_AND_ASSIGN(Settings);
+};
+
+#endif // TOOLS_GN_SETTINGS_H_
diff --git a/chromium/tools/gn/setup.cc b/chromium/tools/gn/setup.cc
new file mode 100644
index 00000000000..72eb8e94d6b
--- /dev/null
+++ b/chromium/tools/gn/setup.cc
@@ -0,0 +1,232 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/setup.h"
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/parser.h"
+#include "tools/gn/source_dir.h"
+#include "tools/gn/source_file.h"
+#include "tools/gn/tokenizer.h"
+#include "tools/gn/value.h"
+
+extern const char kDotfile_Help[] =
+ ".gn file\n"
+ "\n"
+ " When gn starts, it will search the current directory and parent\n"
+ " directories for a file called \".gn\". This indicates the source root.\n"
+ " You can override this detection by using the --root command-line\n"
+ " argument\n"
+ "\n"
+ " The .gn file in the source root will be executed. The syntax is the\n"
+ " same as a buildfile, but with very limited build setup-specific\n"
+ " meaning.\n"
+ "\n"
+ "Variables:\n"
+ " buildconfig [required]\n"
+ " Label of the build config file. This file will be used to setup\n"
+ " the build file execution environment for each toolchain.\n"
+ "\n"
+ " secondary_source [optional]\n"
+ " Label of an alternate directory tree to find input files. When\n"
+ " searching for a BUILD.gn file (or the build config file discussed\n"
+ " above), the file fill first be looked for in the source root.\n"
+ " If it's not found, the secondary source root will be checked\n"
+ " (which would contain a parallel directory hierarchy).\n"
+ "\n"
+ " This behavior is intended to be used when BUILD.gn files can't be\n"
+ " checked in to certain source directories for whaever reason.\n"
+ "\n"
+ " The secondary source root must be inside the main source tree.\n"
+ "\n"
+ "Example .gn file contents:\n"
+ "\n"
+ " buildconfig = \"//build/config/BUILDCONFIG.gn\"\n"
+ "\n"
+ " secondary_source = \"//build/config/temporary_buildfiles/\"\n";
+
+namespace {
+
+// More logging.
+const char kSwitchVerbose[] = "v";
+
+const char kSwitchRoot[] = "root";
+const char kSecondarySource[] = "secondary";
+
+const base::FilePath::CharType kGnFile[] = FILE_PATH_LITERAL(".gn");
+
+base::FilePath FindDotFile(const base::FilePath& current_dir) {
+ base::FilePath try_this_file = current_dir.Append(kGnFile);
+ if (base::PathExists(try_this_file))
+ return try_this_file;
+
+ base::FilePath with_no_slash = current_dir.StripTrailingSeparators();
+ base::FilePath up_one_dir = with_no_slash.DirName();
+ if (up_one_dir == current_dir)
+ return base::FilePath(); // Got to the top.
+
+ return FindDotFile(up_one_dir);
+}
+
+} // namespace
+
+Setup::Setup()
+ : dotfile_toolchain_(Label()),
+ dotfile_settings_(&dotfile_build_settings_, &dotfile_toolchain_,
+ std::string()),
+ dotfile_scope_(&dotfile_settings_) {
+}
+
+Setup::~Setup() {
+}
+
+bool Setup::DoSetup() {
+ CommandLine* cmdline = CommandLine::ForCurrentProcess();
+
+ scheduler_.set_verbose_logging(cmdline->HasSwitch(kSwitchVerbose));
+
+ if (!FillSourceDir(*cmdline))
+ return false;
+ if (!RunConfigFile())
+ return false;
+ if (!FillOtherConfig(*cmdline))
+ return false;
+
+ // FIXME(brettw) get python path!
+#if defined(OS_WIN)
+ build_settings_.set_python_path(
+ base::FilePath(FILE_PATH_LITERAL("cmd.exe /c python")));
+#else
+ build_settings_.set_python_path(base::FilePath(FILE_PATH_LITERAL("python")));
+#endif
+
+ build_settings_.SetBuildDir(SourceDir("//out/gn/"));
+
+ return true;
+}
+
+bool Setup::Run() {
+ // Load the root build file and start runnung.
+ build_settings_.toolchain_manager().StartLoadingUnlocked(
+ SourceFile("//BUILD.gn"));
+ if (!scheduler_.Run())
+ return false;
+
+ Err err = build_settings_.item_tree().CheckForBadItems();
+ if (err.has_error()) {
+ err.PrintToStdout();
+ return false;
+ }
+ return true;
+}
+
+bool Setup::FillSourceDir(const CommandLine& cmdline) {
+ // Find the .gn file.
+ base::FilePath root_path;
+
+ // Prefer the command line args to the config file.
+ base::FilePath relative_root_path = cmdline.GetSwitchValuePath(kSwitchRoot);
+ if (!relative_root_path.empty()) {
+ root_path = base::MakeAbsoluteFilePath(relative_root_path);
+ dotfile_name_ = root_path.Append(kGnFile);
+ } else {
+ base::FilePath cur_dir;
+ file_util::GetCurrentDirectory(&cur_dir);
+ dotfile_name_ = FindDotFile(cur_dir);
+ if (dotfile_name_.empty()) {
+ Err(Location(), "Can't find source root.",
+ "I could not find a \".gn\" file in the current directory or any "
+ "parent,\nand the --root command-line argument was not specified.")
+ .PrintToStdout();
+ return false;
+ }
+ root_path = dotfile_name_.DirName();
+ }
+
+ if (scheduler_.verbose_logging())
+ scheduler_.Log("Using source root", FilePathToUTF8(root_path));
+ build_settings_.set_root_path(root_path);
+
+ return true;
+}
+
+bool Setup::RunConfigFile() {
+ if (scheduler_.verbose_logging())
+ scheduler_.Log("Got dotfile", FilePathToUTF8(dotfile_name_));
+
+ dotfile_input_file_.reset(new InputFile(SourceFile("//.gn")));
+ if (!dotfile_input_file_->Load(dotfile_name_)) {
+ Err(Location(), "Could not load dotfile.",
+ "The file \"" + FilePathToUTF8(dotfile_name_) + "\" cound't be loaded")
+ .PrintToStdout();
+ return false;
+ }
+
+ Err err;
+ dotfile_tokens_ = Tokenizer::Tokenize(dotfile_input_file_.get(), &err);
+ if (err.has_error()) {
+ err.PrintToStdout();
+ return false;
+ }
+
+ dotfile_root_ = Parser::Parse(dotfile_tokens_, &err);
+ if (err.has_error()) {
+ err.PrintToStdout();
+ return false;
+ }
+
+ dotfile_root_->AsBlock()->ExecuteBlockInScope(&dotfile_scope_, &err);
+ if (err.has_error()) {
+ err.PrintToStdout();
+ return false;
+ }
+
+ return true;
+}
+
+bool Setup::FillOtherConfig(const CommandLine& cmdline) {
+ Err err;
+
+ // Secondary source path.
+ SourceDir secondary_source;
+ if (cmdline.HasSwitch(kSecondarySource)) {
+ // Prefer the command line over the config file.
+ secondary_source =
+ SourceDir(cmdline.GetSwitchValueASCII(kSecondarySource));
+ } else {
+ // Read from the config file if present.
+ const Value* secondary_value =
+ dotfile_scope_.GetValue("secondary_source", true);
+ if (secondary_value) {
+ if (!secondary_value->VerifyTypeIs(Value::STRING, &err)) {
+ err.PrintToStdout();
+ return false;
+ }
+ build_settings_.SetSecondarySourcePath(
+ SourceDir(secondary_value->string_value()));
+ }
+ }
+
+ // Build config file.
+ const Value* build_config_value =
+ dotfile_scope_.GetValue("buildconfig", true);
+ if (!build_config_value) {
+ Err(Location(), "No build config file.",
+ "Your .gn file (\"" + FilePathToUTF8(dotfile_name_) + "\")\n"
+ "didn't specify a \"buildconfig\" value.").PrintToStdout();
+ return false;
+ } else if (!build_config_value->VerifyTypeIs(Value::STRING, &err)) {
+ err.PrintToStdout();
+ return false;
+ }
+ build_settings_.set_build_config_file(
+ SourceFile(build_config_value->string_value()));
+
+ return true;
+}
diff --git a/chromium/tools/gn/setup.h b/chromium/tools/gn/setup.h
new file mode 100644
index 00000000000..4070a0fe529
--- /dev/null
+++ b/chromium/tools/gn/setup.h
@@ -0,0 +1,71 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SETUP_H_
+#define TOOLS_GN_SETUP_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/token.h"
+#include "tools/gn/toolchain.h"
+
+class CommandLine;
+class InputFile;
+class ParseNode;
+
+extern const char kDotfile_Help[];
+
+// Helper class to setup the build settings and environment for the various
+// commands to run.
+class Setup {
+ public:
+ Setup();
+ ~Setup();
+
+ // Configures the build for the current command line. On success returns
+ // true. On failure, prints the error and returns false.
+ bool DoSetup();
+
+ // Runs the load, returning true on success. On failure, prints the error
+ // and returns false.
+ bool Run();
+
+ BuildSettings& build_settings() { return build_settings_; }
+ Scheduler& scheduler() { return scheduler_; }
+
+ private:
+ // Fills the root directory into the settings. Returns true on success.
+ bool FillSourceDir(const CommandLine& cmdline);
+
+ // Run config file.
+ bool RunConfigFile();
+
+ bool FillOtherConfig(const CommandLine& cmdline);
+
+ BuildSettings build_settings_;
+ Scheduler scheduler_;
+
+ // State for invoking the dotfile.
+ // TODO(brettw) this seems a bit excessive, maybe we can get this down
+ // somehow?
+ base::FilePath dotfile_name_;
+ scoped_ptr<InputFile> dotfile_input_file_;
+ std::vector<Token> dotfile_tokens_;
+ scoped_ptr<ParseNode> dotfile_root_;
+ BuildSettings dotfile_build_settings_;
+ Toolchain dotfile_toolchain_;
+ Settings dotfile_settings_;
+ Scope dotfile_scope_;
+
+ DISALLOW_COPY_AND_ASSIGN(Setup);
+};
+
+#endif // TOOLS_GN_SETUP_H_
diff --git a/chromium/tools/gn/source_dir.cc b/chromium/tools/gn/source_dir.cc
new file mode 100644
index 00000000000..5739b527f56
--- /dev/null
+++ b/chromium/tools/gn/source_dir.cc
@@ -0,0 +1,98 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/source_dir.h"
+
+#include "base/logging.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/source_file.h"
+
+namespace {
+
+void AssertValueSourceDirString(const std::string& s) {
+ DCHECK(!s.empty());
+ DCHECK(s[0] == '/');
+ DCHECK(EndsWithSlash(s));
+}
+
+} // namespace
+
+SourceDir::SourceDir() {
+}
+
+SourceDir::SourceDir(const base::StringPiece& p)
+ : value_(p.data(), p.size()) {
+ if (!EndsWithSlash(value_))
+ value_.push_back('/');
+ AssertValueSourceDirString(value_);
+}
+
+SourceDir::~SourceDir() {
+}
+
+SourceFile SourceDir::ResolveRelativeFile(const base::StringPiece& p) const {
+ SourceFile ret;
+
+ // It's an error to resolve an empty string or one that is a directory
+ // (indicated by a trailing slash) because this is the function that expects
+ // to return a file.
+ if (p.empty() || (p.size() > 0 && p[p.size() - 1] == '/'))
+ return SourceFile();
+ if (p[0] == '/') {
+ // Absolute path.
+ ret.value_.assign(p.data(), p.size());
+ return ret;
+ }
+
+ ret.value_.reserve(value_.size() + p.size());
+ ret.value_.assign(value_);
+ ret.value_.append(p.data(), p.size());
+
+ NormalizePath(&ret.value_);
+ return ret;
+}
+
+SourceDir SourceDir::ResolveRelativeDir(const base::StringPiece& p) const {
+ SourceDir ret;
+
+ if (p.empty())
+ return ret;
+ if (p[0] == '/') {
+ // Absolute path.
+ return SourceDir(p);
+ }
+
+ ret.value_.reserve(value_.size() + p.size());
+ ret.value_.assign(value_);
+ ret.value_.append(p.data(), p.size());
+
+ NormalizePath(&ret.value_);
+ if (!EndsWithSlash(ret.value_))
+ ret.value_.push_back('/');
+ AssertValueSourceDirString(ret.value_);
+
+ return ret;
+}
+
+base::FilePath SourceDir::Resolve(const base::FilePath& source_root) const {
+ if (is_null())
+ return base::FilePath();
+
+ std::string converted;
+ if (is_system_absolute()) {
+ converted = value_;
+ ConvertPathToSystem(&converted);
+ return base::FilePath(UTF8ToFilePath(converted));
+ }
+
+ // String the double-leading slash for source-relative paths.
+ converted.assign(&value_[2], value_.size() - 2);
+ ConvertPathToSystem(&converted);
+ return source_root.Append(UTF8ToFilePath(converted));
+}
+
+void SourceDir::SwapInValue(std::string* v) {
+ value_.swap(*v);
+ AssertValueSourceDirString(value_);
+}
diff --git a/chromium/tools/gn/source_dir.h b/chromium/tools/gn/source_dir.h
new file mode 100644
index 00000000000..3b6caee6bcd
--- /dev/null
+++ b/chromium/tools/gn/source_dir.h
@@ -0,0 +1,104 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SOURCE_DIR_H_
+#define TOOLS_GN_SOURCE_DIR_H_
+
+#include <string>
+
+#include "base/containers/hash_tables.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+
+class SourceFile;
+
+// Represents a directory within the source tree. Source dirs begin and end in
+// slashes.
+//
+// If there is one slash at the beginning, it will mean a system-absolute file
+// path. On Windows, absolute system paths will be of the form "/C:/foo/bar".
+//
+// Two slashes at the beginning indicate a path relative to the source root.
+class SourceDir {
+ public:
+ SourceDir();
+ explicit SourceDir(const base::StringPiece& p);
+ ~SourceDir();
+
+ // Resolves a file or dir name relative to this source directory. Will return
+ // an empty SourceDir/File on error. Empty input is always an error (it's
+ // possible we should say ResolveRelativeDir vs. an empty string should be
+ // the source dir, but we require "." instead).
+ SourceFile ResolveRelativeFile(const base::StringPiece& p) const;
+ SourceDir ResolveRelativeDir(const base::StringPiece& p) const;
+
+ // Resolves this source file relative to some given source root. Returns
+ // an empty file path on error.
+ base::FilePath Resolve(const base::FilePath& source_root) const;
+
+ bool is_null() const { return value_.empty(); }
+ const std::string& value() const { return value_; }
+
+ // Returns true if this path starts with a "//" which indicates a path
+ // from the source root.
+ bool is_source_absolute() const {
+ return value_.size() >= 2 && value_[0] == '/' && value_[1] == '/';
+ }
+
+ // Returns true if this path starts with a single slash which indicates a
+ // system-absolute path.
+ bool is_system_absolute() const {
+ return !is_source_absolute();
+ }
+
+ // Returns a source-absolute path starting with only one slash at the
+ // beginning (normally source-absolute paths start with two slashes to mark
+ // them as such). This is normally used when concatenating directories
+ // together.
+ //
+ // This function asserts that the directory is actually source-absolute. The
+ // return value points into our buffer.
+ base::StringPiece SourceAbsoluteWithOneSlash() const {
+ CHECK(is_source_absolute());
+ return base::StringPiece(&value_[1], value_.size() - 1);
+ }
+
+ void SwapInValue(std::string* v);
+
+ bool operator==(const SourceDir& other) const {
+ return value_ == other.value_;
+ }
+ bool operator!=(const SourceDir& other) const {
+ return !operator==(other);
+ }
+ bool operator<(const SourceDir& other) const {
+ return value_ < other.value_;
+ }
+
+ private:
+ friend class SourceFile;
+ std::string value_;
+
+ // Copy & assign supported.
+};
+
+namespace BASE_HASH_NAMESPACE {
+
+#if defined(COMPILER_GCC)
+template<> struct hash<SourceDir> {
+ std::size_t operator()(const SourceDir& v) const {
+ hash<std::string> h;
+ return h(v.value());
+ }
+};
+#elif defined(COMPILER_MSVC)
+inline size_t hash_value(const SourceDir& v) {
+ return hash_value(v.value());
+}
+#endif // COMPILER...
+
+} // namespace BASE_HASH_NAMESPACE
+
+#endif // TOOLS_GN_SOURCE_DIR_H_
diff --git a/chromium/tools/gn/source_dir_unittest.cc b/chromium/tools/gn/source_dir_unittest.cc
new file mode 100644
index 00000000000..745513db759
--- /dev/null
+++ b/chromium/tools/gn/source_dir_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/source_dir.h"
+#include "tools/gn/source_file.h"
+
+TEST(SourceDir, ResolveRelativeFile) {
+ SourceDir base("//base/");
+
+ // Empty input is an error.
+ EXPECT_TRUE(base.ResolveRelativeFile("") == SourceFile());
+
+ // These things are directories, so should be an error.
+ EXPECT_TRUE(base.ResolveRelativeFile("//foo/bar/") == SourceFile());
+ EXPECT_TRUE(base.ResolveRelativeFile("bar/") == SourceFile());
+
+ // Absolute paths should be passed unchanged.
+ EXPECT_TRUE(base.ResolveRelativeFile("//foo") == SourceFile("//foo"));
+ EXPECT_TRUE(base.ResolveRelativeFile("/foo") == SourceFile("/foo"));
+
+ // Basic relative stuff.
+ EXPECT_TRUE(base.ResolveRelativeFile("foo") == SourceFile("//base/foo"));
+ EXPECT_TRUE(base.ResolveRelativeFile("./foo") == SourceFile("//base/foo"));
+ EXPECT_TRUE(base.ResolveRelativeFile("../foo") == SourceFile("//foo"));
+ EXPECT_TRUE(base.ResolveRelativeFile("../../foo") == SourceFile("//foo"));
+}
+
+TEST(SourceDir, ResolveRelativeDir) {
+ SourceDir base("//base/");
+
+ // Empty input is an error.
+ EXPECT_TRUE(base.ResolveRelativeDir("") == SourceDir());
+
+ // Absolute paths should be passed unchanged.
+ EXPECT_TRUE(base.ResolveRelativeDir("//foo") == SourceDir("//foo/"));
+ EXPECT_TRUE(base.ResolveRelativeDir("/foo") == SourceDir("/foo/"));
+
+ // Basic relative stuff.
+ EXPECT_TRUE(base.ResolveRelativeDir("foo") == SourceDir("//base/foo/"));
+ EXPECT_TRUE(base.ResolveRelativeDir("./foo") == SourceDir("//base/foo/"));
+ EXPECT_TRUE(base.ResolveRelativeDir("../foo") == SourceDir("//foo/"));
+ EXPECT_TRUE(base.ResolveRelativeDir("../../foo/") == SourceDir("//foo/"));
+}
diff --git a/chromium/tools/gn/source_file.cc b/chromium/tools/gn/source_file.cc
new file mode 100644
index 00000000000..62f8fb11a45
--- /dev/null
+++ b/chromium/tools/gn/source_file.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/source_file.h"
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/source_dir.h"
+
+SourceFile::SourceFile() {
+}
+
+SourceFile::SourceFile(const base::StringPiece& p)
+ : value_(p.data(), p.size()) {
+ DCHECK(!value_.empty());
+ DCHECK(value_[0] == '/');
+ DCHECK(!EndsWithSlash(value_));
+}
+
+SourceFile::~SourceFile() {
+}
+
+std::string SourceFile::GetName() const {
+ if (is_null())
+ return std::string();
+
+ DCHECK(value_.find('/') != std::string::npos);
+ size_t last_slash = value_.rfind('/');
+ return std::string(&value_[last_slash + 1],
+ value_.size() - last_slash - 1);
+}
+
+SourceDir SourceFile::GetDir() const {
+ if (is_null())
+ return SourceDir();
+
+ DCHECK(value_.find('/') != std::string::npos);
+ size_t last_slash = value_.rfind('/');
+ return SourceDir(base::StringPiece(&value_[0], last_slash + 1));
+}
+
+base::FilePath SourceFile::Resolve(const base::FilePath& source_root) const {
+ if (is_null())
+ return base::FilePath();
+
+ std::string converted;
+#if defined(OS_WIN)
+ if (is_system_absolute()) {
+ converted.assign(&value_[1], value_.size() - 1);
+ DCHECK(converted.size() > 2 && converted[1] == ':')
+ << "Expecting Windows absolute file path with a drive letter: "
+ << value_;
+ return base::FilePath(UTF8ToFilePath(converted));
+ }
+
+ converted.assign(&value_[2], value_.size() - 2);
+ ConvertPathToSystem(&converted);
+ return source_root.Append(UTF8ToFilePath(converted));
+#else
+ if (is_system_absolute())
+ return base::FilePath(value_);
+ converted.assign(&value_[2], value_.size() - 2);
+ return source_root.Append(converted);
+#endif
+}
diff --git a/chromium/tools/gn/source_file.h b/chromium/tools/gn/source_file.h
new file mode 100644
index 00000000000..d883bc061f6
--- /dev/null
+++ b/chromium/tools/gn/source_file.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_SOURCE_FILE_H_
+#define TOOLS_GN_SOURCE_FILE_H_
+
+#include <string>
+
+#include "base/containers/hash_tables.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+
+class SourceDir;
+
+// Represents a file within the source tree. Always begins in a slash, never
+// ends in one.
+class SourceFile {
+ public:
+ SourceFile();
+
+ // Takes a known absolute source file. Always begins in a slash.
+ explicit SourceFile(const base::StringPiece& p);
+
+ ~SourceFile();
+
+ bool is_null() const { return value_.empty(); }
+ const std::string& value() const { return value_; }
+
+ // Returns everythign after the last slash.
+ std::string GetName() const;
+ SourceDir GetDir() const;
+
+ // Resolves this source file relative to some given source root. Returns
+ // an empty file path on error.
+ base::FilePath Resolve(const base::FilePath& source_root) const;
+
+ // Returns true if this file starts with a "//" which indicates a path
+ // from the source root.
+ bool is_source_absolute() const {
+ return value_.size() >= 2 && value_[0] == '/' && value_[1] == '/';
+ }
+
+ // Returns true if this file starts with a single slash which indicates a
+ // system-absolute path.
+ bool is_system_absolute() const {
+ return !is_source_absolute();
+ }
+
+ // Returns a source-absolute path starting with only one slash at the
+ // beginning (normally source-absolute paths start with two slashes to mark
+ // them as such). This is normally used when concatenating names together.
+ //
+ // This function asserts that the file is actually source-absolute. The
+ // return value points into our buffer.
+ base::StringPiece SourceAbsoluteWithOneSlash() const {
+ CHECK(is_source_absolute());
+ return base::StringPiece(&value_[1], value_.size() - 1);
+ }
+
+ bool operator==(const SourceFile& other) const {
+ return value_ == other.value_;
+ }
+ bool operator!=(const SourceFile& other) const {
+ return !operator==(other);
+ }
+ bool operator<(const SourceFile& other) const {
+ return value_ < other.value_;
+ }
+
+ private:
+ friend class SourceDir;
+
+ std::string value_;
+
+ // Copy & assign supported.
+};
+
+namespace BASE_HASH_NAMESPACE {
+
+#if defined(COMPILER_GCC)
+template<> struct hash<SourceFile> {
+ std::size_t operator()(const SourceFile& v) const {
+ hash<std::string> h;
+ return h(v.value());
+ }
+};
+#elif defined(COMPILER_MSVC)
+inline size_t hash_value(const SourceFile& v) {
+ return hash_value(v.value());
+}
+#endif // COMPILER...
+
+} // namespace BASE_HASH_NAMESPACE
+
+#endif // TOOLS_GN_SOURCE_FILE_H_
diff --git a/chromium/tools/gn/standard_out.cc b/chromium/tools/gn/standard_out.cc
new file mode 100644
index 00000000000..f6a20318e41
--- /dev/null
+++ b/chromium/tools/gn/standard_out.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/standard_out.h"
+
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#else
+#include <stdio.h>
+#endif
+
+namespace {
+
+bool initialized = false;
+
+#if defined(OS_WIN)
+HANDLE hstdout;
+WORD default_attributes;
+
+bool is_console = false;
+#endif
+
+void EnsureInitialized() {
+ if (initialized)
+ return;
+ initialized = true;
+
+#if defined(OS_WIN)
+ hstdout = ::GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO info;
+ is_console = !!::GetConsoleScreenBufferInfo(hstdout, &info);
+ default_attributes = info.wAttributes;
+#endif
+}
+
+} // namespace
+
+#if defined(OS_WIN)
+
+void OutputString(const std::string& output, TextDecoration dec) {
+ EnsureInitialized();
+ if (is_console) {
+ switch (dec) {
+ case DECORATION_NONE:
+ break;
+ case DECORATION_BOLD:
+ ::SetConsoleTextAttribute(hstdout, FOREGROUND_INTENSITY);
+ break;
+ case DECORATION_RED:
+ ::SetConsoleTextAttribute(hstdout,
+ FOREGROUND_RED | FOREGROUND_INTENSITY);
+ break;
+ case DECORATION_GREEN:
+ // Keep green non-bold.
+ ::SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN);
+ break;
+ case DECORATION_BLUE:
+ ::SetConsoleTextAttribute(hstdout,
+ FOREGROUND_BLUE | FOREGROUND_INTENSITY);
+ break;
+ case DECORATION_YELLOW:
+ ::SetConsoleTextAttribute(hstdout,
+ FOREGROUND_RED | FOREGROUND_GREEN);
+ break;
+ }
+ }
+
+ DWORD written = 0;
+ ::WriteFile(hstdout, output.c_str(), output.size(), &written, NULL);
+
+ if (is_console)
+ ::SetConsoleTextAttribute(hstdout, default_attributes);
+}
+
+#else
+
+void OutputString(const std::string& output, TextDecoration dec) {
+ printf("%s", output.c_str());
+}
+
+#endif
diff --git a/chromium/tools/gn/standard_out.h b/chromium/tools/gn/standard_out.h
new file mode 100644
index 00000000000..2eb525bd469
--- /dev/null
+++ b/chromium/tools/gn/standard_out.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_STANDARD_OUT_H_
+#define TOOLS_GN_STANDARD_OUT_H_
+
+#include <string>
+
+enum TextDecoration {
+ DECORATION_NONE = 0,
+ DECORATION_BOLD,
+ DECORATION_RED,
+ DECORATION_GREEN,
+ DECORATION_BLUE,
+ DECORATION_YELLOW
+};
+
+void OutputString(const std::string& output,
+ TextDecoration dec = DECORATION_NONE);
+
+#endif // TOOLS_GN_STANDARD_OUT_H_
diff --git a/chromium/tools/gn/string_utils.cc b/chromium/tools/gn/string_utils.cc
new file mode 100644
index 00000000000..14d296a51e2
--- /dev/null
+++ b/chromium/tools/gn/string_utils.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/string_utils.h"
+
+#include "tools/gn/err.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/token.h"
+#include "tools/gn/tokenizer.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+// Constructs an Err indicating a range inside a string. We assume that the
+// token has quotes around it that are not counted by the offset.
+Err ErrInsideStringToken(const Token& token, size_t offset, size_t size,
+ const std::string& msg,
+ const std::string& help = std::string()) {
+ // The "+1" is skipping over the " at the beginning of the token.
+ Location begin_loc(token.location().file(),
+ token.location().line_number(),
+ token.location().char_offset() + offset + 1);
+ Location end_loc(token.location().file(),
+ token.location().line_number(),
+ token.location().char_offset() + offset + 1 + size);
+ return Err(LocationRange(begin_loc, end_loc), msg, help);
+}
+
+// Given the character input[i] indicating the $ in a string, locates the
+// identifier and places its range in |*identifier|, and updates |*i| to
+// point to the last character consumed.
+//
+// On error returns false and sets the error.
+bool LocateInlineIdenfitier(const Token& token,
+ const char* input, size_t size,
+ size_t* i,
+ base::StringPiece* identifier,
+ Err* err) {
+ size_t dollars_index = *i;
+ (*i)++;
+ if (*i == size) {
+ *err = ErrInsideStringToken(token, dollars_index, 1, "$ at end of string.",
+ "I was expecting an identifier after the $.");
+ return false;
+ }
+
+ bool has_brackets;
+ if (input[*i] == '{') {
+ (*i)++;
+ if (*i == size) {
+ *err = ErrInsideStringToken(token, dollars_index, 2,
+ "${ at end of string.",
+ "I was expecting an identifier inside the ${...}.");
+ return false;
+ }
+ has_brackets = true;
+ } else {
+ has_brackets = false;
+ }
+
+ // First char is special.
+ if (!Tokenizer::IsIdentifierFirstChar(input[*i])) {
+ *err = ErrInsideStringToken(
+ token, dollars_index, *i - dollars_index + 1,
+ "$ not followed by an identifier char.",
+ "It you want a literal $ use \"\\$\".");
+ return false;
+ }
+ size_t begin_offset = *i;
+ (*i)++;
+
+ // Find the first non-identifier char following the string.
+ while (*i < size && Tokenizer::IsIdentifierContinuingChar(input[*i]))
+ (*i)++;
+ size_t end_offset = *i;
+
+ // If we started with a bracket, validate that there's an ending one. Leave
+ // *i pointing to the last char we consumed (backing up one).
+ if (has_brackets) {
+ if (*i == size) {
+ *err = ErrInsideStringToken(token, dollars_index, *i - dollars_index,
+ "Unterminated ${...");
+ return false;
+ } else if (input[*i] != '}') {
+ *err = ErrInsideStringToken(token, *i, 1, "Not an identifier in string expansion.",
+ "The contents of ${...} should be an identifier. "
+ "This character is out of sorts.");
+ return false;
+ }
+ // We want to consume the bracket but also back up one, so *i is unchanged.
+ } else {
+ (*i)--;
+ }
+
+ *identifier = base::StringPiece(&input[begin_offset],
+ end_offset - begin_offset);
+ return true;
+}
+
+bool AppendIdentifierValue(Scope* scope,
+ const Token& token,
+ const base::StringPiece& identifier,
+ std::string* output,
+ Err* err) {
+ const Value* value = scope->GetValue(identifier, true);
+ if (!value) {
+ // We assume the identifier points inside the token.
+ *err = ErrInsideStringToken(
+ token, identifier.data() - token.value().data() - 1, identifier.size(),
+ "Undefined identifier in string expansion.",
+ std::string("\"") + identifier + "\" is not currently in scope.");
+ return false;
+ }
+
+ output->append(value->ToString());
+ return true;
+}
+
+} // namespace
+
+bool ExpandStringLiteral(Scope* scope,
+ const Token& literal,
+ Value* result,
+ Err* err) {
+ DCHECK(literal.type() == Token::STRING);
+ DCHECK(literal.value().size() > 1); // Should include quotes.
+ DCHECK(result->type() == Value::STRING); // Should be already set.
+
+ // The token includes the surrounding quotes, so strip those off.
+ const char* input = &literal.value().data()[1];
+ size_t size = literal.value().size() - 2;
+
+ std::string& output = result->string_value();
+ output.reserve(size);
+ for (size_t i = 0; i < size; i++) {
+ if (input[i] == '\\') {
+ if (i < size - 1) {
+ switch (input[i + 1]) {
+ case '\\':
+ case '"':
+ case '$':
+ output.push_back(input[i + 1]);
+ i++;
+ continue;
+ default: // Everything else has no meaning: pass the literal.
+ break;
+ }
+ }
+ output.push_back(input[i]);
+ } else if (input[i] == '$') {
+ base::StringPiece identifier;
+ if (!LocateInlineIdenfitier(literal, input, size, &i, &identifier, err))
+ return false;
+ if (!AppendIdentifierValue(scope, literal, identifier, &output, err))
+ return false;
+ } else {
+ output.push_back(input[i]);
+ }
+ }
+ return true;
+}
+
+std::string RemovePrefix(const std::string& str, const std::string& prefix) {
+ CHECK(str.size() >= prefix.size() &&
+ str.compare(0, prefix.size(), prefix) == 0);
+ return str.substr(prefix.size());
+}
diff --git a/chromium/tools/gn/string_utils.h b/chromium/tools/gn/string_utils.h
new file mode 100644
index 00000000000..7fff1d85602
--- /dev/null
+++ b/chromium/tools/gn/string_utils.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_STRING_UTILS_H_
+#define TOOLS_GN_STRING_UTILS_H_
+
+#include "base/strings/string_piece.h"
+
+class Err;
+class Scope;
+class Token;
+class Value;
+
+inline std::string operator+(const std::string& a, const base::StringPiece& b) {
+ std::string ret;
+ ret.reserve(a.size() + b.size());
+ ret.assign(a);
+ ret.append(b.data(), b.size());
+ return ret;
+}
+
+inline std::string operator+(const base::StringPiece& a, const std::string& b) {
+ std::string ret;
+ ret.reserve(a.size() + b.size());
+ ret.assign(a.data(), a.size());
+ ret.append(b);
+ return ret;
+}
+
+// Unescapes and expands variables in the given literal, writing the result
+// to the given value. On error, sets |err| and returns false.
+bool ExpandStringLiteral(Scope* scope,
+ const Token& literal,
+ Value* result,
+ Err* err);
+
+// Removes the given prefix from the string. Asserts if the string does
+// not have the given prefix.
+//
+// Note: could potentially return a StringPiece into the str.
+std::string RemovePrefix(const std::string& str, const std::string& prefix);
+
+// Appends the given string piece to the given string. This avoids an
+// intermediate copy.
+inline void AppendStringPiece(std::string* dest,
+ const base::StringPiece& piece) {
+ dest->append(piece.data(), piece.size());
+}
+
+#endif // TOOLS_GN_STRING_UTILS_H_
diff --git a/chromium/tools/gn/string_utils_unittest.cc b/chromium/tools/gn/string_utils_unittest.cc
new file mode 100644
index 00000000000..81181d27e67
--- /dev/null
+++ b/chromium/tools/gn/string_utils_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/err.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/string_utils.h"
+#include "tools/gn/token.h"
+#include "tools/gn/value.h"
+
+namespace {
+
+bool CheckExpansionCase(const char* input, const char* expected, bool success) {
+ Scope scope(static_cast<const Settings*>(NULL));
+ scope.SetValue("one", Value(NULL, 1), NULL);
+ scope.SetValue("onestring", Value(NULL, "one"), NULL);
+
+ // Construct the string token, which includes the quotes.
+ std::string literal_string;
+ literal_string.push_back('"');
+ literal_string.append(input);
+ literal_string.push_back('"');
+ Token literal(Location(), Token::STRING, literal_string);
+
+ Value result(NULL, Value::STRING);
+ Err err;
+ bool ret = ExpandStringLiteral(&scope, literal, &result, &err);
+
+ // Err and return value should agree.
+ EXPECT_NE(ret, err.has_error());
+
+ if (ret != success)
+ return false;
+
+ if (!success)
+ return true; // Don't check result on failure.
+ return result.string_value() == expected;
+}
+
+} // namespace
+
+TEST(StringUtils, ExpandStringLiteral) {
+ EXPECT_TRUE(CheckExpansionCase("", "", true));
+ EXPECT_TRUE(CheckExpansionCase("hello", "hello", true));
+ EXPECT_TRUE(CheckExpansionCase("hello #$one", "hello #1", true));
+ EXPECT_TRUE(CheckExpansionCase("hello #$one/two", "hello #1/two", true));
+ EXPECT_TRUE(CheckExpansionCase("hello #${one}", "hello #1", true));
+ EXPECT_TRUE(CheckExpansionCase("hello #${one}one", "hello #1one", true));
+ EXPECT_TRUE(CheckExpansionCase("hello #${one}$one", "hello #11", true));
+ EXPECT_TRUE(CheckExpansionCase("$onestring${one}$one", "one11", true));
+
+ // Errors
+ EXPECT_TRUE(CheckExpansionCase("hello #$", NULL, false));
+ EXPECT_TRUE(CheckExpansionCase("hello #$%", NULL, false));
+ EXPECT_TRUE(CheckExpansionCase("hello #${", NULL, false));
+ EXPECT_TRUE(CheckExpansionCase("hello #${}", NULL, false));
+ EXPECT_TRUE(CheckExpansionCase("hello #$nonexistant", NULL, false));
+ EXPECT_TRUE(CheckExpansionCase("hello #${unterminated", NULL, false));
+
+ // Unknown backslash values aren't special.
+ EXPECT_TRUE(CheckExpansionCase("\\", "\\", true));
+ EXPECT_TRUE(CheckExpansionCase("\\b", "\\b", true));
+
+ // Backslashes escape some special things. \"\$\\ -> "$\ Note that gtest
+ // doesn't like this escape sequence so we have to put it out-of-line.
+ const char* in = "\\\"\\$\\\\";
+ const char* out = "\"$\\";
+ EXPECT_TRUE(CheckExpansionCase(in, out, true));
+}
diff --git a/chromium/tools/gn/target.cc b/chromium/tools/gn/target.cc
new file mode 100644
index 00000000000..e01fa80e240
--- /dev/null
+++ b/chromium/tools/gn/target.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/target.h"
+
+#include "base/bind.h"
+#include "tools/gn/scheduler.h"
+
+namespace {
+
+void TargetResolvedThunk(const base::Callback<void(const Target*)>& cb,
+ const Target* t) {
+ cb.Run(t);
+}
+
+} // namespace
+
+Target::Target(const Settings* settings, const Label& label)
+ : Item(label),
+ settings_(settings),
+ output_type_(UNKNOWN),
+ generated_(false),
+ generator_function_(NULL) {
+}
+
+Target::~Target() {
+}
+
+Target* Target::AsTarget() {
+ return this;
+}
+
+const Target* Target::AsTarget() const {
+ return this;
+}
+
+void Target::OnResolved() {
+ // Gather info from our dependents we need.
+ for (size_t dep = 0; dep < deps_.size(); dep++) {
+ // All dependent configs get pulled to us, and to our dependents.
+ const std::vector<const Config*>& all =
+ deps_[dep]->all_dependent_configs();
+ for (size_t i = 0; i < all.size(); i++) {
+ configs_.push_back(all[i]);
+ all_dependent_configs_.push_back(all[i]);
+ }
+
+ // Direct dependent configs get pulled only to us.
+ const std::vector<const Config*>& direct =
+ deps_[dep]->direct_dependent_configs();
+ for (size_t i = 0; i < direct.size(); i++)
+ configs_.push_back(direct[i]);
+
+ // Direct dependent libraries.
+ if (deps_[dep]->output_type() == STATIC_LIBRARY ||
+ deps_[dep]->output_type() == SHARED_LIBRARY)
+ inherited_libraries_.insert(deps_[dep]);
+
+ // Inherited libraries. Don't pull transitive libraries from shared
+ // libraries, since obviously those shouldn't be linked directly into
+ // later deps unless explicitly specified.
+ if (deps_[dep]->output_type() != SHARED_LIBRARY &&
+ deps_[dep]->output_type() != EXECUTABLE) {
+ const std::set<const Target*> inherited =
+ deps_[dep]->inherited_libraries();
+ for (std::set<const Target*>::const_iterator i = inherited.begin();
+ i != inherited.end(); ++i)
+ inherited_libraries_.insert(*i);
+ }
+ }
+
+ if (!settings_->build_settings()->target_resolved_callback().is_null()) {
+ g_scheduler->ScheduleWork(base::Bind(&TargetResolvedThunk,
+ settings_->build_settings()->target_resolved_callback(),
+ this));
+ }
+}
+
+bool Target::HasBeenGenerated() const {
+ return generated_;
+}
+
+void Target::SetGenerated(const Token* token) {
+ DCHECK(!generated_);
+ generated_ = true;
+ generator_function_ = token;
+}
+
+bool Target::IsLinkable() const {
+ return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
+}
diff --git a/chromium/tools/gn/target.h b/chromium/tools/gn/target.h
new file mode 100644
index 00000000000..b5ea78cbb9b
--- /dev/null
+++ b/chromium/tools/gn/target.h
@@ -0,0 +1,140 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_TARGET_H_
+#define TOOLS_GN_TARGET_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "base/synchronization/lock.h"
+#include "tools/gn/config_values.h"
+#include "tools/gn/item.h"
+#include "tools/gn/script_values.h"
+#include "tools/gn/source_file.h"
+
+class InputFile;
+class Settings;
+class Token;
+
+class Target : public Item {
+ public:
+ enum OutputType {
+ UNKNOWN,
+ GROUP,
+ EXECUTABLE,
+ SHARED_LIBRARY,
+ STATIC_LIBRARY,
+ COPY_FILES,
+ CUSTOM,
+ };
+ typedef std::vector<SourceFile> FileList;
+ typedef std::vector<std::string> StringVector;
+
+ Target(const Settings* settings, const Label& label);
+ virtual ~Target();
+
+ // Item overrides.
+ virtual Target* AsTarget() OVERRIDE;
+ virtual const Target* AsTarget() const OVERRIDE;
+ virtual void OnResolved() OVERRIDE;
+
+ // This flag indicates if we've run the TargetGenerator for this target to
+ // fill out the rest of the values. Once we've done this, we save the
+ // location of the function that started the generating so that we can detect
+ // duplicate declarations.
+ bool HasBeenGenerated() const;
+ void SetGenerated(const Token* token);
+
+ const Settings* settings() const { return settings_; }
+
+ OutputType output_type() const { return output_type_; }
+ void set_output_type(OutputType t) { output_type_ = t; }
+
+ bool IsLinkable() const;
+
+ const FileList& sources() const { return sources_; }
+ void swap_in_sources(FileList* s) { sources_.swap(*s); }
+
+ const FileList& data() const { return data_; }
+ void swap_in_data(FileList* d) { data_.swap(*d); }
+
+ // Linked dependencies.
+ const std::vector<const Target*>& deps() const { return deps_; }
+ void swap_in_deps(std::vector<const Target*>* d) { deps_.swap(*d); }
+
+ // Non-linked dependencies.
+ const std::vector<const Target*>& datadeps() const { return datadeps_; }
+ void swap_in_datadeps(std::vector<const Target*>* d) { datadeps_.swap(*d); }
+
+ // List of configs that this class inherits settings from.
+ const std::vector<const Config*>& configs() const { return configs_; }
+ void swap_in_configs(std::vector<const Config*>* c) { configs_.swap(*c); }
+
+ // List of configs that all dependencies (direct and indirect) of this
+ // target get. These configs are not added to this target.
+ const std::vector<const Config*>& all_dependent_configs() const {
+ return all_dependent_configs_;
+ }
+ void swap_in_all_dependent_configs(std::vector<const Config*>* c) {
+ all_dependent_configs_.swap(*c);
+ }
+
+ // List of configs that targets depending directly on this one get. These
+ // configs are not added to this target.
+ const std::vector<const Config*>& direct_dependent_configs() const {
+ return direct_dependent_configs_;
+ }
+ void swap_in_direct_dependent_configs(std::vector<const Config*>* c) {
+ direct_dependent_configs_.swap(*c);
+ }
+
+ const std::set<const Target*>& inherited_libraries() const {
+ return inherited_libraries_;
+ }
+
+ // This config represents the configuration set directly on this target.
+ ConfigValues& config_values() { return config_values_; }
+ const ConfigValues& config_values() const { return config_values_; }
+
+ ScriptValues& script_values() { return script_values_; }
+ const ScriptValues& script_values() const { return script_values_; }
+
+ const SourceDir& destdir() const { return destdir_; }
+ void set_destdir(const SourceDir& d) { destdir_ = d; }
+
+ private:
+ const Settings* settings_;
+ OutputType output_type_;
+
+ FileList sources_;
+ FileList data_;
+ std::vector<const Target*> deps_;
+ std::vector<const Target*> datadeps_;
+ std::vector<const Config*> configs_;
+ std::vector<const Config*> all_dependent_configs_;
+ std::vector<const Config*> direct_dependent_configs_;
+
+ // Libraries from transitive deps. Libraries need to be linked only
+ // with the end target (executable, shared library). These do not get
+ // pushed beyond shared library boundaries.
+ std::set<const Target*> inherited_libraries_;
+
+ ConfigValues config_values_; // Used for all binary targets.
+ ScriptValues script_values_; // Used for script (CUSTOM) targets.
+
+ SourceDir destdir_;
+
+ bool generated_;
+ const Token* generator_function_; // Who generated this: for error messages.
+
+ DISALLOW_COPY_AND_ASSIGN(Target);
+};
+
+#endif // TOOLS_GN_TARGET_H_
diff --git a/chromium/tools/gn/target_generator.cc b/chromium/tools/gn/target_generator.cc
new file mode 100644
index 00000000000..72f7b004168
--- /dev/null
+++ b/chromium/tools/gn/target_generator.cc
@@ -0,0 +1,229 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/target_generator.h"
+
+#include "tools/gn/binary_target_generator.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/config.h"
+#include "tools/gn/copy_target_generator.h"
+#include "tools/gn/err.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/group_target_generator.h"
+#include "tools/gn/item_node.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/script_target_generator.h"
+#include "tools/gn/target_manager.h"
+#include "tools/gn/token.h"
+#include "tools/gn/value.h"
+#include "tools/gn/value_extractors.h"
+#include "tools/gn/variables.h"
+
+TargetGenerator::TargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Err* err)
+ : target_(target),
+ scope_(scope),
+ function_token_(function_token),
+ err_(err),
+ input_directory_(function_token.location().file()->dir()) {
+}
+
+TargetGenerator::~TargetGenerator() {
+}
+
+void TargetGenerator::Run() {
+ // All target types use these.
+ FillDependentConfigs();
+ FillData();
+ FillDependencies();
+
+ // To type-specific generation.
+ DoRun();
+
+ // Mark the target as complete.
+ if (!err_->has_error()) {
+ target_->SetGenerated(&function_token_);
+ GetBuildSettings()->target_manager().TargetGenerationComplete(
+ target_->label(), err_);
+ }
+}
+
+// static
+void TargetGenerator::GenerateTarget(Scope* scope,
+ const Token& function_token,
+ const std::vector<Value>& args,
+ const std::string& output_type,
+ Err* err) {
+ // Name is the argument to the function.
+ if (args.size() != 1u || args[0].type() != Value::STRING) {
+ *err = Err(function_token,
+ "Target generator requires one string argument.",
+ "Otherwise I'm not sure what to call this target.");
+ return;
+ }
+
+ // The location of the target is the directory name with no slash at the end.
+ // FIXME(brettw) validate name.
+ const Label& toolchain_label = ToolchainLabelForScope(scope);
+ Label label(function_token.location().file()->dir(),
+ args[0].string_value(),
+ toolchain_label.dir(), toolchain_label.name());
+
+ if (g_scheduler->verbose_logging())
+ g_scheduler->Log("Generating target", label.GetUserVisibleName(true));
+
+ Target* target =
+ scope->settings()->build_settings()->target_manager().GetTarget(
+ label, function_token.range(), NULL, err);
+ if (err->has_error())
+ return;
+
+ // Create and call out to the proper generator.
+ if (output_type == functions::kCopy) {
+ CopyTargetGenerator generator(target, scope, function_token, err);
+ generator.Run();
+ } else if (output_type == functions::kCustom) {
+ ScriptTargetGenerator generator(target, scope, function_token, err);
+ generator.Run();
+ } else if (output_type == functions::kExecutable) {
+ BinaryTargetGenerator generator(target, scope, function_token,
+ Target::EXECUTABLE, err);
+ generator.Run();
+ } else if (output_type == functions::kGroup) {
+ GroupTargetGenerator generator(target, scope, function_token, err);
+ generator.Run();
+ } else if (output_type == functions::kSharedLibrary) {
+ BinaryTargetGenerator generator(target, scope, function_token,
+ Target::SHARED_LIBRARY, err);
+ generator.Run();
+ } else if (output_type == functions::kStaticLibrary) {
+ BinaryTargetGenerator generator(target, scope, function_token,
+ Target::STATIC_LIBRARY, err);
+ generator.Run();
+ } else {
+ *err = Err(function_token, "Not a known output type",
+ "I am very confused.");
+ }
+}
+
+const BuildSettings* TargetGenerator::GetBuildSettings() const {
+ return scope_->settings()->build_settings();
+}
+
+void TargetGenerator::FillSources() {
+ const Value* value = scope_->GetValue(variables::kSources, true);
+ if (!value)
+ return;
+
+ Target::FileList dest_sources;
+ if (!ExtractListOfRelativeFiles(*value, input_directory_, &dest_sources,
+ err_))
+ return;
+ target_->swap_in_sources(&dest_sources);
+}
+
+void TargetGenerator::FillConfigs() {
+ FillGenericConfigs(variables::kConfigs, &Target::swap_in_configs);
+}
+
+void TargetGenerator::FillDependentConfigs() {
+ FillGenericConfigs(variables::kAllDependentConfigs,
+ &Target::swap_in_all_dependent_configs);
+ FillGenericConfigs(variables::kDirectDependentConfigs,
+ &Target::swap_in_direct_dependent_configs);
+}
+
+void TargetGenerator::FillData() {
+ // TODO(brettW) hook this up to the constant when we have cleaned up
+ // how data files are used.
+ const Value* value = scope_->GetValue("data", true);
+ if (!value)
+ return;
+
+ Target::FileList dest_data;
+ if (!ExtractListOfRelativeFiles(*value, input_directory_, &dest_data,
+ err_))
+ return;
+ target_->swap_in_data(&dest_data);
+}
+
+void TargetGenerator::FillDependencies() {
+ FillGenericDeps(variables::kDeps, &Target::swap_in_deps);
+ FillGenericDeps(variables::kDatadeps, &Target::swap_in_datadeps);
+}
+
+void TargetGenerator::SetToolchainDependency() {
+ // TODO(brettw) currently we lock separately for each config, dep, and
+ // toolchain we add which is bad! Do this in one lock.
+ ItemTree* tree = &GetBuildSettings()->item_tree();
+ base::AutoLock lock(tree->lock());
+ ItemNode* tc_node =
+ tree->GetExistingNodeLocked(ToolchainLabelForScope(scope_));
+ tree->GetExistingNodeLocked(target_->label())->AddDependency(
+ GetBuildSettings(), function_token_.range(), tc_node, err_);
+}
+
+void TargetGenerator::FillGenericConfigs(
+ const char* var_name,
+ void (Target::*setter)(std::vector<const Config*>*)) {
+ const Value* value = scope_->GetValue(var_name, true);
+ if (!value)
+ return;
+
+ std::vector<Label> labels;
+ if (!ExtractListOfLabels(*value, input_directory_,
+ ToolchainLabelForScope(scope_), &labels, err_))
+ return;
+
+ std::vector<const Config*> dest_configs;
+ dest_configs.resize(labels.size());
+ for (size_t i = 0; i < labels.size(); i++) {
+ dest_configs[i] = Config::GetConfig(
+ scope_->settings(),
+ value->list_value()[i].origin()->GetRange(),
+ labels[i], target_, err_);
+ if (err_->has_error())
+ return;
+ }
+ (target_->*setter)(&dest_configs);
+}
+
+void TargetGenerator::FillGenericDeps(
+ const char* var_name,
+ void (Target::*setter)(std::vector<const Target*>*)) {
+ const Value* value = scope_->GetValue(var_name, true);
+ if (!value)
+ return;
+
+ std::vector<Label> labels;
+ if (!ExtractListOfLabels(*value, input_directory_,
+ ToolchainLabelForScope(scope_), &labels, err_))
+ return;
+
+ std::vector<const Target*> dest_deps;
+ dest_deps.resize(labels.size());
+ for (size_t i = 0; i < labels.size(); i++) {
+ dest_deps[i] = GetBuildSettings()->target_manager().GetTarget(
+ labels[i], value->list_value()[i].origin()->GetRange(), target_, err_);
+ if (err_->has_error())
+ return;
+ }
+
+ (target_->*setter)(&dest_deps);
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chromium/tools/gn/target_generator.h b/chromium/tools/gn/target_generator.h
new file mode 100644
index 00000000000..f970cccbdfa
--- /dev/null
+++ b/chromium/tools/gn/target_generator.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_TARGET_GENERATOR_H_
+#define TOOLS_GN_TARGET_GENERATOR_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "tools/gn/source_dir.h"
+#include "tools/gn/target.h"
+
+class BuildSettings;
+class Err;
+class Location;
+class Scope;
+class Token;
+class Value;
+
+// Fills the variables in a Target object from a Scope (the result of a script
+// execution). Target-type-specific derivations of this class will be used
+// for each different type of function call. This class implements the common
+// behavior.
+class TargetGenerator {
+ public:
+ TargetGenerator(Target* target,
+ Scope* scope,
+ const Token& function_token,
+ Err* err);
+ ~TargetGenerator();
+
+ void Run();
+
+ // The function token is the token of the function name of the generator for
+ // this target. err() will be set on failure.
+ static void GenerateTarget(Scope* scope,
+ const Token& function_token,
+ const std::vector<Value>& args,
+ const std::string& output_type,
+ Err* err);
+
+ protected:
+ // Derived classes implement this to do type-specific generation.
+ virtual void DoRun() = 0;
+
+ const BuildSettings* GetBuildSettings() const;
+
+ void FillSources();
+ void FillConfigs();
+
+ // Sets the current toolchain as a dependecy of this target. All targets with
+ // a dependency on the toolchain should call this function.
+ void SetToolchainDependency();
+
+ Target* target_;
+ Scope* scope_;
+ const Token& function_token_;
+ Err* err_;
+
+ // Sources are relative to this. This comes from the input file which doesn't
+ // get freed so we don't acautlly have to make a copy.
+ const SourceDir& input_directory_;
+
+ private:
+ void FillDependentConfigs(); // Includes all types of dependent configs.
+ void FillData();
+ void FillDependencies(); // Includes data dependencies.
+
+ // Reads configs/deps from the given var name, and uses the given setting on
+ // the target to save them.
+ void FillGenericConfigs(const char* var_name,
+ void (Target::*setter)(std::vector<const Config*>*));
+ void FillGenericDeps(const char* var_name,
+ void (Target::*setter)(std::vector<const Target*>*));
+
+ DISALLOW_COPY_AND_ASSIGN(TargetGenerator);
+};
+
+#endif // TOOLS_GN_TARGET_GENERATOR_H_
diff --git a/chromium/tools/gn/target_generator_unittest.cc b/chromium/tools/gn/target_generator_unittest.cc
new file mode 100644
index 00000000000..feef6a96912
--- /dev/null
+++ b/chromium/tools/gn/target_generator_unittest.cc
@@ -0,0 +1,8 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/target_generator.h"
+
diff --git a/chromium/tools/gn/target_manager.cc b/chromium/tools/gn/target_manager.cc
new file mode 100644
index 00000000000..3b44e573d2e
--- /dev/null
+++ b/chromium/tools/gn/target_manager.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/target_manager.h"
+
+#include <deque>
+
+#include "base/bind.h"
+#include "base/strings/string_piece.h"
+#include "tools/gn/build_settings.h"
+#include "tools/gn/err.h"
+#include "tools/gn/filesystem_utils.h"
+#include "tools/gn/item_node.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/toolchain_manager.h"
+#include "tools/gn/value.h"
+
+TargetManager::TargetManager(const BuildSettings* build_settings)
+ : build_settings_(build_settings) {
+}
+
+TargetManager::~TargetManager() {
+}
+
+Target* TargetManager::GetTarget(const Label& label,
+ const LocationRange& specified_from_here,
+ Target* dep_from,
+ Err* err) {
+ DCHECK(!label.is_null());
+ DCHECK(!label.toolchain_dir().value().empty());
+ DCHECK(!label.toolchain_name().empty());
+
+ base::AutoLock lock(build_settings_->item_tree().lock());
+
+ ItemNode* target_node =
+ build_settings_->item_tree().GetExistingNodeLocked(label);
+ Target* target = NULL;
+ if (!target_node) {
+ // First time we've seen this, may need to load the file.
+
+ // Compute the settings. The common case is that we have a dep_from and
+ // the toolchains match, so we can use the settings from there rather than
+ // querying the toolchain manager (which requires locking, etc.).
+ const Settings* settings;
+ if (dep_from && dep_from->label().ToolchainsEqual(label)) {
+ settings = dep_from->settings();
+ } else {
+ settings =
+ build_settings_->toolchain_manager().GetSettingsForToolchainLocked(
+ specified_from_here, label.GetToolchainLabel(), err);
+ if (!settings)
+ return NULL;
+ }
+
+ target = new Target(settings, label);
+
+ target_node = new ItemNode(target);
+ if (settings->greedy_target_generation()) {
+ if (!target_node->SetShouldGenerate(build_settings_, err))
+ return NULL;
+ }
+ target_node->set_originally_referenced_from_here(specified_from_here);
+
+ build_settings_->item_tree().AddNodeLocked(target_node);
+
+ // We're generating a node when there is no referencing one.
+ if (!dep_from)
+ target_node->set_generated_from_here(specified_from_here);
+
+ } else if ((target = target_node->item()->AsTarget())) {
+ // Previously saw this item as a target.
+
+ // If we have no dep_from, we're generating it.
+ if (!dep_from) {
+ // In this case, it had better not already be generated.
+ if (target_node->state() != ItemNode::REFERENCED) {
+ *err = Err(specified_from_here,
+ "Duplicate target.",
+ "\"" + label.GetUserVisibleName(true) +
+ "\" being defined here.");
+ err->AppendSubErr(Err(target_node->generated_from_here(),
+ "Originally defined here."));
+ return NULL;
+ } else {
+ target_node->set_generated_from_here(specified_from_here);
+ }
+ }
+ } else {
+ // Error, we previously saw this thing as a non-target.
+ *err = Err(specified_from_here, "Not previously a target.",
+ "The target being declared here was previously seen referenced as a\n"
+ "non-target (like a config)");
+ err->AppendSubErr(Err(target_node->originally_referenced_from_here(),
+ "Originally referenced from here."));
+ return NULL;
+ }
+
+ // Keep a record of the guy asking us for this dependency. We know if
+ // somebody is adding a dependency, that guy it himself not resolved.
+ if (dep_from && target_node->state() != ItemNode::RESOLVED) {
+ ItemNode* from_node =
+ build_settings_->item_tree().GetExistingNodeLocked(dep_from->label());
+ if (!from_node->AddDependency(build_settings_, specified_from_here,
+ target_node, err))
+ return NULL;
+ }
+
+ return target;
+}
+
+bool TargetManager::TargetGenerationComplete(const Label& label,
+ Err* err) {
+ base::AutoLock lock(build_settings_->item_tree().lock());
+ return build_settings_->item_tree().MarkItemDefinedLocked(
+ build_settings_, label, err);
+}
+
+void TargetManager::GetAllTargets(
+ std::vector<const Target*>* all_targets) const {
+ base::AutoLock lock(build_settings_->item_tree().lock());
+
+ std::vector<const Item*> all_items;
+ build_settings_->item_tree().GetAllItemsLocked(&all_items);
+ for (size_t i = 0; i < all_items.size(); i++) {
+ const Target* t = all_items[i]->AsTarget();
+ if (t)
+ all_targets->push_back(t);
+ }
+}
diff --git a/chromium/tools/gn/target_manager.h b/chromium/tools/gn/target_manager.h
new file mode 100644
index 00000000000..f7459ff51f1
--- /dev/null
+++ b/chromium/tools/gn/target_manager.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_TARGET_MANAGER_H_
+#define TOOLS_GN_TARGET_MANAGER_H_
+
+#include <set>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/containers/hash_tables.h"
+#include "base/synchronization/lock.h"
+#include "tools/gn/target.h"
+
+class BuildSettings;
+class Err;
+class ItemTree;
+class LocationRange;
+class ToolchainManager;
+class Value;
+
+// Manages all the targets in the system. This integrates with the ItemTree
+// to manage the target-specific rules and creation.
+//
+// This class is threadsafe.
+class TargetManager {
+ public:
+ explicit TargetManager(const BuildSettings* settings);
+ ~TargetManager();
+
+ // Gets a reference to a named target. The given target name is created if
+ // it doesn't exist.
+ //
+ // The label should be fully specified in that it should include an
+ // explicit toolchain.
+ //
+ // |specified_from_here| should indicate the dependency or the target
+ // generator causing this access for error message generation.
+ //
+ // |dep_from| should be set when a target is getting a dep that it depends
+ // on. |dep_from| indicates the target that specified the dependency. It
+ // will be used to track outstanding dependencies so we can know when the
+ // target and all of its dependencies are complete. It should be null when
+ // getting a target for other reasons.
+ //
+ // On failure, |err| will be set.
+ //
+ // The returned pointer must not be dereferenced until it's generated, since
+ // it could be being generated on another thread.
+ Target* GetTarget(const Label& label,
+ const LocationRange& specified_from_here,
+ Target* dep_from,
+ Err* err);
+
+ // Called by a target when it has been loaded from the .gin file. Its
+ // dependencies may or may not be resolved yet.
+ bool TargetGenerationComplete(const Label& label, Err* err);
+
+ // Returns a list of all targets.
+ void GetAllTargets(std::vector<const Target*>* all_targets) const;
+
+ private:
+ const BuildSettings* build_settings_;
+
+ DISALLOW_COPY_AND_ASSIGN(TargetManager);
+};
+
+#endif // TOOLS_GN_TARGET_MANAGER_H
diff --git a/chromium/tools/gn/target_manager_unittest.cc b/chromium/tools/gn/target_manager_unittest.cc
new file mode 100644
index 00000000000..a1a3ad219b8
--- /dev/null
+++ b/chromium/tools/gn/target_manager_unittest.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/err.h"
+#include "tools/gn/settings.h"
+#include "tools/gn/target_manager.h"
+#include "tools/gn/value.h"
+
+/* TODO(brettw) make this compile again
+namespace {
+
+class TestTargetManagerDelegate : public TargetManager::Delegate {
+ public:
+ TestTargetManagerDelegate() {}
+
+ virtual bool ScheduleInvocation(ToolchainManager* toolchain_manager,
+ const LocationRange& origin,
+ const Label& toolchain_name,
+ const SourceDir& dir,
+ Err* err) OVERRIDE {
+ invokes.push_back(dir.value());
+ return true;
+ }
+ virtual void ScheduleTargetFileWrite(const Target* target) {
+ writes.push_back(target);
+ }
+
+ std::vector<std::string> invokes;
+ std::vector<const Target*> writes;
+};
+
+} // namespace
+
+TEST(TargetManager, ResolveDeps) {
+ TestTargetManagerDelegate ttmd;
+ BuildSettings build_settings(&ttmd);
+
+ TargetManager& target_manager = build_settings.target_manager();
+
+ SourceDir tc_dir("/chrome/");
+ std::string tc_name("toolchain");
+
+ // Get a root target. This should not invoke anything.
+ Err err;
+ Label chromelabel(SourceDir("/chrome/"), "chrome", tc_dir, tc_name);
+ Target* chrome = target_manager.GetTarget(
+ chromelabel, LocationRange(), NULL, &err);
+ EXPECT_EQ(0u, ttmd.invokes.size());
+
+ // Declare it has a dependency on content1 and 2. We should get one
+ // invocation of the content build file.
+ Label content1label(SourceDir("/content/"), "content1", tc_dir, tc_name);
+ Target* content1 = target_manager.GetTarget(
+ content1label, LocationRange(), chrome, &err);
+ EXPECT_EQ(1u, ttmd.invokes.size());
+
+ Label content2label(SourceDir("/content/"), "content2", tc_dir, tc_name);
+ Target* content2 = target_manager.GetTarget(
+ content2label, LocationRange(), chrome, &err);
+ EXPECT_EQ(2u, ttmd.invokes.size());
+
+ // Declare chrome has a depdency on base, this should load it.
+ Label baselabel(SourceDir("/base/"), "base", tc_dir, tc_name);
+ Target* base1 = target_manager.GetTarget(
+ baselabel, LocationRange(), chrome, &err);
+ EXPECT_EQ(3u, ttmd.invokes.size());
+
+ // Declare content1 has a dependency on base.
+ Target* base2 = target_manager.GetTarget(
+ baselabel, LocationRange(), content1, &err);
+ EXPECT_EQ(3u, ttmd.invokes.size());
+ EXPECT_EQ(base1, base2);
+
+ // Mark content1 and chrome as done. They have unresolved depdendencies so
+ // shouldn't be written out yet.
+ target_manager.TargetGenerationComplete(content1label);
+ target_manager.TargetGenerationComplete(chromelabel);
+ EXPECT_EQ(0u, ttmd.writes.size());
+
+ // Mark content2 as done. It has no dependencies so should be written.
+ target_manager.TargetGenerationComplete(content2label);
+ ASSERT_EQ(1u, ttmd.writes.size());
+ EXPECT_EQ(content2label, ttmd.writes[0]->label());
+
+ // Mark base as complete. It should have caused itself, content1 and then
+ // chrome to be written.
+ target_manager.TargetGenerationComplete(baselabel);
+ ASSERT_EQ(4u, ttmd.writes.size());
+ EXPECT_EQ(baselabel, ttmd.writes[1]->label());
+ EXPECT_EQ(content1label, ttmd.writes[2]->label());
+ EXPECT_EQ(chromelabel, ttmd.writes[3]->label());
+}
+*/
diff --git a/chromium/tools/gn/token.cc b/chromium/tools/gn/token.cc
new file mode 100644
index 00000000000..cbce5e75d07
--- /dev/null
+++ b/chromium/tools/gn/token.cc
@@ -0,0 +1,60 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/token.h"
+
+#include "base/logging.h"
+
+namespace {
+
+std::string UnescapeString(const base::StringPiece& input) {
+ std::string result;
+ result.reserve(input.size());
+
+ for (size_t i = 0; i < input.size(); i++) {
+ if (input[i] == '\\') {
+ DCHECK(i < input.size() - 1); // Last char shouldn't be a backslash or
+ // it would have escaped the terminator.
+ i++; // Skip backslash, next char is a literal.
+ }
+ result.push_back(input[i]);
+ }
+ return result;
+}
+
+} // namespace
+
+Token::Token() : type_(INVALID), value_() {
+}
+
+Token::Token(const Location& location,
+ Type t,
+ const base::StringPiece& v)
+ : type_(t),
+ value_(v),
+ location_(location) {
+}
+
+bool Token::IsIdentifierEqualTo(const char* v) const {
+ return type_ == IDENTIFIER && value_ == v;
+}
+
+bool Token::IsOperatorEqualTo(const char* v) const {
+ return type_ == OPERATOR && value_ == v;
+}
+
+bool Token::IsScoperEqualTo(const char* v) const {
+ return type_ == SCOPER && value_ == v;
+}
+
+bool Token::IsStringEqualTo(const char* v) const {
+ return type_ == STRING && value_ == v;
+}
+
+std::string Token::StringValue() const {
+ DCHECK(type() == STRING);
+
+ // Trim off the string terminators at the end.
+ return UnescapeString(value_.substr(1, value_.size() - 2));
+}
diff --git a/chromium/tools/gn/token.h b/chromium/tools/gn/token.h
new file mode 100644
index 00000000000..64b06ea13e0
--- /dev/null
+++ b/chromium/tools/gn/token.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_TOKEN_H_
+#define TOOLS_GN_TOKEN_H_
+
+#include "base/strings/string_piece.h"
+#include "tools/gn/location.h"
+
+class Token {
+ public:
+ enum Type {
+ INVALID,
+ INTEGER, // 123
+ STRING, // "blah"
+ OPERATOR, // =, +=, -=, +, -, ==, !=, <=, >=, <, >
+ IDENTIFIER, // foo
+ SCOPER, // (, ), [, ], {, }
+ SEPARATOR, // ,
+ COMMENT // #...\n
+ };
+
+ Token();
+ Token(const Location& location, Type t, const base::StringPiece& v);
+
+ Type type() const { return type_; }
+ const base::StringPiece& value() const { return value_; }
+ const Location& location() const { return location_; }
+ LocationRange range() const {
+ return LocationRange(location_,
+ Location(location_.file(), location_.line_number(),
+ location_.char_offset() + value_.size()));
+ }
+
+ // Helper functions for comparing this token to something.
+ bool IsIdentifierEqualTo(const char* v) const;
+ bool IsOperatorEqualTo(const char* v) const;
+ bool IsScoperEqualTo(const char* v) const;
+ bool IsStringEqualTo(const char* v) const;
+
+ // For STRING tokens, returns the string value (no quotes at end, does
+ // unescaping).
+ std::string StringValue() const;
+
+ private:
+ Type type_;
+ base::StringPiece value_;
+ Location location_;
+};
+
+#endif // TOOLS_GN_TOKEN_H_
diff --git a/chromium/tools/gn/tokenizer.cc b/chromium/tools/gn/tokenizer.cc
new file mode 100644
index 00000000000..971f56b820a
--- /dev/null
+++ b/chromium/tools/gn/tokenizer.cc
@@ -0,0 +1,309 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/tokenizer.h"
+
+#include "base/logging.h"
+#include "tools/gn/input_file.h"
+
+namespace {
+
+bool IsNumberChar(char c) {
+ return c == '-' || (c >= '0' && c <= '9');
+}
+
+bool CouldBeTwoCharOperatorBegin(char c) {
+ return c == '<' || c == '>' || c == '!' || c == '=' || c == '-' ||
+ c == '+' || c == '|' || c == '&';
+}
+
+bool CouldBeTwoCharOperatorEnd(char c) {
+ return c == '=' || c == '|' || c == '&';
+}
+
+bool CouldBeOneCharOperator(char c) {
+ return c == '=' || c == '<' || c == '>' || c == '+' || c == '!' ||
+ c == ':' || c == '|' || c == '&' || c == '-';
+}
+
+bool CouldBeOperator(char c) {
+ return CouldBeOneCharOperator(c) || CouldBeTwoCharOperatorBegin(c);
+}
+
+bool IsSeparatorChar(char c) {
+ return c == ',';
+}
+
+bool IsScoperChar(char c) {
+ return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}';
+}
+
+} // namespace
+
+Tokenizer::Tokenizer(const InputFile* input_file, Err* err)
+ : input_file_(input_file),
+ input_(input_file->contents()),
+ err_(err),
+ cur_(0),
+ line_number_(1),
+ char_in_line_(1) {
+}
+
+Tokenizer::~Tokenizer() {
+}
+
+// static
+std::vector<Token> Tokenizer::Tokenize(const InputFile* input_file, Err* err) {
+ Tokenizer t(input_file, err);
+ return t.Run();
+}
+
+std::vector<Token> Tokenizer::Run() {
+ std::vector<Token> tokens;
+ while (!done()) {
+ AdvanceToNextToken();
+ if (done())
+ break;
+ Location location = GetCurrentLocation();
+
+ Token::Type type = ClassifyCurrent();
+ if (type == Token::INVALID) {
+ *err_ = GetErrorForInvalidToken(location);
+ break;
+ }
+ size_t token_begin = cur_;
+ AdvanceToEndOfToken(location, type);
+ if (has_error())
+ break;
+ size_t token_end = cur_;
+
+ // TODO(brettw) This just strips comments from the token stream. This
+ // is probably wrong, they should be removed at a later stage so we can
+ // do things like rewrite the file. But this makes the parser simpler and
+ // is OK for now.
+ if (type != Token::COMMENT) {
+ tokens.push_back(Token(
+ location,
+ type,
+ base::StringPiece(&input_.data()[token_begin],
+ token_end - token_begin)));
+ }
+ }
+ if (err_->has_error())
+ tokens.clear();
+ return tokens;
+}
+
+// static
+size_t Tokenizer::ByteOffsetOfNthLine(const base::StringPiece& buf, int n) {
+ int cur_line = 1;
+ size_t cur_byte = 0;
+
+ DCHECK(n > 0);
+
+ if (n == 1)
+ return 0;
+
+ while (cur_byte < buf.size()) {
+ if (IsNewline(buf, cur_byte)) {
+ cur_line++;
+ if (cur_line == n)
+ return cur_byte + 1;
+ }
+ cur_byte++;
+ }
+ return -1;
+}
+
+// static
+bool Tokenizer::IsNewline(const base::StringPiece& buffer, size_t offset) {
+ DCHECK(offset < buffer.size());
+ // We may need more logic here to handle different line ending styles.
+ return buffer[offset] == '\n';
+}
+
+
+void Tokenizer::AdvanceToNextToken() {
+ while (!at_end() && IsCurrentWhitespace())
+ Advance();
+}
+
+Token::Type Tokenizer::ClassifyCurrent() const {
+ DCHECK(!at_end());
+ char next_char = cur_char();
+ if (next_char >= '0' && next_char <= '9')
+ return Token::INTEGER;
+ if (next_char == '"')
+ return Token::STRING;
+
+ // Note: '-' handled specially below.
+ if (next_char != '-' && CouldBeOperator(next_char))
+ return Token::OPERATOR;
+
+ if (IsIdentifierFirstChar(next_char))
+ return Token::IDENTIFIER;
+
+ if (IsScoperChar(next_char))
+ return Token::SCOPER;
+
+ if (IsSeparatorChar(next_char))
+ return Token::SEPARATOR;
+
+ if (next_char == '#')
+ return Token::COMMENT;
+
+ // For the case of '-' differentiate between a negative number and anything
+ // else.
+ if (next_char == '-') {
+ if (!CanIncrement())
+ return Token::OPERATOR; // Just the minus before end of file.
+ char following_char = input_[cur_ + 1];
+ if (following_char >= '0' && following_char <= '9')
+ return Token::INTEGER;
+ return Token::OPERATOR;
+ }
+
+ return Token::INVALID;
+}
+
+void Tokenizer::AdvanceToEndOfToken(const Location& location,
+ Token::Type type) {
+ switch (type) {
+ case Token::INTEGER:
+ do {
+ Advance();
+ } while (!at_end() && IsNumberChar(cur_char()));
+ if (!at_end()) {
+ // Require the char after a number to be some kind of space, scope,
+ // or operator.
+ char c = cur_char();
+ if (!IsCurrentWhitespace() && !CouldBeOperator(c) &&
+ !IsScoperChar(c) && !IsSeparatorChar(c)) {
+ *err_ = Err(GetCurrentLocation(),
+ "This is not a valid number.",
+ "Learn to count.");
+ // Highlight the number.
+ err_->AppendRange(LocationRange(location, GetCurrentLocation()));
+ }
+ }
+ break;
+
+ case Token::STRING: {
+ char initial = cur_char();
+ Advance(); // Advance past initial "
+ for (;;) {
+ if (at_end()) {
+ *err_ = Err(LocationRange(location,
+ Location(input_file_, line_number_, char_in_line_)),
+ "Unterminated string literal.",
+ "Don't leave me hanging like this!");
+ break;
+ }
+ if (IsCurrentStringTerminator(initial)) {
+ Advance(); // Skip past last "
+ break;
+ } else if (cur_char() == '\n') {
+ *err_ = Err(LocationRange(location,
+ GetCurrentLocation()),
+ "Newline in string constant.");
+ }
+ Advance();
+ }
+ break;
+ }
+
+ case Token::OPERATOR:
+ // Some operators are two characters, some are one.
+ if (CouldBeTwoCharOperatorBegin(cur_char())) {
+ if (CanIncrement() && CouldBeTwoCharOperatorEnd(input_[cur_ + 1]))
+ Advance();
+ }
+ Advance();
+ break;
+
+ case Token::IDENTIFIER:
+ while (!at_end() && IsIdentifierContinuingChar(cur_char()))
+ Advance();
+ break;
+
+ case Token::SCOPER:
+ case Token::SEPARATOR:
+ Advance(); // All are one char.
+ break;
+
+ case Token::COMMENT:
+ // Eat to EOL.
+ while (!at_end() && !IsCurrentNewline())
+ Advance();
+ break;
+
+ case Token::INVALID:
+ *err_ = Err(location, "Everything is all messed up",
+ "Please insert system disk in drive A: and press any key.");
+ NOTREACHED();
+ return;
+ }
+}
+
+bool Tokenizer::IsCurrentWhitespace() const {
+ DCHECK(!at_end());
+ char c = input_[cur_];
+ // Note that tab (0x09) is illegal.
+ return c == 0x0A || c == 0x0B || c == 0x0C || c == 0x0D || c == 0x20;
+}
+
+bool Tokenizer::IsCurrentStringTerminator(char quote_char) const {
+ DCHECK(!at_end());
+ if (cur_char() != quote_char)
+ return false;
+
+ // Check for escaping. \" is not a string terminator, but \\" is. Count
+ // the number of preceeding backslashes.
+ int num_backslashes = 0;
+ for (int i = static_cast<int>(cur_) - 1; i >= 0 && input_[i] == '\\'; i--)
+ num_backslashes++;
+
+ // Even backslashes mean that they were escaping each other and don't count
+ // as escaping this quote.
+ return (num_backslashes % 2) == 0;
+}
+
+bool Tokenizer::IsCurrentNewline() const {
+ return IsNewline(input_, cur_);
+}
+
+void Tokenizer::Advance() {
+ DCHECK(cur_ < input_.size());
+ if (IsCurrentNewline()) {
+ line_number_++;
+ char_in_line_ = 1;
+ } else {
+ char_in_line_++;
+ }
+ cur_++;
+}
+
+Location Tokenizer::GetCurrentLocation() const {
+ return Location(input_file_, line_number_, char_in_line_);
+}
+
+Err Tokenizer::GetErrorForInvalidToken(const Location& location) const {
+ std::string help;
+ if (cur_char() == ';') {
+ // Semicolon.
+ help = "Semicolons are not needed, delete this one.";
+ } else if (cur_char() == '\t') {
+ // Tab.
+ help = "You got a tab character in here. Tabs are evil. "
+ "Convert to spaces.";
+ } else if (cur_char() == '/' && cur_ + 1 < input_.size() &&
+ (input_[cur_ + 1] == '/' || input_[cur_ + 1] == '*')) {
+ // Different types of comments.
+ help = "Comments should start with # instead";
+ } else {
+ help = "I have no idea what this is.";
+ }
+
+ return Err(location, "Invalid token.", help);
+}
diff --git a/chromium/tools/gn/tokenizer.h b/chromium/tools/gn/tokenizer.h
new file mode 100644
index 00000000000..5e0016919f2
--- /dev/null
+++ b/chromium/tools/gn/tokenizer.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_TOKENIZER_H_
+#define TOOLS_GN_TOKENIZER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/strings/string_piece.h"
+#include "tools/gn/err.h"
+#include "tools/gn/token.h"
+
+class InputFile;
+
+class Tokenizer {
+ public:
+ static std::vector<Token> Tokenize(const InputFile* input_file, Err* err);
+
+ // Counts lines in the given buffer (the first line is "1") and returns
+ // the byte offset of the beginning of that line, or (size_t)-1 if there
+ // aren't that many lines in the file. Note that this will return the byte
+ // one past the end of the input if the last character is a newline.
+ //
+ // This is a helper function for error output so that the tokenizer's
+ // notion of lines can be used elsewhere.
+ static size_t ByteOffsetOfNthLine(const base::StringPiece& buf, int n);
+
+ // Returns true if the given offset of the string piece counts as a newline.
+ // The offset must be in the buffer.
+ static bool IsNewline(const base::StringPiece& buffer, size_t offset);
+
+ static bool IsIdentifierFirstChar(char c) {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_';
+ }
+
+ static bool IsIdentifierContinuingChar(char c) {
+ // Also allow digits after the first char.
+ return IsIdentifierFirstChar(c) || (c >= '0' && c <= '9');
+ }
+
+ private:
+ // InputFile must outlive the tokenizer and all generated tokens.
+ explicit Tokenizer(const InputFile* input_file, Err* err);
+ ~Tokenizer();
+
+ std::vector<Token> Run();
+
+ void AdvanceToNextToken();
+ Token::Type ClassifyCurrent() const;
+ void AdvanceToEndOfToken(const Location& location, Token::Type type);
+
+ bool IsCurrentWhitespace() const;
+ bool IsCurrentNewline() const;
+ bool IsCurrentStringTerminator(char quote_char) const;
+
+ bool CanIncrement() const { return cur_ < input_.size(); }
+
+ // Increments the current location by one.
+ void Advance();
+
+ // Returns the current character in the file as a location.
+ Location GetCurrentLocation() const;
+
+ Err GetErrorForInvalidToken(const Location& location) const;
+
+ bool done() const { return at_end() || has_error(); }
+
+ bool at_end() const { return cur_ == input_.size(); }
+ char cur_char() const { return input_[cur_]; }
+
+ bool has_error() const { return err_->has_error(); }
+
+ const InputFile* input_file_;
+ const base::StringPiece input_;
+ Err* err_;
+ size_t cur_; // Byte offset into input buffer.
+
+ int line_number_;
+ int char_in_line_;
+
+ DISALLOW_COPY_AND_ASSIGN(Tokenizer);
+};
+
+#endif // TOOLS_GN_TOKENIZER_H_
diff --git a/chromium/tools/gn/tokenizer_unittest.cc b/chromium/tools/gn/tokenizer_unittest.cc
new file mode 100644
index 00000000000..d1a678842b8
--- /dev/null
+++ b/chromium/tools/gn/tokenizer_unittest.cc
@@ -0,0 +1,162 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/token.h"
+#include "tools/gn/tokenizer.h"
+
+namespace {
+
+struct TokenExpectation {
+ Token::Type type;
+ const char* value;
+};
+
+template<size_t len>
+bool CheckTokenizer(const char* input, const TokenExpectation (&expect)[len]) {
+ InputFile input_file(SourceFile("/test"));
+ input_file.SetContents(input);
+
+ Err err;
+ std::vector<Token> results = Tokenizer::Tokenize(&input_file, &err);
+
+ if (results.size() != len)
+ return false;
+ for (size_t i = 0; i < len; i++) {
+ if (expect[i].type != results[i].type())
+ return false;
+ if (expect[i].value != results[i].value())
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+TEST(Tokenizer, Empty) {
+ InputFile empty_string_input(SourceFile("/test"));
+ empty_string_input.SetContents("");
+
+ Err err;
+ std::vector<Token> results = Tokenizer::Tokenize(&empty_string_input, &err);
+ EXPECT_TRUE(results.empty());
+
+ InputFile whitespace_input(SourceFile("/test"));
+ whitespace_input.SetContents(" \n\r");
+
+ results = Tokenizer::Tokenize(&whitespace_input, &err);
+ EXPECT_TRUE(results.empty());
+}
+
+TEST(Tokenizer, Identifier) {
+ TokenExpectation one_ident[] = {
+ { Token::IDENTIFIER, "foo" }
+ };
+ EXPECT_TRUE(CheckTokenizer(" foo ", one_ident));
+}
+
+TEST(Tokenizer, Integer) {
+ TokenExpectation integers[] = {
+ { Token::INTEGER, "123" },
+ { Token::INTEGER, "-123" }
+ };
+ EXPECT_TRUE(CheckTokenizer(" 123 -123 ", integers));
+}
+
+TEST(Tokenizer, String) {
+ TokenExpectation strings[] = {
+ { Token::STRING, "\"foo\"" },
+ { Token::STRING, "\"bar\\\"baz\"" },
+ { Token::STRING, "\"asdf\\\\\"" }
+ };
+ EXPECT_TRUE(CheckTokenizer(" \"foo\" \"bar\\\"baz\" \"asdf\\\\\" ",
+ strings));
+}
+
+TEST(Tokenizer, Operator) {
+ TokenExpectation operators[] = {
+ { Token::OPERATOR, "-" },
+ { Token::OPERATOR, "+" },
+ { Token::OPERATOR, "=" },
+ { Token::OPERATOR, "+=" },
+ { Token::OPERATOR, "-=" },
+ { Token::OPERATOR, "!=" },
+ { Token::OPERATOR, "==" },
+ { Token::OPERATOR, "<" },
+ { Token::OPERATOR, ">" },
+ { Token::OPERATOR, "<=" },
+ { Token::OPERATOR, ">=" },
+ };
+ EXPECT_TRUE(CheckTokenizer("- + = += -= != == < > <= >=",
+ operators));
+}
+
+TEST(Tokenizer, Scoper) {
+ TokenExpectation scopers[] = {
+ { Token::SCOPER, "{" },
+ { Token::SCOPER, "[" },
+ { Token::SCOPER, "]" },
+ { Token::SCOPER, "}" },
+ { Token::SCOPER, "(" },
+ { Token::SCOPER, ")" },
+ };
+ EXPECT_TRUE(CheckTokenizer("{[ ]} ()", scopers));
+}
+
+TEST(Tokenizer, FunctionCall) {
+ TokenExpectation fn[] = {
+ { Token::IDENTIFIER, "fun" },
+ { Token::SCOPER, "(" },
+ { Token::STRING, "\"foo\"" },
+ { Token::SCOPER, ")" },
+ { Token::SCOPER, "{" },
+ { Token::IDENTIFIER, "foo" },
+ { Token::OPERATOR, "=" },
+ { Token::INTEGER, "12" },
+ { Token::SCOPER, "}" },
+ };
+ EXPECT_TRUE(CheckTokenizer("fun(\"foo\") {\nfoo = 12}", fn));
+}
+
+TEST(Tokenizer, StringUnescaping) {
+ InputFile input(SourceFile("/test"));
+ input.SetContents("\"asd\\\"f\" \"\"");
+ Err err;
+ std::vector<Token> results = Tokenizer::Tokenize(&input, &err);
+
+ ASSERT_EQ(2u, results.size());
+ EXPECT_EQ("asd\"f", results[0].StringValue());
+ EXPECT_EQ("", results[1].StringValue());
+}
+
+TEST(Tokenizer, Locations) {
+ InputFile input(SourceFile("/test"));
+ input.SetContents("1 2 \"three\"\n 4");
+ Err err;
+ std::vector<Token> results = Tokenizer::Tokenize(&input, &err);
+
+ ASSERT_EQ(4u, results.size());
+ ASSERT_TRUE(results[0].location() == Location(&input, 1, 1));
+ ASSERT_TRUE(results[1].location() == Location(&input, 1, 3));
+ ASSERT_TRUE(results[2].location() == Location(&input, 1, 5));
+ ASSERT_TRUE(results[3].location() == Location(&input, 2, 3));
+}
+
+TEST(Tokenizer, ByteOffsetOfNthLine) {
+ EXPECT_EQ(0u, Tokenizer::ByteOffsetOfNthLine("foo", 1));
+
+ // Windows and Posix have different line endings, so check the byte at the
+ // location rather than the offset.
+ char input1[] = "aaa\nxaa\n\nya";
+ EXPECT_EQ('x', input1[Tokenizer::ByteOffsetOfNthLine(input1, 2)]);
+ EXPECT_EQ('y', input1[Tokenizer::ByteOffsetOfNthLine(input1, 4)]);
+
+ char input2[3];
+ input2[0] = 'a';
+ input2[1] = '\n'; // Manually set to avoid Windows double-byte endings.
+ input2[2] = 0;
+ EXPECT_EQ(0u, Tokenizer::ByteOffsetOfNthLine(input2, 1));
+ EXPECT_EQ(2u, Tokenizer::ByteOffsetOfNthLine(input2, 2));
+}
diff --git a/chromium/tools/gn/toolchain.cc b/chromium/tools/gn/toolchain.cc
new file mode 100644
index 00000000000..d906b9a820b
--- /dev/null
+++ b/chromium/tools/gn/toolchain.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/toolchain.h"
+
+#include "base/logging.h"
+
+const char* Toolchain::kToolCc = "cc";
+const char* Toolchain::kToolCxx = "cxx";
+const char* Toolchain::kToolObjC = "objc";
+const char* Toolchain::kToolObjCxx = "objcxx";
+const char* Toolchain::kToolAsm = "asm";
+const char* Toolchain::kToolAlink = "alink";
+const char* Toolchain::kToolSolink = "solink";
+const char* Toolchain::kToolLink = "link";
+const char* Toolchain::kToolStamp = "stamp";
+const char* Toolchain::kToolCopy = "copy";
+
+Toolchain::Tool::Tool() {
+}
+
+Toolchain::Tool::~Tool() {
+}
+
+Toolchain::Toolchain(const Label& label) : Item(label) {
+}
+
+Toolchain::~Toolchain() {
+}
+
+Toolchain* Toolchain::AsToolchain() {
+ return this;
+}
+
+const Toolchain* Toolchain::AsToolchain() const {
+ return this;
+}
+
+// static
+Toolchain::ToolType Toolchain::ToolNameToType(const base::StringPiece& str) {
+ if (str == kToolCc) return TYPE_CC;
+ if (str == kToolCxx) return TYPE_CXX;
+ if (str == kToolObjC) return TYPE_OBJC;
+ if (str == kToolObjCxx) return TYPE_OBJCXX;
+ if (str == kToolAsm) return TYPE_ASM;
+ if (str == kToolAlink) return TYPE_ALINK;
+ if (str == kToolSolink) return TYPE_SOLINK;
+ if (str == kToolLink) return TYPE_LINK;
+ if (str == kToolStamp) return TYPE_STAMP;
+ if (str == kToolCopy) return TYPE_COPY;
+ return TYPE_NONE;
+}
+
+// static
+std::string Toolchain::ToolTypeToName(ToolType type) {
+ switch (type) {
+ case TYPE_CC: return kToolCc;
+ case TYPE_CXX: return kToolCxx;
+ case TYPE_OBJC: return kToolObjC;
+ case TYPE_OBJCXX: return kToolObjCxx;
+ case TYPE_ASM: return kToolAsm;
+ case TYPE_ALINK: return kToolAlink;
+ case TYPE_SOLINK: return kToolSolink;
+ case TYPE_LINK: return kToolLink;
+ case TYPE_STAMP: return kToolStamp;
+ case TYPE_COPY: return kToolCopy;
+ default:
+ NOTREACHED();
+ return std::string();
+ }
+}
+
+const Toolchain::Tool& Toolchain::GetTool(ToolType type) const {
+ DCHECK(type != TYPE_NONE);
+ return tools_[static_cast<size_t>(type)];
+}
+
+void Toolchain::SetTool(ToolType type, const Tool& t) {
+ DCHECK(type != TYPE_NONE);
+ tools_[static_cast<size_t>(type)] = t;
+}
diff --git a/chromium/tools/gn/toolchain.h b/chromium/tools/gn/toolchain.h
new file mode 100644
index 00000000000..5223a05d266
--- /dev/null
+++ b/chromium/tools/gn/toolchain.h
@@ -0,0 +1,96 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_TOOLCHAIN_H_
+#define TOOLS_GN_TOOLCHAIN_H_
+
+#include "base/compiler_specific.h"
+#include "base/strings/string_piece.h"
+#include "tools/gn/item.h"
+
+// Holds information on a specific toolchain. This data is filled in when we
+// encounter a toolchain definition.
+//
+// This class is an Item so it can participate in dependency management. In
+// particular, when a target uses a toolchain, it should have a dependency on
+// that toolchain's object so that we can be sure we loaded the toolchain
+// before generating the build for that target.
+//
+// Note on threadsafety: The label of the toolchain never changes so can
+// safetly be accessed from any thread at any time (we do this when asking for
+// the toolchain name). But the values in the toolchain do, so these can't
+// be accessed until this Item is resolved.
+class Toolchain : public Item {
+ public:
+ enum ToolType {
+ TYPE_NONE = 0,
+ TYPE_CC,
+ TYPE_CXX,
+ TYPE_OBJC,
+ TYPE_OBJCXX,
+ TYPE_ASM,
+ TYPE_ALINK,
+ TYPE_SOLINK,
+ TYPE_LINK,
+ TYPE_STAMP,
+ TYPE_COPY,
+
+ TYPE_NUMTYPES // Must be last.
+ };
+
+ static const char* kToolCc;
+ static const char* kToolCxx;
+ static const char* kToolObjC;
+ static const char* kToolObjCxx;
+ static const char* kToolAsm;
+ static const char* kToolAlink;
+ static const char* kToolSolink;
+ static const char* kToolLink;
+ static const char* kToolStamp;
+ static const char* kToolCopy;
+
+ struct Tool {
+ Tool();
+ ~Tool();
+
+ bool empty() const {
+ return command.empty() && depfile.empty() && deps.empty() &&
+ description.empty() && pool.empty() && restat.empty() &&
+ rspfile.empty() && rspfile_content.empty();
+ }
+
+ std::string command;
+ std::string depfile;
+ std::string deps;
+ std::string description;
+ std::string pool;
+ std::string restat;
+ std::string rspfile;
+ std::string rspfile_content;
+ };
+
+ Toolchain(const Label& label);
+ virtual ~Toolchain();
+
+ // Item overrides.
+ virtual Toolchain* AsToolchain() OVERRIDE;
+ virtual const Toolchain* AsToolchain() const OVERRIDE;
+
+ // Returns TYPE_NONE on failure.
+ static ToolType ToolNameToType(const base::StringPiece& str);
+ static std::string ToolTypeToName(ToolType type);
+
+ const Tool& GetTool(ToolType type) const;
+ void SetTool(ToolType type, const Tool& t);
+
+ const std::string& environment() const { return environment_; }
+ void set_environment(const std::string& env) { environment_ = env; }
+
+ private:
+ Tool tools_[TYPE_NUMTYPES];
+
+ std::string environment_;
+};
+
+#endif // TOOLS_GN_TOOLCHAIN_H_
diff --git a/chromium/tools/gn/toolchain_manager.cc b/chromium/tools/gn/toolchain_manager.cc
new file mode 100644
index 00000000000..f292626cef3
--- /dev/null
+++ b/chromium/tools/gn/toolchain_manager.cc
@@ -0,0 +1,497 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/toolchain_manager.h"
+
+#include <set>
+
+#include "base/bind.h"
+#include "build/build_config.h"
+#include "tools/gn/err.h"
+#include "tools/gn/item.h"
+#include "tools/gn/item_node.h"
+#include "tools/gn/item_tree.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scheduler.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/scope_per_file_provider.h"
+
+namespace {
+
+SourceFile DirToBuildFile(const SourceDir& dir) {
+ return SourceFile(dir.value() + "BUILD.gn");
+}
+
+void SetSystemVars(const Settings& settings, Scope* scope) {
+#if defined(OS_WIN)
+ scope->SetValue("is_win", Value(NULL, 1), NULL);
+ scope->SetValue("is_posix", Value(NULL, 0), NULL);
+#else
+ scope->SetValue("is_win", Value(NULL, 0), NULL);
+ scope->SetValue("is_posix", Value(NULL, 1), NULL);
+#endif
+
+#if defined(OS_MACOSX)
+ scope->SetValue("is_mac", Value(NULL, 1), NULL);
+#else
+ scope->SetValue("is_mac", Value(NULL, 0), NULL);
+#endif
+
+#if defined(OS_LINUX)
+ scope->SetValue("is_linux", Value(NULL, 1), NULL);
+#else
+ scope->SetValue("is_linux", Value(NULL, 0), NULL);
+#endif
+}
+
+} // namespace
+
+struct ToolchainManager::Info {
+ Info(const BuildSettings* build_settings,
+ const Label& toolchain_name,
+ const std::string& output_subdir_name)
+ : state(TOOLCHAIN_SETTINGS_NOT_LOADED),
+ toolchain(toolchain_name),
+ toolchain_set(false),
+ settings(build_settings, &toolchain, output_subdir_name),
+ item_node(NULL) {
+ }
+
+ // Makes sure that an ItemNode is created for the toolchain, which lets
+ // targets depend on the (potentially future) loading of the toolchain.
+ //
+ // We can't always do this at the beginning since when doing the default
+ // build config, we don't know the toolchain name yet. We also need to go
+ // through some effort to avoid doing this inside the toolchain manager's
+ // lock (to avoid holding two locks at once).
+ void EnsureItemNode() {
+ if (!item_node) {
+ ItemTree& tree = settings.build_settings()->item_tree();
+ item_node = new ItemNode(&toolchain);
+ tree.AddNodeLocked(item_node);
+ }
+ }
+
+ SettingsState state;
+
+ Toolchain toolchain;
+ bool toolchain_set;
+ LocationRange toolchain_definition_location;
+
+ // When the state is TOOLCHAIN_SETTINGS_LOADED, the settings should be
+ // considered read-only and can be read without locking. Otherwise, they
+ // should not be accessed at all except to load them (which can therefore
+ // also be done outside of the lock). This works as long as the state flag
+ // is only ever read or written inside the lock.
+ Settings settings;
+
+ // While state == TOOLCHAIN_SETTINGS_LOADING, this will collect all
+ // scheduled invocations using this toolchain. They'll be issued once the
+ // settings file has been interpreted.
+ //
+ // The map maps the source file to "some" location it was invoked from (so
+ // we can give good error messages. It does NOT map to the root of the
+ // file to be invoked (the file still needs loading). This will be NULL
+ // for internally invoked files.
+ typedef std::map<SourceFile, LocationRange> ScheduledInvocationMap;
+ ScheduledInvocationMap scheduled_invocations;
+
+ // Tracks all scheduled and executed invocations for this toolchain. This
+ // is used to avoid invoking a file more than once for a toolchain.
+ std::set<SourceFile> all_invocations;
+
+ // Filled in by EnsureItemNode, see that for more.
+ ItemNode* item_node;
+};
+
+ToolchainManager::ToolchainManager(const BuildSettings* build_settings)
+ : build_settings_(build_settings) {
+}
+
+ToolchainManager::~ToolchainManager() {
+ for (ToolchainMap::iterator i = toolchains_.begin();
+ i != toolchains_.end(); ++i)
+ delete i->second;
+ toolchains_.clear();
+}
+
+void ToolchainManager::StartLoadingUnlocked(const SourceFile& build_file_name) {
+ // How the default build config works: Initially we don't have a toolchain
+ // name to call the settings for the default build config. So we create one
+ // with an empty toolchain name and execute the default build config file.
+ // When that's done, we'll go and fix up the name to the default build config
+ // that the script set.
+ base::AutoLock lock(GetLock());
+ Err err;
+ Info* info = LoadNewToolchainLocked(LocationRange(), Label(), &err);
+ if (err.has_error())
+ g_scheduler->FailWithError(err);
+ CHECK(info);
+ info->scheduled_invocations[build_file_name] = LocationRange();
+ info->all_invocations.insert(build_file_name);
+
+ g_scheduler->IncrementWorkCount();
+ if (!g_scheduler->input_file_manager()->AsyncLoadFile(
+ LocationRange(), build_settings_,
+ build_settings_->build_config_file(),
+ base::Bind(&ToolchainManager::BackgroundLoadBuildConfig,
+ base::Unretained(this), info, true),
+ &err)) {
+ g_scheduler->FailWithError(err);
+ g_scheduler->DecrementWorkCount();
+ }
+}
+
+const Settings* ToolchainManager::GetSettingsForToolchainLocked(
+ const LocationRange& from_here,
+ const Label& toolchain_name,
+ Err* err) {
+ GetLock().AssertAcquired();
+ ToolchainMap::iterator found = toolchains_.find(toolchain_name);
+ Info* info = NULL;
+ if (found == toolchains_.end()) {
+ info = LoadNewToolchainLocked(from_here, toolchain_name, err);
+ if (!info)
+ return NULL;
+ } else {
+ info = found->second;
+ }
+ info->EnsureItemNode();
+
+ return &info->settings;
+}
+
+const Toolchain* ToolchainManager::GetToolchainDefinitionUnlocked(
+ const Label& toolchain_name) {
+ base::AutoLock lock(GetLock());
+ ToolchainMap::iterator found = toolchains_.find(toolchain_name);
+ if (found == toolchains_.end() || !found->second->toolchain_set)
+ return NULL;
+
+ // Since we don't allow defining a toolchain more than once, we know that
+ // once it's set it won't be mutated, so we can safely return this pointer
+ // for reading outside the lock.
+ return &found->second->toolchain;
+}
+
+bool ToolchainManager::SetDefaultToolchainUnlocked(
+ const Label& default_toolchain,
+ const LocationRange& defined_here,
+ Err* err) {
+ base::AutoLock lock(GetLock());
+ if (!default_toolchain_.is_null()) {
+ *err = Err(defined_here, "Default toolchain already set.");
+ err->AppendSubErr(Err(default_toolchain_defined_here_,
+ "Previously defined here.",
+ "You can only set this once."));
+ return false;
+ }
+
+ if (default_toolchain.is_null()) {
+ *err = Err(defined_here, "Bad default toolchain name.",
+ "You can't set the default toolchain name to nothing.");
+ return false;
+ }
+ if (!default_toolchain.toolchain_dir().is_null() ||
+ !default_toolchain.toolchain_name().empty()) {
+ *err = Err(defined_here, "Toolchain name has toolchain.",
+ "You can't specify a toolchain (inside the parens) for a toolchain "
+ "name. I got:\n" + default_toolchain.GetUserVisibleName(true));
+ return false;
+ }
+
+ default_toolchain_ = default_toolchain;
+ default_toolchain_defined_here_ = defined_here;
+ return true;
+}
+
+Label ToolchainManager::GetDefaultToolchainUnlocked() const {
+ base::AutoLock lock(GetLock());
+ return default_toolchain_;
+}
+
+bool ToolchainManager::SetToolchainDefinitionLocked(
+ const Toolchain& tc,
+ const LocationRange& defined_from,
+ Err* err) {
+ GetLock().AssertAcquired();
+
+ ToolchainMap::iterator found = toolchains_.find(tc.label());
+ Info* info = NULL;
+ if (found == toolchains_.end()) {
+ // New toolchain.
+ info = LoadNewToolchainLocked(defined_from, tc.label(), err);
+ if (!info)
+ return false;
+ } else {
+ // It's important to preserve the exact Toolchain object in our tree since
+ // it will be in the ItemTree and targets may have dependencies on it.
+ info = found->second;
+ }
+
+ // The labels should match or else we're setting the wrong one!
+ CHECK(info->toolchain.label() == tc.label());
+
+ info->toolchain = tc;
+ if (info->toolchain_set) {
+ *err = Err(defined_from, "Duplicate toolchain definition.");
+ err->AppendSubErr(Err(
+ info->toolchain_definition_location,
+ "Previously defined here.",
+ "A toolchain can only be defined once. One tricky way that this could\n"
+ "happen is if your definition is itself in a file that's interpreted\n"
+ "under different toolchains, which would result in multiple\n"
+ "definitions as the file is loaded multiple times. So be sure your\n"
+ "toolchain definitions are in files that either don't define any\n"
+ "targets (probably best) or at least don't contain targets executed\n"
+ "with more than one toolchain."));
+ return false;
+ }
+
+ info->EnsureItemNode();
+
+ info->toolchain_set = true;
+ info->toolchain_definition_location = defined_from;
+ return true;
+}
+
+bool ToolchainManager::ScheduleInvocationLocked(
+ const LocationRange& specified_from,
+ const Label& toolchain_name,
+ const SourceDir& dir,
+ Err* err) {
+ GetLock().AssertAcquired();
+ SourceFile build_file(DirToBuildFile(dir));
+
+ // If there's no specified toolchain name, use the default.
+ ToolchainMap::iterator found;
+ if (toolchain_name.is_null())
+ found = toolchains_.find(default_toolchain_);
+ else
+ found = toolchains_.find(toolchain_name);
+
+ Info* info = NULL;
+ if (found == toolchains_.end()) {
+ // New toolchain.
+ info = LoadNewToolchainLocked(specified_from, toolchain_name, err);
+ if (!info)
+ return false;
+ } else {
+ // Use existing one.
+ info = found->second;
+ if (info->all_invocations.find(build_file) !=
+ info->all_invocations.end()) {
+ // We've already seen this source file for this toolchain, don't need
+ // to do anything.
+ return true;
+ }
+ }
+
+ info->all_invocations.insert(build_file);
+
+ // True if the settings load needs to be scheduled.
+ bool info_needs_settings_load = false;
+
+ // True if the settings load has completed.
+ bool info_settings_loaded = false;
+
+ switch (info->state) {
+ case TOOLCHAIN_SETTINGS_NOT_LOADED:
+ info_needs_settings_load = true;
+ info->scheduled_invocations[build_file] = specified_from;
+ break;
+
+ case TOOLCHAIN_SETTINGS_LOADING:
+ info->scheduled_invocations[build_file] = specified_from;
+ break;
+
+ case TOOLCHAIN_SETTINGS_LOADED:
+ info_settings_loaded = true;
+ break;
+ }
+
+ if (info_needs_settings_load) {
+ // Load the settings file.
+ g_scheduler->IncrementWorkCount();
+ if (!g_scheduler->input_file_manager()->AsyncLoadFile(
+ specified_from, build_settings_,
+ build_settings_->build_config_file(),
+ base::Bind(&ToolchainManager::BackgroundLoadBuildConfig,
+ base::Unretained(this), info, false),
+ err)) {
+ g_scheduler->DecrementWorkCount();
+ return false;
+ }
+ } else if (info_settings_loaded) {
+ // Settings are ready to go, load the target file.
+ g_scheduler->IncrementWorkCount();
+ if (!g_scheduler->input_file_manager()->AsyncLoadFile(
+ specified_from, build_settings_, build_file,
+ base::Bind(&ToolchainManager::BackgroundInvoke,
+ base::Unretained(this), info, build_file),
+ err)) {
+ g_scheduler->DecrementWorkCount();
+ return false;
+ }
+ }
+ // Else we should have added the infocations to the scheduled_invocations
+ // from within the lock above.
+ return true;
+}
+
+// static
+std::string ToolchainManager::ToolchainToOutputSubdir(
+ const Label& toolchain_name) {
+ // For now just assume the toolchain name is always a valid dir name. We may
+ // want to clean up the in the future.
+ return toolchain_name.name();
+}
+
+ToolchainManager::Info* ToolchainManager::LoadNewToolchainLocked(
+ const LocationRange& specified_from,
+ const Label& toolchain_name,
+ Err* err) {
+ GetLock().AssertAcquired();
+ Info* info = new Info(build_settings_,
+ toolchain_name,
+ ToolchainToOutputSubdir(toolchain_name));
+
+ toolchains_[toolchain_name] = info;
+
+ // Invoke the file containing the toolchain definition so that it gets
+ // defined. The default one (label is empty) will be done spearately.
+ if (!toolchain_name.is_null()) {
+ // The default toolchain should be specified whenever we're requesting
+ // another one. This is how we know under what context we should execute
+ // the invoke for the toolchain file.
+ CHECK(!default_toolchain_.is_null());
+ ScheduleInvocationLocked(specified_from, default_toolchain_,
+ toolchain_name.dir(), err);
+ }
+ return info;
+}
+
+void ToolchainManager::FixupDefaultToolchainLocked() {
+ // Now that we've run the default build config, we should know the
+ // default toolchain name. Fix up our reference.
+ // See Start() for more.
+ GetLock().AssertAcquired();
+ if (default_toolchain_.is_null()) {
+ g_scheduler->FailWithError(Err(Location(),
+ "Default toolchain not set.",
+ "Your build config file \"" +
+ build_settings_->build_config_file().value() +
+ "\"\ndid not call set_default_toolchain(). This is needed so "
+ "I know how to actually\ncompile your code."));
+ return;
+ }
+
+ ToolchainMap::iterator old_default = toolchains_.find(Label());
+ CHECK(old_default != toolchains_.end());
+ Info* info = old_default->second;
+ toolchains_[default_toolchain_] = info;
+ toolchains_.erase(old_default);
+
+ // Toolchain should not have been loaded in the build config file.
+ CHECK(!info->toolchain_set);
+
+ // We need to set the toolchain label now that we know it. There's no way
+ // to set the label, but we can assign the toolchain to a new one. Loading
+ // the build config can not change the toolchain, so we won't be overwriting
+ // anything useful.
+ info->toolchain = Toolchain(default_toolchain_);
+ info->EnsureItemNode();
+
+ // The default toolchain is loaded in greedy mode so all targets we
+ // encounter are generated. Non-default toolchain settings stay in non-greedy
+ // so we only generate the minimally required set.
+ info->settings.set_greedy_target_generation(true);
+
+ // Schedule a load of the toolchain build file.
+ Err err;
+ ScheduleInvocationLocked(LocationRange(), default_toolchain_,
+ default_toolchain_.dir(), &err);
+ if (err.has_error())
+ g_scheduler->FailWithError(err);
+}
+
+void ToolchainManager::BackgroundLoadBuildConfig(Info* info,
+ bool is_default,
+ const ParseNode* root) {
+ // Danger: No early returns without decrementing the work count.
+ if (root && !g_scheduler->is_failed()) {
+ // Nobody should be accessing settings at this point other than us since we
+ // haven't marked it loaded, so we can do it outside the lock.
+ Scope* base_config = info->settings.base_config();
+ SetSystemVars(info->settings, base_config);
+ base_config->SetProcessingBuildConfig();
+ if (is_default)
+ base_config->SetProcessingDefaultBuildConfig();
+
+ const BlockNode* root_block = root->AsBlock();
+ Err err;
+ root_block->ExecuteBlockInScope(base_config, &err);
+
+ base_config->ClearProcessingBuildConfig();
+ if (is_default)
+ base_config->ClearProcessingDefaultBuildConfig();
+
+ if (err.has_error()) {
+ g_scheduler->FailWithError(err);
+ } else {
+ // Base config processing succeeded.
+ Info::ScheduledInvocationMap schedule_these;
+ {
+ base::AutoLock lock(GetLock());
+ schedule_these.swap(info->scheduled_invocations);
+ info->state = TOOLCHAIN_SETTINGS_LOADED;
+ if (is_default)
+ FixupDefaultToolchainLocked();
+ }
+
+ // Schedule build files waiting on this settings. There can be many so we
+ // want to load them in parallel on the pool.
+ for (Info::ScheduledInvocationMap::iterator i = schedule_these.begin();
+ i != schedule_these.end() && !g_scheduler->is_failed(); ++i) {
+ // Note i->second may be NULL, so don't dereference.
+ g_scheduler->IncrementWorkCount();
+ if (!g_scheduler->input_file_manager()->AsyncLoadFile(
+ i->second, build_settings_, i->first,
+ base::Bind(&ToolchainManager::BackgroundInvoke,
+ base::Unretained(this), info, i->first),
+ &err)) {
+ g_scheduler->FailWithError(err);
+ g_scheduler->DecrementWorkCount();
+ break;
+ }
+ }
+ }
+ }
+ g_scheduler->DecrementWorkCount();
+}
+
+void ToolchainManager::BackgroundInvoke(const Info* info,
+ const SourceFile& file_name,
+ const ParseNode* root) {
+ if (root && !g_scheduler->is_failed()) {
+ if (g_scheduler->verbose_logging()) {
+ g_scheduler->Log("Running", file_name.value() + " with toolchain " +
+ info->toolchain.label().GetUserVisibleName(false));
+ }
+
+ Scope our_scope(info->settings.base_config());
+ ScopePerFileProvider per_file_provider(&our_scope, file_name);
+
+ Err err;
+ root->Execute(&our_scope, &err);
+ if (err.has_error())
+ g_scheduler->FailWithError(err);
+ }
+
+ g_scheduler->DecrementWorkCount();
+}
+
+base::Lock& ToolchainManager::GetLock() const {
+ return build_settings_->item_tree().lock();
+}
diff --git a/chromium/tools/gn/toolchain_manager.h b/chromium/tools/gn/toolchain_manager.h
new file mode 100644
index 00000000000..3ecb16d527f
--- /dev/null
+++ b/chromium/tools/gn/toolchain_manager.h
@@ -0,0 +1,168 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_TOOLCHAIN_MANAGER_H_
+#define TOOLS_GN_TOOLCHAIN_MANAGER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/synchronization/lock.h"
+#include "tools/gn/label.h"
+#include "tools/gn/location.h"
+#include "tools/gn/source_file.h"
+#include "tools/gn/toolchain.h"
+
+class Err;
+class BuildSettings;
+class ParseNode;
+class Settings;
+
+// The toolchain manager manages the mapping of toolchain names to the
+// settings and toolchain object. It also loads build files in the context of a
+// toolchain context of a toolchain, and manages running the build config
+// script when necessary.
+//
+// This class uses the lock from the item tree to manage threadsafety. The
+// functions requiring this lock to be held are named "Locked" to make this
+// more clear. The "Unlocked" versions will acquire the lock themselves so will
+// break if you call it while locked. (The rationale behind which is which is
+// just based on the needs of the callers, so it can be changed.) There are two
+// reasons for this:
+//
+// The first is that when resolving a target, we do a bunch of script
+// stuff (slow) and then lookup the target, config, and toolchain dependencies
+// based on that. The options are to do a lock around each dependency lookup
+// or do a lock around the entire operation. Given that there's not a huge
+// amount of work, the "big lock" approach is likely a bit better since it
+// avoids lots of locking overhead.
+//
+// The second reason is that if we had a separate lock here, we would need to
+// lock around creating a new toolchain. But creating a new toolchain involves
+// adding it to the item tree, and this needs to be done atomically to prevent
+// other threads from seeing a partially initialized toolchain. This sets up
+// having deadlock do to acquiring multiple locks, or recursive locking
+// problems.
+class ToolchainManager {
+ public:
+ ToolchainManager(const BuildSettings* build_settings);
+ ~ToolchainManager();
+
+ // At the very beginning of processing, this begins loading build files.
+ // This will scheduler loadin the default build config and the given build
+ // file in that context, going out from there.
+ //
+ // This returns immediately, you need to run the Scheduler to actually
+ // process anything. It's assumed this function is called on the main thread
+ // before doing anything, so it does not need locking.
+ void StartLoadingUnlocked(const SourceFile& build_file_name);
+
+ // Returns the settings object for a given toolchain. This does not
+ // schedule loading the given toolchain if it's not loaded yet: you actually
+ // need to invoke a target with that toolchain to get that.
+ //
+ // On error, returns NULL and sets the error.
+ const Settings* GetSettingsForToolchainLocked(const LocationRange& from_here,
+ const Label& toolchain_name,
+ Err* err);
+
+ // Returns the toolchain definition or NULL if the toolchain hasn't been
+ // defined yet.
+ const Toolchain* GetToolchainDefinitionUnlocked(const Label& toolchain_name);
+
+ // Sets the default toolchain. If the default toolchain is already set,
+ // this function will return false and fill in the given err.
+ bool SetDefaultToolchainUnlocked(const Label& dt,
+ const LocationRange& defined_from,
+ Err* err);
+
+ // Returns the default toolchain name. This will be empty if it hasn't been
+ // set.
+ Label GetDefaultToolchainUnlocked() const;
+
+ // Saves the given named toolchain (the name will be taken from the toolchain
+ // parameter). This will fail and return false if the given toolchain was
+ // already defined. In this case, the given error will be set.
+ bool SetToolchainDefinitionLocked(const Toolchain& tc,
+ const LocationRange& defined_from,
+ Err* err);
+
+ // Schedules an invocation of the given file under the given toolchain. The
+ // toolchain file will be loaded if necessary. If the toolchain is an is_null
+ // label, the default toolchain will be used.
+ //
+ // The origin should be the node that will be blamed for this invocation if
+ // an error occurs. If a synchronous error occurs, the given error will be
+ // set and it will return false. If an async error occurs, the error will be
+ // sent to the scheduler.
+ bool ScheduleInvocationLocked(const LocationRange& origin,
+ const Label& toolchain_name,
+ const SourceDir& dir,
+ Err* err);
+
+ private:
+ enum SettingsState {
+ // Toolchain settings have not requested to be loaded. This means we
+ // haven't seen any targets that require this toolchain yet. Not loading
+ // the settings automatically allows you to define a bunch of toolchains
+ // and potentially not use them without much overhead.
+ TOOLCHAIN_SETTINGS_NOT_LOADED,
+
+ // The settings have been scheduled to be loaded but have not completed.
+ TOOLCHAIN_SETTINGS_LOADING,
+
+ // The settings are done being loaded.
+ TOOLCHAIN_SETTINGS_LOADED
+ };
+
+ struct Info;
+
+ static std::string ToolchainToOutputSubdir(const Label& toolchain_name);
+
+ // Creates a new info struct and saves it in the map. A pointer to the
+ // struct is returned. No loads are scheduled.
+ //
+ // If the label is non-empty, the toolchain will be added to the ItemTree
+ // so that other nodes can depend on it. THe empty label case is for the
+ // default build config file (when the toolchain name isn't known yet). It
+ // will be added later.
+ //
+ // On error, will return NULL and the error will be set.
+ Info* LoadNewToolchainLocked(const LocationRange& specified_from,
+ const Label& toolchain_name,
+ Err* err);
+
+ // Fixes up the default toolchain names once they're known when processing
+ // the default build config, or throw an error if the default toolchain
+ // hasn't been set. See the StartLoading() implementation for more.
+ void FixupDefaultToolchainLocked();
+
+ // Loads the base config for the given toolchain. Run on a background thread
+ // asynchronously.
+ void BackgroundLoadBuildConfig(Info* info,
+ bool is_default,
+ const ParseNode* root);
+
+ // Invokes the given file for a toolchain with loaded settings. Run on a
+ // background thread asynchronously.
+ void BackgroundInvoke(const Info* info,
+ const SourceFile& file_name,
+ const ParseNode* root);
+
+ // Returns the lock to use.
+ base::Lock& GetLock() const;
+
+ const BuildSettings* build_settings_;
+
+ // We own the info pointers.
+ typedef std::map<Label, Info*> ToolchainMap;
+ ToolchainMap toolchains_;
+
+ Label default_toolchain_;
+ LocationRange default_toolchain_defined_here_;
+
+ DISALLOW_COPY_AND_ASSIGN(ToolchainManager);
+};
+
+#endif // TOOLS_GN_TOOLCHAIN_MANAGER_H_
diff --git a/chromium/tools/gn/value.cc b/chromium/tools/gn/value.cc
new file mode 100644
index 00000000000..cb78faadcfd
--- /dev/null
+++ b/chromium/tools/gn/value.cc
@@ -0,0 +1,126 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/value.h"
+
+#include "base/strings/string_number_conversions.h"
+
+Value::Value()
+ : type_(NONE),
+ int_value_(0),
+ origin_(NULL) {
+}
+
+Value::Value(const ParseNode* origin, Type t)
+ : type_(t),
+ int_value_(0),
+ origin_(origin) {
+}
+
+Value::Value(const ParseNode* origin, int64 int_val)
+ : type_(INTEGER),
+ int_value_(int_val),
+ origin_(origin) {
+}
+
+Value::Value(const ParseNode* origin, const base::StringPiece& str_val)
+ : type_(STRING),
+ string_value_(str_val.as_string()),
+ int_value_(0),
+ origin_(origin) {
+}
+
+Value::~Value() {
+}
+
+// static
+const char* Value::DescribeType(Type t) {
+ switch (t) {
+ case NONE:
+ return "none";
+ case INTEGER:
+ return "integer";
+ case STRING:
+ return "string";
+ case LIST:
+ return "list";
+ default:
+ NOTREACHED();
+ return "UNKNOWN";
+ }
+}
+
+int64 Value::InterpretAsInt() const {
+ switch (type_) {
+ case NONE:
+ return 0;
+ case INTEGER:
+ return int_value_;
+ case STRING:
+ return string_value_.empty() ? 0 : 1;
+ case LIST:
+ return list_value_.empty() ? 0 : 1;
+ }
+ return 0;
+}
+
+std::string Value::ToString() const {
+ switch (type_) {
+ case NONE:
+ return "<void>";
+ case INTEGER:
+ return base::Int64ToString(int_value_);
+ case STRING:
+ return string_value_;
+ case LIST: {
+ std::string result = "[";
+ for (size_t i = 0; i < list_value_.size(); i++) {
+ if (i > 0)
+ result += ", ";
+ // TODO(brettw) maybe also want to escape quotes in the string.
+ if (list_value_[i].type() == STRING)
+ result += std::string("\"") + list_value_[i].ToString() + "\"";
+ else
+ result += list_value_[i].ToString();
+ }
+ result.push_back(']');
+ return result;
+ }
+ }
+ return std::string();
+}
+
+bool Value::VerifyTypeIs(Type t, Err* err) const {
+ if (type_ == t)
+ return true;
+
+ *err = Err(origin(), std::string("This is not a ") + DescribeType(t) + ".");
+ return false;
+}
+
+bool Value::operator==(const Value& other) const {
+ if (type_ != other.type_)
+ return false;
+
+ switch (type_) {
+ case Value::INTEGER:
+ return int_value() == other.int_value();
+ case Value::STRING:
+ return string_value() == other.string_value();
+ case Value::LIST:
+ if (list_value().size() != other.list_value().size())
+ return false;
+ for (size_t i = 0; i < list_value().size(); i++) {
+ if (list_value()[i] != other.list_value()[i])
+ return false;
+ }
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool Value::operator!=(const Value& other) const {
+ return !operator==(other);
+}
diff --git a/chromium/tools/gn/value.h b/chromium/tools/gn/value.h
new file mode 100644
index 00000000000..8802bffb157
--- /dev/null
+++ b/chromium/tools/gn/value.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_VALUE_H_
+#define TOOLS_GN_VALUE_H_
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/strings/string_piece.h"
+#include "tools/gn/err.h"
+
+class ParseNode;
+
+// Represents a variable value in the interpreter.
+class Value {
+ public:
+ enum Type {
+ NONE = 0,
+ INTEGER,
+ STRING,
+ LIST
+ };
+
+ Value();
+ Value(const ParseNode* origin, Type t);
+ Value(const ParseNode* origin, int64 int_val);
+ Value(const ParseNode* origin, const base::StringPiece& str_val);
+ ~Value();
+
+ Type type() const { return type_; }
+
+ // Returns a string describing the given type.
+ static const char* DescribeType(Type t);
+
+ // Returns the node that made this. May be NULL.
+ const ParseNode* origin() const { return origin_; }
+ void set_origin(const ParseNode* o) { origin_ = o; }
+
+ int64& int_value() {
+ DCHECK(type_ == INTEGER);
+ return int_value_;
+ }
+ const int64& int_value() const {
+ DCHECK(type_ == INTEGER);
+ return int_value_;
+ }
+
+ std::string& string_value() {
+ DCHECK(type_ == STRING);
+ return string_value_;
+ }
+ const std::string& string_value() const {
+ DCHECK(type_ == STRING);
+ return string_value_;
+ }
+
+ std::vector<Value>& list_value() {
+ DCHECK(type_ == LIST);
+ return list_value_;
+ }
+ const std::vector<Value>& list_value() const {
+ DCHECK(type_ == LIST);
+ return list_value_;
+ }
+
+ // Returns the current value converted to an int, normally used for
+ // boolean operations. Undefined variables, empty lists, and empty strings
+ // are all interpreted as 0, otherwise 1.
+ int64 InterpretAsInt() const;
+
+ // Converts the given value to a string.
+ std::string ToString() const;
+
+ // Verifies that the value is of the given type. If it isn't, returns
+ // false and sets the error.
+ bool VerifyTypeIs(Type t, Err* err) const;
+
+ // Compares values. Only the "value" is compared, not the origin.
+ bool operator==(const Value& other) const;
+ bool operator!=(const Value& other) const;
+
+ private:
+ Type type_;
+ std::string string_value_;
+ int64 int_value_;
+ std::vector<Value> list_value_;
+ const ParseNode* origin_;
+};
+
+#endif // TOOLS_GN_VALUE_H_
diff --git a/chromium/tools/gn/value_extractors.cc b/chromium/tools/gn/value_extractors.cc
new file mode 100644
index 00000000000..56a2be28b09
--- /dev/null
+++ b/chromium/tools/gn/value_extractors.cc
@@ -0,0 +1,102 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/value_extractors.h"
+
+#include "tools/gn/err.h"
+#include "tools/gn/label.h"
+#include "tools/gn/source_dir.h"
+#include "tools/gn/source_file.h"
+
+namespace {
+
+// This extractor rejects files with system-absolute file paths. If we need
+// that in the future, we'll have to add some flag to control this.
+struct RelativeFileConverter {
+ RelativeFileConverter(const SourceDir& current_dir_in)
+ : current_dir(current_dir_in) {}
+ bool operator()(const Value& v, SourceFile* out, Err* err) const {
+ if (!v.VerifyTypeIs(Value::STRING, err))
+ return false;
+ *out = current_dir.ResolveRelativeFile(v.string_value());
+ if (out->is_system_absolute()) {
+ *err = Err(v, "System-absolute file path.",
+ "You can't list a system-absolute file path here. Please include "
+ "only files in\nthe source tree. Maybe you meant to begin with two "
+ "slashes to indicate an\nabsolute path in the source tree?");
+ return false;
+ }
+ return true;
+ }
+ const SourceDir& current_dir;
+};
+
+struct RelativeDirConverter {
+ RelativeDirConverter(const SourceDir& current_dir_in)
+ : current_dir(current_dir_in) {}
+ bool operator()(const Value& v, SourceDir* out, Err* err) const {
+ if (!v.VerifyTypeIs(Value::STRING, err))
+ return false;
+ *out = current_dir.ResolveRelativeDir(v.string_value());
+ return true;
+ }
+ const SourceDir& current_dir;
+};
+
+struct LabelResolver {
+ LabelResolver(const SourceDir& current_dir_in,
+ const Label& current_toolchain_in)
+ : current_dir(current_dir_in),
+ current_toolchain(current_toolchain_in) {}
+ bool operator()(const Value& v, Label* out, Err* err) const {
+ if (!v.VerifyTypeIs(Value::STRING, err))
+ return false;
+ *out = Label::Resolve(current_dir, current_toolchain, v, err);
+ return !err->has_error();
+ }
+ const SourceDir& current_dir;
+ const Label& current_toolchain;
+};
+
+} // namespace
+
+bool ExtractListOfStringValues(const Value& value,
+ std::vector<std::string>* dest,
+ Err* err) {
+ if (!value.VerifyTypeIs(Value::LIST, err))
+ return false;
+ const std::vector<Value>& input_list = value.list_value();
+ dest->reserve(input_list.size());
+ for (size_t i = 0; i < input_list.size(); i++) {
+ if (!input_list[i].VerifyTypeIs(Value::STRING, err))
+ return false;
+ dest->push_back(input_list[i].string_value());
+ }
+ return true;
+}
+
+bool ExtractListOfRelativeFiles(const Value& value,
+ const SourceDir& current_dir,
+ std::vector<SourceFile>* files,
+ Err* err) {
+ return ListValueExtractor(value, files, err,
+ RelativeFileConverter(current_dir));
+}
+
+bool ExtractListOfRelativeDirs(const Value& value,
+ const SourceDir& current_dir,
+ std::vector<SourceDir>* dest,
+ Err* err) {
+ return ListValueExtractor(value, dest, err,
+ RelativeDirConverter(current_dir));
+}
+
+bool ExtractListOfLabels(const Value& value,
+ const SourceDir& current_dir,
+ const Label& current_toolchain,
+ std::vector<Label>* dest,
+ Err* err) {
+ return ListValueExtractor(value, dest, err,
+ LabelResolver(current_dir, current_toolchain));
+}
diff --git a/chromium/tools/gn/value_extractors.h b/chromium/tools/gn/value_extractors.h
new file mode 100644
index 00000000000..556f44fd2ee
--- /dev/null
+++ b/chromium/tools/gn/value_extractors.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_VALUE_EXTRACTORS_H_
+#define TOOLS_GN_VALUE_EXTRACTORS_H_
+
+#include <string>
+#include <vector>
+
+#include "tools/gn/value.h"
+
+class Err;
+class Label;
+class SourceDir;
+class SourceFile;
+
+// Sets the error and returns false on failure.
+template<typename T, class Converter>
+bool ListValueExtractor(const Value& value, std::vector<T>* dest,
+ Err* err,
+ const Converter& converter) {
+ if (!value.VerifyTypeIs(Value::LIST, err))
+ return false;
+ const std::vector<Value>& input_list = value.list_value();
+ dest->resize(input_list.size());
+ for (size_t i = 0; i < input_list.size(); i++) {
+ if (!converter(input_list[i], &(*dest)[i], err))
+ return false;
+ }
+ return true;
+}
+
+// On failure, returns false and sets the error.
+bool ExtractListOfStringValues(const Value& value,
+ std::vector<std::string>* dest,
+ Err* err);
+
+// Looks for a list of source files relative to a given current dir.
+bool ExtractListOfRelativeFiles(const Value& value,
+ const SourceDir& current_dir,
+ std::vector<SourceFile>* files,
+ Err* err);
+
+// Looks for a list of source directories relative to a given current dir.
+bool ExtractListOfRelativeDirs(const Value& value,
+ const SourceDir& current_dir,
+ std::vector<SourceDir>* dest,
+ Err* err);
+
+bool ExtractListOfLabels(const Value& value,
+ const SourceDir& current_dir,
+ const Label& current_toolchain,
+ std::vector<Label>* dest,
+ Err* err);
+
+#endif // TOOLS_GN_VALUE_EXTRACTORS_H_
diff --git a/chromium/tools/gn/variables.cc b/chromium/tools/gn/variables.cc
new file mode 100644
index 00000000000..e3e0b6d3b13
--- /dev/null
+++ b/chromium/tools/gn/variables.cc
@@ -0,0 +1,364 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/variables.h"
+
+namespace variables {
+
+// Built-in variables ----------------------------------------------------------
+
+const char kCurrentToolchain[] = "current_toolchain";
+const char kCurrentToolchain_HelpShort[] =
+ "current_toolchain: [string] Label of the current toolchain.";
+const char kCurrentToolchain_Help[] =
+ "current_toolchain: Label of the current toolchain.\n"
+ "\n"
+ " A fully-qualified label representing the current toolchain. You can\n"
+ " use this to make toolchain-related decisions in the build. See also\n"
+ " \"default_toolchain\".\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ " if (current_toolchain == \"//build:64_bit_toolchain\") {\n"
+ " executable(\"output_thats_64_bit_only\") {\n"
+ " ...\n";
+
+const char kDefaultToolchain[] = "default_toolchain";
+const char kDefaultToolchain_HelpShort[] =
+ "default_toolchain: [string] Label of the default toolchain.";
+const char kDefaultToolchain_Help[] =
+ "default_toolchain: [string] Label of the default toolchain.\n"
+ "\n"
+ " A fully-qualified label representing the default toolchain, which may\n"
+ " not necessarily be the current one (see \"current_toolchain\").\n";
+
+const char kPythonPath[] = "python_path";
+const char kPythonPath_HelpShort[] =
+ "python_path: [string] Absolute path of Python.";
+const char kPythonPath_Help[] =
+ "python_path: Absolute path of Python.\n"
+ "\n"
+ " Normally used in toolchain definitions if running some command\n"
+ " requires Python. You will normally not need this when invoking scripts\n"
+ " since GN automatically finds it for you.\n";
+
+const char kRelativeBuildToSourceRootDir[] =
+ "relative_build_to_source_root_dir";
+const char kRelativeBuildToSourceRootDir_HelpShort[] =
+ "relative_build_to_source_root_dir: [string] Relative location of root";
+const char kRelativeBuildToSourceRootDir_Help[] =
+ "relative_build_to_source_root_dir: Relative location of root.\n"
+ "\n"
+ " A relative path from the build directory to the root of the source\n"
+ " tree, with no terminating slash. The build directory will be the\n"
+ " directory when executing normal build commands (except for scripts).\n"
+ "\n"
+ " If the checkout is in \"/foo/src/\" and the build directory is in\n"
+ " \"/foo/src/out/Debug/\" then the relative build to source root dir\n"
+ " will be \"../..\".\n"
+ "\n"
+ "Example:\n"
+ " This is typically used to invoke tools checked out in the tree:\n"
+ "\n"
+ " tool(\"link\") {\n"
+ " command = \"$relative_build_to_source_root_dir/third_party/gold/ld\n"
+ " }\n";
+
+const char kRelativeRootGenDir[] = "relative_root_gen_dir";
+const char kRelativeRootGenDir_HelpShort[] =
+ "relative_root_gen_dir: [string] Relative root dir for generated files.";
+const char kRelativeRootGenDir_Help[] =
+ "relative_root_gen_dir: Relative root for generated files.\n"
+ "\n"
+ " Relative path from the directory of the current build file to the\n"
+ " root of the generated file directory hierarchy for the current\n"
+ " toolchain.\n"
+ "\n"
+ " Generally scripts should use \"relative_target_output_dir\" instead.\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ " If your current build file is in \"//tools\", you might write\n"
+ " args = [ \"$relative_root_gen_dir/output.txt\" ]\n";
+
+const char kRelativeRootOutputDir[] = "relative_root_output_dir";
+const char kRelativeRootOutputDir_HelpShort[] =
+ "relative_root_output_dir: [string] Relative dir for output files.";
+const char kRelativeRootOutputDir_Help[] =
+ "relative_root_output_dir: Relative dir for output files.\n"
+ "\n"
+ " Relative path from the directory of the current build file to the\n"
+ " current toolchain's root build output directory.\n"
+ "\n"
+ " Generally scripts should use \"relative_target_output_dir\" instead.\n";
+
+const char kRelativeTargetGenDir[] = "relative_target_gen_dir";
+const char kRelativeTargetGenDir_HelpShort[] =
+ "relative_target_gen_dir: [string] Relative dir for generated files.";
+const char kRelativeTargetGenDir_Help[] =
+ "relative_target_gen_dir: Relative dir for generated files.\n"
+ "\n"
+ " Relative path from the directory of the current build file to the\n"
+ " current target's generated file directory.\n"
+ "\n"
+ " Normally used when invoking scripts (the current directory of which is\n"
+ " that of the invoking buildfile) that need to write files.\n"
+ "\n"
+ " Scripts generating final rather than intermetiate files should use the\n"
+ " \"relative_target_output_dir\" instead.\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ " If your current build file is in \"//tools\", you might write\n"
+ " args = [ \"$relative_root_gen_dir/output.txt\" ]\n";
+
+const char kRelativeTargetOutputDir[] = "relative_target_output_dir";
+const char kRelativeTargetOutputDir_HelpShort[] =
+ "relative_target_output_dir: [string] Relative dir for build results.";
+const char kRelativeTargetOutputDir_Help[] =
+ "relative_target_output_dir: Relative dir for build results."
+ "\n"
+ " Relative path from the directory of the current build file to the\n"
+ " current target's generated file directory.\n"
+ "\n"
+ " Normally used when invoking scripts (the current directory of which is\n"
+ " that of the invoking buildfile) that need to write files.\n"
+ "\n"
+ " Scripts generating intermediate files rather than final output files\n"
+ " should use the \"relative_target_output_dir\" instead.\n"
+ "\n"
+ "Example:\n"
+ "\n"
+ " If your current build file is in \"//tools\", you might write\n"
+ " args = [ \"$relative_target_output_dir/final.lib\" ]\n";
+
+// Target variables ------------------------------------------------------------
+
+const char kAllDependentConfigs[] = "all_dependent_configs";
+const char kAllDependentConfigs_HelpShort[] =
+ "all_dependent_configs: [label list] Configs to be forced on dependents.";
+const char kAllDependentConfigs_Help[] =
+ "all_dependent_configs: Configs to be forced on dependents.\n"
+ "\n"
+ " A list of config labels.\n"
+ "\n"
+ " All targets depending on this one, and recursively, all targets\n"
+ " depending on those, will have the configs listed in this variable\n"
+ " added to them.\n"
+ "\n"
+ " This addition happens in a second phase once a target and all of its\n"
+ " dependencies have been resolved. Therefore, a target will not see\n"
+ " these force-added configs in their \"configs\" variable while the\n"
+ " script is running, and then can not be removed. As a result, this\n"
+ " capability should generally only be used to add defines and include\n"
+ " directories necessary to compile a target's headers.\n"
+ "\n"
+ " See also \"direct_dependent_configs\".\n";
+
+const char kCflags[] = "cflags";
+const char kCflags_HelpShort[] =
+ "cflags: [string list] Flags passed to all C compiler variants.";
+// Avoid writing long help for each variant.
+#define COMMON_FLAGS_HELP \
+ "\n"\
+ " Flags are never quoted. If your flag includes a string that must be\n"\
+ " quoted, you must do it yourself. This also means that you can\n"\
+ " specify more than one flag in a string if necessary (\"--foo --bar\")\n"\
+ " and have them be seen as separate by the tool.\n"
+const char kCommonCflagsHelp[] =
+ "cflags*: Flags passed to the C compiler.\n"
+ "\n"
+ " A list of strings.\n"
+ "\n"
+ " \"cflags\" are passed to all invocations of the C, C++, Objective C,\n"
+ " and Objective C++ compilers.\n"
+ "\n"
+ " To target one of these variants individually, use \"cflags_c\",\n"
+ " \"cflags_cc\", \"cflags_objc\", and \"cflags_objcc\", respectively.\n"
+ " These variant-specific versions will be appended to the \"cflags\".\n"
+ COMMON_FLAGS_HELP;
+const char* kCflags_Help = kCommonCflagsHelp;
+
+const char kCflagsC[] = "cflags_c";
+const char kCflagsC_HelpShort[] =
+ "cflags_c: [string list] Flags passed to the C compiler.";
+const char* kCflagsC_Help = kCommonCflagsHelp;
+
+const char kCflagsCC[] = "cflags_cc";
+const char kCflagsCC_HelpShort[] =
+ "cflags_cc: [string list] Flags passed to the C++ compiler.";
+const char* kCflagsCC_Help = kCommonCflagsHelp;
+
+const char kCflagsObjC[] = "cflags_objc";
+const char kCflagsObjC_HelpShort[] =
+ "cflags_objc: [string list] Flags passed to the Objective C compiler.";
+const char* kCflagsObjC_Help = kCommonCflagsHelp;
+
+const char kCflagsObjCC[] = "cflags_objcc";
+const char kCflagsObjCC_HelpShort[] =
+ "cflags_objcc: [string list] Flags passed to the Objective C++ compiler.";
+const char* kCflagsObjCC_Help = kCommonCflagsHelp;
+
+const char kConfigs[] = "configs";
+const char kConfigs_HelpShort[] =
+ "configs: [label list] Configs applying to this target.";
+const char kConfigs_Help[] =
+ "configs: Configs applying to this target.\n"
+ "\n"
+ " A list of config labels.\n"
+ "\n"
+ " The includes, defines, etc. in each config are appended in the order\n"
+ " they appear to the compile command for each file in the target. They\n"
+ " will appear after the includes, defines, etc. that the target sets\n"
+ " directly.\n"
+ "\n"
+ " The build configuration script will generally set up the default\n"
+ " configs applying to a given target type (see \"set_defaults\").\n"
+ " When a target is being defined, it can add to or remove from this\n"
+ " list.\n"
+ "\n"
+ "Example:\n"
+ " static_library(\"foo\") {\n"
+ " configs -= \"//build:no_rtti\" # Don't use the default RTTI config.\n"
+ " configs += \":mysettings\" # Add some of our own settings.\n"
+ " }\n";
+
+const char kDatadeps[] = "datadeps";
+const char kDatadeps_HelpShort[] =
+ "datadeps: [label list] Non-linked dependencies.";
+const char kDatadeps_Help[] =
+ "datadeps: Non-linked dependencies.\n"
+ "\n"
+ " A list of target labels.\n"
+ "\n"
+ " Specifies dependencies of a target that are not actually linked into\n"
+ " the current target. Such dependencies will built and will be available\n"
+ " at runtime.\n"
+ "\n"
+ " This is normally used for things like plugins or helper programs that\n"
+ " a target needs at runtime.\n"
+ "\n"
+ " See also \"deps\".\n";
+
+const char kDefines[] = "defines";
+const char kDefines_HelpShort[] =
+ "defines: [string list] C preprocessor defines.";
+const char kDefines_Help[] =
+ "defines: C preprocessor defines.\n"
+ "\n"
+ " A list of strings\n"
+ "\n"
+ " These strings will be passed to the C/C++ compiler as #defines. The\n"
+ " strings may or may not include an \"=\" to assign a value.\n"
+ "\n"
+ "Example:\n"
+ " defines = [ \"AWESOME_FEATURE\", \"LOG_LEVEL=3\" ]\n";
+
+const char kDeps[] = "deps";
+const char kDeps_HelpShort[] =
+ "deps: [label list] Linked dependencies.";
+const char kDeps_Help[] =
+ "deps: Linked dependencies.\n"
+ "\n"
+ " A list of target labels.\n"
+ "\n"
+ " Specifies dependencies of a target. Shared and dynamic libraries will\n"
+ " be linked into the current target. Other target types that can't be\n"
+ " linked (like custom scripts and groups) listed in \"deps\" will be\n"
+ " treated as \"datadeps\". Likewise, if the current target isn't\n"
+ " linkable, then all deps will be treated as \"datadeps\".\n"
+ "\n"
+ " See also \"datadeps\".\n";
+
+const char kDirectDependentConfigs[] = "direct_dependent_configs";
+const char kDirectDependentConfigs_HelpShort[] =
+ "direct_dependent_configs: [label list] Configs to be forced on "
+ "dependents.";
+const char kDirectDependentConfigs_Help[] =
+ "direct_dependent_configs: Configs to be forced on dependents.\n"
+ "\n"
+ " A list of config labels.\n"
+ "\n"
+ " Targets directly referencing this one will have the configs listed in\n"
+ " this variable added to them.\n"
+ "\n"
+ " This addition happens in a second phase once a target and all of its\n"
+ " dependencies have been resolved. Therefore, a target will not see\n"
+ " these force-added configs in their \"configs\" variable while the\n"
+ " script is running, and then can not be removed. As a result, this\n"
+ " capability should generally only be used to add defines and include\n"
+ " directories necessary to compile a target's headers.\n"
+ "\n"
+ " See also \"all_dependent_configs\".\n";
+
+const char kLdflags[] = "ldflags";
+const char kLdflags_HelpShort[] =
+ "ldflags: [string list] Flags passed to the linker.";
+const char kLdflags_Help[] =
+ "ldflags: Flags passed to the linker.\n"
+ "\n"
+ " A list of strings.\n"
+ "\n"
+ " These flags are passed on the command-line to the linker.\n"
+ COMMON_FLAGS_HELP;
+
+const char kSources[] = "sources";
+const char kSources_HelpShort[] =
+ "sources: [file list] Source files for a target.";
+const char kSources_Help[] =
+ "sources: Source files for a target\n"
+ "\n"
+ " A list of files relative to the current buildfile.\n";
+
+// -----------------------------------------------------------------------------
+
+VariableInfo::VariableInfo()
+ : help_short(NULL),
+ help(NULL) {
+}
+
+VariableInfo::VariableInfo(const char* in_help_short, const char* in_help)
+ : help_short(in_help_short),
+ help(in_help) {
+}
+
+#define INSERT_VARIABLE(var) \
+ info_map[k##var] = VariableInfo(k##var##_HelpShort, k##var##_Help);
+
+const VariableInfoMap& GetBuiltinVariables() {
+ static VariableInfoMap info_map;
+ if (info_map.empty()) {
+ INSERT_VARIABLE(CurrentToolchain)
+ INSERT_VARIABLE(DefaultToolchain)
+ INSERT_VARIABLE(PythonPath)
+ INSERT_VARIABLE(RelativeRootGenDir)
+ INSERT_VARIABLE(RelativeRootOutputDir)
+ INSERT_VARIABLE(RelativeTargetGenDir)
+ INSERT_VARIABLE(RelativeTargetOutputDir)
+ }
+ return info_map;
+}
+
+const VariableInfoMap& GetTargetVariables() {
+ static VariableInfoMap info_map;
+ if (info_map.empty()) {
+ INSERT_VARIABLE(AllDependentConfigs)
+ INSERT_VARIABLE(Cflags)
+ INSERT_VARIABLE(CflagsC)
+ INSERT_VARIABLE(CflagsCC)
+ INSERT_VARIABLE(CflagsObjC)
+ INSERT_VARIABLE(CflagsObjCC)
+ INSERT_VARIABLE(Configs)
+ INSERT_VARIABLE(Datadeps)
+ INSERT_VARIABLE(Deps)
+ INSERT_VARIABLE(DirectDependentConfigs)
+ INSERT_VARIABLE(Ldflags)
+ INSERT_VARIABLE(Sources)
+ }
+ return info_map;
+}
+
+#undef INSERT_VARIABLE
+
+} // namespace variables
diff --git a/chromium/tools/gn/variables.h b/chromium/tools/gn/variables.h
new file mode 100644
index 00000000000..4751c3e1d4c
--- /dev/null
+++ b/chromium/tools/gn/variables.h
@@ -0,0 +1,126 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_VARIABLES_H_
+#define TOOLS_GN_VARIABLES_H_
+
+#include <map>
+
+#include "base/strings/string_piece.h"
+
+namespace variables {
+
+// Builtin vars ----------------------------------------------------------------
+
+extern const char kCurrentToolchain[];
+extern const char kCurrentToolchain_HelpShort[];
+extern const char kCurrentToolchain_Help[];
+
+extern const char kDefaultToolchain[];
+extern const char kDefaultToolchain_HelpShort[];
+extern const char kDefaultToolchain_Help[];
+
+extern const char kPythonPath[];
+extern const char kPythonPath_HelpShort[];
+extern const char kPythonPath_Help[];
+
+extern const char kRelativeBuildToSourceRootDir[];
+extern const char kRelativeBuildToSourceRootDir_HelpShort[];
+extern const char kRelativeBuildToSourceRootDir_Help[];
+
+extern const char kRelativeRootGenDir[];
+extern const char kRelativeRootGenDir_HelpShort[];
+extern const char kRelativeRootGenDir_Help[];
+
+extern const char kRelativeRootOutputDir[];
+extern const char kRelativeRootOutputDir_HelpShort[];
+extern const char kRelativeRootOutputDir_Help[];
+
+extern const char kRelativeTargetGenDir[];
+extern const char kRelativeTargetGenDir_HelpShort[];
+extern const char kRelativeTargetGenDir_Help[];
+
+extern const char kRelativeTargetOutputDir[];
+extern const char kRelativeTargetOutputDir_HelpShort[];
+extern const char kRelativeTargetOutputDir_Help[];
+
+// Target vars -----------------------------------------------------------------
+
+extern const char kAllDependentConfigs[];
+extern const char kAllDependentConfigs_HelpShort[];
+extern const char kAllDependentConfigs_Help[];
+
+extern const char kCflags[];
+extern const char kCflags_HelpShort[];
+extern const char* kCflags_Help;
+
+extern const char kCflagsC[];
+extern const char kCflagsC_HelpShort[];
+extern const char* kCflagsC_Help;
+
+extern const char kCflagsCC[];
+extern const char kCflagsCC_HelpShort[];
+extern const char* kCflagsCC_Help;
+
+extern const char kCflagsObjC[];
+extern const char kCflagsObjC_HelpShort[];
+extern const char* kCflagsObjC_Help;
+
+extern const char kCflagsObjCC[];
+extern const char kCflagsObjCC_HelpShort[];
+extern const char* kCflagsObjCC_Help;
+
+extern const char kConfigs[];
+extern const char kConfigs_HelpShort[];
+extern const char kConfigs_Help[];
+
+extern const char kDatadeps[];
+extern const char kDatadeps_HelpShort[];
+extern const char kDatadeps_Help[];
+
+extern const char kDefines[];
+extern const char kDefines_HelpShort[];
+extern const char kDefines_Help[];
+
+extern const char kDeps[];
+extern const char kDeps_HelpShort[];
+extern const char kDeps_Help[];
+
+extern const char kDirectDependentConfigs[];
+extern const char kDirectDependentConfigs_HelpShort[];
+extern const char kDirectDependentConfigs_Help[];
+
+extern const char kLdflags[];
+extern const char kLdflags_HelpShort[];
+extern const char kLdflags_Help[];
+
+extern const char kSources[];
+extern const char kSources_HelpShort[];
+extern const char kSources_Help[];
+
+
+// -----------------------------------------------------------------------------
+
+struct VariableInfo {
+ VariableInfo();
+ VariableInfo(const char* in_help_short,
+ const char* in_help);
+
+ const char* help_short;
+ const char* help;
+};
+
+typedef std::map<base::StringPiece, VariableInfo> VariableInfoMap;
+
+// Returns the built-in readonly variables.
+// Note: this is used only for help so this getter is not threadsafe.
+const VariableInfoMap& GetBuiltinVariables();
+
+// Returns the variables used by target generators.
+// Note: this is used only for help so this getter is not threadsafe.
+const VariableInfoMap& GetTargetVariables();
+
+} // namespace variables
+
+#endif // TOOLS_GN_VARIABLES_H_
diff --git a/chromium/tools/grit/LICENSE b/chromium/tools/grit/LICENSE
new file mode 100644
index 00000000000..2aa394490ca
--- /dev/null
+++ b/chromium/tools/grit/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2012 The Chromium Authors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chromium/tools/grit/PRESUBMIT.py b/chromium/tools/grit/PRESUBMIT.py
new file mode 100644
index 00000000000..700168999ca
--- /dev/null
+++ b/chromium/tools/grit/PRESUBMIT.py
@@ -0,0 +1,22 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""grit unittests presubmit script.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+
+def RunUnittests(input_api, output_api):
+ return input_api.canned_checks.RunPythonUnitTests(input_api, output_api,
+ ['grit.test_suite_all'])
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return RunUnittests(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return RunUnittests(input_api, output_api)
diff --git a/chromium/tools/grit/README b/chromium/tools/grit/README
new file mode 100644
index 00000000000..8fcdafeb16b
--- /dev/null
+++ b/chromium/tools/grit/README
@@ -0,0 +1,2 @@
+GRIT (Google Resource and Internationalization Tool) is a tool for Windows
+projects to manage resources and simplify the localization workflow.
diff --git a/chromium/tools/grit/codereview.settings b/chromium/tools/grit/codereview.settings
new file mode 100644
index 00000000000..4535052eac0
--- /dev/null
+++ b/chromium/tools/grit/codereview.settings
@@ -0,0 +1,6 @@
+# This file is used by gcl to get repository specific information.
+CODE_REVIEW_SERVER: codereview.chromium.org
+CC_LIST: grit-developer@googlegroups.com
+VIEW_VC: http://code.google.com/p/grit-i18n/source/detail?r=
+TRY_ON_UPLOAD: False
+
diff --git a/chromium/tools/grit/grit.py b/chromium/tools/grit/grit.py
new file mode 100755
index 00000000000..b17ceb9280b
--- /dev/null
+++ b/chromium/tools/grit/grit.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Bootstrapping for GRIT.
+'''
+
+import sys
+
+import grit.grit_runner
+
+
+if __name__ == '__main__':
+ grit.grit_runner.Main(sys.argv[1:])
+
diff --git a/chromium/tools/grit/grit/__init__.py b/chromium/tools/grit/grit/__init__.py
new file mode 100644
index 00000000000..57e67091c19
--- /dev/null
+++ b/chromium/tools/grit/grit/__init__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Package 'grit'
+'''
+
+pass
+
diff --git a/chromium/tools/grit/grit/clique.py b/chromium/tools/grit/grit/clique.py
new file mode 100644
index 00000000000..3a979890b8e
--- /dev/null
+++ b/chromium/tools/grit/grit/clique.py
@@ -0,0 +1,483 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Collections of messages and their translations, called cliques. Also
+collections of cliques (uber-cliques).
+'''
+
+import re
+import types
+
+from grit import constants
+from grit import exception
+from grit import lazy_re
+from grit import pseudo
+from grit import pseudo_rtl
+from grit import tclib
+
+
+class UberClique(object):
+ '''A factory (NOT a singleton factory) for making cliques. It has several
+ methods for working with the cliques created using the factory.
+ '''
+
+ def __init__(self):
+ # A map from message ID to list of cliques whose source messages have
+ # that ID. This will contain all cliques created using this factory.
+ # Different messages can have the same ID because they have the
+ # same translateable portion and placeholder names, but occur in different
+ # places in the resource tree.
+ #
+ # Each list of cliques is kept sorted by description, to achieve
+ # stable results from the BestClique method, see below.
+ self.cliques_ = {}
+
+ # A map of clique IDs to list of languages to indicate translations where we
+ # fell back to English.
+ self.fallback_translations_ = {}
+
+ # A map of clique IDs to list of languages to indicate missing translations.
+ self.missing_translations_ = {}
+
+ def _AddMissingTranslation(self, lang, clique, is_error):
+ tl = self.fallback_translations_
+ if is_error:
+ tl = self.missing_translations_
+ id = clique.GetId()
+ if id not in tl:
+ tl[id] = {}
+ if lang not in tl[id]:
+ tl[id][lang] = 1
+
+ def HasMissingTranslations(self):
+ return len(self.missing_translations_) > 0
+
+ def MissingTranslationsReport(self):
+ '''Returns a string suitable for printing to report missing
+ and fallback translations to the user.
+ '''
+ def ReportTranslation(clique, langs):
+ text = clique.GetMessage().GetPresentableContent()
+ # The text 'error' (usually 'Error:' but we are conservative)
+ # can trigger some build environments (Visual Studio, we're
+ # looking at you) to consider invocation of grit to have failed,
+ # so we make sure never to output that word.
+ extract = re.sub('(?i)error', 'REDACTED', text[0:40])[0:40]
+ ellipsis = ''
+ if len(text) > 40:
+ ellipsis = '...'
+ langs_extract = langs[0:6]
+ describe_langs = ','.join(langs_extract)
+ if len(langs) > 6:
+ describe_langs += " and %d more" % (len(langs) - 6)
+ return " %s \"%s%s\" %s" % (clique.GetId(), extract, ellipsis,
+ describe_langs)
+ lines = []
+ if len(self.fallback_translations_):
+ lines.append(
+ "WARNING: Fell back to English for the following translations:")
+ for (id, langs) in self.fallback_translations_.items():
+ lines.append(ReportTranslation(self.cliques_[id][0], langs.keys()))
+ if len(self.missing_translations_):
+ lines.append("ERROR: The following translations are MISSING:")
+ for (id, langs) in self.missing_translations_.items():
+ lines.append(ReportTranslation(self.cliques_[id][0], langs.keys()))
+ return '\n'.join(lines)
+
+ def MakeClique(self, message, translateable=True):
+ '''Create a new clique initialized with a message.
+
+ Args:
+ message: tclib.Message()
+ translateable: True | False
+ '''
+ clique = MessageClique(self, message, translateable)
+
+ # Enable others to find this clique by its message ID
+ if message.GetId() in self.cliques_:
+ presentable_text = clique.GetMessage().GetPresentableContent()
+ if not message.HasAssignedId():
+ for c in self.cliques_[message.GetId()]:
+ assert c.GetMessage().GetPresentableContent() == presentable_text
+ self.cliques_[message.GetId()].append(clique)
+ # We need to keep each list of cliques sorted by description, to
+ # achieve stable results from the BestClique method, see below.
+ self.cliques_[message.GetId()].sort(
+ key=lambda c:c.GetMessage().GetDescription())
+ else:
+ self.cliques_[message.GetId()] = [clique]
+
+ return clique
+
+ def FindCliqueAndAddTranslation(self, translation, language):
+ '''Adds the specified translation to the clique with the source message
+ it is a translation of.
+
+ Args:
+ translation: tclib.Translation()
+ language: 'en' | 'fr' ...
+
+ Return:
+ True if the source message was found, otherwise false.
+ '''
+ if translation.GetId() in self.cliques_:
+ for clique in self.cliques_[translation.GetId()]:
+ clique.AddTranslation(translation, language)
+ return True
+ else:
+ return False
+
+ def BestClique(self, id):
+ '''Returns the "best" clique from a list of cliques. All the cliques
+ must have the same ID. The "best" clique is chosen in the following
+ order of preference:
+ - The first clique that has a non-ID-based description.
+ - If no such clique found, the first clique with an ID-based description.
+ - Otherwise the first clique.
+
+ This method is stable in terms of always returning a clique with
+ an identical description (on different runs of GRIT on the same
+ data) because self.cliques_ is sorted by description.
+ '''
+ clique_list = self.cliques_[id]
+ clique_with_id = None
+ clique_default = None
+ for clique in clique_list:
+ if not clique_default:
+ clique_default = clique
+
+ description = clique.GetMessage().GetDescription()
+ if description and len(description) > 0:
+ if not description.startswith('ID:'):
+ # this is the preferred case so we exit right away
+ return clique
+ elif not clique_with_id:
+ clique_with_id = clique
+ if clique_with_id:
+ return clique_with_id
+ else:
+ return clique_default
+
+ def BestCliquePerId(self):
+ '''Iterates over the list of all cliques and returns the best clique for
+ each ID. This will be the first clique with a source message that has a
+ non-empty description, or an arbitrary clique if none of them has a
+ description.
+ '''
+ for id in self.cliques_:
+ yield self.BestClique(id)
+
+ def BestCliqueByOriginalText(self, text, meaning):
+ '''Finds the "best" (as in BestClique()) clique that has original text
+ 'text' and meaning 'meaning'. Returns None if there is no such clique.
+ '''
+ # If needed, this can be optimized by maintaining a map of
+ # fingerprints of original text+meaning to cliques.
+ for c in self.BestCliquePerId():
+ msg = c.GetMessage()
+ if msg.GetRealContent() == text and msg.GetMeaning() == meaning:
+ return msg
+ return None
+
+ def AllMessageIds(self):
+ '''Returns a list of all defined message IDs.
+ '''
+ return self.cliques_.keys()
+
+ def AllCliques(self):
+ '''Iterates over all cliques. Note that this can return multiple cliques
+ with the same ID.
+ '''
+ for cliques in self.cliques_.values():
+ for c in cliques:
+ yield c
+
+ def GenerateXtbParserCallback(self, lang, debug=False):
+ '''Creates a callback function as required by grit.xtb_reader.Parse().
+ This callback will create Translation objects for each message from
+ the XTB that exists in this uberclique, and add them as translations for
+ the relevant cliques. The callback will add translations to the language
+ specified by 'lang'
+
+ Args:
+ lang: 'fr'
+ debug: True | False
+ '''
+ def Callback(id, structure):
+ if id not in self.cliques_:
+ if debug: print "Ignoring translation #%s" % id
+ return
+
+ if debug: print "Adding translation #%s" % id
+
+ # We fetch placeholder information from the original message (the XTB file
+ # only contains placeholder names).
+ original_msg = self.BestClique(id).GetMessage()
+
+ translation = tclib.Translation(id=id)
+ for is_ph,text in structure:
+ if not is_ph:
+ translation.AppendText(text)
+ else:
+ found_placeholder = False
+ for ph in original_msg.GetPlaceholders():
+ if ph.GetPresentation() == text:
+ translation.AppendPlaceholder(tclib.Placeholder(
+ ph.GetPresentation(), ph.GetOriginal(), ph.GetExample()))
+ found_placeholder = True
+ break
+ if not found_placeholder:
+ raise exception.MismatchingPlaceholders(
+ 'Translation for message ID %s had <ph name="%s"/>, no match\n'
+ 'in original message' % (id, text))
+ self.FindCliqueAndAddTranslation(translation, lang)
+ return Callback
+
+
+class CustomType(object):
+ '''A base class you should implement if you wish to specify a custom type
+ for a message clique (i.e. custom validation and optional modification of
+ translations).'''
+
+ def Validate(self, message):
+ '''Returns true if the message (a tclib.Message object) is valid,
+ otherwise false.
+ '''
+ raise NotImplementedError()
+
+ def ValidateAndModify(self, lang, translation):
+ '''Returns true if the translation (a tclib.Translation object) is valid,
+ otherwise false. The language is also passed in. This method may modify
+ the translation that is passed in, if it so wishes.
+ '''
+ raise NotImplementedError()
+
+ def ModifyTextPart(self, lang, text):
+ '''If you call ModifyEachTextPart, it will turn around and call this method
+ for each text part of the translation. You should return the modified
+ version of the text, or just the original text to not change anything.
+ '''
+ raise NotImplementedError()
+
+ def ModifyEachTextPart(self, lang, translation):
+ '''Call this to easily modify one or more of the textual parts of a
+ translation. It will call ModifyTextPart for each part of the
+ translation.
+ '''
+ contents = translation.GetContent()
+ for ix in range(len(contents)):
+ if (isinstance(contents[ix], types.StringTypes)):
+ contents[ix] = self.ModifyTextPart(lang, contents[ix])
+
+
+class OneOffCustomType(CustomType):
+ '''A very simple custom type that performs the validation expressed by
+ the input expression on all languages including the source language.
+ The expression can access the variables 'lang', 'msg' and 'text()' where 'lang'
+ is the language of 'msg', 'msg' is the message or translation being
+ validated and 'text()' returns the real contents of 'msg' (for shorthand).
+ '''
+ def __init__(self, expression):
+ self.expr = expression
+ def Validate(self, message):
+ return self.ValidateAndModify(MessageClique.source_language, message)
+ def ValidateAndModify(self, lang, msg):
+ def text():
+ return msg.GetRealContent()
+ return eval(self.expr, {},
+ {'lang' : lang,
+ 'text' : text,
+ 'msg' : msg,
+ })
+
+
+class MessageClique(object):
+ '''A message along with all of its translations. Also code to bring
+ translations together with their original message.'''
+
+ # change this to the language code of Messages you add to cliques_.
+ # TODO(joi) Actually change this based on the <grit> node's source language
+ source_language = 'en'
+
+ # A constant translation we use when asked for a translation into the
+ # special language constants.CONSTANT_LANGUAGE.
+ CONSTANT_TRANSLATION = tclib.Translation(text='TTTTTT')
+
+ # A pattern to match messages that are empty or whitespace only.
+ WHITESPACE_MESSAGE = lazy_re.compile(u'^\s*$')
+
+ def __init__(self, uber_clique, message, translateable=True, custom_type=None):
+ '''Create a new clique initialized with just a message.
+
+ Note that messages with a body comprised only of whitespace will implicitly
+ be marked non-translatable.
+
+ Args:
+ uber_clique: Our uber-clique (collection of cliques)
+ message: tclib.Message()
+ translateable: True | False
+ custom_type: instance of clique.CustomType interface
+ '''
+ # Our parent
+ self.uber_clique = uber_clique
+ # If not translateable, we only store the original message.
+ self.translateable = translateable
+
+ # We implicitly mark messages that have a whitespace-only body as
+ # non-translateable.
+ if MessageClique.WHITESPACE_MESSAGE.match(message.GetRealContent()):
+ self.translateable = False
+
+ # A mapping of language identifiers to tclib.BaseMessage and its
+ # subclasses (i.e. tclib.Message and tclib.Translation).
+ self.clique = { MessageClique.source_language : message }
+ # A list of the "shortcut groups" this clique is
+ # part of. Within any given shortcut group, no shortcut key (e.g. &J)
+ # must appear more than once in each language for all cliques that
+ # belong to the group.
+ self.shortcut_groups = []
+ # An instance of the CustomType interface, or None. If this is set, it will
+ # be used to validate the original message and translations thereof, and
+ # will also get a chance to modify translations of the message.
+ self.SetCustomType(custom_type)
+
+ def GetMessage(self):
+ '''Retrieves the tclib.Message that is the source for this clique.'''
+ return self.clique[MessageClique.source_language]
+
+ def GetId(self):
+ '''Retrieves the message ID of the messages in this clique.'''
+ return self.GetMessage().GetId()
+
+ def IsTranslateable(self):
+ return self.translateable
+
+ def AddToShortcutGroup(self, group):
+ self.shortcut_groups.append(group)
+
+ def SetCustomType(self, custom_type):
+ '''Makes this clique use custom_type for validating messages and
+ translations, and optionally modifying translations.
+ '''
+ self.custom_type = custom_type
+ if custom_type and not custom_type.Validate(self.GetMessage()):
+ raise exception.InvalidMessage(self.GetMessage().GetRealContent())
+
+ def MessageForLanguage(self, lang, pseudo_if_no_match=True, fallback_to_english=False):
+ '''Returns the message/translation for the specified language, providing
+ a pseudotranslation if there is no available translation and a pseudo-
+ translation is requested.
+
+ The translation of any message whatsoever in the special language
+ 'x_constant' is the message "TTTTTT".
+
+ Args:
+ lang: 'en'
+ pseudo_if_no_match: True
+ fallback_to_english: False
+
+ Return:
+ tclib.BaseMessage
+ '''
+ if not self.translateable:
+ return self.GetMessage()
+
+ if lang == constants.CONSTANT_LANGUAGE:
+ return self.CONSTANT_TRANSLATION
+
+ for msglang in self.clique.keys():
+ if lang == msglang:
+ return self.clique[msglang]
+
+ if lang == constants.FAKE_BIDI:
+ return pseudo_rtl.PseudoRTLMessage(self.GetMessage())
+
+ if fallback_to_english:
+ self.uber_clique._AddMissingTranslation(lang, self, is_error=False)
+ return self.GetMessage()
+
+ # If we're not supposed to generate pseudotranslations, we add an error
+ # report to a list of errors, then fail at a higher level, so that we
+ # get a list of all messages that are missing translations.
+ if not pseudo_if_no_match:
+ self.uber_clique._AddMissingTranslation(lang, self, is_error=True)
+
+ return pseudo.PseudoMessage(self.GetMessage())
+
+ def AllMessagesThatMatch(self, lang_re, include_pseudo = True):
+ '''Returns a map of all messages that match 'lang', including the pseudo
+ translation if requested.
+
+ Args:
+ lang_re: re.compile('fr|en')
+ include_pseudo: True
+
+ Return:
+ { 'en' : tclib.Message,
+ 'fr' : tclib.Translation,
+ pseudo.PSEUDO_LANG : tclib.Translation }
+ '''
+ if not self.translateable:
+ return [self.GetMessage()]
+
+ matches = {}
+ for msglang in self.clique:
+ if lang_re.match(msglang):
+ matches[msglang] = self.clique[msglang]
+
+ if include_pseudo:
+ matches[pseudo.PSEUDO_LANG] = pseudo.PseudoMessage(self.GetMessage())
+
+ return matches
+
+ def AddTranslation(self, translation, language):
+ '''Add a translation to this clique. The translation must have the same
+ ID as the message that is the source for this clique.
+
+ If this clique is not translateable, the function just returns.
+
+ Args:
+ translation: tclib.Translation()
+ language: 'en'
+
+ Throws:
+ grit.exception.InvalidTranslation if the translation you're trying to add
+ doesn't have the same message ID as the source message of this clique.
+ '''
+ if not self.translateable:
+ return
+ if translation.GetId() != self.GetId():
+ raise exception.InvalidTranslation(
+ 'Msg ID %s, transl ID %s' % (self.GetId(), translation.GetId()))
+
+ assert not language in self.clique
+
+ # Because two messages can differ in the original content of their
+ # placeholders yet share the same ID (because they are otherwise the
+ # same), the translation we are getting may have different original
+ # content for placeholders than our message, yet it is still the right
+ # translation for our message (because it is for the same ID). We must
+ # therefore fetch the original content of placeholders from our original
+ # English message.
+ #
+ # See grit.clique_unittest.MessageCliqueUnittest.testSemiIdenticalCliques
+ # for a concrete explanation of why this is necessary.
+
+ original = self.MessageForLanguage(self.source_language, False)
+ if len(original.GetPlaceholders()) != len(translation.GetPlaceholders()):
+ print ("ERROR: '%s' translation of message id %s does not match" %
+ (language, translation.GetId()))
+ assert False
+
+ transl_msg = tclib.Translation(id=self.GetId(),
+ text=translation.GetPresentableContent(),
+ placeholders=original.GetPlaceholders())
+
+ if self.custom_type and not self.custom_type.ValidateAndModify(language, transl_msg):
+ print "WARNING: %s translation failed validation: %s" % (
+ language, transl_msg.GetId())
+
+ self.clique[language] = transl_msg
+
diff --git a/chromium/tools/grit/grit/clique_unittest.py b/chromium/tools/grit/grit/clique_unittest.py
new file mode 100644
index 00000000000..faf54833f62
--- /dev/null
+++ b/chromium/tools/grit/grit/clique_unittest.py
@@ -0,0 +1,261 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.clique'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import re
+import StringIO
+import unittest
+
+from grit import clique
+from grit import exception
+from grit import pseudo
+from grit import tclib
+from grit import grd_reader
+from grit import util
+
+class MessageCliqueUnittest(unittest.TestCase):
+ def testClique(self):
+ factory = clique.UberClique()
+ msg = tclib.Message(text='Hello USERNAME, how are you?',
+ placeholders=[
+ tclib.Placeholder('USERNAME', '%s', 'Joi')])
+ c = factory.MakeClique(msg)
+
+ self.failUnless(c.GetMessage() == msg)
+ self.failUnless(c.GetId() == msg.GetId())
+
+ msg_fr = tclib.Translation(text='Bonjour USERNAME, comment ca va?',
+ id=msg.GetId(), placeholders=[
+ tclib.Placeholder('USERNAME', '%s', 'Joi')])
+ msg_de = tclib.Translation(text='Guten tag USERNAME, wie geht es dir?',
+ id=msg.GetId(), placeholders=[
+ tclib.Placeholder('USERNAME', '%s', 'Joi')])
+
+ c.AddTranslation(msg_fr, 'fr')
+ factory.FindCliqueAndAddTranslation(msg_de, 'de')
+
+ # sort() sorts lists in-place and does not return them
+ for lang in ('en', 'fr', 'de'):
+ self.failUnless(lang in c.clique)
+
+ self.failUnless(c.MessageForLanguage('fr').GetRealContent() ==
+ msg_fr.GetRealContent())
+
+ try:
+ c.MessageForLanguage('zh-CN', False)
+ self.fail('Should have gotten exception')
+ except:
+ pass
+
+ self.failUnless(c.MessageForLanguage('zh-CN', True) != None)
+
+ rex = re.compile('fr|de|bingo')
+ self.failUnless(len(c.AllMessagesThatMatch(rex, False)) == 2)
+ self.failUnless(c.AllMessagesThatMatch(rex, True)[pseudo.PSEUDO_LANG] != None)
+
+ def testBestClique(self):
+ factory = clique.UberClique()
+ factory.MakeClique(tclib.Message(text='Alfur', description='alfaholl'))
+ factory.MakeClique(tclib.Message(text='Alfur', description=''))
+ factory.MakeClique(tclib.Message(text='Vaettur', description=''))
+ factory.MakeClique(tclib.Message(text='Vaettur', description=''))
+ factory.MakeClique(tclib.Message(text='Troll', description=''))
+ factory.MakeClique(tclib.Message(text='Gryla', description='ID: IDS_GRYLA'))
+ factory.MakeClique(tclib.Message(text='Gryla', description='vondakerling'))
+ factory.MakeClique(tclib.Message(text='Leppaludi', description='ID: IDS_LL'))
+ factory.MakeClique(tclib.Message(text='Leppaludi', description=''))
+
+ count_best_cliques = 0
+ for c in factory.BestCliquePerId():
+ count_best_cliques += 1
+ msg = c.GetMessage()
+ text = msg.GetRealContent()
+ description = msg.GetDescription()
+ if text == 'Alfur':
+ self.failUnless(description == 'alfaholl')
+ elif text == 'Gryla':
+ self.failUnless(description == 'vondakerling')
+ elif text == 'Leppaludi':
+ self.failUnless(description == 'ID: IDS_LL')
+ self.failUnless(count_best_cliques == 5)
+
+ def testAllInUberClique(self):
+ resources = grd_reader.Parse(
+ StringIO.StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ </messages>
+ <structures>
+ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="grit/testdata/klonk.rc" />
+ <structure type="tr_html" name="ID_HTML" file="grit/testdata/simple.html" />
+ </structures>
+ </release>
+</grit>'''), util.PathFromRoot('.'))
+ resources.SetOutputLanguage('en')
+ resources.RunGatherers()
+ content_list = []
+ for clique_list in resources.UberClique().cliques_.values():
+ for clique in clique_list:
+ content_list.append(clique.GetMessage().GetRealContent())
+ self.failUnless('Hello %s, how are you doing today?' in content_list)
+ self.failUnless('Jack "Black" Daniels' in content_list)
+ self.failUnless('Hello!' in content_list)
+
+ def testCorrectExceptionIfWrongEncodingOnResourceFile(self):
+ '''This doesn't really belong in this unittest file, but what the heck.'''
+ resources = grd_reader.Parse(
+ StringIO.StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <structures>
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit/testdata/klonk.rc" />
+ </structures>
+ </release>
+</grit>'''), util.PathFromRoot('.'))
+ self.assertRaises(exception.SectionNotFound, resources.RunGatherers)
+
+ def testSemiIdenticalCliques(self):
+ messages = [
+ tclib.Message(text='Hello USERNAME',
+ placeholders=[tclib.Placeholder('USERNAME', '$1', 'Joi')]),
+ tclib.Message(text='Hello USERNAME',
+ placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi')]),
+ ]
+ self.failUnless(messages[0].GetId() == messages[1].GetId())
+
+ # Both of the above would share a translation.
+ translation = tclib.Translation(id=messages[0].GetId(),
+ text='Bonjour USERNAME',
+ placeholders=[tclib.Placeholder(
+ 'USERNAME', '$1', 'Joi')])
+
+ factory = clique.UberClique()
+ cliques = [factory.MakeClique(msg) for msg in messages]
+
+ for clq in cliques:
+ clq.AddTranslation(translation, 'fr')
+
+ self.failUnless(cliques[0].MessageForLanguage('fr').GetRealContent() ==
+ 'Bonjour $1')
+ self.failUnless(cliques[1].MessageForLanguage('fr').GetRealContent() ==
+ 'Bonjour %s')
+
+ def testMissingTranslations(self):
+ messages = [ tclib.Message(text='Hello'), tclib.Message(text='Goodbye') ]
+ factory = clique.UberClique()
+ cliques = [factory.MakeClique(msg) for msg in messages]
+
+ cliques[1].MessageForLanguage('fr', False, True)
+
+ self.failUnless(not factory.HasMissingTranslations())
+
+ cliques[0].MessageForLanguage('de', False, False)
+
+ self.failUnless(factory.HasMissingTranslations())
+
+ report = factory.MissingTranslationsReport()
+ self.failUnless(report.count('WARNING') == 1)
+ self.failUnless(report.count('8053599568341804890 "Goodbye" fr') == 1)
+ self.failUnless(report.count('ERROR') == 1)
+ self.failUnless(report.count('800120468867715734 "Hello" de') == 1)
+
+ def testCustomTypes(self):
+ factory = clique.UberClique()
+ message = tclib.Message(text='Bingo bongo')
+ c = factory.MakeClique(message)
+ try:
+ c.SetCustomType(DummyCustomType())
+ self.fail()
+ except:
+ pass # expected case - 'Bingo bongo' does not start with 'jjj'
+
+ message = tclib.Message(text='jjjBingo bongo')
+ c = factory.MakeClique(message)
+ c.SetCustomType(util.NewClassInstance(
+ 'grit.clique_unittest.DummyCustomType', clique.CustomType))
+ translation = tclib.Translation(id=message.GetId(), text='Bilingo bolongo')
+ c.AddTranslation(translation, 'fr')
+ self.failUnless(c.MessageForLanguage('fr').GetRealContent().startswith('jjj'))
+
+ def testWhitespaceMessagesAreNontranslateable(self):
+ factory = clique.UberClique()
+
+ message = tclib.Message(text=' \t')
+ c = factory.MakeClique(message, translateable=True)
+ self.failIf(c.IsTranslateable())
+
+ message = tclib.Message(text='\n \n ')
+ c = factory.MakeClique(message, translateable=True)
+ self.failIf(c.IsTranslateable())
+
+ message = tclib.Message(text='\n hello')
+ c = factory.MakeClique(message, translateable=True)
+ self.failUnless(c.IsTranslateable())
+
+ def testEachCliqueKeptSorted(self):
+ factory = clique.UberClique()
+ msg_a = tclib.Message(text='hello', description='a')
+ msg_b = tclib.Message(text='hello', description='b')
+ msg_c = tclib.Message(text='hello', description='c')
+ # Insert out of order
+ clique_b = factory.MakeClique(msg_b, translateable=True)
+ clique_a = factory.MakeClique(msg_a, translateable=True)
+ clique_c = factory.MakeClique(msg_c, translateable=True)
+ clique_list = factory.cliques_[clique_a.GetId()]
+ self.failUnless(len(clique_list) == 3)
+ self.failUnless(clique_list[0] == clique_a)
+ self.failUnless(clique_list[1] == clique_b)
+ self.failUnless(clique_list[2] == clique_c)
+
+ def testBestCliqueSortIsStable(self):
+ factory = clique.UberClique()
+ text = 'hello'
+ msg_no_description = tclib.Message(text=text)
+ msg_id_description_a = tclib.Message(text=text, description='ID: a')
+ msg_id_description_b = tclib.Message(text=text, description='ID: b')
+ msg_description_x = tclib.Message(text=text, description='x')
+ msg_description_y = tclib.Message(text=text, description='y')
+ clique_id = msg_no_description.GetId()
+
+ # Insert in an order that tests all outcomes.
+ clique_no_description = factory.MakeClique(msg_no_description,
+ translateable=True)
+ self.failUnless(factory.BestClique(clique_id) == clique_no_description)
+ clique_id_description_b = factory.MakeClique(msg_id_description_b,
+ translateable=True)
+ self.failUnless(factory.BestClique(clique_id) == clique_id_description_b)
+ clique_id_description_a = factory.MakeClique(msg_id_description_a,
+ translateable=True)
+ self.failUnless(factory.BestClique(clique_id) == clique_id_description_a)
+ clique_description_y = factory.MakeClique(msg_description_y,
+ translateable=True)
+ self.failUnless(factory.BestClique(clique_id) == clique_description_y)
+ clique_description_x = factory.MakeClique(msg_description_x,
+ translateable=True)
+ self.failUnless(factory.BestClique(clique_id) == clique_description_x)
+
+
+class DummyCustomType(clique.CustomType):
+ def Validate(self, message):
+ return message.GetRealContent().startswith('jjj')
+ def ValidateAndModify(self, lang, translation):
+ is_ok = self.Validate(translation)
+ self.ModifyEachTextPart(lang, translation)
+ def ModifyTextPart(self, lang, text):
+ return 'jjj%s' % text
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/constants.py b/chromium/tools/grit/grit/constants.py
new file mode 100644
index 00000000000..77faf2a2c1f
--- /dev/null
+++ b/chromium/tools/grit/grit/constants.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Constant definitions for GRIT.
+'''
+
+
+# This is the Icelandic noun meaning "grit" and is used to check that our
+# input files are in the correct encoding. The middle character gets encoded
+# as two bytes in UTF-8, so this is sufficient to detect incorrect encoding.
+ENCODING_CHECK = u'm\u00f6l'
+
+# A special language, translations into which are always "TTTTTT".
+CONSTANT_LANGUAGE = 'x_constant'
+
+FAKE_BIDI = 'fake-bidi'
diff --git a/chromium/tools/grit/grit/exception.py b/chromium/tools/grit/grit/exception.py
new file mode 100644
index 00000000000..a9584a0e050
--- /dev/null
+++ b/chromium/tools/grit/grit/exception.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Exception types for GRIT.
+'''
+
+class Base(Exception):
+ '''A base exception that uses the class's docstring in addition to any
+ user-provided message as the body of the Base.
+ '''
+ def __init__(self, msg=''):
+ if len(msg):
+ if self.__doc__:
+ msg = self.__doc__ + ': ' + msg
+ else:
+ msg = self.__doc__
+ super(Base, self).__init__(msg)
+
+
+class Parsing(Base):
+ '''An error occurred parsing a GRD or XTB file.'''
+ pass
+
+
+class UnknownElement(Parsing):
+ '''An unknown node type was encountered.'''
+ pass
+
+
+class MissingElement(Parsing):
+ '''An expected element was missing.'''
+ pass
+
+
+class UnexpectedChild(Parsing):
+ '''An unexpected child element was encountered (on a leaf node).'''
+ pass
+
+
+class UnexpectedAttribute(Parsing):
+ '''The attribute was not expected'''
+ pass
+
+
+class UnexpectedContent(Parsing):
+ '''This element should not have content'''
+ pass
+
+
+class MissingMandatoryAttribute(Parsing):
+ '''This element is missing a mandatory attribute'''
+ pass
+
+
+class MutuallyExclusiveMandatoryAttribute(Parsing):
+ '''This element has 2 mutually exclusive mandatory attributes'''
+ pass
+
+
+class DuplicateKey(Parsing):
+ '''A duplicate key attribute was found.'''
+ pass
+
+
+class TooManyExamples(Parsing):
+ '''Only one <ex> element is allowed for each <ph> element.'''
+ pass
+
+
+class GotPathExpectedFilenameOnly(Parsing):
+ '''The 'filename' attribute of <output> and the 'file' attribute of <part>
+ must be bare filenames, not paths.
+ '''
+ pass
+
+
+class FileNotFound(Parsing):
+ '''The resource file was not found.
+ '''
+ pass
+
+
+class InvalidMessage(Base):
+ '''The specified message failed validation.'''
+ pass
+
+
+class InvalidTranslation(Base):
+ '''Attempt to add an invalid translation to a clique.'''
+ pass
+
+
+class NoSuchTranslation(Base):
+ '''Requested translation not available'''
+ pass
+
+
+class NotReady(Base):
+ '''Attempt to use an object before it is ready, or attempt to translate
+ an empty document.'''
+ pass
+
+
+class TooManyPlaceholders(Base):
+ '''Too many placeholders for elements of the same type.'''
+ pass
+
+
+class MismatchingPlaceholders(Base):
+ '''Placeholders do not match.'''
+ pass
+
+
+class InvalidPlaceholderName(Base):
+ '''Placeholder name can only contain A-Z, a-z, 0-9 and underscore.'''
+ pass
+
+
+class BlockTagInTranslateableChunk(Base):
+ '''A block tag was encountered where it wasn't expected.'''
+ pass
+
+
+class SectionNotFound(Base):
+ '''The section you requested was not found in the RC file. Make
+sure the section ID is correct (matches the section's ID in the RC file).
+Also note that you may need to specify the RC file's encoding (using the
+encoding="" attribute) if it is not in the default Windows-1252 encoding.
+ '''
+ pass
+
+
+class IdRangeOverlap(Base):
+ '''ID range overlap.'''
+ pass
+
diff --git a/chromium/tools/grit/grit/extern/BogoFP.py b/chromium/tools/grit/grit/extern/BogoFP.py
new file mode 100644
index 00000000000..3d9cad3d2e1
--- /dev/null
+++ b/chromium/tools/grit/grit/extern/BogoFP.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Bogus fingerprint implementation, do not use for production,
+provided only as an example.
+
+Usage:
+ grit.py -h grit.extern.BogoFP xmb /tmp/foo
+"""
+
+
+import grit.extern.FP
+
+
+def UnsignedFingerPrint(str, encoding='utf-8'):
+ """Generate a fingerprint not intended for production from str (it
+ reduces the precision of the production fingerprint by one bit).
+ """
+ return (0xFFFFF7FFFFFFFFFF &
+ grit.extern.FP._UnsignedFingerPrintImpl(str, encoding))
diff --git a/chromium/tools/grit/grit/extern/FP.py b/chromium/tools/grit/grit/extern/FP.py
new file mode 100644
index 00000000000..3bde18dcfcc
--- /dev/null
+++ b/chromium/tools/grit/grit/extern/FP.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+try:
+ import hashlib
+ _new_md5 = hashlib.md5
+except ImportError:
+ import md5
+ _new_md5 = md5.new
+
+
+"""64-bit fingerprint support for strings.
+
+Usage:
+ from extern import FP
+ print 'Fingerprint is %ld' % FP.FingerPrint('Hello world!')
+"""
+
+
+def _UnsignedFingerPrintImpl(str, encoding='utf-8'):
+ """Generate a 64-bit fingerprint by taking the first half of the md5
+ of the string.
+ """
+ hex128 = _new_md5(str).hexdigest()
+ int64 = long(hex128[:16], 16)
+ return int64
+
+
+def UnsignedFingerPrint(str, encoding='utf-8'):
+ """Generate a 64-bit fingerprint.
+
+ The default implementation uses _UnsignedFingerPrintImpl, which
+ takes the first half of the md5 of the string, but the
+ implementation may be switched using SetUnsignedFingerPrintImpl.
+ """
+ return _UnsignedFingerPrintImpl(str, encoding)
+
+
+def FingerPrint(str, encoding='utf-8'):
+ fp = UnsignedFingerPrint(str, encoding=encoding)
+ # interpret fingerprint as signed longs
+ if fp & 0x8000000000000000L:
+ fp = - ((~fp & 0xFFFFFFFFFFFFFFFFL) + 1)
+ return fp
+
+
+def UseUnsignedFingerPrintFromModule(module_name):
+ """Imports module_name and replaces UnsignedFingerPrint in the
+ current module with the function of the same name from the imported
+ module.
+
+ Returns the function object previously known as
+ grit.extern.FP.UnsignedFingerPrint.
+ """
+ hash_module = __import__(module_name, fromlist=[module_name])
+ return SetUnsignedFingerPrint(hash_module.UnsignedFingerPrint)
+
+
+def SetUnsignedFingerPrint(function_object):
+ """Sets grit.extern.FP.UnsignedFingerPrint to point to
+ function_object.
+
+ Returns the function object previously known as
+ grit.extern.FP.UnsignedFingerPrint.
+ """
+ global UnsignedFingerPrint
+ original_function_object = UnsignedFingerPrint
+ UnsignedFingerPrint = function_object
+ return original_function_object
diff --git a/chromium/tools/grit/grit/extern/__init__.py b/chromium/tools/grit/grit/extern/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/grit/grit/extern/__init__.py
diff --git a/chromium/tools/grit/grit/extern/tclib.py b/chromium/tools/grit/grit/extern/tclib.py
new file mode 100644
index 00000000000..e84f177e1f1
--- /dev/null
+++ b/chromium/tools/grit/grit/extern/tclib.py
@@ -0,0 +1,503 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# The tclib module contains tools for aggregating, verifying, and storing
+# messages destined for the Translation Console, as well as for reading
+# translations back and outputting them in some desired format.
+#
+# This has been stripped down to include only the functionality needed by grit
+# for creating Windows .rc and .h files. These are the only parts needed by
+# the Chrome build process.
+
+import exceptions
+
+from grit.extern import FP
+
+# This module assumes that within a bundle no two messages can have the
+# same id unless they're identical.
+
+# The basic classes defined here for external use are Message and Translation,
+# where the former is used for English messages and the latter for
+# translations. These classes have a lot of common functionality, as expressed
+# by the common parent class BaseMessage. Perhaps the most important
+# distinction is that translated text is stored in UTF-8, whereas original text
+# is stored in whatever encoding the client uses (presumably Latin-1).
+
+# --------------------
+# The public interface
+# --------------------
+
+# Generate message id from message text and meaning string (optional),
+# both in utf-8 encoding
+#
+def GenerateMessageId(message, meaning=''):
+ fp = FP.FingerPrint(message)
+ if meaning:
+ # combine the fingerprints of message and meaning
+ fp2 = FP.FingerPrint(meaning)
+ if fp < 0:
+ fp = fp2 + (fp << 1) + 1
+ else:
+ fp = fp2 + (fp << 1)
+ # To avoid negative ids we strip the high-order bit
+ return str(fp & 0x7fffffffffffffffL)
+
+# -------------------------------------------------------------------------
+# The MessageTranslationError class is used to signal tclib-specific errors.
+
+class MessageTranslationError(exceptions.Exception):
+ def __init__(self, args = ''):
+ self.args = args
+
+
+# -----------------------------------------------------------
+# The Placeholder class represents a placeholder in a message.
+
+class Placeholder(object):
+ # String representation
+ def __str__(self):
+ return '%s, "%s", "%s"' % \
+ (self.__presentation, self.__original, self.__example)
+
+ # Getters
+ def GetOriginal(self):
+ return self.__original
+
+ def GetPresentation(self):
+ return self.__presentation
+
+ def GetExample(self):
+ return self.__example
+
+ def __eq__(self, other):
+ return self.EqualTo(other, strict=1, ignore_trailing_spaces=0)
+
+ # Equality test
+ #
+ # ignore_trailing_spaces: TC is using varchar to store the
+ # phrwr fields, as a result of that, the trailing spaces
+ # are removed by MySQL when the strings are stored into TC:-(
+ # ignore_trailing_spaces parameter is used to ignore
+ # trailing spaces during equivalence comparison.
+ #
+ def EqualTo(self, other, strict = 1, ignore_trailing_spaces = 1):
+ if type(other) is not Placeholder:
+ return 0
+ if StringEquals(self.__presentation, other.__presentation,
+ ignore_trailing_spaces):
+ if not strict or (StringEquals(self.__original, other.__original,
+ ignore_trailing_spaces) and
+ StringEquals(self.__example, other.__example,
+ ignore_trailing_spaces)):
+ return 1
+ return 0
+
+
+# -----------------------------------------------------------------
+# BaseMessage is the common parent class of Message and Translation.
+# It is not meant for direct use.
+
+class BaseMessage(object):
+ # Three types of message construction is supported. If the message text is a
+ # simple string with no dynamic content, you can pass it to the constructor
+ # as the "text" parameter. Otherwise, you can omit "text" and assemble the
+ # message step by step using AppendText() and AppendPlaceholder(). Or, as an
+ # alternative, you can give the constructor the "presentable" version of the
+ # message and a list of placeholders; it will then parse the presentation and
+ # build the message accordingly. For example:
+ # Message(text = "There are NUM_BUGS bugs in your code",
+ # placeholders = [Placeholder("NUM_BUGS", "%d", "33")],
+ # description = "Bla bla bla")
+ def __eq__(self, other):
+ # "source encoding" is nonsense, so ignore it
+ return _ObjectEquals(self, other, ['_BaseMessage__source_encoding'])
+
+ def GetName(self):
+ return self.__name
+
+ def GetSourceEncoding(self):
+ return self.__source_encoding
+
+ # Append a placeholder to the message
+ def AppendPlaceholder(self, placeholder):
+ if not isinstance(placeholder, Placeholder):
+ raise MessageTranslationError, ("Invalid message placeholder %s in "
+ "message %s" % (placeholder, self.GetId()))
+ # Are there other placeholders with the same presentation?
+ # If so, they need to be the same.
+ for other in self.GetPlaceholders():
+ if placeholder.GetPresentation() == other.GetPresentation():
+ if not placeholder.EqualTo(other):
+ raise MessageTranslationError, \
+ "Conflicting declarations of %s within message" % \
+ placeholder.GetPresentation()
+ # update placeholder list
+ dup = 0
+ for item in self.__content:
+ if isinstance(item, Placeholder) and placeholder.EqualTo(item):
+ dup = 1
+ break
+ if not dup:
+ self.__placeholders.append(placeholder)
+
+ # update content
+ self.__content.append(placeholder)
+
+ # Strips leading and trailing whitespace, and returns a tuple
+ # containing the leading and trailing space that was removed.
+ def Strip(self):
+ leading = trailing = ''
+ if len(self.__content) > 0:
+ s0 = self.__content[0]
+ if not isinstance(s0, Placeholder):
+ s = s0.lstrip()
+ leading = s0[:-len(s)]
+ self.__content[0] = s
+
+ s0 = self.__content[-1]
+ if not isinstance(s0, Placeholder):
+ s = s0.rstrip()
+ trailing = s0[len(s):]
+ self.__content[-1] = s
+ return leading, trailing
+
+ # Return the id of this message
+ def GetId(self):
+ if self.__id is None:
+ return self.GenerateId()
+ return self.__id
+
+ # Set the id of this message
+ def SetId(self, id):
+ if id is None:
+ self.__id = None
+ else:
+ self.__id = str(id) # Treat numerical ids as strings
+
+ # Return content of this message as a list (internal use only)
+ def GetContent(self):
+ return self.__content
+
+ # Return a human-readable version of this message
+ def GetPresentableContent(self):
+ presentable_content = ""
+ for item in self.__content:
+ if isinstance(item, Placeholder):
+ presentable_content += item.GetPresentation()
+ else:
+ presentable_content += item
+
+ return presentable_content
+
+ # Return a fragment of a message in escaped format
+ def EscapeFragment(self, fragment):
+ return fragment.replace('%', '%%')
+
+ # Return the "original" version of this message, doing %-escaping
+ # properly. If source_msg is specified, the placeholder original
+ # information inside source_msg will be used instead.
+ def GetOriginalContent(self, source_msg = None):
+ original_content = ""
+ for item in self.__content:
+ if isinstance(item, Placeholder):
+ if source_msg:
+ ph = source_msg.GetPlaceholder(item.GetPresentation())
+ if not ph:
+ raise MessageTranslationError, \
+ "Placeholder %s doesn't exist in message: %s" % \
+ (item.GetPresentation(), source_msg);
+ original_content += ph.GetOriginal()
+ else:
+ original_content += item.GetOriginal()
+ else:
+ original_content += self.EscapeFragment(item)
+ return original_content
+
+ # Return the example of this message
+ def GetExampleContent(self):
+ example_content = ""
+ for item in self.__content:
+ if isinstance(item, Placeholder):
+ example_content += item.GetExample()
+ else:
+ example_content += item
+ return example_content
+
+ # Return a list of all unique placeholders in this message
+ def GetPlaceholders(self):
+ return self.__placeholders
+
+ # Return a placeholder in this message
+ def GetPlaceholder(self, presentation):
+ for item in self.__content:
+ if (isinstance(item, Placeholder) and
+ item.GetPresentation() == presentation):
+ return item
+ return None
+
+ # Return this message's description
+ def GetDescription(self):
+ return self.__description
+
+ # Add a message source
+ def AddSource(self, source):
+ self.__sources.append(source)
+
+ # Return this message's sources as a list
+ def GetSources(self):
+ return self.__sources
+
+ # Return this message's sources as a string
+ def GetSourcesAsText(self, delimiter = "; "):
+ return delimiter.join(self.__sources)
+
+ # Set the obsolete flag for a message (internal use only)
+ def SetObsolete(self):
+ self.__obsolete = 1
+
+ # Get the obsolete flag for a message (internal use only)
+ def IsObsolete(self):
+ return self.__obsolete
+
+ # Get the sequence number (0 by default)
+ def GetSequenceNumber(self):
+ return self.__sequence_number
+
+ # Set the sequence number
+ def SetSequenceNumber(self, number):
+ self.__sequence_number = number
+
+ # Increment instance counter
+ def AddInstance(self):
+ self.__num_instances += 1
+
+ # Return instance count
+ def GetNumInstances(self):
+ return self.__num_instances
+
+ def GetErrors(self, from_tc=0):
+ """
+ Returns a description of the problem if the message is not
+ syntactically valid, or None if everything is fine.
+
+ Args:
+ from_tc: indicates whether this message came from the TC. We let
+ the TC get away with some things we normally wouldn't allow for
+ historical reasons.
+ """
+ # check that placeholders are unambiguous
+ pos = 0
+ phs = {}
+ for item in self.__content:
+ if isinstance(item, Placeholder):
+ phs[pos] = item
+ pos += len(item.GetPresentation())
+ else:
+ pos += len(item)
+ presentation = self.GetPresentableContent()
+ for ph in self.GetPlaceholders():
+ for pos in FindOverlapping(presentation, ph.GetPresentation()):
+ # message contains the same text as a placeholder presentation
+ other_ph = phs.get(pos)
+ if ((not other_ph
+ and not IsSubstringInPlaceholder(pos, len(ph.GetPresentation()), phs))
+ or
+ (other_ph and len(other_ph.GetPresentation()) < len(ph.GetPresentation()))):
+ return "message contains placeholder name '%s':\n%s" % (
+ ph.GetPresentation(), presentation)
+ return None
+
+
+ def __CopyTo(self, other):
+ """
+ Returns a copy of this BaseMessage.
+ """
+ assert isinstance(other, self.__class__) or isinstance(self, other.__class__)
+ other.__source_encoding = self.__source_encoding
+ other.__content = self.__content[:]
+ other.__description = self.__description
+ other.__id = self.__id
+ other.__num_instances = self.__num_instances
+ other.__obsolete = self.__obsolete
+ other.__name = self.__name
+ other.__placeholders = self.__placeholders[:]
+ other.__sequence_number = self.__sequence_number
+ other.__sources = self.__sources[:]
+
+ return other
+
+ def HasText(self):
+ """Returns true iff this message has anything other than placeholders."""
+ for item in self.__content:
+ if not isinstance(item, Placeholder):
+ return True
+ return False
+
+# --------------------------------------------------------
+# The Message class represents original (English) messages
+
+class Message(BaseMessage):
+ # See BaseMessage constructor
+ def __init__(self, source_encoding, text=None, id=None,
+ description=None, meaning="", placeholders=None,
+ source=None, sequence_number=0, clone_from=None,
+ time_created=0, name=None, is_hidden = 0):
+
+ if clone_from is not None:
+ BaseMessage.__init__(self, None, clone_from=clone_from)
+ self.__meaning = clone_from.__meaning
+ self.__time_created = clone_from.__time_created
+ self.__is_hidden = clone_from.__is_hidden
+ return
+
+ BaseMessage.__init__(self, source_encoding, text, id, description,
+ placeholders, source, sequence_number,
+ name=name)
+ self.__meaning = meaning
+ self.__time_created = time_created
+ self.SetIsHidden(is_hidden)
+
+ # String representation
+ def __str__(self):
+ s = 'source: %s, id: %s, content: "%s", meaning: "%s", ' \
+ 'description: "%s"' % \
+ (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
+ self.__meaning, self.GetDescription())
+ if self.GetName() is not None:
+ s += ', name: "%s"' % self.GetName()
+ placeholders = self.GetPlaceholders()
+ for i in range(len(placeholders)):
+ s += ", placeholder[%d]: %s" % (i, placeholders[i])
+ return s
+
+ # Strips leading and trailing whitespace, and returns a tuple
+ # containing the leading and trailing space that was removed.
+ def Strip(self):
+ leading = trailing = ''
+ content = self.GetContent()
+ if len(content) > 0:
+ s0 = content[0]
+ if not isinstance(s0, Placeholder):
+ s = s0.lstrip()
+ leading = s0[:-len(s)]
+ content[0] = s
+
+ s0 = content[-1]
+ if not isinstance(s0, Placeholder):
+ s = s0.rstrip()
+ trailing = s0[len(s):]
+ content[-1] = s
+ return leading, trailing
+
+ # Generate an id by hashing message content
+ def GenerateId(self):
+ self.SetId(GenerateMessageId(self.GetPresentableContent(),
+ self.__meaning))
+ return self.GetId()
+
+ def GetMeaning(self):
+ return self.__meaning
+
+ def GetTimeCreated(self):
+ return self.__time_created
+
+ # Equality operator
+ def EqualTo(self, other, strict = 1):
+ # Check id, meaning, content
+ if self.GetId() != other.GetId():
+ return 0
+ if self.__meaning != other.__meaning:
+ return 0
+ if self.GetPresentableContent() != other.GetPresentableContent():
+ return 0
+ # Check descriptions if comparison is strict
+ if (strict and
+ self.GetDescription() is not None and
+ other.GetDescription() is not None and
+ self.GetDescription() != other.GetDescription()):
+ return 0
+ # Check placeholders
+ ph1 = self.GetPlaceholders()
+ ph2 = other.GetPlaceholders()
+ if len(ph1) != len(ph2):
+ return 0
+ for i in range(len(ph1)):
+ if not ph1[i].EqualTo(ph2[i], strict):
+ return 0
+
+ return 1
+
+ def Copy(self):
+ """
+ Returns a copy of this Message.
+ """
+ assert isinstance(self, Message)
+ return Message(None, clone_from=self)
+
+ def SetIsHidden(self, is_hidden):
+ """Sets whether this message should be hidden.
+
+ Args:
+ is_hidden : 0 or 1 - if the message should be hidden, 0 otherwise
+ """
+ if is_hidden not in [0, 1]:
+ raise MessageTranslationError, "is_hidden must be 0 or 1, got %s"
+ self.__is_hidden = is_hidden
+
+ def IsHidden(self):
+ """Returns 1 if this message is hidden, and 0 otherwise."""
+ return self.__is_hidden
+
+# ----------------------------------------------------
+# The Translation class represents translated messages
+
+class Translation(BaseMessage):
+ # See BaseMessage constructor
+ def __init__(self, source_encoding, text=None, id=None,
+ description=None, placeholders=None, source=None,
+ sequence_number=0, clone_from=None, ignore_ph_errors=0,
+ name=None):
+ if clone_from is not None:
+ BaseMessage.__init__(self, None, clone_from=clone_from)
+ return
+
+ BaseMessage.__init__(self, source_encoding, text, id, description,
+ placeholders, source, sequence_number,
+ ignore_ph_errors=ignore_ph_errors, name=name)
+
+ # String representation
+ def __str__(self):
+ s = 'source: %s, id: %s, content: "%s", description: "%s"' % \
+ (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
+ self.GetDescription());
+ placeholders = self.GetPlaceholders()
+ for i in range(len(placeholders)):
+ s += ", placeholder[%d]: %s" % (i, placeholders[i])
+ return s
+
+ # Equality operator
+ def EqualTo(self, other, strict=1):
+ # Check id and content
+ if self.GetId() != other.GetId():
+ return 0
+ if self.GetPresentableContent() != other.GetPresentableContent():
+ return 0
+ # Check placeholders
+ ph1 = self.GetPlaceholders()
+ ph2 = other.GetPlaceholders()
+ if len(ph1) != len(ph2):
+ return 0
+ for i in range(len(ph1)):
+ if not ph1[i].EqualTo(ph2[i], strict):
+ return 0
+
+ return 1
+
+ def Copy(self):
+ """
+ Returns a copy of this Translation.
+ """
+ return Translation(None, clone_from=self)
+
diff --git a/chromium/tools/grit/grit/format/__init__.py b/chromium/tools/grit/grit/format/__init__.py
new file mode 100644
index 00000000000..2a3c59caeb4
--- /dev/null
+++ b/chromium/tools/grit/grit/format/__init__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Module grit.format
+'''
+
+pass
+
diff --git a/chromium/tools/grit/grit/format/android_xml.py b/chromium/tools/grit/grit/format/android_xml.py
new file mode 100644
index 00000000000..d960bf49ddb
--- /dev/null
+++ b/chromium/tools/grit/grit/format/android_xml.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Produces localized strings.xml files for Android.
+
+In cases where an "android" type output file is requested in a grd, the classes
+in android_xml will process the messages and translations to produce a valid
+strings.xml that is properly localized with the specified language.
+
+For example if the following output tag were to be included in a grd file
+ <outputs>
+ ...
+ <output filename="values-es/strings.xml" type="android" lang="es" />
+ ...
+ </outputs>
+
+for a grd file with the following messages:
+
+ <message name="IDS_HELLO" desc="Simple greeting">Hello</message>
+ <message name="IDS_WORLD" desc="The world">world</message>
+
+and there existed an appropriate xtb file containing the Spanish translations,
+then the output would be:
+
+ <?xml version="1.0" encoding="utf-8"?>
+ <resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <string name="hello">"Hola"</string>
+ <string name="world">"mundo"</string>
+ </resources>
+
+which would be written to values-es/strings.xml and usable by the Android
+resource framework.
+
+Advanced usage
+--------------
+
+To process only certain messages in a grd file, tag each desired message by
+adding "android_java" to formatter_data. Then set the environmental variable
+ANDROID_JAVA_TAGGED_ONLY to "true" when building the grd file. For example:
+
+ <message name="IDS_HELLO" formatter_data="android_java">Hello</message>
+
+To specify the product attribute to be added to a <string> element, add
+"android_java_product" to formatter_data. "android_java_name" can be used to
+override the name in the <string> element. For example,
+
+ <message name="IDS_FOO_NOSDCARD" formatter_data="android_java_product=nosdcard
+ android_java_name=foo">no card</message>
+ <message name="IDS_FOO_DEFAULT" formatter_data="android_java_product=default
+ android_java_name=foo">has card</message>
+
+would generate
+
+ <string name="foo" product="nosdcard">"no card"</string>
+ <string name="foo" product="default">"has card"</string>
+"""
+
+import os
+import types
+import xml.sax.saxutils
+
+from grit import lazy_re
+from grit.node import message
+
+
+# When this environmental variable has value "true", only tagged messages will
+# be outputted.
+_TAGGED_ONLY_ENV_VAR = 'ANDROID_JAVA_TAGGED_ONLY'
+_TAGGED_ONLY_DEFAULT = False
+
+# In tagged-only mode, only messages with this tag will be ouputted.
+_EMIT_TAG = 'android_java'
+
+# This tag controls the product attribute of the generated <string> element.
+_PRODUCT_TAG = 'android_java_product'
+
+# This tag controls the name attribute of the generated <string> element.
+_NAME_TAG = 'android_java_name'
+
+# The Android resource name and optional product information are placed
+# in the grd string name because grd doesn't know about Android product
+# information.
+# TODO(newt): Don't allow product information in mangled names, since it can now
+# be specified using "android_java_product" in formatter_data.
+_NAME_PATTERN = lazy_re.compile(
+ 'IDS_(?P<name>[A-Z0-9_]+)(_product_(?P<product>[a-z]+))?\Z')
+
+
+# In most cases we only need a name attribute and string value.
+_SIMPLE_TEMPLATE = u'<string name="%s">%s</string>\n'
+
+
+# In a few cases a product attribute is needed.
+_PRODUCT_TEMPLATE = u'<string name="%s" product="%s">%s</string>\n'
+
+
+def Format(root, lang='en', output_dir='.'):
+ yield ('<?xml version="1.0" encoding="utf-8"?>\n'
+ '<resources '
+ 'xmlns:android="http://schemas.android.com/apk/res/android">\n')
+
+ tagged_only = _TAGGED_ONLY_DEFAULT
+ if _TAGGED_ONLY_ENV_VAR in os.environ:
+ tagged_only = os.environ[_TAGGED_ONLY_ENV_VAR].lower()
+ if tagged_only == 'true':
+ tagged_only = True
+ elif tagged_only == 'false':
+ tagged_only = False
+ else:
+ raise Exception('env variable ANDROID_JAVA_TAGGED_ONLY must have value '
+ 'true or false. Invalid value: %s' % tagged_only)
+
+ for item in root.ActiveDescendants():
+ with item:
+ if ShouldOutputNode(item, tagged_only):
+ yield _FormatMessage(item, lang)
+
+ yield '</resources>\n'
+
+
+def ShouldOutputNode(node, tagged_only):
+ """Returns true if node should be outputted.
+
+ Args:
+ node: a Node from the grd dom
+ tagged_only: true, if only tagged messages should be outputted
+ """
+ return (isinstance(node, message.MessageNode) and
+ (not tagged_only or _EMIT_TAG in node.formatter_data))
+
+
+def _FormatMessage(item, lang):
+ """Writes out a single string as a <resource/> element."""
+
+ value = item.ws_at_start + item.Translate(lang) + item.ws_at_end
+ # Replace < > & with &lt; &gt; &amp; to ensure we generate valid XML and
+ # replace ' " with \' \" to conform to Android's string formatting rules.
+ value = xml.sax.saxutils.escape(value, {"'": "\\'", '"': '\\"'})
+ # Wrap the string in double quotes to preserve whitespace.
+ value = '"' + value + '"'
+
+ mangled_name = item.GetTextualIds()[0]
+ match = _NAME_PATTERN.match(mangled_name)
+ if not match:
+ raise Exception('Unexpected resource name: %s' % mangled_name)
+ name = match.group('name').lower()
+ product = match.group('product')
+
+ # Override product or name with values in formatter_data, if any.
+ product = item.formatter_data.get(_PRODUCT_TAG, product)
+ name = item.formatter_data.get(_NAME_TAG, name)
+
+ if product:
+ return _PRODUCT_TEMPLATE % (name, product, value)
+ else:
+ return _SIMPLE_TEMPLATE % (name, value)
diff --git a/chromium/tools/grit/grit/format/android_xml_unittest.py b/chromium/tools/grit/grit/format/android_xml_unittest.py
new file mode 100644
index 00000000000..c5ce00f0d5c
--- /dev/null
+++ b/chromium/tools/grit/grit/format/android_xml_unittest.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unittest for android_xml.py."""
+
+import os
+import StringIO
+import sys
+import unittest
+
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+from grit import util
+from grit.format import android_xml
+from grit.node import message
+from grit.tool import build
+
+
+class AndroidXmlUnittest(unittest.TestCase):
+
+ def testMessages(self):
+ root = util.ParseGrdForUnittest(ur"""
+ <messages>
+ <message name="IDS_SIMPLE" desc="A vanilla string">
+ Martha
+ </message>
+ <message name="IDS_ONE_LINE" desc="On one line">sat and wondered</message>
+ <message name="IDS_QUOTES" desc="A string with quotation marks">
+ out loud, "Why don't I build a flying car?"
+ </message>
+ <message name="IDS_MULTILINE" desc="A string split over several lines">
+ She gathered
+wood, charcoal, and
+a sledge hammer.
+ </message>
+ <message name="IDS_WHITESPACE" desc="A string with extra whitespace.">
+ ''' How old fashioned -- she thought. '''
+ </message>
+ <message name="IDS_PRODUCT_SPECIFIC_product_nosdcard"
+ desc="A string that only applies if there's no sdcard">
+ Lasers will probably be helpful.
+ </message>
+ <message name="IDS_PRODUCT_DEFAULT" desc="New style product tag"
+ formatter_data="android_java_product=default android_java_name=custom_name">
+ You have an SD card
+ </message>
+ <message name="IDS_PLACEHOLDERS" desc="A string with placeholders">
+ I'll buy a <ph name="WAVELENGTH">%d<ex>200</ex></ph> nm laser at <ph name="STORE_NAME">%s<ex>the grocery store</ex></ph>.
+ </message>
+ </messages>
+ """)
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('android', 'en'), buf)
+ output = buf.getvalue()
+ expected = ur"""
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<string name="simple">"Martha"</string>
+<string name="one_line">"sat and wondered"</string>
+<string name="quotes">"out loud, \"Why don\'t I build a flying car?\""</string>
+<string name="multiline">"She gathered
+wood, charcoal, and
+a sledge hammer."</string>
+<string name="whitespace">" How old fashioned -- she thought. "</string>
+<string name="product_specific" product="nosdcard">"Lasers will probably be helpful."</string>
+<string name="custom_name" product="default">"You have an SD card"</string>
+<string name="placeholders">"I\'ll buy a %d nm laser at %s."</string>
+</resources>
+"""
+ self.assertEqual(output.strip(), expected.strip())
+
+ def testTaggedOnly(self):
+ root = util.ParseGrdForUnittest(ur"""
+ <messages>
+ <message name="IDS_HELLO" desc="" formatter_data="android_java">
+ Hello
+ </message>
+ <message name="IDS_WORLD" desc="">
+ world
+ </message>
+ </messages>
+ """)
+
+ msg_hello, msg_world = root.GetChildrenOfType(message.MessageNode)
+ self.assertTrue(android_xml.ShouldOutputNode(msg_hello, tagged_only=True))
+ self.assertFalse(android_xml.ShouldOutputNode(msg_world, tagged_only=True))
+ self.assertTrue(android_xml.ShouldOutputNode(msg_hello, tagged_only=False))
+ self.assertTrue(android_xml.ShouldOutputNode(msg_world, tagged_only=False))
+
+
+class DummyOutput(object):
+
+ def __init__(self, type, language):
+ self.type = type
+ self.language = language
+
+ def GetType(self):
+ return self.type
+
+ def GetLanguage(self):
+ return self.language
+
+ def GetOutputFilename(self):
+ return 'hello.gif'
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/c_format.py b/chromium/tools/grit/grit/format/c_format.py
new file mode 100644
index 00000000000..06b94393302
--- /dev/null
+++ b/chromium/tools/grit/grit/format/c_format.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Formats as a .C file for compilation.
+"""
+
+import os
+import re
+import types
+
+from grit import util
+
+
+def _FormatHeader(root, output_dir):
+ """Returns the required preamble for C files."""
+ # Find the location of the resource header file, so that we can include
+ # it.
+ resource_header = 'resource.h' # fall back to this
+ for output in root.GetOutputFiles():
+ if output.attrs['type'] == 'rc_header':
+ resource_header = os.path.abspath(output.GetOutputFilename())
+ resource_header = util.MakeRelativePath(output_dir, resource_header)
+ return """// This file is automatically generated by GRIT. Do not edit.
+
+#include "%s"
+
+// All strings are UTF-8
+""" % (resource_header)
+# end _FormatHeader() function
+
+
+def Format(root, lang='en', output_dir='.'):
+ """Outputs a C switch statement representing the string table."""
+ from grit.node import message
+ assert isinstance(lang, types.StringTypes)
+
+ yield _FormatHeader(root, output_dir)
+
+ yield 'const char* GetString(int id) {\n switch (id) {'
+
+ for item in root.ActiveDescendants():
+ with item:
+ if isinstance(item, message.MessageNode):
+ yield _FormatMessage(item, lang)
+
+ yield '\n default:\n return 0;\n }\n}'
+
+
+def _HexToOct(match):
+ "Return the octal form of the hex numbers"
+ hex = match.group("hex")
+ result = ""
+ while len(hex):
+ next_num = int(hex[2:4], 16)
+ result += "\\" + '%03d' % int(oct(next_num), 10)
+ hex = hex[4:]
+ return match.group("escaped_backslashes") + result
+
+
+def _FormatMessage(item, lang):
+ """Format a single <message> element."""
+
+ message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
+ # output message with non-ascii chars escaped as octal numbers
+ # C's grammar allows escaped hexadecimal numbers to be infinite,
+ # but octal is always of the form \OOO
+ message = message.encode('utf-8').encode('string_escape')
+ # an escaped char is (\xHH)+ but only if the initial
+ # backslash is not escaped.
+ not_a_backslash = r"(^|[^\\])" # beginning of line or a non-backslash char
+ escaped_backslashes = not_a_backslash + r"(\\\\)*"
+ hex_digits = r"((\\x)[0-9a-f]{2})+"
+ two_digit_hex_num = re.compile(
+ r"(?P<escaped_backslashes>%s)(?P<hex>%s)"
+ % (escaped_backslashes, hex_digits))
+ message = two_digit_hex_num.sub(_HexToOct, message)
+ # unescape \ (convert \\ back to \)
+ message = message.replace('\\\\', '\\')
+ message = message.replace('"', '\\"')
+ message = util.LINEBREAKS.sub(r'\\n', message)
+
+ name_attr = item.GetTextualIds()[0]
+
+ return '\n case %s:\n return "%s";' % (name_attr, message)
diff --git a/chromium/tools/grit/grit/format/c_format_unittest.py b/chromium/tools/grit/grit/format/c_format_unittest.py
new file mode 100644
index 00000000000..ba1c5c71c6d
--- /dev/null
+++ b/chromium/tools/grit/grit/format/c_format_unittest.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unittest for c_format.py.
+"""
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit import util
+from grit.tool import build
+
+
+class CFormatUnittest(unittest.TestCase):
+
+ def testMessages(self):
+ root = util.ParseGrdForUnittest("""
+ <messages>
+ <message name="IDS_QUESTIONS">Do you want to play questions?</message>
+ <message name="IDS_QUOTES">
+ "What's in a name, <ph name="NAME">%s<ex>Brandon</ex></ph>?"
+ </message>
+ <message name="IDS_LINE_BREAKS">
+ Was that rhetoric?
+No.
+Statement. Two all. Game point.
+</message>
+ <message name="IDS_NON_ASCII">
+ \xc3\xb5\\xc2\\xa4\\\xc2\xa4\\\\xc3\\xb5\xe4\xa4\xa4
+ </message>
+ </messages>
+ """)
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('c_format', 'en'), buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ self.assertEqual(u"""\
+#include "resource.h"
+const char* GetString(int id) {
+ switch (id) {
+ case IDS_QUESTIONS:
+ return "Do you want to play questions?";
+ case IDS_QUOTES:
+ return "\\"What\\'s in a name, %s?\\"";
+ case IDS_LINE_BREAKS:
+ return "Was that rhetoric?\\nNo.\\nStatement. Two all. Game point.";
+ case IDS_NON_ASCII:
+ return "\\303\\265\\xc2\\xa4\\\\302\\244\\\\xc3\\xb5\\344\\244\\244";
+ default:
+ return 0;
+ }
+}""", output)
+
+
+class DummyOutput(object):
+
+ def __init__(self, type, language):
+ self.type = type
+ self.language = language
+
+ def GetType(self):
+ return self.type
+
+ def GetLanguage(self):
+ return self.language
+
+ def GetOutputFilename(self):
+ return 'hello.gif'
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/chrome_messages_json.py b/chromium/tools/grit/grit/format/chrome_messages_json.py
new file mode 100644
index 00000000000..7b370d7fdca
--- /dev/null
+++ b/chromium/tools/grit/grit/format/chrome_messages_json.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Formats as a .json file that can be used to localize Google Chrome
+extensions."""
+
+from json import JSONEncoder
+import re
+import types
+
+from grit import util
+from grit.node import message
+
+def Format(root, lang='en', output_dir='.'):
+ """Format the messages as JSON."""
+ yield '{\n'
+
+ encoder = JSONEncoder();
+ format = (' "%s": {\n'
+ ' "message": %s\n'
+ ' }')
+ first = True
+ for child in root.ActiveDescendants():
+ if isinstance(child, message.MessageNode):
+ id = child.attrs['name']
+ if id.startswith('IDR_'):
+ id = id[4:]
+
+ loc_message = encoder.encode(child.Translate(lang))
+
+ if not first:
+ yield ',\n'
+ first = False
+ yield format % (id, loc_message)
+
+ yield '\n}\n'
diff --git a/chromium/tools/grit/grit/format/chrome_messages_json_unittest.py b/chromium/tools/grit/grit/format/chrome_messages_json_unittest.py
new file mode 100644
index 00000000000..484230fe49b
--- /dev/null
+++ b/chromium/tools/grit/grit/format/chrome_messages_json_unittest.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unittest for chrome_messages_json.py.
+"""
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit import grd_reader
+from grit import util
+from grit.tool import build
+
+class ChromeMessagesJsonFormatUnittest(unittest.TestCase):
+
+ def testMessages(self):
+ root = util.ParseGrdForUnittest(u"""
+ <messages>
+ <message name="IDS_SIMPLE_MESSAGE">
+ Simple message.
+ </message>
+ <message name="IDS_QUOTES">
+ element\u2019s \u201c<ph name="NAME">%s<ex>name</ex></ph>\u201d attribute
+ </message>
+ <message name="IDS_PLACEHOLDERS">
+ <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
+ </message>
+ <message name="IDS_STARTS_WITH_SPACE">
+ ''' (<ph name="COUNT">%d<ex>2</ex></ph>)
+ </message>
+ <message name="IDS_DOUBLE_QUOTES">
+ A "double quoted" message.
+ </message>
+ <message name="IDS_BACKSLASH">
+ \\
+ </message>
+ </messages>
+ """)
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'en'), buf)
+ output = buf.getvalue()
+ test = u"""
+{
+ "IDS_SIMPLE_MESSAGE": {
+ "message": "Simple message."
+ },
+ "IDS_QUOTES": {
+ "message": "element\\u2019s \\u201c%s\\u201d attribute"
+ },
+ "IDS_PLACEHOLDERS": {
+ "message": "%1$d error, %2$d warning"
+ },
+ "IDS_STARTS_WITH_SPACE": {
+ "message": "(%d)"
+ },
+ "IDS_DOUBLE_QUOTES": {
+ "message": "A \\"double quoted\\" message."
+ },
+ "IDS_BACKSLASH": {
+ "message": "\\\\"
+ }
+}
+"""
+ self.assertEqual(test.strip(), output.strip())
+
+ def testTranslations(self):
+ root = util.ParseGrdForUnittest("""
+ <messages>
+ <message name="ID_HELLO">Hello!</message>
+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
+ Joi</ex></ph></message>
+ </messages>
+ """)
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'fr'), buf)
+ output = buf.getvalue()
+ test = u"""
+{
+ "ID_HELLO": {
+ "message": "H\\u00e9P\\u00e9ll\\u00f4P\\u00f4!"
+ },
+ "ID_HELLO_USER": {
+ "message": "H\\u00e9P\\u00e9ll\\u00f4P\\u00f4 %s"
+ }
+}
+"""
+ self.assertEqual(test.strip(), output.strip())
+
+
+class DummyOutput(object):
+
+ def __init__(self, type, language):
+ self.type = type
+ self.language = language
+
+ def GetType(self):
+ return self.type
+
+ def GetLanguage(self):
+ return self.language
+
+ def GetOutputFilename(self):
+ return 'hello.gif'
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/data_pack.py b/chromium/tools/grit/grit/format/data_pack.py
new file mode 100755
index 00000000000..0cdbbd8d341
--- /dev/null
+++ b/chromium/tools/grit/grit/format/data_pack.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Support for formatting a data pack file used for platform agnostic resource
+files.
+'''
+
+import collections
+import exceptions
+import os
+import struct
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+from grit import util
+from grit.node import include
+from grit.node import message
+from grit.node import structure
+from grit.node import misc
+
+
+PACK_FILE_VERSION = 4
+HEADER_LENGTH = 2 * 4 + 1 # Two uint32s. (file version, number of entries) and
+ # one uint8 (encoding of text resources)
+BINARY, UTF8, UTF16 = range(3)
+
+
+class WrongFileVersion(Exception):
+ pass
+
+
+DataPackContents = collections.namedtuple(
+ 'DataPackContents', 'resources encoding')
+
+
+def Format(root, lang='en', output_dir='.'):
+ '''Writes out the data pack file format (platform agnostic resource file).'''
+ data = {}
+ for node in root.ActiveDescendants():
+ with node:
+ if isinstance(node, (include.IncludeNode, message.MessageNode,
+ structure.StructureNode)):
+ id, value = node.GetDataPackPair(lang, UTF8)
+ if value is not None:
+ data[id] = value
+ return WriteDataPackToString(data, UTF8)
+
+
+def ReadDataPack(input_file):
+ """Reads a data pack file and returns a dictionary."""
+ data = util.ReadFile(input_file, util.BINARY)
+ original_data = data
+
+ # Read the header.
+ version, num_entries, encoding = struct.unpack("<IIB", data[:HEADER_LENGTH])
+ if version != PACK_FILE_VERSION:
+ print "Wrong file version in ", input_file
+ raise WrongFileVersion
+
+ resources = {}
+ if num_entries == 0:
+ return DataPackContents(resources, encoding)
+
+ # Read the index and data.
+ data = data[HEADER_LENGTH:]
+ kIndexEntrySize = 2 + 4 # Each entry is a uint16 and a uint32.
+ for _ in range(num_entries):
+ id, offset = struct.unpack("<HI", data[:kIndexEntrySize])
+ data = data[kIndexEntrySize:]
+ next_id, next_offset = struct.unpack("<HI", data[:kIndexEntrySize])
+ resources[id] = original_data[offset:next_offset]
+
+ return DataPackContents(resources, encoding)
+
+
+def WriteDataPackToString(resources, encoding):
+ """Write a map of id=>data into a string in the data pack format and return
+ it."""
+ ids = sorted(resources.keys())
+ ret = []
+
+ # Write file header.
+ ret.append(struct.pack("<IIB", PACK_FILE_VERSION, len(ids), encoding))
+ HEADER_LENGTH = 2 * 4 + 1 # Two uint32s and one uint8.
+
+ # Each entry is a uint16 + a uint32s. We have one extra entry for the last
+ # item.
+ index_length = (len(ids) + 1) * (2 + 4)
+
+ # Write index.
+ data_offset = HEADER_LENGTH + index_length
+ for id in ids:
+ ret.append(struct.pack("<HI", id, data_offset))
+ data_offset += len(resources[id])
+
+ ret.append(struct.pack("<HI", 0, data_offset))
+
+ # Write data.
+ for id in ids:
+ ret.append(resources[id])
+ return ''.join(ret)
+
+
+def WriteDataPack(resources, output_file, encoding):
+ """Write a map of id=>data into output_file as a data pack."""
+ content = WriteDataPackToString(resources, encoding)
+ with open(output_file, "wb") as file:
+ file.write(content)
+
+
+def RePack(output_file, input_files):
+ """Write a new data pack to |output_file| based on a list of filenames
+ (|input_files|)"""
+ resources = {}
+ encoding = None
+ for filename in input_files:
+ new_content = ReadDataPack(filename)
+
+ # Make sure we have no dups.
+ duplicate_keys = set(new_content.resources.keys()) & set(resources.keys())
+ if len(duplicate_keys) != 0:
+ raise exceptions.KeyError("Duplicate keys: " + str(list(duplicate_keys)))
+
+ # Make sure encoding is consistent.
+ if encoding in (None, BINARY):
+ encoding = new_content.encoding
+ elif new_content.encoding not in (BINARY, encoding):
+ raise exceptions.KeyError("Inconsistent encodings: " +
+ str(encoding) + " vs " +
+ str(new_content.encoding))
+
+ resources.update(new_content.resources)
+
+ # Encoding is 0 for BINARY, 1 for UTF8 and 2 for UTF16
+ if encoding is None:
+ encoding = BINARY
+ WriteDataPack(resources, output_file, encoding)
+
+
+# Temporary hack for external programs that import data_pack.
+# TODO(benrg): Remove this.
+class DataPack(object):
+ pass
+DataPack.ReadDataPack = staticmethod(ReadDataPack)
+DataPack.WriteDataPackToString = staticmethod(WriteDataPackToString)
+DataPack.WriteDataPack = staticmethod(WriteDataPack)
+DataPack.RePack = staticmethod(RePack)
+
+
+def main():
+ if len(sys.argv) > 1:
+ # When an argument is given, read and explode the file to text
+ # format, for easier diffing.
+ data = ReadDataPack(sys.argv[1])
+ print data.encoding
+ for (resource_id, text) in data.resources.iteritems():
+ print "%s: %s" % (resource_id, text)
+ else:
+ # Just write a simple file.
+ data = { 1: "", 4: "this is id 4", 6: "this is id 6", 10: "" }
+ WriteDataPack(data, "datapack1.pak", UTF8)
+ data2 = { 1000: "test", 5: "five" }
+ WriteDataPack(data2, "datapack2.pak", UTF8)
+ print "wrote datapack1 and datapack2 to current directory."
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/grit/grit/format/data_pack_unittest.py b/chromium/tools/grit/grit/format/data_pack_unittest.py
new file mode 100644
index 00000000000..d210c99fdd3
--- /dev/null
+++ b/chromium/tools/grit/grit/format/data_pack_unittest.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.data_pack'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+
+from grit.format import data_pack
+
+
+class FormatDataPackUnittest(unittest.TestCase):
+ def testWriteDataPack(self):
+ expected = (
+ '\x04\x00\x00\x00' # header(version
+ '\x04\x00\x00\x00' # no. entries,
+ '\x01' # encoding)
+ '\x01\x00\x27\x00\x00\x00' # index entry 1
+ '\x04\x00\x27\x00\x00\x00' # index entry 4
+ '\x06\x00\x33\x00\x00\x00' # index entry 6
+ '\x0a\x00\x3f\x00\x00\x00' # index entry 10
+ '\x00\x00\x3f\x00\x00\x00' # extra entry for the size of last
+ 'this is id 4this is id 6') # data
+ input = { 1: "", 4: "this is id 4", 6: "this is id 6", 10: "" }
+ output = data_pack.WriteDataPackToString(input, data_pack.UTF8)
+ self.failUnless(output == expected)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/html_inline.py b/chromium/tools/grit/grit/format/html_inline.py
new file mode 100755
index 00000000000..589e49b6a94
--- /dev/null
+++ b/chromium/tools/grit/grit/format/html_inline.py
@@ -0,0 +1,421 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Flattens a HTML file by inlining its external resources.
+
+This is a small script that takes a HTML file, looks for src attributes
+and inlines the specified file, producing one HTML file with no external
+dependencies. It recursively inlines the included files.
+"""
+
+import os
+import re
+import sys
+import base64
+import mimetypes
+
+from grit import lazy_re
+from grit import util
+
+DIST_DEFAULT = 'chromium'
+DIST_ENV_VAR = 'CHROMIUM_BUILD'
+DIST_SUBSTR = '%DISTRIBUTION%'
+
+# Matches beginning of an "if" block with trailing spaces.
+_BEGIN_IF_BLOCK = lazy_re.compile(
+ '<if [^>]*?expr="(?P<expression>[^"]*)"[^>]*?>\s*')
+
+# Matches ending of an "if" block with preceding spaces.
+_END_IF_BLOCK = lazy_re.compile('\s*</if>')
+
+# Used by DoInline to replace various links with inline content.
+_STYLESHEET_RE = lazy_re.compile(
+ '<link rel="stylesheet"[^>]+?href="(?P<filename>[^"]*)".*?>(\s*</link>)?',
+ re.DOTALL)
+_INCLUDE_RE = lazy_re.compile(
+ '<include[^>]+?src="(?P<filename>[^"\']*)".*?>(\s*</include>)?',
+ re.DOTALL)
+_SRC_RE = lazy_re.compile(
+ r'<(?!script)(?:[^>]+?\s)src=(?P<quote>")(?P<filename>[^"\']*)\1',
+ re.MULTILINE)
+_ICON_RE = lazy_re.compile(
+ r'<link rel="icon"\s(?:[^>]+?\s)?'
+ 'href=(?P<quote>")(?P<filename>[^"\']*)\1',
+ re.MULTILINE)
+
+
+
+def FixupMimeType(mime_type):
+ """Helper function that normalizes platform differences in the mime type
+ returned by the Python's mimetypes.guess_type API.
+ """
+ mappings = {
+ 'image/x-png': 'image/png'
+ }
+ return mappings[mime_type] if mime_type in mappings else mime_type
+
+
+def GetDistribution():
+ """Helper function that gets the distribution we are building.
+
+ Returns:
+ string
+ """
+ distribution = DIST_DEFAULT
+ if DIST_ENV_VAR in os.environ.keys():
+ distribution = os.environ[DIST_ENV_VAR]
+ if len(distribution) > 1 and distribution[0] == '_':
+ distribution = distribution[1:].lower()
+ return distribution
+
+
+def SrcInlineAsDataURL(
+ src_match, base_path, distribution, inlined_files, names_only=False,
+ filename_expansion_function=None):
+ """regex replace function.
+
+ Takes a regex match for src="filename", attempts to read the file
+ at 'filename' and returns the src attribute with the file inlined
+ as a data URI. If it finds DIST_SUBSTR string in file name, replaces
+ it with distribution.
+
+ Args:
+ src_match: regex match object with 'filename' and 'quote' named capturing
+ groups
+ base_path: path that to look for files in
+ distribution: string that should replace DIST_SUBSTR
+ inlined_files: The name of the opened file is appended to this list.
+ names_only: If true, the function will not read the file but just return "".
+ It will still add the filename to |inlined_files|.
+
+ Returns:
+ string
+ """
+ filename = src_match.group('filename')
+ if filename_expansion_function:
+ filename = filename_expansion_function(filename)
+ quote = src_match.group('quote')
+
+ if filename.find(':') != -1:
+ # filename is probably a URL, which we don't want to bother inlining
+ return src_match.group(0)
+
+ filename = filename.replace(DIST_SUBSTR , distribution)
+ filepath = os.path.normpath(os.path.join(base_path, filename))
+ inlined_files.add(filepath)
+
+ if names_only:
+ return ""
+
+ mimetype = FixupMimeType(mimetypes.guess_type(filename)[0]) or 'text/plain'
+ inline_data = base64.standard_b64encode(util.ReadFile(filepath, util.BINARY))
+
+ prefix = src_match.string[src_match.start():src_match.start('filename')]
+ suffix = src_match.string[src_match.end('filename'):src_match.end()]
+ return '%sdata:%s;base64,%s%s' % (prefix, mimetype, inline_data, suffix)
+
+
+class InlinedData:
+ """Helper class holding the results from DoInline().
+
+ Holds the inlined data and the set of filenames of all the inlined
+ files.
+ """
+ def __init__(self, inlined_data, inlined_files):
+ self.inlined_data = inlined_data
+ self.inlined_files = inlined_files
+
+def DoInline(
+ input_filename, grd_node, allow_external_script=False, names_only=False,
+ rewrite_function=None, filename_expansion_function=None):
+ """Helper function that inlines the resources in a specified file.
+
+ Reads input_filename, finds all the src attributes and attempts to
+ inline the files they are referring to, then returns the result and
+ the set of inlined files.
+
+ Args:
+ input_filename: name of file to read in
+ grd_node: html node from the grd file for this include tag
+ names_only: |nil| will be returned for the inlined contents (faster).
+ rewrite_function: function(filepath, text, distribution) which will be
+ called to rewrite html content before inlining images.
+ filename_expansion_function: function(filename) which will be called to
+ rewrite filenames before attempting to read them.
+ Returns:
+ a tuple of the inlined data as a string and the set of filenames
+ of all the inlined files
+ """
+ if filename_expansion_function:
+ input_filename = filename_expansion_function(input_filename)
+ input_filepath = os.path.dirname(input_filename)
+ distribution = GetDistribution()
+
+ # Keep track of all the files we inline.
+ inlined_files = set()
+
+ def SrcReplace(src_match, filepath=input_filepath,
+ inlined_files=inlined_files):
+ """Helper function to provide SrcInlineAsDataURL with the base file path"""
+ return SrcInlineAsDataURL(
+ src_match, filepath, distribution, inlined_files, names_only=names_only,
+ filename_expansion_function=filename_expansion_function)
+
+ def GetFilepath(src_match, base_path = input_filepath):
+ filename = src_match.group('filename')
+
+ if filename.find(':') != -1:
+ # filename is probably a URL, which we don't want to bother inlining
+ return None
+
+ filename = filename.replace('%DISTRIBUTION%', distribution)
+ if filename_expansion_function:
+ filename = filename_expansion_function(filename)
+ return os.path.normpath(os.path.join(base_path, filename))
+
+ def IsConditionSatisfied(src_match):
+ expression = src_match.group('expression')
+ return grd_node is None or grd_node.EvaluateCondition(expression)
+
+ def CheckConditionalElements(str):
+ """Helper function to conditionally inline inner elements"""
+ while True:
+ begin_if = _BEGIN_IF_BLOCK.search(str)
+ if begin_if is None:
+ return str
+
+ condition_satisfied = IsConditionSatisfied(begin_if)
+ leading = str[0:begin_if.start()]
+ content_start = begin_if.end()
+
+ # Find matching "if" block end.
+ count = 1
+ pos = begin_if.end()
+ while True:
+ end_if = _END_IF_BLOCK.search(str, pos)
+ if end_if is None:
+ raise Exception('Unmatched <if>')
+
+ next_if = _BEGIN_IF_BLOCK.search(str, pos)
+ if next_if is None or next_if.start() >= end_if.end():
+ count = count - 1
+ if count == 0:
+ break
+ pos = end_if.end()
+ else:
+ count = count + 1
+ pos = next_if.end()
+
+ content = str[content_start:end_if.start()]
+ trailing = str[end_if.end():]
+
+ if condition_satisfied:
+ str = leading + CheckConditionalElements(content) + trailing
+ else:
+ str = leading + trailing
+
+ def InlineFileContents(src_match, pattern, inlined_files=inlined_files):
+ """Helper function to inline external files of various types"""
+ filepath = GetFilepath(src_match)
+ if filepath is None:
+ return src_match.group(0)
+ inlined_files.add(filepath)
+
+ if names_only:
+ inlined_files.update(GetResourceFilenames(
+ filepath,
+ allow_external_script,
+ rewrite_function,
+ filename_expansion_function=filename_expansion_function))
+ return ""
+
+ return pattern % InlineToString(
+ filepath, grd_node, allow_external_script,
+ filename_expansion_function=filename_expansion_function)
+
+ def InlineIncludeFiles(src_match):
+ """Helper function to directly inline generic external files (without
+ wrapping them with any kind of tags).
+ """
+ return InlineFileContents(src_match, '%s')
+
+ def InlineScript(match):
+ """Helper function to inline external script files"""
+ attrs = (match.group('attrs1') + match.group('attrs2')).strip()
+ if attrs:
+ attrs = ' ' + attrs
+ return InlineFileContents(match, '<script' + attrs + '>%s</script>')
+
+ def InlineCSSText(text, css_filepath):
+ """Helper function that inlines external resources in CSS text"""
+ filepath = os.path.dirname(css_filepath)
+ # Allow custom modifications before inlining images.
+ if rewrite_function:
+ text = rewrite_function(filepath, text, distribution)
+ text = InlineCSSImages(text, filepath)
+ return InlineCSSImports(text, filepath)
+
+ def InlineCSSFile(src_match, pattern, base_path=input_filepath):
+ """Helper function to inline external CSS files.
+
+ Args:
+ src_match: A regular expression match with a named group named "filename".
+ pattern: The pattern to replace with the contents of the CSS file.
+ base_path: The base path to use for resolving the CSS file.
+
+ Returns:
+ The text that should replace the reference to the CSS file.
+ """
+ filepath = GetFilepath(src_match, base_path)
+ if filepath is None:
+ return src_match.group(0)
+
+ # Even if names_only is set, the CSS file needs to be opened, because it
+ # can link to images that need to be added to the file set.
+ inlined_files.add(filepath)
+ # When resolving CSS files we need to pass in the path so that relative URLs
+ # can be resolved.
+ return pattern % InlineCSSText(util.ReadFile(filepath, util.BINARY),
+ filepath)
+
+ def InlineCSSImages(text, filepath=input_filepath):
+ """Helper function that inlines external images in CSS backgrounds."""
+ # Replace contents of url() for css attributes: content, background,
+ # or *-image.
+ return re.sub('(content|background|[\w-]*-image):[^;]*' +
+ '(url\((?P<quote1>"|\'|)[^"\'()]*(?P=quote1)\)|' +
+ 'image-set\(' +
+ '([ ]*url\((?P<quote2>"|\'|)[^"\'()]*(?P=quote2)\)' +
+ '[ ]*[0-9.]*x[ ]*(,[ ]*)?)+\))',
+ lambda m: InlineCSSUrls(m, filepath),
+ text)
+
+ def InlineCSSUrls(src_match, filepath=input_filepath):
+ """Helper function that inlines each url on a CSS image rule match."""
+ # Replace contents of url() references in matches.
+ return re.sub('url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)(?P=quote)\)',
+ lambda m: SrcReplace(m, filepath),
+ src_match.group(0))
+
+ def InlineCSSImports(text, filepath=input_filepath):
+ """Helper function that inlines CSS files included via the @import
+ directive.
+ """
+ return re.sub('@import\s+url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)' +
+ '(?P=quote)\);',
+ lambda m: InlineCSSFile(m, '%s', filepath),
+ text)
+
+
+ flat_text = util.ReadFile(input_filename, util.BINARY)
+
+ # Check conditional elements, remove unsatisfied ones from the file. We do
+ # this twice. The first pass is so that we don't even bother calling
+ # InlineScript, InlineCSSFile and InlineIncludeFiles on text we're eventually
+ # going to throw out anyway.
+ flat_text = CheckConditionalElements(flat_text)
+
+ if not allow_external_script:
+ # We need to inline css and js before we inline images so that image
+ # references gets inlined in the css and js
+ flat_text = re.sub('<script (?P<attrs1>.*?)src="(?P<filename>[^"\']*)"' +
+ '(?P<attrs2>.*?)></script>',
+ InlineScript,
+ flat_text)
+
+ flat_text = _STYLESHEET_RE.sub(
+ lambda m: InlineCSSFile(m, '<style>%s</style>'),
+ flat_text)
+
+ flat_text = _INCLUDE_RE.sub(InlineIncludeFiles, flat_text)
+
+ # Check conditional elements, second pass. This catches conditionals in any
+ # of the text we just inlined.
+ flat_text = CheckConditionalElements(flat_text)
+
+ # Allow custom modifications before inlining images.
+ if rewrite_function:
+ flat_text = rewrite_function(input_filepath, flat_text, distribution)
+
+ flat_text = _SRC_RE.sub(SrcReplace, flat_text)
+
+ # TODO(arv): Only do this inside <style> tags.
+ flat_text = InlineCSSImages(flat_text)
+
+ flat_text = _ICON_RE.sub(SrcReplace, flat_text)
+
+ if names_only:
+ flat_text = None # Will contains garbage if the flag is set anyway.
+ return InlinedData(flat_text, inlined_files)
+
+
+def InlineToString(input_filename, grd_node, allow_external_script=False,
+ rewrite_function=None, filename_expansion_function=None):
+ """Inlines the resources in a specified file and returns it as a string.
+
+ Args:
+ input_filename: name of file to read in
+ grd_node: html node from the grd file for this include tag
+ Returns:
+ the inlined data as a string
+ """
+ try:
+ return DoInline(
+ input_filename,
+ grd_node,
+ allow_external_script=allow_external_script,
+ rewrite_function=rewrite_function,
+ filename_expansion_function=filename_expansion_function).inlined_data
+ except IOError, e:
+ raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
+ (e.filename, input_filename, e.strerror))
+
+
+def InlineToFile(input_filename, output_filename, grd_node):
+ """Inlines the resources in a specified file and writes it.
+
+ Reads input_filename, finds all the src attributes and attempts to
+ inline the files they are referring to, then writes the result
+ to output_filename.
+
+ Args:
+ input_filename: name of file to read in
+ output_filename: name of file to be written to
+ grd_node: html node from the grd file for this include tag
+ Returns:
+ a set of filenames of all the inlined files
+ """
+ inlined_data = InlineToString(input_filename, grd_node)
+ with open(output_filename, 'wb') as out_file:
+ out_file.writelines(inlined_data)
+
+
+def GetResourceFilenames(filename,
+ allow_external_script=False,
+ rewrite_function=None,
+ filename_expansion_function=None):
+ """For a grd file, returns a set of all the files that would be inline."""
+ try:
+ return DoInline(
+ filename,
+ None,
+ names_only=True,
+ allow_external_script=allow_external_script,
+ rewrite_function=rewrite_function,
+ filename_expansion_function=filename_expansion_function).inlined_files
+ except IOError, e:
+ raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
+ (e.filename, filename, e.strerror))
+
+
+def main():
+ if len(sys.argv) <= 2:
+ print "Flattens a HTML file by inlining its external resources.\n"
+ print "html_inline.py inputfile outputfile"
+ else:
+ InlineToFile(sys.argv[1], sys.argv[2], None)
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/grit/grit/format/html_inline_unittest.py b/chromium/tools/grit/grit/format/html_inline_unittest.py
new file mode 100755
index 00000000000..96d87502768
--- /dev/null
+++ b/chromium/tools/grit/grit/format/html_inline_unittest.py
@@ -0,0 +1,328 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.html_inline'''
+
+
+import os
+import re
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+
+from grit import util
+from grit.format import html_inline
+
+
+class HtmlInlineUnittest(unittest.TestCase):
+ '''Unit tests for HtmlInline.'''
+
+ def testGetResourceFilenames(self):
+ '''Tests that all included files are returned by GetResourceFilenames.'''
+
+ files = {
+ 'index.html': '''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <link rel="stylesheet" href="test.css">
+ <link rel="stylesheet"
+ href="really-long-long-long-long-long-test.css">
+ </head>
+ <body>
+ <include src="test.html">
+ <include
+ src="really-long-long-long-long-long-test-file-omg-so-long.html">
+ </body>
+ </html>
+ ''',
+
+ 'test.html': '''
+ <include src="test2.html">
+ ''',
+
+ 'really-long-long-long-long-long-test-file-omg-so-long.html': '''
+ <!-- This really long named resource should be included. -->
+ ''',
+
+ 'test2.html': '''
+ <!-- This second level resource should also be included. -->
+ ''',
+
+ 'test.css': '''
+ .image {
+ background: url('test.png');
+ }
+ ''',
+
+ 'really-long-long-long-long-long-test.css': '''
+ a:hover {
+ font-weight: bold; /* Awesome effect is awesome! */
+ }
+ ''',
+
+ 'test.png': 'PNG DATA',
+ }
+
+ source_resources = set()
+ tmp_dir = util.TempDir(files)
+ for filename in files:
+ source_resources.add(tmp_dir.GetPath(filename))
+
+ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'))
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+ tmp_dir.CleanUp()
+
+ def testCompressedJavaScript(self):
+ '''Tests that ".src=" doesn't treat as a tag.'''
+
+ files = {
+ 'index.js': '''
+ if(i<j)a.src="hoge.png";
+ ''',
+ }
+
+ source_resources = set()
+ tmp_dir = util.TempDir(files)
+ for filename in files:
+ source_resources.add(tmp_dir.GetPath(filename))
+
+ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.js'))
+ resources.add(tmp_dir.GetPath('index.js'))
+ self.failUnlessEqual(resources, source_resources)
+ tmp_dir.CleanUp()
+
+ def testInlineCSSImports(self):
+ '''Tests that @import directives in inlined CSS files are inlined too.
+ '''
+
+ files = {
+ 'index.html': '''
+ <html>
+ <head>
+ <link rel="stylesheet" href="css/test.css">
+ </head>
+ </html>
+ ''',
+
+ 'css/test.css': '''
+ @import url('test2.css');
+ blink {
+ display: none;
+ }
+ ''',
+
+ 'css/test2.css': '''
+ .image {
+ background: url('../images/test.png');
+ }
+ '''.strip(),
+
+ 'images/test.png': 'PNG DATA'
+ }
+
+ expected_inlined = '''
+ <html>
+ <head>
+ <style>
+ .image {
+ background: url('data:image/png;base64,UE5HIERBVEE=');
+ }
+ blink {
+ display: none;
+ }
+ </style>
+ </head>
+ </html>
+ '''
+
+ source_resources = set()
+ tmp_dir = util.TempDir(files)
+ for filename in files:
+ source_resources.add(tmp_dir.GetPath(util.normpath(filename)))
+
+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
+ resources = result.inlined_files
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+ self.failUnlessEqual(expected_inlined,
+ util.FixLineEnd(result.inlined_data, '\n'))
+
+ tmp_dir.CleanUp()
+
+ def testInlineCSSLinks(self):
+ '''Tests that only CSS files referenced via relative URLs are inlined.'''
+
+ files = {
+ 'index.html': '''
+ <html>
+ <head>
+ <link rel="stylesheet" href="foo.css">
+ <link rel="stylesheet" href="chrome://resources/bar.css">
+ </head>
+ </html>
+ ''',
+
+ 'foo.css': '''
+ @import url(chrome://resources/blurp.css);
+ blink {
+ display: none;
+ }
+ ''',
+ }
+
+ expected_inlined = '''
+ <html>
+ <head>
+ <style>
+ @import url(chrome://resources/blurp.css);
+ blink {
+ display: none;
+ }
+ </style>
+ <link rel="stylesheet" href="chrome://resources/bar.css">
+ </head>
+ </html>
+ '''
+
+ source_resources = set()
+ tmp_dir = util.TempDir(files)
+ for filename in files:
+ source_resources.add(tmp_dir.GetPath(filename))
+
+ result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
+ resources = result.inlined_files
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+ self.failUnlessEqual(expected_inlined,
+ util.FixLineEnd(result.inlined_data, '\n'))
+
+ def testFilenameVariableExpansion(self):
+ '''Tests that variables are expanded in filenames before inlining.'''
+
+ files = {
+ 'index.html': '''
+ <html>
+ <head>
+ <link rel="stylesheet" href="style[WHICH].css">
+ <script src="script[WHICH].js"></script>
+ </head>
+ <include src="tmpl[WHICH].html">
+ <img src="img[WHICH].png">
+ </html>
+ ''',
+ 'style1.css': '''h1 {}''',
+ 'tmpl1.html': '''<h1></h1>''',
+ 'script1.js': '''console.log('hello');''',
+ 'img1.png': '''abc''',
+ }
+
+ expected_inlined = '''
+ <html>
+ <head>
+ <style>h1 {}</style>
+ <script>console.log('hello');</script>
+ </head>
+ <h1></h1>
+ <img src="data:image/png;base64,YWJj">
+ </html>
+ '''
+
+ source_resources = set()
+ tmp_dir = util.TempDir(files)
+ for filename in files:
+ source_resources.add(tmp_dir.GetPath(filename))
+
+ def replacer(var, repl):
+ return lambda filename: filename.replace('[%s]' % var, repl)
+
+ # Test normal inlining.
+ result = html_inline.DoInline(
+ tmp_dir.GetPath('index.html'),
+ None,
+ filename_expansion_function=replacer('WHICH', '1'))
+ resources = result.inlined_files
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+ self.failUnlessEqual(expected_inlined,
+ util.FixLineEnd(result.inlined_data, '\n'))
+
+ # Test names-only inlining.
+ result = html_inline.DoInline(
+ tmp_dir.GetPath('index.html'),
+ None,
+ names_only=True,
+ filename_expansion_function=replacer('WHICH', '1'))
+ resources = result.inlined_files
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+
+ def testWithCloseTags(self):
+ '''Tests that close tags are removed.'''
+
+ files = {
+ 'index.html': '''
+ <html>
+ <head>
+ <link rel="stylesheet" href="style1.css"></link>
+ <link rel="stylesheet" href="style2.css">
+ </link>
+ <link rel="stylesheet" href="style2.css"
+ >
+ </link>
+ <script src="script1.js"></script>
+ </head>
+ <include src="tmpl1.html"></include>
+ <include src="tmpl2.html">
+ </include>
+ <include src="tmpl2.html"
+ >
+ </include>
+ <img src="img1.png">
+ </html>
+ ''',
+ 'style1.css': '''h1 {}''',
+ 'style2.css': '''h2 {}''',
+ 'tmpl1.html': '''<h1></h1>''',
+ 'tmpl2.html': '''<h2></h2>''',
+ 'script1.js': '''console.log('hello');''',
+ 'img1.png': '''abc''',
+ }
+
+ expected_inlined = '''
+ <html>
+ <head>
+ <style>h1 {}</style>
+ <style>h2 {}</style>
+ <style>h2 {}</style>
+ <script>console.log('hello');</script>
+ </head>
+ <h1></h1>
+ <h2></h2>
+ <h2></h2>
+ <img src="data:image/png;base64,YWJj">
+ </html>
+ '''
+
+ source_resources = set()
+ tmp_dir = util.TempDir(files)
+ for filename in files:
+ source_resources.add(tmp_dir.GetPath(filename))
+
+ # Test normal inlining.
+ result = html_inline.DoInline(
+ tmp_dir.GetPath('index.html'),
+ None)
+ resources = result.inlined_files
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+ self.failUnlessEqual(expected_inlined,
+ util.FixLineEnd(result.inlined_data, '\n'))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/js_map_format.py b/chromium/tools/grit/grit/format/js_map_format.py
new file mode 100644
index 00000000000..8cc8eb25e72
--- /dev/null
+++ b/chromium/tools/grit/grit/format/js_map_format.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Formats as a .js file using a map: <english text> -> <localized text>.
+"""
+
+import re
+
+from grit import util
+
+
+"""The required preamble for JS files."""
+_HEADER = '// This file is automatically generated by GRIT. Do not edit.\n'
+
+
+def Format(root, lang='en', output_dir='.'):
+ from grit.node import empty, message
+ yield _HEADER
+ for item in root.ActiveDescendants():
+ with item:
+ if isinstance(item, message.MessageNode):
+ yield _FormatMessage(item, lang)
+ elif isinstance(item, empty.MessagesNode):
+ yield '\n'
+
+
+def _FormatMessage(item, lang):
+ """Format a single message."""
+
+ en_message = item.ws_at_start + item.Translate('en') + item.ws_at_end
+ # Remove position numbers from placeholders.
+ en_message = re.sub(r'%\d\$([a-z])', r'%\1', en_message)
+ # Escape double quotes.
+ en_message = re.sub(r'\\', r'\\\\', en_message)
+ en_message = re.sub(r'"', r'\"', en_message)
+
+ loc_message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
+ # Escape double quotes.
+ loc_message = re.sub(r'\\', r'\\\\', loc_message)
+ loc_message = re.sub(r'"', r'\"', loc_message)
+
+ return '\nlocalizedStrings["%s"] = "%s";' % (en_message, loc_message)
diff --git a/chromium/tools/grit/grit/format/js_map_format_unittest.py b/chromium/tools/grit/grit/format/js_map_format_unittest.py
new file mode 100644
index 00000000000..cac0b2e953a
--- /dev/null
+++ b/chromium/tools/grit/grit/format/js_map_format_unittest.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unittest for js_map_format.py.
+"""
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit import util
+from grit.tool import build
+
+
+class JsMapFormatUnittest(unittest.TestCase):
+
+ def testMessages(self):
+ root = util.ParseGrdForUnittest(u"""
+ <messages>
+ <message name="IDS_SIMPLE_MESSAGE">
+ Simple message.
+ </message>
+ <message name="IDS_QUOTES">
+ element\u2019s \u201c<ph name="NAME">%s<ex>name</ex></ph>\u201d attribute
+ </message>
+ <message name="IDS_PLACEHOLDERS">
+ <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
+ </message>
+ <message name="IDS_STARTS_WITH_SPACE">
+ ''' (<ph name="COUNT">%d<ex>2</ex></ph>)
+ </message>
+ <message name="IDS_DOUBLE_QUOTES">
+ A "double quoted" message.
+ </message>
+ <message name="IDS_BACKSLASH">
+ \\
+ </message>
+ </messages>
+ """)
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('js_map_format', 'en'), buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ self.assertEqual(u"""\
+localizedStrings["Simple message."] = "Simple message.";
+localizedStrings["element\u2019s \u201c%s\u201d attribute"] = "element\u2019s \u201c%s\u201d attribute";
+localizedStrings["%d error, %d warning"] = "%1$d error, %2$d warning";
+localizedStrings[" (%d)"] = " (%d)";
+localizedStrings["A \\\"double quoted\\\" message."] = "A \\\"double quoted\\\" message.";
+localizedStrings["\\\\"] = "\\\\";""", output)
+
+ def testTranslations(self):
+ root = util.ParseGrdForUnittest("""
+ <messages>
+ <message name="ID_HELLO">Hello!</message>
+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
+ Joi</ex></ph></message>
+ </messages>
+ """)
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('js_map_format', 'fr'), buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ self.assertEqual(u"""\
+localizedStrings["Hello!"] = "H\xe9P\xe9ll\xf4P\xf4!";
+localizedStrings["Hello %s"] = "H\xe9P\xe9ll\xf4P\xf4 %s";\
+""", output)
+
+
+class DummyOutput(object):
+
+ def __init__(self, type, language):
+ self.type = type
+ self.language = language
+
+ def GetType(self):
+ return self.type
+
+ def GetLanguage(self):
+ return self.language
+
+ def GetOutputFilename(self):
+ return 'hello.gif'
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/PRESUBMIT.py b/chromium/tools/grit/grit/format/policy_templates/PRESUBMIT.py
new file mode 100644
index 00000000000..32a818dc150
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/PRESUBMIT.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+UNIT_TESTS = [
+ 'policy_template_generator_unittest',
+ 'writers.adm_writer_unittest',
+ 'writers.adml_writer_unittest',
+ 'writers.admx_writer_unittest',
+ 'writers.doc_writer_unittest',
+ 'writers.json_writer_unittest',
+ 'writers.plist_strings_writer_unittest',
+ 'writers.plist_writer_unittest',
+ 'writers.reg_writer_unittest',
+ 'writers.template_writer_unittest'
+]
+
+def CheckChangeOnUpload(input_api, output_api):
+ return input_api.canned_checks.RunPythonUnitTests(input_api,
+ output_api,
+ UNIT_TESTS)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return input_api.canned_checks.RunPythonUnitTests(input_api,
+ output_api,
+ UNIT_TESTS)
diff --git a/chromium/tools/grit/grit/format/policy_templates/__init__.py b/chromium/tools/grit/grit/format/policy_templates/__init__.py
new file mode 100644
index 00000000000..21cab6548be
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/__init__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Module grit.format.policy_templates
+'''
+
+pass
+
diff --git a/chromium/tools/grit/grit/format/policy_templates/policy_template_generator.py b/chromium/tools/grit/grit/format/policy_templates/policy_template_generator.py
new file mode 100644
index 00000000000..2540a729c33
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/policy_template_generator.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import copy
+import types
+
+
+class PolicyTemplateGenerator:
+ '''Generates template text for a particular platform.
+
+ This class is used to traverse a JSON structure from a .json template
+ definition metafile and merge GUI message string definitions that come
+ from a .grd resource tree onto it. After this, it can be used to output
+ this data to policy template files using TemplateWriter objects.
+ '''
+
+ def _ImportMessage(self, msg_txt):
+ msg_txt = msg_txt.decode('utf-8')
+ # Replace the placeholder of app name.
+ msg_txt = msg_txt.replace('$1', self._config['app_name'])
+ msg_txt = msg_txt.replace('$2', self._config['os_name'])
+ msg_txt = msg_txt.replace('$3', self._config['frame_name'])
+ # Strip spaces and escape newlines.
+ lines = msg_txt.split('\n')
+ lines = [line.strip() for line in lines]
+ return "\n".join(lines)
+
+ def __init__(self, config, policy_data):
+ '''Initializes this object with all the data necessary to output a
+ policy template.
+
+ Args:
+ messages: An identifier to string dictionary of all the localized
+ messages that might appear in the policy template.
+ policy_definitions: The list of defined policies and groups, as
+ parsed from the policy metafile. Note that this list is passed by
+ reference and its contents are modified.
+ See chrome/app/policy.policy_templates.json for description and
+ content.
+ '''
+ # List of all the policies:
+ self._policy_data = copy.deepcopy(policy_data)
+ # Localized messages to be inserted to the policy_definitions structure:
+ self._messages = self._policy_data['messages']
+ self._config = config
+ for key in self._messages.keys():
+ self._messages[key]['text'] = self._ImportMessage(
+ self._messages[key]['text'])
+ self._policy_definitions = self._policy_data['policy_definitions']
+ self._ProcessPolicyList(self._policy_definitions)
+
+ def _ProcessSupportedOn(self, supported_on):
+ '''Parses and converts the string items of the list of supported platforms
+ into dictionaries.
+
+ Args:
+ supported_on: The list of supported platforms. E.g.:
+ ['chrome.win:8-10', 'chrome_frame:10-']
+
+ Returns:
+ supported_on: The list with its items converted to dictionaries. E.g.:
+ [{
+ 'product': 'chrome',
+ 'platform': 'win',
+ 'since_version': '8',
+ 'until_version': '10'
+ }, {
+ 'product': 'chrome_frame',
+ 'platform': 'win',
+ 'since_version': '10',
+ 'until_version': ''
+ }]
+ '''
+ result = []
+ for supported_on_item in supported_on:
+ product_platform_part, version_part = supported_on_item.split(':')
+
+ # TODO(joaodasilva): enable parsing 'android' as a platform and including
+ # that platform in the generated documentation. Just skip it for now to
+ # prevent build failures.
+ if product_platform_part == 'android':
+ continue
+
+ if '.' in product_platform_part:
+ product, platform = product_platform_part.split('.')
+ if platform == '*':
+ # e.g.: 'chrome.*:8-10'
+ platforms = ['linux', 'mac', 'win']
+ else:
+ # e.g.: 'chrome.win:-10'
+ platforms = [platform]
+ else:
+ # e.g.: 'chrome_frame:7-'
+ product = product_platform_part
+ platform = {
+ 'chrome_os': 'chrome_os',
+ 'chrome_frame': 'win'
+ }[product]
+ platforms = [platform]
+ since_version, until_version = version_part.split('-')
+ result.append({
+ 'product': product,
+ 'platforms': platforms,
+ 'since_version': since_version,
+ 'until_version': until_version
+ })
+ return result
+
+ def _PrintPolicyValue(self, item):
+ '''Produces a string representation for a policy value. Taking care to print
+ dictionaries in a sorted order.'''
+ if type(item) == types.StringType:
+ str_val = "'%s'" % item
+ elif isinstance(item, dict):
+ str_val = "{";
+ for it in sorted(item.iterkeys()):
+ str_val += "\'%s\': %s, " % (it, self._PrintPolicyValue(item[it]))
+ str_val = str_val.rstrip(", ") + "}";
+ else:
+ str_val = str(item)
+ return str_val;
+
+ def _ProcessPolicy(self, policy):
+ '''Processes localized message strings in a policy or a group.
+ Also breaks up the content of 'supported_on' attribute into a list.
+
+ Args:
+ policy: The data structure of the policy or group, that will get message
+ strings here.
+ '''
+ policy['desc'] = self._ImportMessage(policy['desc'])
+ policy['caption'] = self._ImportMessage(policy['caption'])
+ if 'label' in policy:
+ policy['label'] = self._ImportMessage(policy['label'])
+
+ if policy['type'] == 'group':
+ self._ProcessPolicyList(policy['policies'])
+ elif policy['type'] in ('string-enum', 'int-enum'):
+ # Iterate through all the items of an enum-type policy, and add captions.
+ for item in policy['items']:
+ item['caption'] = self._ImportMessage(item['caption'])
+ elif policy['type'] == 'dict' and 'example_value' in policy:
+ policy['example_value'] = self._PrintPolicyValue(policy['example_value'])
+ if policy['type'] != 'group':
+ if not 'label' in policy:
+ # If 'label' is not specified, then it defaults to 'caption':
+ policy['label'] = policy['caption']
+ policy['supported_on'] = self._ProcessSupportedOn(
+ policy['supported_on'])
+
+ def _ProcessPolicyList(self, policy_list):
+ '''Adds localized message strings to each item in a list of policies and
+ groups. Also breaks up the content of 'supported_on' attributes into lists
+ of dictionaries.
+
+ Args:
+ policy_list: A list of policies and groups. Message strings will be added
+ for each item and to their child items, recursively.
+ '''
+ for policy in policy_list:
+ self._ProcessPolicy(policy)
+
+ def GetTemplateText(self, template_writer):
+ '''Generates the text of the template from the arguments given
+ to the constructor, using a given TemplateWriter.
+
+ Args:
+ template_writer: An object implementing TemplateWriter. Its methods
+ are called here for each item of self._policy_groups.
+
+ Returns:
+ The text of the generated template.
+ '''
+ return template_writer.WriteTemplate(self._policy_data)
diff --git a/chromium/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py b/chromium/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py
new file mode 100644
index 00000000000..f06cc2d2189
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/policy_template_generator_unittest.py
@@ -0,0 +1,372 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../..'))
+
+import unittest
+
+from grit.format.policy_templates import policy_template_generator
+from grit.format.policy_templates.writers import mock_writer
+from grit.format.policy_templates.writers import template_writer
+
+
+class PolicyTemplateGeneratorUnittest(unittest.TestCase):
+ '''Unit tests for policy_template_generator.py.'''
+
+ def do_test(self, policy_data, writer):
+ '''Executes a test case.
+
+ Creates and invokes an instance of PolicyTemplateGenerator with
+ the given arguments.
+
+ Notice: Plain comments are used in test methods instead of docstrings,
+ so that method names do not get overridden by the docstrings in the
+ test output.
+
+ Args:
+ policy_data: The list of policies and groups as it would be
+ loaded from policy_templates.json.
+ writer: A writer used for this test. It is usually derived from
+ mock_writer.MockWriter.
+ '''
+ writer.tester = self
+ config = {
+ 'app_name': '_app_name',
+ 'frame_name': '_frame_name',
+ 'os_name': '_os_name',
+ }
+ if not 'messages' in policy_data:
+ policy_data['messages'] = {}
+ if not 'placeholders' in policy_data:
+ policy_data['placeholders'] = []
+ if not 'policy_definitions' in policy_data:
+ policy_data['policy_definitions'] = []
+ policy_generator = policy_template_generator.PolicyTemplateGenerator(
+ config,
+ policy_data)
+ res = policy_generator.GetTemplateText(writer)
+ writer.Test()
+ return res
+
+ def testSequence(self):
+ # Test the sequence of invoking the basic PolicyWriter operations,
+ # in case of empty input data structures.
+ class LocalMockWriter(mock_writer.MockWriter):
+ def __init__(self):
+ self.log = 'init;'
+ def Init(self):
+ self.log += 'prepare;'
+ def BeginTemplate(self):
+ self.log += 'begin;'
+ def EndTemplate(self):
+ self.log += 'end;'
+ def GetTemplateText(self):
+ self.log += 'get_text;'
+ return 'writer_result_string'
+ def Test(self):
+ self.tester.assertEquals(self.log,
+ 'init;prepare;begin;end;get_text;')
+ result = self.do_test({}, LocalMockWriter())
+ self.assertEquals(result, 'writer_result_string')
+
+ def testEmptyGroups(self):
+ # Test that empty policy groups are not passed to the writer.
+ policies_mock = {
+ 'policy_definitions': [
+ {'name': 'Group1', 'type': 'group', 'policies': [],
+ 'desc': '', 'caption': ''},
+ {'name': 'Group2', 'type': 'group', 'policies': [],
+ 'desc': '', 'caption': ''},
+ {'name': 'Group3', 'type': 'group', 'policies': [],
+ 'desc': '', 'caption': ''},
+ ]
+ }
+ class LocalMockWriter(mock_writer.MockWriter):
+ def __init__(self):
+ self.log = ''
+ def BeginPolicyGroup(self, group):
+ self.log += '['
+ def EndPolicyGroup(self):
+ self.log += ']'
+ def Test(self):
+ self.tester.assertEquals(self.log, '')
+ self.do_test(policies_mock, LocalMockWriter())
+
+ def testGroups(self):
+ # Test that policy groups are passed to the writer in the correct order.
+ policies_mock = {
+ 'policy_definitions': [
+ {
+ 'name': 'Group1', 'type': 'group',
+ 'caption': '', 'desc': '',
+ 'policies': [{'name': 'TAG1', 'type': 'mock', 'supported_on': [],
+ 'caption': '', 'desc': ''}]
+ },
+ {
+ 'name': 'Group2', 'type': 'group',
+ 'caption': '', 'desc': '',
+ 'policies': [{'name': 'TAG2', 'type': 'mock', 'supported_on': [],
+ 'caption': '', 'desc': ''}]
+ },
+ {
+ 'name': 'Group3', 'type': 'group',
+ 'caption': '', 'desc': '',
+ 'policies': [{'name': 'TAG3', 'type': 'mock', 'supported_on': [],
+ 'caption': '', 'desc': ''}]
+ },
+ ]
+ }
+ class LocalMockWriter(mock_writer.MockWriter):
+ def __init__(self):
+ self.log = ''
+ def BeginPolicyGroup(self, group):
+ self.log += '[' + group['policies'][0]['name']
+ def EndPolicyGroup(self):
+ self.log += ']'
+ def Test(self):
+ self.tester.assertEquals(self.log, '[TAG1][TAG2][TAG3]')
+ self.do_test(policies_mock, LocalMockWriter())
+
+ def testPolicies(self):
+ # Test that policies are passed to the writer in the correct order.
+ policy_defs_mock = {
+ 'policy_definitions': [
+ {
+ 'name': 'Group1',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [
+ {'name': 'Group1Policy1', 'type': 'string', 'supported_on': [],
+ 'caption': '', 'desc': ''},
+ {'name': 'Group1Policy2', 'type': 'string', 'supported_on': [],
+ 'caption': '', 'desc': ''},
+ ]
+ },
+ {
+ 'name': 'Group2',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [
+ {'name': 'Group2Policy3', 'type': 'string', 'supported_on': [],
+ 'caption': '', 'desc': ''},
+ ]
+ }
+ ]
+ }
+ class LocalMockWriter(mock_writer.MockWriter):
+ def __init__(self):
+ self.policy_name = None
+ self.policy_list = []
+ def BeginPolicyGroup(self, group):
+ self.group = group;
+ def EndPolicyGroup(self):
+ self.group = None
+ def WritePolicy(self, policy):
+ self.tester.assertEquals(policy['name'][0:6], self.group['name'])
+ self.policy_list.append(policy['name'])
+ def Test(self):
+ self.tester.assertEquals(
+ self.policy_list,
+ ['Group1Policy1', 'Group1Policy2', 'Group2Policy3'])
+ self.do_test( policy_defs_mock, LocalMockWriter())
+
+ def testPolicyTexts(self):
+ # Test that GUI messages of policies all get placeholders replaced.
+ policy_data_mock = {
+ 'policy_definitions': [
+ {
+ 'name': 'Group1',
+ 'type': 'group',
+ 'desc': '',
+ 'caption': '',
+ 'policies': [
+ {
+ 'name': 'Policy1',
+ 'caption': '1. app_name -- $1',
+ 'label': '2. os_name -- $2',
+ 'desc': '3. frame_name -- $3',
+ 'type': 'string',
+ 'supported_on': []
+ },
+ ]
+ }
+ ]
+ }
+ class LocalMockWriter(mock_writer.MockWriter):
+ def WritePolicy(self, policy):
+ if policy['name'] == 'Policy1':
+ self.tester.assertEquals(policy['caption'],
+ '1. app_name -- _app_name')
+ self.tester.assertEquals(policy['label'],
+ '2. os_name -- _os_name')
+ self.tester.assertEquals(policy['desc'],
+ '3. frame_name -- _frame_name')
+ elif policy['name'] == 'Group1':
+ pass
+ else:
+ self.tester.fail()
+ self.do_test(policy_data_mock, LocalMockWriter())
+
+ def testIntEnumTexts(self):
+ # Test that GUI messages are assigned correctly to int-enums
+ # (aka dropdown menus).
+ policy_defs_mock = {
+ 'policy_definitions': [{
+ 'name': 'Policy1',
+ 'type': 'int-enum',
+ 'caption': '', 'desc': '',
+ 'supported_on': [],
+ 'items': [
+ {'name': 'item1', 'value': 0, 'caption': 'string1', 'desc': ''},
+ {'name': 'item2', 'value': 1, 'caption': 'string2', 'desc': ''},
+ {'name': 'item3', 'value': 3, 'caption': 'string3', 'desc': ''},
+ ]
+ }]
+ }
+
+ class LocalMockWriter(mock_writer.MockWriter):
+ def WritePolicy(self, policy):
+ self.tester.assertEquals(policy['items'][0]['caption'], 'string1')
+ self.tester.assertEquals(policy['items'][1]['caption'], 'string2')
+ self.tester.assertEquals(policy['items'][2]['caption'], 'string3')
+ self.do_test(policy_defs_mock, LocalMockWriter())
+
+ def testStringEnumTexts(self):
+ # Test that GUI messages are assigned correctly to string-enums
+ # (aka dropdown menus).
+ policy_data_mock = {
+ 'policy_definitions': [{
+ 'name': 'Policy1',
+ 'type': 'string-enum',
+ 'caption': '', 'desc': '',
+ 'supported_on': [],
+ 'items': [
+ {'name': 'item1', 'value': 'one', 'caption': 'string1', 'desc': ''},
+ {'name': 'item2', 'value': 'two', 'caption': 'string2', 'desc': ''},
+ {'name': 'item3', 'value': 'three', 'caption': 'string3', 'desc': ''},
+ ]
+ }]
+ }
+ class LocalMockWriter(mock_writer.MockWriter):
+ def WritePolicy(self, policy):
+ self.tester.assertEquals(policy['items'][0]['caption'], 'string1')
+ self.tester.assertEquals(policy['items'][1]['caption'], 'string2')
+ self.tester.assertEquals(policy['items'][2]['caption'], 'string3')
+ self.do_test(policy_data_mock, LocalMockWriter())
+
+ def testPolicyFiltering(self):
+ # Test that policies are filtered correctly based on their annotations.
+ policy_data_mock = {
+ 'policy_definitions': [
+ {
+ 'name': 'Group1',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [
+ {
+ 'name': 'Group1Policy1',
+ 'type': 'string',
+ 'caption': '',
+ 'desc': '',
+ 'supported_on': [
+ 'chrome.aaa:8-', 'chrome.bbb:8-', 'chrome.ccc:8-'
+ ]
+ },
+ {
+ 'name': 'Group1Policy2',
+ 'type': 'string',
+ 'caption': '',
+ 'desc': '',
+ 'supported_on': ['chrome.ddd:8-']
+ },
+ ]
+ }, {
+ 'name': 'Group2',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [
+ {
+ 'name': 'Group2Policy3',
+ 'type': 'string',
+ 'caption': '',
+ 'desc': '',
+ 'supported_on': ['chrome.eee:8-']
+ },
+ ]
+ }, {
+ 'name': 'SinglePolicy',
+ 'type': 'int',
+ 'caption': '',
+ 'desc': '',
+ 'supported_on': ['chrome.eee:8-']
+ }
+ ]
+ }
+ # This writer accumulates the list of policies it is asked to write.
+ # This list is stored in the result_list member variable and can
+ # be used later for assertions.
+ class LocalMockWriter(mock_writer.MockWriter):
+ def __init__(self, platforms):
+ self.platforms = platforms
+ self.policy_name = None
+ self.result_list = []
+ def BeginPolicyGroup(self, group):
+ self.group = group;
+ self.result_list.append('begin_' + group['name'])
+ def EndPolicyGroup(self):
+ self.result_list.append('end_group')
+ self.group = None
+ def WritePolicy(self, policy):
+ self.result_list.append(policy['name'])
+ def IsPolicySupported(self, policy):
+ # Call the original (non-mock) implementation of this method.
+ return template_writer.TemplateWriter.IsPolicySupported(self, policy)
+
+ local_mock_writer = LocalMockWriter(['eee'])
+ self.do_test(policy_data_mock, local_mock_writer)
+ # Test that only policies of platform 'eee' were written:
+ self.assertEquals(
+ local_mock_writer.result_list,
+ ['begin_Group2', 'Group2Policy3', 'end_group', 'SinglePolicy'])
+
+ local_mock_writer = LocalMockWriter(['ddd', 'bbb'])
+ self.do_test(policy_data_mock, local_mock_writer)
+ # Test that only policies of platforms 'ddd' and 'bbb' were written:
+ self.assertEquals(
+ local_mock_writer.result_list,
+ ['begin_Group1', 'Group1Policy1', 'Group1Policy2', 'end_group'])
+
+ def testSortingInvoked(self):
+ # Tests that policy-sorting happens before passing policies to the writer.
+ policy_data = {
+ 'policy_definitions': [
+ {'name': 'zp', 'type': 'string', 'supported_on': [],
+ 'caption': '', 'desc': ''},
+ {'name': 'ap', 'type': 'string', 'supported_on': [],
+ 'caption': '', 'desc': ''},
+ ]
+ }
+ class LocalMockWriter(mock_writer.MockWriter):
+ def __init__(self):
+ self.result_list = []
+ def WritePolicy(self, policy):
+ self.result_list.append(policy['name'])
+ def Test(self):
+ self.tester.assertEquals(
+ self.result_list,
+ ['ap', 'zp'])
+ self.do_test(policy_data, LocalMockWriter())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/template_formatter.py b/chromium/tools/grit/grit/format/policy_templates/template_formatter.py
new file mode 100644
index 00000000000..53b84ec0a7d
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/template_formatter.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+import sys
+from functools import partial
+
+from grit.format.policy_templates import policy_template_generator
+from grit.format.policy_templates import writer_configuration
+from grit.node import misc
+from grit.node import structure
+
+
+def GetFormatter(type):
+ return partial(_TemplateFormatter,
+ 'grit.format.policy_templates.writers.%s_writer' % type)
+
+
+def _TemplateFormatter(writer_module_name, root, lang, output_dir):
+ '''Creates a template file corresponding to an <output> node of the grit
+ tree.
+
+ More precisely, processes the whole grit tree for a given <output> node whose
+ type is one of adm, plist, plist_strings, admx, adml, doc, json, reg.
+ The result of processing is a policy template file with the given type and
+ language of the <output> node. This function does the interfacing with
+ grit, but the actual template-generating work is done in
+ policy_template_generator.PolicyTemplateGenerator.
+
+ Args:
+ writer_name: A string identifying the TemplateWriter subclass used
+ for generating the output.
+ root: the <grit> root node of the grit tree.
+ lang: the language of outputted text, e.g.: 'en'
+ output_dir: The output directory, currently unused here.
+
+ Yields the text of the template file.
+ '''
+ __import__(writer_module_name)
+ writer_module = sys.modules[writer_module_name]
+ config = writer_configuration.GetConfigurationForBuild(root.defines)
+ policy_data = _ParseGritNodes(root, lang)
+ policy_generator = \
+ policy_template_generator.PolicyTemplateGenerator(config, policy_data)
+ writer = writer_module.GetWriter(config)
+ yield policy_generator.GetTemplateText(writer)
+
+
+def _ParseGritNodes(root, lang):
+ '''Collects the necessary information from the grit tree:
+ the message strings and the policy definitions.
+
+ Args:
+ root: The root of the grit tree.
+ lang: the language of outputted text, e.g.: 'en'
+
+ Returns:
+ Policy data.
+ '''
+ policy_data = None
+ for item in root.ActiveDescendants():
+ with item:
+ if (isinstance(item, structure.StructureNode) and
+ item.attrs['type'] == 'policy_template_metafile'):
+ assert policy_data is None
+ json_text = item.gatherer.Translate(
+ lang,
+ pseudo_if_not_available=item.PseudoIsAllowed(),
+ fallback_to_english=item.ShouldFallbackToEnglish())
+ policy_data = eval(json_text)
+ return policy_data
diff --git a/chromium/tools/grit/grit/format/policy_templates/writer_configuration.py b/chromium/tools/grit/grit/format/policy_templates/writer_configuration.py
new file mode 100644
index 00000000000..00da0ccb98a
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writer_configuration.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+def GetConfigurationForBuild(defines):
+ '''Returns a configuration dictionary for the given build that contains
+ build-specific settings and information.
+
+ Args:
+ defines: Definitions coming from the build system.
+
+ Raises:
+ Exception: If 'defines' contains an unknown build-type.
+ '''
+ # The prefix of key names in config determines which writer will use their
+ # corresponding values:
+ # win: Both ADM and ADMX.
+ # mac: Only plist.
+ # admx: Only ADMX.
+ # none/other: Used by all the writers.
+ if '_chromium' in defines:
+ config = {
+ 'build': 'chromium',
+ 'app_name': 'Chromium',
+ 'frame_name': 'Chromium Frame',
+ 'os_name': 'Chromium OS',
+ 'win_reg_mandatory_key_name': 'Software\\Policies\\Chromium',
+ 'win_reg_recommended_key_name':
+ 'Software\\Policies\\Chromium\\Recommended',
+ 'win_mandatory_category_path': ['chromium'],
+ 'win_recommended_category_path': ['chromium_recommended'],
+ 'admx_namespace': 'Chromium.Policies.Chromium',
+ 'admx_prefix': 'chromium',
+ }
+ elif '_google_chrome' in defines:
+ config = {
+ 'build': 'chrome',
+ 'app_name': 'Google Chrome',
+ 'frame_name': 'Google Chrome Frame',
+ 'os_name': 'Google Chrome OS',
+ 'win_reg_mandatory_key_name': 'Software\\Policies\\Google\\Chrome',
+ 'win_reg_recommended_key_name':
+ 'Software\\Policies\\Google\\Chrome\\Recommended',
+ 'win_mandatory_category_path': ['google', 'googlechrome'],
+ 'win_recommended_category_path': ['google', 'googlechrome_recommended'],
+ 'admx_namespace': 'Google.Policies.Chrome',
+ 'admx_prefix': 'chrome',
+ }
+ else:
+ raise Exception('Unknown build')
+ config['win_group_policy_class'] = 'Both'
+ config['win_supported_os'] = 'SUPPORTED_WINXPSP2'
+ if 'mac_bundle_id' in defines:
+ config['mac_bundle_id'] = defines['mac_bundle_id']
+ return config
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/__init__.py b/chromium/tools/grit/grit/format/policy_templates/writers/__init__.py
new file mode 100644
index 00000000000..fe6d1395609
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/__init__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Module grit.format.policy_templates.writers
+'''
+
+pass
+
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/adm_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/adm_writer.py
new file mode 100644
index 00000000000..8536f01f083
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/adm_writer.py
@@ -0,0 +1,252 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from grit.format.policy_templates.writers import template_writer
+
+
+NEWLINE = '\r\n'
+
+
+def GetWriter(config):
+ '''Factory method for creating AdmWriter objects.
+ See the constructor of TemplateWriter for description of
+ arguments.
+ '''
+ return AdmWriter(['win'], config)
+
+
+class IndentedStringBuilder:
+ '''Utility class for building text with indented lines.'''
+
+ def __init__(self):
+ self.lines = []
+ self.indent = ''
+
+ def AddLine(self, string='', indent_diff=0):
+ '''Appends a string with indentation and a linebreak to |self.lines|.
+
+ Args:
+ string: The string to print.
+ indent_diff: the difference of indentation of the printed line,
+ compared to the next/previous printed line. Increment occurs
+ after printing the line, while decrement occurs before that.
+ '''
+ indent_diff *= 2
+ if indent_diff < 0:
+ self.indent = self.indent[(-indent_diff):]
+ if string != '':
+ self.lines.append(self.indent + string)
+ else:
+ self.lines.append('')
+ if indent_diff > 0:
+ self.indent += ''.ljust(indent_diff)
+
+ def AddLines(self, other):
+ '''Appends the content of another |IndentedStringBuilder| to |self.lines|.
+ Indentation of the added lines will be the sum of |self.indent| and
+ their original indentation.
+
+ Args:
+ other: The buffer from which lines are copied.
+ '''
+ for line in other.lines:
+ self.AddLine(line)
+
+ def ToString(self):
+ '''Returns |self.lines| as text string.'''
+ return NEWLINE.join(self.lines)
+
+
+class AdmWriter(template_writer.TemplateWriter):
+ '''Class for generating policy templates in Windows ADM format.
+ It is used by PolicyTemplateGenerator to write ADM files.
+ '''
+
+ TYPE_TO_INPUT = {
+ 'string': 'EDITTEXT',
+ 'int': 'NUMERIC',
+ 'string-enum': 'DROPDOWNLIST',
+ 'int-enum': 'DROPDOWNLIST',
+ 'list': 'LISTBOX',
+ 'dict': 'EDITTEXT'
+ }
+
+ def _AddGuiString(self, name, value):
+ # Escape newlines in the value.
+ value = value.replace('\n', '\\n')
+ if name in self.strings_seen:
+ err = ('%s was added as "%s" and now added again as "%s"' %
+ (name, self.strings_seen[name], value))
+ assert value == self.strings_seen[name], err
+ else:
+ self.strings_seen[name] = value
+ line = '%s="%s"' % (name, value)
+ self.strings.AddLine(line)
+
+ def _WriteSupported(self, builder):
+ builder.AddLine('#if version >= 4', 1)
+ builder.AddLine('SUPPORTED !!SUPPORTED_WINXPSP2')
+ builder.AddLine('#endif', -1)
+
+ def _WritePart(self, policy, key_name, builder):
+ '''Writes the PART ... END PART section of a policy.
+
+ Args:
+ policy: The policy to write to the output.
+ key_name: The registry key backing the policy.
+ builder: Builder to append lines to.
+ '''
+ policy_part_name = policy['name'] + '_Part'
+ self._AddGuiString(policy_part_name, policy['label'])
+
+ # Print the PART ... END PART section:
+ builder.AddLine()
+ adm_type = self.TYPE_TO_INPUT[policy['type']]
+ builder.AddLine('PART !!%s %s' % (policy_part_name, adm_type), 1)
+ if policy['type'] == 'list':
+ # Note that the following line causes FullArmor ADMX Migrator to create
+ # corrupt ADMX files. Please use admx_writer to get ADMX files.
+ builder.AddLine('KEYNAME "%s\\%s"' % (key_name, policy['name']))
+ builder.AddLine('VALUEPREFIX ""')
+ else:
+ builder.AddLine('VALUENAME "%s"' % policy['name'])
+ if policy['type'] == 'int':
+ # The default max for NUMERIC values is 9999 which is too small for us.
+ builder.AddLine('MIN 0 MAX 2000000000')
+ if policy['type'] in ('int-enum', 'string-enum'):
+ builder.AddLine('ITEMLIST', 1)
+ for item in policy['items']:
+ if policy['type'] == 'int-enum':
+ value_text = 'NUMERIC ' + str(item['value'])
+ else:
+ value_text = '"' + item['value'] + '"'
+ builder.AddLine('NAME !!%s_DropDown VALUE %s' %
+ (item['name'], value_text))
+ self._AddGuiString(item['name'] + '_DropDown', item['caption'])
+ builder.AddLine('END ITEMLIST', -1)
+ builder.AddLine('END PART', -1)
+
+ def _WritePolicy(self, policy, key_name, builder):
+ self._AddGuiString(policy['name'] + '_Policy', policy['caption'])
+ builder.AddLine('POLICY !!%s_Policy' % policy['name'], 1)
+ self._WriteSupported(builder)
+ policy_explain_name = policy['name'] + '_Explain'
+ self._AddGuiString(policy_explain_name, policy['desc'])
+ builder.AddLine('EXPLAIN !!' + policy_explain_name)
+
+ if policy['type'] == 'main':
+ builder.AddLine('VALUENAME "%s"' % policy['name'])
+ builder.AddLine('VALUEON NUMERIC 1')
+ builder.AddLine('VALUEOFF NUMERIC 0')
+ else:
+ self._WritePart(policy, key_name, builder)
+
+ builder.AddLine('END POLICY', -1)
+ builder.AddLine()
+
+ def WritePolicy(self, policy):
+ self._WritePolicy(policy,
+ self.config['win_reg_mandatory_key_name'],
+ self.policies)
+
+ def WriteRecommendedPolicy(self, policy):
+ self._WritePolicy(policy,
+ self.config['win_reg_recommended_key_name'],
+ self.recommended_policies)
+
+ def BeginPolicyGroup(self, group):
+ category_name = group['name'] + '_Category'
+ self._AddGuiString(category_name, group['caption'])
+ self.policies.AddLine('CATEGORY !!' + category_name, 1)
+
+ def EndPolicyGroup(self):
+ self.policies.AddLine('END CATEGORY', -1)
+ self.policies.AddLine('')
+
+ def BeginRecommendedPolicyGroup(self, group):
+ category_name = group['name'] + '_Category'
+ self._AddGuiString(category_name, group['caption'])
+ self.recommended_policies.AddLine('CATEGORY !!' + category_name, 1)
+
+ def EndRecommendedPolicyGroup(self):
+ self.recommended_policies.AddLine('END CATEGORY', -1)
+ self.recommended_policies.AddLine('')
+
+ def _CreateTemplate(self, category_path, key_name, policies):
+ '''Creates the whole ADM template except for the [Strings] section, and
+ returns it as an |IndentedStringBuilder|.
+
+ Args:
+ category_path: List of strings representing the category path.
+ key_name: Main registry key backing the policies.
+ policies: ADM code for all the policies in an |IndentedStringBuilder|.
+ '''
+ lines = IndentedStringBuilder()
+ for part in category_path:
+ lines.AddLine('CATEGORY !!' + part, 1)
+ lines.AddLine('KEYNAME "%s"' % key_name)
+ lines.AddLine()
+
+ lines.AddLines(policies)
+
+ for part in category_path:
+ lines.AddLine('END CATEGORY', -1)
+ lines.AddLine()
+
+ return lines
+
+ def BeginTemplate(self):
+ self._AddGuiString(self.config['win_supported_os'],
+ self.messages['win_supported_winxpsp2']['text'])
+ category_path = self.config['win_mandatory_category_path']
+ recommended_category_path = self.config['win_recommended_category_path']
+ recommended_name = '%s - %s' % \
+ (self.config['app_name'], self.messages['doc_recommended']['text'])
+ if self.config['build'] == 'chrome':
+ self._AddGuiString(category_path[0], 'Google')
+ self._AddGuiString(category_path[1], self.config['app_name'])
+ self._AddGuiString(recommended_category_path[1], recommended_name)
+ elif self.config['build'] == 'chromium':
+ self._AddGuiString(category_path[0], self.config['app_name'])
+ self._AddGuiString(recommended_category_path[0], recommended_name)
+ # All the policies will be written into self.policies.
+ # The final template text will be assembled into self.lines by
+ # self.EndTemplate().
+
+ def EndTemplate(self):
+ # Copy policies into self.lines.
+ policy_class = self.config['win_group_policy_class'].upper()
+ for class_name in ['MACHINE', 'USER']:
+ if policy_class != 'BOTH' and policy_class != class_name:
+ continue
+ self.lines.AddLine('CLASS ' + class_name, 1)
+ self.lines.AddLines(self._CreateTemplate(
+ self.config['win_mandatory_category_path'],
+ self.config['win_reg_mandatory_key_name'],
+ self.policies))
+ self.lines.AddLines(self._CreateTemplate(
+ self.config['win_recommended_category_path'],
+ self.config['win_reg_recommended_key_name'],
+ self.recommended_policies))
+ self.lines.AddLine('', -1)
+ # Copy user strings into self.lines.
+ self.lines.AddLine('[Strings]')
+ self.lines.AddLines(self.strings)
+
+ def Init(self):
+ # String buffer for building the whole ADM file.
+ self.lines = IndentedStringBuilder()
+ # String buffer for building the strings section of the ADM file.
+ self.strings = IndentedStringBuilder()
+ # Map of strings seen, to avoid duplicates.
+ self.strings_seen = {}
+ # String buffer for building the policies of the ADM file.
+ self.policies = IndentedStringBuilder()
+ # String buffer for building the recommended policies of the ADM file.
+ self.recommended_policies = IndentedStringBuilder()
+
+ def GetTemplateText(self):
+ return self.lines.ToString()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py
new file mode 100644
index 00000000000..49c31d8fa58
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/adm_writer_unittest.py
@@ -0,0 +1,844 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.policy_templates.writers.adm_writer'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+import unittest
+
+from grit.format.policy_templates.writers import writer_unittest_common
+
+
+class AdmWriterUnittest(writer_unittest_common.WriterUnittestCommon):
+ '''Unit tests for AdmWriter.'''
+
+ def ConstructOutput(self, classes, body, strings):
+ result = []
+ for clazz in classes:
+ result.append('CLASS ' + clazz)
+ result.append(body)
+ result.append(strings)
+ return ''.join(result)
+
+ def CompareOutputs(self, output, expected_output):
+ '''Compares the output of the adm_writer with its expected output.
+
+ Args:
+ output: The output of the adm writer as returned by grit.
+ expected_output: The expected output.
+
+ Raises:
+ AssertionError: if the two strings are not equivalent.
+ '''
+ self.assertEquals(
+ output.strip(),
+ expected_output.strip().replace('\n', '\r\n'))
+
+ def testEmpty(self):
+ # Test PListWriter in case of empty polices.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least "Windows 3.11', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_chromium': '1',}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!chromium
+ KEYNAME "Software\\Policies\\Chromium"
+
+ END CATEGORY
+
+ CATEGORY !!chromium_recommended
+ KEYNAME "Software\\Policies\\Chromium\\Recommended"
+
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least "Windows 3.11"
+chromium="Chromium"
+chromium_recommended="Chromium - Recommended"''')
+ self.CompareOutputs(output, expected_output)
+
+ def testMainPolicy(self):
+ # Tests a policy group with a single policy of type 'main'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'MainPolicy',
+ 'type': 'main',
+ 'supported_on': ['chrome.win:8-'],
+ 'features': { 'can_be_recommended': True },
+ 'caption': 'Caption of main.',
+ 'desc': 'Description of main.',
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.12', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!google
+ CATEGORY !!googlechrome
+ KEYNAME "Software\\Policies\\Google\\Chrome"
+
+ POLICY !!MainPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!MainPolicy_Explain
+ VALUENAME "MainPolicy"
+ VALUEON NUMERIC 1
+ VALUEOFF NUMERIC 0
+ END POLICY
+
+ END CATEGORY
+ END CATEGORY
+
+ CATEGORY !!google
+ CATEGORY !!googlechrome_recommended
+ KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
+
+ POLICY !!MainPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!MainPolicy_Explain
+ VALUENAME "MainPolicy"
+ VALUEON NUMERIC 1
+ VALUEOFF NUMERIC 0
+ END POLICY
+
+ END CATEGORY
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.12"
+google="Google"
+googlechrome="Google Chrome"
+googlechrome_recommended="Google Chrome - Recommended"
+MainPolicy_Policy="Caption of main."
+MainPolicy_Explain="Description of main."''')
+ self.CompareOutputs(output, expected_output)
+
+ def testStringPolicy(self):
+ # Tests a policy group with a single policy of type 'string'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'StringPolicy',
+ 'type': 'string',
+ 'supported_on': ['chrome.win:8-'],
+ 'features': { 'can_be_recommended': True },
+ 'desc': """Description of group.
+With a newline.""",
+ 'caption': 'Caption of policy.',
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.13', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!chromium
+ KEYNAME "Software\\Policies\\Chromium"
+
+ POLICY !!StringPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!StringPolicy_Explain
+
+ PART !!StringPolicy_Part EDITTEXT
+ VALUENAME "StringPolicy"
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+ CATEGORY !!chromium_recommended
+ KEYNAME "Software\\Policies\\Chromium\\Recommended"
+
+ POLICY !!StringPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!StringPolicy_Explain
+
+ PART !!StringPolicy_Part EDITTEXT
+ VALUENAME "StringPolicy"
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.13"
+chromium="Chromium"
+chromium_recommended="Chromium - Recommended"
+StringPolicy_Policy="Caption of policy."
+StringPolicy_Explain="Description of group.\\nWith a newline."
+StringPolicy_Part="Caption of policy."
+''')
+ self.CompareOutputs(output, expected_output)
+
+ def testIntPolicy(self):
+ # Tests a policy group with a single policy of type 'string'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'IntPolicy',
+ 'type': 'int',
+ 'caption': 'Caption of policy.',
+ 'features': { 'can_be_recommended': True },
+ 'desc': 'Description of policy.',
+ 'supported_on': ['chrome.win:8-']
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.13', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!chromium
+ KEYNAME "Software\\Policies\\Chromium"
+
+ POLICY !!IntPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!IntPolicy_Explain
+
+ PART !!IntPolicy_Part NUMERIC
+ VALUENAME "IntPolicy"
+ MIN 0 MAX 2000000000
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+ CATEGORY !!chromium_recommended
+ KEYNAME "Software\\Policies\\Chromium\\Recommended"
+
+ POLICY !!IntPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!IntPolicy_Explain
+
+ PART !!IntPolicy_Part NUMERIC
+ VALUENAME "IntPolicy"
+ MIN 0 MAX 2000000000
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.13"
+chromium="Chromium"
+chromium_recommended="Chromium - Recommended"
+IntPolicy_Policy="Caption of policy."
+IntPolicy_Explain="Description of policy."
+IntPolicy_Part="Caption of policy."
+''')
+ self.CompareOutputs(output, expected_output)
+
+ def testIntEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'int-enum'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'EnumPolicy',
+ 'type': 'int-enum',
+ 'items': [
+ {
+ 'name': 'ProxyServerDisabled',
+ 'value': 0,
+ 'caption': 'Option1',
+ },
+ {
+ 'name': 'ProxyServerAutoDetect',
+ 'value': 1,
+ 'caption': 'Option2',
+ },
+ ],
+ 'desc': 'Description of policy.',
+ 'caption': 'Caption of policy.',
+ 'supported_on': ['chrome.win:8-'],
+ 'features': { 'can_be_recommended': True },
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.14', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!google
+ CATEGORY !!googlechrome
+ KEYNAME "Software\\Policies\\Google\\Chrome"
+
+ POLICY !!EnumPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!EnumPolicy_Explain
+
+ PART !!EnumPolicy_Part DROPDOWNLIST
+ VALUENAME "EnumPolicy"
+ ITEMLIST
+ NAME !!ProxyServerDisabled_DropDown VALUE NUMERIC 0
+ NAME !!ProxyServerAutoDetect_DropDown VALUE NUMERIC 1
+ END ITEMLIST
+ END PART
+ END POLICY
+
+ END CATEGORY
+ END CATEGORY
+
+ CATEGORY !!google
+ CATEGORY !!googlechrome_recommended
+ KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
+
+ POLICY !!EnumPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!EnumPolicy_Explain
+
+ PART !!EnumPolicy_Part DROPDOWNLIST
+ VALUENAME "EnumPolicy"
+ ITEMLIST
+ NAME !!ProxyServerDisabled_DropDown VALUE NUMERIC 0
+ NAME !!ProxyServerAutoDetect_DropDown VALUE NUMERIC 1
+ END ITEMLIST
+ END PART
+ END POLICY
+
+ END CATEGORY
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.14"
+google="Google"
+googlechrome="Google Chrome"
+googlechrome_recommended="Google Chrome - Recommended"
+EnumPolicy_Policy="Caption of policy."
+EnumPolicy_Explain="Description of policy."
+EnumPolicy_Part="Caption of policy."
+ProxyServerDisabled_DropDown="Option1"
+ProxyServerAutoDetect_DropDown="Option2"
+''')
+ self.CompareOutputs(output, expected_output)
+
+ def testStringEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'int-enum'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'EnumPolicy',
+ 'type': 'string-enum',
+ 'caption': 'Caption of policy.',
+ 'desc': 'Description of policy.',
+ 'items': [
+ {'name': 'ProxyServerDisabled', 'value': 'one',
+ 'caption': 'Option1'},
+ {'name': 'ProxyServerAutoDetect', 'value': 'two',
+ 'caption': 'Option2'},
+ ],
+ 'supported_on': ['chrome.win:8-'],
+ 'features': { 'can_be_recommended': True },
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.14', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!google
+ CATEGORY !!googlechrome
+ KEYNAME "Software\\Policies\\Google\\Chrome"
+
+ POLICY !!EnumPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!EnumPolicy_Explain
+
+ PART !!EnumPolicy_Part DROPDOWNLIST
+ VALUENAME "EnumPolicy"
+ ITEMLIST
+ NAME !!ProxyServerDisabled_DropDown VALUE "one"
+ NAME !!ProxyServerAutoDetect_DropDown VALUE "two"
+ END ITEMLIST
+ END PART
+ END POLICY
+
+ END CATEGORY
+ END CATEGORY
+
+ CATEGORY !!google
+ CATEGORY !!googlechrome_recommended
+ KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
+
+ POLICY !!EnumPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!EnumPolicy_Explain
+
+ PART !!EnumPolicy_Part DROPDOWNLIST
+ VALUENAME "EnumPolicy"
+ ITEMLIST
+ NAME !!ProxyServerDisabled_DropDown VALUE "one"
+ NAME !!ProxyServerAutoDetect_DropDown VALUE "two"
+ END ITEMLIST
+ END PART
+ END POLICY
+
+ END CATEGORY
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.14"
+google="Google"
+googlechrome="Google Chrome"
+googlechrome_recommended="Google Chrome - Recommended"
+EnumPolicy_Policy="Caption of policy."
+EnumPolicy_Explain="Description of policy."
+EnumPolicy_Part="Caption of policy."
+ProxyServerDisabled_DropDown="Option1"
+ProxyServerAutoDetect_DropDown="Option2"
+''')
+ self.CompareOutputs(output, expected_output)
+
+ def testListPolicy(self):
+ # Tests a policy group with a single policy of type 'list'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'ListPolicy',
+ 'type': 'list',
+ 'supported_on': ['chrome.win:8-'],
+ 'features': { 'can_be_recommended': True },
+ 'desc': """Description of list policy.
+With a newline.""",
+ 'caption': 'Caption of list policy.',
+ 'label': 'Label of list policy.'
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.15', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ },
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!chromium
+ KEYNAME "Software\\Policies\\Chromium"
+
+ POLICY !!ListPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!ListPolicy_Explain
+
+ PART !!ListPolicy_Part LISTBOX
+ KEYNAME "Software\\Policies\\Chromium\\ListPolicy"
+ VALUEPREFIX ""
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+ CATEGORY !!chromium_recommended
+ KEYNAME "Software\\Policies\\Chromium\\Recommended"
+
+ POLICY !!ListPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!ListPolicy_Explain
+
+ PART !!ListPolicy_Part LISTBOX
+ KEYNAME "Software\\Policies\\Chromium\\Recommended\\ListPolicy"
+ VALUEPREFIX ""
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.15"
+chromium="Chromium"
+chromium_recommended="Chromium - Recommended"
+ListPolicy_Policy="Caption of list policy."
+ListPolicy_Explain="Description of list policy.\\nWith a newline."
+ListPolicy_Part="Label of list policy."
+''')
+ self.CompareOutputs(output, expected_output)
+
+ def testDictionaryPolicy(self):
+ # Tests a policy group with a single policy of type 'dict'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'DictionaryPolicy',
+ 'type': 'dict',
+ 'supported_on': ['chrome.win:8-'],
+ 'features': { 'can_be_recommended': True },
+ 'desc': 'Description of group.',
+ 'caption': 'Caption of policy.',
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.13', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!chromium
+ KEYNAME "Software\\Policies\\Chromium"
+
+ POLICY !!DictionaryPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!DictionaryPolicy_Explain
+
+ PART !!DictionaryPolicy_Part EDITTEXT
+ VALUENAME "DictionaryPolicy"
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+ CATEGORY !!chromium_recommended
+ KEYNAME "Software\\Policies\\Chromium\\Recommended"
+
+ POLICY !!DictionaryPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!DictionaryPolicy_Explain
+
+ PART !!DictionaryPolicy_Part EDITTEXT
+ VALUENAME "DictionaryPolicy"
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.13"
+chromium="Chromium"
+chromium_recommended="Chromium - Recommended"
+DictionaryPolicy_Policy="Caption of policy."
+DictionaryPolicy_Explain="Description of group."
+DictionaryPolicy_Part="Caption of policy."
+''')
+ self.CompareOutputs(output, expected_output)
+
+ def testNonSupportedPolicy(self):
+ # Tests a policy that is not supported on Windows, so it shouldn't
+ # be included in the ADM file.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'NonWinGroup',
+ 'type': 'group',
+ 'policies': [{
+ 'name': 'NonWinPolicy',
+ 'type': 'list',
+ 'supported_on': ['chrome.linux:8-', 'chrome.mac:8-'],
+ 'caption': 'Caption of list policy.',
+ 'desc': 'Desc of list policy.',
+ }],
+ 'caption': 'Group caption.',
+ 'desc': 'Group description.',
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.16', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!chromium
+ KEYNAME "Software\\Policies\\Chromium"
+
+ END CATEGORY
+
+ CATEGORY !!chromium_recommended
+ KEYNAME "Software\\Policies\\Chromium\\Recommended"
+
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.16"
+chromium="Chromium"
+chromium_recommended="Chromium - Recommended"
+''')
+ self.CompareOutputs(output, expected_output)
+
+ def testNonRecommendedPolicy(self):
+ # Tests a policy that is not recommended, so it should be included.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'MainPolicy',
+ 'type': 'main',
+ 'supported_on': ['chrome.win:8-'],
+ 'caption': 'Caption of main.',
+ 'desc': 'Description of main.',
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.12', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!google
+ CATEGORY !!googlechrome
+ KEYNAME "Software\\Policies\\Google\\Chrome"
+
+ POLICY !!MainPolicy_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!MainPolicy_Explain
+ VALUENAME "MainPolicy"
+ VALUEON NUMERIC 1
+ VALUEOFF NUMERIC 0
+ END POLICY
+
+ END CATEGORY
+ END CATEGORY
+
+ CATEGORY !!google
+ CATEGORY !!googlechrome_recommended
+ KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
+
+ END CATEGORY
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.12"
+google="Google"
+googlechrome="Google Chrome"
+googlechrome_recommended="Google Chrome - Recommended"
+MainPolicy_Policy="Caption of main."
+MainPolicy_Explain="Description of main."''')
+ self.CompareOutputs(output, expected_output)
+
+ def testPolicyGroup(self):
+ # Tests a policy group that has more than one policies.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'Group1',
+ 'type': 'group',
+ 'desc': 'Description of group.',
+ 'caption': 'Caption of group.',
+ 'policies': [{
+ 'name': 'Policy1',
+ 'type': 'list',
+ 'supported_on': ['chrome.win:8-'],
+ 'features': { 'can_be_recommended': True },
+ 'caption': 'Caption of policy1.',
+ 'desc': """Description of policy1.
+With a newline."""
+ },{
+ 'name': 'Policy2',
+ 'type': 'string',
+ 'supported_on': ['chrome.win:8-'],
+ 'caption': 'Caption of policy2.',
+ 'desc': """Description of policy2.
+With a newline."""
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'win_supported_winxpsp2': {
+ 'text': 'At least Windows 3.16', 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended', 'desc': 'bleh'
+ }
+ }
+ }''')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
+ expected_output = self.ConstructOutput(
+ ['MACHINE', 'USER'], '''
+ CATEGORY !!chromium
+ KEYNAME "Software\\Policies\\Chromium"
+
+ CATEGORY !!Group1_Category
+ POLICY !!Policy1_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!Policy1_Explain
+
+ PART !!Policy1_Part LISTBOX
+ KEYNAME "Software\\Policies\\Chromium\\Policy1"
+ VALUEPREFIX ""
+ END PART
+ END POLICY
+
+ POLICY !!Policy2_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!Policy2_Explain
+
+ PART !!Policy2_Part EDITTEXT
+ VALUENAME "Policy2"
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+ END CATEGORY
+
+ CATEGORY !!chromium_recommended
+ KEYNAME "Software\\Policies\\Chromium\\Recommended"
+
+ CATEGORY !!Group1_Category
+ POLICY !!Policy1_Policy
+ #if version >= 4
+ SUPPORTED !!SUPPORTED_WINXPSP2
+ #endif
+ EXPLAIN !!Policy1_Explain
+
+ PART !!Policy1_Part LISTBOX
+ KEYNAME "Software\\Policies\\Chromium\\Recommended\\Policy1"
+ VALUEPREFIX ""
+ END PART
+ END POLICY
+
+ END CATEGORY
+
+ END CATEGORY
+
+
+''', '''[Strings]
+SUPPORTED_WINXPSP2="At least Windows 3.16"
+chromium="Chromium"
+chromium_recommended="Chromium - Recommended"
+Group1_Category="Caption of group."
+Policy1_Policy="Caption of policy1."
+Policy1_Explain="Description of policy1.\\nWith a newline."
+Policy1_Part="Caption of policy1."
+Policy2_Policy="Caption of policy2."
+Policy2_Explain="Description of policy2.\\nWith a newline."
+Policy2_Part="Caption of policy2."
+''')
+ self.CompareOutputs(output, expected_output)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/adml_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/adml_writer.py
new file mode 100644
index 00000000000..5bd124ff4a0
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/adml_writer.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from xml.dom import minidom
+from grit.format.policy_templates.writers import xml_formatted_writer
+
+
+def GetWriter(config):
+ '''Factory method for instanciating the ADMLWriter. Every Writer needs a
+ GetWriter method because the TemplateFormatter uses this method to
+ instantiate a Writer.
+ '''
+ return ADMLWriter(['win'], config)
+
+
+class ADMLWriter(xml_formatted_writer.XMLFormattedWriter):
+ ''' Class for generating an ADML policy template. It is used by the
+ PolicyTemplateGenerator to write the ADML file.
+ '''
+
+ # DOM root node of the generated ADML document.
+ _doc = None
+
+ # The string-table contains all ADML "string" elements.
+ _string_table_elem = None
+
+ # The presentation-table is the container for presentation elements, that
+ # describe the presentation of Policy-Groups and Policies.
+ _presentation_table_elem = None
+
+ def _AddString(self, parent, id, text):
+ ''' Adds an ADML "string" element to the passed parent. The following
+ ADML snippet contains an example:
+
+ <string id="$(id)">$(text)</string>
+
+ Args:
+ parent: Parent element to which the new "string" element is added.
+ id: ID of the newly created "string" element.
+ text: Value of the newly created "string" element.
+ '''
+ string_elem = self.AddElement(parent, 'string', {'id': id})
+ string_elem.appendChild(self._doc.createTextNode(text))
+
+ def WritePolicy(self, policy):
+ '''Generates the ADML elements for a Policy.
+ <stringTable>
+ ...
+ <string id="$(policy_group_name)">$(caption)</string>
+ <string id="$(policy_group_name)_Explain">$(description)</string>
+ </stringTable>
+
+ <presentationTables>
+ ...
+ <presentation id=$(policy_group_name)/>
+ </presentationTables>
+
+ Args:
+ policy: The Policy to generate ADML elements for.
+ '''
+ policy_type = policy['type']
+ policy_name = policy['name']
+ if 'caption' in policy:
+ policy_caption = policy['caption']
+ else:
+ policy_caption = policy_name
+ if 'desc' in policy:
+ policy_description = policy['desc']
+ else:
+ policy_description = policy_name
+ if 'label' in policy:
+ policy_label = policy['label']
+ else:
+ policy_label = policy_name
+
+ self._AddString(self._string_table_elem, policy_name, policy_caption)
+ self._AddString(self._string_table_elem, policy_name + '_Explain',
+ policy_description)
+ presentation_elem = self.AddElement(
+ self._presentation_table_elem, 'presentation', {'id': policy_name})
+
+ if policy_type == 'main':
+ pass
+ elif policy_type in ('string', 'dict'):
+ # 'dict' policies are configured as JSON-encoded strings on Windows.
+ textbox_elem = self.AddElement(presentation_elem, 'textBox',
+ {'refId': policy_name})
+ label_elem = self.AddElement(textbox_elem, 'label')
+ label_elem.appendChild(self._doc.createTextNode(policy_label))
+ elif policy_type == 'int':
+ textbox_elem = self.AddElement(presentation_elem, 'decimalTextBox',
+ {'refId': policy_name})
+ textbox_elem.appendChild(self._doc.createTextNode(policy_label + ':'))
+ elif policy_type in ('int-enum', 'string-enum'):
+ for item in policy['items']:
+ self._AddString(self._string_table_elem, item['name'], item['caption'])
+ dropdownlist_elem = self.AddElement(presentation_elem, 'dropdownList',
+ {'refId': policy_name})
+ dropdownlist_elem.appendChild(self._doc.createTextNode(policy_label))
+ elif policy_type == 'list':
+ self._AddString(self._string_table_elem,
+ policy_name + 'Desc',
+ policy_caption)
+ listbox_elem = self.AddElement(presentation_elem, 'listBox',
+ {'refId': policy_name + 'Desc'})
+ listbox_elem.appendChild(self._doc.createTextNode(policy_label))
+ elif policy_type == 'group':
+ pass
+ else:
+ raise Exception('Unknown policy type %s.' % policy_type)
+
+ def BeginPolicyGroup(self, group):
+ '''Generates ADML elements for a Policy-Group. For each Policy-Group two
+ ADML "string" elements are added to the string-table. One contains the
+ caption of the Policy-Group and the other a description. A Policy-Group also
+ requires an ADML "presentation" element that must be added to the
+ presentation-table. The "presentation" element is the container for the
+ elements that define the visual presentation of the Policy-Goup's Policies.
+ The following ADML snippet shows an example:
+
+ Args:
+ group: The Policy-Group to generate ADML elements for.
+ '''
+ # Add ADML "string" elements to the string-table that are required by a
+ # Policy-Group.
+ self._AddString(self._string_table_elem, group['name'] + '_group',
+ group['caption'])
+
+ def _AddBaseStrings(self, string_table_elem, build):
+ ''' Adds ADML "string" elements to the string-table that are referenced by
+ the ADMX file but not related to any specific Policy-Group or Policy.
+ '''
+ self._AddString(string_table_elem, self.config['win_supported_os'],
+ self.messages['win_supported_winxpsp2']['text'])
+ recommended_name = '%s - %s' % \
+ (self.config['app_name'], self.messages['doc_recommended']['text'])
+ if build == 'chrome':
+ self._AddString(string_table_elem,
+ self.config['win_mandatory_category_path'][0],
+ 'Google')
+ self._AddString(string_table_elem,
+ self.config['win_mandatory_category_path'][1],
+ self.config['app_name'])
+ self._AddString(string_table_elem,
+ self.config['win_recommended_category_path'][1],
+ recommended_name)
+ elif build == 'chromium':
+ self._AddString(string_table_elem,
+ self.config['win_mandatory_category_path'][0],
+ self.config['app_name'])
+ self._AddString(string_table_elem,
+ self.config['win_recommended_category_path'][0],
+ recommended_name)
+
+ def BeginTemplate(self):
+ dom_impl = minidom.getDOMImplementation('')
+ self._doc = dom_impl.createDocument(None, 'policyDefinitionResources',
+ None)
+ policy_definitions_resources_elem = self._doc.documentElement
+ policy_definitions_resources_elem.attributes['revision'] = '1.0'
+ policy_definitions_resources_elem.attributes['schemaVersion'] = '1.0'
+
+ self.AddElement(policy_definitions_resources_elem, 'displayName')
+ self.AddElement(policy_definitions_resources_elem, 'description')
+ resources_elem = self.AddElement(policy_definitions_resources_elem,
+ 'resources')
+ self._string_table_elem = self.AddElement(resources_elem, 'stringTable')
+ self._AddBaseStrings(self._string_table_elem, self.config['build'])
+ self._presentation_table_elem = self.AddElement(resources_elem,
+ 'presentationTable')
+
+ def GetTemplateText(self):
+ # Using "toprettyxml()" confuses the Windows Group Policy Editor
+ # (gpedit.msc) because it interprets whitespace characters in text between
+ # the "string" tags. This prevents gpedit.msc from displaying the category
+ # names correctly.
+ # TODO(markusheintz): Find a better formatting that works with gpedit.
+ return self._doc.toxml()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py
new file mode 100644
index 00000000000..41757d92641
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/adml_writer_unittest.py
@@ -0,0 +1,329 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Unittests for grit.format.policy_templates.writers.adml_writer."""
+
+
+import os
+import sys
+import unittest
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+
+from grit.format.policy_templates.writers import adml_writer
+from grit.format.policy_templates.writers import xml_writer_base_unittest
+
+
+class AdmlWriterTest(xml_writer_base_unittest.XmlWriterBaseTest):
+
+ def setUp(self):
+ config = {
+ 'app_name': 'test',
+ 'build': 'test',
+ 'win_supported_os': 'SUPPORTED_TESTOS',
+ }
+ self.writer = adml_writer.GetWriter(config)
+ self.writer.messages = {
+ 'win_supported_winxpsp2': {
+ 'text': 'Supported on Test OS or higher',
+ 'desc': 'blah'
+ },
+ 'doc_recommended': {
+ 'text': 'Recommended',
+ 'desc': 'bleh'
+ },
+ }
+ self.writer.Init()
+
+ def _InitWriterForAddingPolicyGroups(self, writer):
+ '''Initialize the writer for adding policy groups. This method must be
+ called before the method "BeginPolicyGroup" can be called. It initializes
+ attributes of the writer.
+ '''
+ writer.BeginTemplate()
+
+ def _InitWriterForAddingPolicies(self, writer, policy):
+ '''Initialize the writer for adding policies. This method must be
+ called before the method "WritePolicy" can be called. It initializes
+ attributes of the writer.
+ '''
+ self._InitWriterForAddingPolicyGroups(writer)
+ policy_group = {
+ 'name': 'PolicyGroup',
+ 'caption': 'Test Caption',
+ 'desc': 'This is the test description of the test policy group.',
+ 'policies': policy,
+ }
+ writer.BeginPolicyGroup(policy_group)
+
+ string_elements = \
+ self.writer._string_table_elem.getElementsByTagName('string')
+ for elem in string_elements:
+ self.writer._string_table_elem.removeChild(elem)
+
+ def testEmpty(self):
+ self.writer.BeginTemplate()
+ self.writer.EndTemplate()
+ output = self.writer.GetTemplateText()
+ expected_output = (
+ '<?xml version="1.0" ?><policyDefinitionResources'
+ ' revision="1.0" schemaVersion="1.0"><displayName/><description/>'
+ '<resources><stringTable><string id="SUPPORTED_TESTOS">Supported on'
+ ' Test OS or higher</string></stringTable><presentationTable/>'
+ '</resources></policyDefinitionResources>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testPolicyGroup(self):
+ empty_policy_group = {
+ 'name': 'PolicyGroup',
+ 'caption': 'Test Group Caption',
+ 'desc': 'This is the test description of the test policy group.',
+ 'policies': [
+ {'name': 'PolicyStub2',
+ 'type': 'main'},
+ {'name': 'PolicyStub1',
+ 'type': 'main'},
+ ],
+ }
+ self._InitWriterForAddingPolicyGroups(self.writer)
+ self.writer.BeginPolicyGroup(empty_policy_group)
+ self.writer.EndPolicyGroup
+ # Assert generated string elements.
+ output = self.GetXMLOfChildren(self.writer._string_table_elem)
+ expected_output = (
+ '<string id="SUPPORTED_TESTOS">'
+ 'Supported on Test OS or higher</string>\n'
+ '<string id="PolicyGroup_group">Test Group Caption</string>')
+ self.AssertXMLEquals(output, expected_output)
+ # Assert generated presentation elements.
+ output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
+ expected_output = ''
+ self.AssertXMLEquals(output, expected_output)
+
+ def testMainPolicy(self):
+ main_policy = {
+ 'name': 'DummyMainPolicy',
+ 'type': 'main',
+ 'caption': 'Main policy caption',
+ 'desc': 'Main policy test description.'
+ }
+ self. _InitWriterForAddingPolicies(self.writer, main_policy)
+ self.writer.WritePolicy(main_policy)
+ # Assert generated string elements.
+ output = self.GetXMLOfChildren(self.writer._string_table_elem)
+ expected_output = (
+ '<string id="DummyMainPolicy">Main policy caption</string>\n'
+ '<string id="DummyMainPolicy_Explain">'
+ 'Main policy test description.</string>')
+ self.AssertXMLEquals(output, expected_output)
+ # Assert generated presentation elements.
+ output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
+ expected_output = '<presentation id="DummyMainPolicy"/>'
+ self.AssertXMLEquals(output, expected_output)
+
+ def testStringPolicy(self):
+ string_policy = {
+ 'name': 'StringPolicyStub',
+ 'type': 'string',
+ 'caption': 'String policy caption',
+ 'label': 'String policy label',
+ 'desc': 'This is a test description.',
+ }
+ self. _InitWriterForAddingPolicies(self.writer, string_policy)
+ self.writer.WritePolicy(string_policy)
+ # Assert generated string elements.
+ output = self.GetXMLOfChildren(self.writer._string_table_elem)
+ expected_output = (
+ '<string id="StringPolicyStub">String policy caption</string>\n'
+ '<string id="StringPolicyStub_Explain">'
+ 'This is a test description.</string>')
+ self.AssertXMLEquals(output, expected_output)
+ # Assert generated presentation elements.
+ output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
+ expected_output = (
+ '<presentation id="StringPolicyStub">\n'
+ ' <textBox refId="StringPolicyStub">\n'
+ ' <label>String policy label</label>\n'
+ ' </textBox>\n'
+ '</presentation>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testIntPolicy(self):
+ int_policy = {
+ 'name': 'IntPolicyStub',
+ 'type': 'int',
+ 'caption': 'Int policy caption',
+ 'label': 'Int policy label',
+ 'desc': 'This is a test description.',
+ }
+ self. _InitWriterForAddingPolicies(self.writer, int_policy)
+ self.writer.WritePolicy(int_policy)
+ # Assert generated string elements.
+ output = self.GetXMLOfChildren(self.writer._string_table_elem)
+ expected_output = (
+ '<string id="IntPolicyStub">Int policy caption</string>\n'
+ '<string id="IntPolicyStub_Explain">'
+ 'This is a test description.</string>')
+ self.AssertXMLEquals(output, expected_output)
+ # Assert generated presentation elements.
+ output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
+ expected_output = (
+ '<presentation id="IntPolicyStub">\n'
+ ' <decimalTextBox refId="IntPolicyStub">'
+ 'Int policy label:</decimalTextBox>\n'
+ '</presentation>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testIntEnumPolicy(self):
+ enum_policy = {
+ 'name': 'EnumPolicyStub',
+ 'type': 'int-enum',
+ 'caption': 'Enum policy caption',
+ 'label': 'Enum policy label',
+ 'desc': 'This is a test description.',
+ 'items': [
+ {
+ 'name': 'item 1',
+ 'value': 1,
+ 'caption': 'Caption Item 1',
+ },
+ {
+ 'name': 'item 2',
+ 'value': 2,
+ 'caption': 'Caption Item 2',
+ },
+ ],
+ }
+ self. _InitWriterForAddingPolicies(self.writer, enum_policy)
+ self.writer.WritePolicy(enum_policy)
+ # Assert generated string elements.
+ output = self.GetXMLOfChildren(self.writer._string_table_elem)
+ expected_output = (
+ '<string id="EnumPolicyStub">Enum policy caption</string>\n'
+ '<string id="EnumPolicyStub_Explain">'
+ 'This is a test description.</string>\n'
+ '<string id="item 1">Caption Item 1</string>\n'
+ '<string id="item 2">Caption Item 2</string>')
+ self.AssertXMLEquals(output, expected_output)
+ # Assert generated presentation elements.
+ output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
+ expected_output = (
+ '<presentation id="EnumPolicyStub">\n'
+ ' <dropdownList refId="EnumPolicyStub">'
+ 'Enum policy label</dropdownList>\n'
+ '</presentation>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testStringEnumPolicy(self):
+ enum_policy = {
+ 'name': 'EnumPolicyStub',
+ 'type': 'string-enum',
+ 'caption': 'Enum policy caption',
+ 'label': 'Enum policy label',
+ 'desc': 'This is a test description.',
+ 'items': [
+ {
+ 'name': 'item 1',
+ 'value': 'value 1',
+ 'caption': 'Caption Item 1',
+ },
+ {
+ 'name': 'item 2',
+ 'value': 'value 2',
+ 'caption': 'Caption Item 2',
+ },
+ ],
+ }
+ self. _InitWriterForAddingPolicies(self.writer, enum_policy)
+ self.writer.WritePolicy(enum_policy)
+ # Assert generated string elements.
+ output = self.GetXMLOfChildren(self.writer._string_table_elem)
+ expected_output = (
+ '<string id="EnumPolicyStub">Enum policy caption</string>\n'
+ '<string id="EnumPolicyStub_Explain">'
+ 'This is a test description.</string>\n'
+ '<string id="item 1">Caption Item 1</string>\n'
+ '<string id="item 2">Caption Item 2</string>')
+ self.AssertXMLEquals(output, expected_output)
+ # Assert generated presentation elements.
+ output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
+ expected_output = (
+ '<presentation id="EnumPolicyStub">\n'
+ ' <dropdownList refId="EnumPolicyStub">'
+ 'Enum policy label</dropdownList>\n'
+ '</presentation>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testListPolicy(self):
+ list_policy = {
+ 'name': 'ListPolicyStub',
+ 'type': 'list',
+ 'caption': 'List policy caption',
+ 'label': 'List policy label',
+ 'desc': 'This is a test description.',
+ }
+ self. _InitWriterForAddingPolicies(self.writer, list_policy)
+ self.writer.WritePolicy(list_policy)
+ # Assert generated string elements.
+ output = self.GetXMLOfChildren(self.writer._string_table_elem)
+ expected_output = (
+ '<string id="ListPolicyStub">List policy caption</string>\n'
+ '<string id="ListPolicyStub_Explain">'
+ 'This is a test description.</string>\n'
+ '<string id="ListPolicyStubDesc">List policy caption</string>')
+ self.AssertXMLEquals(output, expected_output)
+ # Assert generated presentation elements.
+ output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
+ expected_output = (
+ '<presentation id="ListPolicyStub">\n'
+ ' <listBox refId="ListPolicyStubDesc">List policy label</listBox>\n'
+ '</presentation>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testDictionaryPolicy(self):
+ dict_policy = {
+ 'name': 'DictionaryPolicyStub',
+ 'type': 'dict',
+ 'caption': 'Dictionary policy caption',
+ 'label': 'Dictionary policy label',
+ 'desc': 'This is a test description.',
+ }
+ self. _InitWriterForAddingPolicies(self.writer, dict_policy)
+ self.writer.WritePolicy(dict_policy)
+ # Assert generated string elements.
+ output = self.GetXMLOfChildren(self.writer._string_table_elem)
+ expected_output = (
+ '<string id="DictionaryPolicyStub">Dictionary policy caption</string>\n'
+ '<string id="DictionaryPolicyStub_Explain">'
+ 'This is a test description.</string>')
+ self.AssertXMLEquals(output, expected_output)
+ # Assert generated presentation elements.
+ output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
+ expected_output = (
+ '<presentation id="DictionaryPolicyStub">\n'
+ ' <textBox refId="DictionaryPolicyStub">\n'
+ ' <label>Dictionary policy label</label>\n'
+ ' </textBox>\n'
+ '</presentation>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testPlatform(self):
+ # Test that the writer correctly chooses policies of platform Windows.
+ self.assertTrue(self.writer.IsPolicySupported({
+ 'supported_on': [
+ {'platforms': ['win', 'zzz']}, {'platforms': ['aaa']}
+ ]
+ }))
+ self.assertFalse(self.writer.IsPolicySupported({
+ 'supported_on': [
+ {'platforms': ['mac', 'linux']}, {'platforms': ['aaa']}
+ ]
+ }))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/admx_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/admx_writer.py
new file mode 100644
index 00000000000..5ee4f0072ce
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/admx_writer.py
@@ -0,0 +1,372 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from xml.dom import minidom
+from grit.format.policy_templates.writers import xml_formatted_writer
+
+
+def GetWriter(config):
+ '''Factory method for instanciating the ADMXWriter. Every Writer needs a
+ GetWriter method because the TemplateFormatter uses this method to
+ instantiate a Writer.
+ '''
+ return ADMXWriter(['win'], config)
+
+
+class ADMXWriter(xml_formatted_writer.XMLFormattedWriter):
+ '''Class for generating an ADMX policy template. It is used by the
+ PolicyTemplateGenerator to write the admx file.
+ '''
+
+ # DOM root node of the generated ADMX document.
+ _doc = None
+
+ # The ADMX "policies" element that contains the ADMX "policy" elements that
+ # are generated.
+ _active_policies_elem = None
+
+ def _AdmlString(self, name):
+ '''Creates a reference to the named string in an ADML file.
+ Args:
+ name: Name of the referenced ADML string.
+ '''
+ return '$(string.' + name + ')'
+
+ def _AdmlStringExplain(self, name):
+ '''Creates a reference to the named explanation string in an ADML file.
+ Args:
+ name: Name of the referenced ADML explanation.
+ '''
+ return '$(string.' + name + '_Explain)'
+
+ def _AdmlPresentation(self, name):
+ '''Creates a reference to the named presentation element in an ADML file.
+ Args:
+ name: Name of the referenced ADML presentation element.
+ '''
+ return '$(presentation.' + name + ')'
+
+ def _AddPolicyNamespaces(self, parent, prefix, namespace):
+ '''Generates the ADMX "policyNamespace" element and adds the elements to the
+ passed parent element. The namespace of the generated ADMX document is
+ define via the ADMX "target" element. Used namespaces are declared with an
+ ADMX "using" element. ADMX "target" and "using" elements are children of the
+ ADMX "policyNamespace" element.
+
+ Args:
+ parent: The parent node to which all generated elements are added.
+ prefix: A logical name that can be used in the generated ADMX document to
+ refere to this namespace.
+ namespace: Namespace of the generated ADMX document.
+ '''
+ policy_namespaces_elem = self.AddElement(parent, 'policyNamespaces')
+ attributes = {
+ 'prefix': prefix,
+ 'namespace': namespace,
+ }
+ self.AddElement(policy_namespaces_elem, 'target', attributes)
+ attributes = {
+ 'prefix': 'windows',
+ 'namespace': 'Microsoft.Policies.Windows',
+ }
+ self.AddElement(policy_namespaces_elem, 'using', attributes)
+
+ def _AddCategory(self, parent, name, display_name,
+ parent_category_name=None):
+ '''Adds an ADMX category element to the passed parent node. The following
+ snippet shows an example of a category element where "chromium" is the value
+ of the parameter name:
+
+ <category displayName="$(string.chromium)" name="chromium"/>
+
+ Each parent node can have only one category with a given name. Adding the
+ same category again with the same attributes is ignored, but adding it
+ again with different attributes is an error.
+
+ Args:
+ parent: The parent node to which all generated elements are added.
+ name: Name of the category.
+ display_name: Display name of the category.
+ parent_category_name: Name of the parent category. Defaults to None.
+ '''
+ existing = filter(lambda e: e.getAttribute('name') == name,
+ parent.getElementsByTagName('category'))
+ if existing:
+ assert len(existing) == 1
+ assert existing[0].getAttribute('name') == name
+ assert existing[0].getAttribute('displayName') == display_name
+ return
+ attributes = {
+ 'name': name,
+ 'displayName': display_name,
+ }
+ category_elem = self.AddElement(parent, 'category', attributes)
+ if parent_category_name:
+ attributes = {'ref': parent_category_name}
+ self.AddElement(category_elem, 'parentCategory', attributes)
+
+ def _AddCategories(self, categories):
+ '''Generates the ADMX "categories" element and adds it to the categories
+ main node. The "categories" element defines the category for the policies
+ defined in this ADMX document. Here is an example of an ADMX "categories"
+ element:
+
+ <categories>
+ <category displayName="$(string.google)" name="google"/>
+ <category displayName="$(string.googlechrome)" name="googlechrome">
+ <parentCategory ref="google"/>
+ </category>
+ </categories>
+
+ Args:
+ categories_path: The categories path e.g. ['google', 'googlechrome']. For
+ each level in the path a "category" element will be generated. Except
+ for the root level, each level refers to its parent. Since the root
+ level category has no parent it does not require a parent reference.
+ '''
+ category_name = None
+ for category in categories:
+ parent_category_name = category_name
+ category_name = category
+ self._AddCategory(self._categories_elem, category_name,
+ self._AdmlString(category_name), parent_category_name)
+
+ def _AddSupportedOn(self, parent, supported_os):
+ '''Generates the "supportedOn" ADMX element and adds it to the passed
+ parent node. The "supportedOn" element contains information about supported
+ Windows OS versions. The following code snippet contains an example of a
+ "supportedOn" element:
+
+ <supportedOn>
+ <definitions>
+ <definition name="SUPPORTED_WINXPSP2"
+ displayName="$(string.SUPPORTED_WINXPSP2)"/>
+ </definitions>
+ ...
+ </supportedOn>
+
+ Args:
+ parent: The parent element to which all generated elements are added.
+ supported_os: List with all supported Win OSes.
+ '''
+ supported_on_elem = self.AddElement(parent, 'supportedOn')
+ definitions_elem = self.AddElement(supported_on_elem, 'definitions')
+ attributes = {
+ 'name': supported_os,
+ 'displayName': self._AdmlString(supported_os)
+ }
+ self.AddElement(definitions_elem, 'definition', attributes)
+
+ def _AddStringPolicy(self, parent, name):
+ '''Generates ADMX elements for a String-Policy and adds them to the
+ passed parent node.
+ '''
+ attributes = {
+ 'id': name,
+ 'valueName': name,
+ }
+ self.AddElement(parent, 'text', attributes)
+
+ def _AddIntPolicy(self, parent, name):
+ '''Generates ADMX elements for an Int-Policy and adds them to the passed
+ parent node.
+ '''
+ attributes = {
+ 'id': name,
+ 'valueName': name,
+ 'maxValue': '2000000000',
+ }
+ self.AddElement(parent, 'decimal', attributes)
+
+ def _AddEnumPolicy(self, parent, policy):
+ '''Generates ADMX elements for an Enum-Policy and adds them to the
+ passed parent element.
+ '''
+ name = policy['name']
+ items = policy['items']
+ attributes = {
+ 'id': name,
+ 'valueName': name,
+ }
+ enum_elem = self.AddElement(parent, 'enum', attributes)
+ for item in items:
+ attributes = {'displayName': self._AdmlString(item['name'])}
+ item_elem = self.AddElement(enum_elem, 'item', attributes)
+ value_elem = self.AddElement(item_elem, 'value')
+ value_string = str(item['value'])
+ if policy['type'] == 'int-enum':
+ self.AddElement(value_elem, 'decimal', {'value': value_string})
+ else:
+ self.AddElement(value_elem, 'string', {}, value_string)
+
+ def _AddListPolicy(self, parent, key, name):
+ '''Generates ADMX XML elements for a List-Policy and adds them to the
+ passed parent element.
+ '''
+ attributes = {
+ # The ID must be in sync with ID of the corresponding element in the ADML
+ # file.
+ 'id': name + 'Desc',
+ 'valuePrefix': '',
+ 'key': key + '\\' + name,
+ }
+ self.AddElement(parent, 'list', attributes)
+
+ def _AddMainPolicy(self, parent):
+ '''Generates ADMX elements for a Main-Policy amd adds them to the
+ passed parent element.
+ '''
+ enabled_value_elem = self.AddElement(parent, 'enabledValue');
+ self.AddElement(enabled_value_elem, 'decimal', {'value': '1'})
+ disabled_value_elem = self.AddElement(parent, 'disabledValue');
+ self.AddElement(disabled_value_elem, 'decimal', {'value': '0'})
+
+ def _GetElements(self, policy_group_elem):
+ '''Returns the ADMX "elements" child from an ADMX "policy" element. If the
+ "policy" element has no "elements" child yet, a new child is created.
+
+ Args:
+ policy_group_elem: The ADMX "policy" element from which the child element
+ "elements" is returned.
+
+ Raises:
+ Exception: The policy_group_elem does not contain a ADMX "policy" element.
+ '''
+ if policy_group_elem.tagName != 'policy':
+ raise Exception('Expected a "policy" element but got a "%s" element'
+ % policy_group_elem.tagName)
+ elements_list = policy_group_elem.getElementsByTagName('elements');
+ if len(elements_list) == 0:
+ return self.AddElement(policy_group_elem, 'elements')
+ elif len(elements_list) == 1:
+ return elements_list[0]
+ else:
+ raise Exception('There is supposed to be only one "elements" node but'
+ ' there are %s.' % str(len(elements_list)))
+
+ def _WritePolicy(self, policy, name, key, parent):
+ '''Generates AMDX elements for a Policy. There are four different policy
+ types: Main-Policy, String-Policy, Enum-Policy and List-Policy.
+ '''
+ policies_elem = self._active_policies_elem
+ policy_type = policy['type']
+ policy_name = policy['name']
+
+ attributes = {
+ 'name': name,
+ 'class': self.config['win_group_policy_class'],
+ 'displayName': self._AdmlString(policy_name),
+ 'explainText': self._AdmlStringExplain(policy_name),
+ 'presentation': self._AdmlPresentation(policy_name),
+ 'key': key,
+ }
+ # Store the current "policy" AMDX element in self for later use by the
+ # WritePolicy method.
+ policy_elem = self.AddElement(policies_elem, 'policy',
+ attributes)
+ self.AddElement(policy_elem, 'parentCategory',
+ {'ref': parent})
+ self.AddElement(policy_elem, 'supportedOn',
+ {'ref': self.config['win_supported_os']})
+ if policy_type == 'main':
+ self.AddAttribute(policy_elem, 'valueName', policy_name)
+ self._AddMainPolicy(policy_elem)
+ elif policy_type in ('string', 'dict'):
+ # 'dict' policies are configured as JSON-encoded strings on Windows.
+ parent = self._GetElements(policy_elem)
+ self._AddStringPolicy(parent, policy_name)
+ elif policy_type == 'int':
+ parent = self._GetElements(policy_elem)
+ self._AddIntPolicy(parent, policy_name)
+ elif policy_type in ('int-enum', 'string-enum'):
+ parent = self._GetElements(policy_elem)
+ self._AddEnumPolicy(parent, policy)
+ elif policy_type == 'list':
+ parent = self._GetElements(policy_elem)
+ self._AddListPolicy(parent, key, policy_name)
+ elif policy_type == 'group':
+ pass
+ else:
+ raise Exception('Unknown policy type %s.' % policy_type)
+
+ def WritePolicy(self, policy):
+ self._WritePolicy(policy,
+ policy['name'],
+ self.config['win_reg_mandatory_key_name'],
+ self._active_mandatory_policy_group_name)
+
+ def WriteRecommendedPolicy(self, policy):
+ self._WritePolicy(policy,
+ policy['name'] + '_recommended',
+ self.config['win_reg_recommended_key_name'],
+ self._active_recommended_policy_group_name)
+
+ def _BeginPolicyGroup(self, group, name, parent):
+ '''Generates ADMX elements for a Policy-Group.
+ '''
+ attributes = {
+ 'name': name,
+ 'displayName': self._AdmlString(group['name'] + '_group'),
+ }
+ category_elem = self.AddElement(self._categories_elem,
+ 'category',
+ attributes)
+ attributes = {
+ 'ref': parent
+ }
+ self.AddElement(category_elem, 'parentCategory', attributes)
+
+ def BeginPolicyGroup(self, group):
+ self._BeginPolicyGroup(group,
+ group['name'],
+ self.config['win_mandatory_category_path'][-1])
+ self._active_mandatory_policy_group_name = group['name']
+
+ def EndPolicyGroup(self):
+ self._active_mandatory_policy_group_name = \
+ self.config['win_mandatory_category_path'][-1]
+
+ def BeginRecommendedPolicyGroup(self, group):
+ self._BeginPolicyGroup(group,
+ group['name'] + '_recommended',
+ self.config['win_recommended_category_path'][-1])
+ self._active_recommended_policy_group_name = group['name'] + '_recommended'
+
+ def EndRecommendedPolicyGroup(self):
+ self._active_recommended_policy_group_name = \
+ self.config['win_recommended_category_path'][-1]
+
+ def BeginTemplate(self):
+ '''Generates the skeleton of the ADMX template. An ADMX template contains
+ an ADMX "PolicyDefinitions" element with four child nodes: "policies"
+ "policyNamspaces", "resources", "supportedOn" and "categories"
+ '''
+ dom_impl = minidom.getDOMImplementation('')
+ self._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
+ policy_definitions_elem = self._doc.documentElement
+
+ policy_definitions_elem.attributes['revision'] = '1.0'
+ policy_definitions_elem.attributes['schemaVersion'] = '1.0'
+
+ self._AddPolicyNamespaces(policy_definitions_elem,
+ self.config['admx_prefix'],
+ self.config['admx_namespace'])
+ self.AddElement(policy_definitions_elem, 'resources',
+ {'minRequiredRevision' : '1.0'})
+ self._AddSupportedOn(policy_definitions_elem,
+ self.config['win_supported_os'])
+ self._categories_elem = self.AddElement(policy_definitions_elem,
+ 'categories')
+ self._AddCategories(self.config['win_mandatory_category_path'])
+ self._AddCategories(self.config['win_recommended_category_path'])
+ self._active_policies_elem = self.AddElement(policy_definitions_elem,
+ 'policies')
+ self._active_mandatory_policy_group_name = \
+ self.config['win_mandatory_category_path'][-1]
+ self._active_recommended_policy_group_name = \
+ self.config['win_recommended_category_path'][-1]
+
+ def GetTemplateText(self):
+ return self.ToPrettyXml(self._doc)
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py
new file mode 100644
index 00000000000..9a2a58ee472
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/admx_writer_unittest.py
@@ -0,0 +1,411 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Unittests for grit.format.policy_templates.writers.admx_writer."""
+
+
+import os
+import sys
+import unittest
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+
+from grit.format.policy_templates.writers import admx_writer
+from grit.format.policy_templates.writers import xml_writer_base_unittest
+from xml.dom import minidom
+
+
+class AdmxWriterTest(xml_writer_base_unittest.XmlWriterBaseTest):
+
+ def _CreateDocumentElement(self):
+ dom_impl = minidom.getDOMImplementation('')
+ doc = dom_impl.createDocument(None, 'root', None)
+ return doc.documentElement
+
+ def setUp(self):
+ # Writer configuration. This dictionary contains parameter used by the ADMX
+ # Writer
+ config = {
+ 'win_group_policy_class': 'TestClass',
+ 'win_supported_os': 'SUPPORTED_TESTOS',
+ 'win_reg_mandatory_key_name': 'Software\\Policies\\Test',
+ 'win_reg_recommended_key_name': 'Software\\Policies\\Test\\Recommended',
+ 'win_mandatory_category_path': ['test_category'],
+ 'win_recommended_category_path': ['test_recommended_category'],
+ 'admx_namespace': 'ADMXWriter.Test.Namespace',
+ 'admx_prefix': 'test_prefix'
+ }
+ self.writer = admx_writer.GetWriter(config)
+ self.writer.Init()
+
+ def _GetPoliciesElement(self, doc):
+ node_list = doc.getElementsByTagName('policies')
+ self.assertTrue(node_list.length == 1)
+ return node_list.item(0)
+
+ def _GetCategoriesElement(self, doc):
+ node_list = doc.getElementsByTagName('categories')
+ self.assertTrue(node_list.length == 1)
+ return node_list.item(0)
+
+ def testEmpty(self):
+ self.writer.BeginTemplate()
+ self.writer.EndTemplate()
+
+ output = self.writer.GetTemplateText()
+ expected_output = (
+ '<?xml version="1.0" ?>\n'
+ '<policyDefinitions revision="1.0" schemaVersion="1.0">\n'
+ ' <policyNamespaces>\n'
+ ' <target namespace="ADMXWriter.Test.Namespace"'
+ ' prefix="test_prefix"/>\n'
+ ' <using namespace="Microsoft.Policies.Windows" prefix="windows"/>\n'
+ ' </policyNamespaces>\n'
+ ' <resources minRequiredRevision="1.0"/>\n'
+ ' <supportedOn>\n'
+ ' <definitions>\n'
+ ' <definition displayName="'
+ '$(string.SUPPORTED_TESTOS)" name="SUPPORTED_TESTOS"/>\n'
+ ' </definitions>\n'
+ ' </supportedOn>\n'
+ ' <categories>\n'
+ ' <category displayName="$(string.test_category)"'
+ ' name="test_category"/>\n'
+ ' <category displayName="$(string.test_recommended_category)"'
+ ' name="test_recommended_category"/>\n'
+ ' </categories>\n'
+ ' <policies/>\n'
+ '</policyDefinitions>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testEmptyPolicyGroup(self):
+ empty_policy_group = {
+ 'name': 'PolicyGroup',
+ 'policies': []
+ }
+ # Initialize writer to write a policy group.
+ self.writer.BeginTemplate()
+ # Write policy group
+ self.writer.BeginPolicyGroup(empty_policy_group)
+ self.writer.EndPolicyGroup()
+
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = ''
+ self.AssertXMLEquals(output, expected_output)
+
+ output = self.GetXMLOfChildren(
+ self._GetCategoriesElement(self.writer._doc))
+ expected_output = (
+ '<category displayName="$(string.test_category)"'
+ ' name="test_category"/>\n'
+ '<category displayName="$(string.test_recommended_category)"'
+ ' name="test_recommended_category"/>\n'
+ '<category displayName="$(string.PolicyGroup_group)"'
+ ' name="PolicyGroup">\n'
+ ' <parentCategory ref="test_category"/>\n'
+ '</category>')
+
+ self.AssertXMLEquals(output, expected_output)
+
+ def testPolicyGroup(self):
+ empty_policy_group = {
+ 'name': 'PolicyGroup',
+ 'policies': [
+ {'name': 'PolicyStub2',
+ 'type': 'main'},
+ {'name': 'PolicyStub1',
+ 'type': 'main'},
+ ]
+ }
+ # Initialize writer to write a policy group.
+ self.writer.BeginTemplate()
+ # Write policy group
+ self.writer.BeginPolicyGroup(empty_policy_group)
+ self.writer.EndPolicyGroup()
+
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = ''
+ self.AssertXMLEquals(output, expected_output)
+
+ output = self.GetXMLOfChildren(
+ self._GetCategoriesElement(self.writer._doc))
+ expected_output = (
+ '<category displayName="$(string.test_category)"'
+ ' name="test_category"/>\n'
+ '<category displayName="$(string.test_recommended_category)"'
+ ' name="test_recommended_category"/>\n'
+ '<category displayName="$(string.PolicyGroup_group)"'
+ ' name="PolicyGroup">\n'
+ ' <parentCategory ref="test_category"/>\n'
+ '</category>')
+ self.AssertXMLEquals(output, expected_output)
+
+
+ def _initWriterForPolicy(self, writer, policy):
+ '''Initializes the writer to write the given policy next.
+ '''
+ policy_group = {
+ 'name': 'PolicyGroup',
+ 'policies': [policy]
+ }
+ writer.BeginTemplate()
+ writer.BeginPolicyGroup(policy_group)
+
+ def testMainPolicy(self):
+ main_policy = {
+ 'name': 'DummyMainPolicy',
+ 'type': 'main',
+ }
+
+ self._initWriterForPolicy(self.writer, main_policy)
+
+ self.writer.WritePolicy(main_policy)
+
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = (
+ '<policy class="TestClass" displayName="$(string.DummyMainPolicy)"'
+ ' explainText="$(string.DummyMainPolicy_Explain)"'
+ ' key="Software\\Policies\\Test" name="DummyMainPolicy"'
+ ' presentation="$(presentation.DummyMainPolicy)"'
+ ' valueName="DummyMainPolicy">\n'
+ ' <parentCategory ref="PolicyGroup"/>\n'
+ ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+ ' <enabledValue>\n'
+ ' <decimal value="1"/>\n'
+ ' </enabledValue>\n'
+ ' <disabledValue>\n'
+ ' <decimal value="0"/>\n'
+ ' </disabledValue>\n'
+ '</policy>')
+
+ self.AssertXMLEquals(output, expected_output)
+
+ def testRecommendedPolicy(self):
+ main_policy = {
+ 'name': 'DummyMainPolicy',
+ 'type': 'main',
+ }
+
+ policy_group = {
+ 'name': 'PolicyGroup',
+ 'policies': [main_policy],
+ }
+ self.writer.BeginTemplate()
+ self.writer.BeginRecommendedPolicyGroup(policy_group)
+
+ self.writer.WriteRecommendedPolicy(main_policy)
+
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = (
+ '<policy class="TestClass" displayName="$(string.DummyMainPolicy)"'
+ ' explainText="$(string.DummyMainPolicy_Explain)"'
+ ' key="Software\\Policies\\Test\\Recommended"'
+ ' name="DummyMainPolicy_recommended"'
+ ' presentation="$(presentation.DummyMainPolicy)"'
+ ' valueName="DummyMainPolicy">\n'
+ ' <parentCategory ref="PolicyGroup_recommended"/>\n'
+ ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+ ' <enabledValue>\n'
+ ' <decimal value="1"/>\n'
+ ' </enabledValue>\n'
+ ' <disabledValue>\n'
+ ' <decimal value="0"/>\n'
+ ' </disabledValue>\n'
+ '</policy>')
+
+ self.AssertXMLEquals(output, expected_output)
+
+ def testStringPolicy(self):
+ string_policy = {
+ 'name': 'SampleStringPolicy',
+ 'type': 'string',
+ }
+ self._initWriterForPolicy(self.writer, string_policy)
+
+ self.writer.WritePolicy(string_policy)
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = (
+ '<policy class="TestClass" displayName="$(string.SampleStringPolicy)"'
+ ' explainText="$(string.SampleStringPolicy_Explain)"'
+ ' key="Software\\Policies\\Test" name="SampleStringPolicy"'
+ ' presentation="$(presentation.SampleStringPolicy)">\n'
+ ' <parentCategory ref="PolicyGroup"/>\n'
+ ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+ ' <elements>\n'
+ ' <text id="SampleStringPolicy" valueName="SampleStringPolicy"/>\n'
+ ' </elements>\n'
+ '</policy>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testIntPolicy(self):
+ int_policy = {
+ 'name': 'SampleIntPolicy',
+ 'type': 'int',
+ }
+ self._initWriterForPolicy(self.writer, int_policy)
+
+ self.writer.WritePolicy(int_policy)
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = (
+ '<policy class="TestClass" displayName="$(string.SampleIntPolicy)"'
+ ' explainText="$(string.SampleIntPolicy_Explain)"'
+ ' key="Software\\Policies\\Test" name="SampleIntPolicy"'
+ ' presentation="$(presentation.SampleIntPolicy)">\n'
+ ' <parentCategory ref="PolicyGroup"/>\n'
+ ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+ ' <elements>\n'
+ ' <decimal id="SampleIntPolicy" maxValue="2000000000" '
+ 'valueName="SampleIntPolicy"/>\n'
+ ' </elements>\n'
+ '</policy>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testIntEnumPolicy(self):
+ enum_policy = {
+ 'name': 'SampleEnumPolicy',
+ 'type': 'int-enum',
+ 'items': [
+ {'name': 'item_1', 'value': 0},
+ {'name': 'item_2', 'value': 1},
+ ]
+ }
+
+ self._initWriterForPolicy(self.writer, enum_policy)
+ self.writer.WritePolicy(enum_policy)
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = (
+ '<policy class="TestClass" displayName="$(string.SampleEnumPolicy)"'
+ ' explainText="$(string.SampleEnumPolicy_Explain)"'
+ ' key="Software\\Policies\\Test" name="SampleEnumPolicy"'
+ ' presentation="$(presentation.SampleEnumPolicy)">\n'
+ ' <parentCategory ref="PolicyGroup"/>\n'
+ ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+ ' <elements>\n'
+ ' <enum id="SampleEnumPolicy" valueName="SampleEnumPolicy">\n'
+ ' <item displayName="$(string.item_1)">\n'
+ ' <value>\n'
+ ' <decimal value="0"/>\n'
+ ' </value>\n'
+ ' </item>\n'
+ ' <item displayName="$(string.item_2)">\n'
+ ' <value>\n'
+ ' <decimal value="1"/>\n'
+ ' </value>\n'
+ ' </item>\n'
+ ' </enum>\n'
+ ' </elements>\n'
+ '</policy>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testStringEnumPolicy(self):
+ enum_policy = {
+ 'name': 'SampleEnumPolicy',
+ 'type': 'string-enum',
+ 'items': [
+ {'name': 'item_1', 'value': 'one'},
+ {'name': 'item_2', 'value': 'two'},
+ ]
+ }
+
+ # This test is different than the others because it also tests that space
+ # usage inside <string> nodes is correct.
+ dom_impl = minidom.getDOMImplementation('')
+ self.writer._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
+ self.writer._active_policies_elem = self.writer._doc.documentElement
+ self.writer._active_mandatory_policy_group_name = 'PolicyGroup'
+ self.writer.WritePolicy(enum_policy)
+ output = self.writer.GetTemplateText()
+ expected_output = (
+ '<?xml version="1.0" ?>\n'
+ '<policyDefinitions>\n'
+ ' <policy class="TestClass" displayName="$(string.SampleEnumPolicy)"'
+ ' explainText="$(string.SampleEnumPolicy_Explain)"'
+ ' key="Software\\Policies\\Test" name="SampleEnumPolicy"'
+ ' presentation="$(presentation.SampleEnumPolicy)">\n'
+ ' <parentCategory ref="PolicyGroup"/>\n'
+ ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+ ' <elements>\n'
+ ' <enum id="SampleEnumPolicy" valueName="SampleEnumPolicy">\n'
+ ' <item displayName="$(string.item_1)">\n'
+ ' <value>\n'
+ ' <string>one</string>\n'
+ ' </value>\n'
+ ' </item>\n'
+ ' <item displayName="$(string.item_2)">\n'
+ ' <value>\n'
+ ' <string>two</string>\n'
+ ' </value>\n'
+ ' </item>\n'
+ ' </enum>\n'
+ ' </elements>\n'
+ ' </policy>\n'
+ '</policyDefinitions>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testListPolicy(self):
+ list_policy = {
+ 'name': 'SampleListPolicy',
+ 'type': 'list',
+ }
+ self._initWriterForPolicy(self.writer, list_policy)
+ self.writer.WritePolicy(list_policy)
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = (
+ '<policy class="TestClass" displayName="$(string.SampleListPolicy)"'
+ ' explainText="$(string.SampleListPolicy_Explain)"'
+ ' key="Software\\Policies\\Test" name="SampleListPolicy"'
+ ' presentation="$(presentation.SampleListPolicy)">\n'
+ ' <parentCategory ref="PolicyGroup"/>\n'
+ ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+ ' <elements>\n'
+ ' <list id="SampleListPolicyDesc"'
+ ' key="Software\Policies\Test\SampleListPolicy" valuePrefix=""/>\n'
+ ' </elements>\n'
+ '</policy>')
+
+ self.AssertXMLEquals(output, expected_output)
+
+ def testDictionaryPolicy(self):
+ dict_policy = {
+ 'name': 'SampleDictionaryPolicy',
+ 'type': 'dict',
+ }
+ self._initWriterForPolicy(self.writer, dict_policy)
+
+ self.writer.WritePolicy(dict_policy)
+ output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
+ expected_output = (
+ '<policy class="TestClass" displayName="$(string.'
+ 'SampleDictionaryPolicy)"'
+ ' explainText="$(string.SampleDictionaryPolicy_Explain)"'
+ ' key="Software\\Policies\\Test" name="SampleDictionaryPolicy"'
+ ' presentation="$(presentation.SampleDictionaryPolicy)">\n'
+ ' <parentCategory ref="PolicyGroup"/>\n'
+ ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
+ ' <elements>\n'
+ ' <text id="SampleDictionaryPolicy" '
+ 'valueName="SampleDictionaryPolicy"/>\n'
+ ' </elements>\n'
+ '</policy>')
+ self.AssertXMLEquals(output, expected_output)
+
+ def testPlatform(self):
+ # Test that the writer correctly chooses policies of platform Windows.
+ self.assertTrue(self.writer.IsPolicySupported({
+ 'supported_on': [
+ {'platforms': ['win', 'zzz']}, {'platforms': ['aaa']}
+ ]
+ }))
+ self.assertFalse(self.writer.IsPolicySupported({
+ 'supported_on': [
+ {'platforms': ['mac', 'linux']}, {'platforms': ['aaa']}
+ ]
+ }))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/doc_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/doc_writer.py
new file mode 100644
index 00000000000..3876fafec5c
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/doc_writer.py
@@ -0,0 +1,654 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from xml.dom import minidom
+from grit import lazy_re
+from grit.format.policy_templates.writers import xml_formatted_writer
+
+
+def GetWriter(config):
+ '''Factory method for creating DocWriter objects.
+ See the constructor of TemplateWriter for description of
+ arguments.
+ '''
+ return DocWriter(['*'], config)
+
+
+class DocWriter(xml_formatted_writer.XMLFormattedWriter):
+ '''Class for generating policy templates in HTML format.
+ The intended use of the generated file is to upload it on
+ http://dev.chromium.org, therefore its format has some limitations:
+ - No HTML and body tags.
+ - Restricted set of element attributes: for example no 'class'.
+ Because of the latter the output is styled using the 'style'
+ attributes of HTML elements. This is supported by the dictionary
+ self._STYLES[] and the method self._AddStyledElement(), they try
+ to mimic the functionality of CSS classes. (But without inheritance.)
+
+ This class is invoked by PolicyTemplateGenerator to create the HTML
+ files.
+ '''
+
+ def _GetLocalizedMessage(self, msg_id):
+ '''Returns a localized message for this writer.
+
+ Args:
+ msg_id: The identifier of the message.
+
+ Returns:
+ The localized message.
+ '''
+ return self.messages['doc_' + msg_id]['text']
+
+ def _MapListToString(self, item_map, items):
+ '''Creates a comma-separated list.
+
+ Args:
+ item_map: A dictionary containing all the elements of 'items' as
+ keys.
+ items: A list of arbitrary items.
+
+ Returns:
+ Looks up each item of 'items' in 'item_maps' and concatenates the
+ resulting items into a comma-separated list.
+ '''
+ return ', '.join([item_map[x] for x in items])
+
+ def _AddTextWithLinks(self, parent, text):
+ '''Parse a string for URLs and add it to a DOM node with the URLs replaced
+ with <a> HTML links.
+
+ Args:
+ parent: The DOM node to which the text will be added.
+ text: The string to be added.
+ '''
+ # Iterate through all the URLs and replace them with links.
+ out = []
+ while True:
+ # Look for the first URL.
+ res = self._url_matcher.search(text)
+ if not res:
+ break
+ # Calculate positions of the substring of the URL.
+ url = res.group(0)
+ start = res.start(0)
+ end = res.end(0)
+ # Add the text prior to the URL.
+ self.AddText(parent, text[:start])
+ # Add a link for the URL.
+ self.AddElement(parent, 'a', {'href': url}, url)
+ # Drop the part of text that is added.
+ text = text[end:]
+ self.AddText(parent, text)
+
+
+ def _AddStyledElement(self, parent, name, style_ids, attrs=None, text=None):
+ '''Adds an XML element to a parent, with CSS style-sheets included.
+
+ Args:
+ parent: The parent DOM node.
+ name: Name of the element to add.
+ style_ids: A list of CSS style strings from self._STYLE[].
+ attrs: Dictionary of attributes for the element.
+ text: Text content for the element.
+ '''
+ if attrs == None:
+ attrs = {}
+
+ style = ''.join([self._STYLE[x] for x in style_ids])
+ if style != '':
+ # Apply the style specified by style_ids.
+ attrs['style'] = style + attrs.get('style', '')
+ return self.AddElement(parent, name, attrs, text)
+
+ def _AddDescription(self, parent, policy):
+ '''Adds a string containing the description of the policy. URLs are
+ replaced with links and the possible choices are enumerated in case
+ of 'string-enum' and 'int-enum' type policies.
+
+ Args:
+ parent: The DOM node for which the feature list will be added.
+ policy: The data structure of a policy.
+ '''
+ # Replace URLs with links in the description.
+ self._AddTextWithLinks(parent, policy['desc'])
+ # Add list of enum items.
+ if policy['type'] in ('string-enum', 'int-enum'):
+ ul = self.AddElement(parent, 'ul')
+ for item in policy['items']:
+ if policy['type'] == 'int-enum':
+ value_string = str(item['value'])
+ else:
+ value_string = '"%s"' % item['value']
+ self.AddElement(
+ ul, 'li', {}, '%s = %s' % (value_string, item['caption']))
+
+ def _AddFeatures(self, parent, policy):
+ '''Adds a string containing the list of supported features of a policy
+ to a DOM node. The text will look like as:
+ Feature_X: Yes, Feature_Y: No
+
+ Args:
+ parent: The DOM node for which the feature list will be added.
+ policy: The data structure of a policy.
+ '''
+ features = []
+ # The sorting is to make the order well-defined for testing.
+ keys = policy['features'].keys()
+ keys.sort()
+ for key in keys:
+ key_name = self._FEATURE_MAP[key]
+ if policy['features'][key]:
+ value_name = self._GetLocalizedMessage('supported')
+ else:
+ value_name = self._GetLocalizedMessage('not_supported')
+ features.append('%s: %s' % (key_name, value_name))
+ self.AddText(parent, ', '.join(features))
+
+ def _AddListExampleMac(self, parent, policy):
+ '''Adds an example value for Mac of a 'list' policy to a DOM node.
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: A policy of type 'list', for which the Mac example value
+ is generated.
+ '''
+ example_value = policy['example_value']
+ self.AddElement(parent, 'dt', {}, 'Mac:')
+ mac = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
+
+ mac_text = ['<array>']
+ for item in example_value:
+ mac_text.append(' <string>%s</string>' % item)
+ mac_text.append('</array>')
+ self.AddText(mac, '\n'.join(mac_text))
+
+ def _AddListExampleWindows(self, parent, policy):
+ '''Adds an example value for Windows of a 'list' policy to a DOM node.
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: A policy of type 'list', for which the Windows example value
+ is generated.
+ '''
+ example_value = policy['example_value']
+ self.AddElement(parent, 'dt', {}, 'Windows:')
+ win = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
+ win_text = []
+ cnt = 1
+ key_name = self.config['win_reg_mandatory_key_name']
+ for item in example_value:
+ win_text.append(
+ '%s\\%s\\%d = "%s"' %
+ (key_name, policy['name'], cnt, item))
+ cnt = cnt + 1
+ self.AddText(win, '\n'.join(win_text))
+
+ def _AddListExampleLinux(self, parent, policy):
+ '''Adds an example value for Linux of a 'list' policy to a DOM node.
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: A policy of type 'list', for which the Linux example value
+ is generated.
+ '''
+ example_value = policy['example_value']
+ self.AddElement(parent, 'dt', {}, 'Linux:')
+ linux = self._AddStyledElement(parent, 'dd', ['.monospace'])
+ linux_text = []
+ for item in example_value:
+ linux_text.append('"%s"' % item)
+ self.AddText(linux, '[%s]' % ', '.join(linux_text))
+
+ def _AddListExample(self, parent, policy):
+ '''Adds the example value of a 'list' policy to a DOM node. Example output:
+ <dl>
+ <dt>Windows:</dt>
+ <dd>
+ Software\Policies\Chromium\DisabledPlugins\0 = "Java"
+ Software\Policies\Chromium\DisabledPlugins\1 = "Shockwave Flash"
+ </dd>
+ <dt>Linux:</dt>
+ <dd>["Java", "Shockwave Flash"]</dd>
+ <dt>Mac:</dt>
+ <dd>
+ <array>
+ <string>Java</string>
+ <string>Shockwave Flash</string>
+ </array>
+ </dd>
+ </dl>
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: The data structure of a policy.
+ '''
+ examples = self._AddStyledElement(parent, 'dl', ['dd dl'])
+ self._AddListExampleWindows(examples, policy)
+ self._AddListExampleLinux(examples, policy)
+ self._AddListExampleMac(examples, policy)
+
+ def _PythonDictionaryToMacDictionary(self, dictionary, indent=''):
+ '''Converts a python dictionary to an equivalent XML plist.
+
+ Returns a list of lines, with one dictionary entry per line.'''
+ result = [indent + '<dict>']
+ indent += ' '
+ for k in sorted(dictionary.keys()):
+ v = dictionary[k]
+ result.append('%s<key>%s</key>' % (indent, k))
+ value_type = type(v)
+ if value_type == bool:
+ result.append('%s<%s/>' % (indent, 'true' if v else 'false'))
+ elif value_type == int:
+ result.append('%s<integer>%s</integer>' % (indent, v))
+ elif value_type == str:
+ result.append('%s<string>%s</string>' % (indent, v))
+ elif value_type == dict:
+ result += self._PythonDictionaryToMacDictionary(v, indent)
+ elif value_type == list:
+ array = []
+ if len(v) != 0:
+ if type(v[0]) == str:
+ array = ['%s <string>%s</string>' % (indent, x) for x in v]
+ elif type(v[0]) == dict:
+ for x in v:
+ array += self._PythonDictionaryToMacDictionary(x, indent + ' ')
+ else:
+ raise Exception('Must be list of string or dict.')
+ result.append('%s<array>' % indent)
+ result += array
+ result.append('%s</array>' % indent)
+ else:
+ raise Exception('Invalid example value type %s' % value_type)
+ result.append(indent[2:] + '</dict>')
+ return result
+
+ def _AddDictionaryExampleMac(self, parent, policy):
+ '''Adds an example value for Mac of a 'dict' policy to a DOM node.
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: A policy of type 'dict', for which the Mac example value
+ is generated.
+ '''
+ example_value = policy['example_value']
+ self.AddElement(parent, 'dt', {}, 'Mac:')
+ mac = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
+ mac_text = ['<key>%s</key>' % (policy['name'])]
+ mac_text += self._PythonDictionaryToMacDictionary(example_value)
+ self.AddText(mac, '\n'.join(mac_text))
+
+ def _AddDictionaryExampleWindows(self, parent, policy):
+ '''Adds an example value for Windows of a 'dict' policy to a DOM node.
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: A policy of type 'dict', for which the Windows example value
+ is generated.
+ '''
+ self.AddElement(parent, 'dt', {}, 'Windows:')
+ win = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
+ key_name = self.config['win_reg_mandatory_key_name']
+ example = str(policy['example_value'])
+ self.AddText(win, '%s\\%s = "%s"' % (key_name, policy['name'], example))
+
+ def _AddDictionaryExampleLinux(self, parent, policy):
+ '''Adds an example value for Linux of a 'dict' policy to a DOM node.
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: A policy of type 'dict', for which the Linux example value
+ is generated.
+ '''
+ self.AddElement(parent, 'dt', {}, 'Linux:')
+ linux = self._AddStyledElement(parent, 'dd', ['.monospace'])
+ example = str(policy['example_value'])
+ self.AddText(linux, '%s: %s' % (policy['name'], example))
+
+ def _AddDictionaryExample(self, parent, policy):
+ '''Adds the example value of a 'dict' policy to a DOM node. Example output:
+ <dl>
+ <dt>Windows:</dt>
+ <dd>
+ Software\Policies\Chromium\ProxySettings = "{ 'ProxyMode': 'direct' }"
+ </dd>
+ <dt>Linux:</dt>
+ <dd>"ProxySettings": {
+ "ProxyMode": "direct"
+ }
+ </dd>
+ <dt>Mac:</dt>
+ <dd>
+ <key>ProxySettings</key>
+ <dict>
+ <key>ProxyMode</key>
+ <string>direct</string>
+ </dict>
+ </dd>
+ </dl>
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: The data structure of a policy.
+ '''
+ examples = self._AddStyledElement(parent, 'dl', ['dd dl'])
+ self._AddDictionaryExampleWindows(examples, policy)
+ self._AddDictionaryExampleLinux(examples, policy)
+ self._AddDictionaryExampleMac(examples, policy)
+
+ def _AddExample(self, parent, policy):
+ '''Adds the HTML DOM representation of the example value of a policy to
+ a DOM node. It is simple text for boolean policies, like
+ '0x00000001 (Windows), true (Linux), <true /> (Mac)' in case of boolean
+ policies, but it may also contain other HTML elements. (See method
+ _AddListExample.)
+
+ Args:
+ parent: The DOM node for which the example will be added.
+ policy: The data structure of a policy.
+
+ Raises:
+ Exception: If the type of the policy is unknown or the example value
+ of the policy is out of its expected range.
+ '''
+ example_value = policy['example_value']
+ policy_type = policy['type']
+ if policy_type == 'main':
+ if example_value == True:
+ self.AddText(
+ parent, '0x00000001 (Windows), true (Linux), <true /> (Mac)')
+ elif example_value == False:
+ self.AddText(
+ parent, '0x00000000 (Windows), false (Linux), <false /> (Mac)')
+ else:
+ raise Exception('Expected boolean value.')
+ elif policy_type == 'string':
+ self.AddText(parent, '"%s"' % example_value)
+ elif policy_type in ('int', 'int-enum'):
+ self.AddText(
+ parent,
+ '0x%08x (Windows), %d (Linux/Mac)' % (example_value, example_value))
+ elif policy_type == 'string-enum':
+ self.AddText(parent, '"%s"' % (example_value))
+ elif policy_type == 'list':
+ self._AddListExample(parent, policy)
+ elif policy_type == 'dict':
+ self._AddDictionaryExample(parent, policy)
+ else:
+ raise Exception('Unknown policy type: ' + policy_type)
+
+ def _AddPolicyAttribute(self, dl, term_id,
+ definition=None, definition_style=None):
+ '''Adds a term-definition pair to a HTML DOM <dl> node. This method is
+ used by _AddPolicyDetails. Its result will have the form of:
+ <dt style="...">...</dt>
+ <dd style="...">...</dd>
+
+ Args:
+ dl: The DOM node of the <dl> list.
+ term_id: A key to self._STRINGS[] which specifies the term of the pair.
+ definition: The text of the definition. (Optional.)
+ definition_style: List of references to values self._STYLE[] that specify
+ the CSS stylesheet of the <dd> (definition) element.
+
+ Returns:
+ The DOM node representing the definition <dd> element.
+ '''
+ # Avoid modifying the default value of definition_style.
+ if definition_style == None:
+ definition_style = []
+ term = self._GetLocalizedMessage(term_id)
+ self._AddStyledElement(dl, 'dt', ['dt'], {}, term)
+ return self._AddStyledElement(dl, 'dd', definition_style, {}, definition)
+
+ def _AddSupportedOnList(self, parent, supported_on_list):
+ '''Creates a HTML list containing the platforms, products and versions
+ that are specified in the list of supported_on.
+
+ Args:
+ parent: The DOM node for which the list will be added.
+ supported_on_list: The list of supported products, as a list of
+ dictionaries.
+ '''
+ ul = self._AddStyledElement(parent, 'ul', ['ul'])
+ for supported_on in supported_on_list:
+ text = []
+ product = supported_on['product']
+ platforms = supported_on['platforms']
+ text.append(self._PRODUCT_MAP[product])
+ text.append('(%s)' %
+ self._MapListToString(self._PLATFORM_MAP, platforms))
+ if supported_on['since_version']:
+ since_version = self._GetLocalizedMessage('since_version')
+ text.append(since_version.replace('$6', supported_on['since_version']))
+ if supported_on['until_version']:
+ until_version = self._GetLocalizedMessage('until_version')
+ text.append(until_version.replace('$6', supported_on['until_version']))
+ # Add the list element:
+ self.AddElement(ul, 'li', {}, ' '.join(text))
+
+ def _AddPolicyDetails(self, parent, policy):
+ '''Adds the list of attributes of a policy to the HTML DOM node parent.
+ It will have the form:
+ <dl>
+ <dt>Attribute:</dt><dd>Description</dd>
+ ...
+ </dl>
+
+ Args:
+ parent: A DOM element for which the list will be added.
+ policy: The data structure of the policy.
+ '''
+
+ dl = self.AddElement(parent, 'dl')
+ self._AddPolicyAttribute(
+ dl,
+ 'data_type',
+ self._TYPE_MAP[policy['type']])
+ self._AddPolicyAttribute(
+ dl,
+ 'win_reg_loc',
+ self.config['win_reg_mandatory_key_name'] + '\\' + policy['name'],
+ ['.monospace'])
+ self._AddPolicyAttribute(
+ dl,
+ 'mac_linux_pref_name',
+ policy['name'],
+ ['.monospace'])
+ dd = self._AddPolicyAttribute(dl, 'supported_on')
+ self._AddSupportedOnList(dd, policy['supported_on'])
+ dd = self._AddPolicyAttribute(dl, 'supported_features')
+ self._AddFeatures(dd, policy)
+ dd = self._AddPolicyAttribute(dl, 'description')
+ self._AddDescription(dd, policy)
+ dd = self._AddPolicyAttribute(dl, 'example_value')
+ self._AddExample(dd, policy)
+
+ def _AddPolicyNote(self, parent, policy):
+ '''If a policy has an additional web page assigned with it, then add
+ a link for that page.
+
+ Args:
+ policy: The data structure of the policy.
+ '''
+ if 'problem_href' not in policy:
+ return
+ problem_href = policy['problem_href']
+ div = self._AddStyledElement(parent, 'div', ['div.note'])
+ note = self._GetLocalizedMessage('note').replace('$6', problem_href)
+ self._AddTextWithLinks(div, note)
+
+ def _AddPolicyRow(self, parent, policy):
+ '''Adds a row for the policy in the summary table.
+
+ Args:
+ parent: The DOM node of the summary table.
+ policy: The data structure of the policy.
+ '''
+ tr = self._AddStyledElement(parent, 'tr', ['tr'])
+ indent = 'padding-left: %dpx;' % (7 + self._indent_level * 14)
+ if policy['type'] != 'group':
+ # Normal policies get two columns with name and caption.
+ name_td = self._AddStyledElement(tr, 'td', ['td', 'td.left'],
+ {'style': indent})
+ self.AddElement(name_td, 'a',
+ {'href': '#' + policy['name']}, policy['name'])
+ self._AddStyledElement(tr, 'td', ['td', 'td.right'], {},
+ policy['caption'])
+ else:
+ # Groups get one column with caption.
+ name_td = self._AddStyledElement(tr, 'td', ['td', 'td.left'],
+ {'style': indent, 'colspan': '2'})
+ self.AddElement(name_td, 'a', {'href': '#' + policy['name']},
+ policy['caption'])
+
+ def _AddPolicySection(self, parent, policy):
+ '''Adds a section about the policy in the detailed policy listing.
+
+ Args:
+ parent: The DOM node of the <div> of the detailed policy list.
+ policy: The data structure of the policy.
+ '''
+ # Set style according to group nesting level.
+ indent = 'margin-left: %dpx' % (self._indent_level * 28)
+ if policy['type'] == 'group':
+ heading = 'h2'
+ else:
+ heading = 'h3'
+ parent2 = self.AddElement(parent, 'div', {'style': indent})
+
+ h2 = self.AddElement(parent2, heading)
+ self.AddElement(h2, 'a', {'name': policy['name']})
+ if policy['type'] != 'group':
+ # Normal policies get a full description.
+ policy_name_text = policy['name']
+ if 'deprecated' in policy and policy['deprecated'] == True:
+ policy_name_text += " ("
+ policy_name_text += self._GetLocalizedMessage('deprecated') + ")"
+ self.AddText(h2, policy_name_text)
+ self.AddElement(parent2, 'span', {}, policy['caption'])
+ self._AddPolicyNote(parent2, policy)
+ self._AddPolicyDetails(parent2, policy)
+ else:
+ # Groups get a more compact description.
+ self.AddText(h2, policy['caption'])
+ self._AddStyledElement(parent2, 'div', ['div.group_desc'],
+ {}, policy['desc'])
+ self.AddElement(
+ parent2, 'a', {'href': '#top'},
+ self._GetLocalizedMessage('back_to_top'))
+
+ #
+ # Implementation of abstract methods of TemplateWriter:
+ #
+
+ def IsDeprecatedPolicySupported(self, policy):
+ return True
+
+ def WritePolicy(self, policy):
+ self._AddPolicyRow(self._summary_tbody, policy)
+ self._AddPolicySection(self._details_div, policy)
+
+ def BeginPolicyGroup(self, group):
+ self.WritePolicy(group)
+ self._indent_level += 1
+
+ def EndPolicyGroup(self):
+ self._indent_level -= 1
+
+ def BeginTemplate(self):
+ # Add a <div> for the summary section.
+ summary_div = self.AddElement(self._main_div, 'div')
+ self.AddElement(summary_div, 'a', {'name': 'top'})
+ self.AddElement(summary_div, 'br')
+ self._AddTextWithLinks(
+ summary_div,
+ self._GetLocalizedMessage('intro'))
+ self.AddElement(summary_div, 'br')
+ self.AddElement(summary_div, 'br')
+ self.AddElement(summary_div, 'br')
+ # Add the summary table of policies.
+ summary_table = self._AddStyledElement(summary_div, 'table', ['table'])
+ # Add the first row.
+ thead = self.AddElement(summary_table, 'thead')
+ tr = self._AddStyledElement(thead, 'tr', ['tr'])
+ self._AddStyledElement(
+ tr, 'td', ['td', 'td.left', 'thead td'], {},
+ self._GetLocalizedMessage('name_column_title'))
+ self._AddStyledElement(
+ tr, 'td', ['td', 'td.right', 'thead td'], {},
+ self._GetLocalizedMessage('description_column_title'))
+ self._summary_tbody = self.AddElement(summary_table, 'tbody')
+
+ # Add a <div> for the detailed policy listing.
+ self._details_div = self.AddElement(self._main_div, 'div')
+
+ def Init(self):
+ dom_impl = minidom.getDOMImplementation('')
+ self._doc = dom_impl.createDocument(None, 'html', None)
+ body = self.AddElement(self._doc.documentElement, 'body')
+ self._main_div = self.AddElement(body, 'div')
+ self._indent_level = 0
+
+ # Human-readable names of supported platforms.
+ self._PLATFORM_MAP = {
+ 'win': 'Windows',
+ 'mac': 'Mac',
+ 'linux': 'Linux',
+ 'chrome_os': self.config['os_name'],
+ }
+ # Human-readable names of supported products.
+ self._PRODUCT_MAP = {
+ 'chrome': self.config['app_name'],
+ 'chrome_frame': self.config['frame_name'],
+ 'chrome_os': self.config['os_name'],
+ }
+ # Human-readable names of supported features. Each supported feature has
+ # a 'doc_feature_X' entry in |self.messages|.
+ self._FEATURE_MAP = {}
+ for message in self.messages:
+ if message.startswith('doc_feature_'):
+ self._FEATURE_MAP[message[12:]] = self.messages[message]['text']
+ # Human-readable names of types.
+ self._TYPE_MAP = {
+ 'string': 'String (REG_SZ)',
+ 'int': 'Integer (REG_DWORD)',
+ 'main': 'Boolean (REG_DWORD)',
+ 'int-enum': 'Integer (REG_DWORD)',
+ 'string-enum': 'String (REG_SZ)',
+ 'list': 'List of strings',
+ 'dict': 'Dictionary (REG_SZ, encoded as a JSON string)',
+ }
+ # The CSS style-sheet used for the document. It will be used in Google
+ # Sites, which strips class attributes from HTML tags. To work around this,
+ # the style-sheet is a dictionary and the style attributes will be added
+ # "by hand" for each element.
+ self._STYLE = {
+ 'table': 'border-style: none; border-collapse: collapse;',
+ 'tr': 'height: 0px;',
+ 'td': 'border: 1px dotted rgb(170, 170, 170); padding: 7px; '
+ 'vertical-align: top; width: 236px; height: 15px;',
+ 'thead td': 'font-weight: bold;',
+ 'td.left': 'width: 200px;',
+ 'td.right': 'width: 100%;',
+ 'dt': 'font-weight: bold;',
+ 'dd dl': 'margin-top: 0px; margin-bottom: 0px;',
+ '.monospace': 'font-family: monospace;',
+ '.pre': 'white-space: pre;',
+ 'div.note': 'border: 2px solid black; padding: 5px; margin: 5px;',
+ 'div.group_desc': 'margin-top: 20px; margin-bottom: 20px;',
+ 'ul': 'padding-left: 0px; margin-left: 0px;'
+ }
+
+ # A simple regexp to search for URLs. It is enough for now.
+ self._url_matcher = lazy_re.compile('(http://[^\\s]*[^\\s\\.])')
+
+ def GetTemplateText(self):
+ # Return the text representation of the main <div> tag.
+ return self._main_div.toxml()
+ # To get a complete HTML file, use the following.
+ # return self._doc.toxml()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py
new file mode 100644
index 00000000000..c413211a80f
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/doc_writer_unittest.py
@@ -0,0 +1,556 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.policy_templates.writers.doc_writer'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+import unittest
+from xml.dom import minidom
+
+from grit.format.policy_templates.writers import writer_unittest_common
+from grit.format.policy_templates.writers import doc_writer
+
+
+class MockMessageDictionary:
+ '''A mock dictionary passed to a writer as the dictionary of
+ localized messages.
+ '''
+
+ # Dictionary of messages.
+ msg_dict = {}
+
+class DocWriterUnittest(writer_unittest_common.WriterUnittestCommon):
+ '''Unit tests for DocWriter.'''
+
+ def setUp(self):
+ # Create a writer for the tests.
+ self.writer = doc_writer.GetWriter(
+ config={
+ 'app_name': 'Chrome',
+ 'frame_name': 'Chrome Frame',
+ 'os_name': 'Chrome OS',
+ 'win_reg_mandatory_key_name': 'MockKey',
+ })
+ self.writer.messages = {
+ 'doc_back_to_top': {'text': '_test_back_to_top'},
+ 'doc_data_type': {'text': '_test_data_type'},
+ 'doc_description': {'text': '_test_description'},
+ 'doc_description_column_title': {
+ 'text': '_test_description_column_title'
+ },
+ 'doc_example_value': {'text': '_test_example_value'},
+ 'doc_feature_dynamic_refresh': {'text': '_test_feature_dynamic_refresh'},
+ 'doc_feature_can_be_recommended': {'text': '_test_feature_recommended'},
+ 'doc_intro': {'text': '_test_intro'},
+ 'doc_mac_linux_pref_name': {'text': '_test_mac_linux_pref_name'},
+ 'doc_note': {'text': '_test_note'},
+ 'doc_name_column_title': {'text': '_test_name_column_title'},
+ 'doc_not_supported': {'text': '_test_not_supported'},
+ 'doc_since_version': {'text': '_test_since_version'},
+ 'doc_supported': {'text': '_test_supported'},
+ 'doc_supported_features': {'text': '_test_supported_features'},
+ 'doc_supported_on': {'text': '_test_supported_on'},
+ 'doc_win_reg_loc': {'text': '_test_win_reg_loc'},
+
+ 'doc_bla': {'text': '_test_bla'},
+ }
+ self.writer.Init()
+
+ # It is not worth testing the exact content of style attributes.
+ # Therefore we override them here with shorter texts.
+ for key in self.writer._STYLE.keys():
+ self.writer._STYLE[key] = 'style_%s;' % key
+ # Add some more style attributes for additional testing.
+ self.writer._STYLE['key1'] = 'style1;'
+ self.writer._STYLE['key2'] = 'style2;'
+
+ # Create a DOM document for the tests.
+ dom_impl = minidom.getDOMImplementation('')
+ self.doc = dom_impl.createDocument(None, 'root', None)
+ self.doc_root = self.doc.documentElement
+
+ def testSkeleton(self):
+ # Test if DocWriter creates the skeleton of the document correctly.
+ self.writer.BeginTemplate()
+ self.assertEquals(
+ self.writer._main_div.toxml(),
+ '<div>'
+ '<div>'
+ '<a name="top"/><br/>_test_intro<br/><br/><br/>'
+ '<table style="style_table;">'
+ '<thead><tr style="style_tr;">'
+ '<td style="style_td;style_td.left;style_thead td;">'
+ '_test_name_column_title'
+ '</td>'
+ '<td style="style_td;style_td.right;style_thead td;">'
+ '_test_description_column_title'
+ '</td>'
+ '</tr></thead>'
+ '<tbody/>'
+ '</table>'
+ '</div>'
+ '<div/>'
+ '</div>')
+
+ def testGetLocalizedMessage(self):
+ # Test if localized messages are retrieved correctly.
+ self.writer.messages = {
+ 'doc_hello_world': {'text': 'hello, vilag!'}
+ }
+ self.assertEquals(
+ self.writer._GetLocalizedMessage('hello_world'),
+ 'hello, vilag!')
+
+ def testMapListToString(self):
+ # Test function DocWriter.MapListToString()
+ self.assertEquals(
+ self.writer._MapListToString({'a1': 'a2', 'b1': 'b2'}, ['a1', 'b1']),
+ 'a2, b2')
+ self.assertEquals(
+ self.writer._MapListToString({'a1': 'a2', 'b1': 'b2'}, []),
+ '')
+ result = self.writer._MapListToString(
+ {'a': '1', 'b': '2', 'c': '3', 'd': '4'}, ['b', 'd'])
+ expected_result = '2, 4'
+ self.assertEquals(
+ result,
+ expected_result)
+
+ def testAddStyledElement(self):
+ # Test function DocWriter.AddStyledElement()
+
+ # Test the case of zero style.
+ e1 = self.writer._AddStyledElement(
+ self.doc_root, 'z', [], {'a': 'b'}, 'text')
+ self.assertEquals(
+ e1.toxml(),
+ '<z a="b">text</z>')
+
+ # Test the case of one style.
+ e2 = self.writer._AddStyledElement(
+ self.doc_root, 'z', ['key1'], {'a': 'b'}, 'text')
+ self.assertEquals(
+ e2.toxml(),
+ '<z a="b" style="style1;">text</z>')
+
+ # Test the case of two styles.
+ e3 = self.writer._AddStyledElement(
+ self.doc_root, 'z', ['key1', 'key2'], {'a': 'b'}, 'text')
+ self.assertEquals(
+ e3.toxml(),
+ '<z a="b" style="style1;style2;">text</z>')
+
+ def testAddDescriptionIntEnum(self):
+ # Test if URLs are replaced and choices of 'int-enum' policies are listed
+ # correctly.
+ policy = {
+ 'type': 'int-enum',
+ 'items': [
+ {'value': 0, 'caption': 'Disable foo'},
+ {'value': 2, 'caption': 'Solve your problem'},
+ {'value': 5, 'caption': 'Enable bar'},
+ ],
+ 'desc': '''This policy disables foo, except in case of bar.
+See http://policy-explanation.example.com for more details.
+'''
+ }
+ self.writer._AddDescription(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '''<root>This policy disables foo, except in case of bar.
+See <a href="http://policy-explanation.example.com">http://policy-explanation.example.com</a> for more details.
+<ul><li>0 = Disable foo</li><li>2 = Solve your problem</li><li>5 = Enable bar</li></ul></root>''')
+
+ def testAddDescriptionStringEnum(self):
+ # Test if URLs are replaced and choices of 'int-enum' policies are listed
+ # correctly.
+ policy = {
+ 'type': 'string-enum',
+ 'items': [
+ {'value': "one", 'caption': 'Disable foo'},
+ {'value': "two", 'caption': 'Solve your problem'},
+ {'value': "three", 'caption': 'Enable bar'},
+ ],
+ 'desc': '''This policy disables foo, except in case of bar.
+See http://policy-explanation.example.com for more details.
+'''
+ }
+ self.writer._AddDescription(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '''<root>This policy disables foo, except in case of bar.
+See <a href="http://policy-explanation.example.com">http://policy-explanation.example.com</a> for more details.
+<ul><li>&quot;one&quot; = Disable foo</li><li>&quot;two&quot; = Solve your problem</li><li>&quot;three&quot; = Enable bar</li></ul></root>''')
+
+ def testAddFeatures(self):
+ # Test if the list of features of a policy is handled correctly.
+ policy = {
+ 'features': {
+ 'spaceship_docking': False,
+ 'dynamic_refresh': True,
+ 'can_be_recommended': True,
+ }
+ }
+ self.writer._FEATURE_MAP = {
+ 'can_be_recommended': 'Can Be Recommended',
+ 'dynamic_refresh': 'Dynamic Refresh',
+ 'spaceship_docking': 'Spaceship Docking',
+ }
+ self.writer._AddFeatures(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>'
+ 'Can Be Recommended: _test_supported, '
+ 'Dynamic Refresh: _test_supported, '
+ 'Spaceship Docking: _test_not_supported'
+ '</root>')
+
+ def testAddListExample(self):
+ policy = {
+ 'name': 'PolicyName',
+ 'example_value': ['Foo', 'Bar']
+ }
+ self.writer._AddListExample(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>'
+ '<dl style="style_dd dl;">'
+ '<dt>Windows:</dt>'
+ '<dd style="style_.monospace;style_.pre;">'
+ 'MockKey\\PolicyName\\1 = &quot;Foo&quot;\n'
+ 'MockKey\\PolicyName\\2 = &quot;Bar&quot;'
+ '</dd>'
+ '<dt>Linux:</dt>'
+ '<dd style="style_.monospace;">'
+ '[&quot;Foo&quot;, &quot;Bar&quot;]'
+ '</dd>'
+ '<dt>Mac:</dt>'
+ '<dd style="style_.monospace;style_.pre;">'
+ '&lt;array&gt;\n'
+ ' &lt;string&gt;Foo&lt;/string&gt;\n'
+ ' &lt;string&gt;Bar&lt;/string&gt;\n'
+ '&lt;/array&gt;'
+ '</dd>'
+ '</dl>'
+ '</root>')
+
+ def testBoolExample(self):
+ # Test representation of boolean example values.
+ policy = {
+ 'name': 'PolicyName',
+ 'type': 'main',
+ 'example_value': True
+ }
+ e1 = self.writer.AddElement(self.doc_root, 'e1')
+ self.writer._AddExample(e1, policy)
+ self.assertEquals(
+ e1.toxml(),
+ '<e1>0x00000001 (Windows), true (Linux), &lt;true /&gt; (Mac)</e1>')
+
+ policy = {
+ 'name': 'PolicyName',
+ 'type': 'main',
+ 'example_value': False
+ }
+ e2 = self.writer.AddElement(self.doc_root, 'e2')
+ self.writer._AddExample(e2, policy)
+ self.assertEquals(
+ e2.toxml(),
+ '<e2>0x00000000 (Windows), false (Linux), &lt;false /&gt; (Mac)</e2>')
+
+ def testIntEnumExample(self):
+ # Test representation of 'int-enum' example values.
+ policy = {
+ 'name': 'PolicyName',
+ 'type': 'int-enum',
+ 'example_value': 16
+ }
+ self.writer._AddExample(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>0x00000010 (Windows), 16 (Linux/Mac)</root>')
+
+ def testStringEnumExample(self):
+ # Test representation of 'int-enum' example values.
+ policy = {
+ 'name': 'PolicyName',
+ 'type': 'string-enum',
+ 'example_value': "wacky"
+ }
+ self.writer._AddExample(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>&quot;wacky&quot;</root>')
+
+ def testStringExample(self):
+ # Test representation of 'string' example values.
+ policy = {
+ 'name': 'PolicyName',
+ 'type': 'string',
+ 'example_value': 'awesome-example'
+ }
+ self.writer._AddExample(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>&quot;awesome-example&quot;</root>')
+
+ def testIntExample(self):
+ # Test representation of 'int' example values.
+ policy = {
+ 'name': 'PolicyName',
+ 'type': 'int',
+ 'example_value': 26
+ }
+ self.writer._AddExample(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>0x0000001a (Windows), 26 (Linux/Mac)</root>')
+
+ def testAddPolicyAttribute(self):
+ # Test creating a policy attribute term-definition pair.
+ self.writer._AddPolicyAttribute(
+ self.doc_root, 'bla', 'hello, world', ['key1'])
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>'
+ '<dt style="style_dt;">_test_bla</dt>'
+ '<dd style="style1;">hello, world</dd>'
+ '</root>')
+
+ def testAddPolicyDetails(self):
+ # Test if the definition list (<dl>) of policy details is created correctly.
+ policy = {
+ 'type': 'main',
+ 'name': 'TestPolicyName',
+ 'caption': 'TestPolicyCaption',
+ 'desc': 'TestPolicyDesc',
+ 'supported_on': [{
+ 'product': 'chrome',
+ 'platforms': ['win'],
+ 'since_version': '8',
+ 'until_version': '',
+ }],
+ 'features': {'dynamic_refresh': False},
+ 'example_value': False
+ }
+ self.writer.messages['doc_since_version'] = {'text': '...$6...'}
+ self.writer._AddPolicyDetails(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root><dl>'
+ '<dt style="style_dt;">_test_data_type</dt><dd>Boolean (REG_DWORD)</dd>'
+ '<dt style="style_dt;">_test_win_reg_loc</dt>'
+ '<dd style="style_.monospace;">MockKey\TestPolicyName</dd>'
+ '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
+ '<dd style="style_.monospace;">TestPolicyName</dd>'
+ '<dt style="style_dt;">_test_supported_on</dt>'
+ '<dd>'
+ '<ul style="style_ul;">'
+ '<li>Chrome (Windows) ...8...</li>'
+ '</ul>'
+ '</dd>'
+ '<dt style="style_dt;">_test_supported_features</dt>'
+ '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
+ '<dt style="style_dt;">_test_description</dt><dd>TestPolicyDesc</dd>'
+ '<dt style="style_dt;">_test_example_value</dt>'
+ '<dd>0x00000000 (Windows), false (Linux), &lt;false /&gt; (Mac)</dd>'
+ '</dl></root>')
+
+ def testAddPolicyNote(self):
+ # TODO(jkummerow): The functionality tested by this test is currently not
+ # used for anything and will probably soon be removed.
+ # Test if nodes are correctly added to policies.
+ policy = {
+ 'problem_href': 'http://www.example.com/5'
+ }
+ self.writer.messages['doc_note'] = {'text': '...$6...'}
+ self.writer._AddPolicyNote(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root><div style="style_div.note;">...'
+ '<a href="http://www.example.com/5">http://www.example.com/5</a>'
+ '...</div></root>')
+
+ def testAddPolicyRow(self):
+ # Test if policies are correctly added to the summary table.
+ policy = {
+ 'name': 'PolicyName',
+ 'caption': 'PolicyCaption',
+ 'type': 'string',
+ }
+ self.writer._indent_level = 3
+ self.writer._AddPolicyRow(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root><tr style="style_tr;">'
+ '<td style="style_td;style_td.left;padding-left: 49px;">'
+ '<a href="#PolicyName">PolicyName</a>'
+ '</td>'
+ '<td style="style_td;style_td.right;">PolicyCaption</td>'
+ '</tr></root>')
+ self.setUp()
+ policy = {
+ 'name': 'PolicyName',
+ 'caption': 'PolicyCaption',
+ 'type': 'group',
+ }
+ self.writer._indent_level = 2
+ self.writer._AddPolicyRow(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root><tr style="style_tr;">'
+ '<td colspan="2" style="style_td;style_td.left;padding-left: 35px;">'
+ '<a href="#PolicyName">PolicyCaption</a>'
+ '</td>'
+ '</tr></root>')
+
+ def testAddPolicySection(self):
+ # Test if policy details are correctly added to the document.
+ policy = {
+ 'name': 'PolicyName',
+ 'caption': 'PolicyCaption',
+ 'desc': 'PolicyDesc',
+ 'type': 'string',
+ 'supported_on': [{
+ 'product': 'chrome',
+ 'platforms': ['win'],
+ 'since_version': '7',
+ 'until_version': '',
+ }],
+ 'features': {'dynamic_refresh': False},
+ 'example_value': False
+ }
+ self.writer.messages['doc_since_version'] = {'text': '..$6..'}
+ self.writer._AddPolicySection(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>'
+ '<div style="margin-left: 0px">'
+ '<h3><a name="PolicyName"/>PolicyName</h3>'
+ '<span>PolicyCaption</span>'
+ '<dl>'
+ '<dt style="style_dt;">_test_data_type</dt>'
+ '<dd>String (REG_SZ)</dd>'
+ '<dt style="style_dt;">_test_win_reg_loc</dt>'
+ '<dd style="style_.monospace;">MockKey\\PolicyName</dd>'
+ '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
+ '<dd style="style_.monospace;">PolicyName</dd>'
+ '<dt style="style_dt;">_test_supported_on</dt>'
+ '<dd>'
+ '<ul style="style_ul;">'
+ '<li>Chrome (Windows) ..7..</li>'
+ '</ul>'
+ '</dd>'
+ '<dt style="style_dt;">_test_supported_features</dt>'
+ '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
+ '<dt style="style_dt;">_test_description</dt>'
+ '<dd>PolicyDesc</dd>'
+ '<dt style="style_dt;">_test_example_value</dt>'
+ '<dd>&quot;False&quot;</dd>'
+ '</dl>'
+ '<a href="#top">_test_back_to_top</a>'
+ '</div>'
+ '</root>')
+ # Test for groups.
+ self.setUp()
+ policy['type'] = 'group'
+ self.writer._AddPolicySection(self.doc_root, policy)
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>'
+ '<div style="margin-left: 0px">'
+ '<h2><a name="PolicyName"/>PolicyCaption</h2>'
+ '<div style="style_div.group_desc;">PolicyDesc</div>'
+ '<a href="#top">_test_back_to_top</a>'
+ '</div>'
+ '</root>')
+
+ def testAddDictionaryExample(self):
+ policy = {
+ 'name': 'PolicyName',
+ 'caption': 'PolicyCaption',
+ 'desc': 'PolicyDesc',
+ 'type': 'dict',
+ 'supported_on': [{
+ 'product': 'chrome',
+ 'platforms': ['win'],
+ 'since_version': '7',
+ 'until_version': '',
+ }],
+ 'features': {'dynamic_refresh': False},
+ 'example_value': {
+ "ProxyMode": "direct",
+ "List": ["1", "2", "3"],
+ "True": True,
+ "False": False,
+ "Integer": 123,
+ "DictList": [ {
+ "A": 1,
+ "B": 2,
+ }, {
+ "C": 3,
+ "D": 4,
+ },
+ ],
+ },
+ }
+ self.writer._AddDictionaryExample(self.doc_root, policy)
+ value = str(policy['example_value'])
+ self.assertEquals(
+ self.doc_root.toxml(),
+ '<root>'
+ '<dl style="style_dd dl;">'
+ '<dt>Windows:</dt>'
+ '<dd style="style_.monospace;style_.pre;">MockKey\PolicyName = '
+ '&quot;' + value + '&quot;'
+ '</dd>'
+ '<dt>Linux:</dt>'
+ '<dd style="style_.monospace;">PolicyName: ' + value + '</dd>'
+ '<dt>Mac:</dt>'
+ '<dd style="style_.monospace;style_.pre;">'
+ '&lt;key&gt;PolicyName&lt;/key&gt;\n'
+ '&lt;dict&gt;\n'
+ ' &lt;key&gt;DictList&lt;/key&gt;\n'
+ ' &lt;array&gt;\n'
+ ' &lt;dict&gt;\n'
+ ' &lt;key&gt;A&lt;/key&gt;\n'
+ ' &lt;integer&gt;1&lt;/integer&gt;\n'
+ ' &lt;key&gt;B&lt;/key&gt;\n'
+ ' &lt;integer&gt;2&lt;/integer&gt;\n'
+ ' &lt;/dict&gt;\n'
+ ' &lt;dict&gt;\n'
+ ' &lt;key&gt;C&lt;/key&gt;\n'
+ ' &lt;integer&gt;3&lt;/integer&gt;\n'
+ ' &lt;key&gt;D&lt;/key&gt;\n'
+ ' &lt;integer&gt;4&lt;/integer&gt;\n'
+ ' &lt;/dict&gt;\n'
+ ' &lt;/array&gt;\n'
+ ' &lt;key&gt;False&lt;/key&gt;\n'
+ ' &lt;false/&gt;\n'
+ ' &lt;key&gt;Integer&lt;/key&gt;\n'
+ ' &lt;integer&gt;123&lt;/integer&gt;\n'
+ ' &lt;key&gt;List&lt;/key&gt;\n'
+ ' &lt;array&gt;\n'
+ ' &lt;string&gt;1&lt;/string&gt;\n'
+ ' &lt;string&gt;2&lt;/string&gt;\n'
+ ' &lt;string&gt;3&lt;/string&gt;\n'
+ ' &lt;/array&gt;\n'
+ ' &lt;key&gt;ProxyMode&lt;/key&gt;\n'
+ ' &lt;string&gt;direct&lt;/string&gt;\n'
+ ' &lt;key&gt;True&lt;/key&gt;\n'
+ ' &lt;true/&gt;\n'
+ '&lt;/dict&gt;'
+ '</dd>'
+ '</dl>'
+ '</root>')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/json_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/json_writer.py
new file mode 100644
index 00000000000..b77974d5434
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/json_writer.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from textwrap import TextWrapper
+from grit.format.policy_templates.writers import template_writer
+
+
+TEMPLATE_HEADER="""\
+// Policy template for Linux.
+// Uncomment the policies you wish to activate and change their values to
+// something useful for your case. The provided values are for reference only
+// and do not provide meaningful defaults!
+{"""
+
+
+HEADER_DELIMETER="""\
+ //-------------------------------------------------------------------------"""
+
+
+def GetWriter(config):
+ '''Factory method for creating JsonWriter objects.
+ See the constructor of TemplateWriter for description of
+ arguments.
+ '''
+ return JsonWriter(['linux'], config)
+
+
+class JsonWriter(template_writer.TemplateWriter):
+ '''Class for generating policy files in JSON format (for Linux). The
+ generated files will define all the supported policies with example values
+ set for them. This class is used by PolicyTemplateGenerator to write .json
+ files.
+ '''
+
+ def PreprocessPolicies(self, policy_list):
+ return self.FlattenGroupsAndSortPolicies(policy_list)
+
+ def WritePolicy(self, policy):
+ example_value = policy['example_value']
+ if policy['type'] == 'string':
+ example_value_str = '"' + example_value + '"'
+ elif policy['type'] in ('int', 'int-enum', 'dict'):
+ example_value_str = str(example_value)
+ elif policy['type'] == 'list':
+ if example_value == []:
+ example_value_str = '[]'
+ else:
+ example_value_str = '["%s"]' % '", "'.join(example_value)
+ elif policy['type'] == 'main':
+ if example_value == True:
+ example_value_str = 'true'
+ else:
+ example_value_str = 'false'
+ elif policy['type'] == 'string-enum':
+ example_value_str = '"%s"' % example_value;
+ else:
+ raise Exception('unknown policy type %s:' % policy['type'])
+
+ # Add comma to the end of the previous line.
+ if not self._first_written:
+ self._out[-2] += ','
+
+ line = ' // %s' % policy['caption']
+ self._out.append(line)
+ self._out.append(HEADER_DELIMETER)
+ description = self._text_wrapper.wrap(policy['desc'])
+ self._out += description;
+ line = ' //"%s": %s' % (policy['name'], example_value_str)
+ self._out.append('')
+ self._out.append(line)
+ self._out.append('')
+
+ self._first_written = False
+
+ def BeginTemplate(self):
+ self._out.append(TEMPLATE_HEADER)
+
+ def EndTemplate(self):
+ self._out.append('}')
+
+ def Init(self):
+ self._out = []
+ # The following boolean member is true until the first policy is written.
+ self._first_written = True
+ # Create the TextWrapper object once.
+ self._text_wrapper = TextWrapper(
+ initial_indent = ' // ',
+ subsequent_indent = ' // ',
+ break_long_words = False,
+ width = 80)
+
+ def GetTemplateText(self):
+ return '\n'.join(self._out)
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py
new file mode 100644
index 00000000000..1281c19d952
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/json_writer_unittest.py
@@ -0,0 +1,340 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.policy_templates.writers.json_writer'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+import unittest
+
+from grit.format.policy_templates.writers import writer_unittest_common
+
+
+TEMPLATE_HEADER="""\
+// Policy template for Linux.
+// Uncomment the policies you wish to activate and change their values to
+// something useful for your case. The provided values are for reference only
+// and do not provide meaningful defaults!
+{
+"""
+
+
+HEADER_DELIMETER="""\
+ //-------------------------------------------------------------------------
+"""
+
+
+class JsonWriterUnittest(writer_unittest_common.WriterUnittestCommon):
+ '''Unit tests for JsonWriter.'''
+
+ def CompareOutputs(self, output, expected_output):
+ '''Compares the output of the json_writer with its expected output.
+
+ Args:
+ output: The output of the json writer as returned by grit.
+ expected_output: The expected output.
+
+ Raises:
+ AssertionError: if the two strings are not equivalent.
+ '''
+ self.assertEquals(
+ output.strip(),
+ expected_output.strip())
+
+ def testEmpty(self):
+ # Test the handling of an empty policy list.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": [],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium': '1',}, 'json', 'en')
+ expected_output = TEMPLATE_HEADER + '}'
+ self.CompareOutputs(output, expected_output)
+
+ def testMainPolicy(self):
+ # Tests a policy group with a single policy of type 'main'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "MainPolicy",'
+ ' "type": "main",'
+ ' "caption": "Example Main Policy",'
+ ' "desc": "Example Main Policy",'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": True'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'json', 'en')
+ expected_output = (
+ TEMPLATE_HEADER +
+ ' // Example Main Policy\n' +
+ HEADER_DELIMETER +
+ ' // Example Main Policy\n\n'
+ ' //"MainPolicy": true\n\n'
+ '}')
+ self.CompareOutputs(output, expected_output)
+
+ def testStringPolicy(self):
+ # Tests a policy group with a single policy of type 'string'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "StringPolicy",'
+ ' "type": "string",'
+ ' "caption": "Example String Policy",'
+ ' "desc": "Example String Policy",'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": "hello, world!"'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
+ expected_output = (
+ TEMPLATE_HEADER +
+ ' // Example String Policy\n' +
+ HEADER_DELIMETER +
+ ' // Example String Policy\n\n'
+ ' //"StringPolicy": "hello, world!"\n\n'
+ '}')
+ self.CompareOutputs(output, expected_output)
+
+ def testIntPolicy(self):
+ # Tests a policy group with a single policy of type 'string'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "IntPolicy",'
+ ' "type": "int",'
+ ' "caption": "Example Int Policy",'
+ ' "desc": "Example Int Policy",'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": 15'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
+ expected_output = (
+ TEMPLATE_HEADER +
+ ' // Example Int Policy\n' +
+ HEADER_DELIMETER +
+ ' // Example Int Policy\n\n'
+ ' //"IntPolicy": 15\n\n'
+ '}')
+ self.CompareOutputs(output, expected_output)
+
+ def testIntEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'int-enum'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "EnumPolicy",'
+ ' "type": "int-enum",'
+ ' "caption": "Example Int Enum",'
+ ' "desc": "Example Int Enum",'
+ ' "items": ['
+ ' {"name": "ProxyServerDisabled", "value": 0, "caption": ""},'
+ ' {"name": "ProxyServerAutoDetect", "value": 1, "caption": ""},'
+ ' ],'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": 1'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'json', 'en')
+ expected_output = (
+ TEMPLATE_HEADER +
+ ' // Example Int Enum\n' +
+ HEADER_DELIMETER +
+ ' // Example Int Enum\n\n'
+ ' //"EnumPolicy": 1\n\n'
+ '}')
+ self.CompareOutputs(output, expected_output)
+
+ def testStringEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'string-enum'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "EnumPolicy",'
+ ' "type": "string-enum",'
+ ' "caption": "Example String Enum",'
+ ' "desc": "Example String Enum",'
+ ' "items": ['
+ ' {"name": "ProxyServerDisabled", "value": "one",'
+ ' "caption": ""},'
+ ' {"name": "ProxyServerAutoDetect", "value": "two",'
+ ' "caption": ""},'
+ ' ],'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": "one"'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'json', 'en')
+ expected_output = (
+ TEMPLATE_HEADER +
+ ' // Example String Enum\n' +
+ HEADER_DELIMETER +
+ ' // Example String Enum\n\n'
+ ' //"EnumPolicy": "one"\n\n'
+ '}')
+ self.CompareOutputs(output, expected_output)
+
+ def testListPolicy(self):
+ # Tests a policy group with a single policy of type 'list'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "ListPolicy",'
+ ' "type": "list",'
+ ' "caption": "Example List",'
+ ' "desc": "Example List",'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": ["foo", "bar"]'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
+ expected_output = (
+ TEMPLATE_HEADER +
+ ' // Example List\n' +
+ HEADER_DELIMETER +
+ ' // Example List\n\n'
+ ' //"ListPolicy": ["foo", "bar"]\n\n'
+ '}')
+ self.CompareOutputs(output, expected_output)
+
+ def testDictionaryPolicy(self):
+ # Tests a policy group with a single policy of type 'dict'.
+ example = {
+ 'bool': True,
+ 'int': 10,
+ 'string': 'abc',
+ 'list': [1, 2, 3],
+ 'dict': {
+ 'a': 1,
+ 'b': 2,
+ }
+ }
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "DictionaryPolicy",'
+ ' "type": "dict",'
+ ' "caption": "Example Dictionary Policy",'
+ ' "desc": "Example Dictionary Policy",'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": ' + str(example) +
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
+ expected_output = (
+ TEMPLATE_HEADER +
+ ' // Example Dictionary Policy\n' +
+ HEADER_DELIMETER +
+ ' // Example Dictionary Policy\n\n'
+ ' //"DictionaryPolicy": {\'bool\': True, \'dict\': {\'a\': 1, '
+ '\'b\': 2}, \'int\': 10, \'list\': [1, 2, 3], \'string\': \'abc\'}\n\n'
+ '}')
+ self.CompareOutputs(output, expected_output)
+
+ def testNonSupportedPolicy(self):
+ # Tests a policy that is not supported on Linux, so it shouldn't
+ # be included in the JSON file.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "NonLinuxPolicy",'
+ ' "type": "list",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.mac:8-"],'
+ ' "example_value": ["a"]'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
+ expected_output = TEMPLATE_HEADER + '}'
+ self.CompareOutputs(output, expected_output)
+
+ def testPolicyGroup(self):
+ # Tests a policy group that has more than one policies.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "Group1",'
+ ' "type": "group",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "policies": [{'
+ ' "name": "Policy1",'
+ ' "type": "list",'
+ ' "caption": "Policy One",'
+ ' "desc": "Policy One",'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": ["a", "b"]'
+ ' },{'
+ ' "name": "Policy2",'
+ ' "type": "string",'
+ ' "caption": "Policy Two",'
+ ' "desc": "Policy Two",'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": "c"'
+ ' }],'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
+ expected_output = (
+ TEMPLATE_HEADER +
+ ' // Policy One\n' +
+ HEADER_DELIMETER +
+ ' // Policy One\n\n'
+ ' //"Policy1": ["a", "b"],\n\n'
+ ' // Policy Two\n' +
+ HEADER_DELIMETER +
+ ' // Policy Two\n\n'
+ ' //"Policy2": "c"\n\n'
+ '}')
+ self.CompareOutputs(output, expected_output)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/mock_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/mock_writer.py
new file mode 100644
index 00000000000..3db3a5432b9
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/mock_writer.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from template_writer import TemplateWriter
+
+
+class MockWriter(TemplateWriter):
+ '''Helper class for unit tests in policy_template_generator_unittest.py
+ '''
+
+ def __init__(self):
+ pass
+
+ def WritePolicy(self, policy):
+ pass
+
+ def BeginTemplate(self):
+ pass
+
+ def GetTemplateText(self):
+ pass
+
+ def IsPolicySupported(self, policy):
+ return True
+
+ def Test(self):
+ pass
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/plist_helper.py b/chromium/tools/grit/grit/format/policy_templates/writers/plist_helper.py
new file mode 100644
index 00000000000..0c599ca7a85
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/plist_helper.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+'''Common functions for plist_writer and plist_strings_writer.
+'''
+
+
+def GetPlistFriendlyName(name):
+ '''Transforms a string so that it will be suitable for use as
+ a pfm_name in the plist manifest file.
+ '''
+ return name.replace(' ', '_')
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py
new file mode 100644
index 00000000000..81c70b0cf4a
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from grit.format.policy_templates.writers import plist_helper
+from grit.format.policy_templates.writers import template_writer
+
+
+def GetWriter(config):
+ '''Factory method for creating PListStringsWriter objects.
+ See the constructor of TemplateWriter for description of
+ arguments.
+ '''
+ return PListStringsWriter(['mac'], config)
+
+
+class PListStringsWriter(template_writer.TemplateWriter):
+ '''Outputs localized string table files for the Mac policy file.
+ These files are named Localizable.strings and they are in the
+ [lang].lproj subdirectories of the manifest bundle.
+ '''
+
+ def _AddToStringTable(self, item_name, caption, desc):
+ '''Add a title and a description of an item to the string table.
+
+ Args:
+ item_name: The name of the item that will get the title and the
+ description.
+ title: The text of the title to add.
+ desc: The text of the description to add.
+ '''
+ caption = caption.replace('"', '\\"')
+ caption = caption.replace('\n', '\\n')
+ desc = desc.replace('"', '\\"')
+ desc = desc.replace('\n', '\\n')
+ self._out.append('%s.pfm_title = \"%s\";' % (item_name, caption))
+ self._out.append('%s.pfm_description = \"%s\";' % (item_name, desc))
+
+ def PreprocessPolicies(self, policy_list):
+ return self.FlattenGroupsAndSortPolicies(policy_list)
+
+ def WritePolicy(self, policy):
+ '''Add strings to the stringtable corresponding a given policy.
+
+ Args:
+ policy: The policy for which the strings will be added to the
+ string table.
+ '''
+ desc = policy['desc']
+ if policy['type'] in ('int-enum','string-enum'):
+ # Append the captions of enum items to the description string.
+ item_descs = []
+ for item in policy['items']:
+ item_descs.append(str(item['value']) + ' - ' + item['caption'])
+ desc = '\n'.join(item_descs) + '\n' + desc
+
+ self._AddToStringTable(policy['name'], policy['label'], desc)
+
+ def BeginTemplate(self):
+ app_name = plist_helper.GetPlistFriendlyName(self.config['app_name'])
+ self._AddToStringTable(
+ app_name,
+ self.config['app_name'],
+ self.messages['mac_chrome_preferences']['text'])
+
+ def Init(self):
+ # A buffer for the lines of the string table being generated.
+ self._out = []
+
+ def GetTemplateText(self):
+ return '\n'.join(self._out)
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py
new file mode 100644
index 00000000000..613a3cd65b5
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.policy_templates.writers.plist_strings_writer'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+import unittest
+
+from grit.format.policy_templates.writers import writer_unittest_common
+
+
+class PListStringsWriterUnittest(writer_unittest_common.WriterUnittestCommon):
+ '''Unit tests for PListStringsWriter.'''
+
+ def testEmpty(self):
+ # Test PListStringsWriter in case of empty polices.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [],
+ 'placeholders': [],
+ 'messages': {
+ 'mac_chrome_preferences': {
+ 'text': '$1 preferen"ces',
+ 'desc': 'blah'
+ }
+ }
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_chromium': '1', 'mac_bundle_id': 'com.example.Test'},
+ 'plist_strings',
+ 'en')
+ expected_output = (
+ 'Chromium.pfm_title = "Chromium";\n'
+ 'Chromium.pfm_description = "Chromium preferen\\"ces";')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testMainPolicy(self):
+ # Tests a policy group with a single policy of type 'main'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'MainGroup',
+ 'type': 'group',
+ 'caption': 'Caption of main.',
+ 'desc': 'Description of main.',
+ 'policies': [{
+ 'name': 'MainPolicy',
+ 'type': 'main',
+ 'supported_on': ['chrome.mac:8-'],
+ 'caption': 'Caption of main policy.',
+ 'desc': 'Description of main policy.',
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'mac_chrome_preferences': {
+ 'text': 'Preferences of $1',
+ 'desc': 'blah'
+ }
+ }
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_google_chrome' : '1', 'mac_bundle_id': 'com.example.Test'},
+ 'plist_strings',
+ 'en')
+ expected_output = (
+ 'Google_Chrome.pfm_title = "Google Chrome";\n'
+ 'Google_Chrome.pfm_description = "Preferences of Google Chrome";\n'
+ 'MainPolicy.pfm_title = "Caption of main policy.";\n'
+ 'MainPolicy.pfm_description = "Description of main policy.";')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testStringPolicy(self):
+ # Tests a policy group with a single policy of type 'string'. Also test
+ # inheriting group description to policy description.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'StringGroup',
+ 'type': 'group',
+ 'caption': 'Caption of group.',
+ 'desc': """Description of group.
+With a newline.""",
+ 'policies': [{
+ 'name': 'StringPolicy',
+ 'type': 'string',
+ 'caption': 'Caption of policy.',
+ 'desc': """Description of policy.
+With a newline.""",
+ 'supported_on': ['chrome.mac:8-'],
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'mac_chrome_preferences': {
+ 'text': 'Preferences of $1',
+ 'desc': 'blah'
+ }
+ }
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
+ 'plist_strings',
+ 'en')
+ expected_output = (
+ 'Chromium.pfm_title = "Chromium";\n'
+ 'Chromium.pfm_description = "Preferences of Chromium";\n'
+ 'StringPolicy.pfm_title = "Caption of policy.";\n'
+ 'StringPolicy.pfm_description = '
+ '"Description of policy.\\nWith a newline.";')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testIntEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'int-enum'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'EnumGroup',
+ 'type': 'group',
+ 'desc': '',
+ 'caption': '',
+ 'policies': [{
+ 'name': 'EnumPolicy',
+ 'type': 'int-enum',
+ 'desc': 'Description of policy.',
+ 'caption': 'Caption of policy.',
+ 'items': [
+ {
+ 'name': 'ProxyServerDisabled',
+ 'value': 0,
+ 'caption': 'Option1'
+ },
+ {
+ 'name': 'ProxyServerAutoDetect',
+ 'value': 1,
+ 'caption': 'Option2'
+ },
+ ],
+ 'supported_on': ['chrome.mac:8-'],
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'mac_chrome_preferences': {
+ 'text': '$1 preferences',
+ 'desc': 'blah'
+ }
+ }
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
+ 'plist_strings',
+ 'en')
+ expected_output = (
+ 'Google_Chrome.pfm_title = "Google Chrome";\n'
+ 'Google_Chrome.pfm_description = "Google Chrome preferences";\n'
+ 'EnumPolicy.pfm_title = "Caption of policy.";\n'
+ 'EnumPolicy.pfm_description = '
+ '"0 - Option1\\n1 - Option2\\nDescription of policy.";\n')
+
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testStringEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'string-enum'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'EnumGroup',
+ 'type': 'group',
+ 'desc': '',
+ 'caption': '',
+ 'policies': [{
+ 'name': 'EnumPolicy',
+ 'type': 'string-enum',
+ 'desc': 'Description of policy.',
+ 'caption': 'Caption of policy.',
+ 'items': [
+ {
+ 'name': 'ProxyServerDisabled',
+ 'value': 'one',
+ 'caption': 'Option1'
+ },
+ {
+ 'name': 'ProxyServerAutoDetect',
+ 'value': 'two',
+ 'caption': 'Option2'
+ },
+ ],
+ 'supported_on': ['chrome.mac:8-'],
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'mac_chrome_preferences': {
+ 'text': '$1 preferences',
+ 'desc': 'blah'
+ }
+ }
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
+ 'plist_strings',
+ 'en')
+ expected_output = (
+ 'Google_Chrome.pfm_title = "Google Chrome";\n'
+ 'Google_Chrome.pfm_description = "Google Chrome preferences";\n'
+ 'EnumPolicy.pfm_title = "Caption of policy.";\n'
+ 'EnumPolicy.pfm_description = '
+ '"one - Option1\\ntwo - Option2\\nDescription of policy.";\n')
+
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testNonSupportedPolicy(self):
+ # Tests a policy that is not supported on Mac, so its strings shouldn't
+ # be included in the plist string table.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'NonMacGroup',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [{
+ 'name': 'NonMacPolicy',
+ 'type': 'string',
+ 'caption': '',
+ 'desc': '',
+ 'supported_on': ['chrome_os:8-'],
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {
+ 'mac_chrome_preferences': {
+ 'text': '$1 preferences',
+ 'desc': 'blah'
+ }
+ }
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
+ 'plist_strings',
+ 'en')
+ expected_output = (
+ 'Google_Chrome.pfm_title = "Google Chrome";\n'
+ 'Google_Chrome.pfm_description = "Google Chrome preferences";')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/plist_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/plist_writer.py
new file mode 100644
index 00000000000..94dc1082487
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/plist_writer.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from xml.dom import minidom
+from grit.format.policy_templates.writers import plist_helper
+from grit.format.policy_templates.writers import xml_formatted_writer
+
+
+def GetWriter(config):
+ '''Factory method for creating PListWriter objects.
+ See the constructor of TemplateWriter for description of
+ arguments.
+ '''
+ return PListWriter(['mac'], config)
+
+
+class PListWriter(xml_formatted_writer.XMLFormattedWriter):
+ '''Class for generating policy templates in Mac plist format.
+ It is used by PolicyTemplateGenerator to write plist files.
+ '''
+
+ STRING_TABLE = 'Localizable.strings'
+ TYPE_TO_INPUT = {
+ 'string': 'string',
+ 'int': 'integer',
+ 'int-enum': 'integer',
+ 'string-enum': 'string',
+ 'main': 'boolean',
+ 'list': 'array',
+ 'dict': 'dictionary',
+ }
+
+ def _AddKeyValuePair(self, parent, key_string, value_tag):
+ '''Adds a plist key-value pair to a parent XML element.
+
+ A key-value pair in plist consists of two XML elements next two each other:
+ <key>key_string</key>
+ <value_tag>...</value_tag>
+
+ Args:
+ key_string: The content of the key tag.
+ value_tag: The name of the value element.
+
+ Returns:
+ The XML element of the value tag.
+ '''
+ self.AddElement(parent, 'key', {}, key_string)
+ return self.AddElement(parent, value_tag)
+
+ def _AddStringKeyValuePair(self, parent, key_string, value_string):
+ '''Adds a plist key-value pair to a parent XML element, where the
+ value element contains a string. The name of the value element will be
+ <string>.
+
+ Args:
+ key_string: The content of the key tag.
+ value_string: The content of the value tag.
+ '''
+ self.AddElement(parent, 'key', {}, key_string)
+ self.AddElement(parent, 'string', {}, value_string)
+
+ def _AddTargets(self, parent):
+ '''Adds the following XML snippet to an XML element:
+ <key>pfm_targets</key>
+ <array>
+ <string>user-managed</string>
+ </array>
+
+ Args:
+ parent: The parent XML element where the snippet will be added.
+ '''
+ array = self._AddKeyValuePair(parent, 'pfm_targets', 'array')
+ self.AddElement(array, 'string', {}, 'user-managed')
+
+ def PreprocessPolicies(self, policy_list):
+ return self.FlattenGroupsAndSortPolicies(policy_list)
+
+ def WritePolicy(self, policy):
+ policy_name = policy['name']
+ policy_type = policy['type']
+
+ dict = self.AddElement(self._array, 'dict')
+ self._AddStringKeyValuePair(dict, 'pfm_name', policy_name)
+ # Set empty strings for title and description. They will be taken by the
+ # OSX Workgroup Manager from the string table in a Localizable.strings file.
+ # Those files are generated by plist_strings_writer.
+ self._AddStringKeyValuePair(dict, 'pfm_description', '')
+ self._AddStringKeyValuePair(dict, 'pfm_title', '')
+ self._AddTargets(dict)
+ self._AddStringKeyValuePair(dict, 'pfm_type',
+ self.TYPE_TO_INPUT[policy_type])
+ if policy_type in ('int-enum', 'string-enum'):
+ range_list = self._AddKeyValuePair(dict, 'pfm_range_list', 'array')
+ for item in policy['items']:
+ if policy_type == 'int-enum':
+ element_type = 'integer'
+ else:
+ element_type = 'string'
+ self.AddElement(range_list, element_type, {}, str(item['value']))
+
+ def BeginTemplate(self):
+ self._plist.attributes['version'] = '1'
+ dict = self.AddElement(self._plist, 'dict')
+
+ app_name = plist_helper.GetPlistFriendlyName(self.config['app_name'])
+ self._AddStringKeyValuePair(dict, 'pfm_name', app_name)
+ self._AddStringKeyValuePair(dict, 'pfm_description', '')
+ self._AddStringKeyValuePair(dict, 'pfm_title', '')
+ self._AddStringKeyValuePair(dict, 'pfm_version', '1')
+ self._AddStringKeyValuePair(dict, 'pfm_domain',
+ self.config['mac_bundle_id'])
+
+ self._array = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array')
+
+ def Init(self):
+ dom_impl = minidom.getDOMImplementation('')
+ doctype = dom_impl.createDocumentType(
+ 'plist',
+ '-//Apple//DTD PLIST 1.0//EN',
+ 'http://www.apple.com/DTDs/PropertyList-1.0.dtd')
+ self._doc = dom_impl.createDocument(None, 'plist', doctype)
+ self._plist = self._doc.documentElement
+
+ def GetTemplateText(self):
+ return self.ToPrettyXml(self._doc)
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py
new file mode 100644
index 00000000000..a9d146df9b9
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py
@@ -0,0 +1,409 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.policy_templates.writers.plist_writer'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+import unittest
+
+from grit.format.policy_templates.writers import writer_unittest_common
+
+
+class PListWriterUnittest(writer_unittest_common.WriterUnittestCommon):
+ '''Unit tests for PListWriter.'''
+
+ def _GetExpectedOutputs(self, product_name, bundle_id, policies):
+ '''Substitutes the variable parts into a plist template. The result
+ of this function can be used as an expected result to test the output
+ of PListWriter.
+
+ Args:
+ product_name: The name of the product, normally Chromium or Google Chrome.
+ bundle_id: The mac bundle id of the product.
+ policies: The list of policies.
+
+ Returns:
+ The text of a plist template with the variable parts substituted.
+ '''
+ return '''
+<?xml version="1.0" ?>
+<!DOCTYPE plist PUBLIC '-//Apple//DTD PLIST 1.0//EN' 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
+<plist version="1">
+ <dict>
+ <key>pfm_name</key>
+ <string>%s</string>
+ <key>pfm_description</key>
+ <string/>
+ <key>pfm_title</key>
+ <string/>
+ <key>pfm_version</key>
+ <string>1</string>
+ <key>pfm_domain</key>
+ <string>%s</string>
+ <key>pfm_subkeys</key>
+ %s
+ </dict>
+</plist>''' % (product_name, bundle_id, policies)
+
+ def testEmpty(self):
+ # Test PListWriter in case of empty polices.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [],
+ 'placeholders': [],
+ 'messages': {},
+ }''')
+
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_chromium': '1', 'mac_bundle_id': 'com.example.Test'},
+ 'plist',
+ 'en')
+ expected_output = self._GetExpectedOutputs(
+ 'Chromium', 'com.example.Test', '<array/>')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testMainPolicy(self):
+ # Tests a policy group with a single policy of type 'main'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'MainGroup',
+ 'type': 'group',
+ 'policies': [{
+ 'name': 'MainPolicy',
+ 'type': 'main',
+ 'desc': '',
+ 'caption': '',
+ 'supported_on': ['chrome.mac:8-'],
+ }],
+ 'desc': '',
+ 'caption': '',
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {}
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
+ 'plist',
+ 'en')
+ expected_output = self._GetExpectedOutputs(
+ 'Chromium', 'com.example.Test', '''<array>
+ <dict>
+ <key>pfm_name</key>
+ <string>MainPolicy</string>
+ <key>pfm_description</key>
+ <string/>
+ <key>pfm_title</key>
+ <string/>
+ <key>pfm_targets</key>
+ <array>
+ <string>user-managed</string>
+ </array>
+ <key>pfm_type</key>
+ <string>boolean</string>
+ </dict>
+ </array>''')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testStringPolicy(self):
+ # Tests a policy group with a single policy of type 'string'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'StringGroup',
+ 'type': 'group',
+ 'desc': '',
+ 'caption': '',
+ 'policies': [{
+ 'name': 'StringPolicy',
+ 'type': 'string',
+ 'supported_on': ['chrome.mac:8-'],
+ 'desc': '',
+ 'caption': '',
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {},
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
+ 'plist',
+ 'en')
+ expected_output = self._GetExpectedOutputs(
+ 'Chromium', 'com.example.Test', '''<array>
+ <dict>
+ <key>pfm_name</key>
+ <string>StringPolicy</string>
+ <key>pfm_description</key>
+ <string/>
+ <key>pfm_title</key>
+ <string/>
+ <key>pfm_targets</key>
+ <array>
+ <string>user-managed</string>
+ </array>
+ <key>pfm_type</key>
+ <string>string</string>
+ </dict>
+ </array>''')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testIntPolicy(self):
+ # Tests a policy group with a single policy of type 'int'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'IntGroup',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [{
+ 'name': 'IntPolicy',
+ 'type': 'int',
+ 'caption': '',
+ 'desc': '',
+ 'supported_on': ['chrome.mac:8-'],
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {},
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
+ 'plist',
+ 'en')
+ expected_output = self._GetExpectedOutputs(
+ 'Chromium', 'com.example.Test', '''<array>
+ <dict>
+ <key>pfm_name</key>
+ <string>IntPolicy</string>
+ <key>pfm_description</key>
+ <string/>
+ <key>pfm_title</key>
+ <string/>
+ <key>pfm_targets</key>
+ <array>
+ <string>user-managed</string>
+ </array>
+ <key>pfm_type</key>
+ <string>integer</string>
+ </dict>
+ </array>''')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testIntEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'int-enum'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'EnumGroup',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [{
+ 'name': 'EnumPolicy',
+ 'type': 'int-enum',
+ 'desc': '',
+ 'caption': '',
+ 'items': [
+ {'name': 'ProxyServerDisabled', 'value': 0, 'caption': ''},
+ {'name': 'ProxyServerAutoDetect', 'value': 1, 'caption': ''},
+ ],
+ 'supported_on': ['chrome.mac:8-'],
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {},
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
+ 'plist',
+ 'en')
+ expected_output = self._GetExpectedOutputs(
+ 'Google_Chrome', 'com.example.Test2', '''<array>
+ <dict>
+ <key>pfm_name</key>
+ <string>EnumPolicy</string>
+ <key>pfm_description</key>
+ <string/>
+ <key>pfm_title</key>
+ <string/>
+ <key>pfm_targets</key>
+ <array>
+ <string>user-managed</string>
+ </array>
+ <key>pfm_type</key>
+ <string>integer</string>
+ <key>pfm_range_list</key>
+ <array>
+ <integer>0</integer>
+ <integer>1</integer>
+ </array>
+ </dict>
+ </array>''')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testStringEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'string-enum'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'EnumGroup',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [{
+ 'name': 'EnumPolicy',
+ 'type': 'string-enum',
+ 'desc': '',
+ 'caption': '',
+ 'items': [
+ {'name': 'ProxyServerDisabled', 'value': 'one', 'caption': ''},
+ {'name': 'ProxyServerAutoDetect', 'value': 'two', 'caption': ''},
+ ],
+ 'supported_on': ['chrome.mac:8-'],
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {},
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
+ 'plist',
+ 'en')
+ expected_output = self._GetExpectedOutputs(
+ 'Google_Chrome', 'com.example.Test2', '''<array>
+ <dict>
+ <key>pfm_name</key>
+ <string>EnumPolicy</string>
+ <key>pfm_description</key>
+ <string/>
+ <key>pfm_title</key>
+ <string/>
+ <key>pfm_targets</key>
+ <array>
+ <string>user-managed</string>
+ </array>
+ <key>pfm_type</key>
+ <string>string</string>
+ <key>pfm_range_list</key>
+ <array>
+ <string>one</string>
+ <string>two</string>
+ </array>
+ </dict>
+ </array>''')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testDictionaryPolicy(self):
+ # Tests a policy group with a single policy of type 'dict'.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'DictionaryGroup',
+ 'type': 'group',
+ 'desc': '',
+ 'caption': '',
+ 'policies': [{
+ 'name': 'DictionaryPolicy',
+ 'type': 'dict',
+ 'supported_on': ['chrome.mac:8-'],
+ 'desc': '',
+ 'caption': '',
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {},
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
+ 'plist',
+ 'en')
+ expected_output = self._GetExpectedOutputs(
+ 'Chromium', 'com.example.Test', '''<array>
+ <dict>
+ <key>pfm_name</key>
+ <string>DictionaryPolicy</string>
+ <key>pfm_description</key>
+ <string/>
+ <key>pfm_title</key>
+ <string/>
+ <key>pfm_targets</key>
+ <array>
+ <string>user-managed</string>
+ </array>
+ <key>pfm_type</key>
+ <string>dictionary</string>
+ </dict>
+ </array>''')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+ def testNonSupportedPolicy(self):
+ # Tests a policy that is not supported on Mac, so it shouldn't
+ # be included in the plist file.
+ grd = self.PrepareTest('''
+ {
+ 'policy_definitions': [
+ {
+ 'name': 'NonMacGroup',
+ 'type': 'group',
+ 'caption': '',
+ 'desc': '',
+ 'policies': [{
+ 'name': 'NonMacPolicy',
+ 'type': 'string',
+ 'supported_on': ['chrome.linux:8-', 'chrome.win:7-'],
+ 'caption': '',
+ 'desc': '',
+ }],
+ },
+ ],
+ 'placeholders': [],
+ 'messages': {},
+ }''')
+ output = self.GetOutput(
+ grd,
+ 'fr',
+ {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
+ 'plist',
+ 'en')
+ expected_output = self._GetExpectedOutputs(
+ 'Google_Chrome', 'com.example.Test2', '''<array/>''')
+ self.assertEquals(output.strip(), expected_output.strip())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/reg_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/reg_writer.py
new file mode 100644
index 00000000000..e278ed5564c
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/reg_writer.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from grit.format.policy_templates.writers import template_writer
+
+
+def GetWriter(config):
+ '''Factory method for creating RegWriter objects.
+ See the constructor of TemplateWriter for description of
+ arguments.
+ '''
+ return RegWriter(['win'], config)
+
+
+class RegWriter(template_writer.TemplateWriter):
+ '''Class for generating policy example files in .reg format (for Windows).
+ The generated files will define all the supported policies with example
+ values set for them. This class is used by PolicyTemplateGenerator to
+ write .reg files.
+ '''
+
+ NEWLINE = '\r\n'
+
+ def _EscapeRegString(self, string):
+ return string.replace('\\', '\\\\').replace('\"', '\\\"')
+
+ def _StartBlock(self, key, suffix, list):
+ key = 'HKEY_LOCAL_MACHINE\\' + key
+ if suffix:
+ key = key + '\\' + suffix
+ if key != self._last_key.get(id(list), None):
+ list.append('')
+ list.append('[%s]' % key)
+ self._last_key[id(list)] = key
+
+ def PreprocessPolicies(self, policy_list):
+ return self.FlattenGroupsAndSortPolicies(policy_list,
+ self.GetPolicySortingKey)
+
+ def GetPolicySortingKey(self, policy):
+ '''Extracts a sorting key from a policy. These keys can be used for
+ list.sort() methods to sort policies.
+ See TemplateWriter.SortPoliciesGroupsFirst for usage.
+ '''
+ is_list = policy['type'] == 'list'
+ # Lists come after regular policies.
+ return (is_list, policy['name'])
+
+ def _WritePolicy(self, policy, key, list):
+ example_value = policy['example_value']
+
+ if policy['type'] == 'list':
+ self._StartBlock(key, policy['name'], list)
+ i = 1
+ for item in example_value:
+ escaped_str = self._EscapeRegString(item)
+ list.append('"%d"="%s"' % (i, escaped_str))
+ i = i + 1
+ else:
+ self._StartBlock(key, None, list)
+ if policy['type'] in ('string', 'dict'):
+ escaped_str = self._EscapeRegString(str(example_value))
+ example_value_str = '"' + escaped_str + '"'
+ elif policy['type'] == 'main':
+ if example_value == True:
+ example_value_str = 'dword:00000001'
+ else:
+ example_value_str = 'dword:00000000'
+ elif policy['type'] in ('int', 'int-enum'):
+ example_value_str = 'dword:%08x' % example_value
+ elif policy['type'] == 'string-enum':
+ example_value_str = '"%s"' % example_value
+ else:
+ raise Exception('unknown policy type %s:' % policy['type'])
+
+ list.append('"%s"=%s' % (policy['name'], example_value_str))
+
+ def WritePolicy(self, policy):
+ self._WritePolicy(policy,
+ self.config['win_reg_mandatory_key_name'],
+ self._mandatory)
+
+ def WriteRecommendedPolicy(self, policy):
+ self._WritePolicy(policy,
+ self.config['win_reg_recommended_key_name'],
+ self._recommended)
+
+ def BeginTemplate(self):
+ pass
+
+ def EndTemplate(self):
+ pass
+
+ def Init(self):
+ self._mandatory = []
+ self._recommended = []
+ self._last_key = {}
+
+ def GetTemplateText(self):
+ prefix = ['Windows Registry Editor Version 5.00']
+ all = prefix + self._mandatory + self._recommended
+ return self.NEWLINE.join(all)
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py
new file mode 100644
index 00000000000..d84599c8230
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/reg_writer_unittest.py
@@ -0,0 +1,318 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+'''Unit tests for grit.format.policy_templates.writers.reg_writer'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+import unittest
+
+from grit.format.policy_templates.writers import writer_unittest_common
+
+
+class RegWriterUnittest(writer_unittest_common.WriterUnittestCommon):
+ '''Unit tests for RegWriter.'''
+
+ NEWLINE = '\r\n'
+
+ def CompareOutputs(self, output, expected_output):
+ '''Compares the output of the reg_writer with its expected output.
+
+ Args:
+ output: The output of the reg writer as returned by grit.
+ expected_output: The expected output.
+
+ Raises:
+ AssertionError: if the two strings are not equivalent.
+ '''
+ self.assertEquals(
+ output.strip(),
+ expected_output.strip())
+
+ def testEmpty(self):
+ # Test the handling of an empty policy list.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": [],'
+ ' "placeholders": [],'
+ ' "messages": {}'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium': '1', }, 'reg', 'en')
+ expected_output = 'Windows Registry Editor Version 5.00'
+ self.CompareOutputs(output, expected_output)
+
+ def testMainPolicy(self):
+ # Tests a policy group with a single policy of type 'main'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "MainPolicy",'
+ ' "type": "main",'
+ ' "features": { "can_be_recommended": True },'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.win:8-"],'
+ ' "example_value": True'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
+ '"MainPolicy"=dword:00000001',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome\\Recommended]',
+ '"MainPolicy"=dword:00000001'])
+ self.CompareOutputs(output, expected_output)
+
+ def testStringPolicy(self):
+ # Tests a policy group with a single policy of type 'string'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "StringPolicy",'
+ ' "type": "string",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.win:8-"],'
+ ' "example_value": "hello, world! \\\" \\\\"'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
+ '"StringPolicy"="hello, world! \\\" \\\\"'])
+ self.CompareOutputs(output, expected_output)
+
+ def testIntPolicy(self):
+ # Tests a policy group with a single policy of type 'int'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "IntPolicy",'
+ ' "type": "int",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.win:8-"],'
+ ' "example_value": 26'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
+ '"IntPolicy"=dword:0000001a'])
+ self.CompareOutputs(output, expected_output)
+
+ def testIntEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'int-enum'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "EnumPolicy",'
+ ' "type": "int-enum",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "items": ['
+ ' {"name": "ProxyServerDisabled", "value": 0, "caption": ""},'
+ ' {"name": "ProxyServerAutoDetect", "value": 1, "caption": ""},'
+ ' ],'
+ ' "supported_on": ["chrome.win:8-"],'
+ ' "example_value": 1'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
+ '"EnumPolicy"=dword:00000001'])
+ self.CompareOutputs(output, expected_output)
+
+ def testStringEnumPolicy(self):
+ # Tests a policy group with a single policy of type 'string-enum'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "EnumPolicy",'
+ ' "type": "string-enum",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "items": ['
+ ' {"name": "ProxyServerDisabled", "value": "one",'
+ ' "caption": ""},'
+ ' {"name": "ProxyServerAutoDetect", "value": "two",'
+ ' "caption": ""},'
+ ' ],'
+ ' "supported_on": ["chrome.win:8-"],'
+ ' "example_value": "two"'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
+ '"EnumPolicy"="two"'])
+ self.CompareOutputs(output, expected_output)
+
+ def testListPolicy(self):
+ # Tests a policy group with a single policy of type 'list'.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "ListPolicy",'
+ ' "type": "list",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.linux:8-"],'
+ ' "example_value": ["foo", "bar"]'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium\\ListPolicy]',
+ '"1"="foo"',
+ '"2"="bar"'])
+
+ def testDictionaryPolicy(self):
+ # Tests a policy group with a single policy of type 'dict'.
+ example = {
+ 'bool': True,
+ 'int': 10,
+ 'string': 'abc',
+ 'list': [1, 2, 3],
+ 'dict': {
+ 'a': 1,
+ 'b': 2,
+ }
+ }
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "DictionaryPolicy",'
+ ' "type": "dict",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.win:8-"],'
+ ' "example_value": ' + str(example) +
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
+ '"DictionaryPolicy"="{\'bool\': True, \'dict\': {\'a\': 1, '
+ '\'b\': 2}, \'int\': 10, \'list\': [1, 2, 3], \'string\': \'abc\'}"'])
+ self.CompareOutputs(output, expected_output)
+
+ def testNonSupportedPolicy(self):
+ # Tests a policy that is not supported on Windows, so it shouldn't
+ # be included in the .REG file.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "NonWindowsPolicy",'
+ ' "type": "list",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.mac:8-"],'
+ ' "example_value": ["a"]'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00'])
+ self.CompareOutputs(output, expected_output)
+
+ def testPolicyGroup(self):
+ # Tests a policy group that has more than one policies.
+ grd = self.PrepareTest(
+ '{'
+ ' "policy_definitions": ['
+ ' {'
+ ' "name": "Group1",'
+ ' "type": "group",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "policies": [{'
+ ' "name": "Policy1",'
+ ' "type": "list",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.win:8-"],'
+ ' "example_value": ["a", "b"]'
+ ' },{'
+ ' "name": "Policy2",'
+ ' "type": "string",'
+ ' "caption": "",'
+ ' "desc": "",'
+ ' "supported_on": ["chrome.win:8-"],'
+ ' "example_value": "c"'
+ ' }],'
+ ' },'
+ ' ],'
+ ' "placeholders": [],'
+ ' "messages": {},'
+ '}')
+ output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
+ expected_output = self.NEWLINE.join([
+ 'Windows Registry Editor Version 5.00',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
+ '"Policy2"="c"',
+ '',
+ '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium\\Policy1]',
+ '"1"="a"',
+ '"2"="b"'])
+ self.CompareOutputs(output, expected_output)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/template_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/template_writer.py
new file mode 100644
index 00000000000..935c886aec2
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/template_writer.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+class TemplateWriter(object):
+ '''Abstract base class for writing policy templates in various formats.
+ The methods of this class will be called by PolicyTemplateGenerator.
+ '''
+
+ def __init__(self, platforms, config):
+ '''Initializes a TemplateWriter object.
+
+ Args:
+ platforms: List of platforms for which this writer can write policies.
+ config: A dictionary of information required to generate the template.
+ It contains some key-value pairs, including the following examples:
+ 'build': 'chrome' or 'chromium'
+ 'branding': 'Google Chrome' or 'Chromium'
+ 'mac_bundle_id': The Mac bundle id of Chrome. (Only set when building
+ for Mac.)
+ messages: List of all the message strings from the grd file. Most of them
+ are also present in the policy data structures that are passed to
+ methods. That is the preferred way of accessing them, this should only
+ be used in exceptional cases. An example for its use is the
+ IDS_POLICY_WIN_SUPPORTED_WINXPSP2 message in ADM files, because that
+ cannot be associated with any policy or group.
+ '''
+ self.platforms = platforms
+ self.config = config
+
+ def IsDeprecatedPolicySupported(self, policy):
+ '''Checks if the given deprecated policy is supported by the writer.
+
+ Args:
+ policy: The dictionary of the policy.
+
+ Returns:
+ True if the writer chooses to include the deprecated 'policy' in its
+ output.
+ '''
+ return False
+
+ def IsFuturePolicySupported(self, policy):
+ '''Checks if the given future policy is supported by the writer.
+
+ Args:
+ policy: The dictionary of the policy.
+
+ Returns:
+ True if the writer chooses to include the deprecated 'policy' in its
+ output.
+ '''
+ return False
+
+ def IsPolicySupported(self, policy):
+ '''Checks if the given policy is supported by the writer.
+ In other words, the set of platforms supported by the writer
+ has a common subset with the set of platforms that support
+ the policy.
+
+ Args:
+ policy: The dictionary of the policy.
+
+ Returns:
+ True if the writer chooses to include 'policy' in its output.
+ '''
+ if ('deprecated' in policy and policy['deprecated'] is True and
+ not self.IsDeprecatedPolicySupported(policy)):
+ return False
+
+ if ('future' in policy and policy['future'] is True and
+ not self.IsFuturePolicySupported(policy)):
+ return False
+
+ if '*' in self.platforms:
+ # Currently chrome_os is only catched here.
+ return True
+ for supported_on in policy['supported_on']:
+ for supported_on_platform in supported_on['platforms']:
+ if supported_on_platform in self.platforms:
+ return True
+ return False
+
+ def CanBeRecommended(self, policy):
+ '''Checks if the given policy can be recommended.'''
+ return policy.get('features', {}).get('can_be_recommended', False)
+
+ def _GetPoliciesForWriter(self, group):
+ '''Filters the list of policies in the passed group that are supported by
+ the writer.
+
+ Args:
+ group: The dictionary of the policy group.
+
+ Returns: The list of policies of the policy group that are compatible
+ with the writer.
+ '''
+ if not 'policies' in group:
+ return []
+ result = []
+ for policy in group['policies']:
+ if self.IsPolicySupported(policy):
+ result.append(policy)
+ return result
+
+ def Init(self):
+ '''Initializes the writer. If the WriteTemplate method is overridden, then
+ this method must be called as first step of each template generation
+ process.
+ '''
+ pass
+
+ def WriteTemplate(self, template):
+ '''Writes the given template definition.
+
+ Args:
+ template: Template definition to write.
+
+ Returns:
+ Generated output for the passed template definition.
+ '''
+ self.messages = template['messages']
+ self.Init()
+ template['policy_definitions'] = \
+ self.PreprocessPolicies(template['policy_definitions'])
+ self.BeginTemplate()
+ for policy in template['policy_definitions']:
+ if policy['type'] == 'group':
+ child_policies = self._GetPoliciesForWriter(policy)
+ child_recommended_policies = filter(self.CanBeRecommended,
+ child_policies)
+ if child_policies:
+ # Only write nonempty groups.
+ self.BeginPolicyGroup(policy)
+ for child_policy in child_policies:
+ # Nesting of groups is currently not supported.
+ self.WritePolicy(child_policy)
+ self.EndPolicyGroup()
+ if child_recommended_policies:
+ self.BeginRecommendedPolicyGroup(policy)
+ for child_policy in child_recommended_policies:
+ self.WriteRecommendedPolicy(child_policy)
+ self.EndRecommendedPolicyGroup()
+ elif self.IsPolicySupported(policy):
+ self.WritePolicy(policy)
+ if self.CanBeRecommended(policy):
+ self.WriteRecommendedPolicy(policy)
+ self.EndTemplate()
+
+ return self.GetTemplateText()
+
+ def PreprocessPolicies(self, policy_list):
+ '''Preprocesses a list of policies according to a given writer's needs.
+ Preprocessing steps include sorting policies and stripping unneeded
+ information such as groups (for writers that ignore them).
+ Subclasses are encouraged to override this method, overriding
+ implementations may call one of the provided specialized implementations.
+ The default behaviour is to use SortPoliciesGroupsFirst().
+
+ Args:
+ policy_list: A list containing the policies to sort.
+
+ Returns:
+ The sorted policy list.
+ '''
+ return self.SortPoliciesGroupsFirst(policy_list)
+
+ def WritePolicy(self, policy):
+ '''Appends the template text corresponding to a policy into the
+ internal buffer.
+
+ Args:
+ policy: The policy as it is found in the JSON file.
+ '''
+ raise NotImplementedError()
+
+ def WriteRecommendedPolicy(self, policy):
+ '''Appends the template text corresponding to a recommended policy into the
+ internal buffer.
+
+ Args:
+ policy: The recommended policy as it is found in the JSON file.
+ '''
+ # TODO
+ #raise NotImplementedError()
+ pass
+
+ def BeginPolicyGroup(self, group):
+ '''Appends the template text corresponding to the beginning of a
+ policy group into the internal buffer.
+
+ Args:
+ group: The policy group as it is found in the JSON file.
+ '''
+ pass
+
+ def EndPolicyGroup(self):
+ '''Appends the template text corresponding to the end of a
+ policy group into the internal buffer.
+ '''
+ pass
+
+ def BeginRecommendedPolicyGroup(self, group):
+ '''Appends the template text corresponding to the beginning of a recommended
+ policy group into the internal buffer.
+
+ Args:
+ group: The recommended policy group as it is found in the JSON file.
+ '''
+ pass
+
+ def EndRecommendedPolicyGroup(self):
+ '''Appends the template text corresponding to the end of a recommended
+ policy group into the internal buffer.
+ '''
+ pass
+
+ def BeginTemplate(self):
+ '''Appends the text corresponding to the beginning of the whole
+ template into the internal buffer.
+ '''
+ raise NotImplementedError()
+
+ def EndTemplate(self):
+ '''Appends the text corresponding to the end of the whole
+ template into the internal buffer.
+ '''
+ pass
+
+ def GetTemplateText(self):
+ '''Gets the content of the internal template buffer.
+
+ Returns:
+ The generated template from the the internal buffer as a string.
+ '''
+ raise NotImplementedError()
+
+ def SortPoliciesGroupsFirst(self, policy_list):
+ '''Sorts a list of policies alphabetically. The order is the
+ following: first groups alphabetically by caption, then other policies
+ alphabetically by name. The order of policies inside groups is unchanged.
+
+ Args:
+ policy_list: The list of policies to sort. Sub-lists in groups will not
+ be sorted.
+ '''
+ policy_list.sort(key=self.GetPolicySortingKeyGroupsFirst)
+ return policy_list
+
+ def FlattenGroupsAndSortPolicies(self, policy_list, sorting_key=None):
+ '''Sorts a list of policies according to |sorting_key|, defaulting
+ to alphabetical sorting if no key is given. If |policy_list| contains
+ policies with type="group", it is flattened first, i.e. any groups' contents
+ are inserted into the list as first-class elements and the groups are then
+ removed.
+ '''
+ new_list = []
+ for policy in policy_list:
+ if policy['type'] == 'group':
+ for grouped_policy in policy['policies']:
+ new_list.append(grouped_policy)
+ else:
+ new_list.append(policy)
+ if sorting_key == None:
+ sorting_key = self.GetPolicySortingKeyName
+ new_list.sort(key=sorting_key)
+ return new_list
+
+ def GetPolicySortingKeyName(self, policy):
+ return policy['name']
+
+ def GetPolicySortingKeyGroupsFirst(self, policy):
+ '''Extracts a sorting key from a policy. These keys can be used for
+ list.sort() methods to sort policies.
+ See TemplateWriter.SortPolicies for usage.
+ '''
+ is_group = policy['type'] == 'group'
+ if is_group:
+ # Groups are sorted by caption.
+ str_key = policy['caption']
+ else:
+ # Regular policies are sorted by name.
+ str_key = policy['name']
+ # Groups come before regular policies.
+ return (not is_group, str_key)
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py
new file mode 100644
index 00000000000..172e2921b52
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/template_writer_unittest.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.policy_templates.writers.template_writer'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
+
+import unittest
+
+from grit.format.policy_templates.writers import template_writer
+
+
+POLICY_DEFS = [
+ {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
+ {
+ 'type': 'group',
+ 'caption': 'z_group1_caption',
+ 'name': 'group1',
+ 'policies': [
+ {'name': 'z0', 'type': 'string', 'supported_on': []},
+ {'name': 'a0', 'type': 'string', 'supported_on': []}
+ ]
+ },
+ {
+ 'type': 'group',
+ 'caption': 'b_group2_caption',
+ 'name': 'group2',
+ 'policies': [{'name': 'q', 'type': 'string', 'supported_on': []}],
+ },
+ {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []}
+]
+
+
+GROUP_FIRST_SORTED_POLICY_DEFS = [
+ {
+ 'type': 'group',
+ 'caption': 'b_group2_caption',
+ 'name': 'group2',
+ 'policies': [{'name': 'q', 'type': 'string', 'supported_on': []}],
+ },
+ {
+ 'type': 'group',
+ 'caption': 'z_group1_caption',
+ 'name': 'group1',
+ 'policies': [
+ {'name': 'z0', 'type': 'string', 'supported_on': []},
+ {'name': 'a0', 'type': 'string', 'supported_on': []}
+ ]
+ },
+ {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []},
+ {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
+]
+
+
+IGNORE_GROUPS_SORTED_POLICY_DEFS = [
+ {'name': 'a0', 'type': 'string', 'supported_on': []},
+ {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []},
+ {'name': 'q', 'type': 'string', 'supported_on': []},
+ {'name': 'z0', 'type': 'string', 'supported_on': []},
+ {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
+]
+
+
+class TemplateWriterUnittests(unittest.TestCase):
+ '''Unit tests for templater_writer.py.'''
+
+ def testSortingGroupsFirst(self):
+ tw = template_writer.TemplateWriter(None, None)
+ sorted_list = tw.SortPoliciesGroupsFirst(POLICY_DEFS)
+ self.assertEqual(sorted_list, GROUP_FIRST_SORTED_POLICY_DEFS)
+
+ def testSortingIgnoreGroups(self):
+ tw = template_writer.TemplateWriter(None, None)
+ sorted_list = tw.FlattenGroupsAndSortPolicies(POLICY_DEFS)
+ self.assertEqual(sorted_list, IGNORE_GROUPS_SORTED_POLICY_DEFS)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py b/chromium/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py
new file mode 100644
index 00000000000..f75c391cebf
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Common tools for unit-testing writers.'''
+
+
+import os
+import tempfile
+import unittest
+import StringIO
+
+from grit import grd_reader
+from grit import util
+from grit.tool import build
+
+
+class DummyOutput(object):
+ def __init__(self, type, language, file = 'hello.gif'):
+ self.type = type
+ self.language = language
+ self.file = file
+ def GetType(self):
+ return self.type
+ def GetLanguage(self):
+ return self.language
+ def GetOutputFilename(self):
+ return self.file
+
+
+class WriterUnittestCommon(unittest.TestCase):
+ '''Common class for unittesting writers.'''
+
+ def PrepareTest(self, policy_json):
+ '''Prepares and parses a grit tree along with a data structure of policies.
+
+ Args:
+ policy_json: The policy data structure in JSON format.
+ '''
+ # First create a temporary file that contains the JSON policy list.
+ tmp_file_name = 'test.json'
+ tmp_dir_name = tempfile.gettempdir()
+ json_file_path = tmp_dir_name + '/' + tmp_file_name
+ with open(json_file_path, 'w') as f:
+ f.write(policy_json.strip())
+ # Then assemble the grit tree.
+ grd_text = '''
+ <grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
+ <release seq="1">
+ <structures>
+ <structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
+ </structures>
+ </release>
+ </grit>''' % json_file_path
+ grd_string_io = StringIO.StringIO(grd_text)
+ # Parse the grit tree and load the policies' JSON with a gatherer.
+ grd = grd_reader.Parse(grd_string_io, dir=tmp_dir_name)
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+ # Remove the policies' JSON.
+ os.unlink(json_file_path)
+ return grd
+
+ def GetOutput(self, grd, env_lang, env_defs, out_type, out_lang):
+ '''Generates an output of a writer.
+
+ Args:
+ grd: The root of the grit tree.
+ env_lang: The environment language.
+ env_defs: Environment definitions.
+ out_type: Type of the output node for which output will be generated.
+ This selects the writer.
+ out_lang: Language of the output node for which output will be generated.
+
+ Returns:
+ The string of the template created by the writer.
+ '''
+ grd.SetOutputLanguage(env_lang)
+ grd.SetDefines(env_defs)
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(grd, DummyOutput(out_type, out_lang), buf)
+ return buf.getvalue()
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py b/chromium/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py
new file mode 100644
index 00000000000..b28d8b672db
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from grit.format.policy_templates.writers import template_writer
+
+
+class XMLFormattedWriter(template_writer.TemplateWriter):
+ '''Helper class for generating XML-based templates.
+ '''
+
+ def AddElement(self, parent, name, attrs=None, text=None):
+ '''
+ Adds a new XML Element as a child to an existing element or the Document.
+
+ Args:
+ parent: An XML element or the document, where the new element will be
+ added.
+ name: The name of the new element.
+ attrs: A dictionary of the attributes' names and values for the new
+ element.
+ text: Text content for the new element.
+
+ Returns:
+ The created new element.
+ '''
+ if attrs == None:
+ attrs = {}
+
+ doc = parent.ownerDocument
+ element = doc.createElement(name)
+ for key, value in attrs.iteritems():
+ element.setAttribute(key, value)
+ if text:
+ element.appendChild(doc.createTextNode(text))
+ parent.appendChild(element)
+ return element
+
+ def AddText(self, parent, text):
+ '''Adds text to a parent node.
+ '''
+ doc = parent.ownerDocument
+ parent.appendChild(doc.createTextNode(text))
+
+ def AddAttribute(self, parent, name, value):
+ '''Adds a new attribute to the parent Element. If an attribute with the
+ given name already exists then it will be replaced.
+ '''
+ doc = parent.ownerDocument
+ attribute = doc.createAttribute(name)
+ attribute.value = value
+ parent.setAttributeNode(attribute)
+
+ def ToPrettyXml(self, doc):
+ # return doc.toprettyxml(indent=' ')
+ # The above pretty-printer does not print the doctype and adds spaces
+ # around texts, e.g.:
+ # <string>
+ # value of the string
+ # </string>
+ # This is problematic both for the OSX Workgroup Manager (plist files) and
+ # the Windows Group Policy Editor (admx files). What they need instead:
+ # <string>value of string</string>
+ # So we use the poor man's pretty printer here. It assumes that there are
+ # no mixed-content nodes.
+ # Get all the XML content in a one-line string.
+ xml = doc.toxml()
+ # Determine where the line breaks will be. (They will only be between tags.)
+ lines = xml[1:len(xml) - 1].split('><')
+ indent = ''
+ res = ''
+ # Determine indent for each line.
+ for i, line in enumerate(lines):
+ if line[0] == '/':
+ # If the current line starts with a closing tag, decrease indent before
+ # printing.
+ indent = indent[2:]
+ lines[i] = indent + '<' + line + '>'
+ if (line[0] not in ['/', '?', '!'] and '</' not in line and
+ line[len(line) - 1] != '/'):
+ # If the current line starts with an opening tag and does not conatin a
+ # closing tag, increase indent after the line is printed.
+ indent += ' '
+ # Reconstruct XML text from the lines.
+ return '\n'.join(lines)
diff --git a/chromium/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py b/chromium/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py
new file mode 100644
index 00000000000..cfa5dc26854
--- /dev/null
+++ b/chromium/tools/grit/grit/format/policy_templates/writers/xml_writer_base_unittest.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Unittests for grit.format.policy_templates.writers.admx_writer."""
+
+
+import re
+import unittest
+
+
+class XmlWriterBaseTest(unittest.TestCase):
+ '''Base class for XML writer unit-tests.
+ '''
+
+ def GetXMLOfChildren(self, parent):
+ '''Returns the XML of all child nodes of the given parent node.
+ Args:
+ parent: The XML of the children of this node will be returned.
+
+ Return: XML of the chrildren of the parent node.
+ '''
+ raw_pretty_xml = ''.join(
+ child.toprettyxml(indent=' ') for child in parent.childNodes)
+ # Python 2.6.5 which is present in Lucid has bug in its pretty print
+ # function which produces new lines around string literals. This has been
+ # fixed in Precise which has Python 2.7.3 but we have to keep compatibility
+ # with both for now.
+ text_re = re.compile('>\n\s+([^<>\s].*?)\n\s*</', re.DOTALL)
+ return text_re.sub('>\g<1></', raw_pretty_xml)
+
+ def AssertXMLEquals(self, output, expected_output):
+ '''Asserts if the passed XML arguements are equal.
+ Args:
+ output: Actual XML text.
+ expected_output: Expected XML text.
+ '''
+ self.assertEquals(output.strip(), expected_output.strip())
diff --git a/chromium/tools/grit/grit/format/rc.py b/chromium/tools/grit/grit/format/rc.py
new file mode 100644
index 00000000000..6c6a1657233
--- /dev/null
+++ b/chromium/tools/grit/grit/format/rc.py
@@ -0,0 +1,473 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Support for formatting an RC file for compilation.
+'''
+
+import os
+import types
+import re
+from functools import partial
+
+from grit import util
+from grit.node import misc
+
+
+def Format(root, lang='en', output_dir='.'):
+ from grit.node import empty, include, message, structure
+
+ yield _FormatHeader(root, lang, output_dir)
+
+ for item in root.ActiveDescendants():
+ if isinstance(item, empty.MessagesNode):
+ # Write one STRINGTABLE per <messages> container.
+ # This is hacky: it iterates over the children twice.
+ yield 'STRINGTABLE\nBEGIN\n'
+ for subitem in item.ActiveDescendants():
+ if isinstance(subitem, message.MessageNode):
+ with subitem:
+ yield FormatMessage(subitem, lang)
+ yield 'END\n\n'
+ elif isinstance(item, include.IncludeNode):
+ with item:
+ yield FormatInclude(item, lang, output_dir)
+ elif isinstance(item, structure.StructureNode):
+ with item:
+ yield FormatStructure(item, lang, output_dir)
+
+
+'''
+This dictionary defines the language charset pair lookup table, which is used
+for replacing the GRIT expand variables for language info in Product Version
+resource. The key is the language ISO country code, and the value
+is the language and character-set pair, which is a hexadecimal string
+consisting of the concatenation of the language and character-set identifiers.
+The first 4 digit of the value is the hex value of LCID, the remaining
+4 digits is the hex value of character-set id(code page)of the language.
+
+LCID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
+Codepage resource: http://www.science.co.il/language/locale-codes.asp
+
+We have defined three GRIT expand_variables to be used in the version resource
+file to set the language info. Here is an example how they should be used in
+the VS_VERSION_INFO section of the resource file to allow GRIT to localize
+the language info correctly according to product locale.
+
+VS_VERSION_INFO VERSIONINFO
+...
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "[GRITVERLANGCHARSETHEX]"
+ BEGIN
+ ...
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", [GRITVERLANGID], [GRITVERCHARSETID]
+ END
+END
+
+'''
+
+_LANGUAGE_CHARSET_PAIR = {
+ # Language neutral LCID, unicode(1200) code page.
+ 'neutral' : '000004b0',
+ # LANG_USER_DEFAULT LCID, unicode(1200) code page.
+ 'userdefault' : '040004b0',
+ 'ar' : '040104e8',
+ 'fi' : '040b04e4',
+ 'ko' : '041203b5',
+ 'es' : '040a04e4',
+ 'bg' : '040204e3',
+ # No codepage for filipino, use unicode(1200).
+ 'fil' : '046404e4',
+ 'fr' : '040c04e4',
+ 'lv' : '042604e9',
+ 'sv' : '041d04e4',
+ 'ca' : '040304e4',
+ 'de' : '040704e4',
+ 'lt' : '042704e9',
+ # Do not use! This is only around for backwards
+ # compatibility and will be removed - use fil instead
+ 'tl' : '0c0004b0',
+ 'zh-CN' : '080403a8',
+ 'zh-TW' : '040403b6',
+ 'zh-HK' : '0c0403b6',
+ 'el' : '040804e5',
+ 'no' : '041404e4',
+ 'th' : '041e036a',
+ 'he' : '040d04e7',
+ 'iw' : '040d04e7',
+ 'pl' : '041504e2',
+ 'tr' : '041f04e6',
+ 'hr' : '041a04e4',
+ # No codepage for Hindi, use unicode(1200).
+ 'hi' : '043904b0',
+ 'pt-PT' : '081604e4',
+ 'pt-BR' : '041604e4',
+ 'uk' : '042204e3',
+ 'cs' : '040504e2',
+ 'hu' : '040e04e2',
+ 'ro' : '041804e2',
+ # No codepage for Urdu, use unicode(1200).
+ 'ur' : '042004b0',
+ 'da' : '040604e4',
+ 'is' : '040f04e4',
+ 'ru' : '041904e3',
+ 'vi' : '042a04ea',
+ 'nl' : '041304e4',
+ 'id' : '042104e4',
+ 'sr' : '081a04e2',
+ 'en-GB' : '0809040e',
+ 'it' : '041004e4',
+ 'sk' : '041b04e2',
+ 'et' : '042504e9',
+ 'ja' : '041103a4',
+ 'sl' : '042404e2',
+ 'en' : '040904b0',
+ # LCID for Mexico; Windows does not support L.A. LCID.
+ 'es-419' : '080a04e4',
+ # No codepage for Bengali, use unicode(1200).
+ 'bn' : '044504b0',
+ 'fa' : '042904e8',
+ # No codepage for Gujarati, use unicode(1200).
+ 'gu' : '044704b0',
+ # No codepage for Kannada, use unicode(1200).
+ 'kn' : '044b04b0',
+ # Malay (Malaysia) [ms-MY]
+ 'ms' : '043e04e4',
+ # No codepage for Malayalam, use unicode(1200).
+ 'ml' : '044c04b0',
+ # No codepage for Marathi, use unicode(1200).
+ 'mr' : '044e04b0',
+ # No codepage for Oriya , use unicode(1200).
+ 'or' : '044804b0',
+ # No codepage for Tamil, use unicode(1200).
+ 'ta' : '044904b0',
+ # No codepage for Telugu, use unicode(1200).
+ 'te' : '044a04b0',
+ # No codepage for Amharic, use unicode(1200). >= Vista.
+ 'am' : '045e04b0',
+ 'sw' : '044104e4',
+ 'af' : '043604e4',
+ 'eu' : '042d04e4',
+ 'fr-CA' : '0c0c04e4',
+ 'gl' : '045604e4',
+ # No codepage for Zulu, use unicode(1200).
+ 'zu' : '043504b0',
+ 'fake-bidi' : '040d04e7',
+}
+
+# Language ID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
+#
+# There is no appropriate sublang for Spanish (Latin America) [es-419], so we
+# use Mexico. SUBLANG_DEFAULT would incorrectly map to Spain. Unlike other
+# Latin American countries, Mexican Spanish is supported by VERSIONINFO:
+# http://msdn.microsoft.com/en-us/library/aa381058.aspx
+
+_LANGUAGE_DIRECTIVE_PAIR = {
+ 'neutral' : 'LANG_NEUTRAL, SUBLANG_NEUTRAL',
+ 'userdefault' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
+ 'ar' : 'LANG_ARABIC, SUBLANG_DEFAULT',
+ 'fi' : 'LANG_FINNISH, SUBLANG_DEFAULT',
+ 'ko' : 'LANG_KOREAN, SUBLANG_KOREAN',
+ 'es' : 'LANG_SPANISH, SUBLANG_SPANISH_MODERN',
+ 'bg' : 'LANG_BULGARIAN, SUBLANG_DEFAULT',
+ # LANG_FILIPINO (100) not in VC 7 winnt.h.
+ 'fil' : '100, SUBLANG_DEFAULT',
+ 'fr' : 'LANG_FRENCH, SUBLANG_FRENCH',
+ 'lv' : 'LANG_LATVIAN, SUBLANG_DEFAULT',
+ 'sv' : 'LANG_SWEDISH, SUBLANG_SWEDISH',
+ 'ca' : 'LANG_CATALAN, SUBLANG_DEFAULT',
+ 'de' : 'LANG_GERMAN, SUBLANG_GERMAN',
+ 'lt' : 'LANG_LITHUANIAN, SUBLANG_LITHUANIAN',
+ # Do not use! See above.
+ 'tl' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
+ 'zh-CN' : 'LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED',
+ 'zh-TW' : 'LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL',
+ 'zh-HK' : 'LANG_CHINESE, SUBLANG_CHINESE_HONGKONG',
+ 'el' : 'LANG_GREEK, SUBLANG_DEFAULT',
+ 'no' : 'LANG_NORWEGIAN, SUBLANG_DEFAULT',
+ 'th' : 'LANG_THAI, SUBLANG_DEFAULT',
+ 'he' : 'LANG_HEBREW, SUBLANG_DEFAULT',
+ 'iw' : 'LANG_HEBREW, SUBLANG_DEFAULT',
+ 'pl' : 'LANG_POLISH, SUBLANG_DEFAULT',
+ 'tr' : 'LANG_TURKISH, SUBLANG_DEFAULT',
+ 'hr' : 'LANG_CROATIAN, SUBLANG_DEFAULT',
+ 'hi' : 'LANG_HINDI, SUBLANG_DEFAULT',
+ 'pt-PT' : 'LANG_PORTUGUESE, SUBLANG_PORTUGUESE',
+ 'pt-BR' : 'LANG_PORTUGUESE, SUBLANG_DEFAULT',
+ 'uk' : 'LANG_UKRAINIAN, SUBLANG_DEFAULT',
+ 'cs' : 'LANG_CZECH, SUBLANG_DEFAULT',
+ 'hu' : 'LANG_HUNGARIAN, SUBLANG_DEFAULT',
+ 'ro' : 'LANG_ROMANIAN, SUBLANG_DEFAULT',
+ 'ur' : 'LANG_URDU, SUBLANG_DEFAULT',
+ 'da' : 'LANG_DANISH, SUBLANG_DEFAULT',
+ 'is' : 'LANG_ICELANDIC, SUBLANG_DEFAULT',
+ 'ru' : 'LANG_RUSSIAN, SUBLANG_DEFAULT',
+ 'vi' : 'LANG_VIETNAMESE, SUBLANG_DEFAULT',
+ 'nl' : 'LANG_DUTCH, SUBLANG_DEFAULT',
+ 'id' : 'LANG_INDONESIAN, SUBLANG_DEFAULT',
+ 'sr' : 'LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC',
+ 'en-GB' : 'LANG_ENGLISH, SUBLANG_ENGLISH_UK',
+ 'it' : 'LANG_ITALIAN, SUBLANG_DEFAULT',
+ 'sk' : 'LANG_SLOVAK, SUBLANG_DEFAULT',
+ 'et' : 'LANG_ESTONIAN, SUBLANG_DEFAULT',
+ 'ja' : 'LANG_JAPANESE, SUBLANG_DEFAULT',
+ 'sl' : 'LANG_SLOVENIAN, SUBLANG_DEFAULT',
+ 'en' : 'LANG_ENGLISH, SUBLANG_ENGLISH_US',
+ # No L.A. sublang exists.
+ 'es-419' : 'LANG_SPANISH, SUBLANG_SPANISH_MEXICAN',
+ 'bn' : 'LANG_BENGALI, SUBLANG_DEFAULT',
+ 'fa' : 'LANG_PERSIAN, SUBLANG_DEFAULT',
+ 'gu' : 'LANG_GUJARATI, SUBLANG_DEFAULT',
+ 'kn' : 'LANG_KANNADA, SUBLANG_DEFAULT',
+ 'ms' : 'LANG_MALAY, SUBLANG_DEFAULT',
+ 'ml' : 'LANG_MALAYALAM, SUBLANG_DEFAULT',
+ 'mr' : 'LANG_MARATHI, SUBLANG_DEFAULT',
+ 'or' : 'LANG_ORIYA, SUBLANG_DEFAULT',
+ 'ta' : 'LANG_TAMIL, SUBLANG_DEFAULT',
+ 'te' : 'LANG_TELUGU, SUBLANG_DEFAULT',
+ 'am' : 'LANG_AMHARIC, SUBLANG_DEFAULT',
+ 'sw' : 'LANG_SWAHILI, SUBLANG_DEFAULT',
+ 'af' : 'LANG_AFRIKAANS, SUBLANG_DEFAULT',
+ 'eu' : 'LANG_BASQUE, SUBLANG_DEFAULT',
+ 'fr-CA' : 'LANG_FRENCH, SUBLANG_FRENCH_CANADIAN',
+ 'gl' : 'LANG_GALICIAN, SUBLANG_DEFAULT',
+ 'zu' : 'LANG_ZULU, SUBLANG_DEFAULT',
+ 'pa' : 'LANG_PUNJABI, SUBLANG_PUNJABI_INDIA',
+ 'sa' : 'LANG_SANSKRIT, SUBLANG_SANSKRIT_INDIA',
+ 'si' : 'LANG_SINHALESE, SUBLANG_SINHALESE_SRI_LANKA',
+ 'ne' : 'LANG_NEPALI, SUBLANG_NEPALI_NEPAL',
+ 'ti' : 'LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ERITREA',
+ 'fake-bidi' : 'LANG_HEBREW, SUBLANG_DEFAULT',
+}
+
+# A note on 'no-specific-language' in the following few functions:
+# Some build systems may wish to call GRIT to scan for dependencies in
+# a language-agnostic way, and can then specify this fake language as
+# the output context. It should never be used when output is actually
+# being generated.
+
+def GetLangCharsetPair(language):
+ if _LANGUAGE_CHARSET_PAIR.has_key(language):
+ return _LANGUAGE_CHARSET_PAIR[language]
+ elif language == 'no-specific-language':
+ return ''
+ else:
+ print 'Warning:GetLangCharsetPair() found undefined language %s' %(language)
+ return ''
+
+def GetLangDirectivePair(language):
+ if _LANGUAGE_DIRECTIVE_PAIR.has_key(language):
+ return _LANGUAGE_DIRECTIVE_PAIR[language]
+ else:
+ # We don't check for 'no-specific-language' here because this
+ # function should only get called when output is being formatted,
+ # and at that point we would not want to get
+ # 'no-specific-language' passed as the language.
+ print ('Warning:GetLangDirectivePair() found undefined language %s' %
+ language)
+ return 'unknown language: see tools/grit/format/rc.py'
+
+def GetLangIdHex(language):
+ if _LANGUAGE_CHARSET_PAIR.has_key(language):
+ langcharset = _LANGUAGE_CHARSET_PAIR[language]
+ lang_id = '0x' + langcharset[0:4]
+ return lang_id
+ elif language == 'no-specific-language':
+ return ''
+ else:
+ print 'Warning:GetLangIdHex() found undefined language %s' %(language)
+ return ''
+
+
+def GetCharsetIdDecimal(language):
+ if _LANGUAGE_CHARSET_PAIR.has_key(language):
+ langcharset = _LANGUAGE_CHARSET_PAIR[language]
+ charset_decimal = int(langcharset[4:], 16)
+ return str(charset_decimal)
+ elif language == 'no-specific-language':
+ return ''
+ else:
+ print 'Warning:GetCharsetIdDecimal() found undefined language %s' % language
+ return ''
+
+
+def GetUnifiedLangCode(language) :
+ r = re.compile('([a-z]{1,2})_([a-z]{1,2})')
+ if r.match(language) :
+ underscore = language.find('_')
+ return language[0:underscore] + '-' + language[underscore + 1:].upper()
+ else :
+ return language
+
+
+def RcSubstitutions(substituter, lang):
+ '''Add language-based substitutions for Rc files to the substitutor.'''
+ unified_lang_code = GetUnifiedLangCode(lang)
+ substituter.AddSubstitutions({
+ 'GRITVERLANGCHARSETHEX': GetLangCharsetPair(unified_lang_code),
+ 'GRITVERLANGID': GetLangIdHex(unified_lang_code),
+ 'GRITVERCHARSETID': GetCharsetIdDecimal(unified_lang_code)})
+
+
+def _FormatHeader(root, lang, output_dir):
+ '''Returns the required preamble for RC files.'''
+ assert isinstance(lang, types.StringTypes)
+ assert isinstance(root, misc.GritNode)
+ # Find the location of the resource header file, so that we can include
+ # it.
+ resource_header = 'resource.h' # fall back to this
+ language_directive = ''
+ for output in root.GetOutputFiles():
+ if output.attrs['type'] == 'rc_header':
+ resource_header = os.path.abspath(output.GetOutputFilename())
+ resource_header = util.MakeRelativePath(output_dir, resource_header)
+ if output.attrs['lang'] != lang:
+ continue
+ if output.attrs['language_section'] == '':
+ # If no language_section is requested, no directive is added
+ # (Used when the generated rc will be included from another rc
+ # file that will have the appropriate language directive)
+ language_directive = ''
+ elif output.attrs['language_section'] == 'neutral':
+ # If a neutral language section is requested (default), add a
+ # neutral language directive
+ language_directive = 'LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL'
+ elif output.attrs['language_section'] == 'lang':
+ language_directive = 'LANGUAGE %s' % GetLangDirectivePair(lang)
+ resource_header = resource_header.replace('\\', '\\\\')
+ return '''// This file is automatically generated by GRIT. Do not edit.
+
+#include "%s"
+#include <winresrc.h>
+#ifdef IDC_STATIC
+#undef IDC_STATIC
+#endif
+#define IDC_STATIC (-1)
+
+%s
+
+
+''' % (resource_header, language_directive)
+# end _FormatHeader() function
+
+
+def FormatMessage(item, lang):
+ '''Returns a single message of a string table.'''
+ message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
+ # Escape quotation marks (RC format uses doubling-up
+ message = message.replace('"', '""')
+ # Replace linebreaks with a \n escape
+ message = util.LINEBREAKS.sub(r'\\n', message)
+ if hasattr(item.GetRoot(), 'GetSubstituter'):
+ substituter = item.GetRoot().GetSubstituter()
+ message = substituter.Substitute(message)
+
+ name_attr = item.GetTextualIds()[0]
+
+ return ' %-15s "%s"\n' % (name_attr, message)
+
+
+def _FormatSection(item, lang, output_dir):
+ '''Writes out an .rc file section.'''
+ assert isinstance(lang, types.StringTypes)
+ from grit.node import structure
+ assert isinstance(item, structure.StructureNode)
+
+ if item.IsExcludedFromRc():
+ return ''
+ else:
+ text = item.gatherer.Translate(
+ lang, skeleton_gatherer=item.GetSkeletonGatherer(),
+ pseudo_if_not_available=item.PseudoIsAllowed(),
+ fallback_to_english=item.ShouldFallbackToEnglish()) + '\n\n'
+
+ # Replace the language expand_variables in version rc info.
+ if item.ExpandVariables() and hasattr(item.GetRoot(), 'GetSubstituter'):
+ substituter = item.GetRoot().GetSubstituter()
+ text = substituter.Substitute(text)
+
+ return text
+
+
+def FormatInclude(item, lang, output_dir, type=None, process_html=False):
+ '''Formats an item that is included in an .rc file (e.g. an ICON).
+
+ Args:
+ item: an IncludeNode or StructureNode
+ lang, output_dir: standard formatter parameters
+ type: .rc file resource type, e.g. 'ICON' (ignored unless item is a
+ StructureNode)
+ process_html: False/True (ignored unless item is a StructureNode)
+ '''
+ assert isinstance(lang, types.StringTypes)
+ from grit.node import structure
+ from grit.node import include
+ assert isinstance(item, (structure.StructureNode, include.IncludeNode))
+
+ if isinstance(item, include.IncludeNode):
+ type = item.attrs['type'].upper()
+ process_html = item.attrs['flattenhtml'] == 'true'
+ filename_only = item.attrs['filenameonly'] == 'true'
+ relative_path = item.attrs['relativepath'] == 'true'
+ else:
+ assert (isinstance(item, structure.StructureNode) and item.attrs['type'] in
+ ['admin_template', 'chrome_html', 'chrome_scaled_image', 'igoogle',
+ 'muppet', 'tr_html', 'txt'])
+ filename_only = False
+ relative_path = False
+
+ # By default, we use relative pathnames to included resources so that
+ # sharing the resulting .rc files is possible.
+ #
+ # The FileForLanguage() Function has the side effect of generating the file
+ # if needed (e.g. if it is an HTML file include).
+ filename = os.path.abspath(item.FileForLanguage(lang, output_dir))
+ if process_html:
+ filename = item.Process(output_dir)
+ elif filename_only:
+ filename = os.path.basename(filename)
+ elif relative_path:
+ filename = util.MakeRelativePath(output_dir, filename)
+
+ filename = filename.replace('\\', '\\\\') # escape for the RC format
+
+ if isinstance(item, structure.StructureNode) and item.IsExcludedFromRc():
+ return ''
+ else:
+ return '%-18s %-18s "%s"\n' % (item.attrs['name'], type, filename)
+
+
+def _DoNotFormat(item, lang, output_dir):
+ return ''
+
+
+# Formatter instance to use for each type attribute
+# when formatting Structure nodes.
+_STRUCTURE_FORMATTERS = {
+ 'accelerators' : _FormatSection,
+ 'dialog' : _FormatSection,
+ 'menu' : _FormatSection,
+ 'rcdata' : _FormatSection,
+ 'version' : _FormatSection,
+ 'admin_template' : partial(FormatInclude, type='ADM'),
+ 'chrome_html' : partial(FormatInclude, type='BINDATA',
+ process_html=True),
+ 'chrome_scaled_image' : partial(FormatInclude, type='BINDATA'),
+ 'igoogle' : partial(FormatInclude, type='XML'),
+ 'muppet' : partial(FormatInclude, type='XML'),
+ 'tr_html' : partial(FormatInclude, type='HTML'),
+ 'txt' : partial(FormatInclude, type='TXT'),
+ 'policy_template_metafile': _DoNotFormat,
+}
+
+
+def FormatStructure(item, lang, output_dir):
+ formatter = _STRUCTURE_FORMATTERS[item.attrs['type']]
+ return formatter(item, lang, output_dir)
diff --git a/chromium/tools/grit/grit/format/rc_header.py b/chromium/tools/grit/grit/format/rc_header.py
new file mode 100644
index 00000000000..118e94ce951
--- /dev/null
+++ b/chromium/tools/grit/grit/format/rc_header.py
@@ -0,0 +1,198 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Item formatters for RC headers.
+'''
+
+from grit import exception
+from grit import util
+from grit.extern import FP
+
+
+def Format(root, lang='en', output_dir='.'):
+ yield '''\
+// This file is automatically generated by GRIT. Do not edit.
+
+#pragma once
+'''
+ # Check for emit nodes under the rc_header. If any emit node
+ # is present, we assume it means the GRD file wants to override
+ # the default header, with no includes.
+ default_includes = ['#include <atlres.h>', '']
+ emit_lines = []
+ for output_node in root.GetOutputFiles():
+ if output_node.GetType() == 'rc_header':
+ for child in output_node.children:
+ if child.name == 'emit' and child.attrs['emit_type'] == 'prepend':
+ emit_lines.append(child.GetCdata())
+ for line in emit_lines or default_includes:
+ yield line + '\n'
+
+ for line in FormatDefines(root, root.ShouldOutputAllResourceDefines()):
+ yield line
+
+
+def FormatDefines(root, output_all_resource_defines=True):
+ '''Yields #define SYMBOL 1234 lines.
+
+ Args:
+ root: A GritNode.
+ output_all_resource_defines: If False, output only the symbols used in the
+ current output configuration.
+ '''
+ from grit.node import message
+ tids = GetIds(root)
+
+ if output_all_resource_defines:
+ items = root.Preorder()
+ else:
+ items = root.ActiveDescendants()
+
+ seen = set()
+ for item in items:
+ if not isinstance(item, message.MessageNode):
+ with item:
+ for tid in item.GetTextualIds():
+ if tid in tids and tid not in seen:
+ seen.add(tid)
+ yield '#define %s %d\n' % (tid, tids[tid])
+ # Temporarily mimic old behavior: MessageNodes were only output if active,
+ # even with output_all_resource_defines set. TODO(benrg): Remove this after
+ # fixing problems in the Chrome tree.
+ for item in root.ActiveDescendants():
+ if isinstance(item, message.MessageNode):
+ with item:
+ for tid in item.GetTextualIds():
+ if tid in tids and tid not in seen:
+ seen.add(tid)
+ yield '#define %s %d\n' % (tid, tids[tid])
+
+
+_cached_ids = {}
+
+
+def GetIds(root):
+ '''Return a dictionary mapping textual ids to numeric ids for the given tree.
+
+ Args:
+ root: A GritNode.
+ '''
+ # TODO(benrg): Since other formatters use this, it might make sense to move it
+ # and _ComputeIds to GritNode and store the cached ids as an attribute. On the
+ # other hand, GritNode has too much random stuff already.
+ if root not in _cached_ids:
+ _cached_ids[root] = _ComputeIds(root)
+ return _cached_ids[root]
+
+
+def _ComputeIds(root):
+ from grit.node import empty, include, message, misc, structure
+
+ ids = {} # Maps numeric id to textual id
+ tids = {} # Maps textual id to numeric id
+ id_reasons = {} # Maps numeric id to text id and a human-readable explanation
+ group = None
+ last_id = None
+
+ for item in root:
+ if isinstance(item, empty.GroupingNode):
+ # Note: this won't work if any GroupingNode can be contained inside
+ # another.
+ group = item
+ last_id = None
+ continue
+
+ assert not item.GetTextualIds() or isinstance(item,
+ (include.IncludeNode, message.MessageNode,
+ misc.IdentifierNode, structure.StructureNode))
+
+ # Resources that use the RES protocol don't need
+ # any numerical ids generated, so we skip them altogether.
+ # This is accomplished by setting the flag 'generateid' to false
+ # in the GRD file.
+ if item.attrs.get('generateid', 'true') == 'false':
+ continue
+
+ for tid in item.GetTextualIds():
+ if util.SYSTEM_IDENTIFIERS.match(tid):
+ # Don't emit a new ID for predefined IDs
+ continue
+
+ if tid in tids:
+ continue
+
+ # Some identifier nodes can provide their own id,
+ # and we use that id in the generated header in that case.
+ if hasattr(item, 'GetId') and item.GetId():
+ id = long(item.GetId())
+ reason = 'returned by GetId() method'
+
+ elif ('offset' in item.attrs and group and
+ group.attrs.get('first_id', '') != ''):
+ offset_text = item.attrs['offset']
+ parent_text = group.attrs['first_id']
+
+ try:
+ offset_id = long(offset_text)
+ except ValueError:
+ offset_id = tids[offset_text]
+
+ try:
+ parent_id = long(parent_text)
+ except ValueError:
+ parent_id = tids[parent_text]
+
+ id = parent_id + offset_id
+ reason = 'first_id %d + offset %d' % (parent_id, offset_id)
+
+ # We try to allocate IDs sequentially for blocks of items that might
+ # be related, for instance strings in a stringtable (as their IDs might be
+ # used e.g. as IDs for some radio buttons, in which case the IDs must
+ # be sequential).
+ #
+ # We do this by having the first item in a section store its computed ID
+ # (computed from a fingerprint) in its parent object. Subsequent children
+ # of the same parent will then try to get IDs that sequentially follow
+ # the currently stored ID (on the parent) and increment it.
+ elif last_id is None:
+ # First check if the starting ID is explicitly specified by the parent.
+ if group and group.attrs.get('first_id', '') != '':
+ id = long(group.attrs['first_id'])
+ reason = "from parent's first_id attribute"
+ else:
+ # Automatically generate the ID based on the first clique from the
+ # first child of the first child node of our parent (i.e. when we
+ # first get to this location in the code).
+
+ # According to
+ # http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
+ # the safe usable range for resource IDs in Windows is from decimal
+ # 101 to 0x7FFF.
+
+ id = FP.UnsignedFingerPrint(tid)
+ id = id % (0x7FFF - 101) + 101
+ reason = 'chosen by random fingerprint -- use first_id to override'
+
+ last_id = id
+ else:
+ id = last_id = last_id + 1
+ reason = 'sequentially assigned'
+
+ reason = "%s (%s)" % (tid, reason)
+ # Don't fail when 'offset' is specified, as the base and the 0th
+ # offset will have the same ID.
+ if id in id_reasons and not 'offset' in item.attrs:
+ raise exception.IdRangeOverlap('ID %d was assigned to both %s and %s.'
+ % (id, id_reasons[id], reason))
+
+ if id < 101:
+ print ('WARNING: Numeric resource IDs should be greater than 100 to\n'
+ 'avoid conflicts with system-defined resource IDs.')
+
+ ids[id] = tid
+ tids[tid] = id
+ id_reasons[id] = reason
+
+ return tids
diff --git a/chromium/tools/grit/grit/format/rc_header_unittest.py b/chromium/tools/grit/grit/format/rc_header_unittest.py
new file mode 100644
index 00000000000..433ff7d8027
--- /dev/null
+++ b/chromium/tools/grit/grit/format/rc_header_unittest.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for the rc_header formatter'''
+
+# GRD samples exceed the 80 character limit.
+# pylint: disable-msg=C6310
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import StringIO
+import unittest
+
+from grit import exception
+from grit import grd_reader
+from grit import util
+from grit.format import rc_header
+
+
+class RcHeaderFormatterUnittest(unittest.TestCase):
+ def FormatAll(self, grd):
+ output = rc_header.FormatDefines(grd, grd.ShouldOutputAllResourceDefines())
+ return ''.join(output).replace(' ', '')
+
+ def testFormatter(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
+ <release seq="3">
+ <includes first_id="300" comment="bingo">
+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
+ </includes>
+ <messages first_id="10000">
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ <message name="IDS_BONGO">
+ Bongo!
+ </message>
+ </messages>
+ <structures>
+ <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc" />
+ <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc" />
+ </structures>
+ </release>
+ </grit>'''), '.')
+ output = self.FormatAll(grd)
+ self.failUnless(output.count('IDS_GREETING10000'))
+ self.failUnless(output.count('ID_LOGO300'))
+
+ def testOnlyDefineResourcesThatSatisfyOutputCondition(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en" current_release="3"
+ base_dir="." output_all_resource_defines="false">
+ <release seq="3">
+ <includes first_id="300" comment="bingo">
+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
+ </includes>
+ <messages first_id="10000">
+ <message name="IDS_FIRSTPRESENTSTRING" desc="Present in .rc file.">
+ I will appear in the .rc file.
+ </message>
+ <if expr="False"> <!--Do not include in the .rc files until used.-->
+ <message name="IDS_MISSINGSTRING" desc="Not present in .rc file.">
+ I will not appear in the .rc file.
+ </message>
+ </if>
+ <if expr="lang != 'es'">
+ <message name="IDS_LANGUAGESPECIFICSTRING" desc="Present in .rc file.">
+ Hello.
+ </message>
+ </if>
+ <if expr="lang == 'es'">
+ <message name="IDS_LANGUAGESPECIFICSTRING" desc="Present in .rc file.">
+ Hola.
+ </message>
+ </if>
+ <message name="IDS_THIRDPRESENTSTRING" desc="Present in .rc file.">
+ I will also appear in the .rc file.
+ </message>
+ </messages>
+ </release>
+ </grit>'''), '.')
+ output = self.FormatAll(grd)
+ self.failUnless(output.count('IDS_FIRSTPRESENTSTRING10000'))
+ self.failIf(output.count('IDS_MISSINGSTRING'))
+ self.failIf(output.count('10001')) # IDS_MISSINGSTRING should get this ID
+ self.failUnless(output.count('IDS_LANGUAGESPECIFICSTRING10002'))
+ self.failUnless(output.count('IDS_THIRDPRESENTSTRING10003'))
+
+ def testExplicitFirstIdOverlaps(self):
+ # second first_id will overlap preexisting range
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
+ <release seq="3">
+ <includes first_id="300" comment="bingo">
+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
+ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
+ </includes>
+ <messages first_id="301">
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ <message name="IDS_SMURFGEBURF">Frubegfrums</message>
+ </messages>
+ </release>
+ </grit>'''), '.')
+ self.assertRaises(exception.IdRangeOverlap, self.FormatAll, grd)
+
+ def testImplicitOverlapsPreexisting(self):
+ # second message in <messages> will overlap preexisting range
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
+ <release seq="3">
+ <includes first_id="301" comment="bingo">
+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
+ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
+ </includes>
+ <messages first_id="300">
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ <message name="IDS_SMURFGEBURF">Frubegfrums</message>
+ </messages>
+ </release>
+ </grit>'''), '.')
+ self.assertRaises(exception.IdRangeOverlap, self.FormatAll, grd)
+
+ def testEmit(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
+ <outputs>
+ <output type="rc_all" filename="dummy">
+ <emit emit_type="prepend">Wrong</emit>
+ </output>
+ <if expr="False">
+ <output type="rc_header" filename="dummy">
+ <emit emit_type="prepend">No</emit>
+ </output>
+ </if>
+ <output type="rc_header" filename="dummy">
+ <emit emit_type="append">Error</emit>
+ </output>
+ <output type="rc_header" filename="dummy">
+ <emit emit_type="prepend">Bingo</emit>
+ </output>
+ </outputs>
+ </grit>'''), '.')
+ output = ''.join(rc_header.Format(grd, 'en', '.'))
+ output = util.StripBlankLinesAndComments(output)
+ self.assertEqual('#pragma once\nBingo', output)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/rc_unittest.py b/chromium/tools/grit/grit/format/rc_unittest.py
new file mode 100644
index 00000000000..a38001b1531
--- /dev/null
+++ b/chromium/tools/grit/grit/format/rc_unittest.py
@@ -0,0 +1,409 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.rc'''
+
+import os
+import re
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import tempfile
+import unittest
+import StringIO
+
+from grit import grd_reader
+from grit import util
+from grit.node import structure
+from grit.tool import build
+
+
+_PREAMBLE = '''\
+#include "resource.h"
+#include <winresrc.h>
+#ifdef IDC_STATIC
+#undef IDC_STATIC
+#endif
+#define IDC_STATIC (-1)
+'''
+
+
+class DummyOutput(object):
+ def __init__(self, type, language, file = 'hello.gif'):
+ self.type = type
+ self.language = language
+ self.file = file
+ def GetType(self):
+ return self.type
+ def GetLanguage(self):
+ return self.language
+ def GetOutputFilename(self):
+ return self.file
+
+class FormatRcUnittest(unittest.TestCase):
+ def testMessages(self):
+ root = util.ParseGrdForUnittest('''
+ <messages>
+ <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ <message name="BONGO" desc="Flippo nippo">
+ Howdie "Mr. Elephant", how are you doing? \'\'\'
+ </message>
+ <message name="IDS_WITH_LINEBREAKS">
+Good day sir,
+I am a bee
+Sting sting
+ </message>
+ </messages>
+ ''')
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ self.assertEqual(_PREAMBLE + u'''\
+STRINGTABLE
+BEGIN
+ IDS_BTN_GO "Go!"
+ IDS_GREETING "Hello %s, how are you doing today?"
+ BONGO "Howdie ""Mr. Elephant"", how are you doing? "
+ IDS_WITH_LINEBREAKS "Good day sir,\\nI am a bee\\nSting sting"
+END''', output)
+
+
+ def testRcSection(self):
+ root = util.ParseGrdForUnittest('''
+ <structures>
+ <structure type="menu" name="IDC_KLONKMENU" file="grit\\testdata\klonk.rc" encoding="utf-16" />
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\testdata\klonk.rc" encoding="utf-16" />
+ <structure type="version" name="VS_VERSION_INFO" file="grit\\testdata\klonk.rc" encoding="utf-16" />
+ </structures>''')
+ root.SetOutputLanguage('en')
+ root.RunGatherers()
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ expected = _PREAMBLE + u'''\
+IDC_KLONKMENU MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "E&xit", IDM_EXIT
+ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
+ POPUP "gonk"
+ BEGIN
+ MENUITEM "Klonk && is [good]", ID_GONK_KLONKIS
+ END
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About ...", IDM_ABOUT
+ END
+END
+
+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
+ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
+ SS_NOPREFIX
+ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
+ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON,46,51,84,10
+END
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "FileDescription", "klonk Application"
+ VALUE "FileVersion", "1, 0, 0, 1"
+ VALUE "InternalName", "klonk"
+ VALUE "LegalCopyright", "Copyright (C) 2005"
+ VALUE "OriginalFilename", "klonk.exe"
+ VALUE "ProductName", " klonk Application"
+ VALUE "ProductVersion", "1, 0, 0, 1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END'''.strip()
+ for expected_line, output_line in zip(expected.split(), output.split()):
+ self.assertEqual(expected_line, output_line)
+
+ def testRcIncludeStructure(self):
+ root = util.ParseGrdForUnittest('''
+ <structures>
+ <structure type="tr_html" name="IDR_HTML" file="bingo.html"/>
+ <structure type="tr_html" name="IDR_HTML2" file="bingo2.html"/>
+ </structures>''', base_dir = '/temp')
+ # We do not run gatherers as it is not needed and wouldn't find the file
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ expected = (_PREAMBLE +
+ u'IDR_HTML HTML "%s"\n'
+ u'IDR_HTML2 HTML "%s"'
+ % (util.normpath('/temp/bingo.html').replace('\\', '\\\\'),
+ util.normpath('/temp/bingo2.html').replace('\\', '\\\\')))
+ # hackety hack to work on win32&lin
+ output = re.sub('"[c-zC-Z]:', '"', output)
+ self.assertEqual(expected, output)
+
+ def testRcIncludeFile(self):
+ root = util.ParseGrdForUnittest('''
+ <includes>
+ <include type="TXT" name="TEXT_ONE" file="bingo.txt"/>
+ <include type="TXT" name="TEXT_TWO" file="bingo2.txt" filenameonly="true" />
+ </includes>''', base_dir = '/temp')
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ expected = (_PREAMBLE +
+ u'TEXT_ONE TXT "%s"\n'
+ u'TEXT_TWO TXT "%s"'
+ % (util.normpath('/temp/bingo.txt').replace('\\', '\\\\'),
+ 'bingo2.txt'))
+ # hackety hack to work on win32&lin
+ output = re.sub('"[c-zC-Z]:', '"', output)
+ self.assertEqual(expected, output)
+
+ def testRcIncludeFlattenedHtmlFile(self):
+ input_file = util.PathFromRoot('grit/testdata/include_test.html')
+ output_file = '%s/HTML_FILE1_include_test.html' % tempfile.gettempdir()
+ root = util.ParseGrdForUnittest('''
+ <includes>
+ <include name="HTML_FILE1" flattenhtml="true" file="%s" type="BINDATA" />
+ </includes>''' % input_file)
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
+ buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+
+ expected = (_PREAMBLE +
+ u'HTML_FILE1 BINDATA "HTML_FILE1_include_test.html"')
+ # hackety hack to work on win32&lin
+ output = re.sub('"[c-zC-Z]:', '"', output)
+ self.assertEqual(expected, output)
+
+ file_contents = util.ReadFile(output_file, util.RAW_TEXT)
+
+ # Check for the content added by the <include> tag.
+ self.failUnless(file_contents.find('Hello Include!') != -1)
+ # Check for the content that was removed by if tag.
+ self.failUnless(file_contents.find('should be removed') == -1)
+ # Check for the content that was kept in place by if.
+ self.failUnless(file_contents.find('should be kept') != -1)
+ self.failUnless(file_contents.find('in the middle...') != -1)
+ self.failUnless(file_contents.find('at the end...') != -1)
+ # Check for nested content that was kept
+ self.failUnless(file_contents.find('nested true should be kept') != -1)
+ self.failUnless(file_contents.find('silbing true should be kept') != -1)
+ # Check for removed "<if>" and "</if>" tags.
+ self.failUnless(file_contents.find('<if expr=') == -1)
+ self.failUnless(file_contents.find('</if>') == -1)
+
+
+ def testStructureNodeOutputfile(self):
+ input_file = util.PathFromRoot('grit/testdata/simple.html')
+ root = util.ParseGrdForUnittest('''\
+ <structures>
+ <structure type="tr_html" name="IDR_HTML" file="%s" />
+ </structures>''' % input_file)
+ struct, = root.GetChildrenOfType(structure.StructureNode)
+ # We must run the gatherer since we'll be wanting the translation of the
+ # file. The file exists in the location pointed to.
+ root.SetOutputLanguage('en')
+ root.RunGatherers()
+
+ output_dir = tempfile.gettempdir()
+ en_file = struct.FileForLanguage('en', output_dir)
+ self.failUnless(en_file == input_file)
+ fr_file = struct.FileForLanguage('fr', output_dir)
+ self.failUnless(fr_file == os.path.join(output_dir, 'fr_simple.html'))
+
+ contents = util.ReadFile(fr_file, util.RAW_TEXT)
+
+ self.failUnless(contents.find('<p>') != -1) # should contain the markup
+ self.failUnless(contents.find('Hello!') == -1) # should be translated
+
+
+ def testChromeHtmlNodeOutputfile(self):
+ input_file = util.PathFromRoot('grit/testdata/chrome_html.html')
+ output_file = '%s/HTML_FILE1_chrome_html.html' % tempfile.gettempdir()
+ root = util.ParseGrdForUnittest('''\
+ <structures>
+ <structure type="chrome_html" name="HTML_FILE1" file="%s" flattenhtml="true" />
+ </structures>''' % input_file)
+ struct, = root.GetChildrenOfType(structure.StructureNode)
+ struct.gatherer.SetDefines({'scale_factors': '2x'})
+ # We must run the gatherers since we'll be wanting the chrome_html output.
+ # The file exists in the location pointed to.
+ root.SetOutputLanguage('en')
+ root.RunGatherers()
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
+ buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ expected = (_PREAMBLE +
+ u'HTML_FILE1 BINDATA "HTML_FILE1_chrome_html.html"')
+ # hackety hack to work on win32&lin
+ output = re.sub('"[c-zC-Z]:', '"', output)
+ self.assertEqual(expected, output)
+
+ file_contents = util.ReadFile(output_file, util.RAW_TEXT)
+
+ # Check for the content added by the <include> tag.
+ self.failUnless(file_contents.find('Hello Include!') != -1)
+ # Check for inserted -webkit-image-set.
+ self.failUnless(file_contents.find('content: -webkit-image-set') != -1)
+
+
+ def testSubstitutionHtml(self):
+ input_file = util.PathFromRoot('grit/testdata/toolbar_about.html')
+ root = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="1" allow_pseudo="False">
+ <structures fallback_to_english="True">
+ <structure type="tr_html" name="IDR_HTML" file="%s" expand_variables="true"/>
+ </structures>
+ </release>
+ </grit>
+ ''' % input_file), util.PathFromRoot('.'))
+ root.SetOutputLanguage('ar')
+ # We must run the gatherers since we'll be wanting the translation of the
+ # file. The file exists in the location pointed to.
+ root.RunGatherers()
+
+ output_dir = tempfile.gettempdir()
+ struct, = root.GetChildrenOfType(structure.StructureNode)
+ ar_file = struct.FileForLanguage('ar', output_dir)
+ self.failUnless(ar_file == os.path.join(output_dir,
+ 'ar_toolbar_about.html'))
+
+ contents = util.ReadFile(ar_file, util.RAW_TEXT)
+
+ self.failUnless(contents.find('dir="RTL"') != -1)
+
+
+ def testFallbackToEnglish(self):
+ root = util.ParseGrdForUnittest('''\
+ <structures fallback_to_english="True">
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\testdata\klonk.rc" encoding="utf-16" />
+ </structures>''', base_dir=util.PathFromRoot('.'))
+ root.SetOutputLanguage('en')
+ root.RunGatherers()
+
+ buf = StringIO.StringIO()
+ formatter = build.RcBuilder.ProcessNode(
+ root, DummyOutput('rc_all', 'bingobongo'), buf)
+ output = util.StripBlankLinesAndComments(buf.getvalue())
+ self.assertEqual(_PREAMBLE + '''\
+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
+ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
+ SS_NOPREFIX
+ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
+ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON,46,51,84,10
+END''', output)
+
+
+ def testSubstitutionRc(self):
+ root = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
+ base_dir=".">
+ <outputs>
+ <output lang="en" type="rc_all" filename="grit\\testdata\klonk_resources.rc"/>
+ </outputs>
+ <release seq="1" allow_pseudo="False">
+ <structures>
+ <structure type="menu" name="IDC_KLONKMENU"
+ file="grit\\testdata\klonk.rc" encoding="utf-16"
+ expand_variables="true" />
+ </structures>
+ <messages>
+ <message name="good" sub_variable="true">
+ excellent
+ </message>
+ </messages>
+ </release>
+ </grit>
+ '''), util.PathFromRoot('.'))
+ root.SetOutputLanguage('en')
+ root.RunGatherers()
+
+ buf = StringIO.StringIO()
+ build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
+ output = buf.getvalue()
+ self.assertEqual('''
+// This file is automatically generated by GRIT. Do not edit.
+
+#include "resource.h"
+#include <winresrc.h>
+#ifdef IDC_STATIC
+#undef IDC_STATIC
+#endif
+#define IDC_STATIC (-1)
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+
+IDC_KLONKMENU MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "E&xit", IDM_EXIT
+ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
+ POPUP "gonk"
+ BEGIN
+ MENUITEM "Klonk && is excellent", ID_GONK_KLONKIS
+ END
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About ...", IDM_ABOUT
+ END
+END
+
+STRINGTABLE
+BEGIN
+ good "excellent"
+END
+'''.strip(), output.strip())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/format/repack.py b/chromium/tools/grit/grit/format/repack.py
new file mode 100755
index 00000000000..e42acdbfc57
--- /dev/null
+++ b/chromium/tools/grit/grit/format/repack.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+A simple utility function to merge data pack files into a single data pack. See
+http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
+for details about the file format.
+"""
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import grit.format.data_pack
+
+def main(argv):
+ if len(argv) < 3:
+ print ("Usage:\n %s <output_filename> <input_file1> [input_file2] ... " %
+ argv[0])
+ sys.exit(-1)
+ grit.format.data_pack.RePack(argv[1], argv[2:])
+
+if '__main__' == __name__:
+ main(sys.argv)
diff --git a/chromium/tools/grit/grit/format/resource_map.py b/chromium/tools/grit/grit/format/resource_map.py
new file mode 100644
index 00000000000..90370aa20eb
--- /dev/null
+++ b/chromium/tools/grit/grit/format/resource_map.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''This file contains item formatters for resource_map_header and
+resource_map_source files. A resource map is a mapping between resource names
+(string) and the internal resource ID.'''
+
+import os
+from functools import partial
+
+from grit import util
+
+
+def GetFormatter(type):
+ if type == 'resource_map_header':
+ return _FormatHeader
+ elif type == 'resource_map_source':
+ return partial(_FormatSource, _GetItemName)
+ elif type == 'resource_file_map_source':
+ return partial(_FormatSource, _GetItemPath)
+
+
+def GetMapName(root):
+ '''Get the name of the resource map based on the header file name. E.g.,
+ if our header filename is theme_resources.h, we name our resource map
+ kThemeResourcesMap.
+
+ |root| is the grd file root.'''
+ outputs = root.GetOutputFiles()
+ rc_header_file = None
+ for output in outputs:
+ if 'rc_header' == output.GetType():
+ rc_header_file = output.GetFilename()
+ if not rc_header_file:
+ raise Exception('unable to find resource header filename')
+ filename = os.path.splitext(os.path.split(rc_header_file)[1])[0]
+ filename = filename[0].upper() + filename[1:]
+ while filename.find('_') != -1:
+ pos = filename.find('_')
+ if pos >= len(filename):
+ break
+ filename = filename[:pos] + filename[pos + 1].upper() + filename[pos + 2:]
+ return 'k' + filename
+
+
+def _FormatHeader(root, lang='en', output_dir='.'):
+ '''Create the header file for the resource mapping. This file just declares
+ an array of name/value pairs.'''
+ return '''\
+// This file is automatically generated by GRIT. Do not edit.
+
+#include <stddef.h>
+
+#ifndef GRIT_RESOURCE_MAP_STRUCT_
+#define GRIT_RESOURCE_MAP_STRUCT_
+struct GritResourceMap {
+ const char* const name;
+ int value;
+};
+#endif // GRIT_RESOURCE_MAP_STRUCT_
+
+extern const GritResourceMap %(map_name)s[];
+extern const size_t %(map_name)sSize;
+''' % { 'map_name': GetMapName(root) }
+
+
+def _FormatSourceHeader(root):
+ '''Create the header of the C++ source file for the resource mapping.'''
+ rc_header_file = None
+ map_header_file = None
+ for output in root.GetOutputFiles():
+ if 'rc_header' == output.GetType():
+ rc_header_file = output.GetFilename()
+ elif 'resource_map_header' == output.GetType():
+ map_header_file = output.GetFilename()
+ if not rc_header_file or not map_header_file:
+ raise Exception('resource_map_source output type requires '
+ 'resource_map_header and rc_header outputs')
+ return '''\
+// This file is automatically generated by GRIT. Do not edit.
+
+#include "%(map_header_file)s"
+
+#include "base/basictypes.h"
+#include "%(rc_header_file)s"
+
+const GritResourceMap %(map_name)s[] = {
+''' % { 'map_header_file': map_header_file,
+ 'rc_header_file': rc_header_file,
+ 'map_name': GetMapName(root),
+ }
+
+
+def _FormatSourceFooter(root):
+ # Return the footer text.
+ return '''\
+};
+
+const size_t %(map_name)sSize = arraysize(%(map_name)s);
+''' % { 'map_name': GetMapName(root) }
+
+
+def _FormatSource(get_key, root, lang, output_dir):
+ from grit.format import rc_header
+ from grit.node import include, structure
+ yield _FormatSourceHeader(root)
+ tids = rc_header.GetIds(root)
+ seen = set()
+ for item in root:
+ if isinstance(item, (include.IncludeNode, structure.StructureNode)):
+ key = get_key(item)
+ tid = item.attrs['name']
+ if tid in tids and key not in seen:
+ seen.add(key)
+ yield ' {"%s", %s},\n' % (key, tid)
+ yield _FormatSourceFooter(root)
+
+
+def _GetItemName(item):
+ return item.attrs['name']
+
+
+def _GetItemPath(item):
+ return item.GetInputPath().replace("\\", "/")
diff --git a/chromium/tools/grit/grit/format/resource_map_unittest.py b/chromium/tools/grit/grit/format/resource_map_unittest.py
new file mode 100644
index 00000000000..ea344658474
--- /dev/null
+++ b/chromium/tools/grit/grit/format/resource_map_unittest.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.format.resource_map'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import StringIO
+import unittest
+
+from grit import grd_reader
+from grit import util
+from grit.format import resource_map
+
+
+class FormatResourceMapUnittest(unittest.TestCase):
+ def testFormatResourceMap(self):
+ grd = grd_reader.Parse(StringIO.StringIO(
+ '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en" current_release="3"
+ base_dir=".">
+ <outputs>
+ <output type="rc_header" filename="the_rc_header.h" />
+ <output type="resource_map_header"
+ filename="the_resource_map_header.h" />
+ </outputs>
+ <release seq="3">
+ <structures first_id="300">
+ <structure type="menu" name="IDC_KLONKMENU"
+ file="grit\\testdata\\klonk.rc" encoding="utf-16" />
+ </structures>
+ <includes first_id="10000">
+ <include type="foo" file="abc" name="IDS_FIRSTPRESENT" />
+ <if expr="False">
+ <include type="foo" file="def" name="IDS_MISSING" />
+ </if>
+ <if expr="lang != 'es'">
+ <include type="foo" file="ghi" name="IDS_LANGUAGESPECIFIC" />
+ </if>
+ <if expr="lang == 'es'">
+ <include type="foo" file="jkl" name="IDS_LANGUAGESPECIFIC" />
+ </if>
+ <include type="foo" file="mno" name="IDS_THIRDPRESENT" />
+ </includes>
+ </release>
+ </grit>'''), util.PathFromRoot('.'))
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+ output = util.StripBlankLinesAndComments(''.join(
+ resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
+ self.assertEqual('''\
+#include <stddef.h>
+#ifndef GRIT_RESOURCE_MAP_STRUCT_
+#define GRIT_RESOURCE_MAP_STRUCT_
+struct GritResourceMap {
+ const char* const name;
+ int value;
+};
+#endif // GRIT_RESOURCE_MAP_STRUCT_
+extern const GritResourceMap kTheRcHeader[];
+extern const size_t kTheRcHeaderSize;''', output)
+ output = util.StripBlankLinesAndComments(''.join(
+ resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
+ self.assertEqual('''\
+#include "the_resource_map_header.h"
+#include "base/basictypes.h"
+#include "the_rc_header.h"
+const GritResourceMap kTheRcHeader[] = {
+ {"IDC_KLONKMENU", IDC_KLONKMENU},
+ {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT},
+ {"IDS_MISSING", IDS_MISSING},
+ {"IDS_LANGUAGESPECIFIC", IDS_LANGUAGESPECIFIC},
+ {"IDS_THIRDPRESENT", IDS_THIRDPRESENT},
+};
+const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
+ output = util.StripBlankLinesAndComments(''.join(
+ resource_map.GetFormatter('resource_file_map_source')(grd, 'en', '.')))
+ self.assertEqual('''\
+#include "the_resource_map_header.h"
+#include "base/basictypes.h"
+#include "the_rc_header.h"
+const GritResourceMap kTheRcHeader[] = {
+ {"grit/testdata/klonk.rc", IDC_KLONKMENU},
+ {"abc", IDS_FIRSTPRESENT},
+ {"def", IDS_MISSING},
+ {"ghi", IDS_LANGUAGESPECIFIC},
+ {"jkl", IDS_LANGUAGESPECIFIC},
+ {"mno", IDS_THIRDPRESENT},
+};
+const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/gather/__init__.py b/chromium/tools/grit/grit/gather/__init__.py
new file mode 100644
index 00000000000..e52734a5b53
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/__init__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Module grit.gather
+'''
+
+pass
diff --git a/chromium/tools/grit/grit/gather/admin_template.py b/chromium/tools/grit/grit/gather/admin_template.py
new file mode 100644
index 00000000000..edf783b3a18
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/admin_template.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Gatherer for administrative template files.
+'''
+
+import re
+
+from grit.gather import regexp
+from grit import exception
+from grit import lazy_re
+
+
+class MalformedAdminTemplateException(exception.Base):
+ '''This file doesn't look like a .adm file to me.'''
+ pass
+
+
+class AdmGatherer(regexp.RegexpGatherer):
+ '''Gatherer for the translateable portions of an admin template.
+
+ This gatherer currently makes the following assumptions:
+ - there is only one [strings] section and it is always the last section
+ of the file
+ - translateable strings do not need to be escaped.
+ '''
+
+ # Finds the strings section as the group named 'strings'
+ _STRINGS_SECTION = lazy_re.compile(
+ '(?P<first_part>.+^\[strings\])(?P<strings>.+)\Z',
+ re.MULTILINE | re.DOTALL)
+
+ # Finds the translateable sections from within the [strings] section.
+ _TRANSLATEABLES = lazy_re.compile(
+ '^\s*[A-Za-z0-9_]+\s*=\s*"(?P<text>.+)"\s*$',
+ re.MULTILINE)
+
+ def Escape(self, text):
+ return text.replace('\n', '\\n')
+
+ def UnEscape(self, text):
+ return text.replace('\\n', '\n')
+
+ def Parse(self):
+ if self.have_parsed_:
+ return
+ self.have_parsed_ = True
+
+ self.text_ = self._LoadInputFile().strip()
+ m = self._STRINGS_SECTION.match(self.text_)
+ if not m:
+ raise MalformedAdminTemplateException()
+ # Add the first part, which is all nontranslateable, to the skeleton
+ self._AddNontranslateableChunk(m.group('first_part'))
+ # Then parse the rest using the _TRANSLATEABLES regexp.
+ self._RegExpParse(self._TRANSLATEABLES, m.group('strings'))
+
+ def GetTextualIds(self):
+ return [self.extkey]
diff --git a/chromium/tools/grit/grit/gather/admin_template_unittest.py b/chromium/tools/grit/grit/gather/admin_template_unittest.py
new file mode 100644
index 00000000000..6c7e56b0525
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/admin_template_unittest.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for the admin template gatherer.'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import StringIO
+import tempfile
+import unittest
+
+from grit.gather import admin_template
+from grit import util
+from grit import grd_reader
+from grit import grit_runner
+from grit.tool import build
+
+
+class AdmGathererUnittest(unittest.TestCase):
+ def testParsingAndTranslating(self):
+ pseudofile = StringIO.StringIO(
+ 'bingo bongo\n'
+ 'ding dong\n'
+ '[strings] \n'
+ 'whatcha="bingo bongo"\n'
+ 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
+ gatherer = admin_template.AdmGatherer(pseudofile)
+ gatherer.Parse()
+ self.failUnless(len(gatherer.GetCliques()) == 2)
+ self.failUnless(gatherer.GetCliques()[1].GetMessage().GetRealContent() ==
+ 'bingolabongola "the wise" fingulafongula')
+
+ translation = gatherer.Translate('en')
+ self.failUnless(translation == gatherer.GetText().strip())
+
+ def testErrorHandling(self):
+ pseudofile = StringIO.StringIO(
+ 'bingo bongo\n'
+ 'ding dong\n'
+ 'whatcha="bingo bongo"\n'
+ 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
+ gatherer = admin_template.AdmGatherer(pseudofile)
+ self.assertRaises(admin_template.MalformedAdminTemplateException,
+ gatherer.Parse)
+
+ _TRANSLATABLES_FROM_FILE = (
+ 'Google', 'Google Desktop', 'Preferences',
+ 'Controls Google Desktop preferences',
+ 'Indexing and Capture Control',
+ 'Controls what files, web pages, and other content will be indexed by Google Desktop.',
+ 'Prevent indexing of email',
+ # there are lots more but we don't check any further
+ )
+
+ def VerifyCliquesFromAdmFile(self, cliques):
+ self.failUnless(len(cliques) > 20)
+ for clique, expected in zip(cliques, self._TRANSLATABLES_FROM_FILE):
+ text = clique.GetMessage().GetRealContent()
+ self.failUnless(text == expected)
+
+ def testFromFile(self):
+ fname = util.PathFromRoot('grit/testdata/GoogleDesktop.adm')
+ gatherer = admin_template.AdmGatherer(fname)
+ gatherer.Parse()
+ cliques = gatherer.GetCliques()
+ self.VerifyCliquesFromAdmFile(cliques)
+
+ def MakeGrd(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3">
+ <release seq="3">
+ <structures>
+ <structure type="admin_template" name="IDAT_GOOGLE_DESKTOP_SEARCH"
+ file="GoogleDesktop.adm" exclude_from_rc="true" />
+ <structure type="txt" name="BINGOBONGO"
+ file="README.txt" exclude_from_rc="true" />
+ </structures>
+ </release>
+ <outputs>
+ <output filename="de_res.rc" type="rc_all" lang="de" />
+ </outputs>
+ </grit>'''), util.PathFromRoot('grit/testdata'))
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+ return grd
+
+ def testInGrd(self):
+ grd = self.MakeGrd()
+ cliques = grd.children[0].children[0].children[0].GetCliques()
+ self.VerifyCliquesFromAdmFile(cliques)
+
+ def testFileIsOutput(self):
+ grd = self.MakeGrd()
+ dirname = tempfile.mkdtemp()
+ try:
+ tool = build.RcBuilder()
+ tool.o = grit_runner.Options()
+ tool.output_directory = dirname
+ tool.res = grd
+ tool.Process()
+
+ self.failUnless(os.path.isfile(
+ os.path.join(dirname, 'de_GoogleDesktop.adm')))
+ self.failUnless(os.path.isfile(
+ os.path.join(dirname, 'de_README.txt')))
+ finally:
+ for f in os.listdir(dirname):
+ os.unlink(os.path.join(dirname, f))
+ os.rmdir(dirname)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/gather/chrome_html.py b/chromium/tools/grit/grit/gather/chrome_html.py
new file mode 100644
index 00000000000..840b2514f5d
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/chrome_html.py
@@ -0,0 +1,331 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Prepares a Chrome HTML file by inlining resources and adding references to
+high DPI resources and removing references to unsupported scale factors.
+
+This is a small gatherer that takes a HTML file, looks for src attributes
+and inlines the specified file, producing one HTML file with no external
+dependencies. It recursively inlines the included files. When inlining CSS
+image files this script also checks for the existence of high DPI versions
+of the inlined file including those on relevant platforms. Unsupported scale
+factors are also removed from existing image sets to support explicitly
+referencing all available images.
+"""
+
+import os
+import re
+
+from grit import lazy_re
+from grit import util
+from grit.format import html_inline
+from grit.gather import interface
+
+
+# Distribution string to replace with distribution.
+DIST_SUBSTR = '%DISTRIBUTION%'
+
+
+# Matches a chrome theme source URL.
+_THEME_SOURCE = lazy_re.compile(
+ '(?P<baseurl>chrome://theme/IDR_[A-Z0-9_]*)(?P<query>\?.*)?')
+# Matches CSS image urls with the capture group 'filename'.
+_CSS_IMAGE_URLS = lazy_re.compile(
+ '(?P<attribute>content|background|[\w-]*-image):[ ]*' +
+ 'url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)(?P=quote)')
+# Matches CSS image sets.
+_CSS_IMAGE_SETS = lazy_re.compile(
+ '(?P<attribute>content|background|[\w-]*-image):[ ]*' +
+ '-webkit-image-set\((?P<images>' +
+ '([,\r\n ]*url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*[0-9.]*x)*)\)',
+ re.MULTILINE)
+# Matches a single image in a CSS image set with the capture group scale.
+_CSS_IMAGE_SET_IMAGE = lazy_re.compile('[,\r\n ]*' +
+ 'url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*(?P<scale>[0-9.]*x)',
+ re.MULTILINE)
+_HTML_IMAGE_SRC = lazy_re.compile(
+ '<img[^>]+src=\"(?P<filename>[^">]*)\"[^>]*>')
+
+def GetImageList(
+ base_path, filename, scale_factors, distribution,
+ filename_expansion_function=None):
+ """Generate the list of images which match the provided scale factors.
+
+ Takes an image filename and checks for files of the same name in folders
+ corresponding to the supported scale factors. If the file is from a
+ chrome://theme/ source, inserts supported @Nx scale factors as high DPI
+ versions.
+
+ Args:
+ base_path: path to look for relative file paths in
+ filename: name of the base image file
+ scale_factors: a list of the supported scale factors (i.e. ['2x'])
+ distribution: string that should replace %DISTRIBUTION%
+
+ Returns:
+ array of tuples containing scale factor and image (i.e.
+ [('1x', 'image.png'), ('2x', '2x/image.png')]).
+ """
+ # Any matches for which a chrome URL handler will serve all scale factors
+ # can simply request all scale factors.
+ theme_match = _THEME_SOURCE.match(filename)
+ if theme_match:
+ images = [('1x', filename)]
+ for scale_factor in scale_factors:
+ scale_filename = "%s@%s" % (theme_match.group('baseurl'), scale_factor)
+ if theme_match.group('query'):
+ scale_filename += theme_match.group('query')
+ images.append((scale_factor, scale_filename))
+ return images
+
+ if filename.find(':') != -1:
+ # filename is probably a URL, only return filename itself.
+ return [('1x', filename)]
+
+ filename = filename.replace(DIST_SUBSTR, distribution)
+ if filename_expansion_function:
+ filename = filename_expansion_function(filename)
+ filepath = os.path.join(base_path, filename)
+ images = [('1x', filename)]
+
+ for scale_factor in scale_factors:
+ # Check for existence of file and add to image set.
+ scale_path = os.path.split(os.path.join(base_path, filename))
+ scale_image_path = os.path.join(scale_path[0], scale_factor, scale_path[1])
+ if os.path.isfile(scale_image_path):
+ # HTML/CSS always uses forward slashed paths.
+ scale_image_name = re.sub('(?P<path>(.*/)?)(?P<file>[^/]*)',
+ '\\g<path>' + scale_factor + '/\\g<file>',
+ filename)
+ images.append((scale_factor, scale_image_name))
+ return images
+
+
+def GenerateImageSet(images, quote):
+ """Generates a -webkit-image-set for the provided list of images.
+
+ Args:
+ images: an array of tuples giving scale factor and file path
+ (i.e. [('1x', 'image.png'), ('2x', '2x/image.png')]).
+ quote: a string giving the quotation character to use (i.e. "'")
+
+ Returns:
+ string giving a -webkit-image-set rule referencing the provided images.
+ (i.e. '-webkit-image-set(url('image.png') 1x, url('2x/image.png') 2x)')
+ """
+ imageset = []
+ for (scale_factor, filename) in images:
+ imageset.append("url(%s%s%s) %s" % (quote, filename, quote, scale_factor))
+ return "-webkit-image-set(%s)" % (', '.join(imageset))
+
+
+def InsertImageSet(
+ src_match, base_path, scale_factors, distribution,
+ filename_expansion_function=None):
+ """Regex replace function which inserts -webkit-image-set.
+
+ Takes a regex match for url('path'). If the file is local, checks for
+ files of the same name in folders corresponding to the supported scale
+ factors. If the file is from a chrome://theme/ source, inserts the
+ supported @Nx scale factor request. In either case inserts a
+ -webkit-image-set rule to fetch the appropriate image for the current
+ scale factor.
+
+ Args:
+ src_match: regex match object from _CSS_IMAGE_URLS
+ base_path: path to look for relative file paths in
+ scale_factors: a list of the supported scale factors (i.e. ['2x'])
+ distribution: string that should replace %DISTRIBUTION%.
+
+ Returns:
+ string
+ """
+ quote = src_match.group('quote')
+ filename = src_match.group('filename')
+ attr = src_match.group('attribute')
+ image_list = GetImageList(
+ base_path, filename, scale_factors, distribution,
+ filename_expansion_function=filename_expansion_function)
+
+ # Don't modify the source if there is only one image.
+ if len(image_list) == 1:
+ return src_match.group(0)
+
+ return "%s: %s" % (attr, GenerateImageSet(image_list, quote)[:-1])
+
+
+def InsertImageStyle(
+ src_match, base_path, scale_factors, distribution,
+ filename_expansion_function=None):
+ """Regex replace function which adds a content style to an <img>.
+
+ Takes a regex match from _HTML_IMAGE_SRC and replaces the attribute with a CSS
+ style which defines the image set.
+ """
+ filename = src_match.group('filename')
+ image_list = GetImageList(
+ base_path, filename, scale_factors, distribution,
+ filename_expansion_function=filename_expansion_function)
+
+ # Don't modify the source if there is only one image or image already defines
+ # a style.
+ if src_match.group(0).find(" style=\"") != -1 or len(image_list) == 1:
+ return src_match.group(0)
+
+ return "%s style=\"content: %s;\">" % (src_match.group(0)[:-1],
+ GenerateImageSet(image_list, "'"))
+
+
+def InsertImageSets(
+ filepath, text, scale_factors, distribution,
+ filename_expansion_function=None):
+ """Helper function that adds references to external images available in any of
+ scale_factors in CSS backgrounds.
+ """
+ # Add high DPI urls for css attributes: content, background,
+ # or *-image or <img src="foo">.
+ return _CSS_IMAGE_URLS.sub(
+ lambda m: InsertImageSet(
+ m, filepath, scale_factors, distribution,
+ filename_expansion_function=filename_expansion_function),
+ _HTML_IMAGE_SRC.sub(
+ lambda m: InsertImageStyle(
+ m, filepath, scale_factors, distribution,
+ filename_expansion_function=filename_expansion_function),
+ text)).decode('utf-8').encode('utf-8')
+
+
+def RemoveImagesNotIn(scale_factors, src_match):
+ """Regex replace function which removes images for scale factors not in
+ scale_factors.
+
+ Takes a regex match for _CSS_IMAGE_SETS. For each image in the group images,
+ checks if this scale factor is in scale_factors and if not, removes it.
+
+ Args:
+ scale_factors: a list of the supported scale factors (i.e. ['1x', '2x'])
+ src_match: regex match object from _CSS_IMAGE_SETS
+
+ Returns:
+ string
+ """
+ attr = src_match.group('attribute')
+ images = _CSS_IMAGE_SET_IMAGE.sub(
+ lambda m: m.group(0) if m.group('scale') in scale_factors else '',
+ src_match.group('images'))
+ return "%s: -webkit-image-set(%s)" % (attr, images)
+
+
+def RemoveImageSetImages(text, scale_factors):
+ """Helper function which removes images in image sets not in the list of
+ supported scale_factors.
+ """
+ return _CSS_IMAGE_SETS.sub(
+ lambda m: RemoveImagesNotIn(scale_factors, m), text)
+
+
+def ProcessImageSets(
+ filepath, text, scale_factors, distribution,
+ filename_expansion_function=None):
+ """Helper function that adds references to external images available in other
+ scale_factors and removes images from image-sets in unsupported scale_factors.
+ """
+ # Explicitly add 1x to supported scale factors so that it is not removed.
+ supported_scale_factors = ['1x']
+ supported_scale_factors.extend(scale_factors)
+ return InsertImageSets(
+ filepath,
+ RemoveImageSetImages(text, supported_scale_factors),
+ scale_factors,
+ distribution,
+ filename_expansion_function=filename_expansion_function)
+
+
+class ChromeHtml(interface.GathererBase):
+ """Represents an HTML document processed for Chrome WebUI.
+
+ HTML documents used in Chrome WebUI have local resources inlined and
+ automatically insert references to high DPI assets used in CSS properties
+ with the use of the -webkit-image-set value. References to unsupported scale
+ factors in image sets are also removed. This does not generate any
+ translateable messages and instead generates a single DataPack resource.
+ """
+
+ def __init__(self, *args, **kwargs):
+ super(ChromeHtml, self).__init__(*args, **kwargs)
+ self.allow_external_script_ = False
+ self.flatten_html_ = False
+ # 1x resources are implicitly already in the source and do not need to be
+ # added.
+ self.scale_factors_ = []
+ self.filename_expansion_function = None
+
+ def SetAttributes(self, attrs):
+ self.allow_external_script_ = ('allowexternalscript' in attrs and
+ attrs['allowexternalscript'] == 'true')
+ self.flatten_html_ = ('flattenhtml' in attrs and
+ attrs['flattenhtml'] == 'true')
+
+ def SetDefines(self, defines):
+ if 'scale_factors' in defines:
+ self.scale_factors_ = defines['scale_factors'].split(',')
+
+ def GetText(self):
+ """Returns inlined text of the HTML document."""
+ return self.inlined_text_
+
+ def GetTextualIds(self):
+ return [self.extkey]
+
+ def GetData(self, lang, encoding):
+ """Returns inlined text of the HTML document."""
+ return self.inlined_text_
+
+ def GetHtmlResourceFilenames(self):
+ """Returns a set of all filenames inlined by this file."""
+ if self.flatten_html_:
+ return html_inline.GetResourceFilenames(
+ self.grd_node.ToRealPath(self.GetInputPath()),
+ allow_external_script=self.allow_external_script_,
+ rewrite_function=lambda fp, t, d: ProcessImageSets(
+ fp, t, self.scale_factors_, d,
+ filename_expansion_function=self.filename_expansion_function),
+ filename_expansion_function=self.filename_expansion_function)
+ return []
+
+ def Translate(self, lang, pseudo_if_not_available=True,
+ skeleton_gatherer=None, fallback_to_english=False):
+ """Returns this document translated."""
+ return self.inlined_text_
+
+ def SetFilenameExpansionFunction(self, fn):
+ self.filename_expansion_function = fn
+
+ def Parse(self):
+ """Parses and inlines the represented file."""
+
+ filename = self.GetInputPath()
+ if self.filename_expansion_function:
+ filename = self.filename_expansion_function(filename)
+ # Hack: some unit tests supply an absolute path and no root node.
+ if not os.path.isabs(filename):
+ filename = self.grd_node.ToRealPath(filename)
+ if self.flatten_html_:
+ self.inlined_text_ = html_inline.InlineToString(
+ filename,
+ self.grd_node,
+ allow_external_script = self.allow_external_script_,
+ rewrite_function=lambda fp, t, d: ProcessImageSets(
+ fp, t, self.scale_factors_, d,
+ filename_expansion_function=self.filename_expansion_function),
+ filename_expansion_function=self.filename_expansion_function)
+ else:
+ distribution = html_inline.GetDistribution()
+ self.inlined_text_ = ProcessImageSets(
+ os.path.dirname(filename),
+ util.ReadFile(filename, 'utf-8'),
+ self.scale_factors_,
+ distribution,
+ filename_expansion_function=self.filename_expansion_function)
diff --git a/chromium/tools/grit/grit/gather/chrome_html_unittest.py b/chromium/tools/grit/grit/gather/chrome_html_unittest.py
new file mode 100644
index 00000000000..55597a4e273
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/chrome_html_unittest.py
@@ -0,0 +1,408 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.gather.chrome_html'''
+
+
+import os
+import re
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+
+from grit import lazy_re
+from grit import util
+from grit.gather import chrome_html
+
+
+_NEW_LINE = lazy_re.compile('(\r\n|\r|\n)', re.MULTILINE)
+
+
+def StandardizeHtml(text):
+ '''Standardizes the newline format and png mime type in Html text.'''
+ return _NEW_LINE.sub('\n', text).replace('data:image/x-png;',
+ 'data:image/png;')
+
+
+class ChromeHtmlUnittest(unittest.TestCase):
+ '''Unit tests for ChromeHtml.'''
+
+ def testFileResources(self):
+ '''Tests inlined image file resources with available high DPI assets.'''
+
+ tmp_dir = util.TempDir({
+ 'index.html': '''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <link rel="stylesheet" href="test.css">
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ ''',
+
+ 'test.css': '''
+ .image {
+ background: url('test.png');
+ }
+ ''',
+
+ 'test.png': 'PNG DATA',
+
+ '1.4x/test.png': '1.4x PNG DATA',
+
+ '1.8x/test.png': '1.8x PNG DATA',
+ })
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <style>
+ .image {
+ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
+ }
+ </style>
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ '''))
+ tmp_dir.CleanUp()
+
+ def testFileResourcesImageTag(self):
+ '''Tests inlined image file resources with available high DPI assets on
+ an image tag.'''
+
+ tmp_dir = util.TempDir({
+ 'index.html': '''
+ <!DOCTYPE HTML>
+ <html>
+ <body>
+ <img id="foo" src="test.png">
+ </body>
+ </html>
+ ''',
+
+ 'test.png': 'PNG DATA',
+
+ '2x/test.png': '2x PNG DATA',
+ })
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
+ html.SetDefines({'scale_factors': '2x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ <!DOCTYPE HTML>
+ <html>
+ <body>
+ <img id="foo" src="data:image/png;base64,UE5HIERBVEE=" style="content: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MnggUE5HIERBVEE=') 2x);">
+ </body>
+ </html>
+ '''))
+ tmp_dir.CleanUp()
+
+ def testFileResourcesNoFlatten(self):
+ '''Tests non-inlined image file resources with available high DPI assets.'''
+
+ tmp_dir = util.TempDir({
+ 'test.css': '''
+ .image {
+ background: url('test.png');
+ }
+ ''',
+
+ 'test.png': 'PNG DATA',
+
+ '1.4x/test.png': '1.4x PNG DATA',
+
+ '1.8x/test.png': '1.8x PNG DATA',
+ })
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
+ html.SetAttributes({'flattenhtml': 'false'})
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ .image {
+ background: -webkit-image-set(url('test.png') 1x, url('1.4x/test.png') 1.4x, url('1.8x/test.png') 1.8x);
+ }
+ '''))
+ tmp_dir.CleanUp()
+
+ def testFileResourcesDoubleQuotes(self):
+ '''Tests inlined image file resources if url() filename is double quoted.'''
+
+ tmp_dir = util.TempDir({
+ 'test.css': '''
+ .image {
+ background: url("test.png");
+ }
+ ''',
+
+ 'test.png': 'PNG DATA',
+
+ '2x/test.png': '2x PNG DATA',
+ })
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
+ html.SetDefines({'scale_factors': '2x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ .image {
+ background: -webkit-image-set(url("data:image/png;base64,UE5HIERBVEE=") 1x, url("data:image/png;base64,MnggUE5HIERBVEE=") 2x);
+ }
+ '''))
+ tmp_dir.CleanUp()
+
+ def testFileResourcesNoQuotes(self):
+ '''Tests inlined image file resources when url() filename is unquoted.'''
+
+ tmp_dir = util.TempDir({
+ 'test.css': '''
+ .image {
+ background: url(test.png);
+ }
+ ''',
+
+ 'test.png': 'PNG DATA',
+
+ '2x/test.png': '2x PNG DATA',
+ })
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
+ html.SetDefines({'scale_factors': '2x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ .image {
+ background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
+ }
+ '''))
+ tmp_dir.CleanUp()
+
+ def testFileResourcesNoFile(self):
+ '''Tests inlined image file resources without available high DPI assets.'''
+
+ tmp_dir = util.TempDir({
+ 'index.html': '''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <link rel="stylesheet" href="test.css">
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ ''',
+
+ 'test.css': '''
+ .image {
+ background: url('test.png');
+ }
+ ''',
+
+ 'test.png': 'PNG DATA',
+ })
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
+ html.SetDefines({'scale_factors': '2x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <style>
+ .image {
+ background: url('data:image/png;base64,UE5HIERBVEE=');
+ }
+ </style>
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ '''))
+ tmp_dir.CleanUp()
+
+ def testThemeResources(self):
+ '''Tests inserting high DPI chrome://theme references.'''
+
+ tmp_dir = util.TempDir({
+ 'index.html': '''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <link rel="stylesheet" href="test.css">
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ ''',
+
+ 'test.css': '''
+ .image {
+ background: url('chrome://theme/IDR_RESOURCE_NAME');
+ content: url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q?$1');
+ }
+ ''',
+ })
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
+ html.SetDefines({'scale_factors': '2x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <style>
+ .image {
+ background: -webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME') 1x, url('chrome://theme/IDR_RESOURCE_NAME@2x') 2x);
+ content: -webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q?$1') 1x, url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q@2x?$1') 2x);
+ }
+ </style>
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ '''))
+ tmp_dir.CleanUp()
+
+ def testRemoveUnsupportedScale(self):
+ '''Tests removing an unsupported scale factor from an explicit image-set.'''
+
+ tmp_dir = util.TempDir({
+ 'index.html': '''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <link rel="stylesheet" href="test.css">
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ ''',
+
+ 'test.css': '''
+ .image {
+ background: -webkit-image-set(url('test.png') 1x,
+ url('test1.4.png') 1.4x,
+ url('test1.8.png') 1.8x);
+ }
+ ''',
+
+ 'test.png': 'PNG DATA',
+
+ 'test1.4.png': '1.4x PNG DATA',
+
+ 'test1.8.png': '1.8x PNG DATA',
+ })
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
+ html.SetDefines({'scale_factors': '1.8x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <style>
+ .image {
+ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x,
+ url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
+ }
+ </style>
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ '''))
+ tmp_dir.CleanUp()
+
+ def testExpandVariablesInFilename(self):
+ '''
+ Tests variable substitution in filenames while flattening images
+ with multiple scale factors.
+ '''
+
+ tmp_dir = util.TempDir({
+ 'index.html': '''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <link rel="stylesheet" href="test.css">
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ ''',
+
+ 'test.css': '''
+ .image {
+ background: url('test[WHICH].png');
+ }
+ ''',
+
+ 'test1.png': 'PNG DATA',
+ '1.4x/test1.png': '1.4x PNG DATA',
+ '1.8x/test1.png': '1.8x PNG DATA',
+ })
+
+ def replacer(var, repl):
+ return lambda filename: filename.replace('[%s]' % var, repl)
+
+ html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
+ html.SetDefines({'scale_factors': '1.4x,1.8x'})
+ html.SetAttributes({'flattenhtml': 'true'})
+ html.SetFilenameExpansionFunction(replacer('WHICH', '1'));
+ html.Parse()
+ self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
+ StandardizeHtml('''
+ <!DOCTYPE HTML>
+ <html>
+ <head>
+ <style>
+ .image {
+ background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
+ }
+ </style>
+ </head>
+ <body>
+ <!-- Don't need a body. -->
+ </body>
+ </html>
+ '''))
+ tmp_dir.CleanUp()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/gather/chrome_scaled_image.py b/chromium/tools/grit/grit/gather/chrome_scaled_image.py
new file mode 100644
index 00000000000..19777d08e95
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/chrome_scaled_image.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Gatherer for <structure type="chrome_scaled_image">.
+'''
+
+import os
+import struct
+
+from grit import exception
+from grit import lazy_re
+from grit import util
+from grit.gather import interface
+
+
+_PNG_SCALE_CHUNK = '\0\0\0\0csCl\xc1\x30\x60\x4d'
+
+
+def _RescaleImage(data, from_scale, to_scale):
+ if from_scale != to_scale:
+ assert from_scale == 100
+ # Rather than rescaling the image we add a custom chunk directing Chrome to
+ # rescale it on load. Just append it to the PNG data since
+ # _MoveSpecialChunksToFront will move it later anyway.
+ data += _PNG_SCALE_CHUNK
+ return data
+
+
+_PNG_MAGIC = '\x89PNG\r\n\x1a\n'
+
+'''Mandatory first chunk in order for the png to be valid.'''
+_FIRST_CHUNK = 'IHDR'
+
+'''Special chunks to move immediately after the IHDR chunk. (so that the PNG
+remains valid.)
+'''
+_SPECIAL_CHUNKS = frozenset('csCl npTc'.split())
+
+'''Any ancillary chunk not in this list is deleted from the PNG.'''
+_ANCILLARY_CHUNKS_TO_LEAVE = frozenset(
+ 'bKGD cHRM gAMA iCCP pHYs sBIT sRGB tRNS'.split())
+
+
+def _MoveSpecialChunksToFront(data):
+ '''Move special chunks immediately after the IHDR chunk (so that the PNG
+ remains valid). Also delete ancillary chunks that are not on our whitelist.
+ '''
+ first = [_PNG_MAGIC]
+ special_chunks = []
+ rest = []
+ for chunk in _ChunkifyPNG(data):
+ type = chunk[4:8]
+ critical = type < 'a'
+ if type == _FIRST_CHUNK:
+ first.append(chunk)
+ elif type in _SPECIAL_CHUNKS:
+ special_chunks.append(chunk)
+ elif critical or type in _ANCILLARY_CHUNKS_TO_LEAVE:
+ rest.append(chunk)
+ return ''.join(first + special_chunks + rest)
+
+
+def _ChunkifyPNG(data):
+ '''Given a PNG image, yield its chunks in order.'''
+ assert data.startswith(_PNG_MAGIC)
+ pos = 8
+ while pos != len(data):
+ length = 12 + struct.unpack_from('>I', data, pos)[0]
+ assert 12 <= length <= len(data) - pos
+ yield data[pos:pos+length]
+ pos += length
+
+
+def _MakeBraceGlob(strings):
+ '''Given ['foo', 'bar'], return '{foo,bar}', for error reporting.
+ '''
+ if len(strings) == 1:
+ return strings[0]
+ else:
+ return '{' + ','.join(strings) + '}'
+
+
+class ChromeScaledImage(interface.GathererBase):
+ '''Represents an image that exists in multiple layout variants
+ (e.g. "default", "touch") and multiple scale variants
+ (e.g. "100_percent", "200_percent").
+ '''
+
+ split_context_re_ = lazy_re.compile(r'(.+)_(\d+)_percent\Z')
+
+ def _FindInputFile(self):
+ output_context = self.grd_node.GetRoot().output_context
+ match = self.split_context_re_.match(output_context)
+ if not match:
+ raise exception.MissingMandatoryAttribute(
+ 'All <output> nodes must have an appropriate context attribute'
+ ' (e.g. context="touch_200_percent")')
+ req_layout, req_scale = match.group(1), int(match.group(2))
+
+ layouts = [req_layout]
+ if 'default' not in layouts:
+ layouts.append('default')
+ scales = [req_scale]
+ try_low_res = self.grd_node.FindBooleanAttribute(
+ 'fallback_to_low_resolution', default=False, skip_self=False)
+ if try_low_res and 100 not in scales:
+ scales.append(100)
+ for layout in layouts:
+ for scale in scales:
+ dir = '%s_%s_percent' % (layout, scale)
+ path = os.path.join(dir, self.rc_file)
+ if os.path.exists(self.grd_node.ToRealPath(path)):
+ return path, scale, req_scale
+ # If we get here then the file is missing, so fail.
+ dir = "%s_%s_percent" % (_MakeBraceGlob(layouts),
+ _MakeBraceGlob(map(str, scales)))
+ raise exception.FileNotFound(
+ 'Tried ' + self.grd_node.ToRealPath(os.path.join(dir, self.rc_file)))
+
+ def GetInputPath(self):
+ path, scale, req_scale = self._FindInputFile()
+ return path
+
+ def Parse(self):
+ pass
+
+ def GetTextualIds(self):
+ return [self.extkey]
+
+ def GetData(self, *args):
+ path, scale, req_scale = self._FindInputFile()
+ data = util.ReadFile(self.grd_node.ToRealPath(path), util.BINARY)
+ data = _RescaleImage(data, scale, req_scale)
+ data = _MoveSpecialChunksToFront(data)
+ return data
+
+ def Translate(self, *args, **kwargs):
+ return self.GetData()
diff --git a/chromium/tools/grit/grit/gather/chrome_scaled_image_unittest.py b/chromium/tools/grit/grit/gather/chrome_scaled_image_unittest.py
new file mode 100644
index 00000000000..957326edc02
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/chrome_scaled_image_unittest.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for ChromeScaledImage.'''
+
+
+import re
+import struct
+import unittest
+import zlib
+
+from grit import exception
+from grit import util
+from grit.format import data_pack
+from grit.tool import build
+
+
+_OUTFILETYPES = [
+ ('.h', 'rc_header'),
+ ('_map.cc', 'resource_map_source'),
+ ('_map.h', 'resource_map_header'),
+ ('.pak', 'data_package'),
+ ('.rc', 'rc_all'),
+]
+
+
+_PNG_HEADER = (
+ '\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52'
+ '\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53'
+ '\xde')
+_PNG_FOOTER = (
+ '\x00\x00\x00\x0c\x49\x44\x41\x54\x18\x57\x63\xf8\xff\xff\x3f\x00'
+ '\x05\xfe\x02\xfe\xa7\x35\x81\x84\x00\x00\x00\x00\x49\x45\x4e\x44'
+ '\xae\x42\x60\x82')
+
+
+def _MakePNG(chunks):
+ pack_int32 = struct.Struct('>i').pack
+ chunks = [pack_int32(len(payload)) + type + payload + pack_int32(zlib.crc32(type + payload))
+ for type, payload in chunks]
+ return _PNG_HEADER + ''.join(chunks) + _PNG_FOOTER
+
+
+def _GetFilesInPak(pakname):
+ '''Get a set of the files that were actually included in the .pak output.
+ '''
+ return set(data_pack.DataPack.ReadDataPack(pakname).resources.values())
+
+
+def _GetFilesInRc(rcname, tmp_dir, contents):
+ '''Get a set of the files that were actually included in the .rc output.
+ '''
+ data = util.ReadFile(rcname, util.BINARY).decode('utf-16')
+ contents = dict((tmp_dir.GetPath(k), v) for k, v in contents.items())
+ return set(contents[m.group(1)]
+ for m in re.finditer(ur'(?m)^\w+\s+BINDATA\s+"([^"]+)"$', data))
+
+
+def _MakeFallbackAttr(fallback):
+ if fallback is None:
+ return ''
+ else:
+ return ' fallback_to_low_resolution="%s"' % ('false', 'true')[fallback]
+
+
+def _Structures(fallback, *body):
+ return '<structures%s>\n%s\n</structures>' % (
+ _MakeFallbackAttr(fallback), '\n'.join(body))
+
+
+def _Structure(name, file, fallback=None):
+ return '<structure name="%s" file="%s" type="chrome_scaled_image"%s />' % (
+ name, file, _MakeFallbackAttr(fallback))
+
+
+def _If(expr, *body):
+ return '<if expr="%s">\n%s\n</if>' % (expr, '\n'.join(body))
+
+
+def _RunBuildTest(self, structures, inputs, expected_outputs, skip_rc=False):
+ outputs = '\n'.join('<output filename="out/%s%s" type="%s" context="%s" />'
+ % (context, ext, type, context)
+ for ext, type in _OUTFILETYPES
+ for context in expected_outputs)
+ infiles = {
+ 'in/in.grd': '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="0" current_release="1">
+ <outputs>
+ %s
+ </outputs>
+ <release seq="1">
+ %s
+ </release>
+ </grit>
+ ''' % (outputs, structures),
+ }
+ for pngpath, pngdata in inputs.items():
+ infiles['in/' + pngpath] = pngdata
+ class Options(object):
+ pass
+ with util.TempDir(infiles) as tmp_dir:
+ with tmp_dir.AsCurrentDir():
+ options = Options()
+ options.input = tmp_dir.GetPath('in/in.grd')
+ options.verbose = False
+ options.extra_verbose = False
+ build.RcBuilder().Run(options, [])
+ for context, expected_data in expected_outputs.items():
+ self.assertEquals(expected_data,
+ _GetFilesInPak(tmp_dir.GetPath('out/%s.pak' % context)))
+ if not skip_rc:
+ self.assertEquals(expected_data,
+ _GetFilesInRc(tmp_dir.GetPath('out/%s.rc' % context),
+ tmp_dir, infiles))
+
+
+class ChromeScaledImageUnittest(unittest.TestCase):
+ def testNormalFallback(self):
+ d123a = _MakePNG([('AbCd', '')])
+ t123a = _MakePNG([('EfGh', '')])
+ d123b = _MakePNG([('IjKl', '')])
+ _RunBuildTest(self,
+ _Structures(None,
+ _Structure('IDR_A', 'a.png'),
+ _Structure('IDR_B', 'b.png'),
+ ),
+ {'default_123_percent/a.png': d123a,
+ 'tactile_123_percent/a.png': t123a,
+ 'default_123_percent/b.png': d123b,
+ },
+ {'default_123_percent': set([d123a, d123b]),
+ 'tactile_123_percent': set([t123a, d123b]),
+ })
+
+ def testNormalFallbackFailure(self):
+ self.assertRaises(exception.FileNotFound,
+ _RunBuildTest, self,
+ _Structures(None,
+ _Structure('IDR_A', 'a.png'),
+ ),
+ {'default_100_percent/a.png': _MakePNG([('AbCd', '')]),
+ 'tactile_100_percent/a.png': _MakePNG([('EfGh', '')]),
+ },
+ {'tactile_123_percent': 'should fail before using this'})
+
+ def testLowresFallback(self):
+ png = _MakePNG([('Abcd', '')])
+ png_with_csCl = _MakePNG([('csCl', ''),('Abcd', '')])
+ for outer in (None, False, True):
+ for inner in (None, False, True):
+ args = (
+ self,
+ _Structures(outer,
+ _Structure('IDR_A', 'a.png', inner),
+ ),
+ {'default_100_percent/a.png': png},
+ {'tactile_200_percent': set([png_with_csCl])})
+ if inner or (inner is None and outer):
+ # should fall back to 100%
+ _RunBuildTest(*args, skip_rc=True)
+ else:
+ # shouldn't fall back
+ self.assertRaises(exception.FileNotFound, _RunBuildTest, *args)
+
+ # Test fallback failure with fallback_to_low_resolution=True
+ self.assertRaises(exception.FileNotFound,
+ _RunBuildTest, self,
+ _Structures(True,
+ _Structure('IDR_A', 'a.png'),
+ ),
+ {}, # no files
+ {'tactile_123_percent': 'should fail before using this'})
diff --git a/chromium/tools/grit/grit/gather/igoogle_strings.py b/chromium/tools/grit/grit/gather/igoogle_strings.py
new file mode 100644
index 00000000000..79ed8390c84
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/igoogle_strings.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Support for ALL_ALL.xml format used by Igoogle plug-ins in Google Desktop.'''
+
+import StringIO
+import re
+import xml.sax
+import xml.sax.handler
+import xml.sax.saxutils
+
+from grit.gather import regexp
+from grit import util
+from grit import tclib
+
+# Placeholders can be defined in strings.xml files by putting the name of the
+# placeholder between [![ and ]!] e.g. <MSG>Hello [![USER]!] how are you<MSG>
+PLACEHOLDER_RE = re.compile('(\[!\[|\]!\])')
+
+
+class IgoogleStringsContentHandler(xml.sax.handler.ContentHandler):
+ '''A very dumb parser for splitting the strings.xml file into translateable
+ and nontranslateable chunks.'''
+
+ def __init__(self, parent):
+ self.curr_elem = ''
+ self.curr_text = ''
+ self.parent = parent
+ self.resource_name = ''
+ self.meaning = ''
+ self.translateable = True
+
+ def startElement(self, name, attrs):
+ if (name != 'messagebundle'):
+ self.curr_elem = name
+
+ attr_names = attrs.getQNames()
+ if 'name' in attr_names:
+ self.resource_name = attrs.getValueByQName('name')
+
+ att_text = []
+ for attr_name in attr_names:
+ att_text.append(' ')
+ att_text.append(attr_name)
+ att_text.append('=')
+ att_text.append(
+ xml.sax.saxutils.quoteattr(attrs.getValueByQName(attr_name)))
+
+ self.parent._AddNontranslateableChunk("<%s%s>" %
+ (name, ''.join(att_text)))
+
+ def characters(self, content):
+ if self.curr_elem != '':
+ self.curr_text += content
+
+ def endElement(self, name):
+ if name != 'messagebundle':
+ self.parent.AddMessage(self.curr_text, self.resource_name,
+ self.meaning, self.translateable)
+ self.parent._AddNontranslateableChunk("</%s>\n" % name)
+ self.curr_elem = ''
+ self.curr_text = ''
+ self.resource_name = ''
+ self.meaning = ''
+ self.translateable = True
+
+ def ignorableWhitespace(self, whitespace):
+ pass
+
+
+class IgoogleStrings(regexp.RegexpGatherer):
+ '''Supports the ALL_ALL.xml format used by Igoogle gadgets.'''
+
+ def AddMessage(self, msgtext, description, meaning, translateable):
+ if msgtext == '':
+ return
+
+ msg = tclib.Message(description=description, meaning=meaning)
+
+ unescaped_text = self.UnEscape(msgtext)
+ parts = PLACEHOLDER_RE.split(unescaped_text)
+ in_placeholder = False
+ for part in parts:
+ if part == '':
+ continue
+ elif part == '[![':
+ in_placeholder = True
+ elif part == ']!]':
+ in_placeholder = False
+ else:
+ if in_placeholder:
+ msg.AppendPlaceholder(tclib.Placeholder(part, '[![%s]!]' % part,
+ '(placeholder)'))
+ else:
+ msg.AppendText(part)
+
+ self.skeleton_.append(
+ self.uberclique.MakeClique(msg, translateable=translateable))
+
+ # if statement needed because this is supposed to be idempotent (so never
+ # set back to false)
+ if translateable:
+ self.translatable_chunk_ = True
+
+ # Although we use the RegexpGatherer base class, we do not use the
+ # _RegExpParse method of that class to implement Parse(). Instead, we
+ # parse using a SAX parser.
+ def Parse(self):
+ if self.have_parsed_:
+ return
+ self.have_parsed_ = True
+
+ self.text_ = self._LoadInputFile().strip()
+ self._AddNontranslateableChunk(u'<messagebundle>\n')
+ stream = StringIO.StringIO(self.text_)
+ handler = IgoogleStringsContentHandler(self)
+ xml.sax.parse(stream, handler)
+ self._AddNontranslateableChunk(u'</messagebundle>\n')
+
+ def Escape(self, text):
+ return util.EncodeCdata(text)
diff --git a/chromium/tools/grit/grit/gather/igoogle_strings_unittest.py b/chromium/tools/grit/grit/gather/igoogle_strings_unittest.py
new file mode 100644
index 00000000000..3a4488c1cd7
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/igoogle_strings_unittest.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.gather.igoogle_strings'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit.gather import igoogle_strings
+
+class IgoogleStringsUnittest(unittest.TestCase):
+ def testParsing(self):
+ original = '''<messagebundle><msg test="hello_world">Hello World</msg></messagebundle>'''
+ gatherer = igoogle_strings.IgoogleStrings(StringIO.StringIO(original))
+ gatherer.Parse()
+ print len(gatherer.GetCliques())
+ print gatherer.GetCliques()[0].GetMessage().GetRealContent()
+ self.failUnless(len(gatherer.GetCliques()) == 1)
+ self.failUnless(gatherer.Translate('en').replace('\n', '') == original)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/gather/interface.py b/chromium/tools/grit/grit/gather/interface.py
new file mode 100644
index 00000000000..c277d379b3c
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/interface.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Interface for all gatherers.
+'''
+
+
+import os.path
+import types
+
+from grit import clique
+from grit import util
+
+
+class GathererBase(object):
+ '''Interface for all gatherer implementations. Subclasses must implement
+ all methods that raise NotImplemented.'''
+
+ def __init__(self, rc_file, extkey=None, encoding='cp1252', is_skeleton=False):
+ '''Initializes the gatherer object's attributes, but does not attempt to
+ read the input file.
+
+ Args:
+ rc_file: The 'file' attribute of the <structure> node (usually the
+ relative path to the source file).
+ extkey: e.g. 'ID_MY_DIALOG'
+ encoding: e.g. 'utf-8'
+ is_skeleton: Indicates whether this gatherer is a skeleton gatherer, in
+ which case we should not do some types of processing on the
+ translateable bits.
+ '''
+ self.rc_file = rc_file
+ self.extkey = extkey
+ self.encoding = encoding
+ # A default uberclique that is local to this object. Users can override
+ # this with the uberclique they are using.
+ self.uberclique = clique.UberClique()
+ # Indicates whether this gatherer is a skeleton gatherer, in which case
+ # we should not do some types of processing on the translateable bits.
+ self.is_skeleton = is_skeleton
+ # Stores the grd node on which this gatherer is running. This allows
+ # evaluating expressions.
+ self.grd_node = None
+
+ def SetAttributes(self, attrs):
+ '''Sets node attributes used by the gatherer.
+
+ By default, this does nothing. If special handling is desired, it should be
+ overridden by the child gatherer.
+
+ Args:
+ attrs: The mapping of node attributes.
+ '''
+ pass
+
+ def SetDefines(self, defines):
+ '''Sets global defines used by the gatherer.
+
+ By default, this does nothing. If special handling is desired, it should be
+ overridden by the child gatherer.
+
+ Args:
+ defines: The mapping of define values.
+ '''
+ pass
+
+ def SetGrdNode(self, node):
+ '''Sets the grd node on which this gatherer is running.
+ '''
+ self.grd_node = node
+
+ def SetUberClique(self, uberclique):
+ '''Overrides the default uberclique so that cliques created by this object
+ become part of the uberclique supplied by the user.
+ '''
+ self.uberclique = uberclique
+
+ def Parse(self):
+ '''Reads and parses the contents of what is being gathered.'''
+ raise NotImplementedError()
+
+ def GetData(self, lang, encoding):
+ '''Returns the data to be added to the DataPack for this node or None if
+ this node does not add a DataPack entry.
+ '''
+ return None
+
+ def GetText(self):
+ '''Returns the text of what is being gathered.'''
+ raise NotImplementedError()
+
+ def GetTextualIds(self):
+ '''Returns the mnemonic IDs that need to be defined for the resource
+ being gathered to compile correctly.'''
+ return []
+
+ def GetCliques(self):
+ '''Returns the MessageClique objects for all translateable portions.'''
+ return []
+
+ def GetInputPath(self):
+ return self.rc_file
+
+ def GetHtmlResourceFilenames(self):
+ """Returns a set of all filenames inlined by this gatherer."""
+ return []
+
+ def Translate(self, lang, pseudo_if_not_available=True,
+ skeleton_gatherer=None, fallback_to_english=False):
+ '''Returns the resource being gathered, with translateable portions filled
+ with the translation for language 'lang'.
+
+ If pseudo_if_not_available is true, a pseudotranslation will be used for any
+ message that doesn't have a real translation available.
+
+ If no translation is available and pseudo_if_not_available is false,
+ fallback_to_english controls the behavior. If it is false, throw an error.
+ If it is true, use the English version of the message as its own
+ "translation".
+
+ If skeleton_gatherer is specified, the translation will use the nontranslateable
+ parts from the gatherer 'skeleton_gatherer', which must be of the same type
+ as 'self'.
+
+ If fallback_to_english
+
+ Args:
+ lang: 'en'
+ pseudo_if_not_available: True | False
+ skeleton_gatherer: other_gatherer
+ fallback_to_english: True | False
+
+ Return:
+ e.g. 'ID_THIS_SECTION TYPE\n...BEGIN\n "Translated message"\n......\nEND'
+
+ Raises:
+ grit.exception.NotReady() if used before Parse() has been successfully
+ called.
+ grit.exception.NoSuchTranslation() if 'pseudo_if_not_available' and
+ fallback_to_english are both false and there is no translation for the
+ requested language.
+ '''
+ raise NotImplementedError()
+
+ def SubstituteMessages(self, substituter):
+ '''Applies substitutions to all messages in the gatherer.
+
+ Args:
+ substituter: a grit.util.Substituter object.
+ '''
+ pass
+
+ def SetFilenameExpansionFunction(self, fn):
+ '''Sets a function for rewriting filenames before gathering.'''
+ pass
+
+ # TODO(benrg): Move this elsewhere, since it isn't part of the interface.
+ def _LoadInputFile(self):
+ '''A convenience function for subclasses that loads the contents of the
+ input file.
+ '''
+ if isinstance(self.rc_file, types.StringTypes):
+ path = self.GetInputPath()
+ # Hack: some unit tests supply an absolute path and no root node.
+ if not os.path.isabs(path):
+ path = self.grd_node.ToRealPath(path)
+ return util.ReadFile(path, self.encoding)
+ else:
+ return self.rc_file.read()
diff --git a/chromium/tools/grit/grit/gather/json_loader.py b/chromium/tools/grit/grit/gather/json_loader.py
new file mode 100644
index 00000000000..6370b10f9ed
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/json_loader.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+from grit.gather import interface
+
+
+class JsonLoader(interface.GathererBase):
+ '''A simple gatherer that loads and parses a JSON file.'''
+
+ def Parse(self):
+ '''Reads and parses the text of self._json_text into the data structure in
+ self._data.
+ '''
+ self._json_text = self._LoadInputFile()
+ self._data = None
+
+ globs = {}
+ exec('data = ' + self._json_text, globs)
+ self._data = globs['data']
+
+ def GetData(self):
+ '''Returns the parsed JSON data.'''
+ return self._data
diff --git a/chromium/tools/grit/grit/gather/muppet_strings.py b/chromium/tools/grit/grit/gather/muppet_strings.py
new file mode 100644
index 00000000000..ab2f08a3d7f
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/muppet_strings.py
@@ -0,0 +1,133 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Support for "strings.xml" format used by Muppet plug-ins in Google Desktop.'''
+
+import StringIO
+import xml.sax
+import xml.sax.handler
+import xml.sax.saxutils
+
+from grit import lazy_re
+from grit import tclib
+from grit import util
+from grit.gather import regexp
+
+
+# Placeholders can be defined in strings.xml files by putting the name of the
+# placeholder between [![ and ]!] e.g. <MSG>Hello [![USER]!] how are you<MSG>
+PLACEHOLDER_RE = lazy_re.compile('(\[!\[|\]!\])')
+
+
+class MuppetStringsContentHandler(xml.sax.handler.ContentHandler):
+ '''A very dumb parser for splitting the strings.xml file into translateable
+ and nontranslateable chunks.'''
+
+ def __init__(self, parent):
+ self.curr_elem = ''
+ self.curr_text = ''
+ self.parent = parent
+ self.description = ''
+ self.meaning = ''
+ self.translateable = True
+
+ def startElement(self, name, attrs):
+ if (name != 'strings'):
+ self.curr_elem = name
+
+ attr_names = attrs.getQNames()
+ if 'desc' in attr_names:
+ self.description = attrs.getValueByQName('desc')
+ if 'meaning' in attr_names:
+ self.meaning = attrs.getValueByQName('meaning')
+ if 'translateable' in attr_names:
+ value = attrs.getValueByQName('translateable')
+ if value.lower() not in ['true', 'yes']:
+ self.translateable = False
+
+ att_text = []
+ for attr_name in attr_names:
+ att_text.append(' ')
+ att_text.append(attr_name)
+ att_text.append('=')
+ att_text.append(
+ xml.sax.saxutils.quoteattr(attrs.getValueByQName(attr_name)))
+
+ self.parent._AddNontranslateableChunk("<%s%s>" %
+ (name, ''.join(att_text)))
+
+ def characters(self, content):
+ if self.curr_elem != '':
+ self.curr_text += content
+
+ def endElement(self, name):
+ if name != 'strings':
+ self.parent.AddMessage(self.curr_text, self.description,
+ self.meaning, self.translateable)
+ self.parent._AddNontranslateableChunk("</%s>\n" % name)
+ self.curr_elem = ''
+ self.curr_text = ''
+ self.description = ''
+ self.meaning = ''
+ self.translateable = True
+
+ def ignorableWhitespace(self, whitespace):
+ pass
+
+class MuppetStrings(regexp.RegexpGatherer):
+ '''Supports the strings.xml format used by Muppet gadgets.'''
+
+ def AddMessage(self, msgtext, description, meaning, translateable):
+ if msgtext == '':
+ return
+
+ msg = tclib.Message(description=description, meaning=meaning)
+
+ unescaped_text = self.UnEscape(msgtext)
+ parts = PLACEHOLDER_RE.split(unescaped_text)
+ in_placeholder = False
+ for part in parts:
+ if part == '':
+ continue
+ elif part == '[![':
+ in_placeholder = True
+ elif part == ']!]':
+ in_placeholder = False
+ else:
+ if in_placeholder:
+ msg.AppendPlaceholder(tclib.Placeholder(part, '[![%s]!]' % part,
+ '(placeholder)'))
+ else:
+ msg.AppendText(part)
+
+ self.skeleton_.append(
+ self.uberclique.MakeClique(msg, translateable=translateable))
+
+ # if statement needed because this is supposed to be idempotent (so never
+ # set back to false)
+ if translateable:
+ self.translatable_chunk_ = True
+
+ # Although we use the RegexpGatherer base class, we do not use the
+ # _RegExpParse method of that class to implement Parse(). Instead, we
+ # parse using a SAX parser.
+ def Parse(self):
+ if self.have_parsed_:
+ return
+ self.have_parsed_ = True
+
+ text = self._LoadInputFile().encode(self.encoding)
+ if util.IsExtraVerbose():
+ print text
+ self.text_ = text.strip()
+
+ self._AddNontranslateableChunk(u'<strings>\n')
+ stream = StringIO.StringIO(self.text_)
+ handler = MuppetStringsContentHandler(self)
+ xml.sax.parse(stream, handler)
+ self._AddNontranslateableChunk(u'</strings>\n')
+
+ def Escape(self, text):
+ return util.EncodeCdata(text)
diff --git a/chromium/tools/grit/grit/gather/muppet_strings_unittest.py b/chromium/tools/grit/grit/gather/muppet_strings_unittest.py
new file mode 100644
index 00000000000..adf66b653cc
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/muppet_strings_unittest.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.gather.muppet_strings'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit.gather import muppet_strings
+
+class MuppetStringsUnittest(unittest.TestCase):
+ def testParsing(self):
+ original = '''<strings><BLA desc="Says hello">hello!</BLA><BINGO>YEEEESSS!!!</BINGO></strings>'''
+ gatherer = muppet_strings.MuppetStrings(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(len(gatherer.GetCliques()) == 2)
+ self.failUnless(gatherer.Translate('en').replace('\n', '') == original)
+
+ def testEscapingAndLinebreaks(self):
+ original = ('''\
+<strings>
+<LINEBREAK desc="Howdie">Hello
+there
+how
+are
+you?</LINEBREAK> <ESCAPED meaning="bingo">4 &lt; 6</ESCAPED>
+</strings>''')
+ gatherer = muppet_strings.MuppetStrings(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(gatherer.GetCliques()[0].translateable)
+ self.failUnless(len(gatherer.GetCliques()) == 2)
+ self.failUnless(gatherer.GetCliques()[0].GetMessage().GetRealContent() ==
+ 'Hello\nthere\nhow\nare\nyou?')
+ self.failUnless(gatherer.GetCliques()[0].GetMessage().GetDescription() == 'Howdie')
+ self.failUnless(gatherer.GetCliques()[1].GetMessage().GetRealContent() ==
+ '4 < 6')
+ self.failUnless(gatherer.GetCliques()[1].GetMessage().GetMeaning() == 'bingo')
+
+ def testPlaceholders(self):
+ original = "<strings><MESSAGE translateable='True'>Hello [![USER]!] how are you? [![HOUR]!]:[![MINUTE]!]</MESSAGE></strings>"
+ gatherer = muppet_strings.MuppetStrings(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(gatherer.GetCliques()[0].translateable)
+ msg = gatherer.GetCliques()[0].GetMessage()
+ self.failUnless(len(msg.GetPlaceholders()) == 3)
+ ph = msg.GetPlaceholders()[0]
+ self.failUnless(ph.GetOriginal() == '[![USER]!]')
+ self.failUnless(ph.GetPresentation() == 'USER')
+
+ def testTranslateable(self):
+ original = "<strings><BINGO translateable='false'>Yo yo hi there</BINGO></strings>"
+ gatherer = muppet_strings.MuppetStrings(StringIO.StringIO(original))
+ gatherer.Parse()
+ msg = gatherer.GetCliques()[0].GetMessage()
+ self.failUnless(msg.GetRealContent() == "Yo yo hi there")
+ self.failUnless(not gatherer.GetCliques()[0].translateable)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/gather/policy_json.py b/chromium/tools/grit/grit/gather/policy_json.py
new file mode 100644
index 00000000000..0dcd831d4d5
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/policy_json.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Support for "policy_templates.json" format used by the policy template
+generator as a source for generating ADM,ADMX,etc files.'''
+
+import types
+import sys
+
+from grit.gather import skeleton_gatherer
+from grit import util
+from grit import tclib
+from xml.dom import minidom
+from xml.parsers.expat import ExpatError
+
+
+class PolicyJson(skeleton_gatherer.SkeletonGatherer):
+ '''Collects and translates the following strings from policy_templates.json:
+ - captions,descriptions and labels of policies
+ - captions of enumeration items
+ - misc strings from the 'messages' section
+ Translatable strings may have untranslateable placeholders with the same
+ format that is used in .grd files.
+ '''
+
+ def _ParsePlaceholder(self, placeholder, msg):
+ '''Extracts a placeholder from a DOM node and adds it to a tclib Message.
+
+ Args:
+ placeholder: A DOM node of the form:
+ <ph name="PLACEHOLDER_NAME">Placeholder text<ex>Example value</ex></ph>
+ msg: The placeholder is added to this message.
+ '''
+ text = []
+ example_text = []
+ for node1 in placeholder.childNodes:
+ if (node1.nodeType == minidom.Node.TEXT_NODE):
+ text.append(node1.data)
+ elif (node1.nodeType == minidom.Node.ELEMENT_NODE and
+ node1.tagName == 'ex'):
+ for node2 in node1.childNodes:
+ example_text.append(node2.toxml())
+ else:
+ raise Exception('Unexpected element inside a placeholder: ' +
+ node2.toxml())
+ if example_text == []:
+ # In such cases the original text is okay for an example.
+ example_text = text
+ msg.AppendPlaceholder(tclib.Placeholder(
+ placeholder.attributes['name'].value,
+ ''.join(text).strip(),
+ ''.join(example_text).strip()))
+
+ def _ParseMessage(self, string, desc):
+ '''Parses a given string and adds it to the output as a translatable chunk
+ with a given description.
+
+ Args:
+ string: The message string to parse.
+ desc: The description of the message (for the translators).
+ '''
+ msg = tclib.Message(description=desc)
+ xml = '<msg>' + string + '</msg>'
+ try:
+ node = minidom.parseString(xml).childNodes[0]
+ except ExpatError:
+ reason = '''Input isn't valid XML (has < & > been escaped?): ''' + string
+ raise Exception, reason, sys.exc_info()[2]
+
+ for child in node.childNodes:
+ if child.nodeType == minidom.Node.TEXT_NODE:
+ msg.AppendText(child.data)
+ elif child.nodeType == minidom.Node.ELEMENT_NODE:
+ if child.tagName == 'ph':
+ self._ParsePlaceholder(child, msg)
+ else:
+ raise Exception("Not implemented.")
+ else:
+ raise Exception("Not implemented.")
+ self.skeleton_.append(self.uberclique.MakeClique(msg))
+
+ def _ParseNode(self, node):
+ '''Traverses the subtree of a DOM node, and register a tclib message for
+ all the <message> nodes.
+ '''
+ att_text = []
+ if node.attributes:
+ items = node.attributes.items()
+ items.sort()
+ for key, value in items:
+ att_text.append(' %s=\"%s\"' % (key, value))
+ self._AddNontranslateableChunk("<%s%s>" %
+ (node.tagName, ''.join(att_text)))
+ if node.tagName == 'message':
+ msg = tclib.Message(description=node.attributes['desc'])
+ for child in node.childNodes:
+ if child.nodeType == minidom.Node.TEXT_NODE:
+ if msg == None:
+ self._AddNontranslateableChunk(child.data)
+ else:
+ msg.AppendText(child.data)
+ elif child.nodeType == minidom.Node.ELEMENT_NODE:
+ if child.tagName == 'ph':
+ self._ParsePlaceholder(child, msg)
+ else:
+ assert False
+ self.skeleton_.append(self.uberclique.MakeClique(msg))
+ else:
+ for child in node.childNodes:
+ if child.nodeType == minidom.Node.TEXT_NODE:
+ self._AddNontranslateableChunk(child.data)
+ elif node.nodeType == minidom.Node.ELEMENT_NODE:
+ self._ParseNode(child)
+
+ self._AddNontranslateableChunk("</%s>" % node.tagName)
+
+ def _AddIndentedNontranslateableChunk(self, depth, string):
+ '''Adds a nontranslateable chunk of text to the internally stored output.
+
+ Args:
+ depth: The number of double spaces to prepend to the next argument string.
+ string: The chunk of text to add.
+ '''
+ result = []
+ while depth > 0:
+ result.append(' ')
+ depth = depth - 1
+ result.append(string)
+ self._AddNontranslateableChunk(''.join(result))
+
+ def _GetDescription(self, item, item_type, parent_item, key):
+ '''Creates a description for a translatable message. The description gives
+ some context for the person who will translate this message.
+
+ Args:
+ item: A policy or an enumeration item.
+ item_type: 'enum_item' | 'policy'
+ parent_item: The owner of item. (A policy of type group or enum.)
+ key: The name of the key to parse.
+ depth: The level of indentation.
+ '''
+ key_map = {
+ 'desc': 'Description',
+ 'caption': 'Caption',
+ 'label': 'Label',
+ }
+ if item_type == 'policy':
+ return '%s of the policy named %s' % (key_map[key], item['name'])
+ elif item_type == 'enum_item':
+ return ('%s of the option named %s in policy %s' %
+ (key_map[key], item['name'], parent_item['name']))
+ else:
+ raise Exception('Unexpected type %s' % item_type)
+
+ def _AddPolicyKey(self, item, item_type, parent_item, key, depth):
+ '''Given a policy/enumeration item and a key, adds that key and its value
+ into the output.
+ E.g.:
+ 'example_value': 123
+ If key indicates that the value is a translatable string, then it is parsed
+ as a translatable string.
+
+ Args:
+ item: A policy or an enumeration item.
+ item_type: 'enum_item' | 'policy'
+ parent_item: The owner of item. (A policy of type group or enum.)
+ key: The name of the key to parse.
+ depth: The level of indentation.
+ '''
+ self._AddIndentedNontranslateableChunk(depth, "'%s': " % key)
+ if key in ('desc', 'caption', 'label'):
+ self._AddNontranslateableChunk("'''")
+ self._ParseMessage(
+ item[key],
+ self._GetDescription(item, item_type, parent_item, key))
+ self._AddNontranslateableChunk("''',\n")
+ else:
+ str_val = item[key]
+ if type(str_val) == types.StringType:
+ str_val = "'%s'" % self.Escape(str_val)
+ else:
+ str_val = str(str_val)
+ self._AddNontranslateableChunk(str_val + ',\n')
+
+ def _AddItems(self, items, item_type, parent_item, depth):
+ '''Parses and adds a list of items from the JSON file. Items can be policies
+ or parts of an enum policy.
+
+ Args:
+ items: Either a list of policies or a list of dictionaries.
+ item_type: 'enum_item' | 'policy'
+ parent_item: If items contains a list of policies, then this is the policy
+ group that owns them. If items contains a list of enumeration items,
+ then this is the enum policy that holds them.
+ depth: Indicates the depth of our position in the JSON hierarchy. Used to
+ add nice line-indent to the output.
+ '''
+ for item1 in items:
+ self._AddIndentedNontranslateableChunk(depth, "{\n")
+ for key in item1.keys():
+ if key == 'items':
+ self._AddIndentedNontranslateableChunk(depth + 1, "'items': [\n")
+ self._AddItems(item1['items'], 'enum_item', item1, depth + 2)
+ self._AddIndentedNontranslateableChunk(depth + 1, "],\n")
+ elif key == 'policies':
+ self._AddIndentedNontranslateableChunk(depth + 1, "'policies': [\n")
+ self._AddItems(item1['policies'], 'policy', item1, depth + 2)
+ self._AddIndentedNontranslateableChunk(depth + 1, "],\n")
+ else:
+ self._AddPolicyKey(item1, item_type, parent_item, key, depth + 1)
+ self._AddIndentedNontranslateableChunk(depth, "},\n")
+
+ def _AddMessages(self):
+ '''Processed and adds the 'messages' section to the output.'''
+ self._AddNontranslateableChunk(" 'messages': {\n")
+ for name, message in self.data['messages'].iteritems():
+ self._AddNontranslateableChunk(" '%s': {\n" % name)
+ self._AddNontranslateableChunk(" 'text': '''")
+ self._ParseMessage(message['text'], message['desc'])
+ self._AddNontranslateableChunk("'''\n")
+ self._AddNontranslateableChunk(" },\n")
+ self._AddNontranslateableChunk(" },\n")
+
+ # Although we use the RegexpGatherer base class, we do not use the
+ # _RegExpParse method of that class to implement Parse(). Instead, we
+ # parse using a DOM parser.
+ def Parse(self):
+ if self.have_parsed_:
+ return
+ self.have_parsed_ = True
+
+ self.text_ = self._LoadInputFile()
+ if util.IsExtraVerbose():
+ print self.text_
+
+ self.data = eval(self.text_)
+
+ self._AddNontranslateableChunk('{\n')
+ self._AddNontranslateableChunk(" 'policy_definitions': [\n")
+ self._AddItems(self.data['policy_definitions'], 'policy', None, 2)
+ self._AddNontranslateableChunk(" ],\n")
+ self._AddMessages()
+ self._AddNontranslateableChunk('\n}')
+
+ def Escape(self, text):
+ # \ -> \\
+ # ' -> \'
+ # " -> \"
+ return text.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'")
diff --git a/chromium/tools/grit/grit/gather/policy_json_unittest.py b/chromium/tools/grit/grit/gather/policy_json_unittest.py
new file mode 100644
index 00000000000..f536f5d867f
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/policy_json_unittest.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.gather.policy_json'''
+
+import os
+import re
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit.gather import policy_json
+
+class PolicyJsonUnittest(unittest.TestCase):
+
+ def GetExpectedOutput(self, original):
+ expected = eval(original)
+ for key, message in expected['messages'].iteritems():
+ del message['desc']
+ return expected
+
+ def testEmpty(self):
+ original = "{'policy_definitions': [], 'messages': {}}"
+ gatherer = policy_json.PolicyJson(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(len(gatherer.GetCliques()) == 0)
+ self.failUnless(eval(original) == eval(gatherer.Translate('en')))
+
+ def testGeneralPolicy(self):
+ original = (
+ "{"
+ " 'policy_definitions': ["
+ " {"
+ " 'name': 'HomepageLocation',"
+ " 'type': 'string',"
+ " 'supported_on': ['chrome.*:8-'],"
+ " 'features': {'dynamic_refresh': 1},"
+ " 'example_value': 'http://chromium.org',"
+ " 'caption': 'nothing special 1',"
+ " 'desc': 'nothing special 2',"
+ " 'label': 'nothing special 3',"
+ " },"
+ " ],"
+ " 'messages': {"
+ " 'msg_identifier': {"
+ " 'text': 'nothing special 3',"
+ " 'desc': 'nothing special descr 3',"
+ " }"
+ " }"
+ "}")
+ gatherer = policy_json.PolicyJson(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(len(gatherer.GetCliques()) == 4)
+ expected = self.GetExpectedOutput(original)
+ self.failUnless(expected == eval(gatherer.Translate('en')))
+
+ def testEnum(self):
+ original = (
+ "{"
+ " 'policy_definitions': ["
+ " {"
+ " 'name': 'Policy1',"
+ " 'items': ["
+ " {"
+ " 'name': 'Item1',"
+ " 'caption': 'nothing special',"
+ " }"
+ " ]"
+ " },"
+ " ],"
+ " 'messages': {}"
+ "}")
+ gatherer = policy_json.PolicyJson(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(len(gatherer.GetCliques()) == 1)
+ expected = self.GetExpectedOutput(original)
+ self.failUnless(expected == eval(gatherer.Translate('en')))
+
+ def testSubPolicy(self):
+ original = (
+ "{"
+ " 'policy_definitions': ["
+ " {"
+ " 'policies': ["
+ " {"
+ " 'name': 'Policy1',"
+ " 'caption': 'nothing special',"
+ " }"
+ " ]"
+ " },"
+ " ],"
+ " 'messages': {}"
+ "}")
+ gatherer = policy_json.PolicyJson(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(len(gatherer.GetCliques()) == 1)
+ expected = self.GetExpectedOutput(original)
+ self.failUnless(expected == eval(gatherer.Translate('en')))
+
+ def testEscapingAndLineBreaks(self):
+ original = """{
+ 'policy_definitions': [],
+ 'messages': {
+ 'msg1': {
+ # The following line will contain two backslash characters when it
+ # ends up in eval().
+ 'text': '''backslashes, Sir? \\\\''',
+ 'desc': '',
+ },
+ 'msg2': {
+ 'text': '''quotes, Madam? "''',
+ 'desc': '',
+ },
+ 'msg3': {
+ # The following line will contain two backslash characters when it
+ # ends up in eval().
+ 'text': 'backslashes, Sir? \\\\',
+ 'desc': '',
+ },
+ 'msg4': {
+ 'text': "quotes, Madam? '",
+ 'desc': '',
+ },
+ 'msg5': {
+ 'text': '''what happens
+with a newline?''',
+ 'desc': ''
+ },
+ 'msg6': {
+ # The following line will contain a backslash+n when it ends up in
+ # eval().
+ 'text': 'what happens\\nwith a newline? (Episode 1)',
+ 'desc': ''
+ }
+ }
+}"""
+ gatherer = policy_json.PolicyJson(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(len(gatherer.GetCliques()) == 6)
+ expected = self.GetExpectedOutput(original)
+ self.failUnless(expected == eval(gatherer.Translate('en')))
+
+ def testPlaceholders(self):
+ original = """{
+ 'policy_definitions': [
+ {
+ 'name': 'Policy1',
+ 'caption': '''Please install
+ <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.''',
+ },
+ ],
+ 'messages': {}
+}"""
+ gatherer = policy_json.PolicyJson(StringIO.StringIO(original))
+ gatherer.Parse()
+ self.failUnless(len(gatherer.GetCliques()) == 1)
+ expected = eval(re.sub('<ph.*ph>', '$1', original))
+ self.failUnless(expected == eval(gatherer.Translate('en')))
+ self.failUnless(gatherer.GetCliques()[0].translateable)
+ msg = gatherer.GetCliques()[0].GetMessage()
+ self.failUnless(len(msg.GetPlaceholders()) == 1)
+ ph = msg.GetPlaceholders()[0]
+ self.failUnless(ph.GetOriginal() == '$1')
+ self.failUnless(ph.GetPresentation() == 'PRODUCT_NAME')
+ self.failUnless(ph.GetExample() == 'Google Chrome')
+
+ def testGetDescription(self):
+ gatherer = policy_json.PolicyJson({})
+ self.assertEquals(
+ gatherer._GetDescription({'name': 'Policy1'}, 'policy', None, 'desc'),
+ 'Description of the policy named Policy1')
+ self.assertEquals(
+ gatherer._GetDescription({'name': 'Plcy2'}, 'policy', None, 'caption'),
+ 'Caption of the policy named Plcy2')
+ self.assertEquals(
+ gatherer._GetDescription({'name': 'Plcy3'}, 'policy', None, 'label'),
+ 'Label of the policy named Plcy3')
+ self.assertEquals(
+ gatherer._GetDescription({'name': 'Item'}, 'enum_item',
+ {'name': 'Policy'}, 'caption'),
+ 'Caption of the option named Item in policy Policy')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/gather/rc.py b/chromium/tools/grit/grit/gather/rc.py
new file mode 100644
index 00000000000..f1e8982ec7a
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/rc.py
@@ -0,0 +1,343 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Support for gathering resources from RC files.
+'''
+
+
+import re
+
+from grit import exception
+from grit import lazy_re
+from grit import tclib
+
+from grit.gather import regexp
+
+
+# Find portions that need unescaping in resource strings. We need to be
+# careful that a \\n is matched _first_ as a \\ rather than matching as
+# a \ followed by a \n.
+# TODO(joi) Handle ampersands if we decide to change them into <ph>
+# TODO(joi) May need to handle other control characters than \n
+_NEED_UNESCAPE = lazy_re.compile(r'""|\\\\|\\n|\\t')
+
+# Find portions that need escaping to encode string as a resource string.
+_NEED_ESCAPE = lazy_re.compile(r'"|\n|\t|\\|\&nbsp\;')
+
+# How to escape certain characters
+_ESCAPE_CHARS = {
+ '"' : '""',
+ '\n' : '\\n',
+ '\t' : '\\t',
+ '\\' : '\\\\',
+ '&nbsp;' : ' '
+}
+
+# How to unescape certain strings
+_UNESCAPE_CHARS = dict([[value, key] for key, value in _ESCAPE_CHARS.items()])
+
+
+
+class Section(regexp.RegexpGatherer):
+ '''A section from a resource file.'''
+
+ @staticmethod
+ def Escape(text):
+ '''Returns a version of 'text' with characters escaped that need to be
+ for inclusion in a resource section.'''
+ def Replace(match):
+ return _ESCAPE_CHARS[match.group()]
+ return _NEED_ESCAPE.sub(Replace, text)
+
+ @staticmethod
+ def UnEscape(text):
+ '''Returns a version of 'text' with escaped characters unescaped.'''
+ def Replace(match):
+ return _UNESCAPE_CHARS[match.group()]
+ return _NEED_UNESCAPE.sub(Replace, text)
+
+ def _RegExpParse(self, rexp, text_to_parse):
+ '''Overrides _RegExpParse to add shortcut group handling. Otherwise
+ the same.
+ '''
+ super(Section, self)._RegExpParse(rexp, text_to_parse)
+
+ if not self.is_skeleton and len(self.GetTextualIds()) > 0:
+ group_name = self.GetTextualIds()[0]
+ for c in self.GetCliques():
+ c.AddToShortcutGroup(group_name)
+
+ def ReadSection(self):
+ rc_text = self._LoadInputFile()
+
+ out = ''
+ begin_count = 0
+ assert self.extkey
+ first_line_re = re.compile(r'\s*' + self.extkey + r'\b')
+ for line in rc_text.splitlines(True):
+ if out or first_line_re.match(line):
+ out += line
+
+ # we stop once we reach the END for the outermost block.
+ begin_count_was = begin_count
+ if len(out) > 0 and line.strip() == 'BEGIN':
+ begin_count += 1
+ elif len(out) > 0 and line.strip() == 'END':
+ begin_count -= 1
+ if begin_count_was == 1 and begin_count == 0:
+ break
+
+ if len(out) == 0:
+ raise exception.SectionNotFound('%s in file %s' % (self.extkey, self.rc_file))
+
+ self.text_ = out.strip()
+
+
+class Dialog(Section):
+ '''A resource section that contains a dialog resource.'''
+
+ # A typical dialog resource section looks like this:
+ #
+ # IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
+ # STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+ # CAPTION "About"
+ # FONT 8, "System", 0, 0, 0x0
+ # BEGIN
+ # ICON IDI_KLONK,IDC_MYICON,14,9,20,20
+ # LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
+ # SS_NOPREFIX
+ # LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
+ # DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
+ # CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
+ # BS_AUTORADIOBUTTON,46,51,84,10
+ # END
+
+ # We are using a sorted set of keys, and we assume that the
+ # group name used for descriptions (type) will come after the "text"
+ # group in alphabetical order. We also assume that there cannot be
+ # more than one description per regular expression match.
+ # If that's not the case some descriptions will be clobbered.
+ dialog_re_ = lazy_re.compile('''
+ # The dialog's ID in the first line
+ (?P<id1>[A-Z0-9_]+)\s+DIALOG(EX)?
+ |
+ # The caption of the dialog
+ (?P<type1>CAPTION)\s+"(?P<text1>.*?([^"]|""))"\s
+ |
+ # Lines for controls that have text and an ID
+ \s+(?P<type2>[A-Z]+)\s+"(?P<text2>.*?([^"]|"")?)"\s*,\s*(?P<id2>[A-Z0-9_]+)\s*,
+ |
+ # Lines for controls that have text only
+ \s+(?P<type3>[A-Z]+)\s+"(?P<text3>.*?([^"]|"")?)"\s*,
+ |
+ # Lines for controls that reference other resources
+ \s+[A-Z]+\s+[A-Z0-9_]+\s*,\s*(?P<id3>[A-Z0-9_]*[A-Z][A-Z0-9_]*)
+ |
+ # This matches "NOT SOME_STYLE" so that it gets consumed and doesn't get
+ # matched by the next option (controls that have only an ID and then just
+ # numbers)
+ \s+NOT\s+[A-Z][A-Z0-9_]+
+ |
+ # Lines for controls that have only an ID and then just numbers
+ \s+[A-Z]+\s+(?P<id4>[A-Z0-9_]*[A-Z][A-Z0-9_]*)\s*,
+ ''', re.MULTILINE | re.VERBOSE)
+
+ def Parse(self):
+ '''Knows how to parse dialog resource sections.'''
+ self.ReadSection()
+ self._RegExpParse(self.dialog_re_, self.text_)
+
+
+class Menu(Section):
+ '''A resource section that contains a menu resource.'''
+
+ # A typical menu resource section looks something like this:
+ #
+ # IDC_KLONK MENU
+ # BEGIN
+ # POPUP "&File"
+ # BEGIN
+ # MENUITEM "E&xit", IDM_EXIT
+ # MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
+ # POPUP "gonk"
+ # BEGIN
+ # MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
+ # END
+ # END
+ # POPUP "&Help"
+ # BEGIN
+ # MENUITEM "&About ...", IDM_ABOUT
+ # END
+ # END
+
+ # Description used for the messages generated for menus, to explain to
+ # the translators how to handle them.
+ MENU_MESSAGE_DESCRIPTION = (
+ 'This message represents a menu. Each of the items appears in sequence '
+ '(some possibly within sub-menus) in the menu. The XX01XX placeholders '
+ 'serve to separate items. Each item contains an & (ampersand) character '
+ 'in front of the keystroke that should be used as a shortcut for that item '
+ 'in the menu. Please make sure that no two items in the same menu share '
+ 'the same shortcut.'
+ )
+
+ # A dandy regexp to suck all the IDs and translateables out of a menu
+ # resource
+ menu_re_ = lazy_re.compile('''
+ # Match the MENU ID on the first line
+ ^(?P<id1>[A-Z0-9_]+)\s+MENU
+ |
+ # Match the translateable caption for a popup menu
+ POPUP\s+"(?P<text1>.*?([^"]|""))"\s
+ |
+ # Match the caption & ID of a MENUITEM
+ MENUITEM\s+"(?P<text2>.*?([^"]|""))"\s*,\s*(?P<id2>[A-Z0-9_]+)
+ ''', re.MULTILINE | re.VERBOSE)
+
+ def Parse(self):
+ '''Knows how to parse menu resource sections. Because it is important that
+ menu shortcuts are unique within the menu, we return each menu as a single
+ message with placeholders to break up the different menu items, rather than
+ return a single message per menu item. we also add an automatic description
+ with instructions for the translators.'''
+ self.ReadSection()
+ self.single_message_ = tclib.Message(description=self.MENU_MESSAGE_DESCRIPTION)
+ self._RegExpParse(self.menu_re_, self.text_)
+
+
+class Version(Section):
+ '''A resource section that contains a VERSIONINFO resource.'''
+
+ # A typical version info resource can look like this:
+ #
+ # VS_VERSION_INFO VERSIONINFO
+ # FILEVERSION 1,0,0,1
+ # PRODUCTVERSION 1,0,0,1
+ # FILEFLAGSMASK 0x3fL
+ # #ifdef _DEBUG
+ # FILEFLAGS 0x1L
+ # #else
+ # FILEFLAGS 0x0L
+ # #endif
+ # FILEOS 0x4L
+ # FILETYPE 0x2L
+ # FILESUBTYPE 0x0L
+ # BEGIN
+ # BLOCK "StringFileInfo"
+ # BEGIN
+ # BLOCK "040904e4"
+ # BEGIN
+ # VALUE "CompanyName", "TODO: <Company name>"
+ # VALUE "FileDescription", "TODO: <File description>"
+ # VALUE "FileVersion", "1.0.0.1"
+ # VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
+ # VALUE "InternalName", "res_format_test.dll"
+ # VALUE "OriginalFilename", "res_format_test.dll"
+ # VALUE "ProductName", "TODO: <Product name>"
+ # VALUE "ProductVersion", "1.0.0.1"
+ # END
+ # END
+ # BLOCK "VarFileInfo"
+ # BEGIN
+ # VALUE "Translation", 0x409, 1252
+ # END
+ # END
+ #
+ #
+ # In addition to the above fields, VALUE fields named "Comments" and
+ # "LegalTrademarks" may also be translateable.
+
+ version_re_ = lazy_re.compile('''
+ # Match the ID on the first line
+ ^(?P<id1>[A-Z0-9_]+)\s+VERSIONINFO
+ |
+ # Match all potentially translateable VALUE sections
+ \s+VALUE\s+"
+ (
+ CompanyName|FileDescription|LegalCopyright|
+ ProductName|Comments|LegalTrademarks
+ )",\s+"(?P<text1>.*?([^"]|""))"\s
+ ''', re.MULTILINE | re.VERBOSE)
+
+ def Parse(self):
+ '''Knows how to parse VERSIONINFO resource sections.'''
+ self.ReadSection()
+ self._RegExpParse(self.version_re_, self.text_)
+
+ # TODO(joi) May need to override the Translate() method to change the
+ # "Translation" VALUE block to indicate the correct language code.
+
+
+class RCData(Section):
+ '''A resource section that contains some data .'''
+
+ # A typical rcdataresource section looks like this:
+ #
+ # IDR_BLAH RCDATA { 1, 2, 3, 4 }
+
+ dialog_re_ = lazy_re.compile('''
+ ^(?P<id1>[A-Z0-9_]+)\s+RCDATA\s+(DISCARDABLE)?\s+\{.*?\}
+ ''', re.MULTILINE | re.VERBOSE | re.DOTALL)
+
+ def Parse(self):
+ '''Implementation for resource types w/braces (not BEGIN/END)
+ '''
+ rc_text = self._LoadInputFile()
+
+ out = ''
+ begin_count = 0
+ openbrace_count = 0
+ assert self.extkey
+ first_line_re = re.compile(r'\s*' + self.extkey + r'\b')
+ for line in rc_text.splitlines(True):
+ if out or first_line_re.match(line):
+ out += line
+
+ # We stop once the braces balance (could happen in one line).
+ begin_count_was = begin_count
+ if len(out) > 0:
+ openbrace_count += line.count('{')
+ begin_count += line.count('{')
+ begin_count -= line.count('}')
+ if ((begin_count_was == 1 and begin_count == 0) or
+ (openbrace_count > 0 and begin_count == 0)):
+ break
+
+ if len(out) == 0:
+ raise exception.SectionNotFound('%s in file %s' % (self.extkey, self.rc_file))
+
+ self.text_ = out
+
+ self._RegExpParse(self.dialog_re_, out)
+
+
+class Accelerators(Section):
+ '''An ACCELERATORS table.
+ '''
+
+ # A typical ACCELERATORS section looks like this:
+ #
+ # IDR_ACCELERATOR1 ACCELERATORS
+ # BEGIN
+ # "^C", ID_ACCELERATOR32770, ASCII, NOINVERT
+ # "^V", ID_ACCELERATOR32771, ASCII, NOINVERT
+ # VK_INSERT, ID_ACCELERATOR32772, VIRTKEY, CONTROL, NOINVERT
+ # END
+
+ accelerators_re_ = lazy_re.compile('''
+ # Match the ID on the first line
+ ^(?P<id1>[A-Z0-9_]+)\s+ACCELERATORS\s+
+ |
+ # Match accelerators specified as VK_XXX
+ \s+VK_[A-Z0-9_]+,\s*(?P<id2>[A-Z0-9_]+)\s*,
+ |
+ # Match accelerators specified as e.g. "^C"
+ \s+"[^"]*",\s+(?P<id3>[A-Z0-9_]+)\s*,
+ ''', re.MULTILINE | re.VERBOSE)
+
+ def Parse(self):
+ '''Knows how to parse ACCELERATORS resource sections.'''
+ self.ReadSection()
+ self._RegExpParse(self.accelerators_re_, self.text_)
diff --git a/chromium/tools/grit/grit/gather/rc_unittest.py b/chromium/tools/grit/grit/gather/rc_unittest.py
new file mode 100644
index 00000000000..c4be35e1ee2
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/rc_unittest.py
@@ -0,0 +1,370 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.gather.rc'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit.gather import rc
+from grit import util
+
+
+class RcUnittest(unittest.TestCase):
+
+ part_we_want = '''IDC_KLONKACC ACCELERATORS
+BEGIN
+ "?", IDM_ABOUT, ASCII, ALT
+ "/", IDM_ABOUT, ASCII, ALT
+END'''
+
+ def testSectionFromFile(self):
+ buf = '''IDC_SOMETHINGELSE BINGO
+BEGIN
+ BLA BLA
+ BLA BLA
+END
+%s
+
+IDC_KLONK BINGOBONGO
+BEGIN
+ HONGO KONGO
+END
+''' % self.part_we_want
+
+ f = StringIO.StringIO(buf)
+
+ out = rc.Section(f, 'IDC_KLONKACC')
+ out.ReadSection()
+ self.failUnless(out.GetText() == self.part_we_want)
+
+ out = rc.Section(util.PathFromRoot(r'grit/testdata/klonk.rc'),
+ 'IDC_KLONKACC',
+ encoding='utf-16')
+ out.ReadSection()
+ out_text = out.GetText().replace('\t', '')
+ out_text = out_text.replace(' ', '')
+ self.part_we_want = self.part_we_want.replace(' ', '')
+ self.failUnless(out_text.strip() == self.part_we_want.strip())
+
+
+ def testDialog(self):
+ dlg = rc.Dialog(StringIO.StringIO('''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
+ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
+ SS_NOPREFIX
+ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
+ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON,46,51,84,10
+ // try a line where the ID is on the continuation line
+ LTEXT "blablablabla blablabla blablablablablablablabla blablabla",
+ ID_SMURF, whatever...
+END
+'''), 'IDD_ABOUTBOX')
+ dlg.Parse()
+ self.failUnless(len(dlg.GetTextualIds()) == 7)
+ self.failUnless(len(dlg.GetCliques()) == 6)
+ self.failUnless(dlg.GetCliques()[1].GetMessage().GetRealContent() ==
+ 'klonk Version "yibbee" 1.0')
+
+ transl = dlg.Translate('en')
+ self.failUnless(transl.strip() == dlg.GetText().strip())
+
+ def testAlternateSkeleton(self):
+ dlg = rc.Dialog(StringIO.StringIO('''IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ LTEXT "Yipee skippy",IDC_STATIC,49,10,119,8,
+ SS_NOPREFIX
+END
+'''), 'IDD_ABOUTBOX')
+ dlg.Parse()
+
+ alt_dlg = rc.Dialog(StringIO.StringIO('''IDD_ABOUTBOX DIALOGEX 040704, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "XXXXXXXXX"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ LTEXT "XXXXXXXXXXXXXXXXX",IDC_STATIC,110978,10,119,8,
+ SS_NOPREFIX
+END
+'''), 'IDD_ABOUTBOX')
+ alt_dlg.Parse()
+
+ transl = dlg.Translate('en', skeleton_gatherer=alt_dlg)
+ self.failUnless(transl.count('040704') and
+ transl.count('110978'))
+ self.failUnless(transl.count('Yipee skippy'))
+
+ def testMenu(self):
+ menu = rc.Menu(StringIO.StringIO('''IDC_KLONK MENU
+BEGIN
+ POPUP "&File """
+ BEGIN
+ MENUITEM "E&xit", IDM_EXIT
+ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
+ POPUP "gonk"
+ BEGIN
+ MENUITEM "Klonk && is ""good""", ID_GONK_KLONKIS
+ END
+ MENUITEM "This is a very long menu caption to try to see if we can make the ID go to a continuation line, blablabla blablabla bla blabla blablabla blablabla blablabla blablabla...",
+ ID_FILE_THISISAVERYLONGMENUCAPTIONTOTRYTOSEEIFWECANMAKETHEIDGOTOACONTINUATIONLINE
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About ...", IDM_ABOUT
+ END
+END'''), 'IDC_KLONK')
+
+ menu.Parse()
+ self.failUnless(len(menu.GetTextualIds()) == 6)
+ self.failUnless(len(menu.GetCliques()) == 1)
+ self.failUnless(len(menu.GetCliques()[0].GetMessage().GetPlaceholders()) ==
+ 9)
+
+ transl = menu.Translate('en')
+ self.failUnless(transl.strip() == menu.GetText().strip())
+
+ def testVersion(self):
+ version = rc.Version(StringIO.StringIO('''
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "TODO: <Company name>"
+ VALUE "FileDescription", "TODO: <File description>"
+ VALUE "FileVersion", "1.0.0.1"
+ VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
+ VALUE "InternalName", "res_format_test.dll"
+ VALUE "OriginalFilename", "res_format_test.dll"
+ VALUE "ProductName", "TODO: <Product name>"
+ VALUE "ProductVersion", "1.0.0.1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+'''.strip()), 'VS_VERSION_INFO')
+ version.Parse()
+ self.failUnless(len(version.GetTextualIds()) == 1)
+ self.failUnless(len(version.GetCliques()) == 4)
+
+ transl = version.Translate('en')
+ self.failUnless(transl.strip() == version.GetText().strip())
+
+
+ def testRegressionDialogBox(self):
+ dialog = rc.Dialog(StringIO.StringIO('''
+IDD_SIDEBAR_WEATHER_PANEL_PROPPAGE DIALOGEX 0, 0, 205, 157
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ EDITTEXT IDC_SIDEBAR_WEATHER_NEW_CITY,3,27,112,14,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "Add Location",IDC_SIDEBAR_WEATHER_ADD,119,27,50,14
+ LISTBOX IDC_SIDEBAR_WEATHER_CURR_CITIES,3,48,127,89,
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Move Up",IDC_SIDEBAR_WEATHER_MOVE_UP,134,104,50,14
+ PUSHBUTTON "Move Down",IDC_SIDEBAR_WEATHER_MOVE_DOWN,134,121,50,14
+ PUSHBUTTON "Remove",IDC_SIDEBAR_WEATHER_DELETE,134,48,50,14
+ LTEXT "To see current weather conditions and forecasts in the USA, enter the zip code (example: 94043) or city and state (example: Mountain View, CA).",
+ IDC_STATIC,3,0,199,25
+ CONTROL "Fahrenheit",IDC_SIDEBAR_WEATHER_FAHRENHEIT,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,3,144,51,10
+ CONTROL "Celsius",IDC_SIDEBAR_WEATHER_CELSIUS,"Button",
+ BS_AUTORADIOBUTTON,57,144,38,10
+END'''.strip()), 'IDD_SIDEBAR_WEATHER_PANEL_PROPPAGE')
+ dialog.Parse()
+ self.failUnless(len(dialog.GetTextualIds()) == 10)
+
+
+ def testRegressionDialogBox2(self):
+ dialog = rc.Dialog(StringIO.StringIO('''
+IDD_SIDEBAR_EMAIL_PANEL_PROPPAGE DIALOG DISCARDABLE 0, 0, 264, 220
+STYLE WS_CHILD
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Email Filters",IDC_STATIC,7,3,250,190
+ LTEXT "Click Add Filter to create the email filter.",IDC_STATIC,16,41,130,9
+ PUSHBUTTON "Add Filter...",IDC_SIDEBAR_EMAIL_ADD_FILTER,196,38,50,14
+ PUSHBUTTON "Remove",IDC_SIDEBAR_EMAIL_REMOVE,196,174,50,14
+ PUSHBUTTON "", IDC_SIDEBAR_EMAIL_HIDDEN, 200, 178, 5, 5, NOT WS_VISIBLE
+ LISTBOX IDC_SIDEBAR_EMAIL_LIST,16,60,230,108,
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "You can prevent certain emails from showing up in the sidebar with a filter.",
+ IDC_STATIC,16,18,234,18
+END'''.strip()), 'IDD_SIDEBAR_EMAIL_PANEL_PROPPAGE')
+ dialog.Parse()
+ self.failUnless('IDC_SIDEBAR_EMAIL_HIDDEN' in dialog.GetTextualIds())
+
+
+ def testRegressionMenuId(self):
+ menu = rc.Menu(StringIO.StringIO('''
+IDR_HYPERMENU_FOLDER MENU
+BEGIN
+ POPUP "HyperFolder"
+ BEGIN
+ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
+ END
+END'''.strip()), 'IDR_HYPERMENU_FOLDER')
+ menu.Parse()
+ self.failUnless(len(menu.GetTextualIds()) == 2)
+
+ def testRegressionNewlines(self):
+ menu = rc.Menu(StringIO.StringIO('''
+IDR_HYPERMENU_FOLDER MENU
+BEGIN
+ POPUP "Hyper\\nFolder"
+ BEGIN
+ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
+ END
+END'''.strip()), 'IDR_HYPERMENU_FOLDER')
+ menu.Parse()
+ transl = menu.Translate('en')
+ # Shouldn't find \\n (the \n shouldn't be changed to \\n)
+ self.failUnless(transl.find('\\\\n') == -1)
+
+ def testRegressionTabs(self):
+ menu = rc.Menu(StringIO.StringIO('''
+IDR_HYPERMENU_FOLDER MENU
+BEGIN
+ POPUP "Hyper\\tFolder"
+ BEGIN
+ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
+ END
+END'''.strip()), 'IDR_HYPERMENU_FOLDER')
+ menu.Parse()
+ transl = menu.Translate('en')
+ # Shouldn't find \\t (the \t shouldn't be changed to \\t)
+ self.failUnless(transl.find('\\\\t') == -1)
+
+ def testEscapeUnescape(self):
+ original = 'Hello "bingo"\n How\\are\\you\\n?'
+ escaped = rc.Section.Escape(original)
+ self.failUnless(escaped == 'Hello ""bingo""\\n How\\\\are\\\\you\\\\n?')
+ unescaped = rc.Section.UnEscape(escaped)
+ self.failUnless(unescaped == original)
+
+ def testRegressionPathsWithSlashN(self):
+ original = '..\\\\..\\\\trs\\\\res\\\\nav_first.gif'
+ unescaped = rc.Section.UnEscape(original)
+ self.failUnless(unescaped == '..\\..\\trs\\res\\nav_first.gif')
+
+ def testRegressionDialogItemsTextOnly(self):
+ dialog = rc.Dialog(StringIO.StringIO('''IDD_OPTIONS_SEARCH DIALOGEX 0, 0, 280, 292
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_DISABLED | WS_CAPTION | WS_SYSMENU
+CAPTION "Search"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Select search buttons and options",-1,7,5,266,262
+ CONTROL "",IDC_OPTIONS,"SysTreeView32",TVS_DISABLEDRAGDROP |
+ WS_BORDER | WS_TABSTOP | 0x800,16,19,248,218
+ LTEXT "Use Google site:",-1,26,248,52,8
+ COMBOBOX IDC_GOOGLE_HOME,87,245,177,256,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Restore Defaults...",IDC_RESET,187,272,86,14
+END'''), 'IDD_OPTIONS_SEARCH')
+ dialog.Parse()
+ translateables = [c.GetMessage().GetRealContent()
+ for c in dialog.GetCliques()]
+ self.failUnless('Select search buttons and options' in translateables)
+ self.failUnless('Use Google site:' in translateables)
+
+ def testAccelerators(self):
+ acc = rc.Accelerators(StringIO.StringIO('''\
+IDR_ACCELERATOR1 ACCELERATORS
+BEGIN
+ "^C", ID_ACCELERATOR32770, ASCII, NOINVERT
+ "^V", ID_ACCELERATOR32771, ASCII, NOINVERT
+ VK_INSERT, ID_ACCELERATOR32772, VIRTKEY, CONTROL, NOINVERT
+END
+'''), 'IDR_ACCELERATOR1')
+ acc.Parse()
+ self.failUnless(len(acc.GetTextualIds()) == 4)
+ self.failUnless(len(acc.GetCliques()) == 0)
+
+ transl = acc.Translate('en')
+ self.failUnless(transl.strip() == acc.GetText().strip())
+
+
+ def testRegressionEmptyString(self):
+ dlg = rc.Dialog(StringIO.StringIO('''\
+IDD_CONFIRM_QUIT_GD_DLG DIALOGEX 0, 0, 267, 108
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_CAPTION
+EXSTYLE WS_EX_TOPMOST
+CAPTION "Google Desktop"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "&Yes",IDYES,82,87,50,14
+ PUSHBUTTON "&No",IDNO,136,87,50,14
+ ICON 32514,IDC_STATIC,7,9,21,20
+ EDITTEXT IDC_TEXTBOX,34,7,231,60,ES_MULTILINE | ES_READONLY | NOT WS_BORDER
+ CONTROL "",
+ IDC_ENABLE_GD_AUTOSTART,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,33,70,231,10
+END'''), 'IDD_CONFIRM_QUIT_GD_DLG')
+ dlg.Parse()
+
+ def Check():
+ self.failUnless(transl.count('IDC_ENABLE_GD_AUTOSTART'))
+ self.failUnless(transl.count('END'))
+
+ transl = dlg.Translate('de', pseudo_if_not_available=True,
+ fallback_to_english=True)
+ Check()
+ transl = dlg.Translate('de', pseudo_if_not_available=True,
+ fallback_to_english=False)
+ Check()
+ transl = dlg.Translate('de', pseudo_if_not_available=False,
+ fallback_to_english=True)
+ Check()
+ transl = dlg.Translate('de', pseudo_if_not_available=False,
+ fallback_to_english=False)
+ Check()
+ transl = dlg.Translate('en', pseudo_if_not_available=True,
+ fallback_to_english=True)
+ Check()
+ transl = dlg.Translate('en', pseudo_if_not_available=True,
+ fallback_to_english=False)
+ Check()
+ transl = dlg.Translate('en', pseudo_if_not_available=False,
+ fallback_to_english=True)
+ Check()
+ transl = dlg.Translate('en', pseudo_if_not_available=False,
+ fallback_to_english=False)
+ Check()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/gather/regexp.py b/chromium/tools/grit/grit/gather/regexp.py
new file mode 100644
index 00000000000..30488a610fb
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/regexp.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''A baseclass for simple gatherers based on regular expressions.
+'''
+
+import re
+
+from grit.gather import skeleton_gatherer
+
+
+class RegexpGatherer(skeleton_gatherer.SkeletonGatherer):
+ '''Common functionality of gatherers based on parsing using a single
+ regular expression.
+ '''
+
+ DescriptionMapping_ = {
+ 'CAPTION' : 'This is a caption for a dialog',
+ 'CHECKBOX' : 'This is a label for a checkbox',
+ 'CONTROL': 'This is the text on a control',
+ 'CTEXT': 'This is a label for a control',
+ 'DEFPUSHBUTTON': 'This is a button definition',
+ 'GROUPBOX': 'This is a label for a grouping',
+ 'ICON': 'This is a label for an icon',
+ 'LTEXT': 'This is the text for a label',
+ 'PUSHBUTTON': 'This is the text for a button',
+ }
+
+ # Contextualization elements. Used for adding additional information
+ # to the message bundle description string from RC files.
+ def AddDescriptionElement(self, string):
+ if self.DescriptionMapping_.has_key(string):
+ description = self.DescriptionMapping_[string]
+ else:
+ description = string
+ if self.single_message_:
+ self.single_message_.SetDescription(description)
+ else:
+ if (self.translatable_chunk_):
+ message = self.skeleton_[len(self.skeleton_) - 1].GetMessage()
+ message.SetDescription(description)
+
+ def _RegExpParse(self, regexp, text_to_parse):
+ '''An implementation of Parse() that can be used for resource sections that
+ can be parsed using a single multi-line regular expression.
+
+ All translateables must be in named groups that have names starting with
+ 'text'. All textual IDs must be in named groups that have names starting
+ with 'id'. All type definitions that can be included in the description
+ field for contextualization purposes should have a name that starts with
+ 'type'.
+
+ Args:
+ regexp: re.compile('...', re.MULTILINE)
+ text_to_parse:
+ '''
+ chunk_start = 0
+ for match in regexp.finditer(text_to_parse):
+ groups = match.groupdict()
+ keys = groups.keys()
+ keys.sort()
+ self.translatable_chunk_ = False
+ for group in keys:
+ if group.startswith('id') and groups[group]:
+ self._AddTextualId(groups[group])
+ elif group.startswith('text') and groups[group]:
+ self._AddNontranslateableChunk(
+ text_to_parse[chunk_start : match.start(group)])
+ chunk_start = match.end(group) # Next chunk will start after the match
+ self._AddTranslateableChunk(groups[group])
+ elif group.startswith('type') and groups[group]:
+ # Add the description to the skeleton_ list. This works because
+ # we are using a sort set of keys, and because we assume that the
+ # group name used for descriptions (type) will come after the "text"
+ # group in alphabetical order. We also assume that there cannot be
+ # more than one description per regular expression match.
+ self.AddDescriptionElement(groups[group])
+
+ self._AddNontranslateableChunk(text_to_parse[chunk_start:])
+
+ if self.single_message_:
+ self.skeleton_.append(self.uberclique.MakeClique(self.single_message_))
+
diff --git a/chromium/tools/grit/grit/gather/skeleton_gatherer.py b/chromium/tools/grit/grit/gather/skeleton_gatherer.py
new file mode 100644
index 00000000000..38b504c3812
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/skeleton_gatherer.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''A baseclass for simple gatherers that store their gathered resource in a
+list.
+'''
+
+import types
+
+from grit.gather import interface
+from grit import clique
+from grit import tclib
+
+
+class SkeletonGatherer(interface.GathererBase):
+ '''Common functionality of gatherers that parse their input as a skeleton of
+ translatable and nontranslatable chunks.
+ '''
+
+ def __init__(self, *args, **kwargs):
+ super(SkeletonGatherer, self).__init__(*args, **kwargs)
+ # List of parts of the document. Translateable parts are
+ # clique.MessageClique objects, nontranslateable parts are plain strings.
+ # Translated messages are inserted back into the skeleton using the quoting
+ # rules defined by self.Escape()
+ self.skeleton_ = []
+ # A list of the names of IDs that need to be defined for this resource
+ # section to compile correctly.
+ self.ids_ = []
+ # True if Parse() has already been called.
+ self.have_parsed_ = False
+ # True if a translatable chunk has been added
+ self.translatable_chunk_ = False
+ # If not None, all parts of the document will be put into this single
+ # message; otherwise the normal skeleton approach is used.
+ self.single_message_ = None
+ # Number to use for the next placeholder name. Used only if single_message
+ # is not None
+ self.ph_counter_ = 1
+
+ def GetText(self):
+ '''Returns the original text of the section'''
+ return self.text_
+
+ def Escape(self, text):
+ '''Subclasses can override. Base impl is identity.
+ '''
+ return text
+
+ def UnEscape(self, text):
+ '''Subclasses can override. Base impl is identity.
+ '''
+ return text
+
+ def GetTextualIds(self):
+ '''Returns the list of textual IDs that need to be defined for this
+ resource section to compile correctly.'''
+ return self.ids_
+
+ def _AddTextualId(self, id):
+ self.ids_.append(id)
+
+ def GetCliques(self):
+ '''Returns the message cliques for each translateable message in the
+ resource section.'''
+ return [x for x in self.skeleton_ if isinstance(x, clique.MessageClique)]
+
+ def Translate(self, lang, pseudo_if_not_available=True,
+ skeleton_gatherer=None, fallback_to_english=False):
+ if len(self.skeleton_) == 0:
+ raise exception.NotReady()
+ if skeleton_gatherer:
+ assert len(skeleton_gatherer.skeleton_) == len(self.skeleton_)
+
+ out = []
+ for ix in range(len(self.skeleton_)):
+ if isinstance(self.skeleton_[ix], types.StringTypes):
+ if skeleton_gatherer:
+ # Make sure the skeleton is like the original
+ assert(isinstance(skeleton_gatherer.skeleton_[ix], types.StringTypes))
+ out.append(skeleton_gatherer.skeleton_[ix])
+ else:
+ out.append(self.skeleton_[ix])
+ else:
+ if skeleton_gatherer: # Make sure the skeleton is like the original
+ assert(not isinstance(skeleton_gatherer.skeleton_[ix],
+ types.StringTypes))
+ msg = self.skeleton_[ix].MessageForLanguage(lang,
+ pseudo_if_not_available,
+ fallback_to_english)
+
+ def MyEscape(text):
+ return self.Escape(text)
+ text = msg.GetRealContent(escaping_function=MyEscape)
+ out.append(text)
+ return ''.join(out)
+
+ def Parse(self):
+ '''Parses the section. Implemented by subclasses. Idempotent.'''
+ raise NotImplementedError()
+
+ def _AddNontranslateableChunk(self, chunk):
+ '''Adds a nontranslateable chunk.'''
+ if self.single_message_:
+ ph = tclib.Placeholder('XX%02dXX' % self.ph_counter_, chunk, chunk)
+ self.ph_counter_ += 1
+ self.single_message_.AppendPlaceholder(ph)
+ else:
+ self.skeleton_.append(chunk)
+
+ def _AddTranslateableChunk(self, chunk):
+ '''Adds a translateable chunk. It will be unescaped before being added.'''
+ # We don't want empty messages since they are redundant and the TC
+ # doesn't allow them.
+ if chunk == '':
+ return
+
+ unescaped_text = self.UnEscape(chunk)
+ if self.single_message_:
+ self.single_message_.AppendText(unescaped_text)
+ else:
+ self.skeleton_.append(self.uberclique.MakeClique(
+ tclib.Message(text=unescaped_text)))
+ self.translatable_chunk_ = True
+
+ def SubstituteMessages(self, substituter):
+ '''Applies substitutions to all messages in the tree.
+
+ Goes through the skeleton and finds all MessageCliques.
+
+ Args:
+ substituter: a grit.util.Substituter object.
+ '''
+ if self.single_message_:
+ self.single_message_ = substituter.SubstituteMessage(self.single_message_)
+ new_skel = []
+ for chunk in self.skeleton_:
+ if isinstance(chunk, clique.MessageClique):
+ old_message = chunk.GetMessage()
+ new_message = substituter.SubstituteMessage(old_message)
+ if new_message is not old_message:
+ new_skel.append(self.uberclique.MakeClique(new_message))
+ continue
+ new_skel.append(chunk)
+ self.skeleton_ = new_skel
diff --git a/chromium/tools/grit/grit/gather/tr_html.py b/chromium/tools/grit/grit/gather/tr_html.py
new file mode 100644
index 00000000000..348725109b8
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/tr_html.py
@@ -0,0 +1,745 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''A gatherer for the TotalRecall brand of HTML templates with replaceable
+portions. We wanted to reuse extern.tclib.api.handlers.html.TCHTMLParser
+but this proved impossible due to the fact that the TotalRecall HTML templates
+are in general quite far from parseable HTML and the TCHTMLParser derives
+from HTMLParser.HTMLParser which requires relatively well-formed HTML. Some
+examples of "HTML" from the TotalRecall HTML templates that wouldn't be
+parseable include things like:
+
+ <a [PARAMS]>blabla</a> (not parseable because attributes are invalid)
+
+ <table><tr><td>[LOTSOFSTUFF]</tr></table> (not parseable because closing
+ </td> is in the HTML [LOTSOFSTUFF]
+ is replaced by)
+
+The other problem with using general parsers (such as TCHTMLParser) is that
+we want to make sure we output the TotalRecall template with as little changes
+as possible in terms of whitespace characters, layout etc. With any parser
+that generates a parse tree, and generates output by dumping the parse tree,
+we would always have little inconsistencies which could cause bugs (the
+TotalRecall template stuff is quite brittle and can break if e.g. a tab
+character is replaced with spaces).
+
+The solution, which may be applicable to some other HTML-like template
+languages floating around Google, is to create a parser with a simple state
+machine that keeps track of what kind of tag it's inside, and whether it's in
+a translateable section or not. Translateable sections are:
+
+a) text (including [BINGO] replaceables) inside of tags that
+ can contain translateable text (which is all tags except
+ for a few)
+
+b) text inside of an 'alt' attribute in an <image> element, or
+ the 'value' attribute of a <submit>, <button> or <text>
+ element.
+
+The parser does not build up a parse tree but rather a "skeleton" which
+is a list of nontranslateable strings intermingled with grit.clique.MessageClique
+objects. This simplifies the parser considerably compared to a regular HTML
+parser. To output a translated document, each item in the skeleton is
+printed out, with the relevant Translation from each MessageCliques being used
+for the requested language.
+
+This implementation borrows some code, constants and ideas from
+extern.tclib.api.handlers.html.TCHTMLParser.
+'''
+
+
+import re
+import types
+
+from grit import clique
+from grit import exception
+from grit import lazy_re
+from grit import util
+from grit import tclib
+
+from grit.gather import interface
+
+
+# HTML tags which break (separate) chunks.
+_BLOCK_TAGS = ['script', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'br',
+ 'body', 'style', 'head', 'title', 'table', 'tr', 'td', 'th',
+ 'ul', 'ol', 'dl', 'nl', 'li', 'div', 'object', 'center',
+ 'html', 'link', 'form', 'select', 'textarea',
+ 'button', 'option', 'map', 'area', 'blockquote', 'pre',
+ 'meta', 'xmp', 'noscript', 'label', 'tbody', 'thead',
+ 'script', 'style', 'pre', 'iframe', 'img', 'input', 'nowrap',
+ 'fieldset', 'legend']
+
+# HTML tags which may appear within a chunk.
+_INLINE_TAGS = ['b', 'i', 'u', 'tt', 'code', 'font', 'a', 'span', 'small',
+ 'key', 'nobr', 'url', 'em', 's', 'sup', 'strike',
+ 'strong']
+
+# HTML tags within which linebreaks are significant.
+_PREFORMATTED_TAGS = ['textarea', 'xmp', 'pre']
+
+# An array mapping some of the inline HTML tags to more meaningful
+# names for those tags. This will be used when generating placeholders
+# representing these tags.
+_HTML_PLACEHOLDER_NAMES = { 'a' : 'link', 'br' : 'break', 'b' : 'bold',
+ 'i' : 'italic', 'li' : 'item', 'ol' : 'ordered_list', 'p' : 'paragraph',
+ 'ul' : 'unordered_list', 'img' : 'image', 'em' : 'emphasis' }
+
+# We append each of these characters in sequence to distinguish between
+# different placeholders with basically the same name (e.g. BOLD1, BOLD2).
+# Keep in mind that a placeholder name must not be a substring of any other
+# placeholder name in the same message, so we can't simply count (BOLD_1
+# would be a substring of BOLD_10).
+_SUFFIXES = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+# Matches whitespace in an HTML document. Also matches HTML comments, which are
+# treated as whitespace.
+_WHITESPACE = lazy_re.compile(r'(\s|&nbsp;|\\n|\\r|<!--\s*desc\s*=.*?-->)+',
+ re.DOTALL)
+
+# Matches whitespace sequences which can be folded into a single whitespace
+# character. This matches single characters so that non-spaces are replaced
+# with spaces.
+_FOLD_WHITESPACE = lazy_re.compile(r'\s+')
+
+# Finds a non-whitespace character
+_NON_WHITESPACE = lazy_re.compile(r'\S')
+
+# Matches two or more &nbsp; in a row (a single &nbsp is not changed into
+# placeholders because different languages require different numbers of spaces
+# and placeholders must match exactly; more than one is probably a "special"
+# whitespace sequence and should be turned into a placeholder).
+_NBSP = lazy_re.compile(r'&nbsp;(&nbsp;)+')
+
+# Matches nontranslateable chunks of the document
+_NONTRANSLATEABLES = lazy_re.compile(r'''
+ <\s*script.+?<\s*/\s*script\s*>
+ |
+ <\s*style.+?<\s*/\s*style\s*>
+ |
+ <!--.+?-->
+ |
+ <\?IMPORT\s.+?> # import tag
+ |
+ <\s*[a-zA-Z_]+:.+?> # custom tag (open)
+ |
+ <\s*/\s*[a-zA-Z_]+:.+?> # custom tag (close)
+ |
+ <!\s*[A-Z]+\s*([^>]+|"[^"]+"|'[^']+')*?>
+ ''', re.MULTILINE | re.DOTALL | re.VERBOSE | re.IGNORECASE)
+
+# Matches a tag and its attributes
+_ELEMENT = lazy_re.compile(r'''
+ # Optional closing /, element name
+ <\s*(?P<closing>/)?\s*(?P<element>[a-zA-Z0-9]+)\s*
+ # Attributes and/or replaceables inside the tag, if any
+ (?P<atts>(
+ \s*([a-zA-Z_][-:.a-zA-Z_0-9]*) # Attribute name
+ (\s*=\s*(\'[^\']*\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\(\)_#=~\'"@]*))?
+ |
+ \s*\[(\$?\~)?([A-Z0-9-_]+?)(\~\$?)?\]
+ )*)
+ \s*(?P<empty>/)?\s*> # Optional empty-tag closing /, and tag close
+ ''',
+ re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+# Matches elements that may have translateable attributes. The value of these
+# special attributes is given by group 'value1' or 'value2'. Note that this
+# regexp demands that the attribute value be quoted; this is necessary because
+# the non-tree-building nature of the parser means we don't know when we're
+# writing out attributes, so we wouldn't know to escape spaces.
+_SPECIAL_ELEMENT = lazy_re.compile(r'''
+ <\s*(
+ input[^>]+?value\s*=\s*(\'(?P<value3>[^\']*)\'|"(?P<value4>[^"]*)")
+ [^>]+type\s*=\s*"?'?(button|reset|text|submit)'?"?
+ |
+ (
+ table[^>]+?title\s*=
+ |
+ img[^>]+?alt\s*=
+ |
+ input[^>]+?type\s*=\s*"?'?(button|reset|text|submit)'?"?[^>]+?value\s*=
+ )
+ \s*(\'(?P<value1>[^\']*)\'|"(?P<value2>[^"]*)")
+ )[^>]*?>
+ ''', re.MULTILINE | re.DOTALL | re.VERBOSE | re.IGNORECASE)
+
+# Matches stuff that is translateable if it occurs in the right context
+# (between tags). This includes all characters and character entities.
+# Note that this also matches &nbsp; which needs to be handled as whitespace
+# before this regexp is applied.
+_CHARACTERS = lazy_re.compile(r'''
+ (
+ \w
+ |
+ [\!\@\#\$\%\^\*\(\)\-\=\_\+\[\]\{\}\\\|\;\:\'\"\,\.\/\?\`\~]
+ |
+ &(\#[0-9]+|\#x[0-9a-fA-F]+|[A-Za-z0-9]+);
+ )+
+ ''', re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+# Matches Total Recall's "replaceable" tags, which are just any text
+# in capitals enclosed by delimiters like [] or [~~] or [$~~$] (e.g. [HELLO],
+# [~HELLO~] and [$~HELLO~$]).
+_REPLACEABLE = lazy_re.compile(r'\[(\$?\~)?(?P<name>[A-Z0-9-_]+?)(\~\$?)?\]',
+ re.MULTILINE)
+
+
+# Matches the silly [!]-prefixed "header" that is used in some TotalRecall
+# templates.
+_SILLY_HEADER = lazy_re.compile(r'\[!\]\ntitle\t(?P<title>[^\n]+?)\n.+?\n\n',
+ re.MULTILINE | re.DOTALL)
+
+
+# Matches a comment that provides a description for the message it occurs in.
+_DESCRIPTION_COMMENT = lazy_re.compile(
+ r'<!--\s*desc\s*=\s*(?P<description>.+?)\s*-->', re.DOTALL)
+
+# Matches a comment which is used to break apart multiple messages.
+_MESSAGE_BREAK_COMMENT = lazy_re.compile(r'<!--\s*message-break\s*-->',
+ re.DOTALL)
+
+# Matches a comment which is used to prevent block tags from splitting a message
+_MESSAGE_NO_BREAK_COMMENT = re.compile(r'<!--\s*message-no-break\s*-->',
+ re.DOTALL)
+
+
+_DEBUG = 0
+def _DebugPrint(text):
+ if _DEBUG:
+ print text.encode('utf-8')
+
+
+class HtmlChunks(object):
+ '''A parser that knows how to break an HTML-like document into a list of
+ chunks, where each chunk is either translateable or non-translateable.
+ The chunks are unmodified sections of the original document, so concatenating
+ the text of all chunks would result in the original document.'''
+
+ def InTranslateable(self):
+ return self.last_translateable != -1
+
+ def Rest(self):
+ return self.text_[self.current:]
+
+ def StartTranslateable(self):
+ assert not self.InTranslateable()
+ if self.current != 0:
+ # Append a nontranslateable chunk
+ chunk_text = self.text_[self.chunk_start : self.last_nontranslateable + 1]
+ # Needed in the case where document starts with a translateable.
+ if len(chunk_text) > 0:
+ self.AddChunk(False, chunk_text)
+ self.chunk_start = self.last_nontranslateable + 1
+ self.last_translateable = self.current
+ self.last_nontranslateable = -1
+
+ def EndTranslateable(self):
+ assert self.InTranslateable()
+ # Append a translateable chunk
+ self.AddChunk(True,
+ self.text_[self.chunk_start : self.last_translateable + 1])
+ self.chunk_start = self.last_translateable + 1
+ self.last_translateable = -1
+ self.last_nontranslateable = self.current
+
+ def AdvancePast(self, match):
+ self.current += match.end()
+
+ def AddChunk(self, translateable, text):
+ '''Adds a chunk to self, removing linebreaks and duplicate whitespace
+ if appropriate.
+ '''
+ m = _DESCRIPTION_COMMENT.search(text)
+ if m:
+ self.last_description = m.group('description')
+ # Remove the description from the output text
+ text = _DESCRIPTION_COMMENT.sub('', text)
+
+ m = _MESSAGE_BREAK_COMMENT.search(text)
+ if m:
+ # Remove the coment from the output text. It should already effectively
+ # break apart messages.
+ text = _MESSAGE_BREAK_COMMENT.sub('', text)
+
+ if translateable and not self.last_element_ in _PREFORMATTED_TAGS:
+ if self.fold_whitespace_:
+ # Fold whitespace sequences if appropriate. This is optional because it
+ # alters the output strings.
+ text = _FOLD_WHITESPACE.sub(' ', text)
+ else:
+ text = text.replace('\n', ' ')
+ text = text.replace('\r', ' ')
+ # This whitespace folding doesn't work in all cases, thus the
+ # fold_whitespace flag to support backwards compatibility.
+ text = text.replace(' ', ' ')
+ text = text.replace(' ', ' ')
+
+ if translateable:
+ description = self.last_description
+ self.last_description = ''
+ else:
+ description = ''
+
+ if text != '':
+ self.chunks_.append((translateable, text, description))
+
+ def Parse(self, text, fold_whitespace):
+ '''Parses self.text_ into an intermediate format stored in self.chunks_
+ which is translateable and nontranslateable chunks. Also returns
+ self.chunks_
+
+ Args:
+ text: The HTML for parsing.
+ fold_whitespace: Whether whitespace sequences should be folded into a
+ single space.
+
+ Return:
+ [chunk1, chunk2, chunk3, ...] (instances of class Chunk)
+ '''
+ #
+ # Chunker state
+ #
+
+ self.text_ = text
+ self.fold_whitespace_ = fold_whitespace
+
+ # A list of tuples (is_translateable, text) which represents the document
+ # after chunking.
+ self.chunks_ = []
+
+ # Start index of the last chunk, whether translateable or not
+ self.chunk_start = 0
+
+ # Index of the last for-sure translateable character if we are parsing
+ # a translateable chunk, -1 to indicate we are not in a translateable chunk.
+ # This is needed so that we don't include trailing whitespace in the
+ # translateable chunk (whitespace is neutral).
+ self.last_translateable = -1
+
+ # Index of the last for-sure nontranslateable character if we are parsing
+ # a nontranslateable chunk, -1 if we are not in a nontranslateable chunk.
+ # This is needed to make sure we can group e.g. "<b>Hello</b> there"
+ # together instead of just "Hello</b> there" which would be much worse
+ # for translation.
+ self.last_nontranslateable = -1
+
+ # Index of the character we're currently looking at.
+ self.current = 0
+
+ # The name of the last block element parsed.
+ self.last_element_ = ''
+
+ # The last explicit description we found.
+ self.last_description = ''
+
+ # Whether no-break was the last chunk seen
+ self.last_nobreak = False
+
+ while self.current < len(self.text_):
+ _DebugPrint('REST: %s' % self.text_[self.current:self.current+60])
+
+ m = _MESSAGE_NO_BREAK_COMMENT.match(self.Rest())
+ if m:
+ self.AdvancePast(m)
+ self.last_nobreak = True
+ continue
+
+ # Try to match whitespace
+ m = _WHITESPACE.match(self.Rest())
+ if m:
+ # Whitespace is neutral, it just advances 'current' and does not switch
+ # between translateable/nontranslateable. If we are in a
+ # nontranslateable section that extends to the current point, we extend
+ # it to include the whitespace. If we are in a translateable section,
+ # we do not extend it until we find
+ # more translateable parts, because we never want a translateable chunk
+ # to end with whitespace.
+ if (not self.InTranslateable() and
+ self.last_nontranslateable == self.current - 1):
+ self.last_nontranslateable = self.current + m.end() - 1
+ self.AdvancePast(m)
+ continue
+
+ # Then we try to match nontranslateables
+ m = _NONTRANSLATEABLES.match(self.Rest())
+ if m:
+ if self.InTranslateable():
+ self.EndTranslateable()
+ self.last_nontranslateable = self.current + m.end() - 1
+ self.AdvancePast(m)
+ continue
+
+ # Now match all other HTML element tags (opening, closing, or empty, we
+ # don't care).
+ m = _ELEMENT.match(self.Rest())
+ if m:
+ element_name = m.group('element').lower()
+ if element_name in _BLOCK_TAGS:
+ self.last_element_ = element_name
+ if self.InTranslateable():
+ if self.last_nobreak:
+ self.last_nobreak = False
+ else:
+ self.EndTranslateable()
+
+ # Check for "special" elements, i.e. ones that have a translateable
+ # attribute, and handle them correctly. Note that all of the
+ # "special" elements are block tags, so no need to check for this
+ # if the tag is not a block tag.
+ sm = _SPECIAL_ELEMENT.match(self.Rest())
+ if sm:
+ # Get the appropriate group name
+ for group in sm.groupdict().keys():
+ if sm.groupdict()[group]:
+ break
+
+ # First make a nontranslateable chunk up to and including the
+ # quote before the translateable attribute value
+ self.AddChunk(False, self.text_[
+ self.chunk_start : self.current + sm.start(group)])
+ # Then a translateable for the translateable bit
+ self.AddChunk(True, self.Rest()[sm.start(group) : sm.end(group)])
+ # Finally correct the data invariant for the parser
+ self.chunk_start = self.current + sm.end(group)
+
+ self.last_nontranslateable = self.current + m.end() - 1
+ elif self.InTranslateable():
+ # We're in a translateable and the tag is an inline tag, so we
+ # need to include it in the translateable.
+ self.last_translateable = self.current + m.end() - 1
+ self.AdvancePast(m)
+ continue
+
+ # Anything else we find must be translateable, so we advance one character
+ # at a time until one of the above matches.
+ if not self.InTranslateable():
+ self.StartTranslateable()
+ else:
+ self.last_translateable = self.current
+ self.current += 1
+
+ # Close the final chunk
+ if self.InTranslateable():
+ self.AddChunk(True, self.text_[self.chunk_start : ])
+ else:
+ self.AddChunk(False, self.text_[self.chunk_start : ])
+
+ return self.chunks_
+
+
+def HtmlToMessage(html, include_block_tags=False, description=''):
+ '''Takes a bit of HTML, which must contain only "inline" HTML elements,
+ and changes it into a tclib.Message. This involves escaping any entities and
+ replacing any HTML code with placeholders.
+
+ If include_block_tags is true, no error will be given if block tags (e.g.
+ <p> or <br>) are included in the HTML.
+
+ Args:
+ html: 'Hello <b>[USERNAME]</b>, how&nbsp;<i>are</i> you?'
+ include_block_tags: False
+
+ Return:
+ tclib.Message('Hello START_BOLD1USERNAMEEND_BOLD, '
+ 'howNBSPSTART_ITALICareEND_ITALIC you?',
+ [ Placeholder('START_BOLD', '<b>', ''),
+ Placeholder('USERNAME', '[USERNAME]', ''),
+ Placeholder('END_BOLD', '</b>', ''),
+ Placeholder('START_ITALIC', '<i>', ''),
+ Placeholder('END_ITALIC', '</i>', ''), ])
+ '''
+ # Approach is:
+ # - first placeholderize, finding <elements>, [REPLACEABLES] and &nbsp;
+ # - then escape all character entities in text in-between placeholders
+
+ parts = [] # List of strings (for text chunks) and tuples (ID, original)
+ # for placeholders
+
+ count_names = {} # Map of base names to number of times used
+ end_names = {} # Map of base names to stack of end tags (for correct nesting)
+
+ def MakeNameClosure(base, type = ''):
+ '''Returns a closure that can be called once all names have been allocated
+ to return the final name of the placeholder. This allows us to minimally
+ number placeholders for non-overlap.
+
+ Also ensures that END_XXX_Y placeholders have the same Y as the
+ corresponding BEGIN_XXX_Y placeholder when we have nested tags of the same
+ type.
+
+ Args:
+ base: 'phname'
+ type: '' | 'begin' | 'end'
+
+ Return:
+ Closure()
+ '''
+ name = base.upper()
+ if type != '':
+ name = ('%s_%s' % (type, base)).upper()
+
+ if name in count_names.keys():
+ count_names[name] += 1
+ else:
+ count_names[name] = 1
+
+ def MakeFinalName(name_ = name, index = count_names[name] - 1):
+ if (type.lower() == 'end' and
+ base in end_names.keys() and len(end_names[base])):
+ return end_names[base].pop(-1) # For correct nesting
+ if count_names[name_] != 1:
+ name_ = '%s_%s' % (name_, _SUFFIXES[index])
+ # We need to use a stack to ensure that the end-tag suffixes match
+ # the begin-tag suffixes. Only needed when more than one tag of the
+ # same type.
+ if type == 'begin':
+ end_name = ('END_%s_%s' % (base, _SUFFIXES[index])).upper()
+ if base in end_names.keys():
+ end_names[base].append(end_name)
+ else:
+ end_names[base] = [end_name]
+
+ return name_
+
+ return MakeFinalName
+
+ current = 0
+ last_nobreak = False
+
+ while current < len(html):
+ m = _MESSAGE_NO_BREAK_COMMENT.match(html[current:])
+ if m:
+ last_nobreak = True
+ current += m.end()
+ continue
+
+ m = _NBSP.match(html[current:])
+ if m:
+ parts.append((MakeNameClosure('SPACE'), m.group()))
+ current += m.end()
+ continue
+
+ m = _REPLACEABLE.match(html[current:])
+ if m:
+ # Replaceables allow - but placeholders don't, so replace - with _
+ ph_name = MakeNameClosure('X_%s_X' % m.group('name').replace('-', '_'))
+ parts.append((ph_name, m.group()))
+ current += m.end()
+ continue
+
+ m = _SPECIAL_ELEMENT.match(html[current:])
+ if m:
+ if not include_block_tags:
+ if last_nobreak:
+ last_nobreak = False
+ else:
+ raise exception.BlockTagInTranslateableChunk(html)
+ element_name = 'block' # for simplification
+ # Get the appropriate group name
+ for group in m.groupdict().keys():
+ if m.groupdict()[group]:
+ break
+ parts.append((MakeNameClosure(element_name, 'begin'),
+ html[current : current + m.start(group)]))
+ parts.append(m.group(group))
+ parts.append((MakeNameClosure(element_name, 'end'),
+ html[current + m.end(group) : current + m.end()]))
+ current += m.end()
+ continue
+
+ m = _ELEMENT.match(html[current:])
+ if m:
+ element_name = m.group('element').lower()
+ if not include_block_tags and not element_name in _INLINE_TAGS:
+ if last_nobreak:
+ last_nobreak = False
+ else:
+ raise exception.BlockTagInTranslateableChunk(html[current:])
+ if element_name in _HTML_PLACEHOLDER_NAMES: # use meaningful names
+ element_name = _HTML_PLACEHOLDER_NAMES[element_name]
+
+ # Make a name for the placeholder
+ type = ''
+ if not m.group('empty'):
+ if m.group('closing'):
+ type = 'end'
+ else:
+ type = 'begin'
+ parts.append((MakeNameClosure(element_name, type), m.group()))
+ current += m.end()
+ continue
+
+ if len(parts) and isinstance(parts[-1], types.StringTypes):
+ parts[-1] += html[current]
+ else:
+ parts.append(html[current])
+ current += 1
+
+ msg_text = ''
+ placeholders = []
+ for part in parts:
+ if isinstance(part, types.TupleType):
+ final_name = part[0]()
+ original = part[1]
+ msg_text += final_name
+ placeholders.append(tclib.Placeholder(final_name, original, '(HTML code)'))
+ else:
+ msg_text += part
+
+ msg = tclib.Message(text=msg_text, placeholders=placeholders,
+ description=description)
+ content = msg.GetContent()
+ for ix in range(len(content)):
+ if isinstance(content[ix], types.StringTypes):
+ content[ix] = util.UnescapeHtml(content[ix], replace_nbsp=False)
+
+ return msg
+
+
+class TrHtml(interface.GathererBase):
+ '''Represents a document or message in the template format used by
+ Total Recall for HTML documents.'''
+
+ def __init__(self, *args, **kwargs):
+ super(TrHtml, self).__init__(*args, **kwargs)
+ self.have_parsed_ = False
+ self.skeleton_ = [] # list of strings and MessageClique objects
+ self.fold_whitespace_ = False
+
+ def SetAttributes(self, attrs):
+ '''Sets node attributes used by the gatherer.
+
+ This checks the fold_whitespace attribute.
+
+ Args:
+ attrs: The mapping of node attributes.
+ '''
+ self.fold_whitespace_ = ('fold_whitespace' in attrs and
+ attrs['fold_whitespace'] == 'true')
+
+ def GetText(self):
+ '''Returns the original text of the HTML document'''
+ return self.text_
+
+ def GetTextualIds(self):
+ return [self.extkey]
+
+ def GetCliques(self):
+ '''Returns the message cliques for each translateable message in the
+ document.'''
+ return [x for x in self.skeleton_ if isinstance(x, clique.MessageClique)]
+
+ def Translate(self, lang, pseudo_if_not_available=True,
+ skeleton_gatherer=None, fallback_to_english=False):
+ '''Returns this document with translateable messages filled with
+ the translation for language 'lang'.
+
+ Args:
+ lang: 'en'
+ pseudo_if_not_available: True
+
+ Return:
+ 'ID_THIS_SECTION TYPE\n...BEGIN\n "Translated message"\n......\nEND
+
+ Raises:
+ grit.exception.NotReady() if used before Parse() has been successfully
+ called.
+ grit.exception.NoSuchTranslation() if 'pseudo_if_not_available' is false
+ and there is no translation for the requested language.
+ '''
+ if len(self.skeleton_) == 0:
+ raise exception.NotReady()
+
+ # TODO(joi) Implement support for skeleton gatherers here.
+
+ out = []
+ for item in self.skeleton_:
+ if isinstance(item, types.StringTypes):
+ out.append(item)
+ else:
+ msg = item.MessageForLanguage(lang,
+ pseudo_if_not_available,
+ fallback_to_english)
+ for content in msg.GetContent():
+ if isinstance(content, tclib.Placeholder):
+ out.append(content.GetOriginal())
+ else:
+ # We escape " characters to increase the chance that attributes
+ # will be properly escaped.
+ out.append(util.EscapeHtml(content, True))
+
+ return ''.join(out)
+
+ def Parse(self):
+ if self.have_parsed_:
+ return
+ self.have_parsed_ = True
+
+ text = self._LoadInputFile()
+
+ # Ignore the BOM character if the document starts with one.
+ if text.startswith(u'\ufeff'):
+ text = text[1:]
+
+ self.text_ = text
+
+ # Parsing is done in two phases: First, we break the document into
+ # translateable and nontranslateable chunks. Second, we run through each
+ # translateable chunk and insert placeholders for any HTML elements,
+ # unescape escaped characters, etc.
+
+ # First handle the silly little [!]-prefixed header because it's not
+ # handled by our HTML parsers.
+ m = _SILLY_HEADER.match(text)
+ if m:
+ self.skeleton_.append(text[:m.start('title')])
+ self.skeleton_.append(self.uberclique.MakeClique(
+ tclib.Message(text=text[m.start('title'):m.end('title')])))
+ self.skeleton_.append(text[m.end('title') : m.end()])
+ text = text[m.end():]
+
+ chunks = HtmlChunks().Parse(text, self.fold_whitespace_)
+
+ for chunk in chunks:
+ if chunk[0]: # Chunk is translateable
+ self.skeleton_.append(self.uberclique.MakeClique(
+ HtmlToMessage(chunk[1], description=chunk[2])))
+ else:
+ self.skeleton_.append(chunk[1])
+
+ # Go through the skeleton and change any messages that consist solely of
+ # placeholders and whitespace into nontranslateable strings.
+ for ix in range(len(self.skeleton_)):
+ got_text = False
+ if isinstance(self.skeleton_[ix], clique.MessageClique):
+ msg = self.skeleton_[ix].GetMessage()
+ for item in msg.GetContent():
+ if (isinstance(item, types.StringTypes) and _NON_WHITESPACE.search(item)
+ and item != '&nbsp;'):
+ got_text = True
+ break
+ if not got_text:
+ self.skeleton_[ix] = msg.GetRealContent()
+
+ def SubstituteMessages(self, substituter):
+ '''Applies substitutions to all messages in the tree.
+
+ Goes through the skeleton and finds all MessageCliques.
+
+ Args:
+ substituter: a grit.util.Substituter object.
+ '''
+ new_skel = []
+ for chunk in self.skeleton_:
+ if isinstance(chunk, clique.MessageClique):
+ old_message = chunk.GetMessage()
+ new_message = substituter.SubstituteMessage(old_message)
+ if new_message is not old_message:
+ new_skel.append(self.uberclique.MakeClique(new_message))
+ continue
+ new_skel.append(chunk)
+ self.skeleton_ = new_skel
+
diff --git a/chromium/tools/grit/grit/gather/tr_html_unittest.py b/chromium/tools/grit/grit/gather/tr_html_unittest.py
new file mode 100644
index 00000000000..3400ad6f014
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/tr_html_unittest.py
@@ -0,0 +1,522 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.gather.tr_html'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import types
+import unittest
+import StringIO
+
+from grit.gather import tr_html
+from grit import clique
+from grit import util
+
+
+class ParserUnittest(unittest.TestCase):
+ def testChunkingWithoutFoldWhitespace(self):
+ self.VerifyChunking(False)
+
+ def testChunkingWithFoldWhitespace(self):
+ self.VerifyChunking(True)
+
+ def VerifyChunking(self, fold_whitespace):
+ """Use a single function to run all chunking testing.
+
+ This makes it easier to run chunking with fold_whitespace both on and off,
+ to make sure the outputs are the same.
+
+ Args:
+ fold_whitespace: Whether whitespace sequences should be folded into a
+ single space.
+ """
+ self.VerifyChunkingBasic(fold_whitespace)
+ self.VerifyChunkingDescriptions(fold_whitespace)
+ self.VerifyChunkingReplaceables(fold_whitespace)
+ self.VerifyChunkingLineBreaks(fold_whitespace)
+ self.VerifyChunkingMessageBreak(fold_whitespace)
+ self.VerifyChunkingMessageNoBreak(fold_whitespace)
+
+ def VerifyChunkingBasic(self, fold_whitespace):
+ p = tr_html.HtmlChunks()
+ chunks = p.Parse('<p>Hello <b>dear</b> how <i>are</i>you?<p>Fine!',
+ fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (False, '<p>', ''), (True, 'Hello <b>dear</b> how <i>are</i>you?', ''),
+ (False, '<p>', ''), (True, 'Fine!', '')])
+
+ chunks = p.Parse('<p> Hello <b>dear</b> how <i>are</i>you? <p>Fine!',
+ fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (False, '<p> ', ''), (True, 'Hello <b>dear</b> how <i>are</i>you?', ''),
+ (False, ' <p>', ''), (True, 'Fine!', '')])
+
+ chunks = p.Parse('<p> Hello <b>dear how <i>are you? <p> Fine!',
+ fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (False, '<p> ', ''), (True, 'Hello <b>dear how <i>are you?', ''),
+ (False, ' <p> ', ''), (True, 'Fine!', '')])
+
+ # Ensure translateable sections that start with inline tags contain
+ # the starting inline tag.
+ chunks = p.Parse('<b>Hello!</b> how are you?<p><i>I am fine.</i>',
+ fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (True, '<b>Hello!</b> how are you?', ''), (False, '<p>', ''),
+ (True, '<i>I am fine.</i>', '')])
+
+ # Ensure translateable sections that end with inline tags contain
+ # the ending inline tag.
+ chunks = p.Parse("Hello! How are <b>you?</b><p><i>I'm fine!</i>",
+ fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (True, 'Hello! How are <b>you?</b>', ''), (False, '<p>', ''),
+ (True, "<i>I'm fine!</i>", '')])
+
+ def VerifyChunkingDescriptions(self, fold_whitespace):
+ p = tr_html.HtmlChunks()
+ # Check capitals and explicit descriptions
+ chunks = p.Parse('<!-- desc=bingo! --><B>Hello!</B> how are you?<P>'
+ '<I>I am fine.</I>', fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (True, '<B>Hello!</B> how are you?', 'bingo!'), (False, '<P>', ''),
+ (True, '<I>I am fine.</I>', '')])
+ chunks = p.Parse('<B><!-- desc=bingo! -->Hello!</B> how are you?<P>'
+ '<I>I am fine.</I>', fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (True, '<B>Hello!</B> how are you?', 'bingo!'), (False, '<P>', ''),
+ (True, '<I>I am fine.</I>', '')])
+ # Linebreaks get handled by the tclib message.
+ chunks = p.Parse('<B>Hello!</B> <!-- desc=bi\nngo\n! -->how are you?<P>'
+ '<I>I am fine.</I>', fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (True, '<B>Hello!</B> how are you?', 'bi\nngo\n!'), (False, '<P>', ''),
+ (True, '<I>I am fine.</I>', '')])
+
+ # In this case, because the explicit description appears after the first
+ # translateable, it will actually apply to the second translateable.
+ chunks = p.Parse('<B>Hello!</B> how are you?<!-- desc=bingo! --><P>'
+ '<I>I am fine.</I>', fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (True, '<B>Hello!</B> how are you?', ''), (False, '<P>', ''),
+ (True, '<I>I am fine.</I>', 'bingo!')])
+
+ def VerifyChunkingReplaceables(self, fold_whitespace):
+ # Check that replaceables within block tags (where attributes would go) are
+ # handled correctly.
+ p = tr_html.HtmlChunks()
+ chunks = p.Parse('<b>Hello!</b> how are you?<p [BINGO] [$~BONGO~$]>'
+ '<i>I am fine.</i>', fold_whitespace)
+ self.failUnlessEqual(chunks, [
+ (True, '<b>Hello!</b> how are you?', ''),
+ (False, '<p [BINGO] [$~BONGO~$]>', ''),
+ (True, '<i>I am fine.</i>', '')])
+
+ def VerifyChunkingLineBreaks(self, fold_whitespace):
+ # Check that the contents of preformatted tags preserve line breaks.
+ p = tr_html.HtmlChunks()
+ chunks = p.Parse('<textarea>Hello\nthere\nhow\nare\nyou?</textarea>',
+ fold_whitespace)
+ self.failUnlessEqual(chunks, [(False, '<textarea>', ''),
+ (True, 'Hello\nthere\nhow\nare\nyou?', ''), (False, '</textarea>', '')])
+
+ # ...and that other tags' line breaks are converted to spaces
+ chunks = p.Parse('<p>Hello\nthere\nhow\nare\nyou?</p>', fold_whitespace)
+ self.failUnlessEqual(chunks, [(False, '<p>', ''),
+ (True, 'Hello there how are you?', ''), (False, '</p>', '')])
+
+ def VerifyChunkingMessageBreak(self, fold_whitespace):
+ p = tr_html.HtmlChunks()
+ # Make sure that message-break comments work properly.
+ chunks = p.Parse('Break<!-- message-break --> apart '
+ '<!--message-break-->messages', fold_whitespace)
+ self.failUnlessEqual(chunks, [(True, 'Break', ''),
+ (False, ' ', ''),
+ (True, 'apart', ''),
+ (False, ' ', ''),
+ (True, 'messages', '')])
+
+ # Make sure message-break comments work in an inline tag.
+ chunks = p.Parse('<a href=\'google.com\'><!-- message-break -->Google'
+ '<!--message-break--></a>', fold_whitespace)
+ self.failUnlessEqual(chunks, [(False, '<a href=\'google.com\'>', ''),
+ (True, 'Google', ''),
+ (False, '</a>', '')])
+
+ def VerifyChunkingMessageNoBreak(self, fold_whitespace):
+ p = tr_html.HtmlChunks()
+ # Make sure that message-no-break comments work properly.
+ chunks = p.Parse('Please <!-- message-no-break --> <br />don\'t break',
+ fold_whitespace)
+ self.failUnlessEqual(chunks, [(True, 'Please <!-- message-no-break --> '
+ '<br />don\'t break', '')])
+
+ chunks = p.Parse('Please <br /> break. <!-- message-no-break --> <br /> '
+ 'But not this time.', fold_whitespace)
+ self.failUnlessEqual(chunks, [(True, 'Please', ''),
+ (False, ' <br /> ', ''),
+ (True, 'break. <!-- message-no-break --> '
+ '<br /> But not this time.', '')])
+
+ def testTranslateableAttributes(self):
+ p = tr_html.HtmlChunks()
+
+ # Check that the translateable attributes in <img>, <submit>, <button> and
+ # <text> elements buttons are handled correctly.
+ chunks = p.Parse('<img src=bingo.jpg alt="hello there">'
+ '<input type=submit value="hello">'
+ '<input type="button" value="hello">'
+ '<input type=\'text\' value=\'Howdie\'>', False)
+ self.failUnlessEqual(chunks, [
+ (False, '<img src=bingo.jpg alt="', ''), (True, 'hello there', ''),
+ (False, '"><input type=submit value="', ''), (True, 'hello', ''),
+ (False, '"><input type="button" value="', ''), (True, 'hello', ''),
+ (False, '"><input type=\'text\' value=\'', ''), (True, 'Howdie', ''),
+ (False, '\'>', '')])
+
+
+ def testTranslateableHtmlToMessage(self):
+ msg = tr_html.HtmlToMessage(
+ 'Hello <b>[USERNAME]</b>, &lt;how&gt;&nbsp;<i>are</i> you?')
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres ==
+ 'Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, '
+ '<how>&nbsp;BEGIN_ITALICareEND_ITALIC you?')
+
+ msg = tr_html.HtmlToMessage('<b>Hello</b><I>Hello</I><b>Hello</b>')
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres ==
+ 'BEGIN_BOLD_1HelloEND_BOLD_1BEGIN_ITALICHelloEND_ITALIC'
+ 'BEGIN_BOLD_2HelloEND_BOLD_2')
+
+ # Check that nesting (of the <font> tags) is handled correctly - i.e. that
+ # the closing placeholder numbers match the opening placeholders.
+ msg = tr_html.HtmlToMessage(
+ '''<font size=-1><font color=#FF0000>Update!</font> '''
+ '''<a href='http://desktop.google.com/whatsnew.html?hl=[$~LANG~$]'>'''
+ '''New Features</a>: Now search PDFs, MP3s, Firefox web history, and '''
+ '''more</font>''')
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres ==
+ 'BEGIN_FONT_1BEGIN_FONT_2Update!END_FONT_2 BEGIN_LINK'
+ 'New FeaturesEND_LINK: Now search PDFs, MP3s, Firefox '
+ 'web history, and moreEND_FONT_1')
+
+ msg = tr_html.HtmlToMessage('''<a href='[$~URL~$]'><b>[NUM][CAT]</b></a>''')
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres == 'BEGIN_LINKBEGIN_BOLDX_NUM_XX_CAT_XEND_BOLDEND_LINK')
+
+ msg = tr_html.HtmlToMessage(
+ '''<font size=-1><a class=q onClick='return window.qs?qs(this):1' '''
+ '''href='http://[WEBSERVER][SEARCH_URI]'>Desktop</a></font>&nbsp;&nbsp;'''
+ '''&nbsp;&nbsp;''')
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres ==
+ '''BEGIN_FONTBEGIN_LINKDesktopEND_LINKEND_FONTSPACE''')
+
+ msg = tr_html.HtmlToMessage(
+ '''<br><br><center><font size=-2>&copy;2005 Google </font></center>''', 1)
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres ==
+ u'BEGIN_BREAK_1BEGIN_BREAK_2BEGIN_CENTERBEGIN_FONT\xa92005'
+ u' Google END_FONTEND_CENTER')
+
+ msg = tr_html.HtmlToMessage(
+ '''&nbsp;-&nbsp;<a class=c href=[$~CACHE~$]>Cached</a>''')
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres ==
+ '&nbsp;-&nbsp;BEGIN_LINKCachedEND_LINK')
+
+ # Check that upper-case tags are handled correctly.
+ msg = tr_html.HtmlToMessage(
+ '''You can read the <A HREF='http://desktop.google.com/privacypolicy.'''
+ '''html?hl=[LANG_CODE]'>Privacy Policy</A> and <A HREF='http://desktop'''
+ '''.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.''')
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres ==
+ 'You can read the BEGIN_LINK_1Privacy PolicyEND_LINK_1 and '
+ 'BEGIN_LINK_2Privacy FAQEND_LINK_2 online.')
+
+ # Check that tags with linebreaks immediately preceding them are handled
+ # correctly.
+ msg = tr_html.HtmlToMessage(
+ '''You can read the
+<A HREF='http://desktop.google.com/privacypolicy.html?hl=[LANG_CODE]'>Privacy Policy</A>
+and <A HREF='http://desktop.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.''')
+ pres = msg.GetPresentableContent()
+ self.failUnless(pres == '''You can read the
+BEGIN_LINK_1Privacy PolicyEND_LINK_1
+and BEGIN_LINK_2Privacy FAQEND_LINK_2 online.''')
+
+ # Check that message-no-break comments are handled correctly.
+ msg = tr_html.HtmlToMessage('''Please <!-- message-no-break --><br /> don't break''')
+ pres = msg.GetPresentableContent()
+ self.failUnlessEqual(pres, '''Please BREAK don't break''')
+
+class TrHtmlUnittest(unittest.TestCase):
+ def testSetAttributes(self):
+ html = tr_html.TrHtml(StringIO.StringIO(''))
+ self.failUnlessEqual(html.fold_whitespace_, False)
+ html.SetAttributes({})
+ self.failUnlessEqual(html.fold_whitespace_, False)
+ html.SetAttributes({'fold_whitespace': 'false'})
+ self.failUnlessEqual(html.fold_whitespace_, False)
+ html.SetAttributes({'fold_whitespace': 'true'})
+ self.failUnlessEqual(html.fold_whitespace_, True)
+
+ def testFoldWhitespace(self):
+ text = '<td> Test Message </td>'
+
+ html = tr_html.TrHtml(StringIO.StringIO(text))
+ html.Parse()
+ self.failUnlessEqual(html.skeleton_[1].GetMessage().GetPresentableContent(),
+ 'Test Message')
+
+ html = tr_html.TrHtml(StringIO.StringIO(text))
+ html.fold_whitespace_ = True
+ html.Parse()
+ self.failUnlessEqual(html.skeleton_[1].GetMessage().GetPresentableContent(),
+ 'Test Message')
+
+ def testTable(self):
+ html = tr_html.TrHtml(StringIO.StringIO('''<table class="shaded-header"><tr>
+<td class="header-element b expand">Preferences</td>
+<td class="header-element s">
+<a href="http://desktop.google.com/preferences.html">Preferences&nbsp;Help</a>
+</td>
+</tr></table>'''))
+ html.Parse()
+ self.failUnless(html.skeleton_[3].GetMessage().GetPresentableContent() ==
+ 'BEGIN_LINKPreferences&nbsp;HelpEND_LINK')
+
+ def testSubmitAttribute(self):
+ html = tr_html.TrHtml(StringIO.StringIO('''</td>
+<td class="header-element"><input type=submit value="Save Preferences"
+name=submit2></td>
+</tr></table>'''))
+ html.Parse()
+ self.failUnless(html.skeleton_[1].GetMessage().GetPresentableContent() ==
+ 'Save Preferences')
+
+ def testWhitespaceAfterInlineTag(self):
+ '''Test that even if there is whitespace after an inline tag at the start
+ of a translateable section the inline tag will be included.
+ '''
+ html = tr_html.TrHtml(
+ StringIO.StringIO('''<label for=DISPLAYNONE><font size=-1> Hello</font>'''))
+ html.Parse()
+ self.failUnless(html.skeleton_[1].GetMessage().GetRealContent() ==
+ '<font size=-1> Hello</font>')
+
+ def testSillyHeader(self):
+ html = tr_html.TrHtml(StringIO.StringIO('''[!]
+title\tHello
+bingo
+bongo
+bla
+
+<p>Other stuff</p>'''))
+ html.Parse()
+ content = html.skeleton_[1].GetMessage().GetRealContent()
+ self.failUnless(content == 'Hello')
+ self.failUnless(html.skeleton_[-1] == '</p>')
+ # Right after the translateable the nontranslateable should start with
+ # a linebreak (this catches a bug we had).
+ self.failUnless(html.skeleton_[2][0] == '\n')
+
+
+ def testExplicitDescriptions(self):
+ html = tr_html.TrHtml(
+ StringIO.StringIO('Hello [USER]<br/><!-- desc=explicit -->'
+ '<input type="button">Go!</input>'))
+ html.Parse()
+ msg = html.GetCliques()[1].GetMessage()
+ self.failUnlessEqual(msg.GetDescription(), 'explicit')
+ self.failUnlessEqual(msg.GetRealContent(), 'Go!')
+
+ html = tr_html.TrHtml(
+ StringIO.StringIO('Hello [USER]<br/><!-- desc=explicit\nmultiline -->'
+ '<input type="button">Go!</input>'))
+ html.Parse()
+ msg = html.GetCliques()[1].GetMessage()
+ self.failUnlessEqual(msg.GetDescription(), 'explicit multiline')
+ self.failUnlessEqual(msg.GetRealContent(), 'Go!')
+
+
+ def testRegressionInToolbarAbout(self):
+ html = tr_html.TrHtml(util.PathFromRoot(r'grit/testdata/toolbar_about.html'))
+ html.Parse()
+ cliques = html.GetCliques()
+ for cl in cliques:
+ content = cl.GetMessage().GetRealContent()
+ if content.count('De parvis grandis acervus erit'):
+ self.failIf(content.count('$/translate'))
+
+
+ def HtmlFromFileWithManualCheck(self, f):
+ html = tr_html.TrHtml(f)
+ html.Parse()
+
+ # For manual results inspection only...
+ list = []
+ for item in html.skeleton_:
+ if isinstance(item, types.StringTypes):
+ list.append(item)
+ else:
+ list.append(item.GetMessage().GetPresentableContent())
+
+ return html
+
+
+ def testPrivacyHtml(self):
+ html = self.HtmlFromFileWithManualCheck(
+ util.PathFromRoot(r'grit/testdata/privacy.html'))
+
+ self.failUnless(html.skeleton_[1].GetMessage().GetRealContent() ==
+ 'Privacy and Google Desktop Search')
+ self.failUnless(html.skeleton_[3].startswith('<'))
+ self.failUnless(len(html.skeleton_) > 10)
+
+
+ def testPreferencesHtml(self):
+ html = self.HtmlFromFileWithManualCheck(
+ util.PathFromRoot(r'grit/testdata/preferences.html'))
+
+ # Verify that we don't get '[STATUS-MESSAGE]' as the original content of
+ # one of the MessageClique objects (it would be a placeholder-only message
+ # and we're supposed to have stripped those).
+
+ for item in [x for x in html.skeleton_
+ if isinstance(x, clique.MessageClique)]:
+ if (item.GetMessage().GetRealContent() == '[STATUS-MESSAGE]' or
+ item.GetMessage().GetRealContent() == '[ADDIN-DO] [ADDIN-OPTIONS]'):
+ self.fail()
+
+ self.failUnless(len(html.skeleton_) > 100)
+
+ def AssertNumberOfTranslateables(self, files, num):
+ '''Fails if any of the files in files don't have exactly
+ num translateable sections.
+
+ Args:
+ files: ['file1', 'file2']
+ num: 3
+ '''
+ for f in files:
+ f = util.PathFromRoot(r'grit/testdata/%s' % f)
+ html = self.HtmlFromFileWithManualCheck(f)
+ self.failUnless(len(html.GetCliques()) == num)
+
+ def testFewTranslateables(self):
+ self.AssertNumberOfTranslateables(['browser.html', 'email_thread.html',
+ 'header.html', 'mini.html',
+ 'oneclick.html', 'script.html',
+ 'time_related.html', 'versions.html'], 0)
+ self.AssertNumberOfTranslateables(['footer.html', 'hover.html'], 1)
+
+ def testOtherHtmlFilesForManualInspection(self):
+ files = [
+ 'about.html', 'bad_browser.html', 'cache_prefix.html',
+ 'cache_prefix_file.html', 'chat_result.html', 'del_footer.html',
+ 'del_header.html', 'deleted.html', 'details.html', 'email_result.html',
+ 'error.html', 'explicit_web.html', 'footer.html',
+ 'homepage.html', 'indexing_speed.html',
+ 'install_prefs.html', 'install_prefs2.html',
+ 'oem_enable.html', 'oem_non_admin.html', 'onebox.html',
+ 'password.html', 'quit_apps.html', 'recrawl.html',
+ 'searchbox.html', 'sidebar_h.html', 'sidebar_v.html', 'status.html',
+ ]
+ for f in files:
+ self.HtmlFromFileWithManualCheck(
+ util.PathFromRoot(r'grit/testdata/%s' % f))
+
+ def testTranslate(self):
+ # Note that the English translation of documents that use character
+ # literals (e.g. &copy;) will not be the same as the original document
+ # because the character literal will be transformed into the Unicode
+ # character itself. So for this test we choose some relatively complex
+ # HTML without character entities (but with &nbsp; because that's handled
+ # specially).
+ html = tr_html.TrHtml(StringIO.StringIO(''' <script>
+ <!--
+ function checkOffice() { var w = document.getElementById("h7");
+ var e = document.getElementById("h8"); var o = document.getElementById("h10");
+ if (!(w.checked || e.checked)) { o.checked=0;o.disabled=1;} else {o.disabled=0;} }
+ // -->
+ </script>
+ <input type=checkbox [CHECK-DOC] name=DOC id=h7 onclick='checkOffice()'>
+ <label for=h7> Word</label><br>
+ <input type=checkbox [CHECK-XLS] name=XLS id=h8 onclick='checkOffice()'>
+ <label for=h8> Excel</label><br>
+ <input type=checkbox [CHECK-PPT] name=PPT id=h9>
+ <label for=h9> PowerPoint</label><br>
+ </span></td><td nowrap valign=top><span class="s">
+ <input type=checkbox [CHECK-PDF] name=PDF id=hpdf>
+ <label for=hpdf> PDF</label><br>
+ <input type=checkbox [CHECK-TXT] name=TXT id=h6>
+ <label for=h6> Text, media, and other files</label><br>
+ </tr>&nbsp;&nbsp;
+ <tr><td nowrap valign=top colspan=3><span class="s"><br />
+ <input type=checkbox [CHECK-SECUREOFFICE] name=SECUREOFFICE id=h10>
+ <label for=h10> Password-protected Office documents (Word, Excel)</label><br />
+ <input type=checkbox [DISABLED-HTTPS] [CHECK-HTTPS] name=HTTPS id=h12><label
+ for=h12> Secure pages (HTTPS) in web history</label></span></td></tr>
+ </table>'''))
+ html.Parse()
+ trans = html.Translate('en')
+ if (html.GetText() != trans):
+ self.fail()
+
+
+ def testHtmlToMessageWithBlockTags(self):
+ msg = tr_html.HtmlToMessage(
+ 'Hello<p>Howdie<img alt="bingo" src="image.gif">', True)
+ result = msg.GetPresentableContent()
+ self.failUnless(
+ result == 'HelloBEGIN_PARAGRAPHHowdieBEGIN_BLOCKbingoEND_BLOCK')
+
+ msg = tr_html.HtmlToMessage(
+ 'Hello<p>Howdie<input type="button" value="bingo">', True)
+ result = msg.GetPresentableContent()
+ self.failUnless(
+ result == 'HelloBEGIN_PARAGRAPHHowdieBEGIN_BLOCKbingoEND_BLOCK')
+
+
+ def testHtmlToMessageRegressions(self):
+ msg = tr_html.HtmlToMessage(' - ', True)
+ result = msg.GetPresentableContent()
+ self.failUnless(result == ' - ')
+
+
+ def testEscapeUnescaped(self):
+ text = '&copy;&nbsp; & &quot;&lt;hello&gt;&quot;'
+ unescaped = util.UnescapeHtml(text)
+ self.failUnless(unescaped == u'\u00a9\u00a0 & "<hello>"')
+ escaped_unescaped = util.EscapeHtml(unescaped, True)
+ self.failUnless(escaped_unescaped ==
+ u'\u00a9\u00a0 &amp; &quot;&lt;hello&gt;&quot;')
+
+ def testRegressionCjkHtmlFile(self):
+ # TODO(joi) Fix this problem where unquoted attributes that
+ # have a value that is CJK characters causes the regular expression
+ # match never to return. (culprit is the _ELEMENT regexp(
+ if False:
+ html = self.HtmlFromFileWithManualCheck(util.PathFromRoot(
+ r'grit/testdata/ko_oem_enable_bug.html'))
+ self.failUnless(True)
+
+ def testRegressionCpuHang(self):
+ # If this regression occurs, the unit test will never return
+ html = tr_html.TrHtml(StringIO.StringIO(
+ '''<input type=text size=12 id=advFileTypeEntry [~SHOW-FILETYPE-BOX~] value="[EXT]" name=ext>'''))
+ html.Parse()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/gather/txt.py b/chromium/tools/grit/grit/gather/txt.py
new file mode 100644
index 00000000000..e8c20de8352
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/txt.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Supports making amessage from a text file.
+'''
+
+from grit.gather import interface
+from grit import tclib
+
+
+class TxtFile(interface.GathererBase):
+ '''A text file gatherer. Very simple, all text from the file becomes a
+ single clique.
+ '''
+
+ def Parse(self):
+ self.text_ = self._LoadInputFile()
+ self.clique_ = self.uberclique.MakeClique(tclib.Message(text=self.text_))
+
+ def GetText(self):
+ '''Returns the text of what is being gathered.'''
+ return self.text_
+
+ def GetTextualIds(self):
+ return [self.extkey]
+
+ def GetCliques(self):
+ '''Returns the MessageClique objects for all translateable portions.'''
+ return [self.clique_]
+
+ def Translate(self, lang, pseudo_if_not_available=True,
+ skeleton_gatherer=None, fallback_to_english=False):
+ return self.clique_.MessageForLanguage(lang,
+ pseudo_if_not_available,
+ fallback_to_english).GetRealContent()
diff --git a/chromium/tools/grit/grit/gather/txt_unittest.py b/chromium/tools/grit/grit/gather/txt_unittest.py
new file mode 100644
index 00000000000..e2ff8a5de30
--- /dev/null
+++ b/chromium/tools/grit/grit/gather/txt_unittest.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for TxtFile gatherer'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+
+import StringIO
+import unittest
+
+from grit.gather import txt
+
+
+class TxtUnittest(unittest.TestCase):
+ def testGather(self):
+ input = StringIO.StringIO('Hello there\nHow are you?')
+ gatherer = txt.TxtFile(input)
+ gatherer.Parse()
+ self.failUnless(gatherer.GetText() == input.getvalue())
+ self.failUnless(len(gatherer.GetCliques()) == 1)
+ self.failUnless(gatherer.GetCliques()[0].GetMessage().GetRealContent() ==
+ input.getvalue())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/grd_reader.py b/chromium/tools/grit/grit/grd_reader.py
new file mode 100644
index 00000000000..055ad73852e
--- /dev/null
+++ b/chromium/tools/grit/grit/grd_reader.py
@@ -0,0 +1,217 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Class for reading GRD files into memory, without processing them.
+'''
+
+import os.path
+import types
+import xml.sax
+import xml.sax.handler
+
+from grit import exception
+from grit import util
+from grit.node import base
+from grit.node import mapping
+from grit.node import misc
+
+
+class StopParsingException(Exception):
+ '''An exception used to stop parsing.'''
+ pass
+
+
+class GrdContentHandler(xml.sax.handler.ContentHandler):
+ def __init__(self, stop_after, debug, dir, defines, tags_to_ignore):
+ # Invariant of data:
+ # 'root' is the root of the parse tree being created, or None if we haven't
+ # parsed out any elements.
+ # 'stack' is the a stack of elements that we push new nodes onto and
+ # pop from when they finish parsing, or [] if we are not currently parsing.
+ # 'stack[-1]' is the top of the stack.
+ self.root = None
+ self.stack = []
+ self.stop_after = stop_after
+ self.debug = debug
+ self.dir = dir
+ self.defines = defines
+ self.tags_to_ignore = tags_to_ignore or set()
+ self.ignore_depth = 0
+
+ def startElement(self, name, attrs):
+ if self.ignore_depth or name in self.tags_to_ignore:
+ if self.debug and self.ignore_depth == 0:
+ print "Ignoring element %s and its children" % name
+ self.ignore_depth += 1
+ return
+
+ if self.debug:
+ attr_list = ' '.join('%s="%s"' % kv for kv in attrs.items())
+ print ("Starting parsing of element %s with attributes %r" %
+ (name, attr_list or '(none)'))
+
+ typeattr = attrs.get('type')
+ node = mapping.ElementToClass(name, typeattr)()
+
+ if self.stack:
+ self.stack[-1].AddChild(node)
+ node.StartParsing(name, self.stack[-1])
+ else:
+ assert self.root is None
+ self.root = node
+ node.StartParsing(name, None)
+ if self.defines:
+ node.SetDefines(self.defines)
+ self.stack.append(node)
+
+ for attr, attrval in attrs.items():
+ node.HandleAttribute(attr, attrval)
+
+ def endElement(self, name):
+ if self.ignore_depth:
+ self.ignore_depth -= 1
+ return
+
+ if name == 'part':
+ partnode = self.stack[-1]
+ partnode.started_inclusion = True
+ # Add the contents of the sub-grd file as children of the <part> node.
+ partname = partnode.GetInputPath()
+ if os.path.dirname(partname):
+ # TODO(benrg): Remove this limitation. (The problem is that GRIT
+ # assumes that files referenced from the GRD file are relative to
+ # a path stored in the root <grit> node.)
+ raise exception.GotPathExpectedFilenameOnly()
+ partname = os.path.join(self.dir, partname)
+ # Exceptions propagate to the handler in grd_reader.Parse().
+ xml.sax.parse(partname, GrdPartContentHandler(self))
+
+ if self.debug:
+ print "End parsing of element %s" % name
+ self.stack.pop().EndParsing()
+
+ if name == self.stop_after:
+ raise StopParsingException()
+
+ def characters(self, content):
+ if self.ignore_depth == 0:
+ if self.stack[-1]:
+ self.stack[-1].AppendContent(content)
+
+ def ignorableWhitespace(self, whitespace):
+ # TODO(joi) This is not supported by expat. Should use a different XML parser?
+ pass
+
+
+class GrdPartContentHandler(xml.sax.handler.ContentHandler):
+ def __init__(self, parent):
+ self.parent = parent
+ self.depth = 0
+
+ def startElement(self, name, attrs):
+ if self.depth:
+ self.parent.startElement(name, attrs)
+ else:
+ if name != 'grit-part':
+ raise exception.MissingElement("root tag must be <grit-part>")
+ if attrs:
+ raise exception.UnexpectedAttribute(
+ "<grit-part> tag must not have attributes")
+ self.depth += 1
+
+ def endElement(self, name):
+ self.depth -= 1
+ if self.depth:
+ self.parent.endElement(name)
+
+ def characters(self, content):
+ self.parent.characters(content)
+
+ def ignorableWhitespace(self, whitespace):
+ self.parent.ignorableWhitespace(whitespace)
+
+
+def Parse(filename_or_stream, dir=None, stop_after=None, first_ids_file=None,
+ debug=False, defines=None, tags_to_ignore=None, target_platform=None):
+ '''Parses a GRD file into a tree of nodes (from grit.node).
+
+ If filename_or_stream is a stream, 'dir' should point to the directory
+ notionally containing the stream (this feature is only used in unit tests).
+
+ If 'stop_after' is provided, the parsing will stop once the first node
+ with this name has been fully parsed (including all its contents).
+
+ If 'debug' is true, lots of information about the parsing events will be
+ printed out during parsing of the file.
+
+ If 'first_ids_file' is non-empty, it is used to override the setting for the
+ first_ids_file attribute of the <grit> root node. Note that the first_ids_file
+ parameter should be relative to the cwd, even though the first_ids_file
+ attribute of the <grit> node is relative to the grd file.
+
+ If 'target_platform' is set, this is used to determine the target
+ platform of builds, instead of using |sys.platform|.
+
+ Args:
+ filename_or_stream: './bla.xml'
+ dir: None (if filename_or_stream is a filename) or '.'
+ stop_after: 'inputs'
+ first_ids_file: 'GRIT_DIR/../gritsettings/resource_ids'
+ debug: False
+ defines: dictionary of defines, like {'chromeos': '1'}
+ target_platform: None or the value that would be returned by sys.platform
+ on your target platform.
+
+ Return:
+ Subclass of grit.node.base.Node
+
+ Throws:
+ grit.exception.Parsing
+ '''
+
+ if dir is None and isinstance(filename_or_stream, types.StringType):
+ dir = util.dirname(filename_or_stream)
+
+ handler = GrdContentHandler(stop_after=stop_after, debug=debug, dir=dir,
+ defines=defines, tags_to_ignore=tags_to_ignore)
+ try:
+ xml.sax.parse(filename_or_stream, handler)
+ except StopParsingException:
+ assert stop_after
+ pass
+ except:
+ if not debug:
+ print "parse exception: run GRIT with the -x flag to debug .grd problems"
+ raise
+
+ if handler.root.name != 'grit':
+ raise exception.MissingElement("root tag must be <grit>")
+
+ if hasattr(handler.root, 'SetOwnDir'):
+ # Fix up the base_dir so it is relative to the input file.
+ assert dir is not None
+ handler.root.SetOwnDir(dir)
+
+ if isinstance(handler.root, misc.GritNode):
+ if target_platform:
+ handler.root.SetTargetPlatform(target_platform)
+ if first_ids_file:
+ # Make the path to the first_ids_file relative to the grd file,
+ # unless it begins with GRIT_DIR.
+ GRIT_DIR_PREFIX = 'GRIT_DIR'
+ if not (first_ids_file.startswith(GRIT_DIR_PREFIX)
+ and first_ids_file[len(GRIT_DIR_PREFIX)] in ['/', '\\']):
+ rel_dir = os.path.relpath(os.getcwd(), dir)
+ first_ids_file = util.normpath(os.path.join(rel_dir, first_ids_file))
+ handler.root.attrs['first_ids_file'] = first_ids_file
+ # Assign first ids to the nodes that don't have them.
+ handler.root.AssignFirstIds(filename_or_stream, defines)
+
+ return handler.root
+
+
+if __name__ == '__main__':
+ util.ChangeStdoutEncoding()
+ print unicode(Parse(sys.argv[1]))
diff --git a/chromium/tools/grit/grit/grd_reader_unittest.py b/chromium/tools/grit/grit/grd_reader_unittest.py
new file mode 100644
index 00000000000..5a4c7c3fa5f
--- /dev/null
+++ b/chromium/tools/grit/grit/grd_reader_unittest.py
@@ -0,0 +1,290 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grd_reader package'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import unittest
+import StringIO
+
+from grit import exception
+from grit import grd_reader
+from grit import util
+from grit.node import empty
+
+
+class GrdReaderUnittest(unittest.TestCase):
+ def testParsingAndXmlOutput(self):
+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit base_dir="." current_release="3" latest_public_release="2" source_lang_id="en-US">
+ <release seq="3">
+ <includes>
+ <include file="images/logo.gif" name="ID_LOGO" type="gif" />
+ </includes>
+ <messages>
+ <if expr="True">
+ <message desc="Printed to greet the currently logged in user" name="IDS_GREETING">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ </if>
+ </messages>
+ <structures>
+ <structure file="rc_files/dialogs.rc" name="IDD_NARROW_DIALOG" type="dialog">
+ <skeleton expr="lang == 'fr-FR'" file="bla.rc" variant_of_revision="3" />
+ </structure>
+ <structure file="rc_files/version.rc" name="VS_VERSION_INFO" type="version" />
+ </structures>
+ </release>
+ <translations>
+ <file lang="nl" path="nl_translations.xtb" />
+ </translations>
+ <outputs>
+ <output filename="resource.h" type="rc_header" />
+ <output filename="resource.rc" lang="en-US" type="rc_all" />
+ </outputs>
+</grit>'''
+ pseudo_file = StringIO.StringIO(input)
+ tree = grd_reader.Parse(pseudo_file, '.')
+ output = unicode(tree)
+ expected_output = input.replace(u' base_dir="."', u'')
+ self.assertEqual(expected_output, output)
+ self.failUnless(tree.GetNodeById('IDS_GREETING'))
+
+
+ def testStopAfter(self):
+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <outputs>
+ <output filename="resource.h" type="rc_header" />
+ <output filename="resource.rc" lang="en-US" type="rc_all" />
+ </outputs>
+ <release seq="3">
+ <includes>
+ <include type="gif" name="ID_LOGO" file="images/logo.gif"/>
+ </includes>
+ </release>
+</grit>'''
+ pseudo_file = StringIO.StringIO(input)
+ tree = grd_reader.Parse(pseudo_file, '.', stop_after='outputs')
+ # only an <outputs> child
+ self.failUnless(len(tree.children) == 1)
+ self.failUnless(tree.children[0].name == 'outputs')
+
+ def testLongLinesWithComments(self):
+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ This is a very long line with no linebreaks yes yes it stretches on <!--
+ -->and on <!--
+ -->and on!
+ </message>
+ </messages>
+ </release>
+</grit>'''
+ pseudo_file = StringIO.StringIO(input)
+ tree = grd_reader.Parse(pseudo_file, '.')
+
+ greeting = tree.GetNodeById('IDS_GREETING')
+ self.failUnless(greeting.GetCliques()[0].GetMessage().GetRealContent() ==
+ 'This is a very long line with no linebreaks yes yes it '
+ 'stretches on and on and on!')
+
+ def doTestAssignFirstIds(self, first_ids_path):
+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3"
+ base_dir="." first_ids_file="%s">
+ <release seq="3">
+ <messages>
+ <message name="IDS_TEST" desc="test">
+ test
+ </message>
+ </messages>
+ </release>
+</grit>''' % first_ids_path
+ pseudo_file = StringIO.StringIO(input)
+ grit_root_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ '..')
+ fake_input_path = os.path.join(
+ grit_root_dir, "grit/testdata/chrome/app/generated_resources.grd")
+ root = grd_reader.Parse(pseudo_file, os.path.split(fake_input_path)[0])
+ root.AssignFirstIds(fake_input_path, {})
+ messages_node = root.children[0].children[0]
+ self.failUnless(isinstance(messages_node, empty.MessagesNode))
+ self.failUnless(messages_node.attrs["first_id"] !=
+ empty.MessagesNode().DefaultAttributes()["first_id"])
+
+ def testAssignFirstIds(self):
+ self.doTestAssignFirstIds("../../tools/grit/resource_ids")
+
+ def testAssignFirstIdsUseGritDir(self):
+ self.doTestAssignFirstIds("GRIT_DIR/grit/testdata/tools/grit/resource_ids")
+
+ def testAssignFirstIdsMultipleMessages(self):
+ """If there are multiple messages sections, the resource_ids file
+ needs to list multiple first_id values."""
+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3"
+ base_dir="." first_ids_file="resource_ids">
+ <release seq="3">
+ <messages>
+ <message name="IDS_TEST" desc="test">
+ test
+ </message>
+ </messages>
+ <messages>
+ <message name="IDS_TEST2" desc="test">
+ test2
+ </message>
+ </messages>
+ </release>
+</grit>'''
+ pseudo_file = StringIO.StringIO(input)
+ grit_root_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
+ '..')
+ fake_input_path = os.path.join(grit_root_dir, "grit/testdata/test.grd")
+
+ root = grd_reader.Parse(pseudo_file, os.path.split(fake_input_path)[0])
+ root.AssignFirstIds(fake_input_path, {})
+ messages_node = root.children[0].children[0]
+ self.assertTrue(isinstance(messages_node, empty.MessagesNode))
+ self.assertEqual('100', messages_node.attrs["first_id"])
+ messages_node = root.children[0].children[1]
+ self.assertTrue(isinstance(messages_node, empty.MessagesNode))
+ self.assertEqual('10000', messages_node.attrs["first_id"])
+
+ def testUseNameForIdAndPpIfdef(self):
+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <if expr="pp_ifdef('hello')">
+ <message name="IDS_HELLO" use_name_for_id="true">
+ Hello!
+ </message>
+ </if>
+ </messages>
+ </release>
+</grit>'''
+ pseudo_file = StringIO.StringIO(input)
+ root = grd_reader.Parse(pseudo_file, '.', defines={'hello': '1'})
+
+ # Check if the ID is set to the name. In the past, there was a bug
+ # that caused the ID to be a generated number.
+ hello = root.GetNodeById('IDS_HELLO')
+ self.failUnless(hello.GetCliques()[0].GetId() == 'IDS_HELLO')
+
+ def testUseNameForIdWithIfElse(self):
+ input = u'''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <if expr="pp_ifdef('hello')">
+ <then>
+ <message name="IDS_HELLO" use_name_for_id="true">
+ Hello!
+ </message>
+ </then>
+ <else>
+ <message name="IDS_HELLO" use_name_for_id="true">
+ Yellow!
+ </message>
+ </else>
+ </if>
+ </messages>
+ </release>
+</grit>'''
+ pseudo_file = StringIO.StringIO(input)
+ root = grd_reader.Parse(pseudo_file, '.', defines={'hello': '1'})
+
+ # Check if the ID is set to the name. In the past, there was a bug
+ # that caused the ID to be a generated number.
+ hello = root.GetNodeById('IDS_HELLO')
+ self.failUnless(hello.GetCliques()[0].GetId() == 'IDS_HELLO')
+
+ def testPartInclusion(self):
+ top_grd = u'''\
+ <grit latest_public_release="2" current_release="3">
+ <release seq="3">
+ <messages>
+ <message name="IDS_TEST" desc="test">
+ test
+ </message>
+ <part file="sub.grp" />
+ </messages>
+ </release>
+ </grit>'''
+ sub_grd = u'''\
+ <grit-part>
+ <message name="IDS_TEST2" desc="test2">test2</message>
+ <part file="subsub.grp" />
+ <message name="IDS_TEST3" desc="test3">test3</message>
+ </grit-part>'''
+ subsub_grd = u'''\
+ <grit-part>
+ <message name="IDS_TEST4" desc="test4">test4</message>
+ </grit-part>'''
+ expected_output = u'''\
+ <grit current_release="3" latest_public_release="2">
+ <release seq="3">
+ <messages>
+ <message desc="test" name="IDS_TEST">
+ test
+ </message>
+ <part file="sub.grp">
+ <message desc="test2" name="IDS_TEST2">
+ test2
+ </message>
+ <part file="subsub.grp">
+ <message desc="test4" name="IDS_TEST4">
+ test4
+ </message>
+ </part>
+ <message desc="test3" name="IDS_TEST3">
+ test3
+ </message>
+ </part>
+ </messages>
+ </release>
+ </grit>'''
+ with util.TempDir({'sub.grp': sub_grd,
+ 'subsub.grp': subsub_grd}) as temp_dir:
+ output = grd_reader.Parse(StringIO.StringIO(top_grd), temp_dir.GetPath())
+ self.assertEqual(expected_output.split(), output.FormatXml().split())
+
+ def testPartInclusionFailure(self):
+ template = u'''
+ <grit latest_public_release="2" current_release="3">
+ <outputs>
+ %s
+ </outputs>
+ </grit>'''
+
+ part_failures = [
+ (exception.UnexpectedContent, u'<part file="x">fnord</part>'),
+ (exception.UnexpectedChild,
+ u'<part file="x"><output filename="x" type="y" /></part>'),
+ ]
+ for raises, data in part_failures:
+ data = StringIO.StringIO(template % data)
+ self.assertRaises(raises, grd_reader.Parse, data, '.')
+
+ gritpart_failures = [
+ (exception.UnexpectedAttribute, u'<grit-part file="xyz"></grit-part>'),
+ (exception.MissingElement, u'<output filename="x" type="y" />'),
+ ]
+ for raises, data in gritpart_failures:
+ top_grd = StringIO.StringIO(template % u'<part file="bad.grp" />')
+ with util.TempDir({'bad.grp': data}) as temp_dir:
+ self.assertRaises(raises, grd_reader.Parse, top_grd, temp_dir.GetPath())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/grit-todo.xml b/chromium/tools/grit/grit/grit-todo.xml
new file mode 100644
index 00000000000..b8c20fdfada
--- /dev/null
+++ b/chromium/tools/grit/grit/grit-todo.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="windows-1252"?>
+<TODOLIST FILEFORMAT="6" PROJECTNAME="GRIT" NEXTUNIQUEID="56" FILEVERSION="69" LASTMODIFIED="2005-08-19">
+ <TASK STARTDATESTRING="2005-04-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38453.49975694" TITLE="check 'name' attribute is unique" TIMEESTUNITS="H" ID="2" PERCENTDONE="100" STARTDATE="38450.00000000" DONEDATESTRING="2005-04-11" POS="22" DONEDATE="38453.00000000"/>
+ <TASK STARTDATESTRING="2005-04-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38488.48189815" TITLE="import id-calculating code" TIMEESTUNITS="H" ID="3" PERCENTDONE="100" STARTDATE="38450.00000000" DONEDATESTRING="2005-05-16" POS="13" DONEDATE="38488.00000000"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38488.48209491" TITLE="Import tool for existing translations" TIMEESTUNITS="H" ID="6" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="12" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00805556" TITLE="Export XMBs" TIMEESTUNITS="H" ID="8" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-08" POS="20" DONEDATE="38511.00000000"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00924769" TITLE="Initial Integration" TIMEESTUNITS="H" ID="10" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-08" POS="10" DONEDATE="38511.00000000">
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38496.54048611" TITLE="parser for %s strings" TIMEESTUNITS="H" ID="4" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-24" POS="2" DONEDATE="38496.00000000"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38497.00261574" TITLE="import tool for existing RC files" TIMEESTUNITS="H" ID="5" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-25" POS="4" DONEDATE="38497.00000000">
+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38496.92990741" TITLE="handle button value= and img alt= in message HTML text" TIMEESTUNITS="H" ID="22" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-05-24" POS="1" DONEDATE="38496.00000000"/>
+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38497.00258102" TITLE="&amp;nbsp; bug" TIMEESTUNITS="H" ID="23" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-05-25" POS="2" DONEDATE="38497.00000000"/>
+ </TASK>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61171296" TITLE="grit build" TIMEESTUNITS="H" ID="7" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="6" DONEDATE="38490.00000000">
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61168981" TITLE="use IDs gathered from gatherers for .h file" TIMEESTUNITS="H" ID="20" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="1" DONEDATE="38490.00000000"/>
+ </TASK>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.55199074" TITLE="SCons Integration" TIMEESTUNITS="H" ID="9" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-01" POS="1" DONEDATE="38504.00000000"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38490.61181713" TITLE="handle includes" TIMEESTUNITS="H" ID="12" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-05-18" POS="5" DONEDATE="38490.00000000"/>
+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38507.98567130" TITLE="output translated HTML templates" TIMEESTUNITS="H" ID="25" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-04" POS="3" DONEDATE="38507.00000000"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38507.99394676" TITLE="bug: re-escape too much in RC dialogs etc." TIMEESTUNITS="H" ID="38" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-04" POS="7" DONEDATE="38507.00000000"/>
+ </TASK>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46444444" TITLE="handle structure variants" TIMEESTUNITS="H" ID="11" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="15" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46456019" TITLE="handle include variants" TIMEESTUNITS="H" ID="13" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="17" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46537037" TITLE="handle translateable text for includes (e.g. image text)" TIMEESTUNITS="H" ID="14" PERCENTDONE="100" STARTDATE="38488.00000000" DONEDATESTRING="2005-06-16" POS="14" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46712963" TITLE="ddoc" TIMEESTUNITS="H" ID="15" STARTDATE="38488.00000000" POS="4">
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46718750" TITLE="review comments miket" TIMEESTUNITS="H" ID="16" STARTDATE="38488.00000000" POS="2"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46722222" TITLE="review comments pdoyle" TIMEESTUNITS="H" ID="17" STARTDATE="38488.00000000" POS="1"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.46732639" TITLE="remove 'extkey' from structure" TIMEESTUNITS="H" ID="18" STARTDATE="38488.00000000" POS="3"/>
+ <TASK STARTDATESTRING="2005-05-16" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38489.53537037" TITLE="add 'encoding' to structure" TIMEESTUNITS="H" ID="19" STARTDATE="38488.00000000" POS="6"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38503.55304398" TITLE="document limitation: emitter doesn't emit the translated HTML templates" TIMEESTUNITS="H" ID="30" STARTDATE="38503.00000000" POS="4"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.58541667" TITLE="add 'internal_comment' to &lt;message&gt;" TIMEESTUNITS="H" ID="32" STARTDATE="38503.00000000" POS="5"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.73391204" TITLE="&lt;outputs&gt; can not have paths (because of SCons integration - goes to build dir)" TIMEESTUNITS="H" ID="36" STARTDATE="38503.00000000" POS="9"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38506.64265046" TITLE="&lt;identifers&gt; and &lt;identifier&gt; nodes" TIMEESTUNITS="H" ID="37" STARTDATE="38503.00000000" POS="10"/>
+ <TASK STARTDATESTRING="2005-06-23" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38526.62344907" TITLE="&lt;structure&gt; can have 'exclude_from_rc' attribute (default false)" TIMEESTUNITS="H" ID="47" STARTDATE="38526.00000000" POS="8"/>
+ <TASK STARTDATESTRING="2005-06-23" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38531.94135417" TITLE="add 'enc_check' to &lt;grit&gt;" TIMEESTUNITS="H" ID="48" STARTDATE="38526.00000000" POS="7"/>
+ </TASK>
+ <TASK STARTDATESTRING="2005-05-18" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38492.51549769" TITLE="handle nontranslateable messages (in MessageClique?)" TIMEESTUNITS="H" ID="21" PERCENTDONE="100" STARTDATE="38490.00000000" DONEDATESTRING="2005-06-16" POS="16" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70454861" TITLE="ask cprince about SCons builder in new mk system" TIMEESTUNITS="H" ID="24" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-02" POS="25" DONEDATE="38505.00000000"/>
+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38504.57436343" TITLE="fix AOL resource in trunk (&quot;???????&quot;)" TIMEESTUNITS="H" ID="26" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-01" POS="19" DONEDATE="38504.00000000"/>
+ <TASK STARTDATESTRING="2005-05-24" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38498.53893519" TITLE="rc_all vs. rc_translateable vs. rc_nontranslateable" TIMEESTUNITS="H" ID="27" PERCENTDONE="100" STARTDATE="38496.00000000" DONEDATESTRING="2005-06-16" POS="6" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38509.45532407" TITLE="make separate .grb &quot;outputs&quot; file (and change SCons integ) (??)" TIMEESTUNITS="H" ID="28" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-06" POS="8" DONEDATE="38509.00000000"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00939815" TITLE="fix unit tests so they run from any directory" TIMEESTUNITS="H" ID="33" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-08" POS="18" DONEDATE="38511.00000000"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38508.96640046" TITLE="Change R4 tool to CC correct team(s) on GRIT changes" TIMEESTUNITS="H" ID="39" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-05" POS="23" DONEDATE="38508.00000000"/>
+ <TASK STARTDATESTRING="2005-06-07" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00881944" TITLE="Document why wrapper.rc" TIMEESTUNITS="H" ID="40" PERCENTDONE="100" STARTDATE="38510.00000000" DONEDATESTRING="2005-06-08" POS="21" DONEDATE="38511.00000000"/>
+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00804398" TITLE="import XTBs" TIMEESTUNITS="H" ID="41" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="11" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00875000" TITLE="Nightly build integration" TIMEESTUNITS="H" ID="42" STARTDATE="38511.00000000" POS="3"/>
+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00891204" TITLE="BUGS" TIMEESTUNITS="H" ID="43" STARTDATE="38511.00000000" POS="24">
+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38513.03375000" TITLE="Should report error if RC-section structure refers to does not exist" TIMEESTUNITS="H" ID="44" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-10" POS="1" DONEDATE="38513.00000000"/>
+ </TASK>
+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.00981481" TITLE="NEW FEATURES" TIMEESTUNITS="H" ID="45" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="7" DONEDATE="38519.00000000">
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70077546" TITLE="Implement line-continuation feature (\ at end of line?)" TIMEESTUNITS="H" ID="34" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-16" POS="1" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-05-31" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38505.70262731" TITLE="Implement conditional inclusion &amp; reflect the conditionals from R3 RC file" TIMEESTUNITS="H" ID="35" PERCENTDONE="100" STARTDATE="38503.00000000" DONEDATESTRING="2005-06-16" POS="2" DONEDATE="38519.00000000"/>
+ </TASK>
+ <TASK STARTDATESTRING="2005-06-08" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38511.01046296" TITLE="TC integration (one-way TO the TC)" TIMEESTUNITS="H" ID="46" PERCENTDONE="100" STARTDATE="38511.00000000" DONEDATESTRING="2005-06-16" POS="5" DONEDATE="38519.00000000"/>
+ <TASK STARTDATESTRING="2005-06-30" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38533.59072917" TITLE="bazaar20 ad for GRIT help" TIMEESTUNITS="H" ID="49" STARTDATE="38533.00000000" POS="2">
+ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72346065" TITLE="bazaar20 ideas" TIMEESTUNITS="H" ID="51" STARTDATE="38583.00000000" POS="1">
+ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72354167" TITLE="GUI for adding/editing messages" TIMEESTUNITS="H" ID="52" STARTDATE="38583.00000000" POS="2"/>
+ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.72365741" TITLE="XLIFF import/export" TIMEESTUNITS="H" ID="54" STARTDATE="38583.00000000" POS="1"/>
+ </TASK>
+ </TASK>
+ <TASK STARTDATESTRING="2005-06-30" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.73721065" TITLE="internal_comment for all resource nodes (not just &lt;message&gt;)" TIMEESTUNITS="H" ID="50" PERCENTDONE="100" STARTDATE="38533.00000000" DONEDATESTRING="2005-08-19" POS="9" DONEDATE="38583.73721065"/>
+ <TASK STARTDATESTRING="2005-08-19" PRIORITY="5" TIMEESPENTUNITS="H" LASTMOD="38583.73743056" TITLE="Preserve XML comments - this gives us line continuation and more" TIMEESTUNITS="H" ID="55" STARTDATE="38583.72326389" POS="1"/>
+</TODOLIST>
diff --git a/chromium/tools/grit/grit/grit_runner.py b/chromium/tools/grit/grit/grit_runner.py
new file mode 100644
index 00000000000..6c1cf5e969e
--- /dev/null
+++ b/chromium/tools/grit/grit/grit_runner.py
@@ -0,0 +1,272 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Command processor for GRIT. This is the script you invoke to run the various
+GRIT tools.
+"""
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import getopt
+
+from grit import util
+
+import grit.extern.FP
+
+# Tool info factories; these import only within each factory to avoid
+# importing most of the GRIT code until required.
+def ToolFactoryBuild():
+ import grit.tool.build
+ return grit.tool.build.RcBuilder()
+
+def ToolFactoryBuildInfo():
+ import grit.tool.buildinfo
+ return grit.tool.buildinfo.DetermineBuildInfo()
+
+def ToolFactoryCount():
+ import grit.tool.count
+ return grit.tool.count.CountMessage()
+
+def ToolFactoryDiffStructures():
+ import grit.tool.diff_structures
+ return grit.tool.diff_structures.DiffStructures()
+
+def ToolFactoryMenuTranslationsFromParts():
+ import grit.tool.menu_from_parts
+ return grit.tool.menu_from_parts.MenuTranslationsFromParts()
+
+def ToolFactoryNewGrd():
+ import grit.tool.newgrd
+ return grit.tool.newgrd.NewGrd()
+
+def ToolFactoryResizeDialog():
+ import grit.tool.resize
+ return grit.tool.resize.ResizeDialog()
+
+def ToolFactoryRc2Grd():
+ import grit.tool.rc2grd
+ return grit.tool.rc2grd.Rc2Grd()
+
+def ToolFactoryTest():
+ import grit.tool.test
+ return grit.tool.test.TestTool()
+
+def ToolFactoryTranslationToTc():
+ import grit.tool.transl2tc
+ return grit.tool.transl2tc.TranslationToTc()
+
+def ToolFactoryUnit():
+ import grit.tool.unit
+ return grit.tool.unit.UnitTestTool()
+
+def ToolFactoryXmb():
+ import grit.tool.xmb
+ return grit.tool.xmb.OutputXmb()
+
+def ToolAndroid2Grd():
+ import grit.tool.android2grd
+ return grit.tool.android2grd.Android2Grd()
+
+# Keys for the following map
+_FACTORY = 1
+_REQUIRES_INPUT = 2
+_HIDDEN = 3 # optional key - presence indicates tool is hidden
+
+# Maps tool names to the tool's module. Done as a list of (key, value) tuples
+# instead of a map to preserve ordering.
+_TOOLS = [
+ ['build', { _FACTORY : ToolFactoryBuild, _REQUIRES_INPUT : True }],
+ ['buildinfo', { _FACTORY : ToolFactoryBuildInfo, _REQUIRES_INPUT : True }],
+ ['count', { _FACTORY : ToolFactoryCount, _REQUIRES_INPUT : True }],
+ ['menufromparts', {
+ _FACTORY: ToolFactoryMenuTranslationsFromParts,
+ _REQUIRES_INPUT : True, _HIDDEN : True }],
+ ['newgrd', { _FACTORY : ToolFactoryNewGrd, _REQUIRES_INPUT : False }],
+ ['rc2grd', { _FACTORY : ToolFactoryRc2Grd, _REQUIRES_INPUT : False }],
+ ['resize', {
+ _FACTORY : ToolFactoryResizeDialog, _REQUIRES_INPUT : True }],
+ ['sdiff', { _FACTORY : ToolFactoryDiffStructures,
+ _REQUIRES_INPUT : False }],
+ ['test', {
+ _FACTORY: ToolFactoryTest, _REQUIRES_INPUT : True,
+ _HIDDEN : True }],
+ ['transl2tc', { _FACTORY : ToolFactoryTranslationToTc,
+ _REQUIRES_INPUT : False }],
+ ['unit', { _FACTORY : ToolFactoryUnit, _REQUIRES_INPUT : False }],
+ ['xmb', { _FACTORY : ToolFactoryXmb, _REQUIRES_INPUT : True }],
+ ['android2grd', {
+ _FACTORY: ToolAndroid2Grd,
+ _REQUIRES_INPUT : False }],
+]
+
+
+def PrintUsage():
+ tool_list = ''
+ for (tool, info) in _TOOLS:
+ if not _HIDDEN in info.keys():
+ tool_list += ' %-12s %s\n' % (tool, info[_FACTORY]().ShortDescription())
+
+ # TODO(joi) Put these back into the usage when appropriate:
+ #
+ # -d Work disconnected. This causes GRIT not to attempt connections with
+ # e.g. Perforce.
+ #
+ # -c Use the specified Perforce CLIENT when talking to Perforce.
+ print """GRIT - the Google Resource and Internationalization Tool
+
+Usage: grit [GLOBALOPTIONS] TOOL [args to tool]
+
+Global options:
+
+ -i INPUT Specifies the INPUT file to use (a .grd file). If this is not
+ specified, GRIT will look for the environment variable GRIT_INPUT.
+ If it is not present either, GRIT will try to find an input file
+ named 'resource.grd' in the current working directory.
+
+ -h MODULE Causes GRIT to use MODULE.UnsignedFingerPrint instead of
+ grit.extern.FP.UnsignedFingerprint. MODULE must be
+ available somewhere in the PYTHONPATH search path.
+
+ -v Print more verbose runtime information.
+
+ -x Print extremely verbose runtime information. Implies -v
+
+ -p FNAME Specifies that GRIT should profile its execution and output the
+ results to the file FNAME.
+
+Tools:
+
+ TOOL can be one of the following:
+%s
+ For more information on how to use a particular tool, and the specific
+ arguments you can send to that tool, execute 'grit help TOOL'
+""" % (tool_list)
+
+
+class Options(object):
+ """Option storage and parsing."""
+
+ def __init__(self):
+ self.disconnected = False
+ self.client = ''
+ self.hash = None
+ self.input = None
+ self.verbose = False
+ self.extra_verbose = False
+ self.output_stream = sys.stdout
+ self.profile_dest = None
+ self.psyco = False
+
+ def ReadOptions(self, args):
+ """Reads options from the start of args and returns the remainder."""
+ (opts, args) = getopt.getopt(args, 'g:qdvxc:i:p:h:', ('psyco',))
+ for (key, val) in opts:
+ if key == '-d': self.disconnected = True
+ elif key == '-c': self.client = val
+ elif key == '-h': self.hash = val
+ elif key == '-i': self.input = val
+ elif key == '-v':
+ self.verbose = True
+ util.verbose = True
+ elif key == '-x':
+ self.verbose = True
+ util.verbose = True
+ self.extra_verbose = True
+ util.extra_verbose = True
+ elif key == '-p': self.profile_dest = val
+ elif key == '--psyco': self.psyco = True
+
+ if not self.input:
+ if 'GRIT_INPUT' in os.environ:
+ self.input = os.environ['GRIT_INPUT']
+ else:
+ self.input = 'resource.grd'
+
+ return args
+
+ def __repr__(self):
+ return '(disconnected: %d, verbose: %d, client: %s, input: %s)' % (
+ self.disconnected, self.verbose, self.client, self.input)
+
+
+def _GetToolInfo(tool):
+ """Returns the info map for the tool named 'tool' or None if there is no
+ such tool."""
+ matches = [t for t in _TOOLS if t[0] == tool]
+ if not matches:
+ return None
+ else:
+ return matches[0][1]
+
+
+def Main(args):
+ """Parses arguments and does the appropriate thing."""
+ util.ChangeStdoutEncoding()
+
+ if sys.version_info < (2, 6):
+ print "GRIT requires Python 2.6 or later."
+ return 2
+ elif not args or (len(args) == 1 and args[0] == 'help'):
+ PrintUsage()
+ return 0
+ elif len(args) == 2 and args[0] == 'help':
+ tool = args[1].lower()
+ if not _GetToolInfo(tool):
+ print "No such tool. Try running 'grit help' for a list of tools."
+ return 2
+
+ print ("Help for 'grit %s' (for general help, run 'grit help'):\n"
+ % (tool))
+ print _GetToolInfo(tool)[_FACTORY]().__doc__
+ return 0
+ else:
+ options = Options()
+ args = options.ReadOptions(args) # args may be shorter after this
+ if not args:
+ print "No tool provided. Try running 'grit help' for a list of tools."
+ return 2
+ tool = args[0]
+ if not _GetToolInfo(tool):
+ print "No such tool. Try running 'grit help' for a list of tools."
+ return 2
+
+ try:
+ if _GetToolInfo(tool)[_REQUIRES_INPUT]:
+ os.stat(options.input)
+ except OSError:
+ print ('Input file %s not found.\n'
+ 'To specify a different input file:\n'
+ ' 1. Use the GRIT_INPUT environment variable.\n'
+ ' 2. Use the -i command-line option. This overrides '
+ 'GRIT_INPUT.\n'
+ ' 3. Specify neither GRIT_INPUT or -i and GRIT will try to load '
+ "'resource.grd'\n"
+ ' from the current directory.' % options.input)
+ return 2
+
+ if options.psyco:
+ # Psyco is a specializing JIT for Python. Early tests indicate that it
+ # could speed up GRIT (at the expense of more memory) for large GRIT
+ # compilations. See http://psyco.sourceforge.net/
+ import psyco
+ psyco.profile()
+
+ if options.hash:
+ grit.extern.FP.UseUnsignedFingerPrintFromModule(options.hash)
+
+ toolobject = _GetToolInfo(tool)[_FACTORY]()
+ if options.profile_dest:
+ import hotshot
+ prof = hotshot.Profile(options.profile_dest)
+ prof.runcall(toolobject.Run, options, args[1:])
+ else:
+ toolobject.Run(options, args[1:])
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
diff --git a/chromium/tools/grit/grit/grit_runner_unittest.py b/chromium/tools/grit/grit/grit_runner_unittest.py
new file mode 100644
index 00000000000..ad6b2ec76e7
--- /dev/null
+++ b/chromium/tools/grit/grit/grit_runner_unittest.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.py'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import unittest
+import StringIO
+
+from grit import util
+import grit.grit_runner
+
+class OptionArgsUnittest(unittest.TestCase):
+ def setUp(self):
+ self.buf = StringIO.StringIO()
+ self.old_stdout = sys.stdout
+ sys.stdout = self.buf
+
+ def tearDown(self):
+ sys.stdout = self.old_stdout
+
+ def testSimple(self):
+ grit.grit_runner.Main(['-i',
+ util.PathFromRoot('grit/testdata/simple-input.xml'),
+ '-d', 'test', 'bla', 'voff', 'ga'])
+ output = self.buf.getvalue()
+ self.failUnless(output.count('disconnected'))
+ self.failUnless(output.count("'test'") == 0) # tool name doesn't occur
+ self.failUnless(output.count('bla'))
+ self.failUnless(output.count('simple-input.xml'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/lazy_re.py b/chromium/tools/grit/grit/lazy_re.py
new file mode 100644
index 00000000000..a532cd04c18
--- /dev/null
+++ b/chromium/tools/grit/grit/lazy_re.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''In GRIT, we used to compile a lot of regular expressions at parse
+time. Since many of them never get used, we use lazy_re to compile
+them on demand the first time they are used, thus speeding up startup
+time in some cases.
+'''
+
+import re
+
+
+class LazyRegexObject(object):
+ '''This object creates a RegexObject with the arguments passed in
+ its constructor, the first time any attribute except the several on
+ the class itself is accessed. This accomplishes lazy compilation of
+ the regular expression while maintaining a nearly-identical
+ interface.
+ '''
+
+ def __init__(self, *args, **kwargs):
+ self._stash_args = args
+ self._stash_kwargs = kwargs
+ self._lazy_re = None
+
+ def _LazyInit(self):
+ if not self._lazy_re:
+ self._lazy_re = re.compile(*self._stash_args, **self._stash_kwargs)
+
+ def __getattribute__(self, name):
+ if name in ('_LazyInit', '_lazy_re', '_stash_args', '_stash_kwargs'):
+ return object.__getattribute__(self, name)
+ else:
+ self._LazyInit()
+ return getattr(self._lazy_re, name)
+
+
+def compile(*args, **kwargs):
+ '''Creates a LazyRegexObject that, when invoked on, will compile a
+ re.RegexObject (via re.compile) with the same arguments passed to
+ this function, and delegate almost all of its methods to it.
+ '''
+ return LazyRegexObject(*args, **kwargs)
diff --git a/chromium/tools/grit/grit/lazy_re_unittest.py b/chromium/tools/grit/grit/lazy_re_unittest.py
new file mode 100644
index 00000000000..99fe1ec9ece
--- /dev/null
+++ b/chromium/tools/grit/grit/lazy_re_unittest.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit test for lazy_re.
+'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import re
+import unittest
+
+from grit import lazy_re
+
+
+class LazyReUnittest(unittest.TestCase):
+
+ def testCreatedOnlyOnDemand(self):
+ rex = lazy_re.compile('bingo')
+ self.assertEqual(None, rex._lazy_re)
+ self.assertTrue(rex.match('bingo'))
+ self.assertNotEqual(None, rex._lazy_re)
+
+ def testJustKwargsWork(self):
+ rex = lazy_re.compile(flags=re.I, pattern='BiNgO')
+ self.assertTrue(rex.match('bingo'))
+
+ def testPositionalAndKwargsWork(self):
+ rex = lazy_re.compile('BiNgO', flags=re.I)
+ self.assertTrue(rex.match('bingo'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/node/__init__.py b/chromium/tools/grit/grit/node/__init__.py
new file mode 100644
index 00000000000..f285e2dc053
--- /dev/null
+++ b/chromium/tools/grit/grit/node/__init__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Package 'grit.node'
+'''
+
+pass
diff --git a/chromium/tools/grit/grit/node/base.py b/chromium/tools/grit/grit/node/base.py
new file mode 100644
index 00000000000..7541fa40405
--- /dev/null
+++ b/chromium/tools/grit/grit/node/base.py
@@ -0,0 +1,567 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Base types for nodes in a GRIT resource tree.
+'''
+
+import collections
+import os
+import sys
+import types
+from xml.sax import saxutils
+
+from grit import clique
+from grit import exception
+from grit import util
+
+
+class Node(object):
+ '''An item in the tree that has children.'''
+
+ # Valid content types that can be returned by _ContentType()
+ _CONTENT_TYPE_NONE = 0 # No CDATA content but may have children
+ _CONTENT_TYPE_CDATA = 1 # Only CDATA, no children.
+ _CONTENT_TYPE_MIXED = 2 # CDATA and children, possibly intermingled
+
+ # Default nodes to not whitelist skipped
+ _whitelist_marked_as_skip = False
+
+ # A class-static cache to memoize EvaluateExpression().
+ # It has a 2 level nested dict structure. The outer dict has keys
+ # of tuples which define the environment in which the expression
+ # will be evaluated. The inner dict is map of expr->result.
+ eval_expr_cache = collections.defaultdict(dict)
+
+ def __init__(self):
+ self.children = [] # A list of child elements
+ self.mixed_content = [] # A list of u'' and/or child elements (this
+ # duplicates 'children' but
+ # is needed to preserve markup-type content).
+ self.name = u'' # The name of this element
+ self.attrs = {} # The set of attributes (keys to values)
+ self.parent = None # Our parent unless we are the root element.
+ self.uberclique = None # Allows overriding uberclique for parts of tree
+
+ # This context handler allows you to write "with node:" and get a
+ # line identifying the offending node if an exception escapes from the body
+ # of the with statement.
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ if exc_type is not None:
+ print u'Error processing node %s' % unicode(self)
+
+ def __iter__(self):
+ '''A preorder iteration through the tree that this node is the root of.'''
+ return self.Preorder()
+
+ def Preorder(self):
+ '''Generator that generates first this node, then the same generator for
+ any child nodes.'''
+ yield self
+ for child in self.children:
+ for iterchild in child.Preorder():
+ yield iterchild
+
+ def ActiveChildren(self):
+ '''Returns the children of this node that should be included in the current
+ configuration. Overridden by <if>.'''
+ return [node for node in self.children if not node.WhitelistMarkedAsSkip()]
+
+ def ActiveDescendants(self):
+ '''Yields the current node and all descendants that should be included in
+ the current configuration, in preorder.'''
+ yield self
+ for child in self.ActiveChildren():
+ for descendant in child.ActiveDescendants():
+ yield descendant
+
+ def GetRoot(self):
+ '''Returns the root Node in the tree this Node belongs to.'''
+ curr = self
+ while curr.parent:
+ curr = curr.parent
+ return curr
+
+ # TODO(joi) Use this (currently untested) optimization?:
+ #if hasattr(self, '_root'):
+ # return self._root
+ #curr = self
+ #while curr.parent and not hasattr(curr, '_root'):
+ # curr = curr.parent
+ #if curr.parent:
+ # self._root = curr._root
+ #else:
+ # self._root = curr
+ #return self._root
+
+ def StartParsing(self, name, parent):
+ '''Called at the start of parsing.
+
+ Args:
+ name: u'elementname'
+ parent: grit.node.base.Node or subclass or None
+ '''
+ assert isinstance(name, types.StringTypes)
+ assert not parent or isinstance(parent, Node)
+ self.name = name
+ self.parent = parent
+
+ def AddChild(self, child):
+ '''Adds a child to the list of children of this node, if it is a valid
+ child for the node.'''
+ assert isinstance(child, Node)
+ if (not self._IsValidChild(child) or
+ self._ContentType() == self._CONTENT_TYPE_CDATA):
+ explanation = 'invalid child %s for parent %s' % (str(child), self.name)
+ raise exception.UnexpectedChild(explanation)
+ self.children.append(child)
+ self.mixed_content.append(child)
+
+ def RemoveChild(self, child_id):
+ '''Removes the first node that has a "name" attribute which
+ matches "child_id" in the list of immediate children of
+ this node.
+
+ Args:
+ child_id: String identifying the child to be removed
+ '''
+ index = 0
+ # Safe not to copy since we only remove the first element found
+ for child in self.children:
+ name_attr = child.attrs['name']
+ if name_attr == child_id:
+ self.children.pop(index)
+ self.mixed_content.pop(index)
+ break
+ index += 1
+
+ def AppendContent(self, content):
+ '''Appends a chunk of text as content of this node.
+
+ Args:
+ content: u'hello'
+
+ Return:
+ None
+ '''
+ assert isinstance(content, types.StringTypes)
+ if self._ContentType() != self._CONTENT_TYPE_NONE:
+ self.mixed_content.append(content)
+ elif content.strip() != '':
+ raise exception.UnexpectedContent()
+
+ def HandleAttribute(self, attrib, value):
+ '''Informs the node of an attribute that was parsed out of the GRD file
+ for it.
+
+ Args:
+ attrib: 'name'
+ value: 'fooblat'
+
+ Return:
+ None
+ '''
+ assert isinstance(attrib, types.StringTypes)
+ assert isinstance(value, types.StringTypes)
+ if self._IsValidAttribute(attrib, value):
+ self.attrs[attrib] = value
+ else:
+ raise exception.UnexpectedAttribute(attrib)
+
+ def EndParsing(self):
+ '''Called at the end of parsing.'''
+
+ # TODO(joi) Rewrite this, it's extremely ugly!
+ if len(self.mixed_content):
+ if isinstance(self.mixed_content[0], types.StringTypes):
+ # Remove leading and trailing chunks of pure whitespace.
+ while (len(self.mixed_content) and
+ isinstance(self.mixed_content[0], types.StringTypes) and
+ self.mixed_content[0].strip() == ''):
+ self.mixed_content = self.mixed_content[1:]
+ # Strip leading and trailing whitespace from mixed content chunks
+ # at front and back.
+ if (len(self.mixed_content) and
+ isinstance(self.mixed_content[0], types.StringTypes)):
+ self.mixed_content[0] = self.mixed_content[0].lstrip()
+ # Remove leading and trailing ''' (used to demarcate whitespace)
+ if (len(self.mixed_content) and
+ isinstance(self.mixed_content[0], types.StringTypes)):
+ if self.mixed_content[0].startswith("'''"):
+ self.mixed_content[0] = self.mixed_content[0][3:]
+ if len(self.mixed_content):
+ if isinstance(self.mixed_content[-1], types.StringTypes):
+ # Same stuff all over again for the tail end.
+ while (len(self.mixed_content) and
+ isinstance(self.mixed_content[-1], types.StringTypes) and
+ self.mixed_content[-1].strip() == ''):
+ self.mixed_content = self.mixed_content[:-1]
+ if (len(self.mixed_content) and
+ isinstance(self.mixed_content[-1], types.StringTypes)):
+ self.mixed_content[-1] = self.mixed_content[-1].rstrip()
+ if (len(self.mixed_content) and
+ isinstance(self.mixed_content[-1], types.StringTypes)):
+ if self.mixed_content[-1].endswith("'''"):
+ self.mixed_content[-1] = self.mixed_content[-1][:-3]
+
+ # Check that all mandatory attributes are there.
+ for node_mandatt in self.MandatoryAttributes():
+ mandatt_list = []
+ if node_mandatt.find('|') >= 0:
+ mandatt_list = node_mandatt.split('|')
+ else:
+ mandatt_list.append(node_mandatt)
+
+ mandatt_option_found = False
+ for mandatt in mandatt_list:
+ assert mandatt not in self.DefaultAttributes().keys()
+ if mandatt in self.attrs:
+ if not mandatt_option_found:
+ mandatt_option_found = True
+ else:
+ raise exception.MutuallyExclusiveMandatoryAttribute(mandatt)
+
+ if not mandatt_option_found:
+ raise exception.MissingMandatoryAttribute(mandatt)
+
+ # Add default attributes if not specified in input file.
+ for defattr in self.DefaultAttributes():
+ if not defattr in self.attrs:
+ self.attrs[defattr] = self.DefaultAttributes()[defattr]
+
+ def GetCdata(self):
+ '''Returns all CDATA of this element, concatenated into a single
+ string. Note that this ignores any elements embedded in CDATA.'''
+ return ''.join([c for c in self.mixed_content
+ if isinstance(c, types.StringTypes)])
+
+ def __unicode__(self):
+ '''Returns this node and all nodes below it as an XML document in a Unicode
+ string.'''
+ header = u'<?xml version="1.0" encoding="UTF-8"?>\n'
+ return header + self.FormatXml()
+
+ def FormatXml(self, indent = u'', one_line = False):
+ '''Returns this node and all nodes below it as an XML
+ element in a Unicode string. This differs from __unicode__ in that it does
+ not include the <?xml> stuff at the top of the string. If one_line is true,
+ children and CDATA are layed out in a way that preserves internal
+ whitespace.
+ '''
+ assert isinstance(indent, types.StringTypes)
+
+ content_one_line = (one_line or
+ self._ContentType() == self._CONTENT_TYPE_MIXED)
+ inside_content = self.ContentsAsXml(indent, content_one_line)
+
+ # Then the attributes for this node.
+ attribs = u''
+ default_attribs = self.DefaultAttributes()
+ for attrib, value in sorted(self.attrs.items()):
+ # Only print an attribute if it is other than the default value.
+ if attrib not in default_attribs or value != default_attribs[attrib]:
+ attribs += u' %s=%s' % (attrib, saxutils.quoteattr(value))
+
+ # Finally build the XML for our node and return it
+ if len(inside_content) > 0:
+ if one_line:
+ return u'<%s%s>%s</%s>' % (self.name, attribs, inside_content, self.name)
+ elif content_one_line:
+ return u'%s<%s%s>\n%s %s\n%s</%s>' % (
+ indent, self.name, attribs,
+ indent, inside_content,
+ indent, self.name)
+ else:
+ return u'%s<%s%s>\n%s\n%s</%s>' % (
+ indent, self.name, attribs,
+ inside_content,
+ indent, self.name)
+ else:
+ return u'%s<%s%s />' % (indent, self.name, attribs)
+
+ def ContentsAsXml(self, indent, one_line):
+ '''Returns the contents of this node (CDATA and child elements) in XML
+ format. If 'one_line' is true, the content will be laid out on one line.'''
+ assert isinstance(indent, types.StringTypes)
+
+ # Build the contents of the element.
+ inside_parts = []
+ last_item = None
+ for mixed_item in self.mixed_content:
+ if isinstance(mixed_item, Node):
+ inside_parts.append(mixed_item.FormatXml(indent + u' ', one_line))
+ if not one_line:
+ inside_parts.append(u'\n')
+ else:
+ message = mixed_item
+ # If this is the first item and it starts with whitespace, we add
+ # the ''' delimiter.
+ if not last_item and message.lstrip() != message:
+ message = u"'''" + message
+ inside_parts.append(util.EncodeCdata(message))
+ last_item = mixed_item
+
+ # If there are only child nodes and no cdata, there will be a spurious
+ # trailing \n
+ if len(inside_parts) and inside_parts[-1] == '\n':
+ inside_parts = inside_parts[:-1]
+
+ # If the last item is a string (not a node) and ends with whitespace,
+ # we need to add the ''' delimiter.
+ if (isinstance(last_item, types.StringTypes) and
+ last_item.rstrip() != last_item):
+ inside_parts[-1] = inside_parts[-1] + u"'''"
+
+ return u''.join(inside_parts)
+
+ def SubstituteMessages(self, substituter):
+ '''Applies substitutions to all messages in the tree.
+
+ Called as a final step of RunGatherers.
+
+ Args:
+ substituter: a grit.util.Substituter object.
+ '''
+ for child in self.children:
+ child.SubstituteMessages(substituter)
+
+ def _IsValidChild(self, child):
+ '''Returns true if 'child' is a valid child of this node.
+ Overridden by subclasses.'''
+ return False
+
+ def _IsValidAttribute(self, name, value):
+ '''Returns true if 'name' is the name of a valid attribute of this element
+ and 'value' is a valid value for that attribute. Overriden by
+ subclasses unless they have only mandatory attributes.'''
+ return (name in self.MandatoryAttributes() or
+ name in self.DefaultAttributes())
+
+ def _ContentType(self):
+ '''Returns the type of content this element can have. Overridden by
+ subclasses. The content type can be one of the _CONTENT_TYPE_XXX constants
+ above.'''
+ return self._CONTENT_TYPE_NONE
+
+ def MandatoryAttributes(self):
+ '''Returns a list of attribute names that are mandatory (non-optional)
+ on the current element. One can specify a list of
+ "mutually exclusive mandatory" attributes by specifying them as one
+ element in the list, separated by a "|" character.
+ '''
+ return []
+
+ def DefaultAttributes(self):
+ '''Returns a dictionary of attribute names that have defaults, mapped to
+ the default value. Overridden by subclasses.'''
+ return {}
+
+ def GetCliques(self):
+ '''Returns all MessageClique objects belonging to this node. Overridden
+ by subclasses.
+
+ Return:
+ [clique1, clique2] or []
+ '''
+ return []
+
+ def ToRealPath(self, path_from_basedir):
+ '''Returns a real path (which can be absolute or relative to the current
+ working directory), given a path that is relative to the base directory
+ set for the GRIT input file.
+
+ Args:
+ path_from_basedir: '..'
+
+ Return:
+ 'resource'
+ '''
+ return util.normpath(os.path.join(self.GetRoot().GetBaseDir(),
+ os.path.expandvars(path_from_basedir)))
+
+ def GetInputPath(self):
+ '''Returns a path, relative to the base directory set for the grd file,
+ that points to the file the node refers to.
+ '''
+ # This implementation works for most nodes that have an input file.
+ return self.attrs['file']
+
+ def UberClique(self):
+ '''Returns the uberclique that should be used for messages originating in
+ a given node. If the node itself has its uberclique set, that is what we
+ use, otherwise we search upwards until we find one. If we do not find one
+ even at the root node, we set the root node's uberclique to a new
+ uberclique instance.
+ '''
+ node = self
+ while not node.uberclique and node.parent:
+ node = node.parent
+ if not node.uberclique:
+ node.uberclique = clique.UberClique()
+ return node.uberclique
+
+ def IsTranslateable(self):
+ '''Returns false if the node has contents that should not be translated,
+ otherwise returns false (even if the node has no contents).
+ '''
+ if not 'translateable' in self.attrs:
+ return True
+ else:
+ return self.attrs['translateable'] == 'true'
+
+ def GetNodeById(self, id):
+ '''Returns the node in the subtree parented by this node that has a 'name'
+ attribute matching 'id'. Returns None if no such node is found.
+ '''
+ for node in self:
+ if 'name' in node.attrs and node.attrs['name'] == id:
+ return node
+ return None
+
+ def GetChildrenOfType(self, type):
+ '''Returns a list of all subnodes (recursing to all leaves) of this node
+ that are of the indicated type (or tuple of types).
+
+ Args:
+ type: A type you could use with isinstance().
+
+ Return:
+ A list, possibly empty.
+ '''
+ return [child for child in self if isinstance(child, type)]
+
+ def GetTextualIds(self):
+ '''Returns a list of the textual ids of this node.
+ '''
+ if 'name' in self.attrs:
+ return [self.attrs['name']]
+ return []
+
+ @classmethod
+ def EvaluateExpression(cls, expr, defs, target_platform, extra_variables=None):
+ '''Worker for EvaluateCondition (below) and conditions in XTB files.'''
+ cache_dict = cls.eval_expr_cache[
+ (tuple(defs.iteritems()), target_platform, extra_variables)]
+ if expr in cache_dict:
+ return cache_dict[expr]
+ def pp_ifdef(symbol):
+ return symbol in defs
+ def pp_if(symbol):
+ return defs.get(symbol, False)
+ variable_map = {
+ 'defs' : defs,
+ 'os': target_platform,
+ 'is_linux': target_platform.startswith('linux'),
+ 'is_macosx': target_platform == 'darwin',
+ 'is_win': target_platform in ('cygwin', 'win32'),
+ 'is_android': target_platform == 'android',
+ 'is_ios': target_platform == 'ios',
+ 'is_posix': (target_platform in ('darwin', 'linux2', 'linux3', 'sunos5',
+ 'android', 'ios')
+ or 'bsd' in target_platform),
+ 'pp_ifdef' : pp_ifdef,
+ 'pp_if' : pp_if,
+ }
+ if extra_variables:
+ variable_map.update(extra_variables)
+ eval_result = cache_dict[expr] = eval(expr, {}, variable_map)
+ return eval_result
+
+ def EvaluateCondition(self, expr):
+ '''Returns true if and only if the Python expression 'expr' evaluates
+ to true.
+
+ The expression is given a few local variables:
+ - 'lang' is the language currently being output
+ (the 'lang' attribute of the <output> element).
+ - 'context' is the current output context
+ (the 'context' attribute of the <output> element).
+ - 'defs' is a map of C preprocessor-style symbol names to their values.
+ - 'os' is the current platform (likely 'linux2', 'win32' or 'darwin').
+ - 'pp_ifdef(symbol)' is a shorthand for "symbol in defs".
+ - 'pp_if(symbol)' is a shorthand for "symbol in defs and defs[symbol]".
+ - 'is_linux', 'is_macosx', 'is_win', 'is_posix' are true if 'os'
+ matches the given platform.
+ '''
+ root = self.GetRoot()
+ lang = getattr(root, 'output_language', '')
+ context = getattr(root, 'output_context', '')
+ defs = getattr(root, 'defines', {})
+ target_platform = getattr(root, 'target_platform', '')
+ extra_variables = (
+ ('lang', lang),
+ ('context', context),
+ )
+ return Node.EvaluateExpression(
+ expr, defs, target_platform, extra_variables)
+
+ def OnlyTheseTranslations(self, languages):
+ '''Turns off loading of translations for languages not in the provided list.
+
+ Attrs:
+ languages: ['fr', 'zh_cn']
+ '''
+ for node in self:
+ if (hasattr(node, 'IsTranslation') and
+ node.IsTranslation() and
+ node.GetLang() not in languages):
+ node.DisableLoading()
+
+ def FindBooleanAttribute(self, attr, default, skip_self):
+ '''Searches all ancestors of the current node for the nearest enclosing
+ definition of the given boolean attribute.
+
+ Args:
+ attr: 'fallback_to_english'
+ default: What to return if no node defines the attribute.
+ skip_self: Don't check the current node, only its parents.
+ '''
+ p = self.parent if skip_self else self
+ while p:
+ value = p.attrs.get(attr, 'default').lower()
+ if value != 'default':
+ return (value == 'true')
+ p = p.parent
+ return default
+
+ def PseudoIsAllowed(self):
+ '''Returns true if this node is allowed to use pseudo-translations. This
+ is true by default, unless this node is within a <release> node that has
+ the allow_pseudo attribute set to false.
+ '''
+ return self.FindBooleanAttribute('allow_pseudo',
+ default=True, skip_self=True)
+
+ def ShouldFallbackToEnglish(self):
+ '''Returns true iff this node should fall back to English when
+ pseudotranslations are disabled and no translation is available for a
+ given message.
+ '''
+ return self.FindBooleanAttribute('fallback_to_english',
+ default=False, skip_self=True)
+
+ def WhitelistMarkedAsSkip(self):
+ '''Returns true if the node is marked to be skipped in the output by a
+ whitelist.
+ '''
+ return self._whitelist_marked_as_skip
+
+ def SetWhitelistMarkedAsSkip(self, mark_skipped):
+ '''Sets WhitelistMarkedAsSkip.
+ '''
+ self._whitelist_marked_as_skip = mark_skipped
+
+ def ExpandVariables(self):
+ '''Whether we need to expand variables on a given node.'''
+ return False
+
+
+class ContentNode(Node):
+ '''Convenience baseclass for nodes that can have content.'''
+ def _ContentType(self):
+ return self._CONTENT_TYPE_MIXED
+
diff --git a/chromium/tools/grit/grit/node/base_unittest.py b/chromium/tools/grit/grit/node/base_unittest.py
new file mode 100644
index 00000000000..63a2033272a
--- /dev/null
+++ b/chromium/tools/grit/grit/node/base_unittest.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for base.Node functionality (as used in various subclasses)'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import StringIO
+import unittest
+
+from grit import grd_reader
+from grit import util
+from grit.node import base
+from grit.node import message
+
+
+def MakePlaceholder(phname='BINGO'):
+ ph = message.PhNode()
+ ph.StartParsing(u'ph', None)
+ ph.HandleAttribute(u'name', phname)
+ ph.AppendContent(u'bongo')
+ ph.EndParsing()
+ return ph
+
+
+class NodeUnittest(unittest.TestCase):
+ def testWhitespaceHandling(self):
+ # We test using the Message node type.
+ node = message.MessageNode()
+ node.StartParsing(u'hello', None)
+ node.HandleAttribute(u'name', u'bla')
+ node.AppendContent(u" ''' two spaces ")
+ node.EndParsing()
+ self.failUnless(node.GetCdata() == u' two spaces')
+
+ node = message.MessageNode()
+ node.StartParsing(u'message', None)
+ node.HandleAttribute(u'name', u'bla')
+ node.AppendContent(u" two spaces ''' ")
+ node.EndParsing()
+ self.failUnless(node.GetCdata() == u'two spaces ')
+
+ def testWhitespaceHandlingWithChildren(self):
+ # We test using the Message node type.
+ node = message.MessageNode()
+ node.StartParsing(u'message', None)
+ node.HandleAttribute(u'name', u'bla')
+ node.AppendContent(u" ''' two spaces ")
+ node.AddChild(MakePlaceholder())
+ node.AppendContent(u' space before and after ')
+ node.AddChild(MakePlaceholder('BONGO'))
+ node.AppendContent(u" space before two after '''")
+ node.EndParsing()
+ self.failUnless(node.mixed_content[0] == u' two spaces ')
+ self.failUnless(node.mixed_content[2] == u' space before and after ')
+ self.failUnless(node.mixed_content[-1] == u' space before two after ')
+
+ def testXmlFormatMixedContent(self):
+ # Again test using the Message node type, because it is the only mixed
+ # content node.
+ node = message.MessageNode()
+ node.StartParsing(u'message', None)
+ node.HandleAttribute(u'name', u'name')
+ node.AppendContent(u'Hello <young> ')
+
+ ph = message.PhNode()
+ ph.StartParsing(u'ph', None)
+ ph.HandleAttribute(u'name', u'USERNAME')
+ ph.AppendContent(u'$1')
+ ex = message.ExNode()
+ ex.StartParsing(u'ex', None)
+ ex.AppendContent(u'Joi')
+ ex.EndParsing()
+ ph.AddChild(ex)
+ ph.EndParsing()
+
+ node.AddChild(ph)
+ node.EndParsing()
+
+ non_indented_xml = node.FormatXml()
+ self.failUnless(non_indented_xml == u'<message name="name">\n Hello '
+ u'&lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
+ u'\n</message>')
+
+ indented_xml = node.FormatXml(u' ')
+ self.failUnless(indented_xml == u' <message name="name">\n Hello '
+ u'&lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
+ u'\n </message>')
+
+ def testXmlFormatMixedContentWithLeadingWhitespace(self):
+ # Again test using the Message node type, because it is the only mixed
+ # content node.
+ node = message.MessageNode()
+ node.StartParsing(u'message', None)
+ node.HandleAttribute(u'name', u'name')
+ node.AppendContent(u"''' Hello <young> ")
+
+ ph = message.PhNode()
+ ph.StartParsing(u'ph', None)
+ ph.HandleAttribute(u'name', u'USERNAME')
+ ph.AppendContent(u'$1')
+ ex = message.ExNode()
+ ex.StartParsing(u'ex', None)
+ ex.AppendContent(u'Joi')
+ ex.EndParsing()
+ ph.AddChild(ex)
+ ph.EndParsing()
+
+ node.AddChild(ph)
+ node.AppendContent(u" yessiree '''")
+ node.EndParsing()
+
+ non_indented_xml = node.FormatXml()
+ self.failUnless(non_indented_xml ==
+ u"<message name=\"name\">\n ''' Hello"
+ u' &lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
+ u" yessiree '''\n</message>")
+
+ indented_xml = node.FormatXml(u' ')
+ self.failUnless(indented_xml ==
+ u" <message name=\"name\">\n ''' Hello"
+ u' &lt;young&gt; <ph name="USERNAME">$1<ex>Joi</ex></ph>'
+ u" yessiree '''\n </message>")
+
+ self.failUnless(node.GetNodeById('name'))
+
+ def testXmlFormatContentWithEntities(self):
+ '''Tests a bug where &nbsp; would not be escaped correctly.'''
+ from grit import tclib
+ msg_node = message.MessageNode.Construct(None, tclib.Message(
+ text = 'BEGIN_BOLDHelloWHITESPACEthere!END_BOLD Bingo!',
+ placeholders = [
+ tclib.Placeholder('BEGIN_BOLD', '<b>', 'bla'),
+ tclib.Placeholder('WHITESPACE', '&nbsp;', 'bla'),
+ tclib.Placeholder('END_BOLD', '</b>', 'bla')]),
+ 'BINGOBONGO')
+ xml = msg_node.FormatXml()
+ self.failUnless(xml.find('&nbsp;') == -1, 'should have no entities')
+
+ def testIter(self):
+ # First build a little tree of message and ph nodes.
+ node = message.MessageNode()
+ node.StartParsing(u'message', None)
+ node.HandleAttribute(u'name', u'bla')
+ node.AppendContent(u" ''' two spaces ")
+ node.AppendContent(u' space before and after ')
+ ph = message.PhNode()
+ ph.StartParsing(u'ph', None)
+ ph.AddChild(message.ExNode())
+ ph.HandleAttribute(u'name', u'BINGO')
+ ph.AppendContent(u'bongo')
+ node.AddChild(ph)
+ node.AddChild(message.PhNode())
+ node.AppendContent(u" space before two after '''")
+
+ order = [message.MessageNode, message.PhNode, message.ExNode, message.PhNode]
+ for n in node:
+ self.failUnless(type(n) == order[0])
+ order = order[1:]
+ self.failUnless(len(order) == 0)
+
+ def testGetChildrenOfType(self):
+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US"
+ current_release="3" base_dir=".">
+ <outputs>
+ <output filename="resource.h" type="rc_header" />
+ <output filename="en/generated_resources.rc" type="rc_all"
+ lang="en" />
+ <if expr="pp_if('NOT_TRUE')">
+ <output filename="de/generated_resources.rc" type="rc_all"
+ lang="de" />
+ </if>
+ </outputs>
+ <release seq="3">
+ <messages>
+ <message name="ID_HELLO">Hello!</message>
+ </messages>
+ </release>
+ </grit>'''
+ grd = grd_reader.Parse(StringIO.StringIO(xml),
+ util.PathFromRoot('grit/test/data'))
+ from grit.node import io
+ output_nodes = grd.GetChildrenOfType(io.OutputNode)
+ self.failUnlessEqual(len(output_nodes), 3)
+ self.failUnlessEqual(output_nodes[2].attrs['filename'],
+ 'de/generated_resources.rc')
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/node/custom/__init__.py b/chromium/tools/grit/grit/node/custom/__init__.py
new file mode 100644
index 00000000000..3e13ca131d5
--- /dev/null
+++ b/chromium/tools/grit/grit/node/custom/__init__.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Package 'grit.node.custom'
+'''
+
+pass
diff --git a/chromium/tools/grit/grit/node/custom/filename.py b/chromium/tools/grit/grit/node/custom/filename.py
new file mode 100644
index 00000000000..79a7744f2eb
--- /dev/null
+++ b/chromium/tools/grit/grit/node/custom/filename.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''A CustomType for filenames.'''
+
+from grit import clique
+from grit import lazy_re
+
+
+class WindowsFilename(clique.CustomType):
+ '''Validates that messages can be used as Windows filenames, and strips
+ illegal characters out of translations.
+ '''
+
+ BANNED = lazy_re.compile('\+|:|\/|\\\\|\*|\?|\"|\<|\>|\|')
+
+ def Validate(self, message):
+ return not self.BANNED.search(message.GetPresentableContent())
+
+ def ValidateAndModify(self, lang, translation):
+ is_ok = self.Validate(translation)
+ self.ModifyEachTextPart(lang, translation)
+ return is_ok
+
+ def ModifyTextPart(self, lang, text):
+ return self.BANNED.sub(' ', text)
diff --git a/chromium/tools/grit/grit/node/custom/filename_unittest.py b/chromium/tools/grit/grit/node/custom/filename_unittest.py
new file mode 100644
index 00000000000..9099086f36e
--- /dev/null
+++ b/chromium/tools/grit/grit/node/custom/filename_unittest.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.node.custom.filename'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../../..'))
+
+import unittest
+from grit.node.custom import filename
+from grit import clique
+from grit import tclib
+
+
+class WindowsFilenameUnittest(unittest.TestCase):
+
+ def testValidate(self):
+ factory = clique.UberClique()
+ msg = tclib.Message(text='Bingo bongo')
+ c = factory.MakeClique(msg)
+ c.SetCustomType(filename.WindowsFilename())
+ translation = tclib.Translation(id=msg.GetId(), text='Bilingo bolongo:')
+ c.AddTranslation(translation, 'fr')
+ self.failUnless(c.MessageForLanguage('fr').GetRealContent() == 'Bilingo bolongo ')
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/node/empty.py b/chromium/tools/grit/grit/node/empty.py
new file mode 100644
index 00000000000..b3759a27ceb
--- /dev/null
+++ b/chromium/tools/grit/grit/node/empty.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Container nodes that don't have any logic.
+'''
+
+
+from grit.node import base
+from grit.node import include
+from grit.node import structure
+from grit.node import message
+from grit.node import io
+from grit.node import misc
+
+
+class GroupingNode(base.Node):
+ '''Base class for all the grouping elements (<structures>, <includes>,
+ <messages> and <identifiers>).'''
+ def DefaultAttributes(self):
+ return {
+ 'first_id' : '',
+ 'comment' : '',
+ 'fallback_to_english' : 'false',
+ 'fallback_to_low_resolution' : 'false',
+ }
+
+
+class IncludesNode(GroupingNode):
+ '''The <includes> element.'''
+ def _IsValidChild(self, child):
+ return isinstance(child, (include.IncludeNode, misc.IfNode, misc.PartNode))
+
+
+class MessagesNode(GroupingNode):
+ '''The <messages> element.'''
+ def _IsValidChild(self, child):
+ return isinstance(child, (message.MessageNode, misc.IfNode, misc.PartNode))
+
+
+class StructuresNode(GroupingNode):
+ '''The <structures> element.'''
+ def _IsValidChild(self, child):
+ return isinstance(child, (structure.StructureNode,
+ misc.IfNode, misc.PartNode))
+
+
+class TranslationsNode(base.Node):
+ '''The <translations> element.'''
+ def _IsValidChild(self, child):
+ return isinstance(child, (io.FileNode, misc.IfNode, misc.PartNode))
+
+
+class OutputsNode(base.Node):
+ '''The <outputs> element.'''
+ def _IsValidChild(self, child):
+ return isinstance(child, (io.OutputNode, misc.IfNode, misc.PartNode))
+
+
+class IdentifiersNode(GroupingNode):
+ '''The <identifiers> element.'''
+ def _IsValidChild(self, child):
+ return isinstance(child, misc.IdentifierNode)
diff --git a/chromium/tools/grit/grit/node/include.py b/chromium/tools/grit/grit/node/include.py
new file mode 100644
index 00000000000..9c3685f5692
--- /dev/null
+++ b/chromium/tools/grit/grit/node/include.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Handling of the <include> element.
+"""
+
+import os
+
+import grit.format.html_inline
+import grit.format.rc_header
+import grit.format.rc
+
+from grit.node import base
+from grit import util
+
+class IncludeNode(base.Node):
+ """An <include> element."""
+ def __init__(self):
+ super(IncludeNode, self).__init__()
+
+ # Cache flattened data so that we don't flatten the same file
+ # multiple times.
+ self._flattened_data = None
+ # Also keep track of the last filename we flattened to, so we can
+ # avoid doing it more than once.
+ self._last_flat_filename = None
+
+ def _IsValidChild(self, child):
+ return False
+
+ def _GetFlattenedData(self, allow_external_script=False):
+ if not self._flattened_data:
+ filename = self.ToRealPath(self.GetInputPath())
+ self._flattened_data = (
+ grit.format.html_inline.InlineToString(filename, self,
+ allow_external_script=allow_external_script))
+ return self._flattened_data
+
+ def MandatoryAttributes(self):
+ return ['name', 'type', 'file']
+
+ def DefaultAttributes(self):
+ return {'translateable' : 'true',
+ 'generateid': 'true',
+ 'filenameonly': 'false',
+ 'mkoutput': 'false',
+ 'flattenhtml': 'false',
+ 'allowexternalscript': 'false',
+ 'relativepath': 'false',
+ 'use_base_dir': 'true',
+ }
+
+ def GetInputPath(self):
+ # Do not mess with absolute paths, that would make them invalid.
+ if os.path.isabs(os.path.expandvars(self.attrs['file'])):
+ return self.attrs['file']
+
+ # We have no control over code that calles ToRealPath later, so convert
+ # the path to be relative against our basedir.
+ if self.attrs.get('use_base_dir', 'true') != 'true':
+ return os.path.relpath(self.attrs['file'], self.GetRoot().GetBaseDir())
+
+ return self.attrs['file']
+
+ def FileForLanguage(self, lang, output_dir):
+ """Returns the file for the specified language. This allows us to return
+ different files for different language variants of the include file.
+ """
+ return self.ToRealPath(self.GetInputPath())
+
+ def GetDataPackPair(self, lang, encoding):
+ """Returns a (id, string) pair that represents the resource id and raw
+ bytes of the data. This is used to generate the data pack data file.
+ """
+ # TODO(benrg/joi): Move this and other implementations of GetDataPackPair
+ # to grit.format.data_pack?
+ from grit.format import rc_header
+ id_map = rc_header.GetIds(self.GetRoot())
+ id = id_map[self.GetTextualIds()[0]]
+ if self.attrs['flattenhtml'] == 'true':
+ allow_external_script = self.attrs['allowexternalscript'] == 'true'
+ data = self._GetFlattenedData(allow_external_script=allow_external_script)
+ else:
+ filename = self.ToRealPath(self.GetInputPath())
+ data = util.ReadFile(filename, util.BINARY)
+
+ # Include does not care about the encoding, because it only returns binary
+ # data.
+ return id, data
+
+ def Process(self, output_dir):
+ """Rewrite file references to be base64 encoded data URLs. The new file
+ will be written to output_dir and the name of the new file is returned."""
+ filename = self.ToRealPath(self.GetInputPath())
+ flat_filename = os.path.join(output_dir,
+ self.attrs['name'] + '_' + os.path.basename(filename))
+
+ if self._last_flat_filename == flat_filename:
+ return
+
+ with open(flat_filename, 'wb') as outfile:
+ outfile.write(self._GetFlattenedData())
+
+ self._last_flat_filename = flat_filename
+ return os.path.basename(flat_filename)
+
+ def GetHtmlResourceFilenames(self):
+ """Returns a set of all filenames inlined by this file."""
+ allow_external_script = self.attrs['allowexternalscript'] == 'true'
+ return grit.format.html_inline.GetResourceFilenames(
+ self.ToRealPath(self.GetInputPath()),
+ allow_external_script=allow_external_script)
+
+ @staticmethod
+ def Construct(parent, name, type, file, translateable=True,
+ filenameonly=False, mkoutput=False, relativepath=False):
+ """Creates a new node which is a child of 'parent', with attributes set
+ by parameters of the same name.
+ """
+ # Convert types to appropriate strings
+ translateable = util.BoolToString(translateable)
+ filenameonly = util.BoolToString(filenameonly)
+ mkoutput = util.BoolToString(mkoutput)
+ relativepath = util.BoolToString(relativepath)
+
+ node = IncludeNode()
+ node.StartParsing('include', parent)
+ node.HandleAttribute('name', name)
+ node.HandleAttribute('type', type)
+ node.HandleAttribute('file', file)
+ node.HandleAttribute('translateable', translateable)
+ node.HandleAttribute('filenameonly', filenameonly)
+ node.HandleAttribute('mkoutput', mkoutput)
+ node.HandleAttribute('relativepath', relativepath)
+ node.EndParsing()
+ return node
diff --git a/chromium/tools/grit/grit/node/include_unittest.py b/chromium/tools/grit/grit/node/include_unittest.py
new file mode 100644
index 00000000000..e5544281fd0
--- /dev/null
+++ b/chromium/tools/grit/grit/node/include_unittest.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for include.IncludeNode'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import os
+import StringIO
+import unittest
+
+from grit.node import misc
+from grit.node import include
+from grit.node import empty
+from grit import grd_reader
+from grit import util
+
+
+class IncludeNodeUnittest(unittest.TestCase):
+ def testGetPath(self):
+ root = misc.GritNode()
+ root.StartParsing(u'grit', None)
+ root.HandleAttribute(u'latest_public_release', u'0')
+ root.HandleAttribute(u'current_release', u'1')
+ root.HandleAttribute(u'base_dir', ur'..\resource')
+ release = misc.ReleaseNode()
+ release.StartParsing(u'release', root)
+ release.HandleAttribute(u'seq', u'1')
+ root.AddChild(release)
+ includes = empty.IncludesNode()
+ includes.StartParsing(u'includes', release)
+ release.AddChild(includes)
+ include_node = include.IncludeNode()
+ include_node.StartParsing(u'include', includes)
+ include_node.HandleAttribute(u'file', ur'flugel\kugel.pdf')
+ includes.AddChild(include_node)
+ root.EndParsing()
+
+ self.assertEqual(root.ToRealPath(include_node.GetInputPath()),
+ util.normpath(
+ os.path.join(ur'../resource', ur'flugel/kugel.pdf')))
+
+ def testGetPathNoBasedir(self):
+ root = misc.GritNode()
+ root.StartParsing(u'grit', None)
+ root.HandleAttribute(u'latest_public_release', u'0')
+ root.HandleAttribute(u'current_release', u'1')
+ root.HandleAttribute(u'base_dir', ur'..\resource')
+ release = misc.ReleaseNode()
+ release.StartParsing(u'release', root)
+ release.HandleAttribute(u'seq', u'1')
+ root.AddChild(release)
+ includes = empty.IncludesNode()
+ includes.StartParsing(u'includes', release)
+ release.AddChild(includes)
+ include_node = include.IncludeNode()
+ include_node.StartParsing(u'include', includes)
+ include_node.HandleAttribute(u'file', ur'flugel\kugel.pdf')
+ include_node.HandleAttribute(u'use_base_dir', u'false')
+ includes.AddChild(include_node)
+ root.EndParsing()
+
+ self.assertEqual(root.ToRealPath(include_node.GetInputPath()),
+ util.normpath(
+ os.path.join(ur'../', ur'flugel/kugel.pdf')))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/node/io.py b/chromium/tools/grit/grit/node/io.py
new file mode 100644
index 00000000000..1e590c56b98
--- /dev/null
+++ b/chromium/tools/grit/grit/node/io.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The <output> and <file> elements.
+'''
+
+import os
+
+import grit.format.rc_header
+
+from grit import xtb_reader
+from grit.node import base
+
+
+class FileNode(base.Node):
+ '''A <file> element.'''
+
+ def __init__(self):
+ super(FileNode, self).__init__()
+ self.re = None
+ self.should_load_ = True
+
+ def IsTranslation(self):
+ return True
+
+ def GetLang(self):
+ return self.attrs['lang']
+
+ def DisableLoading(self):
+ self.should_load_ = False
+
+ def MandatoryAttributes(self):
+ return ['path', 'lang']
+
+ def RunPostSubstitutionGatherer(self, debug=False):
+ if not self.should_load_:
+ return
+
+ root = self.GetRoot()
+ defs = getattr(root, 'defines', {})
+ target_platform = getattr(root, 'target_platform', '')
+
+ xtb_file = open(self.ToRealPath(self.GetInputPath()))
+ try:
+ lang = xtb_reader.Parse(xtb_file,
+ self.UberClique().GenerateXtbParserCallback(
+ self.attrs['lang'], debug=debug),
+ defs=defs,
+ target_platform=target_platform)
+ except:
+ print "Exception during parsing of %s" % self.GetInputPath()
+ raise
+ # We special case 'he' and 'iw' because the translation console uses 'iw'
+ # and we use 'he'.
+ assert (lang == self.attrs['lang'] or
+ (lang == 'iw' and self.attrs['lang'] == 'he')), ('The XTB file you '
+ 'reference must contain messages in the language specified\n'
+ 'by the \'lang\' attribute.')
+
+ def GetInputPath(self):
+ return os.path.expandvars(self.attrs['path'])
+
+
+class OutputNode(base.Node):
+ '''An <output> element.'''
+
+ def MandatoryAttributes(self):
+ return ['filename', 'type']
+
+ def DefaultAttributes(self):
+ return {
+ 'lang' : '', # empty lang indicates all languages
+ 'language_section' : 'neutral', # defines a language neutral section
+ 'context' : '',
+ }
+
+ def GetType(self):
+ return self.attrs['type']
+
+ def GetLanguage(self):
+ '''Returns the language ID, default 'en'.'''
+ return self.attrs['lang']
+
+ def GetContext(self):
+ return self.attrs['context']
+
+ def GetFilename(self):
+ return self.attrs['filename']
+
+ def GetOutputFilename(self):
+ path = None
+ if hasattr(self, 'output_filename'):
+ path = self.output_filename
+ else:
+ path = self.attrs['filename']
+ return os.path.expandvars(path)
+
+ def _IsValidChild(self, child):
+ return isinstance(child, EmitNode)
+
+class EmitNode(base.ContentNode):
+ ''' An <emit> element.'''
+
+ def DefaultAttributes(self):
+ return { 'emit_type' : 'prepend'}
+
+ def GetEmitType(self):
+ '''Returns the emit_type for this node. Default is 'append'.'''
+ return self.attrs['emit_type']
+
diff --git a/chromium/tools/grit/grit/node/io_unittest.py b/chromium/tools/grit/grit/node/io_unittest.py
new file mode 100644
index 00000000000..07298d751de
--- /dev/null
+++ b/chromium/tools/grit/grit/node/io_unittest.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for io.FileNode'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import os
+import StringIO
+import unittest
+
+from grit.node import misc
+from grit.node import io
+from grit.node import empty
+from grit import grd_reader
+from grit import util
+
+
+class FileNodeUnittest(unittest.TestCase):
+ def testGetPath(self):
+ root = misc.GritNode()
+ root.StartParsing(u'grit', None)
+ root.HandleAttribute(u'latest_public_release', u'0')
+ root.HandleAttribute(u'current_release', u'1')
+ root.HandleAttribute(u'base_dir', ur'..\resource')
+ translations = empty.TranslationsNode()
+ translations.StartParsing(u'translations', root)
+ root.AddChild(translations)
+ file_node = io.FileNode()
+ file_node.StartParsing(u'file', translations)
+ file_node.HandleAttribute(u'path', ur'flugel\kugel.pdf')
+ translations.AddChild(file_node)
+ root.EndParsing()
+
+ self.failUnless(root.ToRealPath(file_node.GetInputPath()) ==
+ util.normpath(
+ os.path.join(ur'../resource', ur'flugel/kugel.pdf')))
+
+ def VerifyCliquesContainEnglishAndFrenchAndNothingElse(self, cliques):
+ for clique in cliques:
+ self.failUnlessEquals(len(clique[0].clique), 2)
+ self.failUnless('en' in cliques[i][0].clique)
+ self.failUnless('fr' in cliques[i][0].clique)
+
+ def testLoadTranslations(self):
+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <translations>
+ <file path="generated_resources_fr.xtb" lang="fr" />
+ </translations>
+ <release seq="3">
+ <messages>
+ <message name="ID_HELLO">Hello!</message>
+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
+ </messages>
+ </release>
+ </grit>'''
+ grd = grd_reader.Parse(StringIO.StringIO(xml),
+ util.PathFromRoot('grit/testdata'))
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+ self.VerifyCliquesContainEnglishAndFrenchAndNothingElse(grd.GetCliques())
+
+ def testIffyness(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <translations>
+ <if expr="lang == 'fr'">
+ <file path="generated_resources_fr.xtb" lang="fr" />
+ </if>
+ </translations>
+ <release seq="3">
+ <messages>
+ <message name="ID_HELLO">Hello!</message>
+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
+ </messages>
+ </release>
+ </grit>'''), util.PathFromRoot('grit/testdata'))
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+
+ grd.SetOutputLanguage('fr')
+ grd.RunGatherers()
+
+ def testConditionalLoadTranslations(self):
+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
+ base_dir=".">
+ <translations>
+ <if expr="True">
+ <file path="generated_resources_fr.xtb" lang="fr" />
+ </if>
+ <if expr="False">
+ <file path="no_such_file.xtb" lang="de" />
+ </if>
+ </translations>
+ <release seq="3">
+ <messages>
+ <message name="ID_HELLO">Hello!</message>
+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
+ Joi</ex></ph></message>
+ </messages>
+ </release>
+ </grit>'''
+ grd = grd_reader.Parse(StringIO.StringIO(xml),
+ util.PathFromRoot('grit/testdata'))
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+ self.VerifyCliquesContainEnglishAndFrenchAndNothingElse(grd.GetCliques())
+
+ def testConditionalOutput(self):
+ xml = '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
+ base_dir=".">
+ <outputs>
+ <output filename="resource.h" type="rc_header" />
+ <output filename="en/generated_resources.rc" type="rc_all"
+ lang="en" />
+ <if expr="pp_if('NOT_TRUE')">
+ <output filename="de/generated_resources.rc" type="rc_all"
+ lang="de" />
+ </if>
+ </outputs>
+ <release seq="3">
+ <messages>
+ <message name="ID_HELLO">Hello!</message>
+ </messages>
+ </release>
+ </grit>'''
+ grd = grd_reader.Parse(StringIO.StringIO(xml),
+ util.PathFromRoot('grit/test/data'),
+ defines={})
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+ outputs = grd.GetChildrenOfType(io.OutputNode)
+ active = set(grd.ActiveDescendants())
+ self.failUnless(outputs[0] in active)
+ self.failUnless(outputs[0].GetType() == 'rc_header')
+ self.failUnless(outputs[1] in active)
+ self.failUnless(outputs[1].GetType() == 'rc_all')
+ self.failUnless(outputs[2] not in active)
+ self.failUnless(outputs[2].GetType() == 'rc_all')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/node/mapping.py b/chromium/tools/grit/grit/node/mapping.py
new file mode 100644
index 00000000000..259be97c6b2
--- /dev/null
+++ b/chromium/tools/grit/grit/node/mapping.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Maps each node type to an implementation class.
+When adding a new node type, you add to this mapping.
+'''
+
+
+from grit import exception
+
+from grit.node import empty
+from grit.node import message
+from grit.node import misc
+from grit.node import variant
+from grit.node import structure
+from grit.node import include
+from grit.node import io
+
+
+_ELEMENT_TO_CLASS = {
+ 'identifiers' : empty.IdentifiersNode,
+ 'includes' : empty.IncludesNode,
+ 'messages' : empty.MessagesNode,
+ 'outputs' : empty.OutputsNode,
+ 'structures' : empty.StructuresNode,
+ 'translations' : empty.TranslationsNode,
+ 'include' : include.IncludeNode,
+ 'emit' : io.EmitNode,
+ 'file' : io.FileNode,
+ 'output' : io.OutputNode,
+ 'ex' : message.ExNode,
+ 'message' : message.MessageNode,
+ 'ph' : message.PhNode,
+ 'else' : misc.ElseNode,
+ 'grit' : misc.GritNode,
+ 'identifier' : misc.IdentifierNode,
+ 'if' : misc.IfNode,
+ 'part' : misc.PartNode,
+ 'release' : misc.ReleaseNode,
+ 'then' : misc.ThenNode,
+ 'structure' : structure.StructureNode,
+ 'skeleton' : variant.SkeletonNode,
+}
+
+
+def ElementToClass(name, typeattr):
+ '''Maps an element to a class that handles the element.
+
+ Args:
+ name: 'element' (the name of the element)
+ typeattr: 'type' (the value of the type attribute, if present, else None)
+
+ Return:
+ type
+ '''
+ if name not in _ELEMENT_TO_CLASS:
+ raise exception.UnknownElement()
+ return _ELEMENT_TO_CLASS[name]
+
diff --git a/chromium/tools/grit/grit/node/message.py b/chromium/tools/grit/grit/node/message.py
new file mode 100644
index 00000000000..ca80f41be97
--- /dev/null
+++ b/chromium/tools/grit/grit/node/message.py
@@ -0,0 +1,294 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Handling of the <message> element.
+'''
+
+import re
+import types
+
+from grit.node import base
+
+import grit.format.rc_header
+import grit.format.rc
+
+from grit import clique
+from grit import exception
+from grit import lazy_re
+from grit import tclib
+from grit import util
+
+# Finds whitespace at the start and end of a string which can be multiline.
+_WHITESPACE = lazy_re.compile('(?P<start>\s*)(?P<body>.+?)(?P<end>\s*)\Z',
+ re.DOTALL | re.MULTILINE)
+
+
+class MessageNode(base.ContentNode):
+ '''A <message> element.'''
+
+ # For splitting a list of things that can be separated by commas or
+ # whitespace
+ _SPLIT_RE = lazy_re.compile('\s*,\s*|\s+')
+
+ def __init__(self):
+ super(MessageNode, self).__init__()
+ # Valid after EndParsing, this is the MessageClique that contains the
+ # source message and any translations of it that have been loaded.
+ self.clique = None
+
+ # We don't send leading and trailing whitespace into the translation
+ # console, but rather tack it onto the source message and any
+ # translations when formatting them into RC files or what have you.
+ self.ws_at_start = '' # Any whitespace characters at the start of the text
+ self.ws_at_end = '' # --"-- at the end of the text
+
+ # A list of "shortcut groups" this message is in. We check to make sure
+ # that shortcut keys (e.g. &J) within each shortcut group are unique.
+ self.shortcut_groups_ = []
+
+ # Formatter-specific data used to control the output of individual strings.
+ # formatter_data is a space separated list of C preprocessor-style
+ # definitions. Names without values are given the empty string value.
+ # Example: "foo=5 bar baz=100"
+ self.formatter_data = {}
+
+ def _IsValidChild(self, child):
+ return isinstance(child, (PhNode))
+
+ def _IsValidAttribute(self, name, value):
+ if name not in ['name', 'offset', 'translateable', 'desc', 'meaning',
+ 'internal_comment', 'shortcut_groups', 'custom_type',
+ 'validation_expr', 'use_name_for_id', 'sub_variable',
+ 'formatter_data']:
+ return False
+ if (name in ('translateable', 'sub_variable') and
+ value not in ['true', 'false']):
+ return False
+ return True
+
+ def MandatoryAttributes(self):
+ return ['name|offset']
+
+ def DefaultAttributes(self):
+ return {
+ 'custom_type' : '',
+ 'desc' : '',
+ 'formatter_data' : '',
+ 'internal_comment' : '',
+ 'meaning' : '',
+ 'shortcut_groups' : '',
+ 'sub_variable' : 'false',
+ 'translateable' : 'true',
+ 'use_name_for_id' : 'false',
+ 'validation_expr' : '',
+ }
+
+ def HandleAttribute(self, attrib, value):
+ base.ContentNode.HandleAttribute(self, attrib, value)
+ if attrib == 'formatter_data':
+ # Parse value, a space-separated list of defines, into a dict.
+ # Example: "foo=5 bar" -> {'foo':'5', 'bar':''}
+ for item in value.split():
+ name, sep, val = item.partition('=')
+ self.formatter_data[name] = val
+
+ def GetTextualIds(self):
+ '''
+ Returns the concatenation of the parent's node first_id and
+ this node's offset if it has one, otherwise just call the
+ superclass' implementation
+ '''
+ if 'offset' in self.attrs:
+ # we search for the first grouping node in the parents' list
+ # to take care of the case where the first parent is an <if> node
+ grouping_parent = self.parent
+ import grit.node.empty
+ while grouping_parent and not isinstance(grouping_parent,
+ grit.node.empty.GroupingNode):
+ grouping_parent = grouping_parent.parent
+
+ assert 'first_id' in grouping_parent.attrs
+ return [grouping_parent.attrs['first_id'] + '_' + self.attrs['offset']]
+ else:
+ return super(MessageNode, self).GetTextualIds()
+
+ def IsTranslateable(self):
+ return self.attrs['translateable'] == 'true'
+
+ def EndParsing(self):
+ super(MessageNode, self).EndParsing()
+
+ # Make the text (including placeholder references) and list of placeholders,
+ # then strip and store leading and trailing whitespace and create the
+ # tclib.Message() and a clique to contain it.
+
+ text = ''
+ placeholders = []
+ for item in self.mixed_content:
+ if isinstance(item, types.StringTypes):
+ text += item
+ else:
+ presentation = item.attrs['name'].upper()
+ text += presentation
+ ex = ' '
+ if len(item.children):
+ ex = item.children[0].GetCdata()
+ original = item.GetCdata()
+ placeholders.append(tclib.Placeholder(presentation, original, ex))
+
+ m = _WHITESPACE.match(text)
+ if m:
+ self.ws_at_start = m.group('start')
+ self.ws_at_end = m.group('end')
+ text = m.group('body')
+
+ self.shortcut_groups_ = self._SPLIT_RE.split(self.attrs['shortcut_groups'])
+ self.shortcut_groups_ = [i for i in self.shortcut_groups_ if i != '']
+
+ description_or_id = self.attrs['desc']
+ if description_or_id == '' and 'name' in self.attrs:
+ description_or_id = 'ID: %s' % self.attrs['name']
+
+ assigned_id = None
+ if self.attrs['use_name_for_id'] == 'true':
+ assigned_id = self.attrs['name']
+ message = tclib.Message(text=text, placeholders=placeholders,
+ description=description_or_id,
+ meaning=self.attrs['meaning'],
+ assigned_id=assigned_id)
+ self.InstallMessage(message)
+
+ def InstallMessage(self, message):
+ '''Sets this node's clique from a tclib.Message instance.
+
+ Args:
+ message: A tclib.Message.
+ '''
+ self.clique = self.UberClique().MakeClique(message, self.IsTranslateable())
+ for group in self.shortcut_groups_:
+ self.clique.AddToShortcutGroup(group)
+ if self.attrs['custom_type'] != '':
+ self.clique.SetCustomType(util.NewClassInstance(self.attrs['custom_type'],
+ clique.CustomType))
+ elif self.attrs['validation_expr'] != '':
+ self.clique.SetCustomType(
+ clique.OneOffCustomType(self.attrs['validation_expr']))
+
+ def SubstituteMessages(self, substituter):
+ '''Applies substitution to this message.
+
+ Args:
+ substituter: a grit.util.Substituter object.
+ '''
+ message = substituter.SubstituteMessage(self.clique.GetMessage())
+ if message is not self.clique.GetMessage():
+ self.InstallMessage(message)
+
+ def GetCliques(self):
+ if self.clique:
+ return [self.clique]
+ else:
+ return []
+
+ def Translate(self, lang):
+ '''Returns a translated version of this message.
+ '''
+ assert self.clique
+ msg = self.clique.MessageForLanguage(lang,
+ self.PseudoIsAllowed(),
+ self.ShouldFallbackToEnglish()
+ ).GetRealContent()
+ return msg.replace('[GRITLANGCODE]', lang)
+
+ def NameOrOffset(self):
+ if 'name' in self.attrs:
+ return self.attrs['name']
+ else:
+ return self.attrs['offset']
+
+ def ExpandVariables(self):
+ '''We always expand variables on Messages.'''
+ return True
+
+ def GetDataPackPair(self, lang, encoding):
+ '''Returns a (id, string) pair that represents the string id and the string
+ in the specified encoding, where |encoding| is one of the encoding values
+ accepted by util.Encode. This is used to generate the data pack data file.
+ '''
+ from grit.format import rc_header
+ id_map = rc_header.GetIds(self.GetRoot())
+ id = id_map[self.GetTextualIds()[0]]
+
+ message = self.ws_at_start + self.Translate(lang) + self.ws_at_end
+ return id, util.Encode(message, encoding)
+
+ @staticmethod
+ def Construct(parent, message, name, desc='', meaning='', translateable=True):
+ '''Constructs a new message node that is a child of 'parent', with the
+ name, desc, meaning and translateable attributes set using the same-named
+ parameters and the text of the message and any placeholders taken from
+ 'message', which must be a tclib.Message() object.'''
+ # Convert type to appropriate string
+ translateable = 'true' if translateable else 'false'
+
+ node = MessageNode()
+ node.StartParsing('message', parent)
+ node.HandleAttribute('name', name)
+ node.HandleAttribute('desc', desc)
+ node.HandleAttribute('meaning', meaning)
+ node.HandleAttribute('translateable', translateable)
+
+ items = message.GetContent()
+ for ix, item in enumerate(items):
+ if isinstance(item, types.StringTypes):
+ # Ensure whitespace at front and back of message is correctly handled.
+ if ix == 0:
+ item = "'''" + item
+ if ix == len(items) - 1:
+ item = item + "'''"
+
+ node.AppendContent(item)
+ else:
+ phnode = PhNode()
+ phnode.StartParsing('ph', node)
+ phnode.HandleAttribute('name', item.GetPresentation())
+ phnode.AppendContent(item.GetOriginal())
+
+ if len(item.GetExample()) and item.GetExample() != ' ':
+ exnode = ExNode()
+ exnode.StartParsing('ex', phnode)
+ exnode.AppendContent(item.GetExample())
+ exnode.EndParsing()
+ phnode.AddChild(exnode)
+
+ phnode.EndParsing()
+ node.AddChild(phnode)
+
+ node.EndParsing()
+ return node
+
+class PhNode(base.ContentNode):
+ '''A <ph> element.'''
+
+ def _IsValidChild(self, child):
+ return isinstance(child, ExNode)
+
+ def MandatoryAttributes(self):
+ return ['name']
+
+ def EndParsing(self):
+ super(PhNode, self).EndParsing()
+ # We only allow a single example for each placeholder
+ if len(self.children) > 1:
+ raise exception.TooManyExamples()
+
+ def GetTextualIds(self):
+ # The 'name' attribute is not an ID.
+ return []
+
+
+class ExNode(base.ContentNode):
+ '''An <ex> element.'''
+ pass
diff --git a/chromium/tools/grit/grit/node/message_unittest.py b/chromium/tools/grit/grit/node/message_unittest.py
new file mode 100644
index 00000000000..a058257a74c
--- /dev/null
+++ b/chromium/tools/grit/grit/node/message_unittest.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.node.message'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit import tclib
+from grit import util
+from grit.node import message
+
+class MessageUnittest(unittest.TestCase):
+ def testMessage(self):
+ root = util.ParseGrdForUnittest('''
+ <messages>
+ <message name="IDS_GREETING"
+ desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ </messages>''')
+ msg, = root.GetChildrenOfType(message.MessageNode)
+ cliques = msg.GetCliques()
+ content = cliques[0].GetMessage().GetPresentableContent()
+ self.failUnless(content == 'Hello USERNAME, how are you doing today?')
+
+ def testMessageWithWhitespace(self):
+ root = util.ParseGrdForUnittest("""\
+ <messages>
+ <message name="IDS_BLA" desc="">
+ ''' Hello there <ph name="USERNAME">%s</ph> '''
+ </message>
+ </messages>""")
+ msg, = root.GetChildrenOfType(message.MessageNode)
+ content = msg.GetCliques()[0].GetMessage().GetPresentableContent()
+ self.failUnless(content == 'Hello there USERNAME')
+ self.failUnless(msg.ws_at_start == ' ')
+ self.failUnless(msg.ws_at_end == ' ')
+
+ def testConstruct(self):
+ msg = tclib.Message(text=" Hello USERNAME, how are you? BINGO\t\t",
+ placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi'),
+ tclib.Placeholder('BINGO', '%d', '11')])
+ msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO')
+ self.failUnless(msg_node.children[0].name == 'ph')
+ self.failUnless(msg_node.children[0].children[0].name == 'ex')
+ self.failUnless(msg_node.children[0].children[0].GetCdata() == 'Joi')
+ self.failUnless(msg_node.children[1].children[0].GetCdata() == '11')
+ self.failUnless(msg_node.ws_at_start == ' ')
+ self.failUnless(msg_node.ws_at_end == '\t\t')
+
+ def testUnicodeConstruct(self):
+ text = u'Howdie \u00fe'
+ msg = tclib.Message(text=text)
+ msg_node = message.MessageNode.Construct(None, msg, 'BINGOBONGO')
+ msg_from_node = msg_node.GetCdata()
+ self.failUnless(msg_from_node == text)
+
+ def testFormatterData(self):
+ root = util.ParseGrdForUnittest("""\
+ <messages>
+ <message name="IDS_BLA" desc="" formatter_data=" foo=123 bar qux=low">
+ Text
+ </message>
+ </messages>""")
+ msg, = root.GetChildrenOfType(message.MessageNode)
+ expected_formatter_data = {
+ 'foo': '123',
+ 'bar': '',
+ 'qux': 'low'}
+
+ # Can't use assertDictEqual, not available in Python 2.6, so do it
+ # by hand.
+ self.failUnlessEqual(len(expected_formatter_data),
+ len(msg.formatter_data))
+ for key in expected_formatter_data:
+ self.failUnlessEqual(expected_formatter_data[key],
+ msg.formatter_data[key])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/node/misc.py b/chromium/tools/grit/grit/node/misc.py
new file mode 100755
index 00000000000..33848b22977
--- /dev/null
+++ b/chromium/tools/grit/grit/node/misc.py
@@ -0,0 +1,523 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Miscellaneous node types.
+"""
+
+import os.path
+import re
+import sys
+
+from grit import constants
+from grit import exception
+from grit import util
+import grit.format.rc_header
+from grit.node import base
+from grit.node import io
+from grit.node import message
+
+
+# RTL languages
+# TODO(jennyz): remove this fixed set of RTL language array
+# now that generic expand_variable code exists.
+_RTL_LANGS = (
+ 'ar', # Arabic
+ 'fa', # Farsi
+ 'iw', # Hebrew
+ 'ks', # Kashmiri
+ 'ku', # Kurdish
+ 'ps', # Pashto
+ 'ur', # Urdu
+ 'yi', # Yiddish
+)
+
+
+def _ReadFirstIdsFromFile(filename, defines):
+ """Read the starting resource id values from |filename|. We also
+ expand variables of the form <(FOO) based on defines passed in on
+ the command line.
+
+ Returns a tuple, the absolute path of SRCDIR followed by the
+ first_ids dictionary.
+ """
+ first_ids_dict = eval(util.ReadFile(filename, util.RAW_TEXT))
+ src_root_dir = os.path.abspath(os.path.join(os.path.dirname(filename),
+ first_ids_dict['SRCDIR']))
+
+ def ReplaceVariable(matchobj):
+ for key, value in defines.iteritems():
+ if matchobj.group(1) == key:
+ value = os.path.abspath(value)
+ return value
+ return ''
+
+ renames = []
+ for grd_filename in first_ids_dict:
+ new_grd_filename = re.sub(r'<\(([A-Za-z_]+)\)', ReplaceVariable,
+ grd_filename)
+ if new_grd_filename != grd_filename:
+ new_grd_filename = new_grd_filename.replace('\\', '/')
+ renames.append((grd_filename, new_grd_filename))
+
+ for grd_filename, new_grd_filename in renames:
+ first_ids_dict[new_grd_filename] = first_ids_dict[grd_filename]
+ del(first_ids_dict[grd_filename])
+
+ return (src_root_dir, first_ids_dict)
+
+
+class SplicingNode(base.Node):
+ """A node whose children should be considered to be at the same level as
+ its siblings for most purposes. This includes <if> and <part> nodes.
+ """
+
+ def _IsValidChild(self, child):
+ assert self.parent, '<%s> node should never be root.' % self.name
+ if isinstance(child, SplicingNode):
+ return True # avoid O(n^2) behavior
+ return self.parent._IsValidChild(child)
+
+
+class IfNode(SplicingNode):
+ """A node for conditional inclusion of resources.
+ """
+
+ def MandatoryAttributes(self):
+ return ['expr']
+
+ def _IsValidChild(self, child):
+ return (isinstance(child, (ThenNode, ElseNode)) or
+ super(IfNode, self)._IsValidChild(child))
+
+ def EndParsing(self):
+ children = self.children
+ self.if_then_else = False
+ if any(isinstance(node, (ThenNode, ElseNode)) for node in children):
+ if (len(children) != 2 or not isinstance(children[0], ThenNode) or
+ not isinstance(children[1], ElseNode)):
+ raise exception.UnexpectedChild(
+ '<if> element must be <if><then>...</then><else>...</else></if>')
+ self.if_then_else = True
+
+ def ActiveChildren(self):
+ cond = self.EvaluateCondition(self.attrs['expr'])
+ if self.if_then_else:
+ return self.children[0 if cond else 1].ActiveChildren()
+ else:
+ # Equivalent to having all children inside <then> with an empty <else>
+ return super(IfNode, self).ActiveChildren() if cond else []
+
+
+class ThenNode(SplicingNode):
+ """A <then> node. Can only appear directly inside an <if> node."""
+ pass
+
+
+class ElseNode(SplicingNode):
+ """An <else> node. Can only appear directly inside an <if> node."""
+ pass
+
+
+class PartNode(SplicingNode):
+ """A node for inclusion of sub-grd (*.grp) files.
+ """
+
+ def __init__(self):
+ super(PartNode, self).__init__()
+ self.started_inclusion = False
+
+ def MandatoryAttributes(self):
+ return ['file']
+
+ def _IsValidChild(self, child):
+ return self.started_inclusion and super(PartNode, self)._IsValidChild(child)
+
+
+class ReleaseNode(base.Node):
+ """The <release> element."""
+
+ def _IsValidChild(self, child):
+ from grit.node import empty
+ return isinstance(child, (empty.IncludesNode, empty.MessagesNode,
+ empty.StructuresNode, empty.IdentifiersNode))
+
+ def _IsValidAttribute(self, name, value):
+ return (
+ (name == 'seq' and int(value) <= self.GetRoot().GetCurrentRelease()) or
+ name == 'allow_pseudo'
+ )
+
+ def MandatoryAttributes(self):
+ return ['seq']
+
+ def DefaultAttributes(self):
+ return { 'allow_pseudo' : 'true' }
+
+ def GetReleaseNumber():
+ """Returns the sequence number of this release."""
+ return self.attribs['seq']
+
+class GritNode(base.Node):
+ """The <grit> root element."""
+
+ def __init__(self):
+ super(GritNode, self).__init__()
+ self.output_language = ''
+ self.defines = {}
+ self.substituter = None
+ self.target_platform = sys.platform
+
+ def _IsValidChild(self, child):
+ from grit.node import empty
+ return isinstance(child, (ReleaseNode, empty.TranslationsNode,
+ empty.OutputsNode))
+
+ def _IsValidAttribute(self, name, value):
+ if name not in ['base_dir', 'first_ids_file', 'source_lang_id',
+ 'latest_public_release', 'current_release',
+ 'enc_check', 'tc_project', 'grit_version',
+ 'output_all_resource_defines']:
+ return False
+ if name in ['latest_public_release', 'current_release'] and value.strip(
+ '0123456789') != '':
+ return False
+ return True
+
+ def MandatoryAttributes(self):
+ return ['latest_public_release', 'current_release']
+
+ def DefaultAttributes(self):
+ return {
+ 'base_dir' : '.',
+ 'first_ids_file': '',
+ 'grit_version': 1,
+ 'source_lang_id' : 'en',
+ 'enc_check' : constants.ENCODING_CHECK,
+ 'tc_project' : 'NEED_TO_SET_tc_project_ATTRIBUTE',
+ 'output_all_resource_defines': 'true'
+ }
+
+ def EndParsing(self):
+ super(GritNode, self).EndParsing()
+ if (int(self.attrs['latest_public_release'])
+ > int(self.attrs['current_release'])):
+ raise exception.Parsing('latest_public_release cannot have a greater '
+ 'value than current_release')
+
+ self.ValidateUniqueIds()
+
+ # Add the encoding check if it's not present (should ensure that it's always
+ # present in all .grd files generated by GRIT). If it's present, assert if
+ # it's not correct.
+ if 'enc_check' not in self.attrs or self.attrs['enc_check'] == '':
+ self.attrs['enc_check'] = constants.ENCODING_CHECK
+ else:
+ assert self.attrs['enc_check'] == constants.ENCODING_CHECK, (
+ 'Are you sure your .grd file is in the correct encoding (UTF-8)?')
+
+ def ValidateUniqueIds(self):
+ """Validate that 'name' attribute is unique in all nodes in this tree
+ except for nodes that are children of <if> nodes.
+ """
+ unique_names = {}
+ duplicate_names = []
+ # To avoid false positives from mutually exclusive <if> clauses, check
+ # against whatever the output condition happens to be right now.
+ # TODO(benrg): do something better.
+ for node in self.ActiveDescendants():
+ if node.attrs.get('generateid', 'true') == 'false':
+ continue # Duplication not relevant in that case
+
+ for node_id in node.GetTextualIds():
+ if util.SYSTEM_IDENTIFIERS.match(node_id):
+ continue # predefined IDs are sometimes used more than once
+
+ if node_id in unique_names and node_id not in duplicate_names:
+ duplicate_names.append(node_id)
+ unique_names[node_id] = 1
+
+ if len(duplicate_names):
+ raise exception.DuplicateKey(', '.join(duplicate_names))
+
+
+ def GetCurrentRelease(self):
+ """Returns the current release number."""
+ return int(self.attrs['current_release'])
+
+ def GetLatestPublicRelease(self):
+ """Returns the latest public release number."""
+ return int(self.attrs['latest_public_release'])
+
+ def GetSourceLanguage(self):
+ """Returns the language code of the source language."""
+ return self.attrs['source_lang_id']
+
+ def GetTcProject(self):
+ """Returns the name of this project in the TranslationConsole, or
+ 'NEED_TO_SET_tc_project_ATTRIBUTE' if it is not defined."""
+ return self.attrs['tc_project']
+
+ def SetOwnDir(self, dir):
+ """Informs the 'grit' element of the directory the file it is in resides.
+ This allows it to calculate relative paths from the input file, which is
+ what we desire (rather than from the current path).
+
+ Args:
+ dir: r'c:\bla'
+
+ Return:
+ None
+ """
+ assert dir
+ self.base_dir = os.path.normpath(os.path.join(dir, self.attrs['base_dir']))
+
+ def GetBaseDir(self):
+ """Returns the base directory, relative to the working directory. To get
+ the base directory as set in the .grd file, use GetOriginalBaseDir()
+ """
+ if hasattr(self, 'base_dir'):
+ return self.base_dir
+ else:
+ return self.GetOriginalBaseDir()
+
+ def GetOriginalBaseDir(self):
+ """Returns the base directory, as set in the .grd file.
+ """
+ return self.attrs['base_dir']
+
+ def ShouldOutputAllResourceDefines(self):
+ """Returns true if all resource defines should be output, false if
+ defines for resources not emitted to resource files should be
+ skipped.
+ """
+ return self.attrs['output_all_resource_defines'] == 'true'
+
+ def GetInputFiles(self):
+ """Returns the list of files that are read to produce the output."""
+
+ # Importing this here avoids a circular dependency in the imports.
+ # pylint: disable-msg=C6204
+ from grit.node import include
+ from grit.node import misc
+ from grit.node import structure
+ from grit.node import variant
+
+ # Check if the input is required for any output configuration.
+ input_files = set()
+ old_output_language = self.output_language
+ for lang, ctx in self.GetConfigurations():
+ self.SetOutputLanguage(lang or self.GetSourceLanguage())
+ self.SetOutputContext(ctx)
+ for node in self.ActiveDescendants():
+ if isinstance(node, (io.FileNode, include.IncludeNode, misc.PartNode,
+ structure.StructureNode, variant.SkeletonNode)):
+ input_files.add(node.GetInputPath())
+ self.SetOutputLanguage(old_output_language)
+ return sorted(map(self.ToRealPath, input_files))
+
+ def GetFirstIdsFile(self):
+ """Returns a usable path to the first_ids file, if set, otherwise
+ returns None.
+
+ The first_ids_file attribute is by default relative to the
+ base_dir of the .grd file, but may be prefixed by GRIT_DIR/,
+ which makes it relative to the directory of grit.py
+ (e.g. GRIT_DIR/../gritsettings/resource_ids).
+ """
+ if not self.attrs['first_ids_file']:
+ return None
+
+ path = self.attrs['first_ids_file']
+ GRIT_DIR_PREFIX = 'GRIT_DIR'
+ if (path.startswith(GRIT_DIR_PREFIX)
+ and path[len(GRIT_DIR_PREFIX)] in ['/', '\\']):
+ return util.PathFromRoot(path[len(GRIT_DIR_PREFIX) + 1:])
+ else:
+ return self.ToRealPath(path)
+
+ def GetOutputFiles(self):
+ """Returns the list of <output> nodes that are descendants of this node's
+ <outputs> child and are not enclosed by unsatisfied <if> conditionals.
+ """
+ for child in self.children:
+ if child.name == 'outputs':
+ return [node for node in child.ActiveDescendants()
+ if node.name == 'output']
+ raise exception.MissingElement()
+
+ def GetConfigurations(self):
+ """Returns the distinct (language, context) pairs from the output nodes.
+ """
+ return set((n.GetLanguage(), n.GetContext()) for n in self.GetOutputFiles())
+
+ def GetSubstitutionMessages(self):
+ """Returns the list of <message sub_variable="true"> nodes."""
+ return [n for n in self.ActiveDescendants()
+ if isinstance(n, message.MessageNode)
+ and n.attrs['sub_variable'] == 'true']
+
+ def SetOutputLanguage(self, output_language):
+ """Set the output language. Prepares substitutions.
+
+ The substitutions are reset every time the language is changed.
+ They include messages designated as variables, and language codes for html
+ and rc files.
+
+ Args:
+ output_language: a two-letter language code (eg: 'en', 'ar'...) or ''
+ """
+ if not output_language:
+ # We do not specify the output language for .grh files,
+ # so we get an empty string as the default.
+ # The value should match grit.clique.MessageClique.source_language.
+ output_language = self.GetSourceLanguage()
+ if output_language != self.output_language:
+ self.output_language = output_language
+ self.substituter = None # force recalculate
+
+ def SetOutputContext(self, output_context):
+ self.output_context = output_context
+ self.substituter = None # force recalculate
+
+ def SetDefines(self, defines):
+ self.defines = defines
+ self.substituter = None # force recalculate
+
+ def SetTargetPlatform(self, target_platform):
+ self.target_platform = target_platform
+
+ def GetSubstituter(self):
+ if self.substituter is None:
+ self.substituter = util.Substituter()
+ self.substituter.AddMessages(self.GetSubstitutionMessages(),
+ self.output_language)
+ if self.output_language in _RTL_LANGS:
+ direction = 'dir="RTL"'
+ else:
+ direction = 'dir="LTR"'
+ self.substituter.AddSubstitutions({
+ 'GRITLANGCODE': self.output_language,
+ 'GRITDIR': direction,
+ })
+ from grit.format import rc # avoid circular dep
+ rc.RcSubstitutions(self.substituter, self.output_language)
+ return self.substituter
+
+ def AssignFirstIds(self, filename_or_stream, defines):
+ """Assign first ids to each grouping node based on values from the
+ first_ids file (if specified on the <grit> node).
+ """
+ # If the input is a stream, then we're probably in a unit test and
+ # should skip this step.
+ if type(filename_or_stream) not in (str, unicode):
+ return
+
+ # Nothing to do if the first_ids_filename attribute isn't set.
+ first_ids_filename = self.GetFirstIdsFile()
+ if not first_ids_filename:
+ return
+
+ src_root_dir, first_ids = _ReadFirstIdsFromFile(first_ids_filename,
+ defines)
+ from grit.node import empty
+ for node in self.Preorder():
+ if isinstance(node, empty.GroupingNode):
+ abs_filename = os.path.abspath(filename_or_stream)
+ if abs_filename[:len(src_root_dir)] != src_root_dir:
+ filename = os.path.basename(filename_or_stream)
+ # If the file is not within src_root_dir and the basename is not
+ # found as a key, fall back to using the absolute file name.
+ if not filename in first_ids:
+ filename = abs_filename
+ else:
+ filename = abs_filename[len(src_root_dir) + 1:]
+ filename = filename.replace('\\', '/')
+
+ if node.attrs['first_id'] != '':
+ raise Exception(
+ "Don't set the first_id attribute when using the first_ids_file "
+ "attribute on the <grit> node, update %s instead." %
+ first_ids_filename)
+
+ try:
+ id_list = first_ids[filename][node.name]
+ except KeyError, e:
+ print '-' * 78
+ print 'Resource id not set for %s (%s)!' % (filename, node.name)
+ print ('Please update %s to include an entry for %s. See the '
+ 'comments in resource_ids for information on why you need to '
+ 'update that file.' % (first_ids_filename, filename))
+ print '-' * 78
+ raise e
+
+ try:
+ node.attrs['first_id'] = str(id_list.pop(0))
+ except IndexError, e:
+ raise Exception('Please update %s and add a first id for %s (%s).'
+ % (first_ids_filename, filename, node.name))
+
+ def RunGatherers(self, debug=False):
+ '''Call RunPreSubstitutionGatherer() on every node of the tree, then apply
+ substitutions, then call RunPostSubstitutionGatherer() on every node.
+
+ The substitutions step requires that the output language has been set.
+ Locally, get the Substitution messages and add them to the substituter.
+ Also add substitutions for language codes in the Rc.
+
+ Args:
+ debug: will print information while running gatherers.
+ '''
+ for node in self.ActiveDescendants():
+ if hasattr(node, 'RunPreSubstitutionGatherer'):
+ with node:
+ node.RunPreSubstitutionGatherer(debug=debug)
+
+ assert self.output_language
+ self.SubstituteMessages(self.GetSubstituter())
+
+ for node in self.ActiveDescendants():
+ if hasattr(node, 'RunPostSubstitutionGatherer'):
+ with node:
+ node.RunPostSubstitutionGatherer(debug=debug)
+
+
+class IdentifierNode(base.Node):
+ """A node for specifying identifiers that should appear in the resource
+ header file, and be unique amongst all other resource identifiers, but don't
+ have any other attributes or reference any resources.
+ """
+
+ def MandatoryAttributes(self):
+ return ['name']
+
+ def DefaultAttributes(self):
+ return { 'comment' : '', 'id' : '', 'systemid': 'false' }
+
+ def GetId(self):
+ """Returns the id of this identifier if it has one, None otherwise
+ """
+ if 'id' in self.attrs:
+ return self.attrs['id']
+ return None
+
+ def EndParsing(self):
+ """Handles system identifiers."""
+ super(IdentifierNode, self).EndParsing()
+ if self.attrs['systemid'] == 'true':
+ util.SetupSystemIdentifiers((self.attrs['name'],))
+
+ @staticmethod
+ def Construct(parent, name, id, comment, systemid='false'):
+ """Creates a new node which is a child of 'parent', with attributes set
+ by parameters of the same name.
+ """
+ node = IdentifierNode()
+ node.StartParsing('identifier', parent)
+ node.HandleAttribute('name', name)
+ node.HandleAttribute('id', id)
+ node.HandleAttribute('comment', comment)
+ node.HandleAttribute('systemid', systemid)
+ node.EndParsing()
+ return node
diff --git a/chromium/tools/grit/grit/node/misc_unittest.py b/chromium/tools/grit/grit/node/misc_unittest.py
new file mode 100644
index 00000000000..496d1531615
--- /dev/null
+++ b/chromium/tools/grit/grit/node/misc_unittest.py
@@ -0,0 +1,419 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for misc.GritNode'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit import grd_reader
+import grit.exception
+from grit import util
+from grit.format import rc
+from grit.node import misc
+
+
+class GritNodeUnittest(unittest.TestCase):
+ def testUniqueNameAttribute(self):
+ try:
+ restree = grd_reader.Parse(
+ util.PathFromRoot('grit/testdata/duplicate-name-input.xml'))
+ self.fail('Expected parsing exception because of duplicate names.')
+ except grit.exception.Parsing:
+ pass # Expected case
+
+ def testReadFirstIdsFromFile(self):
+ test_resource_ids = os.path.join(os.path.dirname(__file__), '..',
+ 'testdata', 'resource_ids')
+ base_dir = os.path.dirname(test_resource_ids)
+
+ src_dir, id_dict = misc._ReadFirstIdsFromFile(
+ test_resource_ids,
+ {
+ 'FOO': os.path.join(base_dir, 'bar'),
+ 'SHARED_INTERMEDIATE_DIR': os.path.join(base_dir,
+ 'out/Release/obj/gen'),
+ })
+ self.assertEqual({}, id_dict.get('bar/file.grd', None))
+ self.assertEqual({},
+ id_dict.get('out/Release/obj/gen/devtools/devtools.grd', None))
+
+
+class IfNodeUnittest(unittest.TestCase):
+ def testIffyness(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <if expr="'bingo' in defs">
+ <message name="IDS_BINGO">
+ Bingo!
+ </message>
+ </if>
+ <if expr="'hello' in defs">
+ <message name="IDS_HELLO">
+ Hello!
+ </message>
+ </if>
+ <if expr="lang == 'fr' or 'FORCE_FRENCH' in defs">
+ <message name="IDS_HELLO" internal_comment="French version">
+ Good morning
+ </message>
+ </if>
+ <if expr="is_win">
+ <message name="IDS_ISWIN">is_win</message>
+ </if>
+ </messages>
+ </release>
+ </grit>'''), dir='.')
+
+ messages_node = grd.children[0].children[0]
+ bingo_message = messages_node.children[0].children[0]
+ hello_message = messages_node.children[1].children[0]
+ french_message = messages_node.children[2].children[0]
+ is_win_message = messages_node.children[3].children[0]
+
+ self.assertTrue(bingo_message.name == 'message')
+ self.assertTrue(hello_message.name == 'message')
+ self.assertTrue(french_message.name == 'message')
+
+ grd.SetOutputLanguage('fr')
+ grd.SetDefines({'hello': '1'})
+ active = set(grd.ActiveDescendants())
+ self.failUnless(bingo_message not in active)
+ self.failUnless(hello_message in active)
+ self.failUnless(french_message in active)
+
+ grd.SetOutputLanguage('en')
+ grd.SetDefines({'bingo': 1})
+ active = set(grd.ActiveDescendants())
+ self.failUnless(bingo_message in active)
+ self.failUnless(hello_message not in active)
+ self.failUnless(french_message not in active)
+
+ grd.SetOutputLanguage('en')
+ grd.SetDefines({'FORCE_FRENCH': '1', 'bingo': '1'})
+ active = set(grd.ActiveDescendants())
+ self.failUnless(bingo_message in active)
+ self.failUnless(hello_message not in active)
+ self.failUnless(french_message in active)
+
+ grd.SetOutputLanguage('en')
+ grd.SetDefines({})
+ self.failUnless(grd.target_platform == sys.platform)
+ grd.SetTargetPlatform('darwin')
+ active = set(grd.ActiveDescendants())
+ self.failUnless(is_win_message not in active)
+ grd.SetTargetPlatform('win32')
+ active = set(grd.ActiveDescendants())
+ self.failUnless(is_win_message in active)
+
+ def testElsiness(self):
+ grd = util.ParseGrdForUnittest('''
+ <messages>
+ <if expr="True">
+ <then> <message name="IDS_YES1"></message> </then>
+ <else> <message name="IDS_NO1"></message> </else>
+ </if>
+ <if expr="True">
+ <then> <message name="IDS_YES2"></message> </then>
+ <else> </else>
+ </if>
+ <if expr="True">
+ <then> </then>
+ <else> <message name="IDS_NO2"></message> </else>
+ </if>
+ <if expr="True">
+ <then> </then>
+ <else> </else>
+ </if>
+ <if expr="False">
+ <then> <message name="IDS_NO3"></message> </then>
+ <else> <message name="IDS_YES3"></message> </else>
+ </if>
+ <if expr="False">
+ <then> <message name="IDS_NO4"></message> </then>
+ <else> </else>
+ </if>
+ <if expr="False">
+ <then> </then>
+ <else> <message name="IDS_YES4"></message> </else>
+ </if>
+ <if expr="False">
+ <then> </then>
+ <else> </else>
+ </if>
+ </messages>''')
+ included = [msg.attrs['name'] for msg in grd.ActiveDescendants()
+ if msg.name == 'message']
+ self.assertEqual(['IDS_YES1', 'IDS_YES2', 'IDS_YES3', 'IDS_YES4'], included)
+
+ def testIffynessWithOutputNodes(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <outputs>
+ <output filename="uncond1.rc" type="rc_data" />
+ <if expr="lang == 'fr' or 'hello' in defs">
+ <output filename="only_fr.adm" type="adm" />
+ <output filename="only_fr.plist" type="plist" />
+ </if>
+ <if expr="lang == 'ru'">
+ <output filename="doc.html" type="document" />
+ </if>
+ <output filename="uncond2.adm" type="adm" />
+ <output filename="iftest.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ </outputs>
+ </grit>'''), dir='.')
+
+ outputs_node = grd.children[0]
+ uncond1_output = outputs_node.children[0]
+ only_fr_adm_output = outputs_node.children[1].children[0]
+ only_fr_plist_output = outputs_node.children[1].children[1]
+ doc_output = outputs_node.children[2].children[0]
+ uncond2_output = outputs_node.children[0]
+ self.assertTrue(uncond1_output.name == 'output')
+ self.assertTrue(only_fr_adm_output.name == 'output')
+ self.assertTrue(only_fr_plist_output.name == 'output')
+ self.assertTrue(doc_output.name == 'output')
+ self.assertTrue(uncond2_output.name == 'output')
+
+ grd.SetOutputLanguage('ru')
+ grd.SetDefines({'hello': '1'})
+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
+ self.assertEquals(
+ outputs,
+ ['uncond1.rc', 'only_fr.adm', 'only_fr.plist', 'doc.html',
+ 'uncond2.adm', 'iftest.h'])
+
+ grd.SetOutputLanguage('ru')
+ grd.SetDefines({'bingo': '2'})
+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
+ self.assertEquals(
+ outputs,
+ ['uncond1.rc', 'doc.html', 'uncond2.adm', 'iftest.h'])
+
+ grd.SetOutputLanguage('fr')
+ grd.SetDefines({'hello': '1'})
+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
+ self.assertEquals(
+ outputs,
+ ['uncond1.rc', 'only_fr.adm', 'only_fr.plist', 'uncond2.adm',
+ 'iftest.h'])
+
+ grd.SetOutputLanguage('en')
+ grd.SetDefines({'bingo': '1'})
+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
+ self.assertEquals(outputs, ['uncond1.rc', 'uncond2.adm', 'iftest.h'])
+
+ grd.SetOutputLanguage('fr')
+ grd.SetDefines({'bingo': '1'})
+ outputs = [output.GetFilename() for output in grd.GetOutputFiles()]
+ self.assertNotEquals(outputs, ['uncond1.rc', 'uncond2.adm', 'iftest.h'])
+
+ def testChildrenAccepted(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <includes>
+ <if expr="'bingo' in defs">
+ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
+ </if>
+ <if expr="'bingo' in defs">
+ <if expr="'hello' in defs">
+ <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
+ </if>
+ </if>
+ </includes>
+ <structures>
+ <if expr="'bingo' in defs">
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\test\data\klonk.rc" encoding="utf-16" />
+ </if>
+ <if expr="'bingo' in defs">
+ <if expr="'hello' in defs">
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\test\data\klonk.rc" encoding="utf-16" />
+ </if>
+ </if>
+ </structures>
+ <messages>
+ <if expr="'bingo' in defs">
+ <message name="IDS_BINGO">Bingo!</message>
+ </if>
+ <if expr="'bingo' in defs">
+ <if expr="'hello' in defs">
+ <message name="IDS_BINGO">Bingo!</message>
+ </if>
+ </if>
+ </messages>
+ </release>
+ <translations>
+ <if expr="'bingo' in defs">
+ <file lang="nl" path="nl_translations.xtb" />
+ </if>
+ <if expr="'bingo' in defs">
+ <if expr="'hello' in defs">
+ <file lang="nl" path="nl_translations.xtb" />
+ </if>
+ </if>
+ </translations>
+ </grit>'''), dir='.')
+
+ def testIfBadChildrenNesting(self):
+ # includes
+ xml = StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <includes>
+ <if expr="'bingo' in defs">
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\test\data\klonk.rc" encoding="utf-16" />
+ </if>
+ </includes>
+ </release>
+ </grit>''')
+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
+ # messages
+ xml = StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <if expr="'bingo' in defs">
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\test\data\klonk.rc" encoding="utf-16" />
+ </if>
+ </messages>
+ </release>
+ </grit>''')
+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
+ # structures
+ xml = StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <structures>
+ <if expr="'bingo' in defs">
+ <message name="IDS_BINGO">Bingo!</message>
+ </if>
+ </structures>
+ </release>
+ </grit>''')
+ # translations
+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
+ xml = StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <translations>
+ <if expr="'bingo' in defs">
+ <message name="IDS_BINGO">Bingo!</message>
+ </if>
+ </translations>
+ </grit>''')
+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
+ # same with nesting
+ xml = StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <includes>
+ <if expr="'bingo' in defs">
+ <if expr="'hello' in defs">
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\test\data\klonk.rc" encoding="utf-16" />
+ </if>
+ </if>
+ </includes>
+ </release>
+ </grit>''')
+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
+ xml = StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <if expr="'bingo' in defs">
+ <if expr="'hello' in defs">
+ <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\test\data\klonk.rc" encoding="utf-16" />
+ </if>
+ </if>
+ </messages>
+ </release>
+ </grit>''')
+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
+ xml = StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <structures>
+ <if expr="'bingo' in defs">
+ <if expr="'hello' in defs">
+ <message name="IDS_BINGO">Bingo!</message>
+ </if>
+ </if>
+ </structures>
+ </release>
+ </grit>''')
+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
+ xml = StringIO.StringIO('''<?xml version="1.0"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <translations>
+ <if expr="'bingo' in defs">
+ <if expr="'hello' in defs">
+ <message name="IDS_BINGO">Bingo!</message>
+ </if>
+ </if>
+ </translations>
+ </grit>''')
+ self.assertRaises(grit.exception.UnexpectedChild, grd_reader.Parse, xml)
+
+
+class ReleaseNodeUnittest(unittest.TestCase):
+ def testPseudoControl(self):
+ grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="1" source_lang_id="en-US" current_release="2" base_dir=".">
+ <release seq="1" allow_pseudo="false">
+ <messages>
+ <message name="IDS_HELLO">
+ Hello
+ </message>
+ </messages>
+ <structures>
+ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="klonk.rc" />
+ </structures>
+ </release>
+ <release seq="2">
+ <messages>
+ <message name="IDS_BINGO">
+ Bingo
+ </message>
+ </messages>
+ <structures>
+ <structure type="menu" name="IDC_KLONKMENU" encoding="utf-16" file="klonk.rc" />
+ </structures>
+ </release>
+ </grit>'''), util.PathFromRoot('grit/testdata'))
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+
+ hello = grd.GetNodeById('IDS_HELLO')
+ aboutbox = grd.GetNodeById('IDD_ABOUTBOX')
+ bingo = grd.GetNodeById('IDS_BINGO')
+ menu = grd.GetNodeById('IDC_KLONKMENU')
+
+ for node in [hello, aboutbox]:
+ self.failUnless(not node.PseudoIsAllowed())
+
+ for node in [bingo, menu]:
+ self.failUnless(node.PseudoIsAllowed())
+
+ # TODO(benrg): There was a test here that formatting hello and aboutbox with
+ # a pseudo language should fail, but they do not fail and the test was
+ # broken and failed to catch it. Fix this.
+
+ # Should not raise an exception since pseudo is allowed
+ rc.FormatMessage(bingo, 'xyz-pseudo')
+ rc.FormatStructure(menu, 'xyz-pseudo', '.')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/node/structure.py b/chromium/tools/grit/grit/node/structure.py
new file mode 100644
index 00000000000..48968f65ec5
--- /dev/null
+++ b/chromium/tools/grit/grit/node/structure.py
@@ -0,0 +1,358 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The <structure> element.
+'''
+
+import os
+import platform
+import re
+
+from grit import exception
+from grit import util
+from grit.node import base
+from grit.node import variant
+
+import grit.gather.admin_template
+import grit.gather.chrome_html
+import grit.gather.chrome_scaled_image
+import grit.gather.igoogle_strings
+import grit.gather.muppet_strings
+import grit.gather.policy_json
+import grit.gather.rc
+import grit.gather.tr_html
+import grit.gather.txt
+
+import grit.format.rc
+import grit.format.rc_header
+
+# Type of the gatherer to use for each type attribute
+_GATHERERS = {
+ 'accelerators' : grit.gather.rc.Accelerators,
+ 'admin_template' : grit.gather.admin_template.AdmGatherer,
+ 'chrome_html' : grit.gather.chrome_html.ChromeHtml,
+ 'chrome_scaled_image' : grit.gather.chrome_scaled_image.ChromeScaledImage,
+ 'dialog' : grit.gather.rc.Dialog,
+ 'igoogle' : grit.gather.igoogle_strings.IgoogleStrings,
+ 'menu' : grit.gather.rc.Menu,
+ 'muppet' : grit.gather.muppet_strings.MuppetStrings,
+ 'rcdata' : grit.gather.rc.RCData,
+ 'tr_html' : grit.gather.tr_html.TrHtml,
+ 'txt' : grit.gather.txt.TxtFile,
+ 'version' : grit.gather.rc.Version,
+ 'policy_template_metafile' : grit.gather.policy_json.PolicyJson,
+}
+
+
+# TODO(joi) Print a warning if the 'variant_of_revision' attribute indicates
+# that a skeleton variant is older than the original file.
+
+
+class StructureNode(base.Node):
+ '''A <structure> element.'''
+
+ # Regular expression for a local variable definition. Each definition
+ # is of the form NAME=VALUE, where NAME cannot contain '=' or ',' and
+ # VALUE must escape all commas: ',' -> ',,'. Each variable definition
+ # should be separated by a comma with no extra whitespace.
+ # Example: THING1=foo,THING2=bar
+ variable_pattern = re.compile('([^,=\s]+)=((?:,,|[^,])*)')
+
+ def __init__(self):
+ super(StructureNode, self).__init__()
+
+ # Keep track of the last filename we flattened to, so we can
+ # avoid doing it more than once.
+ self._last_flat_filename = None
+
+ # See _Substitute; this substituter is used for local variables and
+ # the root substituter is used for global variables.
+ self.substituter = None
+
+ def _IsValidChild(self, child):
+ return isinstance(child, variant.SkeletonNode)
+
+ def _ParseVariables(self, variables):
+ '''Parse a variable string into a dictionary.'''
+ matches = StructureNode.variable_pattern.findall(variables)
+ return dict((name, value.replace(',,', ',')) for name, value in matches)
+
+ def EndParsing(self):
+ super(StructureNode, self).EndParsing()
+
+ # Now that we have attributes and children, instantiate the gatherers.
+ gathertype = _GATHERERS[self.attrs['type']]
+
+ self.gatherer = gathertype(self.attrs['file'],
+ self.attrs['name'],
+ self.attrs['encoding'])
+ self.gatherer.SetGrdNode(self)
+ self.gatherer.SetUberClique(self.UberClique())
+ if hasattr(self.GetRoot(), 'defines'):
+ self.gatherer.SetDefines(self.GetRoot().defines)
+ self.gatherer.SetAttributes(self.attrs)
+ if self.ExpandVariables():
+ self.gatherer.SetFilenameExpansionFunction(self._Substitute)
+
+ # Parse local variables and instantiate the substituter.
+ if self.attrs['variables']:
+ variables = self.attrs['variables']
+ self.substituter = util.Substituter()
+ self.substituter.AddSubstitutions(self._ParseVariables(variables))
+
+ self.skeletons = {} # Maps expressions to skeleton gatherers
+ for child in self.children:
+ assert isinstance(child, variant.SkeletonNode)
+ skel = gathertype(child.attrs['file'],
+ self.attrs['name'],
+ child.GetEncodingToUse(),
+ is_skeleton=True)
+ skel.SetGrdNode(self) # TODO(benrg): Or child? Only used for ToRealPath
+ skel.SetUberClique(self.UberClique())
+ if hasattr(self.GetRoot(), 'defines'):
+ skel.SetDefines(self.GetRoot().defines)
+ if self.ExpandVariables():
+ skel.SetFilenameExpansionFunction(self._Substitute)
+ self.skeletons[child.attrs['expr']] = skel
+
+ def MandatoryAttributes(self):
+ return ['type', 'name', 'file']
+
+ def DefaultAttributes(self):
+ return { 'encoding' : 'cp1252',
+ 'exclude_from_rc' : 'false',
+ 'line_end' : 'unix',
+ 'output_encoding' : 'utf-8',
+ 'generateid': 'true',
+ 'expand_variables' : 'false',
+ 'output_filename' : '',
+ 'fold_whitespace': 'false',
+ # Run an arbitrary command after translation is complete
+ # so that it doesn't interfere with what's in translation
+ # console.
+ 'run_command' : '',
+ # Leave empty to run on all platforms, comma-separated
+ # for one or more specific platforms. Values must match
+ # output of platform.system().
+ 'run_command_on_platforms' : '',
+ 'allowexternalscript': 'false',
+ 'flattenhtml': 'false',
+ 'fallback_to_low_resolution': 'default',
+ # TODO(joi) this is a hack - should output all generated files
+ # as SCons dependencies; however, for now there is a bug I can't
+ # find where GRIT doesn't build the matching fileset, therefore
+ # this hack so that only the files you really need are marked as
+ # dependencies.
+ 'sconsdep' : 'false',
+ 'variables': '',
+ }
+
+ def IsExcludedFromRc(self):
+ return self.attrs['exclude_from_rc'] == 'true'
+
+ def Process(self, output_dir):
+ """Writes the processed data to output_dir. In the case of a chrome_html
+ structure this will add references to other scale factors. If flattening
+ this will also write file references to be base64 encoded data URLs. The
+ name of the new file is returned."""
+ filename = self.ToRealPath(self.GetInputPath())
+ flat_filename = os.path.join(output_dir,
+ self.attrs['name'] + '_' + os.path.basename(filename))
+
+ if self._last_flat_filename == flat_filename:
+ return
+
+ with open(flat_filename, 'wb') as outfile:
+ if self.ExpandVariables():
+ text = self.gatherer.GetText()
+ file_contents = self._Substitute(text).encode('utf-8')
+ else:
+ file_contents = self.gatherer.GetData('', 'utf-8')
+ outfile.write(file_contents)
+
+ self._last_flat_filename = flat_filename
+ return os.path.basename(flat_filename)
+
+ def GetLineEnd(self):
+ '''Returns the end-of-line character or characters for files output because
+ of this node ('\r\n', '\n', or '\r' depending on the 'line_end' attribute).
+ '''
+ if self.attrs['line_end'] == 'unix':
+ return '\n'
+ elif self.attrs['line_end'] == 'windows':
+ return '\r\n'
+ elif self.attrs['line_end'] == 'mac':
+ return '\r'
+ else:
+ raise exception.UnexpectedAttribute(
+ "Attribute 'line_end' must be one of 'unix' (default), 'windows' or 'mac'")
+
+ def GetCliques(self):
+ return self.gatherer.GetCliques()
+
+ def GetDataPackPair(self, lang, encoding):
+ """Returns a (id, string|None) pair that represents the resource id and raw
+ bytes of the data (or None if no resource is generated). This is used to
+ generate the data pack data file.
+ """
+ from grit.format import rc_header
+ id_map = rc_header.GetIds(self.GetRoot())
+ id = id_map[self.GetTextualIds()[0]]
+ if self.ExpandVariables():
+ text = self.gatherer.GetText()
+ return id, util.Encode(self._Substitute(text), encoding)
+ return id, self.gatherer.GetData(lang, encoding)
+
+ def GetHtmlResourceFilenames(self):
+ """Returns a set of all filenames inlined by this node."""
+ return self.gatherer.GetHtmlResourceFilenames()
+
+ def GetInputPath(self):
+ return self.gatherer.GetInputPath()
+
+ def GetTextualIds(self):
+ if not hasattr(self, 'gatherer'):
+ # This case is needed because this method is called by
+ # GritNode.ValidateUniqueIds before RunGatherers has been called.
+ # TODO(benrg): Fix this?
+ return [self.attrs['name']]
+ return self.gatherer.GetTextualIds()
+
+ def RunPreSubstitutionGatherer(self, debug=False):
+ if debug:
+ print 'Running gatherer %s for file %s' % (
+ str(type(self.gatherer)), self.GetInputPath())
+
+ # Note: Parse() is idempotent, therefore this method is also.
+ self.gatherer.Parse()
+ for skel in self.skeletons.values():
+ skel.Parse()
+
+ def GetSkeletonGatherer(self):
+ '''Returns the gatherer for the alternate skeleton that should be used,
+ based on the expressions for selecting skeletons, or None if the skeleton
+ from the English version of the structure should be used.
+ '''
+ for expr in self.skeletons:
+ if self.EvaluateCondition(expr):
+ return self.skeletons[expr]
+ return None
+
+ def HasFileForLanguage(self):
+ return self.attrs['type'] in ['tr_html', 'admin_template', 'txt',
+ 'muppet', 'igoogle', 'chrome_scaled_image',
+ 'chrome_html']
+
+ def ExpandVariables(self):
+ '''Variable expansion on structures is controlled by an XML attribute.
+
+ However, old files assume that expansion is always on for Rc files.
+
+ Returns:
+ A boolean.
+ '''
+ attrs = self.GetRoot().attrs
+ if 'grit_version' in attrs and attrs['grit_version'] > 1:
+ return self.attrs['expand_variables'] == 'true'
+ else:
+ return (self.attrs['expand_variables'] == 'true' or
+ self.attrs['file'].lower().endswith('.rc'))
+
+ def _Substitute(self, text):
+ '''Perform local and global variable substitution.'''
+ if self.substituter:
+ text = self.substituter.Substitute(text)
+ return self.GetRoot().GetSubstituter().Substitute(text)
+
+ def RunCommandOnCurrentPlatform(self):
+ if self.attrs['run_command_on_platforms'] == '':
+ return True
+ else:
+ target_platforms = self.attrs['run_command_on_platforms'].split(',')
+ return platform.system() in target_platforms
+
+ def FileForLanguage(self, lang, output_dir, create_file=True,
+ return_if_not_generated=True):
+ '''Returns the filename of the file associated with this structure,
+ for the specified language.
+
+ Args:
+ lang: 'fr'
+ output_dir: 'c:\temp'
+ create_file: True
+ '''
+ assert self.HasFileForLanguage()
+ # If the source language is requested, and no extra changes are requested,
+ # use the existing file.
+ if ((not lang or lang == self.GetRoot().GetSourceLanguage()) and
+ self.attrs['expand_variables'] != 'true' and
+ (not self.attrs['run_command'] or
+ not self.RunCommandOnCurrentPlatform())):
+ if return_if_not_generated:
+ return self.ToRealPath(self.GetInputPath())
+ else:
+ return None
+
+ if self.attrs['output_filename'] != '':
+ filename = self.attrs['output_filename']
+ else:
+ filename = os.path.basename(self.attrs['file'])
+ assert len(filename)
+ filename = '%s_%s' % (lang, filename)
+ filename = os.path.join(output_dir, filename)
+
+ # Only create the output if it was requested by the call.
+ if create_file:
+ text = self.gatherer.Translate(
+ lang,
+ pseudo_if_not_available=self.PseudoIsAllowed(),
+ fallback_to_english=self.ShouldFallbackToEnglish(),
+ skeleton_gatherer=self.GetSkeletonGatherer())
+
+ file_contents = util.FixLineEnd(text, self.GetLineEnd())
+ if self.ExpandVariables():
+ # Note that we reapply substitution a second time here.
+ # This is because a) we need to look inside placeholders
+ # b) the substitution values are language-dependent
+ file_contents = self._Substitute(file_contents)
+
+ with open(filename, 'wb') as file_object:
+ output_stream = util.WrapOutputStream(file_object,
+ self.attrs['output_encoding'])
+ output_stream.write(file_contents)
+
+ if self.attrs['run_command'] and self.RunCommandOnCurrentPlatform():
+ # Run arbitrary commands after translation is complete so that it
+ # doesn't interfere with what's in translation console.
+ command = self.attrs['run_command'] % {'filename': filename}
+ result = os.system(command)
+ assert result == 0, '"%s" failed.' % command
+
+ return filename
+
+ @staticmethod
+ def Construct(parent, name, type, file, encoding='cp1252'):
+ '''Creates a new node which is a child of 'parent', with attributes set
+ by parameters of the same name.
+ '''
+ node = StructureNode()
+ node.StartParsing('structure', parent)
+ node.HandleAttribute('name', name)
+ node.HandleAttribute('type', type)
+ node.HandleAttribute('file', file)
+ node.HandleAttribute('encoding', encoding)
+ node.EndParsing()
+ return node
+
+ def SubstituteMessages(self, substituter):
+ '''Propagates substitution to gatherer.
+
+ Args:
+ substituter: a grit.util.Substituter object.
+ '''
+ assert hasattr(self, 'gatherer')
+ if self.ExpandVariables():
+ self.gatherer.SubstituteMessages(substituter)
+
diff --git a/chromium/tools/grit/grit/node/structure_unittest.py b/chromium/tools/grit/grit/node/structure_unittest.py
new file mode 100644
index 00000000000..a039bce984b
--- /dev/null
+++ b/chromium/tools/grit/grit/node/structure_unittest.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for <structure> nodes.
+'''
+
+import os
+import os.path
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import platform
+import tempfile
+import unittest
+import StringIO
+
+from grit import util
+from grit.node import structure
+from grit.format import rc
+
+
+class StructureUnittest(unittest.TestCase):
+ def testSkeleton(self):
+ grd = util.ParseGrdForUnittest('''
+ <structures>
+ <structure type="dialog" name="IDD_ABOUTBOX" file="klonk.rc" encoding="utf-16-le">
+ <skeleton expr="lang == 'fr'" variant_of_revision="1" file="klonk-alternate-skeleton.rc" />
+ </structure>
+ </structures>''', base_dir=util.PathFromRoot('grit/testdata'))
+ grd.SetOutputLanguage('fr')
+ grd.RunGatherers()
+ transl = ''.join(rc.Format(grd, 'fr', '.'))
+ self.failUnless(transl.count('040704') and transl.count('110978'))
+ self.failUnless(transl.count('2005",IDC_STATIC'))
+
+ def testRunCommandOnCurrentPlatform(self):
+ node = structure.StructureNode()
+ node.attrs = node.DefaultAttributes()
+ self.failUnless(node.RunCommandOnCurrentPlatform())
+ node.attrs['run_command_on_platforms'] = 'Nosuch'
+ self.failIf(node.RunCommandOnCurrentPlatform())
+ node.attrs['run_command_on_platforms'] = (
+ 'Nosuch,%s,Othernot' % platform.system())
+ self.failUnless(node.RunCommandOnCurrentPlatform())
+
+ def testVariables(self):
+ grd = util.ParseGrdForUnittest('''
+ <structures>
+ <structure type="chrome_html" name="hello_tmpl" file="structure_variables.html" expand_variables="true" variables="GREETING=Hello,THINGS=foo,, bar,, baz,EQUATION=2+2==4,filename=simple" flattenhtml="true"></structure>
+ </structures>''', base_dir=util.PathFromRoot('grit/testdata'))
+ grd.SetOutputLanguage('en')
+ grd.RunGatherers()
+ node, = grd.GetChildrenOfType(structure.StructureNode)
+ filename = node.Process(tempfile.gettempdir())
+ with open(os.path.join(tempfile.gettempdir(), filename)) as f:
+ result = f.read()
+ self.failUnlessEqual(('<h1>Hello!</h1>\n'
+ 'Some cool things are foo, bar, baz.\n'
+ 'Did you know that 2+2==4?\n'
+ '<p>\n'
+ ' Hello!\n'
+ '</p>\n'), result)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/node/variant.py b/chromium/tools/grit/grit/node/variant.py
new file mode 100644
index 00000000000..4206712b9fb
--- /dev/null
+++ b/chromium/tools/grit/grit/node/variant.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The <skeleton> element.
+'''
+
+
+from grit.node import base
+
+
+class SkeletonNode(base.Node):
+ '''A <skeleton> element.'''
+
+ # TODO(joi) Support inline skeleton variants as CDATA instead of requiring
+ # a 'file' attribute.
+
+ def MandatoryAttributes(self):
+ return ['expr', 'variant_of_revision', 'file']
+
+ def DefaultAttributes(self):
+ '''If not specified, 'encoding' will actually default to the parent node's
+ encoding.
+ '''
+ return {'encoding' : ''}
+
+ def _ContentType(self):
+ if self.attrs.has_key('file'):
+ return self._CONTENT_TYPE_NONE
+ else:
+ return self._CONTENT_TYPE_CDATA
+
+ def GetEncodingToUse(self):
+ if self.attrs['encoding'] == '':
+ return self.parent.attrs['encoding']
+ else:
+ return self.attrs['encoding']
+
+ def GetInputPath(self):
+ return self.attrs['file']
+
diff --git a/chromium/tools/grit/grit/pseudo.py b/chromium/tools/grit/grit/pseudo.py
new file mode 100644
index 00000000000..17a6ec6af23
--- /dev/null
+++ b/chromium/tools/grit/grit/pseudo.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Pseudotranslation support. Our pseudotranslations are based on the
+P-language, which is a simple vowel-extending language. Examples of P:
+ - "hello" becomes "hepellopo"
+ - "howdie" becomes "hopowdiepie"
+ - "because" becomes "bepecaupause" (but in our implementation we don't
+ handle the silent e at the end so it actually would return "bepecaupausepe"
+
+The P-language has the excellent quality of increasing the length of text
+by around 30-50% which is great for pseudotranslations, to stress test any
+GUI layouts etc.
+
+To make the pseudotranslations more obviously "not a translation" and to make
+them exercise any code that deals with encodings, we also transform all English
+vowels into equivalent vowels with diacriticals on them (rings, acutes,
+diaresis, and circumflex), and we write the "p" in the P-language as a Hebrew
+character Qof. It looks sort of like a latin character "p" but it is outside
+the latin-1 character set which will stress character encoding bugs.
+'''
+
+from grit import lazy_re
+from grit import tclib
+
+
+# An RFC language code for the P pseudolanguage.
+PSEUDO_LANG = 'x-P-pseudo'
+
+# Hebrew character Qof. It looks kind of like a 'p' but is outside
+# the latin-1 character set which is good for our purposes.
+# TODO(joi) For now using P instead of Qof, because of some bugs it used. Find
+# a better solution, i.e. one that introduces a non-latin1 character into the
+# pseudotranslation.
+#_QOF = u'\u05e7'
+_QOF = u'P'
+
+# How we map each vowel.
+_VOWELS = {
+ u'a' : u'\u00e5', # a with ring
+ u'e' : u'\u00e9', # e acute
+ u'i' : u'\u00ef', # i diaresis
+ u'o' : u'\u00f4', # o circumflex
+ u'u' : u'\u00fc', # u diaresis
+ u'y' : u'\u00fd', # y acute
+ u'A' : u'\u00c5', # A with ring
+ u'E' : u'\u00c9', # E acute
+ u'I' : u'\u00cf', # I diaresis
+ u'O' : u'\u00d4', # O circumflex
+ u'U' : u'\u00dc', # U diaresis
+ u'Y' : u'\u00dd', # Y acute
+}
+
+# Matches vowels and P
+_PSUB_RE = lazy_re.compile("(%s)" % '|'.join(_VOWELS.keys() + ['P']))
+
+
+# Pseudotranslations previously created. This is important for performance
+# reasons, especially since we routinely pseudotranslate the whole project
+# several or many different times for each build.
+_existing_translations = {}
+
+
+def MapVowels(str, also_p = False):
+ '''Returns a copy of 'str' where characters that exist as keys in _VOWELS
+ have been replaced with the corresponding value. If also_p is true, this
+ function will also change capital P characters into a Hebrew character Qof.
+ '''
+ def Repl(match):
+ if match.group() == 'p':
+ if also_p:
+ return _QOF
+ else:
+ return 'p'
+ else:
+ return _VOWELS[match.group()]
+ return _PSUB_RE.sub(Repl, str)
+
+
+def PseudoString(str):
+ '''Returns a pseudotranslation of the provided string, in our enhanced
+ P-language.'''
+ if str in _existing_translations:
+ return _existing_translations[str]
+
+ outstr = u''
+ ix = 0
+ while ix < len(str):
+ if str[ix] not in _VOWELS.keys():
+ outstr += str[ix]
+ ix += 1
+ else:
+ # We want to treat consecutive vowels as one composite vowel. This is not
+ # always accurate e.g. in composite words but good enough.
+ consecutive_vowels = u''
+ while ix < len(str) and str[ix] in _VOWELS.keys():
+ consecutive_vowels += str[ix]
+ ix += 1
+ changed_vowels = MapVowels(consecutive_vowels)
+ outstr += changed_vowels
+ outstr += _QOF
+ outstr += changed_vowels
+
+ _existing_translations[str] = outstr
+ return outstr
+
+
+def PseudoMessage(message):
+ '''Returns a pseudotranslation of the provided message.
+
+ Args:
+ message: tclib.Message()
+
+ Return:
+ tclib.Translation()
+ '''
+ transl = tclib.Translation()
+
+ for part in message.GetContent():
+ if isinstance(part, tclib.Placeholder):
+ transl.AppendPlaceholder(part)
+ else:
+ transl.AppendText(PseudoString(part))
+
+ return transl
+
diff --git a/chromium/tools/grit/grit/pseudo_rtl.py b/chromium/tools/grit/grit/pseudo_rtl.py
new file mode 100644
index 00000000000..dee448365c4
--- /dev/null
+++ b/chromium/tools/grit/grit/pseudo_rtl.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Pseudo RTL, (aka Fake Bidi) support. It simply wraps each word with
+Unicode RTL overrides.
+More info at https://sites.google.com/a/chromium.org/dev/Home/fake-bidi
+'''
+
+import re
+
+from grit import lazy_re
+from grit import tclib
+
+ACCENTED_STRINGS = {
+ 'a': u"\u00e5", 'e': u"\u00e9", 'i': u"\u00ee", 'o': u"\u00f6",
+ 'u': u"\u00fb", 'A': u"\u00c5", 'E': u"\u00c9", 'I': u"\u00ce",
+ 'O': u"\u00d6", 'U': u"\u00db", 'c': u"\u00e7", 'd': u"\u00f0",
+ 'n': u"\u00f1", 'p': u"\u00fe", 'y': u"\u00fd", 'C': u"\u00c7",
+ 'D': u"\u00d0", 'N': u"\u00d1", 'P': u"\u00de", 'Y': u"\u00dd",
+ 'f': u"\u0192", 's': u"\u0161", 'S': u"\u0160", 'z': u"\u017e",
+ 'Z': u"\u017d", 'g': u"\u011d", 'G': u"\u011c", 'h': u"\u0125",
+ 'H': u"\u0124", 'j': u"\u0135", 'J': u"\u0134", 'k': u"\u0137",
+ 'K': u"\u0136", 'l': u"\u013c", 'L': u"\u013b", 't': u"\u0163",
+ 'T': u"\u0162", 'w': u"\u0175", 'W': u"\u0174",
+ '$': u"\u20ac", '?': u"\u00bf", 'R': u"\u00ae", r'!': u"\u00a1",
+}
+
+# a character set containing the keys in ACCENTED_STRINGS
+# We should not accent characters in an escape sequence such as "\n".
+# To be safe, we assume every character following a backslash is an escaped
+# character. We also need to consider the case like "\\n", which means
+# a blackslash and a character "n", we will accent the character "n".
+TO_ACCENT = lazy_re.compile(
+ r'[%s]|\\[a-z\\]' % ''.join(ACCENTED_STRINGS.keys()))
+
+# Lex text so that we don't interfere with html tokens and entities.
+# This lexing scheme will handle all well formed tags and entities, html or
+# xhtml. It will not handle comments, CDATA sections, or the unescaping tags:
+# script, style, xmp or listing. If any of those appear in messages,
+# something is wrong.
+TOKENS = [ lazy_re.compile(
+ '^%s' % pattern, # match at the beginning of input
+ re.I | re.S # html tokens are case-insensitive
+ )
+ for pattern in
+ (
+ # a run of non html special characters
+ r'[^<&]+',
+ # a tag
+ (r'</?[a-z]\w*' # beginning of tag
+ r'(?:\s+\w+(?:\s*=\s*' # attribute start
+ r'(?:[^\s"\'>]+|"[^\"]*"|\'[^\']*\'))?' # attribute value
+ r')*\s*/?>'),
+ # an entity
+ r'&(?:[a-z]\w+|#\d+|#x[\da-f]+);',
+ # an html special character not part of a special sequence
+ r'.'
+ ) ]
+
+ALPHABETIC_RUN = lazy_re.compile(r'([^\W0-9_]+)')
+
+RLO = u'\u202e'
+PDF = u'\u202c'
+
+def PseudoRTLString(text):
+ '''Returns a fake bidirectional version of the source string. This code is
+ based on accentString above, in turn copied from Frank Tang.
+ '''
+ parts = []
+ while text:
+ m = None
+ for token in TOKENS:
+ m = token.search(text)
+ if m:
+ part = m.group(0)
+ text = text[len(part):]
+ if part[0] not in ('<', '&'):
+ # not a tag or entity, so accent
+ part = ALPHABETIC_RUN.sub(lambda run: RLO + run.group() + PDF, part)
+ parts.append(part)
+ break
+ return ''.join(parts)
+
+
+def PseudoRTLMessage(message):
+ '''Returns a pseudo-RTL (aka Fake-Bidi) translation of the provided message.
+
+ Args:
+ message: tclib.Message()
+
+ Return:
+ tclib.Translation()
+ '''
+ transl = tclib.Translation()
+ for part in message.GetContent():
+ if isinstance(part, tclib.Placeholder):
+ transl.AppendPlaceholder(part)
+ else:
+ transl.AppendText(PseudoRTLString(part))
+
+ return transl
diff --git a/chromium/tools/grit/grit/pseudo_unittest.py b/chromium/tools/grit/grit/pseudo_unittest.py
new file mode 100644
index 00000000000..ecf34ff0499
--- /dev/null
+++ b/chromium/tools/grit/grit/pseudo_unittest.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.pseudo'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import unittest
+
+from grit import pseudo
+from grit import tclib
+
+
+class PseudoUnittest(unittest.TestCase):
+ def testVowelMapping(self):
+ self.failUnless(pseudo.MapVowels('abebibobuby') ==
+ u'\u00e5b\u00e9b\u00efb\u00f4b\u00fcb\u00fd')
+ self.failUnless(pseudo.MapVowels('ABEBIBOBUBY') ==
+ u'\u00c5B\u00c9B\u00cfB\u00d4B\u00dcB\u00dd')
+
+ def testPseudoString(self):
+ out = pseudo.PseudoString('hello')
+ self.failUnless(out == pseudo.MapVowels(u'hePelloPo', True))
+
+ def testConsecutiveVowels(self):
+ out = pseudo.PseudoString("beautiful weather, ain't it?")
+ self.failUnless(out == pseudo.MapVowels(
+ u"beauPeautiPifuPul weaPeathePer, aiPain't iPit?", 1))
+
+ def testCapitals(self):
+ out = pseudo.PseudoString("HOWDIE DOODIE, DR. JONES")
+ self.failUnless(out == pseudo.MapVowels(
+ u"HOPOWDIEPIE DOOPOODIEPIE, DR. JOPONEPES", 1))
+
+ def testPseudoMessage(self):
+ msg = tclib.Message(text='Hello USERNAME, how are you?',
+ placeholders=[
+ tclib.Placeholder('USERNAME', '%s', 'Joi')])
+ trans = pseudo.PseudoMessage(msg)
+ # TODO(joi) It would be nicer if 'you' -> 'youPou' instead of
+ # 'you' -> 'youPyou' and if we handled the silent e in 'are'
+ self.failUnless(trans.GetPresentableContent() ==
+ pseudo.MapVowels(
+ u'HePelloPo USERNAME, hoPow aParePe youPyou?', 1))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/scons.py b/chromium/tools/grit/grit/scons.py
new file mode 100755
index 00000000000..8545767d219
--- /dev/null
+++ b/chromium/tools/grit/grit/scons.py
@@ -0,0 +1,255 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''SCons integration for GRIT.
+'''
+
+# NOTE: DO NOT IMPORT ANY GRIT STUFF HERE - we import lazily so that
+# grit and its dependencies aren't imported until actually needed.
+
+import os
+import types
+
+def _IsDebugEnabled():
+ return 'GRIT_DEBUG' in os.environ and os.environ['GRIT_DEBUG'] == '1'
+
+def _SourceToFile(source):
+ '''Return the path to the source file, given the 'source' argument as provided
+ by SCons to the _Builder or _Emitter functions.
+ '''
+ # Get the filename of the source. The 'source' parameter can be a string,
+ # a "node", or a list of strings or nodes.
+ if isinstance(source, types.ListType):
+ source = str(source[0])
+ else:
+ source = str(source)
+ return source
+
+
+def _ParseRcFlags(flags):
+ """Gets a mapping of defines.
+
+ Args:
+ flags: env['RCFLAGS']; the input defines.
+
+ Returns:
+ A tuple of (defines, res_file):
+ defines: A mapping of {name: val}
+ res_file: None, or the specified res file for static file dependencies.
+ """
+ from grit import util
+
+ defines = {}
+ res_file = None
+ # Get the CPP defines from the environment.
+ res_flag = '--res_file='
+ for flag in flags:
+ if flag.startswith(res_flag):
+ res_file = flag[len(res_flag):]
+ continue
+ if flag.startswith('/D'):
+ flag = flag[2:]
+ name, val = util.ParseDefine(flag)
+ # Only apply to first instance of a given define
+ if name not in defines:
+ defines[name] = val
+ return (defines, res_file)
+
+
+def _Builder(target, source, env):
+ print _SourceToFile(source)
+
+ from grit import grit_runner
+ from grit.tool import build
+ options = grit_runner.Options()
+ # This sets options to default values
+ options.ReadOptions([])
+ options.input = _SourceToFile(source)
+
+ # TODO(joi) Check if we can get the 'verbose' option from the environment.
+
+ builder = build.RcBuilder(defines=_ParseRcFlags(env['RCFLAGS'])[0])
+
+ # To ensure that our output files match what we promised SCons, we
+ # use the list of targets provided by SCons and update the file paths in
+ # our .grd input file with the targets.
+ builder.scons_targets = [str(t) for t in target]
+ builder.Run(options, [])
+ return None # success
+
+
+def _GetOutputFiles(grd, base_dir):
+ """Processes outputs listed in the grd into rc_headers and rc_alls.
+
+ Note that anything that's not an rc_header is classified as an rc_all.
+
+ Args:
+ grd: An open GRD reader.
+
+ Returns:
+ A tuple of (rc_headers, rc_alls, lang_folders):
+ rc_headers: Outputs marked as rc_header.
+ rc_alls: All other outputs.
+ lang_folders: The output language folders.
+ """
+ rc_headers = []
+ rc_alls = []
+ lang_folders = {}
+
+ # Explicit output files.
+ for output in grd.GetOutputFiles():
+ path = os.path.join(base_dir, output.GetFilename())
+ if (output.GetType() == 'rc_header'):
+ rc_headers.append(path)
+ else:
+ rc_alls.append(path)
+ if _IsDebugEnabled():
+ print 'GRIT: Added target %s' % path
+ if output.attrs['lang'] != '':
+ lang_folders[output.attrs['lang']] = os.path.dirname(path)
+
+ return (rc_headers, rc_alls, lang_folders)
+
+
+def _ProcessNodes(grd, base_dir, lang_folders):
+ """Processes the GRD nodes to figure out file dependencies.
+
+ Args:
+ grd: An open GRD reader.
+ base_dir: The base directory for filenames.
+ lang_folders: THe output language folders.
+
+ Returns:
+ A tuple of (structure_outputs, translated_files, static_files):
+ structure_outputs: Structures marked as sconsdep.
+ translated_files: Files that are structures or skeletons, and get
+ translated by GRIT.
+ static_files: Files that are includes, and are used directly by res files.
+ """
+ structure_outputs = []
+ translated_files = []
+ static_files = []
+
+ # Go through nodes, figuring out resources. Also output certain resources
+ # as build targets, based on the sconsdep flag.
+ for node in grd.ActiveDescendants():
+ with node:
+ file = node.ToRealPath(node.GetInputPath())
+ if node.name == 'structure':
+ translated_files.append(os.path.abspath(file))
+ # TODO(joi) Should remove the "if sconsdep is true" thing as it is a
+ # hack - see grit/node/structure.py
+ if node.HasFileForLanguage() and node.attrs['sconsdep'] == 'true':
+ for lang in lang_folders:
+ path = node.FileForLanguage(lang, lang_folders[lang],
+ create_file=False,
+ return_if_not_generated=False)
+ if path:
+ structure_outputs.append(path)
+ if _IsDebugEnabled():
+ print 'GRIT: Added target %s' % path
+ elif (node.name == 'skeleton' or (node.name == 'file' and node.parent and
+ node.parent.name == 'translations')):
+ translated_files.append(os.path.abspath(file))
+ elif node.name == 'include':
+ # If it's added by file name and the file isn't easy to find, don't make
+ # it a dependency. This could add some build flakiness, but it doesn't
+ # work otherwise.
+ if node.attrs['filenameonly'] != 'true' or os.path.exists(file):
+ static_files.append(os.path.abspath(file))
+ # If it's output from mk, look in the output directory.
+ elif node.attrs['mkoutput'] == 'true':
+ static_files.append(os.path.join(base_dir, os.path.basename(file)))
+
+ return (structure_outputs, translated_files, static_files)
+
+
+def _SetDependencies(env, base_dir, res_file, rc_alls, translated_files,
+ static_files):
+ """Sets dependencies in the environment.
+
+ Args:
+ env: The SCons environment.
+ base_dir: The base directory for filenames.
+ res_file: The res_file specified in the RC flags.
+ rc_alls: All non-rc_header outputs.
+ translated_files: Files that are structures or skeletons, and get
+ translated by GRIT.
+ static_files: Files that are includes, and are used directly by res files.
+ """
+ if res_file:
+ env.Depends(os.path.join(base_dir, res_file), static_files)
+ else:
+ # Make a best effort dependency setup when no res file is specified.
+ translated_files.extend(static_files)
+
+ for rc_all in rc_alls:
+ env.Depends(rc_all, translated_files)
+
+
+def _Emitter(target, source, env):
+ """Modifies the list of targets to include all outputs.
+
+ Note that this also sets up the dependencies, even though it's an emitter
+ rather than a scanner. This is so that the resource header file doesn't show
+ as having dependencies.
+
+ Args:
+ target: The list of targets to emit for.
+ source: The source or list of sources for the target.
+ env: The SCons environment.
+
+ Returns:
+ A tuple of (targets, sources).
+ """
+ from grit import grd_reader
+ from grit import util
+
+ (defines, res_file) = _ParseRcFlags(env['RCFLAGS'])
+
+ grd = grd_reader.Parse(_SourceToFile(source), debug=_IsDebugEnabled())
+ # TODO(jperkins): This is a hack to get an output context set for the reader.
+ # This should really be smarter about the language.
+ grd.SetOutputLanguage('en')
+ grd.SetDefines(defines)
+
+ base_dir = util.dirname(str(target[0]))
+ (rc_headers, rc_alls, lang_folders) = _GetOutputFiles(grd, base_dir)
+ (structure_outputs, translated_files, static_files) = _ProcessNodes(grd,
+ base_dir, lang_folders)
+
+ rc_alls.extend(structure_outputs)
+ _SetDependencies(env, base_dir, res_file, rc_alls, translated_files,
+ static_files)
+
+ targets = rc_headers
+ targets.extend(rc_alls)
+
+ # Return target and source lists.
+ return (targets, source)
+
+
+# Function name is mandated by newer versions of SCons.
+def generate(env):
+ # Importing this module should be possible whenever this function is invoked
+ # since it should only be invoked by SCons.
+ import SCons.Builder
+ import SCons.Action
+
+ # The varlist parameter tells SCons that GRIT needs to be invoked again
+ # if RCFLAGS has changed since last compilation.
+ build_action = SCons.Action.FunctionAction(_Builder, varlist=['RCFLAGS'])
+ emit_action = SCons.Action.FunctionAction(_Emitter, varlist=['RCFLAGS'])
+
+ builder = SCons.Builder.Builder(action=build_action, emitter=emit_action,
+ src_suffix='.grd')
+
+ # Add our builder and scanner to the environment.
+ env.Append(BUILDERS = {'GRIT': builder})
+
+
+# Function name is mandated by newer versions of SCons.
+def exists(env):
+ return 1
diff --git a/chromium/tools/grit/grit/shortcuts.py b/chromium/tools/grit/grit/shortcuts.py
new file mode 100644
index 00000000000..69a4386de3d
--- /dev/null
+++ b/chromium/tools/grit/grit/shortcuts.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Stuff to prevent conflicting shortcuts.
+'''
+
+from grit import lazy_re
+
+
+class ShortcutGroup(object):
+ '''Manages a list of cliques that belong together in a single shortcut
+ group. Knows how to detect conflicting shortcut keys.
+ '''
+
+ # Matches shortcut keys, e.g. &J
+ SHORTCUT_RE = lazy_re.compile('([^&]|^)(&[A-Za-z])')
+
+ def __init__(self, name):
+ self.name = name
+ # Map of language codes to shortcut keys used (which is a map of
+ # shortcut keys to counts).
+ self.keys_by_lang = {}
+ # List of cliques in this group
+ self.cliques = []
+
+ def AddClique(self, c):
+ for existing_clique in self.cliques:
+ if existing_clique.GetId() == c.GetId():
+ # This happens e.g. when we have e.g.
+ # <if expr1><structure 1></if> <if expr2><structure 2></if>
+ # where only one will really be included in the output.
+ return
+
+ self.cliques.append(c)
+ for (lang, msg) in c.clique.items():
+ if lang not in self.keys_by_lang:
+ self.keys_by_lang[lang] = {}
+ keymap = self.keys_by_lang[lang]
+
+ content = msg.GetRealContent()
+ keys = [groups[1] for groups in self.SHORTCUT_RE.findall(content)]
+ for key in keys:
+ key = key.upper()
+ if key in keymap:
+ keymap[key] += 1
+ else:
+ keymap[key] = 1
+
+ def GenerateWarnings(self, tc_project):
+ # For any language that has more than one occurrence of any shortcut,
+ # make a list of the conflicting shortcuts.
+ problem_langs = {}
+ for (lang, keys) in self.keys_by_lang.items():
+ for (key, count) in keys.items():
+ if count > 1:
+ if lang not in problem_langs:
+ problem_langs[lang] = []
+ problem_langs[lang].append(key)
+
+ warnings = []
+ if len(problem_langs):
+ warnings.append("WARNING - duplicate keys exist in shortcut group %s" %
+ self.name)
+ for (lang,keys) in problem_langs.items():
+ warnings.append(" %6s duplicates: %s" % (lang, ', '.join(keys)))
+ return warnings
+
+
+def GenerateDuplicateShortcutsWarnings(uberclique, tc_project):
+ '''Given an UberClique and a project name, will print out helpful warnings
+ if there are conflicting shortcuts within shortcut groups in the provided
+ UberClique.
+
+ Args:
+ uberclique: clique.UberClique()
+ tc_project: 'MyProjectNameInTheTranslationConsole'
+
+ Returns:
+ ['warning line 1', 'warning line 2', ...]
+ '''
+ warnings = []
+ groups = {}
+ for c in uberclique.AllCliques():
+ for group in c.shortcut_groups:
+ if group not in groups:
+ groups[group] = ShortcutGroup(group)
+ groups[group].AddClique(c)
+ for group in groups.values():
+ warnings += group.GenerateWarnings(tc_project)
+ return warnings
+
diff --git a/chromium/tools/grit/grit/shortcuts_unittests.py b/chromium/tools/grit/grit/shortcuts_unittests.py
new file mode 100644
index 00000000000..421cfb297ca
--- /dev/null
+++ b/chromium/tools/grit/grit/shortcuts_unittests.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.shortcuts
+'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import unittest
+import StringIO
+
+from grit import shortcuts
+from grit import clique
+from grit import tclib
+from grit.gather import rc
+
+class ShortcutsUnittest(unittest.TestCase):
+
+ def setUp(self):
+ self.uq = clique.UberClique()
+
+ def testFunctionality(self):
+ c = self.uq.MakeClique(tclib.Message(text="Hello &there"))
+ c.AddToShortcutGroup('group_name')
+ c = self.uq.MakeClique(tclib.Message(text="Howdie &there partner"))
+ c.AddToShortcutGroup('group_name')
+
+ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
+ self.failUnless(warnings)
+
+ def testAmpersandEscaping(self):
+ c = self.uq.MakeClique(tclib.Message(text="Hello &there"))
+ c.AddToShortcutGroup('group_name')
+ c = self.uq.MakeClique(tclib.Message(text="S&&T are the &letters S and T"))
+ c.AddToShortcutGroup('group_name')
+
+ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
+ self.failUnless(len(warnings) == 0)
+
+ def testDialog(self):
+ dlg = rc.Dialog(StringIO.StringIO('''\
+IDD_SIDEBAR_RSS_PANEL_PROPPAGE DIALOGEX 0, 0, 239, 221
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ PUSHBUTTON "Add &URL",IDC_SIDEBAR_RSS_ADD_URL,182,53,57,14
+ EDITTEXT IDC_SIDEBAR_RSS_NEW_URL,0,53,178,15,ES_AUTOHSCROLL
+ PUSHBUTTON "&Remove",IDC_SIDEBAR_RSS_REMOVE,183,200,56,14
+ PUSHBUTTON "&Edit",IDC_SIDEBAR_RSS_EDIT,123,200,56,14
+ CONTROL "&Automatically add commonly viewed clips",
+ IDC_SIDEBAR_RSS_AUTO_ADD,"Button",BS_AUTOCHECKBOX |
+ BS_MULTILINE | WS_TABSTOP,0,200,120,17
+ PUSHBUTTON "",IDC_SIDEBAR_RSS_HIDDEN,179,208,6,6,NOT WS_VISIBLE
+ LTEXT "You can display clips from blogs, news sites, and other online sources.",
+ IDC_STATIC,0,0,239,10
+ LISTBOX IDC_SIDEBAR_DISPLAYED_FEED_LIST,0,69,239,127,LBS_SORT |
+ LBS_OWNERDRAWFIXED | LBS_HASSTRINGS |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL |
+ WS_TABSTOP
+ LTEXT "Add a clip from a recently viewed website by clicking Add Recent Clips.",
+ IDC_STATIC,0,13,141,19
+ LTEXT "Or, if you know a site supports RSS or Atom, you can enter the RSS or Atom URL below and add it to your list of Web Clips.",
+ IDC_STATIC,0,33,239,18
+ PUSHBUTTON "Add Recent &Clips (10)...",
+ IDC_SIDEBAR_RSS_ADD_RECENT_CLIPS,146,14,93,14
+END'''), 'IDD_SIDEBAR_RSS_PANEL_PROPPAGE')
+ dlg.SetUberClique(self.uq)
+ dlg.Parse()
+
+ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(self.uq, 'PROJECT')
+ self.failUnless(len(warnings) == 0)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/tclib.py b/chromium/tools/grit/grit/tclib.py
new file mode 100644
index 00000000000..b4c15db04df
--- /dev/null
+++ b/chromium/tools/grit/grit/tclib.py
@@ -0,0 +1,235 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Adaptation of the extern.tclib classes for our needs.
+'''
+
+
+import re
+import types
+
+from grit import exception
+from grit import lazy_re
+import grit.extern.tclib
+
+
+# Matches whitespace sequences which can be folded into a single whitespace
+# character. This matches single characters so that non-spaces are replaced
+# with spaces.
+_FOLD_WHITESPACE = re.compile(r'\s+')
+
+
+def Identity(i):
+ return i
+
+
+class BaseMessage(object):
+ '''Base class with methods shared by Message and Translation.
+ '''
+
+ def __init__(self, text='', placeholders=[], description='', meaning=''):
+ self.parts = []
+ self.placeholders = []
+ self.meaning = meaning
+ self.dirty = True # True if self.id is (or might be) wrong
+ self.id = 0
+ self.SetDescription(description)
+
+ if text != '':
+ if not placeholders or placeholders == []:
+ self.AppendText(text)
+ else:
+ tag_map = {}
+ for placeholder in placeholders:
+ tag_map[placeholder.GetPresentation()] = [placeholder, 0]
+ # This creates a regexp like '(TAG1|TAG2|TAG3)'.
+ # The tags have to be sorted in order of decreasing length, so that
+ # longer tags are substituted before shorter tags that happen to be
+ # substrings of the longer tag.
+ # E.g. "EXAMPLE_FOO_NAME" must be matched before "EXAMPLE_FOO",
+ # otherwise "EXAMPLE_FOO" splits "EXAMPLE_FOO_NAME" too.
+ tags = tag_map.keys()
+ tags.sort(cmp=lambda x,y: len(x) - len(y) or cmp(x, y), reverse=True)
+ tag_re = '(' + '|'.join(tags) + ')'
+ chunked_text = re.split(tag_re, text)
+ for chunk in chunked_text:
+ if chunk: # ignore empty chunk
+ if tag_map.has_key(chunk):
+ self.AppendPlaceholder(tag_map[chunk][0])
+ tag_map[chunk][1] += 1 # increase placeholder use count
+ else:
+ self.AppendText(chunk)
+ for key in tag_map.keys():
+ assert tag_map[key][1] != 0
+
+ def GetRealContent(self, escaping_function=Identity):
+ '''Returns the original content, i.e. what your application and users
+ will see.
+
+ Specify a function to escape each translateable bit, if you like.
+ '''
+ bits = []
+ for item in self.parts:
+ if isinstance(item, types.StringTypes):
+ bits.append(escaping_function(item))
+ else:
+ bits.append(item.GetOriginal())
+ return ''.join(bits)
+
+ def GetPresentableContent(self):
+ presentable_content = []
+ for part in self.parts:
+ if isinstance(part, Placeholder):
+ presentable_content.append(part.GetPresentation())
+ else:
+ presentable_content.append(part)
+ return ''.join(presentable_content)
+
+ def AppendPlaceholder(self, placeholder):
+ assert isinstance(placeholder, Placeholder)
+ dup = False
+ for other in self.GetPlaceholders():
+ if other.presentation == placeholder.presentation:
+ assert other.original == placeholder.original
+ dup = True
+
+ if not dup:
+ self.placeholders.append(placeholder)
+ self.parts.append(placeholder)
+ self.dirty = True
+
+ def AppendText(self, text):
+ assert isinstance(text, types.StringTypes)
+ assert text != ''
+
+ self.parts.append(text)
+ self.dirty = True
+
+ def GetContent(self):
+ '''Returns the parts of the message. You may modify parts if you wish.
+ Note that you must not call GetId() on this object until you have finished
+ modifying the contents.
+ '''
+ self.dirty = True # user might modify content
+ return self.parts
+
+ def GetDescription(self):
+ return self.description
+
+ def SetDescription(self, description):
+ self.description = _FOLD_WHITESPACE.sub(' ', description)
+
+ def GetMeaning(self):
+ return self.meaning
+
+ def GetId(self):
+ if self.dirty:
+ self.id = self.GenerateId()
+ self.dirty = False
+ return self.id
+
+ def GenerateId(self):
+ # Must use a UTF-8 encoded version of the presentable content, along with
+ # the meaning attribute, to match the TC.
+ return grit.extern.tclib.GenerateMessageId(
+ self.GetPresentableContent().encode('utf-8'), self.meaning)
+
+ def GetPlaceholders(self):
+ return self.placeholders
+
+ def FillTclibBaseMessage(self, msg):
+ msg.SetDescription(self.description.encode('utf-8'))
+
+ for part in self.parts:
+ if isinstance(part, Placeholder):
+ ph = grit.extern.tclib.Placeholder(
+ part.presentation.encode('utf-8'),
+ part.original.encode('utf-8'),
+ part.example.encode('utf-8'))
+ msg.AppendPlaceholder(ph)
+ else:
+ msg.AppendText(part.encode('utf-8'))
+
+
+class Message(BaseMessage):
+ '''A message.'''
+
+ def __init__(self, text='', placeholders=[], description='', meaning='',
+ assigned_id=None):
+ super(Message, self).__init__(text, placeholders, description, meaning)
+ self.assigned_id = assigned_id
+
+ def ToTclibMessage(self):
+ msg = grit.extern.tclib.Message('utf-8', meaning=self.meaning)
+ self.FillTclibBaseMessage(msg)
+ return msg
+
+ def GetId(self):
+ '''Use the assigned id if we have one.'''
+ if self.assigned_id:
+ return self.assigned_id
+
+ return super(Message, self).GetId()
+
+ def HasAssignedId(self):
+ '''Returns True if this message has an assigned id.'''
+ return bool(self.assigned_id)
+
+
+class Translation(BaseMessage):
+ '''A translation.'''
+
+ def __init__(self, text='', id='', placeholders=[], description='', meaning=''):
+ super(Translation, self).__init__(text, placeholders, description, meaning)
+ self.id = id
+
+ def GetId(self):
+ assert id != '', "ID has not been set."
+ return self.id
+
+ def SetId(self, id):
+ self.id = id
+
+ def ToTclibMessage(self):
+ msg = grit.extern.tclib.Message(
+ 'utf-8', id=self.id, meaning=self.meaning)
+ self.FillTclibBaseMessage(msg)
+ return msg
+
+
+class Placeholder(grit.extern.tclib.Placeholder):
+ '''Modifies constructor to accept a Unicode string
+ '''
+
+ # Must match placeholder presentation names
+ _NAME_RE = lazy_re.compile('^[A-Za-z0-9_]+$')
+
+ def __init__(self, presentation, original, example):
+ '''Creates a new placeholder.
+
+ Args:
+ presentation: 'USERNAME'
+ original: '%s'
+ example: 'Joi'
+ '''
+ assert presentation != ''
+ assert original != ''
+ assert example != ''
+ if not self._NAME_RE.match(presentation):
+ raise exception.InvalidPlaceholderName(presentation)
+ self.presentation = presentation
+ self.original = original
+ self.example = example
+
+ def GetPresentation(self):
+ return self.presentation
+
+ def GetOriginal(self):
+ return self.original
+
+ def GetExample(self):
+ return self.example
+
+
diff --git a/chromium/tools/grit/grit/tclib_unittest.py b/chromium/tools/grit/grit/tclib_unittest.py
new file mode 100644
index 00000000000..e85bb946e99
--- /dev/null
+++ b/chromium/tools/grit/grit/tclib_unittest.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.tclib'''
+
+
+import sys
+import os.path
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import types
+import unittest
+
+from grit import tclib
+
+from grit import exception
+import grit.extern.tclib
+
+
+class TclibUnittest(unittest.TestCase):
+ def testInit(self):
+ msg = tclib.Message(text=u'Hello Earthlings',
+ description='Greetings\n\t message')
+ self.failUnlessEqual(msg.GetPresentableContent(), 'Hello Earthlings')
+ self.failUnless(isinstance(msg.GetPresentableContent(), types.StringTypes))
+ self.failUnlessEqual(msg.GetDescription(), 'Greetings message')
+
+ def testGetAttr(self):
+ msg = tclib.Message()
+ msg.AppendText(u'Hello') # Tests __getattr__
+ self.failUnless(msg.GetPresentableContent() == 'Hello')
+ self.failUnless(isinstance(msg.GetPresentableContent(), types.StringTypes))
+
+ def testAll(self):
+ text = u'Howdie USERNAME'
+ phs = [tclib.Placeholder(u'USERNAME', u'%s', 'Joi')]
+ msg = tclib.Message(text=text, placeholders=phs)
+ self.failUnless(msg.GetPresentableContent() == 'Howdie USERNAME')
+
+ trans = tclib.Translation(text=text, placeholders=phs)
+ self.failUnless(trans.GetPresentableContent() == 'Howdie USERNAME')
+ self.failUnless(isinstance(trans.GetPresentableContent(), types.StringTypes))
+
+ def testUnicodeReturn(self):
+ text = u'\u00fe'
+ msg = tclib.Message(text=text)
+ self.failUnless(msg.GetPresentableContent() == text)
+ from_list = msg.GetContent()[0]
+ self.failUnless(from_list == text)
+
+ def testRegressionTranslationInherited(self):
+ '''Regression tests a bug that was caused by grit.tclib.Translation
+ inheriting from the translation console's Translation object
+ instead of only owning an instance of it.
+ '''
+ msg = tclib.Message(text=u"BLA1\r\nFrom: BLA2 \u00fe BLA3",
+ placeholders=[
+ tclib.Placeholder('BLA1', '%s', '%s'),
+ tclib.Placeholder('BLA2', '%s', '%s'),
+ tclib.Placeholder('BLA3', '%s', '%s')])
+ transl = tclib.Translation(text=msg.GetPresentableContent(),
+ placeholders=msg.GetPlaceholders())
+ content = transl.GetContent()
+ self.failUnless(isinstance(content[3], types.UnicodeType))
+
+ def testFingerprint(self):
+ # This has Windows line endings. That is on purpose.
+ id = grit.extern.tclib.GenerateMessageId(
+ 'Google Desktop for Enterprise\r\n'
+ 'Copyright (C) 2006 Google Inc.\r\n'
+ 'All Rights Reserved\r\n'
+ '\r\n'
+ '---------\r\n'
+ 'Contents\r\n'
+ '---------\r\n'
+ 'This distribution contains the following files:\r\n'
+ '\r\n'
+ 'GoogleDesktopSetup.msi - Installation and setup program\r\n'
+ 'GoogleDesktop.adm - Group Policy administrative template file\r\n'
+ 'AdminGuide.pdf - Google Desktop for Enterprise administrative guide\r\n'
+ '\r\n'
+ '\r\n'
+ '--------------\r\n'
+ 'Documentation\r\n'
+ '--------------\r\n'
+ 'Full documentation and installation instructions are in the \r\n'
+ 'administrative guide, and also online at \r\n'
+ 'http://desktop.google.com/enterprise/adminguide.html.\r\n'
+ '\r\n'
+ '\r\n'
+ '------------------------\r\n'
+ 'IBM Lotus Notes Plug-In\r\n'
+ '------------------------\r\n'
+ 'The Lotus Notes plug-in is included in the release of Google \r\n'
+ 'Desktop for Enterprise. The IBM Lotus Notes Plug-in for Google \r\n'
+ 'Desktop indexes mail, calendar, task, contact and journal \r\n'
+ 'documents from Notes. Discussion documents including those from \r\n'
+ 'the discussion and team room templates can also be indexed by \r\n'
+ 'selecting an option from the preferences. Once indexed, this data\r\n'
+ 'will be returned in Google Desktop searches. The corresponding\r\n'
+ 'document can be opened in Lotus Notes from the Google Desktop \r\n'
+ 'results page.\r\n'
+ '\r\n'
+ 'Install: The plug-in will install automatically during the Google \r\n'
+ 'Desktop setup process if Lotus Notes is already installed. Lotus \r\n'
+ 'Notes must not be running in order for the install to occur. \r\n'
+ '\r\n'
+ 'Preferences: Preferences and selection of databases to index are\r\n'
+ 'set in the \'Google Desktop for Notes\' dialog reached through the \r\n'
+ '\'Actions\' menu.\r\n'
+ '\r\n'
+ 'Reindexing: Selecting \'Reindex all databases\' will index all the \r\n'
+ 'documents in each database again.\r\n'
+ '\r\n'
+ '\r\n'
+ 'Notes Plug-in Known Issues\r\n'
+ '---------------------------\r\n'
+ '\r\n'
+ 'If the \'Google Desktop for Notes\' item is not available from the \r\n'
+ 'Lotus Notes Actions menu, then installation was not successful. \r\n'
+ 'Installation consists of writing one file, notesgdsplugin.dll, to \r\n'
+ 'the Notes application directory and a setting to the notes.ini \r\n'
+ 'configuration file. The most likely cause of an unsuccessful \r\n'
+ 'installation is that the installer was not able to locate the \r\n'
+ 'notes.ini file. Installation will complete if the user closes Notes\r\n'
+ 'and manually adds the following setting to this file on a new line:\r\n'
+ 'AddinMenus=notegdsplugin.dll\r\n'
+ '\r\n'
+ 'If the notesgdsplugin.dll file is not in the application directory\r\n'
+ '(e.g., C:\Program Files\Lotus\Notes) after Google Desktop \r\n'
+ 'installation, it is likely that Notes was not installed correctly. \r\n'
+ '\r\n'
+ 'Only local databases can be indexed. If they can be determined, \r\n'
+ 'the user\'s local mail file and address book will be included in the\r\n'
+ 'list automatically. Mail archives and other databases must be \r\n'
+ 'added with the \'Add\' button.\r\n'
+ '\r\n'
+ 'Some users may experience performance issues during the initial \r\n'
+ 'indexing of a database. The \'Perform the initial index of a \r\n'
+ 'database only when I\'m idle\' option will limit the indexing process\r\n'
+ 'to times when the user is not using the machine. If this does not \r\n'
+ 'alleviate the problem or the user would like to continually index \r\n'
+ 'but just do so more slowly or quickly, the GoogleWaitTime notes.ini\r\n'
+ 'value can be set. Increasing the GoogleWaitTime value will slow \r\n'
+ 'down the indexing process, and lowering the value will speed it up.\r\n'
+ 'A value of zero causes the fastest possible indexing. Removing the\r\n'
+ 'ini parameter altogether returns it to the default (20).\r\n'
+ '\r\n'
+ 'Crashes have been known to occur with certain types of history \r\n'
+ 'bookmarks. If the Notes client seems to crash randomly, try \r\n'
+ 'disabling the \'Index note history\' option. If it crashes before,\r\n'
+ 'you can get to the preferences, add the following line to your \r\n'
+ 'notes.ini file:\r\n'
+ 'GDSNoIndexHistory=1\r\n')
+ self.failUnless(id == '8961534701379422820')
+
+ def testPlaceholderNameChecking(self):
+ try:
+ ph = tclib.Placeholder('BINGO BONGO', 'bla', 'bla')
+ raise Exception("We shouldn't get here")
+ except exception.InvalidPlaceholderName:
+ pass # Expect exception to be thrown because presentation contained space
+
+ def testTagsWithCommonSubstring(self):
+ word = 'ABCDEFGHIJ'
+ text = ' '.join([word[:i] for i in range(1, 11)])
+ phs = [tclib.Placeholder(word[:i], str(i), str(i)) for i in range(1, 11)]
+ try:
+ msg = tclib.Message(text=text, placeholders=phs)
+ self.failUnless(msg.GetRealContent() == '1 2 3 4 5 6 7 8 9 10')
+ except:
+ self.fail('tclib.Message() should handle placeholders that are '
+ 'substrings of each other')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/test_suite_all.py b/chromium/tools/grit/grit/test_suite_all.py
new file mode 100644
index 00000000000..3f5c978d0ec
--- /dev/null
+++ b/chromium/tools/grit/grit/test_suite_all.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit test suite that collects all test cases for GRIT.'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import unittest
+
+
+# TODO(joi) Use unittest.defaultTestLoader to automatically load tests
+# from modules. Iterating over the directory and importing could then
+# automate this all the way, if desired.
+
+
+class TestSuiteAll(unittest.TestSuite):
+ def __init__(self):
+ super(TestSuiteAll, self).__init__()
+ # Imports placed here to prevent circular imports.
+ # pylint: disable-msg=C6204
+ import grit.clique_unittest
+ import grit.grd_reader_unittest
+ import grit.grit_runner_unittest
+ import grit.lazy_re_unittest
+ import grit.shortcuts_unittests
+ import grit.tclib_unittest
+ import grit.util_unittest
+ import grit.xtb_reader_unittest
+ import grit.format.android_xml_unittest
+ import grit.format.c_format_unittest
+ import grit.format.chrome_messages_json_unittest
+ import grit.format.data_pack_unittest
+ import grit.format.html_inline_unittest
+ import grit.format.js_map_format_unittest
+ import grit.format.rc_header_unittest
+ import grit.format.rc_unittest
+ import grit.format.resource_map_unittest
+ import grit.format.policy_templates.policy_template_generator_unittest
+ import grit.format.policy_templates.writers.adm_writer_unittest
+ import grit.format.policy_templates.writers.doc_writer_unittest
+ import grit.format.policy_templates.writers.json_writer_unittest
+ import grit.format.policy_templates.writers.plist_strings_writer_unittest
+ import grit.format.policy_templates.writers.plist_writer_unittest
+ import grit.format.policy_templates.writers.reg_writer_unittest
+ import grit.format.policy_templates.writers.template_writer_unittest
+ import grit.format.policy_templates.writers.xml_writer_base_unittest
+ import grit.gather.admin_template_unittest
+ import grit.gather.chrome_html_unittest
+ import grit.gather.chrome_scaled_image_unittest
+ import grit.gather.igoogle_strings_unittest
+ import grit.gather.muppet_strings_unittest
+ import grit.gather.policy_json_unittest
+ import grit.gather.rc_unittest
+ import grit.gather.tr_html_unittest
+ import grit.gather.txt_unittest
+ import grit.node.base_unittest
+ import grit.node.io_unittest
+ import grit.node.include_unittest
+ import grit.node.message_unittest
+ import grit.node.misc_unittest
+ import grit.node.structure_unittest #
+ import grit.node.custom.filename_unittest
+ import grit.tool.android2grd_unittest
+ import grit.tool.build_unittest
+ import grit.tool.buildinfo_unittest
+ import grit.tool.postprocess_unittest
+ import grit.tool.preprocess_unittest
+ import grit.tool.rc2grd_unittest
+ import grit.tool.transl2tc_unittest
+ import grit.tool.xmb_unittest
+
+ test_classes = [
+ grit.clique_unittest.MessageCliqueUnittest,
+ grit.grd_reader_unittest.GrdReaderUnittest,
+ grit.grit_runner_unittest.OptionArgsUnittest,
+ grit.lazy_re_unittest.LazyReUnittest,
+ grit.shortcuts_unittests.ShortcutsUnittest,
+ grit.tclib_unittest.TclibUnittest,
+ grit.util_unittest.UtilUnittest,
+ grit.xtb_reader_unittest.XtbReaderUnittest,
+ grit.format.android_xml_unittest.AndroidXmlUnittest,
+ grit.format.c_format_unittest.CFormatUnittest,
+ grit.format.chrome_messages_json_unittest.
+ ChromeMessagesJsonFormatUnittest,
+ grit.format.data_pack_unittest.FormatDataPackUnittest,
+ grit.format.html_inline_unittest.HtmlInlineUnittest,
+ grit.format.js_map_format_unittest.JsMapFormatUnittest,
+ grit.format.rc_header_unittest.RcHeaderFormatterUnittest,
+ grit.format.rc_unittest.FormatRcUnittest,
+ grit.format.resource_map_unittest.FormatResourceMapUnittest,
+ grit.format.policy_templates.policy_template_generator_unittest.
+ PolicyTemplateGeneratorUnittest,
+ grit.format.policy_templates.writers.adm_writer_unittest.
+ AdmWriterUnittest,
+ grit.format.policy_templates.writers.doc_writer_unittest.
+ DocWriterUnittest,
+ grit.format.policy_templates.writers.json_writer_unittest.
+ JsonWriterUnittest,
+ grit.format.policy_templates.writers.plist_strings_writer_unittest.
+ PListStringsWriterUnittest,
+ grit.format.policy_templates.writers.plist_writer_unittest.
+ PListWriterUnittest,
+ grit.format.policy_templates.writers.reg_writer_unittest.
+ RegWriterUnittest,
+ grit.format.policy_templates.writers.template_writer_unittest.
+ TemplateWriterUnittests,
+ grit.format.policy_templates.writers.xml_writer_base_unittest.
+ XmlWriterBaseTest,
+ grit.gather.admin_template_unittest.AdmGathererUnittest,
+ grit.gather.chrome_html_unittest.ChromeHtmlUnittest,
+ grit.gather.chrome_scaled_image_unittest.ChromeScaledImageUnittest,
+ grit.gather.igoogle_strings_unittest.IgoogleStringsUnittest,
+ grit.gather.muppet_strings_unittest.MuppetStringsUnittest,
+ grit.gather.policy_json_unittest.PolicyJsonUnittest,
+ grit.gather.rc_unittest.RcUnittest,
+ grit.gather.tr_html_unittest.ParserUnittest,
+ grit.gather.tr_html_unittest.TrHtmlUnittest,
+ grit.gather.txt_unittest.TxtUnittest,
+ grit.node.base_unittest.NodeUnittest,
+ grit.node.io_unittest.FileNodeUnittest,
+ grit.node.include_unittest.IncludeNodeUnittest,
+ grit.node.message_unittest.MessageUnittest,
+ grit.node.misc_unittest.GritNodeUnittest,
+ grit.node.misc_unittest.IfNodeUnittest,
+ grit.node.misc_unittest.ReleaseNodeUnittest,
+ grit.node.structure_unittest.StructureUnittest,
+ grit.node.custom.filename_unittest.WindowsFilenameUnittest,
+ grit.tool.android2grd_unittest.Android2GrdUnittest,
+ grit.tool.build_unittest.BuildUnittest,
+ grit.tool.buildinfo_unittest.BuildInfoUnittest,
+ grit.tool.postprocess_unittest.PostProcessingUnittest,
+ grit.tool.preprocess_unittest.PreProcessingUnittest,
+ grit.tool.rc2grd_unittest.Rc2GrdUnittest,
+ grit.tool.transl2tc_unittest.TranslationToTcUnittest,
+ grit.tool.xmb_unittest.XmbUnittest,
+ # add test classes here, in alphabetical order...
+ ]
+
+ for test_class in test_classes:
+ self.addTest(unittest.makeSuite(test_class))
+
+
+if __name__ == '__main__':
+ test_result = unittest.TextTestRunner(verbosity=2).run(TestSuiteAll())
+ sys.exit(len(test_result.errors) + len(test_result.failures))
diff --git a/chromium/tools/grit/grit/testdata/GoogleDesktop.adm b/chromium/tools/grit/grit/testdata/GoogleDesktop.adm
new file mode 100644
index 00000000000..758fb8ee0c6
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/GoogleDesktop.adm
@@ -0,0 +1,945 @@
+CLASS MACHINE
+ CATEGORY !!Cat_Google
+ CATEGORY !!Cat_GoogleDesktopSearch
+ KEYNAME "Software\Policies\Google\Google Desktop"
+
+ CATEGORY !!Cat_Preferences
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences"
+
+ CATEGORY !!Cat_IndexAndCaptureControl
+ POLICY !!Blacklist_Email
+ EXPLAIN !!Explain_Blacklist_Email
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ VALUENAME "1"
+ END POLICY
+
+ POLICY !!Blacklist_Gmail
+ EXPLAIN !!Explain_Blacklist_Gmail
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-pop"
+ VALUENAME "gmail"
+ END POLICY
+
+ POLICY !!Blacklist_WebHistory
+ EXPLAIN !!Explain_Blacklist_WebHistory
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ VALUENAME "2"
+ END POLICY
+
+ POLICY !!Blacklist_Chat
+ EXPLAIN !!Explain_Blacklist_Chat
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "3" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Text
+ EXPLAIN !!Explain_Blacklist_Text
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "4" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Media
+ EXPLAIN !!Explain_Blacklist_Media
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "5" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Contact
+ EXPLAIN !!Explain_Blacklist_Contact
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "9" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Calendar
+ EXPLAIN !!Explain_Blacklist_Calendar
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "10" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Task
+ EXPLAIN !!Explain_Blacklist_Task
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "11" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Note
+ EXPLAIN !!Explain_Blacklist_Note
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "12" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Journal
+ EXPLAIN !!Explain_Blacklist_Journal
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "13" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Word
+ EXPLAIN !!Explain_Blacklist_Word
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "DOC"
+ END POLICY
+
+ POLICY !!Blacklist_Excel
+ EXPLAIN !!Explain_Blacklist_Excel
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "XLS"
+ END POLICY
+
+ POLICY !!Blacklist_Powerpoint
+ EXPLAIN !!Explain_Blacklist_Powerpoint
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "PPT"
+ END POLICY
+
+ POLICY !!Blacklist_PDF
+ EXPLAIN !!Explain_Blacklist_PDF
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "PDF"
+ END POLICY
+
+ POLICY !!Blacklist_ZIP
+ EXPLAIN !!Explain_Blacklist_ZIP
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "ZIP"
+ END POLICY
+
+ POLICY !!Blacklist_HTTPS
+ EXPLAIN !!Explain_Blacklist_HTTPS
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-3"
+ VALUENAME "HTTPS"
+ END POLICY
+
+ POLICY !!Blacklist_PasswordProtectedOffice
+ EXPLAIN !!Explain_Blacklist_PasswordProtectedOffice
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-13"
+ VALUENAME "SECUREOFFICE"
+ END POLICY
+
+ POLICY !!Blacklist_URI_Contains
+ EXPLAIN !!Explain_Blacklist_URI_Contains
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-6"
+ PART !!Blacklist_URI_Contains LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Blacklist_Extensions
+ EXPLAIN !!Explain_Blacklist_Extensions
+ PART !!Blacklist_Extensions EDITTEXT
+ VALUENAME "file_extensions_to_skip"
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Disallow_UserSearchLocations
+ EXPLAIN !!Explain_Disallow_UserSearchLocations
+ VALUENAME user_search_locations
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Search_Location_Whitelist
+ EXPLAIN !!Explain_Search_Location_Whitelist
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\policy_search_location_whitelist"
+ PART !!Search_Locations_Whitelist LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Email_Retention
+ EXPLAIN !!Explain_Email_Retention
+ PART !!Email_Retention_Edit NUMERIC
+ VALUENAME "email_days_to_retain"
+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!Webpage_Retention
+ EXPLAIN !!Explain_Webpage_Retention
+ PART !!Webpage_Retention_Edit NUMERIC
+ VALUENAME "webpage_days_to_retain"
+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!File_Retention
+ EXPLAIN !!Explain_File_Retention
+ PART !!File_Retention_Edit NUMERIC
+ VALUENAME "file_days_to_retain"
+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!IM_Retention
+ EXPLAIN !!Explain_IM_Retention
+ PART !!IM_Retention_Edit NUMERIC
+ VALUENAME "im_days_to_retain"
+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Remove_Deleted_Items
+ EXPLAIN !!Explain_Remove_Deleted_Items
+ VALUENAME remove_deleted_items
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Allow_Simultaneous_Indexing
+ EXPLAIN !!Explain_Allow_Simultaneous_Indexing
+ VALUENAME simultaneous_indexing
+ VALUEON NUMERIC 1
+ END POLICY
+
+ END CATEGORY
+
+ POLICY !!Pol_TurnOffAdvancedFeatures
+ EXPLAIN !!Explain_TurnOffAdvancedFeatures
+ VALUENAME error_report_on
+ VALUEON NUMERIC 0
+ END POLICY
+
+ POLICY !!Pol_TurnOffImproveGd
+ EXPLAIN !!Explain_TurnOffImproveGd
+ VALUENAME improve_gd
+ VALUEON NUMERIC 0
+ VALUEOFF NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_NoPersonalizationInfo
+ EXPLAIN !!Explain_NoPersonalizationInfo
+ VALUENAME send_personalization_info
+ VALUEON NUMERIC 0
+ VALUEOFF NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_OneBoxMode
+ EXPLAIN !!Explain_OneBoxMode
+ VALUENAME onebox_mode
+ VALUEON NUMERIC 0
+ END POLICY
+
+ POLICY !!Pol_EncryptIndex
+ EXPLAIN !!Explain_EncryptIndex
+ VALUENAME encrypt_index
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Hyper
+ EXPLAIN !!Explain_Hyper
+ VALUENAME hyper_off
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Display_Mode
+ EXPLAIN !!Explain_Display_Mode
+ PART !!Pol_Display_Mode DROPDOWNLIST
+ VALUENAME display_mode
+ ITEMLIST
+ NAME !!Sidebar VALUE NUMERIC 1
+ NAME !!Deskbar VALUE NUMERIC 8
+ NAME !!FloatingDeskbar VALUE NUMERIC 4
+ NAME !!None VALUE NUMERIC 0
+ END ITEMLIST
+ END PART
+ END POLICY
+
+ END CATEGORY ; Preferences
+
+ CATEGORY !!Cat_Enterprise
+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise"
+
+ POLICY !!Pol_Autoupdate
+ EXPLAIN !!Explain_Autoupdate
+ VALUENAME autoupdate_host
+ VALUEON ""
+ END POLICY
+
+ POLICY !!Pol_AutoupdateAsSystem
+ EXPLAIN !!Explain_AutoupdateAsSystem
+ VALUENAME autoupdate_impersonate_user
+ VALUEON NUMERIC 0
+ VALUEOFF NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_EnterpriseTab
+ EXPLAIN !!Explain_EnterpriseTab
+ PART !!EnterpriseTabText EDITTEXT
+ VALUENAME enterprise_tab_text
+ END PART
+ PART !!EnterpriseTabHomepage EDITTEXT
+ VALUENAME enterprise_tab_homepage
+ END PART
+ PART !!EnterpriseTabHomepageQuery CHECKBOX
+ VALUENAME enterprise_tab_homepage_query
+ END PART
+ PART !!EnterpriseTabResults EDITTEXT
+ VALUENAME enterprise_tab_results
+ END PART
+ PART !!EnterpriseTabResultsQuery CHECKBOX
+ VALUENAME enterprise_tab_results_query
+ END PART
+ END POLICY
+
+ POLICY !!Pol_GSAHosts
+ EXPLAIN !!Explain_GSAHosts
+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\GSAHosts"
+ PART !!Pol_GSAHosts LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Pol_PolicyUnawareClientProhibitedFlag
+ EXPLAIN !!Explain_PolicyUnawareClientProhibitedFlag
+ KEYNAME "Software\Policies\Google\Google Desktop"
+ VALUENAME PolicyUnawareClientProhibitedFlag
+ END POLICY
+
+ POLICY !!Pol_MinimumAllowedVersion
+ EXPLAIN !!Explain_MinimumAllowedVersion
+ PART !!Pol_MinimumAllowedVersion EDITTEXT
+ VALUENAME minimum_allowed_version
+ END PART
+ END POLICY
+
+ POLICY !!Pol_MaximumAllowedVersion
+ EXPLAIN !!Explain_MaximumAllowedVersion
+ PART !!Pol_MaximumAllowedVersion EDITTEXT
+ VALUENAME maximum_allowed_version
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Disallow_Gadgets
+ EXPLAIN !!Explain_Disallow_Gadgets
+ VALUENAME disallow_gadgets
+ VALUEON NUMERIC 1
+ PART !!Disallow_Only_Non_Builtin_Gadgets CHECKBOX DEFCHECKED
+ VALUENAME disallow_only_non_builtin_gadgets
+ VALUEON NUMERIC 1
+ VALUEOFF NUMERIC 0
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Gadget_Whitelist
+ EXPLAIN !!Explain_Gadget_Whitelist
+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\gadget_whitelist"
+ PART !!Pol_Gadget_Whitelist LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Gadget_Install_Confirmation_Whitelist
+ EXPLAIN !!Explain_Gadget_Install_Confirmation_Whitelist
+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\install_confirmation_whitelist"
+ PART !!Pol_Gadget_Install_Confirmation_Whitelist LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Alternate_User_Data_Dir
+ EXPLAIN !!Explain_Alternate_User_Data_Dir
+ PART !!Pol_Alternate_User_Data_Dir EDITTEXT
+ VALUENAME alternate_user_data_dir
+ END PART
+ END POLICY
+
+ POLICY !!Pol_MaxAllowedOutlookConnections
+ EXPLAIN !!Explain_MaxAllowedOutlookConnections
+ PART !!Pol_MaxAllowedOutlookConnections NUMERIC
+ VALUENAME max_allowed_outlook_connections
+ MIN 1 MAX 65535 DEFAULT 400 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!Pol_DisallowSsdService
+ EXPLAIN !!Explain_DisallowSsdService
+ VALUENAME disallow_ssd_service
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_DisallowSsdOutbound
+ EXPLAIN !!Explain_DisallowSsdOutbound
+ VALUENAME disallow_ssd_outbound
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Disallow_Store_Gadget_Service
+ EXPLAIN !!Explain_Disallow_Store_Gadget_Service
+ VALUENAME disallow_store_gadget_service
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_MaxExchangeIndexingRate
+ EXPLAIN !!Explain_MaxExchangeIndexingRate
+ PART !!Pol_MaxExchangeIndexingRate NUMERIC
+ VALUENAME max_exchange_indexing_rate
+ MIN 1 MAX 1000 DEFAULT 60 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!Pol_EnableSafeweb
+ EXPLAIN !!Explain_Safeweb
+ VALUENAME safe_browsing
+ VALUEON NUMERIC 1
+ VALUEOFF NUMERIC 0
+ END POLICY
+
+ END CATEGORY ; Enterprise
+
+ END CATEGORY ; GoogleDesktopSearch
+ END CATEGORY ; Google
+
+
+CLASS USER
+ CATEGORY !!Cat_Google
+ CATEGORY !!Cat_GoogleDesktopSearch
+ KEYNAME "Software\Policies\Google\Google Desktop"
+
+ CATEGORY !!Cat_Preferences
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences"
+
+ CATEGORY !!Cat_IndexAndCaptureControl
+ POLICY !!Blacklist_Email
+ EXPLAIN !!Explain_Blacklist_Email
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ VALUENAME "1"
+ END POLICY
+
+ POLICY !!Blacklist_Gmail
+ EXPLAIN !!Explain_Blacklist_Gmail
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-pop"
+ VALUENAME "gmail"
+ END POLICY
+
+ POLICY !!Blacklist_WebHistory
+ EXPLAIN !!Explain_Blacklist_WebHistory
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ VALUENAME "2"
+ END POLICY
+
+ POLICY !!Blacklist_Chat
+ EXPLAIN !!Explain_Blacklist_Chat
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "3" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Text
+ EXPLAIN !!Explain_Blacklist_Text
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "4" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Media
+ EXPLAIN !!Explain_Blacklist_Media
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "5" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Contact
+ EXPLAIN !!Explain_Blacklist_Contact
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "9" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Calendar
+ EXPLAIN !!Explain_Blacklist_Calendar
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "10" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Task
+ EXPLAIN !!Explain_Blacklist_Task
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "11" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Note
+ EXPLAIN !!Explain_Blacklist_Note
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "12" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Journal
+ EXPLAIN !!Explain_Blacklist_Journal
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-1"
+ ACTIONLISTON
+ VALUENAME "13" VALUE NUMERIC 1
+ END ACTIONLISTON
+ END POLICY
+
+ POLICY !!Blacklist_Word
+ EXPLAIN !!Explain_Blacklist_Word
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "DOC"
+ END POLICY
+
+ POLICY !!Blacklist_Excel
+ EXPLAIN !!Explain_Blacklist_Excel
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "XLS"
+ END POLICY
+
+ POLICY !!Blacklist_Powerpoint
+ EXPLAIN !!Explain_Blacklist_Powerpoint
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "PPT"
+ END POLICY
+
+ POLICY !!Blacklist_PDF
+ EXPLAIN !!Explain_Blacklist_PDF
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "PDF"
+ END POLICY
+
+ POLICY !!Blacklist_ZIP
+ EXPLAIN !!Explain_Blacklist_ZIP
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-2"
+ VALUENAME "ZIP"
+ END POLICY
+
+ POLICY !!Blacklist_HTTPS
+ EXPLAIN !!Explain_Blacklist_HTTPS
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-3"
+ VALUENAME "HTTPS"
+ END POLICY
+
+ POLICY !!Blacklist_PasswordProtectedOffice
+ EXPLAIN !!Explain_Blacklist_PasswordProtectedOffice
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-13"
+ VALUENAME "SECUREOFFICE"
+ END POLICY
+
+ POLICY !!Blacklist_URI_Contains
+ EXPLAIN !!Explain_Blacklist_URI_Contains
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\blacklist-6"
+ PART !!Blacklist_URI_Contains LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Blacklist_Extensions
+ EXPLAIN !!Explain_Blacklist_Extensions
+ PART !!Blacklist_Extensions EDITTEXT
+ VALUENAME "file_extensions_to_skip"
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Disallow_UserSearchLocations
+ EXPLAIN !!Explain_Disallow_UserSearchLocations
+ VALUENAME user_search_locations
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Search_Location_Whitelist
+ EXPLAIN !!Explain_Search_Location_Whitelist
+ KEYNAME "Software\Policies\Google\Google Desktop\Preferences\policy_search_location_whitelist"
+ PART !!Search_Locations_Whitelist LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Email_Retention
+ EXPLAIN !!Explain_Email_Retention
+ PART !!Email_Retention_Edit NUMERIC
+ VALUENAME "email_days_to_retain"
+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!Webpage_Retention
+ EXPLAIN !!Explain_Webpage_Retention
+ PART !!Webpage_Retention_Edit NUMERIC
+ VALUENAME "webpage_days_to_retain"
+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!File_Retention
+ EXPLAIN !!Explain_File_Retention
+ PART !!File_Retention_Edit NUMERIC
+ VALUENAME "file_days_to_retain"
+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!IM_Retention
+ EXPLAIN !!Explain_IM_Retention
+ PART !!IM_Retention_Edit NUMERIC
+ VALUENAME "im_days_to_retain"
+ MIN 1 MAX 65535 DEFAULT 30 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Remove_Deleted_Items
+ EXPLAIN !!Explain_Remove_Deleted_Items
+ VALUENAME remove_deleted_items
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Allow_Simultaneous_Indexing
+ EXPLAIN !!Explain_Allow_Simultaneous_Indexing
+ VALUENAME simultaneous_indexing
+ VALUEON NUMERIC 1
+ END POLICY
+
+ END CATEGORY
+
+ POLICY !!Pol_TurnOffAdvancedFeatures
+ EXPLAIN !!Explain_TurnOffAdvancedFeatures
+ VALUENAME error_report_on
+ VALUEON NUMERIC 0
+ END POLICY
+
+ POLICY !!Pol_TurnOffImproveGd
+ EXPLAIN !!Explain_TurnOffImproveGd
+ VALUENAME improve_gd
+ VALUEON NUMERIC 0
+ VALUEOFF NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_NoPersonalizationInfo
+ EXPLAIN !!Explain_NoPersonalizationInfo
+ VALUENAME send_personalization_info
+ VALUEON NUMERIC 0
+ VALUEOFF NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_OneBoxMode
+ EXPLAIN !!Explain_OneBoxMode
+ VALUENAME onebox_mode
+ VALUEON NUMERIC 0
+ END POLICY
+
+ POLICY !!Pol_EncryptIndex
+ EXPLAIN !!Explain_EncryptIndex
+ VALUENAME encrypt_index
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Hyper
+ EXPLAIN !!Explain_Hyper
+ VALUENAME hyper_off
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Display_Mode
+ EXPLAIN !!Explain_Display_Mode
+ PART !!Pol_Display_Mode DROPDOWNLIST
+ VALUENAME display_mode
+ ITEMLIST
+ NAME !!Sidebar VALUE NUMERIC 1
+ NAME !!Deskbar VALUE NUMERIC 8
+ NAME !!FloatingDeskbar VALUE NUMERIC 4
+ NAME !!None VALUE NUMERIC 0
+ END ITEMLIST
+ END PART
+ END POLICY
+
+ END CATEGORY ; Preferences
+
+ CATEGORY !!Cat_Enterprise
+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise"
+
+ POLICY !!Pol_Autoupdate
+ EXPLAIN !!Explain_Autoupdate
+ VALUENAME autoupdate_host
+ VALUEON ""
+ END POLICY
+
+ POLICY !!Pol_AutoupdateAsSystem
+ EXPLAIN !!Explain_AutoupdateAsSystem
+ VALUENAME autoupdate_impersonate_user
+ VALUEON NUMERIC 0
+ VALUEOFF NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_EnterpriseTab
+ EXPLAIN !!Explain_EnterpriseTab
+ PART !!EnterpriseTabText EDITTEXT
+ VALUENAME enterprise_tab_text
+ END PART
+ PART !!EnterpriseTabHomepage EDITTEXT
+ VALUENAME enterprise_tab_homepage
+ END PART
+ PART !!EnterpriseTabHomepageQuery CHECKBOX
+ VALUENAME enterprise_tab_homepage_query
+ END PART
+ PART !!EnterpriseTabResults EDITTEXT
+ VALUENAME enterprise_tab_results
+ END PART
+ PART !!EnterpriseTabResultsQuery CHECKBOX
+ VALUENAME enterprise_tab_results_query
+ END PART
+ END POLICY
+
+ POLICY !!Pol_GSAHosts
+ EXPLAIN !!Explain_GSAHosts
+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\GSAHosts"
+ PART !!Pol_GSAHosts LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Disallow_Gadgets
+ EXPLAIN !!Explain_Disallow_Gadgets
+ VALUENAME disallow_gadgets
+ VALUEON NUMERIC 1
+ PART !!Disallow_Only_Non_Builtin_Gadgets CHECKBOX DEFCHECKED
+ VALUENAME disallow_only_non_builtin_gadgets
+ VALUEON NUMERIC 1
+ VALUEOFF NUMERIC 0
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Gadget_Whitelist
+ EXPLAIN !!Explain_Gadget_Whitelist
+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\gadget_whitelist"
+ PART !!Pol_Gadget_Whitelist LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Gadget_Install_Confirmation_Whitelist
+ EXPLAIN !!Explain_Gadget_Install_Confirmation_Whitelist
+ KEYNAME "Software\Policies\Google\Google Desktop\Enterprise\install_confirmation_whitelist"
+ PART !!Pol_Gadget_Install_Confirmation_Whitelist LISTBOX
+ END PART
+ END POLICY
+
+ POLICY !!Pol_Alternate_User_Data_Dir
+ EXPLAIN !!Explain_Alternate_User_Data_Dir
+ PART !!Pol_Alternate_User_Data_Dir EDITTEXT
+ VALUENAME alternate_user_data_dir
+ END PART
+ END POLICY
+
+ POLICY !!Pol_MaxAllowedOutlookConnections
+ EXPLAIN !!Explain_MaxAllowedOutlookConnections
+ PART !!Pol_MaxAllowedOutlookConnections NUMERIC
+ VALUENAME max_allowed_outlook_connections
+ MIN 1 MAX 65535 DEFAULT 400 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!Pol_DisallowSsdService
+ EXPLAIN !!Explain_DisallowSsdService
+ VALUENAME disallow_ssd_service
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_DisallowSsdOutbound
+ EXPLAIN !!Explain_DisallowSsdOutbound
+ VALUENAME disallow_ssd_outbound
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_Disallow_Store_Gadget_Service
+ EXPLAIN !!Explain_Disallow_Store_Gadget_Service
+ VALUENAME disallow_store_gadget_service
+ VALUEON NUMERIC 1
+ END POLICY
+
+ POLICY !!Pol_MaxExchangeIndexingRate
+ EXPLAIN !!Explain_MaxExchangeIndexingRate
+ PART !!Pol_MaxExchangeIndexingRate NUMERIC
+ VALUENAME max_exchange_indexing_rate
+ MIN 1 MAX 1000 DEFAULT 60 SPIN 1
+ END PART
+ END POLICY
+
+ POLICY !!Pol_EnableSafeweb
+ EXPLAIN !!Explain_Safeweb
+ VALUENAME safe_browsing
+ VALUEON NUMERIC 1
+ VALUEOFF NUMERIC 0
+ END POLICY
+
+ END CATEGORY ; Enterprise
+
+ END CATEGORY ; GoogleDesktopSearch
+ END CATEGORY ; Google
+
+;------------------------------------------------------------------------------
+
+[strings]
+Cat_Google="Google"
+Cat_GoogleDesktopSearch="Google Desktop"
+
+;------------------------------------------------------------------------------
+; Preferences
+;------------------------------------------------------------------------------
+Cat_Preferences="Preferences"
+Explain_Preferences="Controls Google Desktop preferences"
+
+Cat_IndexAndCaptureControl="Indexing and Capture Control"
+Explain_IndexAndCaptureControl="Controls what files, web pages, and other content will be indexed by Google Desktop."
+
+Blacklist_Email="Prevent indexing of email"
+Explain_Blacklist_Email="Enabling this policy will prevent Google Desktop from indexing emails.\n\nIf this policy is not configured, the user can choose whether or not to index emails."
+Blacklist_Gmail="Prevent indexing of Gmail"
+Explain_Blacklist_Gmail="Enabling this policy prevents Google Desktop from indexing Gmail messages.\n\nThis policy is in effect only when the policy "Prevent indexing of email" is disabled. When that policy is enabled, all email indexing is disabled, including Gmail indexing.\n\nIf both this policy and "Prevent indexing of email" are disabled or not configured, a user can choose whether or not to index Gmail messages."
+Blacklist_WebHistory="Prevent indexing of web pages"
+Explain_Blacklist_WebHistory="Enabling this policy will prevent Google Desktop from indexing web pages.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index web pages."
+Blacklist_Text="Prevent indexing of text files"
+Explain_Blacklist_Text="Enabling this policy will prevent Google Desktop from indexing text files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index text files."
+Blacklist_Media="Prevent indexing of media files"
+Explain_Blacklist_Media="Enabling this policy will prevent Google Desktop from indexing media files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index media files."
+Blacklist_Contact="Prevent indexing of contacts"
+Explain_Blacklist_Contact="Enabling this policy will prevent Google Desktop from indexing contacts.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index contacts."
+Blacklist_Calendar="Prevent indexing of calendar entries"
+Explain_Blacklist_Calendar="Enabling this policy will prevent Google Desktop from indexing calendar entries.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index calendar entries."
+Blacklist_Task="Prevent indexing of tasks"
+Explain_Blacklist_Task="Enabling this policy will prevent Google Desktop from indexing tasks.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index tasks."
+Blacklist_Note="Prevent indexing of notes"
+Explain_Blacklist_Note="Enabling this policy will prevent Google Desktop from indexing notes.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index notes."
+Blacklist_Journal="Prevent indexing of journal entries"
+Explain_Blacklist_Journal="Enabling this policy will prevent Google Desktop from indexing journal entries.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index journal entries."
+Blacklist_Word="Prevent indexing of Word documents"
+Explain_Blacklist_Word="Enabling this policy will prevent Google Desktop from indexing Word documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index Word documents."
+Blacklist_Excel="Prevent indexing of Excel documents"
+Explain_Blacklist_Excel="Enabling this policy will prevent Google Desktop from indexing Excel documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index Excel documents."
+Blacklist_Powerpoint="Prevent indexing of PowerPoint documents"
+Explain_Blacklist_Powerpoint="Enabling this policy will prevent Google Desktop from indexing PowerPoint documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index PowerPoint documents."
+Blacklist_PDF="Prevent indexing of PDF documents"
+Explain_Blacklist_PDF="Enabling this policy will prevent Google Desktop from indexing PDF documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index PDF documents."
+Blacklist_ZIP="Prevent indexing of ZIP files"
+Explain_Blacklist_ZIP="Enabling this policy will prevent Google Desktop from indexing ZIP files.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index ZIP files."
+Blacklist_HTTPS="Prevent indexing of secure web pages"
+Explain_Blacklist_HTTPS="Enabling this policy will prevent Google Desktop from indexing secure web pages (pages with HTTPS in the URL).\n\nIf this policy is disabled or not configured, the user can choose whether or not to index secure web pages."
+Blacklist_URI_Contains="Prevent indexing of specific web sites and folders"
+Explain_Blacklist_URI_Contains="This policy allows you to prevent Google Desktop from indexing specific websites or folders. If an item's URL or path name contains any of these specified strings, it will not be indexed. These restrictions will be applied in addition to any websites or folders that the user has specified.\n\nThis policy has no effect when disabled or not configured."
+Blacklist_Chat="Prevent indexing of IM chats"
+Explain_Blacklist_Chat="Enabling this policy will prevent Google Desktop from indexing IM chat conversations.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index IM chat conversations."
+Blacklist_PasswordProtectedOffice="Prevent indexing of password-protected Office documents (Word, Excel)"
+Explain_Blacklist_PasswordProtectedOffice="Enabling this policy will prevent Google Desktop from indexing password-protected office documents.\n\nIf this policy is disabled or not configured, the user can choose whether or not to index password-protected office documents."
+Blacklist_Extensions="Prevent indexing of specific file extensions"
+Explain_Blacklist_Extensions="This policy allows you to prevent Google Desktop from indexing files with specific extensions. Enter a list of file extensions, separated by commas, that you wish to exclude from indexing.\n\nThis policy has no effect when disabled or not configured."
+Pol_Disallow_UserSearchLocations="Disallow adding search locations for indexing"
+Explain_Disallow_UserSearchLocations="Enabling this policy will prevent the user from specifying additional drives or networked folders to be indexed by Google Desktop.\n\nIf this policy is disabled or not configured, users may specify additional drives and networked folders to be indexed."
+Pol_Search_Location_Whitelist="Allow indexing of specific folders"
+Explain_Search_Location_Whitelist="This policy allows you to add additional drives and networked folders to index."
+Search_Locations_Whitelist="Search these locations"
+Email_Retention="Only retain emails that are less than x days old"
+Explain_Email_Retention="This policy allows you to configure Google Desktop to only retain emails that are less than the specified number of days old in the index. Enter the number of days to retain emails for\n\nThis policy has no effect when disabled or not configured."
+Email_Retention_Edit="Number of days to retain emails"
+Webpage_Retention="Only retain webpages that are less than x days old"
+Explain_Webpage_Retention="This policy allows you to configure Google Desktop to only retain webpages that are less than the specified number of days old in the index. Enter the number of days to retain webpages for\n\nThis policy has no effect when disabled or not configured."
+Webpage_Retention_Edit="Number of days to retain webpages"
+File_Retention="Only retain files that are less than x days old"
+Explain_File_Retention="This policy allows you to configure Google Desktop to only retain files that are less than the specified number of days old in the index. Enter the number of days to retain files for\n\nThis policy has no effect when disabled or not configured."
+File_Retention_Edit="Number of days to retain files"
+IM_Retention="Only retain IM that are less than x days old"
+Explain_IM_Retention="This policy allows you to configure Google Desktop to only retain IM that are less than the specified number of days old in the index. Enter the number of days to retain IM for\n\nThis policy has no effect when disabled or not configured."
+IM_Retention_Edit="Number of days to retain IM"
+
+Pol_Remove_Deleted_Items="Remove deleted items from the index."
+Explain_Remove_Deleted_Items="Enabling this policy will remove all deleted items from the index and cache. Any items that are deleted will no longer be searchable."
+
+Pol_Allow_Simultaneous_Indexing="Allow historical indexing for multiple users simultaneously."
+Explain_Allow_Simultaneous_Indexing="Enabling this policy will allow a computer to generate first-time indexes for multiple users simultaneously. \n\nIf this policy is disabled or not configured, historical indexing will happen only for the logged-in user that was connected last; historical indexing for any other logged-in user will happen the next time that other user connects."
+
+Pol_TurnOffAdvancedFeatures="Turn off Advanced Features options"
+Explain_TurnOffAdvancedFeatures="Enabling this policy will prevent Google Desktop from sending Advanced Features data to Google (for either improvements or personalization), and users won't be able to change these options. Enabling this policy also prevents older versions of Google Desktop from sending data.\n\nIf this policy is disabled or not configured and the user has a pre-5.5 version of Google Desktop, the user can choose whether or not to enable sending data to Google. If the user has version 5.5 or later, the 'Turn off Improve Google Desktop option' and 'Do not send personalization info' policies will be used instead."
+
+Pol_TurnOffImproveGd="Turn off Improve Google Desktop option"
+Explain_TurnOffImproveGd="Enabling this policy will prevent Google Desktop from sending improvement data, including crash reports and anonymous usage data, to Google.\n\nIf this policy is disabled, improvement data will be sent to Google and the user won't be able to change the option.\n\nIf this policy is not configured, the user can choose whether or not to enable the Improve Google Desktop option.\n\nNote that this policy applies only to version 5.5 or later and doesn't affect previous versions of Google Desktop.\n\nAlso note that this policy can be overridden by the 'Turn off Advanced Features options' policy."
+
+Pol_NoPersonalizationInfo="Do not send personalization info"
+Explain_NoPersonalizationInfo="Enabling this policy will prevent Google Desktop from displaying personalized content, such as news that reflects the user's past interest in articles. Personalized content is derived from anonymous usage data sent to Google.\n\nIf this policy is disabled, personalized content will be displayed for all users, and users won't be able to disable this feature.\n\nIf this policy is not configured, users can choose whether or not to enable personalization in each gadget that supports this feature.\n\nNote that this policy applies only to version 5.5 or later and doesn't affect previous versions of Google Desktop.\n\nAlso note that this policy can be overridden by the 'Turn off Advanced Features options' policy."
+
+Pol_OneBoxMode="Turn off Google Web Search Integration"
+Explain_OneBoxMode="Enabling this policy will prevent Google Desktop from displaying Desktop Search results in queries to google.com.\n\nIf this policy is disabled or not configured, the user can choose whether or not to include Desktop Search results in queries to google.com."
+
+Pol_EncryptIndex="Encrypt index data"
+Explain_EncryptIndex="Enabling this policy will cause Google Desktop to turn on Windows file encryption for the folder containing the Google Desktop index and related user data the next time it is run.\n\nNote that Windows EFS is only available on NTFS volumes. If the user's data is stored on a FAT volume, this policy will have no effect.\n\nThis policy has no effect when disabled or not configured."
+
+Pol_Hyper="Turn off Quick Find"
+Explain_Hyper="Enabling this policy will cause Google Desktop to turn off Quick Find feature. Quick Find allows you to see results as you type.\n\nIf this policy is disabled or not configured, the user can choose whether or not to enable it."
+
+Pol_Display_Mode="Choose display option"
+Explain_Display_Mode="This policy sets the Google Desktop display option: Sidebar, Deskbar, Floating Deskbar or none.\n\nNote that on 64-bit systems, a setting of Deskbar will be interpreted as Floating Deskbar.\n\nIf this policy is disabled or not configured, the user can choose a display option."
+Sidebar="Sidebar"
+Deskbar="Deskbar"
+FloatingDeskbar="Floating Deskbar"
+None="None"
+
+;------------------------------------------------------------------------------
+; Enterprise
+;------------------------------------------------------------------------------
+Cat_Enterprise="Enterprise Integration"
+Explain_Enterprise="Controls features specific to Enterprise installations of Google Desktop"
+
+Pol_Autoupdate="Block Auto-update"
+Explain_Autoupdate="Enabling this policy prevents Google Desktop from automatically checking for and installing updates from google.com.\n\nIf you enable this policy, you must distribute updates to Google Desktop using Group Policy, SMS, or a similar enterprise software distribution mechanism. You should check http://desktop.google.com/enterprise/ for updates.\n\nIf this policy is disabled or not configured, Google Desktop will periodically check for updates from desktop.google.com."
+
+Pol_AutoupdateAsSystem="Use system proxy settings when auto-updating"
+Explain_AutoupdateAsSystem="Enabling this policy makes Google Desktop use the machine-wide proxy settings (as specified using e.g. proxycfg.exe) when performing autoupdates (if enabled).\n\nIf this policy is disabled or not configured, Google Desktop will use the logged-on user's Internet Explorer proxy settings when checking for auto-updates (if enabled)."
+
+Pol_EnterpriseTab="Enterprise search tab"
+Explain_EnterpriseTab="This policy allows you to add a search tab for your Google Search Appliance to Google Desktop and google.com web pages.\n\nYou must provide the name of the tab, such as "Intranet", as well as URLs for the search homepage and for retrieving search results. Use [DISP_QUERY] in place of the query term for the search results URL.\n\nSee the administrator's guide for more details."
+EnterpriseTabText="Tab name"
+EnterpriseTabHomepage="Search homepage URL"
+EnterpriseTabHomepageQuery="Check if search homepage supports '&&q=<query>'"
+EnterpriseTabResults="Search results URL"
+EnterpriseTabResultsQuery="Check if search results page supports '&&q=<query>'"
+
+Pol_GSAHosts="Google Search Appliances"
+Explain_GSAHosts="This policy allows you to list any Google Search Appliances in your intranet. When properly configured, Google Desktop will insert Google Desktop results into the results of queries on the Google Search Appliance"
+
+Pol_PolicyUnawareClientProhibitedFlag="Prohibit Policy-Unaware versions"
+Explain_PolicyUnawareClientProhibitedFlag="Prohibits installation and execution of versions of Google Desktop that are unaware of group policy.\n\nEnabling this policy will prevent users from installing or running version 1.0 of Google Desktop.\n\nThis policy has no effect when disabled or not configured."
+
+Pol_MinimumAllowedVersion="Minimum allowed version"
+Explain_MinimumAllowedVersion="This policy allows you to prevent installation and/or execution of older versions of Google Desktop by specifying the minimum version you wish to allow. When enabling this policy, you should also enable the "Prohibit Policy-Unaware versions" policy to block versions of Google Desktop that did not support group policy.\n\nThis policy has no effect when disabled or not configured."
+
+Pol_MaximumAllowedVersion="Maximum allowed version"
+Explain_MaximumAllowedVersion="This policy allows you to prevent installation and/or execution of newer versions of Google Desktop by specifying the maximum version you wish to allow.\n\nThis policy has no effect when disabled or not configured."
+
+Pol_Disallow_Gadgets="Disallow gadgets and indexing plug-ins"
+Explain_Disallow_Gadgets="This policy prevents the use of all Google Desktop gadgets and indexing plug-ins. The policy applies to gadgets that are included in the Google Desktop installation package (built-in gadgets), built-in indexing plug-ins (currently only the Lotus Notes plug-in), and to gadgets or indexing plug-ins that a user might want to add later (non-built-in gadgets and indexing plug-ins).\n\nYou can prohibit use of all non-built-in gadgets and indexing plug-ins, but allow use of built-in gadgets and indexing plug-ins. To do so, enable this policy and then select the option "Disallow only non-built-in gadgets and indexing plug-ins.\n\nYou can supersede this policy to allow specified built-in and non-built-in gadgets and indexing plug-ins. To do so, enable this policy and then specify the gadgets and/or indexing plug-ins you want to allow under "Gadget and Plug-in Whitelist.""
+Disallow_Only_Non_Builtin_Gadgets="Disallow only non-built-in gadgets and indexing plug-ins"
+
+Pol_Gadget_Whitelist="Gadget and plug-in whitelist"
+Explain_Gadget_Whitelist="This policy specifies a list of Google Desktop gadgets and indexing plug-ins that you want to allow, as exceptions to the "Disallow gadgets and indexing plug-ins" policy. This policy is valid only when the "Disallow gadgets and indexing plug-ins" policy is enabled.\n\nFor each gadget or indexing plug-in you wish to allow, add the CLSID or PROGID of the gadget or indexing plug-in (see the administrator's guide for more details).\n\nThis policy has no effect when disabled or not configured."
+
+Pol_Gadget_Install_Confirmation_Whitelist="Allow silent installation of gadgets"
+Explain_Gadget_Install_Confirmation_Whitelist="Enabling this policy lets you specify a list of Google Desktop gadgets or indexing plug-ins that can be installed without confirmation from the user.\n\nAdd a gadget or indexing plug-in by placing its class ID (CLSID) or program identifier (PROGID) in the list, surrounded with curly braces ({ }).\n\nThis policy has no effect when disabled or not configured."
+
+Pol_Alternate_User_Data_Dir="Alternate user data directory"
+Explain_Alternate_User_Data_Dir="This policy allows you to specify a directory to be used to store user data for Google Desktop (such as index data and cached documents).\n\nYou may use [USER_NAME] or [DOMAIN_NAME] in the path to specify the current user's name or domain. If [USER_NAME] is not specified, the user name will be appended at the end of the path.\n\nThis policy has no effect when disabled or not configured."
+
+Pol_MaxAllowedOutlookConnections="Maximum allowed Outlook connections"
+Explain_MaxAllowedOutlookConnections="This policy specifies the maximum number of open connections that Google Desktop maintains with the Exchange server. Google Desktop opens a connection for each email folder that it indexes. If insufficient connections are allowed, Google Desktop cannot index all the user email folders.\n\nThe default value is 400. Because users rarely have as many as 400 email folders, Google Desktop rarely reaches the limit.\n\nIf you set this policy's value above 400, you must also configure the number of open connections between Outlook and the Exchange server. By default, approximately 400 connections are allowed. If Google Desktop uses too many of these connections, Outlook might be unable to access email.\n\nThis policy has no effect when disabled or not configured."
+
+Pol_DisallowSsdService="Disallow sharing and receiving of web history and documents across computers"
+Explain_DisallowSsdService="Enabling this policy will prevent Google Desktop from sharing the user's web history and document contents across the user's different Google Desktop installations, and will also prevent it from receiving such shared items from the user's other machines. To allow reception but disallow sharing, use DisallowSsdOutbound.\nThis policy has no effect when disabled or not configured."
+
+Pol_DisallowSsdOutbound="Disallow sharing of web history and documents to user's other computers."
+Explain_DisallowSsdOutbound="Enabling this policy will prevent Google Desktop from sending the user's web history and document contents from this machine to the user's other machines. It does not prevent reception of items from the user's other machines; to disallow both, use DisallowSsdService.\nThis policy has no effect when disabled or not configured."
+
+Pol_Disallow_Store_Gadget_Service="Disallow storage of gadget content and settings."
+Explain_Disallow_Store_Gadget_Service="Enabling this policy will prevent users from storing their gadget content and settings with Google. Users will be unable to access their gadget content and settings from other computers and all content and settings will be lost if Google Desktop is uninstalled."
+
+Pol_MaxExchangeIndexingRate="Maximum allowed Exchange indexing rate"
+Explain_MaxExchangeIndexingRate="This policy allows you to specify the maximum number of emails that are indexed per minute. \n\nThis policy has no effect when disabled or not configured."
+
+Pol_EnableSafeweb="Enable or disable safe browsing"
+Explain_Safeweb="Google Desktop safe browsing informs the user whenever they visit any site which is a suspected forgery site or may harm their computer. Enabling this policy turns on safe browsing; disabling the policy turns it off. \n\nIf this policy is not configured, the user can select whether to turn on safe browsing." \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/README.txt b/chromium/tools/grit/grit/testdata/README.txt
new file mode 100644
index 00000000000..a683b3b9e39
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/README.txt
@@ -0,0 +1,87 @@
+Google Desktop for Enterprise
+Copyright (C) 2007 Google Inc.
+All Rights Reserved
+
+---------
+Contents
+---------
+This distribution contains the following files:
+
+GoogleDesktopSetup.msi - Installation and setup program
+GoogleDesktop.adm - Group Policy administrative template file
+AdminGuide.pdf - Google Desktop for Enterprise administrative guide
+
+
+--------------
+Documentation
+--------------
+Full documentation and installation instructions are in the
+administrative guide, and also online at
+http://desktop.google.com/enterprise/adminguide.html.
+
+
+------------------------
+IBM Lotus Notes Plug-In
+------------------------
+The Lotus Notes plug-in is included in the release of Google
+Desktop for Enterprise. The IBM Lotus Notes Plug-in for Google
+Desktop indexes mail, calendar, task, contact and journal
+documents from Notes. Discussion documents including those from
+the discussion and team room templates can also be indexed by
+selecting an option from the preferences. Once indexed, this data
+will be returned in Google Desktop searches. The corresponding
+document can be opened in Lotus Notes from the Google Desktop
+results page.
+
+Install: The plug-in will install automatically during the Google
+Desktop setup process if Lotus Notes is already installed. Lotus
+Notes must not be running in order for the install to occur. The
+Class ID for this plug-in is {8F42BDFB-33E8-427B-AFDC-A04E046D3F07}.
+
+Preferences: Preferences and selection of databases to index are
+set in the 'Google Desktop for Notes' dialog reached through the
+'Actions' menu.
+
+Reindexing: Selecting 'Reindex all databases' will index all the
+documents in each database again.
+
+
+Notes Plug-in Known Issues
+---------------------------
+
+If the 'Google Desktop for Notes' item is not available from the
+Lotus Notes Actions menu, then installation was not successful.
+Installation consists of writing one file, notesgdsplugin.dll, to
+the Notes application directory and a setting to the notes.ini
+configuration file. The most likely cause of an unsuccessful
+installation is that the installer was not able to locate the
+notes.ini file. Installation will complete if the user closes Notes
+and manually adds the following setting to this file on a new line:
+AddinMenus=notesgdsplugin.dll
+
+If the notesgdsplugin.dll file is not in the application directory
+(e.g., C:\Program Files\Lotus\Notes) after Google Desktop
+installation, it is likely that Notes was not installed correctly.
+
+Only local databases can be indexed. If they can be determined,
+the user's local mail file and address book will be included in the
+list automatically. Mail archives and other databases must be
+added with the 'Add' button.
+
+Some users may experience performance issues during the initial
+indexing of a database. The 'Perform the initial index of a
+database only when I'm idle' option will limit the indexing process
+to times when the user is not using the machine. If this does not
+alleviate the problem or the user would like to continually index
+but just do so more slowly or quickly, the GoogleWaitTime notes.ini
+value can be set. Increasing the GoogleWaitTime value will slow
+down the indexing process, and lowering the value will speed it up.
+A value of zero causes the fastest possible indexing. Removing the
+ini parameter altogether returns it to the default (20).
+
+Crashes have been known to occur with certain types of history
+bookmarks. If the Notes client seems to crash randomly, try
+disabling the 'Index note history' option. If it crashes before,
+you can get to the preferences, add the following line to your
+notes.ini file:
+GDSNoIndexHistory=1
diff --git a/chromium/tools/grit/grit/testdata/about.html b/chromium/tools/grit/grit/testdata/about.html
new file mode 100644
index 00000000000..8e5fad7b2b7
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/about.html
@@ -0,0 +1,45 @@
+[HEADER]
+<table cellspacing=0 cellPadding=0 width="100%" border=0><tr bgcolor=#3399cc><td align=middle height=1><img height=1 width=1></td></tr></table>
+<table cellspacing=0 cellPadding=1 width="100%" bgcolor=#e8f4f7 border=0><tr><td height=20><font size=+1 color=#000000>&nbsp;<b>[TITLE]</b></font></td></tr></table>
+<br><center><span style="line-height:16pt"><font color=#335cec><B>Google Desktop Search: Search your own computer.</B></font></span></center><br>
+
+<table cellspacing=1 cellpadding=0 width=300 align=center border=0>
+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="outlook.gif" width=16>&nbsp;&nbsp;Outlook Email</font></td>
+<td nowrap>&nbsp;</td>
+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="netscape.gif" width=16>&nbsp;&nbsp;Netscape Mail / Thunderbird</font></td></tr>
+
+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="oe.gif" width=16>&nbsp;&nbsp;Outlook Express</font></td>
+<td nowrap>&nbsp;</td>
+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ff.gif" width=16>&nbsp;&nbsp;Netscape / Firefox / Mozilla</font></td></tr>
+
+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="doc.gif" width=16>&nbsp;&nbsp;Word</font></td>
+<td nowrap>&nbsp;</td>
+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="pdf.gif" width=16>&nbsp;&nbsp;PDF</font></td></tr>
+
+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="xls.gif" width=16>&nbsp;&nbsp;Excel</font></td>
+<td nowrap>&nbsp;</td>
+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="mus.gif" width=16>&nbsp;&nbsp;Music</font></td></tr>
+
+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ppt.gif" width=16>&nbsp;&nbsp;PowerPoint</font></td>
+<td nowrap>&nbsp;</td>
+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="jpg.gif" width=16>&nbsp;&nbsp;Images</font></td></tr>
+
+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="ie.gif" width=16>&nbsp;&nbsp;Internet Explorer</font></td>
+<td nowrap>&nbsp;</td>
+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="mov.gif" width=16>&nbsp;&nbsp;Video</font></td></tr>
+
+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="aim.gif" width=16>&nbsp;&nbsp;AOL Instant Messenger</font></td>
+<td nowrap>&nbsp;</td>
+<td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="other.gif" width=16>&nbsp;&nbsp;Even more with <a href="http://desktop.google.com/plugins.html">these plug-ins</A></font></td></tr>
+
+<tr><td nowrap><font size=-1><img style="vertical-align:middle" height=16 src="txt.gif" width=16>&nbsp;&nbsp;Text and others</font></td></tr>
+</table>
+<center>
+<p><table cellpadding=1>
+<tr><td><a href="http://desktop.google.com/gettingstarted.html?hl=[LANG_CODE]"><B>Getting Started</B></A> - Learn more about using Google Desktop Search</td></tr>
+<tr><td><a href="http://desktop.google.com/help.html?hl=[LANG_CODE]"><B>Online Help</B></A> - Up-to-date answers to your questions</td></tr>
+<tr><td><a href="[$~PRIVACY~$]"><B>Privacy</B></A> - A few words about privacy and Google Desktop Search</td></tr>
+<tr><td><a href="http://desktop.google.com/uninstall.html?hl=[LANG_CODE]"><B>Uninstall</B></A> - How to uninstall Google Desktop Search</td></tr>
+<tr><td><a href="http://desktop.google.com/feedback.html?hl=[LANG_CODE]"><B>Submit Feedback</B></A> - Send us your comments and ideas</td></tr>
+</table><br><font size=-2>Google Desktop Search [$~BUILDNUMBER~$]</font><br><br>
+[FOOTER] \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/android.xml b/chromium/tools/grit/grit/testdata/android.xml
new file mode 100644
index 00000000000..1604c7c4837
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/android.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<resources>
+ <!-- A string with placeholder. -->
+ <string xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" name="placeholders">
+ Open <xliff:g id="FILENAME" example="internet.html">%s</xliff:g>?
+ </string>
+
+ <!-- A simple string. -->
+ <string name="simple" product="nosdcard">A simple string.</string>
+
+ <!-- A string with a comment. -->
+ <string name="comment">Contains a <!-- ignore this --> comment. </string>
+
+ <!-- A second simple string. -->
+ <string name="simple2"> Another simple string. </string>
+
+ <!-- A non-translatable string. -->
+ <string name="constant" translatable="false">Do not translate me.</string>
+</resources>
diff --git a/chromium/tools/grit/grit/testdata/bad_browser.html b/chromium/tools/grit/grit/testdata/bad_browser.html
new file mode 100644
index 00000000000..e8cf34664d6
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/bad_browser.html
@@ -0,0 +1,16 @@
+<p><b>We're sorry, but we don't seem to be compatible.</b></p>
+<p><font size="-1">Our software suggests that you're using a browser incompatible with Google Desktop Search.
+ Google Desktop Search currently supports the following:</font></p>
+<ul><font size="-1">
+ <li>Microsoft IE 5 and newer (<a href="http://www.microsoft.com/windows/ie/downloads/default.asp">Download</a>)</li>
+ <li>Mozilla (<a href="http://www.mozilla.org/products/mozilla1.x/">Download</a>)</li>
+ <li>Mozilla Firefox (<a href="http://www.mozilla.org/products/firefox/">Download</a>)</li>
+ <li>Netscape 7 and newer (<a href="http://channels.netscape.com/ns/browsers/download.jsp">Download</a>)</li>
+</font></ul>
+
+<p><font size="-1">You may <a href="[REDIR]">click here</a> to use your
+ unsupported browser, though you likely will encounter some areas that don't
+ work as expected. You need to have Javascript enabled, regardless of the
+ browser you use.</font>
+<p><font size="-1">We hope to expand this list in the near future and announce new
+ browsers as they become available.
diff --git a/chromium/tools/grit/grit/testdata/browser.html b/chromium/tools/grit/grit/testdata/browser.html
new file mode 100644
index 00000000000..45d364d56fe
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/browser.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>[$~TITLE~$]</title>
+<style>
+BODY { MARGIN-LEFT: 1em; MARGIN-RIGHT: 1em }
+BODY, TD, DIV, A { FONT-FAMILY: arial,sans-serif}
+DIV, TD { COLOR: #000}
+A:link { COLOR: #00c}
+A:visited { COLOR: #551a8b}
+A:active { COLOR: #f00 }
+</style>
+</head>
+
+<body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#800080" alink="#ff0000" topmargin=2>
+
+<table cellspacing=2 cellpadding=0 width="99%" border=0>
+<tr>
+ <td width="1%" rowspan=2>[$~IMAGE~$]
+ <td>&nbsp;</td>
+ <td rowspan=2>
+ <table cellspacing=0 cellpadding=0 width="100%" border=0>
+ <tr>
+ <td bgcolor=#3399cc><img height=1 width=1></td>
+ </tr>
+ </table>
+ <table cellspacing=0 cellpadding=0 width="100%" border=0 bgcolor=#efefef>
+ <tr>
+ <td nowrap bgcolor=#E8F4F7><font face=arial,sans-serif color=#000000 size=+1><b>&nbsp;[$~CHROME_TITLE~$]</b></font></td>
+ </tr>
+ </table>
+ </td>
+</tr>
+</table>
+
+<table cellpadding=3 width="94%" align="center" cellspacing=0 border=0>
+<tr valign="middle">
+ <td valign="top">
+ [$~BODY~$]
+ </td>
+ </tr>
+</table>
+[$~FOOTER~$]
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/buildinfo.grd b/chromium/tools/grit/grit/testdata/buildinfo.grd
new file mode 100644
index 00000000000..80458a82656
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/buildinfo.grd
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
+<grit
+ base_dir="."
+ source_lang_id="en"
+ tc_project="GoogleDesktopWindowsClient"
+ latest_public_release="0"
+ current_release="1"
+ enc_check="möl">
+ <outputs>
+ <output filename="resource.h" type="rc_header" />
+ <output filename="en_generated_resources.rc" type="rc_all" lang="en" />
+ <output filename="sv_generated_resources.rc" type="rc_all" lang="sv" />
+ </outputs>
+ <translations>
+ <file path="substitute.xmb" lang="sv" />
+ </translations>
+ <release seq="1" allow_pseudo="false">
+ <includes>
+ <include type="BITMAP" name="IDB_PR" file="pr.bmp" />
+ <if expr="lang == 'sv'">
+ <include type="BITMAP" name="IDB_PR2" file="pr2.bmp" />
+ </if>
+ </includes>
+ <structures>
+ <structure name="SIDEBAR_LOADING.HTML" encoding="utf-8" file="sidebar_loading.html" type="tr_html" generateid="false" expand_variables="false"/>
+ <structure name="IDS_PLACEHOLDER" file="transl.rc" type="dialog" >
+ <skeleton expr="lang == 'sv'" file="transl1.rc" variant_of_revision="1"/>
+ </structure>
+ <if expr="lang != 'sv'">
+ <structure name="WELCOME_TOAST.HTML" encoding="utf-8" file="welcome_toast.html" type="tr_html" generateid="false" expand_variables="true"/>
+ </if>
+ </structures>
+ <messages first_id="8192">
+ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
+ Copyright 2008 Google Inc. All Rights Reserved.
+ </message>
+ <message name="IDS_NEWS_PANEL_COPYRIGHT">
+ Google Desktop News gadget
+[IDS_COPYRIGHT_GOOGLE_LONG]
+View news that is personalized based on the articles you read.
+
+For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
+ </message>
+ </messages>
+ </release>
+</grit>
diff --git a/chromium/tools/grit/grit/testdata/cache_prefix.html b/chromium/tools/grit/grit/testdata/cache_prefix.html
new file mode 100644
index 00000000000..b1f91dd82b5
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/cache_prefix.html
@@ -0,0 +1,24 @@
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+</head>
+<body onload="[ONLOAD]">
+<table width="100%" border=1><tr><td>
+<table cellspacing=0 cellpadding=10 width="100%" bgcolor=#ffffff border=1 color="#ffffff">
+<tr><td><font face="arial,sans-serif" color=black size=-1>This is one version of <a href="[$~URL~$]">
+<font color="blue">[URL-DISP]</font></a> from your personal <a href="http://desktop.google.com/webcache.html"><font color=blue>cache</font></a>.<br>
+The page may have changed since that time. Click here for the <a href="[$~URL~$]"><font color="blue">current page</font></a>.<br>
+Since this page is stored on your computer, publicly linking to this page will not work.[$~EXTRA~$]<br><br>
+<font size="-2"><i>Google may not be affiliated with the authors of this page nor responsible for its content. This page may be protected by copyright.</i></font>
+</td>
+</tr></table></td></tr></table>
+<style>
+.hl { color:black; background-color:#ffff88}
+</style>
+<script>
+[$~HIGHLIGHT_SCRIPT~$]
+window.onerror=new Function(';');
+</script>
+<hr id=gg_1>
+</body> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/cache_prefix_file.html b/chromium/tools/grit/grit/testdata/cache_prefix_file.html
new file mode 100644
index 00000000000..f3eb8e0f110
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/cache_prefix_file.html
@@ -0,0 +1,25 @@
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1"></head>
+<body onload="[ONLOAD]">
+<table width="100%" border=1>
+<tr><td>
+<table cellspacing=0 cellpadding=10 width="100%" bgcolor=#ffffff border=1 color="#ffffff">
+<tr><td><font face=arial,sans-serif color=black size=-1>This is one version of <a href="[$~URL~$]"><font color=blue>[URL-DISP]</font></a>
+from your personal <a href="http://desktop.google.com/filecache.html"><font color=blue>cache</font></a>.<br>
+The file may have changed since that time. Click here for the <a href="[$~URL~$]"><font color=blue>current file</font></a>.<br>
+Since this file is stored on your computer, publicly linking to it will not work.[$~EXTRA~$]<br><br>
+<font size="-2"><i>Google may not be affiliated with the authors of this page nor responsible for its content. This page may be protected by copyright.</i></font>
+</td></tr>
+</table>
+</td></tr></table>
+<style>
+.hl { color:black; background-color:#ffff88}
+</style>
+<script>
+[$~HIGHLIGHT_SCRIPT~$]
+window.onerror=new Function(';');
+</script>
+<hr id=gg_1>
+</body> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/chat_result.html b/chromium/tools/grit/grit/testdata/chat_result.html
new file mode 100644
index 00000000000..318078bc3d3
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/chat_result.html
@@ -0,0 +1,24 @@
+[HEADER]
+[CHROME]
+<table border=0 cellpadding=2 cellspacing=2>
+<tr><td>[$~STARTCHAT~$]</td></tr>
+</table>
+<blockquote id=gg_1>
+<table bgcolor=#f0f8ff width=80% cellpadding=5><tr><td>
+<img style="vertical-align:middle;" height=16 src="16x16_chat.gif" width=16> &nbsp; <b>[$~TITLE~$]</b>
+<font size=-1><br><br>Participants: [USERNAME], [BUDDYNAME]<br>
+Date: [TIME]</font></td></tr></table>
+<br id=contents>
+<label>[CONTENTS]</label>
+</blockquote>
+<table border=0 cellpadding=2 cellspacing=2>
+<tr><td>[$~STARTCHAT~$]</td></tr>
+</table>
+<style>
+.hl { color:black; background-color:#ffff88}
+</style>
+<script>
+[$~HIGHLIGHT_SCRIPT~$]
+[ONLOAD]
+</script>
+[FOOTER]
diff --git a/chromium/tools/grit/grit/testdata/chrome/app/generated_resources.grd b/chromium/tools/grit/grit/testdata/chrome/app/generated_resources.grd
new file mode 100644
index 00000000000..c2efb77fd80
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/chrome/app/generated_resources.grd
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+This file contains definitions of resources that will be translated for each
+locale. The variables is_win, is_macosx, is_linux, and is_posix are available
+for making strings OS specific. Other platform defines such as use_titlecase
+are declared in build/common.gypi.
+-->
+
+<grit base_dir="." latest_public_release="0" current_release="1"
+ source_lang_id="en" enc_check="möl">
+ <outputs>
+ <output filename="grit/generated_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="generated_resources_am.pak" type="data_package" lang="am" />
+ <output filename="generated_resources_ar.pak" type="data_package" lang="ar" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_ast.pak" type="data_package" lang="ast" />
+ </if>
+ <output filename="generated_resources_bg.pak" type="data_package" lang="bg" />
+ <output filename="generated_resources_bn.pak" type="data_package" lang="bn" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_bs.pak" type="data_package" lang="bs" />
+ </if>
+ <output filename="generated_resources_ca.pak" type="data_package" lang="ca" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_ca@valencia.pak" type="data_package" lang="ca@valencia" />
+ </if>
+ <output filename="generated_resources_cs.pak" type="data_package" lang="cs" />
+ <output filename="generated_resources_da.pak" type="data_package" lang="da" />
+ <output filename="generated_resources_de.pak" type="data_package" lang="de" />
+ <output filename="generated_resources_el.pak" type="data_package" lang="el" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_en-AU.pak" type="data_package" lang="en-AU" />
+ </if>
+ <output filename="generated_resources_en-GB.pak" type="data_package" lang="en-GB" />
+ <output filename="generated_resources_en-US.pak" type="data_package" lang="en" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_eo.pak" type="data_package" lang="eo" />
+ </if>
+ <output filename="generated_resources_es.pak" type="data_package" lang="es" />
+ <output filename="generated_resources_es-419.pak" type="data_package" lang="es-419" />
+ <output filename="generated_resources_et.pak" type="data_package" lang="et" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_eu.pak" type="data_package" lang="eu" />
+ </if>
+ <output filename="generated_resources_fa.pak" type="data_package" lang="fa" />
+ <output filename="generated_resources_fake-bidi.pak" type="data_package" lang="fake-bidi" />
+ <output filename="generated_resources_fi.pak" type="data_package" lang="fi" />
+ <output filename="generated_resources_fil.pak" type="data_package" lang="fil" />
+ <output filename="generated_resources_fr.pak" type="data_package" lang="fr" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_gl.pak" type="data_package" lang="gl" />
+ </if>
+ <output filename="generated_resources_gu.pak" type="data_package" lang="gu" />
+ <output filename="generated_resources_he.pak" type="data_package" lang="he" />
+ <output filename="generated_resources_hi.pak" type="data_package" lang="hi" />
+ <output filename="generated_resources_hr.pak" type="data_package" lang="hr" />
+ <output filename="generated_resources_hu.pak" type="data_package" lang="hu" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_hy.pak" type="data_package" lang="hy" />
+ <output filename="generated_resources_ia.pak" type="data_package" lang="ia" />
+ </if>
+ <output filename="generated_resources_id.pak" type="data_package" lang="id" />
+ <output filename="generated_resources_it.pak" type="data_package" lang="it" />
+ <output filename="generated_resources_ja.pak" type="data_package" lang="ja" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_ka.pak" type="data_package" lang="ka" />
+ </if>
+ <output filename="generated_resources_kn.pak" type="data_package" lang="kn" />
+ <output filename="generated_resources_ko.pak" type="data_package" lang="ko" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_ku.pak" type="data_package" lang="ku" />
+ <output filename="generated_resources_kw.pak" type="data_package" lang="kw" />
+ </if>
+ <output filename="generated_resources_lt.pak" type="data_package" lang="lt" />
+ <output filename="generated_resources_lv.pak" type="data_package" lang="lv" />
+ <output filename="generated_resources_ml.pak" type="data_package" lang="ml" />
+ <output filename="generated_resources_mr.pak" type="data_package" lang="mr" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_ms.pak" type="data_package" lang="ms" />
+ </if>
+ <output filename="generated_resources_nl.pak" type="data_package" lang="nl" />
+ <!-- The translation console uses 'no' for Norwegian Bokmål. It should
+ be 'nb'. -->
+ <output filename="generated_resources_nb.pak" type="data_package" lang="no" />
+ <output filename="generated_resources_pl.pak" type="data_package" lang="pl" />
+ <output filename="generated_resources_pt-BR.pak" type="data_package" lang="pt-BR" />
+ <output filename="generated_resources_pt-PT.pak" type="data_package" lang="pt-PT" />
+ <output filename="generated_resources_ro.pak" type="data_package" lang="ro" />
+ <output filename="generated_resources_ru.pak" type="data_package" lang="ru" />
+ <output filename="generated_resources_sk.pak" type="data_package" lang="sk" />
+ <output filename="generated_resources_sl.pak" type="data_package" lang="sl" />
+ <output filename="generated_resources_sr.pak" type="data_package" lang="sr" />
+ <output filename="generated_resources_sv.pak" type="data_package" lang="sv" />
+ <output filename="generated_resources_sw.pak" type="data_package" lang="sw" />
+ <output filename="generated_resources_ta.pak" type="data_package" lang="ta" />
+ <output filename="generated_resources_te.pak" type="data_package" lang="te" />
+ <output filename="generated_resources_th.pak" type="data_package" lang="th" />
+ <output filename="generated_resources_tr.pak" type="data_package" lang="tr" />
+ <if expr="pp_ifdef('use_third_party_translations')">
+ <output filename="generated_resources_ug.pak" type="data_package" lang="ug" />
+ </if>
+ <output filename="generated_resources_uk.pak" type="data_package" lang="uk" />
+ <output filename="generated_resources_vi.pak" type="data_package" lang="vi" />
+ <output filename="generated_resources_zh-CN.pak" type="data_package" lang="zh-CN" />
+ <output filename="generated_resources_zh-TW.pak" type="data_package" lang="zh-TW" />
+ </outputs>
+ <translations>
+ <file path="resources/generated_resources_am.xtb" lang="am" />
+ <file path="resources/generated_resources_ar.xtb" lang="ar" />
+ <file path="../../third_party/launchpad_translations/generated_resources_ast.xtb" lang="ast" />
+ <file path="resources/generated_resources_bg.xtb" lang="bg" />
+ <file path="resources/generated_resources_bn.xtb" lang="bn" />
+ <file path="../../third_party/launchpad_translations/generated_resources_bs.xtb" lang="bs" />
+ <file path="resources/generated_resources_ca.xtb" lang="ca" />
+ <file path="../../third_party/launchpad_translations/generated_resources_ca-valencia.xtb" lang="ca@valencia" />
+ <file path="resources/generated_resources_cs.xtb" lang="cs" />
+ <file path="resources/generated_resources_da.xtb" lang="da" />
+ <file path="resources/generated_resources_de.xtb" lang="de" />
+ <file path="resources/generated_resources_el.xtb" lang="el" />
+ <file path="../../third_party/launchpad_translations/generated_resources_en-AU.xtb" lang="en-AU" />
+ <file path="resources/generated_resources_en-GB.xtb" lang="en-GB" />
+ <file path="../../third_party/launchpad_translations/generated_resources_eo.xtb" lang="eo" />
+ <file path="resources/generated_resources_es.xtb" lang="es" />
+ <file path="resources/generated_resources_es-419.xtb" lang="es-419" />
+ <file path="resources/generated_resources_et.xtb" lang="et" />
+ <file path="../../third_party/launchpad_translations/generated_resources_eu.xtb" lang="eu" />
+ <file path="resources/generated_resources_fa.xtb" lang="fa" />
+ <file path="resources/generated_resources_fi.xtb" lang="fi" />
+ <file path="resources/generated_resources_fil.xtb" lang="fil" />
+ <file path="resources/generated_resources_fr.xtb" lang="fr" />
+ <file path="../../third_party/launchpad_translations/generated_resources_gl.xtb" lang="gl" />
+ <file path="resources/generated_resources_gu.xtb" lang="gu" />
+ <file path="resources/generated_resources_hi.xtb" lang="hi" />
+ <file path="resources/generated_resources_hr.xtb" lang="hr" />
+ <file path="resources/generated_resources_hu.xtb" lang="hu" />
+ <file path="../../third_party/launchpad_translations/generated_resources_hy.xtb" lang="hy" />
+ <file path="../../third_party/launchpad_translations/generated_resources_ia.xtb" lang="ia" />
+ <file path="resources/generated_resources_id.xtb" lang="id" />
+ <file path="resources/generated_resources_it.xtb" lang="it" />
+ <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
+ <file path="resources/generated_resources_iw.xtb" lang="he" />
+ <file path="resources/generated_resources_ja.xtb" lang="ja" />
+ <file path="../../third_party/launchpad_translations/generated_resources_ka.xtb" lang="ka" />
+ <file path="resources/generated_resources_kn.xtb" lang="kn" />
+ <file path="resources/generated_resources_ko.xtb" lang="ko" />
+ <file path="../../third_party/launchpad_translations/generated_resources_ku.xtb" lang="ku" />
+ <file path="../../third_party/launchpad_translations/generated_resources_kw.xtb" lang="kw" />
+ <file path="resources/generated_resources_lt.xtb" lang="lt" />
+ <file path="resources/generated_resources_lv.xtb" lang="lv" />
+ <file path="resources/generated_resources_ml.xtb" lang="ml" />
+ <file path="resources/generated_resources_mr.xtb" lang="mr" />
+ <file path="../../third_party/launchpad_translations/generated_resources_ms.xtb" lang="ms" />
+ <file path="resources/generated_resources_nl.xtb" lang="nl" />
+ <file path="resources/generated_resources_no.xtb" lang="no" />
+ <file path="resources/generated_resources_pl.xtb" lang="pl" />
+ <file path="resources/generated_resources_pt-BR.xtb" lang="pt-BR" />
+ <file path="resources/generated_resources_pt-PT.xtb" lang="pt-PT" />
+ <file path="resources/generated_resources_ro.xtb" lang="ro" />
+ <file path="resources/generated_resources_ru.xtb" lang="ru" />
+ <file path="resources/generated_resources_sk.xtb" lang="sk" />
+ <file path="resources/generated_resources_sl.xtb" lang="sl" />
+ <file path="resources/generated_resources_sr.xtb" lang="sr" />
+ <file path="resources/generated_resources_sv.xtb" lang="sv" />
+ <file path="resources/generated_resources_sw.xtb" lang="sw" />
+ <file path="resources/generated_resources_ta.xtb" lang="ta" />
+ <file path="resources/generated_resources_te.xtb" lang="te" />
+ <file path="resources/generated_resources_th.xtb" lang="th" />
+ <file path="resources/generated_resources_tr.xtb" lang="tr" />
+ <file path="../../third_party/launchpad_translations/generated_resources_ug.xtb" lang="ug" />
+ <file path="resources/generated_resources_uk.xtb" lang="uk" />
+ <file path="resources/generated_resources_vi.xtb" lang="vi" />
+ <file path="resources/generated_resources_zh-CN.xtb" lang="zh-CN" />
+ <file path="resources/generated_resources_zh-TW.xtb" lang="zh-TW" />
+ </translations>
+ <release seq="1" allow_pseudo="false">
+ <messages fallback_to_english="true">
+ <!-- TODO add all of your "string table" messages here. Remember to
+ change nontranslateable parts of the messages into placeholders (using the
+ <ph> element). You can also use the 'grit add' tool to help you identify
+ nontranslateable parts and create placeholders for them. -->
+ <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_TITLE" desc="The title of the balloon that is displayed when a background app is installed">
+ New background app installed
+ </message>
+ <message name="IDS_BACKGROUND_APP_INSTALLED_BALLOON_BODY" desc="The contents of the balloon that is displayed when a background app is installed">
+ <ph name="APP_NAME">$1<ex>Background App</ex></ph> will launch at system startup and continue to run in the background even once you've closed all other <ph name="PRODUCT_NAME">$2<ex>Google Chrome</ex></ph> windows.
+ </message>
+ </messages>
+ <structures fallback_to_english="true">
+ <!-- Make sure these stay in sync with the structures in generated_resources.grd. -->
+ <structure name="IDD_CHROME_FRAME_FIND_DIALOG" file="cf_resources.rc" type="dialog" >
+ </structure>
+ <structure name="IDD_CHROME_FRAME_READY_PROMPT" file="cf_resources.rc" type="dialog" >
+ </structure>
+ </structures>
+ </release>
+</grit>
diff --git a/chromium/tools/grit/grit/testdata/chrome_html.html b/chromium/tools/grit/grit/testdata/chrome_html.html
new file mode 100644
index 00000000000..7f7633c5cf2
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/chrome_html.html
@@ -0,0 +1,6 @@
+<include src="included_sample.html">
+<style type="text/css">
+#image {
+ content: url('chrome://theme/IDR_SOME_FILE');
+}
+</style>
diff --git a/chromium/tools/grit/grit/testdata/del_footer.html b/chromium/tools/grit/grit/testdata/del_footer.html
new file mode 100644
index 00000000000..4e19950bfc6
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/del_footer.html
@@ -0,0 +1,8 @@
+<table cellspacing=0 cellpadding=2 width="100%" border=0>
+<tr bgcolor=#EFEFEF><td><font size=-1>&nbsp;<b>Remove</b> checked results and <b>return to search</b>.</font></td>
+<td align=right><font size=-1><a onClick='checkall(1)' href="#">Check all</a> - <a onClick='checkall(0)' href="#">Uncheck all</a>&nbsp;&nbsp;</font></td>
+<td align=right width=1% nowrap><font size=-1>
+<input onclick=deleting() type=submit value="Remove checked results" name=submit2>
+</font></td></tr></table>
+<center><br><font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font></center>
+</body></html>
diff --git a/chromium/tools/grit/grit/testdata/del_header.html b/chromium/tools/grit/grit/testdata/del_header.html
new file mode 100644
index 00000000000..72bc6756eb0
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/del_header.html
@@ -0,0 +1,60 @@
+<body bgcolor="#ffffff" topmargin="2" marginheight="2">
+<table cellSpacing="2" cellPadding="0" width="100%" border="0">
+<form action='[$~DELETE~$]' method="post" name="delform">
+<input name="redir" type="hidden" value="[REDIR]">
+<script>
+<!--
+function deleting() {
+f=document.getElementsByName("del");
+var num = 0;
+if (f.length)
+ for(i=0;i<f.length; i++)
+ if(f[i].checked) num++;
+ if (num == 1) alert("One checked result has been removed");
+ else if (num > 1) alert(num + " checked results have been removed");
+ else alert("No results were checked, so no results have been removed");
+}
+function checkall(v) {
+ f=document.getElementsByName("del");
+ if (f.length)
+ for(i=0;i<f.length; i++)
+ f[i].checked=v;
+}
+//-->
+</script>
+<tr>
+<td vAlign="top" width="1%"><A href='[$~HOMEPAGE~$]'> <img alt="Go to Google Desktop Search" width="150" height="55" src="/logo3.gif" border="0" vspace="12"></A></td>
+<td>&nbsp;</td>
+<td noWrap>
+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td bgColor="#DD0000"><img height="1" alt="" width="1"></td>
+ </tr>
+ </table>
+ <table cellSpacing="0" cellPadding="0" width="100%" border="0">
+ <tr>
+ <td noWrap bgColor="#efefef"><font size="+1"><b>&nbsp;Remove Specific Items</b></font></td>
+ <td noWrap align="right" bgColor="#efefef"><font size="-1"><a href="http://desktop.google.com/remove.html">Help</a>&nbsp;&nbsp;</font></td>
+ </tr>
+ </table>
+</td>
+</tr>
+</table>
+<table cellSpacing="0" cellPadding="2" width="100%" border="0">
+<tr bgColor="#EFEFEF">
+<td><font size="-1">&nbsp;<B>Remove</B> checked results and <B>return to search</B>.</font></td>
+<td align="right"><font size="-1"><a onClick='checkall(1)' href="#">Check all</a> - <a onClick='checkall(0)' href="#">
+Uncheck all</a>&nbsp;&nbsp;</font></td>
+<td align="right" width="1%" nowrap><font size="-1"><input onclick="deleting()" type="submit" value="Remove checked results" name="submit2"></font></td>
+</tr>
+</table>
+<br>
+<table cellspacing="0" cellpadding="2" width="100%" border="0">
+<tr>
+<td colSpan="3" bgcolor="#FFFFFF" style="border:solid; border-width:1px; border-color:#DD0000"><font size="-1">&nbsp;<b>Remove
+checked items from Google Desktop Search. Other copies of the same items will not be
+affected.<br>
+&nbsp;If you view the item again, it will be added back to Google Desktop Search.</b></font></td>
+</tr>
+</table>
+<br> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/deleted.html b/chromium/tools/grit/grit/testdata/deleted.html
new file mode 100644
index 00000000000..5ae5f355faa
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/deleted.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Database Deleted</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
+.q {COLOR: #0000cc}
+</style>
+</head>
+<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
+<center>
+<TABLE cellSpacing=0 cellPadding=0 border=0>
+<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a>
+</td></tr></table><BR>
+<center>The database has been deleted. Click <a href="[$~HOMEPAGE~$]">here</a> to continue.</center>
+</td></tr>
+</table>
+<br><FONT size=-1>[$~BOTTOMLINE~$]</font></p>
+<p><FONT size=-2>&copy;2005 Google</font></p></center></body></html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/details.html b/chromium/tools/grit/grit/testdata/details.html
new file mode 100644
index 00000000000..0ab0e2a90ce
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/details.html
@@ -0,0 +1,10 @@
+[!]
+title Improve Google Desktop Search by Sending Non-Personal Information
+template
+bottomline
+hp_image
+
+<p><strong>This documentation is not yet available</strong></p>
+<center><br>
+<font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font>
+</center>
diff --git a/chromium/tools/grit/grit/testdata/duplicate-name-input.xml b/chromium/tools/grit/grit/testdata/duplicate-name-input.xml
new file mode 100644
index 00000000000..cc4d1d65c57
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/duplicate-name-input.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit base_dir="." latest_public_release="2" current_release="3" source_lang_id="en-US">
+ <release seq="3">
+ <messages>
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ </messages>
+ <structures>
+ <!-- Duplicate name here -->
+ <structure type="version" name="IDS_GREETING" file="rc_files/bla.rc" />
+ </structures>
+ </release>
+ <translations>
+ <file path="figs_nl_translations.xml" />
+ <file path="cjk_translations.xml" />
+ </translations>
+ <outputs>
+ <output filename="resource.h" type="rc_header" />
+ <output filename="resource_en.rc" type="rc_all" lang="en-US" />
+ <output filename="resource_fr.rc" type="rc_all" lang="fr-FR" />
+ <output filename="resource_it.rc" type="rc_translateable" lang="it-IT" />
+ <output filename="resource_zh_cn.rc" type="rc_translateable" lang="zh-CN" />
+ <output filename="nontranslateable.rc" type="rc_nontranslateable" />
+ </outputs>
+</grit>
diff --git a/chromium/tools/grit/grit/testdata/email_result.html b/chromium/tools/grit/grit/testdata/email_result.html
new file mode 100644
index 00000000000..8bb04b988ce
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/email_result.html
@@ -0,0 +1,34 @@
+[HEADER]
+[CHROME]
+<table border=0 cellpadding=2 cellspacing=2 width='100%'>
+<tr><td><font size=-1>[CONV]
+<a href='[$~REPLY_URL~$]'>Reply</a> | <a href='[$~REPLYALL_URL~$]'>Reply&nbsp;to&nbsp;All</a>[$~FORWARD_URL~$] | <a href='mailto:'>Compose</a>[$~OUTLOOKVIEW~$]
+</font></td></tr>
+</table>
+<blockquote id=gg_1>
+<table bgcolor=#f0f8ff width=80% cellpadding=5><tr><td>
+<img style="vertical-align:middle;" height=16 src='/email.gif' width=16> &nbsp; <b>[SUBJECT]</b>
+<p><font size=-1>[FROM-DISP]
+[TO-DISP]
+[CC-DISP]
+[BCC-DISP]
+[REPLYTO-DISP]
+[DATE-DISP]
+[VIEW-DISP]
+[$~ATTACH~$]
+</font></td></tr></table>
+<p class=g><span style="width:500;"><font size=-1><label>[MESSAGE]</label></span></p>
+</font>
+</blockquote>
+<table border=0 cellpadding=2 cellspacing=2 width='100%'>
+<tr><td><font size=-1>[CONV]
+<a href='[$~REPLY_URL~$]'>Reply</a> | <a href='[$~REPLYALL_URL~$]'>Reply&nbsp;to&nbsp;All</a>[$~FORWARD_URL~$] | <a href='mailto:'>Compose</a>[$~OUTLOOKVIEW~$]
+</font></td></tr></table>
+<style>
+.hl { color:black; background-color:#ffff88}
+</style>
+<script>
+[$~HIGHLIGHT_SCRIPT~$]
+[ONLOAD]
+</script>
+[FOOTER] \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/email_thread.html b/chromium/tools/grit/grit/testdata/email_thread.html
new file mode 100644
index 00000000000..3c7279b841d
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/email_thread.html
@@ -0,0 +1,10 @@
+[HEADER]
+[CHROME]
+<blockquote [MAXWIDTH]>
+<b><img src=email.gif style="vertical-align:middle;" width=16 height=16> &nbsp; [SUBJECT]</b><br><br>
+<TABLE cellSpacing=0 cellPadding=3 border=0>
+[CONTENTS]
+</table>
+</blockquote>
+[NEXT_PREV]
+[FOOTER] \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/error.html b/chromium/tools/grit/grit/testdata/error.html
new file mode 100644
index 00000000000..66875a234c9
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/error.html
@@ -0,0 +1,8 @@
+[HEADER]
+[CHROME]
+<br>
+<blockquote>
+[ERROR]<br><br>
+If you think this is an error, please <a href="http://desktop.google.com/feedback.html?version=[VERSION]">contact us</a>.
+</blockquote>
+[FOOTER] \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/explicit_web.html b/chromium/tools/grit/grit/testdata/explicit_web.html
new file mode 100644
index 00000000000..1424adc6178
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/explicit_web.html
@@ -0,0 +1,11 @@
+[HEADER]
+<style>
+.image {BORDER: #0000cc 1px solid;}
+.imageh {BORDER: #0000cc 1px solid;}
+</style>
+[WEB_TOP_CHROME]
+[$~STATUS~$]
+[$~MESSAGE~$]
+[WEB_FILES]
+<br>[NEXT_PREV]
+[FOOTER] \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/footer.html b/chromium/tools/grit/grit/testdata/footer.html
new file mode 100644
index 00000000000..3372d6afac5
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/footer.html
@@ -0,0 +1,14 @@
+<center><br clear=all><br>
+<table cellspacing=0 cellpadding=0 width="100%" border=0><tr bgcolor=#3399CC><td align=middle height=1><img height=1 width=1></td></tr></table>
+<table cellspacing=0 cellpadding=0 width="100%" bgcolor=#e8f4f7 border=0>
+<tr bgcolor=#e8f4f7>
+<td><br>
+<table cellpadding=1 align=center border=0 cellspacing=0 bgcolor=#e8f4f7>
+<form action='[$~SEARCHURL~$]' method=get>
+<tr><td noWrap>[$~BOTTOM~$]</td></tr></form>
+</table><br>
+</td></tr></table>
+<table cellspacing=0 cellpadding=0 width="100%" border=0><tr bgcolor=#3399CC><td align=middle height=1><img height=1 width=1></td></tr></table><br>
+<font size=-1>[$~BOTTOMLINE~$] - &copy;2005 Google </font></center>
+[SCRIPT]
+</body></html>
diff --git a/chromium/tools/grit/grit/testdata/generated_resources_fr.xtb b/chromium/tools/grit/grit/testdata/generated_resources_fr.xtb
new file mode 100644
index 00000000000..6f7d6832f53
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/generated_resources_fr.xtb
@@ -0,0 +1,3090 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fr">
+<translation id="6779164083355903755">Supprime&amp;r</translation>
+<translation id="6879617193011158416">Activer la barre de favoris</translation>
+<translation id="8130276680150879341">Déconnexion du réseau privé</translation>
+<translation id="1058418043520174283"><ph name="INDEX"/> sur <ph name="COUNT"/></translation>
+<translation id="4480627574828695486">Déconnecter ce compte...</translation>
+<translation id="1437399238463685286">Le nom du fichier contient un caractère incorrect : $1</translation>
+<translation id="7040807039050164757">&amp;Vérifier l'orthographe dans ce champ</translation>
+<translation id="778579833039460630">Aucune donnée reçue.</translation>
+<translation id="1852799913675865625">Une erreur s'est produite lors de la tentative de lecture du fichier : <ph name="ERROR_TEXT"/>.</translation>
+<translation id="3828924085048779000">Le mot de passe multiterme est obligatoire.</translation>
+<translation id="8265562484034134517">Importer les données d'un autre navigateur...</translation>
+<translation id="2709516037105925701">Saisie automatique</translation>
+<translation id="4857138207355690859">API P2P</translation>
+<translation id="250599269244456932">Exécuter automatiquement (recommandé)</translation>
+<translation id="3581034179710640788">Le certificat de sécurité du site a expiré !</translation>
+<translation id="2825758591930162672">Clé publique de l'objet</translation>
+<translation id="8275038454117074363">Importer</translation>
+<translation id="8418445294933751433">Afficher dan&amp;s un onglet</translation>
+<translation id="6985276906761169321">ID :</translation>
+<translation id="859285277496340001">Le certificat n'indique aucun mécanisme permettant de vérifier s'il a été révoqué.</translation>
+<translation id="2010799328026760191">Touches de modification...</translation>
+<translation id="3300394989536077382">Signé par :</translation>
+<translation id="654233263479157500">Utiliser un service Web pour résoudre les erreurs de navigation</translation>
+<translation id="4940047036413029306">Guillemet</translation>
+<translation id="1526811905352917883">Une nouvelle tentative de connexion avec SSL 3.0 a dû être effectuée. Cette opération indique généralement que le serveur utilise un logiciel très ancien et qu'il est susceptible de présenter d'autres problèmes de sécurité.</translation>
+<translation id="1497897566809397301">Autoriser le stockage des données locales (recommandé)</translation>
+<translation id="3275778913554317645">Ouvrir dans une fenêtre</translation>
+<translation id="4553117311324416101">Google pense qu'un logiciel malveillant pourrait être installé sur votre ordinateur si vous continuez. Nous vous conseillons de ne pas continuer, même si vous avez déjà consulté ce site auparavant ou si vous avez confiance en celui-ci. Il se peut qu'il ait été piraté récemment. Réessayez demain ou utilisez un autre site.</translation>
+<translation id="509988127256758334">&amp;Rechercher :</translation>
+<translation id="1420684932347524586">Échec de génération de clé privée RSA aléatoire</translation>
+<translation id="2501173422421700905">Certificat en attente</translation>
+<translation id="2313634973119803790">Technologie réseau :</translation>
+<translation id="2382901536325590843">Le certificat du serveur ne figure pas dans le DNS.</translation>
+<translation id="2833791489321462313">Demander le mot de passe au retour de veille</translation>
+<translation id="3850258314292525915">Désactiver la synchronisation</translation>
+<translation id="2721561274224027017">Base de données indexée</translation>
+<translation id="8208216423136871611">Ne pas enregistrer</translation>
+<translation id="684587995079587263"><ph name="PRODUCT_NAME"/> synchronise vos données avec votre compte Google en toute sécurité. Synchronisez toutes vos données ou personnalisez les types de données synchronisées et les options de chiffrement.</translation>
+<translation id="4405141258442788789">Le délai imparti à l'opération est dépassé.</translation>
+<translation id="5048179823246820836">Nordique</translation>
+<translation id="1763046204212875858">Créer des raccourcis vers des applications</translation>
+<translation id="2105006017282194539">Pas encore chargé</translation>
+<translation id="524759338601046922">Confirmer le nouveau code PIN :</translation>
+<translation id="688547603556380205">L2TP/IPSec + Certificat utilisateur</translation>
+<translation id="777702478322588152">Préfecture</translation>
+<translation id="6562437808764959486">Extraction de l'image de récupération...</translation>
+<translation id="561349411957324076">Terminé</translation>
+<translation id="4764776831041365478">Il se peut que la page Web à l'adresse <ph name="URL"/> soit temporairement inaccessible ou qu'elle ait été déplacée de façon permanente à une autre adresse Web.</translation>
+<translation id="6156863943908443225">Cache des scripts</translation>
+<translation id="4610656722473172270">Barre d'outils Google</translation>
+<translation id="151501797353681931">Importés depuis Safari</translation>
+<translation id="6706684875496318067">Le plug-in <ph name="PLUGIN_NAME"/> n'est pas autorisé.</translation>
+<translation id="586567932979200359">Vous exécutez <ph name="PRODUCT_NAME"/> à partir de son image disque. Si vous l'installez sur votre ordinateur, vous pourrez l'utiliser sans image disque et bénéficierez de mises à jour automatiques.</translation>
+<translation id="3775432569830822555">Certificat du serveur SSL</translation>
+<translation id="1829192082282182671">Z&amp;oom arrière</translation>
+<translation id="6102827823267795198">Indique si la suggestion du moteur de recherche doit être entrée immédiatement via la saisie semi-automatique lorsque la fonctionnalité Recherche instantanée est activée.</translation>
+<translation id="1467071896935429871">Mise à jour du système : <ph name="PERCENT"/> % téléchargés</translation>
+<translation id="7881267037441701396">Les informations d'identification associées au partage de vos imprimantes via <ph name="CLOUD_PRINT_NAME"/> sont arrivées à expiration. Cliquez ici pour saisir à nouveau votre nom d'utilisateur et votre mot de passe.</translation>
+<translation id="816055135686411707">Erreur de définition du paramètre de confiance du certificat</translation>
+<translation id="4714531393479055912"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe.</translation>
+<translation id="5704565838965461712">Sélectionnez le certificat à présenter pour l'identification :</translation>
+<translation id="2025632980034333559"><ph name="APP_NAME"/> a planté. Cliquez sur cette info-bulle pour actualiser l'extension.</translation>
+<translation id="4059593000330943833">Compatibilité expérimentale avec des méthodes Wi-Fi Extensible Authentication Protocol supplémentaires, telles que EAP-TLS et LEAP.</translation>
+<translation id="6322279351188361895">Échec de lecture de la clé privée</translation>
+<translation id="3781072658385678636">Les plug-ins suivants ont été bloqués sur cette page :</translation>
+<translation id="4428782877951507641">Configuration de la synchronisation</translation>
+<translation id="3648460724479383440">Case d'option cochée</translation>
+<translation id="4654488276758583406">Très petite</translation>
+<translation id="6647228709620733774">URL de révocation de l'autorité de certification Netscape</translation>
+<translation id="546411240573627095">Style de pavé numérique</translation>
+<translation id="7663002797281767775">Active les feuilles de style CSS 3D et la composition graphique haute performance des pages Web via le processeur graphique.</translation>
+<translation id="2972581237482394796">&amp;Rétablir</translation>
+<translation id="5895138241574237353">Redémarrer</translation>
+<translation id="1858072074757584559">La connexion n'est pas compressée.</translation>
+<translation id="528468243742722775">Fin</translation>
+<translation id="1723824996674794290">&amp;Nouvelle fenêtre</translation>
+<translation id="1313405956111467313">Configuration automatique du proxy</translation>
+<translation id="1589055389569595240">Afficher l'orthographe et la grammaire</translation>
+<translation id="4364779374839574930">Aucune imprimante n'a été trouvée. Veuillez en installer une.</translation>
+<translation id="7017587484910029005">Saisissez les caractères visibles dans l'image ci-dessous.</translation>
+<translation id="9013589315497579992">Certificat d'authentification de client SSL incorrect</translation>
+<translation id="8595062045771121608">Le certificat du serveur ou un certificat AC intermédiaire présenté au navigateur a été signé avec un algorithme de signature faible tel que RSA-MD2. D'après des études récentes menées par des informaticiens, les algorithmes de signature seraient plus faibles qu'on ne le pensait jusqu'alors. Aujourd'hui, ils sont très rarement utilisés par les sites Web jugés dignes de confiance. Ce certificat a peut-être été contrefait. Nous vous déconseillons vivement de continuer.</translation>
+<translation id="8666632926482119393">Rechercher le précédent</translation>
+<translation id="7567293639574541773">I&amp;nspecter l'élément</translation>
+<translation id="8392896330146417149">État d'itinérance :</translation>
+<translation id="6813971406343552491">&amp;Non</translation>
+<translation id="36224234498066874">Effacer les données de navigation...</translation>
+<translation id="3384773155383850738">Nombre maximal de suggestions</translation>
+<translation id="8331498498435985864">L'accessibilité est désactivée.</translation>
+<translation id="8530339740589765688">Sélectionner par domaine</translation>
+<translation id="8677212948402625567">Tout réduire...</translation>
+<translation id="7600965453749440009">Ne jamais traduire les pages rédigées en <ph name="LANGUAGE"/> </translation>
+<translation id="3208703785962634733">Non confirmé</translation>
+<translation id="6523841952727744497">Avant de vous connecter, démarrez une session en tant qu'invité afin d'activer le réseau <ph name="NETWORK_ID"/>.</translation>
+<translation id="7450044767321666434">La gravure de l'image est terminée.</translation>
+<translation id="2653266418988778031">Si vous supprimez le certificat d'une autorité de certification, votre navigateur ne fera plus confiance aux certificats émis par cette autorité de certification.</translation>
+<translation id="298068999958468740">Synchronisez toutes les données de cet ordinateur ou sélectionnez celles que vous souhaitez synchroniser.</translation>
+<translation id="5341849548509163798"><ph name="NUMBER_MANY"/> hours ago</translation>
+<translation id="4422428420715047158">Domaine :</translation>
+<translation id="3602290021589620013">Aperçu</translation>
+<translation id="7516602544578411747">Associe chaque fenêtre du navigateur à un profil et ajoute une option de sélection des profils en haut à droite. Chaque profil possède ses propres favoris, extensions, applications, etc.</translation>
+<translation id="7082055294850503883">Ignorer le verrouillage des majuscules et saisir des minuscules par défaut</translation>
+<translation id="1800124151523561876">Aucune parole détectée</translation>
+<translation id="7814266509351532385">Changer de moteur de recherche par défaut</translation>
+<translation id="5376169624176189338">Cliquer pour revenir en arrière, maintenir pour voir l'historique</translation>
+<translation id="6310545596129886942"><ph name="NUMBER_FEW"/> secondes restantes</translation>
+<translation id="9181716872983600413">Unicode</translation>
+<translation id="1383861834909034572">Ouverture à la fin du téléchargement</translation>
+<translation id="5727728807527375859">Les extensions, les applications et les thèmes peuvent endommager votre ordinateur. Voulez-vous vraiment continuer ?</translation>
+<translation id="3857272004253733895">Schéma du pinyin double</translation>
+<translation id="1636842079139032947">Déconnecter ce compte...</translation>
+<translation id="6721972322305477112">&amp;Fichier</translation>
+<translation id="1076818208934827215">Microsoft Internet Explorer</translation>
+<translation id="9056810968620647706">Aucune correspondance trouvée</translation>
+<translation id="1901494098092085382">État de votre commentaire</translation>
+<translation id="2861301611394761800">Mise à jour terminée. Veuillez redémarrer le système.</translation>
+<translation id="2231238007119540260">Lorsque vous supprimez un certificat de serveur, vous rétablissez les contrôles de sécurité habituels du serveur et un certificat valide lui est demandé.</translation>
+<translation id="5463582782056205887">Essayez d'ajouter
+ <ph name="PRODUCT_NAME"/>
+ aux programmes autorisés dans les paramètres de votre pare-feu ou de votre antivirus. S'il
+ est déjà autorisé, tentez de le supprimer de la liste et de l'ajouter à nouveau à
+ la liste des programmes autorisés.</translation>
+<translation id="7624154074265342755">Réseaux sans fil</translation>
+<translation id="3315158641124845231">Masquer <ph name="PRODUCT_NAME"/></translation>
+<translation id="3496213124478423963">Zoom arrière</translation>
+<translation id="2296019197782308739">Méthode EAP :</translation>
+<translation id="42981349822642051">Développer</translation>
+<translation id="4013794286379809233">Veuillez vous connecter</translation>
+<translation id="7693221960936265065">de n'importe quand</translation>
+<translation id="1763138995382273070">Désactiver la validation des formulaires interactifs HTML5</translation>
+<translation id="4920887663447894854">Le suivi de votre position géographique sur cette page a été bloqué pour les sites suivants :</translation>
+<translation id="7690346658388844119">La gravure de l'image a été interrompue.</translation>
+<translation id="8133676275609324831">&amp;Afficher dans le dossier</translation>
+<translation id="645705751491738698">Continuer à bloquer JavaScript</translation>
+<translation id="4780321648949301421">Enregistrer la page sous...</translation>
+<translation id="9154072353677278078">Le serveur <ph name="DOMAIN"/> à l'adresse <ph name="REALM"/> requiert un nom d'utilisateur et un mot de passe.</translation>
+<translation id="2551191967044410069">Exceptions de géolocalisation</translation>
+<translation id="4092066334306401966">13px</translation>
+<translation id="8178665534778830238">Contenu :</translation>
+<translation id="153384433402665971">Le plug-in <ph name="PLUGIN_NAME"/> a été bloqué, car il n'est plus à jour.</translation>
+<translation id="2610260699262139870">Taille ré&amp;elle</translation>
+<translation id="4535734014498033861">Échec de la connexion au serveur proxy.</translation>
+<translation id="558170650521898289">Vérification de pilote matériel Microsoft Windows</translation>
+<translation id="98515147261107953">Paysage</translation>
+<translation id="8974161578568356045">Détecter automatiquement</translation>
+<translation id="1818606096021558659">Page</translation>
+<translation id="5388588172257446328">Nom d'utilisateur :</translation>
+<translation id="1657406563541664238">Nous aider à améliorer <ph name="PRODUCT_NAME"/> en envoyant automatiquement les statistiques d'utilisation et les rapports d'erreur à Google</translation>
+<translation id="7982789257301363584">Réseau</translation>
+<translation id="8528962588711550376">Connexion en cours</translation>
+<translation id="2336228925368920074">Ajouter tous les onglets aux favoris...</translation>
+<translation id="4985312428111449076">Onglets ou fenêtres</translation>
+<translation id="7481475534986701730">Sites récemment consultés</translation>
+<translation id="4260722247480053581">Ouvrir dans une fenêtre de navigation privée</translation>
+<translation id="8503758797520866434">Préférences de saisie automatique...</translation>
+<translation id="2757031529886297178">Compteur d'images par seconde</translation>
+<translation id="6657585470893396449">Mot de passe</translation>
+<translation id="7881483672146086348">Afficher le compte</translation>
+<translation id="1776883657531386793"><ph name="OID"/> : <ph name="INFO"/></translation>
+<translation id="1510030919967934016">Le suivi de votre position géographique a été bloqué pour cette page.</translation>
+<translation id="4640525840053037973">Connexion à l'aide de votre compte Google</translation>
+<translation id="5255315797444241226">Le mot de passe multiterme entré est incorrect.</translation>
+<translation id="6242054993434749861">télécopie : #<ph name="FAX"/></translation>
+<translation id="762917759028004464">Le navigateur par défaut est actuellement <ph name="BROWSER_NAME"/>.</translation>
+<translation id="9213479837033539041"><ph name="NUMBER_MANY"/> secondes restantes</translation>
+<translation id="560442828508350263">Impossible de déplacer &quot;$1&quot; : $2</translation>
+<translation id="300544934591011246">Mot de passe précédent</translation>
+<translation id="5078796286268621944">Code PIN incorrect</translation>
+<translation id="989988560359834682">Modifier l'adresse</translation>
+<translation id="8487678622945914333">Zoom avant</translation>
+<translation id="2972557485845626008">Micrologiciel</translation>
+<translation id="735327918767574393">Une erreur s'est produite lors de l'affichage de cette page Web. Pour continuer, actualisez cette page ou ouvrez-en une autre.</translation>
+<translation id="8028060951694135607">Récupération de clé Microsoft</translation>
+<translation id="9187657844611842955">recto verso</translation>
+<translation id="6391832066170725637">Fichier ou répertoire introuvable</translation>
+<translation id="4694445829210540512">Aucun forfait de données <ph name="NETWORK"/> actif</translation>
+<translation id="5494920125229734069">Tout sélectionner</translation>
+<translation id="2857834222104759979">Le fichier manifeste est incorrect.</translation>
+<translation id="7931071620596053769">Les pages suivantes ne répondent plus. Vous pouvez attendre qu'elles soient de nouveau accessibles ou les supprimer.</translation>
+<translation id="1209866192426315618"><ph name="NUMBER_DEFAULT"/> minutes restantes</translation>
+<translation id="7938958445268990899">Le certificat du serveur n'est pas encore valide.</translation>
+<translation id="4569998400745857585">Menu contenant des extensions masquées</translation>
+<translation id="4081383687659939437">Enregistrer les infos</translation>
+<translation id="5786805320574273267">Configuration de l'accès à distance à cet ordinateur.</translation>
+<translation id="1801827354178857021">Point</translation>
+<translation id="2179052183774520942">Ajouter un moteur de recherche</translation>
+<translation id="5498951625591520696">Impossible d'atteindre le serveur.</translation>
+<translation id="2956948609882871496">Importer mes favoris...</translation>
+<translation id="1621207256975573490">Enregistrer le &amp;cadre sous...</translation>
+<translation id="4681260323810445443">Vous n'êtes pas autorisé à accéder à la page Web <ph name="URL"/>. Votre connexion peut être requise.</translation>
+<translation id="2176444992480806665">Envoyer la capture d'écran du dernier onglet actif</translation>
+<translation id="1165039591588034296">Erreur</translation>
+<translation id="2064942105849061141">Utiliser le thème GTK+</translation>
+<translation id="2278562042389100163">Ouvrir une fenêtre du navigateur</translation>
+<translation id="5246282308050205996"><ph name="APP_NAME"/> a planté. Cliquez sur cette info-bulle pour redémarrer l'application.</translation>
+<translation id="9218430445555521422">Définir comme navigateur par défaut</translation>
+<translation id="5027550639139316293">Certificat de courrier électronique</translation>
+<translation id="938582441709398163">Clavier en superposition</translation>
+<translation id="427208986916971462">La connexion est compressée avec <ph name="COMPRESSION"/>.</translation>
+<translation id="4589279373639964403">Exporter mes favoris...</translation>
+<translation id="8876215549894133151">Format :</translation>
+<translation id="5234764350956374838">Ignorer</translation>
+<translation id="40027638859996362">Déplacer un mot</translation>
+<translation id="5463275305984126951">Index de <ph name="LOCATION"/></translation>
+<translation id="5154917547274118687">Mémoire</translation>
+<translation id="1493492096534259649">Impossible d'utiliser cette langue pour corriger l'orthographe.</translation>
+<translation id="6628463337424475685">Recherche <ph name="ENGINE"/></translation>
+<translation id="2502105862509471425">Ajouter une autre carte de paiement...</translation>
+<translation id="4037618776454394829">Envoyer la dernière capture d'écran enregistrée</translation>
+<translation id="8987670145726065238">Ce fichier contient du code malveillant. Voulez-vous vraiment continuer ?</translation>
+<translation id="182729337634291014">Erreur de synchronisation...</translation>
+<translation id="4465830120256509958">Clavier brésilien</translation>
+<translation id="2459861677908225199">Utiliser TLS 1.0</translation>
+<translation id="4792711294155034829">&amp;Signaler un problème...</translation>
+<translation id="5819484510464120153">Créer des raccourci&amp;s vers des applications...</translation>
+<translation id="6845180713465955339">Le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; a été émis par :</translation>
+<translation id="7531238562312180404"><ph name="PRODUCT_NAME"/> ne contrôlant pas la façon dont les extensions gèrent vos données personnelles, toutes les extensions sont désactivées dans les fenêtres de navigation privée. Vous pouvez les réactiver individuellement dans le <ph name="BEGIN_LINK"/>gestionnaire des extensions<ph name="END_LINK"/>.</translation>
+<translation id="5667293444945855280">Logiciels malveillants</translation>
+<translation id="3435845180011337502">Mise en page ou mise en forme de la page</translation>
+<translation id="3838186299160040975">Acheter davantage...</translation>
+<translation id="6831043979455480757">Traduire</translation>
+<translation id="3587482841069643663">Tout</translation>
+<translation id="6698381487523150993">Créé :</translation>
+<translation id="4684748086689879921">Annuler l'importation</translation>
+<translation id="9130015405878219958">Le mode indiqué est incorrect.</translation>
+<translation id="6615807189585243369"><ph name="BURNT_AMOUNT"/> copié(s) sur <ph name="TOTAL_SIZE"/></translation>
+<translation id="8518425453349204360">L'accès à distance à cet ordinateur est activé pour <ph name="USER_EMAIL_ADDRESS"/>.</translation>
+<translation id="4950138595962845479">Options...</translation>
+<translation id="4653235815000740718">Un problème est survenu lors de la création du support de récupération du système d'exploitation. Le périphérique de stockage utilisé est introuvable.</translation>
+<translation id="5516565854418269276">Toujours &amp;afficher la barre de favoris</translation>
+<translation id="6426222199977479699">Erreur SSL</translation>
+<translation id="7104784605502674932">Confirmer les préférences de synchronisation</translation>
+<translation id="1788636309517085411">Utiliser les valeurs par défaut</translation>
+<translation id="1661867754829461514">Code secret manquant</translation>
+<translation id="7406714851119047430">L'accès à distance à cet ordinateur est désactivé.</translation>
+<translation id="8589311641140863898">API des extensions expérimentales</translation>
+<translation id="2804922931795102237">Inclure les informations système</translation>
+<translation id="869891660844655955">Date d'expiration</translation>
+<translation id="2178614541317717477">Autorité de certification compromise</translation>
+<translation id="4449935293120761385">À propos de la saisie automatique</translation>
+<translation id="4194570336751258953">Activer la fonction &quot;Taper pour cliquer&quot;</translation>
+<translation id="6066742401428748382">Accès à la page Web refusé</translation>
+<translation id="5111692334209731439">&amp;Gestionnaire de favoris</translation>
+<translation id="8295070100601117548">Erreur serveur</translation>
+<translation id="5661272705528507004">Cette carte SIM est désactivée et ne peut être utilisée. Veuillez demander à votre fournisseur de services de la remplacer.</translation>
+<translation id="443008484043213881">Outils</translation>
+<translation id="2529657954821696995">Clavier néerlandais</translation>
+<translation id="1128128132059598906">EAP-TTLS</translation>
+<translation id="6585234750898046415">Choisissez une image à associer à votre compte. Celle-ci s'affichera sur l'écran de connexion.</translation>
+<translation id="7957054228628133943">Configurer le blocage des fenêtres pop-up...</translation>
+<translation id="179767530217573436">des 4 dernières semaines</translation>
+<translation id="2279770628980885996">Une situation inattendue s'est produite tandis que le serveur tentait de traiter la demande.</translation>
+<translation id="8079135502601738761">Impossible d'afficher certaines parties de ce document PDF. Souhaitez-vous l'ouvrir dans Adobe Reader ?</translation>
+<translation id="9123413579398459698">Proxy FTP</translation>
+<translation id="3887875461425980041">Si vous utilisez la version PPAPI de Flash, exécutez-la dans chaque processus de moteur du rendu plutôt que dans un processus de plug-in dédié.</translation>
+<translation id="8534801226027872331">Cela signifie que le certificat présenté à votre navigateur contient des erreurs et qu'il ne peut pas être compris. Il est possible que les informations sur l'identité du certificat ou que d'autres informations du certificat relatives à la sécurité de la connexion soient incompréhensibles. Ne poursuivez pas.</translation>
+<translation id="3608527593787258723">Activer l'onglet 1</translation>
+<translation id="4497369307931735818">Communication à distance</translation>
+<translation id="3855676282923585394">Importer les favoris et les paramètres...</translation>
+<translation id="1116694919640316211">À propos</translation>
+<translation id="4422347585044846479">Modifier le favori de cette page</translation>
+<translation id="1684638090259711957">Ajouter un format d'exception</translation>
+<translation id="4925481733100738363">Configurer l'accès à distance...</translation>
+<translation id="1880905663253319515">Supprimer le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; ?</translation>
+<translation id="8546306075665861288">Cache des images</translation>
+<translation id="5904093760909470684">Configuration du proxy</translation>
+<translation id="2874027208508018603">En l'absence de connexion Wi-Fi, Google Chrome utilise les données 3G.</translation>
+<translation id="4558734465070698159">Appuyez sur <ph name="HOTKEY_NAME"/> pour sélectionner le mode de saisie précédent.</translation>
+<translation id="3348643303702027858">La création du support de récupération du système d'exploitation a été annulée.</translation>
+<translation id="3391060940042023865">Le plug-in suivant est bloqué : <ph name="PLUGIN_NAME"/></translation>
+<translation id="4237016987259239829">Erreur de connexion réseau</translation>
+<translation id="9050666287014529139">Mot de passe multiterme</translation>
+<translation id="5197255632782567636">Internet</translation>
+<translation id="4755860829306298968">Configurer les paramètres de blocage des plug-ins...</translation>
+<translation id="8879284080359814990">Afficher dan&amp;s un onglet</translation>
+<translation id="2786847742169026523">Synchroniser vos mots de passe</translation>
+<translation id="41293960377217290">Le serveur proxy agit comme un intermédiaire entre votre ordinateur et les autres serveurs. Votre configuration système utilise actuellement un proxy, mais
+ <ph name="PRODUCT_NAME"/>
+ ne parvient pas à s'y connecter.</translation>
+<translation id="4520722934040288962">Sélectionner par type d'application</translation>
+<translation id="3873139305050062481">Procéder à l'i&amp;nspection de l'élément</translation>
+<translation id="7445762425076701745">Impossible de valider entièrement l'identité du serveur auquel vous êtes connecté. Le nom utilisé pour cette connexion n'est valide que sur votre réseau et aucune autorité de certification externe ne peut en vérifier la propriété. Certaines autorités de certification délivrent tout de même des certificats pour ces types de nom, par conséquent nous ne sommes pas en mesure de vérifier que vous êtes connecté au site voulu et non à un site malveillant.</translation>
+<translation id="1556537182262721003">Impossible de déplacer le répertoire d'extensions dans le profil.</translation>
+<translation id="5866557323934807206">Supprimer ces paramètres pour les prochaines visites</translation>
+<translation id="6506104645588011859">L'accessibilité est activée.</translation>
+<translation id="5355351445385646029">Appuyer sur la touche Espace pour sélectionner la suggestion</translation>
+<translation id="6978622699095559061">Vos favoris</translation>
+<translation id="6370820475163108109"><ph name="ORGANIZATION_NAME"/> (<ph name="DOMAIN_NAME"/>)</translation>
+<translation id="5453029940327926427">Fermer les onglets</translation>
+<translation id="406070391919917862">Applications en arrière-plan</translation>
+<translation id="8820817407110198400">Favoris</translation>
+<translation id="3214837514330816581">Supprimer les données synchronisées de Google Dashboard</translation>
+<translation id="2580170710466019930">Veuillez patienter pendant que <ph name="PRODUCT_NAME"/> installe les dernières mises à jour système.</translation>
+<translation id="7428061718435085649">Utilisez les touches Maj gauche et droite pour sélectionner les 2e et 3e propositions</translation>
+<translation id="1070066693520972135">WEP</translation>
+<translation id="206683469794463668">Mode Zhuyin complet. La sélection automatique de la suggestion et les options associées sont désactivées ou ignorées.</translation>
+<translation id="5191625995327478163">&amp;Paramètres linguistiques...</translation>
+<translation id="8833054222610756741">CRX-less Web Apps</translation>
+<translation id="4031729365043810780">Connexion au réseau</translation>
+<translation id="3332115613788466465">Reliure bord long</translation>
+<translation id="1985136186573666099"><ph name="PRODUCT_NAME"/> utilise les paramètres proxy du système pour se connecter au réseau.</translation>
+<translation id="6508261954199872201">Application : <ph name="APP_NAME"/></translation>
+<translation id="5585645215698205895">&amp;Descendre</translation>
+<translation id="8366757838691703947">? Toutes les données présentes sur le périphérique seront supprimées.</translation>
+<translation id="6596816719288285829">Adresse IP</translation>
+<translation id="7747704580171477003">Active le nouveau design de la page &quot;Nouvel onglet&quot; (en cours de développement).</translation>
+<translation id="4508265954913339219">Échec de l'activation</translation>
+<translation id="8656768832129462377">Ne pas vérifier</translation>
+<translation id="715487527529576698">Le chinois simplifié est le mode de saisie initial</translation>
+<translation id="1674989413181946727">Paramètres SSL sur tout l'ordinateur :</translation>
+<translation id="8703575177326907206">Votre connexion à <ph name="DOMAIN"/> n'est pas chiffrée.</translation>
+<translation id="8472623782143987204">matériel requis</translation>
+<translation id="4865571580044923428">Gérer les exceptions...</translation>
+<translation id="2526619973349913024">Rechercher des mises à jour</translation>
+<translation id="3874070094967379652">Utiliser un mot de passe multiterme pour chiffrer mes données de synchronisation</translation>
+<translation id="4864369630010738180">Connexion en cours...</translation>
+<translation id="6500116422101723010">Le serveur ne parvient pas à traiter la demande pour le moment. Ce code indique une situation temporaire. Le serveur sera de nouveau opérationnel ultérieurement.</translation>
+<translation id="1644574205037202324">Historique</translation>
+<translation id="1297175357211070620">Destination</translation>
+<translation id="6219983382864672018">Web audio</translation>
+<translation id="479280082949089240">Cookies placés par cette page</translation>
+<translation id="4198861010405014042">Accès partagé</translation>
+<translation id="6204930791202015665">Afficher...</translation>
+<translation id="5941343993301164315">Veuillez vous connecter à <ph name="TOKEN_NAME"/>.</translation>
+<translation id="4417229845571722044">Ajouter un nouvel e-mail</translation>
+<translation id="8049151370369915255">Personnaliser les polices...</translation>
+<translation id="2886862922374605295">Matériel :</translation>
+<translation id="4497097279402334319">Erreur de connexion au réseau.</translation>
+<translation id="5303618139271450299">Cette page Web est introuvable.</translation>
+<translation id="4256316378292851214">En&amp;registrer la vidéo sous...</translation>
+<translation id="3528171143076753409">Le certificat du serveur n'est pas approuvé.</translation>
+<translation id="6518014396551869914">Cop&amp;ier l'image</translation>
+<translation id="3236997602556743698">Sebeol-sik 390</translation>
+<translation id="542155483965056918"><ph name="NUMBER_ZERO"/> mins ago</translation>
+<translation id="289426338439836048">Autre réseau mobile...</translation>
+<translation id="3986287159189541211">Erreur HTTP <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>) : <ph name="ERROR_TEXT"/></translation>
+<translation id="3225319735946384299">Signature du code</translation>
+<translation id="3118319026408854581">Aide <ph name="PRODUCT_NAME"/></translation>
+<translation id="2422426094670600218">&lt;sans nom&gt;</translation>
+<translation id="2012766523151663935">Version du micrologiciel :</translation>
+<translation id="4120898696391891645">La page ne se charge pas</translation>
+<translation id="6060685159320643512">Attention, ces fonctionnalités expérimentales peuvent mordre.</translation>
+<translation id="5829990587040054282">Verrouiller l'écran ou éteindre</translation>
+<translation id="7800304661137206267">La connexion est chiffrée au moyen de <ph name="CIPHER"/>, avec <ph name="MAC"/> pour l'authentification des messages et <ph name="KX"/> pour la méthode d'échange de clés.</translation>
+<translation id="7706319470528945664">Clavier portugais</translation>
+<translation id="5584537427775243893">Importation</translation>
+<translation id="9128870381267983090">Connexion au réseau</translation>
+<translation id="4181841719683918333">Langues</translation>
+<translation id="6535131196824081346">Cette erreur peut se produire lors de la connexion à un serveur sécurisé (HTTPS).
+ Elle indique que le serveur tente d'établir une connexion sécurisée, mais
+ que celle-ci ne sera pas du tout sécurisée en raison d'une grave erreur de configuration.
+ <ph name="LINE_BREAK"/> Dans ce cas, une intervention
+ est requise sur le serveur.
+ <ph name="PRODUCT_NAME"/>
+ n'utilise pas de connexion non sécurisée pour protéger la confidentialité
+ de vos données.</translation>
+<translation id="5235889404533735074">La synchronisation de <ph name="PRODUCT_NAME"/> vous permet de partager vos données (favoris, préférences) sur vos ordinateurs en toute simplicité. Pour ce faire, <ph name="PRODUCT_NAME"/> enregistre vos données en ligne via Google lorsque vous vous connectez à votre compte.</translation>
+<translation id="6533668113756472185">Format ou mise en forme de la page</translation>
+<translation id="5640179856859982418">Clavier suisse</translation>
+<translation id="5910363049092958439">En&amp;registrer l'image sous...</translation>
+<translation id="1363055550067308502">Basculer en mode pleine chasse ou demi-chasse</translation>
+<translation id="3108967419958202225">Sélectionner...</translation>
+<translation id="6451650035642342749">Effacer les paramètres d'ouverture automatique</translation>
+<translation id="5948544841277865110">Ajouter un réseau privé</translation>
+<translation id="7121570032414343252"><ph name="NUMBER_TWO"/> secondes</translation>
+<translation id="1378451347523657898">Ne pas envoyer de capture d'écran</translation>
+<translation id="5098629044894065541">Hébreu</translation>
+<translation id="7751559664766943798">Toujours afficher la barre de favoris</translation>
+<translation id="5098647635849512368">Impossible de trouver le chemin d'accès absolu du répertoire à empaqueter.</translation>
+<translation id="780617032715125782">Créer un profil</translation>
+<translation id="933712198907837967">Diners Club</translation>
+<translation id="6380224340023442078">Paramètres de contenu...</translation>
+<translation id="950108145290971791">Activer la recherche instantanée pour accélérer la recherche et la navigation ?</translation>
+<translation id="144136026008224475">Plus d'extensions &gt;&gt;</translation>
+<translation id="5486326529110362464">La valeur d'entrée de la clé privée est obligatoire.</translation>
+<translation id="9039663905644212491">PEAP</translation>
+<translation id="62780591024586043">Fonctionnalités de localisation expérimentales</translation>
+<translation id="8584280235376696778">Ou&amp;vrir la vidéo dans un nouvel onglet</translation>
+<translation id="2845382757467349449">Toujours afficher la barre de favoris</translation>
+<translation id="2516384155283419848">Reliure</translation>
+<translation id="3053013834507634016">Utilisation de la clé du certificat</translation>
+<translation id="4487088045714738411">Clavier belge</translation>
+<translation id="7511635910912978956"><ph name="NUMBER_FEW"/> heures restantes</translation>
+<translation id="2152580633399033274">Afficher toutes les images (recommandé)</translation>
+<translation id="7894567402659809897">Cliquez sur
+ <ph name="BEGIN_BOLD"/>Démarrer<ph name="END_BOLD"/>,
+ puis sur
+ <ph name="BEGIN_BOLD"/>Exécuter<ph name="END_BOLD"/>.
+ Saisissez
+ <ph name="BEGIN_BOLD"/>%windir%\\network diagnostic\\xpnetdiag.exe<ph name="END_BOLD"/>
+ et cliquez sur
+ <ph name="BEGIN_BOLD"/>OK<ph name="END_BOLD"/>.</translation>
+<translation id="2934952234745269935">Nom de volume</translation>
+<translation id="7960533875494434480">Reliure bord court</translation>
+<translation id="6431347207794742960"><ph name="PRODUCT_NAME"/> va configurer les mises à jour automatiques pour tous les utilisateurs de cet ordinateur.</translation>
+<translation id="4973698491777102067">Effacer les éléments datant :</translation>
+<translation id="6074963268421707432">Interdire à tous les sites d'afficher des notifications sur le Bureau</translation>
+<translation id="8508050303181238566">Appuyez sur <ph name="HOTKEY_NAME"/> pour passer d'un mode de saisie à l'autre.</translation>
+<translation id="6273404661268779365">Ajouter un nouveau fax</translation>
+<translation id="1995173078718234136">Recherche de contenu en cours...</translation>
+<translation id="4735819417216076266">Style d'entrée avec Espace</translation>
+<translation id="2977095037388048586">Vous avez tenté d'accéder à <ph name="DOMAIN"/>, mais, au lieu de cela, vous communiquez actuellement avec un serveur identifié comme <ph name="DOMAIN2"/>. Cela est peut-être dû à un défaut de configuration du serveur ou à quelque chose de plus grave. Un pirate informatique sur votre réseau cherche peut-être à vous faire visiter une version falsifiée de <ph name="DOMAIN3"/>, donc potentiellement préjudiciable. Nous vous déconseillons vivement de continuer.</translation>
+<translation id="220138918934036434">Masquer le bouton</translation>
+<translation id="5374359983950678924">Modifier l'image</translation>
+<translation id="5158548125608505876">Ne pas synchroniser mes mots de passe</translation>
+<translation id="2167276631610992935">JavaScript</translation>
+<translation id="6974306300279582256">Activer les notifications de <ph name="SITE"/></translation>
+<translation id="492914099844938733">Afficher les incompatibilités</translation>
+<translation id="5233638681132016545">Nouvel onglet</translation>
+<translation id="6567688344210276845">Impossible de charger l'icône &quot;<ph name="ICON"/>&quot; d'action de page.</translation>
+<translation id="5210365745912300556">Fermer l'onglet</translation>
+<translation id="8628085465172583869">Nom d'hôte du serveur :</translation>
+<translation id="498765271601821113">Ajouter une carte de paiement</translation>
+<translation id="7694379099184430148"><ph name="FILENAME"/> : type de fichier inconnu</translation>
+<translation id="1992397118740194946">Non défini</translation>
+<translation id="7966826846893205925">Gérer les paramètres de saisie automatique...</translation>
+<translation id="8556732995053816225">Respecter la &amp;casse</translation>
+<translation id="3314070176311241517">Autoriser tous les sites à exécuter JavaScript (recommandé)</translation>
+<translation id="2406911946387278693">Gérer vos périphériques depuis le cloud</translation>
+<translation id="7419631653042041064">Clavier catalan</translation>
+<translation id="5710740561465385694">Me demander lorsqu'un site essaie de stocker des données</translation>
+<translation id="3897092660631435901">Menu</translation>
+<translation id="7024867552176634416">Sélectionnez le périphérique de stockage amovible à utiliser.</translation>
+<translation id="8553075262323480129">La traduction a échoué, car nous n'avons pas pu déterminer la langue de la page.</translation>
+<translation id="5910680277043747137">Vous pouvez créer des profils supplémentaires pour autoriser plusieurs personnes à utiliser et personnaliser Google Chrome.</translation>
+<translation id="4381849418013903196">Deux-points</translation>
+<translation id="1103523840287552314">Toujours traduire en <ph name="LANGUAGE"/></translation>
+<translation id="2263497240924215535">(désactivée)</translation>
+<translation id="2159087636560291862">Cela signifie que le certificat n'a pas été vérifié par un tiers reconnu par votre ordinateur. N'importe qui peut émettre un certificat en se faisant passer pour un autre site Web. Ce certificat doit donc être vérifié par un tiers approuvé. Sans cette vérification, les informations sur l'identité du certificat sont sans intérêt. Par conséquent, il nous est impossible de vérifier que vous communiquez bien avec <ph name="DOMAIN"/> et non avec un pirate informatique ayant émis son propre certificat en prétendant être <ph name="DOMAIN2"/>. Nous vous déconseillons vivement de continuer.</translation>
+<translation id="58625595078799656"><ph name="PRODUCT_NAME"/> requiert que vous cryptiez vos données à l'aide de votre mot de passe Google ou de votre propre mot de passe multiterme.</translation>
+<translation id="8017335670460187064"><ph name="LABEL"/></translation>
+<translation id="6840184929775541289">N'est pas une autorité de certification</translation>
+<translation id="6099520380851856040">Date et heure : <ph name="CRASH_TIME"/></translation>
+<translation id="144518587530125858">Impossible de charger &quot;<ph name="IMAGE_PATH"/>&quot; pour le thème.</translation>
+<translation id="5355097969896547230">Rechercher à nouveau</translation>
+<translation id="7925285046818567682">En attente de <ph name="HOST_NAME"/>...</translation>
+<translation id="2553440850688409052">Masquer ce plug-in</translation>
+<translation id="3280237271814976245">Enregistrer &amp;sous...</translation>
+<translation id="8301162128839682420">Ajouter une langue :</translation>
+<translation id="7658239707568436148">Annuler</translation>
+<translation id="8695825812785969222">Ouvrir une &amp;adresse...</translation>
+<translation id="4538417792467843292">Supprimer le mot</translation>
+<translation id="8412392972487953978">Vous devez saisir deux fois le même mot de passe multiterme.</translation>
+<translation id="9121814364785106365">Ouvrir dans un onglet épinglé</translation>
+<translation id="6996264303975215450">Page Web, tout type de contenu</translation>
+<translation id="3435896845095436175">Activer</translation>
+<translation id="1891668193654680795">Considérer ce certificat comme fiable pour identifier les développeurs de logiciels.</translation>
+<translation id="5078638979202084724">Ajouter tous les onglets aux favoris</translation>
+<translation id="5585118885427931890">Impossible de créer le dossier de favoris.</translation>
+<translation id="2154710561487035718">Copier l'URL</translation>
+<translation id="8163672774605900272">Si vous pensez ne pas avoir à utiliser de serveur proxy, procédez comme suit :
+ <ph name="PLATFORM_TEXT"/></translation>
+<translation id="5510687173983454382">Définir les utilisateurs autorisés à se connecter à un périphérique et autoriser les sessions de navigation en tant qu'invité</translation>
+<translation id="3241680850019875542">Sélectionnez le répertoire racine de l'extension à empaqueter. Pour mettre à jour une extension, sélectionnez également le fichier de clé privée à réutiliser.</translation>
+<translation id="7500424997253660722">Pool restreint :</translation>
+<translation id="657402800789773160">&amp;Rafraîchir cette page</translation>
+<translation id="6163363155248589649">&amp;Normal</translation>
+<translation id="7972714317346275248">PKCS #1 SHA-384 avec chiffrement RSA</translation>
+<translation id="3020990233660977256">Numéro de série : <ph name="SERIAL_NUMBER"/></translation>
+<translation id="8426519927982004547">HTTPS/SSL</translation>
+<translation id="8216781342946147825">Toutes les données de votre ordinateur et des sites Web que vous visitez</translation>
+<translation id="5548207786079516019">Ceci est une installation secondaire de <ph name="PRODUCT_NAME"/> et ce dernier ne peut pas être défini comme navigateur par défaut.</translation>
+<translation id="3984413272403535372">Erreur lors de la signature de l'extension</translation>
+<translation id="8807083958935897582"><ph name="PRODUCT_NAME"/> permet d'effectuer des recherches sur Internet à l'aide du champ polyvalent. Sélectionnez le moteur de recherche à utiliser :</translation>
+<translation id="6629104427484407292">Sécurité : <ph name="SECURITY"/></translation>
+<translation id="9208886416788010685">Adobe Reader n'est pas à jour</translation>
+<translation id="3373604799988099680">Extensions ou applications</translation>
+<translation id="318408932946428277">Effacer les cookies et autres données de site et de plug-in lorsque je ferme le navigateur</translation>
+<translation id="314141447227043789">Téléchargement de l'image terminé.</translation>
+<translation id="8725178340343806893">Favoris</translation>
+<translation id="5177526793333269655">Afficher les vignettes</translation>
+<translation id="8926389886865778422">Ne plus afficher ce message</translation>
+<translation id="6985235333261347343">Agent de récupération de clé Microsoft</translation>
+<translation id="3605499851022050619">Page de diagnostic de navigation sécurisée</translation>
+<translation id="4417271111203525803">Adresse ligne 2</translation>
+<translation id="7617095560120859490">Décrivez-nous le problème recontré. (Champ obligatoire)</translation>
+<translation id="5618333180342767515">Cela peut prendre quelques minutes.</translation>
+<translation id="5399884481423204214">Échec de l'envoi du commentaire : $1</translation>
+<translation id="4307992518367153382">Options de base</translation>
+<translation id="8480417584335382321">Niveau de zoom par défaut :</translation>
+<translation id="3872166400289564527">Stockage externe</translation>
+<translation id="5912378097832178659">Modifi&amp;er les moteurs de recherche...</translation>
+<translation id="8272426682713568063">Cartes de paiement</translation>
+<translation id="3749289110408117711">Nom du fichier</translation>
+<translation id="3173397526570909331">Arrêter la synchronisation</translation>
+<translation id="5538092967727216836">Actualiser le cadre</translation>
+<translation id="4813345808229079766">Connexion</translation>
+<translation id="411666854932687641">Mémoire privée</translation>
+<translation id="119944043368869598">Tout effacer</translation>
+<translation id="3467848195100883852">Activer la correction orthographique automatique</translation>
+<translation id="1336254985736398701">Afficher les &amp;infos sur la page</translation>
+<translation id="7550830279652415241">favoris_<ph name="DATESTAMP"/>.html</translation>
+<translation id="6828153365543658583">Autoriser uniquement les utilisateurs suivants à se connecter :</translation>
+<translation id="1652965563555864525">&amp;Muet</translation>
+<translation id="4200983522494130825">Nouvel ongle&amp;t</translation>
+<translation id="7979036127916589816">Erreur de synchronisation</translation>
+<translation id="1029317248976101138">Zoom</translation>
+<translation id="5455790498993699893"><ph name="ACTIVE_MATCH"/> sur <ph name="TOTAL_MATCHCOUNT"/></translation>
+<translation id="8890069497175260255">Type de clavier</translation>
+<translation id="1202290638211552064">Délai d'expiration atteint au niveau de la passerelle ou du serveur proxy en attente d'une réponse d'un serveur en amont.</translation>
+<translation id="7765158879357617694">Déplacer</translation>
+<translation id="5731751937436428514">Mode de saisie du vietnamien (VIQR)</translation>
+<translation id="8412144371993786373">Ajouter la page actuelle aux favoris</translation>
+<translation id="7615851733760445951">&lt;aucun cookie sélectionné&gt;</translation>
+<translation id="469553822757430352">Le mot de passe de l'application est incorrect.</translation>
+<translation id="2493021387995458222">Sélectionner &quot;un mot à la fois&quot;</translation>
+<translation id="5279600392753459966">Tout bloquer</translation>
+<translation id="6846298663435243399">Chargement en cours…</translation>
+<translation id="7392915005464253525">&amp;Rouvrir la fenêtre fermée</translation>
+<translation id="1144684570366564048">Gérer les exceptions...</translation>
+<translation id="7400418766976504921">URL</translation>
+<translation id="1541725072327856736">Katakana demi-chasse</translation>
+<translation id="7456847797759667638">Ouvrir une adresse</translation>
+<translation id="1388866984373351434">Données de navigation</translation>
+<translation id="3754634516926225076">Code PIN incorrect. Veuillez réessayer.</translation>
+<translation id="7378627244592794276">Non</translation>
+<translation id="2800537048826676660">Utiliser cette langue pour corriger l'orthographe</translation>
+<translation id="68541483639528434">Fermer les autres onglets</translation>
+<translation id="941543339607623937">Clé privée non valide.</translation>
+<translation id="6499058468232888609">Une erreur réseau s'est produite pendant la communication avec le service de gestion des périphériques.</translation>
+<translation id="4433862206975946675">Importer les données d'un autre navigateur...</translation>
+<translation id="4022426551683927403">&amp;Ajouter au dictionnaire</translation>
+<translation id="2897878306272793870">Voulez-vous vraiment ouvrir <ph name="TAB_COUNT"/> onglets ?</translation>
+<translation id="312759608736432009">Fabricant du périphérique :</translation>
+<translation id="362276910939193118">Afficher l'historique complet</translation>
+<translation id="6079696972035130497">Illimité</translation>
+<translation id="4365411729367255048">Clavier Neo2 allemand</translation>
+<translation id="6348657800373377022">Liste déroulante</translation>
+<translation id="8064671687106936412">Clé :</translation>
+<translation id="2218515861914035131">Coller en texte brut</translation>
+<translation id="1725149567830788547">Afficher les &amp;commandes</translation>
+<translation id="3528033729920178817">Cette page suit votre position géographique.</translation>
+<translation id="5518584115117143805">Certificat de chiffrement de courrier électronique</translation>
+<translation id="9203398526606335860">&amp;Profilage activé</translation>
+<translation id="4307281933914537745">En savoir plus sur la récupération du système</translation>
+<translation id="2849936225196189499">Essentielle</translation>
+<translation id="9001035236599590379">Type MIME</translation>
+<translation id="5612754943696799373">Autoriser le téléchargement ?</translation>
+<translation id="6353618411602605519">Clavier croate</translation>
+<translation id="5515810278159179124">Interdire à tous les sites de suivre ma position géographique</translation>
+<translation id="5999606216064768721">Utiliser la barre de titre du système et les bordures de la fenêtre</translation>
+<translation id="904752364881701675">En bas à gauche</translation>
+<translation id="3398951731874728419">Informations sur l'erreur :</translation>
+<translation id="1464570622807304272">Essayez : saisissez &quot;orchidées&quot;, puis appuyez sur Entrée.</translation>
+<translation id="8026684114486203427">Pour utiliser Chrome Web Store, vous devez être connecté à un compte Google.</translation>
+<translation id="8417276187983054885">Configurer <ph name="CLOUD_PRINT_NAME"/></translation>
+<translation id="3056462238804545033">Petit problème... Nous n'avons pas réussi à vous authentifier. Veuillez vérifier vos identifiants de connexion puis réessayer.</translation>
+<translation id="5298420986276701358">Pour gérer à distance la configuration de ce périphérique <ph name="PRODUCT_NAME"/> depuis le cloud, connectez-vous avec votre compte Google Apps.</translation>
+<translation id="2678063897982469759">Réactiver</translation>
+<translation id="1779766957982586368">Fermer la fenêtre</translation>
+<translation id="4850886885716139402">Présentation</translation>
+<translation id="89217462949994770">Vous avez saisi un trop grand nombre de codes PIN incorrects. Veuillez contacter <ph name="CARRIER_ID"/> pour obtenir une nouvelle clé de déverrouillage du code PIN à 8 chiffres.</translation>
+<translation id="5920618722884262402">Bloquer le contenu inapproprié</translation>
+<translation id="5120247199412907247">Configuration avancée</translation>
+<translation id="5922220455727404691">Utiliser SSL 3.0</translation>
+<translation id="1368352873613152012">Règles de confidentialité liées à la navigation sécurisée</translation>
+<translation id="5105859138906591953">Vous devez être connecté à votre compte Google pour importer les favoris de la barre d'outils Google dans Google Chrome. Connectez-vous et relancez l'importation.</translation>
+<translation id="8899851313684471736">Ouvrir le lien dans une nouvelle &amp;fenêtre</translation>
+<translation id="4110342520124362335">Les cookies de <ph name="DOMAIN"/> ont été bloqués.</translation>
+<translation id="3303818374450886607">Copies</translation>
+<translation id="2019718679933488176">&amp;Ouvrir le fichier audio dans un nouvel onglet</translation>
+<translation id="4138267921960073861">Afficher les noms d'utilisateurs et leur photo sur la page de connexion</translation>
+<translation id="7465778193084373987">URL de révocation de certificat Netscape</translation>
+<translation id="5976690834266782200">Ajoute des options de regroupement des onglets dans le menu contextuel des onglets.</translation>
+<translation id="4755240240651974342">Clavier finnois</translation>
+<translation id="7049893973755373474">Vérifiez votre connexion Internet. Redémarrez votre routeur, votre modem
+ ou tout autre périphérique réseau que vous utilisez.</translation>
+<translation id="7421925624202799674">&amp;Afficher le code source de la page</translation>
+<translation id="3940082421246752453">Le serveur ne prend pas en charge la version HTTP utilisée dans la demande.</translation>
+<translation id="661719348160586794">Vos mots de passe enregistrés s'afficheront ici.</translation>
+<translation id="6686490380836145850">Fermer les onglets sur la droite</translation>
+<translation id="5608669887400696928"><ph name="NUMBER_DEFAULT"/> heures</translation>
+<translation id="8844709414456935411"><ph name="PRODUCT_NAME"/>
+ indique qu'un produit ESET intercepte les connexions sécurisées.
+ En général, cela ne constitue pas un problème de sécurité car le
+ logiciel ESET s'exécute souvent sur le même ordinateur. Toutefois, en raison
+ de certaines incompatibilités avec les connexions sécurisées
+ <ph name="PRODUCT_NAME"/>,
+ vous devez configurer les produits ESET de manière à éviter ces
+ interceptions. Cliquez sur le lien En savoir plus pour obtenir des instructions.</translation>
+<translation id="3936877246852975078">Les requêtes adressées au serveur ont été temporairement limitées.</translation>
+<translation id="2600306978737826651">Impossible de télécharger l'image. Gravure annulée.</translation>
+<translation id="609978099044725181">Activer/désactiver le mode Hanja</translation>
+<translation id="1829483195200467833">Effacer les paramètres d'ouverture automatique</translation>
+<translation id="2738771556149464852">Pas après le</translation>
+<translation id="5774515636230743468">Manifeste :</translation>
+<translation id="719464814642662924">Visa</translation>
+<translation id="7474889694310679759">Clavier anglais canadien</translation>
+<translation id="1817871734039893258">Récupération de fichier Microsoft</translation>
+<translation id="2423578206845792524">En&amp;registrer l'image sous...</translation>
+<translation id="6839929833149231406">Zone</translation>
+<translation id="9068931793451030927">Chemin :</translation>
+<translation id="283278805979278081">Prendre la photo</translation>
+<translation id="7320906967354320621">Inactif</translation>
+<translation id="1407050882688520094">Certains de vos certificats enregistrés identifient ces autorités de certification :</translation>
+<translation id="4287689875748136217">Impossible d'afficher la page Web, car le serveur n'a envoyé aucune donnée.</translation>
+<translation id="1634788685286903402">Considérer ce certificat comme fiable pour identifier les utilisateurs de messageries.</translation>
+<translation id="7052402604161570346">Ce type de fichier peut endommager votre ordinateur. Voulez-vous vraiment télécharger <ph name="FILE_NAME"/> ?</translation>
+<translation id="8642489171979176277">Importés depuis la barre d'outils Google</translation>
+<translation id="4142744419835627535">Recherche instantanée et saisie semi-automatique</translation>
+<translation id="4684427112815847243">Tout synchroniser</translation>
+<translation id="1125520545229165057">Dvorak (Hsu)</translation>
+<translation id="8940229512486821554">Exécuter la commande <ph name="EXTENSION_NAME"/> : <ph name="SEARCH_TERMS"/></translation>
+<translation id="2232876851878324699">Le fichier contenait un certificat, qui n'a pas été importé :</translation>
+<translation id="7787129790495067395">Vous utilisez actuellement un mot de passe multiterme. Si vous l'oubliez, vous pouvez réinitialiser la synchronisation afin de supprimer vos données des serveurs Google à l'aide de Google Dashboard.</translation>
+<translation id="2686759344028411998">Impossible de détecter les modules chargés.</translation>
+<translation id="572525680133754531">Cette fonctionnalité affiche une bordure autour des couches de rendu afin de déboguer et d'étudier leur composition.</translation>
+<translation id="2011110593081822050">Processus de traitement Web : <ph name="WORKER_NAME"/></translation>
+<translation id="3294437725009624529">Invité</translation>
+<translation id="350069200438440499">Nom du fichier :</translation>
+<translation id="9058204152876341570">Un élément est manquant.</translation>
+<translation id="8494979374722910010">Échec de la tentative de connexion au serveur.</translation>
+<translation id="7810202088502699111">Des fenêtres pop-up ont été bloquées sur cette page.</translation>
+<translation id="8190698733819146287">Personnaliser les langues et la saisie...</translation>
+<translation id="646727171725540434">Proxy HTTP</translation>
+<translation id="1006316751839332762">Mot de passe multiterme de chiffrement</translation>
+<translation id="8795916974678578410">Nouvelle fenêtre</translation>
+<translation id="2733275712367076659">Certains certificats provenant de ces organisations vous identifient :</translation>
+<translation id="4801512016965057443">Autoriser l'itinérance des données mobiles</translation>
+<translation id="2515586267016047495">Alt</translation>
+<translation id="2046040965693081040">Utiliser les pages actuelles</translation>
+<translation id="3798449238516105146">Version</translation>
+<translation id="5764483294734785780">En&amp;registrer le fichier audio sous...</translation>
+<translation id="5252456968953390977">Itinérance</translation>
+<translation id="8744641000906923997">Romaji</translation>
+<translation id="8507996248087185956"><ph name="NUMBER_DEFAULT"/> minutes</translation>
+<translation id="4845656988780854088">Synchroniser uniquement les paramètres et\ndonnées qui ont changé depuis la dernière connexion\n(requiert votre mot de passe précédent)</translation>
+<translation id="348620396154188443">Autoriser tous les sites à afficher des notifications sur le Bureau</translation>
+<translation id="8214489666383623925">Ouvrir le fichier...</translation>
+<translation id="5376120287135475614">Changer de fenêtre</translation>
+<translation id="5230160809118287008">Chèvres téléportées</translation>
+<translation id="1701567960725324452">Si vous arrêtez la synchronisation, les données stockées sur cet ordinateur et dans votre compte Google demeureront à ces deux emplacements. Toutefois, les nouvelles données ou les modifications apportées au contenu existant ne seront pas synchronisées.</translation>
+<translation id="7761701407923456692">Le certificat du serveur ne correspond pas à l'URL.</translation>
+<translation id="3885155851504623709">Commune</translation>
+<translation id="4910171858422458941">Impossible d'activer les plug-ins désactivés par une stratégie d'entreprise.</translation>
+<translation id="4495419450179050807">Ne pas afficher sur cette page</translation>
+<translation id="4745800796303246012">Méthodes EAP en Wi-Fi expérimentales</translation>
+<translation id="1225544122210684390">Disque dur</translation>
+<translation id="939736085109172342">Nouveau dossier</translation>
+<translation id="4933484234309072027">intégration sur <ph name="URL"/></translation>
+<translation id="5554720593229208774">Autorité de certification de messagerie</translation>
+<translation id="862750493060684461">Cache CSS</translation>
+<translation id="2832519330402637498">En haut à gauche</translation>
+<translation id="6749695674681934117">Saisissez le nom du nouveau dossier.</translation>
+<translation id="6204994989617056362">L'extension de renégociation SSL était introuvable lors de la négociation sécurisée. Avec certains sites, connus pour leur prise en charge de l'extension de renégociation, Google Chrome exige une négociation mieux sécurisée afin de prévenir certaines attaques. L'absence de cette extension suggère que votre connexion a été interceptée et manipulée au cours du transfert.</translation>
+<translation id="6679492495854441399">Petit problème... Une erreur de communication avec le réseau est survenue lors de la tentative d'inscription de ce périphérique. Veuillez vérifier votre connexion réseau et réessayer.</translation>
+<translation id="7789962463072032349">pause</translation>
+<translation id="121827551500866099">Afficher tous les téléchargements...</translation>
+<translation id="1562633988311880769">Connexion à <ph name="CLOUD_PRINT_NAME"/></translation>
+<translation id="5949910269212525572">Impossible de résoudre l'adresse DNS du serveur.</translation>
+<translation id="3115147772012638511">En attente de l'affichage du cache</translation>
+<translation id="257088987046510401">Thèmes</translation>
+<translation id="6771079623344431310">Impossible de se connecter au serveur proxy.</translation>
+<translation id="2200129049109201305">Ignorer la synchronisation des données chiffrées ?</translation>
+<translation id="1426410128494586442">Oui</translation>
+<translation id="6468252175335241103">%b %-d, %Y</translation>
+<translation id="6725970970008349185">Nombre de suggestions par page</translation>
+<translation id="6198252989419008588">Modifier le code PIN</translation>
+<translation id="5749483996735055937">Un problème est survenu lors de la copie de l'image de récupération sur le périphérique.</translation>
+<translation id="3520476450377425184"><ph name="NUMBER_MANY"/> jours restants</translation>
+<translation id="7643817847124207232">La connexion Internet a été interrompue.</translation>
+<translation id="932327136139879170">Début</translation>
+<translation id="4764675709794295630">« Précédent</translation>
+<translation id="2560794850818211873">C&amp;opier l'URL de la vidéo</translation>
+<translation id="6042708169578999844">Vos données sur <ph name="WEBSITE_1"/> et <ph name="WEBSITE_2"/></translation>
+<translation id="5302048478445481009">Langue</translation>
+<translation id="5553089923092577885">Mappages des stratégies de certificat</translation>
+<translation id="5600907569873192868"><ph name="NUMBER_MANY"/> minutes restantes</translation>
+<translation id="1519704592140256923">Sélectionner la position</translation>
+<translation id="1275018677838892971">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites signalés comme étant des sites de phishing. Ces derniers incitent les internautes à divulguer leurs informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
+<translation id="702455272205692181"><ph name="EXTENSION_NAME"/></translation>
+<translation id="7170041865419449892">Hors de portée</translation>
+<translation id="908263542783690259">Effacer l'historique de navigation</translation>
+<translation id="7518003948725431193">Aucune page Web trouvée à l'adresse :<ph name="URL"/></translation>
+<translation id="745602119385594863">Nouveau moteur de recherche :</translation>
+<translation id="7484645889979462775">Jamais pour ce site</translation>
+<translation id="8666066831007952346"><ph name="NUMBER_TWO"/> jours restants</translation>
+<translation id="9086455579313502267">Impossible d'accéder au réseau.</translation>
+<translation id="5595485650161345191">Modifier l'adresse</translation>
+<translation id="2374144379568843525">&amp;Masquer le panneau de la vérification orthographique</translation>
+<translation id="2694026874607847549">1 cookie</translation>
+<translation id="4393664266930911253">Activer ces fonctionnalités...</translation>
+<translation id="6390842777729054533"><ph name="NUMBER_ZERO"/> secondes restantes</translation>
+<translation id="3909791450649380159">Cou&amp;per</translation>
+<translation id="2955913368246107853">Fermer la barre de recherche</translation>
+<translation id="5642508497713047">Signataire de la liste de révocation de certificats</translation>
+<translation id="813082847718468539">Afficher des informations à propos du site</translation>
+<translation id="3122464029669770682">UC</translation>
+<translation id="1684861821302948641">Fermer les pages</translation>
+<translation id="6092270396854197260">MSPY</translation>
+<translation id="6802031077390104172"><ph name="USAGE"/> (<ph name="OID"/>)</translation>
+<translation id="4052120076834320548">Très petite</translation>
+<translation id="6623138136890659562">Afficher les réseaux privés dans le menu Réseau pour activer la connexion à un VPN</translation>
+<translation id="8969837897925075737">Vérification de la mise à jour du système...</translation>
+<translation id="3393716657345709557">L'entrée demandée est introuvable dans le cache.</translation>
+<translation id="7241389281993241388">Connectez-vous à <ph name="TOKEN_NAME"/> pour importer le certificat client.</translation>
+<translation id="40334469106837974">Modifier la mise en page</translation>
+<translation id="4804818685124855865">Se déconnecter</translation>
+<translation id="2617919205928008385">Espace insuffisant.</translation>
+<translation id="210445503571712769">Préférences synchronisées</translation>
+<translation id="1608306110678187802">Imp&amp;rimer le cadre...</translation>
+<translation id="7427315641433634153">MSCHAP</translation>
+<translation id="6622980291894852883">Continuer à bloquer les images</translation>
+<translation id="5937837224523037661">Lorsqu'un site utilise des plug-ins :</translation>
+<translation id="4988792151665380515">Échec d'exportation de la clé publique</translation>
+<translation id="6333049849394141510">Choisir les éléments à synchroniser</translation>
+<translation id="446322110108864323">Paramètres de saisie du Pinyin</translation>
+<translation id="4948468046837535074">Ouvrir les pages suivantes :</translation>
+<translation id="5222676887888702881">Déconnexion</translation>
+<translation id="6978121630131642226">Moteurs de recherche</translation>
+<translation id="6839225236531462745">Erreur de suppression de certificat</translation>
+<translation id="6745994589677103306">Ne rien faire</translation>
+<translation id="855081842937141170">Épingler l'onglet</translation>
+<translation id="6263541650532042179">réinitialiser la synchronisation</translation>
+<translation id="6055392876709372977">PKCS #1 SHA-256 avec chiffrement RSA</translation>
+<translation id="7903984238293908205">Katakana</translation>
+<translation id="3781488789734864345">Choisir un réseau mobile</translation>
+<translation id="268053382412112343">&amp;Historique</translation>
+<translation id="2723893843198727027">Mode développeur :</translation>
+<translation id="1722567105086139392">Lien</translation>
+<translation id="2620436844016719705">Système</translation>
+<translation id="5362741141255528695">Sélectionnez le fichier de clé privée.</translation>
+<translation id="5292890015345653304">Insérez une carte SD ou une carte mémoire USB.</translation>
+<translation id="5583370583559395927">Temps restant : <ph name="TIME_REMAINING"/></translation>
+<translation id="8065982201906486420">Cliquez ici pour exécuter le plug-in <ph name="PLUGIN_NAME"/>.</translation>
+<translation id="6219717821796422795">Hanyu</translation>
+<translation id="3725367690636977613">pages</translation>
+<translation id="2688477613306174402">Configuration en cours</translation>
+<translation id="1195447618553298278">Erreur inconnue</translation>
+<translation id="3353284378027041011"><ph name="NUMBER_FEW"/> days ago</translation>
+<translation id="8811462119186190367">La langue utilisée pour Google Chrome est passée de &quot;<ph name="FROM_LOCALE"/>&quot; à &quot;<ph name="TO_LOCALE"/>&quot; après la synchronisation de vos paramètres.</translation>
+<translation id="1087119889335281750">&amp;Aucune suggestion orthographique</translation>
+<translation id="5228309736894624122">Erreur de protocole SSL</translation>
+<translation id="8216170236829567922">Mode de saisie du thaï (clavier Pattachote)</translation>
+<translation id="8464132254133862871">Ce compte utilisateur n'est pas compatible avec ce service.</translation>
+<translation id="6812349420832218321"><ph name="PRODUCT_NAME"/> ne peut pas être exécuté en tant que root.</translation>
+<translation id="5076340679995252485">C&amp;oller</translation>
+<translation id="2904348843321044456">Paramètres de contenu...</translation>
+<translation id="1055216403268280980">Dimensions de l'image</translation>
+<translation id="1784284518684746740">Sélectionner le fichier à enregistrer sous</translation>
+<translation id="7032947513385578725">Disque Flash</translation>
+<translation id="5518442882456325299">Moteur de recherche actuel :</translation>
+<translation id="14171126816530869">L'identité de <ph name="ORGANIZATION"/> situé à <ph name="LOCALITY"/> a été vérifiée par <ph name="ISSUER"/>.</translation>
+<translation id="6263082573641595914">Version de l'autorité de certification Microsoft</translation>
+<translation id="3105917916468784889">Enregistrer une capture d'écran</translation>
+<translation id="1741763547273950878">Page sur <ph name="SITE"/></translation>
+<translation id="1587275751631642843">Console &amp;JavaScript</translation>
+<translation id="8460696843433742627">Réponse reçue incorrecte lors de la tentative de chargement de <ph name="URL"/>.
+ Cela peut être dû à une opération de maintenance ou à une configuration incorrecte sur le serveur.</translation>
+<translation id="297870353673992530">Serveur DNS :</translation>
+<translation id="3222066309010235055">Pré-rendu : <ph name="PRERENDER_CONTENTS_NAME"/></translation>
+<translation id="6410063390789552572">Impossible d'accéder à la bibliothèque réseau.</translation>
+<translation id="6880587130513028875">Des images ont été bloquées sur cette page.</translation>
+<translation id="851263357009351303">Toujours autoriser <ph name="HOST"/> à afficher les images</translation>
+<translation id="3511307672085573050">Copier l'adr&amp;esse du lien</translation>
+<translation id="1134009406053225289">Ouvrir dans une fenêtre de navigation privée</translation>
+<translation id="6655190889273724601">Mode développeur</translation>
+<translation id="1071917609930274619">Chiffrement des données</translation>
+<translation id="3473105180351527598">Activer la protection contre le phishing et les logiciels malveillants</translation>
+<translation id="6151323131516309312">Appuyez sur <ph name="SEARCH_KEY"/> pour rechercher sur <ph name="SITE_NAME"/></translation>
+<translation id="3753317529742723206">Voulez-vous utiliser <ph name="HANDLER_TITLE"/> (<ph name="HANDLER_HOSTNAME"/>) au lieu de <ph name="REPLACED_HANDLER_TITLE"/> pour gérer les liens <ph name="PROTOCOL"/>:// à partir de maintenant ?</translation>
+<translation id="6216679966696797604">Démarrer une session en tant qu'invité</translation>
+<translation id="5456397824015721611">Nombre maximal de caractères chinois dans la mémoire tampon de pré-édition, notamment les entrées de symboles Zhuyin</translation>
+<translation id="2055443983279698110">Barre de menus GNOME expérimentale disponible</translation>
+<translation id="2342959293776168129">Effacer l'historique des téléchargements</translation>
+<translation id="2503522102815150840">Navigateur bloqué...</translation>
+<translation id="7201354769043018523">Parenthèse drte</translation>
+<translation id="425878420164891689">Calcul du temps de chargement</translation>
+<translation id="508794495705880051">Ajouter une carte de paiement...</translation>
+<translation id="1425975335069981043">Itinérance :</translation>
+<translation id="1272079795634619415">Arrêter</translation>
+<translation id="5442787703230926158">Erreur de synchronisation...</translation>
+<translation id="2462724976360937186">ID de clé de l'autorité de certification</translation>
+<translation id="6786747875388722282">Extensions</translation>
+<translation id="3944384147860595744">Imprimez où que vous soyez.</translation>
+<translation id="2570648609346224037">Un problème est survenu lors du téléchargement de l'image de récupération.</translation>
+<translation id="4306718255138772973">Cloud Print Proxy</translation>
+<translation id="9053965862400494292">Une erreur s'est produite lors de la configuration de la synchronisation.</translation>
+<translation id="8596540852772265699">Fichiers personnalisés</translation>
+<translation id="7017354871202642555">Impossible de définir le mode une fois la fenêtre créée.</translation>
+<translation id="3101709781009526431">Date et heure</translation>
+<translation id="69375245706918574">Personnaliser les préférences de synchronisation</translation>
+<translation id="833853299050699606">Aucune information disponible sur le forfait</translation>
+<translation id="1737968601308870607">Signaler un problème</translation>
+<translation id="4571852245489094179">Importer mes favoris et paramètres</translation>
+<translation id="99648783926443049">Sélectionnez le <ph name="BEGIN_BOLD"/>menu clé à molette &gt; Paramètres &gt; Options avancées &gt; Modifier les paramètres du proxy<ph name="END_BOLD"/> et vérifiez que vos paramètres sont définis sur &quot;sans proxy&quot; ou &quot;direct&quot;.</translation>
+<translation id="4421917670248123270">Fermer et annuler les téléchargements</translation>
+<translation id="5605623530403479164">Autres moteurs de recherche</translation>
+<translation id="8887243200615092733"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe. Pour protéger vos données, vous devez confirmer les informations relatives à votre compte.</translation>
+<translation id="4740663705480958372">Cette fonctionnalité active les API P2P Pepper et P2P JavaScript. L'API est en cours de développement et n'est pas encore opérationnelle.</translation>
+<translation id="5710435578057952990">L'identité de ce site Web n'a pas été vérifiée.</translation>
+<translation id="1421046588786494306">Sessions à l'étranger</translation>
+<translation id="1661245713600520330">Cette page répertorie tous les modules chargés dans le processus principal et les modules enregistrés de manière à être chargés ultérieurement.</translation>
+<translation id="5451646087589576080">Afficher les &amp;infos sur le cadre</translation>
+<translation id="3368922792935385530">Connecté</translation>
+<translation id="3498309188699715599">Paramètres d'entrée en Chewing</translation>
+<translation id="8486154204771389705">Conserver sur cette page</translation>
+<translation id="3866443872548686097">Votre support de récupération est prêt. Vous pouvez le retirer du système.</translation>
+<translation id="6824564591481349393">Copi&amp;er l'adresse e-mail</translation>
+<translation id="907148966137935206">Interdire à tous les sites d'afficher des fenêtres pop-up (recommandé)</translation>
+<translation id="5184063094292164363">Console &amp;JavaScript</translation>
+<translation id="333371639341676808">Empêcher cette page de générer des boîtes de dialogue supplémentaires</translation>
+<translation id="7632380866023782514">En haut à droite</translation>
+<translation id="4925520021222027859">Entrez le mot de passe associé à votre application :</translation>
+<translation id="3494768541638400973">Mode de saisie Google du japonais (pour clavier japonais)</translation>
+<translation id="5844183150118566785"><ph name="PRODUCT_NAME"/> est à jour (<ph name="VERSION"/>)</translation>
+<translation id="3118046075435288765">Le serveur a mis fin à la connexion de manière inattendue.</translation>
+<translation id="8041140688818013446">Il est possible que le serveur hébergeant la page Web soit surchargé ou ait rencontré une erreur. Pour éviter de générer
+ trop de trafic et d'aggraver la situation,
+ <ph name="PRODUCT_NAME"/> a temporairement
+ bloqué l'acceptation des requêtes adressées au serveur.
+ <ph name="LINE_BREAK"/>
+ Si vous pensez que ce comportement n'est pas souhaitable, (par exemple, dans le cas où vous déboguez votre propre site Web), vous pouvez
+ consulter la page <ph name="NET_INTERNALS_PAGE"/>,
+ sur laquelle vous pourrez trouver plus d'informations ou désactiver cette fonctionnalité.</translation>
+<translation id="1725068750138367834">Gestionnaire de &amp;fichiers</translation>
+<translation id="4254921211241441775">Arrêter la synchronisation du compte</translation>
+<translation id="7791543448312431591">Ajouter</translation>
+<translation id="8569764466147087991">Sélectionnez le fichier à ouvrir</translation>
+<translation id="5449451542704866098">Aucun forfait de données</translation>
+<translation id="307505906468538196">Créer un compte Google</translation>
+<translation id="2053553514270667976">Code postal</translation>
+<translation id="48838266408104654">&amp;Gestionnaire de tâches</translation>
+<translation id="4378154925671717803">Téléphone</translation>
+<translation id="3694027410380121301">Sélectionner l'onglet précédent</translation>
+<translation id="6178664161104547336">Sélectionner un certificat</translation>
+<translation id="1375321115329958930">Mots de passe enregistrés</translation>
+<translation id="3341703758641437857">Autoriser l'accès aux URL de fichier</translation>
+<translation id="5702898740348134351">Modifi&amp;er les moteurs de recherche...</translation>
+<translation id="734303607351427494">Gérer les moteurs de recherche...</translation>
+<translation id="8326478304147373412">PKCS #7, chaîne de certificats</translation>
+<translation id="3242765319725186192">Clé pré-partagée :</translation>
+<translation id="8089798106823170468">Contrôlez et partagez l'accès à vos imprimantes depuis n'importe quel compte Google.</translation>
+<translation id="5984992849064510607">Ajoute l'option &quot;Utiliser les onglets latéraux&quot; au menu contextuel de la barre d'onglets. Utilisez cette option pour déplacer les onglets du haut de l'écran (affichage par défaut) vers le côté. Particulièrement utile sur les grands écrans.</translation>
+<translation id="839736845446313156">S'inscrire</translation>
+<translation id="4668929960204016307">,</translation>
+<translation id="2409527877874991071">Saisissez un nouveau nom.</translation>
+<translation id="4240069395079660403"><ph name="PRODUCT_NAME"/> ne peut pas être affiché dans cette langue.</translation>
+<translation id="747114903913869239">Erreur : impossible de décoder l'extension.</translation>
+<translation id="5412637665001827670">Clavier bulgare</translation>
+<translation id="2113921862428609753">Accès aux informations de l'autorité</translation>
+<translation id="5227536357203429560">Ajouter un réseau privé...</translation>
+<translation id="732677191631732447">C&amp;opier l'URL du fichier audio</translation>
+<translation id="7224023051066864079">Masque de sous-réseau :</translation>
+<translation id="2401813394437822086">Impossible d'accéder à votre compte ?</translation>
+<translation id="2344262275956902282">Utiliser les touches - et = pour paginer une liste d'entrées</translation>
+<translation id="3609138628363401169">Le serveur ne prend pas en charge l'extension de renégociation TLS.</translation>
+<translation id="3369624026883419694">Résolution de l'hôte...</translation>
+<translation id="8870413625673593573">Récemment fermés</translation>
+<translation id="9145357542626308749">Le certificat de sécurité du site a été signé avec un algorithme de signature faible.</translation>
+<translation id="8502803898357295528">Votre mot de passe a été modifié</translation>
+<translation id="4064488613268730704">Gérer les paramètres de saisie automatique...</translation>
+<translation id="6830600606572693159">La page Web <ph name="URL"/> n'est pas disponible pour le moment. Cela peut être dû à une surcharge ou à une opération de maintenance.</translation>
+<translation id="4145797339181155891">Éjecter</translation>
+<translation id="7886793013438592140">Impossible de lancer le processus de service.</translation>
+<translation id="8417944620073548444"><ph name="MEGABYTES"/> Mo restants</translation>
+<translation id="7339898014177206373">Nouvelle fenêtre</translation>
+<translation id="3026202950002788510">Sélectionnez
+ <ph name="BEGIN_BOLD"/>
+ Applications &gt; Préférences système &gt; Réseau &gt; Avancé &gt; Proxys
+ <ph name="END_BOLD"/>
+ et désélectionnez les serveurs proxy sélectionnés.</translation>
+<translation id="7033648024564583278">Gravure en cours d'initialisation...</translation>
+<translation id="2246340272688122454">Téléchargement de l'image de récupération...</translation>
+<translation id="7770995925463083016">il y a <ph name="NUMBER_TWO"/> minutes</translation>
+<translation id="2816269189405906839">Mode de saisie du chinois (cangjie)</translation>
+<translation id="7087282848513945231">Comté</translation>
+<translation id="2149951639139208969">Ouvrir l'adresse dans un nouvel onglet</translation>
+<translation id="175196451752279553">&amp;Rouvrir l'onglet fermé</translation>
+<translation id="5992618901488170220">Impossible d'afficher la page Web, car votre ordinateur est passé en mode
+ veille ou hibernation. Dans ce cas, les connexions réseau sont
+ coupées et les requêtes réseau échouent. L'actualisation de la page
+ devrait permettre de résoudre ce problème.</translation>
+<translation id="2655386581175833247">Certificat utilisateur :</translation>
+<translation id="5039804452771397117">Autoriser</translation>
+<translation id="5435964418642993308">Appuyer sur Entrée pour revenir en arrière et sur la touche de menu contextuel pour afficher l'historique</translation>
+<translation id="81686154743329117">ZRM</translation>
+<translation id="7564146504836211400">Cookies et autres données</translation>
+<translation id="2266011376676382776">Page(s) ne répondant pas</translation>
+<translation id="2714313179822741882">Paramètres d'entrée hangûl</translation>
+<translation id="8658163650946386262">Configurer la synchronisation...</translation>
+<translation id="3100609564180505575">Modules (<ph name="TOTAL_COUNT"/>). Conflits connus : <ph name="BAD_COUNT"/>, conflits probables : <ph name="SUSPICIOUS_COUNT"/></translation>
+<translation id="3627671146180677314">Date de renouvellement du certificat Netscape</translation>
+<translation id="1319824869167805246">Ouvrir tous les favoris dans une nouvelle fenêtre</translation>
+<translation id="8652487083013326477">bouton radio concernant l'étendue de pages</translation>
+<translation id="5204967432542742771">Saisissez votre mot de passe</translation>
+<translation id="4388712255200933062"><ph name="CLOUD_PRINT_NAME"/> est conçu pour rendre l'impression plus intuitive, accessible et utile. <ph name="CLOUD_PRINT_NAME"/> vous permet de rendre vos imprimantes accessibles depuis n'importe quelle application Web ou mobile associée à <ph name="CLOUD_PRINT_NAME"/>.</translation>
+<translation id="2932611376188126394">Dictionnaire de kanji unique</translation>
+<translation id="5485754497697573575">Rétablir tous les onglets</translation>
+<translation id="3371861036502301517">Échec de l'installation de l'extension</translation>
+<translation id="644038709730536388">En savoir plus sur la manière de se protéger des logiciels malveillants en ligne</translation>
+<translation id="2155931291251286316">Toujours afficher les fenêtres pop-up de <ph name="HOST"/></translation>
+<translation id="3445830502289589282">Authentification phase 2 :</translation>
+<translation id="5650551054760837876">Aucun résultat de recherche trouvé</translation>
+<translation id="5494362494988149300">Ouvrir une fois le téléchargement &amp;terminé</translation>
+<translation id="2956763290572484660"><ph name="COOKIES"/> cookies</translation>
+<translation id="6989836856146457314">Mode de saisie du japonais (pour clavier américain)</translation>
+<translation id="9187787570099877815">Continuer à bloquer les plug-ins</translation>
+<translation id="8425492902634685834">Épingler sur la barre des tâches</translation>
+<translation id="825608351287166772">Les certificats ont une période de validité, comme tous les documents relatifs à votre identité (tel qu'un passeport). Le certificat présenté à votre navigateur n'est pas encore valide ! Lorsqu'un certificat est en dehors de sa période de validité, il n'est pas nécessaire d'assurer la maintenance de certaines informations relatives à son état (s'il a été révoqué ou s'il n'est plus approuvé). Par conséquent, il est impossible de vérifier que le certificat est fiable. Ne poursuivez pas.</translation>
+<translation id="741630086309232721">Fermer la session d'invité</translation>
+<translation id="7309459761865060639">Contrôlez vos tâches d'impression et l'état de connexion de vos imprimantes en ligne.</translation>
+<translation id="4803909571878637176">Désinstallation</translation>
+<translation id="5209518306177824490">Empreinte SHA-1</translation>
+<translation id="3300768886937313568">Modifier le code PIN de la carte SIM</translation>
+<translation id="7447657194129453603">État du réseau :</translation>
+<translation id="1553538517812678578">sans limite</translation>
+<translation id="7947315300197525319">(Choisir une autre capture d'écran)</translation>
+<translation id="3612070600336666959">Désactivation</translation>
+<translation id="3759461132968374835">Aucune erreur n'a été signalée récemment. Les erreurs n'apparaissent ici que lorsque l'envoi de rapports d'erreur est activé.</translation>
+<translation id="1516602185768225813">Rouvrir les dernières pages ouvertes</translation>
+<translation id="189210018541388520">Ouvrir en mode plein écran</translation>
+<translation id="8795668016723474529">Ajouter une carte de paiement</translation>
+<translation id="5860033963881614850">Désactivé</translation>
+<translation id="3956882961292411849">Chargement des informations sur votre forfait Internet mobile, veuillez patienter...</translation>
+<translation id="689050928053557380">Acheter un forfait de données...</translation>
+<translation id="4235618124995926194">Inclure cet e-mail :</translation>
+<translation id="4874539263382920044">Le titre doit comporter au moins un caractère.</translation>
+<translation id="798525203920325731">Espaces de noms réseau</translation>
+<translation id="263325223718984101"><ph name="PRODUCT_NAME"/> n'a pas pu terminer l'installation, mais va poursuivre son exécution à partir de son image disque.</translation>
+<translation id="7025190659207909717">Gestion des services Internet mobiles</translation>
+<translation id="8265096285667890932">Utiliser les onglets latéraux</translation>
+<translation id="4250680216510889253">Non</translation>
+<translation id="3949593566929137881">Saisir le code PIN de la carte SIM</translation>
+<translation id="6291953229176937411">&amp;Afficher dans le Finder</translation>
+<translation id="2476990193835943955">Maintenez la touche Ctrl, Alt ou Maj enfoncée&lt;br&gt;pour afficher le raccourci clavier qui lui est associé.</translation>
+<translation id="9187827965378254003">Vraiment désolé, aucun prototype n'est disponible pour le moment.</translation>
+<translation id="8933960630081805351">&amp;Afficher dans le Finder</translation>
+<translation id="3041612393474885105">Informations relatives au certificat</translation>
+<translation id="7378810950367401542">/</translation>
+<translation id="4611079913162790275">La synchronisation des mots de passe requiert votre attention.</translation>
+<translation id="6562758426028728553">Veuillez saisir l'ancien et le nouveau code PIN.</translation>
+<translation id="614161640521680948">Langue :</translation>
+<translation id="3665650519256633768">Résultats de recherche</translation>
+<translation id="3733127536501031542">Serveur SSL avec fonction d'optimisation</translation>
+<translation id="3614837889828516995">Enregistrer en PDF</translation>
+<translation id="5745056705311424885">Mémoire USB détectée</translation>
+<translation id="5895875028328858187">M'avertir lorsque le flux de données est faible ou presque inexistant</translation>
+<translation id="939598580284253335">Saisir le mot de passe multiterme</translation>
+<translation id="7917972308273378936">Clavier lituanien</translation>
+<translation id="8371806639176876412">Les éléments saisis dans le champ polyvalent peuvent être enregistrés.</translation>
+<translation id="4216499942524365685">Les informations de connexion à votre compte sont obsolètes. Cliquez ici pour saisir à nouveau votre mot de passe.</translation>
+<translation id="8899388739470541164">Vietnamien</translation>
+<translation id="4091434297613116013">feuilles de papier</translation>
+<translation id="7475671414023905704">URL de mot de passe perdu Netscape</translation>
+<translation id="3335947283844343239">Rouvrir l'onglet fermé</translation>
+<translation id="4089663545127310568">Effacer les mots de passe enregistrés</translation>
+<translation id="6500444002471948304">Créer un nouveau dossier...</translation>
+<translation id="2480626392695177423">Basculer en mode ponctuation pleine chasse ou demi-chasse</translation>
+<translation id="5830410401012830739">Gérer les paramètres de localisation...</translation>
+<translation id="8977410484919641907">Synchronisé...</translation>
+<translation id="2794293857160098038">Options de recherche par défaut</translation>
+<translation id="3947376313153737208">Aucune sélection</translation>
+<translation id="1346104802985271895">Mode de saisie du vietnamien (TELEX)</translation>
+<translation id="5935630983280450497"><ph name="NUMBER_ONE"/> minute restante</translation>
+<translation id="5889282057229379085">Le nombre maximal d'autorités de certification intermédiaires a été dépassé : <ph name="NUM_INTERMEDIATE_CA"/></translation>
+<translation id="3180365125572747493">Saisissez un mot de passe pour chiffrer ce fichier de certificat.</translation>
+<translation id="5496587651328244253">Organiser</translation>
+<translation id="4821086771593057290">Votre mot de passe a changé. Veuillez réessayer avec votre nouveau mot de passe.</translation>
+<translation id="7075513071073410194">PKCS #1 MD5 avec chiffrement RSA</translation>
+<translation id="4378727699507047138">Utiliser le thème classique</translation>
+<translation id="7124398136655728606">Échap efface toute la mémoire tampon de pré-édition</translation>
+<translation id="8293206222192510085">Ajouter aux favoris</translation>
+<translation id="2592884116796016067">Un incident est survenu sur une partie de cette page (HTML WebWorker). Elle risque de ne pas fonctionner correctement.</translation>
+<translation id="2529133382850673012">Clavier américain</translation>
+<translation id="4411578466613447185">Signataire de code</translation>
+<translation id="1354868058853714482">Adobe Reader n'est pas à jour et risque de ne plus être sécurisé.</translation>
+<translation id="6252594924928912846">Personnaliser les paramètres de synchronisation...</translation>
+<translation id="8425755597197517046">Co&amp;ller et rechercher</translation>
+<translation id="1093148655619282731">Détails du certificat sélectionné :</translation>
+<translation id="5568069709869097550">Impossible de se connecter</translation>
+<translation id="2743322561779022895">Activation :</translation>
+<translation id="4181898366589410653">Système de révocation introuvable dans le certificat du serveur</translation>
+<translation id="8705331520020532516">Numéro de série</translation>
+<translation id="1665770420914915777">Afficher la page &quot;Nouvel onglet&quot;</translation>
+<translation id="2629089419211541119">il y a <ph name="NUMBER_ONE"/> heure</translation>
+<translation id="1691063574428301566">Votre ordinateur redémarrera une fois la mise à jour effectuée.</translation>
+<translation id="131364520783682672">Verr. maj.</translation>
+<translation id="6259308910735500867">L'accès au répertoire de l'hôte de communication à distance a été refusé. Essayez avec un autre compte.</translation>
+<translation id="3415261598051655619">Accessible aux scripts :</translation>
+<translation id="2335122562899522968">Cette page place des cookies.</translation>
+<translation id="3786100282288846904">Impossible de supprimer &quot;$1&quot; : $2</translation>
+<translation id="8461914792118322307">Proxy</translation>
+<translation id="4089521618207933045">Avec sous-menu</translation>
+<translation id="1936157145127842922">Afficher dans le dossier</translation>
+<translation id="6982279413068714821">il y a <ph name="NUMBER_DEFAULT"/> minutes</translation>
+<translation id="7977590112176369853">&lt;saisir une requête&gt;</translation>
+<translation id="3449839693241009168">Appuyez sur <ph name="SEARCH_KEY"/> pour envoyer des commandes à <ph name="EXTENSION_NAME"/>.</translation>
+<translation id="7443484992065838938">Prévisualiser le rapport</translation>
+<translation id="5714678912774000384">Activer le dernier onglet</translation>
+<translation id="3799598397265899467">Lorsque je quitte le navigateur</translation>
+<translation id="2125314715136825419">Continuer sans mettre à jour Adobe Reader (non recommandé)</translation>
+<translation id="1120026268649657149">Le champ de mot clé doit être vide ou comporter un mot unique</translation>
+<translation id="542318722822983047">Déplacer le curseur automatiquement au caractère suivant</translation>
+<translation id="5317780077021120954">Enregistrer</translation>
+<translation id="9027459031423301635">Ouvrir le lien dans un nouvel ongle&amp;t</translation>
+<translation id="2251809247798634662">Nouvelle fenêtre de navigation privée</translation>
+<translation id="358344266898797651">Celtique</translation>
+<translation id="3625870480639975468">Réinitialiser le zoom</translation>
+<translation id="5199729219167945352">Prototypes</translation>
+<translation id="5055518462594137986">Mémoriser mes choix pour tous les liens de ce type</translation>
+<translation id="246059062092993255">Les plug-ins de cette page ont été bloqués.</translation>
+<translation id="2870560284913253234">Site</translation>
+<translation id="6945221475159498467">Sélectionner</translation>
+<translation id="7724603315864178912">Couper</translation>
+<translation id="4164507027399414915">Restaurer toutes les miniatures supprimées</translation>
+<translation id="917051065831856788">Utiliser les onglets latéraux</translation>
+<translation id="1976150099241323601">Se connecter au dispositif de sécurité</translation>
+<translation id="6620110761915583480">Enregistrer le fichier</translation>
+<translation id="4988526792673242964">Pages</translation>
+<translation id="7543025879977230179">Options de <ph name="PRODUCT_NAME"/></translation>
+<translation id="2175607476662778685">Barre de lancement rapide</translation>
+<translation id="6434309073475700221">Annuler</translation>
+<translation id="1367951781824006909">Choisir un fichier</translation>
+<translation id="1425127764082410430">&amp;Rechercher <ph name="SEARCH_TERMS"/> avec <ph name="SEARCH_ENGINE"/></translation>
+<translation id="684265517037058883">(pas encore valide)</translation>
+<translation id="2027538664690697700">Mettre à jour le plug-in...</translation>
+<translation id="8205333955675906842">Police Sans-Serif</translation>
+<translation id="39964277676607559">Impossible de charger le JavaScript &quot;<ph name="RELATIVE_PATH"/>&quot; du script de contenu.</translation>
+<translation id="4378551569595875038">Connexion...</translation>
+<translation id="7029809446516969842">Mots de passe</translation>
+<translation id="8053278772142718589">Fichiers PKCS #12</translation>
+<translation id="3129020372442395066">Options de saisie automatique de <ph name="PRODUCT_NAME_SHORT"/></translation>
+<translation id="4114360727879906392">Fenêtre précédente</translation>
+<translation id="8238649969398088015">Astuce</translation>
+<translation id="5958418293370246440"><ph name="SAVED_FILES"/> / <ph name="TOTAL_FILES"/> fichiers</translation>
+<translation id="2350172092385603347">Localisation utilisée, mais les paramètres régionaux par défaut (default_locale) n'ont pas été indiqués dans le manifeste. </translation>
+<translation id="8221729492052686226">Si vous n'êtes pas à l'origine de cette requête, il s'agit probablement d'une attaque contre votre système. Si vous n'avez pas lancé cette requête de manière intentionnelle, cliquez sur Ne rien faire.</translation>
+<translation id="5894314466642127212">Votre commentaire a bien été envoyé.</translation>
+<translation id="894360074127026135">Fonction d'optimisation internationale Netscape </translation>
+<translation id="6025294537656405544">Taille de police minimale</translation>
+<translation id="1201402288615127009">Suivant</translation>
+<translation id="1335588927966684346">Utilitaire :</translation>
+<translation id="7857823885309308051">Cette opération peut prendre une minute...</translation>
+<translation id="662870454757950142">Le format du mot de passe est incorrect.</translation>
+<translation id="370665806235115550">Chargement...</translation>
+<translation id="1808792122276977615">Ajouter la page...</translation>
+<translation id="2076269580855484719">Masquer ce plug-in</translation>
+<translation id="254416073296957292">&amp;Paramètres linguistiques...</translation>
+<translation id="6652975592920847366">Créer un support de récupération du système d'exploitation</translation>
+<translation id="52912272896845572">Le fichier de clé privée est incorrect.</translation>
+<translation id="3232318083971127729">Valeur :</translation>
+<translation id="8807632654848257479">Stable</translation>
+<translation id="4209092469652827314">Grande</translation>
+<translation id="4222982218026733335">Certificat serveur invalide</translation>
+<translation id="152234381334907219">Jamais enregistrés</translation>
+<translation id="5600599436595580114">Cette page a été préchargée.</translation>
+<translation id="8926468725336609312">Google Chrome ne peut pas afficher l'aperçu avant impression lorsque la visionneuse de documents PDF intégrée est désactivée. Pour l'afficher, veuillez accéder à <ph name="BEGIN_LINK"/>chrome://plugins<ph name="END_LINK"/>, activer &quot;Chrome PDF Viewer&quot; et réessayer.</translation>
+<translation id="8494214181322051417">Nouveau !</translation>
+<translation id="7762841930144642410"><ph name="BEGIN_BOLD"/>Vous êtes passé en navigation privée<ph name="END_BOLD"/>. Les pages que vous consultez dans cette fenêtre n'apparaîtront ni dans l'historique de votre navigateur, ni dans l'historique des recherches, et ne laisseront aucune trace (comme les cookies) sur votre ordinateur une fois que vous aurez fermé la fenêtre de navigation privée. Tous les fichiers téléchargés et les favoris créés seront toutefois conservés. <ph name="LINE_BREAK"/> <ph name="BEGIN_BOLD"/>Passer en navigation privée n'a aucun effet sur les autres utilisateurs, serveurs ou logiciels. Méfiez-vous :<ph name="END_BOLD"/> <ph name="BEGIN_LIST"/> <ph name="BEGIN_LIST_ITEM"/>Des sites Web qui collectent ou partagent des informations vous concernant<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des fournisseurs d'accès Internet ou des employeurs qui conservent une trace des pages que vous visitez<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des programmes indésirables qui enregistrent vos frappes en échange d'émoticônes gratuites<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des personnes qui pourraient surveiller vos activités<ph name="END_LIST_ITEM"/> <ph name="BEGIN_LIST_ITEM"/>Des personnes qui se tiennent derrière vous<ph name="END_LIST_ITEM"/> <ph name="END_LIST"/> <ph name="BEGIN_LINK"/>En savoir plus sur la navigation privée<ph name="END_LINK"/></translation>
+<translation id="2386255080630008482">Le certificat du serveur a été révoqué.</translation>
+<translation id="2135787500304447609">&amp;Reprendre</translation>
+<translation id="8309505303672555187">Sélectionnez un réseau :</translation>
+<translation id="6143635259298204954">Impossible d'extraire les fichiers de l'extension. Pour effectuer cette opération en toute sécurité, vous devez disposer d'un chemin d'accès à votre répertoire de profils ne contenant pas de lien symbolique. Aucun chemin de ce type n'existe pour votre profil.</translation>
+<translation id="1813414402673211292">Effacer les données de navigation</translation>
+<translation id="4062903950301992112">Si vous êtes conscient que la visite de ce site peut être préjudiciable à votre ordinateur, vous pouvez <ph name="PROCEED_LINK"/>.</translation>
+<translation id="32330993344203779">Votre périphérique est inscrit pour bénéficier de la gestion d'entreprise.</translation>
+<translation id="2356762928523809690">Serveur de mise à jour non disponible (erreur : <ph name="ERROR_NUMBER"/>)</translation>
+<translation id="219008588003277019">Module client natif : <ph name="NEXE_NAME"/></translation>
+<translation id="5436510242972373446">Rechercher sur <ph name="SITE_NAME"/> :</translation>
+<translation id="3800764353337460026">Style de symboles</translation>
+<translation id="6719684875142564568"><ph name="NUMBER_ZERO"/> hours</translation>
+<translation id="2096368010154057602">Département</translation>
+<translation id="1036561994998035917">Continuer à utiliser <ph name="ENGINE_NAME"/></translation>
+<translation id="8730621377337864115">OK</translation>
+<translation id="665757950158579497">Essayez de désactiver les prédictions d'actions du réseau en procédant comme suit :
+ Sélectionnez le
+ <ph name="BEGIN_BOLD"/>
+ menu clé à molette &gt;
+ <ph name="SETTINGS_TITLE"/>
+ &gt;
+ <ph name="ADVANCED_TITLE"/>
+ <ph name="END_BOLD"/>
+ et désélectionnez &quot;<ph name="NO_PREFETCH_DESCRIPTION"/>&quot;.
+ Si le problème n'est pas résolu, nous vous conseillons de sélectionner de nouveau
+ cette option pour améliorer les performances.</translation>
+<translation id="4932733599132424254">Date</translation>
+<translation id="6267166720438879315">Sélectionnez un certificat pour vous authentifier sur <ph name="HOST_NAME"/>.</translation>
+<translation id="2422927186524098759">Barre latérale</translation>
+<translation id="7839809549045544450">La clé publique éphémère Diffie-Hellman associée au serveur est peu sûre.</translation>
+<translation id="5515806255487262353">Rechercher dans Dictionnaire</translation>
+<translation id="350048665517711141">Sélectionnez un moteur de recherche</translation>
+<translation id="2790805296069989825">Clavier russe</translation>
+<translation id="5708171344853220004">Nom Microsoft principal</translation>
+<translation id="5464696796438641524">Clavier polonais</translation>
+<translation id="2080010875307505892">Clavier serbe</translation>
+<translation id="2953767478223974804"><ph name="NUMBER_ONE"/> minute</translation>
+<translation id="201192063813189384">Erreur lors de la lecture des données du cache.</translation>
+<translation id="7851768487828137624">Canary</translation>
+<translation id="6129938384427316298">Commentaire du certificat Netscape</translation>
+<translation id="8210608804940886430">Page suivante</translation>
+<translation id="9065596142905430007"><ph name="PRODUCT_NAME"/> est à jour.</translation>
+<translation id="1035650339541835006">Paramètres de saisie automatique...</translation>
+<translation id="6315493146179903667">Tout ramener au premier plan</translation>
+<translation id="1000498691615767391">Sélectionner le dossier à ouvrir</translation>
+<translation id="3593152357631900254">Activer le mode Pinyin fuzzy</translation>
+<translation id="5015344424288992913">Résolution du proxy...</translation>
+<translation id="8506299468868975633">Le téléchargement de l'image a été interrompu.</translation>
+<translation id="4724168406730866204">Eten 26</translation>
+<translation id="308268297242056490">URI</translation>
+<translation id="4479812471636796472">Clavier Dvorak américain</translation>
+<translation id="8673026256276578048">Rechercher sur le Web...</translation>
+<translation id="1437307674059038925">Si vous utilisez un serveur proxy, vérifiez les paramètres associés ou demandez à votre administrateur réseau
+ si ce serveur fonctionne.</translation>
+<translation id="149347756975725155">Impossible de charger l'icône de l'extension &quot;<ph name="ICON"/>&quot;.</translation>
+<translation id="3675321783533846350">Définir un proxy pour se connecter au réseau</translation>
+<translation id="5451285724299252438">zone de texte concernant l'étendue de pages</translation>
+<translation id="5669267381087807207">Activation</translation>
+<translation id="7434823369735508263">Clavier Dvorak britannique</translation>
+<translation id="1572103024875503863"><ph name="NUMBER_MANY"/> jours</translation>
+<translation id="2084978867795361905">MS-IME</translation>
+<translation id="7227669995306390694">Aucun forfait de données <ph name="NETWORK"/></translation>
+<translation id="3481915276125965083">Les fenêtres pop-up suivantes ont été bloquées sur cette page :</translation>
+<translation id="7163503212501929773"><ph name="NUMBER_MANY"/> heures restantes</translation>
+<translation id="7705276765467986571">Impossible de charger le modèle du favori.</translation>
+<translation id="1196338895211115272">Échec d'exportation de la clé privée</translation>
+<translation id="5586329397967040209">Utiliser comme page d'accueil</translation>
+<translation id="629730747756840877">Compte</translation>
+<translation id="8525306231823319788">Plein écran</translation>
+<translation id="9054208318010838">Autoriser tous les sites à suivre ma position géographique</translation>
+<translation id="3058212636943679650">Si la restauration du système d'exploitation de votre ordinateur s'avère nécessaire, une carte SD ou une clé USB de récupération vous sera demandée.</translation>
+<translation id="2815382244540487333">Les cookies suivants ont été bloqués :</translation>
+<translation id="8882395288517865445">Inclure les adresses de ma fiche de Carnet d’adresses</translation>
+<translation id="374530189620960299">Le certificat de sécurité du site n'est pas approuvé !</translation>
+<translation id="8852407435047342287">Votre liste d'applications, d'extensions et de thèmes installés</translation>
+<translation id="5647283451836752568">Exécuter tous les plug-ins de cette page</translation>
+<translation id="8642947597466641025">Augmente la taille du texte</translation>
+<translation id="5188181431048702787">Accepter et continuer »</translation>
+<translation id="1293556467332435079">Fichiers
+</translation>
+<translation id="2490270303663597841">Appliquer uniquement à cette session de navigation privée</translation>
+<translation id="1757915090001272240">Latin large</translation>
+<translation id="8496717697661868878">Exécuter ce plug-in</translation>
+<translation id="3450660100078934250">MasterCard</translation>
+<translation id="2916073183900451334">Sur le Web, Tab permet de sélectionner les liens, ainsi que les champs de formulaire.</translation>
+<translation id="7772127298218883077">À propos de <ph name="PRODUCT_NAME"/></translation>
+<translation id="2090876986345970080">Paramètres de sécurité du système</translation>
+<translation id="9219103736887031265">Images</translation>
+<translation id="5453632173748266363">Cyrillique</translation>
+<translation id="1008557486741366299">Pas maintenant</translation>
+<translation id="8415351664471761088">Attendre la fin du téléchargement</translation>
+<translation id="1545775234664667895">Thème &quot;<ph name="THEME_NAME"/>&quot; installé</translation>
+<translation id="5329858601952122676">&amp;Supprimer</translation>
+<translation id="6100736666660498114">Menu Démarrer</translation>
+<translation id="3994878504415702912">&amp;Zoom</translation>
+<translation id="9009369504041480176">Transfert en cours (<ph name="PROGRESS_PERCENT"/> %)...</translation>
+<translation id="8995603266996330174">Géré par <ph name="DOMAIN"/></translation>
+<translation id="5602600725402519729">&amp;Rafraîchir</translation>
+<translation id="172612876728038702">Configuration du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, cela peut prendre quelques minutes.</translation>
+<translation id="1362165759943288856">Vous avez acheté une quantité illimitée de données le <ph name="DATE"/>.</translation>
+<translation id="2078019350989722914">Confirmer avant de quitter (<ph name="KEY_EQUIVALENT"/>)</translation>
+<translation id="7965010376480416255">Mémoire partagée</translation>
+<translation id="6248988683584659830">Rech. dans les paramètres</translation>
+<translation id="8323232699731382745">mot de passe d'accès au réseau</translation>
+<translation id="6588399906604251380">Activer la vérification orthographique</translation>
+<translation id="7167621057293532233">Types de données</translation>
+<translation id="7053983685419859001">Bloquer</translation>
+<translation id="2485056306054380289">Certificat de l'autorité de certification du serveur :</translation>
+<translation id="6462109140674788769">Clavier grec</translation>
+<translation id="2727712005121231835">Taille réelle</translation>
+<translation id="8887733174653581061">Toujours en haut</translation>
+<translation id="5581211282705227543">Aucun plug-in installé.</translation>
+<translation id="610886263749567451">Alerte JavaScript</translation>
+<translation id="5488468185303821006">Autoriser en mode navigation privée</translation>
+<translation id="6556866813142980365">Rétablir</translation>
+<translation id="2107287771748948380"><ph name="OBFUSCATED_CC_NUMBER"/>, expire le : <ph name="CC_EXPIRATION_DATE"/></translation>
+<translation id="6584811624537923135">Confirmer la désinstallation</translation>
+<translation id="7429235532957570505">Impossible de désactiver les plug-ins ayant été activés par une stratégie d'entreprise.</translation>
+<translation id="7866522434127619318">Cette fonctionnalité active l'option &quot;Lire en un clic&quot; dans les paramètres de contenu du plug-in.</translation>
+<translation id="8860923508273563464">Attendre la fin des téléchargements</translation>
+<translation id="6406506848690869874">Synchronisation</translation>
+<translation id="5288678174502918605">&amp;Rouvrir l'onglet fermé</translation>
+<translation id="7238461040709361198">Votre mot de passe de compte Google a changé depuis votre dernière connexion à partir de cet ordinateur.</translation>
+<translation id="1956050014111002555">Le fichier contenait plusieurs certificats, aucun d'eux n'a été importé :</translation>
+<translation id="302620147503052030">Afficher le bouton</translation>
+<translation id="5512074755152723588">La saisie dans le champ polyvalent d'une URL déjà ouverte dans un autre onglet entraîne l'affichage de l'onglet en question, et non l'affichage de l'URL dans l'onglet actuel.</translation>
+<translation id="9157595877708044936">Configuration en cours...</translation>
+<translation id="4475552974751346499">Rechercher dans les téléchargements</translation>
+<translation id="3021256392995617989">Me demander lorsqu'un site tente de suivre ma position géographique (recommandé)</translation>
+<translation id="5185386675596372454">La nouvelle version de &quot;<ph name="EXTENSION_NAME"/>&quot; a été désactivée, car elle nécessite davantage d'autorisations.</translation>
+<translation id="4285669636069255873">Clavier phonétique russe</translation>
+<translation id="4148925816941278100">American Express</translation>
+<translation id="2320435940785160168">Ce serveur exige un certificat d'authentification et n'a pas accepté celui envoyé par le navigateur.
+Votre certificat a peut-être expiré ou le serveur n'a pas approuvé l'émetteur.
+Réessayez avec un autre certificat si vous en avez un.
+Sinon, vous devrez en obtenir un nouveau d'un autre émetteur.</translation>
+<translation id="6295228342562451544">Lorsque vous vous connectez à un site Web sécurisé, le serveur hébergeant ce site présente à votre navigateur un &quot;certificat&quot; afin de vérifier l'identité du site. Ce certificat contient des informations d'identité, telles que l'adresse du site Web, laquelle est vérifiée par un tiers approuvé par votre ordinateur. En vérifiant que l'adresse du certificat correspond à l'adresse du site Web, il est possible de s'assurer que vous êtes connecté de façon sécurisée avec le site Web souhaité et non pas avec un tiers (tel qu'un pirate informatique sur votre réseau).</translation>
+<translation id="6342069812937806050">À l'instant</translation>
+<translation id="5605716740717446121">Votre carte SIM sera définitivement désactivée si vous ne saisissez pas correctement la clé de déverrouillage du code PIN. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
+<translation id="8836712291807476944"><ph name="SAVED_BYTES"/> / <ph name="TOTAL_BYTES"/> octets, Interrompu</translation>
+<translation id="5502500733115278303">Importés depuis Firefox</translation>
+<translation id="569109051430110155">Détection automatique</translation>
+<translation id="4408599188496843485">&amp;Aide</translation>
+<translation id="5399158067281117682">Les codes PIN sont différents !</translation>
+<translation id="8494234776635784157">Contenu Web</translation>
+<translation id="2681441671465314329">Vider le cache</translation>
+<translation id="3646789916214779970">Rétablir le thème par défaut</translation>
+<translation id="1592960452683145077">Le service de communication à distance a démarré correctement. Vous devriez maintenant pouvoir vous connecter à distance à cet ordinateur.</translation>
+<translation id="1679068421605151609">Outils de développement</translation>
+<translation id="6648524591329069940">Police Serif</translation>
+<translation id="6896758677409633944">Copier</translation>
+<translation id="5260508466980570042">Adresse e-mail ou mot de passe incorrect. Veuillez réessayer.</translation>
+<translation id="7887998671651498201">Le plug-in suivant ne répond pas : souhaitez-vous interrompre <ph name="PLUGIN_NAME"/> ?</translation>
+<translation id="173188813625889224">Sens</translation>
+<translation id="8088823334188264070"><ph name="NUMBER_MANY"/> secondes</translation>
+<translation id="1337036551624197047">Clavier tchèque</translation>
+<translation id="4212108296677106246">Voulez-vous que &quot;<ph name="CERTIFICATE_NAME"/>&quot; soit considérée comme une autorité de certification fiable ?</translation>
+<translation id="2861941300086904918">Gestionnaire de sécurité natif du client</translation>
+<translation id="6991443949605114807">&lt;p&gt;Lorsque vous exécutez <ph name="PRODUCT_NAME"/> dans un environnement de bureau pris en charge, les paramètres proxy du système sont utilisés. Toutefois, soit votre système n'est pas pris en charge, soit un problème est survenu lors du lancement de votre configuration système.&lt;/p&gt;
+
+ &lt;p&gt;Vous avez toujours la possibilité d'effectuer la configuration via la ligne de commande. Pour plus d'informations sur les indicateurs et les variables d'environnement, veuillez vous reporter à &lt;code&gt;man <ph name="PRODUCT_BINARY_NAME"/>&lt;/code&gt;.&lt;/p&gt;</translation>
+<translation id="9071590393348537582">La page Web à l'adresse <ph name="URL"/> a déclenché trop de redirections. Pour résoudre le problème, effacez les cookies de ce site ou autorisez les cookies tiers. Si le problème persiste, il peut être dû à une mauvaise configuration du serveur et n'être aucunement lié à votre ordinateur.</translation>
+<translation id="7205869271332034173">SSID :</translation>
+<translation id="7084579131203911145">Nom du forfait :</translation>
+<translation id="5815645614496570556">Adresse X.400</translation>
+<translation id="3551320343578183772">Fermer l'onglet</translation>
+<translation id="3345886924813989455">Impossible de trouver un navigateur pris en charge.</translation>
+<translation id="74354239584446316">Le compte associé à la boutique en ligne est le suivant : <ph name="EMAIL_ADDRESS"/>. L'utilisation d'un autre compte pour la synchronisation provoque des erreurs.</translation>
+<translation id="3712897371525859903">Enregistrer la p&amp;age sous...</translation>
+<translation id="7926251226597967072"><ph name="PRODUCT_NAME"/> importe actuellement les éléments suivants à partir de <ph name="IMPORT_BROWSER_NAME"/> :</translation>
+<translation id="2767649238005085901">Appuyez sur Entrée pour avancer et sur la touche de menu contextuel pour afficher l'historique</translation>
+<translation id="8580634710208701824">Actualiser le cadre</translation>
+<translation id="1018656279737460067">Annulé</translation>
+<translation id="7606992457248886637">Autorités</translation>
+<translation id="707392107419594760">Sélectionnez votre clavier :</translation>
+<translation id="2007404777272201486">Signaler un problème...</translation>
+<translation id="2390045462562521613">Ignorer ce réseau</translation>
+<translation id="3348038390189153836">Nouveau matériel détecté</translation>
+<translation id="1666788816626221136">Vous disposez de certificats qui n'appartiennent à aucune autre catégorie :</translation>
+<translation id="4821935166599369261">&amp;Profilage activé</translation>
+<translation id="1603914832182249871">(Navigation privée)</translation>
+<translation id="7910768399700579500">&amp;Nouveau dossier</translation>
+<translation id="7472639616520044048">Types MIME :</translation>
+<translation id="2307164895203900614">Afficher les pages en arrière-plan (<ph name="NUM_BACKGROUND_APPS"/>)</translation>
+<translation id="3192947282887913208">Fichiers audio</translation>
+<translation id="6295535972717341389">Plug-ins</translation>
+<translation id="8116190140324504026">Plus d'informations...</translation>
+<translation id="7469894403370665791">Se connecter automatiquement à ce réseau</translation>
+<translation id="4807098396393229769">Titulaire de la carte</translation>
+<translation id="4094130554533891764">Elle peut désormais accéder à :</translation>
+<translation id="4131410914670010031">Noir et blanc</translation>
+<translation id="3800503346337426623">Ignorer la connexion et naviguer en tant qu'invité</translation>
+<translation id="2615413226240911668">Toutefois, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer l'aspect et le comportement de cette page.</translation>
+<translation id="5880867612172997051">Accès réseau interrompu</translation>
+<translation id="7842346819602959665">La dernière version de l'extension &quot;<ph name="EXTENSION_NAME"/>&quot; requiert d'autres permissions. Elle a donc été désactivée.</translation>
+<translation id="3776667127601582921">Dans ce cas, le certificat du serveur ou un certificat d'autorité intermédiaire présenté à votre navigateur n'est pas valide. Cela peut signifier que le certificat est incorrect, qu'il contient des champs non valides ou qu'il n'est pas compatible.</translation>
+<translation id="2412835451908901523">Veuillez saisir la clé de déverrouillage du code PIN à 8 chiffres fournie par <ph name="CARRIER_ID"/>.</translation>
+<translation id="6979448128170032817">Exceptions...</translation>
+<translation id="7584802760054545466">Connexion à <ph name="NETWORK_ID"/></translation>
+<translation id="208047771235602537">Voulez-vous vraiment quitter <ph name="PRODUCT_NAME"/> alors qu'un téléchargement est en cours ?</translation>
+<translation id="4060383410180771901">Le site Web ne parvient pas à gérer la demande associée à <ph name="URL"/>.</translation>
+<translation id="6710213216561001401">Précédent</translation>
+<translation id="1108600514891325577">&amp;Arrêter</translation>
+<translation id="6035087343161522833">Lorsque l'option permettant de bloquer l'enregistrement des cookies tiers est activée, la lecture de ces cookies est également bloquée.</translation>
+<translation id="8619892228487928601"><ph name="CERTIFICATE_NAME"/> : <ph name="ERROR"/></translation>
+<translation id="1567993339577891801">Console JavaScript</translation>
+<translation id="1548132948283577726">Les sites pour lesquels vos mots de passe ne seront jamais enregistrés s'afficheront ici.</translation>
+<translation id="583281660410589416">Inconnu</translation>
+<translation id="3774278775728862009">Mode de saisie du thaï (clavier TIS-820.2538)</translation>
+<translation id="9115675100829699941">&amp;Favoris</translation>
+<translation id="2485422356828889247">Désinstaller</translation>
+<translation id="2621889926470140926">Voulez-vous vraiment quitter <ph name="PRODUCT_NAME"/> alors que <ph name="DOWNLOAD_COUNT"/> téléchargements sont en cours ?</translation>
+<translation id="7279701417129455881">Configurer le blocage des cookies...</translation>
+<translation id="1166359541137214543">ABC</translation>
+<translation id="5412713837047574330">L'application hébergée par <ph name="HOST_NAME"/> est inaccessible, car vous êtes déconnecté du réseau. Cette page s'affichera dès que la connexion réseau sera rétablie. &lt;br&gt;</translation>
+<translation id="5528368756083817449">Gestionnaire de favoris</translation>
+<translation id="7275974018215686543"><ph name="NUMBER_MANY"/> secs ago</translation>
+<translation id="215753907730220065">Quitter le mode plein écran</translation>
+<translation id="7849264908733290972">Ouvrir l'&amp;image dans un nouvel onglet</translation>
+<translation id="1560991001553749272">Favori ajouté !</translation>
+<translation id="3966072572894326936">Choisir un autre dossier...</translation>
+<translation id="8766796754185931010">Kotoeri</translation>
+<translation id="7781829728241885113">Hier</translation>
+<translation id="2762402405578816341">Synchroniser automatiquement les éléments suivants :</translation>
+<translation id="1623661092385839831">Votre ordinateur intègre un périphérique de sécurité TPM (module de plate-forme sécurisée) qui permet de mettre en œuvre plusieurs fonctionnalités de sécurité critiques dans Google Chrome OS.</translation>
+<translation id="3359256513598016054">Contraintes des stratégies de certificat</translation>
+<translation id="4433914671537236274">Créer un support de récupération</translation>
+<translation id="4509345063551561634">Emplacement :</translation>
+<translation id="7596288230018319236">Toutes les pages que vous consultez apparaîtront ici à moins que vous ne les ouvriez dans une fenêtre en navigation privée. Vous pouvez utiliser le bouton Rechercher de cette page pour rechercher dans toutes les pages de votre historique.</translation>
+<translation id="7434509671034404296">Options pour les développeurs</translation>
+<translation id="6447842834002726250">Cookies</translation>
+<translation id="2609371827041010694">Toujours exécuter pour ce site</translation>
+<translation id="5170568018924773124">Afficher le dossier</translation>
+<translation id="883848425547221593">Autres favoris</translation>
+<translation id="6054173164583630569">Clavier français</translation>
+<translation id="4870177177395420201"><ph name="PRODUCT_NAME"/> ne parvient pas à déterminer ou à définir le navigateur par défaut.</translation>
+<translation id="8898786835233784856">Sélectionner l'onglet suivant</translation>
+<translation id="2674170444375937751">Voulez-vous vraiment supprimer ces pages de votre historique ?</translation>
+<translation id="9111102763498581341">Déverrouiller</translation>
+<translation id="289695669188700754">ID de clé : <ph name="KEY_ID"/></translation>
+<translation id="3067198360141518313">Exécuter ce plug-in</translation>
+<translation id="8767072502252310690">Utilisateurs</translation>
+<translation id="683526731807555621">Ajouter un moteur</translation>
+<translation id="6871644448911473373">Répondeur OCSP : <ph name="LOCATION"/></translation>
+<translation id="8281886186245836920">Ignorer</translation>
+<translation id="3867944738977021751">Champs de certificat</translation>
+<translation id="2114224913786726438">Modules (<ph name="TOTAL_COUNT"/>) : aucun conflit détecté.</translation>
+<translation id="7629827748548208700">Onglet : <ph name="TAB_NAME"/></translation>
+<translation id="388442998277590542">Impossible de charger la page d'options &quot;<ph name="OPTIONS_PAGE"/>&quot;.</translation>
+<translation id="8449008133205184768">Coller en adaptant le style</translation>
+<translation id="9114223350847410618">Veuillez ajouter une autre langue avant de supprimer celle-ci.</translation>
+<translation id="4408427661507229495">nom du réseau</translation>
+<translation id="8886960478266132308"><ph name="PRODUCT_NAME"/> synchronise de manière sécurisée vos données avec votre compte Google.</translation>
+<translation id="8028993641010258682">Taille</translation>
+<translation id="5031603669928715570">Activer...</translation>
+<translation id="1383876407941801731">Recherche</translation>
+<translation id="8398877366907290961">Poursuivre quand même</translation>
+<translation id="5063180925553000800">Nouveau code PIN :</translation>
+<translation id="2496540304887968742">La capacité du périphérique doit être d'au moins 4 Go.</translation>
+<translation id="6974053822202609517">De droite à gauche</translation>
+<translation id="2370882663124746154">Activer le mode Pinyin double</translation>
+<translation id="5463856536939868464">Menu contenant des favoris masqués</translation>
+<translation id="8286227656784970313">Utiliser le dictionnaire système</translation>
+<translation id="5431084084184068621">Vous avez choisi de chiffrer les données à l'aide de votre mot de passe Google. Vous pouvez modifier vos paramètres de synchronisation à tout moment, si vous changez d'avis.</translation>
+<translation id="1493263392339817010">Personnaliser les polices...</translation>
+<translation id="5352033265844765294">Enregistrement des informations de date</translation>
+<translation id="6449085810994685586">&amp;Vérifier l'orthographe du texte de ce champ</translation>
+<translation id="3621320549246006887">Ceci est un modèle expérimental qui permet aux enregistrements DNS (utilisant le protocole de sécurité DNSSEC) d'autoriser ou de refuser des certificats HTTPS. Ce message s'affiche lorsque vous activez des fonctionnalités expérimentales via des options de ligne de commande. Vous pouvez supprimer ces options de ligne de commande pour ignorer cette erreur.</translation>
+<translation id="50960180632766478"><ph name="NUMBER_FEW"/> minutes restantes</translation>
+<translation id="3174168572213147020">ÃŽle</translation>
+<translation id="748138892655239008">Contraintes de base du certificat</translation>
+<translation id="457386861538956877">Autres...</translation>
+<translation id="8063491445163840780">Activer l'onglet 4</translation>
+<translation id="5966654788342289517">Données personnelles</translation>
+<translation id="9137013805542155359">Afficher l'original</translation>
+<translation id="4792385443586519711">Nom de la société</translation>
+<translation id="6423731501149634044">Définir Adobe Reader comme visionneuse de documents PDF par défaut ?</translation>
+<translation id="8839907368860424444">Pour gérer les extensions installées, cliquez sur Extensions dans le menu Fenêtre.</translation>
+<translation id="2461687051570989462">Accédez à vos imprimantes depuis n'importe quel ordinateur ou smartphone. <ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/></translation>
+<translation id="7194430665029924274">Me &amp;le rappeler plus tard</translation>
+<translation id="5790085346892983794">Opération réussie !</translation>
+<translation id="1901769927849168791">Carte SD détectée.</translation>
+<translation id="818454486170715660"><ph name="NAME"/> - Propriétaire</translation>
+<translation id="1358032944105037487">Clavier japonais</translation>
+<translation id="8201956630388867069">WPA</translation>
+<translation id="603890000178803545">janv.^févr.^mars^avr.^mai^juin^juil.^août^sept.^oct.^nov.^déc.</translation>
+<translation id="8302838426652833913">Sélectionnez
+ <ph name="BEGIN_BOLD"/>
+ Applications &gt; Préférences système &gt; Réseau &gt; Assistant
+ <ph name="END_BOLD"/>
+ pour tester votre connexion.</translation>
+<translation id="8664389313780386848">&amp;Afficher le code source de la page</translation>
+<translation id="8970407809569722516">Micrologiciel :</translation>
+<translation id="1180549724812639004">Créer un profil</translation>
+<translation id="57646104491463491">Date de modification</translation>
+<translation id="5992752872167177798">Sandbox seccomp</translation>
+<translation id="6362853299801475928">Signale&amp;r un problème...</translation>
+<translation id="3289566588497100676">Entrée de symboles simplifiée</translation>
+<translation id="6507969014813375884">Chinois simplifié</translation>
+<translation id="7314244761674113881">Hôte SOCKS</translation>
+<translation id="5285794783728826432">Considérer ce certificat comme fiable pour identifier les sites Web.</translation>
+<translation id="4224803122026931301">Exceptions de localisation</translation>
+<translation id="749452993132003881">Hiragana</translation>
+<translation id="8226742006292257240">Le mot de passe TPM ci-dessous, généré de façon aléatoire, a été attribué à votre ordinateur :</translation>
+<translation id="8487693399751278191">Importer mes favoris maintenant...</translation>
+<translation id="7985242821674907985"><ph name="PRODUCT_NAME"/></translation>
+<translation id="7484580869648358686">Avertissement : Un problème a été détecté sur cette page.</translation>
+<translation id="2074739700630368799">Avec Google Chrome OS for business, vous pouvez connecter votre périphérique à Google Apps, ce qui vous permet de le rechercher et de le contrôler depuis le panneau de configuration de Google Apps.</translation>
+<translation id="4474155171896946103">Ajouter tous les onglets aux favoris...</translation>
+<translation id="5895187275912066135">Émis le</translation>
+<translation id="1190844492833803334">Lorsque je ferme le navigateur</translation>
+<translation id="5646376287012673985">Localisation</translation>
+<translation id="1110155001042129815">Attendre</translation>
+<translation id="2607101320794533334">Infos sur la clé publique de l'objet</translation>
+<translation id="7071586181848220801">Plug-in inconnu</translation>
+<translation id="3354601307791487577">Connexion en mode invité</translation>
+<translation id="4419409365248380979">Toujours autoriser <ph name="HOST"/> à paramétrer les cookies</translation>
+<translation id="2956070106555335453">Résumé</translation>
+<translation id="917450738466192189">Le certificat du serveur n'est pas valide.</translation>
+<translation id="2649045351178520408">Chaîne de certificats codés Base 64 ASCII</translation>
+<translation id="7424526482660971538">Choisir mon propre mot de passe multiterme</translation>
+<translation id="380271916710942399">Certificat de serveur non répertorié</translation>
+<translation id="6459488832681039634">Rechercher la sélection</translation>
+<translation id="2392369802118427583">Activer</translation>
+<translation id="9040421302519041149">L'accès à ce réseau est protégé.</translation>
+<translation id="5659593005791499971">E-mail</translation>
+<translation id="8235325155053717782">Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>) : <ph name="ERROR_TEXT"/></translation>
+<translation id="6584878029876017575">Signature permanente Microsoft</translation>
+<translation id="562901740552630300">Sélectionnez
+ <ph name="BEGIN_BOLD"/>
+ Démarrer &gt; Panneau de configuration &gt; Réseau et Internet &gt; Centre Réseau et partage &gt; Résolution des problèmes (en bas) &gt; Connexions Internet.
+ <ph name="END_BOLD"/></translation>
+<translation id="8816996941061600321">Gestionnaire de &amp;fichiers</translation>
+<translation id="2773223079752808209">Service client</translation>
+<translation id="4585473702689066695">Impossible de se connecter au réseau &quot;<ph name="NAME"/>&quot;.</translation>
+<translation id="4647175434312795566">J'accepte ces termes</translation>
+<translation id="1084824384139382525">Copier l'adr&amp;esse du lien</translation>
+<translation id="1221462285898798023">Veuillez démarrer <ph name="PRODUCT_NAME"/> en tant qu'utilisateur normal. Pour l'exécuter en tant que root, vous devez indiquer un autre répertoire de données utilisateur pour stocker les informations du profil.</translation>
+<translation id="3220586366024592812">Le processus du connecteur <ph name="CLOUD_PRINT_NAME"/> est bloqué. Voulez-vous le redémarrer ?</translation>
+<translation id="5042992464904238023">Contenu Web</translation>
+<translation id="6254503684448816922">Clé compromise</translation>
+<translation id="1181037720776840403">Supprimer</translation>
+<translation id="4006726980536015530">Si vous fermez <ph name="PRODUCT_NAME"/> maintenant, ces téléchargements seront annulés.</translation>
+<translation id="4194415033234465088">Dachen 26</translation>
+<translation id="1664712100580477121">Voulez-vous vraiment graver l'image sur le périphérique suivant :</translation>
+<translation id="6639554308659482635">Mémoire SQLite</translation>
+<translation id="8141503649579618569"><ph name="DOWNLOAD_RECEIVED"/>/<ph name="DOWNLOAD_TOTAL"/>, <ph name="TIME_LEFT"/></translation>
+<translation id="7650701856438921772"><ph name="PRODUCT_NAME"/> est affiché dans cette langue.</translation>
+<translation id="740624631517654988">Fenêtre pop-up bloquée</translation>
+<translation id="3738924763801731196"><ph name="OID"/> :</translation>
+<translation id="6550769511678490130">Ouvrir tous les favoris</translation>
+<translation id="1847961471583915783">Effacer les cookies et autres données de site et de plug-in lorsque je ferme le navigateur</translation>
+<translation id="8870318296973696995">Page d'accueil</translation>
+<translation id="6659594942844771486">Onglet</translation>
+<translation id="6575134580692778371">Non configuré</translation>
+<translation id="4624768044135598934">Opération réussie !</translation>
+<translation id="6014776969142880350">Relancez <ph name="PRODUCT_NAME"/> pour terminer la mise à jour.</translation>
+<translation id="5582768900447355629">Chiffrer toutes mes données</translation>
+<translation id="6122365914076864562">Veuillez patienter pendant que nous configurons votre réseau pour mobile.</translation>
+<translation id="1974043046396539880">Points de distribution de listes de révocation des certificats</translation>
+<translation id="7049357003967926684">Association</translation>
+<translation id="8641392906089904981">Appuyez sur Maj+Alt pour changer la disposition du clavier.</translation>
+<translation id="3024374909719388945">Utiliser l'horloge au format 24 heures</translation>
+<translation id="1867780286110144690"><ph name="PRODUCT_NAME"/> est prêt à terminer l'installation.</translation>
+<translation id="5316814419223884568">Lancez votre recherche à partir d'ici</translation>
+<translation id="8142732521333266922">OK, synchroniser tout</translation>
+<translation id="965674096648379287">Afin d'être correctement affichée, cette page requiert des données que vous avez précédemment entrées. Vous pouvez de nouveau transmettre ces données, mais, en procédant ainsi, vous devrez répéter chaque action que cette page a effectuée auparavant. Cliquez sur Rafraîchir pour transmettre de nouveau ces données et pour afficher cette page.</translation>
+<translation id="43742617823094120">Cela signifie que le certificat présenté à votre navigateur a été révoqué par son émetteur. L'intégrité de ce certificat a certainement été compromise, et il ne doit donc pas être approuvé. Ne poursuivez pas.</translation>
+<translation id="9019654278847959325">Clavier slovaque</translation>
+<translation id="18139523105317219">Nom de partie EDI</translation>
+<translation id="6657193944556309583">Vous avez déjà chiffré des données avec un mot de passe multiterme. Saisissez-le ci-dessous.</translation>
+<translation id="3328801116991980348">Informations sur le site</translation>
+<translation id="1205605488412590044">Créer un raccourci vers l'application...</translation>
+<translation id="2065985942032347596">Authentification requise</translation>
+<translation id="2553340429761841190"><ph name="PRODUCT_NAME"/> n'est pas parvenu à se connecter à <ph name="NETWORK_ID"/>. Sélectionnez un autre réseau ou réessayez.</translation>
+<translation id="2086712242472027775">Votre compte n'est pas compatible avec <ph name="PRODUCT_NAME"/>. Contactez l'administrateur de votre domaine ou utilisez un compte Google standard pour vous connecter.</translation>
+<translation id="7222232353993864120">Adresse e-mail</translation>
+<translation id="2128531968068887769">Client natif</translation>
+<translation id="7175353351958621980">Chargé depuis :</translation>
+<translation id="4590074117005971373">Active les balises canvas hautes performances dans un contexte 2D, pour effectuer le rendu via le processeur graphique.</translation>
+<translation id="7186367841673660872">Cette page en<ph name="ORIGINAL_LANGUAGE"/>a été traduite en<ph name="LANGUAGE_LANGUAGE"/></translation>
+<translation id="8448695406146523553">Seule une personne en possession de votre mot de passe multiterme peut lire vos données chiffrées. Google ne reçoit ni n'enregistre votre mot de passe multiterme. Si vous oubliez votre mot de passe multiterme, vous devrez</translation>
+<translation id="6052976518993719690">Autorité de certification SSL</translation>
+<translation id="1636959874332483835"><ph name="HOST_NAME"/> contient un logiciel malveillant. Votre ordinateur pourrait être infecté par un virus si vous consultez ce site.</translation>
+<translation id="8050783156231782848">Aucune donnée disponible.</translation>
+<translation id="1175364870820465910">Im&amp;primer...</translation>
+<translation id="3866249974567520381">Description</translation>
+<translation id="2900139581179749587">Voix non reconnue.</translation>
+<translation id="953692523250483872">Aucun fichier sélectionné</translation>
+<translation id="2294358108254308676">Souhaitez-vous installer <ph name="PRODUCT_NAME"/> ?</translation>
+<translation id="6549689063733911810">Activité récente</translation>
+<translation id="1529968269513889022">de la dernière semaine</translation>
+<translation id="5542132724887566711">Profil</translation>
+<translation id="5196117515621749903">Actualiser sans utiliser le cache</translation>
+<translation id="5552632479093547648">Logiciels malveillants et sites de phishing détectés !</translation>
+<translation id="4310537301481716192">Onglet fermé !</translation>
+<translation id="4988273303304146523">il y a <ph name="NUMBER_DEFAULT"/> jours</translation>
+<translation id="8428213095426709021">Paramètres</translation>
+<translation id="1588343679702972132">Ce site exige que vous vous identifiiez avec un certificat :</translation>
+<translation id="7211994749225247711">Supprimer...</translation>
+<translation id="2819994928625218237">&amp;Aucune suggestion orthographique</translation>
+<translation id="1065449928621190041">Clavier franco-canadien</translation>
+<translation id="8327626790128680264">Clavier étendu américain</translation>
+<translation id="2950186680359523359">Le serveur a mis fin à la connexion sans envoyer de données.</translation>
+<translation id="9142623379911037913">Autoriser <ph name="SITE"/> à afficher des notifications sur le Bureau ?</translation>
+<translation id="4196320913210960460">Pour gérer les extensions installées, cliquez sur Extensions dans le menu Outils.</translation>
+<translation id="3449494395612243720">Erreur de synchronisation, veuillez vous connecter à nouveau.</translation>
+<translation id="9118804773997839291">La liste suivante fait état des éléments dangereux détectés sur la page. Cliquez sur le lien &quot;Diagnostic&quot; pour obtenir plus d'informations sur un élément particulier.</translation>
+<translation id="7139724024395191329">Émirat</translation>
+<translation id="1761265592227862828">Synchroniser tous les paramètres et toutes les données\n(peut prendre un certain temps)</translation>
+<translation id="7754704193130578113">Toujours demander où enregistrer les fichiers</translation>
+<translation id="204914487372604757">Créer un raccourci</translation>
+<translation id="2497284189126895209">Tous les fichiers</translation>
+<translation id="696036063053180184">Sebeol-sik No-shift</translation>
+<translation id="452785312504541111">Anglais (pleine chasse)</translation>
+<translation id="945332329539165145">2D avec canvas et accélération matérielle</translation>
+<translation id="5220797120063118010">Cette fonctionnalité autorise l'installation d'applications Google Chrome déployées à partir d'un manifeste situé sur une page Web, plutôt qu'avec un fichier crx contenant le manifeste et les icônes.</translation>
+<translation id="9148126808321036104">Nouvelle connexion</translation>
+<translation id="2282146716419988068">GPU</translation>
+<translation id="428771275901304970">Moins de 1 Mo disponible</translation>
+<translation id="1682548588986054654">Nouvelle fenêtre de navigation privée</translation>
+<translation id="6833901631330113163">Europe du Sud</translation>
+<translation id="8691262314411702087">Sélectionner les éléments à synchroniser</translation>
+<translation id="6065289257230303064">Attributs du répertoire de l'objet du certificat</translation>
+<translation id="2423017480076849397">Accédez à vos imprimantes et partagez-les en ligne via <ph name="CLOUD_PRINT_NAME"/>.</translation>
+<translation id="569520194956422927">&amp;Ajouter...</translation>
+<translation id="4018133169783460046">Afficher <ph name="PRODUCT_NAME"/> dans cette langue</translation>
+<translation id="5110450810124758964">il y a <ph name="NUMBER_ONE"/> jour</translation>
+<translation id="3264544094376351444">Police Sans-Serif</translation>
+<translation id="5586942249556966598">Ne rien faire</translation>
+<translation id="2820806154655529776"><ph name="NUMBER_ONE"/> seconde</translation>
+<translation id="1077946062898560804">Configurer les mises à jour automatiques pour tous les utilisateurs</translation>
+<translation id="3122496702278727796">Échec de la création du répertoire des données</translation>
+<translation id="4517036173149081027">Fermer et annuler le chargement</translation>
+<translation id="7150146631451105528"><ph name="DATE"/></translation>
+<translation id="3166547286524371413">Adresse :</translation>
+<translation id="4522570452068850558">Détails</translation>
+<translation id="59659456909144943">Notification : <ph name="NOTIFICATION_NAME"/></translation>
+<translation id="6731320427842222405">Cette opération peut prendre quelques minutes.</translation>
+<translation id="4806525999832945986">Géré par <ph name="DOMAIN"/> (<ph name="STATUS"/>)</translation>
+<translation id="7503191893372251637">Type de certificat Netscape</translation>
+<translation id="1502960562739459116">Impossible d'afficher certaines parties de ce document PDF. Souhaitez-vous installer Adobe Reader ?</translation>
+<translation id="4135450933899346655">Vos certificats</translation>
+<translation id="4731578803613910821">Vos données personnelles sur <ph name="WEBSITE_1"/>, <ph name="WEBSITE_2"/> et <ph name="WEBSITE_3"/></translation>
+<translation id="7716781361494605745">URL de stratégie de l'autorité de certification Netscape</translation>
+<translation id="2881966438216424900">Dernier accès :</translation>
+<translation id="7552203043556919163">Synchroniser les mots de passe</translation>
+<translation id="630065524203833229">&amp;Quitter</translation>
+<translation id="4647090755847581616">&amp;Fermer l'onglet</translation>
+<translation id="2649204054376361687"><ph name="CITY"/>, <ph name="COUNTRY"/></translation>
+<translation id="7886758531743562066">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites qui semblent héberger des logiciels malveillants. Ces derniers peuvent nuire à votre ordinateur ou agir à votre insu. Le simple fait de visiter un site hébergeant ce type de logiciels peut infecter votre ordinateur.</translation>
+<translation id="2064746092913005102">Total : <ph name="NUMBER_OF_PAGES"/> <ph name="PAGE_OR_PAGES_LABEL"/> <ph name="TWO_SIDED"/> <ph name="TIMES"/> <ph name="NUMBER_OF_COPIES"/> <ph name="COPIES_LABEL"/> <ph name="EQUAL_SIGN"/> <ph name="NUMBER_OF_SHEETS"/> <ph name="SHEETS_LABEL"/></translation>
+<translation id="7538227655922918841">Les cookies de plusieurs sites ont été autorisés pour la session uniquement.</translation>
+<translation id="2385700042425247848">Nom du service :</translation>
+<translation id="7751005832163144684">Imprimer une page de test</translation>
+<translation id="3638865692466101147">Aperçu avant impression - <ph name="PREVIEW_TAB_TITLE"/></translation>
+<translation id="1471300011765310414"><ph name="PRODUCT_NAME"/>
+ ne peut pas à afficher la page Web, car votre ordinateur n'est pas connecté à Internet.</translation>
+<translation id="5464632865477611176">Exécuter cette fois</translation>
+<translation id="4268025649754414643">Chiffrement de la clé</translation>
+<translation id="7925247922861151263">Échec de la vérification AAA</translation>
+<translation id="1168020859489941584">Ouverture dans <ph name="TIME_REMAINING"/>...</translation>
+<translation id="7814458197256864873">&amp;Copier</translation>
+<translation id="8186706823560132848">Logiciel</translation>
+<translation id="4692623383562244444">Moteurs de recherche</translation>
+<translation id="567760371929988174">&amp;Méthodes d'entrée</translation>
+<translation id="10614374240317010">Jamais enregistrés</translation>
+<translation id="5116300307302421503">Impossible d'analyser le fichier.</translation>
+<translation id="2745080116229976798">Subordination qualifiée Microsoft</translation>
+<translation id="2526590354069164005">Bureau</translation>
+<translation id="7983301409776629893">Toujours traduire en <ph name="TARGET_LANGUAGE"/> les pages en <ph name="ORIGINAL_LANGUAGE"/></translation>
+<translation id="4890284164788142455">Thaï</translation>
+<translation id="4312207540304900419">Activer l'onglet suivant</translation>
+<translation id="8456362689280298700"><ph name="HOUR"/>:<ph name="MINUTE"/> de chargement</translation>
+<translation id="7648048654005891115">Style de mappage du clavier</translation>
+<translation id="539295039523818097">Un problème lié à votre microphone s'est produit.</translation>
+<translation id="4033319557821527966"><ph name="CLOUD_PRINT_NAME"/> vous permet d'accéder aux imprimantes de cet ordinateur, où que vous soyez. Connectez-vous pour l'activer.</translation>
+<translation id="6970216967273061347">District</translation>
+<translation id="4479639480957787382">Ethernet</translation>
+<translation id="6312403991423642364">Erreur de réseau inconnue.</translation>
+<translation id="751377616343077236">Nom du certificat</translation>
+<translation id="7154108546743862496">Plus d'informations</translation>
+<translation id="8637688295594795546">Mise à jour du système disponible. Préparation du téléchargement…</translation>
+<translation id="5167270755190684957">Galerie des thèmes Google Chrome</translation>
+<translation id="8382913212082956454">Copi&amp;er l'adresse e-mail</translation>
+<translation id="7447930227192971403">Activer l'onglet 3</translation>
+<translation id="2903493209154104877">Adresses</translation>
+<translation id="2056143100006548702">Plug-in : <ph name="PLUGIN_NAME"/> (<ph name="PLUGIN_VERSION"/>)</translation>
+<translation id="3479552764303398839">Pas maintenant</translation>
+<translation id="6445051938772793705">Pays</translation>
+<translation id="3251759466064201842">&lt;Ne fait pas partie du certificat&gt;</translation>
+<translation id="4229495110203539533">il y a <ph name="NUMBER_ONE"/> seconde</translation>
+<translation id="6410257289063177456">Fichiers image</translation>
+<translation id="6419902127459849040">Europe centrale</translation>
+<translation id="6707389671160270963">Certificat client SSL</translation>
+<translation id="6083557600037991373">Pour accélérer l'affichage des pages Web,
+ <ph name="PRODUCT_NAME"/>
+ enregistre temporairement les fichiers téléchargés sur le disque. Si
+ <ph name="PRODUCT_NAME"/>
+ ne s'arrête pas correctement, ces fichiers peuvent être endommagés, ce qui
+ génère cette erreur. L'actualisation de la page devrait permettre de résoudre
+ ce problème ; celui-ci ne se reproduira vraisemblablement plus si l'arrêt s'effectue
+ correctement.
+ <ph name="LINE_BREAK"/>
+ Si le problème persiste, essayez de supprimer le contenu du cache. Cette
+ erreur peut aussi indiquer que le matériel est sur le point de tomber
+ en panne.</translation>
+<translation id="5298219193514155779">Thème créé par</translation>
+<translation id="7366909168761621528">Données de navigation</translation>
+<translation id="1047726139967079566">Ajouter cette page aux favoris</translation>
+<translation id="9020142588544155172">Le serveur a refusé la connexion.</translation>
+<translation id="6113225828180044308">Module (<ph name="MODULUS_NUM_BITS"/> bits) :\n<ph name="MODULUS_HEX_DUMP"/>\n\nExposant public (<ph name="PUBLIC_EXPONENT_NUM_BITS"/> bits) :\n<ph name="EXPONENT_HEX_DUMP"/></translation>
+<translation id="2544782972264605588"><ph name="NUMBER_DEFAULT"/> secondes restantes</translation>
+<translation id="8871696467337989339">Vous utilisez un indicateur de ligne de commande non pris en charge : <ph name="BAD_FLAG"/>. La stabilité et la sécurité en seront affectées.</translation>
+<translation id="4767443964295394154">Emplacement de téléchargement</translation>
+<translation id="5031870354684148875">À propos de Google Traduction</translation>
+<translation id="720658115504386855">Les lettres ne sont pas sensibles à la casse.</translation>
+<translation id="2454247629720664989">Mot clé</translation>
+<translation id="3950820424414687140">Connexion</translation>
+<translation id="4626106357471783850">Redémarrez <ph name="PRODUCT_NAME"/> pour appliquer la mise à jour.</translation>
+<translation id="1697068104427956555">Sélectionner un carré dans l'image</translation>
+<translation id="2840798130349147766">Bases de données Web</translation>
+<translation id="1628736721748648976">Codage</translation>
+<translation id="1198271701881992799">Mise en route</translation>
+<translation id="782590969421016895">Utiliser les pages actuelles</translation>
+<translation id="6521850982405273806">Signaler une erreur</translation>
+<translation id="736515969993332243">Recherche de réseaux en cours</translation>
+<translation id="8026334261755873520">Effacer les données de navigation</translation>
+<translation id="2717361709448355148">Impossible de renommer &quot;$1&quot; : $2</translation>
+<translation id="1769104665586091481">Ouvrir le lien dans une nouvelle &amp;fenêtre</translation>
+<translation id="8503813439785031346">Nom d'utilisateur</translation>
+<translation id="5319782540886810524">Clavier letton</translation>
+<translation id="8651585100578802546">Forcer l'actualisation de cette page</translation>
+<translation id="685714579710025096">Disposition du clavier :</translation>
+<translation id="1361655923249334273">Non utilisé</translation>
+<translation id="290555789621781773"><ph name="NUMBER_TWO"/> minutes</translation>
+<translation id="5434065355175441495">Chiffrement RSA PKCS #1</translation>
+<translation id="7073704676847768330">Ce n'est probablement pas le site que vous recherchez !</translation>
+<translation id="8477384620836102176">&amp;Général</translation>
+<translation id="1074663319790387896">Configurer la synchronisation</translation>
+<translation id="4302315780171881488">État de connexion :</translation>
+<translation id="3391392691301057522">Ancien code PIN :</translation>
+<translation id="1344519653668879001">Désactiver le contrôle des liens hypertexte</translation>
+<translation id="6463795194797719782">&amp;Modifier</translation>
+<translation id="4262113024799883061">Chinois</translation>
+<translation id="4775879719735953715">Navigateur par défaut</translation>
+<translation id="5575473780076478375">Extension en mode navigation privée :<ph name="EXTENSION_NAME"/></translation>
+<translation id="4188026131102273494">Mot clé :</translation>
+<translation id="2930644991850369934">Un problème est survenu lors du téléchargement de l'image de récupération. La connexion réseau a été perdue.</translation>
+<translation id="3461610253915486539">Votre administrateur a désactivé certaines préférences.</translation>
+<translation id="5750053751252005701">Forfait de données <ph name="NETWORK"/> épuisé</translation>
+<translation id="8858939932848080433">Veuillez indiquer à quel niveau vous rencontrez des problèmes avant d'envoyer vos commentaires.</translation>
+<translation id="1720318856472900922">Authentification du serveur WWW TLS</translation>
+<translation id="8550022383519221471">Le service de synchronisation n'est pas disponible pour votre domaine.</translation>
+<translation id="3355823806454867987">Modifier les paramètres du proxy...</translation>
+<translation id="4780374166989101364">Cette fonctionnalité active les API des extensions expérimentales. Notez que vous ne pouvez pas mettre en ligne des extensions qui font appel aux API expérimentales dans la galerie d'extensions.</translation>
+<translation id="7227780179130368205">Un logiciel malveillant a été détecté !</translation>
+<translation id="435243347905038008">Forfait de données <ph name="NETWORK"/> presque épuisé</translation>
+<translation id="2489428929217601177">des dernières 24 heures</translation>
+<translation id="7418490403869327287">Une fois activée, la recherche instantanée charge la plupart des pages Web dès que vous saisissez l'URL dans le champ polyvalent, avant même que vous n'appuyiez sur Entrée. Si votre moteur de recherche par défaut est compatible, toute lettre saisie dans ce champ offre de nouveaux résultats et les prédictions intégrées vous guident dans vos recherches.\n\nChaque touche utilisée fait l'objet d'une requête, par conséquent il se peut que les éléments saisies dans le champ polyvalent soient enregistrés par votre moteur de recherche par défaut.\n</translation>
+<translation id="5149131957118398098"><ph name="NUMBER_ZERO"/> hours left</translation>
+<translation id="2541913031883863396">poursuivre quand même</translation>
+<translation id="4278390842282768270">Autorisé</translation>
+<translation id="2074527029802029717">Retirer l'onglet</translation>
+<translation id="1533897085022183721">Moins de <ph name="MINUTES"/></translation>
+<translation id="7503821294401948377">Impossible de charger l'icône &quot;<ph name="ICON"/>&quot; d'action du navigateur.</translation>
+<translation id="5539694491979265537">Consulter Google Dashboard</translation>
+<translation id="3942946088478181888">Plus d'informations</translation>
+<translation id="3722396466546931176">Ajoutez des langues puis faites-les glisser pour les classer dans l'ordre souhaité.</translation>
+<translation id="7396845648024431313"><ph name="APP_NAME"/> sera lancé au démarrage du système et continuera de s'exécuter en arrière-plan, même toutes les fenêtres de <ph name="PRODUCT_NAME"/> sont fermées.</translation>
+<translation id="8539727552378197395">Non (HttpOnly)</translation>
+<translation id="4519351128520996510">Saisir votre mot de passe multiterme pour la synchronisation</translation>
+<translation id="2391419135980381625">Police standard</translation>
+<translation id="7893393459573308604"><ph name="ENGINE_NAME"/> (par défaut)</translation>
+<translation id="5392544185395226057">Cette fonctionnalité active la prise en charge du client natif.</translation>
+<translation id="5400640815024374115">La puce du module de plate-forme sécurisée (TPM) est désactivée ou inexistante.</translation>
+<translation id="2151576029659734873">L'index de l'onglet indiqué est incorrect.</translation>
+<translation id="5150254825601720210">Nom du serveur SSL du certificat Netscape</translation>
+<translation id="6771503742377376720">Est une autorité de certification</translation>
+<translation id="8814190375133053267">Wi-Fi</translation>
+<translation id="2040078585890208937">Connexion à <ph name="NAME"/></translation>
+<translation id="8410619858754994443">Confirmer le mot de passe :</translation>
+<translation id="2210840298541351314">Aperçu avant impression</translation>
+<translation id="3858678421048828670">Clavier italien</translation>
+<translation id="4938277090904056629">Impossible d'établir une connexion sécurisée à cause de l'antivirus ESET.</translation>
+<translation id="4521805507184738876">(expiré)</translation>
+<translation id="111844081046043029">Voulez-vous vraiment quitter cette page ?</translation>
+<translation id="1951615167417147110">Faire défiler d'une page vers le haut</translation>
+<translation id="4154664944169082762">Empreintes</translation>
+<translation id="3202578601642193415">Le plus récent</translation>
+<translation id="8112886015144590373"><ph name="NUMBER_FEW"/> heures</translation>
+<translation id="1398853756734560583">Agrandir</translation>
+<translation id="8988255471271407508">La page Web est introuvable dans le cache. Certaines ressources ne sont restituées fidèlement que si elles sont extraites du cache, notamment les pages générées à partir de données que vous avez envoyées. <ph name="LINE_BREAK"/> Cette erreur peut également être due à un cache endommagé lors d'une fermeture incorrecte. <ph name="LINE_BREAK"/> Si le problème persiste, essayez d'effacer le cache.</translation>
+<translation id="1195977189444203128">Le plug-in <ph name="PLUGIN_NAME"/> n'est plus à jour.</translation>
+<translation id="3878562341724547165">Vous avez changé de position. Souhaitez-vous utiliser <ph name="NEW_GOOGLE_URL"/> ?</translation>
+<translation id="1758018619400202187">EAP-TLS</translation>
+<translation id="6690744523875189208"><ph name="NUMBER_TWO"/> heures</translation>
+<translation id="8053390638574070785">Rafraîchir cette page</translation>
+<translation id="5507756662695126555">Non-répudiation</translation>
+<translation id="3678156199662914018">Extension : <ph name="EXTENSION_NAME"/></translation>
+<translation id="7951780829309373534">Impossible de coller &quot;$1&quot; : $2</translation>
+<translation id="9194519262242876737">Active l'API Web audio.</translation>
+<translation id="3531250013160506608">Zone de saisie de mot de passe</translation>
+<translation id="8314066201485587418">Effacer les cookies et autres données de site lorsque je quitte le navigateur</translation>
+<translation id="4094105377635924481">Ajouter l'option de regroupement au menu contextuel des onglets</translation>
+<translation id="8655295600908251630">Version</translation>
+<translation id="8250690786522693009">Latin</translation>
+<translation id="2119721408814495896">Le connecteur <ph name="CLOUD_PRINT_NAME"/> requiert l'installation du pack Microsoft XML Paper Specification Essentials.</translation>
+<translation id="7624267205732106503">Effacer les cookies et autres données de site lorsque je ferme le navigateur</translation>
+<translation id="8401363965527883709">Case décochée</translation>
+<translation id="7771452384635174008">Mise en page</translation>
+<translation id="6188939051578398125">Saisir un nom ou une adresse</translation>
+<translation id="8443621894987748190">Choix de l'image du compte</translation>
+<translation id="10122177803156699">Me montrer</translation>
+<translation id="5260878308685146029"><ph name="NUMBER_TWO"/> minutes restantes</translation>
+<translation id="2192505247865591433">De :</translation>
+<translation id="238391805422906964">Ouvrir un rapport de phishing</translation>
+<translation id="5921544176073914576">Page de phishing</translation>
+<translation id="3727187387656390258">Inspecter le pop-up</translation>
+<translation id="569068482611873351">Importer...</translation>
+<translation id="6571070086367343653">Modifier la carte de paiement</translation>
+<translation id="1204242529756846967">Cette langue est utilisée pour corriger l'orthographe.</translation>
+<translation id="3981760180856053153">Le type d'enregistrement indiqué est incorrect.</translation>
+<translation id="8464591670878858520">Forfait de données <ph name="NETWORK"/> arrivé à expiration</translation>
+<translation id="4568660204877256194">Exporter mes favoris...</translation>
+<translation id="3116361045094675131">Clavier britannique</translation>
+<translation id="4577070033074325641">Importer des favoris...</translation>
+<translation id="1641504961675316934"><ph name="CLOUD_PRINT_NAME"/></translation>
+<translation id="1715941336038158809">Nom d'utilisateur ou mot de passe incorrect</translation>
+<translation id="1901303067676059328">&amp;Tout sélectionner</translation>
+<translation id="674375294223700098">Erreur inconnue liée au certificat du serveur.</translation>
+<translation id="7780428956635859355">Envoyer une capture d'écran enregistrée</translation>
+<translation id="2850961597638370327">Émis pour : <ph name="NAME"/></translation>
+<translation id="2168039046890040389">Page précédente</translation>
+<translation id="1767519210550978135">Hsu</translation>
+<translation id="2498539833203011245">Réduire</translation>
+<translation id="2893168226686371498">Navigateur par défaut</translation>
+<translation id="2435457462613246316">Afficher le mot de passe</translation>
+<translation id="7988355189918024273">Activer les fonctionnalités d'accessibilité</translation>
+<translation id="5438653034651341183">Inclure la capture d'écran actuelle :</translation>
+<translation id="1899708097738826574"><ph name="OPTIONS_TITLE"/> - <ph name="SUBPAGE_TITLE"/></translation>
+<translation id="1765313842989969521">(cette extension est gérée et ne peut être désinstallée ni désactivée)</translation>
+<translation id="6983783921975806247">OID enregistré</translation>
+<translation id="394984172568887996">Importés depuis IE</translation>
+<translation id="5311260548612583999">Fichier de clé privée (facultatif) :</translation>
+<translation id="2430043402233747791">Autoriser pour la session uniquement</translation>
+<translation id="7363290921156020669"><ph name="NUMBER_ZERO"/> mins</translation>
+<translation id="7568790562536448087">Mise à jour en cours</translation>
+<translation id="4856408283021169561">Aucun microphone trouvé.</translation>
+<translation id="8190193592390505034">Connexion à <ph name="PROVIDER_NAME"/></translation>
+<translation id="6144890426075165477"><ph name="PRODUCT_NAME"/> n'est pas votre navigateur par défaut.</translation>
+<translation id="823241703361685511">Forfait</translation>
+<translation id="4068506536726151626">Cette page contient des éléments des sites ci-dessous qui suivent votre position géographique :</translation>
+<translation id="4721475475128190282">Plusieurs profils</translation>
+<translation id="4220128509585149162">Plantages</translation>
+<translation id="8798099450830957504">Par défaut</translation>
+<translation id="9107059250669762581"><ph name="NUMBER_DEFAULT"/> jours</translation>
+<translation id="1640283014264083726">PKCS #1 MD4 avec chiffrement RSA</translation>
+<translation id="872451400847464257">Modifier le moteur de recherche</translation>
+<translation id="6463061331681402734"><ph name="NUMBER_MANY"/> minutes</translation>
+<translation id="2466804342846034717">Indiquez le mot de passe approprié ci-dessus, puis saisissez les caractères figurant dans l'image ci-dessous.</translation>
+<translation id="3881435075661337013">Expiration de <ph name="NETWORK"/> imminente</translation>
+<translation id="5681833099441553262">Activer l'onglet précédent</translation>
+<translation id="4792057643643237295">Désactiver l'accès à distance</translation>
+<translation id="1681614449735360921">Afficher les incompatibilités</translation>
+<translation id="19094784437781028">Carte de débit Solo</translation>
+<translation id="2657327428424666237"><ph name="BEGIN_LINK"/>Actualisez<ph name="END_LINK"/> cette page Web ultérieurement.</translation>
+<translation id="7347751611463936647">Pour utiliser cette extension, saisissez &quot;<ph name="EXTENSION_KEYWORD"/>&quot;, TAB, puis votre commande ou votre recherche.</translation>
+<translation id="659432221160402784"><ph name="PRODUCT_NAME"/> synchronisera les applications installées, afin que vous puissiez y accéder en vous connectant depuis tout navigateur <ph name="PRODUCT_NAME"/>.</translation>
+<translation id="892464165639979917">Langues et paramètres du correcteur orthographique...</translation>
+<translation id="5645845270586517071">Erreur de sécurité</translation>
+<translation id="2805756323405976993">Applications</translation>
+<translation id="3651020361689274926">La ressource demandée n'existe plus et aucune adresse de transfert n'est disponible. Il semble que cet état de fait soit permanent.</translation>
+<translation id="2989786307324390836">Certificat unique binaire codé DER</translation>
+<translation id="3827774300009121996">&amp;Plein écran</translation>
+<translation id="3771294271822695279">Fichiers vidéo</translation>
+<translation id="6704875430222476107"><ph name="PRODUCT_NAME"/> indique que
+ NetNanny intercepte les connexions sécurisées. En général, cela
+ ne constitue pas un problème de sécurité, car le logiciel NetNanny s'exécute souvent
+ sur le même ordinateur. Toutefois, en raison de certaines incompatibilités avec
+ les connexions sécurisées Google Chrome, vous devez configurer NetNanny
+ de manière à éviter ces interceptions. Cliquez sur le lien En savoir plus pour obtenir des instructions.</translation>
+<translation id="3388026114049080752">Vos onglets et activités de navigation</translation>
+<translation id="7525067979554623046">Créer</translation>
+<translation id="4711094779914110278">Turc</translation>
+<translation id="1031460590482534116">Une erreur s'est produite lors de la tentative d'enregistrement du certificat client. Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)</translation>
+<translation id="7136984461011502314">Bienvenue dans <ph name="PRODUCT_NAME"/></translation>
+<translation id="1594030484168838125">Sélectionner</translation>
+<translation id="204497730941176055">Nom du modèle de certificat Microsoft</translation>
+<translation id="6705264787989366486">Configuration de l'adresse IP pour <ph name="NAME"/></translation>
+<translation id="8970721300630048025">Immortalisez votre plus beau sourire et utilisez la photo comme image de compte.</translation>
+<translation id="4087089424473531098">Extension créée :
+
+<ph name="EXTENSION_FILE"/></translation>
+<translation id="16620462294541761">Mot de passe incorrect. Veuillez réessayer.</translation>
+<translation id="5017508259293544172">LEAP</translation>
+<translation id="1394630846966197578">Échec de la connexion aux serveurs de reconnaissance vocale.</translation>
+<translation id="2498765460639677199">Très grande</translation>
+<translation id="2378982052244864789">Sélectionner le répertoire de l'extension</translation>
+<translation id="7861215335140947162">&amp;Téléchargements</translation>
+<translation id="4778630024246633221">Gestionnaire des certificats</translation>
+<translation id="6705050455568279082"><ph name="URL"/> souhaite suivre votre position géographique</translation>
+<translation id="4708849949179781599">Quitter <ph name="PRODUCT_NAME"/></translation>
+<translation id="2505402373176859469"><ph name="RECEIVED_AMOUNT"/> sur <ph name="TOTAL_SIZE"/></translation>
+<translation id="6644512095122093795">Proposer d'enregistrer les mots de passe</translation>
+<translation id="4724450788351008910">Modification de l'affiliation</translation>
+<translation id="2249605167705922988">par exemple : 1-5, 8, 11-13</translation>
+<translation id="8691686986795184760">(Activé par une stratégie d'entreprise)</translation>
+<translation id="1911483096198679472">Qu'est-ce que c'est ?</translation>
+<translation id="1976323404609382849">Les cookies de plusieurs sites ont été bloqués.</translation>
+<translation id="2662952950313424742">Serveur DNS spécifié par l'utilisateur et utilisé par Google Chrome, à la place du paramètre système par défaut, pour les résolutions DNS.</translation>
+<translation id="4176463684765177261">Désactivé</translation>
+<translation id="2079545284768500474">Annuler</translation>
+<translation id="114140604515785785">Répertoire racine de l'extension :</translation>
+<translation id="4788968718241181184">Mode de saisie du vietnamien (TCVN6064)</translation>
+<translation id="1512064327686280138">Échec de l'activation</translation>
+<translation id="3254409185687681395">Ajouter cette page aux favoris</translation>
+<translation id="1384616079544830839">L'identité de ce site Web a été vérifiée par <ph name="ISSUER"/>.</translation>
+<translation id="8710160868773349942">Adresse e-mail : <ph name="EMAIL_ADDRESSES"/></translation>
+<translation id="4057991113334098539">Activation...</translation>
+<translation id="9073281213608662541">PAP</translation>
+<translation id="1800035677272595847">Sites de phishing</translation>
+<translation id="8448317557906454022"><ph name="NUMBER_ZERO"/> secs ago</translation>
+<translation id="402759845255257575">Interdire à tous les sites d'exécuter JavaScript</translation>
+<translation id="4610637590575890427">Vouliez-vous accéder à <ph name="SITE"/> ?</translation>
+<translation id="7723779034587221017">La connexion avec le service de configuration a été perdue. Veuillez réinitialiser votre périphérique ou contacter votre représentant de l'assistance technique.</translation>
+<translation id="3046388203776734202">Paramètres des fenêtres pop-up :</translation>
+<translation id="3437994698969764647">Tout exporter...</translation>
+<translation id="8349305172487531364">Barre de favoris</translation>
+<translation id="1898064240243672867">Stocké dans : <ph name="CERT_LOCATION"/></translation>
+<translation id="444134486829715816">Développer...</translation>
+<translation id="1401874662068168819">Gin Yieh</translation>
+<translation id="7208899522964477531">Rechercher <ph name="SEARCH_TERMS"/> sur <ph name="SITE_NAME"/></translation>
+<translation id="6255097610484507482">Modifier la carte de paiement</translation>
+<translation id="5584091888252706332">Au démarrage</translation>
+<translation id="8960795431111723921">Nous examinons actuellement le problème.</translation>
+<translation id="2482878487686419369">Notifications</translation>
+<translation id="8004582292198964060">Navigateur</translation>
+<translation id="695755122858488207">Case d'option décochée</translation>
+<translation id="6357135709975569075"><ph name="NUMBER_ZERO"/> days</translation>
+<translation id="8666678546361132282">Anglais</translation>
+<translation id="2224551243087462610">Modifier le nom du dossier</translation>
+<translation id="1358741672408003399">Grammaire et orthographe</translation>
+<translation id="4910673011243110136">Réseaux privés</translation>
+<translation id="2527167509808613699">Toutes sortes de connexions</translation>
+<translation id="9095710730982563314">Exceptions liées aux notifications</translation>
+<translation id="8072988827236813198">Épingler les onglets</translation>
+<translation id="1234466194727942574">Barre d'onglets</translation>
+<translation id="7974087985088771286">Activer l'onglet 6</translation>
+<translation id="4035758313003622889">Gestionnaire de &amp;tâches</translation>
+<translation id="6356936121715252359">Paramètres de stockage d'Adobe Flash Player...</translation>
+<translation id="5885996401168273077">Connexion au réseau</translation>
+<translation id="7313804056609272439">Mode de saisie du vietnamien (VNI)</translation>
+<translation id="1768211415369530011">L'application suivante va être lancée si vous acceptez cette requête :\n\n<ph name="APPLICATION"/></translation>
+<translation id="8793043992023823866">Importation...</translation>
+<translation id="8106211421800660735">N° de carte</translation>
+<translation id="2550839177807794974">Gérer les moteurs de recherche...</translation>
+<translation id="7031711645186424727">Utiliser un moniteur externe</translation>
+<translation id="6316768948917110108">Gravure de l'image en cours...</translation>
+<translation id="5089810972385038852">État</translation>
+<translation id="2872961005593481000">Éteindre</translation>
+<translation id="8986267729801483565">Enregistrer les fichiers dans le dossier :</translation>
+<translation id="4322394346347055525">Fermer les autres onglets</translation>
+<translation id="4411770745820968260">Répertoire de fichiers</translation>
+<translation id="881799181680267069">Masquer les autres</translation>
+<translation id="1812631533912615985">Annuler l'épinglage des onglets</translation>
+<translation id="6042308850641462728">Plus</translation>
+<translation id="8318945219881683434">Échec de la vérification de la révocation</translation>
+<translation id="1650709179466243265">Ajouter www. et .com, puis ouvrir la page</translation>
+<translation id="3524079319150349823">Pour inspecter un pop-up, cliquez avec le bouton droit sur la page ou sur l'icône d'action du navigateur, puis sélectionnez Inspecter le pop-up.</translation>
+<translation id="994289308992179865">&amp;Répéter</translation>
+<translation id="7793343764764530903"><ph name="CLOUD_PRINT_NAME"/> est à présent activé. <ph name="PRODUCT_NAME"/> a enregistré les imprimantes installées sur cette machine en les associant à &lt;b&gt;<ph name="EMAIL_ADDRESSES"/>&lt;/b&gt;. Vous pouvez désormais utiliser vos imprimantes depuis n'importe quelle application Web ou mobile associée à <ph name="CLOUD_PRINT_NAME"/>.</translation>
+<translation id="1703490097606704369">Le serveur de <ph name="HOST_NAME"/>
+ est introuvable, car la résolution DNS a échoué. DNS est le service Web qui
+ traduit les noms de site Web en adresses Internet. Cette erreur est
+ généralement due à l'absence de connexion Internet ou à une configuration
+ incorrecte du réseau. Cela peut également venir d'un serveur DNS qui ne
+ répond pas ou d'un pare-feu interdisant l'accès de
+ <ph name="PRODUCT_NAME"/>
+ au réseau.</translation>
+<translation id="8887090188469175989">ZGPY</translation>
+<translation id="3302709122321372472">Impossible de charger le fichier css &quot;<ph name="RELATIVE_PATH"/>&quot; du script de contenu.</translation>
+<translation id="305803244554250778">Créer des raccourcis vers des applications aux emplacements suivants :</translation>
+<translation id="574392208103952083">Moyenne</translation>
+<translation id="3745810751851099214">Envoyé pour :</translation>
+<translation id="3937609171782005782">Aider Google à détecter les logiciels malveillants en envoyant des données supplémentaires concernant les sites pour lesquels cet avertissement s'affiche. Ces données seront gérées conformément aux règles définies sur la page <ph name="PRIVACY_PAGE_LINK"/>.</translation>
+<translation id="8877448029301136595">[répertoire parent]</translation>
+<translation id="7301360164412453905">Touches de sélection du clavier Hsu</translation>
+<translation id="8631271110654520730">Copie de l'image de récupération...</translation>
+<translation id="1963227389609234879">Tout supprimer</translation>
+<translation id="7779140087128114262">Seule une personne en possession de votre mot de passe multiterme peut lire vos données chiffrées. Google ne reçoit ni n'enregistre votre mot de passe multiterme. Si vous oubliez votre mot de passe multiterme, vous devrez réinitialiser la synchronisation.</translation>
+<translation id="8027581147000338959">Ouvrir dans une nouvelle fenêtre</translation>
+<translation id="6030946405726632495">Impossible de créer le dossier &quot;$1&quot;: $2</translation>
+<translation id="8019305344918958688">Dommage... Aucune extension n'est installée. :-(</translation>
+<translation id="7466861475611330213">Style de ponctuation</translation>
+<translation id="2496180316473517155">Historique de navigation</translation>
+<translation id="602251597322198729">Ce site tente de télécharger plusieurs fichiers. Voulez-vous autoriser le chargement ?</translation>
+<translation id="5843685321177053287">Établissement de la liaison avec le service de gestion des périphériques en attente...</translation>
+<translation id="2052389551707911401"><ph name="NUMBER_MANY"/> heures</translation>
+<translation id="5411472733320185105">Ne pas utiliser les paramètres du proxy pour les hôtes et domaines suivants :</translation>
+<translation id="6691936601825168937">&amp;Avancer</translation>
+<translation id="6566142449942033617">Impossible de charger &quot;<ph name="PLUGIN_PATH"/>&quot; pour le plug-in.</translation>
+<translation id="7065534935986314333">À propos du système</translation>
+<translation id="45025857977132537">Utilisation de la clé du certificat : <ph name="USAGES"/></translation>
+<translation id="6454421252317455908">Mode de saisie du chinois (quick)</translation>
+<translation id="368789413795732264">Une erreur s'est produite lors de la tentative d'écriture du fichier : <ph name="ERROR_TEXT"/>.</translation>
+<translation id="1173894706177603556">Renommer</translation>
+<translation id="5670032673361607750">La synchronisation requiert votre attention.</translation>
+<translation id="2148716181193084225">Aujourd'hui</translation>
+<translation id="1002064594444093641">Imp&amp;rimer le cadre...</translation>
+<translation id="7234674978021619913">Le site <ph name="HOST_NAME"/> a déjà été informé qu'un logiciel malveillant a été détecté sur ses pages. Pour plus d'informations concernant les problèmes rencontrés sur <ph name="HOST_NAME2"/>, consultez notre <ph name="DIAGNOSTIC_PAGE"/> Google.</translation>
+<translation id="8202390211066742724">Adresse de serveur DNS spécifiée par l'utilisateur.</translation>
+<translation id="4608500690299898628">&amp;Rechercher...</translation>
+<translation id="3574305903863751447"><ph name="CITY"/>, <ph name="STATE"/> <ph name="COUNTRY"/></translation>
+<translation id="8724859055372736596">&amp;Afficher dans le dossier</translation>
+<translation id="4605399136610325267">Non connecté à Internet.</translation>
+<translation id="978407797571588532">Sélectionnez
+ <ph name="BEGIN_BOLD"/>
+ Démarrer &gt; Panneau de configuration &gt; Connexions réseau &gt; Assistant Nouvelle connexion
+ <ph name="END_BOLD"/>
+ pour tester votre connexion.</translation>
+<translation id="5554489410841842733">Cette icône s'affiche lorsque l'extension peut agir sur la page active.</translation>
+<translation id="579702532610384533">Reconnexion</translation>
+<translation id="4862642413395066333">Réponses OCSP de signature</translation>
+<translation id="5266113311903163739">Erreur d'importation de l'autorité de certification</translation>
+<translation id="9563164493805065">Gravure de l'image terminée.</translation>
+<translation id="4756388243121344051">&amp;Historique</translation>
+<translation id="3789841737615482174">Installer</translation>
+<translation id="4320697033624943677">Ajouter des utilisateurs</translation>
+<translation id="9153934054460603056">Enregistrer l'authentification et le mot de passe</translation>
+<translation id="1455548678241328678">Clavier norvégien</translation>
+<translation id="2520481907516975884">Basculer en mode chinois/anglais</translation>
+<translation id="8571890674111243710">Traduction de la page en <ph name="LANGUAGE"/>...</translation>
+<translation id="4789872672210757069">À propos de &amp;<ph name="PRODUCT_NAME"/></translation>
+<translation id="4056561919922437609"><ph name="TAB_COUNT"/> onglets</translation>
+<translation id="4373894838514502496">il y a <ph name="NUMBER_FEW"/> minutes</translation>
+<translation id="6358450015545214790">Qu'est-ce que c'est ?</translation>
+<translation id="6264365405983206840">Tout &amp;sélectionner</translation>
+<translation id="1017280919048282932">&amp;Ajouter au dictionnaire</translation>
+<translation id="8319414634934645341">Utilisation étendue de la clé</translation>
+<translation id="4563210852471260509">Le chinois est la langue de saisie initiale</translation>
+<translation id="6897140037006041989">Agent utilisateur</translation>
+<translation id="3413122095806433232">Émetteurs de l'autorité de certification : <ph name="LOCATION"/></translation>
+<translation id="4115153316875436289"><ph name="NUMBER_TWO"/> jours</translation>
+<translation id="701080569351381435">Code source</translation>
+<translation id="3286538390144397061">Redémarrer maintenant</translation>
+<translation id="163309982320328737">La largeur de caractères initiale est Complète</translation>
+<translation id="5107325588313356747">Pour masquer l'accès à ce programme, vous devez le désinstaller au moyen de \n<ph name="CONTROL_PANEL_APPLET_NAME"/> du Panneau de configuration.\n\nSouhaitez-vous exécuter <ph name="CONTROL_PANEL_APPLET_NAME"/> ?</translation>
+<translation id="4841055638263130507">Paramètres du microphone</translation>
+<translation id="6965648386495488594">Port</translation>
+<translation id="7631887513477658702">&amp;Toujours ouvrir les fichiers de ce type</translation>
+<translation id="8627795981664801467">Uniquement les connexions sécurisées</translation>
+<translation id="8680787084697685621">Les informations de connexion au compte sont obsolètes.</translation>
+<translation id="3228969707346345236">La traduction a échoué, car la page est déjà en <ph name="LANGUAGE"/>.</translation>
+<translation id="1873879463550486830">Sandbox SUID</translation>
+<translation id="2190355936436201913">(vide)</translation>
+<translation id="8515737884867295000">Échec de l'authentification basée sur le certificat</translation>
+<translation id="5868426874618963178">Envoyer le code source de la page actuelle</translation>
+<translation id="1269138312169077280">Votre administrateur a désactivé certains paramètres.</translation>
+<translation id="5818003990515275822">Coréen</translation>
+<translation id="4182252350869425879">Avertissement : Il s'agit peut-être d'un site de phishing !</translation>
+<translation id="5458214261780477893">Dvorak</translation>
+<translation id="5353719617589986386">Étendue de pages incorrecte</translation>
+<translation id="1164369517022005061"><ph name="NUMBER_DEFAULT"/> heures restantes</translation>
+<translation id="5943260032016910017">Exceptions liées aux cookies et aux données de site</translation>
+<translation id="2214283295778284209"><ph name="SITE"/> n'est pas accessible</translation>
+<translation id="8755376271068075440">P&amp;lus grand</translation>
+<translation id="8132793192354020517">Connecté à <ph name="NAME"/></translation>
+<translation id="8187473050234053012">Le certificat de sécurité du site a été révoqué !</translation>
+<translation id="7444983668544353857">Désactiver <ph name="NETWORKDEVICE"/></translation>
+<translation id="6003177993629630467"><ph name="PRODUCT_NAME"/> risque de ne pas rester à jour.</translation>
+<translation id="421577943854572179">intégré sur tout autre site</translation>
+<translation id="580886651983547002"><ph name="PRODUCT_NAME"/>
+ ne parvient pas à atteindre le site Web. Cela vient probablement d'un problème de réseau,
+ mais peut également être dû à un pare-feu ou à un serveur proxy mal configuré.</translation>
+<translation id="5445557969380904478">À propos de la reconnaissance vocale</translation>
+<translation id="3093473105505681231">Langues et paramètres du correcteur orthographique...</translation>
+<translation id="152482086482215392"><ph name="NUMBER_ONE"/> seconde restante</translation>
+<translation id="529172024324796256">Nom d'utilisateur :</translation>
+<translation id="3308116878371095290">Le stockage des cookies n'est pas autorisé pour cette page.</translation>
+<translation id="7521387064766892559">JavaScript</translation>
+<translation id="1545786162090505744">URL avec %s à la place de la requête</translation>
+<translation id="7219179957768738017">La connexion utilise <ph name="SSL_VERSION"/>.</translation>
+<translation id="7014174261166285193">Échec de l'installation</translation>
+<translation id="1970746430676306437">Afficher les &amp;infos sur la page</translation>
+<translation id="3199127022143353223">Serveurs</translation>
+<translation id="2805646850212350655">Système de fichiers de chiffrement Microsoft </translation>
+<translation id="8053959338015477773">Un plug-in supplémentaire est requis pour afficher certains éléments sur cette page.</translation>
+<translation id="3541661933757219855">Appuyez sur Ctrl+Alt+/ ou sur Échap pour masquer</translation>
+<translation id="8813873272012220470">Cette fonctionnalité effectue des vérifications en arrière-plan et vous avertit en cas d'incompatibilité logicielle (modules tiers bloquant le navigateur, par exemple).</translation>
+<translation id="5020734739305654865">Connexion avec</translation>
+<translation id="2679385451463308372">Imprimer depuis la boîte de dialogue système…</translation>
+<translation id="7414887922320653780"><ph name="NUMBER_ONE"/> heure restante</translation>
+<translation id="121632099317611328">Échec de l'initialisation de l'appareil photo</translation>
+<translation id="399179161741278232">Importés</translation>
+<translation id="3829932584934971895">Type de fournisseur :</translation>
+<translation id="462288279674432182">IP restreinte :</translation>
+<translation id="3927932062596804919">Refuser</translation>
+<translation id="3524915994314972210">Démarrage du téléchargement en cours...</translation>
+<translation id="6484929352454160200">Une nouvelle version de <ph name="PRODUCT_NAME"/> est disponible.</translation>
+<translation id="3187212781151025377">Clavier hébreu</translation>
+<translation id="351152300840026870">Police à largeur fixe</translation>
+<translation id="5827266244928330802">Safari</translation>
+<translation id="778881183694837592">Les champs obligatoires ne doivent pas rester vides.</translation>
+<translation id="2371076942591664043">Ouvrir une fois le téléchargement &amp;terminé</translation>
+<translation id="3920504717067627103">Stratégies de certificat</translation>
+<translation id="155865706765934889">Pavé tactile</translation>
+<translation id="7701040980221191251">Aucun</translation>
+<translation id="5917011688104426363">Activer la barre d'adresse en mode recherche</translation>
+<translation id="6910239454641394402">Exceptions pour JavaScript</translation>
+<translation id="2979639724566107830">Ouvrir dans une nouvelle fenêtre</translation>
+<translation id="3269101346657272573">Veuillez saisir le code PIN.</translation>
+<translation id="9204065299849069896">Options de saisie automatique...</translation>
+<translation id="2822854841007275488">Arabe</translation>
+<translation id="5857090052475505287">Nouveau dossier</translation>
+<translation id="7450732239874446337">E/S réseau interrompue</translation>
+<translation id="5178667623289523808">Rechercher le précédent</translation>
+<translation id="2815448242176260024">Ne jamais enregistrer les mots de passe</translation>
+<translation id="2989805286512600854">Ouvrir dans un nouvel onglet</translation>
+<translation id="8687485617085920635">Fenêtre suivante</translation>
+<translation id="4122118036811378575">&amp;Rechercher le suivant</translation>
+<translation id="6008256403891681546">JCB</translation>
+<translation id="2610780100389066815">Signature de liste d'approbation Microsoft</translation>
+<translation id="8289811203643526145">Gérer les certificats...</translation>
+<translation id="2788575669734834343">Sélectionnez le fichier de certificat.</translation>
+<translation id="8404409224170843728">Fabricant :</translation>
+<translation id="8267453826113867474">Bloquer le contenu inapproprié</translation>
+<translation id="7959074893852789871">Le fichier contenait plusieurs certificats, dont certains n'ont pas été importés :</translation>
+<translation id="1213999834285861200">Exceptions pour les images</translation>
+<translation id="2805707493867224476">Autoriser tous les sites à afficher des fenêtres pop-up</translation>
+<translation id="3561217442734750519">Vous devez indiquer un chemin valide comme valeur de clé privée.</translation>
+<translation id="2444609190341826949">Sans mot de passe multiterme, vos mots de passe et autres données chiffrées ne seront pas synchronisés sur cet ordinateur.</translation>
+<translation id="77221669950527621">Extensions ou applications</translation>
+<translation id="6650142020817594541">Ce site recommande Google Chrome Frame (déjà installé).</translation>
+<translation id="6503077044568424649">Les plus visités</translation>
+<translation id="4625904365165566833">Vous n'êtes pas autorisé à vous connecter. Consultez le propriétaire de cet ordinateur portable.</translation>
+<translation id="7450633916678972976">Remarque : Lorsque vous cliquez sur &quot;Envoyer&quot;, Google Chrome joint à votre
+ envoi un journal indiquant votre version de Google Chrome et celle du système
+ d'exploitation utilisé, ainsi que l'URL associée à votre rapport. Vous pouvez
+ également joindre une capture d'écran. Ces informations nous
+ permettent de diagnostiquer les problèmes et d'améliorer les performances de
+ Google Chrome. Les informations personnelles fournies sciemment dans vos
+ commentaires ou involontairement dans le journal, l'URL ou la capture
+ d'écran sont protégées conformément à nos règles de
+ confidentialité. Si vous ne souhaitez pas indiquer d'URL et/ou de capture
+ d'écran, décochez les cases &quot;Inclure cette URL&quot; et/ou &quot;Inclure cette capture d'écran&quot;. Vous acceptez que Google utilise vos commentaires pour améliorer ses produits ou services.</translation>
+<translation id="465365366590259328">Vos modifications seront prises en compte au prochain démarrage de <ph name="PRODUCT_NAME"/>.</translation>
+<translation id="7168109975831002660">Taille de police minimale</translation>
+<translation id="7070804685954057874">Entrée directe</translation>
+<translation id="3265459715026181080">Fermer la fenêtre</translation>
+<translation id="6074871234879228294">Mode de saisie du japonais (pour clavier japonais)</translation>
+<translation id="7855296476260297092">Inscription réussie</translation>
+<translation id="907841381057066561">Échec de création du fichier zip temporaire lors de la création du pack</translation>
+<translation id="1294298200424241932">Modifier les paramètres de confiance :</translation>
+<translation id="1384617406392001144">Votre historique de navigation</translation>
+<translation id="3831099738707437457">&amp;Masquer le panneau de la vérification orthographique</translation>
+<translation id="1040471547130882189">Plug-in ne répondant pas</translation>
+<translation id="5473075389972733037">IBM</translation>
+<translation id="8307664665247532435">Les paramètres seront effacés lors de la prochaine actualisation.</translation>
+<translation id="790025292736025802"><ph name="URL"/> introuvable</translation>
+<translation id="895347679606913382">Démarrage...</translation>
+<translation id="3319048459796106952">Nouvelle fenêtre de nav&amp;igation privée</translation>
+<translation id="5832669303303483065">Ajouter une adresse postale...</translation>
+<translation id="3127919023693423797">Authentification en cours...</translation>
+<translation id="4195643157523330669">Ouvrir dans un nouvel onglet</translation>
+<translation id="8030169304546394654">Déconnecté</translation>
+<translation id="4010065515774514159">Action du navigateur</translation>
+<translation id="4286563808063000730">Le mot de passe multiterme saisi ne peut pas être utilisé, car vous avez déjà chiffré des données avec un mot de passe multiterme. Entrez ci-dessous le mot de passe multiterme actuellement défini pour la synchronisation.</translation>
+<translation id="1154228249304313899">Ouvrir cette page :</translation>
+<translation id="9074348188580488499">Voulez-vous vraiment supprimer tous les mots de passe ?</translation>
+<translation id="6635491740861629599">Sélectionner par domaine</translation>
+<translation id="3627588569887975815">Ouvrir le lien dans une fenêtre en navi&amp;gation privée</translation>
+<translation id="5851868085455377790">Émetteur</translation>
+<translation id="8223496248037436966">Options de saisie automatique</translation>
+<translation id="1470719357688513792">Les nouveaux paramètres des cookies seront appliqués quand vous aurez actualisé la page.</translation>
+<translation id="5578327870501192725">Votre connexion à <ph name="DOMAIN"/> est sécurisée par un chiffrement <ph name="BIT_COUNT"/> bits.</translation>
+<translation id="869884720829132584">Menu Applications</translation>
+<translation id="7764209408768029281">Outi&amp;ls</translation>
+<translation id="1139892513581762545">Onglets latéraux</translation>
+<translation id="7634357567062076565">Reprendre</translation>
+<translation id="4779083564647765204">Zoom</translation>
+<translation id="3282430104564575032">Inspecteur de DOM</translation>
+<translation id="1526560967942511387">Document sans titre</translation>
+<translation id="1291144580684226670">Police standard</translation>
+<translation id="3979748722126423326">Activer <ph name="NETWORKDEVICE"/></translation>
+<translation id="5538307496474303926">Opération en cours...</translation>
+<translation id="4367133129601245178">C&amp;opier l'URL de l'image</translation>
+<translation id="7542995811387359312">La saisie automatique des numéros de carte de paiement est désactivée, car la connexion utilisée par ce formulaire n'est pas sécurisée.</translation>
+<translation id="3494444535872870968">Enregistrer le &amp;cadre sous...</translation>
+<translation id="987264212798334818">Général</translation>
+<translation id="7005812687360380971">Défaillance</translation>
+<translation id="2356070529366658676">Demander</translation>
+<translation id="5731247495086897348">Coller l'URL et y a&amp;ccéder</translation>
+<translation id="8467548439852845758">Pour plus de sécurité, <ph name="PRODUCT_NAME"/> va chiffrer vos mots de passe.</translation>
+<translation id="2524947000814989347">Si vous avez oublié votre mot de passe multiterme, vous devrez arrêter la synchronisation via Google Dashboard.</translation>
+<translation id="8018154597338652331"><ph name="BURNT_AMOUNT"/> sur <ph name="TOTAL_SIZE"/></translation>
+<translation id="7635741716790924709">Adresse ligne 1</translation>
+<translation id="5135533361271311778">Impossible de créer le favori.</translation>
+<translation id="5271247532544265821">Basculer en mode chinois simplifié/traditionnel</translation>
+<translation id="2052610617971448509">Votre système Sandbox n'est pas correctement configuré.</translation>
+<translation id="7384913436093989340">Sélectionnez le <ph name="BEGIN_BOLD"/>menu clé à molette &gt; Préférences &gt; Options avancées &gt; Modifier les paramètres du proxy<ph name="END_BOLD"/> et vérifiez que vos paramètres sont définis sur &quot;sans proxy&quot; ou &quot;direct&quot;.</translation>
+<translation id="6417515091412812850">Impossible de vérifier si le certificat a été révoqué.</translation>
+<translation id="7282743297697561153">Stockage des données</translation>
+<translation id="3363332416643747536"><ph name="DOWNLOAD_RECEIVED"/>/<ph name="DOWNLOAD_TOTAL"/>, Interrompu</translation>
+<translation id="7347702518873971555">Acheter un forfait</translation>
+<translation id="5285267187067365830">Installer le plug-in...</translation>
+<translation id="5334844597069022743">Afficher le code source</translation>
+<translation id="1166212789817575481">Fermer les onglets sur la droite</translation>
+<translation id="6472893788822429178">Afficher le bouton &quot;Accueil&quot;</translation>
+<translation id="4270393598798225102">Version <ph name="NUMBER"/></translation>
+<translation id="534916491091036097">Parenthèse gche</translation>
+<translation id="4157869833395312646">Microsoft Server Gated Cryptography</translation>
+<translation id="8903921497873541725">Zoom avant</translation>
+<translation id="2195729137168608510">Protection du courrier électronique</translation>
+<translation id="1425734930786274278">Les cookies suivants ont été bloqués (tous les cookies tiers sont bloqués, sans exception) :</translation>
+<translation id="6805647936811177813">Connectez-vous à <ph name="TOKEN_NAME"/> pour importer le certificat client de <ph name="HOST_NAME"/></translation>
+<translation id="3437016096396740659">La batterie est chargée.</translation>
+<translation id="6916146760805488559">Créer un nouveau profil...</translation>
+<translation id="1199232041627643649">Maintenez la touche <ph name="KEY_EQUIVALENT"/> enfoncée pour quitter.</translation>
+<translation id="5428562714029661924">Masquer ce plug-in</translation>
+<translation id="7907591526440419938">Ouvrir le fichier</translation>
+<translation id="2568774940984945469">Conteneur de barres d'infos</translation>
+<translation id="8971063699422889582">Le certificat du serveur a expiré.</translation>
+<translation id="8281596639154340028">Utiliser <ph name="HANDLER_TITLE"/></translation>
+<translation id="7134098520442464001">Réduit la taille du texte</translation>
+<translation id="21133533946938348">Épingler l'onglet</translation>
+<translation id="1325040735987616223">Mise à jour du système</translation>
+<translation id="2864069933652346933"><ph name="NUMBER_ZERO"/> days left</translation>
+<translation id="9090669887503413452">Inclure les informations système</translation>
+<translation id="3084771660770137092">Google Chrome n'avait pas suffisamment de mémoire ou le processus de la page Web a été arrêté pour une autre raison. Pour continuer, actualisez la page ou ouvrez-en une autre.</translation>
+<translation id="1114901192629963971">Impossible de valider votre mot de passe sur le réseau actuel. Sélectionnez un autre réseau.</translation>
+<translation id="5179510805599951267">Cette page n'est pas rédigée en <ph name="ORIGINAL_LANGUAGE"/> ? Signaler l'erreur</translation>
+<translation id="6430814529589430811">Certificat unique codé Base 64 ASCII</translation>
+<translation id="5143712164865402236">Activer le mode plein écran</translation>
+<translation id="8434177709403049435">Codag&amp;e</translation>
+<translation id="4051923669149193910"><ph name="HANDLER_TITLE"/> est déjà utilisé pour gérer les liens <ph name="PROTOCOL"/>://.</translation>
+<translation id="2722201176532936492">Touches de sélection</translation>
+<translation id="385120052649200804">Clavier international américain</translation>
+<translation id="9012607008263791152">Je comprends que la visite de ce site peut être préjudiciable à mon ordinateur.</translation>
+<translation id="6640442327198413730">Ressource cache manquante.</translation>
+<translation id="1441458099223378239">Impossible d'accéder à mon compte</translation>
+<translation id="5793220536715630615">C&amp;opier l'URL de la vidéo</translation>
+<translation id="523397668577733901">Vous préférez <ph name="BEGIN_LINK"/>parcourir la galerie<ph name="END_LINK"/> ?</translation>
+<translation id="2922350208395188000">Impossible de vérifier le certificat du serveur.</translation>
+<translation id="3778740492972734840">Outils de &amp;développement</translation>
+<translation id="8335971947739877923">Exporter...</translation>
+<translation id="5680966941935662618">Paramètres de saisie automatique</translation>
+<translation id="38385141699319881">Téléchargement de l'image en cours...</translation>
+<translation id="6004539838376062211">&amp;Options du vérificateur d'orthographe</translation>
+<translation id="5350198318881239970">Impossible d'ouvrir votre profil correctement.\n\nIl est possible que certaines fonctionnalités ne soient pas disponibles. Vérifiez que ce profil existe et que vous disposez d'une autorisation d'accès à son contenu en lecture et en écriture.</translation>
+<translation id="4058793769387728514">Vérifier le document maintenant</translation>
+<translation id="1810107444790159527">Zone de liste</translation>
+<translation id="3338239663705455570">Clavier slovène</translation>
+<translation id="1859234291848436338">Sens de l'écriture</translation>
+<translation id="4567836003335927027">Vos données sur <ph name="WEBSITE_1"/></translation>
+<translation id="756445078718366910">Ouvrir une fenêtre du navigateur</translation>
+<translation id="4126154898592630571">Conversion de la date et de l'heure</translation>
+<translation id="5088534251099454936">PKCS #1 SHA-512 avec chiffrement RSA</translation>
+<translation id="6392373519963504642">Clavier coréen</translation>
+<translation id="7887334752153342268">Dupliquer</translation>
+<translation id="4980691186726139495">Ne pas conserver sur cette page</translation>
+<translation id="3081523290047420375">Désactiver <ph name="CLOUD_PRINT_NAME"/></translation>
+<translation id="9207194316435230304">ATOK</translation>
+<translation id="9026731007018893674">téléchargement</translation>
+<translation id="7646591409235458998">E-mail :</translation>
+<translation id="703748601351783580">Ouvrir tous les favoris dans une nouvelle &amp;fenêtre</translation>
+<translation id="6199775032047436064">Rafraîchir la page actuelle</translation>
+<translation id="6981982820502123353">Accessibilité</translation>
+<translation id="112343676265501403">Exceptions pour les plug-ins</translation>
+<translation id="770273299705142744">Remplissage automatique des formulaires</translation>
+<translation id="7210998213739223319">Nom d'utilisateur</translation>
+<translation id="4478664379124702289">Enregistrer le lie&amp;n sous...</translation>
+<translation id="8725066075913043281">Réessayer</translation>
+<translation id="8502249598105294518">Personnaliser et configurer <ph name="PRODUCT_NAME"/></translation>
+<translation id="7392089327262158658">Préférences de saisie automatique <ph name="PRODUCT_NAME_SHORT"/></translation>
+<translation id="4163521619127344201">Votre position géographique</translation>
+<translation id="3797008485206955964">Afficher les pages en arrière-plan (<ph name="NUM_BACKGROUND_APPS"/>)</translation>
+<translation id="8590375307970699841">Configurer les mises à jour automatiques</translation>
+<translation id="2797524280730715045">il y a <ph name="NUMBER_DEFAULT"/> heures</translation>
+<translation id="265390580714150011">Valeur du champ</translation>
+<translation id="9073247318500677671">Les dernières versions d'Unity et GNOME (ainsi que la prochaine version d'Ubuntu, Natty Narwhal) affichent une barre de menus de type OSX sur toute la largeur supérieure de l'écran.</translation>
+<translation id="3869917919960562512">Index erroné.</translation>
+<translation id="7031962166228839643">Préparation du module de plate-forme sécurisée (TPM) en cours. Veuillez patienter, l'opération peut prendre quelques minutes.</translation>
+<translation id="4250377793615429299">Nombre de copies incorrect</translation>
+<translation id="7180865173735832675">Personnaliser</translation>
+<translation id="5737306429639033676">Prédire les actions du réseau pour améliorer les performances de chargement des pages</translation>
+<translation id="8123426182923614874">Données restantes :</translation>
+<translation id="3707020109030358290">N'est pas une autorité de certification.</translation>
+<translation id="2115926821277323019">L'URL doit être valide.</translation>
+<translation id="8986494364107987395">Envoyer automatiquement les statistiques d'utilisation et les rapports d'erreur à Google</translation>
+<translation id="7070714457904110559">Cette fonctionnalité active la géolocalisation dans les extensions expérimentales. Cela implique l'utilisation des API de localisation du système d'exploitation (si disponibles) et l'envoi de données sur la configuration réseau locale au service de localisation de Google afin de déterminer une position précise.</translation>
+<translation id="6701535245008341853">Impossible de charger le profil.</translation>
+<translation id="527605982717517565">Toujours exécuter JavaScript sur <ph name="HOST"/></translation>
+<translation id="702373420751953740">Version PRL :</translation>
+<translation id="1307041843857566458">Confirmer la réactivation</translation>
+<translation id="8314308967132194952">Ajouter une adresse postale...</translation>
+<translation id="1221024147024329929">PKCS #1 MD2 avec chiffrement RSA</translation>
+<translation id="853265131227167869">Dim.^Lun.^Mar.^Mer.^Jeu.^Ven.^Sam.</translation>
+<translation id="3323447499041942178">Zone de saisie</translation>
+<translation id="580571955903695899">Trier par nom</translation>
+<translation id="5230516054153933099">Fenêtre</translation>
+<translation id="7554791636758816595">Nouvel onglet</translation>
+<translation id="5503844897713343920">Vous tentez d'accéder au site <ph name="DOMAIN"/>, mais le certificat présenté par le serveur a été révoqué par son émetteur. Cela signifie que les informations d'identification présentées par le serveur ne sont pas approuvées. Vous communiquez peut-être avec un pirate informatique. Nous vous déconseillons vivement de continuer.</translation>
+<translation id="6928853950228839340">Composition hors écran</translation>
+<translation id="1308727876662951186"><ph name="NUMBER_ZERO"/> mins left</translation>
+<translation id="7671576867600624">Technologie :</translation>
+<translation id="1103966635949043187">Accédez à la page d'accueil du site :</translation>
+<translation id="1951332921786364801">Configurer la communication à distance</translation>
+<translation id="1086613338090581534">L'émetteur d'un certificat n'ayant pas expiré est tenu d'assurer la maintenance de ce qui s'appelle &quot;une liste de révocation&quot;. Si un certificat est compromis, l'émetteur peut le révoquer en l'ajoutant à la liste de révocation. Ce certificat n'est alors plus approuvé par votre navigateur. Il n'est pas nécessaire d'assurer la maintenance de l'état &quot;révoqué&quot; des certificats expirés. Donc, bien qu'un certificat ait été qualifié de valide pour le site Web que vous visitez actuellement, il est impossible de déterminer s'il a été, depuis, compromis puis révoqué ou s'il est toujours valide. Par conséquent, il n'est pas possible de s'assurer si vous communiquez avec un site Web légitime ou si le certificat a été compromis et se trouve maintenant en la possession d'un pirate informatique avec lequel vous communiquez. Ne poursuivez pas.</translation>
+<translation id="2645575947416143543">Néanmoins, si vous travaillez dans une entreprise qui génère ses propres certificats, et que vous essayez de vous connecter au site Web interne de l'entreprise avec un certificat de ce type, vous pouvez résoudre ce problème en toute sécurité. Pour ce faire, importez le certificat racine de l'entreprise en tant que &quot;certificat racine&quot;. Par la suite, les certificats émis ou vérifiés par votre entreprise seront approuvés et vous ne verrez plus cette erreur lorsque vous tenterez de vous connecter à nouveau au site Web interne. Contactez le support informatique de votre entreprise pour savoir comment ajouter un nouveau certificat racine sur votre ordinateur.</translation>
+<translation id="376466258076168640">Définir <ph name="PRODUCT_NAME"/> en tant que navigateur par défaut</translation>
+<translation id="1056898198331236512">Avertissement</translation>
+<translation id="8630826211403662855">Préférences de recherche</translation>
+<translation id="8432745813735585631">Clavier Colemak américain</translation>
+<translation id="8151639108075998630">Activer la navigation en tant qu'invité</translation>
+<translation id="2608770217409477136">Utiliser les paramètres par défaut</translation>
+<translation id="3157931365184549694">Rétablir</translation>
+<translation id="7426243339717063209">Désinstaller &quot;<ph name="EXTENSION_NAME"/>&quot; ?</translation>
+<translation id="996250603853062861">Établissement de la connexion sécurisée...</translation>
+<translation id="6059232451013891645">Dossier :</translation>
+<translation id="4274292172790327596">Erreur non reconnue</translation>
+<translation id="760537465793895946">Consultez les conflits connus avec des modules tiers.</translation>
+<translation id="7042418530779813870">Co&amp;ller et rechercher</translation>
+<translation id="9110447413660189038">&amp;Remonter</translation>
+<translation id="375403751935624634">Échec de la traduction en raison d'une erreur de serveur</translation>
+<translation id="2101225219012730419">Version :</translation>
+<translation id="1570242578492689919">Polices et codage</translation>
+<translation id="3082374807674020857"><ph name="PAGE_TITLE"/> - <ph name="PAGE_URL"/></translation>
+<translation id="8050038245906040378">Signature du code commercial Microsoft</translation>
+<translation id="3031557471081358569">Sélectionnez les éléments à importer :</translation>
+<translation id="1368832886055348810">De gauche à droite</translation>
+<translation id="3031433885594348982">Votre connexion à <ph name="DOMAIN"/> est sécurisée par le biais d'un faible chiffrement.</translation>
+<translation id="4047345532928475040">sans objet</translation>
+<translation id="5604324414379907186">Toujours afficher la barre de favoris</translation>
+<translation id="3220630151624181591">Activer l'onglet 2</translation>
+<translation id="8898139864468905752">Aperçu des onglets</translation>
+<translation id="2799223571221894425">Redémarrer</translation>
+<translation id="5771816112378578655">Configuration en cours...</translation>
+<translation id="1197979282329025000">Une erreur s'est produite lors de la récupération des fonctions de l'imprimante <ph name="PRINTER_NAME"/>. Cette imprimante n'a pas pu être enregistrée dans <ph name="CLOUD_PRINT_NAME"/>.</translation>
+<translation id="8820901253980281117">Exceptions pour les fenêtres pop-up</translation>
+<translation id="1143142264369994168">Signataire du certificat </translation>
+<translation id="904949795138183864">La page Web <ph name="URL"/> n'existe plus.</translation>
+<translation id="3228279582454007836">Vous n'avez jamais visité ce site auparavant.</translation>
+<translation id="2159017110205600596">Personnaliser...</translation>
+<translation id="5449716055534515760">Fe&amp;rmer la fenêtre</translation>
+<translation id="2814489978934728345">Arrêter le chargement de cette page</translation>
+<translation id="2354001756790975382">Autres favoris</translation>
+<translation id="8561574028787046517"><ph name="PRODUCT_NAME"/> a été mis à jour.</translation>
+<translation id="5234325087306733083">Mode hors connexion</translation>
+<translation id="1779392088388639487">Erreur d'importation de fichier PKCS #12</translation>
+<translation id="166278006618318542">Algorithme de clé publique de l'objet</translation>
+<translation id="5759272020525228995">Le site Web a rencontré une erreur lors de l'extraction de <ph name="URL"/>.
+ Cela peut être dû à une opération de maintenance ou à une configuration incorrecte.</translation>
+<translation id="641480858134062906">Échec du chargement de la page <ph name="URL"/></translation>
+<translation id="3693415264595406141">Mot de passe :</translation>
+<translation id="74568296546932365">Conserver <ph name="PAGE_TITLE"/> en tant que moteur de recherche par défaut</translation>
+<translation id="8602184400052594090">Fichier manifeste absent ou illisible</translation>
+<translation id="2784949926578158345">La connexion a été réinitialisée.</translation>
+<translation id="6663792236418322902">Le mot de passe choisi vous sera demandé pour restaurer le fichier. Veillez à le conserver en lieu sûr.</translation>
+<translation id="4532822216683966758">La vérification de la provenance du certificat DNS est activée, ce qui peut entraîner l'envoi d'informations privées à Google.</translation>
+<translation id="6321196148033717308">À propos de la reconnaissance vocale</translation>
+<translation id="3412265149091626468">Aller à la sélection</translation>
+<translation id="8167737133281862792">Ajouter un certificat</translation>
+<translation id="2911372483530471524">Espaces de noms PID</translation>
+<translation id="6093374025603915876">Préférences de saisie automatique</translation>
+<translation id="8584134039559266300">Activer l'onglet 8</translation>
+<translation id="5189060859917252173">Le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; représente une autorité de certification.</translation>
+<translation id="3785852283863272759">Envoyer par e-mail l'emplacement de la page</translation>
+<translation id="2255317897038918278">Enregistrement des informations de date Microsoft</translation>
+<translation id="3493881266323043047">Validité</translation>
+<translation id="5979421442488174909">&amp;Traduire en <ph name="LANGUAGE"/></translation>
+<translation id="7326526699920221209">Batterie : <ph name="PRECENTAGE"/> %</translation>
+<translation id="952992212772159698">Désactivé</translation>
+<translation id="8299269255470343364">Japonais</translation>
+<translation id="5187826826541650604"><ph name="KEY_NAME"/> (<ph name="DEVICE"/>)</translation>
+<translation id="6429639049555216915">L'application est actuellement inaccessible.</translation>
+<translation id="2144536955299248197">Lecteur du certificat : <ph name="CERTIFICATE_NAME"/></translation>
+<translation id="50030952220075532"><ph name="NUMBER_ONE"/> jour restant</translation>
+<translation id="2885378588091291677">Gestionnaire de tâches</translation>
+<translation id="5792852254658380406">Gérer les extensions...</translation>
+<translation id="2359808026110333948">Continuer</translation>
+<translation id="176759384517330673">Synchronisation avec <ph name="USER_EMAIL_ADDRESS"/> effectuée. Dernière synchronisation : <ph name="LAST_SYNC_TIME"/></translation>
+<translation id="1618661679583408047">Le certificat de sécurité du site n'est pas encore valide !</translation>
+<translation id="7039912931802252762">Ouverture de session par carte à puce Microsoft</translation>
+<translation id="6285074077487067719">Format</translation>
+<translation id="3065140616557457172">Tapez votre requête ou saisissez une URL pour commencer la navigation : c'est à vous de choisir.</translation>
+<translation id="5509693895992845810">Enregistrer &amp;sous...</translation>
+<translation id="5986279928654338866">Le serveur <ph name="DOMAIN"/> requiert un nom d'utilisateur et un mot de passe.</translation>
+<translation id="521467793286158632">Supprimer tous les mots de passe</translation>
+<translation id="2491120439723279231">Le certificat du serveur contient des erreurs.</translation>
+<translation id="4448844063988177157">Recherche de réseaux Wi-Fi...</translation>
+<translation id="5765780083710877561">Description :</translation>
+<translation id="338583716107319301">Séparateur</translation>
+<translation id="2079053412993822885">Si vous supprimez l'un de vos propres certificats, vous ne pouvez plus l'utiliser pour vous identifier.</translation>
+<translation id="7221869452894271364">Rafraîchir cette page</translation>
+<translation id="6791443592650989371">État d'activation :</translation>
+<translation id="4801257000660565496">Créer des raccourcis vers des applications</translation>
+<translation id="6503256918647795660">Clavier franco-suisse</translation>
+<translation id="6175314957787328458">GUID de domaine Microsoft</translation>
+<translation id="8179976553408161302">Entrer</translation>
+<translation id="8261506727792406068">Supprimer</translation>
+<translation id="4404805853119650018">Échec de l'enregistrement de cet ordinateur pour l'accès à distance.</translation>
+<translation id="345693547134384690">Ouvrir l'&amp;image dans un nouvel onglet</translation>
+<translation id="7422192691352527311">Préférences...</translation>
+<translation id="354211537509721945">L'administrateur a désactivé les mises à jour.</translation>
+<translation id="1375198122581997741">À propos de la version</translation>
+<translation id="7915471803647590281">Veuillez nous indiquer ce qu'il se passe avant d'envoyer votre rapport.</translation>
+<translation id="5725124651280963564">Connectez-vous à <ph name="TOKEN_NAME"/> afin de générer une clé pour <ph name="HOST_NAME"/>.</translation>
+<translation id="8418113698656761985">Clavier roumain</translation>
+<translation id="5976160379964388480">Autres</translation>
+<translation id="3665842570601375360">Sécurité :</translation>
+<translation id="1430915738399379752">Imprimer</translation>
+<translation id="7999087758969799248">Mode de saisie standard</translation>
+<translation id="2635276683026132559">Signature</translation>
+<translation id="4835836146030131423">Erreur lors de la connexion</translation>
+<translation id="7715454002193035316">Pour cette session uniquement</translation>
+<translation id="2475982808118771221">Une erreur s'est produite.</translation>
+<translation id="3324684065575061611">(Désactivé par une stratégie d'entreprise)</translation>
+<translation id="7385854874724088939">Erreur lors de la tentative d'impression. Vérifiez votre imprimante et réessayez.</translation>
+<translation id="770015031906360009">Grec</translation>
+<translation id="3834901049798243128">Ignorer les exceptions et bloquer l'enregistrement des cookies tiers</translation>
+<translation id="8116152017593700047">Cet outil vous permet de sélectionner une capture d'écran enregistrée. Aucune capture d'écran n'est disponible pour le moment. Appuyez simultanément sur Ctrl et sur la touche &quot;Mode Présentation&quot; pour enregistrer une capture d'écran. Vos trois dernières captures apparaissent ici.</translation>
+<translation id="3454157711543303649">Activation effectuée</translation>
+<translation id="884923133447025588">Aucun système de révocation trouvé</translation>
+<translation id="556042886152191864">Bouton</translation>
+<translation id="1352060938076340443">Interrompu</translation>
+<translation id="8571226144504132898">Dictionnaire de symboles</translation>
+<translation id="7229570126336867161">Technologie EvDo requise</translation>
+<translation id="7582844466922312471">Internet mobile</translation>
+<translation id="945522503751344254">Envoyer le commentaire</translation>
+<translation id="4539401194496451708">Associé au profil Chrome <ph name="USER_EMAIL_ADDRESS"/>. Dernière synchronisation : <ph name="LAST_SYNC_TIME"/></translation>
+<translation id="7369847606959702983">Carte de crédit (autre)</translation>
+<translation id="6867459744367338172">Langues et saisie</translation>
+<translation id="7671130400130574146">Utiliser la barre de titre et les bordures de fenêtre du système</translation>
+<translation id="9170848237812810038">Ann&amp;uler</translation>
+<translation id="284970761985428403"><ph name="ASCII_NAME"/> (<ph name="UNICODE_NAME"/>)</translation>
+<translation id="3903912596042358459">Le serveur a refusé d'exécuter la demande.</translation>
+<translation id="8135557862853121765"><ph name="NUM_KILOBYTES"/> Ko</translation>
+<translation id="4444364671565852729"><ph name="PRODUCT_NAME"/> a été mis à jour vers la version <ph name="VERSION"/>.</translation>
+<translation id="5819890516935349394">Navigateur de contenu</translation>
+<translation id="2731392572903530958">&amp;Rouvrir la fenêtre fermée</translation>
+<translation id="1254593899333212300">Se connecter directement à Internet</translation>
+<translation id="6107012941649240045">Émis pour</translation>
+<translation id="6483805311199035658">Ouverture de <ph name="FILE"/> en cours</translation>
+<translation id="3576278878016363465">Cibles disponibles pour l'image</translation>
+<translation id="895541991026785598">Signaler un problème</translation>
+<translation id="940425055435005472">Taille de police :</translation>
+<translation id="494286511941020793">Aide pour la configuration de proxy</translation>
+<translation id="2765217105034171413">Petite</translation>
+<translation id="1285266685456062655"><ph name="NUMBER_FEW"/> hours ago</translation>
+<translation id="9154176715500758432">Rester sur cette page</translation>
+<translation id="5875565123733157100">Type de bug :</translation>
+<translation id="6988771638657196063">Inclure cette URL :</translation>
+<translation id="5717920936024713315">Cookies et données de site...</translation>
+<translation id="3842552989725514455">Police Serif</translation>
+<translation id="1949795154112250744"><ph name="BEGIN_BOLD"/>Avertissement :<ph name="END_BOLD"/> <ph name="PRODUCT_NAME"/> ne peut pas empêcher les extensions d'enregistrer votre historique de navigation. Pour désactiver cette extension en mode navigation privée, désélectionnez-la.</translation>
+<translation id="4440967101351338638">ChromiumOs Image Burn</translation>
+<translation id="1813278315230285598">Services</translation>
+<translation id="6860097299815761905">Paramètres du proxy...</translation>
+<translation id="373572798843615002">1 onglet</translation>
+<translation id="4162393307849942816"><ph name="BEGIN_BOLD"/>Vous naviguez en tant qu'invité<ph name="END_BOLD"/>. Les pages que vous consultez dans cette fenêtre n'apparaîtront pas dans l'historique de votre navigateur ni dans votre historique des recherches. Les autres traces telles que les cookies seront supprimées de l'ordinateur à la fin de votre session. En revanche, les fichiers téléchargés et les favoris créés seront conservés.
+ <ph name="LINE_BREAK"/>
+ <ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/> sur le mode invité</translation>
+<translation id="827924395145979961">Chargement des pages impossible</translation>
+<translation id="3092544800441494315">Inclure cette capture d'écran :</translation>
+<translation id="7714464543167945231">Certificat</translation>
+<translation id="5530864958284331435">$1 fichiers sélectionnés, $2</translation>
+<translation id="3616741288025931835">&amp;Effacer les données de navigation...</translation>
+<translation id="3313622045786997898">Valeur de signature du certificat</translation>
+<translation id="8535005006684281994">URL de renouvellement du certificat Netscape</translation>
+<translation id="2440604414813129000">Afficher la s&amp;ource</translation>
+<translation id="816095449251911490"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/>, <ph name="TIME_REMAINING"/></translation>
+<translation id="8200772114523450471">Reprendre</translation>
+<translation id="6358975074282722691"><ph name="NUMBER_TWO"/> secs ago</translation>
+<translation id="5423849171846380976">Activé</translation>
+<translation id="6748105842970712833">Carte SIM désactivée</translation>
+<translation id="7323391064335160098">Compatibilité avec VPN</translation>
+<translation id="3929673387302322681">Développement - Instable</translation>
+<translation id="4251486191409116828">Échec de création du raccourci vers l'application</translation>
+<translation id="5190835502935405962">Barre de favoris</translation>
+<translation id="7828272290962178636">Le serveur est en mesure de répondre à la demande.</translation>
+<translation id="7823073559911777904">Modifier les paramètres du proxy...</translation>
+<translation id="5438430601586617544">(non empaquetée)</translation>
+<translation id="6460601847208524483">Rechercher le suivant</translation>
+<translation id="8433186206711564395">Paramètres réseau</translation>
+<translation id="4856478137399998590">Votre service Internet mobile est activé et prêt à l'emploi.</translation>
+<translation id="1676388805288306495">Modifier la police et la langue par défaut des pages Web</translation>
+<translation id="8969761905474557563">Composition graphique avec accélération matérielle</translation>
+<translation id="3937640725563832867">Autre nom de l'émetteur du certificat</translation>
+<translation id="4701488924964507374"><ph name="SENTENCE1"/> <ph name="SENTENCE2"/></translation>
+<translation id="1163931534039071049">&amp;Afficher le code source du cadre</translation>
+<translation id="8770196827482281187">Mode de saisie du persan (clavier ISIRI 2901)</translation>
+<translation id="6423239382391657905">OpenVPN</translation>
+<translation id="7564847347806291057">Arrêter le processus</translation>
+<translation id="1607220950420093847">Votre compte a peut-être été supprimé ou désactivé. Veuillez vous déconnecter.</translation>
+<translation id="5613695965848159202">Authentification anonyme :</translation>
+<translation id="2233320200890047564">Bases de données indexées</translation>
+<translation id="7063412606254013905">En savoir plus sur les escroqueries par phishing</translation>
+<translation id="307767688111441685">Page à l'apparence anormale</translation>
+<translation id="9076523132036239772">Adresse e-mail ou mot de passe incorrect. Essayez tout d'abord de vous connecter à un réseau.</translation>
+<translation id="6965978654500191972">Périphérique</translation>
+<translation id="1242521815104806351">Informations sur la connexion</translation>
+<translation id="5295309862264981122">Confirmer la navigation</translation>
+<translation id="1492817554256909552">Nom du point d'accès :</translation>
+<translation id="5546865291508181392">Rechercher</translation>
+<translation id="1999115740519098545">Au démarrage</translation>
+<translation id="2983818520079887040">Paramètres...</translation>
+<translation id="1465619815762735808">Lire en un clic</translation>
+<translation id="6941937518557314510">Connectez-vous à <ph name="TOKEN_NAME"/> pour vous authentifier auprès de <ph name="HOST_NAME"/> avec votre certificat.</translation>
+<translation id="2783600004153937501">Votre administrateur informatique a désactivé certaines options.</translation>
+<translation id="2099686503067610784">Supprimer le certificat de serveur &quot;<ph name="CERTIFICATE_NAME"/>&quot;?</translation>
+<translation id="9027603907212475920">Configurer la synchronisation...</translation>
+<translation id="6873213799448839504">Valider automatiquement une chaîne</translation>
+<translation id="7238585580608191973">Empreinte SHA-256</translation>
+<translation id="2501278716633472235">Retour</translation>
+<translation id="131461803491198646">Réseau domestique, sans itinérance</translation>
+<translation id="7377249249140280793"><ph name="RELATIVE_DATE"/> - <ph name="FULL_DATE"/></translation>
+<translation id="5679279978772703611">Gérer les mots de passe enregistrés...</translation>
+<translation id="4551440281920791563">Sélectionnez
+ <ph name="BEGIN_BOLD"/>
+ Menu clé à molette &gt; Options &gt; Options avancées &gt; Modifier les paramètres du proxy &gt; Paramètres réseau
+ <ph name="END_BOLD"/>
+ et désélectionnez l'option &quot;Utiliser un serveur proxy pour votre réseau local&quot;.</translation>
+<translation id="1285320974508926690">Ne jamais traduire ce site</translation>
+<translation id="8954894007019320973">(suite)</translation>
+<translation id="3748412725338508953">Trop de redirections</translation>
+<translation id="5833726373896279253">Ces paramètres ne peuvent être modifiés que par le propriétaire :</translation>
+<translation id="6858960932090176617">Active la protection XSS Auditor de WebKit (protection contre le Cross-site Scripting), une fonctionnalité qui vous protège de certaines attaques de sites malveillants et offre une sécurité accrue, mais qui n'est pas compatible avec tous les sites Web.</translation>
+<translation id="6005282720244019462">Clavier latino-américain</translation>
+<translation id="8831104962952173133">Phishing détecté !</translation>
+<translation id="5141720258550370428">Voulez-vous utiliser <ph name="HANDLER_TITLE"/> (<ph name="HANDLER_HOSTNAME"/>) pour gérer les liens <ph name="PROTOCOL"/>:// à partir de maintenant ?</translation>
+<translation id="6751344591405861699"><ph name="WINDOW_TITLE"/> (Navigation privée)</translation>
+<translation id="6681668084120808868">Prendre une photo</translation>
+<translation id="780301667611848630">Non merci</translation>
+<translation id="2812989263793994277">Ne pas afficher les images</translation>
+<translation id="7190251665563814471">Toujours autoriser ces plug-ins sur <ph name="HOST"/></translation>
+<translation id="6845383723252244143">Sélectionner un dossier</translation>
+<translation id="8925458182817574960">&amp;Paramètres</translation>
+<translation id="6361850914223837199">Informations sur l'erreur :</translation>
+<translation id="8948393169621400698">Toujours autoriser les plug-ins sur <ph name="HOST"/></translation>
+<translation id="3865082058368813534">Effacer les données de saisie automatique enregistrées</translation>
+<translation id="8288345061925649502">Changer de moteur de recherche</translation>
+<translation id="5436492226391861498">En attente du tunnel proxy...</translation>
+<translation id="3803991353670408298">Veuillez ajouter un autre mode de saisie avant de supprimer celui-ci.</translation>
+<translation id="1095623615273566396"><ph name="NUMBER_FEW"/> secondes</translation>
+<translation id="7006788746334555276">Paramètres de contenu</translation>
+<translation id="3369521687965833290">Impossible d'extraire les fichiers de l'extension. Pour effectuer cette opération en toute sécurité, vous devez disposer d'un chemin d'accès à votre répertoire de profils commençant par une lettre de lecteur et ne contenant ni jonction, ni point de montage, ni lien symbolique. Aucun chemin de ce type n'existe pour votre profil.</translation>
+<translation id="337920581046691015"><ph name="PRODUCT_NAME"/> va être installé.</translation>
+<translation id="6282194474023008486">Code postal</translation>
+<translation id="7733107687644253241">En bas à droite</translation>
+<translation id="5139955368427980650">&amp;Ouvrir</translation>
+<translation id="8136149669168180907"><ph name="DOWNLOADED_AMOUNT"/> téléchargé(s) sur <ph name="TOTAL_SIZE"/></translation>
+<translation id="7375268158414503514">Commentaires d'ordre général/Autres</translation>
+<translation id="4643612240819915418">Ou&amp;vrir la vidéo dans un nouvel onglet</translation>
+<translation id="7997479212858899587">Identité :</translation>
+<translation id="8300849813060516376">Échec de l'opération OTASP</translation>
+<translation id="2213819743710253654">Action sur la page</translation>
+<translation id="1317130519471511503">Modifier des éléments...</translation>
+<translation id="6391538222494443604">Le répertoire d'extensions est obligatoire.</translation>
+<translation id="8051695050440594747"><ph name="MEGABYTES"/> Mo disponibles</translation>
+<translation id="7088615885725309056">Ancien</translation>
+<translation id="461656879692943278"><ph name="HOST_NAME"/> fournit du contenu provenant de <ph name="ELEMENTS_HOST_NAME"/>, un site connu pour distribuer des logiciels malveillants. Votre ordinateur pourrait être infecté par un virus si vous consultez ce site.</translation>
+<translation id="1387022316521171484">Ces fonctionnalités expérimentales sont susceptibles d'être modifiées, interrompues ou supprimées à tout moment. Nous ne fournissons aucune garantie quant aux effets de leur activation. Votre navigateur pourrait bien prendre feu. Trêve de plaisanterie, il est possible que votre navigateur supprime toutes vos données ou que votre sécurité et votre vie privée soient compromises de manière inattendue. Nous vous prions d'agir avec précaution.</translation>
+<translation id="2143778271340628265">Configuration manuelle du proxy</translation>
+<translation id="5294529402252479912">Mettre à jour Adobe Reader maintenant</translation>
+<translation id="5263972071113911534"><ph name="NUMBER_MANY"/> days ago</translation>
+<translation id="7461850476009326849">Désactiver les plug-ins individuels...</translation>
+<translation id="4097411759948332224">Envoyer une capture d'écran de la page en cours</translation>
+<translation id="2231990265377706070">Point d'exclamation</translation>
+<translation id="7199540622786492483"><ph name="PRODUCT_NAME"/> n'est plus à jour, car il n'a pas été relancé depuis quelque temps. La mise à jour disponible sera installée dès que vous le relancerez.</translation>
+<translation id="8652722422052983852">Petit problème... Tentons de le résoudre.</translation>
+<translation id="5970231080121144965">Cette fonctionnalité permet d'établir des correspondances entre les sous-chaînes et plusieurs fragments d'URL figurant dans l'historique.</translation>
+<translation id="4665674675433053715">Page &quot;Nouvel onglet&quot; expérimentale</translation>
+<translation id="3726527440140411893">Les cookies suivants étaient autorisés lorsque vous avez consulté cette page :</translation>
+<translation id="3320859581025497771">votre opérateur</translation>
+<translation id="8828781037212165374">Activer ces fonctionnalités...</translation>
+<translation id="8562413501751825163">Quitter Firefox avant l'importation</translation>
+<translation id="3435541101098866721">Ajouter un nouveau téléphone</translation>
+<translation id="2448046586580826824">Proxy HTTP sécurisé</translation>
+<translation id="4032534284272647190">Accès à <ph name="URL"/> refusé.</translation>
+<translation id="4928569512886388887">Finalisation de la mise à jour du système...</translation>
+<translation id="8258002508340330928">Voulez-vous continuer ?</translation>
+<translation id="4309420042698375243"><ph name="NUM_KILOBYTES"/> Ko (<ph name="NUM_KILOBYTES_LIVE"/> Ko effectifs)</translation>
+<translation id="5554573843028719904">Autre réseau Wi-Fi...</translation>
+<translation id="5034259512732355072">Choisir un autre répertoire...</translation>
+<translation id="8885905466771744233">L'extension indiquée est déjà associée à une clé privée. Utilisez cette clé ou supprimez-la.</translation>
+<translation id="7831504847856284956">Ajouter une adresse</translation>
+<translation id="7505152414826719222">Stockage local</translation>
+<translation id="2541423446708352368">Afficher tous les téléchargements</translation>
+<translation id="4381021079159453506">Navigateur de contenu</translation>
+<translation id="8109246889182548008">Magasin de certificats</translation>
+<translation id="5030338702439866405">Émis par</translation>
+<translation id="5280833172404792470">Quitter le mode plein écran (<ph name="ACCELERATOR"/>)</translation>
+<translation id="2728127805433021124">Le certificat du serveur a été signé avec un algorithme de signature faible.</translation>
+<translation id="2137808486242513288">Ajouter un utilisateur</translation>
+<translation id="6193618946302416945">Me proposer de traduire les pages qui sont écrites dans une langue que je ne sais pas lire</translation>
+<translation id="129553762522093515">Récemment fermés</translation>
+<translation id="4287167099933143704">Saisir la clé de déverrouillage du code PIN</translation>
+<translation id="8355915647418390920"><ph name="NUMBER_FEW"/> jours</translation>
+<translation id="3129140854689651517">Rechercher du texte</translation>
+<translation id="7221585318879598658">Sans-Serif</translation>
+<translation id="5558129378926964177">Zoom &amp;avant</translation>
+<translation id="6451458296329894277">Confirmer le nouvel envoi du formulaire</translation>
+<translation id="5116333507878097773"><ph name="NUMBER_ONE"/> heure</translation>
+<translation id="8028152732786498049">Cet élément doit être installé depuis <ph name="CHROME_WEB_STORE"/>.</translation>
+<translation id="9199258761842902152">Mise en veille ou reprise</translation>
+<translation id="1851266746056575977">Mettre à jour maintenant</translation>
+<translation id="7017219178341817193">Ajouter une page</translation>
+<translation id="1038168778161626396">Chiffrer seulement</translation>
+<translation id="2756651186786928409">Ne jamais intervertir les touches de modification</translation>
+<translation id="1217515703261622005">Conversion des numéros spéciaux</translation>
+<translation id="7179921470347911571">Relancer maintenant</translation>
+<translation id="3715099868207290855">Synchronisation avec <ph name="USER_EMAIL_ADDRESS"/> effectuée</translation>
+<translation id="2679312662830811292">il y a <ph name="NUMBER_ONE"/> minute</translation>
+<translation id="9065203028668620118">Édition</translation>
+<translation id="4718464510840275738">Préférences synchronisées</translation>
+<translation id="8788572795284305350"><ph name="NUMBER_ZERO"/> hours ago</translation>
+<translation id="1177863135347784049">Personnalisé</translation>
+<translation id="8236028464988198644">Rechercher à partir de la barre d'adresse</translation>
+<translation id="4881695831933465202">Ouvrir</translation>
+<translation id="5988520580879236902">Inspecter les vues actives :</translation>
+<translation id="3593965109698325041">Contraintes de nom du certificat</translation>
+<translation id="4358697938732213860">Ajouter une adresse</translation>
+<translation id="8396532978067103567">Mot de passe incorrect.</translation>
+<translation id="5981759340456370804">Statistiques avancées</translation>
+<translation id="8160015581537295331">Clavier espagnol</translation>
+<translation id="3505920073976671674">Sélectionnez votre réseau</translation>
+<translation id="6644971472240498405"><ph name="NUMBER_ONE"/> jour</translation>
+<translation id="1782924894173027610">Le serveur de synchronisation est occupé. Veuillez réessayer ultérieurement.</translation>
+<translation id="6512448926095770873">Quitter cette page</translation>
+<translation id="5457599981699367932">Naviguer en tant qu'invité</translation>
+<translation id="3169472444629675720">Discover</translation>
+<translation id="6294193300318171613">&amp;Toujours afficher la barre de favoris</translation>
+<translation id="4088820693488683766">Options de recherche</translation>
+<translation id="3414952576877147120">Taille :</translation>
+<translation id="9098468523912235228">il y a <ph name="NUMBER_DEFAULT"/> secondes</translation>
+<translation id="7009102566764819240">La liste suivante fait état des éléments dangereux détectés sur la page. Cliquez sur le lien &quot;Diagnostic&quot; pour obtenir plus d'informations sur une ressource particulière. Si une ressource a été signalée comme site de phishing alors que vous êtes certain de sa fiabilité, cliquez sur le lien &quot;Signaler une erreur&quot;.</translation>
+<translation id="4923417429809017348">Cette page rédigée dans une langue non identifiée a été traduite en <ph name="LANGUAGE_LANGUAGE"/>.</translation>
+<translation id="3631337165634322335">Les exceptions ci-dessous s'appliquent uniquement à la session de navigation privée actuelle.</translation>
+<translation id="676327646545845024">Ne plus afficher la boîte de dialogue pour les liens de ce type</translation>
+<translation id="494645311413743213"><ph name="NUMBER_TWO"/> secondes restantes</translation>
+<translation id="1485146213770915382">Insérez <ph name="SEARCH_TERMS_LITERAL"/> dans l'URL où les termes de recherche devraient apparaître.</translation>
+<translation id="4839303808932127586">En&amp;registrer la vidéo sous...</translation>
+<translation id="5626134646977739690">Nom :</translation>
+<translation id="5854409662653665676">Si vous rencontrez des problèmes fréquents avec ce module, vous pouvez tenter d'y remédier en suivant la procédure ci-après :</translation>
+<translation id="3681007416295224113">Informations relatives au certificat</translation>
+<translation id="3046084099139788433">Activer l'onglet 7</translation>
+<translation id="721197778055552897"><ph name="BEGIN_LINK"/>En savoir plus<ph name="END_LINK"/> sur ce problème.</translation>
+<translation id="1699395855685456105">Version du matériel :</translation>
+<translation id="212464871579942993">Le site Web à l'adresse <ph name="HOST_NAME"/> contient des éléments provenant de sites qui semblent héberger des logiciels malveillants. Ces derniers peuvent nuire à votre ordinateur ou agir à votre insu. Le simple fait de visiter un site hébergeant ce type de logiciels peut infecter votre ordinateur. Ce site héberge également des informations provenant de sites signalés comme étant des sites de phishing. Ces derniers incitent les internautes à divulguer des informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
+<translation id="8156020606310233796">Afficher la liste</translation>
+<translation id="957120528631539888">Désactivez l'affichage des messages de confirmation et le blocage de l'envoi des formulaires.</translation>
+<translation id="146000042969587795">Ce cadre a été bloqué, car il contient des éléments non sécurisés.</translation>
+<translation id="8112223930265703044">Tout</translation>
+<translation id="3968739731834770921">Kana</translation>
+<translation id="3729920814805072072">Gérer les mots de passe enregistrés...</translation>
+<translation id="7387829944233909572">Boîte de dialogue &quot;Effacer les données de navigation&quot;</translation>
+<translation id="8023801379949507775">Mettre à jour les extensions maintenant</translation>
+<translation id="6549677549082720666">Nouvelle application en arrière-plan installée</translation>
+<translation id="1983108933174595844">Envoyer une capture d'écran de la page actuelle</translation>
+<translation id="3298789223962368867">L'URL indiquée est incorrecte.</translation>
+<translation id="2202898655984161076">Un problème est survenu lors de l'affichage de la liste des imprimantes. Certaines de vos imprimantes ne sont peut-être pas correctement enregistrées dans <ph name="CLOUD_PRINT_NAME"/>.</translation>
+<translation id="6154697846084421647">Actuellement connecté</translation>
+<translation id="8241707690549784388">La page que vous recherchez a utilisé des informations que vous avez envoyées. Si vous revenez sur cette page, chaque action précédemment effectuée sera répétée. Souhaitez-vous continuer ?</translation>
+<translation id="5359419173856026110">Cette fonctionnalité indique la vitesse d'affichage réelle d'une page, en images par seconde, lorsque l'accélération matérielle est active.</translation>
+<translation id="4104163789986725820">E&amp;xporter...</translation>
+<translation id="2113479184312716848">&amp;Ouvrir un fichier...</translation>
+<translation id="8412709057120877195">Configurer le contrôle d'accès pour vos périphériques</translation>
+<translation id="486595306984036763">Ouvrir un rapport de phishing</translation>
+<translation id="3140353188828248647">Activer la barre d'adresse</translation>
+<translation id="4860787810836767172"><ph name="NUMBER_FEW"/> secs ago</translation>
+<translation id="5565871407246142825">Cartes de paiement</translation>
+<translation id="2587203970400270934">Code opérateur :</translation>
+<translation id="3355936511340229503">Erreur de connexion</translation>
+<translation id="1824910108648426227">Vous avez la possibilité de désactiver ces services.</translation>
+<translation id="3092040396860056776">Essayer d'afficher la page malgré tout</translation>
+<translation id="4350711002179453268">Impossible d'établir une connexion sécurisée avec le serveur. Le serveur a peut-être rencontré un problème ou exige un certificat d'authentification du client dont vous ne disposez pas.</translation>
+<translation id="91731790394942114">Ajouter un nouveau nom</translation>
+<translation id="5963026469094486319">Obtenir d'autres thèmes</translation>
+<translation id="2441719842399509963">Rétablir les valeurs par défaut</translation>
+<translation id="1893137424981664888">Aucun Plug-in installé.</translation>
+<translation id="3718288130002896473">Action</translation>
+<translation id="2168725742002792683">Extensions de fichier</translation>
+<translation id="1753905327828125965">Les plus visités</translation>
+<translation id="8116972784401310538">&amp;Gestionnaire de favoris</translation>
+<translation id="1849632043866553433">Caches des applications</translation>
+<translation id="3591607774768458617">Cette langue est actuellement utilisée par <ph name="PRODUCT_NAME"/>.</translation>
+<translation id="621638399744152264"><ph name="VALUE"/> %</translation>
+<translation id="4927301649992043040">Empaqueter l'extension</translation>
+<translation id="8679658258416378906">Activer l'onglet 5</translation>
+<translation id="4763816722366148126">Sélectionner le mode de saisie précédent</translation>
+<translation id="6458308652667395253">Configurer le blocage de JavaScript...</translation>
+<translation id="8435334418765210033">Réseaux mémorisés</translation>
+<translation id="6516193643535292276">Impossible de se connecter à Internet.</translation>
+<translation id="5125751979347152379">URL incorrecte</translation>
+<translation id="2791364193466153585">Informations sur la sécurité</translation>
+<translation id="4673916386520338632">Impossible d'installer l'application, car elle est en conflit avec &quot;<ph name="APP_NAME"/>&quot;, qui est déjà installé.</translation>
+<translation id="2024918351532495204">Votre périphérique n'est pas connecté.</translation>
+<translation id="6040143037577758943">Fermer</translation>
+<translation id="5787146423283493983">Accord de la clé</translation>
+<translation id="1101671447232096497"><ph name="NUMBER_MANY"/> mins ago</translation>
+<translation id="4265682251887479829">Vous ne trouvez pas ce que vous recherchez ?</translation>
+<translation id="1804251416207250805">Désactivez l'envoi des pings de contrôle des liens hypertexte.</translation>
+<translation id="5116628073786783676">En&amp;registrer le fichier audio sous...</translation>
+<translation id="2557899542277210112">Accédez rapidement à vos favoris en les ajoutant à la barre de favoris.</translation>
+<translation id="2749881179542288782">Vérifier la grammaire et l'orthographe</translation>
+<translation id="5105855035535475848">Épingler les onglets</translation>
+<translation id="6892450194319317066">Sélectionner par type d'application</translation>
+<translation id="3549436232897695316">assembler</translation>
+<translation id="5414121716219514204"><ph name="ENGINE_HOST_NAME"/> souhaite devenir votre moteur de recherche.</translation>
+<translation id="2752805177271551234">Utiliser l'historique d'entrée</translation>
+<translation id="7268365133021434339">Fermer les onglets</translation>
+<translation id="4910619056351738551">Voici quelques suggestions :</translation>
+<translation id="9131598836763251128">Sélectionnez un ou plusieurs fichiers</translation>
+<translation id="5489059749897101717">Afficher le panneau de la &amp;vérification orthographique</translation>
+<translation id="3423858849633684918">Veuillez relancer <ph name="PRODUCT_NAME"/>.</translation>
+<translation id="1232569758102978740">Sans titre</translation>
+<translation id="1903219944620007795">Pour saisir du texte, sélectionnez une langue et consultez la liste des modes de saisie disponibles.</translation>
+<translation id="4362187533051781987">Ville</translation>
+<translation id="9149866541089851383">Modifier...</translation>
+<translation id="7608619752233383356">Réinitialiser la synchronisation</translation>
+<translation id="1065245965611933814">Inclure une capture d'écran enregistrée :</translation>
+<translation id="7876243839304621966">Tout supprimer</translation>
+<translation id="5663459693447872156">Passer automatiquement en demi-chasse</translation>
+<translation id="4593021220803146968">&amp;Accéder à <ph name="URL"/></translation>
+<translation id="1128987120443782698">La capacité de ce périphérique de stockage est de <ph name="DEVICE_CAPACITY"/>. Veuillez insérer une carte SD ou une clé USB d'au moins 4 Go.</translation>
+<translation id="869257642790614972">Rouvrir le dernier onglet fermé</translation>
+<translation id="3978267865113951599">(blocage)</translation>
+<translation id="8412145213513410671">Erreurs (<ph name="CRASH_COUNT"/>)</translation>
+<translation id="560602183358579978">Traitement de la sélection...</translation>
+<translation id="7649070708921625228">Aide</translation>
+<translation id="5994107996638824097">Désolé ! La visionneuse de documents PDF intégrée à Google Chrome, nécessaire à l'affichage de l'aperçu avant impression, n'est pas incluse dans Chromium.</translation>
+<translation id="976526967778596630">Impossible d'ouvrir <ph name="HOST_NAME"/>, car vous êtes déconnecté du réseau. Cette page s'affichera dès que la connexion réseau sera rétablie. &lt;br&gt;</translation>
+<translation id="1734072960870006811">Télécopie</translation>
+<translation id="3095995014811312755">version</translation>
+<translation id="7052500709156631672">La passerelle ou le serveur proxy a reçu une réponse incorrecte d'un serveur en amont.</translation>
+<translation id="281133045296806353">Nouvelle fenêtre ouverte dans la session du navigateur</translation>
+<translation id="7144878232160441200">Réessayer</translation>
+<translation id="2860002559146138960"><ph name="PRODUCT_NAME"/> peut maintenant synchroniser vos mots de passe. Vos données seront chiffrées avec le mot de passe de votre compte Google ou le mot de passe multiterme de votre choix.</translation>
+<translation id="3951872452847539732">Les paramètres réseau de votre proxy sont gérés par une extension.</translation>
+<translation id="6442697326824312960">Retirer l'onglet</translation>
+<translation id="6382612843547381371">Valable du <ph name="START_DATE_TIME"/> au <ph name="END_DATE_TIME"/></translation>
+<translation id="6869402422344886127">Case cochée</translation>
+<translation id="5637380810526272785">Mode de saisie</translation>
+<translation id="404928562651467259">AVERTISSEMENT</translation>
+<translation id="7172053773111046550">Clavier estonien</translation>
+<translation id="497490572025913070">Ajout de bordures aux couches de rendu composées</translation>
+<translation id="9002707937526687073">Imp&amp;rimer...</translation>
+<translation id="5953934840931207585">Paramètres de saisie automatique <ph name="PRODUCT_NAME_SHORT"/></translation>
+<translation id="5556459405103347317">Rafraîchir</translation>
+<translation id="8000020256436988724">Barre d'outils</translation>
+<translation id="8326395326942127023">Nom de la base de données :</translation>
+<translation id="7507930499305566459">Certificat du répondeur d'état</translation>
+<translation id="2689915906323125315">Utiliser le mot de passe de mon compte Google</translation>
+<translation id="6440205424473899061">Vos favoris sont maintenant synchronisés avec Google Documents !
+Pour fusionner et synchroniser vos favoris dans <ph name="PRODUCT_NAME"/> sur un autre ordinateur, procédez de la même manière que précédemment sur l'ordinateur voulu.</translation>
+<translation id="7727721885715384408">Renommer...</translation>
+<translation id="2604243255129603442"><ph name="NAME_OF_EXTENSION"/> a été désactivé. Si vous arrêtez la synchronisation des favoris, vous pouvez la réactiver sur la page des extensions, via le menu Outils.</translation>
+<translation id="2024621544377454980">Affichage des pages impossible</translation>
+<translation id="7136694880210472378">Utiliser par défaut</translation>
+<translation id="7681202901521675750">La carte SIM est verrouillée. Veuillez saisir votre code PIN. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
+<translation id="7420789336015002755">Le nom du dossier contient un caractère incorrect : $1</translation>
+<translation id="1731346223650886555">Point-virgule</translation>
+<translation id="158849752021629804">Réseau domestique requis</translation>
+<translation id="7339763383339757376">PKCS #7, certificat unique</translation>
+<translation id="7587108133605326224">Langues baltes</translation>
+<translation id="3991936620356087075">Vous avez saisi un trop grand nombre de clés de verrouillage du code PIN incorrectes. Votre carte SIM est définitivement désactivée.</translation>
+<translation id="936801553271523408">Données de diagnostic système</translation>
+<translation id="6389701355360299052">Page Web, contenu HTML uniquement</translation>
+<translation id="8067791725177197206">Continuer »</translation>
+<translation id="9009144784540995197">Gérez vos imprimantes.</translation>
+<translation id="1055006259534905434">(Choisir un problème dans la liste ci-dessous)</translation>
+<translation id="3021678814754966447">&amp;Afficher le code source du cadre</translation>
+<translation id="8601206103050338563">Authentification du client WWW TLS</translation>
+<translation id="1692799361700686467">Les cookies de plusieurs sites sont autorisés.</translation>
+<translation id="7074488040076962230">Impossible d'afficher la page de la barre latérale &quot;<ph name="SIDEBAR_PAGE"/>&quot;.</translation>
+<translation id="529232389703829405">Vous avez acheté <ph name="DATA_AMOUNT"/> de données le <ph name="DATE"/>.</translation>
+<translation id="5271549068863921519">Enregistrer le mot de passe</translation>
+<translation id="4345587454538109430">Configurer...</translation>
+<translation id="8148264977957212129">Mode de saisie du pinyin</translation>
+<translation id="5787378733537687553">Intervertir les touches Ctrl et Alt de gauche</translation>
+<translation id="7772032839648071052">Confirmer le mot de passe multiterme</translation>
+<translation id="6857811139397017780">Activer <ph name="NETWORKSERVICE"/></translation>
+<translation id="3251855518428926750">Ajouter...</translation>
+<translation id="4120075327926916474">Voulez-vous que Google Chrome enregistre ces informations de carte de paiement pour le remplissage de formulaires Web ?</translation>
+<translation id="6929555043669117778">Continuer à bloquer les fenêtres pop-up</translation>
+<translation id="5864471791310927901">Échec de la vérification DHCP</translation>
+<translation id="3508920295779105875">Choisir un autre dossier...</translation>
+<translation id="2503458975635466059">Le profil semble être utilisé par le processus <ph name="PROCESS_ID"/> sur l'hôte <ph name="HOST_NAME"/>. Si vous êtes certain qu'aucun autre processus n'utilise ce profil, supprimez le fichier <ph name="LOCK_FILE"/> et relancez <ph name="PRODUCT_NAME"/>.</translation>
+<translation id="2987775926667433828">Chinois traditionnel</translation>
+<translation id="6684737638449364721">Effacer les données de navigation...</translation>
+<translation id="3954582159466790312">Ré&amp;activer le son</translation>
+<translation id="1110772031432362678">Aucun réseau trouvé.</translation>
+<translation id="3936390757709632190">&amp;Ouvrir le fichier audio dans un nouvel onglet</translation>
+<translation id="7297622089831776169">&amp;Méthodes d'entrée</translation>
+<translation id="5731698828607291678">Onglets ou fenêtres</translation>
+<translation id="1152775729948968688">Toutefois, cette page inclut d'autres ressources qui ne sont pas sécurisées. Ces ressources peuvent être consultées par des tiers pendant leur transfert, et modifiées par un pirate informatique dans le but de changer le comportement de cette page.</translation>
+<translation id="604124094241169006">Automatique</translation>
+<translation id="862542460444371744">&amp;Extensions</translation>
+<translation id="8045462269890919536">Roumain</translation>
+<translation id="6320286250305104236">Paramètres du réseau...</translation>
+<translation id="2927657246008729253">Changer...</translation>
+<translation id="7978412674231730200">Clé privée</translation>
+<translation id="464745974361668466">Format :</translation>
+<translation id="5308380583665731573">Se connecter</translation>
+<translation id="9111395131601239814"><ph name="NETWORKDEVICE"/> : <ph name="STATUS"/></translation>
+<translation id="9049981332609050619">Vous avez tenté de contacter <ph name="DOMAIN"/>, mais le certificat présenté par le serveur est incorrect.</translation>
+<translation id="4414232939543644979">Nouvelle fenêtre de nav&amp;igation privée</translation>
+<translation id="1693754753824026215">La page à l'adresse <ph name="SITE"/> indique :</translation>
+<translation id="7148804936871729015">Le serveur associé à <ph name="URL"/> n'a pas répondu à temps. Cela peut être dû à une surcharge.</translation>
+<translation id="5950967683057767490">L2TP/IPSec + Clé pré-partagée</translation>
+<translation id="8108473539339615591">XSS Auditor</translation>
+<translation id="1902576642799138955">Durée de validité</translation>
+<translation id="4910021444507283344">WebGL</translation>
+<translation id="6692173217867674490">Mot de passe multiterme erroné</translation>
+<translation id="5550431144454300634">Corriger automatiquement la saisie</translation>
+<translation id="3308006649705061278">Unité d'organisation</translation>
+<translation id="8912362522468806198">Compte Google</translation>
+<translation id="4443536555189480885">&amp;Aide</translation>
+<translation id="340485819826776184">Utiliser un service de prédiction afin de compléter les recherches et les URL saisies dans la barre d'adresse</translation>
+<translation id="4074900173531346617">Certificat du signataire de courrier électronique</translation>
+<translation id="6165508094623778733">En savoir plus</translation>
+<translation id="9052208328806230490">Vous avez enregistré vos imprimantes sur <ph name="CLOUD_PRINT_NAME"/> via le compte <ph name="EMAIL"/>.</translation>
+<translation id="822618367988303761">il y a <ph name="NUMBER_TWO"/> jours</translation>
+<translation id="7928333295097642153"><ph name="HOUR"/>:<ph name="MINUTE"/> restantes</translation>
+<translation id="7568593326407688803">Cette page est en<ph name="ORIGINAL_LANGUAGE"/>Voulez-vous la traduire ?</translation>
+<translation id="563969276220951735">Saisie automatique des formulaires</translation>
+<translation id="6870130893560916279">Clavier ukrainien</translation>
+<translation id="8629974950076222828">Ouvrir tous les favoris dans une fenêtre de navigation privée</translation>
+<translation id="3126026824346185272">Ctrl</translation>
+<translation id="4745438305783437565"><ph name="NUMBER_FEW"/> minutes</translation>
+<translation id="2649911884196340328">Le certificat de sécurité du serveur contient des erreurs !</translation>
+<translation id="6666647326143344290">avec votre compte Google</translation>
+<translation id="3828029223314399057">Rechercher dans les favoris</translation>
+<translation id="4885705234041587624">MSCHAPv2</translation>
+<translation id="5614190747811328134">Avertissement utilisateur</translation>
+<translation id="8906421963862390172">&amp;Options du vérificateur d'orthographe</translation>
+<translation id="9046895021617826162">Échec de la connexion</translation>
+<translation id="1492188167929010410">Identifiant de l'erreur <ph name="CRASH_ID"/></translation>
+<translation id="1963692530539281474"><ph name="NUMBER_DEFAULT"/> jours restants</translation>
+<translation id="4470270245053809099">Émis par : <ph name="NAME"/></translation>
+<translation id="5365539031341696497">Mode de saisie du thaï (clavier Kesmanee)</translation>
+<translation id="2403091441537561402">Passerelle :</translation>
+<translation id="6337234675334993532">Chiffrement</translation>
+<translation id="668171684555832681">Autre...</translation>
+<translation id="1932098463447129402">Pas avant le</translation>
+<translation id="7845920762538502375"><ph name="PRODUCT_NAME"/> n'a pas pu synchroniser vos données, car la connexion avec le serveur de synchronisation n'a pas pu être établie. Nouvel essai...</translation>
+<translation id="2192664328428693215">Me demander lorsqu'un site souhaite afficher des notifications sur le Bureau (recommandé)</translation>
+<translation id="6708242697268981054">Source :</translation>
+<translation id="4786993863723020412">Erreur de lecture du cache</translation>
+<translation id="6630452975878488444">Raccourci de sélection</translation>
+<translation id="8709969075297564489">Vérifier la révocation du certificat serveur</translation>
+<translation id="8698171900303917290">Vous rencontrez des problèmes lors de l'installation ?</translation>
+<translation id="830868413617744215">Bêta</translation>
+<translation id="5925147183566400388">Pointeur de la déclaration CPS (Certification Practice Statement)</translation>
+<translation id="1497270430858433901">Le <ph name="DATE"/>, vous avez reçu <ph name="DATA_AMOUNT"/> à utiliser librement.</translation>
+<translation id="8150167929304790980">Nom complet</translation>
+<translation id="636850387210749493">Inscription d'entreprise</translation>
+<translation id="1947424002851288782">Clavier allemand</translation>
+<translation id="932508678520956232">Impossible de lancer l'impression.</translation>
+<translation id="4861833787540810454">&amp;Lire</translation>
+<translation id="2552545117464357659">Récent</translation>
+<translation id="7269802741830436641">Cette page Web présente une boucle de redirection.</translation>
+<translation id="4180788401304023883">Supprimer le certificat &quot;<ph name="CERTIFICATE_NAME"/>&quot; émis par l'autorité de certification ?</translation>
+<translation id="5869522115854928033">Mots de passe enregistrés</translation>
+<translation id="2089090684895656482">Moins</translation>
+<translation id="1709220265083931213">Options avancées</translation>
+<translation id="5748266869826978907">Vérifiez vos paramètres DNS. Contactez votre administrateur réseau si vous n'êtes pas sûr de vous.</translation>
+<translation id="4771973620359291008">Une erreur inconnue s'est produite.</translation>
+<translation id="5509914365760201064">Émetteur : <ph name="CERTIFICATE_AUTHORITY"/></translation>
+<translation id="7073385929680664879">Passer d'un mode de saisie à l'autre</translation>
+<translation id="6898699227549475383">Organisation (O)</translation>
+<translation id="4333854382783149454">PKCS #1 SHA-1 avec chiffrement RSA</translation>
+<translation id="762904068808419792">Entrez la requête de recherche ici.</translation>
+<translation id="8615618338313291042">Application en mode navigation privée : <ph name="APP_NAME"/></translation>
+<translation id="978146274692397928">La largeur de ponctuation initiale est Complète</translation>
+<translation id="8959027566438633317">Installer <ph name="EXTENSION_NAME"/> ?</translation>
+<translation id="8155798677707647270">Installation d'une nouvelle version...</translation>
+<translation id="6886871292305414135">Ouvrir le lien dans un nouvel ongle&amp;t</translation>
+<translation id="1639192739400715787">Pour accéder aux paramètres de sécurité, saisissez le code PIN de la carte SIM.</translation>
+<translation id="7961015016161918242">Jamais</translation>
+<translation id="3950924596163729246">Impossible d'accéder au réseau.</translation>
+<translation id="2835170189407361413">Effacer le formulaire</translation>
+<translation id="4631110328717267096">Échec de la mise à jour du système</translation>
+<translation id="3695919544155087829">Saisissez le mot de passe utilisé pour chiffrer ce fichier de certificat.</translation>
+<translation id="2230051135190148440">CHAP</translation>
+<translation id="6308937455967653460">Enregistrer le lie&amp;n sous...</translation>
+<translation id="5421136146218899937">Effacer les données de navigation...</translation>
+<translation id="5783059781478674569">Options de reconnaissance vocale</translation>
+<translation id="5441100684135434593">Réseau câblé</translation>
+<translation id="3285322247471302225">Nouvel ongle&amp;t</translation>
+<translation id="3943582379552582368">R&amp;etour</translation>
+<translation id="7607002721634913082">Téléchargement suspendu</translation>
+<translation id="480990236307250886">Ouvrir la page d'accueil</translation>
+<translation id="8286036467436129157">Connexion</translation>
+<translation id="5999940714422617743">L'installation de <ph name="EXTENSION_NAME"/> est terminée.</translation>
+<translation id="1122198203221319518">&amp;Outils</translation>
+<translation id="5757539081890243754">Page d'accueil</translation>
+<translation id="2760009672169282879">Clavier phonétique bulgare</translation>
+<translation id="6608140561353073361">Cookies et données de site...</translation>
+<translation id="8007030362289124303">Batterie faible</translation>
+<translation id="4513946894732546136">Commentaires</translation>
+<translation id="1135328998467923690">Package incorrect : &quot;<ph name="ERROR_CODE"/>&quot;.</translation>
+<translation id="5906719743126878045"><ph name="NUMBER_TWO"/> heures restantes</translation>
+<translation id="1753682364559456262">Configurer les paramètres de blocage des images...</translation>
+<translation id="6550675742724504774">Options</translation>
+<translation id="8959208747503200525"><ph name="NUMBER_TWO"/> hours ago</translation>
+<translation id="431076611119798497">&amp;Détails</translation>
+<translation id="737801893573836157">Masquer la barre de titre du système et utiliser les bordures</translation>
+<translation id="5352235189388345738">Elle peut accéder aux éléments suivants :</translation>
+<translation id="5040262127954254034">Confidentialité</translation>
+<translation id="7666868073052500132">Objets : <ph name="USAGES"/></translation>
+<translation id="6985345720668445131">Paramètres d'entrée du japonais</translation>
+<translation id="3258281577757096226">Sebeol-sik Final</translation>
+<translation id="2359174522669474766">Un fichier sélectionné, $1</translation>
+<translation id="6906268095242253962">Veuillez vous connecter à Internet pour continuer.</translation>
+<translation id="1908748899139377733">Afficher les &amp;infos sur le cadre</translation>
+<translation id="803771048473350947">Fichier</translation>
+<translation id="6206311232642889873">Cop&amp;ier l'image</translation>
+<translation id="5158983316805876233">Utiliser le même proxy pour tous les protocoles</translation>
+<translation id="7108338896283013870">Masquer</translation>
+<translation id="3366404380928138336">Requête de protocole externe</translation>
+<translation id="5300589172476337783">Afficher</translation>
+<translation id="3160041952246459240">Certains de vos certificats enregistrés identifient ces serveurs :</translation>
+<translation id="566920818739465183">Vous avez visité ce site pour la première fois le <ph name="VISIT_DATE"/>.</translation>
+<translation id="2961695502793809356">Cliquer pour avancer, maintenir pour voir l'historique</translation>
+<translation id="4092878864607680421">La dernière version de l'application &quot;<ph name="APP_NAME"/>&quot; requiert d'autres autorisations. Elle a donc été désactivée.</translation>
+<translation id="8421864404045570940"><ph name="NUMBER_DEFAULT"/> secondes</translation>
+<translation id="5828228029189342317">Vous avez choisi d'ouvrir automatiquement certains types de fichiers après leur téléchargement.</translation>
+<translation id="1416836038590872660">EAP-MD5</translation>
+<translation id="176587472219019965">&amp;Nouvelle fenêtre</translation>
+<translation id="2788135150614412178">+</translation>
+<translation id="4055738107007928968">Vous avez essayé d'accéder au site <ph name="DOMAIN"/>, mais le serveur a présenté un certificat signé avec un algorithme de signature faible. Il se peut que les informations d'identification fournies par le serveur aient été falsifiées. Le serveur n'est peut-être pas celui auquel vous souhaitez accéder (il peut s'agir d'une tentative de piratage). Nous nous déconseillons vivement de continuer.</translation>
+<translation id="5308689395849655368">L'envoi de rapports d'erreur est désactivé.</translation>
+<translation id="8372369524088641025">Clé WEP incorrecte</translation>
+<translation id="8689341121182997459">Date d'expiration :</translation>
+<translation id="899403249577094719">URL de base du certificat Netscape</translation>
+<translation id="2737363922397526254">Réduire...</translation>
+<translation id="4880827082731008257">Rechercher dans l'historique</translation>
+<translation id="8661290697478713397">Ouvrir le lien dans la fenêtre de navi&amp;gation privée</translation>
+<translation id="4197700912384709145"><ph name="NUMBER_ZERO"/> secondes</translation>
+<translation id="7454780465968211330">Historique avancé pour le champ polyvalent</translation>
+<translation id="2158448795143567596">Active l'utilisation de graphismes 3D dans les éléments canvas via l'API WebGL.</translation>
+<translation id="1702534956030472451">Occident</translation>
+<translation id="6636709850131805001">État non reconnu</translation>
+<translation id="6095984072944024315">−</translation>
+<translation id="9141716082071217089">Impossible de vérifier si le certificat du serveur a été révoqué.</translation>
+<translation id="4304224509867189079">Se connecter</translation>
+<translation id="5332624210073556029">Fuseau horaire :</translation>
+<translation id="4799797264838369263">Cette option est soumise à une stratégie d'entreprise. Contactez votre administrateur pour plus d'informations.</translation>
+<translation id="4492190037599258964">Résultats de recherche pour &quot;<ph name="SEARCH_STRING"/>&quot;</translation>
+<translation id="3573179567135747900">Revenir à &quot;<ph name="FROM_LOCALE"/>&quot; (redémarrage requis)</translation>
+<translation id="2238123906478057869"><ph name="PRODUCT_NAME"/> va exécuter les tâches suivantes :</translation>
+<translation id="4042471398575101546">Ajouter la page</translation>
+<translation id="8848709220963126773">Changement de mode via la touche Maj</translation>
+<translation id="4871865824885782245">Options de date et d'heure...</translation>
+<translation id="8828933418460119530">Nom DNS</translation>
+<translation id="988159990683914416">Build de développement</translation>
+<translation id="8026354464835030469"><ph name="BURNT_AMOUNT"/> sur ...</translation>
+<translation id="4114470632216071239">Verrouiller la carte SIM (code PIN obligatoire pour utiliser les données mobiles)</translation>
+<translation id="2183426022964444701">Sélectionnez le répertoire racine de l'extension.</translation>
+<translation id="2517143724531502372">Les cookies de <ph name="DOMAIN"/> sont autorisés uniquement pour cette session.</translation>
+<translation id="9018524897810991865">Confirmer les préférences de synchronisation</translation>
+<translation id="4719905780348837473">RSN</translation>
+<translation id="5212108862377457573">Ajuster la conversion en fonction de l'entrée précédente</translation>
+<translation id="5398353896536222911">Afficher le panneau de la &amp;vérification orthographique</translation>
+<translation id="5811533512835101223">(Revenir à la capture d'écran d'origine)</translation>
+<translation id="5131817835990480221">Mettre à jour &amp;<ph name="PRODUCT_NAME"/></translation>
+<translation id="939519157834106403">SSID</translation>
+<translation id="3705722231355495246">-</translation>
+<translation id="2635102990349508383">Les informations de connexion au compte n'ont pas encore été saisies.</translation>
+<translation id="6902055721023340732">URL de configuration automatique</translation>
+<translation id="4268574628540273656">URL :</translation>
+<translation id="7481312909269577407">Avancer</translation>
+<translation id="3759876923365568382"><ph name="NUMBER_FEW"/> jours restants</translation>
+<translation id="295228163843771014">Vous avez choisi de ne pas synchroniser les mots de passe. Vous pouvez à tout moment modifier vos paramètres de synchronisation, si vous changez d'avis.</translation>
+<translation id="5972826969634861500">Lancer <ph name="PRODUCT_NAME"/></translation>
+<translation id="7828702903116529889"><ph name="PRODUCT_NAME"/>
+ ne parvient pas à accéder au réseau.
+ <ph name="LINE_BREAK"/>
+ Il est possible que votre pare-feu ou votre antivirus considère
+ <ph name="PRODUCT_NAME"/>
+ comme un intrus dans votre ordinateur et qu'il bloque ses tentatives de connexion à Internet.</translation>
+<translation id="878069093594050299">Ce certificat a été vérifié pour les utilisations suivantes :</translation>
+<translation id="5852112051279473187">Petit problème ! Une erreur est survenue lors de l'inscription de ce périphérique. Veuillez réessayer ou contacter votre représentant de l'assistance technique.</translation>
+<translation id="1664314758578115406">Ajouter aux favoris</translation>
+<translation id="7088418943933034707">Gérer les certificats...</translation>
+<translation id="8482183012530311851">Analyse du périphérique...</translation>
+<translation id="3127589841327267804">PYJJ</translation>
+<translation id="8808478386290700967">Web Store</translation>
+<translation id="1732215134274276513">Annuler l'épinglage des onglets</translation>
+<translation id="4084682180776658562">Favori</translation>
+<translation id="8859057652521303089">Sélectionnez votre langue :</translation>
+<translation id="3030138564564344289">Réessayer le téléchargement</translation>
+<translation id="8525552230188318924">Configurer la synchronisation des mots de passe</translation>
+<translation id="4381091992796011497">Nom d'utilisateur :</translation>
+<translation id="5830720307094128296">Enregistrer la p&amp;age sous...</translation>
+<translation id="8114439576766120195">Vos données sur tous les sites Web</translation>
+<translation id="4668954208278016290">Un problème est survenu lors de l'extraction de l'image sur l'ordinateur.</translation>
+<translation id="5822838715583768518">Lancer l'application</translation>
+<translation id="3942974664341190312">Dubeol-sik</translation>
+<translation id="8477241577829954800">Remplacé</translation>
+<translation id="6735304988756581115">Afficher les cookies et autres données de site...</translation>
+<translation id="3048564749795856202">Si vous pensez avoir cerné les risques, vous pouvez <ph name="PROCEED_LINK"/>.</translation>
+<translation id="2433507940547922241">Apparence</translation>
+<translation id="839072384475670817">Créer des raccourci&amp;s vers des applications...</translation>
+<translation id="1478632774608054702">Exécuter le flash PPAPI dans le processus du moteur de rendu</translation>
+<translation id="6756161853376828318">Définir <ph name="PRODUCT_NAME"/> en tant que navigateur par défaut</translation>
+<translation id="9112614144067920641">Veuillez choisir un nouveau code PIN.</translation>
+<translation id="2061855250933714566"><ph name="ENCODING_CATEGORY"/> (<ph name="ENCODING_NAME"/>)</translation>
+<translation id="7138678301420049075">Autre</translation>
+<translation id="9147392381910171771">&amp;Options</translation>
+<translation id="1803557475693955505">Impossible de charger la page d'arrière-plan &quot;<ph name="BACKGROUND_PAGE"/>&quot;.</translation>
+<translation id="5818334088068591797">À quel niveau rencontrez-vous des problèmes ? (Champ obligatoire)</translation>
+<translation id="6264485186158353794">Retour à la sécurité</translation>
+<translation id="5130080518784460891">Eten</translation>
+<translation id="5847724078457510387">Ce site répertorie tous ses certificats valides dans le système DNS. Un certificat non répertorié a cependant été utilisé par le serveur.</translation>
+<translation id="1394853081832053657">Options de reconnaissance vocale</translation>
+<translation id="5037676449506322593">Tout sélectionner</translation>
+<translation id="2785530881066938471">Impossible de charger le fichier &quot;<ph name="RELATIVE_PATH"/>&quot; pour le script de contenu, car ce fichier n'est pas codé en UTF-8.</translation>
+<translation id="3807747707162121253">&amp;Annuler</translation>
+<translation id="3306897190788753224">Désactiver temporairement la personnalisation des conversions, les suggestions basées sur l'historique et le dictionnaire utilisateur</translation>
+<translation id="2574102660421949343">Les cookies de <ph name="DOMAIN"/> sont autorisés.</translation>
+<translation id="77999321721642562">Au fil du temps, la zone ci-dessous affichera les huit sites que vous avez le plus visités.</translation>
+<translation id="1503894213707460512">Le plug-in <ph name="PLUGIN_NAME"/> a besoin de votre autorisation pour s'exécuter.</translation>
+<translation id="471800408830181311">Échec de création de clé privée</translation>
+<translation id="1273291576878293349">Ouvrir tous les favoris dans une fenêtre de navigation privée</translation>
+<translation id="1639058970766796751">Placer dans la file d'attente</translation>
+<translation id="1177437665183591855">Erreur de certificat serveur inconnue</translation>
+<translation id="8467473010914675605">Mode de saisie du coréen</translation>
+<translation id="3819800052061700452">&amp;Plein écran</translation>
+<translation id="5419540894229653647"><ph name="ERROR_DESCRIPTION_TEXT"/>
+ <ph name="LINE_BREAK"/>
+ Vous pouvez essayer de diagnostiquer le problème en procédant comme suit :
+ <ph name="LINE_BREAK"/>
+ <ph name="PLATFORM_TEXT"/></translation>
+<translation id="3533943170037501541">Bienvenue sur votre page d'accueil !</translation>
+<translation id="2333340435262918287">Vos modifications seront prises en compte au prochain démarrage de <ph name="PRODUCT_NAME"/>.</translation>
+<translation id="5906065664303289925">Adresse du matériel :</translation>
+<translation id="3178000186192127858">Lecture seule</translation>
+<translation id="2187895286714876935">Erreur d'importation du certificat serveur</translation>
+<translation id="5460896875189097758">Données stockées localement</translation>
+<translation id="4618990963915449444">Tous les fichiers de <ph name="DEVICE_NAME"/> vont être effacés.</translation>
+<translation id="614998064310228828">Modèle du périphérique :</translation>
+<translation id="1581962803218266616">Afficher dans le Finder</translation>
+<translation id="6096326118418049043">Nom X.500</translation>
+<translation id="6086259540486894113">Vous devez sélectionner au moins un type de données à synchroniser.</translation>
+<translation id="923467487918828349">Tout afficher</translation>
+<translation id="5101042277149003567">Ouvrir tous les favoris</translation>
+<translation id="4298972503445160211">Clavier danois</translation>
+<translation id="6621440228032089700">Cette fonctionnalité permet de réaliser un rendu hors écran de la texture, au lieu d'un affichage direct.</translation>
+<translation id="3488065109653206955">Partiellement activé</translation>
+<translation id="1481244281142949601">Votre système Sandbox est correctement configuré.</translation>
+<translation id="4849517651082200438">Ne pas installer</translation>
+<translation id="8602882075393902833">Activer la recherche instantanée pour accélérer la recherche et la navigation</translation>
+<translation id="6349678711452810642">Utiliser par défaut</translation>
+<translation id="6263284346895336537">Non essentielle</translation>
+<translation id="6409731863280057959">Fenêtres pop-up</translation>
+<translation id="3459774175445953971">Dernière modification :</translation>
+<translation id="73289266812733869">Désélectionné</translation>
+<translation id="3435738964857648380">Sécurité</translation>
+<translation id="9112987648460918699">Rechercher...</translation>
+<translation id="2231233239095101917">Le script de la page utilisait trop de mémoire. Rafraîchissez la page pour réactiver le script.</translation>
+<translation id="870805141700401153">Signature du code individuel Microsoft</translation>
+<translation id="5119173345047096771">Mozilla Firefox</translation>
+<translation id="9020278534503090146">Page Web inaccessible</translation>
+<translation id="4768698601728450387">Recadrer l'image</translation>
+<translation id="6245028464673554252">Si vous fermez <ph name="PRODUCT_NAME"/> maintenant, le téléchargement sera annulé.</translation>
+<translation id="3943857333388298514">Coller</translation>
+<translation id="385051799172605136">Retour</translation>
+<translation id="1742300158964248589">Impossible de graver l'image.</translation>
+<translation id="2670965183549957348">Mode de saisie du Chewing</translation>
+<translation id="5095208057601539847">Province</translation>
+<translation id="4085298594534903246">JavaScript a été bloqué sur cette page.</translation>
+<translation id="5630492933376732170">Remarque : Lorsque vous cliquez sur &quot;Envoyer&quot;, Google Chrome OS
+ joint à votre envoi un journal des événements système de
+ votre périphérique. Ces informations nous permettent de diagnostiquer les
+ problèmes, de comprendre comment vous interagissez avec votre
+ périphérique et d'améliorer les performances de ce dernier. Les
+ informations personnelles fournies sciemment dans vos commentaires ou
+ involontairement dans les journaux système et la capture d'écran sont
+ protégées conformément à nos <ph name="BEGIN_LINK"/>Règles de confidentialité<ph name="END_LINK"/>.
+ Si vous ne souhaitez pas envoyer de journaux système, décochez la case
+ &quot;Inclure les informations système&quot;.</translation>
+<translation id="4341977339441987045">Interdire à tous les sites de stocker des données</translation>
+<translation id="806812017500012252">Trier par nom</translation>
+<translation id="3781751432212184938">Afficher un aperçu des onglets...</translation>
+<translation id="2960316970329790041">Annuler l'importation</translation>
+<translation id="3835522725882634757">Ce serveur envoie des données que <ph name="PRODUCT_NAME"/> ne comprend pas. Veuillez <ph name="BEGIN_LINK"/>signaler un bug<ph name="END_LINK"/> et inclure la <ph name="BEGIN2_LINK"/>liste des raw<ph name="END2_LINK"/>.</translation>
+<translation id="5361734574074701223">Calcul de la durée restante</translation>
+<translation id="6937152069980083337">Mode de saisie Google du japonais (pour clavier américain)</translation>
+<translation id="1731911755844941020">Envoi de la requête...</translation>
+<translation id="8371695176452482769">Parlez maintenant</translation>
+<translation id="2988488679308982380">Impossible d'installer le package : &quot;<ph name="ERROR_CODE"/>&quot;</translation>
+<translation id="2904079386864173492">Modèle :</translation>
+<translation id="3447644283769633681">Bloquer tous les cookies tiers</translation>
+<translation id="8917047707340793412">Remplacer par <ph name="ENGINE_NAME"/></translation>
+<translation id="6129953537138746214">Espace</translation>
+<translation id="3704331259350077894">Arrêt du fonctionnement</translation>
+<translation id="5801568494490449797">Préférences</translation>
+<translation id="1038842779957582377">Nom inconnu</translation>
+<translation id="5327248766486351172">Nom</translation>
+<translation id="5553784454066145694">Choisir un nouveau code PIN</translation>
+<translation id="8989148748219918422"><ph name="ORGANIZATION"/> [<ph name="COUNTRY"/>]</translation>
+<translation id="4664482161435122549">Erreur d'exportation de fichier PKCS #12</translation>
+<translation id="2445081178310039857">Le répertoire racine de l'extension doit être indiqué.</translation>
+<translation id="8251578425305135684">Miniature supprimée</translation>
+<translation id="6163522313638838258">Tout développer...</translation>
+<translation id="3037605927509011580">Aie aie aie</translation>
+<translation id="5803531701633845775">Choisir les expressions en arrière-plan, sans déplacer le pointeur</translation>
+<translation id="1918141783557917887">Plu&amp;s petit</translation>
+<translation id="6996550240668667907">Afficher le clavier en superposition</translation>
+<translation id="4065006016613364460">C&amp;opier l'URL de l'image</translation>
+<translation id="6965382102122355670">OK</translation>
+<translation id="8000066093800657092">Aucun réseau détecté</translation>
+<translation id="4481249487722541506">Charger l'extension non empaquetée...</translation>
+<translation id="8180239481735238521">page</translation>
+<translation id="8321738493186308836">Active l'interface utilisateur et le code de support pour le processus du service de communication à distance, de même que le plug-in client. Avertissement : ce service n'est actuellement disponible que pour les tests de développeurs. Si vous ne faites pas partie de l'équipe de développement et ne figurez pas sur la liste blanche, aucun élément de l'interface utilisateur activée ne fonctionnera.</translation>
+<translation id="2963783323012015985">Clavier turc</translation>
+<translation id="2149973817440762519">Modifier le favori</translation>
+<translation id="5431318178759467895">Couleur</translation>
+<translation id="7064842770504520784">Personnaliser les paramètres de synchronisation...</translation>
+<translation id="2784407158394623927">Activation de votre service Internet mobile</translation>
+<translation id="3679848754951088761"><ph name="SOURCE_ORIGIN"/></translation>
+<translation id="6920989436227028121">Ouvrir dans un onglet standard</translation>
+<translation id="4057041477816018958"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/></translation>
+<translation id="2050339315714019657">Portrait</translation>
+<translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation>
+<translation id="6139139147415955203">Active un service en arrière-plan qui connecte le service <ph name="CLOUD_PRINT_NAME"/> aux éventuelles imprimantes installées sur cet ordinateur. Une fois ce labo activé, vous pouvez lancer <ph name="CLOUD_PRINT_NAME"/> en vous connectant à votre compte Google via Options/Préférences dans la section Options avancées.</translation>
+<translation id="5112577000029535889">Outils de &amp;développement</translation>
+<translation id="2301382460326681002">Le répertoire racine de l'extension est incorrect.</translation>
+<translation id="7839192898639727867">ID de clé de l'objet du certificat</translation>
+<translation id="4759238208242260848">Téléchargements</translation>
+<translation id="2879560882721503072">Le stockage du certificat client généré par <ph name="ISSUER"/> a réussi.</translation>
+<translation id="1275718070701477396">Sélectionnée</translation>
+<translation id="1178581264944972037">Suspendre</translation>
+<translation id="6492313032770352219">Taille sur le disque :</translation>
+<translation id="5233231016133573565">ID du processus</translation>
+<translation id="5941711191222866238">Réduire</translation>
+<translation id="4121428309786185360">Expire le</translation>
+<translation id="2049137146490122801">Votre administrateur a désactivé l'accès aux fichiers locaux sur votre ordinateur.</translation>
+<translation id="1146498888431277930">Erreur de connexion SSL</translation>
+<translation id="8041089156583427627">Envoyer</translation>
+<translation id="6394627529324717982">Virgule</translation>
+<translation id="253434972992662860">&amp;Pause</translation>
+<translation id="335985608243443814">Parcourir...</translation>
+<translation id="7802488492289385605">Mode de saisie Google du japonais (pour clavier Dvorak américain)</translation>
+<translation id="7452120598248906474">Police à largeur fixe</translation>
+<translation id="3129687551880844787">Stockage de session</translation>
+<translation id="7427348830195639090">Page en arrière-plan : <ph name="BACKGROUND_PAGE_URL"/></translation>
+<translation id="5898154795085152510">Le serveur a renvoyé un certificat client incorrect. Erreur <ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)</translation>
+<translation id="2704184184447774363">Signature de document Microsoft</translation>
+<translation id="5677928146339483299">Bloqué</translation>
+<translation id="1474842329983231719">Gérer les paramètres d'impression...</translation>
+<translation id="2455981314101692989">Cette page Web a désactivé la saisie automatique dans ce formulaire.</translation>
+<translation id="1646136617204068573">Clavier hongrois</translation>
+<translation id="5988840637546770870">Les versions en développement permettent de tester de nouvelles idées, mais elles peuvent s'avérer très instables. Nous vous prions d'agir avec précaution.</translation>
+<translation id="3569713929051927529">Ajouter un dossier...</translation>
+<translation id="4032664149172368180">Mode de saisie du japonais (pour clavier Dvorak américain)</translation>
+<translation id="3748706263662799310">Signaler un bug</translation>
+<translation id="7167486101654761064">&amp;Toujours ouvrir les fichiers de ce type</translation>
+<translation id="4283623729247862189">Disque optique</translation>
+<translation id="5826507051599432481">Nom commun</translation>
+<translation id="8914326144705007149">Très grande</translation>
+<translation id="4215444178533108414">Modification terminée</translation>
+<translation id="5154702632169343078">Objet</translation>
+<translation id="2273562597641264981">Opérateur :</translation>
+<translation id="122082903575839559">Algorithme de signature du certificat</translation>
+<translation id="2181257377760181418">Cette fonctionnalité permet d'afficher un onglet d'aperçu avant de lancer une impression.</translation>
+<translation id="7240120331469437312">Autre nom de l'objet du certificat</translation>
+<translation id="6900113680982781280">Activer la saisie automatique pour remplir les formulaires Web d'un simple clic</translation>
+<translation id="1131850611586448366">Le site Web à l'adresse <ph name="HOST_NAME"/> a été signalé comme étant un site de phishing. Ces sites tentent d'amener les internautes à divulguer leurs informations personnelles en se faisant passer pour des institutions de confiance, telles que des banques.</translation>
+<translation id="5413218268059792983">Rechercher directement sur <ph name="SEARCH_ENGINE"/></translation>
+<translation id="1161575384898972166">Connectez-vous à <ph name="TOKEN_NAME"/> pour exporter le certificat client.</translation>
+<translation id="1718559768876751602">Créer un compte Google maintenant</translation>
+<translation id="1884319566525838835">État Sandbox</translation>
+<translation id="2770465223704140727">Retirer de la liste</translation>
+<translation id="3590587280253938212">rapide</translation>
+<translation id="6053401458108962351">&amp;Effacer les données de navigation…</translation>
+<translation id="2339641773402824483">Vérification des mises à jour...</translation>
+<translation id="9111742992492686570">Télécharger les mises à jour de sécurité essentielles</translation>
+<translation id="8636666366616799973">Package incorrect. Détails : &quot;<ph name="ERROR_MESSAGE"/>&quot;.</translation>
+<translation id="2045969484888636535">Continuer à bloquer les cookies</translation>
+<translation id="7353601530677266744">Ligne de commande</translation>
+<translation id="2766006623206032690">Coller l'URL et y a&amp;ccéder</translation>
+<translation id="4394049700291259645">Désactiver</translation>
+<translation id="969892804517981540">Build officiel</translation>
+<translation id="445923051607553918">Se connecter à un réseau Wi-Fi</translation>
+<translation id="100242374795662595">Périphérique inconnu</translation>
+<translation id="9087725134750123268">Supprimer les cookies et autres données de site</translation>
+<translation id="5050255233730056751">URL saisies</translation>
+<translation id="3349155901412833452">Utiliser les touches , et . pour paginer une liste d'entrées</translation>
+<translation id="6872947427305732831">Vider la mémoire</translation>
+<translation id="2742870351467570537">Supprimer les éléments sélectionnés</translation>
+<translation id="7561196759112975576">Toujours</translation>
+<translation id="2116673936380190819">de moins d'une heure</translation>
+<translation id="5765491088802881382">Aucun réseau n'est disponible.</translation>
+<translation id="1971538228422220140">Supprimer les cookies et autres données de site et de plug-in</translation>
+<translation id="883487340845134897">Intervertir les touches Rechercher et Ctrl gauche</translation>
+<translation id="5692957461404855190">Faites glisser trois doigts sur la surface de votre trackpad pour afficher un aperçu de tous vos onglets. Cliquez sur une vignette pour la sélectionner. Idéal en mode plein écran.</translation>
+<translation id="1375215959205954975">Nouveau ! Configurer la synchronisation des mots de passe</translation>
+<translation id="5183088099396036950">Échec de la tentative de connexion au serveur</translation>
+<translation id="4469842253116033348">Désactiver les notifications de <ph name="SITE"/></translation>
+<translation id="7999229196265990314">Les fichiers suivants ont été créés :
+
+Extension : <ph name="EXTENSION_FILE"/>
+Fichier de clé : <ph name="KEY_FILE"/>
+
+Conservez votre fichier de clé en lieu sûr. Vous en aurez besoin lors de la création de nouvelles versions de l'extension.</translation>
+<translation id="1846078536247420691">&amp;Oui</translation>
+<translation id="3036649622769666520">Ouvrir les fichiers</translation>
+<translation id="2966459079597787514">Clavier suédois</translation>
+<translation id="7685049629764448582">Mémoire JavaScript </translation>
+<translation id="6398765197997659313">Quitter le mode plein écran</translation>
+<translation id="6059652578941944813">Hiérarchie des certificats</translation>
+<translation id="4886690096315032939">Afficher l'onglet existant si l'URL associée est demandée dans un autre</translation>
+<translation id="5729712731028706266">&amp;Afficher</translation>
+<translation id="774576312655125744">Vos données personnelles sur <ph name="WEBSITE_1"/>, <ph name="WEBSITE_2"/> et sur <ph name="NUMBER_OF_OTHER_WEBSITES"/> autres sites Web</translation>
+<translation id="6359806961507272919">SMS de <ph name="PHONE_NUMBER"/></translation>
+<translation id="4508765956121923607">Afficher la s&amp;ource</translation>
+<translation id="5975083100439434680">Zoom arrière</translation>
+<translation id="8080048886850452639">C&amp;opier l'URL du fichier audio</translation>
+<translation id="2817109084437064140">Importer et associer au périphérique...</translation>
+<translation id="3331321258768829690">(<ph name="UTCOFFSET"/>) <ph name="LONGTZNAME"/> (<ph name="EXEMPLARCITY"/>)</translation>
+<translation id="619398760000422129">Plug-ins (par ex. Adobe Flash Player, QuickTime, etc.)</translation>
+<translation id="5849869942539715694">Empaqueter l'extension...</translation>
+<translation id="7339785458027436441">Vérifier l'orthographe lors de la frappe</translation>
+<translation id="8308427013383895095">Échec de la traduction en raison d'un problème de connexion réseau</translation>
+<translation id="1801298019027379214">Code PIN incorrect. Veuillez réessayer. Nombre de tentatives restantes : <ph name="TRIES_COUNT"/></translation>
+<translation id="1384721974622518101">Vous pouvez effectuer une recherche directement à partir du champ ci-dessus.</translation>
+<translation id="992543612453727859">Ajouter les expressions au premier plan</translation>
+<translation id="3857773447683694438">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</translation>
+<translation id="1244147615850840081">Opérateur</translation>
+<translation id="8203365863660628138">Confirmer l'installation</translation>
+<translation id="406259880812417922">(Mot clé : <ph name="KEYWORD"/>)</translation>
+<translation id="309628958563171656">Sensibilité :</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/header.html b/chromium/tools/grit/grit/testdata/header.html
new file mode 100644
index 00000000000..8e9d10ec502
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/header.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>[$~TITLE~$]</title>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+[EXTRA_META]
+<style>
+BODY,TD,DIV,.P,A { FONT-FAMILY: arial,sans-serif}
+DIV,TD { COLOR: #000}
+.f { COLOR: #6f6f6f}
+.fl:link { COLOR: #6f6f6f}
+A:link, .w, A.w:link, .w A:link { COLOR: #00c}
+A:visited { COLOR: #551a8b}
+.fl:visited { COLOR: #551a8b}
+A:active, .fl:active { COLOR: #f00}
+.h { COLOR: #3399CC}
+.i { COLOR: #a90a08}
+.i:link { COLOR: #a90a08}
+.a, .a:link, .a:visited { COLOR: #008000}
+DIV.n { MARGIN-TOP: 1ex}
+.n A { FONT-SIZE: 10pt; COLOR: #000}
+.n .i { FONT-WEIGHT: bold; FONT-SIZE: 10pt}
+.q A:visited { COLOR: #00c}
+.q A:link { COLOR: #00c}
+.q A:active { COLOR: #00c}
+.q { COLOR: #00c}
+.b { FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #00c}
+.ch { CURSOR: hand}
+.e { MARGIN-TOP: 0.75em; MARGIN-BOTTOM: 0.75em}
+.g { MARGIN-TOP: 1em; MARGIN-BOTTOM: 1em}
+.f { MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.25em}
+.s { HEIGHT: 10px }
+.c:active { COLOR: #ff0000}
+.c:visited { COLOR: #551a8b}
+.c:link { COLOR: #7777cc}
+.c { COLOR: #7777cc }
+</style>
+</head> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/homepage.html b/chromium/tools/grit/grit/testdata/homepage.html
new file mode 100644
index 00000000000..cce4f2cf35d
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/homepage.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Google Desktop Search</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
+.q {COLOR: #0000cc}
+</style>
+<script>
+<!--
+function sf(){document.f.q.focus();}
+// -->
+</script>
+</head>
+<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
+<center>
+<TABLE cellSpacing=0 cellPadding=0 border=0>
+<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a></td></tr></table><BR>
+<FORM name=f method=GET action='[$~SEARCHURL~$]'>
+<TABLE cellSpacing=0 cellPadding=4 border=0>
+<tr>
+<TD class=q noWrap><FONT size=-1>
+[$~LINKS~$]
+</font></td>
+</tr></table>
+<table cellspacing=0 cellpadding=0>
+<tr vAlign=top>
+<td width=25%>&nbsp;</td>
+<td align=center><input maxlength=256 size=62 name=q value="[DISP_QUERY]"><br><input type=submit value="Search Desktop" name=btnG><INPUT type=submit value="Search the Web" name="redir" accesskey=w></td>
+<td align=left valign=top nowrap width=25%><font size=-2>&nbsp;&nbsp;<A href="[$~PREFERENCES~$]">Desktop&nbsp;Preferences</a></font></td>
+</tr></table></FORM>
+<p><FONT color=#224499><B>Search your own computer.</B></font></p>
+<span style='width:29em'>[$~MESSAGE~$]</span><br>
+<br><FONT size=-1>[$~SETHOMEPAGE~$][$~BOTTOMLINE~$]</font></p>
+<p><FONT size=-2>&copy;2005 Google - Searching [NUM_ITEMS] items</font></p></center></body></html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/hover.html b/chromium/tools/grit/grit/testdata/hover.html
new file mode 100644
index 00000000000..b8f9ce0200e
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/hover.html
@@ -0,0 +1,177 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
+P { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
+TD { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
+A { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
+DIV { FONT-SIZE: 8pt; TEXT-DECORATION: none }
+A:hover { COLOR: #ffffff }
+.border { BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px }
+</style>
+
+<!-- menu experiment start -->
+
+<style>
+<!--
+.menu1 {
+cursor:default;
+position:absolute;
+left: 10;
+top: 0;
+text-align: left;
+font-family: Arial, Helvetica, sans-serif;
+font-size: 8pt;
+background-color: menu;
+visibility: hidden;
+padding-top: 2px;
+padding-bottom: 2px;
+border: 1 solid;
+border-color: #888888;
+z-index: 100;
+}
+.menuitems {
+padding-left: 5px;
+padding-right: 5px;
+}
+-->
+</style>
+<SCRIPT LANGUAGE="JavaScript1.2">
+<!--
+var menustyle = "menu1";
+
+function showmenu() {
+ // var rightedge = document.body.clientWidth-event.clientX;
+ // var bottomedge = document.body.clientHeight-event.clientY;
+ // if (rightedge < rcmenu.offsetWidth)
+ // rcmenu.style.left = document.body.scrollLeft + event.clientX - rcmenu.offsetWidth;
+ // else
+ // rcmenu.style.left = document.body.scrollLeft + event.clientX;
+ // if (bottomedge < rcmenu.offsetHeight)
+ // rcmenu.style.top = document.body.scrollTop + event.clientY - rcmenu.offsetHeight;
+ // else
+ // rcmenu.style.top = document.body.scrollTop + event.clientY;
+
+ rcmenu.style.visibility = "visible";
+ // rcmenu.style.zindex = 0;
+ // document.all('rcmenu').style.zindex = 20;
+ document.onkeydown=ck;
+ return false;
+}
+
+function hidemenu() {
+ rcmenu.style.visibility = "hidden";
+}
+
+function ck(e){
+ evt=document.all?window.event:e;
+ k=document.all?window.event.keyCode:e.keyCode;
+
+ if(k==27 /*<Esc>*/) {
+ hidemenu();
+ }
+}
+
+function menumouseover() {
+ if (event.srcElement.className == "menuitems") {
+ event.srcElement.style.backgroundColor = "highlight";
+ event.srcElement.style.color = "white";
+ }
+}
+
+function menumouseout() {
+ if (event.srcElement.className == "menuitems") {
+ event.srcElement.style.backgroundColor = "";
+ event.srcElement.style.color = "black";
+ window.status = "";
+ }
+}
+
+function menuselect() {
+ if (event.srcElement.className == "menuitems") {
+ if (event.srcElement.getAttribute("target") != null)
+ window.open(event.srcElement.url, event.srcElement.getAttribute("target"));
+ else if (event.srcElement.url.length)
+ window.location = event.srcElement.url;
+ }
+}
+// -->
+</script>
+
+<!-- menu experiment end -->
+
+</head>
+<BODY bottomMargin=0 bgColor=#3300cc leftMargin=0 topMargin=0 rightMargin=0 marginwidth="0" marginheight="0" border=0 style="border-width:0;" scroll=no>
+
+<!-- <br> -->
+
+<!-- menu experiment start -->
+
+<div id="rcmenu" class="skin0" onMouseover="menumouseover()" onMouseout="menumouseout()" onClick="menuselect();">
+<span class="menuitems" url="[$~SETDISP1~$]">Sidebar</span>
+<span class="menuitems" url="[$~SETDISP4~$]">Minibar</span>
+<span class="menuitems" url="[$~HIDE2~$]">Close</span>
+</div>
+
+<script language="JavaScript1.2">
+if (document.all && window.print) {
+ rcmenu.className = menustyle;
+ document.oncontextmenu = showmenu;
+ document.body.onclick = hidemenu;
+}
+</script>
+
+<!-- menu experiment end -->
+
+<script>
+function hide() {
+ return 1;
+ // return confirm("Are you sure you want to hide the minibar?\nYou can show it again in Google Desktop Search Preferences. ");
+}
+function clear() {
+ document.getElementById('q').value='';
+}
+</script>
+
+<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
+<tr><TD vAlign=top>
+
+<form method=get action="[$~SEARCHURL~$]" [$~SEARCH_TARGET~$] name=f1 ID="f1" onsubmit="window.setTimeout('clear()', 500)">
+<input type=hidden name=src value=3>
+<input type=hidden name=redir value='' ID="redir">
+
+<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
+
+<tr>
+<!-- border-top: #414a4f 0px solid; -->
+<!-- z-index:2; z-order:2; -->
+<TD vAlign=top>&nbsp;<INPUT name=q style="position:relative; height=19px;" class=border size=12>&nbsp;</td>
+
+<TD TABINDEX="2" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="f1.submit();q.value=''" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><IMG src="logo.gif" align=middle></td>
+
+<TD width=2><IMG height=1 width=1></td>
+
+<TD TABINDEX="3" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="redir.value='google'; f1.submit(); redir.value='';q.value=''" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><IMG src="gfavicon.ico" align=middle></td></tr>
+</TBODY></table>
+</td>
+
+<TD width=5><IMG height=1 width=1></td>
+
+<TD vAlign=top>
+
+<TABLE cellSpacing=0 cellPadding=1 bgColor=#000099><TBODY>
+<tr><TD TABINDEX="4" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' valign=top onclick="location.href='[$~SETDISP1~$]';" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="down.gif"></td></tr></TBODY></table>
+
+</td>
+
+<TD width=1><IMG height=1 width=1></td>
+
+<TD vAlign=top><TABLE cellSpacing=0 cellPadding=1><TBODY>
+<tr><TD TABINDEX="5" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' valign=top onclick="if (hide())location.href='[$~HIDE2~$]';" class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="close.gif"></td></tr></TBODY></table></td></tr></TBODY></table>
+
+</form>
+</body></html>
diff --git a/chromium/tools/grit/grit/testdata/include_test.html b/chromium/tools/grit/grit/testdata/include_test.html
new file mode 100644
index 00000000000..e08f2e2e8a2
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/include_test.html
@@ -0,0 +1,31 @@
+<include src="included_sample.html">
+<if expr="True">
+should be kept
+</if>
+in the middle...
+<if expr="False">
+should be removed
+</if>
+
+<if expr="False">
+should be removed
+ <if expr="True">
+ should be removed because outer expr is False
+ </if>
+should be removed
+</if>
+
+<if expr="True">
+ <if expr="True">
+ <if expr="True">
+ nested true should be kept
+ </if>
+ <if expr="False">
+ should be removed
+ </if>
+ </if>
+ <if expr="True">
+ silbing true should be kept
+ </if>
+</if>
+at the end...
diff --git a/chromium/tools/grit/grit/testdata/included_sample.html b/chromium/tools/grit/grit/testdata/included_sample.html
new file mode 100644
index 00000000000..7150ffcbea1
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/included_sample.html
@@ -0,0 +1 @@
+Hello Include!
diff --git a/chromium/tools/grit/grit/testdata/indexing_speed.html b/chromium/tools/grit/grit/testdata/indexing_speed.html
new file mode 100644
index 00000000000..db1787b0e2b
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/indexing_speed.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Google Desktop Search Index Speed</title>
+<meta http-equiv=content-type content="text/html; charset=utf-8">
+<style>
+BODY {
+ MARGIN-LEFT: 3em; MARGIN-RIGHT: 3em; FONT-FAMILY: arial,sans-serif
+}
+</style>
+</head>
+<BODY text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff>
+<TABLE cellSpacing=2 cellPadding=0 width="100%" border=0>
+ <tr>
+ <TD vAlign=top width="1%"><A href="[$~HOMEPAGE~$]">
+ <IMG alt="Go to Google Desktop Search" src="/logo3.gif" border=0></A></td>
+ <td>&nbsp;</td>
+ <TD noWrap>
+ <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
+ <tr>
+ <TD bgColor=#3399CC><IMG height=1 alt="" width=1></td>
+ </tr>
+ </table>
+ <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
+ <tr>
+ <TD noWrap bgColor=#efefef><B>&nbsp;Index Speed</B></td>
+ <TD noWrap align=right bgColor=#efefef><FONT size=-1><A href="/customize.html">Index Speed
+ Help</A> | <A href="[$~ABOUT~$]"> About Google Desktop Search</A></font></td>
+ </tr></table></td></tr></table>
+<FONT size=-1>
+<p>
+To make your emails, files, and previously viewed web pages searchable, Google Desktop Search
+needs to index them. This indexing process is currently occuring in the background
+and your computer performance is minimally impacted.
+<p>
+You have the option of speeding up this process.
+<p><B><FONT color=#FF0000>Warning:</font></B> Speeding up indexing will cause your computer
+to become unusable for many minutes, depending on how many items need to be indexed. FAST INDEXING IS NOT
+RECOMMENDED.
+<BR>&nbsp;<BR>
+<FORM action="[$~SETINDEXSPEED~$]" method=GET>
+<input name=url value="[PREVPAGE]" type=hidden>
+<input type=radio name=FAST value="0" [FAST0-CHECKED] id=f0><label for=f0>Use background indexing (recommended)</label><br>
+<input type=radio name=FAST value="1" [FAST1-CHECKED] id=f1><label for=f1>Use fast indexing</label><br><br>
+<input type=submit value="Set Indexing Speed">
+</FORM>
+<BR>
+
+<p>&nbsp;<BR>
+<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
+<TR bgColor=#3399CC>
+ <TD align=middle height=1><IMG height=1 alt="" width=1></td></tr>
+</table>
+
+<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center bgColor=#efefef border=0>
+<tr>
+ <TD align=middle height=20><FONT size=-1><A href="[$~HOMEPAGE~$]">Google Desktop Search&nbsp;Home</A> - <a href="[$~STATUS~$]">Status</a> - <A href="[$~ABOUT~$]">About Google Desktop Search</A> - [$~BUILDNUMBER~$] - &copy;2005 Google </font> </td></tr>
+</table><BR>
+</body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/install_prefs.html b/chromium/tools/grit/grit/testdata/install_prefs.html
new file mode 100644
index 00000000000..eca0b56de52
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/install_prefs.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Google Desktop Search: Initial Preferences</title>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY { FONT-FAMILY: arial,sans-serif }
+.c:active { COLOR: #FF0000 }
+.c:visited { COLOR: #7777CC }
+.c:link { COLOR: #7777CC }
+</style>
+<script>
+<!--
+override = 1;
+function ee() {if (override==1) {(new Image()).src="[COMPLETING]";}}
+// -->
+</script>
+</head><body leftmargin=30 rightmargin=30 onresize="stw()" onunload="ee()">
+<form onsubmit='override=0;return true;' action='[STEP2]' name=f method=post>
+<img src="logo3.gif" border=0>
+<div id=c1 style="width:600px">
+<br><font color=#00218a><b>To continue, please set these initial preferences:</b></font><br><br>
+<table border=0 id=t1 width=100%>
+<tr>
+ <td valign=top><input name=AIM id=chat type=checkbox checked></td>
+ <td>&nbsp;</td><td><label for=chat><font size=-1><B>Enable search over Instant Messenger chats</b><br>
+ <font size=-1>Google Desktop Search will store your chats and make them searchable.
+</font></label></td></tr>
+<tr height=1><td height=10px></td></tr>
+<tr>
+ <td valign=top><input name=HTTPS id=https type=checkbox checked></td>
+ <td>&nbsp;</td><td><label for=https><font size=-1><b>Enable search over secure web pages (HTTPS)</b>
+ <br><font size=-1>Google Desktop Search will store secure web pages that you view and make them
+ searchable.</font></label> </td></tr>
+<tr height=1px><td height=10px></td></tr>
+
+<tr>
+ <td valign=top><input name=SEARCHBOX id=SEARCHBOX type=checkbox checked
+ onclick="handleSBClick(this)"></td>
+ <td>&nbsp;</td><td><label for=searchbox><font size=-1><b>Display search box</b></label>
+ <br><table border=0 cellpadding=0><tr><td valign=top>
+
+<input type="radio" name="SBDISPLAY" id="DISPLAYDB" [DB-CHECKED] value="DISPLAYDB"></td><td>
+<label for=DISPLAYDB><font size=-1>Deskbar - A search box in your taskbar</font></label></td></tr>
+<tr><td></td></tr>
+<tr><td></td><td><img src="deskbar.gif" alt="Deskbar" width="268" height="34"></td></tr>
+<tr><td height=2></td></tr>
+<tr><td valign=top>
+
+<input type="radio" name="SBDISPLAY" id="DISPLAYMB" [MB-CHECKED] VALUE="DISPLAYMB"></td><td>
+<label for=DISPLAYMB><font size=-1>Floating Deskbar - A search box that you can put anywhere on your desktop</font></label></td></tr>
+<tr><td></td></tr>
+<tr><td></td><td><img src="minibar.gif" width="137" height="27"></td></tr>
+<tr><td height=2></td></tr>
+
+</table>
+</td></tr>
+
+<tr>
+ <td valign=top><input name=SENDDATA id=usage type=checkbox checked></td>
+ <td>&nbsp;</td><td><label for=usage><font size=-1><b>Help us improve Google Desktop Search by sending usage data and crash reports</b></label>
+</font></td></tr>
+<tr height=8px><td colspan=3 height=8px></td></tr>
+<tr><td colspan=3><font size=-1>You can change these and other preferences at any time.</font></td></tr>
+</table></div>
+<p><input type=submit value="Set Preferences and Continue" id=s><br>
+</form>
+</center>
+[SCRIPT]
+<script>
+<!--
+function handleSBClick(checkbox) {
+ document.getElementById("DISPLAYDB").disabled = !checkbox.checked;
+ document.getElementById("DISPLAYMB").disabled = !checkbox.checked;
+}
+function stw() {
+if (document.all && document.body.clientWidth < 600) {
+ var w = document.body.clientWidth-35;
+ if (w < 10) { w = 10; }
+ w = w + 'px';
+ document.getElementById('c1').style.width=w;
+ return false;
+}
+document.getElementById('c1').style.width='600px';
+}
+stw();
+document.f.s.focus();
+// -->
+</script>
+<img SRC="http://www.google.com" WIDTH="0" HEIGHT="0" ALIGN="right"></img>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/install_prefs2.html b/chromium/tools/grit/grit/testdata/install_prefs2.html
new file mode 100644
index 00000000000..18380397c29
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/install_prefs2.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Indexing has Started</title>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY { FONT-FAMILY: arial,sans-serif }
+}
+</style>
+<script>
+<!--
+override = 1;
+function ee() {if (override==1) {(new Image()).src="[COMPLETING]";}}
+// -->
+</script>
+</head><body leftmargin=30 rightmargin=30 onresize="stw()" onunload="ee()">
+<form onsubmit='override=0;return true;' action="[STEP3]" name=f>
+<img src="/logo3.gif" border=0><br><br>
+<div id=c1 style="width:575px">
+<table border=0 id=t1 width=100%><tr><td>
+<font color=#00218a><b>One-time indexing has started.</b></font><br><br>
+<font size=-1>An index is being prepared on your computer to allow you
+to search your information as fast as you can search the web.<br><br>
+<li>This is a one-time process that may take several hours.
+<li>You may continue to use your computer as usual and it is safe to shut down your computer.
+<li>Indexing will be performed only when your computer is idle.
+</ul>
+</font>
+<p><input type=submit value="Go to the Desktop Search homepage" name=s><br>
+</center>
+</td></tr></table>
+</form>
+</div>
+<script>
+<!--
+function stw() {
+if (document.all && document.body.clientWidth < 575) {
+ var w = document.body.clientWidth-35;
+ if (w < 10) { w = 10; }
+ w = w + 'px';
+ document.getElementById('c1').style.width=w;
+ return false;
+}
+document.getElementById('c1').style.width='575px';
+}
+stw();
+// -->
+document.f.s.focus();
+</script>
+[SCRIPT]
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/klonk-alternate-skeleton.rc b/chromium/tools/grit/grit/testdata/klonk-alternate-skeleton.rc
new file mode 100644
index 00000000000..5f2c82a5546
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/klonk-alternate-skeleton.rc
Binary files differ
diff --git a/chromium/tools/grit/grit/testdata/klonk.ico b/chromium/tools/grit/grit/testdata/klonk.ico
new file mode 100644
index 00000000000..d371b214dc3
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/klonk.ico
Binary files differ
diff --git a/chromium/tools/grit/grit/testdata/klonk.rc b/chromium/tools/grit/grit/testdata/klonk.rc
new file mode 100644
index 00000000000..35652c4e6dd
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/klonk.rc
Binary files differ
diff --git a/chromium/tools/grit/grit/testdata/ko_oem_enable_bug.html b/chromium/tools/grit/grit/testdata/ko_oem_enable_bug.html
new file mode 100644
index 00000000000..f2c199cc15b
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/ko_oem_enable_bug.html
@@ -0,0 +1 @@
+<IMG style="VERTICAL-ALIGN: middle" height=16 alt=아웃룩 src="/email.gif" width=16> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/ko_oem_non_admin_bug.html b/chromium/tools/grit/grit/testdata/ko_oem_non_admin_bug.html
new file mode 100644
index 00000000000..b9e8a1f2885
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/ko_oem_non_admin_bug.html
@@ -0,0 +1 @@
+<INPUT id=s type=submit value="&nbsp;&nbsp;확ì¸&nbsp;&nbsp;"> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/mini.html b/chromium/tools/grit/grit/testdata/mini.html
new file mode 100644
index 00000000000..8ac0a231a0f
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/mini.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head>
+<meta http-equiv=content-type content="text/html; charset=windows-1252">
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
+P { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
+TD { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
+A { FONT-SIZE: 8pt; FONT-FAMILY: verdana,arial,san-serif }
+DIV { FONT-SIZE: 8pt; TEXT-DECORATION: none }
+A:hover { COLOR: #ffffff }
+.border { BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px }
+</style>
+</head>
+
+<BODY bottomMargin=0 bgColor=#3300cc leftMargin=0 topMargin=0 rightMargin=0 marginwidth="0" marginheight="0">
+
+<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
+<tr><TD vAlign=top>
+
+<TABLE cellSpacing=0 cellPadding=0 bgColor=#3300cc border=0><TBODY>
+
+<tr>
+<TD vAlign=top>&nbsp;<INPUT style="position:relative; height=17px;" class=border size=10>&nbsp;</td>
+
+<TD class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=center align=middle bgColor=#000099><img height=1 width=1><IMG src="logo.gif" align=middle><img height=1 width=1></td>
+
+</TBODY></table>
+</td>
+
+<TD width=2><IMG height=1 width=1></td>
+
+<TD vAlign=top><TABLE cellSpacing=0 cellPadding=1><TBODY>
+<tr><TD class=ch onmouseover="this.bgColor='6666FF'" style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #6666cc 1px solid; BORDER-LEFT: #6666cc 1px solid; BORDER-BOTTOM: #000000 1px solid" onmouseout="this.bgColor='#000099'" vAlign=top noWrap bgColor=#000099><IMG src="mini_close.gif"></td></tr></TBODY></table></td></tr></TBODY></table></body></html>
diff --git a/chromium/tools/grit/grit/testdata/oem_enable.html b/chromium/tools/grit/grit/testdata/oem_enable.html
new file mode 100644
index 00000000000..db6b85eca6f
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/oem_enable.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Google Desktop Search Download</title>
+<meta http-equiv=content-type content="text/html; charset=utf-8">
+<style>BODY {
+ FONT-FAMILY: arial,sans-serif
+}
+TD {
+ FONT-FAMILY: arial,sans-serif
+}
+DIV {
+ FONT-FAMILY: arial,sans-serif
+}
+.p {
+ FONT-FAMILY: arial,sans-serif
+}
+A {
+ FONT-FAMILY: arial,sans-serif
+}
+DIV {
+ COLOR: #000
+}
+TD {
+ COLOR: #000
+}
+A:link {
+ COLOR: #00c
+}
+A:visited {
+ COLOR: #551a8b
+}
+</style>
+
+<meta content="mshtml 6.00.2800.1476" name=generator></head>
+<body>
+<center>
+<TABLE cellSpacing=0 cellPadding=0 border=0>
+ <TBODY>
+ <TR vAlign=center>
+ <td>
+ <DIV align=center><IMG height=55 alt="Google Desktop Search"
+ src="/logo3.gif" width=150 border=0 search=""
+ desktop=""></DIV></td>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td><FONT size=+1><B>Search your own
+computer.</B></font></td></tr></TBODY></table><BR>
+<TABLE cellSpacing=0 cellPadding=0 width=630 border=0>
+ <TBODY>
+ <tr>
+ <TD vAlign=top width="53%"><FONT size=-1>
+ <LI>Find your email, files, web history and chats instantly <NOBR>
+ <LI>View web pages you've seen, even when you're not online</NOBR>
+ <LI>Search as easily as you do on Google
+ <p><B>Google Desktop Search finds:</B></p></font>
+ <TABLE cellSpacing=1 cellPadding=0 width=325 border=0 valign="center">
+ <TBODY>
+ <TR vAlign=center>
+ <TD colSpan=3><FONT size=-1><IMG style="VERTICAL-ALIGN: middle"
+ height=16 alt=Outlook src="/email.gif"
+ width=16>&nbsp;&nbsp;Email from Outlook, Outlook Express, &amp;
+ Thunderbird</font></td></tr>
+ <tr>
+ <TD noWrap colSpan=3><FONT size=-1><IMG
+ style="VERTICAL-ALIGN: middle" height=16 alt="Internet Explorer"
+ src="/html.gif" width=16>&nbsp;&nbsp;Web history
+ from IE/Firefox/Mozilla/Netscape</font></td></tr>
+ <tr>
+ <TD noWrap colSpan=3><FONT size=-1><IMG
+ style="VERTICAL-ALIGN: middle" height=16 alt=Text
+ src="/file.gif" width=16>&nbsp;&nbsp;Files in Word,
+ Excel, Powerpoint, PDF, &amp; media formats</font></td></tr>
+ <tr>
+ <TD vAlign=top colSpan=3><FONT size=-1><IMG
+ style="VERTICAL-ALIGN: middle" height=16 alt="AOL IM"
+ src="/aim.gif" width=16>&nbsp;&nbsp;Chats from AOL
+ Instant Messenger</font></td></tr>
+ <tr>
+ <TD noWrap><FONT size=-1>&nbsp;</font></td></tr></TBODY></table><FONT
+ size=-1>&nbsp;</font><FONT size=-1><A
+ href="http://desktop.google.com/about.html">About Desktop
+ Search</A>&nbsp;&nbsp; <A
+ href="http://desktop.google.com/screenshots.html">Screenshots</A>&nbsp;&nbsp;
+ <A href="http://desktop.google.com/support">Help</A>&nbsp;&nbsp; <A
+ href="http://desktop.google.com/feedback.html">Contact
+ Us</A><BR></font></LI></td>
+ <td>&nbsp;&nbsp;&nbsp;</td>
+ <TD vAlign=top width="53%">
+ <TABLE cellPadding=2 width="100%" align=center>
+ <TBODY>
+ <tr>
+ <TD
+ style="BORDER-RIGHT: rgb(204,204,204) 1px solid; BORDER-TOP: rgb(204,204,204) 1px solid; BORDER-LEFT: rgb(204,204,204) 1px solid; BORDER-BOTTOM: rgb(204,204,204) 1px solid"
+ width="100%" bgColor=#e7eff7 blah2="#fff8dd" blah="#e7eaf7"><BR>
+ <center><FONT size=-1>By using, you agree to our <A
+ href="http://desktop.google.com/eula.html"><BR>Terms &amp;
+ Conditions</A> and <A
+ href="http://desktop.google.com/privacypolicy.html">Privacy
+ Policy</A></font></center>
+ <p></p>
+ <FORM action='[STEP2]'>
+ <P align=center><INPUT style="PADDING-RIGHT: 3px; PADDING-LEFT: 3px; FONT-WEIGHT: bold; FONT-SIZE: 17px; PADDING-BOTTOM: 4px; PADDING-TOP: 4px" type=submit value="Agree and Start Using" name=Submit>
+ </p></FORM><FONT size=-2>* Automatically starts when you turn on
+ your computer</font> </td></tr></TBODY></table>
+ <p></p></td></tr></TBODY></table></center>
+<p></p>
+<center><FONT color=#666666 size=-2>©2005 Google</font>
+<p></p></center></body></html>
diff --git a/chromium/tools/grit/grit/testdata/oem_non_admin.html b/chromium/tools/grit/grit/testdata/oem_non_admin.html
new file mode 100644
index 00000000000..8b7ca13e217
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/oem_non_admin.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Google Desktop Search Preferences</title>
+<meta http-equiv=cache-control content=no-cache>
+<meta http-equiv=content-type content="text/html; charset=utf-8">
+<meta http-equiv=pragma content=no-cache>
+<meta http-equiv=expires content=-1>
+<style>BODY {
+ FONT-FAMILY: arial,sans-serif
+}
+.c:active {
+ COLOR: #ff0000
+}
+.c:visited {
+ COLOR: #7777cc
+}
+.c:link {
+ COLOR: #7777cc
+}
+</style>
+
+<script>
+<!--
+override = 1;
+function ee() {if (override==1) {(new Image()).src="/doneinstallprefs&s=3286011577";}}
+// -->
+</script>
+
+<meta content="mshtml 6.00.2800.1476" name=generator></head>
+<BODY onresize=stw() leftMargin=30 rightMargin=30 onunload=ee()>
+<FORM name=f onsubmit=javascript:window.close();><IMG
+src="/logo3.gif" border=0>
+<DIV id=c1 style="WIDTH: 600px">
+<p><BR><FONT color=#00218a><B>We're sorry, but you need administrator access to
+enable Desktop Search.</B></font></p><FONT size=-1>
+<p>To install or run Google Desktop Search you need administrator access on this
+computer. Please try installing again once you have administrator
+access.</p></font></DIV>
+<p><INPUT id=s type=submit value=&nbsp;&nbsp;OK&nbsp;&nbsp;> <BR></p>
+<center></center></FORM></body></html>
diff --git a/chromium/tools/grit/grit/testdata/onebox.html b/chromium/tools/grit/grit/testdata/onebox.html
new file mode 100644
index 00000000000..c24ff043a5b
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/onebox.html
@@ -0,0 +1,21 @@
+<html><head><title>Google Desktop Search Results</title>
+<style><!--
+body,td,div,.p,a{font-family:arial,sans-serif }
+body{ background-color: transparent }
+div,td{color:#000}
+.f,.fl:link{color:#6f6f6f}
+a:link,.w,a.w:link,.w a:link{color:#00c}
+a:visited,.fl:visited{color:#551a8b}
+a:active,.fl:active{color:#f00}
+.t a:link,.t a:active,.t a:visited,.t{color:#000}
+//-->
+</style>
+</head>
+<body>
+<table cellspacing=0 cellpadding=1 border=0 ID="Google Desktop Search">
+<tr><td colspan=2><nobr><a href="http://[WEBSERVER][$~QUERY~$]" target=_parent>[NUMRESULTS] [RESULT-STRING] stored on your computer</a><font size=-1>&nbsp;-&nbsp;<a href="[HIDENOW]" style="color:#7777cc;" target=_parent>Hide</a>&nbsp;-&nbsp;<a href="http://desktop.google.com/integration.html" style="color:#7777cc;" target=_parent>About</a></font></nobr></td></tr>
+<tr><td valign=top width=40><img height=27 style="margin-top:2px;" src="http://[WEBSERVER]/onebox.gif"></td>
+<td valign=top width="99%"><font size=-1>[RESULTS]</font></td></tr>
+</table>
+</body>
+</html>
diff --git a/chromium/tools/grit/grit/testdata/oneclick.html b/chromium/tools/grit/grit/testdata/oneclick.html
new file mode 100644
index 00000000000..32dc6459dd0
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/oneclick.html
@@ -0,0 +1,34 @@
+[HEADER]
+
+
+<TABLE cellSpacing=4 cellPadding=0 width="100%" border=0>
+<tr>
+ <TD vAlign=top align=left width=50%>
+ [EMAIL_TOP_CHROME]
+
+ <p class=f>
+ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0>
+ [EMAIL]
+ </table>
+ </td>
+
+
+ <TD width=1 align=middle bgColor=#cfcfcf><IMG height=1 width=1></td>
+ <TD width=50% vAlign=top align=left>
+ [FREQ_TOP_CHROME]
+ <p class=f>
+ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0 ID="Table1">
+ [$~FREQ~$]
+ </table>
+ <p class=g>
+ [RECENT_TOP_CHROME]
+ <TABLE cellSpacing=6 cellPadding=0 width="100%" border=0 ID="Table2">
+ [$~RECENT~$]
+ </table>
+ </td>
+ </tr>
+</table>
+<center><BR>
+
+
+[FOOTER]
diff --git a/chromium/tools/grit/grit/testdata/password.html b/chromium/tools/grit/grit/testdata/password.html
new file mode 100644
index 00000000000..16007a1ac06
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/password.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Password Required</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
+.q {COLOR: #0000cc}
+</style>
+<script>
+<!--
+function sf(){document.f.q.focus();}
+// -->
+</script>
+</head>
+<body text=#000000 vLink=#551a8b aLink=#ff0000 link=#0000cc bgColor=#ffffff onload=sf()>
+<center>
+<table cellSpacing=0 cellPadding=0 border=0>
+<tr><td><a href="[$~HOMEPAGE~$]"><IMG border=0 height=110 alt="Google Desktop Search" src="hp_logo.gif" width=276></a></td></tr></table><BR>
+<form name=f method=GET action='/password'>
+<table cellSpacing=0 cellPadding=4 border=0>
+<tr><td class=q noWrap><font size=-1>
+ <table cellSpacing=0 cellPadding=0>
+ <tr vAlign=top>
+ <td align=middle>Password required:&nbsp;&nbsp;<input maxLength=80 size=30 type=password name=pw value="">
+ <script>
+ document.f.q.focus();
+ </script>
+ &nbsp;<input type=submit value="Submit" name=submit>
+ </td></tr>
+ </table>
+ </form>
+</td></tr>
+</table>
+<br><font size=-1>[$~BOTTOMLINE~$]</font></p>
+<p><font size=-2>&copy;2005 Google</font></p></center></body></html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/preferences.html b/chromium/tools/grit/grit/testdata/preferences.html
new file mode 100644
index 00000000000..b37412436bc
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/preferences.html
@@ -0,0 +1,234 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html><head><title>Google Desktop Search Preferences</title>
+<meta http-equiv=content-type content="text/html; charset=utf-8">
+<style>
+body {
+ margin-left: 2em; margin-right: 2em;
+ font-family: arial,sans-serif;
+ color:#000; background-color:#fff;
+}
+a:active { color:#f00 }
+a:visited { color:#551a8b }
+a:link { color:#00c }
+a.c:active { color: #ff0000 }
+a.c:visited { color: #7777cc }
+a.c:link { color: #7777cc }
+.b { font-weight: bold }
+.shaded-header { background-color: #e8f4f7; border-top: 1px solid #39c;
+margin: 0px; padding: 0px }
+.shaded-subheader { background-color: #e8f4f7; margin: 12px 0px 0px 0px;
+ padding: 0px }
+.plain-subheader { background-color: #fff; margin: 12px 0px 0px 0px;
+ padding: 0px }
+.header-element { margin: 0px; padding: 2px}
+.expand { width: 98% }
+.s { font-size: smaller }
+.prefgroup { border: 2px solid #e8f4f7; width: 100% }
+.phead { font-weight: bold; font-size: smaller; vertical-align: top;
+text-transform: capitalize; border-bottom: 2px solid #e8f4f7; margin: 0px;
+padding: 8px}
+.pbody { border-bottom: 2px solid #e8f4f7; margin: 0px;
+padding: 8px}
+.pref-last { border-bottom: 0px }
+.example { color: gray; font-family: monospace; }
+</style>
+<script>
+<!--
+function validate() {}
+function fnOnClickAll() {for (var i = 0; i < document.langform.lr.length; i++) {
+document.langform.lr[i].checked = false;}}
+function fnOnClickSome() {
+var count = 0;for (var i = 0; i < document.langform.lr.length; i++) {
+if (document.langform.lr[i].checked) {count++;}}
+document.langform.lang[0].checked = (count <= 0);
+document.langform.lang[1].checked = (count > 0);}
+// -->
+</script>
+</head>
+<body onload="checkOffice()">
+<form name=prefs action="[$~SETPREFS~$]" method=post><input name=url
+value="[PREVPAGE]" type=hidden>
+<table cellspacing=2 cellpadding=0 width="100%" border=0>
+<tr>
+<td valign=top width="1%"><a href="[$~HOMEPAGE~$]">
+<img alt="Go to Google Desktop Search" src="logo3.gif" border=0></a></td>
+<td>&nbsp;</td>
+<td nowrap>
+
+<table class="shaded-header"><tr>
+<td class="header-element b expand">Preferences</td>
+<td class="header-element s">
+<a href="http://desktop.google.com/preferences.html">Preferences&nbsp;Help</a>
+</td>
+</tr></table>
+
+</tr></table>
+
+<table class="shaded-subheader"><tr>
+<td class="header-element expand s">
+<span class="b">Save</span> your preferences when finished.</td>
+<td class="header-element"><input type=submit value="Save Preferences"
+name=submit2></td>
+</tr></table>
+
+[STATUS-MESSAGE]
+<table class="plain-subheader"><tr>
+<td class="header-element expand"><span class="b">Preferences</span><span
+class="s"> (changes apply to Google Desktop Search application)</span></td>
+</tr></table>
+
+<table class="prefgroup" cellpadding=0 cellspacing=0>
+
+<!-- -->
+<tr>
+<td class="phead">Search types</td>
+<td class="pbody"><div class="s">Index the following items so that you can
+search for them:<br />&nbsp;</div>
+<div>
+ <table border=0>
+ <tr>
+ <td width=150 nowrap valign=top><span class="s">
+ <input type=checkbox [CHECK-EMAIL] name=EMAIL id=h3><label for=h3>
+ Email</label><br>
+ <input type=checkbox [CHECK-AIM] name=AIM id=h5><label for=h5> Chats
+ (AOL/MSN IM)</label><br>
+ <input type=checkbox onclick='if(!this.checked){h12.checked=0;h12.disabled=1;}
+ else {h12.disabled=0;}' [CHECK-WEB] name=WEB id=h11><label for=h11> Web
+ history</label>
+
+ </span></td>
+ <td width=120 nowrap valign=top><span class="s">
+ <script>
+<!--
+function checkOffice() { var w = document.getElementById("h7");
+var e = document.getElementById("h8"); var o = document.getElementById("h10");
+if (!(w.checked || e.checked)) { o.checked=0;o.disabled=1;} else {o.disabled=0;} }
+// -->
+ </script>
+ <input type=checkbox [CHECK-DOC] name=DOC id=h7 onclick='checkOffice()'>
+ <label for=h7> Word</label><br>
+ <input type=checkbox [CHECK-XLS] name=XLS id=h8 onclick='checkOffice()'>
+ <label for=h8> Excel</label><br>
+ <input type=checkbox [CHECK-PPT] name=PPT id=h9>
+ <label for=h9> PowerPoint</label><br>
+ </span></td><td nowrap valign=top><span class="s">
+ <input type=checkbox [CHECK-PDF] name=PDF id=hpdf>
+ <label for=hpdf> PDF</label><br>
+ <input type=checkbox [CHECK-TXT] name=TXT id=h6>
+ <label for=h6> Text, media, and other files</label><br>
+ </tr>
+ <tr><td nowrap valign=top colspan=3><span class="s"><br />
+ <input type=checkbox [CHECK-SECUREOFFICE] name=SECUREOFFICE id=h10>
+ <label for=h10> Password-protected Office documents (Word, Excel)</label><br />
+ <input type=checkbox [DISABLED-HTTPS] [CHECK-HTTPS] name=HTTPS id=h12><label
+ for=h12> Secure pages (HTTPS) in web history</label></span></td></tr>
+</table>
+</div></td></tr>
+</div>
+</td>
+</tr>
+
+<!-- -->
+<tr>
+<td class="phead">Plug-ins</td>
+<td class="pbody"><div class="s"
+style="display:[ADDIN-DISPLAYSTYLE]">Index these additional items:<p>
+[ADDIN-DO]
+[ADDIN-OPTIONS]</div><div class="s">
+To install plug-ins to index other items, visit the
+<a href="http://desktop.google.com/plugins.html">Plug-ins Download page</a>.</div>
+</tr>
+
+<!-- -->
+<tr>
+<td class="phead">Don't search these items</td>
+<td class="pbody"><div class="s">
+<label for=FORBIDDEN>Do not search web sites with the following URLs or files
+with the following paths. Put each entry on a separate line. Examples:</label><br>
+<span class="example">c:\Documents and Settings\username\Private Stuff</span><br>
+<span class="example">http://www.domain.com/</span><br>
+<div>&nbsp;</div>
+<div><TEXTAREA rows=3 cols=65 name=FORBIDDEN id=FORBIDDEN>[FORBIDDEN]
+</TEXTAREA></div>
+</tr>
+
+<!-- -->
+<tr>
+<td class="phead pref">Search Box Display</td>
+<td class="pbody pref" valign=top>
+
+<table border=0 cellpadding=0><tr><td valign=top>
+
+<input type="radio" name="SBDISPLAY" id="DISPLAYDB" [CHECK-DISPLAYDB] value="DISPLAYDB"></td><td>
+<label for=DISPLAYDB><font size=-1>Deskbar - A search box in your taskbar</font></label></td></tr>
+<tr><td></td></tr>
+<tr><td></td><td><img src="deskbar.gif" alt="Deskbar" width="268" height="34"></td></tr>
+<tr><td height=2></td></tr>
+<tr><td valign=top>
+
+<input type="radio" name="SBDISPLAY" id="DISPLAYMB" [CHECK-DISPLAYMB] VALUE="DISPLAYMB"></td><td>
+<label for=DISPLAYMB><font size=-1>Floating Deskbar - A search box you can put anywhere on your desktop</font></label></td></tr>
+<tr><td></td></tr>
+<tr><td></td><td><img src="minibar.gif" width="137" height="27"></td></tr>
+<tr><td height=2></td></tr>
+<tr><td valign=top>
+
+<input type=radio name="SBDISPLAY" id="DISPLAYNONE" [CHECK-DISPLAYNONE] VALUE="DISPLAYNONE"></td><td valign=top>
+<label for=DISPLAYNONE><font size=-1> None</font></label>
+</td></tr>
+</table>
+
+</td></tr>
+
+<!-- -->
+<tr>
+<td class="phead pref">Number of Results</td>
+<td class="pbody pref"><label for=num><span class="s">
+Display <select name=num id="num">
+<option [CHECK-NUM-10]>10
+<option [CHECK-NUM-20]>20
+<option [CHECK-NUM-30]>30
+<option [CHECK-NUM-50]>50
+<option [CHECK-NUM-100]>100</select>
+ results per page</span></label>
+</td>
+</tr>
+
+<!-- -->
+<tr>
+<td class="phead">Google integration</td>
+<td class="pbody">
+<table border=0 cellpadding=0>
+<tr><td><input type=CHECKBOX name=ONEBOX [CHECK-ONEBOX] id=onebox></td>
+<td><label for=onebox>
+ <span class="s">Show Desktop Search results on Google Web Search result pages.
+ </span></label></td></tr>
+ <tr><td></td><td>
+ <span class="s">Your personal results are private from Google.</span>
+ </td></tr></table>
+</td>
+</tr>
+
+<!-- -->
+<tr>
+<td class="phead pref-last">Help us improve</td>
+<td class="pbody pref-last">
+<input type=CHECKBOX name=SENDDATA id="SENDDATA" [CHECK-SENDDATA]><label for=
+SENDDATA> <span class="s">Send non-personal usage data and crash reports to
+Google to help improve Desktop Search.</span></label>
+</td>
+</tr>
+
+</table>
+
+<table class="shaded-subheader"><tr>
+<td class="header-element expand s"><span class="b">Save</span> your preferences
+when finished.</td>
+<td class="header-element"><input type=submit value="Save Preferences"
+name=submit2></td>
+</tr></table>
+
+<p><div align=center>[$~BOTTOMLINE~$]</div>
+<br><center><span class="s">&copy;2005 Google</span></center>
+</form></body></html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/privacy.html b/chromium/tools/grit/grit/testdata/privacy.html
new file mode 100644
index 00000000000..1d45f4a5393
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/privacy.html
@@ -0,0 +1,35 @@
+[!]
+title Privacy and Google Desktop Search
+template
+privacy_bottomline
+hp_image
+
+<TABLE CELLSPACING=0 CELLPADDING=5 WIDTH="98%" BORDER=0>
+<TR VALIGN=TOP>
+<td>
+<h4>Privacy and Google Desktop Search</h4>
+
+<p><FONT SIZE=-1>Google is committed to making search on your desktop as easy
+as searching the web. We recognize that privacy is an important issue,
+so we designed and built Google Desktop Search with respect for your privacy.
+<p>
+So that you can easily search your computer, the Google Desktop Search application indexes
+and stores versions of your files and other computer activity,
+such as email, chats, and web history. These versions may also be mixed
+with your Web search results to produce
+results pages for you that integrate relevant content from your computer and
+information from the Web.
+<p>
+Your computer's content is not made accessible to Google or anyone else without your explicit permission.
+
+<p>You can read the
+<A HREF='http://desktop.google.com/privacypolicy.html?hl=[LANG_CODE]'>Privacy Policy</A>
+and <A HREF='http://desktop.google.com/privacyfaq.html?hl=[LANG_CODE]'>Privacy FAQ</A> online.
+</font>
+</td></tr></table>
+
+<center><br>
+<TABLE CELLSPACING=0 CELLPADDING=0 WIDTH="100%" BORDER=0>
+<TR BGCOLOR=#3399CC><TD ALIGN=MIDDLE HEIGHT=1><IMG HEIGHT=1 ALT="" WIDTH=1></td></tr></table>
+<FONT SIZE=-1>[$~PRIVACY_BOTTOMLINE~$] - &copy;2005 Google </font>
+</center> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/quit_apps.html b/chromium/tools/grit/grit/testdata/quit_apps.html
new file mode 100644
index 00000000000..a501b0e2bf2
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/quit_apps.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Google Desktop Search Preferences</title>
+<meta http-equiv=cache-control content=no-cache>
+<meta http-equiv=content-type content="text/html; charset=utf-8">
+<meta http-equiv=pragma content=no-cache>
+<meta http-equiv=expires content=-1>
+<style>BODY {
+ FONT-FAMILY: arial,sans-serif
+}
+.c:active {
+ COLOR: #ff0000
+}
+.c:visited {
+ COLOR: #7777cc
+}
+.c:link {
+ COLOR: #7777cc
+}
+</style>
+
+<script>
+<!--
+// -->
+</script>
+
+<meta content="mshtml 6.00.2800.1476" name=generator></head>
+<BODY onresize=stw() leftMargin=30 rightMargin=30>
+<FORM name=f action='[NEXTSTEP]' method=post><IMG src="/logo3.gif"
+border=0>
+<DIV id=c1 style="WIDTH: 600px">
+<p><BR><FONT color=#00218a><B>To start using Google Desktop Search, we may need to close the following programs if they are running:</B></font></p>
+<FONT size=-1><p>You can start these programs once Google Desktop Search is running.</p></font>
+
+<LI><FONT size=-1>AOL Instant Messenger</font>
+<LI><FONT size=-1>Firefox</font>
+<LI><FONT size=-1>Internet Explorer</font>
+<LI><FONT size=-1>Microsoft Excel</font>
+<LI><FONT size=-1>Microsoft Outlook </font>
+<LI><FONT size=-1>Microsoft Word </font>
+<LI><FONT size=-1>Mozilla</font>
+<LI><FONT size=-1>Mozilla Thunderbird</font>
+<LI><FONT size=-1>Netscape</font>
+<LI><FONT size=-1>Opera</font>
+<LI><FONT size=-1>Other web browsers</font>
+<FONT size=-1>
+<p>This will take only a few seconds to complete. </p></font></LI></DIV>
+<p><INPUT id=s type=submit name="quit" value="&nbsp;&nbsp;OK.&nbsp;&nbsp;Close&nbsp;these&nbsp;applications&nbsp;&nbsp;">
+ <INPUT id=s type=submit name="redir" value="&nbsp;&nbsp;Cancel.&nbsp;I'll&nbsp;run&nbsp;this&nbsp;later&nbsp;&nbsp;"><BR></p>
+<center></center></FORM></body></html>
diff --git a/chromium/tools/grit/grit/testdata/recrawl.html b/chromium/tools/grit/grit/testdata/recrawl.html
new file mode 100644
index 00000000000..0401e7c2b0b
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/recrawl.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Refresh index</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY,TD,A,P {FONT-FAMILY: arial,sans-serif}
+.q {COLOR: #0000cc}
+</style>
+</head>
+<body text="#000000" vLink="#551a8b" aLink="#ff0000" link="#0000cc" bgColor="#ffffff">
+<center>
+<table cellSpacing="0" cellPadding="0" border="0">
+<tr>
+<td><a href="[$~HOMEPAGE~$]"><img border="0" height="110" alt="Google Desktop Search" src="hp_logo.gif" width="276"></a>
+</td>
+</tr>
+</table>
+<br>
+<center>Google Desktop Search is now recrawling your drive to index new files.</center>
+<center>Note that new files are indexed automatically, and this step is generally not needed.</center>
+<center>Click <a href="[$~HOMEPAGE~$]">here</a> to continue.</center>
+</td></tr></table>
+<br>
+<font size="-1">[$~BOTTOMLINE~$]</font>
+<p><font size="-2">&copy;2005 Google</font></p>
+</center>
+</body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/resource_ids b/chromium/tools/grit/grit/testdata/resource_ids
new file mode 100644
index 00000000000..b230695b47f
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/resource_ids
@@ -0,0 +1,10 @@
+{
+ "SRCDIR": ".",
+ "test.grd": {
+ "messages": [100, 10000],
+ },
+ "<(FOO)/file.grd": {
+ },
+ "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools.grd": {
+ },
+}
diff --git a/chromium/tools/grit/grit/testdata/script.html b/chromium/tools/grit/grit/testdata/script.html
new file mode 100644
index 00000000000..f177d9c30e4
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/script.html
@@ -0,0 +1,38 @@
+<script>
+function run(n,cut){
+ var out = "", str = "abcdefghijklmnopqrstuvwxyz 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ,./:;'\"()*!?-_@[]{}#%`+=|\\>";
+ n.innerHTML = 'aa';
+
+ var base = n.scrollWidth;
+ for(var i=0;i<str.length;i++) {
+ n.innerHTML = 'a'+str.charAt(i)+'a';
+ out += str.charAt(i) + (n.scrollWidth-base) +";";
+
+ if(cut && !i && (n.scrollWidth-base == cut)) {
+ return '\x02'+"0;";
+ }
+ }
+ // extra cases for literals
+ n.innerHTML = 'a&lt;a';
+ out += '<' + (n.scrollWidth-base) +";";
+ n.innerHTML = 'a&amp;a';
+ out += '&' + (n.scrollWidth-base) +";";
+
+ var base_height = n.scrollHeight;
+ n.innerHTML += '<br>a';
+ out += '\x01' + (n.scrollHeight-base_height) +";";
+
+ return out;
+}
+
+function TEST_WIDTH() {
+ var n = document.getElementById('test');
+ var out = run(n[$~CUT~$]);
+ if (out.length>4){
+ n.style.fontWeight='bold';
+ out += run(n);
+ }
+ n.outerHTML = "";
+ (new Image()).src="[$~SETWIDTH~$]?src=[COMPONENT]&data="+escape(out).replace(/\+/g,"%2B");
+}
+</script>
diff --git a/chromium/tools/grit/grit/testdata/searchbox.html b/chromium/tools/grit/grit/testdata/searchbox.html
new file mode 100644
index 00000000000..9eccba99a55
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/searchbox.html
@@ -0,0 +1,22 @@
+<body bgcolor=#ffffff topmargin=2 marginheight=2>
+<table border=0 cellpadding=0 cellspacing=0 width=1%>
+<tr>
+<td valign=top><a href='[$~HOMEPAGE~$]'><img width=150 height=55 src="/logo3.gif" alt="Go to Google Desktop Search" border=0 vspace=12></a></td>
+<td>&nbsp;&nbsp;</td>
+<td valign=top>
+<table cellpadding=0 cellspacing=0 border=0><tr><td colspan=2 height=14 valign=bottom>
+<table border=0 cellpadding=4 cellspacing=0>
+<tr><td class=q><font size=-1>
+[$~LINKS~$]
+</tr>
+</table>
+</td>
+</tr>
+<tr><td nowrap><form name=gs method=GET action='[$~SEARCHURL~$]'><input type=text name=q size=41 maxlength=2048 value="[DISP_QUERY]"><input type=hidden name=ie value="UTF-8">
+<font size=-1>[$~FLAGS~$]<input type=submit name="btnG" value="Search Desktop"><span id=hf></span></font></td>
+<td><font size=-2>&nbsp;&nbsp;<a href='[$~PREFERENCES~$]'>Desktop&nbsp;Preferences</a><br>&nbsp;&nbsp;<a [DELETE_EXTRA] href=[DELETE_PAGE]><nobr>[DELETE_NAME]</nobr></a></font></td>
+</tr></table>
+<table cellpadding=0 cellspacing=0 border=0>
+<tr><td><font size=-1>&nbsp;</font></td></tr>
+</table>
+</td></tr></form></table> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/sidebar_h.html b/chromium/tools/grit/grit/testdata/sidebar_h.html
new file mode 100644
index 00000000000..e103e8f8db3
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/sidebar_h.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY,TD,DIV,A,.p { FONT-FAMILY: arial,sans-serif; SCROLL: no}
+DIV,TD {COLOR: #000}
+.f, .fl:link {COLOR: #6f6f6f}
+A:link { COLOR: #00c}
+A:visited { COLOR: #551a8b}
+A:active { COLOR: #f00}
+.fl:active { COLOR: #f00}
+.h { COLOR: #3399CC}
+.a, .a:link {COLOR: #008000}
+.b { FONT-WEIGHT: bold; FONT-SIZE: 12pt; COLOR: #00c}
+.g { MARGIN-TOP: .5em; MARGIN-BOTTOM: .5em}
+.f { MARGIN-TOP: 0.5em; MARGIN-BOTTOM: 0.25em}
+.c:active, .c:visited, .c:link { COLOR: #6f6f6f}
+.ch {CURSOR: hand}
+</style>
+</head>
+<BODY onload="TEST_WIDTH();" bottomMargin=0 leftMargin=2 topMargin=0 rightMargin=2 marginwidth=0 marginheight=0 SCROLL=NO bgcolor=#E0E0E0 style="border-style:solid; border-width:0;" oncontextmenu="return false;">
+
+<script>
+function hide() {
+ return 1;
+ // return confirm("Are you sure you want to hide the sidebar?\nYou can show it again in Google Desktop Search Preferences. ");
+}
+</script>
+
+
+<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%"><tr>
+<TD WIDTH="19%" VALIGN=TOP>
+
+<form method=get action="[$~SEARCHURL~$]">
+<input type=hidden name=src value=4>
+
+ <table cellspacing=0 cellpadding=0 width='1%'>
+ <tr><td nowrap align=center valign=middle><nobr><img width=16 height=16 src=logo.gif>&nbsp;<b><i><font color=#6F6F6F>Google Desktop Search</font></i></b><IMG id=ctl src="[CONTROL_IMAGE]" border=0 usemap="#control"></nobr></td></tr>
+ <tr><td nowrap align=center valign=middle><nobr><input TABINDEX="1" style="font-size:10px; width:'100%';" name="q" id="q"></nobr></td></tr>
+ <tr><td nowrap align=center valign=middle><nobr><input TABINDEX="2" style="font-size:10px" type=submit value="Local search" name=btnG> <input TABINDEX="3" style="font-size:9px" type=submit value="Web search" name=redir></nobr></td></tr>
+<MAP name="control">
+<area TABINDEX="4" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=1"' title="Move sidebar to Top" shape="rect" coords="9,0,22,8" href="/movesidebar?side=1" onmouseover="ctl.src='control1.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
+<area TABINDEX="5" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=3"' title="Move sidebar to Bottom" shape="rect" coords="9,9,22,17" href="/movesidebar?side=3" onmouseover="ctl.src='control3.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
+<area TABINDEX="6" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=0"' title="Move sidebar to Left" shape="rect" coords="0,2,8,15" href="/movesidebar?side=0" onmouseover="ctl.src='control0.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
+<area TABINDEX="7" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=2"' title="Move sidebar to Right" shape="rect" coords="23,2,31,15" href="/movesidebar?side=2" onmouseover="ctl.src='control2.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
+</MAP>
+ </table>
+</form>
+
+</td>
+<TD WIDTH="27%" VALIGN=TOP>
+
+[HEADER_SECTION1]
+[CONTENT_INBOX]
+
+</td>
+<TD WIDTH="27%" VALIGN=top>
+
+[HEADER_SECTION2]
+[CONTENT_HIST]
+
+</td>
+<TD WIDTH="27%" VALIGN=top>
+
+[CONTENT_NEWS]
+[CONTENT_OTHER]
+
+</td>
+<TD WIDTH="1%" VALIGN=top>
+
+<a TABINDEX="8" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick='return hide()' href='[$~HIDE1~$]' class=ch><img width=12 height=11 style='vertical-align:top;' src=/hide.gif valign=top border=0></a>
+
+</td>
+</tr></table>
+
+<font size=-1><span style="visibility:hidden" id='test'>t</span></font>
+
+[SCRIPT]
+</body></html>
diff --git a/chromium/tools/grit/grit/testdata/sidebar_v.html b/chromium/tools/grit/grit/testdata/sidebar_v.html
new file mode 100644
index 00000000000..e040d8ec59c
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/sidebar_v.html
@@ -0,0 +1,267 @@
+<html><head>
+<title>Google Desktop Search Sidebar</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+<style>
+BODY,TD,P,A {FONT-FAMILY: verdana,arial,sans-serif;font-size:8pt; color:#fff}
+a:link, a:visited, a:hover, b, q b { color: #ffffff}
+a:active { color: #ff0000}
+a:link,a:active,a:visited,div { text-decoration: none;font-size:8pt }
+.g{margin-top: 1em;}
+.gg{margin-top: .4em;}
+.norepeat { background-repeat: no-repeat }
+.indent{margin-top: 0px; margin-bottom: 0px;margin-left:3px;}
+.c:link, .c:visited, .c:active { color: #959595;font-size:8pt }
+.ch{cursor:pointer;cursor:hand}
+.gap{margin-top: 10px; margin-bottom: 10px;}
+.off {display:none}
+.on {display:on}
+.but { border-top: 1px solid #73787E;border-bottom: 1px solid #000000;border-right: 1px solid #000000;border-left: 1px solid #73787E;margin-top: 0px; margin-bottom: 0px; cursor:pointer;cursor:hand}
+</style>
+<script>
+
+function toggle(i) {
+ var v = document.getElementById(i);
+ var vi = document.getElementById(i+'icon');
+ var c = (v['className'] == 'on');
+ if (c) {
+ v['className'] = 'off';
+ vi.src='up.gif';
+ }
+ else {
+ v['className'] = 'on';
+ vi.src='down.gif';
+ }
+ (new Image()).src="[$~TOGGLE~$]?setting="+i+"&mode="+v['className']+"&rnd="+Math.random();
+
+ if (!c && (v['oclass'] == 'off')) {
+ location.href = location.href;
+ }
+
+ return true;
+}
+function hide() {
+ // return confirm("Are you sure you want to hide the sidebar?\nYou can show it again in Google Desktop Search Preferences.");
+ return 1;
+}
+</script>
+
+<!-- menu experiment start -->
+
+<style>
+<!--
+.menu1 {
+cursor:default;
+position:absolute;
+text-align: left;
+font-family: Arial, Helvetica, sans-serif;
+font-size: 8pt;
+font-color: #000000;
+color: #000000;
+background-color: menu;
+visibility: hidden;
+padding-top: 2px;
+padding-bottom: 2px;
+border: 1 solid;
+border-color: #888888;
+z-index: 100;
+}
+.menuitems {
+padding-left: 5px;
+padding-right: 5px;
+}
+-->
+</style>
+<SCRIPT LANGUAGE="JavaScript1.2">
+<!--
+var menustyle = "menu1";
+
+function showmenu() {
+ var rightedge = document.body.clientWidth-event.clientX;
+ var bottomedge = document.body.clientHeight-event.clientY;
+ // if (rightedge < rcmenu.offsetWidth)
+ // rcmenu.style.left = document.body.scrollLeft + event.clientX - rcmenu.offsetWidth;
+ // else
+ // rcmenu.style.left = document.body.scrollLeft + event.clientX;
+
+ // if (rcmenu.style.left < 0) rcmenu.style.left = 0;
+ rcmenu.style.left = 0;
+
+ if (bottomedge < rcmenu.offsetHeight)
+ rcmenu.style.top = document.body.scrollTop + event.clientY - rcmenu.offsetHeight;
+ else
+ rcmenu.style.top = document.body.scrollTop + event.clientY;
+
+ if (rcmenu.style.top < 0) rcmenu.style.top = 0;
+
+ rcmenu.style.visibility = "visible";
+ // rcmenu.style.zindex = 0;
+ // document.all('rcmenu').style.zindex = 20;
+ document.onkeydown=ck;
+ return false;
+}
+
+function hidemenu() {
+ rcmenu.style.visibility = "hidden";
+}
+
+function ck(e){
+ evt=document.all?window.event:e;
+ k=document.all?window.event.keyCode:e.keyCode;
+
+ if(k==27 /*<Esc>*/) {
+ hidemenu();
+ }
+}
+
+function menumouseover() {
+ if (event.srcElement.className == "menuitems") {
+ event.srcElement.style.backgroundColor = "highlight";
+ event.srcElement.style.color = "white";
+ }
+}
+
+function menumouseout() {
+ if (event.srcElement.className == "menuitems") {
+ event.srcElement.style.backgroundColor = "";
+ event.srcElement.style.color = "black";
+ window.status = "";
+ }
+}
+
+function menuselect() {
+ if (event.srcElement.className == "menuitems") {
+ if (event.srcElement.getAttribute("target") != null)
+ window.open(event.srcElement.url, event.srcElement.getAttribute("target"));
+ else if (event.srcElement.url.length)
+ window.location = event.srcElement.url;
+ }
+}
+// -->
+</script>
+
+<!-- menu experiment end -->
+
+</head>
+
+<body onload="TEST_WIDTH();" bottommargin=0 leftmargin=0 marginheight=0 marginwidth=0 rightmargin=0 topmargin=0 style="background-color:'#384146'; background-repeat: repeat-y; border-style:solid; border-width:0;" background="greyback.jpg" scroll=NO oncontextmenu="return false;">
+
+<!-- menu experiment start -->
+
+<div id="rcmenu" class="skin0" onMouseover="menumouseover()" onMouseout="menumouseout()" onClick="menuselect();">
+<div class="menuitems" url="[$~SETDISP4~$]">Switch to minibar</div>
+<div class="menuitems" url="[$~SETDISP2~$]">Switch to hoverbar</div>
+<div class="menuitems" url="[$~HIDE1~$]">Close sidebar</div>
+<div class="menuitems" url="">No change</div>
+</div>
+
+<script language="JavaScript1.2">
+if (document.all && window.print) {
+ rcmenu.className = menustyle;
+ document.oncontextmenu = showmenu;
+ document.body.onclick = hidemenu;
+}
+</script>
+
+<!-- menu experiment end -->
+
+<div id="oneliner" style="visibility:hidden; position:absolute; left:0px; top:0px;"></div>
+<script>
+var h = document.getElementById("oneliner").offsetHeight*2;
+document.write("<style type='text/css'>.truncme { overflow:hidden;height: " +h+"px; }</style>");
+</script>
+
+<table cellpadding=0 cellspacing=0 border=0 width='100%'>
+<form method=get action="[$~SEARCHURL~$]" id=f1>
+<input type=hidden name=src value=5>
+<input type=hidden name=redir value=''>
+<tr>
+ <td width='1%'><IMG id=ctl src="[CONTROL_IMAGE]" border=0 usemap="#control"></td>
+ <td width='97%'><input TABINDEX="1" NAME="q" style="width:'100%'; FONT-FAMILY: verdana,arial,sans-serif;font-size:8pt"></td>
+ <td width='1%'><table cellpadding=2 cellspacing=0><tr><td> </td><td TABINDEX="8" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=but bgcolor=414A4F valign=top onclick="location.href='[$~SETDISP2~$]';"><img src="mini_mini.gif"></td></tr></table></td>
+ <td width='1%'><table cellpadding=2 cellspacing=0><tr><td TABINDEX="9" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=but bgcolor=414A4F valign=top onclick="if (hide())location.href='[$~HIDE1~$]';"><img src="mini_close.gif"></td></tr></table></td>
+</tr>
+<MAP name="control">
+<area TABINDEX="4" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=1"' title="Move sidebar to Top" shape="rect" coords="9,0,22,8" href="/movesidebar?side=1" onmouseover="ctl.src='control1.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
+<area TABINDEX="5" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=3"' title="Move sidebar to Bottom" shape="rect" coords="9,9,22,17" href="/movesidebar?side=3" onmouseover="ctl.src='control3.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
+<area TABINDEX="6" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=0"' title="Move sidebar to Left" shape="rect" coords="0,2,8,15" href="/movesidebar?side=0" onmouseover="ctl.src='control0.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
+<area TABINDEX="7" onkeydown='if(event.keyCode==13)location.href="movesidebar?side=2"' title="Move sidebar to Right" shape="rect" coords="23,2,31,15" href="/movesidebar?side=2" onmouseover="ctl.src='control2.gif'" onmouseout="ctl.src='[CONTROL_IMAGE]'">
+</MAP>
+</table>
+
+<center>
+<table cellpadding=2 cellspacing=3>
+<tr>
+ <td TABINDEX="2" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="f1.submit()" onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=ch nowrap bgcolor=414A4F valign=top style="border-top: 1px solid #73787E;border-bottom: 1px solid #252C30;border-right: 1px solid #252C30;border-left: 1px solid #73787E;"><img src="logo.gif" align="texttop"> <font color=ffffff>Google Desktop Search&nbsp;</td>
+ <td TABINDEX="3" onkeydown='if(event.keyCode!=16&&event.keyCode!=9)onclick()' onclick="redir.value='google'; f1.submit(); redir.value='';" onmouseover="this.bgColor='4C535B'" onmouseout="this.bgColor='#414A4F'" class=ch bgcolor=414A4F nowrap valign=top style="border-top: 1px solid #73787E;border-bottom: 1px solid #252C30;border-right: 1px solid #252C30;border-left: 1px solid #73787E;">&nbsp;<font color=ffffff>Web&nbsp;</td>
+</tr>
+</form>
+</table>
+</center>
+
+<p class=gg>
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("news");' onclick='return toggle("news");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=newsicon src="[$~NEWS_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>News</td></tr></table>
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
+
+<span id="news" class=[$~NEWS_CLASS~$] oclass=[$~NEWS_CLASS~$]>
+[CONTENT_NEWS]
+<p class=g>
+</span>
+
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("inbox");' onclick='return toggle("inbox");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=inboxicon src="[$~INBOX_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Email</td></tr></table>
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
+
+<span id=inbox class=[$~INBOX_CLASS~$] oclass=[$~INBOX_CLASS~$]>
+[CONTENT_INBOX]
+<p class=g>
+</span>
+
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("hist");' onclick='return toggle("hist");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=histicon src="[$~HIST_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Related History</td></tr></table>
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
+
+<span id="hist" class=[$~HIST_CLASS~$] oclass=[$~HIST_CLASS~$]>
+[CONTENT_HIST]
+<p class=g>
+</span>
+
+
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("recent");' onclick='return toggle("recent");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=recenticon src="[$~RECENT_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Recent</td></tr></table>
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
+
+<span id="recent" class=[$~RECENT_CLASS~$] oclass=[$~RECENT_CLASS~$]>
+[CONTENT_RECENT]
+<p class=g>
+</span>
+
+
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("popular");' onclick='return toggle("popular");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=popularicon src="[$~POPULAR_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Frequently Visited</td></tr></table>
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
+
+<span id="popular" class=[$~POPULAR_CLASS~$] oclass=[$~POPULAR_CLASS~$]>
+[CONTENT_POPULAR]
+<p class=g>
+</span>
+
+
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=4E555C><img width=1 height=1></td></tr></table>
+<table class=ch cellpadding=0 cellspacing=0 style="background-color:'#424B50'; background-repeat: repeat-y;" background="section.jpg" width=100% height=18><tr onDblClick='return toggle("quib_debug");' onclick='return toggle("quib_debug");' onmouseover="this.bgColor='#465055'" onmouseout="this.bgColor=''"><td width=16 align=right><img id=quib_debugicon src="[$~QUIB_DEBUG_MODE~$]" border=0></td><td valign=middle>&nbsp;<font color=ffffff>Implicit Query Debug</td></tr></table>
+<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=313B40><img width=1 height=1></td></tr></table>
+
+<span id="quib_debug" class=[$~QUIB_DEBUG_CLASS~$] oclass=[$~QUIB_DEBUG_CLASS~$]>
+[CONTENT_QUIB_DEBUG]
+</span>
+
+<span style="visibility:hidden" id='test'>t</span>
+
+[CONTENT_OTHER]
+
+[SCRIPT]
+</body>
+</html>
diff --git a/chromium/tools/grit/grit/testdata/simple-input.xml b/chromium/tools/grit/grit/testdata/simple-input.xml
new file mode 100644
index 00000000000..92827fa4b56
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/simple-input.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit base_dir="." latest_public_release="2" current_release="3" source_lang_id="en-US">
+ <release seq="2">
+ <messages>
+ <message name="IDS_OLD_MESSAGE" translateable="true">Hello earthlings!</message>
+ </messages>
+ </release>
+ <release seq="3">
+ <includes>
+ <include name="ID_EDIT_BOX_ICON" type="icon" translateable="false" file="images/edit_box.ico" />
+ <include name="ID_LOGO" type="gif" translateable="true" file="images/logo.gif"/>
+ </includes>
+ <messages>
+ <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ </messages>
+ <structures>
+ <structure type="menu" name="IDM_FOO" file="rc_files/menus.rc" />
+ <structure type="dialog" name="IDD_BLAT" file="rc_files/dialogs.rc" />
+ <structure type="tr_html" name="IDR_HTML_TEMPLATE" file="templates/homepage.html" />
+ <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc">
+ <skeleton expr="lang == 'fr-FR'" variant_of_revision="3">
+ <![CDATA[IDD_DIALOG1 DIALOGEX 0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "TRANSLATEABLEPLACEHOLDER1"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "TRANSLATEABLEPLACEHOLDER2",IDOK,129,7,50,14
+ PUSHBUTTON "TRANSLATEABLEPLACEHOLDER3",IDCANCEL,129,24,50,14
+ LTEXT "TRANSLATEABLEPLACEHOLDER4",IDC_STATIC,23,31,40,8
+END]]>
+ </skeleton>
+ </structure>
+ <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc"/>
+ </structures>
+ </release>
+ <translations>
+ <file path="figs_nl_translations.xml" />
+ <file path="cjk_translations.xml" />
+ </translations>
+ <outputs>
+ <output filename="resource.h" type="rc_header" />
+ <output filename="resource_en.rc" type="rc_all" lang="en-US" />
+ <output filename="resource_fr.rc" type="rc_all" lang="fr-FR" />
+ <output filename="resource_it.rc" type="rc_translateable" lang="it-IT" />
+ <output filename="resource_zh_cn.rc" type="rc_translateable" lang="zh-CN" />
+ <output filename="nontranslateable.rc" type="rc_nontranslateable" />
+ </outputs>
+</grit>
diff --git a/chromium/tools/grit/grit/testdata/simple.html b/chromium/tools/grit/grit/testdata/simple.html
new file mode 100644
index 00000000000..4392d23e985
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/simple.html
@@ -0,0 +1,3 @@
+<p>
+ Hello!
+</p> \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/source.rc b/chromium/tools/grit/grit/testdata/source.rc
new file mode 100644
index 00000000000..fbc72284e95
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/source.rc
@@ -0,0 +1,57 @@
+IDC_KLONKMENU MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "E&xit", IDM_EXIT
+ MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
+ POPUP "gonk"
+ BEGIN
+ MENUITEM "Klonk && is [good]", ID_GONK_KLONKIS
+ END
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About ...", IDM_ABOUT
+ END
+END
+
+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
+ LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
+ SS_NOPREFIX
+ LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
+ DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON,46,51,84,10
+END
+
+IDD_DIFFERENT_LENGTH_IN_TRANSL DIALOGEX 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Bingobobbi"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ LTEXT "Howdie dodie!",IDC_STATIC,49,10,119,8,SS_NOPREFIX
+ LTEXT "Yo froodie!",IDC_STATIC,49,20,119,8
+END
+
+STRINGTABLE
+BEGIN
+ IDS_SIMPLE "One"
+ IDS_PLACEHOLDER "%s birds"
+ IDS_PLACEHOLDERS "%d of %d"
+ IDS_REORDERED_PLACEHOLDERS "$1 of $2"
+ // Won't be in translations list because it has changed
+ IDS_CHANGED "This was the old version"
+ IDS_TWIN_1 "Hello"
+ IDS_TWIN_2 "Hello"
+ IDS_NOT_TRANSLATEABLE ":"
+ IDS_LONGER_TRANSLATED "Removed document $1"
+ // Won't appear in the list of translations because it's not in the .grd file
+ IDS_NO_LONGER_USED "Not used"
+ IDS_DIFFERENT_TWIN_1 "Howdie"
+ IDS_DIFFERENT_TWIN_2 "Howdie"
+END
diff --git a/chromium/tools/grit/grit/testdata/status.html b/chromium/tools/grit/grit/testdata/status.html
new file mode 100644
index 00000000000..6b997b93695
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/status.html
@@ -0,0 +1,44 @@
+[HEADER]
+<table cellspacing=0 cellPadding=0 width="100%" border=0>
+<tr bgcolor=#3399cc><td align=middle height=1><img height=1 width=1></td></tr>
+</table>
+<table cellspacing=0 cellPadding=1 width="100%" bgcolor=#e8f4f7 border=0>
+<tr><td height=20><font size=+1 color=#000000>&nbsp;<b>Desktop Search Status</b></font></td></tr>
+</table>
+<br>
+<center>
+[$~MESSAGE~$]
+<table cellspacing=0 cellPadding=6 width=500 border=0>
+<tr>
+ <td>&nbsp;</td>
+ <td align=right nowrap><i><font size=-1>Number of items</font></i></td>
+ <td align=right nowrap><i><font size=-1>Time of newest item</font></i></td>
+</tr>
+<tr>
+ <td width=1% nowrap><img style="vertical-align:middle" width=16 height=16 src=favicon.ico>&nbsp; Total searchable items</td>
+ <td align=right><b>[TOTAL_COUNT]</b></td>
+ <td align=right><b>[TOTAL_TIME]</b></td>
+</tr>
+<tr>
+ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=email.gif width=16 height=16>&nbsp; Emails</font></td>
+ <td align=right><font size=-1>[EMAIL_COUNT]</font></td>
+ <td align=right><font size=-1>[EMAIL_TIME]</font></td>
+</tr>
+<tr>
+ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src="16x16_chat.gif" width=16 height=16>&nbsp; Chats</font></td>
+ <td align=right><font size=-1>[IM_COUNT]</font></td>
+ <td align=right><font size=-1>[IM_TIME]</font></td>
+</tr>
+<tr>
+ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=html.gif width=16 height=16>&nbsp; Web history</font></td>
+ <td align=right><font size=-1>[WEB_COUNT]</font></td>
+ <td align=right><font size=-1>[WEB_TIME]</font></td>
+</tr>
+<tr>
+ <td><font size=-1>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img style="vertical-align:middle" src=file.gif width=16 height=16>&nbsp; Files</font></td>
+ <td align=right><font size=-1>[FILE_COUNT]</font></td>
+ <td align=right><font size=-1>[FILE_TIME]</font></td>
+</tr>
+</table>
+</center>
+[FOOTER] \ No newline at end of file
diff --git a/chromium/tools/grit/grit/testdata/structure_variables.html b/chromium/tools/grit/grit/testdata/structure_variables.html
new file mode 100644
index 00000000000..2a15de80721
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/structure_variables.html
@@ -0,0 +1,4 @@
+<h1>[GREETING]!</h1>
+Some cool things are [THINGS].
+Did you know that [EQUATION]?
+<include src="[filename].html">
diff --git a/chromium/tools/grit/grit/testdata/substitute.grd b/chromium/tools/grit/grit/testdata/substitute.grd
new file mode 100644
index 00000000000..95dcc56e1d4
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/substitute.grd
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
+<grit
+ base_dir="."
+ source_lang_id="en"
+ tc_project="GoogleDesktopWindowsClient"
+ latest_public_release="0"
+ current_release="1"
+ enc_check="möl">
+ <outputs>
+ <output filename="resource.h" type="rc_header" />
+ <output filename="en_generated_resources.rc" type="rc_all" lang="en" />
+ <output filename="sv_generated_resources.rc" type="rc_all" lang="sv" />
+ </outputs>
+ <translations>
+ <file path="substitute.xmb" lang="sv" />
+ </translations>
+ <release seq="1" allow_pseudo="false">
+ <messages first_id="8192">
+ <message name="IDS_COPYRIGHT_GOOGLE_LONG" sub_variable="true" desc="Gadget copyright notice. Needs to be updated every year.">
+ Copyright 2008 Google Inc. All Rights Reserved.
+ </message>
+ <message name="IDS_NEWS_PANEL_COPYRIGHT">
+ Google Desktop News gadget
+[IDS_COPYRIGHT_GOOGLE_LONG]
+View news that is personalized based on the articles you read.
+
+For example, if you read lots of sports news, you'll see more sports articles. If you read technology news less often, you'll see fewer of those articles.
+ </message>
+ </messages>
+ </release>
+</grit>
diff --git a/chromium/tools/grit/grit/testdata/substitute.xmb b/chromium/tools/grit/grit/testdata/substitute.xmb
new file mode 100644
index 00000000000..e592069c8bf
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/substitute.xmb
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE translationbundle SYSTEM "/home/build/nonconf/google3/i18n/translationbundle.dtd">
+<translationbundle lang="sv">
+<translation id="7239109800378180620">© 2008 Google Inc. Med ensamrätt.</translation>
+<translation id="6212022020330010625">Google Desktop News gadget
+<ph name="IDS_COPYRIGHT_GOOGLE_LONG_1"/>
+Se nyheter som är anpassade till dig, baserat på de artiklar du läser.
+
+Om du t.ex. läser massor av sportnyheter kommer du att se fler sportartiklar. Om du inte läser tekniknyheter lika ofta ser du färre av dessa artiklar.</translation>
+</translationbundle>
diff --git a/chromium/tools/grit/grit/testdata/time_related.html b/chromium/tools/grit/grit/testdata/time_related.html
new file mode 100644
index 00000000000..ee64b1665e2
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/time_related.html
@@ -0,0 +1,11 @@
+[HEADER]
+[CHROME]
+[NAV_PRE_POST]
+[$~MESSAGE~$]<br>
+<table border=0 cellpadding=2 cellspacing=0 width='100%'>
+[CONTENTS]
+</table><br>
+
+[NAV_PRE_POST]
+[FOOTER]
+
diff --git a/chromium/tools/grit/grit/testdata/toolbar_about.html b/chromium/tools/grit/grit/testdata/toolbar_about.html
new file mode 100644
index 00000000000..bb4b0eb3552
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/toolbar_about.html
@@ -0,0 +1,138 @@
+<html id=dlgAbout STYLE="width: 25.8em; height: 17em" [GRITDIR]>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>About Google Toolbar</title>
+<style>
+.button {
+ width: 7em;
+ height: 2.2em;
+ color: buttontext;
+ font-family: MS Sans Serif;
+ font-size:8pt;
+ cursor: hand;
+}
+</style>
+
+<script> <!--
+ function HandleError(message, url, line) {
+ var L_Dialog_ErrorMessage = "An error has occured in this dialog.";
+ var L_ErrorNumber_Text = "Error: ";
+ var str = L_Dialog_ErrorMessage + "\n\n"
+ + L_ErrorNumber_Text + line + "\n"
+ + message;
+ alert (str);
+ window.close();
+ return true;
+ }
+
+ function OnKeyPress(nCode) {
+ if (nCode == 27) {
+ window.close();
+ return;
+ }
+ }
+
+ function OnLoad() {
+ if ((null != window.dialogArguments) && (window.dialogArguments.indexOf("&") == -1) && (window.dialogArguments.indexOf("<") == -1)) {
+ version.innerHTML = window.dialogArguments;
+ } else {
+ version.innerText = "Version: Unknown";
+ }
+ }
+
+ window.onerror = HandleError;
+ // -->
+</script>
+
+</head>
+
+
+<body bgcolor="#FFFFFF" onload="OnLoad()" onkeydown="OnKeyPress(event.keyCode)" onkeypress="OnKeyPress(event.keyCode)" scroll=no>
+
+<table border=0>
+
+ <tr height=5>
+ <td width=5></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td width=5></td>
+ </tr>
+
+ <tr>
+ <td></td>
+ <td colspan=3>
+
+
+<table border="0" cellpadding="0" cellspacing="0" valign="top">
+ <tr>
+ <td valign="top" height="47" width="155">
+ <div align="center"><img src="title_toolbar.gif" width="275" height="59" alt="Google Toolbar"></div>
+ </td>
+ <td valign="middle" height="47" width="713">
+ <hr size=1 color=25479D></td></tr>
+</table>
+
+
+ </td>
+ <!--
+ <TD colspan=2>
+ <span style="COLOR: black; FONT: 18pt Tahoma, MS Shell Dlg"><b>
+ Google Toolbar&trade;</b>
+ </span>
+ </TD>
+ -->
+ <td valign="middle">
+ </td>
+ </tr>
+
+ <tr>
+ <td></td>
+ <td align=center><img src="googly.gif"></td>
+ <td colspan=2 align=left>
+ <span style="WIDTH: 25em; height:6em COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg">
+ <span id=version></span><br>
+ </span>
+ </td>
+ <td></td>
+ </tr>
+
+ <tr height=50>
+ <td></td>
+ <td></td>
+ <td colspan=2 align=left>
+ <span style="WIDTH: 25em; height:6em COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg">
+ <!--$/translate-->
+ <i>De parvis grandis acervus erit</i>
+ <!--$translate-->
+ </span>
+ </td>
+ <td></td>
+ </tr>
+
+ <tr height=40>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+
+ <tr>
+ <td></td>
+ <td width=80></td>
+ <td>
+ <!--$/translate-->
+ <span style="WIDTH: 20em; COLOR: black; FONT: 8pt Tahoma, MS Shell Dlg" id="copyright">&copy; 2006 Google</span>
+ <!--$translate-->
+ </td>
+ <td id=ok-button align=right><button tabindex=1 type=submit align=right id="okButton" class=button onClick="window.close();" >OK</button>
+ </td>
+ <td></td>
+ </tr>
+
+</table>
+</span>
+
+</body>
+</html>
diff --git a/chromium/tools/grit/grit/testdata/tools/grit/resource_ids b/chromium/tools/grit/grit/testdata/tools/grit/resource_ids
new file mode 100644
index 00000000000..d8f71ff42f4
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/tools/grit/resource_ids
@@ -0,0 +1,175 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This file is used to assign starting resource ids for resources and strings
+# used by Chromium. This is done to ensure that resource ids are unique
+# across all the grd files. If you are adding a new grd file, please add
+# a new entry to this file.
+#
+# The first entry in the file, SRCDIR, is special: It is a relative path from
+# this file to the base of your checkout.
+#
+# http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx says that the
+# range for IDR_ is 1 to 28,671 and the range for IDS_ is 1 to 32,767 and
+# common convention starts practical use of IDs at 100 or 101.
+{
+ "SRCDIR": "../..",
+
+ "chrome/browser/browser_resources.grd": {
+ "includes": [500],
+ },
+ "chrome/browser/resources/component_extension_resources.grd": {
+ "includes": [1000],
+ },
+ "chrome/browser/resources/net_internals_resources.grd": {
+ "includes": [1500],
+ },
+ "chrome/browser/resources/shared_resources.grd": {
+ "includes": [2000],
+ },
+ "chrome/common/common_resources.grd": {
+ "includes": [2500],
+ },
+ "chrome/default_plugin/default_plugin_resources.grd": {
+ "includes": [3000],
+ },
+ "chrome/renderer/renderer_resources.grd": {
+ "includes": [3500],
+ },
+ "net/base/net_resources.grd": {
+ "includes": [4000],
+ },
+ "webkit/glue/webkit_resources.grd": {
+ "includes": [4500],
+ },
+ "webkit/tools/test_shell/test_shell_resources.grd": {
+ "includes": [5000],
+ },
+ "ui/resources/ui_resources.grd": {
+ "includes": [5500],
+ },
+ "chrome/app/theme/theme_resources.grd": {
+ "includes": [6000],
+ },
+ "chrome_frame/resources/chrome_frame_resources.grd": {
+ "includes": [6500],
+ },
+ # WebKit.grd can be in two different places depending on whether we are
+ # in a chromium checkout or a webkit-only checkout.
+ "third_party/WebKit/Source/WebKit/chromium/WebKit.grd": {
+ "includes": [7000],
+ },
+ "WebKit.grd": {
+ "includes": [7000],
+ },
+
+ "ui/base/strings/app_locale_settings.grd": {
+ "messages": [7500],
+ },
+ "chrome/app/resources/locale_settings.grd": {
+ "includes": [8000],
+ "messages": [8500],
+ },
+ # These each start with the same resource id because we only use one
+ # file for each build (cros, linux, mac, or win).
+ "chrome/app/resources/locale_settings_cros.grd": {
+ "messages": [9000],
+ },
+ "chrome/app/resources/locale_settings_linux.grd": {
+ "messages": [9000],
+ },
+ "chrome/app/resources/locale_settings_mac.grd": {
+ "messages": [9000],
+ },
+ "chrome/app/resources/locale_settings_win.grd": {
+ "messages": [9000],
+ },
+
+ "ui/base/strings/ui_strings.grd": {
+ "messages": [9500],
+ },
+ # Chromium strings and Google Chrome strings must start at the same id.
+ # We only use one file depending on whether we're building Chromium or
+ # Google Chrome.
+ "chrome/app/chromium_strings.grd": {
+ "messages": [10000],
+ },
+ "chrome/app/google_chrome_strings.grd": {
+ "messages": [10000],
+ },
+ # Leave lots of space for generated_resources since it has most of our
+ # strings.
+ "chrome/app/generated_resources.grd": {
+ "structures": [10500],
+ "messages": [11000],
+ },
+ # The chrome frame dialogs are also in generated_resources.grd so they
+ # get included by the translation console. We make sure that the ids
+ # for structures here are the same as for generated_resources.grd.
+ "chrome_frame/resources/chrome_frame_dialogs.grd": {
+ "structures": [10500],
+ "includes": [10750],
+ },
+ "webkit/glue/inspector_strings.grd": {
+ "messages": [16000],
+ },
+ "webkit/glue/webkit_strings.grd": {
+ "messages": [16500],
+ },
+
+ "chrome_frame/resources/chrome_frame_resources.grd": {
+ "includes": [17500],
+ "structures": [18000],
+ },
+
+ "ui/gfx/gfx_resources.grd": {
+ "includes": [18500],
+ },
+
+ "chrome/app/policy/policy_templates.grd": {
+ "structures": [19000],
+ "messages": [19010],
+ },
+
+ "chrome/browser/autofill/autofill_resources.grd": {
+ "messages": [19500],
+ },
+ "chrome/browser/resources/sync_internals_resources.grd": {
+ "includes": [20000],
+ },
+ # This file is generated during the build.
+ "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd": {
+ "includes": [20500],
+ },
+ # All standard and large theme resources should have the same IDs.
+ "chrome/app/theme/theme_resources_standard.grd": {
+ "includes": [21000],
+ },
+ "chrome/app/theme/theme_resources_large.grd": {
+ "includes": [21000],
+ },
+ # This file is generated during the build.
+ "chrome/browser/debugger/frontend/devtools_frontend_resources.grd": {
+ "includes": [21500],
+ },
+ "chrome/browser/resources/options_resources.grd": {
+ "includes": [22000],
+ },
+ "cloud_print/virtual_driver/win/install/virtual_driver_setup_resources.grd": {
+ "messages": [22500],
+ },
+ "chrome/browser/resources/quota_internals_resources.grd": {
+ "includes": [23000],
+ },
+ "chrome/browser/resources/workers_resources.grd": {
+ "includes": [23500],
+ },
+ # All standard and large theme resources should have the same IDs.
+ "ui/resources/ui_resources_standard.grd": {
+ "includes": [24000],
+ },
+ "ui/resources/ui_resources_large.grd": {
+ "includes": [24000],
+ },
+}
diff --git a/chromium/tools/grit/grit/testdata/transl.rc b/chromium/tools/grit/grit/testdata/transl.rc
new file mode 100644
index 00000000000..2f2595db3f2
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/transl.rc
@@ -0,0 +1,56 @@
+IDC_KLONKMENU MENU
+BEGIN
+ POPUP "&Skra"
+ BEGIN
+ MENUITEM "&Haetta", IDM_EXIT
+ MENUITEM "Thetta er ""Klonk"" sem eg fyla", ID_FILE_THISBE
+ POPUP "gonkurinn"
+ BEGIN
+ MENUITEM "Klonk && er [good]", ID_GONK_KLONKIS
+ END
+ END
+ POPUP "&Hjalp"
+ BEGIN
+ MENUITEM "&Um...", IDM_ABOUT
+ END
+END
+
+IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Um Klonk"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ ICON IDI_KLONK,IDC_MYICON,14,9,20,20
+ LTEXT "klonk utgafa ""jibbi"" 1.0",IDC_STATIC,49,10,119,8,
+ SS_NOPREFIX
+ LTEXT "Hofundarrettur (C) 2005",IDC_STATIC,49,20,119,8
+ DEFPUSHBUTTON "I lagi",IDOK,195,6,30,11,WS_GROUP
+ CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON,46,51,84,10
+END
+
+IDD_DIFFERENT_LENGTH_IN_TRANSL DIALOGEX 22, 17, 230, 75
+STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Bingobobbi"
+FONT 8, "System", 0, 0, 0x0
+BEGIN
+ LTEXT "Howdie dodie!",IDC_STATIC,49,10,119,8,SS_NOPREFIX
+END
+
+STRINGTABLE
+BEGIN
+ IDS_SIMPLE "Ein"
+ IDS_PLACEHOLDER "%s Vogeln"
+ IDS_PLACEHOLDERS "%d von %d"
+ // Shouldn't be part of translations list because the translation is
+ // reordered so placeholder fixup fails
+ IDS_REORDERED_PLACEHOLDERS "$2 auf $1"
+ IDS_CHANGED "Dass war die alte Version"
+ IDS_TWIN_1 "Hallo"
+ IDS_TWIN_2 "Hallo"
+ IDS_NOT_TRANSLATEABLE ":"
+ IDS_LONGER_TRANSLATED "Dokument $1 ist entfernt worden"
+ IDS_NO_LONGER_USED "Nicht verwendet"
+ IDS_DIFFERENT_TWIN_1 "Howdie"
+ IDS_DIFFERENT_TWIN_2 "Hallo sagt man"
+END
diff --git a/chromium/tools/grit/grit/testdata/versions.html b/chromium/tools/grit/grit/testdata/versions.html
new file mode 100644
index 00000000000..d1f40d8d727
--- /dev/null
+++ b/chromium/tools/grit/grit/testdata/versions.html
@@ -0,0 +1,7 @@
+[HEADER]
+
+[TOP_CHROME]
+[CONTENTS]
+
+[NEXT_PREV]
+[FOOTER]
diff --git a/chromium/tools/grit/grit/tool/__init__.py b/chromium/tools/grit/grit/tool/__init__.py
new file mode 100644
index 00000000000..c8565d52a59
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/__init__.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Package grit.tool
+'''
+
+pass
+
diff --git a/chromium/tools/grit/grit/tool/android2grd.py b/chromium/tools/grit/grit/tool/android2grd.py
new file mode 100644
index 00000000000..333e33d77ee
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/android2grd.py
@@ -0,0 +1,499 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The 'grit android2grd' tool."""
+
+
+import getopt
+import os.path
+import StringIO
+from xml.dom import Node
+import xml.dom.minidom
+
+import grit.node.empty
+from grit.node import io
+from grit.node import message
+
+from grit.tool import interface
+
+from grit import grd_reader
+from grit import lazy_re
+from grit import tclib
+from grit import util
+
+
+# The name of a string in strings.xml
+_STRING_NAME = lazy_re.compile(r'[a-z0-9_]+\Z')
+
+# A string's character limit in strings.xml
+_CHAR_LIMIT = lazy_re.compile(r'\[CHAR-LIMIT=(\d+)\]')
+
+# Finds String.Format() style format specifiers such as "%-5.2f".
+_FORMAT_SPECIFIER = lazy_re.compile(
+ '%'
+ '([1-9][0-9]*\$|<)?' # argument_index
+ '([-#+ 0,(]*)' # flags
+ '([0-9]+)?' # width
+ '(\.[0-9]+)?' # precision
+ '([bBhHsScCdoxXeEfgGaAtT%n])') # conversion
+
+
+class Android2Grd(interface.Tool):
+ """Tool for converting Android string.xml files into chrome Grd files.
+
+Usage: grit [global options] android2grd [OPTIONS] STRINGS_XML
+
+The Android2Grd tool will convert an Android strings.xml file (whose path is
+specified by STRINGS_XML) and create a chrome style grd file containing the
+relevant information.
+
+Because grd documents are much richer than strings.xml documents we supplement
+the information required by grds using OPTIONS with sensible defaults.
+
+OPTIONS may be any of the following:
+
+ --name FILENAME Specify the base FILENAME. This should be without
+ any file type suffix. By default
+ "chrome_android_strings" will be used.
+
+ --languages LANGUAGES Comma separated list of ISO language codes (e.g.
+ en-US, en-GB, ru, zh-CN). These codes will be used
+ to determine the names of resource and translations
+ files that will be declared by the output grd file.
+
+ --grd-dir GRD_DIR Specify where the resultant grd file
+ (FILENAME.grd) should be output. By default this
+ will be the present working directory.
+
+ --header-dir HEADER_DIR Specify the location of the directory where grit
+ generated C++ headers (whose name will be
+ FILENAME.h) will be placed. Use an empty string to
+ disable rc generation. Default: empty.
+
+ --rc-dir RC_DIR Specify the directory where resource files will
+ be located relative to grit build's output
+ directory. Use an empty string to disable rc
+ generation. Default: empty.
+
+ --xml-dir XML_DIR Specify where to place localized strings.xml files
+ relative to grit build's output directory. For each
+ language xx a values-xx/strings.xml file will be
+ generated. Use an empty string to disable
+ strings.xml generation. Default: '.'.
+
+ --xtb-dir XTB_DIR Specify where the xtb files containing translations
+ will be located relative to the grd file. Default:
+ '.'.
+"""
+
+ _NAME_FLAG = 'name'
+ _LANGUAGES_FLAG = 'languages'
+ _GRD_DIR_FLAG = 'grd-dir'
+ _RC_DIR_FLAG = 'rc-dir'
+ _HEADER_DIR_FLAG = 'header-dir'
+ _XTB_DIR_FLAG = 'xtb-dir'
+ _XML_DIR_FLAG = 'xml-dir'
+
+ def __init__(self):
+ self.name = 'chrome_android_strings'
+ self.languages = []
+ self.grd_dir = '.'
+ self.rc_dir = None
+ self.xtb_dir = '.'
+ self.xml_res_dir = '.'
+ self.header_dir = None
+
+ def ShortDescription(self):
+ """Returns a short description of the Android2Grd tool.
+
+ Overridden from grit.interface.Tool
+
+ Returns:
+ A string containing a short description of the android2grd tool.
+ """
+ return 'Converts Android string.xml files into Chrome grd files.'
+
+ def ParseOptions(self, args):
+ """Set this objects and return all non-option arguments."""
+ flags = [
+ Android2Grd._NAME_FLAG,
+ Android2Grd._LANGUAGES_FLAG,
+ Android2Grd._GRD_DIR_FLAG,
+ Android2Grd._RC_DIR_FLAG,
+ Android2Grd._HEADER_DIR_FLAG,
+ Android2Grd._XTB_DIR_FLAG,
+ Android2Grd._XML_DIR_FLAG, ]
+ (opts, args) = getopt.getopt(args, None, ['%s=' % o for o in flags])
+
+ for key, val in opts:
+ # Get rid of the preceding hypens.
+ k = key[2:]
+ if k == Android2Grd._NAME_FLAG:
+ self.name = val
+ elif k == Android2Grd._LANGUAGES_FLAG:
+ self.languages = val.split(',')
+ elif k == Android2Grd._GRD_DIR_FLAG:
+ self.grd_dir = val
+ elif k == Android2Grd._RC_DIR_FLAG:
+ self.rc_dir = val
+ elif k == Android2Grd._HEADER_DIR_FLAG:
+ self.header_dir = val
+ elif k == Android2Grd._XTB_DIR_FLAG:
+ self.xtb_dir = val
+ elif k == Android2Grd._XML_DIR_FLAG:
+ self.xml_res_dir = val
+ return args
+
+ def Run(self, opts, args):
+ """Runs the Android2Grd tool.
+
+ Inherited from grit.interface.Tool.
+
+ Args:
+ opts: List of string arguments that should be parsed.
+ args: String containing the path of the strings.xml file to be converted.
+ """
+ args = self.ParseOptions(args)
+ if len(args) != 1:
+ print ('Tool requires one argument, the path to the Android '
+ 'strings.xml resource file to be converted.')
+ return 2
+ self.SetOptions(opts)
+
+ android_path = args[0]
+
+ # Read and parse the Android strings.xml file.
+ with open(android_path) as android_file:
+ android_dom = xml.dom.minidom.parse(android_file)
+
+ # Do the hard work -- convert the Android dom to grd file contents.
+ grd_dom = self.AndroidDomToGrdDom(android_dom)
+ grd_string = unicode(grd_dom)
+
+ # Write the grd string to a file in grd_dir.
+ grd_filename = self.name + '.grd'
+ grd_path = os.path.join(self.grd_dir, grd_filename)
+ with open(grd_path, 'w') as grd_file:
+ grd_file.write(grd_string)
+
+ def AndroidDomToGrdDom(self, android_dom):
+ """Converts a strings.xml DOM into a DOM representing the contents of
+ a grd file.
+
+ Args:
+ android_dom: A xml.dom.Document containing the contents of the Android
+ string.xml document.
+ Returns:
+ The DOM for the grd xml document produced by converting the Android DOM.
+ """
+
+ # Start with a basic skeleton for the .grd file.
+ root = grd_reader.Parse(StringIO.StringIO(
+ '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit base_dir="." latest_public_release="0"
+ current_release="1" source_lang_id="en">
+ <release allow_pseudo="false" seq="1">
+ <messages fallback_to_english="true" />
+ </release>
+ <translations />
+ <outputs />
+ </grit>'''), dir='.')
+ messages = root.children[0].children[0]
+ translations = root.children[1]
+ outputs = root.children[2]
+ assert (isinstance(messages, grit.node.empty.MessagesNode) and
+ isinstance(translations, grit.node.empty.TranslationsNode) and
+ isinstance(outputs, grit.node.empty.OutputsNode))
+
+ if self.header_dir:
+ cpp_header = self.__CreateCppHeaderOutputNode(outputs, self.header_dir)
+ for lang in self.languages:
+ # Create an output element for each language.
+ if self.rc_dir:
+ self.__CreateRcOutputNode(outputs, lang, self.rc_dir)
+ if self.xml_res_dir:
+ self.__CreateAndroidXmlOutputNode(outputs, lang, self.xml_res_dir)
+ if lang != 'en':
+ self.__CreateFileNode(translations, lang)
+ # Convert all the strings.xml strings into grd messages.
+ self.__CreateMessageNodes(messages, android_dom.documentElement)
+
+ return root
+
+ def __CreateMessageNodes(self, messages, resources):
+ """Creates the <message> elements and adds them as children of <messages>.
+
+ Args:
+ messages: the <messages> element in the strings.xml dom.
+ resources: the <resources> element in the grd dom.
+ """
+ # <string> elements contain the definition of the resource.
+ # The description of a <string> element is contained within the comment
+ # node element immediately preceeding the string element in question.
+ description = ''
+ for child in resources.childNodes:
+ if child.nodeType == Node.COMMENT_NODE:
+ # Remove leading/trailing whitespace; collapse consecutive whitespaces.
+ description = ' '.join(child.data.split())
+ elif child.nodeType == Node.ELEMENT_NODE:
+ if child.tagName != 'string':
+ print 'Warning: ignoring unknown tag <%s>' % child.tagName
+ else:
+ translatable = self.IsTranslatable(child)
+ raw_name = child.getAttribute('name')
+ product = child.getAttribute('product') or None
+ grd_name = self.__FormatName(raw_name, product)
+ # Transform the <string> node contents into a tclib.Message, taking
+ # care to handle whitespace transformations and escaped characters,
+ # and coverting <xliff:g> placeholders into <ph> placeholders.
+ msg = self.CreateTclibMessage(child)
+ msg_node = self.__CreateMessageNode(messages, grd_name, description,
+ msg, translatable)
+ messages.AddChild(msg_node)
+ # Reset the description once a message has been parsed.
+ description = ''
+
+ def __FormatName(self, name, product=None):
+ """Formats the message name.
+
+ Names in the strings.xml files should be lowercase with underscores. In grd
+ files message names should be mostly uppercase with a IDS prefix. We also
+ will annotate names with product information (lowercase) where appropriate.
+
+ Args:
+ name: The message name as found in the string.xml file.
+ product: An optional product annotation.
+
+ Returns:
+ String containing the grd style name that will be used in the translation
+ console.
+ """
+ if not _STRING_NAME.match(name):
+ print 'Error: string name contains illegal characters: %s' % name
+ grd_name = 'IDS_%s' % name.upper()
+ product_suffix = ('_product_%s' % product.lower()) if product else ''
+ return grd_name + product_suffix
+
+ def CreateTclibMessage(self, android_string):
+ """Transforms a <string/> element from strings.xml into a tclib.Message.
+
+ Interprets whitespace, quotes, and escaped characters in the android_string
+ according to Android's formatting and styling rules for strings. Also
+ converts <xliff:g> placeholders into <ph> placeholders, e.g.:
+
+ <xliff:g id="website" example="google.com">%s</xliff:g>
+ becomes
+ <ph name="website"><ex>google.com</ex>%s</ph>
+
+ Returns:
+ The tclib.Message.
+ """
+ msg = tclib.Message()
+ current_text = '' # Accumulated text that hasn't yet been added to msg.
+ nodes = android_string.childNodes
+
+ for i, node in enumerate(nodes):
+ # Handle text nodes.
+ if node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
+ current_text += node.data
+
+ # Handle <xliff:g> and other tags.
+ elif node.nodeType == Node.ELEMENT_NODE:
+ if node.tagName == 'xliff:g':
+ assert node.hasAttribute('id'), 'missing id: ' + node.data()
+ placeholder_id = node.getAttribute('id')
+ placeholder_text = self.__FormatPlaceholderText(node)
+ placeholder_example = node.getAttribute('example')
+ if not placeholder_example:
+ print ('Info: placeholder does not contain an example: %s' %
+ node.toxml())
+ placeholder_example = placeholder_id.upper()
+ msg.AppendPlaceholder(tclib.Placeholder(placeholder_id,
+ placeholder_text, placeholder_example))
+ else:
+ print ('Warning: removing tag <%s> which must be inside a '
+ 'placeholder: %s' % (node.tagName, node.toxml()))
+ msg.AppendText(self.__FormatPlaceholderText(node))
+
+ # Handle other nodes.
+ elif node.nodeType != Node.COMMENT_NODE:
+ assert False, 'Unknown node type: %s' % node.nodeType
+
+ is_last_node = (i == len(nodes) - 1)
+ if (current_text and
+ (is_last_node or nodes[i + 1].nodeType == Node.ELEMENT_NODE)):
+ # For messages containing just text and comments (no xml tags) Android
+ # strips leading and trailing whitespace. We mimic that behavior.
+ if not msg.GetContent() and is_last_node:
+ current_text = current_text.strip()
+ msg.AppendText(self.__FormatAndroidString(current_text))
+ current_text = ''
+
+ return msg
+
+ def __FormatAndroidString(self, android_string, inside_placeholder=False):
+ r"""Returns android_string formatted for a .grd file.
+
+ * Collapses consecutive whitespaces, except when inside double-quotes.
+ * Replaces \\, \n, \t, \", \' with \, newline, tab, ", '.
+ """
+ backslash_map = {'\\' : '\\', 'n' : '\n', 't' : '\t', '"' : '"', "'" : "'"}
+ is_quoted_section = False # True when we're inside double quotes.
+ is_backslash_sequence = False # True after seeing an unescaped backslash.
+ prev_char = ''
+ output = []
+ for c in android_string:
+ if is_backslash_sequence:
+ # Unescape \\, \n, \t, \", and \'.
+ assert c in backslash_map, 'Illegal escape sequence: \\%s' % c
+ output.append(backslash_map[c])
+ is_backslash_sequence = False
+ elif c == '\\':
+ is_backslash_sequence = True
+ elif c.isspace() and not is_quoted_section:
+ # Turn whitespace into ' ' and collapse consecutive whitespaces.
+ if not prev_char.isspace():
+ output.append(' ')
+ elif c == '"':
+ is_quoted_section = not is_quoted_section
+ else:
+ output.append(c)
+ prev_char = c
+ output = ''.join(output)
+
+ if is_quoted_section:
+ print 'Warning: unbalanced quotes in string: %s' % android_string
+
+ if is_backslash_sequence:
+ print 'Warning: trailing backslash in string: %s' % android_string
+
+ # Check for format specifiers outside of placeholder tags.
+ if not inside_placeholder:
+ format_specifier = _FORMAT_SPECIFIER.search(output)
+ if format_specifier:
+ print ('Warning: format specifiers are not inside a placeholder '
+ '<xliff:g/> tag: %s' % output)
+
+ return output
+
+ def __FormatPlaceholderText(self, placeholder_node):
+ """Returns the text inside of an <xliff:g> placeholder node."""
+ text = []
+ for childNode in placeholder_node.childNodes:
+ if childNode.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
+ text.append(childNode.data)
+ elif childNode.nodeType != Node.COMMENT_NODE:
+ assert False, 'Unknown node type in ' + placeholder_node.toxml()
+ return self.__FormatAndroidString(''.join(text), inside_placeholder=True)
+
+ def __CreateMessageNode(self, messages_node, grd_name, description, msg,
+ translatable):
+ """Creates and initializes a <message> element.
+
+ Message elements correspond to Android <string> elements in that they
+ declare a string resource along with a programmatic id.
+ """
+ if not description:
+ print 'Warning: no description for %s' % grd_name
+ # Check that we actually fit within the character limit we've specified.
+ match = _CHAR_LIMIT.search(description)
+ if match:
+ char_limit = int(match.group(1))
+ msg_content = msg.GetRealContent()
+ if len(msg_content) > char_limit:
+ print ('Warning: char-limit for %s is %d, but length is %d: %s' %
+ (grd_name, char_limit, len(msg_content), msg_content))
+ return message.MessageNode.Construct(parent=messages_node,
+ name=grd_name,
+ message=msg,
+ desc=description,
+ translateable=translatable)
+
+ def __CreateFileNode(self, translations_node, lang):
+ """Creates and initializes the <file> elements.
+
+ File elements provide information on the location of translation files
+ (xtbs)
+ """
+ xtb_file = os.path.normpath(os.path.join(
+ self.xtb_dir, '%s_%s.xtb' % (self.name, lang)))
+ fnode = io.FileNode()
+ fnode.StartParsing(u'file', translations_node)
+ fnode.HandleAttribute('path', xtb_file)
+ fnode.HandleAttribute('lang', lang)
+ fnode.EndParsing()
+ translations_node.AddChild(fnode)
+ return fnode
+
+ def __CreateCppHeaderOutputNode(self, outputs_node, header_dir):
+ """Creates the <output> element corresponding to the generated c header."""
+ header_file_name = os.path.join(header_dir, self.name + '.h')
+ header_node = io.OutputNode()
+ header_node.StartParsing(u'output', outputs_node)
+ header_node.HandleAttribute('filename', header_file_name)
+ header_node.HandleAttribute('type', 'rc_header')
+ emit_node = io.EmitNode()
+ emit_node.StartParsing(u'emit', header_node)
+ emit_node.HandleAttribute('emit_type', 'prepend')
+ emit_node.EndParsing()
+ header_node.AddChild(emit_node)
+ header_node.EndParsing()
+ outputs_node.AddChild(header_node)
+ return header_node
+
+ def __CreateRcOutputNode(self, outputs_node, lang, rc_dir):
+ """Creates the <output> element corresponding to various rc file output."""
+ rc_file_name = self.name + '_' + lang + ".rc"
+ rc_path = os.path.join(rc_dir, rc_file_name)
+ node = io.OutputNode()
+ node.StartParsing(u'output', outputs_node)
+ node.HandleAttribute('filename', rc_path)
+ node.HandleAttribute('lang', lang)
+ node.HandleAttribute('type', 'rc_all')
+ node.EndParsing()
+ outputs_node.AddChild(node)
+ return node
+
+ def __CreateAndroidXmlOutputNode(self, outputs_node, locale, xml_res_dir):
+ """Creates the <output> element corresponding to various rc file output."""
+ # Need to check to see if the locale has a region, e.g. the GB in en-GB.
+ # When a locale has a region Android expects the region to be prefixed
+ # with an 'r'. For example for en-GB Android expects a values-en-rGB
+ # directory. Also, Android expects nb, tl, in, iw, ji as the language
+ # codes for Norwegian, Tagalog/Filipino, Indonesian, Hebrew, and Yiddish:
+ # http://developer.android.com/reference/java/util/Locale.html
+ if locale == 'es-419':
+ android_locale = 'es-rUS'
+ else:
+ android_lang, dash, region = locale.partition('-')
+ lang_map = {'no': 'nb', 'fil': 'tl', 'id': 'in', 'he': 'iw', 'yi': 'ji'}
+ android_lang = lang_map.get(android_lang, android_lang)
+ android_locale = android_lang + ('-r' + region if region else '')
+ values = 'values-' + android_locale if android_locale != 'en' else 'values'
+ xml_path = os.path.normpath(os.path.join(
+ xml_res_dir, values, 'strings.xml'))
+
+ node = io.OutputNode()
+ node.StartParsing(u'output', outputs_node)
+ node.HandleAttribute('filename', xml_path)
+ node.HandleAttribute('lang', locale)
+ node.HandleAttribute('type', 'android')
+ node.EndParsing()
+ outputs_node.AddChild(node)
+ return node
+
+ def IsTranslatable(self, android_string):
+ """Determines if a <string> element is a candidate for translation.
+
+ A <string> element is by default translatable unless otherwise marked.
+ """
+ if android_string.hasAttribute('translatable'):
+ value = android_string.getAttribute('translatable').lower()
+ if value not in ('true', 'false'):
+ print 'Warning: translatable attribute has invalid value: %s' % value
+ return value == 'true'
+ else:
+ return True
+
diff --git a/chromium/tools/grit/grit/tool/android2grd_unittest.py b/chromium/tools/grit/grit/tool/android2grd_unittest.py
new file mode 100644
index 00000000000..b40bf60002f
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/android2grd_unittest.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.tool.android2grd'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import xml.dom.minidom
+
+from grit import grd_reader
+from grit import util
+from grit.node import empty
+from grit.node import io
+from grit.node import message
+from grit.node import misc
+from grit.tool import android2grd
+
+
+class Android2GrdUnittest(unittest.TestCase):
+
+ def __Parse(self, xml_string):
+ return xml.dom.minidom.parseString(xml_string).childNodes[0]
+
+ def testCreateTclibMessage(self):
+ tool = android2grd.Android2Grd()
+ msg = tool.CreateTclibMessage(self.__Parse(r'''
+ <string name="simple">A simple string</string>'''))
+ self.assertEqual(msg.GetRealContent(), 'A simple string')
+ msg = tool.CreateTclibMessage(self.__Parse(r'''
+ <string name="outer_whitespace">
+ Strip leading/trailing whitespace
+ </string>'''))
+ self.assertEqual(msg.GetRealContent(), 'Strip leading/trailing whitespace')
+ msg = tool.CreateTclibMessage(self.__Parse(r'''
+ <string name="inner_whitespace">Fold multiple spaces</string>'''))
+ self.assertEqual(msg.GetRealContent(), 'Fold multiple spaces')
+ msg = tool.CreateTclibMessage(self.__Parse(r'''
+ <string name="escaped_spaces">Retain \n escaped\t spaces</string>'''))
+ self.assertEqual(msg.GetRealContent(), 'Retain \n escaped\t spaces')
+ msg = tool.CreateTclibMessage(self.__Parse(r'''
+ <string name="quotes"> " Quotes preserve
+ whitespace" but only for "enclosed elements "
+ </string>'''))
+ self.assertEqual(msg.GetRealContent(), ''' Quotes preserve
+ whitespace but only for enclosed elements ''')
+ msg = tool.CreateTclibMessage(self.__Parse(
+ r'''<string name="escaped_characters">Escaped characters: \"\'\\\t\n'''
+ '</string>'))
+ self.assertEqual(msg.GetRealContent(), '''Escaped characters: "'\\\t\n''')
+ msg = tool.CreateTclibMessage(self.__Parse(
+ '<string xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" '
+ 'name="placeholders">'
+ 'Open <xliff:g id="FILENAME" example="internet.html">%s</xliff:g>?'
+ '</string>'))
+ self.assertEqual(msg.GetRealContent(), 'Open %s?')
+ self.assertEqual(len(msg.GetPlaceholders()), 1)
+ self.assertEqual(msg.GetPlaceholders()[0].presentation, 'FILENAME')
+ self.assertEqual(msg.GetPlaceholders()[0].original, '%s')
+ self.assertEqual(msg.GetPlaceholders()[0].example, 'internet.html')
+ msg = tool.CreateTclibMessage(self.__Parse(r'''
+ <string name="comment">Contains a <!-- ignore this --> comment
+ </string>'''))
+ self.assertEqual(msg.GetRealContent(), 'Contains a comment')
+
+ def testIsTranslatable(self):
+ tool = android2grd.Android2Grd()
+ string_el = self.__Parse('<string>Hi</string>')
+ self.assertTrue(tool.IsTranslatable(string_el))
+ string_el = self.__Parse(
+ '<string translatable="true">Hi</string>')
+ self.assertTrue(tool.IsTranslatable(string_el))
+ string_el = self.__Parse(
+ '<string translatable="false">Hi</string>')
+ self.assertFalse(tool.IsTranslatable(string_el))
+
+ def __ParseAndroidXml(self, options = []):
+ tool = android2grd.Android2Grd()
+
+ tool.ParseOptions(options)
+
+ android_path = util.PathFromRoot('grit/testdata/android.xml')
+ with open(android_path) as android_file:
+ android_dom = xml.dom.minidom.parse(android_file)
+
+ grd = tool.AndroidDomToGrdDom(android_dom)
+ self.assertTrue(isinstance(grd, misc.GritNode))
+
+ return grd
+
+ def testAndroidDomToGrdDom(self):
+ grd = self.__ParseAndroidXml(['--languages', 'en-US,en-GB,ru'])
+
+ # Check that the structure of the GritNode is as expected.
+ messages = grd.GetChildrenOfType(message.MessageNode)
+ translations = grd.GetChildrenOfType(empty.TranslationsNode)
+ files = grd.GetChildrenOfType(io.FileNode)
+
+ self.assertEqual(len(translations), 1)
+ self.assertEqual(len(files), 3)
+ self.assertEqual(len(messages), 5)
+
+ # Check that a message node is constructed correctly.
+ msg = filter(lambda x: x.GetTextualIds()[0] == "IDS_PLACEHOLDERS", messages)
+ self.assertTrue(msg)
+ msg = msg[0]
+
+ self.assertTrue(msg.IsTranslateable())
+ self.assertEqual(msg.attrs["desc"], "A string with placeholder.")
+
+ def testProductAttribute(self):
+ grd = self.__ParseAndroidXml([])
+ messages = grd.GetChildrenOfType(message.MessageNode)
+ msg = filter(lambda x: x.GetTextualIds()[0] ==
+ "IDS_SIMPLE_product_nosdcard",
+ messages)
+ self.assertTrue(msg)
+
+ def testTranslatableAttribute(self):
+ grd = self.__ParseAndroidXml([])
+ messages = grd.GetChildrenOfType(message.MessageNode)
+ msgs = filter(lambda x: x.GetTextualIds()[0] == "IDS_CONSTANT", messages)
+ self.assertTrue(msgs)
+ self.assertFalse(msgs[0].IsTranslateable())
+
+ def testTranslations(self):
+ grd = self.__ParseAndroidXml(['--languages', 'en-US,en-GB,ru,id'])
+
+ files = grd.GetChildrenOfType(io.FileNode)
+ us_file = filter(lambda x: x.attrs['lang'] == 'en-US', files)
+ self.assertTrue(us_file)
+ self.assertEqual(us_file[0].GetInputPath(),
+ 'chrome_android_strings_en-US.xtb')
+
+ id_file = filter(lambda x: x.attrs['lang'] == 'id', files)
+ self.assertTrue(id_file)
+ self.assertEqual(id_file[0].GetInputPath(),
+ 'chrome_android_strings_id.xtb')
+
+ def testOutputs(self):
+ grd = self.__ParseAndroidXml(['--languages', 'en-US,ru,id',
+ '--rc-dir', 'rc/dir',
+ '--header-dir', 'header/dir',
+ '--xtb-dir', 'xtb/dir',
+ '--xml-dir', 'xml/dir'])
+
+ outputs = grd.GetChildrenOfType(io.OutputNode)
+ self.assertEqual(len(outputs), 7)
+
+ header_outputs = filter(lambda x: x.GetType() == 'rc_header', outputs)
+ rc_outputs = filter(lambda x: x.GetType() == 'rc_all', outputs)
+ xml_outputs = filter(lambda x: x.GetType() == 'android', outputs)
+
+ self.assertEqual(len(header_outputs), 1)
+ self.assertEqual(len(rc_outputs), 3)
+ self.assertEqual(len(xml_outputs), 3)
+
+ # The header node should have an "<emit>" child and the proper filename.
+ self.assertTrue(header_outputs[0].GetChildrenOfType(io.EmitNode))
+ self.assertEqual(util.normpath(header_outputs[0].GetFilename()),
+ util.normpath('header/dir/chrome_android_strings.h'))
+
+ id_rc = filter(lambda x: x.GetLanguage() == 'id', rc_outputs)
+ id_xml = filter(lambda x: x.GetLanguage() == 'id', xml_outputs)
+ self.assertTrue(id_rc)
+ self.assertTrue(id_xml)
+ self.assertEqual(util.normpath(id_rc[0].GetFilename()),
+ util.normpath('rc/dir/chrome_android_strings_id.rc'))
+ self.assertEqual(util.normpath(id_xml[0].GetFilename()),
+ util.normpath('xml/dir/values-in/strings.xml'))
+
+ us_rc = filter(lambda x: x.GetLanguage() == 'en-US', rc_outputs)
+ us_xml = filter(lambda x: x.GetLanguage() == 'en-US', xml_outputs)
+ self.assertTrue(us_rc)
+ self.assertTrue(us_xml)
+ self.assertEqual(util.normpath(us_rc[0].GetFilename()),
+ util.normpath('rc/dir/chrome_android_strings_en-US.rc'))
+ self.assertEqual(util.normpath(us_xml[0].GetFilename()),
+ util.normpath('xml/dir/values-en-rUS/strings.xml'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/tool/build.py b/chromium/tools/grit/grit/tool/build.py
new file mode 100644
index 00000000000..596feb0a0f0
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/build.py
@@ -0,0 +1,306 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The 'grit build' tool along with integration for this tool with the
+SCons build system.
+'''
+
+import filecmp
+import getopt
+import os
+import shutil
+import sys
+
+from grit import grd_reader
+from grit import util
+from grit.tool import interface
+from grit import shortcuts
+
+
+# It would be cleaner to have each module register itself, but that would
+# require importing all of them on every run of GRIT.
+'''Map from <output> node types to modules under grit.format.'''
+_format_modules = {
+ 'android': 'android_xml',
+ 'c_format': 'c_format',
+ 'chrome_messages_json': 'chrome_messages_json',
+ 'data_package': 'data_pack',
+ 'js_map_format': 'js_map_format',
+ 'rc_all': 'rc',
+ 'rc_translateable': 'rc',
+ 'rc_nontranslateable': 'rc',
+ 'rc_header': 'rc_header',
+ 'resource_map_header': 'resource_map',
+ 'resource_map_source': 'resource_map',
+ 'resource_file_map_source': 'resource_map',
+}
+_format_modules.update((type, 'policy_templates.template_formatter')
+ for type in 'adm plist plist_strings admx adml doc json reg'.split())
+
+
+def GetFormatter(type):
+ modulename = 'grit.format.' + _format_modules[type]
+ __import__(modulename)
+ module = sys.modules[modulename]
+ try:
+ return module.Format
+ except AttributeError:
+ return module.GetFormatter(type)
+
+
+class RcBuilder(interface.Tool):
+ '''A tool that builds RC files and resource header files for compilation.
+
+Usage: grit build [-o OUTPUTDIR] [-D NAME[=VAL]]*
+
+All output options for this tool are specified in the input file (see
+'grit help' for details on how to specify the input file - it is a global
+option).
+
+Options:
+
+ -o OUTPUTDIR Specify what directory output paths are relative to.
+ Defaults to the current directory.
+
+ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
+ value VAL (defaults to 1) which will be used to control
+ conditional inclusion of resources.
+
+ -E NAME=VALUE Set environment variable NAME to VALUE (within grit).
+
+ -f FIRSTIDSFILE Path to a python file that specifies the first id of
+ value to use for resources. A non-empty value here will
+ override the value specified in the <grit> node's
+ first_ids_file.
+
+ -w WHITELISTFILE Path to a file containing the string names of the
+ resources to include. Anything not listed is dropped.
+
+ -t PLATFORM Specifies the platform the build is targeting; defaults
+ to the value of sys.platform. The value provided via this
+ flag should match what sys.platform would report for your
+ target platform; see grit.node.base.EvaluateCondition.
+
+Conditional inclusion of resources only affects the output of files which
+control which resources get linked into a binary, e.g. it affects .rc files
+meant for compilation but it does not affect resource header files (that define
+IDs). This helps ensure that values of IDs stay the same, that all messages
+are exported to translation interchange files (e.g. XMB files), etc.
+'''
+
+ def ShortDescription(self):
+ return 'A tool that builds RC files for compilation.'
+
+ def Run(self, opts, args):
+ self.output_directory = '.'
+ first_ids_file = None
+ whitelist_filenames = []
+ target_platform = None
+ (own_opts, args) = getopt.getopt(args, 'o:D:E:f:w:t:')
+ for (key, val) in own_opts:
+ if key == '-o':
+ self.output_directory = val
+ elif key == '-D':
+ name, val = util.ParseDefine(val)
+ self.defines[name] = val
+ elif key == '-E':
+ (env_name, env_value) = val.split('=', 1)
+ os.environ[env_name] = env_value
+ elif key == '-f':
+ # TODO(joi@chromium.org): Remove this override once change
+ # lands in WebKit.grd to specify the first_ids_file in the
+ # .grd itself.
+ first_ids_file = val
+ elif key == '-w':
+ whitelist_filenames.append(val)
+ elif key == '-t':
+ target_platform = val
+
+ if len(args):
+ print 'This tool takes no tool-specific arguments.'
+ return 2
+ self.SetOptions(opts)
+ if self.scons_targets:
+ self.VerboseOut('Using SCons targets to identify files to output.\n')
+ else:
+ self.VerboseOut('Output directory: %s (absolute path: %s)\n' %
+ (self.output_directory,
+ os.path.abspath(self.output_directory)))
+
+ if whitelist_filenames:
+ self.whitelist_names = set()
+ for whitelist_filename in whitelist_filenames:
+ self.VerboseOut('Using whitelist: %s\n' % whitelist_filename);
+ whitelist_contents = util.ReadFile(whitelist_filename, util.RAW_TEXT)
+ self.whitelist_names.update(whitelist_contents.strip().split('\n'))
+
+ self.res = grd_reader.Parse(opts.input,
+ debug=opts.extra_verbose,
+ first_ids_file=first_ids_file,
+ defines=self.defines,
+ target_platform=target_platform)
+ # Set an output context so that conditionals can use defines during the
+ # gathering stage; we use a dummy language here since we are not outputting
+ # a specific language.
+ self.res.SetOutputLanguage('en')
+ self.res.RunGatherers()
+ self.Process()
+ return 0
+
+ def __init__(self, defines=None):
+ # Default file-creation function is built-in open(). Only done to allow
+ # overriding by unit test.
+ self.fo_create = open
+
+ # key/value pairs of C-preprocessor like defines that are used for
+ # conditional output of resources
+ self.defines = defines or {}
+
+ # self.res is a fully-populated resource tree if Run()
+ # has been called, otherwise None.
+ self.res = None
+
+ # Set to a list of filenames for the output nodes that are relative
+ # to the current working directory. They are in the same order as the
+ # output nodes in the file.
+ self.scons_targets = None
+
+ # The set of names that are whitelisted to actually be included in the
+ # output.
+ self.whitelist_names = None
+
+
+ @staticmethod
+ def AddWhitelistTags(start_node, whitelist_names):
+ # Walk the tree of nodes added attributes for the nodes that shouldn't
+ # be written into the target files (skip markers).
+ from grit.node import include
+ from grit.node import message
+ for node in start_node:
+ # Same trick data_pack.py uses to see what nodes actually result in
+ # real items.
+ if (isinstance(node, include.IncludeNode) or
+ isinstance(node, message.MessageNode)):
+ text_ids = node.GetTextualIds()
+ # Mark the item to be skipped if it wasn't in the whitelist.
+ if text_ids and text_ids[0] not in whitelist_names:
+ node.SetWhitelistMarkedAsSkip(True)
+
+ @staticmethod
+ def ProcessNode(node, output_node, outfile):
+ '''Processes a node in-order, calling its formatter before and after
+ recursing to its children.
+
+ Args:
+ node: grit.node.base.Node subclass
+ output_node: grit.node.io.OutputNode
+ outfile: open filehandle
+ '''
+ base_dir = util.dirname(output_node.GetOutputFilename())
+
+ formatter = GetFormatter(output_node.GetType())
+ formatted = formatter(node, output_node.GetLanguage(), output_dir=base_dir)
+ outfile.writelines(formatted)
+
+
+ def Process(self):
+ # Update filenames with those provided by SCons if we're being invoked
+ # from SCons. The list of SCons targets also includes all <structure>
+ # node outputs, but it starts with our output files, in the order they
+ # occur in the .grd
+ if self.scons_targets:
+ assert len(self.scons_targets) >= len(self.res.GetOutputFiles())
+ outfiles = self.res.GetOutputFiles()
+ for ix in range(len(outfiles)):
+ outfiles[ix].output_filename = os.path.abspath(
+ self.scons_targets[ix])
+ else:
+ for output in self.res.GetOutputFiles():
+ output.output_filename = os.path.abspath(os.path.join(
+ self.output_directory, output.GetFilename()))
+
+ # If there are whitelisted names, tag the tree once up front, this way
+ # while looping through the actual output, it is just an attribute check.
+ if self.whitelist_names:
+ self.AddWhitelistTags(self.res, self.whitelist_names)
+
+ for output in self.res.GetOutputFiles():
+ self.VerboseOut('Creating %s...' % output.GetFilename())
+
+ # Microsoft's RC compiler can only deal with single-byte or double-byte
+ # files (no UTF-8), so we make all RC files UTF-16 to support all
+ # character sets.
+ if output.GetType() in ('rc_header', 'resource_map_header',
+ 'resource_map_source', 'resource_file_map_source'):
+ encoding = 'cp1252'
+ elif output.GetType() in ('android', 'c_format', 'js_map_format', 'plist',
+ 'plist_strings', 'doc', 'json'):
+ encoding = 'utf_8'
+ elif output.GetType() in ('chrome_messages_json'):
+ # Chrome Web Store currently expects BOM for UTF-8 files :-(
+ encoding = 'utf-8-sig'
+ else:
+ # TODO(gfeher) modify here to set utf-8 encoding for admx/adml
+ encoding = 'utf_16'
+
+ # Set the context, for conditional inclusion of resources
+ self.res.SetOutputLanguage(output.GetLanguage())
+ self.res.SetOutputContext(output.GetContext())
+ self.res.SetDefines(self.defines)
+
+ # Make the output directory if it doesn't exist.
+ outdir = os.path.split(output.GetOutputFilename())[0]
+ if not os.path.exists(outdir):
+ os.makedirs(outdir)
+
+ # Write the results to a temporary file and only overwrite the original
+ # if the file changed. This avoids unnecessary rebuilds.
+ outfile = self.fo_create(output.GetOutputFilename() + '.tmp', 'wb')
+
+ if output.GetType() != 'data_package':
+ outfile = util.WrapOutputStream(outfile, encoding)
+
+ # Iterate in-order through entire resource tree, calling formatters on
+ # the entry into a node and on exit out of it.
+ with outfile:
+ self.ProcessNode(self.res, output, outfile)
+
+ # Now copy from the temp file back to the real output, but on Windows,
+ # only if the real output doesn't exist or the contents of the file
+ # changed. This prevents identical headers from being written and .cc
+ # files from recompiling (which is painful on Windows).
+ if not os.path.exists(output.GetOutputFilename()):
+ os.rename(output.GetOutputFilename() + '.tmp',
+ output.GetOutputFilename())
+ else:
+ # CHROMIUM SPECIFIC CHANGE.
+ # This clashes with gyp + vstudio, which expect the output timestamp
+ # to change on a rebuild, even if nothing has changed.
+ #files_match = filecmp.cmp(output.GetOutputFilename(),
+ # output.GetOutputFilename() + '.tmp')
+ #if (output.GetType() != 'rc_header' or not files_match
+ # or sys.platform != 'win32'):
+ shutil.copy2(output.GetOutputFilename() + '.tmp',
+ output.GetOutputFilename())
+ os.remove(output.GetOutputFilename() + '.tmp')
+
+ self.VerboseOut(' done.\n')
+
+ # Print warnings if there are any duplicate shortcuts.
+ warnings = shortcuts.GenerateDuplicateShortcutsWarnings(
+ self.res.UberClique(), self.res.GetTcProject())
+ if warnings:
+ print '\n'.join(warnings)
+
+ # Print out any fallback warnings, and missing translation errors, and
+ # exit with an error code if there are missing translations in a non-pseudo
+ # and non-official build.
+ warnings = (self.res.UberClique().MissingTranslationsReport().
+ encode('ascii', 'replace'))
+ if warnings:
+ self.VerboseOut(warnings)
+ if self.res.UberClique().HasMissingTranslations():
+ print self.res.UberClique().missing_translations_
+ sys.exit(-1)
diff --git a/chromium/tools/grit/grit/tool/build_unittest.py b/chromium/tools/grit/grit/tool/build_unittest.py
new file mode 100644
index 00000000000..4ca4740fc62
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/build_unittest.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for the 'grit build' tool.
+'''
+
+import os
+import sys
+import tempfile
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+
+from grit import util
+from grit.tool import build
+
+
+class BuildUnittest(unittest.TestCase):
+
+ def testFindTranslationsWithSubstitutions(self):
+ # This is a regression test; we had a bug where GRIT would fail to find
+ # messages with substitutions e.g. "Hello [IDS_USER]" where IDS_USER is
+ # another <message>.
+ output_dir = tempfile.mkdtemp()
+ builder = build.RcBuilder()
+ class DummyOpts(object):
+ def __init__(self):
+ self.input = util.PathFromRoot('grit/testdata/substitute.grd')
+ self.verbose = False
+ self.extra_verbose = False
+ builder.Run(DummyOpts(), ['-o', output_dir])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/tool/buildinfo.py b/chromium/tools/grit/grit/tool/buildinfo.py
new file mode 100644
index 00000000000..f21d54c22e0
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/buildinfo.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Output the list of files to be generated by GRIT from an input.
+"""
+
+import getopt
+import os
+
+from grit import grd_reader
+from grit.node import structure
+from grit.tool import interface
+
+class DetermineBuildInfo(interface.Tool):
+ """Determine what files will be read and output by GRIT."""
+
+ def __init__(self):
+ pass
+
+ def ShortDescription(self):
+ """Describes this tool for the usage message."""
+ return ('Determine what files will be needed and\n'
+ 'output by GRIT with a given input.')
+
+ def Run(self, opts, args):
+ """Main method for the buildinfo tool. Outputs the list
+ of generated files and inputs used to stdout."""
+ self.output_directory = '.'
+ (own_opts, args) = getopt.getopt(args, 'o:')
+ for (key, val) in own_opts:
+ if key == '-o':
+ self.output_directory = val
+ if len(args) > 0:
+ print 'This tool takes exactly one argument: the output directory via -o'
+ return 2
+ self.SetOptions(opts)
+
+ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
+
+ langs = {}
+ for output in res_tree.GetOutputFiles():
+ if output.attrs['lang']:
+ langs[output.attrs['lang']] = os.path.dirname(output.GetFilename())
+
+ for lang, dirname in langs.iteritems():
+ old_output_language = res_tree.output_language
+ res_tree.SetOutputLanguage(lang)
+ for node in res_tree.ActiveDescendants():
+ with node:
+ if (isinstance(node, structure.StructureNode) and
+ node.HasFileForLanguage()):
+ path = node.FileForLanguage(lang, dirname, create_file=False,
+ return_if_not_generated=False)
+ if path:
+ path = os.path.join(self.output_directory, path)
+ path = os.path.normpath(path)
+ print '%s|%s' % ('rc_all', path)
+ res_tree.SetOutputLanguage(old_output_language)
+
+ for output in res_tree.GetOutputFiles():
+ path = os.path.join(self.output_directory, output.GetFilename())
+ path = os.path.normpath(path)
+ print '%s|%s' % (output.GetType(), path)
+
+ for infile in res_tree.GetInputFiles():
+ print 'input|%s' % os.path.normpath(infile)
diff --git a/chromium/tools/grit/grit/tool/buildinfo_unittest.py b/chromium/tools/grit/grit/tool/buildinfo_unittest.py
new file mode 100644
index 00000000000..b07bcd62206
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/buildinfo_unittest.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for the 'grit buildinfo' tool.
+"""
+
+import os
+import StringIO
+import sys
+import unittest
+
+# This is needed to find some of the imports below.
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+# pylint: disable-msg=C6204
+from grit.tool import buildinfo
+
+
+class BuildInfoUnittest(unittest.TestCase):
+ def setUp(self):
+ self.old_cwd = os.getcwd()
+ # Change CWD to make tests work independently of callers CWD.
+ os.chdir(os.path.dirname(__file__))
+ os.chdir('..')
+ self.buf = StringIO.StringIO()
+ self.old_stdout = sys.stdout
+ sys.stdout = self.buf
+
+ def tearDown(self):
+ sys.stdout = self.old_stdout
+ os.chdir(self.old_cwd)
+
+ def testBuildOutput(self):
+ """Find all of the inputs and outputs for a GRD file."""
+ info_object = buildinfo.DetermineBuildInfo()
+
+ class DummyOpts(object):
+ def __init__(self):
+ self.input = '../grit/testdata/buildinfo.grd'
+ self.print_header = False
+ self.verbose = False
+ self.extra_verbose = False
+ info_object.Run(DummyOpts(), [])
+ output = self.buf.getvalue().replace('\\', '/')
+ self.failUnless(output.count(r'rc_all|sv_sidebar_loading.html'))
+ self.failUnless(output.count(r'rc_header|resource.h'))
+ self.failUnless(output.count(r'rc_all|en_generated_resources.rc'))
+ self.failUnless(output.count(r'rc_all|sv_generated_resources.rc'))
+ self.failUnless(output.count(r'input|../grit/testdata/substitute.xmb'))
+ self.failUnless(output.count(r'input|../grit/testdata/pr.bmp'))
+ self.failUnless(output.count(r'input|../grit/testdata/pr2.bmp'))
+ self.failUnless(
+ output.count(r'input|../grit/testdata/sidebar_loading.html'))
+ self.failUnless(output.count(r'input|../grit/testdata/transl.rc'))
+ self.failUnless(output.count(r'input|../grit/testdata/transl1.rc'))
+
+ def testBuildOutputWithDir(self):
+ """Find all the inputs and outputs for a GRD file with an output dir."""
+ info_object = buildinfo.DetermineBuildInfo()
+
+ class DummyOpts(object):
+ def __init__(self):
+ self.input = '../grit/testdata/buildinfo.grd'
+ self.print_header = False
+ self.verbose = False
+ self.extra_verbose = False
+ info_object.Run(DummyOpts(), ['-o', '../grit/testdata'])
+ output = self.buf.getvalue().replace('\\', '/')
+ self.failUnless(
+ output.count(r'rc_all|../grit/testdata/sv_sidebar_loading.html'))
+ self.failUnless(output.count(r'rc_header|../grit/testdata/resource.h'))
+ self.failUnless(
+ output.count(r'rc_all|../grit/testdata/en_generated_resources.rc'))
+ self.failUnless(
+ output.count(r'rc_all|../grit/testdata/sv_generated_resources.rc'))
+ self.failUnless(output.count(r'input|../grit/testdata/substitute.xmb'))
+ self.failUnlessEqual(0,
+ output.count(r'rc_all|../grit/testdata/sv_welcome_toast.html'))
+ self.failUnless(
+ output.count(r'rc_all|../grit/testdata/en_welcome_toast.html'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/tool/count.py b/chromium/tools/grit/grit/tool/count.py
new file mode 100644
index 00000000000..e87c4900f21
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/count.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Count number of occurrences of a given message ID.'''
+
+from grit import grd_reader
+from grit.tool import interface
+
+
+class CountMessage(interface.Tool):
+ '''Count the number of times a given message ID is used.'''
+
+ def __init__(self):
+ pass
+
+ def ShortDescription(self):
+ return 'Count the number of times a given message ID is used.'
+
+ def Run(self, opts, args):
+ self.SetOptions(opts)
+
+ id = args[0]
+ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
+ res_tree.OnlyTheseTranslations([])
+ res_tree.RunGatherers()
+
+ count = 0
+ for c in res_tree.UberClique().AllCliques():
+ if c.GetId() == id:
+ count += 1
+
+ print "There are %d occurrences of message %s." % (count, id)
+
diff --git a/chromium/tools/grit/grit/tool/diff_structures.py b/chromium/tools/grit/grit/tool/diff_structures.py
new file mode 100644
index 00000000000..e2b10b9a9b4
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/diff_structures.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The 'grit sdiff' tool.
+'''
+
+import os
+import getopt
+import tempfile
+
+from grit.node import structure
+from grit.tool import interface
+
+from grit import constants
+from grit import util
+
+# Builds the description for the tool (used as the __doc__
+# for the DiffStructures class).
+_class_doc = """\
+Allows you to view the differences in the structure of two files,
+disregarding their translateable content. Translateable portions of
+each file are changed to the string "TTTTTT" before invoking the diff program
+specified by the P4DIFF environment variable.
+
+Usage: grit sdiff [-t TYPE] [-s SECTION] [-e ENCODING] LEFT RIGHT
+
+LEFT and RIGHT are the files you want to diff. SECTION is required
+for structure types like 'dialog' to identify the part of the file to look at.
+ENCODING indicates the encoding of the left and right files (default 'cp1252').
+TYPE can be one of the following, defaults to 'tr_html':
+"""
+for gatherer in structure._GATHERERS:
+ _class_doc += " - %s\n" % gatherer
+
+
+class DiffStructures(interface.Tool):
+ __doc__ = _class_doc
+
+ def __init__(self):
+ self.section = None
+ self.left_encoding = 'cp1252'
+ self.right_encoding = 'cp1252'
+ self.structure_type = 'tr_html'
+
+ def ShortDescription(self):
+ return 'View differences without regard for translateable portions.'
+
+ def Run(self, global_opts, args):
+ (opts, args) = getopt.getopt(args, 's:e:t:',
+ ['left_encoding=', 'right_encoding='])
+ for key, val in opts:
+ if key == '-s':
+ self.section = val
+ elif key == '-e':
+ self.left_encoding = val
+ self.right_encoding = val
+ elif key == '-t':
+ self.structure_type = val
+ elif key == '--left_encoding':
+ self.left_encoding = val
+ elif key == '--right_encoding':
+ self.right_encoding == val
+
+ if len(args) != 2:
+ print "Incorrect usage - 'grit help sdiff' for usage details."
+ return 2
+
+ if 'P4DIFF' not in os.environ:
+ print "Environment variable P4DIFF not set; defaulting to 'windiff'."
+ diff_program = 'windiff'
+ else:
+ diff_program = os.environ['P4DIFF']
+
+ left_trans = self.MakeStaticTranslation(args[0], self.left_encoding)
+ try:
+ try:
+ right_trans = self.MakeStaticTranslation(args[1], self.right_encoding)
+
+ os.system('%s %s %s' % (diff_program, left_trans, right_trans))
+ finally:
+ os.unlink(right_trans)
+ finally:
+ os.unlink(left_trans)
+
+ def MakeStaticTranslation(self, original_filename, encoding):
+ """Given the name of the structure type (self.structure_type), the filename
+ of the file holding the original structure, and optionally the "section" key
+ identifying the part of the file to look at (self.section), creates a
+ temporary file holding a "static" translation of the original structure
+ (i.e. one where all translateable parts have been replaced with "TTTTTT")
+ and returns the temporary file name. It is the caller's responsibility to
+ delete the file when finished.
+
+ Args:
+ original_filename: 'c:\\bingo\\bla.rc'
+
+ Return:
+ 'c:\\temp\\werlkjsdf334.tmp'
+ """
+ original = structure._GATHERERS[self.structure_type](original_filename,
+ extkey=self.section,
+ encoding=encoding)
+ original.Parse()
+ translated = original.Translate(constants.CONSTANT_LANGUAGE, False)
+
+ fname = tempfile.mktemp()
+ with util.WrapOutputStream(open(fname, 'w')) as writer:
+ writer.write("Original filename: %s\n=============\n\n"
+ % original_filename)
+ writer.write(translated) # write in UTF-8
+
+ return fname
diff --git a/chromium/tools/grit/grit/tool/interface.py b/chromium/tools/grit/grit/tool/interface.py
new file mode 100644
index 00000000000..bec4e1cc8d6
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/interface.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Base class and interface for tools.
+'''
+
+
+class Tool(object):
+ '''Base class for all tools. Tools should use their docstring (i.e. the
+ class-level docstring) for the help they want to have printed when they
+ are invoked.'''
+
+ #
+ # Interface (abstract methods)
+ #
+
+ def ShortDescription(self):
+ '''Returns a short description of the functionality of the tool.'''
+ raise NotImplementedError()
+
+ def Run(self, global_options, my_arguments):
+ '''Runs the tool.
+
+ Args:
+ global_options: object grit_runner.Options
+ my_arguments: [arg1 arg2 ...]
+
+ Return:
+ 0 for success, non-0 for error
+ '''
+ raise NotImplementedError()
+
+ #
+ # Base class implementation
+ #
+
+ def __init__(self):
+ self.o = None
+
+ def SetOptions(self, opts):
+ self.o = opts
+
+ def Out(self, text):
+ '''Always writes out 'text'.'''
+ self.o.output_stream.write(text)
+
+ def VerboseOut(self, text):
+ '''Writes out 'text' if the verbose option is on.'''
+ if self.o.verbose:
+ self.o.output_stream.write(text)
+
+ def ExtraVerboseOut(self, text):
+ '''Writes out 'text' if the extra-verbose option is on.
+ '''
+ if self.o.extra_verbose:
+ self.o.output_stream.write(text)
diff --git a/chromium/tools/grit/grit/tool/menu_from_parts.py b/chromium/tools/grit/grit/tool/menu_from_parts.py
new file mode 100644
index 00000000000..36d2d4086ac
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/menu_from_parts.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The 'grit menufromparts' tool.'''
+
+import types
+
+from grit import grd_reader
+from grit import tclib
+from grit import util
+from grit import xtb_reader
+from grit.tool import interface
+from grit.tool import transl2tc
+
+import grit.extern.tclib
+
+
+class MenuTranslationsFromParts(interface.Tool):
+ '''One-off tool to generate translated menu messages (where each menu is kept
+in a single message) based on existing translations of the individual menu
+items. Was needed when changing menus from being one message per menu item
+to being one message for the whole menu.'''
+
+ def ShortDescription(self):
+ return ('Create translations of whole menus from existing translations of '
+ 'menu items.')
+
+ def Run(self, globopt, args):
+ self.SetOptions(globopt)
+ assert len(args) == 2, "Need exactly two arguments, the XTB file and the output file"
+
+ xtb_file = args[0]
+ output_file = args[1]
+
+ grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose)
+ grd.OnlyTheseTranslations([]) # don't load translations
+ grd.RunGatherers()
+
+ xtb = {}
+ def Callback(msg_id, parts):
+ msg = []
+ for part in parts:
+ if part[0]:
+ msg = []
+ break # it had a placeholder so ignore it
+ else:
+ msg.append(part[1])
+ if len(msg):
+ xtb[msg_id] = ''.join(msg)
+ with open(xtb_file) as f:
+ xtb_reader.Parse(f, Callback)
+
+ translations = [] # list of translations as per transl2tc.WriteTranslations
+ for node in grd:
+ if node.name == 'structure' and node.attrs['type'] == 'menu':
+ assert len(node.GetCliques()) == 1
+ message = node.GetCliques()[0].GetMessage()
+ translation = []
+
+ contents = message.GetContent()
+ for part in contents:
+ if isinstance(part, types.StringTypes):
+ id = grit.extern.tclib.GenerateMessageId(part)
+ if id not in xtb:
+ print "WARNING didn't find all translations for menu %s" % node.attrs['name']
+ translation = []
+ break
+ translation.append(xtb[id])
+ else:
+ translation.append(part.GetPresentation())
+
+ if len(translation):
+ translations.append([message.GetId(), ''.join(translation)])
+
+ with util.WrapOutputStream(open(output_file, 'w')) as f:
+ transl2tc.TranslationToTc.WriteTranslations(f, translations)
+
diff --git a/chromium/tools/grit/grit/tool/newgrd.py b/chromium/tools/grit/grit/tool/newgrd.py
new file mode 100644
index 00000000000..1dc7a7d3ed8
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/newgrd.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Tool to create a new, empty .grd file with all the basic sections.
+'''
+
+from grit.tool import interface
+from grit import constants
+from grit import util
+
+# The contents of the new .grd file
+_FILE_CONTENTS = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+<grit base_dir="." latest_public_release="0" current_release="1"
+ source_lang_id="en" enc_check="%s">
+ <outputs>
+ <!-- TODO add each of your output files. Modify the three below, and add
+ your own for your various languages. See the user's guide for more
+ details.
+ Note that all output references are relative to the output directory
+ which is specified at build time. -->
+ <output filename="resource.h" type="rc_header" />
+ <output filename="en_resource.rc" type="rc_all" />
+ <output filename="fr_resource.rc" type="rc_all" />
+ </outputs>
+ <translations>
+ <!-- TODO add references to each of the XTB files (from the Translation
+ Console) that contain translations of messages in your project. Each
+ takes a form like <file path="english.xtb" />. Remember that all file
+ references are relative to this .grd file. -->
+ </translations>
+ <release seq="1">
+ <includes>
+ <!-- TODO add a list of your included resources here, e.g. BMP and GIF
+ resources. -->
+ </includes>
+ <structures>
+ <!-- TODO add a list of all your structured resources here, e.g. HTML
+ templates, menus, dialogs etc. Note that for menus, dialogs and version
+ information resources you reference an .rc file containing them.-->
+ </structures>
+ <messages>
+ <!-- TODO add all of your "string table" messages here. Remember to
+ change nontranslateable parts of the messages into placeholders (using the
+ <ph> element). You can also use the 'grit add' tool to help you identify
+ nontranslateable parts and create placeholders for them. -->
+ </messages>
+ </release>
+</grit>''' % constants.ENCODING_CHECK
+
+
+class NewGrd(interface.Tool):
+ '''Usage: grit newgrd OUTPUT_FILE
+
+Creates a new, empty .grd file OUTPUT_FILE with comments about what to put
+where in the file.'''
+
+ def ShortDescription(self):
+ return 'Create a new empty .grd file.'
+
+ def Run(self, global_options, my_arguments):
+ if not len(my_arguments) == 1:
+ print 'This tool requires exactly one argument, the name of the output file.'
+ return 2
+ filename = my_arguments[0]
+ with util.WrapOutputStream(open(filename, 'w'), 'utf-8') as out:
+ out.write(_FILE_CONTENTS)
+ print "Wrote file %s" % filename
diff --git a/chromium/tools/grit/grit/tool/postprocess_interface.py b/chromium/tools/grit/grit/tool/postprocess_interface.py
new file mode 100644
index 00000000000..4a432544414
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/postprocess_interface.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+''' Base class for postprocessing of RC files.
+'''
+
+
+class PostProcessor(object):
+ ''' Base class for postprocessing of the RC file data before being
+ output through the RC2GRD tool. You should implement this class if
+ you want GRIT to do specific things to the RC files after it has
+ converted the data into GRD format, i.e. change the content of the
+ RC file, and put it into a P4 changelist, etc.'''
+
+
+ def Process(self, rctext, rcpath, grdnode):
+ ''' Processes the data in rctext and grdnode.
+ Args:
+ rctext: string containing the contents of the RC file being processed.
+ rcpath: the path used to access the file.
+ grdtext: the root node of the grd xml data generated by
+ the rc2grd tool.
+
+ Return:
+ The root node of the processed GRD tree.
+ '''
+ raise NotImplementedError()
+
+
+
diff --git a/chromium/tools/grit/grit/tool/postprocess_unittest.py b/chromium/tools/grit/grit/tool/postprocess_unittest.py
new file mode 100644
index 00000000000..330db49004b
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/postprocess_unittest.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit test that checks postprocessing of files.
+ Tests postprocessing by having the postprocessor
+ modify the grd data tree, changing the message name attributes.
+'''
+
+import os
+import re
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+
+import grit.tool.postprocess_interface
+from grit.tool import rc2grd
+
+
+class PostProcessingUnittest(unittest.TestCase):
+
+ def testPostProcessing(self):
+ rctext = '''STRINGTABLE
+BEGIN
+ DUMMY_STRING_1 "String 1"
+ // Some random description
+ DUMMY_STRING_2 "This text was added during preprocessing"
+END
+ '''
+ tool = rc2grd.Rc2Grd()
+ class DummyOpts(object):
+ verbose = False
+ extra_verbose = False
+ tool.o = DummyOpts()
+ tool.post_process = 'grit.tool.postprocess_unittest.DummyPostProcessor'
+ result = tool.Process(rctext, '.\resource.rc')
+
+ self.failUnless(
+ result.children[2].children[2].children[0].attrs['name'] == 'SMART_STRING_1')
+ self.failUnless(
+ result.children[2].children[2].children[1].attrs['name'] == 'SMART_STRING_2')
+
+class DummyPostProcessor(grit.tool.postprocess_interface.PostProcessor):
+ '''
+ Post processing replaces all message name attributes containing "DUMMY" to
+ "SMART".
+ '''
+ def Process(self, rctext, rcpath, grdnode):
+ smarter = re.compile(r'(DUMMY)(.*)')
+ messages = grdnode.children[2].children[2]
+ for node in messages.children:
+ name_attr = node.attrs['name']
+ m = smarter.search(name_attr)
+ if m:
+ node.attrs['name'] = 'SMART' + m.group(2)
+ return grdnode
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/tool/preprocess_interface.py b/chromium/tools/grit/grit/tool/preprocess_interface.py
new file mode 100644
index 00000000000..4c5456c6de3
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/preprocess_interface.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+''' Base class for preprocessing of RC files.
+'''
+
+
+class PreProcessor(object):
+ ''' Base class for preprocessing of the RC file data before being
+ output through the RC2GRD tool. You should implement this class if
+ you have specific constructs in your RC files that GRIT cannot handle.'''
+
+
+ def Process(self, rctext, rcpath):
+ ''' Processes the data in rctext.
+ Args:
+ rctext: string containing the contents of the RC file being processed
+ rcpath: the path used to access the file.
+
+ Return:
+ The processed text.
+ '''
+ raise NotImplementedError()
+
+
+
diff --git a/chromium/tools/grit/grit/tool/preprocess_unittest.py b/chromium/tools/grit/grit/tool/preprocess_unittest.py
new file mode 100644
index 00000000000..1fc71922585
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/preprocess_unittest.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit test that checks preprocessing of files.
+ Tests preprocessing by adding having the preprocessor
+ provide the actual rctext data.
+'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+
+import grit.tool.preprocess_interface
+from grit.tool import rc2grd
+
+
+class PreProcessingUnittest(unittest.TestCase):
+
+ def testPreProcessing(self):
+ tool = rc2grd.Rc2Grd()
+ class DummyOpts(object):
+ verbose = False
+ extra_verbose = False
+ tool.o = DummyOpts()
+ tool.pre_process = 'grit.tool.preprocess_unittest.DummyPreProcessor'
+ result = tool.Process('', '.\resource.rc')
+
+ self.failUnless(
+ result.children[2].children[2].children[0].attrs['name'] == 'DUMMY_STRING_1')
+
+class DummyPreProcessor(grit.tool.preprocess_interface.PreProcessor):
+ def Process(self, rctext, rcpath):
+ rctext = '''STRINGTABLE
+BEGIN
+ DUMMY_STRING_1 "String 1"
+ // Some random description
+ DUMMY_STRING_2 "This text was added during preprocessing"
+END
+ '''
+ return rctext
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/tool/rc2grd.py b/chromium/tools/grit/grit/tool/rc2grd.py
new file mode 100644
index 00000000000..10d36f600b0
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/rc2grd.py
@@ -0,0 +1,409 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The 'grit rc2grd' tool.'''
+
+
+import os.path
+import getopt
+import re
+import StringIO
+import types
+
+import grit.node.empty
+from grit.node import include
+from grit.node import structure
+from grit.node import message
+
+from grit.gather import rc
+from grit.gather import tr_html
+
+from grit.tool import interface
+from grit.tool import postprocess_interface
+from grit.tool import preprocess_interface
+
+from grit import grd_reader
+from grit import lazy_re
+from grit import tclib
+from grit import util
+
+
+# Matches files referenced from an .rc file
+_FILE_REF = lazy_re.compile('''
+ ^(?P<id>[A-Z_0-9.]+)[ \t]+
+ (?P<type>[A-Z_0-9]+)[ \t]+
+ "(?P<file>.*?([^"]|""))"[ \t]*$''', re.VERBOSE | re.MULTILINE)
+
+
+# Matches a dialog section
+_DIALOG = lazy_re.compile(
+ '^(?P<id>[A-Z0-9_]+)\s+DIALOG(EX)?\s.+?^BEGIN\s*$.+?^END\s*$',
+ re.MULTILINE | re.DOTALL)
+
+
+# Matches a menu section
+_MENU = lazy_re.compile('^(?P<id>[A-Z0-9_]+)\s+MENU.+?^BEGIN\s*$.+?^END\s*$',
+ re.MULTILINE | re.DOTALL)
+
+
+# Matches a versioninfo section
+_VERSIONINFO = lazy_re.compile(
+ '^(?P<id>[A-Z0-9_]+)\s+VERSIONINFO\s.+?^BEGIN\s*$.+?^END\s*$',
+ re.MULTILINE | re.DOTALL)
+
+
+# Matches a stringtable
+_STRING_TABLE = lazy_re.compile(
+ ('^STRINGTABLE(\s+(PRELOAD|DISCARDABLE|CHARACTERISTICS.+|LANGUAGE.+|'
+ 'VERSION.+))*\s*\nBEGIN\s*$(?P<body>.+?)^END\s*$'),
+ re.MULTILINE | re.DOTALL)
+
+
+# Matches each message inside a stringtable, breaking it up into comments,
+# the ID of the message, and the (RC-escaped) message text.
+_MESSAGE = lazy_re.compile('''
+ (?P<comment>(^\s+//.+?)*) # 0 or more lines of comments preceding the message
+ ^\s*
+ (?P<id>[A-Za-z0-9_]+) # id
+ \s+
+ "(?P<text>.*?([^"]|""))"([^"]|$) # The message itself
+ ''', re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+# Matches each line of comment text in a multi-line comment.
+_COMMENT_TEXT = lazy_re.compile('^\s*//\s*(?P<text>.+?)$', re.MULTILINE)
+
+
+# Matches a string that is empty or all whitespace
+_WHITESPACE_ONLY = lazy_re.compile('\A\s*\Z', re.MULTILINE)
+
+
+# Finds printf and FormatMessage style format specifiers
+# Uses non-capturing groups except for the outermost group, so the output of
+# re.split() should include both the normal text and what we intend to
+# replace with placeholders.
+# TODO(joi) Check documentation for printf (and Windows variants) and FormatMessage
+_FORMAT_SPECIFIER = lazy_re.compile(
+ '(%[-# +]?(?:[0-9]*|\*)(?:\.(?:[0-9]+|\*))?(?:h|l|L)?' # printf up to last char
+ '(?:d|i|o|u|x|X|e|E|f|F|g|G|c|r|s|ls|ws)' # printf last char
+ '|\$[1-9][0-9]*)') # FormatMessage
+
+
+class Rc2Grd(interface.Tool):
+ '''A tool for converting .rc files to .grd files. This tool is only for
+converting the source (nontranslated) .rc file to a .grd file. For importing
+existing translations, use the rc2xtb tool.
+
+Usage: grit [global options] rc2grd [OPTIONS] RCFILE
+
+The tool takes a single argument, which is the path to the .rc file to convert.
+It outputs a .grd file with the same name in the same directory as the .rc file.
+The .grd file may have one or more TODO comments for things that have to be
+cleaned up manually.
+
+OPTIONS may be any of the following:
+
+ -e ENCODING Specify the ENCODING of the .rc file. Default is 'cp1252'.
+
+ -h TYPE Specify the TYPE attribute for HTML structures.
+ Default is 'tr_html'.
+
+ -u ENCODING Specify the ENCODING of HTML files. Default is 'utf-8'.
+
+ -n MATCH Specify the regular expression to match in comments that will
+ indicate that the resource the comment belongs to is not
+ translateable. Default is 'Not locali(s|z)able'.
+
+ -r GRDFILE Specify that GRDFILE should be used as a "role model" for
+ any placeholders that otherwise would have had TODO names.
+ This attempts to find an identical message in the GRDFILE
+ and uses that instead of the automatically placeholderized
+ message.
+
+ --pre CLASS Specify an optional, fully qualified classname, which
+ has to be a subclass of grit.tool.PreProcessor, to
+ run on the text of the RC file before conversion occurs.
+ This can be used to support constructs in the RC files
+ that GRIT cannot handle on its own.
+
+ --post CLASS Specify an optional, fully qualified classname, which
+ has to be a subclass of grit.tool.PostProcessor, to
+ run on the text of the converted RC file.
+ This can be used to alter the content of the RC file
+ based on the conversion that occured.
+
+For menus, dialogs and version info, the .grd file will refer to the original
+.rc file. Once conversion is complete, you can strip the original .rc file
+of its string table and all comments as these will be available in the .grd
+file.
+
+Note that this tool WILL NOT obey C preprocessor rules, so even if something
+is #if 0-ed out it will still be included in the output of this tool
+Therefore, if your .rc file contains sections like this, you should run the
+C preprocessor on the .rc file or manually edit it before using this tool.
+'''
+
+ def ShortDescription(self):
+ return 'A tool for converting .rc source files to .grd files.'
+
+ def __init__(self):
+ self.input_encoding = 'cp1252'
+ self.html_type = 'tr_html'
+ self.html_encoding = 'utf-8'
+ self.not_localizable_re = re.compile('Not locali(s|z)able')
+ self.role_model = None
+ self.pre_process = None
+ self.post_process = None
+
+ def ParseOptions(self, args):
+ '''Given a list of arguments, set this object's options and return
+ all non-option arguments.
+ '''
+ (own_opts, args) = getopt.getopt(args, 'e:h:u:n:r', ['pre=', 'post='])
+ for (key, val) in own_opts:
+ if key == '-e':
+ self.input_encoding = val
+ elif key == '-h':
+ self.html_type = val
+ elif key == '-u':
+ self.html_encoding = val
+ elif key == '-n':
+ self.not_localizable_re = re.compile(val)
+ elif key == '-r':
+ self.role_model = grd_reader.Parse(val)
+ elif key == '--pre':
+ self.pre_process = val
+ elif key == '--post':
+ self.post_process = val
+ return args
+
+ def Run(self, opts, args):
+ args = self.ParseOptions(args)
+ if len(args) != 1:
+ print ('This tool takes a single tool-specific argument, the path to the\n'
+ '.rc file to process.')
+ return 2
+ self.SetOptions(opts)
+
+ path = args[0]
+ out_path = os.path.join(util.dirname(path),
+ os.path.splitext(os.path.basename(path))[0] + '.grd')
+
+ rctext = util.ReadFile(path, self.input_encoding)
+ grd_text = unicode(self.Process(rctext, path))
+ with util.WrapOutputStream(file(out_path, 'w'), 'utf-8') as outfile:
+ outfile.write(grd_text)
+
+ print 'Wrote output file %s.\nPlease check for TODO items in the file.' % out_path
+
+
+ def Process(self, rctext, rc_path):
+ '''Processes 'rctext' and returns a resource tree corresponding to it.
+
+ Args:
+ rctext: complete text of the rc file
+ rc_path: 'resource\resource.rc'
+
+ Return:
+ grit.node.base.Node subclass
+ '''
+
+ if self.pre_process:
+ preprocess_class = util.NewClassInstance(self.pre_process,
+ preprocess_interface.PreProcessor)
+ if preprocess_class:
+ rctext = preprocess_class.Process(rctext, rc_path)
+ else:
+ self.Out(
+ 'PreProcessing class could not be found. Skipping preprocessing.\n')
+
+ # Start with a basic skeleton for the .grd file
+ root = grd_reader.Parse(StringIO.StringIO(
+ '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit base_dir="." latest_public_release="0"
+ current_release="1" source_lang_id="en">
+ <outputs />
+ <translations />
+ <release seq="1">
+ <includes />
+ <structures />
+ <messages />
+ </release>
+ </grit>'''), util.dirname(rc_path))
+ includes = root.children[2].children[0]
+ structures = root.children[2].children[1]
+ messages = root.children[2].children[2]
+ assert (isinstance(includes, grit.node.empty.IncludesNode) and
+ isinstance(structures, grit.node.empty.StructuresNode) and
+ isinstance(messages, grit.node.empty.MessagesNode))
+
+ self.AddIncludes(rctext, includes)
+ self.AddStructures(rctext, structures, os.path.basename(rc_path))
+ self.AddMessages(rctext, messages)
+
+ self.VerboseOut('Validating that all IDs are unique...\n')
+ root.ValidateUniqueIds()
+ self.ExtraVerboseOut('Done validating that all IDs are unique.\n')
+
+ if self.post_process:
+ postprocess_class = util.NewClassInstance(self.post_process,
+ postprocess_interface.PostProcessor)
+ if postprocess_class:
+ root = postprocess_class.Process(rctext, rc_path, root)
+ else:
+ self.Out(
+ 'PostProcessing class could not be found. Skipping postprocessing.\n')
+
+ return root
+
+
+ def IsHtml(self, res_type, fname):
+ '''Check whether both the type and file extension indicate HTML'''
+ fext = fname.split('.')[-1].lower()
+ return res_type == 'HTML' and fext in ('htm', 'html')
+
+
+ def AddIncludes(self, rctext, node):
+ '''Scans 'rctext' for included resources (e.g. BITMAP, ICON) and
+ adds each included resource as an <include> child node of 'node'.'''
+ for m in _FILE_REF.finditer(rctext):
+ id = m.group('id')
+ res_type = m.group('type').upper()
+ fname = rc.Section.UnEscape(m.group('file'))
+ assert fname.find('\n') == -1
+ if not self.IsHtml(res_type, fname):
+ self.VerboseOut('Processing %s with ID %s (filename: %s)\n' %
+ (res_type, id, fname))
+ node.AddChild(include.IncludeNode.Construct(node, id, res_type, fname))
+
+
+ def AddStructures(self, rctext, node, rc_filename):
+ '''Scans 'rctext' for structured resources (e.g. menus, dialogs, version
+ information resources and HTML templates) and adds each as a <structure>
+ child of 'node'.'''
+ # First add HTML includes
+ for m in _FILE_REF.finditer(rctext):
+ id = m.group('id')
+ res_type = m.group('type').upper()
+ fname = rc.Section.UnEscape(m.group('file'))
+ if self.IsHtml(type, fname):
+ node.AddChild(structure.StructureNode.Construct(
+ node, id, self.html_type, fname, self.html_encoding))
+
+ # Then add all RC includes
+ def AddStructure(res_type, id):
+ self.VerboseOut('Processing %s with ID %s\n' % (res_type, id))
+ node.AddChild(structure.StructureNode.Construct(node, id, res_type,
+ rc_filename,
+ encoding=self.input_encoding))
+ for m in _MENU.finditer(rctext):
+ AddStructure('menu', m.group('id'))
+ for m in _DIALOG.finditer(rctext):
+ AddStructure('dialog', m.group('id'))
+ for m in _VERSIONINFO.finditer(rctext):
+ AddStructure('version', m.group('id'))
+
+
+ def AddMessages(self, rctext, node):
+ '''Scans 'rctext' for all messages in string tables, preprocesses them as
+ much as possible for placeholders (e.g. messages containing $1, $2 or %s, %d
+ type format specifiers get those specifiers replaced with placeholders, and
+ HTML-formatted messages get run through the HTML-placeholderizer). Adds
+ each message as a <message> node child of 'node'.'''
+ for tm in _STRING_TABLE.finditer(rctext):
+ table = tm.group('body')
+ for mm in _MESSAGE.finditer(table):
+ comment_block = mm.group('comment')
+ comment_text = []
+ for cm in _COMMENT_TEXT.finditer(comment_block):
+ comment_text.append(cm.group('text'))
+ comment_text = ' '.join(comment_text)
+
+ id = mm.group('id')
+ text = rc.Section.UnEscape(mm.group('text'))
+
+ self.VerboseOut('Processing message %s (text: "%s")\n' % (id, text))
+
+ msg_obj = self.Placeholderize(text)
+
+ # Messages that contain only placeholders do not need translation.
+ is_translateable = False
+ for item in msg_obj.GetContent():
+ if isinstance(item, types.StringTypes):
+ if not _WHITESPACE_ONLY.match(item):
+ is_translateable = True
+
+ if self.not_localizable_re.search(comment_text):
+ is_translateable = False
+
+ message_meaning = ''
+ internal_comment = ''
+
+ # If we have a "role model" (existing GRD file) and this node exists
+ # in the role model, use the description, meaning and translateable
+ # attributes from the role model.
+ if self.role_model:
+ role_node = self.role_model.GetNodeById(id)
+ if role_node:
+ is_translateable = role_node.IsTranslateable()
+ message_meaning = role_node.attrs['meaning']
+ comment_text = role_node.attrs['desc']
+ internal_comment = role_node.attrs['internal_comment']
+
+ # For nontranslateable messages, we don't want the complexity of
+ # placeholderizing everything.
+ if not is_translateable:
+ msg_obj = tclib.Message(text=text)
+
+ msg_node = message.MessageNode.Construct(node, msg_obj, id,
+ desc=comment_text,
+ translateable=is_translateable,
+ meaning=message_meaning)
+ msg_node.attrs['internal_comment'] = internal_comment
+
+ node.AddChild(msg_node)
+ self.ExtraVerboseOut('Done processing message %s\n' % id)
+
+
+ def Placeholderize(self, text):
+ '''Creates a tclib.Message object from 'text', attempting to recognize
+ a few different formats of text that can be automatically placeholderized
+ (HTML code, printf-style format strings, and FormatMessage-style format
+ strings).
+ '''
+
+ try:
+ # First try HTML placeholderizing.
+ # TODO(joi) Allow use of non-TotalRecall flavors of HTML placeholderizing
+ msg = tr_html.HtmlToMessage(text, True)
+ for item in msg.GetContent():
+ if not isinstance(item, types.StringTypes):
+ return msg # Contained at least one placeholder, so we're done
+
+ # HTML placeholderization didn't do anything, so try to find printf or
+ # FormatMessage format specifiers and change them into placeholders.
+ msg = tclib.Message()
+ parts = _FORMAT_SPECIFIER.split(text)
+ todo_counter = 1 # We make placeholder IDs 'TODO_0001' etc.
+ for part in parts:
+ if _FORMAT_SPECIFIER.match(part):
+ msg.AppendPlaceholder(tclib.Placeholder(
+ 'TODO_%04d' % todo_counter, part, 'TODO'))
+ todo_counter += 1
+ elif part != '':
+ msg.AppendText(part)
+
+ if self.role_model and len(parts) > 1: # there are TODO placeholders
+ role_model_msg = self.role_model.UberClique().BestCliqueByOriginalText(
+ msg.GetRealContent(), '')
+ if role_model_msg:
+ # replace wholesale to get placeholder names and examples
+ msg = role_model_msg
+
+ return msg
+ except:
+ print 'Exception processing message with text "%s"' % text
+ raise
+
diff --git a/chromium/tools/grit/grit/tool/rc2grd_unittest.py b/chromium/tools/grit/grit/tool/rc2grd_unittest.py
new file mode 100644
index 00000000000..b41f5e43aaa
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/rc2grd_unittest.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.tool.rc2grd'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import re
+import StringIO
+import unittest
+
+from grit import grd_reader
+from grit.node import base
+from grit.tool import rc2grd
+
+
+class Rc2GrdUnittest(unittest.TestCase):
+ def testPlaceholderize(self):
+ tool = rc2grd.Rc2Grd()
+ original = "Hello %s, how are you? I'm $1 years old!"
+ msg = tool.Placeholderize(original)
+ self.failUnless(msg.GetPresentableContent() == "Hello TODO_0001, how are you? I'm TODO_0002 years old!")
+ self.failUnless(msg.GetRealContent() == original)
+
+ def testHtmlPlaceholderize(self):
+ tool = rc2grd.Rc2Grd()
+ original = "Hello <b>[USERNAME]</b>, how are you? I'm [AGE] years old!"
+ msg = tool.Placeholderize(original)
+ self.failUnless(msg.GetPresentableContent() ==
+ "Hello BEGIN_BOLDX_USERNAME_XEND_BOLD, how are you? I'm X_AGE_X years old!")
+ self.failUnless(msg.GetRealContent() == original)
+
+ def testMenuWithoutWhitespaceRegression(self):
+ # There was a problem in the original regular expression for parsing out
+ # menu sections, that would parse the following block of text as a single
+ # menu instead of two.
+ two_menus = '''
+// Hyper context menus
+IDR_HYPERMENU_FOLDER MENU
+BEGIN
+ POPUP "HyperFolder"
+ BEGIN
+ MENUITEM "Open Containing Folder", IDM_OPENFOLDER
+ END
+END
+
+IDR_HYPERMENU_FILE MENU
+BEGIN
+ POPUP "HyperFile"
+ BEGIN
+ MENUITEM "Open Folder", IDM_OPENFOLDER
+ END
+END
+
+'''
+ self.failUnless(len(rc2grd._MENU.findall(two_menus)) == 2)
+
+ def testRegressionScriptWithTranslateable(self):
+ tool = rc2grd.Rc2Grd()
+
+ # test rig
+ class DummyNode(base.Node):
+ def AddChild(self, item):
+ self.node = item
+ verbose = False
+ extra_verbose = False
+ tool.not_localizable_re = re.compile('')
+ tool.o = DummyNode()
+
+ rc_text = '''STRINGTABLE\nBEGIN\nID_BINGO "<SPAN id=hp style='BEHAVIOR: url(#default#homepage)'></SPAN><script>if (!hp.isHomePage('[$~HOMEPAGE~$]')) {document.write(""<a href=\\""[$~SETHOMEPAGEURL~$]\\"" >Set As Homepage</a> - "");}</script>"\nEND\n'''
+ tool.AddMessages(rc_text, tool.o)
+ self.failUnless(tool.o.node.GetCdata().find('Set As Homepage') != -1)
+
+ # TODO(joi) Improve the HTML parser to support translateables inside
+ # <script> blocks?
+ self.failUnless(tool.o.node.attrs['translateable'] == 'false')
+
+ def testRoleModel(self):
+ rc_text = ('STRINGTABLE\n'
+ 'BEGIN\n'
+ ' // This should not show up\n'
+ ' IDS_BINGO "Hello %s, how are you?"\n'
+ ' // The first description\n'
+ ' IDS_BONGO "Hello %s, my name is %s, and yours?"\n'
+ ' IDS_PROGRAMS_SHUTDOWN_TEXT "Google Desktop Search needs to close the following programs:\\n\\n$1\\nThe installation will not proceed if you choose to cancel."\n'
+ 'END\n')
+ tool = rc2grd.Rc2Grd()
+ tool.role_model = grd_reader.Parse(StringIO.StringIO(
+ '''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <message name="IDS_BINGO">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you?
+ </message>
+ <message name="IDS_BONGO" desc="The other description">
+ Hello <ph name="USERNAME">%s<ex>Jakob</ex></ph>, my name is <ph name="ADMINNAME">%s<ex>Joi</ex></ph>, and yours?
+ </message>
+ <message name="IDS_PROGRAMS_SHUTDOWN_TEXT" desc="LIST_OF_PROGRAMS is replaced by a bulleted list of program names.">
+ Google Desktop Search needs to close the following programs:
+
+<ph name="LIST_OF_PROGRAMS">$1<ex>Program 1, Program 2</ex></ph>
+The installation will not proceed if you choose to cancel.
+ </message>
+ </messages>
+ </release>
+ </grit>'''), dir='.')
+
+ # test rig
+ class DummyOpts(object):
+ verbose = False
+ extra_verbose = False
+ tool.o = DummyOpts()
+ result = tool.Process(rc_text, '.\resource.rc')
+ self.failUnless(
+ result.children[2].children[2].children[0].attrs['desc'] == '')
+ self.failUnless(
+ result.children[2].children[2].children[0].children[0].attrs['name'] == 'USERNAME')
+ self.failUnless(
+ result.children[2].children[2].children[1].attrs['desc'] == 'The other description')
+ self.failUnless(
+ result.children[2].children[2].children[1].attrs['meaning'] == '')
+ self.failUnless(
+ result.children[2].children[2].children[1].children[0].attrs['name'] == 'USERNAME')
+ self.failUnless(
+ result.children[2].children[2].children[1].children[1].attrs['name'] == 'ADMINNAME')
+ self.failUnless(
+ result.children[2].children[2].children[2].children[0].attrs['name'] == 'LIST_OF_PROGRAMS')
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/tool/resize.py b/chromium/tools/grit/grit/tool/resize.py
new file mode 100644
index 00000000000..8b9bdb947a5
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/resize.py
@@ -0,0 +1,289 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The 'grit resize' tool.
+'''
+
+import getopt
+import os
+
+from grit import grd_reader
+from grit import pseudo
+from grit import util
+from grit.format import rc
+from grit.format import rc_header
+from grit.node import include
+from grit.tool import interface
+
+
+# Template for the .vcproj file, with a couple of [[REPLACEABLE]] parts.
+PROJECT_TEMPLATE = '''\
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="[[DIALOG_NAME]]"
+ ProjectGUID="[[PROJECT_GUID]]"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ CharacterSet="2">
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ <File
+ RelativePath=".\[[DIALOG_NAME]].rc">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>'''
+
+
+# Template for the .rc file with a couple of [[REPLACEABLE]] parts.
+# TODO(joi) Improve this (and the resource.h template) to allow saving and then
+# reopening of the RC file in Visual Studio. Currently you can only open it
+# once and change it, then after you close it you won't be able to reopen it.
+RC_TEMPLATE = '''\
+// This file is automatically generated by GRIT and intended for editing
+// the layout of the dialogs contained in it. Do not edit anything but the
+// dialogs. Any changes made to translateable portions of the dialogs will
+// be ignored by GRIT.
+
+#include "resource.h"
+#include <winresrc.h>
+#ifdef IDC_STATIC
+#undef IDC_STATIC
+#endif
+#define IDC_STATIC (-1)
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+#pragma code_page([[CODEPAGE_NUM]])
+
+[[INCLUDES]]
+
+[[DIALOGS]]
+'''
+
+
+# Template for the resource.h file with a couple of [[REPLACEABLE]] parts.
+HEADER_TEMPLATE = '''\
+// This file is automatically generated by GRIT. Do not edit.
+
+#pragma once
+
+// Edit commands
+#define ID_EDIT_CLEAR 0xE120
+#define ID_EDIT_CLEAR_ALL 0xE121
+#define ID_EDIT_COPY 0xE122
+#define ID_EDIT_CUT 0xE123
+#define ID_EDIT_FIND 0xE124
+#define ID_EDIT_PASTE 0xE125
+#define ID_EDIT_PASTE_LINK 0xE126
+#define ID_EDIT_PASTE_SPECIAL 0xE127
+#define ID_EDIT_REPEAT 0xE128
+#define ID_EDIT_REPLACE 0xE129
+#define ID_EDIT_SELECT_ALL 0xE12A
+#define ID_EDIT_UNDO 0xE12B
+#define ID_EDIT_REDO 0xE12C
+
+
+[[DEFINES]]
+'''
+
+
+class ResizeDialog(interface.Tool):
+ '''Generates an RC file, header and Visual Studio project that you can use
+with Visual Studio's GUI resource editor to modify the layout of dialogs for
+the language of your choice. You then use the RC file, after you resize the
+dialog, for the language or languages of your choice, using the <skeleton> child
+of the <structure> node for the dialog. The translateable bits of the dialog
+will be ignored when you use the <skeleton> node (GRIT will instead use the
+translateable bits from the original dialog) but the layout changes you make
+will be used. Note that your layout changes must preserve the order of the
+translateable elements in the RC file.
+
+Usage: grit resize [-f BASEFOLDER] [-l LANG] [-e RCENCODING] DIALOGID*
+
+Arguments:
+ DIALOGID The 'name' attribute of a dialog to output for resizing. Zero
+ or more of these parameters can be used. If none are
+ specified, all dialogs from the input .grd file are output.
+
+Options:
+
+ -f BASEFOLDER The project will be created in a subfolder of BASEFOLDER.
+ The name of the subfolder will be the first DIALOGID you
+ specify. Defaults to '.'
+
+ -l LANG Specifies that the RC file should contain a dialog translated
+ into the language LANG. The default is a cp1252-representable
+ pseudotranslation, because Visual Studio's GUI RC editor only
+ supports single-byte encodings.
+
+ -c CODEPAGE Code page number to indicate to the RC compiler the encoding
+ of the RC file, default is something reasonable for the
+ language you selected (but this does not work for every single
+ language). See details on codepages below. NOTE that you do
+ not need to specify the codepage unless the tool complains
+ that it's not sure which codepage to use. See the following
+ page for codepage numbers supported by Windows:
+ http://www.microsoft.com/globaldev/reference/wincp.mspx
+
+ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
+ value VAL (defaults to 1) which will be used to control
+ conditional inclusion of resources.
+
+
+IMPORTANT NOTE: For now, the tool outputs a UTF-8 encoded file for any language
+that can not be represented in cp1252 (i.e. anything other than Western
+European languages). You will need to open this file in a text editor and
+save it using the codepage indicated in the #pragma code_page(XXXX) command
+near the top of the file, before you open it in Visual Studio.
+
+'''
+
+ # TODO(joi) It would be cool to have this tool note the Perforce revision
+ # of the original RC file somewhere, such that the <skeleton> node could warn
+ # if the original RC file gets updated without the skeleton file being updated.
+
+ # TODO(joi) Would be cool to have option to add the files to Perforce
+
+ def __init__(self):
+ self.lang = pseudo.PSEUDO_LANG
+ self.defines = {}
+ self.base_folder = '.'
+ self.codepage_number = 1252
+ self.codepage_number_specified_explicitly = False
+
+ def SetLanguage(self, lang):
+ '''Sets the language code to output things in.
+ '''
+ self.lang = lang
+ if not self.codepage_number_specified_explicitly:
+ self.codepage_number = util.LanguageToCodepage(lang)
+
+ def GetEncoding(self):
+ if self.codepage_number == 1200:
+ return 'utf_16'
+ if self.codepage_number == 65001:
+ return 'utf_8'
+ return 'cp%d' % self.codepage_number
+
+ def ShortDescription(self):
+ return 'Generate a file where you can resize a given dialog.'
+
+ def Run(self, opts, args):
+ self.SetOptions(opts)
+
+ own_opts, args = getopt.getopt(args, 'l:f:c:D:')
+ for key, val in own_opts:
+ if key == '-l':
+ self.SetLanguage(val)
+ if key == '-f':
+ self.base_folder = val
+ if key == '-c':
+ self.codepage_number = int(val)
+ self.codepage_number_specified_explicitly = True
+ if key == '-D':
+ name, val = util.ParseDefine(val)
+ self.defines[name] = val
+
+ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
+ res_tree.OnlyTheseTranslations([self.lang])
+ res_tree.RunGatherers()
+
+ # Dialog IDs are either explicitly listed, or we output all dialogs from the
+ # .grd file
+ dialog_ids = args
+ if not len(dialog_ids):
+ for node in res_tree:
+ if node.name == 'structure' and node.attrs['type'] == 'dialog':
+ dialog_ids.append(node.attrs['name'])
+
+ self.Process(res_tree, dialog_ids)
+
+ def Process(self, grd, dialog_ids):
+ '''Outputs an RC file and header file for the dialog 'dialog_id' stored in
+ resource tree 'grd', to self.base_folder, as discussed in this class's
+ documentation.
+
+ Arguments:
+ grd: grd = grd_reader.Parse(...); grd.RunGatherers()
+ dialog_ids: ['IDD_MYDIALOG', 'IDD_OTHERDIALOG']
+ '''
+ grd.SetOutputLanguage(self.lang)
+ grd.SetDefines(self.defines)
+
+ project_name = dialog_ids[0]
+
+ dir_path = os.path.join(self.base_folder, project_name)
+ if not os.path.isdir(dir_path):
+ os.mkdir(dir_path)
+
+ # If this fails then we're not on Windows (or you don't have the required
+ # win32all Python libraries installed), so what are you doing mucking
+ # about with RC files anyway? :)
+ import pythoncom
+
+ # Create the .vcproj file
+ project_text = PROJECT_TEMPLATE.replace(
+ '[[PROJECT_GUID]]', str(pythoncom.CreateGuid())
+ ).replace('[[DIALOG_NAME]]', project_name)
+ fname = os.path.join(dir_path, '%s.vcproj' % project_name)
+ self.WriteFile(fname, project_text)
+ print "Wrote %s" % fname
+
+ # Create the .rc file
+ # Output all <include> nodes since the dialogs might depend on them (e.g.
+ # for icons and bitmaps).
+ include_items = []
+ for node in grd.ActiveDescendants():
+ if isinstance(node, include.IncludeNode):
+ include_items.append(rc.FormatInclude(node, self.lang, '.'))
+ rc_text = RC_TEMPLATE.replace('[[CODEPAGE_NUM]]',
+ str(self.codepage_number))
+ rc_text = rc_text.replace('[[INCLUDES]]', ''.join(include_items))
+
+ # Then output the dialogs we have been asked to output.
+ dialogs = []
+ for dialog_id in dialog_ids:
+ node = grd.GetNodeById(dialog_id)
+ assert node.name == 'structure' and node.attrs['type'] == 'dialog'
+ # TODO(joi) Add exception handling for better error reporting
+ dialogs.append(rc.FormatStructure(node, self.lang, '.'))
+ rc_text = rc_text.replace('[[DIALOGS]]', ''.join(dialogs))
+
+ fname = os.path.join(dir_path, '%s.rc' % project_name)
+ self.WriteFile(fname, rc_text, self.GetEncoding())
+ print "Wrote %s" % fname
+
+ # Create the resource.h file
+ header_defines = ''.join(rc_header.FormatDefines(grd))
+ header_text = HEADER_TEMPLATE.replace('[[DEFINES]]', header_defines)
+ fname = os.path.join(dir_path, 'resource.h')
+ self.WriteFile(fname, header_text)
+ print "Wrote %s" % fname
+
+ def WriteFile(self, filename, contents, encoding='cp1252'):
+ with open(filename, 'wb') as f:
+ writer = util.WrapOutputStream(f, encoding)
+ writer.write(contents)
diff --git a/chromium/tools/grit/grit/tool/test.py b/chromium/tools/grit/grit/tool/test.py
new file mode 100644
index 00000000000..246b3dede54
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/test.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from grit.tool import interface
+
+class TestTool(interface.Tool):
+ '''This tool does nothing except print out the global options and
+tool-specific arguments that it receives. It is intended only for testing,
+hence the name :)
+'''
+
+ def ShortDescription(self):
+ return 'A do-nothing tool for testing command-line parsing.'
+
+ def Run(self, global_options, my_arguments):
+ print 'NOTE This tool is only for testing the parsing of global options and'
+ print 'tool-specific arguments that it receives. You may have intended to'
+ print 'run "grit unit" which is the unit-test suite for GRIT.'
+ print 'Options: %s' % repr(global_options)
+ print 'Arguments: %s' % repr(my_arguments)
+ return 0
+
diff --git a/chromium/tools/grit/grit/tool/toolbar_postprocess.py b/chromium/tools/grit/grit/tool/toolbar_postprocess.py
new file mode 100644
index 00000000000..3d561088bac
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/toolbar_postprocess.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+''' Toolbar postprocessing class. Modifies the previously processed GRD tree
+by creating separate message groups for each of the IDS_COMMAND macros.
+Also adds some identifiers nodes to declare specific ids to be included
+in the generated grh file.
+'''
+
+import postprocess_interface
+from grit import lazy_re
+import grit.node.empty
+from grit.node import misc
+
+class ToolbarPostProcessor(postprocess_interface.PostProcessor):
+ ''' Defines message groups within the grd file for each of the
+ IDS_COMMAND stuff.
+ '''
+
+ _IDS_COMMAND = lazy_re.compile(r'IDS_COMMAND_')
+ _GRAB_PARAMETERS = lazy_re.compile(
+ r'(IDS_COMMAND_[a-zA-Z0-9]+)_([a-zA-z0-9]+)')
+
+ def Process(self, rctext, rcpath, grdnode):
+ ''' Processes the data in rctext and grdnode.
+ Args:
+ rctext: string containing the contents of the RC file being processed.
+ rcpath: the path used to access the file.
+ grdnode: the root node of the grd xml data generated by
+ the rc2grd tool.
+
+ Return:
+ The root node of the processed GRD tree.
+ '''
+
+ release = grdnode.children[2]
+ messages = release.children[2]
+
+ identifiers = grit.node.empty.IdentifiersNode()
+ identifiers.StartParsing('identifiers', release)
+ identifiers.EndParsing()
+ release.AddChild(identifiers)
+
+
+ #
+ # Turn the IDS_COMMAND messages into separate message groups
+ # with ids that are offsetted to the message group's first id
+ #
+ previous_name_attr = ''
+ previous_prefix = ''
+ previous_node = ''
+ new_messages_node = self.ConstructNewMessages(release)
+ for node in messages.children[:]:
+ name_attr = node.attrs['name']
+ if self._IDS_COMMAND.search(name_attr):
+ mo = self._GRAB_PARAMETERS.search(name_attr)
+ mp = self._GRAB_PARAMETERS.search(previous_name_attr)
+ if mo and mp:
+ prefix = mo.group(1)
+ previous_prefix = mp.group(1)
+ new_message_id = mp.group(2)
+ if prefix == previous_prefix:
+ messages.RemoveChild(previous_name_attr)
+ previous_node.attrs['offset'] = 'PCI_' + new_message_id
+ del previous_node.attrs['name']
+ new_messages_node.AddChild(previous_node)
+ else:
+ messages.RemoveChild(previous_name_attr)
+ previous_node.attrs['offset'] = 'PCI_' + new_message_id
+ del previous_node.attrs['name']
+ new_messages_node.AddChild(previous_node)
+ new_messages_node.attrs['first_id'] = previous_prefix
+ new_messages_node = self.ConstructNewMessages(release)
+ else:
+ if self._IDS_COMMAND.search(previous_name_attr):
+ messages.RemoveChild(previous_name_attr)
+ previous_prefix = mp.group(1)
+ new_message_id = mp.group(2)
+ previous_node.attrs['offset'] = 'PCI_' + new_message_id
+ del previous_node.attrs['name']
+ new_messages_node.AddChild(previous_node)
+ new_messages_node.attrs['first_id'] = previous_prefix
+ new_messages_node = self.ConstructNewMessages(release)
+ else:
+ if self._IDS_COMMAND.search(previous_name_attr):
+ messages.RemoveChild(previous_name_attr)
+ mp = self._GRAB_PARAMETERS.search(previous_name_attr)
+ previous_prefix = mp.group(1)
+ new_message_id = mp.group(2)
+ previous_node.attrs['offset'] = 'PCI_' + new_message_id
+ del previous_node.attrs['name']
+ new_messages_node.AddChild(previous_node)
+ new_messages_node.attrs['first_id'] = previous_prefix
+ new_messages_node = self.ConstructNewMessages(release)
+ previous_name_attr = name_attr
+ previous_node = node
+
+
+ self.AddIdentifiers(rctext, identifiers)
+ return grdnode
+
+ def ConstructNewMessages(self, parent):
+ new_node = grit.node.empty.MessagesNode()
+ new_node.StartParsing('messages', parent)
+ new_node.EndParsing()
+ parent.AddChild(new_node)
+ return new_node
+
+ def AddIdentifiers(self, rctext, node):
+ node.AddChild(misc.IdentifierNode.Construct(node, 'IDS_COMMAND_gcFirst', '12000', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node,
+ 'IDS_COMMAND_PCI_SPACE', '16', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_BUTTON', '0', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_MENU', '1', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP', '2', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_OPTIONS_TEXT', '3', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_DISABLED', '4', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_MENU', '5', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_MENU_DISABLED', '6', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_OPTIONS', '7', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node, 'PCI_TIP_OPTIONS_DISABLED', '8', ''))
+ node.AddChild(misc.IdentifierNode.Construct(node,
+ 'PCI_TIP_DISABLED_BY_POLICY', '9', ''))
+
diff --git a/chromium/tools/grit/grit/tool/toolbar_preprocess.py b/chromium/tools/grit/grit/tool/toolbar_preprocess.py
new file mode 100644
index 00000000000..ff26f886406
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/toolbar_preprocess.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+''' Toolbar preprocessing code. Turns all IDS_COMMAND macros in the RC file
+into simpler constructs that can be understood by GRIT. Also deals with
+expansion of $lf; placeholders into the correct linefeed character.
+'''
+
+import preprocess_interface
+
+from grit import lazy_re
+
+class ToolbarPreProcessor(preprocess_interface.PreProcessor):
+ ''' Toolbar PreProcessing class.
+ '''
+
+ _IDS_COMMAND_MACRO = lazy_re.compile(
+ r'(.*IDS_COMMAND)\s*\(([a-zA-Z0-9_]*)\s*,\s*([a-zA-Z0-9_]*)\)(.*)')
+ _LINE_FEED_PH = lazy_re.compile(r'\$lf;')
+ _PH_COMMENT = lazy_re.compile(r'PHRWR')
+ _COMMENT = lazy_re.compile(r'^(\s*)//.*')
+
+
+ def Process(self, rctext, rcpath):
+ ''' Processes the data in rctext.
+ Args:
+ rctext: string containing the contents of the RC file being processed
+ rcpath: the path used to access the file.
+
+ Return:
+ The processed text.
+ '''
+
+ ret = ''
+ rclines = rctext.splitlines()
+ for line in rclines:
+
+ if self._LINE_FEED_PH.search(line):
+ # Replace "$lf;" placeholder comments by an empty line.
+ # this will not be put into the processed result
+ if self._PH_COMMENT.search(line):
+ mm = self._COMMENT.search(line)
+ if mm:
+ line = '%s//' % mm.group(1)
+
+ else:
+ # Replace $lf by the right linefeed character
+ line = self._LINE_FEED_PH.sub(r'\\n', line)
+
+ # Deal with IDS_COMMAND_MACRO stuff
+ mo = self._IDS_COMMAND_MACRO.search(line)
+ if mo:
+ line = '%s_%s_%s%s' % (mo.group(1), mo.group(2), mo.group(3), mo.group(4))
+
+ ret += (line + '\n')
+
+ return ret
+
+
diff --git a/chromium/tools/grit/grit/tool/transl2tc.py b/chromium/tools/grit/grit/tool/transl2tc.py
new file mode 100644
index 00000000000..f3f06a93591
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/transl2tc.py
@@ -0,0 +1,252 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''The 'grit transl2tc' tool.
+'''
+
+
+from grit import grd_reader
+from grit import util
+from grit.tool import interface
+from grit.tool import rc2grd
+
+from grit.extern import tclib
+
+
+class TranslationToTc(interface.Tool):
+ '''A tool for importing existing translations in RC format into the
+Translation Console.
+
+Usage:
+
+grit -i GRD transl2tc [-l LIMITS] [RCOPTS] SOURCE_RC TRANSLATED_RC OUT_FILE
+
+The tool needs a "source" RC file, i.e. in English, and an RC file that is a
+translation of precisely the source RC file (not of an older or newer version).
+
+The tool also requires you to provide a .grd file (input file) e.g. using the
+-i global option or the GRIT_INPUT environment variable. The tool uses
+information from your .grd file to correct placeholder names in the
+translations and ensure that only translatable items and translations still
+being used are output.
+
+This tool will accept all the same RCOPTS as the 'grit rc2grd' tool. To get
+a list of these options, run 'grit help rc2grd'.
+
+Additionally, you can use the -l option (which must be the first option to the
+tool) to specify a file containing a list of message IDs to which output should
+be limited. This is only useful if you are limiting the output to your XMB
+files using the 'grit xmb' tool's -l option. See 'grit help xmb' for how to
+generate a file containing a list of the message IDs in an XMB file.
+
+The tool will scan through both of the RC files as well as any HTML files they
+refer to, and match together the source messages and translated messages. It
+will output a file (OUTPUT_FILE) you can import directly into the TC using the
+Bulk Translation Upload tool.
+'''
+
+ def ShortDescription(self):
+ return 'Import existing translations in RC format into the TC'
+
+ def Setup(self, globopt, args):
+ '''Sets the instance up for use.
+ '''
+ self.SetOptions(globopt)
+ self.rc2grd = rc2grd.Rc2Grd()
+ self.rc2grd.SetOptions(globopt)
+ self.limits = None
+ if len(args) and args[0] == '-l':
+ self.limits = util.ReadFile(args[1], util.RAW_TEXT).split('\n')
+ args = args[2:]
+ return self.rc2grd.ParseOptions(args)
+
+ def Run(self, globopt, args):
+ args = self.Setup(globopt, args)
+
+ if len(args) != 3:
+ self.Out('This tool takes exactly three arguments:\n'
+ ' 1. The path to the original RC file\n'
+ ' 2. The path to the translated RC file\n'
+ ' 3. The output file path.\n')
+ return 2
+
+ grd = grd_reader.Parse(self.o.input, debug=self.o.extra_verbose)
+ grd.RunGatherers()
+
+ source_rc = util.ReadFile(args[0], self.rc2grd.input_encoding)
+ transl_rc = util.ReadFile(args[1], self.rc2grd.input_encoding)
+ translations = self.ExtractTranslations(grd,
+ source_rc, args[0],
+ transl_rc, args[1])
+
+ with util.WrapOutputStream(open(args[2], 'w')) as output_file:
+ self.WriteTranslations(output_file, translations.items())
+
+ self.Out('Wrote output file %s' % args[2])
+
+ def ExtractTranslations(self, current_grd, source_rc, source_path,
+ transl_rc, transl_path):
+ '''Extracts translations from the translated RC file, matching them with
+ translations in the source RC file to calculate their ID, and correcting
+ placeholders, limiting output to translateables, etc. using the supplied
+ .grd file which is the current .grd file for your project.
+
+ If this object's 'limits' attribute is not None but a list, the output of
+ this function will be further limited to include only messages that have
+ message IDs in the 'limits' list.
+
+ Args:
+ current_grd: grit.node.base.Node child, that has had RunGatherers() run
+ on it
+ source_rc: Complete text of source RC file
+ source_path: Path to the source RC file
+ transl_rc: Complete text of translated RC file
+ transl_path: Path to the translated RC file
+
+ Return:
+ { id1 : text1, '12345678' : 'Hello USERNAME, howzit?' }
+ '''
+ source_grd = self.rc2grd.Process(source_rc, source_path)
+ self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % source_path)
+ source_grd.SetOutputLanguage(current_grd.output_language)
+ source_grd.SetDefines(current_grd.defines)
+ source_grd.RunGatherers(debug=self.o.extra_verbose)
+ transl_grd = self.rc2grd.Process(transl_rc, transl_path)
+ transl_grd.SetOutputLanguage(current_grd.output_language)
+ transl_grd.SetDefines(current_grd.defines)
+ self.VerboseOut('Read %s into GRIT format, running gatherers.\n' % transl_path)
+ transl_grd.RunGatherers(debug=self.o.extra_verbose)
+ self.VerboseOut('Done running gatherers for %s.\n' % transl_path)
+
+ # Proceed to create a map from ID to translation, getting the ID from the
+ # source GRD and the translation from the translated GRD.
+ id2transl = {}
+ for source_node in source_grd:
+ source_cliques = source_node.GetCliques()
+ if not len(source_cliques):
+ continue
+
+ assert 'name' in source_node.attrs, 'All nodes with cliques should have an ID'
+ node_id = source_node.attrs['name']
+ self.ExtraVerboseOut('Processing node %s\n' % node_id)
+ transl_node = transl_grd.GetNodeById(node_id)
+
+ if transl_node:
+ transl_cliques = transl_node.GetCliques()
+ if not len(transl_cliques) == len(source_cliques):
+ self.Out(
+ 'Warning: Translation for %s has wrong # of cliques, skipping.\n' %
+ node_id)
+ continue
+ else:
+ self.Out('Warning: No translation for %s, skipping.\n' % node_id)
+ continue
+
+ if source_node.name == 'message':
+ # Fixup placeholders as well as possible based on information from
+ # the current .grd file if they are 'TODO_XXXX' placeholders. We need
+ # to fixup placeholders in the translated message so that it looks right
+ # and we also need to fixup placeholders in the source message so that
+ # its calculated ID will match the current message.
+ current_node = current_grd.GetNodeById(node_id)
+ if current_node:
+ assert len(source_cliques) == len(current_node.GetCliques()) == 1
+
+ source_msg = source_cliques[0].GetMessage()
+ current_msg = current_node.GetCliques()[0].GetMessage()
+
+ # Only do this for messages whose source version has not changed.
+ if (source_msg.GetRealContent() != current_msg.GetRealContent()):
+ self.VerboseOut('Info: Message %s has changed; skipping\n' % node_id)
+ else:
+ transl_msg = transl_cliques[0].GetMessage()
+ transl_content = transl_msg.GetContent()
+ current_content = current_msg.GetContent()
+ source_content = source_msg.GetContent()
+
+ ok_to_fixup = True
+ if (len(transl_content) != len(current_content)):
+ # message structure of translation is different, don't try fixup
+ ok_to_fixup = False
+ if ok_to_fixup:
+ for ix in range(len(transl_content)):
+ if isinstance(transl_content[ix], tclib.Placeholder):
+ if not isinstance(current_content[ix], tclib.Placeholder):
+ ok_to_fixup = False # structure has changed
+ break
+ if (transl_content[ix].GetOriginal() !=
+ current_content[ix].GetOriginal()):
+ ok_to_fixup = False # placeholders have likely been reordered
+ break
+ else: # translated part is not a placeholder but a string
+ if isinstance(current_content[ix], tclib.Placeholder):
+ ok_to_fixup = False # placeholders have likely been reordered
+ break
+
+ if not ok_to_fixup:
+ self.VerboseOut(
+ 'Info: Structure of message %s has changed; skipping.\n' % node_id)
+ else:
+ def Fixup(content, ix):
+ if (isinstance(content[ix], tclib.Placeholder) and
+ content[ix].GetPresentation().startswith('TODO_')):
+ assert isinstance(current_content[ix], tclib.Placeholder)
+ # Get the placeholder ID and example from the current message
+ content[ix] = current_content[ix]
+ for ix in range(len(transl_content)):
+ Fixup(transl_content, ix)
+ Fixup(source_content, ix)
+
+ # Only put each translation once into the map. Warn if translations
+ # for the same message are different.
+ for ix in range(len(transl_cliques)):
+ source_msg = source_cliques[ix].GetMessage()
+ source_msg.GenerateId() # needed to refresh ID based on new placeholders
+ message_id = source_msg.GetId()
+ translated_content = transl_cliques[ix].GetMessage().GetPresentableContent()
+
+ if message_id in id2transl:
+ existing_translation = id2transl[message_id]
+ if existing_translation != translated_content:
+ original_text = source_cliques[ix].GetMessage().GetPresentableContent()
+ self.Out('Warning: Two different translations for "%s":\n'
+ ' Translation 1: "%s"\n'
+ ' Translation 2: "%s"\n' %
+ (original_text, existing_translation, translated_content))
+ else:
+ id2transl[message_id] = translated_content
+
+ # Remove translations for messages that do not occur in the current .grd
+ # or have been marked as not translateable, or do not occur in the 'limits'
+ # list (if it has been set).
+ current_message_ids = current_grd.UberClique().AllMessageIds()
+ for message_id in id2transl.keys():
+ if (message_id not in current_message_ids or
+ not current_grd.UberClique().BestClique(message_id).IsTranslateable() or
+ (self.limits and message_id not in self.limits)):
+ del id2transl[message_id]
+
+ return id2transl
+
+ @staticmethod
+ def WriteTranslations(output_file, translations):
+ '''Writes the provided list of translations to the provided output file
+ in the format used by the TC's Bulk Translation Upload tool. The file
+ must be UTF-8 encoded.
+
+ Args:
+ output_file: util.WrapOutputStream(open('bingo.out', 'w'))
+ translations: [ [id1, text1], ['12345678', 'Hello USERNAME, howzit?'] ]
+
+ Return:
+ None
+ '''
+ for id, text in translations:
+ text = text.replace('<', '&lt;').replace('>', '&gt;')
+ output_file.write(id)
+ output_file.write(' ')
+ output_file.write(text)
+ output_file.write('\n')
+
diff --git a/chromium/tools/grit/grit/tool/transl2tc_unittest.py b/chromium/tools/grit/grit/tool/transl2tc_unittest.py
new file mode 100644
index 00000000000..db64d10e6fc
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/transl2tc_unittest.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for the 'grit transl2tc' tool.'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import StringIO
+import unittest
+
+from grit.tool import transl2tc
+from grit import grd_reader
+from grit import util
+
+
+def MakeOptions():
+ from grit import grit_runner
+ return grit_runner.Options()
+
+
+class TranslationToTcUnittest(unittest.TestCase):
+
+ def testOutput(self):
+ buf = StringIO.StringIO()
+ tool = transl2tc.TranslationToTc()
+ translations = [
+ ['1', 'Hello USERNAME, how are you?'],
+ ['12', 'Howdie doodie!'],
+ ['123', 'Hello\n\nthere\n\nhow are you?'],
+ ['1234', 'Hello is > goodbye but < howdie pardner'],
+ ]
+ tool.WriteTranslations(buf, translations)
+ output = buf.getvalue()
+ self.failUnless(output.strip() == '''
+1 Hello USERNAME, how are you?
+12 Howdie doodie!
+123 Hello
+
+there
+
+how are you?
+1234 Hello is &gt; goodbye but &lt; howdie pardner
+'''.strip())
+
+ def testExtractTranslations(self):
+ path = util.PathFromRoot('grit/testdata')
+ current_grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <message name="IDS_SIMPLE">
+ One
+ </message>
+ <message name="IDS_PLACEHOLDER">
+ <ph name="NUMBIRDS">%s<ex>3</ex></ph> birds
+ </message>
+ <message name="IDS_PLACEHOLDERS">
+ <ph name="ITEM">%d<ex>1</ex></ph> of <ph name="COUNT">%d<ex>3</ex></ph>
+ </message>
+ <message name="IDS_REORDERED_PLACEHOLDERS">
+ <ph name="ITEM">$1<ex>1</ex></ph> of <ph name="COUNT">$2<ex>3</ex></ph>
+ </message>
+ <message name="IDS_CHANGED">
+ This is the new version
+ </message>
+ <message name="IDS_TWIN_1">Hello</message>
+ <message name="IDS_TWIN_2">Hello</message>
+ <message name="IDS_NOT_TRANSLATEABLE" translateable="false">:</message>
+ <message name="IDS_LONGER_TRANSLATED">
+ Removed document <ph name="FILENAME">$1<ex>c:\temp</ex></ph>
+ </message>
+ <message name="IDS_DIFFERENT_TWIN_1">Howdie</message>
+ <message name="IDS_DIFFERENT_TWIN_2">Howdie</message>
+ </messages>
+ <structures>
+ <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="klonk.rc" />
+ <structure type="menu" name="IDC_KLONKMENU" encoding="utf-16" file="klonk.rc" />
+ </structures>
+ </release>
+ </grit>'''), path)
+ current_grd.SetOutputLanguage('en')
+ current_grd.RunGatherers()
+
+ source_rc_path = util.PathFromRoot('grit/testdata/source.rc')
+ source_rc = util.ReadFile(source_rc_path, util.RAW_TEXT)
+ transl_rc_path = util.PathFromRoot('grit/testdata/transl.rc')
+ transl_rc = util.ReadFile(transl_rc_path, util.RAW_TEXT)
+
+ tool = transl2tc.TranslationToTc()
+ output_buf = StringIO.StringIO()
+ globopts = MakeOptions()
+ globopts.verbose = True
+ globopts.output_stream = output_buf
+ tool.Setup(globopts, [])
+ translations = tool.ExtractTranslations(current_grd,
+ source_rc, source_rc_path,
+ transl_rc, transl_rc_path)
+
+ values = translations.values()
+ output = output_buf.getvalue()
+
+ self.failUnless('Ein' in values)
+ self.failUnless('NUMBIRDS Vogeln' in values)
+ self.failUnless('ITEM von COUNT' in values)
+ self.failUnless(values.count('Hallo') == 1)
+ self.failIf('Dass war die alte Version' in values)
+ self.failIf(':' in values)
+ self.failIf('Dokument FILENAME ist entfernt worden' in values)
+ self.failIf('Nicht verwendet' in values)
+ self.failUnless(('Howdie' in values or 'Hallo sagt man' in values) and not
+ ('Howdie' in values and 'Hallo sagt man' in values))
+
+ self.failUnless('XX01XX&SkraXX02XX&HaettaXX03XXThetta er "Klonk" sem eg fylaXX04XXgonkurinnXX05XXKlonk && er [good]XX06XX&HjalpXX07XX&Um...XX08XX' in values)
+
+ self.failUnless('I lagi' in values)
+
+ self.failUnless(output.count('Structure of message IDS_REORDERED_PLACEHOLDERS has changed'))
+ self.failUnless(output.count('Message IDS_CHANGED has changed'))
+ self.failUnless(output.count('Structure of message IDS_LONGER_TRANSLATED has changed'))
+ self.failUnless(output.count('Two different translations for "Howdie"'))
+ self.failUnless(output.count('IDD_DIFFERENT_LENGTH_IN_TRANSL has wrong # of cliques'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/tool/unit.py b/chromium/tools/grit/grit/tool/unit.py
new file mode 100644
index 00000000000..f4832629250
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/unit.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''GRIT tool that runs the unit test suite for GRIT.'''
+
+
+import unittest
+
+import grit.test_suite_all
+from grit.tool import interface
+
+
+class UnitTestTool(interface.Tool):
+ '''By using this tool (e.g. 'grit unit') you run all the unit tests for GRIT.
+This happens in the environment that is set up by the basic GRIT runner, i.e.
+whether to run disconnected has been specified, etc.'''
+
+ def ShortDescription(self):
+ return 'Use this tool to run all the unit tests for GRIT.'
+
+ def Run(self, opts, args):
+ return unittest.TextTestRunner(verbosity=2).run(
+ grit.test_suite_all.TestSuiteAll())
+
diff --git a/chromium/tools/grit/grit/tool/xmb.py b/chromium/tools/grit/grit/tool/xmb.py
new file mode 100644
index 00000000000..aaefeecad4b
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/xmb.py
@@ -0,0 +1,291 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The 'grit xmb' tool.
+"""
+
+import getopt
+import os
+
+from xml.sax import saxutils
+
+from grit import grd_reader
+from grit import lazy_re
+from grit import tclib
+from grit import util
+from grit.tool import interface
+
+
+# Used to collapse presentable content to determine if
+# xml:space="preserve" is needed.
+_WHITESPACES_REGEX = lazy_re.compile(ur'\s\s*')
+
+
+# See XmlEscape below.
+_XML_QUOTE_ESCAPES = {
+ u"'": u'&apos;',
+ u'"': u'&quot;',
+}
+_XML_BAD_CHAR_REGEX = lazy_re.compile(u'[^\u0009\u000A\u000D'
+ u'\u0020-\uD7FF\uE000-\uFFFD]')
+
+
+def _XmlEscape(s):
+ """Returns text escaped for XML in a way compatible with Google's
+ internal Translation Console tool. May be used for attributes as
+ well as for contents.
+ """
+ if not type(s) == unicode:
+ s = unicode(s)
+ result = saxutils.escape(s, _XML_QUOTE_ESCAPES)
+ return _XML_BAD_CHAR_REGEX.sub(u'', result).encode('utf-8')
+
+
+def _WriteAttribute(file, name, value):
+ """Writes an XML attribute to the specified file.
+
+ Args:
+ file: file to write to
+ name: name of the attribute
+ value: (unescaped) value of the attribute
+ """
+ if value:
+ file.write(' %s="%s"' % (name, _XmlEscape(value)))
+
+
+def _WriteMessage(file, message):
+ presentable_content = message.GetPresentableContent()
+ assert (type(presentable_content) == unicode or
+ (len(message.parts) == 1 and
+ type(message.parts[0] == tclib.Placeholder)))
+ preserve_space = presentable_content != _WHITESPACES_REGEX.sub(
+ u' ', presentable_content.strip())
+
+ file.write('<msg')
+ _WriteAttribute(file, 'desc', message.GetDescription())
+ _WriteAttribute(file, 'id', message.GetId())
+ _WriteAttribute(file, 'meaning', message.GetMeaning())
+ if preserve_space:
+ _WriteAttribute(file, 'xml:space', 'preserve')
+ file.write('>')
+ if not preserve_space:
+ file.write('\n ')
+
+ parts = message.GetContent()
+ for part in parts:
+ if isinstance(part, tclib.Placeholder):
+ file.write('<ph')
+ _WriteAttribute(file, 'name', part.GetPresentation())
+ file.write('><ex>')
+ file.write(_XmlEscape(part.GetExample()))
+ file.write('</ex>')
+ file.write(_XmlEscape(part.GetOriginal()))
+ file.write('</ph>')
+ else:
+ file.write(_XmlEscape(part))
+ if not preserve_space:
+ file.write('\n')
+ file.write('</msg>\n')
+
+
+def WriteXmbFile(file, messages):
+ """Writes the given grit.tclib.Message items to the specified open
+ file-like object in the XMB format.
+ """
+ file.write("""<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE messagebundle [
+<!ELEMENT messagebundle (msg)*>
+<!ATTLIST messagebundle class CDATA #IMPLIED>
+
+<!ELEMENT msg (#PCDATA|ph|source)*>
+<!ATTLIST msg id CDATA #IMPLIED>
+<!ATTLIST msg seq CDATA #IMPLIED>
+<!ATTLIST msg name CDATA #IMPLIED>
+<!ATTLIST msg desc CDATA #IMPLIED>
+<!ATTLIST msg meaning CDATA #IMPLIED>
+<!ATTLIST msg obsolete (obsolete) #IMPLIED>
+<!ATTLIST msg xml:space (default|preserve) "default">
+<!ATTLIST msg is_hidden CDATA #IMPLIED>
+
+<!ELEMENT source (#PCDATA)>
+
+<!ELEMENT ph (#PCDATA|ex)*>
+<!ATTLIST ph name CDATA #REQUIRED>
+
+<!ELEMENT ex (#PCDATA)>
+]>
+<messagebundle>
+""")
+ for message in messages:
+ _WriteMessage(file, message)
+ file.write('</messagebundle>')
+
+
+class OutputXmb(interface.Tool):
+ """Outputs all translateable messages in the .grd input file to an
+.xmb file, which is the format used to give source messages to
+Google's internal Translation Console tool. The format could easily
+be used for other systems.
+
+Usage: grit xmb [-i|-h] [-l LIMITFILE] OUTPUTPATH
+
+OUTPUTPATH is the path you want to output the .xmb file to.
+
+The -l option can be used to output only some of the resources to the .xmb file.
+LIMITFILE is the path to a file that is used to limit the items output to the
+xmb file. If the filename extension is .grd, the file must be a .grd file
+and the tool only output the contents of nodes from the input file that also
+exist in the limit file (as compared on the 'name' attribute). Otherwise it must
+contain a list of the IDs that output should be limited to, one ID per line, and
+the tool will only output nodes with 'name' attributes that match one of the
+IDs.
+
+The -i option causes 'grit xmb' to output an "IDs only" file instead of an XMB
+file. The "IDs only" file contains the message ID of each message that would
+normally be output to the XMB file, one message ID per line. It is designed for
+use with the 'grit transl2tc' tool's -l option.
+
+Other options:
+
+ -D NAME[=VAL] Specify a C-preprocessor-like define NAME with optional
+ value VAL (defaults to 1) which will be used to control
+ conditional inclusion of resources.
+
+ -E NAME=VALUE Set environment variable NAME to VALUE (within grit).
+
+"""
+ # The different output formats supported by this tool
+ FORMAT_XMB = 0
+ FORMAT_IDS_ONLY = 1
+
+ def __init__(self, defines=None):
+ super(OutputXmb, self).__init__()
+ self.format = self.FORMAT_XMB
+ self.defines = defines or {}
+
+ def ShortDescription(self):
+ return 'Exports all translateable messages into an XMB file.'
+
+ def Run(self, opts, args):
+ self.SetOptions(opts)
+
+ limit_file = None
+ limit_is_grd = False
+ limit_file_dir = None
+ own_opts, args = getopt.getopt(args, 'l:D:ih')
+ for key, val in own_opts:
+ if key == '-l':
+ limit_file = open(val, 'r')
+ limit_file_dir = util.dirname(val)
+ if not len(limit_file_dir):
+ limit_file_dir = '.'
+ limit_is_grd = os.path.splitext(val)[1] == '.grd'
+ elif key == '-i':
+ self.format = self.FORMAT_IDS_ONLY
+ elif key == '-D':
+ name, val = util.ParseDefine(val)
+ self.defines[name] = val
+ elif key == '-E':
+ (env_name, env_value) = val.split('=', 1)
+ os.environ[env_name] = env_value
+ if not len(args) == 1:
+ print ('grit xmb takes exactly one argument, the path to the XMB file '
+ 'to output.')
+ return 2
+
+ xmb_path = args[0]
+ res_tree = grd_reader.Parse(opts.input, debug=opts.extra_verbose)
+ res_tree.SetOutputLanguage('en')
+ res_tree.SetDefines(self.defines)
+ res_tree.OnlyTheseTranslations([])
+ res_tree.RunGatherers()
+
+ with open(xmb_path, 'wb') as output_file:
+ self.Process(
+ res_tree, output_file, limit_file, limit_is_grd, limit_file_dir)
+ if limit_file:
+ limit_file.close()
+ print "Wrote %s" % xmb_path
+
+ def Process(self, res_tree, output_file, limit_file=None, limit_is_grd=False,
+ dir=None):
+ """Writes a document with the contents of res_tree into output_file,
+ limiting output to the IDs specified in limit_file, which is a GRD file if
+ limit_is_grd is true, otherwise a file with one ID per line.
+
+ The format of the output document depends on this object's format attribute.
+ It can be FORMAT_XMB or FORMAT_IDS_ONLY.
+
+ The FORMAT_IDS_ONLY format causes this function to write just a list
+ of the IDs of all messages that would have been added to the XMB file, one
+ ID per line.
+
+ The FORMAT_XMB format causes this function to output the (default) XMB
+ format.
+
+ Args:
+ res_tree: base.Node()
+ output_file: file open for writing
+ limit_file: None or file open for reading
+ limit_is_grd: True | False
+ dir: Directory of the limit file
+ """
+ if limit_file:
+ if limit_is_grd:
+ limit_list = []
+ limit_tree = grd_reader.Parse(limit_file,
+ dir=dir,
+ debug=self.o.extra_verbose)
+ for node in limit_tree:
+ if 'name' in node.attrs:
+ limit_list.append(node.attrs['name'])
+ else:
+ # Not a GRD file, so it's just a file with one ID per line
+ limit_list = [item.strip() for item in limit_file.read().split('\n')]
+
+ ids_already_done = {}
+ messages = []
+ for node in res_tree:
+ if (limit_file and
+ not ('name' in node.attrs and node.attrs['name'] in limit_list)):
+ continue
+ if not node.IsTranslateable():
+ continue
+
+ for clique in node.GetCliques():
+ if not clique.IsTranslateable():
+ continue
+ if not clique.GetMessage().GetRealContent():
+ continue
+
+ # Some explanation is in order here. Note that we can have
+ # many messages with the same ID.
+ #
+ # The way we work around this is to maintain a list of cliques
+ # per message ID (in the UberClique) and select the "best" one
+ # (the first one that has a description, or an arbitrary one
+ # if there is no description) for inclusion in the XMB file.
+ # The translations are all going to be the same for messages
+ # with the same ID, although the way we replace placeholders
+ # might be slightly different.
+ id = clique.GetMessage().GetId()
+ if id in ids_already_done:
+ continue
+ ids_already_done[id] = 1
+
+ message = node.UberClique().BestClique(id).GetMessage()
+ messages += [message]
+
+ # Ensure a stable order of messages, to help regression testing.
+ messages.sort(key=lambda x:x.GetId())
+
+ if self.format == self.FORMAT_IDS_ONLY:
+ # We just print the list of IDs to the output file.
+ for msg in messages:
+ output_file.write(msg.GetId())
+ output_file.write('\n')
+ else:
+ assert self.format == self.FORMAT_XMB
+ WriteXmbFile(output_file, messages)
diff --git a/chromium/tools/grit/grit/tool/xmb_unittest.py b/chromium/tools/grit/grit/tool/xmb_unittest.py
new file mode 100644
index 00000000000..10f81d7cf3e
--- /dev/null
+++ b/chromium/tools/grit/grit/tool/xmb_unittest.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for 'grit xmb' tool.'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+
+import unittest
+import StringIO
+
+from grit import grd_reader
+from grit import util
+from grit.tool import xmb
+
+
+class XmbUnittest(unittest.TestCase):
+ def setUp(self):
+ self.res_tree = grd_reader.Parse(
+ StringIO.StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <includes>
+ <include type="gif" name="ID_LOGO" file="images/logo.gif" />
+ </includes>
+ <messages>
+ <message name="GOOD" desc="sub" sub_variable="true">
+ excellent
+ </message>
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, are you doing [GOOD] today?
+ </message>
+ <message name="IDS_BONGOBINGO">
+ Yibbee
+ </message>
+ </messages>
+ <structures>
+ <structure type="dialog" name="IDD_SPACYBOX" encoding="utf-16" file="grit/testdata/klonk.rc" />
+ </structures>
+ </release>
+ </grit>'''), '.')
+ self.xmb_file = StringIO.StringIO()
+
+ def testNormalOutput(self):
+ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
+ output = self.xmb_file.getvalue()
+ self.failUnless(output.count('Joi') and output.count('Yibbee'))
+
+ def testLimitList(self):
+ limit_file = StringIO.StringIO(
+ 'IDS_BONGOBINGO\nIDS_DOES_NOT_EXIST\nIDS_ALSO_DOES_NOT_EXIST')
+ xmb.OutputXmb().Process(self.res_tree, self.xmb_file, limit_file, False)
+ output = self.xmb_file.getvalue()
+ self.failUnless(output.count('Yibbee'))
+ self.failUnless(not output.count('Joi'))
+
+ def testLimitGrd(self):
+ limit_file = StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
+ <release seq="3">
+ <messages>
+ <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
+ Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
+ </message>
+ </messages>
+ </release>
+ </grit>''')
+ tool = xmb.OutputXmb()
+ class DummyOpts(object):
+ extra_verbose = False
+ tool.o = DummyOpts()
+ tool.Process(self.res_tree, self.xmb_file, limit_file, True, dir='.')
+ output = self.xmb_file.getvalue()
+ self.failUnless(output.count('Joi'))
+ self.failUnless(not output.count('Yibbee'))
+
+ def testSubstitution(self):
+ self.res_tree.SetOutputLanguage('en')
+ os.chdir(util.PathFromRoot('.')) # so it can find klonk.rc
+ self.res_tree.RunGatherers()
+ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
+ output = self.xmb_file.getvalue()
+ self.failUnless(output.count(
+ '<ph name="GOOD_1"><ex>excellent</ex>[GOOD]</ph>'))
+
+ def testLeadingTrailingWhitespace(self):
+ # Regression test for problems outputting messages with leading or
+ # trailing whitespace (these come in via structures only, as
+ # message nodes already strip and store whitespace).
+ self.res_tree.SetOutputLanguage('en')
+ os.chdir(util.PathFromRoot('.')) # so it can find klonk.rc
+ self.res_tree.RunGatherers()
+ xmb.OutputXmb().Process(self.res_tree, self.xmb_file)
+ output = self.xmb_file.getvalue()
+ self.failUnless(output.count('OK ? </msg>'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit/util.py b/chromium/tools/grit/grit/util.py
new file mode 100644
index 00000000000..b958bc22db2
--- /dev/null
+++ b/chromium/tools/grit/grit/util.py
@@ -0,0 +1,661 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Utilities used by GRIT.
+'''
+
+import codecs
+import htmlentitydefs
+import os
+import re
+import shutil
+import sys
+import tempfile
+import time
+import types
+from xml.sax import saxutils
+
+from grit import lazy_re
+
+_root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+
+
+# Unique constants for use by ReadFile().
+BINARY, RAW_TEXT = range(2)
+
+
+# Unique constants representing data pack encodings.
+_, UTF8, UTF16 = range(3)
+
+
+def Encode(message, encoding):
+ '''Returns a byte stream that represents |message| in the given |encoding|.'''
+ # |message| is a python unicode string, so convert to a byte stream that
+ # has the correct encoding requested for the datapacks. We skip the first
+ # 2 bytes of text resources because it is the BOM.
+ if encoding == UTF8:
+ return message.encode('utf8')
+ if encoding == UTF16:
+ return message.encode('utf16')[2:]
+ # Default is BINARY
+ return message
+
+
+# Matches all different types of linebreaks.
+LINEBREAKS = re.compile('\r\n|\n|\r')
+
+def MakeRelativePath(base_path, path_to_make_relative):
+ """Returns a relative path such from the base_path to
+ the path_to_make_relative.
+
+ In other words, os.join(base_path,
+ MakeRelativePath(base_path, path_to_make_relative))
+ is the same location as path_to_make_relative.
+
+ Args:
+ base_path: the root path
+ path_to_make_relative: an absolute path that is on the same drive
+ as base_path
+ """
+
+ def _GetPathAfterPrefix(prefix_path, path_with_prefix):
+ """Gets the subpath within in prefix_path for the path_with_prefix
+ with no beginning or trailing path separators.
+
+ Args:
+ prefix_path: the base path
+ path_with_prefix: a path that starts with prefix_path
+ """
+ assert path_with_prefix.startswith(prefix_path)
+ path_without_prefix = path_with_prefix[len(prefix_path):]
+ normalized_path = os.path.normpath(path_without_prefix.strip(os.path.sep))
+ if normalized_path == '.':
+ normalized_path = ''
+ return normalized_path
+
+ def _GetCommonBaseDirectory(*args):
+ """Returns the common prefix directory for the given paths
+
+ Args:
+ The list of paths (at least one of which should be a directory)
+ """
+ prefix = os.path.commonprefix(args)
+ # prefix is a character-by-character prefix (i.e. it does not end
+ # on a directory bound, so this code fixes that)
+
+ # if the prefix ends with the separator, then it is prefect.
+ if len(prefix) > 0 and prefix[-1] == os.path.sep:
+ return prefix
+
+ # We need to loop through all paths or else we can get
+ # tripped up by "c:\a" and "c:\abc". The common prefix
+ # is "c:\a" which is a directory and looks good with
+ # respect to the first directory but it is clear that
+ # isn't a common directory when the second path is
+ # examined.
+ for path in args:
+ assert len(path) >= len(prefix)
+ # If the prefix the same length as the path,
+ # then the prefix must be a directory (since one
+ # of the arguements should be a directory).
+ if path == prefix:
+ continue
+ # if the character after the prefix in the path
+ # is the separator, then the prefix appears to be a
+ # valid a directory as well for the given path
+ if path[len(prefix)] == os.path.sep:
+ continue
+ # Otherwise, the prefix is not a directory, so it needs
+ # to be shortened to be one
+ index_sep = prefix.rfind(os.path.sep)
+ # The use "index_sep + 1" because it includes the final sep
+ # and it handles the case when the index_sep is -1 as well
+ prefix = prefix[:index_sep + 1]
+ # At this point we backed up to a directory bound which is
+ # common to all paths, so we can quit going through all of
+ # the paths.
+ break
+ return prefix
+
+ prefix = _GetCommonBaseDirectory(base_path, path_to_make_relative)
+ # If the paths had no commonality at all, then return the absolute path
+ # because it is the best that can be done. If the path had to be relative
+ # then eventually this absolute path will be discovered (when a build breaks)
+ # and an appropriate fix can be made, but having this allows for the best
+ # backward compatibility with the absolute path behavior in the past.
+ if len(prefix) <= 0:
+ return path_to_make_relative
+ # Build a path from the base dir to the common prefix
+ remaining_base_path = _GetPathAfterPrefix(prefix, base_path)
+
+ # The follow handles two case: "" and "foo\\bar"
+ path_pieces = remaining_base_path.split(os.path.sep)
+ base_depth_from_prefix = len([d for d in path_pieces if len(d)])
+ base_to_prefix = (".." + os.path.sep) * base_depth_from_prefix
+
+ # Put add in the path from the prefix to the path_to_make_relative
+ remaining_other_path = _GetPathAfterPrefix(prefix, path_to_make_relative)
+ return base_to_prefix + remaining_other_path
+
+
+KNOWN_SYSTEM_IDENTIFIERS = set()
+
+SYSTEM_IDENTIFIERS = None
+
+def SetupSystemIdentifiers(ids):
+ '''Adds ids to a regexp of known system identifiers.
+
+ Can be called many times, ids will be accumulated.
+
+ Args:
+ ids: an iterable of strings
+ '''
+ KNOWN_SYSTEM_IDENTIFIERS.update(ids)
+ global SYSTEM_IDENTIFIERS
+ SYSTEM_IDENTIFIERS = lazy_re.compile(
+ ' | '.join([r'\b%s\b' % i for i in KNOWN_SYSTEM_IDENTIFIERS]),
+ re.VERBOSE)
+
+
+# Matches all of the resource IDs predefined by Windows.
+SetupSystemIdentifiers((
+ 'IDOK', 'IDCANCEL', 'IDC_STATIC', 'IDYES', 'IDNO',
+ 'ID_FILE_NEW', 'ID_FILE_OPEN', 'ID_FILE_CLOSE', 'ID_FILE_SAVE',
+ 'ID_FILE_SAVE_AS', 'ID_FILE_PAGE_SETUP', 'ID_FILE_PRINT_SETUP',
+ 'ID_FILE_PRINT', 'ID_FILE_PRINT_DIRECT', 'ID_FILE_PRINT_PREVIEW',
+ 'ID_FILE_UPDATE', 'ID_FILE_SAVE_COPY_AS', 'ID_FILE_SEND_MAIL',
+ 'ID_FILE_MRU_FIRST', 'ID_FILE_MRU_LAST',
+ 'ID_EDIT_CLEAR', 'ID_EDIT_CLEAR_ALL', 'ID_EDIT_COPY',
+ 'ID_EDIT_CUT', 'ID_EDIT_FIND', 'ID_EDIT_PASTE', 'ID_EDIT_PASTE_LINK',
+ 'ID_EDIT_PASTE_SPECIAL', 'ID_EDIT_REPEAT', 'ID_EDIT_REPLACE',
+ 'ID_EDIT_SELECT_ALL', 'ID_EDIT_UNDO', 'ID_EDIT_REDO',
+ 'VS_VERSION_INFO', 'IDRETRY',
+ 'ID_APP_ABOUT', 'ID_APP_EXIT',
+ 'ID_NEXT_PANE', 'ID_PREV_PANE',
+ 'ID_WINDOW_NEW', 'ID_WINDOW_ARRANGE', 'ID_WINDOW_CASCADE',
+ 'ID_WINDOW_TILE_HORZ', 'ID_WINDOW_TILE_VERT', 'ID_WINDOW_SPLIT',
+ 'ATL_IDS_SCSIZE', 'ATL_IDS_SCMOVE', 'ATL_IDS_SCMINIMIZE',
+ 'ATL_IDS_SCMAXIMIZE', 'ATL_IDS_SCNEXTWINDOW', 'ATL_IDS_SCPREVWINDOW',
+ 'ATL_IDS_SCCLOSE', 'ATL_IDS_SCRESTORE', 'ATL_IDS_SCTASKLIST',
+ 'ATL_IDS_MDICHILD', 'ATL_IDS_IDLEMESSAGE', 'ATL_IDS_MRU_FILE' ))
+
+
+# Matches character entities, whether specified by name, decimal or hex.
+_HTML_ENTITY = lazy_re.compile(
+ '&(#(?P<decimal>[0-9]+)|#x(?P<hex>[a-fA-F0-9]+)|(?P<named>[a-z0-9]+));',
+ re.IGNORECASE)
+
+# Matches characters that should be HTML-escaped. This is <, > and &, but only
+# if the & is not the start of an HTML character entity.
+_HTML_CHARS_TO_ESCAPE = lazy_re.compile(
+ '"|<|>|&(?!#[0-9]+|#x[0-9a-z]+|[a-z]+;)',
+ re.IGNORECASE | re.MULTILINE)
+
+
+def ReadFile(filename, encoding):
+ '''Reads and returns the entire contents of the given file.
+
+ Args:
+ filename: The path to the file.
+ encoding: A Python codec name or one of two special values: BINARY to read
+ the file in binary mode, or RAW_TEXT to read it with newline
+ conversion but without decoding to Unicode.
+ '''
+ mode = 'rb' if encoding == BINARY else 'rU'
+ with open(filename, mode) as f:
+ data = f.read()
+ if encoding not in (BINARY, RAW_TEXT):
+ data = data.decode(encoding)
+ return data
+
+
+def WrapOutputStream(stream, encoding = 'utf-8'):
+ '''Returns a stream that wraps the provided stream, making it write
+ characters using the specified encoding.'''
+ return codecs.getwriter(encoding)(stream)
+
+
+def ChangeStdoutEncoding(encoding = 'utf-8'):
+ '''Changes STDOUT to print characters using the specified encoding.'''
+ sys.stdout = WrapOutputStream(sys.stdout, encoding)
+
+
+def EscapeHtml(text, escape_quotes = False):
+ '''Returns 'text' with <, > and & (and optionally ") escaped to named HTML
+ entities. Any existing named entity or HTML entity defined by decimal or
+ hex code will be left untouched. This is appropriate for escaping text for
+ inclusion in HTML, but not for XML.
+ '''
+ def Replace(match):
+ if match.group() == '&': return '&amp;'
+ elif match.group() == '<': return '&lt;'
+ elif match.group() == '>': return '&gt;'
+ elif match.group() == '"':
+ if escape_quotes: return '&quot;'
+ else: return match.group()
+ else: assert False
+ out = _HTML_CHARS_TO_ESCAPE.sub(Replace, text)
+ return out
+
+
+def UnescapeHtml(text, replace_nbsp=True):
+ '''Returns 'text' with all HTML character entities (both named character
+ entities and those specified by decimal or hexadecimal Unicode ordinal)
+ replaced by their Unicode characters (or latin1 characters if possible).
+
+ The only exception is that &nbsp; will not be escaped if 'replace_nbsp' is
+ False.
+ '''
+ def Replace(match):
+ groups = match.groupdict()
+ if groups['hex']:
+ return unichr(int(groups['hex'], 16))
+ elif groups['decimal']:
+ return unichr(int(groups['decimal'], 10))
+ else:
+ name = groups['named']
+ if name == 'nbsp' and not replace_nbsp:
+ return match.group() # Don't replace &nbsp;
+ assert name != None
+ if name in htmlentitydefs.name2codepoint.keys():
+ return unichr(htmlentitydefs.name2codepoint[name])
+ else:
+ return match.group() # Unknown HTML character entity - don't replace
+
+ out = _HTML_ENTITY.sub(Replace, text)
+ return out
+
+
+def EncodeCdata(cdata):
+ '''Returns the provided cdata in either escaped format or <![CDATA[xxx]]>
+ format, depending on which is more appropriate for easy editing. The data
+ is escaped for inclusion in an XML element's body.
+
+ Args:
+ cdata: 'If x < y and y < z then x < z'
+
+ Return:
+ '<![CDATA[If x < y and y < z then x < z]]>'
+ '''
+ if cdata.count('<') > 1 or cdata.count('>') > 1 and cdata.count(']]>') == 0:
+ return '<![CDATA[%s]]>' % cdata
+ else:
+ return saxutils.escape(cdata)
+
+
+def FixupNamedParam(function, param_name, param_value):
+ '''Returns a closure that is identical to 'function' but ensures that the
+ named parameter 'param_name' is always set to 'param_value' unless explicitly
+ set by the caller.
+
+ Args:
+ function: callable
+ param_name: 'bingo'
+ param_value: 'bongo' (any type)
+
+ Return:
+ callable
+ '''
+ def FixupClosure(*args, **kw):
+ if not param_name in kw:
+ kw[param_name] = param_value
+ return function(*args, **kw)
+ return FixupClosure
+
+
+def PathFromRoot(path):
+ '''Takes a path relative to the root directory for GRIT (the one that grit.py
+ resides in) and returns a path that is either absolute or relative to the
+ current working directory (i.e .a path you can use to open the file).
+
+ Args:
+ path: 'rel_dir\file.ext'
+
+ Return:
+ 'c:\src\tools\rel_dir\file.ext
+ '''
+ return os.path.normpath(os.path.join(_root_dir, path))
+
+
+def ParseGrdForUnittest(body, base_dir=None):
+ '''Parse a skeleton .grd file and return it, for use in unit tests.
+
+ Args:
+ body: XML that goes inside the <release> element.
+ base_dir: The base_dir attribute of the <grit> tag.
+ '''
+ import StringIO
+ from grit import grd_reader
+ if isinstance(body, unicode):
+ body = body.encode('utf-8')
+ if base_dir is None:
+ base_dir = PathFromRoot('.')
+ body = '''<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="2" current_release="3" source_lang_id="en" base_dir="%s">
+ <outputs>
+ </outputs>
+ <release seq="3">
+ %s
+ </release>
+</grit>''' % (base_dir, body)
+ return grd_reader.Parse(StringIO.StringIO(body), dir=".")
+
+
+def StripBlankLinesAndComments(text):
+ '''Strips blank lines and comments from C source code, for unit tests.'''
+ return '\n'.join(line for line in text.splitlines()
+ if line and not line.startswith('//'))
+
+
+def dirname(filename):
+ '''Version of os.path.dirname() that never returns empty paths (returns
+ '.' if the result of os.path.dirname() is empty).
+ '''
+ ret = os.path.dirname(filename)
+ if ret == '':
+ ret = '.'
+ return ret
+
+
+def normpath(path):
+ '''Version of os.path.normpath that also changes backward slashes to
+ forward slashes when not running on Windows.
+ '''
+ # This is safe to always do because the Windows version of os.path.normpath
+ # will replace forward slashes with backward slashes.
+ path = path.replace('\\', '/')
+ return os.path.normpath(path)
+
+
+_LANGUAGE_SPLIT_RE = lazy_re.compile('-|_|/')
+
+
+def CanonicalLanguage(code):
+ '''Canonicalizes two-part language codes by using a dash and making the
+ second part upper case. Returns one-part language codes unchanged.
+
+ Args:
+ code: 'zh_cn'
+
+ Return:
+ code: 'zh-CN'
+ '''
+ parts = _LANGUAGE_SPLIT_RE.split(code)
+ code = [ parts[0] ]
+ for part in parts[1:]:
+ code.append(part.upper())
+ return '-'.join(code)
+
+
+_LANG_TO_CODEPAGE = {
+ 'en' : 1252,
+ 'fr' : 1252,
+ 'it' : 1252,
+ 'de' : 1252,
+ 'es' : 1252,
+ 'nl' : 1252,
+ 'sv' : 1252,
+ 'no' : 1252,
+ 'da' : 1252,
+ 'fi' : 1252,
+ 'pt-BR' : 1252,
+ 'ru' : 1251,
+ 'ja' : 932,
+ 'zh-TW' : 950,
+ 'zh-CN' : 936,
+ 'ko' : 949,
+}
+
+
+def LanguageToCodepage(lang):
+ '''Returns the codepage _number_ that can be used to represent 'lang', which
+ may be either in formats such as 'en', 'pt_br', 'pt-BR', etc.
+
+ The codepage returned will be one of the 'cpXXXX' codepage numbers.
+
+ Args:
+ lang: 'de'
+
+ Return:
+ 1252
+ '''
+ lang = CanonicalLanguage(lang)
+ if lang in _LANG_TO_CODEPAGE:
+ return _LANG_TO_CODEPAGE[lang]
+ else:
+ print "Not sure which codepage to use for %s, assuming cp1252" % lang
+ return 1252
+
+def NewClassInstance(class_name, class_type):
+ '''Returns an instance of the class specified in classname
+
+ Args:
+ class_name: the fully qualified, dot separated package + classname,
+ i.e. "my.package.name.MyClass". Short class names are not supported.
+ class_type: the class or superclass this object must implement
+
+ Return:
+ An instance of the class, or None if none was found
+ '''
+ lastdot = class_name.rfind('.')
+ module_name = ''
+ if lastdot >= 0:
+ module_name = class_name[0:lastdot]
+ if module_name:
+ class_name = class_name[lastdot+1:]
+ module = __import__(module_name, globals(), locals(), [''])
+ if hasattr(module, class_name):
+ class_ = getattr(module, class_name)
+ class_instance = class_()
+ if isinstance(class_instance, class_type):
+ return class_instance
+ return None
+
+
+def FixLineEnd(text, line_end):
+ # First normalize
+ text = text.replace('\r\n', '\n')
+ text = text.replace('\r', '\n')
+ # Then fix
+ text = text.replace('\n', line_end)
+ return text
+
+
+def BoolToString(bool):
+ if bool:
+ return 'true'
+ else:
+ return 'false'
+
+
+verbose = False
+extra_verbose = False
+
+def IsVerbose():
+ return verbose
+
+def IsExtraVerbose():
+ return extra_verbose
+
+def ParseDefine(define):
+ '''Parses a define argument and returns the name and value.
+
+ The format is either "NAME=VAL" or "NAME", using True as the default value.
+ Values of "1" and "0" are transformed to True and False respectively.
+
+ Args:
+ define: a string of the form "NAME=VAL" or "NAME".
+
+ Returns:
+ A (name, value) pair. name is a string, value a string or boolean.
+ '''
+ parts = [part.strip() for part in define.split('=', 1)]
+ assert len(parts) >= 1
+ name = parts[0]
+ val = True
+ if len(parts) > 1:
+ val = parts[1]
+ if val == "1": val = True
+ elif val == "0": val = False
+ return (name, val)
+
+
+class Substituter(object):
+ '''Finds and substitutes variable names in text strings.
+
+ Given a dictionary of variable names and values, prepares to
+ search for patterns of the form [VAR_NAME] in a text.
+ The value will be substituted back efficiently.
+ Also applies to tclib.Message objects.
+ '''
+
+ def __init__(self):
+ '''Create an empty substituter.'''
+ self.substitutions_ = {}
+ self.dirty_ = True
+
+ def AddSubstitutions(self, subs):
+ '''Add new values to the substitutor.
+
+ Args:
+ subs: A dictionary of new substitutions.
+ '''
+ self.substitutions_.update(subs)
+ self.dirty_ = True
+
+ def AddMessages(self, messages, lang):
+ '''Adds substitutions extracted from node.Message objects.
+
+ Args:
+ messages: a list of node.Message objects.
+ lang: The translation language to use in substitutions.
+ '''
+ subs = [(str(msg.attrs['name']), msg.Translate(lang)) for msg in messages]
+ self.AddSubstitutions(dict(subs))
+ self.dirty_ = True
+
+ def GetExp(self):
+ '''Obtain a regular expression that will find substitution keys in text.
+
+ Create and cache if the substituter has been updated. Use the cached value
+ otherwise. Keys will be enclosed in [square brackets] in text.
+
+ Returns:
+ A regular expression object.
+ '''
+ if self.dirty_:
+ components = ['\[%s\]' % (k,) for k in self.substitutions_.keys()]
+ self.exp = re.compile("(%s)" % ('|'.join(components),))
+ self.dirty_ = False
+ return self.exp
+
+ def Substitute(self, text):
+ '''Substitute the variable values in the given text.
+
+ Text of the form [message_name] will be replaced by the message's value.
+
+ Args:
+ text: A string of text.
+
+ Returns:
+ A string of text with substitutions done.
+ '''
+ return ''.join([self._SubFragment(f) for f in self.GetExp().split(text)])
+
+ def _SubFragment(self, fragment):
+ '''Utility function for Substitute.
+
+ Performs a simple substitution if the fragment is exactly of the form
+ [message_name].
+
+ Args:
+ fragment: A simple string.
+
+ Returns:
+ A string with the substitution done.
+ '''
+ if len(fragment) > 2 and fragment[0] == '[' and fragment[-1] == ']':
+ sub = self.substitutions_.get(fragment[1:-1], None)
+ if sub is not None:
+ return sub
+ return fragment
+
+ def SubstituteMessage(self, msg):
+ '''Apply substitutions to a tclib.Message object.
+
+ Text of the form [message_name] will be replaced by a new placeholder,
+ whose presentation will take the form the message_name_{UsageCount}, and
+ whose example will be the message's value. Existing placeholders are
+ not affected.
+
+ Args:
+ msg: A tclib.Message object.
+
+ Returns:
+ A tclib.Message object, with substitutions done.
+ '''
+ from grit import tclib # avoid circular import
+ counts = {}
+ text = msg.GetPresentableContent()
+ placeholders = []
+ newtext = ''
+ for f in self.GetExp().split(text):
+ sub = self._SubFragment(f)
+ if f != sub:
+ f = str(f)
+ count = counts.get(f, 0) + 1
+ counts[f] = count
+ name = "%s_%d" % (f[1:-1], count)
+ placeholders.append(tclib.Placeholder(name, f, sub))
+ newtext += name
+ else:
+ newtext += f
+ if placeholders:
+ return tclib.Message(newtext, msg.GetPlaceholders() + placeholders,
+ msg.GetDescription(), msg.GetMeaning())
+ else:
+ return msg
+
+
+class TempDir(object):
+ '''Creates files with the specified contents in a temporary directory,
+ for unit testing.
+ '''
+ def __init__(self, file_data):
+ self._tmp_dir_name = tempfile.mkdtemp()
+ assert not os.listdir(self.GetPath())
+ for name, contents in file_data.items():
+ file_path = self.GetPath(name)
+ dir_path = os.path.split(file_path)[0]
+ if not os.path.exists(dir_path):
+ os.makedirs(dir_path)
+ with open(file_path, 'w') as f:
+ f.write(file_data[name])
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *exc_info):
+ self.CleanUp()
+
+ def CleanUp(self):
+ shutil.rmtree(self.GetPath())
+
+ def GetPath(self, name=''):
+ name = os.path.join(self._tmp_dir_name, name)
+ assert name.startswith(self._tmp_dir_name)
+ return name
+
+ def AsCurrentDir(self):
+ return self._AsCurrentDirClass(self.GetPath())
+
+ class _AsCurrentDirClass(object):
+ def __init__(self, path):
+ self.path = path
+ def __enter__(self):
+ self.oldpath = os.getcwd()
+ os.chdir(self.path)
+ def __exit__(self, *exc_info):
+ os.chdir(self.oldpath)
diff --git a/chromium/tools/grit/grit/util_unittest.py b/chromium/tools/grit/grit/util_unittest.py
new file mode 100644
index 00000000000..03f8cfef993
--- /dev/null
+++ b/chromium/tools/grit/grit/util_unittest.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit test that checks some of util functions.
+'''
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import unittest
+
+from grit import util
+
+
+class UtilUnittest(unittest.TestCase):
+ ''' Tests functions from util
+ '''
+
+ def testNewClassInstance(self):
+ # Test short class name with no fully qualified package name
+ # Should fail, it is not supported by the function now (as documented)
+ cls = util.NewClassInstance('grit.util.TestClassToLoad',
+ TestBaseClassToLoad)
+ self.failUnless(cls == None)
+
+ # Test non existent class name
+ cls = util.NewClassInstance('grit.util_unittest.NotExistingClass',
+ TestBaseClassToLoad)
+ self.failUnless(cls == None)
+
+ # Test valid class name and valid base class
+ cls = util.NewClassInstance('grit.util_unittest.TestClassToLoad',
+ TestBaseClassToLoad)
+ self.failUnless(isinstance(cls, TestBaseClassToLoad))
+
+ # Test valid class name with wrong hierarchy
+ cls = util.NewClassInstance('grit.util_unittest.TestClassNoBase',
+ TestBaseClassToLoad)
+ self.failUnless(cls == None)
+
+ def testCanonicalLanguage(self):
+ self.failUnless(util.CanonicalLanguage('en') == 'en')
+ self.failUnless(util.CanonicalLanguage('pt_br') == 'pt-BR')
+ self.failUnless(util.CanonicalLanguage('pt-br') == 'pt-BR')
+ self.failUnless(util.CanonicalLanguage('pt-BR') == 'pt-BR')
+ self.failUnless(util.CanonicalLanguage('pt/br') == 'pt-BR')
+ self.failUnless(util.CanonicalLanguage('pt/BR') == 'pt-BR')
+ self.failUnless(util.CanonicalLanguage('no_no_bokmal') == 'no-NO-BOKMAL')
+
+ def testUnescapeHtml(self):
+ self.failUnless(util.UnescapeHtml('&#1010;') == unichr(1010))
+ self.failUnless(util.UnescapeHtml('&#xABcd;') == unichr(43981))
+
+ def testRelativePath(self):
+ """ Verify that MakeRelativePath works in some tricky cases."""
+
+ def TestRelativePathCombinations(base_path, other_path, expected_result):
+ """ Verify that the relative path function works for
+ the given paths regardless of whether or not they end with
+ a trailing slash."""
+ for path1 in [base_path, base_path + os.path.sep]:
+ for path2 in [other_path, other_path + os.path.sep]:
+ result = util.MakeRelativePath(path1, path2)
+ self.failUnless(result == expected_result)
+
+ # set-up variables
+ root_dir = 'c:%sa' % os.path.sep
+ result1 = '..%sabc' % os.path.sep
+ path1 = root_dir + 'bc'
+ result2 = 'bc'
+ path2 = '%s%s%s' % (root_dir, os.path.sep, result2)
+ # run the tests
+ TestRelativePathCombinations(root_dir, path1, result1)
+ TestRelativePathCombinations(root_dir, path2, result2)
+
+ def testReadFile(self):
+ def Test(data, encoding, expected_result):
+ with open('testfile', 'wb') as f:
+ f.write(data)
+ if util.ReadFile('testfile', encoding) != expected_result:
+ print (util.ReadFile('testfile', encoding), expected_result)
+ self.failUnless(util.ReadFile('testfile', encoding) == expected_result)
+
+ test_std_newline = '\xEF\xBB\xBFabc\ndef' # EF BB BF is UTF-8 BOM
+ newlines = ['\n', '\r\n', '\r']
+
+ with util.TempDir({}) as tmp_dir:
+ with tmp_dir.AsCurrentDir():
+ for newline in newlines:
+ test = test_std_newline.replace('\n', newline)
+ Test(test, util.BINARY, test)
+ # RAW_TEXT uses universal newline mode
+ Test(test, util.RAW_TEXT, test_std_newline)
+ # utf-8 doesn't strip BOM
+ Test(test, 'utf-8', test_std_newline.decode('utf-8'))
+ # utf-8-sig strips BOM
+ Test(test, 'utf-8-sig', test_std_newline.decode('utf-8')[1:])
+ # test another encoding
+ Test(test, 'cp1252', test_std_newline.decode('cp1252'))
+ self.assertRaises(UnicodeDecodeError, Test, '\x80', 'utf-8', None)
+
+
+class TestBaseClassToLoad(object):
+ pass
+
+class TestClassToLoad(TestBaseClassToLoad):
+ pass
+
+class TestClassNoBase(object):
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/chromium/tools/grit/grit/xtb_reader.py b/chromium/tools/grit/grit/xtb_reader.py
new file mode 100644
index 00000000000..b92da39e80c
--- /dev/null
+++ b/chromium/tools/grit/grit/xtb_reader.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Fast and efficient parser for XTB files.
+'''
+
+
+import sys
+import xml.sax
+import xml.sax.handler
+
+import grit.node.base
+
+
+class XtbContentHandler(xml.sax.handler.ContentHandler):
+ '''A content handler that calls a given callback function for each
+ translation in the XTB file.
+ '''
+
+ def __init__(self, callback, defs=None, debug=False, target_platform=None):
+ self.callback = callback
+ self.debug = debug
+ # 0 if we are not currently parsing a translation, otherwise the message
+ # ID of that translation.
+ self.current_id = 0
+ # Empty if we are not currently parsing a translation, otherwise the
+ # parts we have for that translation - a list of tuples
+ # (is_placeholder, text)
+ self.current_structure = []
+ # Set to the language ID when we see the <translationbundle> node.
+ self.language = ''
+ # Keep track of the if block we're inside. We can't nest ifs.
+ self.if_expr = None
+ # Root defines to be used with if expr.
+ if defs:
+ self.defines = defs
+ else:
+ self.defines = {}
+ # Target platform for build.
+ if target_platform:
+ self.target_platform = target_platform
+ else:
+ self.target_platform = sys.platform
+
+ def startElement(self, name, attrs):
+ if name == 'translation':
+ assert self.current_id == 0 and len(self.current_structure) == 0, (
+ "Didn't expect a <translation> element here.")
+ self.current_id = attrs.getValue('id')
+ elif name == 'ph':
+ assert self.current_id != 0, "Didn't expect a <ph> element here."
+ self.current_structure.append((True, attrs.getValue('name')))
+ elif name == 'translationbundle':
+ self.language = attrs.getValue('lang')
+ elif name in ('if', 'then', 'else'):
+ assert self.if_expr is None, "Can't nest <if> or use <else> in xtb files"
+ self.if_expr = attrs.getValue('expr')
+
+ def endElement(self, name):
+ if name == 'translation':
+ assert self.current_id != 0
+
+ defs = self.defines
+ def pp_ifdef(define):
+ return define in defs
+ def pp_if(define):
+ return define in defs and defs[define]
+
+ # If we're in an if block, only call the callback (add the translation)
+ # if the expression is True.
+ should_run_callback = True
+ if self.if_expr:
+ should_run_callback = grit.node.base.Node.EvaluateExpression(
+ self.if_expr, self.defines, self.target_platform)
+ if should_run_callback:
+ self.callback(self.current_id, self.current_structure)
+
+ self.current_id = 0
+ self.current_structure = []
+ elif name == 'if':
+ assert self.if_expr is not None
+ self.if_expr = None
+
+ def characters(self, content):
+ if self.current_id != 0:
+ # We are inside a <translation> node so just add the characters to our
+ # structure.
+ #
+ # This naive way of handling characters is OK because in the XTB format,
+ # <ph> nodes are always empty (always <ph name="XXX"/>) and whitespace
+ # inside the <translation> node should be preserved.
+ self.current_structure.append((False, content))
+
+
+class XtbErrorHandler(xml.sax.handler.ErrorHandler):
+ def error(self, exception):
+ pass
+
+ def fatalError(self, exception):
+ raise exception
+
+ def warning(self, exception):
+ pass
+
+
+def Parse(xtb_file, callback_function, defs=None, debug=False,
+ target_platform=None):
+ '''Parse xtb_file, making a call to callback_function for every translation
+ in the XTB file.
+
+ The callback function must have the signature as described below. The 'parts'
+ parameter is a list of tuples (is_placeholder, text). The 'text' part is
+ either the raw text (if is_placeholder is False) or the name of the placeholder
+ (if is_placeholder is True).
+
+ Args:
+ xtb_file: open('fr.xtb')
+ callback_function: def Callback(msg_id, parts): pass
+ defs: None, or a dictionary of preprocessor definitions.
+ debug: Default False. Set True for verbose debug output.
+ target_platform: None, or a sys.platform-like identifier of the build
+ target platform.
+
+ Return:
+ The language of the XTB, e.g. 'fr'
+ '''
+ # Start by advancing the file pointer past the DOCTYPE thing, as the TC
+ # uses a path to the DTD that only works in Unix.
+ # TODO(joi) Remove this ugly hack by getting the TC gang to change the
+ # XTB files somehow?
+ front_of_file = xtb_file.read(1024)
+ xtb_file.seek(front_of_file.find('<translationbundle'))
+
+ handler = XtbContentHandler(callback=callback_function, defs=defs,
+ debug=debug, target_platform=target_platform)
+ xml.sax.parse(xtb_file, handler)
+ assert handler.language != ''
+ return handler.language
+
diff --git a/chromium/tools/grit/grit/xtb_reader_unittest.py b/chromium/tools/grit/grit/xtb_reader_unittest.py
new file mode 100644
index 00000000000..bab019c1f8d
--- /dev/null
+++ b/chromium/tools/grit/grit/xtb_reader_unittest.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Unit tests for grit.xtb_reader'''
+
+
+import os
+import sys
+if __name__ == '__main__':
+ sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+import StringIO
+import unittest
+
+from grit import util
+from grit import xtb_reader
+from grit.node import empty
+
+
+class XtbReaderUnittest(unittest.TestCase):
+ def testParsing(self):
+ xtb_file = StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE translationbundle>
+ <translationbundle lang="fr">
+ <translation id="5282608565720904145">Bingo.</translation>
+ <translation id="2955977306445326147">Bongo longo.</translation>
+ <translation id="238824332917605038">Hullo</translation>
+ <translation id="6629135689895381486"><ph name="PROBLEM_REPORT"/> peut <ph name="START_LINK"/>utilisation excessive de majuscules<ph name="END_LINK"/>.</translation>
+ <translation id="7729135689895381486">Hello
+this is another line
+and another
+
+and another after a blank line.</translation>
+ </translationbundle>''')
+
+ messages = []
+ def Callback(id, structure):
+ messages.append((id, structure))
+ xtb_reader.Parse(xtb_file, Callback)
+ self.failUnless(len(messages[0][1]) == 1)
+ self.failUnless(messages[3][1][0]) # PROBLEM_REPORT placeholder
+ self.failUnless(messages[4][0] == '7729135689895381486')
+ self.failUnless(messages[4][1][7][1] == 'and another after a blank line.')
+
+ def testParsingIntoMessages(self):
+ root = util.ParseGrdForUnittest('''
+ <messages>
+ <message name="ID_MEGA">Fantastic!</message>
+ <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>Joi</ex></ph></message>
+ </messages>''')
+
+ msgs, = root.GetChildrenOfType(empty.MessagesNode)
+ clique_mega = msgs.children[0].GetCliques()[0]
+ msg_mega = clique_mega.GetMessage()
+ clique_hello_user = msgs.children[1].GetCliques()[0]
+ msg_hello_user = clique_hello_user.GetMessage()
+
+ xtb_file = StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE translationbundle>
+ <translationbundle lang="is">
+ <translation id="%s">Meirihattar!</translation>
+ <translation id="%s">Saelir <ph name="USERNAME"/></translation>
+ </translationbundle>''' % (msg_mega.GetId(), msg_hello_user.GetId()))
+
+ xtb_reader.Parse(xtb_file,
+ msgs.UberClique().GenerateXtbParserCallback('is'))
+ self.assertEqual('Meirihattar!',
+ clique_mega.MessageForLanguage('is').GetRealContent())
+ self.failUnless('Saelir %s',
+ clique_hello_user.MessageForLanguage('is').GetRealContent())
+
+ def testIfNodesWithUseNameForId(self):
+ root = util.ParseGrdForUnittest('''
+ <messages>
+ <message name="ID_BINGO" use_name_for_id="true">Bingo!</message>
+ </messages>''')
+ msgs, = root.GetChildrenOfType(empty.MessagesNode)
+ clique = msgs.children[0].GetCliques()[0]
+ msg = clique.GetMessage()
+
+ xtb_file = StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE translationbundle>
+ <translationbundle lang="is">
+ <if expr="is_linux">
+ <translation id="ID_BINGO">Bongo!</translation>
+ </if>
+ <if expr="not is_linux">
+ <translation id="ID_BINGO">Congo!</translation>
+ </if>
+ </translationbundle>''')
+ xtb_reader.Parse(xtb_file,
+ msgs.UberClique().GenerateXtbParserCallback('is'),
+ target_platform='darwin')
+ self.assertEqual('Congo!', clique.MessageForLanguage('is').GetRealContent())
+
+ def testParseLargeFile(self):
+ def Callback(id, structure):
+ pass
+ with open(util.PathFromRoot('grit/testdata/generated_resources_fr.xtb')) as xtb:
+ xtb_reader.Parse(xtb, Callback)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/grit/grit_info.py b/chromium/tools/grit/grit_info.py
new file mode 100755
index 00000000000..9449c48c4eb
--- /dev/null
+++ b/chromium/tools/grit/grit_info.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Tool to determine inputs and outputs of a grit file.
+'''
+
+import optparse
+import os
+import posixpath
+import sys
+
+from grit import grd_reader
+from grit import util
+
+class WrongNumberOfArguments(Exception):
+ pass
+
+
+def Outputs(filename, defines, ids_file):
+ grd = grd_reader.Parse(
+ filename, defines=defines, tags_to_ignore=set(['messages']),
+ first_ids_file=ids_file)
+
+ target = []
+ lang_folders = {}
+ # Add all explicitly-specified output files
+ for output in grd.GetOutputFiles():
+ path = output.GetFilename()
+ target.append(path)
+
+ if path.endswith('.h'):
+ path, filename = os.path.split(path)
+ if output.attrs['lang']:
+ lang_folders[output.attrs['lang']] = os.path.dirname(path)
+
+ # Add all generated files, once for each output language.
+ for node in grd:
+ if node.name == 'structure':
+ with node:
+ # TODO(joi) Should remove the "if sconsdep is true" thing as it is a
+ # hack - see grit/node/structure.py
+ if node.HasFileForLanguage() and node.attrs['sconsdep'] == 'true':
+ for lang in lang_folders:
+ path = node.FileForLanguage(lang, lang_folders[lang],
+ create_file=False,
+ return_if_not_generated=False)
+ if path:
+ target.append(path)
+
+ return [t.replace('\\', '/') for t in target]
+
+
+def GritSourceFiles():
+ files = []
+ grit_root_dir = os.path.relpath(os.path.dirname(__file__), os.getcwd())
+ for root, dirs, filenames in os.walk(grit_root_dir):
+ grit_src = [os.path.join(root, f) for f in filenames
+ if f.endswith('.py')]
+ files.extend(grit_src)
+ return sorted(files)
+
+
+def Inputs(filename, defines, ids_file, target_platform):
+ grd = grd_reader.Parse(
+ filename, debug=False, defines=defines, tags_to_ignore=set(['message']),
+ first_ids_file=ids_file, target_platform=target_platform)
+ files = set()
+ for lang, ctx in grd.GetConfigurations():
+ grd.SetOutputLanguage(lang or grd.GetSourceLanguage())
+ grd.SetOutputContext(ctx)
+ for node in grd.ActiveDescendants():
+ with node:
+ if (node.name == 'structure' or node.name == 'skeleton' or
+ (node.name == 'file' and node.parent and
+ node.parent.name == 'translations')):
+ files.add(grd.ToRealPath(node.GetInputPath()))
+ # If it's a flattened node, grab inlined resources too.
+ if node.name == 'structure' and node.attrs['flattenhtml'] == 'true':
+ node.RunPreSubstitutionGatherer()
+ files.update(node.GetHtmlResourceFilenames())
+ elif node.name == 'grit':
+ first_ids_file = node.GetFirstIdsFile()
+ if first_ids_file:
+ files.add(first_ids_file)
+ elif node.name == 'include':
+ files.add(grd.ToRealPath(node.GetInputPath()))
+ # If it's a flattened node, grab inlined resources too.
+ if node.attrs['flattenhtml'] == 'true':
+ files.update(node.GetHtmlResourceFilenames())
+ elif node.name == 'part':
+ files.add(util.normpath(os.path.join(os.path.dirname(filename),
+ node.GetInputPath())))
+
+ cwd = os.getcwd()
+ return [os.path.relpath(f, cwd) for f in sorted(files)]
+
+
+def PrintUsage():
+ print 'USAGE: ./grit_info.py --inputs [-D foo] [-f resource_ids] <grd-file>'
+ print (' ./grit_info.py --outputs [-D foo] [-f resource_ids] ' +
+ '<out-prefix> <grd-file>')
+
+
+def DoMain(argv):
+ parser = optparse.OptionParser()
+ parser.add_option("--inputs", action="store_true", dest="inputs")
+ parser.add_option("--outputs", action="store_true", dest="outputs")
+ parser.add_option("-D", action="append", dest="defines", default=[])
+ # grit build also supports '-E KEY=VALUE', support that to share command
+ # line flags.
+ parser.add_option("-E", action="append", dest="build_env", default=[])
+ parser.add_option("-w", action="append", dest="whitelist_files", default=[])
+ parser.add_option("-f", dest="ids_file",
+ default="GRIT_DIR/../gritsettings/resource_ids")
+ parser.add_option("-t", dest="target_platform", default=None)
+
+ options, args = parser.parse_args(argv)
+
+ defines = {}
+ for define in options.defines:
+ name, val = util.ParseDefine(define)
+ defines[name] = val
+
+ for env_pair in options.build_env:
+ (env_name, env_value) = env_pair.split('=', 1)
+ os.environ[env_name] = env_value
+
+ if options.inputs:
+ if len(args) > 1:
+ raise WrongNumberOfArguments("Expected 0 or 1 arguments for --inputs.")
+
+ inputs = []
+ if len(args) == 1:
+ filename = args[0]
+ inputs = Inputs(filename, defines, options.ids_file,
+ options.target_platform)
+
+ # Add in the grit source files. If one of these change, we want to re-run
+ # grit.
+ inputs.extend(GritSourceFiles())
+ inputs = [f.replace('\\', '/') for f in inputs]
+
+ if len(args) == 1:
+ # Include grd file as second input (works around gyp expecting it).
+ inputs.insert(1, args[0])
+ if options.whitelist_files:
+ inputs.extend(options.whitelist_files)
+ return '\n'.join(inputs)
+ elif options.outputs:
+ if len(args) != 2:
+ raise WrongNumberOfArguments(
+ "Expected exactly 2 arguments for --outputs.")
+
+ prefix, filename = args
+ outputs = [posixpath.join(prefix, f)
+ for f in Outputs(filename, defines, options.ids_file)]
+ return '\n'.join(outputs)
+ else:
+ raise WrongNumberOfArguments("Expected --inputs or --outputs.")
+
+
+def main(argv):
+ if sys.version_info < (2, 6):
+ print "GRIT requires Python 2.6 or later."
+ return 1
+
+ try:
+ result = DoMain(argv[1:])
+ except WrongNumberOfArguments, e:
+ PrintUsage()
+ print e
+ return 1
+ print result
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/tools/gritsettings/resource_ids b/chromium/tools/gritsettings/resource_ids
new file mode 100644
index 00000000000..0e6b8485237
--- /dev/null
+++ b/chromium/tools/gritsettings/resource_ids
@@ -0,0 +1,221 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This file is used to assign starting resource ids for resources and strings
+# used by Chromium. This is done to ensure that resource ids are unique
+# across all the grd files. If you are adding a new grd file, please add
+# a new entry to this file.
+#
+# The first entry in the file, SRCDIR, is special: It is a relative path from
+# this file to the base of your checkout.
+#
+# http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx says that the
+# range for IDR_ is 1 to 28,671 and the range for IDS_ is 1 to 32,767 and
+# common convention starts practical use of IDs at 100 or 101.
+{
+ "SRCDIR": "../..",
+
+ "chrome/browser/browser_resources.grd": {
+ "includes": [500],
+ "structures": [750],
+ },
+ "chrome/browser/resources/component_extension_resources.grd": {
+ "includes": [1000],
+ "structures": [1450],
+ },
+ "chrome/browser/resources/net_internals_resources.grd": {
+ "includes": [1500],
+ },
+ "ui/webui/resources/webui_resources.grd": {
+ "includes": [2000],
+ "structures": [2200],
+ },
+ "chrome/common/common_resources.grd": {
+ "includes": [2500],
+ },
+ "chrome/renderer/resources/renderer_resources.grd": {
+ "includes": [3500],
+ "structures": [3700],
+ },
+ "net/base/net_resources.grd": {
+ "includes": [4000],
+ },
+ "ui/resources/ui_unscaled_resources.grd": {
+ "includes": [4500],
+ },
+ "webkit/glue/resources/webkit_resources.grd": {
+ "structures": [4700],
+ },
+ "webkit/tools/test_shell/test_shell_resources.grd": {
+ "includes": [5000],
+ },
+ "ui/resources/ui_resources.grd": {
+ "structures": [5500],
+ },
+ "ash/resources/ash_resources.grd": {
+ "includes": [6100],
+ "structures": [6150],
+ },
+ "chrome/app/theme/theme_resources.grd": {
+ "structures": [6500],
+ },
+ "chrome/app/theme/chrome_unscaled_resources.grd": {
+ "includes": [7500],
+ },
+ "chrome_frame/resources/chrome_frame_resources.grd": {
+ "includes": [8000],
+ },
+ "ui/base/strings/app_locale_settings.grd": {
+ "messages": [9000],
+ },
+ "chrome/app/resources/locale_settings.grd": {
+ "includes": [9500],
+ "messages": [10000],
+ },
+ # These each start with the same resource id because we only use one
+ # file for each build (chromiumos, google_chromeos, linux, mac, or win).
+ "chrome/app/resources/locale_settings_chromiumos.grd": {
+ "messages": [10500],
+ },
+ "chrome/app/resources/locale_settings_google_chromeos.grd": {
+ "messages": [10500],
+ },
+ "chrome/app/resources/locale_settings_linux.grd": {
+ "messages": [10500],
+ },
+ "chrome/app/resources/locale_settings_mac.grd": {
+ "messages": [10500],
+ },
+ "chrome/app/resources/locale_settings_win.grd": {
+ "messages": [10500],
+ },
+
+ "ui/base/strings/ui_strings.grd": {
+ "messages": [11000],
+ },
+ # Chromium strings and Google Chrome strings must start at the same id.
+ # We only use one file depending on whether we're building Chromium or
+ # Google Chrome.
+ "chrome/app/chromium_strings.grd": {
+ "messages": [11500],
+ },
+ "chrome/app/google_chrome_strings.grd": {
+ "messages": [11500],
+ },
+ # Leave lots of space for generated_resources since it has most of our
+ # strings.
+ "chrome/app/generated_resources.grd": {
+ "structures": [12000],
+ "messages": [12500],
+ },
+ # The chrome frame dialogs are also in generated_resources.grd so they
+ # get included by the translation console. We make sure that the ids
+ # for structures here are the same as for generated_resources.grd.
+ "chrome_frame/resources/chrome_frame_dialogs.grd": {
+ "structures": [12000],
+ "includes": [12250],
+ },
+ "webkit/glue/inspector_strings.grd": {
+ "messages": [17500],
+ },
+ "webkit/glue/webkit_strings.grd": {
+ "messages": [18000],
+ },
+
+ "chrome_frame/resources/chrome_frame_resources.grd": {
+ "includes": [19000],
+ "structures": [19500],
+ },
+
+ "ui/base/native_theme/resources/native_theme_resources.grd": {
+ "includes": [20000],
+ },
+
+ "chrome/app/policy/policy_templates.grd": {
+ "structures": [20500],
+ "messages": [20510],
+ },
+
+ "chrome/browser/autofill/autofill_resources.grd": {
+ "messages": [21000],
+ },
+ "chrome/browser/resources/sync_internals_resources.grd": {
+ "includes": [21500],
+ },
+ "chrome/browser/resources/signin_internals_resources.grd": {
+ "includes": [21750],
+ },
+ # This file is generated during the build.
+ # devtools_resources.grd can be in two different places depending on whether
+ # we are in a chromium checkout or a webkit-only checkout.
+ "<(SHARED_INTERMEDIATE_DIR)/devtools/devtools_resources.grd": {
+ "includes": [22000],
+ },
+ "devtools_resources.grd": {
+ "includes": [22000],
+ },
+ # This file is generated during the build.
+ "chrome/browser/devtools/frontend/devtools_discovery_page_resources.grd": {
+ "includes": [22500],
+ },
+ "chrome/browser/resources/options_resources.grd": {
+ "includes": [23000],
+ },
+ "chrome/browser/resources/options_resources.grd": {
+ "structures": [23200],
+ },
+ "cloud_print/virtual_driver/win/install/virtual_driver_setup_resources.grd": {
+ "messages": [23500],
+ "includes": [23550],
+ },
+ "cloud_print/service/win/service_resources.grd": {
+ "messages": [23600],
+ "includes": [23800],
+ "structures": [23900],
+ },
+ "chrome/browser/resources/quota_internals_resources.grd": {
+ "includes": [24000],
+ },
+ "content/content_resources.grd": {
+ "includes": [25000],
+ },
+ "content/shell/shell_resources.grd": {
+ "includes": [25500],
+ },
+ # This file is generated during the build.
+ "<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/tracing_resources.grd": {
+ "includes": [25750],
+ },
+ "ash/ash_strings.grd": {
+ "messages": [26000],
+ },
+ "chrome/common/extensions_api_resources.grd": {
+ "includes": [26500],
+ },
+ "third_party/trace-viewer/src/tracing.grd": {
+ "includes": [27000],
+ },
+ "chrome/browser/resources/memory_internals_resources.grd": {
+ "includes": [27500],
+ },
+ "device/bluetooth/bluetooth_strings.grd": {
+ "messages": [28000],
+ },
+ "ui/keyboard/keyboard_resources.grd": {
+ "includes": [28050],
+ },
+ "chrome/browser/resources/translate_internals_resources.grd": {
+ "includes": [28500],
+ },
+ "chrome/browser/resources/sync_file_system_internals_resources.grd": {
+ "includes": [29000],
+ },
+ "components/component_strings.grd": {
+ "messages": [30000],
+ },
+ "third_party/WebKit/public/blink_resources.grd": {
+ "includes": [30500],
+ },
+ # Resource ids starting at 31000 are reserved for projects built on Chromium.
+}
diff --git a/chromium/tools/gtk_clipboard_dump/gtk_clipboard_dump.cc b/chromium/tools/gtk_clipboard_dump/gtk_clipboard_dump.cc
new file mode 100644
index 00000000000..4ddf1a2a73a
--- /dev/null
+++ b/chromium/tools/gtk_clipboard_dump/gtk_clipboard_dump.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+#include <string>
+
+namespace {
+
+void PrintClipboardContents(GtkClipboard* clip) {
+ GdkAtom* targets;
+ int num_targets = 0;
+
+ // This call is bugged, the cache it checks is often stale; see
+ // <http://bugzilla.gnome.org/show_bug.cgi?id=557315>.
+ // gtk_clipboard_wait_for_targets(clip, &targets, &num_targets);
+
+ GtkSelectionData* target_data =
+ gtk_clipboard_wait_for_contents(clip,
+ gdk_atom_intern("TARGETS", false));
+ if (!target_data) {
+ printf("failed to get the contents!\n");
+ return;
+ }
+
+ gtk_selection_data_get_targets(target_data, &targets, &num_targets);
+
+ printf("%d available targets:\n---------------\n", num_targets);
+
+ for (int i = 0; i < num_targets; i++) {
+ gchar* target_name_cstr = gdk_atom_name(targets[i]);
+ std::string target_name(target_name_cstr);
+ g_free(target_name_cstr);
+ printf(" [format: %s", target_name.c_str());
+ GtkSelectionData* data = gtk_clipboard_wait_for_contents(clip, targets[i]);
+ if (!data) {
+ printf("]: NULL\n\n");
+ continue;
+ }
+
+ printf(" / length: %d / bits %d]: ", data->length, data->format);
+
+ if (strstr(target_name.c_str(), "image")) {
+ printf("(image omitted)\n\n");
+ } else if (strstr(target_name.c_str(), "TIMESTAMP")) {
+ // TODO(estade): Print the time stamp in human readable format.
+ printf("(time omitted)\n\n");
+ } else {
+ for (int j = 0; j < data->length; j++) {
+ // Output data one byte at a time. Currently wide strings look
+ // pretty weird.
+ printf("%c", (data->data[j] == 0 ? '_' : data->data[j]));
+ }
+ printf("\n\n");
+ }
+ gtk_selection_data_free(data);
+ }
+
+ if (num_targets <= 0) {
+ printf("No targets advertised. Text is: ");
+ gchar* text = gtk_clipboard_wait_for_text(clip);
+ printf("%s\n", text ? text : "NULL");
+ g_free(text);
+ }
+
+ g_free(targets);
+ gtk_selection_data_free(target_data);
+}
+
+}
+
+/* Small program to dump the contents of GTK's clipboards to the terminal.
+ * Feel free to add to it or improve formatting or whatnot.
+ */
+int main(int argc, char* argv[]) {
+ gtk_init(&argc, &argv);
+
+ printf("Desktop clipboard\n");
+ PrintClipboardContents(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD));
+
+ printf("X clipboard\n");
+ PrintClipboardContents(gtk_clipboard_get(GDK_SELECTION_PRIMARY));
+}
diff --git a/chromium/tools/gtk_clipboard_dump/gtk_clipboard_dump.gyp b/chromium/tools/gtk_clipboard_dump/gtk_clipboard_dump.gyp
new file mode 100644
index 00000000000..21121089a30
--- /dev/null
+++ b/chromium/tools/gtk_clipboard_dump/gtk_clipboard_dump.gyp
@@ -0,0 +1,14 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'gtk_clipboard_dump',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../build/linux/system.gyp:gtk',
+ ],
+ 'sources': [
+ 'gtk_clipboard_dump.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp-explain.py b/chromium/tools/gyp-explain.py
new file mode 100755
index 00000000000..824f72f1d65
--- /dev/null
+++ b/chromium/tools/gyp-explain.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Prints paths between gyp targets.
+"""
+
+import json
+import os
+import sys
+import time
+
+from collections import deque
+
+def usage():
+ print """\
+Usage:
+ tools/gyp-explain.py [--dot] chrome_dll# gtest#
+"""
+
+
+def GetPath(graph, fro, to):
+ """Given a graph in (node -> list of successor nodes) dictionary format,
+ yields all paths from |fro| to |to|, starting with the shortest."""
+ # Storing full paths in the queue is a bit wasteful, but good enough for this.
+ q = deque([(fro, [])])
+ while q:
+ t, path = q.popleft()
+ if t == to:
+ yield path + [t]
+ for d in graph[t]:
+ q.append((d, path + [t]))
+
+
+def MatchNode(graph, substring):
+ """Given a dictionary, returns the key that matches |substring| best. Exits
+ if there's not one single best match."""
+ candidates = []
+ for target in graph:
+ if substring in target:
+ candidates.append(target)
+
+ if not candidates:
+ print 'No targets match "%s"' % substring
+ sys.exit(1)
+ if len(candidates) > 1:
+ print 'More than one target matches "%s": %s' % (
+ substring, ' '.join(candidates))
+ sys.exit(1)
+ return candidates[0]
+
+
+def EscapeForDot(string):
+ suffix = '#target'
+ if string.endswith(suffix):
+ string = string[:-len(suffix)]
+ string = string.replace('\\', '\\\\')
+ return '"' + string + '"'
+
+
+def GenerateDot(fro, to, paths):
+ """Generates an input file for graphviz's dot program."""
+ prefixes = [os.path.commonprefix(path) for path in paths]
+ prefix = os.path.commonprefix(prefixes)
+ print '// Build with "dot -Tpng -ooutput.png this_file.dot"'
+ # "strict" collapses common paths.
+ print 'strict digraph {'
+ for path in paths:
+ print (' -> '.join(EscapeForDot(item[len(prefix):]) for item in path)), ';'
+ print '}'
+
+
+def Main(argv):
+ # Check that dump.json exists and that it's not too old.
+ dump_json_dirty = False
+ try:
+ st = os.stat('dump.json')
+ file_age_s = time.time() - st.st_mtime
+ if file_age_s > 2 * 60 * 60:
+ print 'dump.json is more than 2 hours old.'
+ dump_json_dirty = True
+ except OSError:
+ print 'dump.json not found.'
+ dump_json_dirty = True
+
+ if dump_json_dirty:
+ print 'Run'
+ print ' GYP_GENERATORS=dump_dependency_json build/gyp_chromium'
+ print 'first, then try again.'
+ sys.exit(1)
+
+ g = json.load(open('dump.json'))
+
+ if len(argv) not in (3, 4):
+ usage()
+ sys.exit(1)
+
+ generate_dot = argv[1] == '--dot'
+ if generate_dot:
+ argv.pop(1)
+
+ fro = MatchNode(g, argv[1])
+ to = MatchNode(g, argv[2])
+
+ paths = list(GetPath(g, fro, to))
+ if len(paths) > 0:
+ if generate_dot:
+ GenerateDot(fro, to, paths)
+ else:
+ print 'These paths lead from %s to %s:' % (fro, to)
+ for path in paths:
+ print ' -> '.join(path)
+ else:
+ print 'No paths found from %s to %s.' % (fro, to)
+
+
+if __name__ == '__main__':
+ Main(sys.argv)
diff --git a/chromium/tools/gyp/AUTHORS b/chromium/tools/gyp/AUTHORS
new file mode 100644
index 00000000000..ace20379dd8
--- /dev/null
+++ b/chromium/tools/gyp/AUTHORS
@@ -0,0 +1,9 @@
+# Names should be added to this file like so:
+# Name or Organization <email address>
+
+Google Inc.
+Bloomberg Finance L.P.
+Yandex LLC
+
+Steven Knight <knight@baldmt.com>
+Ryan Norton <rnorton10@gmail.com>
diff --git a/chromium/tools/gyp/DEPS b/chromium/tools/gyp/DEPS
new file mode 100644
index 00000000000..2e1120f2746
--- /dev/null
+++ b/chromium/tools/gyp/DEPS
@@ -0,0 +1,24 @@
+# DEPS file for gclient use in buildbot execution of gyp tests.
+#
+# (You don't need to use gclient for normal GYP development work.)
+
+vars = {
+ "chrome_trunk": "http://src.chromium.org/svn/trunk",
+ "googlecode_url": "http://%s.googlecode.com/svn",
+}
+
+deps = {
+}
+
+deps_os = {
+ "win": {
+ "third_party/cygwin":
+ Var("chrome_trunk") + "/deps/third_party/cygwin@66844",
+
+ "third_party/python_26":
+ Var("chrome_trunk") + "/tools/third_party/python_26@89111",
+
+ "src/third_party/pefile":
+ (Var("googlecode_url") % "pefile") + "/trunk@63",
+ },
+}
diff --git a/chromium/tools/gyp/LICENSE b/chromium/tools/gyp/LICENSE
new file mode 100644
index 00000000000..ab6b011a109
--- /dev/null
+++ b/chromium/tools/gyp/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chromium/tools/gyp/MANIFEST b/chromium/tools/gyp/MANIFEST
new file mode 100644
index 00000000000..03a194a4c1e
--- /dev/null
+++ b/chromium/tools/gyp/MANIFEST
@@ -0,0 +1,19 @@
+setup.py
+gyp
+LICENSE
+AUTHORS
+pylib/gyp/MSVSNew.py
+pylib/gyp/MSVSProject.py
+pylib/gyp/MSVSToolFile.py
+pylib/gyp/MSVSUserFile.py
+pylib/gyp/MSVSVersion.py
+pylib/gyp/__init__.py
+pylib/gyp/common.py
+pylib/gyp/input.py
+pylib/gyp/xcodeproj_file.py
+pylib/gyp/generator/__init__.py
+pylib/gyp/generator/gypd.py
+pylib/gyp/generator/gypsh.py
+pylib/gyp/generator/make.py
+pylib/gyp/generator/msvs.py
+pylib/gyp/generator/xcode.py
diff --git a/chromium/tools/gyp/OWNERS b/chromium/tools/gyp/OWNERS
new file mode 100644
index 00000000000..72e8ffc0db8
--- /dev/null
+++ b/chromium/tools/gyp/OWNERS
@@ -0,0 +1 @@
+*
diff --git a/chromium/tools/gyp/PRESUBMIT.py b/chromium/tools/gyp/PRESUBMIT.py
new file mode 100644
index 00000000000..5567b88bd10
--- /dev/null
+++ b/chromium/tools/gyp/PRESUBMIT.py
@@ -0,0 +1,115 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Top-level presubmit script for GYP.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into gcl.
+"""
+
+
+PYLINT_BLACKLIST = [
+ # TODO: fix me.
+ # From SCons, not done in google style.
+ 'test/lib/TestCmd.py',
+ 'test/lib/TestCommon.py',
+ 'test/lib/TestGyp.py',
+ # Needs style fix.
+ 'pylib/gyp/generator/xcode.py',
+]
+
+
+PYLINT_DISABLED_WARNINGS = [
+ # TODO: fix me.
+ # Many tests include modules they don't use.
+ 'W0611',
+ # Include order doesn't properly include local files?
+ 'F0401',
+ # Some use of built-in names.
+ 'W0622',
+ # Some unused variables.
+ 'W0612',
+ # Operator not preceded/followed by space.
+ 'C0323',
+ 'C0322',
+ # Unnecessary semicolon.
+ 'W0301',
+ # Unused argument.
+ 'W0613',
+ # String has no effect (docstring in wrong place).
+ 'W0105',
+ # Comma not followed by space.
+ 'C0324',
+ # Access to a protected member.
+ 'W0212',
+ # Bad indent.
+ 'W0311',
+ # Line too long.
+ 'C0301',
+ # Undefined variable.
+ 'E0602',
+ # Not exception type specified.
+ 'W0702',
+ # No member of that name.
+ 'E1101',
+ # Dangerous default {}.
+ 'W0102',
+ # Others, too many to sort.
+ 'W0201', 'W0232', 'E1103', 'W0621', 'W0108', 'W0223', 'W0231',
+ 'R0201', 'E0101', 'C0321',
+ # ************* Module copy
+ # W0104:427,12:_test.odict.__setitem__: Statement seems to have no effect
+ 'W0104',
+]
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ report = []
+ report.extend(input_api.canned_checks.PanProjectChecks(
+ input_api, output_api))
+ return report
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ report = []
+
+ # Accept any year number from 2009 to the current year.
+ current_year = int(input_api.time.strftime('%Y'))
+ allowed_years = (str(s) for s in reversed(xrange(2009, current_year + 1)))
+ years_re = '(' + '|'.join(allowed_years) + ')'
+
+ # The (c) is deprecated, but tolerate it until it's removed from all files.
+ license = (
+ r'.*? Copyright (\(c\) )?%(year)s Google Inc\. All rights reserved\.\n'
+ r'.*? Use of this source code is governed by a BSD-style license that '
+ r'can be\n'
+ r'.*? found in the LICENSE file\.\n'
+ ) % {
+ 'year': years_re,
+ }
+
+ report.extend(input_api.canned_checks.PanProjectChecks(
+ input_api, output_api, license_header=license))
+ report.extend(input_api.canned_checks.CheckTreeIsOpen(
+ input_api, output_api,
+ 'http://gyp-status.appspot.com/status',
+ 'http://gyp-status.appspot.com/current'))
+
+ import sys
+ old_sys_path = sys.path
+ try:
+ sys.path = ['pylib', 'test/lib'] + sys.path
+ report.extend(input_api.canned_checks.RunPylint(
+ input_api,
+ output_api,
+ black_list=PYLINT_BLACKLIST,
+ disabled_warnings=PYLINT_DISABLED_WARNINGS))
+ finally:
+ sys.path = old_sys_path
+ return report
+
+
+def GetPreferredTrySlaves():
+ return ['gyp-win32', 'gyp-win64', 'gyp-linux', 'gyp-mac', 'gyp-android']
diff --git a/chromium/tools/gyp/buildbot/buildbot_run.py b/chromium/tools/gyp/buildbot/buildbot_run.py
new file mode 100755
index 00000000000..398eb87a856
--- /dev/null
+++ b/chromium/tools/gyp/buildbot/buildbot_run.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Argument-less script to select what to run on the buildbots."""
+
+
+import os
+import shutil
+import subprocess
+import sys
+
+
+if sys.platform in ['win32', 'cygwin']:
+ EXE_SUFFIX = '.exe'
+else:
+ EXE_SUFFIX = ''
+
+
+BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__))
+TRUNK_DIR = os.path.dirname(BUILDBOT_DIR)
+ROOT_DIR = os.path.dirname(TRUNK_DIR)
+ANDROID_DIR = os.path.join(ROOT_DIR, 'android')
+OUT_DIR = os.path.join(TRUNK_DIR, 'out')
+
+
+def CallSubProcess(*args, **kwargs):
+ """Wrapper around subprocess.call which treats errors as build exceptions."""
+ retcode = subprocess.call(*args, **kwargs)
+ if retcode != 0:
+ print '@@@STEP_EXCEPTION@@@'
+ sys.exit(1)
+
+
+def PrepareAndroidTree():
+ """Prepare an Android tree to run 'android' format tests."""
+ if os.environ['BUILDBOT_CLOBBER'] == '1':
+ print '@@@BUILD_STEP Clobber Android checkout@@@'
+ shutil.rmtree(ANDROID_DIR)
+
+ # The release of Android we use is static, so there's no need to do anything
+ # if the directory already exists.
+ if os.path.isdir(ANDROID_DIR):
+ return
+
+ print '@@@BUILD_STEP Initialize Android checkout@@@'
+ os.mkdir(ANDROID_DIR)
+ CallSubProcess(['git', 'config', '--global', 'user.name', 'trybot'])
+ CallSubProcess(['git', 'config', '--global',
+ 'user.email', 'chrome-bot@google.com'])
+ CallSubProcess(['git', 'config', '--global', 'color.ui', 'false'])
+ CallSubProcess(
+ ['repo', 'init',
+ '-u', 'https://android.googlesource.com/platform/manifest',
+ '-b', 'android-4.2.1_r1',
+ '-g', 'all,-notdefault,-device,-darwin,-mips,-x86'],
+ cwd=ANDROID_DIR)
+
+ print '@@@BUILD_STEP Sync Android@@@'
+ CallSubProcess(['repo', 'sync', '-j4'], cwd=ANDROID_DIR)
+
+ print '@@@BUILD_STEP Build Android@@@'
+ CallSubProcess(
+ ['/bin/bash',
+ '-c', 'source build/envsetup.sh && lunch full-eng && make -j4'],
+ cwd=ANDROID_DIR)
+
+
+def GypTestFormat(title, format=None, msvs_version=None):
+ """Run the gyp tests for a given format, emitting annotator tags.
+
+ See annotator docs at:
+ https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/buildbot-annotations
+ Args:
+ format: gyp format to test.
+ Returns:
+ 0 for sucesss, 1 for failure.
+ """
+ if not format:
+ format = title
+
+ print '@@@BUILD_STEP ' + title + '@@@'
+ sys.stdout.flush()
+ env = os.environ.copy()
+ if msvs_version:
+ env['GYP_MSVS_VERSION'] = msvs_version
+ command = ' '.join(
+ [sys.executable, 'trunk/gyptest.py',
+ '--all',
+ '--passed',
+ '--format', format,
+ '--chdir', 'trunk'])
+ if format == 'android':
+ # gyptest needs the environment setup from envsetup/lunch in order to build
+ # using the 'android' backend, so this is done in a single shell.
+ retcode = subprocess.call(
+ ['/bin/bash',
+ '-c', 'source build/envsetup.sh && lunch full-eng && cd %s && %s'
+ % (ROOT_DIR, command)],
+ cwd=ANDROID_DIR, env=env)
+ else:
+ retcode = subprocess.call(command, cwd=ROOT_DIR, env=env, shell=True)
+ if retcode:
+ # Emit failure tag, and keep going.
+ print '@@@STEP_FAILURE@@@'
+ return 1
+ return 0
+
+
+def GypBuild():
+ # Dump out/ directory.
+ print '@@@BUILD_STEP cleanup@@@'
+ print 'Removing %s...' % OUT_DIR
+ shutil.rmtree(OUT_DIR, ignore_errors=True)
+ print 'Done.'
+
+ retcode = 0
+ # The Android gyp bot runs on linux so this must be tested first.
+ if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-android':
+ PrepareAndroidTree()
+ retcode += GypTestFormat('android')
+ elif sys.platform.startswith('linux'):
+ retcode += GypTestFormat('ninja')
+ retcode += GypTestFormat('make')
+ elif sys.platform == 'darwin':
+ retcode += GypTestFormat('ninja')
+ retcode += GypTestFormat('xcode')
+ retcode += GypTestFormat('make')
+ elif sys.platform == 'win32':
+ retcode += GypTestFormat('ninja')
+ if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64':
+ retcode += GypTestFormat('msvs-2010', format='msvs', msvs_version='2010')
+ retcode += GypTestFormat('msvs-2012', format='msvs', msvs_version='2012')
+ else:
+ raise Exception('Unknown platform')
+ if retcode:
+ # TODO(bradnelson): once the annotator supports a postscript (section for
+ # after the build proper that could be used for cumulative failures),
+ # use that instead of this. This isolates the final return value so
+ # that it isn't misattributed to the last stage.
+ print '@@@BUILD_STEP failures@@@'
+ sys.exit(retcode)
+
+
+if __name__ == '__main__':
+ GypBuild()
diff --git a/chromium/tools/gyp/codereview.settings b/chromium/tools/gyp/codereview.settings
new file mode 100644
index 00000000000..a04a2440df3
--- /dev/null
+++ b/chromium/tools/gyp/codereview.settings
@@ -0,0 +1,10 @@
+# This file is used by gcl to get repository specific information.
+CODE_REVIEW_SERVER: codereview.chromium.org
+CC_LIST: gyp-developer@googlegroups.com
+VIEW_VC: http://code.google.com/p/gyp/source/detail?r=
+TRY_ON_UPLOAD: True
+TRYSERVER_PROJECT: gyp
+TRYSERVER_PATCHLEVEL: 0
+TRYSERVER_ROOT: trunk
+TRYSERVER_SVN_URL: svn://svn.chromium.org/chrome-try/try-nacl
+
diff --git a/chromium/tools/gyp/data/win/large-pdb-shim.cc b/chromium/tools/gyp/data/win/large-pdb-shim.cc
new file mode 100644
index 00000000000..8bca510815e
--- /dev/null
+++ b/chromium/tools/gyp/data/win/large-pdb-shim.cc
@@ -0,0 +1,12 @@
+// Copyright (c) 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is used to generate an empty .pdb -- with a 4KB pagesize -- that is
+// then used during the final link for modules that have large PDBs. Otherwise,
+// the linker will generate a pdb with a page size of 1KB, which imposes a limit
+// of 1GB on the .pdb. By generating an initial empty .pdb with the compiler
+// (rather than the linker), this limit is avoided. With this in place PDBs may
+// grow to 2GB.
+//
+// This file is referenced by the msvs_large_pdb mechanism in MSVSUtil.py.
diff --git a/chromium/tools/gyp/gyp b/chromium/tools/gyp/gyp
new file mode 100755
index 00000000000..a157f34950a
--- /dev/null
+++ b/chromium/tools/gyp/gyp
@@ -0,0 +1,7 @@
+#!/bin/bash
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+BASE=`dirname $0`
+python $BASE/gyp_main.py "$@"
diff --git a/chromium/tools/gyp/gyp.bat b/chromium/tools/gyp/gyp.bat
new file mode 100755
index 00000000000..c0b4ca24e5d
--- /dev/null
+++ b/chromium/tools/gyp/gyp.bat
@@ -0,0 +1,5 @@
+@rem Copyright (c) 2009 Google Inc. All rights reserved.
+@rem Use of this source code is governed by a BSD-style license that can be
+@rem found in the LICENSE file.
+
+@python "%~dp0gyp_main.py" %*
diff --git a/chromium/tools/gyp/gyp_dummy.c b/chromium/tools/gyp/gyp_dummy.c
new file mode 100644
index 00000000000..fb55bbc78da
--- /dev/null
+++ b/chromium/tools/gyp/gyp_dummy.c
@@ -0,0 +1,7 @@
+/* Copyright (c) 2009 Google Inc. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+int main() {
+ return 0;
+}
diff --git a/chromium/tools/gyp/gyp_main.py b/chromium/tools/gyp/gyp_main.py
new file mode 100755
index 00000000000..d52e7116f5a
--- /dev/null
+++ b/chromium/tools/gyp/gyp_main.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+# TODO(mark): sys.path manipulation is some temporary testing stuff.
+try:
+ import gyp
+except ImportError, e:
+ import os.path
+ sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), 'pylib'))
+ import gyp
+
+if __name__ == '__main__':
+ sys.exit(gyp.main(sys.argv[1:]))
diff --git a/chromium/tools/gyp/gyptest.py b/chromium/tools/gyp/gyptest.py
new file mode 100755
index 00000000000..efa75a7aa82
--- /dev/null
+++ b/chromium/tools/gyp/gyptest.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+__doc__ = """
+gyptest.py -- test runner for GYP tests.
+"""
+
+import os
+import optparse
+import subprocess
+import sys
+
+class CommandRunner:
+ """
+ Executor class for commands, including "commands" implemented by
+ Python functions.
+ """
+ verbose = True
+ active = True
+
+ def __init__(self, dictionary={}):
+ self.subst_dictionary(dictionary)
+
+ def subst_dictionary(self, dictionary):
+ self._subst_dictionary = dictionary
+
+ def subst(self, string, dictionary=None):
+ """
+ Substitutes (via the format operator) the values in the specified
+ dictionary into the specified command.
+
+ The command can be an (action, string) tuple. In all cases, we
+ perform substitution on strings and don't worry if something isn't
+ a string. (It's probably a Python function to be executed.)
+ """
+ if dictionary is None:
+ dictionary = self._subst_dictionary
+ if dictionary:
+ try:
+ string = string % dictionary
+ except TypeError:
+ pass
+ return string
+
+ def display(self, command, stdout=None, stderr=None):
+ if not self.verbose:
+ return
+ if type(command) == type(()):
+ func = command[0]
+ args = command[1:]
+ s = '%s(%s)' % (func.__name__, ', '.join(map(repr, args)))
+ if type(command) == type([]):
+ # TODO: quote arguments containing spaces
+ # TODO: handle meta characters?
+ s = ' '.join(command)
+ else:
+ s = self.subst(command)
+ if not s.endswith('\n'):
+ s += '\n'
+ sys.stdout.write(s)
+ sys.stdout.flush()
+
+ def execute(self, command, stdout=None, stderr=None):
+ """
+ Executes a single command.
+ """
+ if not self.active:
+ return 0
+ if type(command) == type(''):
+ command = self.subst(command)
+ cmdargs = shlex.split(command)
+ if cmdargs[0] == 'cd':
+ command = (os.chdir,) + tuple(cmdargs[1:])
+ if type(command) == type(()):
+ func = command[0]
+ args = command[1:]
+ return func(*args)
+ else:
+ if stdout is sys.stdout:
+ # Same as passing sys.stdout, except python2.4 doesn't fail on it.
+ subout = None
+ else:
+ # Open pipe for anything else so Popen works on python2.4.
+ subout = subprocess.PIPE
+ if stderr is sys.stderr:
+ # Same as passing sys.stderr, except python2.4 doesn't fail on it.
+ suberr = None
+ elif stderr is None:
+ # Merge with stdout if stderr isn't specified.
+ suberr = subprocess.STDOUT
+ else:
+ # Open pipe for anything else so Popen works on python2.4.
+ suberr = subprocess.PIPE
+ p = subprocess.Popen(command,
+ shell=(sys.platform == 'win32'),
+ stdout=subout,
+ stderr=suberr)
+ p.wait()
+ if stdout is None:
+ self.stdout = p.stdout.read()
+ elif stdout is not sys.stdout:
+ stdout.write(p.stdout.read())
+ if stderr not in (None, sys.stderr):
+ stderr.write(p.stderr.read())
+ return p.returncode
+
+ def run(self, command, display=None, stdout=None, stderr=None):
+ """
+ Runs a single command, displaying it first.
+ """
+ if display is None:
+ display = command
+ self.display(display)
+ return self.execute(command, stdout, stderr)
+
+
+class Unbuffered:
+ def __init__(self, fp):
+ self.fp = fp
+ def write(self, arg):
+ self.fp.write(arg)
+ self.fp.flush()
+ def __getattr__(self, attr):
+ return getattr(self.fp, attr)
+
+sys.stdout = Unbuffered(sys.stdout)
+sys.stderr = Unbuffered(sys.stderr)
+
+
+def find_all_gyptest_files(directory):
+ result = []
+ for root, dirs, files in os.walk(directory):
+ if '.svn' in dirs:
+ dirs.remove('.svn')
+ result.extend([ os.path.join(root, f) for f in files
+ if f.startswith('gyptest') and f.endswith('.py') ])
+ result.sort()
+ return result
+
+
+def main(argv=None):
+ if argv is None:
+ argv = sys.argv
+
+ usage = "gyptest.py [-ahlnq] [-f formats] [test ...]"
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option("-a", "--all", action="store_true",
+ help="run all tests")
+ parser.add_option("-C", "--chdir", action="store", default=None,
+ help="chdir to the specified directory")
+ parser.add_option("-f", "--format", action="store", default='',
+ help="run tests with the specified formats")
+ parser.add_option("-G", '--gyp_option', action="append", default=[],
+ help="Add -G options to the gyp command line")
+ parser.add_option("-l", "--list", action="store_true",
+ help="list available tests and exit")
+ parser.add_option("-n", "--no-exec", action="store_true",
+ help="no execute, just print the command line")
+ parser.add_option("--passed", action="store_true",
+ help="report passed tests")
+ parser.add_option("--path", action="append", default=[],
+ help="additional $PATH directory")
+ parser.add_option("-q", "--quiet", action="store_true",
+ help="quiet, don't print test command lines")
+ opts, args = parser.parse_args(argv[1:])
+
+ if opts.chdir:
+ os.chdir(opts.chdir)
+
+ if opts.path:
+ extra_path = [os.path.abspath(p) for p in opts.path]
+ extra_path = os.pathsep.join(extra_path)
+ os.environ['PATH'] += os.pathsep + extra_path
+
+ if not args:
+ if not opts.all:
+ sys.stderr.write('Specify -a to get all tests.\n')
+ return 1
+ args = ['test']
+
+ tests = []
+ for arg in args:
+ if os.path.isdir(arg):
+ tests.extend(find_all_gyptest_files(os.path.normpath(arg)))
+ else:
+ tests.append(arg)
+
+ if opts.list:
+ for test in tests:
+ print test
+ sys.exit(0)
+
+ CommandRunner.verbose = not opts.quiet
+ CommandRunner.active = not opts.no_exec
+ cr = CommandRunner()
+
+ os.environ['PYTHONPATH'] = os.path.abspath('test/lib')
+ if not opts.quiet:
+ sys.stdout.write('PYTHONPATH=%s\n' % os.environ['PYTHONPATH'])
+
+ passed = []
+ failed = []
+ no_result = []
+
+ if opts.format:
+ format_list = opts.format.split(',')
+ else:
+ # TODO: not duplicate this mapping from pylib/gyp/__init__.py
+ format_list = {
+ 'freebsd7': ['make'],
+ 'freebsd8': ['make'],
+ 'openbsd5': ['make'],
+ 'cygwin': ['msvs'],
+ 'win32': ['msvs', 'ninja'],
+ 'linux2': ['make', 'ninja'],
+ 'linux3': ['make', 'ninja'],
+ 'darwin': ['make', 'ninja', 'xcode'],
+ }[sys.platform]
+
+ for format in format_list:
+ os.environ['TESTGYP_FORMAT'] = format
+ if not opts.quiet:
+ sys.stdout.write('TESTGYP_FORMAT=%s\n' % format)
+
+ gyp_options = []
+ for option in opts.gyp_option:
+ gyp_options += ['-G', option]
+ if gyp_options and not opts.quiet:
+ sys.stdout.write('Extra Gyp options: %s\n' % gyp_options)
+
+ for test in tests:
+ status = cr.run([sys.executable, test] + gyp_options,
+ stdout=sys.stdout,
+ stderr=sys.stderr)
+ if status == 2:
+ no_result.append(test)
+ elif status:
+ failed.append(test)
+ else:
+ passed.append(test)
+
+ if not opts.quiet:
+ def report(description, tests):
+ if tests:
+ if len(tests) == 1:
+ sys.stdout.write("\n%s the following test:\n" % description)
+ else:
+ fmt = "\n%s the following %d tests:\n"
+ sys.stdout.write(fmt % (description, len(tests)))
+ sys.stdout.write("\t" + "\n\t".join(tests) + "\n")
+
+ if opts.passed:
+ report("Passed", passed)
+ report("Failed", failed)
+ report("No result from", no_result)
+
+ if failed:
+ return 1
+ else:
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSNew.py b/chromium/tools/gyp/pylib/gyp/MSVSNew.py
new file mode 100644
index 00000000000..667e531c99f
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/MSVSNew.py
@@ -0,0 +1,339 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""New implementation of Visual Studio project generation."""
+
+import os
+import random
+
+import gyp.common
+
+# hashlib is supplied as of Python 2.5 as the replacement interface for md5
+# and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if
+# available, avoiding a deprecation warning under 2.6. Import md5 otherwise,
+# preserving 2.4 compatibility.
+try:
+ import hashlib
+ _new_md5 = hashlib.md5
+except ImportError:
+ import md5
+ _new_md5 = md5.new
+
+
+# Initialize random number generator
+random.seed()
+
+# GUIDs for project types
+ENTRY_TYPE_GUIDS = {
+ 'project': '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}',
+ 'folder': '{2150E333-8FDC-42A3-9474-1A3956D46DE8}',
+}
+
+#------------------------------------------------------------------------------
+# Helper functions
+
+
+def MakeGuid(name, seed='msvs_new'):
+ """Returns a GUID for the specified target name.
+
+ Args:
+ name: Target name.
+ seed: Seed for MD5 hash.
+ Returns:
+ A GUID-line string calculated from the name and seed.
+
+ This generates something which looks like a GUID, but depends only on the
+ name and seed. This means the same name/seed will always generate the same
+ GUID, so that projects and solutions which refer to each other can explicitly
+ determine the GUID to refer to explicitly. It also means that the GUID will
+ not change when the project for a target is rebuilt.
+ """
+ # Calculate a MD5 signature for the seed and name.
+ d = _new_md5(str(seed) + str(name)).hexdigest().upper()
+ # Convert most of the signature to GUID form (discard the rest)
+ guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20]
+ + '-' + d[20:32] + '}')
+ return guid
+
+#------------------------------------------------------------------------------
+
+
+class MSVSSolutionEntry(object):
+ def __cmp__(self, other):
+ # Sort by name then guid (so things are in order on vs2008).
+ return cmp((self.name, self.get_guid()), (other.name, other.get_guid()))
+
+
+class MSVSFolder(MSVSSolutionEntry):
+ """Folder in a Visual Studio project or solution."""
+
+ def __init__(self, path, name = None, entries = None,
+ guid = None, items = None):
+ """Initializes the folder.
+
+ Args:
+ path: Full path to the folder.
+ name: Name of the folder.
+ entries: List of folder entries to nest inside this folder. May contain
+ Folder or Project objects. May be None, if the folder is empty.
+ guid: GUID to use for folder, if not None.
+ items: List of solution items to include in the folder project. May be
+ None, if the folder does not directly contain items.
+ """
+ if name:
+ self.name = name
+ else:
+ # Use last layer.
+ self.name = os.path.basename(path)
+
+ self.path = path
+ self.guid = guid
+
+ # Copy passed lists (or set to empty lists)
+ self.entries = sorted(list(entries or []))
+ self.items = list(items or [])
+
+ self.entry_type_guid = ENTRY_TYPE_GUIDS['folder']
+
+ def get_guid(self):
+ if self.guid is None:
+ # Use consistent guids for folders (so things don't regenerate).
+ self.guid = MakeGuid(self.path, seed='msvs_folder')
+ return self.guid
+
+
+#------------------------------------------------------------------------------
+
+
+class MSVSProject(MSVSSolutionEntry):
+ """Visual Studio project."""
+
+ def __init__(self, path, name = None, dependencies = None, guid = None,
+ spec = None, build_file = None, config_platform_overrides = None,
+ fixpath_prefix = None):
+ """Initializes the project.
+
+ Args:
+ path: Absolute path to the project file.
+ name: Name of project. If None, the name will be the same as the base
+ name of the project file.
+ dependencies: List of other Project objects this project is dependent
+ upon, if not None.
+ guid: GUID to use for project, if not None.
+ spec: Dictionary specifying how to build this project.
+ build_file: Filename of the .gyp file that the vcproj file comes from.
+ config_platform_overrides: optional dict of configuration platforms to
+ used in place of the default for this target.
+ fixpath_prefix: the path used to adjust the behavior of _fixpath
+ """
+ self.path = path
+ self.guid = guid
+ self.spec = spec
+ self.build_file = build_file
+ # Use project filename if name not specified
+ self.name = name or os.path.splitext(os.path.basename(path))[0]
+
+ # Copy passed lists (or set to empty lists)
+ self.dependencies = list(dependencies or [])
+
+ self.entry_type_guid = ENTRY_TYPE_GUIDS['project']
+
+ if config_platform_overrides:
+ self.config_platform_overrides = config_platform_overrides
+ else:
+ self.config_platform_overrides = {}
+ self.fixpath_prefix = fixpath_prefix
+ self.msbuild_toolset = None
+
+ def set_dependencies(self, dependencies):
+ self.dependencies = list(dependencies or [])
+
+ def get_guid(self):
+ if self.guid is None:
+ # Set GUID from path
+ # TODO(rspangler): This is fragile.
+ # 1. We can't just use the project filename sans path, since there could
+ # be multiple projects with the same base name (for example,
+ # foo/unittest.vcproj and bar/unittest.vcproj).
+ # 2. The path needs to be relative to $SOURCE_ROOT, so that the project
+ # GUID is the same whether it's included from base/base.sln or
+ # foo/bar/baz/baz.sln.
+ # 3. The GUID needs to be the same each time this builder is invoked, so
+ # that we don't need to rebuild the solution when the project changes.
+ # 4. We should be able to handle pre-built project files by reading the
+ # GUID from the files.
+ self.guid = MakeGuid(self.name)
+ return self.guid
+
+ def set_msbuild_toolset(self, msbuild_toolset):
+ self.msbuild_toolset = msbuild_toolset
+
+#------------------------------------------------------------------------------
+
+
+class MSVSSolution:
+ """Visual Studio solution."""
+
+ def __init__(self, path, version, entries=None, variants=None,
+ websiteProperties=True):
+ """Initializes the solution.
+
+ Args:
+ path: Path to solution file.
+ version: Format version to emit.
+ entries: List of entries in solution. May contain Folder or Project
+ objects. May be None, if the folder is empty.
+ variants: List of build variant strings. If none, a default list will
+ be used.
+ websiteProperties: Flag to decide if the website properties section
+ is generated.
+ """
+ self.path = path
+ self.websiteProperties = websiteProperties
+ self.version = version
+
+ # Copy passed lists (or set to empty lists)
+ self.entries = list(entries or [])
+
+ if variants:
+ # Copy passed list
+ self.variants = variants[:]
+ else:
+ # Use default
+ self.variants = ['Debug|Win32', 'Release|Win32']
+ # TODO(rspangler): Need to be able to handle a mapping of solution config
+ # to project config. Should we be able to handle variants being a dict,
+ # or add a separate variant_map variable? If it's a dict, we can't
+ # guarantee the order of variants since dict keys aren't ordered.
+
+
+ # TODO(rspangler): Automatically write to disk for now; should delay until
+ # node-evaluation time.
+ self.Write()
+
+
+ def Write(self, writer=gyp.common.WriteOnDiff):
+ """Writes the solution file to disk.
+
+ Raises:
+ IndexError: An entry appears multiple times.
+ """
+ # Walk the entry tree and collect all the folders and projects.
+ all_entries = set()
+ entries_to_check = self.entries[:]
+ while entries_to_check:
+ e = entries_to_check.pop(0)
+
+ # If this entry has been visited, nothing to do.
+ if e in all_entries:
+ continue
+
+ all_entries.add(e)
+
+ # If this is a folder, check its entries too.
+ if isinstance(e, MSVSFolder):
+ entries_to_check += e.entries
+
+ all_entries = sorted(all_entries)
+
+ # Open file and print header
+ f = writer(self.path)
+ f.write('Microsoft Visual Studio Solution File, '
+ 'Format Version %s\r\n' % self.version.SolutionVersion())
+ f.write('# %s\r\n' % self.version.Description())
+
+ # Project entries
+ sln_root = os.path.split(self.path)[0]
+ for e in all_entries:
+ relative_path = gyp.common.RelativePath(e.path, sln_root)
+ # msbuild does not accept an empty folder_name.
+ # use '.' in case relative_path is empty.
+ folder_name = relative_path.replace('/', '\\') or '.'
+ f.write('Project("%s") = "%s", "%s", "%s"\r\n' % (
+ e.entry_type_guid, # Entry type GUID
+ e.name, # Folder name
+ folder_name, # Folder name (again)
+ e.get_guid(), # Entry GUID
+ ))
+
+ # TODO(rspangler): Need a way to configure this stuff
+ if self.websiteProperties:
+ f.write('\tProjectSection(WebsiteProperties) = preProject\r\n'
+ '\t\tDebug.AspNetCompiler.Debug = "True"\r\n'
+ '\t\tRelease.AspNetCompiler.Debug = "False"\r\n'
+ '\tEndProjectSection\r\n')
+
+ if isinstance(e, MSVSFolder):
+ if e.items:
+ f.write('\tProjectSection(SolutionItems) = preProject\r\n')
+ for i in e.items:
+ f.write('\t\t%s = %s\r\n' % (i, i))
+ f.write('\tEndProjectSection\r\n')
+
+ if isinstance(e, MSVSProject):
+ if e.dependencies:
+ f.write('\tProjectSection(ProjectDependencies) = postProject\r\n')
+ for d in e.dependencies:
+ f.write('\t\t%s = %s\r\n' % (d.get_guid(), d.get_guid()))
+ f.write('\tEndProjectSection\r\n')
+
+ f.write('EndProject\r\n')
+
+ # Global section
+ f.write('Global\r\n')
+
+ # Configurations (variants)
+ f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n')
+ for v in self.variants:
+ f.write('\t\t%s = %s\r\n' % (v, v))
+ f.write('\tEndGlobalSection\r\n')
+
+ # Sort config guids for easier diffing of solution changes.
+ config_guids = []
+ config_guids_overrides = {}
+ for e in all_entries:
+ if isinstance(e, MSVSProject):
+ config_guids.append(e.get_guid())
+ config_guids_overrides[e.get_guid()] = e.config_platform_overrides
+ config_guids.sort()
+
+ f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n')
+ for g in config_guids:
+ for v in self.variants:
+ nv = config_guids_overrides[g].get(v, v)
+ # Pick which project configuration to build for this solution
+ # configuration.
+ f.write('\t\t%s.%s.ActiveCfg = %s\r\n' % (
+ g, # Project GUID
+ v, # Solution build configuration
+ nv, # Project build config for that solution config
+ ))
+
+ # Enable project in this solution configuration.
+ f.write('\t\t%s.%s.Build.0 = %s\r\n' % (
+ g, # Project GUID
+ v, # Solution build configuration
+ nv, # Project build config for that solution config
+ ))
+ f.write('\tEndGlobalSection\r\n')
+
+ # TODO(rspangler): Should be able to configure this stuff too (though I've
+ # never seen this be any different)
+ f.write('\tGlobalSection(SolutionProperties) = preSolution\r\n')
+ f.write('\t\tHideSolutionNode = FALSE\r\n')
+ f.write('\tEndGlobalSection\r\n')
+
+ # Folder mappings
+ # TODO(rspangler): Should omit this section if there are no folders
+ f.write('\tGlobalSection(NestedProjects) = preSolution\r\n')
+ for e in all_entries:
+ if not isinstance(e, MSVSFolder):
+ continue # Does not apply to projects, only folders
+ for subentry in e.entries:
+ f.write('\t\t%s = %s\r\n' % (subentry.get_guid(), e.get_guid()))
+ f.write('\tEndGlobalSection\r\n')
+
+ f.write('EndGlobal\r\n')
+
+ f.close()
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSProject.py b/chromium/tools/gyp/pylib/gyp/MSVSProject.py
new file mode 100644
index 00000000000..db1ceede344
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/MSVSProject.py
@@ -0,0 +1,208 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Visual Studio project reader/writer."""
+
+import gyp.common
+import gyp.easy_xml as easy_xml
+
+#------------------------------------------------------------------------------
+
+
+class Tool(object):
+ """Visual Studio tool."""
+
+ def __init__(self, name, attrs=None):
+ """Initializes the tool.
+
+ Args:
+ name: Tool name.
+ attrs: Dict of tool attributes; may be None.
+ """
+ self._attrs = attrs or {}
+ self._attrs['Name'] = name
+
+ def _GetSpecification(self):
+ """Creates an element for the tool.
+
+ Returns:
+ A new xml.dom.Element for the tool.
+ """
+ return ['Tool', self._attrs]
+
+class Filter(object):
+ """Visual Studio filter - that is, a virtual folder."""
+
+ def __init__(self, name, contents=None):
+ """Initializes the folder.
+
+ Args:
+ name: Filter (folder) name.
+ contents: List of filenames and/or Filter objects contained.
+ """
+ self.name = name
+ self.contents = list(contents or [])
+
+
+#------------------------------------------------------------------------------
+
+
+class Writer(object):
+ """Visual Studio XML project writer."""
+
+ def __init__(self, project_path, version, name, guid=None, platforms=None):
+ """Initializes the project.
+
+ Args:
+ project_path: Path to the project file.
+ version: Format version to emit.
+ name: Name of the project.
+ guid: GUID to use for project, if not None.
+ platforms: Array of string, the supported platforms. If null, ['Win32']
+ """
+ self.project_path = project_path
+ self.version = version
+ self.name = name
+ self.guid = guid
+
+ # Default to Win32 for platforms.
+ if not platforms:
+ platforms = ['Win32']
+
+ # Initialize the specifications of the various sections.
+ self.platform_section = ['Platforms']
+ for platform in platforms:
+ self.platform_section.append(['Platform', {'Name': platform}])
+ self.tool_files_section = ['ToolFiles']
+ self.configurations_section = ['Configurations']
+ self.files_section = ['Files']
+
+ # Keep a dict keyed on filename to speed up access.
+ self.files_dict = dict()
+
+ def AddToolFile(self, path):
+ """Adds a tool file to the project.
+
+ Args:
+ path: Relative path from project to tool file.
+ """
+ self.tool_files_section.append(['ToolFile', {'RelativePath': path}])
+
+ def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools):
+ """Returns the specification for a configuration.
+
+ Args:
+ config_type: Type of configuration node.
+ config_name: Configuration name.
+ attrs: Dict of configuration attributes; may be None.
+ tools: List of tools (strings or Tool objects); may be None.
+ Returns:
+ """
+ # Handle defaults
+ if not attrs:
+ attrs = {}
+ if not tools:
+ tools = []
+
+ # Add configuration node and its attributes
+ node_attrs = attrs.copy()
+ node_attrs['Name'] = config_name
+ specification = [config_type, node_attrs]
+
+ # Add tool nodes and their attributes
+ if tools:
+ for t in tools:
+ if isinstance(t, Tool):
+ specification.append(t._GetSpecification())
+ else:
+ specification.append(Tool(t)._GetSpecification())
+ return specification
+
+
+ def AddConfig(self, name, attrs=None, tools=None):
+ """Adds a configuration to the project.
+
+ Args:
+ name: Configuration name.
+ attrs: Dict of configuration attributes; may be None.
+ tools: List of tools (strings or Tool objects); may be None.
+ """
+ spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools)
+ self.configurations_section.append(spec)
+
+ def _AddFilesToNode(self, parent, files):
+ """Adds files and/or filters to the parent node.
+
+ Args:
+ parent: Destination node
+ files: A list of Filter objects and/or relative paths to files.
+
+ Will call itself recursively, if the files list contains Filter objects.
+ """
+ for f in files:
+ if isinstance(f, Filter):
+ node = ['Filter', {'Name': f.name}]
+ self._AddFilesToNode(node, f.contents)
+ else:
+ node = ['File', {'RelativePath': f}]
+ self.files_dict[f] = node
+ parent.append(node)
+
+ def AddFiles(self, files):
+ """Adds files to the project.
+
+ Args:
+ files: A list of Filter objects and/or relative paths to files.
+
+ This makes a copy of the file/filter tree at the time of this call. If you
+ later add files to a Filter object which was passed into a previous call
+ to AddFiles(), it will not be reflected in this project.
+ """
+ self._AddFilesToNode(self.files_section, files)
+ # TODO(rspangler) This also doesn't handle adding files to an existing
+ # filter. That is, it doesn't merge the trees.
+
+ def AddFileConfig(self, path, config, attrs=None, tools=None):
+ """Adds a configuration to a file.
+
+ Args:
+ path: Relative path to the file.
+ config: Name of configuration to add.
+ attrs: Dict of configuration attributes; may be None.
+ tools: List of tools (strings or Tool objects); may be None.
+
+ Raises:
+ ValueError: Relative path does not match any file added via AddFiles().
+ """
+ # Find the file node with the right relative path
+ parent = self.files_dict.get(path)
+ if not parent:
+ raise ValueError('AddFileConfig: file "%s" not in project.' % path)
+
+ # Add the config to the file node
+ spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs,
+ tools)
+ parent.append(spec)
+
+ def WriteIfChanged(self):
+ """Writes the project file."""
+ # First create XML content definition
+ content = [
+ 'VisualStudioProject',
+ {'ProjectType': 'Visual C++',
+ 'Version': self.version.ProjectVersion(),
+ 'Name': self.name,
+ 'ProjectGUID': self.guid,
+ 'RootNamespace': self.name,
+ 'Keyword': 'Win32Proj'
+ },
+ self.platform_section,
+ self.tool_files_section,
+ self.configurations_section,
+ ['References'], # empty section
+ self.files_section,
+ ['Globals'] # empty section
+ ]
+ easy_xml.WriteXmlIfChanged(content, self.project_path,
+ encoding="Windows-1252")
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSSettings.py b/chromium/tools/gyp/pylib/gyp/MSVSSettings.py
new file mode 100644
index 00000000000..e8be3862888
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/MSVSSettings.py
@@ -0,0 +1,1051 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Code to validate and convert settings of the Microsoft build tools.
+
+This file contains code to validate and convert settings of the Microsoft
+build tools. The function ConvertToMSBuildSettings(), ValidateMSVSSettings(),
+and ValidateMSBuildSettings() are the entry points.
+
+This file was created by comparing the projects created by Visual Studio 2008
+and Visual Studio 2010 for all available settings through the user interface.
+The MSBuild schemas were also considered. They are typically found in the
+MSBuild install directory, e.g. c:\Program Files (x86)\MSBuild
+"""
+
+import sys
+import re
+
+# Dictionaries of settings validators. The key is the tool name, the value is
+# a dictionary mapping setting names to validation functions.
+_msvs_validators = {}
+_msbuild_validators = {}
+
+
+# A dictionary of settings converters. The key is the tool name, the value is
+# a dictionary mapping setting names to conversion functions.
+_msvs_to_msbuild_converters = {}
+
+
+# Tool name mapping from MSVS to MSBuild.
+_msbuild_name_of_tool = {}
+
+
+class _Tool(object):
+ """Represents a tool used by MSVS or MSBuild.
+
+ Attributes:
+ msvs_name: The name of the tool in MSVS.
+ msbuild_name: The name of the tool in MSBuild.
+ """
+
+ def __init__(self, msvs_name, msbuild_name):
+ self.msvs_name = msvs_name
+ self.msbuild_name = msbuild_name
+
+
+def _AddTool(tool):
+ """Adds a tool to the four dictionaries used to process settings.
+
+ This only defines the tool. Each setting also needs to be added.
+
+ Args:
+ tool: The _Tool object to be added.
+ """
+ _msvs_validators[tool.msvs_name] = {}
+ _msbuild_validators[tool.msbuild_name] = {}
+ _msvs_to_msbuild_converters[tool.msvs_name] = {}
+ _msbuild_name_of_tool[tool.msvs_name] = tool.msbuild_name
+
+
+def _GetMSBuildToolSettings(msbuild_settings, tool):
+ """Returns an MSBuild tool dictionary. Creates it if needed."""
+ return msbuild_settings.setdefault(tool.msbuild_name, {})
+
+
+class _Type(object):
+ """Type of settings (Base class)."""
+
+ def ValidateMSVS(self, value):
+ """Verifies that the value is legal for MSVS.
+
+ Args:
+ value: the value to check for this type.
+
+ Raises:
+ ValueError if value is not valid for MSVS.
+ """
+
+ def ValidateMSBuild(self, value):
+ """Verifies that the value is legal for MSBuild.
+
+ Args:
+ value: the value to check for this type.
+
+ Raises:
+ ValueError if value is not valid for MSBuild.
+ """
+
+ def ConvertToMSBuild(self, value):
+ """Returns the MSBuild equivalent of the MSVS value given.
+
+ Args:
+ value: the MSVS value to convert.
+
+ Returns:
+ the MSBuild equivalent.
+
+ Raises:
+ ValueError if value is not valid.
+ """
+ return value
+
+
+class _String(_Type):
+ """A setting that's just a string."""
+
+ def ValidateMSVS(self, value):
+ if not isinstance(value, basestring):
+ raise ValueError('expected string; got %r' % value)
+
+ def ValidateMSBuild(self, value):
+ if not isinstance(value, basestring):
+ raise ValueError('expected string; got %r' % value)
+
+ def ConvertToMSBuild(self, value):
+ # Convert the macros
+ return ConvertVCMacrosToMSBuild(value)
+
+
+class _StringList(_Type):
+ """A settings that's a list of strings."""
+
+ def ValidateMSVS(self, value):
+ if not isinstance(value, basestring) and not isinstance(value, list):
+ raise ValueError('expected string list; got %r' % value)
+
+ def ValidateMSBuild(self, value):
+ if not isinstance(value, basestring) and not isinstance(value, list):
+ raise ValueError('expected string list; got %r' % value)
+
+ def ConvertToMSBuild(self, value):
+ # Convert the macros
+ if isinstance(value, list):
+ return [ConvertVCMacrosToMSBuild(i) for i in value]
+ else:
+ return ConvertVCMacrosToMSBuild(value)
+
+
+class _Boolean(_Type):
+ """Boolean settings, can have the values 'false' or 'true'."""
+
+ def _Validate(self, value):
+ if value != 'true' and value != 'false':
+ raise ValueError('expected bool; got %r' % value)
+
+ def ValidateMSVS(self, value):
+ self._Validate(value)
+
+ def ValidateMSBuild(self, value):
+ self._Validate(value)
+
+ def ConvertToMSBuild(self, value):
+ self._Validate(value)
+ return value
+
+
+class _Integer(_Type):
+ """Integer settings."""
+
+ def __init__(self, msbuild_base=10):
+ _Type.__init__(self)
+ self._msbuild_base = msbuild_base
+
+ def ValidateMSVS(self, value):
+ # Try to convert, this will raise ValueError if invalid.
+ self.ConvertToMSBuild(value)
+
+ def ValidateMSBuild(self, value):
+ # Try to convert, this will raise ValueError if invalid.
+ int(value, self._msbuild_base)
+
+ def ConvertToMSBuild(self, value):
+ msbuild_format = (self._msbuild_base == 10) and '%d' or '0x%04x'
+ return msbuild_format % int(value)
+
+
+class _Enumeration(_Type):
+ """Type of settings that is an enumeration.
+
+ In MSVS, the values are indexes like '0', '1', and '2'.
+ MSBuild uses text labels that are more representative, like 'Win32'.
+
+ Constructor args:
+ label_list: an array of MSBuild labels that correspond to the MSVS index.
+ In the rare cases where MSVS has skipped an index value, None is
+ used in the array to indicate the unused spot.
+ new: an array of labels that are new to MSBuild.
+ """
+
+ def __init__(self, label_list, new=None):
+ _Type.__init__(self)
+ self._label_list = label_list
+ self._msbuild_values = set(value for value in label_list
+ if value is not None)
+ if new is not None:
+ self._msbuild_values.update(new)
+
+ def ValidateMSVS(self, value):
+ # Try to convert. It will raise an exception if not valid.
+ self.ConvertToMSBuild(value)
+
+ def ValidateMSBuild(self, value):
+ if value not in self._msbuild_values:
+ raise ValueError('unrecognized enumerated value %s' % value)
+
+ def ConvertToMSBuild(self, value):
+ index = int(value)
+ if index < 0 or index >= len(self._label_list):
+ raise ValueError('index value (%d) not in expected range [0, %d)' %
+ (index, len(self._label_list)))
+ label = self._label_list[index]
+ if label is None:
+ raise ValueError('converted value for %s not specified.' % value)
+ return label
+
+
+# Instantiate the various generic types.
+_boolean = _Boolean()
+_integer = _Integer()
+# For now, we don't do any special validation on these types:
+_string = _String()
+_file_name = _String()
+_folder_name = _String()
+_file_list = _StringList()
+_folder_list = _StringList()
+_string_list = _StringList()
+# Some boolean settings went from numerical values to boolean. The
+# mapping is 0: default, 1: false, 2: true.
+_newly_boolean = _Enumeration(['', 'false', 'true'])
+
+
+def _Same(tool, name, setting_type):
+ """Defines a setting that has the same name in MSVS and MSBuild.
+
+ Args:
+ tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+ name: the name of the setting.
+ setting_type: the type of this setting.
+ """
+ _Renamed(tool, name, name, setting_type)
+
+
+def _Renamed(tool, msvs_name, msbuild_name, setting_type):
+ """Defines a setting for which the name has changed.
+
+ Args:
+ tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+ msvs_name: the name of the MSVS setting.
+ msbuild_name: the name of the MSBuild setting.
+ setting_type: the type of this setting.
+ """
+
+ def _Translate(value, msbuild_settings):
+ msbuild_tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
+ msbuild_tool_settings[msbuild_name] = setting_type.ConvertToMSBuild(value)
+
+ _msvs_validators[tool.msvs_name][msvs_name] = setting_type.ValidateMSVS
+ _msbuild_validators[tool.msbuild_name][msbuild_name] = (
+ setting_type.ValidateMSBuild)
+ _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
+
+
+def _Moved(tool, settings_name, msbuild_tool_name, setting_type):
+ _MovedAndRenamed(tool, settings_name, msbuild_tool_name, settings_name,
+ setting_type)
+
+
+def _MovedAndRenamed(tool, msvs_settings_name, msbuild_tool_name,
+ msbuild_settings_name, setting_type):
+ """Defines a setting that may have moved to a new section.
+
+ Args:
+ tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+ msvs_settings_name: the MSVS name of the setting.
+ msbuild_tool_name: the name of the MSBuild tool to place the setting under.
+ msbuild_settings_name: the MSBuild name of the setting.
+ setting_type: the type of this setting.
+ """
+
+ def _Translate(value, msbuild_settings):
+ tool_settings = msbuild_settings.setdefault(msbuild_tool_name, {})
+ tool_settings[msbuild_settings_name] = setting_type.ConvertToMSBuild(value)
+
+ _msvs_validators[tool.msvs_name][msvs_settings_name] = (
+ setting_type.ValidateMSVS)
+ validator = setting_type.ValidateMSBuild
+ _msbuild_validators[msbuild_tool_name][msbuild_settings_name] = validator
+ _msvs_to_msbuild_converters[tool.msvs_name][msvs_settings_name] = _Translate
+
+
+def _MSVSOnly(tool, name, setting_type):
+ """Defines a setting that is only found in MSVS.
+
+ Args:
+ tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+ name: the name of the setting.
+ setting_type: the type of this setting.
+ """
+
+ def _Translate(unused_value, unused_msbuild_settings):
+ # Since this is for MSVS only settings, no translation will happen.
+ pass
+
+ _msvs_validators[tool.msvs_name][name] = setting_type.ValidateMSVS
+ _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate
+
+
+def _MSBuildOnly(tool, name, setting_type):
+ """Defines a setting that is only found in MSBuild.
+
+ Args:
+ tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+ name: the name of the setting.
+ setting_type: the type of this setting.
+ """
+ _msbuild_validators[tool.msbuild_name][name] = setting_type.ValidateMSBuild
+
+
+def _ConvertedToAdditionalOption(tool, msvs_name, flag):
+ """Defines a setting that's handled via a command line option in MSBuild.
+
+ Args:
+ tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+ msvs_name: the name of the MSVS setting that if 'true' becomes a flag
+ flag: the flag to insert at the end of the AdditionalOptions
+ """
+
+ def _Translate(value, msbuild_settings):
+ if value == 'true':
+ tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
+ if 'AdditionalOptions' in tool_settings:
+ new_flags = '%s %s' % (tool_settings['AdditionalOptions'], flag)
+ else:
+ new_flags = flag
+ tool_settings['AdditionalOptions'] = new_flags
+ _msvs_validators[tool.msvs_name][msvs_name] = _boolean.ValidateMSVS
+ _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
+
+
+def _CustomGeneratePreprocessedFile(tool, msvs_name):
+ def _Translate(value, msbuild_settings):
+ tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
+ if value == '0':
+ tool_settings['PreprocessToFile'] = 'false'
+ tool_settings['PreprocessSuppressLineNumbers'] = 'false'
+ elif value == '1': # /P
+ tool_settings['PreprocessToFile'] = 'true'
+ tool_settings['PreprocessSuppressLineNumbers'] = 'false'
+ elif value == '2': # /EP /P
+ tool_settings['PreprocessToFile'] = 'true'
+ tool_settings['PreprocessSuppressLineNumbers'] = 'true'
+ else:
+ raise ValueError('value must be one of [0, 1, 2]; got %s' % value)
+ # Create a bogus validator that looks for '0', '1', or '2'
+ msvs_validator = _Enumeration(['a', 'b', 'c']).ValidateMSVS
+ _msvs_validators[tool.msvs_name][msvs_name] = msvs_validator
+ msbuild_validator = _boolean.ValidateMSBuild
+ msbuild_tool_validators = _msbuild_validators[tool.msbuild_name]
+ msbuild_tool_validators['PreprocessToFile'] = msbuild_validator
+ msbuild_tool_validators['PreprocessSuppressLineNumbers'] = msbuild_validator
+ _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
+
+
+fix_vc_macro_slashes_regex_list = ('IntDir', 'OutDir')
+fix_vc_macro_slashes_regex = re.compile(
+ r'(\$\((?:%s)\))(?:[\\/]+)' % "|".join(fix_vc_macro_slashes_regex_list)
+)
+
+def FixVCMacroSlashes(s):
+ """Replace macros which have excessive following slashes.
+
+ These macros are known to have a built-in trailing slash. Furthermore, many
+ scripts hiccup on processing paths with extra slashes in the middle.
+
+ This list is probably not exhaustive. Add as needed.
+ """
+ if '$' in s:
+ s = fix_vc_macro_slashes_regex.sub(r'\1', s)
+ return s
+
+
+def ConvertVCMacrosToMSBuild(s):
+ """Convert the the MSVS macros found in the string to the MSBuild equivalent.
+
+ This list is probably not exhaustive. Add as needed.
+ """
+ if '$' in s:
+ replace_map = {
+ '$(ConfigurationName)': '$(Configuration)',
+ '$(InputDir)': '%(RootDir)%(Directory)',
+ '$(InputExt)': '%(Extension)',
+ '$(InputFileName)': '%(Filename)%(Extension)',
+ '$(InputName)': '%(Filename)',
+ '$(InputPath)': '%(FullPath)',
+ '$(ParentName)': '$(ProjectFileName)',
+ '$(PlatformName)': '$(Platform)',
+ '$(SafeInputName)': '%(Filename)',
+ }
+ for old, new in replace_map.iteritems():
+ s = s.replace(old, new)
+ s = FixVCMacroSlashes(s)
+ return s
+
+
+def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr):
+ """Converts MSVS settings (VS2008 and earlier) to MSBuild settings (VS2010+).
+
+ Args:
+ msvs_settings: A dictionary. The key is the tool name. The values are
+ themselves dictionaries of settings and their values.
+ stderr: The stream receiving the error messages.
+
+ Returns:
+ A dictionary of MSBuild settings. The key is either the MSBuild tool name
+ or the empty string (for the global settings). The values are themselves
+ dictionaries of settings and their values.
+ """
+ msbuild_settings = {}
+ for msvs_tool_name, msvs_tool_settings in msvs_settings.iteritems():
+ if msvs_tool_name in _msvs_to_msbuild_converters:
+ msvs_tool = _msvs_to_msbuild_converters[msvs_tool_name]
+ for msvs_setting, msvs_value in msvs_tool_settings.iteritems():
+ if msvs_setting in msvs_tool:
+ # Invoke the translation function.
+ try:
+ msvs_tool[msvs_setting](msvs_value, msbuild_settings)
+ except ValueError, e:
+ print >> stderr, ('Warning: while converting %s/%s to MSBuild, '
+ '%s' % (msvs_tool_name, msvs_setting, e))
+ else:
+ # We don't know this setting. Give a warning.
+ print >> stderr, ('Warning: unrecognized setting %s/%s '
+ 'while converting to MSBuild.' %
+ (msvs_tool_name, msvs_setting))
+ else:
+ print >> stderr, ('Warning: unrecognized tool %s while converting to '
+ 'MSBuild.' % msvs_tool_name)
+ return msbuild_settings
+
+
+def ValidateMSVSSettings(settings, stderr=sys.stderr):
+ """Validates that the names of the settings are valid for MSVS.
+
+ Args:
+ settings: A dictionary. The key is the tool name. The values are
+ themselves dictionaries of settings and their values.
+ stderr: The stream receiving the error messages.
+ """
+ _ValidateSettings(_msvs_validators, settings, stderr)
+
+
+def ValidateMSBuildSettings(settings, stderr=sys.stderr):
+ """Validates that the names of the settings are valid for MSBuild.
+
+ Args:
+ settings: A dictionary. The key is the tool name. The values are
+ themselves dictionaries of settings and their values.
+ stderr: The stream receiving the error messages.
+ """
+ _ValidateSettings(_msbuild_validators, settings, stderr)
+
+
+def _ValidateSettings(validators, settings, stderr):
+ """Validates that the settings are valid for MSBuild or MSVS.
+
+ We currently only validate the names of the settings, not their values.
+
+ Args:
+ validators: A dictionary of tools and their validators.
+ settings: A dictionary. The key is the tool name. The values are
+ themselves dictionaries of settings and their values.
+ stderr: The stream receiving the error messages.
+ """
+ for tool_name in settings:
+ if tool_name in validators:
+ tool_validators = validators[tool_name]
+ for setting, value in settings[tool_name].iteritems():
+ if setting in tool_validators:
+ try:
+ tool_validators[setting](value)
+ except ValueError, e:
+ print >> stderr, ('Warning: for %s/%s, %s' %
+ (tool_name, setting, e))
+ else:
+ print >> stderr, ('Warning: unrecognized setting %s/%s' %
+ (tool_name, setting))
+ else:
+ print >> stderr, ('Warning: unrecognized tool %s' % tool_name)
+
+
+# MSVS and MBuild names of the tools.
+_compile = _Tool('VCCLCompilerTool', 'ClCompile')
+_link = _Tool('VCLinkerTool', 'Link')
+_midl = _Tool('VCMIDLTool', 'Midl')
+_rc = _Tool('VCResourceCompilerTool', 'ResourceCompile')
+_lib = _Tool('VCLibrarianTool', 'Lib')
+_manifest = _Tool('VCManifestTool', 'Manifest')
+
+
+_AddTool(_compile)
+_AddTool(_link)
+_AddTool(_midl)
+_AddTool(_rc)
+_AddTool(_lib)
+_AddTool(_manifest)
+# Add sections only found in the MSBuild settings.
+_msbuild_validators[''] = {}
+_msbuild_validators['ProjectReference'] = {}
+_msbuild_validators['ManifestResourceCompile'] = {}
+
+# Descriptions of the compiler options, i.e. VCCLCompilerTool in MSVS and
+# ClCompile in MSBuild.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\cl.xml" for
+# the schema of the MSBuild ClCompile settings.
+
+# Options that have the same name in MSVS and MSBuild
+_Same(_compile, 'AdditionalIncludeDirectories', _folder_list) # /I
+_Same(_compile, 'AdditionalOptions', _string_list)
+_Same(_compile, 'AdditionalUsingDirectories', _folder_list) # /AI
+_Same(_compile, 'AssemblerListingLocation', _file_name) # /Fa
+_Same(_compile, 'BrowseInformationFile', _file_name)
+_Same(_compile, 'BufferSecurityCheck', _boolean) # /GS
+_Same(_compile, 'DisableLanguageExtensions', _boolean) # /Za
+_Same(_compile, 'DisableSpecificWarnings', _string_list) # /wd
+_Same(_compile, 'EnableFiberSafeOptimizations', _boolean) # /GT
+_Same(_compile, 'EnablePREfast', _boolean) # /analyze Visible='false'
+_Same(_compile, 'ExpandAttributedSource', _boolean) # /Fx
+_Same(_compile, 'FloatingPointExceptions', _boolean) # /fp:except
+_Same(_compile, 'ForceConformanceInForLoopScope', _boolean) # /Zc:forScope
+_Same(_compile, 'ForcedIncludeFiles', _file_list) # /FI
+_Same(_compile, 'ForcedUsingFiles', _file_list) # /FU
+_Same(_compile, 'GenerateXMLDocumentationFiles', _boolean) # /doc
+_Same(_compile, 'IgnoreStandardIncludePath', _boolean) # /X
+_Same(_compile, 'MinimalRebuild', _boolean) # /Gm
+_Same(_compile, 'OmitDefaultLibName', _boolean) # /Zl
+_Same(_compile, 'OmitFramePointers', _boolean) # /Oy
+_Same(_compile, 'PreprocessorDefinitions', _string_list) # /D
+_Same(_compile, 'ProgramDataBaseFileName', _file_name) # /Fd
+_Same(_compile, 'RuntimeTypeInfo', _boolean) # /GR
+_Same(_compile, 'ShowIncludes', _boolean) # /showIncludes
+_Same(_compile, 'SmallerTypeCheck', _boolean) # /RTCc
+_Same(_compile, 'StringPooling', _boolean) # /GF
+_Same(_compile, 'SuppressStartupBanner', _boolean) # /nologo
+_Same(_compile, 'TreatWChar_tAsBuiltInType', _boolean) # /Zc:wchar_t
+_Same(_compile, 'UndefineAllPreprocessorDefinitions', _boolean) # /u
+_Same(_compile, 'UndefinePreprocessorDefinitions', _string_list) # /U
+_Same(_compile, 'UseFullPaths', _boolean) # /FC
+_Same(_compile, 'WholeProgramOptimization', _boolean) # /GL
+_Same(_compile, 'XMLDocumentationFileName', _file_name)
+
+_Same(_compile, 'AssemblerOutput',
+ _Enumeration(['NoListing',
+ 'AssemblyCode', # /FA
+ 'All', # /FAcs
+ 'AssemblyAndMachineCode', # /FAc
+ 'AssemblyAndSourceCode'])) # /FAs
+_Same(_compile, 'BasicRuntimeChecks',
+ _Enumeration(['Default',
+ 'StackFrameRuntimeCheck', # /RTCs
+ 'UninitializedLocalUsageCheck', # /RTCu
+ 'EnableFastChecks'])) # /RTC1
+_Same(_compile, 'BrowseInformation',
+ _Enumeration(['false',
+ 'true', # /FR
+ 'true'])) # /Fr
+_Same(_compile, 'CallingConvention',
+ _Enumeration(['Cdecl', # /Gd
+ 'FastCall', # /Gr
+ 'StdCall'])) # /Gz
+_Same(_compile, 'CompileAs',
+ _Enumeration(['Default',
+ 'CompileAsC', # /TC
+ 'CompileAsCpp'])) # /TP
+_Same(_compile, 'DebugInformationFormat',
+ _Enumeration(['', # Disabled
+ 'OldStyle', # /Z7
+ None,
+ 'ProgramDatabase', # /Zi
+ 'EditAndContinue'])) # /ZI
+_Same(_compile, 'EnableEnhancedInstructionSet',
+ _Enumeration(['NotSet',
+ 'StreamingSIMDExtensions', # /arch:SSE
+ 'StreamingSIMDExtensions2'])) # /arch:SSE2
+_Same(_compile, 'ErrorReporting',
+ _Enumeration(['None', # /errorReport:none
+ 'Prompt', # /errorReport:prompt
+ 'Queue'], # /errorReport:queue
+ new=['Send'])) # /errorReport:send"
+_Same(_compile, 'ExceptionHandling',
+ _Enumeration(['false',
+ 'Sync', # /EHsc
+ 'Async'], # /EHa
+ new=['SyncCThrow'])) # /EHs
+_Same(_compile, 'FavorSizeOrSpeed',
+ _Enumeration(['Neither',
+ 'Speed', # /Ot
+ 'Size'])) # /Os
+_Same(_compile, 'FloatingPointModel',
+ _Enumeration(['Precise', # /fp:precise
+ 'Strict', # /fp:strict
+ 'Fast'])) # /fp:fast
+_Same(_compile, 'InlineFunctionExpansion',
+ _Enumeration(['Default',
+ 'OnlyExplicitInline', # /Ob1
+ 'AnySuitable'], # /Ob2
+ new=['Disabled'])) # /Ob0
+_Same(_compile, 'Optimization',
+ _Enumeration(['Disabled', # /Od
+ 'MinSpace', # /O1
+ 'MaxSpeed', # /O2
+ 'Full'])) # /Ox
+_Same(_compile, 'RuntimeLibrary',
+ _Enumeration(['MultiThreaded', # /MT
+ 'MultiThreadedDebug', # /MTd
+ 'MultiThreadedDLL', # /MD
+ 'MultiThreadedDebugDLL'])) # /MDd
+_Same(_compile, 'StructMemberAlignment',
+ _Enumeration(['Default',
+ '1Byte', # /Zp1
+ '2Bytes', # /Zp2
+ '4Bytes', # /Zp4
+ '8Bytes', # /Zp8
+ '16Bytes'])) # /Zp16
+_Same(_compile, 'WarningLevel',
+ _Enumeration(['TurnOffAllWarnings', # /W0
+ 'Level1', # /W1
+ 'Level2', # /W2
+ 'Level3', # /W3
+ 'Level4'], # /W4
+ new=['EnableAllWarnings'])) # /Wall
+
+# Options found in MSVS that have been renamed in MSBuild.
+_Renamed(_compile, 'EnableFunctionLevelLinking', 'FunctionLevelLinking',
+ _boolean) # /Gy
+_Renamed(_compile, 'EnableIntrinsicFunctions', 'IntrinsicFunctions',
+ _boolean) # /Oi
+_Renamed(_compile, 'KeepComments', 'PreprocessKeepComments', _boolean) # /C
+_Renamed(_compile, 'ObjectFile', 'ObjectFileName', _file_name) # /Fo
+_Renamed(_compile, 'OpenMP', 'OpenMPSupport', _boolean) # /openmp
+_Renamed(_compile, 'PrecompiledHeaderThrough', 'PrecompiledHeaderFile',
+ _file_name) # Used with /Yc and /Yu
+_Renamed(_compile, 'PrecompiledHeaderFile', 'PrecompiledHeaderOutputFile',
+ _file_name) # /Fp
+_Renamed(_compile, 'UsePrecompiledHeader', 'PrecompiledHeader',
+ _Enumeration(['NotUsing', # VS recognized '' for this value too.
+ 'Create', # /Yc
+ 'Use'])) # /Yu
+_Renamed(_compile, 'WarnAsError', 'TreatWarningAsError', _boolean) # /WX
+
+_ConvertedToAdditionalOption(_compile, 'DefaultCharIsUnsigned', '/J')
+
+# MSVS options not found in MSBuild.
+_MSVSOnly(_compile, 'Detect64BitPortabilityProblems', _boolean)
+_MSVSOnly(_compile, 'UseUnicodeResponseFiles', _boolean)
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_compile, 'BuildingInIDE', _boolean)
+_MSBuildOnly(_compile, 'CompileAsManaged',
+ _Enumeration([], new=['false',
+ 'true', # /clr
+ 'Pure', # /clr:pure
+ 'Safe', # /clr:safe
+ 'OldSyntax'])) # /clr:oldSyntax
+_MSBuildOnly(_compile, 'CreateHotpatchableImage', _boolean) # /hotpatch
+_MSBuildOnly(_compile, 'MultiProcessorCompilation', _boolean) # /MP
+_MSBuildOnly(_compile, 'PreprocessOutputPath', _string) # /Fi
+_MSBuildOnly(_compile, 'ProcessorNumber', _integer) # the number of processors
+_MSBuildOnly(_compile, 'TrackerLogDirectory', _folder_name)
+_MSBuildOnly(_compile, 'TreatSpecificWarningsAsErrors', _string_list) # /we
+_MSBuildOnly(_compile, 'UseUnicodeForAssemblerListing', _boolean) # /FAu
+
+# Defines a setting that needs very customized processing
+_CustomGeneratePreprocessedFile(_compile, 'GeneratePreprocessedFile')
+
+
+# Directives for converting MSVS VCLinkerTool to MSBuild Link.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\link.xml" for
+# the schema of the MSBuild Link settings.
+
+# Options that have the same name in MSVS and MSBuild
+_Same(_link, 'AdditionalDependencies', _file_list)
+_Same(_link, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH
+# /MANIFESTDEPENDENCY:
+_Same(_link, 'AdditionalManifestDependencies', _file_list)
+_Same(_link, 'AdditionalOptions', _string_list)
+_Same(_link, 'AddModuleNamesToAssembly', _file_list) # /ASSEMBLYMODULE
+_Same(_link, 'AllowIsolation', _boolean) # /ALLOWISOLATION
+_Same(_link, 'AssemblyLinkResource', _file_list) # /ASSEMBLYLINKRESOURCE
+_Same(_link, 'BaseAddress', _string) # /BASE
+_Same(_link, 'CLRUnmanagedCodeCheck', _boolean) # /CLRUNMANAGEDCODECHECK
+_Same(_link, 'DelayLoadDLLs', _file_list) # /DELAYLOAD
+_Same(_link, 'DelaySign', _boolean) # /DELAYSIGN
+_Same(_link, 'EmbedManagedResourceFile', _file_list) # /ASSEMBLYRESOURCE
+_Same(_link, 'EnableUAC', _boolean) # /MANIFESTUAC
+_Same(_link, 'EntryPointSymbol', _string) # /ENTRY
+_Same(_link, 'ForceSymbolReferences', _file_list) # /INCLUDE
+_Same(_link, 'FunctionOrder', _file_name) # /ORDER
+_Same(_link, 'GenerateDebugInformation', _boolean) # /DEBUG
+_Same(_link, 'GenerateMapFile', _boolean) # /MAP
+_Same(_link, 'HeapCommitSize', _string)
+_Same(_link, 'HeapReserveSize', _string) # /HEAP
+_Same(_link, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB
+_Same(_link, 'IgnoreEmbeddedIDL', _boolean) # /IGNOREIDL
+_Same(_link, 'ImportLibrary', _file_name) # /IMPLIB
+_Same(_link, 'KeyContainer', _file_name) # /KEYCONTAINER
+_Same(_link, 'KeyFile', _file_name) # /KEYFILE
+_Same(_link, 'ManifestFile', _file_name) # /ManifestFile
+_Same(_link, 'MapExports', _boolean) # /MAPINFO:EXPORTS
+_Same(_link, 'MapFileName', _file_name)
+_Same(_link, 'MergedIDLBaseFileName', _file_name) # /IDLOUT
+_Same(_link, 'MergeSections', _string) # /MERGE
+_Same(_link, 'MidlCommandFile', _file_name) # /MIDL
+_Same(_link, 'ModuleDefinitionFile', _file_name) # /DEF
+_Same(_link, 'OutputFile', _file_name) # /OUT
+_Same(_link, 'PerUserRedirection', _boolean)
+_Same(_link, 'Profile', _boolean) # /PROFILE
+_Same(_link, 'ProfileGuidedDatabase', _file_name) # /PGD
+_Same(_link, 'ProgramDatabaseFile', _file_name) # /PDB
+_Same(_link, 'RegisterOutput', _boolean)
+_Same(_link, 'SetChecksum', _boolean) # /RELEASE
+_Same(_link, 'StackCommitSize', _string)
+_Same(_link, 'StackReserveSize', _string) # /STACK
+_Same(_link, 'StripPrivateSymbols', _file_name) # /PDBSTRIPPED
+_Same(_link, 'SupportUnloadOfDelayLoadedDLL', _boolean) # /DELAY:UNLOAD
+_Same(_link, 'SuppressStartupBanner', _boolean) # /NOLOGO
+_Same(_link, 'SwapRunFromCD', _boolean) # /SWAPRUN:CD
+_Same(_link, 'TurnOffAssemblyGeneration', _boolean) # /NOASSEMBLY
+_Same(_link, 'TypeLibraryFile', _file_name) # /TLBOUT
+_Same(_link, 'TypeLibraryResourceID', _integer) # /TLBID
+_Same(_link, 'UACUIAccess', _boolean) # /uiAccess='true'
+_Same(_link, 'Version', _string) # /VERSION
+
+_Same(_link, 'EnableCOMDATFolding', _newly_boolean) # /OPT:ICF
+_Same(_link, 'FixedBaseAddress', _newly_boolean) # /FIXED
+_Same(_link, 'LargeAddressAware', _newly_boolean) # /LARGEADDRESSAWARE
+_Same(_link, 'OptimizeReferences', _newly_boolean) # /OPT:REF
+_Same(_link, 'RandomizedBaseAddress', _newly_boolean) # /DYNAMICBASE
+_Same(_link, 'TerminalServerAware', _newly_boolean) # /TSAWARE
+
+_subsystem_enumeration = _Enumeration(
+ ['NotSet',
+ 'Console', # /SUBSYSTEM:CONSOLE
+ 'Windows', # /SUBSYSTEM:WINDOWS
+ 'Native', # /SUBSYSTEM:NATIVE
+ 'EFI Application', # /SUBSYSTEM:EFI_APPLICATION
+ 'EFI Boot Service Driver', # /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER
+ 'EFI ROM', # /SUBSYSTEM:EFI_ROM
+ 'EFI Runtime', # /SUBSYSTEM:EFI_RUNTIME_DRIVER
+ 'WindowsCE'], # /SUBSYSTEM:WINDOWSCE
+ new=['POSIX']) # /SUBSYSTEM:POSIX
+
+_target_machine_enumeration = _Enumeration(
+ ['NotSet',
+ 'MachineX86', # /MACHINE:X86
+ None,
+ 'MachineARM', # /MACHINE:ARM
+ 'MachineEBC', # /MACHINE:EBC
+ 'MachineIA64', # /MACHINE:IA64
+ None,
+ 'MachineMIPS', # /MACHINE:MIPS
+ 'MachineMIPS16', # /MACHINE:MIPS16
+ 'MachineMIPSFPU', # /MACHINE:MIPSFPU
+ 'MachineMIPSFPU16', # /MACHINE:MIPSFPU16
+ None,
+ None,
+ None,
+ 'MachineSH4', # /MACHINE:SH4
+ None,
+ 'MachineTHUMB', # /MACHINE:THUMB
+ 'MachineX64']) # /MACHINE:X64
+
+_Same(_link, 'AssemblyDebug',
+ _Enumeration(['',
+ 'true', # /ASSEMBLYDEBUG
+ 'false'])) # /ASSEMBLYDEBUG:DISABLE
+_Same(_link, 'CLRImageType',
+ _Enumeration(['Default',
+ 'ForceIJWImage', # /CLRIMAGETYPE:IJW
+ 'ForcePureILImage', # /Switch="CLRIMAGETYPE:PURE
+ 'ForceSafeILImage'])) # /Switch="CLRIMAGETYPE:SAFE
+_Same(_link, 'CLRThreadAttribute',
+ _Enumeration(['DefaultThreadingAttribute', # /CLRTHREADATTRIBUTE:NONE
+ 'MTAThreadingAttribute', # /CLRTHREADATTRIBUTE:MTA
+ 'STAThreadingAttribute'])) # /CLRTHREADATTRIBUTE:STA
+_Same(_link, 'DataExecutionPrevention',
+ _Enumeration(['',
+ 'false', # /NXCOMPAT:NO
+ 'true'])) # /NXCOMPAT
+_Same(_link, 'Driver',
+ _Enumeration(['NotSet',
+ 'Driver', # /Driver
+ 'UpOnly', # /DRIVER:UPONLY
+ 'WDM'])) # /DRIVER:WDM
+_Same(_link, 'LinkTimeCodeGeneration',
+ _Enumeration(['Default',
+ 'UseLinkTimeCodeGeneration', # /LTCG
+ 'PGInstrument', # /LTCG:PGInstrument
+ 'PGOptimization', # /LTCG:PGOptimize
+ 'PGUpdate'])) # /LTCG:PGUpdate
+_Same(_link, 'ShowProgress',
+ _Enumeration(['NotSet',
+ 'LinkVerbose', # /VERBOSE
+ 'LinkVerboseLib'], # /VERBOSE:Lib
+ new=['LinkVerboseICF', # /VERBOSE:ICF
+ 'LinkVerboseREF', # /VERBOSE:REF
+ 'LinkVerboseSAFESEH', # /VERBOSE:SAFESEH
+ 'LinkVerboseCLR'])) # /VERBOSE:CLR
+_Same(_link, 'SubSystem', _subsystem_enumeration)
+_Same(_link, 'TargetMachine', _target_machine_enumeration)
+_Same(_link, 'UACExecutionLevel',
+ _Enumeration(['AsInvoker', # /level='asInvoker'
+ 'HighestAvailable', # /level='highestAvailable'
+ 'RequireAdministrator'])) # /level='requireAdministrator'
+
+
+# Options found in MSVS that have been renamed in MSBuild.
+_Renamed(_link, 'ErrorReporting', 'LinkErrorReporting',
+ _Enumeration(['NoErrorReport', # /ERRORREPORT:NONE
+ 'PromptImmediately', # /ERRORREPORT:PROMPT
+ 'QueueForNextLogin'], # /ERRORREPORT:QUEUE
+ new=['SendErrorReport'])) # /ERRORREPORT:SEND
+_Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries',
+ _file_list) # /NODEFAULTLIB
+_Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean) # /NOENTRY
+_Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean) # /SWAPRUN:NET
+
+_Moved(_link, 'GenerateManifest', '', _boolean)
+_Moved(_link, 'IgnoreImportLibrary', '', _boolean)
+_Moved(_link, 'LinkIncremental', '', _newly_boolean)
+_Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
+_Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean)
+
+# MSVS options not found in MSBuild.
+_MSVSOnly(_link, 'OptimizeForWindows98', _newly_boolean)
+_MSVSOnly(_link, 'UseUnicodeResponseFiles', _boolean)
+# These settings generate correctly in the MSVS output files when using
+# e.g. DelayLoadDLLs! or AdditionalDependencies! to exclude files from
+# configuration entries, but result in spurious artifacts which can be
+# safely ignored here. See crbug.com/246570
+_MSVSOnly(_link, 'AdditionalLibraryDirectories_excluded', _folder_list)
+_MSVSOnly(_link, 'DelayLoadDLLs_excluded', _file_list)
+_MSVSOnly(_link, 'AdditionalDependencies_excluded', _file_list)
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_link, 'BuildingInIDE', _boolean)
+_MSBuildOnly(_link, 'ImageHasSafeExceptionHandlers', _boolean) # /SAFESEH
+_MSBuildOnly(_link, 'LinkDLL', _boolean) # /DLL Visible='false'
+_MSBuildOnly(_link, 'LinkStatus', _boolean) # /LTCG:STATUS
+_MSBuildOnly(_link, 'PreventDllBinding', _boolean) # /ALLOWBIND
+_MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean) # /DELAY:NOBIND
+_MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name)
+_MSBuildOnly(_link, 'TreatLinkerWarningAsErrors', _boolean) # /WX
+_MSBuildOnly(_link, 'MinimumRequiredVersion', _string)
+_MSBuildOnly(_link, 'MSDOSStubFileName', _file_name) # /STUB Visible='false'
+_MSBuildOnly(_link, 'SectionAlignment', _integer) # /ALIGN
+_MSBuildOnly(_link, 'SpecifySectionAttributes', _string) # /SECTION
+_MSBuildOnly(_link, 'ForceFileOutput',
+ _Enumeration([], new=['Enabled', # /FORCE
+ # /FORCE:MULTIPLE
+ 'MultiplyDefinedSymbolOnly',
+ 'UndefinedSymbolOnly'])) # /FORCE:UNRESOLVED
+_MSBuildOnly(_link, 'CreateHotPatchableImage',
+ _Enumeration([], new=['Enabled', # /FUNCTIONPADMIN
+ 'X86Image', # /FUNCTIONPADMIN:5
+ 'X64Image', # /FUNCTIONPADMIN:6
+ 'ItaniumImage'])) # /FUNCTIONPADMIN:16
+_MSBuildOnly(_link, 'CLRSupportLastError',
+ _Enumeration([], new=['Enabled', # /CLRSupportLastError
+ 'Disabled', # /CLRSupportLastError:NO
+ # /CLRSupportLastError:SYSTEMDLL
+ 'SystemDlls']))
+
+
+# Directives for converting VCResourceCompilerTool to ResourceCompile.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\rc.xml" for
+# the schema of the MSBuild ResourceCompile settings.
+
+_Same(_rc, 'AdditionalOptions', _string_list)
+_Same(_rc, 'AdditionalIncludeDirectories', _folder_list) # /I
+_Same(_rc, 'Culture', _Integer(msbuild_base=16))
+_Same(_rc, 'IgnoreStandardIncludePath', _boolean) # /X
+_Same(_rc, 'PreprocessorDefinitions', _string_list) # /D
+_Same(_rc, 'ResourceOutputFileName', _string) # /fo
+_Same(_rc, 'ShowProgress', _boolean) # /v
+# There is no UI in VisualStudio 2008 to set the following properties.
+# However they are found in CL and other tools. Include them here for
+# completeness, as they are very likely to have the same usage pattern.
+_Same(_rc, 'SuppressStartupBanner', _boolean) # /nologo
+_Same(_rc, 'UndefinePreprocessorDefinitions', _string_list) # /u
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_rc, 'NullTerminateStrings', _boolean) # /n
+_MSBuildOnly(_rc, 'TrackerLogDirectory', _folder_name)
+
+
+# Directives for converting VCMIDLTool to Midl.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\midl.xml" for
+# the schema of the MSBuild Midl settings.
+
+_Same(_midl, 'AdditionalIncludeDirectories', _folder_list) # /I
+_Same(_midl, 'AdditionalOptions', _string_list)
+_Same(_midl, 'CPreprocessOptions', _string) # /cpp_opt
+_Same(_midl, 'ErrorCheckAllocations', _boolean) # /error allocation
+_Same(_midl, 'ErrorCheckBounds', _boolean) # /error bounds_check
+_Same(_midl, 'ErrorCheckEnumRange', _boolean) # /error enum
+_Same(_midl, 'ErrorCheckRefPointers', _boolean) # /error ref
+_Same(_midl, 'ErrorCheckStubData', _boolean) # /error stub_data
+_Same(_midl, 'GenerateStublessProxies', _boolean) # /Oicf
+_Same(_midl, 'GenerateTypeLibrary', _boolean)
+_Same(_midl, 'HeaderFileName', _file_name) # /h
+_Same(_midl, 'IgnoreStandardIncludePath', _boolean) # /no_def_idir
+_Same(_midl, 'InterfaceIdentifierFileName', _file_name) # /iid
+_Same(_midl, 'MkTypLibCompatible', _boolean) # /mktyplib203
+_Same(_midl, 'OutputDirectory', _string) # /out
+_Same(_midl, 'PreprocessorDefinitions', _string_list) # /D
+_Same(_midl, 'ProxyFileName', _file_name) # /proxy
+_Same(_midl, 'RedirectOutputAndErrors', _file_name) # /o
+_Same(_midl, 'SuppressStartupBanner', _boolean) # /nologo
+_Same(_midl, 'TypeLibraryName', _file_name) # /tlb
+_Same(_midl, 'UndefinePreprocessorDefinitions', _string_list) # /U
+_Same(_midl, 'WarnAsError', _boolean) # /WX
+
+_Same(_midl, 'DefaultCharType',
+ _Enumeration(['Unsigned', # /char unsigned
+ 'Signed', # /char signed
+ 'Ascii'])) # /char ascii7
+_Same(_midl, 'TargetEnvironment',
+ _Enumeration(['NotSet',
+ 'Win32', # /env win32
+ 'Itanium', # /env ia64
+ 'X64'])) # /env x64
+_Same(_midl, 'EnableErrorChecks',
+ _Enumeration(['EnableCustom',
+ 'None', # /error none
+ 'All'])) # /error all
+_Same(_midl, 'StructMemberAlignment',
+ _Enumeration(['NotSet',
+ '1', # Zp1
+ '2', # Zp2
+ '4', # Zp4
+ '8'])) # Zp8
+_Same(_midl, 'WarningLevel',
+ _Enumeration(['0', # /W0
+ '1', # /W1
+ '2', # /W2
+ '3', # /W3
+ '4'])) # /W4
+
+_Renamed(_midl, 'DLLDataFileName', 'DllDataFileName', _file_name) # /dlldata
+_Renamed(_midl, 'ValidateParameters', 'ValidateAllParameters',
+ _boolean) # /robust
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_midl, 'ApplicationConfigurationMode', _boolean) # /app_config
+_MSBuildOnly(_midl, 'ClientStubFile', _file_name) # /cstub
+_MSBuildOnly(_midl, 'GenerateClientFiles',
+ _Enumeration([], new=['Stub', # /client stub
+ 'None'])) # /client none
+_MSBuildOnly(_midl, 'GenerateServerFiles',
+ _Enumeration([], new=['Stub', # /client stub
+ 'None'])) # /client none
+_MSBuildOnly(_midl, 'LocaleID', _integer) # /lcid DECIMAL
+_MSBuildOnly(_midl, 'ServerStubFile', _file_name) # /sstub
+_MSBuildOnly(_midl, 'SuppressCompilerWarnings', _boolean) # /no_warn
+_MSBuildOnly(_midl, 'TrackerLogDirectory', _folder_name)
+_MSBuildOnly(_midl, 'TypeLibFormat',
+ _Enumeration([], new=['NewFormat', # /newtlb
+ 'OldFormat'])) # /oldtlb
+
+
+# Directives for converting VCLibrarianTool to Lib.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\lib.xml" for
+# the schema of the MSBuild Lib settings.
+
+_Same(_lib, 'AdditionalDependencies', _file_list)
+_Same(_lib, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH
+_Same(_lib, 'AdditionalOptions', _string_list)
+_Same(_lib, 'ExportNamedFunctions', _string_list) # /EXPORT
+_Same(_lib, 'ForceSymbolReferences', _string) # /INCLUDE
+_Same(_lib, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB
+_Same(_lib, 'IgnoreSpecificDefaultLibraries', _file_list) # /NODEFAULTLIB
+_Same(_lib, 'ModuleDefinitionFile', _file_name) # /DEF
+_Same(_lib, 'OutputFile', _file_name) # /OUT
+_Same(_lib, 'SuppressStartupBanner', _boolean) # /NOLOGO
+_Same(_lib, 'UseUnicodeResponseFiles', _boolean)
+_Same(_lib, 'LinkTimeCodeGeneration', _boolean) # /LTCG
+
+# TODO(jeanluc) _link defines the same value that gets moved to
+# ProjectReference. We may want to validate that they are consistent.
+_Moved(_lib, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
+
+# TODO(jeanluc) I don't think these are genuine settings but byproducts of Gyp.
+_MSVSOnly(_lib, 'AdditionalLibraryDirectories_excluded', _folder_list)
+
+_MSBuildOnly(_lib, 'DisplayLibrary', _string) # /LIST Visible='false'
+_MSBuildOnly(_lib, 'ErrorReporting',
+ _Enumeration([], new=['PromptImmediately', # /ERRORREPORT:PROMPT
+ 'QueueForNextLogin', # /ERRORREPORT:QUEUE
+ 'SendErrorReport', # /ERRORREPORT:SEND
+ 'NoErrorReport'])) # /ERRORREPORT:NONE
+_MSBuildOnly(_lib, 'MinimumRequiredVersion', _string)
+_MSBuildOnly(_lib, 'Name', _file_name) # /NAME
+_MSBuildOnly(_lib, 'RemoveObjects', _file_list) # /REMOVE
+_MSBuildOnly(_lib, 'SubSystem', _subsystem_enumeration)
+_MSBuildOnly(_lib, 'TargetMachine', _target_machine_enumeration)
+_MSBuildOnly(_lib, 'TrackerLogDirectory', _folder_name)
+_MSBuildOnly(_lib, 'TreatLibWarningAsErrors', _boolean) # /WX
+_MSBuildOnly(_lib, 'Verbose', _boolean)
+
+
+# Directives for converting VCManifestTool to Mt.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\mt.xml" for
+# the schema of the MSBuild Lib settings.
+
+# Options that have the same name in MSVS and MSBuild
+_Same(_manifest, 'AdditionalManifestFiles', _file_list) # /manifest
+_Same(_manifest, 'AdditionalOptions', _string_list)
+_Same(_manifest, 'AssemblyIdentity', _string) # /identity:
+_Same(_manifest, 'ComponentFileName', _file_name) # /dll
+_Same(_manifest, 'GenerateCatalogFiles', _boolean) # /makecdfs
+_Same(_manifest, 'InputResourceManifests', _string) # /inputresource
+_Same(_manifest, 'OutputManifestFile', _file_name) # /out
+_Same(_manifest, 'RegistrarScriptFile', _file_name) # /rgs
+_Same(_manifest, 'ReplacementsFile', _file_name) # /replacements
+_Same(_manifest, 'SuppressStartupBanner', _boolean) # /nologo
+_Same(_manifest, 'TypeLibraryFile', _file_name) # /tlb:
+_Same(_manifest, 'UpdateFileHashes', _boolean) # /hashupdate
+_Same(_manifest, 'UpdateFileHashesSearchPath', _file_name)
+_Same(_manifest, 'VerboseOutput', _boolean) # /verbose
+
+# Options that have moved location.
+_MovedAndRenamed(_manifest, 'ManifestResourceFile',
+ 'ManifestResourceCompile',
+ 'ResourceOutputFileName',
+ _file_name)
+_Moved(_manifest, 'EmbedManifest', '', _boolean)
+
+# MSVS options not found in MSBuild.
+_MSVSOnly(_manifest, 'DependencyInformationFile', _file_name)
+_MSVSOnly(_manifest, 'UseFAT32Workaround', _boolean)
+_MSVSOnly(_manifest, 'UseUnicodeResponseFiles', _boolean)
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_manifest, 'EnableDPIAwareness', _boolean)
+_MSBuildOnly(_manifest, 'GenerateCategoryTags', _boolean) # /category
+_MSBuildOnly(_manifest, 'ManifestFromManagedAssembly',
+ _file_name) # /managedassemblyname
+_MSBuildOnly(_manifest, 'OutputResourceManifests', _string) # /outputresource
+_MSBuildOnly(_manifest, 'SuppressDependencyElement', _boolean) # /nodependency
+_MSBuildOnly(_manifest, 'TrackerLogDirectory', _folder_name)
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSSettings_test.py b/chromium/tools/gyp/pylib/gyp/MSVSSettings_test.py
new file mode 100755
index 00000000000..4e06da3bbe3
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/MSVSSettings_test.py
@@ -0,0 +1,1482 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for the MSVSSettings.py file."""
+
+import StringIO
+import unittest
+import gyp.MSVSSettings as MSVSSettings
+
+
+class TestSequenceFunctions(unittest.TestCase):
+
+ def setUp(self):
+ self.stderr = StringIO.StringIO()
+
+ def _ExpectedWarnings(self, expected):
+ """Compares recorded lines to expected warnings."""
+ self.stderr.seek(0)
+ actual = self.stderr.read().split('\n')
+ actual = [line for line in actual if line]
+ self.assertEqual(sorted(expected), sorted(actual))
+
+ def testValidateMSVSSettings_tool_names(self):
+ """Tests that only MSVS tool names are allowed."""
+ MSVSSettings.ValidateMSVSSettings(
+ {'VCCLCompilerTool': {},
+ 'VCLinkerTool': {},
+ 'VCMIDLTool': {},
+ 'foo': {},
+ 'VCResourceCompilerTool': {},
+ 'VCLibrarianTool': {},
+ 'VCManifestTool': {},
+ 'ClCompile': {}},
+ self.stderr)
+ self._ExpectedWarnings([
+ 'Warning: unrecognized tool foo',
+ 'Warning: unrecognized tool ClCompile'])
+
+ def testValidateMSVSSettings_settings(self):
+ """Tests that for invalid MSVS settings."""
+ MSVSSettings.ValidateMSVSSettings(
+ {'VCCLCompilerTool': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2',
+ 'AdditionalOptions': ['string1', 'string2'],
+ 'AdditionalUsingDirectories': 'folder1;folder2',
+ 'AssemblerListingLocation': 'a_file_name',
+ 'AssemblerOutput': '0',
+ 'BasicRuntimeChecks': '5',
+ 'BrowseInformation': 'fdkslj',
+ 'BrowseInformationFile': 'a_file_name',
+ 'BufferSecurityCheck': 'true',
+ 'CallingConvention': '-1',
+ 'CompileAs': '1',
+ 'DebugInformationFormat': '2',
+ 'DefaultCharIsUnsigned': 'true',
+ 'Detect64BitPortabilityProblems': 'true',
+ 'DisableLanguageExtensions': 'true',
+ 'DisableSpecificWarnings': 'string1;string2',
+ 'EnableEnhancedInstructionSet': '1',
+ 'EnableFiberSafeOptimizations': 'true',
+ 'EnableFunctionLevelLinking': 'true',
+ 'EnableIntrinsicFunctions': 'true',
+ 'EnablePREfast': 'true',
+ 'Enableprefast': 'bogus',
+ 'ErrorReporting': '1',
+ 'ExceptionHandling': '1',
+ 'ExpandAttributedSource': 'true',
+ 'FavorSizeOrSpeed': '1',
+ 'FloatingPointExceptions': 'true',
+ 'FloatingPointModel': '1',
+ 'ForceConformanceInForLoopScope': 'true',
+ 'ForcedIncludeFiles': 'file1;file2',
+ 'ForcedUsingFiles': 'file1;file2',
+ 'GeneratePreprocessedFile': '1',
+ 'GenerateXMLDocumentationFiles': 'true',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InlineFunctionExpansion': '1',
+ 'KeepComments': 'true',
+ 'MinimalRebuild': 'true',
+ 'ObjectFile': 'a_file_name',
+ 'OmitDefaultLibName': 'true',
+ 'OmitFramePointers': 'true',
+ 'OpenMP': 'true',
+ 'Optimization': '1',
+ 'PrecompiledHeaderFile': 'a_file_name',
+ 'PrecompiledHeaderThrough': 'a_file_name',
+ 'PreprocessorDefinitions': 'string1;string2',
+ 'ProgramDataBaseFileName': 'a_file_name',
+ 'RuntimeLibrary': '1',
+ 'RuntimeTypeInfo': 'true',
+ 'ShowIncludes': 'true',
+ 'SmallerTypeCheck': 'true',
+ 'StringPooling': 'true',
+ 'StructMemberAlignment': '1',
+ 'SuppressStartupBanner': 'true',
+ 'TreatWChar_tAsBuiltInType': 'true',
+ 'UndefineAllPreprocessorDefinitions': 'true',
+ 'UndefinePreprocessorDefinitions': 'string1;string2',
+ 'UseFullPaths': 'true',
+ 'UsePrecompiledHeader': '1',
+ 'UseUnicodeResponseFiles': 'true',
+ 'WarnAsError': 'true',
+ 'WarningLevel': '1',
+ 'WholeProgramOptimization': 'true',
+ 'XMLDocumentationFileName': 'a_file_name',
+ 'ZZXYZ': 'bogus'},
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': 'file1;file2',
+ 'AdditionalLibraryDirectories': 'folder1;folder2',
+ 'AdditionalManifestDependencies': 'file1;file2',
+ 'AdditionalOptions': 'a string1',
+ 'AddModuleNamesToAssembly': 'file1;file2',
+ 'AllowIsolation': 'true',
+ 'AssemblyDebug': '2',
+ 'AssemblyLinkResource': 'file1;file2',
+ 'BaseAddress': 'a string1',
+ 'CLRImageType': '2',
+ 'CLRThreadAttribute': '2',
+ 'CLRUnmanagedCodeCheck': 'true',
+ 'DataExecutionPrevention': '2',
+ 'DelayLoadDLLs': 'file1;file2',
+ 'DelaySign': 'true',
+ 'Driver': '2',
+ 'EmbedManagedResourceFile': 'file1;file2',
+ 'EnableCOMDATFolding': '2',
+ 'EnableUAC': 'true',
+ 'EntryPointSymbol': 'a string1',
+ 'ErrorReporting': '2',
+ 'FixedBaseAddress': '2',
+ 'ForceSymbolReferences': 'file1;file2',
+ 'FunctionOrder': 'a_file_name',
+ 'GenerateDebugInformation': 'true',
+ 'GenerateManifest': 'true',
+ 'GenerateMapFile': 'true',
+ 'HeapCommitSize': 'a string1',
+ 'HeapReserveSize': 'a string1',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreDefaultLibraryNames': 'file1;file2',
+ 'IgnoreEmbeddedIDL': 'true',
+ 'IgnoreImportLibrary': 'true',
+ 'ImportLibrary': 'a_file_name',
+ 'KeyContainer': 'a_file_name',
+ 'KeyFile': 'a_file_name',
+ 'LargeAddressAware': '2',
+ 'LinkIncremental': '2',
+ 'LinkLibraryDependencies': 'true',
+ 'LinkTimeCodeGeneration': '2',
+ 'ManifestFile': 'a_file_name',
+ 'MapExports': 'true',
+ 'MapFileName': 'a_file_name',
+ 'MergedIDLBaseFileName': 'a_file_name',
+ 'MergeSections': 'a string1',
+ 'MidlCommandFile': 'a_file_name',
+ 'ModuleDefinitionFile': 'a_file_name',
+ 'OptimizeForWindows98': '1',
+ 'OptimizeReferences': '2',
+ 'OutputFile': 'a_file_name',
+ 'PerUserRedirection': 'true',
+ 'Profile': 'true',
+ 'ProfileGuidedDatabase': 'a_file_name',
+ 'ProgramDatabaseFile': 'a_file_name',
+ 'RandomizedBaseAddress': '2',
+ 'RegisterOutput': 'true',
+ 'ResourceOnlyDLL': 'true',
+ 'SetChecksum': 'true',
+ 'ShowProgress': '2',
+ 'StackCommitSize': 'a string1',
+ 'StackReserveSize': 'a string1',
+ 'StripPrivateSymbols': 'a_file_name',
+ 'SubSystem': '2',
+ 'SupportUnloadOfDelayLoadedDLL': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'SwapRunFromCD': 'true',
+ 'SwapRunFromNet': 'true',
+ 'TargetMachine': '2',
+ 'TerminalServerAware': '2',
+ 'TurnOffAssemblyGeneration': 'true',
+ 'TypeLibraryFile': 'a_file_name',
+ 'TypeLibraryResourceID': '33',
+ 'UACExecutionLevel': '2',
+ 'UACUIAccess': 'true',
+ 'UseLibraryDependencyInputs': 'true',
+ 'UseUnicodeResponseFiles': 'true',
+ 'Version': 'a string1'},
+ 'VCMIDLTool': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2',
+ 'AdditionalOptions': 'a string1',
+ 'CPreprocessOptions': 'a string1',
+ 'DefaultCharType': '1',
+ 'DLLDataFileName': 'a_file_name',
+ 'EnableErrorChecks': '1',
+ 'ErrorCheckAllocations': 'true',
+ 'ErrorCheckBounds': 'true',
+ 'ErrorCheckEnumRange': 'true',
+ 'ErrorCheckRefPointers': 'true',
+ 'ErrorCheckStubData': 'true',
+ 'GenerateStublessProxies': 'true',
+ 'GenerateTypeLibrary': 'true',
+ 'HeaderFileName': 'a_file_name',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InterfaceIdentifierFileName': 'a_file_name',
+ 'MkTypLibCompatible': 'true',
+ 'notgood': 'bogus',
+ 'OutputDirectory': 'a string1',
+ 'PreprocessorDefinitions': 'string1;string2',
+ 'ProxyFileName': 'a_file_name',
+ 'RedirectOutputAndErrors': 'a_file_name',
+ 'StructMemberAlignment': '1',
+ 'SuppressStartupBanner': 'true',
+ 'TargetEnvironment': '1',
+ 'TypeLibraryName': 'a_file_name',
+ 'UndefinePreprocessorDefinitions': 'string1;string2',
+ 'ValidateParameters': 'true',
+ 'WarnAsError': 'true',
+ 'WarningLevel': '1'},
+ 'VCResourceCompilerTool': {
+ 'AdditionalOptions': 'a string1',
+ 'AdditionalIncludeDirectories': 'folder1;folder2',
+ 'Culture': '1003',
+ 'IgnoreStandardIncludePath': 'true',
+ 'notgood2': 'bogus',
+ 'PreprocessorDefinitions': 'string1;string2',
+ 'ResourceOutputFileName': 'a string1',
+ 'ShowProgress': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'UndefinePreprocessorDefinitions': 'string1;string2'},
+ 'VCLibrarianTool': {
+ 'AdditionalDependencies': 'file1;file2',
+ 'AdditionalLibraryDirectories': 'folder1;folder2',
+ 'AdditionalOptions': 'a string1',
+ 'ExportNamedFunctions': 'string1;string2',
+ 'ForceSymbolReferences': 'a string1',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreSpecificDefaultLibraries': 'file1;file2',
+ 'LinkLibraryDependencies': 'true',
+ 'ModuleDefinitionFile': 'a_file_name',
+ 'OutputFile': 'a_file_name',
+ 'SuppressStartupBanner': 'true',
+ 'UseUnicodeResponseFiles': 'true'},
+ 'VCManifestTool': {
+ 'AdditionalManifestFiles': 'file1;file2',
+ 'AdditionalOptions': 'a string1',
+ 'AssemblyIdentity': 'a string1',
+ 'ComponentFileName': 'a_file_name',
+ 'DependencyInformationFile': 'a_file_name',
+ 'GenerateCatalogFiles': 'true',
+ 'InputResourceManifests': 'a string1',
+ 'ManifestResourceFile': 'a_file_name',
+ 'OutputManifestFile': 'a_file_name',
+ 'RegistrarScriptFile': 'a_file_name',
+ 'ReplacementsFile': 'a_file_name',
+ 'SuppressStartupBanner': 'true',
+ 'TypeLibraryFile': 'a_file_name',
+ 'UpdateFileHashes': 'truel',
+ 'UpdateFileHashesSearchPath': 'a_file_name',
+ 'UseFAT32Workaround': 'true',
+ 'UseUnicodeResponseFiles': 'true',
+ 'VerboseOutput': 'true'}},
+ self.stderr)
+ self._ExpectedWarnings([
+ 'Warning: for VCCLCompilerTool/BasicRuntimeChecks, '
+ 'index value (5) not in expected range [0, 4)',
+ 'Warning: for VCCLCompilerTool/BrowseInformation, '
+ "invalid literal for int() with base 10: 'fdkslj'",
+ 'Warning: for VCCLCompilerTool/CallingConvention, '
+ 'index value (-1) not in expected range [0, 3)',
+ 'Warning: for VCCLCompilerTool/DebugInformationFormat, '
+ 'converted value for 2 not specified.',
+ 'Warning: unrecognized setting VCCLCompilerTool/Enableprefast',
+ 'Warning: unrecognized setting VCCLCompilerTool/ZZXYZ',
+ 'Warning: for VCLinkerTool/TargetMachine, '
+ 'converted value for 2 not specified.',
+ 'Warning: unrecognized setting VCMIDLTool/notgood',
+ 'Warning: unrecognized setting VCResourceCompilerTool/notgood2',
+ 'Warning: for VCManifestTool/UpdateFileHashes, '
+ "expected bool; got 'truel'"
+ ''])
+
+ def testValidateMSBuildSettings_settings(self):
+ """Tests that for invalid MSBuild settings."""
+ MSVSSettings.ValidateMSBuildSettings(
+ {'ClCompile': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2',
+ 'AdditionalOptions': ['string1', 'string2'],
+ 'AdditionalUsingDirectories': 'folder1;folder2',
+ 'AssemblerListingLocation': 'a_file_name',
+ 'AssemblerOutput': 'NoListing',
+ 'BasicRuntimeChecks': 'StackFrameRuntimeCheck',
+ 'BrowseInformation': 'false',
+ 'BrowseInformationFile': 'a_file_name',
+ 'BufferSecurityCheck': 'true',
+ 'BuildingInIDE': 'true',
+ 'CallingConvention': 'Cdecl',
+ 'CompileAs': 'CompileAsC',
+ 'CompileAsManaged': 'Pure',
+ 'CreateHotpatchableImage': 'true',
+ 'DebugInformationFormat': 'ProgramDatabase',
+ 'DisableLanguageExtensions': 'true',
+ 'DisableSpecificWarnings': 'string1;string2',
+ 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions',
+ 'EnableFiberSafeOptimizations': 'true',
+ 'EnablePREfast': 'true',
+ 'Enableprefast': 'bogus',
+ 'ErrorReporting': 'Prompt',
+ 'ExceptionHandling': 'SyncCThrow',
+ 'ExpandAttributedSource': 'true',
+ 'FavorSizeOrSpeed': 'Neither',
+ 'FloatingPointExceptions': 'true',
+ 'FloatingPointModel': 'Precise',
+ 'ForceConformanceInForLoopScope': 'true',
+ 'ForcedIncludeFiles': 'file1;file2',
+ 'ForcedUsingFiles': 'file1;file2',
+ 'FunctionLevelLinking': 'false',
+ 'GenerateXMLDocumentationFiles': 'true',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InlineFunctionExpansion': 'OnlyExplicitInline',
+ 'IntrinsicFunctions': 'false',
+ 'MinimalRebuild': 'true',
+ 'MultiProcessorCompilation': 'true',
+ 'ObjectFileName': 'a_file_name',
+ 'OmitDefaultLibName': 'true',
+ 'OmitFramePointers': 'true',
+ 'OpenMPSupport': 'true',
+ 'Optimization': 'Disabled',
+ 'PrecompiledHeader': 'NotUsing',
+ 'PrecompiledHeaderFile': 'a_file_name',
+ 'PrecompiledHeaderOutputFile': 'a_file_name',
+ 'PreprocessKeepComments': 'true',
+ 'PreprocessorDefinitions': 'string1;string2',
+ 'PreprocessOutputPath': 'a string1',
+ 'PreprocessSuppressLineNumbers': 'false',
+ 'PreprocessToFile': 'false',
+ 'ProcessorNumber': '33',
+ 'ProgramDataBaseFileName': 'a_file_name',
+ 'RuntimeLibrary': 'MultiThreaded',
+ 'RuntimeTypeInfo': 'true',
+ 'ShowIncludes': 'true',
+ 'SmallerTypeCheck': 'true',
+ 'StringPooling': 'true',
+ 'StructMemberAlignment': '1Byte',
+ 'SuppressStartupBanner': 'true',
+ 'TrackerLogDirectory': 'a_folder',
+ 'TreatSpecificWarningsAsErrors': 'string1;string2',
+ 'TreatWarningAsError': 'true',
+ 'TreatWChar_tAsBuiltInType': 'true',
+ 'UndefineAllPreprocessorDefinitions': 'true',
+ 'UndefinePreprocessorDefinitions': 'string1;string2',
+ 'UseFullPaths': 'true',
+ 'UseUnicodeForAssemblerListing': 'true',
+ 'WarningLevel': 'TurnOffAllWarnings',
+ 'WholeProgramOptimization': 'true',
+ 'XMLDocumentationFileName': 'a_file_name',
+ 'ZZXYZ': 'bogus'},
+ 'Link': {
+ 'AdditionalDependencies': 'file1;file2',
+ 'AdditionalLibraryDirectories': 'folder1;folder2',
+ 'AdditionalManifestDependencies': 'file1;file2',
+ 'AdditionalOptions': 'a string1',
+ 'AddModuleNamesToAssembly': 'file1;file2',
+ 'AllowIsolation': 'true',
+ 'AssemblyDebug': '',
+ 'AssemblyLinkResource': 'file1;file2',
+ 'BaseAddress': 'a string1',
+ 'BuildingInIDE': 'true',
+ 'CLRImageType': 'ForceIJWImage',
+ 'CLRSupportLastError': 'Enabled',
+ 'CLRThreadAttribute': 'MTAThreadingAttribute',
+ 'CLRUnmanagedCodeCheck': 'true',
+ 'CreateHotPatchableImage': 'X86Image',
+ 'DataExecutionPrevention': 'false',
+ 'DelayLoadDLLs': 'file1;file2',
+ 'DelaySign': 'true',
+ 'Driver': 'NotSet',
+ 'EmbedManagedResourceFile': 'file1;file2',
+ 'EnableCOMDATFolding': 'false',
+ 'EnableUAC': 'true',
+ 'EntryPointSymbol': 'a string1',
+ 'FixedBaseAddress': 'false',
+ 'ForceFileOutput': 'Enabled',
+ 'ForceSymbolReferences': 'file1;file2',
+ 'FunctionOrder': 'a_file_name',
+ 'GenerateDebugInformation': 'true',
+ 'GenerateMapFile': 'true',
+ 'HeapCommitSize': 'a string1',
+ 'HeapReserveSize': 'a string1',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreEmbeddedIDL': 'true',
+ 'IgnoreSpecificDefaultLibraries': 'a_file_list',
+ 'ImageHasSafeExceptionHandlers': 'true',
+ 'ImportLibrary': 'a_file_name',
+ 'KeyContainer': 'a_file_name',
+ 'KeyFile': 'a_file_name',
+ 'LargeAddressAware': 'false',
+ 'LinkDLL': 'true',
+ 'LinkErrorReporting': 'SendErrorReport',
+ 'LinkStatus': 'true',
+ 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
+ 'ManifestFile': 'a_file_name',
+ 'MapExports': 'true',
+ 'MapFileName': 'a_file_name',
+ 'MergedIDLBaseFileName': 'a_file_name',
+ 'MergeSections': 'a string1',
+ 'MidlCommandFile': 'a_file_name',
+ 'MinimumRequiredVersion': 'a string1',
+ 'ModuleDefinitionFile': 'a_file_name',
+ 'MSDOSStubFileName': 'a_file_name',
+ 'NoEntryPoint': 'true',
+ 'OptimizeReferences': 'false',
+ 'OutputFile': 'a_file_name',
+ 'PerUserRedirection': 'true',
+ 'PreventDllBinding': 'true',
+ 'Profile': 'true',
+ 'ProfileGuidedDatabase': 'a_file_name',
+ 'ProgramDatabaseFile': 'a_file_name',
+ 'RandomizedBaseAddress': 'false',
+ 'RegisterOutput': 'true',
+ 'SectionAlignment': '33',
+ 'SetChecksum': 'true',
+ 'ShowProgress': 'LinkVerboseREF',
+ 'SpecifySectionAttributes': 'a string1',
+ 'StackCommitSize': 'a string1',
+ 'StackReserveSize': 'a string1',
+ 'StripPrivateSymbols': 'a_file_name',
+ 'SubSystem': 'Console',
+ 'SupportNobindOfDelayLoadedDLL': 'true',
+ 'SupportUnloadOfDelayLoadedDLL': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'SwapRunFromCD': 'true',
+ 'SwapRunFromNET': 'true',
+ 'TargetMachine': 'MachineX86',
+ 'TerminalServerAware': 'false',
+ 'TrackerLogDirectory': 'a_folder',
+ 'TreatLinkerWarningAsErrors': 'true',
+ 'TurnOffAssemblyGeneration': 'true',
+ 'TypeLibraryFile': 'a_file_name',
+ 'TypeLibraryResourceID': '33',
+ 'UACExecutionLevel': 'AsInvoker',
+ 'UACUIAccess': 'true',
+ 'Version': 'a string1'},
+ 'ResourceCompile': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2',
+ 'AdditionalOptions': 'a string1',
+ 'Culture': '0x236',
+ 'IgnoreStandardIncludePath': 'true',
+ 'NullTerminateStrings': 'true',
+ 'PreprocessorDefinitions': 'string1;string2',
+ 'ResourceOutputFileName': 'a string1',
+ 'ShowProgress': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'TrackerLogDirectory': 'a_folder',
+ 'UndefinePreprocessorDefinitions': 'string1;string2'},
+ 'Midl': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2',
+ 'AdditionalOptions': 'a string1',
+ 'ApplicationConfigurationMode': 'true',
+ 'ClientStubFile': 'a_file_name',
+ 'CPreprocessOptions': 'a string1',
+ 'DefaultCharType': 'Signed',
+ 'DllDataFileName': 'a_file_name',
+ 'EnableErrorChecks': 'EnableCustom',
+ 'ErrorCheckAllocations': 'true',
+ 'ErrorCheckBounds': 'true',
+ 'ErrorCheckEnumRange': 'true',
+ 'ErrorCheckRefPointers': 'true',
+ 'ErrorCheckStubData': 'true',
+ 'GenerateClientFiles': 'Stub',
+ 'GenerateServerFiles': 'None',
+ 'GenerateStublessProxies': 'true',
+ 'GenerateTypeLibrary': 'true',
+ 'HeaderFileName': 'a_file_name',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InterfaceIdentifierFileName': 'a_file_name',
+ 'LocaleID': '33',
+ 'MkTypLibCompatible': 'true',
+ 'OutputDirectory': 'a string1',
+ 'PreprocessorDefinitions': 'string1;string2',
+ 'ProxyFileName': 'a_file_name',
+ 'RedirectOutputAndErrors': 'a_file_name',
+ 'ServerStubFile': 'a_file_name',
+ 'StructMemberAlignment': 'NotSet',
+ 'SuppressCompilerWarnings': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'TargetEnvironment': 'Itanium',
+ 'TrackerLogDirectory': 'a_folder',
+ 'TypeLibFormat': 'NewFormat',
+ 'TypeLibraryName': 'a_file_name',
+ 'UndefinePreprocessorDefinitions': 'string1;string2',
+ 'ValidateAllParameters': 'true',
+ 'WarnAsError': 'true',
+ 'WarningLevel': '1'},
+ 'Lib': {
+ 'AdditionalDependencies': 'file1;file2',
+ 'AdditionalLibraryDirectories': 'folder1;folder2',
+ 'AdditionalOptions': 'a string1',
+ 'DisplayLibrary': 'a string1',
+ 'ErrorReporting': 'PromptImmediately',
+ 'ExportNamedFunctions': 'string1;string2',
+ 'ForceSymbolReferences': 'a string1',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreSpecificDefaultLibraries': 'file1;file2',
+ 'LinkTimeCodeGeneration': 'true',
+ 'MinimumRequiredVersion': 'a string1',
+ 'ModuleDefinitionFile': 'a_file_name',
+ 'Name': 'a_file_name',
+ 'OutputFile': 'a_file_name',
+ 'RemoveObjects': 'file1;file2',
+ 'SubSystem': 'Console',
+ 'SuppressStartupBanner': 'true',
+ 'TargetMachine': 'MachineX86i',
+ 'TrackerLogDirectory': 'a_folder',
+ 'TreatLibWarningAsErrors': 'true',
+ 'UseUnicodeResponseFiles': 'true',
+ 'Verbose': 'true'},
+ 'Manifest': {
+ 'AdditionalManifestFiles': 'file1;file2',
+ 'AdditionalOptions': 'a string1',
+ 'AssemblyIdentity': 'a string1',
+ 'ComponentFileName': 'a_file_name',
+ 'EnableDPIAwareness': 'fal',
+ 'GenerateCatalogFiles': 'truel',
+ 'GenerateCategoryTags': 'true',
+ 'InputResourceManifests': 'a string1',
+ 'ManifestFromManagedAssembly': 'a_file_name',
+ 'notgood3': 'bogus',
+ 'OutputManifestFile': 'a_file_name',
+ 'OutputResourceManifests': 'a string1',
+ 'RegistrarScriptFile': 'a_file_name',
+ 'ReplacementsFile': 'a_file_name',
+ 'SuppressDependencyElement': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'TrackerLogDirectory': 'a_folder',
+ 'TypeLibraryFile': 'a_file_name',
+ 'UpdateFileHashes': 'true',
+ 'UpdateFileHashesSearchPath': 'a_file_name',
+ 'VerboseOutput': 'true'},
+ 'ProjectReference': {
+ 'LinkLibraryDependencies': 'true',
+ 'UseLibraryDependencyInputs': 'true'},
+ 'ManifestResourceCompile': {
+ 'ResourceOutputFileName': 'a_file_name'},
+ '': {
+ 'EmbedManifest': 'true',
+ 'GenerateManifest': 'true',
+ 'IgnoreImportLibrary': 'true',
+ 'LinkIncremental': 'false'}},
+ self.stderr)
+ self._ExpectedWarnings([
+ 'Warning: unrecognized setting ClCompile/Enableprefast',
+ 'Warning: unrecognized setting ClCompile/ZZXYZ',
+ 'Warning: unrecognized setting Manifest/notgood3',
+ 'Warning: for Manifest/GenerateCatalogFiles, '
+ "expected bool; got 'truel'",
+ 'Warning: for Lib/TargetMachine, unrecognized enumerated value '
+ 'MachineX86i',
+ "Warning: for Manifest/EnableDPIAwareness, expected bool; got 'fal'"])
+
+ def testConvertToMSBuildSettings_empty(self):
+ """Tests an empty conversion."""
+ msvs_settings = {}
+ expected_msbuild_settings = {}
+ actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+ msvs_settings,
+ self.stderr)
+ self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+ self._ExpectedWarnings([])
+
+ def testConvertToMSBuildSettings_minimal(self):
+ """Tests a minimal conversion."""
+ msvs_settings = {
+ 'VCCLCompilerTool': {
+ 'AdditionalIncludeDirectories': 'dir1',
+ 'AdditionalOptions': '/foo',
+ 'BasicRuntimeChecks': '0',
+ },
+ 'VCLinkerTool': {
+ 'LinkTimeCodeGeneration': '1',
+ 'ErrorReporting': '1',
+ 'DataExecutionPrevention': '2',
+ },
+ }
+ expected_msbuild_settings = {
+ 'ClCompile': {
+ 'AdditionalIncludeDirectories': 'dir1',
+ 'AdditionalOptions': '/foo',
+ 'BasicRuntimeChecks': 'Default',
+ },
+ 'Link': {
+ 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
+ 'LinkErrorReporting': 'PromptImmediately',
+ 'DataExecutionPrevention': 'true',
+ },
+ }
+ actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+ msvs_settings,
+ self.stderr)
+ self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+ self._ExpectedWarnings([])
+
+ def testConvertToMSBuildSettings_warnings(self):
+ """Tests conversion that generates warnings."""
+ msvs_settings = {
+ 'VCCLCompilerTool': {
+ 'AdditionalIncludeDirectories': '1',
+ 'AdditionalOptions': '2',
+ # These are incorrect values:
+ 'BasicRuntimeChecks': '12',
+ 'BrowseInformation': '21',
+ 'UsePrecompiledHeader': '13',
+ 'GeneratePreprocessedFile': '14'},
+ 'VCLinkerTool': {
+ # These are incorrect values:
+ 'Driver': '10',
+ 'LinkTimeCodeGeneration': '31',
+ 'ErrorReporting': '21',
+ 'FixedBaseAddress': '6'},
+ 'VCResourceCompilerTool': {
+ # Custom
+ 'Culture': '1003'}}
+ expected_msbuild_settings = {
+ 'ClCompile': {
+ 'AdditionalIncludeDirectories': '1',
+ 'AdditionalOptions': '2'},
+ 'Link': {},
+ 'ResourceCompile': {
+ # Custom
+ 'Culture': '0x03eb'}}
+ actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+ msvs_settings,
+ self.stderr)
+ self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+ self._ExpectedWarnings([
+ 'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to '
+ 'MSBuild, index value (12) not in expected range [0, 4)',
+ 'Warning: while converting VCCLCompilerTool/BrowseInformation to '
+ 'MSBuild, index value (21) not in expected range [0, 3)',
+ 'Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to '
+ 'MSBuild, index value (13) not in expected range [0, 3)',
+ 'Warning: while converting VCCLCompilerTool/GeneratePreprocessedFile to '
+ 'MSBuild, value must be one of [0, 1, 2]; got 14',
+
+ 'Warning: while converting VCLinkerTool/Driver to '
+ 'MSBuild, index value (10) not in expected range [0, 4)',
+ 'Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to '
+ 'MSBuild, index value (31) not in expected range [0, 5)',
+ 'Warning: while converting VCLinkerTool/ErrorReporting to '
+ 'MSBuild, index value (21) not in expected range [0, 3)',
+ 'Warning: while converting VCLinkerTool/FixedBaseAddress to '
+ 'MSBuild, index value (6) not in expected range [0, 3)',
+ ])
+
+ def testConvertToMSBuildSettings_full_synthetic(self):
+ """Tests conversion of all the MSBuild settings."""
+ msvs_settings = {
+ 'VCCLCompilerTool': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+ 'AdditionalOptions': 'a_string',
+ 'AdditionalUsingDirectories': 'folder1;folder2;folder3',
+ 'AssemblerListingLocation': 'a_file_name',
+ 'AssemblerOutput': '0',
+ 'BasicRuntimeChecks': '1',
+ 'BrowseInformation': '2',
+ 'BrowseInformationFile': 'a_file_name',
+ 'BufferSecurityCheck': 'true',
+ 'CallingConvention': '0',
+ 'CompileAs': '1',
+ 'DebugInformationFormat': '4',
+ 'DefaultCharIsUnsigned': 'true',
+ 'Detect64BitPortabilityProblems': 'true',
+ 'DisableLanguageExtensions': 'true',
+ 'DisableSpecificWarnings': 'd1;d2;d3',
+ 'EnableEnhancedInstructionSet': '0',
+ 'EnableFiberSafeOptimizations': 'true',
+ 'EnableFunctionLevelLinking': 'true',
+ 'EnableIntrinsicFunctions': 'true',
+ 'EnablePREfast': 'true',
+ 'ErrorReporting': '1',
+ 'ExceptionHandling': '2',
+ 'ExpandAttributedSource': 'true',
+ 'FavorSizeOrSpeed': '0',
+ 'FloatingPointExceptions': 'true',
+ 'FloatingPointModel': '1',
+ 'ForceConformanceInForLoopScope': 'true',
+ 'ForcedIncludeFiles': 'file1;file2;file3',
+ 'ForcedUsingFiles': 'file1;file2;file3',
+ 'GeneratePreprocessedFile': '1',
+ 'GenerateXMLDocumentationFiles': 'true',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InlineFunctionExpansion': '2',
+ 'KeepComments': 'true',
+ 'MinimalRebuild': 'true',
+ 'ObjectFile': 'a_file_name',
+ 'OmitDefaultLibName': 'true',
+ 'OmitFramePointers': 'true',
+ 'OpenMP': 'true',
+ 'Optimization': '3',
+ 'PrecompiledHeaderFile': 'a_file_name',
+ 'PrecompiledHeaderThrough': 'a_file_name',
+ 'PreprocessorDefinitions': 'd1;d2;d3',
+ 'ProgramDataBaseFileName': 'a_file_name',
+ 'RuntimeLibrary': '0',
+ 'RuntimeTypeInfo': 'true',
+ 'ShowIncludes': 'true',
+ 'SmallerTypeCheck': 'true',
+ 'StringPooling': 'true',
+ 'StructMemberAlignment': '1',
+ 'SuppressStartupBanner': 'true',
+ 'TreatWChar_tAsBuiltInType': 'true',
+ 'UndefineAllPreprocessorDefinitions': 'true',
+ 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
+ 'UseFullPaths': 'true',
+ 'UsePrecompiledHeader': '1',
+ 'UseUnicodeResponseFiles': 'true',
+ 'WarnAsError': 'true',
+ 'WarningLevel': '2',
+ 'WholeProgramOptimization': 'true',
+ 'XMLDocumentationFileName': 'a_file_name'},
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': 'file1;file2;file3',
+ 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
+ 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3',
+ 'AdditionalManifestDependencies': 'file1;file2;file3',
+ 'AdditionalOptions': 'a_string',
+ 'AddModuleNamesToAssembly': 'file1;file2;file3',
+ 'AllowIsolation': 'true',
+ 'AssemblyDebug': '0',
+ 'AssemblyLinkResource': 'file1;file2;file3',
+ 'BaseAddress': 'a_string',
+ 'CLRImageType': '1',
+ 'CLRThreadAttribute': '2',
+ 'CLRUnmanagedCodeCheck': 'true',
+ 'DataExecutionPrevention': '0',
+ 'DelayLoadDLLs': 'file1;file2;file3',
+ 'DelaySign': 'true',
+ 'Driver': '1',
+ 'EmbedManagedResourceFile': 'file1;file2;file3',
+ 'EnableCOMDATFolding': '0',
+ 'EnableUAC': 'true',
+ 'EntryPointSymbol': 'a_string',
+ 'ErrorReporting': '0',
+ 'FixedBaseAddress': '1',
+ 'ForceSymbolReferences': 'file1;file2;file3',
+ 'FunctionOrder': 'a_file_name',
+ 'GenerateDebugInformation': 'true',
+ 'GenerateManifest': 'true',
+ 'GenerateMapFile': 'true',
+ 'HeapCommitSize': 'a_string',
+ 'HeapReserveSize': 'a_string',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreDefaultLibraryNames': 'file1;file2;file3',
+ 'IgnoreEmbeddedIDL': 'true',
+ 'IgnoreImportLibrary': 'true',
+ 'ImportLibrary': 'a_file_name',
+ 'KeyContainer': 'a_file_name',
+ 'KeyFile': 'a_file_name',
+ 'LargeAddressAware': '2',
+ 'LinkIncremental': '1',
+ 'LinkLibraryDependencies': 'true',
+ 'LinkTimeCodeGeneration': '2',
+ 'ManifestFile': 'a_file_name',
+ 'MapExports': 'true',
+ 'MapFileName': 'a_file_name',
+ 'MergedIDLBaseFileName': 'a_file_name',
+ 'MergeSections': 'a_string',
+ 'MidlCommandFile': 'a_file_name',
+ 'ModuleDefinitionFile': 'a_file_name',
+ 'OptimizeForWindows98': '1',
+ 'OptimizeReferences': '0',
+ 'OutputFile': 'a_file_name',
+ 'PerUserRedirection': 'true',
+ 'Profile': 'true',
+ 'ProfileGuidedDatabase': 'a_file_name',
+ 'ProgramDatabaseFile': 'a_file_name',
+ 'RandomizedBaseAddress': '1',
+ 'RegisterOutput': 'true',
+ 'ResourceOnlyDLL': 'true',
+ 'SetChecksum': 'true',
+ 'ShowProgress': '0',
+ 'StackCommitSize': 'a_string',
+ 'StackReserveSize': 'a_string',
+ 'StripPrivateSymbols': 'a_file_name',
+ 'SubSystem': '2',
+ 'SupportUnloadOfDelayLoadedDLL': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'SwapRunFromCD': 'true',
+ 'SwapRunFromNet': 'true',
+ 'TargetMachine': '3',
+ 'TerminalServerAware': '2',
+ 'TurnOffAssemblyGeneration': 'true',
+ 'TypeLibraryFile': 'a_file_name',
+ 'TypeLibraryResourceID': '33',
+ 'UACExecutionLevel': '1',
+ 'UACUIAccess': 'true',
+ 'UseLibraryDependencyInputs': 'false',
+ 'UseUnicodeResponseFiles': 'true',
+ 'Version': 'a_string'},
+ 'VCResourceCompilerTool': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+ 'AdditionalOptions': 'a_string',
+ 'Culture': '1003',
+ 'IgnoreStandardIncludePath': 'true',
+ 'PreprocessorDefinitions': 'd1;d2;d3',
+ 'ResourceOutputFileName': 'a_string',
+ 'ShowProgress': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'UndefinePreprocessorDefinitions': 'd1;d2;d3'},
+ 'VCMIDLTool': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+ 'AdditionalOptions': 'a_string',
+ 'CPreprocessOptions': 'a_string',
+ 'DefaultCharType': '0',
+ 'DLLDataFileName': 'a_file_name',
+ 'EnableErrorChecks': '2',
+ 'ErrorCheckAllocations': 'true',
+ 'ErrorCheckBounds': 'true',
+ 'ErrorCheckEnumRange': 'true',
+ 'ErrorCheckRefPointers': 'true',
+ 'ErrorCheckStubData': 'true',
+ 'GenerateStublessProxies': 'true',
+ 'GenerateTypeLibrary': 'true',
+ 'HeaderFileName': 'a_file_name',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InterfaceIdentifierFileName': 'a_file_name',
+ 'MkTypLibCompatible': 'true',
+ 'OutputDirectory': 'a_string',
+ 'PreprocessorDefinitions': 'd1;d2;d3',
+ 'ProxyFileName': 'a_file_name',
+ 'RedirectOutputAndErrors': 'a_file_name',
+ 'StructMemberAlignment': '3',
+ 'SuppressStartupBanner': 'true',
+ 'TargetEnvironment': '1',
+ 'TypeLibraryName': 'a_file_name',
+ 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
+ 'ValidateParameters': 'true',
+ 'WarnAsError': 'true',
+ 'WarningLevel': '4'},
+ 'VCLibrarianTool': {
+ 'AdditionalDependencies': 'file1;file2;file3',
+ 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
+ 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3',
+ 'AdditionalOptions': 'a_string',
+ 'ExportNamedFunctions': 'd1;d2;d3',
+ 'ForceSymbolReferences': 'a_string',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
+ 'LinkLibraryDependencies': 'true',
+ 'ModuleDefinitionFile': 'a_file_name',
+ 'OutputFile': 'a_file_name',
+ 'SuppressStartupBanner': 'true',
+ 'UseUnicodeResponseFiles': 'true'},
+ 'VCManifestTool': {
+ 'AdditionalManifestFiles': 'file1;file2;file3',
+ 'AdditionalOptions': 'a_string',
+ 'AssemblyIdentity': 'a_string',
+ 'ComponentFileName': 'a_file_name',
+ 'DependencyInformationFile': 'a_file_name',
+ 'EmbedManifest': 'true',
+ 'GenerateCatalogFiles': 'true',
+ 'InputResourceManifests': 'a_string',
+ 'ManifestResourceFile': 'my_name',
+ 'OutputManifestFile': 'a_file_name',
+ 'RegistrarScriptFile': 'a_file_name',
+ 'ReplacementsFile': 'a_file_name',
+ 'SuppressStartupBanner': 'true',
+ 'TypeLibraryFile': 'a_file_name',
+ 'UpdateFileHashes': 'true',
+ 'UpdateFileHashesSearchPath': 'a_file_name',
+ 'UseFAT32Workaround': 'true',
+ 'UseUnicodeResponseFiles': 'true',
+ 'VerboseOutput': 'true'}}
+ expected_msbuild_settings = {
+ 'ClCompile': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+ 'AdditionalOptions': 'a_string /J',
+ 'AdditionalUsingDirectories': 'folder1;folder2;folder3',
+ 'AssemblerListingLocation': 'a_file_name',
+ 'AssemblerOutput': 'NoListing',
+ 'BasicRuntimeChecks': 'StackFrameRuntimeCheck',
+ 'BrowseInformation': 'true',
+ 'BrowseInformationFile': 'a_file_name',
+ 'BufferSecurityCheck': 'true',
+ 'CallingConvention': 'Cdecl',
+ 'CompileAs': 'CompileAsC',
+ 'DebugInformationFormat': 'EditAndContinue',
+ 'DisableLanguageExtensions': 'true',
+ 'DisableSpecificWarnings': 'd1;d2;d3',
+ 'EnableEnhancedInstructionSet': 'NotSet',
+ 'EnableFiberSafeOptimizations': 'true',
+ 'EnablePREfast': 'true',
+ 'ErrorReporting': 'Prompt',
+ 'ExceptionHandling': 'Async',
+ 'ExpandAttributedSource': 'true',
+ 'FavorSizeOrSpeed': 'Neither',
+ 'FloatingPointExceptions': 'true',
+ 'FloatingPointModel': 'Strict',
+ 'ForceConformanceInForLoopScope': 'true',
+ 'ForcedIncludeFiles': 'file1;file2;file3',
+ 'ForcedUsingFiles': 'file1;file2;file3',
+ 'FunctionLevelLinking': 'true',
+ 'GenerateXMLDocumentationFiles': 'true',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InlineFunctionExpansion': 'AnySuitable',
+ 'IntrinsicFunctions': 'true',
+ 'MinimalRebuild': 'true',
+ 'ObjectFileName': 'a_file_name',
+ 'OmitDefaultLibName': 'true',
+ 'OmitFramePointers': 'true',
+ 'OpenMPSupport': 'true',
+ 'Optimization': 'Full',
+ 'PrecompiledHeader': 'Create',
+ 'PrecompiledHeaderFile': 'a_file_name',
+ 'PrecompiledHeaderOutputFile': 'a_file_name',
+ 'PreprocessKeepComments': 'true',
+ 'PreprocessorDefinitions': 'd1;d2;d3',
+ 'PreprocessSuppressLineNumbers': 'false',
+ 'PreprocessToFile': 'true',
+ 'ProgramDataBaseFileName': 'a_file_name',
+ 'RuntimeLibrary': 'MultiThreaded',
+ 'RuntimeTypeInfo': 'true',
+ 'ShowIncludes': 'true',
+ 'SmallerTypeCheck': 'true',
+ 'StringPooling': 'true',
+ 'StructMemberAlignment': '1Byte',
+ 'SuppressStartupBanner': 'true',
+ 'TreatWarningAsError': 'true',
+ 'TreatWChar_tAsBuiltInType': 'true',
+ 'UndefineAllPreprocessorDefinitions': 'true',
+ 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
+ 'UseFullPaths': 'true',
+ 'WarningLevel': 'Level2',
+ 'WholeProgramOptimization': 'true',
+ 'XMLDocumentationFileName': 'a_file_name'},
+ 'Link': {
+ 'AdditionalDependencies': 'file1;file2;file3',
+ 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
+ 'AdditionalManifestDependencies': 'file1;file2;file3',
+ 'AdditionalOptions': 'a_string',
+ 'AddModuleNamesToAssembly': 'file1;file2;file3',
+ 'AllowIsolation': 'true',
+ 'AssemblyDebug': '',
+ 'AssemblyLinkResource': 'file1;file2;file3',
+ 'BaseAddress': 'a_string',
+ 'CLRImageType': 'ForceIJWImage',
+ 'CLRThreadAttribute': 'STAThreadingAttribute',
+ 'CLRUnmanagedCodeCheck': 'true',
+ 'DataExecutionPrevention': '',
+ 'DelayLoadDLLs': 'file1;file2;file3',
+ 'DelaySign': 'true',
+ 'Driver': 'Driver',
+ 'EmbedManagedResourceFile': 'file1;file2;file3',
+ 'EnableCOMDATFolding': '',
+ 'EnableUAC': 'true',
+ 'EntryPointSymbol': 'a_string',
+ 'FixedBaseAddress': 'false',
+ 'ForceSymbolReferences': 'file1;file2;file3',
+ 'FunctionOrder': 'a_file_name',
+ 'GenerateDebugInformation': 'true',
+ 'GenerateMapFile': 'true',
+ 'HeapCommitSize': 'a_string',
+ 'HeapReserveSize': 'a_string',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreEmbeddedIDL': 'true',
+ 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
+ 'ImportLibrary': 'a_file_name',
+ 'KeyContainer': 'a_file_name',
+ 'KeyFile': 'a_file_name',
+ 'LargeAddressAware': 'true',
+ 'LinkErrorReporting': 'NoErrorReport',
+ 'LinkTimeCodeGeneration': 'PGInstrument',
+ 'ManifestFile': 'a_file_name',
+ 'MapExports': 'true',
+ 'MapFileName': 'a_file_name',
+ 'MergedIDLBaseFileName': 'a_file_name',
+ 'MergeSections': 'a_string',
+ 'MidlCommandFile': 'a_file_name',
+ 'ModuleDefinitionFile': 'a_file_name',
+ 'NoEntryPoint': 'true',
+ 'OptimizeReferences': '',
+ 'OutputFile': 'a_file_name',
+ 'PerUserRedirection': 'true',
+ 'Profile': 'true',
+ 'ProfileGuidedDatabase': 'a_file_name',
+ 'ProgramDatabaseFile': 'a_file_name',
+ 'RandomizedBaseAddress': 'false',
+ 'RegisterOutput': 'true',
+ 'SetChecksum': 'true',
+ 'ShowProgress': 'NotSet',
+ 'StackCommitSize': 'a_string',
+ 'StackReserveSize': 'a_string',
+ 'StripPrivateSymbols': 'a_file_name',
+ 'SubSystem': 'Windows',
+ 'SupportUnloadOfDelayLoadedDLL': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'SwapRunFromCD': 'true',
+ 'SwapRunFromNET': 'true',
+ 'TargetMachine': 'MachineARM',
+ 'TerminalServerAware': 'true',
+ 'TurnOffAssemblyGeneration': 'true',
+ 'TypeLibraryFile': 'a_file_name',
+ 'TypeLibraryResourceID': '33',
+ 'UACExecutionLevel': 'HighestAvailable',
+ 'UACUIAccess': 'true',
+ 'Version': 'a_string'},
+ 'ResourceCompile': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+ 'AdditionalOptions': 'a_string',
+ 'Culture': '0x03eb',
+ 'IgnoreStandardIncludePath': 'true',
+ 'PreprocessorDefinitions': 'd1;d2;d3',
+ 'ResourceOutputFileName': 'a_string',
+ 'ShowProgress': 'true',
+ 'SuppressStartupBanner': 'true',
+ 'UndefinePreprocessorDefinitions': 'd1;d2;d3'},
+ 'Midl': {
+ 'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+ 'AdditionalOptions': 'a_string',
+ 'CPreprocessOptions': 'a_string',
+ 'DefaultCharType': 'Unsigned',
+ 'DllDataFileName': 'a_file_name',
+ 'EnableErrorChecks': 'All',
+ 'ErrorCheckAllocations': 'true',
+ 'ErrorCheckBounds': 'true',
+ 'ErrorCheckEnumRange': 'true',
+ 'ErrorCheckRefPointers': 'true',
+ 'ErrorCheckStubData': 'true',
+ 'GenerateStublessProxies': 'true',
+ 'GenerateTypeLibrary': 'true',
+ 'HeaderFileName': 'a_file_name',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InterfaceIdentifierFileName': 'a_file_name',
+ 'MkTypLibCompatible': 'true',
+ 'OutputDirectory': 'a_string',
+ 'PreprocessorDefinitions': 'd1;d2;d3',
+ 'ProxyFileName': 'a_file_name',
+ 'RedirectOutputAndErrors': 'a_file_name',
+ 'StructMemberAlignment': '4',
+ 'SuppressStartupBanner': 'true',
+ 'TargetEnvironment': 'Win32',
+ 'TypeLibraryName': 'a_file_name',
+ 'UndefinePreprocessorDefinitions': 'd1;d2;d3',
+ 'ValidateAllParameters': 'true',
+ 'WarnAsError': 'true',
+ 'WarningLevel': '4'},
+ 'Lib': {
+ 'AdditionalDependencies': 'file1;file2;file3',
+ 'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
+ 'AdditionalOptions': 'a_string',
+ 'ExportNamedFunctions': 'd1;d2;d3',
+ 'ForceSymbolReferences': 'a_string',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
+ 'ModuleDefinitionFile': 'a_file_name',
+ 'OutputFile': 'a_file_name',
+ 'SuppressStartupBanner': 'true',
+ 'UseUnicodeResponseFiles': 'true'},
+ 'Manifest': {
+ 'AdditionalManifestFiles': 'file1;file2;file3',
+ 'AdditionalOptions': 'a_string',
+ 'AssemblyIdentity': 'a_string',
+ 'ComponentFileName': 'a_file_name',
+ 'GenerateCatalogFiles': 'true',
+ 'InputResourceManifests': 'a_string',
+ 'OutputManifestFile': 'a_file_name',
+ 'RegistrarScriptFile': 'a_file_name',
+ 'ReplacementsFile': 'a_file_name',
+ 'SuppressStartupBanner': 'true',
+ 'TypeLibraryFile': 'a_file_name',
+ 'UpdateFileHashes': 'true',
+ 'UpdateFileHashesSearchPath': 'a_file_name',
+ 'VerboseOutput': 'true'},
+ 'ManifestResourceCompile': {
+ 'ResourceOutputFileName': 'my_name'},
+ 'ProjectReference': {
+ 'LinkLibraryDependencies': 'true',
+ 'UseLibraryDependencyInputs': 'false'},
+ '': {
+ 'EmbedManifest': 'true',
+ 'GenerateManifest': 'true',
+ 'IgnoreImportLibrary': 'true',
+ 'LinkIncremental': 'false'}}
+ actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+ msvs_settings,
+ self.stderr)
+ self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+ self._ExpectedWarnings([])
+
+ def testConvertToMSBuildSettings_actual(self):
+ """Tests the conversion of an actual project.
+
+ A VS2008 project with most of the options defined was created through the
+ VS2008 IDE. It was then converted to VS2010. The tool settings found in
+ the .vcproj and .vcxproj files were converted to the two dictionaries
+ msvs_settings and expected_msbuild_settings.
+
+ Note that for many settings, the VS2010 converter adds macros like
+ %(AdditionalIncludeDirectories) to make sure than inherited values are
+ included. Since the Gyp projects we generate do not use inheritance,
+ we removed these macros. They were:
+ ClCompile:
+ AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)'
+ AdditionalOptions: ' %(AdditionalOptions)'
+ AdditionalUsingDirectories: ';%(AdditionalUsingDirectories)'
+ DisableSpecificWarnings: ';%(DisableSpecificWarnings)',
+ ForcedIncludeFiles: ';%(ForcedIncludeFiles)',
+ ForcedUsingFiles: ';%(ForcedUsingFiles)',
+ PreprocessorDefinitions: ';%(PreprocessorDefinitions)',
+ UndefinePreprocessorDefinitions:
+ ';%(UndefinePreprocessorDefinitions)',
+ Link:
+ AdditionalDependencies: ';%(AdditionalDependencies)',
+ AdditionalLibraryDirectories: ';%(AdditionalLibraryDirectories)',
+ AdditionalManifestDependencies:
+ ';%(AdditionalManifestDependencies)',
+ AdditionalOptions: ' %(AdditionalOptions)',
+ AddModuleNamesToAssembly: ';%(AddModuleNamesToAssembly)',
+ AssemblyLinkResource: ';%(AssemblyLinkResource)',
+ DelayLoadDLLs: ';%(DelayLoadDLLs)',
+ EmbedManagedResourceFile: ';%(EmbedManagedResourceFile)',
+ ForceSymbolReferences: ';%(ForceSymbolReferences)',
+ IgnoreSpecificDefaultLibraries:
+ ';%(IgnoreSpecificDefaultLibraries)',
+ ResourceCompile:
+ AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)',
+ AdditionalOptions: ' %(AdditionalOptions)',
+ PreprocessorDefinitions: ';%(PreprocessorDefinitions)',
+ Manifest:
+ AdditionalManifestFiles: ';%(AdditionalManifestFiles)',
+ AdditionalOptions: ' %(AdditionalOptions)',
+ InputResourceManifests: ';%(InputResourceManifests)',
+ """
+ msvs_settings = {
+ 'VCCLCompilerTool': {
+ 'AdditionalIncludeDirectories': 'dir1',
+ 'AdditionalOptions': '/more',
+ 'AdditionalUsingDirectories': 'test',
+ 'AssemblerListingLocation': '$(IntDir)\\a',
+ 'AssemblerOutput': '1',
+ 'BasicRuntimeChecks': '3',
+ 'BrowseInformation': '1',
+ 'BrowseInformationFile': '$(IntDir)\\e',
+ 'BufferSecurityCheck': 'false',
+ 'CallingConvention': '1',
+ 'CompileAs': '1',
+ 'DebugInformationFormat': '4',
+ 'DefaultCharIsUnsigned': 'true',
+ 'Detect64BitPortabilityProblems': 'true',
+ 'DisableLanguageExtensions': 'true',
+ 'DisableSpecificWarnings': 'abc',
+ 'EnableEnhancedInstructionSet': '1',
+ 'EnableFiberSafeOptimizations': 'true',
+ 'EnableFunctionLevelLinking': 'true',
+ 'EnableIntrinsicFunctions': 'true',
+ 'EnablePREfast': 'true',
+ 'ErrorReporting': '2',
+ 'ExceptionHandling': '2',
+ 'ExpandAttributedSource': 'true',
+ 'FavorSizeOrSpeed': '2',
+ 'FloatingPointExceptions': 'true',
+ 'FloatingPointModel': '1',
+ 'ForceConformanceInForLoopScope': 'false',
+ 'ForcedIncludeFiles': 'def',
+ 'ForcedUsingFiles': 'ge',
+ 'GeneratePreprocessedFile': '2',
+ 'GenerateXMLDocumentationFiles': 'true',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InlineFunctionExpansion': '1',
+ 'KeepComments': 'true',
+ 'MinimalRebuild': 'true',
+ 'ObjectFile': '$(IntDir)\\b',
+ 'OmitDefaultLibName': 'true',
+ 'OmitFramePointers': 'true',
+ 'OpenMP': 'true',
+ 'Optimization': '3',
+ 'PrecompiledHeaderFile': '$(IntDir)\\$(TargetName).pche',
+ 'PrecompiledHeaderThrough': 'StdAfx.hd',
+ 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE',
+ 'ProgramDataBaseFileName': '$(IntDir)\\vc90b.pdb',
+ 'RuntimeLibrary': '3',
+ 'RuntimeTypeInfo': 'false',
+ 'ShowIncludes': 'true',
+ 'SmallerTypeCheck': 'true',
+ 'StringPooling': 'true',
+ 'StructMemberAlignment': '3',
+ 'SuppressStartupBanner': 'false',
+ 'TreatWChar_tAsBuiltInType': 'false',
+ 'UndefineAllPreprocessorDefinitions': 'true',
+ 'UndefinePreprocessorDefinitions': 'wer',
+ 'UseFullPaths': 'true',
+ 'UsePrecompiledHeader': '0',
+ 'UseUnicodeResponseFiles': 'false',
+ 'WarnAsError': 'true',
+ 'WarningLevel': '3',
+ 'WholeProgramOptimization': 'true',
+ 'XMLDocumentationFileName': '$(IntDir)\\c'},
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': 'zx',
+ 'AdditionalLibraryDirectories': 'asd',
+ 'AdditionalManifestDependencies': 's2',
+ 'AdditionalOptions': '/mor2',
+ 'AddModuleNamesToAssembly': 'd1',
+ 'AllowIsolation': 'false',
+ 'AssemblyDebug': '1',
+ 'AssemblyLinkResource': 'd5',
+ 'BaseAddress': '23423',
+ 'CLRImageType': '3',
+ 'CLRThreadAttribute': '1',
+ 'CLRUnmanagedCodeCheck': 'true',
+ 'DataExecutionPrevention': '0',
+ 'DelayLoadDLLs': 'd4',
+ 'DelaySign': 'true',
+ 'Driver': '2',
+ 'EmbedManagedResourceFile': 'd2',
+ 'EnableCOMDATFolding': '1',
+ 'EnableUAC': 'false',
+ 'EntryPointSymbol': 'f5',
+ 'ErrorReporting': '2',
+ 'FixedBaseAddress': '1',
+ 'ForceSymbolReferences': 'd3',
+ 'FunctionOrder': 'fssdfsd',
+ 'GenerateDebugInformation': 'true',
+ 'GenerateManifest': 'false',
+ 'GenerateMapFile': 'true',
+ 'HeapCommitSize': '13',
+ 'HeapReserveSize': '12',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreDefaultLibraryNames': 'flob;flok',
+ 'IgnoreEmbeddedIDL': 'true',
+ 'IgnoreImportLibrary': 'true',
+ 'ImportLibrary': 'f4',
+ 'KeyContainer': 'f7',
+ 'KeyFile': 'f6',
+ 'LargeAddressAware': '2',
+ 'LinkIncremental': '0',
+ 'LinkLibraryDependencies': 'false',
+ 'LinkTimeCodeGeneration': '1',
+ 'ManifestFile':
+ '$(IntDir)\\$(TargetFileName).2intermediate.manifest',
+ 'MapExports': 'true',
+ 'MapFileName': 'd5',
+ 'MergedIDLBaseFileName': 'f2',
+ 'MergeSections': 'f5',
+ 'MidlCommandFile': 'f1',
+ 'ModuleDefinitionFile': 'sdsd',
+ 'OptimizeForWindows98': '2',
+ 'OptimizeReferences': '2',
+ 'OutputFile': '$(OutDir)\\$(ProjectName)2.exe',
+ 'PerUserRedirection': 'true',
+ 'Profile': 'true',
+ 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd',
+ 'ProgramDatabaseFile': 'Flob.pdb',
+ 'RandomizedBaseAddress': '1',
+ 'RegisterOutput': 'true',
+ 'ResourceOnlyDLL': 'true',
+ 'SetChecksum': 'false',
+ 'ShowProgress': '1',
+ 'StackCommitSize': '15',
+ 'StackReserveSize': '14',
+ 'StripPrivateSymbols': 'd3',
+ 'SubSystem': '1',
+ 'SupportUnloadOfDelayLoadedDLL': 'true',
+ 'SuppressStartupBanner': 'false',
+ 'SwapRunFromCD': 'true',
+ 'SwapRunFromNet': 'true',
+ 'TargetMachine': '1',
+ 'TerminalServerAware': '1',
+ 'TurnOffAssemblyGeneration': 'true',
+ 'TypeLibraryFile': 'f3',
+ 'TypeLibraryResourceID': '12',
+ 'UACExecutionLevel': '2',
+ 'UACUIAccess': 'true',
+ 'UseLibraryDependencyInputs': 'true',
+ 'UseUnicodeResponseFiles': 'false',
+ 'Version': '333'},
+ 'VCResourceCompilerTool': {
+ 'AdditionalIncludeDirectories': 'f3',
+ 'AdditionalOptions': '/more3',
+ 'Culture': '3084',
+ 'IgnoreStandardIncludePath': 'true',
+ 'PreprocessorDefinitions': '_UNICODE;UNICODE2',
+ 'ResourceOutputFileName': '$(IntDir)/$(InputName)3.res',
+ 'ShowProgress': 'true'},
+ 'VCManifestTool': {
+ 'AdditionalManifestFiles': 'sfsdfsd',
+ 'AdditionalOptions': 'afdsdafsd',
+ 'AssemblyIdentity': 'sddfdsadfsa',
+ 'ComponentFileName': 'fsdfds',
+ 'DependencyInformationFile': '$(IntDir)\\mt.depdfd',
+ 'EmbedManifest': 'false',
+ 'GenerateCatalogFiles': 'true',
+ 'InputResourceManifests': 'asfsfdafs',
+ 'ManifestResourceFile':
+ '$(IntDir)\\$(TargetFileName).embed.manifest.resfdsf',
+ 'OutputManifestFile': '$(TargetPath).manifestdfs',
+ 'RegistrarScriptFile': 'sdfsfd',
+ 'ReplacementsFile': 'sdffsd',
+ 'SuppressStartupBanner': 'false',
+ 'TypeLibraryFile': 'sfsd',
+ 'UpdateFileHashes': 'true',
+ 'UpdateFileHashesSearchPath': 'sfsd',
+ 'UseFAT32Workaround': 'true',
+ 'UseUnicodeResponseFiles': 'false',
+ 'VerboseOutput': 'true'}}
+ expected_msbuild_settings = {
+ 'ClCompile': {
+ 'AdditionalIncludeDirectories': 'dir1',
+ 'AdditionalOptions': '/more /J',
+ 'AdditionalUsingDirectories': 'test',
+ 'AssemblerListingLocation': '$(IntDir)a',
+ 'AssemblerOutput': 'AssemblyCode',
+ 'BasicRuntimeChecks': 'EnableFastChecks',
+ 'BrowseInformation': 'true',
+ 'BrowseInformationFile': '$(IntDir)e',
+ 'BufferSecurityCheck': 'false',
+ 'CallingConvention': 'FastCall',
+ 'CompileAs': 'CompileAsC',
+ 'DebugInformationFormat': 'EditAndContinue',
+ 'DisableLanguageExtensions': 'true',
+ 'DisableSpecificWarnings': 'abc',
+ 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions',
+ 'EnableFiberSafeOptimizations': 'true',
+ 'EnablePREfast': 'true',
+ 'ErrorReporting': 'Queue',
+ 'ExceptionHandling': 'Async',
+ 'ExpandAttributedSource': 'true',
+ 'FavorSizeOrSpeed': 'Size',
+ 'FloatingPointExceptions': 'true',
+ 'FloatingPointModel': 'Strict',
+ 'ForceConformanceInForLoopScope': 'false',
+ 'ForcedIncludeFiles': 'def',
+ 'ForcedUsingFiles': 'ge',
+ 'FunctionLevelLinking': 'true',
+ 'GenerateXMLDocumentationFiles': 'true',
+ 'IgnoreStandardIncludePath': 'true',
+ 'InlineFunctionExpansion': 'OnlyExplicitInline',
+ 'IntrinsicFunctions': 'true',
+ 'MinimalRebuild': 'true',
+ 'ObjectFileName': '$(IntDir)b',
+ 'OmitDefaultLibName': 'true',
+ 'OmitFramePointers': 'true',
+ 'OpenMPSupport': 'true',
+ 'Optimization': 'Full',
+ 'PrecompiledHeader': 'NotUsing', # Actual conversion gives ''
+ 'PrecompiledHeaderFile': 'StdAfx.hd',
+ 'PrecompiledHeaderOutputFile': '$(IntDir)$(TargetName).pche',
+ 'PreprocessKeepComments': 'true',
+ 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE',
+ 'PreprocessSuppressLineNumbers': 'true',
+ 'PreprocessToFile': 'true',
+ 'ProgramDataBaseFileName': '$(IntDir)vc90b.pdb',
+ 'RuntimeLibrary': 'MultiThreadedDebugDLL',
+ 'RuntimeTypeInfo': 'false',
+ 'ShowIncludes': 'true',
+ 'SmallerTypeCheck': 'true',
+ 'StringPooling': 'true',
+ 'StructMemberAlignment': '4Bytes',
+ 'SuppressStartupBanner': 'false',
+ 'TreatWarningAsError': 'true',
+ 'TreatWChar_tAsBuiltInType': 'false',
+ 'UndefineAllPreprocessorDefinitions': 'true',
+ 'UndefinePreprocessorDefinitions': 'wer',
+ 'UseFullPaths': 'true',
+ 'WarningLevel': 'Level3',
+ 'WholeProgramOptimization': 'true',
+ 'XMLDocumentationFileName': '$(IntDir)c'},
+ 'Link': {
+ 'AdditionalDependencies': 'zx',
+ 'AdditionalLibraryDirectories': 'asd',
+ 'AdditionalManifestDependencies': 's2',
+ 'AdditionalOptions': '/mor2',
+ 'AddModuleNamesToAssembly': 'd1',
+ 'AllowIsolation': 'false',
+ 'AssemblyDebug': 'true',
+ 'AssemblyLinkResource': 'd5',
+ 'BaseAddress': '23423',
+ 'CLRImageType': 'ForceSafeILImage',
+ 'CLRThreadAttribute': 'MTAThreadingAttribute',
+ 'CLRUnmanagedCodeCheck': 'true',
+ 'DataExecutionPrevention': '',
+ 'DelayLoadDLLs': 'd4',
+ 'DelaySign': 'true',
+ 'Driver': 'UpOnly',
+ 'EmbedManagedResourceFile': 'd2',
+ 'EnableCOMDATFolding': 'false',
+ 'EnableUAC': 'false',
+ 'EntryPointSymbol': 'f5',
+ 'FixedBaseAddress': 'false',
+ 'ForceSymbolReferences': 'd3',
+ 'FunctionOrder': 'fssdfsd',
+ 'GenerateDebugInformation': 'true',
+ 'GenerateMapFile': 'true',
+ 'HeapCommitSize': '13',
+ 'HeapReserveSize': '12',
+ 'IgnoreAllDefaultLibraries': 'true',
+ 'IgnoreEmbeddedIDL': 'true',
+ 'IgnoreSpecificDefaultLibraries': 'flob;flok',
+ 'ImportLibrary': 'f4',
+ 'KeyContainer': 'f7',
+ 'KeyFile': 'f6',
+ 'LargeAddressAware': 'true',
+ 'LinkErrorReporting': 'QueueForNextLogin',
+ 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
+ 'ManifestFile': '$(IntDir)$(TargetFileName).2intermediate.manifest',
+ 'MapExports': 'true',
+ 'MapFileName': 'd5',
+ 'MergedIDLBaseFileName': 'f2',
+ 'MergeSections': 'f5',
+ 'MidlCommandFile': 'f1',
+ 'ModuleDefinitionFile': 'sdsd',
+ 'NoEntryPoint': 'true',
+ 'OptimizeReferences': 'true',
+ 'OutputFile': '$(OutDir)$(ProjectName)2.exe',
+ 'PerUserRedirection': 'true',
+ 'Profile': 'true',
+ 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd',
+ 'ProgramDatabaseFile': 'Flob.pdb',
+ 'RandomizedBaseAddress': 'false',
+ 'RegisterOutput': 'true',
+ 'SetChecksum': 'false',
+ 'ShowProgress': 'LinkVerbose',
+ 'StackCommitSize': '15',
+ 'StackReserveSize': '14',
+ 'StripPrivateSymbols': 'd3',
+ 'SubSystem': 'Console',
+ 'SupportUnloadOfDelayLoadedDLL': 'true',
+ 'SuppressStartupBanner': 'false',
+ 'SwapRunFromCD': 'true',
+ 'SwapRunFromNET': 'true',
+ 'TargetMachine': 'MachineX86',
+ 'TerminalServerAware': 'false',
+ 'TurnOffAssemblyGeneration': 'true',
+ 'TypeLibraryFile': 'f3',
+ 'TypeLibraryResourceID': '12',
+ 'UACExecutionLevel': 'RequireAdministrator',
+ 'UACUIAccess': 'true',
+ 'Version': '333'},
+ 'ResourceCompile': {
+ 'AdditionalIncludeDirectories': 'f3',
+ 'AdditionalOptions': '/more3',
+ 'Culture': '0x0c0c',
+ 'IgnoreStandardIncludePath': 'true',
+ 'PreprocessorDefinitions': '_UNICODE;UNICODE2',
+ 'ResourceOutputFileName': '$(IntDir)%(Filename)3.res',
+ 'ShowProgress': 'true'},
+ 'Manifest': {
+ 'AdditionalManifestFiles': 'sfsdfsd',
+ 'AdditionalOptions': 'afdsdafsd',
+ 'AssemblyIdentity': 'sddfdsadfsa',
+ 'ComponentFileName': 'fsdfds',
+ 'GenerateCatalogFiles': 'true',
+ 'InputResourceManifests': 'asfsfdafs',
+ 'OutputManifestFile': '$(TargetPath).manifestdfs',
+ 'RegistrarScriptFile': 'sdfsfd',
+ 'ReplacementsFile': 'sdffsd',
+ 'SuppressStartupBanner': 'false',
+ 'TypeLibraryFile': 'sfsd',
+ 'UpdateFileHashes': 'true',
+ 'UpdateFileHashesSearchPath': 'sfsd',
+ 'VerboseOutput': 'true'},
+ 'ProjectReference': {
+ 'LinkLibraryDependencies': 'false',
+ 'UseLibraryDependencyInputs': 'true'},
+ '': {
+ 'EmbedManifest': 'false',
+ 'GenerateManifest': 'false',
+ 'IgnoreImportLibrary': 'true',
+ 'LinkIncremental': ''
+ },
+ 'ManifestResourceCompile': {
+ 'ResourceOutputFileName':
+ '$(IntDir)$(TargetFileName).embed.manifest.resfdsf'}
+ }
+ actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+ msvs_settings,
+ self.stderr)
+ self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+ self._ExpectedWarnings([])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSToolFile.py b/chromium/tools/gyp/pylib/gyp/MSVSToolFile.py
new file mode 100644
index 00000000000..74e529a17f1
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/MSVSToolFile.py
@@ -0,0 +1,58 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Visual Studio project reader/writer."""
+
+import gyp.common
+import gyp.easy_xml as easy_xml
+
+
+class Writer(object):
+ """Visual Studio XML tool file writer."""
+
+ def __init__(self, tool_file_path, name):
+ """Initializes the tool file.
+
+ Args:
+ tool_file_path: Path to the tool file.
+ name: Name of the tool file.
+ """
+ self.tool_file_path = tool_file_path
+ self.name = name
+ self.rules_section = ['Rules']
+
+ def AddCustomBuildRule(self, name, cmd, description,
+ additional_dependencies,
+ outputs, extensions):
+ """Adds a rule to the tool file.
+
+ Args:
+ name: Name of the rule.
+ description: Description of the rule.
+ cmd: Command line of the rule.
+ additional_dependencies: other files which may trigger the rule.
+ outputs: outputs of the rule.
+ extensions: extensions handled by the rule.
+ """
+ rule = ['CustomBuildRule',
+ {'Name': name,
+ 'ExecutionDescription': description,
+ 'CommandLine': cmd,
+ 'Outputs': ';'.join(outputs),
+ 'FileExtensions': ';'.join(extensions),
+ 'AdditionalDependencies':
+ ';'.join(additional_dependencies)
+ }]
+ self.rules_section.append(rule)
+
+ def WriteIfChanged(self):
+ """Writes the tool file."""
+ content = ['VisualStudioToolFile',
+ {'Version': '8.00',
+ 'Name': self.name
+ },
+ self.rules_section
+ ]
+ easy_xml.WriteXmlIfChanged(content, self.tool_file_path,
+ encoding="Windows-1252")
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSUserFile.py b/chromium/tools/gyp/pylib/gyp/MSVSUserFile.py
new file mode 100644
index 00000000000..6c07e9a893b
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/MSVSUserFile.py
@@ -0,0 +1,147 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Visual Studio user preferences file writer."""
+
+import os
+import re
+import socket # for gethostname
+
+import gyp.common
+import gyp.easy_xml as easy_xml
+
+
+#------------------------------------------------------------------------------
+
+def _FindCommandInPath(command):
+ """If there are no slashes in the command given, this function
+ searches the PATH env to find the given command, and converts it
+ to an absolute path. We have to do this because MSVS is looking
+ for an actual file to launch a debugger on, not just a command
+ line. Note that this happens at GYP time, so anything needing to
+ be built needs to have a full path."""
+ if '/' in command or '\\' in command:
+ # If the command already has path elements (either relative or
+ # absolute), then assume it is constructed properly.
+ return command
+ else:
+ # Search through the path list and find an existing file that
+ # we can access.
+ paths = os.environ.get('PATH','').split(os.pathsep)
+ for path in paths:
+ item = os.path.join(path, command)
+ if os.path.isfile(item) and os.access(item, os.X_OK):
+ return item
+ return command
+
+def _QuoteWin32CommandLineArgs(args):
+ new_args = []
+ for arg in args:
+ # Replace all double-quotes with double-double-quotes to escape
+ # them for cmd shell, and then quote the whole thing if there
+ # are any.
+ if arg.find('"') != -1:
+ arg = '""'.join(arg.split('"'))
+ arg = '"%s"' % arg
+
+ # Otherwise, if there are any spaces, quote the whole arg.
+ elif re.search(r'[ \t\n]', arg):
+ arg = '"%s"' % arg
+ new_args.append(arg)
+ return new_args
+
+class Writer(object):
+ """Visual Studio XML user user file writer."""
+
+ def __init__(self, user_file_path, version, name):
+ """Initializes the user file.
+
+ Args:
+ user_file_path: Path to the user file.
+ version: Version info.
+ name: Name of the user file.
+ """
+ self.user_file_path = user_file_path
+ self.version = version
+ self.name = name
+ self.configurations = {}
+
+ def AddConfig(self, name):
+ """Adds a configuration to the project.
+
+ Args:
+ name: Configuration name.
+ """
+ self.configurations[name] = ['Configuration', {'Name': name}]
+
+ def AddDebugSettings(self, config_name, command, environment = {},
+ working_directory=""):
+ """Adds a DebugSettings node to the user file for a particular config.
+
+ Args:
+ command: command line to run. First element in the list is the
+ executable. All elements of the command will be quoted if
+ necessary.
+ working_directory: other files which may trigger the rule. (optional)
+ """
+ command = _QuoteWin32CommandLineArgs(command)
+
+ abs_command = _FindCommandInPath(command[0])
+
+ if environment and isinstance(environment, dict):
+ env_list = ['%s="%s"' % (key, val)
+ for (key,val) in environment.iteritems()]
+ environment = ' '.join(env_list)
+ else:
+ environment = ''
+
+ n_cmd = ['DebugSettings',
+ {'Command': abs_command,
+ 'WorkingDirectory': working_directory,
+ 'CommandArguments': " ".join(command[1:]),
+ 'RemoteMachine': socket.gethostname(),
+ 'Environment': environment,
+ 'EnvironmentMerge': 'true',
+ # Currently these are all "dummy" values that we're just setting
+ # in the default manner that MSVS does it. We could use some of
+ # these to add additional capabilities, I suppose, but they might
+ # not have parity with other platforms then.
+ 'Attach': 'false',
+ 'DebuggerType': '3', # 'auto' debugger
+ 'Remote': '1',
+ 'RemoteCommand': '',
+ 'HttpUrl': '',
+ 'PDBPath': '',
+ 'SQLDebugging': '',
+ 'DebuggerFlavor': '0',
+ 'MPIRunCommand': '',
+ 'MPIRunArguments': '',
+ 'MPIRunWorkingDirectory': '',
+ 'ApplicationCommand': '',
+ 'ApplicationArguments': '',
+ 'ShimCommand': '',
+ 'MPIAcceptMode': '',
+ 'MPIAcceptFilter': ''
+ }]
+
+ # Find the config, and add it if it doesn't exist.
+ if config_name not in self.configurations:
+ self.AddConfig(config_name)
+
+ # Add the DebugSettings onto the appropriate config.
+ self.configurations[config_name].append(n_cmd)
+
+ def WriteIfChanged(self):
+ """Writes the user file."""
+ configs = ['Configurations']
+ for config, spec in sorted(self.configurations.iteritems()):
+ configs.append(spec)
+
+ content = ['VisualStudioUserFile',
+ {'Version': self.version.ProjectVersion(),
+ 'Name': self.name
+ },
+ configs]
+ easy_xml.WriteXmlIfChanged(content, self.user_file_path,
+ encoding="Windows-1252")
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSUtil.py b/chromium/tools/gyp/pylib/gyp/MSVSUtil.py
new file mode 100644
index 00000000000..62e8d260d44
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/MSVSUtil.py
@@ -0,0 +1,267 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility functions shared amongst the Windows generators."""
+
+import copy
+import os
+
+
+_TARGET_TYPE_EXT = {
+ 'executable': '.exe',
+ 'loadable_module': '.dll',
+ 'shared_library': '.dll',
+}
+
+
+def _GetLargePdbShimCcPath():
+ """Returns the path of the large_pdb_shim.cc file."""
+ this_dir = os.path.abspath(os.path.dirname(__file__))
+ src_dir = os.path.abspath(os.path.join(this_dir, '..', '..'))
+ win_data_dir = os.path.join(src_dir, 'data', 'win')
+ large_pdb_shim_cc = os.path.join(win_data_dir, 'large-pdb-shim.cc')
+ return large_pdb_shim_cc
+
+
+def _DeepCopySomeKeys(in_dict, keys):
+ """Performs a partial deep-copy on |in_dict|, only copying the keys in |keys|.
+
+ Arguments:
+ in_dict: The dictionary to copy.
+ keys: The keys to be copied. If a key is in this list and doesn't exist in
+ |in_dict| this is not an error.
+ Returns:
+ The partially deep-copied dictionary.
+ """
+ d = {}
+ for key in keys:
+ if key not in in_dict:
+ continue
+ d[key] = copy.deepcopy(in_dict[key])
+ return d
+
+
+def _SuffixName(name, suffix):
+ """Add a suffix to the end of a target.
+
+ Arguments:
+ name: name of the target (foo#target)
+ suffix: the suffix to be added
+ Returns:
+ Target name with suffix added (foo_suffix#target)
+ """
+ parts = name.rsplit('#', 1)
+ parts[0] = '%s_%s' % (parts[0], suffix)
+ return '#'.join(parts)
+
+
+def _ShardName(name, number):
+ """Add a shard number to the end of a target.
+
+ Arguments:
+ name: name of the target (foo#target)
+ number: shard number
+ Returns:
+ Target name with shard added (foo_1#target)
+ """
+ return _SuffixName(name, str(number))
+
+
+def ShardTargets(target_list, target_dicts):
+ """Shard some targets apart to work around the linkers limits.
+
+ Arguments:
+ target_list: List of target pairs: 'base/base.gyp:base'.
+ target_dicts: Dict of target properties keyed on target pair.
+ Returns:
+ Tuple of the new sharded versions of the inputs.
+ """
+ # Gather the targets to shard, and how many pieces.
+ targets_to_shard = {}
+ for t in target_dicts:
+ shards = int(target_dicts[t].get('msvs_shard', 0))
+ if shards:
+ targets_to_shard[t] = shards
+ # Shard target_list.
+ new_target_list = []
+ for t in target_list:
+ if t in targets_to_shard:
+ for i in range(targets_to_shard[t]):
+ new_target_list.append(_ShardName(t, i))
+ else:
+ new_target_list.append(t)
+ # Shard target_dict.
+ new_target_dicts = {}
+ for t in target_dicts:
+ if t in targets_to_shard:
+ for i in range(targets_to_shard[t]):
+ name = _ShardName(t, i)
+ new_target_dicts[name] = copy.copy(target_dicts[t])
+ new_target_dicts[name]['target_name'] = _ShardName(
+ new_target_dicts[name]['target_name'], i)
+ sources = new_target_dicts[name].get('sources', [])
+ new_sources = []
+ for pos in range(i, len(sources), targets_to_shard[t]):
+ new_sources.append(sources[pos])
+ new_target_dicts[name]['sources'] = new_sources
+ else:
+ new_target_dicts[t] = target_dicts[t]
+ # Shard dependencies.
+ for t in new_target_dicts:
+ dependencies = copy.copy(new_target_dicts[t].get('dependencies', []))
+ new_dependencies = []
+ for d in dependencies:
+ if d in targets_to_shard:
+ for i in range(targets_to_shard[d]):
+ new_dependencies.append(_ShardName(d, i))
+ else:
+ new_dependencies.append(d)
+ new_target_dicts[t]['dependencies'] = new_dependencies
+
+ return (new_target_list, new_target_dicts)
+
+
+def _GetPdbPath(target_dict, config_name, vars):
+ """Returns the path to the PDB file that will be generated by a given
+ configuration.
+
+ The lookup proceeds as follows:
+ - Look for an explicit path in the VCLinkerTool configuration block.
+ - Look for an 'msvs_large_pdb_path' variable.
+ - Use '<(PRODUCT_DIR)/<(product_name).(exe|dll).pdb' if 'product_name' is
+ specified.
+ - Use '<(PRODUCT_DIR)/<(target_name).(exe|dll).pdb'.
+
+ Arguments:
+ target_dict: The target dictionary to be searched.
+ config_name: The name of the configuration of interest.
+ vars: A dictionary of common GYP variables with generator-specific values.
+ Returns:
+ The path of the corresponding PDB file.
+ """
+ config = target_dict['configurations'][config_name]
+ msvs = config.setdefault('msvs_settings', {})
+
+ linker = msvs.get('VCLinkerTool', {})
+
+ pdb_path = linker.get('ProgramDatabaseFile')
+ if pdb_path:
+ return pdb_path
+
+ variables = target_dict.get('variables', {})
+ pdb_path = variables.get('msvs_large_pdb_path', None)
+ if pdb_path:
+ return pdb_path
+
+
+ pdb_base = target_dict.get('product_name', target_dict['target_name'])
+ pdb_base = '%s%s.pdb' % (pdb_base, _TARGET_TYPE_EXT[target_dict['type']])
+ pdb_path = vars['PRODUCT_DIR'] + '/' + pdb_base
+
+ return pdb_path
+
+
+def InsertLargePdbShims(target_list, target_dicts, vars):
+ """Insert a shim target that forces the linker to use 4KB pagesize PDBs.
+
+ This is a workaround for targets with PDBs greater than 1GB in size, the
+ limit for the 1KB pagesize PDBs created by the linker by default.
+
+ Arguments:
+ target_list: List of target pairs: 'base/base.gyp:base'.
+ target_dicts: Dict of target properties keyed on target pair.
+ vars: A dictionary of common GYP variables with generator-specific values.
+ Returns:
+ Tuple of the shimmed version of the inputs.
+ """
+ # Determine which targets need shimming.
+ targets_to_shim = []
+ for t in target_dicts:
+ target_dict = target_dicts[t]
+
+ # We only want to shim targets that have msvs_large_pdb enabled.
+ if not int(target_dict.get('msvs_large_pdb', 0)):
+ continue
+ # This is intended for executable, shared_library and loadable_module
+ # targets where every configuration is set up to produce a PDB output.
+ # If any of these conditions is not true then the shim logic will fail
+ # below.
+ targets_to_shim.append(t)
+
+ large_pdb_shim_cc = _GetLargePdbShimCcPath()
+
+ for t in targets_to_shim:
+ target_dict = target_dicts[t]
+ target_name = target_dict.get('target_name')
+
+ base_dict = _DeepCopySomeKeys(target_dict,
+ ['configurations', 'default_configuration', 'toolset'])
+
+ # This is the dict for copying the source file (part of the GYP tree)
+ # to the intermediate directory of the project. This is necessary because
+ # we can't always build a relative path to the shim source file (on Windows
+ # GYP and the project may be on different drives), and Ninja hates absolute
+ # paths (it ends up generating the .obj and .obj.d alongside the source
+ # file, polluting GYPs tree).
+ copy_suffix = 'large_pdb_copy'
+ copy_target_name = target_name + '_' + copy_suffix
+ full_copy_target_name = _SuffixName(t, copy_suffix)
+ shim_cc_basename = os.path.basename(large_pdb_shim_cc)
+ shim_cc_dir = vars['SHARED_INTERMEDIATE_DIR'] + '/' + copy_target_name
+ shim_cc_path = shim_cc_dir + '/' + shim_cc_basename
+ copy_dict = copy.deepcopy(base_dict)
+ copy_dict['target_name'] = copy_target_name
+ copy_dict['type'] = 'none'
+ copy_dict['sources'] = [ large_pdb_shim_cc ]
+ copy_dict['copies'] = [{
+ 'destination': shim_cc_dir,
+ 'files': [ large_pdb_shim_cc ]
+ }]
+
+ # This is the dict for the PDB generating shim target. It depends on the
+ # copy target.
+ shim_suffix = 'large_pdb_shim'
+ shim_target_name = target_name + '_' + shim_suffix
+ full_shim_target_name = _SuffixName(t, shim_suffix)
+ shim_dict = copy.deepcopy(base_dict)
+ shim_dict['target_name'] = shim_target_name
+ shim_dict['type'] = 'static_library'
+ shim_dict['sources'] = [ shim_cc_path ]
+ shim_dict['dependencies'] = [ full_copy_target_name ]
+
+ # Set up the shim to output its PDB to the same location as the final linker
+ # target.
+ for config_name, config in shim_dict.get('configurations').iteritems():
+ pdb_path = _GetPdbPath(target_dict, config_name, vars)
+
+ # A few keys that we don't want to propagate.
+ for key in ['msvs_precompiled_header', 'msvs_precompiled_source', 'test']:
+ config.pop(key, None)
+
+ msvs = config.setdefault('msvs_settings', {})
+
+ # Update the compiler directives in the shim target.
+ compiler = msvs.setdefault('VCCLCompilerTool', {})
+ compiler['DebugInformationFormat'] = '3'
+ compiler['ProgramDataBaseFileName'] = pdb_path
+
+ # Set the explicit PDB path in the appropriate configuration of the
+ # original target.
+ config = target_dict['configurations'][config_name]
+ msvs = config.setdefault('msvs_settings', {})
+ linker = msvs.setdefault('VCLinkerTool', {})
+ linker['GenerateDebugInformation'] = 'true'
+ linker['ProgramDatabaseFile'] = pdb_path
+
+ # Add the new targets. They must go to the beginning of the list so that
+ # the dependency generation works as expected in ninja.
+ target_list.insert(0, full_copy_target_name)
+ target_list.insert(0, full_shim_target_name)
+ target_dicts[full_copy_target_name] = copy_dict
+ target_dicts[full_shim_target_name] = shim_dict
+
+ # Update the original target to depend on the shim target.
+ target_dict.setdefault('dependencies', []).append(full_shim_target_name)
+
+ return (target_list, target_dicts) \ No newline at end of file
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSVersion.py b/chromium/tools/gyp/pylib/gyp/MSVSVersion.py
new file mode 100644
index 00000000000..4e4dbf33a70
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/MSVSVersion.py
@@ -0,0 +1,399 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Handle version information related to Visual Stuio."""
+
+import errno
+import os
+import re
+import subprocess
+import sys
+import gyp
+
+
+class VisualStudioVersion(object):
+ """Information regarding a version of Visual Studio."""
+
+ def __init__(self, short_name, description,
+ solution_version, project_version, flat_sln, uses_vcxproj,
+ path, sdk_based, default_toolset=None):
+ self.short_name = short_name
+ self.description = description
+ self.solution_version = solution_version
+ self.project_version = project_version
+ self.flat_sln = flat_sln
+ self.uses_vcxproj = uses_vcxproj
+ self.path = path
+ self.sdk_based = sdk_based
+ self.default_toolset = default_toolset
+
+ def ShortName(self):
+ return self.short_name
+
+ def Description(self):
+ """Get the full description of the version."""
+ return self.description
+
+ def SolutionVersion(self):
+ """Get the version number of the sln files."""
+ return self.solution_version
+
+ def ProjectVersion(self):
+ """Get the version number of the vcproj or vcxproj files."""
+ return self.project_version
+
+ def FlatSolution(self):
+ return self.flat_sln
+
+ def UsesVcxproj(self):
+ """Returns true if this version uses a vcxproj file."""
+ return self.uses_vcxproj
+
+ def ProjectExtension(self):
+ """Returns the file extension for the project."""
+ return self.uses_vcxproj and '.vcxproj' or '.vcproj'
+
+ def Path(self):
+ """Returns the path to Visual Studio installation."""
+ return self.path
+
+ def ToolPath(self, tool):
+ """Returns the path to a given compiler tool. """
+ return os.path.normpath(os.path.join(self.path, "VC/bin", tool))
+
+ def DefaultToolset(self):
+ """Returns the msbuild toolset version that will be used in the absence
+ of a user override."""
+ return self.default_toolset
+
+ def SetupScript(self, target_arch):
+ """Returns a command (with arguments) to be used to set up the
+ environment."""
+ # Check if we are running in the SDK command line environment and use
+ # the setup script from the SDK if so. |target_arch| should be either
+ # 'x86' or 'x64'.
+ assert target_arch in ('x86', 'x64')
+ sdk_dir = os.environ.get('WindowsSDKDir')
+ if self.sdk_based and sdk_dir:
+ return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')),
+ '/' + target_arch]
+ else:
+ # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls
+ # vcvars32, which it can only find if VS??COMNTOOLS is set, which it
+ # isn't always.
+ if target_arch == 'x86':
+ return [os.path.normpath(
+ os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))]
+ else:
+ assert target_arch == 'x64'
+ arg = 'x86_amd64'
+ if (os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or
+ os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'):
+ # Use the 64-on-64 compiler if we can.
+ arg = 'amd64'
+ return [os.path.normpath(
+ os.path.join(self.path, 'VC/vcvarsall.bat')), arg]
+
+
+def _RegistryQueryBase(sysdir, key, value):
+ """Use reg.exe to read a particular key.
+
+ While ideally we might use the win32 module, we would like gyp to be
+ python neutral, so for instance cygwin python lacks this module.
+
+ Arguments:
+ sysdir: The system subdirectory to attempt to launch reg.exe from.
+ key: The registry key to read from.
+ value: The particular value to read.
+ Return:
+ stdout from reg.exe, or None for failure.
+ """
+ # Skip if not on Windows or Python Win32 setup issue
+ if sys.platform not in ('win32', 'cygwin'):
+ return None
+ # Setup params to pass to and attempt to launch reg.exe
+ cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
+ 'query', key]
+ if value:
+ cmd.extend(['/v', value])
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
+ # Note that the error text may be in [1] in some cases
+ text = p.communicate()[0]
+ # Check return code from reg.exe; officially 0==success and 1==error
+ if p.returncode:
+ return None
+ return text
+
+
+def _RegistryQuery(key, value=None):
+ """Use reg.exe to read a particular key through _RegistryQueryBase.
+
+ First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
+ that fails, it falls back to System32. Sysnative is available on Vista and
+ up and available on Windows Server 2003 and XP through KB patch 942589. Note
+ that Sysnative will always fail if using 64-bit python due to it being a
+ virtual directory and System32 will work correctly in the first place.
+
+ KB 942589 - http://support.microsoft.com/kb/942589/en-us.
+
+ Arguments:
+ key: The registry key.
+ value: The particular registry value to read (optional).
+ Return:
+ stdout from reg.exe, or None for failure.
+ """
+ text = None
+ try:
+ text = _RegistryQueryBase('Sysnative', key, value)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ text = _RegistryQueryBase('System32', key, value)
+ else:
+ raise
+ return text
+
+
+def _RegistryGetValue(key, value):
+ """Use reg.exe to obtain the value of a registry key.
+
+ Args:
+ key: The registry key.
+ value: The particular registry value to read.
+ Return:
+ contents of the registry key's value, or None on failure.
+ """
+ text = _RegistryQuery(key, value)
+ if not text:
+ return None
+ # Extract value.
+ match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
+ if not match:
+ return None
+ return match.group(1)
+
+
+def _RegistryKeyExists(key):
+ """Use reg.exe to see if a key exists.
+
+ Args:
+ key: The registry key to check.
+ Return:
+ True if the key exists
+ """
+ if not _RegistryQuery(key):
+ return False
+ return True
+
+
+def _CreateVersion(name, path, sdk_based=False):
+ """Sets up MSVS project generation.
+
+ Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
+ autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
+ passed in that doesn't match a value in versions python will throw a error.
+ """
+ if path:
+ path = os.path.normpath(path)
+ versions = {
+ '2013': VisualStudioVersion('2013',
+ 'Visual Studio 2013',
+ solution_version='13.00',
+ project_version='12.0',
+ flat_sln=False,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based,
+ default_toolset='v120'),
+ '2013e': VisualStudioVersion('2013e',
+ 'Visual Studio 2013',
+ solution_version='13.00',
+ project_version='12.0',
+ flat_sln=True,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based,
+ default_toolset='v120'),
+ '2012': VisualStudioVersion('2012',
+ 'Visual Studio 2012',
+ solution_version='12.00',
+ project_version='4.0',
+ flat_sln=False,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based,
+ default_toolset='v110'),
+ '2012e': VisualStudioVersion('2012e',
+ 'Visual Studio 2012',
+ solution_version='12.00',
+ project_version='4.0',
+ flat_sln=True,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based,
+ default_toolset='v110'),
+ '2010': VisualStudioVersion('2010',
+ 'Visual Studio 2010',
+ solution_version='11.00',
+ project_version='4.0',
+ flat_sln=False,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based),
+ '2010e': VisualStudioVersion('2010e',
+ 'Visual Studio 2010',
+ solution_version='11.00',
+ project_version='4.0',
+ flat_sln=True,
+ uses_vcxproj=True,
+ path=path,
+ sdk_based=sdk_based),
+ '2008': VisualStudioVersion('2008',
+ 'Visual Studio 2008',
+ solution_version='10.00',
+ project_version='9.00',
+ flat_sln=False,
+ uses_vcxproj=False,
+ path=path,
+ sdk_based=sdk_based),
+ '2008e': VisualStudioVersion('2008e',
+ 'Visual Studio 2008',
+ solution_version='10.00',
+ project_version='9.00',
+ flat_sln=True,
+ uses_vcxproj=False,
+ path=path,
+ sdk_based=sdk_based),
+ '2005': VisualStudioVersion('2005',
+ 'Visual Studio 2005',
+ solution_version='9.00',
+ project_version='8.00',
+ flat_sln=False,
+ uses_vcxproj=False,
+ path=path,
+ sdk_based=sdk_based),
+ '2005e': VisualStudioVersion('2005e',
+ 'Visual Studio 2005',
+ solution_version='9.00',
+ project_version='8.00',
+ flat_sln=True,
+ uses_vcxproj=False,
+ path=path,
+ sdk_based=sdk_based),
+ }
+ return versions[str(name)]
+
+
+def _ConvertToCygpath(path):
+ """Convert to cygwin path if we are using cygwin."""
+ if sys.platform == 'cygwin':
+ p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE)
+ path = p.communicate()[0].strip()
+ return path
+
+
+def _DetectVisualStudioVersions(versions_to_check, force_express):
+ """Collect the list of installed visual studio versions.
+
+ Returns:
+ A list of visual studio versions installed in descending order of
+ usage preference.
+ Base this on the registry and a quick check if devenv.exe exists.
+ Only versions 8-10 are considered.
+ Possibilities are:
+ 2005(e) - Visual Studio 2005 (8)
+ 2008(e) - Visual Studio 2008 (9)
+ 2010(e) - Visual Studio 2010 (10)
+ 2012(e) - Visual Studio 2012 (11)
+ 2013(e) - Visual Studio 2013 (11)
+ Where (e) is e for express editions of MSVS and blank otherwise.
+ """
+ version_to_year = {
+ '8.0': '2005',
+ '9.0': '2008',
+ '10.0': '2010',
+ '11.0': '2012',
+ '12.0': '2013',
+ }
+ versions = []
+ for version in versions_to_check:
+ # Old method of searching for which VS version is installed
+ # We don't use the 2010-encouraged-way because we also want to get the
+ # path to the binaries, which it doesn't offer.
+ keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
+ r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version,
+ r'HKLM\Software\Microsoft\VCExpress\%s' % version,
+ r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version]
+ for index in range(len(keys)):
+ path = _RegistryGetValue(keys[index], 'InstallDir')
+ if not path:
+ continue
+ path = _ConvertToCygpath(path)
+ # Check for full.
+ full_path = os.path.join(path, 'devenv.exe')
+ express_path = os.path.join(path, 'vcexpress.exe')
+ if not force_express and os.path.exists(full_path):
+ # Add this one.
+ versions.append(_CreateVersion(version_to_year[version],
+ os.path.join(path, '..', '..')))
+ # Check for express.
+ elif os.path.exists(express_path):
+ # Add this one.
+ versions.append(_CreateVersion(version_to_year[version] + 'e',
+ os.path.join(path, '..', '..')))
+
+ # The old method above does not work when only SDK is installed.
+ keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7',
+ r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7']
+ for index in range(len(keys)):
+ path = _RegistryGetValue(keys[index], version)
+ if not path:
+ continue
+ path = _ConvertToCygpath(path)
+ versions.append(_CreateVersion(version_to_year[version] + 'e',
+ os.path.join(path, '..'), sdk_based=True))
+
+ return versions
+
+
+def SelectVisualStudioVersion(version='auto'):
+ """Select which version of Visual Studio projects to generate.
+
+ Arguments:
+ version: Hook to allow caller to force a particular version (vs auto).
+ Returns:
+ An object representing a visual studio project format version.
+ """
+ # In auto mode, check environment variable for override.
+ if version == 'auto':
+ version = os.environ.get('GYP_MSVS_VERSION', 'auto')
+ version_map = {
+ 'auto': ('10.0', '9.0', '8.0', '11.0'),
+ '2005': ('8.0',),
+ '2005e': ('8.0',),
+ '2008': ('9.0',),
+ '2008e': ('9.0',),
+ '2010': ('10.0',),
+ '2010e': ('10.0',),
+ '2012': ('11.0',),
+ '2012e': ('11.0',),
+ '2013': ('12.0',),
+ '2013e': ('12.0',),
+ }
+ override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH')
+ if override_path:
+ msvs_version = os.environ.get('GYP_MSVS_VERSION')
+ if not msvs_version or 'e' not in msvs_version:
+ raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be '
+ 'set to an "e" version (e.g. 2010e)')
+ return _CreateVersion(msvs_version, override_path, sdk_based=True)
+ version = str(version)
+ versions = _DetectVisualStudioVersions(version_map[version], 'e' in version)
+ if not versions:
+ if version == 'auto':
+ # Default to 2005 if we couldn't find anything
+ return _CreateVersion('2005', None)
+ else:
+ return _CreateVersion(version, None)
+ return versions[0]
diff --git a/chromium/tools/gyp/pylib/gyp/__init__.py b/chromium/tools/gyp/pylib/gyp/__init__.py
new file mode 100755
index 00000000000..3b921e63f79
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/__init__.py
@@ -0,0 +1,546 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import gyp.input
+import optparse
+import os.path
+import re
+import shlex
+import sys
+import traceback
+from gyp.common import GypError
+
+# Default debug modes for GYP
+debug = {}
+
+# List of "official" debug modes, but you can use anything you like.
+DEBUG_GENERAL = 'general'
+DEBUG_VARIABLES = 'variables'
+DEBUG_INCLUDES = 'includes'
+
+
+def DebugOutput(mode, message, *args):
+ if 'all' in gyp.debug or mode in gyp.debug:
+ ctx = ('unknown', 0, 'unknown')
+ try:
+ f = traceback.extract_stack(limit=2)
+ if f:
+ ctx = f[0][:3]
+ except:
+ pass
+ if args:
+ message %= args
+ print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]),
+ ctx[1], ctx[2], message)
+
+def FindBuildFiles():
+ extension = '.gyp'
+ files = os.listdir(os.getcwd())
+ build_files = []
+ for file in files:
+ if file.endswith(extension):
+ build_files.append(file)
+ return build_files
+
+
+def Load(build_files, format, default_variables={},
+ includes=[], depth='.', params=None, check=False,
+ circular_check=True):
+ """
+ Loads one or more specified build files.
+ default_variables and includes will be copied before use.
+ Returns the generator for the specified format and the
+ data returned by loading the specified build files.
+ """
+ if params is None:
+ params = {}
+
+ flavor = None
+ if '-' in format:
+ format, params['flavor'] = format.split('-', 1)
+
+ default_variables = copy.copy(default_variables)
+
+ # Default variables provided by this program and its modules should be
+ # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace,
+ # avoiding collisions with user and automatic variables.
+ default_variables['GENERATOR'] = format
+
+ # Format can be a custom python file, or by default the name of a module
+ # within gyp.generator.
+ if format.endswith('.py'):
+ generator_name = os.path.splitext(format)[0]
+ path, generator_name = os.path.split(generator_name)
+
+ # Make sure the path to the custom generator is in sys.path
+ # Don't worry about removing it once we are done. Keeping the path
+ # to each generator that is used in sys.path is likely harmless and
+ # arguably a good idea.
+ path = os.path.abspath(path)
+ if path not in sys.path:
+ sys.path.insert(0, path)
+ else:
+ generator_name = 'gyp.generator.' + format
+
+ # These parameters are passed in order (as opposed to by key)
+ # because ActivePython cannot handle key parameters to __import__.
+ generator = __import__(generator_name, globals(), locals(), generator_name)
+ for (key, val) in generator.generator_default_variables.items():
+ default_variables.setdefault(key, val)
+
+ # Give the generator the opportunity to set additional variables based on
+ # the params it will receive in the output phase.
+ if getattr(generator, 'CalculateVariables', None):
+ generator.CalculateVariables(default_variables, params)
+
+ # Give the generator the opportunity to set generator_input_info based on
+ # the params it will receive in the output phase.
+ if getattr(generator, 'CalculateGeneratorInputInfo', None):
+ generator.CalculateGeneratorInputInfo(params)
+
+ # Fetch the generator specific info that gets fed to input, we use getattr
+ # so we can default things and the generators only have to provide what
+ # they need.
+ generator_input_info = {
+ 'generator_wants_absolute_build_file_paths':
+ getattr(generator, 'generator_wants_absolute_build_file_paths', False),
+ 'generator_handles_variants':
+ getattr(generator, 'generator_handles_variants', False),
+ 'non_configuration_keys':
+ getattr(generator, 'generator_additional_non_configuration_keys', []),
+ 'path_sections':
+ getattr(generator, 'generator_additional_path_sections', []),
+ 'extra_sources_for_rules':
+ getattr(generator, 'generator_extra_sources_for_rules', []),
+ 'generator_supports_multiple_toolsets':
+ getattr(generator, 'generator_supports_multiple_toolsets', False),
+ 'generator_wants_static_library_dependencies_adjusted':
+ getattr(generator,
+ 'generator_wants_static_library_dependencies_adjusted', True),
+ 'generator_wants_sorted_dependencies':
+ getattr(generator, 'generator_wants_sorted_dependencies', False),
+ }
+
+ # Process the input specific to this generator.
+ result = gyp.input.Load(build_files, default_variables, includes[:],
+ depth, generator_input_info, check, circular_check,
+ params['parallel'])
+ return [generator] + result
+
+def NameValueListToDict(name_value_list):
+ """
+ Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary
+ of the pairs. If a string is simply NAME, then the value in the dictionary
+ is set to True. If VALUE can be converted to an integer, it is.
+ """
+ result = { }
+ for item in name_value_list:
+ tokens = item.split('=', 1)
+ if len(tokens) == 2:
+ # If we can make it an int, use that, otherwise, use the string.
+ try:
+ token_value = int(tokens[1])
+ except ValueError:
+ token_value = tokens[1]
+ # Set the variable to the supplied value.
+ result[tokens[0]] = token_value
+ else:
+ # No value supplied, treat it as a boolean and set it.
+ result[tokens[0]] = True
+ return result
+
+def ShlexEnv(env_name):
+ flags = os.environ.get(env_name, [])
+ if flags:
+ flags = shlex.split(flags)
+ return flags
+
+def FormatOpt(opt, value):
+ if opt.startswith('--'):
+ return '%s=%s' % (opt, value)
+ return opt + value
+
+def RegenerateAppendFlag(flag, values, predicate, env_name, options):
+ """Regenerate a list of command line flags, for an option of action='append'.
+
+ The |env_name|, if given, is checked in the environment and used to generate
+ an initial list of options, then the options that were specified on the
+ command line (given in |values|) are appended. This matches the handling of
+ environment variables and command line flags where command line flags override
+ the environment, while not requiring the environment to be set when the flags
+ are used again.
+ """
+ flags = []
+ if options.use_environment and env_name:
+ for flag_value in ShlexEnv(env_name):
+ value = FormatOpt(flag, predicate(flag_value))
+ if value in flags:
+ flags.remove(value)
+ flags.append(value)
+ if values:
+ for flag_value in values:
+ flags.append(FormatOpt(flag, predicate(flag_value)))
+ return flags
+
+def RegenerateFlags(options):
+ """Given a parsed options object, and taking the environment variables into
+ account, returns a list of flags that should regenerate an equivalent options
+ object (even in the absence of the environment variables.)
+
+ Any path options will be normalized relative to depth.
+
+ The format flag is not included, as it is assumed the calling generator will
+ set that as appropriate.
+ """
+ def FixPath(path):
+ path = gyp.common.FixIfRelativePath(path, options.depth)
+ if not path:
+ return os.path.curdir
+ return path
+
+ def Noop(value):
+ return value
+
+ # We always want to ignore the environment when regenerating, to avoid
+ # duplicate or changed flags in the environment at the time of regeneration.
+ flags = ['--ignore-environment']
+ for name, metadata in options._regeneration_metadata.iteritems():
+ opt = metadata['opt']
+ value = getattr(options, name)
+ value_predicate = metadata['type'] == 'path' and FixPath or Noop
+ action = metadata['action']
+ env_name = metadata['env_name']
+ if action == 'append':
+ flags.extend(RegenerateAppendFlag(opt, value, value_predicate,
+ env_name, options))
+ elif action in ('store', None): # None is a synonym for 'store'.
+ if value:
+ flags.append(FormatOpt(opt, value_predicate(value)))
+ elif options.use_environment and env_name and os.environ.get(env_name):
+ flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name))))
+ elif action in ('store_true', 'store_false'):
+ if ((action == 'store_true' and value) or
+ (action == 'store_false' and not value)):
+ flags.append(opt)
+ elif options.use_environment and env_name:
+ print >>sys.stderr, ('Warning: environment regeneration unimplemented '
+ 'for %s flag %r env_name %r' % (action, opt,
+ env_name))
+ else:
+ print >>sys.stderr, ('Warning: regeneration unimplemented for action %r '
+ 'flag %r' % (action, opt))
+
+ return flags
+
+class RegeneratableOptionParser(optparse.OptionParser):
+ def __init__(self):
+ self.__regeneratable_options = {}
+ optparse.OptionParser.__init__(self)
+
+ def add_option(self, *args, **kw):
+ """Add an option to the parser.
+
+ This accepts the same arguments as OptionParser.add_option, plus the
+ following:
+ regenerate: can be set to False to prevent this option from being included
+ in regeneration.
+ env_name: name of environment variable that additional values for this
+ option come from.
+ type: adds type='path', to tell the regenerator that the values of
+ this option need to be made relative to options.depth
+ """
+ env_name = kw.pop('env_name', None)
+ if 'dest' in kw and kw.pop('regenerate', True):
+ dest = kw['dest']
+
+ # The path type is needed for regenerating, for optparse we can just treat
+ # it as a string.
+ type = kw.get('type')
+ if type == 'path':
+ kw['type'] = 'string'
+
+ self.__regeneratable_options[dest] = {
+ 'action': kw.get('action'),
+ 'type': type,
+ 'env_name': env_name,
+ 'opt': args[0],
+ }
+
+ optparse.OptionParser.add_option(self, *args, **kw)
+
+ def parse_args(self, *args):
+ values, args = optparse.OptionParser.parse_args(self, *args)
+ values._regeneration_metadata = self.__regeneratable_options
+ return values, args
+
+def gyp_main(args):
+ my_name = os.path.basename(sys.argv[0])
+
+ parser = RegeneratableOptionParser()
+ usage = 'usage: %s [options ...] [build_file ...]'
+ parser.set_usage(usage.replace('%s', '%prog'))
+ parser.add_option('--build', dest='configs', action='append',
+ help='configuration for build after project generation')
+ parser.add_option('--check', dest='check', action='store_true',
+ help='check format of gyp files')
+ parser.add_option('--config-dir', dest='config_dir', action='store',
+ env_name='GYP_CONFIG_DIR', default=None,
+ help='The location for configuration files like '
+ 'include.gypi.')
+ parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE',
+ action='append', default=[], help='turn on a debugging '
+ 'mode for debugging GYP. Supported modes are "variables", '
+ '"includes" and "general" or "all" for all of them.')
+ parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL',
+ env_name='GYP_DEFINES',
+ help='sets variable VAR to value VAL')
+ parser.add_option('--depth', dest='depth', metavar='PATH', type='path',
+ help='set DEPTH gyp variable to a relative path to PATH')
+ parser.add_option('-f', '--format', dest='formats', action='append',
+ env_name='GYP_GENERATORS', regenerate=False,
+ help='output formats to generate')
+ parser.add_option('-G', dest='generator_flags', action='append', default=[],
+ metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS',
+ help='sets generator flag FLAG to VAL')
+ parser.add_option('--generator-output', dest='generator_output',
+ action='store', default=None, metavar='DIR', type='path',
+ env_name='GYP_GENERATOR_OUTPUT',
+ help='puts generated build files under DIR')
+ parser.add_option('--ignore-environment', dest='use_environment',
+ action='store_false', default=True, regenerate=False,
+ help='do not read options from environment variables')
+ parser.add_option('-I', '--include', dest='includes', action='append',
+ metavar='INCLUDE', type='path',
+ help='files to include in all loaded .gyp files')
+ parser.add_option('--msvs-version', dest='msvs_version',
+ regenerate=False,
+ help='Deprecated; use -G msvs_version=MSVS_VERSION instead')
+ # --no-circular-check disables the check for circular relationships between
+ # .gyp files. These relationships should not exist, but they've only been
+ # observed to be harmful with the Xcode generator. Chromium's .gyp files
+ # currently have some circular relationships on non-Mac platforms, so this
+ # option allows the strict behavior to be used on Macs and the lenient
+ # behavior to be used elsewhere.
+ # TODO(mark): Remove this option when http://crbug.com/35878 is fixed.
+ parser.add_option('--no-circular-check', dest='circular_check',
+ action='store_false', default=True, regenerate=False,
+ help="don't check for circular relationships between files")
+ parser.add_option('--parallel', action='store_true',
+ env_name='GYP_PARALLEL',
+ help='Use multiprocessing for speed (experimental)')
+ parser.add_option('-S', '--suffix', dest='suffix', default='',
+ help='suffix to add to generated files')
+ parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store',
+ default=None, metavar='DIR', type='path',
+ help='directory to use as the root of the source tree')
+
+ options, build_files_arg = parser.parse_args(args)
+ build_files = build_files_arg
+
+ # Set up the configuration directory (defaults to ~/.gyp)
+ if not options.config_dir:
+ home = None
+ home_dot_gyp = None
+ if options.use_environment:
+ home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
+ if home_dot_gyp:
+ home_dot_gyp = os.path.expanduser(home_dot_gyp)
+
+ if not home_dot_gyp:
+ home_vars = ['HOME']
+ if sys.platform in ('cygwin', 'win32'):
+ home_vars.append('USERPROFILE')
+ for home_var in home_vars:
+ home = os.getenv(home_var)
+ if home != None:
+ home_dot_gyp = os.path.join(home, '.gyp')
+ if not os.path.exists(home_dot_gyp):
+ home_dot_gyp = None
+ else:
+ break
+ else:
+ home_dot_gyp = os.path.expanduser(options.config_dir)
+
+ if home_dot_gyp and not os.path.exists(home_dot_gyp):
+ home_dot_gyp = None
+
+ if not options.formats:
+ # If no format was given on the command line, then check the env variable.
+ generate_formats = []
+ if options.use_environment:
+ generate_formats = os.environ.get('GYP_GENERATORS', [])
+ if generate_formats:
+ generate_formats = re.split('[\s,]', generate_formats)
+ if generate_formats:
+ options.formats = generate_formats
+ else:
+ # Nothing in the variable, default based on platform.
+ if sys.platform == 'darwin':
+ options.formats = ['xcode']
+ elif sys.platform in ('win32', 'cygwin'):
+ options.formats = ['msvs']
+ else:
+ options.formats = ['make']
+
+ if not options.generator_output and options.use_environment:
+ g_o = os.environ.get('GYP_GENERATOR_OUTPUT')
+ if g_o:
+ options.generator_output = g_o
+
+ if not options.parallel and options.use_environment:
+ p = os.environ.get('GYP_PARALLEL')
+ options.parallel = bool(p and p != '0')
+
+ for mode in options.debug:
+ gyp.debug[mode] = 1
+
+ # Do an extra check to avoid work when we're not debugging.
+ if DEBUG_GENERAL in gyp.debug:
+ DebugOutput(DEBUG_GENERAL, 'running with these options:')
+ for option, value in sorted(options.__dict__.items()):
+ if option[0] == '_':
+ continue
+ if isinstance(value, basestring):
+ DebugOutput(DEBUG_GENERAL, " %s: '%s'", option, value)
+ else:
+ DebugOutput(DEBUG_GENERAL, " %s: %s", option, value)
+
+ if not build_files:
+ build_files = FindBuildFiles()
+ if not build_files:
+ raise GypError((usage + '\n\n%s: error: no build_file') %
+ (my_name, my_name))
+
+ # TODO(mark): Chromium-specific hack!
+ # For Chromium, the gyp "depth" variable should always be a relative path
+ # to Chromium's top-level "src" directory. If no depth variable was set
+ # on the command line, try to find a "src" directory by looking at the
+ # absolute path to each build file's directory. The first "src" component
+ # found will be treated as though it were the path used for --depth.
+ if not options.depth:
+ for build_file in build_files:
+ build_file_dir = os.path.abspath(os.path.dirname(build_file))
+ build_file_dir_components = build_file_dir.split(os.path.sep)
+ components_len = len(build_file_dir_components)
+ for index in xrange(components_len - 1, -1, -1):
+ if build_file_dir_components[index] == 'src':
+ options.depth = os.path.sep.join(build_file_dir_components)
+ break
+ del build_file_dir_components[index]
+
+ # If the inner loop found something, break without advancing to another
+ # build file.
+ if options.depth:
+ break
+
+ if not options.depth:
+ raise GypError('Could not automatically locate src directory. This is'
+ 'a temporary Chromium feature that will be removed. Use'
+ '--depth as a workaround.')
+
+ # If toplevel-dir is not set, we assume that depth is the root of our source
+ # tree.
+ if not options.toplevel_dir:
+ options.toplevel_dir = options.depth
+
+ # -D on the command line sets variable defaults - D isn't just for define,
+ # it's for default. Perhaps there should be a way to force (-F?) a
+ # variable's value so that it can't be overridden by anything else.
+ cmdline_default_variables = {}
+ defines = []
+ if options.use_environment:
+ defines += ShlexEnv('GYP_DEFINES')
+ if options.defines:
+ defines += options.defines
+ cmdline_default_variables = NameValueListToDict(defines)
+ if DEBUG_GENERAL in gyp.debug:
+ DebugOutput(DEBUG_GENERAL,
+ "cmdline_default_variables: %s", cmdline_default_variables)
+
+ # Set up includes.
+ includes = []
+
+ # If ~/.gyp/include.gypi exists, it'll be forcibly included into every
+ # .gyp file that's loaded, before anything else is included.
+ if home_dot_gyp != None:
+ default_include = os.path.join(home_dot_gyp, 'include.gypi')
+ if os.path.exists(default_include):
+ print 'Using overrides found in ' + default_include
+ includes.append(default_include)
+
+ # Command-line --include files come after the default include.
+ if options.includes:
+ includes.extend(options.includes)
+
+ # Generator flags should be prefixed with the target generator since they
+ # are global across all generator runs.
+ gen_flags = []
+ if options.use_environment:
+ gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS')
+ if options.generator_flags:
+ gen_flags += options.generator_flags
+ generator_flags = NameValueListToDict(gen_flags)
+ if DEBUG_GENERAL in gyp.debug.keys():
+ DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags)
+
+ # TODO: Remove this and the option after we've gotten folks to move to the
+ # generator flag.
+ if options.msvs_version:
+ print >>sys.stderr, \
+ 'DEPRECATED: Use generator flag (-G msvs_version=' + \
+ options.msvs_version + ') instead of --msvs-version=' + \
+ options.msvs_version
+ generator_flags['msvs_version'] = options.msvs_version
+
+ # Generate all requested formats (use a set in case we got one format request
+ # twice)
+ for format in set(options.formats):
+ params = {'options': options,
+ 'build_files': build_files,
+ 'generator_flags': generator_flags,
+ 'cwd': os.getcwd(),
+ 'build_files_arg': build_files_arg,
+ 'gyp_binary': sys.argv[0],
+ 'home_dot_gyp': home_dot_gyp,
+ 'parallel': options.parallel}
+
+ # Start with the default variables from the command line.
+ [generator, flat_list, targets, data] = Load(build_files, format,
+ cmdline_default_variables,
+ includes, options.depth,
+ params, options.check,
+ options.circular_check)
+
+ # TODO(mark): Pass |data| for now because the generator needs a list of
+ # build files that came in. In the future, maybe it should just accept
+ # a list, and not the whole data dict.
+ # NOTE: flat_list is the flattened dependency graph specifying the order
+ # that targets may be built. Build systems that operate serially or that
+ # need to have dependencies defined before dependents reference them should
+ # generate targets in the order specified in flat_list.
+ generator.GenerateOutput(flat_list, targets, data, params)
+
+ if options.configs:
+ valid_configs = targets[flat_list[0]]['configurations'].keys()
+ for conf in options.configs:
+ if conf not in valid_configs:
+ raise GypError('Invalid config specified via --build: %s' % conf)
+ generator.PerformBuild(data, options.configs, params)
+
+ # Done
+ return 0
+
+
+def main(args):
+ try:
+ return gyp_main(args)
+ except GypError, e:
+ sys.stderr.write("gyp: %s\n" % e)
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/gyp/pylib/gyp/common.py b/chromium/tools/gyp/pylib/gyp/common.py
new file mode 100644
index 00000000000..19f1cf4a53a
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/common.py
@@ -0,0 +1,498 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import with_statement
+
+import errno
+import filecmp
+import os.path
+import re
+import tempfile
+import sys
+
+
+# A minimal memoizing decorator. It'll blow up if the args aren't immutable,
+# among other "problems".
+class memoize(object):
+ def __init__(self, func):
+ self.func = func
+ self.cache = {}
+ def __call__(self, *args):
+ try:
+ return self.cache[args]
+ except KeyError:
+ result = self.func(*args)
+ self.cache[args] = result
+ return result
+
+
+class GypError(Exception):
+ """Error class representing an error, which is to be presented
+ to the user. The main entry point will catch and display this.
+ """
+ pass
+
+
+def ExceptionAppend(e, msg):
+ """Append a message to the given exception's message."""
+ if not e.args:
+ e.args = (msg,)
+ elif len(e.args) == 1:
+ e.args = (str(e.args[0]) + ' ' + msg,)
+ else:
+ e.args = (str(e.args[0]) + ' ' + msg,) + e.args[1:]
+
+
+def ParseQualifiedTarget(target):
+ # Splits a qualified target into a build file, target name and toolset.
+
+ # NOTE: rsplit is used to disambiguate the Windows drive letter separator.
+ target_split = target.rsplit(':', 1)
+ if len(target_split) == 2:
+ [build_file, target] = target_split
+ else:
+ build_file = None
+
+ target_split = target.rsplit('#', 1)
+ if len(target_split) == 2:
+ [target, toolset] = target_split
+ else:
+ toolset = None
+
+ return [build_file, target, toolset]
+
+
+def ResolveTarget(build_file, target, toolset):
+ # This function resolves a target into a canonical form:
+ # - a fully defined build file, either absolute or relative to the current
+ # directory
+ # - a target name
+ # - a toolset
+ #
+ # build_file is the file relative to which 'target' is defined.
+ # target is the qualified target.
+ # toolset is the default toolset for that target.
+ [parsed_build_file, target, parsed_toolset] = ParseQualifiedTarget(target)
+
+ if parsed_build_file:
+ if build_file:
+ # If a relative path, parsed_build_file is relative to the directory
+ # containing build_file. If build_file is not in the current directory,
+ # parsed_build_file is not a usable path as-is. Resolve it by
+ # interpreting it as relative to build_file. If parsed_build_file is
+ # absolute, it is usable as a path regardless of the current directory,
+ # and os.path.join will return it as-is.
+ build_file = os.path.normpath(os.path.join(os.path.dirname(build_file),
+ parsed_build_file))
+ # Further (to handle cases like ../cwd), make it relative to cwd)
+ if not os.path.isabs(build_file):
+ build_file = RelativePath(build_file, '.')
+ else:
+ build_file = parsed_build_file
+
+ if parsed_toolset:
+ toolset = parsed_toolset
+
+ return [build_file, target, toolset]
+
+
+def BuildFile(fully_qualified_target):
+ # Extracts the build file from the fully qualified target.
+ return ParseQualifiedTarget(fully_qualified_target)[0]
+
+
+def GetEnvironFallback(var_list, default):
+ """Look up a key in the environment, with fallback to secondary keys
+ and finally falling back to a default value."""
+ for var in var_list:
+ if var in os.environ:
+ return os.environ[var]
+ return default
+
+
+def QualifiedTarget(build_file, target, toolset):
+ # "Qualified" means the file that a target was defined in and the target
+ # name, separated by a colon, suffixed by a # and the toolset name:
+ # /path/to/file.gyp:target_name#toolset
+ fully_qualified = build_file + ':' + target
+ if toolset:
+ fully_qualified = fully_qualified + '#' + toolset
+ return fully_qualified
+
+
+@memoize
+def RelativePath(path, relative_to):
+ # Assuming both |path| and |relative_to| are relative to the current
+ # directory, returns a relative path that identifies path relative to
+ # relative_to.
+
+ # Convert to normalized (and therefore absolute paths).
+ path = os.path.realpath(path)
+ relative_to = os.path.realpath(relative_to)
+
+ # On Windows, we can't create a relative path to a different drive, so just
+ # use the absolute path.
+ if sys.platform == 'win32':
+ if (os.path.splitdrive(path)[0].lower() !=
+ os.path.splitdrive(relative_to)[0].lower()):
+ return path
+
+ # Split the paths into components.
+ path_split = path.split(os.path.sep)
+ relative_to_split = relative_to.split(os.path.sep)
+
+ # Determine how much of the prefix the two paths share.
+ prefix_len = len(os.path.commonprefix([path_split, relative_to_split]))
+
+ # Put enough ".." components to back up out of relative_to to the common
+ # prefix, and then append the part of path_split after the common prefix.
+ relative_split = [os.path.pardir] * (len(relative_to_split) - prefix_len) + \
+ path_split[prefix_len:]
+
+ if len(relative_split) == 0:
+ # The paths were the same.
+ return ''
+
+ # Turn it back into a string and we're done.
+ return os.path.join(*relative_split)
+
+
+@memoize
+def InvertRelativePath(path, toplevel_dir=None):
+ """Given a path like foo/bar that is relative to toplevel_dir, return
+ the inverse relative path back to the toplevel_dir.
+
+ E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path)))
+ should always produce the empty string, unless the path contains symlinks.
+ """
+ if not path:
+ return path
+ toplevel_dir = '.' if toplevel_dir is None else toplevel_dir
+ return RelativePath(toplevel_dir, os.path.join(toplevel_dir, path))
+
+
+def FixIfRelativePath(path, relative_to):
+ # Like RelativePath but returns |path| unchanged if it is absolute.
+ if os.path.isabs(path):
+ return path
+ return RelativePath(path, relative_to)
+
+
+def UnrelativePath(path, relative_to):
+ # Assuming that |relative_to| is relative to the current directory, and |path|
+ # is a path relative to the dirname of |relative_to|, returns a path that
+ # identifies |path| relative to the current directory.
+ rel_dir = os.path.dirname(relative_to)
+ return os.path.normpath(os.path.join(rel_dir, path))
+
+
+# re objects used by EncodePOSIXShellArgument. See IEEE 1003.1 XCU.2.2 at
+# http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_02
+# and the documentation for various shells.
+
+# _quote is a pattern that should match any argument that needs to be quoted
+# with double-quotes by EncodePOSIXShellArgument. It matches the following
+# characters appearing anywhere in an argument:
+# \t, \n, space parameter separators
+# # comments
+# $ expansions (quoted to always expand within one argument)
+# % called out by IEEE 1003.1 XCU.2.2
+# & job control
+# ' quoting
+# (, ) subshell execution
+# *, ?, [ pathname expansion
+# ; command delimiter
+# <, >, | redirection
+# = assignment
+# {, } brace expansion (bash)
+# ~ tilde expansion
+# It also matches the empty string, because "" (or '') is the only way to
+# represent an empty string literal argument to a POSIX shell.
+#
+# This does not match the characters in _escape, because those need to be
+# backslash-escaped regardless of whether they appear in a double-quoted
+# string.
+_quote = re.compile('[\t\n #$%&\'()*;<=>?[{|}~]|^$')
+
+# _escape is a pattern that should match any character that needs to be
+# escaped with a backslash, whether or not the argument matched the _quote
+# pattern. _escape is used with re.sub to backslash anything in _escape's
+# first match group, hence the (parentheses) in the regular expression.
+#
+# _escape matches the following characters appearing anywhere in an argument:
+# " to prevent POSIX shells from interpreting this character for quoting
+# \ to prevent POSIX shells from interpreting this character for escaping
+# ` to prevent POSIX shells from interpreting this character for command
+# substitution
+# Missing from this list is $, because the desired behavior of
+# EncodePOSIXShellArgument is to permit parameter (variable) expansion.
+#
+# Also missing from this list is !, which bash will interpret as the history
+# expansion character when history is enabled. bash does not enable history
+# by default in non-interactive shells, so this is not thought to be a problem.
+# ! was omitted from this list because bash interprets "\!" as a literal string
+# including the backslash character (avoiding history expansion but retaining
+# the backslash), which would not be correct for argument encoding. Handling
+# this case properly would also be problematic because bash allows the history
+# character to be changed with the histchars shell variable. Fortunately,
+# as history is not enabled in non-interactive shells and
+# EncodePOSIXShellArgument is only expected to encode for non-interactive
+# shells, there is no room for error here by ignoring !.
+_escape = re.compile(r'(["\\`])')
+
+def EncodePOSIXShellArgument(argument):
+ """Encodes |argument| suitably for consumption by POSIX shells.
+
+ argument may be quoted and escaped as necessary to ensure that POSIX shells
+ treat the returned value as a literal representing the argument passed to
+ this function. Parameter (variable) expansions beginning with $ are allowed
+ to remain intact without escaping the $, to allow the argument to contain
+ references to variables to be expanded by the shell.
+ """
+
+ if not isinstance(argument, str):
+ argument = str(argument)
+
+ if _quote.search(argument):
+ quote = '"'
+ else:
+ quote = ''
+
+ encoded = quote + re.sub(_escape, r'\\\1', argument) + quote
+
+ return encoded
+
+
+def EncodePOSIXShellList(list):
+ """Encodes |list| suitably for consumption by POSIX shells.
+
+ Returns EncodePOSIXShellArgument for each item in list, and joins them
+ together using the space character as an argument separator.
+ """
+
+ encoded_arguments = []
+ for argument in list:
+ encoded_arguments.append(EncodePOSIXShellArgument(argument))
+ return ' '.join(encoded_arguments)
+
+
+def DeepDependencyTargets(target_dicts, roots):
+ """Returns the recursive list of target dependencies."""
+ dependencies = set()
+ pending = set(roots)
+ while pending:
+ # Pluck out one.
+ r = pending.pop()
+ # Skip if visited already.
+ if r in dependencies:
+ continue
+ # Add it.
+ dependencies.add(r)
+ # Add its children.
+ spec = target_dicts[r]
+ pending.update(set(spec.get('dependencies', [])))
+ pending.update(set(spec.get('dependencies_original', [])))
+ return list(dependencies - set(roots))
+
+
+def BuildFileTargets(target_list, build_file):
+ """From a target_list, returns the subset from the specified build_file.
+ """
+ return [p for p in target_list if BuildFile(p) == build_file]
+
+
+def AllTargets(target_list, target_dicts, build_file):
+ """Returns all targets (direct and dependencies) for the specified build_file.
+ """
+ bftargets = BuildFileTargets(target_list, build_file)
+ deptargets = DeepDependencyTargets(target_dicts, bftargets)
+ return bftargets + deptargets
+
+
+def WriteOnDiff(filename):
+ """Write to a file only if the new contents differ.
+
+ Arguments:
+ filename: name of the file to potentially write to.
+ Returns:
+ A file like object which will write to temporary file and only overwrite
+ the target if it differs (on close).
+ """
+
+ class Writer:
+ """Wrapper around file which only covers the target if it differs."""
+ def __init__(self):
+ # Pick temporary file.
+ tmp_fd, self.tmp_path = tempfile.mkstemp(
+ suffix='.tmp',
+ prefix=os.path.split(filename)[1] + '.gyp.',
+ dir=os.path.split(filename)[0])
+ try:
+ self.tmp_file = os.fdopen(tmp_fd, 'wb')
+ except Exception:
+ # Don't leave turds behind.
+ os.unlink(self.tmp_path)
+ raise
+
+ def __getattr__(self, attrname):
+ # Delegate everything else to self.tmp_file
+ return getattr(self.tmp_file, attrname)
+
+ def close(self):
+ try:
+ # Close tmp file.
+ self.tmp_file.close()
+ # Determine if different.
+ same = False
+ try:
+ same = filecmp.cmp(self.tmp_path, filename, False)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+
+ if same:
+ # The new file is identical to the old one, just get rid of the new
+ # one.
+ os.unlink(self.tmp_path)
+ else:
+ # The new file is different from the old one, or there is no old one.
+ # Rename the new file to the permanent name.
+ #
+ # tempfile.mkstemp uses an overly restrictive mode, resulting in a
+ # file that can only be read by the owner, regardless of the umask.
+ # There's no reason to not respect the umask here, which means that
+ # an extra hoop is required to fetch it and reset the new file's mode.
+ #
+ # No way to get the umask without setting a new one? Set a safe one
+ # and then set it back to the old value.
+ umask = os.umask(077)
+ os.umask(umask)
+ os.chmod(self.tmp_path, 0666 & ~umask)
+ if sys.platform == 'win32' and os.path.exists(filename):
+ # NOTE: on windows (but not cygwin) rename will not replace an
+ # existing file, so it must be preceded with a remove. Sadly there
+ # is no way to make the switch atomic.
+ os.remove(filename)
+ os.rename(self.tmp_path, filename)
+ except Exception:
+ # Don't leave turds behind.
+ os.unlink(self.tmp_path)
+ raise
+
+ return Writer()
+
+
+def GetFlavor(params):
+ """Returns |params.flavor| if it's set, the system's default flavor else."""
+ flavors = {
+ 'cygwin': 'win',
+ 'win32': 'win',
+ 'darwin': 'mac',
+ }
+
+ if 'flavor' in params:
+ return params['flavor']
+ if sys.platform in flavors:
+ return flavors[sys.platform]
+ if sys.platform.startswith('sunos'):
+ return 'solaris'
+ if sys.platform.startswith('freebsd'):
+ return 'freebsd'
+ if sys.platform.startswith('openbsd'):
+ return 'openbsd'
+ if sys.platform.startswith('aix'):
+ return 'aix'
+
+ return 'linux'
+
+
+def CopyTool(flavor, out_path):
+ """Finds (mac|sun|win)_tool.gyp in the gyp directory and copies it
+ to |out_path|."""
+ prefix = { 'solaris': 'sun', 'mac': 'mac', 'win': 'win' }.get(flavor, None)
+ if not prefix:
+ return
+
+ # Slurp input file.
+ source_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), '%s_tool.py' % prefix)
+ with open(source_path) as source_file:
+ source = source_file.readlines()
+
+ # Add header and write it out.
+ tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix)
+ with open(tool_path, 'w') as tool_file:
+ tool_file.write(
+ ''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:]))
+
+ # Make file executable.
+ os.chmod(tool_path, 0755)
+
+
+# From Alex Martelli,
+# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
+# ASPN: Python Cookbook: Remove duplicates from a sequence
+# First comment, dated 2001/10/13.
+# (Also in the printed Python Cookbook.)
+
+def uniquer(seq, idfun=None):
+ if idfun is None:
+ idfun = lambda x: x
+ seen = {}
+ result = []
+ for item in seq:
+ marker = idfun(item)
+ if marker in seen: continue
+ seen[marker] = 1
+ result.append(item)
+ return result
+
+
+class CycleError(Exception):
+ """An exception raised when an unexpected cycle is detected."""
+ def __init__(self, nodes):
+ self.nodes = nodes
+ def __str__(self):
+ return 'CycleError: cycle involving: ' + str(self.nodes)
+
+
+def TopologicallySorted(graph, get_edges):
+ """Topologically sort based on a user provided edge definition.
+
+ Args:
+ graph: A list of node names.
+ get_edges: A function mapping from node name to a hashable collection
+ of node names which this node has outgoing edges to.
+ Returns:
+ A list containing all of the node in graph in topological order.
+ It is assumed that calling get_edges once for each node and caching is
+ cheaper than repeatedly calling get_edges.
+ Raises:
+ CycleError in the event of a cycle.
+ Example:
+ graph = {'a': '$(b) $(c)', 'b': 'hi', 'c': '$(b)'}
+ def GetEdges(node):
+ return re.findall(r'\$\(([^))]\)', graph[node])
+ print TopologicallySorted(graph.keys(), GetEdges)
+ ==>
+ ['a', 'c', b']
+ """
+ get_edges = memoize(get_edges)
+ visited = set()
+ visiting = set()
+ ordered_nodes = []
+ def Visit(node):
+ if node in visiting:
+ raise CycleError(visiting)
+ if node in visited:
+ return
+ visited.add(node)
+ visiting.add(node)
+ for neighbor in get_edges(node):
+ Visit(neighbor)
+ visiting.remove(node)
+ ordered_nodes.insert(0, node)
+ for node in sorted(graph):
+ Visit(node)
+ return ordered_nodes
diff --git a/chromium/tools/gyp/pylib/gyp/common_test.py b/chromium/tools/gyp/pylib/gyp/common_test.py
new file mode 100755
index 00000000000..ad6f9a1438f
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/common_test.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for the common.py file."""
+
+import gyp.common
+import unittest
+import sys
+
+
+class TestTopologicallySorted(unittest.TestCase):
+ def test_Valid(self):
+ """Test that sorting works on a valid graph with one possible order."""
+ graph = {
+ 'a': ['b', 'c'],
+ 'b': [],
+ 'c': ['d'],
+ 'd': ['b'],
+ }
+ def GetEdge(node):
+ return tuple(graph[node])
+ self.assertEqual(
+ gyp.common.TopologicallySorted(graph.keys(), GetEdge),
+ ['a', 'c', 'd', 'b'])
+
+ def test_Cycle(self):
+ """Test that an exception is thrown on a cyclic graph."""
+ graph = {
+ 'a': ['b'],
+ 'b': ['c'],
+ 'c': ['d'],
+ 'd': ['a'],
+ }
+ def GetEdge(node):
+ return tuple(graph[node])
+ self.assertRaises(
+ gyp.common.CycleError, gyp.common.TopologicallySorted,
+ graph.keys(), GetEdge)
+
+
+class TestGetFlavor(unittest.TestCase):
+ """Test that gyp.common.GetFlavor works as intended"""
+ original_platform = ''
+
+ def setUp(self):
+ self.original_platform = sys.platform
+
+ def tearDown(self):
+ sys.platform = self.original_platform
+
+ def assertFlavor(self, expected, argument, param):
+ sys.platform = argument
+ self.assertEqual(expected, gyp.common.GetFlavor(param))
+
+ def test_platform_default(self):
+ self.assertFlavor('freebsd', 'freebsd9' , {})
+ self.assertFlavor('freebsd', 'freebsd10', {})
+ self.assertFlavor('openbsd', 'openbsd5' , {})
+ self.assertFlavor('solaris', 'sunos5' , {});
+ self.assertFlavor('solaris', 'sunos' , {});
+ self.assertFlavor('linux' , 'linux2' , {});
+ self.assertFlavor('linux' , 'linux3' , {});
+
+ def test_param(self):
+ self.assertFlavor('foobar', 'linux2' , {'flavor': 'foobar'})
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/gyp/pylib/gyp/easy_xml.py b/chromium/tools/gyp/pylib/gyp/easy_xml.py
new file mode 100644
index 00000000000..bf949b6ac9b
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/easy_xml.py
@@ -0,0 +1,157 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import os
+
+
+def XmlToString(content, encoding='utf-8', pretty=False):
+ """ Writes the XML content to disk, touching the file only if it has changed.
+
+ Visual Studio files have a lot of pre-defined structures. This function makes
+ it easy to represent these structures as Python data structures, instead of
+ having to create a lot of function calls.
+
+ Each XML element of the content is represented as a list composed of:
+ 1. The name of the element, a string,
+ 2. The attributes of the element, a dictionary (optional), and
+ 3+. The content of the element, if any. Strings are simple text nodes and
+ lists are child elements.
+
+ Example 1:
+ <test/>
+ becomes
+ ['test']
+
+ Example 2:
+ <myelement a='value1' b='value2'>
+ <childtype>This is</childtype>
+ <childtype>it!</childtype>
+ </myelement>
+
+ becomes
+ ['myelement', {'a':'value1', 'b':'value2'},
+ ['childtype', 'This is'],
+ ['childtype', 'it!'],
+ ]
+
+ Args:
+ content: The structured content to be converted.
+ encoding: The encoding to report on the first XML line.
+ pretty: True if we want pretty printing with indents and new lines.
+
+ Returns:
+ The XML content as a string.
+ """
+ # We create a huge list of all the elements of the file.
+ xml_parts = ['<?xml version="1.0" encoding="%s"?>' % encoding]
+ if pretty:
+ xml_parts.append('\n')
+ _ConstructContentList(xml_parts, content, pretty)
+
+ # Convert it to a string
+ return ''.join(xml_parts)
+
+
+def _ConstructContentList(xml_parts, specification, pretty, level=0):
+ """ Appends the XML parts corresponding to the specification.
+
+ Args:
+ xml_parts: A list of XML parts to be appended to.
+ specification: The specification of the element. See EasyXml docs.
+ pretty: True if we want pretty printing with indents and new lines.
+ level: Indentation level.
+ """
+ # The first item in a specification is the name of the element.
+ if pretty:
+ indentation = ' ' * level
+ new_line = '\n'
+ else:
+ indentation = ''
+ new_line = ''
+ name = specification[0]
+ if not isinstance(name, str):
+ raise Exception('The first item of an EasyXml specification should be '
+ 'a string. Specification was ' + str(specification))
+ xml_parts.append(indentation + '<' + name)
+
+ # Optionally in second position is a dictionary of the attributes.
+ rest = specification[1:]
+ if rest and isinstance(rest[0], dict):
+ for at, val in sorted(rest[0].iteritems()):
+ xml_parts.append(' %s="%s"' % (at, _XmlEscape(val, attr=True)))
+ rest = rest[1:]
+ if rest:
+ xml_parts.append('>')
+ all_strings = reduce(lambda x, y: x and isinstance(y, str), rest, True)
+ multi_line = not all_strings
+ if multi_line and new_line:
+ xml_parts.append(new_line)
+ for child_spec in rest:
+ # If it's a string, append a text node.
+ # Otherwise recurse over that child definition
+ if isinstance(child_spec, str):
+ xml_parts.append(_XmlEscape(child_spec))
+ else:
+ _ConstructContentList(xml_parts, child_spec, pretty, level + 1)
+ if multi_line and indentation:
+ xml_parts.append(indentation)
+ xml_parts.append('</%s>%s' % (name, new_line))
+ else:
+ xml_parts.append('/>%s' % new_line)
+
+
+def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False,
+ win32=False):
+ """ Writes the XML content to disk, touching the file only if it has changed.
+
+ Args:
+ content: The structured content to be written.
+ path: Location of the file.
+ encoding: The encoding to report on the first line of the XML file.
+ pretty: True if we want pretty printing with indents and new lines.
+ """
+ xml_string = XmlToString(content, encoding, pretty)
+ if win32 and os.linesep != '\r\n':
+ xml_string = xml_string.replace('\n', '\r\n')
+
+ # Get the old content
+ try:
+ f = open(path, 'r')
+ existing = f.read()
+ f.close()
+ except:
+ existing = None
+
+ # It has changed, write it
+ if existing != xml_string:
+ f = open(path, 'w')
+ f.write(xml_string)
+ f.close()
+
+
+_xml_escape_map = {
+ '"': '&quot;',
+ "'": '&apos;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '&': '&amp;',
+ '\n': '&#xA;',
+ '\r': '&#xD;',
+}
+
+
+_xml_escape_re = re.compile(
+ "(%s)" % "|".join(map(re.escape, _xml_escape_map.keys())))
+
+
+def _XmlEscape(value, attr=False):
+ """ Escape a string for inclusion in XML."""
+ def replace(match):
+ m = match.string[match.start() : match.end()]
+ # don't replace single quotes in attrs
+ if attr and m == "'":
+ return m
+ return _xml_escape_map[m]
+ return _xml_escape_re.sub(replace, value)
diff --git a/chromium/tools/gyp/pylib/gyp/easy_xml_test.py b/chromium/tools/gyp/pylib/gyp/easy_xml_test.py
new file mode 100755
index 00000000000..df64354982c
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/easy_xml_test.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Unit tests for the easy_xml.py file. """
+
+import gyp.easy_xml as easy_xml
+import unittest
+import StringIO
+
+
+class TestSequenceFunctions(unittest.TestCase):
+
+ def setUp(self):
+ self.stderr = StringIO.StringIO()
+
+ def test_EasyXml_simple(self):
+ self.assertEqual(
+ easy_xml.XmlToString(['test']),
+ '<?xml version="1.0" encoding="utf-8"?><test/>')
+
+ self.assertEqual(
+ easy_xml.XmlToString(['test'], encoding='Windows-1252'),
+ '<?xml version="1.0" encoding="Windows-1252"?><test/>')
+
+ def test_EasyXml_simple_with_attributes(self):
+ self.assertEqual(
+ easy_xml.XmlToString(['test2', {'a': 'value1', 'b': 'value2'}]),
+ '<?xml version="1.0" encoding="utf-8"?><test2 a="value1" b="value2"/>')
+
+ def test_EasyXml_escaping(self):
+ original = '<test>\'"\r&\nfoo'
+ converted = '&lt;test&gt;\'&quot;&#xD;&amp;&#xA;foo'
+ converted_apos = converted.replace("'", '&apos;')
+ self.assertEqual(
+ easy_xml.XmlToString(['test3', {'a': original}, original]),
+ '<?xml version="1.0" encoding="utf-8"?><test3 a="%s">%s</test3>' %
+ (converted, converted_apos))
+
+ def test_EasyXml_pretty(self):
+ self.assertEqual(
+ easy_xml.XmlToString(
+ ['test3',
+ ['GrandParent',
+ ['Parent1',
+ ['Child']
+ ],
+ ['Parent2']
+ ]
+ ],
+ pretty=True),
+ '<?xml version="1.0" encoding="utf-8"?>\n'
+ '<test3>\n'
+ ' <GrandParent>\n'
+ ' <Parent1>\n'
+ ' <Child/>\n'
+ ' </Parent1>\n'
+ ' <Parent2/>\n'
+ ' </GrandParent>\n'
+ '</test3>\n')
+
+
+ def test_EasyXml_complex(self):
+ # We want to create:
+ target = (
+ '<?xml version="1.0" encoding="utf-8"?>'
+ '<Project>'
+ '<PropertyGroup Label="Globals">'
+ '<ProjectGuid>{D2250C20-3A94-4FB9-AF73-11BC5B73884B}</ProjectGuid>'
+ '<Keyword>Win32Proj</Keyword>'
+ '<RootNamespace>automated_ui_tests</RootNamespace>'
+ '</PropertyGroup>'
+ '<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props"/>'
+ '<PropertyGroup '
+ 'Condition="\'$(Configuration)|$(Platform)\'=='
+ '\'Debug|Win32\'" Label="Configuration">'
+ '<ConfigurationType>Application</ConfigurationType>'
+ '<CharacterSet>Unicode</CharacterSet>'
+ '</PropertyGroup>'
+ '</Project>')
+
+ xml = easy_xml.XmlToString(
+ ['Project',
+ ['PropertyGroup', {'Label': 'Globals'},
+ ['ProjectGuid', '{D2250C20-3A94-4FB9-AF73-11BC5B73884B}'],
+ ['Keyword', 'Win32Proj'],
+ ['RootNamespace', 'automated_ui_tests']
+ ],
+ ['Import', {'Project': '$(VCTargetsPath)\\Microsoft.Cpp.props'}],
+ ['PropertyGroup',
+ {'Condition': "'$(Configuration)|$(Platform)'=='Debug|Win32'",
+ 'Label': 'Configuration'},
+ ['ConfigurationType', 'Application'],
+ ['CharacterSet', 'Unicode']
+ ]
+ ])
+ self.assertEqual(xml, target)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/gyp/pylib/gyp/generator/__init__.py b/chromium/tools/gyp/pylib/gyp/generator/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/__init__.py
diff --git a/chromium/tools/gyp/pylib/gyp/generator/android.py b/chromium/tools/gyp/pylib/gyp/generator/android.py
new file mode 100644
index 00000000000..9476a1df69a
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/android.py
@@ -0,0 +1,1069 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Notes:
+#
+# This generates makefiles suitable for inclusion into the Android build system
+# via an Android.mk file. It is based on make.py, the standard makefile
+# generator.
+#
+# The code below generates a separate .mk file for each target, but
+# all are sourced by the top-level GypAndroid.mk. This means that all
+# variables in .mk-files clobber one another, and furthermore that any
+# variables set potentially clash with other Android build system variables.
+# Try to avoid setting global variables where possible.
+
+import gyp
+import gyp.common
+import gyp.generator.make as make # Reuse global functions from make backend.
+import os
+import re
+import subprocess
+
+generator_default_variables = {
+ 'OS': 'android',
+ 'EXECUTABLE_PREFIX': '',
+ 'EXECUTABLE_SUFFIX': '',
+ 'STATIC_LIB_PREFIX': 'lib',
+ 'SHARED_LIB_PREFIX': 'lib',
+ 'STATIC_LIB_SUFFIX': '.a',
+ 'SHARED_LIB_SUFFIX': '.so',
+ 'INTERMEDIATE_DIR': '$(gyp_intermediate_dir)',
+ 'SHARED_INTERMEDIATE_DIR': '$(gyp_shared_intermediate_dir)',
+ 'PRODUCT_DIR': '$(gyp_shared_intermediate_dir)',
+ 'SHARED_LIB_DIR': '$(builddir)/lib.$(TOOLSET)',
+ 'LIB_DIR': '$(obj).$(TOOLSET)',
+ 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python.
+ 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', # This gets expanded by Python.
+ 'RULE_INPUT_PATH': '$(RULE_SOURCES)',
+ 'RULE_INPUT_EXT': '$(suffix $<)',
+ 'RULE_INPUT_NAME': '$(notdir $<)',
+ 'CONFIGURATION_NAME': '$(GYP_CONFIGURATION)',
+}
+
+# Make supports multiple toolsets
+generator_supports_multiple_toolsets = True
+
+
+# Generator-specific gyp specs.
+generator_additional_non_configuration_keys = [
+ # Boolean to declare that this target does not want its name mangled.
+ 'android_unmangled_name',
+]
+generator_additional_path_sections = []
+generator_extra_sources_for_rules = []
+
+
+SHARED_FOOTER = """\
+# "gyp_all_modules" is a concatenation of the "gyp_all_modules" targets from
+# all the included sub-makefiles. This is just here to clarify.
+gyp_all_modules:
+"""
+
+header = """\
+# This file is generated by gyp; do not edit.
+
+"""
+
+android_standard_include_paths = set([
+ # JNI_H_INCLUDE in build/core/binary.mk
+ 'dalvik/libnativehelper/include/nativehelper',
+ # from SRC_HEADERS in build/core/config.mk
+ 'system/core/include',
+ 'hardware/libhardware/include',
+ 'hardware/libhardware_legacy/include',
+ 'hardware/ril/include',
+ 'dalvik/libnativehelper/include',
+ 'frameworks/native/include',
+ 'frameworks/native/opengl/include',
+ 'frameworks/base/include',
+ 'frameworks/base/opengl/include',
+ 'frameworks/base/native/include',
+ 'external/skia/include',
+ # TARGET_C_INCLUDES in build/core/combo/TARGET_linux-arm.mk
+ 'bionic/libc/arch-arm/include',
+ 'bionic/libc/include',
+ 'bionic/libstdc++/include',
+ 'bionic/libc/kernel/common',
+ 'bionic/libc/kernel/arch-arm',
+ 'bionic/libm/include',
+ 'bionic/libm/include/arm',
+ 'bionic/libthread_db/include',
+ ])
+
+
+# Map gyp target types to Android module classes.
+MODULE_CLASSES = {
+ 'static_library': 'STATIC_LIBRARIES',
+ 'shared_library': 'SHARED_LIBRARIES',
+ 'executable': 'EXECUTABLES',
+}
+
+
+def IsCPPExtension(ext):
+ return make.COMPILABLE_EXTENSIONS.get(ext) == 'cxx'
+
+
+def Sourceify(path):
+ """Convert a path to its source directory form. The Android backend does not
+ support options.generator_output, so this function is a noop."""
+ return path
+
+
+# Map from qualified target to path to output.
+# For Android, the target of these maps is a tuple ('static', 'modulename'),
+# ('dynamic', 'modulename'), or ('path', 'some/path') instead of a string,
+# since we link by module.
+target_outputs = {}
+# Map from qualified target to any linkable output. A subset
+# of target_outputs. E.g. when mybinary depends on liba, we want to
+# include liba in the linker line; when otherbinary depends on
+# mybinary, we just want to build mybinary first.
+target_link_deps = {}
+
+
+class AndroidMkWriter(object):
+ """AndroidMkWriter packages up the writing of one target-specific Android.mk.
+
+ Its only real entry point is Write(), and is mostly used for namespacing.
+ """
+
+ def __init__(self, android_top_dir):
+ self.android_top_dir = android_top_dir
+
+ def Write(self, qualified_target, relative_target, base_path, output_filename,
+ spec, configs, part_of_all):
+ """The main entry point: writes a .mk file for a single target.
+
+ Arguments:
+ qualified_target: target we're generating
+ relative_target: qualified target name relative to the root
+ base_path: path relative to source root we're building in, used to resolve
+ target-relative paths
+ output_filename: output .mk file name to write
+ spec, configs: gyp info
+ part_of_all: flag indicating this target is part of 'all'
+ """
+ make.ensure_directory_exists(output_filename)
+
+ self.fp = open(output_filename, 'w')
+
+ self.fp.write(header)
+
+ self.qualified_target = qualified_target
+ self.relative_target = relative_target
+ self.path = base_path
+ self.target = spec['target_name']
+ self.type = spec['type']
+ self.toolset = spec['toolset']
+
+ deps, link_deps = self.ComputeDeps(spec)
+
+ # Some of the generation below can add extra output, sources, or
+ # link dependencies. All of the out params of the functions that
+ # follow use names like extra_foo.
+ extra_outputs = []
+ extra_sources = []
+
+ self.android_class = MODULE_CLASSES.get(self.type, 'GYP')
+ self.android_module = self.ComputeAndroidModule(spec)
+ (self.android_stem, self.android_suffix) = self.ComputeOutputParts(spec)
+ self.output = self.output_binary = self.ComputeOutput(spec)
+
+ # Standard header.
+ self.WriteLn('include $(CLEAR_VARS)\n')
+
+ # Module class and name.
+ self.WriteLn('LOCAL_MODULE_CLASS := ' + self.android_class)
+ self.WriteLn('LOCAL_MODULE := ' + self.android_module)
+ # Only emit LOCAL_MODULE_STEM if it's different to LOCAL_MODULE.
+ # The library module classes fail if the stem is set. ComputeOutputParts
+ # makes sure that stem == modulename in these cases.
+ if self.android_stem != self.android_module:
+ self.WriteLn('LOCAL_MODULE_STEM := ' + self.android_stem)
+ self.WriteLn('LOCAL_MODULE_SUFFIX := ' + self.android_suffix)
+ self.WriteLn('LOCAL_MODULE_TAGS := optional')
+ if self.toolset == 'host':
+ self.WriteLn('LOCAL_IS_HOST_MODULE := true')
+
+ # Grab output directories; needed for Actions and Rules.
+ self.WriteLn('gyp_intermediate_dir := $(call local-intermediates-dir)')
+ self.WriteLn('gyp_shared_intermediate_dir := '
+ '$(call intermediates-dir-for,GYP,shared)')
+ self.WriteLn()
+
+ # List files this target depends on so that actions/rules/copies/sources
+ # can depend on the list.
+ # TODO: doesn't pull in things through transitive link deps; needed?
+ target_dependencies = [x[1] for x in deps if x[0] == 'path']
+ self.WriteLn('# Make sure our deps are built first.')
+ self.WriteList(target_dependencies, 'GYP_TARGET_DEPENDENCIES',
+ local_pathify=True)
+
+ # Actions must come first, since they can generate more OBJs for use below.
+ if 'actions' in spec:
+ self.WriteActions(spec['actions'], extra_sources, extra_outputs)
+
+ # Rules must be early like actions.
+ if 'rules' in spec:
+ self.WriteRules(spec['rules'], extra_sources, extra_outputs)
+
+ if 'copies' in spec:
+ self.WriteCopies(spec['copies'], extra_outputs)
+
+ # GYP generated outputs.
+ self.WriteList(extra_outputs, 'GYP_GENERATED_OUTPUTS', local_pathify=True)
+
+ # Set LOCAL_ADDITIONAL_DEPENDENCIES so that Android's build rules depend
+ # on both our dependency targets and our generated files.
+ self.WriteLn('# Make sure our deps and generated files are built first.')
+ self.WriteLn('LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) '
+ '$(GYP_GENERATED_OUTPUTS)')
+ self.WriteLn()
+
+ # Sources.
+ if spec.get('sources', []) or extra_sources:
+ self.WriteSources(spec, configs, extra_sources)
+
+ self.WriteTarget(spec, configs, deps, link_deps, part_of_all)
+
+ # Update global list of target outputs, used in dependency tracking.
+ target_outputs[qualified_target] = ('path', self.output_binary)
+
+ # Update global list of link dependencies.
+ if self.type == 'static_library':
+ target_link_deps[qualified_target] = ('static', self.android_module)
+ elif self.type == 'shared_library':
+ target_link_deps[qualified_target] = ('shared', self.android_module)
+
+ self.fp.close()
+ return self.android_module
+
+
+ def WriteActions(self, actions, extra_sources, extra_outputs):
+ """Write Makefile code for any 'actions' from the gyp input.
+
+ extra_sources: a list that will be filled in with newly generated source
+ files, if any
+ extra_outputs: a list that will be filled in with any outputs of these
+ actions (used to make other pieces dependent on these
+ actions)
+ """
+ for action in actions:
+ name = make.StringToMakefileVariable('%s_%s' % (self.relative_target,
+ action['action_name']))
+ self.WriteLn('### Rules for action "%s":' % action['action_name'])
+ inputs = action['inputs']
+ outputs = action['outputs']
+
+ # Build up a list of outputs.
+ # Collect the output dirs we'll need.
+ dirs = set()
+ for out in outputs:
+ if not out.startswith('$'):
+ print ('WARNING: Action for target "%s" writes output to local path '
+ '"%s".' % (self.target, out))
+ dir = os.path.split(out)[0]
+ if dir:
+ dirs.add(dir)
+ if int(action.get('process_outputs_as_sources', False)):
+ extra_sources += outputs
+
+ # Prepare the actual command.
+ command = gyp.common.EncodePOSIXShellList(action['action'])
+ if 'message' in action:
+ quiet_cmd = 'Gyp action: %s ($@)' % action['message']
+ else:
+ quiet_cmd = 'Gyp action: %s ($@)' % name
+ if len(dirs) > 0:
+ command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
+
+ cd_action = 'cd $(gyp_local_path)/%s; ' % self.path
+ command = cd_action + command
+
+ # The makefile rules are all relative to the top dir, but the gyp actions
+ # are defined relative to their containing dir. This replaces the gyp_*
+ # variables for the action rule with an absolute version so that the
+ # output goes in the right place.
+ # Only write the gyp_* rules for the "primary" output (:1);
+ # it's superfluous for the "extra outputs", and this avoids accidentally
+ # writing duplicate dummy rules for those outputs.
+ main_output = make.QuoteSpaces(self.LocalPathify(outputs[0]))
+ self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output)
+ self.WriteLn('%s: gyp_intermediate_dir := '
+ '$(abspath $(gyp_intermediate_dir))' % main_output)
+ self.WriteLn('%s: gyp_shared_intermediate_dir := '
+ '$(abspath $(gyp_shared_intermediate_dir))' % main_output)
+
+ # Android's envsetup.sh adds a number of directories to the path including
+ # the built host binary directory. This causes actions/rules invoked by
+ # gyp to sometimes use these instead of system versions, e.g. bison.
+ # The built host binaries may not be suitable, and can cause errors.
+ # So, we remove them from the PATH using the ANDROID_BUILD_PATHS variable
+ # set by envsetup.
+ self.WriteLn('%s: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))'
+ % main_output)
+
+ for input in inputs:
+ assert ' ' not in input, (
+ "Spaces in action input filenames not supported (%s)" % input)
+ for output in outputs:
+ assert ' ' not in output, (
+ "Spaces in action output filenames not supported (%s)" % output)
+
+ self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' %
+ (main_output, ' '.join(map(self.LocalPathify, inputs))))
+ self.WriteLn('\t@echo "%s"' % quiet_cmd)
+ self.WriteLn('\t$(hide)%s\n' % command)
+ for output in outputs[1:]:
+ # Make each output depend on the main output, with an empty command
+ # to force make to notice that the mtime has changed.
+ self.WriteLn('%s: %s ;' % (self.LocalPathify(output), main_output))
+
+ extra_outputs += outputs
+ self.WriteLn()
+
+ self.WriteLn()
+
+
+ def WriteRules(self, rules, extra_sources, extra_outputs):
+ """Write Makefile code for any 'rules' from the gyp input.
+
+ extra_sources: a list that will be filled in with newly generated source
+ files, if any
+ extra_outputs: a list that will be filled in with any outputs of these
+ rules (used to make other pieces dependent on these rules)
+ """
+ if len(rules) == 0:
+ return
+ rule_trigger = '%s_rule_trigger' % self.android_module
+
+ did_write_rule = False
+ for rule in rules:
+ if len(rule.get('rule_sources', [])) == 0:
+ continue
+ did_write_rule = True
+ name = make.StringToMakefileVariable('%s_%s' % (self.relative_target,
+ rule['rule_name']))
+ self.WriteLn('\n### Generated for rule "%s":' % name)
+ self.WriteLn('# "%s":' % rule)
+
+ inputs = rule.get('inputs')
+ for rule_source in rule.get('rule_sources', []):
+ (rule_source_dirname, rule_source_basename) = os.path.split(rule_source)
+ (rule_source_root, rule_source_ext) = \
+ os.path.splitext(rule_source_basename)
+
+ outputs = [self.ExpandInputRoot(out, rule_source_root,
+ rule_source_dirname)
+ for out in rule['outputs']]
+
+ dirs = set()
+ for out in outputs:
+ if not out.startswith('$'):
+ print ('WARNING: Rule for target %s writes output to local path %s'
+ % (self.target, out))
+ dir = os.path.dirname(out)
+ if dir:
+ dirs.add(dir)
+ extra_outputs += outputs
+ if int(rule.get('process_outputs_as_sources', False)):
+ extra_sources.extend(outputs)
+
+ components = []
+ for component in rule['action']:
+ component = self.ExpandInputRoot(component, rule_source_root,
+ rule_source_dirname)
+ if '$(RULE_SOURCES)' in component:
+ component = component.replace('$(RULE_SOURCES)',
+ rule_source)
+ components.append(component)
+
+ command = gyp.common.EncodePOSIXShellList(components)
+ cd_action = 'cd $(gyp_local_path)/%s; ' % self.path
+ command = cd_action + command
+ if dirs:
+ command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
+
+ # We set up a rule to build the first output, and then set up
+ # a rule for each additional output to depend on the first.
+ outputs = map(self.LocalPathify, outputs)
+ main_output = outputs[0]
+ self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output)
+ self.WriteLn('%s: gyp_intermediate_dir := '
+ '$(abspath $(gyp_intermediate_dir))' % main_output)
+ self.WriteLn('%s: gyp_shared_intermediate_dir := '
+ '$(abspath $(gyp_shared_intermediate_dir))' % main_output)
+
+ # See explanation in WriteActions.
+ self.WriteLn('%s: export PATH := '
+ '$(subst $(ANDROID_BUILD_PATHS),,$(PATH))' % main_output)
+
+ main_output_deps = self.LocalPathify(rule_source)
+ if inputs:
+ main_output_deps += ' '
+ main_output_deps += ' '.join([self.LocalPathify(f) for f in inputs])
+
+ self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' %
+ (main_output, main_output_deps))
+ self.WriteLn('\t%s\n' % command)
+ for output in outputs[1:]:
+ # Make each output depend on the main output, with an empty command
+ # to force make to notice that the mtime has changed.
+ self.WriteLn('%s: %s ;' % (output, main_output))
+ self.WriteLn('.PHONY: %s' % (rule_trigger))
+ self.WriteLn('%s: %s' % (rule_trigger, main_output))
+ self.WriteLn('')
+ if did_write_rule:
+ extra_sources.append(rule_trigger) # Force all rules to run.
+ self.WriteLn('### Finished generating for all rules')
+ self.WriteLn('')
+
+
+ def WriteCopies(self, copies, extra_outputs):
+ """Write Makefile code for any 'copies' from the gyp input.
+
+ extra_outputs: a list that will be filled in with any outputs of this action
+ (used to make other pieces dependent on this action)
+ """
+ self.WriteLn('### Generated for copy rule.')
+
+ variable = make.StringToMakefileVariable(self.relative_target + '_copies')
+ outputs = []
+ for copy in copies:
+ for path in copy['files']:
+ # The Android build system does not allow generation of files into the
+ # source tree. The destination should start with a variable, which will
+ # typically be $(gyp_intermediate_dir) or
+ # $(gyp_shared_intermediate_dir). Note that we can't use an assertion
+ # because some of the gyp tests depend on this.
+ if not copy['destination'].startswith('$'):
+ print ('WARNING: Copy rule for target %s writes output to '
+ 'local path %s' % (self.target, copy['destination']))
+
+ # LocalPathify() calls normpath, stripping trailing slashes.
+ path = Sourceify(self.LocalPathify(path))
+ filename = os.path.split(path)[1]
+ output = Sourceify(self.LocalPathify(os.path.join(copy['destination'],
+ filename)))
+
+ self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES) | $(ACP)' %
+ (output, path))
+ self.WriteLn('\t@echo Copying: $@')
+ self.WriteLn('\t$(hide) mkdir -p $(dir $@)')
+ self.WriteLn('\t$(hide) $(ACP) -r $< $@')
+ self.WriteLn()
+ outputs.append(output)
+ self.WriteLn('%s = %s' % (variable,
+ ' '.join(map(make.QuoteSpaces, outputs))))
+ extra_outputs.append('$(%s)' % variable)
+ self.WriteLn()
+
+
+ def WriteSourceFlags(self, spec, configs):
+ """Write out the flags and include paths used to compile source files for
+ the current target.
+
+ Args:
+ spec, configs: input from gyp.
+ """
+ for configname, config in sorted(configs.iteritems()):
+ extracted_includes = []
+
+ self.WriteLn('\n# Flags passed to both C and C++ files.')
+ cflags, includes_from_cflags = self.ExtractIncludesFromCFlags(
+ config.get('cflags', []) + config.get('cflags_c', []))
+ extracted_includes.extend(includes_from_cflags)
+ self.WriteList(cflags, 'MY_CFLAGS_%s' % configname)
+
+ self.WriteList(config.get('defines'), 'MY_DEFS_%s' % configname,
+ prefix='-D', quoter=make.EscapeCppDefine)
+
+ self.WriteLn('\n# Include paths placed before CFLAGS/CPPFLAGS')
+ includes = list(config.get('include_dirs', []))
+ includes.extend(extracted_includes)
+ includes = map(Sourceify, map(self.LocalPathify, includes))
+ includes = self.NormalizeIncludePaths(includes)
+ self.WriteList(includes, 'LOCAL_C_INCLUDES_%s' % configname)
+
+ self.WriteLn('\n# Flags passed to only C++ (and not C) files.')
+ self.WriteList(config.get('cflags_cc'), 'LOCAL_CPPFLAGS_%s' % configname)
+
+ self.WriteLn('\nLOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) '
+ '$(MY_DEFS_$(GYP_CONFIGURATION))')
+ # Undefine ANDROID for host modules
+ # TODO: the source code should not use macro ANDROID to tell if it's host
+ # or target module.
+ if self.toolset == 'host':
+ self.WriteLn('# Undefine ANDROID for host modules')
+ self.WriteLn('LOCAL_CFLAGS += -UANDROID')
+ self.WriteLn('LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) '
+ '$(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))')
+ self.WriteLn('LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))')
+
+
+ def WriteSources(self, spec, configs, extra_sources):
+ """Write Makefile code for any 'sources' from the gyp input.
+ These are source files necessary to build the current target.
+ We need to handle shared_intermediate directory source files as
+ a special case by copying them to the intermediate directory and
+ treating them as a genereated sources. Otherwise the Android build
+ rules won't pick them up.
+
+ Args:
+ spec, configs: input from gyp.
+ extra_sources: Sources generated from Actions or Rules.
+ """
+ sources = filter(make.Compilable, spec.get('sources', []))
+ generated_not_sources = [x for x in extra_sources if not make.Compilable(x)]
+ extra_sources = filter(make.Compilable, extra_sources)
+
+ # Determine and output the C++ extension used by these sources.
+ # We simply find the first C++ file and use that extension.
+ all_sources = sources + extra_sources
+ local_cpp_extension = '.cpp'
+ for source in all_sources:
+ (root, ext) = os.path.splitext(source)
+ if IsCPPExtension(ext):
+ local_cpp_extension = ext
+ break
+ if local_cpp_extension != '.cpp':
+ self.WriteLn('LOCAL_CPP_EXTENSION := %s' % local_cpp_extension)
+
+ # We need to move any non-generated sources that are coming from the
+ # shared intermediate directory out of LOCAL_SRC_FILES and put them
+ # into LOCAL_GENERATED_SOURCES. We also need to move over any C++ files
+ # that don't match our local_cpp_extension, since Android will only
+ # generate Makefile rules for a single LOCAL_CPP_EXTENSION.
+ local_files = []
+ for source in sources:
+ (root, ext) = os.path.splitext(source)
+ if '$(gyp_shared_intermediate_dir)' in source:
+ extra_sources.append(source)
+ elif '$(gyp_intermediate_dir)' in source:
+ extra_sources.append(source)
+ elif IsCPPExtension(ext) and ext != local_cpp_extension:
+ extra_sources.append(source)
+ else:
+ local_files.append(os.path.normpath(os.path.join(self.path, source)))
+
+ # For any generated source, if it is coming from the shared intermediate
+ # directory then we add a Make rule to copy them to the local intermediate
+ # directory first. This is because the Android LOCAL_GENERATED_SOURCES
+ # must be in the local module intermediate directory for the compile rules
+ # to work properly. If the file has the wrong C++ extension, then we add
+ # a rule to copy that to intermediates and use the new version.
+ final_generated_sources = []
+ # If a source file gets copied, we still need to add the orginal source
+ # directory as header search path, for GCC searches headers in the
+ # directory that contains the source file by default.
+ origin_src_dirs = []
+ for source in extra_sources:
+ local_file = source
+ if not '$(gyp_intermediate_dir)/' in local_file:
+ basename = os.path.basename(local_file)
+ local_file = '$(gyp_intermediate_dir)/' + basename
+ (root, ext) = os.path.splitext(local_file)
+ if IsCPPExtension(ext) and ext != local_cpp_extension:
+ local_file = root + local_cpp_extension
+ if local_file != source:
+ self.WriteLn('%s: %s' % (local_file, self.LocalPathify(source)))
+ self.WriteLn('\tmkdir -p $(@D); cp $< $@')
+ origin_src_dirs.append(os.path.dirname(source))
+ final_generated_sources.append(local_file)
+
+ # We add back in all of the non-compilable stuff to make sure that the
+ # make rules have dependencies on them.
+ final_generated_sources.extend(generated_not_sources)
+ self.WriteList(final_generated_sources, 'LOCAL_GENERATED_SOURCES')
+
+ origin_src_dirs = gyp.common.uniquer(origin_src_dirs)
+ origin_src_dirs = map(Sourceify, map(self.LocalPathify, origin_src_dirs))
+ self.WriteList(origin_src_dirs, 'GYP_COPIED_SOURCE_ORIGIN_DIRS')
+
+ self.WriteList(local_files, 'LOCAL_SRC_FILES')
+
+ # Write out the flags used to compile the source; this must be done last
+ # so that GYP_COPIED_SOURCE_ORIGIN_DIRS can be used as an include path.
+ self.WriteSourceFlags(spec, configs)
+
+
+ def ComputeAndroidModule(self, spec):
+ """Return the Android module name used for a gyp spec.
+
+ We use the complete qualified target name to avoid collisions between
+ duplicate targets in different directories. We also add a suffix to
+ distinguish gyp-generated module names.
+ """
+
+ if int(spec.get('android_unmangled_name', 0)):
+ assert self.type != 'shared_library' or self.target.startswith('lib')
+ return self.target
+
+ if self.type == 'shared_library':
+ # For reasons of convention, the Android build system requires that all
+ # shared library modules are named 'libfoo' when generating -l flags.
+ prefix = 'lib_'
+ else:
+ prefix = ''
+
+ if spec['toolset'] == 'host':
+ suffix = '_host_gyp'
+ else:
+ suffix = '_gyp'
+
+ if self.path:
+ name = '%s%s_%s%s' % (prefix, self.path, self.target, suffix)
+ else:
+ name = '%s%s%s' % (prefix, self.target, suffix)
+
+ return make.StringToMakefileVariable(name)
+
+
+ def ComputeOutputParts(self, spec):
+ """Return the 'output basename' of a gyp spec, split into filename + ext.
+
+ Android libraries must be named the same thing as their module name,
+ otherwise the linker can't find them, so product_name and so on must be
+ ignored if we are building a library, and the "lib" prepending is
+ not done for Android.
+ """
+ assert self.type != 'loadable_module' # TODO: not supported?
+
+ target = spec['target_name']
+ target_prefix = ''
+ target_ext = ''
+ if self.type == 'static_library':
+ target = self.ComputeAndroidModule(spec)
+ target_ext = '.a'
+ elif self.type == 'shared_library':
+ target = self.ComputeAndroidModule(spec)
+ target_ext = '.so'
+ elif self.type == 'none':
+ target_ext = '.stamp'
+ elif self.type != 'executable':
+ print ("ERROR: What output file should be generated?",
+ "type", self.type, "target", target)
+
+ if self.type != 'static_library' and self.type != 'shared_library':
+ target_prefix = spec.get('product_prefix', target_prefix)
+ target = spec.get('product_name', target)
+ product_ext = spec.get('product_extension')
+ if product_ext:
+ target_ext = '.' + product_ext
+
+ target_stem = target_prefix + target
+ return (target_stem, target_ext)
+
+
+ def ComputeOutputBasename(self, spec):
+ """Return the 'output basename' of a gyp spec.
+
+ E.g., the loadable module 'foobar' in directory 'baz' will produce
+ 'libfoobar.so'
+ """
+ return ''.join(self.ComputeOutputParts(spec))
+
+
+ def ComputeOutput(self, spec):
+ """Return the 'output' (full output path) of a gyp spec.
+
+ E.g., the loadable module 'foobar' in directory 'baz' will produce
+ '$(obj)/baz/libfoobar.so'
+ """
+ if self.type == 'executable' and self.toolset == 'host':
+ # We install host executables into shared_intermediate_dir so they can be
+ # run by gyp rules that refer to PRODUCT_DIR.
+ path = '$(gyp_shared_intermediate_dir)'
+ elif self.type == 'shared_library':
+ if self.toolset == 'host':
+ path = '$(HOST_OUT_INTERMEDIATE_LIBRARIES)'
+ else:
+ path = '$(TARGET_OUT_INTERMEDIATE_LIBRARIES)'
+ else:
+ # Other targets just get built into their intermediate dir.
+ if self.toolset == 'host':
+ path = '$(call intermediates-dir-for,%s,%s,true)' % (self.android_class,
+ self.android_module)
+ else:
+ path = '$(call intermediates-dir-for,%s,%s)' % (self.android_class,
+ self.android_module)
+
+ assert spec.get('product_dir') is None # TODO: not supported?
+ return os.path.join(path, self.ComputeOutputBasename(spec))
+
+ def NormalizeIncludePaths(self, include_paths):
+ """ Normalize include_paths.
+ Convert absolute paths to relative to the Android top directory;
+ filter out include paths that are already brought in by the Android build
+ system.
+
+ Args:
+ include_paths: A list of unprocessed include paths.
+ Returns:
+ A list of normalized include paths.
+ """
+ normalized = []
+ for path in include_paths:
+ if path[0] == '/':
+ path = gyp.common.RelativePath(path, self.android_top_dir)
+
+ # Filter out the Android standard search path.
+ if path not in android_standard_include_paths:
+ normalized.append(path)
+ return normalized
+
+ def ExtractIncludesFromCFlags(self, cflags):
+ """Extract includes "-I..." out from cflags
+
+ Args:
+ cflags: A list of compiler flags, which may be mixed with "-I.."
+ Returns:
+ A tuple of lists: (clean_clfags, include_paths). "-I.." is trimmed.
+ """
+ clean_cflags = []
+ include_paths = []
+ for flag in cflags:
+ if flag.startswith('-I'):
+ include_paths.append(flag[2:])
+ else:
+ clean_cflags.append(flag)
+
+ return (clean_cflags, include_paths)
+
+ def ComputeAndroidLibraryModuleNames(self, libraries):
+ """Compute the Android module names from libraries, ie spec.get('libraries')
+
+ Args:
+ libraries: the value of spec.get('libraries')
+ Returns:
+ A tuple (static_lib_modules, dynamic_lib_modules)
+ """
+ static_lib_modules = []
+ dynamic_lib_modules = []
+ for libs in libraries:
+ # Libs can have multiple words.
+ for lib in libs.split():
+ # Filter the system libraries, which are added by default by the Android
+ # build system.
+ if (lib == '-lc' or lib == '-lstdc++' or lib == '-lm' or
+ lib.endswith('libgcc.a')):
+ continue
+ match = re.search(r'([^/]+)\.a$', lib)
+ if match:
+ static_lib_modules.append(match.group(1))
+ continue
+ match = re.search(r'([^/]+)\.so$', lib)
+ if match:
+ dynamic_lib_modules.append(match.group(1))
+ continue
+ # "-lstlport" -> libstlport
+ if lib.startswith('-l'):
+ if lib.endswith('_static'):
+ static_lib_modules.append('lib' + lib[2:])
+ else:
+ dynamic_lib_modules.append('lib' + lib[2:])
+ return (static_lib_modules, dynamic_lib_modules)
+
+
+ def ComputeDeps(self, spec):
+ """Compute the dependencies of a gyp spec.
+
+ Returns a tuple (deps, link_deps), where each is a list of
+ filenames that will need to be put in front of make for either
+ building (deps) or linking (link_deps).
+ """
+ deps = []
+ link_deps = []
+ if 'dependencies' in spec:
+ deps.extend([target_outputs[dep] for dep in spec['dependencies']
+ if target_outputs[dep]])
+ for dep in spec['dependencies']:
+ if dep in target_link_deps:
+ link_deps.append(target_link_deps[dep])
+ deps.extend(link_deps)
+ return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps))
+
+
+ def WriteTargetFlags(self, spec, configs, link_deps):
+ """Write Makefile code to specify the link flags and library dependencies.
+
+ spec, configs: input from gyp.
+ link_deps: link dependency list; see ComputeDeps()
+ """
+ for configname, config in sorted(configs.iteritems()):
+ ldflags = list(config.get('ldflags', []))
+ self.WriteLn('')
+ self.WriteList(ldflags, 'LOCAL_LDFLAGS_%s' % configname)
+ self.WriteLn('\nLOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))')
+
+ # Libraries (i.e. -lfoo)
+ libraries = gyp.common.uniquer(spec.get('libraries', []))
+ static_libs, dynamic_libs = self.ComputeAndroidLibraryModuleNames(
+ libraries)
+
+ # Link dependencies (i.e. libfoo.a, libfoo.so)
+ static_link_deps = [x[1] for x in link_deps if x[0] == 'static']
+ shared_link_deps = [x[1] for x in link_deps if x[0] == 'shared']
+ self.WriteLn('')
+ self.WriteList(static_libs + static_link_deps,
+ 'LOCAL_STATIC_LIBRARIES')
+ self.WriteLn('# Enable grouping to fix circular references')
+ self.WriteLn('LOCAL_GROUP_STATIC_LIBRARIES := true')
+ self.WriteLn('')
+ self.WriteList(dynamic_libs + shared_link_deps,
+ 'LOCAL_SHARED_LIBRARIES')
+
+
+ def WriteTarget(self, spec, configs, deps, link_deps, part_of_all):
+ """Write Makefile code to produce the final target of the gyp spec.
+
+ spec, configs: input from gyp.
+ deps, link_deps: dependency lists; see ComputeDeps()
+ part_of_all: flag indicating this target is part of 'all'
+ """
+ self.WriteLn('### Rules for final target.')
+
+ if self.type != 'none':
+ self.WriteTargetFlags(spec, configs, link_deps)
+
+ # Add to the set of targets which represent the gyp 'all' target. We use the
+ # name 'gyp_all_modules' as the Android build system doesn't allow the use
+ # of the Make target 'all' and because 'all_modules' is the equivalent of
+ # the Make target 'all' on Android.
+ if part_of_all:
+ self.WriteLn('# Add target alias to "gyp_all_modules" target.')
+ self.WriteLn('.PHONY: gyp_all_modules')
+ self.WriteLn('gyp_all_modules: %s' % self.android_module)
+ self.WriteLn('')
+
+ # Add an alias from the gyp target name to the Android module name. This
+ # simplifies manual builds of the target, and is required by the test
+ # framework.
+ if self.target != self.android_module:
+ self.WriteLn('# Alias gyp target name.')
+ self.WriteLn('.PHONY: %s' % self.target)
+ self.WriteLn('%s: %s' % (self.target, self.android_module))
+ self.WriteLn('')
+
+ # Add the command to trigger build of the target type depending
+ # on the toolset. Ex: BUILD_STATIC_LIBRARY vs. BUILD_HOST_STATIC_LIBRARY
+ # NOTE: This has to come last!
+ modifier = ''
+ if self.toolset == 'host':
+ modifier = 'HOST_'
+ if self.type == 'static_library':
+ self.WriteLn('include $(BUILD_%sSTATIC_LIBRARY)' % modifier)
+ elif self.type == 'shared_library':
+ self.WriteLn('LOCAL_PRELINK_MODULE := false')
+ self.WriteLn('include $(BUILD_%sSHARED_LIBRARY)' % modifier)
+ elif self.type == 'executable':
+ if self.toolset == 'host':
+ self.WriteLn('LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)')
+ else:
+ # Don't install target executables for now, as it results in them being
+ # included in ROM. This can be revisited if there's a reason to install
+ # them later.
+ self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true')
+ self.WriteLn('include $(BUILD_%sEXECUTABLE)' % modifier)
+ else:
+ self.WriteLn('LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp')
+ self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true')
+ self.WriteLn()
+ self.WriteLn('include $(BUILD_SYSTEM)/base_rules.mk')
+ self.WriteLn()
+ self.WriteLn('$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)')
+ self.WriteLn('\t$(hide) echo "Gyp timestamp: $@"')
+ self.WriteLn('\t$(hide) mkdir -p $(dir $@)')
+ self.WriteLn('\t$(hide) touch $@')
+
+
+ def WriteList(self, value_list, variable=None, prefix='',
+ quoter=make.QuoteIfNecessary, local_pathify=False):
+ """Write a variable definition that is a list of values.
+
+ E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out
+ foo = blaha blahb
+ but in a pretty-printed style.
+ """
+ values = ''
+ if value_list:
+ value_list = [quoter(prefix + l) for l in value_list]
+ if local_pathify:
+ value_list = [self.LocalPathify(l) for l in value_list]
+ values = ' \\\n\t' + ' \\\n\t'.join(value_list)
+ self.fp.write('%s :=%s\n\n' % (variable, values))
+
+
+ def WriteLn(self, text=''):
+ self.fp.write(text + '\n')
+
+
+ def LocalPathify(self, path):
+ """Convert a subdirectory-relative path into a normalized path which starts
+ with the make variable $(LOCAL_PATH) (i.e. the top of the project tree).
+ Absolute paths, or paths that contain variables, are just normalized."""
+ if '$(' in path or os.path.isabs(path):
+ # path is not a file in the project tree in this case, but calling
+ # normpath is still important for trimming trailing slashes.
+ return os.path.normpath(path)
+ local_path = os.path.join('$(LOCAL_PATH)', self.path, path)
+ local_path = os.path.normpath(local_path)
+ # Check that normalizing the path didn't ../ itself out of $(LOCAL_PATH)
+ # - i.e. that the resulting path is still inside the project tree. The
+ # path may legitimately have ended up containing just $(LOCAL_PATH), though,
+ # so we don't look for a slash.
+ assert local_path.startswith('$(LOCAL_PATH)'), (
+ 'Path %s attempts to escape from gyp path %s !)' % (path, self.path))
+ return local_path
+
+
+ def ExpandInputRoot(self, template, expansion, dirname):
+ if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template:
+ return template
+ path = template % {
+ 'INPUT_ROOT': expansion,
+ 'INPUT_DIRNAME': dirname,
+ }
+ return path
+
+
+def PerformBuild(data, configurations, params):
+ # The android backend only supports the default configuration.
+ options = params['options']
+ makefile = os.path.abspath(os.path.join(options.toplevel_dir,
+ 'GypAndroid.mk'))
+ env = dict(os.environ)
+ env['ONE_SHOT_MAKEFILE'] = makefile
+ arguments = ['make', '-C', os.environ['ANDROID_BUILD_TOP'], 'gyp_all_modules']
+ print 'Building: %s' % arguments
+ subprocess.check_call(arguments, env=env)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ options = params['options']
+ generator_flags = params.get('generator_flags', {})
+ builddir_name = generator_flags.get('output_dir', 'out')
+ limit_to_target_all = generator_flags.get('limit_to_target_all', False)
+ android_top_dir = os.environ.get('ANDROID_BUILD_TOP')
+ assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.'
+
+ def CalculateMakefilePath(build_file, base_name):
+ """Determine where to write a Makefile for a given gyp file."""
+ # Paths in gyp files are relative to the .gyp file, but we want
+ # paths relative to the source root for the master makefile. Grab
+ # the path of the .gyp file as the base to relativize against.
+ # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
+ base_path = gyp.common.RelativePath(os.path.dirname(build_file),
+ options.depth)
+ # We write the file in the base_path directory.
+ output_file = os.path.join(options.depth, base_path, base_name)
+ assert not options.generator_output, (
+ 'The Android backend does not support options.generator_output.')
+ base_path = gyp.common.RelativePath(os.path.dirname(build_file),
+ options.toplevel_dir)
+ return base_path, output_file
+
+ # TODO: search for the first non-'Default' target. This can go
+ # away when we add verification that all targets have the
+ # necessary configurations.
+ default_configuration = None
+ toolsets = set([target_dicts[target]['toolset'] for target in target_list])
+ for target in target_list:
+ spec = target_dicts[target]
+ if spec['default_configuration'] != 'Default':
+ default_configuration = spec['default_configuration']
+ break
+ if not default_configuration:
+ default_configuration = 'Default'
+
+ srcdir = '.'
+ makefile_name = 'GypAndroid' + options.suffix + '.mk'
+ makefile_path = os.path.join(options.toplevel_dir, makefile_name)
+ assert not options.generator_output, (
+ 'The Android backend does not support options.generator_output.')
+ make.ensure_directory_exists(makefile_path)
+ root_makefile = open(makefile_path, 'w')
+
+ root_makefile.write(header)
+
+ # We set LOCAL_PATH just once, here, to the top of the project tree. This
+ # allows all the other paths we use to be relative to the Android.mk file,
+ # as the Android build system expects.
+ root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n')
+
+ # Find the list of targets that derive from the gyp file(s) being built.
+ needed_targets = set()
+ for build_file in params['build_files']:
+ for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
+ needed_targets.add(target)
+
+ build_files = set()
+ include_list = set()
+ android_modules = {}
+ for qualified_target in target_list:
+ build_file, target, toolset = gyp.common.ParseQualifiedTarget(
+ qualified_target)
+ relative_build_file = gyp.common.RelativePath(build_file,
+ options.toplevel_dir)
+ build_files.add(relative_build_file)
+ included_files = data[build_file]['included_files']
+ for included_file in included_files:
+ # The included_files entries are relative to the dir of the build file
+ # that included them, so we have to undo that and then make them relative
+ # to the root dir.
+ relative_include_file = gyp.common.RelativePath(
+ gyp.common.UnrelativePath(included_file, build_file),
+ options.toplevel_dir)
+ abs_include_file = os.path.abspath(relative_include_file)
+ # If the include file is from the ~/.gyp dir, we should use absolute path
+ # so that relocating the src dir doesn't break the path.
+ if (params['home_dot_gyp'] and
+ abs_include_file.startswith(params['home_dot_gyp'])):
+ build_files.add(abs_include_file)
+ else:
+ build_files.add(relative_include_file)
+
+ base_path, output_file = CalculateMakefilePath(build_file,
+ target + '.' + toolset + options.suffix + '.mk')
+
+ spec = target_dicts[qualified_target]
+ configs = spec['configurations']
+
+ part_of_all = (qualified_target in needed_targets and
+ not int(spec.get('suppress_wildcard', False)))
+ if limit_to_target_all and not part_of_all:
+ continue
+
+ relative_target = gyp.common.QualifiedTarget(relative_build_file, target,
+ toolset)
+ writer = AndroidMkWriter(android_top_dir)
+ android_module = writer.Write(qualified_target, relative_target, base_path,
+ output_file, spec, configs,
+ part_of_all=part_of_all)
+ if android_module in android_modules:
+ print ('ERROR: Android module names must be unique. The following '
+ 'targets both generate Android module name %s.\n %s\n %s' %
+ (android_module, android_modules[android_module],
+ qualified_target))
+ return
+ android_modules[android_module] = qualified_target
+
+ # Our root_makefile lives at the source root. Compute the relative path
+ # from there to the output_file for including.
+ mkfile_rel_path = gyp.common.RelativePath(output_file,
+ os.path.dirname(makefile_path))
+ include_list.add(mkfile_rel_path)
+
+ root_makefile.write('GYP_CONFIGURATION ?= %s\n' % default_configuration)
+
+ # Write out the sorted list of includes.
+ root_makefile.write('\n')
+ for include_file in sorted(include_list):
+ root_makefile.write('include $(LOCAL_PATH)/' + include_file + '\n')
+ root_makefile.write('\n')
+
+ root_makefile.write(SHARED_FOOTER)
+
+ root_makefile.close()
diff --git a/chromium/tools/gyp/pylib/gyp/generator/dump_dependency_json.py b/chromium/tools/gyp/pylib/gyp/generator/dump_dependency_json.py
new file mode 100644
index 00000000000..f8480dd2842
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/dump_dependency_json.py
@@ -0,0 +1,93 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import os
+import gyp
+import gyp.common
+import gyp.msvs_emulation
+import json
+import sys
+
+generator_supports_multiple_toolsets = True
+
+generator_wants_static_library_dependencies_adjusted = False
+
+generator_default_variables = {
+}
+for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR',
+ 'LIB_DIR', 'SHARED_LIB_DIR']:
+ # Some gyp steps fail if these are empty(!).
+ generator_default_variables[dirname] = 'dir'
+for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
+ 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
+ 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
+ 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
+ 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
+ 'CONFIGURATION_NAME']:
+ generator_default_variables[unused] = ''
+
+
+def CalculateVariables(default_variables, params):
+ generator_flags = params.get('generator_flags', {})
+ for key, val in generator_flags.items():
+ default_variables.setdefault(key, val)
+ default_variables.setdefault('OS', gyp.common.GetFlavor(params))
+
+ flavor = gyp.common.GetFlavor(params)
+ if flavor =='win':
+ # Copy additional generator configuration data from VS, which is shared
+ # by the Windows Ninja generator.
+ import gyp.generator.msvs as msvs_generator
+ generator_additional_non_configuration_keys = getattr(msvs_generator,
+ 'generator_additional_non_configuration_keys', [])
+ generator_additional_path_sections = getattr(msvs_generator,
+ 'generator_additional_path_sections', [])
+
+ # Set a variable so conditions can be based on msvs_version.
+ msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags)
+ default_variables['MSVS_VERSION'] = msvs_version.ShortName()
+
+ # To determine processor word size on Windows, in addition to checking
+ # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
+ # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
+ # contains the actual word size of the system when running thru WOW64).
+ if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
+ '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
+ default_variables['MSVS_OS_BITS'] = 64
+ else:
+ default_variables['MSVS_OS_BITS'] = 32
+
+
+def CalculateGeneratorInputInfo(params):
+ """Calculate the generator specific info that gets fed to input (called by
+ gyp)."""
+ generator_flags = params.get('generator_flags', {})
+ if generator_flags.get('adjust_static_libraries', False):
+ global generator_wants_static_library_dependencies_adjusted
+ generator_wants_static_library_dependencies_adjusted = True
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ # Map of target -> list of targets it depends on.
+ edges = {}
+
+ # Queue of targets to visit.
+ targets_to_visit = target_list[:]
+
+ while len(targets_to_visit) > 0:
+ target = targets_to_visit.pop()
+ if target in edges:
+ continue
+ edges[target] = []
+
+ for dep in target_dicts[target].get('dependencies', []):
+ edges[target].append(dep)
+ targets_to_visit.append(dep)
+
+ filename = 'dump.json'
+ f = open(filename, 'w')
+ json.dump(edges, f)
+ f.close()
+ print 'Wrote json to %s.' % filename
diff --git a/chromium/tools/gyp/pylib/gyp/generator/eclipse.py b/chromium/tools/gyp/pylib/gyp/generator/eclipse.py
new file mode 100644
index 00000000000..08425da8e89
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/eclipse.py
@@ -0,0 +1,277 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""GYP backend that generates Eclipse CDT settings files.
+
+This backend DOES NOT generate Eclipse CDT projects. Instead, it generates XML
+files that can be imported into an Eclipse CDT project. The XML file contains a
+list of include paths and symbols (i.e. defines).
+
+Because a full .cproject definition is not created by this generator, it's not
+possible to properly define the include dirs and symbols for each file
+individually. Instead, one set of includes/symbols is generated for the entire
+project. This works fairly well (and is a vast improvement in general), but may
+still result in a few indexer issues here and there.
+
+This generator has no automated tests, so expect it to be broken.
+"""
+
+from xml.sax.saxutils import escape
+import os.path
+import subprocess
+import gyp
+import gyp.common
+import shlex
+
+generator_wants_static_library_dependencies_adjusted = False
+
+generator_default_variables = {
+}
+
+for dirname in ['INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']:
+ # Some gyp steps fail if these are empty(!).
+ generator_default_variables[dirname] = 'dir'
+
+for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
+ 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
+ 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
+ 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
+ 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
+ 'CONFIGURATION_NAME']:
+ generator_default_variables[unused] = ''
+
+# Include dirs will occasionally use the SHARED_INTERMEDIATE_DIR variable as
+# part of the path when dealing with generated headers. This value will be
+# replaced dynamically for each configuration.
+generator_default_variables['SHARED_INTERMEDIATE_DIR'] = \
+ '$SHARED_INTERMEDIATE_DIR'
+
+
+def CalculateVariables(default_variables, params):
+ generator_flags = params.get('generator_flags', {})
+ for key, val in generator_flags.items():
+ default_variables.setdefault(key, val)
+ default_variables.setdefault('OS', gyp.common.GetFlavor(params))
+
+
+def CalculateGeneratorInputInfo(params):
+ """Calculate the generator specific info that gets fed to input (called by
+ gyp)."""
+ generator_flags = params.get('generator_flags', {})
+ if generator_flags.get('adjust_static_libraries', False):
+ global generator_wants_static_library_dependencies_adjusted
+ generator_wants_static_library_dependencies_adjusted = True
+
+
+def GetAllIncludeDirectories(target_list, target_dicts,
+ shared_intermediate_dirs, config_name):
+ """Calculate the set of include directories to be used.
+
+ Returns:
+ A list including all the include_dir's specified for every target followed
+ by any include directories that were added as cflag compiler options.
+ """
+
+ gyp_includes_set = set()
+ compiler_includes_list = []
+
+ for target_name in target_list:
+ target = target_dicts[target_name]
+ if config_name in target['configurations']:
+ config = target['configurations'][config_name]
+
+ # Look for any include dirs that were explicitly added via cflags. This
+ # may be done in gyp files to force certain includes to come at the end.
+ # TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and
+ # remove this.
+ cflags = config['cflags']
+ for cflag in cflags:
+ include_dir = ''
+ if cflag.startswith('-I'):
+ include_dir = cflag[2:]
+ if include_dir and not include_dir in compiler_includes_list:
+ compiler_includes_list.append(include_dir)
+
+ # Find standard gyp include dirs.
+ if config.has_key('include_dirs'):
+ include_dirs = config['include_dirs']
+ for shared_intermediate_dir in shared_intermediate_dirs:
+ for include_dir in include_dirs:
+ include_dir = include_dir.replace('$SHARED_INTERMEDIATE_DIR',
+ shared_intermediate_dir)
+ if not os.path.isabs(include_dir):
+ base_dir = os.path.dirname(target_name)
+
+ include_dir = base_dir + '/' + include_dir
+ include_dir = os.path.abspath(include_dir)
+
+ if not include_dir in gyp_includes_set:
+ gyp_includes_set.add(include_dir)
+
+
+ # Generate a list that has all the include dirs.
+ all_includes_list = list(gyp_includes_set)
+ all_includes_list.sort()
+ for compiler_include in compiler_includes_list:
+ if not compiler_include in gyp_includes_set:
+ all_includes_list.append(compiler_include)
+
+ # All done.
+ return all_includes_list
+
+
+def GetCompilerPath(target_list, target_dicts, data):
+ """Determine a command that can be used to invoke the compiler.
+
+ Returns:
+ If this is a gyp project that has explicit make settings, try to determine
+ the compiler from that. Otherwise, see if a compiler was specified via the
+ CC_target environment variable.
+ """
+
+ # First, see if the compiler is configured in make's settings.
+ build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
+ make_global_settings_dict = data[build_file].get('make_global_settings', {})
+ for key, value in make_global_settings_dict:
+ if key in ['CC', 'CXX']:
+ return value
+
+ # Check to see if the compiler was specified as an environment variable.
+ for key in ['CC_target', 'CC', 'CXX']:
+ compiler = os.environ.get(key)
+ if compiler:
+ return compiler
+
+ return 'gcc'
+
+
+def GetAllDefines(target_list, target_dicts, data, config_name):
+ """Calculate the defines for a project.
+
+ Returns:
+ A dict that includes explict defines declared in gyp files along with all of
+ the default defines that the compiler uses.
+ """
+
+ # Get defines declared in the gyp files.
+ all_defines = {}
+ for target_name in target_list:
+ target = target_dicts[target_name]
+
+ if config_name in target['configurations']:
+ config = target['configurations'][config_name]
+ for define in config['defines']:
+ split_define = define.split('=', 1)
+ if len(split_define) == 1:
+ split_define.append('1')
+ if split_define[0].strip() in all_defines:
+ # Already defined
+ continue
+
+ all_defines[split_define[0].strip()] = split_define[1].strip()
+
+ # Get default compiler defines (if possible).
+ cc_target = GetCompilerPath(target_list, target_dicts, data)
+ if cc_target:
+ command = shlex.split(cc_target)
+ command.extend(['-E', '-dM', '-'])
+ cpp_proc = subprocess.Popen(args=command, cwd='.',
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ cpp_output = cpp_proc.communicate()[0]
+ cpp_lines = cpp_output.split('\n')
+ for cpp_line in cpp_lines:
+ if not cpp_line.strip():
+ continue
+ cpp_line_parts = cpp_line.split(' ', 2)
+ key = cpp_line_parts[1]
+ if len(cpp_line_parts) >= 3:
+ val = cpp_line_parts[2]
+ else:
+ val = '1'
+ all_defines[key] = val
+
+ return all_defines
+
+
+def WriteIncludePaths(out, eclipse_langs, include_dirs):
+ """Write the includes section of a CDT settings export file."""
+
+ out.write(' <section name="org.eclipse.cdt.internal.ui.wizards.' \
+ 'settingswizards.IncludePaths">\n')
+ out.write(' <language name="holder for library settings"></language>\n')
+ for lang in eclipse_langs:
+ out.write(' <language name="%s">\n' % lang)
+ for include_dir in include_dirs:
+ out.write(' <includepath workspace_path="false">%s</includepath>\n' %
+ include_dir)
+ out.write(' </language>\n')
+ out.write(' </section>\n')
+
+
+def WriteMacros(out, eclipse_langs, defines):
+ """Write the macros section of a CDT settings export file."""
+
+ out.write(' <section name="org.eclipse.cdt.internal.ui.wizards.' \
+ 'settingswizards.Macros">\n')
+ out.write(' <language name="holder for library settings"></language>\n')
+ for lang in eclipse_langs:
+ out.write(' <language name="%s">\n' % lang)
+ for key in sorted(defines.iterkeys()):
+ out.write(' <macro><name>%s</name><value>%s</value></macro>\n' %
+ (escape(key), escape(defines[key])))
+ out.write(' </language>\n')
+ out.write(' </section>\n')
+
+
+def GenerateOutputForConfig(target_list, target_dicts, data, params,
+ config_name):
+ options = params['options']
+ generator_flags = params.get('generator_flags', {})
+
+ # build_dir: relative path from source root to our output files.
+ # e.g. "out/Debug"
+ build_dir = os.path.join(generator_flags.get('output_dir', 'out'),
+ config_name)
+
+ toplevel_build = os.path.join(options.toplevel_dir, build_dir)
+ # Ninja uses out/Debug/gen while make uses out/Debug/obj/gen as the
+ # SHARED_INTERMEDIATE_DIR. Include both possible locations.
+ shared_intermediate_dirs = [os.path.join(toplevel_build, 'obj', 'gen'),
+ os.path.join(toplevel_build, 'gen')]
+
+ if not os.path.exists(toplevel_build):
+ os.makedirs(toplevel_build)
+ out = open(os.path.join(toplevel_build, 'eclipse-cdt-settings.xml'), 'w')
+
+ out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
+ out.write('<cdtprojectproperties>\n')
+
+ eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File',
+ 'GNU C++', 'GNU C', 'Assembly']
+ include_dirs = GetAllIncludeDirectories(target_list, target_dicts,
+ shared_intermediate_dirs, config_name)
+ WriteIncludePaths(out, eclipse_langs, include_dirs)
+ defines = GetAllDefines(target_list, target_dicts, data, config_name)
+ WriteMacros(out, eclipse_langs, defines)
+
+ out.write('</cdtprojectproperties>\n')
+ out.close()
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ """Generate an XML settings file that can be imported into a CDT project."""
+
+ if params['options'].generator_output:
+ raise NotImplementedError, "--generator_output not implemented for eclipse"
+
+ user_config = params.get('generator_flags', {}).get('config', None)
+ if user_config:
+ GenerateOutputForConfig(target_list, target_dicts, data, params,
+ user_config)
+ else:
+ config_names = target_dicts[target_list[0]]['configurations'].keys()
+ for config_name in config_names:
+ GenerateOutputForConfig(target_list, target_dicts, data, params,
+ config_name)
+
diff --git a/chromium/tools/gyp/pylib/gyp/generator/gypd.py b/chromium/tools/gyp/pylib/gyp/generator/gypd.py
new file mode 100644
index 00000000000..22ef57f847d
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/gypd.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""gypd output module
+
+This module produces gyp input as its output. Output files are given the
+.gypd extension to avoid overwriting the .gyp files that they are generated
+from. Internal references to .gyp files (such as those found in
+"dependencies" sections) are not adjusted to point to .gypd files instead;
+unlike other paths, which are relative to the .gyp or .gypd file, such paths
+are relative to the directory from which gyp was run to create the .gypd file.
+
+This generator module is intended to be a sample and a debugging aid, hence
+the "d" for "debug" in .gypd. It is useful to inspect the results of the
+various merges, expansions, and conditional evaluations performed by gyp
+and to see a representation of what would be fed to a generator module.
+
+It's not advisable to rename .gypd files produced by this module to .gyp,
+because they will have all merges, expansions, and evaluations already
+performed and the relevant constructs not present in the output; paths to
+dependencies may be wrong; and various sections that do not belong in .gyp
+files such as such as "included_files" and "*_excluded" will be present.
+Output will also be stripped of comments. This is not intended to be a
+general-purpose gyp pretty-printer; for that, you probably just want to
+run "pprint.pprint(eval(open('source.gyp').read()))", which will still strip
+comments but won't do all of the other things done to this module's output.
+
+The specific formatting of the output generated by this module is subject
+to change.
+"""
+
+
+import gyp.common
+import errno
+import os
+import pprint
+
+
+# These variables should just be spit back out as variable references.
+_generator_identity_variables = [
+ 'EXECUTABLE_PREFIX',
+ 'EXECUTABLE_SUFFIX',
+ 'INTERMEDIATE_DIR',
+ 'PRODUCT_DIR',
+ 'RULE_INPUT_ROOT',
+ 'RULE_INPUT_DIRNAME',
+ 'RULE_INPUT_EXT',
+ 'RULE_INPUT_NAME',
+ 'RULE_INPUT_PATH',
+ 'SHARED_INTERMEDIATE_DIR',
+]
+
+# gypd doesn't define a default value for OS like many other generator
+# modules. Specify "-D OS=whatever" on the command line to provide a value.
+generator_default_variables = {
+}
+
+# gypd supports multiple toolsets
+generator_supports_multiple_toolsets = True
+
+# TODO(mark): This always uses <, which isn't right. The input module should
+# notify the generator to tell it which phase it is operating in, and this
+# module should use < for the early phase and then switch to > for the late
+# phase. Bonus points for carrying @ back into the output too.
+for v in _generator_identity_variables:
+ generator_default_variables[v] = '<(%s)' % v
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ output_files = {}
+ for qualified_target in target_list:
+ [input_file, target] = \
+ gyp.common.ParseQualifiedTarget(qualified_target)[0:2]
+
+ if input_file[-4:] != '.gyp':
+ continue
+ input_file_stem = input_file[:-4]
+ output_file = input_file_stem + params['options'].suffix + '.gypd'
+
+ if not output_file in output_files:
+ output_files[output_file] = input_file
+
+ for output_file, input_file in output_files.iteritems():
+ output = open(output_file, 'w')
+ pprint.pprint(data[input_file], output)
+ output.close()
diff --git a/chromium/tools/gyp/pylib/gyp/generator/gypsh.py b/chromium/tools/gyp/pylib/gyp/generator/gypsh.py
new file mode 100644
index 00000000000..bd405f43a99
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/gypsh.py
@@ -0,0 +1,56 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""gypsh output module
+
+gypsh is a GYP shell. It's not really a generator per se. All it does is
+fire up an interactive Python session with a few local variables set to the
+variables passed to the generator. Like gypd, it's intended as a debugging
+aid, to facilitate the exploration of .gyp structures after being processed
+by the input module.
+
+The expected usage is "gyp -f gypsh -D OS=desired_os".
+"""
+
+
+import code
+import sys
+
+
+# All of this stuff about generator variables was lovingly ripped from gypd.py.
+# That module has a much better description of what's going on and why.
+_generator_identity_variables = [
+ 'EXECUTABLE_PREFIX',
+ 'EXECUTABLE_SUFFIX',
+ 'INTERMEDIATE_DIR',
+ 'PRODUCT_DIR',
+ 'RULE_INPUT_ROOT',
+ 'RULE_INPUT_DIRNAME',
+ 'RULE_INPUT_EXT',
+ 'RULE_INPUT_NAME',
+ 'RULE_INPUT_PATH',
+ 'SHARED_INTERMEDIATE_DIR',
+]
+
+generator_default_variables = {
+}
+
+for v in _generator_identity_variables:
+ generator_default_variables[v] = '<(%s)' % v
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ locals = {
+ 'target_list': target_list,
+ 'target_dicts': target_dicts,
+ 'data': data,
+ }
+
+ # Use a banner that looks like the stock Python one and like what
+ # code.interact uses by default, but tack on something to indicate what
+ # locals are available, and identify gypsh.
+ banner='Python %s on %s\nlocals.keys() = %s\ngypsh' % \
+ (sys.version, sys.platform, repr(sorted(locals.keys())))
+
+ code.interact(banner, local=locals)
diff --git a/chromium/tools/gyp/pylib/gyp/generator/make.py b/chromium/tools/gyp/pylib/gyp/generator/make.py
new file mode 100644
index 00000000000..c55c261f895
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/make.py
@@ -0,0 +1,2159 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Notes:
+#
+# This is all roughly based on the Makefile system used by the Linux
+# kernel, but is a non-recursive make -- we put the entire dependency
+# graph in front of make and let it figure it out.
+#
+# The code below generates a separate .mk file for each target, but
+# all are sourced by the top-level Makefile. This means that all
+# variables in .mk-files clobber one another. Be careful to use :=
+# where appropriate for immediate evaluation, and similarly to watch
+# that you're not relying on a variable value to last beween different
+# .mk files.
+#
+# TODOs:
+#
+# Global settings and utility functions are currently stuffed in the
+# toplevel Makefile. It may make sense to generate some .mk files on
+# the side to keep the the files readable.
+
+import os
+import re
+import sys
+import subprocess
+import gyp
+import gyp.common
+import gyp.xcode_emulation
+from gyp.common import GetEnvironFallback
+
+generator_default_variables = {
+ 'EXECUTABLE_PREFIX': '',
+ 'EXECUTABLE_SUFFIX': '',
+ 'STATIC_LIB_PREFIX': 'lib',
+ 'SHARED_LIB_PREFIX': 'lib',
+ 'STATIC_LIB_SUFFIX': '.a',
+ 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni',
+ 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen',
+ 'PRODUCT_DIR': '$(builddir)',
+ 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python.
+ 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', # This gets expanded by Python.
+ 'RULE_INPUT_PATH': '$(abspath $<)',
+ 'RULE_INPUT_EXT': '$(suffix $<)',
+ 'RULE_INPUT_NAME': '$(notdir $<)',
+ 'CONFIGURATION_NAME': '$(BUILDTYPE)',
+}
+
+# Make supports multiple toolsets
+generator_supports_multiple_toolsets = True
+
+# Request sorted dependencies in the order from dependents to dependencies.
+generator_wants_sorted_dependencies = False
+
+# Placates pylint.
+generator_additional_non_configuration_keys = []
+generator_additional_path_sections = []
+generator_extra_sources_for_rules = []
+
+
+def CalculateVariables(default_variables, params):
+ """Calculate additional variables for use in the build (called by gyp)."""
+ flavor = gyp.common.GetFlavor(params)
+ if flavor == 'mac':
+ default_variables.setdefault('OS', 'mac')
+ default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
+ default_variables.setdefault('SHARED_LIB_DIR',
+ generator_default_variables['PRODUCT_DIR'])
+ default_variables.setdefault('LIB_DIR',
+ generator_default_variables['PRODUCT_DIR'])
+
+ # Copy additional generator configuration data from Xcode, which is shared
+ # by the Mac Make generator.
+ import gyp.generator.xcode as xcode_generator
+ global generator_additional_non_configuration_keys
+ generator_additional_non_configuration_keys = getattr(xcode_generator,
+ 'generator_additional_non_configuration_keys', [])
+ global generator_additional_path_sections
+ generator_additional_path_sections = getattr(xcode_generator,
+ 'generator_additional_path_sections', [])
+ global generator_extra_sources_for_rules
+ generator_extra_sources_for_rules = getattr(xcode_generator,
+ 'generator_extra_sources_for_rules', [])
+ COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'})
+ else:
+ operating_system = flavor
+ if flavor == 'android':
+ operating_system = 'linux' # Keep this legacy behavior for now.
+ default_variables.setdefault('OS', operating_system)
+ default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
+ default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)')
+ default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)')
+
+
+def CalculateGeneratorInputInfo(params):
+ """Calculate the generator specific info that gets fed to input (called by
+ gyp)."""
+ generator_flags = params.get('generator_flags', {})
+ android_ndk_version = generator_flags.get('android_ndk_version', None)
+ # Android NDK requires a strict link order.
+ if android_ndk_version:
+ global generator_wants_sorted_dependencies
+ generator_wants_sorted_dependencies = True
+
+
+def ensure_directory_exists(path):
+ dir = os.path.dirname(path)
+ if dir and not os.path.exists(dir):
+ os.makedirs(dir)
+
+
+# The .d checking code below uses these functions:
+# wildcard, sort, foreach, shell, wordlist
+# wildcard can handle spaces, the rest can't.
+# Since I could find no way to make foreach work with spaces in filenames
+# correctly, the .d files have spaces replaced with another character. The .d
+# file for
+# Chromium\ Framework.framework/foo
+# is for example
+# out/Release/.deps/out/Release/Chromium?Framework.framework/foo
+# This is the replacement character.
+SPACE_REPLACEMENT = '?'
+
+
+LINK_COMMANDS_LINUX = """\
+quiet_cmd_alink = AR($(TOOLSET)) $@
+cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
+
+quiet_cmd_alink_thin = AR($(TOOLSET)) $@
+cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
+
+# Due to circular dependencies between libraries :(, we wrap the
+# special "figure out circular dependencies" flags around the entire
+# input list during linking.
+quiet_cmd_link = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
+
+# We support two kinds of shared objects (.so):
+# 1) shared_library, which is just bundling together many dependent libraries
+# into a link line.
+# 2) loadable_module, which is generating a module intended for dlopen().
+#
+# They differ only slightly:
+# In the former case, we want to package all dependent code into the .so.
+# In the latter case, we want to package just the API exposed by the
+# outermost module.
+# This means shared_library uses --whole-archive, while loadable_module doesn't.
+# (Note that --whole-archive is incompatible with the --start-group used in
+# normal linking.)
+
+# Other shared-object link notes:
+# - Set SONAME to the library filename so our binaries don't reference
+# the local, absolute paths used on the link command-line.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
+
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
+"""
+
+LINK_COMMANDS_MAC = """\
+quiet_cmd_alink = LIBTOOL-STATIC $@
+cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^)
+
+quiet_cmd_link = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
+
+# TODO(thakis): Find out and document the difference between shared_library and
+# loadable_module on mac.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
+
+# TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
+# -bundle -single_module here (for osmesa.so).
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
+"""
+
+LINK_COMMANDS_ANDROID = """\
+quiet_cmd_alink = AR($(TOOLSET)) $@
+cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
+
+quiet_cmd_alink_thin = AR($(TOOLSET)) $@
+cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
+
+# Due to circular dependencies between libraries :(, we wrap the
+# special "figure out circular dependencies" flags around the entire
+# input list during linking.
+quiet_cmd_link = LINK($(TOOLSET)) $@
+quiet_cmd_link_host = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
+cmd_link_host = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS)
+
+# Other shared-object link notes:
+# - Set SONAME to the library filename so our binaries don't reference
+# the local, absolute paths used on the link command-line.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
+
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
+quiet_cmd_solink_module_host = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module_host = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
+"""
+
+
+# Header of toplevel Makefile.
+# This should go into the build tree, but it's easier to keep it here for now.
+SHARED_HEADER = ("""\
+# We borrow heavily from the kernel build setup, though we are simpler since
+# we don't have Kconfig tweaking settings on us.
+
+# The implicit make rules have it looking for RCS files, among other things.
+# We instead explicitly write all the rules we care about.
+# It's even quicker (saves ~200ms) to pass -r on the command line.
+MAKEFLAGS=-r
+
+# The source directory tree.
+srcdir := %(srcdir)s
+abs_srcdir := $(abspath $(srcdir))
+
+# The name of the builddir.
+builddir_name ?= %(builddir)s
+
+# The V=1 flag on command line makes us verbosely print command lines.
+ifdef V
+ quiet=
+else
+ quiet=quiet_
+endif
+
+# Specify BUILDTYPE=Release on the command line for a release build.
+BUILDTYPE ?= %(default_configuration)s
+
+# Directory all our build output goes into.
+# Note that this must be two directories beneath src/ for unit tests to pass,
+# as they reach into the src/ directory for data with relative paths.
+builddir ?= $(builddir_name)/$(BUILDTYPE)
+abs_builddir := $(abspath $(builddir))
+depsdir := $(builddir)/.deps
+
+# Object output directory.
+obj := $(builddir)/obj
+abs_obj := $(abspath $(obj))
+
+# We build up a list of every single one of the targets so we can slurp in the
+# generated dependency rule Makefiles in one pass.
+all_deps :=
+
+%(make_global_settings)s
+
+# C++ apps need to be linked with g++.
+#
+# Note: flock is used to seralize linking. Linking is a memory-intensive
+# process so running parallel links can often lead to thrashing. To disable
+# the serialization, override LINK via an envrionment variable as follows:
+#
+# export LINK=g++
+#
+# This will allow make to invoke N linker processes as specified in -jN.
+LINK ?= %(flock)s $(builddir)/linker.lock $(CXX.target)
+
+CC.target ?= %(CC.target)s
+CFLAGS.target ?= $(CFLAGS)
+CXX.target ?= %(CXX.target)s
+CXXFLAGS.target ?= $(CXXFLAGS)
+LINK.target ?= %(LINK.target)s
+LDFLAGS.target ?= $(LDFLAGS)
+AR.target ?= $(AR)
+
+# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
+# to replicate this environment fallback in make as well.
+CC.host ?= %(CC.host)s
+CFLAGS.host ?=
+CXX.host ?= %(CXX.host)s
+CXXFLAGS.host ?=
+LINK.host ?= %(LINK.host)s
+LDFLAGS.host ?=
+AR.host ?= %(AR.host)s
+
+# Define a dir function that can handle spaces.
+# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
+# "leading spaces cannot appear in the text of the first argument as written.
+# These characters can be put into the argument value by variable substitution."
+empty :=
+space := $(empty) $(empty)
+
+# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
+replace_spaces = $(subst $(space),""" + SPACE_REPLACEMENT + """,$1)
+unreplace_spaces = $(subst """ + SPACE_REPLACEMENT + """,$(space),$1)
+dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
+
+# Flags to make gcc output dependency info. Note that you need to be
+# careful here to use the flags that ccache and distcc can understand.
+# We write to a dep file on the side first and then rename at the end
+# so we can't end up with a broken dep file.
+depfile = $(depsdir)/$(call replace_spaces,$@).d
+DEPFLAGS = -MMD -MF $(depfile).raw
+
+# We have to fixup the deps output in a few ways.
+# (1) the file output should mention the proper .o file.
+# ccache or distcc lose the path to the target, so we convert a rule of
+# the form:
+# foobar.o: DEP1 DEP2
+# into
+# path/to/foobar.o: DEP1 DEP2
+# (2) we want missing files not to cause us to fail to build.
+# We want to rewrite
+# foobar.o: DEP1 DEP2 \\
+# DEP3
+# to
+# DEP1:
+# DEP2:
+# DEP3:
+# so if the files are missing, they're just considered phony rules.
+# We have to do some pretty insane escaping to get those backslashes
+# and dollar signs past make, the shell, and sed at the same time.
+# Doesn't work with spaces, but that's fine: .d files have spaces in
+# their names replaced with other characters."""
+r"""
+define fixup_dep
+# The depfile may not exist if the input file didn't have any #includes.
+touch $(depfile).raw
+# Fixup path as in (1).
+sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
+# Add extra rules as in (2).
+# We remove slashes and replace spaces with new lines;
+# remove blank lines;
+# delete the first line and append a colon to the remaining lines.
+sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
+ grep -v '^$$' |\
+ sed -e 1d -e 's|$$|:|' \
+ >> $(depfile)
+rm $(depfile).raw
+endef
+"""
+"""
+# Command definitions:
+# - cmd_foo is the actual command to run;
+# - quiet_cmd_foo is the brief-output summary of the command.
+
+quiet_cmd_cc = CC($(TOOLSET)) $@
+cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
+
+quiet_cmd_cxx = CXX($(TOOLSET)) $@
+cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+%(extra_commands)s
+quiet_cmd_touch = TOUCH $@
+cmd_touch = touch $@
+
+quiet_cmd_copy = COPY $@
+# send stderr to /dev/null to ignore messages when linking directories.
+cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
+
+%(link_commands)s
+"""
+
+r"""
+# Define an escape_quotes function to escape single quotes.
+# This allows us to handle quotes properly as long as we always use
+# use single quotes and escape_quotes.
+escape_quotes = $(subst ','\'',$(1))
+# This comment is here just to include a ' to unconfuse syntax highlighting.
+# Define an escape_vars function to escape '$' variable syntax.
+# This allows us to read/write command lines with shell variables (e.g.
+# $LD_LIBRARY_PATH), without triggering make substitution.
+escape_vars = $(subst $$,$$$$,$(1))
+# Helper that expands to a shell command to echo a string exactly as it is in
+# make. This uses printf instead of echo because printf's behaviour with respect
+# to escape sequences is more portable than echo's across different shells
+# (e.g., dash, bash).
+exact_echo = printf '%%s\n' '$(call escape_quotes,$(1))'
+"""
+"""
+# Helper to compare the command we're about to run against the command
+# we logged the last time we ran the command. Produces an empty
+# string (false) when the commands match.
+# Tricky point: Make has no string-equality test function.
+# The kernel uses the following, but it seems like it would have false
+# positives, where one string reordered its arguments.
+# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \\
+# $(filter-out $(cmd_$@), $(cmd_$(1))))
+# We instead substitute each for the empty string into the other, and
+# say they're equal if both substitutions produce the empty string.
+# .d files contain """ + SPACE_REPLACEMENT + \
+ """ instead of spaces, take that into account.
+command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\\
+ $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
+
+# Helper that is non-empty when a prerequisite changes.
+# Normally make does this implicitly, but we force rules to always run
+# so we can check their command lines.
+# $? -- new prerequisites
+# $| -- order-only dependencies
+prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
+
+# Helper that executes all postbuilds until one fails.
+define do_postbuilds
+ @E=0;\\
+ for p in $(POSTBUILDS); do\\
+ eval $$p;\\
+ E=$$?;\\
+ if [ $$E -ne 0 ]; then\\
+ break;\\
+ fi;\\
+ done;\\
+ if [ $$E -ne 0 ]; then\\
+ rm -rf "$@";\\
+ exit $$E;\\
+ fi
+endef
+
+# do_cmd: run a command via the above cmd_foo names, if necessary.
+# Should always run for a given target to handle command-line changes.
+# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
+# Third argument, if non-zero, makes it do POSTBUILDS processing.
+# Note: We intentionally do NOT call dirx for depfile, since it contains """ + \
+ SPACE_REPLACEMENT + """ for
+# spaces already and dirx strips the """ + SPACE_REPLACEMENT + \
+ """ characters.
+define do_cmd
+$(if $(or $(command_changed),$(prereq_changed)),
+ @$(call exact_echo, $($(quiet)cmd_$(1)))
+ @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
+ $(if $(findstring flock,$(word %(flock_index)d,$(cmd_$1))),
+ @$(cmd_$(1))
+ @echo " $(quiet_cmd_$(1)): Finished",
+ @$(cmd_$(1))
+ )
+ @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
+ @$(if $(2),$(fixup_dep))
+ $(if $(and $(3), $(POSTBUILDS)),
+ $(call do_postbuilds)
+ )
+)
+endef
+
+# Declare the "%(default_target)s" target first so it is the default,
+# even though we don't have the deps yet.
+.PHONY: %(default_target)s
+%(default_target)s:
+
+# make looks for ways to re-generate included makefiles, but in our case, we
+# don't have a direct way. Explicitly telling make that it has nothing to do
+# for them makes it go faster.
+%%.d: ;
+
+# Use FORCE_DO_CMD to force a target to run. Should be coupled with
+# do_cmd.
+.PHONY: FORCE_DO_CMD
+FORCE_DO_CMD:
+
+""")
+
+SHARED_HEADER_MAC_COMMANDS = """
+quiet_cmd_objc = CXX($(TOOLSET)) $@
+cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+quiet_cmd_objcxx = CXX($(TOOLSET)) $@
+cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+# Commands for precompiled header files.
+quiet_cmd_pch_c = CXX($(TOOLSET)) $@
+cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
+cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+quiet_cmd_pch_m = CXX($(TOOLSET)) $@
+cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
+quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
+cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+# gyp-mac-tool is written next to the root Makefile by gyp.
+# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
+# already.
+quiet_cmd_mac_tool = MACTOOL $(4) $<
+cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
+
+quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
+cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
+
+quiet_cmd_infoplist = INFOPLIST $@
+cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
+"""
+
+SHARED_HEADER_SUN_COMMANDS = """
+# gyp-sun-tool is written next to the root Makefile by gyp.
+# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
+# already.
+quiet_cmd_sun_tool = SUNTOOL $(4) $<
+cmd_sun_tool = ./gyp-sun-tool $(4) $< "$@"
+"""
+
+
+def WriteRootHeaderSuffixRules(writer):
+ extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower)
+
+ writer.write('# Suffix rules, putting all outputs into $(obj).\n')
+ for ext in extensions:
+ writer.write('$(obj).$(TOOLSET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD\n' % ext)
+ writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
+
+ writer.write('\n# Try building from generated source, too.\n')
+ for ext in extensions:
+ writer.write(
+ '$(obj).$(TOOLSET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD\n' % ext)
+ writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
+ writer.write('\n')
+ for ext in extensions:
+ writer.write('$(obj).$(TOOLSET)/%%.o: $(obj)/%%%s FORCE_DO_CMD\n' % ext)
+ writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
+ writer.write('\n')
+
+
+SHARED_HEADER_SUFFIX_RULES_COMMENT1 = ("""\
+# Suffix rules, putting all outputs into $(obj).
+""")
+
+
+SHARED_HEADER_SUFFIX_RULES_COMMENT2 = ("""\
+# Try building from generated source, too.
+""")
+
+
+SHARED_FOOTER = """\
+# "all" is a concatenation of the "all" targets from all the included
+# sub-makefiles. This is just here to clarify.
+all:
+
+# Add in dependency-tracking rules. $(all_deps) is the list of every single
+# target in our tree. Only consider the ones with .d (dependency) info:
+d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
+ifneq ($(d_files),)
+ include $(d_files)
+endif
+"""
+
+header = """\
+# This file is generated by gyp; do not edit.
+
+"""
+
+# Maps every compilable file extension to the do_cmd that compiles it.
+COMPILABLE_EXTENSIONS = {
+ '.c': 'cc',
+ '.cc': 'cxx',
+ '.cpp': 'cxx',
+ '.cxx': 'cxx',
+ '.s': 'cc',
+ '.S': 'cc',
+}
+
+def Compilable(filename):
+ """Return true if the file is compilable (should be in OBJS)."""
+ for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS):
+ if res:
+ return True
+ return False
+
+
+def Linkable(filename):
+ """Return true if the file is linkable (should be on the link line)."""
+ return filename.endswith('.o')
+
+
+def Target(filename):
+ """Translate a compilable filename to its .o target."""
+ return os.path.splitext(filename)[0] + '.o'
+
+
+def EscapeShellArgument(s):
+ """Quotes an argument so that it will be interpreted literally by a POSIX
+ shell. Taken from
+ http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python
+ """
+ return "'" + s.replace("'", "'\\''") + "'"
+
+
+def EscapeMakeVariableExpansion(s):
+ """Make has its own variable expansion syntax using $. We must escape it for
+ string to be interpreted literally."""
+ return s.replace('$', '$$')
+
+
+def EscapeCppDefine(s):
+ """Escapes a CPP define so that it will reach the compiler unaltered."""
+ s = EscapeShellArgument(s)
+ s = EscapeMakeVariableExpansion(s)
+ # '#' characters must be escaped even embedded in a string, else Make will
+ # treat it as the start of a comment.
+ return s.replace('#', r'\#')
+
+
+def QuoteIfNecessary(string):
+ """TODO: Should this ideally be replaced with one or more of the above
+ functions?"""
+ if '"' in string:
+ string = '"' + string.replace('"', '\\"') + '"'
+ return string
+
+
+def StringToMakefileVariable(string):
+ """Convert a string to a value that is acceptable as a make variable name."""
+ return re.sub('[^a-zA-Z0-9_]', '_', string)
+
+
+srcdir_prefix = ''
+def Sourceify(path):
+ """Convert a path to its source directory form."""
+ if '$(' in path:
+ return path
+ if os.path.isabs(path):
+ return path
+ return srcdir_prefix + path
+
+
+def QuoteSpaces(s, quote=r'\ '):
+ return s.replace(' ', quote)
+
+
+# Map from qualified target to path to output.
+target_outputs = {}
+# Map from qualified target to any linkable output. A subset
+# of target_outputs. E.g. when mybinary depends on liba, we want to
+# include liba in the linker line; when otherbinary depends on
+# mybinary, we just want to build mybinary first.
+target_link_deps = {}
+
+
+class MakefileWriter:
+ """MakefileWriter packages up the writing of one target-specific foobar.mk.
+
+ Its only real entry point is Write(), and is mostly used for namespacing.
+ """
+
+ def __init__(self, generator_flags, flavor):
+ self.generator_flags = generator_flags
+ self.flavor = flavor
+
+ self.suffix_rules_srcdir = {}
+ self.suffix_rules_objdir1 = {}
+ self.suffix_rules_objdir2 = {}
+
+ # Generate suffix rules for all compilable extensions.
+ for ext in COMPILABLE_EXTENSIONS.keys():
+ # Suffix rules for source folder.
+ self.suffix_rules_srcdir.update({ext: ("""\
+$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD
+ @$(call do_cmd,%s,1)
+""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
+
+ # Suffix rules for generated source files.
+ self.suffix_rules_objdir1.update({ext: ("""\
+$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD
+ @$(call do_cmd,%s,1)
+""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
+ self.suffix_rules_objdir2.update({ext: ("""\
+$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
+ @$(call do_cmd,%s,1)
+""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
+
+
+ def Write(self, qualified_target, base_path, output_filename, spec, configs,
+ part_of_all):
+ """The main entry point: writes a .mk file for a single target.
+
+ Arguments:
+ qualified_target: target we're generating
+ base_path: path relative to source root we're building in, used to resolve
+ target-relative paths
+ output_filename: output .mk file name to write
+ spec, configs: gyp info
+ part_of_all: flag indicating this target is part of 'all'
+ """
+ ensure_directory_exists(output_filename)
+
+ self.fp = open(output_filename, 'w')
+
+ self.fp.write(header)
+
+ self.qualified_target = qualified_target
+ self.path = base_path
+ self.target = spec['target_name']
+ self.type = spec['type']
+ self.toolset = spec['toolset']
+
+ self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
+ if self.flavor == 'mac':
+ self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
+ else:
+ self.xcode_settings = None
+
+ deps, link_deps = self.ComputeDeps(spec)
+
+ # Some of the generation below can add extra output, sources, or
+ # link dependencies. All of the out params of the functions that
+ # follow use names like extra_foo.
+ extra_outputs = []
+ extra_sources = []
+ extra_link_deps = []
+ extra_mac_bundle_resources = []
+ mac_bundle_deps = []
+
+ if self.is_mac_bundle:
+ self.output = self.ComputeMacBundleOutput(spec)
+ self.output_binary = self.ComputeMacBundleBinaryOutput(spec)
+ else:
+ self.output = self.output_binary = self.ComputeOutput(spec)
+
+ self.is_standalone_static_library = bool(
+ spec.get('standalone_static_library', 0))
+ self._INSTALLABLE_TARGETS = ('executable', 'loadable_module',
+ 'shared_library')
+ if (self.is_standalone_static_library or
+ self.type in self._INSTALLABLE_TARGETS):
+ self.alias = os.path.basename(self.output)
+ install_path = self._InstallableTargetInstallPath()
+ else:
+ self.alias = self.output
+ install_path = self.output
+
+ self.WriteLn("TOOLSET := " + self.toolset)
+ self.WriteLn("TARGET := " + self.target)
+
+ # Actions must come first, since they can generate more OBJs for use below.
+ if 'actions' in spec:
+ self.WriteActions(spec['actions'], extra_sources, extra_outputs,
+ extra_mac_bundle_resources, part_of_all)
+
+ # Rules must be early like actions.
+ if 'rules' in spec:
+ self.WriteRules(spec['rules'], extra_sources, extra_outputs,
+ extra_mac_bundle_resources, part_of_all)
+
+ if 'copies' in spec:
+ self.WriteCopies(spec['copies'], extra_outputs, part_of_all)
+
+ # Bundle resources.
+ if self.is_mac_bundle:
+ all_mac_bundle_resources = (
+ spec.get('mac_bundle_resources', []) + extra_mac_bundle_resources)
+ self.WriteMacBundleResources(all_mac_bundle_resources, mac_bundle_deps)
+ self.WriteMacInfoPlist(mac_bundle_deps)
+
+ # Sources.
+ all_sources = spec.get('sources', []) + extra_sources
+ if all_sources:
+ self.WriteSources(
+ configs, deps, all_sources, extra_outputs,
+ extra_link_deps, part_of_all,
+ gyp.xcode_emulation.MacPrefixHeader(
+ self.xcode_settings, lambda p: Sourceify(self.Absolutify(p)),
+ self.Pchify))
+ sources = filter(Compilable, all_sources)
+ if sources:
+ self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT1)
+ extensions = set([os.path.splitext(s)[1] for s in sources])
+ for ext in extensions:
+ if ext in self.suffix_rules_srcdir:
+ self.WriteLn(self.suffix_rules_srcdir[ext])
+ self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT2)
+ for ext in extensions:
+ if ext in self.suffix_rules_objdir1:
+ self.WriteLn(self.suffix_rules_objdir1[ext])
+ for ext in extensions:
+ if ext in self.suffix_rules_objdir2:
+ self.WriteLn(self.suffix_rules_objdir2[ext])
+ self.WriteLn('# End of this set of suffix rules')
+
+ # Add dependency from bundle to bundle binary.
+ if self.is_mac_bundle:
+ mac_bundle_deps.append(self.output_binary)
+
+ self.WriteTarget(spec, configs, deps, extra_link_deps + link_deps,
+ mac_bundle_deps, extra_outputs, part_of_all)
+
+ # Update global list of target outputs, used in dependency tracking.
+ target_outputs[qualified_target] = install_path
+
+ # Update global list of link dependencies.
+ if self.type in ('static_library', 'shared_library'):
+ target_link_deps[qualified_target] = self.output_binary
+
+ # Currently any versions have the same effect, but in future the behavior
+ # could be different.
+ if self.generator_flags.get('android_ndk_version', None):
+ self.WriteAndroidNdkModuleRule(self.target, all_sources, link_deps)
+
+ self.fp.close()
+
+
+ def WriteSubMake(self, output_filename, makefile_path, targets, build_dir):
+ """Write a "sub-project" Makefile.
+
+ This is a small, wrapper Makefile that calls the top-level Makefile to build
+ the targets from a single gyp file (i.e. a sub-project).
+
+ Arguments:
+ output_filename: sub-project Makefile name to write
+ makefile_path: path to the top-level Makefile
+ targets: list of "all" targets for this sub-project
+ build_dir: build output directory, relative to the sub-project
+ """
+ ensure_directory_exists(output_filename)
+ self.fp = open(output_filename, 'w')
+ self.fp.write(header)
+ # For consistency with other builders, put sub-project build output in the
+ # sub-project dir (see test/subdirectory/gyptest-subdir-all.py).
+ self.WriteLn('export builddir_name ?= %s' %
+ os.path.join(os.path.dirname(output_filename), build_dir))
+ self.WriteLn('.PHONY: all')
+ self.WriteLn('all:')
+ if makefile_path:
+ makefile_path = ' -C ' + makefile_path
+ self.WriteLn('\t$(MAKE)%s %s' % (makefile_path, ' '.join(targets)))
+ self.fp.close()
+
+
+ def WriteActions(self, actions, extra_sources, extra_outputs,
+ extra_mac_bundle_resources, part_of_all):
+ """Write Makefile code for any 'actions' from the gyp input.
+
+ extra_sources: a list that will be filled in with newly generated source
+ files, if any
+ extra_outputs: a list that will be filled in with any outputs of these
+ actions (used to make other pieces dependent on these
+ actions)
+ part_of_all: flag indicating this target is part of 'all'
+ """
+ env = self.GetSortedXcodeEnv()
+ for action in actions:
+ name = StringToMakefileVariable('%s_%s' % (self.qualified_target,
+ action['action_name']))
+ self.WriteLn('### Rules for action "%s":' % action['action_name'])
+ inputs = action['inputs']
+ outputs = action['outputs']
+
+ # Build up a list of outputs.
+ # Collect the output dirs we'll need.
+ dirs = set()
+ for out in outputs:
+ dir = os.path.split(out)[0]
+ if dir:
+ dirs.add(dir)
+ if int(action.get('process_outputs_as_sources', False)):
+ extra_sources += outputs
+ if int(action.get('process_outputs_as_mac_bundle_resources', False)):
+ extra_mac_bundle_resources += outputs
+
+ # Write the actual command.
+ action_commands = action['action']
+ if self.flavor == 'mac':
+ action_commands = [gyp.xcode_emulation.ExpandEnvVars(command, env)
+ for command in action_commands]
+ command = gyp.common.EncodePOSIXShellList(action_commands)
+ if 'message' in action:
+ self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, action['message']))
+ else:
+ self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, name))
+ if len(dirs) > 0:
+ command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
+
+ cd_action = 'cd %s; ' % Sourceify(self.path or '.')
+
+ # command and cd_action get written to a toplevel variable called
+ # cmd_foo. Toplevel variables can't handle things that change per
+ # makefile like $(TARGET), so hardcode the target.
+ command = command.replace('$(TARGET)', self.target)
+ cd_action = cd_action.replace('$(TARGET)', self.target)
+
+ # Set LD_LIBRARY_PATH in case the action runs an executable from this
+ # build which links to shared libs from this build.
+ # actions run on the host, so they should in theory only use host
+ # libraries, but until everything is made cross-compile safe, also use
+ # target libraries.
+ # TODO(piman): when everything is cross-compile safe, remove lib.target
+ self.WriteLn('cmd_%s = LD_LIBRARY_PATH=$(builddir)/lib.host:'
+ '$(builddir)/lib.target:$$LD_LIBRARY_PATH; '
+ 'export LD_LIBRARY_PATH; '
+ '%s%s'
+ % (name, cd_action, command))
+ self.WriteLn()
+ outputs = map(self.Absolutify, outputs)
+ # The makefile rules are all relative to the top dir, but the gyp actions
+ # are defined relative to their containing dir. This replaces the obj
+ # variable for the action rule with an absolute version so that the output
+ # goes in the right place.
+ # Only write the 'obj' and 'builddir' rules for the "primary" output (:1);
+ # it's superfluous for the "extra outputs", and this avoids accidentally
+ # writing duplicate dummy rules for those outputs.
+ # Same for environment.
+ self.WriteLn("%s: obj := $(abs_obj)" % QuoteSpaces(outputs[0]))
+ self.WriteLn("%s: builddir := $(abs_builddir)" % QuoteSpaces(outputs[0]))
+ self.WriteSortedXcodeEnv(outputs[0], self.GetSortedXcodeEnv())
+
+ for input in inputs:
+ assert ' ' not in input, (
+ "Spaces in action input filenames not supported (%s)" % input)
+ for output in outputs:
+ assert ' ' not in output, (
+ "Spaces in action output filenames not supported (%s)" % output)
+
+ # See the comment in WriteCopies about expanding env vars.
+ outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs]
+ inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs]
+
+ self.WriteDoCmd(outputs, map(Sourceify, map(self.Absolutify, inputs)),
+ part_of_all=part_of_all, command=name)
+
+ # Stuff the outputs in a variable so we can refer to them later.
+ outputs_variable = 'action_%s_outputs' % name
+ self.WriteLn('%s := %s' % (outputs_variable, ' '.join(outputs)))
+ extra_outputs.append('$(%s)' % outputs_variable)
+ self.WriteLn()
+
+ self.WriteLn()
+
+
+ def WriteRules(self, rules, extra_sources, extra_outputs,
+ extra_mac_bundle_resources, part_of_all):
+ """Write Makefile code for any 'rules' from the gyp input.
+
+ extra_sources: a list that will be filled in with newly generated source
+ files, if any
+ extra_outputs: a list that will be filled in with any outputs of these
+ rules (used to make other pieces dependent on these rules)
+ part_of_all: flag indicating this target is part of 'all'
+ """
+ env = self.GetSortedXcodeEnv()
+ for rule in rules:
+ name = StringToMakefileVariable('%s_%s' % (self.qualified_target,
+ rule['rule_name']))
+ count = 0
+ self.WriteLn('### Generated for rule %s:' % name)
+
+ all_outputs = []
+
+ for rule_source in rule.get('rule_sources', []):
+ dirs = set()
+ (rule_source_dirname, rule_source_basename) = os.path.split(rule_source)
+ (rule_source_root, rule_source_ext) = \
+ os.path.splitext(rule_source_basename)
+
+ outputs = [self.ExpandInputRoot(out, rule_source_root,
+ rule_source_dirname)
+ for out in rule['outputs']]
+
+ for out in outputs:
+ dir = os.path.dirname(out)
+ if dir:
+ dirs.add(dir)
+ if int(rule.get('process_outputs_as_sources', False)):
+ extra_sources += outputs
+ if int(rule.get('process_outputs_as_mac_bundle_resources', False)):
+ extra_mac_bundle_resources += outputs
+ inputs = map(Sourceify, map(self.Absolutify, [rule_source] +
+ rule.get('inputs', [])))
+ actions = ['$(call do_cmd,%s_%d)' % (name, count)]
+
+ if name == 'resources_grit':
+ # HACK: This is ugly. Grit intentionally doesn't touch the
+ # timestamp of its output file when the file doesn't change,
+ # which is fine in hash-based dependency systems like scons
+ # and forge, but not kosher in the make world. After some
+ # discussion, hacking around it here seems like the least
+ # amount of pain.
+ actions += ['@touch --no-create $@']
+
+ # See the comment in WriteCopies about expanding env vars.
+ outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs]
+ inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs]
+
+ outputs = map(self.Absolutify, outputs)
+ all_outputs += outputs
+ # Only write the 'obj' and 'builddir' rules for the "primary" output
+ # (:1); it's superfluous for the "extra outputs", and this avoids
+ # accidentally writing duplicate dummy rules for those outputs.
+ self.WriteLn('%s: obj := $(abs_obj)' % outputs[0])
+ self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0])
+ self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions)
+ # Spaces in rule filenames are not supported, but rule variables have
+ # spaces in them (e.g. RULE_INPUT_PATH expands to '$(abspath $<)').
+ # The spaces within the variables are valid, so remove the variables
+ # before checking.
+ variables_with_spaces = re.compile(r'\$\([^ ]* \$<\)')
+ for output in outputs:
+ output = re.sub(variables_with_spaces, '', output)
+ assert ' ' not in output, (
+ "Spaces in rule filenames not yet supported (%s)" % output)
+ self.WriteLn('all_deps += %s' % ' '.join(outputs))
+
+ action = [self.ExpandInputRoot(ac, rule_source_root,
+ rule_source_dirname)
+ for ac in rule['action']]
+ mkdirs = ''
+ if len(dirs) > 0:
+ mkdirs = 'mkdir -p %s; ' % ' '.join(dirs)
+ cd_action = 'cd %s; ' % Sourceify(self.path or '.')
+
+ # action, cd_action, and mkdirs get written to a toplevel variable
+ # called cmd_foo. Toplevel variables can't handle things that change
+ # per makefile like $(TARGET), so hardcode the target.
+ if self.flavor == 'mac':
+ action = [gyp.xcode_emulation.ExpandEnvVars(command, env)
+ for command in action]
+ action = gyp.common.EncodePOSIXShellList(action)
+ action = action.replace('$(TARGET)', self.target)
+ cd_action = cd_action.replace('$(TARGET)', self.target)
+ mkdirs = mkdirs.replace('$(TARGET)', self.target)
+
+ # Set LD_LIBRARY_PATH in case the rule runs an executable from this
+ # build which links to shared libs from this build.
+ # rules run on the host, so they should in theory only use host
+ # libraries, but until everything is made cross-compile safe, also use
+ # target libraries.
+ # TODO(piman): when everything is cross-compile safe, remove lib.target
+ self.WriteLn(
+ "cmd_%(name)s_%(count)d = LD_LIBRARY_PATH="
+ "$(builddir)/lib.host:$(builddir)/lib.target:$$LD_LIBRARY_PATH; "
+ "export LD_LIBRARY_PATH; "
+ "%(cd_action)s%(mkdirs)s%(action)s" % {
+ 'action': action,
+ 'cd_action': cd_action,
+ 'count': count,
+ 'mkdirs': mkdirs,
+ 'name': name,
+ })
+ self.WriteLn(
+ 'quiet_cmd_%(name)s_%(count)d = RULE %(name)s_%(count)d $@' % {
+ 'count': count,
+ 'name': name,
+ })
+ self.WriteLn()
+ count += 1
+
+ outputs_variable = 'rule_%s_outputs' % name
+ self.WriteList(all_outputs, outputs_variable)
+ extra_outputs.append('$(%s)' % outputs_variable)
+
+ self.WriteLn('### Finished generating for rule: %s' % name)
+ self.WriteLn()
+ self.WriteLn('### Finished generating for all rules')
+ self.WriteLn('')
+
+
+ def WriteCopies(self, copies, extra_outputs, part_of_all):
+ """Write Makefile code for any 'copies' from the gyp input.
+
+ extra_outputs: a list that will be filled in with any outputs of this action
+ (used to make other pieces dependent on this action)
+ part_of_all: flag indicating this target is part of 'all'
+ """
+ self.WriteLn('### Generated for copy rule.')
+
+ variable = StringToMakefileVariable(self.qualified_target + '_copies')
+ outputs = []
+ for copy in copies:
+ for path in copy['files']:
+ # Absolutify() may call normpath, and will strip trailing slashes.
+ path = Sourceify(self.Absolutify(path))
+ filename = os.path.split(path)[1]
+ output = Sourceify(self.Absolutify(os.path.join(copy['destination'],
+ filename)))
+
+ # If the output path has variables in it, which happens in practice for
+ # 'copies', writing the environment as target-local doesn't work,
+ # because the variables are already needed for the target name.
+ # Copying the environment variables into global make variables doesn't
+ # work either, because then the .d files will potentially contain spaces
+ # after variable expansion, and .d file handling cannot handle spaces.
+ # As a workaround, manually expand variables at gyp time. Since 'copies'
+ # can't run scripts, there's no need to write the env then.
+ # WriteDoCmd() will escape spaces for .d files.
+ env = self.GetSortedXcodeEnv()
+ output = gyp.xcode_emulation.ExpandEnvVars(output, env)
+ path = gyp.xcode_emulation.ExpandEnvVars(path, env)
+ self.WriteDoCmd([output], [path], 'copy', part_of_all)
+ outputs.append(output)
+ self.WriteLn('%s = %s' % (variable, ' '.join(map(QuoteSpaces, outputs))))
+ extra_outputs.append('$(%s)' % variable)
+ self.WriteLn()
+
+
+ def WriteMacBundleResources(self, resources, bundle_deps):
+ """Writes Makefile code for 'mac_bundle_resources'."""
+ self.WriteLn('### Generated for mac_bundle_resources')
+
+ for output, res in gyp.xcode_emulation.GetMacBundleResources(
+ generator_default_variables['PRODUCT_DIR'], self.xcode_settings,
+ map(Sourceify, map(self.Absolutify, resources))):
+ self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource',
+ part_of_all=True)
+ bundle_deps.append(output)
+
+
+ def WriteMacInfoPlist(self, bundle_deps):
+ """Write Makefile code for bundle Info.plist files."""
+ info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
+ generator_default_variables['PRODUCT_DIR'], self.xcode_settings,
+ lambda p: Sourceify(self.Absolutify(p)))
+ if not info_plist:
+ return
+ if defines:
+ # Create an intermediate file to store preprocessed results.
+ intermediate_plist = ('$(obj).$(TOOLSET)/$(TARGET)/' +
+ os.path.basename(info_plist))
+ self.WriteList(defines, intermediate_plist + ': INFOPLIST_DEFINES', '-D',
+ quoter=EscapeCppDefine)
+ self.WriteMakeRule([intermediate_plist], [info_plist],
+ ['$(call do_cmd,infoplist)',
+ # "Convert" the plist so that any weird whitespace changes from the
+ # preprocessor do not affect the XML parser in mac_tool.
+ '@plutil -convert xml1 $@ $@'])
+ info_plist = intermediate_plist
+ # plists can contain envvars and substitute them into the file.
+ self.WriteSortedXcodeEnv(
+ out, self.GetSortedXcodeEnv(additional_settings=extra_env))
+ self.WriteDoCmd([out], [info_plist], 'mac_tool,,,copy-info-plist',
+ part_of_all=True)
+ bundle_deps.append(out)
+
+
+ def WriteSources(self, configs, deps, sources,
+ extra_outputs, extra_link_deps,
+ part_of_all, precompiled_header):
+ """Write Makefile code for any 'sources' from the gyp input.
+ These are source files necessary to build the current target.
+
+ configs, deps, sources: input from gyp.
+ extra_outputs: a list of extra outputs this action should be dependent on;
+ used to serialize action/rules before compilation
+ extra_link_deps: a list that will be filled in with any outputs of
+ compilation (to be used in link lines)
+ part_of_all: flag indicating this target is part of 'all'
+ """
+
+ # Write configuration-specific variables for CFLAGS, etc.
+ for configname in sorted(configs.keys()):
+ config = configs[configname]
+ self.WriteList(config.get('defines'), 'DEFS_%s' % configname, prefix='-D',
+ quoter=EscapeCppDefine)
+
+ if self.flavor == 'mac':
+ cflags = self.xcode_settings.GetCflags(configname)
+ cflags_c = self.xcode_settings.GetCflagsC(configname)
+ cflags_cc = self.xcode_settings.GetCflagsCC(configname)
+ cflags_objc = self.xcode_settings.GetCflagsObjC(configname)
+ cflags_objcc = self.xcode_settings.GetCflagsObjCC(configname)
+ else:
+ cflags = config.get('cflags')
+ cflags_c = config.get('cflags_c')
+ cflags_cc = config.get('cflags_cc')
+
+ self.WriteLn("# Flags passed to all source files.");
+ self.WriteList(cflags, 'CFLAGS_%s' % configname)
+ self.WriteLn("# Flags passed to only C files.");
+ self.WriteList(cflags_c, 'CFLAGS_C_%s' % configname)
+ self.WriteLn("# Flags passed to only C++ files.");
+ self.WriteList(cflags_cc, 'CFLAGS_CC_%s' % configname)
+ if self.flavor == 'mac':
+ self.WriteLn("# Flags passed to only ObjC files.");
+ self.WriteList(cflags_objc, 'CFLAGS_OBJC_%s' % configname)
+ self.WriteLn("# Flags passed to only ObjC++ files.");
+ self.WriteList(cflags_objcc, 'CFLAGS_OBJCC_%s' % configname)
+ includes = config.get('include_dirs')
+ if includes:
+ includes = map(Sourceify, map(self.Absolutify, includes))
+ self.WriteList(includes, 'INCS_%s' % configname, prefix='-I')
+
+ compilable = filter(Compilable, sources)
+ objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable)))
+ self.WriteList(objs, 'OBJS')
+
+ for obj in objs:
+ assert ' ' not in obj, (
+ "Spaces in object filenames not supported (%s)" % obj)
+ self.WriteLn('# Add to the list of files we specially track '
+ 'dependencies for.')
+ self.WriteLn('all_deps += $(OBJS)')
+ self.WriteLn()
+
+ # Make sure our dependencies are built first.
+ if deps:
+ self.WriteMakeRule(['$(OBJS)'], deps,
+ comment = 'Make sure our dependencies are built '
+ 'before any of us.',
+ order_only = True)
+
+ # Make sure the actions and rules run first.
+ # If they generate any extra headers etc., the per-.o file dep tracking
+ # will catch the proper rebuilds, so order only is still ok here.
+ if extra_outputs:
+ self.WriteMakeRule(['$(OBJS)'], extra_outputs,
+ comment = 'Make sure our actions/rules run '
+ 'before any of us.',
+ order_only = True)
+
+ pchdeps = precompiled_header.GetObjDependencies(compilable, objs )
+ if pchdeps:
+ self.WriteLn('# Dependencies from obj files to their precompiled headers')
+ for source, obj, gch in pchdeps:
+ self.WriteLn('%s: %s' % (obj, gch))
+ self.WriteLn('# End precompiled header dependencies')
+
+ if objs:
+ extra_link_deps.append('$(OBJS)')
+ self.WriteLn("""\
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.""")
+ self.WriteLn("$(OBJS): TOOLSET := $(TOOLSET)")
+ self.WriteLn("$(OBJS): GYP_CFLAGS := "
+ "$(DEFS_$(BUILDTYPE)) "
+ "$(INCS_$(BUILDTYPE)) "
+ "%s " % precompiled_header.GetInclude('c') +
+ "$(CFLAGS_$(BUILDTYPE)) "
+ "$(CFLAGS_C_$(BUILDTYPE))")
+ self.WriteLn("$(OBJS): GYP_CXXFLAGS := "
+ "$(DEFS_$(BUILDTYPE)) "
+ "$(INCS_$(BUILDTYPE)) "
+ "%s " % precompiled_header.GetInclude('cc') +
+ "$(CFLAGS_$(BUILDTYPE)) "
+ "$(CFLAGS_CC_$(BUILDTYPE))")
+ if self.flavor == 'mac':
+ self.WriteLn("$(OBJS): GYP_OBJCFLAGS := "
+ "$(DEFS_$(BUILDTYPE)) "
+ "$(INCS_$(BUILDTYPE)) "
+ "%s " % precompiled_header.GetInclude('m') +
+ "$(CFLAGS_$(BUILDTYPE)) "
+ "$(CFLAGS_C_$(BUILDTYPE)) "
+ "$(CFLAGS_OBJC_$(BUILDTYPE))")
+ self.WriteLn("$(OBJS): GYP_OBJCXXFLAGS := "
+ "$(DEFS_$(BUILDTYPE)) "
+ "$(INCS_$(BUILDTYPE)) "
+ "%s " % precompiled_header.GetInclude('mm') +
+ "$(CFLAGS_$(BUILDTYPE)) "
+ "$(CFLAGS_CC_$(BUILDTYPE)) "
+ "$(CFLAGS_OBJCC_$(BUILDTYPE))")
+
+ self.WritePchTargets(precompiled_header.GetPchBuildCommands())
+
+ # If there are any object files in our input file list, link them into our
+ # output.
+ extra_link_deps += filter(Linkable, sources)
+
+ self.WriteLn()
+
+ def WritePchTargets(self, pch_commands):
+ """Writes make rules to compile prefix headers."""
+ if not pch_commands:
+ return
+
+ for gch, lang_flag, lang, input in pch_commands:
+ extra_flags = {
+ 'c': '$(CFLAGS_C_$(BUILDTYPE))',
+ 'cc': '$(CFLAGS_CC_$(BUILDTYPE))',
+ 'm': '$(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))',
+ 'mm': '$(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))',
+ }[lang]
+ var_name = {
+ 'c': 'GYP_PCH_CFLAGS',
+ 'cc': 'GYP_PCH_CXXFLAGS',
+ 'm': 'GYP_PCH_OBJCFLAGS',
+ 'mm': 'GYP_PCH_OBJCXXFLAGS',
+ }[lang]
+ self.WriteLn("%s: %s := %s " % (gch, var_name, lang_flag) +
+ "$(DEFS_$(BUILDTYPE)) "
+ "$(INCS_$(BUILDTYPE)) "
+ "$(CFLAGS_$(BUILDTYPE)) " +
+ extra_flags)
+
+ self.WriteLn('%s: %s FORCE_DO_CMD' % (gch, input))
+ self.WriteLn('\t@$(call do_cmd,pch_%s,1)' % lang)
+ self.WriteLn('')
+ assert ' ' not in gch, (
+ "Spaces in gch filenames not supported (%s)" % gch)
+ self.WriteLn('all_deps += %s' % gch)
+ self.WriteLn('')
+
+
+ def ComputeOutputBasename(self, spec):
+ """Return the 'output basename' of a gyp spec.
+
+ E.g., the loadable module 'foobar' in directory 'baz' will produce
+ 'libfoobar.so'
+ """
+ assert not self.is_mac_bundle
+
+ if self.flavor == 'mac' and self.type in (
+ 'static_library', 'executable', 'shared_library', 'loadable_module'):
+ return self.xcode_settings.GetExecutablePath()
+
+ target = spec['target_name']
+ target_prefix = ''
+ target_ext = ''
+ if self.type == 'static_library':
+ if target[:3] == 'lib':
+ target = target[3:]
+ target_prefix = 'lib'
+ target_ext = '.a'
+ elif self.type in ('loadable_module', 'shared_library'):
+ if target[:3] == 'lib':
+ target = target[3:]
+ target_prefix = 'lib'
+ target_ext = '.so'
+ elif self.type == 'none':
+ target = '%s.stamp' % target
+ elif self.type != 'executable':
+ print ("ERROR: What output file should be generated?",
+ "type", self.type, "target", target)
+
+ target_prefix = spec.get('product_prefix', target_prefix)
+ target = spec.get('product_name', target)
+ product_ext = spec.get('product_extension')
+ if product_ext:
+ target_ext = '.' + product_ext
+
+ return target_prefix + target + target_ext
+
+
+ def _InstallImmediately(self):
+ return self.toolset == 'target' and self.flavor == 'mac' and self.type in (
+ 'static_library', 'executable', 'shared_library', 'loadable_module')
+
+
+ def ComputeOutput(self, spec):
+ """Return the 'output' (full output path) of a gyp spec.
+
+ E.g., the loadable module 'foobar' in directory 'baz' will produce
+ '$(obj)/baz/libfoobar.so'
+ """
+ assert not self.is_mac_bundle
+
+ path = os.path.join('$(obj).' + self.toolset, self.path)
+ if self.type == 'executable' or self._InstallImmediately():
+ path = '$(builddir)'
+ path = spec.get('product_dir', path)
+ return os.path.join(path, self.ComputeOutputBasename(spec))
+
+
+ def ComputeMacBundleOutput(self, spec):
+ """Return the 'output' (full output path) to a bundle output directory."""
+ assert self.is_mac_bundle
+ path = generator_default_variables['PRODUCT_DIR']
+ return os.path.join(path, self.xcode_settings.GetWrapperName())
+
+
+ def ComputeMacBundleBinaryOutput(self, spec):
+ """Return the 'output' (full output path) to the binary in a bundle."""
+ path = generator_default_variables['PRODUCT_DIR']
+ return os.path.join(path, self.xcode_settings.GetExecutablePath())
+
+
+ def ComputeDeps(self, spec):
+ """Compute the dependencies of a gyp spec.
+
+ Returns a tuple (deps, link_deps), where each is a list of
+ filenames that will need to be put in front of make for either
+ building (deps) or linking (link_deps).
+ """
+ deps = []
+ link_deps = []
+ if 'dependencies' in spec:
+ deps.extend([target_outputs[dep] for dep in spec['dependencies']
+ if target_outputs[dep]])
+ for dep in spec['dependencies']:
+ if dep in target_link_deps:
+ link_deps.append(target_link_deps[dep])
+ deps.extend(link_deps)
+ # TODO: It seems we need to transitively link in libraries (e.g. -lfoo)?
+ # This hack makes it work:
+ # link_deps.extend(spec.get('libraries', []))
+ return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps))
+
+
+ def WriteDependencyOnExtraOutputs(self, target, extra_outputs):
+ self.WriteMakeRule([self.output_binary], extra_outputs,
+ comment = 'Build our special outputs first.',
+ order_only = True)
+
+
+ def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps,
+ extra_outputs, part_of_all):
+ """Write Makefile code to produce the final target of the gyp spec.
+
+ spec, configs: input from gyp.
+ deps, link_deps: dependency lists; see ComputeDeps()
+ extra_outputs: any extra outputs that our target should depend on
+ part_of_all: flag indicating this target is part of 'all'
+ """
+
+ self.WriteLn('### Rules for final target.')
+
+ if extra_outputs:
+ self.WriteDependencyOnExtraOutputs(self.output_binary, extra_outputs)
+ self.WriteMakeRule(extra_outputs, deps,
+ comment=('Preserve order dependency of '
+ 'special output on deps.'),
+ order_only = True)
+
+ target_postbuilds = {}
+ if self.type != 'none':
+ for configname in sorted(configs.keys()):
+ config = configs[configname]
+ if self.flavor == 'mac':
+ ldflags = self.xcode_settings.GetLdflags(configname,
+ generator_default_variables['PRODUCT_DIR'],
+ lambda p: Sourceify(self.Absolutify(p)))
+
+ # TARGET_POSTBUILDS_$(BUILDTYPE) is added to postbuilds later on.
+ gyp_to_build = gyp.common.InvertRelativePath(self.path)
+ target_postbuild = self.xcode_settings.GetTargetPostbuilds(
+ configname,
+ QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build,
+ self.output))),
+ QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build,
+ self.output_binary))))
+ if target_postbuild:
+ target_postbuilds[configname] = target_postbuild
+ else:
+ ldflags = config.get('ldflags', [])
+ # Compute an rpath for this output if needed.
+ if any(dep.endswith('.so') or '.so.' in dep for dep in deps):
+ # We want to get the literal string "$ORIGIN" into the link command,
+ # so we need lots of escaping.
+ ldflags.append(r'-Wl,-rpath=\$$ORIGIN/lib.%s/' % self.toolset)
+ ldflags.append(r'-Wl,-rpath-link=\$(builddir)/lib.%s/' %
+ self.toolset)
+ library_dirs = config.get('library_dirs', [])
+ ldflags += [('-L%s' % library_dir) for library_dir in library_dirs]
+ self.WriteList(ldflags, 'LDFLAGS_%s' % configname)
+ if self.flavor == 'mac':
+ self.WriteList(self.xcode_settings.GetLibtoolflags(configname),
+ 'LIBTOOLFLAGS_%s' % configname)
+ libraries = spec.get('libraries')
+ if libraries:
+ # Remove duplicate entries
+ libraries = gyp.common.uniquer(libraries)
+ if self.flavor == 'mac':
+ libraries = self.xcode_settings.AdjustLibraries(libraries)
+ self.WriteList(libraries, 'LIBS')
+ self.WriteLn('%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' %
+ QuoteSpaces(self.output_binary))
+ self.WriteLn('%s: LIBS := $(LIBS)' % QuoteSpaces(self.output_binary))
+
+ if self.flavor == 'mac':
+ self.WriteLn('%s: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))' %
+ QuoteSpaces(self.output_binary))
+
+ # Postbuild actions. Like actions, but implicitly depend on the target's
+ # output.
+ postbuilds = []
+ if self.flavor == 'mac':
+ if target_postbuilds:
+ postbuilds.append('$(TARGET_POSTBUILDS_$(BUILDTYPE))')
+ postbuilds.extend(
+ gyp.xcode_emulation.GetSpecPostbuildCommands(spec))
+
+ if postbuilds:
+ # Envvars may be referenced by TARGET_POSTBUILDS_$(BUILDTYPE),
+ # so we must output its definition first, since we declare variables
+ # using ":=".
+ self.WriteSortedXcodeEnv(self.output, self.GetSortedXcodePostbuildEnv())
+
+ for configname in target_postbuilds:
+ self.WriteLn('%s: TARGET_POSTBUILDS_%s := %s' %
+ (QuoteSpaces(self.output),
+ configname,
+ gyp.common.EncodePOSIXShellList(target_postbuilds[configname])))
+
+ # Postbuilds expect to be run in the gyp file's directory, so insert an
+ # implicit postbuild to cd to there.
+ postbuilds.insert(0, gyp.common.EncodePOSIXShellList(['cd', self.path]))
+ for i in xrange(len(postbuilds)):
+ if not postbuilds[i].startswith('$'):
+ postbuilds[i] = EscapeShellArgument(postbuilds[i])
+ self.WriteLn('%s: builddir := $(abs_builddir)' % QuoteSpaces(self.output))
+ self.WriteLn('%s: POSTBUILDS := %s' % (
+ QuoteSpaces(self.output), ' '.join(postbuilds)))
+
+ # A bundle directory depends on its dependencies such as bundle resources
+ # and bundle binary. When all dependencies have been built, the bundle
+ # needs to be packaged.
+ if self.is_mac_bundle:
+ # If the framework doesn't contain a binary, then nothing depends
+ # on the actions -- make the framework depend on them directly too.
+ self.WriteDependencyOnExtraOutputs(self.output, extra_outputs)
+
+ # Bundle dependencies. Note that the code below adds actions to this
+ # target, so if you move these two lines, move the lines below as well.
+ self.WriteList(map(QuoteSpaces, bundle_deps), 'BUNDLE_DEPS')
+ self.WriteLn('%s: $(BUNDLE_DEPS)' % QuoteSpaces(self.output))
+
+ # After the framework is built, package it. Needs to happen before
+ # postbuilds, since postbuilds depend on this.
+ if self.type in ('shared_library', 'loadable_module'):
+ self.WriteLn('\t@$(call do_cmd,mac_package_framework,,,%s)' %
+ self.xcode_settings.GetFrameworkVersion())
+
+ # Bundle postbuilds can depend on the whole bundle, so run them after
+ # the bundle is packaged, not already after the bundle binary is done.
+ if postbuilds:
+ self.WriteLn('\t@$(call do_postbuilds)')
+ postbuilds = [] # Don't write postbuilds for target's output.
+
+ # Needed by test/mac/gyptest-rebuild.py.
+ self.WriteLn('\t@true # No-op, used by tests')
+
+ # Since this target depends on binary and resources which are in
+ # nested subfolders, the framework directory will be older than
+ # its dependencies usually. To prevent this rule from executing
+ # on every build (expensive, especially with postbuilds), expliclity
+ # update the time on the framework directory.
+ self.WriteLn('\t@touch -c %s' % QuoteSpaces(self.output))
+
+ if postbuilds:
+ assert not self.is_mac_bundle, ('Postbuilds for bundles should be done '
+ 'on the bundle, not the binary (target \'%s\')' % self.target)
+ assert 'product_dir' not in spec, ('Postbuilds do not work with '
+ 'custom product_dir')
+
+ if self.type == 'executable':
+ self.WriteLn('%s: LD_INPUTS := %s' % (
+ QuoteSpaces(self.output_binary),
+ ' '.join(map(QuoteSpaces, link_deps))))
+ if self.toolset == 'host' and self.flavor == 'android':
+ self.WriteDoCmd([self.output_binary], link_deps, 'link_host',
+ part_of_all, postbuilds=postbuilds)
+ else:
+ self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all,
+ postbuilds=postbuilds)
+
+ elif self.type == 'static_library':
+ for link_dep in link_deps:
+ assert ' ' not in link_dep, (
+ "Spaces in alink input filenames not supported (%s)" % link_dep)
+ if (self.flavor not in ('mac', 'openbsd', 'win') and not
+ self.is_standalone_static_library):
+ self.WriteDoCmd([self.output_binary], link_deps, 'alink_thin',
+ part_of_all, postbuilds=postbuilds)
+ else:
+ self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all,
+ postbuilds=postbuilds)
+ elif self.type == 'shared_library':
+ self.WriteLn('%s: LD_INPUTS := %s' % (
+ QuoteSpaces(self.output_binary),
+ ' '.join(map(QuoteSpaces, link_deps))))
+ self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all,
+ postbuilds=postbuilds)
+ elif self.type == 'loadable_module':
+ for link_dep in link_deps:
+ assert ' ' not in link_dep, (
+ "Spaces in module input filenames not supported (%s)" % link_dep)
+ if self.toolset == 'host' and self.flavor == 'android':
+ self.WriteDoCmd([self.output_binary], link_deps, 'solink_module_host',
+ part_of_all, postbuilds=postbuilds)
+ else:
+ self.WriteDoCmd(
+ [self.output_binary], link_deps, 'solink_module', part_of_all,
+ postbuilds=postbuilds)
+ elif self.type == 'none':
+ # Write a stamp line.
+ self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all,
+ postbuilds=postbuilds)
+ else:
+ print "WARNING: no output for", self.type, target
+
+ # Add an alias for each target (if there are any outputs).
+ # Installable target aliases are created below.
+ if ((self.output and self.output != self.target) and
+ (self.type not in self._INSTALLABLE_TARGETS)):
+ self.WriteMakeRule([self.target], [self.output],
+ comment='Add target alias', phony = True)
+ if part_of_all:
+ self.WriteMakeRule(['all'], [self.target],
+ comment = 'Add target alias to "all" target.',
+ phony = True)
+
+ # Add special-case rules for our installable targets.
+ # 1) They need to install to the build dir or "product" dir.
+ # 2) They get shortcuts for building (e.g. "make chrome").
+ # 3) They are part of "make all".
+ if (self.type in self._INSTALLABLE_TARGETS or
+ self.is_standalone_static_library):
+ if self.type == 'shared_library':
+ file_desc = 'shared library'
+ elif self.type == 'static_library':
+ file_desc = 'static library'
+ else:
+ file_desc = 'executable'
+ install_path = self._InstallableTargetInstallPath()
+ installable_deps = [self.output]
+ if (self.flavor == 'mac' and not 'product_dir' in spec and
+ self.toolset == 'target'):
+ # On mac, products are created in install_path immediately.
+ assert install_path == self.output, '%s != %s' % (
+ install_path, self.output)
+
+ # Point the target alias to the final binary output.
+ self.WriteMakeRule([self.target], [install_path],
+ comment='Add target alias', phony = True)
+ if install_path != self.output:
+ assert not self.is_mac_bundle # See comment a few lines above.
+ self.WriteDoCmd([install_path], [self.output], 'copy',
+ comment = 'Copy this to the %s output path.' %
+ file_desc, part_of_all=part_of_all)
+ installable_deps.append(install_path)
+ if self.output != self.alias and self.alias != self.target:
+ self.WriteMakeRule([self.alias], installable_deps,
+ comment = 'Short alias for building this %s.' %
+ file_desc, phony = True)
+ if part_of_all:
+ self.WriteMakeRule(['all'], [install_path],
+ comment = 'Add %s to "all" target.' % file_desc,
+ phony = True)
+
+
+ def WriteList(self, value_list, variable=None, prefix='',
+ quoter=QuoteIfNecessary):
+ """Write a variable definition that is a list of values.
+
+ E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out
+ foo = blaha blahb
+ but in a pretty-printed style.
+ """
+ values = ''
+ if value_list:
+ value_list = [quoter(prefix + l) for l in value_list]
+ values = ' \\\n\t' + ' \\\n\t'.join(value_list)
+ self.fp.write('%s :=%s\n\n' % (variable, values))
+
+
+ def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None,
+ postbuilds=False):
+ """Write a Makefile rule that uses do_cmd.
+
+ This makes the outputs dependent on the command line that was run,
+ as well as support the V= make command line flag.
+ """
+ suffix = ''
+ if postbuilds:
+ assert ',' not in command
+ suffix = ',,1' # Tell do_cmd to honor $POSTBUILDS
+ self.WriteMakeRule(outputs, inputs,
+ actions = ['$(call do_cmd,%s%s)' % (command, suffix)],
+ comment = comment,
+ force = True)
+ # Add our outputs to the list of targets we read depfiles from.
+ # all_deps is only used for deps file reading, and for deps files we replace
+ # spaces with ? because escaping doesn't work with make's $(sort) and
+ # other functions.
+ outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs]
+ self.WriteLn('all_deps += %s' % ' '.join(outputs))
+
+
+ def WriteMakeRule(self, outputs, inputs, actions=None, comment=None,
+ order_only=False, force=False, phony=False):
+ """Write a Makefile rule, with some extra tricks.
+
+ outputs: a list of outputs for the rule (note: this is not directly
+ supported by make; see comments below)
+ inputs: a list of inputs for the rule
+ actions: a list of shell commands to run for the rule
+ comment: a comment to put in the Makefile above the rule (also useful
+ for making this Python script's code self-documenting)
+ order_only: if true, makes the dependency order-only
+ force: if true, include FORCE_DO_CMD as an order-only dep
+ phony: if true, the rule does not actually generate the named output, the
+ output is just a name to run the rule
+ """
+ outputs = map(QuoteSpaces, outputs)
+ inputs = map(QuoteSpaces, inputs)
+
+ if comment:
+ self.WriteLn('# ' + comment)
+ if phony:
+ self.WriteLn('.PHONY: ' + ' '.join(outputs))
+ # TODO(evanm): just make order_only a list of deps instead of these hacks.
+ if order_only:
+ order_insert = '| '
+ pick_output = ' '.join(outputs)
+ else:
+ order_insert = ''
+ pick_output = outputs[0]
+ if force:
+ force_append = ' FORCE_DO_CMD'
+ else:
+ force_append = ''
+ if actions:
+ self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0])
+ self.WriteLn('%s: %s%s%s' % (pick_output, order_insert, ' '.join(inputs),
+ force_append))
+ if actions:
+ for action in actions:
+ self.WriteLn('\t%s' % action)
+ if not order_only and len(outputs) > 1:
+ # If we have more than one output, a rule like
+ # foo bar: baz
+ # that for *each* output we must run the action, potentially
+ # in parallel. That is not what we're trying to write -- what
+ # we want is that we run the action once and it generates all
+ # the files.
+ # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html
+ # discusses this problem and has this solution:
+ # 1) Write the naive rule that would produce parallel runs of
+ # the action.
+ # 2) Make the outputs seralized on each other, so we won't start
+ # a parallel run until the first run finishes, at which point
+ # we'll have generated all the outputs and we're done.
+ self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0]))
+ # Add a dummy command to the "extra outputs" rule, otherwise make seems to
+ # think these outputs haven't (couldn't have?) changed, and thus doesn't
+ # flag them as changed (i.e. include in '$?') when evaluating dependent
+ # rules, which in turn causes do_cmd() to skip running dependent commands.
+ self.WriteLn('%s: ;' % (' '.join(outputs[1:])))
+ self.WriteLn()
+
+
+ def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps):
+ """Write a set of LOCAL_XXX definitions for Android NDK.
+
+ These variable definitions will be used by Android NDK but do nothing for
+ non-Android applications.
+
+ Arguments:
+ module_name: Android NDK module name, which must be unique among all
+ module names.
+ all_sources: A list of source files (will be filtered by Compilable).
+ link_deps: A list of link dependencies, which must be sorted in
+ the order from dependencies to dependents.
+ """
+ if self.type not in ('executable', 'shared_library', 'static_library'):
+ return
+
+ self.WriteLn('# Variable definitions for Android applications')
+ self.WriteLn('include $(CLEAR_VARS)')
+ self.WriteLn('LOCAL_MODULE := ' + module_name)
+ self.WriteLn('LOCAL_CFLAGS := $(CFLAGS_$(BUILDTYPE)) '
+ '$(DEFS_$(BUILDTYPE)) '
+ # LOCAL_CFLAGS is applied to both of C and C++. There is
+ # no way to specify $(CFLAGS_C_$(BUILDTYPE)) only for C
+ # sources.
+ '$(CFLAGS_C_$(BUILDTYPE)) '
+ # $(INCS_$(BUILDTYPE)) includes the prefix '-I' while
+ # LOCAL_C_INCLUDES does not expect it. So put it in
+ # LOCAL_CFLAGS.
+ '$(INCS_$(BUILDTYPE))')
+ # LOCAL_CXXFLAGS is obsolete and LOCAL_CPPFLAGS is preferred.
+ self.WriteLn('LOCAL_CPPFLAGS := $(CFLAGS_CC_$(BUILDTYPE))')
+ self.WriteLn('LOCAL_C_INCLUDES :=')
+ self.WriteLn('LOCAL_LDLIBS := $(LDFLAGS_$(BUILDTYPE)) $(LIBS)')
+
+ # Detect the C++ extension.
+ cpp_ext = {'.cc': 0, '.cpp': 0, '.cxx': 0}
+ default_cpp_ext = '.cpp'
+ for filename in all_sources:
+ ext = os.path.splitext(filename)[1]
+ if ext in cpp_ext:
+ cpp_ext[ext] += 1
+ if cpp_ext[ext] > cpp_ext[default_cpp_ext]:
+ default_cpp_ext = ext
+ self.WriteLn('LOCAL_CPP_EXTENSION := ' + default_cpp_ext)
+
+ self.WriteList(map(self.Absolutify, filter(Compilable, all_sources)),
+ 'LOCAL_SRC_FILES')
+
+ # Filter out those which do not match prefix and suffix and produce
+ # the resulting list without prefix and suffix.
+ def DepsToModules(deps, prefix, suffix):
+ modules = []
+ for filepath in deps:
+ filename = os.path.basename(filepath)
+ if filename.startswith(prefix) and filename.endswith(suffix):
+ modules.append(filename[len(prefix):-len(suffix)])
+ return modules
+
+ # Retrieve the default value of 'SHARED_LIB_SUFFIX'
+ params = {'flavor': 'linux'}
+ default_variables = {}
+ CalculateVariables(default_variables, params)
+
+ self.WriteList(
+ DepsToModules(link_deps,
+ generator_default_variables['SHARED_LIB_PREFIX'],
+ default_variables['SHARED_LIB_SUFFIX']),
+ 'LOCAL_SHARED_LIBRARIES')
+ self.WriteList(
+ DepsToModules(link_deps,
+ generator_default_variables['STATIC_LIB_PREFIX'],
+ generator_default_variables['STATIC_LIB_SUFFIX']),
+ 'LOCAL_STATIC_LIBRARIES')
+
+ if self.type == 'executable':
+ self.WriteLn('include $(BUILD_EXECUTABLE)')
+ elif self.type == 'shared_library':
+ self.WriteLn('include $(BUILD_SHARED_LIBRARY)')
+ elif self.type == 'static_library':
+ self.WriteLn('include $(BUILD_STATIC_LIBRARY)')
+ self.WriteLn()
+
+
+ def WriteLn(self, text=''):
+ self.fp.write(text + '\n')
+
+
+ def GetSortedXcodeEnv(self, additional_settings=None):
+ return gyp.xcode_emulation.GetSortedXcodeEnv(
+ self.xcode_settings, "$(abs_builddir)",
+ os.path.join("$(abs_srcdir)", self.path), "$(BUILDTYPE)",
+ additional_settings)
+
+
+ def GetSortedXcodePostbuildEnv(self):
+ # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack.
+ # TODO(thakis): It would be nice to have some general mechanism instead.
+ strip_save_file = self.xcode_settings.GetPerTargetSetting(
+ 'CHROMIUM_STRIP_SAVE_FILE', '')
+ # Even if strip_save_file is empty, explicitly write it. Else a postbuild
+ # might pick up an export from an earlier target.
+ return self.GetSortedXcodeEnv(
+ additional_settings={'CHROMIUM_STRIP_SAVE_FILE': strip_save_file})
+
+
+ def WriteSortedXcodeEnv(self, target, env):
+ for k, v in env:
+ # For
+ # foo := a\ b
+ # the escaped space does the right thing. For
+ # export foo := a\ b
+ # it does not -- the backslash is written to the env as literal character.
+ # So don't escape spaces in |env[k]|.
+ self.WriteLn('%s: export %s := %s' % (QuoteSpaces(target), k, v))
+
+
+ def Objectify(self, path):
+ """Convert a path to its output directory form."""
+ if '$(' in path:
+ path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/' % self.toolset)
+ if not '$(obj)' in path:
+ path = '$(obj).%s/$(TARGET)/%s' % (self.toolset, path)
+ return path
+
+
+ def Pchify(self, path, lang):
+ """Convert a prefix header path to its output directory form."""
+ path = self.Absolutify(path)
+ if '$(' in path:
+ path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/pch-%s' %
+ (self.toolset, lang))
+ return path
+ return '$(obj).%s/$(TARGET)/pch-%s/%s' % (self.toolset, lang, path)
+
+
+ def Absolutify(self, path):
+ """Convert a subdirectory-relative path into a base-relative path.
+ Skips over paths that contain variables."""
+ if '$(' in path:
+ # Don't call normpath in this case, as it might collapse the
+ # path too aggressively if it features '..'. However it's still
+ # important to strip trailing slashes.
+ return path.rstrip('/')
+ return os.path.normpath(os.path.join(self.path, path))
+
+
+ def ExpandInputRoot(self, template, expansion, dirname):
+ if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template:
+ return template
+ path = template % {
+ 'INPUT_ROOT': expansion,
+ 'INPUT_DIRNAME': dirname,
+ }
+ return path
+
+
+ def _InstallableTargetInstallPath(self):
+ """Returns the location of the final output for an installable target."""
+ # Xcode puts shared_library results into PRODUCT_DIR, and some gyp files
+ # rely on this. Emulate this behavior for mac.
+ if (self.type == 'shared_library' and
+ (self.flavor != 'mac' or self.toolset != 'target')):
+ # Install all shared libs into a common directory (per toolset) for
+ # convenient access with LD_LIBRARY_PATH.
+ return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias)
+ return '$(builddir)/' + self.alias
+
+
+def WriteAutoRegenerationRule(params, root_makefile, makefile_name,
+ build_files):
+ """Write the target to regenerate the Makefile."""
+ options = params['options']
+ build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir)
+ for filename in params['build_files_arg']]
+
+ gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'],
+ options.toplevel_dir)
+ if not gyp_binary.startswith(os.sep):
+ gyp_binary = os.path.join('.', gyp_binary)
+
+ root_makefile.write(
+ "quiet_cmd_regen_makefile = ACTION Regenerating $@\n"
+ "cmd_regen_makefile = cd $(srcdir); %(cmd)s\n"
+ "%(makefile_name)s: %(deps)s\n"
+ "\t$(call do_cmd,regen_makefile)\n\n" % {
+ 'makefile_name': makefile_name,
+ 'deps': ' '.join(map(Sourceify, build_files)),
+ 'cmd': gyp.common.EncodePOSIXShellList(
+ [gyp_binary, '-fmake'] +
+ gyp.RegenerateFlags(options) +
+ build_files_args)})
+
+
+def PerformBuild(data, configurations, params):
+ options = params['options']
+ for config in configurations:
+ arguments = ['make']
+ if options.toplevel_dir and options.toplevel_dir != '.':
+ arguments += '-C', options.toplevel_dir
+ arguments.append('BUILDTYPE=' + config)
+ print 'Building [%s]: %s' % (config, arguments)
+ subprocess.check_call(arguments)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ options = params['options']
+ flavor = gyp.common.GetFlavor(params)
+ generator_flags = params.get('generator_flags', {})
+ builddir_name = generator_flags.get('output_dir', 'out')
+ android_ndk_version = generator_flags.get('android_ndk_version', None)
+ default_target = generator_flags.get('default_target', 'all')
+
+ def CalculateMakefilePath(build_file, base_name):
+ """Determine where to write a Makefile for a given gyp file."""
+ # Paths in gyp files are relative to the .gyp file, but we want
+ # paths relative to the source root for the master makefile. Grab
+ # the path of the .gyp file as the base to relativize against.
+ # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
+ base_path = gyp.common.RelativePath(os.path.dirname(build_file),
+ options.depth)
+ # We write the file in the base_path directory.
+ output_file = os.path.join(options.depth, base_path, base_name)
+ if options.generator_output:
+ output_file = os.path.join(options.generator_output, output_file)
+ base_path = gyp.common.RelativePath(os.path.dirname(build_file),
+ options.toplevel_dir)
+ return base_path, output_file
+
+ # TODO: search for the first non-'Default' target. This can go
+ # away when we add verification that all targets have the
+ # necessary configurations.
+ default_configuration = None
+ toolsets = set([target_dicts[target]['toolset'] for target in target_list])
+ for target in target_list:
+ spec = target_dicts[target]
+ if spec['default_configuration'] != 'Default':
+ default_configuration = spec['default_configuration']
+ break
+ if not default_configuration:
+ default_configuration = 'Default'
+
+ srcdir = '.'
+ makefile_name = 'Makefile' + options.suffix
+ makefile_path = os.path.join(options.toplevel_dir, makefile_name)
+ if options.generator_output:
+ global srcdir_prefix
+ makefile_path = os.path.join(options.generator_output, makefile_path)
+ srcdir = gyp.common.RelativePath(srcdir, options.generator_output)
+ srcdir_prefix = '$(srcdir)/'
+
+ flock_command= 'flock'
+ header_params = {
+ 'default_target': default_target,
+ 'builddir': builddir_name,
+ 'default_configuration': default_configuration,
+ 'flock': flock_command,
+ 'flock_index': 1,
+ 'link_commands': LINK_COMMANDS_LINUX,
+ 'extra_commands': '',
+ 'srcdir': srcdir,
+ }
+ if flavor == 'mac':
+ flock_command = './gyp-mac-tool flock'
+ header_params.update({
+ 'flock': flock_command,
+ 'flock_index': 2,
+ 'link_commands': LINK_COMMANDS_MAC,
+ 'extra_commands': SHARED_HEADER_MAC_COMMANDS,
+ })
+ elif flavor == 'android':
+ header_params.update({
+ 'link_commands': LINK_COMMANDS_ANDROID,
+ })
+ elif flavor == 'solaris':
+ header_params.update({
+ 'flock': './gyp-sun-tool flock',
+ 'flock_index': 2,
+ 'extra_commands': SHARED_HEADER_SUN_COMMANDS,
+ })
+ elif flavor == 'freebsd':
+ # Note: OpenBSD has sysutils/flock. lockf seems to be FreeBSD specific.
+ header_params.update({
+ 'flock': 'lockf',
+ })
+
+ header_params.update({
+ 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'),
+ 'AR.target': GetEnvironFallback(('AR_target', 'AR'), '$(AR)'),
+ 'CXX.target': GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'),
+ 'LINK.target': GetEnvironFallback(('LD_target', 'LD'), '$(LINK)'),
+ 'CC.host': GetEnvironFallback(('CC_host',), 'gcc'),
+ 'AR.host': GetEnvironFallback(('AR_host',), 'ar'),
+ 'CXX.host': GetEnvironFallback(('CXX_host',), 'g++'),
+ 'LINK.host': GetEnvironFallback(('LD_host',), 'g++'),
+ })
+
+ build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
+ make_global_settings_array = data[build_file].get('make_global_settings', [])
+ wrappers = {}
+ wrappers['LINK'] = '%s $(builddir)/linker.lock' % flock_command
+ for key, value in make_global_settings_array:
+ if key.endswith('_wrapper'):
+ wrappers[key[:-len('_wrapper')]] = '$(abspath %s)' % value
+ make_global_settings = ''
+ for key, value in make_global_settings_array:
+ if re.match('.*_wrapper', key):
+ continue
+ if value[0] != '$':
+ value = '$(abspath %s)' % value
+ wrapper = wrappers.get(key)
+ if wrapper:
+ value = '%s %s' % (wrapper, value)
+ del wrappers[key]
+ if key in ('CC', 'CC.host', 'CXX', 'CXX.host'):
+ make_global_settings += (
+ 'ifneq (,$(filter $(origin %s), undefined default))\n' % key)
+ # Let gyp-time envvars win over global settings.
+ if key in os.environ:
+ value = os.environ[key]
+ make_global_settings += ' %s = %s\n' % (key, value)
+ make_global_settings += 'endif\n'
+ else:
+ make_global_settings += '%s ?= %s\n' % (key, value)
+ # TODO(ukai): define cmd when only wrapper is specified in
+ # make_global_settings.
+
+ header_params['make_global_settings'] = make_global_settings
+
+ ensure_directory_exists(makefile_path)
+ root_makefile = open(makefile_path, 'w')
+ root_makefile.write(SHARED_HEADER % header_params)
+ # Currently any versions have the same effect, but in future the behavior
+ # could be different.
+ if android_ndk_version:
+ root_makefile.write(
+ '# Define LOCAL_PATH for build of Android applications.\n'
+ 'LOCAL_PATH := $(call my-dir)\n'
+ '\n')
+ for toolset in toolsets:
+ root_makefile.write('TOOLSET := %s\n' % toolset)
+ WriteRootHeaderSuffixRules(root_makefile)
+
+ # Put build-time support tools next to the root Makefile.
+ dest_path = os.path.dirname(makefile_path)
+ gyp.common.CopyTool(flavor, dest_path)
+
+ # Find the list of targets that derive from the gyp file(s) being built.
+ needed_targets = set()
+ for build_file in params['build_files']:
+ for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
+ needed_targets.add(target)
+
+ build_files = set()
+ include_list = set()
+ for qualified_target in target_list:
+ build_file, target, toolset = gyp.common.ParseQualifiedTarget(
+ qualified_target)
+
+ this_make_global_settings = data[build_file].get('make_global_settings', [])
+ assert make_global_settings_array == this_make_global_settings, (
+ "make_global_settings needs to be the same for all targets.")
+
+ build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir))
+ included_files = data[build_file]['included_files']
+ for included_file in included_files:
+ # The included_files entries are relative to the dir of the build file
+ # that included them, so we have to undo that and then make them relative
+ # to the root dir.
+ relative_include_file = gyp.common.RelativePath(
+ gyp.common.UnrelativePath(included_file, build_file),
+ options.toplevel_dir)
+ abs_include_file = os.path.abspath(relative_include_file)
+ # If the include file is from the ~/.gyp dir, we should use absolute path
+ # so that relocating the src dir doesn't break the path.
+ if (params['home_dot_gyp'] and
+ abs_include_file.startswith(params['home_dot_gyp'])):
+ build_files.add(abs_include_file)
+ else:
+ build_files.add(relative_include_file)
+
+ base_path, output_file = CalculateMakefilePath(build_file,
+ target + '.' + toolset + options.suffix + '.mk')
+
+ spec = target_dicts[qualified_target]
+ configs = spec['configurations']
+
+ if flavor == 'mac':
+ gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec)
+
+ writer = MakefileWriter(generator_flags, flavor)
+ writer.Write(qualified_target, base_path, output_file, spec, configs,
+ part_of_all=qualified_target in needed_targets)
+
+ # Our root_makefile lives at the source root. Compute the relative path
+ # from there to the output_file for including.
+ mkfile_rel_path = gyp.common.RelativePath(output_file,
+ os.path.dirname(makefile_path))
+ include_list.add(mkfile_rel_path)
+
+ # Write out per-gyp (sub-project) Makefiles.
+ depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd())
+ for build_file in build_files:
+ # The paths in build_files were relativized above, so undo that before
+ # testing against the non-relativized items in target_list and before
+ # calculating the Makefile path.
+ build_file = os.path.join(depth_rel_path, build_file)
+ gyp_targets = [target_dicts[target]['target_name'] for target in target_list
+ if target.startswith(build_file) and
+ target in needed_targets]
+ # Only generate Makefiles for gyp files with targets.
+ if not gyp_targets:
+ continue
+ base_path, output_file = CalculateMakefilePath(build_file,
+ os.path.splitext(os.path.basename(build_file))[0] + '.Makefile')
+ makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path),
+ os.path.dirname(output_file))
+ writer.WriteSubMake(output_file, makefile_rel_path, gyp_targets,
+ builddir_name)
+
+
+ # Write out the sorted list of includes.
+ root_makefile.write('\n')
+ for include_file in sorted(include_list):
+ # We wrap each .mk include in an if statement so users can tell make to
+ # not load a file by setting NO_LOAD. The below make code says, only
+ # load the .mk file if the .mk filename doesn't start with a token in
+ # NO_LOAD.
+ root_makefile.write(
+ "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n"
+ " $(findstring $(join ^,$(prefix)),\\\n"
+ " $(join ^," + include_file + ")))),)\n")
+ root_makefile.write(" include " + include_file + "\n")
+ root_makefile.write("endif\n")
+ root_makefile.write('\n')
+
+ if (not generator_flags.get('standalone')
+ and generator_flags.get('auto_regeneration', True)):
+ WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files)
+
+ root_makefile.write(SHARED_FOOTER)
+
+ root_makefile.close()
diff --git a/chromium/tools/gyp/pylib/gyp/generator/msvs.py b/chromium/tools/gyp/pylib/gyp/generator/msvs.py
new file mode 100644
index 00000000000..bc3b4c2fb44
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/msvs.py
@@ -0,0 +1,3236 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import ntpath
+import os
+import posixpath
+import re
+import subprocess
+import sys
+
+import gyp.common
+import gyp.easy_xml as easy_xml
+import gyp.MSVSNew as MSVSNew
+import gyp.MSVSProject as MSVSProject
+import gyp.MSVSSettings as MSVSSettings
+import gyp.MSVSToolFile as MSVSToolFile
+import gyp.MSVSUserFile as MSVSUserFile
+import gyp.MSVSUtil as MSVSUtil
+import gyp.MSVSVersion as MSVSVersion
+from gyp.common import GypError
+
+
+# Regular expression for validating Visual Studio GUIDs. If the GUID
+# contains lowercase hex letters, MSVS will be fine. However,
+# IncrediBuild BuildConsole will parse the solution file, but then
+# silently skip building the target causing hard to track down errors.
+# Note that this only happens with the BuildConsole, and does not occur
+# if IncrediBuild is executed from inside Visual Studio. This regex
+# validates that the string looks like a GUID with all uppercase hex
+# letters.
+VALID_MSVS_GUID_CHARS = re.compile('^[A-F0-9\-]+$')
+
+
+generator_default_variables = {
+ 'EXECUTABLE_PREFIX': '',
+ 'EXECUTABLE_SUFFIX': '.exe',
+ 'STATIC_LIB_PREFIX': '',
+ 'SHARED_LIB_PREFIX': '',
+ 'STATIC_LIB_SUFFIX': '.lib',
+ 'SHARED_LIB_SUFFIX': '.dll',
+ 'INTERMEDIATE_DIR': '$(IntDir)',
+ 'SHARED_INTERMEDIATE_DIR': '$(OutDir)obj/global_intermediate',
+ 'OS': 'win',
+ 'PRODUCT_DIR': '$(OutDir)',
+ 'LIB_DIR': '$(OutDir)lib',
+ 'RULE_INPUT_ROOT': '$(InputName)',
+ 'RULE_INPUT_DIRNAME': '$(InputDir)',
+ 'RULE_INPUT_EXT': '$(InputExt)',
+ 'RULE_INPUT_NAME': '$(InputFileName)',
+ 'RULE_INPUT_PATH': '$(InputPath)',
+ 'CONFIGURATION_NAME': '$(ConfigurationName)',
+}
+
+
+# The msvs specific sections that hold paths
+generator_additional_path_sections = [
+ 'msvs_cygwin_dirs',
+ 'msvs_props',
+]
+
+
+generator_additional_non_configuration_keys = [
+ 'msvs_cygwin_dirs',
+ 'msvs_cygwin_shell',
+ 'msvs_large_pdb',
+ 'msvs_shard',
+ 'msvs_external_builder',
+ 'msvs_external_builder_out_dir',
+ 'msvs_external_builder_build_cmd',
+ 'msvs_external_builder_clean_cmd',
+]
+
+
+# List of precompiled header related keys.
+precomp_keys = [
+ 'msvs_precompiled_header',
+ 'msvs_precompiled_source',
+]
+
+
+cached_username = None
+
+
+cached_domain = None
+
+
+# TODO(gspencer): Switch the os.environ calls to be
+# win32api.GetDomainName() and win32api.GetUserName() once the
+# python version in depot_tools has been updated to work on Vista
+# 64-bit.
+def _GetDomainAndUserName():
+ if sys.platform not in ('win32', 'cygwin'):
+ return ('DOMAIN', 'USERNAME')
+ global cached_username
+ global cached_domain
+ if not cached_domain or not cached_username:
+ domain = os.environ.get('USERDOMAIN')
+ username = os.environ.get('USERNAME')
+ if not domain or not username:
+ call = subprocess.Popen(['net', 'config', 'Workstation'],
+ stdout=subprocess.PIPE)
+ config = call.communicate()[0]
+ username_re = re.compile('^User name\s+(\S+)', re.MULTILINE)
+ username_match = username_re.search(config)
+ if username_match:
+ username = username_match.group(1)
+ domain_re = re.compile('^Logon domain\s+(\S+)', re.MULTILINE)
+ domain_match = domain_re.search(config)
+ if domain_match:
+ domain = domain_match.group(1)
+ cached_domain = domain
+ cached_username = username
+ return (cached_domain, cached_username)
+
+fixpath_prefix = None
+
+
+def _NormalizedSource(source):
+ """Normalize the path.
+
+ But not if that gets rid of a variable, as this may expand to something
+ larger than one directory.
+
+ Arguments:
+ source: The path to be normalize.d
+
+ Returns:
+ The normalized path.
+ """
+ normalized = os.path.normpath(source)
+ if source.count('$') == normalized.count('$'):
+ source = normalized
+ return source
+
+
+def _FixPath(path):
+ """Convert paths to a form that will make sense in a vcproj file.
+
+ Arguments:
+ path: The path to convert, may contain / etc.
+ Returns:
+ The path with all slashes made into backslashes.
+ """
+ if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$':
+ path = os.path.join(fixpath_prefix, path)
+ path = path.replace('/', '\\')
+ path = _NormalizedSource(path)
+ if path and path[-1] == '\\':
+ path = path[:-1]
+ return path
+
+
+def _FixPaths(paths):
+ """Fix each of the paths of the list."""
+ return [_FixPath(i) for i in paths]
+
+
+def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None,
+ list_excluded=True):
+ """Converts a list split source file paths into a vcproj folder hierarchy.
+
+ Arguments:
+ sources: A list of source file paths split.
+ prefix: A list of source file path layers meant to apply to each of sources.
+ excluded: A set of excluded files.
+
+ Returns:
+ A hierarchy of filenames and MSVSProject.Filter objects that matches the
+ layout of the source tree.
+ For example:
+ _ConvertSourcesToFilterHierarchy([['a', 'bob1.c'], ['b', 'bob2.c']],
+ prefix=['joe'])
+ -->
+ [MSVSProject.Filter('a', contents=['joe\\a\\bob1.c']),
+ MSVSProject.Filter('b', contents=['joe\\b\\bob2.c'])]
+ """
+ if not prefix: prefix = []
+ result = []
+ excluded_result = []
+ folders = dict()
+ # Gather files into the final result, excluded, or folders.
+ for s in sources:
+ if len(s) == 1:
+ filename = _NormalizedSource('\\'.join(prefix + s))
+ if filename in excluded:
+ excluded_result.append(filename)
+ else:
+ result.append(filename)
+ else:
+ if not folders.get(s[0]):
+ folders[s[0]] = []
+ folders[s[0]].append(s[1:])
+ # Add a folder for excluded files.
+ if excluded_result and list_excluded:
+ excluded_folder = MSVSProject.Filter('_excluded_files',
+ contents=excluded_result)
+ result.append(excluded_folder)
+ # Populate all the folders.
+ for f in folders:
+ contents = _ConvertSourcesToFilterHierarchy(folders[f], prefix=prefix + [f],
+ excluded=excluded,
+ list_excluded=list_excluded)
+ contents = MSVSProject.Filter(f, contents=contents)
+ result.append(contents)
+
+ return result
+
+
+def _ToolAppend(tools, tool_name, setting, value, only_if_unset=False):
+ if not value: return
+ _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset)
+
+
+def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False):
+ # TODO(bradnelson): ugly hack, fix this more generally!!!
+ if 'Directories' in setting or 'Dependencies' in setting:
+ if type(value) == str:
+ value = value.replace('/', '\\')
+ else:
+ value = [i.replace('/', '\\') for i in value]
+ if not tools.get(tool_name):
+ tools[tool_name] = dict()
+ tool = tools[tool_name]
+ if tool.get(setting):
+ if only_if_unset: return
+ if type(tool[setting]) == list:
+ tool[setting] += value
+ else:
+ raise TypeError(
+ 'Appending "%s" to a non-list setting "%s" for tool "%s" is '
+ 'not allowed, previous value: %s' % (
+ value, setting, tool_name, str(tool[setting])))
+ else:
+ tool[setting] = value
+
+
+def _ConfigPlatform(config_data):
+ return config_data.get('msvs_configuration_platform', 'Win32')
+
+
+def _ConfigBaseName(config_name, platform_name):
+ if config_name.endswith('_' + platform_name):
+ return config_name[0:-len(platform_name) - 1]
+ else:
+ return config_name
+
+
+def _ConfigFullName(config_name, config_data):
+ platform_name = _ConfigPlatform(config_data)
+ return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name)
+
+
+def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path,
+ quote_cmd, do_setup_env):
+
+ if [x for x in cmd if '$(InputDir)' in x]:
+ input_dir_preamble = (
+ 'set INPUTDIR=$(InputDir)\n'
+ 'set INPUTDIR=%INPUTDIR:$(ProjectDir)=%\n'
+ 'set INPUTDIR=%INPUTDIR:~0,-1%\n'
+ )
+ else:
+ input_dir_preamble = ''
+
+ if cygwin_shell:
+ # Find path to cygwin.
+ cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0])
+ # Prepare command.
+ direct_cmd = cmd
+ direct_cmd = [i.replace('$(IntDir)',
+ '`cygpath -m "${INTDIR}"`') for i in direct_cmd]
+ direct_cmd = [i.replace('$(OutDir)',
+ '`cygpath -m "${OUTDIR}"`') for i in direct_cmd]
+ direct_cmd = [i.replace('$(InputDir)',
+ '`cygpath -m "${INPUTDIR}"`') for i in direct_cmd]
+ if has_input_path:
+ direct_cmd = [i.replace('$(InputPath)',
+ '`cygpath -m "${INPUTPATH}"`')
+ for i in direct_cmd]
+ direct_cmd = ['\\"%s\\"' % i.replace('"', '\\\\\\"') for i in direct_cmd]
+ # direct_cmd = gyp.common.EncodePOSIXShellList(direct_cmd)
+ direct_cmd = ' '.join(direct_cmd)
+ # TODO(quote): regularize quoting path names throughout the module
+ cmd = ''
+ if do_setup_env:
+ cmd += 'call "$(ProjectDir)%(cygwin_dir)s\\setup_env.bat" && '
+ cmd += 'set CYGWIN=nontsec&& '
+ if direct_cmd.find('NUMBER_OF_PROCESSORS') >= 0:
+ cmd += 'set /a NUMBER_OF_PROCESSORS_PLUS_1=%%NUMBER_OF_PROCESSORS%%+1&& '
+ if direct_cmd.find('INTDIR') >= 0:
+ cmd += 'set INTDIR=$(IntDir)&& '
+ if direct_cmd.find('OUTDIR') >= 0:
+ cmd += 'set OUTDIR=$(OutDir)&& '
+ if has_input_path and direct_cmd.find('INPUTPATH') >= 0:
+ cmd += 'set INPUTPATH=$(InputPath) && '
+ cmd += 'bash -c "%(cmd)s"'
+ cmd = cmd % {'cygwin_dir': cygwin_dir,
+ 'cmd': direct_cmd}
+ return input_dir_preamble + cmd
+ else:
+ # Convert cat --> type to mimic unix.
+ if cmd[0] == 'cat':
+ command = ['type']
+ else:
+ command = [cmd[0].replace('/', '\\')]
+ # Add call before command to ensure that commands can be tied together one
+ # after the other without aborting in Incredibuild, since IB makes a bat
+ # file out of the raw command string, and some commands (like python) are
+ # actually batch files themselves.
+ command.insert(0, 'call')
+ # Fix the paths
+ # TODO(quote): This is a really ugly heuristic, and will miss path fixing
+ # for arguments like "--arg=path" or "/opt:path".
+ # If the argument starts with a slash or dash, it's probably a command line
+ # switch
+ arguments = [i if (i[:1] in "/-") else _FixPath(i) for i in cmd[1:]]
+ arguments = [i.replace('$(InputDir)', '%INPUTDIR%') for i in arguments]
+ arguments = [MSVSSettings.FixVCMacroSlashes(i) for i in arguments]
+ if quote_cmd:
+ # Support a mode for using cmd directly.
+ # Convert any paths to native form (first element is used directly).
+ # TODO(quote): regularize quoting path names throughout the module
+ arguments = ['"%s"' % i for i in arguments]
+ # Collapse into a single command.
+ return input_dir_preamble + ' '.join(command + arguments)
+
+
+def _BuildCommandLineForRule(spec, rule, has_input_path, do_setup_env):
+ # Currently this weird argument munging is used to duplicate the way a
+ # python script would need to be run as part of the chrome tree.
+ # Eventually we should add some sort of rule_default option to set this
+ # per project. For now the behavior chrome needs is the default.
+ mcs = rule.get('msvs_cygwin_shell')
+ if mcs is None:
+ mcs = int(spec.get('msvs_cygwin_shell', 1))
+ elif isinstance(mcs, str):
+ mcs = int(mcs)
+ quote_cmd = int(rule.get('msvs_quote_cmd', 1))
+ return _BuildCommandLineForRuleRaw(spec, rule['action'], mcs, has_input_path,
+ quote_cmd, do_setup_env=do_setup_env)
+
+
+def _AddActionStep(actions_dict, inputs, outputs, description, command):
+ """Merge action into an existing list of actions.
+
+ Care must be taken so that actions which have overlapping inputs either don't
+ get assigned to the same input, or get collapsed into one.
+
+ Arguments:
+ actions_dict: dictionary keyed on input name, which maps to a list of
+ dicts describing the actions attached to that input file.
+ inputs: list of inputs
+ outputs: list of outputs
+ description: description of the action
+ command: command line to execute
+ """
+ # Require there to be at least one input (call sites will ensure this).
+ assert inputs
+
+ action = {
+ 'inputs': inputs,
+ 'outputs': outputs,
+ 'description': description,
+ 'command': command,
+ }
+
+ # Pick where to stick this action.
+ # While less than optimal in terms of build time, attach them to the first
+ # input for now.
+ chosen_input = inputs[0]
+
+ # Add it there.
+ if chosen_input not in actions_dict:
+ actions_dict[chosen_input] = []
+ actions_dict[chosen_input].append(action)
+
+
+def _AddCustomBuildToolForMSVS(p, spec, primary_input,
+ inputs, outputs, description, cmd):
+ """Add a custom build tool to execute something.
+
+ Arguments:
+ p: the target project
+ spec: the target project dict
+ primary_input: input file to attach the build tool to
+ inputs: list of inputs
+ outputs: list of outputs
+ description: description of the action
+ cmd: command line to execute
+ """
+ inputs = _FixPaths(inputs)
+ outputs = _FixPaths(outputs)
+ tool = MSVSProject.Tool(
+ 'VCCustomBuildTool',
+ {'Description': description,
+ 'AdditionalDependencies': ';'.join(inputs),
+ 'Outputs': ';'.join(outputs),
+ 'CommandLine': cmd,
+ })
+ # Add to the properties of primary input for each config.
+ for config_name, c_data in spec['configurations'].iteritems():
+ p.AddFileConfig(_FixPath(primary_input),
+ _ConfigFullName(config_name, c_data), tools=[tool])
+
+
+def _AddAccumulatedActionsToMSVS(p, spec, actions_dict):
+ """Add actions accumulated into an actions_dict, merging as needed.
+
+ Arguments:
+ p: the target project
+ spec: the target project dict
+ actions_dict: dictionary keyed on input name, which maps to a list of
+ dicts describing the actions attached to that input file.
+ """
+ for primary_input in actions_dict:
+ inputs = set()
+ outputs = set()
+ descriptions = []
+ commands = []
+ for action in actions_dict[primary_input]:
+ inputs.update(set(action['inputs']))
+ outputs.update(set(action['outputs']))
+ descriptions.append(action['description'])
+ commands.append(action['command'])
+ # Add the custom build step for one input file.
+ description = ', and also '.join(descriptions)
+ command = '\r\n'.join(commands)
+ _AddCustomBuildToolForMSVS(p, spec,
+ primary_input=primary_input,
+ inputs=inputs,
+ outputs=outputs,
+ description=description,
+ cmd=command)
+
+
+def _RuleExpandPath(path, input_file):
+ """Given the input file to which a rule applied, string substitute a path.
+
+ Arguments:
+ path: a path to string expand
+ input_file: the file to which the rule applied.
+ Returns:
+ The string substituted path.
+ """
+ path = path.replace('$(InputName)',
+ os.path.splitext(os.path.split(input_file)[1])[0])
+ path = path.replace('$(InputDir)', os.path.dirname(input_file))
+ path = path.replace('$(InputExt)',
+ os.path.splitext(os.path.split(input_file)[1])[1])
+ path = path.replace('$(InputFileName)', os.path.split(input_file)[1])
+ path = path.replace('$(InputPath)', input_file)
+ return path
+
+
+def _FindRuleTriggerFiles(rule, sources):
+ """Find the list of files which a particular rule applies to.
+
+ Arguments:
+ rule: the rule in question
+ sources: the set of all known source files for this project
+ Returns:
+ The list of sources that trigger a particular rule.
+ """
+ return rule.get('rule_sources', [])
+
+
+def _RuleInputsAndOutputs(rule, trigger_file):
+ """Find the inputs and outputs generated by a rule.
+
+ Arguments:
+ rule: the rule in question.
+ trigger_file: the main trigger for this rule.
+ Returns:
+ The pair of (inputs, outputs) involved in this rule.
+ """
+ raw_inputs = _FixPaths(rule.get('inputs', []))
+ raw_outputs = _FixPaths(rule.get('outputs', []))
+ inputs = set()
+ outputs = set()
+ inputs.add(trigger_file)
+ for i in raw_inputs:
+ inputs.add(_RuleExpandPath(i, trigger_file))
+ for o in raw_outputs:
+ outputs.add(_RuleExpandPath(o, trigger_file))
+ return (inputs, outputs)
+
+
+def _GenerateNativeRulesForMSVS(p, rules, output_dir, spec, options):
+ """Generate a native rules file.
+
+ Arguments:
+ p: the target project
+ rules: the set of rules to include
+ output_dir: the directory in which the project/gyp resides
+ spec: the project dict
+ options: global generator options
+ """
+ rules_filename = '%s%s.rules' % (spec['target_name'],
+ options.suffix)
+ rules_file = MSVSToolFile.Writer(os.path.join(output_dir, rules_filename),
+ spec['target_name'])
+ # Add each rule.
+ for r in rules:
+ rule_name = r['rule_name']
+ rule_ext = r['extension']
+ inputs = _FixPaths(r.get('inputs', []))
+ outputs = _FixPaths(r.get('outputs', []))
+ # Skip a rule with no action and no inputs.
+ if 'action' not in r and not r.get('rule_sources', []):
+ continue
+ cmd = _BuildCommandLineForRule(spec, r, has_input_path=True,
+ do_setup_env=True)
+ rules_file.AddCustomBuildRule(name=rule_name,
+ description=r.get('message', rule_name),
+ extensions=[rule_ext],
+ additional_dependencies=inputs,
+ outputs=outputs,
+ cmd=cmd)
+ # Write out rules file.
+ rules_file.WriteIfChanged()
+
+ # Add rules file to project.
+ p.AddToolFile(rules_filename)
+
+
+def _Cygwinify(path):
+ path = path.replace('$(OutDir)', '$(OutDirCygwin)')
+ path = path.replace('$(IntDir)', '$(IntDirCygwin)')
+ return path
+
+
+def _GenerateExternalRules(rules, output_dir, spec,
+ sources, options, actions_to_add):
+ """Generate an external makefile to do a set of rules.
+
+ Arguments:
+ rules: the list of rules to include
+ output_dir: path containing project and gyp files
+ spec: project specification data
+ sources: set of sources known
+ options: global generator options
+ actions_to_add: The list of actions we will add to.
+ """
+ filename = '%s_rules%s.mk' % (spec['target_name'], options.suffix)
+ mk_file = gyp.common.WriteOnDiff(os.path.join(output_dir, filename))
+ # Find cygwin style versions of some paths.
+ mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n')
+ mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n')
+ # Gather stuff needed to emit all: target.
+ all_inputs = set()
+ all_outputs = set()
+ all_output_dirs = set()
+ first_outputs = []
+ for rule in rules:
+ trigger_files = _FindRuleTriggerFiles(rule, sources)
+ for tf in trigger_files:
+ inputs, outputs = _RuleInputsAndOutputs(rule, tf)
+ all_inputs.update(set(inputs))
+ all_outputs.update(set(outputs))
+ # Only use one target from each rule as the dependency for
+ # 'all' so we don't try to build each rule multiple times.
+ first_outputs.append(list(outputs)[0])
+ # Get the unique output directories for this rule.
+ output_dirs = [os.path.split(i)[0] for i in outputs]
+ for od in output_dirs:
+ all_output_dirs.add(od)
+ first_outputs_cyg = [_Cygwinify(i) for i in first_outputs]
+ # Write out all: target, including mkdir for each output directory.
+ mk_file.write('all: %s\n' % ' '.join(first_outputs_cyg))
+ for od in all_output_dirs:
+ if od:
+ mk_file.write('\tmkdir -p `cygpath -u "%s"`\n' % od)
+ mk_file.write('\n')
+ # Define how each output is generated.
+ for rule in rules:
+ trigger_files = _FindRuleTriggerFiles(rule, sources)
+ for tf in trigger_files:
+ # Get all the inputs and outputs for this rule for this trigger file.
+ inputs, outputs = _RuleInputsAndOutputs(rule, tf)
+ inputs = [_Cygwinify(i) for i in inputs]
+ outputs = [_Cygwinify(i) for i in outputs]
+ # Prepare the command line for this rule.
+ cmd = [_RuleExpandPath(c, tf) for c in rule['action']]
+ cmd = ['"%s"' % i for i in cmd]
+ cmd = ' '.join(cmd)
+ # Add it to the makefile.
+ mk_file.write('%s: %s\n' % (' '.join(outputs), ' '.join(inputs)))
+ mk_file.write('\t%s\n\n' % cmd)
+ # Close up the file.
+ mk_file.close()
+
+ # Add makefile to list of sources.
+ sources.add(filename)
+ # Add a build action to call makefile.
+ cmd = ['make',
+ 'OutDir=$(OutDir)',
+ 'IntDir=$(IntDir)',
+ '-j', '${NUMBER_OF_PROCESSORS_PLUS_1}',
+ '-f', filename]
+ cmd = _BuildCommandLineForRuleRaw(spec, cmd, True, False, True, True)
+ # Insert makefile as 0'th input, so it gets the action attached there,
+ # as this is easier to understand from in the IDE.
+ all_inputs = list(all_inputs)
+ all_inputs.insert(0, filename)
+ _AddActionStep(actions_to_add,
+ inputs=_FixPaths(all_inputs),
+ outputs=_FixPaths(all_outputs),
+ description='Running external rules for %s' %
+ spec['target_name'],
+ command=cmd)
+
+
+def _EscapeEnvironmentVariableExpansion(s):
+ """Escapes % characters.
+
+ Escapes any % characters so that Windows-style environment variable
+ expansions will leave them alone.
+ See http://connect.microsoft.com/VisualStudio/feedback/details/106127/cl-d-name-text-containing-percentage-characters-doesnt-compile
+ to understand why we have to do this.
+
+ Args:
+ s: The string to be escaped.
+
+ Returns:
+ The escaped string.
+ """
+ s = s.replace('%', '%%')
+ return s
+
+
+quote_replacer_regex = re.compile(r'(\\*)"')
+
+
+def _EscapeCommandLineArgumentForMSVS(s):
+ """Escapes a Windows command-line argument.
+
+ So that the Win32 CommandLineToArgv function will turn the escaped result back
+ into the original string.
+ See http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
+ ("Parsing C++ Command-Line Arguments") to understand why we have to do
+ this.
+
+ Args:
+ s: the string to be escaped.
+ Returns:
+ the escaped string.
+ """
+
+ def _Replace(match):
+ # For a literal quote, CommandLineToArgv requires an odd number of
+ # backslashes preceding it, and it produces half as many literal backslashes
+ # (rounded down). So we need to produce 2n+1 backslashes.
+ return 2 * match.group(1) + '\\"'
+
+ # Escape all quotes so that they are interpreted literally.
+ s = quote_replacer_regex.sub(_Replace, s)
+ # Now add unescaped quotes so that any whitespace is interpreted literally.
+ s = '"' + s + '"'
+ return s
+
+
+delimiters_replacer_regex = re.compile(r'(\\*)([,;]+)')
+
+
+def _EscapeVCProjCommandLineArgListItem(s):
+ """Escapes command line arguments for MSVS.
+
+ The VCProj format stores string lists in a single string using commas and
+ semi-colons as separators, which must be quoted if they are to be
+ interpreted literally. However, command-line arguments may already have
+ quotes, and the VCProj parser is ignorant of the backslash escaping
+ convention used by CommandLineToArgv, so the command-line quotes and the
+ VCProj quotes may not be the same quotes. So to store a general
+ command-line argument in a VCProj list, we need to parse the existing
+ quoting according to VCProj's convention and quote any delimiters that are
+ not already quoted by that convention. The quotes that we add will also be
+ seen by CommandLineToArgv, so if backslashes precede them then we also have
+ to escape those backslashes according to the CommandLineToArgv
+ convention.
+
+ Args:
+ s: the string to be escaped.
+ Returns:
+ the escaped string.
+ """
+
+ def _Replace(match):
+ # For a non-literal quote, CommandLineToArgv requires an even number of
+ # backslashes preceding it, and it produces half as many literal
+ # backslashes. So we need to produce 2n backslashes.
+ return 2 * match.group(1) + '"' + match.group(2) + '"'
+
+ segments = s.split('"')
+ # The unquoted segments are at the even-numbered indices.
+ for i in range(0, len(segments), 2):
+ segments[i] = delimiters_replacer_regex.sub(_Replace, segments[i])
+ # Concatenate back into a single string
+ s = '"'.join(segments)
+ if len(segments) % 2 == 0:
+ # String ends while still quoted according to VCProj's convention. This
+ # means the delimiter and the next list item that follow this one in the
+ # .vcproj file will be misinterpreted as part of this item. There is nothing
+ # we can do about this. Adding an extra quote would correct the problem in
+ # the VCProj but cause the same problem on the final command-line. Moving
+ # the item to the end of the list does works, but that's only possible if
+ # there's only one such item. Let's just warn the user.
+ print >> sys.stderr, ('Warning: MSVS may misinterpret the odd number of ' +
+ 'quotes in ' + s)
+ return s
+
+
+def _EscapeCppDefineForMSVS(s):
+ """Escapes a CPP define so that it will reach the compiler unaltered."""
+ s = _EscapeEnvironmentVariableExpansion(s)
+ s = _EscapeCommandLineArgumentForMSVS(s)
+ s = _EscapeVCProjCommandLineArgListItem(s)
+ # cl.exe replaces literal # characters with = in preprocesor definitions for
+ # some reason. Octal-encode to work around that.
+ s = s.replace('#', '\\%03o' % ord('#'))
+ return s
+
+
+quote_replacer_regex2 = re.compile(r'(\\+)"')
+
+
+def _EscapeCommandLineArgumentForMSBuild(s):
+ """Escapes a Windows command-line argument for use by MSBuild."""
+
+ def _Replace(match):
+ return (len(match.group(1)) / 2 * 4) * '\\' + '\\"'
+
+ # Escape all quotes so that they are interpreted literally.
+ s = quote_replacer_regex2.sub(_Replace, s)
+ return s
+
+
+def _EscapeMSBuildSpecialCharacters(s):
+ escape_dictionary = {
+ '%': '%25',
+ '$': '%24',
+ '@': '%40',
+ "'": '%27',
+ ';': '%3B',
+ '?': '%3F',
+ '*': '%2A'
+ }
+ result = ''.join([escape_dictionary.get(c, c) for c in s])
+ return result
+
+
+def _EscapeCppDefineForMSBuild(s):
+ """Escapes a CPP define so that it will reach the compiler unaltered."""
+ s = _EscapeEnvironmentVariableExpansion(s)
+ s = _EscapeCommandLineArgumentForMSBuild(s)
+ s = _EscapeMSBuildSpecialCharacters(s)
+ # cl.exe replaces literal # characters with = in preprocesor definitions for
+ # some reason. Octal-encode to work around that.
+ s = s.replace('#', '\\%03o' % ord('#'))
+ return s
+
+
+def _GenerateRulesForMSVS(p, output_dir, options, spec,
+ sources, excluded_sources,
+ actions_to_add):
+ """Generate all the rules for a particular project.
+
+ Arguments:
+ p: the project
+ output_dir: directory to emit rules to
+ options: global options passed to the generator
+ spec: the specification for this project
+ sources: the set of all known source files in this project
+ excluded_sources: the set of sources excluded from normal processing
+ actions_to_add: deferred list of actions to add in
+ """
+ rules = spec.get('rules', [])
+ rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))]
+ rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))]
+
+ # Handle rules that use a native rules file.
+ if rules_native:
+ _GenerateNativeRulesForMSVS(p, rules_native, output_dir, spec, options)
+
+ # Handle external rules (non-native rules).
+ if rules_external:
+ _GenerateExternalRules(rules_external, output_dir, spec,
+ sources, options, actions_to_add)
+ _AdjustSourcesForRules(spec, rules, sources, excluded_sources)
+
+
+def _AdjustSourcesForRules(spec, rules, sources, excluded_sources):
+ # Add outputs generated by each rule (if applicable).
+ for rule in rules:
+ # Done if not processing outputs as sources.
+ if int(rule.get('process_outputs_as_sources', False)):
+ # Add in the outputs from this rule.
+ trigger_files = _FindRuleTriggerFiles(rule, sources)
+ for trigger_file in trigger_files:
+ inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file)
+ inputs = set(_FixPaths(inputs))
+ outputs = set(_FixPaths(outputs))
+ inputs.remove(_FixPath(trigger_file))
+ sources.update(inputs)
+ if not spec.get('msvs_external_builder'):
+ excluded_sources.update(inputs)
+ sources.update(outputs)
+
+
+def _FilterActionsFromExcluded(excluded_sources, actions_to_add):
+ """Take inputs with actions attached out of the list of exclusions.
+
+ Arguments:
+ excluded_sources: list of source files not to be built.
+ actions_to_add: dict of actions keyed on source file they're attached to.
+ Returns:
+ excluded_sources with files that have actions attached removed.
+ """
+ must_keep = set(_FixPaths(actions_to_add.keys()))
+ return [s for s in excluded_sources if s not in must_keep]
+
+
+def _GetDefaultConfiguration(spec):
+ return spec['configurations'][spec['default_configuration']]
+
+
+def _GetGuidOfProject(proj_path, spec):
+ """Get the guid for the project.
+
+ Arguments:
+ proj_path: Path of the vcproj or vcxproj file to generate.
+ spec: The target dictionary containing the properties of the target.
+ Returns:
+ the guid.
+ Raises:
+ ValueError: if the specified GUID is invalid.
+ """
+ # Pluck out the default configuration.
+ default_config = _GetDefaultConfiguration(spec)
+ # Decide the guid of the project.
+ guid = default_config.get('msvs_guid')
+ if guid:
+ if VALID_MSVS_GUID_CHARS.match(guid) is None:
+ raise ValueError('Invalid MSVS guid: "%s". Must match regex: "%s".' %
+ (guid, VALID_MSVS_GUID_CHARS.pattern))
+ guid = '{%s}' % guid
+ guid = guid or MSVSNew.MakeGuid(proj_path)
+ return guid
+
+
+def _GetMsbuildToolsetOfProject(proj_path, spec, version):
+ """Get the platform toolset for the project.
+
+ Arguments:
+ proj_path: Path of the vcproj or vcxproj file to generate.
+ spec: The target dictionary containing the properties of the target.
+ version: The MSVSVersion object.
+ Returns:
+ the platform toolset string or None.
+ """
+ # Pluck out the default configuration.
+ default_config = _GetDefaultConfiguration(spec)
+ toolset = default_config.get('msbuild_toolset')
+ if not toolset and version.DefaultToolset():
+ toolset = version.DefaultToolset()
+ return toolset
+
+
+def _GenerateProject(project, options, version, generator_flags):
+ """Generates a vcproj file.
+
+ Arguments:
+ project: the MSVSProject object.
+ options: global generator options.
+ version: the MSVSVersion object.
+ generator_flags: dict of generator-specific flags.
+ Returns:
+ A list of source files that cannot be found on disk.
+ """
+ default_config = _GetDefaultConfiguration(project.spec)
+
+ # Skip emitting anything if told to with msvs_existing_vcproj option.
+ if default_config.get('msvs_existing_vcproj'):
+ return []
+
+ if version.UsesVcxproj():
+ return _GenerateMSBuildProject(project, options, version, generator_flags)
+ else:
+ return _GenerateMSVSProject(project, options, version, generator_flags)
+
+
+def _GenerateMSVSProject(project, options, version, generator_flags):
+ """Generates a .vcproj file. It may create .rules and .user files too.
+
+ Arguments:
+ project: The project object we will generate the file for.
+ options: Global options passed to the generator.
+ version: The VisualStudioVersion object.
+ generator_flags: dict of generator-specific flags.
+ """
+ spec = project.spec
+ vcproj_dir = os.path.dirname(project.path)
+ if vcproj_dir and not os.path.exists(vcproj_dir):
+ os.makedirs(vcproj_dir)
+
+ platforms = _GetUniquePlatforms(spec)
+ p = MSVSProject.Writer(project.path, version, spec['target_name'],
+ project.guid, platforms)
+
+ # Get directory project file is in.
+ project_dir = os.path.split(project.path)[0]
+ gyp_path = _NormalizedSource(project.build_file)
+ relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir)
+
+ config_type = _GetMSVSConfigurationType(spec, project.build_file)
+ for config_name, config in spec['configurations'].iteritems():
+ _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config)
+
+ # Prepare list of sources and excluded sources.
+ gyp_file = os.path.split(project.build_file)[1]
+ sources, excluded_sources = _PrepareListOfSources(spec, generator_flags,
+ gyp_file)
+
+ # Add rules.
+ actions_to_add = {}
+ _GenerateRulesForMSVS(p, project_dir, options, spec,
+ sources, excluded_sources,
+ actions_to_add)
+ list_excluded = generator_flags.get('msvs_list_excluded_files', True)
+ sources, excluded_sources, excluded_idl = (
+ _AdjustSourcesAndConvertToFilterHierarchy(
+ spec, options, project_dir, sources, excluded_sources, list_excluded))
+
+ # Add in files.
+ missing_sources = _VerifySourcesExist(sources, project_dir)
+ p.AddFiles(sources)
+
+ _AddToolFilesToMSVS(p, spec)
+ _HandlePreCompiledHeaders(p, sources, spec)
+ _AddActions(actions_to_add, spec, relative_path_of_gyp_file)
+ _AddCopies(actions_to_add, spec)
+ _WriteMSVSUserFile(project.path, version, spec)
+
+ # NOTE: this stanza must appear after all actions have been decided.
+ # Don't excluded sources with actions attached, or they won't run.
+ excluded_sources = _FilterActionsFromExcluded(
+ excluded_sources, actions_to_add)
+ _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl,
+ list_excluded)
+ _AddAccumulatedActionsToMSVS(p, spec, actions_to_add)
+
+ # Write it out.
+ p.WriteIfChanged()
+
+ return missing_sources
+
+
+def _GetUniquePlatforms(spec):
+ """Returns the list of unique platforms for this spec, e.g ['win32', ...].
+
+ Arguments:
+ spec: The target dictionary containing the properties of the target.
+ Returns:
+ The MSVSUserFile object created.
+ """
+ # Gather list of unique platforms.
+ platforms = set()
+ for configuration in spec['configurations']:
+ platforms.add(_ConfigPlatform(spec['configurations'][configuration]))
+ platforms = list(platforms)
+ return platforms
+
+
+def _CreateMSVSUserFile(proj_path, version, spec):
+ """Generates a .user file for the user running this Gyp program.
+
+ Arguments:
+ proj_path: The path of the project file being created. The .user file
+ shares the same path (with an appropriate suffix).
+ version: The VisualStudioVersion object.
+ spec: The target dictionary containing the properties of the target.
+ Returns:
+ The MSVSUserFile object created.
+ """
+ (domain, username) = _GetDomainAndUserName()
+ vcuser_filename = '.'.join([proj_path, domain, username, 'user'])
+ user_file = MSVSUserFile.Writer(vcuser_filename, version,
+ spec['target_name'])
+ return user_file
+
+
+def _GetMSVSConfigurationType(spec, build_file):
+ """Returns the configuration type for this project.
+
+ It's a number defined by Microsoft. May raise an exception.
+
+ Args:
+ spec: The target dictionary containing the properties of the target.
+ build_file: The path of the gyp file.
+ Returns:
+ An integer, the configuration type.
+ """
+ try:
+ config_type = {
+ 'executable': '1', # .exe
+ 'shared_library': '2', # .dll
+ 'loadable_module': '2', # .dll
+ 'static_library': '4', # .lib
+ 'none': '10', # Utility type
+ }[spec['type']]
+ except KeyError:
+ if spec.get('type'):
+ raise GypError('Target type %s is not a valid target type for '
+ 'target %s in %s.' %
+ (spec['type'], spec['target_name'], build_file))
+ else:
+ raise GypError('Missing type field for target %s in %s.' %
+ (spec['target_name'], build_file))
+ return config_type
+
+
+def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config):
+ """Adds a configuration to the MSVS project.
+
+ Many settings in a vcproj file are specific to a configuration. This
+ function the main part of the vcproj file that's configuration specific.
+
+ Arguments:
+ p: The target project being generated.
+ spec: The target dictionary containing the properties of the target.
+ config_type: The configuration type, a number as defined by Microsoft.
+ config_name: The name of the configuration.
+ config: The dictionary that defines the special processing to be done
+ for this configuration.
+ """
+ # Get the information for this configuration
+ include_dirs, resource_include_dirs = _GetIncludeDirs(config)
+ libraries = _GetLibraries(spec)
+ library_dirs = _GetLibraryDirs(config)
+ out_file, vc_tool, _ = _GetOutputFilePathAndTool(spec, msbuild=False)
+ defines = _GetDefines(config)
+ defines = [_EscapeCppDefineForMSVS(d) for d in defines]
+ disabled_warnings = _GetDisabledWarnings(config)
+ prebuild = config.get('msvs_prebuild')
+ postbuild = config.get('msvs_postbuild')
+ def_file = _GetModuleDefinition(spec)
+ precompiled_header = config.get('msvs_precompiled_header')
+
+ # Prepare the list of tools as a dictionary.
+ tools = dict()
+ # Add in user specified msvs_settings.
+ msvs_settings = config.get('msvs_settings', {})
+ MSVSSettings.ValidateMSVSSettings(msvs_settings)
+
+ # Prevent default library inheritance from the environment.
+ _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', ['$(NOINHERIT)'])
+
+ for tool in msvs_settings:
+ settings = config['msvs_settings'][tool]
+ for setting in settings:
+ _ToolAppend(tools, tool, setting, settings[setting])
+ # Add the information to the appropriate tool
+ _ToolAppend(tools, 'VCCLCompilerTool',
+ 'AdditionalIncludeDirectories', include_dirs)
+ _ToolAppend(tools, 'VCResourceCompilerTool',
+ 'AdditionalIncludeDirectories', resource_include_dirs)
+ # Add in libraries.
+ _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', libraries)
+ _ToolAppend(tools, 'VCLinkerTool', 'AdditionalLibraryDirectories',
+ library_dirs)
+ if out_file:
+ _ToolAppend(tools, vc_tool, 'OutputFile', out_file, only_if_unset=True)
+ # Add defines.
+ _ToolAppend(tools, 'VCCLCompilerTool', 'PreprocessorDefinitions', defines)
+ _ToolAppend(tools, 'VCResourceCompilerTool', 'PreprocessorDefinitions',
+ defines)
+ # Change program database directory to prevent collisions.
+ _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName',
+ '$(IntDir)$(ProjectName)\\vc80.pdb', only_if_unset=True)
+ # Add disabled warnings.
+ _ToolAppend(tools, 'VCCLCompilerTool',
+ 'DisableSpecificWarnings', disabled_warnings)
+ # Add Pre-build.
+ _ToolAppend(tools, 'VCPreBuildEventTool', 'CommandLine', prebuild)
+ # Add Post-build.
+ _ToolAppend(tools, 'VCPostBuildEventTool', 'CommandLine', postbuild)
+ # Turn on precompiled headers if appropriate.
+ if precompiled_header:
+ precompiled_header = os.path.split(precompiled_header)[1]
+ _ToolAppend(tools, 'VCCLCompilerTool', 'UsePrecompiledHeader', '2')
+ _ToolAppend(tools, 'VCCLCompilerTool',
+ 'PrecompiledHeaderThrough', precompiled_header)
+ _ToolAppend(tools, 'VCCLCompilerTool',
+ 'ForcedIncludeFiles', precompiled_header)
+ # Loadable modules don't generate import libraries;
+ # tell dependent projects to not expect one.
+ if spec['type'] == 'loadable_module':
+ _ToolAppend(tools, 'VCLinkerTool', 'IgnoreImportLibrary', 'true')
+ # Set the module definition file if any.
+ if def_file:
+ _ToolAppend(tools, 'VCLinkerTool', 'ModuleDefinitionFile', def_file)
+
+ _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name)
+
+
+def _GetIncludeDirs(config):
+ """Returns the list of directories to be used for #include directives.
+
+ Arguments:
+ config: The dictionary that defines the special processing to be done
+ for this configuration.
+ Returns:
+ The list of directory paths.
+ """
+ # TODO(bradnelson): include_dirs should really be flexible enough not to
+ # require this sort of thing.
+ include_dirs = (
+ config.get('include_dirs', []) +
+ config.get('msvs_system_include_dirs', []))
+ resource_include_dirs = config.get('resource_include_dirs', include_dirs)
+ include_dirs = _FixPaths(include_dirs)
+ resource_include_dirs = _FixPaths(resource_include_dirs)
+ return include_dirs, resource_include_dirs
+
+
+def _GetLibraryDirs(config):
+ """Returns the list of directories to be used for library search paths.
+
+ Arguments:
+ config: The dictionary that defines the special processing to be done
+ for this configuration.
+ Returns:
+ The list of directory paths.
+ """
+
+ library_dirs = config.get('library_dirs', [])
+ library_dirs = _FixPaths(library_dirs)
+ return library_dirs
+
+
+def _GetLibraries(spec):
+ """Returns the list of libraries for this configuration.
+
+ Arguments:
+ spec: The target dictionary containing the properties of the target.
+ Returns:
+ The list of directory paths.
+ """
+ libraries = spec.get('libraries', [])
+ # Strip out -l, as it is not used on windows (but is needed so we can pass
+ # in libraries that are assumed to be in the default library path).
+ # Also remove duplicate entries, leaving only the last duplicate, while
+ # preserving order.
+ found = set()
+ unique_libraries_list = []
+ for entry in reversed(libraries):
+ library = re.sub('^\-l', '', entry)
+ if not os.path.splitext(library)[1]:
+ library += '.lib'
+ if library not in found:
+ found.add(library)
+ unique_libraries_list.append(library)
+ unique_libraries_list.reverse()
+ return unique_libraries_list
+
+
+def _GetOutputFilePathAndTool(spec, msbuild):
+ """Returns the path and tool to use for this target.
+
+ Figures out the path of the file this spec will create and the name of
+ the VC tool that will create it.
+
+ Arguments:
+ spec: The target dictionary containing the properties of the target.
+ Returns:
+ A triple of (file path, name of the vc tool, name of the msbuild tool)
+ """
+ # Select a name for the output file.
+ out_file = ''
+ vc_tool = ''
+ msbuild_tool = ''
+ output_file_map = {
+ 'executable': ('VCLinkerTool', 'Link', '$(OutDir)', '.exe'),
+ 'shared_library': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'),
+ 'loadable_module': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'),
+ 'static_library': ('VCLibrarianTool', 'Lib', '$(OutDir)lib\\', '.lib'),
+ }
+ output_file_props = output_file_map.get(spec['type'])
+ if output_file_props and int(spec.get('msvs_auto_output_file', 1)):
+ vc_tool, msbuild_tool, out_dir, suffix = output_file_props
+ if spec.get('standalone_static_library', 0):
+ out_dir = '$(OutDir)'
+ out_dir = spec.get('product_dir', out_dir)
+ product_extension = spec.get('product_extension')
+ if product_extension:
+ suffix = '.' + product_extension
+ elif msbuild:
+ suffix = '$(TargetExt)'
+ prefix = spec.get('product_prefix', '')
+ product_name = spec.get('product_name', '$(ProjectName)')
+ out_file = ntpath.join(out_dir, prefix + product_name + suffix)
+ return out_file, vc_tool, msbuild_tool
+
+
+def _GetDefines(config):
+ """Returns the list of preprocessor definitions for this configuation.
+
+ Arguments:
+ config: The dictionary that defines the special processing to be done
+ for this configuration.
+ Returns:
+ The list of preprocessor definitions.
+ """
+ defines = []
+ for d in config.get('defines', []):
+ if type(d) == list:
+ fd = '='.join([str(dpart) for dpart in d])
+ else:
+ fd = str(d)
+ defines.append(fd)
+ return defines
+
+
+def _GetDisabledWarnings(config):
+ return [str(i) for i in config.get('msvs_disabled_warnings', [])]
+
+
+def _GetModuleDefinition(spec):
+ def_file = ''
+ if spec['type'] in ['shared_library', 'loadable_module', 'executable']:
+ def_files = [s for s in spec.get('sources', []) if s.endswith('.def')]
+ if len(def_files) == 1:
+ def_file = _FixPath(def_files[0])
+ elif def_files:
+ raise ValueError(
+ 'Multiple module definition files in one target, target %s lists '
+ 'multiple .def files: %s' % (
+ spec['target_name'], ' '.join(def_files)))
+ return def_file
+
+
+def _ConvertToolsToExpectedForm(tools):
+ """Convert tools to a form expected by Visual Studio.
+
+ Arguments:
+ tools: A dictionary of settings; the tool name is the key.
+ Returns:
+ A list of Tool objects.
+ """
+ tool_list = []
+ for tool, settings in tools.iteritems():
+ # Collapse settings with lists.
+ settings_fixed = {}
+ for setting, value in settings.iteritems():
+ if type(value) == list:
+ if ((tool == 'VCLinkerTool' and
+ setting == 'AdditionalDependencies') or
+ setting == 'AdditionalOptions'):
+ settings_fixed[setting] = ' '.join(value)
+ else:
+ settings_fixed[setting] = ';'.join(value)
+ else:
+ settings_fixed[setting] = value
+ # Add in this tool.
+ tool_list.append(MSVSProject.Tool(tool, settings_fixed))
+ return tool_list
+
+
+def _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name):
+ """Add to the project file the configuration specified by config.
+
+ Arguments:
+ p: The target project being generated.
+ spec: the target project dict.
+ tools: A dictionary of settings; the tool name is the key.
+ config: The dictionary that defines the special processing to be done
+ for this configuration.
+ config_type: The configuration type, a number as defined by Microsoft.
+ config_name: The name of the configuration.
+ """
+ attributes = _GetMSVSAttributes(spec, config, config_type)
+ # Add in this configuration.
+ tool_list = _ConvertToolsToExpectedForm(tools)
+ p.AddConfig(_ConfigFullName(config_name, config),
+ attrs=attributes, tools=tool_list)
+
+
+def _GetMSVSAttributes(spec, config, config_type):
+ # Prepare configuration attributes.
+ prepared_attrs = {}
+ source_attrs = config.get('msvs_configuration_attributes', {})
+ for a in source_attrs:
+ prepared_attrs[a] = source_attrs[a]
+ # Add props files.
+ vsprops_dirs = config.get('msvs_props', [])
+ vsprops_dirs = _FixPaths(vsprops_dirs)
+ if vsprops_dirs:
+ prepared_attrs['InheritedPropertySheets'] = ';'.join(vsprops_dirs)
+ # Set configuration type.
+ prepared_attrs['ConfigurationType'] = config_type
+ output_dir = prepared_attrs.get('OutputDirectory',
+ '$(SolutionDir)$(ConfigurationName)')
+ prepared_attrs['OutputDirectory'] = _FixPath(output_dir) + '\\'
+ if 'IntermediateDirectory' not in prepared_attrs:
+ intermediate = '$(ConfigurationName)\\obj\\$(ProjectName)'
+ prepared_attrs['IntermediateDirectory'] = _FixPath(intermediate) + '\\'
+ else:
+ intermediate = _FixPath(prepared_attrs['IntermediateDirectory']) + '\\'
+ intermediate = MSVSSettings.FixVCMacroSlashes(intermediate)
+ prepared_attrs['IntermediateDirectory'] = intermediate
+ return prepared_attrs
+
+
+def _AddNormalizedSources(sources_set, sources_array):
+ sources = [_NormalizedSource(s) for s in sources_array]
+ sources_set.update(set(sources))
+
+
+def _PrepareListOfSources(spec, generator_flags, gyp_file):
+ """Prepare list of sources and excluded sources.
+
+ Besides the sources specified directly in the spec, adds the gyp file so
+ that a change to it will cause a re-compile. Also adds appropriate sources
+ for actions and copies. Assumes later stage will un-exclude files which
+ have custom build steps attached.
+
+ Arguments:
+ spec: The target dictionary containing the properties of the target.
+ gyp_file: The name of the gyp file.
+ Returns:
+ A pair of (list of sources, list of excluded sources).
+ The sources will be relative to the gyp file.
+ """
+ sources = set()
+ _AddNormalizedSources(sources, spec.get('sources', []))
+ excluded_sources = set()
+ # Add in the gyp file.
+ if not generator_flags.get('standalone'):
+ sources.add(gyp_file)
+
+ # Add in 'action' inputs and outputs.
+ for a in spec.get('actions', []):
+ inputs = a['inputs']
+ inputs = [_NormalizedSource(i) for i in inputs]
+ # Add all inputs to sources and excluded sources.
+ inputs = set(inputs)
+ sources.update(inputs)
+ if not spec.get('msvs_external_builder'):
+ excluded_sources.update(inputs)
+ if int(a.get('process_outputs_as_sources', False)):
+ _AddNormalizedSources(sources, a.get('outputs', []))
+ # Add in 'copies' inputs and outputs.
+ for cpy in spec.get('copies', []):
+ _AddNormalizedSources(sources, cpy.get('files', []))
+ return (sources, excluded_sources)
+
+
+def _AdjustSourcesAndConvertToFilterHierarchy(
+ spec, options, gyp_dir, sources, excluded_sources, list_excluded):
+ """Adjusts the list of sources and excluded sources.
+
+ Also converts the sets to lists.
+
+ Arguments:
+ spec: The target dictionary containing the properties of the target.
+ options: Global generator options.
+ gyp_dir: The path to the gyp file being processed.
+ sources: A set of sources to be included for this project.
+ excluded_sources: A set of sources to be excluded for this project.
+ Returns:
+ A trio of (list of sources, list of excluded sources,
+ path of excluded IDL file)
+ """
+ # Exclude excluded sources coming into the generator.
+ excluded_sources.update(set(spec.get('sources_excluded', [])))
+ # Add excluded sources into sources for good measure.
+ sources.update(excluded_sources)
+ # Convert to proper windows form.
+ # NOTE: sources goes from being a set to a list here.
+ # NOTE: excluded_sources goes from being a set to a list here.
+ sources = _FixPaths(sources)
+ # Convert to proper windows form.
+ excluded_sources = _FixPaths(excluded_sources)
+
+ excluded_idl = _IdlFilesHandledNonNatively(spec, sources)
+
+ precompiled_related = _GetPrecompileRelatedFiles(spec)
+ # Find the excluded ones, minus the precompiled header related ones.
+ fully_excluded = [i for i in excluded_sources if i not in precompiled_related]
+
+ # Convert to folders and the right slashes.
+ sources = [i.split('\\') for i in sources]
+ sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded,
+ list_excluded=list_excluded)
+
+ return sources, excluded_sources, excluded_idl
+
+
+def _IdlFilesHandledNonNatively(spec, sources):
+ # If any non-native rules use 'idl' as an extension exclude idl files.
+ # Gather a list here to use later.
+ using_idl = False
+ for rule in spec.get('rules', []):
+ if rule['extension'] == 'idl' and int(rule.get('msvs_external_rule', 0)):
+ using_idl = True
+ break
+ if using_idl:
+ excluded_idl = [i for i in sources if i.endswith('.idl')]
+ else:
+ excluded_idl = []
+ return excluded_idl
+
+
+def _GetPrecompileRelatedFiles(spec):
+ # Gather a list of precompiled header related sources.
+ precompiled_related = []
+ for _, config in spec['configurations'].iteritems():
+ for k in precomp_keys:
+ f = config.get(k)
+ if f:
+ precompiled_related.append(_FixPath(f))
+ return precompiled_related
+
+
+def _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl,
+ list_excluded):
+ exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl)
+ for file_name, excluded_configs in exclusions.iteritems():
+ if (not list_excluded and
+ len(excluded_configs) == len(spec['configurations'])):
+ # If we're not listing excluded files, then they won't appear in the
+ # project, so don't try to configure them to be excluded.
+ pass
+ else:
+ for config_name, config in excluded_configs:
+ p.AddFileConfig(file_name, _ConfigFullName(config_name, config),
+ {'ExcludedFromBuild': 'true'})
+
+
+def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl):
+ exclusions = {}
+ # Exclude excluded sources from being built.
+ for f in excluded_sources:
+ excluded_configs = []
+ for config_name, config in spec['configurations'].iteritems():
+ precomped = [_FixPath(config.get(i, '')) for i in precomp_keys]
+ # Don't do this for ones that are precompiled header related.
+ if f not in precomped:
+ excluded_configs.append((config_name, config))
+ exclusions[f] = excluded_configs
+ # If any non-native rules use 'idl' as an extension exclude idl files.
+ # Exclude them now.
+ for f in excluded_idl:
+ excluded_configs = []
+ for config_name, config in spec['configurations'].iteritems():
+ excluded_configs.append((config_name, config))
+ exclusions[f] = excluded_configs
+ return exclusions
+
+
+def _AddToolFilesToMSVS(p, spec):
+ # Add in tool files (rules).
+ tool_files = set()
+ for _, config in spec['configurations'].iteritems():
+ for f in config.get('msvs_tool_files', []):
+ tool_files.add(f)
+ for f in tool_files:
+ p.AddToolFile(f)
+
+
+def _HandlePreCompiledHeaders(p, sources, spec):
+ # Pre-compiled header source stubs need a different compiler flag
+ # (generate precompiled header) and any source file not of the same
+ # kind (i.e. C vs. C++) as the precompiled header source stub needs
+ # to have use of precompiled headers disabled.
+ extensions_excluded_from_precompile = []
+ for config_name, config in spec['configurations'].iteritems():
+ source = config.get('msvs_precompiled_source')
+ if source:
+ source = _FixPath(source)
+ # UsePrecompiledHeader=1 for if using precompiled headers.
+ tool = MSVSProject.Tool('VCCLCompilerTool',
+ {'UsePrecompiledHeader': '1'})
+ p.AddFileConfig(source, _ConfigFullName(config_name, config),
+ {}, tools=[tool])
+ basename, extension = os.path.splitext(source)
+ if extension == '.c':
+ extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx']
+ else:
+ extensions_excluded_from_precompile = ['.c']
+ def DisableForSourceTree(source_tree):
+ for source in source_tree:
+ if isinstance(source, MSVSProject.Filter):
+ DisableForSourceTree(source.contents)
+ else:
+ basename, extension = os.path.splitext(source)
+ if extension in extensions_excluded_from_precompile:
+ for config_name, config in spec['configurations'].iteritems():
+ tool = MSVSProject.Tool('VCCLCompilerTool',
+ {'UsePrecompiledHeader': '0',
+ 'ForcedIncludeFiles': '$(NOINHERIT)'})
+ p.AddFileConfig(_FixPath(source),
+ _ConfigFullName(config_name, config),
+ {}, tools=[tool])
+ # Do nothing if there was no precompiled source.
+ if extensions_excluded_from_precompile:
+ DisableForSourceTree(sources)
+
+
+def _AddActions(actions_to_add, spec, relative_path_of_gyp_file):
+ # Add actions.
+ actions = spec.get('actions', [])
+ # Don't setup_env every time. When all the actions are run together in one
+ # batch file in VS, the PATH will grow too long.
+ # Membership in this set means that the cygwin environment has been set up,
+ # and does not need to be set up again.
+ have_setup_env = set()
+ for a in actions:
+ # Attach actions to the gyp file if nothing else is there.
+ inputs = a.get('inputs') or [relative_path_of_gyp_file]
+ attached_to = inputs[0]
+ need_setup_env = attached_to not in have_setup_env
+ cmd = _BuildCommandLineForRule(spec, a, has_input_path=False,
+ do_setup_env=need_setup_env)
+ have_setup_env.add(attached_to)
+ # Add the action.
+ _AddActionStep(actions_to_add,
+ inputs=inputs,
+ outputs=a.get('outputs', []),
+ description=a.get('message', a['action_name']),
+ command=cmd)
+
+
+def _WriteMSVSUserFile(project_path, version, spec):
+ # Add run_as and test targets.
+ if 'run_as' in spec:
+ run_as = spec['run_as']
+ action = run_as.get('action', [])
+ environment = run_as.get('environment', [])
+ working_directory = run_as.get('working_directory', '.')
+ elif int(spec.get('test', 0)):
+ action = ['$(TargetPath)', '--gtest_print_time']
+ environment = []
+ working_directory = '.'
+ else:
+ return # Nothing to add
+ # Write out the user file.
+ user_file = _CreateMSVSUserFile(project_path, version, spec)
+ for config_name, c_data in spec['configurations'].iteritems():
+ user_file.AddDebugSettings(_ConfigFullName(config_name, c_data),
+ action, environment, working_directory)
+ user_file.WriteIfChanged()
+
+
+def _AddCopies(actions_to_add, spec):
+ copies = _GetCopies(spec)
+ for inputs, outputs, cmd, description in copies:
+ _AddActionStep(actions_to_add, inputs=inputs, outputs=outputs,
+ description=description, command=cmd)
+
+
+def _GetCopies(spec):
+ copies = []
+ # Add copies.
+ for cpy in spec.get('copies', []):
+ for src in cpy.get('files', []):
+ dst = os.path.join(cpy['destination'], os.path.basename(src))
+ # _AddCustomBuildToolForMSVS() will call _FixPath() on the inputs and
+ # outputs, so do the same for our generated command line.
+ if src.endswith('/'):
+ src_bare = src[:-1]
+ base_dir = posixpath.split(src_bare)[0]
+ outer_dir = posixpath.split(src_bare)[1]
+ cmd = 'cd "%s" && xcopy /e /f /y "%s" "%s\\%s\\"' % (
+ _FixPath(base_dir), outer_dir, _FixPath(dst), outer_dir)
+ copies.append(([src], ['dummy_copies', dst], cmd,
+ 'Copying %s to %s' % (src, dst)))
+ else:
+ cmd = 'mkdir "%s" 2>nul & set ERRORLEVEL=0 & copy /Y "%s" "%s"' % (
+ _FixPath(cpy['destination']), _FixPath(src), _FixPath(dst))
+ copies.append(([src], [dst], cmd, 'Copying %s to %s' % (src, dst)))
+ return copies
+
+
+def _GetPathDict(root, path):
+ # |path| will eventually be empty (in the recursive calls) if it was initially
+ # relative; otherwise it will eventually end up as '\', 'D:\', etc.
+ if not path or path.endswith(os.sep):
+ return root
+ parent, folder = os.path.split(path)
+ parent_dict = _GetPathDict(root, parent)
+ if folder not in parent_dict:
+ parent_dict[folder] = dict()
+ return parent_dict[folder]
+
+
+def _DictsToFolders(base_path, bucket, flat):
+ # Convert to folders recursively.
+ children = []
+ for folder, contents in bucket.iteritems():
+ if type(contents) == dict:
+ folder_children = _DictsToFolders(os.path.join(base_path, folder),
+ contents, flat)
+ if flat:
+ children += folder_children
+ else:
+ folder_children = MSVSNew.MSVSFolder(os.path.join(base_path, folder),
+ name='(' + folder + ')',
+ entries=folder_children)
+ children.append(folder_children)
+ else:
+ children.append(contents)
+ return children
+
+
+def _CollapseSingles(parent, node):
+ # Recursively explorer the tree of dicts looking for projects which are
+ # the sole item in a folder which has the same name as the project. Bring
+ # such projects up one level.
+ if (type(node) == dict and
+ len(node) == 1 and
+ node.keys()[0] == parent + '.vcproj'):
+ return node[node.keys()[0]]
+ if type(node) != dict:
+ return node
+ for child in node:
+ node[child] = _CollapseSingles(child, node[child])
+ return node
+
+
+def _GatherSolutionFolders(sln_projects, project_objects, flat):
+ root = {}
+ # Convert into a tree of dicts on path.
+ for p in sln_projects:
+ gyp_file, target = gyp.common.ParseQualifiedTarget(p)[0:2]
+ gyp_dir = os.path.dirname(gyp_file)
+ path_dict = _GetPathDict(root, gyp_dir)
+ path_dict[target + '.vcproj'] = project_objects[p]
+ # Walk down from the top until we hit a folder that has more than one entry.
+ # In practice, this strips the top-level "src/" dir from the hierarchy in
+ # the solution.
+ while len(root) == 1 and type(root[root.keys()[0]]) == dict:
+ root = root[root.keys()[0]]
+ # Collapse singles.
+ root = _CollapseSingles('', root)
+ # Merge buckets until everything is a root entry.
+ return _DictsToFolders('', root, flat)
+
+
+def _GetPathOfProject(qualified_target, spec, options, msvs_version):
+ default_config = _GetDefaultConfiguration(spec)
+ proj_filename = default_config.get('msvs_existing_vcproj')
+ if not proj_filename:
+ proj_filename = (spec['target_name'] + options.suffix +
+ msvs_version.ProjectExtension())
+
+ build_file = gyp.common.BuildFile(qualified_target)
+ proj_path = os.path.join(os.path.dirname(build_file), proj_filename)
+ fix_prefix = None
+ if options.generator_output:
+ project_dir_path = os.path.dirname(os.path.abspath(proj_path))
+ proj_path = os.path.join(options.generator_output, proj_path)
+ fix_prefix = gyp.common.RelativePath(project_dir_path,
+ os.path.dirname(proj_path))
+ return proj_path, fix_prefix
+
+
+def _GetPlatformOverridesOfProject(spec):
+ # Prepare a dict indicating which project configurations are used for which
+ # solution configurations for this target.
+ config_platform_overrides = {}
+ for config_name, c in spec['configurations'].iteritems():
+ config_fullname = _ConfigFullName(config_name, c)
+ platform = c.get('msvs_target_platform', _ConfigPlatform(c))
+ fixed_config_fullname = '%s|%s' % (
+ _ConfigBaseName(config_name, _ConfigPlatform(c)), platform)
+ config_platform_overrides[config_fullname] = fixed_config_fullname
+ return config_platform_overrides
+
+
+def _CreateProjectObjects(target_list, target_dicts, options, msvs_version):
+ """Create a MSVSProject object for the targets found in target list.
+
+ Arguments:
+ target_list: the list of targets to generate project objects for.
+ target_dicts: the dictionary of specifications.
+ options: global generator options.
+ msvs_version: the MSVSVersion object.
+ Returns:
+ A set of created projects, keyed by target.
+ """
+ global fixpath_prefix
+ # Generate each project.
+ projects = {}
+ for qualified_target in target_list:
+ spec = target_dicts[qualified_target]
+ if spec['toolset'] != 'target':
+ raise GypError(
+ 'Multiple toolsets not supported in msvs build (target %s)' %
+ qualified_target)
+ proj_path, fixpath_prefix = _GetPathOfProject(qualified_target, spec,
+ options, msvs_version)
+ guid = _GetGuidOfProject(proj_path, spec)
+ overrides = _GetPlatformOverridesOfProject(spec)
+ build_file = gyp.common.BuildFile(qualified_target)
+ # Create object for this project.
+ obj = MSVSNew.MSVSProject(
+ proj_path,
+ name=spec['target_name'],
+ guid=guid,
+ spec=spec,
+ build_file=build_file,
+ config_platform_overrides=overrides,
+ fixpath_prefix=fixpath_prefix)
+ # Set project toolset if any (MS build only)
+ if msvs_version.UsesVcxproj():
+ obj.set_msbuild_toolset(
+ _GetMsbuildToolsetOfProject(proj_path, spec, msvs_version))
+ projects[qualified_target] = obj
+ # Set all the dependencies, but not if we are using an external builder like
+ # ninja
+ for project in projects.values():
+ if not project.spec.get('msvs_external_builder'):
+ deps = project.spec.get('dependencies', [])
+ deps = [projects[d] for d in deps]
+ project.set_dependencies(deps)
+ return projects
+
+
+def _InitNinjaFlavor(options, target_list, target_dicts):
+ """Initialize targets for the ninja flavor.
+
+ This sets up the necessary variables in the targets to generate msvs projects
+ that use ninja as an external builder. The variables in the spec are only set
+ if they have not been set. This allows individual specs to override the
+ default values initialized here.
+ Arguments:
+ options: Options provided to the generator.
+ target_list: List of target pairs: 'base/base.gyp:base'.
+ target_dicts: Dict of target properties keyed on target pair.
+ """
+ for qualified_target in target_list:
+ spec = target_dicts[qualified_target]
+ if spec.get('msvs_external_builder'):
+ # The spec explicitly defined an external builder, so don't change it.
+ continue
+
+ path_to_ninja = spec.get('msvs_path_to_ninja', 'ninja.exe')
+
+ spec['msvs_external_builder'] = 'ninja'
+ if not spec.get('msvs_external_builder_out_dir'):
+ spec['msvs_external_builder_out_dir'] = \
+ options.depth + '/out/$(Configuration)'
+ if not spec.get('msvs_external_builder_build_cmd'):
+ spec['msvs_external_builder_build_cmd'] = [
+ path_to_ninja,
+ '-C',
+ '$(OutDir)',
+ '$(ProjectName)',
+ ]
+ if not spec.get('msvs_external_builder_clean_cmd'):
+ spec['msvs_external_builder_clean_cmd'] = [
+ path_to_ninja,
+ '-C',
+ '$(OutDir)',
+ '-t',
+ 'clean',
+ '$(ProjectName)',
+ ]
+
+
+def CalculateVariables(default_variables, params):
+ """Generated variables that require params to be known."""
+
+ generator_flags = params.get('generator_flags', {})
+
+ # Select project file format version (if unset, default to auto detecting).
+ msvs_version = MSVSVersion.SelectVisualStudioVersion(
+ generator_flags.get('msvs_version', 'auto'))
+ # Stash msvs_version for later (so we don't have to probe the system twice).
+ params['msvs_version'] = msvs_version
+
+ # Set a variable so conditions can be based on msvs_version.
+ default_variables['MSVS_VERSION'] = msvs_version.ShortName()
+
+ # To determine processor word size on Windows, in addition to checking
+ # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
+ # process), it is also necessary to check PROCESSOR_ARCITEW6432 (which
+ # contains the actual word size of the system when running thru WOW64).
+ if (os.environ.get('PROCESSOR_ARCHITECTURE', '').find('64') >= 0 or
+ os.environ.get('PROCESSOR_ARCHITEW6432', '').find('64') >= 0):
+ default_variables['MSVS_OS_BITS'] = 64
+ else:
+ default_variables['MSVS_OS_BITS'] = 32
+
+ if gyp.common.GetFlavor(params) == 'ninja':
+ default_variables['SHARED_INTERMEDIATE_DIR'] = '$(OutDir)gen'
+
+
+def PerformBuild(data, configurations, params):
+ options = params['options']
+ msvs_version = params['msvs_version']
+ devenv = os.path.join(msvs_version.path, 'Common7', 'IDE', 'devenv.com')
+
+ for build_file, build_file_dict in data.iteritems():
+ (build_file_root, build_file_ext) = os.path.splitext(build_file)
+ if build_file_ext != '.gyp':
+ continue
+ sln_path = build_file_root + options.suffix + '.sln'
+ if options.generator_output:
+ sln_path = os.path.join(options.generator_output, sln_path)
+
+ for config in configurations:
+ arguments = [devenv, sln_path, '/Build', config]
+ print 'Building [%s]: %s' % (config, arguments)
+ rtn = subprocess.check_call(arguments)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ """Generate .sln and .vcproj files.
+
+ This is the entry point for this generator.
+ Arguments:
+ target_list: List of target pairs: 'base/base.gyp:base'.
+ target_dicts: Dict of target properties keyed on target pair.
+ data: Dictionary containing per .gyp data.
+ """
+ global fixpath_prefix
+
+ options = params['options']
+
+ # Get the project file format version back out of where we stashed it in
+ # GeneratorCalculatedVariables.
+ msvs_version = params['msvs_version']
+
+ generator_flags = params.get('generator_flags', {})
+
+ # Optionally shard targets marked with 'msvs_shard': SHARD_COUNT.
+ (target_list, target_dicts) = MSVSUtil.ShardTargets(target_list, target_dicts)
+
+ # Optionally use the large PDB workaround for targets marked with
+ # 'msvs_large_pdb': 1.
+ (target_list, target_dicts) = MSVSUtil.InsertLargePdbShims(
+ target_list, target_dicts, generator_default_variables)
+
+ # Optionally configure each spec to use ninja as the external builder.
+ if params.get('flavor') == 'ninja':
+ _InitNinjaFlavor(options, target_list, target_dicts)
+
+ # Prepare the set of configurations.
+ configs = set()
+ for qualified_target in target_list:
+ spec = target_dicts[qualified_target]
+ for config_name, config in spec['configurations'].iteritems():
+ configs.add(_ConfigFullName(config_name, config))
+ configs = list(configs)
+
+ # Figure out all the projects that will be generated and their guids
+ project_objects = _CreateProjectObjects(target_list, target_dicts, options,
+ msvs_version)
+
+ # Generate each project.
+ missing_sources = []
+ for project in project_objects.values():
+ fixpath_prefix = project.fixpath_prefix
+ missing_sources.extend(_GenerateProject(project, options, msvs_version,
+ generator_flags))
+ fixpath_prefix = None
+
+ for build_file in data:
+ # Validate build_file extension
+ if not build_file.endswith('.gyp'):
+ continue
+ sln_path = os.path.splitext(build_file)[0] + options.suffix + '.sln'
+ if options.generator_output:
+ sln_path = os.path.join(options.generator_output, sln_path)
+ # Get projects in the solution, and their dependents.
+ sln_projects = gyp.common.BuildFileTargets(target_list, build_file)
+ sln_projects += gyp.common.DeepDependencyTargets(target_dicts, sln_projects)
+ # Create folder hierarchy.
+ root_entries = _GatherSolutionFolders(
+ sln_projects, project_objects, flat=msvs_version.FlatSolution())
+ # Create solution.
+ sln = MSVSNew.MSVSSolution(sln_path,
+ entries=root_entries,
+ variants=configs,
+ websiteProperties=False,
+ version=msvs_version)
+ sln.Write()
+
+ if missing_sources:
+ error_message = "Missing input files:\n" + \
+ '\n'.join(set(missing_sources))
+ if generator_flags.get('msvs_error_on_missing_sources', False):
+ raise GypError(error_message)
+ else:
+ print >> sys.stdout, "Warning: " + error_message
+
+
+def _GenerateMSBuildFiltersFile(filters_path, source_files,
+ extension_to_rule_name):
+ """Generate the filters file.
+
+ This file is used by Visual Studio to organize the presentation of source
+ files into folders.
+
+ Arguments:
+ filters_path: The path of the file to be created.
+ source_files: The hierarchical structure of all the sources.
+ extension_to_rule_name: A dictionary mapping file extensions to rules.
+ """
+ filter_group = []
+ source_group = []
+ _AppendFiltersForMSBuild('', source_files, extension_to_rule_name,
+ filter_group, source_group)
+ if filter_group:
+ content = ['Project',
+ {'ToolsVersion': '4.0',
+ 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'
+ },
+ ['ItemGroup'] + filter_group,
+ ['ItemGroup'] + source_group
+ ]
+ easy_xml.WriteXmlIfChanged(content, filters_path, pretty=True, win32=True)
+ elif os.path.exists(filters_path):
+ # We don't need this filter anymore. Delete the old filter file.
+ os.unlink(filters_path)
+
+
+def _AppendFiltersForMSBuild(parent_filter_name, sources,
+ extension_to_rule_name,
+ filter_group, source_group):
+ """Creates the list of filters and sources to be added in the filter file.
+
+ Args:
+ parent_filter_name: The name of the filter under which the sources are
+ found.
+ sources: The hierarchy of filters and sources to process.
+ extension_to_rule_name: A dictionary mapping file extensions to rules.
+ filter_group: The list to which filter entries will be appended.
+ source_group: The list to which source entries will be appeneded.
+ """
+ for source in sources:
+ if isinstance(source, MSVSProject.Filter):
+ # We have a sub-filter. Create the name of that sub-filter.
+ if not parent_filter_name:
+ filter_name = source.name
+ else:
+ filter_name = '%s\\%s' % (parent_filter_name, source.name)
+ # Add the filter to the group.
+ filter_group.append(
+ ['Filter', {'Include': filter_name},
+ ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]])
+ # Recurse and add its dependents.
+ _AppendFiltersForMSBuild(filter_name, source.contents,
+ extension_to_rule_name,
+ filter_group, source_group)
+ else:
+ # It's a source. Create a source entry.
+ _, element = _MapFileToMsBuildSourceType(source, extension_to_rule_name)
+ source_entry = [element, {'Include': source}]
+ # Specify the filter it is part of, if any.
+ if parent_filter_name:
+ source_entry.append(['Filter', parent_filter_name])
+ source_group.append(source_entry)
+
+
+def _MapFileToMsBuildSourceType(source, extension_to_rule_name):
+ """Returns the group and element type of the source file.
+
+ Arguments:
+ source: The source file name.
+ extension_to_rule_name: A dictionary mapping file extensions to rules.
+
+ Returns:
+ A pair of (group this file should be part of, the label of element)
+ """
+ _, ext = os.path.splitext(source)
+ if ext in extension_to_rule_name:
+ group = 'rule'
+ element = extension_to_rule_name[ext]
+ elif ext in ['.cc', '.cpp', '.c', '.cxx']:
+ group = 'compile'
+ element = 'ClCompile'
+ elif ext in ['.h', '.hxx']:
+ group = 'include'
+ element = 'ClInclude'
+ elif ext == '.rc':
+ group = 'resource'
+ element = 'ResourceCompile'
+ elif ext == '.idl':
+ group = 'midl'
+ element = 'Midl'
+ else:
+ group = 'none'
+ element = 'None'
+ return (group, element)
+
+
+def _GenerateRulesForMSBuild(output_dir, options, spec,
+ sources, excluded_sources,
+ props_files_of_rules, targets_files_of_rules,
+ actions_to_add, extension_to_rule_name):
+ # MSBuild rules are implemented using three files: an XML file, a .targets
+ # file and a .props file.
+ # See http://blogs.msdn.com/b/vcblog/archive/2010/04/21/quick-help-on-vs2010-custom-build-rule.aspx
+ # for more details.
+ rules = spec.get('rules', [])
+ rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))]
+ rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))]
+
+ msbuild_rules = []
+ for rule in rules_native:
+ # Skip a rule with no action and no inputs.
+ if 'action' not in rule and not rule.get('rule_sources', []):
+ continue
+ msbuild_rule = MSBuildRule(rule, spec)
+ msbuild_rules.append(msbuild_rule)
+ extension_to_rule_name[msbuild_rule.extension] = msbuild_rule.rule_name
+ if msbuild_rules:
+ base = spec['target_name'] + options.suffix
+ props_name = base + '.props'
+ targets_name = base + '.targets'
+ xml_name = base + '.xml'
+
+ props_files_of_rules.add(props_name)
+ targets_files_of_rules.add(targets_name)
+
+ props_path = os.path.join(output_dir, props_name)
+ targets_path = os.path.join(output_dir, targets_name)
+ xml_path = os.path.join(output_dir, xml_name)
+
+ _GenerateMSBuildRulePropsFile(props_path, msbuild_rules)
+ _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules)
+ _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules)
+
+ if rules_external:
+ _GenerateExternalRules(rules_external, output_dir, spec,
+ sources, options, actions_to_add)
+ _AdjustSourcesForRules(spec, rules, sources, excluded_sources)
+
+
+class MSBuildRule(object):
+ """Used to store information used to generate an MSBuild rule.
+
+ Attributes:
+ rule_name: The rule name, sanitized to use in XML.
+ target_name: The name of the target.
+ after_targets: The name of the AfterTargets element.
+ before_targets: The name of the BeforeTargets element.
+ depends_on: The name of the DependsOn element.
+ compute_output: The name of the ComputeOutput element.
+ dirs_to_make: The name of the DirsToMake element.
+ inputs: The name of the _inputs element.
+ tlog: The name of the _tlog element.
+ extension: The extension this rule applies to.
+ description: The message displayed when this rule is invoked.
+ additional_dependencies: A string listing additional dependencies.
+ outputs: The outputs of this rule.
+ command: The command used to run the rule.
+ """
+
+ def __init__(self, rule, spec):
+ self.display_name = rule['rule_name']
+ # Assure that the rule name is only characters and numbers
+ self.rule_name = re.sub(r'\W', '_', self.display_name)
+ # Create the various element names, following the example set by the
+ # Visual Studio 2008 to 2010 conversion. I don't know if VS2010
+ # is sensitive to the exact names.
+ self.target_name = '_' + self.rule_name
+ self.after_targets = self.rule_name + 'AfterTargets'
+ self.before_targets = self.rule_name + 'BeforeTargets'
+ self.depends_on = self.rule_name + 'DependsOn'
+ self.compute_output = 'Compute%sOutput' % self.rule_name
+ self.dirs_to_make = self.rule_name + 'DirsToMake'
+ self.inputs = self.rule_name + '_inputs'
+ self.tlog = self.rule_name + '_tlog'
+ self.extension = rule['extension']
+ if not self.extension.startswith('.'):
+ self.extension = '.' + self.extension
+
+ self.description = MSVSSettings.ConvertVCMacrosToMSBuild(
+ rule.get('message', self.rule_name))
+ old_additional_dependencies = _FixPaths(rule.get('inputs', []))
+ self.additional_dependencies = (
+ ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i)
+ for i in old_additional_dependencies]))
+ old_outputs = _FixPaths(rule.get('outputs', []))
+ self.outputs = ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i)
+ for i in old_outputs])
+ old_command = _BuildCommandLineForRule(spec, rule, has_input_path=True,
+ do_setup_env=True)
+ self.command = MSVSSettings.ConvertVCMacrosToMSBuild(old_command)
+
+
+def _GenerateMSBuildRulePropsFile(props_path, msbuild_rules):
+ """Generate the .props file."""
+ content = ['Project',
+ {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}]
+ for rule in msbuild_rules:
+ content.extend([
+ ['PropertyGroup',
+ {'Condition': "'$(%s)' == '' and '$(%s)' == '' and "
+ "'$(ConfigurationType)' != 'Makefile'" % (rule.before_targets,
+ rule.after_targets)
+ },
+ [rule.before_targets, 'Midl'],
+ [rule.after_targets, 'CustomBuild'],
+ ],
+ ['PropertyGroup',
+ [rule.depends_on,
+ {'Condition': "'$(ConfigurationType)' != 'Makefile'"},
+ '_SelectedFiles;$(%s)' % rule.depends_on
+ ],
+ ],
+ ['ItemDefinitionGroup',
+ [rule.rule_name,
+ ['CommandLineTemplate', rule.command],
+ ['Outputs', rule.outputs],
+ ['ExecutionDescription', rule.description],
+ ['AdditionalDependencies', rule.additional_dependencies],
+ ],
+ ]
+ ])
+ easy_xml.WriteXmlIfChanged(content, props_path, pretty=True, win32=True)
+
+
+def _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules):
+ """Generate the .targets file."""
+ content = ['Project',
+ {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'
+ }
+ ]
+ item_group = [
+ 'ItemGroup',
+ ['PropertyPageSchema',
+ {'Include': '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'}
+ ]
+ ]
+ for rule in msbuild_rules:
+ item_group.append(
+ ['AvailableItemName',
+ {'Include': rule.rule_name},
+ ['Targets', rule.target_name],
+ ])
+ content.append(item_group)
+
+ for rule in msbuild_rules:
+ content.append(
+ ['UsingTask',
+ {'TaskName': rule.rule_name,
+ 'TaskFactory': 'XamlTaskFactory',
+ 'AssemblyName': 'Microsoft.Build.Tasks.v4.0'
+ },
+ ['Task', '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'],
+ ])
+ for rule in msbuild_rules:
+ rule_name = rule.rule_name
+ target_outputs = '%%(%s.Outputs)' % rule_name
+ target_inputs = ('%%(%s.Identity);%%(%s.AdditionalDependencies);'
+ '$(MSBuildProjectFile)') % (rule_name, rule_name)
+ rule_inputs = '%%(%s.Identity)' % rule_name
+ extension_condition = ("'%(Extension)'=='.obj' or "
+ "'%(Extension)'=='.res' or "
+ "'%(Extension)'=='.rsc' or "
+ "'%(Extension)'=='.lib'")
+ remove_section = [
+ 'ItemGroup',
+ {'Condition': "'@(SelectedFiles)' != ''"},
+ [rule_name,
+ {'Remove': '@(%s)' % rule_name,
+ 'Condition': "'%(Identity)' != '@(SelectedFiles)'"
+ }
+ ]
+ ]
+ inputs_section = [
+ 'ItemGroup',
+ [rule.inputs, {'Include': '%%(%s.AdditionalDependencies)' % rule_name}]
+ ]
+ logging_section = [
+ 'ItemGroup',
+ [rule.tlog,
+ {'Include': '%%(%s.Outputs)' % rule_name,
+ 'Condition': ("'%%(%s.Outputs)' != '' and "
+ "'%%(%s.ExcludedFromBuild)' != 'true'" %
+ (rule_name, rule_name))
+ },
+ ['Source', "@(%s, '|')" % rule_name],
+ ['Inputs', "@(%s -> '%%(Fullpath)', ';')" % rule.inputs],
+ ],
+ ]
+ message_section = [
+ 'Message',
+ {'Importance': 'High',
+ 'Text': '%%(%s.ExecutionDescription)' % rule_name
+ }
+ ]
+ write_tlog_section = [
+ 'WriteLinesToFile',
+ {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
+ "'true'" % (rule.tlog, rule.tlog),
+ 'File': '$(IntDir)$(ProjectName).write.1.tlog',
+ 'Lines': "^%%(%s.Source);@(%s->'%%(Fullpath)')" % (rule.tlog,
+ rule.tlog)
+ }
+ ]
+ read_tlog_section = [
+ 'WriteLinesToFile',
+ {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
+ "'true'" % (rule.tlog, rule.tlog),
+ 'File': '$(IntDir)$(ProjectName).read.1.tlog',
+ 'Lines': "^%%(%s.Source);%%(%s.Inputs)" % (rule.tlog, rule.tlog)
+ }
+ ]
+ command_and_input_section = [
+ rule_name,
+ {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
+ "'true'" % (rule_name, rule_name),
+ 'CommandLineTemplate': '%%(%s.CommandLineTemplate)' % rule_name,
+ 'AdditionalOptions': '%%(%s.AdditionalOptions)' % rule_name,
+ 'Inputs': rule_inputs
+ }
+ ]
+ content.extend([
+ ['Target',
+ {'Name': rule.target_name,
+ 'BeforeTargets': '$(%s)' % rule.before_targets,
+ 'AfterTargets': '$(%s)' % rule.after_targets,
+ 'Condition': "'@(%s)' != ''" % rule_name,
+ 'DependsOnTargets': '$(%s);%s' % (rule.depends_on,
+ rule.compute_output),
+ 'Outputs': target_outputs,
+ 'Inputs': target_inputs
+ },
+ remove_section,
+ inputs_section,
+ logging_section,
+ message_section,
+ write_tlog_section,
+ read_tlog_section,
+ command_and_input_section,
+ ],
+ ['PropertyGroup',
+ ['ComputeLinkInputsTargets',
+ '$(ComputeLinkInputsTargets);',
+ '%s;' % rule.compute_output
+ ],
+ ['ComputeLibInputsTargets',
+ '$(ComputeLibInputsTargets);',
+ '%s;' % rule.compute_output
+ ],
+ ],
+ ['Target',
+ {'Name': rule.compute_output,
+ 'Condition': "'@(%s)' != ''" % rule_name
+ },
+ ['ItemGroup',
+ [rule.dirs_to_make,
+ {'Condition': "'@(%s)' != '' and "
+ "'%%(%s.ExcludedFromBuild)' != 'true'" % (rule_name, rule_name),
+ 'Include': '%%(%s.Outputs)' % rule_name
+ }
+ ],
+ ['Link',
+ {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
+ 'Condition': extension_condition
+ }
+ ],
+ ['Lib',
+ {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
+ 'Condition': extension_condition
+ }
+ ],
+ ['ImpLib',
+ {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
+ 'Condition': extension_condition
+ }
+ ],
+ ],
+ ['MakeDir',
+ {'Directories': ("@(%s->'%%(RootDir)%%(Directory)')" %
+ rule.dirs_to_make)
+ }
+ ]
+ ],
+ ])
+ easy_xml.WriteXmlIfChanged(content, targets_path, pretty=True, win32=True)
+
+
+def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules):
+ # Generate the .xml file
+ content = [
+ 'ProjectSchemaDefinitions',
+ {'xmlns': ('clr-namespace:Microsoft.Build.Framework.XamlTypes;'
+ 'assembly=Microsoft.Build.Framework'),
+ 'xmlns:x': 'http://schemas.microsoft.com/winfx/2006/xaml',
+ 'xmlns:sys': 'clr-namespace:System;assembly=mscorlib',
+ 'xmlns:transformCallback':
+ 'Microsoft.Cpp.Dev10.ConvertPropertyCallback'
+ }
+ ]
+ for rule in msbuild_rules:
+ content.extend([
+ ['Rule',
+ {'Name': rule.rule_name,
+ 'PageTemplate': 'tool',
+ 'DisplayName': rule.display_name,
+ 'Order': '200'
+ },
+ ['Rule.DataSource',
+ ['DataSource',
+ {'Persistence': 'ProjectFile',
+ 'ItemType': rule.rule_name
+ }
+ ]
+ ],
+ ['Rule.Categories',
+ ['Category',
+ {'Name': 'General'},
+ ['Category.DisplayName',
+ ['sys:String', 'General'],
+ ],
+ ],
+ ['Category',
+ {'Name': 'Command Line',
+ 'Subtype': 'CommandLine'
+ },
+ ['Category.DisplayName',
+ ['sys:String', 'Command Line'],
+ ],
+ ],
+ ],
+ ['StringListProperty',
+ {'Name': 'Inputs',
+ 'Category': 'Command Line',
+ 'IsRequired': 'true',
+ 'Switch': ' '
+ },
+ ['StringListProperty.DataSource',
+ ['DataSource',
+ {'Persistence': 'ProjectFile',
+ 'ItemType': rule.rule_name,
+ 'SourceType': 'Item'
+ }
+ ]
+ ],
+ ],
+ ['StringProperty',
+ {'Name': 'CommandLineTemplate',
+ 'DisplayName': 'Command Line',
+ 'Visible': 'False',
+ 'IncludeInCommandLine': 'False'
+ }
+ ],
+ ['DynamicEnumProperty',
+ {'Name': rule.before_targets,
+ 'Category': 'General',
+ 'EnumProvider': 'Targets',
+ 'IncludeInCommandLine': 'False'
+ },
+ ['DynamicEnumProperty.DisplayName',
+ ['sys:String', 'Execute Before'],
+ ],
+ ['DynamicEnumProperty.Description',
+ ['sys:String', 'Specifies the targets for the build customization'
+ ' to run before.'
+ ],
+ ],
+ ['DynamicEnumProperty.ProviderSettings',
+ ['NameValuePair',
+ {'Name': 'Exclude',
+ 'Value': '^%s|^Compute' % rule.before_targets
+ }
+ ]
+ ],
+ ['DynamicEnumProperty.DataSource',
+ ['DataSource',
+ {'Persistence': 'ProjectFile',
+ 'HasConfigurationCondition': 'true'
+ }
+ ]
+ ],
+ ],
+ ['DynamicEnumProperty',
+ {'Name': rule.after_targets,
+ 'Category': 'General',
+ 'EnumProvider': 'Targets',
+ 'IncludeInCommandLine': 'False'
+ },
+ ['DynamicEnumProperty.DisplayName',
+ ['sys:String', 'Execute After'],
+ ],
+ ['DynamicEnumProperty.Description',
+ ['sys:String', ('Specifies the targets for the build customization'
+ ' to run after.')
+ ],
+ ],
+ ['DynamicEnumProperty.ProviderSettings',
+ ['NameValuePair',
+ {'Name': 'Exclude',
+ 'Value': '^%s|^Compute' % rule.after_targets
+ }
+ ]
+ ],
+ ['DynamicEnumProperty.DataSource',
+ ['DataSource',
+ {'Persistence': 'ProjectFile',
+ 'ItemType': '',
+ 'HasConfigurationCondition': 'true'
+ }
+ ]
+ ],
+ ],
+ ['StringListProperty',
+ {'Name': 'Outputs',
+ 'DisplayName': 'Outputs',
+ 'Visible': 'False',
+ 'IncludeInCommandLine': 'False'
+ }
+ ],
+ ['StringProperty',
+ {'Name': 'ExecutionDescription',
+ 'DisplayName': 'Execution Description',
+ 'Visible': 'False',
+ 'IncludeInCommandLine': 'False'
+ }
+ ],
+ ['StringListProperty',
+ {'Name': 'AdditionalDependencies',
+ 'DisplayName': 'Additional Dependencies',
+ 'IncludeInCommandLine': 'False',
+ 'Visible': 'false'
+ }
+ ],
+ ['StringProperty',
+ {'Subtype': 'AdditionalOptions',
+ 'Name': 'AdditionalOptions',
+ 'Category': 'Command Line'
+ },
+ ['StringProperty.DisplayName',
+ ['sys:String', 'Additional Options'],
+ ],
+ ['StringProperty.Description',
+ ['sys:String', 'Additional Options'],
+ ],
+ ],
+ ],
+ ['ItemType',
+ {'Name': rule.rule_name,
+ 'DisplayName': rule.display_name
+ }
+ ],
+ ['FileExtension',
+ {'Name': '*' + rule.extension,
+ 'ContentType': rule.rule_name
+ }
+ ],
+ ['ContentType',
+ {'Name': rule.rule_name,
+ 'DisplayName': '',
+ 'ItemType': rule.rule_name
+ }
+ ]
+ ])
+ easy_xml.WriteXmlIfChanged(content, xml_path, pretty=True, win32=True)
+
+
+def _GetConfigurationAndPlatform(name, settings):
+ configuration = name.rsplit('_', 1)[0]
+ platform = settings.get('msvs_configuration_platform', 'Win32')
+ return (configuration, platform)
+
+
+def _GetConfigurationCondition(name, settings):
+ return (r"'$(Configuration)|$(Platform)'=='%s|%s'" %
+ _GetConfigurationAndPlatform(name, settings))
+
+
+def _GetMSBuildProjectConfigurations(configurations):
+ group = ['ItemGroup', {'Label': 'ProjectConfigurations'}]
+ for (name, settings) in sorted(configurations.iteritems()):
+ configuration, platform = _GetConfigurationAndPlatform(name, settings)
+ designation = '%s|%s' % (configuration, platform)
+ group.append(
+ ['ProjectConfiguration', {'Include': designation},
+ ['Configuration', configuration],
+ ['Platform', platform]])
+ return [group]
+
+
+def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name):
+ namespace = os.path.splitext(gyp_file_name)[0]
+ return [
+ ['PropertyGroup', {'Label': 'Globals'},
+ ['ProjectGuid', guid],
+ ['Keyword', 'Win32Proj'],
+ ['RootNamespace', namespace],
+ ]
+ ]
+
+
+def _GetMSBuildConfigurationDetails(spec, build_file):
+ properties = {}
+ for name, settings in spec['configurations'].iteritems():
+ msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file)
+ condition = _GetConfigurationCondition(name, settings)
+ character_set = msbuild_attributes.get('CharacterSet')
+ _AddConditionalProperty(properties, condition, 'ConfigurationType',
+ msbuild_attributes['ConfigurationType'])
+ if character_set:
+ _AddConditionalProperty(properties, condition, 'CharacterSet',
+ character_set)
+ return _GetMSBuildPropertyGroup(spec, 'Configuration', properties)
+
+
+def _GetMSBuildLocalProperties(msbuild_toolset):
+ # Currently the only local property we support is PlatformToolset
+ properties = {}
+ if msbuild_toolset:
+ properties = [
+ ['PropertyGroup', {'Label': 'Locals'},
+ ['PlatformToolset', msbuild_toolset],
+ ]
+ ]
+ return properties
+
+
+def _GetMSBuildPropertySheets(configurations):
+ user_props = r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props'
+ additional_props = {}
+ props_specified = False
+ for name, settings in sorted(configurations.iteritems()):
+ configuration = _GetConfigurationCondition(name, settings)
+ if settings.has_key('msbuild_props'):
+ additional_props[configuration] = _FixPaths(settings['msbuild_props'])
+ props_specified = True
+ else:
+ additional_props[configuration] = ''
+
+ if not props_specified:
+ return [
+ ['ImportGroup',
+ {'Label': 'PropertySheets'},
+ ['Import',
+ {'Project': user_props,
+ 'Condition': "exists('%s')" % user_props,
+ 'Label': 'LocalAppDataPlatform'
+ }
+ ]
+ ]
+ ]
+ else:
+ sheets = []
+ for condition, props in additional_props.iteritems():
+ import_group = [
+ 'ImportGroup',
+ {'Label': 'PropertySheets',
+ 'Condition': condition
+ },
+ ['Import',
+ {'Project': user_props,
+ 'Condition': "exists('%s')" % user_props,
+ 'Label': 'LocalAppDataPlatform'
+ }
+ ]
+ ]
+ for props_file in props:
+ import_group.append(['Import', {'Project':props_file}])
+ sheets.append(import_group)
+ return sheets
+
+def _ConvertMSVSBuildAttributes(spec, config, build_file):
+ config_type = _GetMSVSConfigurationType(spec, build_file)
+ msvs_attributes = _GetMSVSAttributes(spec, config, config_type)
+ msbuild_attributes = {}
+ for a in msvs_attributes:
+ if a in ['IntermediateDirectory', 'OutputDirectory']:
+ directory = MSVSSettings.ConvertVCMacrosToMSBuild(msvs_attributes[a])
+ if not directory.endswith('\\'):
+ directory += '\\'
+ msbuild_attributes[a] = directory
+ elif a == 'CharacterSet':
+ msbuild_attributes[a] = _ConvertMSVSCharacterSet(msvs_attributes[a])
+ elif a == 'ConfigurationType':
+ msbuild_attributes[a] = _ConvertMSVSConfigurationType(msvs_attributes[a])
+ else:
+ print 'Warning: Do not know how to convert MSVS attribute ' + a
+ return msbuild_attributes
+
+
+def _ConvertMSVSCharacterSet(char_set):
+ if char_set.isdigit():
+ char_set = {
+ '0': 'MultiByte',
+ '1': 'Unicode',
+ '2': 'MultiByte',
+ }[char_set]
+ return char_set
+
+
+def _ConvertMSVSConfigurationType(config_type):
+ if config_type.isdigit():
+ config_type = {
+ '1': 'Application',
+ '2': 'DynamicLibrary',
+ '4': 'StaticLibrary',
+ '10': 'Utility'
+ }[config_type]
+ return config_type
+
+
+def _GetMSBuildAttributes(spec, config, build_file):
+ if 'msbuild_configuration_attributes' not in config:
+ msbuild_attributes = _ConvertMSVSBuildAttributes(spec, config, build_file)
+
+ else:
+ config_type = _GetMSVSConfigurationType(spec, build_file)
+ config_type = _ConvertMSVSConfigurationType(config_type)
+ msbuild_attributes = config.get('msbuild_configuration_attributes', {})
+ msbuild_attributes.setdefault('ConfigurationType', config_type)
+ output_dir = msbuild_attributes.get('OutputDirectory',
+ '$(SolutionDir)$(Configuration)')
+ msbuild_attributes['OutputDirectory'] = _FixPath(output_dir) + '\\'
+ if 'IntermediateDirectory' not in msbuild_attributes:
+ intermediate = _FixPath('$(Configuration)') + '\\'
+ msbuild_attributes['IntermediateDirectory'] = intermediate
+ if 'CharacterSet' in msbuild_attributes:
+ msbuild_attributes['CharacterSet'] = _ConvertMSVSCharacterSet(
+ msbuild_attributes['CharacterSet'])
+ if 'TargetName' not in msbuild_attributes:
+ prefix = spec.get('product_prefix', '')
+ product_name = spec.get('product_name', '$(ProjectName)')
+ target_name = prefix + product_name
+ msbuild_attributes['TargetName'] = target_name
+
+ if spec.get('msvs_external_builder'):
+ external_out_dir = spec.get('msvs_external_builder_out_dir', '.')
+ msbuild_attributes['OutputDirectory'] = _FixPath(external_out_dir) + '\\'
+
+ # Make sure that 'TargetPath' matches 'Lib.OutputFile' or 'Link.OutputFile'
+ # (depending on the tool used) to avoid MSB8012 warning.
+ msbuild_tool_map = {
+ 'executable': 'Link',
+ 'shared_library': 'Link',
+ 'loadable_module': 'Link',
+ 'static_library': 'Lib',
+ }
+ msbuild_tool = msbuild_tool_map.get(spec['type'])
+ if msbuild_tool:
+ msbuild_settings = config['finalized_msbuild_settings']
+ out_file = msbuild_settings[msbuild_tool].get('OutputFile')
+ if out_file:
+ msbuild_attributes['TargetPath'] = _FixPath(out_file)
+
+ return msbuild_attributes
+
+
+def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file):
+ # TODO(jeanluc) We could optimize out the following and do it only if
+ # there are actions.
+ # TODO(jeanluc) Handle the equivalent of setting 'CYGWIN=nontsec'.
+ new_paths = []
+ cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])[0]
+ if cygwin_dirs:
+ cyg_path = '$(MSBuildProjectDirectory)\\%s\\bin\\' % _FixPath(cygwin_dirs)
+ new_paths.append(cyg_path)
+ # TODO(jeanluc) Change the convention to have both a cygwin_dir and a
+ # python_dir.
+ python_path = cyg_path.replace('cygwin\\bin', 'python_26')
+ new_paths.append(python_path)
+ if new_paths:
+ new_paths = '$(ExecutablePath);' + ';'.join(new_paths)
+
+ properties = {}
+ for (name, configuration) in sorted(configurations.iteritems()):
+ condition = _GetConfigurationCondition(name, configuration)
+ attributes = _GetMSBuildAttributes(spec, configuration, build_file)
+ msbuild_settings = configuration['finalized_msbuild_settings']
+ _AddConditionalProperty(properties, condition, 'IntDir',
+ attributes['IntermediateDirectory'])
+ _AddConditionalProperty(properties, condition, 'OutDir',
+ attributes['OutputDirectory'])
+ _AddConditionalProperty(properties, condition, 'TargetName',
+ attributes['TargetName'])
+
+ if attributes.get('TargetPath'):
+ _AddConditionalProperty(properties, condition, 'TargetPath',
+ attributes['TargetPath'])
+
+ if new_paths:
+ _AddConditionalProperty(properties, condition, 'ExecutablePath',
+ new_paths)
+ tool_settings = msbuild_settings.get('', {})
+ for name, value in sorted(tool_settings.iteritems()):
+ formatted_value = _GetValueFormattedForMSBuild('', name, value)
+ _AddConditionalProperty(properties, condition, name, formatted_value)
+ return _GetMSBuildPropertyGroup(spec, None, properties)
+
+
+def _AddConditionalProperty(properties, condition, name, value):
+ """Adds a property / conditional value pair to a dictionary.
+
+ Arguments:
+ properties: The dictionary to be modified. The key is the name of the
+ property. The value is itself a dictionary; its key is the value and
+ the value a list of condition for which this value is true.
+ condition: The condition under which the named property has the value.
+ name: The name of the property.
+ value: The value of the property.
+ """
+ if name not in properties:
+ properties[name] = {}
+ values = properties[name]
+ if value not in values:
+ values[value] = []
+ conditions = values[value]
+ conditions.append(condition)
+
+
+# Regex for msvs variable references ( i.e. $(FOO) ).
+MSVS_VARIABLE_REFERENCE = re.compile('\$\(([a-zA-Z_][a-zA-Z0-9_]*)\)')
+
+
+def _GetMSBuildPropertyGroup(spec, label, properties):
+ """Returns a PropertyGroup definition for the specified properties.
+
+ Arguments:
+ spec: The target project dict.
+ label: An optional label for the PropertyGroup.
+ properties: The dictionary to be converted. The key is the name of the
+ property. The value is itself a dictionary; its key is the value and
+ the value a list of condition for which this value is true.
+ """
+ group = ['PropertyGroup']
+ if label:
+ group.append({'Label': label})
+ num_configurations = len(spec['configurations'])
+ def GetEdges(node):
+ # Use a definition of edges such that user_of_variable -> used_varible.
+ # This happens to be easier in this case, since a variable's
+ # definition contains all variables it references in a single string.
+ edges = set()
+ for value in sorted(properties[node].keys()):
+ # Add to edges all $(...) references to variables.
+ #
+ # Variable references that refer to names not in properties are excluded
+ # These can exist for instance to refer built in definitions like
+ # $(SolutionDir).
+ #
+ # Self references are ignored. Self reference is used in a few places to
+ # append to the default value. I.e. PATH=$(PATH);other_path
+ edges.update(set([v for v in MSVS_VARIABLE_REFERENCE.findall(value)
+ if v in properties and v != node]))
+ return edges
+ properties_ordered = gyp.common.TopologicallySorted(
+ properties.keys(), GetEdges)
+ # Walk properties in the reverse of a topological sort on
+ # user_of_variable -> used_variable as this ensures variables are
+ # defined before they are used.
+ # NOTE: reverse(topsort(DAG)) = topsort(reverse_edges(DAG))
+ for name in reversed(properties_ordered):
+ values = properties[name]
+ for value, conditions in sorted(values.iteritems()):
+ if len(conditions) == num_configurations:
+ # If the value is the same all configurations,
+ # just add one unconditional entry.
+ group.append([name, value])
+ else:
+ for condition in conditions:
+ group.append([name, {'Condition': condition}, value])
+ return [group]
+
+
+def _GetMSBuildToolSettingsSections(spec, configurations):
+ groups = []
+ for (name, configuration) in sorted(configurations.iteritems()):
+ msbuild_settings = configuration['finalized_msbuild_settings']
+ group = ['ItemDefinitionGroup',
+ {'Condition': _GetConfigurationCondition(name, configuration)}
+ ]
+ for tool_name, tool_settings in sorted(msbuild_settings.iteritems()):
+ # Skip the tool named '' which is a holder of global settings handled
+ # by _GetMSBuildConfigurationGlobalProperties.
+ if tool_name:
+ if tool_settings:
+ tool = [tool_name]
+ for name, value in sorted(tool_settings.iteritems()):
+ formatted_value = _GetValueFormattedForMSBuild(tool_name, name,
+ value)
+ tool.append([name, formatted_value])
+ group.append(tool)
+ groups.append(group)
+ return groups
+
+
+def _FinalizeMSBuildSettings(spec, configuration):
+ if 'msbuild_settings' in configuration:
+ converted = False
+ msbuild_settings = configuration['msbuild_settings']
+ MSVSSettings.ValidateMSBuildSettings(msbuild_settings)
+ else:
+ converted = True
+ msvs_settings = configuration.get('msvs_settings', {})
+ msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings)
+ include_dirs, resource_include_dirs = _GetIncludeDirs(configuration)
+ libraries = _GetLibraries(spec)
+ library_dirs = _GetLibraryDirs(configuration)
+ out_file, _, msbuild_tool = _GetOutputFilePathAndTool(spec, msbuild=True)
+ defines = _GetDefines(configuration)
+ if converted:
+ # Visual Studio 2010 has TR1
+ defines = [d for d in defines if d != '_HAS_TR1=0']
+ # Warn of ignored settings
+ ignored_settings = ['msvs_prebuild', 'msvs_postbuild', 'msvs_tool_files']
+ for ignored_setting in ignored_settings:
+ value = configuration.get(ignored_setting)
+ if value:
+ print ('Warning: The automatic conversion to MSBuild does not handle '
+ '%s. Ignoring setting of %s' % (ignored_setting, str(value)))
+
+ defines = [_EscapeCppDefineForMSBuild(d) for d in defines]
+ disabled_warnings = _GetDisabledWarnings(configuration)
+ # TODO(jeanluc) Validate & warn that we don't translate
+ # prebuild = configuration.get('msvs_prebuild')
+ # postbuild = configuration.get('msvs_postbuild')
+ def_file = _GetModuleDefinition(spec)
+ precompiled_header = configuration.get('msvs_precompiled_header')
+
+ # Add the information to the appropriate tool
+ # TODO(jeanluc) We could optimize and generate these settings only if
+ # the corresponding files are found, e.g. don't generate ResourceCompile
+ # if you don't have any resources.
+ _ToolAppend(msbuild_settings, 'ClCompile',
+ 'AdditionalIncludeDirectories', include_dirs)
+ _ToolAppend(msbuild_settings, 'ResourceCompile',
+ 'AdditionalIncludeDirectories', resource_include_dirs)
+ # Add in libraries, note that even for empty libraries, we want this
+ # set, to prevent inheriting default libraries from the enviroment.
+ _ToolSetOrAppend(msbuild_settings, 'Link', 'AdditionalDependencies',
+ libraries)
+ _ToolAppend(msbuild_settings, 'Link', 'AdditionalLibraryDirectories',
+ library_dirs)
+ if out_file:
+ _ToolAppend(msbuild_settings, msbuild_tool, 'OutputFile', out_file,
+ only_if_unset=True)
+ # Add defines.
+ _ToolAppend(msbuild_settings, 'ClCompile',
+ 'PreprocessorDefinitions', defines)
+ _ToolAppend(msbuild_settings, 'ResourceCompile',
+ 'PreprocessorDefinitions', defines)
+ # Add disabled warnings.
+ _ToolAppend(msbuild_settings, 'ClCompile',
+ 'DisableSpecificWarnings', disabled_warnings)
+ # Turn on precompiled headers if appropriate.
+ if precompiled_header:
+ precompiled_header = os.path.split(precompiled_header)[1]
+ _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'Use')
+ _ToolAppend(msbuild_settings, 'ClCompile',
+ 'PrecompiledHeaderFile', precompiled_header)
+ _ToolAppend(msbuild_settings, 'ClCompile',
+ 'ForcedIncludeFiles', precompiled_header)
+ # Loadable modules don't generate import libraries;
+ # tell dependent projects to not expect one.
+ if spec['type'] == 'loadable_module':
+ _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'true')
+ # Set the module definition file if any.
+ if def_file:
+ _ToolAppend(msbuild_settings, 'Link', 'ModuleDefinitionFile', def_file)
+ configuration['finalized_msbuild_settings'] = msbuild_settings
+
+
+def _GetValueFormattedForMSBuild(tool_name, name, value):
+ if type(value) == list:
+ # For some settings, VS2010 does not automatically extends the settings
+ # TODO(jeanluc) Is this what we want?
+ if name in ['AdditionalIncludeDirectories',
+ 'AdditionalLibraryDirectories',
+ 'AdditionalOptions',
+ 'DelayLoadDLLs',
+ 'DisableSpecificWarnings',
+ 'PreprocessorDefinitions']:
+ value.append('%%(%s)' % name)
+ # For most tools, entries in a list should be separated with ';' but some
+ # settings use a space. Check for those first.
+ exceptions = {
+ 'ClCompile': ['AdditionalOptions'],
+ 'Link': ['AdditionalOptions'],
+ 'Lib': ['AdditionalOptions']}
+ if tool_name in exceptions and name in exceptions[tool_name]:
+ char = ' '
+ else:
+ char = ';'
+ formatted_value = char.join(
+ [MSVSSettings.ConvertVCMacrosToMSBuild(i) for i in value])
+ else:
+ formatted_value = MSVSSettings.ConvertVCMacrosToMSBuild(value)
+ return formatted_value
+
+
+def _VerifySourcesExist(sources, root_dir):
+ """Verifies that all source files exist on disk.
+
+ Checks that all regular source files, i.e. not created at run time,
+ exist on disk. Missing files cause needless recompilation but no otherwise
+ visible errors.
+
+ Arguments:
+ sources: A recursive list of Filter/file names.
+ root_dir: The root directory for the relative path names.
+ Returns:
+ A list of source files that cannot be found on disk.
+ """
+ missing_sources = []
+ for source in sources:
+ if isinstance(source, MSVSProject.Filter):
+ missing_sources.extend(_VerifySourcesExist(source.contents, root_dir))
+ else:
+ if '$' not in source:
+ full_path = os.path.join(root_dir, source)
+ if not os.path.exists(full_path):
+ missing_sources.append(full_path)
+ return missing_sources
+
+
+def _GetMSBuildSources(spec, sources, exclusions, extension_to_rule_name,
+ actions_spec, sources_handled_by_action, list_excluded):
+ groups = ['none', 'midl', 'include', 'compile', 'resource', 'rule']
+ grouped_sources = {}
+ for g in groups:
+ grouped_sources[g] = []
+
+ _AddSources2(spec, sources, exclusions, grouped_sources,
+ extension_to_rule_name, sources_handled_by_action, list_excluded)
+ sources = []
+ for g in groups:
+ if grouped_sources[g]:
+ sources.append(['ItemGroup'] + grouped_sources[g])
+ if actions_spec:
+ sources.append(['ItemGroup'] + actions_spec)
+ return sources
+
+
+def _AddSources2(spec, sources, exclusions, grouped_sources,
+ extension_to_rule_name, sources_handled_by_action,
+ list_excluded):
+ extensions_excluded_from_precompile = []
+ for source in sources:
+ if isinstance(source, MSVSProject.Filter):
+ _AddSources2(spec, source.contents, exclusions, grouped_sources,
+ extension_to_rule_name, sources_handled_by_action,
+ list_excluded)
+ else:
+ if not source in sources_handled_by_action:
+ detail = []
+ excluded_configurations = exclusions.get(source, [])
+ if len(excluded_configurations) == len(spec['configurations']):
+ detail.append(['ExcludedFromBuild', 'true'])
+ else:
+ for config_name, configuration in sorted(excluded_configurations):
+ condition = _GetConfigurationCondition(config_name, configuration)
+ detail.append(['ExcludedFromBuild',
+ {'Condition': condition},
+ 'true'])
+ # Add precompile if needed
+ for config_name, configuration in spec['configurations'].iteritems():
+ precompiled_source = configuration.get('msvs_precompiled_source', '')
+ if precompiled_source != '':
+ precompiled_source = _FixPath(precompiled_source)
+ if not extensions_excluded_from_precompile:
+ # If the precompiled header is generated by a C source, we must
+ # not try to use it for C++ sources, and vice versa.
+ basename, extension = os.path.splitext(precompiled_source)
+ if extension == '.c':
+ extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx']
+ else:
+ extensions_excluded_from_precompile = ['.c']
+
+ if precompiled_source == source:
+ condition = _GetConfigurationCondition(config_name, configuration)
+ detail.append(['PrecompiledHeader',
+ {'Condition': condition},
+ 'Create'
+ ])
+ else:
+ # Turn off precompiled header usage for source files of a
+ # different type than the file that generated the
+ # precompiled header.
+ for extension in extensions_excluded_from_precompile:
+ if source.endswith(extension):
+ detail.append(['PrecompiledHeader', ''])
+ detail.append(['ForcedIncludeFiles', ''])
+
+ group, element = _MapFileToMsBuildSourceType(source,
+ extension_to_rule_name)
+ grouped_sources[group].append([element, {'Include': source}] + detail)
+
+
+def _GetMSBuildProjectReferences(project):
+ references = []
+ if project.dependencies:
+ group = ['ItemGroup']
+ for dependency in project.dependencies:
+ guid = dependency.guid
+ project_dir = os.path.split(project.path)[0]
+ relative_path = gyp.common.RelativePath(dependency.path, project_dir)
+ project_ref = ['ProjectReference',
+ {'Include': relative_path},
+ ['Project', guid],
+ ['ReferenceOutputAssembly', 'false']
+ ]
+ for config in dependency.spec.get('configurations', {}).itervalues():
+ # If it's disabled in any config, turn it off in the reference.
+ if config.get('msvs_2010_disable_uldi_when_referenced', 0):
+ project_ref.append(['UseLibraryDependencyInputs', 'false'])
+ break
+ group.append(project_ref)
+ references.append(group)
+ return references
+
+
+def _GenerateMSBuildProject(project, options, version, generator_flags):
+ spec = project.spec
+ configurations = spec['configurations']
+ project_dir, project_file_name = os.path.split(project.path)
+ msbuildproj_dir = os.path.dirname(project.path)
+ if msbuildproj_dir and not os.path.exists(msbuildproj_dir):
+ os.makedirs(msbuildproj_dir)
+ # Prepare list of sources and excluded sources.
+ gyp_path = _NormalizedSource(project.build_file)
+ relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir)
+
+ gyp_file = os.path.split(project.build_file)[1]
+ sources, excluded_sources = _PrepareListOfSources(spec, generator_flags,
+ gyp_file)
+ # Add rules.
+ actions_to_add = {}
+ props_files_of_rules = set()
+ targets_files_of_rules = set()
+ extension_to_rule_name = {}
+ list_excluded = generator_flags.get('msvs_list_excluded_files', True)
+
+ # Don't generate rules if we are using an external builder like ninja.
+ if not spec.get('msvs_external_builder'):
+ _GenerateRulesForMSBuild(project_dir, options, spec,
+ sources, excluded_sources,
+ props_files_of_rules, targets_files_of_rules,
+ actions_to_add, extension_to_rule_name)
+ else:
+ rules = spec.get('rules', [])
+ _AdjustSourcesForRules(spec, rules, sources, excluded_sources)
+
+ sources, excluded_sources, excluded_idl = (
+ _AdjustSourcesAndConvertToFilterHierarchy(spec, options,
+ project_dir, sources,
+ excluded_sources,
+ list_excluded))
+
+ # Don't add actions if we are using an external builder like ninja.
+ if not spec.get('msvs_external_builder'):
+ _AddActions(actions_to_add, spec, project.build_file)
+ _AddCopies(actions_to_add, spec)
+
+ # NOTE: this stanza must appear after all actions have been decided.
+ # Don't excluded sources with actions attached, or they won't run.
+ excluded_sources = _FilterActionsFromExcluded(
+ excluded_sources, actions_to_add)
+
+ exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl)
+ actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild(
+ spec, actions_to_add)
+
+ _GenerateMSBuildFiltersFile(project.path + '.filters', sources,
+ extension_to_rule_name)
+ missing_sources = _VerifySourcesExist(sources, project_dir)
+
+ for configuration in configurations.itervalues():
+ _FinalizeMSBuildSettings(spec, configuration)
+
+ # Add attributes to root element
+
+ import_default_section = [
+ ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.Default.props'}]]
+ import_cpp_props_section = [
+ ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.props'}]]
+ import_cpp_targets_section = [
+ ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.targets'}]]
+ macro_section = [['PropertyGroup', {'Label': 'UserMacros'}]]
+
+ content = [
+ 'Project',
+ {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003',
+ 'ToolsVersion': version.ProjectVersion(),
+ 'DefaultTargets': 'Build'
+ }]
+
+ content += _GetMSBuildProjectConfigurations(configurations)
+ content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name)
+ content += import_default_section
+ content += _GetMSBuildConfigurationDetails(spec, project.build_file)
+ content += _GetMSBuildLocalProperties(project.msbuild_toolset)
+ content += import_cpp_props_section
+ content += _GetMSBuildExtensions(props_files_of_rules)
+ content += _GetMSBuildPropertySheets(configurations)
+ content += macro_section
+ content += _GetMSBuildConfigurationGlobalProperties(spec, configurations,
+ project.build_file)
+ content += _GetMSBuildToolSettingsSections(spec, configurations)
+ content += _GetMSBuildSources(
+ spec, sources, exclusions, extension_to_rule_name, actions_spec,
+ sources_handled_by_action, list_excluded)
+ content += _GetMSBuildProjectReferences(project)
+ content += import_cpp_targets_section
+ content += _GetMSBuildExtensionTargets(targets_files_of_rules)
+
+ if spec.get('msvs_external_builder'):
+ content += _GetMSBuildExternalBuilderTargets(spec)
+
+ # TODO(jeanluc) File a bug to get rid of runas. We had in MSVS:
+ # has_run_as = _WriteMSVSUserFile(project.path, version, spec)
+
+ easy_xml.WriteXmlIfChanged(content, project.path, pretty=True, win32=True)
+
+ return missing_sources
+
+
+def _GetMSBuildExternalBuilderTargets(spec):
+ """Return a list of MSBuild targets for external builders.
+
+ Right now, only "Build" and "Clean" targets are generated.
+
+ Arguments:
+ spec: The gyp target spec.
+ Returns:
+ List of MSBuild 'Target' specs.
+ """
+ build_cmd = _BuildCommandLineForRuleRaw(
+ spec, spec['msvs_external_builder_build_cmd'],
+ False, False, False, False)
+ build_target = ['Target', {'Name': 'Build'}]
+ build_target.append(['Exec', {'Command': build_cmd}])
+
+ clean_cmd = _BuildCommandLineForRuleRaw(
+ spec, spec['msvs_external_builder_clean_cmd'],
+ False, False, False, False)
+ clean_target = ['Target', {'Name': 'Clean'}]
+ clean_target.append(['Exec', {'Command': clean_cmd}])
+
+ return [build_target, clean_target]
+
+
+def _GetMSBuildExtensions(props_files_of_rules):
+ extensions = ['ImportGroup', {'Label': 'ExtensionSettings'}]
+ for props_file in props_files_of_rules:
+ extensions.append(['Import', {'Project': props_file}])
+ return [extensions]
+
+
+def _GetMSBuildExtensionTargets(targets_files_of_rules):
+ targets_node = ['ImportGroup', {'Label': 'ExtensionTargets'}]
+ for targets_file in sorted(targets_files_of_rules):
+ targets_node.append(['Import', {'Project': targets_file}])
+ return [targets_node]
+
+
+def _GenerateActionsForMSBuild(spec, actions_to_add):
+ """Add actions accumulated into an actions_to_add, merging as needed.
+
+ Arguments:
+ spec: the target project dict
+ actions_to_add: dictionary keyed on input name, which maps to a list of
+ dicts describing the actions attached to that input file.
+
+ Returns:
+ A pair of (action specification, the sources handled by this action).
+ """
+ sources_handled_by_action = set()
+ actions_spec = []
+ for primary_input, actions in actions_to_add.iteritems():
+ inputs = set()
+ outputs = set()
+ descriptions = []
+ commands = []
+ for action in actions:
+ inputs.update(set(action['inputs']))
+ outputs.update(set(action['outputs']))
+ descriptions.append(action['description'])
+ cmd = action['command']
+ # For most actions, add 'call' so that actions that invoke batch files
+ # return and continue executing. msbuild_use_call provides a way to
+ # disable this but I have not seen any adverse effect from doing that
+ # for everything.
+ if action.get('msbuild_use_call', True):
+ cmd = 'call ' + cmd
+ commands.append(cmd)
+ # Add the custom build action for one input file.
+ description = ', and also '.join(descriptions)
+
+ # We can't join the commands simply with && because the command line will
+ # get too long. See also _AddActions: cygwin's setup_env mustn't be called
+ # for every invocation or the command that sets the PATH will grow too
+ # long.
+ command = (
+ '\r\nif %errorlevel% neq 0 exit /b %errorlevel%\r\n'.join(commands))
+ _AddMSBuildAction(spec,
+ primary_input,
+ inputs,
+ outputs,
+ command,
+ description,
+ sources_handled_by_action,
+ actions_spec)
+ return actions_spec, sources_handled_by_action
+
+
+def _AddMSBuildAction(spec, primary_input, inputs, outputs, cmd, description,
+ sources_handled_by_action, actions_spec):
+ command = MSVSSettings.ConvertVCMacrosToMSBuild(cmd)
+ primary_input = _FixPath(primary_input)
+ inputs_array = _FixPaths(inputs)
+ outputs_array = _FixPaths(outputs)
+ additional_inputs = ';'.join([i for i in inputs_array
+ if i != primary_input])
+ outputs = ';'.join(outputs_array)
+ sources_handled_by_action.add(primary_input)
+ action_spec = ['CustomBuild', {'Include': primary_input}]
+ action_spec.extend(
+ # TODO(jeanluc) 'Document' for all or just if as_sources?
+ [['FileType', 'Document'],
+ ['Command', command],
+ ['Message', description],
+ ['Outputs', outputs]
+ ])
+ if additional_inputs:
+ action_spec.append(['AdditionalInputs', additional_inputs])
+ actions_spec.append(action_spec)
diff --git a/chromium/tools/gyp/pylib/gyp/generator/msvs_test.py b/chromium/tools/gyp/pylib/gyp/generator/msvs_test.py
new file mode 100755
index 00000000000..c0b021df502
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/msvs_test.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Unit tests for the msvs.py file. """
+
+import gyp.generator.msvs as msvs
+import unittest
+import StringIO
+
+
+class TestSequenceFunctions(unittest.TestCase):
+
+ def setUp(self):
+ self.stderr = StringIO.StringIO()
+
+ def test_GetLibraries(self):
+ self.assertEqual(
+ msvs._GetLibraries({}),
+ [])
+ self.assertEqual(
+ msvs._GetLibraries({'libraries': []}),
+ [])
+ self.assertEqual(
+ msvs._GetLibraries({'other':'foo', 'libraries': ['a.lib']}),
+ ['a.lib'])
+ self.assertEqual(
+ msvs._GetLibraries({'libraries': ['-la']}),
+ ['a.lib'])
+ self.assertEqual(
+ msvs._GetLibraries({'libraries': ['a.lib', 'b.lib', 'c.lib', '-lb.lib',
+ '-lb.lib', 'd.lib', 'a.lib']}),
+ ['c.lib', 'b.lib', 'd.lib', 'a.lib'])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/gyp/pylib/gyp/generator/ninja.py b/chromium/tools/gyp/pylib/gyp/generator/ninja.py
new file mode 100644
index 00000000000..aac0209b672
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/ninja.py
@@ -0,0 +1,2055 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import hashlib
+import multiprocessing
+import os.path
+import re
+import signal
+import subprocess
+import sys
+import gyp
+import gyp.common
+import gyp.msvs_emulation
+import gyp.MSVSUtil as MSVSUtil
+import gyp.xcode_emulation
+
+from gyp.common import GetEnvironFallback
+import gyp.ninja_syntax as ninja_syntax
+
+generator_default_variables = {
+ 'EXECUTABLE_PREFIX': '',
+ 'EXECUTABLE_SUFFIX': '',
+ 'STATIC_LIB_PREFIX': 'lib',
+ 'STATIC_LIB_SUFFIX': '.a',
+ 'SHARED_LIB_PREFIX': 'lib',
+
+ # Gyp expects the following variables to be expandable by the build
+ # system to the appropriate locations. Ninja prefers paths to be
+ # known at gyp time. To resolve this, introduce special
+ # variables starting with $! and $| (which begin with a $ so gyp knows it
+ # should be treated specially, but is otherwise an invalid
+ # ninja/shell variable) that are passed to gyp here but expanded
+ # before writing out into the target .ninja files; see
+ # ExpandSpecial.
+ # $! is used for variables that represent a path and that can only appear at
+ # the start of a string, while $| is used for variables that can appear
+ # anywhere in a string.
+ 'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR',
+ 'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen',
+ 'PRODUCT_DIR': '$!PRODUCT_DIR',
+ 'CONFIGURATION_NAME': '$|CONFIGURATION_NAME',
+
+ # Special variables that may be used by gyp 'rule' targets.
+ # We generate definitions for these variables on the fly when processing a
+ # rule.
+ 'RULE_INPUT_ROOT': '${root}',
+ 'RULE_INPUT_DIRNAME': '${dirname}',
+ 'RULE_INPUT_PATH': '${source}',
+ 'RULE_INPUT_EXT': '${ext}',
+ 'RULE_INPUT_NAME': '${name}',
+}
+
+# Placates pylint.
+generator_additional_non_configuration_keys = []
+generator_additional_path_sections = []
+generator_extra_sources_for_rules = []
+
+# TODO: figure out how to not build extra host objects in the non-cross-compile
+# case when this is enabled, and enable unconditionally.
+generator_supports_multiple_toolsets = (
+ os.environ.get('GYP_CROSSCOMPILE') or
+ os.environ.get('AR_host') or
+ os.environ.get('CC_host') or
+ os.environ.get('CXX_host') or
+ os.environ.get('AR_target') or
+ os.environ.get('CC_target') or
+ os.environ.get('CXX_target'))
+
+
+def StripPrefix(arg, prefix):
+ if arg.startswith(prefix):
+ return arg[len(prefix):]
+ return arg
+
+
+def QuoteShellArgument(arg, flavor):
+ """Quote a string such that it will be interpreted as a single argument
+ by the shell."""
+ # Rather than attempting to enumerate the bad shell characters, just
+ # whitelist common OK ones and quote anything else.
+ if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg):
+ return arg # No quoting necessary.
+ if flavor == 'win':
+ return gyp.msvs_emulation.QuoteForRspFile(arg)
+ return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'"
+
+
+def Define(d, flavor):
+ """Takes a preprocessor define and returns a -D parameter that's ninja- and
+ shell-escaped."""
+ if flavor == 'win':
+ # cl.exe replaces literal # characters with = in preprocesor definitions for
+ # some reason. Octal-encode to work around that.
+ d = d.replace('#', '\\%03o' % ord('#'))
+ return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor)
+
+
+def AddArch(output, arch):
+ """Adds an arch string to an output path."""
+ output, extension = os.path.splitext(output)
+ return '%s.%s%s' % (output, arch, extension)
+
+
+class Target:
+ """Target represents the paths used within a single gyp target.
+
+ Conceptually, building a single target A is a series of steps:
+
+ 1) actions/rules/copies generates source/resources/etc.
+ 2) compiles generates .o files
+ 3) link generates a binary (library/executable)
+ 4) bundle merges the above in a mac bundle
+
+ (Any of these steps can be optional.)
+
+ From a build ordering perspective, a dependent target B could just
+ depend on the last output of this series of steps.
+
+ But some dependent commands sometimes need to reach inside the box.
+ For example, when linking B it needs to get the path to the static
+ library generated by A.
+
+ This object stores those paths. To keep things simple, member
+ variables only store concrete paths to single files, while methods
+ compute derived values like "the last output of the target".
+ """
+ def __init__(self, type):
+ # Gyp type ("static_library", etc.) of this target.
+ self.type = type
+ # File representing whether any input dependencies necessary for
+ # dependent actions have completed.
+ self.preaction_stamp = None
+ # File representing whether any input dependencies necessary for
+ # dependent compiles have completed.
+ self.precompile_stamp = None
+ # File representing the completion of actions/rules/copies, if any.
+ self.actions_stamp = None
+ # Path to the output of the link step, if any.
+ self.binary = None
+ # Path to the file representing the completion of building the bundle,
+ # if any.
+ self.bundle = None
+ # On Windows, incremental linking requires linking against all the .objs
+ # that compose a .lib (rather than the .lib itself). That list is stored
+ # here.
+ self.component_objs = None
+ # Windows only. The import .lib is the output of a build step, but
+ # because dependents only link against the lib (not both the lib and the
+ # dll) we keep track of the import library here.
+ self.import_lib = None
+
+ def Linkable(self):
+ """Return true if this is a target that can be linked against."""
+ return self.type in ('static_library', 'shared_library')
+
+ def UsesToc(self, flavor):
+ """Return true if the target should produce a restat rule based on a TOC
+ file."""
+ # For bundles, the .TOC should be produced for the binary, not for
+ # FinalOutput(). But the naive approach would put the TOC file into the
+ # bundle, so don't do this for bundles for now.
+ if flavor == 'win' or self.bundle:
+ return False
+ return self.type in ('shared_library', 'loadable_module')
+
+ def PreActionInput(self, flavor):
+ """Return the path, if any, that should be used as a dependency of
+ any dependent action step."""
+ if self.UsesToc(flavor):
+ return self.FinalOutput() + '.TOC'
+ return self.FinalOutput() or self.preaction_stamp
+
+ def PreCompileInput(self):
+ """Return the path, if any, that should be used as a dependency of
+ any dependent compile step."""
+ return self.actions_stamp or self.precompile_stamp
+
+ def FinalOutput(self):
+ """Return the last output of the target, which depends on all prior
+ steps."""
+ return self.bundle or self.binary or self.actions_stamp
+
+
+# A small discourse on paths as used within the Ninja build:
+# All files we produce (both at gyp and at build time) appear in the
+# build directory (e.g. out/Debug).
+#
+# Paths within a given .gyp file are always relative to the directory
+# containing the .gyp file. Call these "gyp paths". This includes
+# sources as well as the starting directory a given gyp rule/action
+# expects to be run from. We call the path from the source root to
+# the gyp file the "base directory" within the per-.gyp-file
+# NinjaWriter code.
+#
+# All paths as written into the .ninja files are relative to the build
+# directory. Call these paths "ninja paths".
+#
+# We translate between these two notions of paths with two helper
+# functions:
+#
+# - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file)
+# into the equivalent ninja path.
+#
+# - GypPathToUniqueOutput translates a gyp path into a ninja path to write
+# an output file; the result can be namespaced such that it is unique
+# to the input file name as well as the output target name.
+
+class NinjaWriter:
+ def __init__(self, qualified_target, target_outputs, base_dir, build_dir,
+ output_file, toplevel_build, output_file_name, flavor,
+ toplevel_dir=None):
+ """
+ base_dir: path from source root to directory containing this gyp file,
+ by gyp semantics, all input paths are relative to this
+ build_dir: path from source root to build output
+ toplevel_dir: path to the toplevel directory
+ """
+
+ self.qualified_target = qualified_target
+ self.target_outputs = target_outputs
+ self.base_dir = base_dir
+ self.build_dir = build_dir
+ self.ninja = ninja_syntax.Writer(output_file)
+ self.toplevel_build = toplevel_build
+ self.output_file_name = output_file_name
+
+ self.flavor = flavor
+ self.abs_build_dir = None
+ if toplevel_dir is not None:
+ self.abs_build_dir = os.path.abspath(os.path.join(toplevel_dir,
+ build_dir))
+ self.obj_ext = '.obj' if flavor == 'win' else '.o'
+ if flavor == 'win':
+ # See docstring of msvs_emulation.GenerateEnvironmentFiles().
+ self.win_env = {}
+ for arch in ('x86', 'x64'):
+ self.win_env[arch] = 'environment.' + arch
+
+ # Relative path from build output dir to base dir.
+ build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir)
+ self.build_to_base = os.path.join(build_to_top, base_dir)
+ # Relative path from base dir to build dir.
+ base_to_top = gyp.common.InvertRelativePath(base_dir, toplevel_dir)
+ self.base_to_build = os.path.join(base_to_top, build_dir)
+
+ def ExpandSpecial(self, path, product_dir=None):
+ """Expand specials like $!PRODUCT_DIR in |path|.
+
+ If |product_dir| is None, assumes the cwd is already the product
+ dir. Otherwise, |product_dir| is the relative path to the product
+ dir.
+ """
+
+ PRODUCT_DIR = '$!PRODUCT_DIR'
+ if PRODUCT_DIR in path:
+ if product_dir:
+ path = path.replace(PRODUCT_DIR, product_dir)
+ else:
+ path = path.replace(PRODUCT_DIR + '/', '')
+ path = path.replace(PRODUCT_DIR + '\\', '')
+ path = path.replace(PRODUCT_DIR, '.')
+
+ INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR'
+ if INTERMEDIATE_DIR in path:
+ int_dir = self.GypPathToUniqueOutput('gen')
+ # GypPathToUniqueOutput generates a path relative to the product dir,
+ # so insert product_dir in front if it is provided.
+ path = path.replace(INTERMEDIATE_DIR,
+ os.path.join(product_dir or '', int_dir))
+
+ CONFIGURATION_NAME = '$|CONFIGURATION_NAME'
+ path = path.replace(CONFIGURATION_NAME, self.config_name)
+
+ return path
+
+ def ExpandRuleVariables(self, path, root, dirname, source, ext, name):
+ if self.flavor == 'win':
+ path = self.msvs_settings.ConvertVSMacros(
+ path, config=self.config_name)
+ path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root)
+ path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'],
+ dirname)
+ path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source)
+ path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext)
+ path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name)
+ return path
+
+ def GypPathToNinja(self, path, env=None):
+ """Translate a gyp path to a ninja path, optionally expanding environment
+ variable references in |path| with |env|.
+
+ See the above discourse on path conversions."""
+ if env:
+ if self.flavor == 'mac':
+ path = gyp.xcode_emulation.ExpandEnvVars(path, env)
+ elif self.flavor == 'win':
+ path = gyp.msvs_emulation.ExpandMacros(path, env)
+ if path.startswith('$!'):
+ expanded = self.ExpandSpecial(path)
+ if self.flavor == 'win':
+ expanded = os.path.normpath(expanded)
+ return expanded
+ if '$|' in path:
+ path = self.ExpandSpecial(path)
+ assert '$' not in path, path
+ return os.path.normpath(os.path.join(self.build_to_base, path))
+
+ def GypPathToUniqueOutput(self, path, qualified=True):
+ """Translate a gyp path to a ninja path for writing output.
+
+ If qualified is True, qualify the resulting filename with the name
+ of the target. This is necessary when e.g. compiling the same
+ path twice for two separate output targets.
+
+ See the above discourse on path conversions."""
+
+ path = self.ExpandSpecial(path)
+ assert not path.startswith('$'), path
+
+ # Translate the path following this scheme:
+ # Input: foo/bar.gyp, target targ, references baz/out.o
+ # Output: obj/foo/baz/targ.out.o (if qualified)
+ # obj/foo/baz/out.o (otherwise)
+ # (and obj.host instead of obj for cross-compiles)
+ #
+ # Why this scheme and not some other one?
+ # 1) for a given input, you can compute all derived outputs by matching
+ # its path, even if the input is brought via a gyp file with '..'.
+ # 2) simple files like libraries and stamps have a simple filename.
+
+ obj = 'obj'
+ if self.toolset != 'target':
+ obj += '.' + self.toolset
+
+ path_dir, path_basename = os.path.split(path)
+ if qualified:
+ path_basename = self.name + '.' + path_basename
+ return os.path.normpath(os.path.join(obj, self.base_dir, path_dir,
+ path_basename))
+
+ def WriteCollapsedDependencies(self, name, targets):
+ """Given a list of targets, return a path for a single file
+ representing the result of building all the targets or None.
+
+ Uses a stamp file if necessary."""
+
+ assert targets == filter(None, targets), targets
+ if len(targets) == 0:
+ return None
+ if len(targets) > 1:
+ stamp = self.GypPathToUniqueOutput(name + '.stamp')
+ targets = self.ninja.build(stamp, 'stamp', targets)
+ self.ninja.newline()
+ return targets[0]
+
+ def _SubninjaNameForArch(self, arch):
+ output_file_base = os.path.splitext(self.output_file_name)[0]
+ return '%s.%s.ninja' % (output_file_base, arch)
+
+ def WriteSpec(self, spec, config_name, generator_flags,
+ case_sensitive_filesystem):
+ """The main entry point for NinjaWriter: write the build rules for a spec.
+
+ Returns a Target object, which represents the output paths for this spec.
+ Returns None if there are no outputs (e.g. a settings-only 'none' type
+ target)."""
+
+ self.config_name = config_name
+ self.name = spec['target_name']
+ self.toolset = spec['toolset']
+ config = spec['configurations'][config_name]
+ self.target = Target(spec['type'])
+ self.is_standalone_static_library = bool(
+ spec.get('standalone_static_library', 0))
+
+ self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
+ self.xcode_settings = self.msvs_settings = None
+ if self.flavor == 'mac':
+ self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
+ if self.flavor == 'win':
+ self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec,
+ generator_flags)
+ arch = self.msvs_settings.GetArch(config_name)
+ self.ninja.variable('arch', self.win_env[arch])
+ self.ninja.variable('cc', '$cl_' + arch)
+ self.ninja.variable('cxx', '$cl_' + arch)
+
+ if self.flavor == 'mac':
+ self.archs = self.xcode_settings.GetActiveArchs(config_name)
+ if len(self.archs) > 1:
+ self.arch_subninjas = dict(
+ (arch, ninja_syntax.Writer(
+ open(os.path.join(self.toplevel_build,
+ self._SubninjaNameForArch(arch)),
+ 'w')))
+ for arch in self.archs)
+
+ # Compute predepends for all rules.
+ # actions_depends is the dependencies this target depends on before running
+ # any of its action/rule/copy steps.
+ # compile_depends is the dependencies this target depends on before running
+ # any of its compile steps.
+ actions_depends = []
+ compile_depends = []
+ # TODO(evan): it is rather confusing which things are lists and which
+ # are strings. Fix these.
+ if 'dependencies' in spec:
+ for dep in spec['dependencies']:
+ if dep in self.target_outputs:
+ target = self.target_outputs[dep]
+ actions_depends.append(target.PreActionInput(self.flavor))
+ compile_depends.append(target.PreCompileInput())
+ actions_depends = filter(None, actions_depends)
+ compile_depends = filter(None, compile_depends)
+ actions_depends = self.WriteCollapsedDependencies('actions_depends',
+ actions_depends)
+ compile_depends = self.WriteCollapsedDependencies('compile_depends',
+ compile_depends)
+ self.target.preaction_stamp = actions_depends
+ self.target.precompile_stamp = compile_depends
+
+ # Write out actions, rules, and copies. These must happen before we
+ # compile any sources, so compute a list of predependencies for sources
+ # while we do it.
+ extra_sources = []
+ mac_bundle_depends = []
+ self.target.actions_stamp = self.WriteActionsRulesCopies(
+ spec, extra_sources, actions_depends, mac_bundle_depends)
+
+ # If we have actions/rules/copies, we depend directly on those, but
+ # otherwise we depend on dependent target's actions/rules/copies etc.
+ # We never need to explicitly depend on previous target's link steps,
+ # because no compile ever depends on them.
+ compile_depends_stamp = (self.target.actions_stamp or compile_depends)
+
+ # Write out the compilation steps, if any.
+ link_deps = []
+ sources = spec.get('sources', []) + extra_sources
+ if sources:
+ if self.flavor == 'mac' and len(self.archs) > 1:
+ # Write subninja file containing compile and link commands scoped to
+ # a single arch if a fat binary is being built.
+ for arch in self.archs:
+ self.ninja.subninja(self._SubninjaNameForArch(arch))
+
+ pch = None
+ if self.flavor == 'win':
+ gyp.msvs_emulation.VerifyMissingSources(
+ sources, self.abs_build_dir, generator_flags, self.GypPathToNinja)
+ pch = gyp.msvs_emulation.PrecompiledHeader(
+ self.msvs_settings, config_name, self.GypPathToNinja,
+ self.GypPathToUniqueOutput, self.obj_ext)
+ else:
+ pch = gyp.xcode_emulation.MacPrefixHeader(
+ self.xcode_settings, self.GypPathToNinja,
+ lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang))
+ link_deps = self.WriteSources(
+ self.ninja, config_name, config, sources, compile_depends_stamp, pch,
+ case_sensitive_filesystem, spec)
+ # Some actions/rules output 'sources' that are already object files.
+ obj_outputs = [f for f in sources if f.endswith(self.obj_ext)]
+ if obj_outputs:
+ if self.flavor != 'mac' or len(self.archs) == 1:
+ link_deps += [self.GypPathToNinja(o) for o in obj_outputs]
+ else:
+ print "Warning: Actions/rules writing object files don't work with " \
+ "multiarch targets, dropping. (target %s)" % spec['target_name']
+
+
+ if self.flavor == 'win' and self.target.type == 'static_library':
+ self.target.component_objs = link_deps
+
+ # Write out a link step, if needed.
+ output = None
+ if link_deps or self.target.actions_stamp or actions_depends:
+ output = self.WriteTarget(spec, config_name, config, link_deps,
+ self.target.actions_stamp or actions_depends)
+ if self.is_mac_bundle:
+ mac_bundle_depends.append(output)
+
+ # Bundle all of the above together, if needed.
+ if self.is_mac_bundle:
+ output = self.WriteMacBundle(spec, mac_bundle_depends)
+
+ if not output:
+ return None
+
+ assert self.target.FinalOutput(), output
+ return self.target
+
+ def _WinIdlRule(self, source, prebuild, outputs):
+ """Handle the implicit VS .idl rule for one source file. Fills |outputs|
+ with files that are generated."""
+ outdir, output, vars, flags = self.msvs_settings.GetIdlBuildData(
+ source, self.config_name)
+ outdir = self.GypPathToNinja(outdir)
+ def fix_path(path, rel=None):
+ path = os.path.join(outdir, path)
+ dirname, basename = os.path.split(source)
+ root, ext = os.path.splitext(basename)
+ path = self.ExpandRuleVariables(
+ path, root, dirname, source, ext, basename)
+ if rel:
+ path = os.path.relpath(path, rel)
+ return path
+ vars = [(name, fix_path(value, outdir)) for name, value in vars]
+ output = [fix_path(p) for p in output]
+ vars.append(('outdir', outdir))
+ vars.append(('idlflags', flags))
+ input = self.GypPathToNinja(source)
+ self.ninja.build(output, 'idl', input,
+ variables=vars, order_only=prebuild)
+ outputs.extend(output)
+
+ def WriteWinIdlFiles(self, spec, prebuild):
+ """Writes rules to match MSVS's implicit idl handling."""
+ assert self.flavor == 'win'
+ if self.msvs_settings.HasExplicitIdlRules(spec):
+ return []
+ outputs = []
+ for source in filter(lambda x: x.endswith('.idl'), spec['sources']):
+ self._WinIdlRule(source, prebuild, outputs)
+ return outputs
+
+ def WriteActionsRulesCopies(self, spec, extra_sources, prebuild,
+ mac_bundle_depends):
+ """Write out the Actions, Rules, and Copies steps. Return a path
+ representing the outputs of these steps."""
+ outputs = []
+ extra_mac_bundle_resources = []
+
+ if 'actions' in spec:
+ outputs += self.WriteActions(spec['actions'], extra_sources, prebuild,
+ extra_mac_bundle_resources)
+ if 'rules' in spec:
+ outputs += self.WriteRules(spec['rules'], extra_sources, prebuild,
+ extra_mac_bundle_resources)
+ if 'copies' in spec:
+ outputs += self.WriteCopies(spec['copies'], prebuild, mac_bundle_depends)
+
+ if 'sources' in spec and self.flavor == 'win':
+ outputs += self.WriteWinIdlFiles(spec, prebuild)
+
+ stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs)
+
+ if self.is_mac_bundle:
+ mac_bundle_resources = spec.get('mac_bundle_resources', []) + \
+ extra_mac_bundle_resources
+ self.WriteMacBundleResources(mac_bundle_resources, mac_bundle_depends)
+ self.WriteMacInfoPlist(mac_bundle_depends)
+
+ return stamp
+
+ def GenerateDescription(self, verb, message, fallback):
+ """Generate and return a description of a build step.
+
+ |verb| is the short summary, e.g. ACTION or RULE.
+ |message| is a hand-written description, or None if not available.
+ |fallback| is the gyp-level name of the step, usable as a fallback.
+ """
+ if self.toolset != 'target':
+ verb += '(%s)' % self.toolset
+ if message:
+ return '%s %s' % (verb, self.ExpandSpecial(message))
+ else:
+ return '%s %s: %s' % (verb, self.name, fallback)
+
+ def WriteActions(self, actions, extra_sources, prebuild,
+ extra_mac_bundle_resources):
+ # Actions cd into the base directory.
+ env = self.GetSortedXcodeEnv()
+ if self.flavor == 'win':
+ env = self.msvs_settings.GetVSMacroEnv(
+ '$!PRODUCT_DIR', config=self.config_name)
+ all_outputs = []
+ for action in actions:
+ # First write out a rule for the action.
+ name = '%s_%s' % (action['action_name'],
+ hashlib.md5(self.qualified_target).hexdigest())
+ description = self.GenerateDescription('ACTION',
+ action.get('message', None),
+ name)
+ is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action)
+ if self.flavor == 'win' else False)
+ args = action['action']
+ rule_name, _ = self.WriteNewNinjaRule(name, args, description,
+ is_cygwin, env=env)
+
+ inputs = [self.GypPathToNinja(i, env) for i in action['inputs']]
+ if int(action.get('process_outputs_as_sources', False)):
+ extra_sources += action['outputs']
+ if int(action.get('process_outputs_as_mac_bundle_resources', False)):
+ extra_mac_bundle_resources += action['outputs']
+ outputs = [self.GypPathToNinja(o, env) for o in action['outputs']]
+
+ # Then write out an edge using the rule.
+ self.ninja.build(outputs, rule_name, inputs,
+ order_only=prebuild)
+ all_outputs += outputs
+
+ self.ninja.newline()
+
+ return all_outputs
+
+ def WriteRules(self, rules, extra_sources, prebuild,
+ extra_mac_bundle_resources):
+ env = self.GetSortedXcodeEnv()
+ all_outputs = []
+ for rule in rules:
+ # First write out a rule for the rule action.
+ name = '%s_%s' % (rule['rule_name'],
+ hashlib.md5(self.qualified_target).hexdigest())
+ # Skip a rule with no action and no inputs.
+ if 'action' not in rule and not rule.get('rule_sources', []):
+ continue
+ args = rule['action']
+ description = self.GenerateDescription(
+ 'RULE',
+ rule.get('message', None),
+ ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name)
+ is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule)
+ if self.flavor == 'win' else False)
+ rule_name, args = self.WriteNewNinjaRule(
+ name, args, description, is_cygwin, env=env)
+
+ # TODO: if the command references the outputs directly, we should
+ # simplify it to just use $out.
+
+ # Rules can potentially make use of some special variables which
+ # must vary per source file.
+ # Compute the list of variables we'll need to provide.
+ special_locals = ('source', 'root', 'dirname', 'ext', 'name')
+ needed_variables = set(['source'])
+ for argument in args:
+ for var in special_locals:
+ if ('${%s}' % var) in argument:
+ needed_variables.add(var)
+
+ def cygwin_munge(path):
+ if is_cygwin:
+ return path.replace('\\', '/')
+ return path
+
+ # For each source file, write an edge that generates all the outputs.
+ for source in rule.get('rule_sources', []):
+ source = os.path.normpath(source)
+ dirname, basename = os.path.split(source)
+ root, ext = os.path.splitext(basename)
+
+ # Gather the list of inputs and outputs, expanding $vars if possible.
+ outputs = [self.ExpandRuleVariables(o, root, dirname,
+ source, ext, basename)
+ for o in rule['outputs']]
+ inputs = [self.ExpandRuleVariables(i, root, dirname,
+ source, ext, basename)
+ for i in rule.get('inputs', [])]
+
+ if int(rule.get('process_outputs_as_sources', False)):
+ extra_sources += outputs
+ if int(rule.get('process_outputs_as_mac_bundle_resources', False)):
+ extra_mac_bundle_resources += outputs
+
+ extra_bindings = []
+ for var in needed_variables:
+ if var == 'root':
+ extra_bindings.append(('root', cygwin_munge(root)))
+ elif var == 'dirname':
+ # '$dirname' is a parameter to the rule action, which means
+ # it shouldn't be converted to a Ninja path. But we don't
+ # want $!PRODUCT_DIR in there either.
+ dirname_expanded = self.ExpandSpecial(dirname, self.base_to_build)
+ extra_bindings.append(('dirname', cygwin_munge(dirname_expanded)))
+ elif var == 'source':
+ # '$source' is a parameter to the rule action, which means
+ # it shouldn't be converted to a Ninja path. But we don't
+ # want $!PRODUCT_DIR in there either.
+ source_expanded = self.ExpandSpecial(source, self.base_to_build)
+ extra_bindings.append(('source', cygwin_munge(source_expanded)))
+ elif var == 'ext':
+ extra_bindings.append(('ext', ext))
+ elif var == 'name':
+ extra_bindings.append(('name', cygwin_munge(basename)))
+ else:
+ assert var == None, repr(var)
+
+ inputs = [self.GypPathToNinja(i, env) for i in inputs]
+ outputs = [self.GypPathToNinja(o, env) for o in outputs]
+ extra_bindings.append(('unique_name',
+ hashlib.md5(outputs[0]).hexdigest()))
+ self.ninja.build(outputs, rule_name, self.GypPathToNinja(source),
+ implicit=inputs,
+ order_only=prebuild,
+ variables=extra_bindings)
+
+ all_outputs.extend(outputs)
+
+ return all_outputs
+
+ def WriteCopies(self, copies, prebuild, mac_bundle_depends):
+ outputs = []
+ env = self.GetSortedXcodeEnv()
+ for copy in copies:
+ for path in copy['files']:
+ # Normalize the path so trailing slashes don't confuse us.
+ path = os.path.normpath(path)
+ basename = os.path.split(path)[1]
+ src = self.GypPathToNinja(path, env)
+ dst = self.GypPathToNinja(os.path.join(copy['destination'], basename),
+ env)
+ outputs += self.ninja.build(dst, 'copy', src, order_only=prebuild)
+ if self.is_mac_bundle:
+ # gyp has mac_bundle_resources to copy things into a bundle's
+ # Resources folder, but there's no built-in way to copy files to other
+ # places in the bundle. Hence, some targets use copies for this. Check
+ # if this file is copied into the current bundle, and if so add it to
+ # the bundle depends so that dependent targets get rebuilt if the copy
+ # input changes.
+ if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()):
+ mac_bundle_depends.append(dst)
+
+ return outputs
+
+ def WriteMacBundleResources(self, resources, bundle_depends):
+ """Writes ninja edges for 'mac_bundle_resources'."""
+ for output, res in gyp.xcode_emulation.GetMacBundleResources(
+ generator_default_variables['PRODUCT_DIR'],
+ self.xcode_settings, map(self.GypPathToNinja, resources)):
+ output = self.ExpandSpecial(output)
+ self.ninja.build(output, 'mac_tool', res,
+ variables=[('mactool_cmd', 'copy-bundle-resource')])
+ bundle_depends.append(output)
+
+ def WriteMacInfoPlist(self, bundle_depends):
+ """Write build rules for bundle Info.plist files."""
+ info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
+ generator_default_variables['PRODUCT_DIR'],
+ self.xcode_settings, self.GypPathToNinja)
+ if not info_plist:
+ return
+ out = self.ExpandSpecial(out)
+ if defines:
+ # Create an intermediate file to store preprocessed results.
+ intermediate_plist = self.GypPathToUniqueOutput(
+ os.path.basename(info_plist))
+ defines = ' '.join([Define(d, self.flavor) for d in defines])
+ info_plist = self.ninja.build(intermediate_plist, 'infoplist', info_plist,
+ variables=[('defines',defines)])
+
+ env = self.GetSortedXcodeEnv(additional_settings=extra_env)
+ env = self.ComputeExportEnvString(env)
+
+ self.ninja.build(out, 'mac_tool', info_plist,
+ variables=[('mactool_cmd', 'copy-info-plist'),
+ ('env', env)])
+ bundle_depends.append(out)
+
+ def WriteSources(self, ninja_file, config_name, config, sources, predepends,
+ precompiled_header, case_sensitive_filesystem, spec):
+ """Write build rules to compile all of |sources|."""
+ if self.toolset == 'host':
+ self.ninja.variable('ar', '$ar_host')
+ self.ninja.variable('cc', '$cc_host')
+ self.ninja.variable('cxx', '$cxx_host')
+ self.ninja.variable('ld', '$ld_host')
+
+ if self.flavor != 'mac' or len(self.archs) == 1:
+ return self.WriteSourcesForArch(
+ self.ninja, config_name, config, sources, predepends,
+ precompiled_header, case_sensitive_filesystem, spec)
+ else:
+ return dict((arch, self.WriteSourcesForArch(
+ self.arch_subninjas[arch], config_name, config, sources, predepends,
+ precompiled_header, case_sensitive_filesystem, spec, arch=arch))
+ for arch in self.archs)
+
+ def WriteSourcesForArch(self, ninja_file, config_name, config, sources,
+ predepends, precompiled_header,
+ case_sensitive_filesystem, spec, arch=None):
+ """Write build rules to compile all of |sources|."""
+
+ extra_defines = []
+ if self.flavor == 'mac':
+ cflags = self.xcode_settings.GetCflags(config_name, arch=arch)
+ cflags_c = self.xcode_settings.GetCflagsC(config_name)
+ cflags_cc = self.xcode_settings.GetCflagsCC(config_name)
+ cflags_objc = ['$cflags_c'] + \
+ self.xcode_settings.GetCflagsObjC(config_name)
+ cflags_objcc = ['$cflags_cc'] + \
+ self.xcode_settings.GetCflagsObjCC(config_name)
+ elif self.flavor == 'win':
+ cflags = self.msvs_settings.GetCflags(config_name)
+ cflags_c = self.msvs_settings.GetCflagsC(config_name)
+ cflags_cc = self.msvs_settings.GetCflagsCC(config_name)
+ extra_defines = self.msvs_settings.GetComputedDefines(config_name)
+ pdbpath = self.msvs_settings.GetCompilerPdbName(
+ config_name, self.ExpandSpecial)
+ if not pdbpath:
+ obj = 'obj'
+ if self.toolset != 'target':
+ obj += '.' + self.toolset
+ pdbpath = os.path.normpath(os.path.join(obj, self.base_dir,
+ self.name + '.pdb'))
+ self.WriteVariableList(ninja_file, 'pdbname', [pdbpath])
+ self.WriteVariableList(ninja_file, 'pchprefix', [self.name])
+ else:
+ cflags = config.get('cflags', [])
+
+ # Respect environment variables related to build, but target-specific
+ # flags can still override them.
+ cflags_c = (os.environ.get('CPPFLAGS', '').split() +
+ os.environ.get('CFLAGS', '').split() +
+ config.get('cflags_c', []))
+ cflags_cc = (os.environ.get('CPPFLAGS', '').split() +
+ os.environ.get('CXXFLAGS', '').split() +
+ config.get('cflags_cc', []))
+
+ defines = config.get('defines', []) + extra_defines
+ self.WriteVariableList(ninja_file, 'defines',
+ [Define(d, self.flavor) for d in defines])
+ if self.flavor == 'win':
+ self.WriteVariableList(ninja_file, 'rcflags',
+ [QuoteShellArgument(self.ExpandSpecial(f), self.flavor)
+ for f in self.msvs_settings.GetRcflags(config_name,
+ self.GypPathToNinja)])
+
+ include_dirs = config.get('include_dirs', [])
+ if self.flavor == 'win':
+ include_dirs = self.msvs_settings.AdjustIncludeDirs(include_dirs,
+ config_name)
+ env = self.GetSortedXcodeEnv()
+ self.WriteVariableList(ninja_file, 'includes',
+ [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor)
+ for i in include_dirs])
+
+ pch_commands = precompiled_header.GetPchBuildCommands(arch)
+ if self.flavor == 'mac':
+ # Most targets use no precompiled headers, so only write these if needed.
+ for ext, var in [('c', 'cflags_pch_c'), ('cc', 'cflags_pch_cc'),
+ ('m', 'cflags_pch_objc'), ('mm', 'cflags_pch_objcc')]:
+ include = precompiled_header.GetInclude(ext, arch)
+ if include: ninja_file.variable(var, include)
+
+ self.WriteVariableList(ninja_file, 'cflags',
+ map(self.ExpandSpecial, cflags))
+ self.WriteVariableList(ninja_file, 'cflags_c',
+ map(self.ExpandSpecial, cflags_c))
+ self.WriteVariableList(ninja_file, 'cflags_cc',
+ map(self.ExpandSpecial, cflags_cc))
+ if self.flavor == 'mac':
+ self.WriteVariableList(ninja_file, 'cflags_objc',
+ map(self.ExpandSpecial, cflags_objc))
+ self.WriteVariableList(ninja_file, 'cflags_objcc',
+ map(self.ExpandSpecial, cflags_objcc))
+ ninja_file.newline()
+ outputs = []
+ for source in sources:
+ filename, ext = os.path.splitext(source)
+ ext = ext[1:]
+ obj_ext = self.obj_ext
+ if ext in ('cc', 'cpp', 'cxx'):
+ command = 'cxx'
+ elif ext == 'c' or (ext == 'S' and self.flavor != 'win'):
+ command = 'cc'
+ elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files.
+ command = 'cc_s'
+ elif (self.flavor == 'win' and ext == 'asm' and
+ self.msvs_settings.GetArch(config_name) == 'x86' and
+ not self.msvs_settings.HasExplicitAsmRules(spec)):
+ # Asm files only get auto assembled for x86 (not x64).
+ command = 'asm'
+ # Add the _asm suffix as msvs is capable of handling .cc and
+ # .asm files of the same name without collision.
+ obj_ext = '_asm.obj'
+ elif self.flavor == 'mac' and ext == 'm':
+ command = 'objc'
+ elif self.flavor == 'mac' and ext == 'mm':
+ command = 'objcxx'
+ elif self.flavor == 'win' and ext == 'rc':
+ command = 'rc'
+ obj_ext = '.res'
+ else:
+ # Ignore unhandled extensions.
+ continue
+ input = self.GypPathToNinja(source)
+ output = self.GypPathToUniqueOutput(filename + obj_ext)
+ if arch is not None:
+ output = AddArch(output, arch)
+ # Ninja's depfile handling gets confused when the case of a filename
+ # changes on a case-insensitive file system. To work around that, always
+ # convert .o filenames to lowercase on such file systems. See
+ # https://github.com/martine/ninja/issues/402 for details.
+ if not case_sensitive_filesystem:
+ output = output.lower()
+ implicit = precompiled_header.GetObjDependencies([input], [output], arch)
+ variables = []
+ if self.flavor == 'win':
+ variables, output, implicit = precompiled_header.GetFlagsModifications(
+ input, output, implicit, command, cflags_c, cflags_cc,
+ self.ExpandSpecial)
+ ninja_file.build(output, command, input,
+ implicit=[gch for _, _, gch in implicit],
+ order_only=predepends, variables=variables)
+ outputs.append(output)
+
+ self.WritePchTargets(ninja_file, pch_commands)
+
+ ninja_file.newline()
+ return outputs
+
+ def WritePchTargets(self, ninja_file, pch_commands):
+ """Writes ninja rules to compile prefix headers."""
+ if not pch_commands:
+ return
+
+ for gch, lang_flag, lang, input in pch_commands:
+ var_name = {
+ 'c': 'cflags_pch_c',
+ 'cc': 'cflags_pch_cc',
+ 'm': 'cflags_pch_objc',
+ 'mm': 'cflags_pch_objcc',
+ }[lang]
+
+ map = { 'c': 'cc', 'cc': 'cxx', 'm': 'objc', 'mm': 'objcxx', }
+ cmd = map.get(lang)
+ ninja_file.build(gch, cmd, input, variables=[(var_name, lang_flag)])
+
+ def WriteLink(self, spec, config_name, config, link_deps):
+ """Write out a link step. Fills out target.binary. """
+ if self.flavor != 'mac' or len(self.archs) == 1:
+ return self.WriteLinkForArch(
+ self.ninja, spec, config_name, config, link_deps)
+ else:
+ output = self.ComputeOutput(spec)
+ inputs = [self.WriteLinkForArch(self.arch_subninjas[arch], spec,
+ config_name, config, link_deps[arch],
+ arch=arch)
+ for arch in self.archs]
+ extra_bindings = []
+ if not self.is_mac_bundle:
+ self.AppendPostbuildVariable(extra_bindings, spec, output, output)
+ self.ninja.build(output, 'lipo', inputs, variables=extra_bindings)
+ return output
+
+ def WriteLinkForArch(self, ninja_file, spec, config_name, config,
+ link_deps, arch=None):
+ """Write out a link step. Fills out target.binary. """
+ command = {
+ 'executable': 'link',
+ 'loadable_module': 'solink_module',
+ 'shared_library': 'solink',
+ }[spec['type']]
+ command_suffix = ''
+
+ implicit_deps = set()
+ solibs = set()
+
+ if 'dependencies' in spec:
+ # Two kinds of dependencies:
+ # - Linkable dependencies (like a .a or a .so): add them to the link line.
+ # - Non-linkable dependencies (like a rule that generates a file
+ # and writes a stamp file): add them to implicit_deps
+ extra_link_deps = set()
+ for dep in spec['dependencies']:
+ target = self.target_outputs.get(dep)
+ if not target:
+ continue
+ linkable = target.Linkable()
+ if linkable:
+ if (self.flavor == 'win' and
+ target.component_objs and
+ self.msvs_settings.IsUseLibraryDependencyInputs(config_name)):
+ extra_link_deps |= set(target.component_objs)
+ elif self.flavor == 'win' and target.import_lib:
+ extra_link_deps.add(target.import_lib)
+ elif target.UsesToc(self.flavor):
+ solibs.add(target.binary)
+ implicit_deps.add(target.binary + '.TOC')
+ else:
+ extra_link_deps.add(target.binary)
+
+ final_output = target.FinalOutput()
+ if not linkable or final_output != target.binary:
+ implicit_deps.add(final_output)
+
+ link_deps.extend(list(extra_link_deps))
+
+ extra_bindings = []
+ output = self.ComputeOutput(spec, arch)
+ if arch is None and not self.is_mac_bundle:
+ self.AppendPostbuildVariable(extra_bindings, spec, output, output)
+
+ is_executable = spec['type'] == 'executable'
+ if self.flavor == 'mac':
+ ldflags = self.xcode_settings.GetLdflags(config_name,
+ self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
+ self.GypPathToNinja, arch)
+ elif self.flavor == 'win':
+ manifest_name = self.GypPathToUniqueOutput(
+ self.ComputeOutputFileName(spec))
+ ldflags, manifest_files = self.msvs_settings.GetLdflags(config_name,
+ self.GypPathToNinja, self.ExpandSpecial, manifest_name, is_executable)
+ self.WriteVariableList(ninja_file, 'manifests', manifest_files)
+ command_suffix = _GetWinLinkRuleNameSuffix(
+ self.msvs_settings.IsEmbedManifest(config_name),
+ self.msvs_settings.IsLinkIncremental(config_name))
+ def_file = self.msvs_settings.GetDefFile(self.GypPathToNinja)
+ if def_file:
+ implicit_deps.add(def_file)
+ else:
+ # Respect environment variables related to build, but target-specific
+ # flags can still override them.
+ ldflags = (os.environ.get('LDFLAGS', '').split() +
+ config.get('ldflags', []))
+ if is_executable and len(solibs):
+ rpath = 'lib/'
+ if self.toolset != 'target':
+ rpath += self.toolset
+ ldflags.append('-Wl,-rpath=\$$ORIGIN/%s' % rpath)
+ ldflags.append('-Wl,-rpath-link=%s' % rpath)
+ self.WriteVariableList(ninja_file, 'ldflags',
+ gyp.common.uniquer(map(self.ExpandSpecial, ldflags)))
+
+ library_dirs = config.get('library_dirs', [])
+ if self.flavor == 'win':
+ library_dirs = [self.msvs_settings.ConvertVSMacros(l, config_name)
+ for l in library_dirs]
+ library_dirs = [QuoteShellArgument('-LIBPATH:' + self.GypPathToNinja(l),
+ self.flavor)
+ for l in library_dirs]
+ else:
+ library_dirs = [QuoteShellArgument('-L' + self.GypPathToNinja(l),
+ self.flavor)
+ for l in library_dirs]
+
+ libraries = gyp.common.uniquer(map(self.ExpandSpecial,
+ spec.get('libraries', [])))
+ if self.flavor == 'mac':
+ libraries = self.xcode_settings.AdjustLibraries(libraries)
+ elif self.flavor == 'win':
+ libraries = self.msvs_settings.AdjustLibraries(libraries)
+
+ self.WriteVariableList(ninja_file, 'libs', library_dirs + libraries)
+
+ linked_binary = output
+
+ if command in ('solink', 'solink_module'):
+ extra_bindings.append(('soname', os.path.split(output)[1]))
+ extra_bindings.append(('lib',
+ gyp.common.EncodePOSIXShellArgument(output)))
+ if self.flavor == 'win':
+ extra_bindings.append(('dll', output))
+ if '/NOENTRY' not in ldflags:
+ self.target.import_lib = output + '.lib'
+ extra_bindings.append(('implibflag',
+ '/IMPLIB:%s' % self.target.import_lib))
+ output = [output, self.target.import_lib]
+ else:
+ output = [output, output + '.TOC']
+
+ if len(solibs):
+ extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs)))
+
+ ninja_file.build(output, command + command_suffix, link_deps,
+ implicit=list(implicit_deps),
+ variables=extra_bindings)
+ return linked_binary
+
+ def WriteTarget(self, spec, config_name, config, link_deps, compile_deps):
+ if spec['type'] == 'none':
+ # TODO(evan): don't call this function for 'none' target types, as
+ # it doesn't do anything, and we fake out a 'binary' with a stamp file.
+ self.target.binary = compile_deps
+ elif spec['type'] == 'static_library':
+ self.target.binary = self.ComputeOutput(spec)
+ if (self.flavor not in ('mac', 'openbsd', 'win') and not
+ self.is_standalone_static_library):
+ self.ninja.build(self.target.binary, 'alink_thin', link_deps,
+ order_only=compile_deps)
+ else:
+ variables = []
+ if self.xcode_settings:
+ libtool_flags = self.xcode_settings.GetLibtoolflags(config_name)
+ if libtool_flags:
+ variables.append(('libtool_flags', libtool_flags))
+ if self.msvs_settings:
+ libflags = self.msvs_settings.GetLibFlags(config_name,
+ self.GypPathToNinja)
+ variables.append(('libflags', libflags))
+
+ if self.flavor != 'mac' or len(self.archs) == 1:
+ self.AppendPostbuildVariable(variables, spec,
+ self.target.binary, self.target.binary)
+ self.ninja.build(self.target.binary, 'alink', link_deps,
+ order_only=compile_deps, variables=variables)
+ else:
+ inputs = []
+ for arch in self.archs:
+ output = self.ComputeOutput(spec, arch)
+ self.arch_subninjas[arch].build(output, 'alink', link_deps[arch],
+ order_only=compile_deps,
+ variables=variables)
+ inputs.append(output)
+ # TODO: It's not clear if libtool_flags should be passed to the alink
+ # call that combines single-arch .a files into a fat .a file.
+ self.AppendPostbuildVariable(variables, spec,
+ self.target.binary, self.target.binary)
+ self.ninja.build(self.target.binary, 'alink', inputs,
+ # FIXME: test proving order_only=compile_deps isn't
+ # needed.
+ variables=variables)
+ else:
+ self.target.binary = self.WriteLink(spec, config_name, config, link_deps)
+ return self.target.binary
+
+ def WriteMacBundle(self, spec, mac_bundle_depends):
+ assert self.is_mac_bundle
+ package_framework = spec['type'] in ('shared_library', 'loadable_module')
+ output = self.ComputeMacBundleOutput()
+ variables = []
+ self.AppendPostbuildVariable(variables, spec, output, self.target.binary,
+ is_command_start=not package_framework)
+ if package_framework:
+ variables.append(('version', self.xcode_settings.GetFrameworkVersion()))
+ self.ninja.build(output, 'package_framework', mac_bundle_depends,
+ variables=variables)
+ else:
+ self.ninja.build(output, 'stamp', mac_bundle_depends,
+ variables=variables)
+ self.target.bundle = output
+ return output
+
+ def GetSortedXcodeEnv(self, additional_settings=None):
+ """Returns the variables Xcode would set for build steps."""
+ assert self.abs_build_dir
+ abs_build_dir = self.abs_build_dir
+ return gyp.xcode_emulation.GetSortedXcodeEnv(
+ self.xcode_settings, abs_build_dir,
+ os.path.join(abs_build_dir, self.build_to_base), self.config_name,
+ additional_settings)
+
+ def GetSortedXcodePostbuildEnv(self):
+ """Returns the variables Xcode would set for postbuild steps."""
+ postbuild_settings = {}
+ # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack.
+ # TODO(thakis): It would be nice to have some general mechanism instead.
+ strip_save_file = self.xcode_settings.GetPerTargetSetting(
+ 'CHROMIUM_STRIP_SAVE_FILE')
+ if strip_save_file:
+ postbuild_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file
+ return self.GetSortedXcodeEnv(additional_settings=postbuild_settings)
+
+ def AppendPostbuildVariable(self, variables, spec, output, binary,
+ is_command_start=False):
+ """Adds a 'postbuild' variable if there is a postbuild for |output|."""
+ postbuild = self.GetPostbuildCommand(spec, output, binary, is_command_start)
+ if postbuild:
+ variables.append(('postbuilds', postbuild))
+
+ def GetPostbuildCommand(self, spec, output, output_binary, is_command_start):
+ """Returns a shell command that runs all the postbuilds, and removes
+ |output| if any of them fails. If |is_command_start| is False, then the
+ returned string will start with ' && '."""
+ if not self.xcode_settings or spec['type'] == 'none' or not output:
+ return ''
+ output = QuoteShellArgument(output, self.flavor)
+ target_postbuilds = []
+ if output_binary is not None:
+ target_postbuilds = self.xcode_settings.GetTargetPostbuilds(
+ self.config_name,
+ os.path.normpath(os.path.join(self.base_to_build, output)),
+ QuoteShellArgument(
+ os.path.normpath(os.path.join(self.base_to_build, output_binary)),
+ self.flavor),
+ quiet=True)
+ postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True)
+ postbuilds = target_postbuilds + postbuilds
+ if not postbuilds:
+ return ''
+ # Postbuilds expect to be run in the gyp file's directory, so insert an
+ # implicit postbuild to cd to there.
+ postbuilds.insert(0, gyp.common.EncodePOSIXShellList(
+ ['cd', self.build_to_base]))
+ env = self.ComputeExportEnvString(self.GetSortedXcodePostbuildEnv())
+ # G will be non-null if any postbuild fails. Run all postbuilds in a
+ # subshell.
+ commands = env + ' (' + \
+ ' && '.join([ninja_syntax.escape(command) for command in postbuilds])
+ command_string = (commands + '); G=$$?; '
+ # Remove the final output if any postbuild failed.
+ '((exit $$G) || rm -rf %s) ' % output + '&& exit $$G)')
+ if is_command_start:
+ return '(' + command_string + ' && '
+ else:
+ return '$ && (' + command_string
+
+ def ComputeExportEnvString(self, env):
+ """Given an environment, returns a string looking like
+ 'export FOO=foo; export BAR="${FOO} bar;'
+ that exports |env| to the shell."""
+ export_str = []
+ for k, v in env:
+ export_str.append('export %s=%s;' %
+ (k, ninja_syntax.escape(gyp.common.EncodePOSIXShellArgument(v))))
+ return ' '.join(export_str)
+
+ def ComputeMacBundleOutput(self):
+ """Return the 'output' (full output path) to a bundle output directory."""
+ assert self.is_mac_bundle
+ path = generator_default_variables['PRODUCT_DIR']
+ return self.ExpandSpecial(
+ os.path.join(path, self.xcode_settings.GetWrapperName()))
+
+ def ComputeOutputFileName(self, spec, type=None):
+ """Compute the filename of the final output for the current target."""
+ if not type:
+ type = spec['type']
+
+ default_variables = copy.copy(generator_default_variables)
+ CalculateVariables(default_variables, {'flavor': self.flavor})
+
+ # Compute filename prefix: the product prefix, or a default for
+ # the product type.
+ DEFAULT_PREFIX = {
+ 'loadable_module': default_variables['SHARED_LIB_PREFIX'],
+ 'shared_library': default_variables['SHARED_LIB_PREFIX'],
+ 'static_library': default_variables['STATIC_LIB_PREFIX'],
+ 'executable': default_variables['EXECUTABLE_PREFIX'],
+ }
+ prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(type, ''))
+
+ # Compute filename extension: the product extension, or a default
+ # for the product type.
+ DEFAULT_EXTENSION = {
+ 'loadable_module': default_variables['SHARED_LIB_SUFFIX'],
+ 'shared_library': default_variables['SHARED_LIB_SUFFIX'],
+ 'static_library': default_variables['STATIC_LIB_SUFFIX'],
+ 'executable': default_variables['EXECUTABLE_SUFFIX'],
+ }
+ extension = spec.get('product_extension')
+ if extension:
+ extension = '.' + extension
+ else:
+ extension = DEFAULT_EXTENSION.get(type, '')
+
+ if 'product_name' in spec:
+ # If we were given an explicit name, use that.
+ target = spec['product_name']
+ else:
+ # Otherwise, derive a name from the target name.
+ target = spec['target_name']
+ if prefix == 'lib':
+ # Snip out an extra 'lib' from libs if appropriate.
+ target = StripPrefix(target, 'lib')
+
+ if type in ('static_library', 'loadable_module', 'shared_library',
+ 'executable'):
+ return '%s%s%s' % (prefix, target, extension)
+ elif type == 'none':
+ return '%s.stamp' % target
+ else:
+ raise Exception('Unhandled output type %s' % type)
+
+ def ComputeOutput(self, spec, arch=None):
+ """Compute the path for the final output of the spec."""
+ type = spec['type']
+
+ if self.flavor == 'win':
+ override = self.msvs_settings.GetOutputName(self.config_name,
+ self.ExpandSpecial)
+ if override:
+ return override
+
+ if arch is None and self.flavor == 'mac' and type in (
+ 'static_library', 'executable', 'shared_library', 'loadable_module'):
+ filename = self.xcode_settings.GetExecutablePath()
+ else:
+ filename = self.ComputeOutputFileName(spec, type)
+
+ if arch is None and 'product_dir' in spec:
+ path = os.path.join(spec['product_dir'], filename)
+ return self.ExpandSpecial(path)
+
+ # Some products go into the output root, libraries go into shared library
+ # dir, and everything else goes into the normal place.
+ type_in_output_root = ['executable', 'loadable_module']
+ if self.flavor == 'mac' and self.toolset == 'target':
+ type_in_output_root += ['shared_library', 'static_library']
+ elif self.flavor == 'win' and self.toolset == 'target':
+ type_in_output_root += ['shared_library']
+
+ if arch is not None:
+ # Make sure partial executables don't end up in a bundle or the regular
+ # output directory.
+ archdir = 'arch'
+ if self.toolset != 'target':
+ archdir = os.path.join('arch', '%s' % self.toolset)
+ return os.path.join(archdir, AddArch(filename, arch))
+ elif type in type_in_output_root or self.is_standalone_static_library:
+ return filename
+ elif type == 'shared_library':
+ libdir = 'lib'
+ if self.toolset != 'target':
+ libdir = os.path.join('lib', '%s' % self.toolset)
+ return os.path.join(libdir, filename)
+ else:
+ return self.GypPathToUniqueOutput(filename, qualified=False)
+
+ def WriteVariableList(self, ninja_file, var, values):
+ assert not isinstance(values, str)
+ if values is None:
+ values = []
+ ninja_file.variable(var, ' '.join(values))
+
+ def WriteNewNinjaRule(self, name, args, description, is_cygwin, env):
+ """Write out a new ninja "rule" statement for a given command.
+
+ Returns the name of the new rule, and a copy of |args| with variables
+ expanded."""
+
+ if self.flavor == 'win':
+ args = [self.msvs_settings.ConvertVSMacros(
+ arg, self.base_to_build, config=self.config_name)
+ for arg in args]
+ description = self.msvs_settings.ConvertVSMacros(
+ description, config=self.config_name)
+ elif self.flavor == 'mac':
+ # |env| is an empty list on non-mac.
+ args = [gyp.xcode_emulation.ExpandEnvVars(arg, env) for arg in args]
+ description = gyp.xcode_emulation.ExpandEnvVars(description, env)
+
+ # TODO: we shouldn't need to qualify names; we do it because
+ # currently the ninja rule namespace is global, but it really
+ # should be scoped to the subninja.
+ rule_name = self.name
+ if self.toolset == 'target':
+ rule_name += '.' + self.toolset
+ rule_name += '.' + name
+ rule_name = re.sub('[^a-zA-Z0-9_]', '_', rule_name)
+
+ # Remove variable references, but not if they refer to the magic rule
+ # variables. This is not quite right, as it also protects these for
+ # actions, not just for rules where they are valid. Good enough.
+ protect = [ '${root}', '${dirname}', '${source}', '${ext}', '${name}' ]
+ protect = '(?!' + '|'.join(map(re.escape, protect)) + ')'
+ description = re.sub(protect + r'\$', '_', description)
+
+ # gyp dictates that commands are run from the base directory.
+ # cd into the directory before running, and adjust paths in
+ # the arguments to point to the proper locations.
+ rspfile = None
+ rspfile_content = None
+ args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args]
+ if self.flavor == 'win':
+ rspfile = rule_name + '.$unique_name.rsp'
+ # The cygwin case handles this inside the bash sub-shell.
+ run_in = '' if is_cygwin else ' ' + self.build_to_base
+ if is_cygwin:
+ rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine(
+ args, self.build_to_base)
+ else:
+ rspfile_content = gyp.msvs_emulation.EncodeRspFileList(args)
+ command = ('%s gyp-win-tool action-wrapper $arch ' % sys.executable +
+ rspfile + run_in)
+ else:
+ env = self.ComputeExportEnvString(env)
+ command = gyp.common.EncodePOSIXShellList(args)
+ command = 'cd %s; ' % self.build_to_base + env + command
+
+ # GYP rules/actions express being no-ops by not touching their outputs.
+ # Avoid executing downstream dependencies in this case by specifying
+ # restat=1 to ninja.
+ self.ninja.rule(rule_name, command, description, restat=True,
+ rspfile=rspfile, rspfile_content=rspfile_content)
+ self.ninja.newline()
+
+ return rule_name, args
+
+
+def CalculateVariables(default_variables, params):
+ """Calculate additional variables for use in the build (called by gyp)."""
+ global generator_additional_non_configuration_keys
+ global generator_additional_path_sections
+ flavor = gyp.common.GetFlavor(params)
+ if flavor == 'mac':
+ default_variables.setdefault('OS', 'mac')
+ default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
+ default_variables.setdefault('SHARED_LIB_DIR',
+ generator_default_variables['PRODUCT_DIR'])
+ default_variables.setdefault('LIB_DIR',
+ generator_default_variables['PRODUCT_DIR'])
+
+ # Copy additional generator configuration data from Xcode, which is shared
+ # by the Mac Ninja generator.
+ import gyp.generator.xcode as xcode_generator
+ generator_additional_non_configuration_keys = getattr(xcode_generator,
+ 'generator_additional_non_configuration_keys', [])
+ generator_additional_path_sections = getattr(xcode_generator,
+ 'generator_additional_path_sections', [])
+ global generator_extra_sources_for_rules
+ generator_extra_sources_for_rules = getattr(xcode_generator,
+ 'generator_extra_sources_for_rules', [])
+ elif flavor == 'win':
+ default_variables.setdefault('OS', 'win')
+ default_variables['EXECUTABLE_SUFFIX'] = '.exe'
+ default_variables['STATIC_LIB_PREFIX'] = ''
+ default_variables['STATIC_LIB_SUFFIX'] = '.lib'
+ default_variables['SHARED_LIB_PREFIX'] = ''
+ default_variables['SHARED_LIB_SUFFIX'] = '.dll'
+ generator_flags = params.get('generator_flags', {})
+
+ # Copy additional generator configuration data from VS, which is shared
+ # by the Windows Ninja generator.
+ import gyp.generator.msvs as msvs_generator
+ generator_additional_non_configuration_keys = getattr(msvs_generator,
+ 'generator_additional_non_configuration_keys', [])
+ generator_additional_path_sections = getattr(msvs_generator,
+ 'generator_additional_path_sections', [])
+
+ # Set a variable so conditions can be based on msvs_version.
+ msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags)
+ default_variables['MSVS_VERSION'] = msvs_version.ShortName()
+
+ # To determine processor word size on Windows, in addition to checking
+ # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
+ # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
+ # contains the actual word size of the system when running thru WOW64).
+ if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
+ '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
+ default_variables['MSVS_OS_BITS'] = 64
+ else:
+ default_variables['MSVS_OS_BITS'] = 32
+ else:
+ operating_system = flavor
+ if flavor == 'android':
+ operating_system = 'linux' # Keep this legacy behavior for now.
+ default_variables.setdefault('OS', operating_system)
+ default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
+ default_variables.setdefault('SHARED_LIB_DIR',
+ os.path.join('$!PRODUCT_DIR', 'lib'))
+ # Take into account the fact that toplevel_dir might not be equal to depth
+ toplevel_offset = ''
+ if 'options' in params:
+ options = params['options']
+ toplevel_offset = os.path.relpath(options.depth, options.toplevel_dir)
+ default_variables.setdefault('LIB_DIR',
+ os.path.join('$!PRODUCT_DIR', 'obj', toplevel_offset))
+
+def OpenOutput(path, mode='w'):
+ """Open |path| for writing, creating directories if necessary."""
+ try:
+ os.makedirs(os.path.dirname(path))
+ except OSError:
+ pass
+ return open(path, mode)
+
+
+def CommandWithWrapper(cmd, wrappers, prog):
+ wrapper = wrappers.get(cmd, '')
+ if wrapper:
+ return wrapper + ' ' + prog
+ return prog
+
+
+def GetDefaultConcurrentLinks():
+ """Returns a best-guess for a number of concurrent links."""
+ if sys.platform in ('win32', 'cygwin'):
+ import ctypes
+
+ class MEMORYSTATUSEX(ctypes.Structure):
+ _fields_ = [
+ ("dwLength", ctypes.c_ulong),
+ ("dwMemoryLoad", ctypes.c_ulong),
+ ("ullTotalPhys", ctypes.c_ulonglong),
+ ("ullAvailPhys", ctypes.c_ulonglong),
+ ("ullTotalPageFile", ctypes.c_ulonglong),
+ ("ullAvailPageFile", ctypes.c_ulonglong),
+ ("ullTotalVirtual", ctypes.c_ulonglong),
+ ("ullAvailVirtual", ctypes.c_ulonglong),
+ ("sullAvailExtendedVirtual", ctypes.c_ulonglong),
+ ]
+
+ stat = MEMORYSTATUSEX()
+ stat.dwLength = ctypes.sizeof(stat)
+ ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))
+
+ return max(1, stat.ullTotalPhys / (4 * (2 ** 30))) # total / 4GB
+ else:
+ # TODO(scottmg): Implement this for other platforms.
+ return 1
+
+
+def _GetWinLinkRuleNameSuffix(embed_manifest, link_incremental):
+ """Returns the suffix used to select an appropriate linking rule depending on
+ whether the manifest embedding and/or incremental linking is enabled."""
+ suffix = ''
+ if embed_manifest:
+ suffix += '_embed'
+ if link_incremental:
+ suffix += '_inc'
+ return suffix
+
+
+def _AddWinLinkRules(master_ninja, embed_manifest, link_incremental):
+ """Adds link rules for Windows platform to |master_ninja|."""
+ def FullLinkCommand(ldcmd, out, binary_type):
+ cmd = ('cmd /c %(ldcmd)s'
+ ' && %(python)s gyp-win-tool manifest-wrapper $arch'
+ ' cmd /c if exist %(out)s.manifest del %(out)s.manifest'
+ ' && %(python)s gyp-win-tool manifest-wrapper $arch'
+ ' $mt -nologo -manifest $manifests')
+ if embed_manifest and not link_incremental:
+ # Embed manifest into a binary. If incremental linking is enabled,
+ # embedding is postponed to the re-linking stage (see below).
+ cmd += ' -outputresource:%(out)s;%(resname)s'
+ else:
+ # Save manifest as an external file.
+ cmd += ' -out:%(out)s.manifest'
+ if link_incremental:
+ # There is no point in generating separate rule for the case when
+ # incremental linking is enabled, but manifest embedding is disabled.
+ # In that case the basic rule should be used (e.g. 'link').
+ # See also implementation of _GetWinLinkRuleNameSuffix().
+ assert embed_manifest
+ # Make .rc file out of manifest, compile it to .res file and re-link.
+ cmd += (' && %(python)s gyp-win-tool manifest-to-rc $arch'
+ ' %(out)s.manifest %(out)s.manifest.rc %(resname)s'
+ ' && %(python)s gyp-win-tool rc-wrapper $arch $rc'
+ ' %(out)s.manifest.rc'
+ ' && %(ldcmd)s %(out)s.manifest.res')
+ resource_name = {
+ 'exe': '1',
+ 'dll': '2',
+ }[binary_type]
+ return cmd % {'python': sys.executable,
+ 'out': out,
+ 'ldcmd': ldcmd,
+ 'resname': resource_name}
+
+ rule_name_suffix = _GetWinLinkRuleNameSuffix(embed_manifest, link_incremental)
+ dlldesc = 'LINK%s(DLL) $dll' % rule_name_suffix.upper()
+ dllcmd = ('%s gyp-win-tool link-wrapper $arch '
+ '$ld /nologo $implibflag /DLL /OUT:$dll '
+ '/PDB:$dll.pdb @$dll.rsp' % sys.executable)
+ dllcmd = FullLinkCommand(dllcmd, '$dll', 'dll')
+ master_ninja.rule('solink' + rule_name_suffix,
+ description=dlldesc, command=dllcmd,
+ rspfile='$dll.rsp',
+ rspfile_content='$libs $in_newline $ldflags',
+ restat=True)
+ master_ninja.rule('solink_module' + rule_name_suffix,
+ description=dlldesc, command=dllcmd,
+ rspfile='$dll.rsp',
+ rspfile_content='$libs $in_newline $ldflags',
+ restat=True)
+ # Note that ldflags goes at the end so that it has the option of
+ # overriding default settings earlier in the command line.
+ exe_cmd = ('%s gyp-win-tool link-wrapper $arch '
+ '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' %
+ sys.executable)
+ exe_cmd = FullLinkCommand(exe_cmd, '$out', 'exe')
+ master_ninja.rule('link' + rule_name_suffix,
+ description='LINK%s $out' % rule_name_suffix.upper(),
+ command=exe_cmd,
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline $libs $ldflags')
+
+
+def GenerateOutputForConfig(target_list, target_dicts, data, params,
+ config_name):
+ options = params['options']
+ flavor = gyp.common.GetFlavor(params)
+ generator_flags = params.get('generator_flags', {})
+
+ # generator_dir: relative path from pwd to where make puts build files.
+ # Makes migrating from make to ninja easier, ninja doesn't put anything here.
+ generator_dir = os.path.relpath(params['options'].generator_output or '.')
+
+ # output_dir: relative path from generator_dir to the build directory.
+ output_dir = generator_flags.get('output_dir', 'out')
+
+ # build_dir: relative path from source root to our output files.
+ # e.g. "out/Debug"
+ build_dir = os.path.normpath(os.path.join(generator_dir,
+ output_dir,
+ config_name))
+
+ toplevel_build = os.path.join(options.toplevel_dir, build_dir)
+
+ master_ninja = ninja_syntax.Writer(
+ OpenOutput(os.path.join(toplevel_build, 'build.ninja')),
+ width=120)
+ case_sensitive_filesystem = not os.path.exists(
+ os.path.join(toplevel_build, 'BUILD.NINJA'))
+
+ # Put build-time support tools in out/{config_name}.
+ gyp.common.CopyTool(flavor, toplevel_build)
+
+ # Grab make settings for CC/CXX.
+ # The rules are
+ # - The priority from low to high is gcc/g++, the 'make_global_settings' in
+ # gyp, the environment variable.
+ # - If there is no 'make_global_settings' for CC.host/CXX.host or
+ # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set
+ # to cc/cxx.
+ if flavor == 'win':
+ # Overridden by local arch choice in the use_deps case.
+ # Chromium's ffmpeg c99conv.py currently looks for a 'cc =' line in
+ # build.ninja so needs something valid here. http://crbug.com/233985
+ cc = 'cl.exe'
+ cxx = 'cl.exe'
+ ld = 'link.exe'
+ ld_host = '$ld'
+ else:
+ cc = 'gcc'
+ cxx = 'g++'
+ ld = '$cxx'
+ ld_host = '$cxx_host'
+
+ cc_host = None
+ cxx_host = None
+ cc_host_global_setting = None
+ cxx_host_global_setting = None
+
+ build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
+ make_global_settings = data[build_file].get('make_global_settings', [])
+ build_to_root = gyp.common.InvertRelativePath(build_dir,
+ options.toplevel_dir)
+ wrappers = {}
+ for key, value in make_global_settings:
+ if key == 'CC':
+ cc = os.path.join(build_to_root, value)
+ if key == 'CXX':
+ cxx = os.path.join(build_to_root, value)
+ if key == 'LD':
+ ld = os.path.join(build_to_root, value)
+ if key == 'CC.host':
+ cc_host = os.path.join(build_to_root, value)
+ cc_host_global_setting = value
+ if key == 'CXX.host':
+ cxx_host = os.path.join(build_to_root, value)
+ cxx_host_global_setting = value
+ if key == 'LD.host':
+ ld_host = os.path.join(build_to_root, value)
+ if key.endswith('_wrapper'):
+ wrappers[key[:-len('_wrapper')]] = os.path.join(build_to_root, value)
+
+ # Support wrappers from environment variables too.
+ for key, value in os.environ.iteritems():
+ if key.lower().endswith('_wrapper'):
+ key_prefix = key[:-len('_wrapper')]
+ key_prefix = re.sub(r'\.HOST$', '.host', key_prefix)
+ wrappers[key_prefix] = os.path.join(build_to_root, value)
+
+ if flavor == 'win':
+ cl_paths = gyp.msvs_emulation.GenerateEnvironmentFiles(
+ toplevel_build, generator_flags, OpenOutput)
+ for arch, path in cl_paths.iteritems():
+ master_ninja.variable(
+ 'cl_' + arch, CommandWithWrapper('CC', wrappers,
+ QuoteShellArgument(path, flavor)))
+
+ cc = GetEnvironFallback(['CC_target', 'CC'], cc)
+ master_ninja.variable('cc', CommandWithWrapper('CC', wrappers, cc))
+ cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx)
+ master_ninja.variable('cxx', CommandWithWrapper('CXX', wrappers, cxx))
+ ld = GetEnvironFallback(['LD_target', 'LD'], ld)
+
+ if flavor == 'win':
+ master_ninja.variable('ld', ld)
+ master_ninja.variable('idl', 'midl.exe')
+ master_ninja.variable('ar', 'lib.exe')
+ master_ninja.variable('rc', 'rc.exe')
+ master_ninja.variable('asm', 'ml.exe')
+ master_ninja.variable('mt', 'mt.exe')
+ else:
+ master_ninja.variable('ld', CommandWithWrapper('LINK', wrappers, ld))
+ master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], 'ar'))
+
+ if generator_supports_multiple_toolsets:
+ if not cc_host:
+ cc_host = cc
+ if not cxx_host:
+ cxx_host = cxx
+
+ master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], 'ar'))
+ cc_host = GetEnvironFallback(['CC_host'], cc_host)
+ cxx_host = GetEnvironFallback(['CXX_host'], cxx_host)
+ ld_host = GetEnvironFallback(['LD_host'], ld_host)
+
+ # The environment variable could be used in 'make_global_settings', like
+ # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here.
+ if '$(CC)' in cc_host and cc_host_global_setting:
+ cc_host = cc_host_global_setting.replace('$(CC)', cc)
+ if '$(CXX)' in cxx_host and cxx_host_global_setting:
+ cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx)
+ master_ninja.variable('cc_host',
+ CommandWithWrapper('CC.host', wrappers, cc_host))
+ master_ninja.variable('cxx_host',
+ CommandWithWrapper('CXX.host', wrappers, cxx_host))
+ if flavor == 'win':
+ master_ninja.variable('ld_host', ld_host)
+ else:
+ master_ninja.variable('ld_host', CommandWithWrapper(
+ 'LINK', wrappers, ld_host))
+
+ master_ninja.newline()
+
+ master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks())
+ master_ninja.newline()
+
+ deps = 'msvc' if flavor == 'win' else 'gcc'
+
+ if flavor != 'win':
+ master_ninja.rule(
+ 'cc',
+ description='CC $out',
+ command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
+ '$cflags_pch_c -c $in -o $out'),
+ depfile='$out.d',
+ deps=deps)
+ master_ninja.rule(
+ 'cc_s',
+ description='CC $out',
+ command=('$cc $defines $includes $cflags $cflags_c '
+ '$cflags_pch_c -c $in -o $out'))
+ master_ninja.rule(
+ 'cxx',
+ description='CXX $out',
+ command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
+ '$cflags_pch_cc -c $in -o $out'),
+ depfile='$out.d',
+ deps=deps)
+ else:
+ cc_command = ('ninja -t msvc -e $arch ' +
+ '-- '
+ '$cc /nologo /showIncludes /FC '
+ '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
+ cxx_command = ('ninja -t msvc -e $arch ' +
+ '-- '
+ '$cxx /nologo /showIncludes /FC '
+ '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
+ master_ninja.rule(
+ 'cc',
+ description='CC $out',
+ command=cc_command,
+ rspfile='$out.rsp',
+ rspfile_content='$defines $includes $cflags $cflags_c',
+ deps=deps)
+ master_ninja.rule(
+ 'cxx',
+ description='CXX $out',
+ command=cxx_command,
+ rspfile='$out.rsp',
+ rspfile_content='$defines $includes $cflags $cflags_cc',
+ deps=deps)
+ master_ninja.rule(
+ 'idl',
+ description='IDL $in',
+ command=('%s gyp-win-tool midl-wrapper $arch $outdir '
+ '$tlb $h $dlldata $iid $proxy $in '
+ '$idlflags' % sys.executable))
+ master_ninja.rule(
+ 'rc',
+ description='RC $in',
+ # Note: $in must be last otherwise rc.exe complains.
+ command=('%s gyp-win-tool rc-wrapper '
+ '$arch $rc $defines $includes $rcflags /fo$out $in' %
+ sys.executable))
+ master_ninja.rule(
+ 'asm',
+ description='ASM $in',
+ command=('%s gyp-win-tool asm-wrapper '
+ '$arch $asm $defines $includes /c /Fo $out $in' %
+ sys.executable))
+
+ if flavor != 'mac' and flavor != 'win':
+ master_ninja.rule(
+ 'alink',
+ description='AR $out',
+ command='rm -f $out && $ar rcs $out $in')
+ master_ninja.rule(
+ 'alink_thin',
+ description='AR $out',
+ command='rm -f $out && $ar rcsT $out $in')
+
+ # This allows targets that only need to depend on $lib's API to declare an
+ # order-only dependency on $lib.TOC and avoid relinking such downstream
+ # dependencies when $lib changes only in non-public ways.
+ # The resulting string leaves an uninterpolated %{suffix} which
+ # is used in the final substitution below.
+ mtime_preserving_solink_base = (
+ 'if [ ! -e $lib -o ! -e ${lib}.TOC ]; then '
+ '%(solink)s && %(extract_toc)s > ${lib}.TOC; else '
+ '%(solink)s && %(extract_toc)s > ${lib}.tmp && '
+ 'if ! cmp -s ${lib}.tmp ${lib}.TOC; then mv ${lib}.tmp ${lib}.TOC ; '
+ 'fi; fi'
+ % { 'solink':
+ '$ld -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s',
+ 'extract_toc':
+ ('{ readelf -d ${lib} | grep SONAME ; '
+ 'nm -gD -f p ${lib} | cut -f1-2 -d\' \'; }')})
+
+ master_ninja.rule(
+ 'solink',
+ description='SOLINK $lib',
+ restat=True,
+ command=(mtime_preserving_solink_base % {
+ 'suffix': '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive '
+ '$libs'}),
+ pool='link_pool')
+ master_ninja.rule(
+ 'solink_module',
+ description='SOLINK(module) $lib',
+ restat=True,
+ command=(mtime_preserving_solink_base % {
+ 'suffix': '-Wl,--start-group $in $solibs -Wl,--end-group '
+ '$libs'}),
+ pool='link_pool')
+ master_ninja.rule(
+ 'link',
+ description='LINK $out',
+ command=('$ld $ldflags -o $out '
+ '-Wl,--start-group $in $solibs -Wl,--end-group $libs'),
+ pool='link_pool')
+ elif flavor == 'win':
+ master_ninja.rule(
+ 'alink',
+ description='LIB $out',
+ command=('%s gyp-win-tool link-wrapper $arch '
+ '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' %
+ sys.executable),
+ rspfile='$out.rsp',
+ rspfile_content='$in_newline $libflags')
+ _AddWinLinkRules(master_ninja, embed_manifest=True, link_incremental=True)
+ _AddWinLinkRules(master_ninja, embed_manifest=True, link_incremental=False)
+ _AddWinLinkRules(master_ninja, embed_manifest=False, link_incremental=False)
+ # Do not generate rules for embed_manifest=False and link_incremental=True
+ # because in that case rules for (False, False) should be used (see
+ # implementation of _GetWinLinkRuleNameSuffix()).
+ else:
+ master_ninja.rule(
+ 'objc',
+ description='OBJC $out',
+ command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
+ '$cflags_pch_objc -c $in -o $out'),
+ depfile='$out.d',
+ deps=deps)
+ master_ninja.rule(
+ 'objcxx',
+ description='OBJCXX $out',
+ command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc '
+ '$cflags_pch_objcc -c $in -o $out'),
+ depfile='$out.d',
+ deps=deps)
+ master_ninja.rule(
+ 'alink',
+ description='LIBTOOL-STATIC $out, POSTBUILDS',
+ command='rm -f $out && '
+ './gyp-mac-tool filter-libtool libtool $libtool_flags '
+ '-static -o $out $in'
+ '$postbuilds')
+ master_ninja.rule(
+ 'lipo',
+ description='LIPO $out, POSTBUILDS',
+ command='rm -f $out && lipo -create $in -output $out$postbuilds')
+
+ # Record the public interface of $lib in $lib.TOC. See the corresponding
+ # comment in the posix section above for details.
+ mtime_preserving_solink_base = (
+ 'if [ ! -e $lib -o ! -e ${lib}.TOC ] || '
+ # Always force dependent targets to relink if this library
+ # reexports something. Handling this correctly would require
+ # recursive TOC dumping but this is rare in practice, so punt.
+ 'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then '
+ '%(solink)s && %(extract_toc)s > ${lib}.TOC; '
+ 'else '
+ '%(solink)s && %(extract_toc)s > ${lib}.tmp && '
+ 'if ! cmp -s ${lib}.tmp ${lib}.TOC; then '
+ 'mv ${lib}.tmp ${lib}.TOC ; '
+ 'fi; '
+ 'fi'
+ % { 'solink': '$ld -shared $ldflags -o $lib %(suffix)s',
+ 'extract_toc':
+ '{ otool -l $lib | grep LC_ID_DYLIB -A 5; '
+ 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'})
+
+ # TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
+ # -bundle -single_module here (for osmesa.so).
+ master_ninja.rule(
+ 'solink',
+ description='SOLINK $lib, POSTBUILDS',
+ restat=True,
+ command=(mtime_preserving_solink_base % {
+ 'suffix': '$in $solibs $libs$postbuilds'}),
+ pool='link_pool')
+ master_ninja.rule(
+ 'solink_module',
+ description='SOLINK(module) $lib, POSTBUILDS',
+ restat=True,
+ command=(mtime_preserving_solink_base % {
+ 'suffix': '$in $solibs $libs$postbuilds'}),
+ pool='link_pool')
+
+ master_ninja.rule(
+ 'link',
+ description='LINK $out, POSTBUILDS',
+ command=('$ld $ldflags -o $out '
+ '$in $solibs $libs$postbuilds'),
+ pool='link_pool')
+ master_ninja.rule(
+ 'infoplist',
+ description='INFOPLIST $out',
+ command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && '
+ 'plutil -convert xml1 $out $out'))
+ master_ninja.rule(
+ 'mac_tool',
+ description='MACTOOL $mactool_cmd $in',
+ command='$env ./gyp-mac-tool $mactool_cmd $in $out')
+ master_ninja.rule(
+ 'package_framework',
+ description='PACKAGE FRAMEWORK $out, POSTBUILDS',
+ command='./gyp-mac-tool package-framework $out $version$postbuilds '
+ '&& touch $out')
+ if flavor == 'win':
+ master_ninja.rule(
+ 'stamp',
+ description='STAMP $out',
+ command='%s gyp-win-tool stamp $out' % sys.executable)
+ master_ninja.rule(
+ 'copy',
+ description='COPY $in $out',
+ command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable)
+ else:
+ master_ninja.rule(
+ 'stamp',
+ description='STAMP $out',
+ command='${postbuilds}touch $out')
+ master_ninja.rule(
+ 'copy',
+ description='COPY $in $out',
+ command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)')
+ master_ninja.newline()
+
+ all_targets = set()
+ for build_file in params['build_files']:
+ for target in gyp.common.AllTargets(target_list,
+ target_dicts,
+ os.path.normpath(build_file)):
+ all_targets.add(target)
+ all_outputs = set()
+
+ # target_outputs is a map from qualified target name to a Target object.
+ target_outputs = {}
+ # target_short_names is a map from target short name to a list of Target
+ # objects.
+ target_short_names = {}
+ for qualified_target in target_list:
+ # qualified_target is like: third_party/icu/icu.gyp:icui18n#target
+ build_file, name, toolset = \
+ gyp.common.ParseQualifiedTarget(qualified_target)
+
+ this_make_global_settings = data[build_file].get('make_global_settings', [])
+ assert make_global_settings == this_make_global_settings, (
+ "make_global_settings needs to be the same for all targets.")
+
+ spec = target_dicts[qualified_target]
+ if flavor == 'mac':
+ gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec)
+
+ build_file = gyp.common.RelativePath(build_file, options.toplevel_dir)
+
+ base_path = os.path.dirname(build_file)
+ obj = 'obj'
+ if toolset != 'target':
+ obj += '.' + toolset
+ output_file = os.path.join(obj, base_path, name + '.ninja')
+
+ writer = NinjaWriter(qualified_target, target_outputs, base_path, build_dir,
+ OpenOutput(os.path.join(toplevel_build, output_file)),
+ toplevel_build, output_file,
+ flavor, toplevel_dir=options.toplevel_dir)
+ master_ninja.subninja(output_file)
+
+ target = writer.WriteSpec(
+ spec, config_name, generator_flags, case_sensitive_filesystem)
+ if target:
+ if name != target.FinalOutput() and spec['toolset'] == 'target':
+ target_short_names.setdefault(name, []).append(target)
+ target_outputs[qualified_target] = target
+ if qualified_target in all_targets:
+ all_outputs.add(target.FinalOutput())
+
+ if target_short_names:
+ # Write a short name to build this target. This benefits both the
+ # "build chrome" case as well as the gyp tests, which expect to be
+ # able to run actions and build libraries by their short name.
+ master_ninja.newline()
+ master_ninja.comment('Short names for targets.')
+ for short_name in target_short_names:
+ master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in
+ target_short_names[short_name]])
+
+ if all_outputs:
+ master_ninja.newline()
+ master_ninja.build('all', 'phony', list(all_outputs))
+ master_ninja.default(generator_flags.get('default_target', 'all'))
+
+
+def PerformBuild(data, configurations, params):
+ options = params['options']
+ for config in configurations:
+ builddir = os.path.join(options.toplevel_dir, 'out', config)
+ arguments = ['ninja', '-C', builddir]
+ print 'Building [%s]: %s' % (config, arguments)
+ subprocess.check_call(arguments)
+
+
+def CallGenerateOutputForConfig(arglist):
+ # Ignore the interrupt signal so that the parent process catches it and
+ # kills all multiprocessing children.
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+ (target_list, target_dicts, data, params, config_name) = arglist
+ GenerateOutputForConfig(target_list, target_dicts, data, params, config_name)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ user_config = params.get('generator_flags', {}).get('config', None)
+ if gyp.common.GetFlavor(params) == 'win':
+ target_list, target_dicts = MSVSUtil.ShardTargets(target_list, target_dicts)
+ target_list, target_dicts = MSVSUtil.InsertLargePdbShims(
+ target_list, target_dicts, generator_default_variables)
+
+ if user_config:
+ GenerateOutputForConfig(target_list, target_dicts, data, params,
+ user_config)
+ else:
+ config_names = target_dicts[target_list[0]]['configurations'].keys()
+ if params['parallel']:
+ try:
+ pool = multiprocessing.Pool(len(config_names))
+ arglists = []
+ for config_name in config_names:
+ arglists.append(
+ (target_list, target_dicts, data, params, config_name))
+ pool.map(CallGenerateOutputForConfig, arglists)
+ except KeyboardInterrupt, e:
+ pool.terminate()
+ raise e
+ else:
+ for config_name in config_names:
+ GenerateOutputForConfig(target_list, target_dicts, data, params,
+ config_name)
diff --git a/chromium/tools/gyp/pylib/gyp/generator/ninja_test.py b/chromium/tools/gyp/pylib/gyp/generator/ninja_test.py
new file mode 100644
index 00000000000..52661bcdf09
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/ninja_test.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Unit tests for the ninja.py file. """
+
+import gyp.generator.ninja as ninja
+import unittest
+import StringIO
+import sys
+import TestCommon
+
+
+class TestPrefixesAndSuffixes(unittest.TestCase):
+ def test_BinaryNamesWindows(self):
+ writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.',
+ 'build.ninja', 'win')
+ spec = { 'target_name': 'wee' }
+ self.assertTrue(writer.ComputeOutputFileName(spec, 'executable').
+ endswith('.exe'))
+ self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library').
+ endswith('.dll'))
+ self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library').
+ endswith('.lib'))
+
+ def test_BinaryNamesLinux(self):
+ writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.',
+ 'build.ninja', 'linux')
+ spec = { 'target_name': 'wee' }
+ self.assertTrue('.' not in writer.ComputeOutputFileName(spec,
+ 'executable'))
+ self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library').
+ startswith('lib'))
+ self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library').
+ startswith('lib'))
+ self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library').
+ endswith('.so'))
+ self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library').
+ endswith('.a'))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/gyp/pylib/gyp/generator/xcode.py b/chromium/tools/gyp/pylib/gyp/generator/xcode.py
new file mode 100644
index 00000000000..0229b5c7864
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/xcode.py
@@ -0,0 +1,1245 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import filecmp
+import gyp.common
+import gyp.xcodeproj_file
+import errno
+import os
+import sys
+import posixpath
+import re
+import shutil
+import subprocess
+import tempfile
+
+
+# Project files generated by this module will use _intermediate_var as a
+# custom Xcode setting whose value is a DerivedSources-like directory that's
+# project-specific and configuration-specific. The normal choice,
+# DERIVED_FILE_DIR, is target-specific, which is thought to be too restrictive
+# as it is likely that multiple targets within a single project file will want
+# to access the same set of generated files. The other option,
+# PROJECT_DERIVED_FILE_DIR, is unsuitable because while it is project-specific,
+# it is not configuration-specific. INTERMEDIATE_DIR is defined as
+# $(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION).
+_intermediate_var = 'INTERMEDIATE_DIR'
+
+# SHARED_INTERMEDIATE_DIR is the same, except that it is shared among all
+# targets that share the same BUILT_PRODUCTS_DIR.
+_shared_intermediate_var = 'SHARED_INTERMEDIATE_DIR'
+
+_library_search_paths_var = 'LIBRARY_SEARCH_PATHS'
+
+generator_default_variables = {
+ 'EXECUTABLE_PREFIX': '',
+ 'EXECUTABLE_SUFFIX': '',
+ 'STATIC_LIB_PREFIX': 'lib',
+ 'SHARED_LIB_PREFIX': 'lib',
+ 'STATIC_LIB_SUFFIX': '.a',
+ 'SHARED_LIB_SUFFIX': '.dylib',
+ # INTERMEDIATE_DIR is a place for targets to build up intermediate products.
+ # It is specific to each build environment. It is only guaranteed to exist
+ # and be constant within the context of a project, corresponding to a single
+ # input file. Some build environments may allow their intermediate directory
+ # to be shared on a wider scale, but this is not guaranteed.
+ 'INTERMEDIATE_DIR': '$(%s)' % _intermediate_var,
+ 'OS': 'mac',
+ 'PRODUCT_DIR': '$(BUILT_PRODUCTS_DIR)',
+ 'LIB_DIR': '$(BUILT_PRODUCTS_DIR)',
+ 'RULE_INPUT_ROOT': '$(INPUT_FILE_BASE)',
+ 'RULE_INPUT_EXT': '$(INPUT_FILE_SUFFIX)',
+ 'RULE_INPUT_NAME': '$(INPUT_FILE_NAME)',
+ 'RULE_INPUT_PATH': '$(INPUT_FILE_PATH)',
+ 'RULE_INPUT_DIRNAME': '$(INPUT_FILE_DIRNAME)',
+ 'SHARED_INTERMEDIATE_DIR': '$(%s)' % _shared_intermediate_var,
+ 'CONFIGURATION_NAME': '$(CONFIGURATION)',
+}
+
+# The Xcode-specific sections that hold paths.
+generator_additional_path_sections = [
+ 'mac_bundle_resources',
+ 'mac_framework_headers',
+ 'mac_framework_private_headers',
+ # 'mac_framework_dirs', input already handles _dirs endings.
+]
+
+# The Xcode-specific keys that exist on targets and aren't moved down to
+# configurations.
+generator_additional_non_configuration_keys = [
+ 'mac_bundle',
+ 'mac_bundle_resources',
+ 'mac_framework_headers',
+ 'mac_framework_private_headers',
+ 'xcode_create_dependents_test_runner',
+]
+
+# We want to let any rules apply to files that are resources also.
+generator_extra_sources_for_rules = [
+ 'mac_bundle_resources',
+ 'mac_framework_headers',
+ 'mac_framework_private_headers',
+]
+
+# Xcode's standard set of library directories, which don't need to be duplicated
+# in LIBRARY_SEARCH_PATHS. This list is not exhaustive, but that's okay.
+xcode_standard_library_dirs = frozenset([
+ '$(SDKROOT)/usr/lib',
+ '$(SDKROOT)/usr/local/lib',
+])
+
+def CreateXCConfigurationList(configuration_names):
+ xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []})
+ if len(configuration_names) == 0:
+ configuration_names = ['Default']
+ for configuration_name in configuration_names:
+ xcbc = gyp.xcodeproj_file.XCBuildConfiguration({
+ 'name': configuration_name})
+ xccl.AppendProperty('buildConfigurations', xcbc)
+ xccl.SetProperty('defaultConfigurationName', configuration_names[0])
+ return xccl
+
+
+class XcodeProject(object):
+ def __init__(self, gyp_path, path, build_file_dict):
+ self.gyp_path = gyp_path
+ self.path = path
+ self.project = gyp.xcodeproj_file.PBXProject(path=path)
+ projectDirPath = gyp.common.RelativePath(
+ os.path.dirname(os.path.abspath(self.gyp_path)),
+ os.path.dirname(path) or '.')
+ self.project.SetProperty('projectDirPath', projectDirPath)
+ self.project_file = \
+ gyp.xcodeproj_file.XCProjectFile({'rootObject': self.project})
+ self.build_file_dict = build_file_dict
+
+ # TODO(mark): add destructor that cleans up self.path if created_dir is
+ # True and things didn't complete successfully. Or do something even
+ # better with "try"?
+ self.created_dir = False
+ try:
+ os.makedirs(self.path)
+ self.created_dir = True
+ except OSError, e:
+ if e.errno != errno.EEXIST:
+ raise
+
+ def Finalize1(self, xcode_targets, serialize_all_tests):
+ # Collect a list of all of the build configuration names used by the
+ # various targets in the file. It is very heavily advised to keep each
+ # target in an entire project (even across multiple project files) using
+ # the same set of configuration names.
+ configurations = []
+ for xct in self.project.GetProperty('targets'):
+ xccl = xct.GetProperty('buildConfigurationList')
+ xcbcs = xccl.GetProperty('buildConfigurations')
+ for xcbc in xcbcs:
+ name = xcbc.GetProperty('name')
+ if name not in configurations:
+ configurations.append(name)
+
+ # Replace the XCConfigurationList attached to the PBXProject object with
+ # a new one specifying all of the configuration names used by the various
+ # targets.
+ try:
+ xccl = CreateXCConfigurationList(configurations)
+ self.project.SetProperty('buildConfigurationList', xccl)
+ except:
+ sys.stderr.write("Problem with gyp file %s\n" % self.gyp_path)
+ raise
+
+ # The need for this setting is explained above where _intermediate_var is
+ # defined. The comments below about wanting to avoid project-wide build
+ # settings apply here too, but this needs to be set on a project-wide basis
+ # so that files relative to the _intermediate_var setting can be displayed
+ # properly in the Xcode UI.
+ #
+ # Note that for configuration-relative files such as anything relative to
+ # _intermediate_var, for the purposes of UI tree view display, Xcode will
+ # only resolve the configuration name once, when the project file is
+ # opened. If the active build configuration is changed, the project file
+ # must be closed and reopened if it is desired for the tree view to update.
+ # This is filed as Apple radar 6588391.
+ xccl.SetBuildSetting(_intermediate_var,
+ '$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)')
+ xccl.SetBuildSetting(_shared_intermediate_var,
+ '$(SYMROOT)/DerivedSources/$(CONFIGURATION)')
+
+ # Set user-specified project-wide build settings and config files. This
+ # is intended to be used very sparingly. Really, almost everything should
+ # go into target-specific build settings sections. The project-wide
+ # settings are only intended to be used in cases where Xcode attempts to
+ # resolve variable references in a project context as opposed to a target
+ # context, such as when resolving sourceTree references while building up
+ # the tree tree view for UI display.
+ # Any values set globally are applied to all configurations, then any
+ # per-configuration values are applied.
+ for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems():
+ xccl.SetBuildSetting(xck, xcv)
+ if 'xcode_config_file' in self.build_file_dict:
+ config_ref = self.project.AddOrGetFileInRootGroup(
+ self.build_file_dict['xcode_config_file'])
+ xccl.SetBaseConfiguration(config_ref)
+ build_file_configurations = self.build_file_dict.get('configurations', {})
+ if build_file_configurations:
+ for config_name in configurations:
+ build_file_configuration_named = \
+ build_file_configurations.get(config_name, {})
+ if build_file_configuration_named:
+ xcc = xccl.ConfigurationNamed(config_name)
+ for xck, xcv in build_file_configuration_named.get('xcode_settings',
+ {}).iteritems():
+ xcc.SetBuildSetting(xck, xcv)
+ if 'xcode_config_file' in build_file_configuration_named:
+ config_ref = self.project.AddOrGetFileInRootGroup(
+ build_file_configurations[config_name]['xcode_config_file'])
+ xcc.SetBaseConfiguration(config_ref)
+
+ # Sort the targets based on how they appeared in the input.
+ # TODO(mark): Like a lot of other things here, this assumes internal
+ # knowledge of PBXProject - in this case, of its "targets" property.
+
+ # ordinary_targets are ordinary targets that are already in the project
+ # file. run_test_targets are the targets that run unittests and should be
+ # used for the Run All Tests target. support_targets are the action/rule
+ # targets used by GYP file targets, just kept for the assert check.
+ ordinary_targets = []
+ run_test_targets = []
+ support_targets = []
+
+ # targets is full list of targets in the project.
+ targets = []
+
+ # does the it define it's own "all"?
+ has_custom_all = False
+
+ # targets_for_all is the list of ordinary_targets that should be listed
+ # in this project's "All" target. It includes each non_runtest_target
+ # that does not have suppress_wildcard set.
+ targets_for_all = []
+
+ for target in self.build_file_dict['targets']:
+ target_name = target['target_name']
+ toolset = target['toolset']
+ qualified_target = gyp.common.QualifiedTarget(self.gyp_path, target_name,
+ toolset)
+ xcode_target = xcode_targets[qualified_target]
+ # Make sure that the target being added to the sorted list is already in
+ # the unsorted list.
+ assert xcode_target in self.project._properties['targets']
+ targets.append(xcode_target)
+ ordinary_targets.append(xcode_target)
+ if xcode_target.support_target:
+ support_targets.append(xcode_target.support_target)
+ targets.append(xcode_target.support_target)
+
+ if not int(target.get('suppress_wildcard', False)):
+ targets_for_all.append(xcode_target)
+
+ if target_name.lower() == 'all':
+ has_custom_all = True;
+
+ # If this target has a 'run_as' attribute, add its target to the
+ # targets, and add it to the test targets.
+ if target.get('run_as'):
+ # Make a target to run something. It should have one
+ # dependency, the parent xcode target.
+ xccl = CreateXCConfigurationList(configurations)
+ run_target = gyp.xcodeproj_file.PBXAggregateTarget({
+ 'name': 'Run ' + target_name,
+ 'productName': xcode_target.GetProperty('productName'),
+ 'buildConfigurationList': xccl,
+ },
+ parent=self.project)
+ run_target.AddDependency(xcode_target)
+
+ command = target['run_as']
+ script = ''
+ if command.get('working_directory'):
+ script = script + 'cd "%s"\n' % \
+ gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
+ command.get('working_directory'))
+
+ if command.get('environment'):
+ script = script + "\n".join(
+ ['export %s="%s"' %
+ (key, gyp.xcodeproj_file.ConvertVariablesToShellSyntax(val))
+ for (key, val) in command.get('environment').iteritems()]) + "\n"
+
+ # Some test end up using sockets, files on disk, etc. and can get
+ # confused if more then one test runs at a time. The generator
+ # flag 'xcode_serialize_all_test_runs' controls the forcing of all
+ # tests serially. It defaults to True. To get serial runs this
+ # little bit of python does the same as the linux flock utility to
+ # make sure only one runs at a time.
+ command_prefix = ''
+ if serialize_all_tests:
+ command_prefix = \
+"""python -c "import fcntl, subprocess, sys
+file = open('$TMPDIR/GYP_serialize_test_runs', 'a')
+fcntl.flock(file.fileno(), fcntl.LOCK_EX)
+sys.exit(subprocess.call(sys.argv[1:]))" """
+
+ # If we were unable to exec for some reason, we want to exit
+ # with an error, and fixup variable references to be shell
+ # syntax instead of xcode syntax.
+ script = script + 'exec ' + command_prefix + '%s\nexit 1\n' % \
+ gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
+ gyp.common.EncodePOSIXShellList(command.get('action')))
+
+ ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
+ 'shellScript': script,
+ 'showEnvVarsInLog': 0,
+ })
+ run_target.AppendProperty('buildPhases', ssbp)
+
+ # Add the run target to the project file.
+ targets.append(run_target)
+ run_test_targets.append(run_target)
+ xcode_target.test_runner = run_target
+
+
+ # Make sure that the list of targets being replaced is the same length as
+ # the one replacing it, but allow for the added test runner targets.
+ assert len(self.project._properties['targets']) == \
+ len(ordinary_targets) + len(support_targets)
+
+ self.project._properties['targets'] = targets
+
+ # Get rid of unnecessary levels of depth in groups like the Source group.
+ self.project.RootGroupsTakeOverOnlyChildren(True)
+
+ # Sort the groups nicely. Do this after sorting the targets, because the
+ # Products group is sorted based on the order of the targets.
+ self.project.SortGroups()
+
+ # Create an "All" target if there's more than one target in this project
+ # file and the project didn't define its own "All" target. Put a generated
+ # "All" target first so that people opening up the project for the first
+ # time will build everything by default.
+ if len(targets_for_all) > 1 and not has_custom_all:
+ xccl = CreateXCConfigurationList(configurations)
+ all_target = gyp.xcodeproj_file.PBXAggregateTarget(
+ {
+ 'buildConfigurationList': xccl,
+ 'name': 'All',
+ },
+ parent=self.project)
+
+ for target in targets_for_all:
+ all_target.AddDependency(target)
+
+ # TODO(mark): This is evil because it relies on internal knowledge of
+ # PBXProject._properties. It's important to get the "All" target first,
+ # though.
+ self.project._properties['targets'].insert(0, all_target)
+
+ # The same, but for run_test_targets.
+ if len(run_test_targets) > 1:
+ xccl = CreateXCConfigurationList(configurations)
+ run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget(
+ {
+ 'buildConfigurationList': xccl,
+ 'name': 'Run All Tests',
+ },
+ parent=self.project)
+ for run_test_target in run_test_targets:
+ run_all_tests_target.AddDependency(run_test_target)
+
+ # Insert after the "All" target, which must exist if there is more than
+ # one run_test_target.
+ self.project._properties['targets'].insert(1, run_all_tests_target)
+
+ def Finalize2(self, xcode_targets, xcode_target_to_target_dict):
+ # Finalize2 needs to happen in a separate step because the process of
+ # updating references to other projects depends on the ordering of targets
+ # within remote project files. Finalize1 is responsible for sorting duty,
+ # and once all project files are sorted, Finalize2 can come in and update
+ # these references.
+
+ # To support making a "test runner" target that will run all the tests
+ # that are direct dependents of any given target, we look for
+ # xcode_create_dependents_test_runner being set on an Aggregate target,
+ # and generate a second target that will run the tests runners found under
+ # the marked target.
+ for bf_tgt in self.build_file_dict['targets']:
+ if int(bf_tgt.get('xcode_create_dependents_test_runner', 0)):
+ tgt_name = bf_tgt['target_name']
+ toolset = bf_tgt['toolset']
+ qualified_target = gyp.common.QualifiedTarget(self.gyp_path,
+ tgt_name, toolset)
+ xcode_target = xcode_targets[qualified_target]
+ if isinstance(xcode_target, gyp.xcodeproj_file.PBXAggregateTarget):
+ # Collect all the run test targets.
+ all_run_tests = []
+ pbxtds = xcode_target.GetProperty('dependencies')
+ for pbxtd in pbxtds:
+ pbxcip = pbxtd.GetProperty('targetProxy')
+ dependency_xct = pbxcip.GetProperty('remoteGlobalIDString')
+ if hasattr(dependency_xct, 'test_runner'):
+ all_run_tests.append(dependency_xct.test_runner)
+
+ # Directly depend on all the runners as they depend on the target
+ # that builds them.
+ if len(all_run_tests) > 0:
+ run_all_target = gyp.xcodeproj_file.PBXAggregateTarget({
+ 'name': 'Run %s Tests' % tgt_name,
+ 'productName': tgt_name,
+ },
+ parent=self.project)
+ for run_test_target in all_run_tests:
+ run_all_target.AddDependency(run_test_target)
+
+ # Insert the test runner after the related target.
+ idx = self.project._properties['targets'].index(xcode_target)
+ self.project._properties['targets'].insert(idx + 1, run_all_target)
+
+ # Update all references to other projects, to make sure that the lists of
+ # remote products are complete. Otherwise, Xcode will fill them in when
+ # it opens the project file, which will result in unnecessary diffs.
+ # TODO(mark): This is evil because it relies on internal knowledge of
+ # PBXProject._other_pbxprojects.
+ for other_pbxproject in self.project._other_pbxprojects.keys():
+ self.project.AddOrGetProjectReference(other_pbxproject)
+
+ self.project.SortRemoteProductReferences()
+
+ # Give everything an ID.
+ self.project_file.ComputeIDs()
+
+ # Make sure that no two objects in the project file have the same ID. If
+ # multiple objects wind up with the same ID, upon loading the file, Xcode
+ # will only recognize one object (the last one in the file?) and the
+ # results are unpredictable.
+ self.project_file.EnsureNoIDCollisions()
+
+ def Write(self):
+ # Write the project file to a temporary location first. Xcode watches for
+ # changes to the project file and presents a UI sheet offering to reload
+ # the project when it does change. However, in some cases, especially when
+ # multiple projects are open or when Xcode is busy, things don't work so
+ # seamlessly. Sometimes, Xcode is able to detect that a project file has
+ # changed but can't unload it because something else is referencing it.
+ # To mitigate this problem, and to avoid even having Xcode present the UI
+ # sheet when an open project is rewritten for inconsequential changes, the
+ # project file is written to a temporary file in the xcodeproj directory
+ # first. The new temporary file is then compared to the existing project
+ # file, if any. If they differ, the new file replaces the old; otherwise,
+ # the new project file is simply deleted. Xcode properly detects a file
+ # being renamed over an open project file as a change and so it remains
+ # able to present the "project file changed" sheet under this system.
+ # Writing to a temporary file first also avoids the possible problem of
+ # Xcode rereading an incomplete project file.
+ (output_fd, new_pbxproj_path) = \
+ tempfile.mkstemp(suffix='.tmp', prefix='project.pbxproj.gyp.',
+ dir=self.path)
+
+ try:
+ output_file = os.fdopen(output_fd, 'wb')
+
+ self.project_file.Print(output_file)
+ output_file.close()
+
+ pbxproj_path = os.path.join(self.path, 'project.pbxproj')
+
+ same = False
+ try:
+ same = filecmp.cmp(pbxproj_path, new_pbxproj_path, False)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+
+ if same:
+ # The new file is identical to the old one, just get rid of the new
+ # one.
+ os.unlink(new_pbxproj_path)
+ else:
+ # The new file is different from the old one, or there is no old one.
+ # Rename the new file to the permanent name.
+ #
+ # tempfile.mkstemp uses an overly restrictive mode, resulting in a
+ # file that can only be read by the owner, regardless of the umask.
+ # There's no reason to not respect the umask here, which means that
+ # an extra hoop is required to fetch it and reset the new file's mode.
+ #
+ # No way to get the umask without setting a new one? Set a safe one
+ # and then set it back to the old value.
+ umask = os.umask(077)
+ os.umask(umask)
+
+ os.chmod(new_pbxproj_path, 0666 & ~umask)
+ os.rename(new_pbxproj_path, pbxproj_path)
+
+ except Exception:
+ # Don't leave turds behind. In fact, if this code was responsible for
+ # creating the xcodeproj directory, get rid of that too.
+ os.unlink(new_pbxproj_path)
+ if self.created_dir:
+ shutil.rmtree(self.path, True)
+ raise
+
+
+cached_xcode_version = None
+def InstalledXcodeVersion():
+ """Fetches the installed version of Xcode, returns empty string if it is
+ unable to figure it out."""
+
+ global cached_xcode_version
+ if not cached_xcode_version is None:
+ return cached_xcode_version
+
+ # Default to an empty string
+ cached_xcode_version = ''
+
+ # Collect the xcodebuild's version information.
+ try:
+ import subprocess
+ cmd = ['/usr/bin/xcodebuild', '-version']
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ xcodebuild_version_info = proc.communicate()[0]
+ # Any error, return empty string
+ if proc.returncode:
+ xcodebuild_version_info = ''
+ except OSError:
+ # We failed to launch the tool
+ xcodebuild_version_info = ''
+
+ # Pull out the Xcode version itself.
+ match_line = re.search('^Xcode (.*)$', xcodebuild_version_info, re.MULTILINE)
+ if match_line:
+ cached_xcode_version = match_line.group(1)
+ # Done!
+ return cached_xcode_version
+
+
+def AddSourceToTarget(source, type, pbxp, xct):
+ # TODO(mark): Perhaps source_extensions and library_extensions can be made a
+ # little bit fancier.
+ source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's']
+
+ # .o is conceptually more of a "source" than a "library," but Xcode thinks
+ # of "sources" as things to compile and "libraries" (or "frameworks") as
+ # things to link with. Adding an object file to an Xcode target's frameworks
+ # phase works properly.
+ library_extensions = ['a', 'dylib', 'framework', 'o']
+
+ basename = posixpath.basename(source)
+ (root, ext) = posixpath.splitext(basename)
+ if ext:
+ ext = ext[1:].lower()
+
+ if ext in source_extensions and type != 'none':
+ xct.SourcesPhase().AddFile(source)
+ elif ext in library_extensions and type != 'none':
+ xct.FrameworksPhase().AddFile(source)
+ else:
+ # Files that aren't added to a sources or frameworks build phase can still
+ # go into the project file, just not as part of a build phase.
+ pbxp.AddOrGetFileInRootGroup(source)
+
+
+def AddResourceToTarget(resource, pbxp, xct):
+ # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call
+ # where it's used.
+ xct.ResourcesPhase().AddFile(resource)
+
+
+def AddHeaderToTarget(header, pbxp, xct, is_public):
+ # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call
+ # where it's used.
+ settings = '{ATTRIBUTES = (%s, ); }' % ('Private', 'Public')[is_public]
+ xct.HeadersPhase().AddFile(header, settings)
+
+
+_xcode_variable_re = re.compile('(\$\((.*?)\))')
+def ExpandXcodeVariables(string, expansions):
+ """Expands Xcode-style $(VARIABLES) in string per the expansions dict.
+
+ In some rare cases, it is appropriate to expand Xcode variables when a
+ project file is generated. For any substring $(VAR) in string, if VAR is a
+ key in the expansions dict, $(VAR) will be replaced with expansions[VAR].
+ Any $(VAR) substring in string for which VAR is not a key in the expansions
+ dict will remain in the returned string.
+ """
+
+ matches = _xcode_variable_re.findall(string)
+ if matches == None:
+ return string
+
+ matches.reverse()
+ for match in matches:
+ (to_replace, variable) = match
+ if not variable in expansions:
+ continue
+
+ replacement = expansions[variable]
+ string = re.sub(re.escape(to_replace), replacement, string)
+
+ return string
+
+
+_xcode_define_re = re.compile(r'([\\\"\' ])')
+def EscapeXcodeDefine(s):
+ """We must escape the defines that we give to XCode so that it knows not to
+ split on spaces and to respect backslash and quote literals. However, we
+ must not quote the define, or Xcode will incorrectly intepret variables
+ especially $(inherited)."""
+ return re.sub(_xcode_define_re, r'\\\1', s)
+
+
+def PerformBuild(data, configurations, params):
+ options = params['options']
+
+ for build_file, build_file_dict in data.iteritems():
+ (build_file_root, build_file_ext) = os.path.splitext(build_file)
+ if build_file_ext != '.gyp':
+ continue
+ xcodeproj_path = build_file_root + options.suffix + '.xcodeproj'
+ if options.generator_output:
+ xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path)
+
+ for config in configurations:
+ arguments = ['xcodebuild', '-project', xcodeproj_path]
+ arguments += ['-configuration', config]
+ print "Building [%s]: %s" % (config, arguments)
+ subprocess.check_call(arguments)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+ options = params['options']
+ generator_flags = params.get('generator_flags', {})
+ parallel_builds = generator_flags.get('xcode_parallel_builds', True)
+ serialize_all_tests = \
+ generator_flags.get('xcode_serialize_all_test_runs', True)
+ project_version = generator_flags.get('xcode_project_version', None)
+ skip_excluded_files = \
+ not generator_flags.get('xcode_list_excluded_files', True)
+ xcode_projects = {}
+ for build_file, build_file_dict in data.iteritems():
+ (build_file_root, build_file_ext) = os.path.splitext(build_file)
+ if build_file_ext != '.gyp':
+ continue
+ xcodeproj_path = build_file_root + options.suffix + '.xcodeproj'
+ if options.generator_output:
+ xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path)
+ xcp = XcodeProject(build_file, xcodeproj_path, build_file_dict)
+ xcode_projects[build_file] = xcp
+ pbxp = xcp.project
+
+ if parallel_builds:
+ pbxp.SetProperty('attributes',
+ {'BuildIndependentTargetsInParallel': 'YES'})
+ if project_version:
+ xcp.project_file.SetXcodeVersion(project_version)
+
+ # Add gyp/gypi files to project
+ if not generator_flags.get('standalone'):
+ main_group = pbxp.GetProperty('mainGroup')
+ build_group = gyp.xcodeproj_file.PBXGroup({'name': 'Build'})
+ main_group.AppendChild(build_group)
+ for included_file in build_file_dict['included_files']:
+ build_group.AddOrGetFileByPath(included_file, False)
+
+ xcode_targets = {}
+ xcode_target_to_target_dict = {}
+ for qualified_target in target_list:
+ [build_file, target_name, toolset] = \
+ gyp.common.ParseQualifiedTarget(qualified_target)
+
+ spec = target_dicts[qualified_target]
+ if spec['toolset'] != 'target':
+ raise Exception(
+ 'Multiple toolsets not supported in xcode build (target %s)' %
+ qualified_target)
+ configuration_names = [spec['default_configuration']]
+ for configuration_name in sorted(spec['configurations'].keys()):
+ if configuration_name not in configuration_names:
+ configuration_names.append(configuration_name)
+ xcp = xcode_projects[build_file]
+ pbxp = xcp.project
+
+ # Set up the configurations for the target according to the list of names
+ # supplied.
+ xccl = CreateXCConfigurationList(configuration_names)
+
+ # Create an XCTarget subclass object for the target. The type with
+ # "+bundle" appended will be used if the target has "mac_bundle" set.
+ # loadable_modules not in a mac_bundle are mapped to
+ # com.googlecode.gyp.xcode.bundle, a pseudo-type that xcode.py interprets
+ # to create a single-file mh_bundle.
+ _types = {
+ 'executable': 'com.apple.product-type.tool',
+ 'loadable_module': 'com.googlecode.gyp.xcode.bundle',
+ 'shared_library': 'com.apple.product-type.library.dynamic',
+ 'static_library': 'com.apple.product-type.library.static',
+ 'executable+bundle': 'com.apple.product-type.application',
+ 'loadable_module+bundle': 'com.apple.product-type.bundle',
+ 'shared_library+bundle': 'com.apple.product-type.framework',
+ }
+
+ target_properties = {
+ 'buildConfigurationList': xccl,
+ 'name': target_name,
+ }
+
+ type = spec['type']
+ is_bundle = int(spec.get('mac_bundle', 0))
+ if type != 'none':
+ type_bundle_key = type
+ if is_bundle:
+ type_bundle_key += '+bundle'
+ xctarget_type = gyp.xcodeproj_file.PBXNativeTarget
+ try:
+ target_properties['productType'] = _types[type_bundle_key]
+ except KeyError, e:
+ gyp.common.ExceptionAppend(e, "-- unknown product type while "
+ "writing target %s" % target_name)
+ raise
+ else:
+ xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget
+ assert not is_bundle, (
+ 'mac_bundle targets cannot have type none (target "%s")' %
+ target_name)
+
+ target_product_name = spec.get('product_name')
+ if target_product_name is not None:
+ target_properties['productName'] = target_product_name
+
+ xct = xctarget_type(target_properties, parent=pbxp,
+ force_outdir=spec.get('product_dir'),
+ force_prefix=spec.get('product_prefix'),
+ force_extension=spec.get('product_extension'))
+ pbxp.AppendProperty('targets', xct)
+ xcode_targets[qualified_target] = xct
+ xcode_target_to_target_dict[xct] = spec
+
+ spec_actions = spec.get('actions', [])
+ spec_rules = spec.get('rules', [])
+
+ # Xcode has some "issues" with checking dependencies for the "Compile
+ # sources" step with any source files/headers generated by actions/rules.
+ # To work around this, if a target is building anything directly (not
+ # type "none"), then a second target is used to run the GYP actions/rules
+ # and is made a dependency of this target. This way the work is done
+ # before the dependency checks for what should be recompiled.
+ support_xct = None
+ if type != 'none' and (spec_actions or spec_rules):
+ support_xccl = CreateXCConfigurationList(configuration_names);
+ support_target_properties = {
+ 'buildConfigurationList': support_xccl,
+ 'name': target_name + ' Support',
+ }
+ if target_product_name:
+ support_target_properties['productName'] = \
+ target_product_name + ' Support'
+ support_xct = \
+ gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties,
+ parent=pbxp)
+ pbxp.AppendProperty('targets', support_xct)
+ xct.AddDependency(support_xct)
+ # Hang the support target off the main target so it can be tested/found
+ # by the generator during Finalize.
+ xct.support_target = support_xct
+
+ prebuild_index = 0
+
+ # Add custom shell script phases for "actions" sections.
+ for action in spec_actions:
+ # There's no need to write anything into the script to ensure that the
+ # output directories already exist, because Xcode will look at the
+ # declared outputs and automatically ensure that they exist for us.
+
+ # Do we have a message to print when this action runs?
+ message = action.get('message')
+ if message:
+ message = 'echo note: ' + gyp.common.EncodePOSIXShellArgument(message)
+ else:
+ message = ''
+
+ # Turn the list into a string that can be passed to a shell.
+ action_string = gyp.common.EncodePOSIXShellList(action['action'])
+
+ # Convert Xcode-type variable references to sh-compatible environment
+ # variable references.
+ message_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(message)
+ action_string_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
+ action_string)
+
+ script = ''
+ # Include the optional message
+ if message_sh:
+ script += message_sh + '\n'
+ # Be sure the script runs in exec, and that if exec fails, the script
+ # exits signalling an error.
+ script += 'exec ' + action_string_sh + '\nexit 1\n'
+ ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
+ 'inputPaths': action['inputs'],
+ 'name': 'Action "' + action['action_name'] + '"',
+ 'outputPaths': action['outputs'],
+ 'shellScript': script,
+ 'showEnvVarsInLog': 0,
+ })
+
+ if support_xct:
+ support_xct.AppendProperty('buildPhases', ssbp)
+ else:
+ # TODO(mark): this assumes too much knowledge of the internals of
+ # xcodeproj_file; some of these smarts should move into xcodeproj_file
+ # itself.
+ xct._properties['buildPhases'].insert(prebuild_index, ssbp)
+ prebuild_index = prebuild_index + 1
+
+ # TODO(mark): Should verify that at most one of these is specified.
+ if int(action.get('process_outputs_as_sources', False)):
+ for output in action['outputs']:
+ AddSourceToTarget(output, type, pbxp, xct)
+
+ if int(action.get('process_outputs_as_mac_bundle_resources', False)):
+ for output in action['outputs']:
+ AddResourceToTarget(output, pbxp, xct)
+
+ # tgt_mac_bundle_resources holds the list of bundle resources so
+ # the rule processing can check against it.
+ if is_bundle:
+ tgt_mac_bundle_resources = spec.get('mac_bundle_resources', [])
+ else:
+ tgt_mac_bundle_resources = []
+
+ # Add custom shell script phases driving "make" for "rules" sections.
+ #
+ # Xcode's built-in rule support is almost powerful enough to use directly,
+ # but there are a few significant deficiencies that render them unusable.
+ # There are workarounds for some of its inadequacies, but in aggregate,
+ # the workarounds added complexity to the generator, and some workarounds
+ # actually require input files to be crafted more carefully than I'd like.
+ # Consequently, until Xcode rules are made more capable, "rules" input
+ # sections will be handled in Xcode output by shell script build phases
+ # performed prior to the compilation phase.
+ #
+ # The following problems with Xcode rules were found. The numbers are
+ # Apple radar IDs. I hope that these shortcomings are addressed, I really
+ # liked having the rules handled directly in Xcode during the period that
+ # I was prototyping this.
+ #
+ # 6588600 Xcode compiles custom script rule outputs too soon, compilation
+ # fails. This occurs when rule outputs from distinct inputs are
+ # interdependent. The only workaround is to put rules and their
+ # inputs in a separate target from the one that compiles the rule
+ # outputs. This requires input file cooperation and it means that
+ # process_outputs_as_sources is unusable.
+ # 6584932 Need to declare that custom rule outputs should be excluded from
+ # compilation. A possible workaround is to lie to Xcode about a
+ # rule's output, giving it a dummy file it doesn't know how to
+ # compile. The rule action script would need to touch the dummy.
+ # 6584839 I need a way to declare additional inputs to a custom rule.
+ # A possible workaround is a shell script phase prior to
+ # compilation that touches a rule's primary input files if any
+ # would-be additional inputs are newer than the output. Modifying
+ # the source tree - even just modification times - feels dirty.
+ # 6564240 Xcode "custom script" build rules always dump all environment
+ # variables. This is a low-prioroty problem and is not a
+ # show-stopper.
+ rules_by_ext = {}
+ for rule in spec_rules:
+ rules_by_ext[rule['extension']] = rule
+
+ # First, some definitions:
+ #
+ # A "rule source" is a file that was listed in a target's "sources"
+ # list and will have a rule applied to it on the basis of matching the
+ # rule's "extensions" attribute. Rule sources are direct inputs to
+ # rules.
+ #
+ # Rule definitions may specify additional inputs in their "inputs"
+ # attribute. These additional inputs are used for dependency tracking
+ # purposes.
+ #
+ # A "concrete output" is a rule output with input-dependent variables
+ # resolved. For example, given a rule with:
+ # 'extension': 'ext', 'outputs': ['$(INPUT_FILE_BASE).cc'],
+ # if the target's "sources" list contained "one.ext" and "two.ext",
+ # the "concrete output" for rule input "two.ext" would be "two.cc". If
+ # a rule specifies multiple outputs, each input file that the rule is
+ # applied to will have the same number of concrete outputs.
+ #
+ # If any concrete outputs are outdated or missing relative to their
+ # corresponding rule_source or to any specified additional input, the
+ # rule action must be performed to generate the concrete outputs.
+
+ # concrete_outputs_by_rule_source will have an item at the same index
+ # as the rule['rule_sources'] that it corresponds to. Each item is a
+ # list of all of the concrete outputs for the rule_source.
+ concrete_outputs_by_rule_source = []
+
+ # concrete_outputs_all is a flat list of all concrete outputs that this
+ # rule is able to produce, given the known set of input files
+ # (rule_sources) that apply to it.
+ concrete_outputs_all = []
+
+ # messages & actions are keyed by the same indices as rule['rule_sources']
+ # and concrete_outputs_by_rule_source. They contain the message and
+ # action to perform after resolving input-dependent variables. The
+ # message is optional, in which case None is stored for each rule source.
+ messages = []
+ actions = []
+
+ for rule_source in rule.get('rule_sources', []):
+ rule_source_dirname, rule_source_basename = \
+ posixpath.split(rule_source)
+ (rule_source_root, rule_source_ext) = \
+ posixpath.splitext(rule_source_basename)
+
+ # These are the same variable names that Xcode uses for its own native
+ # rule support. Because Xcode's rule engine is not being used, they
+ # need to be expanded as they are written to the makefile.
+ rule_input_dict = {
+ 'INPUT_FILE_BASE': rule_source_root,
+ 'INPUT_FILE_SUFFIX': rule_source_ext,
+ 'INPUT_FILE_NAME': rule_source_basename,
+ 'INPUT_FILE_PATH': rule_source,
+ 'INPUT_FILE_DIRNAME': rule_source_dirname,
+ }
+
+ concrete_outputs_for_this_rule_source = []
+ for output in rule.get('outputs', []):
+ # Fortunately, Xcode and make both use $(VAR) format for their
+ # variables, so the expansion is the only transformation necessary.
+ # Any remaning $(VAR)-type variables in the string can be given
+ # directly to make, which will pick up the correct settings from
+ # what Xcode puts into the environment.
+ concrete_output = ExpandXcodeVariables(output, rule_input_dict)
+ concrete_outputs_for_this_rule_source.append(concrete_output)
+
+ # Add all concrete outputs to the project.
+ pbxp.AddOrGetFileInRootGroup(concrete_output)
+
+ concrete_outputs_by_rule_source.append( \
+ concrete_outputs_for_this_rule_source)
+ concrete_outputs_all.extend(concrete_outputs_for_this_rule_source)
+
+ # TODO(mark): Should verify that at most one of these is specified.
+ if int(rule.get('process_outputs_as_sources', False)):
+ for output in concrete_outputs_for_this_rule_source:
+ AddSourceToTarget(output, type, pbxp, xct)
+
+ # If the file came from the mac_bundle_resources list or if the rule
+ # is marked to process outputs as bundle resource, do so.
+ was_mac_bundle_resource = rule_source in tgt_mac_bundle_resources
+ if was_mac_bundle_resource or \
+ int(rule.get('process_outputs_as_mac_bundle_resources', False)):
+ for output in concrete_outputs_for_this_rule_source:
+ AddResourceToTarget(output, pbxp, xct)
+
+ # Do we have a message to print when this rule runs?
+ message = rule.get('message')
+ if message:
+ message = gyp.common.EncodePOSIXShellArgument(message)
+ message = ExpandXcodeVariables(message, rule_input_dict)
+ messages.append(message)
+
+ # Turn the list into a string that can be passed to a shell.
+ action_string = gyp.common.EncodePOSIXShellList(rule['action'])
+
+ action = ExpandXcodeVariables(action_string, rule_input_dict)
+ actions.append(action)
+
+ if len(concrete_outputs_all) > 0:
+ # TODO(mark): There's a possibilty for collision here. Consider
+ # target "t" rule "A_r" and target "t_A" rule "r".
+ makefile_name = '%s.make' % re.sub(
+ '[^a-zA-Z0-9_]', '_' , '%s_%s' % (target_name, rule['rule_name']))
+ makefile_path = os.path.join(xcode_projects[build_file].path,
+ makefile_name)
+ # TODO(mark): try/close? Write to a temporary file and swap it only
+ # if it's got changes?
+ makefile = open(makefile_path, 'wb')
+
+ # make will build the first target in the makefile by default. By
+ # convention, it's called "all". List all (or at least one)
+ # concrete output for each rule source as a prerequisite of the "all"
+ # target.
+ makefile.write('all: \\\n')
+ for concrete_output_index in \
+ xrange(0, len(concrete_outputs_by_rule_source)):
+ # Only list the first (index [0]) concrete output of each input
+ # in the "all" target. Otherwise, a parallel make (-j > 1) would
+ # attempt to process each input multiple times simultaneously.
+ # Otherwise, "all" could just contain the entire list of
+ # concrete_outputs_all.
+ concrete_output = \
+ concrete_outputs_by_rule_source[concrete_output_index][0]
+ if concrete_output_index == len(concrete_outputs_by_rule_source) - 1:
+ eol = ''
+ else:
+ eol = ' \\'
+ makefile.write(' %s%s\n' % (concrete_output, eol))
+
+ for (rule_source, concrete_outputs, message, action) in \
+ zip(rule['rule_sources'], concrete_outputs_by_rule_source,
+ messages, actions):
+ makefile.write('\n')
+
+ # Add a rule that declares it can build each concrete output of a
+ # rule source. Collect the names of the directories that are
+ # required.
+ concrete_output_dirs = []
+ for concrete_output_index in xrange(0, len(concrete_outputs)):
+ concrete_output = concrete_outputs[concrete_output_index]
+ if concrete_output_index == 0:
+ bol = ''
+ else:
+ bol = ' '
+ makefile.write('%s%s \\\n' % (bol, concrete_output))
+
+ concrete_output_dir = posixpath.dirname(concrete_output)
+ if (concrete_output_dir and
+ concrete_output_dir not in concrete_output_dirs):
+ concrete_output_dirs.append(concrete_output_dir)
+
+ makefile.write(' : \\\n')
+
+ # The prerequisites for this rule are the rule source itself and
+ # the set of additional rule inputs, if any.
+ prerequisites = [rule_source]
+ prerequisites.extend(rule.get('inputs', []))
+ for prerequisite_index in xrange(0, len(prerequisites)):
+ prerequisite = prerequisites[prerequisite_index]
+ if prerequisite_index == len(prerequisites) - 1:
+ eol = ''
+ else:
+ eol = ' \\'
+ makefile.write(' %s%s\n' % (prerequisite, eol))
+
+ # Make sure that output directories exist before executing the rule
+ # action.
+ if len(concrete_output_dirs) > 0:
+ makefile.write('\t@mkdir -p "%s"\n' %
+ '" "'.join(concrete_output_dirs))
+
+ # The rule message and action have already had the necessary variable
+ # substitutions performed.
+ if message:
+ # Mark it with note: so Xcode picks it up in build output.
+ makefile.write('\t@echo note: %s\n' % message)
+ makefile.write('\t%s\n' % action)
+
+ makefile.close()
+
+ # It might be nice to ensure that needed output directories exist
+ # here rather than in each target in the Makefile, but that wouldn't
+ # work if there ever was a concrete output that had an input-dependent
+ # variable anywhere other than in the leaf position.
+
+ # Don't declare any inputPaths or outputPaths. If they're present,
+ # Xcode will provide a slight optimization by only running the script
+ # phase if any output is missing or outdated relative to any input.
+ # Unfortunately, it will also assume that all outputs are touched by
+ # the script, and if the outputs serve as files in a compilation
+ # phase, they will be unconditionally rebuilt. Since make might not
+ # rebuild everything that could be declared here as an output, this
+ # extra compilation activity is unnecessary. With inputPaths and
+ # outputPaths not supplied, make will always be called, but it knows
+ # enough to not do anything when everything is up-to-date.
+
+ # To help speed things up, pass -j COUNT to make so it does some work
+ # in parallel. Don't use ncpus because Xcode will build ncpus targets
+ # in parallel and if each target happens to have a rules step, there
+ # would be ncpus^2 things going. With a machine that has 2 quad-core
+ # Xeons, a build can quickly run out of processes based on
+ # scheduling/other tasks, and randomly failing builds are no good.
+ script = \
+"""JOB_COUNT="$(/usr/sbin/sysctl -n hw.ncpu)"
+if [ "${JOB_COUNT}" -gt 4 ]; then
+ JOB_COUNT=4
+fi
+exec "${DEVELOPER_BIN_DIR}/make" -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}"
+exit 1
+""" % makefile_name
+ ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
+ 'name': 'Rule "' + rule['rule_name'] + '"',
+ 'shellScript': script,
+ 'showEnvVarsInLog': 0,
+ })
+
+ if support_xct:
+ support_xct.AppendProperty('buildPhases', ssbp)
+ else:
+ # TODO(mark): this assumes too much knowledge of the internals of
+ # xcodeproj_file; some of these smarts should move into xcodeproj_file
+ # itself.
+ xct._properties['buildPhases'].insert(prebuild_index, ssbp)
+ prebuild_index = prebuild_index + 1
+
+ # Extra rule inputs also go into the project file. Concrete outputs were
+ # already added when they were computed.
+ groups = ['inputs', 'inputs_excluded']
+ if skip_excluded_files:
+ groups = [x for x in groups if not x.endswith('_excluded')]
+ for group in groups:
+ for item in rule.get(group, []):
+ pbxp.AddOrGetFileInRootGroup(item)
+
+ # Add "sources".
+ for source in spec.get('sources', []):
+ (source_root, source_extension) = posixpath.splitext(source)
+ if source_extension[1:] not in rules_by_ext:
+ # AddSourceToTarget will add the file to a root group if it's not
+ # already there.
+ AddSourceToTarget(source, type, pbxp, xct)
+ else:
+ pbxp.AddOrGetFileInRootGroup(source)
+
+ # Add "mac_bundle_resources" and "mac_framework_private_headers" if
+ # it's a bundle of any type.
+ if is_bundle:
+ for resource in tgt_mac_bundle_resources:
+ (resource_root, resource_extension) = posixpath.splitext(resource)
+ if resource_extension[1:] not in rules_by_ext:
+ AddResourceToTarget(resource, pbxp, xct)
+ else:
+ pbxp.AddOrGetFileInRootGroup(resource)
+
+ for header in spec.get('mac_framework_private_headers', []):
+ AddHeaderToTarget(header, pbxp, xct, False)
+
+ # Add "mac_framework_headers". These can be valid for both frameworks
+ # and static libraries.
+ if is_bundle or type == 'static_library':
+ for header in spec.get('mac_framework_headers', []):
+ AddHeaderToTarget(header, pbxp, xct, True)
+
+ # Add "copies".
+ pbxcp_dict = {}
+ for copy_group in spec.get('copies', []):
+ dest = copy_group['destination']
+ if dest[0] not in ('/', '$'):
+ # Relative paths are relative to $(SRCROOT).
+ dest = '$(SRCROOT)/' + dest
+
+ # Coalesce multiple "copies" sections in the same target with the same
+ # "destination" property into the same PBXCopyFilesBuildPhase, otherwise
+ # they'll wind up with ID collisions.
+ pbxcp = pbxcp_dict.get(dest, None)
+ if pbxcp is None:
+ pbxcp = gyp.xcodeproj_file.PBXCopyFilesBuildPhase({
+ 'name': 'Copy to ' + copy_group['destination']
+ },
+ parent=xct)
+ pbxcp.SetDestination(dest)
+
+ # TODO(mark): The usual comment about this knowing too much about
+ # gyp.xcodeproj_file internals applies.
+ xct._properties['buildPhases'].insert(prebuild_index, pbxcp)
+
+ pbxcp_dict[dest] = pbxcp
+
+ for file in copy_group['files']:
+ pbxcp.AddFile(file)
+
+ # Excluded files can also go into the project file.
+ if not skip_excluded_files:
+ for key in ['sources', 'mac_bundle_resources', 'mac_framework_headers',
+ 'mac_framework_private_headers']:
+ excluded_key = key + '_excluded'
+ for item in spec.get(excluded_key, []):
+ pbxp.AddOrGetFileInRootGroup(item)
+
+ # So can "inputs" and "outputs" sections of "actions" groups.
+ groups = ['inputs', 'inputs_excluded', 'outputs', 'outputs_excluded']
+ if skip_excluded_files:
+ groups = [x for x in groups if not x.endswith('_excluded')]
+ for action in spec.get('actions', []):
+ for group in groups:
+ for item in action.get(group, []):
+ # Exclude anything in BUILT_PRODUCTS_DIR. They're products, not
+ # sources.
+ if not item.startswith('$(BUILT_PRODUCTS_DIR)/'):
+ pbxp.AddOrGetFileInRootGroup(item)
+
+ for postbuild in spec.get('postbuilds', []):
+ action_string_sh = gyp.common.EncodePOSIXShellList(postbuild['action'])
+ script = 'exec ' + action_string_sh + '\nexit 1\n'
+
+ # Make the postbuild step depend on the output of ld or ar from this
+ # target. Apparently putting the script step after the link step isn't
+ # sufficient to ensure proper ordering in all cases. With an input
+ # declared but no outputs, the script step should run every time, as
+ # desired.
+ ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
+ 'inputPaths': ['$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)'],
+ 'name': 'Postbuild "' + postbuild['postbuild_name'] + '"',
+ 'shellScript': script,
+ 'showEnvVarsInLog': 0,
+ })
+ xct.AppendProperty('buildPhases', ssbp)
+
+ # Add dependencies before libraries, because adding a dependency may imply
+ # adding a library. It's preferable to keep dependencies listed first
+ # during a link phase so that they can override symbols that would
+ # otherwise be provided by libraries, which will usually include system
+ # libraries. On some systems, ld is finicky and even requires the
+ # libraries to be ordered in such a way that unresolved symbols in
+ # earlier-listed libraries may only be resolved by later-listed libraries.
+ # The Mac linker doesn't work that way, but other platforms do, and so
+ # their linker invocations need to be constructed in this way. There's
+ # no compelling reason for Xcode's linker invocations to differ.
+
+ if 'dependencies' in spec:
+ for dependency in spec['dependencies']:
+ xct.AddDependency(xcode_targets[dependency])
+ # The support project also gets the dependencies (in case they are
+ # needed for the actions/rules to work).
+ if support_xct:
+ support_xct.AddDependency(xcode_targets[dependency])
+
+ if 'libraries' in spec:
+ for library in spec['libraries']:
+ xct.FrameworksPhase().AddFile(library)
+ # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary.
+ # I wish Xcode handled this automatically.
+ library_dir = posixpath.dirname(library)
+ if library_dir not in xcode_standard_library_dirs and (
+ not xct.HasBuildSetting(_library_search_paths_var) or
+ library_dir not in xct.GetBuildSetting(_library_search_paths_var)):
+ xct.AppendBuildSetting(_library_search_paths_var, library_dir)
+
+ for configuration_name in configuration_names:
+ configuration = spec['configurations'][configuration_name]
+ xcbc = xct.ConfigurationNamed(configuration_name)
+ for include_dir in configuration.get('mac_framework_dirs', []):
+ xcbc.AppendBuildSetting('FRAMEWORK_SEARCH_PATHS', include_dir)
+ for include_dir in configuration.get('include_dirs', []):
+ xcbc.AppendBuildSetting('HEADER_SEARCH_PATHS', include_dir)
+ for library_dir in configuration.get('library_dirs', []):
+ if library_dir not in xcode_standard_library_dirs and (
+ not xcbc.HasBuildSetting(_library_search_paths_var) or
+ library_dir not in xcbc.GetBuildSetting(_library_search_paths_var)):
+ xcbc.AppendBuildSetting(_library_search_paths_var, library_dir)
+
+ if 'defines' in configuration:
+ for define in configuration['defines']:
+ set_define = EscapeXcodeDefine(define)
+ xcbc.AppendBuildSetting('GCC_PREPROCESSOR_DEFINITIONS', set_define)
+ if 'xcode_settings' in configuration:
+ for xck, xcv in configuration['xcode_settings'].iteritems():
+ xcbc.SetBuildSetting(xck, xcv)
+ if 'xcode_config_file' in configuration:
+ config_ref = pbxp.AddOrGetFileInRootGroup(
+ configuration['xcode_config_file'])
+ xcbc.SetBaseConfiguration(config_ref)
+
+ build_files = []
+ for build_file, build_file_dict in data.iteritems():
+ if build_file.endswith('.gyp'):
+ build_files.append(build_file)
+
+ for build_file in build_files:
+ xcode_projects[build_file].Finalize1(xcode_targets, serialize_all_tests)
+
+ for build_file in build_files:
+ xcode_projects[build_file].Finalize2(xcode_targets,
+ xcode_target_to_target_dict)
+
+ for build_file in build_files:
+ xcode_projects[build_file].Write()
diff --git a/chromium/tools/gyp/pylib/gyp/generator/xcode_test.py b/chromium/tools/gyp/pylib/gyp/generator/xcode_test.py
new file mode 100644
index 00000000000..260324a43f3
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/generator/xcode_test.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Unit tests for the xcode.py file. """
+
+import gyp.generator.xcode as xcode
+import unittest
+import sys
+
+
+class TestEscapeXcodeDefine(unittest.TestCase):
+ if sys.platform == 'darwin':
+ def test_InheritedRemainsUnescaped(self):
+ self.assertEqual(xcode.EscapeXcodeDefine('$(inherited)'), '$(inherited)')
+
+ def test_Escaping(self):
+ self.assertEqual(xcode.EscapeXcodeDefine('a b"c\\'), 'a\\ b\\"c\\\\')
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/gyp/pylib/gyp/input.py b/chromium/tools/gyp/pylib/gyp/input.py
new file mode 100644
index 00000000000..0d9beb0f498
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/input.py
@@ -0,0 +1,2683 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from compiler.ast import Const
+from compiler.ast import Dict
+from compiler.ast import Discard
+from compiler.ast import List
+from compiler.ast import Module
+from compiler.ast import Node
+from compiler.ast import Stmt
+import compiler
+import copy
+import gyp.common
+import multiprocessing
+import optparse
+import os.path
+import re
+import shlex
+import signal
+import subprocess
+import sys
+import threading
+import time
+from gyp.common import GypError
+
+
+# A list of types that are treated as linkable.
+linkable_types = ['executable', 'shared_library', 'loadable_module']
+
+# A list of sections that contain links to other targets.
+dependency_sections = ['dependencies', 'export_dependent_settings']
+
+# base_path_sections is a list of sections defined by GYP that contain
+# pathnames. The generators can provide more keys, the two lists are merged
+# into path_sections, but you should call IsPathSection instead of using either
+# list directly.
+base_path_sections = [
+ 'destination',
+ 'files',
+ 'include_dirs',
+ 'inputs',
+ 'libraries',
+ 'outputs',
+ 'sources',
+]
+path_sections = []
+
+is_path_section_charset = set('=+?!')
+is_path_section_match_re = re.compile('_(dir|file|path)s?$')
+
+def IsPathSection(section):
+ # If section ends in one of these characters, it's applied to a section
+ # without the trailing characters. '/' is notably absent from this list,
+ # because there's no way for a regular expression to be treated as a path.
+ while section[-1:] in is_path_section_charset:
+ section = section[:-1]
+ return section in path_sections or is_path_section_match_re.search(section)
+
+# base_non_configuraiton_keys is a list of key names that belong in the target
+# itself and should not be propagated into its configurations. It is merged
+# with a list that can come from the generator to
+# create non_configuration_keys.
+base_non_configuration_keys = [
+ # Sections that must exist inside targets and not configurations.
+ 'actions',
+ 'configurations',
+ 'copies',
+ 'default_configuration',
+ 'dependencies',
+ 'dependencies_original',
+ 'link_languages',
+ 'libraries',
+ 'postbuilds',
+ 'product_dir',
+ 'product_extension',
+ 'product_name',
+ 'product_prefix',
+ 'rules',
+ 'run_as',
+ 'sources',
+ 'standalone_static_library',
+ 'suppress_wildcard',
+ 'target_name',
+ 'toolset',
+ 'toolsets',
+ 'type',
+ 'variants',
+
+ # Sections that can be found inside targets or configurations, but that
+ # should not be propagated from targets into their configurations.
+ 'variables',
+]
+non_configuration_keys = []
+
+# Keys that do not belong inside a configuration dictionary.
+invalid_configuration_keys = [
+ 'actions',
+ 'all_dependent_settings',
+ 'configurations',
+ 'dependencies',
+ 'direct_dependent_settings',
+ 'libraries',
+ 'link_settings',
+ 'sources',
+ 'standalone_static_library',
+ 'target_name',
+ 'type',
+]
+
+# Controls how the generator want the build file paths.
+absolute_build_file_paths = False
+
+# Controls whether or not the generator supports multiple toolsets.
+multiple_toolsets = False
+
+
+def GetIncludedBuildFiles(build_file_path, aux_data, included=None):
+ """Return a list of all build files included into build_file_path.
+
+ The returned list will contain build_file_path as well as all other files
+ that it included, either directly or indirectly. Note that the list may
+ contain files that were included into a conditional section that evaluated
+ to false and was not merged into build_file_path's dict.
+
+ aux_data is a dict containing a key for each build file or included build
+ file. Those keys provide access to dicts whose "included" keys contain
+ lists of all other files included by the build file.
+
+ included should be left at its default None value by external callers. It
+ is used for recursion.
+
+ The returned list will not contain any duplicate entries. Each build file
+ in the list will be relative to the current directory.
+ """
+
+ if included == None:
+ included = []
+
+ if build_file_path in included:
+ return included
+
+ included.append(build_file_path)
+
+ for included_build_file in aux_data[build_file_path].get('included', []):
+ GetIncludedBuildFiles(included_build_file, aux_data, included)
+
+ return included
+
+
+def CheckedEval(file_contents):
+ """Return the eval of a gyp file.
+
+ The gyp file is restricted to dictionaries and lists only, and
+ repeated keys are not allowed.
+
+ Note that this is slower than eval() is.
+ """
+
+ ast = compiler.parse(file_contents)
+ assert isinstance(ast, Module)
+ c1 = ast.getChildren()
+ assert c1[0] is None
+ assert isinstance(c1[1], Stmt)
+ c2 = c1[1].getChildren()
+ assert isinstance(c2[0], Discard)
+ c3 = c2[0].getChildren()
+ assert len(c3) == 1
+ return CheckNode(c3[0], [])
+
+
+def CheckNode(node, keypath):
+ if isinstance(node, Dict):
+ c = node.getChildren()
+ dict = {}
+ for n in range(0, len(c), 2):
+ assert isinstance(c[n], Const)
+ key = c[n].getChildren()[0]
+ if key in dict:
+ raise GypError("Key '" + key + "' repeated at level " +
+ repr(len(keypath) + 1) + " with key path '" +
+ '.'.join(keypath) + "'")
+ kp = list(keypath) # Make a copy of the list for descending this node.
+ kp.append(key)
+ dict[key] = CheckNode(c[n + 1], kp)
+ return dict
+ elif isinstance(node, List):
+ c = node.getChildren()
+ children = []
+ for index, child in enumerate(c):
+ kp = list(keypath) # Copy list.
+ kp.append(repr(index))
+ children.append(CheckNode(child, kp))
+ return children
+ elif isinstance(node, Const):
+ return node.getChildren()[0]
+ else:
+ raise TypeError, "Unknown AST node at key path '" + '.'.join(keypath) + \
+ "': " + repr(node)
+
+
+def LoadOneBuildFile(build_file_path, data, aux_data, variables, includes,
+ is_target, check):
+ if build_file_path in data:
+ return data[build_file_path]
+
+ if os.path.exists(build_file_path):
+ build_file_contents = open(build_file_path).read()
+ else:
+ raise GypError("%s not found (cwd: %s)" % (build_file_path, os.getcwd()))
+
+ build_file_data = None
+ try:
+ if check:
+ build_file_data = CheckedEval(build_file_contents)
+ else:
+ build_file_data = eval(build_file_contents, {'__builtins__': None},
+ None)
+ except SyntaxError, e:
+ e.filename = build_file_path
+ raise
+ except Exception, e:
+ gyp.common.ExceptionAppend(e, 'while reading ' + build_file_path)
+ raise
+
+ if not isinstance(build_file_data, dict):
+ raise GypError("%s does not evaluate to a dictionary." % build_file_path)
+
+ data[build_file_path] = build_file_data
+ aux_data[build_file_path] = {}
+
+ # Scan for includes and merge them in.
+ try:
+ if is_target:
+ LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
+ aux_data, variables, includes, check)
+ else:
+ LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
+ aux_data, variables, None, check)
+ except Exception, e:
+ gyp.common.ExceptionAppend(e,
+ 'while reading includes of ' + build_file_path)
+ raise
+
+ return build_file_data
+
+
+def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data,
+ variables, includes, check):
+ includes_list = []
+ if includes != None:
+ includes_list.extend(includes)
+ if 'includes' in subdict:
+ for include in subdict['includes']:
+ # "include" is specified relative to subdict_path, so compute the real
+ # path to include by appending the provided "include" to the directory
+ # in which subdict_path resides.
+ relative_include = \
+ os.path.normpath(os.path.join(os.path.dirname(subdict_path), include))
+ includes_list.append(relative_include)
+ # Unhook the includes list, it's no longer needed.
+ del subdict['includes']
+
+ # Merge in the included files.
+ for include in includes_list:
+ if not 'included' in aux_data[subdict_path]:
+ aux_data[subdict_path]['included'] = []
+ aux_data[subdict_path]['included'].append(include)
+
+ gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include)
+
+ MergeDicts(subdict,
+ LoadOneBuildFile(include, data, aux_data, variables, None,
+ False, check),
+ subdict_path, include)
+
+ # Recurse into subdictionaries.
+ for k, v in subdict.iteritems():
+ if v.__class__ == dict:
+ LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, variables,
+ None, check)
+ elif v.__class__ == list:
+ LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, variables,
+ check)
+
+
+# This recurses into lists so that it can look for dicts.
+def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data,
+ variables, check):
+ for item in sublist:
+ if item.__class__ == dict:
+ LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data,
+ variables, None, check)
+ elif item.__class__ == list:
+ LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data,
+ variables, check)
+
+# Processes toolsets in all the targets. This recurses into condition entries
+# since they can contain toolsets as well.
+def ProcessToolsetsInDict(data):
+ if 'targets' in data:
+ target_list = data['targets']
+ new_target_list = []
+ for target in target_list:
+ # If this target already has an explicit 'toolset', and no 'toolsets'
+ # list, don't modify it further.
+ if 'toolset' in target and 'toolsets' not in target:
+ new_target_list.append(target)
+ continue
+ if multiple_toolsets:
+ toolsets = target.get('toolsets', ['target'])
+ else:
+ toolsets = ['target']
+ # Make sure this 'toolsets' definition is only processed once.
+ if 'toolsets' in target:
+ del target['toolsets']
+ if len(toolsets) > 0:
+ # Optimization: only do copies if more than one toolset is specified.
+ for build in toolsets[1:]:
+ new_target = copy.deepcopy(target)
+ new_target['toolset'] = build
+ new_target_list.append(new_target)
+ target['toolset'] = toolsets[0]
+ new_target_list.append(target)
+ data['targets'] = new_target_list
+ if 'conditions' in data:
+ for condition in data['conditions']:
+ if isinstance(condition, list):
+ for condition_dict in condition[1:]:
+ ProcessToolsetsInDict(condition_dict)
+
+
+# TODO(mark): I don't love this name. It just means that it's going to load
+# a build file that contains targets and is expected to provide a targets dict
+# that contains the targets...
+def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes,
+ depth, check, load_dependencies):
+ # If depth is set, predefine the DEPTH variable to be a relative path from
+ # this build file's directory to the directory identified by depth.
+ if depth:
+ # TODO(dglazkov) The backslash/forward-slash replacement at the end is a
+ # temporary measure. This should really be addressed by keeping all paths
+ # in POSIX until actual project generation.
+ d = gyp.common.RelativePath(depth, os.path.dirname(build_file_path))
+ if d == '':
+ variables['DEPTH'] = '.'
+ else:
+ variables['DEPTH'] = d.replace('\\', '/')
+
+ # If the generator needs absolue paths, then do so.
+ if absolute_build_file_paths:
+ build_file_path = os.path.abspath(build_file_path)
+
+ if build_file_path in data['target_build_files']:
+ # Already loaded.
+ return False
+ data['target_build_files'].add(build_file_path)
+
+ gyp.DebugOutput(gyp.DEBUG_INCLUDES,
+ "Loading Target Build File '%s'", build_file_path)
+
+ build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, variables,
+ includes, True, check)
+
+ # Store DEPTH for later use in generators.
+ build_file_data['_DEPTH'] = depth
+
+ # Set up the included_files key indicating which .gyp files contributed to
+ # this target dict.
+ if 'included_files' in build_file_data:
+ raise GypError(build_file_path + ' must not contain included_files key')
+
+ included = GetIncludedBuildFiles(build_file_path, aux_data)
+ build_file_data['included_files'] = []
+ for included_file in included:
+ # included_file is relative to the current directory, but it needs to
+ # be made relative to build_file_path's directory.
+ included_relative = \
+ gyp.common.RelativePath(included_file,
+ os.path.dirname(build_file_path))
+ build_file_data['included_files'].append(included_relative)
+
+ # Do a first round of toolsets expansion so that conditions can be defined
+ # per toolset.
+ ProcessToolsetsInDict(build_file_data)
+
+ # Apply "pre"/"early" variable expansions and condition evaluations.
+ ProcessVariablesAndConditionsInDict(
+ build_file_data, PHASE_EARLY, variables, build_file_path)
+
+ # Since some toolsets might have been defined conditionally, perform
+ # a second round of toolsets expansion now.
+ ProcessToolsetsInDict(build_file_data)
+
+ # Look at each project's target_defaults dict, and merge settings into
+ # targets.
+ if 'target_defaults' in build_file_data:
+ if 'targets' not in build_file_data:
+ raise GypError("Unable to find targets in build file %s" %
+ build_file_path)
+
+ index = 0
+ while index < len(build_file_data['targets']):
+ # This procedure needs to give the impression that target_defaults is
+ # used as defaults, and the individual targets inherit from that.
+ # The individual targets need to be merged into the defaults. Make
+ # a deep copy of the defaults for each target, merge the target dict
+ # as found in the input file into that copy, and then hook up the
+ # copy with the target-specific data merged into it as the replacement
+ # target dict.
+ old_target_dict = build_file_data['targets'][index]
+ new_target_dict = copy.deepcopy(build_file_data['target_defaults'])
+ MergeDicts(new_target_dict, old_target_dict,
+ build_file_path, build_file_path)
+ build_file_data['targets'][index] = new_target_dict
+ index += 1
+
+ # No longer needed.
+ del build_file_data['target_defaults']
+
+ # Look for dependencies. This means that dependency resolution occurs
+ # after "pre" conditionals and variable expansion, but before "post" -
+ # in other words, you can't put a "dependencies" section inside a "post"
+ # conditional within a target.
+
+ dependencies = []
+ if 'targets' in build_file_data:
+ for target_dict in build_file_data['targets']:
+ if 'dependencies' not in target_dict:
+ continue
+ for dependency in target_dict['dependencies']:
+ dependencies.append(
+ gyp.common.ResolveTarget(build_file_path, dependency, None)[0])
+
+ if load_dependencies:
+ for dependency in dependencies:
+ try:
+ LoadTargetBuildFile(dependency, data, aux_data, variables,
+ includes, depth, check, load_dependencies)
+ except Exception, e:
+ gyp.common.ExceptionAppend(
+ e, 'while loading dependencies of %s' % build_file_path)
+ raise
+ else:
+ return (build_file_path, dependencies)
+
+
+def CallLoadTargetBuildFile(global_flags,
+ build_file_path, data,
+ aux_data, variables,
+ includes, depth, check):
+ """Wrapper around LoadTargetBuildFile for parallel processing.
+
+ This wrapper is used when LoadTargetBuildFile is executed in
+ a worker process.
+ """
+
+ try:
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+ # Apply globals so that the worker process behaves the same.
+ for key, value in global_flags.iteritems():
+ globals()[key] = value
+
+ # Save the keys so we can return data that changed.
+ data_keys = set(data)
+ aux_data_keys = set(aux_data)
+
+ result = LoadTargetBuildFile(build_file_path, data,
+ aux_data, variables,
+ includes, depth, check, False)
+ if not result:
+ return result
+
+ (build_file_path, dependencies) = result
+
+ data_out = {}
+ for key in data:
+ if key == 'target_build_files':
+ continue
+ if key not in data_keys:
+ data_out[key] = data[key]
+ aux_data_out = {}
+ for key in aux_data:
+ if key not in aux_data_keys:
+ aux_data_out[key] = aux_data[key]
+
+ # This gets serialized and sent back to the main process via a pipe.
+ # It's handled in LoadTargetBuildFileCallback.
+ return (build_file_path,
+ data_out,
+ aux_data_out,
+ dependencies)
+ except Exception, e:
+ print >>sys.stderr, 'Exception: ', e
+ return None
+
+
+class ParallelProcessingError(Exception):
+ pass
+
+
+class ParallelState(object):
+ """Class to keep track of state when processing input files in parallel.
+
+ If build files are loaded in parallel, use this to keep track of
+ state during farming out and processing parallel jobs. It's stored
+ in a global so that the callback function can have access to it.
+ """
+
+ def __init__(self):
+ # The multiprocessing pool.
+ self.pool = None
+ # The condition variable used to protect this object and notify
+ # the main loop when there might be more data to process.
+ self.condition = None
+ # The "data" dict that was passed to LoadTargetBuildFileParallel
+ self.data = None
+ # The "aux_data" dict that was passed to LoadTargetBuildFileParallel
+ self.aux_data = None
+ # The number of parallel calls outstanding; decremented when a response
+ # was received.
+ self.pending = 0
+ # The set of all build files that have been scheduled, so we don't
+ # schedule the same one twice.
+ self.scheduled = set()
+ # A list of dependency build file paths that haven't been scheduled yet.
+ self.dependencies = []
+ # Flag to indicate if there was an error in a child process.
+ self.error = False
+
+ def LoadTargetBuildFileCallback(self, result):
+ """Handle the results of running LoadTargetBuildFile in another process.
+ """
+ self.condition.acquire()
+ if not result:
+ self.error = True
+ self.condition.notify()
+ self.condition.release()
+ return
+ (build_file_path0, data0, aux_data0, dependencies0) = result
+ self.data['target_build_files'].add(build_file_path0)
+ for key in data0:
+ self.data[key] = data0[key]
+ for key in aux_data0:
+ self.aux_data[key] = aux_data0[key]
+ for new_dependency in dependencies0:
+ if new_dependency not in self.scheduled:
+ self.scheduled.add(new_dependency)
+ self.dependencies.append(new_dependency)
+ self.pending -= 1
+ self.condition.notify()
+ self.condition.release()
+
+
+def LoadTargetBuildFileParallel(build_file_path, data, aux_data,
+ variables, includes, depth, check):
+ parallel_state = ParallelState()
+ parallel_state.condition = threading.Condition()
+ parallel_state.dependencies = [build_file_path]
+ parallel_state.scheduled = set([build_file_path])
+ parallel_state.pending = 0
+ parallel_state.data = data
+ parallel_state.aux_data = aux_data
+
+ try:
+ parallel_state.condition.acquire()
+ while parallel_state.dependencies or parallel_state.pending:
+ if parallel_state.error:
+ print >>sys.stderr, (
+ '\n'
+ 'Note: an error occurred while running gyp using multiprocessing.\n'
+ 'For more verbose output, set GYP_PARALLEL=0 in your environment.\n'
+ 'If the error only occurs when GYP_PARALLEL=1, '
+ 'please report a bug!')
+ break
+ if not parallel_state.dependencies:
+ parallel_state.condition.wait()
+ continue
+
+ dependency = parallel_state.dependencies.pop()
+
+ parallel_state.pending += 1
+ data_in = {}
+ data_in['target_build_files'] = data['target_build_files']
+ aux_data_in = {}
+ global_flags = {
+ 'path_sections': globals()['path_sections'],
+ 'non_configuration_keys': globals()['non_configuration_keys'],
+ 'absolute_build_file_paths': globals()['absolute_build_file_paths'],
+ 'multiple_toolsets': globals()['multiple_toolsets']}
+
+ if not parallel_state.pool:
+ parallel_state.pool = multiprocessing.Pool(8)
+ parallel_state.pool.apply_async(
+ CallLoadTargetBuildFile,
+ args = (global_flags, dependency,
+ data_in, aux_data_in,
+ variables, includes, depth, check),
+ callback = parallel_state.LoadTargetBuildFileCallback)
+ except KeyboardInterrupt, e:
+ parallel_state.pool.terminate()
+ raise e
+
+ parallel_state.condition.release()
+ if parallel_state.error:
+ sys.exit()
+
+
+# Look for the bracket that matches the first bracket seen in a
+# string, and return the start and end as a tuple. For example, if
+# the input is something like "<(foo <(bar)) blah", then it would
+# return (1, 13), indicating the entire string except for the leading
+# "<" and trailing " blah".
+LBRACKETS= set('{[(')
+BRACKETS = {'}': '{', ']': '[', ')': '('}
+def FindEnclosingBracketGroup(input_str):
+ stack = []
+ start = -1
+ for index, char in enumerate(input_str):
+ if char in LBRACKETS:
+ stack.append(char)
+ if start == -1:
+ start = index
+ elif char in BRACKETS:
+ if not stack:
+ return (-1, -1)
+ if stack.pop() != BRACKETS[char]:
+ return (-1, -1)
+ if not stack:
+ return (start, index + 1)
+ return (-1, -1)
+
+
+canonical_int_re = re.compile('(0|-?[1-9][0-9]*)$')
+
+
+def IsStrCanonicalInt(string):
+ """Returns True if |string| is in its canonical integer form.
+
+ The canonical form is such that str(int(string)) == string.
+ """
+ return isinstance(string, str) and canonical_int_re.match(string)
+
+
+# This matches things like "<(asdf)", "<!(cmd)", "<!@(cmd)", "<|(list)",
+# "<!interpreter(arguments)", "<([list])", and even "<([)" and "<(<())".
+# In the last case, the inner "<()" is captured in match['content'].
+early_variable_re = re.compile(
+ '(?P<replace>(?P<type><(?:(?:!?@?)|\|)?)'
+ '(?P<command_string>[-a-zA-Z0-9_.]+)?'
+ '\((?P<is_array>\s*\[?)'
+ '(?P<content>.*?)(\]?)\))')
+
+# This matches the same as early_variable_re, but with '>' instead of '<'.
+late_variable_re = re.compile(
+ '(?P<replace>(?P<type>>(?:(?:!?@?)|\|)?)'
+ '(?P<command_string>[-a-zA-Z0-9_.]+)?'
+ '\((?P<is_array>\s*\[?)'
+ '(?P<content>.*?)(\]?)\))')
+
+# This matches the same as early_variable_re, but with '^' instead of '<'.
+latelate_variable_re = re.compile(
+ '(?P<replace>(?P<type>[\^](?:(?:!?@?)|\|)?)'
+ '(?P<command_string>[-a-zA-Z0-9_.]+)?'
+ '\((?P<is_array>\s*\[?)'
+ '(?P<content>.*?)(\]?)\))')
+
+# Global cache of results from running commands so they don't have to be run
+# more then once.
+cached_command_results = {}
+
+
+def FixupPlatformCommand(cmd):
+ if sys.platform == 'win32':
+ if type(cmd) == list:
+ cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:]
+ else:
+ cmd = re.sub('^cat ', 'type ', cmd)
+ return cmd
+
+
+PHASE_EARLY = 0
+PHASE_LATE = 1
+PHASE_LATELATE = 2
+
+
+def ExpandVariables(input, phase, variables, build_file):
+ # Look for the pattern that gets expanded into variables
+ if phase == PHASE_EARLY:
+ variable_re = early_variable_re
+ expansion_symbol = '<'
+ elif phase == PHASE_LATE:
+ variable_re = late_variable_re
+ expansion_symbol = '>'
+ elif phase == PHASE_LATELATE:
+ variable_re = latelate_variable_re
+ expansion_symbol = '^'
+ else:
+ assert False
+
+ input_str = str(input)
+ if IsStrCanonicalInt(input_str):
+ return int(input_str)
+
+ # Do a quick scan to determine if an expensive regex search is warranted.
+ if expansion_symbol not in input_str:
+ return input_str
+
+ # Get the entire list of matches as a list of MatchObject instances.
+ # (using findall here would return strings instead of MatchObjects).
+ matches = list(variable_re.finditer(input_str))
+ if not matches:
+ return input_str
+
+ output = input_str
+ # Reverse the list of matches so that replacements are done right-to-left.
+ # That ensures that earlier replacements won't mess up the string in a
+ # way that causes later calls to find the earlier substituted text instead
+ # of what's intended for replacement.
+ matches.reverse()
+ for match_group in matches:
+ match = match_group.groupdict()
+ gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Matches: %r", match)
+ # match['replace'] is the substring to look for, match['type']
+ # is the character code for the replacement type (< > <! >! <| >| <@
+ # >@ <!@ >!@), match['is_array'] contains a '[' for command
+ # arrays, and match['content'] is the name of the variable (< >)
+ # or command to run (<! >!). match['command_string'] is an optional
+ # command string. Currently, only 'pymod_do_main' is supported.
+
+ # run_command is true if a ! variant is used.
+ run_command = '!' in match['type']
+ command_string = match['command_string']
+
+ # file_list is true if a | variant is used.
+ file_list = '|' in match['type']
+
+ # Capture these now so we can adjust them later.
+ replace_start = match_group.start('replace')
+ replace_end = match_group.end('replace')
+
+ # Find the ending paren, and re-evaluate the contained string.
+ (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:])
+
+ # Adjust the replacement range to match the entire command
+ # found by FindEnclosingBracketGroup (since the variable_re
+ # probably doesn't match the entire command if it contained
+ # nested variables).
+ replace_end = replace_start + c_end
+
+ # Find the "real" replacement, matching the appropriate closing
+ # paren, and adjust the replacement start and end.
+ replacement = input_str[replace_start:replace_end]
+
+ # Figure out what the contents of the variable parens are.
+ contents_start = replace_start + c_start + 1
+ contents_end = replace_end - 1
+ contents = input_str[contents_start:contents_end]
+
+ # Do filter substitution now for <|().
+ # Admittedly, this is different than the evaluation order in other
+ # contexts. However, since filtration has no chance to run on <|(),
+ # this seems like the only obvious way to give them access to filters.
+ if file_list:
+ processed_variables = copy.deepcopy(variables)
+ ProcessListFiltersInDict(contents, processed_variables)
+ # Recurse to expand variables in the contents
+ contents = ExpandVariables(contents, phase,
+ processed_variables, build_file)
+ else:
+ # Recurse to expand variables in the contents
+ contents = ExpandVariables(contents, phase, variables, build_file)
+
+ # Strip off leading/trailing whitespace so that variable matches are
+ # simpler below (and because they are rarely needed).
+ contents = contents.strip()
+
+ # expand_to_list is true if an @ variant is used. In that case,
+ # the expansion should result in a list. Note that the caller
+ # is to be expecting a list in return, and not all callers do
+ # because not all are working in list context. Also, for list
+ # expansions, there can be no other text besides the variable
+ # expansion in the input string.
+ expand_to_list = '@' in match['type'] and input_str == replacement
+
+ if run_command or file_list:
+ # Find the build file's directory, so commands can be run or file lists
+ # generated relative to it.
+ build_file_dir = os.path.dirname(build_file)
+ if build_file_dir == '':
+ # If build_file is just a leaf filename indicating a file in the
+ # current directory, build_file_dir might be an empty string. Set
+ # it to None to signal to subprocess.Popen that it should run the
+ # command in the current directory.
+ build_file_dir = None
+
+ # Support <|(listfile.txt ...) which generates a file
+ # containing items from a gyp list, generated at gyp time.
+ # This works around actions/rules which have more inputs than will
+ # fit on the command line.
+ if file_list:
+ if type(contents) == list:
+ contents_list = contents
+ else:
+ contents_list = contents.split(' ')
+ replacement = contents_list[0]
+ path = replacement
+ if build_file_dir and not os.path.isabs(path):
+ path = os.path.join(build_file_dir, path)
+ f = gyp.common.WriteOnDiff(path)
+ for i in contents_list[1:]:
+ f.write('%s\n' % i)
+ f.close()
+
+ elif run_command:
+ use_shell = True
+ if match['is_array']:
+ contents = eval(contents)
+ use_shell = False
+
+ # Check for a cached value to avoid executing commands, or generating
+ # file lists more than once.
+ # TODO(http://code.google.com/p/gyp/issues/detail?id=112): It is
+ # possible that the command being invoked depends on the current
+ # directory. For that case the syntax needs to be extended so that the
+ # directory is also used in cache_key (it becomes a tuple).
+ # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory,
+ # someone could author a set of GYP files where each time the command
+ # is invoked it produces different output by design. When the need
+ # arises, the syntax should be extended to support no caching off a
+ # command's output so it is run every time.
+ cache_key = str(contents)
+ cached_value = cached_command_results.get(cache_key, None)
+ if cached_value is None:
+ gyp.DebugOutput(gyp.DEBUG_VARIABLES,
+ "Executing command '%s' in directory '%s'",
+ contents, build_file_dir)
+
+ replacement = ''
+
+ if command_string == 'pymod_do_main':
+ # <!pymod_do_main(modulename param eters) loads |modulename| as a
+ # python module and then calls that module's DoMain() function,
+ # passing ["param", "eters"] as a single list argument. For modules
+ # that don't load quickly, this can be faster than
+ # <!(python modulename param eters). Do this in |build_file_dir|.
+ oldwd = os.getcwd() # Python doesn't like os.open('.'): no fchdir.
+ if build_file_dir: # build_file_dir may be None (see above).
+ os.chdir(build_file_dir)
+ try:
+
+ parsed_contents = shlex.split(contents)
+ try:
+ py_module = __import__(parsed_contents[0])
+ except ImportError as e:
+ raise GypError("Error importing pymod_do_main"
+ "module (%s): %s" % (parsed_contents[0], e))
+ replacement = str(py_module.DoMain(parsed_contents[1:])).rstrip()
+ finally:
+ os.chdir(oldwd)
+ assert replacement != None
+ elif command_string:
+ raise GypError("Unknown command string '%s' in '%s'." %
+ (command_string, contents))
+ else:
+ # Fix up command with platform specific workarounds.
+ contents = FixupPlatformCommand(contents)
+ p = subprocess.Popen(contents, shell=use_shell,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ cwd=build_file_dir)
+
+ p_stdout, p_stderr = p.communicate('')
+
+ if p.wait() != 0 or p_stderr:
+ sys.stderr.write(p_stderr)
+ # Simulate check_call behavior, since check_call only exists
+ # in python 2.5 and later.
+ raise GypError("Call to '%s' returned exit status %d." %
+ (contents, p.returncode))
+ replacement = p_stdout.rstrip()
+
+ cached_command_results[cache_key] = replacement
+ else:
+ gyp.DebugOutput(gyp.DEBUG_VARIABLES,
+ "Had cache value for command '%s' in directory '%s'",
+ contents,build_file_dir)
+ replacement = cached_value
+
+ else:
+ if not contents in variables:
+ if contents[-1] in ['!', '/']:
+ # In order to allow cross-compiles (nacl) to happen more naturally,
+ # we will allow references to >(sources/) etc. to resolve to
+ # and empty list if undefined. This allows actions to:
+ # 'action!': [
+ # '>@(_sources!)',
+ # ],
+ # 'action/': [
+ # '>@(_sources/)',
+ # ],
+ replacement = []
+ else:
+ raise GypError('Undefined variable ' + contents +
+ ' in ' + build_file)
+ else:
+ replacement = variables[contents]
+
+ if isinstance(replacement, list):
+ for item in replacement:
+ if (not contents[-1] == '/' and
+ not isinstance(item, str) and not isinstance(item, int)):
+ raise GypError('Variable ' + contents +
+ ' must expand to a string or list of strings; ' +
+ 'list contains a ' +
+ item.__class__.__name__)
+ # Run through the list and handle variable expansions in it. Since
+ # the list is guaranteed not to contain dicts, this won't do anything
+ # with conditions sections.
+ ProcessVariablesAndConditionsInList(replacement, phase, variables,
+ build_file)
+ elif not isinstance(replacement, str) and \
+ not isinstance(replacement, int):
+ raise GypError('Variable ' + contents +
+ ' must expand to a string or list of strings; ' +
+ 'found a ' + replacement.__class__.__name__)
+
+ if expand_to_list:
+ # Expanding in list context. It's guaranteed that there's only one
+ # replacement to do in |input_str| and that it's this replacement. See
+ # above.
+ if isinstance(replacement, list):
+ # If it's already a list, make a copy.
+ output = replacement[:]
+ else:
+ # Split it the same way sh would split arguments.
+ output = shlex.split(str(replacement))
+ else:
+ # Expanding in string context.
+ encoded_replacement = ''
+ if isinstance(replacement, list):
+ # When expanding a list into string context, turn the list items
+ # into a string in a way that will work with a subprocess call.
+ #
+ # TODO(mark): This isn't completely correct. This should
+ # call a generator-provided function that observes the
+ # proper list-to-argument quoting rules on a specific
+ # platform instead of just calling the POSIX encoding
+ # routine.
+ encoded_replacement = gyp.common.EncodePOSIXShellList(replacement)
+ else:
+ encoded_replacement = replacement
+
+ output = output[:replace_start] + str(encoded_replacement) + \
+ output[replace_end:]
+ # Prepare for the next match iteration.
+ input_str = output
+
+ # Look for more matches now that we've replaced some, to deal with
+ # expanding local variables (variables defined in the same
+ # variables block as this one).
+ gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output)
+ if isinstance(output, list):
+ if output and isinstance(output[0], list):
+ # Leave output alone if it's a list of lists.
+ # We don't want such lists to be stringified.
+ pass
+ else:
+ new_output = []
+ for item in output:
+ new_output.append(
+ ExpandVariables(item, phase, variables, build_file))
+ output = new_output
+ else:
+ output = ExpandVariables(output, phase, variables, build_file)
+
+ # Convert all strings that are canonically-represented integers into integers.
+ if isinstance(output, list):
+ for index in xrange(0, len(output)):
+ if IsStrCanonicalInt(output[index]):
+ output[index] = int(output[index])
+ elif IsStrCanonicalInt(output):
+ output = int(output)
+
+ return output
+
+
+def ProcessConditionsInDict(the_dict, phase, variables, build_file):
+ # Process a 'conditions' or 'target_conditions' section in the_dict,
+ # depending on phase.
+ # early -> conditions
+ # late -> target_conditions
+ # latelate -> no conditions
+ #
+ # Each item in a conditions list consists of cond_expr, a string expression
+ # evaluated as the condition, and true_dict, a dict that will be merged into
+ # the_dict if cond_expr evaluates to true. Optionally, a third item,
+ # false_dict, may be present. false_dict is merged into the_dict if
+ # cond_expr evaluates to false.
+ #
+ # Any dict merged into the_dict will be recursively processed for nested
+ # conditionals and other expansions, also according to phase, immediately
+ # prior to being merged.
+
+ if phase == PHASE_EARLY:
+ conditions_key = 'conditions'
+ elif phase == PHASE_LATE:
+ conditions_key = 'target_conditions'
+ elif phase == PHASE_LATELATE:
+ return
+ else:
+ assert False
+
+ if not conditions_key in the_dict:
+ return
+
+ conditions_list = the_dict[conditions_key]
+ # Unhook the conditions list, it's no longer needed.
+ del the_dict[conditions_key]
+
+ for condition in conditions_list:
+ if not isinstance(condition, list):
+ raise GypError(conditions_key + ' must be a list')
+ if len(condition) != 2 and len(condition) != 3:
+ # It's possible that condition[0] won't work in which case this
+ # attempt will raise its own IndexError. That's probably fine.
+ raise GypError(conditions_key + ' ' + condition[0] +
+ ' must be length 2 or 3, not ' + str(len(condition)))
+
+ [cond_expr, true_dict] = condition[0:2]
+ false_dict = None
+ if len(condition) == 3:
+ false_dict = condition[2]
+
+ # Do expansions on the condition itself. Since the conditon can naturally
+ # contain variable references without needing to resort to GYP expansion
+ # syntax, this is of dubious value for variables, but someone might want to
+ # use a command expansion directly inside a condition.
+ cond_expr_expanded = ExpandVariables(cond_expr, phase, variables,
+ build_file)
+ if not isinstance(cond_expr_expanded, str) and \
+ not isinstance(cond_expr_expanded, int):
+ raise ValueError, \
+ 'Variable expansion in this context permits str and int ' + \
+ 'only, found ' + expanded.__class__.__name__
+
+ try:
+ ast_code = compile(cond_expr_expanded, '<string>', 'eval')
+
+ if eval(ast_code, {'__builtins__': None}, variables):
+ merge_dict = true_dict
+ else:
+ merge_dict = false_dict
+ except SyntaxError, e:
+ syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s '
+ 'at character %d.' %
+ (str(e.args[0]), e.text, build_file, e.offset),
+ e.filename, e.lineno, e.offset, e.text)
+ raise syntax_error
+ except NameError, e:
+ gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' %
+ (cond_expr_expanded, build_file))
+ raise GypError(e)
+
+ if merge_dict != None:
+ # Expand variables and nested conditinals in the merge_dict before
+ # merging it.
+ ProcessVariablesAndConditionsInDict(merge_dict, phase,
+ variables, build_file)
+
+ MergeDicts(the_dict, merge_dict, build_file, build_file)
+
+
+def LoadAutomaticVariablesFromDict(variables, the_dict):
+ # Any keys with plain string values in the_dict become automatic variables.
+ # The variable name is the key name with a "_" character prepended.
+ for key, value in the_dict.iteritems():
+ if isinstance(value, str) or isinstance(value, int) or \
+ isinstance(value, list):
+ variables['_' + key] = value
+
+
+def LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key):
+ # Any keys in the_dict's "variables" dict, if it has one, becomes a
+ # variable. The variable name is the key name in the "variables" dict.
+ # Variables that end with the % character are set only if they are unset in
+ # the variables dict. the_dict_key is the name of the key that accesses
+ # the_dict in the_dict's parent dict. If the_dict's parent is not a dict
+ # (it could be a list or it could be parentless because it is a root dict),
+ # the_dict_key will be None.
+ for key, value in the_dict.get('variables', {}).iteritems():
+ if not isinstance(value, str) and not isinstance(value, int) and \
+ not isinstance(value, list):
+ continue
+
+ if key.endswith('%'):
+ variable_name = key[:-1]
+ if variable_name in variables:
+ # If the variable is already set, don't set it.
+ continue
+ if the_dict_key is 'variables' and variable_name in the_dict:
+ # If the variable is set without a % in the_dict, and the_dict is a
+ # variables dict (making |variables| a varaibles sub-dict of a
+ # variables dict), use the_dict's definition.
+ value = the_dict[variable_name]
+ else:
+ variable_name = key
+
+ variables[variable_name] = value
+
+
+def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in,
+ build_file, the_dict_key=None):
+ """Handle all variable and command expansion and conditional evaluation.
+
+ This function is the public entry point for all variable expansions and
+ conditional evaluations. The variables_in dictionary will not be modified
+ by this function.
+ """
+
+ # Make a copy of the variables_in dict that can be modified during the
+ # loading of automatics and the loading of the variables dict.
+ variables = variables_in.copy()
+ LoadAutomaticVariablesFromDict(variables, the_dict)
+
+ if 'variables' in the_dict:
+ # Make sure all the local variables are added to the variables
+ # list before we process them so that you can reference one
+ # variable from another. They will be fully expanded by recursion
+ # in ExpandVariables.
+ for key, value in the_dict['variables'].iteritems():
+ variables[key] = value
+
+ # Handle the associated variables dict first, so that any variable
+ # references within can be resolved prior to using them as variables.
+ # Pass a copy of the variables dict to avoid having it be tainted.
+ # Otherwise, it would have extra automatics added for everything that
+ # should just be an ordinary variable in this scope.
+ ProcessVariablesAndConditionsInDict(the_dict['variables'], phase,
+ variables, build_file, 'variables')
+
+ LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
+
+ for key, value in the_dict.iteritems():
+ # Skip "variables", which was already processed if present.
+ if key != 'variables' and isinstance(value, str):
+ expanded = ExpandVariables(value, phase, variables, build_file)
+ if not isinstance(expanded, str) and not isinstance(expanded, int):
+ raise ValueError, \
+ 'Variable expansion in this context permits str and int ' + \
+ 'only, found ' + expanded.__class__.__name__ + ' for ' + key
+ the_dict[key] = expanded
+
+ # Variable expansion may have resulted in changes to automatics. Reload.
+ # TODO(mark): Optimization: only reload if no changes were made.
+ variables = variables_in.copy()
+ LoadAutomaticVariablesFromDict(variables, the_dict)
+ LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
+
+ # Process conditions in this dict. This is done after variable expansion
+ # so that conditions may take advantage of expanded variables. For example,
+ # if the_dict contains:
+ # {'type': '<(library_type)',
+ # 'conditions': [['_type=="static_library"', { ... }]]},
+ # _type, as used in the condition, will only be set to the value of
+ # library_type if variable expansion is performed before condition
+ # processing. However, condition processing should occur prior to recursion
+ # so that variables (both automatic and "variables" dict type) may be
+ # adjusted by conditions sections, merged into the_dict, and have the
+ # intended impact on contained dicts.
+ #
+ # This arrangement means that a "conditions" section containing a "variables"
+ # section will only have those variables effective in subdicts, not in
+ # the_dict. The workaround is to put a "conditions" section within a
+ # "variables" section. For example:
+ # {'conditions': [['os=="mac"', {'variables': {'define': 'IS_MAC'}}]],
+ # 'defines': ['<(define)'],
+ # 'my_subdict': {'defines': ['<(define)']}},
+ # will not result in "IS_MAC" being appended to the "defines" list in the
+ # current scope but would result in it being appended to the "defines" list
+ # within "my_subdict". By comparison:
+ # {'variables': {'conditions': [['os=="mac"', {'define': 'IS_MAC'}]]},
+ # 'defines': ['<(define)'],
+ # 'my_subdict': {'defines': ['<(define)']}},
+ # will append "IS_MAC" to both "defines" lists.
+
+ # Evaluate conditions sections, allowing variable expansions within them
+ # as well as nested conditionals. This will process a 'conditions' or
+ # 'target_conditions' section, perform appropriate merging and recursive
+ # conditional and variable processing, and then remove the conditions section
+ # from the_dict if it is present.
+ ProcessConditionsInDict(the_dict, phase, variables, build_file)
+
+ # Conditional processing may have resulted in changes to automatics or the
+ # variables dict. Reload.
+ variables = variables_in.copy()
+ LoadAutomaticVariablesFromDict(variables, the_dict)
+ LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
+
+ # Recurse into child dicts, or process child lists which may result in
+ # further recursion into descendant dicts.
+ for key, value in the_dict.iteritems():
+ # Skip "variables" and string values, which were already processed if
+ # present.
+ if key == 'variables' or isinstance(value, str):
+ continue
+ if isinstance(value, dict):
+ # Pass a copy of the variables dict so that subdicts can't influence
+ # parents.
+ ProcessVariablesAndConditionsInDict(value, phase, variables,
+ build_file, key)
+ elif isinstance(value, list):
+ # The list itself can't influence the variables dict, and
+ # ProcessVariablesAndConditionsInList will make copies of the variables
+ # dict if it needs to pass it to something that can influence it. No
+ # copy is necessary here.
+ ProcessVariablesAndConditionsInList(value, phase, variables,
+ build_file)
+ elif not isinstance(value, int):
+ raise TypeError, 'Unknown type ' + value.__class__.__name__ + \
+ ' for ' + key
+
+
+def ProcessVariablesAndConditionsInList(the_list, phase, variables,
+ build_file):
+ # Iterate using an index so that new values can be assigned into the_list.
+ index = 0
+ while index < len(the_list):
+ item = the_list[index]
+ if isinstance(item, dict):
+ # Make a copy of the variables dict so that it won't influence anything
+ # outside of its own scope.
+ ProcessVariablesAndConditionsInDict(item, phase, variables, build_file)
+ elif isinstance(item, list):
+ ProcessVariablesAndConditionsInList(item, phase, variables, build_file)
+ elif isinstance(item, str):
+ expanded = ExpandVariables(item, phase, variables, build_file)
+ if isinstance(expanded, str) or isinstance(expanded, int):
+ the_list[index] = expanded
+ elif isinstance(expanded, list):
+ the_list[index:index+1] = expanded
+ index += len(expanded)
+
+ # index now identifies the next item to examine. Continue right now
+ # without falling into the index increment below.
+ continue
+ else:
+ raise ValueError, \
+ 'Variable expansion in this context permits strings and ' + \
+ 'lists only, found ' + expanded.__class__.__name__ + ' at ' + \
+ index
+ elif not isinstance(item, int):
+ raise TypeError, 'Unknown type ' + item.__class__.__name__ + \
+ ' at index ' + index
+ index = index + 1
+
+
+def BuildTargetsDict(data):
+ """Builds a dict mapping fully-qualified target names to their target dicts.
+
+ |data| is a dict mapping loaded build files by pathname relative to the
+ current directory. Values in |data| are build file contents. For each
+ |data| value with a "targets" key, the value of the "targets" key is taken
+ as a list containing target dicts. Each target's fully-qualified name is
+ constructed from the pathname of the build file (|data| key) and its
+ "target_name" property. These fully-qualified names are used as the keys
+ in the returned dict. These keys provide access to the target dicts,
+ the dicts in the "targets" lists.
+ """
+
+ targets = {}
+ for build_file in data['target_build_files']:
+ for target in data[build_file].get('targets', []):
+ target_name = gyp.common.QualifiedTarget(build_file,
+ target['target_name'],
+ target['toolset'])
+ if target_name in targets:
+ raise GypError('Duplicate target definitions for ' + target_name)
+ targets[target_name] = target
+
+ return targets
+
+
+def QualifyDependencies(targets):
+ """Make dependency links fully-qualified relative to the current directory.
+
+ |targets| is a dict mapping fully-qualified target names to their target
+ dicts. For each target in this dict, keys known to contain dependency
+ links are examined, and any dependencies referenced will be rewritten
+ so that they are fully-qualified and relative to the current directory.
+ All rewritten dependencies are suitable for use as keys to |targets| or a
+ similar dict.
+ """
+
+ all_dependency_sections = [dep + op
+ for dep in dependency_sections
+ for op in ('', '!', '/')]
+
+ for target, target_dict in targets.iteritems():
+ target_build_file = gyp.common.BuildFile(target)
+ toolset = target_dict['toolset']
+ for dependency_key in all_dependency_sections:
+ dependencies = target_dict.get(dependency_key, [])
+ for index in xrange(0, len(dependencies)):
+ dep_file, dep_target, dep_toolset = gyp.common.ResolveTarget(
+ target_build_file, dependencies[index], toolset)
+ if not multiple_toolsets:
+ # Ignore toolset specification in the dependency if it is specified.
+ dep_toolset = toolset
+ dependency = gyp.common.QualifiedTarget(dep_file,
+ dep_target,
+ dep_toolset)
+ dependencies[index] = dependency
+
+ # Make sure anything appearing in a list other than "dependencies" also
+ # appears in the "dependencies" list.
+ if dependency_key != 'dependencies' and \
+ dependency not in target_dict['dependencies']:
+ raise GypError('Found ' + dependency + ' in ' + dependency_key +
+ ' of ' + target + ', but not in dependencies')
+
+
+def ExpandWildcardDependencies(targets, data):
+ """Expands dependencies specified as build_file:*.
+
+ For each target in |targets|, examines sections containing links to other
+ targets. If any such section contains a link of the form build_file:*, it
+ is taken as a wildcard link, and is expanded to list each target in
+ build_file. The |data| dict provides access to build file dicts.
+
+ Any target that does not wish to be included by wildcard can provide an
+ optional "suppress_wildcard" key in its target dict. When present and
+ true, a wildcard dependency link will not include such targets.
+
+ All dependency names, including the keys to |targets| and the values in each
+ dependency list, must be qualified when this function is called.
+ """
+
+ for target, target_dict in targets.iteritems():
+ toolset = target_dict['toolset']
+ target_build_file = gyp.common.BuildFile(target)
+ for dependency_key in dependency_sections:
+ dependencies = target_dict.get(dependency_key, [])
+
+ # Loop this way instead of "for dependency in" or "for index in xrange"
+ # because the dependencies list will be modified within the loop body.
+ index = 0
+ while index < len(dependencies):
+ (dependency_build_file, dependency_target, dependency_toolset) = \
+ gyp.common.ParseQualifiedTarget(dependencies[index])
+ if dependency_target != '*' and dependency_toolset != '*':
+ # Not a wildcard. Keep it moving.
+ index = index + 1
+ continue
+
+ if dependency_build_file == target_build_file:
+ # It's an error for a target to depend on all other targets in
+ # the same file, because a target cannot depend on itself.
+ raise GypError('Found wildcard in ' + dependency_key + ' of ' +
+ target + ' referring to same build file')
+
+ # Take the wildcard out and adjust the index so that the next
+ # dependency in the list will be processed the next time through the
+ # loop.
+ del dependencies[index]
+ index = index - 1
+
+ # Loop through the targets in the other build file, adding them to
+ # this target's list of dependencies in place of the removed
+ # wildcard.
+ dependency_target_dicts = data[dependency_build_file]['targets']
+ for dependency_target_dict in dependency_target_dicts:
+ if int(dependency_target_dict.get('suppress_wildcard', False)):
+ continue
+ dependency_target_name = dependency_target_dict['target_name']
+ if (dependency_target != '*' and
+ dependency_target != dependency_target_name):
+ continue
+ dependency_target_toolset = dependency_target_dict['toolset']
+ if (dependency_toolset != '*' and
+ dependency_toolset != dependency_target_toolset):
+ continue
+ dependency = gyp.common.QualifiedTarget(dependency_build_file,
+ dependency_target_name,
+ dependency_target_toolset)
+ index = index + 1
+ dependencies.insert(index, dependency)
+
+ index = index + 1
+
+
+def Unify(l):
+ """Removes duplicate elements from l, keeping the first element."""
+ seen = {}
+ return [seen.setdefault(e, e) for e in l if e not in seen]
+
+
+def RemoveDuplicateDependencies(targets):
+ """Makes sure every dependency appears only once in all targets's dependency
+ lists."""
+ for target_name, target_dict in targets.iteritems():
+ for dependency_key in dependency_sections:
+ dependencies = target_dict.get(dependency_key, [])
+ if dependencies:
+ target_dict[dependency_key] = Unify(dependencies)
+
+
+def Filter(l, item):
+ """Removes item from l."""
+ res = {}
+ return [res.setdefault(e, e) for e in l if e != item]
+
+
+def RemoveSelfDependencies(targets):
+ """Remove self dependencies from targets that have the prune_self_dependency
+ variable set."""
+ for target_name, target_dict in targets.iteritems():
+ for dependency_key in dependency_sections:
+ dependencies = target_dict.get(dependency_key, [])
+ if dependencies:
+ for t in dependencies:
+ if t == target_name:
+ if targets[t].get('variables', {}).get('prune_self_dependency', 0):
+ target_dict[dependency_key] = Filter(dependencies, target_name)
+
+
+class DependencyGraphNode(object):
+ """
+
+ Attributes:
+ ref: A reference to an object that this DependencyGraphNode represents.
+ dependencies: List of DependencyGraphNodes on which this one depends.
+ dependents: List of DependencyGraphNodes that depend on this one.
+ """
+
+ class CircularException(GypError):
+ pass
+
+ def __init__(self, ref):
+ self.ref = ref
+ self.dependencies = []
+ self.dependents = []
+
+ def FlattenToList(self):
+ # flat_list is the sorted list of dependencies - actually, the list items
+ # are the "ref" attributes of DependencyGraphNodes. Every target will
+ # appear in flat_list after all of its dependencies, and before all of its
+ # dependents.
+ flat_list = []
+
+ # in_degree_zeros is the list of DependencyGraphNodes that have no
+ # dependencies not in flat_list. Initially, it is a copy of the children
+ # of this node, because when the graph was built, nodes with no
+ # dependencies were made implicit dependents of the root node.
+ in_degree_zeros = set(self.dependents[:])
+
+ while in_degree_zeros:
+ # Nodes in in_degree_zeros have no dependencies not in flat_list, so they
+ # can be appended to flat_list. Take these nodes out of in_degree_zeros
+ # as work progresses, so that the next node to process from the list can
+ # always be accessed at a consistent position.
+ node = in_degree_zeros.pop()
+ flat_list.append(node.ref)
+
+ # Look at dependents of the node just added to flat_list. Some of them
+ # may now belong in in_degree_zeros.
+ for node_dependent in node.dependents:
+ is_in_degree_zero = True
+ for node_dependent_dependency in node_dependent.dependencies:
+ if not node_dependent_dependency.ref in flat_list:
+ # The dependent one or more dependencies not in flat_list. There
+ # will be more chances to add it to flat_list when examining
+ # it again as a dependent of those other dependencies, provided
+ # that there are no cycles.
+ is_in_degree_zero = False
+ break
+
+ if is_in_degree_zero:
+ # All of the dependent's dependencies are already in flat_list. Add
+ # it to in_degree_zeros where it will be processed in a future
+ # iteration of the outer loop.
+ in_degree_zeros.add(node_dependent)
+
+ return flat_list
+
+ def DirectDependencies(self, dependencies=None):
+ """Returns a list of just direct dependencies."""
+ if dependencies == None:
+ dependencies = []
+
+ for dependency in self.dependencies:
+ # Check for None, corresponding to the root node.
+ if dependency.ref != None and dependency.ref not in dependencies:
+ dependencies.append(dependency.ref)
+
+ return dependencies
+
+ def _AddImportedDependencies(self, targets, dependencies=None):
+ """Given a list of direct dependencies, adds indirect dependencies that
+ other dependencies have declared to export their settings.
+
+ This method does not operate on self. Rather, it operates on the list
+ of dependencies in the |dependencies| argument. For each dependency in
+ that list, if any declares that it exports the settings of one of its
+ own dependencies, those dependencies whose settings are "passed through"
+ are added to the list. As new items are added to the list, they too will
+ be processed, so it is possible to import settings through multiple levels
+ of dependencies.
+
+ This method is not terribly useful on its own, it depends on being
+ "primed" with a list of direct dependencies such as one provided by
+ DirectDependencies. DirectAndImportedDependencies is intended to be the
+ public entry point.
+ """
+
+ if dependencies == None:
+ dependencies = []
+
+ index = 0
+ while index < len(dependencies):
+ dependency = dependencies[index]
+ dependency_dict = targets[dependency]
+ # Add any dependencies whose settings should be imported to the list
+ # if not already present. Newly-added items will be checked for
+ # their own imports when the list iteration reaches them.
+ # Rather than simply appending new items, insert them after the
+ # dependency that exported them. This is done to more closely match
+ # the depth-first method used by DeepDependencies.
+ add_index = 1
+ for imported_dependency in \
+ dependency_dict.get('export_dependent_settings', []):
+ if imported_dependency not in dependencies:
+ dependencies.insert(index + add_index, imported_dependency)
+ add_index = add_index + 1
+ index = index + 1
+
+ return dependencies
+
+ def DirectAndImportedDependencies(self, targets, dependencies=None):
+ """Returns a list of a target's direct dependencies and all indirect
+ dependencies that a dependency has advertised settings should be exported
+ through the dependency for.
+ """
+
+ dependencies = self.DirectDependencies(dependencies)
+ return self._AddImportedDependencies(targets, dependencies)
+
+ def DeepDependencies(self, dependencies=None):
+ """Returns a list of all of a target's dependencies, recursively."""
+ if dependencies == None:
+ dependencies = []
+
+ for dependency in self.dependencies:
+ # Check for None, corresponding to the root node.
+ if dependency.ref != None and dependency.ref not in dependencies:
+ dependencies.append(dependency.ref)
+ dependency.DeepDependencies(dependencies)
+
+ return dependencies
+
+ def LinkDependencies(self, targets, dependencies=None, initial=True):
+ """Returns a list of dependency targets that are linked into this target.
+
+ This function has a split personality, depending on the setting of
+ |initial|. Outside callers should always leave |initial| at its default
+ setting.
+
+ When adding a target to the list of dependencies, this function will
+ recurse into itself with |initial| set to False, to collect dependencies
+ that are linked into the linkable target for which the list is being built.
+ """
+ if dependencies == None:
+ dependencies = []
+
+ # Check for None, corresponding to the root node.
+ if self.ref == None:
+ return dependencies
+
+ # It's kind of sucky that |targets| has to be passed into this function,
+ # but that's presently the easiest way to access the target dicts so that
+ # this function can find target types.
+
+ if 'target_name' not in targets[self.ref]:
+ raise GypError("Missing 'target_name' field in target.")
+
+ if 'type' not in targets[self.ref]:
+ raise GypError("Missing 'type' field in target %s" %
+ targets[self.ref]['target_name'])
+
+ target_type = targets[self.ref]['type']
+
+ is_linkable = target_type in linkable_types
+
+ if initial and not is_linkable:
+ # If this is the first target being examined and it's not linkable,
+ # return an empty list of link dependencies, because the link
+ # dependencies are intended to apply to the target itself (initial is
+ # True) and this target won't be linked.
+ return dependencies
+
+ # Don't traverse 'none' targets if explicitly excluded.
+ if (target_type == 'none' and
+ not targets[self.ref].get('dependencies_traverse', True)):
+ if self.ref not in dependencies:
+ dependencies.append(self.ref)
+ return dependencies
+
+ # Executables and loadable modules are already fully and finally linked.
+ # Nothing else can be a link dependency of them, there can only be
+ # dependencies in the sense that a dependent target might run an
+ # executable or load the loadable_module.
+ if not initial and target_type in ('executable', 'loadable_module'):
+ return dependencies
+
+ # The target is linkable, add it to the list of link dependencies.
+ if self.ref not in dependencies:
+ dependencies.append(self.ref)
+ if initial or not is_linkable:
+ # If this is a subsequent target and it's linkable, don't look any
+ # further for linkable dependencies, as they'll already be linked into
+ # this target linkable. Always look at dependencies of the initial
+ # target, and always look at dependencies of non-linkables.
+ for dependency in self.dependencies:
+ dependency.LinkDependencies(targets, dependencies, False)
+
+ return dependencies
+
+
+def BuildDependencyList(targets):
+ # Create a DependencyGraphNode for each target. Put it into a dict for easy
+ # access.
+ dependency_nodes = {}
+ for target, spec in targets.iteritems():
+ if target not in dependency_nodes:
+ dependency_nodes[target] = DependencyGraphNode(target)
+
+ # Set up the dependency links. Targets that have no dependencies are treated
+ # as dependent on root_node.
+ root_node = DependencyGraphNode(None)
+ for target, spec in targets.iteritems():
+ target_node = dependency_nodes[target]
+ target_build_file = gyp.common.BuildFile(target)
+ dependencies = spec.get('dependencies')
+ if not dependencies:
+ target_node.dependencies = [root_node]
+ root_node.dependents.append(target_node)
+ else:
+ for dependency in dependencies:
+ dependency_node = dependency_nodes.get(dependency)
+ if not dependency_node:
+ raise GypError("Dependency '%s' not found while "
+ "trying to load target %s" % (dependency, target))
+ target_node.dependencies.append(dependency_node)
+ dependency_node.dependents.append(target_node)
+
+ flat_list = root_node.FlattenToList()
+
+ # If there's anything left unvisited, there must be a circular dependency
+ # (cycle). If you need to figure out what's wrong, look for elements of
+ # targets that are not in flat_list.
+ if len(flat_list) != len(targets):
+ raise DependencyGraphNode.CircularException(
+ 'Some targets not reachable, cycle in dependency graph detected: ' +
+ ' '.join(set(flat_list) ^ set(targets)))
+
+ return [dependency_nodes, flat_list]
+
+
+def VerifyNoGYPFileCircularDependencies(targets):
+ # Create a DependencyGraphNode for each gyp file containing a target. Put
+ # it into a dict for easy access.
+ dependency_nodes = {}
+ for target in targets.iterkeys():
+ build_file = gyp.common.BuildFile(target)
+ if not build_file in dependency_nodes:
+ dependency_nodes[build_file] = DependencyGraphNode(build_file)
+
+ # Set up the dependency links.
+ for target, spec in targets.iteritems():
+ build_file = gyp.common.BuildFile(target)
+ build_file_node = dependency_nodes[build_file]
+ target_dependencies = spec.get('dependencies', [])
+ for dependency in target_dependencies:
+ try:
+ dependency_build_file = gyp.common.BuildFile(dependency)
+ except GypError, e:
+ gyp.common.ExceptionAppend(
+ e, 'while computing dependencies of .gyp file %s' % build_file)
+ raise
+
+ if dependency_build_file == build_file:
+ # A .gyp file is allowed to refer back to itself.
+ continue
+ dependency_node = dependency_nodes.get(dependency_build_file)
+ if not dependency_node:
+ raise GypError("Dependancy '%s' not found" % dependency_build_file)
+ if dependency_node not in build_file_node.dependencies:
+ build_file_node.dependencies.append(dependency_node)
+ dependency_node.dependents.append(build_file_node)
+
+
+ # Files that have no dependencies are treated as dependent on root_node.
+ root_node = DependencyGraphNode(None)
+ for build_file_node in dependency_nodes.itervalues():
+ if len(build_file_node.dependencies) == 0:
+ build_file_node.dependencies.append(root_node)
+ root_node.dependents.append(build_file_node)
+
+ flat_list = root_node.FlattenToList()
+
+ # If there's anything left unvisited, there must be a circular dependency
+ # (cycle).
+ if len(flat_list) != len(dependency_nodes):
+ bad_files = []
+ for file in dependency_nodes.iterkeys():
+ if not file in flat_list:
+ bad_files.append(file)
+ raise DependencyGraphNode.CircularException, \
+ 'Some files not reachable, cycle in .gyp file dependency graph ' + \
+ 'detected involving some or all of: ' + \
+ ' '.join(bad_files)
+
+
+def DoDependentSettings(key, flat_list, targets, dependency_nodes):
+ # key should be one of all_dependent_settings, direct_dependent_settings,
+ # or link_settings.
+
+ for target in flat_list:
+ target_dict = targets[target]
+ build_file = gyp.common.BuildFile(target)
+
+ if key == 'all_dependent_settings':
+ dependencies = dependency_nodes[target].DeepDependencies()
+ elif key == 'direct_dependent_settings':
+ dependencies = \
+ dependency_nodes[target].DirectAndImportedDependencies(targets)
+ elif key == 'link_settings':
+ dependencies = dependency_nodes[target].LinkDependencies(targets)
+ else:
+ raise GypError("DoDependentSettings doesn't know how to determine "
+ 'dependencies for ' + key)
+
+ for dependency in dependencies:
+ dependency_dict = targets[dependency]
+ if not key in dependency_dict:
+ continue
+ dependency_build_file = gyp.common.BuildFile(dependency)
+ MergeDicts(target_dict, dependency_dict[key],
+ build_file, dependency_build_file)
+
+
+def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes,
+ sort_dependencies):
+ # Recompute target "dependencies" properties. For each static library
+ # target, remove "dependencies" entries referring to other static libraries,
+ # unless the dependency has the "hard_dependency" attribute set. For each
+ # linkable target, add a "dependencies" entry referring to all of the
+ # target's computed list of link dependencies (including static libraries
+ # if no such entry is already present.
+ for target in flat_list:
+ target_dict = targets[target]
+ target_type = target_dict['type']
+
+ if target_type == 'static_library':
+ if not 'dependencies' in target_dict:
+ continue
+
+ target_dict['dependencies_original'] = target_dict.get(
+ 'dependencies', [])[:]
+
+ # A static library should not depend on another static library unless
+ # the dependency relationship is "hard," which should only be done when
+ # a dependent relies on some side effect other than just the build
+ # product, like a rule or action output. Further, if a target has a
+ # non-hard dependency, but that dependency exports a hard dependency,
+ # the non-hard dependency can safely be removed, but the exported hard
+ # dependency must be added to the target to keep the same dependency
+ # ordering.
+ dependencies = \
+ dependency_nodes[target].DirectAndImportedDependencies(targets)
+ index = 0
+ while index < len(dependencies):
+ dependency = dependencies[index]
+ dependency_dict = targets[dependency]
+
+ # Remove every non-hard static library dependency and remove every
+ # non-static library dependency that isn't a direct dependency.
+ if (dependency_dict['type'] == 'static_library' and \
+ not dependency_dict.get('hard_dependency', False)) or \
+ (dependency_dict['type'] != 'static_library' and \
+ not dependency in target_dict['dependencies']):
+ # Take the dependency out of the list, and don't increment index
+ # because the next dependency to analyze will shift into the index
+ # formerly occupied by the one being removed.
+ del dependencies[index]
+ else:
+ index = index + 1
+
+ # Update the dependencies. If the dependencies list is empty, it's not
+ # needed, so unhook it.
+ if len(dependencies) > 0:
+ target_dict['dependencies'] = dependencies
+ else:
+ del target_dict['dependencies']
+
+ elif target_type in linkable_types:
+ # Get a list of dependency targets that should be linked into this
+ # target. Add them to the dependencies list if they're not already
+ # present.
+
+ link_dependencies = dependency_nodes[target].LinkDependencies(targets)
+ for dependency in link_dependencies:
+ if dependency == target:
+ continue
+ if not 'dependencies' in target_dict:
+ target_dict['dependencies'] = []
+ if not dependency in target_dict['dependencies']:
+ target_dict['dependencies'].append(dependency)
+ # Sort the dependencies list in the order from dependents to dependencies.
+ # e.g. If A and B depend on C and C depends on D, sort them in A, B, C, D.
+ # Note: flat_list is already sorted in the order from dependencies to
+ # dependents.
+ if sort_dependencies and 'dependencies' in target_dict:
+ target_dict['dependencies'] = [dep for dep in reversed(flat_list)
+ if dep in target_dict['dependencies']]
+
+
+# Initialize this here to speed up MakePathRelative.
+exception_re = re.compile(r'''["']?[-/$<>^]''')
+
+
+def MakePathRelative(to_file, fro_file, item):
+ # If item is a relative path, it's relative to the build file dict that it's
+ # coming from. Fix it up to make it relative to the build file dict that
+ # it's going into.
+ # Exception: any |item| that begins with these special characters is
+ # returned without modification.
+ # / Used when a path is already absolute (shortcut optimization;
+ # such paths would be returned as absolute anyway)
+ # $ Used for build environment variables
+ # - Used for some build environment flags (such as -lapr-1 in a
+ # "libraries" section)
+ # < Used for our own variable and command expansions (see ExpandVariables)
+ # > Used for our own variable and command expansions (see ExpandVariables)
+ # ^ Used for our own variable and command expansions (see ExpandVariables)
+ #
+ # "/' Used when a value is quoted. If these are present, then we
+ # check the second character instead.
+ #
+ if to_file == fro_file or exception_re.match(item):
+ return item
+ else:
+ # TODO(dglazkov) The backslash/forward-slash replacement at the end is a
+ # temporary measure. This should really be addressed by keeping all paths
+ # in POSIX until actual project generation.
+ ret = os.path.normpath(os.path.join(
+ gyp.common.RelativePath(os.path.dirname(fro_file),
+ os.path.dirname(to_file)),
+ item)).replace('\\', '/')
+ if item[-1] == '/':
+ ret += '/'
+ return ret
+
+def MergeLists(to, fro, to_file, fro_file, is_paths=False, append=True):
+ # Python documentation recommends objects which do not support hash
+ # set this value to None. Python library objects follow this rule.
+ is_hashable = lambda val: val.__hash__
+
+ # If x is hashable, returns whether x is in s. Else returns whether x is in l.
+ def is_in_set_or_list(x, s, l):
+ if is_hashable(x):
+ return x in s
+ return x in l
+
+ prepend_index = 0
+
+ # Make membership testing of hashables in |to| (in particular, strings)
+ # faster.
+ hashable_to_set = set(x for x in to if is_hashable(x))
+ for item in fro:
+ singleton = False
+ if isinstance(item, str) or isinstance(item, int):
+ # The cheap and easy case.
+ if is_paths:
+ to_item = MakePathRelative(to_file, fro_file, item)
+ else:
+ to_item = item
+
+ if not isinstance(item, str) or not item.startswith('-'):
+ # Any string that doesn't begin with a "-" is a singleton - it can
+ # only appear once in a list, to be enforced by the list merge append
+ # or prepend.
+ singleton = True
+ elif isinstance(item, dict):
+ # Make a copy of the dictionary, continuing to look for paths to fix.
+ # The other intelligent aspects of merge processing won't apply because
+ # item is being merged into an empty dict.
+ to_item = {}
+ MergeDicts(to_item, item, to_file, fro_file)
+ elif isinstance(item, list):
+ # Recurse, making a copy of the list. If the list contains any
+ # descendant dicts, path fixing will occur. Note that here, custom
+ # values for is_paths and append are dropped; those are only to be
+ # applied to |to| and |fro|, not sublists of |fro|. append shouldn't
+ # matter anyway because the new |to_item| list is empty.
+ to_item = []
+ MergeLists(to_item, item, to_file, fro_file)
+ else:
+ raise TypeError, \
+ 'Attempt to merge list item of unsupported type ' + \
+ item.__class__.__name__
+
+ if append:
+ # If appending a singleton that's already in the list, don't append.
+ # This ensures that the earliest occurrence of the item will stay put.
+ if not singleton or not is_in_set_or_list(to_item, hashable_to_set, to):
+ to.append(to_item)
+ if is_hashable(to_item):
+ hashable_to_set.add(to_item)
+ else:
+ # If prepending a singleton that's already in the list, remove the
+ # existing instance and proceed with the prepend. This ensures that the
+ # item appears at the earliest possible position in the list.
+ while singleton and to_item in to:
+ to.remove(to_item)
+
+ # Don't just insert everything at index 0. That would prepend the new
+ # items to the list in reverse order, which would be an unwelcome
+ # surprise.
+ to.insert(prepend_index, to_item)
+ if is_hashable(to_item):
+ hashable_to_set.add(to_item)
+ prepend_index = prepend_index + 1
+
+
+def MergeDicts(to, fro, to_file, fro_file):
+ # I wanted to name the parameter "from" but it's a Python keyword...
+ for k, v in fro.iteritems():
+ # It would be nice to do "if not k in to: to[k] = v" but that wouldn't give
+ # copy semantics. Something else may want to merge from the |fro| dict
+ # later, and having the same dict ref pointed to twice in the tree isn't
+ # what anyone wants considering that the dicts may subsequently be
+ # modified.
+ if k in to:
+ bad_merge = False
+ if isinstance(v, str) or isinstance(v, int):
+ if not (isinstance(to[k], str) or isinstance(to[k], int)):
+ bad_merge = True
+ elif v.__class__ != to[k].__class__:
+ bad_merge = True
+
+ if bad_merge:
+ raise TypeError, \
+ 'Attempt to merge dict value of type ' + v.__class__.__name__ + \
+ ' into incompatible type ' + to[k].__class__.__name__ + \
+ ' for key ' + k
+ if isinstance(v, str) or isinstance(v, int):
+ # Overwrite the existing value, if any. Cheap and easy.
+ is_path = IsPathSection(k)
+ if is_path:
+ to[k] = MakePathRelative(to_file, fro_file, v)
+ else:
+ to[k] = v
+ elif isinstance(v, dict):
+ # Recurse, guaranteeing copies will be made of objects that require it.
+ if not k in to:
+ to[k] = {}
+ MergeDicts(to[k], v, to_file, fro_file)
+ elif isinstance(v, list):
+ # Lists in dicts can be merged with different policies, depending on
+ # how the key in the "from" dict (k, the from-key) is written.
+ #
+ # If the from-key has ...the to-list will have this action
+ # this character appended:... applied when receiving the from-list:
+ # = replace
+ # + prepend
+ # ? set, only if to-list does not yet exist
+ # (none) append
+ #
+ # This logic is list-specific, but since it relies on the associated
+ # dict key, it's checked in this dict-oriented function.
+ ext = k[-1]
+ append = True
+ if ext == '=':
+ list_base = k[:-1]
+ lists_incompatible = [list_base, list_base + '?']
+ to[list_base] = []
+ elif ext == '+':
+ list_base = k[:-1]
+ lists_incompatible = [list_base + '=', list_base + '?']
+ append = False
+ elif ext == '?':
+ list_base = k[:-1]
+ lists_incompatible = [list_base, list_base + '=', list_base + '+']
+ else:
+ list_base = k
+ lists_incompatible = [list_base + '=', list_base + '?']
+
+ # Some combinations of merge policies appearing together are meaningless.
+ # It's stupid to replace and append simultaneously, for example. Append
+ # and prepend are the only policies that can coexist.
+ for list_incompatible in lists_incompatible:
+ if list_incompatible in fro:
+ raise GypError('Incompatible list policies ' + k + ' and ' +
+ list_incompatible)
+
+ if list_base in to:
+ if ext == '?':
+ # If the key ends in "?", the list will only be merged if it doesn't
+ # already exist.
+ continue
+ if not isinstance(to[list_base], list):
+ # This may not have been checked above if merging in a list with an
+ # extension character.
+ raise TypeError, \
+ 'Attempt to merge dict value of type ' + v.__class__.__name__ + \
+ ' into incompatible type ' + to[list_base].__class__.__name__ + \
+ ' for key ' + list_base + '(' + k + ')'
+ else:
+ to[list_base] = []
+
+ # Call MergeLists, which will make copies of objects that require it.
+ # MergeLists can recurse back into MergeDicts, although this will be
+ # to make copies of dicts (with paths fixed), there will be no
+ # subsequent dict "merging" once entering a list because lists are
+ # always replaced, appended to, or prepended to.
+ is_paths = IsPathSection(list_base)
+ MergeLists(to[list_base], v, to_file, fro_file, is_paths, append)
+ else:
+ raise TypeError, \
+ 'Attempt to merge dict value of unsupported type ' + \
+ v.__class__.__name__ + ' for key ' + k
+
+
+def MergeConfigWithInheritance(new_configuration_dict, build_file,
+ target_dict, configuration, visited):
+ # Skip if previously visted.
+ if configuration in visited:
+ return
+
+ # Look at this configuration.
+ configuration_dict = target_dict['configurations'][configuration]
+
+ # Merge in parents.
+ for parent in configuration_dict.get('inherit_from', []):
+ MergeConfigWithInheritance(new_configuration_dict, build_file,
+ target_dict, parent, visited + [configuration])
+
+ # Merge it into the new config.
+ MergeDicts(new_configuration_dict, configuration_dict,
+ build_file, build_file)
+
+ # Drop abstract.
+ if 'abstract' in new_configuration_dict:
+ del new_configuration_dict['abstract']
+
+
+def SetUpConfigurations(target, target_dict):
+ # key_suffixes is a list of key suffixes that might appear on key names.
+ # These suffixes are handled in conditional evaluations (for =, +, and ?)
+ # and rules/exclude processing (for ! and /). Keys with these suffixes
+ # should be treated the same as keys without.
+ key_suffixes = ['=', '+', '?', '!', '/']
+
+ build_file = gyp.common.BuildFile(target)
+
+ # Provide a single configuration by default if none exists.
+ # TODO(mark): Signal an error if default_configurations exists but
+ # configurations does not.
+ if not 'configurations' in target_dict:
+ target_dict['configurations'] = {'Default': {}}
+ if not 'default_configuration' in target_dict:
+ concrete = [i for i in target_dict['configurations'].iterkeys()
+ if not target_dict['configurations'][i].get('abstract')]
+ target_dict['default_configuration'] = sorted(concrete)[0]
+
+ for configuration in target_dict['configurations'].keys():
+ old_configuration_dict = target_dict['configurations'][configuration]
+ # Skip abstract configurations (saves work only).
+ if old_configuration_dict.get('abstract'):
+ continue
+ # Configurations inherit (most) settings from the enclosing target scope.
+ # Get the inheritance relationship right by making a copy of the target
+ # dict.
+ new_configuration_dict = copy.deepcopy(target_dict)
+
+ # Take out the bits that don't belong in a "configurations" section.
+ # Since configuration setup is done before conditional, exclude, and rules
+ # processing, be careful with handling of the suffix characters used in
+ # those phases.
+ delete_keys = []
+ for key in new_configuration_dict:
+ key_ext = key[-1:]
+ if key_ext in key_suffixes:
+ key_base = key[:-1]
+ else:
+ key_base = key
+ if key_base in non_configuration_keys:
+ delete_keys.append(key)
+
+ for key in delete_keys:
+ del new_configuration_dict[key]
+
+ # Merge in configuration (with all its parents first).
+ MergeConfigWithInheritance(new_configuration_dict, build_file,
+ target_dict, configuration, [])
+
+ # Put the new result back into the target dict as a configuration.
+ target_dict['configurations'][configuration] = new_configuration_dict
+
+ # Now drop all the abstract ones.
+ for configuration in target_dict['configurations'].keys():
+ old_configuration_dict = target_dict['configurations'][configuration]
+ if old_configuration_dict.get('abstract'):
+ del target_dict['configurations'][configuration]
+
+ # Now that all of the target's configurations have been built, go through
+ # the target dict's keys and remove everything that's been moved into a
+ # "configurations" section.
+ delete_keys = []
+ for key in target_dict:
+ key_ext = key[-1:]
+ if key_ext in key_suffixes:
+ key_base = key[:-1]
+ else:
+ key_base = key
+ if not key_base in non_configuration_keys:
+ delete_keys.append(key)
+ for key in delete_keys:
+ del target_dict[key]
+
+ # Check the configurations to see if they contain invalid keys.
+ for configuration in target_dict['configurations'].keys():
+ configuration_dict = target_dict['configurations'][configuration]
+ for key in configuration_dict.keys():
+ if key in invalid_configuration_keys:
+ raise GypError('%s not allowed in the %s configuration, found in '
+ 'target %s' % (key, configuration, target))
+
+
+
+def ProcessListFiltersInDict(name, the_dict):
+ """Process regular expression and exclusion-based filters on lists.
+
+ An exclusion list is in a dict key named with a trailing "!", like
+ "sources!". Every item in such a list is removed from the associated
+ main list, which in this example, would be "sources". Removed items are
+ placed into a "sources_excluded" list in the dict.
+
+ Regular expression (regex) filters are contained in dict keys named with a
+ trailing "/", such as "sources/" to operate on the "sources" list. Regex
+ filters in a dict take the form:
+ 'sources/': [ ['exclude', '_(linux|mac|win)\\.cc$'],
+ ['include', '_mac\\.cc$'] ],
+ The first filter says to exclude all files ending in _linux.cc, _mac.cc, and
+ _win.cc. The second filter then includes all files ending in _mac.cc that
+ are now or were once in the "sources" list. Items matching an "exclude"
+ filter are subject to the same processing as would occur if they were listed
+ by name in an exclusion list (ending in "!"). Items matching an "include"
+ filter are brought back into the main list if previously excluded by an
+ exclusion list or exclusion regex filter. Subsequent matching "exclude"
+ patterns can still cause items to be excluded after matching an "include".
+ """
+
+ # Look through the dictionary for any lists whose keys end in "!" or "/".
+ # These are lists that will be treated as exclude lists and regular
+ # expression-based exclude/include lists. Collect the lists that are
+ # needed first, looking for the lists that they operate on, and assemble
+ # then into |lists|. This is done in a separate loop up front, because
+ # the _included and _excluded keys need to be added to the_dict, and that
+ # can't be done while iterating through it.
+
+ lists = []
+ del_lists = []
+ for key, value in the_dict.iteritems():
+ operation = key[-1]
+ if operation != '!' and operation != '/':
+ continue
+
+ if not isinstance(value, list):
+ raise ValueError, name + ' key ' + key + ' must be list, not ' + \
+ value.__class__.__name__
+
+ list_key = key[:-1]
+ if list_key not in the_dict:
+ # This happens when there's a list like "sources!" but no corresponding
+ # "sources" list. Since there's nothing for it to operate on, queue up
+ # the "sources!" list for deletion now.
+ del_lists.append(key)
+ continue
+
+ if not isinstance(the_dict[list_key], list):
+ raise ValueError, name + ' key ' + list_key + \
+ ' must be list, not ' + \
+ value.__class__.__name__ + ' when applying ' + \
+ {'!': 'exclusion', '/': 'regex'}[operation]
+
+ if not list_key in lists:
+ lists.append(list_key)
+
+ # Delete the lists that are known to be unneeded at this point.
+ for del_list in del_lists:
+ del the_dict[del_list]
+
+ for list_key in lists:
+ the_list = the_dict[list_key]
+
+ # Initialize the list_actions list, which is parallel to the_list. Each
+ # item in list_actions identifies whether the corresponding item in
+ # the_list should be excluded, unconditionally preserved (included), or
+ # whether no exclusion or inclusion has been applied. Items for which
+ # no exclusion or inclusion has been applied (yet) have value -1, items
+ # excluded have value 0, and items included have value 1. Includes and
+ # excludes override previous actions. All items in list_actions are
+ # initialized to -1 because no excludes or includes have been processed
+ # yet.
+ list_actions = list((-1,) * len(the_list))
+
+ exclude_key = list_key + '!'
+ if exclude_key in the_dict:
+ for exclude_item in the_dict[exclude_key]:
+ for index in xrange(0, len(the_list)):
+ if exclude_item == the_list[index]:
+ # This item matches the exclude_item, so set its action to 0
+ # (exclude).
+ list_actions[index] = 0
+
+ # The "whatever!" list is no longer needed, dump it.
+ del the_dict[exclude_key]
+
+ regex_key = list_key + '/'
+ if regex_key in the_dict:
+ for regex_item in the_dict[regex_key]:
+ [action, pattern] = regex_item
+ pattern_re = re.compile(pattern)
+
+ if action == 'exclude':
+ # This item matches an exclude regex, so set its value to 0 (exclude).
+ action_value = 0
+ elif action == 'include':
+ # This item matches an include regex, so set its value to 1 (include).
+ action_value = 1
+ else:
+ # This is an action that doesn't make any sense.
+ raise ValueError, 'Unrecognized action ' + action + ' in ' + name + \
+ ' key ' + regex_key
+
+ for index in xrange(0, len(the_list)):
+ list_item = the_list[index]
+ if list_actions[index] == action_value:
+ # Even if the regex matches, nothing will change so continue (regex
+ # searches are expensive).
+ continue
+ if pattern_re.search(list_item):
+ # Regular expression match.
+ list_actions[index] = action_value
+
+ # The "whatever/" list is no longer needed, dump it.
+ del the_dict[regex_key]
+
+ # Add excluded items to the excluded list.
+ #
+ # Note that exclude_key ("sources!") is different from excluded_key
+ # ("sources_excluded"). The exclude_key list is input and it was already
+ # processed and deleted; the excluded_key list is output and it's about
+ # to be created.
+ excluded_key = list_key + '_excluded'
+ if excluded_key in the_dict:
+ raise GypError(name + ' key ' + excluded_key +
+ ' must not be present prior '
+ ' to applying exclusion/regex filters for ' + list_key)
+
+ excluded_list = []
+
+ # Go backwards through the list_actions list so that as items are deleted,
+ # the indices of items that haven't been seen yet don't shift. That means
+ # that things need to be prepended to excluded_list to maintain them in the
+ # same order that they existed in the_list.
+ for index in xrange(len(list_actions) - 1, -1, -1):
+ if list_actions[index] == 0:
+ # Dump anything with action 0 (exclude). Keep anything with action 1
+ # (include) or -1 (no include or exclude seen for the item).
+ excluded_list.insert(0, the_list[index])
+ del the_list[index]
+
+ # If anything was excluded, put the excluded list into the_dict at
+ # excluded_key.
+ if len(excluded_list) > 0:
+ the_dict[excluded_key] = excluded_list
+
+ # Now recurse into subdicts and lists that may contain dicts.
+ for key, value in the_dict.iteritems():
+ if isinstance(value, dict):
+ ProcessListFiltersInDict(key, value)
+ elif isinstance(value, list):
+ ProcessListFiltersInList(key, value)
+
+
+def ProcessListFiltersInList(name, the_list):
+ for item in the_list:
+ if isinstance(item, dict):
+ ProcessListFiltersInDict(name, item)
+ elif isinstance(item, list):
+ ProcessListFiltersInList(name, item)
+
+
+def ValidateTargetType(target, target_dict):
+ """Ensures the 'type' field on the target is one of the known types.
+
+ Arguments:
+ target: string, name of target.
+ target_dict: dict, target spec.
+
+ Raises an exception on error.
+ """
+ VALID_TARGET_TYPES = ('executable', 'loadable_module',
+ 'static_library', 'shared_library',
+ 'none')
+ target_type = target_dict.get('type', None)
+ if target_type not in VALID_TARGET_TYPES:
+ raise GypError("Target %s has an invalid target type '%s'. "
+ "Must be one of %s." %
+ (target, target_type, '/'.join(VALID_TARGET_TYPES)))
+ if (target_dict.get('standalone_static_library', 0) and
+ not target_type == 'static_library'):
+ raise GypError('Target %s has type %s but standalone_static_library flag is'
+ ' only valid for static_library type.' % (target,
+ target_type))
+
+
+def ValidateSourcesInTarget(target, target_dict, build_file):
+ # TODO: Check if MSVC allows this for loadable_module targets.
+ if target_dict.get('type', None) not in ('static_library', 'shared_library'):
+ return
+ sources = target_dict.get('sources', [])
+ basenames = {}
+ for source in sources:
+ name, ext = os.path.splitext(source)
+ is_compiled_file = ext in [
+ '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S']
+ if not is_compiled_file:
+ continue
+ basename = os.path.basename(name) # Don't include extension.
+ basenames.setdefault(basename, []).append(source)
+
+ error = ''
+ for basename, files in basenames.iteritems():
+ if len(files) > 1:
+ error += ' %s: %s\n' % (basename, ' '.join(files))
+
+ if error:
+ print('static library %s has several files with the same basename:\n' %
+ target + error + 'Some build systems, e.g. MSVC08, '
+ 'cannot handle that.')
+ raise GypError('Duplicate basenames in sources section, see list above')
+
+
+def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules):
+ """Ensures that the rules sections in target_dict are valid and consistent,
+ and determines which sources they apply to.
+
+ Arguments:
+ target: string, name of target.
+ target_dict: dict, target spec containing "rules" and "sources" lists.
+ extra_sources_for_rules: a list of keys to scan for rule matches in
+ addition to 'sources'.
+ """
+
+ # Dicts to map between values found in rules' 'rule_name' and 'extension'
+ # keys and the rule dicts themselves.
+ rule_names = {}
+ rule_extensions = {}
+
+ rules = target_dict.get('rules', [])
+ for rule in rules:
+ # Make sure that there's no conflict among rule names and extensions.
+ rule_name = rule['rule_name']
+ if rule_name in rule_names:
+ raise GypError('rule %s exists in duplicate, target %s' %
+ (rule_name, target))
+ rule_names[rule_name] = rule
+
+ rule_extension = rule['extension']
+ if rule_extension.startswith('.'):
+ rule_extension = rule_extension[1:]
+ if rule_extension in rule_extensions:
+ raise GypError(('extension %s associated with multiple rules, ' +
+ 'target %s rules %s and %s') %
+ (rule_extension, target,
+ rule_extensions[rule_extension]['rule_name'],
+ rule_name))
+ rule_extensions[rule_extension] = rule
+
+ # Make sure rule_sources isn't already there. It's going to be
+ # created below if needed.
+ if 'rule_sources' in rule:
+ raise GypError(
+ 'rule_sources must not exist in input, target %s rule %s' %
+ (target, rule_name))
+
+ rule_sources = []
+ source_keys = ['sources']
+ source_keys.extend(extra_sources_for_rules)
+ for source_key in source_keys:
+ for source in target_dict.get(source_key, []):
+ (source_root, source_extension) = os.path.splitext(source)
+ if source_extension.startswith('.'):
+ source_extension = source_extension[1:]
+ if source_extension == rule_extension:
+ rule_sources.append(source)
+
+ if len(rule_sources) > 0:
+ rule['rule_sources'] = rule_sources
+
+
+def ValidateRunAsInTarget(target, target_dict, build_file):
+ target_name = target_dict.get('target_name')
+ run_as = target_dict.get('run_as')
+ if not run_as:
+ return
+ if not isinstance(run_as, dict):
+ raise GypError("The 'run_as' in target %s from file %s should be a "
+ "dictionary." %
+ (target_name, build_file))
+ action = run_as.get('action')
+ if not action:
+ raise GypError("The 'run_as' in target %s from file %s must have an "
+ "'action' section." %
+ (target_name, build_file))
+ if not isinstance(action, list):
+ raise GypError("The 'action' for 'run_as' in target %s from file %s "
+ "must be a list." %
+ (target_name, build_file))
+ working_directory = run_as.get('working_directory')
+ if working_directory and not isinstance(working_directory, str):
+ raise GypError("The 'working_directory' for 'run_as' in target %s "
+ "in file %s should be a string." %
+ (target_name, build_file))
+ environment = run_as.get('environment')
+ if environment and not isinstance(environment, dict):
+ raise GypError("The 'environment' for 'run_as' in target %s "
+ "in file %s should be a dictionary." %
+ (target_name, build_file))
+
+
+def ValidateActionsInTarget(target, target_dict, build_file):
+ '''Validates the inputs to the actions in a target.'''
+ target_name = target_dict.get('target_name')
+ actions = target_dict.get('actions', [])
+ for action in actions:
+ action_name = action.get('action_name')
+ if not action_name:
+ raise GypError("Anonymous action in target %s. "
+ "An action must have an 'action_name' field." %
+ target_name)
+ inputs = action.get('inputs', None)
+ if inputs is None:
+ raise GypError('Action in target %s has no inputs.' % target_name)
+ action_command = action.get('action')
+ if action_command and not action_command[0]:
+ raise GypError("Empty action as command in target %s." % target_name)
+
+
+def TurnIntIntoStrInDict(the_dict):
+ """Given dict the_dict, recursively converts all integers into strings.
+ """
+ # Use items instead of iteritems because there's no need to try to look at
+ # reinserted keys and their associated values.
+ for k, v in the_dict.items():
+ if isinstance(v, int):
+ v = str(v)
+ the_dict[k] = v
+ elif isinstance(v, dict):
+ TurnIntIntoStrInDict(v)
+ elif isinstance(v, list):
+ TurnIntIntoStrInList(v)
+
+ if isinstance(k, int):
+ the_dict[str(k)] = v
+ del the_dict[k]
+
+
+def TurnIntIntoStrInList(the_list):
+ """Given list the_list, recursively converts all integers into strings.
+ """
+ for index in xrange(0, len(the_list)):
+ item = the_list[index]
+ if isinstance(item, int):
+ the_list[index] = str(item)
+ elif isinstance(item, dict):
+ TurnIntIntoStrInDict(item)
+ elif isinstance(item, list):
+ TurnIntIntoStrInList(item)
+
+
+def VerifyNoCollidingTargets(targets):
+ """Verify that no two targets in the same directory share the same name.
+
+ Arguments:
+ targets: A list of targets in the form 'path/to/file.gyp:target_name'.
+ """
+ # Keep a dict going from 'subdirectory:target_name' to 'foo.gyp'.
+ used = {}
+ for target in targets:
+ # Separate out 'path/to/file.gyp, 'target_name' from
+ # 'path/to/file.gyp:target_name'.
+ path, name = target.rsplit(':', 1)
+ # Separate out 'path/to', 'file.gyp' from 'path/to/file.gyp'.
+ subdir, gyp = os.path.split(path)
+ # Use '.' for the current directory '', so that the error messages make
+ # more sense.
+ if not subdir:
+ subdir = '.'
+ # Prepare a key like 'path/to:target_name'.
+ key = subdir + ':' + name
+ if key in used:
+ # Complain if this target is already used.
+ raise GypError('Duplicate target name "%s" in directory "%s" used both '
+ 'in "%s" and "%s".' % (name, subdir, gyp, used[key]))
+ used[key] = gyp
+
+
+def Load(build_files, variables, includes, depth, generator_input_info, check,
+ circular_check, parallel):
+ # Set up path_sections and non_configuration_keys with the default data plus
+ # the generator-specifc data.
+ global path_sections
+ path_sections = base_path_sections[:]
+ path_sections.extend(generator_input_info['path_sections'])
+
+ global non_configuration_keys
+ non_configuration_keys = base_non_configuration_keys[:]
+ non_configuration_keys.extend(generator_input_info['non_configuration_keys'])
+
+ # TODO(mark) handle variants if the generator doesn't want them directly.
+ generator_handles_variants = \
+ generator_input_info['generator_handles_variants']
+
+ global absolute_build_file_paths
+ absolute_build_file_paths = \
+ generator_input_info['generator_wants_absolute_build_file_paths']
+
+ global multiple_toolsets
+ multiple_toolsets = generator_input_info[
+ 'generator_supports_multiple_toolsets']
+
+ # A generator can have other lists (in addition to sources) be processed
+ # for rules.
+ extra_sources_for_rules = generator_input_info['extra_sources_for_rules']
+
+ # Load build files. This loads every target-containing build file into
+ # the |data| dictionary such that the keys to |data| are build file names,
+ # and the values are the entire build file contents after "early" or "pre"
+ # processing has been done and includes have been resolved.
+ # NOTE: data contains both "target" files (.gyp) and "includes" (.gypi), as
+ # well as meta-data (e.g. 'included_files' key). 'target_build_files' keeps
+ # track of the keys corresponding to "target" files.
+ data = {'target_build_files': set()}
+ aux_data = {}
+ for build_file in build_files:
+ # Normalize paths everywhere. This is important because paths will be
+ # used as keys to the data dict and for references between input files.
+ build_file = os.path.normpath(build_file)
+ try:
+ if parallel:
+ LoadTargetBuildFileParallel(build_file, data, aux_data,
+ variables, includes, depth, check)
+ else:
+ LoadTargetBuildFile(build_file, data, aux_data,
+ variables, includes, depth, check, True)
+ except Exception, e:
+ gyp.common.ExceptionAppend(e, 'while trying to load %s' % build_file)
+ raise
+
+ # Build a dict to access each target's subdict by qualified name.
+ targets = BuildTargetsDict(data)
+
+ # Fully qualify all dependency links.
+ QualifyDependencies(targets)
+
+ # Remove self-dependencies from targets that have 'prune_self_dependencies'
+ # set to 1.
+ RemoveSelfDependencies(targets)
+
+ # Expand dependencies specified as build_file:*.
+ ExpandWildcardDependencies(targets, data)
+
+ # Apply exclude (!) and regex (/) list filters only for dependency_sections.
+ for target_name, target_dict in targets.iteritems():
+ tmp_dict = {}
+ for key_base in dependency_sections:
+ for op in ('', '!', '/'):
+ key = key_base + op
+ if key in target_dict:
+ tmp_dict[key] = target_dict[key]
+ del target_dict[key]
+ ProcessListFiltersInDict(target_name, tmp_dict)
+ # Write the results back to |target_dict|.
+ for key in tmp_dict:
+ target_dict[key] = tmp_dict[key]
+
+ # Make sure every dependency appears at most once.
+ RemoveDuplicateDependencies(targets)
+
+ if circular_check:
+ # Make sure that any targets in a.gyp don't contain dependencies in other
+ # .gyp files that further depend on a.gyp.
+ VerifyNoGYPFileCircularDependencies(targets)
+
+ [dependency_nodes, flat_list] = BuildDependencyList(targets)
+
+ # Check that no two targets in the same directory have the same name.
+ VerifyNoCollidingTargets(flat_list)
+
+ # Handle dependent settings of various types.
+ for settings_type in ['all_dependent_settings',
+ 'direct_dependent_settings',
+ 'link_settings']:
+ DoDependentSettings(settings_type, flat_list, targets, dependency_nodes)
+
+ # Take out the dependent settings now that they've been published to all
+ # of the targets that require them.
+ for target in flat_list:
+ if settings_type in targets[target]:
+ del targets[target][settings_type]
+
+ # Make sure static libraries don't declare dependencies on other static
+ # libraries, but that linkables depend on all unlinked static libraries
+ # that they need so that their link steps will be correct.
+ gii = generator_input_info
+ if gii['generator_wants_static_library_dependencies_adjusted']:
+ AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes,
+ gii['generator_wants_sorted_dependencies'])
+
+ # Apply "post"/"late"/"target" variable expansions and condition evaluations.
+ for target in flat_list:
+ target_dict = targets[target]
+ build_file = gyp.common.BuildFile(target)
+ ProcessVariablesAndConditionsInDict(
+ target_dict, PHASE_LATE, variables, build_file)
+
+ # Move everything that can go into a "configurations" section into one.
+ for target in flat_list:
+ target_dict = targets[target]
+ SetUpConfigurations(target, target_dict)
+
+ # Apply exclude (!) and regex (/) list filters.
+ for target in flat_list:
+ target_dict = targets[target]
+ ProcessListFiltersInDict(target, target_dict)
+
+ # Apply "latelate" variable expansions and condition evaluations.
+ for target in flat_list:
+ target_dict = targets[target]
+ build_file = gyp.common.BuildFile(target)
+ ProcessVariablesAndConditionsInDict(
+ target_dict, PHASE_LATELATE, variables, build_file)
+
+ # Make sure that the rules make sense, and build up rule_sources lists as
+ # needed. Not all generators will need to use the rule_sources lists, but
+ # some may, and it seems best to build the list in a common spot.
+ # Also validate actions and run_as elements in targets.
+ for target in flat_list:
+ target_dict = targets[target]
+ build_file = gyp.common.BuildFile(target)
+ ValidateTargetType(target, target_dict)
+ # TODO(thakis): Get vpx_scale/arm/scalesystemdependent.c to be renamed to
+ # scalesystemdependent_arm_additions.c or similar.
+ if 'arm' not in variables.get('target_arch', ''):
+ ValidateSourcesInTarget(target, target_dict, build_file)
+ ValidateRulesInTarget(target, target_dict, extra_sources_for_rules)
+ ValidateRunAsInTarget(target, target_dict, build_file)
+ ValidateActionsInTarget(target, target_dict, build_file)
+
+ # Generators might not expect ints. Turn them into strs.
+ TurnIntIntoStrInDict(data)
+
+ # TODO(mark): Return |data| for now because the generator needs a list of
+ # build files that came in. In the future, maybe it should just accept
+ # a list, and not the whole data dict.
+ return [flat_list, targets, data]
diff --git a/chromium/tools/gyp/pylib/gyp/mac_tool.py b/chromium/tools/gyp/pylib/gyp/mac_tool.py
new file mode 100755
index 00000000000..14dac521d74
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/mac_tool.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility functions to perform Xcode-style build steps.
+
+These functions are executed via gyp-mac-tool when using the Makefile generator.
+"""
+
+import fcntl
+import os
+import plistlib
+import re
+import shutil
+import string
+import subprocess
+import sys
+
+
+def main(args):
+ executor = MacTool()
+ exit_code = executor.Dispatch(args)
+ if exit_code is not None:
+ sys.exit(exit_code)
+
+
+class MacTool(object):
+ """This class performs all the Mac tooling steps. The methods can either be
+ executed directly, or dispatched from an argument list."""
+
+ def Dispatch(self, args):
+ """Dispatches a string command to a method."""
+ if len(args) < 1:
+ raise Exception("Not enough arguments")
+
+ method = "Exec%s" % self._CommandifyName(args[0])
+ return getattr(self, method)(*args[1:])
+
+ def _CommandifyName(self, name_string):
+ """Transforms a tool name like copy-info-plist to CopyInfoPlist"""
+ return name_string.title().replace('-', '')
+
+ def ExecCopyBundleResource(self, source, dest):
+ """Copies a resource file to the bundle/Resources directory, performing any
+ necessary compilation on each resource."""
+ extension = os.path.splitext(source)[1].lower()
+ if os.path.isdir(source):
+ # Copy tree.
+ if os.path.exists(dest):
+ shutil.rmtree(dest)
+ shutil.copytree(source, dest)
+ elif extension == '.xib':
+ return self._CopyXIBFile(source, dest)
+ elif extension == '.strings':
+ self._CopyStringsFile(source, dest)
+ else:
+ shutil.copyfile(source, dest)
+
+ def _CopyXIBFile(self, source, dest):
+ """Compiles a XIB file with ibtool into a binary plist in the bundle."""
+ tools_dir = os.environ.get('DEVELOPER_BIN_DIR', '/usr/bin')
+ args = [os.path.join(tools_dir, 'ibtool'), '--errors', '--warnings',
+ '--notices', '--output-format', 'human-readable-text', '--compile',
+ dest, source]
+ ibtool_section_re = re.compile(r'/\*.*\*/')
+ ibtool_re = re.compile(r'.*note:.*is clipping its content')
+ ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE)
+ current_section_header = None
+ for line in ibtoolout.stdout:
+ if ibtool_section_re.match(line):
+ current_section_header = line
+ elif not ibtool_re.match(line):
+ if current_section_header:
+ sys.stdout.write(current_section_header)
+ current_section_header = None
+ sys.stdout.write(line)
+ return ibtoolout.returncode
+
+ def _CopyStringsFile(self, source, dest):
+ """Copies a .strings file using iconv to reconvert the input into UTF-16."""
+ input_code = self._DetectInputEncoding(source) or "UTF-8"
+
+ # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call
+ # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints
+ # CFPropertyListCreateFromXMLData(): Old-style plist parser: missing
+ # semicolon in dictionary.
+ # on invalid files. Do the same kind of validation.
+ import CoreFoundation
+ s = open(source).read()
+ d = CoreFoundation.CFDataCreate(None, s, len(s))
+ _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None)
+ if error:
+ return
+
+ fp = open(dest, 'w')
+ args = ['/usr/bin/iconv', '--from-code', input_code, '--to-code',
+ 'UTF-16', source]
+ subprocess.call(args, stdout=fp)
+ fp.close()
+
+ def _DetectInputEncoding(self, file_name):
+ """Reads the first few bytes from file_name and tries to guess the text
+ encoding. Returns None as a guess if it can't detect it."""
+ fp = open(file_name, 'rb')
+ try:
+ header = fp.read(3)
+ except e:
+ fp.close()
+ return None
+ fp.close()
+ if header.startswith("\xFE\xFF"):
+ return "UTF-16BE"
+ elif header.startswith("\xFF\xFE"):
+ return "UTF-16LE"
+ elif header.startswith("\xEF\xBB\xBF"):
+ return "UTF-8"
+ else:
+ return None
+
+ def ExecCopyInfoPlist(self, source, dest):
+ """Copies the |source| Info.plist to the destination directory |dest|."""
+ # Read the source Info.plist into memory.
+ fd = open(source, 'r')
+ lines = fd.read()
+ fd.close()
+
+ # Go through all the environment variables and replace them as variables in
+ # the file.
+ for key in os.environ:
+ if key.startswith('_'):
+ continue
+ evar = '${%s}' % key
+ lines = string.replace(lines, evar, os.environ[key])
+
+ # Remove any keys with values that haven't been replaced.
+ lines = lines.split('\n')
+ for i in range(len(lines)):
+ if lines[i].strip().startswith("<string>${"):
+ lines[i] = None
+ lines[i - 1] = None
+ lines = '\n'.join(filter(lambda x: x is not None, lines))
+
+ # Write out the file with variables replaced.
+ fd = open(dest, 'w')
+ fd.write(lines)
+ fd.close()
+
+ # Now write out PkgInfo file now that the Info.plist file has been
+ # "compiled".
+ self._WritePkgInfo(dest)
+
+ def _WritePkgInfo(self, info_plist):
+ """This writes the PkgInfo file from the data stored in Info.plist."""
+ plist = plistlib.readPlist(info_plist)
+ if not plist:
+ return
+
+ # Only create PkgInfo for executable types.
+ package_type = plist['CFBundlePackageType']
+ if package_type != 'APPL':
+ return
+
+ # The format of PkgInfo is eight characters, representing the bundle type
+ # and bundle signature, each four characters. If that is missing, four
+ # '?' characters are used instead.
+ signature_code = plist.get('CFBundleSignature', '????')
+ if len(signature_code) != 4: # Wrong length resets everything, too.
+ signature_code = '?' * 4
+
+ dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo')
+ fp = open(dest, 'w')
+ fp.write('%s%s' % (package_type, signature_code))
+ fp.close()
+
+ def ExecFlock(self, lockfile, *cmd_list):
+ """Emulates the most basic behavior of Linux's flock(1)."""
+ # Rely on exception handling to report errors.
+ fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666)
+ fcntl.flock(fd, fcntl.LOCK_EX)
+ return subprocess.call(cmd_list)
+
+ def ExecFilterLibtool(self, *cmd_list):
+ """Calls libtool and filters out 'libtool: file: foo.o has no symbols'."""
+ libtool_re = re.compile(r'^libtool: file: .* has no symbols$')
+ libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE)
+ _, err = libtoolout.communicate()
+ for line in err.splitlines():
+ if not libtool_re.match(line):
+ print >>sys.stderr, line
+ return libtoolout.returncode
+
+ def ExecPackageFramework(self, framework, version):
+ """Takes a path to Something.framework and the Current version of that and
+ sets up all the symlinks."""
+ # Find the name of the binary based on the part before the ".framework".
+ binary = os.path.basename(framework).split('.')[0]
+
+ CURRENT = 'Current'
+ RESOURCES = 'Resources'
+ VERSIONS = 'Versions'
+
+ if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)):
+ # Binary-less frameworks don't seem to contain symlinks (see e.g.
+ # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle).
+ return
+
+ # Move into the framework directory to set the symlinks correctly.
+ pwd = os.getcwd()
+ os.chdir(framework)
+
+ # Set up the Current version.
+ self._Relink(version, os.path.join(VERSIONS, CURRENT))
+
+ # Set up the root symlinks.
+ self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary)
+ self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES)
+
+ # Back to where we were before!
+ os.chdir(pwd)
+
+ def _Relink(self, dest, link):
+ """Creates a symlink to |dest| named |link|. If |link| already exists,
+ it is overwritten."""
+ if os.path.lexists(link):
+ os.remove(link)
+ os.symlink(dest, link)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/gyp/pylib/gyp/msvs_emulation.py b/chromium/tools/gyp/pylib/gyp/msvs_emulation.py
new file mode 100644
index 00000000000..0e16ed6f3a5
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/msvs_emulation.py
@@ -0,0 +1,846 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This module helps emulate Visual Studio 2008 behavior on top of other
+build systems, primarily ninja.
+"""
+
+import os
+import re
+import subprocess
+import sys
+
+import gyp.MSVSVersion
+
+windows_quoter_regex = re.compile(r'(\\*)"')
+
+def QuoteForRspFile(arg):
+ """Quote a command line argument so that it appears as one argument when
+ processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for
+ Windows programs)."""
+ # See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment
+ # threads. This is actually the quoting rules for CommandLineToArgvW, not
+ # for the shell, because the shell doesn't do anything in Windows. This
+ # works more or less because most programs (including the compiler, etc.)
+ # use that function to handle command line arguments.
+
+ # For a literal quote, CommandLineToArgvW requires 2n+1 backslashes
+ # preceding it, and results in n backslashes + the quote. So we substitute
+ # in 2* what we match, +1 more, plus the quote.
+ arg = windows_quoter_regex.sub(lambda mo: 2 * mo.group(1) + '\\"', arg)
+
+ # %'s also need to be doubled otherwise they're interpreted as batch
+ # positional arguments. Also make sure to escape the % so that they're
+ # passed literally through escaping so they can be singled to just the
+ # original %. Otherwise, trying to pass the literal representation that
+ # looks like an environment variable to the shell (e.g. %PATH%) would fail.
+ arg = arg.replace('%', '%%')
+
+ # These commands are used in rsp files, so no escaping for the shell (via ^)
+ # is necessary.
+
+ # Finally, wrap the whole thing in quotes so that the above quote rule
+ # applies and whitespace isn't a word break.
+ return '"' + arg + '"'
+
+
+def EncodeRspFileList(args):
+ """Process a list of arguments using QuoteCmdExeArgument."""
+ # Note that the first argument is assumed to be the command. Don't add
+ # quotes around it because then built-ins like 'echo', etc. won't work.
+ # Take care to normpath only the path in the case of 'call ../x.bat' because
+ # otherwise the whole thing is incorrectly interpreted as a path and not
+ # normalized correctly.
+ if not args: return ''
+ if args[0].startswith('call '):
+ call, program = args[0].split(' ', 1)
+ program = call + ' ' + os.path.normpath(program)
+ else:
+ program = os.path.normpath(args[0])
+ return program + ' ' + ' '.join(QuoteForRspFile(arg) for arg in args[1:])
+
+
+def _GenericRetrieve(root, default, path):
+ """Given a list of dictionary keys |path| and a tree of dicts |root|, find
+ value at path, or return |default| if any of the path doesn't exist."""
+ if not root:
+ return default
+ if not path:
+ return root
+ return _GenericRetrieve(root.get(path[0]), default, path[1:])
+
+
+def _AddPrefix(element, prefix):
+ """Add |prefix| to |element| or each subelement if element is iterable."""
+ if element is None:
+ return element
+ # Note, not Iterable because we don't want to handle strings like that.
+ if isinstance(element, list) or isinstance(element, tuple):
+ return [prefix + e for e in element]
+ else:
+ return prefix + element
+
+
+def _DoRemapping(element, map):
+ """If |element| then remap it through |map|. If |element| is iterable then
+ each item will be remapped. Any elements not found will be removed."""
+ if map is not None and element is not None:
+ if not callable(map):
+ map = map.get # Assume it's a dict, otherwise a callable to do the remap.
+ if isinstance(element, list) or isinstance(element, tuple):
+ element = filter(None, [map(elem) for elem in element])
+ else:
+ element = map(element)
+ return element
+
+
+def _AppendOrReturn(append, element):
+ """If |append| is None, simply return |element|. If |append| is not None,
+ then add |element| to it, adding each item in |element| if it's a list or
+ tuple."""
+ if append is not None and element is not None:
+ if isinstance(element, list) or isinstance(element, tuple):
+ append.extend(element)
+ else:
+ append.append(element)
+ else:
+ return element
+
+
+def _FindDirectXInstallation():
+ """Try to find an installation location for the DirectX SDK. Check for the
+ standard environment variable, and if that doesn't exist, try to find
+ via the registry. May return None if not found in either location."""
+ # Return previously calculated value, if there is one
+ if hasattr(_FindDirectXInstallation, 'dxsdk_dir'):
+ return _FindDirectXInstallation.dxsdk_dir
+
+ dxsdk_dir = os.environ.get('DXSDK_DIR')
+ if not dxsdk_dir:
+ # Setup params to pass to and attempt to launch reg.exe.
+ cmd = ['reg.exe', 'query', r'HKLM\Software\Microsoft\DirectX', '/s']
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ for line in p.communicate()[0].splitlines():
+ if 'InstallPath' in line:
+ dxsdk_dir = line.split(' ')[3] + "\\"
+
+ # Cache return value
+ _FindDirectXInstallation.dxsdk_dir = dxsdk_dir
+ return dxsdk_dir
+
+
+class MsvsSettings(object):
+ """A class that understands the gyp 'msvs_...' values (especially the
+ msvs_settings field). They largely correpond to the VS2008 IDE DOM. This
+ class helps map those settings to command line options."""
+
+ def __init__(self, spec, generator_flags):
+ self.spec = spec
+ self.vs_version = GetVSVersion(generator_flags)
+ self.dxsdk_dir = _FindDirectXInstallation()
+
+ # Try to find an installation location for the Windows DDK by checking
+ # the WDK_DIR environment variable, may be None.
+ self.wdk_dir = os.environ.get('WDK_DIR')
+
+ supported_fields = [
+ ('msvs_configuration_attributes', dict),
+ ('msvs_settings', dict),
+ ('msvs_system_include_dirs', list),
+ ('msvs_disabled_warnings', list),
+ ('msvs_precompiled_header', str),
+ ('msvs_precompiled_source', str),
+ ('msvs_configuration_platform', str),
+ ('msvs_target_platform', str),
+ ]
+ configs = spec['configurations']
+ for field, default in supported_fields:
+ setattr(self, field, {})
+ for configname, config in configs.iteritems():
+ getattr(self, field)[configname] = config.get(field, default())
+
+ self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])
+
+ def GetVSMacroEnv(self, base_to_build=None, config=None):
+ """Get a dict of variables mapping internal VS macro names to their gyp
+ equivalents."""
+ target_platform = 'Win32' if self.GetArch(config) == 'x86' else 'x64'
+ target_name = self.spec.get('product_prefix', '') + \
+ self.spec.get('product_name', self.spec['target_name'])
+ target_dir = base_to_build + '\\' if base_to_build else ''
+ replacements = {
+ '$(OutDir)\\': target_dir,
+ '$(TargetDir)\\': target_dir,
+ '$(IntDir)': '$!INTERMEDIATE_DIR',
+ '$(InputPath)': '${source}',
+ '$(InputName)': '${root}',
+ '$(ProjectName)': self.spec['target_name'],
+ '$(TargetName)': target_name,
+ '$(PlatformName)': target_platform,
+ '$(ProjectDir)\\': '',
+ }
+ # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when
+ # Visual Studio is actually installed.
+ if self.vs_version.Path():
+ replacements['$(VSInstallDir)'] = self.vs_version.Path()
+ replacements['$(VCInstallDir)'] = os.path.join(self.vs_version.Path(),
+ 'VC') + '\\'
+ # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be
+ # set. This happens when the SDK is sync'd via src-internal, rather than
+ # by typical end-user installation of the SDK. If it's not set, we don't
+ # want to leave the unexpanded variable in the path, so simply strip it.
+ replacements['$(DXSDK_DIR)'] = self.dxsdk_dir if self.dxsdk_dir else ''
+ replacements['$(WDK_DIR)'] = self.wdk_dir if self.wdk_dir else ''
+ return replacements
+
+ def ConvertVSMacros(self, s, base_to_build=None, config=None):
+ """Convert from VS macro names to something equivalent."""
+ env = self.GetVSMacroEnv(base_to_build, config=config)
+ return ExpandMacros(s, env)
+
+ def AdjustLibraries(self, libraries):
+ """Strip -l from library if it's specified with that."""
+ return [lib[2:] if lib.startswith('-l') else lib for lib in libraries]
+
+ def _GetAndMunge(self, field, path, default, prefix, append, map):
+ """Retrieve a value from |field| at |path| or return |default|. If
+ |append| is specified, and the item is found, it will be appended to that
+ object instead of returned. If |map| is specified, results will be
+ remapped through |map| before being returned or appended."""
+ result = _GenericRetrieve(field, default, path)
+ result = _DoRemapping(result, map)
+ result = _AddPrefix(result, prefix)
+ return _AppendOrReturn(append, result)
+
+ class _GetWrapper(object):
+ def __init__(self, parent, field, base_path, append=None):
+ self.parent = parent
+ self.field = field
+ self.base_path = [base_path]
+ self.append = append
+ def __call__(self, name, map=None, prefix='', default=None):
+ return self.parent._GetAndMunge(self.field, self.base_path + [name],
+ default=default, prefix=prefix, append=self.append, map=map)
+
+ def GetArch(self, config):
+ """Get architecture based on msvs_configuration_platform and
+ msvs_target_platform. Returns either 'x86' or 'x64'."""
+ configuration_platform = self.msvs_configuration_platform.get(config, '')
+ platform = self.msvs_target_platform.get(config, '')
+ if not platform: # If no specific override, use the configuration's.
+ platform = configuration_platform
+ # Map from platform to architecture.
+ return {'Win32': 'x86', 'x64': 'x64'}.get(platform, 'x86')
+
+ def _TargetConfig(self, config):
+ """Returns the target-specific configuration."""
+ # There's two levels of architecture/platform specification in VS. The
+ # first level is globally for the configuration (this is what we consider
+ # "the" config at the gyp level, which will be something like 'Debug' or
+ # 'Release_x64'), and a second target-specific configuration, which is an
+ # override for the global one. |config| is remapped here to take into
+ # account the local target-specific overrides to the global configuration.
+ arch = self.GetArch(config)
+ if arch == 'x64' and not config.endswith('_x64'):
+ config += '_x64'
+ if arch == 'x86' and config.endswith('_x64'):
+ config = config.rsplit('_', 1)[0]
+ return config
+
+ def _Setting(self, path, config,
+ default=None, prefix='', append=None, map=None):
+ """_GetAndMunge for msvs_settings."""
+ return self._GetAndMunge(
+ self.msvs_settings[config], path, default, prefix, append, map)
+
+ def _ConfigAttrib(self, path, config,
+ default=None, prefix='', append=None, map=None):
+ """_GetAndMunge for msvs_configuration_attributes."""
+ return self._GetAndMunge(
+ self.msvs_configuration_attributes[config],
+ path, default, prefix, append, map)
+
+ def AdjustIncludeDirs(self, include_dirs, config):
+ """Updates include_dirs to expand VS specific paths, and adds the system
+ include dirs used for platform SDK and similar."""
+ config = self._TargetConfig(config)
+ includes = include_dirs + self.msvs_system_include_dirs[config]
+ includes.extend(self._Setting(
+ ('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[]))
+ return [self.ConvertVSMacros(p, config=config) for p in includes]
+
+ def GetComputedDefines(self, config):
+ """Returns the set of defines that are injected to the defines list based
+ on other VS settings."""
+ config = self._TargetConfig(config)
+ defines = []
+ if self._ConfigAttrib(['CharacterSet'], config) == '1':
+ defines.extend(('_UNICODE', 'UNICODE'))
+ if self._ConfigAttrib(['CharacterSet'], config) == '2':
+ defines.append('_MBCS')
+ defines.extend(self._Setting(
+ ('VCCLCompilerTool', 'PreprocessorDefinitions'), config, default=[]))
+ return defines
+
+ def GetCompilerPdbName(self, config, expand_special):
+ """Get the pdb file name that should be used for compiler invocations, or
+ None if there's no explicit name specified."""
+ config = self._TargetConfig(config)
+ pdbname = self._Setting(
+ ('VCCLCompilerTool', 'ProgramDataBaseFileName'), config)
+ if pdbname:
+ pdbname = expand_special(self.ConvertVSMacros(pdbname))
+ return pdbname
+
+ def GetMapFileName(self, config, expand_special):
+ """Gets the explicitly overriden map file name for a target or returns None
+ if it's not set."""
+ config = self._TargetConfig(config)
+ map_file = self._Setting(('VCLinkerTool', 'MapFileName'), config)
+ if map_file:
+ map_file = expand_special(self.ConvertVSMacros(map_file, config=config))
+ return map_file
+
+ def GetOutputName(self, config, expand_special):
+ """Gets the explicitly overridden output name for a target or returns None
+ if it's not overridden."""
+ config = self._TargetConfig(config)
+ type = self.spec['type']
+ root = 'VCLibrarianTool' if type == 'static_library' else 'VCLinkerTool'
+ # TODO(scottmg): Handle OutputDirectory without OutputFile.
+ output_file = self._Setting((root, 'OutputFile'), config)
+ if output_file:
+ output_file = expand_special(self.ConvertVSMacros(
+ output_file, config=config))
+ return output_file
+
+ def GetPDBName(self, config, expand_special):
+ """Gets the explicitly overridden pdb name for a target or returns None
+ if it's not overridden."""
+ config = self._TargetConfig(config)
+ output_file = self._Setting(('VCLinkerTool', 'ProgramDatabaseFile'), config)
+ if output_file:
+ output_file = expand_special(self.ConvertVSMacros(
+ output_file, config=config))
+ return output_file
+
+ def GetCflags(self, config):
+ """Returns the flags that need to be added to .c and .cc compilations."""
+ config = self._TargetConfig(config)
+ cflags = []
+ cflags.extend(['/wd' + w for w in self.msvs_disabled_warnings[config]])
+ cl = self._GetWrapper(self, self.msvs_settings[config],
+ 'VCCLCompilerTool', append=cflags)
+ cl('Optimization',
+ map={'0': 'd', '1': '1', '2': '2', '3': 'x'}, prefix='/O')
+ cl('InlineFunctionExpansion', prefix='/Ob')
+ cl('StringPooling', map={'true': '/GF'})
+ cl('EnableFiberSafeOptimizations', map={'true': '/GT'})
+ cl('OmitFramePointers', map={'false': '-', 'true': ''}, prefix='/Oy')
+ cl('EnableIntrinsicFunctions', map={'false': '-', 'true': ''}, prefix='/Oi')
+ cl('FavorSizeOrSpeed', map={'1': 't', '2': 's'}, prefix='/O')
+ cl('WholeProgramOptimization', map={'true': '/GL'})
+ cl('WarningLevel', prefix='/W')
+ cl('WarnAsError', map={'true': '/WX'})
+ cl('DebugInformationFormat',
+ map={'1': '7', '3': 'i', '4': 'I'}, prefix='/Z')
+ cl('RuntimeTypeInfo', map={'true': '/GR', 'false': '/GR-'})
+ cl('EnableFunctionLevelLinking', map={'true': '/Gy', 'false': '/Gy-'})
+ cl('MinimalRebuild', map={'true': '/Gm'})
+ cl('BufferSecurityCheck', map={'true': '/GS', 'false': '/GS-'})
+ cl('BasicRuntimeChecks', map={'1': 's', '2': 'u', '3': '1'}, prefix='/RTC')
+ cl('RuntimeLibrary',
+ map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M')
+ cl('ExceptionHandling', map={'1': 'sc','2': 'a'}, prefix='/EH')
+ cl('DefaultCharIsUnsigned', map={'true': '/J'})
+ cl('TreatWChar_tAsBuiltInType',
+ map={'false': '-', 'true': ''}, prefix='/Zc:wchar_t')
+ cl('EnablePREfast', map={'true': '/analyze'})
+ cl('AdditionalOptions', prefix='')
+ cflags.extend(['/FI' + f for f in self._Setting(
+ ('VCCLCompilerTool', 'ForcedIncludeFiles'), config, default=[])])
+ # ninja handles parallelism by itself, don't have the compiler do it too.
+ cflags = filter(lambda x: not x.startswith('/MP'), cflags)
+ return cflags
+
+ def GetPrecompiledHeader(self, config, gyp_to_build_path):
+ """Returns an object that handles the generation of precompiled header
+ build steps."""
+ config = self._TargetConfig(config)
+ return _PchHelper(self, config, gyp_to_build_path)
+
+ def _GetPchFlags(self, config, extension):
+ """Get the flags to be added to the cflags for precompiled header support.
+ """
+ config = self._TargetConfig(config)
+ # The PCH is only built once by a particular source file. Usage of PCH must
+ # only be for the same language (i.e. C vs. C++), so only include the pch
+ # flags when the language matches.
+ if self.msvs_precompiled_header[config]:
+ source_ext = os.path.splitext(self.msvs_precompiled_source[config])[1]
+ if _LanguageMatchesForPch(source_ext, extension):
+ pch = os.path.split(self.msvs_precompiled_header[config])[1]
+ return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pch + '.pch']
+ return []
+
+ def GetCflagsC(self, config):
+ """Returns the flags that need to be added to .c compilations."""
+ config = self._TargetConfig(config)
+ return self._GetPchFlags(config, '.c')
+
+ def GetCflagsCC(self, config):
+ """Returns the flags that need to be added to .cc compilations."""
+ config = self._TargetConfig(config)
+ return ['/TP'] + self._GetPchFlags(config, '.cc')
+
+ def _GetAdditionalLibraryDirectories(self, root, config, gyp_to_build_path):
+ """Get and normalize the list of paths in AdditionalLibraryDirectories
+ setting."""
+ config = self._TargetConfig(config)
+ libpaths = self._Setting((root, 'AdditionalLibraryDirectories'),
+ config, default=[])
+ libpaths = [os.path.normpath(
+ gyp_to_build_path(self.ConvertVSMacros(p, config=config)))
+ for p in libpaths]
+ return ['/LIBPATH:"' + p + '"' for p in libpaths]
+
+ def GetLibFlags(self, config, gyp_to_build_path):
+ """Returns the flags that need to be added to lib commands."""
+ config = self._TargetConfig(config)
+ libflags = []
+ lib = self._GetWrapper(self, self.msvs_settings[config],
+ 'VCLibrarianTool', append=libflags)
+ libflags.extend(self._GetAdditionalLibraryDirectories(
+ 'VCLibrarianTool', config, gyp_to_build_path))
+ lib('LinkTimeCodeGeneration', map={'true': '/LTCG'})
+ lib('AdditionalOptions')
+ return libflags
+
+ def GetDefFile(self, gyp_to_build_path):
+ """Returns the .def file from sources, if any. Otherwise returns None."""
+ spec = self.spec
+ if spec['type'] in ('shared_library', 'loadable_module', 'executable'):
+ def_files = [s for s in spec.get('sources', []) if s.endswith('.def')]
+ if len(def_files) == 1:
+ return gyp_to_build_path(def_files[0])
+ elif len(def_files) > 1:
+ raise Exception("Multiple .def files")
+ return None
+
+ def _GetDefFileAsLdflags(self, ldflags, gyp_to_build_path):
+ """.def files get implicitly converted to a ModuleDefinitionFile for the
+ linker in the VS generator. Emulate that behaviour here."""
+ def_file = self.GetDefFile(gyp_to_build_path)
+ if def_file:
+ ldflags.append('/DEF:"%s"' % def_file)
+
+ def GetLdflags(self, config, gyp_to_build_path, expand_special,
+ manifest_base_name, is_executable):
+ """Returns the flags that need to be added to link commands, and the
+ manifest files."""
+ config = self._TargetConfig(config)
+ ldflags = []
+ ld = self._GetWrapper(self, self.msvs_settings[config],
+ 'VCLinkerTool', append=ldflags)
+ self._GetDefFileAsLdflags(ldflags, gyp_to_build_path)
+ ld('GenerateDebugInformation', map={'true': '/DEBUG'})
+ ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:')
+ ldflags.extend(self._GetAdditionalLibraryDirectories(
+ 'VCLinkerTool', config, gyp_to_build_path))
+ ld('DelayLoadDLLs', prefix='/DELAYLOAD:')
+ out = self.GetOutputName(config, expand_special)
+ if out:
+ ldflags.append('/OUT:' + out)
+ pdb = self.GetPDBName(config, expand_special)
+ if pdb:
+ ldflags.append('/PDB:' + pdb)
+ map_file = self.GetMapFileName(config, expand_special)
+ ld('GenerateMapFile', map={'true': '/MAP:' + map_file if map_file
+ else '/MAP'})
+ ld('MapExports', map={'true': '/MAPINFO:EXPORTS'})
+ ld('AdditionalOptions', prefix='')
+ ld('SubSystem', map={'1': 'CONSOLE', '2': 'WINDOWS'}, prefix='/SUBSYSTEM:')
+ ld('TerminalServerAware', map={'1': ':NO', '2': ''}, prefix='/TSAWARE')
+ ld('LinkIncremental', map={'1': ':NO', '2': ''}, prefix='/INCREMENTAL')
+ ld('FixedBaseAddress', map={'1': ':NO', '2': ''}, prefix='/FIXED')
+ ld('RandomizedBaseAddress',
+ map={'1': ':NO', '2': ''}, prefix='/DYNAMICBASE')
+ ld('DataExecutionPrevention',
+ map={'1': ':NO', '2': ''}, prefix='/NXCOMPAT')
+ ld('OptimizeReferences', map={'1': 'NOREF', '2': 'REF'}, prefix='/OPT:')
+ ld('EnableCOMDATFolding', map={'1': 'NOICF', '2': 'ICF'}, prefix='/OPT:')
+ ld('LinkTimeCodeGeneration', map={'1': '/LTCG'})
+ ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:')
+ ld('ResourceOnlyDLL', map={'true': '/NOENTRY'})
+ ld('EntryPointSymbol', prefix='/ENTRY:')
+ ld('Profile', map={'true': '/PROFILE'})
+ ld('LargeAddressAware',
+ map={'1': ':NO', '2': ''}, prefix='/LARGEADDRESSAWARE')
+ # TODO(scottmg): This should sort of be somewhere else (not really a flag).
+ ld('AdditionalDependencies', prefix='')
+
+ # If the base address is not specifically controlled, DYNAMICBASE should
+ # be on by default.
+ base_flags = filter(lambda x: 'DYNAMICBASE' in x or x == '/FIXED',
+ ldflags)
+ if not base_flags:
+ ldflags.append('/DYNAMICBASE')
+
+ # If the NXCOMPAT flag has not been specified, default to on. Despite the
+ # documentation that says this only defaults to on when the subsystem is
+ # Vista or greater (which applies to the linker), the IDE defaults it on
+ # unless it's explicitly off.
+ if not filter(lambda x: 'NXCOMPAT' in x, ldflags):
+ ldflags.append('/NXCOMPAT')
+
+ have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags)
+ manifest_flags, intermediate_manifest_file = self._GetLdManifestFlags(
+ config, manifest_base_name, is_executable and not have_def_file)
+ ldflags.extend(manifest_flags)
+ manifest_files = self._GetAdditionalManifestFiles(config, gyp_to_build_path)
+ manifest_files.append(intermediate_manifest_file)
+
+ return ldflags, manifest_files
+
+ def _GetLdManifestFlags(self, config, name, allow_isolation):
+ """Returns the set of flags that need to be added to the link to generate
+ a default manifest, as well as the name of the generated file."""
+ # The manifest is generated by default.
+ output_name = name + '.intermediate.manifest'
+ flags = [
+ '/MANIFEST',
+ '/ManifestFile:' + output_name,
+ ]
+
+ config = self._TargetConfig(config)
+ enable_uac = self._Setting(('VCLinkerTool', 'EnableUAC'), config,
+ default='true')
+ if enable_uac == 'true':
+ execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'),
+ config, default='0')
+ execution_level_map = {
+ '0': 'asInvoker',
+ '1': 'highestAvailable',
+ '2': 'requireAdministrator'
+ }
+
+ ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config,
+ default='false')
+ flags.append('''/MANIFESTUAC:"level='%s' uiAccess='%s'"''' %
+ (execution_level_map[execution_level], ui_access))
+ else:
+ flags.append('/MANIFESTUAC:NO')
+
+ if allow_isolation:
+ flags.append('/ALLOWISOLATION')
+ return flags, output_name
+
+ def _GetAdditionalManifestFiles(self, config, gyp_to_build_path):
+ """Gets additional manifest files that are added to the default one
+ generated by the linker."""
+ files = self._Setting(('VCManifestTool', 'AdditionalManifestFiles'), config,
+ default=[])
+ if isinstance(files, str):
+ files = files.split(';')
+ return [os.path.normpath(
+ gyp_to_build_path(self.ConvertVSMacros(f, config=config)))
+ for f in files]
+
+ def IsUseLibraryDependencyInputs(self, config):
+ """Returns whether the target should be linked via Use Library Dependency
+ Inputs (using component .objs of a given .lib)."""
+ config = self._TargetConfig(config)
+ uldi = self._Setting(('VCLinkerTool', 'UseLibraryDependencyInputs'), config)
+ return uldi == 'true'
+
+ def IsEmbedManifest(self, config):
+ """Returns whether manifest should be linked into binary."""
+ config = self._TargetConfig(config)
+ embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config)
+ return embed == 'true'
+
+ def IsLinkIncremental(self, config):
+ """Returns whether the target should be linked incrementally."""
+ config = self._TargetConfig(config)
+ link_inc = self._Setting(('VCLinkerTool', 'LinkIncremental'), config)
+ return link_inc != '1'
+
+ def GetRcflags(self, config, gyp_to_ninja_path):
+ """Returns the flags that need to be added to invocations of the resource
+ compiler."""
+ config = self._TargetConfig(config)
+ rcflags = []
+ rc = self._GetWrapper(self, self.msvs_settings[config],
+ 'VCResourceCompilerTool', append=rcflags)
+ rc('AdditionalIncludeDirectories', map=gyp_to_ninja_path, prefix='/I')
+ rcflags.append('/I' + gyp_to_ninja_path('.'))
+ rc('PreprocessorDefinitions', prefix='/d')
+ # /l arg must be in hex without leading '0x'
+ rc('Culture', prefix='/l', map=lambda x: hex(int(x))[2:])
+ return rcflags
+
+ def BuildCygwinBashCommandLine(self, args, path_to_base):
+ """Build a command line that runs args via cygwin bash. We assume that all
+ incoming paths are in Windows normpath'd form, so they need to be
+ converted to posix style for the part of the command line that's passed to
+ bash. We also have to do some Visual Studio macro emulation here because
+ various rules use magic VS names for things. Also note that rules that
+ contain ninja variables cannot be fixed here (for example ${source}), so
+ the outer generator needs to make sure that the paths that are written out
+ are in posix style, if the command line will be used here."""
+ cygwin_dir = os.path.normpath(
+ os.path.join(path_to_base, self.msvs_cygwin_dirs[0]))
+ cd = ('cd %s' % path_to_base).replace('\\', '/')
+ args = [a.replace('\\', '/').replace('"', '\\"') for a in args]
+ args = ["'%s'" % a.replace("'", "'\\''") for a in args]
+ bash_cmd = ' '.join(args)
+ cmd = (
+ 'call "%s\\setup_env.bat" && set CYGWIN=nontsec && ' % cygwin_dir +
+ 'bash -c "%s ; %s"' % (cd, bash_cmd))
+ return cmd
+
+ def IsRuleRunUnderCygwin(self, rule):
+ """Determine if an action should be run under cygwin. If the variable is
+ unset, or set to 1 we use cygwin."""
+ return int(rule.get('msvs_cygwin_shell',
+ self.spec.get('msvs_cygwin_shell', 1))) != 0
+
+ def _HasExplicitRuleForExtension(self, spec, extension):
+ """Determine if there's an explicit rule for a particular extension."""
+ for rule in spec.get('rules', []):
+ if rule['extension'] == extension:
+ return True
+ return False
+
+ def HasExplicitIdlRules(self, spec):
+ """Determine if there's an explicit rule for idl files. When there isn't we
+ need to generate implicit rules to build MIDL .idl files."""
+ return self._HasExplicitRuleForExtension(spec, 'idl')
+
+ def HasExplicitAsmRules(self, spec):
+ """Determine if there's an explicit rule for asm files. When there isn't we
+ need to generate implicit rules to assemble .asm files."""
+ return self._HasExplicitRuleForExtension(spec, 'asm')
+
+ def GetIdlBuildData(self, source, config):
+ """Determine the implicit outputs for an idl file. Returns output
+ directory, outputs, and variables and flags that are required."""
+ config = self._TargetConfig(config)
+ midl_get = self._GetWrapper(self, self.msvs_settings[config], 'VCMIDLTool')
+ def midl(name, default=None):
+ return self.ConvertVSMacros(midl_get(name, default=default),
+ config=config)
+ tlb = midl('TypeLibraryName', default='${root}.tlb')
+ header = midl('HeaderFileName', default='${root}.h')
+ dlldata = midl('DLLDataFileName', default='dlldata.c')
+ iid = midl('InterfaceIdentifierFileName', default='${root}_i.c')
+ proxy = midl('ProxyFileName', default='${root}_p.c')
+ # Note that .tlb is not included in the outputs as it is not always
+ # generated depending on the content of the input idl file.
+ outdir = midl('OutputDirectory', default='')
+ output = [header, dlldata, iid, proxy]
+ variables = [('tlb', tlb),
+ ('h', header),
+ ('dlldata', dlldata),
+ ('iid', iid),
+ ('proxy', proxy)]
+ # TODO(scottmg): Are there configuration settings to set these flags?
+ target_platform = 'win32' if self.GetArch(config) == 'x86' else 'x64'
+ flags = ['/char', 'signed', '/env', target_platform, '/Oicf']
+ return outdir, output, variables, flags
+
+
+def _LanguageMatchesForPch(source_ext, pch_source_ext):
+ c_exts = ('.c',)
+ cc_exts = ('.cc', '.cxx', '.cpp')
+ return ((source_ext in c_exts and pch_source_ext in c_exts) or
+ (source_ext in cc_exts and pch_source_ext in cc_exts))
+
+
+class PrecompiledHeader(object):
+ """Helper to generate dependencies and build rules to handle generation of
+ precompiled headers. Interface matches the GCH handler in xcode_emulation.py.
+ """
+ def __init__(
+ self, settings, config, gyp_to_build_path, gyp_to_unique_output, obj_ext):
+ self.settings = settings
+ self.config = config
+ pch_source = self.settings.msvs_precompiled_source[self.config]
+ self.pch_source = gyp_to_build_path(pch_source)
+ filename, _ = os.path.splitext(pch_source)
+ self.output_obj = gyp_to_unique_output(filename + obj_ext).lower()
+
+ def _PchHeader(self):
+ """Get the header that will appear in an #include line for all source
+ files."""
+ return os.path.split(self.settings.msvs_precompiled_header[self.config])[1]
+
+ def GetObjDependencies(self, sources, objs, arch):
+ """Given a list of sources files and the corresponding object files,
+ returns a list of the pch files that should be depended upon. The
+ additional wrapping in the return value is for interface compatability
+ with make.py on Mac, and xcode_emulation.py."""
+ assert arch is None
+ if not self._PchHeader():
+ return []
+ pch_ext = os.path.splitext(self.pch_source)[1]
+ for source in sources:
+ if _LanguageMatchesForPch(os.path.splitext(source)[1], pch_ext):
+ return [(None, None, self.output_obj)]
+ return []
+
+ def GetPchBuildCommands(self, arch):
+ """Not used on Windows as there are no additional build steps required
+ (instead, existing steps are modified in GetFlagsModifications below)."""
+ return []
+
+ def GetFlagsModifications(self, input, output, implicit, command,
+ cflags_c, cflags_cc, expand_special):
+ """Get the modified cflags and implicit dependencies that should be used
+ for the pch compilation step."""
+ if input == self.pch_source:
+ pch_output = ['/Yc' + self._PchHeader()]
+ if command == 'cxx':
+ return ([('cflags_cc', map(expand_special, cflags_cc + pch_output))],
+ self.output_obj, [])
+ elif command == 'cc':
+ return ([('cflags_c', map(expand_special, cflags_c + pch_output))],
+ self.output_obj, [])
+ return [], output, implicit
+
+
+vs_version = None
+def GetVSVersion(generator_flags):
+ global vs_version
+ if not vs_version:
+ vs_version = gyp.MSVSVersion.SelectVisualStudioVersion(
+ generator_flags.get('msvs_version', 'auto'))
+ return vs_version
+
+def _GetVsvarsSetupArgs(generator_flags, arch):
+ vs = GetVSVersion(generator_flags)
+ return vs.SetupScript()
+
+def ExpandMacros(string, expansions):
+ """Expand $(Variable) per expansions dict. See MsvsSettings.GetVSMacroEnv
+ for the canonical way to retrieve a suitable dict."""
+ if '$' in string:
+ for old, new in expansions.iteritems():
+ assert '$(' not in new, new
+ string = string.replace(old, new)
+ return string
+
+def _ExtractImportantEnvironment(output_of_set):
+ """Extracts environment variables required for the toolchain to run from
+ a textual dump output by the cmd.exe 'set' command."""
+ envvars_to_save = (
+ 'goma_.*', # TODO(scottmg): This is ugly, but needed for goma.
+ 'include',
+ 'lib',
+ 'libpath',
+ 'path',
+ 'pathext',
+ 'systemroot',
+ 'temp',
+ 'tmp',
+ )
+ env = {}
+ for line in output_of_set.splitlines():
+ for envvar in envvars_to_save:
+ if re.match(envvar + '=', line.lower()):
+ var, setting = line.split('=', 1)
+ if envvar == 'path':
+ # Our own rules (for running gyp-win-tool) and other actions in
+ # Chromium rely on python being in the path. Add the path to this
+ # python here so that if it's not in the path when ninja is run
+ # later, python will still be found.
+ setting = os.path.dirname(sys.executable) + os.pathsep + setting
+ env[var.upper()] = setting
+ break
+ for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
+ if required not in env:
+ raise Exception('Environment variable "%s" '
+ 'required to be set to valid path' % required)
+ return env
+
+def _FormatAsEnvironmentBlock(envvar_dict):
+ """Format as an 'environment block' directly suitable for CreateProcess.
+ Briefly this is a list of key=value\0, terminated by an additional \0. See
+ CreateProcess documentation for more details."""
+ block = ''
+ nul = '\0'
+ for key, value in envvar_dict.iteritems():
+ block += key + '=' + value + nul
+ block += nul
+ return block
+
+def _ExtractCLPath(output_of_where):
+ """Gets the path to cl.exe based on the output of calling the environment
+ setup batch file, followed by the equivalent of `where`."""
+ # Take the first line, as that's the first found in the PATH.
+ for line in output_of_where.strip().splitlines():
+ if line.startswith('LOC:'):
+ return line[len('LOC:'):].strip()
+
+def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out):
+ """It's not sufficient to have the absolute path to the compiler, linker,
+ etc. on Windows, as those tools rely on .dlls being in the PATH. We also
+ need to support both x86 and x64 compilers within the same build (to support
+ msvs_target_platform hackery). Different architectures require a different
+ compiler binary, and different supporting environment variables (INCLUDE,
+ LIB, LIBPATH). So, we extract the environment here, wrap all invocations
+ of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which
+ sets up the environment, and then we do not prefix the compiler with
+ an absolute path, instead preferring something like "cl.exe" in the rule
+ which will then run whichever the environment setup has put in the path.
+ When the following procedure to generate environment files does not
+ meet your requirement (e.g. for custom toolchains), you can pass
+ "-G ninja_use_custom_environment_files" to the gyp to suppress file
+ generation and use custom environment files prepared by yourself."""
+ archs = ('x86', 'x64')
+ if generator_flags.get('ninja_use_custom_environment_files', 0):
+ cl_paths = {}
+ for arch in archs:
+ cl_paths[arch] = 'cl.exe'
+ return cl_paths
+ vs = GetVSVersion(generator_flags)
+ cl_paths = {}
+ for arch in archs:
+ # Extract environment variables for subprocesses.
+ args = vs.SetupScript(arch)
+ args.extend(('&&', 'set'))
+ popen = subprocess.Popen(
+ args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ variables, _ = popen.communicate()
+ env = _ExtractImportantEnvironment(variables)
+ env_block = _FormatAsEnvironmentBlock(env)
+ f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb')
+ f.write(env_block)
+ f.close()
+
+ # Find cl.exe location for this architecture.
+ args = vs.SetupScript(arch)
+ args.extend(('&&',
+ 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i'))
+ popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE)
+ output, _ = popen.communicate()
+ cl_paths[arch] = _ExtractCLPath(output)
+ return cl_paths
+
+def VerifyMissingSources(sources, build_dir, generator_flags, gyp_to_ninja):
+ """Emulate behavior of msvs_error_on_missing_sources present in the msvs
+ generator: Check that all regular source files, i.e. not created at run time,
+ exist on disk. Missing files cause needless recompilation when building via
+ VS, and we want this check to match for people/bots that build using ninja,
+ so they're not surprised when the VS build fails."""
+ if int(generator_flags.get('msvs_error_on_missing_sources', 0)):
+ no_specials = filter(lambda x: '$' not in x, sources)
+ relative = [os.path.join(build_dir, gyp_to_ninja(s)) for s in no_specials]
+ missing = filter(lambda x: not os.path.exists(x), relative)
+ if missing:
+ # They'll look like out\Release\..\..\stuff\things.cc, so normalize the
+ # path for a slightly less crazy looking output.
+ cleaned_up = [os.path.normpath(x) for x in missing]
+ raise Exception('Missing input files:\n%s' % '\n'.join(cleaned_up))
diff --git a/chromium/tools/gyp/pylib/gyp/ninja_syntax.py b/chromium/tools/gyp/pylib/gyp/ninja_syntax.py
new file mode 100644
index 00000000000..d2948f06c08
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/ninja_syntax.py
@@ -0,0 +1,160 @@
+# This file comes from
+# https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py
+# Do not edit! Edit the upstream one instead.
+
+"""Python module for generating .ninja files.
+
+Note that this is emphatically not a required piece of Ninja; it's
+just a helpful utility for build-file-generation systems that already
+use Python.
+"""
+
+import textwrap
+import re
+
+def escape_path(word):
+ return word.replace('$ ','$$ ').replace(' ','$ ').replace(':', '$:')
+
+class Writer(object):
+ def __init__(self, output, width=78):
+ self.output = output
+ self.width = width
+
+ def newline(self):
+ self.output.write('\n')
+
+ def comment(self, text):
+ for line in textwrap.wrap(text, self.width - 2):
+ self.output.write('# ' + line + '\n')
+
+ def variable(self, key, value, indent=0):
+ if value is None:
+ return
+ if isinstance(value, list):
+ value = ' '.join(filter(None, value)) # Filter out empty strings.
+ self._line('%s = %s' % (key, value), indent)
+
+ def pool(self, name, depth):
+ self._line('pool %s' % name)
+ self.variable('depth', depth, indent=1)
+
+ def rule(self, name, command, description=None, depfile=None,
+ generator=False, pool=None, restat=False, rspfile=None,
+ rspfile_content=None, deps=None):
+ self._line('rule %s' % name)
+ self.variable('command', command, indent=1)
+ if description:
+ self.variable('description', description, indent=1)
+ if depfile:
+ self.variable('depfile', depfile, indent=1)
+ if generator:
+ self.variable('generator', '1', indent=1)
+ if pool:
+ self.variable('pool', pool, indent=1)
+ if restat:
+ self.variable('restat', '1', indent=1)
+ if rspfile:
+ self.variable('rspfile', rspfile, indent=1)
+ if rspfile_content:
+ self.variable('rspfile_content', rspfile_content, indent=1)
+ if deps:
+ self.variable('deps', deps, indent=1)
+
+ def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
+ variables=None):
+ outputs = self._as_list(outputs)
+ all_inputs = self._as_list(inputs)[:]
+ out_outputs = list(map(escape_path, outputs))
+ all_inputs = list(map(escape_path, all_inputs))
+
+ if implicit:
+ implicit = map(escape_path, self._as_list(implicit))
+ all_inputs.append('|')
+ all_inputs.extend(implicit)
+ if order_only:
+ order_only = map(escape_path, self._as_list(order_only))
+ all_inputs.append('||')
+ all_inputs.extend(order_only)
+
+ self._line('build %s: %s' % (' '.join(out_outputs),
+ ' '.join([rule] + all_inputs)))
+
+ if variables:
+ if isinstance(variables, dict):
+ iterator = iter(variables.items())
+ else:
+ iterator = iter(variables)
+
+ for key, val in iterator:
+ self.variable(key, val, indent=1)
+
+ return outputs
+
+ def include(self, path):
+ self._line('include %s' % path)
+
+ def subninja(self, path):
+ self._line('subninja %s' % path)
+
+ def default(self, paths):
+ self._line('default %s' % ' '.join(self._as_list(paths)))
+
+ def _count_dollars_before_index(self, s, i):
+ """Returns the number of '$' characters right in front of s[i]."""
+ dollar_count = 0
+ dollar_index = i - 1
+ while dollar_index > 0 and s[dollar_index] == '$':
+ dollar_count += 1
+ dollar_index -= 1
+ return dollar_count
+
+ def _line(self, text, indent=0):
+ """Write 'text' word-wrapped at self.width characters."""
+ leading_space = ' ' * indent
+ while len(leading_space) + len(text) > self.width:
+ # The text is too wide; wrap if possible.
+
+ # Find the rightmost space that would obey our width constraint and
+ # that's not an escaped space.
+ available_space = self.width - len(leading_space) - len(' $')
+ space = available_space
+ while True:
+ space = text.rfind(' ', 0, space)
+ if space < 0 or \
+ self._count_dollars_before_index(text, space) % 2 == 0:
+ break
+
+ if space < 0:
+ # No such space; just use the first unescaped space we can find.
+ space = available_space - 1
+ while True:
+ space = text.find(' ', space + 1)
+ if space < 0 or \
+ self._count_dollars_before_index(text, space) % 2 == 0:
+ break
+ if space < 0:
+ # Give up on breaking.
+ break
+
+ self.output.write(leading_space + text[0:space] + ' $\n')
+ text = text[space+1:]
+
+ # Subsequent lines are continuations, so indent them.
+ leading_space = ' ' * (indent+2)
+
+ self.output.write(leading_space + text + '\n')
+
+ def _as_list(self, input):
+ if input is None:
+ return []
+ if isinstance(input, list):
+ return input
+ return [input]
+
+
+def escape(string):
+ """Escape a string such that it can be embedded into a Ninja file without
+ further interpretation."""
+ assert '\n' not in string, 'Ninja syntax does not allow newlines'
+ # We only have one special metacharacter: '$'.
+ return string.replace('$', '$$')
diff --git a/chromium/tools/gyp/pylib/gyp/sun_tool.py b/chromium/tools/gyp/pylib/gyp/sun_tool.py
new file mode 100755
index 00000000000..90d59c82409
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/sun_tool.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""These functions are executed via gyp-sun-tool when using the Makefile
+generator."""
+
+import fcntl
+import os
+import struct
+import subprocess
+import sys
+
+
+def main(args):
+ executor = SunTool()
+ executor.Dispatch(args)
+
+
+class SunTool(object):
+ """This class performs all the SunOS tooling steps. The methods can either be
+ executed directly, or dispatched from an argument list."""
+
+ def Dispatch(self, args):
+ """Dispatches a string command to a method."""
+ if len(args) < 1:
+ raise Exception("Not enough arguments")
+
+ method = "Exec%s" % self._CommandifyName(args[0])
+ getattr(self, method)(*args[1:])
+
+ def _CommandifyName(self, name_string):
+ """Transforms a tool name like copy-info-plist to CopyInfoPlist"""
+ return name_string.title().replace('-', '')
+
+ def ExecFlock(self, lockfile, *cmd_list):
+ """Emulates the most basic behavior of Linux's flock(1)."""
+ # Rely on exception handling to report errors.
+ # Note that the stock python on SunOS has a bug
+ # where fcntl.flock(fd, LOCK_EX) always fails
+ # with EBADF, that's why we use this F_SETLK
+ # hack instead.
+ fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666)
+ op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
+ fcntl.fcntl(fd, fcntl.F_SETLK, op)
+ return subprocess.call(cmd_list)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/gyp/pylib/gyp/win_tool.py b/chromium/tools/gyp/pylib/gyp/win_tool.py
new file mode 100755
index 00000000000..3424c015d30
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/win_tool.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility functions for Windows builds.
+
+These functions are executed via gyp-win-tool when using the ninja generator.
+"""
+
+import os
+import shutil
+import subprocess
+import sys
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def main(args):
+ executor = WinTool()
+ exit_code = executor.Dispatch(args)
+ if exit_code is not None:
+ sys.exit(exit_code)
+
+
+class WinTool(object):
+ """This class performs all the Windows tooling steps. The methods can either
+ be executed directly, or dispatched from an argument list."""
+
+ def Dispatch(self, args):
+ """Dispatches a string command to a method."""
+ if len(args) < 1:
+ raise Exception("Not enough arguments")
+
+ method = "Exec%s" % self._CommandifyName(args[0])
+ return getattr(self, method)(*args[1:])
+
+ def _CommandifyName(self, name_string):
+ """Transforms a tool name like recursive-mirror to RecursiveMirror."""
+ return name_string.title().replace('-', '')
+
+ def _GetEnv(self, arch):
+ """Gets the saved environment from a file for a given architecture."""
+ # The environment is saved as an "environment block" (see CreateProcess
+ # and msvs_emulation for details). We convert to a dict here.
+ # Drop last 2 NULs, one for list terminator, one for trailing vs. separator.
+ pairs = open(arch).read()[:-2].split('\0')
+ kvs = [item.split('=', 1) for item in pairs]
+ return dict(kvs)
+
+ def ExecStamp(self, path):
+ """Simple stamp command."""
+ open(path, 'w').close()
+
+ def ExecRecursiveMirror(self, source, dest):
+ """Emulation of rm -rf out && cp -af in out."""
+ if os.path.exists(dest):
+ if os.path.isdir(dest):
+ shutil.rmtree(dest)
+ else:
+ os.unlink(dest)
+ if os.path.isdir(source):
+ shutil.copytree(source, dest)
+ else:
+ shutil.copy2(source, dest)
+
+ def ExecLinkWrapper(self, arch, *args):
+ """Filter diagnostic output from link that looks like:
+ ' Creating library ui.dll.lib and object ui.dll.exp'
+ This happens when there are exports from the dll or exe.
+ """
+ env = self._GetEnv(arch)
+ popen = subprocess.Popen(args, shell=True, env=env,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ out, _ = popen.communicate()
+ for line in out.splitlines():
+ if not line.startswith(' Creating library '):
+ print line
+ return popen.returncode
+
+ def ExecManifestWrapper(self, arch, *args):
+ """Run manifest tool with environment set. Strip out undesirable warning
+ (some XML blocks are recognized by the OS loader, but not the manifest
+ tool)."""
+ env = self._GetEnv(arch)
+ popen = subprocess.Popen(args, shell=True, env=env,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ out, _ = popen.communicate()
+ for line in out.splitlines():
+ if line and 'manifest authoring warning 81010002' not in line:
+ print line
+ return popen.returncode
+
+ def ExecManifestToRc(self, arch, *args):
+ """Creates a resource file pointing a SxS assembly manifest.
+ |args| is tuple containing path to resource file, path to manifest file
+ and resource name which can be "1" (for executables) or "2" (for DLLs)."""
+ manifest_path, resource_path, resource_name = args
+ with open(resource_path, 'wb') as output:
+ output.write('#include <windows.h>\n%s RT_MANIFEST "%s"' % (
+ resource_name,
+ os.path.abspath(manifest_path).replace('\\', '/')))
+
+ def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl,
+ *flags):
+ """Filter noisy filenames output from MIDL compile step that isn't
+ quietable via command line flags.
+ """
+ args = ['midl', '/nologo'] + list(flags) + [
+ '/out', outdir,
+ '/tlb', tlb,
+ '/h', h,
+ '/dlldata', dlldata,
+ '/iid', iid,
+ '/proxy', proxy,
+ idl]
+ env = self._GetEnv(arch)
+ popen = subprocess.Popen(args, shell=True, env=env,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ out, _ = popen.communicate()
+ # Filter junk out of stdout, and write filtered versions. Output we want
+ # to filter is pairs of lines that look like this:
+ # Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl
+ # objidl.idl
+ lines = out.splitlines()
+ prefix = 'Processing '
+ processing = set(os.path.basename(x) for x in lines if x.startswith(prefix))
+ for line in lines:
+ if not line.startswith(prefix) and line not in processing:
+ print line
+ return popen.returncode
+
+ def ExecAsmWrapper(self, arch, *args):
+ """Filter logo banner from invocations of asm.exe."""
+ env = self._GetEnv(arch)
+ # MSVS doesn't assemble x64 asm files.
+ if arch == 'environment.x64':
+ return 0
+ popen = subprocess.Popen(args, shell=True, env=env,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ out, _ = popen.communicate()
+ for line in out.splitlines():
+ if (not line.startswith('Copyright (C) Microsoft Corporation') and
+ not line.startswith('Microsoft (R) Macro Assembler') and
+ not line.startswith(' Assembling: ') and
+ line):
+ print line
+ return popen.returncode
+
+ def ExecRcWrapper(self, arch, *args):
+ """Filter logo banner from invocations of rc.exe. Older versions of RC
+ don't support the /nologo flag."""
+ env = self._GetEnv(arch)
+ popen = subprocess.Popen(args, shell=True, env=env,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ out, _ = popen.communicate()
+ for line in out.splitlines():
+ if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler') and
+ not line.startswith('Copyright (C) Microsoft Corporation') and
+ line):
+ print line
+ return popen.returncode
+
+ def ExecActionWrapper(self, arch, rspfile, *dir):
+ """Runs an action command line from a response file using the environment
+ for |arch|. If |dir| is supplied, use that as the working directory."""
+ env = self._GetEnv(arch)
+ args = open(rspfile).read()
+ dir = dir[0] if dir else None
+ popen = subprocess.Popen(args, shell=True, env=env, cwd=dir)
+ popen.wait()
+ return popen.returncode
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/gyp/pylib/gyp/xcode_emulation.py b/chromium/tools/gyp/pylib/gyp/xcode_emulation.py
new file mode 100644
index 00000000000..f79fb0bba0c
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/xcode_emulation.py
@@ -0,0 +1,1136 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This module contains classes that help to emulate xcodebuild behavior on top of
+other build systems, such as make and ninja.
+"""
+
+import gyp.common
+import os.path
+import re
+import shlex
+import subprocess
+import sys
+from gyp.common import GypError
+
+class XcodeSettings(object):
+ """A class that understands the gyp 'xcode_settings' object."""
+
+ # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached
+ # at class-level for efficiency.
+ _sdk_path_cache = {}
+
+ def __init__(self, spec):
+ self.spec = spec
+
+ self.isIOS = False
+
+ # Per-target 'xcode_settings' are pushed down into configs earlier by gyp.
+ # This means self.xcode_settings[config] always contains all settings
+ # for that config -- the per-target settings as well. Settings that are
+ # the same for all configs are implicitly per-target settings.
+ self.xcode_settings = {}
+ configs = spec['configurations']
+ for configname, config in configs.iteritems():
+ self.xcode_settings[configname] = config.get('xcode_settings', {})
+ if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET',
+ None):
+ self.isIOS = True
+
+ # If you need this, speak up at http://crbug.com/122592
+ conditional_keys = [key for key in self.xcode_settings[configname]
+ if key.endswith(']')]
+ if conditional_keys:
+ print 'Warning: Conditional keys not implemented, ignoring:', \
+ ' '.join(conditional_keys)
+ for key in conditional_keys:
+ del self.xcode_settings[configname][key]
+
+ # This is only non-None temporarily during the execution of some methods.
+ self.configname = None
+
+ # Used by _AdjustLibrary to match .a and .dylib entries in libraries.
+ self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$')
+
+ def _Settings(self):
+ assert self.configname
+ return self.xcode_settings[self.configname]
+
+ def _Test(self, test_key, cond_key, default):
+ return self._Settings().get(test_key, default) == cond_key
+
+ def _Appendf(self, lst, test_key, format_str, default=None):
+ if test_key in self._Settings():
+ lst.append(format_str % str(self._Settings()[test_key]))
+ elif default:
+ lst.append(format_str % str(default))
+
+ def _WarnUnimplemented(self, test_key):
+ if test_key in self._Settings():
+ print 'Warning: Ignoring not yet implemented key "%s".' % test_key
+
+ def _IsBundle(self):
+ return int(self.spec.get('mac_bundle', 0)) != 0
+
+ def GetFrameworkVersion(self):
+ """Returns the framework version of the current target. Only valid for
+ bundles."""
+ assert self._IsBundle()
+ return self.GetPerTargetSetting('FRAMEWORK_VERSION', default='A')
+
+ def GetWrapperExtension(self):
+ """Returns the bundle extension (.app, .framework, .plugin, etc). Only
+ valid for bundles."""
+ assert self._IsBundle()
+ if self.spec['type'] in ('loadable_module', 'shared_library'):
+ default_wrapper_extension = {
+ 'loadable_module': 'bundle',
+ 'shared_library': 'framework',
+ }[self.spec['type']]
+ wrapper_extension = self.GetPerTargetSetting(
+ 'WRAPPER_EXTENSION', default=default_wrapper_extension)
+ return '.' + self.spec.get('product_extension', wrapper_extension)
+ elif self.spec['type'] == 'executable':
+ return '.' + self.spec.get('product_extension', 'app')
+ else:
+ assert False, "Don't know extension for '%s', target '%s'" % (
+ self.spec['type'], self.spec['target_name'])
+
+ def GetProductName(self):
+ """Returns PRODUCT_NAME."""
+ return self.spec.get('product_name', self.spec['target_name'])
+
+ def GetFullProductName(self):
+ """Returns FULL_PRODUCT_NAME."""
+ if self._IsBundle():
+ return self.GetWrapperName()
+ else:
+ return self._GetStandaloneBinaryPath()
+
+ def GetWrapperName(self):
+ """Returns the directory name of the bundle represented by this target.
+ Only valid for bundles."""
+ assert self._IsBundle()
+ return self.GetProductName() + self.GetWrapperExtension()
+
+ def GetBundleContentsFolderPath(self):
+ """Returns the qualified path to the bundle's contents folder. E.g.
+ Chromium.app/Contents or Foo.bundle/Versions/A. Only valid for bundles."""
+ if self.isIOS:
+ return self.GetWrapperName()
+ assert self._IsBundle()
+ if self.spec['type'] == 'shared_library':
+ return os.path.join(
+ self.GetWrapperName(), 'Versions', self.GetFrameworkVersion())
+ else:
+ # loadable_modules have a 'Contents' folder like executables.
+ return os.path.join(self.GetWrapperName(), 'Contents')
+
+ def GetBundleResourceFolder(self):
+ """Returns the qualified path to the bundle's resource folder. E.g.
+ Chromium.app/Contents/Resources. Only valid for bundles."""
+ assert self._IsBundle()
+ if self.isIOS:
+ return self.GetBundleContentsFolderPath()
+ return os.path.join(self.GetBundleContentsFolderPath(), 'Resources')
+
+ def GetBundlePlistPath(self):
+ """Returns the qualified path to the bundle's plist file. E.g.
+ Chromium.app/Contents/Info.plist. Only valid for bundles."""
+ assert self._IsBundle()
+ if self.spec['type'] in ('executable', 'loadable_module'):
+ return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist')
+ else:
+ return os.path.join(self.GetBundleContentsFolderPath(),
+ 'Resources', 'Info.plist')
+
+ def GetProductType(self):
+ """Returns the PRODUCT_TYPE of this target."""
+ if self._IsBundle():
+ return {
+ 'executable': 'com.apple.product-type.application',
+ 'loadable_module': 'com.apple.product-type.bundle',
+ 'shared_library': 'com.apple.product-type.framework',
+ }[self.spec['type']]
+ else:
+ return {
+ 'executable': 'com.apple.product-type.tool',
+ 'loadable_module': 'com.apple.product-type.library.dynamic',
+ 'shared_library': 'com.apple.product-type.library.dynamic',
+ 'static_library': 'com.apple.product-type.library.static',
+ }[self.spec['type']]
+
+ def GetMachOType(self):
+ """Returns the MACH_O_TYPE of this target."""
+ # Weird, but matches Xcode.
+ if not self._IsBundle() and self.spec['type'] == 'executable':
+ return ''
+ return {
+ 'executable': 'mh_execute',
+ 'static_library': 'staticlib',
+ 'shared_library': 'mh_dylib',
+ 'loadable_module': 'mh_bundle',
+ }[self.spec['type']]
+
+ def _GetBundleBinaryPath(self):
+ """Returns the name of the bundle binary of by this target.
+ E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles."""
+ assert self._IsBundle()
+ if self.spec['type'] in ('shared_library') or self.isIOS:
+ path = self.GetBundleContentsFolderPath()
+ elif self.spec['type'] in ('executable', 'loadable_module'):
+ path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS')
+ return os.path.join(path, self.GetExecutableName())
+
+ def _GetStandaloneExecutableSuffix(self):
+ if 'product_extension' in self.spec:
+ return '.' + self.spec['product_extension']
+ return {
+ 'executable': '',
+ 'static_library': '.a',
+ 'shared_library': '.dylib',
+ 'loadable_module': '.so',
+ }[self.spec['type']]
+
+ def _GetStandaloneExecutablePrefix(self):
+ return self.spec.get('product_prefix', {
+ 'executable': '',
+ 'static_library': 'lib',
+ 'shared_library': 'lib',
+ # Non-bundled loadable_modules are called foo.so for some reason
+ # (that is, .so and no prefix) with the xcode build -- match that.
+ 'loadable_module': '',
+ }[self.spec['type']])
+
+ def _GetStandaloneBinaryPath(self):
+ """Returns the name of the non-bundle binary represented by this target.
+ E.g. hello_world. Only valid for non-bundles."""
+ assert not self._IsBundle()
+ assert self.spec['type'] in (
+ 'executable', 'shared_library', 'static_library', 'loadable_module'), (
+ 'Unexpected type %s' % self.spec['type'])
+ target = self.spec['target_name']
+ if self.spec['type'] == 'static_library':
+ if target[:3] == 'lib':
+ target = target[3:]
+ elif self.spec['type'] in ('loadable_module', 'shared_library'):
+ if target[:3] == 'lib':
+ target = target[3:]
+
+ target_prefix = self._GetStandaloneExecutablePrefix()
+ target = self.spec.get('product_name', target)
+ target_ext = self._GetStandaloneExecutableSuffix()
+ return target_prefix + target + target_ext
+
+ def GetExecutableName(self):
+ """Returns the executable name of the bundle represented by this target.
+ E.g. Chromium."""
+ if self._IsBundle():
+ return self.spec.get('product_name', self.spec['target_name'])
+ else:
+ return self._GetStandaloneBinaryPath()
+
+ def GetExecutablePath(self):
+ """Returns the directory name of the bundle represented by this target. E.g.
+ Chromium.app/Contents/MacOS/Chromium."""
+ if self._IsBundle():
+ return self._GetBundleBinaryPath()
+ else:
+ return self._GetStandaloneBinaryPath()
+
+ def GetActiveArchs(self, configname):
+ """Returns the architectures this target should be built for."""
+ # TODO: Look at VALID_ARCHS, ONLY_ACTIVE_ARCH; possibly set
+ # CURRENT_ARCH / NATIVE_ARCH env vars?
+ return self.xcode_settings[configname].get('ARCHS', ['i386'])
+
+ def _GetSdkVersionInfoItem(self, sdk, infoitem):
+ job = subprocess.Popen(['xcodebuild', '-version', '-sdk', sdk, infoitem],
+ stdout=subprocess.PIPE)
+ out = job.communicate()[0]
+ if job.returncode != 0:
+ sys.stderr.write(out + '\n')
+ raise GypError('Error %d running xcodebuild' % job.returncode)
+ return out.rstrip('\n')
+
+ def _SdkPath(self):
+ sdk_root = self.GetPerTargetSetting('SDKROOT', default='macosx')
+ if sdk_root.startswith('/'):
+ return sdk_root
+ if sdk_root not in XcodeSettings._sdk_path_cache:
+ XcodeSettings._sdk_path_cache[sdk_root] = self._GetSdkVersionInfoItem(
+ sdk_root, 'Path')
+ return XcodeSettings._sdk_path_cache[sdk_root]
+
+ def _AppendPlatformVersionMinFlags(self, lst):
+ self._Appendf(lst, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s')
+ if 'IPHONEOS_DEPLOYMENT_TARGET' in self._Settings():
+ # TODO: Implement this better?
+ sdk_path_basename = os.path.basename(self._SdkPath())
+ if sdk_path_basename.lower().startswith('iphonesimulator'):
+ self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET',
+ '-mios-simulator-version-min=%s')
+ else:
+ self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET',
+ '-miphoneos-version-min=%s')
+
+ def GetCflags(self, configname, arch=None):
+ """Returns flags that need to be added to .c, .cc, .m, and .mm
+ compilations."""
+ # This functions (and the similar ones below) do not offer complete
+ # emulation of all xcode_settings keys. They're implemented on demand.
+
+ self.configname = configname
+ cflags = []
+
+ sdk_root = self._SdkPath()
+ if 'SDKROOT' in self._Settings():
+ cflags.append('-isysroot %s' % sdk_root)
+
+ if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'):
+ cflags.append('-Wconstant-conversion')
+
+ if self._Test('GCC_CHAR_IS_UNSIGNED_CHAR', 'YES', default='NO'):
+ cflags.append('-funsigned-char')
+
+ if self._Test('GCC_CW_ASM_SYNTAX', 'YES', default='YES'):
+ cflags.append('-fasm-blocks')
+
+ if 'GCC_DYNAMIC_NO_PIC' in self._Settings():
+ if self._Settings()['GCC_DYNAMIC_NO_PIC'] == 'YES':
+ cflags.append('-mdynamic-no-pic')
+ else:
+ pass
+ # TODO: In this case, it depends on the target. xcode passes
+ # mdynamic-no-pic by default for executable and possibly static lib
+ # according to mento
+
+ if self._Test('GCC_ENABLE_PASCAL_STRINGS', 'YES', default='YES'):
+ cflags.append('-mpascal-strings')
+
+ self._Appendf(cflags, 'GCC_OPTIMIZATION_LEVEL', '-O%s', default='s')
+
+ if self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES'):
+ dbg_format = self._Settings().get('DEBUG_INFORMATION_FORMAT', 'dwarf')
+ if dbg_format == 'dwarf':
+ cflags.append('-gdwarf-2')
+ elif dbg_format == 'stabs':
+ raise NotImplementedError('stabs debug format is not supported yet.')
+ elif dbg_format == 'dwarf-with-dsym':
+ cflags.append('-gdwarf-2')
+ else:
+ raise NotImplementedError('Unknown debug format %s' % dbg_format)
+
+ if self._Settings().get('GCC_STRICT_ALIASING') == 'YES':
+ cflags.append('-fstrict-aliasing')
+ elif self._Settings().get('GCC_STRICT_ALIASING') == 'NO':
+ cflags.append('-fno-strict-aliasing')
+
+ if self._Test('GCC_SYMBOLS_PRIVATE_EXTERN', 'YES', default='NO'):
+ cflags.append('-fvisibility=hidden')
+
+ if self._Test('GCC_TREAT_WARNINGS_AS_ERRORS', 'YES', default='NO'):
+ cflags.append('-Werror')
+
+ if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'):
+ cflags.append('-Wnewline-eof')
+
+ self._AppendPlatformVersionMinFlags(cflags)
+
+ # TODO:
+ if self._Test('COPY_PHASE_STRIP', 'YES', default='NO'):
+ self._WarnUnimplemented('COPY_PHASE_STRIP')
+ self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS')
+ self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS')
+
+ # TODO: This is exported correctly, but assigning to it is not supported.
+ self._WarnUnimplemented('MACH_O_TYPE')
+ self._WarnUnimplemented('PRODUCT_TYPE')
+
+ if arch is not None:
+ archs = [arch]
+ else:
+ archs = self._Settings().get('ARCHS', ['i386'])
+ if len(archs) != 1:
+ # TODO: Supporting fat binaries will be annoying.
+ self._WarnUnimplemented('ARCHS')
+ archs = ['i386']
+ cflags.append('-arch ' + archs[0])
+
+ if archs[0] in ('i386', 'x86_64'):
+ if self._Test('GCC_ENABLE_SSE3_EXTENSIONS', 'YES', default='NO'):
+ cflags.append('-msse3')
+ if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES',
+ default='NO'):
+ cflags.append('-mssse3') # Note 3rd 's'.
+ if self._Test('GCC_ENABLE_SSE41_EXTENSIONS', 'YES', default='NO'):
+ cflags.append('-msse4.1')
+ if self._Test('GCC_ENABLE_SSE42_EXTENSIONS', 'YES', default='NO'):
+ cflags.append('-msse4.2')
+
+ cflags += self._Settings().get('WARNING_CFLAGS', [])
+
+ config = self.spec['configurations'][self.configname]
+ framework_dirs = config.get('mac_framework_dirs', [])
+ for directory in framework_dirs:
+ cflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root))
+
+ self.configname = None
+ return cflags
+
+ def GetCflagsC(self, configname):
+ """Returns flags that need to be added to .c, and .m compilations."""
+ self.configname = configname
+ cflags_c = []
+ if self._Settings().get('GCC_C_LANGUAGE_STANDARD', '') == 'ansi':
+ cflags_c.append('-ansi')
+ else:
+ self._Appendf(cflags_c, 'GCC_C_LANGUAGE_STANDARD', '-std=%s')
+ cflags_c += self._Settings().get('OTHER_CFLAGS', [])
+ self.configname = None
+ return cflags_c
+
+ def GetCflagsCC(self, configname):
+ """Returns flags that need to be added to .cc, and .mm compilations."""
+ self.configname = configname
+ cflags_cc = []
+
+ clang_cxx_language_standard = self._Settings().get(
+ 'CLANG_CXX_LANGUAGE_STANDARD')
+ # Note: Don't make c++0x to c++11 so that c++0x can be used with older
+ # clangs that don't understand c++11 yet (like Xcode 4.2's).
+ if clang_cxx_language_standard:
+ cflags_cc.append('-std=%s' % clang_cxx_language_standard)
+
+ self._Appendf(cflags_cc, 'CLANG_CXX_LIBRARY', '-stdlib=%s')
+
+ if self._Test('GCC_ENABLE_CPP_RTTI', 'NO', default='YES'):
+ cflags_cc.append('-fno-rtti')
+ if self._Test('GCC_ENABLE_CPP_EXCEPTIONS', 'NO', default='YES'):
+ cflags_cc.append('-fno-exceptions')
+ if self._Test('GCC_INLINES_ARE_PRIVATE_EXTERN', 'YES', default='NO'):
+ cflags_cc.append('-fvisibility-inlines-hidden')
+ if self._Test('GCC_THREADSAFE_STATICS', 'NO', default='YES'):
+ cflags_cc.append('-fno-threadsafe-statics')
+ # Note: This flag is a no-op for clang, it only has an effect for gcc.
+ if self._Test('GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO', 'NO', default='YES'):
+ cflags_cc.append('-Wno-invalid-offsetof')
+
+ other_ccflags = []
+
+ for flag in self._Settings().get('OTHER_CPLUSPLUSFLAGS', ['$(inherited)']):
+ # TODO: More general variable expansion. Missing in many other places too.
+ if flag in ('$inherited', '$(inherited)', '${inherited}'):
+ flag = '$OTHER_CFLAGS'
+ if flag in ('$OTHER_CFLAGS', '$(OTHER_CFLAGS)', '${OTHER_CFLAGS}'):
+ other_ccflags += self._Settings().get('OTHER_CFLAGS', [])
+ else:
+ other_ccflags.append(flag)
+ cflags_cc += other_ccflags
+
+ self.configname = None
+ return cflags_cc
+
+ def _AddObjectiveCGarbageCollectionFlags(self, flags):
+ gc_policy = self._Settings().get('GCC_ENABLE_OBJC_GC', 'unsupported')
+ if gc_policy == 'supported':
+ flags.append('-fobjc-gc')
+ elif gc_policy == 'required':
+ flags.append('-fobjc-gc-only')
+
+ def _AddObjectiveCARCFlags(self, flags):
+ if self._Test('CLANG_ENABLE_OBJC_ARC', 'YES', default='NO'):
+ flags.append('-fobjc-arc')
+
+ def GetCflagsObjC(self, configname):
+ """Returns flags that need to be added to .m compilations."""
+ self.configname = configname
+ cflags_objc = []
+ self._AddObjectiveCGarbageCollectionFlags(cflags_objc)
+ self._AddObjectiveCARCFlags(cflags_objc)
+ self.configname = None
+ return cflags_objc
+
+ def GetCflagsObjCC(self, configname):
+ """Returns flags that need to be added to .mm compilations."""
+ self.configname = configname
+ cflags_objcc = []
+ self._AddObjectiveCGarbageCollectionFlags(cflags_objcc)
+ self._AddObjectiveCARCFlags(cflags_objcc)
+ if self._Test('GCC_OBJC_CALL_CXX_CDTORS', 'YES', default='NO'):
+ cflags_objcc.append('-fobjc-call-cxx-cdtors')
+ self.configname = None
+ return cflags_objcc
+
+ def GetInstallNameBase(self):
+ """Return DYLIB_INSTALL_NAME_BASE for this target."""
+ # Xcode sets this for shared_libraries, and for nonbundled loadable_modules.
+ if (self.spec['type'] != 'shared_library' and
+ (self.spec['type'] != 'loadable_module' or self._IsBundle())):
+ return None
+ install_base = self.GetPerTargetSetting(
+ 'DYLIB_INSTALL_NAME_BASE',
+ default='/Library/Frameworks' if self._IsBundle() else '/usr/local/lib')
+ return install_base
+
+ def _StandardizePath(self, path):
+ """Do :standardizepath processing for path."""
+ # I'm not quite sure what :standardizepath does. Just call normpath(),
+ # but don't let @executable_path/../foo collapse to foo.
+ if '/' in path:
+ prefix, rest = '', path
+ if path.startswith('@'):
+ prefix, rest = path.split('/', 1)
+ rest = os.path.normpath(rest) # :standardizepath
+ path = os.path.join(prefix, rest)
+ return path
+
+ def GetInstallName(self):
+ """Return LD_DYLIB_INSTALL_NAME for this target."""
+ # Xcode sets this for shared_libraries, and for nonbundled loadable_modules.
+ if (self.spec['type'] != 'shared_library' and
+ (self.spec['type'] != 'loadable_module' or self._IsBundle())):
+ return None
+
+ default_install_name = \
+ '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)'
+ install_name = self.GetPerTargetSetting(
+ 'LD_DYLIB_INSTALL_NAME', default=default_install_name)
+
+ # Hardcode support for the variables used in chromium for now, to
+ # unblock people using the make build.
+ if '$' in install_name:
+ assert install_name in ('$(DYLIB_INSTALL_NAME_BASE:standardizepath)/'
+ '$(WRAPPER_NAME)/$(PRODUCT_NAME)', default_install_name), (
+ 'Variables in LD_DYLIB_INSTALL_NAME are not generally supported '
+ 'yet in target \'%s\' (got \'%s\')' %
+ (self.spec['target_name'], install_name))
+
+ install_name = install_name.replace(
+ '$(DYLIB_INSTALL_NAME_BASE:standardizepath)',
+ self._StandardizePath(self.GetInstallNameBase()))
+ if self._IsBundle():
+ # These are only valid for bundles, hence the |if|.
+ install_name = install_name.replace(
+ '$(WRAPPER_NAME)', self.GetWrapperName())
+ install_name = install_name.replace(
+ '$(PRODUCT_NAME)', self.GetProductName())
+ else:
+ assert '$(WRAPPER_NAME)' not in install_name
+ assert '$(PRODUCT_NAME)' not in install_name
+
+ install_name = install_name.replace(
+ '$(EXECUTABLE_PATH)', self.GetExecutablePath())
+ return install_name
+
+ def _MapLinkerFlagFilename(self, ldflag, gyp_to_build_path):
+ """Checks if ldflag contains a filename and if so remaps it from
+ gyp-directory-relative to build-directory-relative."""
+ # This list is expanded on demand.
+ # They get matched as:
+ # -exported_symbols_list file
+ # -Wl,exported_symbols_list file
+ # -Wl,exported_symbols_list,file
+ LINKER_FILE = '(\S+)'
+ WORD = '\S+'
+ linker_flags = [
+ ['-exported_symbols_list', LINKER_FILE], # Needed for NaCl.
+ ['-unexported_symbols_list', LINKER_FILE],
+ ['-reexported_symbols_list', LINKER_FILE],
+ ['-sectcreate', WORD, WORD, LINKER_FILE], # Needed for remoting.
+ ]
+ for flag_pattern in linker_flags:
+ regex = re.compile('(?:-Wl,)?' + '[ ,]'.join(flag_pattern))
+ m = regex.match(ldflag)
+ if m:
+ ldflag = ldflag[:m.start(1)] + gyp_to_build_path(m.group(1)) + \
+ ldflag[m.end(1):]
+ # Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS,
+ # TODO(thakis): Update ffmpeg.gyp):
+ if ldflag.startswith('-L'):
+ ldflag = '-L' + gyp_to_build_path(ldflag[len('-L'):])
+ return ldflag
+
+ def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None):
+ """Returns flags that need to be passed to the linker.
+
+ Args:
+ configname: The name of the configuration to get ld flags for.
+ product_dir: The directory where products such static and dynamic
+ libraries are placed. This is added to the library search path.
+ gyp_to_build_path: A function that converts paths relative to the
+ current gyp file to paths relative to the build direcotry.
+ """
+ self.configname = configname
+ ldflags = []
+
+ # The xcode build is relative to a gyp file's directory, and OTHER_LDFLAGS
+ # can contain entries that depend on this. Explicitly absolutify these.
+ for ldflag in self._Settings().get('OTHER_LDFLAGS', []):
+ ldflags.append(self._MapLinkerFlagFilename(ldflag, gyp_to_build_path))
+
+ if self._Test('USE_LIBCPP', 'YES', default='NO'):
+ ldflags.append('-stdlib=libc++')
+
+ if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'):
+ ldflags.append('-Wl,-dead_strip')
+
+ if self._Test('PREBINDING', 'YES', default='NO'):
+ ldflags.append('-Wl,-prebind')
+
+ self._Appendf(
+ ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s')
+ self._Appendf(
+ ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s')
+
+ self._AppendPlatformVersionMinFlags(ldflags)
+
+ if 'SDKROOT' in self._Settings():
+ ldflags.append('-isysroot ' + self._SdkPath())
+
+ for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []):
+ ldflags.append('-L' + gyp_to_build_path(library_path))
+
+ if 'ORDER_FILE' in self._Settings():
+ ldflags.append('-Wl,-order_file ' +
+ '-Wl,' + gyp_to_build_path(
+ self._Settings()['ORDER_FILE']))
+
+ if arch is not None:
+ archs = [arch]
+ else:
+ archs = self._Settings().get('ARCHS', ['i386'])
+ if len(archs) != 1:
+ # TODO: Supporting fat binaries will be annoying.
+ self._WarnUnimplemented('ARCHS')
+ archs = ['i386']
+ ldflags.append('-arch ' + archs[0])
+
+ # Xcode adds the product directory by default.
+ ldflags.append('-L' + product_dir)
+
+ install_name = self.GetInstallName()
+ if install_name:
+ ldflags.append('-install_name ' + install_name.replace(' ', r'\ '))
+
+ for rpath in self._Settings().get('LD_RUNPATH_SEARCH_PATHS', []):
+ ldflags.append('-Wl,-rpath,' + rpath)
+
+ config = self.spec['configurations'][self.configname]
+ framework_dirs = config.get('mac_framework_dirs', [])
+ for directory in framework_dirs:
+ ldflags.append('-F' + directory.replace('$(SDKROOT)', self._SdkPath()))
+
+ self.configname = None
+ return ldflags
+
+ def GetLibtoolflags(self, configname):
+ """Returns flags that need to be passed to the static linker.
+
+ Args:
+ configname: The name of the configuration to get ld flags for.
+ """
+ self.configname = configname
+ libtoolflags = []
+
+ for libtoolflag in self._Settings().get('OTHER_LDFLAGS', []):
+ libtoolflags.append(libtoolflag)
+ # TODO(thakis): ARCHS?
+
+ self.configname = None
+ return libtoolflags
+
+ def GetPerTargetSettings(self):
+ """Gets a list of all the per-target settings. This will only fetch keys
+ whose values are the same across all configurations."""
+ first_pass = True
+ result = {}
+ for configname in sorted(self.xcode_settings.keys()):
+ if first_pass:
+ result = dict(self.xcode_settings[configname])
+ first_pass = False
+ else:
+ for key, value in self.xcode_settings[configname].iteritems():
+ if key not in result:
+ continue
+ elif result[key] != value:
+ del result[key]
+ return result
+
+ def GetPerTargetSetting(self, setting, default=None):
+ """Tries to get xcode_settings.setting from spec. Assumes that the setting
+ has the same value in all configurations and throws otherwise."""
+ first_pass = True
+ result = None
+ for configname in sorted(self.xcode_settings.keys()):
+ if first_pass:
+ result = self.xcode_settings[configname].get(setting, None)
+ first_pass = False
+ else:
+ assert result == self.xcode_settings[configname].get(setting, None), (
+ "Expected per-target setting for '%s', got per-config setting "
+ "(target %s)" % (setting, spec['target_name']))
+ if result is None:
+ return default
+ return result
+
+ def _GetStripPostbuilds(self, configname, output_binary, quiet):
+ """Returns a list of shell commands that contain the shell commands
+ neccessary to strip this target's binary. These should be run as postbuilds
+ before the actual postbuilds run."""
+ self.configname = configname
+
+ result = []
+ if (self._Test('DEPLOYMENT_POSTPROCESSING', 'YES', default='NO') and
+ self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')):
+
+ default_strip_style = 'debugging'
+ if self._IsBundle():
+ default_strip_style = 'non-global'
+ elif self.spec['type'] == 'executable':
+ default_strip_style = 'all'
+
+ strip_style = self._Settings().get('STRIP_STYLE', default_strip_style)
+ strip_flags = {
+ 'all': '',
+ 'non-global': '-x',
+ 'debugging': '-S',
+ }[strip_style]
+
+ explicit_strip_flags = self._Settings().get('STRIPFLAGS', '')
+ if explicit_strip_flags:
+ strip_flags += ' ' + _NormalizeEnvVarReferences(explicit_strip_flags)
+
+ if not quiet:
+ result.append('echo STRIP\\(%s\\)' % self.spec['target_name'])
+ result.append('strip %s %s' % (strip_flags, output_binary))
+
+ self.configname = None
+ return result
+
+ def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet):
+ """Returns a list of shell commands that contain the shell commands
+ neccessary to massage this target's debug information. These should be run
+ as postbuilds before the actual postbuilds run."""
+ self.configname = configname
+
+ # For static libraries, no dSYMs are created.
+ result = []
+ if (self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES') and
+ self._Test(
+ 'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and
+ self.spec['type'] != 'static_library'):
+ if not quiet:
+ result.append('echo DSYMUTIL\\(%s\\)' % self.spec['target_name'])
+ result.append('dsymutil %s -o %s' % (output_binary, output + '.dSYM'))
+
+ self.configname = None
+ return result
+
+ def GetTargetPostbuilds(self, configname, output, output_binary, quiet=False):
+ """Returns a list of shell commands that contain the shell commands
+ to run as postbuilds for this target, before the actual postbuilds."""
+ # dSYMs need to build before stripping happens.
+ return (
+ self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) +
+ self._GetStripPostbuilds(configname, output_binary, quiet))
+
+ def _AdjustLibrary(self, library):
+ if library.endswith('.framework'):
+ l = '-framework ' + os.path.splitext(os.path.basename(library))[0]
+ else:
+ m = self.library_re.match(library)
+ if m:
+ l = '-l' + m.group(1)
+ else:
+ l = library
+ return l.replace('$(SDKROOT)', self._SdkPath())
+
+ def AdjustLibraries(self, libraries):
+ """Transforms entries like 'Cocoa.framework' in libraries into entries like
+ '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc.
+ """
+ libraries = [ self._AdjustLibrary(library) for library in libraries]
+ return libraries
+
+
+class MacPrefixHeader(object):
+ """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature.
+
+ This feature consists of several pieces:
+ * If GCC_PREFIX_HEADER is present, all compilations in that project get an
+ additional |-include path_to_prefix_header| cflag.
+ * If GCC_PRECOMPILE_PREFIX_HEADER is present too, then the prefix header is
+ instead compiled, and all other compilations in the project get an
+ additional |-include path_to_compiled_header| instead.
+ + Compiled prefix headers have the extension gch. There is one gch file for
+ every language used in the project (c, cc, m, mm), since gch files for
+ different languages aren't compatible.
+ + gch files themselves are built with the target's normal cflags, but they
+ obviously don't get the |-include| flag. Instead, they need a -x flag that
+ describes their language.
+ + All o files in the target need to depend on the gch file, to make sure
+ it's built before any o file is built.
+
+ This class helps with some of these tasks, but it needs help from the build
+ system for writing dependencies to the gch files, for writing build commands
+ for the gch files, and for figuring out the location of the gch files.
+ """
+ def __init__(self, xcode_settings,
+ gyp_path_to_build_path, gyp_path_to_build_output):
+ """If xcode_settings is None, all methods on this class are no-ops.
+
+ Args:
+ gyp_path_to_build_path: A function that takes a gyp-relative path,
+ and returns a path relative to the build directory.
+ gyp_path_to_build_output: A function that takes a gyp-relative path and
+ a language code ('c', 'cc', 'm', or 'mm'), and that returns a path
+ to where the output of precompiling that path for that language
+ should be placed (without the trailing '.gch').
+ """
+ # This doesn't support per-configuration prefix headers. Good enough
+ # for now.
+ self.header = None
+ self.compile_headers = False
+ if xcode_settings:
+ self.header = xcode_settings.GetPerTargetSetting('GCC_PREFIX_HEADER')
+ self.compile_headers = xcode_settings.GetPerTargetSetting(
+ 'GCC_PRECOMPILE_PREFIX_HEADER', default='NO') != 'NO'
+ self.compiled_headers = {}
+ if self.header:
+ if self.compile_headers:
+ for lang in ['c', 'cc', 'm', 'mm']:
+ self.compiled_headers[lang] = gyp_path_to_build_output(
+ self.header, lang)
+ self.header = gyp_path_to_build_path(self.header)
+
+ def _CompiledHeader(self, lang, arch):
+ assert self.compile_headers
+ h = self.compiled_headers[lang]
+ if arch:
+ h += '.' + arch
+ return h
+
+ def GetInclude(self, lang, arch=None):
+ """Gets the cflags to include the prefix header for language |lang|."""
+ if self.compile_headers and lang in self.compiled_headers:
+ return '-include %s' % self._CompiledHeader(lang, arch)
+ elif self.header:
+ return '-include %s' % self.header
+ else:
+ return ''
+
+ def _Gch(self, lang, arch):
+ """Returns the actual file name of the prefix header for language |lang|."""
+ assert self.compile_headers
+ return self._CompiledHeader(lang, arch) + '.gch'
+
+ def GetObjDependencies(self, sources, objs, arch=None):
+ """Given a list of source files and the corresponding object files, returns
+ a list of (source, object, gch) tuples, where |gch| is the build-directory
+ relative path to the gch file each object file depends on. |compilable[i]|
+ has to be the source file belonging to |objs[i]|."""
+ if not self.header or not self.compile_headers:
+ return []
+
+ result = []
+ for source, obj in zip(sources, objs):
+ ext = os.path.splitext(source)[1]
+ lang = {
+ '.c': 'c',
+ '.cpp': 'cc', '.cc': 'cc', '.cxx': 'cc',
+ '.m': 'm',
+ '.mm': 'mm',
+ }.get(ext, None)
+ if lang:
+ result.append((source, obj, self._Gch(lang, arch)))
+ return result
+
+ def GetPchBuildCommands(self, arch=None):
+ """Returns [(path_to_gch, language_flag, language, header)].
+ |path_to_gch| and |header| are relative to the build directory.
+ """
+ if not self.header or not self.compile_headers:
+ return []
+ return [
+ (self._Gch('c', arch), '-x c-header', 'c', self.header),
+ (self._Gch('cc', arch), '-x c++-header', 'cc', self.header),
+ (self._Gch('m', arch), '-x objective-c-header', 'm', self.header),
+ (self._Gch('mm', arch), '-x objective-c++-header', 'mm', self.header),
+ ]
+
+
+def MergeGlobalXcodeSettingsToSpec(global_dict, spec):
+ """Merges the global xcode_settings dictionary into each configuration of the
+ target represented by spec. For keys that are both in the global and the local
+ xcode_settings dict, the local key gets precendence.
+ """
+ # The xcode generator special-cases global xcode_settings and does something
+ # that amounts to merging in the global xcode_settings into each local
+ # xcode_settings dict.
+ global_xcode_settings = global_dict.get('xcode_settings', {})
+ for config in spec['configurations'].values():
+ if 'xcode_settings' in config:
+ new_settings = global_xcode_settings.copy()
+ new_settings.update(config['xcode_settings'])
+ config['xcode_settings'] = new_settings
+
+
+def IsMacBundle(flavor, spec):
+ """Returns if |spec| should be treated as a bundle.
+
+ Bundles are directories with a certain subdirectory structure, instead of
+ just a single file. Bundle rules do not produce a binary but also package
+ resources into that directory."""
+ is_mac_bundle = (int(spec.get('mac_bundle', 0)) != 0 and flavor == 'mac')
+ if is_mac_bundle:
+ assert spec['type'] != 'none', (
+ 'mac_bundle targets cannot have type none (target "%s")' %
+ spec['target_name'])
+ return is_mac_bundle
+
+
+def GetMacBundleResources(product_dir, xcode_settings, resources):
+ """Yields (output, resource) pairs for every resource in |resources|.
+ Only call this for mac bundle targets.
+
+ Args:
+ product_dir: Path to the directory containing the output bundle,
+ relative to the build directory.
+ xcode_settings: The XcodeSettings of the current target.
+ resources: A list of bundle resources, relative to the build directory.
+ """
+ dest = os.path.join(product_dir,
+ xcode_settings.GetBundleResourceFolder())
+ for res in resources:
+ output = dest
+
+ # The make generator doesn't support it, so forbid it everywhere
+ # to keep the generators more interchangable.
+ assert ' ' not in res, (
+ "Spaces in resource filenames not supported (%s)" % res)
+
+ # Split into (path,file).
+ res_parts = os.path.split(res)
+
+ # Now split the path into (prefix,maybe.lproj).
+ lproj_parts = os.path.split(res_parts[0])
+ # If the resource lives in a .lproj bundle, add that to the destination.
+ if lproj_parts[1].endswith('.lproj'):
+ output = os.path.join(output, lproj_parts[1])
+
+ output = os.path.join(output, res_parts[1])
+ # Compiled XIB files are referred to by .nib.
+ if output.endswith('.xib'):
+ output = output[0:-3] + 'nib'
+
+ yield output, res
+
+
+def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path):
+ """Returns (info_plist, dest_plist, defines, extra_env), where:
+ * |info_plist| is the source plist path, relative to the
+ build directory,
+ * |dest_plist| is the destination plist path, relative to the
+ build directory,
+ * |defines| is a list of preprocessor defines (empty if the plist
+ shouldn't be preprocessed,
+ * |extra_env| is a dict of env variables that should be exported when
+ invoking |mac_tool copy-info-plist|.
+
+ Only call this for mac bundle targets.
+
+ Args:
+ product_dir: Path to the directory containing the output bundle,
+ relative to the build directory.
+ xcode_settings: The XcodeSettings of the current target.
+ gyp_to_build_path: A function that converts paths relative to the
+ current gyp file to paths relative to the build direcotry.
+ """
+ info_plist = xcode_settings.GetPerTargetSetting('INFOPLIST_FILE')
+ if not info_plist:
+ return None, None, [], {}
+
+ # The make generator doesn't support it, so forbid it everywhere
+ # to keep the generators more interchangable.
+ assert ' ' not in info_plist, (
+ "Spaces in Info.plist filenames not supported (%s)" % info_plist)
+
+ info_plist = gyp_path_to_build_path(info_plist)
+
+ # If explicitly set to preprocess the plist, invoke the C preprocessor and
+ # specify any defines as -D flags.
+ if xcode_settings.GetPerTargetSetting(
+ 'INFOPLIST_PREPROCESS', default='NO') == 'YES':
+ # Create an intermediate file based on the path.
+ defines = shlex.split(xcode_settings.GetPerTargetSetting(
+ 'INFOPLIST_PREPROCESSOR_DEFINITIONS', default=''))
+ else:
+ defines = []
+
+ dest_plist = os.path.join(product_dir, xcode_settings.GetBundlePlistPath())
+ extra_env = xcode_settings.GetPerTargetSettings()
+
+ return info_plist, dest_plist, defines, extra_env
+
+
+def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration,
+ additional_settings=None):
+ """Return the environment variables that Xcode would set. See
+ http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW153
+ for a full list.
+
+ Args:
+ xcode_settings: An XcodeSettings object. If this is None, this function
+ returns an empty dict.
+ built_products_dir: Absolute path to the built products dir.
+ srcroot: Absolute path to the source root.
+ configuration: The build configuration name.
+ additional_settings: An optional dict with more values to add to the
+ result.
+ """
+ if not xcode_settings: return {}
+
+ # This function is considered a friend of XcodeSettings, so let it reach into
+ # its implementation details.
+ spec = xcode_settings.spec
+
+ # These are filled in on a as-needed basis.
+ env = {
+ 'BUILT_PRODUCTS_DIR' : built_products_dir,
+ 'CONFIGURATION' : configuration,
+ 'PRODUCT_NAME' : xcode_settings.GetProductName(),
+ # See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME
+ 'SRCROOT' : srcroot,
+ 'SOURCE_ROOT': '${SRCROOT}',
+ # This is not true for static libraries, but currently the env is only
+ # written for bundles:
+ 'TARGET_BUILD_DIR' : built_products_dir,
+ 'TEMP_DIR' : '${TMPDIR}',
+ }
+ if xcode_settings.GetPerTargetSetting('SDKROOT'):
+ env['SDKROOT'] = xcode_settings._SdkPath()
+ else:
+ env['SDKROOT'] = ''
+
+ if spec['type'] in (
+ 'executable', 'static_library', 'shared_library', 'loadable_module'):
+ env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName()
+ env['EXECUTABLE_PATH'] = xcode_settings.GetExecutablePath()
+ env['FULL_PRODUCT_NAME'] = xcode_settings.GetFullProductName()
+ mach_o_type = xcode_settings.GetMachOType()
+ if mach_o_type:
+ env['MACH_O_TYPE'] = mach_o_type
+ env['PRODUCT_TYPE'] = xcode_settings.GetProductType()
+ if xcode_settings._IsBundle():
+ env['CONTENTS_FOLDER_PATH'] = \
+ xcode_settings.GetBundleContentsFolderPath()
+ env['UNLOCALIZED_RESOURCES_FOLDER_PATH'] = \
+ xcode_settings.GetBundleResourceFolder()
+ env['INFOPLIST_PATH'] = xcode_settings.GetBundlePlistPath()
+ env['WRAPPER_NAME'] = xcode_settings.GetWrapperName()
+
+ install_name = xcode_settings.GetInstallName()
+ if install_name:
+ env['LD_DYLIB_INSTALL_NAME'] = install_name
+ install_name_base = xcode_settings.GetInstallNameBase()
+ if install_name_base:
+ env['DYLIB_INSTALL_NAME_BASE'] = install_name_base
+
+ if not additional_settings:
+ additional_settings = {}
+ else:
+ # Flatten lists to strings.
+ for k in additional_settings:
+ if not isinstance(additional_settings[k], str):
+ additional_settings[k] = ' '.join(additional_settings[k])
+ additional_settings.update(env)
+
+ for k in additional_settings:
+ additional_settings[k] = _NormalizeEnvVarReferences(additional_settings[k])
+
+ return additional_settings
+
+
+def _NormalizeEnvVarReferences(str):
+ """Takes a string containing variable references in the form ${FOO}, $(FOO),
+ or $FOO, and returns a string with all variable references in the form ${FOO}.
+ """
+ # $FOO -> ${FOO}
+ str = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'${\1}', str)
+
+ # $(FOO) -> ${FOO}
+ matches = re.findall(r'(\$\(([a-zA-Z0-9\-_]+)\))', str)
+ for match in matches:
+ to_replace, variable = match
+ assert '$(' not in match, '$($(FOO)) variables not supported: ' + match
+ str = str.replace(to_replace, '${' + variable + '}')
+
+ return str
+
+
+def ExpandEnvVars(string, expansions):
+ """Expands ${VARIABLES}, $(VARIABLES), and $VARIABLES in string per the
+ expansions list. If the variable expands to something that references
+ another variable, this variable is expanded as well if it's in env --
+ until no variables present in env are left."""
+ for k, v in reversed(expansions):
+ string = string.replace('${' + k + '}', v)
+ string = string.replace('$(' + k + ')', v)
+ string = string.replace('$' + k, v)
+ return string
+
+
+def _TopologicallySortedEnvVarKeys(env):
+ """Takes a dict |env| whose values are strings that can refer to other keys,
+ for example env['foo'] = '$(bar) and $(baz)'. Returns a list L of all keys of
+ env such that key2 is after key1 in L if env[key2] refers to env[key1].
+
+ Throws an Exception in case of dependency cycles.
+ """
+ # Since environment variables can refer to other variables, the evaluation
+ # order is important. Below is the logic to compute the dependency graph
+ # and sort it.
+ regex = re.compile(r'\$\{([a-zA-Z0-9\-_]+)\}')
+ def GetEdges(node):
+ # Use a definition of edges such that user_of_variable -> used_varible.
+ # This happens to be easier in this case, since a variable's
+ # definition contains all variables it references in a single string.
+ # We can then reverse the result of the topological sort at the end.
+ # Since: reverse(topsort(DAG)) = topsort(reverse_edges(DAG))
+ matches = set([v for v in regex.findall(env[node]) if v in env])
+ for dependee in matches:
+ assert '${' not in dependee, 'Nested variables not supported: ' + dependee
+ return matches
+
+ try:
+ # Topologically sort, and then reverse, because we used an edge definition
+ # that's inverted from the expected result of this function (see comment
+ # above).
+ order = gyp.common.TopologicallySorted(env.keys(), GetEdges)
+ order.reverse()
+ return order
+ except gyp.common.CycleError, e:
+ raise GypError(
+ 'Xcode environment variables are cyclically dependent: ' + str(e.nodes))
+
+
+def GetSortedXcodeEnv(xcode_settings, built_products_dir, srcroot,
+ configuration, additional_settings=None):
+ env = _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration,
+ additional_settings)
+ return [(key, env[key]) for key in _TopologicallySortedEnvVarKeys(env)]
+
+
+def GetSpecPostbuildCommands(spec, quiet=False):
+ """Returns the list of postbuilds explicitly defined on |spec|, in a form
+ executable by a shell."""
+ postbuilds = []
+ for postbuild in spec.get('postbuilds', []):
+ if not quiet:
+ postbuilds.append('echo POSTBUILD\\(%s\\) %s' % (
+ spec['target_name'], postbuild['postbuild_name']))
+ postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild['action']))
+ return postbuilds
diff --git a/chromium/tools/gyp/pylib/gyp/xcodeproj_file.py b/chromium/tools/gyp/pylib/gyp/xcodeproj_file.py
new file mode 100644
index 00000000000..47712a7f6e0
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/xcodeproj_file.py
@@ -0,0 +1,2870 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Xcode project file generator.
+
+This module is both an Xcode project file generator and a documentation of the
+Xcode project file format. Knowledge of the project file format was gained
+based on extensive experience with Xcode, and by making changes to projects in
+Xcode.app and observing the resultant changes in the associated project files.
+
+XCODE PROJECT FILES
+
+The generator targets the file format as written by Xcode 3.2 (specifically,
+3.2.6), but past experience has taught that the format has not changed
+significantly in the past several years, and future versions of Xcode are able
+to read older project files.
+
+Xcode project files are "bundled": the project "file" from an end-user's
+perspective is actually a directory with an ".xcodeproj" extension. The
+project file from this module's perspective is actually a file inside this
+directory, always named "project.pbxproj". This file contains a complete
+description of the project and is all that is needed to use the xcodeproj.
+Other files contained in the xcodeproj directory are simply used to store
+per-user settings, such as the state of various UI elements in the Xcode
+application.
+
+The project.pbxproj file is a property list, stored in a format almost
+identical to the NeXTstep property list format. The file is able to carry
+Unicode data, and is encoded in UTF-8. The root element in the property list
+is a dictionary that contains several properties of minimal interest, and two
+properties of immense interest. The most important property is a dictionary
+named "objects". The entire structure of the project is represented by the
+children of this property. The objects dictionary is keyed by unique 96-bit
+values represented by 24 uppercase hexadecimal characters. Each value in the
+objects dictionary is itself a dictionary, describing an individual object.
+
+Each object in the dictionary is a member of a class, which is identified by
+the "isa" property of each object. A variety of classes are represented in a
+project file. Objects can refer to other objects by ID, using the 24-character
+hexadecimal object key. A project's objects form a tree, with a root object
+of class PBXProject at the root. As an example, the PBXProject object serves
+as parent to an XCConfigurationList object defining the build configurations
+used in the project, a PBXGroup object serving as a container for all files
+referenced in the project, and a list of target objects, each of which defines
+a target in the project. There are several different types of target object,
+such as PBXNativeTarget and PBXAggregateTarget. In this module, this
+relationship is expressed by having each target type derive from an abstract
+base named XCTarget.
+
+The project.pbxproj file's root dictionary also contains a property, sibling to
+the "objects" dictionary, named "rootObject". The value of rootObject is a
+24-character object key referring to the root PBXProject object in the
+objects dictionary.
+
+In Xcode, every file used as input to a target or produced as a final product
+of a target must appear somewhere in the hierarchy rooted at the PBXGroup
+object referenced by the PBXProject's mainGroup property. A PBXGroup is
+generally represented as a folder in the Xcode application. PBXGroups can
+contain other PBXGroups as well as PBXFileReferences, which are pointers to
+actual files.
+
+Each XCTarget contains a list of build phases, represented in this module by
+the abstract base XCBuildPhase. Examples of concrete XCBuildPhase derivations
+are PBXSourcesBuildPhase and PBXFrameworksBuildPhase, which correspond to the
+"Compile Sources" and "Link Binary With Libraries" phases displayed in the
+Xcode application. Files used as input to these phases (for example, source
+files in the former case and libraries and frameworks in the latter) are
+represented by PBXBuildFile objects, referenced by elements of "files" lists
+in XCTarget objects. Each PBXBuildFile object refers to a PBXBuildFile
+object as a "weak" reference: it does not "own" the PBXBuildFile, which is
+owned by the root object's mainGroup or a descendant group. In most cases, the
+layer of indirection between an XCBuildPhase and a PBXFileReference via a
+PBXBuildFile appears extraneous, but there's actually one reason for this:
+file-specific compiler flags are added to the PBXBuildFile object so as to
+allow a single file to be a member of multiple targets while having distinct
+compiler flags for each. These flags can be modified in the Xcode applciation
+in the "Build" tab of a File Info window.
+
+When a project is open in the Xcode application, Xcode will rewrite it. As
+such, this module is careful to adhere to the formatting used by Xcode, to
+avoid insignificant changes appearing in the file when it is used in the
+Xcode application. This will keep version control repositories happy, and
+makes it possible to compare a project file used in Xcode to one generated by
+this module to determine if any significant changes were made in the
+application.
+
+Xcode has its own way of assigning 24-character identifiers to each object,
+which is not duplicated here. Because the identifier only is only generated
+once, when an object is created, and is then left unchanged, there is no need
+to attempt to duplicate Xcode's behavior in this area. The generator is free
+to select any identifier, even at random, to refer to the objects it creates,
+and Xcode will retain those identifiers and use them when subsequently
+rewriting the project file. However, the generator would choose new random
+identifiers each time the project files are generated, leading to difficulties
+comparing "used" project files to "pristine" ones produced by this module,
+and causing the appearance of changes as every object identifier is changed
+when updated projects are checked in to a version control repository. To
+mitigate this problem, this module chooses identifiers in a more deterministic
+way, by hashing a description of each object as well as its parent and ancestor
+objects. This strategy should result in minimal "shift" in IDs as successive
+generations of project files are produced.
+
+THIS MODULE
+
+This module introduces several classes, all derived from the XCObject class.
+Nearly all of the "brains" are built into the XCObject class, which understands
+how to create and modify objects, maintain the proper tree structure, compute
+identifiers, and print objects. For the most part, classes derived from
+XCObject need only provide a _schema class object, a dictionary that
+expresses what properties objects of the class may contain.
+
+Given this structure, it's possible to build a minimal project file by creating
+objects of the appropriate types and making the proper connections:
+
+ config_list = XCConfigurationList()
+ group = PBXGroup()
+ project = PBXProject({'buildConfigurationList': config_list,
+ 'mainGroup': group})
+
+With the project object set up, it can be added to an XCProjectFile object.
+XCProjectFile is a pseudo-class in the sense that it is a concrete XCObject
+subclass that does not actually correspond to a class type found in a project
+file. Rather, it is used to represent the project file's root dictionary.
+Printing an XCProjectFile will print the entire project file, including the
+full "objects" dictionary.
+
+ project_file = XCProjectFile({'rootObject': project})
+ project_file.ComputeIDs()
+ project_file.Print()
+
+Xcode project files are always encoded in UTF-8. This module will accept
+strings of either the str class or the unicode class. Strings of class str
+are assumed to already be encoded in UTF-8. Obviously, if you're just using
+ASCII, you won't encounter difficulties because ASCII is a UTF-8 subset.
+Strings of class unicode are handled properly and encoded in UTF-8 when
+a project file is output.
+"""
+
+import gyp.common
+import posixpath
+import re
+import struct
+import sys
+
+# hashlib is supplied as of Python 2.5 as the replacement interface for sha
+# and other secure hashes. In 2.6, sha is deprecated. Import hashlib if
+# available, avoiding a deprecation warning under 2.6. Import sha otherwise,
+# preserving 2.4 compatibility.
+try:
+ import hashlib
+ _new_sha1 = hashlib.sha1
+except ImportError:
+ import sha
+ _new_sha1 = sha.new
+
+
+# See XCObject._EncodeString. This pattern is used to determine when a string
+# can be printed unquoted. Strings that match this pattern may be printed
+# unquoted. Strings that do not match must be quoted and may be further
+# transformed to be properly encoded. Note that this expression matches the
+# characters listed with "+", for 1 or more occurrences: if a string is empty,
+# it must not match this pattern, because it needs to be encoded as "".
+_unquoted = re.compile('^[A-Za-z0-9$./_]+$')
+
+# Strings that match this pattern are quoted regardless of what _unquoted says.
+# Oddly, Xcode will quote any string with a run of three or more underscores.
+_quoted = re.compile('___')
+
+# This pattern should match any character that needs to be escaped by
+# XCObject._EncodeString. See that function.
+_escaped = re.compile('[\\\\"]|[^ -~]')
+
+
+# Used by SourceTreeAndPathFromPath
+_path_leading_variable = re.compile('^\$\((.*?)\)(/(.*))?$')
+
+def SourceTreeAndPathFromPath(input_path):
+ """Given input_path, returns a tuple with sourceTree and path values.
+
+ Examples:
+ input_path (source_tree, output_path)
+ '$(VAR)/path' ('VAR', 'path')
+ '$(VAR)' ('VAR', None)
+ 'path' (None, 'path')
+ """
+
+ source_group_match = _path_leading_variable.match(input_path)
+ if source_group_match:
+ source_tree = source_group_match.group(1)
+ output_path = source_group_match.group(3) # This may be None.
+ else:
+ source_tree = None
+ output_path = input_path
+
+ return (source_tree, output_path)
+
+def ConvertVariablesToShellSyntax(input_string):
+ return re.sub('\$\((.*?)\)', '${\\1}', input_string)
+
+class XCObject(object):
+ """The abstract base of all class types used in Xcode project files.
+
+ Class variables:
+ _schema: A dictionary defining the properties of this class. The keys to
+ _schema are string property keys as used in project files. Values
+ are a list of four or five elements:
+ [ is_list, property_type, is_strong, is_required, default ]
+ is_list: True if the property described is a list, as opposed
+ to a single element.
+ property_type: The type to use as the value of the property,
+ or if is_list is True, the type to use for each
+ element of the value's list. property_type must
+ be an XCObject subclass, or one of the built-in
+ types str, int, or dict.
+ is_strong: If property_type is an XCObject subclass, is_strong
+ is True to assert that this class "owns," or serves
+ as parent, to the property value (or, if is_list is
+ True, values). is_strong must be False if
+ property_type is not an XCObject subclass.
+ is_required: True if the property is required for the class.
+ Note that is_required being True does not preclude
+ an empty string ("", in the case of property_type
+ str) or list ([], in the case of is_list True) from
+ being set for the property.
+ default: Optional. If is_requried is True, default may be set
+ to provide a default value for objects that do not supply
+ their own value. If is_required is True and default
+ is not provided, users of the class must supply their own
+ value for the property.
+ Note that although the values of the array are expressed in
+ boolean terms, subclasses provide values as integers to conserve
+ horizontal space.
+ _should_print_single_line: False in XCObject. Subclasses whose objects
+ should be written to the project file in the
+ alternate single-line format, such as
+ PBXFileReference and PBXBuildFile, should
+ set this to True.
+ _encode_transforms: Used by _EncodeString to encode unprintable characters.
+ The index into this list is the ordinal of the
+ character to transform; each value is a string
+ used to represent the character in the output. XCObject
+ provides an _encode_transforms list suitable for most
+ XCObject subclasses.
+ _alternate_encode_transforms: Provided for subclasses that wish to use
+ the alternate encoding rules. Xcode seems
+ to use these rules when printing objects in
+ single-line format. Subclasses that desire
+ this behavior should set _encode_transforms
+ to _alternate_encode_transforms.
+ _hashables: A list of XCObject subclasses that can be hashed by ComputeIDs
+ to construct this object's ID. Most classes that need custom
+ hashing behavior should do it by overriding Hashables,
+ but in some cases an object's parent may wish to push a
+ hashable value into its child, and it can do so by appending
+ to _hashables.
+ Attributes:
+ id: The object's identifier, a 24-character uppercase hexadecimal string.
+ Usually, objects being created should not set id until the entire
+ project file structure is built. At that point, UpdateIDs() should
+ be called on the root object to assign deterministic values for id to
+ each object in the tree.
+ parent: The object's parent. This is set by a parent XCObject when a child
+ object is added to it.
+ _properties: The object's property dictionary. An object's properties are
+ described by its class' _schema variable.
+ """
+
+ _schema = {}
+ _should_print_single_line = False
+
+ # See _EncodeString.
+ _encode_transforms = []
+ i = 0
+ while i < ord(' '):
+ _encode_transforms.append('\\U%04x' % i)
+ i = i + 1
+ _encode_transforms[7] = '\\a'
+ _encode_transforms[8] = '\\b'
+ _encode_transforms[9] = '\\t'
+ _encode_transforms[10] = '\\n'
+ _encode_transforms[11] = '\\v'
+ _encode_transforms[12] = '\\f'
+ _encode_transforms[13] = '\\n'
+
+ _alternate_encode_transforms = list(_encode_transforms)
+ _alternate_encode_transforms[9] = chr(9)
+ _alternate_encode_transforms[10] = chr(10)
+ _alternate_encode_transforms[11] = chr(11)
+
+ def __init__(self, properties=None, id=None, parent=None):
+ self.id = id
+ self.parent = parent
+ self._properties = {}
+ self._hashables = []
+ self._SetDefaultsFromSchema()
+ self.UpdateProperties(properties)
+
+ def __repr__(self):
+ try:
+ name = self.Name()
+ except NotImplementedError:
+ return '<%s at 0x%x>' % (self.__class__.__name__, id(self))
+ return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
+
+ def Copy(self):
+ """Make a copy of this object.
+
+ The new object will have its own copy of lists and dicts. Any XCObject
+ objects owned by this object (marked "strong") will be copied in the
+ new object, even those found in lists. If this object has any weak
+ references to other XCObjects, the same references are added to the new
+ object without making a copy.
+ """
+
+ that = self.__class__(id=self.id, parent=self.parent)
+ for key, value in self._properties.iteritems():
+ is_strong = self._schema[key][2]
+
+ if isinstance(value, XCObject):
+ if is_strong:
+ new_value = value.Copy()
+ new_value.parent = that
+ that._properties[key] = new_value
+ else:
+ that._properties[key] = value
+ elif isinstance(value, str) or isinstance(value, unicode) or \
+ isinstance(value, int):
+ that._properties[key] = value
+ elif isinstance(value, list):
+ if is_strong:
+ # If is_strong is True, each element is an XCObject, so it's safe to
+ # call Copy.
+ that._properties[key] = []
+ for item in value:
+ new_item = item.Copy()
+ new_item.parent = that
+ that._properties[key].append(new_item)
+ else:
+ that._properties[key] = value[:]
+ elif isinstance(value, dict):
+ # dicts are never strong.
+ if is_strong:
+ raise TypeError, 'Strong dict for key ' + key + ' in ' + \
+ self.__class__.__name__
+ else:
+ that._properties[key] = value.copy()
+ else:
+ raise TypeError, 'Unexpected type ' + value.__class__.__name__ + \
+ ' for key ' + key + ' in ' + self.__class__.__name__
+
+ return that
+
+ def Name(self):
+ """Return the name corresponding to an object.
+
+ Not all objects necessarily need to be nameable, and not all that do have
+ a "name" property. Override as needed.
+ """
+
+ # If the schema indicates that "name" is required, try to access the
+ # property even if it doesn't exist. This will result in a KeyError
+ # being raised for the property that should be present, which seems more
+ # appropriate than NotImplementedError in this case.
+ if 'name' in self._properties or \
+ ('name' in self._schema and self._schema['name'][3]):
+ return self._properties['name']
+
+ raise NotImplementedError, \
+ self.__class__.__name__ + ' must implement Name'
+
+ def Comment(self):
+ """Return a comment string for the object.
+
+ Most objects just use their name as the comment, but PBXProject uses
+ different values.
+
+ The returned comment is not escaped and does not have any comment marker
+ strings applied to it.
+ """
+
+ return self.Name()
+
+ def Hashables(self):
+ hashables = [self.__class__.__name__]
+
+ name = self.Name()
+ if name != None:
+ hashables.append(name)
+
+ hashables.extend(self._hashables)
+
+ return hashables
+
+ def HashablesForChild(self):
+ return None
+
+ def ComputeIDs(self, recursive=True, overwrite=True, seed_hash=None):
+ """Set "id" properties deterministically.
+
+ An object's "id" property is set based on a hash of its class type and
+ name, as well as the class type and name of all ancestor objects. As
+ such, it is only advisable to call ComputeIDs once an entire project file
+ tree is built.
+
+ If recursive is True, recurse into all descendant objects and update their
+ hashes.
+
+ If overwrite is True, any existing value set in the "id" property will be
+ replaced.
+ """
+
+ def _HashUpdate(hash, data):
+ """Update hash with data's length and contents.
+
+ If the hash were updated only with the value of data, it would be
+ possible for clowns to induce collisions by manipulating the names of
+ their objects. By adding the length, it's exceedingly less likely that
+ ID collisions will be encountered, intentionally or not.
+ """
+
+ hash.update(struct.pack('>i', len(data)))
+ hash.update(data)
+
+ if seed_hash is None:
+ seed_hash = _new_sha1()
+
+ hash = seed_hash.copy()
+
+ hashables = self.Hashables()
+ assert len(hashables) > 0
+ for hashable in hashables:
+ _HashUpdate(hash, hashable)
+
+ if recursive:
+ hashables_for_child = self.HashablesForChild()
+ if hashables_for_child is None:
+ child_hash = hash
+ else:
+ assert len(hashables_for_child) > 0
+ child_hash = seed_hash.copy()
+ for hashable in hashables_for_child:
+ _HashUpdate(child_hash, hashable)
+
+ for child in self.Children():
+ child.ComputeIDs(recursive, overwrite, child_hash)
+
+ if overwrite or self.id is None:
+ # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is
+ # is 160 bits. Instead of throwing out 64 bits of the digest, xor them
+ # into the portion that gets used.
+ assert hash.digest_size % 4 == 0
+ digest_int_count = hash.digest_size / 4
+ digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest())
+ id_ints = [0, 0, 0]
+ for index in xrange(0, digest_int_count):
+ id_ints[index % 3] ^= digest_ints[index]
+ self.id = '%08X%08X%08X' % tuple(id_ints)
+
+ def EnsureNoIDCollisions(self):
+ """Verifies that no two objects have the same ID. Checks all descendants.
+ """
+
+ ids = {}
+ descendants = self.Descendants()
+ for descendant in descendants:
+ if descendant.id in ids:
+ other = ids[descendant.id]
+ raise KeyError, \
+ 'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \
+ (descendant.id, str(descendant._properties),
+ str(other._properties), self._properties['rootObject'].Name())
+ ids[descendant.id] = descendant
+
+ def Children(self):
+ """Returns a list of all of this object's owned (strong) children."""
+
+ children = []
+ for property, attributes in self._schema.iteritems():
+ (is_list, property_type, is_strong) = attributes[0:3]
+ if is_strong and property in self._properties:
+ if not is_list:
+ children.append(self._properties[property])
+ else:
+ children.extend(self._properties[property])
+ return children
+
+ def Descendants(self):
+ """Returns a list of all of this object's descendants, including this
+ object.
+ """
+
+ children = self.Children()
+ descendants = [self]
+ for child in children:
+ descendants.extend(child.Descendants())
+ return descendants
+
+ def PBXProjectAncestor(self):
+ # The base case for recursion is defined at PBXProject.PBXProjectAncestor.
+ if self.parent:
+ return self.parent.PBXProjectAncestor()
+ return None
+
+ def _EncodeComment(self, comment):
+ """Encodes a comment to be placed in the project file output, mimicing
+ Xcode behavior.
+ """
+
+ # This mimics Xcode behavior by wrapping the comment in "/*" and "*/". If
+ # the string already contains a "*/", it is turned into "(*)/". This keeps
+ # the file writer from outputting something that would be treated as the
+ # end of a comment in the middle of something intended to be entirely a
+ # comment.
+
+ return '/* ' + comment.replace('*/', '(*)/') + ' */'
+
+ def _EncodeTransform(self, match):
+ # This function works closely with _EncodeString. It will only be called
+ # by re.sub with match.group(0) containing a character matched by the
+ # the _escaped expression.
+ char = match.group(0)
+
+ # Backslashes (\) and quotation marks (") are always replaced with a
+ # backslash-escaped version of the same. Everything else gets its
+ # replacement from the class' _encode_transforms array.
+ if char == '\\':
+ return '\\\\'
+ if char == '"':
+ return '\\"'
+ return self._encode_transforms[ord(char)]
+
+ def _EncodeString(self, value):
+ """Encodes a string to be placed in the project file output, mimicing
+ Xcode behavior.
+ """
+
+ # Use quotation marks when any character outside of the range A-Z, a-z, 0-9,
+ # $ (dollar sign), . (period), and _ (underscore) is present. Also use
+ # quotation marks to represent empty strings.
+ #
+ # Escape " (double-quote) and \ (backslash) by preceding them with a
+ # backslash.
+ #
+ # Some characters below the printable ASCII range are encoded specially:
+ # 7 ^G BEL is encoded as "\a"
+ # 8 ^H BS is encoded as "\b"
+ # 11 ^K VT is encoded as "\v"
+ # 12 ^L NP is encoded as "\f"
+ # 127 ^? DEL is passed through as-is without escaping
+ # - In PBXFileReference and PBXBuildFile objects:
+ # 9 ^I HT is passed through as-is without escaping
+ # 10 ^J NL is passed through as-is without escaping
+ # 13 ^M CR is passed through as-is without escaping
+ # - In other objects:
+ # 9 ^I HT is encoded as "\t"
+ # 10 ^J NL is encoded as "\n"
+ # 13 ^M CR is encoded as "\n" rendering it indistinguishable from
+ # 10 ^J NL
+ # All other nonprintable characters within the ASCII range (0 through 127
+ # inclusive) are encoded as "\U001f" referring to the Unicode code point in
+ # hexadecimal. For example, character 14 (^N SO) is encoded as "\U000e".
+ # Characters above the ASCII range are passed through to the output encoded
+ # as UTF-8 without any escaping. These mappings are contained in the
+ # class' _encode_transforms list.
+
+ if _unquoted.search(value) and not _quoted.search(value):
+ return value
+
+ return '"' + _escaped.sub(self._EncodeTransform, value) + '"'
+
+ def _XCPrint(self, file, tabs, line):
+ file.write('\t' * tabs + line)
+
+ def _XCPrintableValue(self, tabs, value, flatten_list=False):
+ """Returns a representation of value that may be printed in a project file,
+ mimicing Xcode's behavior.
+
+ _XCPrintableValue can handle str and int values, XCObjects (which are
+ made printable by returning their id property), and list and dict objects
+ composed of any of the above types. When printing a list or dict, and
+ _should_print_single_line is False, the tabs parameter is used to determine
+ how much to indent the lines corresponding to the items in the list or
+ dict.
+
+ If flatten_list is True, single-element lists will be transformed into
+ strings.
+ """
+
+ printable = ''
+ comment = None
+
+ if self._should_print_single_line:
+ sep = ' '
+ element_tabs = ''
+ end_tabs = ''
+ else:
+ sep = '\n'
+ element_tabs = '\t' * (tabs + 1)
+ end_tabs = '\t' * tabs
+
+ if isinstance(value, XCObject):
+ printable += value.id
+ comment = value.Comment()
+ elif isinstance(value, str):
+ printable += self._EncodeString(value)
+ elif isinstance(value, unicode):
+ printable += self._EncodeString(value.encode('utf-8'))
+ elif isinstance(value, int):
+ printable += str(value)
+ elif isinstance(value, list):
+ if flatten_list and len(value) <= 1:
+ if len(value) == 0:
+ printable += self._EncodeString('')
+ else:
+ printable += self._EncodeString(value[0])
+ else:
+ printable = '(' + sep
+ for item in value:
+ printable += element_tabs + \
+ self._XCPrintableValue(tabs + 1, item, flatten_list) + \
+ ',' + sep
+ printable += end_tabs + ')'
+ elif isinstance(value, dict):
+ printable = '{' + sep
+ for item_key, item_value in sorted(value.iteritems()):
+ printable += element_tabs + \
+ self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \
+ self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \
+ sep
+ printable += end_tabs + '}'
+ else:
+ raise TypeError, "Can't make " + value.__class__.__name__ + ' printable'
+
+ if comment != None:
+ printable += ' ' + self._EncodeComment(comment)
+
+ return printable
+
+ def _XCKVPrint(self, file, tabs, key, value):
+ """Prints a key and value, members of an XCObject's _properties dictionary,
+ to file.
+
+ tabs is an int identifying the indentation level. If the class'
+ _should_print_single_line variable is True, tabs is ignored and the
+ key-value pair will be followed by a space insead of a newline.
+ """
+
+ if self._should_print_single_line:
+ printable = ''
+ after_kv = ' '
+ else:
+ printable = '\t' * tabs
+ after_kv = '\n'
+
+ # Xcode usually prints remoteGlobalIDString values in PBXContainerItemProxy
+ # objects without comments. Sometimes it prints them with comments, but
+ # the majority of the time, it doesn't. To avoid unnecessary changes to
+ # the project file after Xcode opens it, don't write comments for
+ # remoteGlobalIDString. This is a sucky hack and it would certainly be
+ # cleaner to extend the schema to indicate whether or not a comment should
+ # be printed, but since this is the only case where the problem occurs and
+ # Xcode itself can't seem to make up its mind, the hack will suffice.
+ #
+ # Also see PBXContainerItemProxy._schema['remoteGlobalIDString'].
+ if key == 'remoteGlobalIDString' and isinstance(self,
+ PBXContainerItemProxy):
+ value_to_print = value.id
+ else:
+ value_to_print = value
+
+ # PBXBuildFile's settings property is represented in the output as a dict,
+ # but a hack here has it represented as a string. Arrange to strip off the
+ # quotes so that it shows up in the output as expected.
+ if key == 'settings' and isinstance(self, PBXBuildFile):
+ strip_value_quotes = True
+ else:
+ strip_value_quotes = False
+
+ # In another one-off, let's set flatten_list on buildSettings properties
+ # of XCBuildConfiguration objects, because that's how Xcode treats them.
+ if key == 'buildSettings' and isinstance(self, XCBuildConfiguration):
+ flatten_list = True
+ else:
+ flatten_list = False
+
+ try:
+ printable_key = self._XCPrintableValue(tabs, key, flatten_list)
+ printable_value = self._XCPrintableValue(tabs, value_to_print,
+ flatten_list)
+ if strip_value_quotes and len(printable_value) > 1 and \
+ printable_value[0] == '"' and printable_value[-1] == '"':
+ printable_value = printable_value[1:-1]
+ printable += printable_key + ' = ' + printable_value + ';' + after_kv
+ except TypeError, e:
+ gyp.common.ExceptionAppend(e,
+ 'while printing key "%s"' % key)
+ raise
+
+ self._XCPrint(file, 0, printable)
+
+ def Print(self, file=sys.stdout):
+ """Prints a reprentation of this object to file, adhering to Xcode output
+ formatting.
+ """
+
+ self.VerifyHasRequiredProperties()
+
+ if self._should_print_single_line:
+ # When printing an object in a single line, Xcode doesn't put any space
+ # between the beginning of a dictionary (or presumably a list) and the
+ # first contained item, so you wind up with snippets like
+ # ...CDEF = {isa = PBXFileReference; fileRef = 0123...
+ # If it were me, I would have put a space in there after the opening
+ # curly, but I guess this is just another one of those inconsistencies
+ # between how Xcode prints PBXFileReference and PBXBuildFile objects as
+ # compared to other objects. Mimic Xcode's behavior here by using an
+ # empty string for sep.
+ sep = ''
+ end_tabs = 0
+ else:
+ sep = '\n'
+ end_tabs = 2
+
+ # Start the object. For example, '\t\tPBXProject = {\n'.
+ self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep)
+
+ # "isa" isn't in the _properties dictionary, it's an intrinsic property
+ # of the class which the object belongs to. Xcode always outputs "isa"
+ # as the first element of an object dictionary.
+ self._XCKVPrint(file, 3, 'isa', self.__class__.__name__)
+
+ # The remaining elements of an object dictionary are sorted alphabetically.
+ for property, value in sorted(self._properties.iteritems()):
+ self._XCKVPrint(file, 3, property, value)
+
+ # End the object.
+ self._XCPrint(file, end_tabs, '};\n')
+
+ def UpdateProperties(self, properties, do_copy=False):
+ """Merge the supplied properties into the _properties dictionary.
+
+ The input properties must adhere to the class schema or a KeyError or
+ TypeError exception will be raised. If adding an object of an XCObject
+ subclass and the schema indicates a strong relationship, the object's
+ parent will be set to this object.
+
+ If do_copy is True, then lists, dicts, strong-owned XCObjects, and
+ strong-owned XCObjects in lists will be copied instead of having their
+ references added.
+ """
+
+ if properties is None:
+ return
+
+ for property, value in properties.iteritems():
+ # Make sure the property is in the schema.
+ if not property in self._schema:
+ raise KeyError, property + ' not in ' + self.__class__.__name__
+
+ # Make sure the property conforms to the schema.
+ (is_list, property_type, is_strong) = self._schema[property][0:3]
+ if is_list:
+ if value.__class__ != list:
+ raise TypeError, \
+ property + ' of ' + self.__class__.__name__ + \
+ ' must be list, not ' + value.__class__.__name__
+ for item in value:
+ if not isinstance(item, property_type) and \
+ not (item.__class__ == unicode and property_type == str):
+ # Accept unicode where str is specified. str is treated as
+ # UTF-8-encoded.
+ raise TypeError, \
+ 'item of ' + property + ' of ' + self.__class__.__name__ + \
+ ' must be ' + property_type.__name__ + ', not ' + \
+ item.__class__.__name__
+ elif not isinstance(value, property_type) and \
+ not (value.__class__ == unicode and property_type == str):
+ # Accept unicode where str is specified. str is treated as
+ # UTF-8-encoded.
+ raise TypeError, \
+ property + ' of ' + self.__class__.__name__ + ' must be ' + \
+ property_type.__name__ + ', not ' + value.__class__.__name__
+
+ # Checks passed, perform the assignment.
+ if do_copy:
+ if isinstance(value, XCObject):
+ if is_strong:
+ self._properties[property] = value.Copy()
+ else:
+ self._properties[property] = value
+ elif isinstance(value, str) or isinstance(value, unicode) or \
+ isinstance(value, int):
+ self._properties[property] = value
+ elif isinstance(value, list):
+ if is_strong:
+ # If is_strong is True, each element is an XCObject, so it's safe
+ # to call Copy.
+ self._properties[property] = []
+ for item in value:
+ self._properties[property].append(item.Copy())
+ else:
+ self._properties[property] = value[:]
+ elif isinstance(value, dict):
+ self._properties[property] = value.copy()
+ else:
+ raise TypeError, "Don't know how to copy a " + \
+ value.__class__.__name__ + ' object for ' + \
+ property + ' in ' + self.__class__.__name__
+ else:
+ self._properties[property] = value
+
+ # Set up the child's back-reference to this object. Don't use |value|
+ # any more because it may not be right if do_copy is true.
+ if is_strong:
+ if not is_list:
+ self._properties[property].parent = self
+ else:
+ for item in self._properties[property]:
+ item.parent = self
+
+ def HasProperty(self, key):
+ return key in self._properties
+
+ def GetProperty(self, key):
+ return self._properties[key]
+
+ def SetProperty(self, key, value):
+ self.UpdateProperties({key: value})
+
+ def DelProperty(self, key):
+ if key in self._properties:
+ del self._properties[key]
+
+ def AppendProperty(self, key, value):
+ # TODO(mark): Support ExtendProperty too (and make this call that)?
+
+ # Schema validation.
+ if not key in self._schema:
+ raise KeyError, key + ' not in ' + self.__class__.__name__
+
+ (is_list, property_type, is_strong) = self._schema[key][0:3]
+ if not is_list:
+ raise TypeError, key + ' of ' + self.__class__.__name__ + ' must be list'
+ if not isinstance(value, property_type):
+ raise TypeError, 'item of ' + key + ' of ' + self.__class__.__name__ + \
+ ' must be ' + property_type.__name__ + ', not ' + \
+ value.__class__.__name__
+
+ # If the property doesn't exist yet, create a new empty list to receive the
+ # item.
+ if not key in self._properties:
+ self._properties[key] = []
+
+ # Set up the ownership link.
+ if is_strong:
+ value.parent = self
+
+ # Store the item.
+ self._properties[key].append(value)
+
+ def VerifyHasRequiredProperties(self):
+ """Ensure that all properties identified as required by the schema are
+ set.
+ """
+
+ # TODO(mark): A stronger verification mechanism is needed. Some
+ # subclasses need to perform validation beyond what the schema can enforce.
+ for property, attributes in self._schema.iteritems():
+ (is_list, property_type, is_strong, is_required) = attributes[0:4]
+ if is_required and not property in self._properties:
+ raise KeyError, self.__class__.__name__ + ' requires ' + property
+
+ def _SetDefaultsFromSchema(self):
+ """Assign object default values according to the schema. This will not
+ overwrite properties that have already been set."""
+
+ defaults = {}
+ for property, attributes in self._schema.iteritems():
+ (is_list, property_type, is_strong, is_required) = attributes[0:4]
+ if is_required and len(attributes) >= 5 and \
+ not property in self._properties:
+ default = attributes[4]
+
+ defaults[property] = default
+
+ if len(defaults) > 0:
+ # Use do_copy=True so that each new object gets its own copy of strong
+ # objects, lists, and dicts.
+ self.UpdateProperties(defaults, do_copy=True)
+
+
+class XCHierarchicalElement(XCObject):
+ """Abstract base for PBXGroup and PBXFileReference. Not represented in a
+ project file."""
+
+ # TODO(mark): Do name and path belong here? Probably so.
+ # If path is set and name is not, name may have a default value. Name will
+ # be set to the basename of path, if the basename of path is different from
+ # the full value of path. If path is already just a leaf name, name will
+ # not be set.
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'comments': [0, str, 0, 0],
+ 'fileEncoding': [0, str, 0, 0],
+ 'includeInIndex': [0, int, 0, 0],
+ 'indentWidth': [0, int, 0, 0],
+ 'lineEnding': [0, int, 0, 0],
+ 'sourceTree': [0, str, 0, 1, '<group>'],
+ 'tabWidth': [0, int, 0, 0],
+ 'usesTabs': [0, int, 0, 0],
+ 'wrapsLines': [0, int, 0, 0],
+ })
+
+ def __init__(self, properties=None, id=None, parent=None):
+ # super
+ XCObject.__init__(self, properties, id, parent)
+ if 'path' in self._properties and not 'name' in self._properties:
+ path = self._properties['path']
+ name = posixpath.basename(path)
+ if name != '' and path != name:
+ self.SetProperty('name', name)
+
+ if 'path' in self._properties and \
+ (not 'sourceTree' in self._properties or \
+ self._properties['sourceTree'] == '<group>'):
+ # If the pathname begins with an Xcode variable like "$(SDKROOT)/", take
+ # the variable out and make the path be relative to that variable by
+ # assigning the variable name as the sourceTree.
+ (source_tree, path) = SourceTreeAndPathFromPath(self._properties['path'])
+ if source_tree != None:
+ self._properties['sourceTree'] = source_tree
+ if path != None:
+ self._properties['path'] = path
+ if source_tree != None and path is None and \
+ not 'name' in self._properties:
+ # The path was of the form "$(SDKROOT)" with no path following it.
+ # This object is now relative to that variable, so it has no path
+ # attribute of its own. It does, however, keep a name.
+ del self._properties['path']
+ self._properties['name'] = source_tree
+
+ def Name(self):
+ if 'name' in self._properties:
+ return self._properties['name']
+ elif 'path' in self._properties:
+ return self._properties['path']
+ else:
+ # This happens in the case of the root PBXGroup.
+ return None
+
+ def Hashables(self):
+ """Custom hashables for XCHierarchicalElements.
+
+ XCHierarchicalElements are special. Generally, their hashes shouldn't
+ change if the paths don't change. The normal XCObject implementation of
+ Hashables adds a hashable for each object, which means that if
+ the hierarchical structure changes (possibly due to changes caused when
+ TakeOverOnlyChild runs and encounters slight changes in the hierarchy),
+ the hashes will change. For example, if a project file initially contains
+ a/b/f1 and a/b becomes collapsed into a/b, f1 will have a single parent
+ a/b. If someone later adds a/f2 to the project file, a/b can no longer be
+ collapsed, and f1 winds up with parent b and grandparent a. That would
+ be sufficient to change f1's hash.
+
+ To counteract this problem, hashables for all XCHierarchicalElements except
+ for the main group (which has neither a name nor a path) are taken to be
+ just the set of path components. Because hashables are inherited from
+ parents, this provides assurance that a/b/f1 has the same set of hashables
+ whether its parent is b or a/b.
+
+ The main group is a special case. As it is permitted to have no name or
+ path, it is permitted to use the standard XCObject hash mechanism. This
+ is not considered a problem because there can be only one main group.
+ """
+
+ if self == self.PBXProjectAncestor()._properties['mainGroup']:
+ # super
+ return XCObject.Hashables(self)
+
+ hashables = []
+
+ # Put the name in first, ensuring that if TakeOverOnlyChild collapses
+ # children into a top-level group like "Source", the name always goes
+ # into the list of hashables without interfering with path components.
+ if 'name' in self._properties:
+ # Make it less likely for people to manipulate hashes by following the
+ # pattern of always pushing an object type value onto the list first.
+ hashables.append(self.__class__.__name__ + '.name')
+ hashables.append(self._properties['name'])
+
+ # NOTE: This still has the problem that if an absolute path is encountered,
+ # including paths with a sourceTree, they'll still inherit their parents'
+ # hashables, even though the paths aren't relative to their parents. This
+ # is not expected to be much of a problem in practice.
+ path = self.PathFromSourceTreeAndPath()
+ if path != None:
+ components = path.split(posixpath.sep)
+ for component in components:
+ hashables.append(self.__class__.__name__ + '.path')
+ hashables.append(component)
+
+ hashables.extend(self._hashables)
+
+ return hashables
+
+ def Compare(self, other):
+ # Allow comparison of these types. PBXGroup has the highest sort rank;
+ # PBXVariantGroup is treated as equal to PBXFileReference.
+ valid_class_types = {
+ PBXFileReference: 'file',
+ PBXGroup: 'group',
+ PBXVariantGroup: 'file',
+ }
+ self_type = valid_class_types[self.__class__]
+ other_type = valid_class_types[other.__class__]
+
+ if self_type == other_type:
+ # If the two objects are of the same sort rank, compare their names.
+ return cmp(self.Name(), other.Name())
+
+ # Otherwise, sort groups before everything else.
+ if self_type == 'group':
+ return -1
+ return 1
+
+ def CompareRootGroup(self, other):
+ # This function should be used only to compare direct children of the
+ # containing PBXProject's mainGroup. These groups should appear in the
+ # listed order.
+ # TODO(mark): "Build" is used by gyp.generator.xcode, perhaps the
+ # generator should have a way of influencing this list rather than having
+ # to hardcode for the generator here.
+ order = ['Source', 'Intermediates', 'Projects', 'Frameworks', 'Products',
+ 'Build']
+
+ # If the groups aren't in the listed order, do a name comparison.
+ # Otherwise, groups in the listed order should come before those that
+ # aren't.
+ self_name = self.Name()
+ other_name = other.Name()
+ self_in = isinstance(self, PBXGroup) and self_name in order
+ other_in = isinstance(self, PBXGroup) and other_name in order
+ if not self_in and not other_in:
+ return self.Compare(other)
+ if self_name in order and not other_name in order:
+ return -1
+ if other_name in order and not self_name in order:
+ return 1
+
+ # If both groups are in the listed order, go by the defined order.
+ self_index = order.index(self_name)
+ other_index = order.index(other_name)
+ if self_index < other_index:
+ return -1
+ if self_index > other_index:
+ return 1
+ return 0
+
+ def PathFromSourceTreeAndPath(self):
+ # Turn the object's sourceTree and path properties into a single flat
+ # string of a form comparable to the path parameter. If there's a
+ # sourceTree property other than "<group>", wrap it in $(...) for the
+ # comparison.
+ components = []
+ if self._properties['sourceTree'] != '<group>':
+ components.append('$(' + self._properties['sourceTree'] + ')')
+ if 'path' in self._properties:
+ components.append(self._properties['path'])
+
+ if len(components) > 0:
+ return posixpath.join(*components)
+
+ return None
+
+ def FullPath(self):
+ # Returns a full path to self relative to the project file, or relative
+ # to some other source tree. Start with self, and walk up the chain of
+ # parents prepending their paths, if any, until no more parents are
+ # available (project-relative path) or until a path relative to some
+ # source tree is found.
+ xche = self
+ path = None
+ while isinstance(xche, XCHierarchicalElement) and \
+ (path is None or \
+ (not path.startswith('/') and not path.startswith('$'))):
+ this_path = xche.PathFromSourceTreeAndPath()
+ if this_path != None and path != None:
+ path = posixpath.join(this_path, path)
+ elif this_path != None:
+ path = this_path
+ xche = xche.parent
+
+ return path
+
+
+class PBXGroup(XCHierarchicalElement):
+ """
+ Attributes:
+ _children_by_path: Maps pathnames of children of this PBXGroup to the
+ actual child XCHierarchicalElement objects.
+ _variant_children_by_name_and_path: Maps (name, path) tuples of
+ PBXVariantGroup children to the actual child PBXVariantGroup objects.
+ """
+
+ _schema = XCHierarchicalElement._schema.copy()
+ _schema.update({
+ 'children': [1, XCHierarchicalElement, 1, 1, []],
+ 'name': [0, str, 0, 0],
+ 'path': [0, str, 0, 0],
+ })
+
+ def __init__(self, properties=None, id=None, parent=None):
+ # super
+ XCHierarchicalElement.__init__(self, properties, id, parent)
+ self._children_by_path = {}
+ self._variant_children_by_name_and_path = {}
+ for child in self._properties.get('children', []):
+ self._AddChildToDicts(child)
+
+ def Hashables(self):
+ # super
+ hashables = XCHierarchicalElement.Hashables(self)
+
+ # It is not sufficient to just rely on name and parent to build a unique
+ # hashable : a node could have two child PBXGroup sharing a common name.
+ # To add entropy the hashable is enhanced with the names of all its
+ # children.
+ for child in self._properties.get('children', []):
+ child_name = child.Name()
+ if child_name != None:
+ hashables.append(child_name)
+
+ return hashables
+
+ def HashablesForChild(self):
+ # To avoid a circular reference the hashables used to compute a child id do
+ # not include the child names.
+ return XCHierarchicalElement.Hashables(self)
+
+ def _AddChildToDicts(self, child):
+ # Sets up this PBXGroup object's dicts to reference the child properly.
+ child_path = child.PathFromSourceTreeAndPath()
+ if child_path:
+ if child_path in self._children_by_path:
+ raise ValueError, 'Found multiple children with path ' + child_path
+ self._children_by_path[child_path] = child
+
+ if isinstance(child, PBXVariantGroup):
+ child_name = child._properties.get('name', None)
+ key = (child_name, child_path)
+ if key in self._variant_children_by_name_and_path:
+ raise ValueError, 'Found multiple PBXVariantGroup children with ' + \
+ 'name ' + str(child_name) + ' and path ' + \
+ str(child_path)
+ self._variant_children_by_name_and_path[key] = child
+
+ def AppendChild(self, child):
+ # Callers should use this instead of calling
+ # AppendProperty('children', child) directly because this function
+ # maintains the group's dicts.
+ self.AppendProperty('children', child)
+ self._AddChildToDicts(child)
+
+ def GetChildByName(self, name):
+ # This is not currently optimized with a dict as GetChildByPath is because
+ # it has few callers. Most callers probably want GetChildByPath. This
+ # function is only useful to get children that have names but no paths,
+ # which is rare. The children of the main group ("Source", "Products",
+ # etc.) is pretty much the only case where this likely to come up.
+ #
+ # TODO(mark): Maybe this should raise an error if more than one child is
+ # present with the same name.
+ if not 'children' in self._properties:
+ return None
+
+ for child in self._properties['children']:
+ if child.Name() == name:
+ return child
+
+ return None
+
+ def GetChildByPath(self, path):
+ if not path:
+ return None
+
+ if path in self._children_by_path:
+ return self._children_by_path[path]
+
+ return None
+
+ def GetChildByRemoteObject(self, remote_object):
+ # This method is a little bit esoteric. Given a remote_object, which
+ # should be a PBXFileReference in another project file, this method will
+ # return this group's PBXReferenceProxy object serving as a local proxy
+ # for the remote PBXFileReference.
+ #
+ # This function might benefit from a dict optimization as GetChildByPath
+ # for some workloads, but profiling shows that it's not currently a
+ # problem.
+ if not 'children' in self._properties:
+ return None
+
+ for child in self._properties['children']:
+ if not isinstance(child, PBXReferenceProxy):
+ continue
+
+ container_proxy = child._properties['remoteRef']
+ if container_proxy._properties['remoteGlobalIDString'] == remote_object:
+ return child
+
+ return None
+
+ def AddOrGetFileByPath(self, path, hierarchical):
+ """Returns an existing or new file reference corresponding to path.
+
+ If hierarchical is True, this method will create or use the necessary
+ hierarchical group structure corresponding to path. Otherwise, it will
+ look in and create an item in the current group only.
+
+ If an existing matching reference is found, it is returned, otherwise, a
+ new one will be created, added to the correct group, and returned.
+
+ If path identifies a directory by virtue of carrying a trailing slash,
+ this method returns a PBXFileReference of "folder" type. If path
+ identifies a variant, by virtue of it identifying a file inside a directory
+ with an ".lproj" extension, this method returns a PBXVariantGroup
+ containing the variant named by path, and possibly other variants. For
+ all other paths, a "normal" PBXFileReference will be returned.
+ """
+
+ # Adding or getting a directory? Directories end with a trailing slash.
+ is_dir = False
+ if path.endswith('/'):
+ is_dir = True
+ path = posixpath.normpath(path)
+ if is_dir:
+ path = path + '/'
+
+ # Adding or getting a variant? Variants are files inside directories
+ # with an ".lproj" extension. Xcode uses variants for localization. For
+ # a variant path/to/Language.lproj/MainMenu.nib, put a variant group named
+ # MainMenu.nib inside path/to, and give it a variant named Language. In
+ # this example, grandparent would be set to path/to and parent_root would
+ # be set to Language.
+ variant_name = None
+ parent = posixpath.dirname(path)
+ grandparent = posixpath.dirname(parent)
+ parent_basename = posixpath.basename(parent)
+ (parent_root, parent_ext) = posixpath.splitext(parent_basename)
+ if parent_ext == '.lproj':
+ variant_name = parent_root
+ if grandparent == '':
+ grandparent = None
+
+ # Putting a directory inside a variant group is not currently supported.
+ assert not is_dir or variant_name is None
+
+ path_split = path.split(posixpath.sep)
+ if len(path_split) == 1 or \
+ ((is_dir or variant_name != None) and len(path_split) == 2) or \
+ not hierarchical:
+ # The PBXFileReference or PBXVariantGroup will be added to or gotten from
+ # this PBXGroup, no recursion necessary.
+ if variant_name is None:
+ # Add or get a PBXFileReference.
+ file_ref = self.GetChildByPath(path)
+ if file_ref != None:
+ assert file_ref.__class__ == PBXFileReference
+ else:
+ file_ref = PBXFileReference({'path': path})
+ self.AppendChild(file_ref)
+ else:
+ # Add or get a PBXVariantGroup. The variant group name is the same
+ # as the basename (MainMenu.nib in the example above). grandparent
+ # specifies the path to the variant group itself, and path_split[-2:]
+ # is the path of the specific variant relative to its group.
+ variant_group_name = posixpath.basename(path)
+ variant_group_ref = self.AddOrGetVariantGroupByNameAndPath(
+ variant_group_name, grandparent)
+ variant_path = posixpath.sep.join(path_split[-2:])
+ variant_ref = variant_group_ref.GetChildByPath(variant_path)
+ if variant_ref != None:
+ assert variant_ref.__class__ == PBXFileReference
+ else:
+ variant_ref = PBXFileReference({'name': variant_name,
+ 'path': variant_path})
+ variant_group_ref.AppendChild(variant_ref)
+ # The caller is interested in the variant group, not the specific
+ # variant file.
+ file_ref = variant_group_ref
+ return file_ref
+ else:
+ # Hierarchical recursion. Add or get a PBXGroup corresponding to the
+ # outermost path component, and then recurse into it, chopping off that
+ # path component.
+ next_dir = path_split[0]
+ group_ref = self.GetChildByPath(next_dir)
+ if group_ref != None:
+ assert group_ref.__class__ == PBXGroup
+ else:
+ group_ref = PBXGroup({'path': next_dir})
+ self.AppendChild(group_ref)
+ return group_ref.AddOrGetFileByPath(posixpath.sep.join(path_split[1:]),
+ hierarchical)
+
+ def AddOrGetVariantGroupByNameAndPath(self, name, path):
+ """Returns an existing or new PBXVariantGroup for name and path.
+
+ If a PBXVariantGroup identified by the name and path arguments is already
+ present as a child of this object, it is returned. Otherwise, a new
+ PBXVariantGroup with the correct properties is created, added as a child,
+ and returned.
+
+ This method will generally be called by AddOrGetFileByPath, which knows
+ when to create a variant group based on the structure of the pathnames
+ passed to it.
+ """
+
+ key = (name, path)
+ if key in self._variant_children_by_name_and_path:
+ variant_group_ref = self._variant_children_by_name_and_path[key]
+ assert variant_group_ref.__class__ == PBXVariantGroup
+ return variant_group_ref
+
+ variant_group_properties = {'name': name}
+ if path != None:
+ variant_group_properties['path'] = path
+ variant_group_ref = PBXVariantGroup(variant_group_properties)
+ self.AppendChild(variant_group_ref)
+
+ return variant_group_ref
+
+ def TakeOverOnlyChild(self, recurse=False):
+ """If this PBXGroup has only one child and it's also a PBXGroup, take
+ it over by making all of its children this object's children.
+
+ This function will continue to take over only children when those children
+ are groups. If there are three PBXGroups representing a, b, and c, with
+ c inside b and b inside a, and a and b have no other children, this will
+ result in a taking over both b and c, forming a PBXGroup for a/b/c.
+
+ If recurse is True, this function will recurse into children and ask them
+ to collapse themselves by taking over only children as well. Assuming
+ an example hierarchy with files at a/b/c/d1, a/b/c/d2, and a/b/c/d3/e/f
+ (d1, d2, and f are files, the rest are groups), recursion will result in
+ a group for a/b/c containing a group for d3/e.
+ """
+
+ # At this stage, check that child class types are PBXGroup exactly,
+ # instead of using isinstance. The only subclass of PBXGroup,
+ # PBXVariantGroup, should not participate in reparenting in the same way:
+ # reparenting by merging different object types would be wrong.
+ while len(self._properties['children']) == 1 and \
+ self._properties['children'][0].__class__ == PBXGroup:
+ # Loop to take over the innermost only-child group possible.
+
+ child = self._properties['children'][0]
+
+ # Assume the child's properties, including its children. Save a copy
+ # of this object's old properties, because they'll still be needed.
+ # This object retains its existing id and parent attributes.
+ old_properties = self._properties
+ self._properties = child._properties
+ self._children_by_path = child._children_by_path
+
+ if not 'sourceTree' in self._properties or \
+ self._properties['sourceTree'] == '<group>':
+ # The child was relative to its parent. Fix up the path. Note that
+ # children with a sourceTree other than "<group>" are not relative to
+ # their parents, so no path fix-up is needed in that case.
+ if 'path' in old_properties:
+ if 'path' in self._properties:
+ # Both the original parent and child have paths set.
+ self._properties['path'] = posixpath.join(old_properties['path'],
+ self._properties['path'])
+ else:
+ # Only the original parent has a path, use it.
+ self._properties['path'] = old_properties['path']
+ if 'sourceTree' in old_properties:
+ # The original parent had a sourceTree set, use it.
+ self._properties['sourceTree'] = old_properties['sourceTree']
+
+ # If the original parent had a name set, keep using it. If the original
+ # parent didn't have a name but the child did, let the child's name
+ # live on. If the name attribute seems unnecessary now, get rid of it.
+ if 'name' in old_properties and old_properties['name'] != None and \
+ old_properties['name'] != self.Name():
+ self._properties['name'] = old_properties['name']
+ if 'name' in self._properties and 'path' in self._properties and \
+ self._properties['name'] == self._properties['path']:
+ del self._properties['name']
+
+ # Notify all children of their new parent.
+ for child in self._properties['children']:
+ child.parent = self
+
+ # If asked to recurse, recurse.
+ if recurse:
+ for child in self._properties['children']:
+ if child.__class__ == PBXGroup:
+ child.TakeOverOnlyChild(recurse)
+
+ def SortGroup(self):
+ self._properties['children'] = \
+ sorted(self._properties['children'], cmp=lambda x,y: x.Compare(y))
+
+ # Recurse.
+ for child in self._properties['children']:
+ if isinstance(child, PBXGroup):
+ child.SortGroup()
+
+
+class XCFileLikeElement(XCHierarchicalElement):
+ # Abstract base for objects that can be used as the fileRef property of
+ # PBXBuildFile.
+
+ def PathHashables(self):
+ # A PBXBuildFile that refers to this object will call this method to
+ # obtain additional hashables specific to this XCFileLikeElement. Don't
+ # just use this object's hashables, they're not specific and unique enough
+ # on their own (without access to the parent hashables.) Instead, provide
+ # hashables that identify this object by path by getting its hashables as
+ # well as the hashables of ancestor XCHierarchicalElement objects.
+
+ hashables = []
+ xche = self
+ while xche != None and isinstance(xche, XCHierarchicalElement):
+ xche_hashables = xche.Hashables()
+ for index in xrange(0, len(xche_hashables)):
+ hashables.insert(index, xche_hashables[index])
+ xche = xche.parent
+ return hashables
+
+
+class XCContainerPortal(XCObject):
+ # Abstract base for objects that can be used as the containerPortal property
+ # of PBXContainerItemProxy.
+ pass
+
+
+class XCRemoteObject(XCObject):
+ # Abstract base for objects that can be used as the remoteGlobalIDString
+ # property of PBXContainerItemProxy.
+ pass
+
+
+class PBXFileReference(XCFileLikeElement, XCContainerPortal, XCRemoteObject):
+ _schema = XCFileLikeElement._schema.copy()
+ _schema.update({
+ 'explicitFileType': [0, str, 0, 0],
+ 'lastKnownFileType': [0, str, 0, 0],
+ 'name': [0, str, 0, 0],
+ 'path': [0, str, 0, 1],
+ })
+
+ # Weird output rules for PBXFileReference.
+ _should_print_single_line = True
+ # super
+ _encode_transforms = XCFileLikeElement._alternate_encode_transforms
+
+ def __init__(self, properties=None, id=None, parent=None):
+ # super
+ XCFileLikeElement.__init__(self, properties, id, parent)
+ if 'path' in self._properties and self._properties['path'].endswith('/'):
+ self._properties['path'] = self._properties['path'][:-1]
+ is_dir = True
+ else:
+ is_dir = False
+
+ if 'path' in self._properties and \
+ not 'lastKnownFileType' in self._properties and \
+ not 'explicitFileType' in self._properties:
+ # TODO(mark): This is the replacement for a replacement for a quick hack.
+ # It is no longer incredibly sucky, but this list needs to be extended.
+ extension_map = {
+ 'a': 'archive.ar',
+ 'app': 'wrapper.application',
+ 'bdic': 'file',
+ 'bundle': 'wrapper.cfbundle',
+ 'c': 'sourcecode.c.c',
+ 'cc': 'sourcecode.cpp.cpp',
+ 'cpp': 'sourcecode.cpp.cpp',
+ 'css': 'text.css',
+ 'cxx': 'sourcecode.cpp.cpp',
+ 'dylib': 'compiled.mach-o.dylib',
+ 'framework': 'wrapper.framework',
+ 'h': 'sourcecode.c.h',
+ 'hxx': 'sourcecode.cpp.h',
+ 'icns': 'image.icns',
+ 'java': 'sourcecode.java',
+ 'js': 'sourcecode.javascript',
+ 'm': 'sourcecode.c.objc',
+ 'mm': 'sourcecode.cpp.objcpp',
+ 'nib': 'wrapper.nib',
+ 'o': 'compiled.mach-o.objfile',
+ 'pdf': 'image.pdf',
+ 'pl': 'text.script.perl',
+ 'plist': 'text.plist.xml',
+ 'pm': 'text.script.perl',
+ 'png': 'image.png',
+ 'py': 'text.script.python',
+ 'r': 'sourcecode.rez',
+ 'rez': 'sourcecode.rez',
+ 's': 'sourcecode.asm',
+ 'storyboard': 'file.storyboard',
+ 'strings': 'text.plist.strings',
+ 'ttf': 'file',
+ 'xcconfig': 'text.xcconfig',
+ 'xcdatamodel': 'wrapper.xcdatamodel',
+ 'xib': 'file.xib',
+ 'y': 'sourcecode.yacc',
+ }
+
+ if is_dir:
+ file_type = 'folder'
+ else:
+ basename = posixpath.basename(self._properties['path'])
+ (root, ext) = posixpath.splitext(basename)
+ # Check the map using a lowercase extension.
+ # TODO(mark): Maybe it should try with the original case first and fall
+ # back to lowercase, in case there are any instances where case
+ # matters. There currently aren't.
+ if ext != '':
+ ext = ext[1:].lower()
+
+ # TODO(mark): "text" is the default value, but "file" is appropriate
+ # for unrecognized files not containing text. Xcode seems to choose
+ # based on content.
+ file_type = extension_map.get(ext, 'text')
+
+ self._properties['lastKnownFileType'] = file_type
+
+
+class PBXVariantGroup(PBXGroup, XCFileLikeElement):
+ """PBXVariantGroup is used by Xcode to represent localizations."""
+ # No additions to the schema relative to PBXGroup.
+ pass
+
+
+# PBXReferenceProxy is also an XCFileLikeElement subclass. It is defined below
+# because it uses PBXContainerItemProxy, defined below.
+
+
+class XCBuildConfiguration(XCObject):
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'baseConfigurationReference': [0, PBXFileReference, 0, 0],
+ 'buildSettings': [0, dict, 0, 1, {}],
+ 'name': [0, str, 0, 1],
+ })
+
+ def HasBuildSetting(self, key):
+ return key in self._properties['buildSettings']
+
+ def GetBuildSetting(self, key):
+ return self._properties['buildSettings'][key]
+
+ def SetBuildSetting(self, key, value):
+ # TODO(mark): If a list, copy?
+ self._properties['buildSettings'][key] = value
+
+ def AppendBuildSetting(self, key, value):
+ if not key in self._properties['buildSettings']:
+ self._properties['buildSettings'][key] = []
+ self._properties['buildSettings'][key].append(value)
+
+ def DelBuildSetting(self, key):
+ if key in self._properties['buildSettings']:
+ del self._properties['buildSettings'][key]
+
+ def SetBaseConfiguration(self, value):
+ self._properties['baseConfigurationReference'] = value
+
+class XCConfigurationList(XCObject):
+ # _configs is the default list of configurations.
+ _configs = [ XCBuildConfiguration({'name': 'Debug'}),
+ XCBuildConfiguration({'name': 'Release'}) ]
+
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'buildConfigurations': [1, XCBuildConfiguration, 1, 1, _configs],
+ 'defaultConfigurationIsVisible': [0, int, 0, 1, 1],
+ 'defaultConfigurationName': [0, str, 0, 1, 'Release'],
+ })
+
+ def Name(self):
+ return 'Build configuration list for ' + \
+ self.parent.__class__.__name__ + ' "' + self.parent.Name() + '"'
+
+ def ConfigurationNamed(self, name):
+ """Convenience accessor to obtain an XCBuildConfiguration by name."""
+ for configuration in self._properties['buildConfigurations']:
+ if configuration._properties['name'] == name:
+ return configuration
+
+ raise KeyError, name
+
+ def DefaultConfiguration(self):
+ """Convenience accessor to obtain the default XCBuildConfiguration."""
+ return self.ConfigurationNamed(self._properties['defaultConfigurationName'])
+
+ def HasBuildSetting(self, key):
+ """Determines the state of a build setting in all XCBuildConfiguration
+ child objects.
+
+ If all child objects have key in their build settings, and the value is the
+ same in all child objects, returns 1.
+
+ If no child objects have the key in their build settings, returns 0.
+
+ If some, but not all, child objects have the key in their build settings,
+ or if any children have different values for the key, returns -1.
+ """
+
+ has = None
+ value = None
+ for configuration in self._properties['buildConfigurations']:
+ configuration_has = configuration.HasBuildSetting(key)
+ if has is None:
+ has = configuration_has
+ elif has != configuration_has:
+ return -1
+
+ if configuration_has:
+ configuration_value = configuration.GetBuildSetting(key)
+ if value is None:
+ value = configuration_value
+ elif value != configuration_value:
+ return -1
+
+ if not has:
+ return 0
+
+ return 1
+
+ def GetBuildSetting(self, key):
+ """Gets the build setting for key.
+
+ All child XCConfiguration objects must have the same value set for the
+ setting, or a ValueError will be raised.
+ """
+
+ # TODO(mark): This is wrong for build settings that are lists. The list
+ # contents should be compared (and a list copy returned?)
+
+ value = None
+ for configuration in self._properties['buildConfigurations']:
+ configuration_value = configuration.GetBuildSetting(key)
+ if value is None:
+ value = configuration_value
+ else:
+ if value != configuration_value:
+ raise ValueError, 'Variant values for ' + key
+
+ return value
+
+ def SetBuildSetting(self, key, value):
+ """Sets the build setting for key to value in all child
+ XCBuildConfiguration objects.
+ """
+
+ for configuration in self._properties['buildConfigurations']:
+ configuration.SetBuildSetting(key, value)
+
+ def AppendBuildSetting(self, key, value):
+ """Appends value to the build setting for key, which is treated as a list,
+ in all child XCBuildConfiguration objects.
+ """
+
+ for configuration in self._properties['buildConfigurations']:
+ configuration.AppendBuildSetting(key, value)
+
+ def DelBuildSetting(self, key):
+ """Deletes the build setting key from all child XCBuildConfiguration
+ objects.
+ """
+
+ for configuration in self._properties['buildConfigurations']:
+ configuration.DelBuildSetting(key)
+
+ def SetBaseConfiguration(self, value):
+ """Sets the build configuration in all child XCBuildConfiguration objects.
+ """
+
+ for configuration in self._properties['buildConfigurations']:
+ configuration.SetBaseConfiguration(value)
+
+
+class PBXBuildFile(XCObject):
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'fileRef': [0, XCFileLikeElement, 0, 1],
+ 'settings': [0, str, 0, 0], # hack, it's a dict
+ })
+
+ # Weird output rules for PBXBuildFile.
+ _should_print_single_line = True
+ _encode_transforms = XCObject._alternate_encode_transforms
+
+ def Name(self):
+ # Example: "main.cc in Sources"
+ return self._properties['fileRef'].Name() + ' in ' + self.parent.Name()
+
+ def Hashables(self):
+ # super
+ hashables = XCObject.Hashables(self)
+
+ # It is not sufficient to just rely on Name() to get the
+ # XCFileLikeElement's name, because that is not a complete pathname.
+ # PathHashables returns hashables unique enough that no two
+ # PBXBuildFiles should wind up with the same set of hashables, unless
+ # someone adds the same file multiple times to the same target. That
+ # would be considered invalid anyway.
+ hashables.extend(self._properties['fileRef'].PathHashables())
+
+ return hashables
+
+
+class XCBuildPhase(XCObject):
+ """Abstract base for build phase classes. Not represented in a project
+ file.
+
+ Attributes:
+ _files_by_path: A dict mapping each path of a child in the files list by
+ path (keys) to the corresponding PBXBuildFile children (values).
+ _files_by_xcfilelikeelement: A dict mapping each XCFileLikeElement (keys)
+ to the corresponding PBXBuildFile children (values).
+ """
+
+ # TODO(mark): Some build phase types, like PBXShellScriptBuildPhase, don't
+ # actually have a "files" list. XCBuildPhase should not have "files" but
+ # another abstract subclass of it should provide this, and concrete build
+ # phase types that do have "files" lists should be derived from that new
+ # abstract subclass. XCBuildPhase should only provide buildActionMask and
+ # runOnlyForDeploymentPostprocessing, and not files or the various
+ # file-related methods and attributes.
+
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'buildActionMask': [0, int, 0, 1, 0x7fffffff],
+ 'files': [1, PBXBuildFile, 1, 1, []],
+ 'runOnlyForDeploymentPostprocessing': [0, int, 0, 1, 0],
+ })
+
+ def __init__(self, properties=None, id=None, parent=None):
+ # super
+ XCObject.__init__(self, properties, id, parent)
+
+ self._files_by_path = {}
+ self._files_by_xcfilelikeelement = {}
+ for pbxbuildfile in self._properties.get('files', []):
+ self._AddBuildFileToDicts(pbxbuildfile)
+
+ def FileGroup(self, path):
+ # Subclasses must override this by returning a two-element tuple. The
+ # first item in the tuple should be the PBXGroup to which "path" should be
+ # added, either as a child or deeper descendant. The second item should
+ # be a boolean indicating whether files should be added into hierarchical
+ # groups or one single flat group.
+ raise NotImplementedError, \
+ self.__class__.__name__ + ' must implement FileGroup'
+
+ def _AddPathToDict(self, pbxbuildfile, path):
+ """Adds path to the dict tracking paths belonging to this build phase.
+
+ If the path is already a member of this build phase, raises an exception.
+ """
+
+ if path in self._files_by_path:
+ raise ValueError, 'Found multiple build files with path ' + path
+ self._files_by_path[path] = pbxbuildfile
+
+ def _AddBuildFileToDicts(self, pbxbuildfile, path=None):
+ """Maintains the _files_by_path and _files_by_xcfilelikeelement dicts.
+
+ If path is specified, then it is the path that is being added to the
+ phase, and pbxbuildfile must contain either a PBXFileReference directly
+ referencing that path, or it must contain a PBXVariantGroup that itself
+ contains a PBXFileReference referencing the path.
+
+ If path is not specified, either the PBXFileReference's path or the paths
+ of all children of the PBXVariantGroup are taken as being added to the
+ phase.
+
+ If the path is already present in the phase, raises an exception.
+
+ If the PBXFileReference or PBXVariantGroup referenced by pbxbuildfile
+ are already present in the phase, referenced by a different PBXBuildFile
+ object, raises an exception. This does not raise an exception when
+ a PBXFileReference or PBXVariantGroup reappear and are referenced by the
+ same PBXBuildFile that has already introduced them, because in the case
+ of PBXVariantGroup objects, they may correspond to multiple paths that are
+ not all added simultaneously. When this situation occurs, the path needs
+ to be added to _files_by_path, but nothing needs to change in
+ _files_by_xcfilelikeelement, and the caller should have avoided adding
+ the PBXBuildFile if it is already present in the list of children.
+ """
+
+ xcfilelikeelement = pbxbuildfile._properties['fileRef']
+
+ paths = []
+ if path != None:
+ # It's best when the caller provides the path.
+ if isinstance(xcfilelikeelement, PBXVariantGroup):
+ paths.append(path)
+ else:
+ # If the caller didn't provide a path, there can be either multiple
+ # paths (PBXVariantGroup) or one.
+ if isinstance(xcfilelikeelement, PBXVariantGroup):
+ for variant in xcfilelikeelement._properties['children']:
+ paths.append(variant.FullPath())
+ else:
+ paths.append(xcfilelikeelement.FullPath())
+
+ # Add the paths first, because if something's going to raise, the
+ # messages provided by _AddPathToDict are more useful owing to its
+ # having access to a real pathname and not just an object's Name().
+ for a_path in paths:
+ self._AddPathToDict(pbxbuildfile, a_path)
+
+ # If another PBXBuildFile references this XCFileLikeElement, there's a
+ # problem.
+ if xcfilelikeelement in self._files_by_xcfilelikeelement and \
+ self._files_by_xcfilelikeelement[xcfilelikeelement] != pbxbuildfile:
+ raise ValueError, 'Found multiple build files for ' + \
+ xcfilelikeelement.Name()
+ self._files_by_xcfilelikeelement[xcfilelikeelement] = pbxbuildfile
+
+ def AppendBuildFile(self, pbxbuildfile, path=None):
+ # Callers should use this instead of calling
+ # AppendProperty('files', pbxbuildfile) directly because this function
+ # maintains the object's dicts. Better yet, callers can just call AddFile
+ # with a pathname and not worry about building their own PBXBuildFile
+ # objects.
+ self.AppendProperty('files', pbxbuildfile)
+ self._AddBuildFileToDicts(pbxbuildfile, path)
+
+ def AddFile(self, path, settings=None):
+ (file_group, hierarchical) = self.FileGroup(path)
+ file_ref = file_group.AddOrGetFileByPath(path, hierarchical)
+
+ if file_ref in self._files_by_xcfilelikeelement and \
+ isinstance(file_ref, PBXVariantGroup):
+ # There's already a PBXBuildFile in this phase corresponding to the
+ # PBXVariantGroup. path just provides a new variant that belongs to
+ # the group. Add the path to the dict.
+ pbxbuildfile = self._files_by_xcfilelikeelement[file_ref]
+ self._AddBuildFileToDicts(pbxbuildfile, path)
+ else:
+ # Add a new PBXBuildFile to get file_ref into the phase.
+ if settings is None:
+ pbxbuildfile = PBXBuildFile({'fileRef': file_ref})
+ else:
+ pbxbuildfile = PBXBuildFile({'fileRef': file_ref, 'settings': settings})
+ self.AppendBuildFile(pbxbuildfile, path)
+
+
+class PBXHeadersBuildPhase(XCBuildPhase):
+ # No additions to the schema relative to XCBuildPhase.
+
+ def Name(self):
+ return 'Headers'
+
+ def FileGroup(self, path):
+ return self.PBXProjectAncestor().RootGroupForPath(path)
+
+
+class PBXResourcesBuildPhase(XCBuildPhase):
+ # No additions to the schema relative to XCBuildPhase.
+
+ def Name(self):
+ return 'Resources'
+
+ def FileGroup(self, path):
+ return self.PBXProjectAncestor().RootGroupForPath(path)
+
+
+class PBXSourcesBuildPhase(XCBuildPhase):
+ # No additions to the schema relative to XCBuildPhase.
+
+ def Name(self):
+ return 'Sources'
+
+ def FileGroup(self, path):
+ return self.PBXProjectAncestor().RootGroupForPath(path)
+
+
+class PBXFrameworksBuildPhase(XCBuildPhase):
+ # No additions to the schema relative to XCBuildPhase.
+
+ def Name(self):
+ return 'Frameworks'
+
+ def FileGroup(self, path):
+ (root, ext) = posixpath.splitext(path)
+ if ext != '':
+ ext = ext[1:].lower()
+ if ext == 'o':
+ # .o files are added to Xcode Frameworks phases, but conceptually aren't
+ # frameworks, they're more like sources or intermediates. Redirect them
+ # to show up in one of those other groups.
+ return self.PBXProjectAncestor().RootGroupForPath(path)
+ else:
+ return (self.PBXProjectAncestor().FrameworksGroup(), False)
+
+
+class PBXShellScriptBuildPhase(XCBuildPhase):
+ _schema = XCBuildPhase._schema.copy()
+ _schema.update({
+ 'inputPaths': [1, str, 0, 1, []],
+ 'name': [0, str, 0, 0],
+ 'outputPaths': [1, str, 0, 1, []],
+ 'shellPath': [0, str, 0, 1, '/bin/sh'],
+ 'shellScript': [0, str, 0, 1],
+ 'showEnvVarsInLog': [0, int, 0, 0],
+ })
+
+ def Name(self):
+ if 'name' in self._properties:
+ return self._properties['name']
+
+ return 'ShellScript'
+
+
+class PBXCopyFilesBuildPhase(XCBuildPhase):
+ _schema = XCBuildPhase._schema.copy()
+ _schema.update({
+ 'dstPath': [0, str, 0, 1],
+ 'dstSubfolderSpec': [0, int, 0, 1],
+ 'name': [0, str, 0, 0],
+ })
+
+ # path_tree_re matches "$(DIR)/path" or just "$(DIR)". Match group 1 is
+ # "DIR", match group 3 is "path" or None.
+ path_tree_re = re.compile('^\\$\\((.*)\\)(/(.*)|)$')
+
+ # path_tree_to_subfolder maps names of Xcode variables to the associated
+ # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object.
+ path_tree_to_subfolder = {
+ 'BUILT_PRODUCTS_DIR': 16, # Products Directory
+ # Other types that can be chosen via the Xcode UI.
+ # TODO(mark): Map Xcode variable names to these.
+ # : 1, # Wrapper
+ # : 6, # Executables: 6
+ # : 7, # Resources
+ # : 15, # Java Resources
+ # : 10, # Frameworks
+ # : 11, # Shared Frameworks
+ # : 12, # Shared Support
+ # : 13, # PlugIns
+ }
+
+ def Name(self):
+ if 'name' in self._properties:
+ return self._properties['name']
+
+ return 'CopyFiles'
+
+ def FileGroup(self, path):
+ return self.PBXProjectAncestor().RootGroupForPath(path)
+
+ def SetDestination(self, path):
+ """Set the dstSubfolderSpec and dstPath properties from path.
+
+ path may be specified in the same notation used for XCHierarchicalElements,
+ specifically, "$(DIR)/path".
+ """
+
+ path_tree_match = self.path_tree_re.search(path)
+ if path_tree_match:
+ # Everything else needs to be relative to an Xcode variable.
+ path_tree = path_tree_match.group(1)
+ relative_path = path_tree_match.group(3)
+
+ if path_tree in self.path_tree_to_subfolder:
+ subfolder = self.path_tree_to_subfolder[path_tree]
+ if relative_path is None:
+ relative_path = ''
+ else:
+ # The path starts with an unrecognized Xcode variable
+ # name like $(SRCROOT). Xcode will still handle this
+ # as an "absolute path" that starts with the variable.
+ subfolder = 0
+ relative_path = path
+ elif path.startswith('/'):
+ # Special case. Absolute paths are in dstSubfolderSpec 0.
+ subfolder = 0
+ relative_path = path[1:]
+ else:
+ raise ValueError, 'Can\'t use path %s in a %s' % \
+ (path, self.__class__.__name__)
+
+ self._properties['dstPath'] = relative_path
+ self._properties['dstSubfolderSpec'] = subfolder
+
+
+class PBXBuildRule(XCObject):
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'compilerSpec': [0, str, 0, 1],
+ 'filePatterns': [0, str, 0, 0],
+ 'fileType': [0, str, 0, 1],
+ 'isEditable': [0, int, 0, 1, 1],
+ 'outputFiles': [1, str, 0, 1, []],
+ 'script': [0, str, 0, 0],
+ })
+
+ def Name(self):
+ # Not very inspired, but it's what Xcode uses.
+ return self.__class__.__name__
+
+ def Hashables(self):
+ # super
+ hashables = XCObject.Hashables(self)
+
+ # Use the hashables of the weak objects that this object refers to.
+ hashables.append(self._properties['fileType'])
+ if 'filePatterns' in self._properties:
+ hashables.append(self._properties['filePatterns'])
+ return hashables
+
+
+class PBXContainerItemProxy(XCObject):
+ # When referencing an item in this project file, containerPortal is the
+ # PBXProject root object of this project file. When referencing an item in
+ # another project file, containerPortal is a PBXFileReference identifying
+ # the other project file.
+ #
+ # When serving as a proxy to an XCTarget (in this project file or another),
+ # proxyType is 1. When serving as a proxy to a PBXFileReference (in another
+ # project file), proxyType is 2. Type 2 is used for references to the
+ # producs of the other project file's targets.
+ #
+ # Xcode is weird about remoteGlobalIDString. Usually, it's printed without
+ # a comment, indicating that it's tracked internally simply as a string, but
+ # sometimes it's printed with a comment (usually when the object is initially
+ # created), indicating that it's tracked as a project file object at least
+ # sometimes. This module always tracks it as an object, but contains a hack
+ # to prevent it from printing the comment in the project file output. See
+ # _XCKVPrint.
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'containerPortal': [0, XCContainerPortal, 0, 1],
+ 'proxyType': [0, int, 0, 1],
+ 'remoteGlobalIDString': [0, XCRemoteObject, 0, 1],
+ 'remoteInfo': [0, str, 0, 1],
+ })
+
+ def __repr__(self):
+ props = self._properties
+ name = '%s.gyp:%s' % (props['containerPortal'].Name(), props['remoteInfo'])
+ return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
+
+ def Name(self):
+ # Admittedly not the best name, but it's what Xcode uses.
+ return self.__class__.__name__
+
+ def Hashables(self):
+ # super
+ hashables = XCObject.Hashables(self)
+
+ # Use the hashables of the weak objects that this object refers to.
+ hashables.extend(self._properties['containerPortal'].Hashables())
+ hashables.extend(self._properties['remoteGlobalIDString'].Hashables())
+ return hashables
+
+
+class PBXTargetDependency(XCObject):
+ # The "target" property accepts an XCTarget object, and obviously not
+ # NoneType. But XCTarget is defined below, so it can't be put into the
+ # schema yet. The definition of PBXTargetDependency can't be moved below
+ # XCTarget because XCTarget's own schema references PBXTargetDependency.
+ # Python doesn't deal well with this circular relationship, and doesn't have
+ # a real way to do forward declarations. To work around, the type of
+ # the "target" property is reset below, after XCTarget is defined.
+ #
+ # At least one of "name" and "target" is required.
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'name': [0, str, 0, 0],
+ 'target': [0, None.__class__, 0, 0],
+ 'targetProxy': [0, PBXContainerItemProxy, 1, 1],
+ })
+
+ def __repr__(self):
+ name = self._properties.get('name') or self._properties['target'].Name()
+ return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
+
+ def Name(self):
+ # Admittedly not the best name, but it's what Xcode uses.
+ return self.__class__.__name__
+
+ def Hashables(self):
+ # super
+ hashables = XCObject.Hashables(self)
+
+ # Use the hashables of the weak objects that this object refers to.
+ hashables.extend(self._properties['targetProxy'].Hashables())
+ return hashables
+
+
+class PBXReferenceProxy(XCFileLikeElement):
+ _schema = XCFileLikeElement._schema.copy()
+ _schema.update({
+ 'fileType': [0, str, 0, 1],
+ 'path': [0, str, 0, 1],
+ 'remoteRef': [0, PBXContainerItemProxy, 1, 1],
+ })
+
+
+class XCTarget(XCRemoteObject):
+ # An XCTarget is really just an XCObject, the XCRemoteObject thing is just
+ # to allow PBXProject to be used in the remoteGlobalIDString property of
+ # PBXContainerItemProxy.
+ #
+ # Setting a "name" property at instantiation may also affect "productName",
+ # which may in turn affect the "PRODUCT_NAME" build setting in children of
+ # "buildConfigurationList". See __init__ below.
+ _schema = XCRemoteObject._schema.copy()
+ _schema.update({
+ 'buildConfigurationList': [0, XCConfigurationList, 1, 1,
+ XCConfigurationList()],
+ 'buildPhases': [1, XCBuildPhase, 1, 1, []],
+ 'dependencies': [1, PBXTargetDependency, 1, 1, []],
+ 'name': [0, str, 0, 1],
+ 'productName': [0, str, 0, 1],
+ })
+
+ def __init__(self, properties=None, id=None, parent=None,
+ force_outdir=None, force_prefix=None, force_extension=None):
+ # super
+ XCRemoteObject.__init__(self, properties, id, parent)
+
+ # Set up additional defaults not expressed in the schema. If a "name"
+ # property was supplied, set "productName" if it is not present. Also set
+ # the "PRODUCT_NAME" build setting in each configuration, but only if
+ # the setting is not present in any build configuration.
+ if 'name' in self._properties:
+ if not 'productName' in self._properties:
+ self.SetProperty('productName', self._properties['name'])
+
+ if 'productName' in self._properties:
+ if 'buildConfigurationList' in self._properties:
+ configs = self._properties['buildConfigurationList']
+ if configs.HasBuildSetting('PRODUCT_NAME') == 0:
+ configs.SetBuildSetting('PRODUCT_NAME',
+ self._properties['productName'])
+
+ def AddDependency(self, other):
+ pbxproject = self.PBXProjectAncestor()
+ other_pbxproject = other.PBXProjectAncestor()
+ if pbxproject == other_pbxproject:
+ # Add a dependency to another target in the same project file.
+ container = PBXContainerItemProxy({'containerPortal': pbxproject,
+ 'proxyType': 1,
+ 'remoteGlobalIDString': other,
+ 'remoteInfo': other.Name()})
+ dependency = PBXTargetDependency({'target': other,
+ 'targetProxy': container})
+ self.AppendProperty('dependencies', dependency)
+ else:
+ # Add a dependency to a target in a different project file.
+ other_project_ref = \
+ pbxproject.AddOrGetProjectReference(other_pbxproject)[1]
+ container = PBXContainerItemProxy({
+ 'containerPortal': other_project_ref,
+ 'proxyType': 1,
+ 'remoteGlobalIDString': other,
+ 'remoteInfo': other.Name(),
+ })
+ dependency = PBXTargetDependency({'name': other.Name(),
+ 'targetProxy': container})
+ self.AppendProperty('dependencies', dependency)
+
+ # Proxy all of these through to the build configuration list.
+
+ def ConfigurationNamed(self, name):
+ return self._properties['buildConfigurationList'].ConfigurationNamed(name)
+
+ def DefaultConfiguration(self):
+ return self._properties['buildConfigurationList'].DefaultConfiguration()
+
+ def HasBuildSetting(self, key):
+ return self._properties['buildConfigurationList'].HasBuildSetting(key)
+
+ def GetBuildSetting(self, key):
+ return self._properties['buildConfigurationList'].GetBuildSetting(key)
+
+ def SetBuildSetting(self, key, value):
+ return self._properties['buildConfigurationList'].SetBuildSetting(key, \
+ value)
+
+ def AppendBuildSetting(self, key, value):
+ return self._properties['buildConfigurationList'].AppendBuildSetting(key, \
+ value)
+
+ def DelBuildSetting(self, key):
+ return self._properties['buildConfigurationList'].DelBuildSetting(key)
+
+
+# Redefine the type of the "target" property. See PBXTargetDependency._schema
+# above.
+PBXTargetDependency._schema['target'][1] = XCTarget
+
+
+class PBXNativeTarget(XCTarget):
+ # buildPhases is overridden in the schema to be able to set defaults.
+ #
+ # NOTE: Contrary to most objects, it is advisable to set parent when
+ # constructing PBXNativeTarget. A parent of an XCTarget must be a PBXProject
+ # object. A parent reference is required for a PBXNativeTarget during
+ # construction to be able to set up the target defaults for productReference,
+ # because a PBXBuildFile object must be created for the target and it must
+ # be added to the PBXProject's mainGroup hierarchy.
+ _schema = XCTarget._schema.copy()
+ _schema.update({
+ 'buildPhases': [1, XCBuildPhase, 1, 1,
+ [PBXSourcesBuildPhase(), PBXFrameworksBuildPhase()]],
+ 'buildRules': [1, PBXBuildRule, 1, 1, []],
+ 'productReference': [0, PBXFileReference, 0, 1],
+ 'productType': [0, str, 0, 1],
+ })
+
+ # Mapping from Xcode product-types to settings. The settings are:
+ # filetype : used for explicitFileType in the project file
+ # prefix : the prefix for the file name
+ # suffix : the suffix for the filen ame
+ _product_filetypes = {
+ 'com.apple.product-type.application': ['wrapper.application',
+ '', '.app'],
+ 'com.apple.product-type.bundle': ['wrapper.cfbundle',
+ '', '.bundle'],
+ 'com.apple.product-type.framework': ['wrapper.framework',
+ '', '.framework'],
+ 'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib',
+ 'lib', '.dylib'],
+ 'com.apple.product-type.library.static': ['archive.ar',
+ 'lib', '.a'],
+ 'com.apple.product-type.tool': ['compiled.mach-o.executable',
+ '', ''],
+ 'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib',
+ '', '.so'],
+ }
+
+ def __init__(self, properties=None, id=None, parent=None,
+ force_outdir=None, force_prefix=None, force_extension=None):
+ # super
+ XCTarget.__init__(self, properties, id, parent)
+
+ if 'productName' in self._properties and \
+ 'productType' in self._properties and \
+ not 'productReference' in self._properties and \
+ self._properties['productType'] in self._product_filetypes:
+ products_group = None
+ pbxproject = self.PBXProjectAncestor()
+ if pbxproject != None:
+ products_group = pbxproject.ProductsGroup()
+
+ if products_group != None:
+ (filetype, prefix, suffix) = \
+ self._product_filetypes[self._properties['productType']]
+ # Xcode does not have a distinct type for loadable modules that are
+ # pure BSD targets (not in a bundle wrapper). GYP allows such modules
+ # to be specified by setting a target type to loadable_module without
+ # having mac_bundle set. These are mapped to the pseudo-product type
+ # com.googlecode.gyp.xcode.bundle.
+ #
+ # By picking up this special type and converting it to a dynamic
+ # library (com.apple.product-type.library.dynamic) with fix-ups,
+ # single-file loadable modules can be produced.
+ #
+ # MACH_O_TYPE is changed to mh_bundle to produce the proper file type
+ # (as opposed to mh_dylib). In order for linking to succeed,
+ # DYLIB_CURRENT_VERSION and DYLIB_COMPATIBILITY_VERSION must be
+ # cleared. They are meaningless for type mh_bundle.
+ #
+ # Finally, the .so extension is forcibly applied over the default
+ # (.dylib), unless another forced extension is already selected.
+ # .dylib is plainly wrong, and .bundle is used by loadable_modules in
+ # bundle wrappers (com.apple.product-type.bundle). .so seems an odd
+ # choice because it's used as the extension on many other systems that
+ # don't distinguish between linkable shared libraries and non-linkable
+ # loadable modules, but there's precedent: Python loadable modules on
+ # Mac OS X use an .so extension.
+ if self._properties['productType'] == 'com.googlecode.gyp.xcode.bundle':
+ self._properties['productType'] = \
+ 'com.apple.product-type.library.dynamic'
+ self.SetBuildSetting('MACH_O_TYPE', 'mh_bundle')
+ self.SetBuildSetting('DYLIB_CURRENT_VERSION', '')
+ self.SetBuildSetting('DYLIB_COMPATIBILITY_VERSION', '')
+ if force_extension is None:
+ force_extension = suffix[1:]
+
+ if force_extension is not None:
+ # If it's a wrapper (bundle), set WRAPPER_EXTENSION.
+ if filetype.startswith('wrapper.'):
+ self.SetBuildSetting('WRAPPER_EXTENSION', force_extension)
+ else:
+ # Extension override.
+ suffix = '.' + force_extension
+ self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension)
+
+ if filetype.startswith('compiled.mach-o.executable'):
+ product_name = self._properties['productName']
+ product_name += suffix
+ suffix = ''
+ self.SetProperty('productName', product_name)
+ self.SetBuildSetting('PRODUCT_NAME', product_name)
+
+ # Xcode handles most prefixes based on the target type, however there
+ # are exceptions. If a "BSD Dynamic Library" target is added in the
+ # Xcode UI, Xcode sets EXECUTABLE_PREFIX. This check duplicates that
+ # behavior.
+ if force_prefix is not None:
+ prefix = force_prefix
+ if filetype.startswith('wrapper.'):
+ self.SetBuildSetting('WRAPPER_PREFIX', prefix)
+ else:
+ self.SetBuildSetting('EXECUTABLE_PREFIX', prefix)
+
+ if force_outdir is not None:
+ self.SetBuildSetting('TARGET_BUILD_DIR', force_outdir)
+
+ # TODO(tvl): Remove the below hack.
+ # http://code.google.com/p/gyp/issues/detail?id=122
+
+ # Some targets include the prefix in the target_name. These targets
+ # really should just add a product_name setting that doesn't include
+ # the prefix. For example:
+ # target_name = 'libevent', product_name = 'event'
+ # This check cleans up for them.
+ product_name = self._properties['productName']
+ prefix_len = len(prefix)
+ if prefix_len and (product_name[:prefix_len] == prefix):
+ product_name = product_name[prefix_len:]
+ self.SetProperty('productName', product_name)
+ self.SetBuildSetting('PRODUCT_NAME', product_name)
+
+ ref_props = {
+ 'explicitFileType': filetype,
+ 'includeInIndex': 0,
+ 'path': prefix + product_name + suffix,
+ 'sourceTree': 'BUILT_PRODUCTS_DIR',
+ }
+ file_ref = PBXFileReference(ref_props)
+ products_group.AppendChild(file_ref)
+ self.SetProperty('productReference', file_ref)
+
+ def GetBuildPhaseByType(self, type):
+ if not 'buildPhases' in self._properties:
+ return None
+
+ the_phase = None
+ for phase in self._properties['buildPhases']:
+ if isinstance(phase, type):
+ # Some phases may be present in multiples in a well-formed project file,
+ # but phases like PBXSourcesBuildPhase may only be present singly, and
+ # this function is intended as an aid to GetBuildPhaseByType. Loop
+ # over the entire list of phases and assert if more than one of the
+ # desired type is found.
+ assert the_phase is None
+ the_phase = phase
+
+ return the_phase
+
+ def HeadersPhase(self):
+ headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase)
+ if headers_phase is None:
+ headers_phase = PBXHeadersBuildPhase()
+
+ # The headers phase should come before the resources, sources, and
+ # frameworks phases, if any.
+ insert_at = len(self._properties['buildPhases'])
+ for index in xrange(0, len(self._properties['buildPhases'])):
+ phase = self._properties['buildPhases'][index]
+ if isinstance(phase, PBXResourcesBuildPhase) or \
+ isinstance(phase, PBXSourcesBuildPhase) or \
+ isinstance(phase, PBXFrameworksBuildPhase):
+ insert_at = index
+ break
+
+ self._properties['buildPhases'].insert(insert_at, headers_phase)
+ headers_phase.parent = self
+
+ return headers_phase
+
+ def ResourcesPhase(self):
+ resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase)
+ if resources_phase is None:
+ resources_phase = PBXResourcesBuildPhase()
+
+ # The resources phase should come before the sources and frameworks
+ # phases, if any.
+ insert_at = len(self._properties['buildPhases'])
+ for index in xrange(0, len(self._properties['buildPhases'])):
+ phase = self._properties['buildPhases'][index]
+ if isinstance(phase, PBXSourcesBuildPhase) or \
+ isinstance(phase, PBXFrameworksBuildPhase):
+ insert_at = index
+ break
+
+ self._properties['buildPhases'].insert(insert_at, resources_phase)
+ resources_phase.parent = self
+
+ return resources_phase
+
+ def SourcesPhase(self):
+ sources_phase = self.GetBuildPhaseByType(PBXSourcesBuildPhase)
+ if sources_phase is None:
+ sources_phase = PBXSourcesBuildPhase()
+ self.AppendProperty('buildPhases', sources_phase)
+
+ return sources_phase
+
+ def FrameworksPhase(self):
+ frameworks_phase = self.GetBuildPhaseByType(PBXFrameworksBuildPhase)
+ if frameworks_phase is None:
+ frameworks_phase = PBXFrameworksBuildPhase()
+ self.AppendProperty('buildPhases', frameworks_phase)
+
+ return frameworks_phase
+
+ def AddDependency(self, other):
+ # super
+ XCTarget.AddDependency(self, other)
+
+ static_library_type = 'com.apple.product-type.library.static'
+ shared_library_type = 'com.apple.product-type.library.dynamic'
+ framework_type = 'com.apple.product-type.framework'
+ if isinstance(other, PBXNativeTarget) and \
+ 'productType' in self._properties and \
+ self._properties['productType'] != static_library_type and \
+ 'productType' in other._properties and \
+ (other._properties['productType'] == static_library_type or \
+ ((other._properties['productType'] == shared_library_type or \
+ other._properties['productType'] == framework_type) and \
+ ((not other.HasBuildSetting('MACH_O_TYPE')) or
+ other.GetBuildSetting('MACH_O_TYPE') != 'mh_bundle'))):
+
+ file_ref = other.GetProperty('productReference')
+
+ pbxproject = self.PBXProjectAncestor()
+ other_pbxproject = other.PBXProjectAncestor()
+ if pbxproject != other_pbxproject:
+ other_project_product_group = \
+ pbxproject.AddOrGetProjectReference(other_pbxproject)[0]
+ file_ref = other_project_product_group.GetChildByRemoteObject(file_ref)
+
+ self.FrameworksPhase().AppendProperty('files',
+ PBXBuildFile({'fileRef': file_ref}))
+
+
+class PBXAggregateTarget(XCTarget):
+ pass
+
+
+class PBXProject(XCContainerPortal):
+ # A PBXProject is really just an XCObject, the XCContainerPortal thing is
+ # just to allow PBXProject to be used in the containerPortal property of
+ # PBXContainerItemProxy.
+ """
+
+ Attributes:
+ path: "sample.xcodeproj". TODO(mark) Document me!
+ _other_pbxprojects: A dictionary, keyed by other PBXProject objects. Each
+ value is a reference to the dict in the
+ projectReferences list associated with the keyed
+ PBXProject.
+ """
+
+ _schema = XCContainerPortal._schema.copy()
+ _schema.update({
+ 'attributes': [0, dict, 0, 0],
+ 'buildConfigurationList': [0, XCConfigurationList, 1, 1,
+ XCConfigurationList()],
+ 'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.2'],
+ 'hasScannedForEncodings': [0, int, 0, 1, 1],
+ 'mainGroup': [0, PBXGroup, 1, 1, PBXGroup()],
+ 'projectDirPath': [0, str, 0, 1, ''],
+ 'projectReferences': [1, dict, 0, 0],
+ 'projectRoot': [0, str, 0, 1, ''],
+ 'targets': [1, XCTarget, 1, 1, []],
+ })
+
+ def __init__(self, properties=None, id=None, parent=None, path=None):
+ self.path = path
+ self._other_pbxprojects = {}
+ # super
+ return XCContainerPortal.__init__(self, properties, id, parent)
+
+ def Name(self):
+ name = self.path
+ if name[-10:] == '.xcodeproj':
+ name = name[:-10]
+ return posixpath.basename(name)
+
+ def Path(self):
+ return self.path
+
+ def Comment(self):
+ return 'Project object'
+
+ def Children(self):
+ # super
+ children = XCContainerPortal.Children(self)
+
+ # Add children that the schema doesn't know about. Maybe there's a more
+ # elegant way around this, but this is the only case where we need to own
+ # objects in a dictionary (that is itself in a list), and three lines for
+ # a one-off isn't that big a deal.
+ if 'projectReferences' in self._properties:
+ for reference in self._properties['projectReferences']:
+ children.append(reference['ProductGroup'])
+
+ return children
+
+ def PBXProjectAncestor(self):
+ return self
+
+ def _GroupByName(self, name):
+ if not 'mainGroup' in self._properties:
+ self.SetProperty('mainGroup', PBXGroup())
+
+ main_group = self._properties['mainGroup']
+ group = main_group.GetChildByName(name)
+ if group is None:
+ group = PBXGroup({'name': name})
+ main_group.AppendChild(group)
+
+ return group
+
+ # SourceGroup and ProductsGroup are created by default in Xcode's own
+ # templates.
+ def SourceGroup(self):
+ return self._GroupByName('Source')
+
+ def ProductsGroup(self):
+ return self._GroupByName('Products')
+
+ # IntermediatesGroup is used to collect source-like files that are generated
+ # by rules or script phases and are placed in intermediate directories such
+ # as DerivedSources.
+ def IntermediatesGroup(self):
+ return self._GroupByName('Intermediates')
+
+ # FrameworksGroup and ProjectsGroup are top-level groups used to collect
+ # frameworks and projects.
+ def FrameworksGroup(self):
+ return self._GroupByName('Frameworks')
+
+ def ProjectsGroup(self):
+ return self._GroupByName('Projects')
+
+ def RootGroupForPath(self, path):
+ """Returns a PBXGroup child of this object to which path should be added.
+
+ This method is intended to choose between SourceGroup and
+ IntermediatesGroup on the basis of whether path is present in a source
+ directory or an intermediates directory. For the purposes of this
+ determination, any path located within a derived file directory such as
+ PROJECT_DERIVED_FILE_DIR is treated as being in an intermediates
+ directory.
+
+ The returned value is a two-element tuple. The first element is the
+ PBXGroup, and the second element specifies whether that group should be
+ organized hierarchically (True) or as a single flat list (False).
+ """
+
+ # TODO(mark): make this a class variable and bind to self on call?
+ # Also, this list is nowhere near exhaustive.
+ # INTERMEDIATE_DIR and SHARED_INTERMEDIATE_DIR are used by
+ # gyp.generator.xcode. There should probably be some way for that module
+ # to push the names in, rather than having to hard-code them here.
+ source_tree_groups = {
+ 'DERIVED_FILE_DIR': (self.IntermediatesGroup, True),
+ 'INTERMEDIATE_DIR': (self.IntermediatesGroup, True),
+ 'PROJECT_DERIVED_FILE_DIR': (self.IntermediatesGroup, True),
+ 'SHARED_INTERMEDIATE_DIR': (self.IntermediatesGroup, True),
+ }
+
+ (source_tree, path) = SourceTreeAndPathFromPath(path)
+ if source_tree != None and source_tree in source_tree_groups:
+ (group_func, hierarchical) = source_tree_groups[source_tree]
+ group = group_func()
+ return (group, hierarchical)
+
+ # TODO(mark): make additional choices based on file extension.
+
+ return (self.SourceGroup(), True)
+
+ def AddOrGetFileInRootGroup(self, path):
+ """Returns a PBXFileReference corresponding to path in the correct group
+ according to RootGroupForPath's heuristics.
+
+ If an existing PBXFileReference for path exists, it will be returned.
+ Otherwise, one will be created and returned.
+ """
+
+ (group, hierarchical) = self.RootGroupForPath(path)
+ return group.AddOrGetFileByPath(path, hierarchical)
+
+ def RootGroupsTakeOverOnlyChildren(self, recurse=False):
+ """Calls TakeOverOnlyChild for all groups in the main group."""
+
+ for group in self._properties['mainGroup']._properties['children']:
+ if isinstance(group, PBXGroup):
+ group.TakeOverOnlyChild(recurse)
+
+ def SortGroups(self):
+ # Sort the children of the mainGroup (like "Source" and "Products")
+ # according to their defined order.
+ self._properties['mainGroup']._properties['children'] = \
+ sorted(self._properties['mainGroup']._properties['children'],
+ cmp=lambda x,y: x.CompareRootGroup(y))
+
+ # Sort everything else by putting group before files, and going
+ # alphabetically by name within sections of groups and files. SortGroup
+ # is recursive.
+ for group in self._properties['mainGroup']._properties['children']:
+ if not isinstance(group, PBXGroup):
+ continue
+
+ if group.Name() == 'Products':
+ # The Products group is a special case. Instead of sorting
+ # alphabetically, sort things in the order of the targets that
+ # produce the products. To do this, just build up a new list of
+ # products based on the targets.
+ products = []
+ for target in self._properties['targets']:
+ if not isinstance(target, PBXNativeTarget):
+ continue
+ product = target._properties['productReference']
+ # Make sure that the product is already in the products group.
+ assert product in group._properties['children']
+ products.append(product)
+
+ # Make sure that this process doesn't miss anything that was already
+ # in the products group.
+ assert len(products) == len(group._properties['children'])
+ group._properties['children'] = products
+ else:
+ group.SortGroup()
+
+ def AddOrGetProjectReference(self, other_pbxproject):
+ """Add a reference to another project file (via PBXProject object) to this
+ one.
+
+ Returns [ProductGroup, ProjectRef]. ProductGroup is a PBXGroup object in
+ this project file that contains a PBXReferenceProxy object for each
+ product of each PBXNativeTarget in the other project file. ProjectRef is
+ a PBXFileReference to the other project file.
+
+ If this project file already references the other project file, the
+ existing ProductGroup and ProjectRef are returned. The ProductGroup will
+ still be updated if necessary.
+ """
+
+ if not 'projectReferences' in self._properties:
+ self._properties['projectReferences'] = []
+
+ product_group = None
+ project_ref = None
+
+ if not other_pbxproject in self._other_pbxprojects:
+ # This project file isn't yet linked to the other one. Establish the
+ # link.
+ product_group = PBXGroup({'name': 'Products'})
+
+ # ProductGroup is strong.
+ product_group.parent = self
+
+ # There's nothing unique about this PBXGroup, and if left alone, it will
+ # wind up with the same set of hashables as all other PBXGroup objects
+ # owned by the projectReferences list. Add the hashables of the
+ # remote PBXProject that it's related to.
+ product_group._hashables.extend(other_pbxproject.Hashables())
+
+ # The other project reports its path as relative to the same directory
+ # that this project's path is relative to. The other project's path
+ # is not necessarily already relative to this project. Figure out the
+ # pathname that this project needs to use to refer to the other one.
+ this_path = posixpath.dirname(self.Path())
+ projectDirPath = self.GetProperty('projectDirPath')
+ if projectDirPath:
+ if posixpath.isabs(projectDirPath[0]):
+ this_path = projectDirPath
+ else:
+ this_path = posixpath.join(this_path, projectDirPath)
+ other_path = gyp.common.RelativePath(other_pbxproject.Path(), this_path)
+
+ # ProjectRef is weak (it's owned by the mainGroup hierarchy).
+ project_ref = PBXFileReference({
+ 'lastKnownFileType': 'wrapper.pb-project',
+ 'path': other_path,
+ 'sourceTree': 'SOURCE_ROOT',
+ })
+ self.ProjectsGroup().AppendChild(project_ref)
+
+ ref_dict = {'ProductGroup': product_group, 'ProjectRef': project_ref}
+ self._other_pbxprojects[other_pbxproject] = ref_dict
+ self.AppendProperty('projectReferences', ref_dict)
+
+ # Xcode seems to sort this list case-insensitively
+ self._properties['projectReferences'] = \
+ sorted(self._properties['projectReferences'], cmp=lambda x,y:
+ cmp(x['ProjectRef'].Name().lower(),
+ y['ProjectRef'].Name().lower()))
+ else:
+ # The link already exists. Pull out the relevnt data.
+ project_ref_dict = self._other_pbxprojects[other_pbxproject]
+ product_group = project_ref_dict['ProductGroup']
+ project_ref = project_ref_dict['ProjectRef']
+
+ self._SetUpProductReferences(other_pbxproject, product_group, project_ref)
+
+ return [product_group, project_ref]
+
+ def _SetUpProductReferences(self, other_pbxproject, product_group,
+ project_ref):
+ # TODO(mark): This only adds references to products in other_pbxproject
+ # when they don't exist in this pbxproject. Perhaps it should also
+ # remove references from this pbxproject that are no longer present in
+ # other_pbxproject. Perhaps it should update various properties if they
+ # change.
+ for target in other_pbxproject._properties['targets']:
+ if not isinstance(target, PBXNativeTarget):
+ continue
+
+ other_fileref = target._properties['productReference']
+ if product_group.GetChildByRemoteObject(other_fileref) is None:
+ # Xcode sets remoteInfo to the name of the target and not the name
+ # of its product, despite this proxy being a reference to the product.
+ container_item = PBXContainerItemProxy({
+ 'containerPortal': project_ref,
+ 'proxyType': 2,
+ 'remoteGlobalIDString': other_fileref,
+ 'remoteInfo': target.Name()
+ })
+ # TODO(mark): Does sourceTree get copied straight over from the other
+ # project? Can the other project ever have lastKnownFileType here
+ # instead of explicitFileType? (Use it if so?) Can path ever be
+ # unset? (I don't think so.) Can other_fileref have name set, and
+ # does it impact the PBXReferenceProxy if so? These are the questions
+ # that perhaps will be answered one day.
+ reference_proxy = PBXReferenceProxy({
+ 'fileType': other_fileref._properties['explicitFileType'],
+ 'path': other_fileref._properties['path'],
+ 'sourceTree': other_fileref._properties['sourceTree'],
+ 'remoteRef': container_item,
+ })
+
+ product_group.AppendChild(reference_proxy)
+
+ def SortRemoteProductReferences(self):
+ # For each remote project file, sort the associated ProductGroup in the
+ # same order that the targets are sorted in the remote project file. This
+ # is the sort order used by Xcode.
+
+ def CompareProducts(x, y, remote_products):
+ # x and y are PBXReferenceProxy objects. Go through their associated
+ # PBXContainerItem to get the remote PBXFileReference, which will be
+ # present in the remote_products list.
+ x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString']
+ y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString']
+ x_index = remote_products.index(x_remote)
+ y_index = remote_products.index(y_remote)
+
+ # Use the order of each remote PBXFileReference in remote_products to
+ # determine the sort order.
+ return cmp(x_index, y_index)
+
+ for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems():
+ # Build up a list of products in the remote project file, ordered the
+ # same as the targets that produce them.
+ remote_products = []
+ for target in other_pbxproject._properties['targets']:
+ if not isinstance(target, PBXNativeTarget):
+ continue
+ remote_products.append(target._properties['productReference'])
+
+ # Sort the PBXReferenceProxy children according to the list of remote
+ # products.
+ product_group = ref_dict['ProductGroup']
+ product_group._properties['children'] = sorted(
+ product_group._properties['children'],
+ cmp=lambda x, y: CompareProducts(x, y, remote_products))
+
+
+class XCProjectFile(XCObject):
+ _schema = XCObject._schema.copy()
+ _schema.update({
+ 'archiveVersion': [0, int, 0, 1, 1],
+ 'classes': [0, dict, 0, 1, {}],
+ 'objectVersion': [0, int, 0, 1, 45],
+ 'rootObject': [0, PBXProject, 1, 1],
+ })
+
+ def SetXcodeVersion(self, version):
+ version_to_object_version = {
+ '2.4': 45,
+ '3.0': 45,
+ '3.1': 45,
+ '3.2': 46,
+ }
+ if not version in version_to_object_version:
+ supported_str = ', '.join(sorted(version_to_object_version.keys()))
+ raise Exception(
+ 'Unsupported Xcode version %s (supported: %s)' %
+ ( version, supported_str ) )
+ compatibility_version = 'Xcode %s' % version
+ self._properties['rootObject'].SetProperty('compatibilityVersion',
+ compatibility_version)
+ self.SetProperty('objectVersion', version_to_object_version[version]);
+
+ def ComputeIDs(self, recursive=True, overwrite=True, hash=None):
+ # Although XCProjectFile is implemented here as an XCObject, it's not a
+ # proper object in the Xcode sense, and it certainly doesn't have its own
+ # ID. Pass through an attempt to update IDs to the real root object.
+ if recursive:
+ self._properties['rootObject'].ComputeIDs(recursive, overwrite, hash)
+
+ def Print(self, file=sys.stdout):
+ self.VerifyHasRequiredProperties()
+
+ # Add the special "objects" property, which will be caught and handled
+ # separately during printing. This structure allows a fairly standard
+ # loop do the normal printing.
+ self._properties['objects'] = {}
+ self._XCPrint(file, 0, '// !$*UTF8*$!\n')
+ if self._should_print_single_line:
+ self._XCPrint(file, 0, '{ ')
+ else:
+ self._XCPrint(file, 0, '{\n')
+ for property, value in sorted(self._properties.iteritems(),
+ cmp=lambda x, y: cmp(x, y)):
+ if property == 'objects':
+ self._PrintObjects(file)
+ else:
+ self._XCKVPrint(file, 1, property, value)
+ self._XCPrint(file, 0, '}\n')
+ del self._properties['objects']
+
+ def _PrintObjects(self, file):
+ if self._should_print_single_line:
+ self._XCPrint(file, 0, 'objects = {')
+ else:
+ self._XCPrint(file, 1, 'objects = {\n')
+
+ objects_by_class = {}
+ for object in self.Descendants():
+ if object == self:
+ continue
+ class_name = object.__class__.__name__
+ if not class_name in objects_by_class:
+ objects_by_class[class_name] = []
+ objects_by_class[class_name].append(object)
+
+ for class_name in sorted(objects_by_class):
+ self._XCPrint(file, 0, '\n')
+ self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n')
+ for object in sorted(objects_by_class[class_name],
+ cmp=lambda x, y: cmp(x.id, y.id)):
+ object.Print(file)
+ self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n')
+
+ if self._should_print_single_line:
+ self._XCPrint(file, 0, '}; ')
+ else:
+ self._XCPrint(file, 1, '};\n')
diff --git a/chromium/tools/gyp/pylib/gyp/xml_fix.py b/chromium/tools/gyp/pylib/gyp/xml_fix.py
new file mode 100644
index 00000000000..5de848158d2
--- /dev/null
+++ b/chromium/tools/gyp/pylib/gyp/xml_fix.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Applies a fix to CR LF TAB handling in xml.dom.
+
+Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293
+Working around this: http://bugs.python.org/issue5752
+TODO(bradnelson): Consider dropping this when we drop XP support.
+"""
+
+
+import xml.dom.minidom
+
+
+def _Replacement_write_data(writer, data, is_attrib=False):
+ """Writes datachars to writer."""
+ data = data.replace("&", "&amp;").replace("<", "&lt;")
+ data = data.replace("\"", "&quot;").replace(">", "&gt;")
+ if is_attrib:
+ data = data.replace(
+ "\r", "&#xD;").replace(
+ "\n", "&#xA;").replace(
+ "\t", "&#x9;")
+ writer.write(data)
+
+
+def _Replacement_writexml(self, writer, indent="", addindent="", newl=""):
+ # indent = current indentation
+ # addindent = indentation to add to higher levels
+ # newl = newline string
+ writer.write(indent+"<" + self.tagName)
+
+ attrs = self._get_attributes()
+ a_names = attrs.keys()
+ a_names.sort()
+
+ for a_name in a_names:
+ writer.write(" %s=\"" % a_name)
+ _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True)
+ writer.write("\"")
+ if self.childNodes:
+ writer.write(">%s" % newl)
+ for node in self.childNodes:
+ node.writexml(writer, indent + addindent, addindent, newl)
+ writer.write("%s</%s>%s" % (indent, self.tagName, newl))
+ else:
+ writer.write("/>%s" % newl)
+
+
+class XmlFix(object):
+ """Object to manage temporary patching of xml.dom.minidom."""
+
+ def __init__(self):
+ # Preserve current xml.dom.minidom functions.
+ self.write_data = xml.dom.minidom._write_data
+ self.writexml = xml.dom.minidom.Element.writexml
+ # Inject replacement versions of a function and a method.
+ xml.dom.minidom._write_data = _Replacement_write_data
+ xml.dom.minidom.Element.writexml = _Replacement_writexml
+
+ def Cleanup(self):
+ if self.write_data:
+ xml.dom.minidom._write_data = self.write_data
+ xml.dom.minidom.Element.writexml = self.writexml
+ self.write_data = None
+
+ def __del__(self):
+ self.Cleanup()
diff --git a/chromium/tools/gyp/pylintrc b/chromium/tools/gyp/pylintrc
new file mode 100644
index 00000000000..d7c23d2a211
--- /dev/null
+++ b/chromium/tools/gyp/pylintrc
@@ -0,0 +1,307 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+# C0103: Invalid name "NN" (should match [a-z_][a-z0-9_]{2,30}$)
+# C0111: Missing docstring
+# C0302: Too many lines in module (NN)
+# R0902: Too many instance attributes (N/7)
+# R0903: Too few public methods (N/2)
+# R0904: Too many public methods (NN/20)
+# R0912: Too many branches (NN/12)
+# R0913: Too many arguments (N/5)
+# R0914: Too many local variables (NN/15)
+# R0915: Too many statements (NN/50)
+# W0141: Used builtin function 'map'
+# W0142: Used * or ** magic
+# W0232: Class has no __init__ method
+# W0511: TODO
+# W0603: Using the global statement
+#
+# These should be enabled eventually:
+# C0112: Empty docstring
+# C0301: Line too long (NN/80)
+# C0321: More than one statement on single line
+# C0322: Operator not preceded by a space
+# C0323: Operator not followed by a space
+# C0324: Comma not followed by a space
+# E0101: Explicit return in __init__
+# E0102: function already defined line NN
+# E1002: Use of super on an old style class
+# E1101: Instance of 'XX' has no 'YY' member
+# E1103: Instance of 'XX' has no 'XX' member (but some types could not be inferred)
+# E0602: Undefined variable 'XX'
+# F0401: Unable to import 'XX'
+# R0201: Method could be a function
+# R0801: Similar lines in N files
+# W0102: Dangerous default value {} as argument
+# W0104: Statement seems to have no effect
+# W0105: String statement has no effect
+# W0108: Lambda may not be necessary
+# W0201: Attribute 'XX' defined outside __init__
+# W0212: Access to a protected member XX of a client class
+# W0221: Arguments number differs from overridden method
+# W0223: Method 'XX' is abstract in class 'YY' but is not overridden
+# W0231: __init__ method from base class 'XX' is not called
+# W0301: Unnecessary semicolon
+# W0311: Bad indentation. Found NN spaces, expected NN
+# W0401: Wildcard import XX
+# W0402: Uses of a deprecated module 'string'
+# W0403: Relative import 'XX', should be 'YY.XX'
+# W0404: Reimport 'XX' (imported line NN)
+# W0601: Global variable 'XX' undefined at the module level
+# W0602: Using global for 'XX' but no assignment is done
+# W0611: Unused import pprint
+# W0612: Unused variable 'XX'
+# W0613: Unused argument 'XX'
+# W0614: Unused import XX from wildcard import
+# W0621: Redefining name 'XX' from outer scope (line NN)
+# W0622: Redefining built-in 'NN'
+# W0631: Using possibly undefined loop variable 'XX'
+# W0701: Raising a string exception
+# W0702: No exception type(s) specified
+disable=C0103,C0111,C0302,R0902,R0903,R0904,R0912,R0913,R0914,R0915,W0141,W0142,W0232,W0511,W0603,C0112,C0301,C0321,C0322,C0323,C0324,E0101,E0102,E1002,E1101,E1103,E0602,F0401,R0201,R0801,W0102,W0104,W0105,W0108,W0201,W0212,W0221,W0223,W0231,W0301,W0311,W0401,W0402,W0403,W0404,W0601,W0602,W0611,W0612,W0613,W0614,W0621,W0622,W0631,W0701,W0702
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html
+output-format=text
+
+# Include message's id in output
+include-ids=yes
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/chromium/tools/gyp/samples/samples b/chromium/tools/gyp/samples/samples
new file mode 100755
index 00000000000..804b6189987
--- /dev/null
+++ b/chromium/tools/gyp/samples/samples
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os.path
+import shutil
+import sys
+
+
+gyps = [
+ 'app/app.gyp',
+ 'base/base.gyp',
+ 'build/temp_gyp/googleurl.gyp',
+ 'build/all.gyp',
+ 'build/common.gypi',
+ 'build/external_code.gypi',
+ 'chrome/test/security_tests/security_tests.gyp',
+ 'chrome/third_party/hunspell/hunspell.gyp',
+ 'chrome/chrome.gyp',
+ 'media/media.gyp',
+ 'net/net.gyp',
+ 'printing/printing.gyp',
+ 'sdch/sdch.gyp',
+ 'skia/skia.gyp',
+ 'testing/gmock.gyp',
+ 'testing/gtest.gyp',
+ 'third_party/bzip2/bzip2.gyp',
+ 'third_party/icu38/icu38.gyp',
+ 'third_party/libevent/libevent.gyp',
+ 'third_party/libjpeg/libjpeg.gyp',
+ 'third_party/libpng/libpng.gyp',
+ 'third_party/libxml/libxml.gyp',
+ 'third_party/libxslt/libxslt.gyp',
+ 'third_party/lzma_sdk/lzma_sdk.gyp',
+ 'third_party/modp_b64/modp_b64.gyp',
+ 'third_party/npapi/npapi.gyp',
+ 'third_party/sqlite/sqlite.gyp',
+ 'third_party/zlib/zlib.gyp',
+ 'v8/tools/gyp/v8.gyp',
+ 'webkit/activex_shim/activex_shim.gyp',
+ 'webkit/activex_shim_dll/activex_shim_dll.gyp',
+ 'webkit/build/action_csspropertynames.py',
+ 'webkit/build/action_cssvaluekeywords.py',
+ 'webkit/build/action_jsconfig.py',
+ 'webkit/build/action_makenames.py',
+ 'webkit/build/action_maketokenizer.py',
+ 'webkit/build/action_useragentstylesheets.py',
+ 'webkit/build/rule_binding.py',
+ 'webkit/build/rule_bison.py',
+ 'webkit/build/rule_gperf.py',
+ 'webkit/tools/test_shell/test_shell.gyp',
+ 'webkit/webkit.gyp',
+]
+
+
+def Main(argv):
+ if len(argv) != 3 or argv[1] not in ['push', 'pull']:
+ print 'Usage: %s push/pull PATH_TO_CHROME' % argv[0]
+ return 1
+
+ path_to_chrome = argv[2]
+
+ for g in gyps:
+ chrome_file = os.path.join(path_to_chrome, g)
+ local_file = os.path.join(os.path.dirname(argv[0]), os.path.split(g)[1])
+ if argv[1] == 'push':
+ print 'Copying %s to %s' % (local_file, chrome_file)
+ shutil.copyfile(local_file, chrome_file)
+ elif argv[1] == 'pull':
+ print 'Copying %s to %s' % (chrome_file, local_file)
+ shutil.copyfile(chrome_file, local_file)
+ else:
+ assert False
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/chromium/tools/gyp/samples/samples.bat b/chromium/tools/gyp/samples/samples.bat
new file mode 100644
index 00000000000..778d9c90f06
--- /dev/null
+++ b/chromium/tools/gyp/samples/samples.bat
@@ -0,0 +1,5 @@
+@rem Copyright (c) 2009 Google Inc. All rights reserved.
+@rem Use of this source code is governed by a BSD-style license that can be
+@rem found in the LICENSE file.
+
+@python %~dp0/samples %*
diff --git a/chromium/tools/gyp/setup.py b/chromium/tools/gyp/setup.py
new file mode 100755
index 00000000000..ed2b41a3c30
--- /dev/null
+++ b/chromium/tools/gyp/setup.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from distutils.core import setup
+from distutils.command.install import install
+from distutils.command.install_lib import install_lib
+from distutils.command.install_scripts import install_scripts
+
+setup(
+ name='gyp',
+ version='0.1',
+ description='Generate Your Projects',
+ author='Chromium Authors',
+ author_email='chromium-dev@googlegroups.com',
+ url='http://code.google.com/p/gyp',
+ package_dir = {'': 'pylib'},
+ packages=['gyp', 'gyp.generator'],
+
+ scripts = ['gyp'],
+ cmdclass = {'install': install,
+ 'install_lib': install_lib,
+ 'install_scripts': install_scripts},
+)
diff --git a/chromium/tools/gyp/test/actions-bare/src/bare.gyp b/chromium/tools/gyp/test/actions-bare/src/bare.gyp
new file mode 100644
index 00000000000..3d28f099d44
--- /dev/null
+++ b/chromium/tools/gyp/test/actions-bare/src/bare.gyp
@@ -0,0 +1,25 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'bare',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'action1',
+ 'inputs': [
+ 'bare.py',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/out.txt',
+ ],
+ 'action': ['python', 'bare.py', '<(PRODUCT_DIR)/out.txt'],
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions-multiple/src/actions.gyp b/chromium/tools/gyp/test/actions-multiple/src/actions.gyp
new file mode 100644
index 00000000000..c70a58f702f
--- /dev/null
+++ b/chromium/tools/gyp/test/actions-multiple/src/actions.gyp
@@ -0,0 +1,226 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ # Have a long string so that actions will exceed xp 512 character
+ # command limit on xp.
+ 'long_string':
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ 'abcdefghijklmnopqrstuvwxyz0123456789'
+ },
+ 'targets': [
+ {
+ 'target_name': 'multiple_action_target',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'action1',
+ 'inputs': [
+ 'copy.py',
+ 'input.txt',
+ ],
+ 'outputs': [
+ 'output1.txt',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'action2',
+ 'inputs': [
+ 'copy.py',
+ 'input.txt',
+ ],
+ 'outputs': [
+ 'output2.txt',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'action3',
+ 'inputs': [
+ 'copy.py',
+ 'input.txt',
+ ],
+ 'outputs': [
+ 'output3.txt',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'action4',
+ 'inputs': [
+ 'copy.py',
+ 'input.txt',
+ ],
+ 'outputs': [
+ 'output4.txt',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'multiple_action_source_filter',
+ 'type': 'executable',
+ 'sources': [
+ 'main.c',
+ # TODO(bradnelson): add foo.c here once this issue is fixed:
+ # http://code.google.com/p/gyp/issues/detail?id=175
+ ],
+ 'actions': [
+ {
+ 'action_name': 'action1',
+ 'inputs': [
+ 'foo.c',
+ 'filter.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/output1.c',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'action': [
+ 'python', 'filter.py', 'foo', 'bar', 'foo.c', '<@(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'action2',
+ 'inputs': [
+ 'foo.c',
+ 'filter.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/output2.c',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'action': [
+ 'python', 'filter.py', 'foo', 'car', 'foo.c', '<@(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'action3',
+ 'inputs': [
+ 'foo.c',
+ 'filter.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/output3.c',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'action': [
+ 'python', 'filter.py', 'foo', 'dar', 'foo.c', '<@(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'action4',
+ 'inputs': [
+ 'foo.c',
+ 'filter.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/output4.c',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'action': [
+ 'python', 'filter.py', 'foo', 'ear', 'foo.c', '<@(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'multiple_dependent_target',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'action1',
+ 'inputs': [
+ 'copy.py',
+ 'input.txt',
+ ],
+ 'outputs': [
+ 'multi1.txt',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'action2',
+ 'inputs': [
+ 'copy.py',
+ 'input.txt',
+ ],
+ 'outputs': [
+ 'multi2.txt',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ 'dependencies': [
+ 'multiple_required_target',
+ ],
+ },
+ {
+ 'target_name': 'multiple_required_target',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'multi_dep',
+ 'inputs': [
+ 'copy.py',
+ 'input.txt',
+ ],
+ 'outputs': [
+ 'multi_dep.txt',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'action': [
+ 'python', '<@(_inputs)', '<(_outputs)', '<(long_string)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions-none/src/none_with_source_files.gyp b/chromium/tools/gyp/test/actions-none/src/none_with_source_files.gyp
new file mode 100644
index 00000000000..e2aaebc10a6
--- /dev/null
+++ b/chromium/tools/gyp/test/actions-none/src/none_with_source_files.gyp
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Test that 'none' type targets can have .cc files in them.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'none_with_sources',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'foo.cc',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'fake_cross',
+ 'inputs': [
+ 'fake_cross.py',
+ '<@(_sources)',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/fake.out',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<@(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ }
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions-subdir/src/none.gyp b/chromium/tools/gyp/test/actions-subdir/src/none.gyp
new file mode 100644
index 00000000000..23f8d25a53e
--- /dev/null
+++ b/chromium/tools/gyp/test/actions-subdir/src/none.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'file',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'actions': [
+ {
+ 'action_name': 'make-file',
+ 'inputs': [
+ 'make-file.py',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/file.out',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ }
+ ],
+ 'dependencies': [
+ 'subdir/subdir.gyp:subdir_file',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions-subdir/src/subdir/subdir.gyp b/chromium/tools/gyp/test/actions-subdir/src/subdir/subdir.gyp
new file mode 100644
index 00000000000..0315d4eb83f
--- /dev/null
+++ b/chromium/tools/gyp/test/actions-subdir/src/subdir/subdir.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'subdir_file',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'actions': [
+ {
+ 'action_name': 'make-subdir-file',
+ 'inputs': [
+ 'make-subdir-file.py',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/subdir_file.out',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ }
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions/generated-header/test.gyp b/chromium/tools/gyp/test/actions/generated-header/test.gyp
new file mode 100644
index 00000000000..209b951ef6c
--- /dev/null
+++ b/chromium/tools/gyp/test/actions/generated-header/test.gyp
@@ -0,0 +1,34 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'generate_header',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'inputs': [ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/MyHeader.h',
+ ],
+ 'action_name': 'generate header',
+ 'action': ['python', './action.py',
+ '<(SHARED_INTERMEDIATE_DIR)/MyHeader.h', 'foobar output' ],
+ },
+ ],
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'dependencies': [
+ 'generate_header',
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'sources': [ 'main.cc' ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions/src/action_missing_name.gyp b/chromium/tools/gyp/test/actions/src/action_missing_name.gyp
new file mode 100644
index 00000000000..00424c35a11
--- /dev/null
+++ b/chromium/tools/gyp/test/actions/src/action_missing_name.gyp
@@ -0,0 +1,24 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'broken_actions2',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'inputs': [
+ 'no_name.input',
+ ],
+ 'action': [
+ 'python',
+ '-c',
+ 'print \'missing name\'',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions/src/actions.gyp b/chromium/tools/gyp/test/actions/src/actions.gyp
new file mode 100644
index 00000000000..5d2db1955e2
--- /dev/null
+++ b/chromium/tools/gyp/test/actions/src/actions.gyp
@@ -0,0 +1,114 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'pull_in_all_actions',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir1/executable.gyp:*',
+ 'subdir2/none.gyp:*',
+ 'subdir3/null_input.gyp:*',
+ ],
+ },
+ {
+ 'target_name': 'depend_on_always_run_action',
+ 'type': 'none',
+ 'dependencies': [ 'subdir1/executable.gyp:counter' ],
+ 'actions': [
+ {
+ 'action_name': 'use_always_run_output',
+ 'inputs': [
+ 'subdir1/actions-out/action-counter.txt',
+ 'subdir1/counter.py',
+ ],
+ 'outputs': [
+ 'subdir1/actions-out/action-counter_2.txt',
+ ],
+ 'action': [
+ 'python', 'subdir1/counter.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+
+ # Three deps which don't finish immediately.
+ # Each one has a small delay then creates a file.
+ # Delays are 1.0, 1.1, and 2.0 seconds.
+ {
+ 'target_name': 'dep_1',
+ 'type': 'none',
+ 'actions': [{
+ 'inputs': [ 'actions.gyp' ],
+ 'outputs': [ 'dep_1.txt' ],
+ 'action_name': 'dep_1',
+ 'action': [ 'python', '-c',
+ 'import time; time.sleep(1); open(\'dep_1.txt\', \'w\')' ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ }],
+ },
+ {
+ 'target_name': 'dep_2',
+ 'type': 'none',
+ 'actions': [{
+ 'inputs': [ 'actions.gyp' ],
+ 'outputs': [ 'dep_2.txt' ],
+ 'action_name': 'dep_2',
+ 'action': [ 'python', '-c',
+ 'import time; time.sleep(1.1); open(\'dep_2.txt\', \'w\')' ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ }],
+ },
+ {
+ 'target_name': 'dep_3',
+ 'type': 'none',
+ 'actions': [{
+ 'inputs': [ 'actions.gyp' ],
+ 'outputs': [ 'dep_3.txt' ],
+ 'action_name': 'dep_3',
+ 'action': [ 'python', '-c',
+ 'import time; time.sleep(2.0); open(\'dep_3.txt\', \'w\')' ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ }],
+ },
+
+ # An action which assumes the deps have completed.
+ # Does NOT list the output files of it's deps as inputs.
+ # On success create the file deps_all_done_first.txt.
+ {
+ 'target_name': 'action_with_dependencies_123',
+ 'type': 'none',
+ 'dependencies': [ 'dep_1', 'dep_2', 'dep_3' ],
+ 'actions': [{
+ 'inputs': [ 'actions.gyp' ],
+ 'outputs': [ 'deps_all_done_first_123.txt' ],
+ 'action_name': 'action_with_dependencies_123',
+ 'action': [ 'python', 'confirm-dep-files.py', '<(_outputs)' ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ }],
+ },
+ # Same as above but with deps in reverse.
+ {
+ 'target_name': 'action_with_dependencies_321',
+ 'type': 'none',
+ 'dependencies': [ 'dep_3', 'dep_2', 'dep_1' ],
+ 'actions': [{
+ 'inputs': [ 'actions.gyp' ],
+ 'outputs': [ 'deps_all_done_first_321.txt' ],
+ 'action_name': 'action_with_dependencies_321',
+ 'action': [ 'python', 'confirm-dep-files.py', '<(_outputs)' ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ }],
+ },
+
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions/src/subdir1/executable.gyp b/chromium/tools/gyp/test/actions/src/subdir1/executable.gyp
new file mode 100644
index 00000000000..6a1ce4f91e0
--- /dev/null
+++ b/chromium/tools/gyp/test/actions/src/subdir1/executable.gyp
@@ -0,0 +1,74 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'program.c',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'make-prog1',
+ 'inputs': [
+ 'make-prog1.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/prog1.c',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ {
+ 'action_name': 'make-prog2',
+ 'inputs': [
+ 'make-prog2.py',
+ ],
+ 'outputs': [
+ 'actions-out/prog2.c',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'counter',
+ 'type': 'none',
+ 'actions': [
+ {
+ # This action should always run, regardless of whether or not it's
+ # inputs or the command-line change. We do this by creating a dummy
+ # first output, which is always missing, thus causing the build to
+ # always try to recreate it. Actual output files should be listed
+ # after the dummy one, and dependent targets should list the real
+ # output(s) in their inputs
+ # (see '../actions.gyp:depend_on_always_run_action').
+ 'action_name': 'action_counter',
+ 'inputs': [
+ 'counter.py',
+ ],
+ 'outputs': [
+ 'actions-out/action-counter.txt.always',
+ 'actions-out/action-counter.txt',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', 'actions-out/action-counter.txt', '2',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions/src/subdir2/none.gyp b/chromium/tools/gyp/test/actions/src/subdir2/none.gyp
new file mode 100644
index 00000000000..2caa97d55c9
--- /dev/null
+++ b/chromium/tools/gyp/test/actions/src/subdir2/none.gyp
@@ -0,0 +1,33 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'file',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'actions': [
+ {
+ 'action_name': 'make-file',
+ 'inputs': [
+ 'make-file.py',
+ ],
+ 'outputs': [
+ 'file.out',
+ # TODO: enhance testing infrastructure to test this
+ # without having to hard-code the intermediate dir paths.
+ #'<(INTERMEDIATE_DIR)/file.out',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ }
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/actions/src/subdir3/null_input.gyp b/chromium/tools/gyp/test/actions/src/subdir3/null_input.gyp
new file mode 100644
index 00000000000..9b0bea5fdb4
--- /dev/null
+++ b/chromium/tools/gyp/test/actions/src/subdir3/null_input.gyp
@@ -0,0 +1,29 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'null_input',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'actions': [
+ {
+ 'action_name': 'generate_main',
+ 'process_outputs_as_sources': 1,
+ 'inputs': [],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/main.c',
+ ],
+ 'action': [
+ # TODO: we can't just use <(_outputs) here?!
+ 'python', 'generate_main.py', '<(INTERMEDIATE_DIR)/main.c',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/additional-targets/src/all.gyp b/chromium/tools/gyp/test/additional-targets/src/all.gyp
new file mode 100644
index 00000000000..21c83080aaf
--- /dev/null
+++ b/chromium/tools/gyp/test/additional-targets/src/all.gyp
@@ -0,0 +1,13 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'all_targets',
+ 'type': 'none',
+ 'dependencies': ['dir1/actions.gyp:*'],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/additional-targets/src/dir1/actions.gyp b/chromium/tools/gyp/test/additional-targets/src/dir1/actions.gyp
new file mode 100644
index 00000000000..5089c809131
--- /dev/null
+++ b/chromium/tools/gyp/test/additional-targets/src/dir1/actions.gyp
@@ -0,0 +1,56 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'action1_target',
+ 'type': 'none',
+ 'suppress_wildcard': 1,
+ 'actions': [
+ {
+ 'action_name': 'action1',
+ 'inputs': [
+ 'emit.py',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/out.txt',
+ ],
+ 'action': ['python', 'emit.py', '<(PRODUCT_DIR)/out.txt'],
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'action2_target',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'action2',
+ 'inputs': [
+ 'emit.py',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/out2.txt',
+ ],
+ 'action': ['python', 'emit.py', '<(PRODUCT_DIR)/out2.txt'],
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'foolib1',
+ 'type': 'shared_library',
+ 'suppress_wildcard': 1,
+ 'sources': ['lib1.c'],
+ },
+ ],
+ 'conditions': [
+ ['OS=="linux"', {
+ 'target_defaults': {
+ 'cflags': ['-fPIC'],
+ },
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/assembly/src/assembly.gyp b/chromium/tools/gyp/test/assembly/src/assembly.gyp
new file mode 100644
index 00000000000..565cb0fa0e3
--- /dev/null
+++ b/chromium/tools/gyp/test/assembly/src/assembly.gyp
@@ -0,0 +1,62 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'conditions': [
+ ['OS=="win"', {
+ 'defines': ['PLATFORM_WIN'],
+ }],
+ ['OS=="mac" or OS=="ios"', {
+ 'defines': ['PLATFORM_MAC'],
+ }],
+ ['OS=="linux"', {
+ 'defines': ['PLATFORM_LINUX'],
+ }],
+ ['OS=="android"', {
+ 'defines': ['PLATFORM_ANDROID'],
+ }],
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'dependencies': ['lib1'],
+ 'sources': [
+ 'program.c',
+ ],
+ },
+ {
+ 'target_name': 'lib1',
+ 'type': 'static_library',
+ 'sources': [
+ 'lib1.S',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'target_defaults': {
+ 'rules': [
+ {
+ 'rule_name': 'assembler',
+ 'msvs_cygwin_shell': 0,
+ 'extension': 'S',
+ 'inputs': [
+ 'as.bat',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).obj',
+ ],
+ 'action':
+ ['as.bat', 'lib1.c', '<(_outputs)'],
+ 'message': 'Building assembly file <(RULE_INPUT_PATH)',
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ },],
+ ],
+}
diff --git a/chromium/tools/gyp/test/assembly/src/override.gyp b/chromium/tools/gyp/test/assembly/src/override.gyp
new file mode 100644
index 00000000000..39a4072effc
--- /dev/null
+++ b/chromium/tools/gyp/test/assembly/src/override.gyp
@@ -0,0 +1,34 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'sources': [
+ 'program.c',
+ 'override_asm.asm',
+ ],
+ 'rules': [
+ {
+ # Test that if there's a specific .asm rule, it overrides the
+ # built in one on Windows.
+ 'rule_name': 'assembler',
+ 'msvs_cygwin_shell': 0,
+ 'extension': 'asm',
+ 'inputs': [
+ 'as.bat',
+ ],
+ 'outputs': [
+ 'output.obj',
+ ],
+ 'action': ['as.bat', 'lib1.c', '<(_outputs)'],
+ 'message': 'Building assembly file <(RULE_INPUT_PATH)',
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/build-option/hello.gyp b/chromium/tools/gyp/test/build-option/hello.gyp
new file mode 100644
index 00000000000..1974d51ccd1
--- /dev/null
+++ b/chromium/tools/gyp/test/build-option/hello.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/builddir/src/builddir.gypi b/chromium/tools/gyp/test/builddir/src/builddir.gypi
new file mode 100644
index 00000000000..ce175db8f84
--- /dev/null
+++ b/chromium/tools/gyp/test/builddir/src/builddir.gypi
@@ -0,0 +1,18 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'configurations': {
+ 'Default': {
+ 'msvs_configuration_attributes': {
+ 'OutputDirectory': '<(DEPTH)\\builddir/Default',
+ },
+ },
+ },
+ },
+ 'xcode_settings': {
+ 'SYMROOT': '<(DEPTH)/builddir',
+ },
+}
diff --git a/chromium/tools/gyp/test/builddir/src/prog1.gyp b/chromium/tools/gyp/test/builddir/src/prog1.gyp
new file mode 100644
index 00000000000..5b96f035ec7
--- /dev/null
+++ b/chromium/tools/gyp/test/builddir/src/prog1.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ 'builddir.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'pull_in_all',
+ 'type': 'none',
+ 'dependencies': [
+ 'prog1',
+ 'subdir2/prog2.gyp:prog2',
+ 'subdir2/subdir3/prog3.gyp:prog3',
+ 'subdir2/subdir3/subdir4/prog4.gyp:prog4',
+ 'subdir2/subdir3/subdir4/subdir5/prog5.gyp:prog5',
+ ],
+ },
+ {
+ 'target_name': 'prog1',
+ 'type': 'executable',
+ 'sources': [
+ 'prog1.c',
+ 'func1.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/builddir/src/subdir2/prog2.gyp b/chromium/tools/gyp/test/builddir/src/subdir2/prog2.gyp
new file mode 100644
index 00000000000..96299b646d2
--- /dev/null
+++ b/chromium/tools/gyp/test/builddir/src/subdir2/prog2.gyp
@@ -0,0 +1,19 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../builddir.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog2',
+ 'type': 'executable',
+ 'sources': [
+ 'prog2.c',
+ '../func2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp b/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp
new file mode 100644
index 00000000000..d7df43c7bde
--- /dev/null
+++ b/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/prog3.gyp
@@ -0,0 +1,19 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../../builddir.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog3',
+ 'type': 'executable',
+ 'sources': [
+ 'prog3.c',
+ '../../func3.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp b/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp
new file mode 100644
index 00000000000..862a8a18cd7
--- /dev/null
+++ b/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/prog4.gyp
@@ -0,0 +1,19 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../../../builddir.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog4',
+ 'type': 'executable',
+ 'sources': [
+ 'prog4.c',
+ '../../../func4.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp b/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp
new file mode 100644
index 00000000000..fe1c9cbf50f
--- /dev/null
+++ b/chromium/tools/gyp/test/builddir/src/subdir2/subdir3/subdir4/subdir5/prog5.gyp
@@ -0,0 +1,19 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../../../../builddir.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog5',
+ 'type': 'executable',
+ 'sources': [
+ 'prog5.c',
+ '../../../../func5.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/cflags/cflags.gyp b/chromium/tools/gyp/test/cflags/cflags.gyp
new file mode 100644
index 00000000000..9003fb16794
--- /dev/null
+++ b/chromium/tools/gyp/test/cflags/cflags.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'cflags',
+ 'type': 'executable',
+ 'opt': '-Os',
+ 'sources': [
+ 'cflags.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/compilable/src/headers.gyp b/chromium/tools/gyp/test/compilable/src/headers.gyp
new file mode 100644
index 00000000000..b6c2a8857be
--- /dev/null
+++ b/chromium/tools/gyp/test/compilable/src/headers.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'dependencies': [
+ 'lib1'
+ ],
+ 'sources': [
+ 'program.cpp',
+ ],
+ },
+ {
+ 'target_name': 'lib1',
+ 'type': 'static_library',
+ 'sources': [
+ 'lib1.hpp',
+ 'lib1.cpp',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/compiler-override/compiler-host.gyp b/chromium/tools/gyp/test/compiler-override/compiler-host.gyp
new file mode 100644
index 00000000000..05b0368d4c2
--- /dev/null
+++ b/chromium/tools/gyp/test/compiler-override/compiler-host.gyp
@@ -0,0 +1,17 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'toolset': 'host',
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'test.c',
+ 'cxxtest.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/compiler-override/compiler.gyp b/chromium/tools/gyp/test/compiler-override/compiler.gyp
new file mode 100644
index 00000000000..c2f3002f207
--- /dev/null
+++ b/chromium/tools/gyp/test/compiler-override/compiler.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'test.c',
+ 'cxxtest.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/basics/configurations.gyp b/chromium/tools/gyp/test/configurations/basics/configurations.gyp
new file mode 100644
index 00000000000..93f1d8d5c7f
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/basics/configurations.gyp
@@ -0,0 +1,32 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'executable',
+ 'sources': [
+ 'configurations.c',
+ ],
+ 'configurations': {
+ 'Debug': {
+ 'defines': [
+ 'DEBUG',
+ ],
+ },
+ 'Release': {
+ 'defines': [
+ 'RELEASE',
+ ],
+ },
+ 'Foo': {
+ 'defines': [
+ 'FOO',
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/inheritance/configurations.gyp b/chromium/tools/gyp/test/configurations/inheritance/configurations.gyp
new file mode 100644
index 00000000000..9441376b4d1
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/inheritance/configurations.gyp
@@ -0,0 +1,40 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'configurations': {
+ 'Base': {
+ 'abstract': 1,
+ 'defines': ['BASE'],
+ },
+ 'Common': {
+ 'abstract': 1,
+ 'inherit_from': ['Base'],
+ 'defines': ['COMMON'],
+ },
+ 'Common2': {
+ 'abstract': 1,
+ 'defines': ['COMMON2'],
+ },
+ 'Debug': {
+ 'inherit_from': ['Common', 'Common2'],
+ 'defines': ['DEBUG'],
+ },
+ 'Release': {
+ 'inherit_from': ['Common', 'Common2'],
+ 'defines': ['RELEASE'],
+ },
+ },
+ },
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'executable',
+ 'sources': [
+ 'configurations.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/actions.gyp b/chromium/tools/gyp/test/configurations/invalid/actions.gyp
new file mode 100644
index 00000000000..a6e42089eba
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/actions.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'actions': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp b/chromium/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp
new file mode 100644
index 00000000000..b16a245df54
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/all_dependent_settings.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'all_dependent_settings': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/configurations.gyp b/chromium/tools/gyp/test/configurations/invalid/configurations.gyp
new file mode 100644
index 00000000000..2cfc9600498
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/configurations.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'configurations': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/dependencies.gyp b/chromium/tools/gyp/test/configurations/invalid/dependencies.gyp
new file mode 100644
index 00000000000..74633f3f111
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/dependencies.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'dependencies': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp b/chromium/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp
new file mode 100644
index 00000000000..8a0f2e95ea7
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/direct_dependent_settings.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'direct_dependent_settings': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/libraries.gyp b/chromium/tools/gyp/test/configurations/invalid/libraries.gyp
new file mode 100644
index 00000000000..c4014ed4065
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/libraries.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'libraries': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/link_settings.gyp b/chromium/tools/gyp/test/configurations/invalid/link_settings.gyp
new file mode 100644
index 00000000000..2f0e1c46f5c
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/link_settings.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'link_settings': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/sources.gyp b/chromium/tools/gyp/test/configurations/invalid/sources.gyp
new file mode 100644
index 00000000000..b38cca03818
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/sources.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'sources': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/standalone_static_library.gyp b/chromium/tools/gyp/test/configurations/invalid/standalone_static_library.gyp
new file mode 100644
index 00000000000..2edb9febd64
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/standalone_static_library.gyp
@@ -0,0 +1,17 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'standalone_static_library': 1,
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/target_name.gyp b/chromium/tools/gyp/test/configurations/invalid/target_name.gyp
new file mode 100644
index 00000000000..83baad95d60
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/target_name.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'target_name': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/invalid/type.gyp b/chromium/tools/gyp/test/configurations/invalid/type.gyp
new file mode 100644
index 00000000000..bc55898b89e
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/invalid/type.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'none',
+ 'configurations': {
+ 'Debug': {
+ 'type': [
+ ],
+ },
+ }
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/target_platform/configurations.gyp b/chromium/tools/gyp/test/configurations/target_platform/configurations.gyp
new file mode 100644
index 00000000000..d15429f4e5d
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/target_platform/configurations.gyp
@@ -0,0 +1,58 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'configurations': {
+ 'Debug_Win32': {
+ 'msvs_configuration_platform': 'Win32',
+ },
+ 'Debug_x64': {
+ 'msvs_configuration_platform': 'x64',
+ },
+ },
+ },
+ 'targets': [
+ {
+ 'target_name': 'left',
+ 'type': 'static_library',
+ 'sources': [
+ 'left.c',
+ ],
+ 'configurations': {
+ 'Debug_Win32': {
+ 'msvs_target_platform': 'x64',
+ },
+ },
+ },
+ {
+ 'target_name': 'right',
+ 'type': 'static_library',
+ 'sources': [
+ 'right.c',
+ ],
+ },
+ {
+ 'target_name': 'front_left',
+ 'type': 'executable',
+ 'dependencies': ['left'],
+ 'sources': [
+ 'front.c',
+ ],
+ 'configurations': {
+ 'Debug_Win32': {
+ 'msvs_target_platform': 'x64',
+ },
+ },
+ },
+ {
+ 'target_name': 'front_right',
+ 'type': 'executable',
+ 'dependencies': ['right'],
+ 'sources': [
+ 'front.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/configurations/x64/configurations.gyp b/chromium/tools/gyp/test/configurations/x64/configurations.gyp
new file mode 100644
index 00000000000..8b0139f1418
--- /dev/null
+++ b/chromium/tools/gyp/test/configurations/x64/configurations.gyp
@@ -0,0 +1,38 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'configurations': {
+ 'Debug': {
+ 'msvs_configuration_platform': 'Win32',
+ },
+ 'Debug_x64': {
+ 'inherit_from': ['Debug'],
+ 'msvs_configuration_platform': 'x64',
+ },
+ },
+ },
+ 'targets': [
+ {
+ 'target_name': 'configurations',
+ 'type': 'executable',
+ 'sources': [
+ 'configurations.c',
+ ],
+ },
+ {
+ 'target_name': 'configurations64',
+ 'type': 'executable',
+ 'sources': [
+ 'configurations.c',
+ ],
+ 'configurations': {
+ 'Debug': {
+ 'msvs_target_platform': 'x64',
+ },
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/copies/src/copies-samedir.gyp b/chromium/tools/gyp/test/copies/src/copies-samedir.gyp
new file mode 100644
index 00000000000..2919ce503ed
--- /dev/null
+++ b/chromium/tools/gyp/test/copies/src/copies-samedir.gyp
@@ -0,0 +1,37 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'copies_samedir',
+ 'type': 'none',
+ 'dependencies': [
+ 'copies_samedir_dependency',
+ ],
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out-samedir',
+ 'files': [
+ 'file1',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'copies_samedir_dependency',
+ 'type': 'none',
+ 'direct_dependent_settings': {
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out-samedir',
+ 'files': [
+ 'file2',
+ ],
+ },
+ ],
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/copies/src/copies-slash.gyp b/chromium/tools/gyp/test/copies/src/copies-slash.gyp
new file mode 100644
index 00000000000..9bf54bd1814
--- /dev/null
+++ b/chromium/tools/gyp/test/copies/src/copies-slash.gyp
@@ -0,0 +1,36 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # A trailing slash on the destination directory should be ignored.
+ {
+ 'target_name': 'copies_recursive_trailing_slash',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out-slash/',
+ 'files': [
+ 'directory/',
+ ],
+ },
+ ],
+ },
+ # Even if the source directory is below <(PRODUCT_DIR).
+ {
+ 'target_name': 'copies_recursive_trailing_slash_in_product_dir',
+ 'type': 'none',
+ 'dependencies': [ ':copies_recursive_trailing_slash' ],
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out-slash-2/',
+ 'files': [
+ '<(PRODUCT_DIR)/copies-out-slash/directory/',
+ ],
+ },
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/copies/src/copies-updir.gyp b/chromium/tools/gyp/test/copies/src/copies-updir.gyp
new file mode 100644
index 00000000000..bd3bfdd1d2e
--- /dev/null
+++ b/chromium/tools/gyp/test/copies/src/copies-updir.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'copies_up',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/../copies-out-updir',
+ 'files': [
+ 'file1',
+ ],
+ },
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/copies/src/copies.gyp b/chromium/tools/gyp/test/copies/src/copies.gyp
new file mode 100644
index 00000000000..ce2e0cabca5
--- /dev/null
+++ b/chromium/tools/gyp/test/copies/src/copies.gyp
@@ -0,0 +1,70 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'copies1',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': 'copies-out',
+ 'files': [
+ 'file1',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'copies2',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out',
+ 'files': [
+ 'file2',
+ ],
+ },
+ ],
+ },
+ # Copy a directory tree.
+ {
+ 'target_name': 'copies_recursive',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out',
+ 'files': [
+ 'directory/',
+ ],
+ },
+ ],
+ },
+ # Copy a directory from deeper in the tree (this should not reproduce the
+ # entire directory path in the destination, only the final directory).
+ {
+ 'target_name': 'copies_recursive_depth',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out',
+ 'files': [
+ 'parentdir/subdir/',
+ ],
+ },
+ ],
+ },
+ # Verify that a null 'files' list doesn't gag the generators.
+ {
+ 'target_name': 'copies_null',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-null',
+ 'files': [],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/custom-generator/test.gyp b/chromium/tools/gyp/test/custom-generator/test.gyp
new file mode 100644
index 00000000000..aa5f864a3b7
--- /dev/null
+++ b/chromium/tools/gyp/test/custom-generator/test.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'exe',
+ 'type': 'executable',
+ 'sources': [
+ 'main.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/cxxflags/cxxflags.gyp b/chromium/tools/gyp/test/cxxflags/cxxflags.gyp
new file mode 100644
index 00000000000..24d883aaed6
--- /dev/null
+++ b/chromium/tools/gyp/test/cxxflags/cxxflags.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'cxxflags',
+ 'type': 'executable',
+ 'opt': '-Os',
+ 'sources': [
+ 'cxxflags.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/defines-escaping/defines-escaping.gyp b/chromium/tools/gyp/test/defines-escaping/defines-escaping.gyp
new file mode 100644
index 00000000000..6f0f3fde41f
--- /dev/null
+++ b/chromium/tools/gyp/test/defines-escaping/defines-escaping.gyp
@@ -0,0 +1,19 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'defines_escaping',
+ 'type': 'executable',
+ 'sources': [
+ 'defines-escaping.c',
+ ],
+ 'defines': [
+ 'TEST_FORMAT="<(test_format)"',
+ 'TEST_ARGS=<(test_args)',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/defines/defines-env.gyp b/chromium/tools/gyp/test/defines/defines-env.gyp
new file mode 100644
index 00000000000..1781546ae08
--- /dev/null
+++ b/chromium/tools/gyp/test/defines/defines-env.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'value%': '5',
+ },
+ 'targets': [
+ {
+ 'target_name': 'defines',
+ 'type': 'executable',
+ 'sources': [
+ 'defines.c',
+ ],
+ 'defines': [
+ 'VALUE=<(value)',
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/defines/defines.gyp b/chromium/tools/gyp/test/defines/defines.gyp
new file mode 100644
index 00000000000..90a755eb84a
--- /dev/null
+++ b/chromium/tools/gyp/test/defines/defines.gyp
@@ -0,0 +1,38 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'defines',
+ 'type': 'executable',
+ 'sources': [
+ 'defines.c',
+ ],
+ 'defines': [
+ 'FOO',
+ 'VALUE=1',
+ 'PAREN_VALUE=(1+2+3)',
+ 'HASH_VALUE="a#1"',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="fakeos"', {
+ 'targets': [
+ {
+ 'target_name': 'fakeosprogram',
+ 'type': 'executable',
+ 'sources': [
+ 'defines.c',
+ ],
+ 'defines': [
+ 'FOO',
+ 'VALUE=1',
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/dependencies/b/b.gyp b/chromium/tools/gyp/test/dependencies/b/b.gyp
new file mode 100755
index 00000000000..893dc64d652
--- /dev/null
+++ b/chromium/tools/gyp/test/dependencies/b/b.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'b',
+ 'type': 'static_library',
+ 'sources': [
+ 'b.c',
+ ],
+ },
+ {
+ 'target_name': 'b3',
+ 'type': 'static_library',
+ 'sources': [
+ 'b3.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/dependencies/c/c.gyp b/chromium/tools/gyp/test/dependencies/c/c.gyp
new file mode 100644
index 00000000000..eabebea9efb
--- /dev/null
+++ b/chromium/tools/gyp/test/dependencies/c/c.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'c_unused',
+ 'type': 'static_library',
+ 'sources': [
+ 'c.c',
+ ],
+ },
+ {
+ 'target_name': 'd',
+ 'type': 'static_library',
+ 'sources': [
+ 'd.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/dependencies/double_dependency.gyp b/chromium/tools/gyp/test/dependencies/double_dependency.gyp
new file mode 100644
index 00000000000..c4a2d00139d
--- /dev/null
+++ b/chromium/tools/gyp/test/dependencies/double_dependency.gyp
@@ -0,0 +1,23 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'double_dependency',
+ 'type': 'shared_library',
+ 'dependencies': [
+ 'double_dependent.gyp:double_dependent',
+ ],
+ 'conditions': [
+ ['1==1', {
+ 'dependencies': [
+ 'double_dependent.gyp:*',
+ ],
+ }],
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/dependencies/double_dependent.gyp b/chromium/tools/gyp/test/dependencies/double_dependent.gyp
new file mode 100644
index 00000000000..334caff723c
--- /dev/null
+++ b/chromium/tools/gyp/test/dependencies/double_dependent.gyp
@@ -0,0 +1,12 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'double_dependent',
+ 'type': 'none',
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/dependencies/extra_targets.gyp b/chromium/tools/gyp/test/dependencies/extra_targets.gyp
new file mode 100644
index 00000000000..c1a26de4228
--- /dev/null
+++ b/chromium/tools/gyp/test/dependencies/extra_targets.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'static_library',
+ 'sources': [
+ 'a.c',
+ ],
+ # This only depends on the "d" target; other targets in c.gyp
+ # should not become part of the build (unlike with 'c/c.gyp:*').
+ 'dependencies': ['c/c.gyp:d'],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/dependencies/lib_only.gyp b/chromium/tools/gyp/test/dependencies/lib_only.gyp
new file mode 100755
index 00000000000..f6c84dea64f
--- /dev/null
+++ b/chromium/tools/gyp/test/dependencies/lib_only.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'static_library',
+ 'sources': [
+ 'a.c',
+ ],
+ 'dependencies': ['b/b.gyp:b'],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/dependencies/none_traversal.gyp b/chromium/tools/gyp/test/dependencies/none_traversal.gyp
new file mode 100755
index 00000000000..3d8ab30aff5
--- /dev/null
+++ b/chromium/tools/gyp/test/dependencies/none_traversal.gyp
@@ -0,0 +1,46 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'needs_chain',
+ 'type': 'executable',
+ 'sources': [
+ 'a.c',
+ 'main.c',
+ ],
+ 'dependencies': ['chain'],
+ },
+ {
+ 'target_name': 'chain',
+ 'type': 'none',
+ 'dependencies': ['b/b.gyp:b'],
+ },
+ {
+ 'target_name': 'doesnt_need_chain',
+ 'type': 'executable',
+ 'sources': [
+ 'main.c',
+ ],
+ 'dependencies': ['no_chain', 'other_chain'],
+ },
+ {
+ 'target_name': 'no_chain',
+ 'type': 'none',
+ 'sources': [
+ ],
+ 'dependencies': ['b/b.gyp:b'],
+ 'dependencies_traverse': 0,
+ },
+ {
+ 'target_name': 'other_chain',
+ 'type': 'static_library',
+ 'sources': [
+ 'a.c',
+ ],
+ 'dependencies': ['b/b.gyp:b3'],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/dependency-copy/src/copies.gyp b/chromium/tools/gyp/test/dependency-copy/src/copies.gyp
new file mode 100644
index 00000000000..4176b18787b
--- /dev/null
+++ b/chromium/tools/gyp/test/dependency-copy/src/copies.gyp
@@ -0,0 +1,25 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'proj1',
+ 'type': 'executable',
+ 'sources': [
+ 'file1.c',
+ ],
+ },
+ {
+ 'target_name': 'proj2',
+ 'type': 'executable',
+ 'sources': [
+ 'file2.c',
+ ],
+ 'dependencies': [
+ 'proj1',
+ ]
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/errors/duplicate_basenames.gyp b/chromium/tools/gyp/test/errors/duplicate_basenames.gyp
new file mode 100644
index 00000000000..b3dceb3949b
--- /dev/null
+++ b/chromium/tools/gyp/test/errors/duplicate_basenames.gyp
@@ -0,0 +1,13 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'foo',
+ 'type': 'static_library',
+ 'sources': ['foo.c', 'foo.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/errors/duplicate_node.gyp b/chromium/tools/gyp/test/errors/duplicate_node.gyp
new file mode 100644
index 00000000000..d6096096bd8
--- /dev/null
+++ b/chromium/tools/gyp/test/errors/duplicate_node.gyp
@@ -0,0 +1,12 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ { 'target_name' : 'foo', 'type': 'executable' },
+ ],
+ 'targets': [
+ { 'target_name' : 'bar', 'type': 'executable' },
+ ]
+}
diff --git a/chromium/tools/gyp/test/errors/duplicate_rule.gyp b/chromium/tools/gyp/test/errors/duplicate_rule.gyp
new file mode 100644
index 00000000000..dab98e96c2b
--- /dev/null
+++ b/chromium/tools/gyp/test/errors/duplicate_rule.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'foo',
+ 'type': 'executable',
+ 'rules': [
+ {
+ 'rule_name': 'bar',
+ 'extension': '',
+ },
+ {
+ 'rule_name': 'bar',
+ 'extension': '',
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/errors/duplicate_targets.gyp b/chromium/tools/gyp/test/errors/duplicate_targets.gyp
new file mode 100644
index 00000000000..aec470eefa8
--- /dev/null
+++ b/chromium/tools/gyp/test/errors/duplicate_targets.gyp
@@ -0,0 +1,14 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'foo'
+ },
+ {
+ 'target_name': 'foo'
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/errors/missing_dep.gyp b/chromium/tools/gyp/test/errors/missing_dep.gyp
new file mode 100644
index 00000000000..08746be3d7a
--- /dev/null
+++ b/chromium/tools/gyp/test/errors/missing_dep.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'foo',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'missing.gyp'
+ ]
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/errors/missing_targets.gyp b/chromium/tools/gyp/test/errors/missing_targets.gyp
new file mode 100644
index 00000000000..13d4f924c19
--- /dev/null
+++ b/chromium/tools/gyp/test/errors/missing_targets.gyp
@@ -0,0 +1,8 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ },
+}
diff --git a/chromium/tools/gyp/test/escaping/colon/test.gyp b/chromium/tools/gyp/test/escaping/colon/test.gyp
new file mode 100644
index 00000000000..715f95490e4
--- /dev/null
+++ b/chromium/tools/gyp/test/escaping/colon/test.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'colon',
+ 'type': 'executable',
+ 'sources': [
+ 'a:b.c',
+ ],
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/',
+ # MSVS2008 gets confused if the same file is in 'sources' and 'copies'
+ 'files': [ 'a:b.c-d', ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/exclusion/exclusion.gyp b/chromium/tools/gyp/test/exclusion/exclusion.gyp
new file mode 100644
index 00000000000..1232dabaef9
--- /dev/null
+++ b/chromium/tools/gyp/test/exclusion/exclusion.gyp
@@ -0,0 +1,23 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ 'bogus.c',
+ 'also/not/real.c',
+ 'also/not/real2.c',
+ ],
+ 'sources!': [
+ 'bogus.c',
+ 'also/not/real.c',
+ 'also/not/real2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/external-cross-compile/src/cross.gyp b/chromium/tools/gyp/test/external-cross-compile/src/cross.gyp
new file mode 100644
index 00000000000..aeda76b5bdf
--- /dev/null
+++ b/chromium/tools/gyp/test/external-cross-compile/src/cross.gyp
@@ -0,0 +1,83 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': ['cross_compile.gypi'],
+ 'target_defaults': {
+ 'variables': {
+ 'nix_lame%': 0,
+ },
+ 'target_conditions': [
+ ['nix_lame==1', {
+ 'sources/': [
+ ['exclude', 'lame'],
+ ],
+ }],
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'dependencies': [
+ 'program_inc',
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'sources': [
+ 'program.cc',
+ ],
+ },
+ {
+ 'target_name': 'program_inc',
+ 'type': 'none',
+ 'dependencies': ['cross_program'],
+ 'actions': [
+ {
+ 'action_name': 'program_inc',
+ 'inputs': ['<(SHARED_INTERMEDIATE_DIR)/cross_program.fake'],
+ 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/cross_program.h'],
+ 'action': ['python', 'tochar.py', '<@(_inputs)', '<@(_outputs)'],
+ },
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'target_name': 'cross_program',
+ 'type': 'none',
+ 'variables': {
+ 'cross': 1,
+ 'nix_lame': 1,
+ },
+ 'dependencies': ['cross_lib'],
+ 'sources': [
+ 'test1.cc',
+ 'test2.c',
+ 'very_lame.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/cross_lib.fake',
+ ],
+ },
+ {
+ 'target_name': 'cross_lib',
+ 'type': 'none',
+ 'variables': {
+ 'cross': 1,
+ 'nix_lame': 1,
+ },
+ 'sources': [
+ 'test3.cc',
+ 'test4.c',
+ 'bogus1.cc',
+ 'bogus2.c',
+ 'sort_of_lame.cc',
+ ],
+ 'sources!': [
+ 'bogus1.cc',
+ 'bogus2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/external-cross-compile/src/cross_compile.gypi b/chromium/tools/gyp/test/external-cross-compile/src/cross_compile.gypi
new file mode 100644
index 00000000000..36e651903f5
--- /dev/null
+++ b/chromium/tools/gyp/test/external-cross-compile/src/cross_compile.gypi
@@ -0,0 +1,23 @@
+{
+ 'target_defaults': {
+ 'variables': {
+ 'cross%': 0,
+ },
+ 'target_conditions': [
+ ['cross==1', {
+ 'actions': [
+ {
+ 'action_name': 'cross compile >(_target_name)',
+ 'inputs': ['^@(_sources)'],
+ 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/>(_target_name).fake'],
+ 'action': [
+ 'python', 'fake_cross.py', '>@(_outputs)', '^@(_sources)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ }],
+ ],
+ },
+}
diff --git a/chromium/tools/gyp/test/generator-output/actions/actions.gyp b/chromium/tools/gyp/test/generator-output/actions/actions.gyp
new file mode 100644
index 00000000000..dded59aff3e
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/actions/actions.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'pull_in_all_actions',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir1/executable.gyp:*',
+ 'subdir2/none.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/actions/subdir1/executable.gyp b/chromium/tools/gyp/test/generator-output/actions/subdir1/executable.gyp
new file mode 100644
index 00000000000..6bdd60a1fb7
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/actions/subdir1/executable.gyp
@@ -0,0 +1,44 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'program.c',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'make-prog1',
+ 'inputs': [
+ 'make-prog1.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/prog1.c',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ {
+ 'action_name': 'make-prog2',
+ 'inputs': [
+ 'make-prog2.py',
+ ],
+ 'outputs': [
+ 'actions-out/prog2.c',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/actions/subdir2/none.gyp b/chromium/tools/gyp/test/generator-output/actions/subdir2/none.gyp
new file mode 100644
index 00000000000..f98f52753d0
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/actions/subdir2/none.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'file',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'actions': [
+ {
+ 'action_name': 'make-file',
+ 'inputs': [
+ 'make-file.py',
+ ],
+ 'outputs': [
+ 'actions-out/file.out',
+ # TODO: enhance testing infrastructure to test this
+ # without having to hard-code the intermediate dir paths.
+ #'<(INTERMEDIATE_DIR)/file.out',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ }
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/copies/copies.gyp b/chromium/tools/gyp/test/generator-output/copies/copies.gyp
new file mode 100644
index 00000000000..479a3d9b6e8
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/copies/copies.gyp
@@ -0,0 +1,50 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'pull_in_subdir',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir/subdir.gyp:*',
+ ],
+ },
+ {
+ 'target_name': 'copies1',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': 'copies-out',
+ 'files': [
+ 'file1',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'copies2',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out',
+ 'files': [
+ 'file2',
+ ],
+ },
+ ],
+ },
+ # Verify that a null 'files' list doesn't gag the generators.
+ {
+ 'target_name': 'copies_null',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-null',
+ 'files': [],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/copies/subdir/subdir.gyp b/chromium/tools/gyp/test/generator-output/copies/subdir/subdir.gyp
new file mode 100644
index 00000000000..af031d283ae
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/copies/subdir/subdir.gyp
@@ -0,0 +1,32 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'copies3',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': 'copies-out',
+ 'files': [
+ 'file3',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'copies4',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/copies-out',
+ 'files': [
+ 'file4',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/mac-bundle/test.gyp b/chromium/tools/gyp/test/generator-output/mac-bundle/test.gyp
new file mode 100644
index 00000000000..35ac674f6d7
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/mac-bundle/test.gyp
@@ -0,0 +1,25 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test App Gyp',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'main.c',
+ ],
+ 'mac_bundle_resources': [
+ 'resource.sb',
+ ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ 'ORDER_FILE': 'app.order',
+ 'GCC_PREFIX_HEADER': 'header.h',
+ 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/rules/rules.gyp b/chromium/tools/gyp/test/generator-output/rules/rules.gyp
new file mode 100644
index 00000000000..dded59aff3e
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/rules/rules.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'pull_in_all_actions',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir1/executable.gyp:*',
+ 'subdir2/none.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/rules/subdir1/executable.gyp b/chromium/tools/gyp/test/generator-output/rules/subdir1/executable.gyp
new file mode 100644
index 00000000000..42bee4d7467
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/rules/subdir1/executable.gyp
@@ -0,0 +1,59 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'program.c',
+ 'function1.in1',
+ 'function2.in1',
+ 'define3.in0',
+ 'define4.in0',
+ ],
+ 'include_dirs': [
+ '<(INTERMEDIATE_DIR)',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file_0',
+ 'extension': 'in0',
+ 'inputs': [
+ '../copy-file.py',
+ ],
+ 'outputs': [
+ # TODO: fix Make to support generated files not
+ # in a variable-named path like <(INTERMEDIATE_DIR)
+ #'<(RULE_INPUT_ROOT).c',
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).h',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 0,
+ },
+ {
+ 'rule_name': 'copy_file_1',
+ 'extension': 'in1',
+ 'inputs': [
+ '../copy-file.py',
+ ],
+ 'outputs': [
+ # TODO: fix Make to support generated files not
+ # in a variable-named path like <(INTERMEDIATE_DIR)
+ #'<(RULE_INPUT_ROOT).c',
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/rules/subdir2/none.gyp b/chromium/tools/gyp/test/generator-output/rules/subdir2/none.gyp
new file mode 100644
index 00000000000..664cbd9cb75
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/rules/subdir2/none.gyp
@@ -0,0 +1,49 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'files',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'file1.in0',
+ 'file2.in0',
+ 'file3.in1',
+ 'file4.in1',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file_0',
+ 'extension': 'in0',
+ 'inputs': [
+ '../copy-file.py',
+ ],
+ 'outputs': [
+ 'rules-out/<(RULE_INPUT_ROOT).out',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 0,
+ },
+ {
+ 'rule_name': 'copy_file_1',
+ 'extension': 'in1',
+ 'inputs': [
+ '../copy-file.py',
+ ],
+ 'outputs': [
+ 'rules-out/<(RULE_INPUT_ROOT).out',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/src/prog1.gyp b/chromium/tools/gyp/test/generator-output/src/prog1.gyp
new file mode 100644
index 00000000000..d50e6fb0a7e
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/src/prog1.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ 'symroot.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog1',
+ 'type': 'executable',
+ 'dependencies': [
+ 'subdir2/prog2.gyp:prog2',
+ ],
+ 'include_dirs': [
+ '.',
+ 'inc1',
+ 'subdir2/inc2',
+ 'subdir3/inc3',
+ 'subdir2/deeper',
+ ],
+ 'sources': [
+ 'prog1.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp b/chromium/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp
new file mode 100644
index 00000000000..86487708723
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/src/subdir2/deeper/deeper.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../../symroot.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'deeper',
+ 'type': 'executable',
+ 'sources': [
+ 'deeper.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/src/subdir2/prog2.gyp b/chromium/tools/gyp/test/generator-output/src/subdir2/prog2.gyp
new file mode 100644
index 00000000000..7176ed8be74
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/src/subdir2/prog2.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../symroot.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog2',
+ 'type': 'executable',
+ 'include_dirs': [
+ '..',
+ '../inc1',
+ 'inc2',
+ '../subdir3/inc3',
+ 'deeper',
+ ],
+ 'dependencies': [
+ '../subdir3/prog3.gyp:prog3',
+ ],
+ 'sources': [
+ 'prog2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/src/subdir3/prog3.gyp b/chromium/tools/gyp/test/generator-output/src/subdir3/prog3.gyp
new file mode 100644
index 00000000000..46c5e000a27
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/src/subdir3/prog3.gyp
@@ -0,0 +1,25 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../symroot.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog3',
+ 'type': 'executable',
+ 'include_dirs': [
+ '..',
+ '../inc1',
+ '../subdir2/inc2',
+ 'inc3',
+ '../subdir2/deeper',
+ ],
+ 'sources': [
+ 'prog3.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/generator-output/src/symroot.gypi b/chromium/tools/gyp/test/generator-output/src/symroot.gypi
new file mode 100644
index 00000000000..519916427c9
--- /dev/null
+++ b/chromium/tools/gyp/test/generator-output/src/symroot.gypi
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'set_symroot%': 0,
+ },
+ 'conditions': [
+ ['set_symroot == 1', {
+ 'xcode_settings': {
+ 'SYMROOT': '<(DEPTH)/build',
+ },
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/gyp-defines/defines.gyp b/chromium/tools/gyp/test/gyp-defines/defines.gyp
new file mode 100644
index 00000000000..f59bbd20d29
--- /dev/null
+++ b/chromium/tools/gyp/test/gyp-defines/defines.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_target',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'test_action',
+ 'inputs': [],
+ 'outputs': [ 'action.txt' ],
+ 'action': [
+ 'python',
+ 'echo.py',
+ '<(key)',
+ '<(_outputs)',
+ ],
+ 'msvs_cygwin_shell': 0,
+ }
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/hard_dependency/src/hard_dependency.gyp b/chromium/tools/gyp/test/hard_dependency/src/hard_dependency.gyp
new file mode 100644
index 00000000000..4479c5f0452
--- /dev/null
+++ b/chromium/tools/gyp/test/hard_dependency/src/hard_dependency.gyp
@@ -0,0 +1,78 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'static_library',
+ 'sources': [
+ 'a.c',
+ 'a.h',
+ ],
+ 'hard_dependency': 1,
+ 'actions': [
+ {
+ 'action_name': 'generate_headers',
+ 'inputs': [
+ 'emit.py'
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/generated.h'
+ ],
+ 'action': [
+ 'python',
+ 'emit.py',
+ '<(SHARED_INTERMEDIATE_DIR)/generated.h',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ },
+ },
+ {
+ 'target_name': 'b',
+ 'type': 'static_library',
+ 'sources': [
+ 'b.c',
+ 'b.h',
+ ],
+ 'dependencies': [
+ 'a',
+ ],
+ 'export_dependent_settings': [
+ 'a',
+ ],
+ },
+ {
+ 'target_name': 'c',
+ 'type': 'static_library',
+ 'sources': [
+ 'c.c',
+ 'c.h',
+ ],
+ 'dependencies': [
+ 'b',
+ ],
+ },
+ {
+ 'target_name': 'd',
+ 'type': 'static_library',
+ 'sources': [
+ 'd.c',
+ ],
+ 'dependencies': [
+ 'c',
+ ],
+ }
+ ],
+}
diff --git a/chromium/tools/gyp/test/hello/hello.gyp b/chromium/tools/gyp/test/hello/hello.gyp
new file mode 100644
index 00000000000..1974d51ccd1
--- /dev/null
+++ b/chromium/tools/gyp/test/hello/hello.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/hello/hello2.gyp b/chromium/tools/gyp/test/hello/hello2.gyp
new file mode 100644
index 00000000000..25b08caf3ca
--- /dev/null
+++ b/chromium/tools/gyp/test/hello/hello2.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/home_dot_gyp/home/.gyp/include.gypi b/chromium/tools/gyp/test/home_dot_gyp/home/.gyp/include.gypi
new file mode 100644
index 00000000000..fcfb39befd8
--- /dev/null
+++ b/chromium/tools/gyp/test/home_dot_gyp/home/.gyp/include.gypi
@@ -0,0 +1,5 @@
+{
+ 'variables': {
+ 'foo': '"fromhome"',
+ },
+}
diff --git a/chromium/tools/gyp/test/home_dot_gyp/home2/.gyp/include.gypi b/chromium/tools/gyp/test/home_dot_gyp/home2/.gyp/include.gypi
new file mode 100644
index 00000000000..f0d84b31ad5
--- /dev/null
+++ b/chromium/tools/gyp/test/home_dot_gyp/home2/.gyp/include.gypi
@@ -0,0 +1,5 @@
+{
+ 'variables': {
+ 'foo': '"fromhome2"',
+ },
+}
diff --git a/chromium/tools/gyp/test/home_dot_gyp/home2/.gyp_new/include.gypi b/chromium/tools/gyp/test/home_dot_gyp/home2/.gyp_new/include.gypi
new file mode 100644
index 00000000000..4094dfd2f8f
--- /dev/null
+++ b/chromium/tools/gyp/test/home_dot_gyp/home2/.gyp_new/include.gypi
@@ -0,0 +1,5 @@
+{
+ 'variables': {
+ 'foo': '"fromhome3"',
+ },
+}
diff --git a/chromium/tools/gyp/test/home_dot_gyp/src/all.gyp b/chromium/tools/gyp/test/home_dot_gyp/src/all.gyp
new file mode 100644
index 00000000000..14b6aea2859
--- /dev/null
+++ b/chromium/tools/gyp/test/home_dot_gyp/src/all.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'foo%': '"fromdefault"',
+ },
+ 'targets': [
+ {
+ 'target_name': 'printfoo',
+ 'type': 'executable',
+ 'sources': [
+ 'printfoo.c',
+ ],
+ 'defines': [
+ 'FOO=<(foo)',
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/include_dirs/src/includes.gyp b/chromium/tools/gyp/test/include_dirs/src/includes.gyp
new file mode 100644
index 00000000000..3592690208a
--- /dev/null
+++ b/chromium/tools/gyp/test/include_dirs/src/includes.gyp
@@ -0,0 +1,27 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'includes',
+ 'type': 'executable',
+ 'dependencies': [
+ 'subdir/subdir_includes.gyp:subdir_includes',
+ ],
+ 'cflags': [
+ '-Ishadow1',
+ ],
+ 'include_dirs': [
+ '.',
+ 'inc1',
+ 'shadow2',
+ 'subdir/inc2',
+ ],
+ 'sources': [
+ 'includes.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp b/chromium/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp
new file mode 100644
index 00000000000..257d052c3c9
--- /dev/null
+++ b/chromium/tools/gyp/test/include_dirs/src/subdir/subdir_includes.gyp
@@ -0,0 +1,20 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'subdir_includes',
+ 'type': 'executable',
+ 'include_dirs': [
+ '.',
+ '../inc1',
+ 'inc2',
+ ],
+ 'sources': [
+ 'subdir_includes.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/intermediate_dir/src/test.gyp b/chromium/tools/gyp/test/intermediate_dir/src/test.gyp
new file mode 100644
index 00000000000..b61e7e8ea58
--- /dev/null
+++ b/chromium/tools/gyp/test/intermediate_dir/src/test.gyp
@@ -0,0 +1,42 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'target1',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'intermediate',
+ 'inputs': [],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/intermediate_out.txt',
+ 'outfile.txt',
+ ],
+ 'action': [
+ 'python', 'script.py', 'target1', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'shared_intermediate',
+ 'inputs': [
+ 'shared_infile.txt',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/intermediate_out.txt',
+ 'shared_outfile.txt',
+ ],
+ 'action': [
+ 'python', 'script.py', 'shared_target1', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/intermediate_dir/src/test2.gyp b/chromium/tools/gyp/test/intermediate_dir/src/test2.gyp
new file mode 100644
index 00000000000..41f5564663e
--- /dev/null
+++ b/chromium/tools/gyp/test/intermediate_dir/src/test2.gyp
@@ -0,0 +1,42 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'target2',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'intermediate',
+ 'inputs': [],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/intermediate_out.txt',
+ 'outfile.txt',
+ ],
+ 'action': [
+ 'python', 'script.py', 'target2', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ {
+ 'action_name': 'shared_intermediate',
+ 'inputs': [
+ 'shared_infile.txt',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/intermediate_out.txt',
+ 'shared_outfile.txt',
+ ],
+ 'action': [
+ 'python', 'script.py', 'shared_target2', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/ios/app-bundle/test.gyp b/chromium/tools/gyp/test/ios/app-bundle/test.gyp
new file mode 100644
index 00000000000..41de4221554
--- /dev/null
+++ b/chromium/tools/gyp/test/ios/app-bundle/test.gyp
@@ -0,0 +1,44 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'conditions': [
+ ['"<(GENERATOR)"=="ninja"', {
+ 'make_global_settings': [
+ ['CC', '/usr/bin/clang'],
+ ['CXX', '/usr/bin/clang++'],
+ ],
+ }],
+ ],
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test App Gyp',
+ 'type': 'executable',
+ 'product_extension': 'bundle',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'TestApp/main.m',
+ ],
+ 'mac_bundle_resources': [
+ 'TestApp/English.lproj/InfoPlist.strings',
+ 'TestApp/English.lproj/MainMenu.xib',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ '$(SDKROOT)/System/Library/Frameworks/UIKit.framework',
+ ],
+ },
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-fobjc-abi-version=2',
+ ],
+ 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
+ 'SDKROOT': 'iphonesimulator', # -isysroot
+ 'IPHONEOS_DEPLOYMENT_TARGET': '4.2',
+ 'CONFIGURATION_BUILD_DIR':'build/Default',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/ios/deployment-target/deployment-target.gyp b/chromium/tools/gyp/test/ios/deployment-target/deployment-target.gyp
new file mode 100644
index 00000000000..e272276b19e
--- /dev/null
+++ b/chromium/tools/gyp/test/ios/deployment-target/deployment-target.gyp
@@ -0,0 +1,58 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'make_global_settings': [
+ ['CC', '/usr/bin/clang'],
+ ['CXX', '/usr/bin/clang++'],
+ ],
+ 'targets': [
+ {
+ 'target_name': 'iphoneos-version-min-4.3',
+ 'type': 'static_library',
+ 'sources': [ 'check-version-min.c', ],
+ 'defines': [ 'GYPTEST_IOS_VERSION_MIN=40300', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'ARCHS': [ 'armv7' ],
+ 'SDKROOT': 'iphoneos',
+ 'IPHONEOS_DEPLOYMENT_TARGET': '4.3',
+ },
+ },
+ {
+ 'target_name': 'iphoneos-version-min-5.0',
+ 'type': 'static_library',
+ 'sources': [ 'check-version-min.c', ],
+ 'defines': [ 'GYPTEST_IOS_VERSION_MIN=50000', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'ARCHS': [ 'armv7' ],
+ 'SDKROOT': 'iphoneos',
+ 'IPHONEOS_DEPLOYMENT_TARGET': '5.0',
+ },
+ },
+ {
+ 'target_name': 'iphonesimulator-version-min-4.3',
+ 'type': 'static_library',
+ 'sources': [ 'check-version-min.c', ],
+ 'defines': [ 'GYPTEST_IOS_VERSION_MIN=40300', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'SDKROOT': 'iphonesimulator',
+ 'IPHONEOS_DEPLOYMENT_TARGET': '4.3',
+ },
+ },
+ {
+ 'target_name': 'iphonesimulator-version-min-5.0',
+ 'type': 'static_library',
+ 'sources': [ 'check-version-min.c', ],
+ 'defines': [ 'GYPTEST_IOS_VERSION_MIN=50000', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'SDKROOT': 'iphonesimulator',
+ 'IPHONEOS_DEPLOYMENT_TARGET': '5.0',
+ },
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/library/src/library.gyp b/chromium/tools/gyp/test/library/src/library.gyp
new file mode 100644
index 00000000000..bc355164260
--- /dev/null
+++ b/chromium/tools/gyp/test/library/src/library.gyp
@@ -0,0 +1,58 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'moveable_function%': 0,
+ },
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'dependencies': [
+ 'lib1',
+ 'lib2',
+ ],
+ 'sources': [
+ 'program.c',
+ ],
+ },
+ {
+ 'target_name': 'lib1',
+ 'type': '<(library)',
+ 'sources': [
+ 'lib1.c',
+ ],
+ 'conditions': [
+ ['moveable_function=="lib1"', {
+ 'sources': [
+ 'lib1_moveable.c',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'lib2',
+ 'type': '<(library)',
+ 'sources': [
+ 'lib2.c',
+ ],
+ 'conditions': [
+ ['moveable_function=="lib2"', {
+ 'sources': [
+ 'lib2_moveable.c',
+ ],
+ }],
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="linux"', {
+ 'target_defaults': {
+ # Support 64-bit shared libs (also works fine for 32-bit).
+ 'cflags': ['-fPIC'],
+ },
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/library/src/shared_dependency.gyp b/chromium/tools/gyp/test/library/src/shared_dependency.gyp
new file mode 100644
index 00000000000..7d29f5de598
--- /dev/null
+++ b/chromium/tools/gyp/test/library/src/shared_dependency.gyp
@@ -0,0 +1,33 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'lib1',
+ 'type': 'shared_library',
+ 'sources': [
+ 'lib1.c',
+ ],
+ },
+ {
+ 'target_name': 'lib2',
+ 'type': 'shared_library',
+ 'sources': [
+ 'lib2.c',
+ ],
+ 'dependencies': [
+ 'lib1',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="linux"', {
+ 'target_defaults': {
+ # Support 64-bit shared libs (also works fine for 32-bit).
+ 'cflags': ['-fPIC'],
+ },
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/library_dirs/subdir/test.gyp b/chromium/tools/gyp/test/library_dirs/subdir/test.gyp
new file mode 100644
index 00000000000..f83d7f2bf1f
--- /dev/null
+++ b/chromium/tools/gyp/test/library_dirs/subdir/test.gyp
@@ -0,0 +1,68 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ # This creates a static library and puts it in a nonstandard location for
+ # libraries-search-path-test.
+ 'target_name': 'mylib',
+ 'type': 'static_library',
+ 'standalone_static_library': 1,
+ # This directory is NOT in the default library search locations. It also
+ # MUST be passed in on the gyp command line:
+ #
+ # -D abs_path_to_secret_library_location=/some_absolute_path
+ #
+ # The gyptest itself (../gyptest-library-dirs.py) provides this.
+ 'product_dir': '<(abs_path_to_secret_library_location)',
+ 'sources': [
+ 'mylib.cc',
+ ],
+ },
+ {
+ 'target_name': 'libraries-search-path-test',
+ 'type': 'executable',
+ 'dependencies': [
+ # It is important to NOT list the mylib as a dependency here, because
+ # some build systems will track it down based on its product_dir,
+ # such that the link succeeds even without the library_dirs below.
+ #
+ # The point of this weird structuring is to ensure that 'library_dirs'
+ # works as advertised, such that just '-lmylib' (or its equivalent)
+ # works based on the directories that library_dirs puts in the library
+ # link path.
+ #
+ # If 'mylib' was listed as a proper dependency here, the build system
+ # would find it and link with its path on disk.
+ #
+ # Note that this implies 'mylib' must already be built when building
+ # 'libraries-search-path-test' (see ../gyptest-library-dirs.py).
+ #
+ #'mylib',
+ ],
+ 'sources': [
+ 'hello.cc',
+ ],
+ # Note that without this, the mylib library would not be found and
+ # successfully linked.
+ 'library_dirs': [
+ '<(abs_path_to_secret_library_location)',
+ ],
+ 'link_settings': {
+ 'conditions': [
+ ['OS=="linux"', {
+ 'libraries': [
+ '-lmylib',
+ ],
+ }, { # else
+ 'libraries': [
+ '<(STATIC_LIB_PREFIX)mylib<(STATIC_LIB_SUFFIX)',
+ ],
+ }],
+ ], # conditions
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/link-objects/link-objects.gyp b/chromium/tools/gyp/test/link-objects/link-objects.gyp
new file mode 100644
index 00000000000..ab72855531a
--- /dev/null
+++ b/chromium/tools/gyp/test/link-objects/link-objects.gyp
@@ -0,0 +1,24 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'link-objects',
+ 'type': 'executable',
+ 'actions': [
+ {
+ 'action_name': 'build extra object',
+ 'inputs': ['extra.c'],
+ 'outputs': ['extra.o'],
+ 'action': ['gcc', '-o', 'extra.o', '-c', 'extra.c'],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ 'sources': [
+ 'base.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/linux/implicit-rpath/test.gyp b/chromium/tools/gyp/test/linux/implicit-rpath/test.gyp
new file mode 100644
index 00000000000..b546106986e
--- /dev/null
+++ b/chromium/tools/gyp/test/linux/implicit-rpath/test.gyp
@@ -0,0 +1,47 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'shared',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ },
+ {
+ 'target_name': 'shared_no_so_suffix',
+ 'product_extension': 'so.0.1',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ },
+ {
+ 'target_name': 'static',
+ 'type': 'static_library',
+ 'sources': [ 'file.c' ],
+ },
+ {
+ 'target_name': 'shared_executable',
+ 'type': 'executable',
+ 'sources': [ 'main.c' ],
+ 'dependencies': [
+ 'shared',
+ ]
+ },
+ {
+ 'target_name': 'shared_executable_no_so_suffix',
+ 'type': 'executable',
+ 'sources': [ 'main.c' ],
+ 'dependencies': [
+ 'shared_no_so_suffix',
+ ]
+ },
+ {
+ 'target_name': 'static_executable',
+ 'type': 'executable',
+ 'sources': [ 'main.c' ],
+ 'dependencies': [
+ 'static',
+ ]
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/action-envvars/action/action.gyp b/chromium/tools/gyp/test/mac/action-envvars/action/action.gyp
new file mode 100644
index 00000000000..d9d65745ca3
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/action-envvars/action/action.gyp
@@ -0,0 +1,34 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'action',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'inputs': [ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/result',
+ '<(SHARED_INTERMEDIATE_DIR)/tempfile',
+ ],
+ 'action_name': 'Test action',
+ 'action': ['./action.sh', '<(SHARED_INTERMEDIATE_DIR)/tempfile' ],
+ },
+ {
+ 'inputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/tempfile',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/other_result',
+ ],
+ 'action_name': 'Other test action',
+ 'action': ['cp', '<(SHARED_INTERMEDIATE_DIR)/tempfile',
+ '<(PRODUCT_DIR)/other_result' ],
+ },
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/app-bundle/test-error.gyp b/chromium/tools/gyp/test/mac/app-bundle/test-error.gyp
new file mode 100644
index 00000000000..370772cc31e
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/app-bundle/test-error.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test App Gyp',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'TestApp/main.m',
+ 'TestApp/TestApp_Prefix.pch',
+ 'TestApp/TestAppAppDelegate.h',
+ 'TestApp/TestAppAppDelegate.m',
+ ],
+ 'mac_bundle_resources': [
+ 'TestApp/English.lproj/InfoPlist-error.strings',
+ 'TestApp/English.lproj/MainMenu.xib',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
+ ],
+ },
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/app-bundle/test.gyp b/chromium/tools/gyp/test/mac/app-bundle/test.gyp
new file mode 100644
index 00000000000..f51c7b4b677
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/app-bundle/test.gyp
@@ -0,0 +1,39 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'dep_framework',
+ 'product_name': 'Dependency Framework',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'empty.c', ],
+ },
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test App Gyp',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'dependencies': [ 'dep_framework', ],
+ 'sources': [
+ 'TestApp/main.m',
+ 'TestApp/TestApp_Prefix.pch',
+ 'TestApp/TestAppAppDelegate.h',
+ 'TestApp/TestAppAppDelegate.m',
+ ],
+ 'mac_bundle_resources': [
+ 'TestApp/English.lproj/InfoPlist.strings',
+ 'TestApp/English.lproj/MainMenu.xib',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
+ ],
+ },
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'TestApp/TestApp-Info.plist',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/archs/test-archs-multiarch.gyp b/chromium/tools/gyp/test/mac/archs/test-archs-multiarch.gyp
new file mode 100644
index 00000000000..a187ca5c357
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/archs/test-archs-multiarch.gyp
@@ -0,0 +1,60 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'static_32_64',
+ 'type': 'static_library',
+ 'sources': [ 'my_file.cc' ],
+ 'xcode_settings': {
+ 'ARCHS': [ 'i386', 'x86_64' ],
+ },
+ },
+ {
+ 'target_name': 'shared_32_64',
+ 'type': 'shared_library',
+ 'sources': [ 'my_file.cc' ],
+ 'xcode_settings': {
+ 'ARCHS': [ 'i386', 'x86_64' ],
+ },
+ },
+ {
+ 'target_name': 'module_32_64',
+ 'type': 'loadable_module',
+ 'sources': [ 'my_file.cc' ],
+ 'xcode_settings': {
+ 'ARCHS': [ 'i386', 'x86_64' ],
+ },
+ },
+ {
+ 'target_name': 'exe_32_64',
+ 'type': 'executable',
+ 'sources': [ 'empty_main.cc' ],
+ 'xcode_settings': {
+ 'ARCHS': [ 'i386', 'x86_64' ],
+ },
+ },
+ {
+ 'target_name': 'exe_32_64_bundle',
+ 'product_name': 'Test App',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [ 'empty_main.cc' ],
+ 'xcode_settings': {
+ 'ARCHS': [ 'i386', 'x86_64' ],
+ },
+ },
+ # This only needs to compile.
+ {
+ 'target_name': 'precompiled_prefix_header_mm_32_64',
+ 'type': 'shared_library',
+ 'sources': [ 'file.mm', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES',
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/mac/archs/test-archs-x86_64.gyp b/chromium/tools/gyp/test/mac/archs/test-archs-x86_64.gyp
new file mode 100644
index 00000000000..d11a896273c
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/archs/test-archs-x86_64.gyp
@@ -0,0 +1,27 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'lib',
+ 'product_name': 'Test64',
+ 'type': 'static_library',
+ 'sources': [ 'my_file.cc' ],
+ 'xcode_settings': {
+ 'ARCHS': [ 'x86_64' ],
+ },
+ },
+ {
+ 'target_name': 'exe',
+ 'product_name': 'Test64',
+ 'type': 'executable',
+ 'dependencies': [ 'lib' ],
+ 'sources': [ 'my_main_file.cc' ],
+ 'xcode_settings': {
+ 'ARCHS': [ 'x86_64' ],
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/mac/archs/test-no-archs.gyp b/chromium/tools/gyp/test/mac/archs/test-no-archs.gyp
new file mode 100644
index 00000000000..8f3b6b47cc1
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/archs/test-no-archs.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'lib',
+ 'product_name': 'Test',
+ 'type': 'static_library',
+ 'sources': [ 'my_file.cc' ],
+ },
+ {
+ 'target_name': 'exe',
+ 'product_name': 'Test',
+ 'type': 'executable',
+ 'dependencies': [ 'lib' ],
+ 'sources': [ 'my_main_file.cc' ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/mac/cflags/test.gyp b/chromium/tools/gyp/test/mac/cflags/test.gyp
new file mode 100644
index 00000000000..d330a548f64
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/cflags/test.gyp
@@ -0,0 +1,132 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'mytarget',
+ 'type': 'shared_library',
+ 'sources': [
+ 'cfile.c',
+ 'mfile.m',
+ 'ccfile.cc',
+ 'cppfile.cpp',
+ 'cxxfile.cxx',
+ 'mmfile.mm',
+ ],
+ 'xcode_settings': {
+ # Normally, defines would go in 'defines' instead. This is just for
+ # testing.
+ 'OTHER_CFLAGS': [
+ '-DCFLAG',
+ ],
+ 'OTHER_CPLUSPLUSFLAGS': [
+ '-DCCFLAG',
+ ],
+ 'GCC_C_LANGUAGE_STANDARD': 'c99',
+ },
+ },
+ {
+ 'target_name': 'mytarget_reuse_cflags',
+ 'type': 'shared_library',
+ 'sources': [
+ 'cfile.c',
+ 'mfile.m',
+ 'ccfile_withcflags.cc',
+ 'cppfile_withcflags.cpp',
+ 'cxxfile_withcflags.cxx',
+ 'mmfile_withcflags.mm',
+ ],
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-DCFLAG',
+ ],
+ 'OTHER_CPLUSPLUSFLAGS': [
+ '$OTHER_CFLAGS',
+ '-DCCFLAG',
+ ],
+ # This is a C-only flag, to check these don't get added to C++ files.
+ 'GCC_C_LANGUAGE_STANDARD': 'c99',
+ },
+ },
+ {
+ 'target_name': 'mytarget_inherit_cflags',
+ 'type': 'shared_library',
+ 'sources': [
+ 'cfile.c',
+ 'mfile.m',
+ 'ccfile_withcflags.cc',
+ 'cppfile_withcflags.cpp',
+ 'cxxfile_withcflags.cxx',
+ 'mmfile_withcflags.mm',
+ ],
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-DCFLAG',
+ ],
+ 'OTHER_CPLUSPLUSFLAGS': [
+ '$inherited',
+ '-DCCFLAG',
+ ],
+ 'GCC_C_LANGUAGE_STANDARD': 'c99',
+ },
+ },
+ {
+ 'target_name': 'mytarget_inherit_cflags_parens',
+ 'type': 'shared_library',
+ 'sources': [
+ 'cfile.c',
+ 'mfile.m',
+ 'ccfile_withcflags.cc',
+ 'cppfile_withcflags.cpp',
+ 'cxxfile_withcflags.cxx',
+ 'mmfile_withcflags.mm',
+ ],
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-DCFLAG',
+ ],
+ 'OTHER_CPLUSPLUSFLAGS': [
+ '$(inherited)',
+ '-DCCFLAG',
+ ],
+ 'GCC_C_LANGUAGE_STANDARD': 'c99',
+ },
+ },
+ {
+ 'target_name': 'mytarget_inherit_cflags_braces',
+ 'type': 'shared_library',
+ 'sources': [
+ 'cfile.c',
+ 'mfile.m',
+ 'ccfile_withcflags.cc',
+ 'cppfile_withcflags.cpp',
+ 'cxxfile_withcflags.cxx',
+ 'mmfile_withcflags.mm',
+ ],
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-DCFLAG',
+ ],
+ 'OTHER_CPLUSPLUSFLAGS': [
+ '${inherited}',
+ '-DCCFLAG',
+ ],
+ 'GCC_C_LANGUAGE_STANDARD': 'c99',
+ },
+ },
+ {
+ 'target_name': 'ansi_standard',
+ 'type': 'shared_library',
+ 'sources': [
+ 'cfile.c',
+ ],
+ 'xcode_settings': {
+ 'OTHER_CFLAGS': [
+ '-DCFLAG',
+ ],
+ 'GCC_C_LANGUAGE_STANDARD': 'ansi',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/clang-cxx-language-standard/clang-cxx-language-standard.gyp b/chromium/tools/gyp/test/mac/clang-cxx-language-standard/clang-cxx-language-standard.gyp
new file mode 100644
index 00000000000..eb60bbd0e88
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/clang-cxx-language-standard/clang-cxx-language-standard.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'make_global_settings': [
+ ['CC', '/usr/bin/clang'],
+ ['CXX', '/usr/bin/clang++'],
+ ],
+ 'targets': [
+ {
+ 'target_name': 'c++98',
+ 'type': 'executable',
+ 'sources': [ 'c++98.cc', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'CLANG_CXX_LANGUAGE_STANDARD': 'c++98',
+ },
+ },
+ {
+ 'target_name': 'c++11',
+ 'type': 'executable',
+ 'sources': [ 'c++11.cc', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'CLANG_CXX_LANGUAGE_STANDARD': 'c++0x',
+ },
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/clang-cxx-library/clang-cxx-library.gyp b/chromium/tools/gyp/test/mac/clang-cxx-library/clang-cxx-library.gyp
new file mode 100644
index 00000000000..67006e50a01
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/clang-cxx-library/clang-cxx-library.gyp
@@ -0,0 +1,32 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'make_global_settings': [
+ ['CC', '/usr/bin/clang'],
+ ['CXX', '/usr/bin/clang++'],
+ ],
+ 'targets': [
+ {
+ 'target_name': 'libc++',
+ 'type': 'executable',
+ 'sources': [ 'libc++.cc', ],
+ 'xcode_settings': {
+ 'CC': 'clang',
+ # libc++ requires OS X 10.7+.
+ 'MACOSX_DEPLOYMENT_TARGET': '10.7',
+ 'CLANG_CXX_LIBRARY': 'libc++',
+ },
+ },
+ {
+ 'target_name': 'libstdc++',
+ 'type': 'executable',
+ 'sources': [ 'libstdc++.cc', ],
+ 'xcode_settings': {
+ 'CC': 'clang',
+ 'CLANG_CXX_LIBRARY': 'libstdc++',
+ },
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/copy-dylib/test.gyp b/chromium/tools/gyp/test/mac/copy-dylib/test.gyp
new file mode 100644
index 00000000000..4210c514634
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/copy-dylib/test.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'my_dylib',
+ 'type': 'shared_library',
+ 'sources': [ 'empty.c', ],
+ },
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test App',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'dependencies': [ 'my_dylib', ],
+ 'sources': [
+ 'empty.c',
+ ],
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/Test App.app/Contents/Resources',
+ 'files': [
+ '<(PRODUCT_DIR)/libmy_dylib.dylib',
+ ],
+ },
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/debuginfo/test.gyp b/chromium/tools/gyp/test/mac/debuginfo/test.gyp
new file mode 100644
index 00000000000..3faf6b5c76e
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/debuginfo/test.gyp
@@ -0,0 +1,82 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'nonbundle_static_library',
+ 'type': 'static_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ },
+ },
+ {
+ 'target_name': 'nonbundle_shared_library',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ },
+ },
+ {
+ 'target_name': 'nonbundle_loadable_module',
+ 'type': 'loadable_module',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ },
+ },
+ {
+ 'target_name': 'nonbundle_executable',
+ 'type': 'executable',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ },
+ },
+
+ {
+ 'target_name': 'bundle_shared_library',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ },
+ },
+ {
+ 'target_name': 'bundle_loadable_module',
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ },
+ },
+ {
+ 'target_name': 'my_app',
+ 'product_name': 'My App',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/depend-on-bundle/test.gyp b/chromium/tools/gyp/test/mac/depend-on-bundle/test.gyp
new file mode 100644
index 00000000000..e00b1054159
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/depend-on-bundle/test.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'my_bundle',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'bundle.c' ],
+ 'mac_bundle_resources': [
+ 'English.lproj/InfoPlist.strings',
+ ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ }
+ },
+ {
+ 'target_name': 'dependent_on_bundle',
+ 'type': 'executable',
+ 'sources': [ 'executable.c' ],
+ 'dependencies': [
+ 'my_bundle',
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/deployment-target/deployment-target.gyp b/chromium/tools/gyp/test/mac/deployment-target/deployment-target.gyp
new file mode 100644
index 00000000000..47e0565c0c7
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/deployment-target/deployment-target.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'macosx-version-min-10.5',
+ 'type': 'executable',
+ 'sources': [ 'check-version-min.c', ],
+ 'defines': [ 'GYPTEST_MAC_VERSION_MIN=1050', ],
+ 'xcode_settings': {
+ 'SDKROOT': 'macosx',
+ 'MACOSX_DEPLOYMENT_TARGET': '10.5',
+ },
+ },
+ {
+ 'target_name': 'macosx-version-min-10.6',
+ 'type': 'executable',
+ 'sources': [ 'check-version-min.c', ],
+ 'defines': [ 'GYPTEST_MAC_VERSION_MIN=1060', ],
+ 'xcode_settings': {
+ 'SDKROOT': 'macosx',
+ 'MACOSX_DEPLOYMENT_TARGET': '10.6',
+ },
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/framework-dirs/framework-dirs.gyp b/chromium/tools/gyp/test/mac/framework-dirs/framework-dirs.gyp
new file mode 100644
index 00000000000..bf1cbde4def
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/framework-dirs/framework-dirs.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'calculate',
+ 'type': 'executable',
+ 'sources': [
+ 'calculate.c',
+ ],
+ 'libraries': [
+ '/System/Library/PrivateFrameworks/Calculate.framework',
+ ],
+ 'mac_framework_dirs': [
+ '/System/Library/PrivateFrameworks',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/framework-headers/test.gyp b/chromium/tools/gyp/test/mac/framework-headers/test.gyp
new file mode 100644
index 00000000000..70ed00715c8
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/framework-headers/test.gyp
@@ -0,0 +1,44 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_framework_headers_framework',
+ 'product_name': 'TestFramework',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'myframework.h',
+ 'myframework.m',
+ ],
+ 'mac_framework_headers': [
+ 'myframework.h',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ ],
+ },
+ },{
+ 'target_name': 'test_framework_headers_static',
+ 'product_name': 'TestLibrary',
+ 'type': 'static_library',
+ 'xcode_settings': {
+ 'PUBLIC_HEADERS_FOLDER_PATH': 'include',
+ },
+ 'sources': [
+ 'myframework.h',
+ 'myframework.m',
+ ],
+ 'mac_framework_headers': [
+ 'myframework.h',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ ],
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/framework/framework.gyp b/chromium/tools/gyp/test/mac/framework/framework.gyp
new file mode 100644
index 00000000000..7480e526c6b
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/framework/framework.gyp
@@ -0,0 +1,74 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'dep_framework',
+ 'product_name': 'Dependency Bundle',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'empty.c', ],
+ },
+ {
+ 'target_name': 'test_framework',
+ 'product_name': 'Test Framework',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'dependencies': [ 'dep_framework', ],
+ 'sources': [
+ 'TestFramework/ObjCVector.h',
+ 'TestFramework/ObjCVectorInternal.h',
+ 'TestFramework/ObjCVector.mm',
+ ],
+ 'mac_framework_headers': [
+ 'TestFramework/ObjCVector.h',
+ ],
+ 'mac_bundle_resources': [
+ 'TestFramework/English.lproj/InfoPlist.strings',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
+ ],
+ },
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'TestFramework/Info.plist',
+ 'GCC_DYNAMIC_NO_PIC': 'NO',
+ },
+ 'copies': [
+ # Test copying to a file that has envvars in its dest path.
+ # Needs to be in a mac_bundle target, else CONTENTS_FOLDER_PATH isn't
+ # set.
+ {
+ 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Libraries',
+ 'files': [
+ 'empty.c',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'copy_target',
+ 'type': 'none',
+ 'dependencies': [ 'test_framework', 'dep_framework', ],
+ 'copies': [
+ # Test copying directories with spaces in src and dest paths.
+ {
+ 'destination': '<(PRODUCT_DIR)/Test Framework.framework/foo',
+ 'files': [
+ '<(PRODUCT_DIR)/Dependency Bundle.framework',
+ ],
+ },
+ ],
+ 'actions': [
+ {
+ 'action_name': 'aektschn',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/touched_file'],
+ 'action': ['touch', '${BUILT_PRODUCTS_DIR}/action_file'],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/global-settings/src/dir1/dir1.gyp b/chromium/tools/gyp/test/mac/global-settings/src/dir1/dir1.gyp
new file mode 100644
index 00000000000..153e34ddd68
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/global-settings/src/dir1/dir1.gyp
@@ -0,0 +1,11 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'dir1_target',
+ 'type': 'none',
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/global-settings/src/dir2/dir2.gyp b/chromium/tools/gyp/test/mac/global-settings/src/dir2/dir2.gyp
new file mode 100644
index 00000000000..cda46c839ba
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/global-settings/src/dir2/dir2.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'dir2_target',
+ 'type': 'none',
+ 'dependencies': [
+ '../dir1/dir1.gyp:dir1_target',
+ ],
+ 'actions': [
+ {
+ 'inputs': [ ],
+ 'outputs': [ '<(PRODUCT_DIR)/file.txt' ],
+ 'action_name': 'Test action',
+ 'action': ['cp', 'file.txt', '${BUILT_PRODUCTS_DIR}/file.txt' ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/gyptest-postbuild-static-library.gyp b/chromium/tools/gyp/test/mac/gyptest-postbuild-static-library.gyp
new file mode 100644
index 00000000000..8f9a6ebcb09
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/gyptest-postbuild-static-library.gyp
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Verifies that a postbuilds on static libraries work, and that sourceless
+libraries don't cause failures at gyp time.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'darwin':
+ test = TestGyp.TestGyp(formats=['make', 'xcode'])
+
+ CHDIR = 'postbuild-static-library'
+ test.run_gyp('test.gyp', chdir=CHDIR)
+ test.build('test.gyp', 'my_lib', chdir=CHDIR)
+ # Building my_sourceless_lib doesn't work with make. gyp should probably
+ # forbid sourceless static libraries, since they're pretty pointless.
+ # But they shouldn't cause gyp time exceptions.
+
+ test.built_file_must_exist('postbuild-file', chdir=CHDIR)
+
+ test.pass_test()
diff --git a/chromium/tools/gyp/test/mac/gyptest-sourceless-module.gyp b/chromium/tools/gyp/test/mac/gyptest-sourceless-module.gyp
new file mode 100644
index 00000000000..c3ea73a1714
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/gyptest-sourceless-module.gyp
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Verifies that bundles that have no 'sources' (pure resource containers) work.
+"""
+
+import TestGyp
+
+import sys
+
+if sys.platform == 'darwin':
+ test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'])
+
+ test.run_gyp('test.gyp', chdir='sourceless-module')
+
+ # Just needs to build without errors.
+ test.build('test.gyp', 'empty_bundle', chdir='sourceless-module')
+ test.built_file_must_not_exist(
+ 'empty_bundle.bundle', chdir='sourceless-module')
+
+ # Needs to build, and contain a resource.
+ test.build('test.gyp', 'resource_bundle', chdir='sourceless-module')
+
+ test.built_file_must_exist(
+ 'resource_bundle.bundle/Contents/Resources/foo.manifest',
+ chdir='sourceless-module')
+ test.built_file_must_not_exist(
+ 'resource_bundle.bundle/Contents/MacOS/resource_bundle',
+ chdir='sourceless-module')
+
+ # Needs to build and cause the bundle to be built.
+ test.build(
+ 'test.gyp', 'dependent_on_resource_bundle', chdir='sourceless-module')
+
+ test.built_file_must_exist(
+ 'resource_bundle.bundle/Contents/Resources/foo.manifest',
+ chdir='sourceless-module')
+ test.built_file_must_not_exist(
+ 'resource_bundle.bundle/Contents/MacOS/resource_bundle',
+ chdir='sourceless-module')
+
+ test.pass_test()
diff --git a/chromium/tools/gyp/test/mac/infoplist-process/test1.gyp b/chromium/tools/gyp/test/mac/infoplist-process/test1.gyp
new file mode 100644
index 00000000000..bc625a968be
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/infoplist-process/test1.gyp
@@ -0,0 +1,25 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'main.c',
+ ],
+ 'configurations': {
+ 'One': {
+ },
+ },
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ 'INFOPLIST_PREPROCESS': 'YES',
+ 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1=Foo PROCESSED_KEY2=Bar',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/infoplist-process/test2.gyp b/chromium/tools/gyp/test/mac/infoplist-process/test2.gyp
new file mode 100644
index 00000000000..ecfbc9f64c9
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/infoplist-process/test2.gyp
@@ -0,0 +1,25 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'main.c',
+ ],
+ 'configurations': {
+ 'Two': {
+ },
+ },
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ 'INFOPLIST_PREPROCESS': 'YES',
+ 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1="Foo (Bar)"',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/infoplist-process/test3.gyp b/chromium/tools/gyp/test/mac/infoplist-process/test3.gyp
new file mode 100644
index 00000000000..be8fe75a53e
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/infoplist-process/test3.gyp
@@ -0,0 +1,25 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test App',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'main.c',
+ ],
+ 'configurations': {
+ 'Three': {
+ },
+ },
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ 'INFOPLIST_PREPROCESS': 'NO',
+ 'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'PROCESSED_KEY1=Foo',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/installname/test.gyp b/chromium/tools/gyp/test/mac/installname/test.gyp
new file mode 100644
index 00000000000..60c867ff122
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/installname/test.gyp
@@ -0,0 +1,93 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'default_installname',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ },
+ {
+ 'target_name': 'default_bundle_installname',
+ 'product_name': 'My Framework',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c' ],
+ },
+ {
+ 'target_name': 'explicit_installname',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ 'LD_DYLIB_INSTALL_NAME': 'Trapped in a dynamiclib factory',
+ },
+ },
+ {
+ 'target_name': 'explicit_installname_base',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ 'DYLIB_INSTALL_NAME_BASE': '@executable_path/../../..',
+
+ },
+ },
+ {
+ 'target_name': 'explicit_installname_base_bundle',
+ 'product_name': 'My Other Framework',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ 'DYLIB_INSTALL_NAME_BASE': '@executable_path/../../..',
+
+ },
+ },
+ {
+ 'target_name': 'both_base_and_installname',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ # LD_DYLIB_INSTALL_NAME wins.
+ 'LD_DYLIB_INSTALL_NAME': 'Still trapped in a dynamiclib factory',
+ 'DYLIB_INSTALL_NAME_BASE': '@executable_path/../../..',
+ },
+ },
+ {
+ 'target_name': 'explicit_installname_with_base',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ 'LD_DYLIB_INSTALL_NAME': '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)',
+ },
+ },
+ {
+ 'target_name': 'explicit_installname_with_explicit_base',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ 'DYLIB_INSTALL_NAME_BASE': '@executable_path/..',
+ 'LD_DYLIB_INSTALL_NAME': '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)',
+ },
+ },
+ {
+ 'target_name': 'executable',
+ 'type': 'executable',
+ 'sources': [ 'main.c' ],
+ 'xcode_settings': {
+ 'LD_DYLIB_INSTALL_NAME': 'Should be ignored for not shared_lib',
+ },
+ },
+ # Regression test for http://crbug.com/113918
+ {
+ 'target_name': 'install_name_with_info_plist',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ 'LD_DYLIB_INSTALL_NAME': '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/ldflags-libtool/test.gyp b/chromium/tools/gyp/test/mac/ldflags-libtool/test.gyp
new file mode 100644
index 00000000000..4e7aa07106b
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/ldflags-libtool/test.gyp
@@ -0,0 +1,17 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'ldflags_passed_to_libtool',
+ 'type': 'static_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ '-fblorfen-horf-does-not-exist',
+ ],
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/ldflags/subdirectory/test.gyp b/chromium/tools/gyp/test/mac/ldflags/subdirectory/test.gyp
new file mode 100644
index 00000000000..db00c7465ca
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/ldflags/subdirectory/test.gyp
@@ -0,0 +1,66 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'raw',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ '-exported_symbols_list symbol_list.def',
+ '-sectcreate __TEXT __info_plist Info.plist',
+ ],
+ },
+ },
+ # TODO(thakis): This form should ideally be supported, too. (But
+ # -Wlfoo,bar,baz is cleaner so people should use that anyway.)
+ #{
+ # 'target_name': 'raw_sep',
+ # 'type': 'shared_library',
+ # 'sources': [ 'file.c', ],
+ # 'xcode_settings': {
+ # 'OTHER_LDFLAGS': [
+ # '-exported_symbols_list', 'symbol_list.def',
+ # '-sectcreate', '__TEXT', '__info_plist', 'Info.plist',
+ # ],
+ # },
+ #},
+ {
+ 'target_name': 'wl_space',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ # Works because clang passes unknown files on to the linker.
+ '-Wl,-exported_symbols_list symbol_list.def',
+ ],
+ },
+ },
+ # TODO(thakis): This form should ideally be supported, too. (But
+ # -Wlfoo,bar,baz is cleaner so people should use that anyway.)
+ #{
+ # 'target_name': 'wl_space_sep',
+ # 'type': 'shared_library',
+ # 'sources': [ 'file.c', ],
+ # 'xcode_settings': {
+ # 'OTHER_LDFLAGS': [
+ # # Works because clang passes unknown files on to the linker.
+ # '-Wl,-exported_symbols_list', 'symbol_list.def',
+ # ],
+ # },
+ #},
+ {
+ 'target_name': 'wl_comma',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ '-Wl,-exported_symbols_list,symbol_list.def',
+ '-Wl,-sectcreate,__TEXT,__info_plist,Info.plist',
+ ],
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/libraries/subdir/test.gyp b/chromium/tools/gyp/test/mac/libraries/subdir/test.gyp
new file mode 100644
index 00000000000..59fef51017b
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/libraries/subdir/test.gyp
@@ -0,0 +1,65 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'libraries-test',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.cc',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ 'libcrypto.dylib',
+ ],
+ },
+ },
+ {
+ # This creates a static library and puts it in a nonstandard location for
+ # libraries-search-path-test.
+ 'target_name': 'mylib',
+ 'type': 'static_library',
+ 'sources': [
+ 'mylib.c',
+ ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Make a secret location',
+ 'action': [
+ 'mkdir',
+ '-p',
+ '${SRCROOT}/../secret_location',
+ ],
+ },
+ {
+ 'postbuild_name': 'Copy to secret location, with secret name',
+ 'action': [
+ 'cp',
+ '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}',
+ '${SRCROOT}/../secret_location/libmysecretlib.a',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'libraries-search-path-test',
+ 'type': 'executable',
+ 'dependencies': [ 'mylib' ],
+ 'sources': [
+ 'hello.cc',
+ ],
+ 'xcode_settings': {
+ 'LIBRARY_SEARCH_PATHS': [
+ '<(DEPTH)/secret_location',
+ ],
+ },
+ 'link_settings': {
+ 'libraries': [
+ 'libmysecretlib.a',
+ ],
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/loadable-module/test.gyp b/chromium/tools/gyp/test/mac/loadable-module/test.gyp
new file mode 100644
index 00000000000..3c8a5309d25
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/loadable-module/test.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_loadable_module',
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ 'sources': [ 'module.c' ],
+ 'product_extension': 'plugin',
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/missing-cfbundlesignature/test.gyp b/chromium/tools/gyp/test/mac/missing-cfbundlesignature/test.gyp
new file mode 100644
index 00000000000..b50cc2791a0
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/missing-cfbundlesignature/test.gyp
@@ -0,0 +1,34 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'mytarget',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ },
+ },
+ {
+ 'target_name': 'myothertarget',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Other-Info.plist',
+ },
+ },
+ {
+ 'target_name': 'thirdtarget',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Third-Info.plist',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/non-strs-flattened-to-env/test.gyp b/chromium/tools/gyp/test/mac/non-strs-flattened-to-env/test.gyp
new file mode 100644
index 00000000000..aaf821c9257
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/non-strs-flattened-to-env/test.gyp
@@ -0,0 +1,27 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [ 'main.c', ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ 'MY_VAR': 'some expansion',
+ 'OTHER_CFLAGS': [
+ # Just some (more than one) random flags.
+ '-fstack-protector-all',
+ '-fno-strict-aliasing',
+ '-DS="A Space"', # Would normally be in 'defines'
+ ],
+ },
+ 'include_dirs': [
+ '$(SDKROOT)/usr/include/libxml2',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/objc-arc/test.gyp b/chromium/tools/gyp/test/mac/objc-arc/test.gyp
new file mode 100644
index 00000000000..59cf0e29cee
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/objc-arc/test.gyp
@@ -0,0 +1,45 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'make_global_settings': [
+ ['CC', '/usr/bin/clang'],
+ ['CXX', '/usr/bin/clang++'],
+ ],
+
+ 'targets': [
+ {
+ 'target_name': 'arc_enabled',
+ 'type': 'static_library',
+ 'sources': [
+ 'c-file.c',
+ 'cc-file.cc',
+ 'm-file.m',
+ 'mm-file.mm',
+ ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'MACOSX_DEPLOYMENT_TARGET': '10.6',
+ 'ARCHS': [ 'x86_64' ], # For the non-fragile objc ABI.
+ 'CLANG_ENABLE_OBJC_ARC': 'YES',
+ },
+ },
+
+ {
+ 'target_name': 'arc_disabled',
+ 'type': 'static_library',
+ 'sources': [
+ 'c-file.c',
+ 'cc-file.cc',
+ 'm-file-no-arc.m',
+ 'mm-file-no-arc.mm',
+ ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'MACOSX_DEPLOYMENT_TARGET': '10.6',
+ 'ARCHS': [ 'x86_64' ], # For the non-fragile objc ABI.
+ },
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/objc-gc/test.gyp b/chromium/tools/gyp/test/mac/objc-gc/test.gyp
new file mode 100644
index 00000000000..4d827c1b39c
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/objc-gc/test.gyp
@@ -0,0 +1,102 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ # For some reason, static_library targets that are built with gc=required
+ # and then linked to executables that don't use gc, the linker doesn't
+ # complain. For shared_libraries it does, so use that.
+ {
+ 'target_name': 'no_gc_lib',
+ 'type': 'shared_library',
+ 'sources': [
+ 'c-file.c',
+ 'cc-file.cc',
+ 'needs-gc-mm.mm',
+ 'needs-gc.m',
+ ],
+ },
+ {
+ 'target_name': 'gc_lib',
+ 'type': 'shared_library',
+ 'sources': [
+ 'c-file.c',
+ 'cc-file.cc',
+ 'needs-gc-mm.mm',
+ 'needs-gc.m',
+ ],
+ 'xcode_settings': {
+ 'GCC_ENABLE_OBJC_GC': 'supported',
+ },
+ },
+ {
+ 'target_name': 'gc_req_lib',
+ 'type': 'shared_library',
+ 'sources': [
+ 'c-file.c',
+ 'cc-file.cc',
+ 'needs-gc-mm.mm',
+ 'needs-gc.m',
+ ],
+ 'xcode_settings': {
+ 'GCC_ENABLE_OBJC_GC': 'required',
+ },
+ },
+
+ {
+ 'target_name': 'gc_exe_fails',
+ 'type': 'executable',
+ 'sources': [ 'main.m' ],
+ 'dependencies': [ 'no_gc_lib' ],
+ 'xcode_settings': {
+ 'GCC_ENABLE_OBJC_GC': 'required',
+ },
+ 'libraries': [ 'Foundation.framework' ],
+ },
+ {
+ 'target_name': 'gc_req_exe',
+ 'type': 'executable',
+ 'sources': [ 'main.m' ],
+ 'dependencies': [ 'gc_lib' ],
+ 'xcode_settings': {
+ 'GCC_ENABLE_OBJC_GC': 'required',
+ },
+ 'libraries': [ 'Foundation.framework' ],
+ },
+ {
+ 'target_name': 'gc_exe_req_lib',
+ 'type': 'executable',
+ 'sources': [ 'main.m' ],
+ 'dependencies': [ 'gc_req_lib' ],
+ 'xcode_settings': {
+ 'GCC_ENABLE_OBJC_GC': 'supported',
+ },
+ 'libraries': [ 'Foundation.framework' ],
+ },
+ {
+ 'target_name': 'gc_exe',
+ 'type': 'executable',
+ 'sources': [ 'main.m' ],
+ 'dependencies': [ 'gc_lib' ],
+ 'xcode_settings': {
+ 'GCC_ENABLE_OBJC_GC': 'supported',
+ },
+ 'libraries': [ 'Foundation.framework' ],
+ },
+ {
+ 'target_name': 'gc_off_exe_req_lib',
+ 'type': 'executable',
+ 'sources': [ 'main.m' ],
+ 'dependencies': [ 'gc_req_lib' ],
+ 'libraries': [ 'Foundation.framework' ],
+ },
+ {
+ 'target_name': 'gc_off_exe',
+ 'type': 'executable',
+ 'sources': [ 'main.m' ],
+ 'dependencies': [ 'gc_lib' ],
+ 'libraries': [ 'Foundation.framework' ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/postbuild-copy-bundle/test.gyp b/chromium/tools/gyp/test/mac/postbuild-copy-bundle/test.gyp
new file mode 100644
index 00000000000..a03e6432f2a
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/postbuild-copy-bundle/test.gyp
@@ -0,0 +1,49 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_bundle',
+ 'product_name': 'My Framework',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'empty.c', ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Framework-Info.plist',
+ },
+ 'mac_bundle_resources': [
+ 'resource_file.sb',
+ ],
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Libraries',
+ 'files': [ 'copied.txt' ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test App',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'dependencies': [
+ 'test_bundle',
+ ],
+ 'sources': [ 'main.c', ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'TestApp-Info.plist',
+ },
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Copy dependent framework into app',
+ 'action': [
+ './postbuild-copy-framework.sh',
+ '${BUILT_PRODUCTS_DIR}/My Framework.framework',
+ '${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/postbuild-defaults/test.gyp b/chromium/tools/gyp/test/mac/postbuild-defaults/test.gyp
new file mode 100644
index 00000000000..be0a075efc6
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/postbuild-defaults/test.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [ 'main.c', ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ },
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Postbuild that calls defaults',
+ 'action': [
+ './postbuild-defaults.sh',
+ '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/postbuild-fail/test.gyp b/chromium/tools/gyp/test/mac/postbuild-fail/test.gyp
new file mode 100644
index 00000000000..e63283db036
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/postbuild-fail/test.gyp
@@ -0,0 +1,38 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'nonbundle',
+ 'type': 'static_library',
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Postbuild Fail',
+ 'action': [ './postbuild-fail.sh', ],
+ },
+ {
+ 'postbuild_name': 'Runs after failing postbuild',
+ 'action': [ './touch-static.sh', ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'bundle',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Postbuild Fail',
+ 'action': [ './postbuild-fail.sh', ],
+ },
+ {
+ 'postbuild_name': 'Runs after failing postbuild',
+ 'action': [ './touch-dynamic.sh', ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/postbuild-multiple-configurations/test.gyp b/chromium/tools/gyp/test/mac/postbuild-multiple-configurations/test.gyp
new file mode 100644
index 00000000000..c350b20d683
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/postbuild-multiple-configurations/test.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'target_defaults': {
+ 'configurations': {
+ 'Debug': {},
+ 'Release': {},
+ },
+ },
+ 'targets': [
+ {
+ 'target_name': 'random_target',
+ 'type': 'executable',
+ 'sources': [ 'main.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Touch a file.',
+ 'action': [
+ './postbuild-touch-file.sh',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/postbuild-static-library/test.gyp b/chromium/tools/gyp/test/mac/postbuild-static-library/test.gyp
new file mode 100644
index 00000000000..9ef55a0afa9
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/postbuild-static-library/test.gyp
@@ -0,0 +1,34 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'my_lib',
+ 'type': 'static_library',
+ 'sources': [ 'empty.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Postbuild that touches a file',
+ 'action': [
+ './postbuild-touch-file.sh', 'postbuild-file'
+ ],
+ },
+ ],
+ },
+
+ {
+ 'target_name': 'my_sourceless_lib',
+ 'type': 'static_library',
+ 'dependencies': [ 'my_lib' ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Postbuild that touches a file',
+ 'action': [
+ './postbuild-touch-file.sh', 'postbuild-file-sourceless'
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp b/chromium/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp
new file mode 100644
index 00000000000..6d4f2395e37
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/postbuilds/subdirectory/nested_target.gyp
@@ -0,0 +1,53 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'nest_el',
+ 'type': 'static_library',
+ 'sources': [ '../file_g.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Static library postbuild',
+ 'variables': {
+ 'some_regex': 'a|b',
+ },
+ 'action': [
+ '../script/static_library_postbuild.sh',
+ '<(some_regex)',
+ 'arg with spaces',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'nest_dyna',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ '../file_h.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Dynamic library postbuild',
+ 'variables': {
+ 'some_regex': 'a|b',
+ },
+ 'action': [
+ '../script/shared_library_postbuild.sh',
+ '<(some_regex)',
+ 'arg with spaces',
+ ],
+ },
+ {
+ 'postbuild_name': 'Test paths relative to gyp file',
+ 'action': [
+ '../copy.sh',
+ './copied_file.txt',
+ '${BUILT_PRODUCTS_DIR}/copied_file_2.txt',
+ ],
+ },
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/postbuilds/test.gyp b/chromium/tools/gyp/test/mac/postbuilds/test.gyp
new file mode 100644
index 00000000000..7c0b523f86f
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/postbuilds/test.gyp
@@ -0,0 +1,93 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'el',
+ 'type': 'static_library',
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Static library postbuild',
+ 'variables': {
+ 'some_regex': 'a|b',
+ },
+ 'action': [
+ 'script/static_library_postbuild.sh',
+ '<(some_regex)',
+ 'arg with spaces',
+ ],
+ },
+ {
+ 'postbuild_name': 'Test variable in gyp file',
+ 'action': [
+ 'cp',
+ '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}',
+ '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch.a',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'dyna',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'dependencies': [
+ 'subdirectory/nested_target.gyp:nest_dyna',
+ 'subdirectory/nested_target.gyp:nest_el',
+ ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Dynamic library postbuild',
+ 'variables': {
+ 'some_regex': 'a|b',
+ },
+ 'action': [
+ 'script/shared_library_postbuild.sh',
+ '<(some_regex)',
+ 'arg with spaces',
+ ],
+ },
+ {
+ 'postbuild_name': 'Test variable in gyp file',
+ 'action': [
+ 'cp',
+ '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}',
+ '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch',
+ ],
+ },
+ {
+ 'postbuild_name': 'Test paths relative to gyp file',
+ 'action': [
+ './copy.sh',
+ 'subdirectory/copied_file.txt',
+ '${BUILT_PRODUCTS_DIR}',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'dyna_standalone',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Test variable in gyp file',
+ 'action': [
+ 'cp',
+ '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}',
+ '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}_gyp_touch.dylib',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'EmptyBundle',
+ 'product_extension': 'bundle',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/prefixheader/test.gyp b/chromium/tools/gyp/test/mac/prefixheader/test.gyp
new file mode 100644
index 00000000000..7e6b1af807f
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/prefixheader/test.gyp
@@ -0,0 +1,82 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'prefix_header_c',
+ 'type': 'static_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ },
+ },
+ {
+ 'target_name': 'precompiled_prefix_header_c',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES',
+ },
+ },
+
+ {
+ 'target_name': 'prefix_header_cc',
+ 'type': 'static_library',
+ 'sources': [ 'file.cc', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ },
+ },
+ {
+ 'target_name': 'precompiled_prefix_header_cc',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.cc', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES',
+ },
+ },
+
+ {
+ 'target_name': 'prefix_header_m',
+ 'type': 'static_library',
+ 'sources': [ 'file.m', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ },
+ },
+ {
+ 'target_name': 'precompiled_prefix_header_m',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.m', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES',
+ },
+ },
+
+ {
+ 'target_name': 'prefix_header_mm',
+ 'type': 'static_library',
+ 'sources': [ 'file.mm', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ },
+ },
+ {
+ 'target_name': 'precompiled_prefix_header_mm',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.mm', ],
+ 'xcode_settings': {
+ 'GCC_PREFIX_HEADER': 'header.h',
+ 'GCC_PRECOMPILE_PREFIX_HEADER': 'YES',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/rebuild/test.gyp b/chromium/tools/gyp/test/mac/rebuild/test.gyp
new file mode 100644
index 00000000000..15b4e4ef2f5
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/rebuild/test.gyp
@@ -0,0 +1,56 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test App',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'main.c',
+ ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'TestApp-Info.plist',
+ },
+ },
+ {
+ 'target_name': 'test_app_postbuilds',
+ 'product_name': 'Test App 2',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'main.c',
+ ],
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'TestApp-Info.plist',
+ },
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Postbuild that touches the app binary',
+ 'action': [
+ './delay-touch.sh', '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'test_framework_postbuilds',
+ 'product_name': 'Test Framework',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'empty.c',
+ ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Postbuild that touches the framework binary',
+ 'action': [
+ './delay-touch.sh', '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/rpath/test.gyp b/chromium/tools/gyp/test/mac/rpath/test.gyp
new file mode 100644
index 00000000000..7255cb7cd20
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/rpath/test.gyp
@@ -0,0 +1,48 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'default_rpath',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ },
+ {
+ 'target_name': 'explicit_rpath',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ 'LD_RUNPATH_SEARCH_PATHS': ['@executable_path/.'],
+ },
+ },
+ {
+ 'target_name': 'explicit_rpaths_escaped',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ # Xcode requires spaces to be escaped, else it ends up adding two
+ # independent rpaths.
+ 'LD_RUNPATH_SEARCH_PATHS': ['First\\ rpath', 'Second\\ rpath'],
+ },
+ },
+ {
+ 'target_name': 'explicit_rpaths_bundle',
+ 'product_name': 'My Framework',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c' ],
+ 'xcode_settings': {
+ 'LD_RUNPATH_SEARCH_PATHS': ['@loader_path/.'],
+ },
+ },
+ {
+ 'target_name': 'executable',
+ 'type': 'executable',
+ 'sources': [ 'main.c' ],
+ 'xcode_settings': {
+ 'LD_RUNPATH_SEARCH_PATHS': ['@executable_path/.'],
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/sdkroot/test.gyp b/chromium/tools/gyp/test/mac/sdkroot/test.gyp
new file mode 100644
index 00000000000..2fc11a0280b
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/sdkroot/test.gyp
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'mytarget',
+ 'type': 'executable',
+ 'sources': [ 'file.cc', ],
+ 'xcode_settings': {
+ 'SDKROOT': 'macosx%s',
+ },
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_shorthand.sh', ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'absolute',
+ 'type': 'executable',
+ 'sources': [ 'file.cc', ],
+ 'xcode_settings': {
+ 'SDKROOT': '<(sdk_path)',
+ },
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_shorthand.sh', ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/sourceless-module/test.gyp b/chromium/tools/gyp/test/mac/sourceless-module/test.gyp
new file mode 100644
index 00000000000..49dc2af9c63
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/sourceless-module/test.gyp
@@ -0,0 +1,39 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'empty_bundle',
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ },
+ {
+ 'target_name': 'resource_bundle',
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ 'actions': [
+ {
+ 'action_name': 'Add Resource',
+ 'inputs': [],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/app_manifest/foo.manifest',
+ ],
+ 'action': [
+ 'touch', '<(INTERMEDIATE_DIR)/app_manifest/foo.manifest',
+ ],
+ 'process_outputs_as_mac_bundle_resources': 1,
+ },
+ ],
+ },
+ {
+ 'target_name': 'dependent_on_resource_bundle',
+ 'type': 'executable',
+ 'sources': [ 'empty.c' ],
+ 'dependencies': [
+ 'resource_bundle',
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/strip/subdirectory/subdirectory.gyp b/chromium/tools/gyp/test/mac/strip/subdirectory/subdirectory.gyp
new file mode 100644
index 00000000000..5d0d190914e
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/strip/subdirectory/subdirectory.gyp
@@ -0,0 +1,38 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'nested_strip_save',
+ 'type': 'shared_library',
+ 'sources': [ 'nested_file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ 'STRIPFLAGS': '-s $(CHROMIUM_STRIP_SAVE_FILE)',
+ 'CHROMIUM_STRIP_SAVE_FILE': 'nested_strip.saves',
+ },
+ },
+ {
+ 'target_name': 'nested_strip_save_postbuild',
+ 'type': 'shared_library',
+ 'sources': [ 'nested_file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ 'STRIPFLAGS': '-s $(CHROMIUM_STRIP_SAVE_FILE)',
+ 'CHROMIUM_STRIP_SAVE_FILE': 'nested_strip.saves',
+ },
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'Action that reads CHROMIUM_STRIP_SAVE_FILE',
+ 'action': [
+ './test_reading_save_file_from_postbuild.sh',
+ ],
+ },
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/strip/test.gyp b/chromium/tools/gyp/test/mac/strip/test.gyp
new file mode 100644
index 00000000000..2558aa91bbe
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/strip/test.gyp
@@ -0,0 +1,119 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# These xcode_settings affect stripping:
+# "Deployment postprocessing involves stripping the binary, and setting
+# its file mode, owner, and group."
+#'DEPLOYMENT_POSTPROCESSING': 'YES',
+
+# "Specifies whether to strip symbol information from the binary.
+# Prerequisite: $DEPLOYMENT_POSTPROCESSING = YES" "Default Value: 'NO'"
+#'STRIP_INSTALLED_PRODUCT': 'YES',
+
+# "Values:
+# * all: Strips the binary completely, removing the symbol table and
+# relocation information
+# * non-global: Strips nonglobal symbols but saves external symbols.
+# * debugging: Strips debugging symbols but saves local and global
+# symbols."
+# (maps to no flag, -x, -S in that order)
+#'STRIP_STYLE': 'non-global',
+
+# "Additional strip flags"
+#'STRIPFLAGS': '-c',
+
+# "YES: Copied binaries are stripped of debugging symbols. This does
+# not cause the binary produced by the linker to be stripped. Use
+# 'STRIP_INSTALLED_PRODUCT (Strip Linked Product)' to have the linker
+# strip the binary."
+#'COPY_PHASE_STRIP': 'NO',
+{
+ 'targets': [
+ {
+ 'target_name': 'no_postprocess',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'NO',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ },
+ },
+ {
+ 'target_name': 'no_strip',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'NO',
+ },
+ },
+ {
+ 'target_name': 'strip_all',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ 'STRIP_STYLE': 'all',
+ },
+ },
+ {
+ 'target_name': 'strip_nonglobal',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ 'STRIP_STYLE': 'non-global',
+ },
+ },
+ {
+ 'target_name': 'strip_debugging',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ 'STRIP_STYLE': 'debugging',
+ },
+ },
+ {
+ 'target_name': 'strip_all_custom_flags',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ 'STRIP_STYLE': 'all',
+ 'STRIPFLAGS': '-c',
+ },
+ },
+ {
+ 'target_name': 'strip_all_bundle',
+ 'type': 'shared_library',
+ 'mac_bundle': '1',
+ 'sources': [ 'file.c', ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ 'STRIP_STYLE': 'all',
+ },
+ },
+ {
+ 'target_name': 'strip_save',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'dependencies': [
+ 'subdirectory/subdirectory.gyp:nested_strip_save',
+ 'subdirectory/subdirectory.gyp:nested_strip_save_postbuild',
+ ],
+ 'xcode_settings': {
+ 'DEPLOYMENT_POSTPROCESSING': 'YES',
+ 'STRIP_INSTALLED_PRODUCT': 'YES',
+ 'STRIPFLAGS': '-s $(CHROMIUM_STRIP_SAVE_FILE)',
+ 'CHROMIUM_STRIP_SAVE_FILE': 'strip.saves',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/type_envvars/test.gyp b/chromium/tools/gyp/test/mac/type_envvars/test.gyp
new file mode 100644
index 00000000000..465670056bd
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/type_envvars/test.gyp
@@ -0,0 +1,100 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'my_app',
+ 'product_name': 'My App',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_bundle_executable.sh', ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'bundle_loadable_module',
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_bundle_loadable_module.sh', ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'bundle_shared_library',
+ 'type': 'shared_library',
+ 'mac_bundle': 1,
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_bundle_shared_library.sh', ],
+ },
+ ],
+ },
+ # Types 'static_library' and 'none' can't exist as bundles.
+
+ {
+ 'target_name': 'nonbundle_executable',
+ 'type': 'executable',
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_nonbundle_executable.sh', ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'nonbundle_loadable_module',
+ 'type': 'loadable_module',
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_nonbundle_loadable_module.sh', ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'nonbundle_shared_library',
+ 'type': 'shared_library',
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_nonbundle_shared_library.sh', ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'nonbundle_static_library',
+ 'type': 'static_library',
+ 'sources': [ 'file.c', ],
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_nonbundle_static_library.sh', ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'nonbundle_none',
+ 'type': 'none',
+ 'postbuilds': [
+ {
+ 'postbuild_name': 'envtest',
+ 'action': [ './test_nonbundle_none.sh', ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/xcode-env-order/test.gyp b/chromium/tools/gyp/test/mac/xcode-env-order/test.gyp
new file mode 100644
index 00000000000..8f975f7d6b1
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/xcode-env-order/test.gyp
@@ -0,0 +1,121 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'test_app',
+ 'product_name': 'Test',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'main.c',
+ 'file.ext1',
+ 'file.ext2',
+ 'file.ext3',
+ ],
+ # Env vars in copies.
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/${PRODUCT_NAME}-copy-brace',
+ 'files': [ 'main.c', ], # ${SOURCE_ROOT} doesn't work with xcode
+ },
+ {
+ 'destination': '<(PRODUCT_DIR)/$(PRODUCT_NAME)-copy-paren',
+ 'files': [ '$(SOURCE_ROOT)/main.c', ],
+ },
+ {
+ 'destination': '<(PRODUCT_DIR)/$PRODUCT_NAME-copy-bare',
+ 'files': [ 'main.c', ], # $SOURCE_ROOT doesn't work with xcode
+ },
+ ],
+ # Env vars in actions. The $FOO's are here to test that env vars that
+ # aren't defined are handled in some way that doesn't break the build.
+ 'actions': [
+ {
+ 'action_name': 'Action copy braces ${PRODUCT_NAME} ${FOO}',
+ 'description': 'Action copy braces ${PRODUCT_NAME} ${FOO}',
+ 'inputs': [ '${SOURCE_ROOT}/main.c' ],
+ # Referencing ${PRODUCT_NAME} in action outputs doesn't work with
+ # the Xcode generator (PRODUCT_NAME expands to "Test Support").
+ 'outputs': [ '<(PRODUCT_DIR)/action-copy-brace.txt' ],
+ 'action': [ 'cp', '${SOURCE_ROOT}/main.c',
+ '<(PRODUCT_DIR)/action-copy-brace.txt' ],
+ },
+ {
+ 'action_name': 'Action copy parens $(PRODUCT_NAME) $(FOO)',
+ 'description': 'Action copy parens $(PRODUCT_NAME) $(FOO)',
+ 'inputs': [ '$(SOURCE_ROOT)/main.c' ],
+ # Referencing $(PRODUCT_NAME) in action outputs doesn't work with
+ # the Xcode generator (PRODUCT_NAME expands to "Test Support").
+ 'outputs': [ '<(PRODUCT_DIR)/action-copy-paren.txt' ],
+ 'action': [ 'cp', '$(SOURCE_ROOT)/main.c',
+ '<(PRODUCT_DIR)/action-copy-paren.txt' ],
+ },
+ {
+ 'action_name': 'Action copy bare $PRODUCT_NAME $FOO',
+ 'description': 'Action copy bare $PRODUCT_NAME $FOO',
+ 'inputs': [ '$SOURCE_ROOT/main.c' ],
+ # Referencing $PRODUCT_NAME in action outputs doesn't work with
+ # the Xcode generator (PRODUCT_NAME expands to "Test Support").
+ 'outputs': [ '<(PRODUCT_DIR)/action-copy-bare.txt' ],
+ 'action': [ 'cp', '$SOURCE_ROOT/main.c',
+ '<(PRODUCT_DIR)/action-copy-bare.txt' ],
+ },
+ ],
+ # Env vars in xcode_settings.
+ 'xcode_settings': {
+ 'INFOPLIST_FILE': 'Info.plist',
+ 'STRING_KEY': '/Source/Project',
+
+ 'BRACE_DEPENDENT_KEY2': '${STRING_KEY}/${PRODUCT_NAME}',
+ 'BRACE_DEPENDENT_KEY1': 'D:${BRACE_DEPENDENT_KEY2}',
+ 'BRACE_DEPENDENT_KEY3': '${PRODUCT_TYPE}:${BRACE_DEPENDENT_KEY1}',
+
+ 'PAREN_DEPENDENT_KEY2': '$(STRING_KEY)/$(PRODUCT_NAME)',
+ 'PAREN_DEPENDENT_KEY1': 'D:$(PAREN_DEPENDENT_KEY2)',
+ 'PAREN_DEPENDENT_KEY3': '$(PRODUCT_TYPE):$(PAREN_DEPENDENT_KEY1)',
+
+ 'BARE_DEPENDENT_KEY2': '$STRING_KEY/$PRODUCT_NAME',
+ 'BARE_DEPENDENT_KEY1': 'D:$BARE_DEPENDENT_KEY2',
+ 'BARE_DEPENDENT_KEY3': '$PRODUCT_TYPE:$BARE_DEPENDENT_KEY1',
+
+ 'MIXED_DEPENDENT_KEY': '${STRING_KEY}:$(PRODUCT_NAME):$MACH_O_TYPE',
+ },
+ # Env vars in rules. The $FOO's are here to test that env vars that
+ # aren't defined are handled in some way that doesn't break the build.
+ 'rules': [
+ {
+ 'rule_name': 'brace_rule',
+ 'message': 'Rule braces ${PRODUCT_NAME} ${FOO} <(RULE_INPUT_NAME)',
+ 'extension': 'ext1',
+ 'inputs': [ '${SOURCE_ROOT}/main.c' ],
+ 'outputs': [ '<(PRODUCT_DIR)/rule-copy-brace.txt' ],
+ 'action': [ 'cp', '${SOURCE_ROOT}/main.c',
+ '<(PRODUCT_DIR)/rule-copy-brace.txt' ],
+ },
+ {
+ 'rule_name': 'paren_rule',
+ 'message': 'Rule parens $(PRODUCT_NAME) $(FOO) <(RULE_INPUT_NAME)',
+ 'extension': 'ext2',
+ 'inputs': [ '$(SOURCE_ROOT)/main.c' ],
+ 'outputs': [ '<(PRODUCT_DIR)/rule-copy-paren.txt' ],
+ 'action': [ 'cp', '$(SOURCE_ROOT)/main.c',
+ '<(PRODUCT_DIR)/rule-copy-paren.txt' ],
+ },
+ # TODO: Fails in xcode. Looks like a bug in the xcode generator though
+ # (which uses makefiles for rules, and thinks $PRODUCT_NAME is
+ # $(P)RODUCT_NAME).
+ #{
+ # 'rule_name': 'bare_rule',
+ # 'message': 'Rule copy bare $PRODUCT_NAME $FOO',
+ # 'extension': 'ext3',
+ # 'inputs': [ '$SOURCE_ROOT/main.c' ],
+ # 'outputs': [ '<(PRODUCT_DIR)/rule-copy-bare.txt' ],
+ # 'action': [ 'cp', '$SOURCE_ROOT/main.c',
+ # '<(PRODUCT_DIR)/rule-copy-bare.txt' ],
+ #},
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/mac/xcode-gcc/test-clang.gyp b/chromium/tools/gyp/test/mac/xcode-gcc/test-clang.gyp
new file mode 100644
index 00000000000..9f4a98ae73f
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/xcode-gcc/test-clang.gyp
@@ -0,0 +1,42 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'make_global_settings': [
+ ['CC', '/usr/bin/clang'],
+ ['CXX', '/usr/bin/clang++'],
+ ],
+
+ 'targets': [
+ {
+ 'target_name': 'aliasing_yes',
+ 'type': 'executable',
+ 'sources': [ 'aliasing.cc', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'GCC_STRICT_ALIASING': 'YES',
+ 'GCC_OPTIMIZATION_LEVEL': 2,
+ },
+ },
+ {
+ 'target_name': 'aliasing_no',
+ 'type': 'executable',
+ 'sources': [ 'aliasing.cc', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'GCC_STRICT_ALIASING': 'NO',
+ 'GCC_OPTIMIZATION_LEVEL': 2,
+ },
+ },
+ {
+ 'target_name': 'aliasing_default',
+ 'type': 'executable',
+ 'sources': [ 'aliasing.cc', ],
+ 'xcode_settings': {
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'GCC_OPTIMIZATION_LEVEL': 2,
+ },
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/mac/xcode-gcc/test.gyp b/chromium/tools/gyp/test/mac/xcode-gcc/test.gyp
new file mode 100644
index 00000000000..1ca8b215d87
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/xcode-gcc/test.gyp
@@ -0,0 +1,60 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'target_defaults': {
+ 'xcode_settings': {
+ 'GCC_TREAT_WARNINGS_AS_ERRORS': 'YES',
+ },
+ },
+
+ 'variables': {
+ # Non-failing tests should check that these trivial files in every language
+ # still compile correctly.
+ 'valid_sources': [
+ 'valid_c.c',
+ 'valid_cc.cc',
+ 'valid_m.m',
+ 'valid_mm.mm',
+ ],
+ },
+
+ # Targets come in pairs: 'foo' and 'foo-fail', with the former building with
+ # no warnings and the latter not.
+ 'targets': [
+ # GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO (default: YES):
+ {
+ 'target_name': 'warn_about_invalid_offsetof_macro',
+ 'type': 'executable',
+ 'sources': [
+ 'warn_about_invalid_offsetof_macro.cc',
+ '<@(valid_sources)',
+ ],
+ 'xcode_settings': {
+ 'GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO': 'NO',
+ },
+ },
+ {
+ 'target_name': 'warn_about_invalid_offsetof_macro-fail',
+ 'type': 'executable',
+ 'sources': [ 'warn_about_invalid_offsetof_macro.cc', ],
+ },
+ # GCC_WARN_ABOUT_MISSING_NEWLINE (default: NO):
+ {
+ 'target_name': 'warn_about_missing_newline',
+ 'type': 'executable',
+ 'sources': [
+ 'warn_about_missing_newline.c',
+ '<@(valid_sources)',
+ ],
+ },
+ {
+ 'target_name': 'warn_about_missing_newline-fail',
+ 'type': 'executable',
+ 'sources': [ 'warn_about_missing_newline.c', ],
+ 'xcode_settings': {
+ 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/make/dependencies.gyp b/chromium/tools/gyp/test/make/dependencies.gyp
new file mode 100644
index 00000000000..e2bee24fcef
--- /dev/null
+++ b/chromium/tools/gyp/test/make/dependencies.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'main',
+ 'type': 'executable',
+ 'sources': [
+ 'main.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/make/noload/all.gyp b/chromium/tools/gyp/test/make/noload/all.gyp
new file mode 100644
index 00000000000..1617a9e97c9
--- /dev/null
+++ b/chromium/tools/gyp/test/make/noload/all.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'exe',
+ 'type': 'executable',
+ 'sources': [
+ 'main.c',
+ ],
+ 'dependencies': [
+ 'lib/shared.gyp:shared',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/make/noload/lib/shared.gyp b/chromium/tools/gyp/test/make/noload/lib/shared.gyp
new file mode 100644
index 00000000000..8a8841b3a06
--- /dev/null
+++ b/chromium/tools/gyp/test/make/noload/lib/shared.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'shared',
+ 'type': 'shared_library',
+ 'sources': [
+ 'shared.c',
+ 'shared.h',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/make_global_settings/basics/make_global_settings.gyp b/chromium/tools/gyp/test/make_global_settings/basics/make_global_settings.gyp
new file mode 100644
index 00000000000..07b8791c08d
--- /dev/null
+++ b/chromium/tools/gyp/test/make_global_settings/basics/make_global_settings.gyp
@@ -0,0 +1,17 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style licence that can be
+# found in the LICENSE file.
+
+{
+ 'make_global_settings': [
+ ['CC', 'clang'],
+ ['LINK', 'clang++'],
+ ],
+ 'targets': [
+ {
+ 'target_name': 'test',
+ 'type': 'static_library',
+ 'sources': [ 'foo.c' ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/make_global_settings/env-wrapper/wrapper.gyp b/chromium/tools/gyp/test/make_global_settings/env-wrapper/wrapper.gyp
new file mode 100644
index 00000000000..c5d46bd068c
--- /dev/null
+++ b/chromium/tools/gyp/test/make_global_settings/env-wrapper/wrapper.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'make_global_settings': [
+ ['CC', 'clang'],
+ ['LINK', 'clang++'],
+ ['CC.host', 'clang'],
+ ],
+ 'targets': [
+ {
+ 'target_name': 'test',
+ 'type': 'static_library',
+ 'sources': [ 'foo.c' ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/make_global_settings/wrapper/wrapper.gyp b/chromium/tools/gyp/test/make_global_settings/wrapper/wrapper.gyp
new file mode 100644
index 00000000000..3d4cd04b164
--- /dev/null
+++ b/chromium/tools/gyp/test/make_global_settings/wrapper/wrapper.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'make_global_settings': [
+ ['CC', 'clang'],
+ ['CC_wrapper', 'distcc'],
+ ['LINK', 'clang++'],
+ ['LINK_wrapper', 'distlink'],
+ ['CC.host', 'clang'],
+ ['CC.host_wrapper', 'ccache'],
+ ],
+ 'targets': [
+ {
+ 'target_name': 'test',
+ 'type': 'static_library',
+ 'sources': [ 'foo.c' ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/many-actions/many-actions-unsorted.gyp b/chromium/tools/gyp/test/many-actions/many-actions-unsorted.gyp
new file mode 100644
index 00000000000..eec79fe8d85
--- /dev/null
+++ b/chromium/tools/gyp/test/many-actions/many-actions-unsorted.gyp
@@ -0,0 +1,154 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'msvs_cygwin_dirs': ['../../../../<(DEPTH)/third_party/cygwin'],
+ },
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'none',
+ 'actions': [
+ # Notice that the inputs go 0, 1, ..., 0, 1, .... This is to test
+ # a regression in the msvs generator in _AddActions.
+ {
+ 'action_name': 'do_0',
+ 'inputs': ['file0'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_0.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_0.h',
+ ],
+ },
+ {
+ 'action_name': 'do_1',
+ 'inputs': ['file1'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_1.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_1.h',
+ ],
+ },
+ {
+ 'action_name': 'do_2',
+ 'inputs': ['file2'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_2.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_2.h',
+ ],
+ },
+ {
+ 'action_name': 'do_3',
+ 'inputs': ['file3'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_3.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_3.h',
+ ],
+ },
+ {
+ 'action_name': 'do_4',
+ 'inputs': ['file4'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_4.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_4.h',
+ ],
+ },
+ {
+ 'action_name': 'do_5',
+ 'inputs': ['file0'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_5.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_5.h',
+ ],
+ },
+ {
+ 'action_name': 'do_6',
+ 'inputs': ['file1'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_6.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_6.h',
+ ],
+ },
+ {
+ 'action_name': 'do_7',
+ 'inputs': ['file2'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_7.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_7.h',
+ ],
+ },
+ {
+ 'action_name': 'do_8',
+ 'inputs': ['file3'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_8.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_8.h',
+ ],
+ },
+ {
+ 'action_name': 'do_9',
+ 'inputs': ['file4'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_9.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_9.h',
+ ],
+ },
+ {
+ 'action_name': 'do_10',
+ 'inputs': ['file0'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_10.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_10.h',
+ ],
+ },
+ {
+ 'action_name': 'do_11',
+ 'inputs': ['file1'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_11.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_11.h',
+ ],
+ },
+ {
+ 'action_name': 'do_12',
+ 'inputs': ['file2'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_12.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_12.h',
+ ],
+ },
+ {
+ 'action_name': 'do_13',
+ 'inputs': ['file3'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_13.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_13.h',
+ ],
+ },
+ {
+ 'action_name': 'do_14',
+ 'inputs': ['file4'],
+ 'outputs': ['<(PRODUCT_DIR)/generated_14.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_14.h',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/many-actions/many-actions.gyp b/chromium/tools/gyp/test/many-actions/many-actions.gyp
new file mode 100644
index 00000000000..38545d2d885
--- /dev/null
+++ b/chromium/tools/gyp/test/many-actions/many-actions.gyp
@@ -0,0 +1,1817 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'msvs_cygwin_dirs': ['../../../../<(DEPTH)/third_party/cygwin'],
+ },
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'do_0',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_0.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_0.h',
+ ],
+ },
+ {
+ 'action_name': 'do_1',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_1.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_1.h',
+ ],
+ },
+ {
+ 'action_name': 'do_2',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_2.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_2.h',
+ ],
+ },
+ {
+ 'action_name': 'do_3',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_3.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_3.h',
+ ],
+ },
+ {
+ 'action_name': 'do_4',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_4.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_4.h',
+ ],
+ },
+ {
+ 'action_name': 'do_5',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_5.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_5.h',
+ ],
+ },
+ {
+ 'action_name': 'do_6',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_6.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_6.h',
+ ],
+ },
+ {
+ 'action_name': 'do_7',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_7.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_7.h',
+ ],
+ },
+ {
+ 'action_name': 'do_8',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_8.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_8.h',
+ ],
+ },
+ {
+ 'action_name': 'do_9',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_9.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_9.h',
+ ],
+ },
+ {
+ 'action_name': 'do_10',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_10.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_10.h',
+ ],
+ },
+ {
+ 'action_name': 'do_11',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_11.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_11.h',
+ ],
+ },
+ {
+ 'action_name': 'do_12',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_12.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_12.h',
+ ],
+ },
+ {
+ 'action_name': 'do_13',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_13.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_13.h',
+ ],
+ },
+ {
+ 'action_name': 'do_14',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_14.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_14.h',
+ ],
+ },
+ {
+ 'action_name': 'do_15',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_15.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_15.h',
+ ],
+ },
+ {
+ 'action_name': 'do_16',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_16.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_16.h',
+ ],
+ },
+ {
+ 'action_name': 'do_17',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_17.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_17.h',
+ ],
+ },
+ {
+ 'action_name': 'do_18',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_18.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_18.h',
+ ],
+ },
+ {
+ 'action_name': 'do_19',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_19.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_19.h',
+ ],
+ },
+ {
+ 'action_name': 'do_20',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_20.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_20.h',
+ ],
+ },
+ {
+ 'action_name': 'do_21',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_21.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_21.h',
+ ],
+ },
+ {
+ 'action_name': 'do_22',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_22.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_22.h',
+ ],
+ },
+ {
+ 'action_name': 'do_23',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_23.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_23.h',
+ ],
+ },
+ {
+ 'action_name': 'do_24',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_24.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_24.h',
+ ],
+ },
+ {
+ 'action_name': 'do_25',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_25.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_25.h',
+ ],
+ },
+ {
+ 'action_name': 'do_26',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_26.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_26.h',
+ ],
+ },
+ {
+ 'action_name': 'do_27',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_27.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_27.h',
+ ],
+ },
+ {
+ 'action_name': 'do_28',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_28.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_28.h',
+ ],
+ },
+ {
+ 'action_name': 'do_29',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_29.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_29.h',
+ ],
+ },
+ {
+ 'action_name': 'do_30',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_30.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_30.h',
+ ],
+ },
+ {
+ 'action_name': 'do_31',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_31.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_31.h',
+ ],
+ },
+ {
+ 'action_name': 'do_32',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_32.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_32.h',
+ ],
+ },
+ {
+ 'action_name': 'do_33',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_33.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_33.h',
+ ],
+ },
+ {
+ 'action_name': 'do_34',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_34.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_34.h',
+ ],
+ },
+ {
+ 'action_name': 'do_35',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_35.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_35.h',
+ ],
+ },
+ {
+ 'action_name': 'do_36',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_36.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_36.h',
+ ],
+ },
+ {
+ 'action_name': 'do_37',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_37.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_37.h',
+ ],
+ },
+ {
+ 'action_name': 'do_38',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_38.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_38.h',
+ ],
+ },
+ {
+ 'action_name': 'do_39',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_39.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_39.h',
+ ],
+ },
+ {
+ 'action_name': 'do_40',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_40.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_40.h',
+ ],
+ },
+ {
+ 'action_name': 'do_41',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_41.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_41.h',
+ ],
+ },
+ {
+ 'action_name': 'do_42',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_42.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_42.h',
+ ],
+ },
+ {
+ 'action_name': 'do_43',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_43.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_43.h',
+ ],
+ },
+ {
+ 'action_name': 'do_44',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_44.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_44.h',
+ ],
+ },
+ {
+ 'action_name': 'do_45',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_45.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_45.h',
+ ],
+ },
+ {
+ 'action_name': 'do_46',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_46.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_46.h',
+ ],
+ },
+ {
+ 'action_name': 'do_47',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_47.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_47.h',
+ ],
+ },
+ {
+ 'action_name': 'do_48',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_48.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_48.h',
+ ],
+ },
+ {
+ 'action_name': 'do_49',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_49.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_49.h',
+ ],
+ },
+ {
+ 'action_name': 'do_50',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_50.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_50.h',
+ ],
+ },
+ {
+ 'action_name': 'do_51',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_51.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_51.h',
+ ],
+ },
+ {
+ 'action_name': 'do_52',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_52.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_52.h',
+ ],
+ },
+ {
+ 'action_name': 'do_53',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_53.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_53.h',
+ ],
+ },
+ {
+ 'action_name': 'do_54',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_54.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_54.h',
+ ],
+ },
+ {
+ 'action_name': 'do_55',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_55.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_55.h',
+ ],
+ },
+ {
+ 'action_name': 'do_56',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_56.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_56.h',
+ ],
+ },
+ {
+ 'action_name': 'do_57',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_57.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_57.h',
+ ],
+ },
+ {
+ 'action_name': 'do_58',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_58.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_58.h',
+ ],
+ },
+ {
+ 'action_name': 'do_59',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_59.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_59.h',
+ ],
+ },
+ {
+ 'action_name': 'do_60',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_60.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_60.h',
+ ],
+ },
+ {
+ 'action_name': 'do_61',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_61.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_61.h',
+ ],
+ },
+ {
+ 'action_name': 'do_62',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_62.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_62.h',
+ ],
+ },
+ {
+ 'action_name': 'do_63',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_63.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_63.h',
+ ],
+ },
+ {
+ 'action_name': 'do_64',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_64.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_64.h',
+ ],
+ },
+ {
+ 'action_name': 'do_65',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_65.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_65.h',
+ ],
+ },
+ {
+ 'action_name': 'do_66',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_66.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_66.h',
+ ],
+ },
+ {
+ 'action_name': 'do_67',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_67.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_67.h',
+ ],
+ },
+ {
+ 'action_name': 'do_68',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_68.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_68.h',
+ ],
+ },
+ {
+ 'action_name': 'do_69',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_69.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_69.h',
+ ],
+ },
+ {
+ 'action_name': 'do_70',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_70.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_70.h',
+ ],
+ },
+ {
+ 'action_name': 'do_71',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_71.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_71.h',
+ ],
+ },
+ {
+ 'action_name': 'do_72',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_72.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_72.h',
+ ],
+ },
+ {
+ 'action_name': 'do_73',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_73.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_73.h',
+ ],
+ },
+ {
+ 'action_name': 'do_74',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_74.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_74.h',
+ ],
+ },
+ {
+ 'action_name': 'do_75',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_75.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_75.h',
+ ],
+ },
+ {
+ 'action_name': 'do_76',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_76.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_76.h',
+ ],
+ },
+ {
+ 'action_name': 'do_77',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_77.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_77.h',
+ ],
+ },
+ {
+ 'action_name': 'do_78',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_78.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_78.h',
+ ],
+ },
+ {
+ 'action_name': 'do_79',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_79.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_79.h',
+ ],
+ },
+ {
+ 'action_name': 'do_80',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_80.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_80.h',
+ ],
+ },
+ {
+ 'action_name': 'do_81',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_81.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_81.h',
+ ],
+ },
+ {
+ 'action_name': 'do_82',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_82.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_82.h',
+ ],
+ },
+ {
+ 'action_name': 'do_83',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_83.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_83.h',
+ ],
+ },
+ {
+ 'action_name': 'do_84',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_84.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_84.h',
+ ],
+ },
+ {
+ 'action_name': 'do_85',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_85.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_85.h',
+ ],
+ },
+ {
+ 'action_name': 'do_86',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_86.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_86.h',
+ ],
+ },
+ {
+ 'action_name': 'do_87',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_87.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_87.h',
+ ],
+ },
+ {
+ 'action_name': 'do_88',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_88.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_88.h',
+ ],
+ },
+ {
+ 'action_name': 'do_89',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_89.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_89.h',
+ ],
+ },
+ {
+ 'action_name': 'do_90',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_90.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_90.h',
+ ],
+ },
+ {
+ 'action_name': 'do_91',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_91.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_91.h',
+ ],
+ },
+ {
+ 'action_name': 'do_92',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_92.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_92.h',
+ ],
+ },
+ {
+ 'action_name': 'do_93',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_93.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_93.h',
+ ],
+ },
+ {
+ 'action_name': 'do_94',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_94.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_94.h',
+ ],
+ },
+ {
+ 'action_name': 'do_95',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_95.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_95.h',
+ ],
+ },
+ {
+ 'action_name': 'do_96',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_96.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_96.h',
+ ],
+ },
+ {
+ 'action_name': 'do_97',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_97.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_97.h',
+ ],
+ },
+ {
+ 'action_name': 'do_98',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_98.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_98.h',
+ ],
+ },
+ {
+ 'action_name': 'do_99',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_99.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_99.h',
+ ],
+ },
+ {
+ 'action_name': 'do_100',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_100.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_100.h',
+ ],
+ },
+ {
+ 'action_name': 'do_101',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_101.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_101.h',
+ ],
+ },
+ {
+ 'action_name': 'do_102',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_102.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_102.h',
+ ],
+ },
+ {
+ 'action_name': 'do_103',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_103.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_103.h',
+ ],
+ },
+ {
+ 'action_name': 'do_104',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_104.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_104.h',
+ ],
+ },
+ {
+ 'action_name': 'do_105',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_105.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_105.h',
+ ],
+ },
+ {
+ 'action_name': 'do_106',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_106.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_106.h',
+ ],
+ },
+ {
+ 'action_name': 'do_107',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_107.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_107.h',
+ ],
+ },
+ {
+ 'action_name': 'do_108',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_108.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_108.h',
+ ],
+ },
+ {
+ 'action_name': 'do_109',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_109.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_109.h',
+ ],
+ },
+ {
+ 'action_name': 'do_110',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_110.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_110.h',
+ ],
+ },
+ {
+ 'action_name': 'do_111',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_111.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_111.h',
+ ],
+ },
+ {
+ 'action_name': 'do_112',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_112.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_112.h',
+ ],
+ },
+ {
+ 'action_name': 'do_113',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_113.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_113.h',
+ ],
+ },
+ {
+ 'action_name': 'do_114',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_114.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_114.h',
+ ],
+ },
+ {
+ 'action_name': 'do_115',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_115.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_115.h',
+ ],
+ },
+ {
+ 'action_name': 'do_116',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_116.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_116.h',
+ ],
+ },
+ {
+ 'action_name': 'do_117',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_117.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_117.h',
+ ],
+ },
+ {
+ 'action_name': 'do_118',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_118.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_118.h',
+ ],
+ },
+ {
+ 'action_name': 'do_119',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_119.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_119.h',
+ ],
+ },
+ {
+ 'action_name': 'do_120',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_120.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_120.h',
+ ],
+ },
+ {
+ 'action_name': 'do_121',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_121.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_121.h',
+ ],
+ },
+ {
+ 'action_name': 'do_122',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_122.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_122.h',
+ ],
+ },
+ {
+ 'action_name': 'do_123',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_123.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_123.h',
+ ],
+ },
+ {
+ 'action_name': 'do_124',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_124.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_124.h',
+ ],
+ },
+ {
+ 'action_name': 'do_125',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_125.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_125.h',
+ ],
+ },
+ {
+ 'action_name': 'do_126',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_126.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_126.h',
+ ],
+ },
+ {
+ 'action_name': 'do_127',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_127.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_127.h',
+ ],
+ },
+ {
+ 'action_name': 'do_128',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_128.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_128.h',
+ ],
+ },
+ {
+ 'action_name': 'do_129',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_129.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_129.h',
+ ],
+ },
+ {
+ 'action_name': 'do_130',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_130.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_130.h',
+ ],
+ },
+ {
+ 'action_name': 'do_131',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_131.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_131.h',
+ ],
+ },
+ {
+ 'action_name': 'do_132',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_132.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_132.h',
+ ],
+ },
+ {
+ 'action_name': 'do_133',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_133.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_133.h',
+ ],
+ },
+ {
+ 'action_name': 'do_134',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_134.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_134.h',
+ ],
+ },
+ {
+ 'action_name': 'do_135',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_135.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_135.h',
+ ],
+ },
+ {
+ 'action_name': 'do_136',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_136.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_136.h',
+ ],
+ },
+ {
+ 'action_name': 'do_137',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_137.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_137.h',
+ ],
+ },
+ {
+ 'action_name': 'do_138',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_138.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_138.h',
+ ],
+ },
+ {
+ 'action_name': 'do_139',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_139.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_139.h',
+ ],
+ },
+ {
+ 'action_name': 'do_140',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_140.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_140.h',
+ ],
+ },
+ {
+ 'action_name': 'do_141',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_141.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_141.h',
+ ],
+ },
+ {
+ 'action_name': 'do_142',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_142.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_142.h',
+ ],
+ },
+ {
+ 'action_name': 'do_143',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_143.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_143.h',
+ ],
+ },
+ {
+ 'action_name': 'do_144',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_144.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_144.h',
+ ],
+ },
+ {
+ 'action_name': 'do_145',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_145.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_145.h',
+ ],
+ },
+ {
+ 'action_name': 'do_146',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_146.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_146.h',
+ ],
+ },
+ {
+ 'action_name': 'do_147',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_147.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_147.h',
+ ],
+ },
+ {
+ 'action_name': 'do_148',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_148.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_148.h',
+ ],
+ },
+ {
+ 'action_name': 'do_149',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_149.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_149.h',
+ ],
+ },
+ {
+ 'action_name': 'do_150',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_150.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_150.h',
+ ],
+ },
+ {
+ 'action_name': 'do_151',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_151.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_151.h',
+ ],
+ },
+ {
+ 'action_name': 'do_152',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_152.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_152.h',
+ ],
+ },
+ {
+ 'action_name': 'do_153',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_153.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_153.h',
+ ],
+ },
+ {
+ 'action_name': 'do_154',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_154.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_154.h',
+ ],
+ },
+ {
+ 'action_name': 'do_155',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_155.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_155.h',
+ ],
+ },
+ {
+ 'action_name': 'do_156',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_156.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_156.h',
+ ],
+ },
+ {
+ 'action_name': 'do_157',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_157.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_157.h',
+ ],
+ },
+ {
+ 'action_name': 'do_158',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_158.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_158.h',
+ ],
+ },
+ {
+ 'action_name': 'do_159',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_159.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_159.h',
+ ],
+ },
+ {
+ 'action_name': 'do_160',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_160.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_160.h',
+ ],
+ },
+ {
+ 'action_name': 'do_161',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_161.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_161.h',
+ ],
+ },
+ {
+ 'action_name': 'do_162',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_162.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_162.h',
+ ],
+ },
+ {
+ 'action_name': 'do_163',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_163.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_163.h',
+ ],
+ },
+ {
+ 'action_name': 'do_164',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_164.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_164.h',
+ ],
+ },
+ {
+ 'action_name': 'do_165',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_165.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_165.h',
+ ],
+ },
+ {
+ 'action_name': 'do_166',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_166.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_166.h',
+ ],
+ },
+ {
+ 'action_name': 'do_167',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_167.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_167.h',
+ ],
+ },
+ {
+ 'action_name': 'do_168',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_168.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_168.h',
+ ],
+ },
+ {
+ 'action_name': 'do_169',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_169.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_169.h',
+ ],
+ },
+ {
+ 'action_name': 'do_170',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_170.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_170.h',
+ ],
+ },
+ {
+ 'action_name': 'do_171',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_171.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_171.h',
+ ],
+ },
+ {
+ 'action_name': 'do_172',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_172.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_172.h',
+ ],
+ },
+ {
+ 'action_name': 'do_173',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_173.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_173.h',
+ ],
+ },
+ {
+ 'action_name': 'do_174',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_174.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_174.h',
+ ],
+ },
+ {
+ 'action_name': 'do_175',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_175.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_175.h',
+ ],
+ },
+ {
+ 'action_name': 'do_176',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_176.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_176.h',
+ ],
+ },
+ {
+ 'action_name': 'do_177',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_177.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_177.h',
+ ],
+ },
+ {
+ 'action_name': 'do_178',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_178.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_178.h',
+ ],
+ },
+ {
+ 'action_name': 'do_179',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_179.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_179.h',
+ ],
+ },
+ {
+ 'action_name': 'do_180',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_180.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_180.h',
+ ],
+ },
+ {
+ 'action_name': 'do_181',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_181.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_181.h',
+ ],
+ },
+ {
+ 'action_name': 'do_182',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_182.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_182.h',
+ ],
+ },
+ {
+ 'action_name': 'do_183',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_183.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_183.h',
+ ],
+ },
+ {
+ 'action_name': 'do_184',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_184.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_184.h',
+ ],
+ },
+ {
+ 'action_name': 'do_185',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_185.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_185.h',
+ ],
+ },
+ {
+ 'action_name': 'do_186',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_186.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_186.h',
+ ],
+ },
+ {
+ 'action_name': 'do_187',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_187.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_187.h',
+ ],
+ },
+ {
+ 'action_name': 'do_188',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_188.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_188.h',
+ ],
+ },
+ {
+ 'action_name': 'do_189',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_189.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_189.h',
+ ],
+ },
+ {
+ 'action_name': 'do_190',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_190.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_190.h',
+ ],
+ },
+ {
+ 'action_name': 'do_191',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_191.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_191.h',
+ ],
+ },
+ {
+ 'action_name': 'do_192',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_192.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_192.h',
+ ],
+ },
+ {
+ 'action_name': 'do_193',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_193.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_193.h',
+ ],
+ },
+ {
+ 'action_name': 'do_194',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_194.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_194.h',
+ ],
+ },
+ {
+ 'action_name': 'do_195',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_195.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_195.h',
+ ],
+ },
+ {
+ 'action_name': 'do_196',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_196.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_196.h',
+ ],
+ },
+ {
+ 'action_name': 'do_197',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_197.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_197.h',
+ ],
+ },
+ {
+ 'action_name': 'do_198',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_198.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_198.h',
+ ],
+ },
+ {
+ 'action_name': 'do_199',
+ 'inputs': [],
+ 'outputs': ['<(PRODUCT_DIR)/generated_199.h'],
+ 'action': [
+ 'touch',
+ '<(PRODUCT_DIR)/generated_199.h',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/module/src/module.gyp b/chromium/tools/gyp/test/module/src/module.gyp
new file mode 100644
index 00000000000..7fbfbb04a0b
--- /dev/null
+++ b/chromium/tools/gyp/test/module/src/module.gyp
@@ -0,0 +1,55 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'conditions': [
+ ['OS=="win"', {
+ 'defines': ['PLATFORM_WIN'],
+ }],
+ ['OS=="mac" or OS=="ios"', {
+ 'defines': ['PLATFORM_MAC'],
+ }],
+ ['OS=="linux"', {
+ 'defines': ['PLATFORM_LINUX'],
+ # Support 64-bit shared libs (also works fine for 32-bit).
+ 'cflags': ['-fPIC'],
+ 'libraries': ['-ldl'],
+ }],
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'dependencies': [
+ 'lib1',
+ 'lib2',
+ ],
+ 'sources': [
+ 'program.c',
+ ],
+ },
+ {
+ 'target_name': 'lib1',
+ 'type': 'loadable_module',
+ 'product_name': 'lib1',
+ 'product_prefix': '',
+ 'xcode_settings': {'OTHER_LDFLAGS': ['-dynamiclib'], 'MACH_O_TYPE': ''},
+ 'sources': [
+ 'lib1.c',
+ ],
+ },
+ {
+ 'target_name': 'lib2',
+ 'product_name': 'lib2',
+ 'product_prefix': '',
+ 'type': 'loadable_module',
+ 'xcode_settings': {'OTHER_LDFLAGS': ['-dynamiclib'], 'MACH_O_TYPE': ''},
+ 'sources': [
+ 'lib2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/config_attrs/hello.gyp b/chromium/tools/gyp/test/msvs/config_attrs/hello.gyp
new file mode 100644
index 00000000000..810a80edd80
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/config_attrs/hello.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ 'msvs_configuration_attributes': {
+ 'OutputDirectory':'$(SolutionDir)VC90/'
+ },
+ 'msbuild_configuration_attributes': {
+ 'OutputDirectory':'$(SolutionDir)VC100/',
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/express/base/base.gyp b/chromium/tools/gyp/test/msvs/express/base/base.gyp
new file mode 100644
index 00000000000..b7c9fc6d81f
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/express/base/base.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'static_library',
+ 'sources': [
+ 'a.c',
+ ],
+ },
+ {
+ 'target_name': 'b',
+ 'type': 'static_library',
+ 'sources': [
+ 'b.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/express/express.gyp b/chromium/tools/gyp/test/msvs/express/express.gyp
new file mode 100644
index 00000000000..917abe2cc0b
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/express/express.gyp
@@ -0,0 +1,19 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'express',
+ 'type': 'executable',
+ 'dependencies': [
+ 'base/base.gyp:a',
+ 'base/base.gyp:b',
+ ],
+ 'sources': [
+ 'main.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/external_builder/external.gyp b/chromium/tools/gyp/test/msvs/external_builder/external.gyp
new file mode 100644
index 00000000000..abe5b5889c3
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/external_builder/external.gyp
@@ -0,0 +1,68 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ # the test driver switches this flag when testing external builder
+ 'use_external_builder%': 0,
+ },
+ 'targets': [
+ {
+ 'target_name': 'external',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.cpp',
+ 'hello.z',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'test_rule',
+ 'extension': 'z',
+ 'outputs': [
+ 'msbuild_rule.out',
+ ],
+ 'action': [
+ 'python',
+ 'msbuild_rule.py',
+ '<(RULE_INPUT_PATH)',
+ 'a', 'b', 'c',
+ ],
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ 'actions': [
+ {
+ 'action_name': 'test action',
+ 'inputs': [
+ 'msbuild_action.py',
+ ],
+ 'outputs': [
+ 'msbuild_action.out',
+ ],
+ 'action': [
+ 'python',
+ '<@(_inputs)',
+ 'x', 'y', 'z',
+ ],
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ 'conditions': [
+ ['use_external_builder==1', {
+ 'msvs_external_builder': 'test',
+ 'msvs_external_builder_build_cmd': [
+ 'python',
+ 'external_builder.py',
+ 'build', '1', '2', '3',
+ ],
+ 'msvs_external_builder_clean_cmd': [
+ 'python',
+ 'external_builder.py',
+ 'clean', '4', '5',
+ ],
+ }],
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/list_excluded/hello_exclude.gyp b/chromium/tools/gyp/test/msvs/list_excluded/hello_exclude.gyp
new file mode 100644
index 00000000000..aa160f2367a
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/list_excluded/hello_exclude.gyp
@@ -0,0 +1,19 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.cpp',
+ 'hello_mac.cpp',
+ ],
+ 'conditions': [
+ ['OS!="mac"', {'sources!': ['hello_mac.cpp']}],
+ ]
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/missing_sources/hello_missing.gyp b/chromium/tools/gyp/test/msvs/missing_sources/hello_missing.gyp
new file mode 100644
index 00000000000..c08926bbff4
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/missing_sources/hello_missing.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello_missing.cpp',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/props/hello.gyp b/chromium/tools/gyp/test/msvs/props/hello.gyp
new file mode 100644
index 00000000000..5a58317fa7b
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/props/hello.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'product_name': '$(AppName)',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ 'msvs_props': [
+ '$(SolutionDir)AppName.vsprops'
+ ],
+ 'msbuild_props': [
+ '$(SolutionDir)AppName.props'
+ ],
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/msvs/shared_output/common.gypi b/chromium/tools/gyp/test/msvs/shared_output/common.gypi
new file mode 100644
index 00000000000..c6fa341d68c
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/shared_output/common.gypi
@@ -0,0 +1,17 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'default_configuration': 'Baz',
+ 'configurations': {
+ 'Baz': {
+ 'msvs_configuration_attributes': {
+ 'OutputDirectory': '<(DEPTH)/foo',
+ 'IntermediateDirectory': '$(OutDir)/bar',
+ },
+ },
+ },
+ },
+}
diff --git a/chromium/tools/gyp/test/msvs/shared_output/hello.gyp b/chromium/tools/gyp/test/msvs/shared_output/hello.gyp
new file mode 100644
index 00000000000..f80e5cfca1d
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/shared_output/hello.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': ['common.gypi'],
+ 'targets': [
+ {
+ 'target_name': 'pull_in_there',
+ 'type': 'none',
+ 'dependencies': ['there/there.gyp:*'],
+ },
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/shared_output/there/there.gyp b/chromium/tools/gyp/test/msvs/shared_output/there/there.gyp
new file mode 100644
index 00000000000..56feff326ce
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/shared_output/there/there.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': ['../common.gypi'],
+ 'targets': [
+ {
+ 'target_name': 'there',
+ 'type': 'executable',
+ 'sources': [
+ 'there.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/msvs/uldi2010/hello.gyp b/chromium/tools/gyp/test/msvs/uldi2010/hello.gyp
new file mode 100644
index 00000000000..a2bf2badb18
--- /dev/null
+++ b/chromium/tools/gyp/test/msvs/uldi2010/hello.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ 'dependencies': [
+ 'hellolib',
+ ]
+ },
+ {
+ 'target_name': 'hellolib',
+ 'type': 'static_library',
+ 'sources': [
+ 'hello2.c',
+ ],
+ 'msvs_2010_disable_uldi_when_referenced': 1,
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/multiple-targets/src/multiple.gyp b/chromium/tools/gyp/test/multiple-targets/src/multiple.gyp
new file mode 100644
index 00000000000..3db4ea30cd0
--- /dev/null
+++ b/chromium/tools/gyp/test/multiple-targets/src/multiple.gyp
@@ -0,0 +1,24 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'prog1',
+ 'type': 'executable',
+ 'sources': [
+ 'prog1.c',
+ 'common.c',
+ ],
+ },
+ {
+ 'target_name': 'prog2',
+ 'type': 'executable',
+ 'sources': [
+ 'prog2.c',
+ 'common.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp b/chromium/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp
new file mode 100644
index 00000000000..5baa7a7d47e
--- /dev/null
+++ b/chromium/tools/gyp/test/ninja/action_dependencies/src/action_dependencies.gyp
@@ -0,0 +1,88 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'static_library',
+ 'sources': [
+ 'a.c',
+ 'a.h',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate_headers',
+ 'inputs': [
+ 'emit.py'
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/a/generated.h'
+ ],
+ 'action': [
+ 'python',
+ 'emit.py',
+ '<(SHARED_INTERMEDIATE_DIR)/a/generated.h',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ },
+ },
+ {
+ 'target_name': 'b',
+ 'type': 'executable',
+ 'sources': [
+ 'b.c',
+ 'b.h',
+ ],
+ 'dependencies': [
+ 'a',
+ ],
+ },
+ {
+ 'target_name': 'c',
+ 'type': 'static_library',
+ 'sources': [
+ 'c.c',
+ 'c.h',
+ ],
+ 'dependencies': [
+ 'b',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate_headers',
+ 'inputs': [
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/c/generated.h'
+ ],
+ 'action': [
+ '<(PRODUCT_DIR)/b',
+ '<(SHARED_INTERMEDIATE_DIR)/c/generated.h',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/ninja/chained-dependency/chained-dependency.gyp b/chromium/tools/gyp/test/ninja/chained-dependency/chained-dependency.gyp
new file mode 100644
index 00000000000..3fe68ae85a7
--- /dev/null
+++ b/chromium/tools/gyp/test/ninja/chained-dependency/chained-dependency.gyp
@@ -0,0 +1,53 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # This first target generates a header.
+ {
+ 'target_name': 'generate_header',
+ 'type': 'none',
+ 'msvs_cygwin_shell': '0',
+ 'actions': [
+ {
+ 'action_name': 'generate header',
+ 'inputs': [],
+ 'outputs': ['<(SHARED_INTERMEDIATE_DIR)/generated/header.h'],
+ 'action': [
+ 'python', '-c', 'open(<(_outputs), "w")'
+ ]
+ },
+ ],
+ 'all_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ },
+ },
+
+ # This intermediate target does nothing other than pull in a
+ # dependency on the above generated target.
+ {
+ 'target_name': 'chain',
+ 'type': 'none',
+ 'dependencies': [
+ 'generate_header',
+ ],
+ },
+
+ # This final target is:
+ # - a static library (so gyp doesn't transitively pull in dependencies);
+ # - that relies on the generated file two dependencies away.
+ {
+ 'target_name': 'chained',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'chain',
+ ],
+ 'sources': [
+ 'chained.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/ninja/normalize-paths-win/normalize-paths.gyp b/chromium/tools/gyp/test/ninja/normalize-paths-win/normalize-paths.gyp
new file mode 100644
index 00000000000..ba0ee28157b
--- /dev/null
+++ b/chromium/tools/gyp/test/ninja/normalize-paths-win/normalize-paths.gyp
@@ -0,0 +1,56 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'Some_Target',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '<(PRODUCT_DIR)/stuff/AnotherName.exe',
+ },
+ },
+ 'sources': [
+ 'HeLLo.cc',
+ 'blOrP.idl',
+ ],
+ },
+ {
+ 'target_name': 'second',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(OutDir)\\things\\AnotherName.exe',
+ },
+ },
+ 'sources': [
+ 'HeLLo.cc',
+ ],
+ },
+ {
+ 'target_name': 'action',
+ 'type': 'none',
+ 'msvs_cygwin_shell': '0',
+ 'actions': [
+ {
+ 'inputs': [
+ '$(IntDir)\\SomeInput',
+ '$(OutDir)\\SomeOtherInput',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/ReSuLt',
+ '<(SHARED_INTERMEDIATE_DIR)/TempFile',
+ '$(OutDir)\SomethingElse',
+ ],
+ 'action_name': 'Test action',
+ # Unfortunately, we can't normalize this field because it's
+ # free-form. Fortunately, ninja doesn't inspect it at all (only the
+ # inputs and outputs) so it's not mandatory.
+ 'action': [],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/ninja/s-needs-no-depfiles/s-needs-no-depfiles.gyp b/chromium/tools/gyp/test/ninja/s-needs-no-depfiles/s-needs-no-depfiles.gyp
new file mode 100644
index 00000000000..bd66b1a70a8
--- /dev/null
+++ b/chromium/tools/gyp/test/ninja/s-needs-no-depfiles/s-needs-no-depfiles.gyp
@@ -0,0 +1,13 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'empty',
+ 'type': 'shared_library',
+ 'sources': [ 'empty.s' ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/ninja/solibs_avoid_relinking/solibs_avoid_relinking.gyp b/chromium/tools/gyp/test/ninja/solibs_avoid_relinking/solibs_avoid_relinking.gyp
new file mode 100644
index 00000000000..e816351d684
--- /dev/null
+++ b/chromium/tools/gyp/test/ninja/solibs_avoid_relinking/solibs_avoid_relinking.gyp
@@ -0,0 +1,38 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'shared_library',
+ 'sources': [ 'solib.cc' ],
+ # Incremental linking enabled so that .lib timestamp is maintained when
+ # exports are unchanged.
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '2',
+ }
+ },
+ },
+ {
+ 'target_name': 'b',
+ 'type': 'executable',
+ 'sources': [ 'main.cc' ],
+ 'dependencies': [ 'a' ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '2',
+ }
+ },
+ },
+ ],
+ 'conditions': [
+ ['OS=="linux"', {
+ 'target_defaults': {
+ 'cflags': ['-fPIC'],
+ },
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.gyp b/chromium/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.gyp
new file mode 100644
index 00000000000..dbc95a9439c
--- /dev/null
+++ b/chromium/tools/gyp/test/ninja/use-custom-environment-files/use-custom-environment-files.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_use_custom_environment_files',
+ 'type': 'executable',
+ 'sources': [
+ 'use-custom-environment-files.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/no-output/src/nooutput.gyp b/chromium/tools/gyp/test/no-output/src/nooutput.gyp
new file mode 100644
index 00000000000..c40124efc1e
--- /dev/null
+++ b/chromium/tools/gyp/test/no-output/src/nooutput.gyp
@@ -0,0 +1,17 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'no_output',
+ 'type': 'none',
+ 'direct_dependent_settings': {
+ 'defines': [
+ 'NADA',
+ ],
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/product/product.gyp b/chromium/tools/gyp/test/product/product.gyp
new file mode 100644
index 00000000000..c25eaaacb51
--- /dev/null
+++ b/chromium/tools/gyp/test/product/product.gyp
@@ -0,0 +1,128 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello1',
+ 'product_name': 'alt1',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello2',
+ 'product_extension': 'stuff',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello3',
+ 'product_name': 'alt3',
+ 'product_extension': 'stuff',
+ 'product_prefix': 'yo',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+
+ {
+ 'target_name': 'hello4',
+ 'product_name': 'alt4',
+ 'type': 'shared_library',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello5',
+ 'product_extension': 'stuff',
+ 'type': 'shared_library',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello6',
+ 'product_name': 'alt6',
+ 'product_extension': 'stuff',
+ 'product_prefix': 'yo',
+ 'type': 'shared_library',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+
+ {
+ 'target_name': 'hello7',
+ 'product_name': 'alt7',
+ 'type': 'static_library',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello8',
+ 'product_extension': 'stuff',
+ 'type': 'static_library',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello9',
+ 'product_name': 'alt9',
+ 'product_extension': 'stuff',
+ 'product_prefix': 'yo',
+ 'type': 'static_library',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello10',
+ 'product_name': 'alt10',
+ 'product_extension': 'stuff',
+ 'product_prefix': 'yo',
+ 'product_dir': '<(PRODUCT_DIR)/bob',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello11',
+ 'product_name': 'alt11',
+ 'product_extension': 'stuff',
+ 'product_prefix': 'yo',
+ 'product_dir': '<(PRODUCT_DIR)/bob',
+ 'type': 'shared_library',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ {
+ 'target_name': 'hello12',
+ 'product_name': 'alt12',
+ 'product_extension': 'stuff',
+ 'product_prefix': 'yo',
+ 'product_dir': '<(PRODUCT_DIR)/bob',
+ 'type': 'static_library',
+ 'sources': [
+ 'hello.c',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="linux"', {
+ 'target_defaults': {
+ 'cflags': ['-fPIC'],
+ },
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/relative/foo/a/a.gyp b/chromium/tools/gyp/test/relative/foo/a/a.gyp
new file mode 100644
index 00000000000..66316ac681f
--- /dev/null
+++ b/chromium/tools/gyp/test/relative/foo/a/a.gyp
@@ -0,0 +1,13 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'executable',
+ 'sources': ['a.cc'],
+ 'dependencies': [
+ '../../foo/b/b.gyp:b',
+ 'c/c.gyp:c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/relative/foo/a/c/c.gyp b/chromium/tools/gyp/test/relative/foo/a/c/c.gyp
new file mode 100644
index 00000000000..c1f087db993
--- /dev/null
+++ b/chromium/tools/gyp/test/relative/foo/a/c/c.gyp
@@ -0,0 +1,12 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'c',
+ 'type': 'static_library',
+ 'sources': ['c.cc'],
+ 'dependencies': [
+ '../../b/b.gyp:b',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/relative/foo/b/b.gyp b/chromium/tools/gyp/test/relative/foo/b/b.gyp
new file mode 100644
index 00000000000..0ebe4533d3f
--- /dev/null
+++ b/chromium/tools/gyp/test/relative/foo/b/b.gyp
@@ -0,0 +1,9 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'b',
+ 'type': 'static_library',
+ 'sources': ['b.cc'],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rename/filecase/test-casesensitive.gyp b/chromium/tools/gyp/test/rename/filecase/test-casesensitive.gyp
new file mode 100644
index 00000000000..48eaa6eb679
--- /dev/null
+++ b/chromium/tools/gyp/test/rename/filecase/test-casesensitive.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'filecaserename_sensitive',
+ 'type': 'executable',
+ 'sources': [
+ 'FiLe.c',
+ 'fIlE.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rename/filecase/test.gyp b/chromium/tools/gyp/test/rename/filecase/test.gyp
new file mode 100644
index 00000000000..eaee9337b6c
--- /dev/null
+++ b/chromium/tools/gyp/test/rename/filecase/test.gyp
@@ -0,0 +1,14 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'filecaserename',
+ 'type': 'executable',
+ 'sources': [
+ 'file.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/restat/src/restat.gyp b/chromium/tools/gyp/test/restat/src/restat.gyp
new file mode 100644
index 00000000000..ff020e0ce66
--- /dev/null
+++ b/chromium/tools/gyp/test/restat/src/restat.gyp
@@ -0,0 +1,50 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'create_intermediate',
+ 'type': 'none',
+ 'msvs_cygwin_shell': '0',
+ 'actions': [
+ {
+ 'action_name': 'create_intermediate',
+ 'inputs': [
+ 'create_intermediate.py',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/intermediate',
+ 'ALWAYS.run.ALWAYS',
+ ],
+ 'action': [
+ 'python', 'create_intermediate.py', '<(PRODUCT_DIR)/intermediate',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'dependent',
+ 'type': 'none',
+ 'msvs_cygwin_shell': '0',
+ 'dependencies': [
+ 'create_intermediate',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'dependent',
+ 'inputs': [
+ '<(PRODUCT_DIR)/intermediate',
+ ],
+ 'outputs': [
+ '<(PRODUCT_DIR)/dependent'
+ ],
+ 'action': [
+ 'python', 'touch.py', '<(PRODUCT_DIR)/dependent', '<(PRODUCT_DIR)/side_effect',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules-dirname/src/actions.gyp b/chromium/tools/gyp/test/rules-dirname/src/actions.gyp
new file mode 100644
index 00000000000..c5693c6c9e1
--- /dev/null
+++ b/chromium/tools/gyp/test/rules-dirname/src/actions.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'pull_in_all_actions',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir/input-rule-dirname.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules-dirname/src/subdir/input-rule-dirname.gyp b/chromium/tools/gyp/test/rules-dirname/src/subdir/input-rule-dirname.gyp
new file mode 100644
index 00000000000..6f41d4f489b
--- /dev/null
+++ b/chromium/tools/gyp/test/rules-dirname/src/subdir/input-rule-dirname.gyp
@@ -0,0 +1,92 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'print_rule_input_path',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'foo/bar/baz.printvars',
+ 'a/b/c.printvars',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'printvars',
+ 'extension': 'printvars',
+ 'inputs': [
+ 'printvars.py',
+ ],
+ 'outputs': [
+ '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).printed',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(RULE_INPUT_DIRNAME)', '<@(_outputs)',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'gencc_int_output',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'],
+ 'sources': [
+ 'foo/bar/baz.gencc',
+ 'a/b/c.gencc',
+ 'main.cc',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'dependencies': [
+ 'cygwin',
+ ],
+ }],
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'gencc',
+ 'extension': 'gencc',
+ 'msvs_external_rule': 1,
+ 'inputs': [
+ '<(DEPTH)/copy-file.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT).cc',
+ ],
+ 'action': [
+ 'python', '<@(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'targets': [
+ {
+ 'target_name': 'cygwin',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'setup_mount',
+ 'msvs_cygwin_shell': 0,
+ 'inputs': [
+ '../../../../../../<(DEPTH)/third_party/cygwin/setup_mount.bat',
+ ],
+ # Visual Studio requires an output file, or else the
+ # custom build step won't run.
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/_always_run_setup_mount.marker',
+ ],
+ 'action': ['<@(_inputs)'],
+ },
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules-rebuild/src/same_target.gyp b/chromium/tools/gyp/test/rules-rebuild/src/same_target.gyp
new file mode 100644
index 00000000000..22ba56056d2
--- /dev/null
+++ b/chromium/tools/gyp/test/rules-rebuild/src/same_target.gyp
@@ -0,0 +1,31 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'main.c',
+ 'prog1.in',
+ 'prog2.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'make_sources',
+ 'extension': 'in',
+ 'inputs': [
+ 'make-sources.py',
+ ],
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c',
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).h',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_NAME)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules-use-built-dependencies/src/use-built-dependencies-rule.gyp b/chromium/tools/gyp/test/rules-use-built-dependencies/src/use-built-dependencies-rule.gyp
new file mode 100644
index 00000000000..92bfeda3928
--- /dev/null
+++ b/chromium/tools/gyp/test/rules-use-built-dependencies/src/use-built-dependencies-rule.gyp
@@ -0,0 +1,42 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'main',
+ 'toolsets': ['host'],
+ 'type': 'executable',
+ 'sources': [
+ 'main.cc',
+ ],
+ },
+ {
+ 'target_name': 'post',
+ 'toolsets': ['host'],
+ 'type': 'none',
+ 'dependencies': [
+ 'main',
+ ],
+ 'sources': [
+ # As this test is written it could easily be made into an action.
+ # An acutal use case would have a number of these 'sources'.
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)main<(EXECUTABLE_SUFFIX)',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'generate_output',
+ 'extension': '<(EXECUTABLE_SUFFIX)',
+ 'outputs': [ '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT)_output', ],
+ 'msvs_cygwin_shell': 0,
+ 'action': [
+ '<(RULE_INPUT_PATH)',
+ '<(RULE_INPUT_DIRNAME)/<(RULE_INPUT_ROOT)_output',
+ ],
+ 'message': 'Generating output for <(RULE_INPUT_ROOT)'
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules-variables/src/variables.gyp b/chromium/tools/gyp/test/rules-variables/src/variables.gyp
new file mode 100644
index 00000000000..6debba12e34
--- /dev/null
+++ b/chromium/tools/gyp/test/rules-variables/src/variables.gyp
@@ -0,0 +1,40 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ # This test shouldn't ever actually need to execute its rules: there's no
+ # command line that generates any output anyway. However, there's something
+ # slightly broken in either ninja or (maybe more likely?) on the win32 VM
+ # gypbots that breaks dependency checking and causes this rule to want to
+ # run. When it does run, the cygwin path is wrong, so the do-nothing step
+ # fails.
+ # TODO: Investigate and fix whatever's actually failing and remove this.
+ 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'],
+ },
+ 'targets': [
+ {
+ 'target_name': 'all_rule_variables',
+ 'type': 'executable',
+ 'sources': [
+ 'subdir/test.c',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'rule_variable',
+ 'extension': 'c',
+ 'outputs': [
+ '<(RULE_INPUT_ROOT).input_root.c',
+ '<(RULE_INPUT_DIRNAME)/input_dirname.c',
+ 'input_path/<(RULE_INPUT_PATH)',
+ 'input_ext<(RULE_INPUT_EXT)',
+ 'input_name/<(RULE_INPUT_NAME)',
+ ],
+ 'action': [],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/actions.gyp b/chromium/tools/gyp/test/rules/src/actions.gyp
new file mode 100644
index 00000000000..5c0a40b0ce9
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/actions.gyp
@@ -0,0 +1,22 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'pull_in_all_actions',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir1/executable.gyp:*',
+ 'subdir2/never_used.gyp:*',
+ 'subdir2/no_inputs.gyp:*',
+ 'subdir2/no_action.gyp:*',
+ 'subdir2/none.gyp:*',
+ 'subdir3/executable2.gyp:*',
+ 'subdir4/build-asm.gyp:*',
+ 'external/external.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/external/external.gyp b/chromium/tools/gyp/test/rules/src/external/external.gyp
new file mode 100644
index 00000000000..b28174f57c3
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/external/external.gyp
@@ -0,0 +1,66 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Test that the case where there are no inputs (other than the
+# file the rule applies to).
+{
+ 'target_defaults': {
+ 'msvs_cygwin_dirs': ['../../../../../../<(DEPTH)/third_party/cygwin'],
+ },
+ 'targets': [
+ {
+ 'target_name': 'external_rules',
+ 'type': 'none',
+ 'sources': [
+ 'file1.in',
+ 'file2.in',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'dependencies': [
+ 'cygwin',
+ ],
+ }],
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file',
+ 'extension': 'in',
+ 'msvs_external_rule': 1,
+ 'outputs': [
+ '<(RULE_INPUT_ROOT).external_rules.out',
+ ],
+ 'action': [
+ 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ },
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'targets': [
+ {
+ 'target_name': 'cygwin',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'setup_mount',
+ 'msvs_cygwin_shell': 0,
+ 'inputs': [
+ '../../../../../../<(DEPTH)/third_party/cygwin/setup_mount.bat',
+ ],
+ # Visual Studio requires an output file, or else the
+ # custom build step won't run.
+ 'outputs': [
+ '<(INTERMEDIATE_DIR)/_always_run_setup_mount.marker',
+ ],
+ 'action': ['<@(_inputs)'],
+ },
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/input-root.gyp b/chromium/tools/gyp/test/rules/src/input-root.gyp
new file mode 100644
index 00000000000..b6600e767c8
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/input-root.gyp
@@ -0,0 +1,24 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test',
+ 'type': 'executable',
+ 'sources': [ 'somefile.ext', ],
+ 'rules': [{
+ 'rule_name': 'rule',
+ 'extension': 'ext',
+ 'inputs': [ 'rule.py', ],
+ 'outputs': [ '<(RULE_INPUT_ROOT).cc', ],
+ 'action': [ 'python', 'rule.py', '<(RULE_INPUT_ROOT)', ],
+ 'message': 'Processing <(RULE_INPUT_PATH)',
+ 'process_outputs_as_sources': 1,
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ }],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/noaction/no_action_with_rules_fails.gyp b/chromium/tools/gyp/test/rules/src/noaction/no_action_with_rules_fails.gyp
new file mode 100644
index 00000000000..9b6a65629f3
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/noaction/no_action_with_rules_fails.gyp
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Test the case where there's no action but there are input rules that should
+# be processed results in a gyp failure.
+{
+ 'targets': [
+ {
+ 'target_name': 'extension_does_match_sources_but_no_action',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'file1.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'assembled',
+ 'extension': 'in',
+ 'outputs': [
+ '<(RULE_INPUT_ROOT).in',
+ ],
+ 'conditions': [
+ # Always fails.
+ [ '"true"=="false"', {
+ 'action': [
+ 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'message': 'test_rule',
+ }],
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/special-variables.gyp b/chromium/tools/gyp/test/rules/src/special-variables.gyp
new file mode 100644
index 00000000000..fc55665e75b
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/special-variables.gyp
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'rules': [
+ {
+ 'rule_name': 'assembler (gnu-compatible)',
+ 'msvs_cygwin_shell': 0,
+ 'msvs_quote_cmd': 0,
+ 'extension': 'S',
+ 'inputs': [
+ 'as.bat',
+ '$(InputPath)'
+ ],
+ 'outputs': [
+ '$(IntDir)/$(InputName).obj',
+ ],
+ 'action': [
+ 'as.bat',
+ '$(InputPath)',
+ '$(IntDir)/$(InputName).obj',
+ ],
+ 'message': 'Building assembly language file $(InputPath)',
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ 'target_name': 'test',
+ 'type': 'static_library',
+ 'sources': [ 'an_asm.S' ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/subdir1/executable.gyp b/chromium/tools/gyp/test/rules/src/subdir1/executable.gyp
new file mode 100644
index 00000000000..c34cce5a92e
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/subdir1/executable.gyp
@@ -0,0 +1,37 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'program.c',
+ 'function1.in',
+ 'function2.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file',
+ 'extension': 'in',
+ 'inputs': [
+ '../copy-file.py',
+ ],
+ 'outputs': [
+ # TODO: fix Make to support generated files not
+ # in a variable-named path like <(INTERMEDIATE_DIR)
+ #'<(RULE_INPUT_ROOT).c',
+ '<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).c',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/subdir2/never_used.gyp b/chromium/tools/gyp/test/rules/src/subdir2/never_used.gyp
new file mode 100644
index 00000000000..17f6f553710
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/subdir2/never_used.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Test that the case where there is a rule that doesn't apply to anything.
+{
+ 'targets': [
+ {
+ 'target_name': 'files_no_input2',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'file1.in',
+ 'file2.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file3',
+ 'extension': 'in2',
+ 'outputs': [
+ '<(RULE_INPUT_ROOT).out3',
+ ],
+ 'action': [
+ 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/subdir2/no_action.gyp b/chromium/tools/gyp/test/rules/src/subdir2/no_action.gyp
new file mode 100644
index 00000000000..ffa1cefe182
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/subdir2/no_action.gyp
@@ -0,0 +1,38 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Test that the case where an action is only specified under a conditional is
+# evaluated appropriately.
+{
+ 'targets': [
+ {
+ 'target_name': 'extension_does_not_match_sources_and_no_action',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'file1.in',
+ 'file2.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'assemble',
+ 'extension': 'asm',
+ 'outputs': [
+ '<(RULE_INPUT_ROOT).fail',
+ ],
+ 'conditions': [
+ # Always fails.
+ [ '"true"=="false"', {
+ 'action': [
+ 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'message': 'test_rule',
+ }],
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/subdir2/no_inputs.gyp b/chromium/tools/gyp/test/rules/src/subdir2/no_inputs.gyp
new file mode 100644
index 00000000000..e61a1a3ff67
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/subdir2/no_inputs.gyp
@@ -0,0 +1,32 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Test that the case where there are no inputs (other than the
+# file the rule applies to).
+{
+ 'targets': [
+ {
+ 'target_name': 'files_no_input',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'file1.in',
+ 'file2.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file2',
+ 'extension': 'in',
+ 'outputs': [
+ '<(RULE_INPUT_ROOT).out2',
+ ],
+ 'action': [
+ 'python', '../copy-file.py', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/subdir2/none.gyp b/chromium/tools/gyp/test/rules/src/subdir2/none.gyp
new file mode 100644
index 00000000000..38bcdabdf66
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/subdir2/none.gyp
@@ -0,0 +1,33 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'files',
+ 'type': 'none',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'file1.in',
+ 'file2.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file',
+ 'extension': 'in',
+ 'inputs': [
+ '../copy-file.py',
+ ],
+ 'outputs': [
+ '<(RULE_INPUT_ROOT).out',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/subdir3/executable2.gyp b/chromium/tools/gyp/test/rules/src/subdir3/executable2.gyp
new file mode 100644
index 00000000000..a2a528fc7be
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/subdir3/executable2.gyp
@@ -0,0 +1,37 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This one tests that rules are properly written if extensions are different
+# between the target's sources (program.c) and the generated files
+# (function3.cc)
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program2',
+ 'type': 'executable',
+ 'msvs_cygwin_shell': 0,
+ 'sources': [
+ 'program.c',
+ 'function3.in',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'copy_file',
+ 'extension': 'in',
+ 'inputs': [
+ '../copy-file.py',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).cc',
+ ],
+ 'action': [
+ 'python', '<(_inputs)', '<(RULE_INPUT_PATH)', '<@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/rules/src/subdir4/build-asm.gyp b/chromium/tools/gyp/test/rules/src/subdir4/build-asm.gyp
new file mode 100644
index 00000000000..6b9505b79a2
--- /dev/null
+++ b/chromium/tools/gyp/test/rules/src/subdir4/build-asm.gyp
@@ -0,0 +1,49 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This one tests that assembly files ended as .s and .S are compiled.
+
+{
+ 'target_defaults': {
+ 'conditions': [
+ ['OS=="win"', {
+ 'defines': ['PLATFORM_WIN'],
+ }],
+ ['OS=="mac"', {
+ 'defines': ['PLATFORM_MAC'],
+ }],
+ ['OS=="linux"', {
+ 'defines': ['PLATFORM_LINUX'],
+ }],
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'program4',
+ 'type': 'executable',
+ 'sources': [
+ 'asm-function.assem',
+ 'program.c',
+ ],
+ 'conditions': [
+ ['OS=="linux" or OS=="mac"', {
+ 'rules': [
+ {
+ 'rule_name': 'convert_assem',
+ 'extension': 'assem',
+ 'inputs': [],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).S',
+ ],
+ 'action': [
+ 'bash', '-c', 'mv <(RULE_INPUT_PATH) <@(_outputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ }],
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-gyp-name/library/one/sub.gyp b/chromium/tools/gyp/test/same-gyp-name/library/one/sub.gyp
new file mode 100644
index 00000000000..1bed941e547
--- /dev/null
+++ b/chromium/tools/gyp/test/same-gyp-name/library/one/sub.gyp
@@ -0,0 +1,11 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'one',
+ 'type': 'static_library',
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-gyp-name/library/test.gyp b/chromium/tools/gyp/test/same-gyp-name/library/test.gyp
new file mode 100644
index 00000000000..552a77ed7ee
--- /dev/null
+++ b/chromium/tools/gyp/test/same-gyp-name/library/test.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'duplicate_names',
+ 'type': 'shared_library',
+ 'dependencies': [
+ 'one/sub.gyp:one',
+ 'two/sub.gyp:two',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-gyp-name/library/two/sub.gyp b/chromium/tools/gyp/test/same-gyp-name/library/two/sub.gyp
new file mode 100644
index 00000000000..934c98a496e
--- /dev/null
+++ b/chromium/tools/gyp/test/same-gyp-name/library/two/sub.gyp
@@ -0,0 +1,11 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'two',
+ 'type': 'static_library',
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-gyp-name/src/all.gyp b/chromium/tools/gyp/test/same-gyp-name/src/all.gyp
new file mode 100644
index 00000000000..229f02ea845
--- /dev/null
+++ b/chromium/tools/gyp/test/same-gyp-name/src/all.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'all_exes',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir1/executable.gyp:*',
+ 'subdir2/executable.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp b/chromium/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp
new file mode 100644
index 00000000000..82483b4c696
--- /dev/null
+++ b/chromium/tools/gyp/test/same-gyp-name/src/subdir1/executable.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program1',
+ 'type': 'executable',
+ 'sources': [
+ 'main1.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp b/chromium/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp
new file mode 100644
index 00000000000..e3537013eb1
--- /dev/null
+++ b/chromium/tools/gyp/test/same-gyp-name/src/subdir2/executable.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program2',
+ 'type': 'executable',
+ 'sources': [
+ 'main2.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-rule-output-file-name/src/subdir1/subdir1.gyp b/chromium/tools/gyp/test/same-rule-output-file-name/src/subdir1/subdir1.gyp
new file mode 100644
index 00000000000..bff381a5a51
--- /dev/null
+++ b/chromium/tools/gyp/test/same-rule-output-file-name/src/subdir1/subdir1.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'target1',
+ 'type': 'none',
+ 'sources': [
+ '../touch.py'
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'rule1',
+ 'extension': 'py',
+ 'inputs': [],
+ 'outputs': [
+ 'rule.txt',
+ ],
+ 'action': [
+ 'python', '../touch.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-rule-output-file-name/src/subdir2/subdir2.gyp b/chromium/tools/gyp/test/same-rule-output-file-name/src/subdir2/subdir2.gyp
new file mode 100644
index 00000000000..12a35600a31
--- /dev/null
+++ b/chromium/tools/gyp/test/same-rule-output-file-name/src/subdir2/subdir2.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'target2',
+ 'type': 'none',
+ 'sources': [
+ '../touch.py'
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'rule2',
+ 'extension': 'py',
+ 'inputs': [],
+ 'outputs': [
+ 'rule.txt',
+ ],
+ 'action': [
+ 'python', '../touch.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-rule-output-file-name/src/subdirs.gyp b/chromium/tools/gyp/test/same-rule-output-file-name/src/subdirs.gyp
new file mode 100644
index 00000000000..25259a38f4e
--- /dev/null
+++ b/chromium/tools/gyp/test/same-rule-output-file-name/src/subdirs.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'subdirs',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir1/subdir1.gyp:*',
+ 'subdir2/subdir2.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-source-file-name/src/all.gyp b/chromium/tools/gyp/test/same-source-file-name/src/all.gyp
new file mode 100644
index 00000000000..4fe052c6687
--- /dev/null
+++ b/chromium/tools/gyp/test/same-source-file-name/src/all.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'prog1',
+ 'type': 'executable',
+ 'defines': [
+ 'PROG="prog1"',
+ ],
+ 'sources': [
+ 'prog1.c',
+ 'func.c',
+ ],
+ },
+ {
+ 'target_name': 'prog2',
+ 'type': 'executable',
+ 'defines': [
+ 'PROG="prog2"',
+ ],
+ 'sources': [
+ 'prog2.c',
+ 'func.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-source-file-name/src/double-executable.gyp b/chromium/tools/gyp/test/same-source-file-name/src/double-executable.gyp
new file mode 100644
index 00000000000..477bd87e0d8
--- /dev/null
+++ b/chromium/tools/gyp/test/same-source-file-name/src/double-executable.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'prog3',
+ 'type': 'executable',
+ 'sources': [
+ 'prog3.c',
+ 'func.c',
+ 'subdir1/func.c',
+ 'subdir2/func.c',
+ ],
+ 'defines': [
+ 'PROG="prog3"',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-source-file-name/src/double-shared.gyp b/chromium/tools/gyp/test/same-source-file-name/src/double-shared.gyp
new file mode 100644
index 00000000000..40d995f5dec
--- /dev/null
+++ b/chromium/tools/gyp/test/same-source-file-name/src/double-shared.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'lib',
+ 'type': 'shared_library',
+ 'sources': [
+ 'prog2.c',
+ 'func.c',
+ 'subdir1/func.c',
+ 'subdir2/func.c',
+ ],
+ 'defines': [
+ 'PROG="prog2"',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-source-file-name/src/double-static.gyp b/chromium/tools/gyp/test/same-source-file-name/src/double-static.gyp
new file mode 100644
index 00000000000..3da1242381a
--- /dev/null
+++ b/chromium/tools/gyp/test/same-source-file-name/src/double-static.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'lib',
+ 'type': 'static_library',
+ 'sources': [
+ 'prog1.c',
+ 'func.c',
+ 'subdir1/func.c',
+ 'subdir2/func.c',
+ ],
+ 'defines': [
+ 'PROG="prog1"',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-target-name-different-directory/src/subdir1/subdir1.gyp b/chromium/tools/gyp/test/same-target-name-different-directory/src/subdir1/subdir1.gyp
new file mode 100644
index 00000000000..d4ec2e679ac
--- /dev/null
+++ b/chromium/tools/gyp/test/same-target-name-different-directory/src/subdir1/subdir1.gyp
@@ -0,0 +1,66 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'target',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'action1',
+ 'inputs': [],
+ 'outputs': [
+ 'action1.txt',
+ ],
+ 'action': [
+ 'python', '../touch.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'target_same_action_name',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'action',
+ 'inputs': [],
+ 'outputs': [
+ 'action.txt',
+ ],
+ 'action': [
+ 'python', '../touch.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'target_same_rule_name',
+ 'type': 'none',
+ 'sources': [
+ '../touch.py'
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'rule',
+ 'extension': 'py',
+ 'inputs': [],
+ 'outputs': [
+ 'rule.txt',
+ ],
+ 'action': [
+ 'python', '../touch.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-target-name-different-directory/src/subdir2/subdir2.gyp b/chromium/tools/gyp/test/same-target-name-different-directory/src/subdir2/subdir2.gyp
new file mode 100644
index 00000000000..9006d450b26
--- /dev/null
+++ b/chromium/tools/gyp/test/same-target-name-different-directory/src/subdir2/subdir2.gyp
@@ -0,0 +1,66 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'target',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'action2',
+ 'inputs': [],
+ 'outputs': [
+ 'action2.txt',
+ ],
+ 'action': [
+ 'python', '../touch.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'target_same_action_name',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'action',
+ 'inputs': [],
+ 'outputs': [
+ 'action.txt',
+ ],
+ 'action': [
+ 'python', '../touch.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ {
+ 'target_name': 'target_same_rule_name',
+ 'type': 'none',
+ 'sources': [
+ '../touch.py'
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'rule',
+ 'extension': 'py',
+ 'inputs': [],
+ 'outputs': [
+ 'rule.txt',
+ ],
+ 'action': [
+ 'python', '../touch.py', '<(_outputs)',
+ ],
+ # Allows the test to run without hermetic cygwin on windows.
+ 'msvs_cygwin_shell': 0,
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-target-name-different-directory/src/subdirs.gyp b/chromium/tools/gyp/test/same-target-name-different-directory/src/subdirs.gyp
new file mode 100644
index 00000000000..65413e73b2b
--- /dev/null
+++ b/chromium/tools/gyp/test/same-target-name-different-directory/src/subdirs.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'subdirs',
+ 'type': 'none',
+ 'dependencies': [
+ 'subdir1/subdir1.gyp:*',
+ 'subdir2/subdir2.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-target-name/src/all.gyp b/chromium/tools/gyp/test/same-target-name/src/all.gyp
new file mode 100644
index 00000000000..ac16976da6a
--- /dev/null
+++ b/chromium/tools/gyp/test/same-target-name/src/all.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'all_exes',
+ 'type': 'none',
+ 'dependencies': [
+ 'executable1.gyp:*',
+ 'executable2.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-target-name/src/executable1.gyp b/chromium/tools/gyp/test/same-target-name/src/executable1.gyp
new file mode 100644
index 00000000000..3c492c1b375
--- /dev/null
+++ b/chromium/tools/gyp/test/same-target-name/src/executable1.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'sources': [
+ 'main1.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/same-target-name/src/executable2.gyp b/chromium/tools/gyp/test/same-target-name/src/executable2.gyp
new file mode 100644
index 00000000000..41e84a61c67
--- /dev/null
+++ b/chromium/tools/gyp/test/same-target-name/src/executable2.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'sources': [
+ 'main2.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/sanitize-rule-names/sanitize-rule-names.gyp b/chromium/tools/gyp/test/sanitize-rule-names/sanitize-rule-names.gyp
new file mode 100644
index 00000000000..184253e966d
--- /dev/null
+++ b/chromium/tools/gyp/test/sanitize-rule-names/sanitize-rule-names.gyp
@@ -0,0 +1,27 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 's_test',
+ 'type': 'executable',
+ 'rules': [
+ {
+ # Make sure this rule name doesn't cause an invalid ninja file.
+ 'rule_name': 'rule name with odd characters ()/',
+ 'extension': 'S',
+ 'outputs': ['outfile'],
+ 'msvs_cygwin_shell': 0,
+ 'msvs_quote_cmd': 0,
+ 'action': ['python', 'script.py', '<(RULE_INPUT_PATH)', 'outfile'],
+ },
+ ],
+ 'sources': [
+ 'blah.S',
+ 'hello.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/self-dependency/common.gypi b/chromium/tools/gyp/test/self-dependency/common.gypi
new file mode 100644
index 00000000000..aae221a5dd0
--- /dev/null
+++ b/chromium/tools/gyp/test/self-dependency/common.gypi
@@ -0,0 +1,13 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# A common file that other .gyp files include.
+# Makes every target in the project depend on dep.gyp:dep.
+{
+ 'target_defaults': {
+ 'dependencies': [
+ 'dep.gyp:dep',
+ ],
+ },
+}
diff --git a/chromium/tools/gyp/test/self-dependency/dep.gyp b/chromium/tools/gyp/test/self-dependency/dep.gyp
new file mode 100644
index 00000000000..2b6c9dda854
--- /dev/null
+++ b/chromium/tools/gyp/test/self-dependency/dep.gyp
@@ -0,0 +1,23 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# dep.gyp contains a target dep, on which all the targets in the project
+# depend. This means there's a self-dependency of dep on itself, which is
+# pruned by setting prune_self_dependency to 1.
+
+{
+ 'includes': [
+ 'common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'dep',
+ 'type': 'none',
+ 'variables': {
+ # Without this GYP will report a cycle in dependency graph.
+ 'prune_self_dependency': 1,
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/self-dependency/self_dependency.gyp b/chromium/tools/gyp/test/self-dependency/self_dependency.gyp
new file mode 100644
index 00000000000..0ca76c669b6
--- /dev/null
+++ b/chromium/tools/gyp/test/self-dependency/self_dependency.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ 'common.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'a',
+ 'type': 'none',
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/sibling/src/build/all.gyp b/chromium/tools/gyp/test/sibling/src/build/all.gyp
new file mode 100644
index 00000000000..79c80c93635
--- /dev/null
+++ b/chromium/tools/gyp/test/sibling/src/build/all.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'All',
+ 'type': 'none',
+ 'dependencies': [
+ '../prog1/prog1.gyp:*',
+ '../prog2/prog2.gyp:*',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/sibling/src/prog1/prog1.gyp b/chromium/tools/gyp/test/sibling/src/prog1/prog1.gyp
new file mode 100644
index 00000000000..4532e4be101
--- /dev/null
+++ b/chromium/tools/gyp/test/sibling/src/prog1/prog1.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program1',
+ 'type': 'executable',
+ 'sources': [
+ 'prog1.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/sibling/src/prog2/prog2.gyp b/chromium/tools/gyp/test/sibling/src/prog2/prog2.gyp
new file mode 100644
index 00000000000..4cf7f6eb2f4
--- /dev/null
+++ b/chromium/tools/gyp/test/sibling/src/prog2/prog2.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program2',
+ 'type': 'executable',
+ 'sources': [
+ 'prog2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/standalone-static-library/invalid.gyp b/chromium/tools/gyp/test/standalone-static-library/invalid.gyp
new file mode 100644
index 00000000000..54b32117e05
--- /dev/null
+++ b/chromium/tools/gyp/test/standalone-static-library/invalid.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'bad',
+ 'type': 'executable',
+ 'standalone_static_library': 1,
+ 'sources': [
+ 'prog.c',
+ ],
+ },
+ ],
+} \ No newline at end of file
diff --git a/chromium/tools/gyp/test/standalone-static-library/mylib.gyp b/chromium/tools/gyp/test/standalone-static-library/mylib.gyp
new file mode 100644
index 00000000000..2d191de3197
--- /dev/null
+++ b/chromium/tools/gyp/test/standalone-static-library/mylib.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'mylib',
+ 'type': 'static_library',
+ 'standalone_static_library': 1,
+ 'sources': [
+ 'mylib.c',
+ ],
+ },
+ {
+ 'target_name': 'prog',
+ 'type': 'executable',
+ 'sources': [
+ 'prog.c',
+ ],
+ 'dependencies': [
+ 'mylib',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/standalone/standalone.gyp b/chromium/tools/gyp/test/standalone/standalone.gyp
new file mode 100644
index 00000000000..b2a67854303
--- /dev/null
+++ b/chromium/tools/gyp/test/standalone/standalone.gyp
@@ -0,0 +1,12 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name' : 'foo',
+ 'type' : 'executable'
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/subdirectory/src/prog1.gyp b/chromium/tools/gyp/test/subdirectory/src/prog1.gyp
new file mode 100644
index 00000000000..2aa66ce7d7f
--- /dev/null
+++ b/chromium/tools/gyp/test/subdirectory/src/prog1.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ 'symroot.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog1',
+ 'type': 'executable',
+ 'dependencies': [
+ 'subdir/prog2.gyp:prog2',
+ ],
+ 'sources': [
+ 'prog1.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/subdirectory/src/subdir/prog2.gyp b/chromium/tools/gyp/test/subdirectory/src/subdir/prog2.gyp
new file mode 100644
index 00000000000..c6cd35f7f81
--- /dev/null
+++ b/chromium/tools/gyp/test/subdirectory/src/subdir/prog2.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../symroot.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog2',
+ 'type': 'executable',
+ 'sources': [
+ 'prog2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp b/chromium/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp
new file mode 100644
index 00000000000..b49fb591137
--- /dev/null
+++ b/chromium/tools/gyp/test/subdirectory/src/subdir/subdir2/prog3.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'includes': [
+ '../../symroot.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'prog3',
+ 'type': 'executable',
+ 'sources': [
+ 'prog3.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/subdirectory/src/symroot.gypi b/chromium/tools/gyp/test/subdirectory/src/symroot.gypi
new file mode 100644
index 00000000000..519916427c9
--- /dev/null
+++ b/chromium/tools/gyp/test/subdirectory/src/symroot.gypi
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'set_symroot%': 0,
+ },
+ 'conditions': [
+ ['set_symroot == 1', {
+ 'xcode_settings': {
+ 'SYMROOT': '<(DEPTH)/build',
+ },
+ }],
+ ],
+}
diff --git a/chromium/tools/gyp/test/toolsets/toolsets.gyp b/chromium/tools/gyp/test/toolsets/toolsets.gyp
new file mode 100644
index 00000000000..3bc3a784ea8
--- /dev/null
+++ b/chromium/tools/gyp/test/toolsets/toolsets.gyp
@@ -0,0 +1,62 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'target_conditions': [
+ ['_toolset=="target"', {'defines': ['TARGET']}]
+ ]
+ },
+ 'targets': [
+ {
+ 'target_name': 'toolsets',
+ 'type': 'static_library',
+ 'toolsets': ['target', 'host'],
+ 'sources': [
+ 'toolsets.cc',
+ ],
+ },
+ {
+ 'target_name': 'host-main',
+ 'type': 'executable',
+ 'toolsets': ['host'],
+ 'dependencies': ['toolsets', 'toolsets_shared'],
+ 'sources': [
+ 'main.cc',
+ ],
+ },
+ {
+ 'target_name': 'target-main',
+ 'type': 'executable',
+ 'dependencies': ['toolsets', 'toolsets_shared'],
+ 'sources': [
+ 'main.cc',
+ ],
+ },
+ # This tests that build systems can handle a shared library being build for
+ # both host and target.
+ {
+ 'target_name': 'janus',
+ 'type': 'shared_library',
+ 'toolsets': ['target', 'host'],
+ 'sources': [
+ 'toolsets.cc',
+ ],
+ 'cflags': [ '-fPIC' ],
+ },
+ {
+ 'target_name': 'toolsets_shared',
+ 'type': 'shared_library',
+ 'toolsets': ['target', 'host'],
+ 'target_conditions': [
+ # Ensure target and host have different shared_library names
+ ['_toolset=="host"', {'product_extension': 'host'}],
+ ],
+ 'sources': [
+ 'toolsets_shared.cc',
+ ],
+ 'cflags': [ '-fPIC' ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/toplevel-dir/src/sub1/main.gyp b/chromium/tools/gyp/test/toplevel-dir/src/sub1/main.gyp
new file mode 100644
index 00000000000..33219010e48
--- /dev/null
+++ b/chromium/tools/gyp/test/toplevel-dir/src/sub1/main.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'prog1',
+ 'type': 'executable',
+ 'dependencies': [
+ '<(DEPTH)/../sub2/prog2.gyp:prog2',
+ ],
+ 'sources': [
+ 'prog1.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp b/chromium/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp
new file mode 100644
index 00000000000..59345483692
--- /dev/null
+++ b/chromium/tools/gyp/test/toplevel-dir/src/sub2/prog2.gyp
@@ -0,0 +1,15 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'prog2',
+ 'type': 'executable',
+ 'sources': [
+ 'prog2.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/variables/commands/commands-repeated.gyp b/chromium/tools/gyp/test/variables/commands/commands-repeated.gyp
new file mode 100644
index 00000000000..822ae4f05d4
--- /dev/null
+++ b/chromium/tools/gyp/test/variables/commands/commands-repeated.gyp
@@ -0,0 +1,128 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is a simple test file to make sure that variable substitution
+# happens correctly. Run "run_tests.py" using python to generate the
+# output from this gyp file.
+
+{
+ 'variables': {
+ 'pi': 'import math; print math.pi',
+ 'third_letters': "<(other_letters)HIJK",
+ 'letters_list': 'ABCD',
+ 'other_letters': '<(letters_list)EFG',
+ 'check_included': '<(included_variable)',
+ 'check_lists': [
+ '<(included_variable)',
+ '<(third_letters)',
+ ],
+ 'check_int': 5,
+ 'check_str_int': '6',
+ 'check_list_int': [
+ 7,
+ '8',
+ 9,
+ ],
+ 'not_int_1': ' 10',
+ 'not_int_2': '11 ',
+ 'not_int_3': '012',
+ 'not_int_4': '13.0',
+ 'not_int_5': '+14',
+ 'negative_int': '-15',
+ 'zero_int': '0',
+ },
+ 'includes': [
+ 'commands.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'foo',
+ 'type': 'none',
+ 'variables': {
+ 'var1': '<!(["python", "-c", "<(pi)"])',
+ 'var2': '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")',
+ 'var3': '<!(python -c "print \'<(letters_list)\'")',
+ 'var4': '<(<!(python -c "print \'letters_list\'"))',
+ 'var5': 'letters_',
+ 'var6': 'list',
+ 'var7': '<(check_int)',
+ 'var8': '<(check_int)blah',
+ 'var9': '<(check_str_int)',
+ 'var10': '<(check_list_int)',
+ 'var11': ['<@(check_list_int)'],
+ 'var12': '<(not_int_1)',
+ 'var13': '<(not_int_2)',
+ 'var14': '<(not_int_3)',
+ 'var15': '<(not_int_4)',
+ 'var16': '<(not_int_5)',
+ 'var17': '<(negative_int)',
+ 'var18': '<(zero_int)',
+ # A second set with different names to make sure they only execute the
+ # commands once.
+ 'var1prime': '<!(["python", "-c", "<(pi)"])',
+ 'var2prime': '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")',
+ 'var3prime': '<!(python -c "print \'<(letters_list)\'")',
+ 'var4prime': '<(<!(python -c "print \'letters_list\'"))',
+ },
+ 'actions': [
+ {
+ 'action_name': 'test_action',
+ 'variables': {
+ 'var7': '<!(echo <(var5)<(var6))',
+ },
+ 'inputs' : [
+ '<(var2)',
+ ],
+ 'outputs': [
+ '<(var4)',
+ '<(var7)',
+ ],
+ 'action': [
+ 'echo',
+ '<(_inputs)',
+ '<(_outputs)',
+ ],
+ },
+ # Again with the same vars to make sure the right things happened.
+ {
+ 'action_name': 'test_action_prime',
+ 'variables': {
+ 'var7': '<!(echo <(var5)<(var6))',
+ },
+ 'inputs' : [
+ '<(var2)',
+ ],
+ 'outputs': [
+ '<(var4)',
+ '<(var7)',
+ ],
+ 'action': [
+ 'echo',
+ '<(_inputs)',
+ '<(_outputs)',
+ ],
+ },
+ # And one more time with the other vars...
+ {
+ 'action_name': 'test_action_prime_prime',
+ 'variables': {
+ 'var7': '<!(echo <(var5)<(var6))',
+ },
+ 'inputs' : [
+ '<(var2prime)',
+ ],
+ 'outputs': [
+ '<(var4prime)',
+ '<(var7)',
+ ],
+ 'action': [
+ 'echo',
+ '<(_inputs)',
+ '<(_outputs)',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/variables/commands/commands.gyp b/chromium/tools/gyp/test/variables/commands/commands.gyp
new file mode 100644
index 00000000000..78376edd995
--- /dev/null
+++ b/chromium/tools/gyp/test/variables/commands/commands.gyp
@@ -0,0 +1,91 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is a simple test file to make sure that variable substitution
+# happens correctly. Run "run_tests.py" using python to generate the
+# output from this gyp file.
+
+{
+ 'variables': {
+ 'pi': 'import math; print math.pi',
+ 'third_letters': "<(other_letters)HIJK",
+ 'letters_list': 'ABCD',
+ 'other_letters': '<(letters_list)EFG',
+ 'check_included': '<(included_variable)',
+ 'check_lists': [
+ '<(included_variable)',
+ '<(third_letters)',
+ ],
+ 'check_int': 5,
+ 'check_str_int': '6',
+ 'check_list_int': [
+ 7,
+ '8',
+ 9,
+ ],
+ 'not_int_1': ' 10',
+ 'not_int_2': '11 ',
+ 'not_int_3': '012',
+ 'not_int_4': '13.0',
+ 'not_int_5': '+14',
+ 'negative_int': '-15',
+ 'zero_int': '0',
+ },
+ 'includes': [
+ 'commands.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'foo',
+ 'type': 'none',
+ 'variables': {
+ 'var1': '<!(["python", "-c", "<(pi)"])',
+ 'var2': '<!(python -c "print \'<!(python -c "<(pi)") <(letters_list)\'")',
+ 'var3': '<!(python -c "print \'<(letters_list)\'")',
+ 'var4': '<(<!(python -c "print \'letters_list\'"))',
+ 'var5': 'letters_',
+ 'var6': 'list',
+ 'var7': '<(check_int)',
+ 'var8': '<(check_int)blah',
+ 'var9': '<(check_str_int)',
+ 'var10': '<(check_list_int)',
+ 'var11': ['<@(check_list_int)'],
+ 'var12': '<(not_int_1)',
+ 'var13': '<(not_int_2)',
+ 'var14': '<(not_int_3)',
+ 'var15': '<(not_int_4)',
+ 'var16': '<(not_int_5)',
+ 'var17': '<(negative_int)',
+ 'var18': '<(zero_int)',
+ 'var19': ['<!@(python test.py)'],
+ 'var20': '<!(python test.py)',
+ 'var21': '<(default_str)',
+ 'var22': '<(default_empty_str)',
+ 'var23': '<(default_int)',
+ 'var24': '<(default_empty_files)',
+ 'var25': '<(default_int_files)',
+ },
+ 'actions': [
+ {
+ 'action_name': 'test_action',
+ 'variables': {
+ 'var7': '<!(echo <(var5)<(var6))',
+ },
+ 'inputs' : [
+ '<(var2)',
+ ],
+ 'outputs': [
+ '<(var4)',
+ '<(var7)',
+ ],
+ 'action': [
+ 'echo',
+ '<(_inputs)',
+ '<(_outputs)',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/variables/commands/commands.gypi b/chromium/tools/gyp/test/variables/commands/commands.gypi
new file mode 100644
index 00000000000..839cb30b7e1
--- /dev/null
+++ b/chromium/tools/gyp/test/variables/commands/commands.gypi
@@ -0,0 +1,23 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is included from commands.gyp to test evaluation order of includes.
+{
+ 'variables': {
+ 'included_variable': 'XYZ',
+
+ 'default_str%': 'my_str',
+ 'default_empty_str%': '',
+ 'default_int%': 0,
+
+ 'default_empty_files%': '',
+ 'default_int_files%': 0,
+ },
+ 'targets': [
+ {
+ 'target_name': 'dummy',
+ 'type': 'none',
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/variables/filelist/src/filelist.gyp b/chromium/tools/gyp/test/variables/filelist/src/filelist.gyp
new file mode 100644
index 00000000000..df48eb3e4a6
--- /dev/null
+++ b/chromium/tools/gyp/test/variables/filelist/src/filelist.gyp
@@ -0,0 +1,93 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is a test to make sure that <|(foo.txt a b c) generates
+# a pre-calculated file list at gyp time and returns foo.txt.
+# This feature is useful to work around limits in the number of arguments that
+# can be passed to rule/action.
+
+{
+ 'variables': {
+ 'names': [
+ 'John',
+ 'Jacob',
+ 'Astor',
+ 'Jingleheimer',
+ 'Jerome',
+ 'Schmidt',
+ 'Schultz',
+ ],
+ 'names!': [
+ 'Astor',
+ ],
+ 'names/': [
+ ['exclude', 'Sch.*'],
+ ['include', '.*dt'],
+ ['exclude', 'Jer.*'],
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'foo',
+ 'type': 'none',
+ 'variables': {
+ 'names_listfile': '<|(names.txt <@(names))',
+ },
+ 'actions': [
+ {
+ 'action_name': 'test_action',
+ 'inputs' : [
+ '<(names_listfile)',
+ '<!@(cat <(names_listfile))',
+ ],
+ 'outputs': [
+ 'dummy_foo',
+ ],
+ 'action': [
+ 'python', 'dummy.py', '<(names_listfile)',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'bar',
+ 'type': 'none',
+ 'sources': [
+ 'John',
+ 'Jacob',
+ 'Astor',
+ 'Jingleheimer',
+ 'Jerome',
+ 'Schmidt',
+ 'Schultz',
+ ],
+ 'sources!': [
+ 'Astor',
+ ],
+ 'sources/': [
+ ['exclude', 'Sch.*'],
+ ['include', '.*dt'],
+ ['exclude', 'Jer.*'],
+ ],
+ 'variables': {
+ 'sources_listfile': '<|(sources.txt <@(_sources))',
+ },
+ 'actions': [
+ {
+ 'action_name': 'test_action',
+ 'inputs' : [
+ '<(sources_listfile)',
+ '<!@(cat <(sources_listfile))',
+ ],
+ 'outputs': [
+ 'dummy_foo',
+ ],
+ 'action': [
+ 'python', 'dummy.py', '<(sources_listfile)',
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/variables/latelate/src/latelate.gyp b/chromium/tools/gyp/test/variables/latelate/src/latelate.gyp
new file mode 100644
index 00000000000..312f3765b67
--- /dev/null
+++ b/chromium/tools/gyp/test/variables/latelate/src/latelate.gyp
@@ -0,0 +1,34 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'target_conditions': [
+ ['has_lame==1', {
+ 'sources/': [
+ ['exclude', 'lame'],
+ ],
+ }],
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'variables': {
+ 'has_lame': 1,
+ },
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'defines': [
+ 'FOO="^(_sources)"',
+ ],
+ 'sources': [
+ 'program.cc',
+ 'this_is_lame.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/variables/variable-in-path/variable-in-path.gyp b/chromium/tools/gyp/test/variables/variable-in-path/variable-in-path.gyp
new file mode 100644
index 00000000000..908d21eb662
--- /dev/null
+++ b/chromium/tools/gyp/test/variables/variable-in-path/variable-in-path.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello1',
+ 'type': 'executable',
+ 'sources': [
+ '<(CONFIGURATION_NAME)/hello.cc',
+ ],
+ },
+ {
+ 'target_name': 'hello2',
+ 'type': 'executable',
+ 'sources': [
+ './<(CONFIGURATION_NAME)/hello.cc',
+ ],
+ },
+ ],
+ 'target_defaults': {
+ 'default_configuration': 'C1',
+ 'configurations': {
+ 'C1': {
+ },
+ 'C2': {
+ },
+ },
+ },
+}
diff --git a/chromium/tools/gyp/test/win/asm-files/asm-files.gyp b/chromium/tools/gyp/test/win/asm-files/asm-files.gyp
new file mode 100644
index 00000000000..b1f132ceea7
--- /dev/null
+++ b/chromium/tools/gyp/test/win/asm-files/asm-files.gyp
@@ -0,0 +1,17 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'sources_with_asm',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.cc',
+ 'b.s',
+ 'c.S',
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/batch-file-action/batch-file-action.gyp b/chromium/tools/gyp/test/win/batch-file-action/batch-file-action.gyp
new file mode 100644
index 00000000000..e4db9af9d3d
--- /dev/null
+++ b/chromium/tools/gyp/test/win/batch-file-action/batch-file-action.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_batch',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'copy_to_output',
+ 'inputs': ['infile'],
+ 'outputs': ['outfile'],
+ 'action': ['somecmd.bat', 'infile', 'outfile'],
+ 'msvs_cygwin_shell': 0,
+ }
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/command-quote/command-quote.gyp b/chromium/tools/gyp/test/win/command-quote/command-quote.gyp
new file mode 100644
index 00000000000..8489c5040d3
--- /dev/null
+++ b/chromium/tools/gyp/test/win/command-quote/command-quote.gyp
@@ -0,0 +1,84 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'msvs_cygwin_dirs': ['../../../../../<(DEPTH)/third_party/cygwin'],
+ },
+ 'targets': [
+ {
+ 'target_name': 'test_batch',
+ 'type': 'none',
+ 'rules': [
+ {
+ 'rule_name': 'build_with_batch',
+ 'msvs_cygwin_shell': 0,
+ 'extension': 'S',
+ 'inputs': ['<(RULE_INPUT_PATH)'],
+ 'outputs': ['output.obj'],
+ 'action': ['call go.bat', '<(RULE_INPUT_PATH)', 'output.obj'],
+ },],
+ 'sources': ['a.S'],
+ },
+ {
+ 'target_name': 'test_call_separate',
+ 'type': 'none',
+ 'rules': [
+ {
+ 'rule_name': 'build_with_batch2',
+ 'msvs_cygwin_shell': 0,
+ 'extension': 'S',
+ 'inputs': ['<(RULE_INPUT_PATH)'],
+ 'outputs': ['output2.obj'],
+ 'action': ['call', 'go.bat', '<(RULE_INPUT_PATH)', 'output2.obj'],
+ },],
+ 'sources': ['a.S'],
+ },
+ {
+ 'target_name': 'test_with_spaces',
+ 'type': 'none',
+ 'rules': [
+ {
+ 'rule_name': 'build_with_batch3',
+ 'msvs_cygwin_shell': 0,
+ 'extension': 'S',
+ 'inputs': ['<(RULE_INPUT_PATH)'],
+ 'outputs': ['output3.obj'],
+ 'action': ['bat with spaces.bat', '<(RULE_INPUT_PATH)', 'output3.obj'],
+ },],
+ 'sources': ['a.S'],
+ },
+ {
+ 'target_name': 'test_with_double_quotes',
+ 'type': 'none',
+ 'rules': [
+ {
+ 'rule_name': 'build_with_batch3',
+ 'msvs_cygwin_shell': 1,
+ 'extension': 'S',
+ 'inputs': ['<(RULE_INPUT_PATH)'],
+ 'outputs': ['output4.obj'],
+ 'arguments': ['-v'],
+ 'action': ['python', '-c', 'import shutil; '
+ 'shutil.copy("<(RULE_INPUT_PATH)", "output4.obj")'],
+ },],
+ 'sources': ['a.S'],
+ },
+ {
+ 'target_name': 'test_with_single_quotes',
+ 'type': 'none',
+ 'rules': [
+ {
+ 'rule_name': 'build_with_batch3',
+ 'msvs_cygwin_shell': 1,
+ 'extension': 'S',
+ 'inputs': ['<(RULE_INPUT_PATH)'],
+ 'outputs': ['output5.obj'],
+ 'action': ['python', '-c', "import shutil; "
+ "shutil.copy('<(RULE_INPUT_PATH)', 'output5.obj')"],
+ },],
+ 'sources': ['a.S'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/command-quote/subdir/and/another/in-subdir.gyp b/chromium/tools/gyp/test/win/command-quote/subdir/and/another/in-subdir.gyp
new file mode 100644
index 00000000000..be363bbc893
--- /dev/null
+++ b/chromium/tools/gyp/test/win/command-quote/subdir/and/another/in-subdir.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_batch_depth',
+ 'type': 'none',
+ 'variables': {
+ # Taken from native_client/build/common.gypi. Seems unintentional (a
+ # string in a 1 element list)? But since it works on other generators,
+ # I guess it should work here too.
+ 'filepath': [ 'call <(DEPTH)/../../../go.bat' ],
+ },
+ 'rules': [
+ {
+ 'rule_name': 'build_with_batch4',
+ 'msvs_cygwin_shell': 0,
+ 'extension': 'S',
+ 'inputs': ['<(RULE_INPUT_PATH)'],
+ 'outputs': ['output4.obj'],
+ 'action': ['<@(filepath)', '<(RULE_INPUT_PATH)', 'output4.obj'],
+ },],
+ 'sources': ['<(DEPTH)\\..\\..\\..\\a.S'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/additional-include-dirs.gyp b/chromium/tools/gyp/test/win/compiler-flags/additional-include-dirs.gyp
new file mode 100644
index 00000000000..42c7e849f63
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/additional-include-dirs.gyp
@@ -0,0 +1,20 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_incs',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'AdditionalIncludeDirectories': [
+ 'subdir',
+ ],
+ }
+ },
+ 'sources': ['additional-include-dirs.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/additional-options.gyp b/chromium/tools/gyp/test/win/compiler-flags/additional-options.gyp
new file mode 100644
index 00000000000..6a365a2062a
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/additional-options.gyp
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_additional_none',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '4',
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['additional-options.cc'],
+ },
+ {
+ 'target_name': 'test_additional_one',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '4',
+ 'WarnAsError': 'true',
+ 'AdditionalOptions': [ '/W1' ],
+ }
+ },
+ 'sources': ['additional-options.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/analysis.gyp b/chromium/tools/gyp/test/win/compiler-flags/analysis.gyp
new file mode 100644
index 00000000000..97e942258fb
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/analysis.gyp
@@ -0,0 +1,40 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_analysis_on',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnablePREfast': 'true',
+ 'WarnAsError': 'true',
+ },
+ },
+ 'sources': ['uninit.cc'],
+ },
+ {
+ 'target_name': 'test_analysis_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnablePREfast': 'false',
+ 'WarnAsError': 'true',
+ },
+ },
+ 'sources': ['uninit.cc'],
+ },
+ {
+ 'target_name': 'test_analysis_unspec',
+ 'type': 'executable',
+ 'sources': ['uninit.cc'],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarnAsError': 'true',
+ },
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/buffer-security-check.gyp b/chromium/tools/gyp/test/win/compiler-flags/buffer-security-check.gyp
new file mode 100644
index 00000000000..cc5a12b9536
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/buffer-security-check.gyp
@@ -0,0 +1,51 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Turn debug information on so that we can see the name of the buffer
+ # security check cookie in the disassembly.
+ {
+ 'target_name': 'test_bsc_unset',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ 'sources': ['buffer-security.cc'],
+ },
+ {
+ 'target_name': 'test_bsc_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'BufferSecurityCheck': 'false',
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ 'sources': ['buffer-security.cc'],
+ },
+ {
+ 'target_name': 'test_bsc_on',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'BufferSecurityCheck': 'true',
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ 'sources': ['buffer-security.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/character-set.gyp b/chromium/tools/gyp/test/win/compiler-flags/character-set.gyp
new file mode 100644
index 00000000000..3dc45557d9b
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/character-set.gyp
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_cs_notset',
+ 'product_name': 'test_cs_notset',
+ 'type': 'executable',
+ 'msvs_configuration_attributes': {
+ 'CharacterSet': '0'
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_cs_unicode',
+ 'product_name': 'test_cs_unicode',
+ 'type': 'executable',
+ 'msvs_configuration_attributes': {
+ 'CharacterSet': '1'
+ },
+ 'sources': ['character-set-unicode.cc'],
+ },
+ {
+ 'target_name': 'test_cs_mbcs',
+ 'product_name': 'test_cs_mbcs',
+ 'type': 'executable',
+ 'msvs_configuration_attributes': {
+ 'CharacterSet': '2'
+ },
+ 'sources': ['character-set-mbcs.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/debug-format.gyp b/chromium/tools/gyp/test/win/compiler-flags/debug-format.gyp
new file mode 100644
index 00000000000..daaed23ff1f
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/debug-format.gyp
@@ -0,0 +1,48 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test-debug-format-off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '0'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test-debug-format-oldstyle',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '1'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test-debug-format-pdb',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test-debug-format-editcontinue',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '4'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.gyp b/chromium/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.gyp
new file mode 100644
index 00000000000..941e5810dd1
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/default-char-is-unsigned.gyp
@@ -0,0 +1,20 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_default_char_is_unsigned',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DefaultCharIsUnsigned': 'true',
+ },
+ },
+ 'sources': [
+ 'default-char-is-unsigned.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/exception-handling.gyp b/chromium/tools/gyp/test/win/compiler-flags/exception-handling.gyp
new file mode 100644
index 00000000000..c266768ddae
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/exception-handling.gyp
@@ -0,0 +1,46 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Optimization disabled so that the exception-causing code is not removed
+ # (divide by zero was getting optimized away in VS2010).
+ {
+ 'target_name': 'test_eh_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'ExceptionHandling': '0',
+ 'WarnAsError': 'true',
+ 'Optimization': '0',
+ }
+ },
+ 'sources': ['exception-handling-on.cc'],
+ },
+ {
+ 'target_name': 'test_eh_s',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'ExceptionHandling': '1',
+ 'WarnAsError': 'true',
+ 'Optimization': '0',
+ }
+ },
+ 'sources': ['exception-handling-on.cc'],
+ },
+ {
+ 'target_name': 'test_eh_a',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'ExceptionHandling': '2',
+ 'WarnAsError': 'true',
+ 'Optimization': '0',
+ }
+ },
+ 'sources': ['exception-handling-on.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/force-include-files.gyp b/chromium/tools/gyp/test/win/compiler-flags/force-include-files.gyp
new file mode 100644
index 00000000000..a81609e2169
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/force-include-files.gyp
@@ -0,0 +1,20 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_force_include_files',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'ForcedIncludeFiles': ['string', 'vector', 'list'],
+ },
+ },
+ 'sources': [
+ 'force-include-files.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/function-level-linking.gyp b/chromium/tools/gyp/test/win/compiler-flags/function-level-linking.gyp
new file mode 100644
index 00000000000..5858586a249
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/function-level-linking.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_fll_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFunctionLevelLinking': 'false'
+ }
+ },
+ 'sources': ['function-level-linking.cc'],
+ },
+ {
+ 'target_name': 'test_fll_on',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFunctionLevelLinking': 'true',
+ }
+ },
+ 'sources': ['function-level-linking.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/optimizations.gyp b/chromium/tools/gyp/test/win/compiler-flags/optimizations.gyp
new file mode 100644
index 00000000000..e63096f0f70
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/optimizations.gyp
@@ -0,0 +1,207 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_opt_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '0'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_lev_size',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '1'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_lev_speed',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '2'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_lev_max',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '3'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_unset',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_fpo',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'OmitFramePointers': 'true'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_fpo_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'OmitFramePointers': 'false'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_intrinsic',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableIntrinsicFunctions': 'true'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_intrinsic_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableIntrinsicFunctions': 'false'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_inline_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'InlineFunctionExpansion': '0'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_inline_manual',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'InlineFunctionExpansion': '1'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_inline_auto',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'InlineFunctionExpansion': '2'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_neither',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'FavorSizeOrSpeed': '0'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_speed',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'FavorSizeOrSpeed': '1'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_size',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'FavorSizeOrSpeed': '2'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_wpo',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WholeProgramOptimization': 'true'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_sp',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'StringPooling': 'true'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_sp_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'StringPooling': 'false'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_fso',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFiberSafeOptimizations': 'true'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_opt_fso_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFiberSafeOptimizations': 'false'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/pdbname-override.gyp b/chromium/tools/gyp/test/win/compiler-flags/pdbname-override.gyp
new file mode 100644
index 00000000000..dad20e01fde
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/pdbname-override.gyp
@@ -0,0 +1,26 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_pdbname',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.cc',
+ 'pdbname.cc',
+ ],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ 'ProgramDataBaseFileName': '<(PRODUCT_DIR)/compiler_generated.pdb',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'ProgramDatabaseFile': '<(PRODUCT_DIR)/linker_generated.pdb',
+ },
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/pdbname.gyp b/chromium/tools/gyp/test/win/compiler-flags/pdbname.gyp
new file mode 100644
index 00000000000..8fcf754727c
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/pdbname.gyp
@@ -0,0 +1,24 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_pdbname',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.cc',
+ 'pdbname.cc',
+ ],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/rtti.gyp b/chromium/tools/gyp/test/win/compiler-flags/rtti.gyp
new file mode 100644
index 00000000000..704cd58f5a5
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/rtti.gyp
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_rtti_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'RuntimeTypeInfo': 'false',
+ 'WarnAsError': 'true'
+ }
+ },
+ 'sources': ['rtti-on.cc'],
+ },
+ {
+ 'target_name': 'test_rtti_on',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'RuntimeTypeInfo': 'true',
+ 'WarnAsError': 'true'
+ }
+ },
+ 'sources': ['rtti-on.cc'],
+ },
+ {
+ 'target_name': 'test_rtti_unset',
+ 'type': 'executable',
+ 'msvs_settings': {
+ },
+ 'sources': ['rtti-on.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/runtime-checks.gyp b/chromium/tools/gyp/test/win/compiler-flags/runtime-checks.gyp
new file mode 100644
index 00000000000..8ea30920577
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/runtime-checks.gyp
@@ -0,0 +1,29 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_brc_none',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '0',
+ }
+ },
+ 'sources': ['runtime-checks.cc'],
+ },
+ {
+ 'target_name': 'test_brc_1',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'Optimization': '0',
+ 'BasicRuntimeChecks': '3'
+ }
+ },
+ 'sources': ['runtime-checks.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/runtime-library.gyp b/chromium/tools/gyp/test/win/compiler-flags/runtime-library.gyp
new file mode 100644
index 00000000000..04afc391c77
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/runtime-library.gyp
@@ -0,0 +1,48 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_rl_md',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'RuntimeLibrary': '2'
+ }
+ },
+ 'sources': ['runtime-library-md.cc'],
+ },
+ {
+ 'target_name': 'test_rl_mdd',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'RuntimeLibrary': '3'
+ }
+ },
+ 'sources': ['runtime-library-mdd.cc'],
+ },
+ {
+ 'target_name': 'test_rl_mt',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'RuntimeLibrary': '0'
+ }
+ },
+ 'sources': ['runtime-library-mt.cc'],
+ },
+ {
+ 'target_name': 'test_rl_mtd',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'RuntimeLibrary': '1'
+ }
+ },
+ 'sources': ['runtime-library-mtd.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type.gyp b/chromium/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type.gyp
new file mode 100644
index 00000000000..456fe047d04
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/treat-wchar-t-as-built-in-type.gyp
@@ -0,0 +1,33 @@
+# Copyright (c) 2010 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_treat_wchar_t_as_built_in_type_negative',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'TreatWChar_tAsBuiltInType': 'false',
+ },
+ },
+ 'sources': [
+ 'treat-wchar-t-as-built-in-type1.cc',
+ ],
+ },
+ {
+ 'target_name': 'test_treat_wchar_t_as_built_in_type_positive',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'TreatWChar_tAsBuiltInType': 'true',
+ },
+ },
+ 'sources': [
+ 'treat-wchar-t-as-built-in-type2.cc',
+ ],
+ },
+
+ ],
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/warning-as-error.gyp b/chromium/tools/gyp/test/win/compiler-flags/warning-as-error.gyp
new file mode 100644
index 00000000000..d71f2611410
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/warning-as-error.gyp
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_warn_as_error_false',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarnAsError': 'false'
+ }
+ },
+ 'sources': ['warning-as-error.cc']
+ },
+ {
+ 'target_name': 'test_warn_as_error_true',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarnAsError': 'true'
+ }
+ },
+ 'sources': ['warning-as-error.cc']
+ },
+ {
+ 'target_name': 'test_warn_as_error_unset',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ }
+ },
+ 'sources': ['warning-as-error.cc']
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/compiler-flags/warning-level.gyp b/chromium/tools/gyp/test/win/compiler-flags/warning-level.gyp
new file mode 100644
index 00000000000..2297aa7cacf
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/warning-level.gyp
@@ -0,0 +1,115 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Level 1
+ {
+ 'target_name': 'test_wl1_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '1',
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['warning-level1.cc'],
+ },
+ {
+ 'target_name': 'test_wl1_pass',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '1',
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['warning-level2.cc'],
+ },
+
+ # Level 2
+ {
+ 'target_name': 'test_wl2_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '2',
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['warning-level2.cc'],
+ },
+ {
+ 'target_name': 'test_wl2_pass',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '2',
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['warning-level3.cc'],
+ },
+
+ # Level 3
+ {
+ 'target_name': 'test_wl3_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '3',
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['warning-level3.cc'],
+ },
+ {
+ 'target_name': 'test_wl3_pass',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '3',
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['warning-level4.cc'],
+ },
+
+
+ # Level 4
+ {
+ 'target_name': 'test_wl4_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '4',
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['warning-level4.cc'],
+ },
+
+ # Default level
+ {
+ 'target_name': 'test_def_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarnAsError': 'true',
+ }
+ },
+ 'sources': ['warning-level1.cc'],
+ },
+ {
+ 'target_name': 'test_def_pass',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ }
+ },
+ 'sources': ['warning-level2.cc'],
+ },
+
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/generator-output-different-drive/prog.gyp b/chromium/tools/gyp/test/win/generator-output-different-drive/prog.gyp
new file mode 100644
index 00000000000..92f53e5da56
--- /dev/null
+++ b/chromium/tools/gyp/test/win/generator-output-different-drive/prog.gyp
@@ -0,0 +1,15 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'program',
+ 'type': 'executable',
+ 'sources': [
+ 'prog.c',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/win/idl-rules/basic-idl.gyp b/chromium/tools/gyp/test/win/idl-rules/basic-idl.gyp
new file mode 100644
index 00000000000..9c08327574e
--- /dev/null
+++ b/chromium/tools/gyp/test/win/idl-rules/basic-idl.gyp
@@ -0,0 +1,42 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'midl_out_dir': '<(SHARED_INTERMEDIATE_DIR)',
+ },
+ 'target_defaults': {
+ 'configurations': {
+ 'Debug': {
+ 'msvs_configuration_platform': 'Win32',
+ },
+ 'Debug_x64': {
+ 'inherit_from': ['Debug'],
+ 'msvs_configuration_platform': 'x64',
+ },
+ },
+ },
+ 'targets': [
+ {
+ 'target_name': 'idl_test',
+ 'type': 'executable',
+ 'sources': [
+ 'history_indexer.idl',
+ '<(midl_out_dir)/history_indexer.h',
+ '<(midl_out_dir)/history_indexer_i.c',
+ 'history_indexer_user.cc',
+ ],
+ 'libraries': ['ole32.lib'],
+ 'include_dirs': [
+ '<(midl_out_dir)',
+ ],
+ 'msvs_settings': {
+ 'VCMIDLTool': {
+ 'OutputDirectory': '<(midl_out_dir)',
+ 'HeaderFileName': '<(RULE_INPUT_ROOT).h',
+ },
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/win/importlib/importlib.gyp b/chromium/tools/gyp/test/win/importlib/importlib.gyp
new file mode 100644
index 00000000000..ab15b1893d4
--- /dev/null
+++ b/chromium/tools/gyp/test/win/importlib/importlib.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_importlib',
+ 'type': 'shared_library',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '2',
+ }
+ },
+ 'sources': ['has-exports.cc'],
+ },
+
+ {
+ 'target_name': 'test_linkagainst',
+ 'type': 'executable',
+ 'dependencies': ['test_importlib'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '2',
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/large-pdb/large-pdb.gyp b/chromium/tools/gyp/test/win/large-pdb/large-pdb.gyp
new file mode 100644
index 00000000000..2a241a56233
--- /dev/null
+++ b/chromium/tools/gyp/test/win/large-pdb/large-pdb.gyp
@@ -0,0 +1,98 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'large_pdb_exe',
+ 'type': 'executable',
+ 'msvs_large_pdb': 1,
+ 'sources': [
+ 'main.cc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'ProgramDatabaseFile': '<(PRODUCT_DIR)/large_pdb_exe.exe.pdb',
+ },
+ },
+ },
+ {
+ 'target_name': 'small_pdb_exe',
+ 'type': 'executable',
+ 'msvs_large_pdb': 0,
+ 'sources': [
+ 'main.cc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'ProgramDatabaseFile': '<(PRODUCT_DIR)/small_pdb_exe.exe.pdb',
+ },
+ },
+ },
+ {
+ 'target_name': 'large_pdb_dll',
+ 'type': 'shared_library',
+ 'msvs_large_pdb': 1,
+ 'sources': [
+ 'dllmain.cc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'ProgramDatabaseFile': '<(PRODUCT_DIR)/large_pdb_dll.dll.pdb',
+ },
+ },
+ },
+ {
+ 'target_name': 'small_pdb_dll',
+ 'type': 'shared_library',
+ 'msvs_large_pdb': 0,
+ 'sources': [
+ 'dllmain.cc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'ProgramDatabaseFile': '<(PRODUCT_DIR)/small_pdb_dll.dll.pdb',
+ },
+ },
+ },
+ {
+ 'target_name': 'large_pdb_implicit_exe',
+ 'type': 'executable',
+ 'msvs_large_pdb': 1,
+ 'sources': [
+ 'main.cc',
+ ],
+ # No PDB file is specified. However, the msvs_large_pdb mechanism should
+ # default to the appropriate <(PRODUCT_DIR)/<(TARGET_NAME).exe.pdb.
+ },
+ {
+ 'target_name': 'large_pdb_variable_exe',
+ 'type': 'executable',
+ 'msvs_large_pdb': 1,
+ 'sources': [
+ 'main.cc',
+ ],
+ # No PDB file is specified. However, the msvs_large_pdb_path variable
+ # explicitly sets one.
+ 'variables': {
+ 'msvs_large_pdb_path': '<(PRODUCT_DIR)/foo.pdb',
+ },
+ },
+ {
+ 'target_name': 'large_pdb_product_exe',
+ 'product_name': 'bar',
+ 'type': 'executable',
+ 'msvs_large_pdb': 1,
+ 'sources': [
+ 'main.cc',
+ ],
+ # No PDB file is specified. However, we've specified a product name so
+ # it should use <(PRODUCT_DIR)/bar.exe.pdb.
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/lib-flags/ltcg.gyp b/chromium/tools/gyp/test/win/lib-flags/ltcg.gyp
new file mode 100644
index 00000000000..c183107730a
--- /dev/null
+++ b/chromium/tools/gyp/test/win/lib-flags/ltcg.gyp
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'lib_answer',
+ 'type': 'static_library',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WholeProgramOptimization': 'true', # /GL
+ },
+ 'VCLibrarianTool': {
+ 'LinkTimeCodeGeneration': 'true', # /LTCG
+ },
+ },
+ 'sources': ['answer.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/additional-deps.gyp b/chromium/tools/gyp/test/win/linker-flags/additional-deps.gyp
new file mode 100644
index 00000000000..55afe64fb09
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/additional-deps.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_deps_none',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_deps_few',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': [
+ 'wininet.lib',
+ 'ws2_32.lib',
+ ]
+ }
+ },
+ 'sources': ['additional-deps.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/additional-options.gyp b/chromium/tools/gyp/test/win/linker-flags/additional-options.gyp
new file mode 100644
index 00000000000..cab3994cd10
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/additional-options.gyp
@@ -0,0 +1,29 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_additional_none',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_additional_few',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalOptions': [
+ '/dynamicbase:no',
+ ]
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/aslr.gyp b/chromium/tools/gyp/test/win/linker-flags/aslr.gyp
new file mode 100644
index 00000000000..b3aefd50b7f
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/aslr.gyp
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_aslr_default',
+ 'type': 'executable',
+ 'msvs_settings': {
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_aslr_no',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'RandomizedBaseAddress': '1',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_aslr_yes',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'RandomizedBaseAddress': '2',
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/debug-info.gyp b/chromium/tools/gyp/test/win/linker-flags/debug-info.gyp
new file mode 100644
index 00000000000..d47d0ecced9
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/debug-info.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_debug_off',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'false'
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_debug_on',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true'
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/deffile-multiple.gyp b/chromium/tools/gyp/test/win/linker-flags/deffile-multiple.gyp
new file mode 100644
index 00000000000..c74a9af20ae
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/deffile-multiple.gyp
@@ -0,0 +1,17 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_deffile_multiple_fail',
+ 'type': 'shared_library',
+ 'sources': [
+ 'deffile.cc',
+ 'deffile.def',
+ 'deffile2.def',
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/deffile.gyp b/chromium/tools/gyp/test/win/linker-flags/deffile.gyp
new file mode 100644
index 00000000000..7b241d5e3ae
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/deffile.gyp
@@ -0,0 +1,38 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_deffile_dll_ok',
+ 'type': 'shared_library',
+ 'sources': [
+ 'deffile.cc',
+ 'deffile.def',
+ ],
+ },
+ {
+ 'target_name': 'test_deffile_dll_notexported',
+ 'type': 'shared_library',
+ 'sources': [
+ 'deffile.cc',
+ ],
+ },
+ {
+ 'target_name': 'test_deffile_exe_ok',
+ 'type': 'executable',
+ 'sources': [
+ 'deffile.cc',
+ 'deffile.def',
+ ],
+ },
+ {
+ 'target_name': 'test_deffile_exe_notexported',
+ 'type': 'executable',
+ 'sources': [
+ 'deffile.cc',
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/delay-load-dlls.gyp b/chromium/tools/gyp/test/win/linker-flags/delay-load-dlls.gyp
new file mode 100644
index 00000000000..671cbaa802f
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/delay-load-dlls.gyp
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_dld_none',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ }
+ },
+ 'sources': ['delay-load.cc'],
+ 'libraries': [
+ 'delayimp.lib',
+ 'shell32.lib',
+ ],
+ },
+ {
+ 'target_name': 'test_dld_shell32',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'DelayLoadDLLs': ['shell32.dll']
+ }
+ },
+ 'sources': ['delay-load.cc'],
+ 'libraries': [
+ 'delayimp.lib',
+ 'shell32.lib',
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/embed-manifest.gyp b/chromium/tools/gyp/test/win/linker-flags/embed-manifest.gyp
new file mode 100644
index 00000000000..fefb2f56d85
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/embed-manifest.gyp
@@ -0,0 +1,109 @@
+# Copyright (c) 2013 Yandex LLC. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_manifest_exe',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '1',
+ },
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_dll',
+ 'type': 'loadable_module',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '1',
+ },
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_extra1',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ 'AdditionalManifestFiles': 'extra.manifest',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_extra2',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ 'AdditionalManifestFiles': 'extra.manifest;extra2.manifest',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_extra_list',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ 'AdditionalManifestFiles': [
+ 'extra.manifest',
+ 'extra2.manifest'
+ ],
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_dll_inc',
+ 'type': 'loadable_module',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '2',
+ },
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_exe_inc',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '2',
+ },
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_exe_inc_no_embed',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '2',
+ },
+ 'VCManifestTool': {
+ 'EmbedManifest': 'false',
+ }
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/enable-uac.gyp b/chromium/tools/gyp/test/win/linker-flags/enable-uac.gyp
new file mode 100644
index 00000000000..4e58c86ec88
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/enable-uac.gyp
@@ -0,0 +1,45 @@
+# Copyright 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'enable_uac',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ }
+ },
+ },
+ {
+ 'target_name': 'enable_uac_no',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'EnableUAC': 'false',
+ },
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ }
+ },
+ },
+ {
+ 'target_name': 'enable_uac_admin',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'UACExecutionLevel': 2,
+ 'UACUIAccess': 'true',
+ },
+ 'VCManifestTool': {
+ 'EmbedManifest': 'true',
+ }
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/entrypointsymbol.gyp b/chromium/tools/gyp/test/win/linker-flags/entrypointsymbol.gyp
new file mode 100644
index 00000000000..7f2c14252d0
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/entrypointsymbol.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_ok',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'EntryPointSymbol': 'MainEntryPoint',
+ }
+ },
+ 'sources': ['entrypointsymbol.cc'],
+ },
+ {
+ 'target_name': 'test_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'EntryPointSymbol': 'MainEntryPoint',
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/fixed-base.gyp b/chromium/tools/gyp/test/win/linker-flags/fixed-base.gyp
new file mode 100644
index 00000000000..cc2982eb279
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/fixed-base.gyp
@@ -0,0 +1,52 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Disable DYNAMICBASE for these tests because it implies/doesn't imply
+ # FIXED in certain cases so it complicates the test for FIXED.
+ {
+ 'target_name': 'test_fixed_default_exe',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'RandomizedBaseAddress': '1',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_fixed_default_dll',
+ 'type': 'shared_library',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'RandomizedBaseAddress': '1',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_fixed_no',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'FixedBaseAddress': '1',
+ 'RandomizedBaseAddress': '1',
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_fixed_yes',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'FixedBaseAddress': '2',
+ 'RandomizedBaseAddress': '1',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/generate-manifest.gyp b/chromium/tools/gyp/test/win/linker-flags/generate-manifest.gyp
new file mode 100644
index 00000000000..fe5ee741363
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/generate-manifest.gyp
@@ -0,0 +1,64 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_manifest_exe',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'false',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_dll',
+ 'type': 'shared_library',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'false',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_extra1',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'false',
+ 'AdditionalManifestFiles': 'extra.manifest',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_extra2',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'false',
+ 'AdditionalManifestFiles': 'extra.manifest;extra2.manifest',
+ }
+ },
+ },
+ {
+ 'target_name': 'test_manifest_extra_list',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'EmbedManifest': 'false',
+ 'AdditionalManifestFiles': [
+ 'extra.manifest',
+ 'extra2.manifest'
+ ],
+ }
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/incremental.gyp b/chromium/tools/gyp/test/win/linker-flags/incremental.gyp
new file mode 100644
index 00000000000..59f3103253c
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/incremental.gyp
@@ -0,0 +1,65 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Turn on debug information so the incremental linking tables have a
+ # visible symbolic name in the disassembly.
+ {
+ 'target_name': 'test_incremental_unset',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_incremental_default',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'LinkIncremental': '0',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_incremental_no',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'LinkIncremental': '1',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_incremental_yes',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'LinkIncremental': '2',
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/large-address-aware.gyp b/chromium/tools/gyp/test/win/linker-flags/large-address-aware.gyp
new file mode 100644
index 00000000000..fa56d3789ce
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/large-address-aware.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_large_address_aware_no',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LargeAddressAware': '1',
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_large_address_aware_yes',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LargeAddressAware': '2',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/library-adjust.gyp b/chromium/tools/gyp/test/win/linker-flags/library-adjust.gyp
new file mode 100644
index 00000000000..10e9996f5c6
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/library-adjust.gyp
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_adjust',
+ 'type': 'executable',
+ 'libraries': [
+ '-lws2_32.lib'
+ ],
+ 'sources': ['library-adjust.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/library-directories.gyp b/chromium/tools/gyp/test/win/linker-flags/library-directories.gyp
new file mode 100644
index 00000000000..25395d6c879
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/library-directories.gyp
@@ -0,0 +1,42 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_libdirs_none',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'AdditionalDependencies': [
+ 'test_lib.lib',
+ ],
+ },
+ },
+ 'sources': ['library-directories-reference.cc'],
+ },
+ {
+ 'target_name': 'test_libdirs_with',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ # NOTE: Don't use this for general dependencies between gyp
+ # libraries (use 'dependencies' instead). This is done here only for
+ # testing.
+ #
+ # This setting should only be used to depend on third party prebuilt
+ # libraries that are stored as binaries at a known location.
+ 'AdditionalLibraryDirectories': [
+ '<(DEPTH)/out/Default/obj/subdir', # ninja style
+ '<(DEPTH)/subdir/Default/lib', # msvs style
+ ],
+ 'AdditionalDependencies': [
+ 'test_lib.lib',
+ ],
+ },
+ },
+ 'sources': ['library-directories-reference.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/mapfile.gyp b/chromium/tools/gyp/test/win/linker-flags/mapfile.gyp
new file mode 100644
index 00000000000..14206fe28d7
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/mapfile.gyp
@@ -0,0 +1,45 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_mapfile_unset',
+ 'type': 'executable',
+ 'sources': ['mapfile.cc'],
+ },
+ {
+ 'target_name': 'test_mapfile_generate',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateMapFile': 'true',
+ },
+ },
+ 'sources': ['mapfile.cc'],
+ },
+ {
+ 'target_name': 'test_mapfile_generate_exports',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateMapFile': 'true',
+ 'MapExports': 'true',
+ },
+ },
+ 'sources': ['mapfile.cc'],
+ },
+ {
+ 'target_name': 'test_mapfile_generate_filename',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'GenerateMapFile': 'true',
+ 'MapFileName': '<(PRODUCT_DIR)/custom_file_name.map',
+ },
+ },
+ 'sources': ['mapfile.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/no-default-libs.gyp b/chromium/tools/gyp/test/win/linker-flags/no-default-libs.gyp
new file mode 100644
index 00000000000..77838ce8c4c
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/no-default-libs.gyp
@@ -0,0 +1,13 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_default',
+ 'type': 'executable',
+ 'sources': ['no-default-libs.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/nodefaultlib.gyp b/chromium/tools/gyp/test/win/linker-flags/nodefaultlib.gyp
new file mode 100644
index 00000000000..4fb452a18bc
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/nodefaultlib.gyp
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_ok',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'IgnoreDefaultLibraryNames':
+ ['libcmtd.lib', 'libcmt.lib', 'msvcrt.lib', 'msvcrtd.lib'],
+ }
+ },
+ 'sources': ['nodefaultlib.cc'],
+ },
+ {
+ 'target_name': 'test_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'IgnoreDefaultLibraryNames':
+ ['libcmtd.lib', 'libcmt.lib', 'msvcrt.lib', 'msvcrtd.lib'],
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/nxcompat.gyp b/chromium/tools/gyp/test/win/linker-flags/nxcompat.gyp
new file mode 100644
index 00000000000..fa4118cbd73
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/nxcompat.gyp
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_nxcompat_default',
+ 'type': 'executable',
+ 'msvs_settings': {
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_nxcompat_no',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'DataExecutionPrevention': '1',
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_nxcompat_yes',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'DataExecutionPrevention': '2',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/opt-icf.gyp b/chromium/tools/gyp/test/win/linker-flags/opt-icf.gyp
new file mode 100644
index 00000000000..effe8021c34
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/opt-icf.gyp
@@ -0,0 +1,63 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Have to turn on function level linking here to get the function packaged
+ # as a COMDAT so that it's eligible for merging. Also turn on debug
+ # information so that the symbol names for the code appear in the dump.
+ # Finally, specify non-incremental linking so that there's not a bunch of
+ # extra "similar_function"s in the output (the ILT jump table).
+ {
+ 'target_name': 'test_opticf_default',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFunctionLevelLinking': 'true',
+ 'DebugInformationFormat': '3',
+ 'Optimization': '0',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'LinkIncremental': '1',
+ },
+ },
+ 'sources': ['opt-icf.cc'],
+ },
+ {
+ 'target_name': 'test_opticf_no',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFunctionLevelLinking': 'true',
+ 'DebugInformationFormat': '3',
+ 'Optimization': '0',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'EnableCOMDATFolding': '1',
+ 'LinkIncremental': '1',
+ },
+ },
+ 'sources': ['opt-icf.cc'],
+ },
+ {
+ 'target_name': 'test_opticf_yes',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFunctionLevelLinking': 'true',
+ 'DebugInformationFormat': '3',
+ 'Optimization': '0',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'EnableCOMDATFolding': '2',
+ 'LinkIncremental': '1',
+ },
+ },
+ 'sources': ['opt-icf.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/opt-ref.gyp b/chromium/tools/gyp/test/win/linker-flags/opt-ref.gyp
new file mode 100644
index 00000000000..69d0281a08d
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/opt-ref.gyp
@@ -0,0 +1,56 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Have to turn on function level linking here to get the function packaged
+ # as a COMDAT so that it's eligible for optimizing away. Also turn on
+ # debug information so that the symbol names for the code appear in the
+ # dump (so we can verify if they are included in the final exe).
+ {
+ 'target_name': 'test_optref_default',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFunctionLevelLinking': 'true',
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ 'sources': ['opt-ref.cc'],
+ },
+ {
+ 'target_name': 'test_optref_no',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFunctionLevelLinking': 'true',
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'OptimizeReferences': '1',
+ },
+ },
+ 'sources': ['opt-ref.cc'],
+ },
+ {
+ 'target_name': 'test_optref_yes',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'EnableFunctionLevelLinking': 'true',
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'OptimizeReferences': '2',
+ },
+ },
+ 'sources': ['opt-ref.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/outputfile.gyp b/chromium/tools/gyp/test/win/linker-flags/outputfile.gyp
new file mode 100644
index 00000000000..1022ec2e20a
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/outputfile.gyp
@@ -0,0 +1,58 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_output_exe',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(OutDir)\\blorp.exe'
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_output_exe2',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(OutDir)\\subdir\\blorp.exe'
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_output_dll',
+ 'type': 'shared_library',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(OutDir)\\blorp.dll'
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_output_lib',
+ 'type': 'static_library',
+ 'msvs_settings': {
+ 'VCLibrarianTool': {
+ 'OutputFile': '$(OutDir)\\blorp.lib'
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_output_lib2',
+ 'type': 'static_library',
+ 'msvs_settings': {
+ 'VCLibrarianTool': {
+ 'OutputFile': '$(OutDir)\\subdir\\blorp.lib'
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/profile.gyp b/chromium/tools/gyp/test/win/linker-flags/profile.gyp
new file mode 100644
index 00000000000..d60a700fbbf
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/profile.gyp
@@ -0,0 +1,50 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Verify that 'Profile' option correctly makes it to LINK steup in Ninja
+ {
+ 'target_name': 'test_profile_true',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3'
+ },
+ 'VCLinkerTool': {
+ 'Profile': 'true',
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ },
+ {
+ 'target_name': 'test_profile_false',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3'
+ },
+ 'VCLinkerTool': {
+ 'Profile': 'false',
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ },
+ {
+ 'target_name': 'test_profile_default',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3'
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/program-database.gyp b/chromium/tools/gyp/test/win/linker-flags/program-database.gyp
new file mode 100644
index 00000000000..b822a8be40e
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/program-database.gyp
@@ -0,0 +1,39 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ # Verify that 'ProgramDataBase' option correctly makes it to LINK step in Ninja
+ {
+ # Verify that VC macros and windows paths work correctly
+ 'target_name': 'test_pdb_outdir',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3'
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'ProgramDatabaseFile': '$(OutDir)\\name_outdir.pdb',
+ },
+ },
+ },
+ {
+ # Verify that GYP macros and POSIX paths work correctly
+ 'target_name': 'test_pdb_proddir',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3'
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ 'ProgramDatabaseFile': '<(PRODUCT_DIR)/name_proddir.pdb',
+ },
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/subdir/library.gyp b/chromium/tools/gyp/test/win/linker-flags/subdir/library.gyp
new file mode 100644
index 00000000000..519577f0d7e
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/subdir/library.gyp
@@ -0,0 +1,13 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_lib',
+ 'type': 'static_library',
+ 'sources': ['../library-directories-define.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/subsystem.gyp b/chromium/tools/gyp/test/win/linker-flags/subsystem.gyp
new file mode 100644
index 00000000000..ec68e805c9b
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/subsystem.gyp
@@ -0,0 +1,48 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_console_ok',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '1'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_console_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '1'
+ }
+ },
+ 'sources': ['subsystem-windows.cc'],
+ },
+ {
+ 'target_name': 'test_windows_ok',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2'
+ }
+ },
+ 'sources': ['subsystem-windows.cc'],
+ },
+ {
+ 'target_name': 'test_windows_fail',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2'
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/linker-flags/tsaware.gyp b/chromium/tools/gyp/test/win/linker-flags/tsaware.gyp
new file mode 100644
index 00000000000..7ffc7426bbf
--- /dev/null
+++ b/chromium/tools/gyp/test/win/linker-flags/tsaware.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_tsaware_no',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'TerminalServerAware': '1',
+ }
+ },
+ 'sources': ['hello.cc'],
+ },
+ {
+ 'target_name': 'test_tsaware_yes',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'TerminalServerAware': '2',
+ },
+ },
+ 'sources': ['hello.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/long-command-line/long-command-line.gyp b/chromium/tools/gyp/test/win/long-command-line/long-command-line.gyp
new file mode 100644
index 00000000000..964c94fa946
--- /dev/null
+++ b/chromium/tools/gyp/test/win/long-command-line/long-command-line.gyp
@@ -0,0 +1,54 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'longexe',
+ 'type': 'executable',
+ 'msvs_settings': {
+ # Use this as a simple way to get a long command.
+ 'VCCLCompilerTool': {
+ 'AdditionalOptions': '/nologo ' * 8000,
+ },
+ 'VCLinkerTool': {
+ 'AdditionalOptions': '/nologo ' * 8000,
+ },
+ },
+ 'sources': [
+ 'hello.cc',
+ ],
+ },
+ {
+ 'target_name': 'longlib',
+ 'type': 'static_library',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'AdditionalOptions': '/nologo ' * 8000,
+ },
+ 'VCLibrarianTool': {
+ 'AdditionalOptions': '/nologo ' * 8000,
+ },
+ },
+ 'sources': [
+ 'function.cc',
+ ],
+ },
+ {
+ 'target_name': 'longdll',
+ 'type': 'shared_library',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'AdditionalOptions': '/nologo ' * 8000,
+ },
+ 'VCLinkerTool': {
+ 'AdditionalOptions': '/nologo ' * 8000,
+ },
+ },
+ 'sources': [
+ 'hello.cc',
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/precompiled/hello.gyp b/chromium/tools/gyp/test/win/precompiled/hello.gyp
new file mode 100644
index 00000000000..5f82c535939
--- /dev/null
+++ b/chromium/tools/gyp/test/win/precompiled/hello.gyp
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'hello',
+ 'type': 'executable',
+ 'sources': [
+ 'hello.c',
+ 'hello2.c',
+ 'precomp.c',
+ ],
+ 'msvs_precompiled_header': 'stdio.h',
+ 'msvs_precompiled_source': 'precomp.c',
+
+ # Required so that the printf actually causes a build failure
+ # if the pch isn't included.
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarningLevel': '3',
+ 'WarnAsError': 'true',
+ },
+ },
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/win/rc-build/hello.gyp b/chromium/tools/gyp/test/win/rc-build/hello.gyp
new file mode 100644
index 00000000000..2bd055c244f
--- /dev/null
+++ b/chromium/tools/gyp/test/win/rc-build/hello.gyp
@@ -0,0 +1,66 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'with_resources',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ 'VCResourceCompilerTool': {
+ 'Culture' : '1033',
+ },
+ },
+ 'sources': [
+ 'hello.cpp',
+ 'hello.rc',
+ ],
+ 'libraries': [
+ 'kernel32.lib',
+ 'user32.lib',
+ ],
+ },
+ {
+ 'target_name': 'with_resources_subdir',
+ 'type': 'executable',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'DebugInformationFormat': '3',
+ },
+ 'VCLinkerTool': {
+ 'GenerateDebugInformation': 'true',
+ },
+ 'VCResourceCompilerTool': {
+ 'Culture' : '1033',
+ },
+ },
+ 'sources': [
+ 'hello.cpp',
+ 'subdir/hello2.rc',
+ ],
+ 'libraries': [
+ 'kernel32.lib',
+ 'user32.lib',
+ ],
+ },
+ {
+ 'target_name': 'resource_only_dll',
+ 'type': 'shared_library',
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'ResourceOnlyDLL': 'true',
+ },
+ },
+ 'sources': [
+ 'hello.rc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/gyp/test/win/shard/shard.gyp b/chromium/tools/gyp/test/win/shard/shard.gyp
new file mode 100644
index 00000000000..0635a75dde9
--- /dev/null
+++ b/chromium/tools/gyp/test/win/shard/shard.gyp
@@ -0,0 +1,20 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'shard',
+ 'type': 'static_library',
+ 'msvs_shard': 4,
+ 'sources': [
+ 'hello1.cc',
+ 'hello2.cc',
+ 'hello3.cc',
+ 'hello4.cc',
+ ],
+ 'product_dir': '<(PRODUCT_DIR)',
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/uldi/uldi.gyp b/chromium/tools/gyp/test/win/uldi/uldi.gyp
new file mode 100644
index 00000000000..c32f5e0956e
--- /dev/null
+++ b/chromium/tools/gyp/test/win/uldi/uldi.gyp
@@ -0,0 +1,45 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'lib1',
+ 'type': 'static_library',
+ 'sources': ['a.cc'],
+ },
+ {
+ 'target_name': 'final_uldi',
+ 'type': 'executable',
+ 'dependencies': [
+ 'lib1',
+ 'lib2',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'UseLibraryDependencyInputs': 'true'
+ },
+ },
+ 'sources': ['main.cc'],
+ },
+ {
+ 'target_name': 'final_no_uldi',
+ 'type': 'executable',
+ 'dependencies': [
+ 'lib1',
+ 'lib2',
+ ],
+ 'sources': ['main.cc'],
+ },
+ {
+ 'target_name': 'lib2',
+ 'type': 'static_library',
+ # b.cc has the same named function as a.cc, but don't use the same name
+ # so that the .obj will have a different name. If the obj file has the
+ # same name, the linker will discard the obj file, invalidating the
+ # test.
+ 'sources': ['b.cc'],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/vs-macros/containing-gyp.gyp b/chromium/tools/gyp/test/win/vs-macros/containing-gyp.gyp
new file mode 100644
index 00000000000..fa799a4e4e5
--- /dev/null
+++ b/chromium/tools/gyp/test/win/vs-macros/containing-gyp.gyp
@@ -0,0 +1,40 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_expansions',
+ 'msvs_cygwin_shell': 0,
+ 'type': 'none',
+ 'rules': [
+ {
+ 'rule_name': 'assembler (gnu-compatible)',
+ 'msvs_cygwin_shell': 0,
+ 'msvs_quote_cmd': 0,
+ 'extension': 'S',
+ 'inputs': [
+ 'as.py',
+ '$(InputPath)'
+ ],
+ 'outputs': [
+ '$(IntDir)/$(InputName).obj',
+ ],
+ 'action':
+ ['python',
+ 'as.py',
+ '-a', '$(PlatformName)',
+ '-o', '$(IntDir)/$(InputName).obj',
+ '-p', '<(DEPTH)',
+ '$(InputPath)'],
+ 'message': 'Building assembly language file $(InputPath)',
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ 'sources': [
+ 'input.S',
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/vs-macros/input-output-macros.gyp b/chromium/tools/gyp/test/win/vs-macros/input-output-macros.gyp
new file mode 100644
index 00000000000..b7a3c1e3bde
--- /dev/null
+++ b/chromium/tools/gyp/test/win/vs-macros/input-output-macros.gyp
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_expansions',
+ 'msvs_cygwin_shell': 0,
+ 'type': 'none',
+ 'rules': [
+ {
+ 'rule_name': 'generate_file',
+ 'extension': 'blah',
+ 'inputs': [
+ '<(RULE_INPUT_PATH)',
+ 'do_stuff.py',
+ ],
+ 'outputs': [
+ '$(OutDir)\\<(RULE_INPUT_NAME).something',
+ ],
+ 'action': ['python',
+ 'do_stuff.py',
+ '<(RULE_INPUT_PATH)',
+ '$(OutDir)\\<(RULE_INPUT_NAME).something',],
+ },
+ ],
+ 'sources': [
+ 'stuff.blah',
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/vs-macros/projectname.gyp b/chromium/tools/gyp/test/win/vs-macros/projectname.gyp
new file mode 100644
index 00000000000..625a1776435
--- /dev/null
+++ b/chromium/tools/gyp/test/win/vs-macros/projectname.gyp
@@ -0,0 +1,29 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_expansions',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(OutDir)\\$(ProjectName)_plus_something.exe',
+ },
+ },
+ },
+ {
+ 'target_name': 'test_with_product_name',
+ 'product_name': 'prod_name',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(OutDir)\\$(ProjectName)_plus_something.exe',
+ },
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/vs-macros/targetname.gyp b/chromium/tools/gyp/test/win/vs-macros/targetname.gyp
new file mode 100644
index 00000000000..a53d3c0aa3b
--- /dev/null
+++ b/chromium/tools/gyp/test/win/vs-macros/targetname.gyp
@@ -0,0 +1,52 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_targetname',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(TargetDir)\\$(TargetName)_plus_something1.exe',
+ },
+ },
+ },
+ {
+ 'target_name': 'test_targetname_with_prefix',
+ 'product_prefix': 'prod_prefix',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(TargetDir)\\$(TargetName)_plus_something2.exe',
+ },
+ },
+ },
+ {
+ 'target_name': 'test_targetname_with_prodname',
+ 'product_name': 'prod_name',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(TargetDir)\\$(TargetName)_plus_something3.exe',
+ },
+ },
+ },
+ {
+ 'target_name': 'test_targetname_with_prodname_with_prefix',
+ 'product_name': 'prod_name',
+ 'product_prefix': 'prod_prefix',
+ 'type': 'executable',
+ 'sources': ['hello.cc'],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'OutputFile': '$(TargetDir)\\$(TargetName)_plus_something4.exe',
+ },
+ },
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/test/win/vs-macros/vcinstalldir.gyp b/chromium/tools/gyp/test/win/vs-macros/vcinstalldir.gyp
new file mode 100644
index 00000000000..3763a4eb182
--- /dev/null
+++ b/chromium/tools/gyp/test/win/vs-macros/vcinstalldir.gyp
@@ -0,0 +1,41 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_slash_trailing',
+ 'type': 'none',
+ 'msvs_cygwin_shell': '0',
+ 'actions': [
+ {
+ 'action_name': 'root',
+ 'inputs': [],
+ 'outputs': ['out1'],
+ 'action': ['python', 'test_exists.py', '$(VCInstallDir)', 'out1']
+ },
+ ],
+ },
+ {
+ 'target_name': 'test_slash_dir',
+ 'type': 'none',
+ 'msvs_cygwin_shell': '0',
+ 'actions': [
+ {
+ 'action_name': 'bin',
+ 'inputs': [],
+ 'outputs': ['out2'],
+ 'action': ['python', 'test_exists.py', '$(VCInstallDir)bin', 'out2'],
+ },
+ {
+ 'action_name': 'compiler',
+ 'inputs': [],
+ 'outputs': ['out3'],
+ 'action': [
+ 'python', 'test_exists.py', '$(VCInstallDir)bin\\cl.exe', 'out3'],
+ },
+ ],
+ },
+ ]
+}
diff --git a/chromium/tools/gyp/tools/README b/chromium/tools/gyp/tools/README
new file mode 100644
index 00000000000..712e4efbb7a
--- /dev/null
+++ b/chromium/tools/gyp/tools/README
@@ -0,0 +1,15 @@
+pretty_vcproj:
+ Usage: pretty_vcproj.py "c:\path\to\vcproj.vcproj" [key1=value1] [key2=value2]
+
+ They key/value pair are used to resolve vsprops name.
+
+ For example, if I want to diff the base.vcproj project:
+
+ pretty_vcproj.py z:\dev\src-chrome\src\base\build\base.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > orignal.txt
+ pretty_vcproj.py z:\dev\src-chrome\src\base\base_gyp.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > gyp.txt
+
+ And you can use your favorite diff tool to see the changes.
+
+ Note: In the case of base.vcproj, the original vcproj is one level up the generated one.
+ I suggest you do a search and replace for '"..\' and replace it with '"' in original.txt
+ before you perform the diff. \ No newline at end of file
diff --git a/chromium/tools/gyp/tools/Xcode/README b/chromium/tools/gyp/tools/Xcode/README
new file mode 100644
index 00000000000..2492a2c2f8f
--- /dev/null
+++ b/chromium/tools/gyp/tools/Xcode/README
@@ -0,0 +1,5 @@
+Specifications contains syntax formatters for Xcode 3. These do not appear to be supported yet on Xcode 4. To use these with Xcode 3 please install both the gyp.pbfilespec and gyp.xclangspec files in
+
+~/Library/Application Support/Developer/Shared/Xcode/Specifications/
+
+and restart Xcode. \ No newline at end of file
diff --git a/chromium/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec b/chromium/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec
new file mode 100644
index 00000000000..85e2e268a51
--- /dev/null
+++ b/chromium/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec
@@ -0,0 +1,27 @@
+/*
+ gyp.pbfilespec
+ GYP source file spec for Xcode 3
+
+ There is not much documentation available regarding the format
+ of .pbfilespec files. As a starting point, see for instance the
+ outdated documentation at:
+ http://maxao.free.fr/xcode-plugin-interface/specifications.html
+ and the files in:
+ /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/
+
+ Place this file in directory:
+ ~/Library/Application Support/Developer/Shared/Xcode/Specifications/
+*/
+
+(
+ {
+ Identifier = sourcecode.gyp;
+ BasedOn = sourcecode;
+ Name = "GYP Files";
+ Extensions = ("gyp", "gypi");
+ MIMETypes = ("text/gyp");
+ Language = "xcode.lang.gyp";
+ IsTextFile = YES;
+ IsSourceFile = YES;
+ }
+)
diff --git a/chromium/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec b/chromium/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec
new file mode 100644
index 00000000000..3b3506d319e
--- /dev/null
+++ b/chromium/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec
@@ -0,0 +1,226 @@
+/*
+ Copyright (c) 2011 Google Inc. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+
+ gyp.xclangspec
+ GYP language specification for Xcode 3
+
+ There is not much documentation available regarding the format
+ of .xclangspec files. As a starting point, see for instance the
+ outdated documentation at:
+ http://maxao.free.fr/xcode-plugin-interface/specifications.html
+ and the files in:
+ /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/
+
+ Place this file in directory:
+ ~/Library/Application Support/Developer/Shared/Xcode/Specifications/
+*/
+
+(
+
+ {
+ Identifier = "xcode.lang.gyp.keyword";
+ Syntax = {
+ Words = (
+ "and",
+ "or",
+ "<!",
+ "<",
+ );
+ Type = "xcode.syntax.keyword";
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.target.declarator";
+ Syntax = {
+ Words = (
+ "'target_name'",
+ );
+ Type = "xcode.syntax.identifier.type";
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.string.singlequote";
+ Syntax = {
+ IncludeRules = (
+ "xcode.lang.string",
+ "xcode.lang.gyp.keyword",
+ "xcode.lang.number",
+ );
+ Start = "'";
+ End = "'";
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.comma";
+ Syntax = {
+ Words = ( ",", );
+
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp";
+ Description = "GYP Coloring";
+ BasedOn = "xcode.lang.simpleColoring";
+ IncludeInMenu = YES;
+ Name = "GYP";
+ Syntax = {
+ Tokenizer = "xcode.lang.gyp.lexer.toplevel";
+ IncludeRules = (
+ "xcode.lang.gyp.dictionary",
+ );
+ Type = "xcode.syntax.plain";
+ };
+ },
+
+ // The following rule returns tokens to the other rules
+ {
+ Identifier = "xcode.lang.gyp.lexer";
+ Syntax = {
+ IncludeRules = (
+ "xcode.lang.gyp.comment",
+ "xcode.lang.string",
+ 'xcode.lang.gyp.targetname.declarator',
+ "xcode.lang.gyp.string.singlequote",
+ "xcode.lang.number",
+ "xcode.lang.gyp.comma",
+ );
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.lexer.toplevel";
+ Syntax = {
+ IncludeRules = (
+ "xcode.lang.gyp.comment",
+ );
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.assignment";
+ Syntax = {
+ Tokenizer = "xcode.lang.gyp.lexer";
+ Rules = (
+ "xcode.lang.gyp.assignment.lhs",
+ ":",
+ "xcode.lang.gyp.assignment.rhs",
+ );
+ };
+
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.target.declaration";
+ Syntax = {
+ Tokenizer = "xcode.lang.gyp.lexer";
+ Rules = (
+ "xcode.lang.gyp.target.declarator",
+ ":",
+ "xcode.lang.gyp.target.name",
+ );
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.target.name";
+ Syntax = {
+ Tokenizer = "xcode.lang.gyp.lexer";
+ Rules = (
+ "xcode.lang.gyp.string.singlequote",
+ );
+ Type = "xcode.syntax.definition.function";
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.assignment.lhs";
+ Syntax = {
+ Tokenizer = "xcode.lang.gyp.lexer";
+ Rules = (
+ "xcode.lang.gyp.string.singlequote",
+ );
+ Type = "xcode.syntax.identifier.type";
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.assignment.rhs";
+ Syntax = {
+ Tokenizer = "xcode.lang.gyp.lexer";
+ Rules = (
+ "xcode.lang.gyp.string.singlequote?",
+ "xcode.lang.gyp.array?",
+ "xcode.lang.gyp.dictionary?",
+ "xcode.lang.number?",
+ );
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.dictionary";
+ Syntax = {
+ Tokenizer = "xcode.lang.gyp.lexer";
+ Start = "{";
+ End = "}";
+ Foldable = YES;
+ Recursive = YES;
+ IncludeRules = (
+ "xcode.lang.gyp.target.declaration",
+ "xcode.lang.gyp.assignment",
+ );
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.array";
+ Syntax = {
+ Tokenizer = "xcode.lang.gyp.lexer";
+ Start = "[";
+ End = "]";
+ Foldable = YES;
+ Recursive = YES;
+ IncludeRules = (
+ "xcode.lang.gyp.array",
+ "xcode.lang.gyp.dictionary",
+ "xcode.lang.gyp.string.singlequote",
+ );
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.todo.mark";
+ Syntax = {
+ StartChars = "T";
+ Match = (
+ "^\(TODO\(.*\):[ \t]+.*\)$", // include "TODO: " in the markers list
+ );
+ // This is the order of captures. All of the match strings above need the same order.
+ CaptureTypes = (
+ "xcode.syntax.mark"
+ );
+ Type = "xcode.syntax.comment";
+ };
+ },
+
+ {
+ Identifier = "xcode.lang.gyp.comment";
+ BasedOn = "xcode.lang.comment"; // for text macros
+ Syntax = {
+ Start = "#";
+ End = "\n";
+ IncludeRules = (
+ "xcode.lang.url",
+ "xcode.lang.url.mail",
+ "xcode.lang.comment.mark",
+ "xcode.lang.gyp.todo.mark",
+ );
+ Type = "xcode.syntax.comment";
+ };
+ },
+)
diff --git a/chromium/tools/gyp/tools/emacs/README b/chromium/tools/gyp/tools/emacs/README
new file mode 100644
index 00000000000..eeef39f41b7
--- /dev/null
+++ b/chromium/tools/gyp/tools/emacs/README
@@ -0,0 +1,12 @@
+How to install gyp-mode for emacs:
+
+Add the following to your ~/.emacs (replace ... with the path to your gyp
+checkout).
+
+(setq load-path (cons ".../tools/emacs" load-path))
+(require 'gyp)
+
+Restart emacs (or eval-region the added lines) and you should be all set.
+
+Please note that ert is required for running the tests, which is included in
+Emacs 24, or available separately from https://github.com/ohler/ert
diff --git a/chromium/tools/gyp/tools/emacs/gyp-tests.el b/chromium/tools/gyp/tools/emacs/gyp-tests.el
new file mode 100644
index 00000000000..11b84978860
--- /dev/null
+++ b/chromium/tools/gyp/tools/emacs/gyp-tests.el
@@ -0,0 +1,63 @@
+;;; gyp-tests.el - unit tests for gyp-mode.
+
+;; Copyright (c) 2012 Google Inc. All rights reserved.
+;; Use of this source code is governed by a BSD-style license that can be
+;; found in the LICENSE file.
+
+;; The recommended way to run these tests is to run them from the command-line,
+;; with the run-unit-tests.sh script.
+
+(require 'cl)
+(require 'ert)
+(require 'gyp)
+
+(defconst samples (directory-files "testdata" t ".gyp$")
+ "List of golden samples to check")
+
+(defun fontify (filename)
+ (with-temp-buffer
+ (insert-file-contents-literally filename)
+ (gyp-mode)
+ (font-lock-fontify-buffer)
+ (buffer-string)))
+
+(defun read-golden-sample (filename)
+ (with-temp-buffer
+ (insert-file-contents-literally (concat filename ".fontified"))
+ (read (current-buffer))))
+
+(defun equivalent-face (face)
+ "For the purposes of face comparison, we're not interested in the
+ differences between certain faces. For example, the difference between
+ font-lock-comment-delimiter and font-lock-comment-face."
+ (case face
+ ((font-lock-comment-delimiter-face) font-lock-comment-face)
+ (t face)))
+
+(defun text-face-properties (s)
+ "Extract the text properties from s"
+ (let ((result (list t)))
+ (dotimes (i (length s))
+ (setq result (cons (equivalent-face (get-text-property i 'face s))
+ result)))
+ (nreverse result)))
+
+(ert-deftest test-golden-samples ()
+ "Check that fontification produces the same results as the golden samples"
+ (dolist (sample samples)
+ (let ((golden (read-golden-sample sample))
+ (fontified (fontify sample)))
+ (should (equal golden fontified))
+ (should (equal (text-face-properties golden)
+ (text-face-properties fontified))))))
+
+(defun create-golden-sample (filename)
+ "Create a golden sample by fontifying filename and writing out the printable
+ representation of the fontified buffer (with text properties) to the
+ FILENAME.fontified"
+ (with-temp-file (concat filename ".fontified")
+ (print (fontify filename) (current-buffer))))
+
+(defun create-golden-samples ()
+ "Recreate the golden samples"
+ (dolist (sample samples) (create-golden-sample sample)))
diff --git a/chromium/tools/gyp/tools/emacs/gyp.el b/chromium/tools/gyp/tools/emacs/gyp.el
new file mode 100644
index 00000000000..f558b53135f
--- /dev/null
+++ b/chromium/tools/gyp/tools/emacs/gyp.el
@@ -0,0 +1,251 @@
+;;; gyp.el - font-lock-mode support for gyp files.
+
+;; Copyright (c) 2012 Google Inc. All rights reserved.
+;; Use of this source code is governed by a BSD-style license that can be
+;; found in the LICENSE file.
+
+;; Put this somewhere in your load-path and
+;; (require 'gyp)
+
+(require 'python)
+(require 'cl)
+
+(when (string-match "python-mode.el" (symbol-file 'python-mode 'defun))
+ (error (concat "python-mode must be loaded from python.el (bundled with "
+ "recent emacsen), not from the older and less maintained "
+ "python-mode.el")))
+
+(defadvice python-calculate-indentation (after ami-outdent-closing-parens
+ activate)
+ "De-indent closing parens, braces, and brackets in gyp-mode."
+ (if (and (eq major-mode 'gyp-mode)
+ (string-match "^ *[])}][],)}]* *$"
+ (buffer-substring-no-properties
+ (line-beginning-position) (line-end-position))))
+ (setq ad-return-value (- ad-return-value 2))))
+
+(define-derived-mode gyp-mode python-mode "Gyp"
+ "Major mode for editing .gyp files. See http://code.google.com/p/gyp/"
+ ;; gyp-parse-history is a stack of (POSITION . PARSE-STATE) tuples,
+ ;; with greater positions at the top of the stack. PARSE-STATE
+ ;; is a list of section symbols (see gyp-section-name and gyp-parse-to)
+ ;; with most nested section symbol at the front of the list.
+ (set (make-local-variable 'gyp-parse-history) '((1 . (list))))
+ (gyp-add-font-lock-keywords))
+
+(defun gyp-set-indentation ()
+ "Hook function to configure python indentation to suit gyp mode."
+ (setq python-continuation-offset 2
+ python-indent 2
+ python-guess-indent nil))
+
+(add-hook 'gyp-mode-hook 'gyp-set-indentation)
+
+(add-to-list 'auto-mode-alist '("\\.gyp\\'" . gyp-mode))
+(add-to-list 'auto-mode-alist '("\\.gypi\\'" . gyp-mode))
+
+;;; Font-lock support
+
+(defconst gyp-dependencies-regexp
+ (regexp-opt (list "dependencies" "export_dependent_settings"))
+ "Regular expression to introduce 'dependencies' section")
+
+(defconst gyp-sources-regexp
+ (regexp-opt (list "action" "files" "include_dirs" "includes" "inputs"
+ "libraries" "outputs" "sources"))
+ "Regular expression to introduce 'sources' sections")
+
+(defconst gyp-conditions-regexp
+ (regexp-opt (list "conditions" "target_conditions"))
+ "Regular expression to introduce conditions sections")
+
+(defconst gyp-variables-regexp
+ "^variables"
+ "Regular expression to introduce variables sections")
+
+(defconst gyp-defines-regexp
+ "^defines"
+ "Regular expression to introduce 'defines' sections")
+
+(defconst gyp-targets-regexp
+ "^targets"
+ "Regular expression to introduce 'targets' sections")
+
+(defun gyp-section-name (section)
+ "Map the sections we are interested in from SECTION to symbol.
+
+ SECTION is a string from the buffer that introduces a section. The result is
+ a symbol representing the kind of section.
+
+ This allows us to treat (for the purposes of font-lock) several different
+ section names as the same kind of section. For example, a 'sources section
+ can be introduced by the 'sources', 'inputs', 'outputs' keyword.
+
+ 'other is the default section kind when a more specific match is not made."
+ (cond ((string-match-p gyp-dependencies-regexp section) 'dependencies)
+ ((string-match-p gyp-sources-regexp section) 'sources)
+ ((string-match-p gyp-variables-regexp section) 'variables)
+ ((string-match-p gyp-conditions-regexp section) 'conditions)
+ ((string-match-p gyp-targets-regexp section) 'targets)
+ ((string-match-p gyp-defines-regexp section) 'defines)
+ (t 'other)))
+
+(defun gyp-invalidate-parse-states-after (target-point)
+ "Erase any parse information after target-point."
+ (while (> (caar gyp-parse-history) target-point)
+ (setq gyp-parse-history (cdr gyp-parse-history))))
+
+(defun gyp-parse-point ()
+ "The point of the last parse state added by gyp-parse-to."
+ (caar gyp-parse-history))
+
+(defun gyp-parse-sections ()
+ "A list of section symbols holding at the last parse state point."
+ (cdar gyp-parse-history))
+
+(defun gyp-inside-dictionary-p ()
+ "Predicate returning true if the parser is inside a dictionary."
+ (not (eq (cadar gyp-parse-history) 'list)))
+
+(defun gyp-add-parse-history (point sections)
+ "Add parse state SECTIONS to the parse history at POINT so that parsing can be
+ resumed instantly."
+ (while (>= (caar gyp-parse-history) point)
+ (setq gyp-parse-history (cdr gyp-parse-history)))
+ (setq gyp-parse-history (cons (cons point sections) gyp-parse-history)))
+
+(defun gyp-parse-to (target-point)
+ "Parses from (point) to TARGET-POINT adding the parse state information to
+ gyp-parse-state-history. Parsing stops if TARGET-POINT is reached or if a
+ string literal has been parsed. Returns nil if no further parsing can be
+ done, otherwise returns the position of the start of a parsed string, leaving
+ the point at the end of the string."
+ (let ((parsing t)
+ string-start)
+ (while parsing
+ (setq string-start nil)
+ ;; Parse up to a character that starts a sexp, or if the nesting
+ ;; level decreases.
+ (let ((state (parse-partial-sexp (gyp-parse-point)
+ target-point
+ -1
+ t))
+ (sections (gyp-parse-sections)))
+ (if (= (nth 0 state) -1)
+ (setq sections (cdr sections)) ; pop out a level
+ (cond ((looking-at-p "['\"]") ; a string
+ (setq string-start (point))
+ (goto-char (scan-sexps (point) 1))
+ (if (gyp-inside-dictionary-p)
+ ;; Look for sections inside a dictionary
+ (let ((section (gyp-section-name
+ (buffer-substring-no-properties
+ (+ 1 string-start)
+ (- (point) 1)))))
+ (setq sections (cons section (cdr sections)))))
+ ;; Stop after the string so it can be fontified.
+ (setq target-point (point)))
+ ((looking-at-p "{")
+ ;; Inside a dictionary. Increase nesting.
+ (forward-char 1)
+ (setq sections (cons 'unknown sections)))
+ ((looking-at-p "\\[")
+ ;; Inside a list. Increase nesting
+ (forward-char 1)
+ (setq sections (cons 'list sections)))
+ ((not (eobp))
+ ;; other
+ (forward-char 1))))
+ (gyp-add-parse-history (point) sections)
+ (setq parsing (< (point) target-point))))
+ string-start))
+
+(defun gyp-section-at-point ()
+ "Transform the last parse state, which is a list of nested sections and return
+ the section symbol that should be used to determine font-lock information for
+ the string. Can return nil indicating the string should not have any attached
+ section."
+ (let ((sections (gyp-parse-sections)))
+ (cond
+ ((eq (car sections) 'conditions)
+ ;; conditions can occur in a variables section, but we still want to
+ ;; highlight it as a keyword.
+ nil)
+ ((and (eq (car sections) 'list)
+ (eq (cadr sections) 'list))
+ ;; conditions and sources can have items in [[ ]]
+ (caddr sections))
+ (t (cadr sections)))))
+
+(defun gyp-section-match (limit)
+ "Parse from (point) to LIMIT returning by means of match data what was
+ matched. The group of the match indicates what style font-lock should apply.
+ See also `gyp-add-font-lock-keywords'."
+ (gyp-invalidate-parse-states-after (point))
+ (let ((group nil)
+ (string-start t))
+ (while (and (< (point) limit)
+ (not group)
+ string-start)
+ (setq string-start (gyp-parse-to limit))
+ (if string-start
+ (setq group (case (gyp-section-at-point)
+ ('dependencies 1)
+ ('variables 2)
+ ('conditions 2)
+ ('sources 3)
+ ('defines 4)
+ (nil nil)))))
+ (if group
+ (progn
+ ;; Set the match data to indicate to the font-lock mechanism the
+ ;; highlighting to be performed.
+ (set-match-data (append (list string-start (point))
+ (make-list (* (1- group) 2) nil)
+ (list (1+ string-start) (1- (point)))))
+ t))))
+
+;;; Please see http://code.google.com/p/gyp/wiki/GypLanguageSpecification for
+;;; canonical list of keywords.
+(defun gyp-add-font-lock-keywords ()
+ "Add gyp-mode keywords to font-lock mechanism."
+ ;; TODO(jknotten): Move all the keyword highlighting into gyp-section-match
+ ;; so that we can do the font-locking in a single font-lock pass.
+ (font-lock-add-keywords
+ nil
+ (list
+ ;; Top-level keywords
+ (list (concat "['\"]\\("
+ (regexp-opt (list "action" "action_name" "actions" "cflags"
+ "conditions" "configurations" "copies" "defines"
+ "dependencies" "destination"
+ "direct_dependent_settings"
+ "export_dependent_settings" "extension" "files"
+ "include_dirs" "includes" "inputs" "libraries"
+ "link_settings" "mac_bundle" "message"
+ "msvs_external_rule" "outputs" "product_name"
+ "process_outputs_as_sources" "rules" "rule_name"
+ "sources" "suppress_wildcard"
+ "target_conditions" "target_defaults"
+ "target_defines" "target_name" "toolsets"
+ "targets" "type" "variables" "xcode_settings"))
+ "[!/+=]?\\)") 1 'font-lock-keyword-face t)
+ ;; Type of target
+ (list (concat "['\"]\\("
+ (regexp-opt (list "loadable_module" "static_library"
+ "shared_library" "executable" "none"))
+ "\\)") 1 'font-lock-type-face t)
+ (list "\\(?:target\\|action\\)_name['\"]\\s-*:\\s-*['\"]\\([^ '\"]*\\)" 1
+ 'font-lock-function-name-face t)
+ (list 'gyp-section-match
+ (list 1 'font-lock-function-name-face t t) ; dependencies
+ (list 2 'font-lock-variable-name-face t t) ; variables, conditions
+ (list 3 'font-lock-constant-face t t) ; sources
+ (list 4 'font-lock-preprocessor-face t t)) ; preprocessor
+ ;; Variable expansion
+ (list "<@?(\\([^\n )]+\\))" 1 'font-lock-variable-name-face t)
+ ;; Command expansion
+ (list "<!@?(\\([^\n )]+\\))" 1 'font-lock-variable-name-face t)
+ )))
+
+(provide 'gyp)
diff --git a/chromium/tools/gyp/tools/emacs/run-unit-tests.sh b/chromium/tools/gyp/tools/emacs/run-unit-tests.sh
new file mode 100755
index 00000000000..6e62b9b28cb
--- /dev/null
+++ b/chromium/tools/gyp/tools/emacs/run-unit-tests.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+emacs --no-site-file --no-init-file --batch \
+ --load ert.el --load gyp.el --load gyp-tests.el \
+ -f ert-run-tests-batch-and-exit
diff --git a/chromium/tools/gyp/tools/emacs/testdata/media.gyp b/chromium/tools/gyp/tools/emacs/testdata/media.gyp
new file mode 100644
index 00000000000..29300fe1b89
--- /dev/null
+++ b/chromium/tools/gyp/tools/emacs/testdata/media.gyp
@@ -0,0 +1,1105 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ # Override to dynamically link the PulseAudio library.
+ 'use_pulseaudio%': 0,
+ # Override to dynamically link the cras (ChromeOS audio) library.
+ 'use_cras%': 0,
+ },
+ 'targets': [
+ {
+ 'target_name': 'media',
+ 'type': '<(component)',
+ 'dependencies': [
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../build/temp_gyp/googleurl.gyp:googleurl',
+ '../crypto/crypto.gyp:crypto',
+ '../third_party/openmax/openmax.gyp:il',
+ '../ui/ui.gyp:ui',
+ ],
+ 'defines': [
+ 'MEDIA_IMPLEMENTATION',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'audio/android/audio_manager_android.cc',
+ 'audio/android/audio_manager_android.h',
+ 'audio/android/audio_track_output_android.cc',
+ 'audio/android/audio_track_output_android.h',
+ 'audio/android/opensles_input.cc',
+ 'audio/android/opensles_input.h',
+ 'audio/android/opensles_output.cc',
+ 'audio/android/opensles_output.h',
+ 'audio/async_socket_io_handler.h',
+ 'audio/async_socket_io_handler_posix.cc',
+ 'audio/async_socket_io_handler_win.cc',
+ 'audio/audio_buffers_state.cc',
+ 'audio/audio_buffers_state.h',
+ 'audio/audio_io.h',
+ 'audio/audio_input_controller.cc',
+ 'audio/audio_input_controller.h',
+ 'audio/audio_input_stream_impl.cc',
+ 'audio/audio_input_stream_impl.h',
+ 'audio/audio_device_name.cc',
+ 'audio/audio_device_name.h',
+ 'audio/audio_manager.cc',
+ 'audio/audio_manager.h',
+ 'audio/audio_manager_base.cc',
+ 'audio/audio_manager_base.h',
+ 'audio/audio_output_controller.cc',
+ 'audio/audio_output_controller.h',
+ 'audio/audio_output_dispatcher.cc',
+ 'audio/audio_output_dispatcher.h',
+ 'audio/audio_output_dispatcher_impl.cc',
+ 'audio/audio_output_dispatcher_impl.h',
+ 'audio/audio_output_mixer.cc',
+ 'audio/audio_output_mixer.h',
+ 'audio/audio_output_proxy.cc',
+ 'audio/audio_output_proxy.h',
+ 'audio/audio_parameters.cc',
+ 'audio/audio_parameters.h',
+ 'audio/audio_util.cc',
+ 'audio/audio_util.h',
+ 'audio/cross_process_notification.cc',
+ 'audio/cross_process_notification.h',
+ 'audio/cross_process_notification_win.cc',
+ 'audio/cross_process_notification_posix.cc',
+ 'audio/fake_audio_input_stream.cc',
+ 'audio/fake_audio_input_stream.h',
+ 'audio/fake_audio_output_stream.cc',
+ 'audio/fake_audio_output_stream.h',
+ 'audio/linux/audio_manager_linux.cc',
+ 'audio/linux/audio_manager_linux.h',
+ 'audio/linux/alsa_input.cc',
+ 'audio/linux/alsa_input.h',
+ 'audio/linux/alsa_output.cc',
+ 'audio/linux/alsa_output.h',
+ 'audio/linux/alsa_util.cc',
+ 'audio/linux/alsa_util.h',
+ 'audio/linux/alsa_wrapper.cc',
+ 'audio/linux/alsa_wrapper.h',
+ 'audio/linux/cras_output.cc',
+ 'audio/linux/cras_output.h',
+ 'audio/openbsd/audio_manager_openbsd.cc',
+ 'audio/openbsd/audio_manager_openbsd.h',
+ 'audio/mac/audio_input_mac.cc',
+ 'audio/mac/audio_input_mac.h',
+ 'audio/mac/audio_low_latency_input_mac.cc',
+ 'audio/mac/audio_low_latency_input_mac.h',
+ 'audio/mac/audio_low_latency_output_mac.cc',
+ 'audio/mac/audio_low_latency_output_mac.h',
+ 'audio/mac/audio_manager_mac.cc',
+ 'audio/mac/audio_manager_mac.h',
+ 'audio/mac/audio_output_mac.cc',
+ 'audio/mac/audio_output_mac.h',
+ 'audio/null_audio_sink.cc',
+ 'audio/null_audio_sink.h',
+ 'audio/pulse/pulse_output.cc',
+ 'audio/pulse/pulse_output.h',
+ 'audio/sample_rates.cc',
+ 'audio/sample_rates.h',
+ 'audio/simple_sources.cc',
+ 'audio/simple_sources.h',
+ 'audio/win/audio_low_latency_input_win.cc',
+ 'audio/win/audio_low_latency_input_win.h',
+ 'audio/win/audio_low_latency_output_win.cc',
+ 'audio/win/audio_low_latency_output_win.h',
+ 'audio/win/audio_manager_win.cc',
+ 'audio/win/audio_manager_win.h',
+ 'audio/win/avrt_wrapper_win.cc',
+ 'audio/win/avrt_wrapper_win.h',
+ 'audio/win/device_enumeration_win.cc',
+ 'audio/win/device_enumeration_win.h',
+ 'audio/win/wavein_input_win.cc',
+ 'audio/win/wavein_input_win.h',
+ 'audio/win/waveout_output_win.cc',
+ 'audio/win/waveout_output_win.h',
+ 'base/android/media_jni_registrar.cc',
+ 'base/android/media_jni_registrar.h',
+ 'base/audio_decoder.cc',
+ 'base/audio_decoder.h',
+ 'base/audio_decoder_config.cc',
+ 'base/audio_decoder_config.h',
+ 'base/audio_renderer.h',
+ 'base/audio_renderer_mixer.cc',
+ 'base/audio_renderer_mixer.h',
+ 'base/audio_renderer_mixer_input.cc',
+ 'base/audio_renderer_mixer_input.h',
+ 'base/bitstream_buffer.h',
+ 'base/buffers.cc',
+ 'base/buffers.h',
+ 'base/byte_queue.cc',
+ 'base/byte_queue.h',
+ 'base/channel_layout.cc',
+ 'base/channel_layout.h',
+ 'base/clock.cc',
+ 'base/clock.h',
+ 'base/composite_filter.cc',
+ 'base/composite_filter.h',
+ 'base/data_buffer.cc',
+ 'base/data_buffer.h',
+ 'base/data_source.cc',
+ 'base/data_source.h',
+ 'base/decoder_buffer.cc',
+ 'base/decoder_buffer.h',
+ 'base/decrypt_config.cc',
+ 'base/decrypt_config.h',
+ 'base/decryptor.h',
+ 'base/decryptor_client.h',
+ 'base/demuxer.cc',
+ 'base/demuxer.h',
+ 'base/demuxer_stream.cc',
+ 'base/demuxer_stream.h',
+ 'base/djb2.cc',
+ 'base/djb2.h',
+ 'base/filter_collection.cc',
+ 'base/filter_collection.h',
+ 'base/filter_host.h',
+ 'base/filters.cc',
+ 'base/filters.h',
+ 'base/h264_bitstream_converter.cc',
+ 'base/h264_bitstream_converter.h',
+ 'base/media.h',
+ 'base/media_android.cc',
+ 'base/media_export.h',
+ 'base/media_log.cc',
+ 'base/media_log.h',
+ 'base/media_log_event.h',
+ 'base/media_posix.cc',
+ 'base/media_switches.cc',
+ 'base/media_switches.h',
+ 'base/media_win.cc',
+ 'base/message_loop_factory.cc',
+ 'base/message_loop_factory.h',
+ 'base/pipeline.cc',
+ 'base/pipeline.h',
+ 'base/pipeline_status.cc',
+ 'base/pipeline_status.h',
+ 'base/ranges.cc',
+ 'base/ranges.h',
+ 'base/seekable_buffer.cc',
+ 'base/seekable_buffer.h',
+ 'base/state_matrix.cc',
+ 'base/state_matrix.h',
+ 'base/stream_parser.cc',
+ 'base/stream_parser.h',
+ 'base/stream_parser_buffer.cc',
+ 'base/stream_parser_buffer.h',
+ 'base/video_decoder.cc',
+ 'base/video_decoder.h',
+ 'base/video_decoder_config.cc',
+ 'base/video_decoder_config.h',
+ 'base/video_frame.cc',
+ 'base/video_frame.h',
+ 'base/video_renderer.h',
+ 'base/video_util.cc',
+ 'base/video_util.h',
+ 'crypto/aes_decryptor.cc',
+ 'crypto/aes_decryptor.h',
+ 'ffmpeg/ffmpeg_common.cc',
+ 'ffmpeg/ffmpeg_common.h',
+ 'ffmpeg/file_protocol.cc',
+ 'ffmpeg/file_protocol.h',
+ 'filters/audio_file_reader.cc',
+ 'filters/audio_file_reader.h',
+ 'filters/audio_renderer_algorithm.cc',
+ 'filters/audio_renderer_algorithm.h',
+ 'filters/audio_renderer_impl.cc',
+ 'filters/audio_renderer_impl.h',
+ 'filters/bitstream_converter.cc',
+ 'filters/bitstream_converter.h',
+ 'filters/chunk_demuxer.cc',
+ 'filters/chunk_demuxer.h',
+ 'filters/chunk_demuxer_client.h',
+ 'filters/dummy_demuxer.cc',
+ 'filters/dummy_demuxer.h',
+ 'filters/ffmpeg_audio_decoder.cc',
+ 'filters/ffmpeg_audio_decoder.h',
+ 'filters/ffmpeg_demuxer.cc',
+ 'filters/ffmpeg_demuxer.h',
+ 'filters/ffmpeg_h264_bitstream_converter.cc',
+ 'filters/ffmpeg_h264_bitstream_converter.h',
+ 'filters/ffmpeg_glue.cc',
+ 'filters/ffmpeg_glue.h',
+ 'filters/ffmpeg_video_decoder.cc',
+ 'filters/ffmpeg_video_decoder.h',
+ 'filters/file_data_source.cc',
+ 'filters/file_data_source.h',
+ 'filters/gpu_video_decoder.cc',
+ 'filters/gpu_video_decoder.h',
+ 'filters/in_memory_url_protocol.cc',
+ 'filters/in_memory_url_protocol.h',
+ 'filters/source_buffer_stream.cc',
+ 'filters/source_buffer_stream.h',
+ 'filters/video_frame_generator.cc',
+ 'filters/video_frame_generator.h',
+ 'filters/video_renderer_base.cc',
+ 'filters/video_renderer_base.h',
+ 'video/capture/fake_video_capture_device.cc',
+ 'video/capture/fake_video_capture_device.h',
+ 'video/capture/linux/video_capture_device_linux.cc',
+ 'video/capture/linux/video_capture_device_linux.h',
+ 'video/capture/mac/video_capture_device_mac.h',
+ 'video/capture/mac/video_capture_device_mac.mm',
+ 'video/capture/mac/video_capture_device_qtkit_mac.h',
+ 'video/capture/mac/video_capture_device_qtkit_mac.mm',
+ 'video/capture/video_capture.h',
+ 'video/capture/video_capture_device.h',
+ 'video/capture/video_capture_device_dummy.cc',
+ 'video/capture/video_capture_device_dummy.h',
+ 'video/capture/video_capture_proxy.cc',
+ 'video/capture/video_capture_proxy.h',
+ 'video/capture/video_capture_types.h',
+ 'video/capture/win/filter_base_win.cc',
+ 'video/capture/win/filter_base_win.h',
+ 'video/capture/win/pin_base_win.cc',
+ 'video/capture/win/pin_base_win.h',
+ 'video/capture/win/sink_filter_observer_win.h',
+ 'video/capture/win/sink_filter_win.cc',
+ 'video/capture/win/sink_filter_win.h',
+ 'video/capture/win/sink_input_pin_win.cc',
+ 'video/capture/win/sink_input_pin_win.h',
+ 'video/capture/win/video_capture_device_win.cc',
+ 'video/capture/win/video_capture_device_win.h',
+ 'video/picture.cc',
+ 'video/picture.h',
+ 'video/video_decode_accelerator.cc',
+ 'video/video_decode_accelerator.h',
+ 'webm/webm_constants.h',
+ 'webm/webm_cluster_parser.cc',
+ 'webm/webm_cluster_parser.h',
+ 'webm/webm_content_encodings.cc',
+ 'webm/webm_content_encodings.h',
+ 'webm/webm_content_encodings_client.cc',
+ 'webm/webm_content_encodings_client.h',
+ 'webm/webm_info_parser.cc',
+ 'webm/webm_info_parser.h',
+ 'webm/webm_parser.cc',
+ 'webm/webm_parser.h',
+ 'webm/webm_stream_parser.cc',
+ 'webm/webm_stream_parser.h',
+ 'webm/webm_tracks_parser.cc',
+ 'webm/webm_tracks_parser.h',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ 'conditions': [
+ # Android doesn't use ffmpeg, so make the dependency conditional
+ # and exclude the sources which depend on ffmpeg.
+ ['OS != "android"', {
+ 'dependencies': [
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ }],
+ ['OS == "android"', {
+ 'sources!': [
+ 'base/media_posix.cc',
+ 'ffmpeg/ffmpeg_common.cc',
+ 'ffmpeg/ffmpeg_common.h',
+ 'ffmpeg/file_protocol.cc',
+ 'ffmpeg/file_protocol.h',
+ 'filters/audio_file_reader.cc',
+ 'filters/audio_file_reader.h',
+ 'filters/bitstream_converter.cc',
+ 'filters/bitstream_converter.h',
+ 'filters/chunk_demuxer.cc',
+ 'filters/chunk_demuxer.h',
+ 'filters/chunk_demuxer_client.h',
+ 'filters/ffmpeg_audio_decoder.cc',
+ 'filters/ffmpeg_audio_decoder.h',
+ 'filters/ffmpeg_demuxer.cc',
+ 'filters/ffmpeg_demuxer.h',
+ 'filters/ffmpeg_h264_bitstream_converter.cc',
+ 'filters/ffmpeg_h264_bitstream_converter.h',
+ 'filters/ffmpeg_glue.cc',
+ 'filters/ffmpeg_glue.h',
+ 'filters/ffmpeg_video_decoder.cc',
+ 'filters/ffmpeg_video_decoder.h',
+ 'filters/gpu_video_decoder.cc',
+ 'filters/gpu_video_decoder.h',
+ 'webm/webm_cluster_parser.cc',
+ 'webm/webm_cluster_parser.h',
+ 'webm/webm_stream_parser.cc',
+ 'webm/webm_stream_parser.h',
+ ],
+ }],
+ # The below 'android' condition were added temporarily and should be
+ # removed in downstream, because there is no Java environment setup in
+ # upstream yet.
+ ['OS == "android"', {
+ 'sources!':[
+ 'audio/android/audio_track_output_android.cc',
+ ],
+ 'sources':[
+ 'audio/android/audio_track_output_stub_android.cc',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-lOpenSLES',
+ ],
+ },
+ }],
+ ['OS=="linux" or OS=="freebsd" or OS=="solaris"', {
+ 'link_settings': {
+ 'libraries': [
+ '-lasound',
+ ],
+ },
+ }],
+ ['OS=="openbsd"', {
+ 'sources/': [ ['exclude', '/alsa_' ],
+ ['exclude', '/audio_manager_linux' ] ],
+ 'link_settings': {
+ 'libraries': [
+ ],
+ },
+ }],
+ ['OS!="openbsd"', {
+ 'sources!': [
+ 'audio/openbsd/audio_manager_openbsd.cc',
+ 'audio/openbsd/audio_manager_openbsd.h',
+ ],
+ }],
+ ['OS=="linux"', {
+ 'variables': {
+ 'conditions': [
+ ['sysroot!=""', {
+ 'pkg-config': '../build/linux/pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
+ }, {
+ 'pkg-config': 'pkg-config'
+ }],
+ ],
+ },
+ 'conditions': [
+ ['use_cras == 1', {
+ 'cflags': [
+ '<!@(<(pkg-config) --cflags libcras)',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '<!@(<(pkg-config) --libs libcras)',
+ ],
+ },
+ 'defines': [
+ 'USE_CRAS',
+ ],
+ }, { # else: use_cras == 0
+ 'sources!': [
+ 'audio/linux/cras_output.cc',
+ 'audio/linux/cras_output.h',
+ ],
+ }],
+ ],
+ }],
+ ['os_posix == 1', {
+ 'conditions': [
+ ['use_pulseaudio == 1', {
+ 'cflags': [
+ '<!@(pkg-config --cflags libpulse)',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '<!@(pkg-config --libs-only-l libpulse)',
+ ],
+ },
+ 'defines': [
+ 'USE_PULSEAUDIO',
+ ],
+ }, { # else: use_pulseaudio == 0
+ 'sources!': [
+ 'audio/pulse/pulse_output.cc',
+ 'audio/pulse/pulse_output.h',
+ ],
+ }],
+ ],
+ }],
+ ['os_posix == 1 and OS != "android"', {
+ # Video capture isn't supported in Android yet.
+ 'sources!': [
+ 'video/capture/video_capture_device_dummy.cc',
+ 'video/capture/video_capture_device_dummy.h',
+ ],
+ }],
+ ['OS=="mac"', {
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/AudioUnit.framework',
+ '$(SDKROOT)/System/Library/Frameworks/AudioToolbox.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreAudio.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreVideo.framework',
+ '$(SDKROOT)/System/Library/Frameworks/QTKit.framework',
+ ],
+ },
+ }],
+ ['OS=="win"', {
+ 'sources!': [
+ 'audio/pulse/pulse_output.cc',
+ 'audio/pulse/pulse_output.h',
+ 'video/capture/video_capture_device_dummy.cc',
+ 'video/capture/video_capture_device_dummy.h',
+ ],
+ }],
+ ['proprietary_codecs==1 or branding=="Chrome"', {
+ 'sources': [
+ 'mp4/avc.cc',
+ 'mp4/avc.h',
+ 'mp4/box_definitions.cc',
+ 'mp4/box_definitions.h',
+ 'mp4/box_reader.cc',
+ 'mp4/box_reader.h',
+ 'mp4/cenc.cc',
+ 'mp4/cenc.h',
+ 'mp4/mp4_stream_parser.cc',
+ 'mp4/mp4_stream_parser.h',
+ 'mp4/offset_byte_queue.cc',
+ 'mp4/offset_byte_queue.h',
+ 'mp4/track_run_iterator.cc',
+ 'mp4/track_run_iterator.h',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'yuv_convert',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'conditions': [
+ ['order_profiling != 0', {
+ 'target_conditions' : [
+ ['_toolset=="target"', {
+ 'cflags!': [ '-finstrument-functions' ],
+ }],
+ ],
+ }],
+ [ 'target_arch == "ia32" or target_arch == "x64"', {
+ 'dependencies': [
+ 'yuv_convert_simd_x86',
+ ],
+ }],
+ [ 'target_arch == "arm"', {
+ 'dependencies': [
+ 'yuv_convert_simd_arm',
+ ],
+ }],
+ ],
+ 'sources': [
+ 'base/yuv_convert.cc',
+ 'base/yuv_convert.h',
+ ],
+ },
+ {
+ 'target_name': 'yuv_convert_simd_x86',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'base/simd/convert_rgb_to_yuv_c.cc',
+ 'base/simd/convert_rgb_to_yuv_sse2.cc',
+ 'base/simd/convert_rgb_to_yuv_ssse3.asm',
+ 'base/simd/convert_rgb_to_yuv_ssse3.cc',
+ 'base/simd/convert_rgb_to_yuv_ssse3.inc',
+ 'base/simd/convert_yuv_to_rgb_c.cc',
+ 'base/simd/convert_yuv_to_rgb_x86.cc',
+ 'base/simd/convert_yuv_to_rgb_mmx.asm',
+ 'base/simd/convert_yuv_to_rgb_mmx.inc',
+ 'base/simd/convert_yuv_to_rgb_sse.asm',
+ 'base/simd/filter_yuv.h',
+ 'base/simd/filter_yuv_c.cc',
+ 'base/simd/filter_yuv_mmx.cc',
+ 'base/simd/filter_yuv_sse2.cc',
+ 'base/simd/linear_scale_yuv_to_rgb_mmx.asm',
+ 'base/simd/linear_scale_yuv_to_rgb_mmx.inc',
+ 'base/simd/linear_scale_yuv_to_rgb_sse.asm',
+ 'base/simd/scale_yuv_to_rgb_mmx.asm',
+ 'base/simd/scale_yuv_to_rgb_mmx.inc',
+ 'base/simd/scale_yuv_to_rgb_sse.asm',
+ 'base/simd/yuv_to_rgb_table.cc',
+ 'base/simd/yuv_to_rgb_table.h',
+ ],
+ 'conditions': [
+ ['order_profiling != 0', {
+ 'target_conditions' : [
+ ['_toolset=="target"', {
+ 'cflags!': [ '-finstrument-functions' ],
+ }],
+ ],
+ }],
+ [ 'target_arch == "x64"', {
+ # Source files optimized for X64 systems.
+ 'sources': [
+ 'base/simd/linear_scale_yuv_to_rgb_mmx_x64.asm',
+ 'base/simd/scale_yuv_to_rgb_sse2_x64.asm',
+ ],
+ }],
+ [ 'os_posix == 1 and OS != "mac" and OS != "android"', {
+ 'cflags': [
+ '-msse2',
+ ],
+ }],
+ [ 'OS == "mac"', {
+ 'configurations': {
+ 'Debug': {
+ 'xcode_settings': {
+ # gcc on the mac builds horribly unoptimized sse code in debug
+ # mode. Since this is rarely going to be debugged, run with full
+ # optimizations in Debug as well as Release.
+ 'GCC_OPTIMIZATION_LEVEL': '3', # -O3
+ },
+ },
+ },
+ }],
+ [ 'OS=="win"', {
+ 'variables': {
+ 'yasm_flags': [
+ '-DWIN32',
+ '-DMSVC',
+ '-DCHROMIUM',
+ '-Isimd',
+ ],
+ },
+ }],
+ [ 'OS=="mac"', {
+ 'variables': {
+ 'yasm_flags': [
+ '-DPREFIX',
+ '-DMACHO',
+ '-DCHROMIUM',
+ '-Isimd',
+ ],
+ },
+ }],
+ [ 'os_posix==1 and OS!="mac"', {
+ 'variables': {
+ 'conditions': [
+ [ 'target_arch=="ia32"', {
+ 'yasm_flags': [
+ '-DX86_32',
+ '-DELF',
+ '-DCHROMIUM',
+ '-Isimd',
+ ],
+ }, {
+ 'yasm_flags': [
+ '-DARCH_X86_64',
+ '-DELF',
+ '-DPIC',
+ '-DCHROMIUM',
+ '-Isimd',
+ ],
+ }],
+ ],
+ },
+ }],
+ ],
+ 'variables': {
+ 'yasm_output_path': '<(SHARED_INTERMEDIATE_DIR)/media',
+ },
+ 'msvs_2010_disable_uldi_when_referenced': 1,
+ 'includes': [
+ '../third_party/yasm/yasm_compile.gypi',
+ ],
+ },
+ {
+ 'target_name': 'yuv_convert_simd_arm',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'base/simd/convert_rgb_to_yuv_c.cc',
+ 'base/simd/convert_rgb_to_yuv.h',
+ 'base/simd/convert_yuv_to_rgb_c.cc',
+ 'base/simd/convert_yuv_to_rgb.h',
+ 'base/simd/filter_yuv.h',
+ 'base/simd/filter_yuv_c.cc',
+ 'base/simd/yuv_to_rgb_table.cc',
+ 'base/simd/yuv_to_rgb_table.h',
+ ],
+ },
+ {
+ 'target_name': 'media_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'media_test_support',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../base/base.gyp:base_i18n',
+ '../base/base.gyp:test_support_base',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ '../ui/ui.gyp:ui',
+ ],
+ 'sources': [
+ 'audio/async_socket_io_handler_unittest.cc',
+ 'audio/audio_input_controller_unittest.cc',
+ 'audio/audio_input_device_unittest.cc',
+ 'audio/audio_input_unittest.cc',
+ 'audio/audio_input_volume_unittest.cc',
+ 'audio/audio_low_latency_input_output_unittest.cc',
+ 'audio/audio_output_controller_unittest.cc',
+ 'audio/audio_output_proxy_unittest.cc',
+ 'audio/audio_parameters_unittest.cc',
+ 'audio/audio_util_unittest.cc',
+ 'audio/cross_process_notification_unittest.cc',
+ 'audio/linux/alsa_output_unittest.cc',
+ 'audio/mac/audio_low_latency_input_mac_unittest.cc',
+ 'audio/mac/audio_output_mac_unittest.cc',
+ 'audio/simple_sources_unittest.cc',
+ 'audio/win/audio_low_latency_input_win_unittest.cc',
+ 'audio/win/audio_low_latency_output_win_unittest.cc',
+ 'audio/win/audio_output_win_unittest.cc',
+ 'base/audio_renderer_mixer_unittest.cc',
+ 'base/audio_renderer_mixer_input_unittest.cc',
+ 'base/buffers_unittest.cc',
+ 'base/clock_unittest.cc',
+ 'base/composite_filter_unittest.cc',
+ 'base/data_buffer_unittest.cc',
+ 'base/decoder_buffer_unittest.cc',
+ 'base/djb2_unittest.cc',
+ 'base/fake_audio_render_callback.cc',
+ 'base/fake_audio_render_callback.h',
+ 'base/filter_collection_unittest.cc',
+ 'base/h264_bitstream_converter_unittest.cc',
+ 'base/pipeline_unittest.cc',
+ 'base/ranges_unittest.cc',
+ 'base/run_all_unittests.cc',
+ 'base/seekable_buffer_unittest.cc',
+ 'base/state_matrix_unittest.cc',
+ 'base/test_data_util.cc',
+ 'base/test_data_util.h',
+ 'base/video_frame_unittest.cc',
+ 'base/video_util_unittest.cc',
+ 'base/yuv_convert_unittest.cc',
+ 'crypto/aes_decryptor_unittest.cc',
+ 'ffmpeg/ffmpeg_common_unittest.cc',
+ 'filters/audio_renderer_algorithm_unittest.cc',
+ 'filters/audio_renderer_impl_unittest.cc',
+ 'filters/bitstream_converter_unittest.cc',
+ 'filters/chunk_demuxer_unittest.cc',
+ 'filters/ffmpeg_audio_decoder_unittest.cc',
+ 'filters/ffmpeg_decoder_unittest.h',
+ 'filters/ffmpeg_demuxer_unittest.cc',
+ 'filters/ffmpeg_glue_unittest.cc',
+ 'filters/ffmpeg_h264_bitstream_converter_unittest.cc',
+ 'filters/ffmpeg_video_decoder_unittest.cc',
+ 'filters/file_data_source_unittest.cc',
+ 'filters/pipeline_integration_test.cc',
+ 'filters/pipeline_integration_test_base.cc',
+ 'filters/source_buffer_stream_unittest.cc',
+ 'filters/video_renderer_base_unittest.cc',
+ 'video/capture/video_capture_device_unittest.cc',
+ 'webm/cluster_builder.cc',
+ 'webm/cluster_builder.h',
+ 'webm/webm_cluster_parser_unittest.cc',
+ 'webm/webm_content_encodings_client_unittest.cc',
+ 'webm/webm_parser_unittest.cc',
+ ],
+ 'conditions': [
+ ['os_posix==1 and OS!="mac"', {
+ 'conditions': [
+ ['linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '../base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
+ }],
+ ['OS != "android"', {
+ 'dependencies': [
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ }],
+ ['OS == "android"', {
+ 'sources!': [
+ 'audio/audio_input_volume_unittest.cc',
+ 'base/test_data_util.cc',
+ 'base/test_data_util.h',
+ 'ffmpeg/ffmpeg_common_unittest.cc',
+ 'filters/ffmpeg_audio_decoder_unittest.cc',
+ 'filters/bitstream_converter_unittest.cc',
+ 'filters/chunk_demuxer_unittest.cc',
+ 'filters/ffmpeg_demuxer_unittest.cc',
+ 'filters/ffmpeg_glue_unittest.cc',
+ 'filters/ffmpeg_h264_bitstream_converter_unittest.cc',
+ 'filters/ffmpeg_video_decoder_unittest.cc',
+ 'filters/pipeline_integration_test.cc',
+ 'filters/pipeline_integration_test_base.cc',
+ 'mp4/mp4_stream_parser_unittest.cc',
+ 'webm/webm_cluster_parser_unittest.cc',
+ ],
+ }],
+ ['OS == "linux"', {
+ 'conditions': [
+ ['use_cras == 1', {
+ 'sources': [
+ 'audio/linux/cras_output_unittest.cc',
+ ],
+ 'defines': [
+ 'USE_CRAS',
+ ],
+ }],
+ ],
+ }],
+ [ 'target_arch=="ia32" or target_arch=="x64"', {
+ 'sources': [
+ 'base/simd/convert_rgb_to_yuv_unittest.cc',
+ ],
+ }],
+ ['proprietary_codecs==1 or branding=="Chrome"', {
+ 'sources': [
+ 'mp4/avc_unittest.cc',
+ 'mp4/box_reader_unittest.cc',
+ 'mp4/mp4_stream_parser_unittest.cc',
+ 'mp4/offset_byte_queue_unittest.cc',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'media_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'media',
+ '../base/base.gyp:base',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'audio/test_audio_input_controller_factory.cc',
+ 'audio/test_audio_input_controller_factory.h',
+ 'base/mock_callback.cc',
+ 'base/mock_callback.h',
+ 'base/mock_data_source_host.cc',
+ 'base/mock_data_source_host.h',
+ 'base/mock_demuxer_host.cc',
+ 'base/mock_demuxer_host.h',
+ 'base/mock_filter_host.cc',
+ 'base/mock_filter_host.h',
+ 'base/mock_filters.cc',
+ 'base/mock_filters.h',
+ ],
+ },
+ {
+ 'target_name': 'scaler_bench',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../skia/skia.gyp:skia',
+ ],
+ 'sources': [
+ 'tools/scaler_bench/scaler_bench.cc',
+ ],
+ },
+ {
+ 'target_name': 'qt_faststart',
+ 'type': 'executable',
+ 'sources': [
+ 'tools/qt_faststart/qt_faststart.c'
+ ],
+ },
+ {
+ 'target_name': 'seek_tester',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ '../base/base.gyp:base',
+ ],
+ 'sources': [
+ 'tools/seek_tester/seek_tester.cc',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'targets': [
+ {
+ 'target_name': 'player_wtl',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../ui/ui.gyp:ui',
+ ],
+ 'include_dirs': [
+ '<(DEPTH)/third_party/wtl/include',
+ ],
+ 'sources': [
+ 'tools/player_wtl/list.h',
+ 'tools/player_wtl/mainfrm.h',
+ 'tools/player_wtl/movie.cc',
+ 'tools/player_wtl/movie.h',
+ 'tools/player_wtl/player_wtl.cc',
+ 'tools/player_wtl/player_wtl.rc',
+ 'tools/player_wtl/props.h',
+ 'tools/player_wtl/seek.h',
+ 'tools/player_wtl/resource.h',
+ 'tools/player_wtl/view.h',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
+ },
+ },
+ 'defines': [
+ '_CRT_SECURE_NO_WARNINGS=1',
+ ],
+ },
+ ],
+ }],
+ ['OS == "win" or toolkit_uses_gtk == 1', {
+ 'targets': [
+ {
+ 'target_name': 'shader_bench',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../ui/gl/gl.gyp:gl',
+ ],
+ 'sources': [
+ 'tools/shader_bench/shader_bench.cc',
+ 'tools/shader_bench/cpu_color_painter.cc',
+ 'tools/shader_bench/cpu_color_painter.h',
+ 'tools/shader_bench/gpu_color_painter.cc',
+ 'tools/shader_bench/gpu_color_painter.h',
+ 'tools/shader_bench/gpu_painter.cc',
+ 'tools/shader_bench/gpu_painter.h',
+ 'tools/shader_bench/painter.cc',
+ 'tools/shader_bench/painter.h',
+ 'tools/shader_bench/window.cc',
+ 'tools/shader_bench/window.h',
+ ],
+ 'conditions': [
+ ['toolkit_uses_gtk == 1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:gtk',
+ ],
+ 'sources': [
+ 'tools/shader_bench/window_linux.cc',
+ ],
+ }],
+ ['OS=="win"', {
+ 'dependencies': [
+ '../third_party/angle/src/build_angle.gyp:libEGL',
+ '../third_party/angle/src/build_angle.gyp:libGLESv2',
+ ],
+ 'sources': [
+ 'tools/shader_bench/window_win.cc',
+ ],
+ }],
+ ],
+ },
+ ],
+ }],
+ ['OS == "linux" and target_arch != "arm"', {
+ 'targets': [
+ {
+ 'target_name': 'tile_render_bench',
+ 'type': 'executable',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../ui/gl/gl.gyp:gl',
+ ],
+ 'libraries': [
+ '-lGL',
+ '-ldl',
+ ],
+ 'sources': [
+ 'tools/tile_render_bench/tile_render_bench.cc',
+ ],
+ },
+ ],
+ }],
+ ['os_posix == 1 and OS != "mac" and OS != "android"', {
+ 'targets': [
+ {
+ 'target_name': 'player_x11',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../ui/gl/gl.gyp:gl',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-ldl',
+ '-lX11',
+ '-lXrender',
+ '-lXext',
+ ],
+ },
+ 'sources': [
+ 'tools/player_x11/data_source_logger.cc',
+ 'tools/player_x11/data_source_logger.h',
+ 'tools/player_x11/gl_video_renderer.cc',
+ 'tools/player_x11/gl_video_renderer.h',
+ 'tools/player_x11/player_x11.cc',
+ 'tools/player_x11/x11_video_renderer.cc',
+ 'tools/player_x11/x11_video_renderer.h',
+ ],
+ },
+ ],
+ }],
+ ['OS == "android"', {
+ 'targets': [
+ {
+ 'target_name': 'player_android',
+ 'type': 'static_library',
+ 'sources': [
+ 'base/android/media_player_bridge.cc',
+ 'base/android/media_player_bridge.h',
+ ],
+ 'dependencies': [
+ '../base/base.gyp:base',
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)/media',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate-jni-headers',
+ 'inputs': [
+ '../base/android/jni_generator/jni_generator.py',
+ 'base/android/java/src/org/chromium/media/MediaPlayerListener.java',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/media/jni/media_player_listener_jni.h',
+ ],
+ 'action': [
+ 'python',
+ '<(DEPTH)/base/android/jni_generator/jni_generator.py',
+ '-o',
+ '<@(_inputs)',
+ '<@(_outputs)',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'media_java',
+ 'type': 'none',
+ 'dependencies': [ '../base/base.gyp:base_java' ],
+ 'variables': {
+ 'package_name': 'media',
+ 'java_in_dir': 'base/android/java',
+ },
+ 'includes': [ '../build/java.gypi' ],
+ },
+
+ ],
+ }, { # OS != "android"'
+ # Android does not use ffmpeg, so disable the targets which require it.
+ 'targets': [
+ {
+ 'target_name': 'ffmpeg_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'media_test_support',
+ '../base/base.gyp:base',
+ '../base/base.gyp:base_i18n',
+ '../base/base.gyp:test_support_base',
+ '../base/base.gyp:test_support_perf',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ 'sources': [
+ 'ffmpeg/ffmpeg_unittest.cc',
+ ],
+ 'conditions': [
+ ['toolkit_uses_gtk == 1', {
+ 'dependencies': [
+ # Needed for the following #include chain:
+ # base/run_all_unittests.cc
+ # ../base/test_suite.h
+ # gtk/gtk.h
+ '../build/linux/system.gyp:gtk',
+ ],
+ 'conditions': [
+ ['linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '../base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'ffmpeg_regression_tests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'media_test_support',
+ '../base/base.gyp:test_support_base',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ 'sources': [
+ 'base/test_data_util.cc',
+ 'base/run_all_unittests.cc',
+ 'ffmpeg/ffmpeg_regression_tests.cc',
+ 'filters/pipeline_integration_test_base.cc',
+ ],
+ 'conditions': [
+ ['os_posix==1 and OS!="mac"', {
+ 'conditions': [
+ ['linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '../base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'ffmpeg_tests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ '../base/base.gyp:base',
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ 'sources': [
+ 'test/ffmpeg_tests/ffmpeg_tests.cc',
+ ],
+ },
+ {
+ 'target_name': 'media_bench',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ '../base/base.gyp:base',
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ 'sources': [
+ 'tools/media_bench/media_bench.cc',
+ ],
+ },
+ ],
+ }]
+ ],
+}
diff --git a/chromium/tools/gyp/tools/emacs/testdata/media.gyp.fontified b/chromium/tools/gyp/tools/emacs/testdata/media.gyp.fontified
new file mode 100644
index 00000000000..962b7b2c43a
--- /dev/null
+++ b/chromium/tools/gyp/tools/emacs/testdata/media.gyp.fontified
@@ -0,0 +1,1107 @@
+
+#("# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ # Override to dynamically link the PulseAudio library.
+ 'use_pulseaudio%': 0,
+ # Override to dynamically link the cras (ChromeOS audio) library.
+ 'use_cras%': 0,
+ },
+ 'targets': [
+ {
+ 'target_name': 'media',
+ 'type': '<(component)',
+ 'dependencies': [
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../build/temp_gyp/googleurl.gyp:googleurl',
+ '../crypto/crypto.gyp:crypto',
+ '../third_party/openmax/openmax.gyp:il',
+ '../ui/ui.gyp:ui',
+ ],
+ 'defines': [
+ 'MEDIA_IMPLEMENTATION',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'audio/android/audio_manager_android.cc',
+ 'audio/android/audio_manager_android.h',
+ 'audio/android/audio_track_output_android.cc',
+ 'audio/android/audio_track_output_android.h',
+ 'audio/android/opensles_input.cc',
+ 'audio/android/opensles_input.h',
+ 'audio/android/opensles_output.cc',
+ 'audio/android/opensles_output.h',
+ 'audio/async_socket_io_handler.h',
+ 'audio/async_socket_io_handler_posix.cc',
+ 'audio/async_socket_io_handler_win.cc',
+ 'audio/audio_buffers_state.cc',
+ 'audio/audio_buffers_state.h',
+ 'audio/audio_io.h',
+ 'audio/audio_input_controller.cc',
+ 'audio/audio_input_controller.h',
+ 'audio/audio_input_stream_impl.cc',
+ 'audio/audio_input_stream_impl.h',
+ 'audio/audio_device_name.cc',
+ 'audio/audio_device_name.h',
+ 'audio/audio_manager.cc',
+ 'audio/audio_manager.h',
+ 'audio/audio_manager_base.cc',
+ 'audio/audio_manager_base.h',
+ 'audio/audio_output_controller.cc',
+ 'audio/audio_output_controller.h',
+ 'audio/audio_output_dispatcher.cc',
+ 'audio/audio_output_dispatcher.h',
+ 'audio/audio_output_dispatcher_impl.cc',
+ 'audio/audio_output_dispatcher_impl.h',
+ 'audio/audio_output_mixer.cc',
+ 'audio/audio_output_mixer.h',
+ 'audio/audio_output_proxy.cc',
+ 'audio/audio_output_proxy.h',
+ 'audio/audio_parameters.cc',
+ 'audio/audio_parameters.h',
+ 'audio/audio_util.cc',
+ 'audio/audio_util.h',
+ 'audio/cross_process_notification.cc',
+ 'audio/cross_process_notification.h',
+ 'audio/cross_process_notification_win.cc',
+ 'audio/cross_process_notification_posix.cc',
+ 'audio/fake_audio_input_stream.cc',
+ 'audio/fake_audio_input_stream.h',
+ 'audio/fake_audio_output_stream.cc',
+ 'audio/fake_audio_output_stream.h',
+ 'audio/linux/audio_manager_linux.cc',
+ 'audio/linux/audio_manager_linux.h',
+ 'audio/linux/alsa_input.cc',
+ 'audio/linux/alsa_input.h',
+ 'audio/linux/alsa_output.cc',
+ 'audio/linux/alsa_output.h',
+ 'audio/linux/alsa_util.cc',
+ 'audio/linux/alsa_util.h',
+ 'audio/linux/alsa_wrapper.cc',
+ 'audio/linux/alsa_wrapper.h',
+ 'audio/linux/cras_output.cc',
+ 'audio/linux/cras_output.h',
+ 'audio/openbsd/audio_manager_openbsd.cc',
+ 'audio/openbsd/audio_manager_openbsd.h',
+ 'audio/mac/audio_input_mac.cc',
+ 'audio/mac/audio_input_mac.h',
+ 'audio/mac/audio_low_latency_input_mac.cc',
+ 'audio/mac/audio_low_latency_input_mac.h',
+ 'audio/mac/audio_low_latency_output_mac.cc',
+ 'audio/mac/audio_low_latency_output_mac.h',
+ 'audio/mac/audio_manager_mac.cc',
+ 'audio/mac/audio_manager_mac.h',
+ 'audio/mac/audio_output_mac.cc',
+ 'audio/mac/audio_output_mac.h',
+ 'audio/null_audio_sink.cc',
+ 'audio/null_audio_sink.h',
+ 'audio/pulse/pulse_output.cc',
+ 'audio/pulse/pulse_output.h',
+ 'audio/sample_rates.cc',
+ 'audio/sample_rates.h',
+ 'audio/simple_sources.cc',
+ 'audio/simple_sources.h',
+ 'audio/win/audio_low_latency_input_win.cc',
+ 'audio/win/audio_low_latency_input_win.h',
+ 'audio/win/audio_low_latency_output_win.cc',
+ 'audio/win/audio_low_latency_output_win.h',
+ 'audio/win/audio_manager_win.cc',
+ 'audio/win/audio_manager_win.h',
+ 'audio/win/avrt_wrapper_win.cc',
+ 'audio/win/avrt_wrapper_win.h',
+ 'audio/win/device_enumeration_win.cc',
+ 'audio/win/device_enumeration_win.h',
+ 'audio/win/wavein_input_win.cc',
+ 'audio/win/wavein_input_win.h',
+ 'audio/win/waveout_output_win.cc',
+ 'audio/win/waveout_output_win.h',
+ 'base/android/media_jni_registrar.cc',
+ 'base/android/media_jni_registrar.h',
+ 'base/audio_decoder.cc',
+ 'base/audio_decoder.h',
+ 'base/audio_decoder_config.cc',
+ 'base/audio_decoder_config.h',
+ 'base/audio_renderer.h',
+ 'base/audio_renderer_mixer.cc',
+ 'base/audio_renderer_mixer.h',
+ 'base/audio_renderer_mixer_input.cc',
+ 'base/audio_renderer_mixer_input.h',
+ 'base/bitstream_buffer.h',
+ 'base/buffers.cc',
+ 'base/buffers.h',
+ 'base/byte_queue.cc',
+ 'base/byte_queue.h',
+ 'base/channel_layout.cc',
+ 'base/channel_layout.h',
+ 'base/clock.cc',
+ 'base/clock.h',
+ 'base/composite_filter.cc',
+ 'base/composite_filter.h',
+ 'base/data_buffer.cc',
+ 'base/data_buffer.h',
+ 'base/data_source.cc',
+ 'base/data_source.h',
+ 'base/decoder_buffer.cc',
+ 'base/decoder_buffer.h',
+ 'base/decrypt_config.cc',
+ 'base/decrypt_config.h',
+ 'base/decryptor.h',
+ 'base/decryptor_client.h',
+ 'base/demuxer.cc',
+ 'base/demuxer.h',
+ 'base/demuxer_stream.cc',
+ 'base/demuxer_stream.h',
+ 'base/djb2.cc',
+ 'base/djb2.h',
+ 'base/filter_collection.cc',
+ 'base/filter_collection.h',
+ 'base/filter_host.h',
+ 'base/filters.cc',
+ 'base/filters.h',
+ 'base/h264_bitstream_converter.cc',
+ 'base/h264_bitstream_converter.h',
+ 'base/media.h',
+ 'base/media_android.cc',
+ 'base/media_export.h',
+ 'base/media_log.cc',
+ 'base/media_log.h',
+ 'base/media_log_event.h',
+ 'base/media_posix.cc',
+ 'base/media_switches.cc',
+ 'base/media_switches.h',
+ 'base/media_win.cc',
+ 'base/message_loop_factory.cc',
+ 'base/message_loop_factory.h',
+ 'base/pipeline.cc',
+ 'base/pipeline.h',
+ 'base/pipeline_status.cc',
+ 'base/pipeline_status.h',
+ 'base/ranges.cc',
+ 'base/ranges.h',
+ 'base/seekable_buffer.cc',
+ 'base/seekable_buffer.h',
+ 'base/state_matrix.cc',
+ 'base/state_matrix.h',
+ 'base/stream_parser.cc',
+ 'base/stream_parser.h',
+ 'base/stream_parser_buffer.cc',
+ 'base/stream_parser_buffer.h',
+ 'base/video_decoder.cc',
+ 'base/video_decoder.h',
+ 'base/video_decoder_config.cc',
+ 'base/video_decoder_config.h',
+ 'base/video_frame.cc',
+ 'base/video_frame.h',
+ 'base/video_renderer.h',
+ 'base/video_util.cc',
+ 'base/video_util.h',
+ 'crypto/aes_decryptor.cc',
+ 'crypto/aes_decryptor.h',
+ 'ffmpeg/ffmpeg_common.cc',
+ 'ffmpeg/ffmpeg_common.h',
+ 'ffmpeg/file_protocol.cc',
+ 'ffmpeg/file_protocol.h',
+ 'filters/audio_file_reader.cc',
+ 'filters/audio_file_reader.h',
+ 'filters/audio_renderer_algorithm.cc',
+ 'filters/audio_renderer_algorithm.h',
+ 'filters/audio_renderer_impl.cc',
+ 'filters/audio_renderer_impl.h',
+ 'filters/bitstream_converter.cc',
+ 'filters/bitstream_converter.h',
+ 'filters/chunk_demuxer.cc',
+ 'filters/chunk_demuxer.h',
+ 'filters/chunk_demuxer_client.h',
+ 'filters/dummy_demuxer.cc',
+ 'filters/dummy_demuxer.h',
+ 'filters/ffmpeg_audio_decoder.cc',
+ 'filters/ffmpeg_audio_decoder.h',
+ 'filters/ffmpeg_demuxer.cc',
+ 'filters/ffmpeg_demuxer.h',
+ 'filters/ffmpeg_h264_bitstream_converter.cc',
+ 'filters/ffmpeg_h264_bitstream_converter.h',
+ 'filters/ffmpeg_glue.cc',
+ 'filters/ffmpeg_glue.h',
+ 'filters/ffmpeg_video_decoder.cc',
+ 'filters/ffmpeg_video_decoder.h',
+ 'filters/file_data_source.cc',
+ 'filters/file_data_source.h',
+ 'filters/gpu_video_decoder.cc',
+ 'filters/gpu_video_decoder.h',
+ 'filters/in_memory_url_protocol.cc',
+ 'filters/in_memory_url_protocol.h',
+ 'filters/source_buffer_stream.cc',
+ 'filters/source_buffer_stream.h',
+ 'filters/video_frame_generator.cc',
+ 'filters/video_frame_generator.h',
+ 'filters/video_renderer_base.cc',
+ 'filters/video_renderer_base.h',
+ 'video/capture/fake_video_capture_device.cc',
+ 'video/capture/fake_video_capture_device.h',
+ 'video/capture/linux/video_capture_device_linux.cc',
+ 'video/capture/linux/video_capture_device_linux.h',
+ 'video/capture/mac/video_capture_device_mac.h',
+ 'video/capture/mac/video_capture_device_mac.mm',
+ 'video/capture/mac/video_capture_device_qtkit_mac.h',
+ 'video/capture/mac/video_capture_device_qtkit_mac.mm',
+ 'video/capture/video_capture.h',
+ 'video/capture/video_capture_device.h',
+ 'video/capture/video_capture_device_dummy.cc',
+ 'video/capture/video_capture_device_dummy.h',
+ 'video/capture/video_capture_proxy.cc',
+ 'video/capture/video_capture_proxy.h',
+ 'video/capture/video_capture_types.h',
+ 'video/capture/win/filter_base_win.cc',
+ 'video/capture/win/filter_base_win.h',
+ 'video/capture/win/pin_base_win.cc',
+ 'video/capture/win/pin_base_win.h',
+ 'video/capture/win/sink_filter_observer_win.h',
+ 'video/capture/win/sink_filter_win.cc',
+ 'video/capture/win/sink_filter_win.h',
+ 'video/capture/win/sink_input_pin_win.cc',
+ 'video/capture/win/sink_input_pin_win.h',
+ 'video/capture/win/video_capture_device_win.cc',
+ 'video/capture/win/video_capture_device_win.h',
+ 'video/picture.cc',
+ 'video/picture.h',
+ 'video/video_decode_accelerator.cc',
+ 'video/video_decode_accelerator.h',
+ 'webm/webm_constants.h',
+ 'webm/webm_cluster_parser.cc',
+ 'webm/webm_cluster_parser.h',
+ 'webm/webm_content_encodings.cc',
+ 'webm/webm_content_encodings.h',
+ 'webm/webm_content_encodings_client.cc',
+ 'webm/webm_content_encodings_client.h',
+ 'webm/webm_info_parser.cc',
+ 'webm/webm_info_parser.h',
+ 'webm/webm_parser.cc',
+ 'webm/webm_parser.h',
+ 'webm/webm_stream_parser.cc',
+ 'webm/webm_stream_parser.h',
+ 'webm/webm_tracks_parser.cc',
+ 'webm/webm_tracks_parser.h',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ 'conditions': [
+ # Android doesn't use ffmpeg, so make the dependency conditional
+ # and exclude the sources which depend on ffmpeg.
+ ['OS != \"android\"', {
+ 'dependencies': [
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ }],
+ ['OS == \"android\"', {
+ 'sources!': [
+ 'base/media_posix.cc',
+ 'ffmpeg/ffmpeg_common.cc',
+ 'ffmpeg/ffmpeg_common.h',
+ 'ffmpeg/file_protocol.cc',
+ 'ffmpeg/file_protocol.h',
+ 'filters/audio_file_reader.cc',
+ 'filters/audio_file_reader.h',
+ 'filters/bitstream_converter.cc',
+ 'filters/bitstream_converter.h',
+ 'filters/chunk_demuxer.cc',
+ 'filters/chunk_demuxer.h',
+ 'filters/chunk_demuxer_client.h',
+ 'filters/ffmpeg_audio_decoder.cc',
+ 'filters/ffmpeg_audio_decoder.h',
+ 'filters/ffmpeg_demuxer.cc',
+ 'filters/ffmpeg_demuxer.h',
+ 'filters/ffmpeg_h264_bitstream_converter.cc',
+ 'filters/ffmpeg_h264_bitstream_converter.h',
+ 'filters/ffmpeg_glue.cc',
+ 'filters/ffmpeg_glue.h',
+ 'filters/ffmpeg_video_decoder.cc',
+ 'filters/ffmpeg_video_decoder.h',
+ 'filters/gpu_video_decoder.cc',
+ 'filters/gpu_video_decoder.h',
+ 'webm/webm_cluster_parser.cc',
+ 'webm/webm_cluster_parser.h',
+ 'webm/webm_stream_parser.cc',
+ 'webm/webm_stream_parser.h',
+ ],
+ }],
+ # The below 'android' condition were added temporarily and should be
+ # removed in downstream, because there is no Java environment setup in
+ # upstream yet.
+ ['OS == \"android\"', {
+ 'sources!':[
+ 'audio/android/audio_track_output_android.cc',
+ ],
+ 'sources':[
+ 'audio/android/audio_track_output_stub_android.cc',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-lOpenSLES',
+ ],
+ },
+ }],
+ ['OS==\"linux\" or OS==\"freebsd\" or OS==\"solaris\"', {
+ 'link_settings': {
+ 'libraries': [
+ '-lasound',
+ ],
+ },
+ }],
+ ['OS==\"openbsd\"', {
+ 'sources/': [ ['exclude', '/alsa_' ],
+ ['exclude', '/audio_manager_linux' ] ],
+ 'link_settings': {
+ 'libraries': [
+ ],
+ },
+ }],
+ ['OS!=\"openbsd\"', {
+ 'sources!': [
+ 'audio/openbsd/audio_manager_openbsd.cc',
+ 'audio/openbsd/audio_manager_openbsd.h',
+ ],
+ }],
+ ['OS==\"linux\"', {
+ 'variables': {
+ 'conditions': [
+ ['sysroot!=\"\"', {
+ 'pkg-config': '../build/linux/pkg-config-wrapper \"<(sysroot)\" \"<(target_arch)\"',
+ }, {
+ 'pkg-config': 'pkg-config'
+ }],
+ ],
+ },
+ 'conditions': [
+ ['use_cras == 1', {
+ 'cflags': [
+ '<!@(<(pkg-config) --cflags libcras)',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '<!@(<(pkg-config) --libs libcras)',
+ ],
+ },
+ 'defines': [
+ 'USE_CRAS',
+ ],
+ }, { # else: use_cras == 0
+ 'sources!': [
+ 'audio/linux/cras_output.cc',
+ 'audio/linux/cras_output.h',
+ ],
+ }],
+ ],
+ }],
+ ['os_posix == 1', {
+ 'conditions': [
+ ['use_pulseaudio == 1', {
+ 'cflags': [
+ '<!@(pkg-config --cflags libpulse)',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '<!@(pkg-config --libs-only-l libpulse)',
+ ],
+ },
+ 'defines': [
+ 'USE_PULSEAUDIO',
+ ],
+ }, { # else: use_pulseaudio == 0
+ 'sources!': [
+ 'audio/pulse/pulse_output.cc',
+ 'audio/pulse/pulse_output.h',
+ ],
+ }],
+ ],
+ }],
+ ['os_posix == 1 and OS != \"android\"', {
+ # Video capture isn't supported in Android yet.
+ 'sources!': [
+ 'video/capture/video_capture_device_dummy.cc',
+ 'video/capture/video_capture_device_dummy.h',
+ ],
+ }],
+ ['OS==\"mac\"', {
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/AudioUnit.framework',
+ '$(SDKROOT)/System/Library/Frameworks/AudioToolbox.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreAudio.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreVideo.framework',
+ '$(SDKROOT)/System/Library/Frameworks/QTKit.framework',
+ ],
+ },
+ }],
+ ['OS==\"win\"', {
+ 'sources!': [
+ 'audio/pulse/pulse_output.cc',
+ 'audio/pulse/pulse_output.h',
+ 'video/capture/video_capture_device_dummy.cc',
+ 'video/capture/video_capture_device_dummy.h',
+ ],
+ }],
+ ['proprietary_codecs==1 or branding==\"Chrome\"', {
+ 'sources': [
+ 'mp4/avc.cc',
+ 'mp4/avc.h',
+ 'mp4/box_definitions.cc',
+ 'mp4/box_definitions.h',
+ 'mp4/box_reader.cc',
+ 'mp4/box_reader.h',
+ 'mp4/cenc.cc',
+ 'mp4/cenc.h',
+ 'mp4/mp4_stream_parser.cc',
+ 'mp4/mp4_stream_parser.h',
+ 'mp4/offset_byte_queue.cc',
+ 'mp4/offset_byte_queue.h',
+ 'mp4/track_run_iterator.cc',
+ 'mp4/track_run_iterator.h',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'yuv_convert',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'conditions': [
+ ['order_profiling != 0', {
+ 'target_conditions' : [
+ ['_toolset==\"target\"', {
+ 'cflags!': [ '-finstrument-functions' ],
+ }],
+ ],
+ }],
+ [ 'target_arch == \"ia32\" or target_arch == \"x64\"', {
+ 'dependencies': [
+ 'yuv_convert_simd_x86',
+ ],
+ }],
+ [ 'target_arch == \"arm\"', {
+ 'dependencies': [
+ 'yuv_convert_simd_arm',
+ ],
+ }],
+ ],
+ 'sources': [
+ 'base/yuv_convert.cc',
+ 'base/yuv_convert.h',
+ ],
+ },
+ {
+ 'target_name': 'yuv_convert_simd_x86',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'base/simd/convert_rgb_to_yuv_c.cc',
+ 'base/simd/convert_rgb_to_yuv_sse2.cc',
+ 'base/simd/convert_rgb_to_yuv_ssse3.asm',
+ 'base/simd/convert_rgb_to_yuv_ssse3.cc',
+ 'base/simd/convert_rgb_to_yuv_ssse3.inc',
+ 'base/simd/convert_yuv_to_rgb_c.cc',
+ 'base/simd/convert_yuv_to_rgb_x86.cc',
+ 'base/simd/convert_yuv_to_rgb_mmx.asm',
+ 'base/simd/convert_yuv_to_rgb_mmx.inc',
+ 'base/simd/convert_yuv_to_rgb_sse.asm',
+ 'base/simd/filter_yuv.h',
+ 'base/simd/filter_yuv_c.cc',
+ 'base/simd/filter_yuv_mmx.cc',
+ 'base/simd/filter_yuv_sse2.cc',
+ 'base/simd/linear_scale_yuv_to_rgb_mmx.asm',
+ 'base/simd/linear_scale_yuv_to_rgb_mmx.inc',
+ 'base/simd/linear_scale_yuv_to_rgb_sse.asm',
+ 'base/simd/scale_yuv_to_rgb_mmx.asm',
+ 'base/simd/scale_yuv_to_rgb_mmx.inc',
+ 'base/simd/scale_yuv_to_rgb_sse.asm',
+ 'base/simd/yuv_to_rgb_table.cc',
+ 'base/simd/yuv_to_rgb_table.h',
+ ],
+ 'conditions': [
+ ['order_profiling != 0', {
+ 'target_conditions' : [
+ ['_toolset==\"target\"', {
+ 'cflags!': [ '-finstrument-functions' ],
+ }],
+ ],
+ }],
+ [ 'target_arch == \"x64\"', {
+ # Source files optimized for X64 systems.
+ 'sources': [
+ 'base/simd/linear_scale_yuv_to_rgb_mmx_x64.asm',
+ 'base/simd/scale_yuv_to_rgb_sse2_x64.asm',
+ ],
+ }],
+ [ 'os_posix == 1 and OS != \"mac\" and OS != \"android\"', {
+ 'cflags': [
+ '-msse2',
+ ],
+ }],
+ [ 'OS == \"mac\"', {
+ 'configurations': {
+ 'Debug': {
+ 'xcode_settings': {
+ # gcc on the mac builds horribly unoptimized sse code in debug
+ # mode. Since this is rarely going to be debugged, run with full
+ # optimizations in Debug as well as Release.
+ 'GCC_OPTIMIZATION_LEVEL': '3', # -O3
+ },
+ },
+ },
+ }],
+ [ 'OS==\"win\"', {
+ 'variables': {
+ 'yasm_flags': [
+ '-DWIN32',
+ '-DMSVC',
+ '-DCHROMIUM',
+ '-Isimd',
+ ],
+ },
+ }],
+ [ 'OS==\"mac\"', {
+ 'variables': {
+ 'yasm_flags': [
+ '-DPREFIX',
+ '-DMACHO',
+ '-DCHROMIUM',
+ '-Isimd',
+ ],
+ },
+ }],
+ [ 'os_posix==1 and OS!=\"mac\"', {
+ 'variables': {
+ 'conditions': [
+ [ 'target_arch==\"ia32\"', {
+ 'yasm_flags': [
+ '-DX86_32',
+ '-DELF',
+ '-DCHROMIUM',
+ '-Isimd',
+ ],
+ }, {
+ 'yasm_flags': [
+ '-DARCH_X86_64',
+ '-DELF',
+ '-DPIC',
+ '-DCHROMIUM',
+ '-Isimd',
+ ],
+ }],
+ ],
+ },
+ }],
+ ],
+ 'variables': {
+ 'yasm_output_path': '<(SHARED_INTERMEDIATE_DIR)/media',
+ },
+ 'msvs_2010_disable_uldi_when_referenced': 1,
+ 'includes': [
+ '../third_party/yasm/yasm_compile.gypi',
+ ],
+ },
+ {
+ 'target_name': 'yuv_convert_simd_arm',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'base/simd/convert_rgb_to_yuv_c.cc',
+ 'base/simd/convert_rgb_to_yuv.h',
+ 'base/simd/convert_yuv_to_rgb_c.cc',
+ 'base/simd/convert_yuv_to_rgb.h',
+ 'base/simd/filter_yuv.h',
+ 'base/simd/filter_yuv_c.cc',
+ 'base/simd/yuv_to_rgb_table.cc',
+ 'base/simd/yuv_to_rgb_table.h',
+ ],
+ },
+ {
+ 'target_name': 'media_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'media_test_support',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../base/base.gyp:base_i18n',
+ '../base/base.gyp:test_support_base',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ '../ui/ui.gyp:ui',
+ ],
+ 'sources': [
+ 'audio/async_socket_io_handler_unittest.cc',
+ 'audio/audio_input_controller_unittest.cc',
+ 'audio/audio_input_device_unittest.cc',
+ 'audio/audio_input_unittest.cc',
+ 'audio/audio_input_volume_unittest.cc',
+ 'audio/audio_low_latency_input_output_unittest.cc',
+ 'audio/audio_output_controller_unittest.cc',
+ 'audio/audio_output_proxy_unittest.cc',
+ 'audio/audio_parameters_unittest.cc',
+ 'audio/audio_util_unittest.cc',
+ 'audio/cross_process_notification_unittest.cc',
+ 'audio/linux/alsa_output_unittest.cc',
+ 'audio/mac/audio_low_latency_input_mac_unittest.cc',
+ 'audio/mac/audio_output_mac_unittest.cc',
+ 'audio/simple_sources_unittest.cc',
+ 'audio/win/audio_low_latency_input_win_unittest.cc',
+ 'audio/win/audio_low_latency_output_win_unittest.cc',
+ 'audio/win/audio_output_win_unittest.cc',
+ 'base/audio_renderer_mixer_unittest.cc',
+ 'base/audio_renderer_mixer_input_unittest.cc',
+ 'base/buffers_unittest.cc',
+ 'base/clock_unittest.cc',
+ 'base/composite_filter_unittest.cc',
+ 'base/data_buffer_unittest.cc',
+ 'base/decoder_buffer_unittest.cc',
+ 'base/djb2_unittest.cc',
+ 'base/fake_audio_render_callback.cc',
+ 'base/fake_audio_render_callback.h',
+ 'base/filter_collection_unittest.cc',
+ 'base/h264_bitstream_converter_unittest.cc',
+ 'base/pipeline_unittest.cc',
+ 'base/ranges_unittest.cc',
+ 'base/run_all_unittests.cc',
+ 'base/seekable_buffer_unittest.cc',
+ 'base/state_matrix_unittest.cc',
+ 'base/test_data_util.cc',
+ 'base/test_data_util.h',
+ 'base/video_frame_unittest.cc',
+ 'base/video_util_unittest.cc',
+ 'base/yuv_convert_unittest.cc',
+ 'crypto/aes_decryptor_unittest.cc',
+ 'ffmpeg/ffmpeg_common_unittest.cc',
+ 'filters/audio_renderer_algorithm_unittest.cc',
+ 'filters/audio_renderer_impl_unittest.cc',
+ 'filters/bitstream_converter_unittest.cc',
+ 'filters/chunk_demuxer_unittest.cc',
+ 'filters/ffmpeg_audio_decoder_unittest.cc',
+ 'filters/ffmpeg_decoder_unittest.h',
+ 'filters/ffmpeg_demuxer_unittest.cc',
+ 'filters/ffmpeg_glue_unittest.cc',
+ 'filters/ffmpeg_h264_bitstream_converter_unittest.cc',
+ 'filters/ffmpeg_video_decoder_unittest.cc',
+ 'filters/file_data_source_unittest.cc',
+ 'filters/pipeline_integration_test.cc',
+ 'filters/pipeline_integration_test_base.cc',
+ 'filters/source_buffer_stream_unittest.cc',
+ 'filters/video_renderer_base_unittest.cc',
+ 'video/capture/video_capture_device_unittest.cc',
+ 'webm/cluster_builder.cc',
+ 'webm/cluster_builder.h',
+ 'webm/webm_cluster_parser_unittest.cc',
+ 'webm/webm_content_encodings_client_unittest.cc',
+ 'webm/webm_parser_unittest.cc',
+ ],
+ 'conditions': [
+ ['os_posix==1 and OS!=\"mac\"', {
+ 'conditions': [
+ ['linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '../base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
+ }],
+ ['OS != \"android\"', {
+ 'dependencies': [
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ }],
+ ['OS == \"android\"', {
+ 'sources!': [
+ 'audio/audio_input_volume_unittest.cc',
+ 'base/test_data_util.cc',
+ 'base/test_data_util.h',
+ 'ffmpeg/ffmpeg_common_unittest.cc',
+ 'filters/ffmpeg_audio_decoder_unittest.cc',
+ 'filters/bitstream_converter_unittest.cc',
+ 'filters/chunk_demuxer_unittest.cc',
+ 'filters/ffmpeg_demuxer_unittest.cc',
+ 'filters/ffmpeg_glue_unittest.cc',
+ 'filters/ffmpeg_h264_bitstream_converter_unittest.cc',
+ 'filters/ffmpeg_video_decoder_unittest.cc',
+ 'filters/pipeline_integration_test.cc',
+ 'filters/pipeline_integration_test_base.cc',
+ 'mp4/mp4_stream_parser_unittest.cc',
+ 'webm/webm_cluster_parser_unittest.cc',
+ ],
+ }],
+ ['OS == \"linux\"', {
+ 'conditions': [
+ ['use_cras == 1', {
+ 'sources': [
+ 'audio/linux/cras_output_unittest.cc',
+ ],
+ 'defines': [
+ 'USE_CRAS',
+ ],
+ }],
+ ],
+ }],
+ [ 'target_arch==\"ia32\" or target_arch==\"x64\"', {
+ 'sources': [
+ 'base/simd/convert_rgb_to_yuv_unittest.cc',
+ ],
+ }],
+ ['proprietary_codecs==1 or branding==\"Chrome\"', {
+ 'sources': [
+ 'mp4/avc_unittest.cc',
+ 'mp4/box_reader_unittest.cc',
+ 'mp4/mp4_stream_parser_unittest.cc',
+ 'mp4/offset_byte_queue_unittest.cc',
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'media_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'media',
+ '../base/base.gyp:base',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ ],
+ 'sources': [
+ 'audio/test_audio_input_controller_factory.cc',
+ 'audio/test_audio_input_controller_factory.h',
+ 'base/mock_callback.cc',
+ 'base/mock_callback.h',
+ 'base/mock_data_source_host.cc',
+ 'base/mock_data_source_host.h',
+ 'base/mock_demuxer_host.cc',
+ 'base/mock_demuxer_host.h',
+ 'base/mock_filter_host.cc',
+ 'base/mock_filter_host.h',
+ 'base/mock_filters.cc',
+ 'base/mock_filters.h',
+ ],
+ },
+ {
+ 'target_name': 'scaler_bench',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../skia/skia.gyp:skia',
+ ],
+ 'sources': [
+ 'tools/scaler_bench/scaler_bench.cc',
+ ],
+ },
+ {
+ 'target_name': 'qt_faststart',
+ 'type': 'executable',
+ 'sources': [
+ 'tools/qt_faststart/qt_faststart.c'
+ ],
+ },
+ {
+ 'target_name': 'seek_tester',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ '../base/base.gyp:base',
+ ],
+ 'sources': [
+ 'tools/seek_tester/seek_tester.cc',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS==\"win\"', {
+ 'targets': [
+ {
+ 'target_name': 'player_wtl',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../ui/ui.gyp:ui',
+ ],
+ 'include_dirs': [
+ '<(DEPTH)/third_party/wtl/include',
+ ],
+ 'sources': [
+ 'tools/player_wtl/list.h',
+ 'tools/player_wtl/mainfrm.h',
+ 'tools/player_wtl/movie.cc',
+ 'tools/player_wtl/movie.h',
+ 'tools/player_wtl/player_wtl.cc',
+ 'tools/player_wtl/player_wtl.rc',
+ 'tools/player_wtl/props.h',
+ 'tools/player_wtl/seek.h',
+ 'tools/player_wtl/resource.h',
+ 'tools/player_wtl/view.h',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
+ },
+ },
+ 'defines': [
+ '_CRT_SECURE_NO_WARNINGS=1',
+ ],
+ },
+ ],
+ }],
+ ['OS == \"win\" or toolkit_uses_gtk == 1', {
+ 'targets': [
+ {
+ 'target_name': 'shader_bench',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../ui/gl/gl.gyp:gl',
+ ],
+ 'sources': [
+ 'tools/shader_bench/shader_bench.cc',
+ 'tools/shader_bench/cpu_color_painter.cc',
+ 'tools/shader_bench/cpu_color_painter.h',
+ 'tools/shader_bench/gpu_color_painter.cc',
+ 'tools/shader_bench/gpu_color_painter.h',
+ 'tools/shader_bench/gpu_painter.cc',
+ 'tools/shader_bench/gpu_painter.h',
+ 'tools/shader_bench/painter.cc',
+ 'tools/shader_bench/painter.h',
+ 'tools/shader_bench/window.cc',
+ 'tools/shader_bench/window.h',
+ ],
+ 'conditions': [
+ ['toolkit_uses_gtk == 1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:gtk',
+ ],
+ 'sources': [
+ 'tools/shader_bench/window_linux.cc',
+ ],
+ }],
+ ['OS==\"win\"', {
+ 'dependencies': [
+ '../third_party/angle/src/build_angle.gyp:libEGL',
+ '../third_party/angle/src/build_angle.gyp:libGLESv2',
+ ],
+ 'sources': [
+ 'tools/shader_bench/window_win.cc',
+ ],
+ }],
+ ],
+ },
+ ],
+ }],
+ ['OS == \"linux\" and target_arch != \"arm\"', {
+ 'targets': [
+ {
+ 'target_name': 'tile_render_bench',
+ 'type': 'executable',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../ui/gl/gl.gyp:gl',
+ ],
+ 'libraries': [
+ '-lGL',
+ '-ldl',
+ ],
+ 'sources': [
+ 'tools/tile_render_bench/tile_render_bench.cc',
+ ],
+ },
+ ],
+ }],
+ ['os_posix == 1 and OS != \"mac\" and OS != \"android\"', {
+ 'targets': [
+ {
+ 'target_name': 'player_x11',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'yuv_convert',
+ '../base/base.gyp:base',
+ '../ui/gl/gl.gyp:gl',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '-ldl',
+ '-lX11',
+ '-lXrender',
+ '-lXext',
+ ],
+ },
+ 'sources': [
+ 'tools/player_x11/data_source_logger.cc',
+ 'tools/player_x11/data_source_logger.h',
+ 'tools/player_x11/gl_video_renderer.cc',
+ 'tools/player_x11/gl_video_renderer.h',
+ 'tools/player_x11/player_x11.cc',
+ 'tools/player_x11/x11_video_renderer.cc',
+ 'tools/player_x11/x11_video_renderer.h',
+ ],
+ },
+ ],
+ }],
+ ['OS == \"android\"', {
+ 'targets': [
+ {
+ 'target_name': 'player_android',
+ 'type': 'static_library',
+ 'sources': [
+ 'base/android/media_player_bridge.cc',
+ 'base/android/media_player_bridge.h',
+ ],
+ 'dependencies': [
+ '../base/base.gyp:base',
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)/media',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate-jni-headers',
+ 'inputs': [
+ '../base/android/jni_generator/jni_generator.py',
+ 'base/android/java/src/org/chromium/media/MediaPlayerListener.java',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/media/jni/media_player_listener_jni.h',
+ ],
+ 'action': [
+ 'python',
+ '<(DEPTH)/base/android/jni_generator/jni_generator.py',
+ '-o',
+ '<@(_inputs)',
+ '<@(_outputs)',
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'media_java',
+ 'type': 'none',
+ 'dependencies': [ '../base/base.gyp:base_java' ],
+ 'variables': {
+ 'package_name': 'media',
+ 'java_in_dir': 'base/android/java',
+ },
+ 'includes': [ '../build/java.gypi' ],
+ },
+
+ ],
+ }, { # OS != \"android\"'
+ # Android does not use ffmpeg, so disable the targets which require it.
+ 'targets': [
+ {
+ 'target_name': 'ffmpeg_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'media_test_support',
+ '../base/base.gyp:base',
+ '../base/base.gyp:base_i18n',
+ '../base/base.gyp:test_support_base',
+ '../base/base.gyp:test_support_perf',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ 'sources': [
+ 'ffmpeg/ffmpeg_unittest.cc',
+ ],
+ 'conditions': [
+ ['toolkit_uses_gtk == 1', {
+ 'dependencies': [
+ # Needed for the following #include chain:
+ # base/run_all_unittests.cc
+ # ../base/test_suite.h
+ # gtk/gtk.h
+ '../build/linux/system.gyp:gtk',
+ ],
+ 'conditions': [
+ ['linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '../base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'ffmpeg_regression_tests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ 'media_test_support',
+ '../base/base.gyp:test_support_base',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ 'sources': [
+ 'base/test_data_util.cc',
+ 'base/run_all_unittests.cc',
+ 'ffmpeg/ffmpeg_regression_tests.cc',
+ 'filters/pipeline_integration_test_base.cc',
+ ],
+ 'conditions': [
+ ['os_posix==1 and OS!=\"mac\"', {
+ 'conditions': [
+ ['linux_use_tcmalloc==1', {
+ 'dependencies': [
+ '../base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
+ }],
+ ],
+ },
+ {
+ 'target_name': 'ffmpeg_tests',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ '../base/base.gyp:base',
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ 'sources': [
+ 'test/ffmpeg_tests/ffmpeg_tests.cc',
+ ],
+ },
+ {
+ 'target_name': 'media_bench',
+ 'type': 'executable',
+ 'dependencies': [
+ 'media',
+ '../base/base.gyp:base',
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ ],
+ 'sources': [
+ 'tools/media_bench/media_bench.cc',
+ ],
+ },
+ ],
+ }]
+ ],
+}
+" 0 64 (face font-lock-comment-face) 64 137 (face font-lock-comment-face) 137 166 (face font-lock-comment-face) 166 171 nil 171 172 (face font-lock-string-face) 172 181 (face font-lock-keyword-face) 181 182 (face font-lock-string-face) 182 190 nil 190 191 (face font-lock-string-face) 191 204 (face font-lock-variable-name-face) 204 205 (face font-lock-string-face) 205 214 nil 214 269 (face font-lock-comment-face) 269 273 nil 273 274 (face font-lock-string-face) 274 289 (face font-lock-variable-name-face) 289 290 (face font-lock-string-face) 290 299 nil 299 365 (face font-lock-comment-face) 365 369 nil 369 370 (face font-lock-string-face) 370 379 (face font-lock-variable-name-face) 379 380 (face font-lock-string-face) 380 392 nil 392 393 (face font-lock-string-face) 393 400 (face font-lock-keyword-face) 400 401 (face font-lock-string-face) 401 417 nil 417 418 (face font-lock-string-face) 418 429 (face font-lock-keyword-face) 429 430 (face font-lock-string-face) 430 432 nil 432 433 (face font-lock-string-face) 433 438 (face font-lock-function-name-face) 438 439 (face font-lock-string-face) 439 447 nil 447 448 (face font-lock-string-face) 448 452 (face font-lock-keyword-face) 452 453 (face font-lock-string-face) 453 455 nil 455 458 (face font-lock-string-face) 458 467 (face font-lock-variable-name-face) 467 469 (face font-lock-string-face) 469 477 nil 477 478 (face font-lock-string-face) 478 490 (face font-lock-keyword-face) 490 491 (face font-lock-string-face) 491 503 nil 503 504 (face font-lock-string-face) 504 515 (face font-lock-function-name-face) 515 516 (face font-lock-string-face) 516 526 nil 526 527 (face font-lock-string-face) 527 548 (face font-lock-function-name-face) 548 549 (face font-lock-string-face) 549 559 nil 559 560 (face font-lock-string-face) 560 643 (face font-lock-function-name-face) 643 644 (face font-lock-string-face) 644 654 nil 654 655 (face font-lock-string-face) 655 696 (face font-lock-function-name-face) 696 697 (face font-lock-string-face) 697 707 nil 707 708 (face font-lock-string-face) 708 735 (face font-lock-function-name-face) 735 736 (face font-lock-string-face) 736 746 nil 746 747 (face font-lock-string-face) 747 784 (face font-lock-function-name-face) 784 785 (face font-lock-string-face) 785 795 nil 795 796 (face font-lock-string-face) 796 811 (face font-lock-function-name-face) 811 812 (face font-lock-string-face) 812 829 nil 829 830 (face font-lock-string-face) 830 837 (face font-lock-keyword-face) 837 838 (face font-lock-string-face) 838 850 nil 850 851 (face font-lock-string-face) 851 871 (face font-lock-preprocessor-face) 871 872 (face font-lock-string-face) 872 889 nil 889 890 (face font-lock-string-face) 890 902 (face font-lock-keyword-face) 902 903 (face font-lock-string-face) 903 915 nil 915 916 (face font-lock-string-face) 916 918 (face font-lock-constant-face) 918 919 (face font-lock-string-face) 919 936 nil 936 937 (face font-lock-string-face) 937 944 (face font-lock-keyword-face) 944 945 (face font-lock-string-face) 945 957 nil 957 958 (face font-lock-string-face) 958 996 (face font-lock-constant-face) 996 997 (face font-lock-string-face) 997 1007 nil 1007 1008 (face font-lock-string-face) 1008 1045 (face font-lock-constant-face) 1045 1046 (face font-lock-string-face) 1046 1056 nil 1056 1057 (face font-lock-string-face) 1057 1100 (face font-lock-constant-face) 1100 1101 (face font-lock-string-face) 1101 1111 nil 1111 1112 (face font-lock-string-face) 1112 1154 (face font-lock-constant-face) 1154 1155 (face font-lock-string-face) 1155 1165 nil 1165 1166 (face font-lock-string-face) 1166 1197 (face font-lock-constant-face) 1197 1198 (face font-lock-string-face) 1198 1208 nil 1208 1209 (face font-lock-string-face) 1209 1239 (face font-lock-constant-face) 1239 1240 (face font-lock-string-face) 1240 1250 nil 1250 1251 (face font-lock-string-face) 1251 1283 (face font-lock-constant-face) 1283 1284 (face font-lock-string-face) 1284 1294 nil 1294 1295 (face font-lock-string-face) 1295 1326 (face font-lock-constant-face) 1326 1327 (face font-lock-string-face) 1327 1337 nil 1337 1338 (face font-lock-string-face) 1338 1369 (face font-lock-constant-face) 1369 1370 (face font-lock-string-face) 1370 1380 nil 1380 1381 (face font-lock-string-face) 1381 1419 (face font-lock-constant-face) 1419 1420 (face font-lock-string-face) 1420 1430 nil 1430 1431 (face font-lock-string-face) 1431 1467 (face font-lock-constant-face) 1467 1468 (face font-lock-string-face) 1468 1478 nil 1478 1479 (face font-lock-string-face) 1479 1507 (face font-lock-constant-face) 1507 1508 (face font-lock-string-face) 1508 1518 nil 1518 1519 (face font-lock-string-face) 1519 1546 (face font-lock-constant-face) 1546 1547 (face font-lock-string-face) 1547 1557 nil 1557 1558 (face font-lock-string-face) 1558 1574 (face font-lock-constant-face) 1574 1575 (face font-lock-string-face) 1575 1585 nil 1585 1586 (face font-lock-string-face) 1586 1617 (face font-lock-constant-face) 1617 1618 (face font-lock-string-face) 1618 1628 nil 1628 1629 (face font-lock-string-face) 1629 1659 (face font-lock-constant-face) 1659 1660 (face font-lock-string-face) 1660 1670 nil 1670 1671 (face font-lock-string-face) 1671 1703 (face font-lock-constant-face) 1703 1704 (face font-lock-string-face) 1704 1714 nil 1714 1715 (face font-lock-string-face) 1715 1746 (face font-lock-constant-face) 1746 1747 (face font-lock-string-face) 1747 1757 nil 1757 1758 (face font-lock-string-face) 1758 1784 (face font-lock-constant-face) 1784 1785 (face font-lock-string-face) 1785 1795 nil 1795 1796 (face font-lock-string-face) 1796 1821 (face font-lock-constant-face) 1821 1822 (face font-lock-string-face) 1822 1832 nil 1832 1833 (face font-lock-string-face) 1833 1855 (face font-lock-constant-face) 1855 1856 (face font-lock-string-face) 1856 1866 nil 1866 1867 (face font-lock-string-face) 1867 1888 (face font-lock-constant-face) 1888 1889 (face font-lock-string-face) 1889 1899 nil 1899 1900 (face font-lock-string-face) 1900 1927 (face font-lock-constant-face) 1927 1928 (face font-lock-string-face) 1928 1938 nil 1938 1939 (face font-lock-string-face) 1939 1965 (face font-lock-constant-face) 1965 1966 (face font-lock-string-face) 1966 1976 nil 1976 1977 (face font-lock-string-face) 1977 2009 (face font-lock-constant-face) 2009 2010 (face font-lock-string-face) 2010 2020 nil 2020 2021 (face font-lock-string-face) 2021 2052 (face font-lock-constant-face) 2052 2053 (face font-lock-string-face) 2053 2063 nil 2063 2064 (face font-lock-string-face) 2064 2096 (face font-lock-constant-face) 2096 2097 (face font-lock-string-face) 2097 2107 nil 2107 2108 (face font-lock-string-face) 2108 2139 (face font-lock-constant-face) 2139 2140 (face font-lock-string-face) 2140 2150 nil 2150 2151 (face font-lock-string-face) 2151 2188 (face font-lock-constant-face) 2188 2189 (face font-lock-string-face) 2189 2199 nil 2199 2200 (face font-lock-string-face) 2200 2236 (face font-lock-constant-face) 2236 2237 (face font-lock-string-face) 2237 2247 nil 2247 2248 (face font-lock-string-face) 2248 2275 (face font-lock-constant-face) 2275 2276 (face font-lock-string-face) 2276 2286 nil 2286 2287 (face font-lock-string-face) 2287 2313 (face font-lock-constant-face) 2313 2314 (face font-lock-string-face) 2314 2324 nil 2324 2325 (face font-lock-string-face) 2325 2352 (face font-lock-constant-face) 2352 2353 (face font-lock-string-face) 2353 2363 nil 2363 2364 (face font-lock-string-face) 2364 2390 (face font-lock-constant-face) 2390 2391 (face font-lock-string-face) 2391 2401 nil 2401 2402 (face font-lock-string-face) 2402 2427 (face font-lock-constant-face) 2427 2428 (face font-lock-string-face) 2428 2438 nil 2438 2439 (face font-lock-string-face) 2439 2463 (face font-lock-constant-face) 2463 2464 (face font-lock-string-face) 2464 2474 nil 2474 2475 (face font-lock-string-face) 2475 2494 (face font-lock-constant-face) 2494 2495 (face font-lock-string-face) 2495 2505 nil 2505 2506 (face font-lock-string-face) 2506 2524 (face font-lock-constant-face) 2524 2525 (face font-lock-string-face) 2525 2535 nil 2535 2536 (face font-lock-string-face) 2536 2571 (face font-lock-constant-face) 2571 2572 (face font-lock-string-face) 2572 2582 nil 2582 2583 (face font-lock-string-face) 2583 2617 (face font-lock-constant-face) 2617 2618 (face font-lock-string-face) 2618 2628 nil 2628 2629 (face font-lock-string-face) 2629 2668 (face font-lock-constant-face) 2668 2669 (face font-lock-string-face) 2669 2679 nil 2679 2680 (face font-lock-string-face) 2680 2721 (face font-lock-constant-face) 2721 2722 (face font-lock-string-face) 2722 2732 nil 2732 2733 (face font-lock-string-face) 2733 2765 (face font-lock-constant-face) 2765 2766 (face font-lock-string-face) 2766 2776 nil 2776 2777 (face font-lock-string-face) 2777 2808 (face font-lock-constant-face) 2808 2809 (face font-lock-string-face) 2809 2819 nil 2819 2820 (face font-lock-string-face) 2820 2853 (face font-lock-constant-face) 2853 2854 (face font-lock-string-face) 2854 2864 nil 2864 2865 (face font-lock-string-face) 2865 2897 (face font-lock-constant-face) 2897 2898 (face font-lock-string-face) 2898 2908 nil 2908 2909 (face font-lock-string-face) 2909 2943 (face font-lock-constant-face) 2943 2944 (face font-lock-string-face) 2944 2954 nil 2954 2955 (face font-lock-string-face) 2955 2988 (face font-lock-constant-face) 2988 2989 (face font-lock-string-face) 2989 2999 nil 2999 3000 (face font-lock-string-face) 3000 3025 (face font-lock-constant-face) 3025 3026 (face font-lock-string-face) 3026 3036 nil 3036 3037 (face font-lock-string-face) 3037 3061 (face font-lock-constant-face) 3061 3062 (face font-lock-string-face) 3062 3072 nil 3072 3073 (face font-lock-string-face) 3073 3099 (face font-lock-constant-face) 3099 3100 (face font-lock-string-face) 3100 3110 nil 3110 3111 (face font-lock-string-face) 3111 3136 (face font-lock-constant-face) 3136 3137 (face font-lock-string-face) 3137 3147 nil 3147 3148 (face font-lock-string-face) 3148 3172 (face font-lock-constant-face) 3172 3173 (face font-lock-string-face) 3173 3183 nil 3183 3184 (face font-lock-string-face) 3184 3207 (face font-lock-constant-face) 3207 3208 (face font-lock-string-face) 3208 3218 nil 3218 3219 (face font-lock-string-face) 3219 3246 (face font-lock-constant-face) 3246 3247 (face font-lock-string-face) 3247 3257 nil 3257 3258 (face font-lock-string-face) 3258 3284 (face font-lock-constant-face) 3284 3285 (face font-lock-string-face) 3285 3295 nil 3295 3296 (face font-lock-string-face) 3296 3322 (face font-lock-constant-face) 3322 3323 (face font-lock-string-face) 3323 3333 nil 3333 3334 (face font-lock-string-face) 3334 3359 (face font-lock-constant-face) 3359 3360 (face font-lock-string-face) 3360 3370 nil 3370 3371 (face font-lock-string-face) 3371 3409 (face font-lock-constant-face) 3409 3410 (face font-lock-string-face) 3410 3420 nil 3420 3421 (face font-lock-string-face) 3421 3458 (face font-lock-constant-face) 3458 3459 (face font-lock-string-face) 3459 3469 nil 3469 3470 (face font-lock-string-face) 3470 3498 (face font-lock-constant-face) 3498 3499 (face font-lock-string-face) 3499 3509 nil 3509 3510 (face font-lock-string-face) 3510 3537 (face font-lock-constant-face) 3537 3538 (face font-lock-string-face) 3538 3548 nil 3548 3549 (face font-lock-string-face) 3549 3589 (face font-lock-constant-face) 3589 3590 (face font-lock-string-face) 3590 3600 nil 3600 3601 (face font-lock-string-face) 3601 3640 (face font-lock-constant-face) 3640 3641 (face font-lock-string-face) 3641 3651 nil 3651 3652 (face font-lock-string-face) 3652 3693 (face font-lock-constant-face) 3693 3694 (face font-lock-string-face) 3694 3704 nil 3704 3705 (face font-lock-string-face) 3705 3745 (face font-lock-constant-face) 3745 3746 (face font-lock-string-face) 3746 3756 nil 3756 3757 (face font-lock-string-face) 3757 3787 (face font-lock-constant-face) 3787 3788 (face font-lock-string-face) 3788 3798 nil 3798 3799 (face font-lock-string-face) 3799 3828 (face font-lock-constant-face) 3828 3829 (face font-lock-string-face) 3829 3839 nil 3839 3840 (face font-lock-string-face) 3840 3869 (face font-lock-constant-face) 3869 3870 (face font-lock-string-face) 3870 3880 nil 3880 3881 (face font-lock-string-face) 3881 3909 (face font-lock-constant-face) 3909 3910 (face font-lock-string-face) 3910 3920 nil 3920 3921 (face font-lock-string-face) 3921 3945 (face font-lock-constant-face) 3945 3946 (face font-lock-string-face) 3946 3956 nil 3956 3957 (face font-lock-string-face) 3957 3980 (face font-lock-constant-face) 3980 3981 (face font-lock-string-face) 3981 3991 nil 3991 3992 (face font-lock-string-face) 3992 4019 (face font-lock-constant-face) 4019 4020 (face font-lock-string-face) 4020 4030 nil 4030 4031 (face font-lock-string-face) 4031 4057 (face font-lock-constant-face) 4057 4058 (face font-lock-string-face) 4058 4068 nil 4068 4069 (face font-lock-string-face) 4069 4090 (face font-lock-constant-face) 4090 4091 (face font-lock-string-face) 4091 4101 nil 4101 4102 (face font-lock-string-face) 4102 4122 (face font-lock-constant-face) 4122 4123 (face font-lock-string-face) 4123 4133 nil 4133 4134 (face font-lock-string-face) 4134 4157 (face font-lock-constant-face) 4157 4158 (face font-lock-string-face) 4158 4168 nil 4168 4169 (face font-lock-string-face) 4169 4191 (face font-lock-constant-face) 4191 4192 (face font-lock-string-face) 4192 4202 nil 4202 4203 (face font-lock-string-face) 4203 4243 (face font-lock-constant-face) 4243 4244 (face font-lock-string-face) 4244 4254 nil 4254 4255 (face font-lock-string-face) 4255 4294 (face font-lock-constant-face) 4294 4295 (face font-lock-string-face) 4295 4305 nil 4305 4306 (face font-lock-string-face) 4306 4347 (face font-lock-constant-face) 4347 4348 (face font-lock-string-face) 4348 4358 nil 4358 4359 (face font-lock-string-face) 4359 4399 (face font-lock-constant-face) 4399 4400 (face font-lock-string-face) 4400 4410 nil 4410 4411 (face font-lock-string-face) 4411 4441 (face font-lock-constant-face) 4441 4442 (face font-lock-string-face) 4442 4452 nil 4452 4453 (face font-lock-string-face) 4453 4482 (face font-lock-constant-face) 4482 4483 (face font-lock-string-face) 4483 4493 nil 4493 4494 (face font-lock-string-face) 4494 4523 (face font-lock-constant-face) 4523 4524 (face font-lock-string-face) 4524 4534 nil 4534 4535 (face font-lock-string-face) 4535 4563 (face font-lock-constant-face) 4563 4564 (face font-lock-string-face) 4564 4574 nil 4574 4575 (face font-lock-string-face) 4575 4610 (face font-lock-constant-face) 4610 4611 (face font-lock-string-face) 4611 4621 nil 4621 4622 (face font-lock-string-face) 4622 4656 (face font-lock-constant-face) 4656 4657 (face font-lock-string-face) 4657 4667 nil 4667 4668 (face font-lock-string-face) 4668 4697 (face font-lock-constant-face) 4697 4698 (face font-lock-string-face) 4698 4708 nil 4708 4709 (face font-lock-string-face) 4709 4737 (face font-lock-constant-face) 4737 4738 (face font-lock-string-face) 4738 4748 nil 4748 4749 (face font-lock-string-face) 4749 4780 (face font-lock-constant-face) 4780 4781 (face font-lock-string-face) 4781 4791 nil 4791 4792 (face font-lock-string-face) 4792 4822 (face font-lock-constant-face) 4822 4823 (face font-lock-string-face) 4823 4833 nil 4833 4834 (face font-lock-string-face) 4834 4869 (face font-lock-constant-face) 4869 4870 (face font-lock-string-face) 4870 4880 nil 4880 4881 (face font-lock-string-face) 4881 4915 (face font-lock-constant-face) 4915 4916 (face font-lock-string-face) 4916 4926 nil 4926 4927 (face font-lock-string-face) 4927 4948 (face font-lock-constant-face) 4948 4949 (face font-lock-string-face) 4949 4959 nil 4959 4960 (face font-lock-string-face) 4960 4980 (face font-lock-constant-face) 4980 4981 (face font-lock-string-face) 4981 4991 nil 4991 4992 (face font-lock-string-face) 4992 5020 (face font-lock-constant-face) 5020 5021 (face font-lock-string-face) 5021 5031 nil 5031 5032 (face font-lock-string-face) 5032 5059 (face font-lock-constant-face) 5059 5060 (face font-lock-string-face) 5060 5070 nil 5070 5071 (face font-lock-string-face) 5071 5092 (face font-lock-constant-face) 5092 5093 (face font-lock-string-face) 5093 5103 nil 5103 5104 (face font-lock-string-face) 5104 5132 (face font-lock-constant-face) 5132 5133 (face font-lock-string-face) 5133 5143 nil 5143 5144 (face font-lock-string-face) 5144 5171 (face font-lock-constant-face) 5171 5172 (face font-lock-string-face) 5172 5182 nil 5182 5183 (face font-lock-string-face) 5183 5217 (face font-lock-constant-face) 5217 5218 (face font-lock-string-face) 5218 5228 nil 5228 5229 (face font-lock-string-face) 5229 5262 (face font-lock-constant-face) 5262 5263 (face font-lock-string-face) 5263 5273 nil 5273 5274 (face font-lock-string-face) 5274 5297 (face font-lock-constant-face) 5297 5298 (face font-lock-string-face) 5298 5308 nil 5308 5309 (face font-lock-string-face) 5309 5324 (face font-lock-constant-face) 5324 5325 (face font-lock-string-face) 5325 5335 nil 5335 5336 (face font-lock-string-face) 5336 5350 (face font-lock-constant-face) 5350 5351 (face font-lock-string-face) 5351 5361 nil 5361 5362 (face font-lock-string-face) 5362 5380 (face font-lock-constant-face) 5380 5381 (face font-lock-string-face) 5381 5391 nil 5391 5392 (face font-lock-string-face) 5392 5409 (face font-lock-constant-face) 5409 5410 (face font-lock-string-face) 5410 5420 nil 5420 5421 (face font-lock-string-face) 5421 5443 (face font-lock-constant-face) 5443 5444 (face font-lock-string-face) 5444 5454 nil 5454 5455 (face font-lock-string-face) 5455 5476 (face font-lock-constant-face) 5476 5477 (face font-lock-string-face) 5477 5487 nil 5487 5488 (face font-lock-string-face) 5488 5501 (face font-lock-constant-face) 5501 5502 (face font-lock-string-face) 5502 5512 nil 5512 5513 (face font-lock-string-face) 5513 5525 (face font-lock-constant-face) 5525 5526 (face font-lock-string-face) 5526 5536 nil 5536 5537 (face font-lock-string-face) 5537 5561 (face font-lock-constant-face) 5561 5562 (face font-lock-string-face) 5562 5572 nil 5572 5573 (face font-lock-string-face) 5573 5596 (face font-lock-constant-face) 5596 5597 (face font-lock-string-face) 5597 5607 nil 5607 5608 (face font-lock-string-face) 5608 5627 (face font-lock-constant-face) 5627 5628 (face font-lock-string-face) 5628 5638 nil 5638 5639 (face font-lock-string-face) 5639 5657 (face font-lock-constant-face) 5657 5658 (face font-lock-string-face) 5658 5668 nil 5668 5669 (face font-lock-string-face) 5669 5688 (face font-lock-constant-face) 5688 5689 (face font-lock-string-face) 5689 5699 nil 5699 5700 (face font-lock-string-face) 5700 5718 (face font-lock-constant-face) 5718 5719 (face font-lock-string-face) 5719 5729 nil 5729 5730 (face font-lock-string-face) 5730 5752 (face font-lock-constant-face) 5752 5753 (face font-lock-string-face) 5753 5763 nil 5763 5764 (face font-lock-string-face) 5764 5785 (face font-lock-constant-face) 5785 5786 (face font-lock-string-face) 5786 5796 nil 5796 5797 (face font-lock-string-face) 5797 5819 (face font-lock-constant-face) 5819 5820 (face font-lock-string-face) 5820 5830 nil 5830 5831 (face font-lock-string-face) 5831 5852 (face font-lock-constant-face) 5852 5853 (face font-lock-string-face) 5853 5863 nil 5863 5864 (face font-lock-string-face) 5864 5880 (face font-lock-constant-face) 5880 5881 (face font-lock-string-face) 5881 5891 nil 5891 5892 (face font-lock-string-face) 5892 5915 (face font-lock-constant-face) 5915 5916 (face font-lock-string-face) 5916 5926 nil 5926 5927 (face font-lock-string-face) 5927 5942 (face font-lock-constant-face) 5942 5943 (face font-lock-string-face) 5943 5953 nil 5953 5954 (face font-lock-string-face) 5954 5968 (face font-lock-constant-face) 5968 5969 (face font-lock-string-face) 5969 5979 nil 5979 5980 (face font-lock-string-face) 5980 6002 (face font-lock-constant-face) 6002 6003 (face font-lock-string-face) 6003 6013 nil 6013 6014 (face font-lock-string-face) 6014 6035 (face font-lock-constant-face) 6035 6036 (face font-lock-string-face) 6036 6046 nil 6046 6047 (face font-lock-string-face) 6047 6059 (face font-lock-constant-face) 6059 6060 (face font-lock-string-face) 6060 6070 nil 6070 6071 (face font-lock-string-face) 6071 6082 (face font-lock-constant-face) 6082 6083 (face font-lock-string-face) 6083 6093 nil 6093 6094 (face font-lock-string-face) 6094 6119 (face font-lock-constant-face) 6119 6120 (face font-lock-string-face) 6120 6130 nil 6130 6131 (face font-lock-string-face) 6131 6155 (face font-lock-constant-face) 6155 6156 (face font-lock-string-face) 6156 6166 nil 6166 6167 (face font-lock-string-face) 6167 6185 (face font-lock-constant-face) 6185 6186 (face font-lock-string-face) 6186 6196 nil 6196 6197 (face font-lock-string-face) 6197 6212 (face font-lock-constant-face) 6212 6213 (face font-lock-string-face) 6213 6223 nil 6223 6224 (face font-lock-string-face) 6224 6238 (face font-lock-constant-face) 6238 6239 (face font-lock-string-face) 6239 6249 nil 6249 6250 (face font-lock-string-face) 6250 6282 (face font-lock-constant-face) 6282 6283 (face font-lock-string-face) 6283 6293 nil 6293 6294 (face font-lock-string-face) 6294 6325 (face font-lock-constant-face) 6325 6326 (face font-lock-string-face) 6326 6336 nil 6336 6337 (face font-lock-string-face) 6337 6349 (face font-lock-constant-face) 6349 6350 (face font-lock-string-face) 6350 6360 nil 6360 6361 (face font-lock-string-face) 6361 6382 (face font-lock-constant-face) 6382 6383 (face font-lock-string-face) 6383 6393 nil 6393 6394 (face font-lock-string-face) 6394 6413 (face font-lock-constant-face) 6413 6414 (face font-lock-string-face) 6414 6424 nil 6424 6425 (face font-lock-string-face) 6425 6442 (face font-lock-constant-face) 6442 6443 (face font-lock-string-face) 6443 6453 nil 6453 6454 (face font-lock-string-face) 6454 6470 (face font-lock-constant-face) 6470 6471 (face font-lock-string-face) 6471 6481 nil 6481 6482 (face font-lock-string-face) 6482 6504 (face font-lock-constant-face) 6504 6505 (face font-lock-string-face) 6505 6515 nil 6515 6516 (face font-lock-string-face) 6516 6535 (face font-lock-constant-face) 6535 6536 (face font-lock-string-face) 6536 6546 nil 6546 6547 (face font-lock-string-face) 6547 6569 (face font-lock-constant-face) 6569 6570 (face font-lock-string-face) 6570 6580 nil 6580 6581 (face font-lock-string-face) 6581 6602 (face font-lock-constant-face) 6602 6603 (face font-lock-string-face) 6603 6613 nil 6613 6614 (face font-lock-string-face) 6614 6631 (face font-lock-constant-face) 6631 6632 (face font-lock-string-face) 6632 6642 nil 6642 6643 (face font-lock-string-face) 6643 6671 (face font-lock-constant-face) 6671 6672 (face font-lock-string-face) 6672 6682 nil 6682 6683 (face font-lock-string-face) 6683 6710 (face font-lock-constant-face) 6710 6711 (face font-lock-string-face) 6711 6721 nil 6721 6722 (face font-lock-string-face) 6722 6738 (face font-lock-constant-face) 6738 6739 (face font-lock-string-face) 6739 6749 nil 6749 6750 (face font-lock-string-face) 6750 6765 (face font-lock-constant-face) 6765 6766 (face font-lock-string-face) 6766 6776 nil 6776 6777 (face font-lock-string-face) 6777 6800 (face font-lock-constant-face) 6800 6801 (face font-lock-string-face) 6801 6811 nil 6811 6812 (face font-lock-string-face) 6812 6834 (face font-lock-constant-face) 6834 6835 (face font-lock-string-face) 6835 6845 nil 6845 6846 (face font-lock-string-face) 6846 6860 (face font-lock-constant-face) 6860 6861 (face font-lock-string-face) 6861 6871 nil 6871 6872 (face font-lock-string-face) 6872 6885 (face font-lock-constant-face) 6885 6886 (face font-lock-string-face) 6886 6896 nil 6896 6897 (face font-lock-string-face) 6897 6920 (face font-lock-constant-face) 6920 6921 (face font-lock-string-face) 6921 6931 nil 6931 6932 (face font-lock-string-face) 6932 6954 (face font-lock-constant-face) 6954 6955 (face font-lock-string-face) 6955 6965 nil 6965 6966 (face font-lock-string-face) 6966 6986 (face font-lock-constant-face) 6986 6987 (face font-lock-string-face) 6987 6997 nil 6997 6998 (face font-lock-string-face) 6998 7017 (face font-lock-constant-face) 7017 7018 (face font-lock-string-face) 7018 7028 nil 7028 7029 (face font-lock-string-face) 7029 7050 (face font-lock-constant-face) 7050 7051 (face font-lock-string-face) 7051 7061 nil 7061 7062 (face font-lock-string-face) 7062 7082 (face font-lock-constant-face) 7082 7083 (face font-lock-string-face) 7083 7093 nil 7093 7094 (face font-lock-string-face) 7094 7122 (face font-lock-constant-face) 7122 7123 (face font-lock-string-face) 7123 7133 nil 7133 7134 (face font-lock-string-face) 7134 7161 (face font-lock-constant-face) 7161 7162 (face font-lock-string-face) 7162 7172 nil 7172 7173 (face font-lock-string-face) 7173 7194 (face font-lock-constant-face) 7194 7195 (face font-lock-string-face) 7195 7205 nil 7205 7206 (face font-lock-string-face) 7206 7226 (face font-lock-constant-face) 7226 7227 (face font-lock-string-face) 7227 7237 nil 7237 7238 (face font-lock-string-face) 7238 7266 (face font-lock-constant-face) 7266 7267 (face font-lock-string-face) 7267 7277 nil 7277 7278 (face font-lock-string-face) 7278 7305 (face font-lock-constant-face) 7305 7306 (face font-lock-string-face) 7306 7316 nil 7316 7317 (face font-lock-string-face) 7317 7336 (face font-lock-constant-face) 7336 7337 (face font-lock-string-face) 7337 7347 nil 7347 7348 (face font-lock-string-face) 7348 7366 (face font-lock-constant-face) 7366 7367 (face font-lock-string-face) 7367 7377 nil 7377 7378 (face font-lock-string-face) 7378 7399 (face font-lock-constant-face) 7399 7400 (face font-lock-string-face) 7400 7410 nil 7410 7411 (face font-lock-string-face) 7411 7429 (face font-lock-constant-face) 7429 7430 (face font-lock-string-face) 7430 7440 nil 7440 7441 (face font-lock-string-face) 7441 7458 (face font-lock-constant-face) 7458 7459 (face font-lock-string-face) 7459 7469 nil 7469 7470 (face font-lock-string-face) 7470 7493 (face font-lock-constant-face) 7493 7494 (face font-lock-string-face) 7494 7504 nil 7504 7505 (face font-lock-string-face) 7505 7527 (face font-lock-constant-face) 7527 7528 (face font-lock-string-face) 7528 7538 nil 7538 7539 (face font-lock-string-face) 7539 7562 (face font-lock-constant-face) 7562 7563 (face font-lock-string-face) 7563 7573 nil 7573 7574 (face font-lock-string-face) 7574 7596 (face font-lock-constant-face) 7596 7597 (face font-lock-string-face) 7597 7607 nil 7607 7608 (face font-lock-string-face) 7608 7631 (face font-lock-constant-face) 7631 7632 (face font-lock-string-face) 7632 7642 nil 7642 7643 (face font-lock-string-face) 7643 7665 (face font-lock-constant-face) 7665 7666 (face font-lock-string-face) 7666 7676 nil 7676 7677 (face font-lock-string-face) 7677 7705 (face font-lock-constant-face) 7705 7706 (face font-lock-string-face) 7706 7716 nil 7716 7717 (face font-lock-string-face) 7717 7744 (face font-lock-constant-face) 7744 7745 (face font-lock-string-face) 7745 7755 nil 7755 7756 (face font-lock-string-face) 7756 7791 (face font-lock-constant-face) 7791 7792 (face font-lock-string-face) 7792 7802 nil 7802 7803 (face font-lock-string-face) 7803 7837 (face font-lock-constant-face) 7837 7838 (face font-lock-string-face) 7838 7848 nil 7848 7849 (face font-lock-string-face) 7849 7879 (face font-lock-constant-face) 7879 7880 (face font-lock-string-face) 7880 7890 nil 7890 7891 (face font-lock-string-face) 7891 7920 (face font-lock-constant-face) 7920 7921 (face font-lock-string-face) 7921 7931 nil 7931 7932 (face font-lock-string-face) 7932 7962 (face font-lock-constant-face) 7962 7963 (face font-lock-string-face) 7963 7973 nil 7973 7974 (face font-lock-string-face) 7974 8003 (face font-lock-constant-face) 8003 8004 (face font-lock-string-face) 8004 8014 nil 8014 8015 (face font-lock-string-face) 8015 8039 (face font-lock-constant-face) 8039 8040 (face font-lock-string-face) 8040 8050 nil 8050 8051 (face font-lock-string-face) 8051 8074 (face font-lock-constant-face) 8074 8075 (face font-lock-string-face) 8075 8085 nil 8085 8086 (face font-lock-string-face) 8086 8116 (face font-lock-constant-face) 8116 8117 (face font-lock-string-face) 8117 8127 nil 8127 8128 (face font-lock-string-face) 8128 8152 (face font-lock-constant-face) 8152 8153 (face font-lock-string-face) 8153 8163 nil 8163 8164 (face font-lock-string-face) 8164 8187 (face font-lock-constant-face) 8187 8188 (face font-lock-string-face) 8188 8198 nil 8198 8199 (face font-lock-string-face) 8199 8230 (face font-lock-constant-face) 8230 8231 (face font-lock-string-face) 8231 8241 nil 8241 8242 (face font-lock-string-face) 8242 8272 (face font-lock-constant-face) 8272 8273 (face font-lock-string-face) 8273 8283 nil 8283 8284 (face font-lock-string-face) 8284 8309 (face font-lock-constant-face) 8309 8310 (face font-lock-string-face) 8310 8320 nil 8320 8321 (face font-lock-string-face) 8321 8345 (face font-lock-constant-face) 8345 8346 (face font-lock-string-face) 8346 8356 nil 8356 8357 (face font-lock-string-face) 8357 8399 (face font-lock-constant-face) 8399 8400 (face font-lock-string-face) 8400 8410 nil 8410 8411 (face font-lock-string-face) 8411 8452 (face font-lock-constant-face) 8452 8453 (face font-lock-string-face) 8453 8463 nil 8463 8464 (face font-lock-string-face) 8464 8486 (face font-lock-constant-face) 8486 8487 (face font-lock-string-face) 8487 8497 nil 8497 8498 (face font-lock-string-face) 8498 8519 (face font-lock-constant-face) 8519 8520 (face font-lock-string-face) 8520 8530 nil 8530 8531 (face font-lock-string-face) 8531 8562 (face font-lock-constant-face) 8562 8563 (face font-lock-string-face) 8563 8573 nil 8573 8574 (face font-lock-string-face) 8574 8604 (face font-lock-constant-face) 8604 8605 (face font-lock-string-face) 8605 8615 nil 8615 8616 (face font-lock-string-face) 8616 8643 (face font-lock-constant-face) 8643 8644 (face font-lock-string-face) 8644 8654 nil 8654 8655 (face font-lock-string-face) 8655 8681 (face font-lock-constant-face) 8681 8682 (face font-lock-string-face) 8682 8692 nil 8692 8693 (face font-lock-string-face) 8693 8721 (face font-lock-constant-face) 8721 8722 (face font-lock-string-face) 8722 8732 nil 8732 8733 (face font-lock-string-face) 8733 8760 (face font-lock-constant-face) 8760 8761 (face font-lock-string-face) 8761 8771 nil 8771 8772 (face font-lock-string-face) 8772 8805 (face font-lock-constant-face) 8805 8806 (face font-lock-string-face) 8806 8816 nil 8816 8817 (face font-lock-string-face) 8817 8849 (face font-lock-constant-face) 8849 8850 (face font-lock-string-face) 8850 8860 nil 8860 8861 (face font-lock-string-face) 8861 8892 (face font-lock-constant-face) 8892 8893 (face font-lock-string-face) 8893 8903 nil 8903 8904 (face font-lock-string-face) 8904 8934 (face font-lock-constant-face) 8934 8935 (face font-lock-string-face) 8935 8945 nil 8945 8946 (face font-lock-string-face) 8946 8978 (face font-lock-constant-face) 8978 8979 (face font-lock-string-face) 8979 8989 nil 8989 8990 (face font-lock-string-face) 8990 9021 (face font-lock-constant-face) 9021 9022 (face font-lock-string-face) 9022 9032 nil 9032 9033 (face font-lock-string-face) 9033 9063 (face font-lock-constant-face) 9063 9064 (face font-lock-string-face) 9064 9074 nil 9074 9075 (face font-lock-string-face) 9075 9104 (face font-lock-constant-face) 9104 9105 (face font-lock-string-face) 9105 9115 nil 9115 9116 (face font-lock-string-face) 9116 9158 (face font-lock-constant-face) 9158 9159 (face font-lock-string-face) 9159 9169 nil 9169 9170 (face font-lock-string-face) 9170 9211 (face font-lock-constant-face) 9211 9212 (face font-lock-string-face) 9212 9222 nil 9222 9223 (face font-lock-string-face) 9223 9272 (face font-lock-constant-face) 9272 9273 (face font-lock-string-face) 9273 9283 nil 9283 9284 (face font-lock-string-face) 9284 9332 (face font-lock-constant-face) 9332 9333 (face font-lock-string-face) 9333 9343 nil 9343 9344 (face font-lock-string-face) 9344 9388 (face font-lock-constant-face) 9388 9389 (face font-lock-string-face) 9389 9399 nil 9399 9400 (face font-lock-string-face) 9400 9445 (face font-lock-constant-face) 9445 9446 (face font-lock-string-face) 9446 9456 nil 9456 9457 (face font-lock-string-face) 9457 9507 (face font-lock-constant-face) 9507 9508 (face font-lock-string-face) 9508 9518 nil 9518 9519 (face font-lock-string-face) 9519 9570 (face font-lock-constant-face) 9570 9571 (face font-lock-string-face) 9571 9581 nil 9581 9582 (face font-lock-string-face) 9582 9611 (face font-lock-constant-face) 9611 9612 (face font-lock-string-face) 9612 9622 nil 9622 9623 (face font-lock-string-face) 9623 9659 (face font-lock-constant-face) 9659 9660 (face font-lock-string-face) 9660 9670 nil 9670 9671 (face font-lock-string-face) 9671 9714 (face font-lock-constant-face) 9714 9715 (face font-lock-string-face) 9715 9725 nil 9725 9726 (face font-lock-string-face) 9726 9768 (face font-lock-constant-face) 9768 9769 (face font-lock-string-face) 9769 9779 nil 9779 9780 (face font-lock-string-face) 9780 9816 (face font-lock-constant-face) 9816 9817 (face font-lock-string-face) 9817 9827 nil 9827 9828 (face font-lock-string-face) 9828 9863 (face font-lock-constant-face) 9863 9864 (face font-lock-string-face) 9864 9874 nil 9874 9875 (face font-lock-string-face) 9875 9910 (face font-lock-constant-face) 9910 9911 (face font-lock-string-face) 9911 9921 nil 9921 9922 (face font-lock-string-face) 9922 9958 (face font-lock-constant-face) 9958 9959 (face font-lock-string-face) 9959 9969 nil 9969 9970 (face font-lock-string-face) 9970 10005 (face font-lock-constant-face) 10005 10006 (face font-lock-string-face) 10006 10016 nil 10016 10017 (face font-lock-string-face) 10017 10050 (face font-lock-constant-face) 10050 10051 (face font-lock-string-face) 10051 10061 nil 10061 10062 (face font-lock-string-face) 10062 10094 (face font-lock-constant-face) 10094 10095 (face font-lock-string-face) 10095 10105 nil 10105 10106 (face font-lock-string-face) 10106 10150 (face font-lock-constant-face) 10150 10151 (face font-lock-string-face) 10151 10161 nil 10161 10162 (face font-lock-string-face) 10162 10198 (face font-lock-constant-face) 10198 10199 (face font-lock-string-face) 10199 10209 nil 10209 10210 (face font-lock-string-face) 10210 10245 (face font-lock-constant-face) 10245 10246 (face font-lock-string-face) 10246 10256 nil 10256 10257 (face font-lock-string-face) 10257 10296 (face font-lock-constant-face) 10296 10297 (face font-lock-string-face) 10297 10307 nil 10307 10308 (face font-lock-string-face) 10308 10346 (face font-lock-constant-face) 10346 10347 (face font-lock-string-face) 10347 10357 nil 10357 10358 (face font-lock-string-face) 10358 10403 (face font-lock-constant-face) 10403 10404 (face font-lock-string-face) 10404 10414 nil 10414 10415 (face font-lock-string-face) 10415 10459 (face font-lock-constant-face) 10459 10460 (face font-lock-string-face) 10460 10470 nil 10470 10471 (face font-lock-string-face) 10471 10487 (face font-lock-constant-face) 10487 10488 (face font-lock-string-face) 10488 10498 nil 10498 10499 (face font-lock-string-face) 10499 10514 (face font-lock-constant-face) 10514 10515 (face font-lock-string-face) 10515 10525 nil 10525 10526 (face font-lock-string-face) 10526 10559 (face font-lock-constant-face) 10559 10560 (face font-lock-string-face) 10560 10570 nil 10570 10571 (face font-lock-string-face) 10571 10603 (face font-lock-constant-face) 10603 10604 (face font-lock-string-face) 10604 10614 nil 10614 10615 (face font-lock-string-face) 10615 10636 (face font-lock-constant-face) 10636 10637 (face font-lock-string-face) 10637 10647 nil 10647 10648 (face font-lock-string-face) 10648 10675 (face font-lock-constant-face) 10675 10676 (face font-lock-string-face) 10676 10686 nil 10686 10687 (face font-lock-string-face) 10687 10713 (face font-lock-constant-face) 10713 10714 (face font-lock-string-face) 10714 10724 nil 10724 10725 (face font-lock-string-face) 10725 10755 (face font-lock-constant-face) 10755 10756 (face font-lock-string-face) 10756 10766 nil 10766 10767 (face font-lock-string-face) 10767 10796 (face font-lock-constant-face) 10796 10797 (face font-lock-string-face) 10797 10807 nil 10807 10808 (face font-lock-string-face) 10808 10845 (face font-lock-constant-face) 10845 10846 (face font-lock-string-face) 10846 10856 nil 10856 10857 (face font-lock-string-face) 10857 10893 (face font-lock-constant-face) 10893 10894 (face font-lock-string-face) 10894 10904 nil 10904 10905 (face font-lock-string-face) 10905 10929 (face font-lock-constant-face) 10929 10930 (face font-lock-string-face) 10930 10940 nil 10940 10941 (face font-lock-string-face) 10941 10964 (face font-lock-constant-face) 10964 10965 (face font-lock-string-face) 10965 10975 nil 10975 10976 (face font-lock-string-face) 10976 10995 (face font-lock-constant-face) 10995 10996 (face font-lock-string-face) 10996 11006 nil 11006 11007 (face font-lock-string-face) 11007 11025 (face font-lock-constant-face) 11025 11026 (face font-lock-string-face) 11026 11036 nil 11036 11037 (face font-lock-string-face) 11037 11063 (face font-lock-constant-face) 11063 11064 (face font-lock-string-face) 11064 11074 nil 11074 11075 (face font-lock-string-face) 11075 11100 (face font-lock-constant-face) 11100 11101 (face font-lock-string-face) 11101 11111 nil 11111 11112 (face font-lock-string-face) 11112 11138 (face font-lock-constant-face) 11138 11139 (face font-lock-string-face) 11139 11149 nil 11149 11150 (face font-lock-string-face) 11150 11175 (face font-lock-constant-face) 11175 11176 (face font-lock-string-face) 11176 11193 nil 11193 11194 (face font-lock-string-face) 11194 11219 (face font-lock-keyword-face) 11219 11220 (face font-lock-string-face) 11220 11232 nil 11232 11233 (face font-lock-string-face) 11233 11245 (face font-lock-keyword-face) 11245 11246 (face font-lock-string-face) 11246 11260 nil 11260 11261 (face font-lock-string-face) 11261 11263 (face font-lock-constant-face) 11263 11264 (face font-lock-string-face) 11264 11292 nil 11292 11293 (face font-lock-string-face) 11293 11303 (face font-lock-keyword-face) 11303 11304 (face font-lock-string-face) 11304 11316 nil 11316 11381 (face font-lock-comment-face) 11381 11389 nil 11389 11439 (face font-lock-comment-face) 11439 11448 nil 11448 11449 (face font-lock-string-face) 11449 11464 (face font-lock-variable-name-face) 11464 11465 (face font-lock-string-face) 11465 11479 nil 11479 11480 (face font-lock-string-face) 11480 11492 (face font-lock-keyword-face) 11492 11493 (face font-lock-string-face) 11493 11509 nil 11509 11510 (face font-lock-string-face) 11510 11549 (face font-lock-function-name-face) 11549 11550 (face font-lock-string-face) 11550 11586 nil 11586 11587 (face font-lock-string-face) 11587 11602 (face font-lock-variable-name-face) 11602 11603 (face font-lock-string-face) 11603 11617 nil 11617 11618 (face font-lock-string-face) 11618 11626 (face font-lock-keyword-face) 11626 11627 (face font-lock-string-face) 11627 11643 nil 11643 11644 (face font-lock-string-face) 11644 11663 (face font-lock-constant-face) 11663 11664 (face font-lock-string-face) 11664 11678 nil 11678 11679 (face font-lock-string-face) 11679 11702 (face font-lock-constant-face) 11702 11703 (face font-lock-string-face) 11703 11717 nil 11717 11718 (face font-lock-string-face) 11718 11740 (face font-lock-constant-face) 11740 11741 (face font-lock-string-face) 11741 11755 nil 11755 11756 (face font-lock-string-face) 11756 11779 (face font-lock-constant-face) 11779 11780 (face font-lock-string-face) 11780 11794 nil 11794 11795 (face font-lock-string-face) 11795 11817 (face font-lock-constant-face) 11817 11818 (face font-lock-string-face) 11818 11832 nil 11832 11833 (face font-lock-string-face) 11833 11861 (face font-lock-constant-face) 11861 11862 (face font-lock-string-face) 11862 11876 nil 11876 11877 (face font-lock-string-face) 11877 11904 (face font-lock-constant-face) 11904 11905 (face font-lock-string-face) 11905 11919 nil 11919 11920 (face font-lock-string-face) 11920 11950 (face font-lock-constant-face) 11950 11951 (face font-lock-string-face) 11951 11965 nil 11965 11966 (face font-lock-string-face) 11966 11995 (face font-lock-constant-face) 11995 11996 (face font-lock-string-face) 11996 12010 nil 12010 12011 (face font-lock-string-face) 12011 12035 (face font-lock-constant-face) 12035 12036 (face font-lock-string-face) 12036 12050 nil 12050 12051 (face font-lock-string-face) 12051 12074 (face font-lock-constant-face) 12074 12075 (face font-lock-string-face) 12075 12089 nil 12089 12090 (face font-lock-string-face) 12090 12120 (face font-lock-constant-face) 12120 12121 (face font-lock-string-face) 12121 12135 nil 12135 12136 (face font-lock-string-face) 12136 12167 (face font-lock-constant-face) 12167 12168 (face font-lock-string-face) 12168 12182 nil 12182 12183 (face font-lock-string-face) 12183 12213 (face font-lock-constant-face) 12213 12214 (face font-lock-string-face) 12214 12228 nil 12228 12229 (face font-lock-string-face) 12229 12254 (face font-lock-constant-face) 12254 12255 (face font-lock-string-face) 12255 12269 nil 12269 12270 (face font-lock-string-face) 12270 12294 (face font-lock-constant-face) 12294 12295 (face font-lock-string-face) 12295 12309 nil 12309 12310 (face font-lock-string-face) 12310 12352 (face font-lock-constant-face) 12352 12353 (face font-lock-string-face) 12353 12367 nil 12367 12368 (face font-lock-string-face) 12368 12409 (face font-lock-constant-face) 12409 12410 (face font-lock-string-face) 12410 12424 nil 12424 12425 (face font-lock-string-face) 12425 12447 (face font-lock-constant-face) 12447 12448 (face font-lock-string-face) 12448 12462 nil 12462 12463 (face font-lock-string-face) 12463 12484 (face font-lock-constant-face) 12484 12485 (face font-lock-string-face) 12485 12499 nil 12499 12500 (face font-lock-string-face) 12500 12531 (face font-lock-constant-face) 12531 12532 (face font-lock-string-face) 12532 12546 nil 12546 12547 (face font-lock-string-face) 12547 12577 (face font-lock-constant-face) 12577 12578 (face font-lock-string-face) 12578 12592 nil 12592 12593 (face font-lock-string-face) 12593 12621 (face font-lock-constant-face) 12621 12622 (face font-lock-string-face) 12622 12636 nil 12636 12637 (face font-lock-string-face) 12637 12664 (face font-lock-constant-face) 12664 12665 (face font-lock-string-face) 12665 12679 nil 12679 12680 (face font-lock-string-face) 12680 12707 (face font-lock-constant-face) 12707 12708 (face font-lock-string-face) 12708 12722 nil 12722 12723 (face font-lock-string-face) 12723 12749 (face font-lock-constant-face) 12749 12750 (face font-lock-string-face) 12750 12764 nil 12764 12765 (face font-lock-string-face) 12765 12791 (face font-lock-constant-face) 12791 12792 (face font-lock-string-face) 12792 12806 nil 12806 12807 (face font-lock-string-face) 12807 12832 (face font-lock-constant-face) 12832 12833 (face font-lock-string-face) 12833 12868 nil 12868 12937 (face font-lock-comment-face) 12937 12945 nil 12945 13016 (face font-lock-comment-face) 13016 13024 nil 13024 13040 (face font-lock-comment-face) 13040 13049 nil 13049 13050 (face font-lock-string-face) 13050 13065 (face font-lock-variable-name-face) 13065 13066 (face font-lock-string-face) 13066 13080 nil 13080 13081 (face font-lock-string-face) 13081 13089 (face font-lock-keyword-face) 13089 13090 (face font-lock-string-face) 13090 13105 nil 13105 13106 (face font-lock-string-face) 13106 13149 (face font-lock-constant-face) 13149 13150 (face font-lock-string-face) 13150 13175 nil 13175 13176 (face font-lock-string-face) 13176 13183 (face font-lock-keyword-face) 13183 13184 (face font-lock-string-face) 13184 13199 nil 13199 13200 (face font-lock-string-face) 13200 13248 (face font-lock-constant-face) 13248 13249 (face font-lock-string-face) 13249 13274 nil 13274 13275 (face font-lock-string-face) 13275 13288 (face font-lock-keyword-face) 13288 13289 (face font-lock-string-face) 13289 13305 nil 13305 13306 (face font-lock-string-face) 13306 13315 (face font-lock-keyword-face) 13315 13316 (face font-lock-string-face) 13316 13334 nil 13334 13335 (face font-lock-string-face) 13335 13345 (face font-lock-constant-face) 13345 13346 (face font-lock-string-face) 13346 13397 nil 13397 13398 (face font-lock-string-face) 13398 13443 (face font-lock-variable-name-face) 13443 13444 (face font-lock-string-face) 13444 13458 nil 13458 13459 (face font-lock-string-face) 13459 13472 (face font-lock-keyword-face) 13472 13473 (face font-lock-string-face) 13473 13489 nil 13489 13490 (face font-lock-string-face) 13490 13499 (face font-lock-keyword-face) 13499 13500 (face font-lock-string-face) 13500 13518 nil 13518 13519 (face font-lock-string-face) 13519 13527 (face font-lock-constant-face) 13527 13528 (face font-lock-string-face) 13528 13579 nil 13579 13580 (face font-lock-string-face) 13580 13593 (face font-lock-variable-name-face) 13593 13594 (face font-lock-string-face) 13594 13608 nil 13608 13609 (face font-lock-string-face) 13609 13617 (face font-lock-keyword-face) 13617 13618 (face font-lock-string-face) 13618 13623 nil 13623 13624 (face font-lock-string-face) 13624 13631 (face font-lock-constant-face) 13631 13632 (face font-lock-string-face) 13632 13634 nil 13634 13635 (face font-lock-string-face) 13635 13641 (face font-lock-constant-face) 13641 13642 (face font-lock-string-face) 13642 13671 nil 13671 13672 (face font-lock-string-face) 13672 13679 (face font-lock-constant-face) 13679 13680 (face font-lock-string-face) 13680 13682 nil 13682 13683 (face font-lock-string-face) 13683 13703 (face font-lock-constant-face) 13703 13704 (face font-lock-string-face) 13704 13720 nil 13720 13721 (face font-lock-string-face) 13721 13734 (face font-lock-keyword-face) 13734 13735 (face font-lock-string-face) 13735 13751 nil 13751 13752 (face font-lock-string-face) 13752 13761 (face font-lock-keyword-face) 13761 13762 (face font-lock-string-face) 13762 13815 nil 13815 13816 (face font-lock-string-face) 13816 13829 (face font-lock-variable-name-face) 13829 13830 (face font-lock-string-face) 13830 13844 nil 13844 13845 (face font-lock-string-face) 13845 13853 (face font-lock-keyword-face) 13853 13854 (face font-lock-string-face) 13854 13870 nil 13870 13871 (face font-lock-string-face) 13871 13909 (face font-lock-constant-face) 13909 13910 (face font-lock-string-face) 13910 13924 nil 13924 13925 (face font-lock-string-face) 13925 13962 (face font-lock-constant-face) 13962 13963 (face font-lock-string-face) 13963 13999 nil 13999 14000 (face font-lock-string-face) 14000 14011 (face font-lock-variable-name-face) 14011 14012 (face font-lock-string-face) 14012 14026 nil 14026 14027 (face font-lock-string-face) 14027 14036 (face font-lock-keyword-face) 14036 14037 (face font-lock-string-face) 14037 14053 nil 14053 14054 (face font-lock-string-face) 14054 14064 (face font-lock-keyword-face) 14064 14065 (face font-lock-string-face) 14065 14084 nil 14084 14085 (face font-lock-string-face) 14085 14096 (face font-lock-variable-name-face) 14096 14097 (face font-lock-string-face) 14097 14117 nil 14117 14129 (face font-lock-string-face) 14129 14131 nil 14131 14169 (face font-lock-string-face) 14169 14176 (face font-lock-variable-name-face) 14176 14182 (face font-lock-string-face) 14182 14193 (face font-lock-variable-name-face) 14193 14196 (face font-lock-string-face) 14196 14233 nil 14233 14245 (face font-lock-string-face) 14245 14247 nil 14247 14259 (face font-lock-string-face) 14259 14316 nil 14316 14317 (face font-lock-string-face) 14317 14327 (face font-lock-keyword-face) 14327 14328 (face font-lock-string-face) 14328 14345 nil 14345 14346 (face font-lock-string-face) 14346 14359 (face font-lock-variable-name-face) 14359 14360 (face font-lock-string-face) 14360 14378 nil 14378 14379 (face font-lock-string-face) 14379 14385 (face font-lock-keyword-face) 14385 14386 (face font-lock-string-face) 14386 14406 nil 14406 14411 (face font-lock-string-face) 14411 14413 (face font-lock-variable-name-face) 14413 14423 (face font-lock-variable-name-face) 14423 14443 (face font-lock-string-face) 14443 14476 nil 14476 14477 (face font-lock-string-face) 14477 14490 (face font-lock-keyword-face) 14490 14491 (face font-lock-string-face) 14491 14511 nil 14511 14512 (face font-lock-string-face) 14512 14521 (face font-lock-keyword-face) 14521 14522 (face font-lock-string-face) 14522 14544 nil 14544 14545 (face font-lock-string-face) 14545 14549 (face font-lock-constant-face) 14549 14551 (face font-lock-variable-name-face) 14551 14561 (face font-lock-variable-name-face) 14561 14578 (face font-lock-constant-face) 14578 14579 (face font-lock-string-face) 14579 14631 nil 14631 14632 (face font-lock-string-face) 14632 14639 (face font-lock-keyword-face) 14639 14640 (face font-lock-string-face) 14640 14660 nil 14660 14661 (face font-lock-string-face) 14661 14669 (face font-lock-preprocessor-face) 14669 14670 (face font-lock-string-face) 14670 14707 nil 14707 14729 (face font-lock-comment-face) 14729 14743 nil 14743 14744 (face font-lock-string-face) 14744 14752 (face font-lock-keyword-face) 14752 14753 (face font-lock-string-face) 14753 14773 nil 14773 14774 (face font-lock-string-face) 14774 14800 (face font-lock-constant-face) 14800 14801 (face font-lock-string-face) 14801 14819 nil 14819 14820 (face font-lock-string-face) 14820 14845 (face font-lock-constant-face) 14845 14846 (face font-lock-string-face) 14846 14915 nil 14915 14916 (face font-lock-string-face) 14916 14929 (face font-lock-variable-name-face) 14929 14930 (face font-lock-string-face) 14930 14944 nil 14944 14945 (face font-lock-string-face) 14945 14955 (face font-lock-keyword-face) 14955 14956 (face font-lock-string-face) 14956 14973 nil 14973 14974 (face font-lock-string-face) 14974 14993 (face font-lock-variable-name-face) 14993 14994 (face font-lock-string-face) 14994 15012 nil 15012 15013 (face font-lock-string-face) 15013 15019 (face font-lock-keyword-face) 15019 15020 (face font-lock-string-face) 15020 15040 nil 15040 15075 (face font-lock-string-face) 15075 15108 nil 15108 15109 (face font-lock-string-face) 15109 15122 (face font-lock-keyword-face) 15122 15123 (face font-lock-string-face) 15123 15143 nil 15143 15144 (face font-lock-string-face) 15144 15153 (face font-lock-keyword-face) 15153 15154 (face font-lock-string-face) 15154 15176 nil 15176 15177 (face font-lock-string-face) 15177 15215 (face font-lock-constant-face) 15215 15216 (face font-lock-string-face) 15216 15268 nil 15268 15269 (face font-lock-string-face) 15269 15276 (face font-lock-keyword-face) 15276 15277 (face font-lock-string-face) 15277 15297 nil 15297 15298 (face font-lock-string-face) 15298 15312 (face font-lock-preprocessor-face) 15312 15313 (face font-lock-string-face) 15313 15350 nil 15350 15378 (face font-lock-comment-face) 15378 15392 nil 15392 15393 (face font-lock-string-face) 15393 15401 (face font-lock-keyword-face) 15401 15402 (face font-lock-string-face) 15402 15422 nil 15422 15423 (face font-lock-string-face) 15423 15450 (face font-lock-constant-face) 15450 15451 (face font-lock-string-face) 15451 15469 nil 15469 15470 (face font-lock-string-face) 15470 15496 (face font-lock-constant-face) 15496 15497 (face font-lock-string-face) 15497 15566 nil 15566 15567 (face font-lock-string-face) 15567 15600 (face font-lock-variable-name-face) 15600 15601 (face font-lock-string-face) 15601 15615 nil 15615 15663 (face font-lock-comment-face) 15663 15673 nil 15673 15674 (face font-lock-string-face) 15674 15682 (face font-lock-keyword-face) 15682 15683 (face font-lock-string-face) 15683 15699 nil 15699 15700 (face font-lock-string-face) 15700 15743 (face font-lock-constant-face) 15743 15744 (face font-lock-string-face) 15744 15758 nil 15758 15759 (face font-lock-string-face) 15759 15801 (face font-lock-constant-face) 15801 15802 (face font-lock-string-face) 15802 15838 nil 15838 15839 (face font-lock-string-face) 15839 15848 (face font-lock-variable-name-face) 15848 15849 (face font-lock-string-face) 15849 15863 nil 15863 15864 (face font-lock-string-face) 15864 15877 (face font-lock-keyword-face) 15877 15878 (face font-lock-string-face) 15878 15894 nil 15894 15895 (face font-lock-string-face) 15895 15904 (face font-lock-keyword-face) 15904 15905 (face font-lock-string-face) 15905 15923 nil 15923 15924 (face font-lock-string-face) 15924 15980 (face font-lock-constant-face) 15980 15981 (face font-lock-string-face) 15981 15997 nil 15997 15998 (face font-lock-string-face) 15998 16057 (face font-lock-constant-face) 16057 16058 (face font-lock-string-face) 16058 16074 nil 16074 16075 (face font-lock-string-face) 16075 16131 (face font-lock-constant-face) 16131 16132 (face font-lock-string-face) 16132 16148 nil 16148 16149 (face font-lock-string-face) 16149 16205 (face font-lock-constant-face) 16205 16206 (face font-lock-string-face) 16206 16222 nil 16222 16223 (face font-lock-string-face) 16223 16275 (face font-lock-constant-face) 16275 16276 (face font-lock-string-face) 16276 16327 nil 16327 16328 (face font-lock-string-face) 16328 16337 (face font-lock-variable-name-face) 16337 16338 (face font-lock-string-face) 16338 16352 nil 16352 16353 (face font-lock-string-face) 16353 16361 (face font-lock-keyword-face) 16361 16362 (face font-lock-string-face) 16362 16378 nil 16378 16379 (face font-lock-string-face) 16379 16406 (face font-lock-constant-face) 16406 16407 (face font-lock-string-face) 16407 16421 nil 16421 16422 (face font-lock-string-face) 16422 16448 (face font-lock-constant-face) 16448 16449 (face font-lock-string-face) 16449 16463 nil 16463 16464 (face font-lock-string-face) 16464 16507 (face font-lock-constant-face) 16507 16508 (face font-lock-string-face) 16508 16522 nil 16522 16523 (face font-lock-string-face) 16523 16565 (face font-lock-constant-face) 16565 16566 (face font-lock-string-face) 16566 16602 nil 16602 16603 (face font-lock-string-face) 16603 16646 (face font-lock-variable-name-face) 16646 16647 (face font-lock-string-face) 16647 16661 nil 16661 16662 (face font-lock-string-face) 16662 16669 (face font-lock-keyword-face) 16669 16670 (face font-lock-string-face) 16670 16686 nil 16686 16687 (face font-lock-string-face) 16687 16697 (face font-lock-constant-face) 16697 16698 (face font-lock-string-face) 16698 16712 nil 16712 16713 (face font-lock-string-face) 16713 16722 (face font-lock-constant-face) 16722 16723 (face font-lock-string-face) 16723 16737 nil 16737 16738 (face font-lock-string-face) 16738 16760 (face font-lock-constant-face) 16760 16761 (face font-lock-string-face) 16761 16775 nil 16775 16776 (face font-lock-string-face) 16776 16797 (face font-lock-constant-face) 16797 16798 (face font-lock-string-face) 16798 16812 nil 16812 16813 (face font-lock-string-face) 16813 16830 (face font-lock-constant-face) 16830 16831 (face font-lock-string-face) 16831 16845 nil 16845 16846 (face font-lock-string-face) 16846 16862 (face font-lock-constant-face) 16862 16863 (face font-lock-string-face) 16863 16877 nil 16877 16878 (face font-lock-string-face) 16878 16889 (face font-lock-constant-face) 16889 16890 (face font-lock-string-face) 16890 16904 nil 16904 16905 (face font-lock-string-face) 16905 16915 (face font-lock-constant-face) 16915 16916 (face font-lock-string-face) 16916 16930 nil 16930 16931 (face font-lock-string-face) 16931 16955 (face font-lock-constant-face) 16955 16956 (face font-lock-string-face) 16956 16970 nil 16970 16971 (face font-lock-string-face) 16971 16994 (face font-lock-constant-face) 16994 16995 (face font-lock-string-face) 16995 17009 nil 17009 17010 (face font-lock-string-face) 17010 17034 (face font-lock-constant-face) 17034 17035 (face font-lock-string-face) 17035 17049 nil 17049 17050 (face font-lock-string-face) 17050 17073 (face font-lock-constant-face) 17073 17074 (face font-lock-string-face) 17074 17088 nil 17088 17089 (face font-lock-string-face) 17089 17114 (face font-lock-constant-face) 17114 17115 (face font-lock-string-face) 17115 17129 nil 17129 17130 (face font-lock-string-face) 17130 17154 (face font-lock-constant-face) 17154 17155 (face font-lock-string-face) 17155 17210 nil 17210 17211 (face font-lock-string-face) 17211 17222 (face font-lock-keyword-face) 17222 17223 (face font-lock-string-face) 17223 17225 nil 17225 17226 (face font-lock-string-face) 17226 17237 (face font-lock-function-name-face) 17237 17238 (face font-lock-string-face) 17238 17246 nil 17246 17247 (face font-lock-string-face) 17247 17251 (face font-lock-keyword-face) 17251 17252 (face font-lock-string-face) 17252 17254 nil 17254 17255 (face font-lock-string-face) 17255 17269 (face font-lock-type-face) 17269 17270 (face font-lock-string-face) 17270 17278 nil 17278 17279 (face font-lock-string-face) 17279 17291 (face font-lock-keyword-face) 17291 17292 (face font-lock-string-face) 17292 17304 nil 17304 17305 (face font-lock-string-face) 17305 17307 (face font-lock-constant-face) 17307 17308 (face font-lock-string-face) 17308 17325 nil 17325 17326 (face font-lock-string-face) 17326 17336 (face font-lock-keyword-face) 17336 17337 (face font-lock-string-face) 17337 17350 nil 17350 17351 (face font-lock-string-face) 17351 17371 (face font-lock-variable-name-face) 17371 17372 (face font-lock-string-face) 17372 17386 nil 17386 17387 (face font-lock-string-face) 17387 17404 (face font-lock-keyword-face) 17404 17405 (face font-lock-string-face) 17405 17423 nil 17423 17424 (face font-lock-string-face) 17424 17442 (face font-lock-variable-name-face) 17442 17443 (face font-lock-string-face) 17443 17461 nil 17461 17462 (face font-lock-string-face) 17462 17469 (face font-lock-keyword-face) 17469 17470 (face font-lock-string-face) 17470 17474 nil 17474 17498 (face font-lock-string-face) 17498 17553 nil 17553 17554 (face font-lock-string-face) 17554 17599 (face font-lock-variable-name-face) 17599 17600 (face font-lock-string-face) 17600 17614 nil 17614 17615 (face font-lock-string-face) 17615 17627 (face font-lock-keyword-face) 17627 17628 (face font-lock-string-face) 17628 17644 nil 17644 17645 (face font-lock-string-face) 17645 17665 (face font-lock-function-name-face) 17665 17666 (face font-lock-string-face) 17666 17703 nil 17703 17704 (face font-lock-string-face) 17704 17724 (face font-lock-variable-name-face) 17724 17725 (face font-lock-string-face) 17725 17739 nil 17739 17740 (face font-lock-string-face) 17740 17752 (face font-lock-keyword-face) 17752 17753 (face font-lock-string-face) 17753 17769 nil 17769 17770 (face font-lock-string-face) 17770 17790 (face font-lock-function-name-face) 17790 17791 (face font-lock-string-face) 17791 17833 nil 17833 17834 (face font-lock-string-face) 17834 17841 (face font-lock-keyword-face) 17841 17842 (face font-lock-string-face) 17842 17854 nil 17854 17855 (face font-lock-string-face) 17855 17874 (face font-lock-constant-face) 17874 17875 (face font-lock-string-face) 17875 17885 nil 17885 17886 (face font-lock-string-face) 17886 17904 (face font-lock-constant-face) 17904 17905 (face font-lock-string-face) 17905 17935 nil 17935 17936 (face font-lock-string-face) 17936 17947 (face font-lock-keyword-face) 17947 17948 (face font-lock-string-face) 17948 17950 nil 17950 17951 (face font-lock-string-face) 17951 17971 (face font-lock-function-name-face) 17971 17972 (face font-lock-string-face) 17972 17980 nil 17980 17981 (face font-lock-string-face) 17981 17985 (face font-lock-keyword-face) 17985 17986 (face font-lock-string-face) 17986 17988 nil 17988 17989 (face font-lock-string-face) 17989 18003 (face font-lock-type-face) 18003 18004 (face font-lock-string-face) 18004 18012 nil 18012 18013 (face font-lock-string-face) 18013 18025 (face font-lock-keyword-face) 18025 18026 (face font-lock-string-face) 18026 18038 nil 18038 18039 (face font-lock-string-face) 18039 18041 (face font-lock-constant-face) 18041 18042 (face font-lock-string-face) 18042 18059 nil 18059 18060 (face font-lock-string-face) 18060 18067 (face font-lock-keyword-face) 18067 18068 (face font-lock-string-face) 18068 18080 nil 18080 18081 (face font-lock-string-face) 18081 18114 (face font-lock-constant-face) 18114 18115 (face font-lock-string-face) 18115 18125 nil 18125 18126 (face font-lock-string-face) 18126 18162 (face font-lock-constant-face) 18162 18163 (face font-lock-string-face) 18163 18173 nil 18173 18174 (face font-lock-string-face) 18174 18212 (face font-lock-constant-face) 18212 18213 (face font-lock-string-face) 18213 18223 nil 18223 18224 (face font-lock-string-face) 18224 18261 (face font-lock-constant-face) 18261 18262 (face font-lock-string-face) 18262 18272 nil 18272 18273 (face font-lock-string-face) 18273 18311 (face font-lock-constant-face) 18311 18312 (face font-lock-string-face) 18312 18322 nil 18322 18323 (face font-lock-string-face) 18323 18356 (face font-lock-constant-face) 18356 18357 (face font-lock-string-face) 18357 18367 nil 18367 18368 (face font-lock-string-face) 18368 18403 (face font-lock-constant-face) 18403 18404 (face font-lock-string-face) 18404 18414 nil 18414 18415 (face font-lock-string-face) 18415 18451 (face font-lock-constant-face) 18451 18452 (face font-lock-string-face) 18452 18462 nil 18462 18463 (face font-lock-string-face) 18463 18499 (face font-lock-constant-face) 18499 18500 (face font-lock-string-face) 18500 18510 nil 18510 18511 (face font-lock-string-face) 18511 18547 (face font-lock-constant-face) 18547 18548 (face font-lock-string-face) 18548 18558 nil 18558 18559 (face font-lock-string-face) 18559 18581 (face font-lock-constant-face) 18581 18582 (face font-lock-string-face) 18582 18592 nil 18592 18593 (face font-lock-string-face) 18593 18618 (face font-lock-constant-face) 18618 18619 (face font-lock-string-face) 18619 18629 nil 18629 18630 (face font-lock-string-face) 18630 18657 (face font-lock-constant-face) 18657 18658 (face font-lock-string-face) 18658 18668 nil 18668 18669 (face font-lock-string-face) 18669 18697 (face font-lock-constant-face) 18697 18698 (face font-lock-string-face) 18698 18708 nil 18708 18709 (face font-lock-string-face) 18709 18750 (face font-lock-constant-face) 18750 18751 (face font-lock-string-face) 18751 18761 nil 18761 18762 (face font-lock-string-face) 18762 18803 (face font-lock-constant-face) 18803 18804 (face font-lock-string-face) 18804 18814 nil 18814 18815 (face font-lock-string-face) 18815 18856 (face font-lock-constant-face) 18856 18857 (face font-lock-string-face) 18857 18867 nil 18867 18868 (face font-lock-string-face) 18868 18902 (face font-lock-constant-face) 18902 18903 (face font-lock-string-face) 18903 18913 nil 18913 18914 (face font-lock-string-face) 18914 18948 (face font-lock-constant-face) 18948 18949 (face font-lock-string-face) 18949 18959 nil 18959 18960 (face font-lock-string-face) 18960 18994 (face font-lock-constant-face) 18994 18995 (face font-lock-string-face) 18995 19005 nil 19005 19006 (face font-lock-string-face) 19006 19035 (face font-lock-constant-face) 19035 19036 (face font-lock-string-face) 19036 19046 nil 19046 19047 (face font-lock-string-face) 19047 19075 (face font-lock-constant-face) 19075 19076 (face font-lock-string-face) 19076 19093 nil 19093 19094 (face font-lock-string-face) 19094 19104 (face font-lock-keyword-face) 19104 19105 (face font-lock-string-face) 19105 19118 nil 19118 19119 (face font-lock-string-face) 19119 19139 (face font-lock-variable-name-face) 19139 19140 (face font-lock-string-face) 19140 19154 nil 19154 19155 (face font-lock-string-face) 19155 19172 (face font-lock-keyword-face) 19172 19173 (face font-lock-string-face) 19173 19191 nil 19191 19192 (face font-lock-string-face) 19192 19210 (face font-lock-variable-name-face) 19210 19211 (face font-lock-string-face) 19211 19229 nil 19229 19230 (face font-lock-string-face) 19230 19237 (face font-lock-keyword-face) 19237 19238 (face font-lock-string-face) 19238 19242 nil 19242 19266 (face font-lock-string-face) 19266 19321 nil 19321 19322 (face font-lock-string-face) 19322 19342 (face font-lock-variable-name-face) 19342 19343 (face font-lock-string-face) 19343 19357 nil 19357 19399 (face font-lock-comment-face) 19399 19409 nil 19409 19410 (face font-lock-string-face) 19410 19417 (face font-lock-keyword-face) 19417 19418 (face font-lock-string-face) 19418 19434 nil 19434 19435 (face font-lock-string-face) 19435 19480 (face font-lock-constant-face) 19480 19481 (face font-lock-string-face) 19481 19495 nil 19495 19496 (face font-lock-string-face) 19496 19535 (face font-lock-constant-face) 19535 19536 (face font-lock-string-face) 19536 19573 nil 19573 19574 (face font-lock-string-face) 19574 19623 (face font-lock-variable-name-face) 19623 19624 (face font-lock-string-face) 19624 19638 nil 19638 19639 (face font-lock-string-face) 19639 19645 (face font-lock-keyword-face) 19645 19646 (face font-lock-string-face) 19646 19662 nil 19662 19670 (face font-lock-string-face) 19670 19707 nil 19707 19708 (face font-lock-string-face) 19708 19719 (face font-lock-variable-name-face) 19719 19720 (face font-lock-string-face) 19720 19734 nil 19734 19735 (face font-lock-string-face) 19735 19749 (face font-lock-keyword-face) 19749 19750 (face font-lock-string-face) 19750 19766 nil 19766 19773 (face font-lock-string-face) 19773 19791 nil 19791 19792 (face font-lock-string-face) 19792 19806 (face font-lock-keyword-face) 19806 19807 (face font-lock-string-face) 19807 19827 nil 19827 19890 (face font-lock-comment-face) 19890 19906 nil 19906 19971 (face font-lock-comment-face) 19971 19987 nil 19987 20032 (face font-lock-comment-face) 20032 20048 nil 20048 20072 (face font-lock-string-face) 20072 20074 nil 20074 20077 (face font-lock-string-face) 20077 20080 nil 20080 20086 (face font-lock-comment-face) 20086 20155 nil 20155 20156 (face font-lock-string-face) 20156 20165 (face font-lock-variable-name-face) 20165 20166 (face font-lock-string-face) 20166 20180 nil 20180 20181 (face font-lock-string-face) 20181 20190 (face font-lock-keyword-face) 20190 20191 (face font-lock-string-face) 20191 20207 nil 20207 20208 (face font-lock-string-face) 20208 20218 (face font-lock-variable-name-face) 20218 20219 (face font-lock-string-face) 20219 20237 nil 20237 20246 (face font-lock-string-face) 20246 20262 nil 20262 20270 (face font-lock-string-face) 20270 20286 nil 20286 20298 (face font-lock-string-face) 20298 20314 nil 20314 20322 (face font-lock-string-face) 20322 20374 nil 20374 20375 (face font-lock-string-face) 20375 20384 (face font-lock-variable-name-face) 20384 20385 (face font-lock-string-face) 20385 20399 nil 20399 20400 (face font-lock-string-face) 20400 20409 (face font-lock-keyword-face) 20409 20410 (face font-lock-string-face) 20410 20426 nil 20426 20427 (face font-lock-string-face) 20427 20437 (face font-lock-variable-name-face) 20437 20438 (face font-lock-string-face) 20438 20456 nil 20456 20466 (face font-lock-string-face) 20466 20482 nil 20482 20491 (face font-lock-string-face) 20491 20507 nil 20507 20519 (face font-lock-string-face) 20519 20535 nil 20535 20543 (face font-lock-string-face) 20543 20595 nil 20595 20596 (face font-lock-string-face) 20596 20621 (face font-lock-variable-name-face) 20621 20622 (face font-lock-string-face) 20622 20636 nil 20636 20637 (face font-lock-string-face) 20637 20646 (face font-lock-keyword-face) 20646 20647 (face font-lock-string-face) 20647 20663 nil 20663 20664 (face font-lock-string-face) 20664 20674 (face font-lock-keyword-face) 20674 20675 (face font-lock-string-face) 20675 20695 nil 20695 20696 (face font-lock-string-face) 20696 20715 (face font-lock-variable-name-face) 20715 20716 (face font-lock-string-face) 20716 20736 nil 20736 20748 (face font-lock-string-face) 20748 20770 nil 20770 20780 (face font-lock-string-face) 20780 20800 nil 20800 20807 (face font-lock-string-face) 20807 20827 nil 20827 20839 (face font-lock-string-face) 20839 20859 nil 20859 20867 (face font-lock-string-face) 20867 20923 nil 20923 20935 (face font-lock-string-face) 20935 20957 nil 20957 20972 (face font-lock-string-face) 20972 20992 nil 20992 20999 (face font-lock-string-face) 20999 21019 nil 21019 21026 (face font-lock-string-face) 21026 21046 nil 21046 21058 (face font-lock-string-face) 21058 21078 nil 21078 21086 (face font-lock-string-face) 21086 21180 nil 21180 21181 (face font-lock-string-face) 21181 21190 (face font-lock-keyword-face) 21190 21191 (face font-lock-string-face) 21191 21203 nil 21203 21204 (face font-lock-string-face) 21204 21220 (face font-lock-variable-name-face) 21220 21221 (face font-lock-string-face) 21221 21223 nil 21223 21224 (face font-lock-string-face) 21224 21256 (face font-lock-variable-name-face) 21256 21257 (face font-lock-string-face) 21257 21274 nil 21274 21314 (face font-lock-string-face) 21314 21325 nil 21325 21326 (face font-lock-string-face) 21326 21334 (face font-lock-keyword-face) 21334 21335 (face font-lock-string-face) 21335 21347 nil 21347 21348 (face font-lock-string-face) 21348 21385 (face font-lock-constant-face) 21385 21386 (face font-lock-string-face) 21386 21416 nil 21416 21417 (face font-lock-string-face) 21417 21428 (face font-lock-keyword-face) 21428 21429 (face font-lock-string-face) 21429 21431 nil 21431 21432 (face font-lock-string-face) 21432 21452 (face font-lock-function-name-face) 21452 21453 (face font-lock-string-face) 21453 21461 nil 21461 21462 (face font-lock-string-face) 21462 21466 (face font-lock-keyword-face) 21466 21467 (face font-lock-string-face) 21467 21469 nil 21469 21470 (face font-lock-string-face) 21470 21484 (face font-lock-type-face) 21484 21485 (face font-lock-string-face) 21485 21493 nil 21493 21494 (face font-lock-string-face) 21494 21506 (face font-lock-keyword-face) 21506 21507 (face font-lock-string-face) 21507 21519 nil 21519 21520 (face font-lock-string-face) 21520 21522 (face font-lock-constant-face) 21522 21523 (face font-lock-string-face) 21523 21540 nil 21540 21541 (face font-lock-string-face) 21541 21548 (face font-lock-keyword-face) 21548 21549 (face font-lock-string-face) 21549 21561 nil 21561 21562 (face font-lock-string-face) 21562 21595 (face font-lock-constant-face) 21595 21596 (face font-lock-string-face) 21596 21606 nil 21606 21607 (face font-lock-string-face) 21607 21637 (face font-lock-constant-face) 21637 21638 (face font-lock-string-face) 21638 21648 nil 21648 21649 (face font-lock-string-face) 21649 21682 (face font-lock-constant-face) 21682 21683 (face font-lock-string-face) 21683 21693 nil 21693 21694 (face font-lock-string-face) 21694 21724 (face font-lock-constant-face) 21724 21725 (face font-lock-string-face) 21725 21735 nil 21735 21736 (face font-lock-string-face) 21736 21758 (face font-lock-constant-face) 21758 21759 (face font-lock-string-face) 21759 21769 nil 21769 21770 (face font-lock-string-face) 21770 21795 (face font-lock-constant-face) 21795 21796 (face font-lock-string-face) 21796 21806 nil 21806 21807 (face font-lock-string-face) 21807 21836 (face font-lock-constant-face) 21836 21837 (face font-lock-string-face) 21837 21847 nil 21847 21848 (face font-lock-string-face) 21848 21876 (face font-lock-constant-face) 21876 21877 (face font-lock-string-face) 21877 21907 nil 21907 21908 (face font-lock-string-face) 21908 21919 (face font-lock-keyword-face) 21919 21920 (face font-lock-string-face) 21920 21922 nil 21922 21923 (face font-lock-string-face) 21923 21938 (face font-lock-function-name-face) 21938 21939 (face font-lock-string-face) 21939 21947 nil 21947 21948 (face font-lock-string-face) 21948 21952 (face font-lock-keyword-face) 21952 21953 (face font-lock-string-face) 21953 21955 nil 21955 21956 (face font-lock-string-face) 21956 21966 (face font-lock-type-face) 21966 21967 (face font-lock-string-face) 21967 21975 nil 21975 21976 (face font-lock-string-face) 21976 21988 (face font-lock-keyword-face) 21988 21989 (face font-lock-string-face) 21989 22001 nil 22001 22002 (face font-lock-string-face) 22002 22007 (face font-lock-function-name-face) 22007 22008 (face font-lock-string-face) 22008 22018 nil 22018 22019 (face font-lock-string-face) 22019 22037 (face font-lock-function-name-face) 22037 22038 (face font-lock-string-face) 22038 22048 nil 22048 22049 (face font-lock-string-face) 22049 22060 (face font-lock-function-name-face) 22060 22061 (face font-lock-string-face) 22061 22071 nil 22071 22072 (face font-lock-string-face) 22072 22093 (face font-lock-function-name-face) 22093 22094 (face font-lock-string-face) 22094 22104 nil 22104 22105 (face font-lock-string-face) 22105 22131 (face font-lock-function-name-face) 22131 22132 (face font-lock-string-face) 22132 22142 nil 22142 22143 (face font-lock-string-face) 22143 22177 (face font-lock-function-name-face) 22177 22178 (face font-lock-string-face) 22178 22188 nil 22188 22189 (face font-lock-string-face) 22189 22215 (face font-lock-function-name-face) 22215 22216 (face font-lock-string-face) 22216 22226 nil 22226 22227 (face font-lock-string-face) 22227 22253 (face font-lock-function-name-face) 22253 22254 (face font-lock-string-face) 22254 22264 nil 22264 22265 (face font-lock-string-face) 22265 22280 (face font-lock-function-name-face) 22280 22281 (face font-lock-string-face) 22281 22298 nil 22298 22299 (face font-lock-string-face) 22299 22306 (face font-lock-keyword-face) 22306 22307 (face font-lock-string-face) 22307 22319 nil 22319 22320 (face font-lock-string-face) 22320 22361 (face font-lock-constant-face) 22361 22362 (face font-lock-string-face) 22362 22372 nil 22372 22373 (face font-lock-string-face) 22373 22413 (face font-lock-constant-face) 22413 22414 (face font-lock-string-face) 22414 22424 nil 22424 22425 (face font-lock-string-face) 22425 22461 (face font-lock-constant-face) 22461 22462 (face font-lock-string-face) 22462 22472 nil 22472 22473 (face font-lock-string-face) 22473 22502 (face font-lock-constant-face) 22502 22503 (face font-lock-string-face) 22503 22513 nil 22513 22514 (face font-lock-string-face) 22514 22550 (face font-lock-constant-face) 22550 22551 (face font-lock-string-face) 22551 22561 nil 22561 22562 (face font-lock-string-face) 22562 22610 (face font-lock-constant-face) 22610 22611 (face font-lock-string-face) 22611 22621 nil 22621 22622 (face font-lock-string-face) 22622 22663 (face font-lock-constant-face) 22663 22664 (face font-lock-string-face) 22664 22674 nil 22674 22675 (face font-lock-string-face) 22675 22711 (face font-lock-constant-face) 22711 22712 (face font-lock-string-face) 22712 22722 nil 22722 22723 (face font-lock-string-face) 22723 22757 (face font-lock-constant-face) 22757 22758 (face font-lock-string-face) 22758 22768 nil 22768 22769 (face font-lock-string-face) 22769 22797 (face font-lock-constant-face) 22797 22798 (face font-lock-string-face) 22798 22808 nil 22808 22809 (face font-lock-string-face) 22809 22853 (face font-lock-constant-face) 22853 22854 (face font-lock-string-face) 22854 22864 nil 22864 22865 (face font-lock-string-face) 22865 22900 (face font-lock-constant-face) 22900 22901 (face font-lock-string-face) 22901 22911 nil 22911 22912 (face font-lock-string-face) 22912 22961 (face font-lock-constant-face) 22961 22962 (face font-lock-string-face) 22962 22972 nil 22972 22973 (face font-lock-string-face) 22973 23011 (face font-lock-constant-face) 23011 23012 (face font-lock-string-face) 23012 23022 nil 23022 23023 (face font-lock-string-face) 23023 23055 (face font-lock-constant-face) 23055 23056 (face font-lock-string-face) 23056 23066 nil 23066 23067 (face font-lock-string-face) 23067 23116 (face font-lock-constant-face) 23116 23117 (face font-lock-string-face) 23117 23127 nil 23127 23128 (face font-lock-string-face) 23128 23178 (face font-lock-constant-face) 23178 23179 (face font-lock-string-face) 23179 23189 nil 23189 23190 (face font-lock-string-face) 23190 23228 (face font-lock-constant-face) 23228 23229 (face font-lock-string-face) 23229 23239 nil 23239 23240 (face font-lock-string-face) 23240 23277 (face font-lock-constant-face) 23277 23278 (face font-lock-string-face) 23278 23288 nil 23288 23289 (face font-lock-string-face) 23289 23332 (face font-lock-constant-face) 23332 23333 (face font-lock-string-face) 23333 23343 nil 23343 23344 (face font-lock-string-face) 23344 23368 (face font-lock-constant-face) 23368 23369 (face font-lock-string-face) 23369 23379 nil 23379 23380 (face font-lock-string-face) 23380 23402 (face font-lock-constant-face) 23402 23403 (face font-lock-string-face) 23403 23413 nil 23413 23414 (face font-lock-string-face) 23414 23447 (face font-lock-constant-face) 23447 23448 (face font-lock-string-face) 23448 23458 nil 23458 23459 (face font-lock-string-face) 23459 23487 (face font-lock-constant-face) 23487 23488 (face font-lock-string-face) 23488 23498 nil 23498 23499 (face font-lock-string-face) 23499 23530 (face font-lock-constant-face) 23530 23531 (face font-lock-string-face) 23531 23541 nil 23541 23542 (face font-lock-string-face) 23542 23563 (face font-lock-constant-face) 23563 23564 (face font-lock-string-face) 23564 23574 nil 23574 23575 (face font-lock-string-face) 23575 23609 (face font-lock-constant-face) 23609 23610 (face font-lock-string-face) 23610 23620 nil 23620 23621 (face font-lock-string-face) 23621 23654 (face font-lock-constant-face) 23654 23655 (face font-lock-string-face) 23655 23665 nil 23665 23666 (face font-lock-string-face) 23666 23700 (face font-lock-constant-face) 23700 23701 (face font-lock-string-face) 23701 23711 nil 23711 23712 (face font-lock-string-face) 23712 23753 (face font-lock-constant-face) 23753 23754 (face font-lock-string-face) 23754 23764 nil 23764 23765 (face font-lock-string-face) 23765 23790 (face font-lock-constant-face) 23790 23791 (face font-lock-string-face) 23791 23801 nil 23801 23802 (face font-lock-string-face) 23802 23825 (face font-lock-constant-face) 23825 23826 (face font-lock-string-face) 23826 23836 nil 23836 23837 (face font-lock-string-face) 23837 23862 (face font-lock-constant-face) 23862 23863 (face font-lock-string-face) 23863 23873 nil 23873 23874 (face font-lock-string-face) 23874 23906 (face font-lock-constant-face) 23906 23907 (face font-lock-string-face) 23907 23917 nil 23917 23918 (face font-lock-string-face) 23918 23947 (face font-lock-constant-face) 23947 23948 (face font-lock-string-face) 23948 23958 nil 23958 23959 (face font-lock-string-face) 23959 23981 (face font-lock-constant-face) 23981 23982 (face font-lock-string-face) 23982 23992 nil 23992 23993 (face font-lock-string-face) 23993 24014 (face font-lock-constant-face) 24014 24015 (face font-lock-string-face) 24015 24025 nil 24025 24026 (face font-lock-string-face) 24026 24054 (face font-lock-constant-face) 24054 24055 (face font-lock-string-face) 24055 24065 nil 24065 24066 (face font-lock-string-face) 24066 24093 (face font-lock-constant-face) 24093 24094 (face font-lock-string-face) 24094 24104 nil 24104 24105 (face font-lock-string-face) 24105 24133 (face font-lock-constant-face) 24133 24134 (face font-lock-string-face) 24134 24144 nil 24144 24145 (face font-lock-string-face) 24145 24177 (face font-lock-constant-face) 24177 24178 (face font-lock-string-face) 24178 24188 nil 24188 24189 (face font-lock-string-face) 24189 24221 (face font-lock-constant-face) 24221 24222 (face font-lock-string-face) 24222 24232 nil 24232 24233 (face font-lock-string-face) 24233 24277 (face font-lock-constant-face) 24277 24278 (face font-lock-string-face) 24278 24288 nil 24288 24289 (face font-lock-string-face) 24289 24328 (face font-lock-constant-face) 24328 24329 (face font-lock-string-face) 24329 24339 nil 24339 24340 (face font-lock-string-face) 24340 24379 (face font-lock-constant-face) 24379 24380 (face font-lock-string-face) 24380 24390 nil 24390 24391 (face font-lock-string-face) 24391 24424 (face font-lock-constant-face) 24424 24425 (face font-lock-string-face) 24425 24435 nil 24435 24436 (face font-lock-string-face) 24436 24476 (face font-lock-constant-face) 24476 24477 (face font-lock-string-face) 24477 24487 nil 24487 24488 (face font-lock-string-face) 24488 24521 (face font-lock-constant-face) 24521 24522 (face font-lock-string-face) 24522 24532 nil 24532 24533 (face font-lock-string-face) 24533 24567 (face font-lock-constant-face) 24567 24568 (face font-lock-string-face) 24568 24578 nil 24578 24579 (face font-lock-string-face) 24579 24610 (face font-lock-constant-face) 24610 24611 (face font-lock-string-face) 24611 24621 nil 24621 24622 (face font-lock-string-face) 24622 24673 (face font-lock-constant-face) 24673 24674 (face font-lock-string-face) 24674 24684 nil 24684 24685 (face font-lock-string-face) 24685 24725 (face font-lock-constant-face) 24725 24726 (face font-lock-string-face) 24726 24736 nil 24736 24737 (face font-lock-string-face) 24737 24773 (face font-lock-constant-face) 24773 24774 (face font-lock-string-face) 24774 24784 nil 24784 24785 (face font-lock-string-face) 24785 24821 (face font-lock-constant-face) 24821 24822 (face font-lock-string-face) 24822 24832 nil 24832 24833 (face font-lock-string-face) 24833 24874 (face font-lock-constant-face) 24874 24875 (face font-lock-string-face) 24875 24885 nil 24885 24886 (face font-lock-string-face) 24886 24926 (face font-lock-constant-face) 24926 24927 (face font-lock-string-face) 24927 24937 nil 24937 24938 (face font-lock-string-face) 24938 24977 (face font-lock-constant-face) 24977 24978 (face font-lock-string-face) 24978 24988 nil 24988 24989 (face font-lock-string-face) 24989 25035 (face font-lock-constant-face) 25035 25036 (face font-lock-string-face) 25036 25046 nil 25046 25047 (face font-lock-string-face) 25047 25070 (face font-lock-constant-face) 25070 25071 (face font-lock-string-face) 25071 25081 nil 25081 25082 (face font-lock-string-face) 25082 25104 (face font-lock-constant-face) 25104 25105 (face font-lock-string-face) 25105 25115 nil 25115 25116 (face font-lock-string-face) 25116 25152 (face font-lock-constant-face) 25152 25153 (face font-lock-string-face) 25153 25163 nil 25163 25164 (face font-lock-string-face) 25164 25210 (face font-lock-constant-face) 25210 25211 (face font-lock-string-face) 25211 25221 nil 25221 25222 (face font-lock-string-face) 25222 25250 (face font-lock-constant-face) 25250 25251 (face font-lock-string-face) 25251 25268 nil 25268 25269 (face font-lock-string-face) 25269 25279 (face font-lock-keyword-face) 25279 25280 (face font-lock-string-face) 25280 25293 nil 25293 25294 (face font-lock-string-face) 25294 25319 (face font-lock-variable-name-face) 25319 25320 (face font-lock-string-face) 25320 25334 nil 25334 25335 (face font-lock-string-face) 25335 25345 (face font-lock-keyword-face) 25345 25346 (face font-lock-string-face) 25346 25363 nil 25363 25364 (face font-lock-string-face) 25364 25385 (face font-lock-variable-name-face) 25385 25386 (face font-lock-string-face) 25386 25404 nil 25404 25405 (face font-lock-string-face) 25405 25417 (face font-lock-keyword-face) 25417 25418 (face font-lock-string-face) 25418 25438 nil 25438 25439 (face font-lock-string-face) 25439 25480 (face font-lock-function-name-face) 25480 25481 (face font-lock-string-face) 25481 25550 nil 25550 25551 (face font-lock-string-face) 25551 25566 (face font-lock-variable-name-face) 25566 25567 (face font-lock-string-face) 25567 25581 nil 25581 25582 (face font-lock-string-face) 25582 25594 (face font-lock-keyword-face) 25594 25595 (face font-lock-string-face) 25595 25611 nil 25611 25612 (face font-lock-string-face) 25612 25651 (face font-lock-function-name-face) 25651 25652 (face font-lock-string-face) 25652 25688 nil 25688 25689 (face font-lock-string-face) 25689 25704 (face font-lock-variable-name-face) 25704 25705 (face font-lock-string-face) 25705 25719 nil 25719 25720 (face font-lock-string-face) 25720 25728 (face font-lock-keyword-face) 25728 25729 (face font-lock-string-face) 25729 25745 nil 25745 25746 (face font-lock-string-face) 25746 25782 (face font-lock-constant-face) 25782 25783 (face font-lock-string-face) 25783 25797 nil 25797 25798 (face font-lock-string-face) 25798 25820 (face font-lock-constant-face) 25820 25821 (face font-lock-string-face) 25821 25835 nil 25835 25836 (face font-lock-string-face) 25836 25857 (face font-lock-constant-face) 25857 25858 (face font-lock-string-face) 25858 25872 nil 25872 25873 (face font-lock-string-face) 25873 25905 (face font-lock-constant-face) 25905 25906 (face font-lock-string-face) 25906 25920 nil 25920 25921 (face font-lock-string-face) 25921 25961 (face font-lock-constant-face) 25961 25962 (face font-lock-string-face) 25962 25976 nil 25976 25977 (face font-lock-string-face) 25977 26016 (face font-lock-constant-face) 26016 26017 (face font-lock-string-face) 26017 26031 nil 26031 26032 (face font-lock-string-face) 26032 26065 (face font-lock-constant-face) 26065 26066 (face font-lock-string-face) 26066 26080 nil 26080 26081 (face font-lock-string-face) 26081 26115 (face font-lock-constant-face) 26115 26116 (face font-lock-string-face) 26116 26130 nil 26130 26131 (face font-lock-string-face) 26131 26162 (face font-lock-constant-face) 26162 26163 (face font-lock-string-face) 26163 26177 nil 26177 26178 (face font-lock-string-face) 26178 26229 (face font-lock-constant-face) 26229 26230 (face font-lock-string-face) 26230 26244 nil 26244 26245 (face font-lock-string-face) 26245 26285 (face font-lock-constant-face) 26285 26286 (face font-lock-string-face) 26286 26300 nil 26300 26301 (face font-lock-string-face) 26301 26337 (face font-lock-constant-face) 26337 26338 (face font-lock-string-face) 26338 26352 nil 26352 26353 (face font-lock-string-face) 26353 26394 (face font-lock-constant-face) 26394 26395 (face font-lock-string-face) 26395 26409 nil 26409 26410 (face font-lock-string-face) 26410 26443 (face font-lock-constant-face) 26443 26444 (face font-lock-string-face) 26444 26458 nil 26458 26459 (face font-lock-string-face) 26459 26495 (face font-lock-constant-face) 26495 26496 (face font-lock-string-face) 26496 26532 nil 26532 26533 (face font-lock-string-face) 26533 26546 (face font-lock-variable-name-face) 26546 26547 (face font-lock-string-face) 26547 26561 nil 26561 26562 (face font-lock-string-face) 26562 26572 (face font-lock-keyword-face) 26572 26573 (face font-lock-string-face) 26573 26590 nil 26590 26591 (face font-lock-string-face) 26591 26604 (face font-lock-variable-name-face) 26604 26605 (face font-lock-string-face) 26605 26623 nil 26623 26624 (face font-lock-string-face) 26624 26631 (face font-lock-keyword-face) 26631 26632 (face font-lock-string-face) 26632 26652 nil 26652 26653 (face font-lock-string-face) 26653 26688 (face font-lock-constant-face) 26688 26689 (face font-lock-string-face) 26689 26722 nil 26722 26723 (face font-lock-string-face) 26723 26730 (face font-lock-keyword-face) 26730 26731 (face font-lock-string-face) 26731 26751 nil 26751 26752 (face font-lock-string-face) 26752 26760 (face font-lock-preprocessor-face) 26760 26761 (face font-lock-string-face) 26761 26831 nil 26831 26832 (face font-lock-string-face) 26832 26873 (face font-lock-variable-name-face) 26873 26874 (face font-lock-string-face) 26874 26888 nil 26888 26889 (face font-lock-string-face) 26889 26896 (face font-lock-keyword-face) 26896 26897 (face font-lock-string-face) 26897 26913 nil 26913 26914 (face font-lock-string-face) 26914 26954 (face font-lock-constant-face) 26954 26955 (face font-lock-string-face) 26955 26991 nil 26991 26992 (face font-lock-string-face) 26992 27035 (face font-lock-variable-name-face) 27035 27036 (face font-lock-string-face) 27036 27050 nil 27050 27051 (face font-lock-string-face) 27051 27058 (face font-lock-keyword-face) 27058 27059 (face font-lock-string-face) 27059 27075 nil 27075 27076 (face font-lock-string-face) 27076 27095 (face font-lock-constant-face) 27095 27096 (face font-lock-string-face) 27096 27110 nil 27110 27111 (face font-lock-string-face) 27111 27137 (face font-lock-constant-face) 27137 27138 (face font-lock-string-face) 27138 27152 nil 27152 27153 (face font-lock-string-face) 27153 27186 (face font-lock-constant-face) 27186 27187 (face font-lock-string-face) 27187 27201 nil 27201 27202 (face font-lock-string-face) 27202 27235 (face font-lock-constant-face) 27235 27236 (face font-lock-string-face) 27236 27291 nil 27291 27292 (face font-lock-string-face) 27292 27303 (face font-lock-keyword-face) 27303 27304 (face font-lock-string-face) 27304 27306 nil 27306 27307 (face font-lock-string-face) 27307 27325 (face font-lock-function-name-face) 27325 27326 (face font-lock-string-face) 27326 27334 nil 27334 27335 (face font-lock-string-face) 27335 27339 (face font-lock-keyword-face) 27339 27340 (face font-lock-string-face) 27340 27342 nil 27342 27343 (face font-lock-string-face) 27343 27357 (face font-lock-type-face) 27357 27358 (face font-lock-string-face) 27358 27366 nil 27366 27367 (face font-lock-string-face) 27367 27379 (face font-lock-keyword-face) 27379 27380 (face font-lock-string-face) 27380 27392 nil 27392 27393 (face font-lock-string-face) 27393 27398 (face font-lock-function-name-face) 27398 27399 (face font-lock-string-face) 27399 27409 nil 27409 27410 (face font-lock-string-face) 27410 27431 (face font-lock-function-name-face) 27431 27432 (face font-lock-string-face) 27432 27442 nil 27442 27443 (face font-lock-string-face) 27443 27469 (face font-lock-function-name-face) 27469 27470 (face font-lock-string-face) 27470 27480 nil 27480 27481 (face font-lock-string-face) 27481 27507 (face font-lock-function-name-face) 27507 27508 (face font-lock-string-face) 27508 27525 nil 27525 27526 (face font-lock-string-face) 27526 27533 (face font-lock-keyword-face) 27533 27534 (face font-lock-string-face) 27534 27546 nil 27546 27547 (face font-lock-string-face) 27547 27591 (face font-lock-constant-face) 27591 27592 (face font-lock-string-face) 27592 27602 nil 27602 27603 (face font-lock-string-face) 27603 27646 (face font-lock-constant-face) 27646 27647 (face font-lock-string-face) 27647 27657 nil 27657 27658 (face font-lock-string-face) 27658 27679 (face font-lock-constant-face) 27679 27680 (face font-lock-string-face) 27680 27690 nil 27690 27691 (face font-lock-string-face) 27691 27711 (face font-lock-constant-face) 27711 27712 (face font-lock-string-face) 27712 27722 nil 27722 27723 (face font-lock-string-face) 27723 27752 (face font-lock-constant-face) 27752 27753 (face font-lock-string-face) 27753 27763 nil 27763 27764 (face font-lock-string-face) 27764 27792 (face font-lock-constant-face) 27792 27793 (face font-lock-string-face) 27793 27803 nil 27803 27804 (face font-lock-string-face) 27804 27829 (face font-lock-constant-face) 27829 27830 (face font-lock-string-face) 27830 27840 nil 27840 27841 (face font-lock-string-face) 27841 27865 (face font-lock-constant-face) 27865 27866 (face font-lock-string-face) 27866 27876 nil 27876 27877 (face font-lock-string-face) 27877 27901 (face font-lock-constant-face) 27901 27902 (face font-lock-string-face) 27902 27912 nil 27912 27913 (face font-lock-string-face) 27913 27936 (face font-lock-constant-face) 27936 27937 (face font-lock-string-face) 27937 27947 nil 27947 27948 (face font-lock-string-face) 27948 27968 (face font-lock-constant-face) 27968 27969 (face font-lock-string-face) 27969 27979 nil 27979 27980 (face font-lock-string-face) 27980 27999 (face font-lock-constant-face) 27999 28000 (face font-lock-string-face) 28000 28030 nil 28030 28031 (face font-lock-string-face) 28031 28042 (face font-lock-keyword-face) 28042 28043 (face font-lock-string-face) 28043 28045 nil 28045 28046 (face font-lock-string-face) 28046 28058 (face font-lock-function-name-face) 28058 28059 (face font-lock-string-face) 28059 28067 nil 28067 28068 (face font-lock-string-face) 28068 28072 (face font-lock-keyword-face) 28072 28073 (face font-lock-string-face) 28073 28075 nil 28075 28076 (face font-lock-string-face) 28076 28086 (face font-lock-type-face) 28086 28087 (face font-lock-string-face) 28087 28095 nil 28095 28096 (face font-lock-string-face) 28096 28108 (face font-lock-keyword-face) 28108 28109 (face font-lock-string-face) 28109 28121 nil 28121 28122 (face font-lock-string-face) 28122 28127 (face font-lock-function-name-face) 28127 28128 (face font-lock-string-face) 28128 28138 nil 28138 28139 (face font-lock-string-face) 28139 28150 (face font-lock-function-name-face) 28150 28151 (face font-lock-string-face) 28151 28161 nil 28161 28162 (face font-lock-string-face) 28162 28183 (face font-lock-function-name-face) 28183 28184 (face font-lock-string-face) 28184 28194 nil 28194 28195 (face font-lock-string-face) 28195 28216 (face font-lock-function-name-face) 28216 28217 (face font-lock-string-face) 28217 28234 nil 28234 28235 (face font-lock-string-face) 28235 28242 (face font-lock-keyword-face) 28242 28243 (face font-lock-string-face) 28243 28255 nil 28255 28256 (face font-lock-string-face) 28256 28290 (face font-lock-constant-face) 28290 28291 (face font-lock-string-face) 28291 28321 nil 28321 28322 (face font-lock-string-face) 28322 28333 (face font-lock-keyword-face) 28333 28334 (face font-lock-string-face) 28334 28336 nil 28336 28337 (face font-lock-string-face) 28337 28349 (face font-lock-function-name-face) 28349 28350 (face font-lock-string-face) 28350 28358 nil 28358 28359 (face font-lock-string-face) 28359 28363 (face font-lock-keyword-face) 28363 28364 (face font-lock-string-face) 28364 28366 nil 28366 28367 (face font-lock-string-face) 28367 28377 (face font-lock-type-face) 28377 28378 (face font-lock-string-face) 28378 28386 nil 28386 28387 (face font-lock-string-face) 28387 28394 (face font-lock-keyword-face) 28394 28395 (face font-lock-string-face) 28395 28407 nil 28407 28408 (face font-lock-string-face) 28408 28441 (face font-lock-constant-face) 28441 28442 (face font-lock-string-face) 28442 28471 nil 28471 28472 (face font-lock-string-face) 28472 28483 (face font-lock-keyword-face) 28483 28484 (face font-lock-string-face) 28484 28486 nil 28486 28487 (face font-lock-string-face) 28487 28498 (face font-lock-function-name-face) 28498 28499 (face font-lock-string-face) 28499 28507 nil 28507 28508 (face font-lock-string-face) 28508 28512 (face font-lock-keyword-face) 28512 28513 (face font-lock-string-face) 28513 28515 nil 28515 28516 (face font-lock-string-face) 28516 28526 (face font-lock-type-face) 28526 28527 (face font-lock-string-face) 28527 28535 nil 28535 28536 (face font-lock-string-face) 28536 28548 (face font-lock-keyword-face) 28548 28549 (face font-lock-string-face) 28549 28561 nil 28561 28562 (face font-lock-string-face) 28562 28567 (face font-lock-function-name-face) 28567 28568 (face font-lock-string-face) 28568 28578 nil 28578 28579 (face font-lock-string-face) 28579 28600 (face font-lock-function-name-face) 28600 28601 (face font-lock-string-face) 28601 28618 nil 28618 28619 (face font-lock-string-face) 28619 28626 (face font-lock-keyword-face) 28626 28627 (face font-lock-string-face) 28627 28639 nil 28639 28640 (face font-lock-string-face) 28640 28672 (face font-lock-constant-face) 28672 28673 (face font-lock-string-face) 28673 28698 nil 28698 28699 (face font-lock-string-face) 28699 28709 (face font-lock-keyword-face) 28709 28710 (face font-lock-string-face) 28710 28719 nil 28719 28720 (face font-lock-string-face) 28720 28729 (face font-lock-variable-name-face) 28729 28730 (face font-lock-string-face) 28730 28740 nil 28740 28741 (face font-lock-string-face) 28741 28748 (face font-lock-keyword-face) 28748 28749 (face font-lock-string-face) 28749 28773 nil 28773 28774 (face font-lock-string-face) 28774 28785 (face font-lock-keyword-face) 28785 28786 (face font-lock-string-face) 28786 28788 nil 28788 28789 (face font-lock-string-face) 28789 28799 (face font-lock-function-name-face) 28799 28800 (face font-lock-string-face) 28800 28812 nil 28812 28813 (face font-lock-string-face) 28813 28817 (face font-lock-keyword-face) 28817 28818 (face font-lock-string-face) 28818 28820 nil 28820 28821 (face font-lock-string-face) 28821 28831 (face font-lock-type-face) 28831 28832 (face font-lock-string-face) 28832 28844 nil 28844 28845 (face font-lock-string-face) 28845 28857 (face font-lock-keyword-face) 28857 28858 (face font-lock-string-face) 28858 28874 nil 28874 28875 (face font-lock-string-face) 28875 28880 (face font-lock-function-name-face) 28880 28881 (face font-lock-string-face) 28881 28895 nil 28895 28896 (face font-lock-string-face) 28896 28907 (face font-lock-function-name-face) 28907 28908 (face font-lock-string-face) 28908 28922 nil 28922 28923 (face font-lock-string-face) 28923 28944 (face font-lock-function-name-face) 28944 28945 (face font-lock-string-face) 28945 28959 nil 28959 28960 (face font-lock-string-face) 28960 29043 (face font-lock-function-name-face) 29043 29044 (face font-lock-string-face) 29044 29058 nil 29058 29059 (face font-lock-string-face) 29059 29074 (face font-lock-function-name-face) 29074 29075 (face font-lock-string-face) 29075 29100 nil 29100 29101 (face font-lock-string-face) 29101 29113 (face font-lock-keyword-face) 29113 29114 (face font-lock-string-face) 29114 29130 nil 29130 29131 (face font-lock-string-face) 29131 29133 (face font-lock-constant-face) 29133 29138 (face font-lock-variable-name-face) 29138 29163 (face font-lock-constant-face) 29163 29164 (face font-lock-string-face) 29164 29189 nil 29189 29190 (face font-lock-string-face) 29190 29197 (face font-lock-keyword-face) 29197 29198 (face font-lock-string-face) 29198 29214 nil 29214 29215 (face font-lock-string-face) 29215 29238 (face font-lock-constant-face) 29238 29239 (face font-lock-string-face) 29239 29253 nil 29253 29254 (face font-lock-string-face) 29254 29280 (face font-lock-constant-face) 29280 29281 (face font-lock-string-face) 29281 29295 nil 29295 29296 (face font-lock-string-face) 29296 29321 (face font-lock-constant-face) 29321 29322 (face font-lock-string-face) 29322 29336 nil 29336 29337 (face font-lock-string-face) 29337 29361 (face font-lock-constant-face) 29361 29362 (face font-lock-string-face) 29362 29376 nil 29376 29377 (face font-lock-string-face) 29377 29407 (face font-lock-constant-face) 29407 29408 (face font-lock-string-face) 29408 29422 nil 29422 29423 (face font-lock-string-face) 29423 29453 (face font-lock-constant-face) 29453 29454 (face font-lock-string-face) 29454 29468 nil 29468 29469 (face font-lock-string-face) 29469 29493 (face font-lock-constant-face) 29493 29494 (face font-lock-string-face) 29494 29508 nil 29508 29509 (face font-lock-string-face) 29509 29532 (face font-lock-constant-face) 29532 29533 (face font-lock-string-face) 29533 29547 nil 29547 29548 (face font-lock-string-face) 29548 29575 (face font-lock-constant-face) 29575 29576 (face font-lock-string-face) 29576 29590 nil 29590 29591 (face font-lock-string-face) 29591 29614 (face font-lock-constant-face) 29614 29615 (face font-lock-string-face) 29615 29640 nil 29640 29655 (face font-lock-string-face) 29655 29671 nil 29671 29685 (face font-lock-string-face) 29685 29703 nil 29703 29714 (face font-lock-string-face) 29714 29716 nil 29716 29719 (face font-lock-string-face) 29719 29729 nil 29729 29754 (face font-lock-comment-face) 29754 29792 nil 29792 29793 (face font-lock-string-face) 29793 29800 (face font-lock-keyword-face) 29800 29801 (face font-lock-string-face) 29801 29817 nil 29817 29818 (face font-lock-string-face) 29818 29843 (face font-lock-preprocessor-face) 29843 29844 (face font-lock-string-face) 29844 29892 nil 29892 29893 (face font-lock-string-face) 29893 29929 (face font-lock-variable-name-face) 29929 29930 (face font-lock-string-face) 29930 29940 nil 29940 29941 (face font-lock-string-face) 29941 29948 (face font-lock-keyword-face) 29948 29949 (face font-lock-string-face) 29949 29973 nil 29973 29974 (face font-lock-string-face) 29974 29985 (face font-lock-keyword-face) 29985 29986 (face font-lock-string-face) 29986 29988 nil 29988 29989 (face font-lock-string-face) 29989 30001 (face font-lock-function-name-face) 30001 30002 (face font-lock-string-face) 30002 30014 nil 30014 30015 (face font-lock-string-face) 30015 30019 (face font-lock-keyword-face) 30019 30020 (face font-lock-string-face) 30020 30022 nil 30022 30023 (face font-lock-string-face) 30023 30033 (face font-lock-type-face) 30033 30034 (face font-lock-string-face) 30034 30046 nil 30046 30047 (face font-lock-string-face) 30047 30059 (face font-lock-keyword-face) 30059 30060 (face font-lock-string-face) 30060 30076 nil 30076 30077 (face font-lock-string-face) 30077 30082 (face font-lock-function-name-face) 30082 30083 (face font-lock-string-face) 30083 30097 nil 30097 30098 (face font-lock-string-face) 30098 30109 (face font-lock-function-name-face) 30109 30110 (face font-lock-string-face) 30110 30124 nil 30124 30125 (face font-lock-string-face) 30125 30146 (face font-lock-function-name-face) 30146 30147 (face font-lock-string-face) 30147 30161 nil 30161 30162 (face font-lock-string-face) 30162 30180 (face font-lock-function-name-face) 30180 30181 (face font-lock-string-face) 30181 30206 nil 30206 30207 (face font-lock-string-face) 30207 30214 (face font-lock-keyword-face) 30214 30215 (face font-lock-string-face) 30215 30231 nil 30231 30232 (face font-lock-string-face) 30232 30266 (face font-lock-constant-face) 30266 30267 (face font-lock-string-face) 30267 30281 nil 30281 30282 (face font-lock-string-face) 30282 30321 (face font-lock-constant-face) 30321 30322 (face font-lock-string-face) 30322 30336 nil 30336 30337 (face font-lock-string-face) 30337 30375 (face font-lock-constant-face) 30375 30376 (face font-lock-string-face) 30376 30390 nil 30390 30391 (face font-lock-string-face) 30391 30430 (face font-lock-constant-face) 30430 30431 (face font-lock-string-face) 30431 30445 nil 30445 30446 (face font-lock-string-face) 30446 30484 (face font-lock-constant-face) 30484 30485 (face font-lock-string-face) 30485 30499 nil 30499 30500 (face font-lock-string-face) 30500 30533 (face font-lock-constant-face) 30533 30534 (face font-lock-string-face) 30534 30548 nil 30548 30549 (face font-lock-string-face) 30549 30581 (face font-lock-constant-face) 30581 30582 (face font-lock-string-face) 30582 30596 nil 30596 30597 (face font-lock-string-face) 30597 30626 (face font-lock-constant-face) 30626 30627 (face font-lock-string-face) 30627 30641 nil 30641 30642 (face font-lock-string-face) 30642 30670 (face font-lock-constant-face) 30670 30671 (face font-lock-string-face) 30671 30685 nil 30685 30686 (face font-lock-string-face) 30686 30714 (face font-lock-constant-face) 30714 30715 (face font-lock-string-face) 30715 30729 nil 30729 30730 (face font-lock-string-face) 30730 30757 (face font-lock-constant-face) 30757 30758 (face font-lock-string-face) 30758 30783 nil 30783 30784 (face font-lock-string-face) 30784 30794 (face font-lock-keyword-face) 30794 30795 (face font-lock-string-face) 30795 30812 nil 30812 30813 (face font-lock-string-face) 30813 30834 (face font-lock-variable-name-face) 30834 30835 (face font-lock-string-face) 30835 30853 nil 30853 30854 (face font-lock-string-face) 30854 30866 (face font-lock-keyword-face) 30866 30867 (face font-lock-string-face) 30867 30887 nil 30887 30888 (face font-lock-string-face) 30888 30917 (face font-lock-function-name-face) 30917 30918 (face font-lock-string-face) 30918 30951 nil 30951 30952 (face font-lock-string-face) 30952 30959 (face font-lock-keyword-face) 30959 30960 (face font-lock-string-face) 30960 30980 nil 30980 30981 (face font-lock-string-face) 30981 31015 (face font-lock-constant-face) 31015 31016 (face font-lock-string-face) 31016 31064 nil 31064 31065 (face font-lock-string-face) 31065 31074 (face font-lock-variable-name-face) 31074 31075 (face font-lock-string-face) 31075 31093 nil 31093 31094 (face font-lock-string-face) 31094 31106 (face font-lock-keyword-face) 31106 31107 (face font-lock-string-face) 31107 31127 nil 31127 31128 (face font-lock-string-face) 31128 31175 (face font-lock-function-name-face) 31175 31176 (face font-lock-string-face) 31176 31194 nil 31194 31195 (face font-lock-string-face) 31195 31245 (face font-lock-function-name-face) 31245 31246 (face font-lock-string-face) 31246 31279 nil 31279 31280 (face font-lock-string-face) 31280 31287 (face font-lock-keyword-face) 31287 31288 (face font-lock-string-face) 31288 31308 nil 31308 31309 (face font-lock-string-face) 31309 31341 (face font-lock-constant-face) 31341 31342 (face font-lock-string-face) 31342 31423 nil 31423 31424 (face font-lock-string-face) 31424 31462 (face font-lock-variable-name-face) 31462 31463 (face font-lock-string-face) 31463 31473 nil 31473 31474 (face font-lock-string-face) 31474 31481 (face font-lock-keyword-face) 31481 31482 (face font-lock-string-face) 31482 31506 nil 31506 31507 (face font-lock-string-face) 31507 31518 (face font-lock-keyword-face) 31518 31519 (face font-lock-string-face) 31519 31521 nil 31521 31522 (face font-lock-string-face) 31522 31539 (face font-lock-function-name-face) 31539 31540 (face font-lock-string-face) 31540 31552 nil 31552 31553 (face font-lock-string-face) 31553 31557 (face font-lock-keyword-face) 31557 31558 (face font-lock-string-face) 31558 31560 nil 31560 31561 (face font-lock-string-face) 31561 31571 (face font-lock-type-face) 31571 31572 (face font-lock-string-face) 31572 31584 nil 31584 31585 (face font-lock-string-face) 31585 31597 (face font-lock-keyword-face) 31597 31598 (face font-lock-string-face) 31598 31614 nil 31614 31615 (face font-lock-string-face) 31615 31636 (face font-lock-function-name-face) 31636 31637 (face font-lock-string-face) 31637 31651 nil 31651 31652 (face font-lock-string-face) 31652 31670 (face font-lock-function-name-face) 31670 31671 (face font-lock-string-face) 31671 31696 nil 31696 31697 (face font-lock-string-face) 31697 31706 (face font-lock-keyword-face) 31706 31707 (face font-lock-string-face) 31707 31723 nil 31723 31724 (face font-lock-string-face) 31724 31728 (face font-lock-constant-face) 31728 31729 (face font-lock-string-face) 31729 31743 nil 31743 31744 (face font-lock-string-face) 31744 31748 (face font-lock-constant-face) 31748 31749 (face font-lock-string-face) 31749 31774 nil 31774 31775 (face font-lock-string-face) 31775 31782 (face font-lock-keyword-face) 31782 31783 (face font-lock-string-face) 31783 31799 nil 31799 31800 (face font-lock-string-face) 31800 31844 (face font-lock-constant-face) 31844 31845 (face font-lock-string-face) 31845 31893 nil 31893 31894 (face font-lock-string-face) 31894 31943 (face font-lock-variable-name-face) 31943 31944 (face font-lock-string-face) 31944 31954 nil 31954 31955 (face font-lock-string-face) 31955 31962 (face font-lock-keyword-face) 31962 31963 (face font-lock-string-face) 31963 31987 nil 31987 31988 (face font-lock-string-face) 31988 31999 (face font-lock-keyword-face) 31999 32000 (face font-lock-string-face) 32000 32002 nil 32002 32003 (face font-lock-string-face) 32003 32013 (face font-lock-function-name-face) 32013 32014 (face font-lock-string-face) 32014 32026 nil 32026 32027 (face font-lock-string-face) 32027 32031 (face font-lock-keyword-face) 32031 32032 (face font-lock-string-face) 32032 32034 nil 32034 32035 (face font-lock-string-face) 32035 32045 (face font-lock-type-face) 32045 32046 (face font-lock-string-face) 32046 32058 nil 32058 32059 (face font-lock-string-face) 32059 32071 (face font-lock-keyword-face) 32071 32072 (face font-lock-string-face) 32072 32088 nil 32088 32089 (face font-lock-string-face) 32089 32094 (face font-lock-function-name-face) 32094 32095 (face font-lock-string-face) 32095 32109 nil 32109 32110 (face font-lock-string-face) 32110 32121 (face font-lock-function-name-face) 32121 32122 (face font-lock-string-face) 32122 32136 nil 32136 32137 (face font-lock-string-face) 32137 32158 (face font-lock-function-name-face) 32158 32159 (face font-lock-string-face) 32159 32173 nil 32173 32174 (face font-lock-string-face) 32174 32192 (face font-lock-function-name-face) 32192 32193 (face font-lock-string-face) 32193 32218 nil 32218 32219 (face font-lock-string-face) 32219 32232 (face font-lock-keyword-face) 32232 32233 (face font-lock-string-face) 32233 32249 nil 32249 32250 (face font-lock-string-face) 32250 32259 (face font-lock-keyword-face) 32259 32260 (face font-lock-string-face) 32260 32278 nil 32278 32279 (face font-lock-string-face) 32279 32283 (face font-lock-constant-face) 32283 32284 (face font-lock-string-face) 32284 32300 nil 32300 32301 (face font-lock-string-face) 32301 32306 (face font-lock-constant-face) 32306 32307 (face font-lock-string-face) 32307 32323 nil 32323 32324 (face font-lock-string-face) 32324 32333 (face font-lock-constant-face) 32333 32334 (face font-lock-string-face) 32334 32350 nil 32350 32351 (face font-lock-string-face) 32351 32357 (face font-lock-constant-face) 32357 32358 (face font-lock-string-face) 32358 32398 nil 32398 32399 (face font-lock-string-face) 32399 32406 (face font-lock-keyword-face) 32406 32407 (face font-lock-string-face) 32407 32423 nil 32423 32424 (face font-lock-string-face) 32424 32462 (face font-lock-constant-face) 32462 32463 (face font-lock-string-face) 32463 32477 nil 32477 32478 (face font-lock-string-face) 32478 32515 (face font-lock-constant-face) 32515 32516 (face font-lock-string-face) 32516 32530 nil 32530 32531 (face font-lock-string-face) 32531 32568 (face font-lock-constant-face) 32568 32569 (face font-lock-string-face) 32569 32583 nil 32583 32584 (face font-lock-string-face) 32584 32620 (face font-lock-constant-face) 32620 32621 (face font-lock-string-face) 32621 32635 nil 32635 32636 (face font-lock-string-face) 32636 32666 (face font-lock-constant-face) 32666 32667 (face font-lock-string-face) 32667 32681 nil 32681 32682 (face font-lock-string-face) 32682 32720 (face font-lock-constant-face) 32720 32721 (face font-lock-string-face) 32721 32735 nil 32735 32736 (face font-lock-string-face) 32736 32773 (face font-lock-constant-face) 32773 32774 (face font-lock-string-face) 32774 32822 nil 32822 32823 (face font-lock-string-face) 32823 32838 (face font-lock-variable-name-face) 32838 32839 (face font-lock-string-face) 32839 32849 nil 32849 32850 (face font-lock-string-face) 32850 32857 (face font-lock-keyword-face) 32857 32858 (face font-lock-string-face) 32858 32882 nil 32882 32883 (face font-lock-string-face) 32883 32894 (face font-lock-keyword-face) 32894 32895 (face font-lock-string-face) 32895 32897 nil 32897 32898 (face font-lock-string-face) 32898 32912 (face font-lock-function-name-face) 32912 32913 (face font-lock-string-face) 32913 32925 nil 32925 32926 (face font-lock-string-face) 32926 32930 (face font-lock-keyword-face) 32930 32931 (face font-lock-string-face) 32931 32933 nil 32933 32934 (face font-lock-string-face) 32934 32948 (face font-lock-type-face) 32948 32949 (face font-lock-string-face) 32949 32961 nil 32961 32962 (face font-lock-string-face) 32962 32969 (face font-lock-keyword-face) 32969 32970 (face font-lock-string-face) 32970 32986 nil 32986 32987 (face font-lock-string-face) 32987 33022 (face font-lock-constant-face) 33022 33023 (face font-lock-string-face) 33023 33037 nil 33037 33038 (face font-lock-string-face) 33038 33072 (face font-lock-constant-face) 33072 33073 (face font-lock-string-face) 33073 33098 nil 33098 33099 (face font-lock-string-face) 33099 33111 (face font-lock-keyword-face) 33111 33112 (face font-lock-string-face) 33112 33128 nil 33128 33129 (face font-lock-string-face) 33129 33150 (face font-lock-function-name-face) 33150 33151 (face font-lock-string-face) 33151 33176 nil 33176 33177 (face font-lock-string-face) 33177 33189 (face font-lock-keyword-face) 33189 33190 (face font-lock-string-face) 33190 33206 nil 33206 33207 (face font-lock-string-face) 33207 33209 (face font-lock-constant-face) 33209 33232 (face font-lock-variable-name-face) 33232 33239 (face font-lock-constant-face) 33239 33240 (face font-lock-string-face) 33240 33265 nil 33265 33266 (face font-lock-string-face) 33266 33273 (face font-lock-keyword-face) 33273 33274 (face font-lock-string-face) 33274 33306 nil 33306 33307 (face font-lock-string-face) 33307 33318 (face font-lock-keyword-face) 33318 33319 (face font-lock-string-face) 33319 33321 nil 33321 33322 (face font-lock-string-face) 33322 33342 (face font-lock-function-name-face) 33342 33343 (face font-lock-string-face) 33343 33359 nil 33359 33360 (face font-lock-string-face) 33360 33366 (face font-lock-keyword-face) 33366 33367 (face font-lock-string-face) 33367 33387 nil 33387 33388 (face font-lock-string-face) 33388 33434 (face font-lock-constant-face) 33434 33435 (face font-lock-string-face) 33435 33453 nil 33453 33454 (face font-lock-string-face) 33454 33519 (face font-lock-constant-face) 33519 33520 (face font-lock-string-face) 33520 33553 nil 33553 33554 (face font-lock-string-face) 33554 33561 (face font-lock-keyword-face) 33561 33562 (face font-lock-string-face) 33562 33582 nil 33582 33583 (face font-lock-string-face) 33583 33585 (face font-lock-constant-face) 33585 33608 (face font-lock-variable-name-face) 33608 33647 (face font-lock-constant-face) 33647 33648 (face font-lock-string-face) 33648 33681 nil 33681 33682 (face font-lock-string-face) 33682 33688 (face font-lock-keyword-face) 33688 33689 (face font-lock-string-face) 33689 33709 nil 33709 33710 (face font-lock-string-face) 33710 33716 (face font-lock-constant-face) 33716 33717 (face font-lock-string-face) 33717 33735 nil 33735 33736 (face font-lock-string-face) 33736 33738 (face font-lock-constant-face) 33738 33743 (face font-lock-variable-name-face) 33743 33788 (face font-lock-constant-face) 33788 33789 (face font-lock-string-face) 33789 33807 nil 33807 33808 (face font-lock-string-face) 33808 33810 (face font-lock-constant-face) 33810 33811 (face font-lock-string-face) 33811 33829 nil 33829 33830 (face font-lock-string-face) 33830 33833 (face font-lock-constant-face) 33833 33840 (face font-lock-variable-name-face) 33840 33841 (face font-lock-constant-face) 33841 33842 (face font-lock-string-face) 33842 33860 nil 33860 33861 (face font-lock-string-face) 33861 33864 (face font-lock-constant-face) 33864 33872 (face font-lock-variable-name-face) 33872 33873 (face font-lock-constant-face) 33873 33874 (face font-lock-string-face) 33874 33952 nil 33952 33953 (face font-lock-string-face) 33953 33964 (face font-lock-keyword-face) 33964 33965 (face font-lock-string-face) 33965 33967 nil 33967 33968 (face font-lock-string-face) 33968 33978 (face font-lock-function-name-face) 33978 33979 (face font-lock-string-face) 33979 33991 nil 33991 33992 (face font-lock-string-face) 33992 33996 (face font-lock-keyword-face) 33996 33997 (face font-lock-string-face) 33997 33999 nil 33999 34000 (face font-lock-string-face) 34000 34004 (face font-lock-type-face) 34004 34005 (face font-lock-string-face) 34005 34017 nil 34017 34018 (face font-lock-string-face) 34018 34030 (face font-lock-keyword-face) 34030 34031 (face font-lock-string-face) 34031 34035 nil 34035 34036 (face font-lock-string-face) 34036 34062 (face font-lock-function-name-face) 34062 34063 (face font-lock-string-face) 34063 34077 nil 34077 34078 (face font-lock-string-face) 34078 34087 (face font-lock-keyword-face) 34087 34088 (face font-lock-string-face) 34088 34104 nil 34104 34105 (face font-lock-string-face) 34105 34117 (face font-lock-variable-name-face) 34117 34118 (face font-lock-string-face) 34118 34120 nil 34120 34121 (face font-lock-string-face) 34121 34126 (face font-lock-variable-name-face) 34126 34127 (face font-lock-string-face) 34127 34141 nil 34141 34142 (face font-lock-string-face) 34142 34153 (face font-lock-variable-name-face) 34153 34154 (face font-lock-string-face) 34154 34156 nil 34156 34157 (face font-lock-string-face) 34157 34174 (face font-lock-variable-name-face) 34174 34175 (face font-lock-string-face) 34175 34200 nil 34200 34201 (face font-lock-string-face) 34201 34209 (face font-lock-keyword-face) 34209 34210 (face font-lock-string-face) 34210 34214 nil 34214 34215 (face font-lock-string-face) 34215 34233 (face font-lock-constant-face) 34233 34234 (face font-lock-string-face) 34234 34268 nil 34268 34287 (face font-lock-comment-face) 34287 34293 nil 34293 34365 (face font-lock-comment-face) 34365 34371 nil 34371 34372 (face font-lock-string-face) 34372 34379 (face font-lock-keyword-face) 34379 34380 (face font-lock-string-face) 34380 34404 nil 34404 34405 (face font-lock-string-face) 34405 34416 (face font-lock-keyword-face) 34416 34417 (face font-lock-string-face) 34417 34419 nil 34419 34420 (face font-lock-string-face) 34420 34436 (face font-lock-function-name-face) 34436 34437 (face font-lock-string-face) 34437 34449 nil 34449 34450 (face font-lock-string-face) 34450 34454 (face font-lock-keyword-face) 34454 34455 (face font-lock-string-face) 34455 34457 nil 34457 34458 (face font-lock-string-face) 34458 34468 (face font-lock-type-face) 34468 34469 (face font-lock-string-face) 34469 34481 nil 34481 34482 (face font-lock-string-face) 34482 34494 (face font-lock-keyword-face) 34494 34495 (face font-lock-string-face) 34495 34511 nil 34511 34512 (face font-lock-string-face) 34512 34517 (face font-lock-function-name-face) 34517 34518 (face font-lock-string-face) 34518 34532 nil 34532 34533 (face font-lock-string-face) 34533 34551 (face font-lock-function-name-face) 34551 34552 (face font-lock-string-face) 34552 34566 nil 34566 34567 (face font-lock-string-face) 34567 34588 (face font-lock-function-name-face) 34588 34589 (face font-lock-string-face) 34589 34603 nil 34603 34604 (face font-lock-string-face) 34604 34630 (face font-lock-function-name-face) 34630 34631 (face font-lock-string-face) 34631 34645 nil 34645 34646 (face font-lock-string-face) 34646 34680 (face font-lock-function-name-face) 34680 34681 (face font-lock-string-face) 34681 34695 nil 34695 34696 (face font-lock-string-face) 34696 34730 (face font-lock-function-name-face) 34730 34731 (face font-lock-string-face) 34731 34745 nil 34745 34746 (face font-lock-string-face) 34746 34772 (face font-lock-function-name-face) 34772 34773 (face font-lock-string-face) 34773 34787 nil 34787 34788 (face font-lock-string-face) 34788 34827 (face font-lock-function-name-face) 34827 34828 (face font-lock-string-face) 34828 34853 nil 34853 34854 (face font-lock-string-face) 34854 34861 (face font-lock-keyword-face) 34861 34862 (face font-lock-string-face) 34862 34878 nil 34878 34879 (face font-lock-string-face) 34879 34904 (face font-lock-constant-face) 34904 34905 (face font-lock-string-face) 34905 34930 nil 34930 34931 (face font-lock-string-face) 34931 34941 (face font-lock-keyword-face) 34941 34942 (face font-lock-string-face) 34942 34959 nil 34959 34960 (face font-lock-string-face) 34960 34981 (face font-lock-variable-name-face) 34981 34982 (face font-lock-string-face) 34982 35000 nil 35000 35001 (face font-lock-string-face) 35001 35013 (face font-lock-keyword-face) 35013 35014 (face font-lock-string-face) 35014 35034 nil 35034 35077 (face font-lock-comment-face) 35077 35093 nil 35093 35123 (face font-lock-comment-face) 35123 35139 nil 35139 35164 (face font-lock-comment-face) 35164 35180 nil 35180 35194 (face font-lock-comment-face) 35194 35210 nil 35210 35211 (face font-lock-string-face) 35211 35240 (face font-lock-function-name-face) 35240 35241 (face font-lock-string-face) 35241 35274 nil 35274 35275 (face font-lock-string-face) 35275 35285 (face font-lock-keyword-face) 35285 35286 (face font-lock-string-face) 35286 35307 nil 35307 35308 (face font-lock-string-face) 35308 35329 (face font-lock-variable-name-face) 35329 35330 (face font-lock-string-face) 35330 35352 nil 35352 35353 (face font-lock-string-face) 35353 35365 (face font-lock-keyword-face) 35365 35366 (face font-lock-string-face) 35366 35390 nil 35390 35391 (face font-lock-string-face) 35391 35432 (face font-lock-function-name-face) 35432 35433 (face font-lock-string-face) 35433 35553 nil 35553 35554 (face font-lock-string-face) 35554 35565 (face font-lock-keyword-face) 35565 35566 (face font-lock-string-face) 35566 35568 nil 35568 35569 (face font-lock-string-face) 35569 35592 (face font-lock-function-name-face) 35592 35593 (face font-lock-string-face) 35593 35605 nil 35605 35606 (face font-lock-string-face) 35606 35610 (face font-lock-keyword-face) 35610 35611 (face font-lock-string-face) 35611 35613 nil 35613 35614 (face font-lock-string-face) 35614 35624 (face font-lock-type-face) 35624 35625 (face font-lock-string-face) 35625 35637 nil 35637 35638 (face font-lock-string-face) 35638 35650 (face font-lock-keyword-face) 35650 35651 (face font-lock-string-face) 35651 35667 nil 35667 35668 (face font-lock-string-face) 35668 35673 (face font-lock-function-name-face) 35673 35674 (face font-lock-string-face) 35674 35688 nil 35688 35689 (face font-lock-string-face) 35689 35707 (face font-lock-function-name-face) 35707 35708 (face font-lock-string-face) 35708 35722 nil 35722 35723 (face font-lock-string-face) 35723 35757 (face font-lock-function-name-face) 35757 35758 (face font-lock-string-face) 35758 35772 nil 35772 35773 (face font-lock-string-face) 35773 35799 (face font-lock-function-name-face) 35799 35800 (face font-lock-string-face) 35800 35814 nil 35814 35815 (face font-lock-string-face) 35815 35841 (face font-lock-function-name-face) 35841 35842 (face font-lock-string-face) 35842 35856 nil 35856 35857 (face font-lock-string-face) 35857 35896 (face font-lock-function-name-face) 35896 35897 (face font-lock-string-face) 35897 35922 nil 35922 35923 (face font-lock-string-face) 35923 35930 (face font-lock-keyword-face) 35930 35931 (face font-lock-string-face) 35931 35947 nil 35947 35948 (face font-lock-string-face) 35948 35970 (face font-lock-constant-face) 35970 35971 (face font-lock-string-face) 35971 35985 nil 35985 35986 (face font-lock-string-face) 35986 36011 (face font-lock-constant-face) 36011 36012 (face font-lock-string-face) 36012 36026 nil 36026 36027 (face font-lock-string-face) 36027 36060 (face font-lock-constant-face) 36060 36061 (face font-lock-string-face) 36061 36075 nil 36075 36076 (face font-lock-string-face) 36076 36117 (face font-lock-constant-face) 36117 36118 (face font-lock-string-face) 36118 36143 nil 36143 36144 (face font-lock-string-face) 36144 36154 (face font-lock-keyword-face) 36154 36155 (face font-lock-string-face) 36155 36172 nil 36172 36173 (face font-lock-string-face) 36173 36198 (face font-lock-variable-name-face) 36198 36199 (face font-lock-string-face) 36199 36217 nil 36217 36218 (face font-lock-string-face) 36218 36228 (face font-lock-keyword-face) 36228 36229 (face font-lock-string-face) 36229 36250 nil 36250 36251 (face font-lock-string-face) 36251 36272 (face font-lock-variable-name-face) 36272 36273 (face font-lock-string-face) 36273 36295 nil 36295 36296 (face font-lock-string-face) 36296 36308 (face font-lock-keyword-face) 36308 36309 (face font-lock-string-face) 36309 36333 nil 36333 36334 (face font-lock-string-face) 36334 36375 (face font-lock-function-name-face) 36375 36376 (face font-lock-string-face) 36376 36496 nil 36496 36497 (face font-lock-string-face) 36497 36508 (face font-lock-keyword-face) 36508 36509 (face font-lock-string-face) 36509 36511 nil 36511 36512 (face font-lock-string-face) 36512 36524 (face font-lock-function-name-face) 36524 36525 (face font-lock-string-face) 36525 36537 nil 36537 36538 (face font-lock-string-face) 36538 36542 (face font-lock-keyword-face) 36542 36543 (face font-lock-string-face) 36543 36545 nil 36545 36546 (face font-lock-string-face) 36546 36556 (face font-lock-type-face) 36556 36557 (face font-lock-string-face) 36557 36569 nil 36569 36570 (face font-lock-string-face) 36570 36582 (face font-lock-keyword-face) 36582 36583 (face font-lock-string-face) 36583 36599 nil 36599 36600 (face font-lock-string-face) 36600 36605 (face font-lock-function-name-face) 36605 36606 (face font-lock-string-face) 36606 36620 nil 36620 36621 (face font-lock-string-face) 36621 36642 (face font-lock-function-name-face) 36642 36643 (face font-lock-string-face) 36643 36657 nil 36657 36658 (face font-lock-string-face) 36658 36697 (face font-lock-function-name-face) 36697 36698 (face font-lock-string-face) 36698 36723 nil 36723 36724 (face font-lock-string-face) 36724 36731 (face font-lock-keyword-face) 36731 36732 (face font-lock-string-face) 36732 36748 nil 36748 36749 (face font-lock-string-face) 36749 36782 (face font-lock-constant-face) 36782 36783 (face font-lock-string-face) 36783 36829 nil 36829 36830 (face font-lock-string-face) 36830 36841 (face font-lock-keyword-face) 36841 36842 (face font-lock-string-face) 36842 36844 nil 36844 36845 (face font-lock-string-face) 36845 36856 (face font-lock-function-name-face) 36856 36857 (face font-lock-string-face) 36857 36869 nil 36869 36870 (face font-lock-string-face) 36870 36874 (face font-lock-keyword-face) 36874 36875 (face font-lock-string-face) 36875 36877 nil 36877 36878 (face font-lock-string-face) 36878 36888 (face font-lock-type-face) 36888 36889 (face font-lock-string-face) 36889 36901 nil 36901 36902 (face font-lock-string-face) 36902 36914 (face font-lock-keyword-face) 36914 36915 (face font-lock-string-face) 36915 36931 nil 36931 36932 (face font-lock-string-face) 36932 36937 (face font-lock-function-name-face) 36937 36938 (face font-lock-string-face) 36938 36952 nil 36952 36953 (face font-lock-string-face) 36953 36974 (face font-lock-function-name-face) 36974 36975 (face font-lock-string-face) 36975 36989 nil 36989 36990 (face font-lock-string-face) 36990 37029 (face font-lock-function-name-face) 37029 37030 (face font-lock-string-face) 37030 37055 nil 37055 37056 (face font-lock-string-face) 37056 37063 (face font-lock-keyword-face) 37063 37064 (face font-lock-string-face) 37064 37080 nil 37080 37081 (face font-lock-string-face) 37081 37113 (face font-lock-constant-face) 37113 37114 (face font-lock-string-face) 37114 37163 nil)
diff --git a/chromium/tools/gyp/tools/graphviz.py b/chromium/tools/gyp/tools/graphviz.py
new file mode 100755
index 00000000000..326ae221cf8
--- /dev/null
+++ b/chromium/tools/gyp/tools/graphviz.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Using the JSON dumped by the dump-dependency-json generator,
+generate input suitable for graphviz to render a dependency graph of
+targets."""
+
+import collections
+import json
+import sys
+
+
+def ParseTarget(target):
+ target, _, suffix = target.partition('#')
+ filename, _, target = target.partition(':')
+ return filename, target, suffix
+
+
+def LoadEdges(filename, targets):
+ """Load the edges map from the dump file, and filter it to only
+ show targets in |targets| and their depedendents."""
+
+ file = open('dump.json')
+ edges = json.load(file)
+ file.close()
+
+ # Copy out only the edges we're interested in from the full edge list.
+ target_edges = {}
+ to_visit = targets[:]
+ while to_visit:
+ src = to_visit.pop()
+ if src in target_edges:
+ continue
+ target_edges[src] = edges[src]
+ to_visit.extend(edges[src])
+
+ return target_edges
+
+
+def WriteGraph(edges):
+ """Print a graphviz graph to stdout.
+ |edges| is a map of target to a list of other targets it depends on."""
+
+ # Bucket targets by file.
+ files = collections.defaultdict(list)
+ for src, dst in edges.items():
+ build_file, target_name, toolset = ParseTarget(src)
+ files[build_file].append(src)
+
+ print 'digraph D {'
+ print ' fontsize=8' # Used by subgraphs.
+ print ' node [fontsize=8]'
+
+ # Output nodes by file. We must first write out each node within
+ # its file grouping before writing out any edges that may refer
+ # to those nodes.
+ for filename, targets in files.items():
+ if len(targets) == 1:
+ # If there's only one node for this file, simplify
+ # the display by making it a box without an internal node.
+ target = targets[0]
+ build_file, target_name, toolset = ParseTarget(target)
+ print ' "%s" [shape=box, label="%s\\n%s"]' % (target, filename,
+ target_name)
+ else:
+ # Group multiple nodes together in a subgraph.
+ print ' subgraph "cluster_%s" {' % filename
+ print ' label = "%s"' % filename
+ for target in targets:
+ build_file, target_name, toolset = ParseTarget(target)
+ print ' "%s" [label="%s"]' % (target, target_name)
+ print ' }'
+
+ # Now that we've placed all the nodes within subgraphs, output all
+ # the edges between nodes.
+ for src, dsts in edges.items():
+ for dst in dsts:
+ print ' "%s" -> "%s"' % (src, dst)
+
+ print '}'
+
+
+def main():
+ if len(sys.argv) < 2:
+ print >>sys.stderr, __doc__
+ print >>sys.stderr
+ print >>sys.stderr, 'usage: %s target1 target2...' % (sys.argv[0])
+ return 1
+
+ edges = LoadEdges('dump.json', sys.argv[1:])
+
+ WriteGraph(edges)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/gyp/tools/pretty_gyp.py b/chromium/tools/gyp/tools/pretty_gyp.py
new file mode 100755
index 00000000000..c51d35872cc
--- /dev/null
+++ b/chromium/tools/gyp/tools/pretty_gyp.py
@@ -0,0 +1,155 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Pretty-prints the contents of a GYP file."""
+
+import sys
+import re
+
+
+# Regex to remove comments when we're counting braces.
+COMMENT_RE = re.compile(r'\s*#.*')
+
+# Regex to remove quoted strings when we're counting braces.
+# It takes into account quoted quotes, and makes sure that the quotes match.
+# NOTE: It does not handle quotes that span more than one line, or
+# cases where an escaped quote is preceeded by an escaped backslash.
+QUOTE_RE_STR = r'(?P<q>[\'"])(.*?)(?<![^\\][\\])(?P=q)'
+QUOTE_RE = re.compile(QUOTE_RE_STR)
+
+
+def comment_replace(matchobj):
+ return matchobj.group(1) + matchobj.group(2) + '#' * len(matchobj.group(3))
+
+
+def mask_comments(input):
+ """Mask the quoted strings so we skip braces inside quoted strings."""
+ search_re = re.compile(r'(.*?)(#)(.*)')
+ return [search_re.sub(comment_replace, line) for line in input]
+
+
+def quote_replace(matchobj):
+ return "%s%s%s%s" % (matchobj.group(1),
+ matchobj.group(2),
+ 'x'*len(matchobj.group(3)),
+ matchobj.group(2))
+
+
+def mask_quotes(input):
+ """Mask the quoted strings so we skip braces inside quoted strings."""
+ search_re = re.compile(r'(.*?)' + QUOTE_RE_STR)
+ return [search_re.sub(quote_replace, line) for line in input]
+
+
+def do_split(input, masked_input, search_re):
+ output = []
+ mask_output = []
+ for (line, masked_line) in zip(input, masked_input):
+ m = search_re.match(masked_line)
+ while m:
+ split = len(m.group(1))
+ line = line[:split] + r'\n' + line[split:]
+ masked_line = masked_line[:split] + r'\n' + masked_line[split:]
+ m = search_re.match(masked_line)
+ output.extend(line.split(r'\n'))
+ mask_output.extend(masked_line.split(r'\n'))
+ return (output, mask_output)
+
+
+def split_double_braces(input):
+ """Masks out the quotes and comments, and then splits appropriate
+ lines (lines that matche the double_*_brace re's above) before
+ indenting them below.
+
+ These are used to split lines which have multiple braces on them, so
+ that the indentation looks prettier when all laid out (e.g. closing
+ braces make a nice diagonal line).
+ """
+ double_open_brace_re = re.compile(r'(.*?[\[\{\(,])(\s*)([\[\{\(])')
+ double_close_brace_re = re.compile(r'(.*?[\]\}\)],?)(\s*)([\]\}\)])')
+
+ masked_input = mask_quotes(input)
+ masked_input = mask_comments(masked_input)
+
+ (output, mask_output) = do_split(input, masked_input, double_open_brace_re)
+ (output, mask_output) = do_split(output, mask_output, double_close_brace_re)
+
+ return output
+
+
+def count_braces(line):
+ """keeps track of the number of braces on a given line and returns the result.
+
+ It starts at zero and subtracts for closed braces, and adds for open braces.
+ """
+ open_braces = ['[', '(', '{']
+ close_braces = [']', ')', '}']
+ closing_prefix_re = re.compile(r'(.*?[^\s\]\}\)]+.*?)([\]\}\)],?)\s*$')
+ cnt = 0
+ stripline = COMMENT_RE.sub(r'', line)
+ stripline = QUOTE_RE.sub(r"''", stripline)
+ for char in stripline:
+ for brace in open_braces:
+ if char == brace:
+ cnt += 1
+ for brace in close_braces:
+ if char == brace:
+ cnt -= 1
+
+ after = False
+ if cnt > 0:
+ after = True
+
+ # This catches the special case of a closing brace having something
+ # other than just whitespace ahead of it -- we don't want to
+ # unindent that until after this line is printed so it stays with
+ # the previous indentation level.
+ if cnt < 0 and closing_prefix_re.match(stripline):
+ after = True
+ return (cnt, after)
+
+
+def prettyprint_input(lines):
+ """Does the main work of indenting the input based on the brace counts."""
+ indent = 0
+ basic_offset = 2
+ last_line = ""
+ for line in lines:
+ if COMMENT_RE.match(line):
+ print line
+ else:
+ line = line.strip('\r\n\t ') # Otherwise doesn't strip \r on Unix.
+ if len(line) > 0:
+ (brace_diff, after) = count_braces(line)
+ if brace_diff != 0:
+ if after:
+ print " " * (basic_offset * indent) + line
+ indent += brace_diff
+ else:
+ indent += brace_diff
+ print " " * (basic_offset * indent) + line
+ else:
+ print " " * (basic_offset * indent) + line
+ else:
+ print ""
+ last_line = line
+
+
+def main():
+ if len(sys.argv) > 1:
+ data = open(sys.argv[1]).read().splitlines()
+ else:
+ data = sys.stdin.read().splitlines()
+ # Split up the double braces.
+ lines = split_double_braces(data)
+
+ # Indent and print the output.
+ prettyprint_input(lines)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/gyp/tools/pretty_sln.py b/chromium/tools/gyp/tools/pretty_sln.py
new file mode 100755
index 00000000000..3195d8581be
--- /dev/null
+++ b/chromium/tools/gyp/tools/pretty_sln.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Prints the information in a sln file in a diffable way.
+
+ It first outputs each projects in alphabetical order with their
+ dependencies.
+
+ Then it outputs a possible build order.
+"""
+
+__author__ = 'nsylvain (Nicolas Sylvain)'
+
+import os
+import re
+import sys
+import pretty_vcproj
+
+def BuildProject(project, built, projects, deps):
+ # if all dependencies are done, we can build it, otherwise we try to build the
+ # dependency.
+ # This is not infinite-recursion proof.
+ for dep in deps[project]:
+ if dep not in built:
+ BuildProject(dep, built, projects, deps)
+ print project
+ built.append(project)
+
+def ParseSolution(solution_file):
+ # All projects, their clsid and paths.
+ projects = dict()
+
+ # A list of dependencies associated with a project.
+ dependencies = dict()
+
+ # Regular expressions that matches the SLN format.
+ # The first line of a project definition.
+ begin_project = re.compile(('^Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942'
+ '}"\) = "(.*)", "(.*)", "(.*)"$'))
+ # The last line of a project definition.
+ end_project = re.compile('^EndProject$')
+ # The first line of a dependency list.
+ begin_dep = re.compile('ProjectSection\(ProjectDependencies\) = postProject$')
+ # The last line of a dependency list.
+ end_dep = re.compile('EndProjectSection$')
+ # A line describing a dependency.
+ dep_line = re.compile(' *({.*}) = ({.*})$')
+
+ in_deps = False
+ solution = open(solution_file)
+ for line in solution:
+ results = begin_project.search(line)
+ if results:
+ # Hack to remove icu because the diff is too different.
+ if results.group(1).find('icu') != -1:
+ continue
+ # We remove "_gyp" from the names because it helps to diff them.
+ current_project = results.group(1).replace('_gyp', '')
+ projects[current_project] = [results.group(2).replace('_gyp', ''),
+ results.group(3),
+ results.group(2)]
+ dependencies[current_project] = []
+ continue
+
+ results = end_project.search(line)
+ if results:
+ current_project = None
+ continue
+
+ results = begin_dep.search(line)
+ if results:
+ in_deps = True
+ continue
+
+ results = end_dep.search(line)
+ if results:
+ in_deps = False
+ continue
+
+ results = dep_line.search(line)
+ if results and in_deps and current_project:
+ dependencies[current_project].append(results.group(1))
+ continue
+
+ # Change all dependencies clsid to name instead.
+ for project in dependencies:
+ # For each dependencies in this project
+ new_dep_array = []
+ for dep in dependencies[project]:
+ # Look for the project name matching this cldis
+ for project_info in projects:
+ if projects[project_info][1] == dep:
+ new_dep_array.append(project_info)
+ dependencies[project] = sorted(new_dep_array)
+
+ return (projects, dependencies)
+
+def PrintDependencies(projects, deps):
+ print "---------------------------------------"
+ print "Dependencies for all projects"
+ print "---------------------------------------"
+ print "-- --"
+
+ for (project, dep_list) in sorted(deps.items()):
+ print "Project : %s" % project
+ print "Path : %s" % projects[project][0]
+ if dep_list:
+ for dep in dep_list:
+ print " - %s" % dep
+ print ""
+
+ print "-- --"
+
+def PrintBuildOrder(projects, deps):
+ print "---------------------------------------"
+ print "Build order "
+ print "---------------------------------------"
+ print "-- --"
+
+ built = []
+ for (project, _) in sorted(deps.items()):
+ if project not in built:
+ BuildProject(project, built, projects, deps)
+
+ print "-- --"
+
+def PrintVCProj(projects):
+
+ for project in projects:
+ print "-------------------------------------"
+ print "-------------------------------------"
+ print project
+ print project
+ print project
+ print "-------------------------------------"
+ print "-------------------------------------"
+
+ project_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[1]),
+ projects[project][2]))
+
+ pretty = pretty_vcproj
+ argv = [ '',
+ project_path,
+ '$(SolutionDir)=%s\\' % os.path.dirname(sys.argv[1]),
+ ]
+ argv.extend(sys.argv[3:])
+ pretty.main(argv)
+
+def main():
+ # check if we have exactly 1 parameter.
+ if len(sys.argv) < 2:
+ print 'Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0]
+ return 1
+
+ (projects, deps) = ParseSolution(sys.argv[1])
+ PrintDependencies(projects, deps)
+ PrintBuildOrder(projects, deps)
+
+ if '--recursive' in sys.argv:
+ PrintVCProj(projects)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/gyp/tools/pretty_vcproj.py b/chromium/tools/gyp/tools/pretty_vcproj.py
new file mode 100755
index 00000000000..6099bd7cc4d
--- /dev/null
+++ b/chromium/tools/gyp/tools/pretty_vcproj.py
@@ -0,0 +1,329 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Make the format of a vcproj really pretty.
+
+ This script normalize and sort an xml. It also fetches all the properties
+ inside linked vsprops and include them explicitly in the vcproj.
+
+ It outputs the resulting xml to stdout.
+"""
+
+__author__ = 'nsylvain (Nicolas Sylvain)'
+
+import os
+import sys
+
+from xml.dom.minidom import parse
+from xml.dom.minidom import Node
+
+REPLACEMENTS = dict()
+ARGUMENTS = None
+
+
+class CmpTuple(object):
+ """Compare function between 2 tuple."""
+ def __call__(self, x, y):
+ return cmp(x[0], y[0])
+
+
+class CmpNode(object):
+ """Compare function between 2 xml nodes."""
+
+ def __call__(self, x, y):
+ def get_string(node):
+ node_string = "node"
+ node_string += node.nodeName
+ if node.nodeValue:
+ node_string += node.nodeValue
+
+ if node.attributes:
+ # We first sort by name, if present.
+ node_string += node.getAttribute("Name")
+
+ all_nodes = []
+ for (name, value) in node.attributes.items():
+ all_nodes.append((name, value))
+
+ all_nodes.sort(CmpTuple())
+ for (name, value) in all_nodes:
+ node_string += name
+ node_string += value
+
+ return node_string
+
+ return cmp(get_string(x), get_string(y))
+
+
+def PrettyPrintNode(node, indent=0):
+ if node.nodeType == Node.TEXT_NODE:
+ if node.data.strip():
+ print '%s%s' % (' '*indent, node.data.strip())
+ return
+
+ if node.childNodes:
+ node.normalize()
+ # Get the number of attributes
+ attr_count = 0
+ if node.attributes:
+ attr_count = node.attributes.length
+
+ # Print the main tag
+ if attr_count == 0:
+ print '%s<%s>' % (' '*indent, node.nodeName)
+ else:
+ print '%s<%s' % (' '*indent, node.nodeName)
+
+ all_attributes = []
+ for (name, value) in node.attributes.items():
+ all_attributes.append((name, value))
+ all_attributes.sort(CmpTuple())
+ for (name, value) in all_attributes:
+ print '%s %s="%s"' % (' '*indent, name, value)
+ print '%s>' % (' '*indent)
+ if node.nodeValue:
+ print '%s %s' % (' '*indent, node.nodeValue)
+
+ for sub_node in node.childNodes:
+ PrettyPrintNode(sub_node, indent=indent+2)
+ print '%s</%s>' % (' '*indent, node.nodeName)
+
+
+def FlattenFilter(node):
+ """Returns a list of all the node and sub nodes."""
+ node_list = []
+
+ if (node.attributes and
+ node.getAttribute('Name') == '_excluded_files'):
+ # We don't add the "_excluded_files" filter.
+ return []
+
+ for current in node.childNodes:
+ if current.nodeName == 'Filter':
+ node_list.extend(FlattenFilter(current))
+ else:
+ node_list.append(current)
+
+ return node_list
+
+
+def FixFilenames(filenames, current_directory):
+ new_list = []
+ for filename in filenames:
+ if filename:
+ for key in REPLACEMENTS:
+ filename = filename.replace(key, REPLACEMENTS[key])
+ os.chdir(current_directory)
+ filename = filename.strip('"\' ')
+ if filename.startswith('$'):
+ new_list.append(filename)
+ else:
+ new_list.append(os.path.abspath(filename))
+ return new_list
+
+
+def AbsoluteNode(node):
+ """Makes all the properties we know about in this node absolute."""
+ if node.attributes:
+ for (name, value) in node.attributes.items():
+ if name in ['InheritedPropertySheets', 'RelativePath',
+ 'AdditionalIncludeDirectories',
+ 'IntermediateDirectory', 'OutputDirectory',
+ 'AdditionalLibraryDirectories']:
+ # We want to fix up these paths
+ path_list = value.split(';')
+ new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1]))
+ node.setAttribute(name, ';'.join(new_list))
+ if not value:
+ node.removeAttribute(name)
+
+
+def CleanupVcproj(node):
+ """For each sub node, we call recursively this function."""
+ for sub_node in node.childNodes:
+ AbsoluteNode(sub_node)
+ CleanupVcproj(sub_node)
+
+ # Normalize the node, and remove all extranous whitespaces.
+ for sub_node in node.childNodes:
+ if sub_node.nodeType == Node.TEXT_NODE:
+ sub_node.data = sub_node.data.replace("\r", "")
+ sub_node.data = sub_node.data.replace("\n", "")
+ sub_node.data = sub_node.data.rstrip()
+
+ # Fix all the semicolon separated attributes to be sorted, and we also
+ # remove the dups.
+ if node.attributes:
+ for (name, value) in node.attributes.items():
+ sorted_list = sorted(value.split(';'))
+ unique_list = []
+ for i in sorted_list:
+ if not unique_list.count(i):
+ unique_list.append(i)
+ node.setAttribute(name, ';'.join(unique_list))
+ if not value:
+ node.removeAttribute(name)
+
+ if node.childNodes:
+ node.normalize()
+
+ # For each node, take a copy, and remove it from the list.
+ node_array = []
+ while node.childNodes and node.childNodes[0]:
+ # Take a copy of the node and remove it from the list.
+ current = node.childNodes[0]
+ node.removeChild(current)
+
+ # If the child is a filter, we want to append all its children
+ # to this same list.
+ if current.nodeName == 'Filter':
+ node_array.extend(FlattenFilter(current))
+ else:
+ node_array.append(current)
+
+
+ # Sort the list.
+ node_array.sort(CmpNode())
+
+ # Insert the nodes in the correct order.
+ for new_node in node_array:
+ # But don't append empty tool node.
+ if new_node.nodeName == 'Tool':
+ if new_node.attributes and new_node.attributes.length == 1:
+ # This one was empty.
+ continue
+ if new_node.nodeName == 'UserMacro':
+ continue
+ node.appendChild(new_node)
+
+
+def GetConfiguationNodes(vcproj):
+ #TODO(nsylvain): Find a better way to navigate the xml.
+ nodes = []
+ for node in vcproj.childNodes:
+ if node.nodeName == "Configurations":
+ for sub_node in node.childNodes:
+ if sub_node.nodeName == "Configuration":
+ nodes.append(sub_node)
+
+ return nodes
+
+
+def GetChildrenVsprops(filename):
+ dom = parse(filename)
+ if dom.documentElement.attributes:
+ vsprops = dom.documentElement.getAttribute('InheritedPropertySheets')
+ return FixFilenames(vsprops.split(';'), os.path.dirname(filename))
+ return []
+
+def SeekToNode(node1, child2):
+ # A text node does not have properties.
+ if child2.nodeType == Node.TEXT_NODE:
+ return None
+
+ # Get the name of the current node.
+ current_name = child2.getAttribute("Name")
+ if not current_name:
+ # There is no name. We don't know how to merge.
+ return None
+
+ # Look through all the nodes to find a match.
+ for sub_node in node1.childNodes:
+ if sub_node.nodeName == child2.nodeName:
+ name = sub_node.getAttribute("Name")
+ if name == current_name:
+ return sub_node
+
+ # No match. We give up.
+ return None
+
+
+def MergeAttributes(node1, node2):
+ # No attributes to merge?
+ if not node2.attributes:
+ return
+
+ for (name, value2) in node2.attributes.items():
+ # Don't merge the 'Name' attribute.
+ if name == 'Name':
+ continue
+ value1 = node1.getAttribute(name)
+ if value1:
+ # The attribute exist in the main node. If it's equal, we leave it
+ # untouched, otherwise we concatenate it.
+ if value1 != value2:
+ node1.setAttribute(name, ';'.join([value1, value2]))
+ else:
+ # The attribute does nto exist in the main node. We append this one.
+ node1.setAttribute(name, value2)
+
+ # If the attribute was a property sheet attributes, we remove it, since
+ # they are useless.
+ if name == 'InheritedPropertySheets':
+ node1.removeAttribute(name)
+
+
+def MergeProperties(node1, node2):
+ MergeAttributes(node1, node2)
+ for child2 in node2.childNodes:
+ child1 = SeekToNode(node1, child2)
+ if child1:
+ MergeProperties(child1, child2)
+ else:
+ node1.appendChild(child2.cloneNode(True))
+
+
+def main(argv):
+ """Main function of this vcproj prettifier."""
+ global ARGUMENTS
+ ARGUMENTS = argv
+
+ # check if we have exactly 1 parameter.
+ if len(argv) < 2:
+ print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] '
+ '[key2=value2]' % argv[0])
+ return 1
+
+ # Parse the keys
+ for i in range(2, len(argv)):
+ (key, value) = argv[i].split('=')
+ REPLACEMENTS[key] = value
+
+ # Open the vcproj and parse the xml.
+ dom = parse(argv[1])
+
+ # First thing we need to do is find the Configuration Node and merge them
+ # with the vsprops they include.
+ for configuration_node in GetConfiguationNodes(dom.documentElement):
+ # Get the property sheets associated with this configuration.
+ vsprops = configuration_node.getAttribute('InheritedPropertySheets')
+
+ # Fix the filenames to be absolute.
+ vsprops_list = FixFilenames(vsprops.strip().split(';'),
+ os.path.dirname(argv[1]))
+
+ # Extend the list of vsprops with all vsprops contained in the current
+ # vsprops.
+ for current_vsprops in vsprops_list:
+ vsprops_list.extend(GetChildrenVsprops(current_vsprops))
+
+ # Now that we have all the vsprops, we need to merge them.
+ for current_vsprops in vsprops_list:
+ MergeProperties(configuration_node,
+ parse(current_vsprops).documentElement)
+
+ # Now that everything is merged, we need to cleanup the xml.
+ CleanupVcproj(dom.documentElement)
+
+ # Finally, we use the prett xml function to print the vcproj back to the
+ # user.
+ #print dom.toprettyxml(newl="\n")
+ PrettyPrintNode(dom.documentElement)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/tools/gypv8sh.py b/chromium/tools/gypv8sh.py
new file mode 100755
index 00000000000..918368cbbfc
--- /dev/null
+++ b/chromium/tools/gypv8sh.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This script is used by chrome_tests.gypi's js2webui action to maintain the
+argument lists and to generate inlinable tests.
+
+Usage:
+ python tools/gypv8sh.py v8_shell mock.js test_api.js js2webui.js \
+ inputfile inputrelfile cxxoutfile jsoutfile
+"""
+
+import json
+import optparse
+import os
+import subprocess
+import sys
+import shutil
+
+
+def main ():
+ parser = optparse.OptionParser()
+ parser.set_usage(
+ "%prog v8_shell mock.js axs_testing.js test_api.js js2webui.js "
+ "testtype inputfile inputrelfile cxxoutfile jsoutfile")
+ parser.add_option('-v', '--verbose', action='store_true')
+ parser.add_option('-n', '--impotent', action='store_true',
+ help="don't execute; just print (as if verbose)")
+ (opts, args) = parser.parse_args()
+
+ if len(args) != 10:
+ parser.error('all arguments are required.')
+ (v8_shell, mock_js, axs_testing_js, test_api, js2webui, test_type,
+ inputfile, inputrelfile, cxxoutfile, jsoutfile) = args
+ arguments = [js2webui, inputfile, inputrelfile, cxxoutfile, test_type]
+ cmd = [v8_shell, '-e', "arguments=" + json.dumps(arguments), mock_js,
+ axs_testing_js, test_api, js2webui]
+ if opts.verbose or opts.impotent:
+ print cmd
+ if not opts.impotent:
+ try:
+ with open(cxxoutfile, 'w') as f:
+ subprocess.check_call(cmd, stdin=subprocess.PIPE, stdout=f)
+ shutil.copyfile(inputfile, jsoutfile)
+ except Exception, ex:
+ if os.path.exists(cxxoutfile):
+ os.remove(cxxoutfile)
+ if os.path.exists(jsoutfile):
+ os.remove(jsoutfile)
+ raise
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/heapcheck/PRESUBMIT.py b/chromium/tools/heapcheck/PRESUBMIT.py
new file mode 100644
index 00000000000..075dd1c8f4e
--- /dev/null
+++ b/chromium/tools/heapcheck/PRESUBMIT.py
@@ -0,0 +1,63 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into gcl.
+"""
+
+import re
+
+def CheckChange(input_api, output_api):
+ """Checks the heapcheck suppressions files for bad data."""
+ sup_regex = re.compile('suppressions.*\.txt$')
+ suppressions = {}
+ errors = []
+ check_for_heapcheck = False
+ skip_next_line = False
+ for f in filter(lambda x: sup_regex.search(x.LocalPath()),
+ input_api.AffectedFiles()):
+ for line, line_num in zip(f.NewContents(),
+ xrange(1, len(f.NewContents()) + 1)):
+ line = line.lstrip()
+ if line.startswith('#') or not line:
+ continue
+
+ if skip_next_line:
+ if 'insert_a_suppression_name_here' in line:
+ errors.append('"insert_a_suppression_name_here" is not a valid '
+ 'suppression name')
+ if suppressions.has_key(line):
+ errors.append('suppression with name "%s" at %s line %s has already '
+ 'been defined at line %s' % (line, f.LocalPath(),
+ line_num,
+ suppressions[line][1]))
+ else:
+ suppressions[line] = (f, line_num)
+ check_for_heapcheck = True
+ skip_next_line = False
+ continue
+ if check_for_heapcheck:
+ if not line == 'Heapcheck:Leak':
+ errors.append('"%s" should be "Heapcheck:Leak" in %s line %s' %
+ (line, f.LocalPath(), line_num))
+ check_for_heapcheck = False;
+ if line == '{':
+ skip_next_line = True
+ continue
+ if (line.startswith('fun:') or line.startswith('obj:') or
+ line == 'Heapcheck:Leak' or line == '}' or
+ line == '...'):
+ continue
+ errors.append('"%s" is probably wrong: %s line %s' % (line, f.LocalPath(),
+ line_num))
+ if errors:
+ return [output_api.PresubmitError('\n'.join(errors))]
+ return []
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CheckChange(input_api, output_api)
diff --git a/chromium/tools/heapcheck/base_unittests.gtest-heapcheck.txt b/chromium/tools/heapcheck/base_unittests.gtest-heapcheck.txt
new file mode 100644
index 00000000000..00589f8d6d2
--- /dev/null
+++ b/chromium/tools/heapcheck/base_unittests.gtest-heapcheck.txt
@@ -0,0 +1,3 @@
+# Failing after Lucid migration. http://crbug.com/82715
+ProcessUtilTest.GetTerminationStatusExit
+SharedMemoryProcessTest.Tasks
diff --git a/chromium/tools/heapcheck/chrome_tests.py b/chromium/tools/heapcheck/chrome_tests.py
new file mode 100755
index 00000000000..5d1e9d9c138
--- /dev/null
+++ b/chromium/tools/heapcheck/chrome_tests.py
@@ -0,0 +1,499 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+''' Runs various chrome tests through heapcheck_test.py.
+
+Most of this code is copied from ../valgrind/chrome_tests.py.
+TODO(glider): put common functions to a standalone module.
+'''
+
+import glob
+import logging
+import optparse
+import os
+import stat
+import sys
+
+import logging_utils
+import path_utils
+
+import common
+import heapcheck_test
+
+class TestNotFound(Exception): pass
+
+def Dir2IsNewer(dir1, dir2):
+ if dir2 is None or not os.path.isdir(dir2):
+ return False
+ if dir1 is None or not os.path.isdir(dir1):
+ return True
+ return os.stat(dir2)[stat.ST_MTIME] > os.stat(dir1)[stat.ST_MTIME]
+
+def FindNewestDir(dirs):
+ newest_dir = None
+ for dir in dirs:
+ if Dir2IsNewer(newest_dir, dir):
+ newest_dir = dir
+ return newest_dir
+
+def File2IsNewer(file1, file2):
+ if file2 is None or not os.path.isfile(file2):
+ return False
+ if file1 is None or not os.path.isfile(file1):
+ return True
+ return os.stat(file2)[stat.ST_MTIME] > os.stat(file1)[stat.ST_MTIME]
+
+def FindDirContainingNewestFile(dirs, file):
+ """Searches for the directory containing the newest copy of |file|.
+
+ Args:
+ dirs: A list of paths to the directories to search among.
+ file: A string containing the file name to search.
+
+ Returns:
+ The string representing the the directory containing the newest copy of
+ |file|.
+
+ Raises:
+ IOError: |file| was not found.
+ """
+ newest_dir = None
+ newest_file = None
+ for dir in dirs:
+ the_file = os.path.join(dir, file)
+ if File2IsNewer(newest_file, the_file):
+ newest_dir = dir
+ newest_file = the_file
+ if newest_dir is None:
+ raise IOError("cannot find file %s anywhere, have you built it?" % file)
+ return newest_dir
+
+class ChromeTests(object):
+ '''This class is derived from the chrome_tests.py file in ../purify/.
+ '''
+
+ def __init__(self, options, args, test):
+ # The known list of tests.
+ # Recognise the original abbreviations as well as full executable names.
+ self._test_list = {
+ "app_list": self.TestAppList, "app_list_unittests": self.TestAppList,
+ "ash": self.TestAsh, "ash_unittests": self.TestAsh,
+ "aura": self.TestAura, "aura_unittests": self.TestAura,
+ "base": self.TestBase, "base_unittests": self.TestBase,
+ "browser": self.TestBrowser, "browser_tests": self.TestBrowser,
+ "chromeos": self.TestChromeOS, "chromeos_unittests": self.TestChromeOS,
+ "components": self.TestComponents,
+ "components_unittests": self.TestComponents,
+ "compositor": self.TestCompositor,
+ "compositor_unittests": self.TestCompositor,
+ "content": self.TestContent, "content_unittests": self.TestContent,
+ "content_browsertests": self.TestContentBrowser,
+ "courgette": self.TestCourgette,
+ "courgette_unittests": self.TestCourgette,
+ "crypto": self.TestCrypto, "crypto_unittests": self.TestCrypto,
+ "device": self.TestDevice, "device_unittests": self.TestDevice,
+ "gpu": self.TestGPU, "gpu_unittests": self.TestGPU,
+ "ipc": self.TestIpc, "ipc_tests": self.TestIpc,
+ "jingle": self.TestJingle, "jingle_unittests": self.TestJingle,
+ "layout": self.TestLayout, "layout_tests": self.TestLayout,
+ "media": self.TestMedia, "media_unittests": self.TestMedia,
+ "message_center": self.TestMessageCenter,
+ "message_center_unittests" : self.TestMessageCenter,
+ "net": self.TestNet, "net_unittests": self.TestNet,
+ "ppapi": self.TestPPAPI, "ppapi_unittests": self.TestPPAPI,
+ "printing": self.TestPrinting, "printing_unittests": self.TestPrinting,
+ "remoting": self.TestRemoting, "remoting_unittests": self.TestRemoting,
+ "sql": self.TestSql, "sql_unittests": self.TestSql,
+ "startup": self.TestStartup, "startup_tests": self.TestStartup,
+ "sync": self.TestSync, "sync_unit_tests": self.TestSync,
+ "ui_unit": self.TestUIUnit, "ui_unittests": self.TestUIUnit,
+ "unit": self.TestUnit, "unit_tests": self.TestUnit,
+ "url": self.TestURL, "url_unittests": self.TestURL,
+ "views": self.TestViews, "views_unittests": self.TestViews,
+ }
+
+ if test not in self._test_list:
+ raise TestNotFound("Unknown test: %s" % test)
+
+ self._options = options
+ self._args = args
+ self._test = test
+
+ script_dir = path_utils.ScriptDir()
+
+ # Compute the top of the tree (the "source dir") from the script dir (where
+ # this script lives). We assume that the script dir is in tools/heapcheck/
+ # relative to the top of the tree.
+ self._source_dir = os.path.dirname(os.path.dirname(script_dir))
+
+ # Since this path is used for string matching, make sure it's always
+ # an absolute Unix-style path.
+ self._source_dir = os.path.abspath(self._source_dir).replace('\\', '/')
+
+ heapcheck_test_script = os.path.join(script_dir, "heapcheck_test.py")
+ self._command_preamble = [heapcheck_test_script]
+
+ def _DefaultCommand(self, module, exe=None, heapcheck_test_args=None):
+ '''Generates the default command array that most tests will use.
+
+ Args:
+ module: The module name (corresponds to the dir in src/ where the test
+ data resides).
+ exe: The executable name.
+ heapcheck_test_args: additional arguments to append to the command line.
+ Returns:
+ A string with the command to run the test.
+ '''
+ if not self._options.build_dir:
+ dirs = [
+ os.path.join(self._source_dir, "xcodebuild", "Debug"),
+ os.path.join(self._source_dir, "out", "Debug"),
+ ]
+ if exe:
+ self._options.build_dir = FindDirContainingNewestFile(dirs, exe)
+ else:
+ self._options.build_dir = FindNewestDir(dirs)
+
+ cmd = list(self._command_preamble)
+
+ if heapcheck_test_args != None:
+ for arg in heapcheck_test_args:
+ cmd.append(arg)
+ if exe:
+ cmd.append(os.path.join(self._options.build_dir, exe))
+ # Heapcheck runs tests slowly, so slow tests hurt more; show elapased time
+ # so we can find the slowpokes.
+ cmd.append("--gtest_print_time")
+ if self._options.gtest_repeat:
+ cmd.append("--gtest_repeat=%s" % self._options.gtest_repeat)
+ return cmd
+
+ def Suppressions(self):
+ '''Builds the list of available suppressions files.'''
+ ret = []
+ directory = path_utils.ScriptDir()
+ suppression_file = os.path.join(directory, "suppressions.txt")
+ if os.path.exists(suppression_file):
+ ret.append(suppression_file)
+ suppression_file = os.path.join(directory, "suppressions_linux.txt")
+ if os.path.exists(suppression_file):
+ ret.append(suppression_file)
+ return ret
+
+ def Run(self):
+ '''Runs the test specified by command-line argument --test.'''
+ logging.info("running test %s" % (self._test))
+ return self._test_list[self._test]()
+
+ def _ReadGtestFilterFile(self, name, cmd):
+ '''Reads files which contain lists of tests to filter out with
+ --gtest_filter and appends the command-line option to |cmd|.
+
+ Args:
+ name: the test executable name.
+ cmd: the test running command line to be modified.
+ '''
+ filters = []
+ directory = path_utils.ScriptDir()
+ gtest_filter_files = [
+ os.path.join(directory, name + ".gtest-heapcheck.txt"),
+ # TODO(glider): Linux vs. CrOS?
+ ]
+ logging.info("Reading gtest exclude filter files:")
+ for filename in gtest_filter_files:
+ # strip the leading absolute path (may be very long on the bot)
+ # and the following / or \.
+ readable_filename = filename.replace(self._source_dir, "")[1:]
+ if not os.path.exists(filename):
+ logging.info(" \"%s\" - not found" % readable_filename)
+ continue
+ logging.info(" \"%s\" - OK" % readable_filename)
+ f = open(filename, 'r')
+ for line in f.readlines():
+ if line.startswith("#") or line.startswith("//") or line.isspace():
+ continue
+ line = line.rstrip()
+ filters.append(line)
+ gtest_filter = self._options.gtest_filter
+ if len(filters):
+ if gtest_filter:
+ gtest_filter += ":"
+ if gtest_filter.find("-") < 0:
+ gtest_filter += "-"
+ else:
+ gtest_filter = "-"
+ gtest_filter += ":".join(filters)
+ if gtest_filter:
+ cmd.append("--gtest_filter=%s" % gtest_filter)
+
+ def SimpleTest(self, module, name, heapcheck_test_args=None, cmd_args=None):
+ '''Builds the command line and runs the specified test.
+
+ Args:
+ module: The module name (corresponds to the dir in src/ where the test
+ data resides).
+ name: The executable name.
+ heapcheck_test_args: Additional command line args for heap checker.
+ cmd_args: Additional command line args for the test.
+ '''
+ cmd = self._DefaultCommand(module, name, heapcheck_test_args)
+ supp = self.Suppressions()
+ self._ReadGtestFilterFile(name, cmd)
+ if cmd_args:
+ cmd.extend(["--"])
+ cmd.extend(cmd_args)
+
+ # Sets LD_LIBRARY_PATH to the build folder so external libraries can be
+ # loaded.
+ if (os.getenv("LD_LIBRARY_PATH")):
+ os.putenv("LD_LIBRARY_PATH", "%s:%s" % (os.getenv("LD_LIBRARY_PATH"),
+ self._options.build_dir))
+ else:
+ os.putenv("LD_LIBRARY_PATH", self._options.build_dir)
+ return heapcheck_test.RunTool(cmd, supp, module)
+
+ # TODO(glider): it's an overkill to define a method for each simple test.
+ def TestAppList(self):
+ return self.SimpleTest("app_list", "app_list_unittests")
+
+ def TestAsh(self):
+ return self.SimpleTest("ash", "ash_unittests")
+
+ def TestAura(self):
+ return self.SimpleTest("aura", "aura_unittests")
+
+ def TestBase(self):
+ return self.SimpleTest("base", "base_unittests")
+
+ def TestBrowser(self):
+ return self.SimpleTest("chrome", "browser_tests")
+
+ def TestChromeOS(self):
+ return self.SimpleTest("chromeos", "chromeos_unittests")
+
+ def TestComponents(self):
+ return self.SimpleTest("components", "components_unittests")
+
+ def TestCompositor(self):
+ return self.SimpleTest("compositor", "compositor_unittests")
+
+ def TestContent(self):
+ return self.SimpleTest("content", "content_unittests")
+
+ def TestContentBrowser(self):
+ return self.SimpleTest("content", "content_browsertests")
+
+ def TestCourgette(self):
+ return self.SimpleTest("courgette", "courgette_unittests")
+
+ def TestCrypto(self):
+ return self.SimpleTest("crypto", "crypto_unittests")
+
+ def TestDevice(self):
+ return self.SimpleTest("device", "device_unittests")
+
+ def TestGPU(self):
+ return self.SimpleTest("gpu", "gpu_unittests")
+
+ def TestIpc(self):
+ return self.SimpleTest("ipc", "ipc_tests")
+
+ def TestJingle(self):
+ return self.SimpleTest("chrome", "jingle_unittests")
+
+ def TestMedia(self):
+ return self.SimpleTest("chrome", "media_unittests")
+
+ def TestMessageCenter(self):
+ return self.SimpleTest("message_center", "message_center_unittests")
+
+ def TestNet(self):
+ return self.SimpleTest("net", "net_unittests")
+
+ def TestPPAPI(self):
+ return self.SimpleTest("chrome", "ppapi_unittests")
+
+ def TestPrinting(self):
+ return self.SimpleTest("chrome", "printing_unittests")
+
+ def TestRemoting(self):
+ return self.SimpleTest("chrome", "remoting_unittests")
+
+ def TestSync(self):
+ return self.SimpleTest("chrome", "sync_unit_tests")
+
+ def TestStartup(self):
+ # We don't need the performance results, we're just looking for pointer
+ # errors, so set number of iterations down to the minimum.
+ os.putenv("STARTUP_TESTS_NUMCYCLES", "1")
+ logging.info("export STARTUP_TESTS_NUMCYCLES=1");
+ return self.SimpleTest("chrome", "startup_tests")
+
+ def TestUIUnit(self):
+ return self.SimpleTest("chrome", "ui_unittests")
+
+ def TestUnit(self):
+ return self.SimpleTest("chrome", "unit_tests")
+
+ def TestURL(self):
+ return self.SimpleTest("chrome", "url_unittests")
+
+ def TestSql(self):
+ return self.SimpleTest("chrome", "sql_unittests")
+
+ def TestViews(self):
+ return self.SimpleTest("views", "views_unittests")
+
+ def TestLayoutChunk(self, chunk_num, chunk_size):
+ '''Runs tests [chunk_num*chunk_size .. (chunk_num+1)*chunk_size).
+
+ Wrap around to beginning of list at end. If chunk_size is zero, run all
+ tests in the list once. If a text file is given as argument, it is used as
+ the list of tests.
+ '''
+ # Build the ginormous commandline in 'cmd'.
+ # It's going to be roughly
+ # python heapcheck_test.py ... python run_webkit_tests.py ...
+ # but we'll use the --indirect flag to heapcheck_test.py
+ # to avoid heapchecking python.
+ # Start by building the heapcheck_test.py commandline.
+ cmd = self._DefaultCommand("webkit")
+
+ # Now build script_cmd, the run_webkits_tests.py commandline
+ # Store each chunk in its own directory so that we can find the data later
+ chunk_dir = os.path.join("layout", "chunk_%05d" % chunk_num)
+ out_dir = os.path.join(path_utils.ScriptDir(), "latest")
+ out_dir = os.path.join(out_dir, chunk_dir)
+ if os.path.exists(out_dir):
+ old_files = glob.glob(os.path.join(out_dir, "*.txt"))
+ for f in old_files:
+ os.remove(f)
+ else:
+ os.makedirs(out_dir)
+
+ script = os.path.join(self._source_dir, "webkit", "tools", "layout_tests",
+ "run_webkit_tests.py")
+ script_cmd = ["python", script, "--run-singly", "-v",
+ "--noshow-results", "--time-out-ms=200000",
+ "--nocheck-sys-deps"]
+
+ # Pass build mode to run_webkit_tests.py. We aren't passed it directly,
+ # so parse it out of build_dir. run_webkit_tests.py can only handle
+ # the two values "Release" and "Debug".
+ # TODO(Hercules): unify how all our scripts pass around build mode
+ # (--mode / --target / --build_dir / --debug)
+ if self._options.build_dir.endswith("Debug"):
+ script_cmd.append("--debug");
+ if (chunk_size > 0):
+ script_cmd.append("--run-chunk=%d:%d" % (chunk_num, chunk_size))
+ if len(self._args):
+ # if the arg is a txt file, then treat it as a list of tests
+ if os.path.isfile(self._args[0]) and self._args[0][-4:] == ".txt":
+ script_cmd.append("--test-list=%s" % self._args[0])
+ else:
+ script_cmd.extend(self._args)
+ self._ReadGtestFilterFile("layout", script_cmd)
+
+ # Now run script_cmd with the wrapper in cmd
+ cmd.extend(["--"])
+ cmd.extend(script_cmd)
+ supp = self.Suppressions()
+ return heapcheck_test.RunTool(cmd, supp, "layout")
+
+ def TestLayout(self):
+ '''Runs the layout tests.'''
+ # A "chunk file" is maintained in the local directory so that each test
+ # runs a slice of the layout tests of size chunk_size that increments with
+ # each run. Since tests can be added and removed from the layout tests at
+ # any time, this is not going to give exact coverage, but it will allow us
+ # to continuously run small slices of the layout tests under purify rather
+ # than having to run all of them in one shot.
+ chunk_size = self._options.num_tests
+ if (chunk_size == 0):
+ return self.TestLayoutChunk(0, 0)
+ chunk_num = 0
+ chunk_file = os.path.join("heapcheck_layout_chunk.txt")
+
+ logging.info("Reading state from " + chunk_file)
+ try:
+ f = open(chunk_file)
+ if f:
+ str = f.read()
+ if len(str):
+ chunk_num = int(str)
+ # This should be enough so that we have a couple of complete runs
+ # of test data stored in the archive (although note that when we loop
+ # that we almost guaranteed won't be at the end of the test list)
+ if chunk_num > 10000:
+ chunk_num = 0
+ f.close()
+ except IOError, (errno, strerror):
+ logging.error("error reading from file %s (%d, %s)" % (chunk_file,
+ errno, strerror))
+ ret = self.TestLayoutChunk(chunk_num, chunk_size)
+
+ # Wait until after the test runs to completion to write out the new chunk
+ # number. This way, if the bot is killed, we'll start running again from
+ # the current chunk rather than skipping it.
+ logging.info("Saving state to " + chunk_file)
+ try:
+ f = open(chunk_file, "w")
+ chunk_num += 1
+ f.write("%d" % chunk_num)
+ f.close()
+ except IOError, (errno, strerror):
+ logging.error("error writing to file %s (%d, %s)" % (chunk_file, errno,
+ strerror))
+
+ # Since we're running small chunks of the layout tests, it's important to
+ # mark the ones that have errors in them. These won't be visible in the
+ # summary list for long, but will be useful for someone reviewing this bot.
+ return ret
+
+
+def main():
+ if not sys.platform.startswith('linux'):
+ logging.error("Heap checking works only on Linux at the moment.")
+ return 1
+ parser = optparse.OptionParser("usage: %prog -b <dir> -t <test> "
+ "[-t <test> ...]")
+ parser.disable_interspersed_args()
+ parser.add_option("-b", "--build_dir",
+ help="the location of the output of the compiler output")
+ parser.add_option("-t", "--test", action="append",
+ help="which test to run")
+ parser.add_option("", "--gtest_filter",
+ help="additional arguments to --gtest_filter")
+ parser.add_option("", "--gtest_repeat",
+ help="argument for --gtest_repeat")
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="verbose output - enable debug log messages")
+ # My machine can do about 120 layout tests/hour in release mode.
+ # Let's do 30 minutes worth per run.
+ # The CPU is mostly idle, so perhaps we can raise this when
+ # we figure out how to run them more efficiently.
+ parser.add_option("-n", "--num_tests", default=60, type="int",
+ help="for layout tests: # of subtests per run. 0 for all.")
+
+ options, args = parser.parse_args()
+
+ if options.verbose:
+ logging_utils.config_root(logging.DEBUG)
+ else:
+ logging_utils.config_root()
+
+ if not options.test or not len(options.test):
+ parser.error("--test not specified")
+
+ for t in options.test:
+ tests = ChromeTests(options, args, t)
+ ret = tests.Run()
+ if ret:
+ return ret
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/heapcheck/chrome_tests.sh b/chromium/tools/heapcheck/chrome_tests.sh
new file mode 100755
index 00000000000..3b31f393437
--- /dev/null
+++ b/chromium/tools/heapcheck/chrome_tests.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+THISDIR=$(dirname "${0}")
+PYTHONPATH="${THISDIR}/../valgrind:${THISDIR}/../python/google" exec "${THISDIR}/chrome_tests.py" "${@}"
diff --git a/chromium/tools/heapcheck/content_unittests.gtest-heapcheck.txt b/chromium/tools/heapcheck/content_unittests.gtest-heapcheck.txt
new file mode 100644
index 00000000000..4e50d30bbb7
--- /dev/null
+++ b/chromium/tools/heapcheck/content_unittests.gtest-heapcheck.txt
@@ -0,0 +1 @@
+WebRTCAudioDeviceTest.*
diff --git a/chromium/tools/heapcheck/gpu_unittests.gtest-heapcheck.txt b/chromium/tools/heapcheck/gpu_unittests.gtest-heapcheck.txt
new file mode 100644
index 00000000000..a66a64e269f
--- /dev/null
+++ b/chromium/tools/heapcheck/gpu_unittests.gtest-heapcheck.txt
@@ -0,0 +1,2 @@
+# These tests silently crash, see http://crbug.com/259393
+GLES2Decoder*
diff --git a/chromium/tools/heapcheck/heapcheck_std.sh b/chromium/tools/heapcheck/heapcheck_std.sh
new file mode 100755
index 00000000000..b5ec947974f
--- /dev/null
+++ b/chromium/tools/heapcheck/heapcheck_std.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+exec "${@}" 2>heapcheck.log
diff --git a/chromium/tools/heapcheck/heapcheck_test.py b/chromium/tools/heapcheck/heapcheck_test.py
new file mode 100644
index 00000000000..6987624146c
--- /dev/null
+++ b/chromium/tools/heapcheck/heapcheck_test.py
@@ -0,0 +1,250 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Wrapper for running the test under heapchecker and analyzing the output."""
+
+import datetime
+import logging
+import os
+import re
+
+import common
+import path_utils
+import suppressions
+
+
+class HeapcheckWrapper(object):
+ TMP_FILE = 'heapcheck.log'
+ SANITY_TEST_SUPPRESSION = "Heapcheck sanity test"
+ LEAK_REPORT_RE = re.compile(
+ 'Leak of ([0-9]*) bytes in ([0-9]*) objects allocated from:')
+ # Workaround for http://crbug.com/132867, see below.
+ HOOKED_ALLOCATOR_RE = re.compile(
+ 'Hooked allocator frame not found, returning empty trace')
+ STACK_LINE_RE = re.compile('\s*@\s*(?:0x)?[0-9a-fA-F]+\s*([^\n]*)')
+ BORING_CALLERS = common.BoringCallers(mangled=False, use_re_wildcards=True)
+
+ def __init__(self, supp_files):
+ self._mode = 'strict'
+ self._timeout = 3600
+ self._nocleanup_on_exit = False
+ self._suppressions = []
+ for fname in supp_files:
+ self._suppressions.extend(suppressions.ReadSuppressionsFromFile(fname))
+ if os.path.exists(self.TMP_FILE):
+ os.remove(self.TMP_FILE)
+
+ def PutEnvAndLog(self, env_name, env_value):
+ """Sets the env var |env_name| to |env_value| and writes to logging.info.
+ """
+ os.putenv(env_name, env_value)
+ logging.info('export %s=%s', env_name, env_value)
+
+ def Execute(self):
+ """Executes the app to be tested."""
+ logging.info('starting execution...')
+ proc = ['sh', path_utils.ScriptDir() + '/heapcheck_std.sh']
+ proc += self._args
+ self.PutEnvAndLog('G_SLICE', 'always-malloc')
+ self.PutEnvAndLog('NSS_DISABLE_ARENA_FREE_LIST', '1')
+ self.PutEnvAndLog('NSS_DISABLE_UNLOAD', '1')
+ self.PutEnvAndLog('GTEST_DEATH_TEST_USE_FORK', '1')
+ self.PutEnvAndLog('HEAPCHECK', self._mode)
+ self.PutEnvAndLog('HEAP_CHECK_ERROR_EXIT_CODE', '0')
+ self.PutEnvAndLog('HEAP_CHECK_MAX_LEAKS', '-1')
+ self.PutEnvAndLog('KEEP_SHADOW_STACKS', '1')
+ self.PutEnvAndLog('PPROF_PATH',
+ path_utils.ScriptDir() +
+ '/../../third_party/tcmalloc/chromium/src/pprof')
+ self.PutEnvAndLog('LD_LIBRARY_PATH',
+ '/usr/lib/debug/:/usr/lib32/debug/')
+ # CHROME_DEVEL_SANDBOX causes problems with heapcheck
+ self.PutEnvAndLog('CHROME_DEVEL_SANDBOX', '');
+
+ return common.RunSubprocess(proc, self._timeout)
+
+ def Analyze(self, log_lines, check_sanity=False):
+ """Analyzes the app's output and applies suppressions to the reports.
+
+ Analyze() searches the logs for leak reports and tries to apply
+ suppressions to them. Unsuppressed reports and other log messages are
+ dumped as is.
+
+ If |check_sanity| is True, the list of suppressed reports is searched for a
+ report starting with SANITY_TEST_SUPPRESSION. If there isn't one, Analyze
+ returns 2 regardless of the unsuppressed reports.
+
+ Args:
+ log_lines: An iterator over the app's log lines.
+ check_sanity: A flag that determines whether we should check the tool's
+ sanity.
+ Returns:
+ 2, if the sanity check fails,
+ 1, if unsuppressed reports remain in the output and the sanity check
+ passes,
+ 0, if all the errors are suppressed and the sanity check passes.
+ """
+ return_code = 0
+ # leak signature: [number of bytes, number of objects]
+ cur_leak_signature = None
+ cur_stack = []
+ cur_report = []
+ reported_hashes = {}
+ # Statistics grouped by suppression description:
+ # [hit count, bytes, objects].
+ used_suppressions = {}
+ hooked_allocator_line_encountered = False
+ for line in log_lines:
+ line = line.rstrip() # remove the trailing \n
+ match = self.STACK_LINE_RE.match(line)
+ if match:
+ cur_stack.append(match.groups()[0])
+ cur_report.append(line)
+ continue
+ else:
+ if cur_stack:
+ # Try to find the suppression that applies to the current leak stack.
+ description = ''
+ for supp in self._suppressions:
+ if supp.Match(cur_stack):
+ cur_stack = []
+ description = supp.description
+ break
+ if cur_stack:
+ if not cur_leak_signature:
+ print 'Missing leak signature for the following stack: '
+ for frame in cur_stack:
+ print ' ' + frame
+ print 'Aborting...'
+ return 3
+
+ # Drop boring callers from the stack to get less redundant info
+ # and fewer unique reports.
+ found_boring = False
+ for i in range(1, len(cur_stack)):
+ for j in self.BORING_CALLERS:
+ if re.match(j, cur_stack[i]):
+ cur_stack = cur_stack[:i]
+ cur_report = cur_report[:i]
+ found_boring = True
+ break
+ if found_boring:
+ break
+
+ error_hash = hash("".join(cur_stack)) & 0xffffffffffffffff
+ if error_hash not in reported_hashes:
+ reported_hashes[error_hash] = 1
+ # Print the report and set the return code to 1.
+ print ('Leak of %d bytes in %d objects allocated from:'
+ % tuple(cur_leak_signature))
+ print '\n'.join(cur_report)
+ return_code = 1
+ # Generate the suppression iff the stack contains more than one
+ # frame (otherwise it's likely to be broken)
+ if len(cur_stack) > 1 or found_boring:
+ print '\nSuppression (error hash=#%016X#):\n{' % (error_hash)
+ print ' <insert_a_suppression_name_here>'
+ print ' Heapcheck:Leak'
+ for frame in cur_stack:
+ print ' fun:' + frame
+ print '}\n\n'
+ else:
+ print ('This stack may be broken due to omitted frame pointers.'
+ ' It is not recommended to suppress it.\n')
+ else:
+ # Update the suppressions histogram.
+ if description in used_suppressions:
+ hits, bytes, objects = used_suppressions[description]
+ hits += 1
+ bytes += cur_leak_signature[0]
+ objects += cur_leak_signature[1]
+ used_suppressions[description] = [hits, bytes, objects]
+ else:
+ used_suppressions[description] = [1] + cur_leak_signature
+ cur_stack = []
+ cur_report = []
+ cur_leak_signature = None
+ match = self.LEAK_REPORT_RE.match(line)
+ if match:
+ cur_leak_signature = map(int, match.groups())
+ else:
+ match = self.HOOKED_ALLOCATOR_RE.match(line)
+ if match:
+ hooked_allocator_line_encountered = True
+ else:
+ print line
+ # Print the list of suppressions used.
+ is_sane = False
+ if used_suppressions:
+ print
+ print '-----------------------------------------------------'
+ print 'Suppressions used:'
+ print ' count bytes objects name'
+ histo = {}
+ for description in used_suppressions:
+ if description.startswith(HeapcheckWrapper.SANITY_TEST_SUPPRESSION):
+ is_sane = True
+ hits, bytes, objects = used_suppressions[description]
+ line = '%8d %8d %8d %s' % (hits, bytes, objects, description)
+ if hits in histo:
+ histo[hits].append(line)
+ else:
+ histo[hits] = [line]
+ keys = histo.keys()
+ keys.sort()
+ for count in keys:
+ for line in histo[count]:
+ print line
+ print '-----------------------------------------------------'
+ if hooked_allocator_line_encountered:
+ print ('WARNING: Workaround for http://crbug.com/132867 (tons of '
+ '"Hooked allocator frame not found, returning empty trace") '
+ 'in effect.')
+ if check_sanity and not is_sane:
+ logging.error("Sanity check failed")
+ return 2
+ else:
+ return return_code
+
+ def RunTestsAndAnalyze(self, check_sanity):
+ exec_retcode = self.Execute()
+ log_file = file(self.TMP_FILE, 'r')
+ analyze_retcode = self.Analyze(log_file, check_sanity)
+ log_file.close()
+
+ if analyze_retcode:
+ logging.error("Analyze failed.")
+ return analyze_retcode
+
+ if exec_retcode:
+ logging.error("Test execution failed.")
+ return exec_retcode
+ else:
+ logging.info("Test execution completed successfully.")
+
+ return 0
+
+ def Main(self, args, check_sanity=False):
+ self._args = args
+ start = datetime.datetime.now()
+ retcode = -1
+ retcode = self.RunTestsAndAnalyze(check_sanity)
+ end = datetime.datetime.now()
+ seconds = (end - start).seconds
+ hours = seconds / 3600
+ seconds %= 3600
+ minutes = seconds / 60
+ seconds %= 60
+ logging.info('elapsed time: %02d:%02d:%02d', hours, minutes, seconds)
+ logging.info('For more information on the Heapcheck bot see '
+ 'http://dev.chromium.org/developers/how-tos/'
+ 'using-the-heap-leak-checker')
+ return retcode
+
+
+def RunTool(args, supp_files, module):
+ tool = HeapcheckWrapper(supp_files)
+ MODULES_TO_SANITY_CHECK = ["base"]
+ check_sanity = module in MODULES_TO_SANITY_CHECK
+ return tool.Main(args[1:], check_sanity)
diff --git a/chromium/tools/heapcheck/ipc_tests.gtest-heapcheck.txt b/chromium/tools/heapcheck/ipc_tests.gtest-heapcheck.txt
new file mode 100644
index 00000000000..8c0bd54165b
--- /dev/null
+++ b/chromium/tools/heapcheck/ipc_tests.gtest-heapcheck.txt
@@ -0,0 +1,4 @@
+# Failing after Lucid migration. http://crbug.com/82715
+IPCChannelPosixTest.AdvancedConnected
+IPCChannelPosixTest.MultiConnection
+IPCChannelPosixTest.ResetState
diff --git a/chromium/tools/heapcheck/net_unittests.gtest-heapcheck.txt b/chromium/tools/heapcheck/net_unittests.gtest-heapcheck.txt
new file mode 100644
index 00000000000..79b53589bf8
--- /dev/null
+++ b/chromium/tools/heapcheck/net_unittests.gtest-heapcheck.txt
@@ -0,0 +1,30 @@
+# http://crbug.com/31129 -- forking Python servers may break heapchecker's
+# symbolization.
+URLRequestTestHTTP.*
+# Exclude tests that simulate a crash: they leak a lot of stuff.
+# Note that *InvalidEntry* is too general.
+DiskCacheBackendTest.AppCacheInvalidEntry
+DiskCacheBackendTest.AppCacheInvalidEntryRead
+DiskCacheBackendTest.AppCacheInvalidEntryWithLoad
+DiskCacheBackendTest.InvalidEntry
+DiskCacheBackendTest.InvalidEntryEnumeration
+DiskCacheBackendTest.InvalidEntryRead
+DiskCacheBackendTest.InvalidEntryWithLoad
+DiskCacheBackendTest.TrimInvalidEntry
+DiskCacheBackendTest.TrimInvalidEntry2
+DiskCacheBackendTest.NewEvictionInvalidEntry
+DiskCacheBackendTest.NewEvictionInvalidEntryEnumeration
+DiskCacheBackendTest.NewEvictionInvalidEntryRead
+DiskCacheBackendTest.NewEvictionInvalidEntryWithLoad
+DiskCacheBackendTest.NewEvictionTrimInvalidEntry
+DiskCacheBackendTest.NewEvictionTrimInvalidEntry2
+DiskCacheBackendTest.ShaderCacheInvalidEntry
+DiskCacheBackendTest.ShaderCacheInvalidEntryRead
+DiskCacheBackendTest.ShaderCacheInvalidEntryWithLoad
+DiskCacheBackendTest.ShutdownWithPendingCreate_Fast
+DiskCacheBackendTest.ShutdownWithPendingFileIO_Fast
+DiskCacheBackendTest.ShutdownWithPendingIO_Fast
+
+# http://crbug.com/61908 - It's too slow
+DirectoryListerTest.BigDirRecursiveTest
+
diff --git a/chromium/tools/heapcheck/suppressions.py b/chromium/tools/heapcheck/suppressions.py
new file mode 100755
index 00000000000..506caa670f8
--- /dev/null
+++ b/chromium/tools/heapcheck/suppressions.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Valgrind-style suppressions for heapchecker reports.
+
+Suppressions are defined as follows:
+
+# optional one-line comments anywhere in the suppressions file.
+{
+ Toolname:Errortype
+ Short description of the error.
+ fun:function_name
+ fun:wildcarded_fun*_name
+ # an ellipsis wildcards zero or more functions in a stack.
+ ...
+ fun:some_other_function_name
+}
+
+Note that only a 'fun:' prefix is allowed, i.e. we can't suppress objects and
+source files.
+
+If ran from the command line, suppressions.py does a self-test of the
+Suppression class.
+"""
+
+import re
+
+ELLIPSIS = '...'
+
+
+class Suppression(object):
+ """This class represents a single stack trace suppression.
+
+ Attributes:
+ type: A string representing the error type, e.g. Heapcheck:Leak.
+ description: A string representing the error description.
+ """
+
+ def __init__(self, kind, description, stack):
+ """Inits Suppression.
+
+ stack is a list of function names and/or wildcards.
+
+ Args:
+ kind:
+ description: Same as class attributes.
+ stack: A list of strings.
+ """
+ self.type = kind
+ self.description = description
+ self._stack = stack
+ re_line = ''
+ re_bucket = ''
+ for line in stack:
+ if line == ELLIPSIS:
+ re_line += re.escape(re_bucket)
+ re_bucket = ''
+ re_line += '(.*\n)*'
+ else:
+ for char in line:
+ if char == '*':
+ re_line += re.escape(re_bucket)
+ re_bucket = ''
+ re_line += '.*'
+ else: # there can't be any '\*'s in a stack trace
+ re_bucket += char
+ re_line += re.escape(re_bucket)
+ re_bucket = ''
+ re_line += '\n'
+ self._re = re.compile(re_line, re.MULTILINE)
+
+ def Match(self, report):
+ """Returns bool indicating whether the suppression matches the given report.
+
+ Args:
+ report: list of strings (function names).
+ Returns:
+ True if the suppression is not empty and matches the report.
+ """
+ if not self._stack:
+ return False
+ if self._re.match('\n'.join(report) + '\n'):
+ return True
+ else:
+ return False
+
+
+class SuppressionError(Exception):
+ def __init__(self, filename, line, report=''):
+ Exception.__init__(self, filename, line, report)
+ self._file = filename
+ self._line = line
+ self._report = report
+
+ def __str__(self):
+ return 'Error reading suppressions from "%s" (line %d): %s.' % (
+ self._file, self._line, self._report)
+
+
+def ReadSuppressionsFromFile(filename):
+ """Given a file, returns a list of suppressions."""
+ input_file = file(filename, 'r')
+ result = []
+ cur_descr = ''
+ cur_type = ''
+ cur_stack = []
+ nline = 0
+ try:
+ for line in input_file:
+ nline += 1
+ line = line.strip()
+ if line.startswith('#'):
+ continue
+ elif line.startswith('{'):
+ pass
+ elif line.startswith('}'):
+ result.append(Suppression(cur_type, cur_descr, cur_stack))
+ cur_descr = ''
+ cur_type = ''
+ cur_stack = []
+ elif not cur_descr:
+ cur_descr = line
+ continue
+ elif not cur_type:
+ cur_type = line
+ continue
+ elif line.startswith('fun:'):
+ line = line[4:]
+ cur_stack.append(line.strip())
+ elif line.startswith(ELLIPSIS):
+ cur_stack.append(ELLIPSIS)
+ else:
+ raise SuppressionError(filename, nline,
+ '"fun:function_name" or "..." expected')
+ except SuppressionError:
+ input_file.close()
+ raise
+ return result
+
+
+def MatchTest():
+ """Tests the Suppression.Match() capabilities."""
+
+ def GenSupp(*lines):
+ return Suppression('', '', list(lines))
+ empty = GenSupp()
+ assert not empty.Match([])
+ assert not empty.Match(['foo', 'bar'])
+ asterisk = GenSupp('*bar')
+ assert asterisk.Match(['foobar', 'foobaz'])
+ assert not asterisk.Match(['foobaz', 'foobar'])
+ ellipsis = GenSupp('...', 'foo')
+ assert ellipsis.Match(['foo', 'bar'])
+ assert ellipsis.Match(['bar', 'baz', 'foo'])
+ assert not ellipsis.Match(['bar', 'baz', 'bah'])
+ mixed = GenSupp('...', 'foo*', 'function')
+ assert mixed.Match(['foobar', 'foobaz', 'function'])
+ assert not mixed.Match(['foobar', 'blah', 'function'])
+ at_and_dollar = GenSupp('foo@GLIBC', 'bar@NOCANCEL')
+ assert at_and_dollar.Match(['foo@GLIBC', 'bar@NOCANCEL'])
+ re_chars = GenSupp('.*')
+ assert re_chars.Match(['.foobar'])
+ assert not re_chars.Match(['foobar'])
+ print 'PASS'
+
+
+if __name__ == '__main__':
+ MatchTest()
diff --git a/chromium/tools/heapcheck/suppressions.txt b/chromium/tools/heapcheck/suppressions.txt
new file mode 100644
index 00000000000..6df68fba8eb
--- /dev/null
+++ b/chromium/tools/heapcheck/suppressions.txt
@@ -0,0 +1,854 @@
+# There are three kinds of suppressions in this file.
+# 1. third party stuff we have no control over
+#
+# 2. intentional unit test errors, or stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing
+#
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system (but a few aren't yet).
+# Periodically we should sweep this file and the bug tracker clean by
+# running overnight and removing outdated bugs/suppressions.
+#-----------------------------------------------------------------------
+
+# 1. third party stuff we have no control over
+{
+ bug_39050_a
+ Heapcheck:Leak
+ fun:FcPatternObjectAddWithBinding
+}
+{
+ bug_39050_b
+ Heapcheck:Leak
+ fun:FcPatternObjectInsertElt
+}
+{
+ bug_39050_c
+ Heapcheck:Leak
+ fun:FcConfigValues
+}
+{
+ bug_39050_d
+ Heapcheck:Leak
+ fun:IA__FcLangSetCreate
+}
+{
+ bug_39050_d2
+ Heapcheck:Leak
+ fun:FcLangSetCreate
+}
+{
+ bug_39050_e
+ Heapcheck:Leak
+ fun:IA__FcStrCopy
+}
+{
+ bug_39050_e2
+ Heapcheck:Leak
+ fun:FcStrCopy
+}
+{
+ bug_39050_f
+ Heapcheck:Leak
+ fun:FcValueSave
+}
+{
+ bug_39050_g
+ Heapcheck:Leak
+ fun:FcPatternHash
+}
+{
+ bug_39050_h
+ Heapcheck:Leak
+ fun:FcConfigFilename
+}
+{
+ bug_39050_i
+ Heapcheck:Leak
+ fun:FcCharSetFindLeafCreate
+}
+{
+ bug_39050_j
+ Heapcheck:Leak
+ fun:FcCharSetPutLeaf
+}
+{
+ bug_39050_k
+ Heapcheck:Leak
+ fun:IA__FcCharSetCreate
+}
+{
+ bug_186086 (Skia -- global singleton instance of SkFontConfigDirect)
+ Heapcheck:Leak
+ ...
+ fun:SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect
+ fun:SkFontConfigInterface::GetSingletonDirectInterface
+}
+{
+ bug_51988_a
+ Heapcheck:Leak
+ ...
+ fun:*nsPKCS12Blob_ImportHelper
+ fun:mozilla_security_manager::nsPKCS12Blob_Import
+ fun:net::NSSCertDatabase::ImportFromPKCS12
+}
+{
+ bug_51988_b
+ Heapcheck:Leak
+ ...
+ fun:mozilla_security_manager::nsPKCS12Blob_Export
+ fun:net::NSSCertDatabase::ExportToPKCS12
+}
+{
+ bug_51988_c
+ Heapcheck:Leak
+ ...
+ fun:crypto::Open*NSSDB
+}
+{
+ bug_51988_d
+ Heapcheck:Leak
+ ...
+ fun:*New
+ ...
+ fun:crypto::EnsureNSSInit
+}
+{
+ bug_51988_e
+ Heapcheck:Leak
+ ...
+ fun:net::CertDatabaseNSSTest_*_Test::TestBody
+}
+{
+ bug_51988_f
+ Heapcheck:Leak
+ ...
+ fun:net::CertDatabaseNSSTest::TearDown
+}
+{
+ bug_51988_g
+ Heapcheck:Leak
+ fun:sqlite3MemMalloc
+ ...
+ fun:net::CertDatabaseNSSTest::SetUp
+}
+{
+ bug_51988_h
+ Heapcheck:Leak
+ fun:sqlite3MemMalloc
+ ...
+ fun:chromeos::onc::CertificateImporter::ParseServerOrCaCertificate
+}
+{
+ bug_51988_i
+ Heapcheck:Leak
+ fun:sqlite3MemMalloc
+ fun:net::X509Certificate::GetDefaultNickname
+}
+{
+ bug_51988_j
+ Heapcheck:Leak
+ fun:sqlite3MemMalloc
+ fun:chromeos::*::ListCertsInSlot
+}
+{
+ bug_119677
+ Heapcheck:Leak
+ ...
+ fun:DisplayChangeObserverX11
+ fun:aura::Env::Init
+ fun:aura::Env::GetInstance
+}
+{
+ bug_146464_a
+ Heapcheck:Leak
+ fun:get_peer_sock_name
+ fun:base::MessagePumpAuraX11::GetDefaultXDisplay
+}
+{
+ bug_146464_b
+ Heapcheck:Leak
+ fun:add_codeset.isra.10
+ ...
+ fun:RootWindowHostX11
+ fun:aura::RootWindowHost::Create
+}
+{
+ bug_146464_c
+ Heapcheck:Leak
+ ...
+ fun:RootWindowHostX11
+ fun:aura::RootWindowHost::Create
+}
+
+# When NSS 3.15 is the minimum version required, this should be removed.
+{
+ bug_272673
+ Heapcheck:Leak
+ fun:*
+ fun:*OpenUserDB
+ fun:*OpenTestNSSDB
+ fun:*ScopedTestNSSDB
+}
+
+# Probably a leak in GTK.
+{
+ bug_175744
+ Heapcheck:Leak
+ ...
+ fun:GtkThemeService::GtkThemeService
+ fun:ThemeServiceFactory::BuildServiceInstanceFor
+ fun:BrowserContextKeyedServiceFactory::GetServiceForBrowserContext
+ fun:*
+ fun:BrowserContextDependencyManager::CreateBrowserContextServices
+ fun:TestingProfile::Init
+ fun:TestingProfile::TestingProfile
+}
+
+
+#-----------------------------------------------------------------------
+# 2. intentional unit test errors, or stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing
+{
+ Heapcheck sanity test (ToolsSanityTest.MemoryLeak).
+ Heapcheck:Leak
+ fun:base::ToolsSanityTest_MemoryLeak_Test::TestBody
+}
+{
+ FileStream::Context can leak through WorkerPool by design (Linux)
+ Heapcheck:Leak
+ fun:net::FileStream::FileStream
+}
+{
+ FileStream::Context can leak through WorkerPool by design (CrOS)
+ Heapcheck:Leak
+ fun:FileStream
+}
+{
+ Tasks posted to WorkerPool can leak by design
+ Heapcheck:Leak
+ fun:base::internal::PostTaskAndReplyImpl::PostTaskAndReply
+ fun:base::WorkerPool::PostTaskAndReply
+}
+# This one pops out too often on different leaks and the stacks are very often
+# uninformative, e.g. don't include anything related to the bug.
+# TODO(earthdok): revisit what we want to do with _Rep when we have LSan.
+{
+ basic_string::_Rep::_S_create
+ Heapcheck:Leak
+ fun:std::basic_string::_Rep::_S_create
+ fun:std::basic_string::basic_string
+}
+
+#-----------------------------------------------------------------------
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system (but a few aren't yet).
+# Periodically we should sweep this file and the bug tracker clean by
+# running overnight and removing outdated bugs/suppressions.
+{
+ bug_34994_a
+ Heapcheck:Leak
+ ...
+ fun:*Invoke
+ fun:v8::internal::Execution::Call
+ fun:v8::Script::Run
+}
+{
+ bug_34994_b
+ Heapcheck:Leak
+ ...
+ fun:*Invoke
+ fun:v8::internal::Execution::Call
+ fun:v8::Function::Call
+}
+{
+ bug_49300_a
+ Heapcheck:Leak
+ fun:disk_cache::StorageBlock::AllocateData
+ fun:disk_cache::StorageBlock::Data
+}
+{
+ bug_49300_b
+ Heapcheck:Leak
+ ...
+ fun:disk_cache::BackendImpl::CreateEntryImpl
+ fun:disk_cache::BackendImpl::SyncCreateEntry
+ fun:disk_cache::BackendIO::ExecuteBackendOperation
+}
+{
+ bug_49300_c
+ Heapcheck:Leak
+ ...
+ fun:disk_cache::BackendImpl::NewEntry
+ fun:disk_cache::BackendImpl::MatchEntry
+}
+{
+ bug_65940_a
+ Heapcheck:Leak
+ ...
+ fun:IPC::SyncChannel::SyncChannel
+ fun:ChildThread::Init
+ fun:ChildThread::ChildThread
+ fun:RenderThreadImpl::RenderThreadImpl
+}
+{
+ bug_65940_b
+ Heapcheck:Leak
+ fun:__gnu_cxx::new_allocator::allocate
+ fun:std::_Vector_base::_M_allocate
+ fun:std::vector::_M_insert_aux
+ fun:std::vector::push_back
+ fun:IPC::ChannelProxy::Context::OnAddFilter
+}
+{
+ bug_67378_a
+ Heapcheck:Leak
+ ...
+ fun:*SetPacScriptFromDisk
+}
+{
+ bug_67378_b
+ Heapcheck:Leak
+ ...
+ fun:*LoadScriptData
+}
+{
+ bug_67378_c
+ Heapcheck:Leak
+ fun:*ASCIILiteralToV8String
+ fun:net::ProxyResolverV8::Context::InitV8
+ fun:net::ProxyResolverV8::SetPacScript
+}
+{
+ bug_67378_d
+ Heapcheck:Leak
+ fun:*ScriptDataToV8String
+ fun:net::ProxyResolverV8::Context::InitV8
+ fun:net::ProxyResolverV8::SetPacScript
+}
+{
+ bug_82974a
+ Heapcheck:Leak
+ ...
+ fun:net::X509Certificate::CreateOSCertHandleFromBytes*
+}
+{
+ bug_82974b
+ Heapcheck:Leak
+ ...
+ fun:*PKIXVerifyCert
+}
+{
+ bug_82974c
+ Heapcheck:Leak
+ fun:sqlite3MemMalloc
+ fun:net::*::ListCertsInSlot
+ ...
+ fun:net::CertDatabaseNSSTest::TearDown
+}
+{
+ bug_82974d
+ Heapcheck:Leak
+ fun:sqlite3MemMalloc
+ fun:net::NSSCertDatabase::ListCerts
+}
+{
+ bug_82974e
+ Heapcheck:Leak
+ ...
+ fun:net::NSSCertDatabase::DeleteCertAndKey
+ fun:*::CleanupSlotContents
+}
+{
+ bug_82974f
+ Heapcheck:Leak
+ ...
+ fun:net::NSSCertDatabase::DeleteCertAndKey
+ fun:*ParseServerOrCaCertificate
+}
+{
+ bug_90013_a
+ Heapcheck:Leak
+ fun:??
+ fun:gfx::RenderTextLinux::EnsureLayout
+}
+{
+ bug_90013_b
+ Heapcheck:Leak
+ fun:??
+ fun:gfx::RenderTextLinux::GetStringSize
+}
+{
+ bug_90013_c
+ Heapcheck:Leak
+ fun:??
+ fun:*FindBestMatchFontFamilyName
+ fun:PlatformFontPango
+}
+{
+ bug_90013_d
+ Heapcheck:Leak
+ fun:??
+ fun:gfx::GetPangoFontMetrics
+ fun:gfx::PlatformFontPango::InitPangoMetrics
+}
+{
+ bug_99304
+ Heapcheck:Leak
+ fun:v8::internal::SkipList::Update
+ fun:v8::internal::PagedSpace::AllocateRaw
+ fun:v8::internal::Heap::ReserveSpace
+ fun:v8::internal::Deserializer::Deserialize
+ fun:v8::internal::Isolate::Init
+ fun:v8::internal::V8::Initialize
+ fun:v8::internal::Snapshot::Initialize
+ fun:*InitializeHelper
+}
+{
+ bug_114770
+ Heapcheck:Leak
+ ...
+ fun:TestShell::InitializeTestShell
+ fun:TestShellTestSuite::Initialize
+ fun:base::TestSuite::Run
+}
+{
+ bug_114978
+ Heapcheck:Leak
+ ...
+ fun:mozilla_security_manager::GenKeyAndSignChallenge
+ fun:net::KeygenHandler::GenKeyAndSignChallenge
+}
+{
+ bug_114986
+ Heapcheck:Leak
+ ...
+ fun:ThemeServiceFactory::BuildServiceInstanceFor
+ ...
+ fun:BrowserContextKeyedServiceFactory::GetServiceForBrowserContext
+ fun:ThemeServiceFactory::GetForProfile
+}
+{
+ bug_124758
+ Heapcheck:Leak
+ fun:sqlite3MemMalloc
+ fun:crypto::RSAPrivateKey::FindFromPublicKeyInfo
+ fun:crypto::RSAPrivateKeyNSSTest_*_Test::TestBody
+}
+{
+ bug_132431
+ Heapcheck:Leak
+ ...
+ fun:*LoadDefaults
+ fun:gfx::GetDefaultWebKitFontRenderParams
+ ...
+ fun:*TestBody
+}
+{
+ bug_145703
+ Heapcheck:Leak
+ ...
+ fun:content::SiteInstanceImpl::GetProcess
+ fun:RenderViewHostImpl
+ fun:content::RenderViewHostFactory::Create
+ fun:content::RenderViewHostManager::Init
+ fun:content::WebContentsImpl::Init
+ fun:content::TestWebContents::Create
+ fun:content::WebContentsTester::CreateTestWebContents
+}
+{
+ bug_145705
+ Heapcheck:Leak
+ ...
+ fun:extensions::SettingsFrontend::Create
+ fun:ExtensionService::ExtensionService
+ fun:extensions::TestExtensionSystem::CreateExtensionService
+ fun:extensions::::TestExtensionEnvironment::GetExtensionService
+ fun:extensions::::TestExtensionEnvironment::MakeExtension
+ fun:extensions::::DeclarativeContentActionTest_ShowPageAction_Test::TestBody
+}
+{
+ bug_150648
+ Heapcheck:Leak
+ fun:WTF::fastMalloc
+ fun:WTF::StringImpl::createUninitialized
+ fun:WTF::StringImpl::create
+ fun:WebKit::WebString::assign
+ fun:*WebString*
+ fun:webkit_glue::CppBoundClass::BindToJavascript
+ fun:*didClearWindowObject
+ fun:WebKit::FrameLoaderClientImpl::dispatchDidClearWindowObjectInWorld
+ fun:WebCore::FrameLoader::dispatchDidClearWindowObjectInWorld
+}
+{
+ bug_157885
+ Heapcheck:Leak
+ ...
+ fun:content::DOMStorageContextImpl::CreateSessionNamespace
+}
+{
+ bug_159191
+ Heapcheck:Leak
+ ...
+ fun:SkFontHost::CreateTypeface
+ fun:SkTypeface::GetDefaultTypeface
+ fun:SkScalerContext::MakeRec
+ fun:SkPaint::descriptorProc
+ fun:SkPaint::detachCache
+ fun:SkAutoGlyphCache::SkAutoGlyphCache
+ fun:SkDraw::drawText
+ fun:SkDevice::drawText
+ fun:SkCanvas::drawText
+ fun:media::FakeVideoCaptureDevice::OnCaptureTask
+}
+# Need to figure out if the bug_159551 leaks are intentional or not.
+{
+ bug_159551_message_loop
+ Heapcheck:Leak
+ fun:MessageLoop
+ ...
+ fun:testing::internal::TestFactoryImpl::CreateTest
+}
+{
+ bug_159551_bind_cros
+ Heapcheck:Leak
+ fun:base::Bind
+ fun:net::FileStream::Context::CloseAndDelete
+ fun:net::FileStream::Context::Orphan
+ fun:~FileStream
+}
+{
+ bug_159551_bind_linux
+ Heapcheck:Leak
+ fun:base::Bind
+ fun:net::FileStream::Context::CloseAndDelete
+ fun:net::FileStream::Context::Orphan
+ fun:net::FileStream::~FileStream
+}
+{
+ bug_164185
+ Heapcheck:Leak
+ ...
+ fun:BookmarkBarGtk::GetFirstHiddenBookmark
+ fun:BookmarkBarGtk::SetChevronState
+ fun:BookmarkBarGtk::BookmarkNodeAdded
+ fun:BookmarkModel::AddNode
+ fun:BookmarkModel::AddURLWithCreationTime
+ fun:BookmarkModel::AddURL
+ fun:BookmarkBarGtkUnittest_HidesHelpMessageWithBookmark_Test::TestBody
+}
+{
+ bug_166989
+ Heapcheck:Leak
+ ...
+ fun:ui::CreateInvisibleCursor
+ ...
+ fun:ui::CursorLoader::Create
+ fun:ash::ImageCursors::SetDeviceScaleFactor
+ fun:ash::CursorManager::SetDeviceScaleFactor
+ fun:ash::Shell::Init
+}
+{
+ bug_171547_b
+ Heapcheck:Leak
+ ...
+ fun:FilterBuilder
+ fun:::LoadWhitelistsOnBlockingPoolThread
+}
+{
+ bug_171547_c
+ Heapcheck:Leak
+ ...
+ fun:FilterBuilder::Build
+ fun:::LoadWhitelistsOnBlockingPoolThread
+}
+{
+ bug_172077
+ Heapcheck:Leak
+ ...
+ fun:extensions::RegexSetMatcher::RebuildMatcher
+ fun:extensions::RegexSetMatcher::ClearPatterns
+ ...
+ fun:extensions::URLMatcher::UpdateRegexSetMatcher
+ fun:extensions::URLMatcher::UpdateInternalDatastructures
+ fun:extensions::URLMatcher::AddConditionSets
+ fun:::FilterBuilder::Build
+ fun:::LoadWhitelistsOnBlockingPoolThread
+}
+{
+ bug_173597
+ Heapcheck:Leak
+ fun:FcConfigEvaluate
+ fun:gfx::RenderTextLinux::EnsureLayout
+ fun:gfx::RenderTextTest_PangoAttributes_Test::TestBody
+}
+{
+ bug_175100
+ Heapcheck:Leak
+ ...
+ fun:*StartSync
+ ...
+ fun:OneClickSigninHelper::DidStopLoading
+ ...
+ fun:OneClickSigninHelperTest*::TestBody
+}
+{
+ bug_176888
+ Heapcheck:Leak
+ fun:__GI___strdup
+ fun:Init
+ fun:GcryptInitializer
+}
+{
+ bug_177285
+ Heapcheck:Leak
+ fun:MessageLoop
+ fun:FileSystemURLRequestJobTest
+}
+# * is for DeriveFont and InitWithNameAndSize.
+{
+ bug_189170
+ Heapcheck:Leak
+ ...
+ fun:SkFontHost::CreateTypeface
+ fun:SkTypeface::CreateFromName
+ fun:gfx::PlatformFontPango::*
+}
+{
+ bug_189194_a
+ Heapcheck:Leak
+ ...
+ fun:extensions::SettingsFrontend::Create
+ fun:ExtensionService::ExtensionService
+ fun:extensions::TestExtensionSystem::CreateExtensionService
+ fun:ProfileSigninConfirmationHelperTest::SetUp
+}
+{
+ bug_225596
+ Heapcheck:Leak
+ fun:chromeos::input_method::InputMethodManagerImpl::Init
+ fun:chromeos::input_method::Initialize
+ fun:chromeos::input_method::InputMethodConfigurationTest_TestInitialize_Test::TestBody
+}
+{
+ bug_233532
+ Heapcheck:Leak
+ ...
+ fun:GetStoragePartitionFromConfig
+ fun:content::BrowserContext::GetStoragePartition
+ fun:content::NavigationControllerImpl::GetSessionStorageNamespace
+ fun:content::RenderViewHostManager::Init
+}
+{
+ bug_236791
+ Heapcheck:Leak
+ ...
+ fun:ash::test::FocusCyclerTest_CycleFocusThroughWindowWithPanes_Test::TestBody
+}
+{
+ bug_246567a
+ Heapcheck:Leak
+ fun:v8::internal::PerThreadAssertScopeBase::AssertData
+ fun:v8::internal::PerThreadAssertScope::IsAllowed
+ fun:v8::internal::Heap::AllocateRaw
+ fun:v8::internal::Heap::Allocate
+ fun:v8::internal::Heap::AllocateForeign
+ fun:v8::internal::Heap::AllocateExternal
+ fun:v8::internal::Factory::NewExternal
+ fun:v8::External::New
+ fun:net::ProxyResolverV8::Context::InitV8
+ fun:net::ProxyResolverV8::SetPacScript
+ fun:net::ProxyResolverV8Tracing::Job::ExecuteProxyResolver
+ fun:net::ProxyResolverV8Tracing::Job::ExecuteBlocking
+}
+{
+ bug_246567b
+ Heapcheck:Leak
+ fun:v8::internal::PerThreadAssertScopeBase::AssertData
+ fun:v8::internal::PerThreadAssertScope::IsAllowed
+ fun:v8::internal::HandleScope::CreateHandle
+ fun:Handle
+ fun:MacroAssembler
+ fun:v8::internal::Deoptimizer::EnsureCodeForDeoptimizationEntry
+ fun:v8::internal::Isolate::Init
+ fun:v8::internal::V8::Initialize
+ fun:v8::internal::Snapshot::Initialize
+ fun:InitializeHelper
+ fun:v8::V8::Initialize
+ fun:v8::Locker::Initialize
+ fun:net::ProxyResolverV8::Context::InitV8
+ fun:net::ProxyResolverV8::SetPacScript
+ fun:net::ProxyResolverV8Tracing::Job::ExecuteProxyResolver
+ fun:net::ProxyResolverV8Tracing::Job::ExecuteBlocking
+}
+{
+ bug_246567c
+ Heapcheck:Leak
+ fun:v8::internal::PerThreadAssertScopeBase::AssertData
+ fun:v8::internal::PerThreadAssertScope::IsAllowed
+ fun:v8::internal::HandleScope::CreateHandle
+ fun:Handle
+}
+{
+ bug_247525
+ Heapcheck:Leak
+ ...
+ fun:appcache::AppCacheStorageImpl::Initialize
+ fun:appcache::AppCacheService::Initialize
+ fun:content::ChromeAppCacheService::InitializeOnIOThread
+}
+{
+ bug_250533
+ Heapcheck:Leak
+ ...
+ fun:net::TestURLRequestContextGetter::GetURLRequestContext
+ fun:ProxyResolvingClientSocket
+ fun:jingle_glue::XmppClientSocketFactory::CreateTransportClientSocket
+ fun:jingle_glue::ChromeAsyncSocket::Connect
+}
+{
+ bug_251034_a
+ Heapcheck:Leak
+ ...
+ fun:gfx::OSMESAApiBase::OSMesaMakeCurrentFn
+ fun:gfx::GLContextOSMesa::MakeCurrent
+ fun:gpu::gles2::GLES2DecoderImpl::MakeCurrent
+ fun:PumpCommands
+}
+{
+ bug_251034_b
+ Heapcheck:Leak
+ ...
+ fun:gpu::gles2::ShaderTranslator::Init
+ fun:gpu::gles2::ShaderTranslatorCache::GetTranslator
+ fun:gpu::gles2::GLES2DecoderImpl::InitializeShaderTranslator
+ fun:gpu::gles2::GLES2DecoderImpl::Initialize
+ fun:gpu::InProcessCommandBuffer::InitializeOnGpuThread
+}
+{
+ bug_251034_c
+ Heapcheck:Leak
+ ...
+ fun:gfx::OSMESAApiBase::OSMesaMakeCurrentFn
+ fun:gfx::GLContextOSMesa::MakeCurrent
+ fun:ScopedMakeCurrent
+ fun:gfx::GLSurfaceOSMesa::Resize
+ fun:gfx::NativeViewGLSurfaceOSMesa::Resize
+ fun:OnResizeView
+}
+{
+ bug_251034_d
+ Heapcheck:Leak
+ ...
+ fun:gfx::OSMESAApiBase::OSMesaMakeCurrentFn
+ fun:gfx::GLContextOSMesa::MakeCurrent
+ fun:~ScopedMakeCurrent
+ fun:base::DefaultDeleter::operator
+ fun:~scoped_ptr_impl
+ fun:~scoped_ptr
+ fun:gfx::GLSurfaceOSMesa::Resize
+ fun:gfx::NativeViewGLSurfaceOSMesa::Resize
+ fun:OnResizeView
+}
+{
+ bug_258113
+ Heapcheck:Leak
+ fun:ppapi::proxy::PPP_Class_Proxy::CreateProxiedObject
+ fun:ppapi::proxy::PPB_Var_Deprecated_Proxy::OnMsgCreateObjectDeprecated
+ fun:void DispatchToMethod
+ fun:IPC::SyncMessageSchema::DispatchWithSendParams
+ fun:PpapiHostMsg_PPBVar_CreateObjectDeprecated::Dispatch
+ fun:ppapi::proxy::PPB_Var_Deprecated_Proxy::OnMessageReceived
+ fun:ppapi::proxy::Dispatcher::OnMessageReceived
+ fun:ppapi::proxy::HostDispatcher::OnMessageReceived
+ fun:IPC::ChannelProxy::Context::OnDispatchMessage
+ fun:IPC::SyncChannel::ReceivedSyncMsgQueue::DispatchMessages
+ fun:IPC::SyncChannel::SyncContext::DispatchMessages
+ fun:IPC::SyncChannel::WaitForReply
+ fun:IPC::SyncChannel::SendWithTimeout
+ fun:IPC::SyncChannel::Send
+ fun:ppapi::proxy::ProxyChannel::Send
+ fun:ppapi::proxy::HostDispatcher::Send
+ fun:DidCreate
+ fun:ppapi::proxy::PPP_Instance_Private_ProxyTest_PPPInstancePrivate_Test::TestBody
+}
+{
+ bug_258132
+ Heapcheck:Leak
+ ...
+ fun:ppapi::proxy::PluginProxyMultiThreadTest::RunTest
+ fun:ppapi::ThreadAwareCallbackMultiThreadTest_RunOnTargetThread_Test::TestBody
+}
+{
+ bug_263748a
+ Heapcheck:Leak
+ ...
+ fun:DisassemblerElf32X86Test_All_Test::TestBody
+}
+{
+ bug_263748b
+ Heapcheck:Leak
+ ...
+ fun:TypedRVATest_*_Test::TestBody
+}
+{
+ bug_263748c
+ Heapcheck:Leak
+ ...
+ fun:EncodeDecodeTest_Elf_Small_Test::TestBody
+}
+{
+ bug_268258
+ Heapcheck:Leak
+ fun:WTF::fastMalloc
+ fun:WTF::StringImpl::createStatic
+ fun:WebCore::*Names::init
+}
+{
+ bug_268267
+ Heapcheck:Leak
+ fun:base::internal::WeakReferenceOwner::GetRef
+ fun:GetWeakPtr
+ fun:base::WeakPtrTest_MoveOwnershipAfterInvalidate_Test::TestBody
+}
+{
+ bug_269716a
+ Heapcheck:Leak
+ fun:PL_ArenaAllocate
+ fun:net::NSSCertDatabase::DeleteCertAndKey
+ fun:chromeos::NetworkCertMigratorTest::CleanupTestCert
+}
+{
+ bug_269716b
+ Heapcheck:Leak
+ fun:PR_NewLock
+ fun:net::NSSCertDatabase::DeleteCertAndKey
+ fun:chromeos::NetworkCertMigratorTest::CleanupTestCert
+}
+{
+ bug_269716c
+ Heapcheck:Leak
+ fun:nss_ZAlloc
+ fun:net::NSSCertDatabase::DeleteCertAndKey
+ fun:chromeos::NetworkCertMigratorTest::CleanupTestCert
+}
+{
+ bug_270312
+ Heapcheck:Leak
+ ...
+ fun:MessageCenterButtonBar
+ fun:MessageCenterView
+ fun:message_center::MessageCenterViewTest::SetUp
+}
+{
+ bug_272083
+ Heapcheck:Leak
+ fun:ThemeService::SetManagedUserTheme
+ fun:ThemeService::OnManagedUserInitialized
+}
+{
+ bug_272596
+ Heapcheck:Leak
+ fun:*
+ fun:net::NSSCertDatabase::ListCerts
+ fun:LoadNSSCertificates
+}
diff --git a/chromium/tools/heapcheck/sync_unit_tests.gtest-heapcheck.txt b/chromium/tools/heapcheck/sync_unit_tests.gtest-heapcheck.txt
new file mode 100644
index 00000000000..a8a85902e3c
--- /dev/null
+++ b/chromium/tools/heapcheck/sync_unit_tests.gtest-heapcheck.txt
@@ -0,0 +1,3 @@
+# http://crbug.com/118203
+InvalidationNotifierTest.Basic
+NonBlockingInvalidationNotifierTest.Basic
diff --git a/chromium/tools/heapcheck/unit_tests.gtest-heapcheck.txt b/chromium/tools/heapcheck/unit_tests.gtest-heapcheck.txt
new file mode 100644
index 00000000000..d8b99201e2b
--- /dev/null
+++ b/chromium/tools/heapcheck/unit_tests.gtest-heapcheck.txt
@@ -0,0 +1,38 @@
+# Disable JavaScript tests that cause V8 to install a SIGPROF handler that
+# times out the subsequent fork() calls.
+# http://crbug.com/79320
+*Json*
+
+# Failing after Lucid migration. http://crbug.com/82715
+MultiProcessLockTest.BasicCreationTest
+MultiProcessLockTest.LockScope
+MultiProcessLockTest.RecursiveLock
+MultiProcessLockTest.SimpleLock
+ServiceProcessStateTest.ForceShutdown
+ServiceProcessStateTest.ReadyState
+ServiceProcessStateTest.Singleton
+
+# http://crbug.com/88221
+ConnectionTesterTest.DeleteWhileInProgress
+
+# Fails under Heapcheck http://crbug.com/93027
+ProcessWatcherTest.ImmediateTermination
+
+# Two memory leaks with too inconcrete stacks http://crbug.com/114988
+BookmarkEditorGtkTest.ModelsMatch
+BookmarkEditorGtkTest.MoveToNewParent
+
+# Timing out all over the place. Disabling for now. http://crbug.com/149715
+ExtensionWebRequestTest.*
+
+# Crashes occasionally. http://crbug.com/165458
+BackgroundApplicationListModelTest.ExplicitTest
+
+# Timing out. Disabling for now. http://crbug.com/175496
+AppsModelBuilderTest.OnExtensionMoved
+
+# Don't run FLAKY or FAILS tests under the heapchecker.
+# They may cause flaky leak reports and timeouts.
+*FLAKY_*
+*FAILS_*
+
diff --git a/chromium/tools/idl_parser/PRESUBMIT.py b/chromium/tools/idl_parser/PRESUBMIT.py
new file mode 100644
index 00000000000..ff657aa8596
--- /dev/null
+++ b/chromium/tools/idl_parser/PRESUBMIT.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+WHITELIST = [ r'^.+_test\.py$' ]
+
+def CheckChangeOnUpload(input_api, output_api):
+ return input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, '.', whitelist=WHITELIST)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, '.', whitelist=WHITELIST)
diff --git a/chromium/tools/idl_parser/__init__.py b/chromium/tools/idl_parser/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/idl_parser/__init__.py
diff --git a/chromium/tools/idl_parser/idl_lexer.py b/chromium/tools/idl_parser/idl_lexer.py
new file mode 100755
index 00000000000..d7311df1ca6
--- /dev/null
+++ b/chromium/tools/idl_parser/idl_lexer.py
@@ -0,0 +1,285 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Lexer for PPAPI IDL
+
+The lexer uses the PLY library to build a tokenizer which understands both
+WebIDL and Pepper tokens.
+
+WebIDL, and WebIDL regular expressions can be found at:
+ http://www.w3.org/TR/2012/CR-WebIDL-20120419/
+PLY can be found at:
+ http://www.dabeaz.com/ply/
+"""
+
+import os.path
+import sys
+
+#
+# Try to load the ply module, if not, then assume it is in the third_party
+# directory.
+#
+try:
+ # Disable lint check which fails to find the ply module.
+ # pylint: disable=F0401
+ from ply import lex
+except ImportError:
+ module_path, module_name = os.path.split(__file__)
+ third_party = os.path.join(module_path, '..', '..', 'third_party')
+ sys.path.append(third_party)
+ # pylint: disable=F0401
+ from ply import lex
+
+#
+# IDL Lexer
+#
+class IDLLexer(object):
+ # 'literals' is a value expected by lex which specifies a list of valid
+ # literal tokens, meaning the token type and token value are identical.
+ literals = r'"*.(){}[],;:=+-/~|&^?<>'
+
+ # 't_ignore' contains ignored characters (spaces and tabs)
+ t_ignore = ' \t'
+
+ # 'tokens' is a value required by lex which specifies the complete list
+ # of valid token types.
+ tokens = [
+ # Data types
+ 'float',
+ 'integer',
+ 'string',
+
+ # Symbol and keywords types
+ 'COMMENT',
+ 'identifier',
+
+ # MultiChar operators
+ 'ELLIPSIS',
+ ]
+
+ # 'keywords' is a map of string to token type. All tokens matching
+ # KEYWORD_OR_SYMBOL are matched against keywords dictionary, to determine
+ # if the token is actually a keyword.
+ keywords = {
+ 'any' : 'ANY',
+ 'attribute' : 'ATTRIBUTE',
+ 'boolean' : 'BOOLEAN',
+ 'byte' : 'BYTE',
+ 'callback' : 'CALLBACK',
+ 'const' : 'CONST',
+ 'creator' : 'CREATOR',
+ 'Date' : 'DATE',
+ 'deleter' : 'DELETER',
+ 'dictionary' : 'DICTIONARY',
+ 'DOMString' : 'DOMSTRING',
+ 'double' : 'DOUBLE',
+ 'enum' : 'ENUM',
+ 'false' : 'FALSE',
+ 'float' : 'FLOAT',
+ 'exception' : 'EXCEPTION',
+ 'getter': 'GETTER',
+ 'implements' : 'IMPLEMENTS',
+ 'Infinity' : 'INFINITY',
+ 'inherit' : 'INHERIT',
+ 'interface' : 'INTERFACE',
+ 'legacycaller' : 'LEGACYCALLER',
+ 'long' : 'LONG',
+ 'Nan' : 'NAN',
+ 'null' : 'NULL',
+ 'object' : 'OBJECT',
+ 'octet' : 'OCTET',
+ 'optional' : 'OPTIONAL',
+ 'or' : 'OR',
+ 'partial' : 'PARTIAL',
+ 'readonly' : 'READONLY',
+ 'sequence' : 'SEQUENCE',
+ 'setter': 'SETTER',
+ 'short' : 'SHORT',
+ 'static' : 'STATIC',
+ 'stringifier' : 'STRINGIFIER',
+ 'typedef' : 'TYPEDEF',
+ 'true' : 'TRUE',
+ 'unsigned' : 'UNSIGNED',
+ 'unrestricted' : 'UNRESTRICTED',
+ 'void' : 'VOID'
+ }
+
+ # Token definitions
+ #
+ # Lex assumes any value or function in the form of 't_<TYPE>' represents a
+ # regular expression where a match will emit a token of type <TYPE>. In the
+ # case of a function, the function is called when a match is made. These
+ # definitions come from WebIDL.
+ #
+ # These need to be methods for lexer construction, despite not using self.
+ # pylint: disable=R0201
+ def t_ELLIPSIS(self, t):
+ r'\.\.\.'
+ return t
+
+ # Regex needs to be in the docstring
+ # pylint: disable=C0301
+ def t_float(self, t):
+ r'-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)'
+ return t
+
+ def t_integer(self, t):
+ r'-?([1-9][0-9]*|0[Xx][0-9A-Fa-f]+|0[0-7]*)'
+ return t
+
+
+ # A line ending '\n', we use this to increment the line number
+ def t_LINE_END(self, t):
+ r'\n+'
+ self.AddLines(len(t.value))
+
+ # We do not process escapes in the IDL strings. Strings are exclusively
+ # used for attributes and enums, and not used as typical 'C' constants.
+ def t_string(self, t):
+ r'"[^"]*"'
+ t.value = t.value[1:-1]
+ self.AddLines(t.value.count('\n'))
+ return t
+
+ # A C or C++ style comment: /* xxx */ or //
+ def t_COMMENT(self, t):
+ r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)'
+ self.AddLines(t.value.count('\n'))
+ return t
+
+ # A symbol or keyword.
+ def t_KEYWORD_OR_SYMBOL(self, t):
+ r'_?[A-Za-z][A-Za-z_0-9]*'
+
+ # All non-keywords are assumed to be symbols
+ t.type = self.keywords.get(t.value, 'identifier')
+
+ # We strip leading underscores so that you can specify symbols with the same
+ # value as a keywords (E.g. a dictionary named 'interface').
+ if t.value[0] == '_':
+ t.value = t.value[1:]
+ return t
+
+ def t_ANY_error(self, t):
+ msg = 'Unrecognized input'
+ line = self.Lexer().lineno
+
+ # If that line has not been accounted for, then we must have hit
+ # EoF, so compute the beginning of the line that caused the problem.
+ if line >= len(self.index):
+ # Find the offset in the line of the first word causing the issue
+ word = t.value.split()[0]
+ offs = self.lines[line - 1].find(word)
+ # Add the computed line's starting position
+ self.index.append(self.Lexer().lexpos - offs)
+ msg = 'Unexpected EoF reached after'
+
+ pos = self.Lexer().lexpos - self.index[line]
+ out = self.ErrorMessage(line, pos, msg)
+ sys.stderr.write(out + '\n')
+ self._lex_errors += 1
+
+
+ def AddLines(self, count):
+ # Set the lexer position for the beginning of the next line. In the case
+ # of multiple lines, tokens can not exist on any of the lines except the
+ # last one, so the recorded value for previous lines are unused. We still
+ # fill the array however, to make sure the line count is correct.
+ self.Lexer().lineno += count
+ for _ in range(count):
+ self.index.append(self.Lexer().lexpos)
+
+ def FileLineMsg(self, line, msg):
+ # Generate a message containing the file and line number of a token.
+ filename = self.Lexer().filename
+ if filename:
+ return "%s(%d) : %s" % (filename, line + 1, msg)
+ return "<BuiltIn> : %s" % msg
+
+ def SourceLine(self, line, pos):
+ # Create a source line marker
+ caret = ' ' * pos + '^'
+ # We decrement the line number since the array is 0 based while the
+ # line numbers are 1 based.
+ return "%s\n%s" % (self.lines[line - 1], caret)
+
+ def ErrorMessage(self, line, pos, msg):
+ return "\n%s\n%s" % (
+ self.FileLineMsg(line, msg),
+ self.SourceLine(line, pos))
+
+#
+# Tokenizer
+#
+# The token function returns the next token provided by IDLLexer for matching
+# against the leaf paterns.
+#
+ def token(self):
+ tok = self.Lexer().token()
+ if tok:
+ self.last = tok
+ return tok
+
+
+ def GetTokens(self):
+ outlist = []
+ while True:
+ t = self.Lexer().token()
+ if not t:
+ break
+ outlist.append(t)
+ return outlist
+
+ def Tokenize(self, data, filename='__no_file__'):
+ lexer = self.Lexer()
+ lexer.lineno = 1
+ lexer.filename = filename
+ lexer.input(data)
+ self.lines = data.split('\n')
+
+ def KnownTokens(self):
+ return self.tokens
+
+ def Lexer(self):
+ if not self._lexobj:
+ self._lexobj = lex.lex(object=self, lextab=None, optimize=0)
+ return self._lexobj
+
+ def _AddToken(self, token):
+ if token in self.tokens:
+ raise RuntimeError('Same token: ' + token)
+ self.tokens.append(token)
+
+ def _AddTokens(self, tokens):
+ for token in tokens:
+ self._AddToken(token)
+
+ def _AddKeywords(self, keywords):
+ for key in keywords:
+ value = key.upper()
+ self._AddToken(value)
+ self.keywords[key] = value
+
+ def _DelKeywords(self, keywords):
+ for key in keywords:
+ self.tokens.remove(key.upper())
+ del self.keywords[key]
+
+ def __init__(self):
+ self.index = [0]
+ self._lex_errors = 0
+ self.linex = []
+ self.filename = None
+ self.keywords = {}
+ self.tokens = []
+ self._AddTokens(IDLLexer.tokens)
+ self._AddKeywords(IDLLexer.keywords)
+ self._lexobj = None
+ self.last = None
+ self.lines = None
+
+# If run by itself, attempt to build the lexer
+if __name__ == '__main__':
+ lexer_object = IDLLexer()
diff --git a/chromium/tools/idl_parser/idl_lexer_test.py b/chromium/tools/idl_parser/idl_lexer_test.py
new file mode 100755
index 00000000000..8b20da85fbd
--- /dev/null
+++ b/chromium/tools/idl_parser/idl_lexer_test.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from idl_lexer import IDLLexer
+from idl_ppapi_lexer import IDLPPAPILexer
+
+#
+# FileToTokens
+#
+# From a source file generate a list of tokens.
+#
+def FileToTokens(lexer, filename):
+ with open(filename, 'rb') as srcfile:
+ lexer.Tokenize(srcfile.read(), filename)
+ return lexer.GetTokens()
+
+
+#
+# TextToTokens
+#
+# From a source file generate a list of tokens.
+#
+def TextToTokens(lexer, text):
+ lexer.Tokenize(text)
+ return lexer.GetTokens()
+
+
+class WebIDLLexer(unittest.TestCase):
+ def setUp(self):
+ self.lexer = IDLLexer()
+ self.filenames = [
+ 'test_lexer/values.in',
+ 'test_lexer/keywords.in'
+ ]
+
+ #
+ # testRebuildText
+ #
+ # From a set of tokens, generate a new source text by joining with a
+ # single space. The new source is then tokenized and compared against the
+ # old set.
+ #
+ def testRebuildText(self):
+ for filename in self.filenames:
+ tokens1 = FileToTokens(self.lexer, filename)
+ to_text = '\n'.join(['%s' % t.value for t in tokens1])
+ tokens2 = TextToTokens(self.lexer, to_text)
+
+ count1 = len(tokens1)
+ count2 = len(tokens2)
+ self.assertEqual(count1, count2)
+
+ for i in range(count1):
+ msg = 'Value %s does not match original %s on line %d of %s.' % (
+ tokens2[i].value, tokens1[i].value, tokens1[i].lineno, filename)
+ self.assertEqual(tokens1[i].value, tokens2[i].value, msg)
+
+ #
+ # testExpectedType
+ #
+ # From a set of tokens pairs, verify the type field of the second matches
+ # the value of the first, so that:
+ # integer 123 float 1.1 ...
+ # will generate a passing test, when the first token has both the type and
+ # value of the keyword integer and the second has the type of integer and
+ # value of 123 and so on.
+ #
+ def testExpectedType(self):
+ for filename in self.filenames:
+ tokens = FileToTokens(self.lexer, filename)
+ count = len(tokens)
+ self.assertTrue(count > 0)
+ self.assertFalse(count & 1)
+
+ index = 0
+ while index < count:
+ expect_type = tokens[index].value
+ actual_type = tokens[index + 1].type
+ msg = 'Type %s does not match expected %s on line %d of %s.' % (
+ actual_type, expect_type, tokens[index].lineno, filename)
+ index += 2
+ self.assertEqual(expect_type, actual_type, msg)
+
+
+class PepperIDLLexer(WebIDLLexer):
+ def setUp(self):
+ self.lexer = IDLPPAPILexer()
+ self.filenames = [
+ 'test_lexer/values_ppapi.in',
+ 'test_lexer/keywords_ppapi.in'
+ ]
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/idl_parser/idl_node.py b/chromium/tools/idl_parser/idl_node.py
new file mode 100755
index 00000000000..83aefa52adc
--- /dev/null
+++ b/chromium/tools/idl_parser/idl_node.py
@@ -0,0 +1,217 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+#
+# IDL Node
+#
+# IDL Node defines the IDLAttribute and IDLNode objects which are constructed
+# by the parser as it processes the various 'productions'. The IDLAttribute
+# objects are assigned to the IDLNode's property dictionary instead of being
+# applied as children of The IDLNodes, so they do not exist in the final tree.
+# The AST of IDLNodes is the output from the parsing state and will be used
+# as the source data by the various generators.
+#
+
+
+#
+# CopyToList
+#
+# Takes an input item, list, or None, and returns a new list of that set.
+def CopyToList(item):
+ # If the item is 'Empty' make it an empty list
+ if not item:
+ item = []
+
+ # If the item is not a list
+ if type(item) is not type([]):
+ item = [item]
+
+ # Make a copy we can modify
+ return list(item)
+
+
+# IDLSearch
+#
+# A temporary object used by the parsing process to hold an Extended Attribute
+# which will be passed as a child to a standard IDLNode.
+#
+class IDLSearch(object):
+ def __init__(self):
+ self.depth = 0
+
+ def Enter(self, node):
+ pass
+
+ def Exit(self, node):
+ pass
+
+
+# IDLAttribute
+#
+# A temporary object used by the parsing process to hold an Extended Attribute
+# which will be passed as a child to a standard IDLNode.
+#
+class IDLAttribute(object):
+ def __init__(self, name, value):
+ self._cls = 'Property'
+ self.name = name
+ self.value = value
+
+ def __str__(self):
+ return '%s=%s' % (self.name, self.value)
+
+ def GetClass(self):
+ return self._cls
+
+#
+# IDLNode
+#
+# This class implements the AST tree, providing the associations between
+# parents and children. It also contains a namepsace and propertynode to
+# allow for look-ups. IDLNode is derived from IDLRelease, so it is
+# version aware.
+#
+class IDLNode(object):
+ def __init__(self, cls, filename, lineno, pos, children=None):
+ self._cls = cls
+ self._properties = {
+ 'ERRORS' : [],
+ 'WARNINGS': [],
+ 'FILENAME': filename,
+ 'LINENO' : lineno,
+ 'POSSITION' : pos,
+ }
+
+ self._children = []
+ self._parent = None
+ self.AddChildren(children)
+
+#
+#
+#
+ # Return a string representation of this node
+ def __str__(self):
+ name = self.GetProperty('NAME','')
+ return '%s(%s)' % (self._cls, name)
+
+ def GetLogLine(self, msg):
+ filename, lineno = self.GetFileAndLine()
+ return '%s(%d) : %s\n' % (filename, lineno, msg)
+
+ # Log an error for this object
+ def Error(self, msg):
+ self.GetProperty('ERRORS').append(msg)
+ sys.stderr.write(self.GetLogLine('error: ' + msg))
+
+ # Log a warning for this object
+ def Warning(self, msg):
+ self.GetProperty('WARNINGS').append(msg)
+ sys.stdout.write(self.GetLogLine('warning:' + msg))
+
+ # Return file and line number for where node was defined
+ def GetFileAndLine(self):
+ return self.GetProperty('FILENAME'), self.GetProperty('LINENO')
+
+ def GetClass(self):
+ return self._cls
+
+ def GetName(self):
+ return self.GetProperty('NAME')
+
+ def GetParent(self):
+ return self._parent
+
+ def Traverse(self, search, filter_nodes):
+ if self._cls in filter_nodes:
+ return ''
+
+ search.Enter(self)
+ search.depth += 1
+ for child in self._children:
+ child.Traverse(search, filter_nodes)
+ search.depth -= 1
+ search.Exit(self)
+
+
+ def Tree(self, filter_nodes=None, accept_props=None):
+ class DumpTreeSearch(IDLSearch):
+ def __init__(self, props):
+ IDLSearch.__init__(self)
+ self.out = []
+ self.props = props
+
+ def Enter(self, node):
+ tab = ''.rjust(self.depth * 2)
+ self.out.append(tab + str(node))
+ if self.props:
+ proplist = []
+ for key, value in node.GetProperties().iteritems():
+ if key in self.props:
+ proplist.append(tab + ' %s: %s' % (key, str(value)))
+ if proplist:
+ self.out.append(tab + ' PROPERTIES')
+ self.out.extend(proplist)
+
+ if filter_nodes == None:
+ filter_nodes = ['Comment', 'Copyright']
+
+ search = DumpTreeSearch(accept_props)
+ self.Traverse(search, filter_nodes)
+ return search.out
+
+#
+# Search related functions
+#
+ # Check if node is of a given type
+ def IsA(self, *typelist):
+ if self._cls in typelist:
+ return True
+ return False
+
+ # Get a list of all children
+ def GetChildren(self):
+ return self._children
+
+ def GetListOf(self, *keys):
+ out = []
+ for child in self.GetChildren():
+ if child.GetClass() in keys:
+ out.append(child)
+ return out
+
+ def GetOneOf(self, *keys):
+ out = self.GetListOf(*keys)
+ if out:
+ return out[0]
+ return None
+
+ def AddChildren(self, children):
+ children = CopyToList(children)
+ for child in children:
+ if not child:
+ continue
+ if type(child) == IDLAttribute:
+ self.SetProperty(child.name, child.value)
+ continue
+ if type(child) == IDLNode:
+ child._parent = self
+ self._children.append(child)
+ continue
+ raise RuntimeError('Adding child of type .\n' % type(child).__name__)
+
+
+#
+# Property Functions
+#
+ def SetProperty(self, name, val):
+ self._properties[name] = val
+
+ def GetProperty(self, name, default=None):
+ return self._properties.get(name, default)
+
+ def GetProperties(self):
+ return self._properties
diff --git a/chromium/tools/idl_parser/idl_parser.py b/chromium/tools/idl_parser/idl_parser.py
new file mode 100755
index 00000000000..8a682ea688b
--- /dev/null
+++ b/chromium/tools/idl_parser/idl_parser.py
@@ -0,0 +1,1053 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Parser for PPAPI IDL """
+
+#
+# IDL Parser
+#
+# The parser is uses the PLY yacc library to build a set of parsing rules based
+# on WebIDL.
+#
+# WebIDL, and WebIDL grammar can be found at:
+# http://dev.w3.org/2006/webapi/WebIDL/
+# PLY can be found at:
+# http://www.dabeaz.com/ply/
+#
+# The parser generates a tree by recursively matching sets of items against
+# defined patterns. When a match is made, that set of items is reduced
+# to a new item. The new item can provide a match for parent patterns.
+# In this way an AST is built (reduced) depth first.
+#
+
+#
+# Disable check for line length and Member as Function due to how grammar rules
+# are defined with PLY
+#
+# pylint: disable=R0201
+# pylint: disable=C0301
+
+import os.path
+import sys
+import time
+
+from idl_lexer import IDLLexer
+from idl_node import IDLAttribute, IDLNode
+
+#
+# Try to load the ply module, if not, then assume it is in the third_party
+# directory.
+#
+try:
+ # Disable lint check which fails to find the ply module.
+ # pylint: disable=F0401
+ from ply import lex
+ from ply import yacc
+except ImportError:
+ module_path, module_name = os.path.split(__file__)
+ third_party = os.path.join(module_path, os.par, os.par, 'third_party')
+ sys.path.append(third_party)
+ # pylint: disable=F0401
+ from ply import lex
+ from ply import yacc
+
+#
+# ERROR_REMAP
+#
+# Maps the standard error formula into a more friendly error message.
+#
+ERROR_REMAP = {
+ 'Unexpected ")" after "(".' : 'Empty argument list.',
+ 'Unexpected ")" after ",".' : 'Missing argument.',
+ 'Unexpected "}" after ",".' : 'Trailing comma in block.',
+ 'Unexpected "}" after "{".' : 'Unexpected empty block.',
+ 'Unexpected comment after "}".' : 'Unexpected trailing comment.',
+ 'Unexpected "{" after keyword "enum".' : 'Enum missing name.',
+ 'Unexpected "{" after keyword "struct".' : 'Struct missing name.',
+ 'Unexpected "{" after keyword "interface".' : 'Interface missing name.',
+}
+
+
+def Boolean(val):
+ """Convert to strict boolean type."""
+ if val:
+ return True
+ return False
+
+
+def ListFromConcat(*items):
+ """Generate list by concatenating inputs"""
+ itemsout = []
+ for item in items:
+ if item is None:
+ continue
+ if type(item) is not type([]):
+ itemsout.append(item)
+ else:
+ itemsout.extend(item)
+
+ return itemsout
+
+def ExpandProduction(p):
+ if type(p) == list:
+ return '[' + ', '.join([ExpandProduction(x) for x in p]) + ']'
+ if type(p) == IDLNode:
+ return 'Node:' + str(p)
+ if type(p) == IDLAttribute:
+ return 'Attr:' + str(p)
+ if type(p) == str:
+ return 'str:' + p
+ return '%s:%s' % (p.__class__.__name__, str(p))
+
+# TokenTypeName
+#
+# Generate a string which has the type and value of the token.
+#
+def TokenTypeName(t):
+ if t.type == 'SYMBOL':
+ return 'symbol %s' % t.value
+ if t.type in ['HEX', 'INT', 'OCT', 'FLOAT']:
+ return 'value %s' % t.value
+ if t.type == 'string' :
+ return 'string "%s"' % t.value
+ if t.type == 'COMMENT' :
+ return 'comment'
+ if t.type == t.value:
+ return '"%s"' % t.value
+ if t.type == ',':
+ return 'Comma'
+ if t.type == 'identifier':
+ return 'identifier "%s"' % t.value
+ return 'keyword "%s"' % t.value
+
+
+#
+# IDL Parser
+#
+# The Parser inherits the from the Lexer to provide PLY with the tokenizing
+# definitions. Parsing patterns are encoded as functions where p_<name> is
+# is called any time a patern matching the function documentation is found.
+# Paterns are expressed in the form of:
+# """ <new item> : <item> ....
+# | <item> ...."""
+#
+# Where new item is the result of a match against one or more sets of items
+# separated by the "|".
+#
+# The function is called with an object 'p' where p[0] is the output object
+# and p[n] is the set of inputs for positive values of 'n'. Len(p) can be
+# used to distinguish between multiple item sets in the pattern.
+#
+# For more details on parsing refer to the PLY documentation at
+# http://www.dabeaz.com/ply/
+#
+# The parser is based on the WebIDL standard. See:
+# http://www.w3.org/TR/WebIDL/#idl-grammar
+#
+# The various productions are annotated so that the WHOLE number greater than
+# zero in the comment denotes the matching WebIDL grammar definition.
+#
+# Productions with a fractional component in the comment denote additions to
+# the WebIDL spec, such as comments.
+#
+
+
+class IDLParser(object):
+#
+# We force all input files to start with two comments. The first comment is a
+# Copyright notice followed by a file comment and finally by file level
+# productions.
+#
+ # [0] Insert a TOP definition for Copyright and Comments
+ def p_Top(self, p):
+ """Top : COMMENT COMMENT Definitions"""
+ Copyright = self.BuildComment('Copyright', p, 1)
+ Filedoc = self.BuildComment('Comment', p, 2)
+ p[0] = ListFromConcat(Copyright, Filedoc, p[3])
+
+ # [0.1] Add support for Multiple COMMENTS
+ def p_Comments(self, p):
+ """Comments : CommentsRest"""
+ if len(p) > 1:
+ p[0] = p[1]
+
+ # [0.2] Produce a COMMENT and aggregate sibling comments
+ def p_CommentsRest(self, p):
+ """CommentsRest : COMMENT CommentsRest
+ | """
+ if len(p) > 1:
+ p[0] = ListFromConcat(self.BuildComment('Comment', p, 1), p[2])
+
+
+#
+#The parser is based on the WebIDL standard. See:
+# http://www.w3.org/TR/WebIDL/#idl-grammar
+#
+ # [1]
+ def p_Definitions(self, p):
+ """Definitions : ExtendedAttributeList Definition Definitions
+ | """
+ if len(p) > 1:
+ p[2].AddChildren(p[1])
+ p[0] = ListFromConcat(p[2], p[3])
+
+ # [2] Add INLINE definition
+ def p_Definition(self, p):
+ """Definition : CallbackOrInterface
+ | Partial
+ | Dictionary
+ | Exception
+ | Enum
+ | Typedef
+ | ImplementsStatement"""
+ p[0] = p[1]
+
+ # [2.1] Error recovery for definition
+ def p_DefinitionError(self, p):
+ """Definition : error ';'"""
+ p[0] = self.BuildError(p, 'Definition')
+
+ # [3]
+ def p_CallbackOrInterface(self, p):
+ """CallbackOrInterface : CALLBACK CallbackRestOrInterface
+ | Interface"""
+ if len(p) > 2:
+ p[0] = p[2]
+ else:
+ p[0] = p[1]
+
+ # [4]
+ def p_CallbackRestOrInterface(self, p):
+ """CallbackRestOrInterface : CallbackRest
+ | Interface"""
+ p[0] = p[1]
+
+ # [5]
+ def p_Interface(self, p):
+ """Interface : INTERFACE identifier Inheritance '{' InterfaceMembers '}' ';'"""
+ p[0] = self.BuildNamed('Interface', p, 2, ListFromConcat(p[3], p[5]))
+
+ # [6] Error recovery for PARTIAL
+ def p_Partial(self, p):
+ """Partial : PARTIAL PartialDefinition"""
+ p[2].AddChildren(self.BuildTrue('Partial'))
+ p[0] = p[2]
+
+ # [6.1] Error recovery for Enums
+ def p_PartialError(self, p):
+ """Partial : PARTIAL error"""
+ p[0] = self.BuildError(p, 'Partial')
+
+ # [7]
+ def p_PartialDefinition(self, p):
+ """PartialDefinition : PartialDictionary
+ | PartialInterface"""
+ p[0] = p[1]
+
+ # [8]
+ def p_PartialInterface(self, p):
+ """PartialInterface : INTERFACE identifier '{' InterfaceMembers '}' ';'"""
+ p[0] = self.BuildNamed('Interface', p, 2, p[4])
+
+ # [9]
+ def p_InterfaceMembers(self, p):
+ """InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
+ |"""
+ if len(p) > 1:
+ p[2].AddChildren(p[1])
+ p[0] = ListFromConcat(p[2], p[3])
+
+ # [10]
+ def p_InterfaceMember(self, p):
+ """InterfaceMember : Const
+ | AttributeOrOperation"""
+ p[0] = p[1]
+
+ # [11]
+ def p_Dictionary(self, p):
+ """Dictionary : DICTIONARY identifier Inheritance '{' DictionaryMembers '}' ';'"""
+ p[0] = self.BuildNamed('Dictionary', p, 2, ListFromConcat(p[3], p[5]))
+
+ # [11.1] Error recovery for regular Dictionary
+ def p_DictionaryError(self, p):
+ """Dictionary : DICTIONARY error ';'"""
+ p[0] = self.BuildError(p, 'Dictionary')
+
+ # [12]
+ def p_DictionaryMembers(self, p):
+ """DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers
+ |"""
+ if len(p) > 1:
+ p[2].AddChildren(p[1])
+ p[0] = ListFromConcat(p[2], p[3])
+
+ # [13]
+ def p_DictionaryMember(self, p):
+ """DictionaryMember : Type identifier Default ';'"""
+ p[0] = self.BuildNamed('Key', p, 2, ListFromConcat(p[1], p[3]))
+
+ # [14]
+ def p_PartialDictionary(self, p):
+ """PartialDictionary : DICTIONARY identifier '{' DictionaryMembers '}' ';'"""
+ partial = self.BuildTrue('Partial')
+ p[0] = self.BuildNamed('Dictionary', p, 2, ListFromConcat(p[4], partial))
+
+ # [14.1] Error recovery for Partial Dictionary
+ def p_PartialDictionaryError(self, p):
+ """PartialDictionary : DICTIONARY error ';'"""
+ p[0] = self.BuildError(p, 'PartialDictionary')
+
+ # [15]
+ def p_Default(self, p):
+ """Default : '=' DefaultValue
+ |"""
+ if len(p) > 1:
+ p[0] = self.BuildProduction('Default', p, 2, p[2])
+
+ # [16]
+ def p_DefaultValue(self, p):
+ """DefaultValue : ConstValue
+ | string"""
+ if type(p[1]) == str:
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'DOMString'),
+ self.BuildAttribute('NAME', p[1]))
+ else:
+ p[0] = p[1]
+
+ # [17]
+ def p_Exception(self, p):
+ """Exception : EXCEPTION identifier Inheritance '{' ExceptionMembers '}' ';'"""
+ p[0] = self.BuildNamed('Exception', p, 2, ListFromConcat(p[3], p[5]))
+
+ # [18]
+ def p_ExceptionMembers(self, p):
+ """ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers
+ |"""
+ if len(p) > 1:
+ p[2].AddChildren(p[1])
+ p[0] = ListFromConcat(p[2], p[3])
+
+ # [18.1] Error recovery for ExceptionMembers
+ def p_ExceptionMembersError(self, p):
+ """ExceptionMembers : error"""
+ p[0] = self.BuildError(p, 'ExceptionMembers')
+
+ # [19]
+ def p_Inheritance(self, p):
+ """Inheritance : ':' identifier
+ |"""
+ if len(p) > 1:
+ p[0] = self.BuildNamed('Inherit', p, 2)
+
+ # [20]
+ def p_Enum(self, p):
+ """Enum : ENUM identifier '{' EnumValueList '}' ';'"""
+ p[0] = self.BuildNamed('Enum', p, 2, p[4])
+
+ # [20.1] Error recovery for Enums
+ def p_EnumError(self, p):
+ """Enum : ENUM error ';'"""
+ p[0] = self.BuildError(p, 'Enum')
+
+ # [21]
+ def p_EnumValueList(self, p):
+ """EnumValueList : ExtendedAttributeList string EnumValues"""
+ enum = self.BuildNamed('EnumItem', p, 2, p[1])
+ p[0] = ListFromConcat(enum, p[3])
+
+ # [22]
+ def p_EnumValues(self, p):
+ """EnumValues : ',' ExtendedAttributeList string EnumValues
+ |"""
+ if len(p) > 1:
+ enum = self.BuildNamed('EnumItem', p, 3, p[2])
+ p[0] = ListFromConcat(enum, p[4])
+
+ # [23]
+ def p_CallbackRest(self, p):
+ """CallbackRest : identifier '=' ReturnType '(' ArgumentList ')' ';'"""
+ arguments = self.BuildProduction('Arguments', p, 4, p[5])
+ p[0] = self.BuildNamed('Callback', p, 1, ListFromConcat(p[3], arguments))
+
+ # [24]
+ def p_Typedef(self, p):
+ """Typedef : TYPEDEF ExtendedAttributeListNoComments Type identifier ';'"""
+ p[0] = self.BuildNamed('Typedef', p, 4, ListFromConcat(p[2], p[3]))
+
+ # [24.1] Error recovery for Typedefs
+ def p_TypedefError(self, p):
+ """Typedef : TYPEDEF error ';'"""
+ p[0] = self.BuildError(p, 'Typedef')
+
+ # [25]
+ def p_ImplementsStatement(self, p):
+ """ImplementsStatement : identifier IMPLEMENTS identifier ';'"""
+ name = self.BuildAttribute('REFERENCE', p[3])
+ p[0] = self.BuildNamed('Implements', p, 1, name)
+
+ # [26]
+ def p_Const(self, p):
+ """Const : CONST ConstType identifier '=' ConstValue ';'"""
+ value = self.BuildProduction('Value', p, 5, p[5])
+ p[0] = self.BuildNamed('Const', p, 3, ListFromConcat(p[2], value))
+
+ # [27]
+ def p_ConstValue(self, p):
+ """ConstValue : BooleanLiteral
+ | FloatLiteral
+ | integer
+ | null"""
+ if type(p[1]) == str:
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'),
+ self.BuildAttribute('NAME', p[1]))
+ else:
+ p[0] = p[1]
+
+ # [27.1] Add definition for NULL
+ def p_null(self, p):
+ """null : NULL"""
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'NULL'),
+ self.BuildAttribute('NAME', 'NULL'))
+
+ # [28]
+ def p_BooleanLiteral(self, p):
+ """BooleanLiteral : TRUE
+ | FALSE"""
+ value = self.BuildAttribute('VALUE', Boolean(p[1] == 'true'))
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'boolean'), value)
+
+ # [29]
+ def p_FloatLiteral(self, p):
+ """FloatLiteral : float
+ | '-' INFINITY
+ | INFINITY
+ | NAN """
+ if len(p) > 2:
+ val = '-Infinity'
+ else:
+ val = p[1]
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'float'),
+ self.BuildAttribute('VALUE', val))
+
+ # [30]
+ def p_AttributeOrOperation(self, p):
+ """AttributeOrOperation : STRINGIFIER StringifierAttributeOrOperation
+ | Attribute
+ | Operation"""
+ if len(p) > 2:
+ p[0] = p[2]
+ else:
+ p[0] = p[1]
+
+ # [31]
+ def p_StringifierAttributeOrOperation(self, p):
+ """StringifierAttributeOrOperation : Attribute
+ | OperationRest
+ | ';'"""
+ if p[1] == ';':
+ p[0] = self.BuildAttribute('STRINGIFIER', Boolean(True))
+ else:
+ p[0] = ListFromConcat(self.BuildAttribute('STRINGIFIER', p[1]), p[1])
+
+ # [32]
+ def p_Attribute(self, p):
+ """Attribute : Inherit ReadOnly ATTRIBUTE Type identifier ';'"""
+ p[0] = self.BuildNamed('Attribute', p, 5,
+ ListFromConcat(p[1], p[2], p[4]))
+
+ # [33]
+ def p_Inherit(self, p):
+ """Inherit : INHERIT
+ |"""
+ if len(p) > 1:
+ p[0] = self.BuildTrue('INHERIT')
+
+ # [34]
+ def p_ReadOnly(self, p):
+ """ReadOnly : READONLY
+ |"""
+ if len(p) > 1:
+ p[0] = self.BuildTrue('READONLY')
+
+ # [35]
+ def p_Operation(self, p):
+ """Operation : Qualifiers OperationRest"""
+ p[2].AddChildren(p[1])
+ p[0] = p[2]
+
+ # [36]
+ def p_Qualifiers(self, p):
+ """Qualifiers : STATIC
+ | Specials"""
+ if p[1] == 'static':
+ p[0] = self.BuildTrue('STATIC')
+ else:
+ p[0] = p[1]
+
+ # [37]
+ def p_Specials(self, p):
+ """Specials : Special Specials
+ | """
+ if len(p) > 1:
+ p[0] = ListFromConcat(p[1], p[2])
+
+ # [38]
+ def p_Special(self, p):
+ """Special : GETTER
+ | SETTER
+ | CREATOR
+ | DELETER
+ | LEGACYCALLER"""
+ p[0] = self.BuildTrue(p[1].upper())
+
+
+ # [39]
+ def p_OperationRest(self, p):
+ """OperationRest : ReturnType OptionalIdentifier '(' ArgumentList ')' ';'"""
+ arguments = self.BuildProduction('Arguments', p, 3, p[4])
+ p[0] = self.BuildNamed('Operation', p, 2, ListFromConcat(p[1], arguments))
+
+ # [40]
+ def p_OptionalIdentifier(self, p):
+ """OptionalIdentifier : identifier
+ |"""
+ if len(p) > 1:
+ p[0] = p[1]
+ else:
+ p[0] = '_unnamed_'
+
+ # [41]
+ def p_ArgumentList(self, p):
+ """ArgumentList : Argument Arguments
+ |"""
+ if len(p) > 1:
+ p[0] = ListFromConcat(p[1], p[2])
+
+ # [41.1] ArgumentList error recovery
+ def p_ArgumentListError(self, p):
+ """ArgumentList : error """
+ p[0] = self.BuildError(p, 'ArgumentList')
+
+ # [42]
+ def p_Arguments(self, p):
+ """Arguments : ',' Argument Arguments
+ |"""
+ if len(p) > 1:
+ p[0] = ListFromConcat(p[2], p[3])
+
+ # [43]
+ def p_Argument(self, p):
+ """Argument : ExtendedAttributeList OptionalOrRequiredArgument"""
+ p[2].AddChildren(p[1])
+ p[0] = p[2]
+
+
+ # [44]
+ def p_OptionalOrRequiredArgument(self, p):
+ """OptionalOrRequiredArgument : OPTIONAL Type ArgumentName Default
+ | Type Ellipsis ArgumentName"""
+ if len(p) > 4:
+ arg = self.BuildNamed('Argument', p, 3, ListFromConcat(p[2], p[4]))
+ arg.AddChildren(self.BuildTrue('OPTIONAL'))
+ else:
+ arg = self.BuildNamed('Argument', p, 3, ListFromConcat(p[1], p[2]))
+ p[0] = arg
+
+ # [45]
+ def p_ArgumentName(self, p):
+ """ArgumentName : ArgumentNameKeyword
+ | identifier"""
+ p[0] = p[1]
+
+ # [46]
+ def p_Ellipsis(self, p):
+ """Ellipsis : ELLIPSIS
+ |"""
+ if len(p) > 1:
+ p[0] = self.BuildNamed('Argument', p, 1)
+ p[0].AddChildren(self.BuildTrue('ELLIPSIS'))
+
+ # [47]
+ def p_ExceptionMember(self, p):
+ """ExceptionMember : Const
+ | ExceptionField"""
+ p[0] = p[1]
+
+ # [48]
+ def p_ExceptionField(self, p):
+ """ExceptionField : Type identifier ';'"""
+ p[0] = self.BuildNamed('ExceptionField', p, 2, p[1])
+
+ # [48.1] Error recovery for ExceptionMembers
+ def p_ExceptionFieldError(self, p):
+ """ExceptionField : error"""
+ p[0] = self.BuildError(p, 'ExceptionField')
+
+ # [49] No comment version for mid statement attributes.
+ def p_ExtendedAttributeListNoComments(self, p):
+ """ExtendedAttributeListNoComments : '[' ExtendedAttribute ExtendedAttributes ']'
+ | """
+ if len(p) > 2:
+ items = ListFromConcat(p[2], p[3])
+ p[0] = self.BuildProduction('ExtAttributes', p, 1, items)
+
+ # [49.1] Add optional comment field for start of statements.
+ def p_ExtendedAttributeList(self, p):
+ """ExtendedAttributeList : Comments '[' ExtendedAttribute ExtendedAttributes ']'
+ | Comments """
+ if len(p) > 2:
+ items = ListFromConcat(p[3], p[4])
+ attribs = self.BuildProduction('ExtAttributes', p, 2, items)
+ p[0] = ListFromConcat(p[1], attribs)
+ else:
+ p[0] = p[1]
+
+ # [50]
+ def p_ExtendedAttributes(self, p):
+ """ExtendedAttributes : ',' ExtendedAttribute ExtendedAttributes
+ |"""
+ if len(p) > 1:
+ p[0] = ListFromConcat(p[2], p[3])
+
+ # We only support:
+ # [ identifier ]
+ # [ identifier = identifier ]
+ # [ identifier ( ArgumentList )]
+ # [ identifier = identifier ( ArgumentList )]
+ # [51] map directly to 74-77
+ # [52-54, 56] are unsupported
+ def p_ExtendedAttribute(self, p):
+ """ExtendedAttribute : ExtendedAttributeNoArgs
+ | ExtendedAttributeArgList
+ | ExtendedAttributeIdent
+ | ExtendedAttributeNamedArgList"""
+ p[0] = p[1]
+
+ # [55]
+ def p_ArgumentNameKeyword(self, p):
+ """ArgumentNameKeyword : ATTRIBUTE
+ | CALLBACK
+ | CONST
+ | CREATOR
+ | DELETER
+ | DICTIONARY
+ | ENUM
+ | EXCEPTION
+ | GETTER
+ | IMPLEMENTS
+ | INHERIT
+ | LEGACYCALLER
+ | PARTIAL
+ | SETTER
+ | STATIC
+ | STRINGIFIER
+ | TYPEDEF
+ | UNRESTRICTED"""
+ p[0] = p[1]
+
+ # [57]
+ def p_Type(self, p):
+ """Type : SingleType
+ | UnionType TypeSuffix"""
+ if len(p) == 2:
+ p[0] = self.BuildProduction('Type', p, 1, p[1])
+ else:
+ p[0] = self.BuildProduction('Type', p, 1, ListFromConcat(p[1], p[2]))
+
+ # [58]
+ def p_SingleType(self, p):
+ """SingleType : NonAnyType
+ | ANY TypeSuffixStartingWithArray"""
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ p[0] = ListFromConcat(self.BuildProduction('Any', p, 1), p[2])
+
+ # [59]
+ def p_UnionType(self, p):
+ """UnionType : '(' UnionMemberType OR UnionMemberType UnionMemberTypes ')'"""
+
+ # [60]
+ def p_UnionMemberType(self, p):
+ """UnionMemberType : NonAnyType
+ | UnionType TypeSuffix
+ | ANY '[' ']' TypeSuffix"""
+ # [61]
+ def p_UnionMemberTypes(self, p):
+ """UnionMemberTypes : OR UnionMemberType UnionMemberTypes
+ |"""
+
+ # [62] Moved DATE, DOMSTRING, OBJECT to PrimitiveType
+ def p_NonAnyType(self, p):
+ """NonAnyType : PrimitiveType TypeSuffix
+ | identifier TypeSuffix
+ | SEQUENCE '<' Type '>' Null"""
+ if len(p) == 3:
+ if type(p[1]) == str:
+ typeref = self.BuildNamed('Typeref', p, 1)
+ else:
+ typeref = p[1]
+ p[0] = ListFromConcat(typeref, p[2])
+
+ if len(p) == 6:
+ p[0] = self.BuildProduction('Sequence', p, 1, ListFromConcat(p[3], p[5]))
+
+
+ # [63]
+ def p_ConstType(self, p):
+ """ConstType : PrimitiveType Null
+ | identifier Null"""
+ if type(p[1]) == str:
+ p[0] = self.BuildNamed('Typeref', p, 1, p[2])
+ else:
+ p[1].AddChildren(p[2])
+ p[0] = p[1]
+
+
+ # [64]
+ def p_PrimitiveType(self, p):
+ """PrimitiveType : UnsignedIntegerType
+ | UnrestrictedFloatType
+ | BOOLEAN
+ | BYTE
+ | OCTET
+ | DOMSTRING
+ | DATE
+ | OBJECT"""
+ if type(p[1]) == str:
+ p[0] = self.BuildNamed('PrimitiveType', p, 1)
+ else:
+ p[0] = p[1]
+
+
+ # [65]
+ def p_UnrestrictedFloatType(self, p):
+ """UnrestrictedFloatType : UNRESTRICTED FloatType
+ | FloatType"""
+ if len(p) == 2:
+ typeref = self.BuildNamed('PrimitiveType', p, 1)
+ else:
+ typeref = self.BuildNamed('PrimitiveType', p, 2)
+ typeref.AddChildren(self.BuildTrue('UNRESTRICTED'))
+ p[0] = typeref
+
+
+ # [66]
+ def p_FloatType(self, p):
+ """FloatType : FLOAT
+ | DOUBLE"""
+ p[0] = p[1]
+
+ # [67]
+ def p_UnsignedIntegerType(self, p):
+ """UnsignedIntegerType : UNSIGNED IntegerType
+ | IntegerType"""
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ p[0] = 'unsigned ' + p[2]
+
+ # [68]
+ def p_IntegerType(self, p):
+ """IntegerType : SHORT
+ | LONG OptionalLong"""
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ p[0] = p[1] + p[2]
+
+ # [69]
+ def p_OptionalLong(self, p):
+ """OptionalLong : LONG
+ | """
+ if len(p) > 1:
+ p[0] = ' ' + p[1]
+ else:
+ p[0] = ''
+
+
+ # [70] Add support for sized array
+ def p_TypeSuffix(self, p):
+ """TypeSuffix : '[' integer ']' TypeSuffix
+ | '[' ']' TypeSuffix
+ | '?' TypeSuffixStartingWithArray
+ | """
+ if len(p) == 5:
+ p[0] = self.BuildNamed('Array', p, 2, p[4])
+
+ if len(p) == 4:
+ p[0] = self.BuildProduction('Array', p, 1, p[3])
+
+ if len(p) == 3:
+ p[0] = ListFromConcat(self.BuildTrue('NULLABLE'), p[2])
+
+
+ # [71]
+ def p_TypeSuffixStartingWithArray(self, p):
+ """TypeSuffixStartingWithArray : '[' ']' TypeSuffix
+ | """
+ if len(p) > 1:
+ p[0] = self.BuildProduction('Array', p, 0, p[3])
+
+ # [72]
+ def p_Null(self, p):
+ """Null : '?'
+ |"""
+ if len(p) > 1:
+ p[0] = self.BuildTrue('NULLABLE')
+
+ # [73]
+ def p_ReturnType(self, p):
+ """ReturnType : Type
+ | VOID"""
+ if p[1] == 'void':
+ p[0] = self.BuildProduction('Type', p, 1)
+ p[0].AddChildren(self.BuildNamed('PrimitiveType', p, 1))
+ else:
+ p[0] = p[1]
+
+ # [74]
+ def p_ExtendedAttributeNoArgs(self, p):
+ """ExtendedAttributeNoArgs : identifier"""
+ p[0] = self.BuildNamed('ExtAttribute', p, 1)
+
+ # [75]
+ def p_ExtendedAttributeArgList(self, p):
+ """ExtendedAttributeArgList : identifier '(' ArgumentList ')'"""
+ arguments = self.BuildProduction('Arguments', p, 2, p[3])
+ p[0] = self.BuildNamed('ExtAttribute', p, 1, arguments)
+
+ # [76]
+ def p_ExtendedAttributeIdent(self, p):
+ """ExtendedAttributeIdent : identifier '=' identifier"""
+ value = self.BuildAttribute('VALUE', p[3])
+ p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
+
+ # [77]
+ def p_ExtendedAttributeNamedArgList(self, p):
+ """ExtendedAttributeNamedArgList : identifier '=' identifier '(' ArgumentList ')'"""
+ args = self.BuildProduction('Arguments', p, 4, p[5])
+ value = self.BuildNamed('Call', p, 3, args)
+ p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
+
+#
+# Parser Errors
+#
+# p_error is called whenever the parser can not find a pattern match for
+# a set of items from the current state. The p_error function defined here
+# is triggered logging an error, and parsing recovery happens as the
+# p_<type>_error functions defined above are called. This allows the parser
+# to continue so as to capture more than one error per file.
+#
+ def p_error(self, t):
+ if t:
+ lineno = t.lineno
+ pos = t.lexpos
+ prev = self.yaccobj.symstack[-1]
+ if type(prev) == lex.LexToken:
+ msg = "Unexpected %s after %s." % (
+ TokenTypeName(t), TokenTypeName(prev))
+ else:
+ msg = "Unexpected %s." % (t.value)
+ else:
+ last = self.LastToken()
+ lineno = last.lineno
+ pos = last.lexpos
+ msg = "Unexpected end of file after %s." % TokenTypeName(last)
+ self.yaccobj.restart()
+
+ # Attempt to remap the error to a friendlier form
+ if msg in ERROR_REMAP:
+ msg = ERROR_REMAP[msg]
+
+ self._last_error_msg = msg
+ self._last_error_lineno = lineno
+ self._last_error_pos = pos
+
+ def Warn(self, node, msg):
+ sys.stdout.write(node.GetLogLine(msg))
+ self.parse_warnings += 1
+
+ def LastToken(self):
+ return self.lexer.last
+
+ def __init__(self, lexer, verbose=False, debug=False, mute_error=False):
+ self.lexer = lexer
+ self.tokens = lexer.KnownTokens()
+ self.yaccobj = yacc.yacc(module=self, tabmodule=None, debug=debug,
+ optimize=0, write_tables=0)
+ self.parse_debug = debug
+ self.verbose = verbose
+ self.mute_error = mute_error
+ self._parse_errors = 0
+ self._parse_warnings = 0
+ self._last_error_msg = None
+ self._last_error_lineno = 0
+ self._last_error_pos = 0
+
+
+#
+# BuildProduction
+#
+# Production is the set of items sent to a grammar rule resulting in a new
+# item being returned.
+#
+# p - Is the Yacc production object containing the stack of items
+# index - Index into the production of the name for the item being produced.
+# cls - The type of item being producted
+# childlist - The children of the new item
+ def BuildProduction(self, cls, p, index, childlist=None):
+ try:
+ if not childlist:
+ childlist = []
+
+ filename = self.lexer.Lexer().filename
+ lineno = p.lineno(index)
+ pos = p.lexpos(index)
+ out = IDLNode(cls, filename, lineno, pos, childlist)
+ return out
+ except:
+ print 'Exception while parsing:'
+ for num, item in enumerate(p):
+ print ' [%d] %s' % (num, ExpandProduction(item))
+ if self.LastToken():
+ print 'Last token: %s' % str(self.LastToken())
+ raise
+
+ def BuildNamed(self, cls, p, index, childlist=None):
+ childlist = ListFromConcat(childlist)
+ childlist.append(self.BuildAttribute('NAME', p[index]))
+ return self.BuildProduction(cls, p, index, childlist)
+
+ def BuildComment(self, cls, p, index):
+ name = p[index]
+
+ # Remove comment markers
+ lines = []
+ if name[:2] == '//':
+ # For C++ style, remove any leading whitespace and the '//' marker from
+ # each line.
+ form = 'cc'
+ for line in name.split('\n'):
+ start = line.find('//')
+ lines.append(line[start+2:])
+ else:
+ # For C style, remove ending '*/''
+ form = 'c'
+ for line in name[:-2].split('\n'):
+ # Remove characters until start marker for this line '*' if found
+ # otherwise it should be blank.
+ offs = line.find('*')
+ if offs >= 0:
+ line = line[offs + 1:].rstrip()
+ else:
+ line = ''
+ lines.append(line)
+ name = '\n'.join(lines)
+ childlist = [self.BuildAttribute('NAME', name),
+ self.BuildAttribute('FORM', form)]
+ return self.BuildProduction(cls, p, index, childlist)
+
+#
+# BuildError
+#
+# Build and Errror node as part of the recovery process.
+#
+#
+ def BuildError(self, p, prod):
+ self._parse_errors += 1
+ name = self.BuildAttribute('NAME', self._last_error_msg)
+ line = self.BuildAttribute('LINE', self._last_error_lineno)
+ pos = self.BuildAttribute('POS', self._last_error_pos)
+ prod = self.BuildAttribute('PROD', prod)
+
+ node = self.BuildProduction('Error', p, 1,
+ ListFromConcat(name, line, pos, prod))
+ if not self.mute_error:
+ node.Error(self._last_error_msg)
+
+ return node
+
+#
+# BuildAttribute
+#
+# An ExtendedAttribute is a special production that results in a property
+# which is applied to the adjacent item. Attributes have no children and
+# instead represent key/value pairs.
+#
+ def BuildAttribute(self, key, val):
+ return IDLAttribute(key, val)
+
+ def BuildFalse(self, key):
+ return IDLAttribute(key, Boolean(False))
+
+ def BuildTrue(self, key):
+ return IDLAttribute(key, Boolean(True))
+
+ def GetErrors(self):
+ # Access lexer errors, despite being private
+ # pylint: disable=W0212
+ return self._parse_errors + self.lexer._lex_errors
+
+#
+# ParseData
+#
+# Attempts to parse the current data loaded in the lexer.
+#
+ def ParseText(self, filename, data):
+ self._parse_errors = 0
+ self._parse_warnings = 0
+ self._last_error_msg = None
+ self._last_error_lineno = 0
+ self._last_error_pos = 0
+
+ try:
+ self.lexer.Tokenize(data, filename)
+ nodes = self.yaccobj.parse(lexer=self.lexer) or []
+ name = self.BuildAttribute('NAME', filename)
+ return IDLNode('File', filename, 0, 0, nodes + [name])
+
+ except lex.LexError as lexError:
+ sys.stderr.write('Error in token: %s\n' % str(lexError))
+ return None
+
+
+
+def ParseFile(parser, filename):
+ """Parse a file and return a File type of node."""
+ with open(filename) as fileobject:
+ try:
+ out = parser.ParseText(filename, fileobject.read())
+ out.SetProperty('DATETIME', time.ctime(os.path.getmtime(filename)))
+ out.SetProperty('ERRORS', parser.GetErrors())
+ return out
+
+ except Exception as e:
+ last = parser.LastToken()
+ sys.stderr.write('%s(%d) : Internal parsing error\n\t%s.\n' % (
+ filename, last.lineno, str(e)))
+
+
+def main(argv):
+ nodes = []
+ parser = IDLParser(IDLLexer())
+ errors = 0
+ for filename in argv:
+ filenode = ParseFile(parser, filename)
+ if (filenode):
+ errors += filenode.GetProperty('ERRORS')
+ nodes.append(filenode)
+
+ ast = IDLNode('AST', '__AST__', 0, 0, nodes)
+
+ print '\n'.join(ast.Tree(accept_props=['PROD']))
+ if errors:
+ print '\nFound %d errors.\n' % errors
+
+ return errors
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/idl_parser/idl_parser_test.py b/chromium/tools/idl_parser/idl_parser_test.py
new file mode 100755
index 00000000000..76a9571b9de
--- /dev/null
+++ b/chromium/tools/idl_parser/idl_parser_test.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import glob
+import unittest
+
+from idl_lexer import IDLLexer
+from idl_parser import IDLParser, ParseFile
+from idl_ppapi_lexer import IDLPPAPILexer
+from idl_ppapi_parser import IDLPPAPIParser
+
+def ParseCommentTest(comment):
+ comment = comment.strip()
+ comments = comment.split(None, 1)
+ return comments[0], comments[1]
+
+
+class WebIDLParser(unittest.TestCase):
+ def setUp(self):
+ self.parser = IDLParser(IDLLexer(), mute_error=True)
+ self.filenames = glob.glob('test_parser/*_web.idl')
+
+ def _TestNode(self, node):
+ comments = node.GetListOf('Comment')
+ for comment in comments:
+ check, value = ParseCommentTest(comment.GetName())
+ if check == 'BUILD':
+ msg = 'Expecting %s, but found %s.\n' % (value, str(node))
+ self.assertEqual(value, str(node), msg)
+
+ if check == 'ERROR':
+ msg = node.GetLogLine('Expecting\n\t%s\nbut found \n\t%s\n' % (
+ value, str(node)))
+ self.assertEqual(value, node.GetName(), msg)
+
+ if check == 'PROP':
+ key, expect = value.split('=')
+ actual = str(node.GetProperty(key))
+ msg = 'Mismatched property %s: %s vs %s.\n' % (key, expect, actual)
+ self.assertEqual(expect, actual, msg)
+
+ if check == 'TREE':
+ quick = '\n'.join(node.Tree())
+ lineno = node.GetProperty('LINENO')
+ msg = 'Mismatched tree at line %d:\n%sVS\n%s' % (lineno, value, quick)
+ self.assertEqual(value, quick, msg)
+
+ def testExpectedNodes(self):
+ for filename in self.filenames:
+ filenode = ParseFile(self.parser, filename)
+ children = filenode.GetChildren()
+ self.assertTrue(len(children) > 2, 'Expecting children in %s.' %
+ filename)
+
+ for node in filenode.GetChildren()[2:]:
+ self._TestNode(node)
+
+
+class PepperIDLParser(unittest.TestCase):
+ def setUp(self):
+ self.parser = IDLPPAPIParser(IDLPPAPILexer(), mute_error=True)
+ self.filenames = glob.glob('test_parser/*_ppapi.idl')
+
+ def _TestNode(self, filename, node):
+ comments = node.GetListOf('Comment')
+ for comment in comments:
+ check, value = ParseCommentTest(comment.GetName())
+ if check == 'BUILD':
+ msg = '%s - Expecting %s, but found %s.\n' % (
+ filename, value, str(node))
+ self.assertEqual(value, str(node), msg)
+
+ if check == 'ERROR':
+ msg = node.GetLogLine('%s - Expecting\n\t%s\nbut found \n\t%s\n' % (
+ filename, value, str(node)))
+ self.assertEqual(value, node.GetName(), msg)
+
+ if check == 'PROP':
+ key, expect = value.split('=')
+ actual = str(node.GetProperty(key))
+ msg = '%s - Mismatched property %s: %s vs %s.\n' % (
+ filename, key, expect, actual)
+ self.assertEqual(expect, actual, msg)
+
+ if check == 'TREE':
+ quick = '\n'.join(node.Tree())
+ lineno = node.GetProperty('LINENO')
+ msg = '%s - Mismatched tree at line %d:\n%sVS\n%s' % (
+ filename, lineno, value, quick)
+ self.assertEqual(value, quick, msg)
+
+ def testExpectedNodes(self):
+ for filename in self.filenames:
+ filenode = ParseFile(self.parser, filename)
+ children = filenode.GetChildren()
+ self.assertTrue(len(children) > 2, 'Expecting children in %s.' %
+ filename)
+
+ for node in filenode.GetChildren()[2:]:
+ self._TestNode(filename, node)
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
+
diff --git a/chromium/tools/idl_parser/idl_ppapi_lexer.py b/chromium/tools/idl_parser/idl_ppapi_lexer.py
new file mode 100755
index 00000000000..9e834863c8d
--- /dev/null
+++ b/chromium/tools/idl_parser/idl_ppapi_lexer.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Lexer for PPAPI IDL
+
+The lexer uses the PLY library to build a tokenizer which understands both
+WebIDL and Pepper tokens.
+
+WebIDL, and WebIDL regular expressions can be found at:
+ http://www.w3.org/TR/2012/CR-WebIDL-20120419/
+PLY can be found at:
+ http://www.dabeaz.com/ply/
+"""
+
+from idl_lexer import IDLLexer
+
+
+#
+# IDL PPAPI Lexer
+#
+class IDLPPAPILexer(IDLLexer):
+ # Token definitions
+ #
+ # These need to be methods for lexer construction, despite not using self.
+ # pylint: disable=R0201
+
+ # Special multi-character operators
+ def t_LSHIFT(self, t):
+ r'<<'
+ return t
+
+ def t_RSHIFT(self, t):
+ r'>>'
+ return t
+
+ def t_INLINE(self, t):
+ r'\#inline (.|\n)*?\#endinl.*'
+ self.AddLines(t.value.count('\n'))
+ return t
+
+ # Return a "preprocessor" inline block
+ def __init__(self):
+ IDLLexer.__init__(self)
+ self._AddTokens(['INLINE', 'LSHIFT', 'RSHIFT'])
+ self._AddKeywords(['label', 'struct'])
+
+ # Add number types
+ self._AddKeywords(['char', 'int8_t', 'int16_t', 'int32_t', 'int64_t'])
+ self._AddKeywords(['uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'])
+ self._AddKeywords(['double_t', 'float_t'])
+
+ # Add handle types
+ self._AddKeywords(['handle_t', 'PP_FileHandle'])
+
+ # Add pointer types (void*, char*, const char*, const void*)
+ self._AddKeywords(['mem_t', 'str_t', 'cstr_t', 'interface_t'])
+
+ # Remove JS types
+ self._DelKeywords(['boolean', 'byte', 'Date', 'DOMString', 'double',
+ 'float', 'long', 'object', 'octet', 'short', 'unsigned'])
+
+
+# If run by itself, attempt to build the lexer
+if __name__ == '__main__':
+ lexer = IDLPPAPILexer()
+ lexer.Tokenize(open('test_parser/inline_ppapi.idl').read())
+ for tok in lexer.GetTokens():
+ print '\n' + str(tok)
diff --git a/chromium/tools/idl_parser/idl_ppapi_parser.py b/chromium/tools/idl_parser/idl_ppapi_parser.py
new file mode 100755
index 00000000000..c02e42c818f
--- /dev/null
+++ b/chromium/tools/idl_parser/idl_ppapi_parser.py
@@ -0,0 +1,304 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Parser for PPAPI IDL """
+
+#
+# IDL Parser
+#
+# The parser is uses the PLY yacc library to build a set of parsing rules based
+# on WebIDL.
+#
+# WebIDL, and WebIDL grammar can be found at:
+# http://dev.w3.org/2006/webapi/WebIDL/
+# PLY can be found at:
+# http://www.dabeaz.com/ply/
+#
+# The parser generates a tree by recursively matching sets of items against
+# defined patterns. When a match is made, that set of items is reduced
+# to a new item. The new item can provide a match for parent patterns.
+# In this way an AST is built (reduced) depth first.
+#
+
+#
+# Disable check for line length and Member as Function due to how grammar rules
+# are defined with PLY
+#
+# pylint: disable=R0201
+# pylint: disable=C0301
+
+import sys
+
+from idl_ppapi_lexer import IDLPPAPILexer
+from idl_parser import IDLParser, ListFromConcat, ParseFile
+from idl_node import IDLNode
+
+class IDLPPAPIParser(IDLParser):
+#
+# We force all input files to start with two comments. The first comment is a
+# Copyright notice followed by a file comment and finally by file level
+# productions.
+#
+ # [0] Insert a TOP definition for Copyright and Comments
+ def p_Top(self, p):
+ """Top : COMMENT COMMENT Definitions"""
+ Copyright = self.BuildComment('Copyright', p, 1)
+ Filedoc = self.BuildComment('Comment', p, 2)
+ p[0] = ListFromConcat(Copyright, Filedoc, p[3])
+
+#
+#The parser is based on the WebIDL standard. See:
+# http://www.w3.org/TR/WebIDL/#idl-grammar
+#
+ # [1]
+ def p_Definitions(self, p):
+ """Definitions : ExtendedAttributeList Definition Definitions
+ | """
+ if len(p) > 1:
+ p[2].AddChildren(p[1])
+ p[0] = ListFromConcat(p[2], p[3])
+
+ # [2] Add INLINE definition
+ def p_Definition(self, p):
+ """Definition : CallbackOrInterface
+ | Struct
+ | Partial
+ | Dictionary
+ | Exception
+ | Enum
+ | Typedef
+ | ImplementsStatement
+ | Label
+ | Inline"""
+ p[0] = p[1]
+
+ def p_Inline(self, p):
+ """Inline : INLINE"""
+ words = p[1].split()
+ name = self.BuildAttribute('NAME', words[1])
+ lines = p[1].split('\n')
+ value = self.BuildAttribute('VALUE', '\n'.join(lines[1:-1]) + '\n')
+ children = ListFromConcat(name, value)
+ p[0] = self.BuildProduction('Inline', p, 1, children)
+
+#
+# Label
+#
+# A label is a special kind of enumeration which allows us to go from a
+# set of version numbrs to releases
+#
+ def p_Label(self, p):
+ """Label : LABEL identifier '{' LabelList '}' ';'"""
+ p[0] = self.BuildNamed('Label', p, 2, p[4])
+
+ def p_LabelList(self, p):
+ """LabelList : identifier '=' float LabelCont"""
+ val = self.BuildAttribute('VALUE', p[3])
+ label = self.BuildNamed('LabelItem', p, 1, val)
+ p[0] = ListFromConcat(label, p[4])
+
+ def p_LabelCont(self, p):
+ """LabelCont : ',' LabelList
+ |"""
+ if len(p) > 1:
+ p[0] = p[2]
+
+ def p_LabelContError(self, p):
+ """LabelCont : error LabelCont"""
+ p[0] = p[2]
+
+ # [5.1] Add "struct" style interface
+ def p_Struct(self, p):
+ """Struct : STRUCT identifier Inheritance '{' StructMembers '}' ';'"""
+ p[0] = self.BuildNamed('Struct', p, 2, ListFromConcat(p[3], p[5]))
+
+ def p_StructMembers(self, p):
+ """StructMembers : StructMember StructMembers
+ |"""
+ if len(p) > 1:
+ p[0] = ListFromConcat(p[1], p[2])
+
+ def p_StructMember(self, p):
+ """StructMember : ExtendedAttributeList Type identifier ';'"""
+ p[0] = self.BuildNamed('Member', p, 3, ListFromConcat(p[1], p[2]))
+
+ # [24]
+ def p_Typedef(self, p):
+ """Typedef : TYPEDEF ExtendedAttributeListNoComments Type identifier ';'"""
+ p[0] = self.BuildNamed('Typedef', p, 4, ListFromConcat(p[2], p[3]))
+
+ # [24.1]
+ def p_TypedefFunc(self, p):
+ """Typedef : TYPEDEF ExtendedAttributeListNoComments ReturnType identifier '(' ArgumentList ')' ';'"""
+ args = self.BuildProduction('Arguments', p, 5, p[6])
+ p[0] = self.BuildNamed('Callback', p, 4, ListFromConcat(p[2], p[3], args))
+
+ # [27]
+ def p_ConstValue(self, p):
+ """ConstValue : integer
+ | integer LSHIFT integer
+ | integer RSHIFT integer"""
+ val = str(p[1])
+ if len(p) > 2:
+ val = "%s %s %s" % (p[1], p[2], p[3])
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'),
+ self.BuildAttribute('VALUE', val))
+
+ def p_ConstValueStr(self, p):
+ """ConstValue : string"""
+ p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'string'),
+ self.BuildAttribute('VALUE', p[1]))
+
+ # Boolean & Float Literals area already BuildAttributes
+ def p_ConstValueLiteral(self, p):
+ """ConstValue : FloatLiteral
+ | BooleanLiteral """
+ p[0] = p[1]
+
+ # [21]
+ def p_EnumValueList(self, p):
+ """EnumValueList : EnumValue EnumValues"""
+ p[0] = ListFromConcat(p[1], p[2])
+
+ # [22]
+ def p_EnumValues(self, p):
+ """EnumValues : ',' EnumValue EnumValues
+ |"""
+ if len(p) > 1:
+ p[0] = ListFromConcat(p[2], p[3])
+
+ def p_EnumValue(self, p):
+ """EnumValue : ExtendedAttributeList identifier
+ | ExtendedAttributeList identifier '=' ConstValue"""
+ p[0] = self.BuildNamed('EnumItem', p, 2, p[1])
+ if len(p) > 3:
+ p[0].AddChildren(p[4])
+
+ def p_PrimitiveType(self, p):
+ """PrimitiveType : IntegerType
+ | UnsignedIntegerType
+ | FloatType
+ | HandleType
+ | PointerType"""
+ if type(p[1]) == str:
+ p[0] = self.BuildNamed('PrimitiveType', p, 1)
+ else:
+ p[0] = p[1]
+
+ def p_PointerType(self, p):
+ """PointerType : STR_T
+ | MEM_T
+ | CSTR_T
+ | INTERFACE_T
+ | NULL"""
+ p[0] = p[1]
+
+ def p_HandleType(self, p):
+ """HandleType : HANDLE_T
+ | PP_FILEHANDLE"""
+ p[0] = p[1]
+
+ # [66]
+ def p_FloatType(self, p):
+ """FloatType : FLOAT_T
+ | DOUBLE_T"""
+ p[0] = p[1]
+
+ # [67]
+ def p_UnsignedIntegerType(self, p):
+ """UnsignedIntegerType : UINT8_T
+ | UINT16_T
+ | UINT32_T
+ | UINT64_T"""
+ p[0] = p[1]
+
+
+ # [68]
+ def p_IntegerType(self, p):
+ """IntegerType : CHAR
+ | INT8_T
+ | INT16_T
+ | INT32_T
+ | INT64_T"""
+ p[0] = p[1]
+
+ # These targets are no longer used
+ def p_OptionalLong(self, p):
+ """ """
+ pass
+
+ def p_UnrestrictedFloatType(self, p):
+ """ """
+ pass
+
+ def p_null(self, p):
+ """ """
+ pass
+
+ # We only support:
+ # [ identifier ]
+ # [ identifier = identifier ]
+ # [ identifier ( ArgumentList )]
+ # [ identifier ( ValueList )]
+ # [ identifier = identifier ( ArgumentList )]
+ # [51] map directly to 74-77
+ # [52-54, 56] are unsupported
+ def p_ExtendedAttribute(self, p):
+ """ExtendedAttribute : ExtendedAttributeNoArgs
+ | ExtendedAttributeArgList
+ | ExtendedAttributeValList
+ | ExtendedAttributeIdent
+ | ExtendedAttributeIdentConst
+ | ExtendedAttributeNamedArgList"""
+ p[0] = p[1]
+
+ def p_ExtendedAttributeValList(self, p):
+ """ExtendedAttributeValList : identifier '(' ValueList ')'"""
+ arguments = self.BuildProduction('Values', p, 2, p[3])
+ p[0] = self.BuildNamed('ExtAttribute', p, 1, arguments)
+
+ def p_ValueList(self, p):
+ """ValueList : ConstValue ValueListCont"""
+ p[0] = ListFromConcat(p[1], p[2])
+
+ def p_ValueListCont(self, p):
+ """ValueListCont : ValueList
+ |"""
+ if len(p) > 1:
+ p[0] = p[1]
+
+ # [76]
+ def p_ExtendedAttributeIdentConst(self, p):
+ """ExtendedAttributeIdentConst : identifier '=' ConstValue"""
+ p[0] = self.BuildNamed('ExtAttribute', p, 1, p[3])
+
+
+ def __init__(self, lexer, verbose=False, debug=False, mute_error=False):
+ IDLParser.__init__(self, lexer, verbose, debug, mute_error)
+
+
+def main(argv):
+ nodes = []
+ parser = IDLPPAPIParser(IDLPPAPILexer())
+ errors = 0
+
+ for filename in argv:
+ filenode = ParseFile(parser, filename)
+ if filenode:
+ errors += filenode.GetProperty('ERRORS')
+ nodes.append(filenode)
+
+ ast = IDLNode('AST', '__AST__', 0, 0, nodes)
+
+ print '\n'.join(ast.Tree(accept_props=['PROD', 'TYPE', 'VALUE']))
+ if errors:
+ print '\nFound %d errors.\n' % errors
+
+
+ return errors
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/idl_parser/run_tests.py b/chromium/tools/idl_parser/run_tests.py
new file mode 100755
index 00000000000..cf26759f7b9
--- /dev/null
+++ b/chromium/tools/idl_parser/run_tests.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import glob
+import sys
+import unittest
+
+if __name__ == '__main__':
+ suite = unittest.TestSuite()
+ for testname in glob.glob('*_test.py'):
+ print 'Adding Test: ' + testname
+ module = __import__(testname[:-3])
+ suite.addTests(unittest.defaultTestLoader.loadTestsFromModule(module))
+ result = unittest.TextTestRunner(verbosity=2).run(suite)
+ if result.wasSuccessful():
+ sys.exit(0)
+ else:
+ sys.exit(1)
diff --git a/chromium/tools/idl_parser/test_lexer/keywords.in b/chromium/tools/idl_parser/test_lexer/keywords.in
new file mode 100644
index 00000000000..11baff907f3
--- /dev/null
+++ b/chromium/tools/idl_parser/test_lexer/keywords.in
@@ -0,0 +1,37 @@
+ANY any
+ATTRIBUTE attribute
+BOOLEAN boolean
+BYTE byte
+CALLBACK callback
+CONST const
+CREATOR creator
+DATE Date
+DELETER deleter
+DICTIONARY dictionary
+DOMSTRING DOMString
+DOUBLE double
+FALSE false
+FLOAT float
+EXCEPTION exception
+GETTER getter
+IMPLEMENTS implements
+INFINITY Infinity
+INTERFACE interface
+LEGACYCALLER legacycaller
+LONG long
+NAN Nan
+NULL null
+OBJECT object
+OPTIONAL optional
+OR or
+PARTIAL partial
+READONLY readonly
+SETTER setter
+SHORT short
+STATIC static
+STRINGIFIER stringifier
+TYPEDEF typedef
+TRUE true
+UNSIGNED unsigned
+UNRESTRICTED unrestricted
+VOID void
diff --git a/chromium/tools/idl_parser/test_lexer/keywords_ppapi.in b/chromium/tools/idl_parser/test_lexer/keywords_ppapi.in
new file mode 100644
index 00000000000..62567e4852c
--- /dev/null
+++ b/chromium/tools/idl_parser/test_lexer/keywords_ppapi.in
@@ -0,0 +1,44 @@
+ANY any
+ATTRIBUTE attribute
+CALLBACK callback
+CONST const
+CREATOR creator
+DELETER deleter
+DICTIONARY dictionary
+FALSE false
+EXCEPTION exception
+GETTER getter
+IMPLEMENTS implements
+INFINITY Infinity
+INTERFACE interface
+LABEL label
+LEGACYCALLER legacycaller
+NAN Nan
+NULL null
+OPTIONAL optional
+OR or
+PARTIAL partial
+READONLY readonly
+SETTER setter
+STATIC static
+STRINGIFIER stringifier
+TYPEDEF typedef
+TRUE true
+VOID void
+CHAR char
+INT8_T int8_t
+INT16_T int16_t
+INT32_T int32_t
+INT64_T int64_t
+UINT8_T uint8_t
+UINT16_T uint16_t
+UINT32_T uint32_t
+UINT64_T uint64_t
+DOUBLE_T double_t
+FLOAT_T float_t
+MEM_T mem_t
+STR_T str_t
+CSTR_T cstr_t
+INTERFACE_T interface_t
+HANDLE_T handle_t
+PP_FILEHANDLE PP_FileHandle \ No newline at end of file
diff --git a/chromium/tools/idl_parser/test_lexer/values.in b/chromium/tools/idl_parser/test_lexer/values.in
new file mode 100644
index 00000000000..be714d08191
--- /dev/null
+++ b/chromium/tools/idl_parser/test_lexer/values.in
@@ -0,0 +1,55 @@
+integer 1 integer 123 integer 12345
+identifier A123 identifier A_A
+
+COMMENT /*XXXX*/
+COMMENT //XXXX
+
+COMMENT /*MULTI LINE*/
+
+[ [
+] ]
+* *
+. .
+( (
+) )
+{ {
+} }
+[ [
+] ]
+, ,
+; ;
+: :
+= =
++ +
+- -
+/ /
+~ ~
+| |
+& &
+^ ^
+> >
+< <
+
+ELLIPSIS ...
+
+float 1.1
+float 1e1
+float -1.1
+float -1e1
+float 1e-1
+float -1e-1
+float 1.0e1
+float -1.0e-1
+
+integer 00
+integer 01
+integer 0123
+integer 01234567
+integer 123
+integer 1234567890
+integer 0x123
+integer 0X123
+integer 0x1234567890AbCdEf
+integer 0X1234567890aBcDeF
+
+identifier blah
diff --git a/chromium/tools/idl_parser/test_lexer/values_ppapi.in b/chromium/tools/idl_parser/test_lexer/values_ppapi.in
new file mode 100644
index 00000000000..33fa577202c
--- /dev/null
+++ b/chromium/tools/idl_parser/test_lexer/values_ppapi.in
@@ -0,0 +1,50 @@
+integer 1 integer 123 integer 12345
+identifier A123 identifier A_A
+
+COMMENT /*XXXX*/
+COMMENT //XXXX
+
+COMMENT /*MULTI LINE*/
+
+[ [
+] ]
+* *
+. .
+( (
+) )
+{ {
+} }
+[ [
+] ]
+, ,
+; ;
+: :
+= =
++ +
+- -
+/ /
+~ ~
+| |
+& &
+^ ^
+> >
+< <
+
+LSHIFT <<
+RSHIFT >>
+ELLIPSIS ...
+
+float 1.1
+float 1e1
+float -1.1
+float -1e1
+float 1e-1
+float -1e-1
+float 1.0e1
+float -1.0e-1
+
+integer 00
+integer 01
+integer 0123
+
+identifier blah
diff --git a/chromium/tools/idl_parser/test_parser/callback_web.idl b/chromium/tools/idl_parser/test_parser/callback_web.idl
new file mode 100644
index 00000000000..b16b6b5751e
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/callback_web.idl
@@ -0,0 +1,116 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Callback productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+
+/* TREE
+ *Callback(VoidFunc)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ */
+callback VoidFunc = void();
+
+/* TREE
+ *Callback(VoidFuncLongErr)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Error(Unexpected ).)
+ */
+callback VoidFuncLongErr = void ( long );
+
+/* TREE
+ *Callback(VoidFuncLong)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(L1)
+ * Type()
+ * PrimitiveType(long)
+ */
+callback VoidFuncLong = void ( long L1 );
+
+/* TREE
+ *Callback(VoidFuncLongArray)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(L1)
+ * Type()
+ * PrimitiveType(long)
+ * Array()
+ */
+callback VoidFuncLongArray = void ( long[] L1 );
+
+/* TREE
+ *Callback(VoidFuncLongArray5)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(L1)
+ * Type()
+ * PrimitiveType(long)
+ * Array(5)
+ */
+callback VoidFuncLongArray5 = void ( long[5] L1 );
+
+
+/* TREE
+ *Callback(VoidFuncLongArray54)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(L1)
+ * Type()
+ * PrimitiveType(long)
+ * Array(5)
+ * Argument(L2)
+ * Type()
+ * PrimitiveType(long long)
+ * Array(4)
+ */
+callback VoidFuncLongArray54 = void ( long[5] L1, long long [4] L2 );
+
+
+/* TREE
+ *Callback(VoidFuncLongIdent)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(L1)
+ * Type()
+ * PrimitiveType(long)
+ * Array(5)
+ * Argument(L2)
+ * Type()
+ * Typeref(VoidFuncLongArray)
+ */
+callback VoidFuncLongIdent = void ( long[5] L1, VoidFuncLongArray L2 );
diff --git a/chromium/tools/idl_parser/test_parser/dictionary_web.idl b/chromium/tools/idl_parser/test_parser/dictionary_web.idl
new file mode 100644
index 00000000000..5030686fc93
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/dictionary_web.idl
@@ -0,0 +1,95 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Dictionary productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+
+/* TREE
+ *Dictionary(MyDict)
+ */
+dictionary MyDict { };
+
+/* TREE
+ *Dictionary(MyDictInherit)
+ * Inherit(Foo)
+ */
+dictionary MyDictInherit : Foo {};
+
+/* TREE
+ *Dictionary(MyDictPartial)
+ */
+partial dictionary MyDictPartial { };
+
+/* ERROR Unexpected ":" after identifier "MyDictInherit". */
+partial dictionary MyDictInherit : Foo {};
+
+/* TREE
+ *Dictionary(MyDictBig)
+ * Key(setString)
+ * Type()
+ * PrimitiveType(DOMString)
+ * Default(Foo)
+ * Key(setLong)
+ * Type()
+ * PrimitiveType(unsigned long long)
+ * Default(123)
+ * Key(unsetLong)
+ * Type()
+ * PrimitiveType(long)
+ */
+dictionary MyDictBig {
+ DOMString setString = "Foo";
+ unsigned long long setLong = 123;
+ long unsetLong;
+};
+
+
+/* ERROR Unexpected "{" after keyword "dictionary". */
+dictionary {
+ DOMString? setString = null;
+};
+
+
+/* ERROR Unexpected identifier "NoColon" after identifier "ForParent". */
+dictionary ForParent NoColon {
+ DOMString? setString = null;
+};
+
+/* TREE
+ *Dictionary(MyDictNull)
+ * Key(setString)
+ * Type()
+ * PrimitiveType(DOMString)
+ * Default(NULL)
+ */
+dictionary MyDictNull {
+ DOMString? setString = null;
+};
+
+
diff --git a/chromium/tools/idl_parser/test_parser/enum_ppapi.idl b/chromium/tools/idl_parser/test_parser/enum_ppapi.idl
new file mode 100644
index 00000000000..1b088b84009
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/enum_ppapi.idl
@@ -0,0 +1,126 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Enum productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+/* TREE
+ *Enum(MealType1)
+ * EnumItem(rice)
+ * EnumItem(noodles)
+ * EnumItem(other)
+*/
+enum MealType1 {
+ /* BUILD EnumItem (rice) */
+ rice,
+ /* BUILD EnumItem (noodles) */
+ noodles,
+ /* BUILD EnumItem(other) */
+ other
+};
+
+/* BUILD Error(Enum missing name.) */
+/* ERROR Enum missing name. */
+enum {
+ rice,
+ noodles,
+ other,
+};
+
+/* TREE
+ *Enum(MealType2)
+ * EnumItem(rice)
+ * EnumItem(noodles)
+ * EnumItem(other)
+*/
+enum MealType2 {
+ /* BUILD EnumItem(rice) */
+ rice,
+ /* BUILD EnumItem(noodles) */
+ noodles = 1,
+ /* BUILD EnumItem(other) */
+ other
+};
+
+/* BUILD Error(Unexpected identifier "noodles" after identifier "rice".) */
+/* ERROR Unexpected identifier "noodles" after identifier "rice". */
+enum MissingComma {
+ rice
+ noodles,
+ other
+};
+
+/* BUILD Error(Trailing comma in block.) */
+/* ERROR Trailing comma in block. */
+enum TrailingComma {
+ rice,
+ noodles,
+ other,
+};
+
+/* BUILD Error(Unexpected "," after ",".) */
+/* ERROR Unexpected "," after ",". */
+enum ExtraComma {
+ rice,
+ noodles,
+ ,other,
+};
+
+/* BUILD Error(Unexpected keyword "interface" after "{".) */
+/* ERROR Unexpected keyword "interface" after "{". */
+enum ExtraComma {
+ interface,
+ noodles,
+ ,other,
+};
+
+/* BUILD Error(Unexpected string "somename" after "{".) */
+/* ERROR Unexpected string "somename" after "{". */
+enum ExtraComma {
+ "somename",
+ noodles,
+ other,
+};
+
+/* BUILD Enum(MealType3) */
+enum MealType3 {
+ /* BUILD EnumItem(rice) */
+ rice = 1 << 1,
+ /* BUILD EnumItem(noodles) */
+ noodles = 0x1 << 0x2,
+ /* BUILD EnumItem(other) */
+ other = 012 << 777
+};
+
+/* BUILD Enum(MealType4) */
+enum MealType4 {
+ /* BUILD EnumItem(rice) */
+ rice = true,
+ /* BUILD EnumItem(noodles) */
+ noodles = false
+};
diff --git a/chromium/tools/idl_parser/test_parser/enum_web.idl b/chromium/tools/idl_parser/test_parser/enum_web.idl
new file mode 100644
index 00000000000..233410c5d5d
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/enum_web.idl
@@ -0,0 +1,119 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Enum productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+/* TREE
+ *Enum(MealType1)
+ * EnumItem(rice)
+ * EnumItem(noodles)
+ * EnumItem(other)
+*/
+enum MealType1 {
+ /* BUILD EnumItem (rice) */
+ "rice",
+ /* BUILD EnumItem (noodles) */
+ "noodles",
+ /* BUILD EnumItem(other) */
+ "other"
+};
+
+/* BUILD Error(Enum missing name.) */
+/* ERROR Enum missing name. */
+enum {
+ "rice",
+ "noodles",
+ "other"
+};
+
+/* TREE
+ *Enum(MealType2)
+ * EnumItem(rice)
+ * EnumItem(noodles)
+ * EnumItem(other)
+*/
+enum MealType2 {
+ /* BUILD EnumItem(rice) */
+ "rice",
+ /* BUILD EnumItem(noodles) */
+ "noodles",
+ /* BUILD EnumItem(other) */
+ "other"
+};
+
+/* BUILD Error(Unexpected string "noodles" after string "rice".) */
+/* ERROR Unexpected string "noodles" after string "rice". */
+enum MissingComma {
+ "rice"
+ "noodles",
+ "other"
+};
+
+/* BUILD Error(Trailing comma in block.) */
+/* ERROR Trailing comma in block. */
+enum TrailingComma {
+ "rice",
+ "noodles",
+ "other",
+};
+
+/* BUILD Error(Unexpected "," after ",".) */
+/* ERROR Unexpected "," after ",". */
+enum ExtraComma {
+ "rice",
+ "noodles",
+ ,"other",
+};
+
+/* BUILD Error(Unexpected keyword "interface" after "{".) */
+/* ERROR Unexpected keyword "interface" after "{". */
+enum ExtraComma {
+ interface,
+ "noodles",
+ ,"other",
+};
+
+/* BUILD Error(Unexpected identifier "somename" after "{".) */
+/* ERROR Unexpected identifier "somename" after "{". */
+enum ExtraComma {
+ somename,
+ "noodles",
+ ,"other",
+};
+
+/* BUILD Enum(MealType3) */
+enum MealType3 {
+ /* BUILD EnumItem(rice) */
+ "rice",
+ /* BUILD EnumItem(noodles) */
+ "noodles",
+ /* BUILD EnumItem(other) */
+ "other"
+};
+
diff --git a/chromium/tools/idl_parser/test_parser/exception_web.idl b/chromium/tools/idl_parser/test_parser/exception_web.idl
new file mode 100644
index 00000000000..3801a4aa7dc
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/exception_web.idl
@@ -0,0 +1,87 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Exception productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+
+/* TREE
+ *Exception(MyExc)
+ */
+exception MyExc { };
+
+/* TREE
+ *Exception(MyExcInherit)
+ * Inherit(Foo)
+ */
+exception MyExcInherit : Foo {};
+
+/* ERROR Unexpected keyword "exception" after keyword "partial". */
+partial exception MyExcPartial { };
+
+/* TREE
+ *Exception(MyExcBig)
+ * ExceptionField(MyString)
+ * Type()
+ * PrimitiveType(DOMString)
+ * Error(Unexpected "=" after identifier "ErrorSetLong".)
+ * ExceptionField(MyLong)
+ * Type()
+ * PrimitiveType(long)
+ */
+exception MyExcBig {
+ DOMString MyString;
+ unsigned long long ErrorSetLong = 123;
+ long MyLong;
+};
+
+
+/* ERROR Unexpected "{" after keyword "exception". */
+exception {
+ DOMString? setString = null;
+};
+
+
+/* ERROR Unexpected identifier "NoColon" after identifier "ForParent". */
+exception ForParent NoColon {
+ DOMString? setString = null;
+};
+
+/* TREE
+ *Exception(MyExcConst)
+ * Const(setString)
+ * PrimitiveType(DOMString)
+ * Value(NULL)
+ */
+exception MyExcConst {
+ const DOMString? setString = null;
+};
+
+
+
+
diff --git a/chromium/tools/idl_parser/test_parser/extattr_ppapi.idl b/chromium/tools/idl_parser/test_parser/extattr_ppapi.idl
new file mode 100644
index 00000000000..0206901eba6
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/extattr_ppapi.idl
@@ -0,0 +1,91 @@
+/* Copyright 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test ExtendedAttribute productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+/* TREE
+ *Interface(Foo)
+ * ExtAttributes()
+ * ExtAttribute(foo)
+ * Arguments()
+ */
+
+[foo()] interface Foo {};
+
+/* TREE
+ *Interface(Foo)
+ * ExtAttributes()
+ * ExtAttribute(foo)
+ * Values()
+ */
+
+[foo(1)] interface Foo {};
+
+/* TREE
+ *Interface(Foo)
+ * ExtAttributes()
+ * ExtAttribute(foo)
+ * Values()
+ */
+
+[foo(1 true 1.2e-3)] interface Foo {};
+
+/* TREE
+ *Interface(Foo)
+ * ExtAttributes()
+ * ExtAttribute(foo)
+ * Arguments()
+ * Error(Unexpected ).)
+ */
+
+[foo(null)] interface Foo {};
+
+/* TREE
+ *Interface(Foo)
+ * ExtAttributes()
+ * ExtAttribute(foo)
+ */
+
+[foo=1] interface Foo {};
+
+/* TREE
+ *Interface(Foo)
+ * ExtAttributes()
+ * ExtAttribute(foo)
+ */
+
+[foo=true] interface Foo {};
+
+/* TREE
+ *Interface(Foo)
+ * ExtAttributes()
+ * ExtAttribute(foo)
+ */
+
+[foo=1.2e-3] interface Foo {};
diff --git a/chromium/tools/idl_parser/test_parser/implements_web.idl b/chromium/tools/idl_parser/test_parser/implements_web.idl
new file mode 100644
index 00000000000..252dd4bb7f8
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/implements_web.idl
@@ -0,0 +1,52 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Implements productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+/* BUILD Implements(A) */
+/* PROP REFERENCE=B */
+A implements B;
+
+/* ERROR Unexpected ";" after keyword "implements". */
+A implements;
+
+/* BUILD Implements(B) */
+/* PROP REFERENCE=C */
+B implements C;
+
+/* ERROR Unexpected keyword "implements" after "]". */
+[foo] implements B;
+
+/* BUILD Implements(D) */
+/* PROP REFERENCE=E */
+D implements E;
+
+/* ERROR Unexpected keyword "implements" after comment. */
+implements C;
+
diff --git a/chromium/tools/idl_parser/test_parser/inline_ppapi.idl b/chromium/tools/idl_parser/test_parser/inline_ppapi.idl
new file mode 100644
index 00000000000..134f60d7f1b
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/inline_ppapi.idl
@@ -0,0 +1,46 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Typedef productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+/* TREE
+ *Inline(C)
+ */
+
+#inline C
+This is my block of C code
+#endinl
+
+/* TREE
+ *Inline(CC)
+ */
+#inline CC
+This is my block of CC code
+#endinl
+
diff --git a/chromium/tools/idl_parser/test_parser/interface_web.idl b/chromium/tools/idl_parser/test_parser/interface_web.idl
new file mode 100644
index 00000000000..a8a4135e5c1
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/interface_web.idl
@@ -0,0 +1,127 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Interface productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+
+/* TREE
+ *Interface(MyIFace)
+ */
+interface MyIFace { };
+
+/* TREE
+ *Interface(MyIFaceInherit)
+ * Inherit(Foo)
+ */
+interface MyIFaceInherit : Foo {};
+
+/* TREE
+ *Interface(MyIFacePartial)
+ */
+partial interface MyIFacePartial { };
+
+/* ERROR Unexpected ":" after identifier "MyIFaceInherit". */
+partial interface MyIFaceInherit : Foo {};
+
+/* TREE
+ *Interface(MyIFaceBig)
+ * Const(setString)
+ * PrimitiveType(DOMString)
+ * Value(NULL)
+ */
+interface MyIFaceBig {
+ const DOMString? setString = null;
+};
+
+/* TREE
+ *Interface(MyIFaceBig2)
+ * Const(nullValue)
+ * PrimitiveType(DOMString)
+ * Value(NULL)
+ * Const(longValue)
+ * PrimitiveType(long)
+ * Value(123)
+ * Const(longValue2)
+ * PrimitiveType(long long)
+ * Value(123)
+ * Attribute(myString)
+ * Type()
+ * PrimitiveType(DOMString)
+ * Attribute(readOnlyString)
+ * Type()
+ * PrimitiveType(DOMString)
+ * Operation(myFunction)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(myLong)
+ * Type()
+ * PrimitiveType(long long)
+ */
+interface MyIFaceBig2 {
+ const DOMString? nullValue = null;
+ const long longValue = 123;
+ const long long longValue2 = 123;
+ attribute DOMString myString;
+ readonly attribute DOMString readOnlyString;
+ void myFunction(long long myLong);
+};
+
+
+/* TREE
+ *Interface(MyIFaceSpecials)
+ * Operation(set)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(property)
+ * Type()
+ * PrimitiveType(DOMString)
+ * Operation(_unnamed_)
+ * Type()
+ * PrimitiveType(double)
+ * Arguments()
+ * Argument(property)
+ * Type()
+ * PrimitiveType(DOMString)
+ * Operation(GetFiveSix)
+ * Type()
+ * PrimitiveType(long long)
+ * Array(5)
+ * Array(6)
+ * Arguments()
+ * Argument(arg)
+ * Type()
+ * Typeref(SomeType)
+ */
+interface MyIFaceSpecials {
+ setter creator void set(DOMString property);
+ getter double (DOMString property);
+ long long [5][6] GetFiveSix(SomeType arg);
+};
diff --git a/chromium/tools/idl_parser/test_parser/label_ppapi.idl b/chromium/tools/idl_parser/test_parser/label_ppapi.idl
new file mode 100644
index 00000000000..264699dd8e9
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/label_ppapi.idl
@@ -0,0 +1,48 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Typedef productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+/* TREE
+ *Label(Chrome1)
+ * LabelItem(M13)
+ */
+label Chrome1 {
+ M13 = 0.0
+};
+
+/* TREE
+ *Label(Chrome2)
+ * LabelItem(M12)
+ * LabelItem(M13)
+ */
+label Chrome2 {
+ M12 = 1.0,
+ M13 = 2.0,
+}; \ No newline at end of file
diff --git a/chromium/tools/idl_parser/test_parser/struct_ppapi.idl b/chromium/tools/idl_parser/test_parser/struct_ppapi.idl
new file mode 100644
index 00000000000..dd017ac47f2
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/struct_ppapi.idl
@@ -0,0 +1,52 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Struct productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+/* TREE
+ *Struct(MyStruct)
+ * Member(x)
+ * Type()
+ * PrimitiveType(uint32_t)
+ * Member(y)
+ * Type()
+ * PrimitiveType(uint64_t)
+ * Member(string)
+ * ExtAttributes()
+ * ExtAttribute(fake_attribute)
+ * Type()
+ * PrimitiveType(str_t)
+ * ExtAttributes()
+ * ExtAttribute(union)
+ */
+[union] struct MyStruct {
+ uint32_t x;
+ uint64_t y;
+ [fake_attribute] str_t string;
+};
diff --git a/chromium/tools/idl_parser/test_parser/typedef_ppapi.idl b/chromium/tools/idl_parser/test_parser/typedef_ppapi.idl
new file mode 100644
index 00000000000..1a80415f596
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/typedef_ppapi.idl
@@ -0,0 +1,92 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Typedef productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+/* TREE
+ *Callback(foo)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(x)
+ * Type()
+ * PrimitiveType(int32_t)
+ */
+callback foo = void (int32_t x);
+
+/* TREE
+ *Callback(foo)
+ * Type()
+ * PrimitiveType(void)
+ * Arguments()
+ * Argument(x)
+ * Type()
+ * PrimitiveType(int32_t)
+ */
+typedef void foo(int32_t x);
+
+/* TREE
+ *Typedef(MyLong)
+ * Type()
+ * PrimitiveType(int32_t)
+ */
+typedef int32_t MyLong;
+
+/* TREE
+ *Typedef(MyLongArray)
+ * Type()
+ * PrimitiveType(str_t)
+ * Array()
+ */
+typedef str_t[] MyLongArray;
+
+/* TREE
+ *Typedef(MyLongArray5)
+ * Type()
+ * PrimitiveType(mem_t)
+ * Array(5)
+ */
+typedef mem_t[5] MyLongArray5;
+
+/* TREE
+ *Typedef(MyLongArrayN5)
+ * Type()
+ * PrimitiveType(handle_t)
+ * Array()
+ * Array(5)
+ */
+typedef handle_t[][5] MyLongArrayN5;
+
+
+/* TREE
+ *Typedef(bar)
+ * Type()
+ * Typeref(foo)
+ */
+typedef foo bar; \ No newline at end of file
diff --git a/chromium/tools/idl_parser/test_parser/typedef_web.idl b/chromium/tools/idl_parser/test_parser/typedef_web.idl
new file mode 100644
index 00000000000..ba95db7ccfe
--- /dev/null
+++ b/chromium/tools/idl_parser/test_parser/typedef_web.idl
@@ -0,0 +1,190 @@
+/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file. */
+
+/* Test Typedef productions
+
+Run with --test to generate an AST and verify that all comments accurately
+reflect the state of the Nodes.
+
+BUILD Type(Name)
+This comment signals that a node of type <Type> is created with the
+name <Name>.
+
+ERROR Error String
+This comment signals that a error of <Error String> is generated. The error
+is not assigned to a node, but are expected in order.
+
+PROP Key=Value
+This comment signals that a property has been set on the Node such that
+<Key> = <Value>.
+
+TREE
+Type(Name)
+ Type(Name)
+ Type(Name)
+ Type(Name)
+ ...
+This comment signals that a tree of nodes matching the BUILD comment
+symatics should exist. This is an exact match.
+*/
+
+
+/* TREE
+ *Typedef(MyLong)
+ * Type()
+ * PrimitiveType(long)
+ */
+typedef long MyLong;
+
+/* TREE
+ *Typedef(MyLong)
+ * ExtAttributes()
+ * ExtAttribute(foo)
+ * Type()
+ * PrimitiveType(long)
+ */
+typedef [foo] long MyLong;
+
+/* TREE
+ *Typedef(MyLongArray)
+ * Type()
+ * PrimitiveType(long)
+ * Array()
+ */
+typedef long[] MyLongArray;
+
+/* TREE
+ *Typedef(MyLongSizedArray)
+ * Type()
+ * PrimitiveType(long)
+ * Array(4)
+ */
+typedef long[4] MyLongSizedArray;
+
+/* TREE
+ *Typedef(MyLongSizedArrayArray)
+ * Type()
+ * PrimitiveType(long)
+ * Array(4)
+ * Array(5)
+ */
+typedef long[4][5] MyLongSizedArrayArray;
+
+/* TREE
+ *Typedef(MyLongArraySizedArray)
+ * Type()
+ * PrimitiveType(long)
+ * Array()
+ * Array(5)
+ */
+typedef long[][5] MyLongArraySizedArray;
+
+/* TREE
+ *Typedef(MyTypeFive)
+ * Type()
+ * Typeref(MyType)
+ * Array(5)
+ */
+typedef MyType[5] MyTypeFive;
+
+/* TREE
+ *Typedef(MyTypeUnsizedFive)
+ * Type()
+ * Typeref(MyType)
+ * Array()
+ * Array(5)
+ */
+typedef MyType[][5] MyTypeUnsizedFive;
+
+/* TREE
+ *Typedef(MyLongLong)
+ * Type()
+ * PrimitiveType(long long)
+ */
+typedef long long MyLongLong;
+
+/* TREE
+ *Typedef(MyULong)
+ * Type()
+ * PrimitiveType(unsigned long)
+ */
+typedef unsigned long MyULong;
+
+/* TREE
+ *Typedef(MyULongLong)
+ * Type()
+ * PrimitiveType(unsigned long long)
+ */
+typedef unsigned long long MyULongLong;
+
+/* TREE
+ *Typedef(MyString)
+ * Type()
+ * PrimitiveType(DOMString)
+ */
+typedef DOMString MyString;
+
+/* TREE
+ *Typedef(MyObject)
+ * Type()
+ * PrimitiveType(object)
+ */
+typedef object MyObject;
+
+/* TREE
+ *Typedef(MyDate)
+ * Type()
+ * PrimitiveType(Date)
+ */
+typedef Date MyDate;
+
+/* TREE
+ *Typedef(MyFloat)
+ * Type()
+ * PrimitiveType(float)
+ */
+typedef float MyFloat;
+
+/* TREE
+ *Typedef(MyUFloat)
+ * Type()
+ * PrimitiveType(float)
+ */
+typedef unrestricted float MyUFloat;
+
+/* TREE
+ *Typedef(MyDouble)
+ * Type()
+ * PrimitiveType(double)
+ */
+typedef double MyDouble;
+
+/* TREE
+ *Typedef(MyUDouble)
+ * Type()
+ * PrimitiveType(double)
+ */
+typedef unrestricted double MyUDouble;
+
+/* TREE
+ *Typedef(MyBool)
+ * Type()
+ * PrimitiveType(boolean)
+ */
+typedef boolean MyBool;
+
+/* TREE
+ *Typedef(MyByte)
+ * Type()
+ * PrimitiveType(byte)
+ */
+typedef byte MyByte;
+
+/* TREE
+ *Typedef(MyOctet)
+ * Type()
+ * PrimitiveType(octet)
+ */
+typedef octet MyOctet;
+
diff --git a/chromium/tools/imagediff/DEPS b/chromium/tools/imagediff/DEPS
new file mode 100644
index 00000000000..170e24fb81f
--- /dev/null
+++ b/chromium/tools/imagediff/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+third_party/libpng/png.h",
+ "+third_party/zlib/zlib.h",
+]
diff --git a/chromium/tools/imagediff/image_diff.cc b/chromium/tools/imagediff/image_diff.cc
new file mode 100644
index 00000000000..8d31795446a
--- /dev/null
+++ b/chromium/tools/imagediff/image_diff.cc
@@ -0,0 +1,381 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file input format is based loosely on
+// Tools/DumpRenderTree/ImageDiff.m
+
+// The exact format of this tool's output to stdout is important, to match
+// what the run-webkit-tests script expects.
+
+#include <algorithm>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/process/memory.h"
+#include "base/safe_numerics.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "tools/imagediff/image_diff_png.h"
+
+#if defined(OS_WIN)
+#include "windows.h"
+#endif
+
+// Causes the app to remain open, waiting for pairs of filenames on stdin.
+// The caller is then responsible for terminating this app.
+static const char kOptionPollStdin[] = "use-stdin";
+static const char kOptionGenerateDiff[] = "diff";
+
+// Return codes used by this utility.
+static const int kStatusSame = 0;
+static const int kStatusDifferent = 1;
+static const int kStatusError = 2;
+
+// Color codes.
+static const uint32 RGBA_RED = 0x000000ff;
+static const uint32 RGBA_ALPHA = 0xff000000;
+
+class Image {
+ public:
+ Image() : w_(0), h_(0) {
+ }
+
+ Image(const Image& image)
+ : w_(image.w_),
+ h_(image.h_),
+ data_(image.data_) {
+ }
+
+ bool has_image() const {
+ return w_ > 0 && h_ > 0;
+ }
+
+ int w() const {
+ return w_;
+ }
+
+ int h() const {
+ return h_;
+ }
+
+ const unsigned char* data() const {
+ return &data_.front();
+ }
+
+ // Creates the image from stdin with the given data length. On success, it
+ // will return true. On failure, no other methods should be accessed.
+ bool CreateFromStdin(size_t byte_length) {
+ if (byte_length == 0)
+ return false;
+
+ scoped_ptr<unsigned char[]> source(new unsigned char[byte_length]);
+ if (fread(source.get(), 1, byte_length, stdin) != byte_length)
+ return false;
+
+ if (!image_diff_png::DecodePNG(source.get(), byte_length,
+ &data_, &w_, &h_)) {
+ Clear();
+ return false;
+ }
+ return true;
+ }
+
+ // Creates the image from the given filename on disk, and returns true on
+ // success.
+ bool CreateFromFilename(const base::FilePath& path) {
+ FILE* f = file_util::OpenFile(path, "rb");
+ if (!f)
+ return false;
+
+ std::vector<unsigned char> compressed;
+ const int buf_size = 1024;
+ unsigned char buf[buf_size];
+ size_t num_read = 0;
+ while ((num_read = fread(buf, 1, buf_size, f)) > 0) {
+ compressed.insert(compressed.end(), buf, buf + num_read);
+ }
+
+ file_util::CloseFile(f);
+
+ if (!image_diff_png::DecodePNG(&compressed[0], compressed.size(),
+ &data_, &w_, &h_)) {
+ Clear();
+ return false;
+ }
+ return true;
+ }
+
+ void Clear() {
+ w_ = h_ = 0;
+ data_.clear();
+ }
+
+ // Returns the RGBA value of the pixel at the given location
+ uint32 pixel_at(int x, int y) const {
+ DCHECK(x >= 0 && x < w_);
+ DCHECK(y >= 0 && y < h_);
+ return *reinterpret_cast<const uint32*>(&(data_[(y * w_ + x) * 4]));
+ }
+
+ void set_pixel_at(int x, int y, uint32 color) const {
+ DCHECK(x >= 0 && x < w_);
+ DCHECK(y >= 0 && y < h_);
+ void* addr = &const_cast<unsigned char*>(&data_.front())[(y * w_ + x) * 4];
+ *reinterpret_cast<uint32*>(addr) = color;
+ }
+
+ private:
+ // pixel dimensions of the image
+ int w_, h_;
+
+ std::vector<unsigned char> data_;
+};
+
+float PercentageDifferent(const Image& baseline, const Image& actual) {
+ int w = std::min(baseline.w(), actual.w());
+ int h = std::min(baseline.h(), actual.h());
+
+ // compute pixels different in the overlap
+ int pixels_different = 0;
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ if (baseline.pixel_at(x, y) != actual.pixel_at(x, y))
+ pixels_different++;
+ }
+ }
+
+ // count pixels that are a difference in size as also being different
+ int max_w = std::max(baseline.w(), actual.w());
+ int max_h = std::max(baseline.h(), actual.h());
+
+ // ...pixels off the right side, but not including the lower right corner
+ pixels_different += (max_w - w) * h;
+
+ // ...pixels along the bottom, including the lower right corner
+ pixels_different += (max_h - h) * max_w;
+
+ // Like the WebKit ImageDiff tool, we define percentage different in terms
+ // of the size of the 'actual' bitmap.
+ float total_pixels = static_cast<float>(actual.w()) *
+ static_cast<float>(actual.h());
+ if (total_pixels == 0)
+ return 100.0f; // when the bitmap is empty, they are 100% different
+ return static_cast<float>(pixels_different) / total_pixels * 100;
+}
+
+void PrintHelp() {
+ fprintf(stderr,
+ "Usage:\n"
+ " image_diff <compare file> <reference file>\n"
+ " Compares two files on disk, returning 0 when they are the same\n"
+ " image_diff --use-stdin\n"
+ " Stays open reading pairs of filenames from stdin, comparing them,\n"
+ " and sending 0 to stdout when they are the same\n"
+ " image_diff --diff <compare file> <reference file> <output file>\n"
+ " Compares two files on disk, outputs an image that visualizes the"
+ " difference to <output file>\n");
+ /* For unfinished webkit-like-mode (see below)
+ "\n"
+ " image_diff -s\n"
+ " Reads stream input from stdin, should be EXACTLY of the format\n"
+ " \"Content-length: <byte length> <data>Content-length: ...\n"
+ " it will take as many file pairs as given, and will compare them as\n"
+ " (cmp_file, reference_file) pairs\n");
+ */
+}
+
+int CompareImages(const base::FilePath& file1, const base::FilePath& file2) {
+ Image actual_image;
+ Image baseline_image;
+
+ if (!actual_image.CreateFromFilename(file1)) {
+ fprintf(stderr, "image_diff: Unable to open file \"%" PRFilePath "\"\n",
+ file1.value().c_str());
+ return kStatusError;
+ }
+ if (!baseline_image.CreateFromFilename(file2)) {
+ fprintf(stderr, "image_diff: Unable to open file \"%" PRFilePath "\"\n",
+ file2.value().c_str());
+ return kStatusError;
+ }
+
+ float percent = PercentageDifferent(actual_image, baseline_image);
+ if (percent > 0.0) {
+ // failure: The WebKit version also writes the difference image to
+ // stdout, which seems excessive for our needs.
+ printf("diff: %01.2f%% failed\n", percent);
+ return kStatusDifferent;
+ }
+
+ // success
+ printf("diff: %01.2f%% passed\n", percent);
+ return kStatusSame;
+
+/* Untested mode that acts like WebKit's image comparator. I wrote this but
+ decided it's too complicated. We may use it in the future if it looks useful
+
+ char buffer[2048];
+ while (fgets(buffer, sizeof(buffer), stdin)) {
+
+ if (strncmp("Content-length: ", buffer, 16) == 0) {
+ char* context;
+ strtok_s(buffer, " ", &context);
+ int image_size = strtol(strtok_s(NULL, " ", &context), NULL, 10);
+
+ bool success = false;
+ if (image_size > 0 && actual_image.has_image() == 0) {
+ if (!actual_image.CreateFromStdin(image_size)) {
+ fputs("Error, input image can't be decoded.\n", stderr);
+ return 1;
+ }
+ } else if (image_size > 0 && baseline_image.has_image() == 0) {
+ if (!baseline_image.CreateFromStdin(image_size)) {
+ fputs("Error, baseline image can't be decoded.\n", stderr);
+ return 1;
+ }
+ } else {
+ fputs("Error, image size must be specified.\n", stderr);
+ return 1;
+ }
+ }
+
+ if (actual_image.has_image() && baseline_image.has_image()) {
+ float percent = PercentageDifferent(actual_image, baseline_image);
+ if (percent > 0.0) {
+ // failure: The WebKit version also writes the difference image to
+ // stdout, which seems excessive for our needs.
+ printf("diff: %01.2f%% failed\n", percent);
+ } else {
+ // success
+ printf("diff: %01.2f%% passed\n", percent);
+ }
+ actual_image.Clear();
+ baseline_image.Clear();
+ }
+
+ fflush(stdout);
+ }
+*/
+}
+
+bool CreateImageDiff(const Image& image1, const Image& image2, Image* out) {
+ int w = std::min(image1.w(), image2.w());
+ int h = std::min(image1.h(), image2.h());
+ *out = Image(image1);
+ bool same = (image1.w() == image2.w()) && (image1.h() == image2.h());
+
+ // TODO(estade): do something with the extra pixels if the image sizes
+ // are different.
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ uint32 base_pixel = image1.pixel_at(x, y);
+ if (base_pixel != image2.pixel_at(x, y)) {
+ // Set differing pixels red.
+ out->set_pixel_at(x, y, RGBA_RED | RGBA_ALPHA);
+ same = false;
+ } else {
+ // Set same pixels as faded.
+ uint32 alpha = base_pixel & RGBA_ALPHA;
+ uint32 new_pixel = base_pixel - ((alpha / 2) & RGBA_ALPHA);
+ out->set_pixel_at(x, y, new_pixel);
+ }
+ }
+ }
+
+ return same;
+}
+
+int DiffImages(const base::FilePath& file1, const base::FilePath& file2,
+ const base::FilePath& out_file) {
+ Image actual_image;
+ Image baseline_image;
+
+ if (!actual_image.CreateFromFilename(file1)) {
+ fprintf(stderr, "image_diff: Unable to open file \"%" PRFilePath "\"\n",
+ file1.value().c_str());
+ return kStatusError;
+ }
+ if (!baseline_image.CreateFromFilename(file2)) {
+ fprintf(stderr, "image_diff: Unable to open file \"%" PRFilePath "\"\n",
+ file2.value().c_str());
+ return kStatusError;
+ }
+
+ Image diff_image;
+ bool same = CreateImageDiff(baseline_image, actual_image, &diff_image);
+ if (same)
+ return kStatusSame;
+
+ std::vector<unsigned char> png_encoding;
+ image_diff_png::EncodeRGBAPNG(
+ diff_image.data(), diff_image.w(), diff_image.h(),
+ diff_image.w() * 4, &png_encoding);
+ if (file_util::WriteFile(out_file,
+ reinterpret_cast<char*>(&png_encoding.front()),
+ base::checked_numeric_cast<int>(png_encoding.size())) < 0)
+ return kStatusError;
+
+ return kStatusDifferent;
+}
+
+// It isn't strictly correct to only support ASCII paths, but this
+// program reads paths on stdin and the program that spawns it outputs
+// paths as non-wide strings anyway.
+base::FilePath FilePathFromASCII(const std::string& str) {
+#if defined(OS_WIN)
+ return base::FilePath(ASCIIToWide(str));
+#else
+ return base::FilePath(str);
+#endif
+}
+
+int main(int argc, const char* argv[]) {
+ base::EnableTerminationOnHeapCorruption();
+ CommandLine::Init(argc, argv);
+ const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
+ if (parsed_command_line.HasSwitch(kOptionPollStdin)) {
+ // Watch stdin for filenames.
+ std::string stdin_buffer;
+ base::FilePath filename1;
+ while (std::getline(std::cin, stdin_buffer)) {
+ if (stdin_buffer.empty())
+ continue;
+
+ if (!filename1.empty()) {
+ // CompareImages writes results to stdout unless an error occurred.
+ base::FilePath filename2 = FilePathFromASCII(stdin_buffer);
+ if (CompareImages(filename1, filename2) == kStatusError)
+ printf("error\n");
+ fflush(stdout);
+ filename1 = base::FilePath();
+ } else {
+ // Save the first filename in another buffer and wait for the second
+ // filename to arrive via stdin.
+ filename1 = FilePathFromASCII(stdin_buffer);
+ }
+ }
+ return 0;
+ }
+
+ const CommandLine::StringVector& args = parsed_command_line.GetArgs();
+ if (parsed_command_line.HasSwitch(kOptionGenerateDiff)) {
+ if (args.size() == 3) {
+ return DiffImages(base::FilePath(args[0]),
+ base::FilePath(args[1]),
+ base::FilePath(args[2]));
+ }
+ } else if (args.size() == 2) {
+ return CompareImages(base::FilePath(args[0]), base::FilePath(args[1]));
+ }
+
+ PrintHelp();
+ return kStatusError;
+}
diff --git a/chromium/tools/imagediff/image_diff.gyp b/chromium/tools/imagediff/image_diff.gyp
new file mode 100644
index 00000000000..c07fcf3c25d
--- /dev/null
+++ b/chromium/tools/imagediff/image_diff.gyp
@@ -0,0 +1,39 @@
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets' : [
+ {
+ 'target_name': 'image_diff',
+ 'type': 'executable',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ '../../third_party/libpng/libpng.gyp:libpng',
+ '../../third_party/zlib/zlib.gyp:zlib',
+ ],
+ 'include_dirs': [
+ '../../',
+ ],
+ 'sources': [
+ 'image_diff.cc',
+ 'image_diff_png.h',
+ 'image_diff_png.cc',
+ ],
+ 'conditions': [
+ ['OS=="android" and android_webview_build==0', {
+ # The Chromium Android port will compare images on host rather
+ # than target (a device or emulator) for performance reasons.
+ 'toolsets': ['host'],
+ }],
+ ['OS=="android" and android_webview_build==1', {
+ 'type': 'none',
+ }],
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/imagediff/image_diff_png.cc b/chromium/tools/imagediff/image_diff_png.cc
new file mode 100644
index 00000000000..a34a799811c
--- /dev/null
+++ b/chromium/tools/imagediff/image_diff_png.cc
@@ -0,0 +1,650 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/imagediff/image_diff_png.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "third_party/libpng/png.h"
+#include "third_party/zlib/zlib.h"
+
+namespace image_diff_png {
+
+// This is a duplicate of ui/gfx/codec/png_codec.cc, after removing code related
+// to Skia, that we can use when running layout tests with minimal dependencies.
+namespace {
+
+enum ColorFormat {
+ // 3 bytes per pixel (packed), in RGB order regardless of endianness.
+ // This is the native JPEG format.
+ FORMAT_RGB,
+
+ // 4 bytes per pixel, in RGBA order in memory regardless of endianness.
+ FORMAT_RGBA,
+
+ // 4 bytes per pixel, in BGRA order in memory regardless of endianness.
+ // This is the default Windows DIB order.
+ FORMAT_BGRA,
+
+ // 4 bytes per pixel, in pre-multiplied kARGB_8888_Config format. For use
+ // with directly writing to a skia bitmap.
+ FORMAT_SkBitmap
+};
+
+// Represents a comment in the tEXt ancillary chunk of the png.
+struct Comment {
+ Comment(const std::string& k, const std::string& t)
+ : key(k), text(t) {
+ }
+
+ ~Comment() {
+ };
+
+ std::string key;
+ std::string text;
+};
+
+// Converts BGRA->RGBA and RGBA->BGRA.
+void ConvertBetweenBGRAandRGBA(const unsigned char* input, int pixel_width,
+ unsigned char* output, bool* is_opaque) {
+ for (int x = 0; x < pixel_width; x++) {
+ const unsigned char* pixel_in = &input[x * 4];
+ unsigned char* pixel_out = &output[x * 4];
+ pixel_out[0] = pixel_in[2];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[0];
+ pixel_out[3] = pixel_in[3];
+ }
+}
+
+void ConvertRGBAtoRGB(const unsigned char* rgba, int pixel_width,
+ unsigned char* rgb, bool* is_opaque) {
+ for (int x = 0; x < pixel_width; x++) {
+ const unsigned char* pixel_in = &rgba[x * 4];
+ unsigned char* pixel_out = &rgb[x * 3];
+ pixel_out[0] = pixel_in[0];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[2];
+ }
+}
+
+} // namespace
+
+// Decoder --------------------------------------------------------------------
+//
+// This code is based on WebKit libpng interface (PNGImageDecoder), which is
+// in turn based on the Mozilla png decoder.
+
+namespace {
+
+// Gamma constants: We assume we're on Windows which uses a gamma of 2.2.
+const double kMaxGamma = 21474.83; // Maximum gamma accepted by png library.
+const double kDefaultGamma = 2.2;
+const double kInverseGamma = 1.0 / kDefaultGamma;
+
+class PngDecoderState {
+ public:
+ // Output is a vector<unsigned char>.
+ PngDecoderState(ColorFormat ofmt, std::vector<unsigned char>* o)
+ : output_format(ofmt),
+ output_channels(0),
+ is_opaque(true),
+ output(o),
+ row_converter(NULL),
+ width(0),
+ height(0),
+ done(false) {
+ }
+
+ ColorFormat output_format;
+ int output_channels;
+
+ // Used during the reading of an SkBitmap. Defaults to true until we see a
+ // pixel with anything other than an alpha of 255.
+ bool is_opaque;
+
+ // An intermediary buffer for decode output.
+ std::vector<unsigned char>* output;
+
+ // Called to convert a row from the library to the correct output format.
+ // When NULL, no conversion is necessary.
+ void (*row_converter)(const unsigned char* in, int w, unsigned char* out,
+ bool* is_opaque);
+
+ // Size of the image, set in the info callback.
+ int width;
+ int height;
+
+ // Set to true when we've found the end of the data.
+ bool done;
+};
+
+void ConvertRGBtoRGBA(const unsigned char* rgb, int pixel_width,
+ unsigned char* rgba, bool* is_opaque) {
+ for (int x = 0; x < pixel_width; x++) {
+ const unsigned char* pixel_in = &rgb[x * 3];
+ unsigned char* pixel_out = &rgba[x * 4];
+ pixel_out[0] = pixel_in[0];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[2];
+ pixel_out[3] = 0xff;
+ }
+}
+
+void ConvertRGBtoBGRA(const unsigned char* rgb, int pixel_width,
+ unsigned char* bgra, bool* is_opaque) {
+ for (int x = 0; x < pixel_width; x++) {
+ const unsigned char* pixel_in = &rgb[x * 3];
+ unsigned char* pixel_out = &bgra[x * 4];
+ pixel_out[0] = pixel_in[2];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[0];
+ pixel_out[3] = 0xff;
+ }
+}
+
+// Called when the png header has been read. This code is based on the WebKit
+// PNGImageDecoder
+void DecodeInfoCallback(png_struct* png_ptr, png_info* info_ptr) {
+ PngDecoderState* state = static_cast<PngDecoderState*>(
+ png_get_progressive_ptr(png_ptr));
+
+ int bit_depth, color_type, interlace_type, compression_type;
+ int filter_type, channels;
+ png_uint_32 w, h;
+ png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type,
+ &interlace_type, &compression_type, &filter_type);
+
+ // Bounds check. When the image is unreasonably big, we'll error out and
+ // end up back at the setjmp call when we set up decoding. "Unreasonably big"
+ // means "big enough that w * h * 32bpp might overflow an int"; we choose this
+ // threshold to match WebKit and because a number of places in code assume
+ // that an image's size (in bytes) fits in a (signed) int.
+ unsigned long long total_size =
+ static_cast<unsigned long long>(w) * static_cast<unsigned long long>(h);
+ if (total_size > ((1 << 29) - 1))
+ longjmp(png_jmpbuf(png_ptr), 1);
+ state->width = static_cast<int>(w);
+ state->height = static_cast<int>(h);
+
+ // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA.
+ if (color_type == PNG_COLOR_TYPE_PALETTE ||
+ (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8))
+ png_set_expand(png_ptr);
+
+ // Transparency for paletted images.
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_expand(png_ptr);
+
+ // Convert 16-bit to 8-bit.
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+
+ // Expand grayscale to RGB.
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+ // Deal with gamma and keep it under our control.
+ double gamma;
+ if (png_get_gAMA(png_ptr, info_ptr, &gamma)) {
+ if (gamma <= 0.0 || gamma > kMaxGamma) {
+ gamma = kInverseGamma;
+ png_set_gAMA(png_ptr, info_ptr, gamma);
+ }
+ png_set_gamma(png_ptr, kDefaultGamma, gamma);
+ } else {
+ png_set_gamma(png_ptr, kDefaultGamma, kInverseGamma);
+ }
+
+ // Tell libpng to send us rows for interlaced pngs.
+ if (interlace_type == PNG_INTERLACE_ADAM7)
+ png_set_interlace_handling(png_ptr);
+
+ // Update our info now
+ png_read_update_info(png_ptr, info_ptr);
+ channels = png_get_channels(png_ptr, info_ptr);
+
+ // Pick our row format converter necessary for this data.
+ if (channels == 3) {
+ switch (state->output_format) {
+ case FORMAT_RGB:
+ state->row_converter = NULL; // no conversion necessary
+ state->output_channels = 3;
+ break;
+ case FORMAT_RGBA:
+ state->row_converter = &ConvertRGBtoRGBA;
+ state->output_channels = 4;
+ break;
+ case FORMAT_BGRA:
+ state->row_converter = &ConvertRGBtoBGRA;
+ state->output_channels = 4;
+ break;
+ default:
+ NOTREACHED() << "Unknown output format";
+ break;
+ }
+ } else if (channels == 4) {
+ switch (state->output_format) {
+ case FORMAT_RGB:
+ state->row_converter = &ConvertRGBAtoRGB;
+ state->output_channels = 3;
+ break;
+ case FORMAT_RGBA:
+ state->row_converter = NULL; // no conversion necessary
+ state->output_channels = 4;
+ break;
+ case FORMAT_BGRA:
+ state->row_converter = &ConvertBetweenBGRAandRGBA;
+ state->output_channels = 4;
+ break;
+ default:
+ NOTREACHED() << "Unknown output format";
+ break;
+ }
+ } else {
+ NOTREACHED() << "Unknown input channels";
+ longjmp(png_jmpbuf(png_ptr), 1);
+ }
+
+ state->output->resize(
+ state->width * state->output_channels * state->height);
+}
+
+void DecodeRowCallback(png_struct* png_ptr, png_byte* new_row,
+ png_uint_32 row_num, int pass) {
+ PngDecoderState* state = static_cast<PngDecoderState*>(
+ png_get_progressive_ptr(png_ptr));
+
+ DCHECK(pass == 0);
+ if (static_cast<int>(row_num) > state->height) {
+ NOTREACHED() << "Invalid row";
+ return;
+ }
+
+ unsigned char* base = NULL;
+ base = &state->output->front();
+
+ unsigned char* dest = &base[state->width * state->output_channels * row_num];
+ if (state->row_converter)
+ state->row_converter(new_row, state->width, dest, &state->is_opaque);
+ else
+ memcpy(dest, new_row, state->width * state->output_channels);
+}
+
+void DecodeEndCallback(png_struct* png_ptr, png_info* info) {
+ PngDecoderState* state = static_cast<PngDecoderState*>(
+ png_get_progressive_ptr(png_ptr));
+
+ // Mark the image as complete, this will tell the Decode function that we
+ // have successfully found the end of the data.
+ state->done = true;
+}
+
+// Automatically destroys the given read structs on destruction to make
+// cleanup and error handling code cleaner.
+class PngReadStructDestroyer {
+ public:
+ PngReadStructDestroyer(png_struct** ps, png_info** pi) : ps_(ps), pi_(pi) {
+ }
+ ~PngReadStructDestroyer() {
+ png_destroy_read_struct(ps_, pi_, NULL);
+ }
+ private:
+ png_struct** ps_;
+ png_info** pi_;
+};
+
+bool BuildPNGStruct(const unsigned char* input, size_t input_size,
+ png_struct** png_ptr, png_info** info_ptr) {
+ if (input_size < 8)
+ return false; // Input data too small to be a png
+
+ // Have libpng check the signature, it likes the first 8 bytes.
+ if (png_sig_cmp(const_cast<unsigned char*>(input), 0, 8) != 0)
+ return false;
+
+ *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!*png_ptr)
+ return false;
+
+ *info_ptr = png_create_info_struct(*png_ptr);
+ if (!*info_ptr) {
+ png_destroy_read_struct(png_ptr, NULL, NULL);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+// static
+bool Decode(const unsigned char* input, size_t input_size,
+ ColorFormat format, std::vector<unsigned char>* output,
+ int* w, int* h) {
+ png_struct* png_ptr = NULL;
+ png_info* info_ptr = NULL;
+ if (!BuildPNGStruct(input, input_size, &png_ptr, &info_ptr))
+ return false;
+
+ PngReadStructDestroyer destroyer(&png_ptr, &info_ptr);
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ // The destroyer will ensure that the structures are cleaned up in this
+ // case, even though we may get here as a jump from random parts of the
+ // PNG library called below.
+ return false;
+ }
+
+ PngDecoderState state(format, output);
+
+ png_set_progressive_read_fn(png_ptr, &state, &DecodeInfoCallback,
+ &DecodeRowCallback, &DecodeEndCallback);
+ png_process_data(png_ptr,
+ info_ptr,
+ const_cast<unsigned char*>(input),
+ input_size);
+
+ if (!state.done) {
+ // Fed it all the data but the library didn't think we got all the data, so
+ // this file must be truncated.
+ output->clear();
+ return false;
+ }
+
+ *w = state.width;
+ *h = state.height;
+ return true;
+}
+
+// Encoder --------------------------------------------------------------------
+//
+// This section of the code is based on nsPNGEncoder.cpp in Mozilla
+// (Copyright 2005 Google Inc.)
+
+namespace {
+
+// Passed around as the io_ptr in the png structs so our callbacks know where
+// to write data.
+struct PngEncoderState {
+ explicit PngEncoderState(std::vector<unsigned char>* o) : out(o) {}
+ std::vector<unsigned char>* out;
+};
+
+// Called by libpng to flush its internal buffer to ours.
+void EncoderWriteCallback(png_structp png, png_bytep data, png_size_t size) {
+ PngEncoderState* state = static_cast<PngEncoderState*>(png_get_io_ptr(png));
+ DCHECK(state->out);
+
+ size_t old_size = state->out->size();
+ state->out->resize(old_size + size);
+ memcpy(&(*state->out)[old_size], data, size);
+}
+
+void FakeFlushCallback(png_structp png) {
+ // We don't need to perform any flushing since we aren't doing real IO, but
+ // we're required to provide this function by libpng.
+}
+
+void ConvertBGRAtoRGB(const unsigned char* bgra, int pixel_width,
+ unsigned char* rgb, bool* is_opaque) {
+ for (int x = 0; x < pixel_width; x++) {
+ const unsigned char* pixel_in = &bgra[x * 4];
+ unsigned char* pixel_out = &rgb[x * 3];
+ pixel_out[0] = pixel_in[2];
+ pixel_out[1] = pixel_in[1];
+ pixel_out[2] = pixel_in[0];
+ }
+}
+
+#ifdef PNG_TEXT_SUPPORTED
+
+inline char* strdup(const char* str) {
+#if defined(OS_WIN)
+ return _strdup(str);
+#else
+ return ::strdup(str);
+#endif
+}
+
+class CommentWriter {
+ public:
+ explicit CommentWriter(const std::vector<Comment>& comments)
+ : comments_(comments),
+ png_text_(new png_text[comments.size()]) {
+ for (size_t i = 0; i < comments.size(); ++i)
+ AddComment(i, comments[i]);
+ }
+
+ ~CommentWriter() {
+ for (size_t i = 0; i < comments_.size(); ++i) {
+ free(png_text_[i].key);
+ free(png_text_[i].text);
+ }
+ delete [] png_text_;
+ }
+
+ bool HasComments() {
+ return !comments_.empty();
+ }
+
+ png_text* get_png_text() {
+ return png_text_;
+ }
+
+ int size() {
+ return static_cast<int>(comments_.size());
+ }
+
+ private:
+ void AddComment(size_t pos, const Comment& comment) {
+ png_text_[pos].compression = PNG_TEXT_COMPRESSION_NONE;
+ // A PNG comment's key can only be 79 characters long.
+ DCHECK(comment.key.length() < 79);
+ png_text_[pos].key = strdup(comment.key.substr(0, 78).c_str());
+ png_text_[pos].text = strdup(comment.text.c_str());
+ png_text_[pos].text_length = comment.text.length();
+#ifdef PNG_iTXt_SUPPORTED
+ png_text_[pos].itxt_length = 0;
+ png_text_[pos].lang = 0;
+ png_text_[pos].lang_key = 0;
+#endif
+ }
+
+ const std::vector<Comment> comments_;
+ png_text* png_text_;
+};
+#endif // PNG_TEXT_SUPPORTED
+
+// The type of functions usable for converting between pixel formats.
+typedef void (*FormatConverter)(const unsigned char* in, int w,
+ unsigned char* out, bool* is_opaque);
+
+// libpng uses a wacky setjmp-based API, which makes the compiler nervous.
+// We constrain all of the calls we make to libpng where the setjmp() is in
+// place to this function.
+// Returns true on success.
+bool DoLibpngWrite(png_struct* png_ptr, png_info* info_ptr,
+ PngEncoderState* state,
+ int width, int height, int row_byte_width,
+ const unsigned char* input, int compression_level,
+ int png_output_color_type, int output_color_components,
+ FormatConverter converter,
+ const std::vector<Comment>& comments) {
+#ifdef PNG_TEXT_SUPPORTED
+ CommentWriter comment_writer(comments);
+#endif
+ unsigned char* row_buffer = NULL;
+
+ // Make sure to not declare any locals here -- locals in the presence
+ // of setjmp() in C++ code makes gcc complain.
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ delete[] row_buffer;
+ return false;
+ }
+
+ png_set_compression_level(png_ptr, compression_level);
+
+ // Set our callback for libpng to give us the data.
+ png_set_write_fn(png_ptr, state, EncoderWriteCallback, FakeFlushCallback);
+
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8, png_output_color_type,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+
+#ifdef PNG_TEXT_SUPPORTED
+ if (comment_writer.HasComments()) {
+ png_set_text(png_ptr, info_ptr, comment_writer.get_png_text(),
+ comment_writer.size());
+ }
+#endif
+
+ png_write_info(png_ptr, info_ptr);
+
+ if (!converter) {
+ // No conversion needed, give the data directly to libpng.
+ for (int y = 0; y < height; y ++) {
+ png_write_row(png_ptr,
+ const_cast<unsigned char*>(&input[y * row_byte_width]));
+ }
+ } else {
+ // Needs conversion using a separate buffer.
+ row_buffer = new unsigned char[width * output_color_components];
+ for (int y = 0; y < height; y ++) {
+ converter(&input[y * row_byte_width], width, row_buffer, NULL);
+ png_write_row(png_ptr, row_buffer);
+ }
+ delete[] row_buffer;
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ return true;
+}
+
+} // namespace
+
+// static
+bool EncodeWithCompressionLevel(const unsigned char* input, ColorFormat format,
+ const int width, const int height,
+ int row_byte_width,
+ bool discard_transparency,
+ const std::vector<Comment>& comments,
+ int compression_level,
+ std::vector<unsigned char>* output) {
+ // Run to convert an input row into the output row format, NULL means no
+ // conversion is necessary.
+ FormatConverter converter = NULL;
+
+ int input_color_components, output_color_components;
+ int png_output_color_type;
+ switch (format) {
+ case FORMAT_RGB:
+ input_color_components = 3;
+ output_color_components = 3;
+ png_output_color_type = PNG_COLOR_TYPE_RGB;
+ discard_transparency = false;
+ break;
+
+ case FORMAT_RGBA:
+ input_color_components = 4;
+ if (discard_transparency) {
+ output_color_components = 3;
+ png_output_color_type = PNG_COLOR_TYPE_RGB;
+ converter = ConvertRGBAtoRGB;
+ } else {
+ output_color_components = 4;
+ png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ converter = NULL;
+ }
+ break;
+
+ case FORMAT_BGRA:
+ input_color_components = 4;
+ if (discard_transparency) {
+ output_color_components = 3;
+ png_output_color_type = PNG_COLOR_TYPE_RGB;
+ converter = ConvertBGRAtoRGB;
+ } else {
+ output_color_components = 4;
+ png_output_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ converter = ConvertBetweenBGRAandRGBA;
+ }
+ break;
+
+ default:
+ NOTREACHED() << "Unknown pixel format";
+ return false;
+ }
+
+ // Row stride should be at least as long as the length of the data.
+ DCHECK(input_color_components * width <= row_byte_width);
+
+ png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+ if (!png_ptr)
+ return false;
+ png_info* info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_write_struct(&png_ptr, NULL);
+ return false;
+ }
+
+ PngEncoderState state(output);
+ bool success = DoLibpngWrite(png_ptr, info_ptr, &state,
+ width, height, row_byte_width,
+ input, compression_level, png_output_color_type,
+ output_color_components, converter, comments);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ return success;
+}
+
+// static
+bool Encode(const unsigned char* input, ColorFormat format,
+ const int width, const int height, int row_byte_width,
+ bool discard_transparency,
+ const std::vector<Comment>& comments,
+ std::vector<unsigned char>* output) {
+ return EncodeWithCompressionLevel(input, format, width, height,
+ row_byte_width,
+ discard_transparency,
+ comments, Z_DEFAULT_COMPRESSION,
+ output);
+}
+
+// Decode a PNG into an RGBA pixel array.
+bool DecodePNG(const unsigned char* input, size_t input_size,
+ std::vector<unsigned char>* output,
+ int* width, int* height) {
+ return Decode(input, input_size, FORMAT_RGBA, output, width, height);
+}
+
+// Encode an RGBA pixel array into a PNG.
+bool EncodeRGBAPNG(const unsigned char* input,
+ int width,
+ int height,
+ int row_byte_width,
+ std::vector<unsigned char>* output) {
+ return Encode(input, FORMAT_RGBA,
+ width, height, row_byte_width, false,
+ std::vector<Comment>(), output);
+}
+
+// Encode an BGRA pixel array into a PNG.
+bool EncodeBGRAPNG(const unsigned char* input,
+ int width,
+ int height,
+ int row_byte_width,
+ bool discard_transparency,
+ std::vector<unsigned char>* output) {
+ return Encode(input, FORMAT_BGRA,
+ width, height, row_byte_width, discard_transparency,
+ std::vector<Comment>(), output);
+}
+
+} // image_diff_png
diff --git a/chromium/tools/imagediff/image_diff_png.h b/chromium/tools/imagediff/image_diff_png.h
new file mode 100644
index 00000000000..c371337f99d
--- /dev/null
+++ b/chromium/tools/imagediff/image_diff_png.h
@@ -0,0 +1,35 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_IMAGEDIFF_IMAGE_DIFF_PNG_H_
+#define TOOLS_IMAGEDIFF_IMAGE_DIFF_PNG_H_
+
+#include <string>
+#include <vector>
+
+namespace image_diff_png {
+
+// Decode a PNG into an RGBA pixel array.
+bool DecodePNG(const unsigned char* input, size_t input_size,
+ std::vector<unsigned char>* output,
+ int* width, int* height);
+
+// Encode an RGBA pixel array into a PNG.
+bool EncodeRGBAPNG(const unsigned char* input,
+ int width,
+ int height,
+ int row_byte_width,
+ std::vector<unsigned char>* output);
+
+// Encode an BGRA pixel array into a PNG.
+bool EncodeBGRAPNG(const unsigned char* input,
+ int width,
+ int height,
+ int row_byte_width,
+ bool discard_transparency,
+ std::vector<unsigned char>* output);
+
+} // namespace image_diff_png
+
+#endif // TOOLS_IMAGEDIFF_IMAGE_DIFF_PNG_H_
diff --git a/chromium/tools/include_tracer.py b/chromium/tools/include_tracer.py
new file mode 100755
index 00000000000..df30c65c005
--- /dev/null
+++ b/chromium/tools/include_tracer.py
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# based on an almost identical script by: jyrki@google.com (Jyrki Alakuijala)
+
+"""Prints out include dependencies in chrome.
+
+Since it ignores defines, it gives just a rough estimation of file size.
+
+Usage:
+ tools/include_tracer.py chrome/browser/ui/browser.h
+"""
+
+import os
+import sys
+
+# Created by copying the command line for prerender_browsertest.cc, replacing
+# spaces with newlines, and dropping everything except -F and -I switches.
+# TODO(port): Add windows, linux directories.
+INCLUDE_PATHS = [
+ '',
+ 'gpu',
+ 'skia/config',
+ 'skia/ext',
+ 'testing/gmock/include',
+ 'testing/gtest/include',
+ 'third_party/GTM',
+ 'third_party/WebKit/Source',
+ 'third_party/WebKit/Source/wtf',
+ 'third_party/WebKit/Source/core',
+ 'third_party/WebKit/Source/core/accessibility',
+ 'third_party/WebKit/Source/core/accessibility/chromium',
+ 'third_party/WebKit/Source/core/bindings',
+ 'third_party/WebKit/Source/core/bindings/generic',
+ 'third_party/WebKit/Source/core/bindings/v8',
+ 'third_party/WebKit/Source/core/bindings/v8/custom',
+ 'third_party/WebKit/Source/core/bindings/v8/specialization',
+ 'third_party/WebKit/Source/core/bridge',
+ 'third_party/WebKit/Source/core/bridge/jni',
+ 'third_party/WebKit/Source/core/bridge/jni/v8',
+ 'third_party/WebKit/Source/core/css',
+ 'third_party/WebKit/Source/core/dom',
+ 'third_party/WebKit/Source/core/dom/default',
+ 'third_party/WebKit/Source/core/editing',
+ 'third_party/WebKit/Source/core/fileapi',
+ 'third_party/WebKit/Source/core/history',
+ 'third_party/WebKit/Source/core/html',
+ 'third_party/WebKit/Source/core/html/canvas',
+ 'third_party/WebKit/Source/core/html/parser',
+ 'third_party/WebKit/Source/core/html/shadow',
+ 'third_party/WebKit/Source/core/inspector',
+ 'third_party/WebKit/Source/core/loader',
+ 'third_party/WebKit/Source/core/loader/appcache',
+ 'third_party/WebKit/Source/core/loader/archive',
+ 'third_party/WebKit/Source/core/loader/cache',
+ 'third_party/WebKit/Source/core/loader/icon',
+ 'third_party/WebKit/Source/core/mathml',
+ 'third_party/WebKit/Source/core/notifications',
+ 'third_party/WebKit/Source/core/page',
+ 'third_party/WebKit/Source/core/page/animation',
+ 'third_party/WebKit/Source/core/page/chromium',
+ 'third_party/WebKit/Source/core/platform',
+ 'third_party/WebKit/Source/core/platform/animation',
+ 'third_party/WebKit/Source/core/platform/audio',
+ 'third_party/WebKit/Source/core/platform/audio/chromium',
+ 'third_party/WebKit/Source/core/platform/audio/mac',
+ 'third_party/WebKit/Source/core/platform/chromium',
+ 'third_party/WebKit/Source/core/platform/cocoa',
+ 'third_party/WebKit/Source/core/platform/graphics',
+ 'third_party/WebKit/Source/core/platform/graphics/cg',
+ 'third_party/WebKit/Source/core/platform/graphics/chromium',
+ 'third_party/WebKit/Source/core/platform/graphics/cocoa',
+ 'third_party/WebKit/Source/core/platform/graphics/filters',
+ 'third_party/WebKit/Source/core/platform/graphics/gpu',
+ 'third_party/WebKit/Source/core/platform/graphics/mac',
+ 'third_party/WebKit/Source/core/platform/graphics/opentype',
+ 'third_party/WebKit/Source/core/platform/graphics/skia',
+ 'third_party/WebKit/Source/core/platform/graphics/transforms',
+ 'third_party/WebKit/Source/core/platform/image-decoders',
+ 'third_party/WebKit/Source/core/platform/image-decoders/bmp',
+ 'third_party/WebKit/Source/core/platform/image-decoders/gif',
+ 'third_party/WebKit/Source/core/platform/image-decoders/ico',
+ 'third_party/WebKit/Source/core/platform/image-decoders/jpeg',
+ 'third_party/WebKit/Source/core/platform/image-decoders/png',
+ 'third_party/WebKit/Source/core/platform/image-decoders/skia',
+ 'third_party/WebKit/Source/core/platform/image-decoders/webp',
+ 'third_party/WebKit/Source/core/platform/image-decoders/xbm',
+ 'third_party/WebKit/Source/core/platform/image-encoders/skia',
+ 'third_party/WebKit/Source/core/platform/mac',
+ 'third_party/WebKit/Source/core/platform/mock',
+ 'third_party/WebKit/Source/core/platform/network',
+ 'third_party/WebKit/Source/core/platform/network/chromium',
+ 'third_party/WebKit/Source/core/platform/sql',
+ 'third_party/WebKit/Source/core/platform/text',
+ 'third_party/WebKit/Source/core/platform/text/mac',
+ 'third_party/WebKit/Source/core/platform/text/transcoder',
+ 'third_party/WebKit/Source/core/plugins',
+ 'third_party/WebKit/Source/core/plugins/chromium',
+ 'third_party/WebKit/Source/core/rendering',
+ 'third_party/WebKit/Source/core/rendering/style',
+ 'third_party/WebKit/Source/core/rendering/svg',
+ 'third_party/WebKit/Source/core/storage',
+ 'third_party/WebKit/Source/core/storage/chromium',
+ 'third_party/WebKit/Source/core/svg',
+ 'third_party/WebKit/Source/core/svg/animation',
+ 'third_party/WebKit/Source/core/svg/graphics',
+ 'third_party/WebKit/Source/core/svg/graphics/filters',
+ 'third_party/WebKit/Source/core/svg/properties',
+ 'third_party/WebKit/Source/core/webaudio',
+ 'third_party/WebKit/Source/core/websockets',
+ 'third_party/WebKit/Source/core/workers',
+ 'third_party/WebKit/Source/core/xml',
+ 'third_party/WebKit/Source/public',
+ 'third_party/WebKit/Source/web',
+ 'third_party/cld',
+ 'third_party/icu/public/common',
+ 'third_party/icu/public/i18n',
+ 'third_party/npapi',
+ 'third_party/npapi/bindings',
+ 'third_party/protobuf',
+ 'third_party/protobuf/src',
+ 'third_party/skia/gpu/include',
+ 'third_party/skia/include/config',
+ 'third_party/skia/include/core',
+ 'third_party/skia/include/effects',
+ 'third_party/skia/include/gpu',
+ 'third_party/skia/include/pdf',
+ 'third_party/skia/include/ports',
+ 'v8/include',
+ 'xcodebuild/Debug/include',
+ 'xcodebuild/DerivedSources/Debug/chrome',
+ 'xcodebuild/DerivedSources/Debug/policy',
+ 'xcodebuild/DerivedSources/Debug/protoc_out',
+ 'xcodebuild/DerivedSources/Debug/webkit',
+ 'xcodebuild/DerivedSources/Debug/webkit/bindings',
+]
+
+
+def Walk(seen, filename, parent, indent):
+ """Returns the size of |filename| plus the size of all files included by
+ |filename| and prints the include tree of |filename| to stdout. Every file
+ is visited at most once.
+ """
+ total_bytes = 0
+
+ # .proto(devel) filename translation
+ if filename.endswith('.pb.h'):
+ basename = filename[:-5]
+ if os.path.exists(basename + '.proto'):
+ filename = basename + '.proto'
+ else:
+ print 'could not find ', filename
+
+ # Show and count files only once.
+ if filename in seen:
+ return total_bytes
+ seen.add(filename)
+
+ # Display the paths.
+ print ' ' * indent + filename
+
+ # Skip system includes.
+ if filename[0] == '<':
+ return total_bytes
+
+ # Find file in all include paths.
+ resolved_filename = filename
+ for root in INCLUDE_PATHS + [os.path.dirname(parent)]:
+ if os.path.exists(os.path.join(root, filename)):
+ resolved_filename = os.path.join(root, filename)
+ break
+
+ # Recurse.
+ if os.path.exists(resolved_filename):
+ lines = open(resolved_filename).readlines()
+ else:
+ print ' ' * (indent + 2) + "-- not found"
+ lines = []
+ for line in lines:
+ line = line.strip()
+ if line.startswith('#include "'):
+ total_bytes += Walk(
+ seen, line.split('"')[1], resolved_filename, indent + 2)
+ elif line.startswith('#include '):
+ include = '<' + line.split('<')[1].split('>')[0] + '>'
+ total_bytes += Walk(
+ seen, include, resolved_filename, indent + 2)
+ elif line.startswith('import '):
+ total_bytes += Walk(
+ seen, line.split('"')[1], resolved_filename, indent + 2)
+ return total_bytes + len("".join(lines))
+
+
+def main():
+ bytes = Walk(set(), sys.argv[1], '', 0)
+ print
+ print float(bytes) / (1 << 20), "megabytes of chrome source"
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/ipc_messages_log.py b/chromium/tools/ipc_messages_log.py
new file mode 100755
index 00000000000..26284d1cd60
--- /dev/null
+++ b/chromium/tools/ipc_messages_log.py
@@ -0,0 +1,168 @@
+#!/usr/bin/python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""""Processes a log file and resolves IPC message identifiers.
+
+Resolves IPC messages of the form [unknown type NNNNNN] to named IPC messages.
+
+e.g. logfile containing
+
+I/stderr ( 3915): ipc 3915.3.1370207904 2147483647 S [unknown type 66372]
+
+will be transformed to:
+
+I/stderr ( 3915): ipc 3915.3.1370207904 2147483647 S ViewMsg_SetCSSColors
+
+In order to find the message header files efficiently, it requires that
+Chromium is checked out using git.
+"""
+
+import optparse
+import os
+import re
+import subprocess
+import sys
+
+
+def _SourceDir():
+ """Get chromium's source directory."""
+ return os.path.join(sys.path[0], '..')
+
+
+def _ReadLines(f):
+ """Read from file f and generate right-stripped lines."""
+ for line in f:
+ yield line.rstrip()
+
+
+def _GetMsgStartTable():
+ """Read MsgStart enumeration from ipc/ipc_message_utils.h.
+
+ Determines the message type identifiers by reading.
+ header file ipc/ipc_message_utils.h and looking for
+ enum IPCMessageStart. Assumes following code format in header file:
+ enum IPCMessageStart {
+ Type1MsgStart ...,
+ Type2MsgStart,
+ };
+
+ Returns:
+ A dictionary mapping StartName to enumeration value.
+ """
+ ipc_message_file = _SourceDir() + '/ipc/ipc_message_utils.h'
+ ipc_message_lines = _ReadLines(open(ipc_message_file))
+ is_msg_start = False
+ count = 0
+ msg_start_table = dict()
+ for line in ipc_message_lines:
+ if is_msg_start:
+ if line.strip() == '};':
+ break
+ msgstart_index = line.find('MsgStart')
+ msg_type = line[:msgstart_index] + 'MsgStart'
+ msg_start_table[msg_type.strip()] = count
+ count+=1
+ elif line.strip() == 'enum IPCMessageStart {':
+ is_msg_start = True
+
+ return msg_start_table
+
+
+def _FindMessageHeaderFiles():
+ """Look through the source directory for *_messages.h."""
+ os.chdir(_SourceDir())
+ pipe = subprocess.Popen(['git', 'ls-files', '--', '*_messages.h'],
+ stdout=subprocess.PIPE)
+ return _ReadLines(pipe.stdout)
+
+
+def _GetMsgId(msg_start, line_number, msg_start_table):
+ """Construct the meessage id given the msg_start and the line number."""
+ hex_str = '%x%04x' % (msg_start_table[msg_start], line_number)
+ return int(hex_str, 16)
+
+
+def _ReadHeaderFile(f, msg_start_table, msg_map):
+ """Read a header file and construct a map from message_id to message name."""
+ msg_def_re = re.compile(
+ '^IPC_(?:SYNC_)?MESSAGE_[A-Z0-9_]+\(([A-Za-z0-9_]+).*')
+ msg_start_re = re.compile(
+ '^\s*#define\s+IPC_MESSAGE_START\s+([a-zA-Z0-9_]+MsgStart).*')
+ msg_start = None
+ msg_name = None
+ line_number = 0
+
+ for line in f:
+ line_number+=1
+ match = re.match(msg_start_re, line)
+ if match:
+ msg_start = match.group(1)
+ # print "msg_start = " + msg_start
+ match = re.match(msg_def_re, line)
+ if match:
+ msg_name = match.group(1)
+ # print "msg_name = " + msg_name
+ if msg_start and msg_name:
+ msg_id = _GetMsgId(msg_start, line_number, msg_start_table)
+ msg_map[msg_id] = msg_name
+ return msg_map
+
+
+def _ResolveMsg(msg_type, msg_map):
+ """Fully resolve a message type to a name."""
+ if msg_type in msg_map:
+ return msg_map[msg_type]
+ else:
+ return '[Unknown message %d (0x%x)]x' % (msg_type, msg_type)
+
+
+def _ProcessLog(f, msg_map):
+ """Read lines from f and resolve the IPC messages according to msg_map."""
+ unknown_msg_re = re.compile('\[unknown type (\d+)\]')
+ for line in f:
+ line = line.rstrip()
+ match = re.search(unknown_msg_re, line)
+ if match:
+ line = re.sub(unknown_msg_re,
+ _ResolveMsg(int(match.group(1)), msg_map),
+ line)
+ print line
+
+
+def _GetMsgMap():
+ """Returns a dictionary mapping from message number to message name."""
+ msg_start_table = _GetMsgStartTable()
+ msg_map = dict()
+ for header_file in _FindMessageHeaderFiles():
+ _ReadHeaderFile(open(header_file),
+ msg_start_table,
+ msg_map)
+ return msg_map
+
+
+def main():
+ """Processes one or more log files with IPC logging messages.
+
+ Replaces '[unknown type NNNNNN]' with resolved
+ IPC messages.
+
+ Reads from standard input if no log files specified on the
+ command line.
+ """
+ parser = optparse.OptionParser('usage: %prog [LOGFILE...]')
+ (_, args) = parser.parse_args()
+
+ msg_map = _GetMsgMap()
+ log_files = args
+
+ if log_files:
+ for log_file in log_files:
+ _ProcessLog(open(log_file), msg_map)
+ else:
+ _ProcessLog(sys.stdin, msg_map)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/json_comment_eater/everything.json b/chromium/tools/json_comment_eater/everything.json
new file mode 100644
index 00000000000..31db5032966
--- /dev/null
+++ b/chromium/tools/json_comment_eater/everything.json
@@ -0,0 +1,13 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Test API.
+{ "namespace": "test",
+ "comments": "yo", // Comments all have a // in them.
+ "strings": "yes", // Comment with "strings" and " character
+ "escaped\"": "string\"isescaped",
+ "more//": "\"more",
+ "so\\many": "\\\\escapes\\\\\"whoa",
+ "comment//inmiddle": "of string"
+}
diff --git a/chromium/tools/json_comment_eater/everything_expected.json b/chromium/tools/json_comment_eater/everything_expected.json
new file mode 100644
index 00000000000..3fa02c15dc7
--- /dev/null
+++ b/chromium/tools/json_comment_eater/everything_expected.json
@@ -0,0 +1,13 @@
+
+
+
+
+
+{ "namespace": "test",
+ "comments": "yo",
+ "strings": "yes",
+ "escaped\"": "string\"isescaped",
+ "more//": "\"more",
+ "so\\many": "\\\\escapes\\\\\"whoa",
+ "comment//inmiddle": "of string"
+}
diff --git a/chromium/tools/json_comment_eater/json_comment_eater.py b/chromium/tools/json_comment_eater/json_comment_eater.py
new file mode 100644
index 00000000000..85874649980
--- /dev/null
+++ b/chromium/tools/json_comment_eater/json_comment_eater.py
@@ -0,0 +1,60 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+'''Utility to remove comments from JSON files so that they can be parsed by
+json.loads.
+'''
+
+def _Rcount(string, chars):
+ '''Returns the number of consecutive characters from |chars| that occur at the
+ end of |string|.
+ '''
+ return len(string) - len(string.rstrip(chars))
+
+def _FindNextToken(string, tokens, start):
+ '''Finds the next token in |tokens| that occurs in |string| from |start|.
+ Returns a tuple (index, token key).
+ '''
+ min_index, min_key = (-1, None)
+ for k in tokens:
+ index = string.find(k, start)
+ if index != -1 and (min_index == -1 or index < min_index):
+ min_index, min_key = (index, k)
+ return (min_index, min_key)
+
+def _ReadString(input, start, output):
+ output.append('"')
+ start_range, end_range = (start, input.find('"', start))
+ # \" escapes the ", \\" doesn't, \\\" does, etc.
+ while (end_range != -1 and
+ _Rcount(input[start_range:end_range], '\\') % 2 == 1):
+ start_range, end_range = (end_range, input.find('"', end_range + 1))
+ if end_range == -1:
+ return start_range + 1
+ output.append(input[start:end_range + 1])
+ return end_range + 1
+
+def _ReadComment(input, start, output):
+ eol_tokens = ('\n', '\r')
+ eol_token_index, eol_token = _FindNextToken(input, eol_tokens, start)
+ if eol_token is None:
+ return len(input)
+ output.append(eol_token)
+ return eol_token_index + len(eol_token)
+
+def Nom(input):
+ token_actions = {
+ '"': _ReadString,
+ '//': _ReadComment,
+ }
+ output = []
+ pos = 0
+ while pos < len(input):
+ token_index, token = _FindNextToken(input, token_actions.keys(), pos)
+ if token is None:
+ output.append(input[pos:])
+ break
+ output.append(input[pos:token_index])
+ pos = token_actions[token](input, token_index + len(token), output)
+ return ''.join(output)
diff --git a/chromium/tools/json_comment_eater/json_comment_eater_test.py b/chromium/tools/json_comment_eater/json_comment_eater_test.py
new file mode 100755
index 00000000000..5a230eb2802
--- /dev/null
+++ b/chromium/tools/json_comment_eater/json_comment_eater_test.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from json_comment_eater import Nom
+import unittest
+
+class JsonCommentEaterTest(unittest.TestCase):
+ def _Load(self, test_name):
+ '''Loads the input and expected output for |test_name| as given by reading
+ in |test_name|.json and |test_name|_expected.json, and returns the string
+ contents as a tuple in that order.
+ '''
+ def read(file_name):
+ with open(file_name, 'r') as f:
+ return f.read()
+ return [read(pattern % test_name)
+ for pattern in ('%s.json', '%s_expected.json')]
+
+ def testEverything(self):
+ json, expected_json = self._Load('everything')
+ self.assertEqual(expected_json, Nom(json))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/PRESUBMIT.py b/chromium/tools/json_schema_compiler/PRESUBMIT.py
new file mode 100644
index 00000000000..b98649b3b4b
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/PRESUBMIT.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit script for changes affecting tools/json_schema_compiler/
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into gcl.
+"""
+
+WHITELIST = [ r'.+_test.py$' ]
+
+def CheckChangeOnUpload(input_api, output_api):
+ return input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, '.', whitelist=WHITELIST)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, '.', whitelist=WHITELIST)
diff --git a/chromium/tools/json_schema_compiler/api_gen_util.gyp b/chromium/tools/json_schema_compiler/api_gen_util.gyp
new file mode 100644
index 00000000000..54966cc6030
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/api_gen_util.gyp
@@ -0,0 +1,20 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [{
+ 'target_name': 'api_gen_util',
+ 'type': 'static_library',
+ 'sources': [
+ 'util.cc',
+ ],
+ 'dependencies': ['<(DEPTH)/base/base.gyp:base'],
+ 'include_dirs': [
+ '<(DEPTH)',
+ ],
+ }],
+}
diff --git a/chromium/tools/json_schema_compiler/cc_generator.py b/chromium/tools/json_schema_compiler/cc_generator.py
new file mode 100644
index 00000000000..d7d565e3846
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/cc_generator.py
@@ -0,0 +1,943 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from code import Code
+from model import PropertyType, Type
+import cpp_util
+import model
+import schema_util
+import sys
+import util_cc_helper
+
+class CCGenerator(object):
+ def __init__(self, type_generator, cpp_namespace):
+ self._type_generator = type_generator
+ self._cpp_namespace = cpp_namespace
+
+ def Generate(self, namespace):
+ return _Generator(namespace,
+ self._type_generator,
+ self._cpp_namespace).Generate()
+
+class _Generator(object):
+ """A .cc generator for a namespace.
+ """
+ def __init__(self, namespace, cpp_type_generator, cpp_namespace):
+ self._namespace = namespace
+ self._type_helper = cpp_type_generator
+ self._cpp_namespace = cpp_namespace
+ self._target_namespace = (
+ self._type_helper.GetCppNamespaceName(self._namespace))
+ self._util_cc_helper = (
+ util_cc_helper.UtilCCHelper(self._type_helper))
+ self._generate_error_messages = namespace.compiler_options.get(
+ 'generate_error_messages', False)
+
+ def Generate(self):
+ """Generates a Code object with the .cc for a single namespace.
+ """
+ c = Code()
+ (c.Append(cpp_util.CHROMIUM_LICENSE)
+ .Append()
+ .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file)
+ .Append()
+ .Append(self._util_cc_helper.GetIncludePath())
+ .Append('#include "base/logging.h"')
+ .Append('#include "base/strings/string_number_conversions.h"')
+ .Append('#include "%s/%s.h"' %
+ (self._namespace.source_file_dir, self._namespace.unix_name))
+ .Cblock(self._type_helper.GenerateIncludes(include_soft=True))
+ .Append()
+ .Concat(cpp_util.OpenNamespace(self._cpp_namespace))
+ .Cblock(self._type_helper.GetNamespaceStart())
+ )
+ if self._namespace.properties:
+ (c.Append('//')
+ .Append('// Properties')
+ .Append('//')
+ .Append()
+ )
+ for property in self._namespace.properties.values():
+ property_code = self._type_helper.GeneratePropertyValues(
+ property,
+ 'const %(type)s %(name)s = %(value)s;',
+ nodoc=True)
+ if property_code:
+ c.Cblock(property_code)
+ if self._namespace.types:
+ (c.Append('//')
+ .Append('// Types')
+ .Append('//')
+ .Append()
+ .Cblock(self._GenerateTypes(None, self._namespace.types.values()))
+ )
+ if self._namespace.functions:
+ (c.Append('//')
+ .Append('// Functions')
+ .Append('//')
+ .Append()
+ )
+ for function in self._namespace.functions.values():
+ c.Cblock(self._GenerateFunction(function))
+ if self._namespace.events:
+ (c.Append('//')
+ .Append('// Events')
+ .Append('//')
+ .Append()
+ )
+ for event in self._namespace.events.values():
+ c.Cblock(self._GenerateEvent(event))
+ (c.Concat(self._type_helper.GetNamespaceEnd())
+ .Cblock(cpp_util.CloseNamespace(self._cpp_namespace))
+ )
+ return c
+
+ def _GenerateType(self, cpp_namespace, type_):
+ """Generates the function definitions for a type.
+ """
+ classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
+ c = Code()
+
+ if type_.functions:
+ # Wrap functions within types in the type's namespace.
+ (c.Append('namespace %s {' % classname)
+ .Append())
+ for function in type_.functions.values():
+ c.Cblock(self._GenerateFunction(function))
+ c.Append('} // namespace %s' % classname)
+ elif type_.property_type == PropertyType.ARRAY:
+ c.Cblock(self._GenerateType(cpp_namespace, type_.item_type))
+ elif type_.property_type in (PropertyType.CHOICES,
+ PropertyType.OBJECT):
+ if cpp_namespace is None:
+ classname_in_namespace = classname
+ else:
+ classname_in_namespace = '%s::%s' % (cpp_namespace, classname)
+
+ if type_.property_type == PropertyType.OBJECT:
+ c.Cblock(self._GeneratePropertyFunctions(classname_in_namespace,
+ type_.properties.values()))
+ else:
+ c.Cblock(self._GenerateTypes(classname_in_namespace, type_.choices))
+
+ (c.Append('%s::%s()' % (classname_in_namespace, classname))
+ .Cblock(self._GenerateInitializersAndBody(type_))
+ .Append('%s::~%s() {}' % (classname_in_namespace, classname))
+ .Append()
+ )
+ if type_.origin.from_json:
+ c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_))
+ if cpp_namespace is None: # only generate for top-level types
+ c.Cblock(self._GenerateTypeFromValue(classname_in_namespace, type_))
+ if type_.origin.from_client:
+ c.Cblock(self._GenerateTypeToValue(classname_in_namespace, type_))
+ elif type_.property_type == PropertyType.ENUM:
+ (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_))
+ .Cblock(self._GenerateEnumFromString(cpp_namespace, type_))
+ )
+
+ return c
+
+ def _GenerateInitializersAndBody(self, type_):
+ items = []
+ for prop in type_.properties.values():
+ if prop.optional:
+ continue
+
+ t = prop.type_
+ if t.property_type == PropertyType.INTEGER:
+ items.append('%s(0)' % prop.unix_name)
+ elif t.property_type == PropertyType.DOUBLE:
+ items.append('%s(0.0)' % prop.unix_name)
+ elif t.property_type == PropertyType.BOOLEAN:
+ items.append('%s(false)' % prop.unix_name)
+ elif (t.property_type == PropertyType.ANY or
+ t.property_type == PropertyType.ARRAY or
+ t.property_type == PropertyType.BINARY or # mapped to std::string
+ t.property_type == PropertyType.CHOICES or
+ t.property_type == PropertyType.ENUM or
+ t.property_type == PropertyType.OBJECT or
+ t.property_type == PropertyType.FUNCTION or
+ t.property_type == PropertyType.REF or
+ t.property_type == PropertyType.STRING):
+ # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we
+ # don't presently have the semantics to indicate which one of a set
+ # should be the default.
+ continue
+ else:
+ raise TypeError(t)
+
+ if items:
+ s = ': %s' % (', '.join(items))
+ else:
+ s = ''
+ s = s + ' {}'
+ return Code().Append(s)
+
+ def _GenerateTypePopulate(self, cpp_namespace, type_):
+ """Generates the function for populating a type given a pointer to it.
+
+ E.g for type "Foo", generates Foo::Populate()
+ """
+ classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
+ c = Code()
+ (c.Append('// static')
+ .Append('bool %(namespace)s::Populate(')
+ .Sblock(' %s) {' % self._GenerateParams(
+ ('const base::Value& value', '%(name)s* out'))))
+
+ if type_.property_type == PropertyType.CHOICES:
+ for choice in type_.choices:
+ (c.Sblock('if (%s) {' % self._GenerateValueIsTypeExpression('value',
+ choice))
+ .Concat(self._GeneratePopulateVariableFromValue(
+ choice,
+ '(&value)',
+ 'out->as_%s' % choice.unix_name,
+ 'false',
+ is_ptr=True))
+ .Append('return true;')
+ .Eblock('}')
+ )
+ (c.Concat(self._GenerateError(
+ '"expected %s, got " + %s' %
+ (" or ".join(choice.name for choice in type_.choices),
+ self._util_cc_helper.GetValueTypeString('value'))))
+ .Append('return false;'))
+ elif type_.property_type == PropertyType.OBJECT:
+ (c.Sblock('if (!value.IsType(base::Value::TYPE_DICTIONARY)) {')
+ .Concat(self._GenerateError(
+ '"expected dictionary, got " + ' +
+ self._util_cc_helper.GetValueTypeString('value')))
+ .Append('return false;')
+ .Eblock('}'))
+
+ if type_.properties or type_.additional_properties is not None:
+ c.Append('const base::DictionaryValue* dict = '
+ 'static_cast<const base::DictionaryValue*>(&value);')
+ for prop in type_.properties.values():
+ c.Concat(self._InitializePropertyToDefault(prop, 'out'))
+ for prop in type_.properties.values():
+ c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out'))
+ if type_.additional_properties is not None:
+ if type_.additional_properties.property_type == PropertyType.ANY:
+ c.Append('out->additional_properties.MergeDictionary(dict);')
+ else:
+ cpp_type = self._type_helper.GetCppType(type_.additional_properties,
+ is_in_container=True)
+ (c.Append('for (base::DictionaryValue::Iterator it(*dict);')
+ .Sblock(' !it.IsAtEnd(); it.Advance()) {')
+ .Append('%s tmp;' % cpp_type)
+ .Concat(self._GeneratePopulateVariableFromValue(
+ type_.additional_properties,
+ '(&it.value())',
+ 'tmp',
+ 'false'))
+ .Append('out->additional_properties[it.key()] = tmp;')
+ .Eblock('}')
+ )
+ c.Append('return true;')
+ (c.Eblock('}')
+ .Substitute({'namespace': cpp_namespace, 'name': classname}))
+ return c
+
+ def _GenerateValueIsTypeExpression(self, var, type_):
+ real_type = self._type_helper.FollowRef(type_)
+ if real_type.property_type is PropertyType.CHOICES:
+ return '(%s)' % ' || '.join(self._GenerateValueIsTypeExpression(var,
+ choice)
+ for choice in real_type.choices)
+ return '%s.IsType(%s)' % (var, cpp_util.GetValueType(real_type))
+
+ def _GenerateTypePopulateProperty(self, prop, src, dst):
+ """Generate the code to populate a single property in a type.
+
+ src: base::DictionaryValue*
+ dst: Type*
+ """
+ c = Code()
+ value_var = prop.unix_name + '_value'
+ c.Append('const base::Value* %(value_var)s = NULL;')
+ if prop.optional:
+ (c.Sblock(
+ 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {')
+ .Concat(self._GeneratePopulatePropertyFromValue(
+ prop, value_var, dst, 'false')))
+ underlying_type = self._type_helper.FollowRef(prop.type_)
+ if underlying_type.property_type == PropertyType.ENUM:
+ (c.Append('} else {')
+ .Append('%%(dst)s->%%(name)s = %s;' %
+ self._type_helper.GetEnumNoneValue(prop.type_)))
+ c.Eblock('}')
+ else:
+ (c.Sblock(
+ 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {')
+ .Concat(self._GenerateError('"\'%%(key)s\' is required"'))
+ .Append('return false;')
+ .Eblock('}')
+ .Concat(self._GeneratePopulatePropertyFromValue(
+ prop, value_var, dst, 'false'))
+ )
+ c.Append()
+ c.Substitute({
+ 'value_var': value_var,
+ 'key': prop.name,
+ 'src': src,
+ 'dst': dst,
+ 'name': prop.unix_name
+ })
+ return c
+
+ def _GenerateTypeFromValue(self, cpp_namespace, type_):
+ classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
+ c = Code()
+ (c.Append('// static')
+ .Append('scoped_ptr<%s> %s::FromValue(%s) {' % (classname,
+ cpp_namespace, self._GenerateParams(('const base::Value& value',))))
+ .Append(' scoped_ptr<%s> out(new %s());' % (classname, classname))
+ .Append(' if (!Populate(%s))' % self._GenerateArgs(
+ ('value', 'out.get()')))
+ .Append(' return scoped_ptr<%s>();' % classname)
+ .Append(' return out.Pass();')
+ .Append('}')
+ )
+ return c
+
+ def _GenerateTypeToValue(self, cpp_namespace, type_):
+ """Generates a function that serializes the type into a base::Value.
+ E.g. for type "Foo" generates Foo::ToValue()
+ """
+ if type_.property_type == PropertyType.OBJECT:
+ return self._GenerateObjectTypeToValue(cpp_namespace, type_)
+ elif type_.property_type == PropertyType.CHOICES:
+ return self._GenerateChoiceTypeToValue(cpp_namespace, type_)
+ else:
+ raise ValueError("Unsupported property type %s" % type_.type_)
+
+ def _GenerateObjectTypeToValue(self, cpp_namespace, type_):
+ """Generates a function that serializes an object-representing type
+ into a base::DictionaryValue.
+ """
+ c = Code()
+ (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' %
+ cpp_namespace)
+ .Append('scoped_ptr<base::DictionaryValue> value('
+ 'new base::DictionaryValue());')
+ .Append()
+ )
+
+ for prop in type_.properties.values():
+ if prop.optional:
+ # Optional enum values are generated with a NONE enum value.
+ underlying_type = self._type_helper.FollowRef(prop.type_)
+ if underlying_type.property_type == PropertyType.ENUM:
+ c.Sblock('if (%s != %s) {' %
+ (prop.unix_name,
+ self._type_helper.GetEnumNoneValue(prop.type_)))
+ else:
+ c.Sblock('if (%s.get()) {' % prop.unix_name)
+
+ # ANY is a base::Value which is abstract and cannot be a direct member, so
+ # it will always be a pointer.
+ is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY
+ c.Append('value->SetWithoutPathExpansion("%s", %s);' % (
+ prop.name,
+ self._CreateValueFromType(prop.type_,
+ 'this->%s' % prop.unix_name,
+ is_ptr=is_ptr)))
+
+ if prop.optional:
+ c.Eblock('}');
+
+ if type_.additional_properties is not None:
+ if type_.additional_properties.property_type == PropertyType.ANY:
+ c.Append('value->MergeDictionary(&additional_properties);')
+ else:
+ # Non-copyable types will be wrapped in a linked_ptr for inclusion in
+ # maps, so we need to unwrap them.
+ needs_unwrap = (
+ not self._type_helper.IsCopyable(type_.additional_properties))
+ cpp_type = self._type_helper.GetCppType(type_.additional_properties,
+ is_in_container=True)
+ (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' %
+ cpp_util.PadForGenerics(cpp_type))
+ .Append(' additional_properties.begin();')
+ .Append(' it != additional_properties.end(); ++it) {')
+ .Append('value->SetWithoutPathExpansion(it->first, %s);' %
+ self._CreateValueFromType(
+ type_.additional_properties,
+ '%sit->second' % ('*' if needs_unwrap else '')))
+ .Eblock('}')
+ )
+
+ return (c.Append()
+ .Append('return value.Pass();')
+ .Eblock('}'))
+
+ def _GenerateChoiceTypeToValue(self, cpp_namespace, type_):
+ """Generates a function that serializes a choice-representing type
+ into a base::Value.
+ """
+ c = Code()
+ c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace)
+ c.Append('scoped_ptr<base::Value> result;');
+ for choice in type_.choices:
+ choice_var = 'as_%s' % choice.unix_name
+ (c.Sblock('if (%s) {' % choice_var)
+ .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' %
+ type_.unix_name)
+ .Append('result.reset(%s);' %
+ self._CreateValueFromType(choice, '*%s' % choice_var))
+ .Eblock('}')
+ )
+ (c.Append('DCHECK(result) << "Must set at least one choice for %s";' %
+ type_.unix_name)
+ .Append('return result.Pass();')
+ .Eblock('}')
+ )
+ return c
+
+ def _GenerateFunction(self, function):
+ """Generates the definitions for function structs.
+ """
+ c = Code()
+
+ # TODO(kalman): use function.unix_name not Classname.
+ function_namespace = cpp_util.Classname(function.name)
+ """Windows has a #define for SendMessage, so to avoid any issues, we need
+ to not use the name.
+ """
+ if function_namespace == 'SendMessage':
+ function_namespace = 'PassMessage'
+ (c.Append('namespace %s {' % function_namespace)
+ .Append()
+ )
+
+ # Params::Populate function
+ if function.params:
+ c.Concat(self._GeneratePropertyFunctions('Params', function.params))
+ (c.Append('Params::Params() {}')
+ .Append('Params::~Params() {}')
+ .Append()
+ .Cblock(self._GenerateFunctionParamsCreate(function))
+ )
+
+ # Results::Create function
+ if function.callback:
+ c.Concat(self._GenerateCreateCallbackArguments('Results',
+ function.callback))
+
+ c.Append('} // namespace %s' % function_namespace)
+ return c
+
+ def _GenerateEvent(self, event):
+ # TODO(kalman): use event.unix_name not Classname.
+ c = Code()
+ event_namespace = cpp_util.Classname(event.name)
+ (c.Append('namespace %s {' % event_namespace)
+ .Append()
+ .Cblock(self._GenerateEventNameConstant(None, event))
+ .Cblock(self._GenerateCreateCallbackArguments(None, event))
+ .Append('} // namespace %s' % event_namespace)
+ )
+ return c
+
+ def _CreateValueFromType(self, type_, var, is_ptr=False):
+ """Creates a base::Value given a type. Generated code passes ownership
+ to caller.
+
+ var: variable or variable*
+
+ E.g for std::string, generate new base::StringValue(var)
+ """
+ underlying_type = self._type_helper.FollowRef(type_)
+ if (underlying_type.property_type == PropertyType.CHOICES or
+ underlying_type.property_type == PropertyType.OBJECT):
+ if is_ptr:
+ return '(%s)->ToValue().release()' % var
+ else:
+ return '(%s).ToValue().release()' % var
+ elif (underlying_type.property_type == PropertyType.ANY or
+ underlying_type.property_type == PropertyType.FUNCTION):
+ if is_ptr:
+ vardot = '(%s)->' % var
+ else:
+ vardot = '(%s).' % var
+ return '%sDeepCopy()' % vardot
+ elif underlying_type.property_type == PropertyType.ENUM:
+ return 'new base::StringValue(ToString(%s))' % var
+ elif underlying_type.property_type == PropertyType.BINARY:
+ if is_ptr:
+ vardot = var + '->'
+ else:
+ vardot = var + '.'
+ return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' %
+ (vardot, vardot))
+ elif underlying_type.property_type == PropertyType.ARRAY:
+ return '%s.release()' % self._util_cc_helper.CreateValueFromArray(
+ underlying_type,
+ var,
+ is_ptr)
+ elif underlying_type.property_type.is_fundamental:
+ if is_ptr:
+ var = '*%s' % var
+ if underlying_type.property_type == PropertyType.STRING:
+ return 'new base::StringValue(%s)' % var
+ else:
+ return 'new base::FundamentalValue(%s)' % var
+ else:
+ raise NotImplementedError('Conversion of %s to base::Value not '
+ 'implemented' % repr(type_.type_))
+
+ def _GenerateParamsCheck(self, function, var):
+ """Generates a check for the correct number of arguments when creating
+ Params.
+ """
+ c = Code()
+ num_required = 0
+ for param in function.params:
+ if not param.optional:
+ num_required += 1
+ if num_required == len(function.params):
+ c.Sblock('if (%(var)s.GetSize() != %(total)d) {')
+ elif not num_required:
+ c.Sblock('if (%(var)s.GetSize() > %(total)d) {')
+ else:
+ c.Sblock('if (%(var)s.GetSize() < %(required)d'
+ ' || %(var)s.GetSize() > %(total)d) {')
+ (c.Concat(self._GenerateError(
+ '"expected %%(total)d arguments, got " '
+ '+ base::IntToString(%%(var)s.GetSize())'))
+ .Append('return scoped_ptr<Params>();')
+ .Eblock('}')
+ .Substitute({
+ 'var': var,
+ 'required': num_required,
+ 'total': len(function.params),
+ }))
+ return c
+
+ def _GenerateFunctionParamsCreate(self, function):
+ """Generate function to create an instance of Params. The generated
+ function takes a base::ListValue of arguments.
+
+ E.g for function "Bar", generate Bar::Params::Create()
+ """
+ c = Code()
+ (c.Append('// static')
+ .Sblock('scoped_ptr<Params> Params::Create(%s) {' % self._GenerateParams(
+ ['const base::ListValue& args']))
+ .Concat(self._GenerateParamsCheck(function, 'args'))
+ .Append('scoped_ptr<Params> params(new Params());'))
+
+ for param in function.params:
+ c.Concat(self._InitializePropertyToDefault(param, 'params'))
+
+ for i, param in enumerate(function.params):
+ # Any failure will cause this function to return. If any argument is
+ # incorrect or missing, those following it are not processed. Note that
+ # for optional arguments, we allow missing arguments and proceed because
+ # there may be other arguments following it.
+ failure_value = 'scoped_ptr<Params>()'
+ c.Append()
+ value_var = param.unix_name + '_value'
+ (c.Append('const base::Value* %(value_var)s = NULL;')
+ .Append('if (args.Get(%(i)s, &%(value_var)s) &&')
+ .Sblock(' !%(value_var)s->IsType(base::Value::TYPE_NULL)) {')
+ .Concat(self._GeneratePopulatePropertyFromValue(
+ param, value_var, 'params', failure_value))
+ .Eblock('}')
+ )
+ if not param.optional:
+ (c.Sblock('else {')
+ .Concat(self._GenerateError('"\'%%(key)s\' is required"'))
+ .Append('return %s;' % failure_value)
+ .Eblock('}'))
+ c.Substitute({'value_var': value_var, 'i': i, 'key': param.name})
+ (c.Append()
+ .Append('return params.Pass();')
+ .Eblock('}')
+ .Append()
+ )
+
+ return c
+
+ def _GeneratePopulatePropertyFromValue(self,
+ prop,
+ src_var,
+ dst_class_var,
+ failure_value):
+ """Generates code to populate property |prop| of |dst_class_var| (a
+ pointer) from a Value*. See |_GeneratePopulateVariableFromValue| for
+ semantics.
+ """
+ return self._GeneratePopulateVariableFromValue(prop.type_,
+ src_var,
+ '%s->%s' % (dst_class_var,
+ prop.unix_name),
+ failure_value,
+ is_ptr=prop.optional)
+
+ def _GeneratePopulateVariableFromValue(self,
+ type_,
+ src_var,
+ dst_var,
+ failure_value,
+ is_ptr=False):
+ """Generates code to populate a variable |dst_var| of type |type_| from a
+ Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated
+ code, if |dst_var| fails to be populated then Populate will return
+ |failure_value|.
+ """
+ c = Code()
+ c.Sblock('{')
+
+ underlying_type = self._type_helper.FollowRef(type_)
+
+ if underlying_type.property_type.is_fundamental:
+ if is_ptr:
+ (c.Append('%(cpp_type)s temp;')
+ .Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue(
+ self._type_helper.FollowRef(type_), src_var, '&temp'))
+ .Concat(self._GenerateError(
+ '"\'%%(key)s\': expected ' + '%s, got " + %s' % (
+ type_.name,
+ self._util_cc_helper.GetValueTypeString(
+ '%%(src_var)s', True))))
+ .Append('return %(failure_value)s;')
+ .Eblock('}')
+ .Append('%(dst_var)s.reset(new %(cpp_type)s(temp));')
+ )
+ else:
+ (c.Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue(
+ self._type_helper.FollowRef(type_),
+ src_var,
+ '&%s' % dst_var))
+ .Concat(self._GenerateError(
+ '"\'%%(key)s\': expected ' + '%s, got " + %s' % (
+ type_.name,
+ self._util_cc_helper.GetValueTypeString(
+ '%%(src_var)s', True))))
+ .Append('return %(failure_value)s;')
+ .Eblock('}')
+ )
+ elif underlying_type.property_type == PropertyType.OBJECT:
+ if is_ptr:
+ (c.Append('const base::DictionaryValue* dictionary = NULL;')
+ .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {')
+ .Concat(self._GenerateError(
+ '"\'%%(key)s\': expected dictionary, got " + ' +
+ self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
+ .Append('return %(failure_value)s;')
+ .Eblock('}')
+ .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
+ .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs(
+ ('*dictionary', 'temp.get()')))
+ .Append(' return %(failure_value)s;')
+ .Append('}')
+ .Append('%(dst_var)s = temp.Pass();')
+ )
+ else:
+ (c.Append('const base::DictionaryValue* dictionary = NULL;')
+ .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {')
+ .Concat(self._GenerateError(
+ '"\'%%(key)s\': expected dictionary, got " + ' +
+ self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
+ .Append('return %(failure_value)s;')
+ .Eblock('}')
+ .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs(
+ ('*dictionary', '&%(dst_var)s')))
+ .Append(' return %(failure_value)s;')
+ .Append('}')
+ )
+ elif underlying_type.property_type == PropertyType.FUNCTION:
+ if is_ptr:
+ c.Append('%(dst_var)s.reset(new base::DictionaryValue());')
+ elif underlying_type.property_type == PropertyType.ANY:
+ c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());')
+ elif underlying_type.property_type == PropertyType.ARRAY:
+ # util_cc_helper deals with optional and required arrays
+ (c.Append('const base::ListValue* list = NULL;')
+ .Sblock('if (!%(src_var)s->GetAsList(&list)) {')
+ .Concat(self._GenerateError(
+ '"\'%%(key)s\': expected list, got " + ' +
+ self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
+ .Append('return %(failure_value)s;')
+ .Eblock('}'))
+ item_type = self._type_helper.FollowRef(underlying_type.item_type)
+ if item_type.property_type == PropertyType.ENUM:
+ c.Concat(self._GenerateListValueToEnumArrayConversion(
+ item_type,
+ 'list',
+ dst_var,
+ failure_value,
+ is_ptr=is_ptr))
+ else:
+ (c.Sblock('if (!%s) {' % self._util_cc_helper.PopulateArrayFromList(
+ underlying_type,
+ 'list',
+ dst_var,
+ is_ptr))
+ .Concat(self._GenerateError(
+ '"unable to populate array \'%%(parent_key)s\'"'))
+ .Append('return %(failure_value)s;')
+ .Eblock('}')
+ )
+ elif underlying_type.property_type == PropertyType.CHOICES:
+ if is_ptr:
+ (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
+ .Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
+ ('*%(src_var)s', 'temp.get()')))
+ .Append(' return %(failure_value)s;')
+ .Append('%(dst_var)s = temp.Pass();')
+ )
+ else:
+ (c.Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
+ ('*%(src_var)s', '&%(dst_var)s')))
+ .Append(' return %(failure_value)s;'))
+ elif underlying_type.property_type == PropertyType.ENUM:
+ c.Concat(self._GenerateStringToEnumConversion(type_,
+ src_var,
+ dst_var,
+ failure_value))
+ elif underlying_type.property_type == PropertyType.BINARY:
+ (c.Sblock('if (!%(src_var)s->IsType(base::Value::TYPE_BINARY)) {')
+ .Concat(self._GenerateError(
+ '"\'%%(key)s\': expected binary, got " + ' +
+ self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
+ .Append('return %(failure_value)s;')
+ .Eblock('}')
+ .Append('const base::BinaryValue* binary_value =')
+ .Append(' static_cast<const base::BinaryValue*>(%(src_var)s);')
+ )
+ if is_ptr:
+ (c.Append('%(dst_var)s.reset(')
+ .Append(' new std::string(binary_value->GetBuffer(),')
+ .Append(' binary_value->GetSize()));')
+ )
+ else:
+ (c.Append('%(dst_var)s.assign(binary_value->GetBuffer(),')
+ .Append(' binary_value->GetSize());')
+ )
+ else:
+ raise NotImplementedError(type_)
+ return c.Eblock('}').Substitute({
+ 'cpp_type': self._type_helper.GetCppType(type_),
+ 'src_var': src_var,
+ 'dst_var': dst_var,
+ 'failure_value': failure_value,
+ 'key': type_.name,
+ 'parent_key': type_.parent.name
+ })
+
+ def _GenerateListValueToEnumArrayConversion(self,
+ item_type,
+ src_var,
+ dst_var,
+ failure_value,
+ is_ptr=False):
+ """Returns Code that converts a ListValue of string constants from
+ |src_var| into an array of enums of |type_| in |dst_var|. On failure,
+ returns |failure_value|.
+ """
+ c = Code()
+ accessor = '.'
+ if is_ptr:
+ accessor = '->'
+ cpp_type = self._type_helper.GetCppType(item_type, is_in_container=True)
+ c.Append('%s.reset(new std::vector<%s>);' %
+ (dst_var, cpp_util.PadForGenerics(cpp_type)))
+ (c.Sblock('for (base::ListValue::const_iterator it = %s->begin(); '
+ 'it != %s->end(); ++it) {' % (src_var, src_var))
+ .Append('%s tmp;' % self._type_helper.GetCppType(item_type))
+ .Concat(self._GenerateStringToEnumConversion(item_type,
+ '(*it)',
+ 'tmp',
+ failure_value))
+ .Append('%s%spush_back(tmp);' % (dst_var, accessor))
+ .Eblock('}')
+ )
+ return c
+
+ def _GenerateStringToEnumConversion(self,
+ type_,
+ src_var,
+ dst_var,
+ failure_value):
+ """Returns Code that converts a string type in |src_var| to an enum with
+ type |type_| in |dst_var|. In the generated code, if |src_var| is not
+ a valid enum name then the function will return |failure_value|.
+ """
+ c = Code()
+ enum_as_string = '%s_as_string' % type_.unix_name
+ (c.Append('std::string %s;' % enum_as_string)
+ .Sblock('if (!%s->GetAsString(&%s)) {' % (src_var, enum_as_string))
+ .Concat(self._GenerateError(
+ '"\'%%(key)s\': expected string, got " + ' +
+ self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
+ .Append('return %s;' % failure_value)
+ .Eblock('}')
+ .Append('%s = Parse%s(%s);' % (dst_var,
+ self._type_helper.GetCppType(type_),
+ enum_as_string))
+ .Sblock('if (%s == %s) {' % (dst_var,
+ self._type_helper.GetEnumNoneValue(type_)))
+ .Concat(self._GenerateError(
+ '\"\'%%(key)s\': expected \\"' +
+ '\\" or \\"'.join(self._type_helper.FollowRef(type_).enum_values) +
+ '\\", got \\"" + %s + "\\""' % enum_as_string))
+ .Append('return %s;' % failure_value)
+ .Eblock('}')
+ .Substitute({'src_var': src_var, 'key': type_.name})
+ )
+ return c
+
+ def _GeneratePropertyFunctions(self, namespace, params):
+ """Generates the member functions for a list of parameters.
+ """
+ return self._GenerateTypes(namespace, (param.type_ for param in params))
+
+ def _GenerateTypes(self, namespace, types):
+ """Generates the member functions for a list of types.
+ """
+ c = Code()
+ for type_ in types:
+ c.Cblock(self._GenerateType(namespace, type_))
+ return c
+
+ def _GenerateEnumToString(self, cpp_namespace, type_):
+ """Generates ToString() which gets the string representation of an enum.
+ """
+ c = Code()
+ classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
+
+ if cpp_namespace is not None:
+ c.Append('// static')
+ maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace
+
+ c.Sblock('std::string %sToString(%s enum_param) {' %
+ (maybe_namespace, classname))
+ c.Sblock('switch (enum_param) {')
+ for enum_value in self._type_helper.FollowRef(type_).enum_values:
+ (c.Append('case %s: ' % self._type_helper.GetEnumValue(type_, enum_value))
+ .Append(' return "%s";' % enum_value))
+ (c.Append('case %s:' % self._type_helper.GetEnumNoneValue(type_))
+ .Append(' return "";')
+ .Eblock('}')
+ .Append('NOTREACHED();')
+ .Append('return "";')
+ .Eblock('}')
+ )
+ return c
+
+ def _GenerateEnumFromString(self, cpp_namespace, type_):
+ """Generates FromClassNameString() which gets an enum from its string
+ representation.
+ """
+ c = Code()
+ classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
+
+ if cpp_namespace is not None:
+ c.Append('// static')
+ maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace
+
+ c.Sblock('%s%s %sParse%s(const std::string& enum_string) {' %
+ (maybe_namespace, classname, maybe_namespace, classname))
+ for i, enum_value in enumerate(
+ self._type_helper.FollowRef(type_).enum_values):
+ # This is broken up into all ifs with no else ifs because we get
+ # "fatal error C1061: compiler limit : blocks nested too deeply"
+ # on Windows.
+ (c.Append('if (enum_string == "%s")' % enum_value)
+ .Append(' return %s;' %
+ self._type_helper.GetEnumValue(type_, enum_value)))
+ (c.Append('return %s;' % self._type_helper.GetEnumNoneValue(type_))
+ .Eblock('}')
+ )
+ return c
+
+ def _GenerateCreateCallbackArguments(self, function_scope, callback):
+ """Generate all functions to create Value parameters for a callback.
+
+ E.g for function "Bar", generate Bar::Results::Create
+ E.g for event "Baz", generate Baz::Create
+
+ function_scope: the function scope path, e.g. Foo::Bar for the function
+ Foo::Bar::Baz(). May be None if there is no function scope.
+ callback: the Function object we are creating callback arguments for.
+ """
+ c = Code()
+ params = callback.params
+ c.Concat(self._GeneratePropertyFunctions(function_scope, params))
+
+ (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s'
+ 'Create(%(declaration_list)s) {')
+ .Append('scoped_ptr<base::ListValue> create_results('
+ 'new base::ListValue());')
+ )
+ declaration_list = []
+ for param in params:
+ declaration_list.append(cpp_util.GetParameterDeclaration(
+ param, self._type_helper.GetCppType(param.type_)))
+ c.Append('create_results->Append(%s);' %
+ self._CreateValueFromType(param.type_, param.unix_name))
+ c.Append('return create_results.Pass();')
+ c.Eblock('}')
+ c.Substitute({
+ 'function_scope': ('%s::' % function_scope) if function_scope else '',
+ 'declaration_list': ', '.join(declaration_list),
+ 'param_names': ', '.join(param.unix_name for param in params)
+ })
+ return c
+
+ def _GenerateEventNameConstant(self, function_scope, event):
+ """Generates a constant string array for the event name.
+ """
+ c = Code()
+ c.Append('const char kEventName[] = "%s.%s";' % (
+ self._namespace.name, event.name))
+ return c
+
+ def _InitializePropertyToDefault(self, prop, dst):
+ """Initialize a model.Property to its default value inside an object.
+
+ E.g for optional enum "state", generate dst->state = STATE_NONE;
+
+ dst: Type*
+ """
+ c = Code()
+ underlying_type = self._type_helper.FollowRef(prop.type_)
+ if (underlying_type.property_type == PropertyType.ENUM and
+ prop.optional):
+ c.Append('%s->%s = %s;' % (
+ dst,
+ prop.unix_name,
+ self._type_helper.GetEnumNoneValue(prop.type_)))
+ return c
+
+ def _GenerateError(self, body):
+ """Generates an error message pertaining to population failure.
+
+ E.g 'expected bool, got int'
+ """
+ c = Code()
+ if not self._generate_error_messages:
+ return c
+ (c.Append('if (error)')
+ .Append(' *error = ' + body + ';'))
+ return c
+
+ def _GenerateParams(self, params):
+ """Builds the parameter list for a function, given an array of parameters.
+ """
+ if self._generate_error_messages:
+ params = list(params) + ['std::string* error']
+ return ', '.join(str(p) for p in params)
+
+ def _GenerateArgs(self, args):
+ """Builds the argument list for a function, given an array of arguments.
+ """
+ if self._generate_error_messages:
+ args = list(args) + ['error']
+ return ', '.join(str(a) for a in args)
diff --git a/chromium/tools/json_schema_compiler/code.py b/chromium/tools/json_schema_compiler/code.py
new file mode 100644
index 00000000000..3622237a84a
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/code.py
@@ -0,0 +1,141 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class Code(object):
+ """A convenience object for constructing code.
+
+ Logically each object should be a block of code. All methods except |Render|
+ and |IsEmpty| return self.
+ """
+ def __init__(self, indent_size=2, comment_length=80):
+ self._code = []
+ self._indent_level = 0
+ self._indent_size = indent_size
+ self._comment_length = comment_length
+
+ def Append(self, line='', substitute=True, indent_level=None):
+ """Appends a line of code at the current indent level or just a newline if
+ line is not specified. Trailing whitespace is stripped.
+
+ substitute: indicated whether this line should be affected by
+ code.Substitute().
+ """
+ if indent_level is None:
+ indent_level = self._indent_level
+ self._code.append(Line(((' ' * indent_level) + line).rstrip(),
+ substitute=substitute))
+ return self
+
+ def IsEmpty(self):
+ """Returns True if the Code object is empty.
+ """
+ return not bool(self._code)
+
+ def Concat(self, obj):
+ """Concatenate another Code object onto this one. Trailing whitespace is
+ stripped.
+
+ Appends the code at the current indent level. Will fail if there are any
+ un-interpolated format specifiers eg %s, %(something)s which helps
+ isolate any strings that haven't been substituted.
+ """
+ if not isinstance(obj, Code):
+ raise TypeError(type(obj))
+ assert self is not obj
+ for line in obj._code:
+ try:
+ # line % () will fail if any substitution tokens are left in line
+ if line.substitute:
+ line.value %= ()
+ except TypeError:
+ raise TypeError('Unsubstituted value when concatting\n' + line.value)
+ except ValueError:
+ raise ValueError('Stray % character when concatting\n' + line.value)
+ self.Append(line.value, line.substitute)
+
+ return self
+
+ def Cblock(self, code):
+ """Concatenates another Code object |code| onto this one followed by a
+ blank line, if |code| is non-empty."""
+ if not code.IsEmpty():
+ self.Concat(code).Append()
+ return self
+
+ def Sblock(self, line=None):
+ """Starts a code block.
+
+ Appends a line of code and then increases the indent level.
+ """
+ if line is not None:
+ self.Append(line)
+ self._indent_level += self._indent_size
+ return self
+
+ def Eblock(self, line=None):
+ """Ends a code block by decreasing and then appending a line (or a blank
+ line if not given).
+ """
+ # TODO(calamity): Decide if type checking is necessary
+ #if not isinstance(line, basestring):
+ # raise TypeError
+ self._indent_level -= self._indent_size
+ if line is not None:
+ self.Append(line)
+ return self
+
+ def Comment(self, comment, comment_prefix='// '):
+ """Adds the given string as a comment.
+
+ Will split the comment if it's too long. Use mainly for variable length
+ comments. Otherwise just use code.Append('// ...') for comments.
+
+ Unaffected by code.Substitute().
+ """
+ max_len = self._comment_length - self._indent_level - len(comment_prefix)
+ while len(comment) >= max_len:
+ line = comment[0:max_len]
+ last_space = line.rfind(' ')
+ if last_space != -1:
+ line = line[0:last_space]
+ comment = comment[last_space + 1:]
+ else:
+ comment = comment[max_len:]
+ self.Append(comment_prefix + line, substitute=False)
+ self.Append(comment_prefix + comment, substitute=False)
+ return self
+
+ def Substitute(self, d):
+ """Goes through each line and interpolates using the given dict.
+
+ Raises type error if passed something that isn't a dict
+
+ Use for long pieces of code using interpolation with the same variables
+ repeatedly. This will reduce code and allow for named placeholders which
+ are more clear.
+ """
+ if not isinstance(d, dict):
+ raise TypeError('Passed argument is not a dictionary: ' + d)
+ for i, line in enumerate(self._code):
+ if self._code[i].substitute:
+ # Only need to check %s because arg is a dict and python will allow
+ # '%s %(named)s' but just about nothing else
+ if '%s' in self._code[i].value or '%r' in self._code[i].value:
+ raise TypeError('"%s" or "%r" found in substitution. '
+ 'Named arguments only. Use "%" to escape')
+ self._code[i].value = line.value % d
+ self._code[i].substitute = False
+ return self
+
+ def Render(self):
+ """Renders Code as a string.
+ """
+ return '\n'.join([l.value for l in self._code])
+
+class Line(object):
+ """A line of code.
+ """
+ def __init__(self, value, substitute=True):
+ self.value = value
+ self.substitute = substitute
diff --git a/chromium/tools/json_schema_compiler/code_test.py b/chromium/tools/json_schema_compiler/code_test.py
new file mode 100755
index 00000000000..ca3652420f9
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/code_test.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from code import Code
+import unittest
+
+class CodeTest(unittest.TestCase):
+ def testAppend(self):
+ c = Code()
+ c.Append('line')
+ self.assertEquals('line', c.Render())
+
+ def testBlock(self):
+ c = Code()
+ (c.Append('line')
+ .Sblock('sblock')
+ .Append('inner')
+ .Append('moreinner')
+ .Sblock('moresblock')
+ .Append('inner')
+ .Eblock('out')
+ .Append('inner')
+ .Eblock('out')
+ )
+ self.assertEquals(
+ 'line\n'
+ 'sblock\n'
+ ' inner\n'
+ ' moreinner\n'
+ ' moresblock\n'
+ ' inner\n'
+ ' out\n'
+ ' inner\n'
+ 'out',
+ c.Render())
+
+ def testConcat(self):
+ b = Code()
+ (b.Sblock('2')
+ .Append('2')
+ .Eblock('2')
+ )
+ c = Code()
+ (c.Sblock('1')
+ .Concat(b)
+ .Append('1')
+ .Eblock('1')
+ )
+ self.assertEquals(
+ '1\n'
+ ' 2\n'
+ ' 2\n'
+ ' 2\n'
+ ' 1\n'
+ '1',
+ c.Render())
+ d = Code()
+ a = Code()
+ a.Concat(d)
+ self.assertEquals('', a.Render())
+ a.Concat(c)
+ self.assertEquals(
+ '1\n'
+ ' 2\n'
+ ' 2\n'
+ ' 2\n'
+ ' 1\n'
+ '1',
+ a.Render())
+
+ def testConcatErrors(self):
+ c = Code()
+ d = Code()
+ d.Append('%s')
+ self.assertRaises(TypeError, c.Concat, d)
+ d = Code()
+ d.Append('%(classname)s')
+ self.assertRaises(TypeError, c.Concat, d)
+ d = 'line of code'
+ self.assertRaises(TypeError, c.Concat, d)
+
+ def testSubstitute(self):
+ c = Code()
+ c.Append('%(var1)s %(var2)s %(var1)s')
+ c.Substitute({'var1': 'one', 'var2': 'two'})
+ self.assertEquals('one two one', c.Render())
+ c.Append('%(var1)s %(var2)s %(var3)s')
+ c.Append('%(var2)s %(var1)s %(var3)s')
+ c.Substitute({'var1': 'one', 'var2': 'two', 'var3': 'three'})
+ self.assertEquals(
+ 'one two one\n'
+ 'one two three\n'
+ 'two one three',
+ c.Render())
+
+ def testSubstituteErrors(self):
+ # No unnamed placeholders allowed when substitute is run
+ c = Code()
+ c.Append('%s %s')
+ self.assertRaises(TypeError, c.Substitute, ('var1', 'one'))
+ c = Code()
+ c.Append('%s %(var1)s')
+ self.assertRaises(TypeError, c.Substitute, {'var1': 'one'})
+ c = Code()
+ c.Append('%s %(var1)s')
+ self.assertRaises(TypeError, c.Substitute, {'var1': 'one'})
+ c = Code()
+ c.Append('%(var1)s')
+ self.assertRaises(KeyError, c.Substitute, {'clearlynotvar1': 'one'})
+
+ def testIsEmpty(self):
+ c = Code()
+ self.assertTrue(c.IsEmpty())
+ c.Append('asdf')
+ self.assertFalse(c.IsEmpty())
+
+ def testComment(self):
+ long_comment = ('This comment is eighty nine characters in longness, '
+ 'that is, to use another word, length')
+ c = Code()
+ c.Comment(long_comment)
+ self.assertEquals(
+ '// This comment is eighty nine characters '
+ 'in longness, that is, to use another\n'
+ '// word, length',
+ c.Render())
+ c = Code()
+ c.Sblock('sblock')
+ c.Comment(long_comment)
+ c.Eblock('eblock')
+ c.Comment(long_comment)
+ self.assertEquals(
+ 'sblock\n'
+ ' // This comment is eighty nine characters '
+ 'in longness, that is, to use\n'
+ ' // another word, length\n'
+ 'eblock\n'
+ '// This comment is eighty nine characters in '
+ 'longness, that is, to use another\n'
+ '// word, length',
+ c.Render())
+ long_word = 'x' * 100
+ c = Code()
+ c.Comment(long_word)
+ self.assertEquals(
+ '// ' + 'x' * 77 + '\n'
+ '// ' + 'x' * 23,
+ c.Render())
+
+ def testCommentWithSpecialCharacters(self):
+ c = Code()
+ c.Comment('20% of 80%s')
+ c.Substitute({})
+ self.assertEquals('// 20% of 80%s', c.Render())
+ d = Code()
+ d.Append('90')
+ d.Concat(c)
+ self.assertEquals('90\n'
+ '// 20% of 80%s',
+ d.Render())
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/compiler.py b/chromium/tools/json_schema_compiler/compiler.py
new file mode 100755
index 00000000000..acf64acd91d
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/compiler.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Generator for C++ structs from api json files.
+
+The purpose of this tool is to remove the need for hand-written code that
+converts to and from base::Value types when receiving javascript api calls.
+Originally written for generating code for extension apis. Reference schemas
+are in chrome/common/extensions/api.
+
+Usage example:
+ compiler.py --root /home/Work/src --namespace extensions windows.json
+ tabs.json
+ compiler.py --destdir gen --root /home/Work/src
+ --namespace extensions windows.json tabs.json
+"""
+
+import optparse
+import os
+import sys
+
+from cpp_bundle_generator import CppBundleGenerator
+from cpp_generator import CppGenerator
+from cpp_type_generator import CppTypeGenerator
+from dart_generator import DartGenerator
+import json_schema
+from model import Model, UnixName
+from schema_loader import SchemaLoader
+
+# Names of supported code generators, as specified on the command-line.
+# First is default.
+GENERATORS = ['cpp', 'cpp-bundle', 'dart']
+
+def GenerateSchema(generator,
+ filenames,
+ root,
+ destdir,
+ root_namespace,
+ dart_overrides_dir):
+ schema_loader = SchemaLoader(os.path.dirname(os.path.relpath(
+ os.path.normpath(filenames[0]), root)))
+ # Merge the source files into a single list of schemas.
+ api_defs = []
+ for filename in filenames:
+ schema = os.path.normpath(filename)
+ schema_filename, schema_extension = os.path.splitext(schema)
+ path, short_filename = os.path.split(schema_filename)
+ api_def = schema_loader.LoadSchema(schema)
+
+ # If compiling the C++ model code, delete 'nocompile' nodes.
+ if generator == 'cpp':
+ api_def = json_schema.DeleteNodes(api_def, 'nocompile')
+ api_defs.extend(api_def)
+
+ api_model = Model()
+
+ # For single-schema compilation make sure that the first (i.e. only) schema
+ # is the default one.
+ default_namespace = None
+
+ # Load the actual namespaces into the model.
+ for target_namespace, schema_filename in zip(api_defs, filenames):
+ relpath = os.path.relpath(os.path.normpath(schema_filename), root)
+ namespace = api_model.AddNamespace(target_namespace,
+ relpath,
+ include_compiler_options=True)
+ if default_namespace is None:
+ default_namespace = namespace
+
+ path, filename = os.path.split(schema_filename)
+ short_filename, extension = os.path.splitext(filename)
+
+ # Filenames are checked against the unix_names of the namespaces they
+ # generate because the gyp uses the names of the JSON files to generate
+ # the names of the .cc and .h files. We want these to be using unix_names.
+ if namespace.unix_name != short_filename:
+ sys.exit("Filename %s is illegal. Name files using unix_hacker style." %
+ schema_filename)
+
+ # The output filename must match the input filename for gyp to deal with it
+ # properly.
+ out_file = namespace.unix_name
+
+ # Construct the type generator with all the namespaces in this model.
+ type_generator = CppTypeGenerator(api_model,
+ schema_loader,
+ default_namespace=default_namespace)
+
+ if generator == 'cpp-bundle':
+ cpp_bundle_generator = CppBundleGenerator(root,
+ api_model,
+ api_defs,
+ type_generator,
+ root_namespace)
+ generators = [
+ ('generated_api.cc', cpp_bundle_generator.api_cc_generator),
+ ('generated_api.h', cpp_bundle_generator.api_h_generator),
+ ('generated_schemas.cc', cpp_bundle_generator.schemas_cc_generator),
+ ('generated_schemas.h', cpp_bundle_generator.schemas_h_generator)
+ ]
+ elif generator == 'cpp':
+ cpp_generator = CppGenerator(type_generator, root_namespace)
+ generators = [
+ ('%s.h' % namespace.unix_name, cpp_generator.h_generator),
+ ('%s.cc' % namespace.unix_name, cpp_generator.cc_generator)
+ ]
+ elif generator == 'dart':
+ generators = [
+ ('%s.dart' % namespace.unix_name, DartGenerator(
+ dart_overrides_dir))
+ ]
+ else:
+ raise Exception('Unrecognised generator %s' % generator)
+
+ output_code = []
+ for filename, generator in generators:
+ code = generator.Generate(namespace).Render()
+ if destdir:
+ with open(os.path.join(destdir, namespace.source_file_dir,
+ filename), 'w') as f:
+ f.write(code)
+ output_code += [filename, '', code, '']
+
+ return '\n'.join(output_code)
+
+if __name__ == '__main__':
+ parser = optparse.OptionParser(
+ description='Generates a C++ model of an API from JSON schema',
+ usage='usage: %prog [option]... schema')
+ parser.add_option('-r', '--root', default='.',
+ help='logical include root directory. Path to schema files from specified'
+ 'dir will be the include path.')
+ parser.add_option('-d', '--destdir',
+ help='root directory to output generated files.')
+ parser.add_option('-n', '--namespace', default='generated_api_schemas',
+ help='C++ namespace for generated files. e.g extensions::api.')
+ parser.add_option('-g', '--generator', default=GENERATORS[0],
+ choices=GENERATORS,
+ help='The generator to use to build the output code. Supported values are'
+ ' %s' % GENERATORS)
+ parser.add_option('-D', '--dart-overrides-dir', dest='dart_overrides_dir',
+ help='Adds custom dart from files in the given directory (Dart only).')
+
+ (opts, filenames) = parser.parse_args()
+
+ if not filenames:
+ sys.exit(0) # This is OK as a no-op
+
+ # Unless in bundle mode, only one file should be specified.
+ if opts.generator != 'cpp-bundle' and len(filenames) > 1:
+ # TODO(sashab): Could also just use filenames[0] here and not complain.
+ raise Exception(
+ "Unless in bundle mode, only one file can be specified at a time.")
+
+ result = GenerateSchema(opts.generator, filenames, opts.root, opts.destdir,
+ opts.namespace, opts.dart_overrides_dir)
+ if not opts.destdir:
+ print result
diff --git a/chromium/tools/json_schema_compiler/cpp_bundle_generator.py b/chromium/tools/json_schema_compiler/cpp_bundle_generator.py
new file mode 100644
index 00000000000..580bca85208
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/cpp_bundle_generator.py
@@ -0,0 +1,291 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import code
+import cpp_util
+from model import Platforms
+from schema_util import CapitalizeFirstLetter
+from schema_util import JsFunctionNameToClassName
+
+import json
+import os
+import re
+
+# TODO(miket/asargent) - parameterize this.
+SOURCE_BASE_PATH = 'chrome/common/extensions/api'
+
+def _RemoveDescriptions(node):
+ """Returns a copy of |schema| with "description" fields removed.
+ """
+ if isinstance(node, dict):
+ result = {}
+ for key, value in node.items():
+ # Some schemas actually have properties called "description", so only
+ # remove descriptions that have string values.
+ if key == 'description' and isinstance(value, basestring):
+ continue
+ result[key] = _RemoveDescriptions(value)
+ return result
+ if isinstance(node, list):
+ return [_RemoveDescriptions(v) for v in node]
+ return node
+
+class CppBundleGenerator(object):
+ """This class contains methods to generate code based on multiple schemas.
+ """
+
+ def __init__(self, root, model, api_defs, cpp_type_generator, cpp_namespace):
+ self._root = root;
+ self._model = model
+ self._api_defs = api_defs
+ self._cpp_type_generator = cpp_type_generator
+ self._cpp_namespace = cpp_namespace
+
+ self.api_cc_generator = _APICCGenerator(self)
+ self.api_h_generator = _APIHGenerator(self)
+ self.schemas_cc_generator = _SchemasCCGenerator(self)
+ self.schemas_h_generator = _SchemasHGenerator(self)
+
+ def _GenerateHeader(self, file_base, body_code):
+ """Generates a code.Code object for a header file
+
+ Parameters:
+ - |file_base| - the base of the filename, e.g. 'foo' (for 'foo.h')
+ - |body_code| - the code to put in between the multiple inclusion guards"""
+ c = code.Code()
+ c.Append(cpp_util.CHROMIUM_LICENSE)
+ c.Append()
+ c.Append(cpp_util.GENERATED_BUNDLE_FILE_MESSAGE % SOURCE_BASE_PATH)
+ ifndef_name = cpp_util.GenerateIfndefName(SOURCE_BASE_PATH, file_base)
+ c.Append()
+ c.Append('#ifndef %s' % ifndef_name)
+ c.Append('#define %s' % ifndef_name)
+ c.Append()
+ c.Concat(body_code)
+ c.Append()
+ c.Append('#endif // %s' % ifndef_name)
+ c.Append()
+ return c
+
+ def _GetPlatformIfdefs(self, model_object):
+ """Generates the "defined" conditional for an #if check if |model_object|
+ has platform restrictions. Returns None if there are no restrictions.
+ """
+ if model_object.platforms is None:
+ return None
+ ifdefs = []
+ for platform in model_object.platforms:
+ if platform == Platforms.CHROMEOS:
+ ifdefs.append('defined(OS_CHROMEOS)')
+ else:
+ raise ValueError("Unsupported platform ifdef: %s" % platform.name)
+ return ' and '.join(ifdefs)
+
+ def _GenerateRegisterFunctions(self, namespace_name, function):
+ c = code.Code()
+ function_ifdefs = self._GetPlatformIfdefs(function)
+ if function_ifdefs is not None:
+ c.Append("#if %s" % function_ifdefs, indent_level=0)
+
+ function_name = JsFunctionNameToClassName(namespace_name, function.name)
+ c.Append("registry->RegisterFunction<%sFunction>();" % (
+ function_name))
+
+ if function_ifdefs is not None:
+ c.Append("#endif // %s" % function_ifdefs, indent_level=0)
+ return c
+
+ def _GenerateFunctionRegistryRegisterAll(self):
+ c = code.Code()
+ c.Append('// static')
+ c.Sblock('void GeneratedFunctionRegistry::RegisterAll('
+ 'ExtensionFunctionRegistry* registry) {')
+ for namespace in self._model.namespaces.values():
+ namespace_ifdefs = self._GetPlatformIfdefs(namespace)
+ if namespace_ifdefs is not None:
+ c.Append("#if %s" % namespace_ifdefs, indent_level=0)
+
+ namespace_name = CapitalizeFirstLetter(namespace.name.replace(
+ "experimental.", ""))
+ for function in namespace.functions.values():
+ if function.nocompile:
+ continue
+ c.Concat(self._GenerateRegisterFunctions(namespace.name, function))
+
+ for type_ in namespace.types.values():
+ for function in type_.functions.values():
+ if function.nocompile:
+ continue
+ namespace_types_name = JsFunctionNameToClassName(
+ namespace.name, type_.name)
+ c.Concat(self._GenerateRegisterFunctions(namespace_types_name,
+ function))
+
+ if namespace_ifdefs is not None:
+ c.Append("#endif // %s" % namespace_ifdefs, indent_level=0)
+ c.Eblock("}")
+ return c
+
+class _APIHGenerator(object):
+ """Generates the header for API registration / declaration"""
+ def __init__(self, cpp_bundle):
+ self._bundle = cpp_bundle
+
+ def Generate(self, namespace):
+ c = code.Code()
+
+ c.Append('#include <string>')
+ c.Append()
+ c.Append('#include "base/basictypes.h"')
+ c.Append()
+ c.Append("class ExtensionFunctionRegistry;")
+ c.Append()
+ c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
+ c.Append()
+ c.Append('class GeneratedFunctionRegistry {')
+ c.Sblock(' public:')
+ c.Append('static void RegisterAll('
+ 'ExtensionFunctionRegistry* registry);')
+ c.Eblock('};');
+ c.Append()
+ c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace))
+ return self._bundle._GenerateHeader('generated_api', c)
+
+class _APICCGenerator(object):
+ """Generates a code.Code object for the generated API .cc file"""
+
+ def __init__(self, cpp_bundle):
+ self._bundle = cpp_bundle
+
+ def Generate(self, namespace):
+ c = code.Code()
+ c.Append(cpp_util.CHROMIUM_LICENSE)
+ c.Append()
+ c.Append('#include "%s"' % (os.path.join(SOURCE_BASE_PATH,
+ 'generated_api.h')))
+ c.Append()
+ for namespace in self._bundle._model.namespaces.values():
+ namespace_name = namespace.unix_name.replace("experimental_", "")
+ implementation_header = namespace.compiler_options.get(
+ "implemented_in",
+ "chrome/browser/extensions/api/%s/%s_api.h" % (namespace_name,
+ namespace_name))
+ if not os.path.exists(
+ os.path.join(self._bundle._root,
+ os.path.normpath(implementation_header))):
+ if "implemented_in" in namespace.compiler_options:
+ raise ValueError('Header file for namespace "%s" specified in '
+ 'compiler_options not found: %s' %
+ (namespace.unix_name, implementation_header))
+ continue
+ ifdefs = self._bundle._GetPlatformIfdefs(namespace)
+ if ifdefs is not None:
+ c.Append("#if %s" % ifdefs, indent_level=0)
+
+ c.Append('#include "%s"' % implementation_header)
+
+ if ifdefs is not None:
+ c.Append("#endif // %s" % ifdefs, indent_level=0)
+ c.Append()
+ c.Append('#include '
+ '"chrome/browser/extensions/extension_function_registry.h"')
+ c.Append()
+ c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
+ c.Append()
+ c.Concat(self._bundle._GenerateFunctionRegistryRegisterAll())
+ c.Append()
+ c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace))
+ c.Append()
+ return c
+
+class _SchemasHGenerator(object):
+ """Generates a code.Code object for the generated schemas .h file"""
+ def __init__(self, cpp_bundle):
+ self._bundle = cpp_bundle
+
+ def Generate(self, namespace):
+ c = code.Code()
+ c.Append('#include <map>')
+ c.Append('#include <string>')
+ c.Append();
+ c.Append('#include "base/strings/string_piece.h"')
+ c.Append()
+ c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
+ c.Append()
+ c.Append('class GeneratedSchemas {')
+ c.Sblock(' public:')
+ c.Append('// Determines if schema named |name| is generated.')
+ c.Append('static bool IsGenerated(std::string name);')
+ c.Append()
+ c.Append('// Gets the API schema named |name|.')
+ c.Append('static base::StringPiece Get(const std::string& name);')
+ c.Eblock('};');
+ c.Append()
+ c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace))
+ return self._bundle._GenerateHeader('generated_schemas', c)
+
+def _FormatNameAsConstant(name):
+ """Formats a name to be a C++ constant of the form kConstantName"""
+ name = '%s%s' % (name[0].upper(), name[1:])
+ return 'k%s' % re.sub('_[a-z]',
+ lambda m: m.group(0)[1].upper(),
+ name.replace('.', '_'))
+
+class _SchemasCCGenerator(object):
+ """Generates a code.Code object for the generated schemas .cc file"""
+
+ def __init__(self, cpp_bundle):
+ self._bundle = cpp_bundle
+
+ def Generate(self, namespace):
+ c = code.Code()
+ c.Append(cpp_util.CHROMIUM_LICENSE)
+ c.Append()
+ c.Append('#include "%s"' % (os.path.join(SOURCE_BASE_PATH,
+ 'generated_schemas.h')))
+ c.Append()
+ c.Append('#include "base/lazy_instance.h"')
+ c.Append()
+ c.Append('namespace {')
+ for api in self._bundle._api_defs:
+ namespace = self._bundle._model.namespaces[api.get('namespace')]
+ # JSON parsing code expects lists of schemas, so dump a singleton list.
+ json_content = json.dumps([_RemoveDescriptions(api)],
+ separators=(',', ':'))
+ # Escape all double-quotes and backslashes. For this to output a valid
+ # JSON C string, we need to escape \ and ".
+ json_content = json_content.replace('\\', '\\\\').replace('"', '\\"')
+ c.Append('const char %s[] = "%s";' %
+ (_FormatNameAsConstant(namespace.name), json_content))
+ c.Append('}')
+ c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
+ c.Append()
+ c.Sblock('struct Static {')
+ c.Sblock('Static() {')
+ for api in self._bundle._api_defs:
+ namespace = self._bundle._model.namespaces[api.get('namespace')]
+ c.Append('schemas["%s"] = %s;' % (namespace.name,
+ _FormatNameAsConstant(namespace.name)))
+ c.Eblock('}');
+ c.Append()
+ c.Append('std::map<std::string, const char*> schemas;')
+ c.Eblock('};');
+ c.Append()
+ c.Append('base::LazyInstance<Static> g_lazy_instance;')
+ c.Append()
+ c.Append('// static')
+ c.Sblock('base::StringPiece GeneratedSchemas::Get('
+ 'const std::string& name) {')
+ c.Append('return IsGenerated(name) ? '
+ 'g_lazy_instance.Get().schemas[name] : "";')
+ c.Eblock('}')
+ c.Append()
+ c.Append('// static')
+ c.Sblock('bool GeneratedSchemas::IsGenerated(std::string name) {')
+ c.Append('return g_lazy_instance.Get().schemas.count(name) > 0;')
+ c.Eblock('}')
+ c.Append()
+ c.Concat(cpp_util.CloseNamespace(self._bundle._cpp_namespace))
+ c.Append()
+ return c
diff --git a/chromium/tools/json_schema_compiler/cpp_generator.py b/chromium/tools/json_schema_compiler/cpp_generator.py
new file mode 100644
index 00000000000..6dc05137205
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/cpp_generator.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from cc_generator import CCGenerator
+from h_generator import HGenerator
+
+class CppGenerator(object):
+ def __init__(self, type_generator, cpp_namespace):
+ self.h_generator = HGenerator(type_generator, cpp_namespace)
+ self.cc_generator = CCGenerator(type_generator, cpp_namespace)
diff --git a/chromium/tools/json_schema_compiler/cpp_type_generator.py b/chromium/tools/json_schema_compiler/cpp_type_generator.py
new file mode 100644
index 00000000000..efb712ee728
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/cpp_type_generator.py
@@ -0,0 +1,276 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from code import Code
+from model import Namespace, PropertyType, Type
+import cpp_util
+from json_parse import OrderedDict
+from operator import attrgetter
+import schema_util
+
+class _TypeDependency(object):
+ """Contains information about a dependency a namespace has on a type: the
+ type's model, and whether that dependency is "hard" meaning that it cannot be
+ forward declared.
+ """
+ def __init__(self, type_, hard=False):
+ self.type_ = type_
+ self.hard = hard
+
+ def GetSortKey(self):
+ return '%s.%s' % (self.type_.namespace.name, self.type_.name)
+
+class CppTypeGenerator(object):
+ """Manages the types of properties and provides utilities for getting the
+ C++ type out of a model.Property
+ """
+ def __init__(self, model, schema_loader, default_namespace=None):
+ """Creates a cpp_type_generator. The given root_namespace should be of the
+ format extensions::api::sub. The generator will generate code suitable for
+ use in the given model's namespace.
+ """
+ self._default_namespace = default_namespace
+ if self._default_namespace is None:
+ self._default_namespace = model.namespaces.values()[0]
+ self._schema_loader = schema_loader
+
+ def GetCppNamespaceName(self, namespace):
+ """Gets the mapped C++ namespace name for the given namespace relative to
+ the root namespace.
+ """
+ return namespace.unix_name
+
+ def GetNamespaceStart(self):
+ """Get opening self._default_namespace namespace declaration.
+ """
+ return Code().Append('namespace %s {' %
+ self.GetCppNamespaceName(self._default_namespace))
+
+ def GetNamespaceEnd(self):
+ """Get closing self._default_namespace namespace declaration.
+ """
+ return Code().Append('} // %s' %
+ self.GetCppNamespaceName(self._default_namespace))
+
+ def GetEnumNoneValue(self, type_):
+ """Gets the enum value in the given model.Property indicating no value has
+ been set.
+ """
+ return '%s_NONE' % self.FollowRef(type_).unix_name.upper()
+
+ def GetEnumValue(self, type_, enum_value):
+ """Gets the enum value of the given model.Property of the given type.
+
+ e.g VAR_STRING
+ """
+ value = '%s_%s' % (self.FollowRef(type_).unix_name.upper(),
+ cpp_util.Classname(enum_value.upper()))
+ # To avoid collisions with built-in OS_* preprocessor definitions, we add a
+ # trailing slash to enum names that start with OS_.
+ if value.startswith("OS_"):
+ value += "_"
+ return value
+
+ def GetCppType(self, type_, is_ptr=False, is_in_container=False):
+ """Translates a model.Property or model.Type into its C++ type.
+
+ If REF types from different namespaces are referenced, will resolve
+ using self._schema_loader.
+
+ Use |is_ptr| if the type is optional. This will wrap the type in a
+ scoped_ptr if possible (it is not possible to wrap an enum).
+
+ Use |is_in_container| if the type is appearing in a collection, e.g. a
+ std::vector or std::map. This will wrap it in the correct type with spacing.
+ """
+ cpp_type = None
+ if type_.property_type == PropertyType.REF:
+ ref_type = self._FindType(type_.ref_type)
+ if ref_type is None:
+ raise KeyError('Cannot find referenced type: %s' % type_.ref_type)
+ if self._default_namespace is ref_type.namespace:
+ cpp_type = ref_type.name
+ else:
+ cpp_type = '%s::%s' % (ref_type.namespace.unix_name, ref_type.name)
+ elif type_.property_type == PropertyType.BOOLEAN:
+ cpp_type = 'bool'
+ elif type_.property_type == PropertyType.INTEGER:
+ cpp_type = 'int'
+ elif type_.property_type == PropertyType.INT64:
+ cpp_type = 'int64'
+ elif type_.property_type == PropertyType.DOUBLE:
+ cpp_type = 'double'
+ elif type_.property_type == PropertyType.STRING:
+ cpp_type = 'std::string'
+ elif type_.property_type == PropertyType.ENUM:
+ cpp_type = cpp_util.Classname(type_.name)
+ elif type_.property_type == PropertyType.ANY:
+ cpp_type = 'base::Value'
+ elif (type_.property_type == PropertyType.OBJECT or
+ type_.property_type == PropertyType.CHOICES):
+ cpp_type = cpp_util.Classname(type_.name)
+ elif type_.property_type == PropertyType.FUNCTION:
+ # Functions come into the json schema compiler as empty objects. We can
+ # record these as empty DictionaryValues so that we know if the function
+ # was passed in or not.
+ cpp_type = 'base::DictionaryValue'
+ elif type_.property_type == PropertyType.ARRAY:
+ item_cpp_type = self.GetCppType(type_.item_type, is_in_container=True)
+ cpp_type = 'std::vector<%s>' % cpp_util.PadForGenerics(item_cpp_type)
+ elif type_.property_type == PropertyType.BINARY:
+ cpp_type = 'std::string'
+ else:
+ raise NotImplementedError('Cannot get type of %s' % type_.property_type)
+
+ # HACK: optional ENUM is represented elsewhere with a _NONE value, so it
+ # never needs to be wrapped in pointer shenanigans.
+ # TODO(kalman): change this - but it's an exceedingly far-reaching change.
+ if not self.FollowRef(type_).property_type == PropertyType.ENUM:
+ if is_in_container and (is_ptr or not self.IsCopyable(type_)):
+ cpp_type = 'linked_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
+ elif is_ptr:
+ cpp_type = 'scoped_ptr<%s>' % cpp_util.PadForGenerics(cpp_type)
+
+ return cpp_type
+
+ def IsCopyable(self, type_):
+ return not (self.FollowRef(type_).property_type in (PropertyType.ANY,
+ PropertyType.ARRAY,
+ PropertyType.OBJECT,
+ PropertyType.CHOICES))
+
+ def GenerateForwardDeclarations(self):
+ """Returns the forward declarations for self._default_namespace.
+ """
+ c = Code()
+
+ for namespace, dependencies in self._NamespaceTypeDependencies().items():
+ c.Append('namespace %s {' % namespace.unix_name)
+ for dependency in dependencies:
+ # No point forward-declaring hard dependencies.
+ if dependency.hard:
+ continue
+ # Add more ways to forward declare things as necessary.
+ if dependency.type_.property_type in (PropertyType.CHOICES,
+ PropertyType.OBJECT):
+ c.Append('struct %s;' % dependency.type_.name)
+ c.Append('}')
+
+ return c
+
+ def GenerateIncludes(self, include_soft=False):
+ """Returns the #include lines for self._default_namespace.
+ """
+ c = Code()
+ for namespace, dependencies in self._NamespaceTypeDependencies().items():
+ for dependency in dependencies:
+ if dependency.hard or include_soft:
+ c.Append('#include "%s/%s.h"' % (namespace.source_file_dir,
+ namespace.unix_name))
+ return c
+
+ def _FindType(self, full_name):
+ """Finds the model.Type with name |qualified_name|. If it's not from
+ |self._default_namespace| then it needs to be qualified.
+ """
+ namespace = self._schema_loader.ResolveType(full_name,
+ self._default_namespace)
+ if namespace is None:
+ raise KeyError('Cannot resolve type %s. Maybe it needs a prefix '
+ 'if it comes from another namespace?' % full_name)
+ return namespace.types[schema_util.StripNamespace(full_name)]
+
+ def FollowRef(self, type_):
+ """Follows $ref link of types to resolve the concrete type a ref refers to.
+
+ If the property passed in is not of type PropertyType.REF, it will be
+ returned unchanged.
+ """
+ if type_.property_type != PropertyType.REF:
+ return type_
+ return self.FollowRef(self._FindType(type_.ref_type))
+
+ def _NamespaceTypeDependencies(self):
+ """Returns a dict ordered by namespace name containing a mapping of
+ model.Namespace to every _TypeDependency for |self._default_namespace|,
+ sorted by the type's name.
+ """
+ dependencies = set()
+ for function in self._default_namespace.functions.values():
+ for param in function.params:
+ dependencies |= self._TypeDependencies(param.type_,
+ hard=not param.optional)
+ if function.callback:
+ for param in function.callback.params:
+ dependencies |= self._TypeDependencies(param.type_,
+ hard=not param.optional)
+ for type_ in self._default_namespace.types.values():
+ for prop in type_.properties.values():
+ dependencies |= self._TypeDependencies(prop.type_,
+ hard=not prop.optional)
+ for event in self._default_namespace.events.values():
+ for param in event.params:
+ dependencies |= self._TypeDependencies(param.type_,
+ hard=not param.optional)
+
+ # Make sure that the dependencies are returned in alphabetical order.
+ dependency_namespaces = OrderedDict()
+ for dependency in sorted(dependencies, key=_TypeDependency.GetSortKey):
+ namespace = dependency.type_.namespace
+ if namespace is self._default_namespace:
+ continue
+ if namespace not in dependency_namespaces:
+ dependency_namespaces[namespace] = []
+ dependency_namespaces[namespace].append(dependency)
+
+ return dependency_namespaces
+
+ def _TypeDependencies(self, type_, hard=False):
+ """Gets all the type dependencies of a property.
+ """
+ deps = set()
+ if type_.property_type == PropertyType.REF:
+ deps.add(_TypeDependency(self._FindType(type_.ref_type), hard=hard))
+ elif type_.property_type == PropertyType.ARRAY:
+ # Non-copyable types are not hard because they are wrapped in linked_ptrs
+ # when generated. Otherwise they're typedefs, so they're hard (though we
+ # could generate those typedefs in every dependent namespace, but that
+ # seems weird).
+ deps = self._TypeDependencies(type_.item_type,
+ hard=self.IsCopyable(type_.item_type))
+ elif type_.property_type == PropertyType.CHOICES:
+ for type_ in type_.choices:
+ deps |= self._TypeDependencies(type_, hard=self.IsCopyable(type_))
+ elif type_.property_type == PropertyType.OBJECT:
+ for p in type_.properties.values():
+ deps |= self._TypeDependencies(p.type_, hard=not p.optional)
+ return deps
+
+ def GeneratePropertyValues(self, property, line, nodoc=False):
+ """Generates the Code to display all value-containing properties.
+ """
+ c = Code()
+ if not nodoc:
+ c.Comment(property.description)
+
+ if property.value is not None:
+ c.Append(line % {
+ "type": self.GetCppType(property.type_),
+ "name": property.name,
+ "value": property.value
+ })
+ else:
+ has_child_code = False
+ c.Sblock('namespace %s {' % property.name)
+ for child_property in property.type_.properties.values():
+ child_code = self.GeneratePropertyValues(child_property,
+ line,
+ nodoc=nodoc)
+ if child_code:
+ has_child_code = True
+ c.Concat(child_code)
+ c.Eblock('} // namespace %s' % property.name)
+ if not has_child_code:
+ c = None
+ return c
diff --git a/chromium/tools/json_schema_compiler/cpp_type_generator_test.py b/chromium/tools/json_schema_compiler/cpp_type_generator_test.py
new file mode 100755
index 00000000000..7782b234a4c
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/cpp_type_generator_test.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from cpp_type_generator import CppTypeGenerator
+from json_schema import CachedLoad
+import model
+import unittest
+
+from collections import defaultdict
+
+class _FakeSchemaLoader(object):
+ def __init__(self, model):
+ self._model = model
+
+ def ResolveType(self, type_name, default):
+ parts = type_name.rsplit('.', 1)
+ if len(parts) == 1:
+ return default if type_name in default.types else None
+ return self._model.namespaces[parts[0]]
+
+class CppTypeGeneratorTest(unittest.TestCase):
+ def setUp(self):
+ self.models = defaultdict(model.Model)
+
+ self.forbidden_json = CachedLoad('test/forbidden.json')
+ self.forbidden = self.models['forbidden'].AddNamespace(
+ self.forbidden_json[0], 'path/to/forbidden.json')
+ self.permissions_json = CachedLoad('test/permissions.json')
+ self.permissions = self.models['permissions'].AddNamespace(
+ self.permissions_json[0], 'path/to/permissions.json')
+ self.windows_json = CachedLoad('test/windows.json')
+ self.windows = self.models['windows'].AddNamespace(self.windows_json[0],
+ 'path/to/window.json')
+ self.tabs_json = CachedLoad('test/tabs.json')
+ self.tabs = self.models['tabs'].AddNamespace(self.tabs_json[0],
+ 'path/to/tabs.json')
+ self.browser_action_json = CachedLoad('test/browser_action.json')
+ self.browser_action = self.models['browser_action'].AddNamespace(
+ self.browser_action_json[0], 'path/to/browser_action.json')
+ self.font_settings_json = CachedLoad('test/font_settings.json')
+ self.font_settings = self.models['font_settings'].AddNamespace(
+ self.font_settings_json[0], 'path/to/font_settings.json')
+ self.dependency_tester_json = CachedLoad('test/dependency_tester.json')
+ self.dependency_tester = self.models['dependency_tester'].AddNamespace(
+ self.dependency_tester_json[0], 'path/to/dependency_tester.json')
+ self.content_settings_json = CachedLoad('test/content_settings.json')
+ self.content_settings = self.models['content_settings'].AddNamespace(
+ self.content_settings_json[0], 'path/to/content_settings.json')
+
+ def testGenerateIncludesAndForwardDeclarations(self):
+ m = model.Model()
+ m.AddNamespace(self.windows_json[0], 'path/to/windows.json')
+ m.AddNamespace(self.tabs_json[0], 'path/to/tabs.json')
+ manager = CppTypeGenerator(m, _FakeSchemaLoader(m))
+
+ self.assertEquals('', manager.GenerateIncludes().Render())
+ self.assertEquals('#include "path/to/tabs.h"',
+ manager.GenerateIncludes(include_soft=True).Render())
+ self.assertEquals('namespace tabs {\n'
+ 'struct Tab;\n'
+ '}',
+ manager.GenerateForwardDeclarations().Render())
+ manager = CppTypeGenerator(self.models.get('permissions'),
+ _FakeSchemaLoader(m))
+ self.assertEquals('', manager.GenerateIncludes().Render())
+ self.assertEquals('', manager.GenerateIncludes().Render())
+ self.assertEquals('', manager.GenerateForwardDeclarations().Render())
+ manager = CppTypeGenerator(self.models.get('content_settings'),
+ _FakeSchemaLoader(m))
+ self.assertEquals('', manager.GenerateIncludes().Render())
+
+ def testGenerateIncludesAndForwardDeclarationsDependencies(self):
+ m = model.Model()
+ # Insert 'font_settings' before 'browser_action' in order to test that
+ # CppTypeGenerator sorts them properly.
+ m.AddNamespace(self.font_settings_json[0], 'path/to/font_settings.json')
+ m.AddNamespace(self.browser_action_json[0], 'path/to/browser_action.json')
+ dependency_tester = m.AddNamespace(self.dependency_tester_json[0],
+ 'path/to/dependency_tester.json')
+ manager = CppTypeGenerator(m,
+ _FakeSchemaLoader(m),
+ default_namespace=dependency_tester)
+ self.assertEquals('#include "path/to/browser_action.h"\n'
+ '#include "path/to/font_settings.h"',
+ manager.GenerateIncludes().Render())
+ self.assertEquals('namespace browser_action {\n'
+ '}\n'
+ 'namespace font_settings {\n'
+ '}',
+ manager.GenerateForwardDeclarations().Render())
+
+ def testGetCppTypeSimple(self):
+ manager = CppTypeGenerator(self.models.get('tabs'), _FakeSchemaLoader(None))
+ self.assertEquals(
+ 'int',
+ manager.GetCppType(self.tabs.types['Tab'].properties['id'].type_))
+ self.assertEquals(
+ 'std::string',
+ manager.GetCppType(self.tabs.types['Tab'].properties['status'].type_))
+ self.assertEquals(
+ 'bool',
+ manager.GetCppType(self.tabs.types['Tab'].properties['selected'].type_))
+
+ def testStringAsType(self):
+ manager = CppTypeGenerator(self.models.get('font_settings'),
+ _FakeSchemaLoader(None))
+ self.assertEquals(
+ 'std::string',
+ manager.GetCppType(self.font_settings.types['FakeStringType']))
+
+ def testArrayAsType(self):
+ manager = CppTypeGenerator(self.models.get('browser_action'),
+ _FakeSchemaLoader(None))
+ self.assertEquals(
+ 'std::vector<int>',
+ manager.GetCppType(self.browser_action.types['ColorArray']))
+
+ def testGetCppTypeArray(self):
+ manager = CppTypeGenerator(self.models.get('windows'),
+ _FakeSchemaLoader(None))
+ self.assertEquals(
+ 'std::vector<linked_ptr<Window> >',
+ manager.GetCppType(
+ self.windows.functions['getAll'].callback.params[0].type_))
+ manager = CppTypeGenerator(self.models.get('permissions'),
+ _FakeSchemaLoader(None))
+ self.assertEquals(
+ 'std::vector<std::string>',
+ manager.GetCppType(
+ self.permissions.types['Permissions'].properties['origins'].type_))
+
+ def testGetCppTypeLocalRef(self):
+ manager = CppTypeGenerator(self.models.get('tabs'), _FakeSchemaLoader(None))
+ self.assertEquals(
+ 'Tab',
+ manager.GetCppType(self.tabs.functions['get'].callback.params[0].type_))
+
+ def testGetCppTypeIncludedRef(self):
+ m = model.Model()
+ m.AddNamespace(self.windows_json[0], 'path/to/windows.json')
+ m.AddNamespace(self.tabs_json[0], 'path/to/tabs.json')
+ manager = CppTypeGenerator(m, _FakeSchemaLoader(m))
+ self.assertEquals(
+ 'std::vector<linked_ptr<tabs::Tab> >',
+ manager.GetCppType(
+ self.windows.types['Window'].properties['tabs'].type_))
+
+ def testGetCppTypeWithPadForGeneric(self):
+ manager = CppTypeGenerator(self.models.get('permissions'),
+ _FakeSchemaLoader(None))
+ self.assertEquals('std::vector<std::string>',
+ manager.GetCppType(
+ self.permissions.types['Permissions'].properties['origins'].type_,
+ is_in_container=False))
+ self.assertEquals('linked_ptr<std::vector<std::string> >',
+ manager.GetCppType(
+ self.permissions.types['Permissions'].properties['origins'].type_,
+ is_in_container=True))
+ self.assertEquals('bool',
+ manager.GetCppType(
+ self.permissions.functions['contains'].callback.params[0].type_,
+ is_in_container=True))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/cpp_util.py b/chromium/tools/json_schema_compiler/cpp_util.py
new file mode 100644
index 00000000000..2de42293fba
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/cpp_util.py
@@ -0,0 +1,113 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utilies and constants specific to Chromium C++ code.
+"""
+
+from code import Code
+from datetime import datetime
+from model import Property, PropertyType, Type
+import os
+import re
+
+CHROMIUM_LICENSE = (
+"""// Copyright (c) %d The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.""" % datetime.now().year
+)
+GENERATED_FILE_MESSAGE = """// GENERATED FROM THE API DEFINITION IN
+// %s
+// DO NOT EDIT.
+"""
+GENERATED_BUNDLE_FILE_MESSAGE = """// GENERATED FROM THE API DEFINITIONS IN
+// %s
+// DO NOT EDIT.
+"""
+
+def Classname(s):
+ """Translates a namespace name or function name into something more
+ suited to C++.
+
+ eg experimental.downloads -> Experimental_Downloads
+ updateAll -> UpdateAll.
+ """
+ return '_'.join([x[0].upper() + x[1:] for x in re.split('\W', s)])
+
+def GetAsFundamentalValue(type_, src, dst):
+ """Returns the C++ code for retrieving a fundamental type from a
+ Value into a variable.
+
+ src: Value*
+ dst: Property*
+ """
+ return {
+ PropertyType.BOOLEAN: '%s->GetAsBoolean(%s)',
+ PropertyType.DOUBLE: '%s->GetAsDouble(%s)',
+ PropertyType.INTEGER: '%s->GetAsInteger(%s)',
+ PropertyType.STRING: '%s->GetAsString(%s)',
+ }[type_.property_type] % (src, dst)
+
+def GetValueType(type_):
+ """Returns the Value::Type corresponding to the model.Type.
+ """
+ return {
+ PropertyType.ARRAY: 'base::Value::TYPE_LIST',
+ PropertyType.BINARY: 'base::Value::TYPE_BINARY',
+ PropertyType.BOOLEAN: 'base::Value::TYPE_BOOLEAN',
+ # PropertyType.CHOICES can be any combination of types.
+ PropertyType.DOUBLE: 'base::Value::TYPE_DOUBLE',
+ PropertyType.ENUM: 'base::Value::TYPE_STRING',
+ PropertyType.FUNCTION: 'base::Value::TYPE_DICTIONARY',
+ PropertyType.INTEGER: 'base::Value::TYPE_INTEGER',
+ PropertyType.OBJECT: 'base::Value::TYPE_DICTIONARY',
+ PropertyType.STRING: 'base::Value::TYPE_STRING',
+ }[type_.property_type]
+
+def GetParameterDeclaration(param, type_):
+ """Gets a parameter declaration of a given model.Property and its C++
+ type.
+ """
+ if param.type_.property_type in (PropertyType.ANY,
+ PropertyType.ARRAY,
+ PropertyType.CHOICES,
+ PropertyType.OBJECT,
+ PropertyType.REF,
+ PropertyType.STRING):
+ arg = 'const %(type)s& %(name)s'
+ else:
+ arg = '%(type)s %(name)s'
+ return arg % {
+ 'type': type_,
+ 'name': param.unix_name,
+ }
+
+def GenerateIfndefName(path, filename):
+ """Formats a path and filename as a #define name.
+
+ e.g chrome/extensions/gen, file.h becomes CHROME_EXTENSIONS_GEN_FILE_H__.
+ """
+ return (('%s_%s_H__' % (path, filename))
+ .upper().replace(os.sep, '_').replace('/', '_'))
+
+def PadForGenerics(var):
+ """Appends a space to |var| if it ends with a >, so that it can be compiled
+ within generic types.
+ """
+ return ('%s ' % var) if var.endswith('>') else var
+
+def OpenNamespace(namespace):
+ """Get opening root namespace declarations.
+ """
+ c = Code()
+ for component in namespace.split('::'):
+ c.Append('namespace %s {' % component)
+ return c
+
+def CloseNamespace(namespace):
+ """Get closing root namespace declarations.
+ """
+ c = Code()
+ for component in reversed(namespace.split('::')):
+ c.Append('} // namespace %s' % component)
+ return c
diff --git a/chromium/tools/json_schema_compiler/cpp_util_test.py b/chromium/tools/json_schema_compiler/cpp_util_test.py
new file mode 100755
index 00000000000..ede309587f3
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/cpp_util_test.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import cpp_util
+import unittest
+
+class CppUtilTest(unittest.TestCase):
+ def testClassname(self):
+ self.assertEquals('Permissions', cpp_util.Classname('permissions'))
+ self.assertEquals('UpdateAllTheThings',
+ cpp_util.Classname('updateAllTheThings'))
+ self.assertEquals('Aa_Bb_Cc', cpp_util.Classname('aa.bb.cc'))
+
+ def testNamespaceDeclaration(self):
+ self.assertEquals('namespace extensions {',
+ cpp_util.OpenNamespace('extensions').Render())
+ self.assertEquals('} // namespace extensions',
+ cpp_util.CloseNamespace('extensions').Render())
+ self.assertEquals('namespace extensions {\n'
+ 'namespace gen {\n'
+ 'namespace api {',
+ cpp_util.OpenNamespace('extensions::gen::api').Render())
+ self.assertEquals('} // namespace api\n'
+ '} // namespace gen\n'
+ '} // namespace extensions',
+ cpp_util.CloseNamespace('extensions::gen::api').Render())
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/dart_generator.py b/chromium/tools/json_schema_compiler/dart_generator.py
new file mode 100644
index 00000000000..3a4c2e33c10
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_generator.py
@@ -0,0 +1,762 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Generator language component for compiler.py that adds Dart language support.
+"""
+
+from code import Code
+from model import *
+from schema_util import *
+
+import os
+from datetime import datetime
+
+LICENSE = (
+"""// Copyright (c) %s, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.""" %
+ datetime.now().year)
+
+class DartGenerator(object):
+ def __init__(self, dart_overrides_dir=None):
+ self._dart_overrides_dir = dart_overrides_dir
+
+ def Generate(self, namespace):
+ return _Generator(namespace, self._dart_overrides_dir).Generate()
+
+class _Generator(object):
+ """A .dart generator for a namespace.
+ """
+
+ def __init__(self, namespace, dart_overrides_dir=None):
+ self._namespace = namespace
+ # TODO(sashab): Once inline type definitions start being added to
+ # self._types, make a _FindType(self, type_) function that looks at
+ # self._namespace.types.
+ self._types = namespace.types
+
+ # Build a dictionary of Type Name --> Custom Dart code.
+ self._type_overrides = {}
+ if dart_overrides_dir is not None:
+ for filename in os.listdir(dart_overrides_dir):
+ if filename.startswith(namespace.unix_name):
+ with open(os.path.join(dart_overrides_dir, filename)) as f:
+ # Split off the namespace and file extension, leaving just the type.
+ type_path = '.'.join(filename.split('.')[1:-1])
+ self._type_overrides[type_path] = f.read()
+
+ # TODO(sashab): Add all inline type definitions to the global Types
+ # dictionary here, so they have proper names, and are implemented along with
+ # all other types. Also update the parameters/members with these types
+ # to reference these new types instead.
+
+ def Generate(self):
+ """Generates a Code object with the .dart for the entire namespace.
+ """
+ c = Code()
+ (c.Append(LICENSE)
+ .Append()
+ .Append('// Generated from namespace: %s' % self._namespace.name)
+ .Append()
+ .Append('part of chrome;'))
+
+ if self._types:
+ (c.Append()
+ .Append('/**')
+ .Append(' * Types')
+ .Append(' */')
+ .Append()
+ )
+ for type_ in self._types.values():
+ # Check for custom dart for this whole type.
+ override = self._GetOverride([type_.name], document_with=type_)
+ c.Cblock(override if override is not None else self._GenerateType(type_))
+
+ if self._namespace.events:
+ (c.Append('/**')
+ .Append(' * Events')
+ .Append(' */')
+ .Append()
+ )
+ for event_name in self._namespace.events:
+ c.Cblock(self._GenerateEvent(self._namespace.events[event_name]))
+
+ (c.Append('/**')
+ .Append(' * Functions')
+ .Append(' */')
+ .Append()
+ )
+ c.Cblock(self._GenerateMainClass())
+
+ return c
+
+ def _GenerateType(self, type_):
+ """Given a Type object, returns the Code with the .dart for this
+ type's definition.
+
+ Assumes this type is a Parameter Type (creatable by user), and creates an
+ object that extends ChromeObject. All parameters are specifiable as named
+ arguments in the constructor, and all methods are wrapped with getters and
+ setters that hide the JS() implementation.
+ """
+ c = Code()
+
+ # Since enums are just treated as strings for now, don't generate their
+ # type.
+ # TODO(sashab): Find a nice way to wrap enum objects.
+ if type_.property_type is PropertyType.ENUM:
+ return c
+
+ (c.Concat(self._GenerateDocumentation(type_))
+ .Sblock('class %(type_name)s extends ChromeObject {')
+ )
+
+ # Check whether this type has function members. If it does, don't allow
+ # public construction.
+ add_public_constructor = all(not self._IsFunction(p.type_)
+ for p in type_.properties.values())
+ constructor_fields = [self._GeneratePropertySignature(p)
+ for p in type_.properties.values()]
+
+ if add_public_constructor:
+ (c.Append('/*')
+ .Append(' * Public constructor')
+ .Append(' */')
+ .Sblock('%(type_name)s({%(constructor_fields)s}) {')
+ )
+
+ for prop_name in type_.properties:
+ (c.Sblock('if (%s != null)' % prop_name)
+ .Append('this.%s = %s;' % (prop_name, prop_name))
+ .Eblock()
+ )
+ (c.Eblock('}')
+ .Append()
+ )
+
+ (c.Append('/*')
+ .Append(' * Private constructor')
+ .Append(' */')
+ .Append('%(type_name)s._proxy(_jsObject) : super._proxy(_jsObject);')
+ )
+
+ # Add an accessor (getter & setter) for each property.
+ properties = [p for p in type_.properties.values()
+ if not self._IsFunction(p.type_)]
+ if properties:
+ (c.Append()
+ .Append('/*')
+ .Append(' * Public accessors')
+ .Append(' */')
+ )
+ for prop in properties:
+ override = self._GetOverride([type_.name, prop.name], document_with=prop)
+ c.Concat(override if override is not None
+ else self._GenerateGetterAndSetter(type_, prop))
+
+ # Now add all the methods.
+ methods = [t for t in type_.properties.values()
+ if self._IsFunction(t.type_)]
+ if methods:
+ (c.Append()
+ .Append('/*')
+ .Append(' * Methods')
+ .Append(' */')
+ )
+ for prop in methods:
+ # Check if there's an override for this method.
+ override = self._GetOverride([type_.name, prop.name], document_with=prop)
+ c.Cblock(override if override is not None
+ else self._GenerateFunction(prop.type_.function))
+
+ (c.Eblock('}')
+ .Substitute({
+ 'type_name': self._AddPrefix(type_.simple_name),
+ 'constructor_fields': ', '.join(constructor_fields)
+ })
+ )
+
+ return c
+
+ def _GenerateGetterAndSetter(self, type_, prop):
+ """Given a Type and Property, returns the Code object for the getter and
+ setter for that property.
+ """
+ c = Code()
+ override = self._GetOverride([type_.name, prop.name, '.get'],
+ document_with=prop)
+ c.Cblock(override if override is not None
+ else self._GenerateGetter(type_, prop))
+ override = self._GetOverride([type_.name, prop.name, '.set'])
+ c.Cblock(override if override is not None
+ else self._GenerateSetter(type_, prop))
+ return c
+
+ def _GenerateGetter(self, type_, prop):
+ """Given a Type and Property, returns the Code object for the getter for
+ that property.
+
+ Also adds the documentation for this property before the method.
+ """
+ c = Code()
+ c.Concat(self._GenerateDocumentation(prop))
+
+ type_name = self._GetDartType(prop.type_)
+ if (self._IsBaseType(prop.type_)):
+ c.Append("%s get %s => JS('%s', '#.%s', this._jsObject);" %
+ (type_name, prop.name, type_name, prop.name))
+ elif self._IsSerializableObjectType(prop.type_):
+ c.Append("%s get %s => new %s._proxy(JS('', '#.%s', "
+ "this._jsObject));" %
+ (type_name, prop.name, type_name, prop.name))
+ elif self._IsListOfSerializableObjects(prop.type_):
+ (c.Sblock('%s get %s {' % (type_name, prop.name))
+ .Append('%s __proxy_%s = new %s();' % (type_name, prop.name,
+ type_name))
+ .Append("int count = JS('int', '#.%s.length', this._jsObject);" %
+ prop.name)
+ .Sblock("for (int i = 0; i < count; i++) {")
+ .Append("var item = JS('', '#.%s[#]', this._jsObject, i);" % prop.name)
+ .Append('__proxy_%s.add(new %s._proxy(item));' % (prop.name,
+ self._GetDartType(prop.type_.item_type)))
+ .Eblock('}')
+ .Append('return __proxy_%s;' % prop.name)
+ .Eblock('}')
+ )
+ elif self._IsObjectType(prop.type_):
+ # TODO(sashab): Think of a way to serialize generic Dart objects.
+ if type_name in self._types:
+ c.Append("%s get %s => new %s._proxy(JS('%s', '#.%s', "
+ "this._jsObject));" %
+ (type_name, prop.name, type_name, type_name, prop.name))
+ else:
+ c.Append("%s get %s => JS('%s', '#.%s', this._jsObject);" %
+ (type_name, prop.name, type_name, prop.name))
+ else:
+ raise Exception(
+ "Could not generate wrapper for %s.%s: unserializable type %s" %
+ (type_.name, prop.name, type_name)
+ )
+ return c
+
+ def _GenerateSetter(self, type_, prop):
+ """Given a Type and Property, returns the Code object for the setter for
+ that property.
+ """
+ c = Code()
+ type_name = self._GetDartType(prop.type_)
+ wrapped_name = prop.name
+ if not self._IsBaseType(prop.type_):
+ wrapped_name = 'convertArgument(%s)' % prop.name
+
+ (c.Sblock("void set %s(%s %s) {" % (prop.name, type_name, prop.name))
+ .Append("JS('void', '#.%s = #', this._jsObject, %s);" %
+ (prop.name, wrapped_name))
+ .Eblock("}")
+ )
+ return c
+
+ def _GenerateDocumentation(self, prop):
+ """Given an object, generates the documentation for this object (as a
+ code string) and returns the Code object.
+
+ Returns an empty code object if the object has no documentation.
+
+ Uses triple-quotes for the string.
+ """
+ c = Code()
+ if prop.description is not None:
+ for line in prop.description.split('\n'):
+ c.Comment(line, comment_prefix='/// ')
+ return c
+
+ def _GenerateFunction(self, f):
+ """Returns the Code object for the given function.
+ """
+ c = Code()
+ c.Concat(self._GenerateDocumentation(f))
+
+ if not self._NeedsProxiedCallback(f):
+ c.Append("%s => %s;" % (self._GenerateFunctionSignature(f),
+ self._GenerateProxyCall(f)))
+ return c
+
+ (c.Sblock("%s {" % self._GenerateFunctionSignature(f))
+ .Concat(self._GenerateProxiedFunction(f.callback, f.callback.name))
+ .Append('%s;' % self._GenerateProxyCall(f))
+ .Eblock('}')
+ )
+
+ return c
+
+ def _GenerateProxiedFunction(self, f, callback_name):
+ """Given a function (assumed to be a callback), generates the proxied
+ version of this function, which calls |callback_name| if it is defined.
+
+ Returns a Code object.
+ """
+ c = Code()
+ proxied_params = []
+ # A list of Properties, containing List<*> objects that need proxying for
+ # their members (by copying out each member and proxying it).
+ lists_to_proxy = []
+ for p in f.params:
+ if self._IsBaseType(p.type_):
+ proxied_params.append(p.name)
+ elif self._IsSerializableObjectType(p.type_):
+ proxied_params.append('new %s._proxy(%s)' % (
+ self._GetDartType(p.type_), p.name))
+ elif self._IsListOfSerializableObjects(p.type_):
+ proxied_params.append('__proxy_%s' % p.name)
+ lists_to_proxy.append(p)
+ elif self._IsObjectType(p.type_):
+ # TODO(sashab): Find a way to build generic JS objects back in Dart.
+ proxied_params.append('%s' % p.name)
+ elif p.type_.property_type is PropertyType.ARRAY:
+ # TODO(sashab): This might be okay - what if this is a list of
+ # FileEntry elements? In this case, a basic list will proxy the objects
+ # fine.
+ proxied_params.append('%s' % p.name)
+ else:
+ raise Exception(
+ "Cannot automatically create proxy; can't wrap %s, type %s" % (
+ self._GenerateFunctionSignature(f), self._GetDartType(p.type_)))
+
+ (c.Sblock("void __proxy_callback(%s) {" % ', '.join(p.name for p in
+ f.params))
+ .Sblock('if (%s != null) {' % callback_name)
+ )
+
+ # Add the proxied lists.
+ for list_to_proxy in lists_to_proxy:
+ (c.Append("%s __proxy_%s = new %s();" % (
+ self._GetDartType(list_to_proxy.type_),
+ list_to_proxy.name,
+ self._GetDartType(list_to_proxy.type_)))
+ .Sblock("for (var o in %s) {" % list_to_proxy.name)
+ .Append('__proxy_%s.add(new %s._proxy(o));' % (list_to_proxy.name,
+ self._GetDartType(list_to_proxy.type_.item_type)))
+ .Eblock("}")
+ )
+
+ (c.Append("%s(%s);" % (callback_name, ', '.join(proxied_params)))
+ .Eblock('}')
+ .Eblock('}')
+ )
+ return c
+
+ def _NeedsProxiedCallback(self, f):
+ """Given a function, returns True if this function's callback needs to be
+ proxied, False if not.
+
+ Function callbacks need to be proxied if they have at least one
+ non-base-type parameter.
+ """
+ return f.callback and self._NeedsProxy(f.callback)
+
+ def _NeedsProxy(self, f):
+ """Given a function, returns True if it needs to be proxied, False if not.
+
+ A function needs to be proxied if any of its members are non-base types.
+ This means that, when the function object is passed to Javascript, it
+ needs to be wrapped in a "proxied" call that converts the JS inputs to Dart
+ objects explicitly, before calling the real function with these new objects.
+ """
+ return any(not self._IsBaseType(p.type_) for p in f.params)
+
+ def _GenerateProxyCall(self, function, call_target='this._jsObject'):
+ """Given a function, generates the code to call that function via JS().
+ Returns a string.
+
+ |call_target| is the name of the object to call the function on. The default
+ is this._jsObject.
+
+ e.g.
+ JS('void', '#.resizeTo(#, #)', this._jsObject, width, height)
+ JS('void', '#.setBounds(#)', this._jsObject, convertArgument(bounds))
+ """
+ n_params = len(function.params)
+ if function.callback:
+ n_params += 1
+
+ return_type_str = self._GetDartType(function.returns)
+ params = []
+
+ # If this object is serializable, don't convert the type from JS - pass the
+ # JS object straight into the proxy.
+ if self._IsSerializableObjectType(function.returns):
+ params.append("''")
+ else:
+ params.append("'%s'" % return_type_str)
+
+ params.append("'#.%s(%s)'" % (function.name, ', '.join(['#'] * n_params)))
+ params.append(call_target)
+
+ for param in function.params:
+ if not self._IsBaseType(param.type_):
+ params.append('convertArgument(%s)' % param.name)
+ else:
+ params.append(param.name)
+ if function.callback:
+ # If this isn't a base type, we need a proxied callback.
+ callback_name = function.callback.name
+ if self._NeedsProxiedCallback(function):
+ callback_name = "__proxy_callback"
+ params.append('convertDartClosureToJS(%s, %s)' % (callback_name,
+ len(function.callback.params)))
+
+ # If the object is serializable, call the proxy constructor for this type.
+ proxy_call = 'JS(%s)' % ', '.join(params)
+ if self._IsSerializableObjectType(function.returns):
+ proxy_call = 'new %s._proxy(%s)' % (return_type_str, proxy_call)
+
+ return proxy_call
+
+ def _GenerateEvent(self, event):
+ """Given a Function object, returns the Code with the .dart for this event,
+ represented by the function.
+
+ All events extend the Event base type.
+ """
+ c = Code()
+
+ # Add documentation for this event.
+ (c.Concat(self._GenerateDocumentation(event))
+ .Sblock('class Event_%(event_name)s extends Event {')
+ )
+
+ # If this event needs a proxy, all calls need to be proxied.
+ needs_proxy = self._NeedsProxy(event)
+
+ # Override Event callback type definitions.
+ for ret_type, event_func in (('void', 'addListener'),
+ ('void', 'removeListener'),
+ ('bool', 'hasListener')):
+ param_list = self._GenerateParameterList(event.params, event.callback,
+ convert_optional=True)
+ if needs_proxy:
+ (c.Sblock('%s %s(void callback(%s)) {' % (ret_type, event_func,
+ param_list))
+ .Concat(self._GenerateProxiedFunction(event, 'callback'))
+ .Append('super.%s(__proxy_callback);' % event_func)
+ .Eblock('}')
+ )
+ else:
+ c.Append('%s %s(void callback(%s)) => super.%s(callback);' %
+ (ret_type, event_func, param_list, event_func))
+ c.Append()
+
+ # Generate the constructor.
+ (c.Append('Event_%(event_name)s(jsObject) : '
+ 'super._(jsObject, %(param_num)d);')
+ .Eblock('}')
+ .Substitute({
+ 'event_name': self._namespace.unix_name + '_' + event.name,
+ 'param_num': len(event.params)
+ })
+ )
+
+ return c
+
+ def _GenerateMainClass(self):
+ """Generates the main class for this file, which links to all functions
+ and events.
+
+ Returns a code object.
+ """
+ c = Code()
+ (c.Sblock('class API_%s {' % self._namespace.unix_name)
+ .Append('/*')
+ .Append(' * API connection')
+ .Append(' */')
+ .Append('Object _jsObject;')
+ )
+
+ # Add events.
+ if self._namespace.events:
+ (c.Append()
+ .Append('/*')
+ .Append(' * Events')
+ .Append(' */')
+ )
+ for event_name in self._namespace.events:
+ c.Append('Event_%s_%s %s;' % (self._namespace.unix_name, event_name,
+ event_name))
+
+ # Add functions.
+ if self._namespace.functions:
+ (c.Append()
+ .Append('/*')
+ .Append(' * Functions')
+ .Append(' */')
+ )
+ for function in self._namespace.functions.values():
+ # Check for custom dart for this whole property.
+ override = self._GetOverride([function.name], document_with=function)
+ c.Cblock(override if override is not None
+ else self._GenerateFunction(function))
+
+ # Add the constructor.
+ c.Sblock('API_%s(this._jsObject) {' % self._namespace.unix_name)
+
+ # Add events to constructor.
+ for event_name in self._namespace.events:
+ c.Append("%s = new Event_%s_%s(JS('', '#.%s', this._jsObject));" %
+ (event_name, self._namespace.unix_name, event_name, event_name))
+
+ (c.Eblock('}')
+ .Eblock('}')
+ )
+ return c
+
+ def _GeneratePropertySignature(self, prop):
+ """Given a property, returns a signature for that property.
+ Recursively generates the signature for callbacks.
+ Returns a String for the given property.
+
+ e.g.
+ bool x
+ void onClosed()
+ void doSomething(bool x, void callback([String x]))
+ """
+ if self._IsFunction(prop.type_):
+ return self._GenerateFunctionSignature(prop.type_.function)
+ return '%(type)s %(name)s' % {
+ 'type': self._GetDartType(prop.type_),
+ 'name': prop.simple_name
+ }
+
+ def _GenerateFunctionSignature(self, function, convert_optional=False):
+ """Given a function object, returns the signature for that function.
+ Recursively generates the signature for callbacks.
+ Returns a String for the given function.
+
+ If convert_optional is True, changes optional parameters to be required.
+
+ e.g.
+ void onClosed()
+ bool isOpen([String type])
+ void doSomething(bool x, void callback([String x]))
+ """
+ sig = '%(return_type)s %(name)s(%(params)s)'
+
+ if function.returns:
+ return_type = self._GetDartType(function.returns)
+ else:
+ return_type = 'void'
+
+ return sig % {
+ 'return_type': return_type,
+ 'name': function.simple_name,
+ 'params': self._GenerateParameterList(function.params,
+ function.callback,
+ convert_optional=convert_optional)
+ }
+
+ def _GenerateParameterList(self,
+ params,
+ callback=None,
+ convert_optional=False):
+ """Given a list of function parameters, generates their signature (as a
+ string).
+
+ e.g.
+ [String type]
+ bool x, void callback([String x])
+
+ If convert_optional is True, changes optional parameters to be required.
+ Useful for callbacks, where optional parameters are treated as required.
+ """
+ # Params lists (required & optional), to be joined with commas.
+ # TODO(sashab): Don't assume optional params always come after required
+ # ones.
+ params_req = []
+ params_opt = []
+ for param in params:
+ p_sig = self._GeneratePropertySignature(param)
+ if param.optional and not convert_optional:
+ params_opt.append(p_sig)
+ else:
+ params_req.append(p_sig)
+
+ # Add the callback, if it exists.
+ if callback:
+ c_sig = self._GenerateFunctionSignature(callback, convert_optional=True)
+ if callback.optional:
+ params_opt.append(c_sig)
+ else:
+ params_req.append(c_sig)
+
+ # Join the parameters with commas.
+ # Optional parameters have to be in square brackets, e.g.:
+ #
+ # required params | optional params | output
+ # [] | [] | ''
+ # [x, y] | [] | 'x, y'
+ # [] | [a, b] | '[a, b]'
+ # [x, y] | [a, b] | 'x, y, [a, b]'
+ if params_opt:
+ params_opt[0] = '[%s' % params_opt[0]
+ params_opt[-1] = '%s]' % params_opt[-1]
+ param_sets = [', '.join(params_req), ', '.join(params_opt)]
+
+ # The 'if p' part here is needed to prevent commas where there are no
+ # parameters of a certain type.
+ # If there are no optional parameters, this prevents a _trailing_ comma,
+ # e.g. '(x, y,)'. Similarly, if there are no required parameters, this
+ # prevents a leading comma, e.g. '(, [a, b])'.
+ return ', '.join(p for p in param_sets if p)
+
+ def _GetOverride(self, key_chain, document_with=None):
+ """Given a list of keys, joins them with periods and searches for them in
+ the custom dart overrides.
+ If there is an override for that key, finds the override code and returns
+ the Code object. If not, returns None.
+
+ If document_with is not None, adds the documentation for this property
+ before the override code.
+ """
+ c = Code()
+ contents = self._type_overrides.get('.'.join(key_chain))
+ if contents is None:
+ return None
+
+ if document_with is not None:
+ c.Concat(self._GenerateDocumentation(document_with))
+ for line in contents.strip('\n').split('\n'):
+ c.Append(line)
+ return c
+
+ def _AddPrefix(self, name):
+ """Given the name of a type, prefixes the namespace (as camelcase) and
+ returns the new name.
+ """
+ # TODO(sashab): Split the dart library into multiple files, avoiding the
+ # need for this prefixing.
+ return ('%s%s' % (
+ ''.join(s.capitalize() for s in self._namespace.name.split('.')),
+ name))
+
+ def _IsFunction(self, type_):
+ """Given a model.Type, returns whether this type is a function.
+ """
+ return type_.property_type == PropertyType.FUNCTION
+
+ def _IsSerializableObjectType(self, type_):
+ """Given a model.Type, returns whether this type is a serializable object.
+ Serializable objects are custom types defined in this namespace.
+
+ If this object is a reference to something not in this namespace, assumes
+ its a serializable object.
+ """
+ if type_ is None:
+ return False
+ if type_.property_type is PropertyType.CHOICES:
+ return all(self._IsSerializableObjectType(c) for c in type_.choices)
+ if type_.property_type is PropertyType.REF:
+ if type_.ref_type in self._types:
+ return self._IsObjectType(self._types[type_.ref_type])
+ return True
+ if (type_.property_type == PropertyType.OBJECT
+ and type_.instance_of in self._types):
+ return self._IsObjectType(self._types[type_.instance_of])
+ return False
+
+ def _IsObjectType(self, type_):
+ """Given a model.Type, returns whether this type is an object.
+ """
+ return (self._IsSerializableObjectType(type_)
+ or type_.property_type in [PropertyType.OBJECT, PropertyType.ANY])
+
+ def _IsListOfSerializableObjects(self, type_):
+ """Given a model.Type, returns whether this type is a list of serializable
+ objects (or regular objects, if this list is treated as a type - in this
+ case, the item type was defined inline).
+
+ If this type is a reference to something not in this namespace, assumes
+ it is not a list of serializable objects.
+ """
+ if type_.property_type is PropertyType.CHOICES:
+ return all(self._IsListOfSerializableObjects(c) for c in type_.choices)
+ if type_.property_type is PropertyType.REF:
+ if type_.ref_type in self._types:
+ return self._IsListOfSerializableObjects(self._types[type_.ref_type])
+ return False
+ return (type_.property_type is PropertyType.ARRAY and
+ (self._IsSerializableObjectType(type_.item_type)))
+
+ def _IsListOfBaseTypes(self, type_):
+ """Given a model.Type, returns whether this type is a list of base type
+ objects (PropertyType.REF types).
+ """
+ if type_.property_type is PropertyType.CHOICES:
+ return all(self._IsListOfBaseTypes(c) for c in type_.choices)
+ return (type_.property_type is PropertyType.ARRAY and
+ self._IsBaseType(type_.item_type))
+
+ def _IsBaseType(self, type_):
+ """Given a model.type_, returns whether this type is a base type
+ (string, number, boolean, or a list of these).
+
+ If type_ is a Choices object, returns True if all possible choices are base
+ types.
+ """
+ # TODO(sashab): Remove 'Choices' as a base type once they are wrapped in
+ # native Dart classes.
+ if type_.property_type is PropertyType.CHOICES:
+ return all(self._IsBaseType(c) for c in type_.choices)
+ return (
+ (self._GetDartType(type_) in ['bool', 'num', 'int', 'double', 'String'])
+ or (type_.property_type is PropertyType.ARRAY
+ and self._IsBaseType(type_.item_type))
+ )
+
+ def _GetDartType(self, type_):
+ """Given a model.Type object, returns its type as a Dart string.
+ """
+ if type_ is None:
+ return 'void'
+
+ prop_type = type_.property_type
+ if prop_type is PropertyType.REF:
+ if type_.ref_type in self._types:
+ return self._GetDartType(self._types[type_.ref_type])
+ # TODO(sashab): If the type is foreign, it might have to be imported.
+ return StripNamespace(type_.ref_type)
+ elif prop_type is PropertyType.BOOLEAN:
+ return 'bool'
+ elif prop_type is PropertyType.INTEGER:
+ return 'int'
+ elif prop_type is PropertyType.INT64:
+ return 'num'
+ elif prop_type is PropertyType.DOUBLE:
+ return 'double'
+ elif prop_type is PropertyType.STRING:
+ return 'String'
+ elif prop_type is PropertyType.ENUM:
+ return 'String'
+ elif prop_type is PropertyType.CHOICES:
+ # TODO(sashab): Think of a nice way to generate code for Choices objects
+ # in Dart.
+ return 'Object'
+ elif prop_type is PropertyType.ANY:
+ return 'Object'
+ elif prop_type is PropertyType.OBJECT:
+ # TODO(sashab): type_.name is the name of the function's parameter for
+ # inline types defined in functions. Think of a way to generate names
+ # for this, or remove all inline type definitions at the start.
+ if type_.instance_of is not None:
+ return type_.instance_of
+ if not isinstance(type_.parent, Function):
+ return self._AddPrefix(type_.name)
+ return 'Object'
+ elif prop_type is PropertyType.FUNCTION:
+ return 'Function'
+ elif prop_type is PropertyType.ARRAY:
+ return 'List<%s>' % self._GetDartType(type_.item_type)
+ elif prop_type is PropertyType.BINARY:
+ return 'String'
+ else:
+ raise NotImplementedError(prop_type)
+
diff --git a/chromium/tools/json_schema_compiler/dart_generator_test.py b/chromium/tools/json_schema_compiler/dart_generator_test.py
new file mode 100755
index 00000000000..65ec7f1e638
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_generator_test.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import unittest
+import glob
+
+from dart_generator import DartGenerator
+from compiler import GenerateSchema
+
+# If --rebase is passed to this test, this is set to True, indicating the test
+# output should be re-generated for each test (rather than running the tests
+# themselves).
+REBASE_MODE = False
+
+# The directory containing the input and expected output files corresponding
+# to each test name.
+TESTS_DIR = 'dart_test'
+
+class DartTest(unittest.TestCase):
+
+ def _RunTest(self, test_filename):
+ '''Given the name of a test, runs compiler.py on the file:
+ TESTS_DIR/test_filename.idl
+ and compares it to the output in the file:
+ TESTS_DIR/test_filename.dart
+ '''
+ file_rel = os.path.join(TESTS_DIR, test_filename)
+
+ output_dir = None
+ if REBASE_MODE:
+ output_dir = TESTS_DIR
+ output_code = GenerateSchema('dart', ['%s.idl' % file_rel], TESTS_DIR,
+ output_dir, None, None)
+
+ if not REBASE_MODE:
+ with open('%s.dart' % file_rel) as f:
+ expected_output = f.read()
+ # Remove the first line of the output code (as it contains the filename).
+ # Also remove all blank lines, ignoring them from the comparison.
+ # Compare with lists instead of strings for clearer diffs (especially with
+ # whitespace) when a test fails.
+ self.assertEqual([l for l in expected_output.split('\n') if l],
+ [l for l in output_code.split('\n')[1:] if l])
+
+ def setUp(self):
+ # Increase the maximum diff amount to see the full diff on a failed test.
+ self.maxDiff = 2000
+
+ def testComments(self):
+ self._RunTest('comments')
+
+ def testDictionaries(self):
+ self._RunTest('dictionaries')
+
+ def testEmptyNamespace(self):
+ self._RunTest('empty_namespace')
+
+ def testEmptyType(self):
+ self._RunTest('empty_type')
+
+ def testEvents(self):
+ self._RunTest('enums')
+
+ def testEvents(self):
+ self._RunTest('events')
+
+ def testBasicFunction(self):
+ self._RunTest('functions')
+
+ def testOpratableType(self):
+ self._RunTest('operatable_type')
+
+ def testTags(self):
+ self._RunTest('tags')
+
+if __name__ == '__main__':
+ if '--rebase' in sys.argv:
+ print "Running in rebase mode."
+ REBASE_MODE = True
+ sys.argv.remove('--rebase')
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/dart_test/comments.dart b/chromium/tools/json_schema_compiler/dart_test/comments.dart
new file mode 100644
index 00000000000..d734d56f522
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/comments.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated from namespace: comments
+
+part of chrome;
+/**
+ * Functions
+ */
+
+class API_comments {
+ /*
+ * API connection
+ */
+ Object _jsObject;
+
+ /*
+ * Functions
+ */
+ /// There's a blank line at the start of this comment. Documentation for
+ /// basicFunction. BasicFunction() is a great function. There is a newline
+ /// after this.<br/><br/> It works like so: +-----+ | |
+ /// +--+ | | | | +-----+ --> +--+<br/><br/> Some other
+ /// stuff here. This paragraph starts with whitespace. Overall, its a
+ /// great function. There's also a blank line at the end of this comment.
+ void basicFunction() => JS('void', '#.basicFunction()', this._jsObject);
+
+ API_comments(this._jsObject) {
+ }
+}
diff --git a/chromium/tools/json_schema_compiler/dart_test/comments.idl b/chromium/tools/json_schema_compiler/dart_test/comments.idl
new file mode 100644
index 00000000000..867d289d264
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/comments.idl
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This comment is for the comments namespace.
+namespace comments {
+ // This comments the "Functions" block, and should be ignored.
+ interface Functions {
+ // This comment is separated by at least one blank line from the start of
+ // the function, and should be ignored.
+
+ //
+ // There's a blank line at the start of this comment.
+ //
+ // Documentation for basicFunction.
+ // BasicFunction() is a great function.
+ // There is a newline after this.
+ //
+ // It works like so:
+ // +-----+
+ // | | +--+
+ // | | | |
+ // +-----+ --> +--+
+ //
+ // Some other stuff here.
+ // This paragraph starts with whitespace.
+ // Overall, its a great function.
+ // There's also a blank line at the end of this comment.
+ //
+ static void basicFunction();
+ };
+};
diff --git a/chromium/tools/json_schema_compiler/dart_test/dictionaries.dart b/chromium/tools/json_schema_compiler/dart_test/dictionaries.dart
new file mode 100644
index 00000000000..ebe92a6c1eb
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/dictionaries.dart
@@ -0,0 +1,235 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated from namespace: dictionaries
+
+part of chrome;
+
+/**
+ * Types
+ */
+
+class DictionariesInnerType extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ DictionariesInnerType({String s, int b, int i, int l, double d, FileEntry f, String os, int ob, int oi, int ol, double od, FileEntry of}) {
+ if (s != null)
+ this.s = s;
+ if (b != null)
+ this.b = b;
+ if (i != null)
+ this.i = i;
+ if (l != null)
+ this.l = l;
+ if (d != null)
+ this.d = d;
+ if (f != null)
+ this.f = f;
+ if (os != null)
+ this.os = os;
+ if (ob != null)
+ this.ob = ob;
+ if (oi != null)
+ this.oi = oi;
+ if (ol != null)
+ this.ol = ol;
+ if (od != null)
+ this.od = od;
+ if (of != null)
+ this.of = of;
+ }
+
+ /*
+ * Private constructor
+ */
+ DictionariesInnerType._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ /// Documentation for the String s.
+ String get s => JS('String', '#.s', this._jsObject);
+
+ void set s(String s) {
+ JS('void', '#.s = #', this._jsObject, s);
+ }
+
+ /// Documentation for the boolean b.
+ int get b => JS('int', '#.b', this._jsObject);
+
+ void set b(int b) {
+ JS('void', '#.b = #', this._jsObject, b);
+ }
+
+ /// Documentation for the int i.
+ int get i => JS('int', '#.i', this._jsObject);
+
+ void set i(int i) {
+ JS('void', '#.i = #', this._jsObject, i);
+ }
+
+ /// Documentation for the long l.
+ int get l => JS('int', '#.l', this._jsObject);
+
+ void set l(int l) {
+ JS('void', '#.l = #', this._jsObject, l);
+ }
+
+ /// Documentation for the double d.
+ double get d => JS('double', '#.d', this._jsObject);
+
+ void set d(double d) {
+ JS('void', '#.d = #', this._jsObject, d);
+ }
+
+ /// Documentation for the file entry f.
+ FileEntry get f => JS('FileEntry', '#.f', this._jsObject);
+
+ void set f(FileEntry f) {
+ JS('void', '#.f = #', this._jsObject, convertArgument(f));
+ }
+
+ /// Documentation for the optional String s.
+ String get os => JS('String', '#.os', this._jsObject);
+
+ void set os(String os) {
+ JS('void', '#.os = #', this._jsObject, os);
+ }
+
+ /// Documentation for the optional boolean ob.
+ int get ob => JS('int', '#.ob', this._jsObject);
+
+ void set ob(int ob) {
+ JS('void', '#.ob = #', this._jsObject, ob);
+ }
+
+ /// Documentation for the optional int i.
+ int get oi => JS('int', '#.oi', this._jsObject);
+
+ void set oi(int oi) {
+ JS('void', '#.oi = #', this._jsObject, oi);
+ }
+
+ /// Documentation for the optional long l.
+ int get ol => JS('int', '#.ol', this._jsObject);
+
+ void set ol(int ol) {
+ JS('void', '#.ol = #', this._jsObject, ol);
+ }
+
+ /// Documentation for the optional double d.
+ double get od => JS('double', '#.od', this._jsObject);
+
+ void set od(double od) {
+ JS('void', '#.od = #', this._jsObject, od);
+ }
+
+ /// Documentation for the optional file entry f.
+ FileEntry get of => JS('FileEntry', '#.of', this._jsObject);
+
+ void set of(FileEntry of) {
+ JS('void', '#.of = #', this._jsObject, convertArgument(of));
+ }
+
+}
+
+class DictionariesOuterType extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ DictionariesOuterType({List<DictionariesInnerType> items, List<DictionariesInnerType> oitems}) {
+ if (items != null)
+ this.items = items;
+ if (oitems != null)
+ this.oitems = oitems;
+ }
+
+ /*
+ * Private constructor
+ */
+ DictionariesOuterType._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ /// Documentation for the array of InnerTypes items.
+ List<DictionariesInnerType> get items {
+ List<DictionariesInnerType> __proxy_items = new List<DictionariesInnerType>();
+ int count = JS('int', '#.items.length', this._jsObject);
+ for (int i = 0; i < count; i++) {
+ var item = JS('', '#.items[#]', this._jsObject, i);
+ __proxy_items.add(new DictionariesInnerType._proxy(item));
+ }
+ return __proxy_items;
+ }
+
+ void set items(List<DictionariesInnerType> items) {
+ JS('void', '#.items = #', this._jsObject, convertArgument(items));
+ }
+
+ /// Documentation for the optional array of Inner Types oitems.
+ List<DictionariesInnerType> get oitems {
+ List<DictionariesInnerType> __proxy_oitems = new List<DictionariesInnerType>();
+ int count = JS('int', '#.oitems.length', this._jsObject);
+ for (int i = 0; i < count; i++) {
+ var item = JS('', '#.oitems[#]', this._jsObject, i);
+ __proxy_oitems.add(new DictionariesInnerType._proxy(item));
+ }
+ return __proxy_oitems;
+ }
+
+ void set oitems(List<DictionariesInnerType> oitems) {
+ JS('void', '#.oitems = #', this._jsObject, convertArgument(oitems));
+ }
+
+}
+
+class DictionariesComplexType extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ DictionariesComplexType({int i, DictionariesComplexType c}) {
+ if (i != null)
+ this.i = i;
+ if (c != null)
+ this.c = c;
+ }
+
+ /*
+ * Private constructor
+ */
+ DictionariesComplexType._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ /// Documentation for the int i.
+ int get i => JS('int', '#.i', this._jsObject);
+
+ void set i(int i) {
+ JS('void', '#.i = #', this._jsObject, i);
+ }
+
+ /// Documentation for the ComplexType c.
+ DictionariesComplexType get c => new DictionariesComplexType._proxy(JS('', '#.c', this._jsObject));
+
+ void set c(DictionariesComplexType c) {
+ JS('void', '#.c = #', this._jsObject, convertArgument(c));
+ }
+
+}
+
+/**
+ * Functions
+ */
+
+class API_dictionaries {
+ /*
+ * API connection
+ */
+ Object _jsObject;
+ API_dictionaries(this._jsObject) {
+ }
+}
diff --git a/chromium/tools/json_schema_compiler/dart_test/dictionaries.idl b/chromium/tools/json_schema_compiler/dart_test/dictionaries.idl
new file mode 100644
index 00000000000..1eb9e25e0a0
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/dictionaries.idl
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This comment is for the dictionaries namespace.
+namespace dictionaries {
+ // Documentation for ComplexType.
+ dictionary InnerType {
+ // Documentation for the String s.
+ DOMString s;
+
+ // Documentation for the boolean b.
+ int b;
+
+ // Documentation for the int i.
+ int i;
+
+ // Documentation for the long l.
+ long l;
+
+ // Documentation for the double d.
+ double d;
+
+ // Documentation for the file entry f.
+ [instanceOf=FileEntry] object f;
+
+ // Documentation for the optional String s.
+ DOMString? os;
+
+ // Documentation for the optional boolean ob.
+ int ob;
+
+ // Documentation for the optional int i.
+ int? oi;
+
+ // Documentation for the optional long l.
+ long? ol;
+
+ // Documentation for the optional double d.
+ double? od;
+
+ // Documentation for the optional file entry f.
+ [instanceOf=FileEntry] object? of;
+ };
+
+ dictionary OuterType {
+ // Documentation for the array of InnerTypes items.
+ InnerType[] items;
+
+ // Documentation for the optional array of Inner Types oitems.
+ InnerType[]? oitems;
+ };
+
+ dictionary ComplexType {
+ // Documentation for the int i.
+ int i;
+
+ // Documentation for the ComplexType c.
+ ComplexType c;
+ };
+};
diff --git a/chromium/tools/json_schema_compiler/dart_test/empty_namespace.dart b/chromium/tools/json_schema_compiler/dart_test/empty_namespace.dart
new file mode 100644
index 00000000000..d2378a2860c
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/empty_namespace.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated from namespace: empty_namespace
+
+part of chrome;
+/**
+ * Functions
+ */
+
+class API_empty_namespace {
+ /*
+ * API connection
+ */
+ Object _jsObject;
+ API_empty_namespace(this._jsObject) {
+ }
+}
diff --git a/chromium/tools/json_schema_compiler/dart_test/empty_namespace.idl b/chromium/tools/json_schema_compiler/dart_test/empty_namespace.idl
new file mode 100644
index 00000000000..824de2d80e7
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/empty_namespace.idl
@@ -0,0 +1,7 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// An empty comment is required for an empty namespace.
+namespace empty_namespace {
+};
diff --git a/chromium/tools/json_schema_compiler/dart_test/empty_type.dart b/chromium/tools/json_schema_compiler/dart_test/empty_type.dart
new file mode 100644
index 00000000000..ebe8e69659a
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/empty_type.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated from namespace: empty_type
+
+part of chrome;
+
+/**
+ * Types
+ */
+
+class Empty_typeEmptyType extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ Empty_typeEmptyType({}) {
+ }
+
+ /*
+ * Private constructor
+ */
+ Empty_typeEmptyType._proxy(_jsObject) : super._proxy(_jsObject);
+}
+
+/**
+ * Functions
+ */
+
+class API_empty_type {
+ /*
+ * API connection
+ */
+ Object _jsObject;
+ API_empty_type(this._jsObject) {
+ }
+}
diff --git a/chromium/tools/json_schema_compiler/dart_test/empty_type.idl b/chromium/tools/json_schema_compiler/dart_test/empty_type.idl
new file mode 100644
index 00000000000..9d7de6f7a70
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/empty_type.idl
@@ -0,0 +1,10 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Namespace-level comment for EmptyType.
+namespace empty_type {
+ // Documentation for EmptyType.
+ dictionary EmptyType {
+ };
+};
diff --git a/chromium/tools/json_schema_compiler/dart_test/enums.idl b/chromium/tools/json_schema_compiler/dart_test/enums.idl
new file mode 100644
index 00000000000..1c82d00824a
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/enums.idl
@@ -0,0 +1,12 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A comment for the enums namespace.
+namespace enums {
+ // A basic enumeration.
+ enum Enum1 { a, b };
+
+ // Another basic enumeration.
+ enum Enum2 { ab, bc, de, ef, fg, hi };
+};
diff --git a/chromium/tools/json_schema_compiler/dart_test/events.dart b/chromium/tools/json_schema_compiler/dart_test/events.dart
new file mode 100644
index 00000000000..d2e79ba1b31
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/events.dart
@@ -0,0 +1,282 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated from namespace: events
+
+part of chrome;
+
+/**
+ * Types
+ */
+
+class EventsEventArgumentElement extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ EventsEventArgumentElement({String elementStringArg}) {
+ if (elementStringArg != null)
+ this.elementStringArg = elementStringArg;
+ }
+
+ /*
+ * Private constructor
+ */
+ EventsEventArgumentElement._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ String get elementStringArg => JS('String', '#.elementStringArg', this._jsObject);
+
+ void set elementStringArg(String elementStringArg) {
+ JS('void', '#.elementStringArg = #', this._jsObject, elementStringArg);
+ }
+
+}
+
+class EventsEventArgument extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ EventsEventArgument({FileEntry entryArg, String stringArg, int intArg, List<EventsEventArgumentElement> elements, FileEntry optionalEntryArg, String optionalStringArg, int optionalIntArg, List<EventsEventArgumentElement> optionalElements}) {
+ if (entryArg != null)
+ this.entryArg = entryArg;
+ if (stringArg != null)
+ this.stringArg = stringArg;
+ if (intArg != null)
+ this.intArg = intArg;
+ if (elements != null)
+ this.elements = elements;
+ if (optionalEntryArg != null)
+ this.optionalEntryArg = optionalEntryArg;
+ if (optionalStringArg != null)
+ this.optionalStringArg = optionalStringArg;
+ if (optionalIntArg != null)
+ this.optionalIntArg = optionalIntArg;
+ if (optionalElements != null)
+ this.optionalElements = optionalElements;
+ }
+
+ /*
+ * Private constructor
+ */
+ EventsEventArgument._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ /// A file entry
+ FileEntry get entryArg => JS('FileEntry', '#.entryArg', this._jsObject);
+
+ void set entryArg(FileEntry entryArg) {
+ JS('void', '#.entryArg = #', this._jsObject, convertArgument(entryArg));
+ }
+
+ /// A string
+ String get stringArg => JS('String', '#.stringArg', this._jsObject);
+
+ void set stringArg(String stringArg) {
+ JS('void', '#.stringArg = #', this._jsObject, stringArg);
+ }
+
+ /// A primitive
+ int get intArg => JS('int', '#.intArg', this._jsObject);
+
+ void set intArg(int intArg) {
+ JS('void', '#.intArg = #', this._jsObject, intArg);
+ }
+
+ /// An array
+ List<EventsEventArgumentElement> get elements {
+ List<EventsEventArgumentElement> __proxy_elements = new List<EventsEventArgumentElement>();
+ int count = JS('int', '#.elements.length', this._jsObject);
+ for (int i = 0; i < count; i++) {
+ var item = JS('', '#.elements[#]', this._jsObject, i);
+ __proxy_elements.add(new EventsEventArgumentElement._proxy(item));
+ }
+ return __proxy_elements;
+ }
+
+ void set elements(List<EventsEventArgumentElement> elements) {
+ JS('void', '#.elements = #', this._jsObject, convertArgument(elements));
+ }
+
+ /// Optional file entry
+ FileEntry get optionalEntryArg => JS('FileEntry', '#.optionalEntryArg', this._jsObject);
+
+ void set optionalEntryArg(FileEntry optionalEntryArg) {
+ JS('void', '#.optionalEntryArg = #', this._jsObject, convertArgument(optionalEntryArg));
+ }
+
+ /// A string
+ String get optionalStringArg => JS('String', '#.optionalStringArg', this._jsObject);
+
+ void set optionalStringArg(String optionalStringArg) {
+ JS('void', '#.optionalStringArg = #', this._jsObject, optionalStringArg);
+ }
+
+ /// A primitive
+ int get optionalIntArg => JS('int', '#.optionalIntArg', this._jsObject);
+
+ void set optionalIntArg(int optionalIntArg) {
+ JS('void', '#.optionalIntArg = #', this._jsObject, optionalIntArg);
+ }
+
+ /// An array
+ List<EventsEventArgumentElement> get optionalElements {
+ List<EventsEventArgumentElement> __proxy_optionalElements = new List<EventsEventArgumentElement>();
+ int count = JS('int', '#.optionalElements.length', this._jsObject);
+ for (int i = 0; i < count; i++) {
+ var item = JS('', '#.optionalElements[#]', this._jsObject, i);
+ __proxy_optionalElements.add(new EventsEventArgumentElement._proxy(item));
+ }
+ return __proxy_optionalElements;
+ }
+
+ void set optionalElements(List<EventsEventArgumentElement> optionalElements) {
+ JS('void', '#.optionalElements = #', this._jsObject, convertArgument(optionalElements));
+ }
+
+}
+
+/**
+ * Events
+ */
+
+/// Documentation for the first basic event.
+class Event_events_firstBasicEvent extends Event {
+ void addListener(void callback()) => super.addListener(callback);
+
+ void removeListener(void callback()) => super.removeListener(callback);
+
+ bool hasListener(void callback()) => super.hasListener(callback);
+
+ Event_events_firstBasicEvent(jsObject) : super._(jsObject, 0);
+}
+
+/// Documentation for the second basic event.
+class Event_events_secondBasicEvent extends Event {
+ void addListener(void callback()) => super.addListener(callback);
+
+ void removeListener(void callback()) => super.removeListener(callback);
+
+ bool hasListener(void callback()) => super.hasListener(callback);
+
+ Event_events_secondBasicEvent(jsObject) : super._(jsObject, 0);
+}
+
+/// Documentation for an event with a non-optional primitive argument.
+class Event_events_nonOptionalPrimitiveArgEvent extends Event {
+ void addListener(void callback(int argument)) => super.addListener(callback);
+
+ void removeListener(void callback(int argument)) => super.removeListener(callback);
+
+ bool hasListener(void callback(int argument)) => super.hasListener(callback);
+
+ Event_events_nonOptionalPrimitiveArgEvent(jsObject) : super._(jsObject, 1);
+}
+
+/// Documentation for an event with an optional primitive argument.
+class Event_events_optionalPrimitiveArgEvent extends Event {
+ void addListener(void callback(int argument)) => super.addListener(callback);
+
+ void removeListener(void callback(int argument)) => super.removeListener(callback);
+
+ bool hasListener(void callback(int argument)) => super.hasListener(callback);
+
+ Event_events_optionalPrimitiveArgEvent(jsObject) : super._(jsObject, 1);
+}
+
+/// Documentation for an event with a non-optional dictionary argument.
+class Event_events_nonOptionalDictArgEvent extends Event {
+ void addListener(void callback(EventsEventArgument argument)) {
+ void __proxy_callback(argument) {
+ if (callback != null) {
+ callback(new EventsEventArgument._proxy(argument));
+ }
+ }
+ super.addListener(__proxy_callback);
+ }
+
+ void removeListener(void callback(EventsEventArgument argument)) {
+ void __proxy_callback(argument) {
+ if (callback != null) {
+ callback(new EventsEventArgument._proxy(argument));
+ }
+ }
+ super.removeListener(__proxy_callback);
+ }
+
+ bool hasListener(void callback(EventsEventArgument argument)) {
+ void __proxy_callback(argument) {
+ if (callback != null) {
+ callback(new EventsEventArgument._proxy(argument));
+ }
+ }
+ super.hasListener(__proxy_callback);
+ }
+
+ Event_events_nonOptionalDictArgEvent(jsObject) : super._(jsObject, 1);
+}
+
+/// Documentation for an event with a optional dictionary argument.
+class Event_events_optionalDictArgEvent extends Event {
+ void addListener(void callback(EventsEventArgument argument)) {
+ void __proxy_callback(argument) {
+ if (callback != null) {
+ callback(new EventsEventArgument._proxy(argument));
+ }
+ }
+ super.addListener(__proxy_callback);
+ }
+
+ void removeListener(void callback(EventsEventArgument argument)) {
+ void __proxy_callback(argument) {
+ if (callback != null) {
+ callback(new EventsEventArgument._proxy(argument));
+ }
+ }
+ super.removeListener(__proxy_callback);
+ }
+
+ bool hasListener(void callback(EventsEventArgument argument)) {
+ void __proxy_callback(argument) {
+ if (callback != null) {
+ callback(new EventsEventArgument._proxy(argument));
+ }
+ }
+ super.hasListener(__proxy_callback);
+ }
+
+ Event_events_optionalDictArgEvent(jsObject) : super._(jsObject, 1);
+}
+
+/**
+ * Functions
+ */
+
+class API_events {
+ /*
+ * API connection
+ */
+ Object _jsObject;
+
+ /*
+ * Events
+ */
+ Event_events_firstBasicEvent firstBasicEvent;
+ Event_events_secondBasicEvent secondBasicEvent;
+ Event_events_nonOptionalPrimitiveArgEvent nonOptionalPrimitiveArgEvent;
+ Event_events_optionalPrimitiveArgEvent optionalPrimitiveArgEvent;
+ Event_events_nonOptionalDictArgEvent nonOptionalDictArgEvent;
+ Event_events_optionalDictArgEvent optionalDictArgEvent;
+ API_events(this._jsObject) {
+ firstBasicEvent = new Event_events_firstBasicEvent(JS('', '#.firstBasicEvent', this._jsObject));
+ secondBasicEvent = new Event_events_secondBasicEvent(JS('', '#.secondBasicEvent', this._jsObject));
+ nonOptionalPrimitiveArgEvent = new Event_events_nonOptionalPrimitiveArgEvent(JS('', '#.nonOptionalPrimitiveArgEvent', this._jsObject));
+ optionalPrimitiveArgEvent = new Event_events_optionalPrimitiveArgEvent(JS('', '#.optionalPrimitiveArgEvent', this._jsObject));
+ nonOptionalDictArgEvent = new Event_events_nonOptionalDictArgEvent(JS('', '#.nonOptionalDictArgEvent', this._jsObject));
+ optionalDictArgEvent = new Event_events_optionalDictArgEvent(JS('', '#.optionalDictArgEvent', this._jsObject));
+ }
+}
diff --git a/chromium/tools/json_schema_compiler/dart_test/events.idl b/chromium/tools/json_schema_compiler/dart_test/events.idl
new file mode 100644
index 00000000000..f1fb4b67dcc
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/events.idl
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This comment is for the events namespace.
+namespace events {
+ dictionary EventArgumentElement {
+ DOMString elementStringArg;
+ };
+
+ dictionary EventArgument {
+ // A file entry
+ [instanceOf=FileEntry] object entryArg;
+
+ // A string
+ DOMString stringArg;
+
+ // A primitive
+ int intArg;
+
+ // An array
+ EventArgumentElement[] elements;
+
+ // Optional file entry
+ [instanceOf=FileEntry] object? optionalEntryArg;
+
+ // A string
+ DOMString? optionalStringArg;
+
+ // A primitive
+ int? optionalIntArg;
+
+ // An array
+ EventArgumentElement[]? optionalElements;
+ };
+
+ interface Events {
+ // Documentation for the first basic event.
+ static void firstBasicEvent();
+
+ // Documentation for the second basic event.
+ static void secondBasicEvent();
+
+ // Documentation for an event with a non-optional primitive argument.
+ static void nonOptionalPrimitiveArgEvent(int argument);
+
+ // Documentation for an event with an optional primitive argument.
+ static void optionalPrimitiveArgEvent(optional int argument);
+
+ // Documentation for an event with a non-optional dictionary argument.
+ static void nonOptionalDictArgEvent(EventArgument argument);
+
+ // Documentation for an event with a optional dictionary argument.
+ static void optionalDictArgEvent(EventArgument argument);
+ };
+};
diff --git a/chromium/tools/json_schema_compiler/dart_test/functions.dart b/chromium/tools/json_schema_compiler/dart_test/functions.dart
new file mode 100644
index 00000000000..2b4f02bc1c6
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/functions.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated from namespace: functions
+
+part of chrome;
+
+/**
+ * Types
+ */
+
+class FunctionsDictType extends ChromeObject {
+ /*
+ * Private constructor
+ */
+ FunctionsDictType._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ /// A field.
+ int get a => JS('int', '#.a', this._jsObject);
+
+ void set a(int a) {
+ JS('void', '#.a = #', this._jsObject, a);
+ }
+
+
+ /*
+ * Methods
+ */
+ /// A parameter.
+ void voidFunc() => JS('void', '#.voidFunc()', this._jsObject);
+
+}
+
+/**
+ * Functions
+ */
+
+class API_functions {
+ /*
+ * API connection
+ */
+ Object _jsObject;
+
+ /*
+ * Functions
+ */
+ /// Simple function.
+ void voidFunc() => JS('void', '#.voidFunc()', this._jsObject);
+
+ /// Function taking a non-optional argument.
+ void argFunc(String s) => JS('void', '#.argFunc(#)', this._jsObject, s);
+
+ /// Function taking an optional argument.
+ void optionalArgFunc([String s]) => JS('void', '#.optionalArgFunc(#)', this._jsObject, s);
+
+ /// Function taking a non-optional dictionary argument.
+ void dictArgFunc(FunctionsDictType d) => JS('void', '#.dictArgFunc(#)', this._jsObject, convertArgument(d));
+
+ /// Function taking an optional dictionary argument.
+ void optionalDictArgFunc([FunctionsDictType d]) => JS('void', '#.optionalDictArgFunc(#)', this._jsObject, convertArgument(d));
+
+ /// Function taking an entry argument.
+ void entryArgFunc(Object entry) => JS('void', '#.entryArgFunc(#)', this._jsObject, convertArgument(entry));
+
+ /// Function taking a simple callback.
+ void callbackFunc(void c()) => JS('void', '#.callbackFunc(#)', this._jsObject, convertDartClosureToJS(c, 0));
+
+ /// Function taking an optional simple callback.
+ void optionalCallbackFunc([void c()]) => JS('void', '#.optionalCallbackFunc(#)', this._jsObject, convertDartClosureToJS(c, 0));
+
+ /// Function taking a primitive callback.
+ void primitiveCallbackFunc(void c(int i)) => JS('void', '#.primitiveCallbackFunc(#)', this._jsObject, convertDartClosureToJS(c, 1));
+
+ /// Function taking a dictionary callback.
+ void dictCallbackFunc(void c(DictType dict)) {
+ void __proxy_callback(dict) {
+ if (c != null) {
+ c(new DictType._proxy(dict));
+ }
+ }
+ JS('void', '#.dictCallbackFunc(#)', this._jsObject, convertDartClosureToJS(__proxy_callback, 1));
+ }
+
+ /// Function returning a dictionary.
+ FunctionsDictType dictRetFunc() => new FunctionsDictType._proxy(JS('', '#.dictRetFunc()', this._jsObject));
+
+ API_functions(this._jsObject) {
+ }
+}
diff --git a/chromium/tools/json_schema_compiler/dart_test/functions.idl b/chromium/tools/json_schema_compiler/dart_test/functions.idl
new file mode 100644
index 00000000000..e303d0de022
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/functions.idl
@@ -0,0 +1,55 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A comment for the functions namespace.
+namespace functions {
+ callback SimpleCallback = void ();
+
+ callback PrimitiveCallback = void (int i);
+
+ callback DictCallback = void ([instanceOf=DictType] object dict);
+
+ dictionary DictType {
+ // A field.
+ int a;
+
+ // A parameter.
+ static void voidFunc();
+ };
+
+ interface Functions {
+ // Simple function.
+ static void voidFunc();
+
+ // Function taking a non-optional argument.
+ static void argFunc(DOMString s);
+
+ // Function taking an optional argument.
+ static void optionalArgFunc(optional DOMString s);
+
+ // Function taking a non-optional dictionary argument.
+ static void dictArgFunc(DictType d);
+
+ // Function taking an optional dictionary argument.
+ static void optionalDictArgFunc(optional DictType d);
+
+ // Function taking an entry argument.
+ static void entryArgFunc([intanceOf=FileEntry] object entry);
+
+ // Function taking a simple callback.
+ static void callbackFunc(SimpleCallback c);
+
+ // Function taking an optional simple callback.
+ static void optionalCallbackFunc(optional SimpleCallback c);
+
+ // Function taking a primitive callback.
+ static void primitiveCallbackFunc(PrimitiveCallback c);
+
+ // Function taking a dictionary callback.
+ static void dictCallbackFunc(DictCallback c);
+
+ // Function returning a dictionary.
+ static DictType dictRetFunc();
+ };
+};
diff --git a/chromium/tools/json_schema_compiler/dart_test/operatable_type.dart b/chromium/tools/json_schema_compiler/dart_test/operatable_type.dart
new file mode 100644
index 00000000000..725d6a68882
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/operatable_type.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated from namespace: operatable_type
+
+part of chrome;
+
+/**
+ * Types
+ */
+
+class Operatable_typeDictType extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ Operatable_typeDictType({int x, int y}) {
+ if (x != null)
+ this.x = x;
+ if (y != null)
+ this.y = y;
+ }
+
+ /*
+ * Private constructor
+ */
+ Operatable_typeDictType._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ int get x => JS('int', '#.x', this._jsObject);
+
+ void set x(int x) {
+ JS('void', '#.x = #', this._jsObject, x);
+ }
+
+ int get y => JS('int', '#.y', this._jsObject);
+
+ void set y(int y) {
+ JS('void', '#.y = #', this._jsObject, y);
+ }
+
+}
+
+class Operatable_typeOperatableType extends ChromeObject {
+ /*
+ * Private constructor
+ */
+ Operatable_typeOperatableType._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ /// Documentation for the String t.
+ String get t => JS('String', '#.t', this._jsObject);
+
+ void set t(String t) {
+ JS('void', '#.t = #', this._jsObject, t);
+ }
+
+
+ /*
+ * Methods
+ */
+ /// Function returning nothing, taking nothing.
+ void voidFunc() => JS('void', '#.voidFunc()', this._jsObject);
+
+ /// Function returning primitive type.
+ int intRetFunc() => new int._proxy(JS('', '#.intRetFunc()', this._jsObject));
+
+ /// Function returning dictionary.
+ Operatable_typeDictType dictRetFunc() => new Operatable_typeDictType._proxy(JS('', '#.dictRetFunc()', this._jsObject));
+
+ /// Function taking primitive type.
+ void intArgFunc(int i) => JS('void', '#.intArgFunc(#)', this._jsObject, i);
+
+ /// Function taking dict type.
+ void dictArgFunc(Operatable_typeDictType d) => JS('void', '#.dictArgFunc(#)', this._jsObject, convertArgument(d));
+
+}
+
+/**
+ * Functions
+ */
+
+class API_operatable_type {
+ /*
+ * API connection
+ */
+ Object _jsObject;
+ API_operatable_type(this._jsObject) {
+ }
+}
diff --git a/chromium/tools/json_schema_compiler/dart_test/operatable_type.idl b/chromium/tools/json_schema_compiler/dart_test/operatable_type.idl
new file mode 100644
index 00000000000..9c5f53cc0ef
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/operatable_type.idl
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Top-level namespace-comment for operatableType
+namespace operatable_type {
+ dictionary DictType {
+ int x;
+ int y;
+ };
+
+ // Documentation for OperatableType.
+ dictionary OperatableType {
+ // Documentation for the String t.
+ DOMString t;
+
+ // Function returning nothing, taking nothing.
+ static void voidFunc();
+
+ // Function returning primitive type.
+ static int intRetFunc();
+
+ // Function returning dictionary.
+ static DictType dictRetFunc();
+
+ // Function taking primitive type.
+ static void intArgFunc(int i);
+
+ // Function taking dict type.
+ static void dictArgFunc(DictType d);
+ };
+};
diff --git a/chromium/tools/json_schema_compiler/dart_test/tags.dart b/chromium/tools/json_schema_compiler/dart_test/tags.dart
new file mode 100644
index 00000000000..4c3514aeebf
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/tags.dart
@@ -0,0 +1,116 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Generated from namespace: tags
+
+part of chrome;
+
+/**
+ * Types
+ */
+
+class TagsInlineDoc extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ TagsInlineDoc({}) {
+ }
+
+ /*
+ * Private constructor
+ */
+ TagsInlineDoc._proxy(_jsObject) : super._proxy(_jsObject);
+}
+
+class TagsNodoc extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ TagsNodoc({}) {
+ }
+
+ /*
+ * Private constructor
+ */
+ TagsNodoc._proxy(_jsObject) : super._proxy(_jsObject);
+}
+
+class TagsNocompile extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ TagsNocompile({}) {
+ }
+
+ /*
+ * Private constructor
+ */
+ TagsNocompile._proxy(_jsObject) : super._proxy(_jsObject);
+}
+
+class TagsPlainDict extends ChromeObject {
+ /*
+ * Public constructor
+ */
+ TagsPlainDict({int inline_doc, String nodoc, double nocompile, fileEntry instance_of_tag}) {
+ if (inline_doc != null)
+ this.inline_doc = inline_doc;
+ if (nodoc != null)
+ this.nodoc = nodoc;
+ if (nocompile != null)
+ this.nocompile = nocompile;
+ if (instance_of_tag != null)
+ this.instance_of_tag = instance_of_tag;
+ }
+
+ /*
+ * Private constructor
+ */
+ TagsPlainDict._proxy(_jsObject) : super._proxy(_jsObject);
+
+ /*
+ * Public accessors
+ */
+ /// This int has the property [inline_doc].
+ int get inline_doc => JS('int', '#.inline_doc', this._jsObject);
+
+ void set inline_doc(int inline_doc) {
+ JS('void', '#.inline_doc = #', this._jsObject, inline_doc);
+ }
+
+ /// This String has the property [nodoc].
+ String get nodoc => JS('String', '#.nodoc', this._jsObject);
+
+ void set nodoc(String nodoc) {
+ JS('void', '#.nodoc = #', this._jsObject, nodoc);
+ }
+
+ /// This double has the property [nocompile].
+ double get nocompile => JS('double', '#.nocompile', this._jsObject);
+
+ void set nocompile(double nocompile) {
+ JS('void', '#.nocompile = #', this._jsObject, nocompile);
+ }
+
+ /// This object has the property [instanceOf=fileEntry].
+ fileEntry get instance_of_tag => JS('fileEntry', '#.instance_of_tag', this._jsObject);
+
+ void set instance_of_tag(fileEntry instance_of_tag) {
+ JS('void', '#.instance_of_tag = #', this._jsObject, convertArgument(instance_of_tag));
+ }
+
+}
+
+/**
+ * Functions
+ */
+
+class API_tags {
+ /*
+ * API connection
+ */
+ Object _jsObject;
+ API_tags(this._jsObject) {
+ }
+}
diff --git a/chromium/tools/json_schema_compiler/dart_test/tags.idl b/chromium/tools/json_schema_compiler/dart_test/tags.idl
new file mode 100644
index 00000000000..7a029cd70e3
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/dart_test/tags.idl
@@ -0,0 +1,33 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A comment describing tags.
+namespace tags {
+ // This dictionary has the property [inline_doc].
+ [inline_doc] dictionary InlineDoc {
+ };
+
+ // This dictionary has the property [nodoc].
+ [nodoc] dictionary Nodoc {
+ };
+
+ // This dictionary has the property [nocompile].
+ [nocompile] dictionary Nocompile {
+ };
+
+ // This dictionary has no tags on the dictionary itself.
+ dictionary PlainDict {
+ // This int has the property [inline_doc].
+ [inline_doc] int inline_doc;
+
+ // This String has the property [nodoc].
+ [nodoc] String nodoc;
+
+ // This double has the property [nocompile].
+ [nocompile] double nocompile;
+
+ // This object has the property [instanceOf=fileEntry].
+ [instanceOf=fileEntry] object instance_of_tag;
+ };
+};
diff --git a/chromium/tools/json_schema_compiler/h_generator.py b/chromium/tools/json_schema_compiler/h_generator.py
new file mode 100644
index 00000000000..9a348fe51dc
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/h_generator.py
@@ -0,0 +1,397 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from code import Code
+from model import PropertyType, Type
+import cpp_util
+import schema_util
+
+class HGenerator(object):
+ def __init__(self, type_generator, cpp_namespace):
+ self._type_generator = type_generator
+ self._cpp_namespace = cpp_namespace
+
+ def Generate(self, namespace):
+ return _Generator(namespace,
+ self._type_generator,
+ self._cpp_namespace).Generate()
+
+class _Generator(object):
+ """A .h generator for a namespace.
+ """
+ def __init__(self, namespace, cpp_type_generator, cpp_namespace):
+ self._namespace = namespace
+ self._type_helper = cpp_type_generator
+ self._cpp_namespace = cpp_namespace
+ self._target_namespace = (
+ self._type_helper.GetCppNamespaceName(self._namespace))
+ self._generate_error_messages = namespace.compiler_options.get(
+ 'generate_error_messages', False)
+
+ def Generate(self):
+ """Generates a Code object with the .h for a single namespace.
+ """
+ c = Code()
+ (c.Append(cpp_util.CHROMIUM_LICENSE)
+ .Append()
+ .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file)
+ .Append()
+ )
+
+ ifndef_name = cpp_util.GenerateIfndefName(self._namespace.source_file_dir,
+ self._target_namespace)
+ (c.Append('#ifndef %s' % ifndef_name)
+ .Append('#define %s' % ifndef_name)
+ .Append()
+ .Append('#include <map>')
+ .Append('#include <string>')
+ .Append('#include <vector>')
+ .Append()
+ .Append('#include "base/basictypes.h"')
+ .Append('#include "base/logging.h"')
+ .Append('#include "base/memory/linked_ptr.h"')
+ .Append('#include "base/memory/scoped_ptr.h"')
+ .Append('#include "base/values.h"')
+ .Cblock(self._type_helper.GenerateIncludes())
+ .Append()
+ )
+
+ c.Concat(cpp_util.OpenNamespace(self._cpp_namespace))
+ # TODO(calamity): These forward declarations should be #includes to allow
+ # $ref types from other files to be used as required params. This requires
+ # some detangling of windows and tabs which will currently lead to circular
+ # #includes.
+ forward_declarations = (
+ self._type_helper.GenerateForwardDeclarations())
+ if not forward_declarations.IsEmpty():
+ (c.Append()
+ .Cblock(forward_declarations)
+ )
+
+ c.Concat(self._type_helper.GetNamespaceStart())
+ c.Append()
+ if self._namespace.properties:
+ (c.Append('//')
+ .Append('// Properties')
+ .Append('//')
+ .Append()
+ )
+ for property in self._namespace.properties.values():
+ property_code = self._type_helper.GeneratePropertyValues(
+ property,
+ 'extern const %(type)s %(name)s;')
+ if property_code:
+ c.Cblock(property_code)
+ if self._namespace.types:
+ (c.Append('//')
+ .Append('// Types')
+ .Append('//')
+ .Append()
+ .Cblock(self._GenerateTypes(self._FieldDependencyOrder(),
+ is_toplevel=True,
+ generate_typedefs=True))
+ )
+ if self._namespace.functions:
+ (c.Append('//')
+ .Append('// Functions')
+ .Append('//')
+ .Append()
+ )
+ for function in self._namespace.functions.values():
+ c.Cblock(self._GenerateFunction(function))
+ if self._namespace.events:
+ (c.Append('//')
+ .Append('// Events')
+ .Append('//')
+ .Append()
+ )
+ for event in self._namespace.events.values():
+ c.Cblock(self._GenerateEvent(event))
+ (c.Concat(self._type_helper.GetNamespaceEnd())
+ .Concat(cpp_util.CloseNamespace(self._cpp_namespace))
+ .Append('#endif // %s' % ifndef_name)
+ .Append()
+ )
+ return c
+
+ def _FieldDependencyOrder(self):
+ """Generates the list of types in the current namespace in an order in which
+ depended-upon types appear before types which depend on them.
+ """
+ dependency_order = []
+
+ def ExpandType(path, type_):
+ if type_ in path:
+ raise ValueError("Illegal circular dependency via cycle " +
+ ", ".join(map(lambda x: x.name, path + [type_])))
+ for prop in type_.properties.values():
+ if (prop.type_ == PropertyType.REF and
+ schema_util.GetNamespace(prop.ref_type) == self._namespace.name):
+ ExpandType(path + [type_], self._namespace.types[prop.ref_type])
+ if not type_ in dependency_order:
+ dependency_order.append(type_)
+
+ for type_ in self._namespace.types.values():
+ ExpandType([], type_)
+ return dependency_order
+
+ def _GenerateEnumDeclaration(self, enum_name, type_):
+ """Generate the declaration of a C++ enum.
+ """
+ c = Code()
+ c.Sblock('enum %s {' % enum_name)
+ c.Append(self._type_helper.GetEnumNoneValue(type_) + ',')
+ for value in type_.enum_values:
+ c.Append(self._type_helper.GetEnumValue(type_, value) + ',')
+ return c.Eblock('};')
+
+ def _GenerateFields(self, props):
+ """Generates the field declarations when declaring a type.
+ """
+ c = Code()
+ needs_blank_line = False
+ for prop in props:
+ if needs_blank_line:
+ c.Append()
+ needs_blank_line = True
+ if prop.description:
+ c.Comment(prop.description)
+ # ANY is a base::Value which is abstract and cannot be a direct member, so
+ # we always need to wrap it in a scoped_ptr.
+ is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY
+ (c.Append('%s %s;' % (
+ self._type_helper.GetCppType(prop.type_, is_ptr=is_ptr),
+ prop.unix_name))
+ )
+ return c
+
+ def _GenerateType(self, type_, is_toplevel=False, generate_typedefs=False):
+ """Generates a struct for |type_|.
+
+ |is_toplevel| implies that the type was declared in the "types" field
+ of an API schema. This determines the correct function
+ modifier(s).
+ |generate_typedefs| controls whether primitive types should be generated as
+ a typedef. This may not always be desired. If false,
+ primitive types are ignored.
+ """
+ classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
+ c = Code()
+
+ if type_.functions:
+ # Wrap functions within types in the type's namespace.
+ (c.Append('namespace %s {' % classname)
+ .Append()
+ )
+ for function in type_.functions.values():
+ c.Cblock(self._GenerateFunction(function))
+ c.Append('} // namespace %s' % classname)
+ elif type_.property_type == PropertyType.ARRAY:
+ if generate_typedefs and type_.description:
+ c.Comment(type_.description)
+ c.Cblock(self._GenerateType(type_.item_type))
+ if generate_typedefs:
+ (c.Append('typedef std::vector<%s > %s;' % (
+ self._type_helper.GetCppType(type_.item_type),
+ classname))
+ )
+ elif type_.property_type == PropertyType.STRING:
+ if generate_typedefs:
+ if type_.description:
+ c.Comment(type_.description)
+ c.Append('typedef std::string %(classname)s;')
+ elif type_.property_type == PropertyType.ENUM:
+ if type_.description:
+ c.Comment(type_.description)
+ c.Sblock('enum %(classname)s {')
+ c.Append('%s,' % self._type_helper.GetEnumNoneValue(type_))
+ for value in type_.enum_values:
+ c.Append('%s,' % self._type_helper.GetEnumValue(type_, value))
+ # Top level enums are in a namespace scope so the methods shouldn't be
+ # static. On the other hand, those declared inline (e.g. in an object) do.
+ maybe_static = '' if is_toplevel else 'static '
+ (c.Eblock('};')
+ .Append()
+ .Append('%sstd::string ToString(%s as_enum);' %
+ (maybe_static, classname))
+ .Append('%s%s Parse%s(const std::string& as_string);' %
+ (maybe_static, classname, classname))
+ )
+ elif type_.property_type in (PropertyType.CHOICES,
+ PropertyType.OBJECT):
+ if type_.description:
+ c.Comment(type_.description)
+ (c.Sblock('struct %(classname)s {')
+ .Append('%(classname)s();')
+ .Append('~%(classname)s();')
+ )
+ if type_.origin.from_json:
+ (c.Append()
+ .Comment('Populates a %s object from a base::Value. Returns'
+ ' whether |out| was successfully populated.' % classname)
+ .Append('static bool Populate(%s);' % self._GenerateParams(
+ ('const base::Value& value', '%s* out' % classname)))
+ )
+ if is_toplevel:
+ (c.Append()
+ .Comment('Creates a %s object from a base::Value, or NULL on '
+ 'failure.' % classname)
+ .Append('static scoped_ptr<%s> FromValue(%s);' % (
+ classname, self._GenerateParams(('const base::Value& value',))))
+ )
+ if type_.origin.from_client:
+ value_type = ('base::Value'
+ if type_.property_type is PropertyType.CHOICES else
+ 'base::DictionaryValue')
+ (c.Append()
+ .Comment('Returns a new %s representing the serialized form of this '
+ '%s object.' % (value_type, classname))
+ .Append('scoped_ptr<%s> ToValue() const;' % value_type)
+ )
+ if type_.property_type == PropertyType.CHOICES:
+ # Choices are modelled with optional fields for each choice. Exactly one
+ # field of the choice is guaranteed to be set by the compiler.
+ c.Cblock(self._GenerateTypes(type_.choices))
+ c.Append('// Choices:')
+ for choice_type in type_.choices:
+ c.Append('%s as_%s;' % (
+ self._type_helper.GetCppType(choice_type, is_ptr=True),
+ choice_type.unix_name))
+ else:
+ properties = type_.properties.values()
+ (c.Append()
+ .Cblock(self._GenerateTypes(p.type_ for p in properties))
+ .Cblock(self._GenerateFields(properties)))
+ if type_.additional_properties is not None:
+ # Most additionalProperties actually have type "any", which is better
+ # modelled as a DictionaryValue rather than a map of string -> Value.
+ if type_.additional_properties.property_type == PropertyType.ANY:
+ c.Append('base::DictionaryValue additional_properties;')
+ else:
+ (c.Cblock(self._GenerateType(type_.additional_properties))
+ .Append('std::map<std::string, %s> additional_properties;' %
+ cpp_util.PadForGenerics(
+ self._type_helper.GetCppType(type_.additional_properties,
+ is_in_container=True)))
+ )
+ (c.Eblock()
+ .Append()
+ .Sblock(' private:')
+ .Append('DISALLOW_COPY_AND_ASSIGN(%(classname)s);')
+ .Eblock('};')
+ )
+ return c.Substitute({'classname': classname})
+
+ def _GenerateEvent(self, event):
+ """Generates the namespaces for an event.
+ """
+ c = Code()
+ # TODO(kalman): use event.unix_name not Classname.
+ event_namespace = cpp_util.Classname(event.name)
+ (c.Append('namespace %s {' % event_namespace)
+ .Append()
+ .Concat(self._GenerateEventNameConstant(event))
+ .Concat(self._GenerateCreateCallbackArguments(event))
+ .Eblock('} // namespace %s' % event_namespace)
+ )
+ return c
+
+ def _GenerateFunction(self, function):
+ """Generates the namespaces and structs for a function.
+ """
+ c = Code()
+ # TODO(kalman): Use function.unix_name not Classname here.
+ function_namespace = cpp_util.Classname(function.name)
+ """Windows has a #define for SendMessage, so to avoid any issues, we need
+ to not use the name.
+ """
+ if function_namespace == 'SendMessage':
+ function_namespace = 'PassMessage'
+ (c.Append('namespace %s {' % function_namespace)
+ .Append()
+ .Cblock(self._GenerateFunctionParams(function))
+ )
+ if function.callback:
+ c.Cblock(self._GenerateFunctionResults(function.callback))
+ c.Append('} // namespace %s' % function_namespace)
+ return c
+
+ def _GenerateFunctionParams(self, function):
+ """Generates the struct for passing parameters from JSON to a function.
+ """
+ if not function.params:
+ return Code()
+
+ c = Code()
+ (c.Sblock('struct Params {')
+ .Append('static scoped_ptr<Params> Create(%s);' % self._GenerateParams(
+ ('const base::ListValue& args',)))
+ .Append('~Params();')
+ .Append()
+ .Cblock(self._GenerateTypes(p.type_ for p in function.params))
+ .Cblock(self._GenerateFields(function.params))
+ .Eblock()
+ .Append()
+ .Sblock(' private:')
+ .Append('Params();')
+ .Append()
+ .Append('DISALLOW_COPY_AND_ASSIGN(Params);')
+ .Eblock('};')
+ )
+ return c
+
+ def _GenerateTypes(self, types, is_toplevel=False, generate_typedefs=False):
+ """Generate the structures required by a property such as OBJECT classes
+ and enums.
+ """
+ c = Code()
+ for type_ in types:
+ c.Cblock(self._GenerateType(type_,
+ is_toplevel=is_toplevel,
+ generate_typedefs=generate_typedefs))
+ return c
+
+ def _GenerateCreateCallbackArguments(self, function):
+ """Generates functions for passing parameters to a callback.
+ """
+ c = Code()
+ params = function.params
+ c.Cblock(self._GenerateTypes((p.type_ for p in params), is_toplevel=True))
+
+ declaration_list = []
+ for param in params:
+ if param.description:
+ c.Comment(param.description)
+ declaration_list.append(cpp_util.GetParameterDeclaration(
+ param, self._type_helper.GetCppType(param.type_)))
+ c.Append('scoped_ptr<base::ListValue> Create(%s);' %
+ ', '.join(declaration_list))
+ return c
+
+ def _GenerateEventNameConstant(self, event):
+ """Generates a constant string array for the event name.
+ """
+ c = Code()
+ c.Append('extern const char kEventName[]; // "%s.%s"' % (
+ self._namespace.name, event.name))
+ c.Append()
+ return c
+
+ def _GenerateFunctionResults(self, callback):
+ """Generates namespace for passing a function's result back.
+ """
+ c = Code()
+ (c.Append('namespace Results {')
+ .Append()
+ .Concat(self._GenerateCreateCallbackArguments(callback))
+ .Append('} // namespace Results')
+ )
+ return c
+
+ def _GenerateParams(self, params):
+ """Builds the parameter list for a function, given an array of parameters.
+ """
+ if self._generate_error_messages:
+ params += ('std::string* error = NULL',)
+ return ', '.join(str(p) for p in params)
diff --git a/chromium/tools/json_schema_compiler/highlighters/__init__.py b/chromium/tools/json_schema_compiler/highlighters/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/highlighters/__init__.py
diff --git a/chromium/tools/json_schema_compiler/highlighters/hilite_me_highlighter.py b/chromium/tools/json_schema_compiler/highlighters/hilite_me_highlighter.py
new file mode 100644
index 00000000000..af0484723cd
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/highlighters/hilite_me_highlighter.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import urllib
+import urllib2
+
+class HiliteMeHighlighter(object):
+ """Highlighter that calls the http://hilite.me API to highlight code.
+ """
+ def GetCSS(self, style):
+ return ''
+
+ def GetCodeElement(self, code, style):
+ # Call hilite.me API to do syntax highlighting
+ return urllib2.urlopen('http://hilite.me/api',
+ urllib.urlencode([
+ ('code', code),
+ ('lexer', 'cpp'),
+ ('style', style),
+ ('linenos', 1)])
+ ).read()
+
+ def DisplayName(self):
+ return 'hilite.me (slow, requires internet)'
+
+ def GetStyles(self):
+ return ['monokai', 'manni', 'perldoc', 'borland', 'colorful', 'default',
+ 'murphy', 'vs', 'trac', 'tango', 'fruity', 'autumn', 'bw', 'emacs',
+ 'vim', 'pastie', 'friendly', 'native']
diff --git a/chromium/tools/json_schema_compiler/highlighters/none_highlighter.py b/chromium/tools/json_schema_compiler/highlighters/none_highlighter.py
new file mode 100644
index 00000000000..ac1cc2b4b26
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/highlighters/none_highlighter.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import cgi
+
+class NoneHighlighter(object):
+ """Highlighter that just wraps code in a <pre>.
+ """
+ def GetCSS(self, style):
+ return ''
+
+ def GetCodeElement(self, code, style):
+ return '<pre>' + cgi.escape(code) + '</pre>'
+
+ def DisplayName(self):
+ return 'none'
+
+ def GetStyles(self):
+ return []
diff --git a/chromium/tools/json_schema_compiler/highlighters/pygments_highlighter.py b/chromium/tools/json_schema_compiler/highlighters/pygments_highlighter.py
new file mode 100644
index 00000000000..06abd33c790
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/highlighters/pygments_highlighter.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+try:
+ import pygments
+ from pygments.lexers import CppLexer
+ from pygments.formatters import HtmlFormatter
+ PYGMENTS_IMPORTED = True
+except ImportError:
+ print('It appears that Pygments is not installed. '
+ 'Can be installed using easy_install Pygments or from http://pygments.org.')
+ PYGMENTS_IMPORTED = False
+
+class PygmentsHighlighter(object):
+ def __init__(self):
+ if not PYGMENTS_IMPORTED:
+ raise ImportError('Pygments not installed')
+
+ """Highlighter that uses the python pygments library to highlight code.
+ """
+ def GetCSS(self, style):
+ formatter = HtmlFormatter(linenos=True,
+ style=pygments.styles.get_style_by_name(style))
+ return formatter.get_style_defs('.highlight')
+
+ def GetCodeElement(self, code, style):
+ formatter = HtmlFormatter(linenos=True,
+ style=pygments.styles.get_style_by_name(style))
+ return pygments.highlight(code, CppLexer(), formatter)
+
+ def DisplayName(self):
+ return 'pygments' + ('' if PYGMENTS_IMPORTED else ' (not installed)')
+
+ def GetStyles(self):
+ return list(pygments.styles.get_all_styles())
diff --git a/chromium/tools/json_schema_compiler/idl_schema.py b/chromium/tools/json_schema_compiler/idl_schema.py
new file mode 100644
index 00000000000..0556236be4f
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/idl_schema.py
@@ -0,0 +1,417 @@
+#! /usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import itertools
+import json
+import os.path
+import re
+import sys
+
+from json_parse import OrderedDict
+import schema_util
+
+# This file is a peer to json_schema.py. Each of these files understands a
+# certain format describing APIs (either JSON or IDL), reads files written
+# in that format into memory, and emits them as a Python array of objects
+# corresponding to those APIs, where the objects are formatted in a way that
+# the JSON schema compiler understands. compiler.py drives both idl_schema.py
+# and json_schema.py.
+
+# idl_parser expects to be able to import certain files in its directory,
+# so let's set things up the way it wants.
+_idl_generators_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ os.pardir, os.pardir, 'ppapi', 'generators')
+if _idl_generators_path in sys.path:
+ import idl_parser
+else:
+ sys.path.insert(0, _idl_generators_path)
+ try:
+ import idl_parser
+ finally:
+ sys.path.pop(0)
+
+def ProcessComment(comment):
+ '''
+ Convert a comment into a parent comment and a list of parameter comments.
+
+ Function comments are of the form:
+ Function documentation. May contain HTML and multiple lines.
+
+ |arg1_name|: Description of arg1. Use <var>argument</var> to refer
+ to other arguments.
+ |arg2_name|: Description of arg2...
+
+ Newlines are removed, and leading and trailing whitespace is stripped.
+
+ Args:
+ comment: The string from a Comment node.
+
+ Returns: A tuple that looks like:
+ (
+ "The processed comment, minus all |parameter| mentions.",
+ {
+ 'parameter_name_1': "The comment that followed |parameter_name_1|:",
+ ...
+ }
+ )
+ '''
+ # Find all the parameter comments of the form '|name|: comment'.
+ parameter_starts = list(re.finditer(r' *\|([^|]*)\| *: *', comment))
+
+ # Get the parent comment (everything before the first parameter comment.
+ first_parameter_location = (parameter_starts[0].start()
+ if parameter_starts else len(comment))
+ parent_comment = comment[:first_parameter_location]
+
+ # We replace \n\n with <br/><br/> here and below, because the documentation
+ # needs to know where the newlines should be, and this is easier than
+ # escaping \n.
+ parent_comment = (parent_comment.strip().replace('\n\n', '<br/><br/>')
+ .replace('\n', ''))
+
+ params = OrderedDict()
+ for (cur_param, next_param) in itertools.izip_longest(parameter_starts,
+ parameter_starts[1:]):
+ param_name = cur_param.group(1)
+
+ # A parameter's comment goes from the end of its introduction to the
+ # beginning of the next parameter's introduction.
+ param_comment_start = cur_param.end()
+ param_comment_end = next_param.start() if next_param else len(comment)
+ params[param_name] = (comment[param_comment_start:param_comment_end
+ ].strip().replace('\n\n', '<br/><br/>')
+ .replace('\n', ''))
+ return (parent_comment, params)
+
+class Callspec(object):
+ '''
+ Given a Callspec node representing an IDL function declaration, converts into
+ a tuple:
+ (name, list of function parameters, return type)
+ '''
+ def __init__(self, callspec_node, comment):
+ self.node = callspec_node
+ self.comment = comment
+
+ def process(self, callbacks):
+ parameters = []
+ return_type = None
+ if self.node.GetProperty('TYPEREF') not in ('void', None):
+ return_type = Typeref(self.node.GetProperty('TYPEREF'),
+ self.node,
+ {'name': self.node.GetName()}).process(callbacks)
+ # The IDL parser doesn't allow specifying return types as optional.
+ # Instead we infer any object return values to be optional.
+ # TODO(asargent): fix the IDL parser to support optional return types.
+ if return_type.get('type') == 'object' or '$ref' in return_type:
+ return_type['optional'] = True;
+ for node in self.node.children:
+ parameter = Param(node).process(callbacks)
+ if parameter['name'] in self.comment:
+ parameter['description'] = self.comment[parameter['name']]
+ parameters.append(parameter)
+ return (self.node.GetName(), parameters, return_type)
+
+class Param(object):
+ '''
+ Given a Param node representing a function parameter, converts into a Python
+ dictionary that the JSON schema compiler expects to see.
+ '''
+ def __init__(self, param_node):
+ self.node = param_node
+
+ def process(self, callbacks):
+ return Typeref(self.node.GetProperty('TYPEREF'),
+ self.node,
+ {'name': self.node.GetName()}).process(callbacks)
+
+class Dictionary(object):
+ '''
+ Given an IDL Dictionary node, converts into a Python dictionary that the JSON
+ schema compiler expects to see.
+ '''
+ def __init__(self, dictionary_node):
+ self.node = dictionary_node
+
+ def process(self, callbacks):
+ properties = OrderedDict()
+ for node in self.node.children:
+ if node.cls == 'Member':
+ k, v = Member(node).process(callbacks)
+ properties[k] = v
+ result = {'id': self.node.GetName(),
+ 'properties': properties,
+ 'type': 'object'}
+ if self.node.GetProperty('inline_doc'):
+ result['inline_doc'] = True
+ elif self.node.GetProperty('noinline_doc'):
+ result['noinline_doc'] = True
+ return result
+
+
+class Member(object):
+ '''
+ Given an IDL dictionary or interface member, converts into a name/value pair
+ where the value is a Python dictionary that the JSON schema compiler expects
+ to see.
+ '''
+ def __init__(self, member_node):
+ self.node = member_node
+
+ def process(self, callbacks):
+ properties = OrderedDict()
+ name = self.node.GetName()
+ for property_name in ('OPTIONAL', 'nodoc', 'nocompile', 'nodart'):
+ if self.node.GetProperty(property_name):
+ properties[property_name.lower()] = True
+ for option_name, sanitizer in [
+ ('maxListeners', int),
+ ('supportsFilters', lambda s: s == 'true'),
+ ('supportsListeners', lambda s: s == 'true'),
+ ('supportsRules', lambda s: s == 'true')]:
+ if self.node.GetProperty(option_name):
+ if 'options' not in properties:
+ properties['options'] = {}
+ properties['options'][option_name] = sanitizer(self.node.GetProperty(
+ option_name))
+ is_function = False
+ parameter_comments = OrderedDict()
+ for node in self.node.children:
+ if node.cls == 'Comment':
+ (parent_comment, parameter_comments) = ProcessComment(node.GetName())
+ properties['description'] = parent_comment
+ elif node.cls == 'Callspec':
+ is_function = True
+ name, parameters, return_type = (Callspec(node, parameter_comments)
+ .process(callbacks))
+ properties['parameters'] = parameters
+ if return_type is not None:
+ properties['returns'] = return_type
+ properties['name'] = name
+ if is_function:
+ properties['type'] = 'function'
+ else:
+ properties = Typeref(self.node.GetProperty('TYPEREF'),
+ self.node, properties).process(callbacks)
+ enum_values = self.node.GetProperty('legalValues')
+ if enum_values:
+ if properties['type'] == 'integer':
+ enum_values = map(int, enum_values)
+ elif properties['type'] == 'double':
+ enum_values = map(float, enum_values)
+ properties['enum'] = enum_values
+ return name, properties
+
+class Typeref(object):
+ '''
+ Given a TYPEREF property representing the type of dictionary member or
+ function parameter, converts into a Python dictionary that the JSON schema
+ compiler expects to see.
+ '''
+ def __init__(self, typeref, parent, additional_properties=OrderedDict()):
+ self.typeref = typeref
+ self.parent = parent
+ self.additional_properties = additional_properties
+
+ def process(self, callbacks):
+ properties = self.additional_properties
+ result = properties
+
+ if self.parent.GetProperty('OPTIONAL', False):
+ properties['optional'] = True
+
+ # The IDL parser denotes array types by adding a child 'Array' node onto
+ # the Param node in the Callspec.
+ for sibling in self.parent.GetChildren():
+ if sibling.cls == 'Array' and sibling.GetName() == self.parent.GetName():
+ properties['type'] = 'array'
+ properties['items'] = OrderedDict()
+ properties = properties['items']
+ break
+
+ if self.typeref == 'DOMString':
+ properties['type'] = 'string'
+ elif self.typeref == 'boolean':
+ properties['type'] = 'boolean'
+ elif self.typeref == 'double':
+ properties['type'] = 'number'
+ elif self.typeref == 'long':
+ properties['type'] = 'integer'
+ elif self.typeref == 'any':
+ properties['type'] = 'any'
+ elif self.typeref == 'object':
+ properties['type'] = 'object'
+ if 'additionalProperties' not in properties:
+ properties['additionalProperties'] = OrderedDict()
+ properties['additionalProperties']['type'] = 'any'
+ instance_of = self.parent.GetProperty('instanceOf')
+ if instance_of:
+ properties['isInstanceOf'] = instance_of
+ elif self.typeref == 'ArrayBuffer':
+ properties['type'] = 'binary'
+ properties['isInstanceOf'] = 'ArrayBuffer'
+ elif self.typeref == 'FileEntry':
+ properties['type'] = 'object'
+ properties['isInstanceOf'] = 'FileEntry'
+ if 'additionalProperties' not in properties:
+ properties['additionalProperties'] = OrderedDict()
+ properties['additionalProperties']['type'] = 'any'
+ elif self.typeref is None:
+ properties['type'] = 'function'
+ else:
+ if self.typeref in callbacks:
+ # Do not override name and description if they are already specified.
+ name = properties.get('name', None)
+ description = properties.get('description', None)
+ properties.update(callbacks[self.typeref])
+ if description is not None:
+ properties['description'] = description
+ if name is not None:
+ properties['name'] = name
+ else:
+ properties['$ref'] = self.typeref
+ return result
+
+
+class Enum(object):
+ '''
+ Given an IDL Enum node, converts into a Python dictionary that the JSON
+ schema compiler expects to see.
+ '''
+ def __init__(self, enum_node):
+ self.node = enum_node
+ self.description = ''
+
+ def process(self, callbacks):
+ enum = []
+ for node in self.node.children:
+ if node.cls == 'EnumItem':
+ enum.append(node.GetName())
+ elif node.cls == 'Comment':
+ self.description = ProcessComment(node.GetName())[0]
+ else:
+ sys.exit('Did not process %s %s' % (node.cls, node))
+ result = {'id' : self.node.GetName(),
+ 'description': self.description,
+ 'type': 'string',
+ 'enum': enum}
+ for property_name in ('inline_doc', 'noinline_doc', 'nodoc'):
+ if self.node.GetProperty(property_name):
+ result[property_name] = True
+ return result
+
+
+class Namespace(object):
+ '''
+ Given an IDLNode representing an IDL namespace, converts into a Python
+ dictionary that the JSON schema compiler expects to see.
+ '''
+
+ def __init__(self, namespace_node, description, nodoc=False, internal=False):
+ self.namespace = namespace_node
+ self.nodoc = nodoc
+ self.internal = internal
+ self.events = []
+ self.functions = []
+ self.types = []
+ self.callbacks = OrderedDict()
+ self.description = description
+
+ def process(self):
+ for node in self.namespace.children:
+ if node.cls == 'Dictionary':
+ self.types.append(Dictionary(node).process(self.callbacks))
+ elif node.cls == 'Callback':
+ k, v = Member(node).process(self.callbacks)
+ self.callbacks[k] = v
+ elif node.cls == 'Interface' and node.GetName() == 'Functions':
+ self.functions = self.process_interface(node)
+ elif node.cls == 'Interface' and node.GetName() == 'Events':
+ self.events = self.process_interface(node)
+ elif node.cls == 'Enum':
+ self.types.append(Enum(node).process(self.callbacks))
+ else:
+ sys.exit('Did not process %s %s' % (node.cls, node))
+ return {'namespace': self.namespace.GetName(),
+ 'description': self.description,
+ 'nodoc': self.nodoc,
+ 'types': self.types,
+ 'functions': self.functions,
+ 'internal': self.internal,
+ 'events': self.events}
+
+ def process_interface(self, node):
+ members = []
+ for member in node.children:
+ if member.cls == 'Member':
+ name, properties = Member(member).process(self.callbacks)
+ members.append(properties)
+ return members
+
+class IDLSchema(object):
+ '''
+ Given a list of IDLNodes and IDLAttributes, converts into a Python list
+ of api_defs that the JSON schema compiler expects to see.
+ '''
+
+ def __init__(self, idl):
+ self.idl = idl
+
+ def process(self):
+ namespaces = []
+ nodoc = False
+ internal = False
+ description = None
+ for node in self.idl:
+ if node.cls == 'Namespace':
+ if not description:
+ # TODO(kalman): Go back to throwing an error here.
+ print('%s must have a namespace-level comment. This will '
+ 'appear on the API summary page.' % node.GetName())
+ description = ''
+ namespace = Namespace(node, description, nodoc, internal)
+ namespaces.append(namespace.process())
+ nodoc = False
+ internal = False
+ elif node.cls == 'Copyright':
+ continue
+ elif node.cls == 'Comment':
+ description = node.GetName()
+ elif node.cls == 'ExtAttribute':
+ if node.name == 'nodoc':
+ nodoc = bool(node.value)
+ elif node.name == 'internal':
+ internal = bool(node.value)
+ else:
+ continue
+ else:
+ sys.exit('Did not process %s %s' % (node.cls, node))
+ return namespaces
+
+def Load(filename):
+ '''
+ Given the filename of an IDL file, parses it and returns an equivalent
+ Python dictionary in a format that the JSON schema compiler expects to see.
+ '''
+
+ f = open(filename, 'r')
+ contents = f.read()
+ f.close()
+
+ idl = idl_parser.IDLParser().ParseData(contents, filename)
+ idl_schema = IDLSchema(idl)
+ return idl_schema.process()
+
+def Main():
+ '''
+ Dump a json serialization of parse result for the IDL files whose names
+ were passed in on the command line.
+ '''
+ for filename in sys.argv[1:]:
+ schema = Load(filename)
+ print json.dumps(schema, indent=2)
+
+if __name__ == '__main__':
+ Main()
diff --git a/chromium/tools/json_schema_compiler/idl_schema_test.py b/chromium/tools/json_schema_compiler/idl_schema_test.py
new file mode 100755
index 00000000000..6adbbd7e288
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/idl_schema_test.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import idl_schema
+import unittest
+
+def getFunction(schema, name):
+ for item in schema['functions']:
+ if item['name'] == name:
+ return item
+ raise KeyError('Missing function %s' % name)
+
+def getParams(schema, name):
+ function = getFunction(schema, name)
+ return function['parameters']
+
+def getType(schema, id):
+ for item in schema['types']:
+ if item['id'] == id:
+ return item
+
+class IdlSchemaTest(unittest.TestCase):
+ def setUp(self):
+ loaded = idl_schema.Load('test/idl_basics.idl')
+ self.assertEquals(1, len(loaded))
+ self.assertEquals('idl_basics', loaded[0]['namespace'])
+ self.idl_basics = loaded[0]
+
+ def testSimpleCallbacks(self):
+ schema = self.idl_basics
+ expected = [{'type':'function', 'name':'cb', 'parameters':[]}]
+ self.assertEquals(expected, getParams(schema, 'function4'))
+
+ expected = [{'type':'function', 'name':'cb',
+ 'parameters':[{'name':'x', 'type':'integer'}]}]
+ self.assertEquals(expected, getParams(schema, 'function5'))
+
+ expected = [{'type':'function', 'name':'cb',
+ 'parameters':[{'name':'arg', '$ref':'MyType1'}]}]
+ self.assertEquals(expected, getParams(schema, 'function6'))
+
+ def testCallbackWithArrayArgument(self):
+ schema = self.idl_basics
+ expected = [{'type':'function', 'name':'cb',
+ 'parameters':[{'name':'arg', 'type':'array',
+ 'items':{'$ref':'MyType2'}}]}]
+ self.assertEquals(expected, getParams(schema, 'function12'))
+
+
+ def testArrayOfCallbacks(self):
+ schema = idl_schema.Load('test/idl_callback_arrays.idl')[0]
+ expected = [{'type':'array', 'name':'callbacks',
+ 'items':{'type':'function', 'name':'MyCallback',
+ 'parameters':[{'type':'integer', 'name':'x'}]}}]
+ self.assertEquals(expected, getParams(schema, 'whatever'))
+
+ def testLegalValues(self):
+ self.assertEquals({
+ 'x': {'name': 'x', 'type': 'integer', 'enum': [1,2],
+ 'description': 'This comment tests "double-quotes".'},
+ 'y': {'name': 'y', 'type': 'string'},
+ 'z': {'name': 'z', 'type': 'string'},
+ 'a': {'name': 'a', 'type': 'string'},
+ 'b': {'name': 'b', 'type': 'string'},
+ 'c': {'name': 'c', 'type': 'string'}},
+ getType(self.idl_basics, 'MyType1')['properties'])
+
+ def testMemberOrdering(self):
+ self.assertEquals(
+ ['x', 'y', 'z', 'a', 'b', 'c'],
+ getType(self.idl_basics, 'MyType1')['properties'].keys())
+
+ def testEnum(self):
+ schema = self.idl_basics
+ expected = {'enum': ['name1', 'name2'], 'description': 'Enum description',
+ 'type': 'string', 'id': 'EnumType'}
+ self.assertEquals(expected, getType(schema, expected['id']))
+
+ expected = [{'name':'type', '$ref':'EnumType'},
+ {'type':'function', 'name':'cb',
+ 'parameters':[{'name':'type', '$ref':'EnumType'}]}]
+ self.assertEquals(expected, getParams(schema, 'function13'))
+
+ expected = [{'items': {'$ref': 'EnumType'}, 'name': 'types',
+ 'type': 'array'}]
+ self.assertEquals(expected, getParams(schema, 'function14'))
+
+ def testNoCompile(self):
+ schema = self.idl_basics
+ func = getFunction(schema, 'function15')
+ self.assertTrue(func is not None)
+ self.assertTrue(func['nocompile'])
+
+ def testNoDocOnEnum(self):
+ schema = self.idl_basics
+ enum_with_nodoc = getType(schema, 'EnumTypeWithNoDoc')
+ self.assertTrue(enum_with_nodoc is not None)
+ self.assertTrue(enum_with_nodoc['nodoc'])
+
+ def testInternalNamespace(self):
+ idl_basics = self.idl_basics
+ self.assertEquals('idl_basics', idl_basics['namespace'])
+ self.assertTrue(idl_basics['internal'])
+ self.assertFalse(idl_basics['nodoc'])
+
+ def testCallbackComment(self):
+ schema = self.idl_basics
+ self.assertEquals('A comment on a callback.',
+ getParams(schema, 'function16')[0]['description'])
+ self.assertEquals(
+ 'A parameter.',
+ getParams(schema, 'function16')[0]['parameters'][0]['description'])
+ self.assertEquals(
+ 'Just a parameter comment, with no comment on the callback.',
+ getParams(schema, 'function17')[0]['parameters'][0]['description'])
+ self.assertEquals(
+ 'Override callback comment.',
+ getParams(schema, 'function18')[0]['description'])
+
+ def testFunctionComment(self):
+ schema = self.idl_basics
+ func = getFunction(schema, 'function3')
+ self.assertEquals(('This comment should appear in the documentation, '
+ 'despite occupying multiple lines.'),
+ func['description'])
+ self.assertEquals(
+ [{'description': ('So should this comment about the argument. '
+ '<em>HTML</em> is fine too.'),
+ 'name': 'arg',
+ '$ref': 'MyType1'}],
+ func['parameters'])
+ func = getFunction(schema, 'function4')
+ self.assertEquals(('This tests if "double-quotes" are escaped correctly.'
+ '<br/><br/> It also tests a comment with two newlines.'),
+ func['description'])
+
+ def testReservedWords(self):
+ schema = idl_schema.Load('test/idl_reserved_words.idl')[0]
+
+ foo_type = getType(schema, 'Foo')
+ self.assertEquals(['float', 'DOMString'], foo_type['enum'])
+
+ enum_type = getType(schema, 'enum')
+ self.assertEquals(['callback', 'namespace'], enum_type['enum'])
+
+ dictionary = getType(schema, 'dictionary');
+ self.assertEquals('integer', dictionary['properties']['long']['type'])
+
+ mytype = getType(schema, 'MyType')
+ self.assertEquals('string', mytype['properties']['interface']['type'])
+
+ params = getParams(schema, 'static')
+ self.assertEquals('Foo', params[0]['$ref'])
+ self.assertEquals('enum', params[1]['$ref'])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/json_parse.py b/chromium/tools/json_schema_compiler/json_parse.py
new file mode 100644
index 00000000000..9502e91d5c2
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/json_parse.py
@@ -0,0 +1,61 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import logging
+import os
+import sys
+
+_FILE_PATH = os.path.dirname(os.path.realpath(__file__))
+_SYS_PATH = sys.path[:]
+try:
+ _COMMENT_EATER_PATH = os.path.join(
+ _FILE_PATH, os.pardir, 'json_comment_eater')
+ sys.path.insert(0, _COMMENT_EATER_PATH)
+ import json_comment_eater
+finally:
+ sys.path = _SYS_PATH
+
+try:
+ from collections import OrderedDict
+
+ # Successfully imported, so we're running Python >= 2.7, and json.loads
+ # supports object_pairs_hook.
+ def Parse(json_str):
+ return json.loads(json_comment_eater.Nom(json_str),
+ object_pairs_hook=OrderedDict)
+
+except ImportError:
+ # Failed to import, so we're running Python < 2.7, and json.loads doesn't
+ # support object_pairs_hook. simplejson however does, but it's slow.
+ #
+ # TODO(cduvall/kalman): Refuse to start the docs server in this case, but
+ # let json-schema-compiler do its thing.
+ #logging.warning('Using simplejson to parse, this might be slow! Upgrade to '
+ # 'Python 2.7.')
+
+ _SYS_PATH = sys.path[:]
+ try:
+ _SIMPLE_JSON_PATH = os.path.join(_FILE_PATH,
+ os.pardir,
+ os.pardir,
+ 'third_party')
+ sys.path.insert(0, _SIMPLE_JSON_PATH)
+ # Add this path in case this is being used in the docs server.
+ sys.path.insert(0, os.path.join(_FILE_PATH,
+ os.pardir,
+ os.pardir,
+ 'third_party',
+ 'json_schema_compiler'))
+ import simplejson
+ from simplejson import OrderedDict
+ finally:
+ sys.path = _SYS_PATH
+
+ def Parse(json_str):
+ return simplejson.loads(json_comment_eater.Nom(json_str),
+ object_pairs_hook=OrderedDict)
+
+def IsDict(item):
+ return isinstance(item, (dict, OrderedDict))
diff --git a/chromium/tools/json_schema_compiler/json_schema.py b/chromium/tools/json_schema_compiler/json_schema.py
new file mode 100644
index 00000000000..0fa1ba57e96
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/json_schema.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import os
+import sys
+
+import json_parse
+import schema_util
+
+def DeleteNodes(item, delete_key):
+ """Deletes the given nodes in item, recursively, that have |delete_key| as
+ an attribute.
+ """
+ def HasKey(thing):
+ return json_parse.IsDict(thing) and thing.get(delete_key, False)
+
+ if json_parse.IsDict(item):
+ toDelete = []
+ for key, value in item.items():
+ if HasKey(value):
+ toDelete.append(key)
+ else:
+ DeleteNodes(value, delete_key)
+ for key in toDelete:
+ del item[key]
+ elif type(item) == list:
+ item[:] = [DeleteNodes(thing, delete_key)
+ for thing in item if not HasKey(thing)]
+
+ return item
+
+def Load(filename):
+ with open(filename, 'r') as handle:
+ schemas = json_parse.Parse(handle.read())
+ return schemas
+
+# A dictionary mapping |filename| to the object resulting from loading the JSON
+# at |filename|.
+_cache = {}
+
+def CachedLoad(filename):
+ """Equivalent to Load(filename), but caches results for subsequent calls"""
+ if filename not in _cache:
+ _cache[filename] = Load(filename)
+ # Return a copy of the object so that any changes a caller makes won't affect
+ # the next caller.
+ return copy.deepcopy(_cache[filename])
+
diff --git a/chromium/tools/json_schema_compiler/json_schema_test.py b/chromium/tools/json_schema_compiler/json_schema_test.py
new file mode 100755
index 00000000000..11ba61e443a
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/json_schema_test.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json_schema
+import json_schema_test
+import unittest
+
+class JsonSchemaUnittest(unittest.TestCase):
+ def testNocompile(self):
+ compiled = [
+ {
+ "namespace": "compile",
+ "description": "The compile API.",
+ "functions": [],
+ "types": {}
+ },
+
+ {
+ "namespace": "functions",
+ "description": "The functions API.",
+ "functions": [
+ {
+ "id": "two"
+ },
+ {
+ "id": "four"
+ }
+ ],
+
+ "types": {
+ "one": { "key": "value" }
+ }
+ },
+
+ {
+ "namespace": "types",
+ "description": "The types API.",
+ "functions": [
+ { "id": "one" }
+ ],
+ "types": {
+ "two": {
+ "key": "value"
+ },
+ "four": {
+ "key": "value"
+ }
+ }
+ },
+
+ {
+ "namespace": "nested",
+ "description": "The nested API.",
+ "properties": {
+ "sync": {
+ "functions": [
+ {
+ "id": "two"
+ },
+ {
+ "id": "four"
+ }
+ ],
+ "types": {
+ "two": {
+ "key": "value"
+ },
+ "four": {
+ "key": "value"
+ }
+ }
+ }
+ }
+ }
+ ]
+
+ schema = json_schema.CachedLoad('test/json_schema_test.json')
+ self.assertEquals(compiled, json_schema.DeleteNodes(schema, 'nocompile'))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/memoize.py b/chromium/tools/json_schema_compiler/memoize.py
new file mode 100644
index 00000000000..1402a6ecd80
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/memoize.py
@@ -0,0 +1,13 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+def memoize(fn):
+ '''Decorates |fn| to memoize.
+ '''
+ memory = {}
+ def impl(*args):
+ if args not in memory:
+ memory[args] = fn(*args)
+ return memory[args]
+ return impl
diff --git a/chromium/tools/json_schema_compiler/model.py b/chromium/tools/json_schema_compiler/model.py
new file mode 100644
index 00000000000..50a9c581403
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/model.py
@@ -0,0 +1,492 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os.path
+
+from json_parse import OrderedDict
+from memoize import memoize
+
+class ParseException(Exception):
+ """Thrown when data in the model is invalid.
+ """
+ def __init__(self, parent, message):
+ hierarchy = _GetModelHierarchy(parent)
+ hierarchy.append(message)
+ Exception.__init__(
+ self, 'Model parse exception at:\n' + '\n'.join(hierarchy))
+
+class Model(object):
+ """Model of all namespaces that comprise an API.
+
+ Properties:
+ - |namespaces| a map of a namespace name to its model.Namespace
+ """
+ def __init__(self):
+ self.namespaces = {}
+
+ def AddNamespace(self, json, source_file, include_compiler_options=False):
+ """Add a namespace's json to the model and returns the namespace.
+ """
+ namespace = Namespace(json,
+ source_file,
+ include_compiler_options=include_compiler_options)
+ self.namespaces[namespace.name] = namespace
+ return namespace
+
+class Namespace(object):
+ """An API namespace.
+
+ Properties:
+ - |name| the name of the namespace
+ - |description| the description of the namespace
+ - |unix_name| the unix_name of the namespace
+ - |source_file| the file that contained the namespace definition
+ - |source_file_dir| the directory component of |source_file|
+ - |source_file_filename| the filename component of |source_file|
+ - |platforms| if not None, the list of platforms that the namespace is
+ available to
+ - |types| a map of type names to their model.Type
+ - |functions| a map of function names to their model.Function
+ - |events| a map of event names to their model.Function
+ - |properties| a map of property names to their model.Property
+ - |compiler_options| the compiler_options dict, only not empty if
+ |include_compiler_options| is True
+ """
+ def __init__(self, json, source_file, include_compiler_options=False):
+ self.name = json['namespace']
+ if 'description' not in json:
+ # TODO(kalman): Go back to throwing an error here.
+ print('%s must have a "description" field. This will appear '
+ 'on the API summary page.' % self.name)
+ json['description'] = ''
+ self.description = json['description']
+ self.unix_name = UnixName(self.name)
+ self.source_file = source_file
+ self.source_file_dir, self.source_file_filename = os.path.split(source_file)
+ self.parent = None
+ self.platforms = _GetPlatforms(json)
+ toplevel_origin = Origin(from_client=True, from_json=True)
+ self.types = _GetTypes(self, json, self, toplevel_origin)
+ self.functions = _GetFunctions(self, json, self)
+ self.events = _GetEvents(self, json, self)
+ self.properties = _GetProperties(self, json, self, toplevel_origin)
+ self.compiler_options = (json.get('compiler_options', {})
+ if include_compiler_options else {})
+
+class Origin(object):
+ """Stores the possible origin of model object as a pair of bools. These are:
+
+ |from_client| indicating that instances can originate from users of
+ generated code (for example, function results), or
+ |from_json| indicating that instances can originate from the JSON (for
+ example, function parameters)
+
+ It is possible for model objects to originate from both the client and json,
+ for example Types defined in the top-level schema, in which case both
+ |from_client| and |from_json| would be True.
+ """
+ def __init__(self, from_client=False, from_json=False):
+ if not from_client and not from_json:
+ raise ValueError('One of from_client or from_json must be true')
+ self.from_client = from_client
+ self.from_json = from_json
+
+class Type(object):
+ """A Type defined in the json.
+
+ Properties:
+ - |name| the type name
+ - |namespace| the Type's namespace
+ - |description| the description of the type (if provided)
+ - |properties| a map of property unix_names to their model.Property
+ - |functions| a map of function names to their model.Function
+ - |events| a map of event names to their model.Event
+ - |origin| the Origin of the type
+ - |property_type| the PropertyType of this Type
+ - |item_type| if this is an array, the type of items in the array
+ - |simple_name| the name of this Type without a namespace
+ - |additional_properties| the type of the additional properties, if any is
+ specified
+ """
+ def __init__(self,
+ parent,
+ name,
+ json,
+ namespace,
+ origin):
+ self.name = name
+ self.namespace = namespace
+ self.simple_name = _StripNamespace(self.name, namespace)
+ self.unix_name = UnixName(self.name)
+ self.description = json.get('description', None)
+ self.origin = origin
+ self.parent = parent
+ self.instance_of = json.get('isInstanceOf', None)
+
+ # TODO(kalman): Only objects need functions/events/properties, but callers
+ # assume that all types have them. Fix this.
+ self.functions = _GetFunctions(self, json, namespace)
+ self.events = _GetEvents(self, json, namespace)
+ self.properties = _GetProperties(self, json, namespace, origin)
+
+ json_type = json.get('type', None)
+ if json_type == 'array':
+ self.property_type = PropertyType.ARRAY
+ self.item_type = Type(
+ self, '%sType' % name, json['items'], namespace, origin)
+ elif '$ref' in json:
+ self.property_type = PropertyType.REF
+ self.ref_type = json['$ref']
+ elif 'enum' in json and json_type == 'string':
+ self.property_type = PropertyType.ENUM
+ self.enum_values = [value for value in json['enum']]
+ elif json_type == 'any':
+ self.property_type = PropertyType.ANY
+ elif json_type == 'binary':
+ self.property_type = PropertyType.BINARY
+ elif json_type == 'boolean':
+ self.property_type = PropertyType.BOOLEAN
+ elif json_type == 'integer':
+ self.property_type = PropertyType.INTEGER
+ elif (json_type == 'double' or
+ json_type == 'number'):
+ self.property_type = PropertyType.DOUBLE
+ elif json_type == 'string':
+ self.property_type = PropertyType.STRING
+ elif 'choices' in json:
+ self.property_type = PropertyType.CHOICES
+ def generate_type_name(type_json):
+ if 'items' in type_json:
+ return '%ss' % generate_type_name(type_json['items'])
+ if '$ref' in type_json:
+ return type_json['$ref']
+ if 'type' in type_json:
+ return type_json['type']
+ return None
+ self.choices = [
+ Type(self,
+ generate_type_name(choice) or 'choice%s' % i,
+ choice,
+ namespace,
+ origin)
+ for i, choice in enumerate(json['choices'])]
+ elif json_type == 'object':
+ if not (
+ 'properties' in json or
+ 'additionalProperties' in json or
+ 'functions' in json or
+ 'events' in json):
+ raise ParseException(self, name + " has no properties or functions")
+ self.property_type = PropertyType.OBJECT
+ additional_properties_json = json.get('additionalProperties', None)
+ if additional_properties_json is not None:
+ self.additional_properties = Type(self,
+ 'additionalProperties',
+ additional_properties_json,
+ namespace,
+ origin)
+ else:
+ self.additional_properties = None
+ elif json_type == 'function':
+ self.property_type = PropertyType.FUNCTION
+ # Sometimes we might have an unnamed function, e.g. if it's a property
+ # of an object. Use the name of the property in that case.
+ function_name = json.get('name', name)
+ self.function = Function(self, function_name, json, namespace, origin)
+ else:
+ raise ParseException(self, 'Unsupported JSON type %s' % json_type)
+
+class Function(object):
+ """A Function defined in the API.
+
+ Properties:
+ - |name| the function name
+ - |platforms| if not None, the list of platforms that the function is
+ available to
+ - |params| a list of parameters to the function (order matters). A separate
+ parameter is used for each choice of a 'choices' parameter
+ - |description| a description of the function (if provided)
+ - |callback| the callback parameter to the function. There should be exactly
+ one
+ - |optional| whether the Function is "optional"; this only makes sense to be
+ present when the Function is representing a callback property
+ - |simple_name| the name of this Function without a namespace
+ - |returns| the return type of the function; None if the function does not
+ return a value
+ """
+ def __init__(self,
+ parent,
+ name,
+ json,
+ namespace,
+ origin):
+ self.name = name
+ self.simple_name = _StripNamespace(self.name, namespace)
+ self.platforms = _GetPlatforms(json)
+ self.params = []
+ self.description = json.get('description')
+ self.callback = None
+ self.optional = json.get('optional', False)
+ self.parent = parent
+ self.nocompile = json.get('nocompile')
+ options = json.get('options', {})
+ self.conditions = options.get('conditions', [])
+ self.actions = options.get('actions', [])
+ self.supports_listeners = options.get('supportsListeners', True)
+ self.supports_rules = options.get('supportsRules', False)
+
+ def GeneratePropertyFromParam(p):
+ return Property(self, p['name'], p, namespace, origin)
+
+ self.filters = [GeneratePropertyFromParam(filter)
+ for filter in json.get('filters', [])]
+ callback_param = None
+ for param in json.get('parameters', []):
+ if param.get('type') == 'function':
+ if callback_param:
+ # No ParseException because the webstore has this.
+ # Instead, pretend all intermediate callbacks are properties.
+ self.params.append(GeneratePropertyFromParam(callback_param))
+ callback_param = param
+ else:
+ self.params.append(GeneratePropertyFromParam(param))
+
+ if callback_param:
+ self.callback = Function(self,
+ callback_param['name'],
+ callback_param,
+ namespace,
+ Origin(from_client=True))
+
+ self.returns = None
+ if 'returns' in json:
+ self.returns = Type(self,
+ '%sReturnType' % name,
+ json['returns'],
+ namespace,
+ origin)
+
+class Property(object):
+ """A property of a type OR a parameter to a function.
+ Properties:
+ - |name| name of the property as in the json. This shouldn't change since
+ it is the key used to access DictionaryValues
+ - |unix_name| the unix_style_name of the property. Used as variable name
+ - |optional| a boolean representing whether the property is optional
+ - |description| a description of the property (if provided)
+ - |type_| the model.Type of this property
+ - |simple_name| the name of this Property without a namespace
+ """
+ def __init__(self, parent, name, json, namespace, origin):
+ """Creates a Property from JSON.
+ """
+ self.parent = parent
+ self.name = name
+ self._unix_name = UnixName(self.name)
+ self._unix_name_used = False
+ self.origin = origin
+ self.simple_name = _StripNamespace(self.name, namespace)
+ self.description = json.get('description', None)
+ self.optional = json.get('optional', None)
+ self.instance_of = json.get('isInstanceOf', None)
+
+ # HACK: only support very specific value types.
+ is_allowed_value = (
+ '$ref' not in json and
+ ('type' not in json or json['type'] == 'integer'
+ or json['type'] == 'string'))
+
+ self.value = None
+ if 'value' in json and is_allowed_value:
+ self.value = json['value']
+ if 'type' not in json:
+ # Sometimes the type of the value is left out, and we need to figure
+ # it out for ourselves.
+ if isinstance(self.value, int):
+ json['type'] = 'integer'
+ elif isinstance(self.value, basestring):
+ json['type'] = 'string'
+ else:
+ # TODO(kalman): support more types as necessary.
+ raise ParseException(
+ parent,
+ '"%s" is not a supported type for "value"' % type(self.value))
+
+ self.type_ = Type(parent, name, json, namespace, origin)
+
+ def GetUnixName(self):
+ """Gets the property's unix_name. Raises AttributeError if not set.
+ """
+ if not self._unix_name:
+ raise AttributeError('No unix_name set on %s' % self.name)
+ self._unix_name_used = True
+ return self._unix_name
+
+ def SetUnixName(self, unix_name):
+ """Set the property's unix_name. Raises AttributeError if the unix_name has
+ already been used (GetUnixName has been called).
+ """
+ if unix_name == self._unix_name:
+ return
+ if self._unix_name_used:
+ raise AttributeError(
+ 'Cannot set the unix_name on %s; '
+ 'it is already used elsewhere as %s' %
+ (self.name, self._unix_name))
+ self._unix_name = unix_name
+
+ unix_name = property(GetUnixName, SetUnixName)
+
+class _Enum(object):
+ """Superclass for enum types with a "name" field, setting up repr/eq/ne.
+ Enums need to do this so that equality/non-equality work over pickling.
+ """
+ @staticmethod
+ def GetAll(cls):
+ """Yields all _Enum objects declared in |cls|.
+ """
+ for prop_key in dir(cls):
+ prop_value = getattr(cls, prop_key)
+ if isinstance(prop_value, _Enum):
+ yield prop_value
+
+ def __init__(self, name):
+ self.name = name
+
+ def __eq__(self, other):
+ return type(other) == type(self) and other.name == self.name
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __repr__(self):
+ return self.name
+
+ def __str__(self):
+ return repr(self)
+
+class _PropertyTypeInfo(_Enum):
+ def __init__(self, is_fundamental, name):
+ _Enum.__init__(self, name)
+ self.is_fundamental = is_fundamental
+
+class PropertyType(object):
+ """Enum of different types of properties/parameters.
+ """
+ ANY = _PropertyTypeInfo(False, "any")
+ ARRAY = _PropertyTypeInfo(False, "array")
+ BINARY = _PropertyTypeInfo(False, "binary")
+ BOOLEAN = _PropertyTypeInfo(True, "boolean")
+ CHOICES = _PropertyTypeInfo(False, "choices")
+ DOUBLE = _PropertyTypeInfo(True, "double")
+ ENUM = _PropertyTypeInfo(False, "enum")
+ FUNCTION = _PropertyTypeInfo(False, "function")
+ INT64 = _PropertyTypeInfo(True, "int64")
+ INTEGER = _PropertyTypeInfo(True, "integer")
+ OBJECT = _PropertyTypeInfo(False, "object")
+ REF = _PropertyTypeInfo(False, "ref")
+ STRING = _PropertyTypeInfo(True, "string")
+
+@memoize
+def UnixName(name):
+ '''Returns the unix_style name for a given lowerCamelCase string.
+ '''
+ unix_name = []
+ for i, c in enumerate(name):
+ if c.isupper() and i > 0 and name[i - 1] != '_':
+ # Replace lowerUpper with lower_Upper.
+ if name[i - 1].islower():
+ unix_name.append('_')
+ # Replace ACMEWidgets with ACME_Widgets
+ elif i + 1 < len(name) and name[i + 1].islower():
+ unix_name.append('_')
+ if c == '.':
+ # Replace hello.world with hello_world.
+ unix_name.append('_')
+ else:
+ # Everything is lowercase.
+ unix_name.append(c.lower())
+ return ''.join(unix_name)
+
+def _StripNamespace(name, namespace):
+ if name.startswith(namespace.name + '.'):
+ return name[len(namespace.name + '.'):]
+ return name
+
+def _GetModelHierarchy(entity):
+ """Returns the hierarchy of the given model entity."""
+ hierarchy = []
+ while entity is not None:
+ hierarchy.append(getattr(entity, 'name', repr(entity)))
+ if isinstance(entity, Namespace):
+ hierarchy.insert(0, ' in %s' % entity.source_file)
+ entity = getattr(entity, 'parent', None)
+ hierarchy.reverse()
+ return hierarchy
+
+def _GetTypes(parent, json, namespace, origin):
+ """Creates Type objects extracted from |json|.
+ """
+ types = OrderedDict()
+ for type_json in json.get('types', []):
+ type_ = Type(parent, type_json['id'], type_json, namespace, origin)
+ types[type_.name] = type_
+ return types
+
+def _GetFunctions(parent, json, namespace):
+ """Creates Function objects extracted from |json|.
+ """
+ functions = OrderedDict()
+ for function_json in json.get('functions', []):
+ function = Function(parent,
+ function_json['name'],
+ function_json,
+ namespace,
+ Origin(from_json=True))
+ functions[function.name] = function
+ return functions
+
+def _GetEvents(parent, json, namespace):
+ """Creates Function objects generated from the events in |json|.
+ """
+ events = OrderedDict()
+ for event_json in json.get('events', []):
+ event = Function(parent,
+ event_json['name'],
+ event_json,
+ namespace,
+ Origin(from_client=True))
+ events[event.name] = event
+ return events
+
+def _GetProperties(parent, json, namespace, origin):
+ """Generates Property objects extracted from |json|.
+ """
+ properties = OrderedDict()
+ for name, property_json in json.get('properties', {}).items():
+ properties[name] = Property(parent, name, property_json, namespace, origin)
+ return properties
+
+class _PlatformInfo(_Enum):
+ def __init__(self, name):
+ _Enum.__init__(self, name)
+
+class Platforms(object):
+ """Enum of the possible platforms.
+ """
+ CHROMEOS = _PlatformInfo("chromeos")
+ CHROMEOS_TOUCH = _PlatformInfo("chromeos_touch")
+ LINUX = _PlatformInfo("linux")
+ MAC = _PlatformInfo("mac")
+ WIN = _PlatformInfo("win")
+
+def _GetPlatforms(json):
+ if 'platforms' not in json:
+ return None
+ platforms = []
+ for platform_name in json['platforms']:
+ for platform_enum in _Enum.GetAll(Platforms):
+ if platform_name == platform_enum.name:
+ platforms.append(platform_enum)
+ break
+ return platforms
diff --git a/chromium/tools/json_schema_compiler/model_test.py b/chromium/tools/json_schema_compiler/model_test.py
new file mode 100755
index 00000000000..5003af91e24
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/model_test.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from json_schema import CachedLoad
+import model
+import unittest
+
+class ModelTest(unittest.TestCase):
+ def setUp(self):
+ self.model = model.Model()
+ self.permissions_json = CachedLoad('test/permissions.json')
+ self.model.AddNamespace(self.permissions_json[0],
+ 'path/to/permissions.json')
+ self.permissions = self.model.namespaces.get('permissions')
+ self.windows_json = CachedLoad('test/windows.json')
+ self.model.AddNamespace(self.windows_json[0],
+ 'path/to/window.json')
+ self.windows = self.model.namespaces.get('windows')
+ self.tabs_json = CachedLoad('test/tabs.json')
+ self.model.AddNamespace(self.tabs_json[0],
+ 'path/to/tabs.json')
+ self.tabs = self.model.namespaces.get('tabs')
+
+ def testNamespaces(self):
+ self.assertEquals(3, len(self.model.namespaces))
+ self.assertTrue(self.permissions)
+
+ def testHasFunctions(self):
+ self.assertEquals(["contains", "getAll", "remove", "request"],
+ sorted(self.permissions.functions.keys()))
+
+ def testHasTypes(self):
+ self.assertEquals(['Tab'], self.tabs.types.keys())
+ self.assertEquals(['Permissions'], self.permissions.types.keys())
+ self.assertEquals(['Window'], self.windows.types.keys())
+
+ def testHasProperties(self):
+ self.assertEquals(["active", "favIconUrl", "highlighted", "id",
+ "incognito", "index", "pinned", "selected", "status", "title", "url",
+ "windowId"],
+ sorted(self.tabs.types['Tab'].properties.keys()))
+
+ def testProperties(self):
+ string_prop = self.tabs.types['Tab'].properties['status']
+ self.assertEquals(model.PropertyType.STRING,
+ string_prop.type_.property_type)
+ integer_prop = self.tabs.types['Tab'].properties['id']
+ self.assertEquals(model.PropertyType.INTEGER,
+ integer_prop.type_.property_type)
+ array_prop = self.windows.types['Window'].properties['tabs']
+ self.assertEquals(model.PropertyType.ARRAY,
+ array_prop.type_.property_type)
+ self.assertEquals(model.PropertyType.REF,
+ array_prop.type_.item_type.property_type)
+ self.assertEquals('tabs.Tab', array_prop.type_.item_type.ref_type)
+ object_prop = self.tabs.functions['query'].params[0]
+ self.assertEquals(model.PropertyType.OBJECT,
+ object_prop.type_.property_type)
+ self.assertEquals(
+ ["active", "highlighted", "pinned", "status", "title", "url",
+ "windowId", "windowType"],
+ sorted(object_prop.type_.properties.keys()))
+
+ def testChoices(self):
+ self.assertEquals(model.PropertyType.CHOICES,
+ self.tabs.functions['move'].params[0].type_.property_type)
+
+ def testPropertyNotImplemented(self):
+ (self.permissions_json[0]['types'][0]
+ ['properties']['permissions']['type']) = 'something'
+ self.assertRaises(model.ParseException, self.model.AddNamespace,
+ self.permissions_json[0], 'path/to/something.json')
+
+ def testDescription(self):
+ self.assertFalse(
+ self.permissions.functions['contains'].params[0].description)
+ self.assertEquals('True if the extension has the specified permissions.',
+ self.permissions.functions['contains'].callback.params[0].description)
+
+ def testPropertyUnixName(self):
+ param = self.tabs.functions['move'].params[0]
+ self.assertEquals('tab_ids', param.unix_name)
+
+ def testUnixName(self):
+ expectations = {
+ 'foo': 'foo',
+ 'fooBar': 'foo_bar',
+ 'fooBarBaz': 'foo_bar_baz',
+ 'fooBARBaz': 'foo_bar_baz',
+ 'fooBAR': 'foo_bar',
+ 'FOO': 'foo',
+ 'FOOBar': 'foo_bar',
+ 'foo.bar': 'foo_bar',
+ 'foo.BAR': 'foo_bar',
+ 'foo.barBAZ': 'foo_bar_baz',
+ 'foo_Bar_Baz_box': 'foo_bar_baz_box',
+ }
+ for name in expectations:
+ self.assertEquals(expectations[name], model.UnixName(name));
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/preview.py b/chromium/tools/json_schema_compiler/preview.py
new file mode 100755
index 00000000000..22ed0f2df9f
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/preview.py
@@ -0,0 +1,366 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Server for viewing the compiled C++ code from tools/json_schema_compiler.
+"""
+
+import cc_generator
+import code
+import compiler
+import cpp_type_generator
+import cpp_util
+import h_generator
+import idl_schema
+import json_schema
+import model
+import optparse
+import os
+import schema_loader
+import sys
+import urlparse
+from highlighters import (
+ pygments_highlighter, none_highlighter, hilite_me_highlighter)
+from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+
+class CompilerHandler(BaseHTTPRequestHandler):
+ """A HTTPRequestHandler that outputs the result of tools/json_schema_compiler.
+ """
+ def do_GET(self):
+ parsed_url = urlparse.urlparse(self.path)
+ request_path = self._GetRequestPath(parsed_url)
+
+ chromium_favicon = 'http://codereview.chromium.org/static/favicon.ico'
+
+ head = code.Code()
+ head.Append('<link rel="icon" href="%s">' % chromium_favicon)
+ head.Append('<link rel="shortcut icon" href="%s">' % chromium_favicon)
+
+ body = code.Code()
+
+ try:
+ if os.path.isdir(request_path):
+ self._ShowPanels(parsed_url, head, body)
+ else:
+ self._ShowCompiledFile(parsed_url, head, body)
+ finally:
+ self.wfile.write('<html><head>')
+ self.wfile.write(head.Render())
+ self.wfile.write('</head><body>')
+ self.wfile.write(body.Render())
+ self.wfile.write('</body></html>')
+
+ def _GetRequestPath(self, parsed_url, strip_nav=False):
+ """Get the relative path from the current directory to the requested file.
+ """
+ path = parsed_url.path
+ if strip_nav:
+ path = parsed_url.path.replace('/nav', '')
+ return os.path.normpath(os.curdir + path)
+
+ def _ShowPanels(self, parsed_url, head, body):
+ """Show the previewer frame structure.
+
+ Code panes are populated via XHR after links in the nav pane are clicked.
+ """
+ (head.Append('<style>')
+ .Append('body {')
+ .Append(' margin: 0;')
+ .Append('}')
+ .Append('.pane {')
+ .Append(' height: 100%;')
+ .Append(' overflow-x: auto;')
+ .Append(' overflow-y: scroll;')
+ .Append(' display: inline-block;')
+ .Append('}')
+ .Append('#nav_pane {')
+ .Append(' width: 20%;')
+ .Append('}')
+ .Append('#nav_pane ul {')
+ .Append(' list-style-type: none;')
+ .Append(' padding: 0 0 0 1em;')
+ .Append('}')
+ .Append('#cc_pane {')
+ .Append(' width: 40%;')
+ .Append('}')
+ .Append('#h_pane {')
+ .Append(' width: 40%;')
+ .Append('}')
+ .Append('</style>')
+ )
+
+ body.Append(
+ '<div class="pane" id="nav_pane">%s</div>'
+ '<div class="pane" id="h_pane"></div>'
+ '<div class="pane" id="cc_pane"></div>' %
+ self._RenderNavPane(parsed_url.path[1:])
+ )
+
+ # The Javascript that interacts with the nav pane and panes to show the
+ # compiled files as the URL or highlighting options change.
+ body.Append('''<script type="text/javascript">
+// Calls a function for each highlighter style <select> element.
+function forEachHighlighterStyle(callback) {
+ var highlighterStyles =
+ document.getElementsByClassName('highlighter_styles');
+ for (var i = 0; i < highlighterStyles.length; ++i)
+ callback(highlighterStyles[i]);
+}
+
+// Called when anything changes, such as the highlighter or hashtag.
+function updateEverything() {
+ var highlighters = document.getElementById('highlighters');
+ var highlighterName = highlighters.value;
+
+ // Cache in localStorage for when the page loads next.
+ localStorage.highlightersValue = highlighterName;
+
+ // Show/hide the highlighter styles.
+ var highlighterStyleName = '';
+ forEachHighlighterStyle(function(highlighterStyle) {
+ if (highlighterStyle.id === highlighterName + '_styles') {
+ highlighterStyle.removeAttribute('style')
+ highlighterStyleName = highlighterStyle.value;
+ } else {
+ highlighterStyle.setAttribute('style', 'display:none')
+ }
+
+ // Cache in localStorage for when the page next loads.
+ localStorage[highlighterStyle.id + 'Value'] = highlighterStyle.value;
+ });
+
+ // Populate the code panes.
+ function populateViaXHR(elementId, requestPath) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState != 4)
+ return;
+ if (xhr.status != 200) {
+ alert('XHR error to ' + requestPath);
+ return;
+ }
+ document.getElementById(elementId).innerHTML = xhr.responseText;
+ };
+ xhr.open('GET', requestPath, true);
+ xhr.send();
+ }
+
+ var targetName = window.location.hash;
+ targetName = targetName.substring('#'.length);
+ targetName = targetName.split('.', 1)[0]
+
+ if (targetName !== '') {
+ var basePath = window.location.pathname;
+ var query = 'highlighter=' + highlighterName + '&' +
+ 'style=' + highlighterStyleName;
+ populateViaXHR('h_pane', basePath + '/' + targetName + '.h?' + query);
+ populateViaXHR('cc_pane', basePath + '/' + targetName + '.cc?' + query);
+ }
+}
+
+// Initial load: set the values of highlighter and highlighterStyles from
+// localStorage.
+(function() {
+var cachedValue = localStorage.highlightersValue;
+if (cachedValue)
+ document.getElementById('highlighters').value = cachedValue;
+
+forEachHighlighterStyle(function(highlighterStyle) {
+ var cachedValue = localStorage[highlighterStyle.id + 'Value'];
+ if (cachedValue)
+ highlighterStyle.value = cachedValue;
+});
+})();
+
+window.addEventListener('hashchange', updateEverything, false);
+updateEverything();
+</script>''')
+
+ def _LoadModel(self, basedir, name):
+ """Loads and returns the model for the |name| API from either its JSON or
+ IDL file, e.g.
+ name=contextMenus will be loaded from |basedir|/context_menus.json,
+ name=alarms will be loaded from |basedir|/alarms.idl.
+ """
+ loaders = {
+ 'json': json_schema.Load,
+ 'idl': idl_schema.Load
+ }
+ # APIs are referred to like "webRequest" but that's in a file
+ # "web_request.json" so we need to unixify the name.
+ unix_name = model.UnixName(name)
+ for loader_ext, loader_fn in loaders.items():
+ file_path = '%s/%s.%s' % (basedir, unix_name, loader_ext)
+ if os.path.exists(file_path):
+ # For historical reasons these files contain a singleton list with the
+ # model, so just return that single object.
+ return (loader_fn(file_path)[0], file_path)
+ raise ValueError('File for model "%s" not found' % name)
+
+ def _ShowCompiledFile(self, parsed_url, head, body):
+ """Show the compiled version of a json or idl file given the path to the
+ compiled file.
+ """
+ api_model = model.Model()
+
+ request_path = self._GetRequestPath(parsed_url)
+ (file_root, file_ext) = os.path.splitext(request_path)
+ (filedir, filename) = os.path.split(file_root)
+
+ try:
+ # Get main file.
+ (api_def, file_path) = self._LoadModel(filedir, filename)
+ namespace = api_model.AddNamespace(api_def, file_path)
+ type_generator = cpp_type_generator.CppTypeGenerator(
+ api_model,
+ schema_loader.SchemaLoader(filedir),
+ namespace)
+
+ # Get the model's dependencies.
+ for dependency in api_def.get('dependencies', []):
+ # Dependencies can contain : in which case they don't refer to APIs,
+ # rather, permissions or manifest keys.
+ if ':' in dependency:
+ continue
+ (api_def, file_path) = self._LoadModel(filedir, dependency)
+ referenced_namespace = api_model.AddNamespace(api_def, file_path)
+ if referenced_namespace:
+ type_generator.AddNamespace(referenced_namespace,
+ cpp_util.Classname(referenced_namespace.name).lower())
+
+ # Generate code
+ cpp_namespace = 'generated_api_schemas'
+ if file_ext == '.h':
+ cpp_code = (h_generator.HGenerator(type_generator, cpp_namespace)
+ .Generate(namespace).Render())
+ elif file_ext == '.cc':
+ cpp_code = (cc_generator.CCGenerator(type_generator, cpp_namespace)
+ .Generate(namespace).Render())
+ else:
+ self.send_error(404, "File not found: %s" % request_path)
+ return
+
+ # Do highlighting on the generated code
+ (highlighter_param, style_param) = self._GetHighlighterParams(parsed_url)
+ head.Append('<style>' +
+ self.server.highlighters[highlighter_param].GetCSS(style_param) +
+ '</style>')
+ body.Append(self.server.highlighters[highlighter_param]
+ .GetCodeElement(cpp_code, style_param))
+ except IOError:
+ self.send_error(404, "File not found: %s" % request_path)
+ return
+ except (TypeError, KeyError, AttributeError,
+ AssertionError, NotImplementedError) as error:
+ body.Append('<pre>')
+ body.Append('compiler error: %s' % error)
+ body.Append('Check server log for more details')
+ body.Append('</pre>')
+ raise
+
+ def _GetHighlighterParams(self, parsed_url):
+ """Get the highlighting parameters from a parsed url.
+ """
+ query_dict = urlparse.parse_qs(parsed_url.query)
+ return (query_dict.get('highlighter', ['pygments'])[0],
+ query_dict.get('style', ['colorful'])[0])
+
+ def _RenderNavPane(self, path):
+ """Renders an HTML nav pane.
+
+ This consists of a select element to set highlight style, and a list of all
+ files at |path| with the appropriate onclick handlers to open either
+ subdirectories or JSON files.
+ """
+ html = code.Code()
+
+ # Highlighter chooser.
+ html.Append('<select id="highlighters" onChange="updateEverything()">')
+ for name, highlighter in self.server.highlighters.items():
+ html.Append('<option value="%s">%s</option>' %
+ (name, highlighter.DisplayName()))
+ html.Append('</select>')
+
+ html.Append('<br/>')
+
+ # Style for each highlighter.
+ # The correct highlighting will be shown by Javascript.
+ for name, highlighter in self.server.highlighters.items():
+ styles = sorted(highlighter.GetStyles())
+ if not styles:
+ continue
+
+ html.Append('<select class="highlighter_styles" id="%s_styles" '
+ 'onChange="updateEverything()">' % name)
+ for style in styles:
+ html.Append('<option>%s</option>' % style)
+ html.Append('</select>')
+
+ html.Append('<br/>')
+
+ # The files, with appropriate handlers.
+ html.Append('<ul>')
+
+ # Make path point to a non-empty directory. This can happen if a URL like
+ # http://localhost:8000 is navigated to.
+ if path == '':
+ path = os.curdir
+
+ # Firstly, a .. link if this isn't the root.
+ if not os.path.samefile(os.curdir, path):
+ normpath = os.path.normpath(os.path.join(path, os.pardir))
+ html.Append('<li><a href="/%s">%s/</a>' % (normpath, os.pardir))
+
+ # Each file under path/
+ for filename in sorted(os.listdir(path)):
+ full_path = os.path.join(path, filename)
+ (file_root, file_ext) = os.path.splitext(full_path)
+ if os.path.isdir(full_path) and not full_path.endswith('.xcodeproj'):
+ html.Append('<li><a href="/%s/">%s/</a>' % (full_path, filename))
+ elif file_ext in ['.json', '.idl']:
+ # cc/h panes will automatically update via the hash change event.
+ html.Append('<li><a href="#%s">%s</a>' %
+ (filename, filename))
+
+ html.Append('</ul>')
+
+ return html.Render()
+
+class PreviewHTTPServer(HTTPServer, object):
+ def __init__(self, server_address, handler, highlighters):
+ super(PreviewHTTPServer, self).__init__(server_address, handler)
+ self.highlighters = highlighters
+
+
+if __name__ == '__main__':
+ parser = optparse.OptionParser(
+ description='Runs a server to preview the json_schema_compiler output.',
+ usage='usage: %prog [option]...')
+ parser.add_option('-p', '--port', default='8000',
+ help='port to run the server on')
+
+ (opts, argv) = parser.parse_args()
+
+ try:
+ print('Starting previewserver on port %s' % opts.port)
+ print('The extension documentation can be found at:')
+ print('')
+ print(' http://localhost:%s/chrome/common/extensions/api' % opts.port)
+ print('')
+
+ highlighters = {
+ 'hilite': hilite_me_highlighter.HiliteMeHighlighter(),
+ 'none': none_highlighter.NoneHighlighter()
+ }
+ try:
+ highlighters['pygments'] = pygments_highlighter.PygmentsHighlighter()
+ except ImportError as e:
+ pass
+
+ server = PreviewHTTPServer(('', int(opts.port)),
+ CompilerHandler,
+ highlighters)
+ server.serve_forever()
+ except KeyboardInterrupt:
+ server.socket.close()
diff --git a/chromium/tools/json_schema_compiler/schema_loader.py b/chromium/tools/json_schema_compiler/schema_loader.py
new file mode 100644
index 00000000000..c434dc16746
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/schema_loader.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+import idl_schema
+import json_schema
+from model import Model
+
+class SchemaLoader(object):
+ '''Resolves a type name into the namespace the type belongs to.
+ '''
+ def __init__(self, api_path):
+ self._api_path = api_path
+
+ def ResolveType(self, full_name, default_namespace):
+ name_parts = full_name.rsplit('.', 1)
+ if len(name_parts) == 1:
+ if full_name not in default_namespace.types:
+ return None
+ return default_namespace
+ namespace_name, type_name = name_parts
+ real_name = None
+ for ext in ['json', 'idl']:
+ filename = '%s.%s' % (namespace_name, ext)
+ if os.path.exists(filename):
+ real_name = filename
+ break
+ if real_name is None:
+ return None
+ namespace = Model().AddNamespace(self.LoadSchema(real_name)[0],
+ os.path.join(self._api_path, real_name))
+ if type_name not in namespace.types:
+ return None
+ return namespace
+
+ def LoadSchema(self, schema):
+ schema_filename, schema_extension = os.path.splitext(schema)
+
+ if schema_extension == '.json':
+ api_defs = json_schema.Load(schema)
+ elif schema_extension == '.idl':
+ api_defs = idl_schema.Load(schema)
+ else:
+ sys.exit('Did not recognize file extension %s for schema %s' %
+ (schema_extension, schema))
+ if len(api_defs) != 1:
+ sys.exit('File %s has multiple schemas. Files are only allowed to contain'
+ 'a single schema.' % schema)
+
+ return api_defs
diff --git a/chromium/tools/json_schema_compiler/schema_util.py b/chromium/tools/json_schema_compiler/schema_util.py
new file mode 100644
index 00000000000..7ce399e8ed3
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/schema_util.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Utilies for the processing of schema python structures.
+"""
+
+import json_parse
+
+def CapitalizeFirstLetter(value):
+ return value[0].capitalize() + value[1:]
+
+def GetNamespace(ref):
+ return SplitNamespace(ref)[0]
+
+def StripNamespace(ref):
+ return SplitNamespace(ref)[1]
+
+def SplitNamespace(ref):
+ """Returns (namespace, entity) from |ref|, e.g. app.window.AppWindow ->
+ (app.window, AppWindow). If |ref| isn't qualified then returns (None, ref).
+ """
+ if '.' in ref:
+ return tuple(ref.rsplit('.', 1))
+ return (None, ref)
+
+def JsFunctionNameToClassName(namespace_name, function_name):
+ """Transform a fully qualified function name like foo.bar.baz into FooBarBaz
+
+ Also strips any leading 'Experimental' prefix."""
+ parts = []
+ full_name = namespace_name + "." + function_name
+ for part in full_name.split("."):
+ parts.append(CapitalizeFirstLetter(part))
+ if parts[0] == "Experimental":
+ del parts[0]
+ class_name = "".join(parts)
+ return class_name
diff --git a/chromium/tools/json_schema_compiler/schema_util_test.py b/chromium/tools/json_schema_compiler/schema_util_test.py
new file mode 100755
index 00000000000..154da0137ea
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/schema_util_test.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from schema_util import JsFunctionNameToClassName
+from schema_util import StripNamespace
+import unittest
+
+class SchemaUtilTest(unittest.TestCase):
+ def testStripNamespace(self):
+ self.assertEquals('Bar', StripNamespace('foo.Bar'))
+ self.assertEquals('Baz', StripNamespace('Baz'))
+
+ def testJsFunctionNameToClassName(self):
+ self.assertEquals('FooBar', JsFunctionNameToClassName('foo', 'bar'))
+ self.assertEquals('FooBar',
+ JsFunctionNameToClassName('experimental.foo', 'bar'))
+ self.assertEquals('FooBarBaz',
+ JsFunctionNameToClassName('foo.bar', 'baz'))
+ self.assertEquals('FooBarBaz',
+ JsFunctionNameToClassName('experimental.foo.bar', 'baz'))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp b/chromium/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp
new file mode 100644
index 00000000000..27ec4385be8
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/test/json_schema_compiler_tests.gyp
@@ -0,0 +1,44 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'json_schema_compiler_tests',
+ 'type': 'static_library',
+ 'variables': {
+ 'chromium_code': 1,
+ 'schema_files': [
+ 'additional_properties.json',
+ 'any.json',
+ 'arrays.json',
+ 'callbacks.json',
+ 'choices.json',
+ 'crossref.json',
+ 'enums.json',
+ 'functions_as_parameters.json',
+ 'functions_on_types.json',
+ 'idl_basics.idl',
+ 'idl_object_types.idl',
+ 'objects.json',
+ 'simple_api.json',
+ 'error_generation.json'
+ ],
+ 'cc_dir': 'tools/json_schema_compiler/test',
+ 'root_namespace': 'test::api',
+ },
+ 'inputs': [
+ '<@(schema_files)',
+ ],
+ 'sources': [
+ '<@(schema_files)',
+ 'test_util.cc',
+ 'test_util.h',
+ ],
+ 'includes': ['../../../build/json_schema_compile.gypi'],
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [4267, ],
+ },
+ ],
+}
diff --git a/chromium/tools/json_schema_compiler/util.cc b/chromium/tools/json_schema_compiler/util.cc
new file mode 100644
index 00000000000..d0e77659e6a
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/util.cc
@@ -0,0 +1,97 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/json_schema_compiler/util.h"
+
+#include "base/values.h"
+
+namespace json_schema_compiler {
+namespace util {
+
+bool GetItemFromList(const base::ListValue& from, int index, int* out) {
+ return from.GetInteger(index, out);
+}
+
+bool GetItemFromList(const base::ListValue& from, int index, bool* out) {
+ return from.GetBoolean(index, out);
+}
+
+bool GetItemFromList(const base::ListValue& from, int index, double* out) {
+ return from.GetDouble(index, out);
+}
+
+bool GetItemFromList(const base::ListValue& from, int index, std::string* out) {
+ return from.GetString(index, out);
+}
+
+bool GetItemFromList(const base::ListValue& from,
+ int index,
+ linked_ptr<base::Value>* out) {
+ const base::Value* value = NULL;
+ if (!from.Get(index, &value))
+ return false;
+ *out = make_linked_ptr(value->DeepCopy());
+ return true;
+}
+
+bool GetItemFromList(const base::ListValue& from, int index,
+ linked_ptr<base::DictionaryValue>* out) {
+ const base::DictionaryValue* dict = NULL;
+ if (!from.GetDictionary(index, &dict))
+ return false;
+ *out = make_linked_ptr(dict->DeepCopy());
+ return true;
+}
+
+void AddItemToList(const int from, base::ListValue* out) {
+ out->Append(new base::FundamentalValue(from));
+}
+
+void AddItemToList(const bool from, base::ListValue* out) {
+ out->Append(new base::FundamentalValue(from));
+}
+
+void AddItemToList(const double from, base::ListValue* out) {
+ out->Append(new base::FundamentalValue(from));
+}
+
+void AddItemToList(const std::string& from, base::ListValue* out) {
+ out->Append(new base::StringValue(from));
+}
+
+void AddItemToList(const linked_ptr<base::Value>& from,
+ base::ListValue* out) {
+ out->Append(from->DeepCopy());
+}
+
+void AddItemToList(const linked_ptr<base::DictionaryValue>& from,
+ base::ListValue* out) {
+ out->Append(static_cast<base::Value*>(from->DeepCopy()));
+}
+
+std::string ValueTypeToString(Value::Type type) {
+ switch(type) {
+ case Value::TYPE_NULL:
+ return "null";
+ case Value::TYPE_BOOLEAN:
+ return "boolean";
+ case Value::TYPE_INTEGER:
+ return "integer";
+ case Value::TYPE_DOUBLE:
+ return "number";
+ case Value::TYPE_STRING:
+ return "string";
+ case Value::TYPE_BINARY:
+ return "binary";
+ case Value::TYPE_DICTIONARY:
+ return "dictionary";
+ case Value::TYPE_LIST:
+ return "list";
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace api_util
+} // namespace extensions
diff --git a/chromium/tools/json_schema_compiler/util.h b/chromium/tools/json_schema_compiler/util.h
new file mode 100644
index 00000000000..b775be7e0cc
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/util.h
@@ -0,0 +1,181 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
+#define TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
+
+#include <string>
+#include <vector>
+
+#include "base/memory/linked_ptr.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+
+namespace json_schema_compiler {
+
+namespace util {
+
+// Creates a new item at |out| from |from|[|index|]. These are used by template
+// specializations of |Get(Optional)ArrayFromList|.
+bool GetItemFromList(const base::ListValue& from, int index, int* out);
+bool GetItemFromList(const base::ListValue& from, int index, bool* out);
+bool GetItemFromList(const base::ListValue& from, int index, double* out);
+bool GetItemFromList(const base::ListValue& from, int index, std::string* out);
+bool GetItemFromList(const base::ListValue& from,
+ int index,
+ linked_ptr<base::Value>* out);
+bool GetItemFromList(const base::ListValue& from,
+ int index,
+ linked_ptr<base::DictionaryValue>* out);
+
+// This template is used for types generated by tools/json_schema_compiler.
+template<class T>
+bool GetItemFromList(const base::ListValue& from,
+ int index,
+ linked_ptr<T>* out) {
+ const base::DictionaryValue* dict;
+ if (!from.GetDictionary(index, &dict))
+ return false;
+ scoped_ptr<T> obj(new T());
+ if (!T::Populate(*dict, obj.get()))
+ return false;
+ *out = linked_ptr<T>(obj.release());
+ return true;
+}
+
+// Populates |out| with |list|. Returns false if there is no list at the
+// specified key or if the list has anything other than |T|.
+template <class T>
+bool PopulateArrayFromList(
+ const base::ListValue& list, std::vector<T>* out) {
+ out->clear();
+ T value;
+ for (size_t i = 0; i < list.GetSize(); ++i) {
+ if (!GetItemFromList(list, i, &value))
+ return false;
+ out->push_back(value);
+ }
+
+ return true;
+}
+
+// Populates |out| with |from|.|name|. Returns false if there is no list at
+// the specified key or if the list has anything other than |T|.
+template <class T>
+bool PopulateArrayFromDictionary(
+ const base::DictionaryValue& from,
+ const std::string& name,
+ std::vector<T>* out) {
+ const base::ListValue* list = NULL;
+ if (!from.GetListWithoutPathExpansion(name, &list))
+ return false;
+
+ return PopulateArrayFromList(*list, out);
+}
+
+// Creates a new vector containing |list| at |out|. Returns
+// true on success or if there is nothing at the specified key. Returns false
+// if anything other than a list of |T| is at the specified key.
+template <class T>
+bool PopulateOptionalArrayFromList(
+ const base::ListValue& list,
+ scoped_ptr<std::vector<T> >* out) {
+ out->reset(new std::vector<T>());
+ T value;
+ for (size_t i = 0; i < list.GetSize(); ++i) {
+ if (!GetItemFromList(list, i, &value)) {
+ out->reset();
+ return false;
+ }
+ (*out)->push_back(value);
+ }
+
+ return true;
+}
+
+// Creates a new vector containing |from|.|name| at |out|. Returns
+// true on success or if there is nothing at the specified key. Returns false
+// if anything other than a list of |T| is at the specified key.
+template <class T>
+bool PopulateOptionalArrayFromDictionary(
+ const base::DictionaryValue& from,
+ const std::string& name,
+ scoped_ptr<std::vector<T> >* out) {
+ const base::ListValue* list = NULL;
+ {
+ const base::Value* maybe_list = NULL;
+ // Since |name| is optional, its absence is acceptable. However, anything
+ // other than a ListValue is not.
+ if (!from.GetWithoutPathExpansion(name, &maybe_list))
+ return true;
+ if (!maybe_list->IsType(base::Value::TYPE_LIST))
+ return false;
+ list = static_cast<const base::ListValue*>(maybe_list);
+ }
+
+ return PopulateOptionalArrayFromList(*list, out);
+}
+
+// Appends a Value newly created from |from| to |out|. These used by template
+// specializations of |Set(Optional)ArrayToList|.
+void AddItemToList(const int from, base::ListValue* out);
+void AddItemToList(const bool from, base::ListValue* out);
+void AddItemToList(const double from, base::ListValue* out);
+void AddItemToList(const std::string& from, base::ListValue* out);
+void AddItemToList(const linked_ptr<base::Value>& from,
+ base::ListValue* out);
+void AddItemToList(const linked_ptr<base::DictionaryValue>& from,
+ base::ListValue* out);
+
+// This template is used for types generated by tools/json_schema_compiler.
+template<class T>
+void AddItemToList(const linked_ptr<T>& from, base::ListValue* out) {
+ out->Append(from->ToValue().release());
+}
+
+// Set |out| to the the contents of |from|. Requires GetItemFromList to be
+// implemented for |T|.
+template <class T>
+void PopulateListFromArray(
+ const std::vector<T>& from,
+ base::ListValue* out) {
+ out->Clear();
+ for (typename std::vector<T>::const_iterator it = from.begin();
+ it != from.end(); ++it) {
+ AddItemToList(*it, out);
+ }
+}
+
+// Set |out| to the the contents of |from| if |from| is non-NULL. Requires
+// GetItemFromList to be implemented for |T|.
+template <class T>
+void PopulateListFromOptionalArray(
+ const scoped_ptr<std::vector<T> >& from,
+ base::ListValue* out) {
+ if (from.get())
+ PopulateListFromArray(*from, out);
+
+}
+
+template <class T>
+scoped_ptr<base::Value> CreateValueFromArray(const std::vector<T>& from) {
+ base::ListValue* list = new base::ListValue();
+ PopulateListFromArray(from, list);
+ return scoped_ptr<base::Value>(list);
+}
+
+template <class T>
+scoped_ptr<base::Value> CreateValueFromOptionalArray(
+ const scoped_ptr<std::vector<T> >& from) {
+ if (from.get())
+ return CreateValueFromArray(*from);
+ return scoped_ptr<base::Value>();
+}
+
+std::string ValueTypeToString(Value::Type type);
+
+} // namespace util
+} // namespace json_schema_compiler
+
+#endif // TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
diff --git a/chromium/tools/json_schema_compiler/util_cc_helper.py b/chromium/tools/json_schema_compiler/util_cc_helper.py
new file mode 100644
index 00000000000..df5b6de0f50
--- /dev/null
+++ b/chromium/tools/json_schema_compiler/util_cc_helper.py
@@ -0,0 +1,85 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+API_UTIL_NAMESPACE = 'json_schema_compiler::util'
+
+class UtilCCHelper(object):
+ """A util class that generates code that uses
+ tools/json_schema_compiler/util.cc.
+ """
+ def __init__(self, type_manager):
+ self._type_manager = type_manager
+
+ def PopulateArrayFromDictionary(self, array_prop, src, name, dst):
+ """Generates code to get an array from a src.name into dst.
+
+ src: DictionaryValue*
+ dst: std::vector or scoped_ptr<std::vector>
+ """
+ prop = array_prop.item_type
+ sub = {
+ 'namespace': API_UTIL_NAMESPACE,
+ 'name': name,
+ 'src': src,
+ 'dst': dst,
+ }
+
+ sub['type'] = self._type_manager.GetCppType(prop),
+ if array_prop.optional:
+ val = ('%(namespace)s::PopulateOptionalArrayFromDictionary'
+ '(*%(src)s, "%(name)s", &%(dst)s)')
+ else:
+ val = ('%(namespace)s::PopulateArrayFromDictionary'
+ '(*%(src)s, "%(name)s", &%(dst)s)')
+
+ return val % sub
+
+ def PopulateArrayFromList(self, array_prop, src, dst, optional):
+ """Generates code to get an array from src into dst.
+
+ src: ListValue*
+ dst: std::vector or scoped_ptr<std::vector>
+ """
+ prop = array_prop.item_type
+ sub = {
+ 'namespace': API_UTIL_NAMESPACE,
+ 'src': src,
+ 'dst': dst,
+ 'type': self._type_manager.GetCppType(prop),
+ }
+
+ if optional:
+ val = '%(namespace)s::PopulateOptionalArrayFromList(*%(src)s, &%(dst)s)'
+ else:
+ val = '%(namespace)s::PopulateArrayFromList(*%(src)s, &%(dst)s)'
+
+ return val % sub
+
+ def CreateValueFromArray(self, array_prop, src, optional):
+ """Generates code to create a scoped_pt<Value> from the array at src.
+
+ src: std::vector or scoped_ptr<std::vector>
+ """
+ prop = array_prop.item_type
+ sub = {
+ 'namespace': API_UTIL_NAMESPACE,
+ 'src': src,
+ 'type': self._type_manager.GetCppType(prop),
+ }
+
+ if optional:
+ val = '%(namespace)s::CreateValueFromOptionalArray(%(src)s)'
+ else:
+ val = '%(namespace)s::CreateValueFromArray(%(src)s)'
+
+ return val % sub
+
+ def GetIncludePath(self):
+ return '#include "tools/json_schema_compiler/util.h"'
+
+ def GetValueTypeString(self, value, is_ptr=False):
+ call = '.GetType()'
+ if is_ptr:
+ call = '->GetType()'
+ return 'json_schema_compiler::util::ValueTypeToString(%s%s)' % (value, call)
diff --git a/chromium/tools/json_to_struct/PRESUBMIT.py b/chromium/tools/json_to_struct/PRESUBMIT.py
new file mode 100644
index 00000000000..dd4d9a46ba9
--- /dev/null
+++ b/chromium/tools/json_to_struct/PRESUBMIT.py
@@ -0,0 +1,20 @@
+# Copyright 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit script for changes affecting tools/json_to_struct/
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into gcl.
+"""
+
+WHITELIST = [ r'.+_test.py$' ]
+
+def CheckChangeOnUpload(input_api, output_api):
+ return input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, '.', whitelist=WHITELIST)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, '.', whitelist=WHITELIST)
diff --git a/chromium/tools/json_to_struct/element_generator.py b/chromium/tools/json_to_struct/element_generator.py
new file mode 100644
index 00000000000..20d3069a1c0
--- /dev/null
+++ b/chromium/tools/json_to_struct/element_generator.py
@@ -0,0 +1,122 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import struct_generator
+
+def _JSONToCString16(json_string_literal):
+ """Converts a JSON string literal to a C++ UTF-16 string literal. This is
+ done by converting \\u#### to \\x####.
+ """
+ c_string_literal = json_string_literal
+ escape_index = c_string_literal.find('\\')
+ while escape_index > 0:
+ if c_string_literal[escape_index + 1] == 'u':
+ # We close the C string literal after the 4 hex digits and reopen it right
+ # after, otherwise the Windows compiler will sometimes try to get more
+ # than 4 characters in the hex string.
+ c_string_literal = (c_string_literal[0:escape_index + 1] + 'x' +
+ c_string_literal[escape_index + 2:escape_index + 6] + '" L"' +
+ c_string_literal[escape_index + 6:])
+ escape_index = c_string_literal.find('\\', escape_index + 6)
+ return c_string_literal
+
+def _GenerateString(content, lines):
+ """Generates an UTF-8 string to be included in a static structure initializer.
+ If content is not specified, uses NULL.
+ """
+ if content is None:
+ lines.append(' NULL,')
+ else:
+ # json.dumps quotes the string and escape characters as required.
+ lines.append(' %s,' % json.dumps(content))
+
+def _GenerateString16(content, lines):
+ """Generates an UTF-16 string to be included in a static structure
+ initializer. If content is not specified, uses NULL.
+ """
+ if content is None:
+ lines.append(' NULL,')
+ else:
+ # json.dumps quotes the string and escape characters as required.
+ lines.append(' L%s,' % _JSONToCString16(json.dumps(content)))
+
+def _GenerateArray(element_name, field_info, content, lines):
+ """Generates an array to be included in a static structure initializer. If
+ content is not specified, uses NULL. The array is assigned to a temporary
+ variable which is initialized before the structure.
+ """
+ if content is None:
+ lines.append(' NULL,')
+ lines.append(' 0,') # Size of the array.
+ return
+
+ # Create a new array variable and use it in the structure initializer.
+ # This prohibits nested arrays. Add a clash detection and renaming mechanism
+ # to solve the problem.
+ var = 'array_%s_%s' % (element_name, field_info['field']);
+ lines.append(' %s,' % var)
+ lines.append(' %s,' % len(content)) # Size of the array.
+ # Generate the array content.
+ array_lines = []
+ field_info['contents']['field'] = var;
+ array_lines.append(struct_generator.GenerateField(
+ field_info['contents']) + '[] = {')
+ for subcontent in content:
+ GenerateFieldContent(element_name, field_info['contents'], subcontent,
+ array_lines)
+ array_lines.append('};')
+ # Prepend the generated array so it is initialized before the structure.
+ lines.reverse()
+ array_lines.reverse()
+ lines.extend(array_lines)
+ lines.reverse()
+
+def GenerateFieldContent(element_name, field_info, content, lines):
+ """Generate the content of a field to be included in the static structure
+ initializer. If the field's content is not specified, uses the default value
+ if one exists.
+ """
+ if content is None:
+ content = field_info.get('default', None)
+ type = field_info['type']
+ if type == 'int' or type == 'enum':
+ lines.append(' %s,' % content)
+ elif type == 'string':
+ _GenerateString(content, lines)
+ elif type == 'string16':
+ _GenerateString16(content, lines)
+ elif type == 'array':
+ _GenerateArray(element_name, field_info, content, lines)
+ else:
+ raise RuntimeError('Unknown field type "%s"' % type)
+
+def GenerateElement(type_name, schema, element_name, element):
+ """Generate the static structure initializer for one element.
+ """
+ lines = [];
+ lines.append('const %s %s = {' % (type_name, element_name));
+ for field_info in schema:
+ content = element.get(field_info['field'], None)
+ if (content == None and not field_info.get('optional', False)):
+ raise RuntimeError('Mandatory field "%s" omitted in element "%s".' %
+ (field_info['field'], element_name))
+ GenerateFieldContent(element_name, field_info, content, lines)
+ lines.append('};')
+ return '\n'.join(lines)
+
+def GenerateElements(type_name, schema, description):
+ """Generate the static structure initializer for all the elements in the
+ description['elements'] dictionary, as well as for any variables in
+ description['int_variables'].
+ """
+ result = [];
+ for var_name, value in description.get('int_variables', {}).items():
+ result.append('const int %s = %s;' % (var_name, value))
+ result.append('')
+
+ for element_name, element in description.get('elements', {}).items():
+ result.append(GenerateElement(type_name, schema, element_name, element))
+ result.append('')
+ return '\n'.join(result)
diff --git a/chromium/tools/json_to_struct/element_generator_test.py b/chromium/tools/json_to_struct/element_generator_test.py
new file mode 100755
index 00000000000..67459a1d871
--- /dev/null
+++ b/chromium/tools/json_to_struct/element_generator_test.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from element_generator import GenerateFieldContent
+from element_generator import GenerateElements
+import unittest
+
+class ElementGeneratorTest(unittest.TestCase):
+ def testGenerateIntFieldContent(self):
+ lines = [];
+ GenerateFieldContent('', {'type': 'int', 'default': 5}, None, lines)
+ self.assertEquals([' 5,'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'int', 'default': 5}, 12, lines)
+ self.assertEquals([' 12,'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'int'}, -3, lines)
+ self.assertEquals([' -3,'], lines)
+
+ def testGenerateStringFieldContent(self):
+ lines = [];
+ GenerateFieldContent('', {'type': 'string', 'default': 'foo_bar'}, None,
+ lines)
+ self.assertEquals([' "foo_bar",'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'string', 'default': 'foo'}, 'bar\n',
+ lines)
+ self.assertEquals([' "bar\\n",'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'string'}, None, lines)
+ self.assertEquals([' NULL,'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'string'}, 'foo', lines)
+ self.assertEquals([' "foo",'], lines)
+
+ def testGenerateString16FieldContent(self):
+ lines = [];
+ GenerateFieldContent('', {'type': 'string16',
+ 'default': u'f\u00d8\u00d81a'}, None, lines)
+ self.assertEquals([' L"f\\x00d8" L"\\x00d8" L"1a",'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'string16', 'default': 'foo'},
+ u'b\uc3a5r', lines)
+ self.assertEquals([' L"b\\xc3a5" L"r",'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'string16'}, None, lines)
+ self.assertEquals([' NULL,'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'string16'}, u'foo\\u1234', lines)
+ self.assertEquals([' L"foo\\\\u1234",'], lines)
+
+ def testGenerateEnumFieldContent(self):
+ lines = [];
+ GenerateFieldContent('', {'type': 'enum', 'default': 'RED'}, None, lines)
+ self.assertEquals([' RED,'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'enum', 'default': 'RED'}, 'BLACK', lines)
+ self.assertEquals([' BLACK,'], lines)
+ lines = [];
+ GenerateFieldContent('', {'type': 'enum'}, 'BLUE', lines)
+ self.assertEquals([' BLUE,'], lines)
+
+ def testGenerateArrayFieldContent(self):
+ lines = ['STRUCT BEGINS'];
+ GenerateFieldContent('test', {'type': 'array', 'contents': {'type': 'int'}},
+ None, lines)
+ self.assertEquals(['STRUCT BEGINS', ' NULL,', ' 0,'], lines)
+ lines = ['STRUCT BEGINS'];
+ GenerateFieldContent('test', {'field': 'my_array', 'type': 'array',
+ 'contents': {'type': 'int'}}, [3, 4], lines)
+ self.assertEquals('const int array_test_my_array[] = {\n' +
+ ' 3,\n' +
+ ' 4,\n' +
+ '};\n' +
+ 'STRUCT BEGINS\n' +
+ ' array_test_my_array,\n' +
+ ' 2,', '\n'.join(lines))
+
+ def testGenerateElements(self):
+ schema = [
+ {'field': 'f0', 'type': 'int', 'default': 1000, 'optional': True},
+ {'field': 'f1', 'type': 'string'},
+ {'field': 'f2', 'type': 'enum', 'ctype': 'QuasiBool', 'default': 'MAYBE',
+ 'optional': True},
+ {'field': 'f3', 'type': 'array', 'contents': {'type': 'string16'},
+ 'optional': True}
+ ]
+ description = {
+ 'int_variables': {'a': -5, 'b': 5},
+ 'elements': {
+ 'elem0': {'f0': 5, 'f1': 'foo', 'f2': 'SURE'},
+ 'elem1': {'f2': 'NOWAY', 'f0': -2, 'f1': 'bar'},
+ 'elem2': {'f1': 'foo_bar', 'f3': [u'bar', u'foo']}
+ }
+ }
+
+ # Build the expected result stream based on the unpredicatble order the
+ # dictionary element are listed in.
+ int_variable_expected = {
+ 'a': 'const int a = -5;\n',
+ 'b': 'const int b = 5;\n',
+ }
+ elements_expected = {
+ 'elem0': 'const MyType elem0 = {\n' +
+ ' 5,\n' +
+ ' "foo",\n' +
+ ' SURE,\n' +
+ ' NULL,\n' +
+ ' 0,\n'
+ '};\n',
+ 'elem1': 'const MyType elem1 = {\n' +
+ ' -2,\n' +
+ ' "bar",\n' +
+ ' NOWAY,\n' +
+ ' NULL,\n' +
+ ' 0,\n'
+ '};\n',
+ 'elem2': 'const wchar_t* const array_elem2_f3[] = {\n' +
+ ' L"bar",\n' +
+ ' L"foo",\n' +
+ '};\n' +
+ 'const MyType elem2 = {\n' +
+ ' 1000,\n' +
+ ' "foo_bar",\n' +
+ ' MAYBE,\n' +
+ ' array_elem2_f3,\n' +
+ ' 2,\n'
+ '};\n'
+ }
+ expected = ''
+ for key, value in description['int_variables'].items():
+ expected += int_variable_expected[key]
+ expected += '\n'
+ elements = []
+ for key, value in description['elements'].items():
+ elements.append(elements_expected[key])
+ expected += '\n'.join(elements)
+
+ result = GenerateElements('MyType', schema, description)
+ self.assertEquals(expected, result)
+
+ def testGenerateElementsMissingMandatoryField(self):
+ schema = [
+ {'field': 'f0', 'type': 'int'},
+ {'field': 'f1', 'type': 'string'},
+ ]
+ description = {
+ 'int_variables': {'a': -5, 'b': 5},
+ 'elements': {
+ 'elem0': {'f0': 5},
+ }
+ }
+
+ self.assertRaises(RuntimeError,
+ lambda: GenerateElements('MyType', schema, description))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/json_to_struct/json_to_struct.py b/chromium/tools/json_to_struct/json_to_struct.py
new file mode 100755
index 00000000000..38b6341091c
--- /dev/null
+++ b/chromium/tools/json_to_struct/json_to_struct.py
@@ -0,0 +1,211 @@
+#!/usr/bin/env python
+# Copyright 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Format for the JSON schema file:
+# {
+# "type_name": "DesiredCStructName",
+# "headers": [ // Optional list of headers to be included by the .h.
+# "path/to/header.h"
+# ],
+# "schema": [ // Fields of the generated structure.
+# {
+# "field": "my_enum_field",
+# "type": "enum", // Either: int, string, string16, enum, array.
+# "default": "RED", // Optional. Cannot be used for array.
+# "ctype": "Color" // Only for enum, specify the C type.
+# },
+# {
+# "field": "my_int_array_field", // my_int_array_field_size will also
+# "type": "array", // be generated.
+# "contents": {
+# "type": "int" // Either: int, string, string16, enum, array.
+# }
+# },
+# ...
+# ]
+# }
+#
+# Format for the JSON description file:
+# {
+# "int_variables": { // An optional list of constant int variables.
+# "kDesiredConstantName": 45
+# },
+# "elements": { // All the elements for which to create static
+# // initialization code in the .cc file.
+# "my_const_variable": {
+# "my_int_field": 10,
+# "my_string_field": "foo bar",
+# "my_enum_field": "BLACK",
+# "my_int_array_field": [ 1, 2, 3, 5, 7 ],
+# },
+# "my_other_const_variable": {
+# ...
+# }
+# }
+# }
+
+import json
+from datetime import datetime
+import os.path
+import sys
+import optparse
+import re
+_script_path = os.path.realpath(__file__)
+
+sys.path.insert(0, os.path.normpath(_script_path + "/../../json_comment_eater"))
+try:
+ import json_comment_eater
+finally:
+ sys.path.pop(0)
+
+import struct_generator
+import element_generator
+
+HEAD = """// Copyright %d The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// GENERATED FROM THE SCHEMA DEFINITION AND DESCRIPTION IN
+// %s
+// %s
+// DO NOT EDIT.
+
+"""
+
+def _GenerateHeaderGuard(h_filename):
+ """Generates the string used in #ifndef guarding the header file.
+ """
+ result = re.sub('[%s\\\\.]' % os.sep, '_', h_filename.upper())
+ return re.sub('^_*', '', result) + '_' # Remove leading underscores.
+
+def _GenerateH(basepath, fileroot, head, namespace, schema, description):
+ """Generates the .h file containing the definition of the structure specified
+ by the schema.
+
+ Args:
+ basepath: The base directory in which files are generated.
+ fileroot: The filename and path, relative to basepath, of the file to
+ create, without an extension.
+ head: The string to output as the header of the .h file.
+ namespace: A string corresponding to the C++ namespace to use.
+ schema: A dict containing the schema. See comment at the top of this file.
+ description: A dict containing the description. See comment at the top of
+ this file.
+ """
+
+ h_filename = fileroot + '.h'
+ with open(os.path.join(basepath, h_filename), 'w') as f:
+ f.write(head)
+
+ f.write('#include <cstddef>\n')
+ f.write('\n')
+
+ header_guard = _GenerateHeaderGuard(h_filename)
+ f.write('#ifndef %s\n' % header_guard)
+ f.write('#define %s\n' % header_guard)
+ f.write('\n')
+
+ for header in schema.get('headers', []):
+ f.write('#include "%s"\n' % header)
+ f.write('\n')
+
+ if namespace:
+ f.write('namespace %s {\n' % namespace)
+ f.write('\n')
+
+ f.write(struct_generator.GenerateStruct(
+ schema['type_name'], schema['schema']))
+ f.write('\n')
+
+ for var_name, value in description.get('int_variables', []).items():
+ f.write('extern const int %s;\n' % var_name)
+ f.write('\n')
+
+ for element_name, element in description['elements'].items():
+ f.write('extern const %s %s;\n' % (schema['type_name'], element_name))
+
+ if namespace:
+ f.write('\n')
+ f.write('} // namespace %s\n' % namespace)
+
+ f.write('\n')
+ f.write( '#endif // %s\n' % header_guard)
+
+def _GenerateCC(basepath, fileroot, head, namespace, schema, description):
+ """Generates the .cc file containing the static initializers for the
+ of the elements specified in the description.
+
+ Args:
+ basepath: The base directory in which files are generated.
+ fileroot: The filename and path, relative to basepath, of the file to
+ create, without an extension.
+ head: The string to output as the header of the .cc file.
+ namespace: A string corresponding to the C++ namespace to use.
+ schema: A dict containing the schema. See comment at the top of this file.
+ description: A dict containing the description. See comment at the top of
+ this file.
+ """
+
+ with open(os.path.join(basepath, fileroot + '.cc'), 'w') as f:
+ f.write(head)
+
+ f.write('#include "%s"\n' % (fileroot + '.h'))
+ f.write('\n')
+
+ if namespace:
+ f.write('namespace %s {\n' % namespace)
+ f.write('\n')
+
+ f.write(element_generator.GenerateElements(schema['type_name'],
+ schema['schema'], description))
+
+ if namespace:
+ f.write('\n')
+ f.write('} // namespace %s\n' % namespace)
+
+def _Load(filename):
+ """Loads a JSON file int a Python object and return this object.
+ """
+ # TODO(beaudoin): When moving to Python 2.7 use object_pairs_hook=OrderedDict.
+ with open(filename, 'r') as handle:
+ result = json.loads(json_comment_eater.Nom(handle.read()))
+ return result
+
+if __name__ == '__main__':
+ parser = optparse.OptionParser(
+ description='Generates an C++ array of struct from a JSON description.',
+ usage='usage: %prog [option] -s schema description')
+ parser.add_option('-b', '--destbase',
+ help='base directory of generated files.')
+ parser.add_option('-d', '--destdir',
+ help='directory to output generated files, relative to destbase.')
+ parser.add_option('-n', '--namespace',
+ help='C++ namespace for generated files. e.g search_providers.')
+ parser.add_option('-s', '--schema', help='path to the schema file, '
+ 'mandatory.')
+ (opts, args) = parser.parse_args()
+
+ if not opts.schema:
+ parser.error('You must specify a --schema.')
+
+ description_filename = os.path.normpath(args[0])
+ root, ext = os.path.splitext(description_filename)
+ shortroot = os.path.split(root)[1]
+ if opts.destdir:
+ output_root = os.path.join(os.path.normpath(opts.destdir), shortroot)
+ else:
+ output_root = shortroot
+
+ if opts.destbase:
+ basepath = os.path.normpath(opts.destbase)
+ else:
+ basepath = ''
+
+ schema = _Load(opts.schema)
+ description = _Load(description_filename)
+
+ head = HEAD % (datetime.now().year, opts.schema, description_filename)
+ _GenerateH(basepath, output_root, head, opts.namespace, schema, description)
+ _GenerateCC(basepath, output_root, head, opts.namespace, schema, description)
diff --git a/chromium/tools/json_to_struct/struct_generator.py b/chromium/tools/json_to_struct/struct_generator.py
new file mode 100644
index 00000000000..501cb577e52
--- /dev/null
+++ b/chromium/tools/json_to_struct/struct_generator.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+def _GenerateArrayField(field_info):
+ """Generate a string defining an array field in a C structure.
+ """
+ contents = field_info['contents']
+ contents['field'] = '* ' + field_info['field']
+ if contents['type'] == 'array':
+ raise RuntimeError('Nested arrays are not supported.')
+ return (GenerateField(contents) + ';\n' +
+ ' const size_t %s_size') % field_info['field'];
+
+def GenerateField(field_info):
+ """Generate a string defining a field of the type specified by
+ field_info['type'] in a C structure.
+ """
+ field = field_info['field']
+ type = field_info['type']
+ if type == 'int':
+ return 'const int %s' % field
+ elif type == 'string':
+ return 'const char* const %s' % field
+ elif type == 'string16':
+ return 'const wchar_t* const %s' % field
+ elif type == 'enum':
+ return 'const %s %s' % (field_info['ctype'], field)
+ elif type == 'array':
+ return _GenerateArrayField(field_info)
+ else:
+ raise RuntimeError('Unknown field type "%s"' % type)
+
+def GenerateStruct(type_name, schema):
+ """Generate a string defining a structure containing the fields specified in
+ the schema list.
+ """
+ lines = [];
+ lines.append('struct %s {' % type_name)
+ for field_info in schema:
+ lines.append(' ' + GenerateField(field_info) + ';')
+ lines.append('};');
+ return '\n'.join(lines) + '\n';
diff --git a/chromium/tools/json_to_struct/struct_generator_test.py b/chromium/tools/json_to_struct/struct_generator_test.py
new file mode 100755
index 00000000000..8566c335bcd
--- /dev/null
+++ b/chromium/tools/json_to_struct/struct_generator_test.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from struct_generator import GenerateField
+from struct_generator import GenerateStruct
+import unittest
+
+class StructGeneratorTest(unittest.TestCase):
+ def testGenerateIntField(self):
+ self.assertEquals('const int foo_bar',
+ GenerateField({'type': 'int', 'field': 'foo_bar'}))
+
+ def testGenerateStringField(self):
+ self.assertEquals('const char* const bar_foo',
+ GenerateField({'type': 'string', 'field': 'bar_foo'}))
+
+ def testGenerateString16Field(self):
+ self.assertEquals('const wchar_t* const foo_bar',
+ GenerateField({'type': 'string16', 'field': 'foo_bar'}))
+
+ def testGenerateEnumField(self):
+ self.assertEquals('const MyEnumType foo_foo',
+ GenerateField({'type': 'enum',
+ 'field': 'foo_foo',
+ 'ctype': 'MyEnumType'}))
+
+ def testGenerateArrayField(self):
+ self.assertEquals('const int * bar_bar;\n'
+ ' const size_t bar_bar_size',
+ GenerateField({'type': 'array',
+ 'field': 'bar_bar',
+ 'contents': {'type': 'int'}}))
+
+ def testGenerateStruct(self):
+ schema = [
+ {'type': 'int', 'field': 'foo_bar'},
+ {'type': 'string', 'field': 'bar_foo', 'default': 'dummy'},
+ {
+ 'type': 'array',
+ 'field': 'bar_bar',
+ 'contents': {
+ 'type': 'enum',
+ 'ctype': 'MyEnumType'
+ }
+ }
+ ]
+ struct = ('struct MyTypeName {\n'
+ ' const int foo_bar;\n'
+ ' const char* const bar_foo;\n'
+ ' const MyEnumType * bar_bar;\n'
+ ' const size_t bar_bar_size;\n'
+ '};\n')
+ self.assertEquals(struct, GenerateStruct('MyTypeName', schema))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/licenses.py b/chromium/tools/licenses.py
new file mode 100755
index 00000000000..d2c535b3fea
--- /dev/null
+++ b/chromium/tools/licenses.py
@@ -0,0 +1,477 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility for checking and processing licensing information in third_party
+directories.
+
+Usage: licenses.py <command>
+
+Commands:
+ scan scan third_party directories, verifying that we have licensing info
+ credits generate about:credits on stdout
+
+(You can also import this as a module.)
+"""
+
+import cgi
+import os
+import sys
+
+# Paths from the root of the tree to directories to skip.
+PRUNE_PATHS = set([
+ # Same module occurs in crypto/third_party/nss and net/third_party/nss, so
+ # skip this one.
+ os.path.join('third_party','nss'),
+
+ # Placeholder directory only, not third-party code.
+ os.path.join('third_party','adobe'),
+
+ # Build files only, not third-party code.
+ os.path.join('third_party','widevine'),
+
+ # Only binaries, used during development.
+ os.path.join('third_party','valgrind'),
+
+ # Used for development and test, not in the shipping product.
+ os.path.join('third_party','bison'),
+ os.path.join('third_party','cygwin'),
+ os.path.join('third_party','gnu_binutils'),
+ os.path.join('third_party','gold'),
+ os.path.join('third_party','gperf'),
+ os.path.join('third_party','lighttpd'),
+ os.path.join('third_party','llvm'),
+ os.path.join('third_party','llvm-build'),
+ os.path.join('third_party','mingw-w64'),
+ os.path.join('third_party','nacl_sdk_binaries'),
+ os.path.join('third_party','pefile'),
+ os.path.join('third_party','perl'),
+ os.path.join('third_party','psyco_win32'),
+ os.path.join('third_party','pylib'),
+ os.path.join('third_party','python_26'),
+ os.path.join('third_party','pywebsocket'),
+ os.path.join('third_party','syzygy'),
+ os.path.join('tools','gn'),
+
+ # Chromium code in third_party.
+ os.path.join('third_party','fuzzymatch'),
+
+ # Stuff pulled in from chrome-internal for official builds/tools.
+ os.path.join('third_party', 'clear_cache'),
+ os.path.join('third_party', 'gnu'),
+ os.path.join('third_party', 'googlemac'),
+ os.path.join('third_party', 'pcre'),
+ os.path.join('third_party', 'psutils'),
+ os.path.join('third_party', 'sawbuck'),
+
+ # Redistribution does not require attribution in documentation.
+ os.path.join('third_party','directxsdk'),
+ os.path.join('third_party','platformsdk_win2008_6_1'),
+ os.path.join('third_party','platformsdk_win7'),
+])
+
+# Directories we don't scan through.
+VCS_METADATA_DIRS = ('.svn', '.git')
+PRUNE_DIRS = (VCS_METADATA_DIRS +
+ ('out', 'Debug', 'Release', # build files
+ 'layout_tests')) # lots of subdirs
+
+ADDITIONAL_PATHS = (
+ os.path.join('breakpad'),
+ os.path.join('chrome', 'common', 'extensions', 'docs', 'examples'),
+ os.path.join('chrome', 'test', 'chromeos', 'autotest'),
+ os.path.join('chrome', 'test', 'data'),
+ os.path.join('native_client'),
+ os.path.join('native_client_sdk'),
+ os.path.join('net', 'tools', 'spdyshark'),
+ os.path.join('ppapi'),
+ os.path.join('sandbox', 'linux', 'seccomp-legacy'),
+ os.path.join('sdch', 'open-vcdiff'),
+ os.path.join('testing', 'gmock'),
+ os.path.join('testing', 'gtest'),
+ # The directory with the word list for Chinese and Japanese segmentation
+ # with different license terms than ICU.
+ os.path.join('third_party','icu','source','data','brkitr'),
+ os.path.join('tools', 'grit'),
+ os.path.join('tools', 'gyp'),
+ os.path.join('tools', 'page_cycler', 'acid3'),
+ os.path.join('url', 'third_party', 'mozilla'),
+ os.path.join('v8'),
+ # Fake directory so we can include the strongtalk license.
+ os.path.join('v8', 'strongtalk'),
+)
+
+
+# Directories where we check out directly from upstream, and therefore
+# can't provide a README.chromium. Please prefer a README.chromium
+# wherever possible.
+SPECIAL_CASES = {
+ os.path.join('native_client'): {
+ "Name": "native client",
+ "URL": "http://code.google.com/p/nativeclient",
+ "License": "BSD",
+ },
+ os.path.join('sandbox', 'linux', 'seccomp-legacy'): {
+ "Name": "seccompsandbox",
+ "URL": "http://code.google.com/p/seccompsandbox",
+ "License": "BSD",
+ },
+ os.path.join('sdch', 'open-vcdiff'): {
+ "Name": "open-vcdiff",
+ "URL": "http://code.google.com/p/open-vcdiff",
+ "License": "Apache 2.0, MIT, GPL v2 and custom licenses",
+ "License Android Compatible": "yes",
+ },
+ os.path.join('testing', 'gmock'): {
+ "Name": "gmock",
+ "URL": "http://code.google.com/p/googlemock",
+ "License": "BSD",
+ "License File": "NOT_SHIPPED",
+ },
+ os.path.join('testing', 'gtest'): {
+ "Name": "gtest",
+ "URL": "http://code.google.com/p/googletest",
+ "License": "BSD",
+ "License File": "NOT_SHIPPED",
+ },
+ os.path.join('third_party', 'angle'): {
+ "Name": "Almost Native Graphics Layer Engine",
+ "URL": "http://code.google.com/p/angleproject/",
+ "License": "BSD",
+ },
+ os.path.join('third_party', 'cros_system_api'): {
+ "Name": "Chromium OS system API",
+ "URL": "http://www.chromium.org/chromium-os",
+ "License": "BSD",
+ # Absolute path here is resolved as relative to the source root.
+ "License File": "/LICENSE.chromium_os",
+ },
+ os.path.join('third_party', 'GTM'): {
+ "Name": "Google Toolbox for Mac",
+ "URL": "http://code.google.com/p/google-toolbox-for-mac/",
+ "License": "Apache 2.0",
+ "License File": "COPYING",
+ },
+ os.path.join('third_party', 'lss'): {
+ "Name": "linux-syscall-support",
+ "URL": "http://code.google.com/p/linux-syscall-support/",
+ "License": "BSD",
+ "License File": "/LICENSE",
+ },
+ os.path.join('third_party', 'ots'): {
+ "Name": "OTS (OpenType Sanitizer)",
+ "URL": "http://code.google.com/p/ots/",
+ "License": "BSD",
+ },
+ os.path.join('third_party', 'pdfsqueeze'): {
+ "Name": "pdfsqueeze",
+ "URL": "http://code.google.com/p/pdfsqueeze/",
+ "License": "Apache 2.0",
+ "License File": "COPYING",
+ },
+ os.path.join('third_party', 'ppapi'): {
+ "Name": "ppapi",
+ "URL": "http://code.google.com/p/ppapi/",
+ },
+ os.path.join('third_party', 'scons-2.0.1'): {
+ "Name": "scons-2.0.1",
+ "URL": "http://www.scons.org",
+ "License": "MIT",
+ "License File": "NOT_SHIPPED",
+ },
+ os.path.join('third_party', 'trace-viewer'): {
+ "Name": "trace-viewer",
+ "URL": "http://code.google.com/p/trace-viewer",
+ "License": "BSD",
+ "License File": "NOT_SHIPPED",
+ },
+ os.path.join('third_party', 'v8-i18n'): {
+ "Name": "Internationalization Library for v8",
+ "URL": "http://code.google.com/p/v8-i18n/",
+ "License": "Apache 2.0",
+ },
+ os.path.join('third_party', 'WebKit'): {
+ "Name": "WebKit",
+ "URL": "http://webkit.org/",
+ "License": "BSD and GPL v2",
+ # Absolute path here is resolved as relative to the source root.
+ "License File": "/webkit/LICENSE",
+ },
+ os.path.join('third_party', 'webpagereplay'): {
+ "Name": "webpagereplay",
+ "URL": "http://code.google.com/p/web-page-replay",
+ "License": "Apache 2.0",
+ "License File": "NOT_SHIPPED",
+ },
+ os.path.join('tools', 'grit'): {
+ "Name": "grit",
+ "URL": "http://code.google.com/p/grit-i18n",
+ "License": "BSD",
+ "License File": "NOT_SHIPPED",
+ },
+ os.path.join('tools', 'gyp'): {
+ "Name": "gyp",
+ "URL": "http://code.google.com/p/gyp",
+ "License": "BSD",
+ "License File": "NOT_SHIPPED",
+ },
+ os.path.join('v8'): {
+ "Name": "V8 JavaScript Engine",
+ "URL": "http://code.google.com/p/v8",
+ "License": "BSD",
+ },
+ os.path.join('v8', 'strongtalk'): {
+ "Name": "Strongtalk",
+ "URL": "http://www.strongtalk.org/",
+ "License": "BSD",
+ # Absolute path here is resolved as relative to the source root.
+ "License File": "/v8/LICENSE.strongtalk",
+ },
+}
+
+# Special value for 'License File' field used to indicate that the license file
+# should not be used in about:credits.
+NOT_SHIPPED = "NOT_SHIPPED"
+
+
+class LicenseError(Exception):
+ """We raise this exception when a directory's licensing info isn't
+ fully filled out."""
+ pass
+
+def AbsolutePath(path, filename, root):
+ """Convert a path in README.chromium to be absolute based on the source
+ root."""
+ if filename.startswith('/'):
+ # Absolute-looking paths are relative to the source root
+ # (which is the directory we're run from).
+ absolute_path = os.path.join(root, filename[1:])
+ else:
+ absolute_path = os.path.join(root, path, filename)
+ if os.path.exists(absolute_path):
+ return absolute_path
+ return None
+
+def ParseDir(path, root, require_license_file=True):
+ """Examine a third_party/foo component and extract its metadata."""
+
+ # Parse metadata fields out of README.chromium.
+ # We examine "LICENSE" for the license file by default.
+ metadata = {
+ "License File": "LICENSE", # Relative path to license text.
+ "Name": None, # Short name (for header on about:credits).
+ "URL": None, # Project home page.
+ "License": None, # Software license.
+ }
+
+ # Relative path to a file containing some html we're required to place in
+ # about:credits.
+ optional_keys = ["Required Text", "License Android Compatible"]
+
+ if path in SPECIAL_CASES:
+ metadata.update(SPECIAL_CASES[path])
+ else:
+ # Try to find README.chromium.
+ readme_path = os.path.join(root, path, 'README.chromium')
+ if not os.path.exists(readme_path):
+ raise LicenseError("missing README.chromium or licenses.py "
+ "SPECIAL_CASES entry")
+
+ for line in open(readme_path):
+ line = line.strip()
+ if not line:
+ break
+ for key in metadata.keys() + optional_keys:
+ field = key + ": "
+ if line.startswith(field):
+ metadata[key] = line[len(field):]
+
+ # Check that all expected metadata is present.
+ for key, value in metadata.iteritems():
+ if not value:
+ raise LicenseError("couldn't find '" + key + "' line "
+ "in README.chromium or licences.py "
+ "SPECIAL_CASES")
+
+ # Special-case modules that aren't in the shipping product, so don't need
+ # their license in about:credits.
+ if metadata["License File"] != NOT_SHIPPED:
+ # Check that the license file exists.
+ for filename in (metadata["License File"], "COPYING"):
+ license_path = AbsolutePath(path, filename, root)
+ if license_path is not None:
+ break
+
+ if require_license_file and not license_path:
+ raise LicenseError("License file not found. "
+ "Either add a file named LICENSE, "
+ "import upstream's COPYING if available, "
+ "or add a 'License File:' line to "
+ "README.chromium with the appropriate path.")
+ metadata["License File"] = license_path
+
+ if "Required Text" in metadata:
+ required_path = AbsolutePath(path, metadata["Required Text"], root)
+ if required_path is not None:
+ metadata["Required Text"] = required_path
+ else:
+ raise LicenseError("Required text file listed but not found.")
+
+ return metadata
+
+
+def ContainsFiles(path, root):
+ """Determines whether any files exist in a directory or in any of its
+ subdirectories."""
+ for _, dirs, files in os.walk(os.path.join(root, path)):
+ if files:
+ return True
+ for vcs_metadata in VCS_METADATA_DIRS:
+ if vcs_metadata in dirs:
+ dirs.remove(vcs_metadata)
+ return False
+
+
+def FilterDirsWithFiles(dirs_list, root):
+ # If a directory contains no files, assume it's a DEPS directory for a
+ # project not used by our current configuration and skip it.
+ return [x for x in dirs_list if ContainsFiles(x, root)]
+
+
+def FindThirdPartyDirs(prune_paths, root):
+ """Find all third_party directories underneath the source root."""
+ third_party_dirs = []
+ for path, dirs, files in os.walk(root):
+ path = path[len(root)+1:] # Pretty up the path.
+
+ if path in prune_paths:
+ dirs[:] = []
+ continue
+
+ # Prune out directories we want to skip.
+ # (Note that we loop over PRUNE_DIRS so we're not iterating over a
+ # list that we're simultaneously mutating.)
+ for skip in PRUNE_DIRS:
+ if skip in dirs:
+ dirs.remove(skip)
+
+ if os.path.basename(path) == 'third_party':
+ # Add all subdirectories that are not marked for skipping.
+ for dir in dirs:
+ dirpath = os.path.join(path, dir)
+ if dirpath not in prune_paths:
+ third_party_dirs.append(dirpath)
+
+ # Don't recurse into any subdirs from here.
+ dirs[:] = []
+ continue
+
+ # Don't recurse into paths in ADDITIONAL_PATHS, like we do with regular
+ # third_party/foo paths.
+ if path in ADDITIONAL_PATHS:
+ dirs[:] = []
+
+ for dir in ADDITIONAL_PATHS:
+ if dir not in prune_paths:
+ third_party_dirs.append(dir)
+
+ return third_party_dirs
+
+
+def ScanThirdPartyDirs(root=None):
+ """Scan a list of directories and report on any problems we find."""
+ if root is None:
+ root = os.getcwd()
+ third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, root)
+ third_party_dirs = FilterDirsWithFiles(third_party_dirs, root)
+
+ errors = []
+ for path in sorted(third_party_dirs):
+ try:
+ metadata = ParseDir(path, root)
+ except LicenseError, e:
+ errors.append((path, e.args[0]))
+ continue
+
+ for path, error in sorted(errors):
+ print path + ": " + error
+
+ return len(errors) == 0
+
+
+def GenerateCredits():
+ """Generate about:credits."""
+
+ if len(sys.argv) not in (2, 3):
+ print 'usage: licenses.py credits [output_file]'
+ return False
+
+ def EvaluateTemplate(template, env, escape=True):
+ """Expand a template with variables like {{foo}} using a
+ dictionary of expansions."""
+ for key, val in env.items():
+ if escape and not key.endswith("_unescaped"):
+ val = cgi.escape(val)
+ template = template.replace('{{%s}}' % key, val)
+ return template
+
+ root = os.path.join(os.path.dirname(__file__), '..')
+ third_party_dirs = FindThirdPartyDirs(PRUNE_PATHS, root)
+
+ entry_template = open(os.path.join(root, 'chrome', 'browser', 'resources',
+ 'about_credits_entry.tmpl'), 'rb').read()
+ entries = []
+ for path in sorted(third_party_dirs):
+ try:
+ metadata = ParseDir(path, root)
+ except LicenseError:
+ # TODO(phajdan.jr): Convert to fatal error (http://crbug.com/39240).
+ continue
+ if metadata['License File'] == NOT_SHIPPED:
+ continue
+ env = {
+ 'name': metadata['Name'],
+ 'url': metadata['URL'],
+ 'license': open(metadata['License File'], 'rb').read(),
+ 'license_unescaped': '',
+ }
+ if 'Required Text' in metadata:
+ required_text = open(metadata['Required Text'], 'rb').read()
+ env["license_unescaped"] = required_text
+ entries.append(EvaluateTemplate(entry_template, env))
+
+ file_template = open(os.path.join(root, 'chrome', 'browser', 'resources',
+ 'about_credits.tmpl'), 'rb').read()
+ template_contents = "<!-- Generated by licenses.py; do not edit. -->"
+ template_contents += EvaluateTemplate(file_template,
+ {'entries': '\n'.join(entries)},
+ escape=False)
+
+ if len(sys.argv) == 3:
+ with open(sys.argv[2], 'w') as output_file:
+ output_file.write(template_contents)
+ elif len(sys.argv) == 2:
+ print template_contents
+
+ return True
+
+
+def main():
+ command = 'help'
+ if len(sys.argv) > 1:
+ command = sys.argv[1]
+
+ if command == 'scan':
+ if not ScanThirdPartyDirs():
+ return 1
+ elif command == 'credits':
+ if not GenerateCredits():
+ return 1
+ else:
+ print __doc__
+ return 1
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/linux/dump-static-initializers.py b/chromium/tools/linux/dump-static-initializers.py
new file mode 100755
index 00000000000..865559b9320
--- /dev/null
+++ b/chromium/tools/linux/dump-static-initializers.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Dump functions called by static intializers in a Linux Release binary.
+
+Usage example:
+ tools/linux/dump-static-intializers.py out/Release/chrome
+
+A brief overview of static initialization:
+1) the compiler writes out, per object file, a function that contains
+ the static intializers for that file.
+2) the compiler also writes out a pointer to that function in a special
+ section.
+3) at link time, the linker concatenates the function pointer sections
+ into a single list of all initializers.
+4) at run time, on startup the binary runs all function pointers.
+
+The functions in (1) all have mangled names of the form
+ _GLOBAL__I_foobar.cc
+using objdump, we can disassemble those functions and dump all symbols that
+they reference.
+"""
+
+import optparse
+import re
+import subprocess
+import sys
+
+# A map of symbol => informative text about it.
+NOTES = {
+ '__cxa_atexit@plt': 'registers a dtor to run at exit',
+ 'std::__ioinit': '#includes <iostream>, use <ostream> instead',
+}
+
+# Determine whether this is a git checkout (as opposed to e.g. svn).
+IS_GIT_WORKSPACE = (subprocess.Popen(
+ ['git', 'rev-parse'], stderr=subprocess.PIPE).wait() == 0)
+
+class Demangler(object):
+ """A wrapper around c++filt to provide a function to demangle symbols."""
+ def __init__(self):
+ self.cppfilt = subprocess.Popen(['c++filt'],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+
+ def Demangle(self, sym):
+ """Given mangled symbol |sym|, return its demangled form."""
+ self.cppfilt.stdin.write(sym + '\n')
+ return self.cppfilt.stdout.readline().strip()
+
+# Matches for example: "cert_logger.pb.cc", capturing "cert_logger".
+protobuf_filename_re = re.compile(r'(.*)\.pb\.cc$')
+def QualifyFilenameAsProto(filename):
+ """Attempt to qualify a bare |filename| with a src-relative path, assuming it
+ is a protoc-generated file. If a single match is found, it is returned.
+ Otherwise the original filename is returned."""
+ if not IS_GIT_WORKSPACE:
+ return filename
+ match = protobuf_filename_re.match(filename)
+ if not match:
+ return filename
+ basename = match.groups(0)
+ gitlsfiles = subprocess.Popen(
+ ['git', 'ls-files', '--', '*/%s.proto' % basename],
+ stdout=subprocess.PIPE)
+ candidate = filename
+ for line in gitlsfiles.stdout:
+ if candidate != filename:
+ return filename # Multiple hits, can't help.
+ candidate = line.strip()
+ return candidate
+
+# Regex matching the substring of a symbol's demangled text representation most
+# likely to appear in a source file.
+# Example: "v8::internal::Builtins::InitBuiltinFunctionTable()" becomes
+# "InitBuiltinFunctionTable", since the first (optional & non-capturing) group
+# picks up any ::-qualification and the last fragment picks up a suffix that
+# starts with an opener.
+symbol_code_name_re = re.compile(r'^(?:[^(<[]*::)?([^:(<[]*).*?$')
+def QualifyFilename(filename, symbol):
+ """Given a bare filename and a symbol that occurs in it, attempt to qualify
+ it with a src-relative path. If more than one file matches, return the
+ original filename."""
+ if not IS_GIT_WORKSPACE:
+ return filename
+ match = symbol_code_name_re.match(symbol)
+ if not match:
+ return filename
+ symbol = match.group(1)
+ gitgrep = subprocess.Popen(
+ ['git', 'grep', '-l', symbol, '--', '*/%s' % filename],
+ stdout=subprocess.PIPE)
+ candidate = filename
+ for line in gitgrep.stdout:
+ if candidate != filename: # More than one candidate; return bare filename.
+ return filename
+ candidate = line.strip()
+ return candidate
+
+# Regex matching nm output for the symbols we're interested in.
+# See test_ParseNmLine for examples.
+nm_re = re.compile(r'(\S+) (\S+) t (?:_ZN12)?_GLOBAL__(?:sub_)?I_(.*)')
+def ParseNmLine(line):
+ """Given a line of nm output, parse static initializers as a
+ (file, start, size) tuple."""
+ match = nm_re.match(line)
+ if match:
+ addr, size, filename = match.groups()
+ return (filename, int(addr, 16), int(size, 16))
+
+
+def test_ParseNmLine():
+ """Verify the nm_re regex matches some sample lines."""
+ parse = ParseNmLine(
+ '0000000001919920 0000000000000008 t '
+ '_ZN12_GLOBAL__I_safe_browsing_service.cc')
+ assert parse == ('safe_browsing_service.cc', 26319136, 8), parse
+
+ parse = ParseNmLine(
+ '00000000026b9eb0 0000000000000024 t '
+ '_GLOBAL__sub_I_extension_specifics.pb.cc')
+ assert parse == ('extension_specifics.pb.cc', 40607408, 36), parse
+
+# Just always run the test; it is fast enough.
+test_ParseNmLine()
+
+
+def ParseNm(binary):
+ """Given a binary, yield static initializers as (file, start, size) tuples."""
+ nm = subprocess.Popen(['nm', '-S', binary], stdout=subprocess.PIPE)
+ for line in nm.stdout:
+ parse = ParseNmLine(line)
+ if parse:
+ yield parse
+
+# Regex matching objdump output for the symbols we're interested in.
+# Example line:
+# 12354ab: (disassembly, including <FunctionReference>)
+disassembly_re = re.compile(r'^\s+[0-9a-f]+:.*<(\S+)>')
+def ExtractSymbolReferences(binary, start, end):
+ """Given a span of addresses, returns symbol references from disassembly."""
+ cmd = ['objdump', binary, '--disassemble',
+ '--start-address=0x%x' % start, '--stop-address=0x%x' % end]
+ objdump = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+
+ refs = set()
+ for line in objdump.stdout:
+ if '__static_initialization_and_destruction' in line:
+ raise RuntimeError, ('code mentions '
+ '__static_initialization_and_destruction; '
+ 'did you accidentally run this on a Debug binary?')
+ match = disassembly_re.search(line)
+ if match:
+ (ref,) = match.groups()
+ if ref.startswith('.LC') or ref.startswith('_DYNAMIC'):
+ # Ignore these, they are uninformative.
+ continue
+ if ref.startswith('_GLOBAL__I_'):
+ # Probably a relative jump within this function.
+ continue
+ refs.add(ref)
+
+ return sorted(refs)
+
+def main():
+ parser = optparse.OptionParser(usage='%prog [option] filename')
+ parser.add_option('-d', '--diffable', dest='diffable',
+ action='store_true', default=False,
+ help='Prints the filename on each line, for more easily '
+ 'diff-able output. (Used by sizes.py)')
+ opts, args = parser.parse_args()
+ if len(args) != 1:
+ parser.error('missing filename argument')
+ return 1
+ binary = args[0]
+
+ demangler = Demangler()
+ file_count = 0
+ initializer_count = 0
+
+ files = ParseNm(binary)
+ if opts.diffable:
+ files = sorted(files)
+ for filename, addr, size in files:
+ file_count += 1
+ ref_output = []
+
+ qualified_filename = QualifyFilenameAsProto(filename)
+
+ if size == 2:
+ # gcc generates a two-byte 'repz retq' initializer when there is a
+ # ctor even when the ctor is empty. This is fixed in gcc 4.6, but
+ # Android uses gcc 4.4.
+ ref_output.append('[empty ctor, but it still has cost on gcc <4.6]')
+ else:
+ for ref in ExtractSymbolReferences(binary, addr, addr+size):
+ initializer_count += 1
+
+ ref = demangler.Demangle(ref)
+ if qualified_filename == filename:
+ qualified_filename = QualifyFilename(filename, ref)
+
+ note = ''
+ if ref in NOTES:
+ note = NOTES[ref]
+ elif ref.endswith('_2eproto()'):
+ note = 'protocol compiler bug: crbug.com/105626'
+
+ if note:
+ ref_output.append('%s [%s]' % (ref, note))
+ else:
+ ref_output.append(ref)
+
+ if opts.diffable:
+ print '\n'.join('# ' + qualified_filename + ' ' + r for r in ref_output)
+ else:
+ print '%s (initializer offset 0x%x size 0x%x)' % (qualified_filename,
+ addr, size)
+ print ''.join(' %s\n' % r for r in ref_output)
+
+ if opts.diffable:
+ print '#',
+ print 'Found %d static initializers in %d files.' % (initializer_count,
+ file_count)
+
+ return 0
+
+if '__main__' == __name__:
+ sys.exit(main())
diff --git a/chromium/tools/lsan/suppressions.txt b/chromium/tools/lsan/suppressions.txt
new file mode 100644
index 00000000000..f2dbbc5d56e
--- /dev/null
+++ b/chromium/tools/lsan/suppressions.txt
@@ -0,0 +1,51 @@
+# HeapCheck sanity test
+leak:base::ToolsSanityTest_MemoryLeak_Test::TestBody
+
+# False positives in libfontconfig. http://crbug.com/39050
+leak:libfontconfig
+
+# Intentionally leaked "static" strings in Blink. http://crbug.com/268258
+leak:WTF::StringImpl::createStatic
+
+# V8 leak, expect 1024 bytes leaked per process. http://crbug.com/99304
+leak:v8::internal::V8::Initialize
+
+# V8 GC issues in ProxyResolver tests, probably harmless. http://crbug.com/67378
+leak:net::ProxyResolverV8::SetPacScript
+leak:net::(anonymous namespace)::ProxyResolverV8WithMockBindings::SetPacScriptFromDisk
+leak:net::(anonymous namespace)::InitResolver
+leak:net::ProxyResolverScriptData::FromUTF8
+
+# http://crbug.com/270180
+leak:net::ProxyResolverV8::Context::ResolveProxy
+
+# NSS leaks in CertDatabaseNSSTest tests. http://crbug.com/51988
+leak:net::NSSCertDatabase::ImportFromPKCS12
+leak:net::NSSCertDatabase::ListCerts
+leak:net::NSSCertDatabase::DeleteCertAndKey
+leak:crypto::ScopedTestNSSDB::ScopedTestNSSDB
+# The suppressions above will not fire when the fast stack unwinder is used,
+# because it can't unwind through NSS libraries. Apply blanket supressions for now.
+leak:libnssutil3
+leak:libnspr4
+leak:libnss3
+leak:libplds4
+
+# Skia leaks. http://crbug.com/189170
+leak:FontConfigTypeface::LegacyCreateTypeface
+
+# Skia leaks GrGpuGL::ProgramCache::Entry. http://crbug.com/262934
+leak:GrGpuGL::flushGraphicsState
+
+# Small test-only leak in ppapi_unittests. http://crbug.com/258113
+leak:ppapi::proxy::PPP_Instance_Private_ProxyTest_PPPInstancePrivate_Test
+
+# Leak in base_unittests. http://crbug.com/268267
+leak:base::WeakPtrTest_MoveOwnershipAfterInvalidate_Test::TestBody
+
+# GTK leaks. GTK is deprecated, so we won't be fixing these.
+# Most of them should apply to the full browser process only.
+leak:StatusIconGtk::UpdatePlatformContextMenu
+leak:GlobalMenuBar::GlobalMenuBar
+leak:BookmarkBubbleGtk::InitFolderComboModel
+leak:TranslateInfoBarBase::CreateLanguageCombobox
diff --git a/chromium/tools/mac/symbolicate_crash.py b/chromium/tools/mac/symbolicate_crash.py
new file mode 100755
index 00000000000..731cc85f8dc
--- /dev/null
+++ b/chromium/tools/mac/symbolicate_crash.py
@@ -0,0 +1,504 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This script can take an Apple-style CrashReporter log and symbolicate it. This
+is useful for when a user's reports aren't being uploaded, for example.
+
+Only versions 6, 7, 8, and 9 reports are supported. For more information on the
+file format, reference this document:
+ TN2123 <http://developer.apple.com/library/mac/#technotes/tn2004/tn2123.html>
+
+Information on symbolication was gleaned from:
+ <http://developer.apple.com/tools/xcode/symbolizingcrashdumps.html>
+"""
+
+import optparse
+import os.path
+import re
+import subprocess
+import sys
+
+# Maps binary image identifiers to binary names (minus the .dSYM portion) found
+# in the archive. These are the only objects that will be looked up.
+SYMBOL_IMAGE_MAP = {
+ 'com.google.Chrome': 'Google Chrome.app',
+ 'com.google.Chrome.framework': 'Google Chrome Framework.framework',
+ 'com.google.Chrome.helper': 'Google Chrome Helper.app'
+}
+
+class CrashReport(object):
+ """A parsed representation of an Apple CrashReport text file."""
+ def __init__(self, file_name):
+ super(CrashReport, self).__init__()
+ self.report_info = {}
+ self.threads = []
+ self._binary_images = {}
+
+ fd = open(file_name, 'r')
+ self._ParseHeader(fd)
+
+ # Try and get the report version. If it's not a version we handle, abort.
+ self.report_version = int(self.report_info['Report Version'])
+ # Version 6: 10.5 and 10.6 crash report
+ # Version 7: 10.6 spindump report
+ # Version 8: 10.7 spindump report
+ # Version 9: 10.7 crash report
+ valid_versions = (6, 7, 8, 9)
+ if self.report_version not in valid_versions:
+ raise Exception("Only crash reports of versions %s are accepted." %
+ str(valid_versions))
+
+ # If this is a spindump (version 7 or 8 report), use a special parser. The
+ # format is undocumented, but is similar to version 6. However, the spindump
+ # report contains user and kernel stacks for every process on the system.
+ if self.report_version == 7 or self.report_version == 8:
+ self._ParseSpindumpStack(fd)
+ else:
+ self._ParseStack(fd)
+
+ self._ParseBinaryImages(fd)
+ fd.close()
+
+ def Symbolicate(self, symbol_path):
+ """Symbolicates a crash report stack trace."""
+ # In order to be efficient, collect all the offsets that will be passed to
+ # atos by the image name.
+ offsets_by_image = self._CollectAddressesForImages(SYMBOL_IMAGE_MAP.keys())
+
+ # For each image, run atos with the list of addresses.
+ for image_name, addresses in offsets_by_image.items():
+ # If this image was not loaded or is in no stacks, skip.
+ if image_name not in self._binary_images or not len(addresses):
+ continue
+
+ # Combine the |image_name| and |symbol_path| into the path of the dSYM.
+ dsym_file = self._GetDSymPath(symbol_path, image_name)
+
+ # From the list of 2-Tuples of (frame, address), create a list of just
+ # addresses.
+ address_list = map(lambda x: x[1], addresses)
+
+ # Look up the load address of the image.
+ binary_base = self._binary_images[image_name][0]
+
+ # This returns a list of just symbols. The indices will match up with the
+ # list of |addresses|.
+ symbol_names = self._RunAtos(binary_base, dsym_file, address_list)
+ if not symbol_names:
+ print 'Error loading symbols for ' + image_name
+ continue
+
+ # Attaches a list of symbol names to stack frames. This assumes that the
+ # order of |addresses| has stayed the same as |symbol_names|.
+ self._AddSymbolsToFrames(symbol_names, addresses)
+
+ def _ParseHeader(self, fd):
+ """Parses the header section of a crash report, which contains the OS and
+ application version information."""
+ # The header is made up of different sections, depending on the type of
+ # report and the report version. Almost all have a format of a key and
+ # value separated by a colon. Accumulate all of these artifacts into a
+ # dictionary until the first thread stack is reached.
+ thread_re = re.compile('^[ \t]*Thread ([a-f0-9]+)')
+ line = ''
+ while not thread_re.match(line):
+ # Skip blank lines. There are typically three or four sections separated
+ # by newlines in the header.
+ line = line.strip()
+ if line:
+ parts = line.split(':', 1)
+ # Certain lines in different report versions don't follow the key-value
+ # format, so skip them.
+ if len(parts) == 2:
+ # There's a varying amount of space padding after the ':' to align all
+ # the values; strip that.
+ self.report_info[parts[0]] = parts[1].lstrip()
+ line = fd.readline()
+
+ # When this loop exits, the header has been read in full. However, the first
+ # thread stack heading has been read past. Seek backwards from the current
+ # position by the length of the line so that it is re-read when
+ # _ParseStack() is entered.
+ fd.seek(-len(line), os.SEEK_CUR)
+
+ def _ParseStack(self, fd):
+ """Parses the stack dump of a crash report and creates a list of threads
+ and their stack traces."""
+ # Compile a regex that matches the start of a thread stack. Note that this
+ # must be specific to not include the thread state section, which comes
+ # right after all the stack traces.
+ line_re = re.compile('^Thread ([0-9]+)( Crashed)?:(.*)')
+
+ # On entry into this function, the fd has been walked up to the "Thread 0"
+ # line.
+ line = fd.readline().rstrip()
+ in_stack = False
+ thread = None
+ while line_re.match(line) or in_stack:
+ # Check for start of the thread stack.
+ matches = line_re.match(line)
+
+ if not line.strip():
+ # A blank line indicates a break in the thread stack.
+ in_stack = False
+ elif matches:
+ # If this is the start of a thread stack, create the CrashThread.
+ in_stack = True
+ thread = CrashThread(matches.group(1))
+ thread.name = matches.group(3)
+ thread.did_crash = matches.group(2) != None
+ self.threads.append(thread)
+ else:
+ # All other lines are stack frames.
+ thread.stack.append(self._ParseStackFrame(line))
+ # Read the next line.
+ line = fd.readline()
+
+ def _ParseStackFrame(self, line):
+ """Takes in a single line of text and transforms it into a StackFrame."""
+ frame = StackFrame(line)
+
+ # A stack frame is in the format of:
+ # |<frame-number> <binary-image> 0x<address> <symbol> <offset>|.
+ regex = '^([0-9]+) +(.+)[ \t]+(0x[0-9a-f]+) (.*) \+ ([0-9]+)$'
+ matches = re.match(regex, line)
+ if matches is None:
+ return frame
+
+ # Create a stack frame with the information extracted from the regex.
+ frame.frame_id = matches.group(1)
+ frame.image = matches.group(2)
+ frame.address = int(matches.group(3), 0) # Convert HEX to an int.
+ frame.original_symbol = matches.group(4)
+ frame.offset = matches.group(5)
+ frame.line = None
+ return frame
+
+ def _ParseSpindumpStack(self, fd):
+ """Parses a spindump stack report. In this format, each thread stack has
+ both a user and kernel trace. Only the user traces are symbolicated."""
+
+ # The stack trace begins with the thread header, which is identified by a
+ # HEX number. The thread names appear to be incorrect in spindumps.
+ user_thread_re = re.compile('^ Thread ([0-9a-fx]+)')
+
+ # When this method is called, the fd has been walked right up to the first
+ # line.
+ line = fd.readline()
+ in_user_stack = False
+ in_kernel_stack = False
+ thread = None
+ frame_id = 0
+ while user_thread_re.match(line) or in_user_stack or in_kernel_stack:
+ # Check for the start of a thread.
+ matches = user_thread_re.match(line)
+
+ if not line.strip():
+ # A blank line indicates the start of a new thread. The blank line comes
+ # after the kernel stack before a new thread header.
+ in_kernel_stack = False
+ elif matches:
+ # This is the start of a thread header. The next line is the heading for
+ # the user stack, followed by the actual trace.
+ thread = CrashThread(matches.group(1))
+ frame_id = 0
+ self.threads.append(thread)
+ in_user_stack = True
+ line = fd.readline() # Read past the 'User stack:' header.
+ elif line.startswith(' Kernel stack:'):
+ # The kernel stack header comes immediately after the last frame (really
+ # the top frame) in the user stack, without a blank line.
+ in_user_stack = False
+ in_kernel_stack = True
+ elif in_user_stack:
+ # If this is a line while in the user stack, parse it as a stack frame.
+ thread.stack.append(self._ParseSpindumpStackFrame(line))
+ # Loop with the next line.
+ line = fd.readline()
+
+ # When the loop exits, the file has been read through the 'Binary images:'
+ # header. Seek backwards so that _ParseBinaryImages() does the right thing.
+ fd.seek(-len(line), os.SEEK_CUR)
+
+ def _ParseSpindumpStackFrame(self, line):
+ """Parses a spindump-style stackframe."""
+ frame = StackFrame(line)
+
+ # The format of the frame is either:
+ # A: |<space><steps> <symbol> + <offset> (in <image-name>) [<address>]|
+ # B: |<space><steps> ??? (in <image-name> + <offset>) [<address>]|
+ regex_a = '^([ ]+[0-9]+) (.*) \+ ([0-9]+) \(in (.*)\) \[(0x[0-9a-f]+)\]'
+ regex_b = '^([ ]+[0-9]+) \?\?\?( \(in (.*) \+ ([0-9]+)\))? \[(0x[0-9a-f]+)\]'
+
+ # Create the stack frame with the information extracted from the regex.
+ matches = re.match(regex_a, line)
+ if matches:
+ frame.frame_id = matches.group(1)[4:] # Remove some leading spaces.
+ frame.original_symbol = matches.group(2)
+ frame.offset = matches.group(3)
+ frame.image = matches.group(4)
+ frame.address = int(matches.group(5), 0)
+ frame.line = None
+ return frame
+
+ # If pattern A didn't match (which it will most of the time), try B.
+ matches = re.match(regex_b, line)
+ if matches:
+ frame.frame_id = matches.group(1)[4:] # Remove some leading spaces.
+ frame.image = matches.group(3)
+ frame.offset = matches.group(4)
+ frame.address = int(matches.group(5), 0)
+ frame.line = None
+ return frame
+
+ # Otherwise, this frame could not be matched and just use the raw input.
+ frame.line = frame.line.strip()
+ return frame
+
+ def _ParseBinaryImages(self, fd):
+ """Parses out the binary images section in order to get the load offset."""
+ # The parser skips some sections, so advance until the "Binary Images"
+ # header is reached.
+ while not fd.readline().lstrip().startswith("Binary Images:"): pass
+
+ # Create a regex to match the lines of format:
+ # |0x<start> - 0x<end> <binary-image> <version> (<version>) <<UUID>> <path>|
+ image_re = re.compile(
+ '[ ]*(0x[0-9a-f]+) -[ \t]+(0x[0-9a-f]+) [+ ]([a-zA-Z0-9._\-]+)')
+
+ # This section is in this format:
+ # |<start address> - <end address> <image name>|.
+ while True:
+ line = fd.readline()
+ if not line.strip():
+ # End when a blank line is hit.
+ return
+ # Match the line to the regex.
+ match = image_re.match(line)
+ if match:
+ # Store the offsets by image name so it can be referenced during
+ # symbolication. These are hex numbers with leading '0x', so int() can
+ # convert them to decimal if base=0.
+ address_range = (int(match.group(1), 0), int(match.group(2), 0))
+ self._binary_images[match.group(3)] = address_range
+
+ def _CollectAddressesForImages(self, images):
+ """Iterates all the threads and stack frames and all the stack frames that
+ are in a list of binary |images|. The result is a dictionary, keyed by the
+ image name that maps to a list of tuples. Each is a 2-Tuple of
+ (stack_frame, address)"""
+ # Create the collection and initialize it with empty lists for each image.
+ collection = {}
+ for image in images:
+ collection[image] = []
+
+ # Perform the iteration.
+ for thread in self.threads:
+ for frame in thread.stack:
+ image_name = self._ImageForAddress(frame.address)
+ if image_name in images:
+ # Replace the image name in the frame in case it was elided.
+ frame.image = image_name
+ collection[frame.image].append((frame, frame.address))
+
+ # Return the result.
+ return collection
+
+ def _ImageForAddress(self, address):
+ """Given a PC address, returns the bundle identifier of the image in which
+ the address resides."""
+ for image_name, address_range in self._binary_images.items():
+ if address >= address_range[0] and address <= address_range[1]:
+ return image_name
+ return None
+
+ def _GetDSymPath(self, base_path, image_name):
+ """Takes a base path for the symbols and an image name. It looks the name up
+ in SYMBOL_IMAGE_MAP and creates a full path to the dSYM in the bundle."""
+ image_file = SYMBOL_IMAGE_MAP[image_name]
+ return os.path.join(base_path, image_file + '.dSYM', 'Contents',
+ 'Resources', 'DWARF',
+ os.path.splitext(image_file)[0]) # Chop off the extension.
+
+ def _RunAtos(self, load_address, dsym_file, addresses):
+ """Runs the atos with the provided arguments. |addresses| is used as stdin.
+ Returns a list of symbol information in the same order as |addresses|."""
+ args = ['atos', '-l', str(load_address), '-o', dsym_file]
+
+ # Get the arch type. This is of the format |X86 (Native)|.
+ if 'Code Type' in self.report_info:
+ arch = self.report_info['Code Type'].lower().split(' ')
+ if len(arch) == 2:
+ arch = arch[0]
+ if arch == 'x86':
+ # The crash report refers to i386 as x86, but atos doesn't know what
+ # that is.
+ arch = 'i386'
+ args.extend(['-arch', arch])
+
+ proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ addresses = map(hex, addresses)
+ (stdout, stderr) = proc.communicate(' '.join(addresses))
+ if proc.returncode:
+ return None
+ return stdout.rstrip().split('\n')
+
+ def _AddSymbolsToFrames(self, symbols, address_tuples):
+ """Takes a single value (the list) from _CollectAddressesForImages and does
+ a smart-zip with the data returned by atos in |symbols|. Note that the
+ indices must match for this to succeed."""
+ if len(symbols) != len(address_tuples):
+ print 'symbols do not match'
+
+ # Each line of output from atos is in this format:
+ # |<symbol> (in <image>) (<file>:<line>)|.
+ line_regex = re.compile('(.+) \(in (.+)\) (\((.+):([0-9]+)\))?')
+
+ # Zip the two data sets together.
+ for i in range(len(symbols)):
+ symbol_parts = line_regex.match(symbols[i])
+ if not symbol_parts:
+ continue # Error.
+ frame = address_tuples[i][0]
+ frame.symbol = symbol_parts.group(1)
+ frame.image = symbol_parts.group(2)
+ frame.file_name = symbol_parts.group(4)
+ frame.line_number = symbol_parts.group(5)
+
+
+class CrashThread(object):
+ """A CrashThread represents a stacktrace of a single thread """
+ def __init__(self, thread_id):
+ super(CrashThread, self).__init__()
+ self.thread_id = thread_id
+ self.name = None
+ self.did_crash = False
+ self.stack = []
+
+ def __repr__(self):
+ name = ''
+ if self.name:
+ name = ': ' + self.name
+ return 'Thread ' + self.thread_id + name + '\n' + \
+ '\n'.join(map(str, self.stack))
+
+
+class StackFrame(object):
+ """A StackFrame is owned by a CrashThread."""
+ def __init__(self, line):
+ super(StackFrame, self).__init__()
+ # The original line. This will be set to None if symbolication was
+ # successfuly.
+ self.line = line
+
+ self.frame_id = 0
+ self.image = None
+ self.address = 0x0
+ self.original_symbol = None
+ self.offset = 0x0
+ # The following members are set after symbolication.
+ self.symbol = None
+ self.file_name = None
+ self.line_number = 0
+
+ def __repr__(self):
+ # If symbolication failed, just use the original line.
+ if self.line:
+ return ' %s' % self.line
+
+ # Use different location information depending on symbolicated data.
+ location = None
+ if self.file_name:
+ location = ' - %s:%s' % (self.file_name, self.line_number)
+ else:
+ location = ' + %s' % self.offset
+
+ # Same with the symbol information.
+ symbol = self.original_symbol
+ if self.symbol:
+ symbol = self.symbol
+
+ return ' %s\t0x%x\t[%s\t%s]\t%s' % (self.frame_id, self.address,
+ self.image, location, symbol)
+
+
+def PrettyPrintReport(report):
+ """Takes a crash report and prints it like the crash server would."""
+ print 'Process : ' + report.report_info['Process']
+ print 'Version : ' + report.report_info['Version']
+ print 'Date : ' + report.report_info['Date/Time']
+ print 'OS Version : ' + report.report_info['OS Version']
+ print
+ if 'Crashed Thread' in report.report_info:
+ print 'Crashed Thread : ' + report.report_info['Crashed Thread']
+ print
+ if 'Event' in report.report_info:
+ print 'Event : ' + report.report_info['Event']
+ print
+
+ for thread in report.threads:
+ print
+ if thread.did_crash:
+ exc_type = report.report_info['Exception Type'].split(' ')[0]
+ exc_code = report.report_info['Exception Codes'].replace('at', '@')
+ print '*CRASHED* ( ' + exc_type + ' / ' + exc_code + ' )'
+ # Version 7 reports have spindump-style output (with a stepped stack trace),
+ # so remove the first tab to get better alignment.
+ if report.report_version == 7:
+ for line in repr(thread).split('\n'):
+ print line.replace('\t', ' ', 1)
+ else:
+ print thread
+
+
+def Main(args):
+ """Program main."""
+ parser = optparse.OptionParser(
+ usage='%prog [options] symbol_path crash_report',
+ description='This will parse and symbolicate an Apple CrashReporter v6-9 '
+ 'file.')
+ parser.add_option('-s', '--std-path', action='store_true', dest='std_path',
+ help='With this flag, the symbol_path is a containing '
+ 'directory, in which a dSYM files are stored in a '
+ 'directory named by the version. Example: '
+ '[symbolicate_crash.py -s ./symbols/ report.crash] will '
+ 'look for dSYMs in ./symbols/15.0.666.0/ if the report is '
+ 'from that verison.')
+ (options, args) = parser.parse_args(args[1:])
+
+ # Check that we have something to symbolicate.
+ if len(args) != 2:
+ parser.print_usage()
+ return 1
+
+ report = CrashReport(args[1])
+ symbol_path = None
+
+ # If not using the standard layout, this is a full path to the symbols.
+ if not options.std_path:
+ symbol_path = args[0]
+ # Otherwise, use the report version to locate symbols in a directory.
+ else:
+ # This is in the format of |M.N.B.P (B.P)|. Get just the part before the
+ # space.
+ chrome_version = report.report_info['Version'].split(' ')[0]
+ symbol_path = os.path.join(args[0], chrome_version)
+
+ # Check that the symbols exist.
+ if not os.path.isdir(symbol_path):
+ print >>sys.stderr, 'Symbol path %s is not a directory' % symbol_path
+ return 2
+
+ print >>sys.stderr, 'Using symbols from ' + symbol_path
+ print >>sys.stderr, '=' * 80
+
+ report.Symbolicate(symbol_path)
+ PrettyPrintReport(report)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/chromium/tools/measure_page_load_time/ff_ext/chrome.manifest b/chromium/tools/measure_page_load_time/ff_ext/chrome.manifest
new file mode 100644
index 00000000000..9e1d73d4284
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ff_ext/chrome.manifest
@@ -0,0 +1,2 @@
+content measurepageloadtimeextension content/
+overlay chrome://browser/content/browser.xul chrome://measurepageloadtimeextension/content/firefoxOverlay.xul
diff --git a/chromium/tools/measure_page_load_time/ff_ext/content/firefoxOverlay.xul b/chromium/tools/measure_page_load_time/ff_ext/content/firefoxOverlay.xul
new file mode 100644
index 00000000000..1c5529eaa69
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ff_ext/content/firefoxOverlay.xul
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://measurepageloadtimeextension/skin/overlay.css" type="text/css"?>
+<!DOCTYPE overlay SYSTEM "chrome://measurepageloadtimeextension/locale/measurepageloadtimeextension.dtd">
+<overlay id="measurepageloadtimeextension-overlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="measure_page_load_time.js"/>
+</overlay>
diff --git a/chromium/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js b/chromium/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js
new file mode 100644
index 00000000000..44473ccb105
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js
@@ -0,0 +1,209 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview measure_page_load_time.js implements a Firefox extension
+ * for measuring how long a page takes to load. It waits on TCP port
+ * 42492 for connections, then accepts URLs and returns strings of the
+ * form url,time, where "time" is the load time in milliseconds or the
+ * string "timeout" or "error". Load time is measured from the call to
+ * loadURI until the load event fires, or until the status changes to
+ * STATUS_STOP if the load event doesn't fire (there's an error.)
+ * @author jhaas@google.com (Jonathan Haas) */
+
+// Shorthand reference to nsIWebProgress[Listener] interfaces
+var IWP = Components.interfaces.nsIWebProgress;
+var IWPL = Components.interfaces.nsIWebProgressListener;
+
+
+var MPLT = {
+ /**
+ * Constants
+ */
+ PORT_NUMBER : 42492, // port to listen for connections on
+ TIME_OUT : 4 * 60 * 1000, // timeout in 4 minutes
+
+ /**
+ * Incoming URL buffer
+ * @type {string}
+ */
+ textBuffer : '',
+
+ /**
+ * URL we're currently visiting
+ * @type {string}
+ */
+ URL : '',
+
+ /**
+ * Listener to accept incoming connections
+ * @type {nsIServerSocketListener}
+ */
+ acceptListener :
+ {
+ onSocketAccepted : function(serverSocket, transport)
+ {
+ MPLT.streamInput = transport.openInputStream(0,0,0);
+ MPLT.streamOutput = transport.openOutputStream(0,0,0);
+
+ MPLT.scriptStream = Components.classes['@mozilla.org/scriptableinputstream;1']
+ .createInstance(Components.interfaces.nsIScriptableInputStream);
+ MPLT.scriptStream.init(MPLT.streamInput);
+ MPLT.pump = Components.classes['@mozilla.org/network/input-stream-pump;1']
+ .createInstance(Components.interfaces.nsIInputStreamPump);
+ MPLT.pump.init(MPLT.streamInput, -1, -1, 0, 0, false);
+ MPLT.pump.asyncRead(MPLT.dataListener,null);
+ },
+
+ onStopListening : function(){}
+ },
+
+ /**
+ * Listener for network input
+ * @type {nsIStreamListener}
+ */
+ dataListener :
+ {
+ onStartRequest: function(){},
+ onStopRequest: function(){},
+ onDataAvailable: function(request, context, inputStream, offset, count){
+ // Add the received data to the buffer, then process it
+ // Change CRLF to newline while we're at it
+ MPLT.textBuffer += MPLT.scriptStream.read(count).replace('\r\n', '\n');
+
+ MPLT.process();
+ }
+ },
+
+ /**
+ * Process the incoming data buffer
+ */
+ process : function()
+ {
+ // If we're waiting for a page to finish loading, wait
+ if (MPLT.timeLoadStarted)
+ return;
+
+ // Look for a carriage return
+ var firstCR = MPLT.textBuffer.indexOf('\n');
+
+ // If we haven't received a carriage return yet, wait
+ if (firstCR < 0)
+ return;
+
+ // If the first character was a carriage return, we're done!
+ if (firstCR == 0) {
+ MPLT.textBuffer = '';
+ MPLT.streamInput.close();
+ MPLT.streamOutput.close();
+
+ return;
+ }
+
+ // Remove the URL from the buffer
+ MPLT.URL = MPLT.textBuffer.substr(0, firstCR);
+ MPLT.textBuffer = MPLT.textBuffer.substr(firstCR + 1);
+
+ // Remember the current time and navigate to the new URL
+ MPLT.timeLoadStarted = new Date();
+ gBrowser.loadURIWithFlags(MPLT.URL, gBrowser.LOAD_FLAGS_BYPASS_CACHE);
+ setTimeout('MPLT.onTimeOut()', MPLT.TIME_OUT);
+ },
+
+ /**
+ * Page load completion handler
+ */
+ onPageLoad : function(e) {
+ // Ignore loads of non-HTML documents
+ if (!(e.originalTarget instanceof HTMLDocument))
+ return;
+
+ // Also ignore subframe loads
+ if (e.originalTarget.defaultView.frameElement)
+ return;
+
+ clearTimeout();
+ var timeElapsed = new Date() - MPLT.timeLoadStarted;
+
+ MPLT.outputResult(timeElapsed);
+ },
+
+ /**
+ * Timeout handler
+ */
+ onTimeOut : function() {
+ gBrowser.stop();
+
+ MPLT.outputResult('timeout');
+ },
+
+
+ /**
+ * Sends a properly-formatted result to the client
+ * @param {string} result The value to send along with the URL
+ */
+ outputResult : function(result) {
+
+ if (MPLT.URL) {
+ var outputString = MPLT.URL + ',' + result + '\n';
+ MPLT.streamOutput.write(outputString, outputString.length);
+ MPLT.URL = '';
+ }
+
+ MPLT.timeLoadStarted = null;
+ MPLT.process();
+ },
+
+ /**
+ * Time the page load started. If null, we're waiting for the
+ * initial page load, or otherwise don't care about the page
+ * that's currently loading
+ * @type {number}
+ */
+ timeLoadStarted : null,
+
+ /*
+ * TODO(jhaas): add support for nsIWebProgressListener
+ * If the URL being visited died as part of a network error
+ * (host not found, connection reset by peer, etc), the onload
+ * event doesn't fire. The only way to catch it would be in
+ * a web progress listener. However, nsIWebProgress is not
+ * behaving according to documentation. More research is needed.
+ * For now, omitting it means that if any of our URLs are "dirty"
+ * (do not point to real web servers with real responses), we'll log
+ * them as timeouts. This doesn't affect pages where the server
+ * exists but returns an error code.
+ */
+
+ /**
+ * Initialize the plugin, create the socket and listen
+ */
+ initialize: function() {
+ // Register for page load events
+ gBrowser.addEventListener('load', this.onPageLoad, true);
+
+ // Set a timeout to wait for the initial page to load
+ MPLT.timeLoadStarted = new Date();
+ setTimeout('MPLT.onTimeOut()', MPLT.TIME_OUT);
+
+ // Create the listening socket
+ MPLT.serverSocket = Components.classes['@mozilla.org/network/server-socket;1']
+ .createInstance(Components.interfaces.nsIServerSocket);
+
+ MPLT.serverSocket.init(MPLT.PORT_NUMBER, true, 1);
+ MPLT.serverSocket.asyncListen(this.acceptListener);
+ },
+
+ /**
+ * Close the socket(s)
+ */
+ deinitialize: function() {
+ if (MPLT.streamInput) MPLT.streamInput.close();
+ if (MPLT.streamOutput) MPLT.streamOutput.close();
+ if (MPLT.serverSocket) MPLT.serverSocket.close();
+ }
+};
+
+window.addEventListener('load', function(e) { MPLT.initialize(); }, false);
+window.addEventListener('unload', function(e) { MPLT.deinitialize(); }, false);
diff --git a/chromium/tools/measure_page_load_time/ff_ext/install.rdf b/chromium/tools/measure_page_load_time/ff_ext/install.rdf
new file mode 100644
index 00000000000..c79d24e66f3
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ff_ext/install.rdf
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>measurepageloadtimeextension@google.com</em:id>
+ <em:name>MeasurePageLoadTime</em:name>
+ <em:version>1.0</em:version>
+ <em:creator>Jonathan Haas</em:creator>
+ <em:targetApplication>
+ <Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- firefox -->
+ <em:minVersion>1.5</em:minVersion>
+ <em:maxVersion>3.0.*</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ </Description>
+</RDF>
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.cpp b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.cpp
new file mode 100644
index 00000000000..d3a8d542519
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// MeasurePageLoadTime.cpp : Implementation of DLL Exports.
+
+#include "stdafx.h"
+#include "resource.h"
+#include "MeasurePageLoadTime.h"
+
+
+class CMeasurePageLoadTimeModule : public CAtlDllModuleT< CMeasurePageLoadTimeModule >
+{
+public :
+ DECLARE_LIBID(LIBID_MeasurePageLoadTimeLib)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_MEASUREPAGELOADTIME, "{56C6D9F9-643C-4F6E-906C-5F7CECB23C24}")
+};
+
+CMeasurePageLoadTimeModule _AtlModule;
+
+
+#ifdef _MANAGED
+#pragma managed(push, off)
+#endif
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ DisableThreadLibraryCalls(hInstance);
+ }
+ return _AtlModule.DllMain(dwReason, lpReserved);
+}
+
+#ifdef _MANAGED
+#pragma managed(pop)
+#endif
+
+
+
+
+// Used to determine whether the DLL can be unloaded by OLE
+STDAPI DllCanUnloadNow(void)
+{
+ return _AtlModule.DllCanUnloadNow();
+}
+
+
+// Returns a class factory to create an object of the requested type
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+
+// DllRegisterServer - Adds entries to the system registry
+STDAPI DllRegisterServer(void)
+{
+ // registers object, typelib and all interfaces in typelib
+ HRESULT hr = _AtlModule.DllRegisterServer();
+ return hr;
+}
+
+
+// DllUnregisterServer - Removes entries from the system registry
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+ return hr;
+}
+
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.def b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.def
new file mode 100644
index 00000000000..5552923379d
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.def
@@ -0,0 +1,9 @@
+; MeasurePageLoadTime.def : Declares the module parameters.
+
+LIBRARY "MeasurePageLoadTime.DLL"
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.idl b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.idl
new file mode 100644
index 00000000000..d2f98da3089
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.idl
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// MeasurePageLoadTime.idl : IDL source for MeasurePageLoadTime
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (MeasurePageLoadTime.tlb) and marshalling code.
+
+import "oaidl.idl";
+import "ocidl.idl";
+
+[
+ object,
+ uuid(019637EB-B865-485B-9A66-419477EE55A0),
+ dual,
+ nonextensible,
+ helpstring("IMeasurePageLoadTimeBHO Interface"),
+ pointer_default(unique)
+]
+interface IMeasurePageLoadTimeBHO : IDispatch{
+};
+[
+ uuid(61AC7AC4-B715-4955-A238-5F9AEA80DF4B),
+ version(1.0),
+ helpstring("MeasurePageLoadTime 1.0 Type Library")
+]
+library MeasurePageLoadTimeLib
+{
+ importlib("stdole2.tlb");
+ [
+ uuid(807E68BC-238F-4163-AE4B-0A3604F3E145),
+ helpstring("MeasurePageLoadTimeBHO Class")
+ ]
+ coclass MeasurePageLoadTimeBHO
+ {
+ [default] interface IMeasurePageLoadTimeBHO;
+ };
+};
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rc b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rc
new file mode 100644
index 00000000000..9285a705062
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rc
@@ -0,0 +1,121 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "1 TYPELIB ""MeasurePageLoadTime.tlb""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "Google"
+ VALUE "FileDescription", "Measures page load times"
+ VALUE "FileVersion", "1.0.0.1"
+ VALUE "LegalCopyright", "(c) 2008 Google. All rights reserved."
+ VALUE "InternalName", "MeasurePageLoadTime.dll"
+ VALUE "OriginalFilename", "MeasurePageLoadTime.dll"
+ VALUE "ProductName", "MeasurePageLoadTime"
+ VALUE "ProductVersion", "1.0.0.1"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_MEASUREPAGELOADTIME REGISTRY "MeasurePageLoadTime.rgs"
+IDR_MEASUREPAGELOADTIMEBHO REGISTRY "MeasurePageLoadTimeBHO.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PROJNAME "MeasurePageLoadTime"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "MeasurePageLoadTime.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rgs b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rgs
new file mode 100644
index 00000000000..98e7f78318e
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.rgs
@@ -0,0 +1,29 @@
+HKCR
+{
+ NoRemove AppID
+ {
+ '%APPID%' = s 'MeasurePageLoadTime'
+ 'MeasurePageLoadTime.DLL'
+ {
+ val AppID = s '%APPID%'
+ }
+ }
+}
+
+HKLM {
+ NoRemove SOFTWARE {
+ NoRemove Microsoft {
+ NoRemove Windows {
+ NoRemove CurrentVersion {
+ NoRemove Explorer {
+ NoRemove 'Browser Helper Objects' {
+ ForceRemove '{807E68BC-238F-4163-AE4B-0A3604F3E145}' = s 'MeasurePageLoadTimeBHO' {
+ val 'NoExplorer' = d '1'
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.vcproj b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.vcproj
new file mode 100644
index 00000000000..9ed8327bf95
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTime.vcproj
@@ -0,0 +1,320 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="MeasurePageLoadTime"
+ ProjectGUID="{151243DF-25BE-4A88-B566-8B7AE8970E86}"
+ RootNamespace="MeasurePageLoadTime"
+ Keyword="AtlProj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="2"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="false"
+ TargetEnvironment="1"
+ GenerateStublessProxies="true"
+ TypeLibraryName="$(IntDir)/MeasurePageLoadTime.tlb"
+ HeaderFileName="MeasurePageLoadTime.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="MeasurePageLoadTime_i.c"
+ ProxyFileName="MeasurePageLoadTime_p.c"
+ ValidateParameters="false"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="true"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="ws2_32.lib"
+ LinkIncremental="2"
+ ModuleDefinitionFile=".\MeasurePageLoadTime.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfATL="1"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="false"
+ TargetEnvironment="1"
+ GenerateStublessProxies="true"
+ TypeLibraryName="$(IntDir)/MeasurePageLoadTime.tlb"
+ HeaderFileName="MeasurePageLoadTime.h"
+ DLLDataFileName=""
+ InterfaceIdentifierFileName="MeasurePageLoadTime_i.c"
+ ProxyFileName="MeasurePageLoadTime_p.c"
+ ValidateParameters="false"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ AdditionalIncludeDirectories="$(IntDir)"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ RegisterOutput="true"
+ IgnoreImportLibrary="true"
+ AdditionalDependencies="ws2_32.lib"
+ LinkIncremental="1"
+ ModuleDefinitionFile=".\MeasurePageLoadTime.def"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\MeasurePageLoadTime.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTime.def"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTime.idl"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTimeBHO.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\MeasurePageLoadTimeBHO.h"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\MeasurePageLoadTime.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTime.rgs"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTimeBHO.rgs"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Generated Files"
+ SourceControlFiles="false"
+ >
+ <File
+ RelativePath=".\MeasurePageLoadTime.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MeasurePageLoadTime_i.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.cpp b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.cpp
new file mode 100644
index 00000000000..3de87f3c803
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.cpp
@@ -0,0 +1,292 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Implements a Browser Helper Object (BHO) which opens a socket
+// and waits to receive URLs over it. Visits those URLs, measuring
+// how long it takes between the start of navigation and the
+// DocumentComplete event, and returns the time in milliseconds as
+// a string to the caller.
+
+#include "stdafx.h"
+#include "MeasurePageLoadTimeBHO.h"
+
+#define MAX_URL 1024 // size of URL buffer
+#define MAX_PAGELOADTIME (4*60*1000) // assume all pages take < 4 minutes
+#define PORT 42492 // port to listen on. Also jhaas's
+ // old MSFT employee number
+
+
+// Static function to serve as thread entry point, takes a "this"
+// pointer as pParam and calls the method in the object
+static DWORD WINAPI ProcessPageTimeRequests(LPVOID pThis) {
+ reinterpret_cast<CMeasurePageLoadTimeBHO*>(pThis)->ProcessPageTimeRequests();
+
+ return 0;
+}
+
+
+STDMETHODIMP CMeasurePageLoadTimeBHO::SetSite(IUnknown* pUnkSite)
+{
+ if (pUnkSite != NULL)
+ {
+ // Cache the pointer to IWebBrowser2.
+ HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
+ if (SUCCEEDED(hr))
+ {
+ // Register to sink events from DWebBrowserEvents2.
+ hr = DispEventAdvise(m_spWebBrowser);
+ if (SUCCEEDED(hr))
+ {
+ m_fAdvised = TRUE;
+ }
+
+ // Stash the interface in the global interface table
+ CComGITPtr<IWebBrowser2> git(m_spWebBrowser);
+ m_dwCookie = git.Detach();
+
+ // Create the event to be signaled when navigation completes.
+ // Start it in nonsignaled state, and allow it to be triggered
+ // when the initial page load is done.
+ m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ // Create a thread to wait on the socket
+ HANDLE hThread = CreateThread(NULL, 0, ::ProcessPageTimeRequests, this, 0, NULL);
+ }
+ }
+ else
+ {
+ // Unregister event sink.
+ if (m_fAdvised)
+ {
+ DispEventUnadvise(m_spWebBrowser);
+ m_fAdvised = FALSE;
+ }
+
+ // Release cached pointers and other resources here.
+ m_spWebBrowser.Release();
+ }
+
+ // Call base class implementation.
+ return IObjectWithSiteImpl<CMeasurePageLoadTimeBHO>::SetSite(pUnkSite);
+}
+
+
+void STDMETHODCALLTYPE CMeasurePageLoadTimeBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
+{
+ if (pDisp == m_spWebBrowser)
+ {
+ // Fire the event when the page is done loading
+ // to unblock the other thread.
+ SetEvent(m_hEvent);
+ }
+}
+
+
+void CMeasurePageLoadTimeBHO::ProcessPageTimeRequests()
+{
+ CoInitialize(NULL);
+
+ // The event will start in nonsignaled state, meaning that
+ // the initial page load isn't done yet. Wait for that to
+ // finish before doing anything.
+ //
+ // It seems to be the case that the BHO will get loaded
+ // and SetSite called always before the initial page load
+ // even begins, but just to be on the safe side, we won't
+ // wait indefinitely.
+ WaitForSingleObject(m_hEvent, MAX_PAGELOADTIME);
+
+ // Retrieve the web browser interface from the global table
+ CComGITPtr<IWebBrowser2> git(m_dwCookie);
+ IWebBrowser2* browser;
+ git.CopyTo(&browser);
+
+ // Create a listening socket
+ m_sockListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (m_sockListen == SOCKET_ERROR)
+ ErrorExit();
+
+ BOOL on = TRUE;
+ if (setsockopt(m_sockListen, SOL_SOCKET, SO_REUSEADDR,
+ (const char*)&on, sizeof(on)))
+ ErrorExit();
+
+ // Bind the listening socket
+ SOCKADDR_IN addrBind;
+
+ addrBind.sin_family = AF_INET;
+ addrBind.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addrBind.sin_port = htons(PORT);
+
+ if (bind(m_sockListen, (sockaddr*)&addrBind, sizeof(addrBind)))
+ ErrorExit();
+
+ // Listen for incoming connections
+ if (listen(m_sockListen, 1))
+ ErrorExit();
+
+ // Ensure the socket is blocking... it should be by default, but
+ // it can't hurt to make sure
+ unsigned long nNonblocking = 0;
+ if (ioctlsocket(m_sockListen, FIONBIO, &nNonblocking))
+ ErrorExit();
+
+ m_sockTransport = 0;
+
+ // Loop indefinitely waiting for connections
+ while(1)
+ {
+ SOCKADDR_IN addrConnected;
+ int sConnected = sizeof(addrConnected);
+
+ // Wait for a client to connect and send a URL
+ m_sockTransport = accept(
+ m_sockListen, (sockaddr*)&addrConnected, &sConnected);
+
+ if (m_sockTransport == SOCKET_ERROR)
+ ErrorExit();
+
+ char pbBuffer[MAX_URL], strURL[MAX_URL];
+ DWORD cbRead, cbWritten;
+
+ bool fDone = false;
+
+ // Loop until we're done with this client
+ while (!fDone)
+ {
+ *strURL = '\0';
+ bool fReceivedCR = false;
+
+ do
+ {
+ // Only receive up to the first carriage return
+ cbRead = recv(m_sockTransport, pbBuffer, MAX_URL-1, MSG_PEEK);
+
+ // An error on read most likely means that the remote peer
+ // closed the connection. Go back to waiting
+ if (cbRead == 0)
+ {
+ fDone = true;
+ break;
+ }
+
+ // Null terminate the received characters so strchr() is safe
+ pbBuffer[cbRead] = '\0';
+
+ if(char* pchFirstCR = strchr(pbBuffer, '\n'))
+ {
+ cbRead = (DWORD)(pchFirstCR - pbBuffer + 1);
+ fReceivedCR = true;
+ }
+
+ // The below call will not block, since we determined with
+ // MSG_PEEK that at least cbRead bytes are in the TCP receive buffer
+ recv(m_sockTransport, pbBuffer, cbRead, 0);
+ pbBuffer[cbRead] = '\0';
+
+ strcat_s(strURL, sizeof(strURL), pbBuffer);
+ } while (!fReceivedCR);
+
+ // If an error occurred while reading, exit this loop
+ if (fDone)
+ break;
+
+ // Strip the trailing CR and/or LF
+ int i;
+ for (i = (int)strlen(strURL)-1; i >= 0 && isspace(strURL[i]); i--)
+ {
+ strURL[i] = '\0';
+ }
+
+ if (i < 0)
+ {
+ // Sending a carriage return on a line by itself means that
+ // the client is done making requests
+ fDone = true;
+ }
+ else
+ {
+ // Send the browser to the requested URL
+ CComVariant vNavFlags( navNoReadFromCache );
+ CComVariant vTargetFrame("_self");
+ CComVariant vPostData("");
+ CComVariant vHTTPHeaders("");
+
+ ResetEvent(m_hEvent);
+ DWORD dwStartTime = GetTickCount();
+
+ HRESULT hr = browser->Navigate(
+ CComBSTR(strURL),
+ &vNavFlags,
+ &vTargetFrame, // TargetFrameName
+ &vPostData, // PostData
+ &vHTTPHeaders // Headers
+ );
+
+ // The main browser thread will call OnDocumentComplete() when
+ // the page is done loading, which will in turn trigger
+ // m_hEvent. Wait here until then; the event will reset itself
+ // once this thread is released
+ if (WaitForSingleObject(m_hEvent, MAX_PAGELOADTIME) == WAIT_TIMEOUT)
+ {
+ sprintf_s(pbBuffer, sizeof(pbBuffer), "%s,timeout\n", strURL);
+
+ browser->Stop();
+ }
+ else
+ {
+ // Format the elapsed time as a string
+ DWORD dwLoadTime = GetTickCount() - dwStartTime;
+ sprintf_s(
+ pbBuffer, sizeof(pbBuffer), "%s,%d\n", strURL, dwLoadTime);
+ }
+
+ // Send the result. Just in case the TCP buffer can't handle
+ // the whole thing, send in parts if necessary
+ char *chSend = pbBuffer;
+
+ while (*chSend)
+ {
+ cbWritten = send(
+ m_sockTransport, chSend, (int)strlen(chSend), 0);
+
+ // Error on send probably means connection reset by peer
+ if (cbWritten == 0)
+ {
+ fDone = true;
+ break;
+ }
+
+ chSend += cbWritten;
+ }
+ }
+ }
+
+ // Close the transport socket and wait for another connection
+ closesocket(m_sockTransport);
+ m_sockTransport = 0;
+ }
+}
+
+
+void CMeasurePageLoadTimeBHO::ErrorExit()
+{
+ // Unlink from IE, close the sockets, then terminate this
+ // thread
+ SetSite(NULL);
+
+ if (m_sockTransport && m_sockTransport != SOCKET_ERROR)
+ {
+ closesocket(m_sockTransport);
+ m_sockTransport = 0;
+ }
+
+ if (m_sockListen && m_sockListen != SOCKET_ERROR)
+ {
+ closesocket(m_sockListen);
+ m_sockListen = 0;
+ }
+
+ TerminateThread(GetCurrentThread(), -1);
+}
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.h b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.h
new file mode 100644
index 00000000000..cabb02401f5
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// MeasurePageLoadTimeBHO.h : Declaration of the CMeasurePageLoadTimeBHO
+
+#include "resource.h" // main symbols
+
+#include <shlguid.h> // IID_IWebBrowser2, DIID_DWebBrowserEvents2, et
+#include <exdispid.h> // DISPID_DOCUMENTCOMPLETE, etc.
+
+#include <string>
+
+#include "MeasurePageLoadTime.h"
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM objects and allow use of its single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+
+
+// CMeasurePageLoadTimeBHO
+
+class ATL_NO_VTABLE CMeasurePageLoadTimeBHO :
+ public CComObjectRootEx<CComSingleThreadModel>,
+ public CComCoClass<CMeasurePageLoadTimeBHO, &CLSID_MeasurePageLoadTimeBHO>,
+ public IObjectWithSiteImpl<CMeasurePageLoadTimeBHO>,
+ public IDispatchImpl<IMeasurePageLoadTimeBHO, &IID_IMeasurePageLoadTimeBHO, &LIBID_MeasurePageLoadTimeLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
+ public IDispEventImpl<1, CMeasurePageLoadTimeBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
+{
+public:
+ CMeasurePageLoadTimeBHO()
+ {
+ }
+
+DECLARE_REGISTRY_RESOURCEID(IDR_MEASUREPAGELOADTIMEBHO)
+
+DECLARE_NOT_AGGREGATABLE(CMeasurePageLoadTimeBHO)
+
+BEGIN_COM_MAP(CMeasurePageLoadTimeBHO)
+ COM_INTERFACE_ENTRY(IMeasurePageLoadTimeBHO)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(IObjectWithSite)
+END_COM_MAP()
+
+BEGIN_SINK_MAP(CMeasurePageLoadTimeBHO)
+ SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
+END_SINK_MAP()
+
+ // DWebBrowserEvents2
+ void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);
+ STDMETHOD(SetSite)(IUnknown *pUnkSite);
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+ void ProcessPageTimeRequests(void);
+ void VisitNextURL(void);
+ void ErrorExit(void);
+
+private:
+ CComPtr<IWebBrowser2> m_spWebBrowser;
+ BOOL m_fAdvised;
+
+ // Handle to global interface table
+ DWORD m_dwCookie;
+
+ // Handle to event to signal when navigation completes
+ HANDLE m_hEvent;
+
+ // Socket for accepting incoming connections
+ SOCKET m_sockListen;
+
+ // Socket for communicating with remote peers
+ SOCKET m_sockTransport;
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(MeasurePageLoadTimeBHO), CMeasurePageLoadTimeBHO)
diff --git a/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.rgs b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.rgs
new file mode 100644
index 00000000000..907015fc30b
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/MeasurePageLoadTimeBHO.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ MeasurePageLoadTime.MeasurePageLoadTi.1 = s 'MeasurePageLoadTimeBHO Class'
+ {
+ CLSID = s '{807E68BC-238F-4163-AE4B-0A3604F3E145}'
+ }
+ MeasurePageLoadTime.MeasurePageLoadTime = s 'MeasurePageLoadTimeBHO Class'
+ {
+ CLSID = s '{807E68BC-238F-4163-AE4B-0A3604F3E145}'
+ CurVer = s 'MeasurePageLoadTime.MeasurePageLoadTi.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {807E68BC-238F-4163-AE4B-0A3604F3E145} = s 'MeasurePageLoadTimeBHO Class'
+ {
+ ProgID = s 'MeasurePageLoadTime.MeasurePageLoadTi.1'
+ VersionIndependentProgID = s 'MeasurePageLoadTime.MeasurePageLoadTime'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{61AC7AC4-B715-4955-A238-5F9AEA80DF4B}'
+ }
+ }
+}
diff --git a/chromium/tools/measure_page_load_time/ie_bho/resource.h b/chromium/tools/measure_page_load_time/ie_bho/resource.h
new file mode 100644
index 00000000000..38dc82565b7
--- /dev/null
+++ b/chromium/tools/measure_page_load_time/ie_bho/resource.h
@@ -0,0 +1,18 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by MeasurePageLoadTime.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_MEASUREPAGELOADTIME 101
+#define IDR_MEASUREPAGELOADTIMEBHO 102
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 103
+#endif
+#endif
diff --git a/chromium/tools/memory_watcher/DEPS b/chromium/tools/memory_watcher/DEPS
new file mode 100644
index 00000000000..b51da65b022
--- /dev/null
+++ b/chromium/tools/memory_watcher/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+ui/base",
+ "+ui/gfx",
+]
diff --git a/chromium/tools/memory_watcher/README b/chromium/tools/memory_watcher/README
new file mode 100644
index 00000000000..4850b18246f
--- /dev/null
+++ b/chromium/tools/memory_watcher/README
@@ -0,0 +1,17 @@
+memory_watcher is a library that can be linked into chromium to trace the
+memory allocations. It works by hooking the system allocation/deallocation
+functions, and recording the actions.
+
+To use memory_watcher in chromium:
+
+(1) Compile the memory_watcher library (it is part of the solution by default)
+
+(2) Run chromium with these flags "--memory-profile -no-sandbox"
+(The instrumentation doesn't work with the sandbox)
+
+(3) Hit ctrl-alt-D to generate a dump of the memory allocations.
+This will create a log file called memorywatcher.logXXXX for every
+chromium process (where XXXX is the pid).
+
+The log file is a human readable text format, which can be further analyzed
+using the helpers in the "scripts/" directory.
diff --git a/chromium/tools/memory_watcher/call_stack.cc b/chromium/tools/memory_watcher/call_stack.cc
new file mode 100644
index 00000000000..6f829b45017
--- /dev/null
+++ b/chromium/tools/memory_watcher/call_stack.cc
@@ -0,0 +1,399 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/memory_watcher/call_stack.h"
+
+#include <shlwapi.h>
+#include <tlhelp32.h>
+
+#include "base/strings/string_number_conversions.h"
+#include "tools/memory_watcher/memory_hook.h"
+
+// Typedefs for explicit dynamic linking with functions exported from
+// dbghelp.dll.
+typedef BOOL (__stdcall *t_StackWalk64)(DWORD, HANDLE, HANDLE,
+ LPSTACKFRAME64, PVOID,
+ PREAD_PROCESS_MEMORY_ROUTINE64,
+ PFUNCTION_TABLE_ACCESS_ROUTINE64,
+ PGET_MODULE_BASE_ROUTINE64,
+ PTRANSLATE_ADDRESS_ROUTINE64);
+typedef PVOID (__stdcall *t_SymFunctionTableAccess64)(HANDLE, DWORD64);
+typedef DWORD64 (__stdcall *t_SymGetModuleBase64)(HANDLE, DWORD64);
+typedef BOOL (__stdcall *t_SymCleanup)(HANDLE);
+typedef BOOL (__stdcall *t_SymGetSymFromAddr64)(HANDLE, DWORD64,
+ PDWORD64, PIMAGEHLP_SYMBOL64);
+typedef BOOL (__stdcall *t_SymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD,
+ PIMAGEHLP_LINE64);
+typedef BOOL (__stdcall *t_SymInitialize)(HANDLE, PCTSTR, BOOL);
+typedef DWORD (__stdcall *t_SymGetOptions)(void);
+typedef DWORD (__stdcall *t_SymSetOptions)(DWORD);
+typedef BOOL (__stdcall *t_SymGetSearchPath)(HANDLE, PTSTR, DWORD);
+typedef DWORD64 (__stdcall *t_SymLoadModule64)(HANDLE, HANDLE, PCSTR,
+ PCSTR, DWORD64, DWORD);
+typedef BOOL (__stdcall *t_SymGetModuleInfo64)(HANDLE, DWORD64,
+ PIMAGEHLP_MODULE64);
+
+// static
+base::Lock CallStack::dbghelp_lock_;
+// static
+bool CallStack::dbghelp_loaded_ = false;
+// static
+DWORD CallStack::active_thread_id_ = 0;
+
+
+static t_StackWalk64 pStackWalk64 = NULL;
+static t_SymCleanup pSymCleanup = NULL;
+static t_SymGetSymFromAddr64 pSymGetSymFromAddr64 = NULL;
+static t_SymFunctionTableAccess64 pSymFunctionTableAccess64 = NULL;
+static t_SymGetModuleBase64 pSymGetModuleBase64 = NULL;
+static t_SymGetLineFromAddr64 pSymGetLineFromAddr64 = NULL;
+static t_SymInitialize pSymInitialize = NULL;
+static t_SymGetOptions pSymGetOptions = NULL;
+static t_SymSetOptions pSymSetOptions = NULL;
+static t_SymGetModuleInfo64 pSymGetModuleInfo64 = NULL;
+static t_SymGetSearchPath pSymGetSearchPath = NULL;
+static t_SymLoadModule64 pSymLoadModule64 = NULL;
+
+#define LOADPROC(module, name) do { \
+ p##name = reinterpret_cast<t_##name>(GetProcAddress(module, #name)); \
+ if (p##name == NULL) return false; \
+} while (0)
+
+// This code has to be VERY careful to not induce any allocations, as memory
+// watching code may cause recursion, which may obscure the stack for the truly
+// offensive issue. We use this function to break into a debugger, and it
+// is guaranteed to not do any allocations (in fact, not do anything).
+static void UltraSafeDebugBreak() {
+ _asm int(3);
+}
+
+// static
+bool CallStack::LoadDbgHelp() {
+ if (!dbghelp_loaded_) {
+ base::AutoLock Lock(dbghelp_lock_);
+
+ // Re-check if we've loaded successfully now that we have the lock.
+ if (dbghelp_loaded_)
+ return true;
+
+ // Load dbghelp.dll, and obtain pointers to the exported functions that we
+ // will be using.
+ HMODULE dbghelp_module = LoadLibrary(L"dbghelp.dll");
+ if (dbghelp_module) {
+ LOADPROC(dbghelp_module, StackWalk64);
+ LOADPROC(dbghelp_module, SymFunctionTableAccess64);
+ LOADPROC(dbghelp_module, SymGetModuleBase64);
+ LOADPROC(dbghelp_module, SymCleanup);
+ LOADPROC(dbghelp_module, SymGetSymFromAddr64);
+ LOADPROC(dbghelp_module, SymGetLineFromAddr64);
+ LOADPROC(dbghelp_module, SymInitialize);
+ LOADPROC(dbghelp_module, SymGetOptions);
+ LOADPROC(dbghelp_module, SymSetOptions);
+ LOADPROC(dbghelp_module, SymGetModuleInfo64);
+ LOADPROC(dbghelp_module, SymGetSearchPath);
+ LOADPROC(dbghelp_module, SymLoadModule64);
+ dbghelp_loaded_ = true;
+ } else {
+ UltraSafeDebugBreak();
+ return false;
+ }
+ }
+ return dbghelp_loaded_;
+}
+
+// Load the symbols for generating stack traces.
+static bool LoadSymbols(HANDLE process_handle) {
+ static bool symbols_loaded = false;
+ if (symbols_loaded) return true;
+
+ BOOL ok;
+
+ // Initialize the symbol engine.
+ ok = pSymInitialize(process_handle, /* hProcess */
+ NULL, /* UserSearchPath */
+ FALSE); /* fInvadeProcess */
+ if (!ok) return false;
+
+ DWORD options = pSymGetOptions();
+ options |= SYMOPT_LOAD_LINES;
+ options |= SYMOPT_FAIL_CRITICAL_ERRORS;
+ options |= SYMOPT_UNDNAME;
+ options = pSymSetOptions(options);
+
+ const DWORD kMaxSearchPath = 1024;
+ TCHAR buf[kMaxSearchPath] = {0};
+ ok = pSymGetSearchPath(process_handle, buf, kMaxSearchPath);
+ if (!ok)
+ return false;
+
+ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
+ GetCurrentProcessId());
+ if (snapshot == INVALID_HANDLE_VALUE)
+ return false;
+
+ MODULEENTRY32W module;
+ module.dwSize = sizeof(module); // Set the size of the structure.
+ BOOL cont = Module32FirstW(snapshot, &module);
+ while (cont) {
+ DWORD64 base;
+ // NOTE the SymLoadModule64 function has the peculiarity of accepting a
+ // both unicode and ASCII strings even though the parameter is PSTR.
+ base = pSymLoadModule64(process_handle,
+ 0,
+ reinterpret_cast<PSTR>(module.szExePath),
+ reinterpret_cast<PSTR>(module.szModule),
+ reinterpret_cast<DWORD64>(module.modBaseAddr),
+ module.modBaseSize);
+ if (base == 0) {
+ int err = GetLastError();
+ if (err != ERROR_MOD_NOT_FOUND && err != ERROR_INVALID_HANDLE)
+ return false;
+ }
+ cont = Module32NextW(snapshot, &module);
+ }
+ CloseHandle(snapshot);
+
+ symbols_loaded = true;
+ return true;
+}
+
+
+CallStack::SymbolCache* CallStack::symbol_cache_;
+
+bool CallStack::Initialize() {
+ // We need to delay load the symbol cache until after
+ // the MemoryHook heap is alive.
+ symbol_cache_ = new SymbolCache();
+ return LoadDbgHelp();
+}
+
+CallStack::CallStack() {
+ static LONG callstack_id = 0;
+ frame_count_ = 0;
+ hash_ = 0;
+ id_ = InterlockedIncrement(&callstack_id);
+ valid_ = false;
+
+ if (!dbghelp_loaded_) {
+ UltraSafeDebugBreak(); // Initialize should have been called.
+ return;
+ }
+
+ GetStackTrace();
+}
+
+bool CallStack::IsEqual(const CallStack &target) {
+ if (frame_count_ != target.frame_count_)
+ return false; // They can't be equal if the sizes are different.
+
+ // Walk the frames array until we
+ // either find a mismatch, or until we reach the end of the call stacks.
+ for (int index = 0; index < frame_count_; index++) {
+ if (frames_[index] != target.frames_[index])
+ return false; // Found a mismatch. They are not equal.
+ }
+
+ // Reached the end of the call stacks. They are equal.
+ return true;
+}
+
+void CallStack::AddFrame(DWORD_PTR pc) {
+ DCHECK(frame_count_ < kMaxTraceFrames);
+ frames_[frame_count_++] = pc;
+
+ // Create a unique id for this CallStack.
+ pc = pc + (frame_count_ * 13); // Alter the PC based on position in stack.
+ hash_ = ~hash_ + (pc << 15);
+ hash_ = hash_ ^ (pc >> 12);
+ hash_ = hash_ + (pc << 2);
+ hash_ = hash_ ^ (pc >> 4);
+ hash_ = hash_ * 2057;
+ hash_ = hash_ ^ (pc >> 16);
+}
+
+bool CallStack::LockedRecursionDetected() const {
+ if (!active_thread_id_) return false;
+ DWORD thread_id = GetCurrentThreadId();
+ // TODO(jar): Perchance we should use atomic access to member.
+ return thread_id == active_thread_id_;
+}
+
+bool CallStack::GetStackTrace() {
+ if (LockedRecursionDetected())
+ return false;
+
+ // Initialize the context record.
+ CONTEXT context;
+ memset(&context, 0, sizeof(context));
+ context.ContextFlags = CONTEXT_FULL;
+ __asm call x
+ __asm x: pop eax
+ __asm mov context.Eip, eax
+ __asm mov context.Ebp, ebp
+ __asm mov context.Esp, esp
+
+ STACKFRAME64 frame;
+ memset(&frame, 0, sizeof(frame));
+
+#ifdef _M_IX86
+ DWORD image_type = IMAGE_FILE_MACHINE_I386;
+ frame.AddrPC.Offset = context.Eip;
+ frame.AddrPC.Mode = AddrModeFlat;
+ frame.AddrFrame.Offset = context.Ebp;
+ frame.AddrFrame.Mode = AddrModeFlat;
+ frame.AddrStack.Offset = context.Esp;
+ frame.AddrStack.Mode = AddrModeFlat;
+#elif
+ NOT IMPLEMENTED!
+#endif
+
+ HANDLE current_process = GetCurrentProcess();
+ HANDLE current_thread = GetCurrentThread();
+
+ // Walk the stack.
+ unsigned int count = 0;
+ {
+ AutoDbgHelpLock thread_monitoring_lock;
+
+ while (count < kMaxTraceFrames) {
+ count++;
+ if (!pStackWalk64(image_type,
+ current_process,
+ current_thread,
+ &frame,
+ &context,
+ 0,
+ pSymFunctionTableAccess64,
+ pSymGetModuleBase64,
+ NULL))
+ break; // Couldn't trace back through any more frames.
+
+ if (frame.AddrFrame.Offset == 0)
+ continue; // End of stack.
+
+ // Push this frame's program counter onto the provided CallStack.
+ AddFrame((DWORD_PTR)frame.AddrPC.Offset);
+ }
+ valid_ = true;
+ }
+ return true;
+}
+
+void CallStack::ToString(PrivateAllocatorString* output) {
+ static const int kStackWalkMaxNameLen = MAX_SYM_NAME;
+ HANDLE current_process = GetCurrentProcess();
+
+ if (!LoadSymbols(current_process)) {
+ *output = "Error";
+ return;
+ }
+
+ base::AutoLock lock(dbghelp_lock_);
+
+ // Iterate through each frame in the call stack.
+ for (int32 index = 0; index < frame_count_; index++) {
+ PrivateAllocatorString line;
+
+ DWORD_PTR intruction_pointer = frame(index);
+
+ SymbolCache::iterator it;
+ it = symbol_cache_->find(intruction_pointer);
+ if (it != symbol_cache_->end()) {
+ line = it->second;
+ } else {
+ // Try to locate a symbol for this frame.
+ DWORD64 symbol_displacement = 0;
+ ULONG64 buffer[(sizeof(IMAGEHLP_SYMBOL64) +
+ sizeof(TCHAR)*kStackWalkMaxNameLen +
+ sizeof(ULONG64) - 1) / sizeof(ULONG64)];
+ IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(buffer);
+ memset(buffer, 0, sizeof(buffer));
+ symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+ symbol->MaxNameLength = kStackWalkMaxNameLen;
+ BOOL ok = pSymGetSymFromAddr64(current_process, // hProcess
+ intruction_pointer, // Address
+ &symbol_displacement, // Displacement
+ symbol); // Symbol
+ if (ok) {
+ // Try to locate more source information for the symbol.
+ IMAGEHLP_LINE64 Line;
+ memset(&Line, 0, sizeof(Line));
+ Line.SizeOfStruct = sizeof(Line);
+ DWORD line_displacement;
+ ok = pSymGetLineFromAddr64(current_process,
+ intruction_pointer,
+ &line_displacement,
+ &Line);
+ if (ok) {
+ // Skip junk symbols from our internal stuff.
+ if (strstr(symbol->Name, "CallStack::") ||
+ strstr(symbol->Name, "MemoryWatcher::") ||
+ strstr(symbol->Name, "Perftools_") ||
+ strstr(symbol->Name, "MemoryHook::") ) {
+ // Just record a blank string.
+ (*symbol_cache_)[intruction_pointer] = "";
+ continue;
+ }
+
+ line += " ";
+ line += static_cast<char*>(Line.FileName);
+ line += " (";
+ // TODO(jar): get something like this template to work :-/
+ // line += IntToCustomString<PrivateAllocatorString>(Line.LineNumber);
+ // ...and then delete this line, which uses std::string.
+ line += base::IntToString(Line.LineNumber).c_str();
+ line += "): ";
+ line += symbol->Name;
+ line += "\n";
+ } else {
+ line += " unknown (0):";
+ line += symbol->Name;
+ line += "\n";
+ }
+ } else {
+ // OK - couldn't get any info. Try for the module.
+ IMAGEHLP_MODULE64 module_info;
+ module_info.SizeOfStruct = sizeof(module_info);
+ if (pSymGetModuleInfo64(current_process, intruction_pointer,
+ &module_info)) {
+ line += " (";
+ line += static_cast<char*>(module_info.ModuleName);
+ line += ")\n";
+ } else {
+ line += " ???\n";
+ }
+ }
+ }
+
+ (*symbol_cache_)[intruction_pointer] = line;
+ *output += line;
+ }
+ *output += "==================\n";
+}
+
+
+base::Lock AllocationStack::freelist_lock_;
+AllocationStack* AllocationStack::freelist_ = NULL;
+
+void* AllocationStack::operator new(size_t size) {
+ DCHECK(size == sizeof(AllocationStack));
+ {
+ base::AutoLock lock(freelist_lock_);
+ if (freelist_ != NULL) {
+ AllocationStack* stack = freelist_;
+ freelist_ = freelist_->next_;
+ stack->next_ = NULL;
+ return stack;
+ }
+ }
+ return MemoryHook::Alloc(size);
+}
+
+void AllocationStack::operator delete(void* ptr) {
+ AllocationStack *stack = reinterpret_cast<AllocationStack*>(ptr);
+ base::AutoLock lock(freelist_lock_);
+ DCHECK(stack->next_ == NULL);
+ stack->next_ = freelist_;
+ freelist_ = stack;
+}
diff --git a/chromium/tools/memory_watcher/call_stack.h b/chromium/tools/memory_watcher/call_stack.h
new file mode 100644
index 00000000000..941aad4987e
--- /dev/null
+++ b/chromium/tools/memory_watcher/call_stack.h
@@ -0,0 +1,168 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Parts of this module come from:
+// http://www.codeproject.com/KB/applications/visualleakdetector.aspx
+// by Dan Moulding.
+// http://www.codeproject.com/KB/threads/StackWalker.aspx
+// by Jochen Kalmbach
+
+#ifndef TOOLS_MEMORY_WATCHER_CALL_STACK_H_
+#define TOOLS_MEMORY_WATCHER_CALL_STACK_H_
+
+#include <windows.h>
+#include <dbghelp.h>
+#include <functional>
+#include <map>
+#include <string>
+
+#include "base/logging.h"
+#include "base/synchronization/lock.h"
+#include "tools/memory_watcher/memory_watcher.h"
+
+// The CallStack Class
+// A stack where memory has been allocated.
+class CallStack {
+ public:
+ // Initialize for tracing CallStacks.
+ static bool Initialize();
+
+ CallStack();
+ virtual ~CallStack() {}
+
+ // Get a hash for this CallStack.
+ // Identical stack traces will have matching hashes.
+ int32 hash() { return hash_; }
+
+ // Get a unique ID for this CallStack.
+ // No two CallStacks will ever have the same ID. The ID is a monotonically
+ // increasing number. Newer CallStacks always have larger IDs.
+ int32 id() { return id_; }
+
+ // Retrieves the frame at the specified index.
+ DWORD_PTR frame(int32 index) {
+ DCHECK(index < frame_count_ && index >= 0);
+ return frames_[index];
+ }
+
+ // Compares the CallStack to another CallStack
+ // for equality. Two CallStacks are equal if they are the same size and if
+ // every frame in each is identical to the corresponding frame in the other.
+ bool IsEqual(const CallStack &target);
+
+ typedef std::basic_string<char, std::char_traits<char>,
+ PrivateHookAllocator<char> > PrivateAllocatorString;
+
+ // Convert the callstack to a string stored in output.
+ void CallStack::ToString(PrivateAllocatorString* output);
+
+ //
+ bool Valid() const { return valid_; }
+
+ private:
+ // The maximum number of frames to trace.
+ static const int kMaxTraceFrames = 32;
+
+ // Pushes a frame's program counter onto the CallStack.
+ void AddFrame(DWORD_PTR programcounter);
+
+ // Traces the stack, starting from this function, up to kMaxTraceFrames
+ // frames.
+ bool GetStackTrace();
+
+ // Functions for manipulating the frame list.
+ void ClearFrames();
+
+ // Dynamically load the DbgHelp library and supporting routines that we
+ // will use.
+ static bool LoadDbgHelp();
+
+ static void LockDbgHelp() {
+ dbghelp_lock_.Acquire();
+ active_thread_id_ = GetCurrentThreadId();
+ }
+
+ static void UnlockDbgHelp() {
+ active_thread_id_ = 0;
+ dbghelp_lock_.Release();
+ }
+
+ class AutoDbgHelpLock {
+ public:
+ AutoDbgHelpLock() {
+ CallStack::LockDbgHelp();
+ }
+ ~AutoDbgHelpLock() {
+ CallStack::UnlockDbgHelp();
+ }
+ };
+
+ // Check to see if this thread is already processing a stack.
+ bool LockedRecursionDetected() const;
+
+ // According to http://msdn2.microsoft.com/en-us/library/ms680650(VS.85).aspx
+ // "All DbgHelp functions, such as this one, are single threaded. Therefore,
+ // calls from more than one thread to this function will likely result in
+ // unexpected behavior or memory corruption. To avoid this, you must
+ // synchromize all concurrent calls from one thread to this function."
+ //
+ // dbghelp_lock_ is used to serialize access across all calls to the DbgHelp
+ // library. This may be overly conservative (serializing them all together),
+ // but does guarantee correctness.
+ static base::Lock dbghelp_lock_;
+
+ // Record the fact that dbghelp has been loaded.
+ // Changes to this variable are protected by dbghelp_lock_.
+ // It will only changes once... from false to true.
+ static bool dbghelp_loaded_;
+
+ // To prevent infinite recursion due to unexpected side effects in libraries,
+ // we track the thread_id of the thread currently holding the dbghelp_lock_.
+ // We avoid re-aquiring said lock and return an !valid_ instance when we
+ // detect recursion.
+ static DWORD active_thread_id_;
+
+ int frame_count_; // Current size (in frames)
+ DWORD_PTR frames_[kMaxTraceFrames];
+ int32 hash_;
+ int32 id_;
+
+ // Indicate is this is a valid stack.
+ // This is false if recursion precluded a real stack generation.
+ bool valid_;
+
+ // Cache ProgramCounter -> Symbol lookups.
+ // This cache is not thread safe.
+ typedef std::map<int32, PrivateAllocatorString, std::less<int32>,
+ PrivateHookAllocator<int32> > SymbolCache;
+ static SymbolCache* symbol_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallStack);
+};
+
+// An AllocationStack is a type of CallStack which represents a CallStack where
+// memory has been allocated. This class is also a list item, so that it can
+// be easilly allocated and deallocated from its static singly-linked-list of
+// free instances.
+class AllocationStack : public CallStack {
+ public:
+ explicit AllocationStack(int32 size)
+ : next_(NULL), size_(size), CallStack() {}
+
+ // We maintain a freelist of the AllocationStacks.
+ void* operator new(size_t s);
+ void operator delete(void*p);
+
+ int32 size() const { return size_; }
+
+ private:
+ AllocationStack* next_; // Pointer used when on the freelist.
+ int32 size_; // Size of block allocated.
+ static AllocationStack* freelist_;
+ static base::Lock freelist_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(AllocationStack);
+};
+
+#endif // TOOLS_MEMORY_WATCHER_CALL_STACK_H_
diff --git a/chromium/tools/memory_watcher/dllmain.cc b/chromium/tools/memory_watcher/dllmain.cc
new file mode 100644
index 00000000000..6bd91535d50
--- /dev/null
+++ b/chromium/tools/memory_watcher/dllmain.cc
@@ -0,0 +1,155 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The memory_watcher.dll is hooked by simply linking it. When we get the
+// windows notification that this DLL is loaded, we do a few things:
+// 1) Register a Hot Key.
+// Only one process can hook the Hot Key, so one will get it, and the
+// others will silently fail.
+// 2) Create a thread to wait on an event.
+// Since only one process will get the HotKey, it will be responsible for
+// notifying all process when it's time to do something. Each process
+// will have a thread waiting for communication from the master to dump
+// the callstacks.
+
+#include <windows.h>
+
+#include "base/at_exit.h"
+#include "tools/memory_watcher/memory_watcher.h"
+#include "tools/memory_watcher/hotkey.h"
+
+class MemoryWatcherDumpKey; // Defined below.
+
+static wchar_t* kDumpEvent = L"MemWatcher.DumpEvent";
+static base::AtExitManager* g_memory_watcher_exit_manager = NULL;
+static MemoryWatcher* g_memory_watcher = NULL;
+static MemoryWatcherDumpKey* g_hotkey_handler = NULL;
+static HANDLE g_dump_event = INVALID_HANDLE_VALUE;
+static HANDLE g_quit_event = INVALID_HANDLE_VALUE;
+static HANDLE g_watcher_thread = INVALID_HANDLE_VALUE;
+
+// A HotKey to dump the memory statistics.
+class MemoryWatcherDumpKey : public HotKeyHandler {
+ public:
+ MemoryWatcherDumpKey(UINT modifiers, UINT vkey)
+ : HotKeyHandler(modifiers, vkey) {}
+
+ virtual LRESULT OnHotKey(UINT, WPARAM, LPARAM, BOOL& bHandled) {
+ SetEvent(g_dump_event);
+ return 1;
+ }
+};
+
+// Creates the global memory watcher.
+void CreateMemoryWatcher() {
+ g_memory_watcher_exit_manager = new base::AtExitManager();
+ g_memory_watcher = new MemoryWatcher();
+ // Register ALT-CONTROL-D to Dump Memory stats.
+ g_hotkey_handler = new MemoryWatcherDumpKey(MOD_ALT|MOD_CONTROL, 0x44);
+}
+
+// Deletes the global memory watcher.
+void DeleteMemoryWatcher() {
+ if (g_hotkey_handler)
+ delete g_hotkey_handler;
+ g_hotkey_handler = NULL;
+ if (g_memory_watcher)
+ delete g_memory_watcher;
+ g_memory_watcher = NULL;
+
+ // Intentionly leak g_memory_watcher_exit_manager.
+}
+
+// Thread for watching for key events.
+DWORD WINAPI ThreadMain(LPVOID) {
+ bool stopping = false;
+ HANDLE events[2] = { g_dump_event, g_quit_event };
+ while (!stopping) {
+ DWORD rv = WaitForMultipleObjects(2, events, FALSE, INFINITE);
+ switch (rv) {
+ case WAIT_OBJECT_0:
+ if (g_memory_watcher) {
+ g_memory_watcher->DumpLeaks();
+ }
+ stopping = true;
+ break;
+ case WAIT_OBJECT_0 + 1:
+ stopping = true;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ return 0;
+}
+
+// Creates the background thread
+void CreateBackgroundThread() {
+ // Create a named event which can be used to notify
+ // all watched processes.
+ g_dump_event = CreateEvent(0, TRUE, FALSE, kDumpEvent);
+ DCHECK(g_dump_event != NULL);
+
+ // Create a local event which can be used to kill our
+ // background thread.
+ g_quit_event = CreateEvent(0, TRUE, FALSE, NULL);
+ DCHECK(g_quit_event != NULL);
+
+ // Create the background thread.
+ g_watcher_thread = CreateThread(0,
+ 0,
+ ThreadMain,
+ 0,
+ 0,
+ 0);
+ DCHECK(g_watcher_thread != NULL);
+}
+
+// Tell the background thread to stop.
+void StopBackgroundThread() {
+ // Send notification to our background thread.
+ SetEvent(g_quit_event);
+
+ // Wait for our background thread to die.
+ DWORD rv = WaitForSingleObject(g_watcher_thread, INFINITE);
+ DCHECK(rv == WAIT_OBJECT_0);
+
+ // Cleanup our global handles.
+ CloseHandle(g_quit_event);
+ CloseHandle(g_dump_event);
+ CloseHandle(g_watcher_thread);
+}
+
+bool IsChromeExe() {
+ return GetModuleHandleA("chrome.exe") != NULL;
+}
+
+extern "C" {
+// DllMain is the windows entry point to this DLL.
+// We use the entry point as the mechanism for starting and stopping
+// the MemoryWatcher.
+BOOL WINAPI DllMain(HINSTANCE dll_instance, DWORD reason,
+ LPVOID reserved) {
+ if (!IsChromeExe())
+ return FALSE;
+
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ CreateMemoryWatcher();
+ CreateBackgroundThread();
+ break;
+ case DLL_PROCESS_DETACH:
+ DeleteMemoryWatcher();
+ StopBackgroundThread();
+ break;
+ }
+ return TRUE;
+}
+
+__declspec(dllexport) void __cdecl SetLogName(char* name) {
+ g_memory_watcher->SetLogName(name);
+}
+
+} // extern "C"
diff --git a/chromium/tools/memory_watcher/hotkey.h b/chromium/tools/memory_watcher/hotkey.h
new file mode 100644
index 00000000000..0348062e6a4
--- /dev/null
+++ b/chromium/tools/memory_watcher/hotkey.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_MEMORY_WATCHER_HOTKEY_H_
+#define TOOLS_MEMORY_WATCHER_HOTKEY_H_
+
+#include "ui/base/win/window_impl.h"
+#include "ui/gfx/rect.h"
+
+// HotKey handler.
+// Programs wishing to register a hotkey can use this.
+class HotKeyHandler : public ui::WindowImpl {
+ public:
+ HotKeyHandler(UINT modifiers, UINT vk)
+ : modifiers_(modifiers),
+ vkey_(vk) {
+ Start();
+ }
+ ~HotKeyHandler() { Stop(); }
+
+ BEGIN_MSG_MAP_EX(HotKeyHandler)
+ MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
+ END_MSG_MAP()
+
+ private:
+ static const int hotkey_id = 0x0000baba;
+
+ bool Start() {
+ set_window_style(WS_POPUP);
+ Init(NULL, gfx::Rect());
+ return RegisterHotKey(hwnd(), hotkey_id, modifiers_, vkey_) == TRUE;
+ }
+
+ void Stop() {
+ UnregisterHotKey(hwnd(), hotkey_id);
+ DestroyWindow(hwnd());
+ }
+
+ // Handle the registered Hotkey being pressed.
+ virtual LRESULT OnHotKey(UINT /*uMsg*/, WPARAM /*wParam*/,
+ LPARAM /*lParam*/, BOOL& bHandled) = 0;
+
+ UINT modifiers_;
+ UINT vkey_;
+};
+
+#endif // TOOLS_MEMORY_WATCHER_HOTKEY_H_
diff --git a/chromium/tools/memory_watcher/ia32_modrm_map.cc b/chromium/tools/memory_watcher/ia32_modrm_map.cc
new file mode 100644
index 00000000000..5c4ec3f2ff4
--- /dev/null
+++ b/chromium/tools/memory_watcher/ia32_modrm_map.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Table of relevant information about how to decode the ModR/M byte.
+ * Based on information in the IA 32 Intel Architecture
+ * Software Developer's Manual Volume 2: Instruction Set Reference.
+ */
+
+#include "mini_disassembler.h"
+#include "mini_disassembler_types.h"
+
+namespace sidestep {
+
+const ModrmEntry MiniDisassembler::s_ia16_modrm_map_[] = {
+// mod == 00
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { true, false, OS_WORD },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+// mod == 01
+ /* r/m == 000 */ { true, false, OS_BYTE },
+ /* r/m == 001 */ { true, false, OS_BYTE },
+ /* r/m == 010 */ { true, false, OS_BYTE },
+ /* r/m == 011 */ { true, false, OS_BYTE },
+ /* r/m == 100 */ { true, false, OS_BYTE },
+ /* r/m == 101 */ { true, false, OS_BYTE },
+ /* r/m == 110 */ { true, false, OS_BYTE },
+ /* r/m == 111 */ { true, false, OS_BYTE },
+// mod == 10
+ /* r/m == 000 */ { true, false, OS_WORD },
+ /* r/m == 001 */ { true, false, OS_WORD },
+ /* r/m == 010 */ { true, false, OS_WORD },
+ /* r/m == 011 */ { true, false, OS_WORD },
+ /* r/m == 100 */ { true, false, OS_WORD },
+ /* r/m == 101 */ { true, false, OS_WORD },
+ /* r/m == 110 */ { true, false, OS_WORD },
+ /* r/m == 111 */ { true, false, OS_WORD },
+// mod == 11
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO }
+};
+
+const ModrmEntry MiniDisassembler::s_ia32_modrm_map_[] = {
+// mod == 00
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, true, OS_ZERO },
+ /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+// mod == 01
+ /* r/m == 000 */ { true, false, OS_BYTE },
+ /* r/m == 001 */ { true, false, OS_BYTE },
+ /* r/m == 010 */ { true, false, OS_BYTE },
+ /* r/m == 011 */ { true, false, OS_BYTE },
+ /* r/m == 100 */ { true, true, OS_BYTE },
+ /* r/m == 101 */ { true, false, OS_BYTE },
+ /* r/m == 110 */ { true, false, OS_BYTE },
+ /* r/m == 111 */ { true, false, OS_BYTE },
+// mod == 10
+ /* r/m == 000 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 001 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 010 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 011 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 100 */ { true, true, OS_DOUBLE_WORD },
+ /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 110 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 111 */ { true, false, OS_DOUBLE_WORD },
+// mod == 11
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+};
+
+}; // namespace sidestep
diff --git a/chromium/tools/memory_watcher/ia32_opcode_map.cc b/chromium/tools/memory_watcher/ia32_opcode_map.cc
new file mode 100644
index 00000000000..6fb15d81089
--- /dev/null
+++ b/chromium/tools/memory_watcher/ia32_opcode_map.cc
@@ -0,0 +1,1161 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Opcode decoding maps. Based on the IA-32 Intel Architecture
+ * Software Developer's Manual Volume 2: Instruction Set Reference. Idea
+ * for how to lay out the tables in memory taken from the implementation
+ * in the Bastard disassembly environment.
+ */
+
+#include "mini_disassembler.h"
+
+namespace sidestep {
+
+/*
+* This is the first table to be searched; the first field of each
+* Opcode in the table is either 0 to indicate you're in the
+* right table, or an index to the correct table, in the global
+* map g_pentiumOpcodeMap
+*/
+const Opcode s_first_opcode_byte[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF */ { 1, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x10 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x11 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x12 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x13 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x14 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x15 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x16 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x17 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x18 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x19 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1E */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1F */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x20 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x21 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x22 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x23 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x24 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x25 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x26 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x27 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "daa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x28 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x29 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "das", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x30 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x31 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x32 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x33 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x34 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x35 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x36 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x37 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aaa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x38 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x39 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aas", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x40 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x41 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x42 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x43 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x44 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x45 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x46 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x47 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x48 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x49 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x50 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x51 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x52 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x53 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x54 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x55 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x56 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x57 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x58 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x59 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x60 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x61 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x62 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_A, AM_NOT_USED, "bound", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x63 */ { 0, IT_GENERIC, AM_E | OT_W, AM_G | OT_W, AM_NOT_USED, "arpl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x64 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x65 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x66 */ { 0, IT_PREFIX_OPERAND, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x67 */ { 0, IT_PREFIX_ADDRESS, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x68 */ { 0, IT_GENERIC, AM_I | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x69 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_V, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6A */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_B, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6C */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "insb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6D */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "insd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6E */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X | OT_B, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X | OT_V, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x70 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x71 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x72 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x73 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x74 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x75 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x76 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x77 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x78 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x79 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7A */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7B */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7C */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7D */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7E */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7F */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x80 */ { 2, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x81 */ { 3, IT_REFERENCE, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x82 */ { 4, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x83 */ { 5, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x84 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x85 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x86 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x87 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x88 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x89 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8C */ { 0, IT_GENERIC, AM_E | OT_W, AM_S | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8D */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, "lea", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8E */ { 0, IT_GENERIC, AM_S | OT_W, AM_E | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8F */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x90 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "nop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x91 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x92 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x93 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x94 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x95 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x96 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x97 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x98 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cwde", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x99 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cdq", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9A */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "callf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9B */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wait", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9E */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_O | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_O | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA2 */ { 0, IT_GENERIC, AM_O | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA3 */ { 0, IT_GENERIC, AM_O | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA4 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "movsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA5 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "movsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA6 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "cmpsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA7 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "cmpsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAA */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "stosb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAB */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "stosd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X| OT_B, AM_NOT_USED, "lodsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X| OT_V, AM_NOT_USED, "lodsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAE */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_Y | OT_B, AM_NOT_USED, "scasb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_Y | OT_V, AM_NOT_USED, "scasd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB1 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB2 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB3 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB8 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBA */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBB */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBC */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBE */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC0 */ { 6, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC1 */ { 7, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC2 */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC3 */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC4 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "les", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "lds", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC8 */ { 0, IT_GENERIC, AM_I | OT_W, AM_I | OT_B, AM_NOT_USED, "enter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "leave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCA */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCB */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "int3", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCD */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "int", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCE */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "into", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCF */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "iret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD0 */ { 8, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD1 */ { 9, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD2 */ { 10, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD3 */ { 11, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD4 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aam", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD5 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "xlat", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+
+ // The following 8 lines would be references to the FPU tables, but we currently
+ // do not support the FPU instructions in this disassembler.
+
+ /* 0xD8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDA */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDB */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDC */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDD */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDE */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDF */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+
+
+ /* 0xE0 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE1 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE2 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE3 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jcxz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE6 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE7 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE8 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE9 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEA */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEB */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xED */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEF */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_V, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF0 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lock:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF2 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "repne:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF3 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rep:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF4 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "hlt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF6 */ { 12, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF7 */ { 13, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cli", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFB */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFD */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "std", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFE */ { 14, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFF */ { 15, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f[] = {
+ /* 0x0 */ { 16, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 17, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lsl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "invd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wbinvd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud2", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x10 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movups", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "movsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "movss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movupd" } },
+ /* 0x11 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movups", true,
+ /* F2h */ { 0, IT_GENERIC, AM_W | OT_SD, AM_V | OT_SD, AM_NOT_USED, "movsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_W | OT_SS, AM_V | OT_SS, AM_NOT_USED, "movss" },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movupd" } },
+ /* 0x12 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // only one of ...
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // ...these two is correct, Intel doesn't specify which
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_S, AM_NOT_USED, "movlpd" } },
+ /* 0x13 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlpd" } },
+ /* 0x14 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpcklps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpcklpd" } },
+ /* 0x15 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpckhps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpckhpd" } },
+ /* 0x16 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // only one of...
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // ...these two is correct, Intel doesn't specify which
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhpd" } },
+ /* 0x17 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhpd" } },
+ /* 0x18 */ { 18, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x19 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1C */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x20 */ { 0, IT_GENERIC, AM_R | OT_D, AM_C | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x21 */ { 0, IT_GENERIC, AM_R | OT_D, AM_D | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x22 */ { 0, IT_GENERIC, AM_C | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x23 */ { 0, IT_GENERIC, AM_D | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x24 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x25 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x26 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x27 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x28 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movaps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movapd" } },
+ /* 0x29 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movaps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movapd" } },
+ /* 0x2A */ { 0, IT_GENERIC, AM_V | OT_PS, AM_Q | OT_Q, AM_NOT_USED, "cvtpi2ps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_E | OT_D, AM_NOT_USED, "cvtsi2sd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_E | OT_D, AM_NOT_USED, "cvtsi2ss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_Q | OT_DQ, AM_NOT_USED, "cvtpi2pd" } },
+ /* 0x2B */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movntps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movntpd" } },
+ /* 0x2C */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvttps2pi", true,
+ /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvttsd2si" },
+ /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvttss2si" },
+ /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2pi" } },
+ /* 0x2D */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvtps2pi", true,
+ /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvtsd2si" },
+ /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvtss2si" },
+ /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2pi" } },
+ /* 0x2E */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "ucomiss", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "ucomisd" } },
+ /* 0x2F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_SS, AM_NOT_USED, "comiss", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "comisd" } },
+ /* 0x30 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wrmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x31 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdtsc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x32 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x33 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdpmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x34 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysenter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x35 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysexit", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x36 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x37 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x38 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x39 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x40 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x41 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x42 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x43 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x44 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x45 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x46 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x47 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmova", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x48 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x49 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4A */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4D */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4E */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4F */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x50 */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PS, AM_NOT_USED, "movmskps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PD, AM_NOT_USED, "movmskpd" } },
+ /* 0x51 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "sqrtps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "sqrtsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "sqrtss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "sqrtpd" } },
+ /* 0x52 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rsqrtps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rsqrtss" },
+ /* 66h */ { 0 } },
+ /* 0x53 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rcpps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rcpss" },
+ /* 66h */ { 0 } },
+ /* 0x54 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andpd" } },
+ /* 0x55 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andnps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andnpd" } },
+ /* 0x56 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "orps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "orpd" } },
+ /* 0x57 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "xorps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "xorpd" } },
+ /* 0x58 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "addps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "addsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "addss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "addpd" } },
+ /* 0x59 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "mulps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "mulsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "mulss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "mulpd" } },
+ /* 0x5A */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PS, AM_NOT_USED, "cvtps2pd", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "cvtsd2ss" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "cvtss2sd" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PD, AM_NOT_USED, "cvtpd2ps" } },
+ /* 0x5B */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2ps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvttps2dq" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvtps2dq" } },
+ /* 0x5C */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "subps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "subsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "subss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "subpd" } },
+ /* 0x5D */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "minps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "minsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "minss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "minpd" } },
+ /* 0x5E */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "divps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "divsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "divss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "divpd" } },
+ /* 0x5F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "maxps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "maxsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "maxss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "maxpd" } },
+ /* 0x60 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklbw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklbw" } },
+ /* 0x61 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklwd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklwd" } },
+ /* 0x62 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckldq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpckldq" } },
+ /* 0x63 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packsswb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packsswb" } },
+ /* 0x64 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtb" } },
+ /* 0x65 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtw" } },
+ /* 0x66 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtd" } },
+ /* 0x67 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packuswb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packuswb" } },
+ /* 0x68 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhbw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhbw" } },
+ /* 0x69 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhwd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhwd" } },
+ /* 0x6A */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhdq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhdq" } },
+ /* 0x6B */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packssdw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "packssdw" } },
+ /* 0x6C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
+ /* 0x6D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
+ /* 0x6E */ { 0, IT_GENERIC, AM_P | OT_D, AM_E | OT_D, AM_NOT_USED, "movd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_NOT_USED, "movd" } },
+ /* 0x6F */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "movq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqu" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqa" } },
+ /* 0x70 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_I | OT_B, "pshuf", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshuflw" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufhw" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufd" } },
+ /* 0x71 */ { 19, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x72 */ { 20, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x73 */ { 21, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x74 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqb" } },
+ /* 0x75 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqw" } },
+ /* 0x76 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqd" } },
+ /* 0x77 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "emms", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+
+ // The following six opcodes are escapes into the MMX stuff, which this disassembler does not support.
+ /* 0x78 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x79 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7A */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7B */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7C */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7D */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+
+ /* 0x7E */ { 0, IT_GENERIC, AM_E | OT_D, AM_P | OT_D, AM_NOT_USED, "movd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movq" },
+ /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_DQ, AM_NOT_USED, "movd" } },
+ /* 0x7F */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_P | OT_Q, AM_NOT_USED, "movq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqu" },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqa" } },
+ /* 0x80 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x81 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x82 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x83 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x84 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x85 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x86 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x87 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x88 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x89 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8A */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8B */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8C */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8D */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8E */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8F */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x90 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seto", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x91 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x92 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x93 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x94 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x95 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x96 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x97 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seta", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x98 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "sets", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x99 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9A */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9B */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9C */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9D */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9E */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9F */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cpuid", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA6 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA7 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rsm", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAC */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAD */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAE */ { 22, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB2 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lss", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB4 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lfs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB5 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lgs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB6 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB7 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud1", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBA */ { 23, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBC */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBD */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBE */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC2 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "cmpps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_I | OT_B, "cmpsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_I | OT_B, "cmpss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "cmppd" } },
+ /* 0xC3 */ { 0, IT_GENERIC, AM_E | OT_D, AM_G | OT_D, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_E | OT_D, AM_I | OT_B, "pinsrw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_I | OT_B, "pinsrw" } },
+ /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_I | OT_B, "pextrw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_I | OT_B, "pextrw" } },
+ /* 0xC6 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "shufps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "shufpd" } },
+ /* 0xC7 */ { 24, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC8 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC9 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCA */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCB */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCC */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCD */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCE */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCF */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlw" } },
+ /* 0xD2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrld", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrld" } },
+ /* 0xD3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlq" } },
+ /* 0xD4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddq" } },
+ /* 0xD5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmullw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmullw" } },
+ /* 0xD6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "unused without prefix", true,
+ /* F2h */ { 0, IT_GENERIC, AM_P | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movdq2q" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_Q | OT_Q, AM_NOT_USED, "movq2dq" },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movq" } },
+ /* 0xD7 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_NOT_USED, "pmovmskb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_NOT_USED, "pmovmskb" } },
+ /* 0xD8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusb" } },
+ /* 0xD9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusw" } },
+ /* 0xDA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminub", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminub" } },
+ /* 0xDB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pand", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pand" } },
+ /* 0xDC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusb" } },
+ /* 0xDD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusw" } },
+ /* 0xDE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxub", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxub" } },
+ /* 0xDF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pandn", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pandn" } },
+ /* 0xE0 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgb" } },
+ /* 0xE1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psraw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrqw" } },
+ /* 0xE2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrad", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrad" } },
+ /* 0xE3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgw" } },
+ /* 0xE4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhuw" } },
+ /* 0xE5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhw" } },
+ /* 0xE6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2dq" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2pd" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2dq" } },
+ /* 0xE7 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movntq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movntdq" } },
+ /* 0xE8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsb" } },
+ /* 0xE9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsw" } },
+ /* 0xEA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminsw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminsw" } },
+ /* 0xEB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "por", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "por" } },
+ /* 0xEC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsb" } },
+ /* 0xED */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsw" } },
+ /* 0xEE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxsw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxsw" } },
+ /* 0xEF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pxor", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pxor" } },
+ /* 0xF0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllw" } },
+ /* 0xF2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pslld", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pslld" } },
+ /* 0xF3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllq" } },
+ /* 0xF4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmuludq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmuludq" } },
+ /* 0xF5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaddwd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaddwd" } },
+ /* 0xF6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psadbw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psadbw" } },
+ /* 0xF7 */ { 0, IT_GENERIC, AM_P | OT_PI, AM_Q | OT_PI, AM_NOT_USED, "maskmovq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "maskmovdqu" } },
+ /* 0xF8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubb" } },
+ /* 0xF9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubw" } },
+ /* 0xFA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubd" } },
+ /* 0xFB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubq" } },
+ /* 0xFC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddb" } },
+ /* 0xFD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddw" } },
+ /* 0xFE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddd" } },
+ /* 0xFF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f00[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "sldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "str", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "ltr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f01[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "smsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lmsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_M | OT_B, AM_NOT_USED, AM_NOT_USED, "invlpg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f18[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f71[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlw" } },
+ /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psraw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psraw" } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllw" } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f72[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrld", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrld" } },
+ /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrad", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrad" } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "pslld", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslld" } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f73[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlq" } },
+ /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllq" } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq" } },
+};
+
+const Opcode s_opcode_byte_after_0fae[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxsave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxrstor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ldmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "mfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clflush/sfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+};
+
+const Opcode s_opcode_byte_after_0fba[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0fc7[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_Q, AM_NOT_USED, AM_NOT_USED, "cmpxch8b", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_80[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_81[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_82[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_83[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_c0[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_c1[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d0[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d1[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d2[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d3[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_f6[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_f7[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_fe[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_ff[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+/*
+* A table of all the other tables, containing some extra information, e.g.
+* how to mask out the byte we're looking at.
+*/
+const OpcodeTable MiniDisassembler::s_ia32_opcode_map_[]={
+ // One-byte opcodes and jumps to larger
+ /* 0 */ {s_first_opcode_byte, 0, 0xff, 0, 0xff},
+ // Two-byte opcodes (second byte)
+ /* 1 */ {s_opcode_byte_after_0f, 0, 0xff, 0, 0xff},
+ // Start of tables for opcodes using ModR/M bits as extension
+ /* 2 */ {s_opcode_byte_after_80, 3, 0x07, 0, 0x07},
+ /* 3 */ {s_opcode_byte_after_81, 3, 0x07, 0, 0x07},
+ /* 4 */ {s_opcode_byte_after_82, 3, 0x07, 0, 0x07},
+ /* 5 */ {s_opcode_byte_after_83, 3, 0x07, 0, 0x07},
+ /* 6 */ {s_opcode_byte_after_c0, 3, 0x07, 0, 0x07},
+ /* 7 */ {s_opcode_byte_after_c1, 3, 0x07, 0, 0x07},
+ /* 8 */ {s_opcode_byte_after_d0, 3, 0x07, 0, 0x07},
+ /* 9 */ {s_opcode_byte_after_d1, 3, 0x07, 0, 0x07},
+ /* 10 */ {s_opcode_byte_after_d2, 3, 0x07, 0, 0x07},
+ /* 11 */ {s_opcode_byte_after_d3, 3, 0x07, 0, 0x07},
+ /* 12 */ {s_opcode_byte_after_f6, 3, 0x07, 0, 0x07},
+ /* 13 */ {s_opcode_byte_after_f7, 3, 0x07, 0, 0x07},
+ /* 14 */ {s_opcode_byte_after_fe, 3, 0x07, 0, 0x01},
+ /* 15 */ {s_opcode_byte_after_ff, 3, 0x07, 0, 0x07},
+ /* 16 */ {s_opcode_byte_after_0f00, 3, 0x07, 0, 0x07},
+ /* 17 */ {s_opcode_byte_after_0f01, 3, 0x07, 0, 0x07},
+ /* 18 */ {s_opcode_byte_after_0f18, 3, 0x07, 0, 0x07},
+ /* 19 */ {s_opcode_byte_after_0f71, 3, 0x07, 0, 0x07},
+ /* 20 */ {s_opcode_byte_after_0f72, 3, 0x07, 0, 0x07},
+ /* 21 */ {s_opcode_byte_after_0f73, 3, 0x07, 0, 0x07},
+ /* 22 */ {s_opcode_byte_after_0fae, 3, 0x07, 0, 0x07},
+ /* 23 */ {s_opcode_byte_after_0fba, 3, 0x07, 0, 0x07},
+ /* 24 */ {s_opcode_byte_after_0fc7, 3, 0x07, 0, 0x01}
+};
+
+}; // namespace sidestep
diff --git a/chromium/tools/memory_watcher/memory_hook.cc b/chromium/tools/memory_watcher/memory_hook.cc
new file mode 100644
index 00000000000..b6ef00f7950
--- /dev/null
+++ b/chromium/tools/memory_watcher/memory_hook.cc
@@ -0,0 +1,562 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Static class for hooking Win32 API routines.
+
+// Some notes about how to hook Memory Allocation Routines in Windows.
+//
+// For our purposes we do not hook the libc routines. There are two
+// reasons for this. First, the libc routines all go through HeapAlloc
+// anyway. So, it's redundant to log both HeapAlloc and malloc.
+// Second, it can be tricky to hook in both static and dynamic linkages
+// of libc.
+
+#include <windows.h>
+
+#include "memory_hook.h"
+#include "memory_watcher.h"
+#include "preamble_patcher.h"
+
+// Calls GetProcAddress, but casts to the correct type.
+#define GET_PROC_ADDRESS(hmodule, name) \
+ ( (Type_##name)(::GetProcAddress(hmodule, #name)) )
+
+// Macro to declare Patch functions.
+#define DECLARE_PATCH(name) Patch<Type_##name> patch_##name
+
+// Macro to install Patch functions.
+#define INSTALL_PATCH(name) do { \
+ patch_##name.set_original(GET_PROC_ADDRESS(hkernel32, ##name)); \
+ patch_##name.Install(&Perftools_##name); \
+} while (0)
+
+// Macro to install Patch functions.
+#define INSTALL_NTDLLPATCH(name) do { \
+ patch_##name.set_original(GET_PROC_ADDRESS(hntdll, ##name)); \
+ patch_##name.Install(&Perftools_##name); \
+} while (0)
+
+// Macro to uninstall Patch functions.
+#define UNINSTALL_PATCH(name) patch_##name.Uninstall();
+
+
+
+// Windows APIs to be hooked
+
+// HeapAlloc routines
+typedef HANDLE (WINAPI *Type_HeapCreate)(DWORD flOptions,
+ SIZE_T dwInitialSize,
+ SIZE_T dwMaximumSize);
+typedef BOOL (WINAPI *Type_HeapDestroy)(HANDLE hHeap);
+typedef LPVOID (WINAPI *Type_HeapAlloc)(HANDLE hHeap, DWORD dwFlags,
+ DWORD_PTR dwBytes);
+typedef LPVOID (WINAPI *Type_HeapReAlloc)(HANDLE hHeap, DWORD dwFlags,
+ LPVOID lpMem, SIZE_T dwBytes);
+typedef BOOL (WINAPI *Type_HeapFree)(HANDLE hHeap, DWORD dwFlags,
+ LPVOID lpMem);
+
+// GlobalAlloc routines
+typedef HGLOBAL (WINAPI *Type_GlobalAlloc)(UINT uFlags, SIZE_T dwBytes);
+typedef HGLOBAL (WINAPI *Type_GlobalReAlloc)(HGLOBAL hMem, SIZE_T dwBytes,
+ UINT uFlags);
+typedef HGLOBAL (WINAPI *Type_GlobalFree)(HGLOBAL hMem);
+
+// LocalAlloc routines
+typedef HLOCAL (WINAPI *Type_LocalAlloc)(UINT uFlags, SIZE_T uBytes);
+typedef HLOCAL (WINAPI *Type_LocalReAlloc)(HLOCAL hMem, SIZE_T uBytes,
+ UINT uFlags);
+typedef HLOCAL (WINAPI *Type_LocalFree)(HLOCAL hMem);
+
+// A Windows-API equivalent of mmap and munmap, for "anonymous regions"
+typedef LPVOID (WINAPI *Type_VirtualAllocEx)(HANDLE process, LPVOID address,
+ SIZE_T size, DWORD type,
+ DWORD protect);
+typedef BOOL (WINAPI *Type_VirtualFreeEx)(HANDLE process, LPVOID address,
+ SIZE_T size, DWORD type);
+
+// A Windows-API equivalent of mmap and munmap, for actual files
+typedef LPVOID (WINAPI *Type_MapViewOfFile)(HANDLE hFileMappingObject,
+ DWORD dwDesiredAccess,
+ DWORD dwFileOffsetHigh,
+ DWORD dwFileOffsetLow,
+ SIZE_T dwNumberOfBytesToMap);
+typedef LPVOID (WINAPI *Type_MapViewOfFileEx)(HANDLE hFileMappingObject,
+ DWORD dwDesiredAccess,
+ DWORD dwFileOffsetHigh,
+ DWORD dwFileOffsetLow,
+ SIZE_T dwNumberOfBytesToMap,
+ LPVOID lpBaseAddress);
+typedef BOOL (WINAPI *Type_UnmapViewOfFile)(LPVOID lpBaseAddress);
+
+typedef DWORD (WINAPI *Type_NtUnmapViewOfSection)(HANDLE process,
+ LPVOID lpBaseAddress);
+
+
+// Patch is a template for keeping the pointer to the original
+// hooked routine, the function to call when hooked, and the
+// stub routine which is patched.
+template<class T>
+class Patch {
+ public:
+ // Constructor. Does not hook the function yet.
+ Patch<T>()
+ : original_function_(NULL),
+ patch_function_(NULL),
+ stub_function_(NULL) {
+ }
+
+ // Destructor. Unhooks the function if it has been hooked.
+ ~Patch<T>() {
+ Uninstall();
+ }
+
+ // Patches original function with func.
+ // Must have called set_original to set the original function.
+ void Install(T func) {
+ patch_function_ = func;
+ CHECK(patch_function_ != NULL);
+ CHECK(original_function_ != NULL);
+ CHECK(stub_function_ == NULL);
+ CHECK(sidestep::SIDESTEP_SUCCESS ==
+ sidestep::PreamblePatcher::Patch(original_function_,
+ patch_function_, &stub_function_));
+ }
+
+ // Un-patches the function.
+ void Uninstall() {
+ if (stub_function_)
+ sidestep::PreamblePatcher::Unpatch(original_function_,
+ patch_function_, stub_function_);
+ stub_function_ = NULL;
+ }
+
+ // Set the function to be patched.
+ void set_original(T original) { original_function_ = original; }
+
+ // Get the original function being patched.
+ T original() { return original_function_; }
+
+ // Get the patched function. (e.g. the replacement function)
+ T patched() { return patch_function_; }
+
+ // Access to the stub for calling the original function
+ // while it is patched.
+ T operator()() {
+ DCHECK(stub_function_);
+ return stub_function_;
+ }
+
+ private:
+ // The function that we plan to patch.
+ T original_function_;
+ // The function to replace the original with.
+ T patch_function_;
+ // To unpatch, we also need to keep around a "stub" that points to the
+ // pre-patched Windows function.
+ T stub_function_;
+};
+
+
+// All Windows memory-allocation routines call through to one of these.
+DECLARE_PATCH(HeapCreate);
+DECLARE_PATCH(HeapDestroy);
+DECLARE_PATCH(HeapAlloc);
+DECLARE_PATCH(HeapReAlloc);
+DECLARE_PATCH(HeapFree);
+DECLARE_PATCH(VirtualAllocEx);
+DECLARE_PATCH(VirtualFreeEx);
+DECLARE_PATCH(MapViewOfFile);
+DECLARE_PATCH(MapViewOfFileEx);
+DECLARE_PATCH(UnmapViewOfFile);
+DECLARE_PATCH(GlobalAlloc);
+DECLARE_PATCH(GlobalReAlloc);
+DECLARE_PATCH(GlobalFree);
+DECLARE_PATCH(LocalAlloc);
+DECLARE_PATCH(LocalReAlloc);
+DECLARE_PATCH(LocalFree);
+DECLARE_PATCH(NtUnmapViewOfSection);
+
+// Our replacement functions.
+
+static HANDLE WINAPI Perftools_HeapCreate(DWORD flOptions,
+ SIZE_T dwInitialSize,
+ SIZE_T dwMaximumSize) {
+ if (dwInitialSize > 4096)
+ dwInitialSize = 4096;
+ return patch_HeapCreate()(flOptions, dwInitialSize, dwMaximumSize);
+}
+
+static BOOL WINAPI Perftools_HeapDestroy(HANDLE hHeap) {
+ return patch_HeapDestroy()(hHeap);
+}
+
+static LPVOID WINAPI Perftools_HeapAlloc(HANDLE hHeap, DWORD dwFlags,
+ DWORD_PTR dwBytes) {
+ LPVOID rv = patch_HeapAlloc()(hHeap, dwFlags, dwBytes);
+ MemoryHook::hook()->OnTrack(hHeap, reinterpret_cast<int32>(rv), dwBytes);
+ return rv;
+}
+
+static BOOL WINAPI Perftools_HeapFree(HANDLE hHeap, DWORD dwFlags,
+ LPVOID lpMem) {
+ size_t size = 0;
+ if (lpMem != 0) {
+ size = HeapSize(hHeap, 0, lpMem); // Will crash if lpMem is 0.
+ // Note: size could be 0; HeapAlloc does allocate 0 length buffers.
+ }
+ MemoryHook::hook()->OnUntrack(hHeap, reinterpret_cast<int32>(lpMem), size);
+ return patch_HeapFree()(hHeap, dwFlags, lpMem);
+}
+
+static LPVOID WINAPI Perftools_HeapReAlloc(HANDLE hHeap, DWORD dwFlags,
+ LPVOID lpMem, SIZE_T dwBytes) {
+ // Don't call realloc, but instead do a free/malloc. The problem is that
+ // the builtin realloc may either expand a buffer, or it may simply
+ // just call free/malloc. If so, we will already have tracked the new
+ // block via Perftools_HeapAlloc.
+
+ LPVOID rv = Perftools_HeapAlloc(hHeap, dwFlags, dwBytes);
+ DCHECK_EQ((HEAP_REALLOC_IN_PLACE_ONLY & dwFlags), 0);
+
+ // If there was an old buffer, now copy the data to the new buffer.
+ if (lpMem != 0) {
+ size_t size = HeapSize(hHeap, 0, lpMem);
+ if (size > dwBytes)
+ size = dwBytes;
+ // Note: size could be 0; HeapAlloc does allocate 0 length buffers.
+ memcpy(rv, lpMem, size);
+ Perftools_HeapFree(hHeap, dwFlags, lpMem);
+ }
+ return rv;
+}
+
+static LPVOID WINAPI Perftools_VirtualAllocEx(HANDLE process, LPVOID address,
+ SIZE_T size, DWORD type,
+ DWORD protect) {
+ bool already_committed = false;
+ if (address != NULL) {
+ MEMORY_BASIC_INFORMATION info;
+ CHECK(VirtualQuery(address, &info, sizeof(info)));
+ if (info.State & MEM_COMMIT) {
+ already_committed = true;
+ CHECK(size >= info.RegionSize);
+ }
+ }
+ bool reserving = (address == NULL) || (type & MEM_RESERVE);
+ bool committing = !already_committed && (type & MEM_COMMIT);
+
+
+ LPVOID result = patch_VirtualAllocEx()(process, address, size, type,
+ protect);
+ MEMORY_BASIC_INFORMATION info;
+ CHECK(VirtualQuery(result, &info, sizeof(info)));
+ size = info.RegionSize;
+
+ if (committing)
+ MemoryHook::hook()->OnTrack(0, reinterpret_cast<int32>(result), size);
+
+ return result;
+}
+
+static BOOL WINAPI Perftools_VirtualFreeEx(HANDLE process, LPVOID address,
+ SIZE_T size, DWORD type) {
+ int chunk_size = size;
+ MEMORY_BASIC_INFORMATION info;
+ CHECK(VirtualQuery(address, &info, sizeof(info)));
+ if (chunk_size == 0)
+ chunk_size = info.RegionSize;
+ bool decommit = (info.State & MEM_COMMIT);
+
+ if (decommit)
+ MemoryHook::hook()->OnUntrack(0, reinterpret_cast<int32>(address),
+ chunk_size);
+
+ return patch_VirtualFreeEx()(process, address, size, type);
+}
+
+static base::Lock known_maps_lock;
+static std::map<void*, int> known_maps;
+
+static LPVOID WINAPI Perftools_MapViewOfFileEx(HANDLE hFileMappingObject,
+ DWORD dwDesiredAccess,
+ DWORD dwFileOffsetHigh,
+ DWORD dwFileOffsetLow,
+ SIZE_T dwNumberOfBytesToMap,
+ LPVOID lpBaseAddress) {
+ // For this function pair, you always deallocate the full block of
+ // data that you allocate, so NewHook/DeleteHook is the right API.
+ LPVOID result = patch_MapViewOfFileEx()(hFileMappingObject, dwDesiredAccess,
+ dwFileOffsetHigh, dwFileOffsetLow,
+ dwNumberOfBytesToMap, lpBaseAddress);
+ {
+ base::AutoLock lock(known_maps_lock);
+ MEMORY_BASIC_INFORMATION info;
+ if (known_maps.find(result) == known_maps.end()) {
+ CHECK(VirtualQuery(result, &info, sizeof(info)));
+ // TODO(mbelshe): THIS map uses the standard heap!!!!
+ known_maps[result] = 1;
+ MemoryHook::hook()->OnTrack(0, reinterpret_cast<int32>(result),
+ info.RegionSize);
+ } else {
+ known_maps[result] = known_maps[result] + 1;
+ }
+ }
+ return result;
+}
+
+static LPVOID WINAPI Perftools_MapViewOfFile(HANDLE hFileMappingObject,
+ DWORD dwDesiredAccess,
+ DWORD dwFileOffsetHigh,
+ DWORD dwFileOffsetLow,
+ SIZE_T dwNumberOfBytesToMap) {
+ return Perftools_MapViewOfFileEx(hFileMappingObject, dwDesiredAccess,
+ dwFileOffsetHigh, dwFileOffsetLow,
+ dwNumberOfBytesToMap, 0);
+}
+
+static BOOL WINAPI Perftools_UnmapViewOfFile(LPVOID lpBaseAddress) {
+ // This will call into NtUnmapViewOfSection().
+ return patch_UnmapViewOfFile()(lpBaseAddress);
+}
+
+static DWORD WINAPI Perftools_NtUnmapViewOfSection(HANDLE process,
+ LPVOID lpBaseAddress) {
+ // Some windows APIs call directly into this routine rather
+ // than calling UnmapViewOfFile. If we didn't trap this function,
+ // then we appear to have bogus leaks.
+ {
+ base::AutoLock lock(known_maps_lock);
+ MEMORY_BASIC_INFORMATION info;
+ CHECK(VirtualQuery(lpBaseAddress, &info, sizeof(info)));
+ if (known_maps.find(lpBaseAddress) != known_maps.end()) {
+ if (known_maps[lpBaseAddress] == 1) {
+ MemoryHook::hook()->OnUntrack(0, reinterpret_cast<int32>(lpBaseAddress),
+ info.RegionSize);
+ known_maps.erase(lpBaseAddress);
+ } else {
+ known_maps[lpBaseAddress] = known_maps[lpBaseAddress] - 1;
+ }
+ }
+ }
+ return patch_NtUnmapViewOfSection()(process, lpBaseAddress);
+}
+
+static HGLOBAL WINAPI Perftools_GlobalAlloc(UINT uFlags, SIZE_T dwBytes) {
+ // GlobalAlloc is built atop HeapAlloc anyway. So we don't track these.
+ // GlobalAlloc will internally call into HeapAlloc and we track there.
+
+ // Force all memory to be fixed.
+ uFlags &= ~GMEM_MOVEABLE;
+ HGLOBAL rv = patch_GlobalAlloc()(uFlags, dwBytes);
+ return rv;
+}
+
+static HGLOBAL WINAPI Perftools_GlobalFree(HGLOBAL hMem) {
+ return patch_GlobalFree()(hMem);
+}
+
+static HGLOBAL WINAPI Perftools_GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes,
+ UINT uFlags) {
+ // TODO(jar): [The following looks like a copy/paste typo from LocalRealloc.]
+ // GlobalDiscard is a macro which calls LocalReAlloc with size 0.
+ if (dwBytes == 0) {
+ return patch_GlobalReAlloc()(hMem, dwBytes, uFlags);
+ }
+
+ HGLOBAL rv = Perftools_GlobalAlloc(uFlags, dwBytes);
+ if (hMem != 0) {
+ size_t size = GlobalSize(hMem);
+ if (size > dwBytes)
+ size = dwBytes;
+ // Note: size could be 0; HeapAlloc does allocate 0 length buffers.
+ memcpy(rv, hMem, size);
+ Perftools_GlobalFree(hMem);
+ }
+
+ return rv;
+}
+
+static HLOCAL WINAPI Perftools_LocalAlloc(UINT uFlags, SIZE_T dwBytes) {
+ // LocalAlloc is built atop HeapAlloc anyway. So we don't track these.
+ // LocalAlloc will internally call into HeapAlloc and we track there.
+
+ // Force all memory to be fixed.
+ uFlags &= ~LMEM_MOVEABLE;
+ HLOCAL rv = patch_LocalAlloc()(uFlags, dwBytes);
+ return rv;
+}
+
+static HLOCAL WINAPI Perftools_LocalFree(HLOCAL hMem) {
+ return patch_LocalFree()(hMem);
+}
+
+static HLOCAL WINAPI Perftools_LocalReAlloc(HLOCAL hMem, SIZE_T dwBytes,
+ UINT uFlags) {
+ // LocalDiscard is a macro which calls LocalReAlloc with size 0.
+ if (dwBytes == 0) {
+ return patch_LocalReAlloc()(hMem, dwBytes, uFlags);
+ }
+
+ HGLOBAL rv = Perftools_LocalAlloc(uFlags, dwBytes);
+ if (hMem != 0) {
+ size_t size = LocalSize(hMem);
+ if (size > dwBytes)
+ size = dwBytes;
+ // Note: size could be 0; HeapAlloc does allocate 0 length buffers.
+ memcpy(rv, hMem, size);
+ Perftools_LocalFree(hMem);
+ }
+
+ return rv;
+}
+
+bool MemoryHook::hooked_ = false;
+MemoryHook* MemoryHook::global_hook_ = NULL;
+
+MemoryHook::MemoryHook()
+ : watcher_(NULL),
+ heap_(NULL) {
+ CreateHeap();
+}
+
+MemoryHook::~MemoryHook() {
+ // It's a bit dangerous to ever close this heap; MemoryWatchers may have
+ // used this heap for their tracking data. Closing the heap while any
+ // MemoryWatchers still exist is pretty dangerous.
+ CloseHeap();
+}
+
+bool MemoryHook::Initialize() {
+ if (global_hook_ == NULL)
+ global_hook_ = new MemoryHook();
+ return true;
+}
+
+bool MemoryHook::Hook() {
+ DCHECK(!hooked_);
+ if (!hooked_) {
+ DCHECK(global_hook_);
+
+ // Luckily, Patch() doesn't call malloc or windows alloc routines
+ // itself -- though it does call new (we can use PatchWithStub to
+ // get around that, and will need to if we need to patch new).
+
+ HMODULE hkernel32 = ::GetModuleHandle(L"kernel32");
+ CHECK(hkernel32 != NULL);
+
+ HMODULE hntdll = ::GetModuleHandle(L"ntdll");
+ CHECK(hntdll != NULL);
+
+ // Now that we've found all the functions, patch them
+ INSTALL_PATCH(HeapCreate);
+ INSTALL_PATCH(HeapDestroy);
+ INSTALL_PATCH(HeapAlloc);
+ INSTALL_PATCH(HeapReAlloc);
+ INSTALL_PATCH(HeapFree);
+ INSTALL_PATCH(VirtualAllocEx);
+ INSTALL_PATCH(VirtualFreeEx);
+ INSTALL_PATCH(MapViewOfFileEx);
+ INSTALL_PATCH(MapViewOfFile);
+ INSTALL_PATCH(UnmapViewOfFile);
+ INSTALL_NTDLLPATCH(NtUnmapViewOfSection);
+ INSTALL_PATCH(GlobalAlloc);
+ INSTALL_PATCH(GlobalReAlloc);
+ INSTALL_PATCH(GlobalFree);
+ INSTALL_PATCH(LocalAlloc);
+ INSTALL_PATCH(LocalReAlloc);
+ INSTALL_PATCH(LocalFree);
+
+ // We are finally completely hooked.
+ hooked_ = true;
+ }
+ return true;
+}
+
+bool MemoryHook::Unhook() {
+ if (hooked_) {
+ // We need to go back to the system malloc/etc at global destruct time,
+ // so objects that were constructed before tcmalloc, using the system
+ // malloc, can destroy themselves using the system free. This depends
+ // on DLLs unloading in the reverse order in which they load!
+ //
+ // We also go back to the default HeapAlloc/etc, just for consistency.
+ // Who knows, it may help avoid weird bugs in some situations.
+ UNINSTALL_PATCH(HeapCreate);
+ UNINSTALL_PATCH(HeapDestroy);
+ UNINSTALL_PATCH(HeapAlloc);
+ UNINSTALL_PATCH(HeapReAlloc);
+ UNINSTALL_PATCH(HeapFree);
+ UNINSTALL_PATCH(VirtualAllocEx);
+ UNINSTALL_PATCH(VirtualFreeEx);
+ UNINSTALL_PATCH(MapViewOfFile);
+ UNINSTALL_PATCH(MapViewOfFileEx);
+ UNINSTALL_PATCH(UnmapViewOfFile);
+ UNINSTALL_PATCH(NtUnmapViewOfSection);
+ UNINSTALL_PATCH(GlobalAlloc);
+ UNINSTALL_PATCH(GlobalReAlloc);
+ UNINSTALL_PATCH(GlobalFree);
+ UNINSTALL_PATCH(LocalAlloc);
+ UNINSTALL_PATCH(LocalReAlloc);
+ UNINSTALL_PATCH(LocalFree);
+
+ hooked_ = false;
+ }
+ return true;
+}
+
+bool MemoryHook::RegisterWatcher(MemoryObserver* watcher) {
+ DCHECK(global_hook_->watcher_ == NULL);
+
+ if (!hooked_)
+ Hook();
+
+ DCHECK(global_hook_);
+ global_hook_->watcher_ = watcher;
+ return true;
+}
+
+bool MemoryHook::UnregisterWatcher(MemoryObserver* watcher) {
+ DCHECK(hooked_);
+ DCHECK(global_hook_->watcher_ == watcher);
+ // TODO(jar): changing watcher_ here is very racy. Other threads may (without
+ // a lock) testing, and then calling through this value. We probably can't
+ // remove this until we are single threaded.
+ global_hook_->watcher_ = NULL;
+
+ // For now, since there are no more watchers, unhook memory.
+ return Unhook();
+}
+
+bool MemoryHook::CreateHeap() {
+ // Create a heap for our own memory.
+ DCHECK(heap_ == NULL);
+ heap_ = HeapCreate(0, 0, 0);
+ DCHECK(heap_ != NULL);
+ return heap_ != NULL;
+}
+
+bool MemoryHook::CloseHeap() {
+ DCHECK(heap_ != NULL);
+ HeapDestroy(heap_);
+ heap_ = NULL;
+ return true;
+}
+
+void MemoryHook::OnTrack(HANDLE heap, int32 id, int32 size) {
+ // Don't notify about allocations to our internal heap.
+ if (heap == heap_)
+ return;
+
+ if (watcher_)
+ watcher_->OnTrack(heap, id, size);
+}
+
+void MemoryHook::OnUntrack(HANDLE heap, int32 id, int32 size) {
+ // Don't notify about allocations to our internal heap.
+ if (heap == heap_)
+ return;
+
+ if (watcher_)
+ watcher_->OnUntrack(heap, id, size);
+}
diff --git a/chromium/tools/memory_watcher/memory_hook.h b/chromium/tools/memory_watcher/memory_hook.h
new file mode 100644
index 00000000000..4227edb7ca4
--- /dev/null
+++ b/chromium/tools/memory_watcher/memory_hook.h
@@ -0,0 +1,153 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Static class for hooking Win32 API routines. For now,
+// we only add one watcher at a time.
+//
+// TODO(mbelshe): Support multiple watchers.
+
+#ifndef MEMORY_WATCHER_MEMORY_HOOK_
+#define MEMORY_WATCHER_MEMORY_HOOK_
+
+#include "base/logging.h"
+
+// When allocating memory for internal use with the MemoryHook,
+// we must always use the MemoryHook's heap; otherwise, the memory
+// gets tracked, and it becomes an infinite loop (allocation() calls
+// MemoryHook() which calls allocation(), etc).
+//
+// PrivateHookAllocator is an STL-friendly Allocator so that STL lists,
+// maps, etc can be used on the global MemoryHook's heap.
+template <class T>
+class PrivateHookAllocator {
+ public:
+ // These type definitions are needed for stl allocators.
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+
+ PrivateHookAllocator() {}
+
+ // Allocate memory for STL.
+ pointer allocate(size_type n, const void * = 0) {
+ return reinterpret_cast<T*>(MemoryHook::Alloc(n * sizeof(T)));
+ }
+
+ // Deallocate memory for STL.
+ void deallocate(void* p, size_type) {
+ if (p)
+ MemoryHook::Free(p);
+ }
+
+ // Construct the object
+ void construct(pointer p, const T& val) {
+ new (reinterpret_cast<T*>(p))T(val);
+ }
+
+ // Destruct an object
+ void destroy(pointer p) { p->~T(); }
+
+ size_type max_size() const { return size_t(-1); }
+
+ template <class U>
+ struct rebind { typedef PrivateHookAllocator<U> other; };
+
+ template <class U>
+ PrivateHookAllocator(const PrivateHookAllocator<U>&) {}
+};
+
+template<class T, class U> inline
+bool operator==(const PrivateHookAllocator<T>&,
+ const PrivateHookAllocator<U>&) {
+ return (true);
+}
+
+template<class T, class U> inline
+bool operator!=(const PrivateHookAllocator<T>& left,
+ const PrivateHookAllocator<U>& right) {
+ return (!(left == right));
+}
+
+
+// Classes which monitor memory from these hooks implement
+// the MemoryObserver interface.
+class MemoryObserver {
+ public:
+ virtual ~MemoryObserver() {}
+
+ // Track a pointer. Will capture the current StackTrace.
+ virtual void OnTrack(HANDLE heap, int32 id, int32 size) = 0;
+
+ // Untrack a pointer, removing it from our list.
+ virtual void OnUntrack(HANDLE heap, int32 id, int32 size) = 0;
+};
+
+class MemoryHook : MemoryObserver {
+ public:
+ // Initialize the MemoryHook. Must be called before
+ // registering watchers. This can be called repeatedly,
+ // but is not thread safe.
+ static bool Initialize();
+
+ // Returns true is memory allocations and deallocations
+ // are being traced.
+ static bool hooked() { return hooked_ != NULL; }
+
+ // Register a class to receive memory allocation & deallocation
+ // callbacks. If we haven't hooked memory yet, this call will
+ // force memory hooking to start.
+ static bool RegisterWatcher(MemoryObserver* watcher);
+
+ // Register a class to stop receiving callbacks. If there are
+ // no more watchers, this call will unhook memory.
+ static bool UnregisterWatcher(MemoryObserver* watcher);
+
+ // MemoryHook provides a private heap for allocating
+ // unwatched memory.
+ static void* Alloc(size_t size) {
+ DCHECK(global_hook_ && global_hook_->heap_);
+ return HeapAlloc(global_hook_->heap_, 0, size);
+ }
+ static void Free(void* ptr) {
+ DCHECK(global_hook_ && global_hook_->heap_);
+ HeapFree(global_hook_->heap_, 0, ptr);
+ }
+
+ // Access the global hook. For internal use only from static "C"
+ // hooks.
+ static MemoryHook* hook() { return global_hook_; }
+
+ // MemoryObserver interface.
+ virtual void OnTrack(HANDLE hHeap, int32 id, int32 size);
+ virtual void OnUntrack(HANDLE hHeap, int32 id, int32 size);
+
+ private:
+ MemoryHook();
+ ~MemoryHook();
+
+ // Enable memory tracing. When memory is 'hooked',
+ // MemoryWatchers which have registered will be called
+ // as memory is allocated and deallocated.
+ static bool Hook();
+
+ // Disables memory tracing.
+ static bool Unhook();
+
+ // Create our private heap
+ bool CreateHeap();
+
+ // Close our private heap.
+ bool CloseHeap();
+
+ MemoryObserver* watcher_;
+ HANDLE heap_; // An internal accounting heap.
+ static bool hooked_;
+ static MemoryHook* global_hook_;
+};
+
+#endif // MEMORY_WATCHER_MEMORY_HOOK_
diff --git a/chromium/tools/memory_watcher/memory_watcher.cc b/chromium/tools/memory_watcher/memory_watcher.cc
new file mode 100644
index 00000000000..4743a37840c
--- /dev/null
+++ b/chromium/tools/memory_watcher/memory_watcher.cc
@@ -0,0 +1,255 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <windows.h>
+#include <tlhelp32.h> // for CreateToolhelp32Snapshot()
+#include <map>
+
+#include "tools/memory_watcher/memory_watcher.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/metrics/stats_counters.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
+#include "tools/memory_watcher/call_stack.h"
+#include "tools/memory_watcher/preamble_patcher.h"
+
+static base::StatsCounter mem_in_use("MemoryInUse.Bytes");
+static base::StatsCounter mem_in_use_blocks("MemoryInUse.Blocks");
+static base::StatsCounter mem_in_use_allocs("MemoryInUse.Allocs");
+static base::StatsCounter mem_in_use_frees("MemoryInUse.Frees");
+
+// ---------------------------------------------------------------------
+
+MemoryWatcher::MemoryWatcher()
+ : file_(NULL),
+ hooked_(false),
+ active_thread_id_(0) {
+ MemoryHook::Initialize();
+ CallStack::Initialize();
+
+ block_map_ = new CallStackMap();
+
+ // Register last - only after we're ready for notifications!
+ Hook();
+}
+
+MemoryWatcher::~MemoryWatcher() {
+ Unhook();
+
+ CloseLogFile();
+
+ // Pointers in the block_map are part of the MemoryHook heap. Be sure
+ // to delete the map before closing the heap.
+ delete block_map_;
+}
+
+void MemoryWatcher::Hook() {
+ DCHECK(!hooked_);
+ MemoryHook::RegisterWatcher(this);
+ hooked_ = true;
+}
+
+void MemoryWatcher::Unhook() {
+ if (hooked_) {
+ MemoryHook::UnregisterWatcher(this);
+ hooked_ = false;
+ }
+}
+
+void MemoryWatcher::OpenLogFile() {
+ DCHECK(file_ == NULL);
+ file_name_ = "memwatcher";
+ if (!log_name_.empty()) {
+ file_name_ += ".";
+ file_name_ += log_name_;
+ }
+ file_name_ += ".log";
+ char buf[16];
+ file_name_ += _itoa(GetCurrentProcessId(), buf, 10);
+
+ std::string tmp_name(file_name_);
+ tmp_name += ".tmp";
+ file_ = fopen(tmp_name.c_str(), "w+");
+}
+
+void MemoryWatcher::CloseLogFile() {
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ std::wstring tmp_name = ASCIIToWide(file_name_);
+ tmp_name += L".tmp";
+ base::Move(base::FilePath(tmp_name),
+ base::FilePath(ASCIIToWide(file_name_)));
+ }
+}
+
+bool MemoryWatcher::LockedRecursionDetected() const {
+ if (!active_thread_id_) return false;
+ DWORD thread_id = GetCurrentThreadId();
+ // TODO(jar): Perchance we should use atomic access to member.
+ return thread_id == active_thread_id_;
+}
+
+void MemoryWatcher::OnTrack(HANDLE heap, int32 id, int32 size) {
+ // Don't track zeroes. It's a waste of time.
+ if (size == 0)
+ return;
+
+ if (LockedRecursionDetected())
+ return;
+
+ // AllocationStack overrides new/delete to not allocate
+ // from the main heap.
+ AllocationStack* stack = new AllocationStack(size);
+ if (!stack->Valid()) return; // Recursion blocked generation of stack.
+
+ {
+ base::AutoLock lock(block_map_lock_);
+
+ // Ideally, we'd like to verify that the block being added
+ // here is not already in our list of tracked blocks. However,
+ // the lookup in our hash table is expensive and slows us too
+ // much.
+ CallStackMap::iterator block_it = block_map_->find(id);
+ if (block_it != block_map_->end()) {
+#if 0 // Don't do this until stack->ToString() uses ONLY our heap.
+ active_thread_id_ = GetCurrentThreadId();
+ PrivateAllocatorString output;
+ block_it->second->ToString(&output);
+ // VLOG(1) << "First Stack size " << stack->size() << "was\n" << output;
+ stack->ToString(&output);
+ // VLOG(1) << "Second Stack size " << stack->size() << "was\n" << output;
+#endif // 0
+
+ // TODO(jar): We should delete one stack, and keep the other, perhaps
+ // based on size.
+ // For now, just delete the first, and keep the second?
+ delete block_it->second;
+ }
+ // TODO(jar): Perchance we should use atomic access to member.
+ active_thread_id_ = 0; // Note: Only do this AFTER exiting above scope!
+
+ (*block_map_)[id] = stack;
+ }
+
+ mem_in_use.Add(size);
+ mem_in_use_blocks.Increment();
+ mem_in_use_allocs.Increment();
+}
+
+void MemoryWatcher::OnUntrack(HANDLE heap, int32 id, int32 size) {
+ DCHECK_GE(size, 0);
+
+ // Don't bother with these.
+ if (size == 0)
+ return;
+
+ if (LockedRecursionDetected())
+ return;
+
+ {
+ base::AutoLock lock(block_map_lock_);
+ active_thread_id_ = GetCurrentThreadId();
+
+ // First, find the block in our block_map.
+ CallStackMap::iterator it = block_map_->find(id);
+ if (it != block_map_->end()) {
+ AllocationStack* stack = it->second;
+ DCHECK(stack->size() == size);
+ block_map_->erase(id);
+ delete stack;
+ } else {
+ // Untracked item. This happens a fair amount, and it is
+ // normal. A lot of time elapses during process startup
+ // before the allocation routines are hooked.
+ size = 0; // Ignore size in tallies.
+ }
+ // TODO(jar): Perchance we should use atomic access to member.
+ active_thread_id_ = 0;
+ }
+
+ mem_in_use.Add(-size);
+ mem_in_use_blocks.Decrement();
+ mem_in_use_frees.Increment();
+}
+
+void MemoryWatcher::SetLogName(char* log_name) {
+ if (!log_name)
+ return;
+
+ log_name_ = log_name;
+}
+
+// Help sort lists of stacks based on allocation cost.
+// Note: Sort based on allocation count is interesting too!
+static bool CompareCallStackIdItems(MemoryWatcher::StackTrack* left,
+ MemoryWatcher::StackTrack* right) {
+ return left->size > right->size;
+}
+
+
+void MemoryWatcher::DumpLeaks() {
+ // We can only dump the leaks once. We'll cleanup the hooks here.
+ if (!hooked_)
+ return;
+ Unhook();
+
+ base::AutoLock lock(block_map_lock_);
+ active_thread_id_ = GetCurrentThreadId();
+
+ OpenLogFile();
+
+ // Aggregate contributions from each allocated block on per-stack basis.
+ CallStackIdMap stack_map;
+ for (CallStackMap::iterator block_it = block_map_->begin();
+ block_it != block_map_->end(); ++block_it) {
+ AllocationStack* stack = block_it->second;
+ int32 stack_hash = stack->hash();
+ int32 alloc_block_size = stack->size();
+ CallStackIdMap::iterator it = stack_map.find(stack_hash);
+ if (it == stack_map.end()) {
+ StackTrack tracker;
+ tracker.count = 1;
+ tracker.size = alloc_block_size;
+ tracker.stack = stack; // Temporary pointer into block_map_.
+ stack_map[stack_hash] = tracker;
+ } else {
+ it->second.count++;
+ it->second.size += alloc_block_size;
+ }
+ }
+ // Don't release lock yet, as block_map_ is still pointed into.
+
+ // Put references to StrackTracks into array for sorting.
+ std::vector<StackTrack*, PrivateHookAllocator<int32> >
+ stack_tracks(stack_map.size());
+ CallStackIdMap::iterator it = stack_map.begin();
+ for (size_t i = 0; i < stack_tracks.size(); ++i) {
+ stack_tracks[i] = &(it->second);
+ ++it;
+ }
+ sort(stack_tracks.begin(), stack_tracks.end(), CompareCallStackIdItems);
+
+ int32 total_bytes = 0;
+ int32 total_blocks = 0;
+ for (size_t i = 0; i < stack_tracks.size(); ++i) {
+ StackTrack* stack_track = stack_tracks[i];
+ fwprintf(file_, L"%d bytes, %d allocs, #%d\n",
+ stack_track->size, stack_track->count, i);
+ total_bytes += stack_track->size;
+ total_blocks += stack_track->count;
+
+ CallStack* stack = stack_track->stack;
+ PrivateAllocatorString output;
+ stack->ToString(&output);
+ fprintf(file_, "%s", output.c_str());
+ }
+ fprintf(file_, "Total Leaks: %d\n", total_blocks);
+ fprintf(file_, "Total Stacks: %d\n", stack_tracks.size());
+ fprintf(file_, "Total Bytes: %d\n", total_bytes);
+ CloseLogFile();
+}
diff --git a/chromium/tools/memory_watcher/memory_watcher.gyp b/chromium/tools/memory_watcher/memory_watcher.gyp
new file mode 100644
index 00000000000..eb1970529ad
--- /dev/null
+++ b/chromium/tools/memory_watcher/memory_watcher.gyp
@@ -0,0 +1,43 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'memory_watcher',
+ 'type': 'shared_library',
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ '../../ui/ui.gyp:ui',
+ ],
+ 'defines': [
+ 'BUILD_MEMORY_WATCHER',
+ ],
+ 'include_dirs': [
+ '../..',
+ '<(DEPTH)/third_party/wtl/include',
+ ],
+ # "/GS can not protect parameters and local variables from local buffer
+ # overrun because optimizations are disabled in function". Nothing to be
+ # done about this warning.
+ 'msvs_disabled_warnings': [ 4748 ],
+ 'sources': [
+ 'call_stack.cc',
+ 'call_stack.h',
+ 'dllmain.cc',
+ 'hotkey.h',
+ 'ia32_modrm_map.cc',
+ 'ia32_opcode_map.cc',
+ 'memory_hook.cc',
+ 'memory_hook.h',
+ 'memory_watcher.cc',
+ 'memory_watcher.h',
+ 'mini_disassembler.cc',
+ 'preamble_patcher.cc',
+ 'preamble_patcher.h',
+ 'preamble_patcher_with_stub.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/memory_watcher/memory_watcher.h b/chromium/tools/memory_watcher/memory_watcher.h
new file mode 100644
index 00000000000..8f5f1c2eb6f
--- /dev/null
+++ b/chromium/tools/memory_watcher/memory_watcher.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// MemoryWatcher.
+// The MemoryWatcher is a library that can be linked into any
+// win32 application. It will override the default memory allocators
+// and track call stacks for any allocations that are made. It can
+// then be used to see what memory is in use.
+
+#ifndef TOOLS_MEMORY_WATCHER_MEMORY_WATCHER_
+#define TOOLS_MEMORY_WATCHER_MEMORY_WATCHER_
+
+#include <map>
+#include <functional>
+
+#include "base/synchronization/lock.h"
+#include "tools/memory_watcher/memory_hook.h"
+
+class CallStack;
+class AllocationStack;
+
+// The MemoryWatcher installs allocation hooks and monitors
+// allocations and frees.
+class MemoryWatcher : MemoryObserver {
+ public:
+ struct StackTrack {
+ CallStack* stack;
+ int count;
+ int size;
+ };
+
+ typedef std::map<int32, AllocationStack*, std::less<int32>,
+ PrivateHookAllocator<int32> > CallStackMap;
+ typedef std::map<int32, StackTrack, std::less<int32>,
+ PrivateHookAllocator<int32> > CallStackIdMap;
+ typedef std::basic_string<char, std::char_traits<char>,
+ PrivateHookAllocator<char> > PrivateAllocatorString;
+
+ MemoryWatcher();
+ virtual ~MemoryWatcher();
+
+ // Dump all tracked pointers still in use.
+ void DumpLeaks();
+
+ // MemoryObserver interface.
+ virtual void OnTrack(HANDLE heap, int32 id, int32 size);
+ virtual void OnUntrack(HANDLE heap, int32 id, int32 size);
+
+ // Sets a name that appears in the generated file name.
+ void SetLogName(char* log_name);
+
+ private:
+ // Opens the logfile which we create.
+ void OpenLogFile();
+
+ // Close the logfile.
+ void CloseLogFile();
+
+ // Hook the memory hooks.
+ void Hook();
+
+ // Unhooks our memory hooks.
+ void Unhook();
+
+ // Check to see if this thread is already processing a block, and should not
+ // recurse.
+ bool LockedRecursionDetected() const;
+
+ // This is for logging.
+ FILE* file_;
+
+ bool hooked_; // True when this class has the memory_hooks hooked.
+
+ // Either 0, or else the threadID for a thread that is actively working on
+ // a stack track. Used to avoid recursive tracking.
+ DWORD active_thread_id_;
+
+ base::Lock block_map_lock_;
+ // The block_map provides quick lookups based on the allocation
+ // pointer. This is important for having fast round trips through
+ // malloc/free.
+ CallStackMap *block_map_;
+
+ // The file name for that log.
+ std::string file_name_;
+
+ // An optional name that appears in the log file name (used to differentiate
+ // logs).
+ std::string log_name_;
+};
+
+
+
+#endif // TOOLS_MEMORY_WATCHER_MEMORY_WATCHER_
diff --git a/chromium/tools/memory_watcher/mini_disassembler.cc b/chromium/tools/memory_watcher/mini_disassembler.cc
new file mode 100644
index 00000000000..c97ae6f3e2b
--- /dev/null
+++ b/chromium/tools/memory_watcher/mini_disassembler.cc
@@ -0,0 +1,392 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Implementation of MiniDisassembler.
+ */
+
+#include "mini_disassembler.h"
+
+namespace sidestep {
+
+MiniDisassembler::MiniDisassembler(bool operand_default_is_32_bits,
+ bool address_default_is_32_bits)
+ : operand_default_is_32_bits_(operand_default_is_32_bits),
+ address_default_is_32_bits_(address_default_is_32_bits) {
+ Initialize();
+}
+
+MiniDisassembler::MiniDisassembler()
+ : operand_default_is_32_bits_(true),
+ address_default_is_32_bits_(true) {
+ Initialize();
+}
+
+InstructionType MiniDisassembler::Disassemble(
+ unsigned char* start_byte,
+ unsigned int& instruction_bytes) {
+ // Clean up any state from previous invocations.
+ Initialize();
+
+ // Start by processing any prefixes.
+ unsigned char* current_byte = start_byte;
+ unsigned int size = 0;
+ InstructionType instruction_type = ProcessPrefixes(current_byte, size);
+
+ if (IT_UNKNOWN == instruction_type)
+ return instruction_type;
+
+ current_byte += size;
+ size = 0;
+
+ // Invariant: We have stripped all prefixes, and the operand_is_32_bits_
+ // and address_is_32_bits_ flags are correctly set.
+
+ instruction_type = ProcessOpcode(current_byte, 0, size);
+
+ // Check for error processing instruction
+ if ((IT_UNKNOWN == instruction_type_) || (IT_UNUSED == instruction_type_)) {
+ return IT_UNKNOWN;
+ }
+
+ current_byte += size;
+
+ // Invariant: operand_bytes_ indicates the total size of operands
+ // specified by the opcode and/or ModR/M byte and/or SIB byte.
+ // pCurrentByte points to the first byte after the ModR/M byte, or after
+ // the SIB byte if it is present (i.e. the first byte of any operands
+ // encoded in the instruction).
+
+ // We get the total length of any prefixes, the opcode, and the ModR/M and
+ // SIB bytes if present, by taking the difference of the original starting
+ // address and the current byte (which points to the first byte of the
+ // operands if present, or to the first byte of the next instruction if
+ // they are not). Adding the count of bytes in the operands encoded in
+ // the instruction gives us the full length of the instruction in bytes.
+ instruction_bytes += operand_bytes_ + (current_byte - start_byte);
+
+ // Return the instruction type, which was set by ProcessOpcode().
+ return instruction_type_;
+}
+
+void MiniDisassembler::Initialize() {
+ operand_is_32_bits_ = operand_default_is_32_bits_;
+ address_is_32_bits_ = address_default_is_32_bits_;
+ operand_bytes_ = 0;
+ have_modrm_ = false;
+ should_decode_modrm_ = false;
+ instruction_type_ = IT_UNKNOWN;
+ got_f2_prefix_ = false;
+ got_f3_prefix_ = false;
+ got_66_prefix_ = false;
+}
+
+InstructionType MiniDisassembler::ProcessPrefixes(unsigned char* start_byte,
+ unsigned int& size) {
+ InstructionType instruction_type = IT_GENERIC;
+ const Opcode& opcode = s_ia32_opcode_map_[0].table_[*start_byte];
+
+ switch (opcode.type_) {
+ case IT_PREFIX_ADDRESS:
+ address_is_32_bits_ = !address_default_is_32_bits_;
+ goto nochangeoperand;
+ case IT_PREFIX_OPERAND:
+ operand_is_32_bits_ = !operand_default_is_32_bits_;
+ nochangeoperand:
+ case IT_PREFIX:
+
+ if (0xF2 == (*start_byte))
+ got_f2_prefix_ = true;
+ else if (0xF3 == (*start_byte))
+ got_f3_prefix_ = true;
+ else if (0x66 == (*start_byte))
+ got_66_prefix_ = true;
+
+ instruction_type = opcode.type_;
+ size ++;
+ // we got a prefix, so add one and check next byte
+ ProcessPrefixes(start_byte + 1, size);
+ default:
+ break; // not a prefix byte
+ }
+
+ return instruction_type;
+}
+
+InstructionType MiniDisassembler::ProcessOpcode(unsigned char* start_byte,
+ unsigned int table_index,
+ unsigned int& size) {
+ const OpcodeTable& table = s_ia32_opcode_map_[table_index]; // Get our table
+ unsigned char current_byte = (*start_byte) >> table.shift_;
+ current_byte = current_byte & table.mask_; // Mask out the bits we will use
+
+ // Check whether the byte we have is inside the table we have.
+ if (current_byte < table.min_lim_ || current_byte > table.max_lim_) {
+ instruction_type_ = IT_UNKNOWN;
+ return instruction_type_;
+ }
+
+ const Opcode& opcode = table.table_[current_byte];
+ if (IT_UNUSED == opcode.type_) {
+ // This instruction is not used by the IA-32 ISA, so we indicate
+ // this to the user. Probably means that we were pointed to
+ // a byte in memory that was not the start of an instruction.
+ instruction_type_ = IT_UNUSED;
+ return instruction_type_;
+ } else if (IT_REFERENCE == opcode.type_) {
+ // We are looking at an opcode that has more bytes (or is continued
+ // in the ModR/M byte). Recursively find the opcode definition in
+ // the table for the opcode's next byte.
+ size++;
+ ProcessOpcode(start_byte + 1, opcode.table_index_, size);
+ return instruction_type_;
+ }
+
+ const SpecificOpcode* specific_opcode = (SpecificOpcode*)&opcode;
+ if (opcode.is_prefix_dependent_) {
+ if (got_f2_prefix_ && opcode.opcode_if_f2_prefix_.mnemonic_ != 0) {
+ specific_opcode = &opcode.opcode_if_f2_prefix_;
+ } else if (got_f3_prefix_ && opcode.opcode_if_f3_prefix_.mnemonic_ != 0) {
+ specific_opcode = &opcode.opcode_if_f3_prefix_;
+ } else if (got_66_prefix_ && opcode.opcode_if_66_prefix_.mnemonic_ != 0) {
+ specific_opcode = &opcode.opcode_if_66_prefix_;
+ }
+ }
+
+ // Inv: The opcode type is known.
+ instruction_type_ = specific_opcode->type_;
+
+ // Let's process the operand types to see if we have any immediate
+ // operands, and/or a ModR/M byte.
+
+ ProcessOperand(specific_opcode->flag_dest_);
+ ProcessOperand(specific_opcode->flag_source_);
+ ProcessOperand(specific_opcode->flag_aux_);
+
+ // Inv: We have processed the opcode and incremented operand_bytes_
+ // by the number of bytes of any operands specified by the opcode
+ // that are stored in the instruction (not registers etc.). Now
+ // we need to return the total number of bytes for the opcode and
+ // for the ModR/M or SIB bytes if they are present.
+
+ if (table.mask_ != 0xff) {
+ if (have_modrm_) {
+ // we're looking at a ModR/M byte so we're not going to
+ // count that into the opcode size
+ ProcessModrm(start_byte, size);
+ return IT_GENERIC;
+ } else {
+ // need to count the ModR/M byte even if it's just being
+ // used for opcode extension
+ size++;
+ return IT_GENERIC;
+ }
+ } else {
+ if (have_modrm_) {
+ // The ModR/M byte is the next byte.
+ size++;
+ ProcessModrm(start_byte + 1, size);
+ return IT_GENERIC;
+ } else {
+ size++;
+ return IT_GENERIC;
+ }
+ }
+}
+
+bool MiniDisassembler::ProcessOperand(int flag_operand) {
+ bool succeeded = true;
+ if (AM_NOT_USED == flag_operand)
+ return succeeded;
+
+ // Decide what to do based on the addressing mode.
+ switch (flag_operand & AM_MASK) {
+ // No ModR/M byte indicated by these addressing modes, and no
+ // additional (e.g. immediate) parameters.
+ case AM_A: // Direct address
+ case AM_F: // EFLAGS register
+ case AM_X: // Memory addressed by the DS:SI register pair
+ case AM_Y: // Memory addressed by the ES:DI register pair
+ case AM_IMPLICIT: // Parameter is implicit, occupies no space in
+ // instruction
+ break;
+
+ // There is a ModR/M byte but it does not necessarily need
+ // to be decoded.
+ case AM_C: // reg field of ModR/M selects a control register
+ case AM_D: // reg field of ModR/M selects a debug register
+ case AM_G: // reg field of ModR/M selects a general register
+ case AM_P: // reg field of ModR/M selects an MMX register
+ case AM_R: // mod field of ModR/M may refer only to a general register
+ case AM_S: // reg field of ModR/M selects a segment register
+ case AM_T: // reg field of ModR/M selects a test register
+ case AM_V: // reg field of ModR/M selects a 128-bit XMM register
+ have_modrm_ = true;
+ break;
+
+ // In these addressing modes, there is a ModR/M byte and it needs to be
+ // decoded. No other (e.g. immediate) params than indicated in ModR/M.
+ case AM_E: // Operand is either a general-purpose register or memory,
+ // specified by ModR/M byte
+ case AM_M: // ModR/M byte will refer only to memory
+ case AM_Q: // Operand is either an MMX register or memory (complex
+ // evaluation), specified by ModR/M byte
+ case AM_W: // Operand is either a 128-bit XMM register or memory (complex
+ // eval), specified by ModR/M byte
+ have_modrm_ = true;
+ should_decode_modrm_ = true;
+ break;
+
+ // These addressing modes specify an immediate or an offset value
+ // directly, so we need to look at the operand type to see how many
+ // bytes.
+ case AM_I: // Immediate data.
+ case AM_J: // Jump to offset.
+ case AM_O: // Operand is at offset.
+ switch (flag_operand & OT_MASK) {
+ case OT_B: // Byte regardless of operand-size attribute.
+ operand_bytes_ += OS_BYTE;
+ break;
+ case OT_C: // Byte or word, depending on operand-size attribute.
+ if (operand_is_32_bits_)
+ operand_bytes_ += OS_WORD;
+ else
+ operand_bytes_ += OS_BYTE;
+ break;
+ case OT_D: // Doubleword, regardless of operand-size attribute.
+ operand_bytes_ += OS_DOUBLE_WORD;
+ break;
+ case OT_DQ: // Double-quadword, regardless of operand-size attribute.
+ operand_bytes_ += OS_DOUBLE_QUAD_WORD;
+ break;
+ case OT_P: // 32-bit or 48-bit pointer, depending on operand-size
+ // attribute.
+ if (operand_is_32_bits_)
+ operand_bytes_ += OS_48_BIT_POINTER;
+ else
+ operand_bytes_ += OS_32_BIT_POINTER;
+ break;
+ case OT_PS: // 128-bit packed single-precision floating-point data.
+ operand_bytes_ += OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING;
+ break;
+ case OT_Q: // Quadword, regardless of operand-size attribute.
+ operand_bytes_ += OS_QUAD_WORD;
+ break;
+ case OT_S: // 6-byte pseudo-descriptor.
+ operand_bytes_ += OS_PSEUDO_DESCRIPTOR;
+ break;
+ case OT_SD: // Scalar Double-Precision Floating-Point Value
+ case OT_PD: // Unaligned packed double-precision floating point value
+ operand_bytes_ += OS_DOUBLE_PRECISION_FLOATING;
+ break;
+ case OT_SS:
+ // Scalar element of a 128-bit packed single-precision
+ // floating data.
+ // We simply return enItUnknown since we don't have to support
+ // floating point
+ succeeded = false;
+ break;
+ case OT_V: // Word or doubleword, depending on operand-size attribute.
+ if (operand_is_32_bits_)
+ operand_bytes_ += OS_DOUBLE_WORD;
+ else
+ operand_bytes_ += OS_WORD;
+ break;
+ case OT_W: // Word, regardless of operand-size attribute.
+ operand_bytes_ += OS_WORD;
+ break;
+
+ // Can safely ignore these.
+ case OT_A: // Two one-word operands in memory or two double-word
+ // operands in memory
+ case OT_PI: // Quadword MMX technology register (e.g. mm0)
+ case OT_SI: // Doubleword integer register (e.g., eax)
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return succeeded;
+}
+
+bool MiniDisassembler::ProcessModrm(unsigned char* start_byte,
+ unsigned int& size) {
+ // If we don't need to decode, we just return the size of the ModR/M
+ // byte (there is never a SIB byte in this case).
+ if (!should_decode_modrm_) {
+ size++;
+ return true;
+ }
+
+ // We never care about the reg field, only the combination of the mod
+ // and r/m fields, so let's start by packing those fields together into
+ // 5 bits.
+ unsigned char modrm = (*start_byte);
+ unsigned char mod = modrm & 0xC0; // mask out top two bits to get mod field
+ modrm = modrm & 0x07; // mask out bottom 3 bits to get r/m field
+ mod = mod >> 3; // shift the mod field to the right place
+ modrm = mod | modrm; // combine the r/m and mod fields as discussed
+ mod = mod >> 3; // shift the mod field to bits 2..0
+
+ // Invariant: modrm contains the mod field in bits 4..3 and the r/m field
+ // in bits 2..0, and mod contains the mod field in bits 2..0
+
+ const ModrmEntry* modrm_entry = 0;
+ if (address_is_32_bits_)
+ modrm_entry = &s_ia32_modrm_map_[modrm];
+ else
+ modrm_entry = &s_ia16_modrm_map_[modrm];
+
+ // Invariant: modrm_entry points to information that we need to decode
+ // the ModR/M byte.
+
+ // Add to the count of operand bytes, if the ModR/M byte indicates
+ // that some operands are encoded in the instruction.
+ if (modrm_entry->is_encoded_in_instruction_)
+ operand_bytes_ += modrm_entry->operand_size_;
+
+ // Process the SIB byte if necessary, and return the count
+ // of ModR/M and SIB bytes.
+ if (modrm_entry->use_sib_byte_) {
+ size++;
+ return ProcessSib(start_byte + 1, mod, size);
+ } else {
+ size++;
+ return true;
+ }
+}
+
+bool MiniDisassembler::ProcessSib(unsigned char* start_byte,
+ unsigned char mod,
+ unsigned int& size) {
+ // get the mod field from the 2..0 bits of the SIB byte
+ unsigned char sib_base = (*start_byte) & 0x07;
+ if (0x05 == sib_base) {
+ switch (mod) {
+ case 0x00: // mod == 00
+ case 0x02: // mod == 10
+ operand_bytes_ += OS_DOUBLE_WORD;
+ break;
+ case 0x01: // mod == 01
+ operand_bytes_ += OS_BYTE;
+ break;
+ case 0x03: // mod == 11
+ // According to the IA-32 docs, there does not seem to be a disp
+ // value for this value of mod
+ default:
+ break;
+ }
+ }
+
+ size++;
+ return true;
+}
+
+}; // namespace sidestep
diff --git a/chromium/tools/memory_watcher/mini_disassembler.h b/chromium/tools/memory_watcher/mini_disassembler.h
new file mode 100644
index 00000000000..1d0f966e3b1
--- /dev/null
+++ b/chromium/tools/memory_watcher/mini_disassembler.h
@@ -0,0 +1,163 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Definition of MiniDisassembler.
+ */
+
+#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
+#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
+
+#include <windows.h>
+#include "mini_disassembler_types.h"
+
+// compatibility shim
+#include "base/logging.h"
+#define ASSERT(cond, msg) DCHECK(cond)
+#define ASSERT1(cond) DCHECK(cond)
+
+namespace sidestep {
+
+// This small disassembler is very limited
+// in its functionality, and in fact does only the bare minimum required by the
+// preamble patching utility. It may be useful for other purposes, however.
+//
+// The limitations include at least the following:
+// -# No support for coprocessor opcodes, MMX, etc.
+// -# No machine-readable identification of opcodes or decoding of
+// assembly parameters. The name of the opcode (as a string) is given,
+// however, to aid debugging.
+//
+// You may ask what this little disassembler actually does, then? The answer is
+// that it does the following, which is exactly what the patching utility needs:
+// -# Indicates if opcode is a jump (any kind) or a return (any kind)
+// because this is important for the patching utility to determine if
+// a function is too short or there are jumps too early in it for it
+// to be preamble patched.
+// -# The opcode length is always calculated, so that the patching utility
+// can figure out where the next instruction starts, and whether it
+// already has enough instructions to replace with the absolute jump
+// to the patching code.
+//
+// The usage is quite simple; just create a MiniDisassembler and use its
+// Disassemble() method.
+//
+// If you would like to extend this disassembler, please refer to the
+// IA-32 Intel Architecture Software Developer's Manual Volume 2:
+// Instruction Set Reference for information about operand decoding
+// etc.
+class MiniDisassembler {
+ public:
+
+ // Creates a new instance and sets defaults.
+ //
+ // @param operand_default_32_bits If true, the default operand size is
+ // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
+ // @param address_default_32_bits If true, the default address size is
+ // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
+ MiniDisassembler(bool operand_default_32_bits,
+ bool address_default_32_bits);
+
+ // Equivalent to MiniDisassembler(true, true);
+ MiniDisassembler();
+
+ // Attempts to disassemble a single instruction starting from the
+ // address in memory it is pointed to.
+ //
+ // @param start Address where disassembly should start.
+ // @param instruction_bytes Variable that will be <b>incremented</b> by
+ // the length in bytes of the instruction.
+ // @return enItJump, enItReturn or enItGeneric on success. enItUnknown
+ // if unable to disassemble, enItUnused if this seems to be an unused
+ // opcode. In the last two (error) cases, cbInstruction will be set
+ // to 0xffffffff.
+ //
+ // @post This instance of the disassembler is ready to be used again,
+ // with unchanged defaults from creation time.
+ InstructionType Disassemble(unsigned char* start, unsigned int& instruction_bytes);
+
+ private:
+
+ // Makes the disassembler ready for reuse.
+ void Initialize();
+
+ // Sets the flags for address and operand sizes.
+ // @return Number of prefix bytes.
+ InstructionType ProcessPrefixes(unsigned char* start, unsigned int& size);
+
+ // Sets the flag for whether we have ModR/M, and increments
+ // operand_bytes_ if any are specifies by the opcode directly.
+ // @return Number of opcode bytes.
+ InstructionType ProcessOpcode(unsigned char * start,
+ unsigned int table,
+ unsigned int& size);
+
+ // Checks the type of the supplied operand. Increments
+ // operand_bytes_ if it directly indicates an immediate etc.
+ // operand. Asserts have_modrm_ if the operand specifies
+ // a ModR/M byte.
+ bool ProcessOperand(int flag_operand);
+
+ // Increments operand_bytes_ by size specified by ModR/M and
+ // by SIB if present.
+ // @return 0 in case of error, 1 if there is just a ModR/M byte,
+ // 2 if there is a ModR/M byte and a SIB byte.
+ bool ProcessModrm(unsigned char* start, unsigned int& size);
+
+ // Processes the SIB byte that it is pointed to.
+ // @param start Pointer to the SIB byte.
+ // @param mod The mod field from the ModR/M byte.
+ // @return 1 to indicate success (indicates 1 SIB byte)
+ bool ProcessSib(unsigned char* start, unsigned char mod, unsigned int& size);
+
+ // The instruction type we have decoded from the opcode.
+ InstructionType instruction_type_;
+
+ // Counts the number of bytes that is occupied by operands in
+ // the current instruction (note: we don't care about how large
+ // operands stored in registers etc. are).
+ unsigned int operand_bytes_;
+
+ // True iff there is a ModR/M byte in this instruction.
+ bool have_modrm_;
+
+ // True iff we need to decode the ModR/M byte (sometimes it just
+ // points to a register, we can tell by the addressing mode).
+ bool should_decode_modrm_;
+
+ // Current operand size is 32 bits if true, 16 bits if false.
+ bool operand_is_32_bits_;
+
+ // Default operand size is 32 bits if true, 16 bits if false.
+ bool operand_default_is_32_bits_;
+
+ // Current address size is 32 bits if true, 16 bits if false.
+ bool address_is_32_bits_;
+
+ // Default address size is 32 bits if true, 16 bits if false.
+ bool address_default_is_32_bits_;
+
+ // Huge big opcode table based on the IA-32 manual, defined
+ // in Ia32OpcodeMap.cc
+ static const OpcodeTable s_ia32_opcode_map_[];
+
+ // Somewhat smaller table to help with decoding ModR/M bytes
+ // when 16-bit addressing mode is being used. Defined in
+ // Ia32ModrmMap.cc
+ static const ModrmEntry s_ia16_modrm_map_[];
+
+ // Somewhat smaller table to help with decoding ModR/M bytes
+ // when 32-bit addressing mode is being used. Defined in
+ // Ia32ModrmMap.cc
+ static const ModrmEntry s_ia32_modrm_map_[];
+
+ // Indicators of whether we got certain prefixes that certain
+ // silly Intel instructions depend on in nonstandard ways for
+ // their behaviors.
+ bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_;
+};
+
+}; // namespace sidestep
+
+#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_H__
diff --git a/chromium/tools/memory_watcher/mini_disassembler_types.h b/chromium/tools/memory_watcher/mini_disassembler_types.h
new file mode 100644
index 00000000000..4fc24abde34
--- /dev/null
+++ b/chromium/tools/memory_watcher/mini_disassembler_types.h
@@ -0,0 +1,199 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Several simple types used by the disassembler and some of the patching
+ * mechanisms.
+ */
+
+#ifndef GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
+#define GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
+
+namespace sidestep {
+
+// Categories of instructions that we care about
+enum InstructionType {
+ // This opcode is not used
+ IT_UNUSED,
+ // This disassembler does not recognize this opcode (error)
+ IT_UNKNOWN,
+ // This is not an instruction but a reference to another table
+ IT_REFERENCE,
+ // This byte is a prefix byte that we can ignore
+ IT_PREFIX,
+ // This is a prefix byte that switches to the nondefault address size
+ IT_PREFIX_ADDRESS,
+ // This is a prefix byte that switches to the nondefault operand size
+ IT_PREFIX_OPERAND,
+ // A jump or call instruction
+ IT_JUMP,
+ // A return instruction
+ IT_RETURN,
+ // Any other type of instruction (in this case we don't care what it is)
+ IT_GENERIC,
+};
+
+// Lists IA-32 operand sizes in multiples of 8 bits
+enum OperandSize {
+ OS_ZERO = 0,
+ OS_BYTE = 1,
+ OS_WORD = 2,
+ OS_DOUBLE_WORD = 4,
+ OS_QUAD_WORD = 8,
+ OS_DOUBLE_QUAD_WORD = 16,
+ OS_32_BIT_POINTER = 32/8,
+ OS_48_BIT_POINTER = 48/8,
+ OS_SINGLE_PRECISION_FLOATING = 32/8,
+ OS_DOUBLE_PRECISION_FLOATING = 64/8,
+ OS_DOUBLE_EXTENDED_PRECISION_FLOATING = 80/8,
+ OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING = 128/8,
+ OS_PSEUDO_DESCRIPTOR = 6
+};
+
+// Operand addressing methods from the IA-32 manual. The enAmMask value
+// is a mask for the rest. The other enumeration values are named for the
+// names given to the addressing methods in the manual, e.g. enAm_D is for
+// the D addressing method.
+//
+// The reason we use a full 4 bytes and a mask, is that we need to combine
+// these flags with the enOperandType to store the details
+// on the operand in a single integer.
+enum AddressingMethod {
+ AM_NOT_USED = 0, // This operand is not used for this instruction
+ AM_MASK = 0x00FF0000, // Mask for the rest of the values in this enumeration
+ AM_A = 0x00010000, // A addressing type
+ AM_C = 0x00020000, // C addressing type
+ AM_D = 0x00030000, // D addressing type
+ AM_E = 0x00040000, // E addressing type
+ AM_F = 0x00050000, // F addressing type
+ AM_G = 0x00060000, // G addressing type
+ AM_I = 0x00070000, // I addressing type
+ AM_J = 0x00080000, // J addressing type
+ AM_M = 0x00090000, // M addressing type
+ AM_O = 0x000A0000, // O addressing type
+ AM_P = 0x000B0000, // P addressing type
+ AM_Q = 0x000C0000, // Q addressing type
+ AM_R = 0x000D0000, // R addressing type
+ AM_S = 0x000E0000, // S addressing type
+ AM_T = 0x000F0000, // T addressing type
+ AM_V = 0x00100000, // V addressing type
+ AM_W = 0x00110000, // W addressing type
+ AM_X = 0x00120000, // X addressing type
+ AM_Y = 0x00130000, // Y addressing type
+ AM_REGISTER = 0x00140000, // Specific register is always used as this op
+ AM_IMPLICIT = 0x00150000, // An implicit, fixed value is used
+};
+
+// Operand types from the IA-32 manual. The enOtMask value is
+// a mask for the rest. The rest of the values are named for the
+// names given to these operand types in the manual, e.g. enOt_ps
+// is for the ps operand type in the manual.
+//
+// The reason we use a full 4 bytes and a mask, is that we need
+// to combine these flags with the enAddressingMethod to store the details
+// on the operand in a single integer.
+enum OperandType {
+ OT_MASK = 0xFF000000,
+ OT_A = 0x01000000,
+ OT_B = 0x02000000,
+ OT_C = 0x03000000,
+ OT_D = 0x04000000,
+ OT_DQ = 0x05000000,
+ OT_P = 0x06000000,
+ OT_PI = 0x07000000,
+ OT_PS = 0x08000000, // actually unsupported for (we don't know its size)
+ OT_Q = 0x09000000,
+ OT_S = 0x0A000000,
+ OT_SS = 0x0B000000,
+ OT_SI = 0x0C000000,
+ OT_V = 0x0D000000,
+ OT_W = 0x0E000000,
+ OT_SD = 0x0F000000, // scalar double-precision floating-point value
+ OT_PD = 0x10000000, // double-precision floating point
+ // dummy "operand type" for address mode M - which doesn't specify
+ // operand type
+ OT_ADDRESS_MODE_M = 0x80000000
+};
+
+// Everything that's in an Opcode (see below) except the three
+// alternative opcode structs for different prefixes.
+struct SpecificOpcode {
+ // Index to continuation table, or 0 if this is the last
+ // byte in the opcode.
+ int table_index_;
+
+ // The opcode type
+ InstructionType type_;
+
+ // Description of the type of the dest, src and aux operands,
+ // put together from an enOperandType flag and an enAddressingMethod
+ // flag.
+ int flag_dest_;
+ int flag_source_;
+ int flag_aux_;
+
+ // We indicate the mnemonic for debugging purposes
+ const char* mnemonic_;
+};
+
+// The information we keep in our tables about each of the different
+// valid instructions recognized by the IA-32 architecture.
+struct Opcode {
+ // Index to continuation table, or 0 if this is the last
+ // byte in the opcode.
+ int table_index_;
+
+ // The opcode type
+ InstructionType type_;
+
+ // Description of the type of the dest, src and aux operands,
+ // put together from an enOperandType flag and an enAddressingMethod
+ // flag.
+ int flag_dest_;
+ int flag_source_;
+ int flag_aux_;
+
+ // We indicate the mnemonic for debugging purposes
+ const char* mnemonic_;
+
+ // Alternative opcode info if certain prefixes are specified.
+ // In most cases, all of these are zeroed-out. Only used if
+ // bPrefixDependent is true.
+ bool is_prefix_dependent_;
+ SpecificOpcode opcode_if_f2_prefix_;
+ SpecificOpcode opcode_if_f3_prefix_;
+ SpecificOpcode opcode_if_66_prefix_;
+};
+
+// Information about each table entry.
+struct OpcodeTable {
+ // Table of instruction entries
+ const Opcode* table_;
+ // How many bytes left to shift ModR/M byte <b>before</b> applying mask
+ unsigned char shift_;
+ // Mask to apply to byte being looked at before comparing to table
+ unsigned char mask_;
+ // Minimum/maximum indexes in table.
+ unsigned char min_lim_;
+ unsigned char max_lim_;
+};
+
+// Information about each entry in table used to decode ModR/M byte.
+struct ModrmEntry {
+ // Is the operand encoded as bytes in the instruction (rather than
+ // if it's e.g. a register in which case it's just encoded in the
+ // ModR/M byte)
+ bool is_encoded_in_instruction_;
+
+ // Is there a SIB byte? In this case we always need to decode it.
+ bool use_sib_byte_;
+
+ // What is the size of the operand (only important if it's encoded
+ // in the instruction)?
+ OperandSize operand_size_;
+};
+
+}; // namespace sidestep
+
+#endif // GOOGLE_PERFTOOLS_MINI_DISASSEMBLER_TYPES_H__
diff --git a/chromium/tools/memory_watcher/preamble_patcher.cc b/chromium/tools/memory_watcher/preamble_patcher.cc
new file mode 100644
index 00000000000..846d88141be
--- /dev/null
+++ b/chromium/tools/memory_watcher/preamble_patcher.cc
@@ -0,0 +1,228 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "preamble_patcher.h"
+#include "memory_hook.h"
+#include "mini_disassembler.h"
+
+// compatibility shims
+#include "base/logging.h"
+
+// Definitions of assembly statements we need
+#define ASM_JMP32REL 0xE9
+#define ASM_INT3 0xCC
+
+namespace sidestep {
+
+SideStepError PreamblePatcher::RawPatchWithStubAndProtections(
+ void* target_function, void *replacement_function,
+ unsigned char* preamble_stub, unsigned long stub_size,
+ unsigned long* bytes_needed) {
+ // We need to be able to write to a process-local copy of the first
+ // MAX_PREAMBLE_STUB_SIZE bytes of target_function. We may be giving execute
+ // privilege to something that doesn't have it, but that's the price to pay
+ // for tools.
+ DWORD old_target_function_protect = 0;
+ BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function),
+ MAX_PREAMBLE_STUB_SIZE,
+ PAGE_EXECUTE_READWRITE,
+ &old_target_function_protect);
+ if (!succeeded) {
+ ASSERT(false, "Failed to make page containing target function "
+ "copy-on-write.");
+ return SIDESTEP_ACCESS_DENIED;
+ }
+
+ SideStepError error_code = RawPatchWithStub(target_function,
+ replacement_function,
+ preamble_stub,
+ stub_size,
+ bytes_needed);
+ if (SIDESTEP_SUCCESS != error_code) {
+ ASSERT1(false);
+ return error_code;
+ }
+
+ // Restore the protection of the first MAX_PREAMBLE_STUB_SIZE bytes of
+ // pTargetFunction to what they were before we started goofing around.
+ succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function),
+ MAX_PREAMBLE_STUB_SIZE,
+ old_target_function_protect,
+ &old_target_function_protect);
+ if (!succeeded) {
+ ASSERT(false, "Failed to restore protection to target function.");
+ // We must not return an error here because the function has actually
+ // been patched, and returning an error would likely cause our client
+ // code not to unpatch it. So we just keep going.
+ }
+
+ // Flush the instruction cache to make sure the processor doesn't execute the
+ // old version of the instructions (before our patch).
+ //
+ // FlushInstructionCache is actually a no-op at least on single-processor
+ // XP machines. I'm not sure why this is so, but it is, yet I want to keep
+ // the call to the API here for correctness in case there is a difference in
+ // some variants of Windows/hardware.
+ succeeded = ::FlushInstructionCache(::GetCurrentProcess(),
+ target_function,
+ MAX_PREAMBLE_STUB_SIZE);
+ if (!succeeded) {
+ ASSERT(false, "Failed to flush instruction cache.");
+ // We must not return an error here because the function has actually
+ // been patched, and returning an error would likely cause our client
+ // code not to unpatch it. So we just keep going.
+ }
+
+ return SIDESTEP_SUCCESS;
+}
+
+SideStepError PreamblePatcher::RawPatch(void* target_function,
+ void* replacement_function,
+ void** original_function_stub) {
+ if (!target_function || !replacement_function || !original_function_stub ||
+ (*original_function_stub) || target_function == replacement_function) {
+ ASSERT(false, "Preconditions not met");
+ return SIDESTEP_INVALID_PARAMETER;
+ }
+
+ // @see MAX_PREAMBLE_STUB_SIZE for an explanation of how we arrives at
+ // this size
+ unsigned char* preamble_stub =
+ reinterpret_cast<unsigned char*>(
+ MemoryHook::Alloc(sizeof(unsigned char) * MAX_PREAMBLE_STUB_SIZE));
+ if (!preamble_stub) {
+ ASSERT(false, "Unable to allocate preamble-stub.");
+ return SIDESTEP_INSUFFICIENT_BUFFER;
+ }
+
+ // Change the protection of the newly allocated preamble stub to
+ // PAGE_EXECUTE_READWRITE. This is required to work with DEP (Data
+ // Execution Prevention) which will cause an exception if code is executed
+ // from a page on which you do not have read access.
+ DWORD old_stub_protect = 0;
+ BOOL succeeded = VirtualProtect(preamble_stub, MAX_PREAMBLE_STUB_SIZE,
+ PAGE_EXECUTE_READWRITE, &old_stub_protect);
+ if (!succeeded) {
+ ASSERT(false, "Failed to make page preamble stub read-write-execute.");
+ delete[] preamble_stub;
+ return SIDESTEP_ACCESS_DENIED;
+ }
+
+ SideStepError error_code = RawPatchWithStubAndProtections(target_function,
+ replacement_function,
+ preamble_stub,
+ MAX_PREAMBLE_STUB_SIZE,
+ NULL);
+ if (SIDESTEP_SUCCESS != error_code) {
+ ASSERT1(false);
+ delete[] preamble_stub;
+ return error_code;
+ }
+
+ *original_function_stub = reinterpret_cast<void*>(preamble_stub);
+
+ // NOTE: For hooking malloc/free, we don't want to use streams which
+ // allocate. Basically, we've hooked malloc, but not necessarily
+ // hooked free yet. To do anything which uses the heap could crash
+ // with a mismatched malloc/free!
+ //VLOG(1) << "PreamblePatcher::RawPatch successfully patched 0x"
+ // << target_function;
+
+ return SIDESTEP_SUCCESS;
+}
+
+SideStepError PreamblePatcher::Unpatch(void* target_function,
+ void* replacement_function,
+ void* original_function_stub) {
+ ASSERT1(target_function && original_function_stub);
+ if (!target_function || !original_function_stub) {
+ return SIDESTEP_INVALID_PARAMETER;
+ }
+
+ // We disassemble the preamble of the _stub_ to see how many bytes we
+ // originally copied to the stub.
+ MiniDisassembler disassembler;
+ unsigned int preamble_bytes = 0;
+ while (preamble_bytes < 5) {
+ InstructionType instruction_type = disassembler.Disassemble(
+ reinterpret_cast<unsigned char*>(original_function_stub) +
+ preamble_bytes, preamble_bytes);
+ if (IT_GENERIC != instruction_type) {
+ ASSERT(false, "Should only have generic instructions in stub!!");
+ return SIDESTEP_UNSUPPORTED_INSTRUCTION;
+ }
+ }
+
+ // Before unpatching, target_function should be a JMP to
+ // replacement_function. If it's not, then either it's an error, or
+ // we're falling into the case where the original instruction was a
+ // JMP, and we patched the jumped_to address rather than the JMP
+ // itself. (For instance, if malloc() is just a JMP to __malloc(),
+ // we patched __malloc() and not malloc().)
+ unsigned char* target = reinterpret_cast<unsigned char*>(target_function);
+ while (1) { // we stop when target is a JMP to replacement_function
+ if (target[0] != ASM_JMP32REL) {
+ ASSERT(false, "target_function does not look like it was patched.");
+ return SIDESTEP_INVALID_PARAMETER;
+ }
+ int relative_offset; // Windows guarantees int is 4 bytes
+ ASSERT1(sizeof(relative_offset) == 4);
+ memcpy(reinterpret_cast<void*>(&relative_offset),
+ reinterpret_cast<void*>(target + 1), 4);
+ unsigned char* jump_to = target + 5 + relative_offset;
+ if (jump_to == replacement_function)
+ break;
+ target = jump_to; // follow the jmp
+ }
+
+ // We need to be able to write to a process-local copy of the first
+ // MAX_PREAMBLE_STUB_SIZE bytes of target_function. We may be giving execute
+ // privilege to something that doesn't have it, but that's the price to pay
+ // for tools.
+ DWORD old_target_function_protect = 0;
+ BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target),
+ MAX_PREAMBLE_STUB_SIZE,
+ PAGE_EXECUTE_READWRITE,
+ &old_target_function_protect);
+ if (!succeeded) {
+ ASSERT(false, "Failed to make page containing target function "
+ "copy-on-write.");
+ return SIDESTEP_ACCESS_DENIED;
+ }
+
+ // Replace the first few bytes of the original function with the bytes we
+ // previously moved to the preamble stub.
+ memcpy(reinterpret_cast<void*>(target),
+ original_function_stub, preamble_bytes);
+
+ // Stub is now useless so delete it.
+ // [csilvers: Commented out for perftools because it causes big problems
+ // when we're unpatching malloc. We just let this live on as a leak.]
+ //delete original_function_stub;
+
+ // Restore the protection of the first MAX_PREAMBLE_STUB_SIZE bytes of
+ // target to what they were before we started goofing around.
+ succeeded = ::VirtualProtect(reinterpret_cast<void*>(target),
+ MAX_PREAMBLE_STUB_SIZE,
+ old_target_function_protect,
+ &old_target_function_protect);
+
+ // Flush the instruction cache to make sure the processor doesn't execute the
+ // old version of the instructions (before our patch).
+ //
+ // See comment on FlushInstructionCache elsewhere in this file.
+ succeeded = ::FlushInstructionCache(::GetCurrentProcess(),
+ target,
+ MAX_PREAMBLE_STUB_SIZE);
+ if (!succeeded) {
+ ASSERT(false, "Failed to flush instruction cache.");
+ return SIDESTEP_UNEXPECTED;
+ }
+
+ VLOG(1) << "PreamblePatcher::Unpatch successfully unpatched 0x"
+ << target_function;
+ return SIDESTEP_SUCCESS;
+}
+
+}; // namespace sidestep
diff --git a/chromium/tools/memory_watcher/preamble_patcher.h b/chromium/tools/memory_watcher/preamble_patcher.h
new file mode 100644
index 00000000000..fae2551bd7b
--- /dev/null
+++ b/chromium/tools/memory_watcher/preamble_patcher.h
@@ -0,0 +1,293 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Definition of PreamblePatcher
+ */
+
+#ifndef MEMORY_WATCHER_PREAMBLE_PATCHER_H__
+#define MEMORY_WATCHER_PREAMBLE_PATCHER_H__
+
+#include <windows.h>
+
+// compatibility shim
+#include "base/logging.h"
+#define ASSERT(cond, msg) DCHECK(cond)
+#define ASSERT1(cond) DCHECK(cond)
+
+// Maximum size of the preamble stub. We overwrite at least the first 5
+// bytes of the function. Considering the worst case scenario, we need 4
+// bytes + the max instruction size + 5 more bytes for our jump back to
+// the original code. With that in mind, 32 is a good number :)
+#define MAX_PREAMBLE_STUB_SIZE (32)
+
+namespace sidestep {
+
+// Possible results of patching/unpatching
+enum SideStepError {
+ SIDESTEP_SUCCESS = 0,
+ SIDESTEP_INVALID_PARAMETER,
+ SIDESTEP_INSUFFICIENT_BUFFER,
+ SIDESTEP_JUMP_INSTRUCTION,
+ SIDESTEP_FUNCTION_TOO_SMALL,
+ SIDESTEP_UNSUPPORTED_INSTRUCTION,
+ SIDESTEP_NO_SUCH_MODULE,
+ SIDESTEP_NO_SUCH_FUNCTION,
+ SIDESTEP_ACCESS_DENIED,
+ SIDESTEP_UNEXPECTED,
+};
+
+#define SIDESTEP_TO_HRESULT(error) \
+ MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error)
+
+// Implements a patching mechanism that overwrites the first few bytes of
+// a function preamble with a jump to our hook function, which is then
+// able to call the original function via a specially-made preamble-stub
+// that imitates the action of the original preamble.
+//
+// NOTE: This patching mechanism should currently only be used for
+// non-production code, e.g. unit tests, because it is not threadsafe.
+// See the TODO in preamble_patcher_with_stub.cc for instructions on what
+// we need to do before using it in production code; it's fairly simple
+// but unnecessary for now since we only intend to use it in unit tests.
+//
+// To patch a function, use either of the typesafe Patch() methods. You
+// can unpatch a function using Unpatch().
+//
+// Typical usage goes something like this:
+// @code
+// typedef int (*MyTypesafeFuncPtr)(int x);
+// MyTypesafeFuncPtr original_func_stub;
+// int MyTypesafeFunc(int x) { return x + 1; }
+// int HookMyTypesafeFunc(int x) { return 1 + original_func_stub(x); }
+//
+// void MyPatchInitializingFunction() {
+// original_func_stub = PreamblePatcher::Patch(
+// MyTypesafeFunc, HookMyTypesafeFunc);
+// if (!original_func_stub) {
+// // ... error handling ...
+// }
+//
+// // ... continue - you have patched the function successfully ...
+// }
+// @endcode
+//
+// Note that there are a number of ways that this method of patching can
+// fail. The most common are:
+// - If there is a jump (jxx) instruction in the first 5 bytes of
+// the function being patched, we cannot patch it because in the
+// current implementation we do not know how to rewrite relative
+// jumps after relocating them to the preamble-stub. Note that
+// if you really really need to patch a function like this, it
+// would be possible to add this functionality (but at some cost).
+// - If there is a return (ret) instruction in the first 5 bytes
+// we cannot patch the function because it may not be long enough
+// for the jmp instruction we use to inject our patch.
+// - If there is another thread currently executing within the bytes
+// that are copied to the preamble stub, it will crash in an undefined
+// way.
+//
+// If you get any other error than the above, you're either pointing the
+// patcher at an invalid instruction (e.g. into the middle of a multi-
+// byte instruction, or not at memory containing executable instructions)
+// or, there may be a bug in the disassembler we use to find
+// instruction boundaries.
+//
+// NOTE: In optimized builds, when you have very trivial functions that
+// the compiler can reason do not have side effects, the compiler may
+// reuse the result of calling the function with a given parameter, which
+// may mean if you patch the function in between your patch will never get
+// invoked. See preamble_patcher_test.cc for an example.
+class PreamblePatcher {
+ public:
+
+ // This is a typesafe version of RawPatch(), identical in all other
+ // ways than it takes a template parameter indicating the type of the
+ // function being patched.
+ //
+ // @param T The type of the function you are patching. Usually
+ // you will establish this type using a typedef, as in the following
+ // example:
+ // @code
+ // typedef BOOL (WINAPI *MessageBoxPtr)(HWND, LPCTSTR, LPCTSTR, UINT);
+ // MessageBoxPtr original = NULL;
+ // PreamblePatcher::Patch(MessageBox, Hook_MessageBox, &original);
+ // @endcode
+ template <class T>
+ static SideStepError Patch(T target_function,
+ T replacement_function,
+ T* original_function_stub) {
+ // NOTE: casting from a function to a pointer is contra the C++
+ // spec. It's not safe on IA64, but is on i386. We use
+ // a C-style cast here to emphasize this is not legal C++.
+ return RawPatch((void*)(target_function),
+ (void*)(replacement_function),
+ (void**)(original_function_stub));
+ }
+
+ // Patches a named function imported from the named module using
+ // preamble patching. Uses RawPatch() to do the actual patching
+ // work.
+ //
+ // @param T The type of the function you are patching. Must
+ // exactly match the function you specify using module_name and
+ // function_name.
+ //
+ // @param module_name The name of the module from which the function
+ // is being imported. Note that the patch will fail if this module
+ // has not already been loaded into the current process.
+ //
+ // @param function_name The name of the function you wish to patch.
+ //
+ // @param replacement_function Your replacement function which
+ // will be called whenever code tries to call the original function.
+ //
+ // @param original_function_stub Pointer to memory that should receive a
+ // pointer that can be used (e.g. in the replacement function) to call the
+ // original function, or NULL to indicate failure.
+ //
+ // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
+ // indicates success.
+ template <class T>
+ static SideStepError Patch(LPCTSTR module_name,
+ LPCSTR function_name,
+ T replacement_function,
+ T* original_function_stub) {
+ ASSERT1(module_name && function_name);
+ if (!module_name || !function_name) {
+ ASSERT(false,
+ "You must specify a module name and function name.");
+ return SIDESTEP_INVALID_PARAMETER;
+ }
+ HMODULE module = ::GetModuleHandle(module_name);
+ ASSERT1(module != NULL);
+ if (!module) {
+ ASSERT(false, "Invalid module name.");
+ return SIDESTEP_NO_SUCH_MODULE;
+ }
+ FARPROC existing_function = ::GetProcAddress(module, function_name);
+ if (!existing_function) {
+ return SIDESTEP_NO_SUCH_FUNCTION;
+ }
+ // NOTE: casting from a function to a pointer is contra the C++
+ // spec. It's not safe on IA64, but is on i386. We use
+ // a C-style cast here to emphasize this is not legal C++.
+ return RawPatch((void*)existing_function, (void*)replacement_function,
+ (void**)(original_function_stub));
+ }
+
+ // Patches a function by overwriting its first few bytes with
+ // a jump to a different function. This is the "worker" function
+ // for each of the typesafe Patch() functions. In most cases,
+ // it is preferable to use the Patch() functions rather than
+ // this one as they do more checking at compile time.
+ //
+ // @param target_function A pointer to the function that should be
+ // patched.
+ //
+ // @param replacement_function A pointer to the function that should
+ // replace the target function. The replacement function must have
+ // exactly the same calling convention and parameters as the original
+ // function.
+ //
+ // @param original_function_stub Pointer to memory that should receive a
+ // pointer that can be used (e.g. in the replacement function) to call the
+ // original function, or NULL to indicate failure.
+ //
+ // @param original_function_stub Pointer to memory that should receive a
+ // pointer that can be used (e.g. in the replacement function) to call the
+ // original function, or NULL to indicate failure.
+ //
+ // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
+ // indicates success.
+ //
+ // @note The preamble-stub (the memory pointed to by
+ // *original_function_stub) is allocated on the heap, and (in
+ // production binaries) never destroyed, resulting in a memory leak. This
+ // will be the case until we implement safe unpatching of a method.
+ // However, it is quite difficult to unpatch a method (because other
+ // threads in the process may be using it) so we are leaving it for now.
+ // See however UnsafeUnpatch, which can be used for binaries where you
+ // know only one thread is running, e.g. unit tests.
+ static SideStepError RawPatch(void* target_function,
+ void* replacement_function,
+ void** original_function_stub);
+
+ // Unpatches target_function and deletes the stub that previously could be
+ // used to call the original version of the function.
+ //
+ // DELETES the stub that is passed to the function.
+ //
+ // @param target_function Pointer to the target function which was
+ // previously patched, i.e. a pointer which value should match the value
+ // of the symbol prior to patching it.
+ //
+ // @param replacement_function Pointer to the function target_function
+ // was patched to.
+ //
+ // @param original_function_stub Pointer to the stub returned when
+ // patching, that could be used to call the original version of the
+ // patched function. This function will also delete the stub, which after
+ // unpatching is useless.
+ //
+ // If your original call was
+ // origptr = Patch(VirtualAlloc, MyVirtualAlloc)
+ // then to undo it you would call
+ // Unpatch(VirtualAlloc, MyVirtualAlloc, origptr);
+ //
+ // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
+ // indicates success.
+ static SideStepError Unpatch(void* target_function,
+ void* replacement_function,
+ void* original_function_stub);
+
+ private:
+
+ // Patches a function by overwriting its first few bytes with
+ // a jump to a different function. This is similar to the RawPatch
+ // function except that it uses the stub allocated by the caller
+ // instead of allocating it.
+ //
+ // We call VirtualProtect to make the
+ // target function writable at least for the duration of the call.
+ //
+ // @param target_function A pointer to the function that should be
+ // patched.
+ //
+ // @param replacement_function A pointer to the function that should
+ // replace the target function. The replacement function must have
+ // exactly the same calling convention and parameters as the original
+ // function.
+ //
+ // @param preamble_stub A pointer to a buffer where the preamble stub
+ // should be copied. The size of the buffer should be sufficient to
+ // hold the preamble bytes.
+ //
+ // @param stub_size Size in bytes of the buffer allocated for the
+ // preamble_stub
+ //
+ // @param bytes_needed Pointer to a variable that receives the minimum
+ // number of bytes required for the stub. Can be set to NULL if you're
+ // not interested.
+ //
+ // @return An error code indicating the result of patching.
+ static SideStepError RawPatchWithStubAndProtections(void* target_function,
+ void *replacement_function,
+ unsigned char* preamble_stub,
+ unsigned long stub_size,
+ unsigned long* bytes_needed);
+
+ // A helper function used by RawPatchWithStubAndProtections -- it does
+ // everything but the VirtualProtect wsork. Defined in
+ // preamble_patcher_with_stub.cc.
+ static SideStepError RawPatchWithStub(void* target_function,
+ void *replacement_function,
+ unsigned char* preamble_stub,
+ unsigned long stub_size,
+ unsigned long* bytes_needed);
+};
+
+}; // namespace sidestep
+
+#endif // MEMORY_WATCHER_PREAMBLE_PATCHER_H__
diff --git a/chromium/tools/memory_watcher/preamble_patcher_with_stub.cc b/chromium/tools/memory_watcher/preamble_patcher_with_stub.cc
new file mode 100644
index 00000000000..31303065c36
--- /dev/null
+++ b/chromium/tools/memory_watcher/preamble_patcher_with_stub.cc
@@ -0,0 +1,174 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/*
+ * Implementation of PreamblePatcher
+ */
+
+#include "preamble_patcher.h"
+
+#include "mini_disassembler.h"
+
+// Definitions of assembly statements we need
+#define ASM_JMP32REL 0xE9
+#define ASM_INT3 0xCC
+
+namespace sidestep {
+
+SideStepError PreamblePatcher::RawPatchWithStub(
+ void* target_function,
+ void *replacement_function,
+ unsigned char* preamble_stub,
+ unsigned long stub_size,
+ unsigned long* bytes_needed) {
+ if ((NULL == target_function) ||
+ (NULL == replacement_function) ||
+ (NULL == preamble_stub)) {
+ ASSERT(false, "Invalid parameters - either pTargetFunction or "
+ "pReplacementFunction or pPreambleStub were NULL.");
+ return SIDESTEP_INVALID_PARAMETER;
+ }
+
+ // TODO(V7:joi) Siggi and I just had a discussion and decided that both
+ // patching and unpatching are actually unsafe. We also discussed a
+ // method of making it safe, which is to freeze all other threads in the
+ // process, check their thread context to see if their eip is currently
+ // inside the block of instructions we need to copy to the stub, and if so
+ // wait a bit and try again, then unfreeze all threads once we've patched.
+ // Not implementing this for now since we're only using SideStep for unit
+ // testing, but if we ever use it for production code this is what we
+ // should do.
+ //
+ // NOTE: Stoyan suggests we can write 8 or even 10 bytes atomically using
+ // FPU instructions, and on newer processors we could use cmpxchg8b or
+ // cmpxchg16b. So it might be possible to do the patching/unpatching
+ // atomically and avoid having to freeze other threads. Note though, that
+ // doing it atomically does not help if one of the other threads happens
+ // to have its eip in the middle of the bytes you change while you change
+ // them.
+ unsigned char* target = reinterpret_cast<unsigned char*>(target_function);
+
+ // First, deal with a special case that we see with functions that
+ // point into an IAT table (including functions linked statically
+ // into the application): these function already starts with
+ // ASM_JMP32REL. For instance, malloc() might be implemented as a
+ // JMP to __malloc(). In that case, we replace the destination of
+ // the JMP (__malloc), rather than the JMP itself (malloc). This
+ // way we get the correct behavior no matter how malloc gets called.
+ if (target[0] == ASM_JMP32REL) {
+ // target[1-4] holds the place the jmp goes to, but it's
+ // relative to the next instruction.
+ int relative_offset; // Windows guarantees int is 4 bytes
+ ASSERT1(sizeof(relative_offset) == 4);
+ memcpy(reinterpret_cast<void*>(&relative_offset),
+ reinterpret_cast<void*>(target + 1), 4);
+ // I'd like to just say "target = target + 5 + relative_offset" here, but
+ // I can't, because the new target will need to have its protections set.
+ return RawPatchWithStubAndProtections(target + 5 + relative_offset,
+ replacement_function, preamble_stub,
+ stub_size, bytes_needed);
+ }
+
+ // Let's disassemble the preamble of the target function to see if we can
+ // patch, and to see how much of the preamble we need to take. We need 5
+ // bytes for our jmp instruction, so let's find the minimum number of
+ // instructions to get 5 bytes.
+ MiniDisassembler disassembler;
+ unsigned int preamble_bytes = 0;
+ while (preamble_bytes < 5) {
+ InstructionType instruction_type =
+ disassembler.Disassemble(target + preamble_bytes, preamble_bytes);
+ if (IT_JUMP == instruction_type) {
+ ASSERT(false, "Unable to patch because there is a jump instruction "
+ "in the first 5 bytes.");
+ return SIDESTEP_JUMP_INSTRUCTION;
+ } else if (IT_RETURN == instruction_type) {
+ ASSERT(false, "Unable to patch because function is too short");
+ return SIDESTEP_FUNCTION_TOO_SMALL;
+ } else if (IT_GENERIC != instruction_type) {
+ ASSERT(false, "Disassembler encountered unsupported instruction "
+ "(either unused or unknown)");
+ return SIDESTEP_UNSUPPORTED_INSTRUCTION;
+ }
+ }
+
+ if (NULL != bytes_needed)
+ *bytes_needed = preamble_bytes + 5;
+
+ // Inv: cbPreamble is the number of bytes (at least 5) that we need to take
+ // from the preamble to have whole instructions that are 5 bytes or more
+ // in size total. The size of the stub required is cbPreamble + size of
+ // jmp (5)
+ if (preamble_bytes + 5 > stub_size) {
+ ASSERT1(false);
+ return SIDESTEP_INSUFFICIENT_BUFFER;
+ }
+
+ // First, copy the preamble that we will overwrite.
+ memcpy(reinterpret_cast<void*>(preamble_stub),
+ reinterpret_cast<void*>(target), preamble_bytes);
+
+ // Now, make a jmp instruction to the rest of the target function (minus the
+ // preamble bytes we moved into the stub) and copy it into our preamble-stub.
+ // find address to jump to, relative to next address after jmp instruction
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4244)
+#endif
+ int relative_offset_to_target_rest
+ = ((reinterpret_cast<unsigned char*>(target) + preamble_bytes) -
+ (preamble_stub + preamble_bytes + 5));
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+ // jmp (Jump near, relative, displacement relative to next instruction)
+ preamble_stub[preamble_bytes] = ASM_JMP32REL;
+ // copy the address
+ memcpy(reinterpret_cast<void*>(preamble_stub + preamble_bytes + 1),
+ reinterpret_cast<void*>(&relative_offset_to_target_rest), 4);
+
+ // Inv: preamble_stub points to assembly code that will execute the
+ // original function by first executing the first cbPreamble bytes of the
+ // preamble, then jumping to the rest of the function.
+
+ // Overwrite the first 5 bytes of the target function with a jump to our
+ // replacement function.
+ // (Jump near, relative, displacement relative to next instruction)
+ target[0] = ASM_JMP32REL;
+
+ // Find offset from instruction after jmp, to the replacement function.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4244)
+#endif
+ int offset_to_replacement_function =
+ reinterpret_cast<unsigned char*>(replacement_function) -
+ reinterpret_cast<unsigned char*>(target) - 5;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+ // complete the jmp instruction
+ memcpy(reinterpret_cast<void*>(target + 1),
+ reinterpret_cast<void*>(&offset_to_replacement_function), 4);
+ // Set any remaining bytes that were moved to the preamble-stub to INT3 so
+ // as not to cause confusion (otherwise you might see some strange
+ // instructions if you look at the disassembly, or even invalid
+ // instructions). Also, by doing this, we will break into the debugger if
+ // some code calls into this portion of the code. If this happens, it
+ // means that this function cannot be patched using this patcher without
+ // further thought.
+ if (preamble_bytes > 5) {
+ memset(reinterpret_cast<void*>(target + 5), ASM_INT3, preamble_bytes - 5);
+ }
+
+ // Inv: The memory pointed to by target_function now points to a relative
+ // jump instruction that jumps over to the preamble_stub. The preamble
+ // stub contains the first stub_size bytes of the original target
+ // function's preamble code, followed by a relative jump back to the next
+ // instruction after the first cbPreamble bytes.
+
+ return SIDESTEP_SUCCESS;
+}
+
+}; // namespace sidestep
diff --git a/chromium/tools/memory_watcher/scripts/finditem.pl b/chromium/tools/memory_watcher/scripts/finditem.pl
new file mode 100755
index 00000000000..36838ebc733
--- /dev/null
+++ b/chromium/tools/memory_watcher/scripts/finditem.pl
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+sub process_raw($$) {
+ my $file = shift;
+ my $search = shift;
+
+ my %leaks = ();
+
+ my $save = 0;
+ my $print = 0;
+ my $bytes = 0;
+ my $calls = 0;
+ my $sum_bytes = 0;
+ my $sum_calls = 0;
+
+ open (LOGFILE, "$file") or die("could not open $file");
+ while(<LOGFILE>) {
+ my $line = $_;
+ if ($line =~ m/([0-9]*) bytes, ([0-9]*) allocs/) {
+ $save = "";
+ $print = 0;
+ $bytes = $1;
+ $calls = $2;
+ }
+ elsif ($line =~ m/$search/) {
+ $print = 1;
+ }
+ elsif ($line =~ m/=============/) {
+ $save .= $line;
+ if ($print) {
+ print "$bytes bytes ($calls calls)\n";
+ print $save;
+ $sum_bytes += $bytes;
+ $sum_calls += $calls;
+ $save = "";
+ $print = 0;
+ $calls = 0;
+ }
+ }
+ $save .= $line;
+ }
+ print("TOTAL: $sum_bytes bytes ($sum_calls calls)\n");
+}
+
+
+# ----- Main ------------------------------------------------
+
+# Get the command line argument
+my $filename = shift;
+my $search = shift;
+
+# Process the file.
+process_raw($filename, $search);
diff --git a/chromium/tools/memory_watcher/scripts/memprof.pl b/chromium/tools/memory_watcher/scripts/memprof.pl
new file mode 100755
index 00000000000..d902e5e4fac
--- /dev/null
+++ b/chromium/tools/memory_watcher/scripts/memprof.pl
@@ -0,0 +1,116 @@
+#!/usr/bin/perl
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Given a memwatcher logfile, group memory allocations by callstack.
+#
+# Usage:
+#
+# memprof.pl <logfile>
+#
+# logfile -- The memwatcher.logXXXX file to summarize.
+#
+#
+#
+# Sample output:
+#
+# 54,061,617 100.00% AllocationStack::AllocationStack
+# 41,975,368 77.64% malloc
+# 11,886,592 21.99% VirtualAlloc
+# 7,168,000 13.26% v8::internal::OS::Allocate
+# 7,168,000 13.26% v8::internal::MemoryAllocator::AllocateRawMemory
+# 5,976,184 11.05% WebCore::V8Bridge::evaluate
+# 5,767,168 10.67% v8::internal::MemoryAllocator::AllocatePages
+# 5,451,776 10.08% WebCore::V8Proxy::initContextIfNeeded
+# ....
+#
+#
+#
+# ********
+# Note: The output is currently sorted by decreasing size.
+# ********
+#
+
+sub process_raw($$) {
+ my $file = shift;
+ my $filter = shift;
+
+ my %leaks = ();
+ my %stackframes = ();
+
+ my $blamed = 0;
+ my $bytes = 0;
+ my $hits = 0;
+ open (LOGFILE, "$file") or die("could not open $file");
+ while(<LOGFILE>) {
+ my $line = $_;
+#print "$line";
+ chomp($line);
+ if ($line =~ m/([0-9]*) bytes, ([0-9]*) allocs/) {
+
+ # If we didn't find any frames to account this to, log that.
+ if ($blamed == 0) {
+ $leaks{"UNACCOUNTED"} += $bytes;
+ }
+
+#print "START\n";
+ #print("stackframe " . $1 . ", " . $2 . "\n");
+ $hits = $2;
+ $bytes = $1;
+ %stackframes = (); # we have a new frame, clear the list.
+ $blamed = 0; # we haven't blamed anyone yet
+ }
+ elsif ($line =~ m/Total Bytes:[ ]*([0-9]*)/) {
+ $total_bytes += $1;
+ }
+ elsif ($line =~ m/=============/) {
+ next;
+ }
+ elsif ($line =~ m/[ ]*([\-a-zA-Z_\\0-9\.]*) \(([0-9]*)\):[ ]*([<>_a-zA-Z_0-9:]*)/) {
+# print("junk: " . $line . "\n");
+# print("file: $1\n");
+# print("line: $2\n");
+# print("function: $3\n");
+#
+
+ # blame the function
+ my $pig = $3;
+# my $pig = $1;
+
+ # only add the memory if this function is not yet on our callstack
+ if (!exists $stackframes{$pig}) {
+ $leaks{$pig} += $bytes;
+ }
+
+ $stackframes{$pig}++;
+ $blamed++;
+ }
+ }
+
+ # now dump our hash table
+ my $sum = 0;
+ my @keys = sort { $leaks{$b} <=> $leaks{$a} }keys %leaks;
+ for ($i=0; $i<@keys; $i++) {
+ my $key = @keys[$i];
+ printf "%11s\t%3.2f%%\t%s\n", comma_print($leaks{$key}), (100* $leaks{$key} / $total_bytes), $key;
+ $sum += $leaks{$key};
+ }
+ printf("TOTAL: %s\n", comma_print($sum));
+}
+
+# Insert commas into an integer after each three digits for printing.
+sub comma_print {
+ my $num = "$_[0]";
+ $num =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g;
+ return $num;
+}
+
+# ----- Main ------------------------------------------------
+
+# Get the command line argument
+my $filename = shift;
+my $filter = shift;
+
+# Process the file.
+process_raw($filename, $filter);
diff --git a/chromium/tools/memory_watcher/scripts/memtrace.pl b/chromium/tools/memory_watcher/scripts/memtrace.pl
new file mode 100755
index 00000000000..04a70fd8c29
--- /dev/null
+++ b/chromium/tools/memory_watcher/scripts/memtrace.pl
@@ -0,0 +1,146 @@
+#!/usr/bin/perl
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Blame callstacks for each memory allocation.
+# Similar to memprof.pl, will also try to filter out unuseful stacks.
+# TODO: better describe how these tools differ.
+#
+# Usage:
+#
+# memtrace.pl <logfile>
+#
+# logfile -- The memwatcher.logXXXX file to summarize.
+#
+#
+#
+# Sample output:
+#
+# 41,975,368 77.64% f:\sp\vctools\crt_bld\self_x86\crt\src\malloc.c (163): malloc
+# 2,097,152 3.88% c:\src\chrome1\src\webkit\pending\frameloader.cpp (3300): WebCore::FrameLoader::committedLoad
+# 1,572,864 2.91% c:\src\chrome1\src\webkit\port\bridge\v8bridge.cpp (214): WebCore::V8Bridge::evaluate
+# 1,572,864 2.91% c:\src\chrome1\src\webkit\glue\webframeloaderclient_impl.cc (1071): WebFrameLoaderClient::committedLoad
+# 1,572,864 2.91% c:\src\chrome1\src\v8\src\ast.h (1181): v8::internal::Visitor::Visit
+#
+#
+#
+
+
+sub process_raw($) {
+ my $file = shift;
+
+ my %leaks = ();
+
+ my $location_bytes = 0;
+ my $location_hits = 0;
+ my $location_blame = "";
+ my $location_last = "";
+ my $contains_load_lib = 0;
+ my $total_bytes = 0;
+ open (LOGFILE, "$file") or die("could not open $file");
+ while(<LOGFILE>) {
+ my $line = $_;
+#print "$line";
+ chomp($line);
+ if ($line =~ m/([0-9]*) bytes, ([0-9]*) allocs/) {
+
+#print "START\n";
+ # Dump "prior" frame here
+ if ($location_bytes > 0) {
+#print("GOTLEAK: $location_bytes ($location_hits) $location_blame\n");
+ if ($location_blame eq "") {
+ $location_blame = $location_last;
+ }
+ if (!$contains_load_lib) {
+ $leaks{$location_blame} += $location_bytes;
+ }
+ $location_bytes = 0;
+ $location_blame = "";
+ $contains_load_lib = 0;
+ }
+
+ #print("stackframe " . $1 . ", " . $2 . "\n");
+ $location_hits = $2;
+ $location_bytes = $1;
+ }
+ elsif ($line =~ m/Total Bytes:[ ]*([0-9]*)/) {
+ $total_bytes += $1;
+ }
+ elsif ($line =~ m/LoadLibrary/) {
+ # skip these, they contain false positives.
+ $contains_load_lib = 1;
+ next;
+ }
+ elsif ($line =~ m/=============/) {
+ next;
+ }
+ elsif ($line =~ m/Untracking untracked/) {
+ next;
+ }
+ elsif ($line =~ m/[ ]*([a-z]:\\[a-z]*\\[a-zA-Z_\\0-9\.]*) /) {
+ my $filename = $1;
+ if ($filename =~ m/memory_watcher/) {
+ next;
+ }
+ if ($filename =~ m/skmemory_stdlib.cpp/) {
+ next;
+ }
+ if ($filename =~ m/stringimpl.cpp/) {
+ next;
+ }
+ if ($filename =~ m/stringbuffer.h/) {
+ next;
+ }
+ if ($filename =~ m/fastmalloc.h/) {
+ next;
+ }
+ if ($filename =~ m/microsoft visual studio 8/) {
+ next;
+ }
+ if ($filename =~ m/platformsdk_win2008_6_1/) {
+ next;
+ }
+ if ($location_blame eq "") {
+ # use this to blame the line
+ $location_blame = $line;
+
+ # use this to blame the file.
+ # $location_blame = $filename;
+
+#print("blaming $location_blame\n");
+ }
+ } else {
+# print("junk: " . $line . "\n");
+ if (! ($line =~ m/GetModuleFileNameA/) ) {
+ $location_last = $line;
+ }
+ }
+ }
+
+ # now dump our hash table
+ my $sum = 0;
+ my @keys = sort { $leaks{$b} <=> $leaks{$a} }keys %leaks;
+ for ($i=0; $i<@keys; $i++) {
+ my $key = @keys[$i];
+ if (0 == $total_bytes) { $total_bytes = 1; }
+ printf "%11s\t%3.2f%%\t%s\n", comma_print($leaks{$key}), (100* $leaks{$key} / $total_bytes), $key;
+ $sum += $leaks{$key};
+ }
+ printf("TOTAL: %s\n", comma_print($sum));
+}
+
+# Insert commas into an integer after each three digits for printing.
+sub comma_print {
+ my $num = "$_[0]";
+ $num =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g;
+ return $num;
+}
+
+# ----- Main ------------------------------------------------
+
+# Get the command line argument
+my $filename = shift;
+
+# Process the file.
+process_raw($filename);
diff --git a/chromium/tools/memory_watcher/scripts/summary.pl b/chromium/tools/memory_watcher/scripts/summary.pl
new file mode 100755
index 00000000000..4ba10c1cc66
--- /dev/null
+++ b/chromium/tools/memory_watcher/scripts/summary.pl
@@ -0,0 +1,156 @@
+#!/usr/bin/perl
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Read a memtrace logfile from stdin and group memory allocations by logical
+# code component. The code component is guessed from the callstack, and
+# is something like {v8, sqlite, disk cache, skia, etc..}
+#
+# Usage:
+#
+# summary.pl
+#
+# [STDIN] -- The memwatcher.logXXXX file to summarize.
+#
+
+sub process_stdin() {
+ my %leaks = ();
+ my $total_bytes = 0;
+
+ while(<STDIN>) {
+ my $line = $_;
+ chomp($line);
+ my $bytes, $loc;
+ ($bytes, $loc) = ($line =~ m/[ \t]*([0-9]*)[ \t]*[0-9\.%]*[ \t]*(.*)/);
+ chomp($loc);
+ while(<STDIN>) {
+ my $cont = $_;
+ chomp($cont);
+ last if $cont =~ m/=====/;
+ $loc .= "\n" . $cont;
+ }
+ my $location_blame = "";
+
+# print "Found: $bytes, $loc\n";
+
+ if ($loc =~ m/v8::internal::Snapshot::Deserialize/) {
+ $location_blame = "v8 Snapshot Deserialize";
+ } elsif ($loc =~ m/RenderStyle::create/) {
+ $location_blame = "RenderStyle::create";
+ } elsif ($loc =~ m/v8::internal::OldSpace::SlowAllocateRaw/) {
+ $location_blame = "v8 OldSpace";
+ } elsif ($loc =~ m/sqlite/) {
+ $location_blame = "sqlite";
+ } elsif ($loc =~ m/ TransportDIB::Map/) {
+ $location_blame = "Shared Memory Backing Store";
+ } elsif ($loc =~ m/imagedecoder/) {
+ $location_blame = "img decoder";
+ } elsif ($loc =~ m/SkBitmap/) {
+ $location_blame = "skia";
+ } elsif ($loc =~ m/disk_cache/) {
+ $location_blame = "disk cache";
+ } elsif ($loc =~ m/skia/) {
+ $location_blame = "skia";
+ } elsif ($loc =~ m/:WSA/) {
+ $location_blame = "net";
+ } elsif ($loc =~ m/dns/) {
+ $location_blame = "net";
+ } elsif ($loc =~ m/trunk\\net/) {
+ $location_blame = "net";
+ } elsif ($loc =~ m/WinHttp/) {
+ $location_blame = "WinHttp";
+ } elsif ($loc =~ m/:I_Crypt/) {
+ $location_blame = "WinHttpSSL";
+ } elsif ($loc =~ m/CryptGetTls/) {
+ $location_blame = "WinHttpSSL";
+ } elsif ($loc =~ m/WinVerifyTrust/) {
+ $location_blame = "WinHttpSSL";
+ } elsif ($loc =~ m/Cert/) {
+ $location_blame = "WinHttpSSL";
+ } elsif ($loc =~ m/plugin/) {
+ $location_blame = "plugin";
+ } elsif ($loc =~ m/NP_/) {
+ $location_blame = "plugin";
+ } elsif ($loc =~ m/hunspell/) {
+ $location_blame = "hunspell";
+ } elsif ($loc =~ m/TextCodec/) {
+ $location_blame = "fonts";
+ } elsif ($loc =~ m/glyph/) {
+ $location_blame = "fonts";
+ } elsif ($loc =~ m/cssparser/) {
+ $location_blame = "webkit css";
+ } elsif ($loc =~ m/::CSS/) {
+ $location_blame = "webkit css";
+ } elsif ($loc =~ m/Arena/) {
+ $location_blame = "webkit arenas";
+ } elsif ($loc =~ m/WebCore::.*ResourceLoader::addData/) {
+ $location_blame = "WebCore *ResourceLoader addData";
+ } elsif ($loc =~ m/OnUpdateVisitedLinks/) {
+ $location_blame = "OnUpdateVisitedLinks";
+ } elsif ($loc =~ m/IPC/) {
+ $location_blame = "ipc";
+ } elsif ($loc =~ m/trunk\\chrome\\browser/) {
+ $location_blame = "browser";
+ } elsif ($loc =~ m/trunk\\chrome\\renderer/) {
+ $location_blame = "renderer";
+ } elsif ($loc =~ m/webcore\\html/) {
+ $location_blame = "webkit webcore html";
+ } elsif ($loc =~ m/webkit.*string/) {
+ $location_blame = "webkit strings";
+ } elsif ($loc =~ m/htmltokenizer/) {
+ $location_blame = "webkit HTMLTokenizer";
+ } elsif ($loc =~ m/javascriptcore/) {
+ $location_blame = "webkit javascriptcore";
+ } elsif ($loc =~ m/webkit/) {
+ $location_blame = "webkit other";
+ } elsif ($loc =~ m/safe_browsing/) {
+ $location_blame = "safe_browsing";
+ } elsif ($loc =~ m/VisitedLinkMaster/) {
+ $location_blame = "VisitedLinkMaster";
+ } elsif ($loc =~ m/NewDOMUI/) {
+ $location_blame = "NewDOMUI";
+ } elsif ($loc =~ m/RegistryControlledDomainService/) {
+ $location_blame = "RegistryControlledDomainService";
+ } elsif ($loc =~ m/URLRequestChromeJob::DataAvailable/) {
+ $location_blame = "URLRequestChromeJob DataAvailable";
+ } elsif ($loc =~ m/history_publisher/) {
+ $location_blame = "history publisher";
+ } else {
+ $location_blame = "unknown";
+ }
+
+ # Surface large outliers in an "interesting" group.
+ my $interesting_group = "unknown";
+ my $interesting_size = 10000000; # Make this smaller as needed.
+ # TODO(jar): Add this as a pair of shell arguments.
+ if ($bytes > $interesting_size && $location_blame eq $interesting_group) {
+ # Create a special group for the exact stack that contributed so much.
+ $location_blame = $loc;
+ }
+
+ $total_bytes += $bytes;
+ $leaks{$location_blame} += $bytes;
+ }
+
+ # now dump our hash table
+ my $sum = 0;
+ my @keys = sort { $leaks{$b} <=> $leaks{$a} }keys %leaks;
+ for ($i=0; $i<@keys; $i++) {
+ my $key = @keys[$i];
+ printf "%11s\t(%3.2f%%)\t%s\n", comma_print($leaks{$key}), (100* $leaks{$key} / $total_bytes), $key;
+ $sum += $leaks{$key};
+ }
+ printf("TOTAL: %s\n", comma_print($sum));
+}
+
+# Insert commas into an integer after each three digits for printing.
+sub comma_print {
+ my $num = "$_[0]";
+ $num =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g;
+ return $num;
+}
+
+# ----- Main ------------------------------------------------
+
+process_stdin();
diff --git a/chromium/tools/metrics/OWNERS b/chromium/tools/metrics/OWNERS
new file mode 100644
index 00000000000..b8146456564
--- /dev/null
+++ b/chromium/tools/metrics/OWNERS
@@ -0,0 +1,10 @@
+set noparent
+
+asvitkine@chromium.org
+isherman@chromium.org
+jar@chromium.org
+mpearson@chromium.org
+
+# Owners-in-training:
+# jwd@chromium.org
+
diff --git a/chromium/tools/metrics/actions/OWNERS b/chromium/tools/metrics/actions/OWNERS
new file mode 100644
index 00000000000..e57c08959a9
--- /dev/null
+++ b/chromium/tools/metrics/actions/OWNERS
@@ -0,0 +1,2 @@
+# per-file rules:
+per-file chromeactions.txt=*
diff --git a/chromium/tools/metrics/actions/chromeactions.txt b/chromium/tools/metrics/actions/chromeactions.txt
new file mode 100644
index 00000000000..8f074734883
--- /dev/null
+++ b/chromium/tools/metrics/actions/chromeactions.txt
@@ -0,0 +1,1640 @@
+0x5d4affbdc9e636fe AboutChrome
+0x6c3fb8ca36f60394 AboutConflicts
+0xe93a6d5909da6a5a AboutFlags_StartupTick
+0xbfdd432b8d9d4ad6 AboutFlags_background-webapps
+0x439284a07fb851bb AboutFlags_click-to-play
+0x10ffe0a8b323b586 AboutFlags_cloud-print
+0x4da52e00bdfac86a AboutFlags_cloud-print-proxy
+0xc5ec36aaa32ceff4 AboutFlags_confirm-to-quit
+0x4e8fe1c674de45dd AboutFlags_conflicting-modules-check
+0x4ebeea0717b98e89 AboutFlags_disable-chrome-to-mobile
+0xe9d2339d6b9225c7 AboutFlags_disable-outdated-plugins
+0x40c0bddfe31a67c2 AboutFlags_disable-pnacl
+0xf73b5212b48e2a75 AboutFlags_disable-print-preview
+0x088990bbea59a185 AboutFlags_disable-website-settings
+0xdddbf34cee2c636c AboutFlags_dns-server
+0x3add7fc42803849e AboutFlags_downloads-new-ui
+0x487390cc957aa352 AboutFlags_enable-chrome-to-mobile
+0x4eae5ccc2900dffa AboutFlags_enable-nacl
+0x91d89fbc43b29963 AboutFlags_enable-nacl-debug
+0x6d932203ed5c6ae8 AboutFlags_enable-nacl-exception-handling
+0x26ca6c633d183f66 AboutFlags_enable-pnacl
+0x1a3d598e2cd416a0 AboutFlags_enable-smooth-scrolling
+0x22268494c966e464 AboutFlags_enable-website-settings
+0x79571e31c2dc4d3c AboutFlags_experimental-location-features
+0x307b8a127f85947e AboutFlags_expose-for-tabs
+0x2c97f94b6aca4a22 AboutFlags_extension-apis
+0x3a73624e6d06ac2e AboutFlags_focus-existing-tab-on-open
+0x66a2e456dfe783d3 AboutFlags_gpu-canvas-2d
+0x0a1b6a5d816fde03 AboutFlags_indexeddb-use-leveldb
+0x6cb0582a680ffec6 AboutFlags_instant-autocomplete-immediately
+0x67b7031bb00a6917 AboutFlags_instant-type
+0x681dbf08b11af420 AboutFlags_match-preview
+0x0156f26c1be32122 AboutFlags_my-special-feature
+0x3327ba9002a2b7b9 AboutFlags_nacl-debug-mask
+0x94c46ee32cd0fd19 AboutFlags_nacl-gdb
+0xbec26a19fa263850 AboutFlags_nacl-gdb-script
+0xb41d9c886871e31a AboutFlags_page-prerender
+0x735ca25b198de8ab AboutFlags_prerender-from-omnibox
+0xb33861525ba727a4 AboutFlags_print-preview
+0x75b933619fb87fec AboutFlags_remoting
+0x4ef8419b680e7a19 AboutFlags_save-page-as-mhtml
+0xb9396e0515186060 AboutFlags_snap-start
+0x4efbca63b3accd5f AboutFlags_tabbed-options
+0x2ec81fb90d9bed1e AboutFlags_verbatim-instant
+0x6e65ea1edca0f441 AboutFlags_vertical-tabs
+0xb0140558fbb7c0bf AboutFlags_xss-auditor
+0x46299b11fb76c5d3 Accel_Back_Backspace
+0x942956b3c704a9a2 Accel_Back_F1
+0x651680cc43f0574d Accel_Back_Left
+0x9d53a3047a707543 Accel_BrightnessDown_F6
+0xb05e783429d6cfac Accel_BrightnessUp_F7
+0x2fa7197377421869 Accel_Exit_First_Q
+0x75c842188f8d6864 Accel_Exit_Second_Q
+0x7f2c75700d286c16 Accel_FocusLocation_D
+0xe566241731cecfbb Accel_FocusLocation_L
+0xb4f736d60280d914 Accel_FocusSearch_E
+0xbe8f2bb497e569c3 Accel_FocusSearch_K
+0x87886216ce3f147d Accel_Forward_Backspace
+0x5aa4a40eb4d92d0a Accel_Forward_F2
+0xad7e6131ff6f2528 Accel_Forward_Right
+0x36adab865c373745 Accel_Fullscreen_F4
+0x125f05329e660307 Accel_KeyboardBrightnessDown_F6
+0xcdd268156ab80bb1 Accel_KeyboardBrightnessUp_F7
+0xb3ca99d79240c92f Accel_LockScreen_L
+0x8fadf02749171923 Accel_LockScreen_LockButton
+0xaf0a974743d27634 Accel_LockScreen_PowerButton
+0x290302f64fd4dfe1 Accel_Maximize_Restore_F4
+0x5e6bce93ecde1df8 Accel_NewTab_T
+0x5a27559e6846a75e Accel_NextWindow_F5
+0xc217e3bb30e9a004 Accel_NextWindow_Tab
+0x450e0851cdca9dba Accel_Overview_F5
+0x2e92845dc8edee91 Accel_PrevWindow_F5
+0x49b33857117c4c43 Accel_PrevWindow_Tab
+0xa2654c422408df28 Accel_Reload_F3
+0x6db94baf96eb6cfd Accel_Reload_R
+0xe315330404ef14a8 Accel_Search_LWin
+0x01b760c64064556f Accel_SelectNextTab
+0x86e5b771da4dc62f Accel_SelectPreviousTab
+0x178d1faf1167b4ca Accel_ShutDown_PowerButton
+0x7974ffb673dd5475 Accel_VolumeDown_F9
+0xbe6aee0aaab8ed8a Accel_VolumeMute_F8
+0x1cbd5b055dc9a3cc Accel_VolumeUp_F10
+0x649461e26c8e5796 AcceptedGeneratedKeyword
+0x2b6ed5e3f78e1295 AcceptedKeyword
+0xaa16d48a61361aa6 AcceptedKeywordHint
+0x21cdf71f12d41976 ActionBox.ClickButton
+0xbd451ad0142aa0c0 ActionBox.FindShareHandlers
+0xe86a88a8a34848a8 ActiveBrowserChanged
+0xb52f7beb7f11bedf ActiveTabChanged
+0x966cdbb949bad0d7 AppCloseButton_Clk
+0xfc0c75574fa0f498 AppList_ClickOnApp
+0x73d7010c18cf1912 AppList_ClickOnAppFromSearch
+0xdd57b39909cb275a AppList_Search
+0x9ff9ef57d8d1d87c AutoDetectChange
+0x0557fa923dcee4d0 Back
+0xc66d44d8107c5f5d BackColor
+0xcafd9c09ee856f4d BackMenu_ChapterClick1
+0x0f870d70d3ad63af BackMenu_ChapterClick10
+0xcc7f480485be490f BackMenu_ChapterClick11
+0x66df4c323616cc9c BackMenu_ChapterClick12
+0x6ec9591704e695aa BackMenu_ChapterClick13
+0x58c363a6b68f5ea5 BackMenu_ChapterClick14
+0xce465328fcddd205 BackMenu_ChapterClick15
+0x537f15b23c6f30fd BackMenu_ChapterClick16
+0x59fc3ff15b0285ce BackMenu_ChapterClick17
+0x76eff190094eeebd BackMenu_ChapterClick18
+0x612d4da6cc153fcb BackMenu_ChapterClick19
+0x0a2a978da163a692 BackMenu_ChapterClick2
+0xaae08324262e26af BackMenu_ChapterClick3
+0x92f71dc4c198baa5 BackMenu_ChapterClick4
+0xfbeb6fe82a534622 BackMenu_ChapterClick5
+0x3b6f45a1f7eba171 BackMenu_ChapterClick6
+0x0b70734d408d755b BackMenu_ChapterClick7
+0x119b707f7f07cefe BackMenu_ChapterClick8
+0xb74f7eb6d083cb24 BackMenu_ChapterClick9
+0x8263388629c2ea39 BackMenu_HistoryClick1
+0x3a4283b20c70c670 BackMenu_HistoryClick10
+0xa283fd8a15a4e007 BackMenu_HistoryClick11
+0xd183cc11491b8574 BackMenu_HistoryClick12
+0x01409b3abb9faf3f BackMenu_HistoryClick13
+0x1cf609ef7031b464 BackMenu_HistoryClick14
+0xbbf3b3884419f441 BackMenu_HistoryClick15
+0x525beb7c7bf0b6c2 BackMenu_HistoryClick16
+0x087081f30a41a309 BackMenu_HistoryClick17
+0xe72486ef9669532b BackMenu_HistoryClick18
+0xd551fbd2fbcf39f3 BackMenu_HistoryClick19
+0xb4d488c6dbd86f28 BackMenu_HistoryClick2
+0xf3949ca015f2facd BackMenu_HistoryClick3
+0x314bb467b300d16f BackMenu_HistoryClick4
+0x2a8ce062be9f62c5 BackMenu_HistoryClick5
+0x6fda0344ca038ae7 BackMenu_HistoryClick6
+0x743a926f56fd079a BackMenu_HistoryClick7
+0xca86e954d3d40ec0 BackMenu_HistoryClick8
+0x24dc0dd3b2471a22 BackMenu_HistoryClick9
+0xd31dee084a5166e5 BackMenu_Popup
+0x478e9b82a50ffea5 BackMenu_ShowFullHistory
+0x048733a8c6205d00 BackgroundImageCache
+0x554b7c860c749c2f BadMessageTerminate_ACDH
+0x878b28b309d1205e BadMessageTerminate_AOF
+0xec6518c4af50b7ac BadMessageTerminate_BMF
+0x1f57dc66c6c91837 BadMessageTerminate_BPE
+0x0eba05c9a1e2be6a BadMessageTerminate_BPGM
+0x5a858938e484c903 BadMessageTerminate_BRPH
+0x6f41bf748eb54008 BadMessageTerminate_DBMF
+0xd910b7f4e1b53c11 BadMessageTerminate_DSMF
+0x3c463d9eb1c92f64 BadMessageTerminate_DSMF_1
+0x8b956c45b0f38be9 BadMessageTerminate_DSMF_2
+0x6ebaa5e3651107fa BadMessageTerminate_EFD
+0xff06108fb2aa73fa BadMessageTerminate_FAMF
+0xbecb3852be04c506 BadMessageTerminate_IDBMF
+0xd7e4d61883121c76 BadMessageTerminate_NC
+0x448f44d226b839b7 BadMessageTerminate_NC17
+0xd267646495d87640 BadMessageTerminate_RDH
+0xce2d3186346ab161 BadMessageTerminate_RVD
+0xf845124429e7aa80 BadMessageTerminate_RVH
+0xcb59a352ad13dc91 BadMessageTerminate_RWH
+0xa47427921bd8233b BadMessageTerminate_RWH1
+0x1b40d08165319763 BadMessageTerminate_RWH2
+0xb4074307cbcb96bd BadMessageTerminate_RWH3
+0xa00e08812a4284c2 BadMessageTerminate_RWH4
+0xefc9deffa33ee67d BadMessageTerminate_RWH5
+0xc4874f0e8e8b60aa BadMessageTerminate_WPH
+0x56649dd19258ed1f BindingsMismatchTerminate_RVH_WebUI
+0x85a700c6e9915ca8 BindingsMismatch_GetProcessHostPerSite
+0x1d145f0af708242c BlockNonsandboxedPlugins_Disable
+0xd80cc9291c9c82a9 BlockNonsandboxedPlugins_Enable
+0xe0daa169d443430e BlockedPluginInfobar.AllowThisTime
+0xbc5f7815d41f0a0a BlockedPluginInfobar.AlwaysAllow
+0xa6092c47f7cd698b BlockedPluginInfobar.Closed
+0xf73bbd9fdcaeb1f9 BlockedPluginInfobar.Dismissed
+0x4937bd47014fb3e0 BlockedPluginInfobar.LearnMore
+0x127e30ad4cde6b00 BlockedPluginInfobar.Shown
+0x4353c1e2880c75be BlockedPluginInfobar.Shown.Java
+0x84cc82257207df8d BlockedPluginInfobar.Shown.QuickTime
+0x819dbe166b094c47 BlockedPluginInfobar.Shown.RealPlayer
+0x65add1afd150b840 BlockedPluginInfobar.Shown.Shockwave
+0x0ef80834f3e539cc BlockedPluginInfobar.Shown.WindowsMediaPlayer
+0x114c3050111d8b8d Bold
+0x084d04c506da33c4 BookmarkAdded
+0x02f476e54c6d58bd BookmarkBarFolder_CtxMenu
+0x3012b56b98c28823 BookmarkBarFolder_DragEnd
+0xe71c0ba72ca2f331 BookmarkBarFolder_DragStart
+0x4213d5e4d5da1c0a BookmarkBar_ContextMenu_Add
+0x1ce97170a30f2fdd BookmarkBar_ContextMenu_Edit
+0xbe267767bb380a0d BookmarkBar_ContextMenu_NewFolder
+0x41b46cb5ee579e4a BookmarkBar_ContextMenu_Open
+0xc0b2c7f3e0cf1d69 BookmarkBar_ContextMenu_OpenAll
+0xb6828d311b612fdd BookmarkBar_ContextMenu_OpenAllInNewWindow
+0x95a93ad59fa23f78 BookmarkBar_ContextMenu_OpenAllIncognito
+0x798f8467fbe49e1e BookmarkBar_ContextMenu_OpenInNewTab
+0x14c4432cb3aca04b BookmarkBar_ContextMenu_OpenInNewWindow
+0xd8a39c089af645f1 BookmarkBar_ContextMenu_Remove
+0xa90364ba80763db0 BookmarkBar_ContextMenu_RemoveFromBookmarkBar
+0xa905159308ac6adc BookmarkBar_ContextMenu_ShowInFolder
+0x07801d0423d26682 BookmarkBar_CtxMenu
+0x8623e5f54147dbe6 BookmarkBar_DragButton
+0x4b37738130b32b3e BookmarkBar_DragEnd
+0x6c0fc567d362960e BookmarkBar_DragFromFolder
+0xeec5d4ade759d651 BookmarkBar_DragRecentlyBookmarked
+0xeffa5b8ce7f96fd9 BookmarkBar_DragStart
+0x949073bf8996b6c8 BookmarkBar_ShowOtherBookmarks
+0xef415d0bbf795b32 BookmarkBar_ShowRecentlyBookmarked
+0xd4d041fb05dcaebf BookmarkBubble_ChangeParent
+0x83076d556121e076 BookmarkBubble_ChangeTitleInBubble
+0x4cc462516fa2889d BookmarkBubble_Edit
+0x58cace8d3ebf1abe BookmarkBubble_EditFromCombobox
+0xf7694a5980ded770 BookmarkBubble_Options
+0x39ef6892d936d7a7 BookmarkBubble_RemoveFromBookmarkBar
+0x75e42372b72c1861 BookmarkBubble_ShowOnBookmarkBar
+0x30597ba5e2be6f6d BookmarkBubble_Unstar
+0xfd805402bb43ad35 BookmarkManager_Command_AddPage
+0xf415e2985a9b8797 BookmarkManager_Command_Copy
+0xd652521dd6f6520d BookmarkManager_Command_Cut
+0xf63d235dce12af6c BookmarkManager_Command_Delete
+0xeb9d14b63c668935 BookmarkManager_Command_Edit
+0x6952f508cca0af6c BookmarkManager_Command_Export
+0x07b4870fefd41631 BookmarkManager_Command_Import
+0x38f61b3a1f189cf1 BookmarkManager_Command_NewFolder
+0xfe57bff660e9bfdc BookmarkManager_Command_OpenInNewTab
+0xc60afc5e287d7673 BookmarkManager_Command_OpenInNewWindow
+0x4708046b0cfa4229 BookmarkManager_Command_OpenInSame
+0x1b3262b87b17f67c BookmarkManager_Command_OpenIncognito
+0x81230a6e417dcd81 BookmarkManager_Command_Paste
+0x35fe4acf56dc3bf4 BookmarkManager_Command_ShowInFolder
+0x000b578d014a1fac BookmarkManager_Command_Sort
+0x911ace5e57087cf7 BookmarkManager_Command_UndoDelete
+0x6596199ad9e751f9 BookmarkManager_Command_UndoGlobal
+0x4ac8df00196c66e3 BookmarkManager_Command_UndoNone
+0x1671befd86500f4c BookmarkManager_Export
+0x2a8f60054baba3eb BookmarkManager_Import
+0x6528526502a5491e BookmarkManager_NavigateTo_BookmarkBar
+0x1302e50e6a427538 BookmarkManager_NavigateTo_Mobile
+0x5103f6e198f61079 BookmarkManager_NavigateTo_Other
+0xbbc7d061af736ad3 BookmarkManager_NavigateTo_Recent
+0x5b3873d060943bd9 BookmarkManager_NavigateTo_Search
+0x2540c3dd2d046919 BookmarkManager_NavigateTo_SubFolder
+0xfc2f9e1efe0612ba BookmarkManager_Sort
+0xc7c989d7aa14f64d BookmarkManager_Sync
+0xec92650848f88dda BookmarkMenu_clicked
+0xd1cd299109c75a4c Bookmarks_Search
+0xbd8c276496f8eb7a BrowserPlugin.Guest.AbnormalDeath
+0x39907654af4d7a8a BrowserPlugin.Guest.Attached
+0x371d5e60b00738d9 BrowserPlugin.Guest.Crashed
+0x854cc1f139ba9418 BrowserPlugin.Guest.Create
+0xa1822ac47db91018 BrowserPlugin.Guest.DidNavigate
+0xde8be5ce26955605 BrowserPlugin.Guest.Hung
+0xa369e99aa2e21969 BrowserPlugin.Guest.Killed
+0x428cf267aeb35e28 BrowserPlugin.Guest.Navigate
+0xdd4859340407e122 BrowserPlugin.Guest.PermissionRequest
+0x20ba04d2331f9bfa BrowserPlugin.Guest.PermissionRequest.Download
+0x8d7c904ec99c12fd BrowserPlugin.Guest.PermissionRequest.Geolocation
+0xf9453f6f98d12f02 BrowserPlugin.Guest.PermissionRequest.Media
+0x2b75a893f779e6df BrowserPlugin.Guest.PermissionRequest.NewWindow
+0x2ff464e34165d946 BrowserPlugin.Guest.PermissionRequest.PointerLock
+0x69b219de7f17c077 BrowserPlugin.Guest.Responsive
+0x7784cf1f8b1cc3f0 BrowserPlugin.Guest.Terminate
+0x24941c4fd42fb51f CanCommitURL_BlockedAndKilled
+0xea4788705e6873b4 Cancel
+0xb1c07c66ce4ae2ac Caption_ClickTogglesMaximize
+0x96c3ac2d2a5d9dba Caption_GestureTogglesMaximize
+0x89394b102e55da81 ClearAuthenticationCache
+0x6bd5f5b094096aa7 ClearBrowsingData_Autofill
+0xae5b20986fb024db ClearBrowsingData_Cache
+0xb603e4fc4d7fe748 ClearBrowsingData_ContentLicenses
+0x6755e17f118c99d8 ClearBrowsingData_Cookies
+0xea9b835bf0310f85 ClearBrowsingData_Downloads
+0x02a6a06a2b91e758 ClearBrowsingData_Everything
+0xe3c9686626019346 ClearBrowsingData_History
+0x86678d0ede469c46 ClearBrowsingData_LSOData
+0x4c15666f9dd774eb ClearBrowsingData_LastDay
+0xbbbdc8f919aaba08 ClearBrowsingData_LastHour
+0xf38b7fedd47d32dc ClearBrowsingData_LastMonth
+0xa18138df43b60210 ClearBrowsingData_LastWeek
+0xe4d7f2be93ee4d1e ClearBrowsingData_MaskContainsExtension
+0xadd630995b43ce2f ClearBrowsingData_MaskContainsProtectedWeb
+0x1f885e1523585d6f ClearBrowsingData_MaskContainsUnprotectedWeb
+0x511e8366cdda3890 ClearBrowsingData_Passwords
+0x3db76495a0acc98c ClearBrowsingData_ServerBoundCerts
+0xdaaff0c5b7682b18 ClearBrowsingData_ShaderCache
+0x6d69a061f7adf595 ClearBrowsingData_ShowDlg
+0x9fd631c62234969a ClearSelection
+0x49c37636ddeb5a10 ClearSiteDataOnExitDisabled
+0xf63362e0c7d7420d ClearSiteDataOnExitEnabled
+0xdf8129e4f853f264 ClickDisableGpuAcceleration
+0xf2c974774a0fd57e ClickToPlay_AllowAlways
+0x3589e51b0b1bf730 ClickToPlay_Dismiss_Infobar
+0xe1b2d67ea37c5ba0 ClickToPlay_InfobarShown
+0xcfe5a8d495d7df34 ClickToPlay_LoadAll_Bubble
+0xb30dcb1850e21bce ClickToPlay_LoadAll_Infobar
+0x9cd1157e30fc2b55 ClickedBookmarkBarAppsShortcutButton
+0x57b3678b429935ee ClickedBookmarkBarFolder
+0x55c851e7c3d9a792 ClickedBookmarkBarURLButton
+0x4f667771b8f484b1 CloseAllSuppressedPopups
+0x74f6ce7e0602ca13 CloseButton_Clk
+0xde70efb3bc9fe575 CloseFromContextMenu
+0x9436ccb9a5cc6a27 CloseTab
+0x4443008dac19bfbc CloseTabByKey
+0x7596c9721c97c14c CloseTab_Accelerator
+0xd477cbce1681d404 CloseTab_Mouse
+0x4b31de70a21d7903 CloseWebApp
+0xdf8926d323575ff8 CloseWindow
+0xcd94a7d0199de11d CloseWindowByKey
+0xa0ebbbdb0eca8d89 ConflictBadge
+0x355517777b3f002e ConflictingModuleNotificationDismissed
+0x2f1ba1d06c32c45d ConflictingModuleNotificationShown
+0x33056b44f816c204 CookieBlockingDisabledPerDefault
+0xcc192d44d8f426c7 CookieBlockingEnabledPerDefault
+0x5fb63579fc981698 Copy
+0x89d1b3eda3d01e3a CopyToFindPboard
+0xb3d0f42456c6eaf6 CopyURLToClipBoard
+0x2aeb39c03cc86464 CreateLink
+0x1225d110ef7fba17 CreateProfile
+0x30604f84327d0ae5 CreateShortcut
+0x8b83a029888765ac CriticalNotificationShown
+0x3811e868a8b2639a CriticalNotification_AutoRestart
+0x74d29a646c3b335c CriticalNotification_Ignore
+0x417f35273c2e009b CriticalNotification_Restart
+0xfdf6ee64a0588855 Cryptohome.PKCS11InitFail
+0xeb334dca00e390e0 Cut
+0xb94d8a074eddd267 Debugger
+0xf2a6c498fb90ee34 Delete
+0xee9ce204f091eb10 DeleteBackward
+0x77996bb1dd52320d DeleteForward
+0xef062a4139c5c9f7 DeleteSelection
+0x7845bb87dfa671c5 DeleteToEndOfParagraph
+0x6c02931afa83fea8 DeleteWordBackward
+0x433dee161f756bb5 DeleteWordForward
+0x6efd3c1be94b4370 Destination_Application_Edit
+0x599586022e671645 Destination_Application_Launch
+0x7311c4dcd9426448 Destination_Application_Uninstall
+0x2caa887c60d0edea Destination_Bookmarks
+0x06fe9a0e5226b124 Destination_Bookmarks_OpenURL
+0x215c802c8c94cbed Destination_Downloads
+0x0813fdaffe0ea8c3 Destination_History
+0xdff1c6338f5f5371 Destination_History_OpenURL
+0x9d2d922e923f97f9 Destination_MostVisited
+0xee9739d40c3c4a7a Destination_MostVisited_OpenURL
+0x68b765b881701d50 Destination_Sessions
+0xd3e90631d6d04d51 DevTools_InspectElement
+0xbadaf91b6bdbbe68 DevTools_ToggleConsole
+0xddaad2f5e9238157 DevTools_ToggleWindow
+0xe581401517f920ca DisabledExtensionNotificationDismissed
+0x240b0da0a404d35c DisabledExtensionNotificationShown
+0xdad0f491267f672e DockingWindow_Bottom
+0x7ecb78846fadf9bf DockingWindow_BottomHalf
+0xc818526e20834ebf DockingWindow_Left
+0xf87264dd1cac30d9 DockingWindow_LeftHalf
+0xa9f758a358041079 DockingWindow_Maximize
+0xc68b578019349940 DockingWindow_Right
+0xec44ad3c479571f4 DockingWindow_RightHalf
+0x91991a7061775526 DockingWindow_Top
+0xed75712b0eb1913c Duplicate
+0xae5fcc3ad3a00c19 EditApplicationSettings
+0x0326e6132edca57b EditKeywords
+0x2e08637d43bc3450 EditSearchEngines
+0x9a2fdef24427ff67 EmailPageLocation
+0xb63daeca06ecea16 EnterFullScreenWithWrenchMenu
+0xfef46e5063ce3dc7 Exit
+0xdf56dffe242f621a Extensions.ExtensionInstalled
+0x4f07c158c8047ab9 Extensions.ExtensionUninstalled
+0x08566bf746b7f665 Extensions.IDChangedError
+0xa295e3ad39bbacc0 Extensions.WebStoreLaunch
+0xbea4c2c8eb82d058 Feedback
+0x4268aeb48d5c0d1e FileBrowser.CreateNewFolder
+0x604a1468d08b7c7b FileBrowser.PhotoEditor.Edit
+0xca74d47b273dd801 FileBrowser.PhotoEditor.View
+0xd1b4f6b656a826e8 FilterURLTermiate_About
+0x933a3a418a658dec FilterURLTermiate_Blocked
+0x6a372395e62bd36e FilterURLTermiate_Invalid
+0x4cfa6c981549e990 Find
+0x058404d575478e31 FindNext
+0xca56592cf013fc40 FindPrevious
+0xd9b084b400f26439 FindString
+0x79f97bfa526b56ec FirstRunDef_Accept
+0x7ff73528feb7491b FocusAppMenu
+0x05804843ffe72695 FocusBookmarksToolbar
+0x44c489e30171039c FocusChromeOSStatus
+0x1e226eae1a9e27ee FocusInfobars
+0xff4066491e7794bc FocusLocation
+0x930bb978f3a88be2 FocusNextPane
+0x5e6c303e567af436 FocusPageAndAppMenus
+0x658708a96ac44ccc FocusPreviousPane
+0x5b7b952796f109ad FocusSearch
+0xc27e065ab57a01e7 FocusToolbar
+0x12d7f80b419064fa FontName
+0x24b0296570b11c95 FontSize
+0x3c2f5208ba19e684 FontSizeDelta
+0xe45960835dd83532 ForeColor
+0x674e7408732120dc FormatBlock
+0x67d2f6740a8eaebf Forward
+0x407c6f01fc926581 ForwardDelete
+0x0659a6d28eeb3cdc ForwardMenu_ChapterClick1
+0x1cf8a9593dddd549 ForwardMenu_ChapterClick10
+0x282fb4c4773f6091 ForwardMenu_ChapterClick11
+0x7aaaba5ddf181715 ForwardMenu_ChapterClick12
+0xbf183c3b27f4612a ForwardMenu_ChapterClick13
+0x7b457b6824846628 ForwardMenu_ChapterClick14
+0xe7b6c76310cf28a0 ForwardMenu_ChapterClick15
+0xf83ba97f2dc5eda7 ForwardMenu_ChapterClick16
+0x9f7e9db5377a87fd ForwardMenu_ChapterClick17
+0x3b7969fdde988c47 ForwardMenu_ChapterClick18
+0xe00eaa33028aef1e ForwardMenu_ChapterClick19
+0x22ae6afaebb88ede ForwardMenu_ChapterClick2
+0xeaf788ceb40b4c52 ForwardMenu_ChapterClick3
+0xc36c2fcdcce64d3c ForwardMenu_ChapterClick4
+0xa4989f324b58fed9 ForwardMenu_ChapterClick5
+0x0f52ae4eda2f03a2 ForwardMenu_ChapterClick6
+0x50b4aac8ef09fad6 ForwardMenu_ChapterClick7
+0x6ad416ed5bbe25c3 ForwardMenu_ChapterClick8
+0xd636afb40773f667 ForwardMenu_ChapterClick9
+0x80457994e5624cb9 ForwardMenu_HistoryClick1
+0x4afed56ff6097552 ForwardMenu_HistoryClick10
+0xdc2821e4b1e4f4a5 ForwardMenu_HistoryClick11
+0x49d0080788fb2dcf ForwardMenu_HistoryClick12
+0x93c16e3dfa87e30e ForwardMenu_HistoryClick13
+0x73d941830a276551 ForwardMenu_HistoryClick14
+0xe7579f3c29b77b5b ForwardMenu_HistoryClick15
+0xb9c4a0ec5f6fdce5 ForwardMenu_HistoryClick16
+0x7c4fb0eac18dc2f7 ForwardMenu_HistoryClick17
+0x3130d901f8b9c6fe ForwardMenu_HistoryClick18
+0x2255d4f02bee3df3 ForwardMenu_HistoryClick19
+0xa975db997d781b24 ForwardMenu_HistoryClick2
+0xc22f8eaba64014d3 ForwardMenu_HistoryClick3
+0x4cadc0f6a99ba415 ForwardMenu_HistoryClick4
+0xe2f627fd545952fb ForwardMenu_HistoryClick5
+0x41b16a28f2130885 ForwardMenu_HistoryClick6
+0xf9a72fbc4c89c2b6 ForwardMenu_HistoryClick7
+0x4787fdb9e4526676 ForwardMenu_HistoryClick8
+0xb685d7994214aa1f ForwardMenu_HistoryClick9
+0xb8ea5cd4ac9a7a71 ForwardMenu_Popup
+0x87bdcab6bfd481db ForwardMenu_ShowFullHistory
+0x5f075ae3e1f9d038 Go
+0xab2334cdb766e7c7 GoogleNow.ButtonClicked0
+0xc06f4ecf7cf01b27 GoogleNow.ButtonClicked1
+0x813aeef215b68741 GoogleNow.Dismissed
+0x436c20892470d838 GoogleNow.MessageClicked
+0x80726a05369be7ca GoogleNow.WelcomeToastClickedNo
+0x1e6b0ae24163b1e8 GoogleNow.WelcomeToastClickedYes
+0x7813d5bea46a5fa8 GoogleNow.WelcomeToastDismissed
+0xd6c29b06a8c7e3e2 GpuAccelerationDisabled
+0xd18fed7efb6cf062 GpuAccelerationEnabled
+0x696c3c52634726aa HiliteColor
+0x77201c4b10451e59 HistoryPage_BookmarkStarClicked
+0x6590f397656717f0 HistoryPage_CancelRemoveSelected
+0x0368c6ea1d547d64 HistoryPage_ConfirmRemoveSelected
+0x29ad2e81f9dd07b0 HistoryPage_EntryLinkClick
+0x408ecf8ef58e563e HistoryPage_EntryLinkRightClick
+0xef342c7f49d28270 HistoryPage_EntryMenuRemoveFromHistory
+0xa99f2b83f809c313 HistoryPage_EntryMenuShowMoreFromSite
+0xb58708176abcc0fe HistoryPage_InitClearBrowsingData
+0x0138978105397298 HistoryPage_NewerHistoryClick
+0x5027e981a37ad402 HistoryPage_NewestHistoryClick
+0xd47b8fce881ce2df HistoryPage_OlderHistoryClick
+0xea2d5f6015fefa6c HistoryPage_RemoveSelected
+0x00431057dee9c3a2 HistoryPage_Search
+0xee4e188d1a5818c1 HistoryPage_SearchResultClick
+0xee812ce81df64b01 HistoryPage_SearchResultRemove
+0x4869b7ac0caae3fe History_DeleteHistory
+0xddf00e6e13ebc7ab History_DragIcon
+0xca7db0b9cda2eecd History_DragThumbnail
+0xdf8379d1cab60cbf History_Search
+0x8cf04a9734132302 Home
+0x3f8725913f9606e0 ImportLockDialogCocoa_Shown
+0x10209a50a49ea88f ImportLockDialogGtk_Shown
+0x03154e02d9a7d1b0 ImportLockDialogView_Shown
+0x2679e82f33d66fc0 Import_ShowDlg
+0x497470e76a40fc53 Indent
+0xddbd530e88f0baad InputMethodOptions_Open_chewing
+0x4b9b7bb2668d0482 InputMethodOptions_Open_english-m
+0xfe212a1637f75443 InputMethodOptions_Open_hangul
+0xf51582a1f3563c5d InputMethodOptions_Open_m17n:am:sera
+0x155fe2aa889c6475 InputMethodOptions_Open_m17n:ar:kbd
+0xddee376a378bb55a InputMethodOptions_Open_m17n:bn:itrans
+0x702d3712351014c9 InputMethodOptions_Open_m17n:fa:isiri
+0xf3d0bd08d56571df InputMethodOptions_Open_m17n:gu:itrans
+0xcd3d52a63eb9d19f InputMethodOptions_Open_m17n:hi:itrans
+0x76e4ec0d7dac8fbd InputMethodOptions_Open_m17n:kn:itrans
+0x4005c392a6808200 InputMethodOptions_Open_m17n:ml:itrans
+0x2a6f509c2aa50853 InputMethodOptions_Open_m17n:mr:itrans
+0x231bb5b79df1109d InputMethodOptions_Open_m17n:ta:inscript
+0x4f6c3bf8089610a3 InputMethodOptions_Open_m17n:ta:itrans
+0x641ffe0ae23919d9 InputMethodOptions_Open_m17n:ta:phonetic
+0x74ac378c41355823 InputMethodOptions_Open_m17n:ta:tamil99
+0x44628dae21677214 InputMethodOptions_Open_m17n:ta:typewriter
+0xab2182c49b66b7d6 InputMethodOptions_Open_m17n:te:itrans
+0x84a453cc41b70ade InputMethodOptions_Open_m17n:th:kesmanee
+0x781cb9476ef74fb6 InputMethodOptions_Open_m17n:th:pattachote
+0x7ed4a3c1dbbea563 InputMethodOptions_Open_m17n:th:tis820
+0x515db9088433579e InputMethodOptions_Open_m17n:vi:tcvn
+0x28585f828d27064e InputMethodOptions_Open_m17n:vi:telex
+0xaa5bd22b752b2402 InputMethodOptions_Open_m17n:vi:viqr
+0x32caeac9c52a0b3e InputMethodOptions_Open_m17n:vi:vni
+0x9b5fe154dcfed5fc InputMethodOptions_Open_m17n:zh:cangjie
+0x4b904484c5ae5ef9 InputMethodOptions_Open_m17n:zh:quick
+0xd760683dc9d7524f InputMethodOptions_Open_mozc
+0xf323966e4ec000ab InputMethodOptions_Open_mozc-chewing
+0xaf5b5ca01e17f82f InputMethodOptions_Open_mozc-dv
+0xd5513441251b0dfe InputMethodOptions_Open_mozc-hangul
+0x560b367165104ca0 InputMethodOptions_Open_mozc-jp
+0xfc8099598cc3d1e6 InputMethodOptions_Open_pinyin
+0xcef96af4d892e9ab InputMethodOptions_Open_pinyin-dv
+0x08ac76684d7e7d26 InputMethodOptions_Open_xkb:be::fra
+0x850b8ba271d39949 InputMethodOptions_Open_xkb:be::ger
+0x0b947d8e36f5c932 InputMethodOptions_Open_xkb:be::nld
+0x46a87a1ab952dc04 InputMethodOptions_Open_xkb:bg::bul
+0xa46c41e1afe6014b InputMethodOptions_Open_xkb:bg:phonetic:bul
+0x822bf0422c6827cd InputMethodOptions_Open_xkb:br::por
+0xabf8d015035007d4 InputMethodOptions_Open_xkb:ca::fra
+0x1c146e1accb26ba1 InputMethodOptions_Open_xkb:ca:eng:eng
+0x1092170d80d1a97e InputMethodOptions_Open_xkb:ch::ger
+0xee168304fd52c6da InputMethodOptions_Open_xkb:ch:fr:fra
+0x310e1c8edd3124fd InputMethodOptions_Open_xkb:cz::cze
+0xe7c956d1a5fe18b8 InputMethodOptions_Open_xkb:de::ger
+0x6ae0a3c608578b06 InputMethodOptions_Open_xkb:de:neo:ger
+0x54fd79dcc2c5078e InputMethodOptions_Open_xkb:dk::dan
+0xaaa3e638c0277e5d InputMethodOptions_Open_xkb:ee::est
+0x10d646c96bb290b0 InputMethodOptions_Open_xkb:es::spa
+0x9e9970f4b46c2945 InputMethodOptions_Open_xkb:es:cat:cat
+0x365b92eea899e7e7 InputMethodOptions_Open_xkb:fi::fin
+0xc81eae3dfb9e0b9d InputMethodOptions_Open_xkb:fr::fra
+0xbcf08367d19013e3 InputMethodOptions_Open_xkb:gb:dvorak:eng
+0x526ffe2c52ecda24 InputMethodOptions_Open_xkb:gb:extd:eng
+0x8030ee073cf7a3c6 InputMethodOptions_Open_xkb:gr::gre
+0xd154dbf3bb7c8107 InputMethodOptions_Open_xkb:hr::scr
+0x4f9eafd4473f6e19 InputMethodOptions_Open_xkb:hu::hun
+0x33f2b9f6c8539fde InputMethodOptions_Open_xkb:il::heb
+0x36471978fb1b0bea InputMethodOptions_Open_xkb:it::ita
+0x22020a263d5795ed InputMethodOptions_Open_xkb:jp::jpn
+0xed01f2795c864acf InputMethodOptions_Open_xkb:kr:kr104:kor
+0xfa8c5d3c569dfb46 InputMethodOptions_Open_xkb:latam::spa
+0xc165f3fd0b803830 InputMethodOptions_Open_xkb:lt::lit
+0x18b9e4dbb8025455 InputMethodOptions_Open_xkb:lv::lav
+0xcb6f3f90c1010f75 InputMethodOptions_Open_xkb:lv:apostrophe:lav
+0x34a05814ab58931d InputMethodOptions_Open_xkb:nl::nld
+0x4d16bf11c3ad7cd0 InputMethodOptions_Open_xkb:no::nob
+0x25659d10deab047d InputMethodOptions_Open_xkb:no::nor
+0xe39db1a9105a1816 InputMethodOptions_Open_xkb:pl::pol
+0x545654bd66e632ff InputMethodOptions_Open_xkb:pt::por
+0x0b2eb1ceb2af7e31 InputMethodOptions_Open_xkb:ro::rum
+0x397d3a57fed5bbac InputMethodOptions_Open_xkb:rs::srp
+0xd6b7cc8f607a5d62 InputMethodOptions_Open_xkb:ru::rus
+0xb6ded54d82c9c63d InputMethodOptions_Open_xkb:ru:phonetic:rus
+0xf18cf6b9c54bcd9e InputMethodOptions_Open_xkb:se::swe
+0x4fcae8c67666b3a4 InputMethodOptions_Open_xkb:si::slv
+0x06425a2a094ed04f InputMethodOptions_Open_xkb:sk::slo
+0x0217ffe65d9240b7 InputMethodOptions_Open_xkb:tr::tur
+0x029ef6d08daae227 InputMethodOptions_Open_xkb:ua::ukr
+0x8242054ab1bd9fdf InputMethodOptions_Open_xkb:us::eng
+0x6f0ca0c3f941e7f3 InputMethodOptions_Open_xkb:us:altgr-intl:eng
+0x3cafeb09bc83fb78 InputMethodOptions_Open_xkb:us:colemak:eng
+0x8c4bc3c1ddaf086f InputMethodOptions_Open_xkb:us:dvorak:eng
+0xcdb6a2617df255a0 InputMethodOptions_Open_xkb:us:intl:eng
+0x3f383d6272a64128 InsertBacktab
+0x22d1980eb6def616 InsertHTML
+0x0ff692418469f747 InsertHorizontalRule
+0xd90a0bafb43b7937 InsertImage
+0x6243f0401d9d1817 InsertLineBreak
+0x819ce2a733068b4d InsertNewline
+0x05534baac660c1e0 InsertNewlineInQuotedContent
+0xfe80e1819088136d InsertOrderedList
+0x876c542c54254736 InsertParagraph
+0x883d075e3e6d670c InsertTab
+0xb8890ced118a58f6 InsertText
+0x1342e1e52f335f69 InsertUnorderedList
+0xb7c371f7dd19c6fd InstallSite
+0x9ee757dac968cead InstantExtended.MostVisitedClicked
+0x3545f6127f5688ab InstantExtended.ShowNTP
+0x67ae87c0c5a6f55d InstantExtended.ShowSRP
+0x1d874710ccdcd46b Italic
+0x5569092107ae9fb0 JustifyCenter
+0xb2e54b8c7671e92e JustifyLeft
+0xcd362d0d3c2a301a JustifyRight
+0x54eeedf1d26e7698 KeywordEditor_AddKeyword
+0x204aad0f4a1f0f22 KeywordEditor_AddKeywordJS
+0x37ac83353fd9be1f KeywordEditor_ModifiedKeyword
+0x2d038477eb20483b KeywordEditor_RemoveKeyword
+0xab20f097361154dc LanguageChange_Accept
+0x98ee7b2a2893443f LanguageChange_Revert
+0xcce20fb4bce11250 LanguageConfigView_Open
+0x6c9d4656451fe020 LanguageMenuButton_InputMethodChanged
+0x9895b811fa1a2f7e LanguageMenuButton_Open
+0x4bef75db451d23fb LanguageOptions_DisableInputMethod_chewing
+0xf8fff1e1c48a01f9 LanguageOptions_DisableInputMethod_english-m
+0xf336ef307e081efe LanguageOptions_DisableInputMethod_hangul
+0x473fff093fed5585 LanguageOptions_DisableInputMethod_m17n:am:sera
+0x31f603e454ce9301 LanguageOptions_DisableInputMethod_m17n:ar:kbd
+0x5cb365ca1a9f0a87 LanguageOptions_DisableInputMethod_m17n:bn:itrans
+0x8d99e4c7475dbc4e LanguageOptions_DisableInputMethod_m17n:fa:isiri
+0xa7e7896176de5020 LanguageOptions_DisableInputMethod_m17n:gu:itrans
+0x978a3702045ddd98 LanguageOptions_DisableInputMethod_m17n:hi:itrans
+0x7b8c5bcdf04dcec9 LanguageOptions_DisableInputMethod_m17n:kn:itrans
+0xe103b81ce59e1ff6 LanguageOptions_DisableInputMethod_m17n:ml:itrans
+0x466e0dad1b9632fd LanguageOptions_DisableInputMethod_m17n:mr:itrans
+0x52ef1a32c928ab9f LanguageOptions_DisableInputMethod_m17n:ta:inscript
+0x3b7bccba8f7c9d9d LanguageOptions_DisableInputMethod_m17n:ta:itrans
+0xaaa84d23cee33ba2 LanguageOptions_DisableInputMethod_m17n:ta:phonetic
+0x9d9736754936c0d2 LanguageOptions_DisableInputMethod_m17n:ta:tamil99
+0x915153efd566a118 LanguageOptions_DisableInputMethod_m17n:ta:typewriter
+0x0e3555d2c2574839 LanguageOptions_DisableInputMethod_m17n:te:itrans
+0x3bf8f7a682215755 LanguageOptions_DisableInputMethod_m17n:th:kesmanee
+0x7ddb7bc2e25e4c86 LanguageOptions_DisableInputMethod_m17n:th:pattachote
+0x7c79ba0a7ddc551f LanguageOptions_DisableInputMethod_m17n:th:tis820
+0x64a3fb231691a106 LanguageOptions_DisableInputMethod_m17n:vi:tcvn
+0x25c742d3c23ff71e LanguageOptions_DisableInputMethod_m17n:vi:telex
+0x2282d16406d4149c LanguageOptions_DisableInputMethod_m17n:vi:viqr
+0xc46962be71e81a74 LanguageOptions_DisableInputMethod_m17n:vi:vni
+0x6f8182b9533a7bf6 LanguageOptions_DisableInputMethod_m17n:zh:cangjie
+0xdd214c6e6e223f2c LanguageOptions_DisableInputMethod_m17n:zh:quick
+0xe5b7a334a40a29b1 LanguageOptions_DisableInputMethod_mozc
+0xb04e0a3af2d11cb7 LanguageOptions_DisableInputMethod_mozc-chewing
+0x34c0af16cc2283f8 LanguageOptions_DisableInputMethod_mozc-dv
+0x39e72b2fc3872c16 LanguageOptions_DisableInputMethod_mozc-hangul
+0x1e33e194e43d85ff LanguageOptions_DisableInputMethod_mozc-jp
+0xfd89518df98afaf3 LanguageOptions_DisableInputMethod_pinyin
+0xd6157bb480ef90f7 LanguageOptions_DisableInputMethod_pinyin-dv
+0x20108869230aba12 LanguageOptions_DisableInputMethod_xkb:be::fra
+0x977dc3accf7e638b LanguageOptions_DisableInputMethod_xkb:be::ger
+0xcf0b649f9a1a59c7 LanguageOptions_DisableInputMethod_xkb:be::nld
+0xde0ba68a4ea3a9bf LanguageOptions_DisableInputMethod_xkb:bg::bul
+0xdaacfedb410a091e LanguageOptions_DisableInputMethod_xkb:bg:phonetic:bul
+0x60f266cb898affd4 LanguageOptions_DisableInputMethod_xkb:br::por
+0x4fecb3e04929aca2 LanguageOptions_DisableInputMethod_xkb:ca::fra
+0x197d8fb2f176e036 LanguageOptions_DisableInputMethod_xkb:ca:eng:eng
+0x64305300f1ffa8af LanguageOptions_DisableInputMethod_xkb:ch::ger
+0xb3517f39d893bc56 LanguageOptions_DisableInputMethod_xkb:ch:fr:fra
+0xf407ba1d8f098570 LanguageOptions_DisableInputMethod_xkb:cz::cze
+0x66ec7b7c518dab3c LanguageOptions_DisableInputMethod_xkb:de::ger
+0x562bc573da86fe6c LanguageOptions_DisableInputMethod_xkb:de:neo:ger
+0xaab2b2ab32b79eaf LanguageOptions_DisableInputMethod_xkb:dk::dan
+0x231800f9acc70b4f LanguageOptions_DisableInputMethod_xkb:ee::est
+0x55901fb5aa842097 LanguageOptions_DisableInputMethod_xkb:es::spa
+0xec86a454fb80111e LanguageOptions_DisableInputMethod_xkb:es:cat:cat
+0x18ca64de485033c8 LanguageOptions_DisableInputMethod_xkb:fi::fin
+0x6d236611b97a8f64 LanguageOptions_DisableInputMethod_xkb:fr::fra
+0x204bead7902d82d7 LanguageOptions_DisableInputMethod_xkb:gb:dvorak:eng
+0x13facbf7da2f7826 LanguageOptions_DisableInputMethod_xkb:gb:extd:eng
+0x215d96a1bda18a53 LanguageOptions_DisableInputMethod_xkb:gr::gre
+0x6e3d64f780b3424a LanguageOptions_DisableInputMethod_xkb:hr::scr
+0x625fbaee633b4e53 LanguageOptions_DisableInputMethod_xkb:hu::hun
+0x14a66e0b221a13bb LanguageOptions_DisableInputMethod_xkb:il::heb
+0xf5dbc48f5bcfd65f LanguageOptions_DisableInputMethod_xkb:it::ita
+0x11cb89758a2d2606 LanguageOptions_DisableInputMethod_xkb:jp::jpn
+0x02b207c3740c92db LanguageOptions_DisableInputMethod_xkb:kr:kr104:kor
+0xbe433a85af5f3219 LanguageOptions_DisableInputMethod_xkb:latam::spa
+0xcafacab7d5bec6c3 LanguageOptions_DisableInputMethod_xkb:lt::lit
+0xa310032375e1a775 LanguageOptions_DisableInputMethod_xkb:lv::lav
+0x683e9f41fec504f1 LanguageOptions_DisableInputMethod_xkb:lv:apostrophe:lav
+0xfb0bedc9f892abf2 LanguageOptions_DisableInputMethod_xkb:nl::nld
+0x29d544cb2af7a80a LanguageOptions_DisableInputMethod_xkb:no::nob
+0xc7210bf937ebf4d1 LanguageOptions_DisableInputMethod_xkb:no::nor
+0x4f7d52ae0938b86e LanguageOptions_DisableInputMethod_xkb:pl::pol
+0xc7123952f2b4bf52 LanguageOptions_DisableInputMethod_xkb:pt::por
+0xbf5c339263965e41 LanguageOptions_DisableInputMethod_xkb:ro::rum
+0xf4c88d1eb003f153 LanguageOptions_DisableInputMethod_xkb:rs::srp
+0xddc77955cace9f69 LanguageOptions_DisableInputMethod_xkb:ru::rus
+0xb6e2bdd72bc5ca1b LanguageOptions_DisableInputMethod_xkb:ru:phonetic:rus
+0xbdbbb828f1afce9f LanguageOptions_DisableInputMethod_xkb:se::swe
+0xe65a7b8f5c72a35b LanguageOptions_DisableInputMethod_xkb:si::slv
+0x8e05ca20d7d104fa LanguageOptions_DisableInputMethod_xkb:sk::slo
+0x83928dfd8c874fd0 LanguageOptions_DisableInputMethod_xkb:tr::tur
+0x15f38552ce3ef440 LanguageOptions_DisableInputMethod_xkb:ua::ukr
+0x40118f4b64720619 LanguageOptions_DisableInputMethod_xkb:us::eng
+0x99b1530d498aa978 LanguageOptions_DisableInputMethod_xkb:us:altgr-intl:eng
+0x092d37b467b2355b LanguageOptions_DisableInputMethod_xkb:us:colemak:eng
+0x28a17da0e5170d9c LanguageOptions_DisableInputMethod_xkb:us:dvorak:eng
+0x36618553183c61a0 LanguageOptions_DisableInputMethod_xkb:us:intl:eng
+0xbf74d2491fd43546 LanguageOptions_EnableInputMethod_chewing
+0xd9282b12fa5f188f LanguageOptions_EnableInputMethod_english-m
+0xa3850d86987729e3 LanguageOptions_EnableInputMethod_hangul
+0x3f4b10aeaec96ce8 LanguageOptions_EnableInputMethod_m17n:am:sera
+0xbd41d816d8ffa4d0 LanguageOptions_EnableInputMethod_m17n:ar:kbd
+0xc203f3b486a353a5 LanguageOptions_EnableInputMethod_m17n:bn:itrans
+0xba649d035929fcc7 LanguageOptions_EnableInputMethod_m17n:fa:isiri
+0xed3203cbaaa64216 LanguageOptions_EnableInputMethod_m17n:gu:itrans
+0xd55995652310e97d LanguageOptions_EnableInputMethod_m17n:hi:itrans
+0x81829d172068cd4a LanguageOptions_EnableInputMethod_m17n:kn:itrans
+0x6735d1bbdb6402b2 LanguageOptions_EnableInputMethod_m17n:ml:itrans
+0xe446ca103495822f LanguageOptions_EnableInputMethod_m17n:mr:itrans
+0x4a404258c039c9f7 LanguageOptions_EnableInputMethod_m17n:ta:inscript
+0x99c1dad1382f9723 LanguageOptions_EnableInputMethod_m17n:ta:itrans
+0x4709812f00883cc2 LanguageOptions_EnableInputMethod_m17n:ta:phonetic
+0x4d7c4797ad697bbd LanguageOptions_EnableInputMethod_m17n:ta:tamil99
+0x638a88a46df1a617 LanguageOptions_EnableInputMethod_m17n:ta:typewriter
+0xbfa551d544d618b0 LanguageOptions_EnableInputMethod_m17n:te:itrans
+0xc9349a3c4ea64758 LanguageOptions_EnableInputMethod_m17n:th:kesmanee
+0x8ebf5ecdd9403d86 LanguageOptions_EnableInputMethod_m17n:th:pattachote
+0xc1771d7b829a738e LanguageOptions_EnableInputMethod_m17n:th:tis820
+0x094f24c724c35098 LanguageOptions_EnableInputMethod_m17n:vi:tcvn
+0x8f062dc3fbc54bd6 LanguageOptions_EnableInputMethod_m17n:vi:telex
+0xb31dc2cc3a8b46cd LanguageOptions_EnableInputMethod_m17n:vi:viqr
+0x905e70ae85a254d9 LanguageOptions_EnableInputMethod_m17n:vi:vni
+0xfef5e66f81905f45 LanguageOptions_EnableInputMethod_m17n:zh:cangjie
+0x707054c3cc12ba9b LanguageOptions_EnableInputMethod_m17n:zh:quick
+0xf757893b8f47d386 LanguageOptions_EnableInputMethod_mozc
+0x12e67d2f62569179 LanguageOptions_EnableInputMethod_mozc-chewing
+0x5e800e2879b118e1 LanguageOptions_EnableInputMethod_mozc-dv
+0xac71bc394dac5dd1 LanguageOptions_EnableInputMethod_mozc-hangul
+0x0876a103cad5d843 LanguageOptions_EnableInputMethod_mozc-jp
+0x56da8023f0cbe550 LanguageOptions_EnableInputMethod_pinyin
+0x95ce2c3e8dfefc08 LanguageOptions_EnableInputMethod_pinyin-dv
+0x7ddef14e3ae9ca9b LanguageOptions_EnableInputMethod_xkb:be::fra
+0xcd6ff3d5d0cc4817 LanguageOptions_EnableInputMethod_xkb:be::ger
+0xcc82746494498dc4 LanguageOptions_EnableInputMethod_xkb:be::nld
+0x0aa7853408b07074 LanguageOptions_EnableInputMethod_xkb:bg::bul
+0x699564bdd5712be7 LanguageOptions_EnableInputMethod_xkb:bg:phonetic:bul
+0xc644632c62aeb8ca LanguageOptions_EnableInputMethod_xkb:br::por
+0x3a2c133c17b2bc75 LanguageOptions_EnableInputMethod_xkb:ca::fra
+0x20bc5b77deb279f8 LanguageOptions_EnableInputMethod_xkb:ca:eng:eng
+0x6cb09a3c8026a7aa LanguageOptions_EnableInputMethod_xkb:ch::ger
+0x9ad6a4a9638b5782 LanguageOptions_EnableInputMethod_xkb:ch:fr:fra
+0xa559566c8c6ea637 LanguageOptions_EnableInputMethod_xkb:cz::cze
+0x98af6ef5e3f72fb2 LanguageOptions_EnableInputMethod_xkb:de::ger
+0xe3e1f005e4881269 LanguageOptions_EnableInputMethod_xkb:de:neo:ger
+0xd42956556814d1ac LanguageOptions_EnableInputMethod_xkb:dk::dan
+0x0a403824d4bf1af8 LanguageOptions_EnableInputMethod_xkb:ee::est
+0x6c0a59356dde2eac LanguageOptions_EnableInputMethod_xkb:es::spa
+0x8f92752907a878f4 LanguageOptions_EnableInputMethod_xkb:es:cat:cat
+0xcd068af26c3eeb04 LanguageOptions_EnableInputMethod_xkb:fi::fin
+0x23e04c4b87b2ec4a LanguageOptions_EnableInputMethod_xkb:fr::fra
+0xa25f41f242fc4801 LanguageOptions_EnableInputMethod_xkb:gb:dvorak:eng
+0x61b45586224d5505 LanguageOptions_EnableInputMethod_xkb:gb:extd:eng
+0xcf2286bdb20f63dd LanguageOptions_EnableInputMethod_xkb:gr::gre
+0xad8f3703500bedcc LanguageOptions_EnableInputMethod_xkb:hr::scr
+0xe37001b17655d436 LanguageOptions_EnableInputMethod_xkb:hu::hun
+0x48ece720994692cd LanguageOptions_EnableInputMethod_xkb:il::heb
+0xfbce8fb375d0cb10 LanguageOptions_EnableInputMethod_xkb:it::ita
+0xe86c32f284eaa235 LanguageOptions_EnableInputMethod_xkb:jp::jpn
+0x75254f6c14869f23 LanguageOptions_EnableInputMethod_xkb:kr:kr104:kor
+0x3ac95cb77e3aecd3 LanguageOptions_EnableInputMethod_xkb:latam::spa
+0x7e72cd1f5e56c8de LanguageOptions_EnableInputMethod_xkb:lt::lit
+0x7e55464b40755c35 LanguageOptions_EnableInputMethod_xkb:lv::lav
+0x984465cbf1dc14c7 LanguageOptions_EnableInputMethod_xkb:lv:apostrophe:lav
+0x1a1ca3eb2d8f9b6d LanguageOptions_EnableInputMethod_xkb:nl::nld
+0x73bfcb9c835bcb38 LanguageOptions_EnableInputMethod_xkb:no::nob
+0x06d15353036ca947 LanguageOptions_EnableInputMethod_xkb:no::nor
+0x1e7c51aa38eb9c65 LanguageOptions_EnableInputMethod_xkb:pl::pol
+0xa7e387a15749319e LanguageOptions_EnableInputMethod_xkb:pt::por
+0x87a75b792f1d8ee1 LanguageOptions_EnableInputMethod_xkb:ro::rum
+0x38e76dba9085fa94 LanguageOptions_EnableInputMethod_xkb:rs::srp
+0x9c6ce402bd03337b LanguageOptions_EnableInputMethod_xkb:ru::rus
+0x6bb6082988e4cbea LanguageOptions_EnableInputMethod_xkb:ru:phonetic:rus
+0xf78f942da3223853 LanguageOptions_EnableInputMethod_xkb:se::swe
+0x46d0c5799ae35ae7 LanguageOptions_EnableInputMethod_xkb:si::slv
+0x00084283db086e29 LanguageOptions_EnableInputMethod_xkb:sk::slo
+0xc079d20c400f3e61 LanguageOptions_EnableInputMethod_xkb:tr::tur
+0xac38bf5ba676edfb LanguageOptions_EnableInputMethod_xkb:ua::ukr
+0x4ae7cbf387b2ee2c LanguageOptions_EnableInputMethod_xkb:us::eng
+0xfc019a30579d475d LanguageOptions_EnableInputMethod_xkb:us:altgr-intl:eng
+0xf47b49df07dcafca LanguageOptions_EnableInputMethod_xkb:us:colemak:eng
+0xf6b8e8d4de66cf77 LanguageOptions_EnableInputMethod_xkb:us:dvorak:eng
+0x23aaf851e47f2bf7 LanguageOptions_EnableInputMethod_xkb:us:intl:eng
+0xfa78305d269c1ec1 LanguageOptions_Open
+0xda947fb4440a66e7 LanguageOptions_Restart
+0xb5f8e1034ebaab43 LanguageOptions_SignOut
+0x3bdcb57ed74b6f2c LanguageOptions_SpellCheckLanguageChange_af
+0x0268501c247fa3e1 LanguageOptions_SpellCheckLanguageChange_am
+0x9d68c5a82572b3a5 LanguageOptions_SpellCheckLanguageChange_ar
+0x216ae3faf9f4fc61 LanguageOptions_SpellCheckLanguageChange_az
+0x85bddda0d071875b LanguageOptions_SpellCheckLanguageChange_be
+0x552a4f4066bb456b LanguageOptions_SpellCheckLanguageChange_bg
+0xea6b28b89f3b1bc2 LanguageOptions_SpellCheckLanguageChange_bh
+0x173c0736c9838394 LanguageOptions_SpellCheckLanguageChange_bn
+0xa357a0df0b190220 LanguageOptions_SpellCheckLanguageChange_br
+0x474752275567a519 LanguageOptions_SpellCheckLanguageChange_bs
+0x77b12159bb08e0c0 LanguageOptions_SpellCheckLanguageChange_ca
+0x6872456b4ea20026 LanguageOptions_SpellCheckLanguageChange_co
+0x258da94c1135762c LanguageOptions_SpellCheckLanguageChange_cs
+0x29a8f1a61033a69a LanguageOptions_SpellCheckLanguageChange_cy
+0xb30aafb7259dcd76 LanguageOptions_SpellCheckLanguageChange_da
+0xd4d51eee8ca53562 LanguageOptions_SpellCheckLanguageChange_de
+0x8d90ebda20909ebe LanguageOptions_SpellCheckLanguageChange_de-AT
+0x2311311ecb5272c2 LanguageOptions_SpellCheckLanguageChange_de-CH
+0xdc02d8c4e8b01766 LanguageOptions_SpellCheckLanguageChange_de-DE
+0x7ee2af2c5a437e1a LanguageOptions_SpellCheckLanguageChange_el
+0x4fc6d56cdd72700e LanguageOptions_SpellCheckLanguageChange_en
+0x7a9875b0b8efb1ad LanguageOptions_SpellCheckLanguageChange_en-AU
+0x210830b65e90eedf LanguageOptions_SpellCheckLanguageChange_en-CA
+0x9c5ecf7ee4cd7fe6 LanguageOptions_SpellCheckLanguageChange_en-GB
+0xa1ca46cc1bacf01e LanguageOptions_SpellCheckLanguageChange_en-NZ
+0xc2ef2ccd8a872da8 LanguageOptions_SpellCheckLanguageChange_en-US
+0xfa49edbe6e1a8099 LanguageOptions_SpellCheckLanguageChange_en-ZA
+0xb89148d2ec4d78eb LanguageOptions_SpellCheckLanguageChange_eo
+0x7a8a9928c6951178 LanguageOptions_SpellCheckLanguageChange_es
+0x335c54f4600c0b06 LanguageOptions_SpellCheckLanguageChange_es-419
+0x2be5d12ada80fe8c LanguageOptions_SpellCheckLanguageChange_et
+0x85fb3829228fcc2e LanguageOptions_SpellCheckLanguageChange_eu
+0x888c6e9da75bd6ea LanguageOptions_SpellCheckLanguageChange_fa
+0x6a71fe1235b65ea8 LanguageOptions_SpellCheckLanguageChange_fi
+0x786510108f6bd621 LanguageOptions_SpellCheckLanguageChange_fil
+0xb65b87a46bc6848a LanguageOptions_SpellCheckLanguageChange_fo
+0x350594ed486733ab LanguageOptions_SpellCheckLanguageChange_fr
+0x92b548bfe8dc3ae9 LanguageOptions_SpellCheckLanguageChange_fr-CA
+0x22d8ce8d402861df LanguageOptions_SpellCheckLanguageChange_fr-CH
+0x04b12f0c336d715c LanguageOptions_SpellCheckLanguageChange_fr-FR
+0xedba3ba5ccd84adc LanguageOptions_SpellCheckLanguageChange_fy
+0xfc18bb1660a03b60 LanguageOptions_SpellCheckLanguageChange_ga
+0x1b9c8352f74b0c82 LanguageOptions_SpellCheckLanguageChange_gd
+0xfdfa4d8cd811f664 LanguageOptions_SpellCheckLanguageChange_gl
+0xac52fce34c780009 LanguageOptions_SpellCheckLanguageChange_gn
+0xd78744f6c3b943d5 LanguageOptions_SpellCheckLanguageChange_gu
+0xd4bb24d5585722d5 LanguageOptions_SpellCheckLanguageChange_ha
+0xa1df103387fe44eb LanguageOptions_SpellCheckLanguageChange_haw
+0xe6a740028864e54c LanguageOptions_SpellCheckLanguageChange_he
+0x4a5ac45c11294524 LanguageOptions_SpellCheckLanguageChange_hi
+0x5634d2d630b62db7 LanguageOptions_SpellCheckLanguageChange_hr
+0x0d9b2da08e908398 LanguageOptions_SpellCheckLanguageChange_hu
+0x6235fe36d587a174 LanguageOptions_SpellCheckLanguageChange_hy
+0x96a69530dcf9c952 LanguageOptions_SpellCheckLanguageChange_ia
+0x33858a0f90601b99 LanguageOptions_SpellCheckLanguageChange_id
+0x421fd3a986c9268a LanguageOptions_SpellCheckLanguageChange_is
+0x6963156dd2e5a8da LanguageOptions_SpellCheckLanguageChange_it
+0x0c579f6bc1d7eb3d LanguageOptions_SpellCheckLanguageChange_it-CH
+0x9415bc67e35d695b LanguageOptions_SpellCheckLanguageChange_it-IT
+0xc309312f7d87e667 LanguageOptions_SpellCheckLanguageChange_ja
+0xa16e44ff1be39a3e LanguageOptions_SpellCheckLanguageChange_jw
+0x69a6884a3d26b3da LanguageOptions_SpellCheckLanguageChange_ka
+0xda7c858e99e65ef4 LanguageOptions_SpellCheckLanguageChange_kk
+0x2ef0148c5104510b LanguageOptions_SpellCheckLanguageChange_km
+0x0c285764bac9c412 LanguageOptions_SpellCheckLanguageChange_kn
+0xdf1b960c7c2cc1e7 LanguageOptions_SpellCheckLanguageChange_ko
+0x5d128aa7040d29c6 LanguageOptions_SpellCheckLanguageChange_ku
+0x535257816775f9f5 LanguageOptions_SpellCheckLanguageChange_ky
+0x9c4079a6ebd99d4f LanguageOptions_SpellCheckLanguageChange_la
+0xbcdb116c72381903 LanguageOptions_SpellCheckLanguageChange_ln
+0x188a55a79836e3ab LanguageOptions_SpellCheckLanguageChange_lo
+0x35c70c9a4d851dc6 LanguageOptions_SpellCheckLanguageChange_lt
+0x8566b76a82e7fdeb LanguageOptions_SpellCheckLanguageChange_lv
+0xb21dc3c6409fb03b LanguageOptions_SpellCheckLanguageChange_mk
+0xbc1d9b51b30e674e LanguageOptions_SpellCheckLanguageChange_ml
+0xe184488215d31cff LanguageOptions_SpellCheckLanguageChange_mn
+0xb4048acd46620f9d LanguageOptions_SpellCheckLanguageChange_mo
+0x494852187a45238e LanguageOptions_SpellCheckLanguageChange_mr
+0x3252be13f227791e LanguageOptions_SpellCheckLanguageChange_ms
+0x47b98aa2c04db05a LanguageOptions_SpellCheckLanguageChange_mt
+0xd1019f3988676333 LanguageOptions_SpellCheckLanguageChange_nb
+0xc7d80d5be9fd265a LanguageOptions_SpellCheckLanguageChange_ne
+0x0fe1fa4c9113cdca LanguageOptions_SpellCheckLanguageChange_nl
+0xbf2dc22115880d3d LanguageOptions_SpellCheckLanguageChange_nn
+0xcab46544f005c97a LanguageOptions_SpellCheckLanguageChange_no
+0x031c51747e109ed0 LanguageOptions_SpellCheckLanguageChange_oc
+0x18148cc2641e2e75 LanguageOptions_SpellCheckLanguageChange_om
+0x5af0c86bd4fbc6d4 LanguageOptions_SpellCheckLanguageChange_or
+0xe9142e813c57d901 LanguageOptions_SpellCheckLanguageChange_pa
+0x56f8dea08fc60dd0 LanguageOptions_SpellCheckLanguageChange_pl
+0xcc46a9b43892cd17 LanguageOptions_SpellCheckLanguageChange_ps
+0xa8e521739e3a8111 LanguageOptions_SpellCheckLanguageChange_pt
+0x0965fa6496b7bc86 LanguageOptions_SpellCheckLanguageChange_pt-BR
+0xa245fca6322289f1 LanguageOptions_SpellCheckLanguageChange_pt-PT
+0x0c0249f8a5ddd2fd LanguageOptions_SpellCheckLanguageChange_qu
+0x1e4414f0c08e409b LanguageOptions_SpellCheckLanguageChange_rm
+0x9de3adae56cd4645 LanguageOptions_SpellCheckLanguageChange_ro
+0xdf75477e7e9105c9 LanguageOptions_SpellCheckLanguageChange_ru
+0xa5227b45669bf1d9 LanguageOptions_SpellCheckLanguageChange_sd
+0x99ac10d69235bc19 LanguageOptions_SpellCheckLanguageChange_sh
+0xb65301fe78a5f948 LanguageOptions_SpellCheckLanguageChange_si
+0x4043d3a9b8a0b7d3 LanguageOptions_SpellCheckLanguageChange_sk
+0xd48fd58efca4a848 LanguageOptions_SpellCheckLanguageChange_sl
+0x4811fa57db8aba7b LanguageOptions_SpellCheckLanguageChange_sn
+0xb460c6a021ce30ce LanguageOptions_SpellCheckLanguageChange_so
+0xcf8fbb2f35d437f9 LanguageOptions_SpellCheckLanguageChange_sq
+0x4266aeea5a172fed LanguageOptions_SpellCheckLanguageChange_sr
+0xb70d00fe5b60399f LanguageOptions_SpellCheckLanguageChange_st
+0x4f307c5e96126e39 LanguageOptions_SpellCheckLanguageChange_su
+0x793f0539702106b3 LanguageOptions_SpellCheckLanguageChange_sv
+0xd0683f1a88f2dcd9 LanguageOptions_SpellCheckLanguageChange_sw
+0x4adb832cdfa82e95 LanguageOptions_SpellCheckLanguageChange_ta
+0xe5e6f8a2c34dbf3f LanguageOptions_SpellCheckLanguageChange_te
+0xb56ca80c23e21e82 LanguageOptions_SpellCheckLanguageChange_tg
+0xc31434dd30b37c79 LanguageOptions_SpellCheckLanguageChange_th
+0xbf3ce64eb42276ce LanguageOptions_SpellCheckLanguageChange_ti
+0x9a7852d3d5a451dd LanguageOptions_SpellCheckLanguageChange_tk
+0x54a10166348130da LanguageOptions_SpellCheckLanguageChange_to
+0xceb028c8d98b6f69 LanguageOptions_SpellCheckLanguageChange_tr
+0x6110f46e5d1d5ce3 LanguageOptions_SpellCheckLanguageChange_tt
+0x9ed4a1802694e371 LanguageOptions_SpellCheckLanguageChange_tw
+0xf2aa74178fae8737 LanguageOptions_SpellCheckLanguageChange_ug
+0xeba4b1bfb148fe5c LanguageOptions_SpellCheckLanguageChange_uk
+0xdc2fbf10c4e3cc7e LanguageOptions_SpellCheckLanguageChange_ur
+0x7de2dd2191f8f3b5 LanguageOptions_SpellCheckLanguageChange_uz
+0x20f26902bf2b0f7e LanguageOptions_SpellCheckLanguageChange_vi
+0x69a672e997291046 LanguageOptions_SpellCheckLanguageChange_xh
+0xd95a13401430464b LanguageOptions_SpellCheckLanguageChange_yi
+0xdfa41d1e586edede LanguageOptions_SpellCheckLanguageChange_yo
+0xe464bee2f7b47f05 LanguageOptions_SpellCheckLanguageChange_zh
+0x02feeb3c3fbb0e6d LanguageOptions_SpellCheckLanguageChange_zh-CN
+0x388861c5b05fcfd7 LanguageOptions_SpellCheckLanguageChange_zh-TW
+0xa7832f7951587154 LanguageOptions_SpellCheckLanguageChange_zu
+0x28f95708216c5f3f LanguageOptions_UiLanguageChange_af
+0x64bf99d3a3ae3c09 LanguageOptions_UiLanguageChange_am
+0x37e45415ff188c83 LanguageOptions_UiLanguageChange_ar
+0xc16e98ac284f7a2c LanguageOptions_UiLanguageChange_az
+0x86afaa8af655ec3a LanguageOptions_UiLanguageChange_be
+0xd3444f0a33415c12 LanguageOptions_UiLanguageChange_bg
+0x2a970136519d8e05 LanguageOptions_UiLanguageChange_bh
+0x373b5f9df58f10b1 LanguageOptions_UiLanguageChange_bn
+0xaa60c4c46bab2840 LanguageOptions_UiLanguageChange_br
+0x576186b20f58a62e LanguageOptions_UiLanguageChange_bs
+0x2ee7812d1d628187 LanguageOptions_UiLanguageChange_ca
+0x0d39e71d36e3f98c LanguageOptions_UiLanguageChange_co
+0x009ad7b74dd6eead LanguageOptions_UiLanguageChange_cs
+0x9fc56d8b05719e95 LanguageOptions_UiLanguageChange_cy
+0x71c22450bc774ac6 LanguageOptions_UiLanguageChange_da
+0xdad8029db0738ca3 LanguageOptions_UiLanguageChange_de
+0xe5f02b9f07d5c321 LanguageOptions_UiLanguageChange_de-AT
+0x937082a0f96b339b LanguageOptions_UiLanguageChange_de-CH
+0x60067bef740b0cee LanguageOptions_UiLanguageChange_de-DE
+0x0598fe9cffcf7342 LanguageOptions_UiLanguageChange_el
+0x20682c0970bf6c39 LanguageOptions_UiLanguageChange_en
+0xb6b90d60aa7397dc LanguageOptions_UiLanguageChange_en-AU
+0x20ffa805c7cb2d11 LanguageOptions_UiLanguageChange_en-CA
+0x0abeddf23bb637dd LanguageOptions_UiLanguageChange_en-GB
+0x8e377316a588ae05 LanguageOptions_UiLanguageChange_en-NZ
+0x5e4314a4bd4d6ec1 LanguageOptions_UiLanguageChange_en-US
+0xacb33ac957ca869b LanguageOptions_UiLanguageChange_en-ZA
+0xabb1750f364f3fdf LanguageOptions_UiLanguageChange_eo
+0x42ef1c985cf8dac3 LanguageOptions_UiLanguageChange_es
+0x207a8d00a40289d5 LanguageOptions_UiLanguageChange_es-419
+0x3396cd1cc34fcd6b LanguageOptions_UiLanguageChange_et
+0x1bc0603299c4c900 LanguageOptions_UiLanguageChange_eu
+0x4f3e8052d630b9ef LanguageOptions_UiLanguageChange_fa
+0xef30a035ea67916e LanguageOptions_UiLanguageChange_fi
+0x6b0bf8c255f455c4 LanguageOptions_UiLanguageChange_fil
+0xa43a6a0b854ffefd LanguageOptions_UiLanguageChange_fo
+0x3636182675a031c8 LanguageOptions_UiLanguageChange_fr
+0x6f0bffdb3032caed LanguageOptions_UiLanguageChange_fr-CA
+0xd912f13c73979882 LanguageOptions_UiLanguageChange_fr-CH
+0xe924dfbfd17a3242 LanguageOptions_UiLanguageChange_fr-FR
+0x061bf0d19eeef81e LanguageOptions_UiLanguageChange_fy
+0x8251febc4083f54f LanguageOptions_UiLanguageChange_ga
+0xccd31a77ee4366bf LanguageOptions_UiLanguageChange_gd
+0x1f67f851b23ced0f LanguageOptions_UiLanguageChange_gl
+0xcc9859375f855961 LanguageOptions_UiLanguageChange_gn
+0xd56c64f864957d91 LanguageOptions_UiLanguageChange_gu
+0xd08b36368944e379 LanguageOptions_UiLanguageChange_ha
+0xb3a6464f5fe71073 LanguageOptions_UiLanguageChange_haw
+0xed8f4616b34e2185 LanguageOptions_UiLanguageChange_he
+0x88ca2030cc3a49d9 LanguageOptions_UiLanguageChange_hi
+0xb8bd533bdc898a53 LanguageOptions_UiLanguageChange_hr
+0x746a1a0e63dd3f6d LanguageOptions_UiLanguageChange_hu
+0x48906875b3fd6c95 LanguageOptions_UiLanguageChange_hy
+0x1366ee57f2aebfad LanguageOptions_UiLanguageChange_ia
+0xff1d8f2925f8463c LanguageOptions_UiLanguageChange_id
+0x915c19c85aed6a03 LanguageOptions_UiLanguageChange_is
+0xd1abd6db369ab7ef LanguageOptions_UiLanguageChange_it
+0xe0c3a22acdd867b9 LanguageOptions_UiLanguageChange_it-CH
+0x3090b03a3e46582b LanguageOptions_UiLanguageChange_it-IT
+0x60f4dd00cc06d874 LanguageOptions_UiLanguageChange_ja
+0x86c8f166345df95e LanguageOptions_UiLanguageChange_jw
+0x670ea55ac2c8b062 LanguageOptions_UiLanguageChange_ka
+0x5b57cde2d36ca8cd LanguageOptions_UiLanguageChange_kk
+0xbeb6576493ae6d05 LanguageOptions_UiLanguageChange_km
+0xce996c9699b3168c LanguageOptions_UiLanguageChange_kn
+0xbd07adaea57b26f5 LanguageOptions_UiLanguageChange_ko
+0x4f0a66f954fa580e LanguageOptions_UiLanguageChange_ku
+0xb87acb54b22131c8 LanguageOptions_UiLanguageChange_ky
+0x8263585e1943372f LanguageOptions_UiLanguageChange_la
+0x6642ed654dd4aaa4 LanguageOptions_UiLanguageChange_ln
+0x273efc98e31a51cd LanguageOptions_UiLanguageChange_lo
+0xd25cfe9ca78a31d7 LanguageOptions_UiLanguageChange_lt
+0x794081adfcb1744c LanguageOptions_UiLanguageChange_lv
+0xf6ea1c5fc4dcafb8 LanguageOptions_UiLanguageChange_mk
+0x2258884fcb94b3a3 LanguageOptions_UiLanguageChange_ml
+0x00bdaddaf47561d1 LanguageOptions_UiLanguageChange_mn
+0x3b0c2fa0b7b027db LanguageOptions_UiLanguageChange_mo
+0xfec577eb29f4b768 LanguageOptions_UiLanguageChange_mr
+0x2d1ef24818ca5e4f LanguageOptions_UiLanguageChange_ms
+0x06ddcd11da46bb50 LanguageOptions_UiLanguageChange_mt
+0x5683a40b0b8caa20 LanguageOptions_UiLanguageChange_nb
+0x2ba4d49749d043fa LanguageOptions_UiLanguageChange_ne
+0x584a118482ee3a32 LanguageOptions_UiLanguageChange_nl
+0x7ca178a2a1311c1e LanguageOptions_UiLanguageChange_nn
+0xcef3082674f7bfc0 LanguageOptions_UiLanguageChange_no
+0x4ef5f77644dbfc68 LanguageOptions_UiLanguageChange_oc
+0x648ba70088175e47 LanguageOptions_UiLanguageChange_om
+0xb76df1c750016022 LanguageOptions_UiLanguageChange_or
+0x4d3566c9fb39fde3 LanguageOptions_UiLanguageChange_pa
+0xb2e1327766d055ad LanguageOptions_UiLanguageChange_pl
+0x9e562f625cfbb008 LanguageOptions_UiLanguageChange_ps
+0xd970808d9c9448d1 LanguageOptions_UiLanguageChange_pt
+0xf7b46f1138de06a9 LanguageOptions_UiLanguageChange_pt-BR
+0x086ef991869ac783 LanguageOptions_UiLanguageChange_pt-PT
+0x69a974172e5e9f73 LanguageOptions_UiLanguageChange_qu
+0xdd1935e2579c1284 LanguageOptions_UiLanguageChange_rm
+0xe5738c8e946ba1d0 LanguageOptions_UiLanguageChange_ro
+0x125913fb14d47526 LanguageOptions_UiLanguageChange_ru
+0x0f156a0f15f74bb8 LanguageOptions_UiLanguageChange_sd
+0x9240b6a14cd35919 LanguageOptions_UiLanguageChange_sh
+0x6763083d96429a61 LanguageOptions_UiLanguageChange_si
+0x587831f4b9220eca LanguageOptions_UiLanguageChange_sk
+0x15a09e54aa1e9f4a LanguageOptions_UiLanguageChange_sl
+0x6a5ac197de560ec4 LanguageOptions_UiLanguageChange_sn
+0x93472fab0fe3f061 LanguageOptions_UiLanguageChange_so
+0x1bbc961a4eb4fb07 LanguageOptions_UiLanguageChange_sq
+0xb1392f5ad48fe1a7 LanguageOptions_UiLanguageChange_sr
+0x04e5f8326179901e LanguageOptions_UiLanguageChange_st
+0x5fef5745a2763b80 LanguageOptions_UiLanguageChange_su
+0x8993a9d1df3ccc59 LanguageOptions_UiLanguageChange_sv
+0xaedab7909dff790b LanguageOptions_UiLanguageChange_sw
+0x6c1f62315896ca95 LanguageOptions_UiLanguageChange_ta
+0x762084c13a9a9b62 LanguageOptions_UiLanguageChange_te
+0x0060f27c68e28c87 LanguageOptions_UiLanguageChange_tg
+0x80b5fea53c9d6164 LanguageOptions_UiLanguageChange_th
+0xeeb3bd273099c7d3 LanguageOptions_UiLanguageChange_ti
+0xfa67fec49e23c547 LanguageOptions_UiLanguageChange_tk
+0x052e8ac2c052128c LanguageOptions_UiLanguageChange_to
+0xaa97a95d0c9e20b5 LanguageOptions_UiLanguageChange_tr
+0x8e949fbebe2126cf LanguageOptions_UiLanguageChange_tt
+0xe0fc96469f2d822f LanguageOptions_UiLanguageChange_tw
+0xa4a84a5651503494 LanguageOptions_UiLanguageChange_ug
+0x0b0bcb0d93b5a367 LanguageOptions_UiLanguageChange_uk
+0x2be9356bc4812c15 LanguageOptions_UiLanguageChange_ur
+0xe0e1ece201b6889f LanguageOptions_UiLanguageChange_uz
+0x28a1a4b9dc5a83f1 LanguageOptions_UiLanguageChange_vi
+0xf16ab2f1f9cfeaab LanguageOptions_UiLanguageChange_xh
+0x26561f9577c4d728 LanguageOptions_UiLanguageChange_yi
+0x0d5d98b098d7429b LanguageOptions_UiLanguageChange_yo
+0xa9b1ee532cc5580b LanguageOptions_UiLanguageChange_zh
+0xbee911865b93d504 LanguageOptions_UiLanguageChange_zh-CN
+0x03a61bc8bd6c791b LanguageOptions_UiLanguageChange_zh-TW
+0xd93d87f83683d666 LanguageOptions_UiLanguageChange_zu
+0x7f28f030259fc65e Launcher_ClickOnApp
+0x2df1e564b9b0952f Launcher_ClickOnApplistButton
+0x384a6609143bbcae LoadURL
+0xe009e92f3909009c LoadURLFromKeyword
+0x795fc04747be6afa LockScreen
+0x733f4fb7447b7323 Login.CreateAccount
+0xb9cc6258dfd41f37 Login_DemoUserLoginSuccess
+0xfb40450c5de92998 Login_Failure
+0x31374d163aec5a5e Login_GuestLoginSuccess
+0x47421e3d3406b4e1 Login_OffTheRecordLoginSuccess
+0xc23fa875d14a7ddb Login_Success
+0xb8f04c6d0fe44916 ManagedMode_ClosePassphraseDialog
+0x2e52d9ec770aefb3 ManagedMode_LocallyManagedUserCreated
+0x41b5faabb7c9327c ManagedMode_MainFrameNavigation
+0xa29f3f7e4bb25494 ManagedMode_NewManagedUserWindow
+0x29c1bda4ed1db0e0 ManagedMode_OpenPassphraseDialog
+0x238d1563c0fa1ce2 ManagedMode_OpenSettings
+0x0b747e86c82229bc ManagedMode_StartupEnableManagedSwitch
+0x9f5c6206cd6609b6 ManagedMode_StartupManagedSwitch
+0x91519377450fa09e ManagedMode_StartupNoManagedSwitch
+0xe6e506b6ca3fd10f ManagedUsers_UploadItem_Queued
+0xc5b20d272f57cec5 ManagedUsers_UploadItem_Syncing
+0x336d5775206b39a0 MaxButton_Clk_ExitFS
+0x30e3f55c61ca1f4d MaxButton_Clk_Maximize
+0x49226fae388cd5f0 MaxButton_Clk_Restore
+0x9c4e110de24ddbfb MaxButton_MaxLeft
+0xe5e2c8bb60a6f019 MaxButton_MaxRight
+0x0ed29608c3edb9ee MaxButton_Maximize
+0xfa675ab4e35a8dfb MaxButton_Minimize
+0x9ddc8fc34f81c18c MaxButton_Restore
+0xf5f4e08ff4ffc48e MaxButton_ShowBubble
+0x84ba0ed3cbdf3956 MediaContextMenu_Controls
+0x7b82a108ac28a1ac MediaContextMenu_Loop
+0x458edb8f0451b9f5 MediaContextMenu_Mute
+0xcbbec2e6e4bc9bc7 MediaContextMenu_Pause
+0x8b5912c6a1d5add6 MediaContextMenu_Play
+0xc2d04b65a8ff1f89 MediaContextMenu_Unmute
+0x6b52c76dc897d0ac MinButton_Clk
+0x7b262d2127dd8256 Minimize_UsingKey
+0xfa4408343dc15b72 MixedScript_LoadAnyway_Bubble
+0x3dce569ec6ea9080 MobileBeamCallbackSuccess
+0x90e5a607c36178ce MobileBeamInvalidAppState
+0xbc28c6539da4d688 MobileBreakpadUploadAttempt
+0x4622f7e73642ad8a MobileBreakpadUploadFailure
+0x29f2927c01084453 MobileBreakpadUploadSuccess
+0xd51394e7d79ed777 MobileContextMenuCopyImageLinkAddress
+0xa7b47844dbca122c MobileContextMenuCopyLinkAddress
+0x5ff99655278e08bf MobileContextMenuCopyLinkText
+0x6607f1a62c7086b7 MobileContextMenuImage
+0x5ac057123a1aa102 MobileContextMenuLink
+0xaea6ec9898f5dca7 MobileContextMenuOpenImageInNewTab
+0xf20535df9a8b8956 MobileContextMenuOpenLink
+0x9e77fb06de21d0b4 MobileContextMenuOpenLinkInIncognito
+0xa024c8dce2320bb1 MobileContextMenuOpenLinkInNewTab
+0xde20f676a6805404 MobileContextMenuSaveImage
+0xf123d71a7f1df18a MobileContextMenuSearchByImage
+0x470fb8fde85c094b MobileContextMenuShareLink
+0xb177bc454b6a2105 MobileContextMenuText
+0xac284cf4338f8a66 MobileContextMenuViewImage
+0xaa0f56a837e6fc61 MobileFreAttemptSignIn
+0xe18a359c1fcb3fbb MobileFreSignInSuccessful
+0x1d68dcd4ec7fdadc MobileFreSkipSignIn
+0xd593c486af2f742f MobileMenuAddToBookmarks
+0x952e55d25fd7f645 MobileMenuAllBookmarks
+0x012de2560a8ce076 MobileMenuBack
+0x8e57c931b602766a MobileMenuCloseAllTabs
+0xa8326b05fd6bc10c MobileMenuCloseTab
+0x4852b77757f1128a MobileMenuFeedback
+0x70d79227bd988ebd MobileMenuFindInPage
+0x6a191ad02dfcfde5 MobileMenuForward
+0x32de876b3eb8f2fb MobileMenuFullscreen
+0xa880dc9ccdc2ed51 MobileMenuNewIncognitoTab
+0x8d1aefe7246707fa MobileMenuNewTab
+0x0581354d10947136 MobileMenuOpenTabs
+0x6771b11116f29809 MobileMenuQuit
+0xdeddac455059a536 MobileMenuReload
+0xbd48a04b98a0806d MobileMenuSettings
+0x4a8e89dbe7dc9821 MobileMenuShare
+0xc9389060e824d3ec MobileMenuShow
+0x23f55337b40c7686 MobileNTPBookmark
+0x2927c5a40258df17 MobileNTPForeignSession
+0x5a4f535062ffe001 MobileNTPMostVisited
+0xc172db5c29ae2771 MobileNTPSwitchToBookmarks
+0xd4df8c01afe71935 MobileNTPSwitchToIncognito
+0x46c727e82f8494bc MobileNTPSwitchToMostVisited
+0x2f3ff7588b15e4b5 MobileNTPSwitchToOpenTabs
+0xd6643e725ce30ed4 MobileNewTabOpened
+0x90071ab23ccdcd96 MobileOmniboxSearch
+0x23037bbea96a8ceb MobileOmniboxVoiceSearch
+0xb1249f32bf64d5e8 MobilePageLoaded
+0x029217f521222d21 MobilePageLoadedDesktopUserAgent
+0x7bdf9c4a8dab56fb MobilePageLoadedWithKeyboard
+0xe9e4921fd2dc5ca6 MobileReceivedExternalIntent
+0xd38e217ec665e879 MobileRendererCrashed
+0x09618d294069e60c MobileShortcutAllBookmarks
+0x2ad4806d40f823b2 MobileShortcutFindInPage
+0xc6e9ebacfe2e732e MobileShortcutNewIncognitoTab
+0x54aa16ebe7a27823 MobileShortcutNewTab
+0x5b326627b3bfa8f2 MobileSideSwipeFinished
+0xd96fefb036806b54 MobileStackViewCloseTab
+0x0a340661b1591ab5 MobileStackViewSwipeCloseTab
+0xe0c5fc409e7d2a9e MobileTabClobbered
+0x27caa49d16b71362 MobileTabClosed
+0x371b72b6cd5313f4 MobileTabStripCloseTab
+0xbb2496f58a543215 MobileTabStripNewTab
+0x61bd701a880845ea MobileTabSwitched
+0xeddccaa7cc01c9c4 MobileToolbarBack
+0x0082decef81a99e8 MobileToolbarForward
+0xc7cd1610c9a15c4d MobileToolbarNewTab
+0xf7a930aae6dd681f MobileToolbarReload
+0x3cf24b6fee3f97bf MobileToolbarShowMenu
+0x3deff4b1d1a6c795 MobileToolbarShowStackView
+0xa358306810cb78c4 MobileToolbarStackViewNewTab
+0x001b06917446ac95 MobileToolbarToggleBookmark
+0xfe5d7732799048fd MobileUsingMenuByHwButtonDragging
+0xb25fb65d8d767718 MobileUsingMenuByHwButtonTap
+0xaf60773aea14a7b5 MobileUsingMenuBySwButtonDragging
+0x15fd6bb5bff45129 MobileUsingMenuBySwButtonTap
+0x409a073e57298782 MostVisited0
+0xaf4909be766297ab MostVisited1
+0x6028c57529e1608f MostVisited2
+0x3a94312581f33dde MostVisited3
+0xd8a6b50e524602b1 MostVisited4
+0xa61f8bda87c26817 MostVisited5
+0xaf2d6d86c5115610 MostVisited6
+0x576b4b3570828783 MostVisited7
+0x7e2c4d68af709827 MostVisited8
+0x1b40c6b1b5dd7106 MostVisited9
+0x245e4aa9fe5a8a3c MostVisitedReordered
+0x9c6a4ef293d946ca MostVisited_BlacklistCleared
+0x018c0ec301cb02ae MostVisited_UrlBlacklisted
+0x4cbb82140919fe65 MostVisited_UrlPinned
+0xa90e38146e0a4399 MostVisited_UrlRemoved
+0xe39ca5075f8cb467 MostVisited_UrlUnpinned
+0x4a0afb1ce16f661e Mouse_Down
+0xf812385dfcc1a683 MoveBackward
+0xd5980f1362f718dd MoveBackwardAndModifySelection
+0x8c95fa949833ae3c MoveDown
+0x601512931eeb8aa3 MoveDownAndModifySelection
+0x122077e11a3cc3a5 MoveForward
+0x645ad0c708fc5558 MoveForwardAndModifySelection
+0xe8a98c6fabdea857 MoveLeft
+0xe7929afc55d64080 MoveLeftAndModifySelection
+0xffee5f8627577124 MovePageDown
+0x7c9e3f063ca16598 MovePageDownAndModifySelection
+0x3f2197bd2a87175c MovePageUp
+0x2b0ce1185e0ee65d MovePageUpAndModifySelection
+0x78af9b7fcdf1574f MoveRight
+0x90177a63e4ab5878 MoveRightAndModifySelection
+0x6c8c1cceb6be3172 MoveTabNext
+0x56f311997d5f98ed MoveTabPrevious
+0xb57645f74f42e96c MoveToBeginningOfDocument
+0x3379b28a420f0c0e MoveToBeginningOfLine
+0xe9ba772da7cca699 MoveToBeginningOfLineAndModifySelection
+0x02bb149b88f68e59 MoveToBeginningOfParagraph
+0xfa68df5359bb8fdc MoveToBeginningOfParagraphAndModifySelection
+0x0d05f6fc5732a16d MoveToEndOfDocument
+0xd6b0cd02740d6118 MoveToEndOfLine
+0x660cce052c15cd1c MoveToEndOfLineAndModifySelection
+0x925cca836b27299f MoveToEndOfParagraph
+0xafbef52070141639 MoveToEndOfParagraphAndModifySelection
+0xa56a3ff692c679e3 MoveUp
+0x5011c876151c1812 MoveUpAndModifySelection
+0xccdc0bb665a92238 MoveWordBackward
+0x9372bb835cd720fb MoveWordForward
+0x002e07cb5223cd33 MoveWordLeft
+0xd55f7c4e520b18a4 MoveWordRight
+0xfc8e40d96ab33f1b NTPPromoClosed
+0x0cdd043c5d63d234 NTPPromoShown
+0xdcf1af37de1d8dd0 NativeUI_Applications
+0x08b0a573ad336d14 NavEntryCommitted
+0xcace6bb1e166082f NavEntryCommitted.SRP
+0x3c6e0d9310ba3a20 NewIncognitoWindow
+0xeddaa38a10bf8374 NewProfileWindowByIndex
+0x290eb683f96572f1 NewTab
+0x95c990454684cb1d NewTabPage_ReopenTab
+0xab4d417c5ca44904 NewTab_Button
+0xbdc9ec125e7a3ade NewWindow
+0xa86d43452b05bf72 Notifications.ShowMessageCenter
+0xa72c673a1f44d11f OmniboxDestinationURLIsSearchOnDSP
+0x6048dbd4f2f2ca50 OmniboxDestinationURLMatchesDefaultSearchProvider
+0x268376698078c71b OmniboxInputInProgress
+0xe7ff15c3f1043a26 Omnibox_DragString
+0x1a18c36c737ec22b Omnibox_DragURL
+0x56c5e8af805a2fe8 OpenAddBluetoothDeviceDialog
+0xa00fbd8da8229c83 OpenAllBookmarks
+0x7242962875070018 OpenAllBookmarksIncognitoWindow
+0x5e3bd4e3535ecc38 OpenAllBookmarksNewWindow
+0xf6bce188756ecaf8 OpenChangeProfilePictureDialog
+0x4b858349a1b8bb15 OpenFile
+0xedaa8487de2a33c6 OpenFileManager
+0xb3c3e8d99702cf70 OpenFileSystemPersistent
+0x1e6740b4b7fda686 OpenFileSystemTemporary
+0x4928347f9423c013 OpenInternetOptionsDialog
+0x83af6accb98b9954 OpenLanguageOptionsDialog
+0xe7147544a7db079d OpenSystemOptionsDialog
+0xe4f08e5732cebbd3 OpenTabpose
+0x7d3309f039cebdb1 Options_AppLanguage
+0xaabae975f4a0bb66 Options_AskForSaveLocation_Disable
+0x85464d6e64bbb505 Options_AskForSaveLocation_Enable
+0x158f62ce172e002b Options_AutoSpellCorrection_Disable
+0xa19b903d23620d91 Options_AutoSpellCorrection_Enable
+0xc77b497271ed97a4 Options_AutofillAuxiliaryProfiles_Disable
+0xb23c25ac48557c58 Options_AutofillAuxiliaryProfiles_Enable
+0x212dbab3096e37b2 Options_Autologin_Disable
+0x73bafa15344565f3 Options_Autologin_Enable
+0xbf4441a54e9b8e50 Options_BackgroundMode_Disable
+0xc481e10b3ba27f8c Options_BackgroundMode_Enable
+0xc65558de1b0b2371 Options_BlockAllPopups_Disable
+0x6886cd43bb132ac1 Options_BlockAllPopups_Enable
+0xa64d82b58336f482 Options_ChangeDefaultZoomLevel
+0x76cf57336cea96ff Options_ChangeFixedFont
+0xa198434035fd95dc Options_ChangeFontEncoding
+0xac4f01f24c2cad48 Options_ChangeProxies
+0x279dd81ae1252131 Options_ChangeSansSerifFont
+0xbbecdfd270d46408 Options_ChangeSerifFont
+0x45f2145964c18350 Options_ChangeStandardFont
+0x98ccc71c44973ca0 Options_CheckCertRevocation_Disable
+0xc6599b9ffadec866 Options_CheckCertRevocation_Enable
+0x67aa79d60894f3d7 Options_ClearData
+0x2d5b58850046ac0a Options_ContentSettings
+0xe2fd858f8395432f Options_CustomFrame_Disable
+0x531823c36ca21da2 Options_CustomFrame_Enable
+0x33e7b018e003c5b1 Options_DefaultCookieSettingChanged
+0x3864ed1197ddceb8 Options_DefaultGeolocationSettingChanged
+0x3f92cd6678d2f595 Options_DefaultHandlersSettingChanged
+0x5dfe307474e6b526 Options_DefaultImagesSettingChanged
+0x8ac0134529158dae Options_DefaultJavaScriptSettingChanged
+0x3a8bb054f5841f1a Options_DefaultMIDISysExSettingChanged
+0x04303682ca0b2a8d Options_DefaultMediaStreamMicSettingChanged
+0x6a97ed68e3457d0e Options_DefaultMediaStreamSettingChanged
+0xfca02a749fa0f811 Options_DefaultMouseLockSettingChanged
+0xbc49f9107e7c7c7c Options_DefaultNotificationsSettingChanged
+0x6b91203aa4b5fb3c Options_DefaultPluginsSettingChanged
+0x8b20daa9a0c1a0a6 Options_DefaultPopupsSettingChanged
+0x2d3b125fe15e828e Options_DictionaryLanguage
+0xc895ecf32a4970be Options_DisableCloudPrintProxy
+0xa381adec8b0e61ee Options_DisableGData_Disable
+0x31bc6949351f46a1 Options_DisableGData_Enable
+0x3c91497bc48f7456 Options_DnsPrefetchCheckbox_Disable
+0xb1c929ead405f1a9 Options_DnsPrefetchCheckbox_Enable
+0x5e1d34b2eb43d66f Options_DoNotTrackCheckbox_Disable
+0x127ee5905bb2d0cd Options_DoNotTrackCheckbox_Enable
+0x24f63c90f4b05e70 Options_EnableCloudPrintProxy
+0x7224f61ec49ec7ce Options_FormAutofill_Disable
+0xe88933ca2c819b4e Options_FormAutofill_Enable
+0xb186750fe61b8254 Options_GearsSettings
+0x9014fbda0ce53308 Options_GoogleGeolocationAccessCheckbox_Disable
+0x4954403fd4c98f51 Options_GoogleGeolocationAccessCheckbox_Enable
+0x8e87d1b7048f4b2f Options_GtkThemeSet
+0xa8b432017c641f12 Options_Homepage_HideHomeButton
+0xcf50dce927f3c8a8 Options_Homepage_HomeButton_Disable
+0x9815eaa9d1b11198 Options_Homepage_HomeButton_Enable
+0xb2391b14884e357a Options_Homepage_IsNewTabPage_Disable
+0x2e719fd1ab37b148 Options_Homepage_IsNewTabPage_Enable
+0xc8faba7110ff04c3 Options_Homepage_ShowHomeButton
+0x26cdb65b6a92b56a Options_Homepage_UseNewTab
+0xca6dd0b172e6df26 Options_Homepage_UseURL
+0x3462530e3c04ab92 Options_ImagesCheckbox_Disable
+0x3b55d5acba24ebad Options_ImagesCheckbox_Enable
+0xe82fe68817c3bf54 Options_InstantEnabled_Disable
+0x6efe012fa2603811 Options_InstantEnabled_Enable
+0xd7bc54bcc7d96d7b Options_InstantExtendedEnabled_Disable
+0x9eb89c74eb206694 Options_InstantExtendedEnabled_Enable
+0x9e2677a81e8d73a3 Options_Internet_DataRoaming_Disable
+0xce32dc47692c5927 Options_Internet_DataRoaming_Enable
+0x386291531b93301b Options_JavaCheckbox_Disable
+0xe1d9dbcef8116c71 Options_JavaCheckbox_Enable
+0x704c162610c6ffd5 Options_LinkDoctorCheckbox_Disable
+0x64ea4cda15571db8 Options_LinkDoctorCheckbox_Enable
+0xc8073584c5521315 Options_ManageCloudPrinters
+0xd97025bbf470c3ba Options_ManageSSLCertificates
+0xfeb23e6946b41cdc Options_ManageSearchEngines
+0x84502179f3e2ae8c Options_ManagerCerts
+0x540bea8eaba24835 Options_MetricsReportingCheckbox_Disable
+0x4aa2c70a745dbb49 Options_MetricsReportingCheckbox_Enable
+0x224b0bf60dccdeda Options_MousePrimaryRight_Disable
+0xb23cd3cde814d929 Options_MousePrimaryRight_Enable
+0x820f29cc9c44d0d5 Options_PasswordGenerationCheckbox_Disable
+0x4df19d1fb4741c2a Options_PasswordGenerationCheckbox_Enable
+0xc5fbe9d9b3a165dd Options_PasswordManager_Disable
+0x59b4f208d9d9f648 Options_PasswordManager_Enable
+0x6149925370ef4f47 Options_PluginsCheckbox_Disable
+0x38a52a23bebcb35d Options_PluginsCheckbox_Enable
+0x4c8f0d80d0819583 Options_ResetAutoOpenFiles
+0x0e3ea2998edfc23b Options_ResetToDefaults
+0xdad9014dcb04a1be Options_SSL2_Disable
+0xdacc44975593ad02 Options_SSL2_Enable
+0x88e4d09541842432 Options_SSL3_Disable
+0x6b2fbab68d97bb5b Options_SSL3_Enable
+0x08e75d386343cc27 Options_SafeBrowsingCheckbox_Disable
+0xc951b246a33514ac Options_SafeBrowsingCheckbox_Enable
+0x7653dc09eac4e2bf Options_SearchEngineChanged
+0x47fd936f55f6abd4 Options_SensitivitySlider_Changed
+0xb6e98e1635e14c7d Options_SetAsDefaultBrowser
+0x6268ba17ac147927 Options_SetDownloadDirectory
+0xcbfeef35b3ad832e Options_ShowAutoFillSettings
+0xeaa21f7cf4791a0f Options_ShowBookmarksBar_Disable
+0x0e3c8e82d47db7c6 Options_ShowBookmarksBar_Enable
+0x626c01f2ae5a9ba2 Options_ShowCookies
+0x9b00328b8c542526 Options_ShowPasswordManager
+0x1d4a5f924ea24d2c Options_ShowPasswordsExceptions
+0xc7fbc422d732eac5 Options_ShowProxySettings
+0xc9362f32313889f1 Options_SpeedFactorSlider_Changed
+0xc8fa104e4dd724e3 Options_SpellCheck_Disable
+0x7470044370eb75f8 Options_SpellCheck_Enable
+0xf9f1e5efda6f9978 Options_Startup_Custom
+0xf8e60cd9af4e6187 Options_Startup_Homepage
+0x1747b98bb0705d52 Options_Startup_LastSession
+0x635cadbdc678371f Options_Startup_NewTab
+0x24301fc721f3f091 Options_TLS1_Disable
+0x1c669fc919a6eccb Options_TLS1_Enable
+0x0e213ca8fa03d268 Options_TabsToLinks_Disable
+0x60adcbc1d31d59a2 Options_TabsToLinks_Enable
+0x01c2684695fc839e Options_TapToClickCheckbox_Disable
+0x6f37e83ce98b3082 Options_TapToClickCheckbox_Enable
+0x73defd4825af2700 Options_ThemesGallery
+0x60d52658d42b1593 Options_ThemesReset
+0x5101b63f43ebef59 Options_TouchpadNaturalScroll_Disable
+0xe1b1c799201cdfd3 Options_TouchpadNaturalScroll_Enable
+0x4a469294c73f23e4 Options_TouchpadTapToClick_Disable
+0x61a29472d343cf72 Options_TouchpadTapToClick_Enable
+0xa35806253d8d8b30 Options_Translate_Disable
+0x280bb55487be6eb4 Options_Translate_Enable
+0x5ebf6f9ecb47b4ad Options_UseSpellingServiceCheckbox_Disable
+0x78f845e65f47f3f6 Options_UseSpellingServiceCheckbox_Enable
+0x6f40a6712a19568a Options_UseSuggestCheckbox_Disable
+0x9abd34cb9a857b9e Options_UseSuggestCheckbox_Enable
+0x24604cce8816243c Options_VertEdgeScrollCheckbox_Disable
+0x8d45d4c781319d53 Options_VertEdgeScrollCheckbox_Enable
+0x40a2640625760310 OutdatedPluginInfobar.AllowThisTime
+0xa0361f9250c19197 OutdatedPluginInfobar.Closed
+0xb4be73d2951aab5b OutdatedPluginInfobar.Dismissed
+0x883c4259bb3beddd OutdatedPluginInfobar.LearnMore
+0xaf62158873b29888 OutdatedPluginInfobar.Shown
+0x3691471b03ca8103 OutdatedPluginInfobar.Shown.Java
+0x25e1fc613aa70de4 OutdatedPluginInfobar.Shown.QuickTime
+0x703e5cc7ad485d8f OutdatedPluginInfobar.Shown.Reader
+0x5c977c210e40986b OutdatedPluginInfobar.Shown.RealPlayer
+0xcc2c490fe5fc55ef OutdatedPluginInfobar.Shown.Shockwave
+0x0ef39278378fe05d OutdatedPluginInfobar.Shown.Silverlight
+0x7e7073691a152241 OutdatedPluginInfobar.Update
+0x26da45ced13360f3 OutdatedUpgradeBubble.Later
+0xe55f92fea3aac9d0 OutdatedUpgradeBubble.Reinstall
+0x9a1b867a0b9532ca OutdatedUpgradeBubble.Show
+0x016839db155e0468 Outdent
+0x69fae31849862d21 OverrideEncoding
+0xdcb4676e49e95259 PDF.FitToHeightButton
+0xac15a659a088ccc5 PDF.FitToPageButton
+0x5f58a2db6428c1a0 PDF.FitToWidthButton
+0xc3c876c4e5846f66 PDF.LoadFailure
+0x9c67afdea49aa8c1 PDF.LoadSuccess
+0xa0853d13a6382cb2 PDF.PreviewDocumentLoadFailure
+0x715bc13f0a521ab7 PDF.PrintButton
+0x95be082d470e41c9 PDF.PrintPage
+0x5b2d6203fcccbfa9 PDF.SaveButton
+0xf7d4dd6244747179 PDF.SavePage
+0x99ed44568e5ff51a PDF.ZoomFromBrowser
+0x1d57434947820665 PDF.ZoomInButton
+0x40ca10ced9d81d17 PDF.ZoomOutButton
+0xcf6b6026dc11987b PDF_EnableReaderInfoBarCancel
+0x00a3a874d94e0ae5 PDF_EnableReaderInfoBarOK
+0x8cae37cf015a06ba PDF_EnableReaderInfoBarShown
+0x1f8608be3f132d3f PDF_InstallReaderInfoBarCancel
+0x020d4194a7e4b5e1 PDF_InstallReaderInfoBarOK
+0xe8d7c93dac04f552 PDF_InstallReaderInfoBarShown
+0xbd058843faaa1507 PDF_ReaderInterstitialCancel
+0x673c5fad6fc74eac PDF_ReaderInterstitialIgnore
+0xe1cd8e7ef514360d PDF_ReaderInterstitialShown
+0x4bde610f2543fbd7 PDF_ReaderInterstitialUpdate
+0x0b951f22f9dff291 PDF_Unsupported_3D
+0x3c012d5822815c63 PDF_Unsupported_Attachment
+0x7322054dc4e9d451 PDF_Unsupported_Bookmarks
+0x75035f67192c6952 PDF_Unsupported_Digital_Signature
+0xc09901d647ad722f PDF_Unsupported_Movie
+0x282157da06d467b9 PDF_Unsupported_Portfolios
+0xdb9aecef729fd680 PDF_Unsupported_Portfolios_Packages
+0x74d8faa1b4e92791 PDF_Unsupported_Rights_Management
+0x571f65a8518214ae PDF_Unsupported_Screen
+0xdf8b4231d4bd3f90 PDF_Unsupported_Shared_Form
+0xb7474a7496f9a77e PDF_Unsupported_Shared_Review
+0x6efe497913838ea5 PDF_Unsupported_Sound
+0x08640e2d5578cf94 PDF_Unsupported_XFA
+0xde70e21d95b52c83 PDF_UseReaderInfoBarCancel
+0xc35f4595bbf2a0fa PDF_UseReaderInfoBarOK
+0xb7334d4097ba87ef PDF_UseReaderInfoBarShown
+0xbf1053adc4e5cd87 PPAPI.BrokerInfobarClickedAllow
+0x146afa4664512557 PPAPI.BrokerInfobarClickedDeny
+0xcd9ed785cbf9424b PPAPI.BrokerInfobarDisplayed
+0x002f8a6579713ab1 PPAPI.BrokerSettingAllow
+0x957b8f35c259d30a PPAPI.BrokerSettingDeny
+0xee3677bcca83ece9 PageDown
+0xac722301695b9315 PageLoad
+0x4e1f42df4b730437 PageLoadSRP
+0x9b869c510c75c582 PageUp
+0x9ba3ff80fde405cd PasswordManager_Disabled
+0x6cc1116fbd900ebf PasswordManager_Enabled
+0x36bb6559696dc912 Paste
+0x5d0e6942f354a06c PasteAndMatchStyle
+0xca471265efb33961 PluginContextMenu_RotateClockwise
+0xa260d9dde6e550c4 PluginContextMenu_RotateCounterclockwise
+0x6f2cd84fa374c281 Plugin_Blocked
+0xcecb82fcd8e64529 Plugin_ClickToPlay
+0xc52b281d793adc6b Plugin_Hide_Click
+0x838019f901a8e405 Plugin_Hide_Menu
+0x007757ef58e358af Plugin_Load_Click
+0xd84554ce585d6c63 Plugin_Load_Menu
+0x116bd7e07524f140 Plugin_Load_UI
+0x352f2d6315d52044 PrintNow
+0xcb83fba9c48fd911 PrintPreview
+0x89ad6a22de4ca850 PrintView_PrintDialog
+0x77db2baef38a1efc PrintView_PrintNow
+0xf5105f4fc4c32476 PrintView_ZoomMinus
+0xd432798852b5bdde PrintView_ZoomPageFull
+0x05bdd1f2f9628b7a PrintView_ZoomPageWidth
+0x89fa328f28747907 PrintView_ZoomPlus
+0xe23f821c3632547c ProcessSwapBindingsMismatch_RVHM
+0x5afeaba074ef570d Redo
+0x58d906ea1827983c RegisterProtocolHandler.ContextMenu_Open
+0x2f25b38028a24b10 RegisterProtocolHandler.ContextMenu_Settings
+0x21fd8c0ce09e106a RegisterProtocolHandler.InfoBar_Deny
+0xb1d098583dc63173 RegisterProtocolHandler.InfoBar_LearnMore
+0x1596504542ebc81d RegisterProtocolHandler.InfoBar_Shown
+0xee4b2f044de46f4b RegisterProtocolHandler.Infobar_Accept
+0x4d1c8263ba103675 Reload
+0x4641db18f24b11e1 ReloadIgnoringCache
+0xbcc54eb67cab2ae9 RemoveFormat
+0xa728f2892204aabc ReportBug
+0x4129a29cb4b8675d ResetProfile
+0x8f83bd601e845bc1 RestoreTab
+0x665cc78aff3f37f5 SBInterstitialMalwareDontProceed
+0xb00e7625ea2bc160 SBInterstitialMalwareDontProceed_V1
+0x32d1ed791369d0f3 SBInterstitialMalwareDontProceed_V2
+0xe25978a348044c85 SBInterstitialMalwareForcedDontProceed
+0x1cdfeccb11aecbfd SBInterstitialMalwareForcedDontProceed_V1
+0xdac337204e30c8f6 SBInterstitialMalwareForcedDontProceed_V2
+0xf02ed35cab0dcf4b SBInterstitialMalwareProceed
+0x90c44a041377ef24 SBInterstitialMalwareProceed_V1
+0x7ca5ef009d952b10 SBInterstitialMalwareProceed_V2
+0x09af23846e454261 SBInterstitialMalwareShow
+0x496ab75c7d751661 SBInterstitialMalwareShow_V1
+0xe882bc7f116fd6cd SBInterstitialMalwareShow_V2
+0xc81645e63b16cb44 SBInterstitialMultipleDontProceed
+0x30f4fb842cb92288 SBInterstitialMultipleDontProceed_V1
+0xc20442d6ef877b4b SBInterstitialMultipleDontProceed_V2
+0x8dd6ffcec8e73dd6 SBInterstitialMultipleForcedDontProceed
+0xe9d5cef9ca3da7a3 SBInterstitialMultipleForcedDontProceed_V1
+0x6c7b42218d4c0506 SBInterstitialMultipleForcedDontProceed_V2
+0x866cc35d2bcdf71d SBInterstitialMultipleProceed
+0x7e06a09bd57fcafa SBInterstitialMultipleProceed_V1
+0x98962df6f96dd0be SBInterstitialMultipleProceed_V2
+0x6dbe9571062fcfde SBInterstitialMultipleShow
+0xe639000a76d7e498 SBInterstitialMultipleShow_V1
+0xbe02295974c9a940 SBInterstitialMultipleShow_V2
+0x60578de80374e115 SBInterstitialPhishingDontProceed
+0x827278fea0de39a7 SBInterstitialPhishingDontProceed_V1
+0x569becba96026dfa SBInterstitialPhishingDontProceed_V2
+0xf3714282bdf38737 SBInterstitialPhishingForcedDontProceed
+0x62e1ba78dee8193c SBInterstitialPhishingForcedDontProceed_V1
+0x16741330208d63a3 SBInterstitialPhishingForcedDontProceed_V2
+0x340331e81b86f933 SBInterstitialPhishingProceed
+0x959e2d9b5f4f4a1d SBInterstitialPhishingProceed_V1
+0x6c158c3fee4d1bcd SBInterstitialPhishingProceed_V2
+0xf8af4ff865669301 SBInterstitialPhishingShow
+0x322a4e72ca14756b SBInterstitialPhishingShow_V1
+0xafb9afa1a94e513c SBInterstitialPhishingShow_V2
+0xe1df5f4bee6d0e2f SSL.DisplayedInsecureContent
+0xba6bde79f10497a9 SSL.RanInsecureContent
+0x12affa291e3d0146 SSL.RanInsecureContentGoogle
+0xc9cc8cce247e49ba Save
+0xfc7723f7c10f79d5 SavePage
+0xc849f604a9954989 ScreenLocker_OnLoginFailure
+0x0b8efe82e35086c2 ScreenLocker_Show
+0xe643aadfeec1d6fc ScreenLocker_Signout
+0x61ce545b97b3f1cd ScreenLocker_StartScreenSaver
+0x7a0c1d1c5392ec8e SearchWithRLZ
+0x2e17e73bd11af537 SearchWithoutRLZ
+0x702bbdc91c8e399d SelectAll
+0xd016dafd5f0eca55 SelectLastTab
+0x64658593002b74ad SelectLine
+0x25243a56d24dffd3 SelectNextTab
+0x7ae303310d8cfc29 SelectNumberedTab
+0x893981a84c5d0871 SelectPrevTab
+0x4578941ed28b34dd SelectProfile
+0x5b166a78549ae371 SelectTab0
+0x8fadb48c1fd4356e SelectTab1
+0xfa3cfe1e11999c78 SelectTab2
+0x43382573b0490660 SelectTab3
+0xcc1402f3ad4cae89 SelectTab4
+0x2d9491c68a4ec635 SelectTab5
+0x8fa9d8e88271c82d SelectTab6
+0xdaa611aa645914e5 SelectTab7
+0xbc7eb334ae9f29d0 ShowAccessibilitySettings
+0x1da022468e27685c ShowAppLauncherPage
+0x0d1d6961dd313b79 ShowAppMenu
+0x9be2b265107318b8 ShowApplications
+0x853927a304493ac7 ShowAsTab
+0x2c5584a8586dc1ab ShowBluetoothSettingsPage
+0x1b93c35c19ff3600 ShowBookmarkManager
+0xd1a227df4f361dbb ShowBookmarks
+0x1afb02b1f90b177e ShowBookmarksBar
+0xe8705f2d7890043e ShowControlPanel
+0x537e45904298316b ShowDateOptions
+0xa27f5c1b4192af95 ShowDisplayOptions
+0x3d0170d09a816e7f ShowDownloads
+0xf530f742ba5b2683 ShowExtensions
+0xa0118397d83c34d0 ShowFileBrowserFullTab
+0xb1abf919e7eea1ad ShowHelpTab
+0x12391b25bf32b0de ShowHelpTabViaF1
+0xb2a3954e828f87c9 ShowHelpTabViaWrenchMenu
+0xb04b2eea6e26ebef ShowHistory
+0x404c3c24f3091fd7 ShowJSConsole
+0xa231b4c4e5ada262 ShowModalDialog
+0x658963e1a47a5018 ShowOptions
+0x564171f658dcb78e ShowPageMenu
+0xecf70e5f5be34681 ShowRecentlyViewed
+0xfd243b004d004e00 ShowSections_RecentSitesDisabled
+0x3b86156dcf560cdb ShowSections_RecentSitesEnabled
+0x5118181c3ece5e84 ShowSessions
+0x1a4ebb180ba59b06 Shutdown
+0x26f93e6e68e28a69 Star
+0x2fbe99005588ef01 StartupTick
+0x11a755d598c0c417 Stop
+0x926a51baad949d12 Strikethrough
+0xc3100ff8c8a00184 SystemBack
+0x4c211ce58592c3e6 SystemBackForNavigation
+0x4d56afb0a9837d41 TabContextMenu_BookmarkAllTabs
+0x3712160bf3495979 TabContextMenu_CloseOtherTabs
+0x417bd10a7c5e0210 TabContextMenu_CloseTab
+0xa0965146c626cd18 TabContextMenu_CloseTabsOpenedBy
+0x6adcbb467523c7d9 TabContextMenu_CloseTabsToRight
+0xaadbb71a197d76ad TabContextMenu_CompactNavigationBar
+0x89e073e006a686d1 TabContextMenu_Duplicate
+0x88aefc727559ebaf TabContextMenu_NewTab
+0x218d462d319b449c TabContextMenu_OpenTabsLeftToRight
+0x807b9158faa086ca TabContextMenu_OpenTabsRightToLeft
+0x1180c152ca336f5d TabContextMenu_Reload
+0x7c86965f80103b54 TabContextMenu_RestoreTab
+0xdcc35326aa8a5aeb TabContextMenu_TogglePinned
+0xdd2b0058433af670 TabContextMenu_UseDestinationsTab_Off
+0xe5f9f328f5d86b51 TabContextMenu_UseDestinationsTab_On
+0x3fe88a1365e8dc47 TabContextMenu_UseVerticalTabs
+0xb5ffa70ecb67b6f3 TabOverview_DetachCell
+0x060f1f68f262b152 TabOverview_DragCell
+0xad9c26360444768c TabOverview_DragOverMiniWindow
+0x1cdf073bd93d5346 TabOverview_DropOnMiniWindow
+0x0d699bd1ec9da211 TabOverview_ExitMouse
+0x0dffb74e62a90ad3 TabOverview_Keystroke
+0x65b8a6d7098e4825 TabOverview_PressedCreateNewBrowserButton
+0x552a7bf28446f0aa Tab_DropURLBetweenTabs
+0xc508d4d1583f51d6 Tab_DropURLOnTab
+0xdad4668bc0b8e79c TaskManager
+0x23afdebb497957f4 Themes.Gone
+0x07c710bf40f92990 Themes.Loaded
+0x77ae5b6a7529d8b5 Themes.Migrated
+0x0e6b2a071df7800e Themes_Installed
+0xf1b1f7db67f07b8c Themes_Reset
+0xc2c0c13f120b9c7c ThirdPartyCookieBlockingDisabled
+0x60aa171d4c36e576 ThirdPartyCookieBlockingEnabled
+0x9e2832408b48e761 ToggleBold
+0x303ce89ccac1592b ToggleCompactNavigationBar
+0x94122935e94b54f3 ToggleDevTools
+0xb639f67713eed8ea ToggleDevToolsConsole
+0x887771883a8fbbae ToggleExtensionShelf
+0x5250f5caaff979ba ToggleFullscreen
+0xedf6e4b0b320885f ToggleItalic
+0x904d810f7dd68a8e ToggleUnderline
+0xb92bc75c64039682 Toolbar_DragStar
+0x8ce9fbd537e4983c TouchscreenScroll
+0x112c55c811540624 TouchscreenScrollFling
+0x05691d7006369070 Touchscreen_Down
+0x5d7f9a146f393dfc TrackpadScroll
+0x6f2d421111db4527 TrackpadScrollFling
+0xaf70b1ac863830a4 Transpose
+0x84416581e5767dfc Tray_Help
+0x1bba1e9ab7b38249 Tray_LockScreen
+0xcb28c56123f30247 Tray_ShutDown
+0x852721aa5fc738df Underline
+0x1cdc076b28f70afa Undo
+0xc1a39b6a60f8b2f8 Unlink
+0x46b816f573557a53 Unselect
+0xbcd41ce97e3c5568 UpdateChrome
+0x0746723e6884a2fb Updater.ServerCertificateChanged
+0x169dd0fd613963e8 Updater.ServerCertificateFailed
+0x9b4b5afb2e791f23 UpgradeCheck_AlreadyUpToDate
+0x27b72192736f904d UpgradeCheck_AlreadyUpgraded
+0x7a54d49f1f7db4ee UpgradeCheck_Done
+0x8bcf8b1b4f3c7451 UpgradeCheck_Error
+0xe42c4b8d6cb9188f UpgradeCheck_Started
+0x7edc3598854d0ab1 UpgradeCheck_TimedOut
+0x72714123f2bd0636 UpgradeCheck_UpgradeIsAvailable
+0xcd4da03d7cbaeb84 UpgradeCheck_Upgraded
+0x624ddd04836efdcd Upgrade_Started
+0xa909d722e2ae4285 ViewAboutConflicts
+0xf3768ba285ebca7e ViewAboutFlash
+0xd3879291d67e1389 ViewAboutNaCl
+0xfb4a178539bac6bd ViewSource
+0x6932875212d36f57 WP_EditImage
+0x34a770eb3bbf5632 WP_Gallery
+0x1058b3af68275a1d WebView.ExecuteScript
+0x749d2199e73fa34c WebView.Guest.Terminate
+0x50de3f60387a3613 WebView.WebRequest.AddListener
+0x949730a9468e27a1 WebsiteSettings_CookiesDialogOpened
+0xddc2a5698e145d16 WebsiteSettings_Opened
+0x75af94f65efafada Win8DesktopRestart
+0x8f88175ece0f933b Win8MetroRestart
+0x554103fbf5582ee0 ZoomMinus
+0x82d278b1f2e78bcd ZoomMinus_AtMinimum
+0x4344cd22d03f6800 ZoomNormal
+0x860db3714d502e03 ZoomPlus
+0x644dbac8a6242f3f ZoomPlus_AtMaximum
+0xbfb6af70a0626dcd justifyFull
+0x2768e36e23ebef80 mceAddControl
+0xfe4c8898ac25e705 mceBeginUndoLevel
+0x02650dd15c064422 mceEndUndoLevel
+0x2e58ba22e02b06bb mceInsertContent
+0xd311c8d6ed1b9762 mceRepaint
+0xf4c75cafe4330950 mceSave
+0xfb7010f719b412c4 mceSetStyleInfo
+0x7174576438022591 styleWithCSS
diff --git a/chromium/tools/metrics/actions/extract_actions.py b/chromium/tools/metrics/actions/extract_actions.py
new file mode 100755
index 00000000000..f6819afdd05
--- /dev/null
+++ b/chromium/tools/metrics/actions/extract_actions.py
@@ -0,0 +1,608 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Extract UserMetrics "actions" strings from the Chrome source.
+
+This program generates the list of known actions we expect to see in the
+user behavior logs. It walks the Chrome source, looking for calls to
+UserMetrics functions, extracting actions and warning on improper calls,
+as well as generating the lists of possible actions in situations where
+there are many possible actions.
+
+See also:
+ content/browser/user_metrics.h
+ http://wiki.corp.google.com/twiki/bin/view/Main/ChromeUserExperienceMetrics
+
+If run with a "--hash" argument, chromeactions.txt will be updated.
+"""
+
+__author__ = 'evanm (Evan Martin)'
+
+import hashlib
+from HTMLParser import HTMLParser
+import os
+import re
+import sys
+
+sys.path.insert(1, os.path.join(sys.path[0], '..', '..', 'python'))
+from google import path_utils
+
+# Files that are known to use content::RecordComputedAction(), which means
+# they require special handling code in this script.
+# To add a new file, add it to this list and add the appropriate logic to
+# generate the known actions to AddComputedActions() below.
+KNOWN_COMPUTED_USERS = (
+ 'back_forward_menu_model.cc',
+ 'options_page_view.cc',
+ 'render_view_host.cc', # called using webkit identifiers
+ 'user_metrics.cc', # method definition
+ 'new_tab_ui.cc', # most visited clicks 1-9
+ 'extension_metrics_module.cc', # extensions hook for user metrics
+ 'safe_browsing_blocking_page.cc', # various interstitial types and actions
+ 'language_options_handler_common.cc', # languages and input methods in CrOS
+ 'cros_language_options_handler.cc', # languages and input methods in CrOS
+ 'about_flags.cc', # do not generate a warning; see AddAboutFlagsActions()
+ 'external_metrics.cc', # see AddChromeOSActions()
+ 'core_options_handler.cc', # see AddWebUIActions()
+ 'browser_render_process_host.cc' # see AddRendererActions()
+)
+
+# Language codes used in Chrome. The list should be updated when a new
+# language is added to app/l10n_util.cc, as follows:
+#
+# % (cat app/l10n_util.cc | \
+# perl -n0e 'print $1 if /kAcceptLanguageList.*?\{(.*?)\}/s' | \
+# perl -nle 'print $1, if /"(.*)"/'; echo 'es-419') | \
+# sort | perl -pe "s/(.*)\n/'\$1', /" | \
+# fold -w75 -s | perl -pe 's/^/ /;s/ $//'; echo
+#
+# The script extracts language codes from kAcceptLanguageList, but es-419
+# (Spanish in Latin America) is an exception.
+LANGUAGE_CODES = (
+ 'af', 'am', 'ar', 'az', 'be', 'bg', 'bh', 'bn', 'br', 'bs', 'ca', 'co',
+ 'cs', 'cy', 'da', 'de', 'de-AT', 'de-CH', 'de-DE', 'el', 'en', 'en-AU',
+ 'en-CA', 'en-GB', 'en-NZ', 'en-US', 'en-ZA', 'eo', 'es', 'es-419', 'et',
+ 'eu', 'fa', 'fi', 'fil', 'fo', 'fr', 'fr-CA', 'fr-CH', 'fr-FR', 'fy',
+ 'ga', 'gd', 'gl', 'gn', 'gu', 'ha', 'haw', 'he', 'hi', 'hr', 'hu', 'hy',
+ 'ia', 'id', 'is', 'it', 'it-CH', 'it-IT', 'ja', 'jw', 'ka', 'kk', 'km',
+ 'kn', 'ko', 'ku', 'ky', 'la', 'ln', 'lo', 'lt', 'lv', 'mk', 'ml', 'mn',
+ 'mo', 'mr', 'ms', 'mt', 'nb', 'ne', 'nl', 'nn', 'no', 'oc', 'om', 'or',
+ 'pa', 'pl', 'ps', 'pt', 'pt-BR', 'pt-PT', 'qu', 'rm', 'ro', 'ru', 'sd',
+ 'sh', 'si', 'sk', 'sl', 'sn', 'so', 'sq', 'sr', 'st', 'su', 'sv', 'sw',
+ 'ta', 'te', 'tg', 'th', 'ti', 'tk', 'to', 'tr', 'tt', 'tw', 'ug', 'uk',
+ 'ur', 'uz', 'vi', 'xh', 'yi', 'yo', 'zh', 'zh-CN', 'zh-TW', 'zu',
+)
+
+# Input method IDs used in Chrome OS. The list should be updated when a
+# new input method is added to
+# chrome/browser/chromeos/input_method/input_methods.txt in the Chrome tree, as
+# follows:
+#
+# % sort chrome/browser/chromeos/input_method/input_methods.txt | \
+# perl -ne "print \"'\$1', \" if /^([^#]+?)\s/" | \
+# fold -w75 -s | perl -pe 's/^/ /;s/ $//'; echo
+#
+# The script extracts input method IDs from input_methods.txt.
+INPUT_METHOD_IDS = (
+ 'english-m', 'm17n:am:sera', 'm17n:ar:kbd', 'm17n:bn:itrans',
+ 'm17n:fa:isiri', 'm17n:gu:itrans', 'm17n:hi:itrans', 'm17n:kn:itrans',
+ 'm17n:ml:itrans', 'm17n:mr:itrans', 'm17n:ta:inscript', 'm17n:ta:itrans',
+ 'm17n:ta:phonetic', 'm17n:ta:tamil99', 'm17n:ta:typewriter',
+ 'm17n:te:itrans', 'm17n:th:kesmanee', 'm17n:th:pattachote',
+ 'm17n:th:tis820', 'm17n:vi:tcvn', 'm17n:vi:telex', 'm17n:vi:viqr',
+ 'm17n:vi:vni', 'm17n:zh:cangjie', 'm17n:zh:quick', 'mozc', 'mozc-chewing',
+ 'mozc-dv', 'mozc-hangul', 'mozc-jp', 'pinyin', 'pinyin-dv', 'xkb:be::fra',
+ 'xkb:be::ger', 'xkb:be::nld', 'xkb:bg::bul', 'xkb:bg:phonetic:bul',
+ 'xkb:br::por', 'xkb:ca::fra', 'xkb:ca:eng:eng', 'xkb:ch::ger',
+ 'xkb:ch:fr:fra', 'xkb:cz::cze', 'xkb:de::ger', 'xkb:de:neo:ger',
+ 'xkb:dk::dan', 'xkb:ee::est', 'xkb:es::spa', 'xkb:es:cat:cat',
+ 'xkb:fi::fin', 'xkb:fr::fra', 'xkb:gb:dvorak:eng', 'xkb:gb:extd:eng',
+ 'xkb:gr::gre', 'xkb:hr::scr', 'xkb:hu::hun', 'xkb:il::heb', 'xkb:it::ita',
+ 'xkb:jp::jpn', 'xkb:kr:kr104:kor', 'xkb:latam::spa', 'xkb:lt::lit',
+ 'xkb:lv:apostrophe:lav', 'xkb:no::nob', 'xkb:pl::pol', 'xkb:pt::por',
+ 'xkb:ro::rum', 'xkb:rs::srp', 'xkb:ru::rus', 'xkb:ru:phonetic:rus',
+ 'xkb:se::swe', 'xkb:si::slv', 'xkb:sk::slo', 'xkb:tr::tur', 'xkb:ua::ukr',
+ 'xkb:us::eng', 'xkb:us:altgr-intl:eng', 'xkb:us:colemak:eng',
+ 'xkb:us:dvorak:eng', 'xkb:us:intl:eng',
+)
+
+# The path to the root of the repository.
+REPOSITORY_ROOT = os.path.join(path_utils.ScriptDir(), '..', '..', '..')
+
+number_of_files_total = 0
+
+
+def AddComputedActions(actions):
+ """Add computed actions to the actions list.
+
+ Arguments:
+ actions: set of actions to add to.
+ """
+
+ # Actions for back_forward_menu_model.cc.
+ for dir in ('BackMenu_', 'ForwardMenu_'):
+ actions.add(dir + 'ShowFullHistory')
+ actions.add(dir + 'Popup')
+ for i in range(1, 20):
+ actions.add(dir + 'HistoryClick' + str(i))
+ actions.add(dir + 'ChapterClick' + str(i))
+
+ # Actions for new_tab_ui.cc.
+ for i in range(1, 10):
+ actions.add('MostVisited%d' % i)
+
+ # Actions for safe_browsing_blocking_page.cc.
+ for interstitial in ('Phishing', 'Malware', 'Multiple'):
+ for action in ('Show', 'Proceed', 'DontProceed', 'ForcedDontProceed'):
+ actions.add('SBInterstitial%s%s' % (interstitial, action))
+
+ # Actions for language_options_handler.cc (Chrome OS specific).
+ for input_method_id in INPUT_METHOD_IDS:
+ actions.add('LanguageOptions_DisableInputMethod_%s' % input_method_id)
+ actions.add('LanguageOptions_EnableInputMethod_%s' % input_method_id)
+ actions.add('InputMethodOptions_Open_%s' % input_method_id)
+ for language_code in LANGUAGE_CODES:
+ actions.add('LanguageOptions_UiLanguageChange_%s' % language_code)
+ actions.add('LanguageOptions_SpellCheckLanguageChange_%s' % language_code)
+
+def AddWebKitEditorActions(actions):
+ """Add editor actions from editor_client_impl.cc.
+
+ Arguments:
+ actions: set of actions to add to.
+ """
+ action_re = re.compile(r'''\{ [\w']+, +\w+, +"(.*)" +\},''')
+
+ editor_file = os.path.join(REPOSITORY_ROOT, 'webkit', 'api', 'src',
+ 'EditorClientImpl.cc')
+ for line in open(editor_file):
+ match = action_re.search(line)
+ if match: # Plain call to RecordAction
+ actions.add(match.group(1))
+
+def AddClosedSourceActions(actions):
+ """Add actions that are in code which is not checked out by default
+
+ Arguments
+ actions: set of actions to add to.
+ """
+ actions.add('PDF.PrintPage')
+ actions.add('PDF.FitToHeightButton')
+ actions.add('PDF.FitToWidthButton')
+ actions.add('PDF.LoadFailure')
+ actions.add('PDF.LoadSuccess')
+ actions.add('PDF.PreviewDocumentLoadFailure')
+ actions.add('PDF.ZoomFromBrowser')
+ actions.add('PDF.ZoomOutButton')
+ actions.add('PDF.ZoomInButton')
+ actions.add('PDF_Unsupported_Rights_Management')
+ actions.add('PDF_Unsupported_XFA')
+ actions.add('PDF_Unsupported_3D')
+ actions.add('PDF_Unsupported_Movie')
+ actions.add('PDF_Unsupported_Sound')
+ actions.add('PDF_Unsupported_Screen')
+ actions.add('PDF_Unsupported_Portfolios_Packages')
+ actions.add('PDF_Unsupported_Attachment')
+ actions.add('PDF_Unsupported_Digital_Signature')
+ actions.add('PDF_Unsupported_Shared_Review')
+ actions.add('PDF_Unsupported_Shared_Form')
+ actions.add('PDF_Unsupported_Bookmarks')
+
+def AddAndroidActions(actions):
+ """Add actions that are used by Chrome on Android.
+
+ Arguments
+ actions: set of actions to add to.
+ """
+ actions.add('MobileBeamCallbackSuccess')
+ actions.add('MobileBeamInvalidAppState')
+ actions.add('MobileBreakpadUploadAttempt')
+ actions.add('MobileBreakpadUploadFailure')
+ actions.add('MobileBreakpadUploadSuccess')
+ actions.add('MobileContextMenuCopyImageLinkAddress')
+ actions.add('MobileContextMenuCopyLinkAddress')
+ actions.add('MobileContextMenuCopyLinkText')
+ actions.add('MobileContextMenuImage')
+ actions.add('MobileContextMenuLink')
+ actions.add('MobileContextMenuOpenImageInNewTab')
+ actions.add('MobileContextMenuOpenLink')
+ actions.add('MobileContextMenuOpenLinkInIncognito')
+ actions.add('MobileContextMenuOpenLinkInNewTab')
+ actions.add('MobileContextMenuSaveImage')
+ actions.add('MobileContextMenuSearchByImage')
+ actions.add('MobileContextMenuShareLink')
+ actions.add('MobileContextMenuText')
+ actions.add('MobileContextMenuViewImage')
+ actions.add('MobileFreAttemptSignIn')
+ actions.add('MobileFreSignInSuccessful')
+ actions.add('MobileFreSkipSignIn')
+ actions.add('MobileMenuAddToBookmarks')
+ actions.add('MobileMenuAllBookmarks')
+ actions.add('MobileMenuBack')
+ actions.add('MobileMenuCloseAllTabs')
+ actions.add('MobileMenuCloseTab')
+ actions.add('MobileMenuFeedback')
+ actions.add('MobileMenuFindInPage')
+ actions.add('MobileMenuForward')
+ actions.add('MobileMenuFullscreen')
+ actions.add('MobileMenuNewIncognitoTab')
+ actions.add('MobileMenuNewTab')
+ actions.add('MobileMenuOpenTabs')
+ actions.add('MobileMenuQuit')
+ actions.add('MobileMenuReload')
+ actions.add('MobileMenuSettings')
+ actions.add('MobileMenuShare')
+ actions.add('MobileMenuShow')
+ actions.add('MobileNTPBookmark')
+ actions.add('MobileNTPForeignSession')
+ actions.add('MobileNTPMostVisited')
+ actions.add('MobileNTPSwitchToBookmarks')
+ actions.add('MobileNTPSwitchToIncognito')
+ actions.add('MobileNTPSwitchToMostVisited')
+ actions.add('MobileNTPSwitchToOpenTabs')
+ actions.add('MobileNewTabOpened')
+ actions.add('MobileOmniboxSearch')
+ actions.add('MobileOmniboxVoiceSearch')
+ actions.add('MobilePageLoaded')
+ actions.add('MobilePageLoadedDesktopUserAgent')
+ actions.add('MobilePageLoadedWithKeyboard')
+ actions.add('MobileReceivedExternalIntent')
+ actions.add('MobileRendererCrashed')
+ actions.add('MobileShortcutAllBookmarks')
+ actions.add('MobileShortcutFindInPage')
+ actions.add('MobileShortcutNewIncognitoTab')
+ actions.add('MobileShortcutNewTab')
+ actions.add('MobileSideSwipeFinished')
+ actions.add('MobileStackViewCloseTab')
+ actions.add('MobileStackViewSwipeCloseTab')
+ actions.add('MobileTabClobbered')
+ actions.add('MobileTabClosed')
+ actions.add('MobileTabStripCloseTab')
+ actions.add('MobileTabStripNewTab')
+ actions.add('MobileTabSwitched')
+ actions.add('MobileToolbarBack')
+ actions.add('MobileToolbarForward')
+ actions.add('MobileToolbarNewTab')
+ actions.add('MobileToolbarReload')
+ actions.add('MobileToolbarShowMenu')
+ actions.add('MobileToolbarShowStackView')
+ actions.add('MobileToolbarStackViewNewTab')
+ actions.add('MobileToolbarToggleBookmark')
+ actions.add('MobileUsingMenuByHwButtonDragging')
+ actions.add('MobileUsingMenuByHwButtonTap')
+ actions.add('MobileUsingMenuBySwButtonDragging')
+ actions.add('MobileUsingMenuBySwButtonTap')
+ actions.add('SystemBack')
+ actions.add('SystemBackForNavigation')
+
+def AddAboutFlagsActions(actions):
+ """This parses the experimental feature flags for UMA actions.
+
+ Arguments:
+ actions: set of actions to add to.
+ """
+ about_flags = os.path.join(REPOSITORY_ROOT, 'chrome', 'browser',
+ 'about_flags.cc')
+ flag_name_re = re.compile(r'\s*"([0-9a-zA-Z\-_]+)",\s*// FLAGS:RECORD_UMA')
+ for line in open(about_flags):
+ match = flag_name_re.search(line)
+ if match:
+ actions.add("AboutFlags_" + match.group(1))
+ # If the line contains the marker but was not matched by the regex, put up
+ # an error if the line is not a comment.
+ elif 'FLAGS:RECORD_UMA' in line and line[0:2] != '//':
+ print >>sys.stderr, 'WARNING: This line is marked for recording ' + \
+ 'about:flags metrics, but is not in the proper format:\n' + line
+
+def AddBookmarkManagerActions(actions):
+ """Add actions that are used by BookmarkManager.
+
+ Arguments
+ actions: set of actions to add to.
+ """
+ actions.add('BookmarkManager_Command_AddPage')
+ actions.add('BookmarkManager_Command_Copy')
+ actions.add('BookmarkManager_Command_Cut')
+ actions.add('BookmarkManager_Command_Delete')
+ actions.add('BookmarkManager_Command_Edit')
+ actions.add('BookmarkManager_Command_Export')
+ actions.add('BookmarkManager_Command_Import')
+ actions.add('BookmarkManager_Command_NewFolder')
+ actions.add('BookmarkManager_Command_OpenIncognito')
+ actions.add('BookmarkManager_Command_OpenInNewTab')
+ actions.add('BookmarkManager_Command_OpenInNewWindow')
+ actions.add('BookmarkManager_Command_OpenInSame')
+ actions.add('BookmarkManager_Command_Paste')
+ actions.add('BookmarkManager_Command_ShowInFolder')
+ actions.add('BookmarkManager_Command_Sort')
+ actions.add('BookmarkManager_Command_UndoDelete')
+ actions.add('BookmarkManager_Command_UndoGlobal')
+ actions.add('BookmarkManager_Command_UndoNone')
+
+ actions.add('BookmarkManager_NavigateTo_BookmarkBar')
+ actions.add('BookmarkManager_NavigateTo_Mobile')
+ actions.add('BookmarkManager_NavigateTo_Other')
+ actions.add('BookmarkManager_NavigateTo_Recent')
+ actions.add('BookmarkManager_NavigateTo_Search')
+ actions.add('BookmarkManager_NavigateTo_SubFolder')
+
+def AddChromeOSActions(actions):
+ """Add actions reported by non-Chrome processes in Chrome OS.
+
+ Arguments:
+ actions: set of actions to add to.
+ """
+ # Actions sent by Chrome OS update engine.
+ actions.add('Updater.ServerCertificateChanged')
+ actions.add('Updater.ServerCertificateFailed')
+
+ # Actions sent by Chrome OS cryptohome.
+ actions.add('Cryptohome.PKCS11InitFail')
+
+def AddExtensionActions(actions):
+ """Add actions reported by extensions via chrome.metricsPrivate API.
+
+ Arguments:
+ actions: set of actions to add to.
+ """
+ # Actions sent by Chrome OS File Browser.
+ actions.add('FileBrowser.CreateNewFolder')
+ actions.add('FileBrowser.PhotoEditor.Edit')
+ actions.add('FileBrowser.PhotoEditor.View')
+
+ # Actions sent by Google Now client.
+ actions.add('GoogleNow.MessageClicked')
+ actions.add('GoogleNow.ButtonClicked0')
+ actions.add('GoogleNow.ButtonClicked1')
+ actions.add('GoogleNow.WelcomeToastClickedYes')
+ actions.add('GoogleNow.WelcomeToastClickedNo')
+ actions.add('GoogleNow.WelcomeToastDismissed')
+ actions.add('GoogleNow.Dismissed')
+
+def GrepForActions(path, actions):
+ """Grep a source file for calls to UserMetrics functions.
+
+ Arguments:
+ path: path to the file
+ actions: set of actions to add to
+ """
+ global number_of_files_total
+ number_of_files_total = number_of_files_total + 1
+ # we look for the UserMetricsAction structure constructor
+ # this should be on one line
+ action_re = re.compile(r'[^a-zA-Z]UserMetricsAction\("([^"]*)')
+ malformed_action_re = re.compile(r'[^a-zA-Z]UserMetricsAction\([^"]')
+ computed_action_re = re.compile(r'RecordComputedAction')
+ line_number = 0
+ for line in open(path):
+ line_number = line_number + 1
+ match = action_re.search(line)
+ if match: # Plain call to RecordAction
+ actions.add(match.group(1))
+ elif malformed_action_re.search(line):
+ # Warn if this line is using RecordAction incorrectly.
+ print >>sys.stderr, ('WARNING: %s has malformed call to RecordAction'
+ ' at %d' % (path, line_number))
+ elif computed_action_re.search(line):
+ # Warn if this file shouldn't be calling RecordComputedAction.
+ if os.path.basename(path) not in KNOWN_COMPUTED_USERS:
+ print >>sys.stderr, ('WARNING: %s has RecordComputedAction at %d' %
+ (path, line_number))
+
+class WebUIActionsParser(HTMLParser):
+ """Parses an HTML file, looking for all tags with a 'metric' attribute.
+ Adds user actions corresponding to any metrics found.
+
+ Arguments:
+ actions: set of actions to add to
+ """
+ def __init__(self, actions):
+ HTMLParser.__init__(self)
+ self.actions = actions
+
+ def handle_starttag(self, tag, attrs):
+ # We only care to examine tags that have a 'metric' attribute.
+ attrs = dict(attrs)
+ if not 'metric' in attrs:
+ return
+
+ # Boolean metrics have two corresponding actions. All other metrics have
+ # just one corresponding action. By default, we check the 'dataType'
+ # attribute.
+ is_boolean = ('dataType' in attrs and attrs['dataType'] == 'boolean')
+ if 'type' in attrs and attrs['type'] in ('checkbox', 'radio'):
+ if attrs['type'] == 'checkbox':
+ is_boolean = True
+ else:
+ # Radio buttons are boolean if and only if their values are 'true' or
+ # 'false'.
+ assert(attrs['type'] == 'radio')
+ if 'value' in attrs and attrs['value'] in ['true', 'false']:
+ is_boolean = True
+
+ if is_boolean:
+ self.actions.add(attrs['metric'] + '_Enable')
+ self.actions.add(attrs['metric'] + '_Disable')
+ else:
+ self.actions.add(attrs['metric'])
+
+def GrepForWebUIActions(path, actions):
+ """Grep a WebUI source file for elements with associated metrics.
+
+ Arguments:
+ path: path to the file
+ actions: set of actions to add to
+ """
+ close_called = False
+ try:
+ parser = WebUIActionsParser(actions)
+ parser.feed(open(path).read())
+ # An exception can be thrown by parser.close(), so do it in the try to
+ # ensure the path of the file being parsed gets printed if that happens.
+ close_called = True
+ parser.close()
+ except Exception, e:
+ print "Error encountered for path %s" % path
+ raise e
+ finally:
+ if not close_called:
+ parser.close()
+
+def WalkDirectory(root_path, actions, extensions, callback):
+ for path, dirs, files in os.walk(root_path):
+ if '.svn' in dirs:
+ dirs.remove('.svn')
+ if '.git' in dirs:
+ dirs.remove('.git')
+ for file in files:
+ ext = os.path.splitext(file)[1]
+ if ext in extensions:
+ callback(os.path.join(path, file), actions)
+
+def GrepForRendererActions(path, actions):
+ """Grep a source file for calls to RenderThread::RecordUserMetrics.
+
+ Arguments:
+ path: path to the file
+ actions: set of actions to add to
+ """
+ # We look for the ViewHostMsg_UserMetricsRecordAction constructor.
+ # This should be on one line.
+ action_re = re.compile(
+ r'[^a-zA-Z]RenderThread::RecordUserMetrics\("([^"]*)')
+ line_number = 0
+ for line in open(path):
+ match = action_re.search(line)
+ if match: # Plain call to RecordAction
+ actions.add(match.group(1))
+
+def AddLiteralActions(actions):
+ """Add literal actions specified via calls to UserMetrics functions.
+
+ Arguments:
+ actions: set of actions to add to.
+ """
+ EXTENSIONS = ('.cc', '.mm', '.c', '.m')
+
+ # Walk the source tree to process all .cc files.
+ chrome_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'chrome'))
+ WalkDirectory(chrome_root, actions, EXTENSIONS, GrepForActions)
+ content_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'content'))
+ WalkDirectory(content_root, actions, EXTENSIONS, GrepForActions)
+ webkit_root = os.path.normpath(os.path.join(REPOSITORY_ROOT, 'webkit'))
+ WalkDirectory(os.path.join(webkit_root, 'glue'), actions, EXTENSIONS,
+ GrepForActions)
+ WalkDirectory(os.path.join(webkit_root, 'port'), actions, EXTENSIONS,
+ GrepForActions)
+
+def AddWebUIActions(actions):
+ """Add user actions defined in WebUI files.
+
+ Arguments:
+ actions: set of actions to add to.
+ """
+ resources_root = os.path.join(REPOSITORY_ROOT, 'chrome', 'browser',
+ 'resources')
+ WalkDirectory(resources_root, actions, ('.html'), GrepForWebUIActions)
+
+def AddRendererActions(actions):
+ """Add user actions sent via calls to RenderThread::RecordUserMetrics.
+
+ Arguments:
+ actions: set of actions to add to.
+ """
+ EXTENSIONS = ('.cc', '.mm', '.c', '.m')
+
+ chrome_renderer_root = os.path.join(REPOSITORY_ROOT, 'chrome', 'renderer')
+ content_renderer_root = os.path.join(REPOSITORY_ROOT, 'content', 'renderer')
+ WalkDirectory(chrome_renderer_root, actions, EXTENSIONS,
+ GrepForRendererActions)
+ WalkDirectory(content_renderer_root, actions, EXTENSIONS,
+ GrepForRendererActions)
+
+def AddHistoryPageActions(actions):
+ """Add actions that are used in History page.
+
+ Arguments
+ actions: set of actions to add to.
+ """
+ actions.add('HistoryPage_BookmarkStarClicked')
+ actions.add('HistoryPage_EntryMenuRemoveFromHistory')
+ actions.add('HistoryPage_EntryLinkClick')
+ actions.add('HistoryPage_EntryLinkRightClick')
+ actions.add('HistoryPage_SearchResultClick')
+ actions.add('HistoryPage_EntryMenuShowMoreFromSite')
+ actions.add('HistoryPage_NewestHistoryClick')
+ actions.add('HistoryPage_NewerHistoryClick')
+ actions.add('HistoryPage_OlderHistoryClick')
+ actions.add('HistoryPage_Search')
+ actions.add('HistoryPage_InitClearBrowsingData')
+ actions.add('HistoryPage_RemoveSelected')
+ actions.add('HistoryPage_SearchResultRemove')
+ actions.add('HistoryPage_ConfirmRemoveSelected')
+ actions.add('HistoryPage_CancelRemoveSelected')
+
+def main(argv):
+ if '--hash' in argv:
+ hash_output = True
+ else:
+ hash_output = False
+ print >>sys.stderr, "WARNING: If you added new UMA tags, you must" + \
+ " use the --hash option to update chromeactions.txt."
+ # if we do a hash output, we want to only append NEW actions, and we know
+ # the file we want to work on
+ actions = set()
+
+ chromeactions_path = os.path.join(path_utils.ScriptDir(), "chromeactions.txt")
+
+ if hash_output:
+ f = open(chromeactions_path)
+ for line in f:
+ part = line.rpartition("\t")
+ part = part[2].strip()
+ actions.add(part)
+ f.close()
+
+
+ AddComputedActions(actions)
+ # TODO(fmantek): bring back webkit editor actions.
+ # AddWebKitEditorActions(actions)
+ AddAboutFlagsActions(actions)
+ AddWebUIActions(actions)
+ AddRendererActions(actions)
+
+ AddLiteralActions(actions)
+
+ # print "Scanned {0} number of files".format(number_of_files_total)
+ # print "Found {0} entries".format(len(actions))
+
+ AddClosedSourceActions(actions)
+ AddChromeOSActions(actions)
+ AddExtensionActions(actions)
+ AddAndroidActions(actions)
+ AddBookmarkManagerActions(actions)
+ AddHistoryPageActions(actions)
+
+ if hash_output:
+ f = open(chromeactions_path, "wb")
+
+
+ # Print out the actions as a sorted list.
+ for action in sorted(actions):
+ if hash_output:
+ hash = hashlib.md5()
+ hash.update(action)
+ print >>f, '0x%s\t%s' % (hash.hexdigest()[:16], action)
+ else:
+ print action
+
+ if hash_output:
+ print "Done. Do not forget to add chromeactions.txt to your changelist"
+ return 0
+
+
+if '__main__' == __name__:
+ sys.exit(main(sys.argv))
diff --git a/chromium/tools/metrics/actions/extract_actions.sh b/chromium/tools/metrics/actions/extract_actions.sh
new file mode 100755
index 00000000000..88b6d2fcdf5
--- /dev/null
+++ b/chromium/tools/metrics/actions/extract_actions.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+system_root=`cygpath "$SYSTEMROOT"`
+export PATH="/usr/bin:$system_root/system32:$system_root:$system_root/system32/WBEM"
+
+exec_dir=$(dirname $0)
+
+"$exec_dir/../../../third_party/python_24/python.exe" \
+ "$exec_dir/extract_actions.py" "$@"
diff --git a/chromium/tools/metrics/histograms/PRESUBMIT.py b/chromium/tools/metrics/histograms/PRESUBMIT.py
new file mode 100644
index 00000000000..a4b4ee74b03
--- /dev/null
+++ b/chromium/tools/metrics/histograms/PRESUBMIT.py
@@ -0,0 +1,39 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into gcl.
+"""
+
+
+def CheckChange(input_api, output_api):
+ """Checks that histograms.xml is pretty-printed and well-formatted."""
+ for f in input_api.AffectedTextFiles():
+ p = f.AbsoluteLocalPath()
+ if (input_api.basename(p) == 'histograms.xml'
+ and input_api.os_path.dirname(p) == input_api.PresubmitLocalPath()):
+ cwd = input_api.os_path.dirname(p)
+ exit_code = input_api.subprocess.call(
+ ['python', 'pretty_print.py', '--presubmit'], cwd=cwd)
+ if exit_code != 0:
+ return [output_api.PresubmitError(
+ 'histograms.xml is not formatted correctly; run pretty_print.py '
+ 'to fix')]
+
+ exit_code = input_api.subprocess.call(
+ ['python', 'validate_format.py'], cwd=cwd)
+ if exit_code != 0:
+ return [output_api.PresubmitError(
+ 'histograms.xml is not well formatted; run validate_format.py '
+ 'and fix the reported errors')]
+ return []
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CheckChange(input_api, output_api)
diff --git a/chromium/tools/metrics/histograms/diffutil.py b/chromium/tools/metrics/histograms/diffutil.py
new file mode 100644
index 00000000000..0350a58c8ec
--- /dev/null
+++ b/chromium/tools/metrics/histograms/diffutil.py
@@ -0,0 +1,47 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility functions for prompting user if changes automatically applied to some
+user-managed files are correct.
+"""
+
+import logging
+import os
+import webbrowser
+
+from difflib import HtmlDiff
+from tempfile import NamedTemporaryFile
+
+
+def PromptUserToAcceptDiff(old_text, new_text, prompt):
+ """Displays a difference in two strings (old and new file contents) to the
+ user and asks whether the new version is acceptable.
+
+ Args:
+ old_text: A string containing old file contents.
+ new_text: A string containing new file contents.
+ prompt: Text that should be displayed to the user, asking whether the new
+ file contents should be accepted.
+
+ Returns:
+ True is user accepted the changes or there were no changes, False otherwise.
+ """
+ logging.info('Computing diff...')
+ if old_text == new_text:
+ logging.info('No changes detected')
+ return True
+ html_diff = HtmlDiff(wrapcolumn=80).make_file(
+ old_text.splitlines(), new_text.splitlines(), fromdesc='Original',
+ todesc='Updated', context=True, numlines=5)
+ temp = NamedTemporaryFile(suffix='.html', delete=False)
+ try:
+ temp.write(html_diff)
+ temp.close() # Close the file so the browser process can access it.
+ webbrowser.open('file://' + temp.name)
+ print prompt
+ response = raw_input('(Y/n): ').strip().lower()
+ finally:
+ temp.close() # May be called on already closed file.
+ os.remove(temp.name)
+ return response == 'y' or response == ''
diff --git a/chromium/tools/metrics/histograms/extract_histograms.py b/chromium/tools/metrics/histograms/extract_histograms.py
new file mode 100644
index 00000000000..1ba030c1bcf
--- /dev/null
+++ b/chromium/tools/metrics/histograms/extract_histograms.py
@@ -0,0 +1,368 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Extract histogram names from the description XML file.
+
+For more information on the format of the XML file, which is self-documenting,
+see histograms.xml; however, here is a simple example to get you started. The
+XML below will generate the following five histograms:
+
+ HistogramTime
+ HistogramEnum
+ HistogramEnum_Chrome
+ HistogramEnum_IE
+ HistogramEnum_Firefox
+
+<histogram-configuration>
+
+<histograms>
+
+<histogram name="HistogramTime" units="milliseconds">
+ <summary>A brief description.</summary>
+ <details>This is a more thorough description of this histogram.</details>
+</histogram>
+
+<histogram name="HistogramEnum" enum="MyEnumType">
+ <summary>This histogram sports an enum value type.</summary>
+</histogram>
+
+</histograms>
+
+<enums>
+
+<enum name="MyEnumType">
+ <summary>This is an example enum type, where the values mean little.</summary>
+ <int value="1" label="FIRST_VALUE">This is the first value.</int>
+ <int value="2" label="SECOND_VALUE">This is the second value.</int>
+</enum>
+
+</enums>
+
+<fieldtrials>
+
+<fieldtrial name="BrowserType">
+ <group name="Chrome"/>
+ <group name="IE"/>
+ <group name="Firefox"/>
+ <affected-histogram name="HistogramEnum"/>
+</fieldtrial>
+
+</fieldtrials>
+
+</histogram-configuration>
+
+"""
+
+import copy
+import logging
+import xml.dom.minidom
+
+
+MAX_FIELDTRIAL_DEPENDENCY_DEPTH = 5
+
+
+class Error(Exception):
+ pass
+
+
+def JoinChildNodes(tag):
+ return ''.join([c.toxml() for c in tag.childNodes]).strip()
+
+
+def NormalizeAttributeValue(s):
+ """Normalizes an attribute value (which might be wrapped over multiple lines)
+ by replacing each whitespace sequence with a single space.
+
+ Args:
+ s: The string to normalize, e.g. ' \n a b c\n d '
+
+ Returns:
+ The normalized string, e.g. 'a b c d'
+ """
+ return ' '.join(s.split())
+
+
+def NormalizeAllAttributeValues(node):
+ """Recursively normalizes all tag attribute values in the given tree.
+
+ Args:
+ node: The minidom node to be normalized.
+
+ Returns:
+ The normalized minidom node.
+ """
+ if node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE:
+ for a in node.attributes.keys():
+ node.attributes[a].value = NormalizeAttributeValue(
+ node.attributes[a].value)
+
+ for c in node.childNodes: NormalizeAllAttributeValues(c)
+ return node
+
+
+def _ExpandHistogramNameWithFieldTrial(group_name, histogram_name, fieldtrial):
+ """Creates a new histogram name based on the field trial group.
+
+ Args:
+ group_name: The name of the field trial group. May be empty.
+ histogram_name: The name of the histogram. May be of the form
+ Group.BaseName or BaseName
+ field_trial: The FieldTrial XML element.
+
+ Returns:
+ A string with the expanded histogram name.
+
+ Raises:
+ Error if the expansion can't be done.
+ """
+ if fieldtrial.hasAttribute('separator'):
+ separator = fieldtrial.getAttribute('separator')
+ else:
+ separator = '_'
+
+ if fieldtrial.hasAttribute('ordering'):
+ ordering = fieldtrial.getAttribute('ordering')
+ else:
+ ordering = 'suffix'
+ if ordering not in ['prefix', 'suffix']:
+ logging.error('ordering needs to be prefix or suffix, value is %s' %
+ ordering)
+ raise Error()
+
+ if not group_name:
+ return histogram_name
+
+ if ordering == 'suffix':
+ return histogram_name + separator + group_name
+
+ # For prefixes, the group_name is inserted between the "cluster" and the
+ # "remainder", e.g. Foo.BarHist expanded with gamma becomes Foo.gamma_BarHist.
+ sections = histogram_name.split('.')
+ if len(sections) <= 1:
+ logging.error(
+ 'Prefix Field Trial expansions require histogram names which include a '
+ 'dot separator. Histogram name is %s, and Field Trial is %s' %
+ (histogram_name, fieldtrial.getAttribute('name')))
+ raise Error()
+
+ cluster = sections[0] + '.'
+ remainder = '.'.join(sections[1:])
+ return cluster + group_name + separator + remainder
+
+
+def ExtractHistograms(filename):
+ """Compute the histogram names and descriptions from the XML representation.
+
+ Args:
+ filename: The path to the histograms XML file.
+
+ Returns:
+ { 'histogram_name': 'histogram_description', ... }
+
+ Raises:
+ Error if the file is not well-formatted.
+ """
+ # Slurp in histograms.xml
+ raw_xml = ''
+ with open(filename, 'r') as f:
+ raw_xml = f.read()
+
+ # Parse the XML into a tree
+ tree = xml.dom.minidom.parseString(raw_xml)
+ NormalizeAllAttributeValues(tree)
+
+ histograms = {}
+ have_errors = False
+
+ # Load the enums.
+ enums = {}
+ last_name = None
+ for enum in tree.getElementsByTagName("enum"):
+ if enum.getAttribute('type') != 'int':
+ logging.error('Unknown enum type %s' % enum.getAttribute('type'))
+ have_errors = True
+ continue
+
+ name = enum.getAttribute('name')
+ if last_name is not None and name.lower() < last_name.lower():
+ logging.error('Enums %s and %s are not in alphabetical order'
+ % (last_name, name))
+ have_errors = True
+ last_name = name
+
+ if name in enums:
+ logging.error('Duplicate enum %s' % name)
+ have_errors = True
+ continue
+
+ last_int_value = None
+ enum_dict = {}
+ enum_dict['name'] = name
+ enum_dict['values'] = {}
+
+ for int_tag in enum.getElementsByTagName("int"):
+ value_dict = {}
+ int_value = int(int_tag.getAttribute('value'))
+ if last_int_value is not None and int_value < last_int_value:
+ logging.error('Enum %s int values %d and %d are not in numerical order'
+ % (name, last_int_value, int_value))
+ have_errors = True
+ last_int_value = int_value
+ if int_value in enum_dict['values']:
+ logging.error('Duplicate enum value %d for enum %s' % (int_value, name))
+ have_errors = True
+ continue
+ value_dict['label'] = int_tag.getAttribute('label')
+ value_dict['summary'] = JoinChildNodes(int_tag)
+ enum_dict['values'][int_value] = value_dict
+
+ summary_nodes = enum.getElementsByTagName("summary")
+ if len(summary_nodes) > 0:
+ enum_dict['summary'] = JoinChildNodes(summary_nodes[0])
+
+ enums[name] = enum_dict
+
+ # Process the histograms. The descriptions can include HTML tags.
+ last_name = None
+ for histogram in tree.getElementsByTagName("histogram"):
+ name = histogram.getAttribute('name')
+ if last_name is not None and name.lower() < last_name.lower():
+ logging.error('Histograms %s and %s are not in alphabetical order'
+ % (last_name, name))
+ have_errors = True
+ last_name = name
+ if name in histograms:
+ logging.error('Duplicate histogram definition %s' % name)
+ have_errors = True
+ continue
+ histograms[name] = {}
+
+ # Find <summary> tag.
+ summary_nodes = histogram.getElementsByTagName("summary")
+ if len(summary_nodes) > 0:
+ histograms[name]['summary'] = JoinChildNodes(summary_nodes[0])
+ else:
+ histograms[name]['summary'] = 'TBD'
+
+ # Find <obsolete> tag.
+ obsolete_nodes = histogram.getElementsByTagName("obsolete")
+ if len(obsolete_nodes) > 0:
+ reason = JoinChildNodes(obsolete_nodes[0])
+ histograms[name]['obsolete'] = reason
+
+ # Handle units.
+ if histogram.hasAttribute('units'):
+ histograms[name]['units'] = histogram.getAttribute('units')
+
+ # Find <details> tag.
+ details_nodes = histogram.getElementsByTagName("details")
+ if len(details_nodes) > 0:
+ histograms[name]['details'] = JoinChildNodes(details_nodes[0])
+
+ # Handle enum types.
+ if histogram.hasAttribute('enum'):
+ enum_name = histogram.getAttribute('enum')
+ if not enum_name in enums:
+ logging.error('Unknown enum %s in histogram %s' % (enum_name, name))
+ have_errors = True
+ else:
+ histograms[name]['enum'] = enums[enum_name]
+
+ # Process the field trials and compute the combinations with their affected
+ # histograms.
+ last_name = None
+ for fieldtrial in tree.getElementsByTagName("fieldtrial"):
+ name = fieldtrial.getAttribute('name')
+ if last_name is not None and name.lower() < last_name.lower():
+ logging.error('Field trials %s and %s are not in alphabetical order'
+ % (last_name, name))
+ have_errors = True
+ last_name = name
+ # Field trials can depend on other field trials, so we need to be careful.
+ # Make a temporary copy of the list of field trials to use as a queue.
+ # Field trials whose dependencies have not yet been processed will get
+ # relegated to the back of the queue to be processed later.
+ reprocess_queue = []
+ def GenerateFieldTrials():
+ for f in tree.getElementsByTagName("fieldtrial"): yield 0, f
+ for r, f in reprocess_queue: yield r, f
+ for reprocess_count, fieldtrial in GenerateFieldTrials():
+ # Check dependencies first
+ dependencies_valid = True
+ affected_histograms = fieldtrial.getElementsByTagName('affected-histogram')
+ for affected_histogram in affected_histograms:
+ histogram_name = affected_histogram.getAttribute('name')
+ if not histogram_name in histograms:
+ # Base histogram is missing
+ dependencies_valid = False
+ missing_dependency = histogram_name
+ break
+ if not dependencies_valid:
+ if reprocess_count < MAX_FIELDTRIAL_DEPENDENCY_DEPTH:
+ reprocess_queue.append( (reprocess_count + 1, fieldtrial) )
+ continue
+ else:
+ logging.error('Field trial %s is missing its dependency %s'
+ % (fieldtrial.getAttribute('name'),
+ missing_dependency))
+ have_errors = True
+ continue
+
+ name = fieldtrial.getAttribute('name')
+ groups = fieldtrial.getElementsByTagName('group')
+ group_labels = {}
+ for group in groups:
+ group_labels[group.getAttribute('name')] = group.getAttribute('label')
+ last_histogram_name = None
+ for affected_histogram in affected_histograms:
+ histogram_name = affected_histogram.getAttribute('name')
+ if (last_histogram_name is not None
+ and histogram_name.lower() < last_histogram_name.lower()):
+ logging.error('Affected histograms %s and %s of field trial %s are not '
+ 'in alphabetical order'
+ % (last_histogram_name, histogram_name, name))
+ have_errors = True
+ last_histogram_name = histogram_name
+ base_description = histograms[histogram_name]
+ with_groups = affected_histogram.getElementsByTagName('with-group')
+ if len(with_groups) > 0:
+ histogram_groups = with_groups
+ else:
+ histogram_groups = groups
+ for group in histogram_groups:
+ group_name = group.getAttribute('name')
+ try:
+ new_histogram_name = _ExpandHistogramNameWithFieldTrial(
+ group_name, histogram_name, fieldtrial)
+ if new_histogram_name != histogram_name:
+ histograms[new_histogram_name] = copy.deepcopy(
+ histograms[histogram_name])
+
+ group_label = group_labels.get(group_name, '')
+
+ if not 'fieldtrial_groups' in histograms[new_histogram_name]:
+ histograms[new_histogram_name]['fieldtrial_groups'] = []
+ histograms[new_histogram_name]['fieldtrial_groups'].append(group_name)
+
+ if not 'fieldtrial_names' in histograms[new_histogram_name]:
+ histograms[new_histogram_name]['fieldtrial_names'] = []
+ histograms[new_histogram_name]['fieldtrial_names'].append(name)
+
+ if not 'fieldtrial_labels' in histograms[new_histogram_name]:
+ histograms[new_histogram_name]['fieldtrial_labels'] = []
+ histograms[new_histogram_name]['fieldtrial_labels'].append(
+ group_label)
+
+ except Error:
+ have_errors = True
+
+ if have_errors:
+ logging.error('Error parsing %s' % filename)
+ raise Error()
+
+ return histograms
+
+
+def ExtractNames(histograms):
+ return sorted(histograms.keys())
diff --git a/chromium/tools/metrics/histograms/find_unmapped_histograms.py b/chromium/tools/metrics/histograms/find_unmapped_histograms.py
new file mode 100644
index 00000000000..a72eac447ee
--- /dev/null
+++ b/chromium/tools/metrics/histograms/find_unmapped_histograms.py
@@ -0,0 +1,227 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Scans the Chromium source for histograms that are absent from histograms.xml.
+
+This is a heuristic scan, so a clean run of this script does not guarantee that
+all histograms in the Chromium source are properly mapped. Notably, field
+trials are entirely ignored by this script.
+
+"""
+
+import commands
+import extract_histograms
+import logging
+import optparse
+import os
+import re
+import sys
+
+
+ADJACENT_C_STRING_REGEX = re.compile(r"""
+ (" # Opening quotation mark
+ [^"]*) # Literal string contents
+ " # Closing quotation mark
+ \s* # Any number of spaces
+ " # Another opening quotation mark
+ """, re.VERBOSE)
+CONSTANT_REGEX = re.compile(r"""
+ (\w*::)? # Optional namespace
+ k[A-Z] # Match a constant identifier: 'k' followed by an uppercase letter
+ \w* # Match the rest of the constant identifier
+ $ # Make sure there's only the identifier, nothing else
+ """, re.VERBOSE)
+HISTOGRAM_REGEX = re.compile(r"""
+ UMA_HISTOGRAM # Match the shared prefix for standard UMA histogram macros
+ \w* # Match the rest of the macro name, e.g. '_ENUMERATION'
+ \( # Match the opening parenthesis for the macro
+ \s* # Match any whitespace -- especially, any newlines
+ ([^,]*) # Capture the first parameter to the macro
+ , # Match the comma that delineates the first parameter
+ """, re.VERBOSE)
+
+
+class DirectoryNotFoundException(Exception):
+ """Base class to distinguish locally defined exceptions from standard ones."""
+ def __init__(self, msg):
+ self.msg = msg
+
+ def __str__(self):
+ return self.msg
+
+
+def changeWorkingDirectory(target_directory):
+ """Changes the working directory to the given |target_directory|, which
+ defaults to the root of the Chromium checkout.
+
+ Returns:
+ None
+
+ Raises:
+ DirectoryNotFoundException if the target directory cannot be found.
+ """
+ working_directory = os.getcwd()
+ pos = working_directory.find(target_directory)
+ if pos < 0:
+ raise DirectoryNotFoundException('Could not find root directory "' +
+ target_directory + '". ' +
+ 'Please run this script within your ' +
+ 'Chromium checkout.')
+
+ os.chdir(working_directory[:pos + len(target_directory)])
+
+
+def collapseAdjacentCStrings(string):
+ """Collapses any adjacent C strings into a single string.
+
+ Useful to re-combine strings that were split across multiple lines to satisfy
+ the 80-col restriction.
+
+ Args:
+ string: The string to recombine, e.g. '"Foo"\n "bar"'
+
+ Returns:
+ The collapsed string, e.g. "Foobar" for an input of '"Foo"\n "bar"'
+ """
+ while True:
+ collapsed = ADJACENT_C_STRING_REGEX.sub(r'\1', string, count=1)
+ if collapsed == string:
+ return collapsed
+
+ string = collapsed
+
+
+def logNonLiteralHistogram(filename, histogram):
+ """Logs a statement warning about a non-literal histogram name found in the
+ Chromium source.
+
+ Filters out known acceptable exceptions.
+
+ Args:
+ filename: The filename for the file containing the histogram, e.g.
+ 'chrome/browser/memory_details.cc'
+ histogram: The expression that evaluates to the name of the histogram, e.g.
+ '"FakeHistogram" + variant'
+
+ Returns:
+ None
+ """
+ # Ignore histogram macros, which typically contain backslashes so that they
+ # can be formatted across lines.
+ if '\\' in histogram:
+ return
+
+ # Field trials are unique within a session, so are effectively constants.
+ if histogram.startswith('base::FieldTrial::MakeName'):
+ return
+
+ # Ignore histogram names that have been pulled out into C++ constants.
+ if CONSTANT_REGEX.match(histogram):
+ return
+
+ # TODO(isherman): This is still a little noisy... needs further filtering to
+ # reduce the noise.
+ logging.warning('%s contains non-literal histogram name <%s>', filename,
+ histogram)
+
+
+def readChromiumHistograms():
+ """Searches the Chromium source for all histogram names.
+
+ Also prints warnings for any invocations of the UMA_HISTOGRAM_* macros with
+ names that might vary during a single run of the app.
+
+ Returns:
+ A set cotaining any found literal histogram names.
+ """
+ logging.info('Scanning Chromium source for histograms...')
+
+ # Use git grep to find all invocations of the UMA_HISTOGRAM_* macros.
+ # Examples:
+ # 'path/to/foo.cc:420: UMA_HISTOGRAM_COUNTS_100("FooGroup.FooName",'
+ # 'path/to/bar.cc:632: UMA_HISTOGRAM_ENUMERATION('
+ locations = commands.getoutput('git gs UMA_HISTOGRAM').split('\n')
+ filenames = set([location.split(':')[0] for location in locations])
+
+ histograms = set()
+ for filename in filenames:
+ contents = ''
+ with open(filename, 'r') as f:
+ contents = f.read()
+
+ matches = set(HISTOGRAM_REGEX.findall(contents))
+ for histogram in matches:
+ histogram = collapseAdjacentCStrings(histogram)
+
+ # Must begin and end with a quotation mark.
+ if histogram[0] != '"' or histogram[-1] != '"':
+ logNonLiteralHistogram(filename, histogram)
+ continue
+
+ # Must not include any quotation marks other than at the beginning or end.
+ histogram_stripped = histogram.strip('"')
+ if '"' in histogram_stripped:
+ logNonLiteralHistogram(filename, histogram)
+ continue
+
+ histograms.add(histogram_stripped)
+
+ return histograms
+
+
+def readXmlHistograms(histograms_file_location):
+ """Parses all histogram names from histograms.xml.
+
+ Returns:
+ A set cotaining the parsed histogram names.
+ """
+ logging.info('Reading histograms from %s...' % histograms_file_location)
+ histograms = extract_histograms.ExtractHistograms(histograms_file_location)
+ return set(extract_histograms.ExtractNames(histograms))
+
+
+def main():
+ # Parse command line options
+ parser = optparse.OptionParser()
+ parser.add_option(
+ '--root-directory', dest='root_directory', default='src',
+ help='scan within DIRECTORY for histograms [optional, defaults to "src/"]',
+ metavar='DIRECTORY')
+ parser.add_option(
+ '--histograms-file', dest='histograms_file_location',
+ default='tools/metrics/histograms/histograms.xml',
+ help='read histogram definitions from FILE (relative to --root-directory) '
+ '[optional, defaults to "tools/histograms/histograms.xml"]',
+ metavar='FILE')
+
+ (options, args) = parser.parse_args()
+ if args:
+ parser.print_help()
+ sys.exit(1)
+
+ logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
+
+ try:
+ changeWorkingDirectory(options.root_directory)
+ except DirectoryNotFoundException as e:
+ logging.error(e)
+ sys.exit(1)
+ chromium_histograms = readChromiumHistograms()
+ xml_histograms = readXmlHistograms(options.histograms_file_location)
+
+ unmapped_histograms = sorted(chromium_histograms - xml_histograms)
+ if len(unmapped_histograms):
+ logging.info('')
+ logging.info('')
+ logging.info('Histograms in Chromium but not in %s:' %
+ options.histograms_file_location)
+ logging.info('-------------------------------------------------')
+ for histogram in unmapped_histograms:
+ logging.info(' %s', histogram)
+ else:
+ logging.info('Success! No unmapped histograms found.')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/metrics/histograms/histograms.xml b/chromium/tools/metrics/histograms/histograms.xml
new file mode 100644
index 00000000000..bdb1c4f4214
--- /dev/null
+++ b/chromium/tools/metrics/histograms/histograms.xml
@@ -0,0 +1,24865 @@
+<!--
+Copyright 2013 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<!--
+This file is used to generate a comprehensive list of Chrome histograms along
+with a detailed description for each histogram.
+
+Please pretty-print and validate your edits by running the pretty_print.py
+and validate_format.py scripts in the same directory as this file before
+uploading your change for review.
+
+Take a moment to page through the contents of this file. You will find
+three sections:
+
+* The histograms section describes base histograms, giving their name,
+ and optionally their units or enum type, a short one-line summary,
+ and optionally a more detailed description.
+* The enums section defines and documents the enumerated types referred to by
+ the histograms.
+* The fieldtrials section defines active field trials and their groups, along
+ with their descriptions.
+
+Each field trial lists the histograms that it affects. The complete list of
+histograms is computed by appending the field trial group names to each of
+the affected histograms. For example, define the following:
+
+ <histogram name="FileLoadLatency"/>
+
+ <fieldtrial name="SuperHttpExperiment">
+ <group name="SuperHttpEnabled"/>
+ <group name="SuperHttpDisabled"/>
+ <affected-histogram name="FileLoadLatency"/>
+ </fieldtrial>
+
+The complete list of histograms will be:
+
+ FileLoadLatency
+ FileLoadLatency_SuperHttpEnabled
+ FileLoadLatency_SuperHttpDisabled
+
+Field trial definitions can currently be used in any situation where multiple
+suffixes need to be appended to a histogram name; they do not have to
+correspond to actual field trials in the Chrome source code.
+
+TODO(mlloyd): Refactor the XML so that field trials can be distinguished from
+other types of suffix sets.
+-->
+
+<histogram-configuration>
+
+<!-- Histogram definitions -->
+
+<histograms>
+
+<histogram name="Accessibility.CrosAlwaysShowA11yMenu" enum="BooleanEnabled">
+ <summary>
+ Whether the Chrome OS Accessibility Menu is set to be shown regardless of
+ the state of a11y features.(checked once 45 secs after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.CrosHighContrast" enum="BooleanEnabled">
+ <summary>
+ Whether the Chrome OS High Constrast mode feature is on (checked once 45
+ secs after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.CrosLargeCursor" enum="BooleanEnabled">
+ <summary>
+ Whether the Chrome OS Large Cursor feature is on (checked once 45 secs after
+ startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.CrosScreenMagnifier" enum="BooleanEnabled">
+ <summary>
+ Whether the Chrome OS Screen Magnifier feature is on (checked once 45 secs
+ after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.CrosSpokenFeedback" enum="BooleanEnabled">
+ <summary>
+ Whether the Chrome OS Spoken Feedback feature is on (checked once 45 secs
+ after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.CrosVirtualKeyboard" enum="BooleanEnabled">
+ <summary>
+ Whether the Chrome OS Virtual Keyboard feature is on (checked once 45 secs
+ after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.InvertedColors" enum="BooleanEnabled">
+ <summary>
+ Whether Windows system settings show that high-contrast mode is enabled and
+ the user has selected a light-on-dark color scheme (checked once 45 secs
+ after startup). This causes Chrome to prompt the user with a bubble to
+ optionally install a High Contrast extension and theme.
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.ManuallyEnabled" enum="BooleanEnabled">
+ <summary>
+ Whether Chrome has enabled accessibility support because the user passed the
+ --force-renderer-accessibility flag on the command-line (checked once 45
+ secs after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.State" enum="BooleanEnabled">
+ <summary>
+ Whether Chrome has enabled accessibility support because it detects
+ supported assistive technology running, or due to being manually enabled via
+ a command-line flag (checked once 45 secs after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.WinAudioDescription" enum="BooleanEnabled">
+ <summary>
+ Whether Windows system settings show that audio descriptions are enabled
+ (checked once 45 secs after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.WinJAWS" enum="BooleanEnabled">
+ <summary>
+ Whether the third-party JAWS screen reader is running (checked once 45 secs
+ after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.WinNVDA" enum="BooleanEnabled">
+ <summary>
+ Whether the third-party NVDA screen reader is running (checked once 45 secs
+ after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.WinSAToGo" enum="BooleanEnabled">
+ <summary>
+ Whether the third-party System Access To Go screen reader is running
+ (checked once 45 secs after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.WinScreenReader" enum="BooleanEnabled">
+ <summary>
+ Whether Windows system settings show that a screen reader is running
+ (checked once 45 secs after startup). Note that this does not necessarily
+ mean that Chrome has detected a supported screen reader and has enabled its
+ accessibility mode.
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.WinStickyKeys" enum="BooleanEnabled">
+ <summary>
+ Whether Windows system settings show that Sticky Keys are enabled.
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.WinZoomText" enum="BooleanEnabled">
+ <summary>
+ Whether the third-party ZoomText screen magnifier is running.
+ </summary>
+</histogram>
+
+<histogram name="Apps.AppLaunch" enum="AppLaunch">
+ <summary>
+ The number of times v2 packaged apps are launched grouped by
+ extension_misc::AppLaunchBuckets. See also Extensions.AppLaunch.
+ </summary>
+</histogram>
+
+<histogram name="Apps.AppLauncherPromo" enum="AppLauncherPromo">
+ <summary>Interactions with the App Launcher promo dialog.</summary>
+</histogram>
+
+<histogram name="Apps.AppListSearchCommenced" units="searches">
+ <summary>
+ The number of searches that are started in the app list. This is gathered
+ each time the app list search box transitions from empty to non-empty.
+ </summary>
+</histogram>
+
+<histogram name="Apps.AppListSearchResultOpenType" enum="AppListSearchResult">
+ <summary>
+ The type of app list search result that was opened by the user. This is
+ gathered per click of a search result.
+ </summary>
+</histogram>
+
+<histogram name="Ash.ActiveTouchPoints">
+ <summary>
+ Number of active touch-points when a new touch-point is added.
+ </summary>
+</histogram>
+
+<histogram name="Ash.GestureCreated" enum="UIEventType">
+ <summary>
+ The gesture-events recognized and dispatched by the browser gesture
+ recognizer.
+ </summary>
+</histogram>
+
+<histogram name="Ash.GestureTarget" enum="GestureActionType">
+ <summary>
+ The gesture-events recognized and dispatched by the browser gesture
+ recognizer for various UI components.
+ </summary>
+</histogram>
+
+<histogram name="Ash.TouchDuration" units="milliseconds">
+ <summary>The duration of a touch-sequence.</summary>
+</histogram>
+
+<histogram name="Ash.TouchMoveInterval" units="milliseconds">
+ <summary>The interval between touch-move events.</summary>
+</histogram>
+
+<histogram name="Ash.TouchMoveSteps" units="pixels">
+ <summary>The distance between touch-move events.</summary>
+</histogram>
+
+<histogram name="Ash.TouchPositionX" units="pixels">
+ <summary>The position of the touch-events along the X axis.</summary>
+</histogram>
+
+<histogram name="Ash.TouchPositionY" units="pixels">
+ <summary>The position of the touch-events along the Y axis.</summary>
+</histogram>
+
+<histogram name="Ash.TouchRadius" units="pixels">
+ <summary>The radius of a touch event.</summary>
+</histogram>
+
+<histogram name="Ash.TouchStartAfterEnd" units="milliseconds">
+ <summary>
+ The interval between the end of a touch-sequence and the start of the next
+ touch-sequence.
+ </summary>
+</histogram>
+
+<histogram name="Ash.TouchStartBurst">
+ <summary>
+ The number of rapid touch-starts that happened within a short interval.
+ Logged once for each such burst group.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.AttemptCountFail">
+ <summary>
+ Count of DnsAttempts before DnsTransaction completes with failure.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.AttemptCountSuccess">
+ <summary>
+ Count of DnsAttempts before DnsTransaction completes successfully.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ConfigChange" enum="BooleanSuccess">
+ <summary>
+ Whether DnsConfigService::OnConfigChange actually corresponded to a change
+ in DnsConfig.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ConfigNotifyInterval" units="milliseconds">
+ <summary>
+ Duration of time between calls to DnsConfigService::InvalidateConfig.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ConfigParseDuration" units="milliseconds">
+ <summary>Duration of time spent parsing DnsConfig.</summary>
+</histogram>
+
+<histogram name="AsyncDNS.ConfigParsePosix" enum="AsyncDNSConfigParsePosix">
+ <summary>
+ Counts of results of parsing DnsConfig in DnsConfigServicePosix.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ConfigParseResult" enum="BooleanSuccess">
+ <summary>Whether DnsConfig was parsed successfully.</summary>
+</histogram>
+
+<histogram name="AsyncDNS.ConfigParseWin" enum="AsyncDNSConfigParseWin">
+ <summary>
+ Counts of results of parsing DnsConfig in DnsConfigServiceWin.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.DNSChangerDetected" enum="BooleanSuccess">
+ <summary>
+ Whether the first valid DnsConfig included a rogue nameserver.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.DnsClientDisabledReason" enum="NetErrorCodes">
+ <summary>
+ Counts of specific error codes returned by DnsTask if a subsequent ProcTask
+ succeeded, at the end of a streak of failures after which the DnsClient was
+ disabled.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.DnsClientEnabled" enum="BooleanSuccess">
+ <summary>
+ TRUE counts the events when a valid DnsConfig is received and used to enable
+ DnsClient, while FALSE counts the events when DnsClient is disabled after a
+ series of successful fallbacks from DnsTask to ProcTask.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.FallbackFail" units="milliseconds">
+ <summary>
+ Duration of time spent by ProcTask in failing fallback resolutions.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.FallbackSuccess" units="milliseconds">
+ <summary>
+ Duration of time spent by ProcTask in successful fallback resolutions.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.HaveDnsConfig" enum="BooleanSuccess">
+ <summary>
+ Whether there was a valid DNS configuration at the start of a job which
+ eventually completed successfully.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.HostParseResult" enum="BooleanSuccess">
+ <summary>Whether DnsHosts were parsed successfully.</summary>
+</histogram>
+
+<histogram name="AsyncDNS.HostsChange" enum="BooleanSuccess">
+ <summary>
+ Whether DnsConfigService::OnHostsChange actually corresponded to a change in
+ DnsHosts.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.HostsNotifyInterval" units="milliseconds">
+ <summary>
+ Duration of time between calls to DnsConfigService::InvalidateHosts.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.HostsParseDuration" units="milliseconds">
+ <summary>Duration of time spent parsing DnsHosts.</summary>
+</histogram>
+
+<histogram name="AsyncDNS.HostsParseWin" enum="AsyncDNSHostsParseWin">
+ <summary>
+ Counts of results of parsing DnsHosts in DnsConfigServiceWin.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.HostsSize" units="bytes">
+ <summary>
+ The size of the HOSTS file observed before each attempt to parse it.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTime" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (using DnsClient).
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTime_HIGHEST" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (using DnsClient). Includes only Jobs which had
+ priority HIGHEST when started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTime_IDLE" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (using DnsClient). Includes only Jobs which had
+ priority IDLE when started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTime_LOW" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (using DnsClient). Includes only Jobs which had
+ priority LOW when started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTime_LOWEST" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (using DnsClient). Includes only Jobs which had
+ priority LOWEST when started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTime_MEDIUM" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (using DnsClient). Includes only Jobs which had
+ priority MEDIUM when started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTimeAfterChange" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (using DnsClient).
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTimeAfterChange_HIGHEST" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (using DnsClient). Includes only Jobs which had priority HIGHEST
+ when started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTimeAfterChange_IDLE" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (using DnsClient). Includes only Jobs which had priority IDLE when
+ started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTimeAfterChange_LOW" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (using DnsClient). Includes only Jobs which had priority LOW when
+ started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTimeAfterChange_LOWEST" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (using DnsClient). Includes only Jobs which had priority LOWEST when
+ started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.JobQueueTimeAfterChange_MEDIUM" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (using DnsClient). Includes only Jobs which had priority MEDIUM when
+ started.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ParseToAddressList" enum="AsyncDNSParseResult">
+ <summary>
+ Counts of results of parsing addresses out of DNS responses in successful
+ DnsTransactions.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ResolveError" enum="NetErrorCodes">
+ <summary>
+ Counts of specific error codes returned by DnsTask if a subsequent ProcTask
+ succeeded.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ResolveFail" units="milliseconds">
+ <summary>
+ Duration of time taken by DnsTask in resolutions that failed. Excludes time
+ spent in the subsequent fallback.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ResolveStatus" enum="AsyncDNSResolveStatus">
+ <summary>
+ Counts of the overall results of using asynchronous DNS in HostResolverImpl.
+ This only includes jobs started with valid DNS configuration and excludes
+ synchronous resolutions (as IP literals, from cache, and from HOSTS).
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ResolveSuccess" units="milliseconds">
+ <summary>
+ Duration of time taken by DnsTask in resolutions that succeeded.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ResolveSuccess_FAMILY_IPV4" units="milliseconds">
+ <summary>
+ Same as AsyncDNS.ResolveSuccess, but limited to pure IPv4 lookups.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ResolveSuccess_FAMILY_IPV6" units="milliseconds">
+ <summary>
+ Same as AsyncDNS.ResolveSuccess, but limited to pure IPv6 lookups.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ResolveSuccess_FAMILY_UNSPEC" units="milliseconds">
+ <summary>
+ Same as AsyncDNS.ResolveSuccess, but limited to IPv4/IPv6 lookups.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ServerCount">
+ <summary>
+ Count of servers in DnsConfig. Recorded on every new DnsSession, which is
+ created on DNS change.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ServerFailureIndex">
+ <summary>
+ Index in DnsConfig of the failing server, recorded at the time of failure.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ServerFailuresAfterNetworkChange">
+ <summary>
+ Count of server failures after network change before first success in the
+ DnsSession. Recorded at the time of first success.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ServerFailuresAfterSuccess">
+ <summary>
+ Count of server failures after success until the end of the session. Server
+ has reported success at some point during the session. Recorded at the end
+ of the DnsSession.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ServerFailuresBeforeSuccess">
+ <summary>
+ Count of server failures before success. This is NOT the first success in
+ the DnsSession. Recorded at the time of success.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ServerFailuresWithoutSuccess">
+ <summary>
+ Count of server failures without success until the end of the session.
+ Server has never reported success during the DnsSession. Recorded at the end
+ of the DnsSession.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.ServerIsGood" units="BooleanSuccess">
+ <summary>
+ The current server is &quot;good&quot; and does not have to be skipped.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.SortFailure" units="milliseconds">
+ <summary>
+ Duration of time taken in failing calls to AddressSorter in dual-stack
+ resolutions using DnsTask.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.SortSuccess" units="milliseconds">
+ <summary>
+ Duration of time taken in successful calls to AddressSorter in dual-stack
+ resolutions using DnsTask.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.SuffixSearchDone">
+ <summary>
+ The number of names from the search name list consumed during a successful
+ transaction (QTYPE A only).
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.SuffixSearchRemain">
+ <summary>
+ The number of names left on the search name list at the end of a successful
+ transaction (QTYPE A only).
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.SuffixSearchStart">
+ <summary>
+ The number of names on the search name list at the start of a transaction
+ (QTYPE A only).
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TCPAttemptFail" units="milliseconds">
+ <summary>
+ Duration of time taken by DnsTCPAttempt in failed attempts. Excludes
+ timeouts.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TCPAttemptSuccess" units="milliseconds">
+ <summary>
+ Duration of time taken by DnsTCPAttempt in successful attempts.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TimeoutErrorHistogram" units="milliseconds">
+ <summary>
+ Difference between RTT and timeout calculated using Histogram algorithm.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TimeoutErrorHistogramUnder" units="milliseconds">
+ <summary>
+ Difference between timeout calculated using Histogram algorithm and RTT.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TimeoutErrorJacobson" units="milliseconds">
+ <summary>
+ Difference between RTT and timeout calculated using Jacobson algorithm.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TimeoutErrorJacobsonUnder" units="milliseconds">
+ <summary>
+ Difference between timeout calculated using Jacobson algorithm and RTT.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TimeoutSpentHistogram" units="milliseconds">
+ <summary>
+ Duration of time that would be spent waiting for lost request using
+ Histogram algorithm.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TimeoutSpentJacobson" units="milliseconds">
+ <summary>
+ Duration of time that would be spent waiting for lost request using Jacobson
+ algorithm.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TotalTime" units="milliseconds">
+ <summary>
+ Duration of time since a HostResolverImpl::Resolve request to the time a
+ result is posted. Excludes canceled, evicted, and aborted requests. Includes
+ cache hits (recorded as 0). Excludes speculative requests.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TotalTime_speculative" units="milliseconds">
+ <summary>
+ Duration of time since a HostResolverImpl::Resolve request to the time a
+ result is posted. Excludes canceled, evicted, and aborted requests. Includes
+ cache hits (recorded as 0). Speculative requests only.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TransactionFailure" units="milliseconds">
+ <summary>
+ Duration of time taken in failing DnsTransactions. This includes server
+ failures, timeouts and NXDOMAIN results.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TransactionSuccess" units="milliseconds">
+ <summary>
+ Duration of time taken in successful DnsTransactions. This includes all
+ NOERROR answers, even if they indicate the name has no addresses or they
+ cannot be parsed.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TransactionSuccess_A" units="milliseconds">
+ <summary>
+ Same as AsyncDNS.TransactionSuccess but limited to A query type.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TransactionSuccess_AAAA" units="milliseconds">
+ <summary>
+ Same as AsyncDNS.TransactionSuccess but limited to AAAA query type.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.TTL" units="milliseconds">
+ <summary>
+ TTL of the resolved addresses, as in the response received from the server.
+ For results served from local cache, the TTL is from the original response.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.UDPAttemptFail" units="milliseconds">
+ <summary>
+ Duration of time taken by DnsUDPAttempt in failed attempts. Excludes
+ timeouts.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.UDPAttemptSuccess" units="milliseconds">
+ <summary>
+ Duration of time taken by DnsUDPAttempt in successful attempts. Includes
+ responses arriving after timeout, if multiple attempts are allowed.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.UnchangedConfigInterval" units="milliseconds">
+ <summary>
+ Duration of time since the last empty config result to the time a non-change
+ OnConfigChange is received.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.UnchangedHostsInterval" units="milliseconds">
+ <summary>
+ Duration of time since the last empty config result to the time a non-change
+ OnHostsChange is received.
+ </summary>
+</histogram>
+
+<histogram name="AsyncDNS.WatchStatus" enum="AsyncDNSWatchStatus">
+ <summary>
+ The result of DnsConfigService watch. Counts STARTED on every initialization
+ and FAILED_* on any failure.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.Bubble" enum="AutocheckoutBubble">
+ <summary>
+ Measures the frequency of user interactions with the Autocheckout bubble,
+ which prompts users to invoke Autocheckout on supported websites.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.BuyFlow" enum="AutocheckoutBuyFlow">
+ <summary>
+ Measures the frequency of final states reached in Autocheckout buy flow.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.DismissalState"
+ enum="AutofillDialogDismissalState">
+ <summary>The state of the Autocheckout dialog when it was dismissed.</summary>
+</histogram>
+
+<histogram name="Autocheckout.FlowDuration" units="ms">
+ <summary>
+ Measures the time elapsed between when the user submitted the Autocheckout
+ dialog and when the Autocheckout flow, or filling process, concluded.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.FlowDuration.Failed" units="ms">
+ <summary>
+ Measures the time elapsed between when the user submitted the Autocheckout
+ dialog and when the Autocheckout flow concluded, in cases where the flow
+ failed.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.FlowDuration.Succeeded" units="ms">
+ <summary>
+ Measures the time elapsed between when the user submitted the Autocheckout
+ dialog and when the Autocheckout flow concluded, in cases where the flow
+ succeeded.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.InitialUserState"
+ enum="AutofillDialogInitialUserState">
+ <summary>
+ The initial state of a user that's interacting with a freshly shown
+ Autocheckout dialog.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.PopupInDialog" enum="AutofillDialogPopupEvent">
+ <summary>
+ User interactions with the Autofill popup shown while filling an
+ Autocheckout dialog.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.Security" enum="AutofillDialogSecurity">
+ <summary>
+ Measures the frequency of security warnings and errors in the Autocheckout
+ dialog.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.UiDuration" units="ms">
+ <summary>
+ Measures the duration for which an Autocheckout dialog was shown.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.UiDuration.Cancel" units="ms">
+ <summary>
+ Measures the duration for which an Autocheckout dialog was shown, in cases
+ where the user ended up canceling out of the dialog.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.UiDuration.Submit" units="ms">
+ <summary>
+ Measures the duration for which an Autocheckout dialog was shown, in cases
+ where the user ended up accepting the dialog.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.UiEvents" enum="AutofillDialogUiEvents">
+ <summary>
+ Measures how users are interacting with the Autocheckout dialog UI.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.UiLatencyToShow" units="ms">
+ <summary>
+ Measures the duration of time it takes for the Autocheckout UI to be
+ actionable by the user after it is shown.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.WalletErrors" enum="WalletErrors">
+ <summary>
+ Measures the frequency of errors in communicating with the Google Online
+ Wallet server.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.WalletRequiredActions"
+ enum="WalletRequiredActions">
+ <summary>
+ Measures the frequency of required user actions returned by the Google
+ Online Wallet server.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.WhitelistDownloadDuration" units="ms">
+ <summary>
+ Measures time taken to download the Autocheckout whitelist file.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.WhitelistDownloadDuration.Failed" units="ms">
+ <summary>
+ Measures time taken to download the Autocheckout whitelist file in case the
+ download was failed.
+ </summary>
+</histogram>
+
+<histogram name="Autocheckout.WhitelistDownloadDuration.Succeeded" units="ms">
+ <summary>
+ Measures time taken to download the Autocheckout whitelist file in case the
+ download was succeeded.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.AddressSuggestionsCount">
+ <summary>
+ The number of address suggestions shown in the Autofill popup.
+ </summary>
+</histogram>
+
+<histogram name="AutoFill.CCInfoBarAccepted">
+ <obsolete>
+ Deprecated as of 3/2011, replaced by Autofill.CreditCardInfoBar.
+ </obsolete>
+ <summary>The Autofill credit card info bar was accepted.</summary>
+</histogram>
+
+<histogram name="AutoFill.CCInfoBarDenied">
+ <obsolete>
+ Deprecated as of 3/2011, replaced by Autofill.CreditCardInfoBar.
+ </obsolete>
+ <summary>The Autofill credit card info bar was denied.</summary>
+</histogram>
+
+<histogram name="Autofill.CreditCardInfoBar" enum="AutofillCreditCardInfoBar">
+ <summary>
+ The relative frequency with which users accept, deny, or ignore the Autofill
+ credit card info bar prompt.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.DeveloperEngagement"
+ enum="AutofillDeveloperEngagement">
+ <summary>
+ Measures the adoption of the HTML autocomplete type hint specification (see
+ http://is.gd/whatwg_autocomplete for more details). For each fillable form
+ detected, logs whether that form includes author-specified type hints.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.FillDuration.FromInteraction.WithAutofill">
+ <summary>
+ Time elapsed between the user's first interaction with a form and the form's
+ submission, for an autofilled form.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.FillDuration.FromInteraction.WithoutAutofill">
+ <summary>
+ Time elapsed between the user's first interaction with a form and the form's
+ submission, for a non-autofilled form.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.FillDuration.FromLoad.WithAutofill">
+ <summary>
+ Time elapsed between form load and form submission, for an autofilled form.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.FillDuration.FromLoad.WithoutAutofill">
+ <summary>
+ Time elapsed between form load and form submission, for a non-autofilled
+ form.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.IsEnabled.PageLoad" enum="BooleanEnabled">
+ <summary>
+ Tracks whether Autofill is enabled on page load for a page containing forms.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.IsEnabled.Startup" enum="BooleanEnabled">
+ <summary>Tracks whether Autofill is enabled when Chrome launches.</summary>
+</histogram>
+
+<histogram name="AutoFill.ProfileCount">
+ <obsolete>
+ Deprecated as of 3/2011, replaced by Autofill.StoredProfileCount.
+ </obsolete>
+ <summary>The number of Autofill address profiles a user has.</summary>
+</histogram>
+
+<histogram name="AutoFill.Quality" enum="AutofillQuality">
+ <obsolete>
+ Deprecated as of 3/2011, replaced by Autofill.Quality.
+ </obsolete>
+ <summary>The quality of the AutoFill implementation.</summary>
+</histogram>
+
+<histogram name="Autofill.Quality" enum="AutofillQuality">
+ <summary>The quality of the Autofill implementation.</summary>
+</histogram>
+
+<histogram name="Autofill.Quality.HeuristicType" enum="AutofillTypeQuality">
+ <summary>The quality of Autofill's heuristic field type detection.</summary>
+</histogram>
+
+<histogram name="Autofill.Quality.HeuristicType.ByFieldType"
+ enum="AutofillTypeQualityByFieldType">
+ <summary>
+ The quality of Autofill's heuristic field type detection, broken down by the
+ specific field type. Fields with multiple possible types (based on the
+ stored Autofill data) are logged as having ambiguous type.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.Quality.PredictedType" enum="AutofillTypeQuality">
+ <summary>The overall quality of the Autofill field type predictions.</summary>
+</histogram>
+
+<histogram name="Autofill.Quality.PredictedType.ByFieldType"
+ enum="AutofillTypeQualityByFieldType">
+ <summary>
+ The overall quality of the Autofill field type predictions, broken down by
+ the specific field type. Fields with multiple possible types (based on the
+ stored Autofill data) are logged as having ambiguous type.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.Quality.ServerType" enum="AutofillTypeQuality">
+ <summary>The quality of the Autofill server's field type detection.</summary>
+</histogram>
+
+<histogram name="Autofill.Quality.ServerType.ByFieldType"
+ enum="AutofillTypeQualityByFieldType">
+ <summary>
+ The quality of the Autofill server's field type detection, broken down by
+ the specific field type. Fields with multiple possible types (based on the
+ stored Autofill data) are logged as having ambiguous type.
+ </summary>
+</histogram>
+
+<histogram name="AutoFill.RequestErrorimcklfaapmppdhilegjoahjbahdgfhcn">
+ <summary>TBD.</summary>
+</histogram>
+
+<histogram name="AutoFill.RequestSuccessimcklfaapmppdhilegjoahjbahdgfhcn">
+ <summary>TBD.</summary>
+</histogram>
+
+<histogram name="Autofill.ServerExperimentId" enum="AutofillExperimentId">
+ <obsolete>
+ Deprecated as of 6/2011, replaced by Autofill.ServerExperimentId.Query.
+ </obsolete>
+ <summary>
+ The experiment ID received in response to an Autofill server query.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.ServerExperimentId.Query" enum="AutofillExperimentId">
+ <summary>
+ The experiment ID received in response to an Autofill server query.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.ServerExperimentId.Upload"
+ enum="AutofillExperimentId">
+ <summary>
+ The experiment ID received at the time of an Autofill upload.
+ </summary>
+</histogram>
+
+<histogram name="AutoFill.ServerQueryResponse" enum="AutofillQueryResult">
+ <obsolete>
+ Deprecated as of 3/2011, replaced by Autofill.ServerQueryResponse.
+ </obsolete>
+ <summary>The usefulness of AutoFill server information.</summary>
+</histogram>
+
+<histogram name="Autofill.ServerQueryResponse" enum="AutofillQueryResult">
+ <summary>The usefulness of Autofill server information.</summary>
+</histogram>
+
+<histogram name="Autofill.StoredProfileCount">
+ <summary>
+ The number of Autofill addresses a user has stored, measured at launch time.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.UserHappiness" enum="AutofillUserHappiness">
+ <summary>
+ Measures the frequency of various events in the Autofill user interaction
+ flow. By comparing frequencies, we can compute several interesting
+ &quot;user happiness&quot; metrics.
+ </summary>
+</histogram>
+
+<histogram name="Bluetooth.ConnectedDeviceCount" units="devices">
+ <summary>
+ Counts the number of simulataneously connected Bluetooth devices. Used to
+ direct testing efforts, and by our UI team to determine appropriate UI
+ sizes.
+ </summary>
+</histogram>
+
+<histogram name="Bluetooth.PairingMethod" enum="BluetoothPairingMethod">
+ <summary>
+ Records the method used to pair each Bluetooth Device. Used to direct our
+ testing efforts.
+ </summary>
+</histogram>
+
+<histogram name="Bluetooth.PairingResult" enum="BluetoothPairingResult">
+ <summary>
+ Records the result of pairing each Bluetooth Device. Used to understand
+ whether we are having significant problems with Bluetooth pairing and seeing
+ errors more commonly than we should.
+ </summary>
+</histogram>
+
+<histogram name="Canvas.ContextType" enum="CanvasContextType">
+ <summary>
+ Records the context type names used to create canvas rendering contexts.
+ </summary>
+</histogram>
+
+<histogram name="Cellular.ActivationFailure">
+ <summary>
+ The count of cellular device activation failures (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="Cellular.ActivationTry">
+ <summary>The count of cellular device activation tries (Chrome OS).</summary>
+</histogram>
+
+<histogram name="Cellular.ConnectionFailed">
+ <summary>
+ The count of cellular reconnect failures during activation (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="Cellular.ConnectionRetry">
+ <summary>
+ The count of cellular device reconnect tries during activation (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="Cellular.MobileSetupFailed">
+ <summary>
+ The count of successful cellular plan established (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="Cellular.MobileSetupStart">
+ <summary>
+ The count of initiated cellular device setup starts (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="Cellular.MobileSetupSucceeded">
+ <summary>The count of failed cellular plan setup tries (Chrome OS).</summary>
+</histogram>
+
+<histogram name="Cellular.PaymentFailed">
+ <summary>The count of failed cellular plan purchases (Chrome OS).</summary>
+</histogram>
+
+<histogram name="Cellular.PaymentReceived">
+ <summary>
+ The count of successfully completed cellular plan purchases (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="CertificateType">
+ <obsolete>
+ Deprecated as of 8/2013. This histogram only considered the leaf certificate
+ expiry date as a proxy for whether a certificate was in-scope for the BRs,
+ but did not consider the issuance date. As some CAs have issued long-lived
+ certs prior to the BRs, this disproportionately reported those certs as
+ being subject to the BRs, but non-compliant, when in reality they're not
+ subject.
+ </obsolete>
+ <summary>
+ Information about the certificate algorithms and sizes in use on the web, to
+ examine compliance with the CA/Browser Forum requirements and security best
+ practice.
+ </summary>
+</histogram>
+
+<histogram name="CertificateType2">
+ <summary>
+ Information about the certificate algorithms and sizes in use on the web, to
+ examine compliance with the CA/Browser Forum requirements and security best
+ practice. This histogram considers the notBefore as the issuance date, for
+ purposes of what requirements apply.
+ </summary>
+</histogram>
+
+<histogram name="Chrome.SearchSelectExempt" enum="SearchEngine">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ The default search engine selected by a user not in the search engine dialog
+ experiment.
+ </summary>
+</histogram>
+
+<histogram name="Chrome.SearchSelectExperiment" enum="SearchEngine">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ The default search engine selected by a user in the search engine dialog
+ experiment.
+ </summary>
+</histogram>
+
+<histogram name="Chrome.SearchSelectExperimentSlot1" enum="SearchEngine">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ The default search engine selected by a user in slot 1 of a randomized
+ search engine dialog.
+ </summary>
+</histogram>
+
+<histogram name="Chrome.SearchSelectExperimentSlot2" enum="SearchEngine">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ The default search engine selected by a user in slot 2 of a randomized
+ search engine dialog.
+ </summary>
+</histogram>
+
+<histogram name="Chrome.SearchSelectExperimentSlot3" enum="SearchEngine">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ The default search engine selected by a user in slot 3 of a randomized
+ search engine dialog.
+ </summary>
+</histogram>
+
+<histogram name="Chrome.SearchSelectExperimentSlot4" enum="SearchEngine">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ The default search engine selected by a user in slot 4 of a randomized
+ search engine dialog.
+ </summary>
+</histogram>
+
+<histogram name="clickjacking.discard_download" units="ms">
+ <summary>
+ The length of time between a dangerous download appearing on the downloads
+ shelf, and the &quot;Discard&quot; button being clicked.
+ </summary>
+</histogram>
+
+<histogram name="clickjacking.launch_url" units="ms">
+ <summary>
+ The length of time between the external protocol dialog being shown and the
+ &quot;Launch Application&quot; button being clicked.
+ </summary>
+</histogram>
+
+<histogram name="clickjacking.open_download" units="ms">
+ <summary>
+ The length of time between a download appearing on the download shelf, and
+ the user opening it by clicking the item or pressing return.
+ </summary>
+</histogram>
+
+<histogram name="clickjacking.report_and_discard_download" units="ms">
+ <summary>
+ Time between &quot;Report and Discard&quot; button being shown and it being
+ clicked.
+ </summary>
+</histogram>
+
+<histogram name="clickjacking.save_download" units="ms">
+ <summary>
+ The length of time between a dangerous download appearing on the download
+ shelf, and the &quot;Keep&quot; button being clicked.
+ </summary>
+</histogram>
+
+<histogram name="Clipboard.IncognitoUseCase" enum="ClipboardAction">
+ <obsolete>
+ Deprecated as of 4/2013, experiment confirmed correctness of our patch.
+ </obsolete>
+ <summary>
+ Counts how often the user writes or reads from the clipboard and whether the
+ write was from an incognito window or not.
+ </summary>
+</histogram>
+
+<histogram name="Cookie.ParsedCookieStatus" enum="ParsedCookieStatus">
+ <summary>
+ When parsing a cookie, indicates if control characters were present in any
+ of the cookie values and if any of the cookie values were invalid.
+ Specifically, checks that all of the parsed values are valid according to
+ the valid token definition in Section 2.2 of RFC2616 which specifies a token
+ must have no separators (i.e. no characters from the following string,
+ ignoring the starting and ending single quote: '()&lt;&gt;@,;:\&quot;/[]?={}
+ \t') and no control characters.
+ </summary>
+</histogram>
+
+<histogram name="Cookie.ReinstatedCookies" units="seconds">
+ <summary>
+ The duration in seconds between a cookie getting evicted (due to the number
+ of cookies exceeding a domain limit), and subsequently reinstated.
+ </summary>
+</histogram>
+
+<histogram name="Cookie.SetAttributePairCharsValidity" enum="BooleanValid">
+ <summary>
+ Indicates whether a cookie attribute pair was set with both a valid key and
+ a valid attribute value or not. For the key, this implies that it was a
+ valid token as defined in Section 2.2 of RFC2616 which specifies a token
+ must have no separators (i.e. no characters from the following string,
+ ignoring the starting and ending single quote: '()&lt;&gt;@,;:\&quot;/[]?={}
+ \t') and no control characters. For the value, this implies that it
+ contained no control characters and no semicolon.
+ </summary>
+</histogram>
+
+<histogram name="Cookie.SetNameValidity" enum="BooleanValid">
+ <summary>
+ Indicates whether a cookie name was set with a valid token. A valid token is
+ defined in Section 2.2 of RFC2616 which specifies a token must have no
+ separators (i.e. no characters from the following string, ignoring the
+ starting and ending single quote: '()&lt;&gt;@,;:\&quot;/[]?={} \t') and no
+ control characters.
+ </summary>
+</histogram>
+
+<histogram name="Cookie.SetValueCookieValueValidity" enum="BooleanValid">
+ <summary>
+ Indicates whether a cookie value was valid or invalid when there was an
+ attempt to set it, where a valid value is defined in RFC 6265 as ASCII
+ characters excluding controls, whitspace, comma, semicolon, and backslash.
+ </summary>
+</histogram>
+
+<histogram name="Cros.ClickOnShelf" enum="CrosShelfClickTarget">
+ <summary>Chrome OS shelf clicks.</summary>
+</histogram>
+
+<histogram name="CrosDisks.ArchiveType" enum="CrosDisksArchiveType">
+ <summary>
+ The type of archive file that Chrome OS cros-disks daemon is requested to
+ mount.
+ </summary>
+</histogram>
+
+<histogram name="CrosDisks.DeviceMediaType" enum="CrosDisksDeviceMediaType">
+ <summary>
+ The media type of removable device that Chrome OS cros-disks daemon is
+ requested to mount.
+ </summary>
+</histogram>
+
+<histogram name="CrosDisks.FilesystemType" enum="CrosDisksFilesystemType">
+ <summary>
+ The type of file system that Chrome OS cros-disks daemon is requested to
+ mount.
+ </summary>
+</histogram>
+
+<histogram name="DisabledExtension.ExtensionWipedStatus" enum="BooleanWiped">
+ <summary>Whether an extension has been wiped out.</summary>
+</histogram>
+
+<histogram name="DisabledExtension.SideloadWipeoutCount">
+ <summary>
+ How many external extensions get wiped out as a result of the Sideload
+ Wipeout one-time initiative.
+ </summary>
+</histogram>
+
+<histogram name="DisabledExtension.SideloadWipeoutNeeded" enum="BooleanSuccess">
+ <summary>
+ Whether any extension got wiped out as a result of the Sideload Wipeout
+ one-time initiative.
+ </summary>
+</histogram>
+
+<histogram name="DisabledExtension.UserSelection" enum="SideloadWipeoutBubble">
+ <summary>
+ The user selection in the Sideload Wipeout bubble, grouped by the
+ UmaWipeoutHistogramOptions enum.
+ </summary>
+</histogram>
+
+<histogram name="DiskCache.TotalIOTime" units="milliseconds">
+ <obsolete>
+ Deprecated.
+ </obsolete>
+ <summary>
+ The total time it takes to perform a payload IO operation, for the regular
+ disk cache.
+ </summary>
+</histogram>
+
+<histogram name="DNS.AttemptCancelled">
+ <summary>
+ The attempt which completed after the job was already cancelled.
+ </summary>
+</histogram>
+
+<histogram name="DNS.AttemptDiscarded">
+ <summary>
+ The attempt which completed after the job was already cancelled OR the
+ attempt that has finished after host resolution was already completed by an
+ earlier attempt.
+ </summary>
+</histogram>
+
+<histogram name="DNS.AttemptFailDuration" units="milliseconds">
+ <summary>
+ Duration of time taken in OS resolutions for actual navigations. These
+ attempts which completed after the job was already canceled OR after the job
+ was already completed by an earlier attempt. Note that cached resolutions
+ may provide low (0ms?) resolution times.
+ </summary>
+</histogram>
+
+<histogram name="DNS.AttemptFailure">
+ <summary>The attempt that has not resolved the host successfully.</summary>
+</histogram>
+
+<histogram name="DNS.AttemptFirstFailure">
+ <summary>
+ The attempt that resolved the host first and the resolution was not
+ successful.
+ </summary>
+</histogram>
+
+<histogram name="DNS.AttemptFirstSuccess">
+ <summary>
+ The attempt that resolved the host first and the resolution was successful.
+ </summary>
+</histogram>
+
+<histogram name="DNS.AttemptSuccess">
+ <summary>The attempt that has resolved the host successfully.</summary>
+</histogram>
+
+<histogram name="DNS.AttemptSuccessDuration" units="milliseconds">
+ <summary>
+ Duration of time taken in OS resolutions that succeeded and were requested
+ for actual navigations. These attempts which completed after the job was
+ already canceled OR after the job was already completed by an earlier
+ attempt. Note that cached resolutions may provide low (0ms?) resolution
+ times.
+ </summary>
+</histogram>
+
+<histogram name="DNS.AttemptTimeSavedByRetry" units="milliseconds">
+ <summary>
+ This histogram shows the time saved by having spawned an extra attempt, when
+ the first attempt didn't finish before retry attempt.
+ </summary>
+</histogram>
+
+<histogram name="DNS.CacheEvicted" units="milliseconds">
+ <summary>
+ The time left to expiration of an entry when it is removed while compacting
+ the HostCache.
+ </summary>
+</histogram>
+
+<histogram name="DNS.CacheExpired" units="milliseconds">
+ <summary>
+ The time since expiration of an entry when it is removed while compacting
+ the HostCache.
+ </summary>
+</histogram>
+
+<histogram name="DNS.CacheExpiredOnGet" units="milliseconds">
+ <summary>
+ The time since expiration of an entry when it is removed on lookup.
+ </summary>
+</histogram>
+
+<histogram name="DNS.EmptyAddressListAndNoError"
+ enum="DNSEmptyAddressListAndNoError">
+ <summary>
+ Error status when an empty address list was found in OnLookupComplete().
+ </summary>
+</histogram>
+
+<histogram name="DNS.IndependentFailedNavigation" units="milliseconds">
+ <summary>
+ When either a pre-resolution was not done recently enough to provide
+ benefit, or the the corresponding pre-resolution is still pending, this
+ histogram shows the duration of time used to resolve a hostname as not
+ existing during a failed attempt to navigate to (GET) a URL. In newer
+ versions, if the hostname has never been found as a link during a page scan,
+ and it has a referring URL, then it is added to referrer list data structure
+ (hoping we'll do better next time).
+ </summary>
+</histogram>
+
+<histogram name="DNS.IndependentNavigation" units="milliseconds">
+ <summary>
+ When either a pre-resolution was not done recently enough to provide
+ benefit, or the the corresponding pre-resolution is still pending, this
+ histogram shows the duration of the duration of time used to resolve a
+ hostname to navigate to (GET) a URL. In newer versions, if the hostname has
+ never been found as a link during a page scan, and it has a referring URL,
+ then it is added to referrer list data structure (hoping we'll do better
+ next time).
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTime" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (a getaddrinfo call was dispatched to the thread
+ pool).
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTime_HIGHEST" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (a getaddrinfo call was dispatched to the thread
+ pool). Includes only Jobs which had priority HIGHEST when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTime_IDLE" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (a getaddrinfo call was dispatched to the thread
+ pool). Includes only Jobs which had priority IDLE when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTime_LOW" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (a getaddrinfo call was dispatched to the thread
+ pool). Includes only Jobs which had priority LOW when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTime_LOWEST" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (a getaddrinfo call was dispatched to the thread
+ pool). Includes only Jobs which had priority LOWEST when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTime_MEDIUM" units="milliseconds">
+ <summary>
+ Time elapsed between the time the HostResolverImpl::Job was created and the
+ time the Job was started (a getaddrinfo call was dispatched to the thread
+ pool). Includes only Jobs which had priority MEDIUM when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTimeAfterChange" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (a getaddrinfo call was dispatched to the thread pool).
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTimeAfterChange_HIGHEST" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (a getaddrinfo call was dispatched to the thread pool). Includes
+ only Jobs which had priority HIGHEST when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTimeAfterChange_IDLE" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (a getaddrinfo call was dispatched to the thread pool). Includes
+ only Jobs which had priority IDLE when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTimeAfterChange_LOW" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (a getaddrinfo call was dispatched to the thread pool). Includes
+ only Jobs which had priority LOW when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTimeAfterChange_LOWEST" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (a getaddrinfo call was dispatched to the thread pool). Includes
+ only Jobs which had priority LOWEST when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.JobQueueTimeAfterChange_MEDIUM" units="milliseconds">
+ <summary>
+ Time elapsed between the last time the priority of a HostResolverImpl::Job
+ changed (when a Request was attached or detached) and the time the Job was
+ started (a getaddrinfo call was dispatched to the thread pool). Includes
+ only Jobs which had priority MEDIUM when started.
+ </summary>
+</histogram>
+
+<histogram name="DNS.PrefetchCacheEviction" units="milliseconds">
+ <summary>
+ The duration of time used (most recently) to pre-resolve a hostname, when
+ the prefetched resolution was apparently evicted from the cache. The
+ included samples only list pre-resolution times when the later
+ navigations/fetches took in excess of 15ms.
+ </summary>
+</histogram>
+
+<histogram name="DNS.PrefetchCacheEvictionL" units="milliseconds">
+ <summary>
+ The duration of time used (most recently) to pre-resolve a hostname, when
+ the prefetched resolution was apparently evicted from the cache. The
+ included samples only list pre-resolution times when the later
+ navigations/fetches took in excess of 15ms.
+ </summary>
+</histogram>
+
+<histogram name="DNS.PrefetchFoundName">
+ <summary>Replaced by DNS.PrefetchFoundNameL.</summary>
+</histogram>
+
+<histogram name="DNS.PrefetchFoundNameL" units="milliseconds">
+ <obsolete>
+ Deprecated 2/2010, and replaced by DNS.PrefetchResolution
+ </obsolete>
+ <summary>
+ The duration of time used by the DNS pre-resolving threads to resolve a host
+ name via the network. Any resolutions that are faster than 15ms are
+ considered to be local cache hits, not requiring network access, and are not
+ included in this histogram. This histogram is most useful for estimating the
+ typical cost of a name resolution, but it also estimates the total number of
+ network-based resolutions induced by this feature. Not all these
+ resolutions prove helpful (i.e., the user does not always actually visit the
+ resolved hostnames).
+ </summary>
+</histogram>
+
+<histogram name="DNS.PrefetchNegativeHit">
+ <summary>Replaced by DNS.PrefetchNegativeHitL.</summary>
+</histogram>
+
+<histogram name="DNS.PrefetchNegativeHitL" units="milliseconds">
+ <summary>
+ The duration of time saved due to DNS pre-resolving in the &quot;name not
+ found&quot; case. Time &quot;savings&quot; shown in the histogram are
+ defined to be the difference between the DNS pre-resolution duration, and
+ the DNS resolution duration seen during a navigation. These cache hits only
+ list events where the DNS pre-resolve duration for a host was in excess of
+ 15ms (i.e., the network was consulted), and the actual DNS resolution (when
+ a user attempted to navigate to a link with the same host name) took less
+ than 15ms (i.e., the network was not consulted), which means the gain was a
+ result of a &quot;cache hit&quot; in the OS cache. For some users with
+ LANs, all negative results (even when the DNS cache might otherwise help)
+ take about 2.5 seconds (due to timeouts for netbios broadcasts), and hence
+ no savings are possible (or shown) for such users in this category.
+ </summary>
+</histogram>
+
+<histogram name="DNS.PrefetchPositiveHit">
+ <summary>Replaced by DNS.PrefetchPositiveHitL.</summary>
+</histogram>
+
+<histogram name="DNS.PrefetchPositiveHitL" units="milliseconds">
+ <summary>
+ The duration of time saved due to DNS pre-resolving in the &quot;name was
+ found&quot; case, and induced by either a page scan for a link or an omnibox
+ entry by the user. Time &quot;savings&quot; shown in the histogram are
+ defined to be the difference between the DNS pre-resolution duration, and
+ the DNS resolution duration seen during a navigation. These cache hits only
+ list events where the DNS pre-resolve duration for a host was in excess of
+ 15ms (i.e., the network was consulted), and the actual DNS resolution (when
+ a user attempted to navigate to a link with the same host name) took less
+ than 15ms (i.e., the network was not consulted), which means the gain was a
+ result of a &quot;cache hit&quot; in the OS cache.
+ </summary>
+</histogram>
+
+<histogram name="DNS.PrefetchQueue" units="milliseconds">
+ <summary>
+ The duration of time spent by a proposed resolution waiting in the queue to
+ be resolved. This number is in addition to any DNS resolution time that may
+ come later.
+ </summary>
+</histogram>
+
+<histogram name="DNS.PrefetchReferredPositiveHit" units="milliseconds">
+ <summary>
+ The duration of time saved due to DNS pre-resolving in the &quot;name was
+ found&quot; case, and induced by predicting (using referrer lists) that a
+ resolution was needed. Time &quot;savings&quot; shown in the histogram are
+ defined to be the difference between the DNS pre-resolution duration, and
+ the DNS resolution duration seen during a navigation. These cache hits only
+ list events where the DNS pre-resolve duration for a host was in excess of
+ 15ms (i.e., the network was consulted), and the actual DNS resolution (when
+ a user attempted to navigate to a link with the same host name) took less
+ than 15ms (i.e., the network was not consulted), which means the gain was a
+ result of a &quot;cache hit&quot; in the OS cache.
+ </summary>
+</histogram>
+
+<histogram name="DNS.PrefetchResolution" units="milliseconds">
+ <summary>
+ The duration of time used by the DNS pre-resolving threads to resolve a host
+ name via the network. Any resolutions that are faster than 15ms are
+ considered to be local cache hits, not requiring network access, and are not
+ included in this histogram. This histogram is most useful for estimating the
+ typical cost of a name resolution, but it also estimates the total number of
+ network-based resolutions induced by this feature. Not all these
+ resolutions prove helpful (i.e., the user does not always actually visit the
+ resolved hostnames).
+ </summary>
+</histogram>
+
+<histogram name="DNS.QueueRecycledDeltaOver2">
+ <summary>
+ When, due to congestion avoidance, a queued pre-resolution is abandoned
+ (recycled) without actually being resolved, this histograms records the age
+ in the queue of that entry. Only times over 2 seconds are recorded in this
+ histogram.
+ </summary>
+</histogram>
+
+<histogram name="DNS.QueueRecycledUnder2">
+ <summary>
+ When, due to congestion avoidance, a queued pre-resolution is abandoned
+ (recycled) without actually being resolved, this histograms records the age
+ in the queue of that entry. Only times less than or equal to 2 seconds are
+ recorded in this histogram.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveCategory" enum="ResolutionCategory">
+ <summary>
+ Counts of successes and failures of OS resolutions in various categories.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveFail" units="milliseconds">
+ <summary>
+ Duration of time taken in OS resolutions for actual navigations. Note that
+ cached OS resolutions may provide low (0ms?) resolution times.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveFail_FAMILY_IPV4" units="milliseconds">
+ <summary>Same as DNS.ResolveFail, but limited to pure IPv4 lookups.</summary>
+</histogram>
+
+<histogram name="DNS.ResolveFail_FAMILY_IPV6" units="milliseconds">
+ <summary>Same as DNS.ResolveFail, but limited to pure IPv6 lookups.</summary>
+</histogram>
+
+<histogram name="DNS.ResolveFail_FAMILY_UNSPEC" units="milliseconds">
+ <summary>Same as DNS.ResolveFail, but limited to IPv4/IPv6 lookups.</summary>
+</histogram>
+
+<histogram name="DNS.ResolveSpeculativeFail" units="milliseconds">
+ <summary>
+ Duration of time taken in speculative OS resolutions. Note that cached OS
+ resolutions may provide low (0ms?) resolution times.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveSpeculativeSuccess" units="milliseconds">
+ <summary>
+ Duration of time taken in speculative OS resolution that succeeded. Note
+ that cached resolutions may provide low (0ms?) resolution times.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveSuccess" units="milliseconds">
+ <summary>
+ Duration of time taken in OS resolutions that succeeded and were requested
+ for actual navigations. Note that cached resolutions may provide low (0ms?)
+ resolution times.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveSuccess_FAMILY_IPV4" units="milliseconds">
+ <summary>
+ Same as DNS.ResolveSuccess, but limited to pure IPv4 lookups.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveSuccess_FAMILY_IPV6" units="milliseconds">
+ <summary>
+ Same as DNS.ResolveSuccess, but limited to pure IPv6 lookups.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveSuccess_FAMILY_UNSPEC" units="milliseconds">
+ <summary>
+ Same as DNS.ResolveSuccess, but limited to IPv4/IPv6 lookups.
+ </summary>
+</histogram>
+
+<histogram name="DNS.ResolveUnspecWaste" enum="ResolutionUnspecWasteCategory">
+ <obsolete>
+ Deprecated as of 5/2013.
+ </obsolete>
+ <summary>
+ Counts of hits and misses in the DNS cache and DNS jobs pool of wasted
+ HostResolverImpl::Jobs that could be avoided by always resolving using
+ AF_UNSPEC.
+ </summary>
+</histogram>
+
+<histogram name="DNS.TotalTime" units="milliseconds">
+ <summary>
+ Duration of time since a HostResolverImpl::Resolve request to the time a
+ result is posted. Excludes canceled, evicted, and aborted requests. Includes
+ cache hits (recorded as 0). Excludes speculative requests.
+ </summary>
+</histogram>
+
+<histogram name="DNS.TotalTime_speculative" units="milliseconds">
+ <summary>
+ Duration of time since a HostResolverImpl::Resolve request to the time a
+ result is posted. Excludes canceled, evicted, and aborted requests. Includes
+ cache hits (recorded as 0). Speculative requests only.
+ </summary>
+</histogram>
+
+<histogram name="DNS.UnexpectedResolution">
+ <summary>
+ In some cases, such as when content arrives with embedded references to
+ other servers, the prefetch system can't (or doesn't) attempt to pre-resolve
+ the hostnames. As an example, a visit to www.cnn.com will fetch content
+ with references to about 12 additional hostnames, none of which are
+ currently anticipated. Such resolutions are termed &quot;Unexpected
+ Resolutions,&quot; and the durations associated with those DNS resolutions
+ are shown below. Future features may attempt to learn (from prior
+ experience locally, or from server provided hints), what secondary hostname
+ resolutions should be done when a primary resolution (or navigation) takes
+ place. This histogram shows what the potential savings are that
+ &quot;remain on the table&quot; until we employ some of these more advanced
+ features.
+ </summary>
+</histogram>
+
+<histogram name="DNS.UnexpectedResolutionL">
+ <summary>
+ In some cases, such as when content arrives with embedded references to
+ other servers, or when a page (such as one in SSL) preclude scanning and
+ prefetching, the prefetch system can't (or doesn't) attempt to pre-resolve
+ the hostnames. As an example, a visit to www.cnn.com will fetch content
+ with references to about 12 additional hostnames, none of which might be
+ anticipated. Similarly, clicking on a link in an SSL page won't be
+ anticipated (since scanning in not allowed by default). Such resolutions are
+ termed &quot;Unexpected Resolutions,&quot; and the durations associated with
+ those navigation induced DNS resolutions are shown below. If a referring
+ URL is available for the navigation, the relationship to the referring URL
+ was recorded, and future navigations to the referring hostname would have
+ induced a pre-resolution of hostname that caused an entry below. Such any
+ entry may facilitate future listing in the ReferredPositiveHit histogram.
+ </summary>
+</histogram>
+
+<histogram name="DnsProbe.ErrorPageUpdateStatus" enum="DnsProbe.ProbeStatus">
+ <summary>Status of DNS probe updates sent to a DNS error page.</summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.Elapsed" units="ms">
+ <obsolete>
+ Renamed 7/2013 to DnsProbe.ProbeDuration.
+ </obsolete>
+ <summary>Time between starting and finishing DNS probe.</summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.NcnOffline.Elapsed" units="ms">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>
+ Time between starting and finishing DNS probe when NCN says we're offline.
+ </summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.NcnOffline.Result"
+ enum="DnsProbe.ObsoleteProbeResult">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>
+ Result of DNS probes sent by the probe service when NCN says we're offline.
+ </summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.NcnOnline.Elapsed" units="ms">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>
+ Time between starting and finishing DNS probe when NCN says we're online.
+ </summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.NcnOnline.Result"
+ enum="DnsProbe.ObsoleteProbeResult">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>
+ Result of DNS probes sent by the probe service when NCN says we're online.
+ </summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.Result" enum="DnsProbe.ObsoleteProbeResult">
+ <obsolete>
+ Renamed 7/2013 to DnsProbe.ProbeResult. (Also switched to the full
+ DnsProbe.ProbeStatus enum.)
+ </obsolete>
+ <summary>Result of DNS probes sent by the probe service.</summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.ResultBadConfig.Elapsed" units="ms">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>Elapsed time of DNS probes that return PROBE_BAD_CONFIG.</summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.ResultBadConfig.SystemIsLocalhost"
+ enum="DnsProbe.SystemIsLocalhost">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>
+ Whether the only nameserver in the system DNS config was 127.0.0.1 when the
+ probe result was BAD_CONFIG.
+ </summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.ResultBadConfig.SystemJobResult"
+ enum="DnsProbe.JobResult">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>
+ The result of the system probe job when the overall probe result was
+ BAD_CONFIG.
+ </summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.ResultBadConfig.SystemNameserverCount">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>
+ The number of nameservers in the system DNS config when the probe result was
+ BAD_CONFIG.
+ </summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.ResultNoInternet.Elapsed" units="ms">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>Elapsed time of DNS probes that return PROBE_NO_INTERNET.</summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.ResultNxdomain.Elapsed" units="ms">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>Elapsed time of DNS probes that return PROBE_NXDOMAIN.</summary>
+</histogram>
+
+<histogram name="DnsProbe.Probe.ResultUnknown.Elapsed" units="ms">
+ <obsolete>
+ Removed 7/2013.
+ </obsolete>
+ <summary>Elapsed time of DNS probes that return PROBE_UNKNOWN.</summary>
+</histogram>
+
+<histogram name="DnsProbe.ProbeDuration" units="ms">
+ <summary>Time between starting and finishing DNS probe.</summary>
+</histogram>
+
+<histogram name="DnsProbe.ProbeResult" enum="DnsProbe.ProbeStatus">
+ <summary>Result of DNS probes sent by the probe service.</summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.DBLoadedCount">
+ <summary>Number of certs loaded from domain bound cert database.</summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.DBLoadTime" units="ms">
+ <summary>Time spent loading domain bound cert database.</summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.DBSizeInKB" units="KB">
+ <summary>
+ The size, on disk, of the domain bound cert database as it is being loaded.
+ </summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.GenerateCertTime" units="ms">
+ <summary>Time spent generating a domain bound cert.</summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.GetCertTime" units="ms">
+ <summary>
+ Combined time for GetDomainBoundCert retrieval (both synchronous and
+ asynchronous).
+ </summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.GetCertTimeAsync" units="ms">
+ <summary>
+ Time for asynchronous retrieval (from the GetDomainBoundCert call until
+ completion callback is called).
+ </summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.GetCertTimeSync" units="ms">
+ <summary>Time for synchronous GetDomainBoundCert cert retrieval.</summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.GetDomainBoundCertResult"
+ enum="DomainBoundCerts.GetCertResult">
+ <summary>Result of GetDomainBoundCert function.</summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.KillDatabaseResult" enum="BooleanSuccess">
+ <summary>
+ Whether the domain-bound certs sqlite database was killed succesfully when
+ an unrecoverable error was detected.
+ </summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.Support" enum="DomainBoundCerts.Support">
+ <summary>
+ Counts of SSL client sockets broken down by support for Domain Bound
+ Certificates TLS extension. Counts only connections with full handshakes,
+ resumed sessions are not counted.
+ </summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.TaskMaxWaitTime" units="ms">
+ <summary>
+ Longest time spent by requests waiting for load of domain bound cert
+ database.
+ </summary>
+</histogram>
+
+<histogram name="DomainBoundCerts.TaskWaitCount">
+ <summary>
+ Number of requests that waited for load of domain bound cert database.
+ </summary>
+</histogram>
+
+<histogram name="Download.AcceptRangesBytes.KBytes" units="KB">
+ <summary>The length of downloads for serves that accept byte ranges.</summary>
+</histogram>
+
+<histogram name="Download.AcceptRangesMissingOrInvalid.KBytes" units="KB">
+ <summary>
+ The length of downloads for serves that do not specify whether the accept
+ ranges, or have invalid ranges specified.
+ </summary>
+</histogram>
+
+<histogram name="Download.AcceptRangesNone.KBytes" units="KB">
+ <summary>
+ The length of downloads for serves that do not accept ranges.
+ </summary>
+</histogram>
+
+<histogram name="Download.ActualBandwidth" units="Bytes/second">
+ <summary>The actual bandwidth (per read) of a download.</summary>
+</histogram>
+
+<histogram name="Download.ApiFunctions" enum="DownloadFunctions">
+ <summary>Downloads extension API function calls.</summary>
+</histogram>
+
+<histogram name="Download.BandwidthDiskBytesPerSecond">
+ <summary>
+ Disk bandwidth (defined as total bytes divided by the amount of time blocked
+ on write or close on the file descriptor) seen for a single download.
+ </summary>
+</histogram>
+
+<histogram name="Download.BandwidthOverallBytesPerSecond">
+ <summary>
+ Overall bandwidth seen for the download. Note that this is measured at the
+ point at which the file is written, and so will not take into account the
+ time costs of activities that occur after file write is completed (e.g. safe
+ browsing scanning).
+ </summary>
+</histogram>
+
+<histogram name="Download.BandwidthUsed" units="%">
+ <summary>
+ The percentage of the potential bandwidth actually used (per read) of a
+ download. An entry of 100% implies that Chrome was the limiting factor in
+ download speed.
+ </summary>
+</histogram>
+
+<histogram name="Download.ClearAllSize">
+ <summary>
+ The number of downloads in history at the time it is cleared.
+ </summary>
+</histogram>
+
+<histogram name="Download.ContentDisposition" enum="DownloadContentDisposition">
+ <summary>
+ Content-Disposition header features. The presence of a Content-Disposition
+ header, use of 'name', 'filename' and 'filename*' parameters, and string
+ encoding schemes are counted for each unthrottled download. The total number
+ downloads is Download.Counts[5] (Initiated and Unthrottled).
+ </summary>
+</histogram>
+
+<histogram name="Download.ContentImageType" enum="DownloadImageType">
+ <summary>Types of images that are downloaded.</summary>
+</histogram>
+
+<histogram name="Download.ContentType" enum="DownloadContentType">
+ <summary>Content types that are downloaded.</summary>
+</histogram>
+
+<histogram name="Download.Counts" enum="DownloadCountType">
+ <summary>
+ Various individual counts in the download system; see DownloadCountType for
+ details.
+ </summary>
+</histogram>
+
+<histogram name="Download.CountsChrome" enum="ChromeDownloadCountType">
+ <summary>
+ Various individual counts in the download system, for example the number of
+ downloads blocked by throttling from the DownloadRequestLimiter.
+ </summary>
+</histogram>
+
+<histogram name="Download.DangerousDownloadValidated"
+ enum="DownloadItem.DangerType">
+ <summary>
+ User chose to save a download which was marked dangerous. Grouped by the
+ type of danger.
+ </summary>
+</histogram>
+
+<histogram name="Download.DatabaseRecordDropped"
+ enum="DownloadDatabaseRecordDroppedType">
+ <summary>Reason for dropping a record read in from the DB.</summary>
+</histogram>
+
+<histogram name="Download.DatabaseRemoveDownloadsCount">
+ <summary>Number of downloads removed from the history at once.</summary>
+</histogram>
+
+<histogram name="Download.DatabaseRemoveDownloadsTime" units="microseconds">
+ <summary>How long it took to delete some downloads from history.</summary>
+</histogram>
+
+<histogram name="Download.DatabaseRemoveDownloadsTimePerRecord"
+ units="nanoseconds/record">
+ <summary>
+ How long it took to delete some downloads from history, per download.
+ </summary>
+</histogram>
+
+<histogram name="Download.Discard" enum="DownloadItem.DangerType">
+ <summary>
+ A download which was marked dangerous was discarded without the user
+ directly choosing, because the browser was closed. Grouped by the type of
+ danger.
+ </summary>
+</histogram>
+
+<histogram name="Download.DiskBandwidthUsedPercentage" units="Percent">
+ <summary>
+ The percentage of the available disk bandwidth that was used by the
+ download. 100% indicates that the disk bandwidth was the limiting factor
+ for the download.
+ </summary>
+</histogram>
+
+<histogram name="Download.DOMEvent" enum="DownloadDOMEvent">
+ <summary>User actions in chrome://downloads</summary>
+</histogram>
+
+<histogram name="Download.DownloadSize" units="KB">
+ <summary>The size of successfully completed downloads.</summary>
+</histogram>
+
+<histogram name="Download.FilePickerResult" enum="DownloadFilePickerResult">
+ <summary>
+ How the user interacts with the file chooser when doing a &quot;Save
+ As&quot; for non-full-page saves.
+ </summary>
+</histogram>
+
+<histogram name="Download.FileThreadBlockedTime">
+ <summary>
+ The amount of time in milliseconds the file thread blocks for each set of
+ buffers drained from the incoming pipe (ms).
+ </summary>
+</histogram>
+
+<histogram name="Download.FileThreadReceiveBuffers">
+ <summary>
+ The number of buffers in a call to DownloadManager::UpdateDownload.
+ </summary>
+</histogram>
+
+<histogram name="Download.FirstOpenTime" units="milliseconds">
+ <summary>
+ The time between a download completing and the file being opened for the
+ first time.
+ </summary>
+</histogram>
+
+<histogram name="Download.HistorySize">
+ <summary>
+ The number of items in the History database, at the time a new download is
+ recorded.
+ </summary>
+</histogram>
+
+<histogram name="Download.HistorySize2">
+ <summary>
+ The number of items in the History database, at the time a new download is
+ recorded. Higher maximum, more buckets than Download.HistorySize.
+ </summary>
+</histogram>
+
+<histogram name="Download.InterruptedAtEndError" enum="NetErrorCodes">
+ <summary>
+ Positive net error code that caused a download to be interrupted at the
+ *end* of a download (when the number of bytes is known). This is only
+ triggered when the total content size is known before any bytes are
+ transferred, such as when a Content-Length header is supplied.
+ </summary>
+</histogram>
+
+<histogram name="Download.InterruptedAtEndReason" enum="InterruptReason">
+ <summary>
+ The reason that a download was interrupted at the *end* of a download (when
+ the number of bytes is known). This is only triggered when the total content
+ size is known before any bytes are transferred, such as when a
+ Content-Length header is supplied.
+ </summary>
+</histogram>
+
+<histogram name="Download.InterruptedError" enum="NetErrorCodes">
+ <summary>
+ Positive net error code that caused a download to be interrupted.
+ </summary>
+</histogram>
+
+<histogram name="Download.InterruptedOverrunBytes">
+ <summary>
+ The excessive number of bytes which have been received at the time that a
+ download is interrupted. This is only triggered when the total content size
+ is known before any bytes are transferred, such as when a Content-Length
+ header is supplied.
+ </summary>
+</histogram>
+
+<histogram name="Download.InterruptedReason" enum="InterruptReason">
+ <summary>The reason that a download was interrupted.</summary>
+</histogram>
+
+<histogram name="Download.InterruptedReceivedSizeK" units="KB">
+ <summary>
+ The number of kilobytes received for a download at the time it is
+ interrupted.
+ </summary>
+</histogram>
+
+<histogram name="Download.InterruptedTotalSizeK" units="KB">
+ <summary>
+ The reported total size in kilobytes for a download at the time it is
+ interrupted. This is essentially the size reported by the Content-Length
+ header. If no size is specified up-front, it is not recorded in the
+ histogram. For example, a download transferred with chunked encoding will
+ not be recorded.
+ </summary>
+</histogram>
+
+<histogram name="Download.InterruptedUnderrunBytes">
+ <summary>
+ The total number of bytes minus the received number of bytes at the time
+ that a download is interrupted. This is only triggered when the total
+ content size is known before any bytes are transferred, such as when a
+ Content-Length header is supplied.
+ </summary>
+</histogram>
+
+<histogram name="Download.InterruptedUnknownSize"
+ enum="DownloadInterruptedUnknownSizeType">
+ <summary>
+ True if the size of an interrupted download is unknown, false if it is
+ known.
+ </summary>
+</histogram>
+
+<histogram name="Download.MapErrorNetworkFailed" enum="NetErrorCodes">
+ <summary>
+ Network error that produced a DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED
+ result in DownloadResourceHandler::OnResponseCompleted().
+ </summary>
+</histogram>
+
+<histogram name="Download.MapWinShErrorAccessDenied"
+ enum="SpecialShFileOperationCodes">
+ <summary>
+ Windows error that produced a DOWNLOAD_INTERRUPT_REASON_ACCESS_DENIED result
+ in MapShFileOperationCodes().
+ </summary>
+</histogram>
+
+<histogram name="Download.MapWinShErrorFileFailed"
+ enum="SpecialShFileOperationCodes">
+ <summary>
+ Windows error that produced a DOWNLOAD_INTERRUPT_REASON_FILE_FAILED result
+ in MapShFileOperationCodes().
+ </summary>
+</histogram>
+
+<histogram name="Download.OnChanged">
+ <summary>
+ Percentage of DownloadItem::Observer::OnDownloadUpdated events that
+ signified a change in the extension API representation of the download.
+ </summary>
+</histogram>
+
+<histogram name="Download.OpensOutstanding">
+ <summary>The number of unopened downloads, when one is opened.</summary>
+</histogram>
+
+<histogram name="Download.OpenTime" units="milliseconds">
+ <summary>
+ The time between a download completing and the file being opened.
+ </summary>
+</histogram>
+
+<histogram name="Download.PotentialBandwidth" units="Bytes/second">
+ <summary>
+ The maximum bandwidth (per read) that Chrome could have provided for the
+ download. If the actual bandwidth equals the potential bandwidth, that
+ means that Chrome was the limiting factor for download bandwidth.
+ </summary>
+</histogram>
+
+<histogram name="Download.ResourceHandlerBlockedPercentage" units="Percent">
+ <summary>
+ The percentage of the lifetime of the DownloadResourceHandler for which it
+ was blocked by downstream flow control. 0% indicates that the network
+ bandwidth was the limiting factor for the download.
+ </summary>
+</histogram>
+
+<histogram name="Download.SavePackage" enum="DownloadSavePackageEvent">
+ <summary>
+ Events (e.g. Started, Cancelled, Finished, Write to Completed file, Write to
+ Failed file) occuring within the state machine of a SavePackage operation.
+ </summary>
+</histogram>
+
+<histogram name="Download.ShelfInProgressSizeOnAutoClose">
+ <summary>
+ The number of download items in progress on the shelf when it closes
+ automatically.
+ </summary>
+</histogram>
+
+<histogram name="Download.ShelfInProgressSizeOnUserClose">
+ <summary>
+ The number of download items in progress on the shelf when the user closes
+ it.
+ </summary>
+</histogram>
+
+<histogram name="Download.ShelfSizeOnAutoClose">
+ <summary>
+ The number of download items on the shelf when it closes automatically.
+ </summary>
+</histogram>
+
+<histogram name="Download.ShelfSizeOnUserClose">
+ <summary>
+ The number of download items on the shelf when the user closes it.
+ </summary>
+</histogram>
+
+<histogram name="Download.Sources" enum="DownloadSource">
+ <summary>
+ The initiation source (if initiated within the content layer of chrome) for
+ a download.
+ </summary>
+</histogram>
+
+<histogram name="Download.SourcesChrome" enum="ChromeDownloadSource">
+ <summary>
+ The initiation source (if initiated within the above-content layer of
+ chrome) for a download.
+ </summary>
+</histogram>
+
+<histogram name="Download.Time" units="milliseconds">
+ <summary>Time between the start of a download and its completion.</summary>
+</histogram>
+
+<histogram name="Download.UserDiscard" enum="DownloadItem.DangerType">
+ <summary>
+ User chose to discard a download which was marked dangerous. Grouped by the
+ type of danger.
+ </summary>
+</histogram>
+
+<histogram name="Download.WriteLoopCount">
+ <summary>
+ The number of iterations for the write loop in BaseFile::AppendDataTofile().
+ </summary>
+</histogram>
+
+<histogram name="Download.WriteSize" units="Bytes">
+ <summary>The write size for calls to BaseFile::AppendDataTofile().</summary>
+</histogram>
+
+<histogram name="Drive.CacheDBOpenStatus" enum="DriveCacheDBOpenStatus">
+ <summary>Status of drive cache metadata database open.</summary>
+</histogram>
+
+<histogram name="Drive.EntireFeedLoadTime" units="microseconds">
+ <summary>
+ Time spent to load the entire file system information from the server
+ </summary>
+</histogram>
+
+<histogram name="Drive.EntryKind" enum="DriveEntryKind">
+ <summary>
+ Provides breakdown of specific formats for hosted documents. Recorded when
+ feed is loaded from the server.
+ </summary>
+</histogram>
+
+<histogram name="Drive.FileFormat" enum="DriveFileFormat">
+ <summary>
+ Provides breakdown of specific file formats for regular files. Recorded when
+ feed is loaded from the server.
+ </summary>
+</histogram>
+
+<histogram name="Drive.InitialFeedLoadTime" units="microseconds">
+ <summary>
+ Time spent to load the initial part of the file system information from the
+ server
+ </summary>
+</histogram>
+
+<histogram name="Drive.MetadataDBInitResult" enum="DriveMetadataDBInitStatus">
+ <summary>Result of drive resource metadata database initialization.</summary>
+</histogram>
+
+<histogram name="Drive.MetadataDBOpenExistingResult"
+ enum="DriveMetadataDBInitStatus">
+ <summary>
+ Result of attempt to open existing drive resource metadata database.
+ </summary>
+</histogram>
+
+<histogram name="Drive.NumberOfHostedDocuments">
+ <summary>
+ Number of hosted documents (spreadsheets etc.) on Drive. Logged when Drive
+ is first accessed.
+ </summary>
+</histogram>
+
+<histogram name="Drive.NumberOfRegularFiles">
+ <summary>
+ Number of regualr files on Drive. Logged when Drive is first accessed.
+ </summary>
+</histogram>
+
+<histogram name="Drive.NumberOfTotalFiles">
+ <summary>
+ Number of total files (regualr files + hosted documents) on Drive. Logged
+ when Drive is first accessed.
+ </summary>
+</histogram>
+
+<histogram name="Drive.PushNotificationInitiallyEnabled" enum="BooleanEnabled">
+ <summary>
+ Tracks whether the push notification is initially enabled for Drive.
+ Recorded when the first notification is processed. Notification is emulated
+ by polling if the push notication is disabled.
+ </summary>
+</histogram>
+
+<histogram name="Drive.PushNotificationRegistered" enum="BooleanRegistered">
+ <summary>
+ Tracks whether the push notification request is registered correctly for
+ Drive. Recorded when the push notification manager is initialized.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.AutoEnrollmentExtraTime" units="milliseconds">
+ <summary>
+ Time since the user logged in until the auto-enrollment protocol completed.
+ 0 is sampled when the protocol is done by the time the user logs in.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.AutoEnrollmentProtocolTime" units="milliseconds">
+ <summary>Total duration time of the auto-enrollment protocol.</summary>
+</histogram>
+
+<histogram name="Enterprise.AutoEnrollmentRequestNetworkErrorCode"
+ enum="NetErrorCodes">
+ <summary>
+ Network error code (if applicable) for auto-enrollment requests.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.AutoEnrollmentRequestStatus"
+ enum="EnterpriseDeviceManagementStatus">
+ <summary>URL fetcher status for auto-enrollment requests.</summary>
+</histogram>
+
+<histogram name="Enterprise.DMToken" enum="EnterpriseDMTokenType">
+ <summary>
+ Events related to fetching, saving and loading DM server tokens. These are
+ used to retrieve cloud policies.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.Enrollment" enum="EnterpriseEnrollmentType">
+ <summary>
+ Events related to device enrollment on new installs of ChromeOS devices.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.ONC.PolicyValidation" enum="BooleanSuccess">
+ <summary>Result of the OpenNetworkConfiguration policy validation.</summary>
+</histogram>
+
+<histogram name="Enterprise.Policies" enum="EnterprisePolicies">
+ <summary>
+ A set of enterprise policy rules that are in use. This is recorded every 24
+ hours and at startup, if the last recording was earlier than a day before.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.Policy" enum="EnterprisePolicyType">
+ <summary>
+ Events related to fetching, saving and loading user policies, and also
+ device policies on ChromeOS.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.PolicyInvalidations"
+ enum="EnterprisePolicyInvalidations">
+ <summary>
+ Events for counting policy invalidations received with and without payloads.
+ Invalidations indicate that a policy has been updated and should be
+ refreshed. Payloads provide context about the policy update, but may be
+ absent if dropped by the invalidation service.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.PolicyInvalidationsStartupTime"
+ units="milliseconds">
+ <summary>
+ Time since startup of the cloud policy code until the policy invalidation
+ service first reported its online status.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.PolicyLoadStatus" enum="EnterprisePolicyLoadStatus">
+ <summary>
+ Load status from the policy loaders which pull policy settings from the
+ underlying platform, such as Windows Group Policy.
+ </summary>
+</histogram>
+
+<histogram name="Enterprise.PolicyRefresh" enum="EnterprisePolicyRefresh">
+ <summary>
+ Events measuring effectiveness of refreshing policy when invalidations are
+ received from a service. For each refresh, indicates whether the policy
+ changed, and whether the policy was invalidated at the time of the refresh.
+ </summary>
+</histogram>
+
+<histogram name="Event.CoalescedCount.Mouse">
+ <summary>Number of Mouse events coalesced.</summary>
+</histogram>
+
+<histogram name="Event.CoalescedCount.Touch">
+ <summary>Number of Touch events coalesced.</summary>
+</histogram>
+
+<histogram name="Event.CoalescedLatency.Mouse" units="milliseconds">
+ <summary>
+ Time between the first and last events in a coalesced mouse events group.
+ </summary>
+</histogram>
+
+<histogram name="Event.CoalescedLatency.Touch" units="milliseconds">
+ <summary>
+ Time between the first and last events in a coalesced touch events group.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser" units="microseconds">
+ <summary>
+ Time between initiation of all input events and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_DROP_TARGET_EVENT"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_BEGIN" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_DOUBLE_TAP"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_END" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_LONG_PRESS"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_LONG_TAP"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_MULTIFINGER_SWIPE"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_PINCH_BEGIN"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_PINCH_END"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_PINCH_UPDATE"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_SCROLL_BEGIN"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_SCROLL_END"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_SCROLL_UPDATE"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_TAP" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_TAP_CANCEL"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_TAP_DOWN"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_GESTURE_TWO_FINGER_TAP"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_KEY_PRESSED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_KEY_RELEASED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_MOUSE_CAPTURE_CHANGED"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_MOUSE_DRAGGED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_MOUSE_ENTERED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_MOUSE_EXITED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_MOUSE_MOVED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_MOUSE_RELEASED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_MOUSEWHEEL" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_SCROLL" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_SCROLL_FLING_CANCEL"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_SCROLL_FLING_START"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_TOUCH_CANCELLED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_TOUCH_MOVED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_TOUCH_PRESSED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_TOUCH_RELEASED" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_TOUCH_STATIONARY"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_TRANSLATED_KEY_PRESS"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_TRANSLATED_KEY_RELEASE"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.ET_UNKNOWN" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.TouchAcked" units="microseconds">
+ <summary>
+ Time between touch events sent from RWH to renderer and acked by renderer.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Browser.TouchUI" units="microseconds">
+ <summary>
+ Time between touch events received by Chrome and sent from RWH to renderer.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer" units="microseconds">
+ <summary>
+ Time between initiation of all input events and renderer processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.Char" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.ContextMenu" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureDoubleTap" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureFlingCancel"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureFlingStart" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureLongPress" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureLongTap" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GesturePinchBegin" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GesturePinchEnd" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GesturePinchUpdate"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureScrollBegin"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureScrollEnd" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureScrollUpdate"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureTap" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureTapCancel" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureTapDown" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.GestureTwoFingerTap"
+ units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.KeyDown" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.KeyUp" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.MouseDown" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.MouseEnter" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.MouseLeave" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.MouseMove" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.MouseUp" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.MouseWheel" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.RawKeyDown" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.TouchCancel" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.TouchEnd" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.TouchMove" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.TouchStart" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.Renderer.Undefined" units="microseconds">
+ <summary>
+ Time between initiation of input event and browser processing.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.RendererImpl.GestureScroll" units="microseconds">
+ <summary>
+ Time between initial creation of touch event and the resulting ScrollGesture
+ reaches Impl thread.
+ </summary>
+</histogram>
+
+<histogram name="Event.Latency.TouchToScrollUpdateSwap" units="microseconds">
+ <summary>
+ Time between initial creation of touch event and the resulting frame from
+ ScrollUpdate is swapped.
+ </summary>
+</histogram>
+
+<histogram name="ExtensionBlacklist.BlacklistInstalled"
+ enum="ExtensionLocation">
+ <summary>
+ The number of extensions that were blacklisted when already installed,
+ grouped by Extension::Location. Logged when ExtensionService blackists and
+ unloads an installed extension.
+ </summary>
+</histogram>
+
+<histogram name="ExtensionBlacklist.BlockCRX" enum="ExtensionLocation">
+ <summary>
+ The number of extensions that have been blocked from installing grouped by
+ Extension::Location. Logged when ExtensionService refuses to install a
+ blacklisted extension.
+ </summary>
+</histogram>
+
+<histogram name="ExtensionBlacklist.SilentInstall" enum="ExtensionLocation">
+ <summary>
+ The number of extensions that have been silently installed in a blacklisted
+ state, grouped by Extension::Location. Logged when ExtensionService installs
+ a blacklisted extension without blocking it (ExtensionBlacklist.BlockCRX
+ would be logged otherwise). Typically this will be when a user has a
+ blacklisted extension synced.
+ </summary>
+</histogram>
+
+<histogram name="ExtensionBlacklist.UnblacklistInstalled"
+ enum="ExtensionLocation">
+ <summary>
+ The number of extensions that were unblacklisted when installed, grouped by
+ Extension::Location. Logged when ExtensionService unblacklists and loads a
+ blacklisted extension.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.AllocatePortIdPairOverflow">
+ <summary>
+ Records when the allocation of IDs for chrome.runtime.Port overflows.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.APIUse_RelativeURL" enum="UrlResolutionResult">
+ <summary>
+ Captures the results of URL resolution when relative urls are used in the
+ tabs/windows api.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.AppLaunch" enum="AppLaunch">
+ <summary>
+ The number of times v1 apps are launched grouped by
+ extension_misc::AppLaunchBuckets. See also Apps.AppLaunch for v2 apps.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.AppLaunchContainer" enum="AppLaunchContainer">
+ <summary>
+ The number of times apps are launched grouped by
+ extension_misc::LaunchContainer.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.AppLocation" enum="ExtensionLocation">
+ <summary>
+ The number of apps loaded at startup time grouped by Extension::Location.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.AppsPromo" enum="AppPromoAction">
+ <summary>
+ The actions taken in the NTP apps promo grouped by
+ extension_misc::AppsPromoBuckets.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.AppTabLaunchType" enum="ExtensionLaunchType">
+ <summary>
+ The number of apps launched grouped by ExtensionPrefs::LaunchType.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.BackgroundPageLoadTime" units="milliseconds">
+ <summary>The time for an extension's background page to load.</summary>
+</histogram>
+
+<histogram name="Extensions.BackgroundPageType"
+ units="ExtensionBackgroundPageType">
+ <summary>
+ The type (if any) of background page the extension has. Recorded for
+ installed extensions on startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.CrxFetchFailureRetryCountGoogleUrl">
+ <summary>
+ Number of times chrome retried to download an extension with a url on a
+ google.com domain, before eventually giving up.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.CrxFetchFailureRetryCountOtherUrl">
+ <summary>
+ Number of times chrome retried to download an extension with a url on a non
+ google.com domain, before eventually giving up.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.CrxFetchSuccessRetryCountGoogleUrl">
+ <summary>
+ Number of times chrome retried to download an extension with a url on a
+ google.com domain, before eventually succeeding.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.CrxFetchSuccessRetryCountOtherUrl">
+ <summary>
+ Number of times chrome retried to download an extension with a url on a non
+ google.com domain, before eventually succeeding.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.CrxInstallDirPathLength">
+ <summary>
+ Length of the path to the directory under which an extension is installed.
+ This directory is in the user's profile.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.DeclarativeRulesStorageInitialization"
+ units="milliseconds">
+ <summary>Time spent until rules storage delegate gets ready.</summary>
+</histogram>
+
+<histogram name="Extensions.DepricatedExternalJsonCount">
+ <summary>
+ Number of extensions referenced in the depricated external extensions source
+ at path chrome::DIR_DEPRICATED_EXTERNAL_EXTENSIONS.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.DialogLoadTime" units="milliseconds">
+ <summary>The time for a dialog-hosted extension to load.</summary>
+</histogram>
+
+<histogram name="Extensions.Disabled">
+ <summary>
+ The number of extensions that are disabled at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.DisabledForPermissions">
+ <summary>
+ The number of extensions that are disabled at browser startup due to
+ permissions increases.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.DisabledUIUserResponse"
+ enum="ExtensionDisabledUIUserResponse">
+ <summary>
+ User response to the dialog shown when an extension is disabled due to an
+ update requiring more permissions.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ErrorCodeFromCrxOpen">
+ <summary>
+ If opening the CRX file for unpacking fails, this integer is the error code
+ given by the OS.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.EventPageActiveTime" units="milliseconds">
+ <summary>The time an extension's event page has spent loaded.</summary>
+</histogram>
+
+<histogram name="Extensions.EventPageIdleTime" units="milliseconds">
+ <summary>The time an extension's event page has spent unloaded.</summary>
+</histogram>
+
+<histogram name="Extensions.EventPageLoadTime" units="milliseconds">
+ <summary>The time for an extension's event page to load.</summary>
+</histogram>
+
+<histogram name="Extensions.ExtensionInstalled">
+ <summary>An extension has been installed.</summary>
+</histogram>
+
+<histogram name="Extensions.ExtensionLocation" enum="ExtensionLocation">
+ <summary>
+ The number of extensions loaded at startup time grouped by
+ Extension::Location.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ExtensionRootPathLength">
+ <summary>
+ Length of the Extensions dir path inside the profile directory.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ExtensionUninstalled">
+ <summary>An extension has been uninstalled.</summary>
+</histogram>
+
+<histogram name="Extensions.ExternalExtensionEvent" enum="SideloadUIEvents">
+ <summary>
+ Records what happens to extensions that are sideloaded, grouped by the
+ ExternalExtensionEvent enum.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ExternalItemState" enum="ExternalItemState">
+ <summary>
+ The number of sideloaded apps/extensions loaded on startup grouped by
+ enabled/disabled state.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ExternalJsonCount">
+ <summary>
+ Number of extensions referenced in the external extensions source at path
+ chrome::DIR_EXTERNAL_EXTENSIONS.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.FromWebstoreInconsistency"
+ enum="ExtensionFromWebstoreInconcistencyEnum">
+ <summary>
+ Number of apps/extensions loaded on startup with an inconsistent &quot;from
+ webstore&quot; state. This means an item that is flagged as from_webstore,
+ but with either a non-webstore update_url or an external install location.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.FunctionCalls" enum="ExtensionFunctions">
+ <summary>Number of calls to extension functions.</summary>
+</histogram>
+
+<histogram name="Extensions.GetUserDataTempDir" enum="GetUserDataTempDirResult">
+ <summary>
+ What happens when the extensions system tries to get a temp dir to unpack
+ in?
+ </summary>
+</histogram>
+
+<histogram name="Extensions.InjectCssTime" units="milliseconds">
+ <summary>
+ The amount of time for a CSS file to be injected into a page.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.InjectEnd_ScriptCount">
+ <summary>Number of scripts injected at document end by extensions.</summary>
+</histogram>
+
+<histogram name="Extensions.InjectEnd_Time" units="milliseconds">
+ <summary>
+ Time taken to inject all scripts at document end by extensions.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.InjectIdle_ScriptCount">
+ <summary>Number of scripts injected at document idle by extensions.</summary>
+</histogram>
+
+<histogram name="Extensions.InjectIdle_Time" units="milliseconds">
+ <summary>
+ Time taken to inject all scripts at document idle by extensions.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.InjectScriptTime" units="milliseconds">
+ <summary>Time taken to inject all scripts by extensions.</summary>
+</histogram>
+
+<histogram name="Extensions.InjectStart_CssCount">
+ <summary>Number of css files injected by extensions.</summary>
+</histogram>
+
+<histogram name="Extensions.InjectStart_ScriptCount">
+ <summary>Number of scripts injected at document start by extensions.</summary>
+</histogram>
+
+<histogram name="Extensions.InjectStart_Time" units="milliseconds">
+ <summary>
+ Time taken to inject css/scripts at document start by extensions.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.InstallSource" enum="ExtensionLocation">
+ <summary>Installs grouped by the location property in prefs.</summary>
+</histogram>
+
+<histogram name="Extensions.InstallType" enum="ExtensionType">
+ <summary>Installs grouped by Extension::HistogramType.</summary>
+</histogram>
+
+<histogram name="Extensions.LoadAll">
+ <summary>
+ The number of extensions and themes loaded at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadAllTime" units="milliseconds">
+ <summary>Time taken to load all extensions at browser startup.</summary>
+</histogram>
+
+<histogram name="Extensions.LoadApp">
+ <summary>The number of apps loaded by each user at startup time.</summary>
+</histogram>
+
+<histogram name="Extensions.LoadAppExternal">
+ <summary>
+ The number of externally managed apps loaded by each user at startup time.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadAppUser">
+ <summary>
+ The number of user-installed apps loaded by each user at startup time.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadBrowserAction">
+ <summary>
+ The number of browser action extensions loaded at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadContentPack">
+ <summary>
+ The number of content-pack extensions loaded at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadExtension">
+ <summary>The number of extensions loaded at browser startup.</summary>
+</histogram>
+
+<histogram name="Extensions.LoadExtensionExternal">
+ <summary>
+ The number of externally managed extensions loaded at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadExtensionUser">
+ <summary>
+ The number of user-installed extensions loaded at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadExternal">
+ <summary>
+ The number of externally managed extensions and apps loaded at browser
+ startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadHostedApp">
+ <summary>
+ The number of hosted apps loaded by each user at startup time.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadPackagedApp">
+ <summary>
+ The number of legacy packaged apps loaded by each user at startup time.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadPageAction">
+ <summary>
+ The number of page action extensions loaded at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadPlatformApp">
+ <summary>The number of platform apps loaded at browser startup.</summary>
+</histogram>
+
+<histogram name="Extensions.LoadTheme">
+ <summary>The number of themes loaded at browser startup.</summary>
+</histogram>
+
+<histogram name="Extensions.LoadType" enum="ExtensionType">
+ <summary>
+ The number of extensions loaded at startup time grouped by
+ Extension::HistogramType.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.LoadUserScript">
+ <summary>
+ The number of converted user scripts loaded at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ManifestFetchFailureRetryCountGoogleUrl">
+ <summary>
+ Number of times chrome retried to download an extension update manifest with
+ a url on a google.com domain, before eventually giving up.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ManifestFetchFailureRetryCountOtherUrl">
+ <summary>
+ Number of times chrome retried to download an extension update manifest with
+ a url on a non google.com domain, before eventually giving up.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ManifestFetchSuccessRetryCountGoogleUrl">
+ <summary>
+ Number of times chrome retried to download an extension update manifest with
+ a url on a google.com domain, before eventually succeeding.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ManifestFetchSuccessRetryCountOtherUrl">
+ <summary>
+ Number of times chrome retried to download an extension update manifest with
+ a url on a non google.com domain, before eventually succeeding.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ManifestReloadNeedsRelocalization">
+ <summary>
+ Number of extension loads on startup where it is necessary to reload the
+ mainfest because the locale has changed.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ManifestReloadNotNeeded">
+ <summary>
+ Number of extension loads on startup where it is not necessary to reload the
+ extension's manifest.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ManifestReloadUnpackedDir">
+ <summary>
+ Number of extension loads on startup where it is necessary to reload the
+ manifest because the extension is unpacked.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.NetworkDelay" units="milliseconds">
+ <summary>Time that network requests were blocked due to extensions.</summary>
+</histogram>
+
+<histogram name="Extensions.NetworkDelayPercentage" units="%">
+ <summary>
+ Percentage of total lifetime a network request was blocked due to an
+ extension.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.NetworkDelayRegistryLoad" units="milliseconds">
+ <summary>
+ Time that network requests were blocked due to relevant rule registries
+ loading.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.NonWebstoreLocation" enum="ExtensionLocation">
+ <summary>
+ The number of apps/extensions with a non-webstore update_url loaded at
+ startup time grouped by Extension::Location.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.NonWebStoreNewTabPageOverrides">
+ <summary>
+ Number of non-WebStore extensions on startup that override the new tab page.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_AutoDisable" enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when it is automatically disabled
+ due to a permission increase (e.g., after an extension upgrade).
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_Install" enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when it was installed.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_InstallAbort"
+ enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when installation was aborted, not
+ including installation errors and user cancels.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_InstallCancel"
+ enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when installation was canceled.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_Load" enum="ExtensionPermission">
+ <summary>The permissions present in an extension when it was loaded.</summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_ReEnable" enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when it was re-enabled from a
+ confirmation prompt.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_ReEnableAbort"
+ enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when the re-enable prompt was
+ aborted, not including installation errors and manual user cancels.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_ReEnableCancel"
+ enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when the re-enable was canceled from
+ the confirmation prompt.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_Uninstall" enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when it was uninstalled.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_WebStoreInstall"
+ enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when it was installed through the
+ web store.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_WebStoreInstallAbort"
+ enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when installation from the web store
+ was aborted, not including installation errors and user cancels.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.Permissions_WebStoreInstallCancel"
+ enum="ExtensionPermission">
+ <summary>
+ The permissions present in an extension when installation from the web store
+ was canceled.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackFailure">
+ <summary>
+ Count the number of times a sandboxed extension unpack fails.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackFailureReason"
+ enum="ExtensionUnpackFailureReason">
+ <summary>What caused a sandboxed extension unpack to fail?</summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackFailureTime">
+ <summary>Time taken to unpack an extension, when the unpack fails.</summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackInitialCrxPathLength">
+ <summary>Length of the initial path to the CRX to be unpacked.</summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackLinkFreeCrxPathLength">
+ <summary>
+ Length of the normalized (link/junction free) path to the temporary copy of
+ a CRX made during unpacking.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackRate">
+ <summary>
+ Rate at which a CRX file is unpacked in Kilobytes per second.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackRate1To2mB">
+ <summary>
+ Rate at which CRX files 1MB to 2MB are unpacked in Kilobytes per second.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackRate2To5mB">
+ <summary>
+ Rate at which CRX files 2MB to 5MB are unpacked in Kilobytes per second.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackRate50kBTo1mB">
+ <summary>
+ Rate at which CRX files 50kB to 1MB are unpacked in Kilobytes per second.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackRate5To10mB">
+ <summary>
+ Rate at which CRX files 5MB to 10 MB are unpacked in Kilobytes per second.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackRateOver10mB">
+ <summary>
+ Rate at which CRX files larger than 10MB are unpacked in Kilobytes per
+ second.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackRateUnder50kB">
+ <summary>
+ Rate at which CRX files under 50 KB are unpacked in Kilobytes per second.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackSuccess">
+ <summary>Count the number of times a sandboxed CRX unpack succeeds.</summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackSuccessCantGetCrxSize">
+ <summary>
+ Count the number of times a sandboxed CRX unpack succeeds, but we can't get
+ the file size.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackSuccessTime">
+ <summary>
+ Time taken to unpack an extension, when the unpack succeeds.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackTempCrxPathLength">
+ <summary>
+ Length of the path of the temporary copy of a CRX made during unpacking.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.SandboxUnpackUnpackedCrxPathLength">
+ <summary>Length of the path under which a CRX is unpacked.</summary>
+</histogram>
+
+<histogram name="Extensions.StartupDelay" units="milliseconds">
+ <summary>The time one extension delays network requests at startup.</summary>
+</histogram>
+
+<histogram name="Extensions.StartupDelay_Total" units="milliseconds">
+ <summary>
+ The total time extensions delay network requests at startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ToolstripLoadTime" units="milliseconds">
+ <summary>Time taken to load a toolstrip.</summary>
+</histogram>
+
+<histogram name="Extensions.UninstallType" enum="ExtensionType">
+ <summary>Uninstalls grouped by Extension::HistogramType.</summary>
+</histogram>
+
+<histogram name="Extensions.UnpackFailureInstallCause"
+ enum="ExtensionInstallCause">
+ <summary>
+ Count failing CRX installs, grouped by the way an extension can be
+ installed.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UnpackFailureInstallSource"
+ enum="ExtensionLocation">
+ <summary>
+ Count successful CRX installs, grouped by the location property in prefs.
+ installed.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UnpackSuccessInstallCause"
+ enum="ExtensionInstallCause">
+ <summary>
+ Count successful CRX installs, grouped by the cause of the install.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UnpackSuccessInstallSource"
+ enum="ExtensionLocation">
+ <summary>
+ Count successful CRX installs, grouped by the location property in prefs.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateCheckApp">
+ <summary>
+ The number of legacy packaged apps and hosted apps that were checked during
+ an update check.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateCheckExtension">
+ <summary>
+ The number of extensions that were checked during an update check.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateCheckGap" units="minutes">
+ <summary>Time in minutes between update checks.</summary>
+</histogram>
+
+<histogram name="Extensions.UpdateCheckGoogleUrl">
+ <summary>
+ The number of crx's with a Google-hosted update URL that were checked during
+ an update check.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateCheckNoUrl">
+ <summary>
+ The number of crx's with no update URL checked during an update check.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateCheckOtherUrl">
+ <summary>
+ The number of crx's with a non-Google update URL that were checked during an
+ update check.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateCheckPackagedApp">
+ <summary>
+ The number of packaged apps that were checked during an update check.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateCheckTheme">
+ <summary>
+ The number of themes that were checked during an update check.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateOnLoad">
+ <summary>
+ The number of extensions that were updated at browser startup.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdaterWriteCrx" enum="ExtensionFileWriteResult">
+ <summary>
+ What happened when the extension updater tried to write a file?
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateSource" enum="ExtensionLocation">
+ <summary>Updates grouped by the location property in prefs.</summary>
+</histogram>
+
+<histogram name="Extensions.UpdateType" enum="ExtensionType">
+ <summary>Updates grouped by Extension::HistogramType.</summary>
+</histogram>
+
+<histogram name="FileBrowser.Create" enum="FileDialogType">
+ <summary>Chrome OS File Browser opening mode.</summary>
+</histogram>
+
+<histogram name="FileBrowser.DirectoryScan" units="milliseconds">
+ <summary>
+ Chrome OS File Browser: time to scan a directory. Measured on every File
+ Browser directory change.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.DownloadDestination.IsGoogleDrive.Changed"
+ enum="BooleanEnabled">
+ <summary>
+ Tracks whether download destination is set to a Google Drive folder when the
+ download destination is changed by the user in the settings page.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.DownloadDestination.IsGoogleDrive.Started"
+ enum="BooleanEnabled">
+ <summary>
+ Tracks whether download destination is set to a Google Drive folder on
+ startup.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.DownloadsCount">
+ <summary>
+ Chrome OS File Browser: number of files and directories in the Downloads
+ directory (not including the contents of nested directories). Computed every
+ time the File Browser current directory changes to Downloads.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.FolderShortcut.Add">
+ <summary>
+ Chrome OS File Browser: this is recorded when the user adds a folder
+ shortcut.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.FolderShortcut.Count">
+ <summary>
+ Chrome OS File Browser: number of saved folder shorcuts. This is recorded
+ when Files.app is launched.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.FolderShortcut.Navigate">
+ <summary>
+ Chrome OS File Browser: this is recorded when the user clicks or selects a
+ folder shortcut and is navigated to the target folder.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.FolderShortcut.Remove">
+ <summary>
+ Chrome OS File Browser: this is recorded when the user removes a folder
+ shortcut.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.Load" units="milliseconds">
+ <summary>
+ Chrome OS File Browser is an built-in extension without a background page.
+ Its main.html file is loaded every time the user opens a File Browser tab or
+ a file chooser dialog. The file is fairly large and the initialization is
+ pretty expensive.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.OpeningFileType" enum="FileType">
+ <obsolete>
+ Deprecated 4/2013, and replaced by FileBrowser.ViewingFileType.
+ </obsolete>
+ <summary>File types that were tried to be opened through browser.</summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.DisplayTime" units="milliseconds">
+ <summary>
+ Chrome OS Photo Editor: time to display an image. Measured from the moment
+ the user selected the image till the moment it is displayed (not counting
+ the low resolution preview).
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.FileType" enum="PhotoEditorFileType">
+ <summary>Chrome OS Photo Editor: the type of the file opened.</summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.LoadMode" enum="PhotoEditorLoadMode">
+ <summary>Chrome OS Photo Editor: the way the image has been loaded.</summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.LoadTime" units="milliseconds">
+ <summary>Chrome OS Photo Editor: time to load an image from a file.</summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.SaveResult"
+ enum="PhotoEditorSaveResult">
+ <summary>
+ Chrome OS Photo Editor: the result of a file save operation.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.SaveTime" units="milliseconds">
+ <summary>Chrome OS Photo Editor: time to save an image to a file.</summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.Size.MB" units="MBytes">
+ <summary>
+ Chrome OS Photo Editor: size of an image file in megabytes. Measured on
+ every image load.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.Size.MPix" units="MPixels">
+ <summary>
+ Chrome OS Photo Editor: size of an image in megapixels. Measured on every
+ image load.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoEditor.Tool" enum="PhotoEditorToolType">
+ <summary>Chrome OS Photo Editor: the button which the user clicked.</summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoImport.Action" enum="ExternalDeviceAction">
+ <summary>
+ Chrome OS Photo Import flow: action chosen in the Action Choice dialog for
+ the external device.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoImport.ImportCount">
+ <summary>
+ Chrome OS Photo Import flow: the number of photos imported. Measured on
+ every successfull import operation.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoImport.ImportPercentage">
+ <summary>
+ Chrome OS Photo Import flow: the percent of photos imported among all the
+ photos on the device. Measured on every successfull import operation.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoImport.Load" units="milliseconds">
+ <summary>
+ Chrome OS Photo Import flow: time to load the action dialog. Measured
+ between the moment window appears and the moment user see all available
+ actions for the device.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.PhotoImport.Scan" units="milliseconds">
+ <summary>
+ Chrome OS Photo Import flow: time to scan the external device.
+ </summary>
+</histogram>
+
+<histogram name="FileBrowser.ViewingFileType" enum="ViewFileType">
+ <summary>
+ File types that were tried to be viewed through browser. This is recorded
+ when the user tries to view a file from Files.app.
+ </summary>
+</histogram>
+
+<histogram name="GData.AuthSuccess" enum="GDataAuthResult">
+ <summary>Result of the authentication for Drive.</summary>
+</histogram>
+
+<histogram name="GData.EntireFeedLoadTime" units="microseconds">
+ <obsolete>
+ Deprecated 9/2012, and replaced by Drive.EntireFeedLoadTime
+ </obsolete>
+ <summary>
+ Time spent to load the entire file system information from the server
+ </summary>
+</histogram>
+
+<histogram name="GData.EntryKind" enum="GDataEntryKind">
+ <obsolete>
+ Deprecated 9/2012, and replaced by Drive.EntryKind
+ </obsolete>
+ <summary>
+ Provides breakdown of specific formats for hosted documents. Recorded when
+ feed is loaded from the server.
+ </summary>
+</histogram>
+
+<histogram name="GData.InitialFeedLoadTime" units="microseconds">
+ <obsolete>
+ Deprecated 9/2012, and replaced by Drive.InitialFeedLoadTime
+ </obsolete>
+ <summary>
+ Time spent to load the initial part of the file system information from the
+ server
+ </summary>
+</histogram>
+
+<histogram name="GData.NumberOfHostedDocuments">
+ <obsolete>
+ Deprecated 9/2012, and replaced by Drive.NumberOfHostedDocuments
+ </obsolete>
+ <summary>
+ Number of hosted documents (spreadsheets etc.) on Drive. Logged when Drive
+ is first accessed.
+ </summary>
+</histogram>
+
+<histogram name="GData.NumberOfRegularFiles">
+ <obsolete>
+ Deprecated 9/2012, and replaced by Drive.NumberOfRegularFiles
+ </obsolete>
+ <summary>
+ Number of regualr files on Drive. Logged when Drive is first accessed.
+ </summary>
+</histogram>
+
+<histogram name="GData.NumberOfTotalFiles">
+ <obsolete>
+ Deprecated 9/2012, and replaced by Drive.NumberOfTotalFiles
+ </obsolete>
+ <summary>
+ Number of total files (regualr files + hosted documents) on Drive. Logged
+ when Drive is first accessed.
+ </summary>
+</histogram>
+
+<histogram name="GoogleNow.Event" enum="GoogleNowEvent">
+ <summary>Events in Google Now component extension.</summary>
+</histogram>
+
+<histogram name="History.TopSitesVisitsByRank" units="rank">
+ <summary>
+ Page visits to each of a user's top 50 sites. Visits to all other sites go
+ into the 51st bucket. Only count the page visit if it came from user
+ browsing and only count it once when cycling through a redirect chain.
+ </summary>
+</histogram>
+
+<histogram name="HistoryPage.ClickPosition">
+ <summary>
+ Number of entries that the clicked entry is older than in History page. Last
+ bucket is any entry of that value or higher.
+ </summary>
+</histogram>
+
+<histogram name="HistoryPage.ClickPositionSubset">
+ <summary>
+ Subset of the Click Position histogram. Contains only the first smaller
+ subset of entries on the page. Number of entries that the clicked entry is
+ older than in History page. Last bucket is entries of that value or higher.
+ </summary>
+</histogram>
+
+<histogram name="HistoryPage.OtherDevicesMenu" enum="NtpOtherSessionsType">
+ <summary>
+ Histogram for usage of the section in the history page that allows the user
+ to access tabs from other devices.
+ </summary>
+</histogram>
+
+<histogram name="HistoryPage.RemoveEntryPosition">
+ <summary>
+ Number of entries that the deleted entry is older than in History page. Last
+ bucket is any entry of that value or higher. Confirmed removal is not
+ guaranteed, just an initiation of 'Remove selected items'.
+ </summary>
+</histogram>
+
+<histogram name="HistoryPage.RemoveEntryPositionSubset">
+ <summary>
+ Subset of Remove Entry Position histogram. Contains only the first smaller
+ subset of entries on the page. Number of entries that the deleted entry is
+ older than in History page. Last bucket is any entry of that value or
+ higher. Confirmed removal is not guaranteed, just an initiation of 'Remove
+ selected items'.
+ </summary>
+</histogram>
+
+<histogram name="HttpCache.EntryLockWait" units="milliseconds">
+ <summary>
+ The time spent waiting for write lock on a disk cache entry.
+ </summary>
+</histogram>
+
+<histogram name="HttpCache.OfflineStatus" enum="OfflineStatus">
+ <summary>
+ Result of a main page HttpCacheTransaction if offline mode had been enabled.
+ </summary>
+</histogram>
+
+<histogram name="HttpCache.ReadErrorNonRestartable" enum="NetErrorCodes">
+ <summary>Net error results from non-restartable cache read errors.</summary>
+</histogram>
+
+<histogram name="HttpCache.ReadErrorRestartable" enum="NetErrorCodes">
+ <summary>Net error results from restartable cache read errors.</summary>
+</histogram>
+
+<histogram name="Import.ImporterType.AutoImport" enum="ImporterType">
+ <summary>The importer used on first run Auto Import.</summary>
+</histogram>
+
+<histogram name="Import.ImporterType.BookmarksAPI" enum="ImporterType">
+ <summary>The importer used on import from the bookmarks file API.</summary>
+</histogram>
+
+<histogram name="Import.ImporterType.ImportDataHandler" enum="ImporterType">
+ <summary>
+ The importer used on import from the chrome://settings/importData UI.
+ </summary>
+</histogram>
+
+<histogram name="Import.ShowDialog.FromBookmarkBarView" units="seconds">
+ <summary>
+ The amount of time from install time to time that user opens import dialog
+ from BookmarkBarView.
+ </summary>
+</histogram>
+
+<histogram name="Import.ShowDialog.FromFloatingBookmarkBarView" units="seconds">
+ <summary>
+ The amount of time from install time to time that user opens import dialog
+ from NTP floating BookmarkBarView.
+ </summary>
+</histogram>
+
+<histogram name="Import_ShowDlg.FromBookmarkBarView" units="seconds">
+ <obsolete>
+ Deprecated and replaced by Import.ShowDialog.FromBookmarkBarView
+ </obsolete>
+ <summary>
+ The amount of time from install time to time that user opens import dialog
+ from BookmarkBarView.
+ </summary>
+</histogram>
+
+<histogram name="Import_ShowDlg.FromFloatingBookmarkBarView" units="seconds">
+ <obsolete>
+ Deprecated and replaced by Import.ShowDialog.FromFloatingBookmarkBarView
+ </obsolete>
+ <summary>
+ The amount of time from install time to time that user opens import dialog
+ from NTP floating BookmarkBarView.
+ </summary>
+</histogram>
+
+<histogram name="Installer.DevModeErrorCodes" enum="UpdateEngineErrorCode">
+ <summary>Errors from update_engine process when running in dev mode.</summary>
+</histogram>
+
+<histogram name="Installer.DownloadOverheadPercentage" units="%">
+ <summary>
+ The overhead in downloading extra bytes due to errors/interruptions.
+ Expressed as a percentage of the bytes that are actually needed to be
+ downloaded for the update to be successful.
+ </summary>
+</histogram>
+
+<histogram name="Installer.DownloadSourcesUsed"
+ enum="UpdateEngineDownloadSources">
+ <summary>
+ The combinations of protocol and source server that were used to complete a
+ successful update.
+ </summary>
+</histogram>
+
+<histogram name="Installer.NormalErrorCodes" enum="UpdateEngineErrorCode">
+ <summary>
+ Errors from update_engine process when running in normal mode.
+ </summary>
+</histogram>
+
+<histogram name="Installer.SuccessfulMBsDownloadedFrom" units="MB">
+ <summary>
+ Number of MBs downloaded from during an update that completed successfully.
+ </summary>
+</histogram>
+
+<histogram name="Installer.TotalMBsDownloadedFrom" units="MB">
+ <summary>
+ Total number of MBs downloaded since the last successful update. This also
+ includes all the bytes downloaded during any prior failed attempts.
+ </summary>
+</histogram>
+
+<histogram name="Installer.UpdateDurationMinutes" units="Minutes">
+ <summary>
+ Absolute wallclock time duration it took for the update to complete from the
+ time an update first began. It includes not just the time the device was
+ up, but also includes the time the device spent sleeping.
+ </summary>
+</histogram>
+
+<histogram name="Installer.UpdateDurationUptimeMinutes" units="Minutes">
+ <summary>
+ Uptime duration it took for the update to complete from the time an update
+ first began. It does not include the time the device spent sleeping, but it
+ does include the uptime spent in waiting for the hourly update checks to
+ happen.
+ </summary>
+</histogram>
+
+<histogram name="Installer.UpdateNumReboots" units="count">
+ <summary>
+ Number of times the device was rebooted by the user since an update began
+ and until it completed successfully.
+ </summary>
+</histogram>
+
+<histogram name="Installer.UpdateURLSwitches" units="count">
+ <summary>
+ Number of times the download URLs were switched due to failures.
+ </summary>
+</histogram>
+
+<histogram name="Instant.InstantControllerEvent" enum="InstantControllerEvent">
+ <summary>
+ Records various events of interest in the InstantController. E.g. When URLs
+ are blacklisted.
+ </summary>
+</histogram>
+
+<histogram name="Instant.SessionsStorageNamespace"
+ enum="InstantSessionStorageNamespace">
+ <summary>
+ How often an Instant preview is committed onto a different tab than it was
+ created from.
+ </summary>
+</histogram>
+
+<histogram name="Instant.TimeToFirstShow" units="milliseconds">
+ <summary>
+ The time between the first Omnibox interaction and when the Instant preview
+ shows. If the instant preview was already showing when the user interacted
+ with the omnibox, this histogram is not recorded.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.FallbackToLocalOverlay"
+ enum="InstantExtended_FallbackCause">
+ <summary>
+ Records the cause for falling back to a local overlay at the time of
+ fallback.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.InstantNavigation"
+ enum="InstantExtended_InstantNavigation">
+ <summary>
+ Records a histogram for instant extended (Local NTP and Online NTP) and
+ non-extended navigations.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.NewOptInState"
+ enum="InstantExtended_NewOptInState">
+ <summary>
+ Records, on startup, whether the user has chosen to opt-in to or opt-out of
+ InstantExtended via chrome://flags.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.OptInState" enum="InstantExtended_OptInState">
+ <obsolete>
+ Deprecated 2013-06. As of m30 use InstantExtended.NewOptInState.
+ </obsolete>
+ <summary>
+ Records, on startup, whether the user has chosen to opt-in to or opt-out of
+ InstantExtended via chrome://flags.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PercentageMatchQuerytoQuery" units="%">
+ <obsolete>
+ Deprecated 2013-07. Please see
+ InstantExtended.PercentageMatchV2_QuerytoQuery instead.
+ </obsolete>
+ <summary>
+ Records the number of matching characters at the start of the user's text as
+ a percentage of average length between the old and new text when the user
+ navigates from a search query to another search query.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PercentageMatchQuerytoURL" units="%">
+ <obsolete>
+ Deprecated 2013-07. Please see InstantExtended.PercentageMatchV2_QuerytoURL
+ instead.
+ </obsolete>
+ <summary>
+ Records the number of matching characters at the start of the user's text as
+ a percentage of average length between the old and new text when the user
+ navigates from a search query to a url. Example: Accidental search for
+ google.con, then navigation to google.com.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PercentageMatchURLtoQuery" units="%">
+ <obsolete>
+ Deprecated 2013-07. Please see InstantExtended.PercentageMatchV2_URLtoQuery
+ instead.
+ </obsolete>
+ <summary>
+ Records the number of matching characters at the start of the user's text as
+ a percentage of average length between the old and new text when the user
+ navigates from a url to a search query.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PercentageMatchURLtoURL" units="%">
+ <obsolete>
+ Deprecated 2013-07. Please see InstantExtended.PercentageMatchV2_URLtoURL
+ instead.
+ </obsolete>
+ <summary>
+ Records the number of matching characters at the start of the user's text as
+ a percentage of average length between the old and new text when the user
+ navigates from a url to another url.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PercentageMatchV2_QuerytoQuery" units="%">
+ <summary>
+ Records the number of matching characters at the start of the user's text as
+ a percentage of average length between the old and new text when the user
+ navigates from a search query to another search query.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PercentageMatchV2_QuerytoURL" units="%">
+ <summary>
+ Records the number of matching characters at the start of the user's text as
+ a percentage of average length between the old and new text when the user
+ navigates from a search query to a url. Example: Accidental search for
+ google.con, then navigation to google.com.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PercentageMatchV2_URLtoQuery" units="%">
+ <summary>
+ Records the number of matching characters at the start of the user's text as
+ a percentage of average length between the old and new text when the user
+ navigates from a url to a search query.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PercentageMatchV2_URLtoURL" units="%">
+ <summary>
+ Records the number of matching characters at the start of the user's text as
+ a percentage of average length between the old and new text when the user
+ navigates from a url to another url.
+ </summary>
+</histogram>
+
+<histogram name="InstantExtended.PrefValue" enum="BooleanEnabled">
+ <obsolete>
+ Deprecated 2013-06. This preference has not been exposed or used for months,
+ and we do not plan to use it in the future.
+ </obsolete>
+ <summary>
+ Records, on startup, the value of the &quot;Allow your search engine to
+ provide Instant result&quot; preference setting for the first profile
+ loaded.
+ </summary>
+</histogram>
+
+<histogram name="interstitial.authority_invalid_time" units="milliseconds">
+ <obsolete>
+ Removed on 8/1/13.
+ </obsolete>
+ <summary>
+ The time between the SSL interstitial display and the user decision, which
+ may be either accept or deny. This is only recorded for overridable SSL
+ warnings with a CERT_AUTHORITY_INVALID warning. Timing begins when user
+ first focuses on the page.
+ </summary>
+</histogram>
+
+<histogram name="interstitial.common_name_invalid_time" units="milliseconds">
+ <obsolete>
+ Removed on 8/1/13.
+ </obsolete>
+ <summary>
+ The time between the SSL interstitial display and the user decision, which
+ may be either accept or deny. This is only recorded for overridable SSL
+ warnings with a CERT_COMMON_NAME_INVALID warning. Timing begins when user
+ first focuses on the page.
+ </summary>
+</histogram>
+
+<histogram name="interstitial.date_invalid_time" units="milliseconds">
+ <obsolete>
+ Removed on 8/1/13.
+ </obsolete>
+ <summary>
+ The time between the SSL interstitial display and the user decision, which
+ may be either accept or deny. This is only recorded for overridable SSL
+ warnings with a CERT_DATE_INVALID warning. Timing begins when user first
+ focuses on the page.
+ </summary>
+</histogram>
+
+<histogram name="interstitial.ssl" enum="SSLResponseTypesV2">
+ <summary>
+ User action when the user is shown a SSL interstitial. SHOW_ALL and MORE
+ refer to the total number of SSL errors; all of the other numbers pertain to
+ the number of actions related to SSL errors that are overridable. The
+ counts do not sum to 100%; SHOW_ALL is a superset of SHOW_OVERRIDABLE, which
+ in turn will be a supserset of the PROCEED/DONT_PROCEED variables.
+ SHOW_UNDERSTAND is only being used by an experimental field trial.
+ </summary>
+</histogram>
+
+<histogram name="interstitial.ssl_accept_time" units="milliseconds">
+ <obsolete>
+ Removed on 8/1/13.
+ </obsolete>
+ <summary>
+ The time between the SSL interstitial display and the user decision, when
+ the user accepts the SSL warning. This is only recorded for overridable SSL
+ warnings. Timing begins when user first focuses on the page.
+ </summary>
+</histogram>
+
+<histogram name="interstitial.ssl_error_type" enum="SSLErrorTypes">
+ <summary>
+ The type of SSL error that the user encounters. This is recorded for all
+ SSL warnings, regardless of whether they are overridable.
+ </summary>
+</histogram>
+
+<histogram name="interstitial.ssl_reject_time" units="milliseconds">
+ <obsolete>
+ Removed on 8/1/13.
+ </obsolete>
+ <summary>
+ The time between the SSL interstitial display and the user decision, when
+ the user rejects the SSL warning. This is only recorded for overridable SSL
+ warnings. Timing begins when user first focuses on the page.
+ </summary>
+</histogram>
+
+<histogram name="LanguageUsage.AcceptLanguage" enum="LanguageCode">
+ <summary>Accept languages.</summary>
+</histogram>
+
+<histogram name="LanguageUsage.ApplicationLanguage" enum="LanguageCode">
+ <summary>Application languages used for UI.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.All.SafeThreadAccess" units="accesses">
+ <summary>
+ Linux and CrOS use unlocked_stdio(3). If it is used unsafely, record it
+ here. If there is no record of unsafety after chrome 29 has been in the
+ stable channel for a few weeks then revert this change.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.IOError" enum="LevelDBIOErrorMethods">
+ <summary>
+ Methods where leveldb's Chromium environment has IO errors when being used
+ by IndexedDB.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.IOError." enum="PlatformFileError">
+ <summary>
+ PlatformFileErrors encountered by a single leveldb env method.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.IOError.NewLogger" enum="OSAgnosticErrno">
+ <summary>Errno of errors encountered in NewLogger.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.IOError.NewSequentialFile"
+ enum="OSAgnosticErrno">
+ <summary>Errno of errors encountered in NewSequentialFile.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.IOError.RandomAccessFile"
+ enum="PlatformFileError">
+ <obsolete>
+ Deprecated 2013-04. As of m28 use
+ LevelDBEnv.IDB.IOError.NewRandomAccessFile.
+ </obsolete>
+ <summary>File errors in leveldb IDBEnv's NewRandomAccessFile method.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.IOError.WritableFileAppend"
+ enum="OSAgnosticErrno">
+ <summary>Errno of errors encountered in WritableFileAppend.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.IOError.WritableFileFlush"
+ enum="OSAgnosticErrno">
+ <summary>Errno of errors encountered in WritableFileFlush.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.LockFileAncestorsNotFound" units="directories">
+ <summary>
+ Number of directories missing when IDB LevelDBEnv tries to create a Lock
+ file.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.MaxFDs" units="files">
+ <summary>
+ File descriptor limit recorded every time LevelDB calls NewRandomAccessFile
+ for IndexedDB.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.RetryRecoveredFromErrorIn"
+ enum="PlatformFileError">
+ <summary>
+ When IDB LevelDBEnv successfully retries an operation that had failed,
+ record the error from the most recent failed attempt.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.TimeTo" units="milliseconds">
+ <obsolete>
+ Deprecated 2013-04. As of m28 use LevelDBEnv.IDB.TimeUntilSuccessFor.
+ </obsolete>
+ <summary>
+ Time IDB LevelDBEnv slept before successfully completing this operation. 0
+ means success on the first try.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IDB.TimeUntilSuccessFor" units="milliseconds">
+ <summary>
+ Time IDB LevelDBEnv slept before successfully completing this operation. 0
+ means success on the first try.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IOError" enum="LevelDBIOErrorMethods">
+ <summary>Methods where leveldb's Chromium environment has IO errors.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IOError." enum="PlatformFileError">
+ <summary>PlatformFileErrors encountered by a single leveldb method.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IOError.NewLogger" enum="OSAgnosticErrno">
+ <summary>Errno of errors encountered in NewLogger.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IOError.NewSequentialFile" enum="OSAgnosticErrno">
+ <summary>Errno of errors encountered in NewSequentialFile.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IOError.RandomAccessFile" enum="PlatformFileError">
+ <obsolete>
+ Deprecated 2013-04. As of m28 use LevelDBEnv.IOError.NewRandomAccessFile.
+ </obsolete>
+ <summary>
+ File errors in leveldb ChromiumEnv's NewRandomAccessFile method.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IOError.WritableFileAppend" enum="OSAgnosticErrno">
+ <summary>Errno of errors encountered in WritableFileAppend.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.IOError.WritableFileFlush" enum="OSAgnosticErrno">
+ <summary>Errno of errors encountered in WritableFileFlush.</summary>
+</histogram>
+
+<histogram name="LevelDBEnv.LockFileAncestorsNotFound" units="directories">
+ <summary>
+ Number of directories missing when Non-IDB LevelDBEnv tries to create a Lock
+ file.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.MaxFDs" units="files">
+ <summary>
+ File descriptor limit recorded every time LevelDB calls NewRandomAccessFile
+ for clients other than IndexedDB.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.RetryRecoveredFromErrorIn" enum="PlatformFileError">
+ <summary>
+ When Non-IDB LevelDBEnv successfully retries an operation that had failed,
+ record the error from the most recent failed attempt.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.TimeTo" units="milliseconds">
+ <obsolete>
+ Deprecated 2013-04. As of m28 use LevelDBEnv.TimeUntilSuccessFor.
+ </obsolete>
+ <summary>
+ Time Non-IDB LevelDBEnv slept before successfully completing this operation.
+ 0 means success on the first try.
+ </summary>
+</histogram>
+
+<histogram name="LevelDBEnv.TimeUntilSuccessFor" units="milliseconds">
+ <summary>
+ Time Non-IDB LevelDBEnv slept before successfully completing this operation.
+ 0 means success on the first try.
+ </summary>
+</histogram>
+
+<histogram name="Linux.GlibcVersion" enum="LinuxGlibcVersion">
+ <summary>The version of glibc used. (Linux only)</summary>
+</histogram>
+
+<histogram name="Media.AcceleratedCompositingActive" enum="BooleanSuccess">
+ <summary>
+ Whether accelerated compositing was used for HTML5 media rendering.
+ </summary>
+</histogram>
+
+<histogram name="Media.AudioBitsPerChannel">
+ <summary>Bits per channel of HTML5 audio sample data.</summary>
+</histogram>
+
+<histogram name="Media.AudioChannelLayout" enum="ChannelLayout">
+ <summary>Audio channel layout in HTML5 media.</summary>
+</histogram>
+
+<histogram name="Media.AudioCodec" enum="AudioCodec">
+ <summary>Audio codec used in HTML5 media.</summary>
+</histogram>
+
+<histogram name="Media.AudioInputController" units="ms">
+ <summary>Measures the time taken for AudioInputController::</summary>
+</histogram>
+
+<histogram name="Media.AudioInputDeviceManager" units="ms">
+ <summary>Measures the time taken for AudioInputDeviceManager::</summary>
+</histogram>
+
+<histogram name="Media.AudioOutputController" units="ms">
+ <summary>Measures the time taken for AudioOutputController::</summary>
+</histogram>
+
+<histogram name="Media.AudioOutputControllerDataNotReady" units="ms">
+ <summary>
+ Time spent waiting in AudioOutputController::WaitTillDataReady() if the data
+ was not initially available.
+ </summary>
+</histogram>
+
+<histogram name="Media.AudioRendererEvents" enum="AudioRendererEvents">
+ <summary>Captures statistics for various AudioRendererImpl events.</summary>
+</histogram>
+
+<histogram name="Media.AudioRendererMissedDeadline" units="%">
+ <summary>
+ Percentage of AudioSyncReader::Read() calls where the renderer missed its
+ realtime deadline.
+ </summary>
+</histogram>
+
+<histogram name="Media.AudioSampleFormat" enum="AudioSampleFormat">
+ <summary>
+ Audio sample format in HTML5 media. Logged when Audio Decoder initializes.
+ </summary>
+</histogram>
+
+<histogram name="Media.AudioSamplesPerSecond" enum="AudioSampleRate">
+ <summary>Audio samples per second in HTML5 media.</summary>
+</histogram>
+
+<histogram name="Media.AudioSamplesPerSecondUnexpected" units="Hz">
+ <summary>
+ Audio samples per second in HTML5 media (atypical values, in Hz).
+ </summary>
+</histogram>
+
+<histogram name="Media.CacheUseful" enum="BooleanSuccess">
+ <summary>
+ Whether a media response might be used to satisfy a future request.
+ </summary>
+</histogram>
+
+<histogram name="Media.ChromeCast.DelayedAndDroppedFramesPer5Sec"
+ units="frames/5s">
+ <summary>
+ The average number of delayed and dropped frames for the ChromeCast
+ application. Reported every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.ChromeCast.DisplayedFramesPerSecond" units="frames/s">
+ <summary>
+ The average number of displayed frames for the ChromeCast application.
+ Reported every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.ChromeCast.TimeToBufferAv" units="ms">
+ <summary>
+ Time needed to pre-buffer A/V data before the actual playback for the
+ ChromeCast application.
+ </summary>
+</histogram>
+
+<histogram name="Media.ChromeCast.TimeToBufferAvAfterAbort" units="ms">
+ <summary>
+ Time needed to buffer A/V data after an abort for the ChromeCast
+ application.
+ </summary>
+</histogram>
+
+<histogram name="Media.ChromeCast.TimeToBufferAvAfterUnderrun" units="ms">
+ <summary>
+ Time needed to buffer A/V data after an underrun for the ChromeCast
+ application.
+ </summary>
+</histogram>
+
+<histogram name="Media.DetectedAudioCodec" enum="FFmpegCodecs">
+ <summary>Audio codec used in HTML5 media.</summary>
+</histogram>
+
+<histogram name="Media.DetectedContainer" enum="MediaContainers">
+ <summary>Container used for HTML5 media.</summary>
+</histogram>
+
+<histogram name="Media.DetectedVideoCodec" enum="FFmpegCodecs">
+ <summary>Video codec used in HTML5 media.</summary>
+</histogram>
+
+<histogram name="Media.DevicePermissionActions" enum="DevicePermissionActions">
+ <summary>
+ Measures the actions taken in the media infobar, which prompts the users for
+ device permission.
+ </summary>
+</histogram>
+
+<histogram name="Media.Duration" units="ms">
+ <summary>Duration in milliseconds of HTML5 media (when known).</summary>
+</histogram>
+
+<histogram name="Media.EME.ClearKey.addKey" enum="MediaKeyException">
+ <summary>addKey result using the Clear Key key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.ClearKey.cancelKeyRequest" enum="MediaKeyException">
+ <summary>cancelKeyRequest result using the Clear Key key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.ClearKey.DecryptError">
+ <summary>
+ Decryption error event count using the Clear Key key system.
+ </summary>
+</histogram>
+
+<histogram name="Media.EME.ClearKey.generateKeyRequest"
+ enum="MediaKeyException">
+ <summary>generateKeyRequest result using the Clear Key key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.ClearKey.KeyAdded">
+ <summary>KeyAdded event count using the Clear Key key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.ClearKey.KeyError" enum="MediaKeyError">
+ <summary>KeyError event count using the Clear Key key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.NeedKey">
+ <summary>EME NeedKey event count.</summary>
+</histogram>
+
+<histogram name="Media.EME.Unknown.addKey" enum="MediaKeyException">
+ <summary>addKey result using an unknown key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Unknown.cancelKeyRequest" enum="MediaKeyException">
+ <summary>cancelKeyRequest result using an unknown key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Unknown.DecryptError">
+ <summary>Decryption error event count using an unknown key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Unknown.generateKeyRequest" enum="MediaKeyException">
+ <summary>generateKeyRequest result using an unknown key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Unknown.KeyAdded">
+ <summary>KeyAdded event count using an unknown key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Unknown.KeyError" enum="MediaKeyError">
+ <summary>KeyError event count using an unknown key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Widevine.addKey" enum="MediaKeyException">
+ <summary>addKey result using the Widevine key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Widevine.cancelKeyRequest" enum="MediaKeyException">
+ <summary>cancelKeyRequest result using the Widevine key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Widevine.DecryptError">
+ <summary>Decryption error event count using the Widevine key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Widevine.generateKeyRequest"
+ enum="MediaKeyException">
+ <summary>generateKeyRequest result using the Widevine key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Widevine.KeyAdded">
+ <summary>KeyAdded event count using the Widevine key system.</summary>
+</histogram>
+
+<histogram name="Media.EME.Widevine.KeyError" enum="MediaKeyError">
+ <summary>KeyError event count using the Widevine key system.</summary>
+</histogram>
+
+<histogram name="Media.FallbackHardwareAudioBitsPerChannel">
+ <summary>
+ Bits per channel of the hardware audio device which failed to open in low
+ latency mode and required high latency fallback.
+ </summary>
+</histogram>
+
+<histogram name="Media.FallbackHardwareAudioChannelCount">
+ <summary>
+ Channel count of the hardware audio device which failed to open in low
+ latency mode and required high latency fallback.
+ </summary>
+</histogram>
+
+<histogram name="Media.FallbackHardwareAudioChannelLayout" enum="ChannelLayout">
+ <summary>
+ Channel layout of the hardware audio device which failed to open in low
+ latency mode and required high latency fallback.
+ </summary>
+</histogram>
+
+<histogram name="Media.FallbackHardwareAudioSamplesPerSecond"
+ enum="AudioSampleRate">
+ <summary>
+ Samples per second of the hardware audio device which failed to open in low
+ latency mode and required high latency fallback.
+ </summary>
+</histogram>
+
+<histogram name="Media.FallbackHardwareAudioSamplesPerSecondUnexpected"
+ units="Hz">
+ <summary>
+ Samples per second of the hardware audio device (atypical values, in Hz)
+ which failed to open in low latency mode and required high latency fallback.
+ </summary>
+</histogram>
+
+<histogram name="Media.FallbackToHighLatencyAudioPath" enum="BooleanSuccess">
+ <summary>
+ Whether Chrome had to fallback to the high latency audio path or not.
+ </summary>
+</histogram>
+
+<histogram name="Media.Fling.DelayedAndDroppedFramesPer5Sec" units="frames/5s">
+ <summary>
+ The average number of delayed and dropped frames for the Fling application.
+ Reported every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.Fling.DisplayedFramesPerSecond" units="frames/s">
+ <summary>
+ The average number of displayed frames for the Fling application. Reported
+ every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.Fling.TimeToBufferAv" units="ms">
+ <summary>
+ Time needed to pre-buffer A/V data before the actual playback for the Fling
+ application.
+ </summary>
+</histogram>
+
+<histogram name="Media.Fling.TimeToBufferAvAfterAbort" units="ms">
+ <summary>
+ Time needed to buffer A/V data after an abort for the Fling application.
+ </summary>
+</histogram>
+
+<histogram name="Media.Fling.TimeToBufferAvAfterUnderrun" units="ms">
+ <summary>
+ Time needed to buffer A/V data after an underrun for the Fling application.
+ </summary>
+</histogram>
+
+<histogram name="Media.GpuVideoDecoderInitializeStatus" enum="PipelineStatus">
+ <summary>Results of attempts to GpuVideoDecoder::Initialize().</summary>
+</histogram>
+
+<histogram name="Media.HardwareAudioBitsPerChannel">
+ <summary>Bits per channel of the hardware audio device.</summary>
+</histogram>
+
+<histogram name="Media.HardwareAudioChannelCount">
+ <summary>Channel count of the hardware audio device.</summary>
+</histogram>
+
+<histogram name="Media.HardwareAudioChannelLayout" enum="ChannelLayout">
+ <summary>Channel layout of the hardware audio device.</summary>
+</histogram>
+
+<histogram name="Media.HardwareAudioSamplesPerSecond" enum="AudioSampleRate">
+ <summary>Samples per second of the hardware audio device.</summary>
+</histogram>
+
+<histogram name="Media.HardwareAudioSamplesPerSecondUnexpected" units="Hz">
+ <summary>
+ Samples per second of the hardware audio device (atypical values, in Hz).
+ </summary>
+</histogram>
+
+<histogram name="Media.InfoLoadDelay" units="milliseconds">
+ <summary>
+ The time it takes to perform redirect tracking and a CORS access check while
+ preparing to play a media file.
+ </summary>
+</histogram>
+
+<histogram name="Media.LinuxAudioIO" enum="LinuxAudioIO">
+ <summary>
+ Audio IO layer used by the Linux OS, sampled once at startup of the browser.
+ </summary>
+</histogram>
+
+<histogram name="Media.MSE.AudioCodec" enum="MSECodec">
+ <summary>
+ Audio codec used in Media Source Extensions playback. Set when AddId() is
+ called during playback.
+ </summary>
+</histogram>
+
+<histogram name="Media.MSE.NumberOfTracks">
+ <summary>
+ Number of tracks specified to AddId() for Media Source Extensions playback.
+ May be called multiple times per element if playback is dynamically altered.
+ </summary>
+</histogram>
+
+<histogram name="Media.MSE.Playback" enum="BooleanSuccess">
+ <summary>
+ Whether Media Source Extensions is specified for playback of Media elements.
+ Sampled when media pipeline starts.
+ </summary>
+</histogram>
+
+<histogram name="Media.MSE.VideoCodec" enum="MSECodec">
+ <summary>
+ Video codec used in Media Source Extensions playback. Set when AddId() is
+ called during playback.
+ </summary>
+</histogram>
+
+<histogram name="Media.Netflix.AudioBitrate" units="kbps">
+ <summary>
+ The audio bit rate as reported by the Netflix application. May be reported
+ multiple times as network conditions change during playback.
+ </summary>
+</histogram>
+
+<histogram name="Media.Netflix.AudioNumChannels" units="channels">
+ <summary>
+ The number of audio channels as reported by the Netflix application. May be
+ reported multiple times as network conditions change during playback.
+ </summary>
+</histogram>
+
+<histogram name="Media.Netflix.DelayedAndDroppedFramesPer5Sec"
+ units="frames/5s">
+ <summary>
+ The average number of delayed and dropped frames for the Netflix
+ application. Reported every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.Netflix.DisplayedFramesPerSecond" units="frames/s">
+ <summary>
+ The average number of displayed frames for the Netflix application. Reported
+ every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.Netflix.VideoBitrate" units="kbps">
+ <summary>
+ Video bit rate as reported by the Netflix application. May be reported
+ multiple times as network conditions change during playback.
+ </summary>
+</histogram>
+
+<histogram name="Media.Netflix.VideoHeight" units="pixels">
+ <summary>
+ Video height as reported by the Netflix application. May be reported
+ multiple times as network conditions change during playback.
+ </summary>
+</histogram>
+
+<histogram name="Media.PepperVideoDecoderError" enum="PepperVideoDecodeError">
+ <summary>Counts of video decode errors reported to plugin.</summary>
+</histogram>
+
+<histogram name="Media.PepperVideoDecoderPictureCount">
+ <summary>
+ Number of PictureBuffers/textures requested per hardware decoder creation.
+ This value varies by platform and video. A user visible video may trigger
+ multiple decoder creations (sometimes every 5 seconds) but would normally
+ not hold more than 2 sets of buffers at any given time in memory.
+ </summary>
+</histogram>
+
+<histogram name="Media.PepperVideoDecoderPictureHeight">
+ <summary>
+ Vertical video resolution rounded to the nearest bucket. (Corresponds
+ roughly to the number in 720p.)
+ </summary>
+</histogram>
+
+<histogram name="Media.PlayMovies.DelayedAndDroppedFramesPer5Sec"
+ units="frames/5s">
+ <summary>
+ The average number of delayed and dropped frames for the PlayMovies
+ application. Reported every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.PlayMovies.DisplayedFramesPerSecond" units="frames/s">
+ <summary>
+ The average number of displayed frames for the PlayMovies application.
+ Reported every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.TimeToPipelineStarted" units="ms">
+ <summary>
+ Time in milliseconds from HTML5 media pipeline creation to playing event.
+ </summary>
+</histogram>
+
+<histogram name="Media.TotalMBytes" units="MB">
+ <summary>Size of HTML5 media (when known), in MB.</summary>
+</histogram>
+
+<histogram name="Media.UncacheableReason" enum="UncacheableReason">
+ <summary>
+ Reasons a media response won't be used to satisfy a future request.
+ </summary>
+</histogram>
+
+<histogram name="Media.URLScheme" enum="URLSchemeForHistogram">
+ <summary>
+ URL scheme used with HTML5 media. (each URL provides one sample)
+ </summary>
+</histogram>
+
+<histogram name="Media.VAVDAH264.DecoderFailure" enum="VAVDAH264DecoderFailure">
+ <summary>
+ Error codes reported by video decode using VA-API hardware video decoder.
+ </summary>
+</histogram>
+
+<histogram name="Media.VideoCaptureManager" units="ms">
+ <summary>Measures the time taken for VideoCaptureManager::</summary>
+</histogram>
+
+<histogram name="Media.VideoCodec" enum="VideoCodec">
+ <summary>Video codec used in HTML5 media.</summary>
+</histogram>
+
+<histogram name="Media.VideoCodecProfile" enum="VideoCodecProfile">
+ <summary>Video codec profile used in HTML5 media.</summary>
+</histogram>
+
+<histogram name="Media.VideoCodedAspectRatio">
+ <summary>Coded aspect ratio of HTML5 video.</summary>
+</histogram>
+
+<histogram name="Media.VideoCodedWidth">
+ <summary>Coded width of HTML5 video.</summary>
+</histogram>
+
+<histogram name="Media.VideoVisibleAspectRatio">
+ <summary>Visible aspect ratio of HTML5 video.</summary>
+</histogram>
+
+<histogram name="Media.VideoVisibleWidth">
+ <summary>Visible width of HTML5 video.</summary>
+</histogram>
+
+<histogram name="Media.YouTube.DelayedAndDroppedFramesPer5Sec"
+ units="frames/5s">
+ <summary>
+ The average number of delayed and dropped frames for the YouTube
+ application. Reported every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.YouTube.DisplayedFramesPerSecond" units="frames/s">
+ <summary>
+ The average number of displayed frames for the YouTube application. Reported
+ every 5 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Media.YouTube.TimeToBufferAv" units="ms">
+ <summary>
+ Time needed to pre-buffer A/V data before the actual playback for the
+ YouTube application.
+ </summary>
+</histogram>
+
+<histogram name="Media.YouTube.TimeToBufferAvAfterAbort" units="ms">
+ <summary>
+ Time needed to buffer A/V data after an abort for the YouTube application.
+ </summary>
+</histogram>
+
+<histogram name="Media.YouTube.TimeToBufferAvAfterUnderrun" units="ms">
+ <summary>
+ Time needed to buffer A/V data after an underrun for the YouTube
+ application.
+ </summary>
+</histogram>
+
+<histogram name="Memory.BackingStore">
+ <summary>TBD.</summary>
+</histogram>
+
+<histogram name="Memory.Browser" units="KB">
+ <summary>
+ The private working set used by the browser process. Recorded once per UMA
+ ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.CachedFontAndDC">
+ <summary>TBD.</summary>
+</histogram>
+
+<histogram name="Memory.Chrome" units="KB">
+ <summary>
+ The private working set used by each chrome:// renderer process. Each
+ process provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.ChromeProcessCount">
+ <summary>
+ The count of active chrome:// processes. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Extension" units="KB">
+ <summary>
+ The private working set used by each extension process. Each process
+ provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.GlyphPagesPerLoad">
+ <summary>
+ The number of glyph pages present in the renderer when it commits a load.
+ Since this is per-sub-process, you can get the average number of glyph pages
+ in the system by multiplying this number with the average number of
+ renderers. Note that this typically won't count the glyph pages added as a
+ result of the load that just committed, since layout will happen after the
+ commit. There are 512 bytes per glyph page, but this number also very
+ closely approximates the number of glyph width map pages in the same
+ renderer. The only difference is that if you have font fallback, it will
+ make a new glyph page and no width page, but in most common cases there is
+ no fallback). Width pages are 1K each (256 floats), so you could think of
+ this value as being the number of &quot;1.5K units related to glyphs per
+ renderer per page load&quot;.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Gpu" units="KB">
+ <summary>
+ The private working set used by the GPU process. Recorded once per UMA
+ ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Graphics" units="MB">
+ <summary>
+ System-wide graphics driver memory consumption. Recorded on Chrome OS for
+ platforms where it is exposed by the kernel (for example, Intel i915 and
+ Exynos Mali). Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.NativeClient" units="KB">
+ <summary>
+ The private working set used by each Native Client loader process. Each
+ process provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.NativeClientBroker" units="KB">
+ <summary>
+ The private working set used by each Native Client broker process. Each
+ process provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.OtherProcessCount">
+ <summary>
+ The count of other various utility processes (nacl, gpu, sandbox, zygote,
+ utility). Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.PepperPlugin" units="KB">
+ <summary>
+ The private working set used by each Pepper plugin process. Each plugin
+ process provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.PepperPluginBroker" units="KB">
+ <summary>
+ The private working set used by each Pepper plugin broker process. Each
+ process provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.PepperPluginBrokerProcessCount">
+ <summary>
+ The count of Pepper plugin broker processes, recorded once per metrics
+ services (UMA) update. See MetricsReportingScheduler for details.
+ </summary>
+</histogram>
+
+<histogram name="Memory.PepperPluginProcessCount">
+ <summary>
+ The count of active Pepper plugin processes. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Plugin" units="KB">
+ <summary>
+ The private working set used by each plugin process. Each plugin process
+ provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.PluginProcessCount">
+ <summary>
+ The count of active plugin processes. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.ProcessCount">
+ <summary>
+ The count of all active processes. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.ProcessLimit">
+ <summary>The current process limit. Recorded once per UMA ping.</summary>
+</histogram>
+
+<histogram name="Memory.Renderer" units="KB">
+ <summary>
+ The private working set used by each renderer process. Each renderer
+ process provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.RendererProcessCount">
+ <summary>
+ The count of active renderer processes. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.SandboxHelper" units="KB">
+ <summary>
+ The private working set used by each sandbox helper process. Each sandbox
+ helper process provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Browser" units="KB">
+ <summary>
+ The swap used by the browser process. Recorded once per UMA ping if the
+ system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Chrome" units="KB">
+ <summary>
+ The swap used by each chrome:// renderer process. Each process provides one
+ sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.CompressedDataSize" units="MB">
+ <summary>
+ The amount of memory that swap was compressed into. Recorded once per UMA
+ ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.CompressionRatio">
+ <summary>
+ The ratio of swapped data original size to compressed size. Recorded once
+ per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Extension" units="KB">
+ <summary>
+ The swap used by each extension process. Each process provides one sample.
+ Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Gpu" units="KB">
+ <summary>
+ The swap used by the GPU process. Recorded once per UMA ping if the system
+ has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.HaveSwapped" units="BooleanSuccess">
+ <summary>
+ Indicates that the system has swapped memory out at least once since boot.
+ Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.MemUsedTotal" units="MB">
+ <summary>
+ The amount of memory that is used by swap, including bookkeeping. Recorded
+ once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.NativeClient" units="KB">
+ <summary>
+ The swap used by each Native Client loader process. Each process provides
+ one sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.NativeClientBroker" units="KB">
+ <summary>
+ The swap used by each Native Client broker process. Each process provides
+ one sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.NumReads">
+ <summary>
+ The number of reads from swap. Recorded once per UMA ping if the system
+ has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.NumWrites">
+ <summary>
+ The number of writes to swap. Recorded once per UMA ping if the system has
+ swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.OriginalDataSize" units="MB">
+ <summary>
+ The amount of memory that was swapped out. Recorded once per UMA ping if
+ the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.PepperPlugin" units="KB">
+ <summary>
+ The swap used by each Pepper plugin process. Each plugin process provides
+ one sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.PepperPluginBroker" units="KB">
+ <summary>
+ The swap used by each Pepper plugin broker process. Each process provides
+ one sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Plugin" units="KB">
+ <summary>
+ The swap used by each plugin process. Each plugin process provides one
+ sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Renderer" units="KB">
+ <summary>
+ The swap used by each renderer process. Each renderer process provides one
+ sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.SandboxHelper" units="KB">
+ <summary>
+ The swap used by each sandbox helper process. Each sandbox helper process
+ provides one sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Total" units="MB">
+ <summary>
+ The sum of all processes' swap. Recorded once per UMA ping if the system
+ has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Utility" units="KB">
+ <summary>
+ The swap used by each utility process. Each utility process provides one
+ sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Swap.Worker" units="KB">
+ <summary>
+ The swap used by each worker process. Each worker process provides one
+ sample. Recorded once per UMA ping if the system has swapped.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Total" units="MB">
+ <summary>The sum of all processes. Recorded once per UMA ping.</summary>
+</histogram>
+
+<histogram name="Memory.Utility" units="KB">
+ <summary>
+ The private working set used by each utility process. Each utility process
+ provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Worker" units="KB">
+ <summary>
+ The private working set used by each worker process. Each worker process
+ provides one sample. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Memory.WorkerProcessCount">
+ <summary>TBD.</summary>
+</histogram>
+
+<histogram name="MemoryAndroid.DeviceMemoryClass">
+ <summary>
+ Value of getMemoryClass() recorded once upon startup. This is an integer,
+ device-specific constant correlated with the amount of memory available on
+ Android device.
+ </summary>
+</histogram>
+
+<histogram name="MemoryAndroid.EvictionReason" enum="AndroidEvictionReason">
+ <summary>
+ Reasons behind evictions of individual tabs, recorded upon each tab
+ eviction.
+ </summary>
+</histogram>
+
+<histogram name="MemoryAndroid.LowMemoryLoadedTabCount">
+ <summary>
+ Number of loaded (memory-resident) tabs when LowMemory notification is
+ delivered.
+ </summary>
+</histogram>
+
+<histogram name="MemoryAndroid.LowMemoryTimeBetween" units="milliseconds">
+ <summary>
+ Time between two consecutive LowMemory notification in one foreground
+ session.
+ </summary>
+</histogram>
+
+<histogram name="MemoryAndroid.NotificationBackground"
+ enum="AndroidMemoryNotificationBackground">
+ <summary>
+ Memory notifications delivered through system callbacks to Chrome while in
+ the background.
+ </summary>
+</histogram>
+
+<histogram name="MemoryAndroid.NotificationForeground"
+ enum="AndroidMemoryNotificationForeground">
+ <summary>
+ Memory notifications delivered through system callbacks to Chrome while in
+ the foreground - we count LowMemory notification vs particular levels of
+ TrimMemory foreground notification.
+ </summary>
+</histogram>
+
+<histogram name="Mouse.PointerSensitivity.Changed" enum="PointerSensitivity">
+ <summary>
+ Tracks mouse sensitivity setting changes by the user. This replaces the old
+ Mouse.Sensitivity.Changed metric.
+ </summary>
+</histogram>
+
+<histogram name="Mouse.PointerSensitivity.Started" enum="PointerSensitivity">
+ <summary>
+ Tracks mouse sensitivity setting on startup. This replaces the old
+ Mouse.Sensitivity.Started metric.
+ </summary>
+</histogram>
+
+<histogram name="Mouse.Sensitivity.Changed" enum="PointerSensitivity">
+ <obsolete>
+ Deprecated as of 6/2013, replaced by Mouse.PointerSensitivity.Changed.
+ </obsolete>
+ <summary>Tracks mouse sensitivity setting.</summary>
+</histogram>
+
+<histogram name="Mouse.Sensitivity.Started" enum="PointerSensitivity">
+ <obsolete>
+ Deprecated as of 6/2013, replaced by Mouse.PointerSensitivity.Started.
+ </obsolete>
+ <summary>Tracks mouse sensitivity setting on startup.</summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.MouseDownDuration_Click" units="ms">
+ <summary>
+ Measures the time elapsed between when the user mousedown-ed a link and when
+ the user clicked a link.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.MouseDownFollowedByClick"
+ enum="MouseEventFollowedByClick">
+ <summary>
+ For each click handled by an HTML anchor tag link, whether Blink saw a
+ mousedown event preceding it. This is only measured for clicks handled by
+ the anchor tag's default click event handler.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.MouseDowns">
+ <summary>
+ The number of mousedown events detected at HTML anchor-tag links' default
+ event handler.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.MouseOverDuration_Click" units="ms">
+ <summary>
+ Measures the time elapsed between when the user mouseover-ed a link and when
+ the user clicked a link.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.MouseOverDuration_NoClick" units="ms">
+ <summary>
+ Measures the time elapsed between when the user mouseover-ed a link and when
+ the user mouseout-ed a link without click.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.MouseOvers">
+ <summary>
+ The number of mouseover events detected at HTML anchor-tag links' default
+ event handler.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.PreTapEventsFollowedByClick"
+ enum="PreTapEvents">
+ <summary>
+ The tap gesture events detected before click at HTML anchor-tag links'
+ default event handler.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.TapDownDuration_Click" units="ms">
+ <summary>
+ Measures the time elapsed between when the user tapdown-ed a link and when
+ the user clicked a link.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.TapDowns">
+ <summary>
+ The number of gesturetapdown events detected at HTML anchor-tag links'
+ default event handler.
+ </summary>
+</histogram>
+
+<histogram name="MouseEventPrefetch.TapUnconfirmeds">
+ <summary>
+ The number of gesturetapunconfirmed events detected at HTML anchor-tag
+ links' default event handler.
+ </summary>
+</histogram>
+
+<histogram name="Navigation.MainFrameScheme" enum="NavigationScheme">
+ <summary>The scheme of the URL for each main-frame navigation.</summary>
+</histogram>
+
+<histogram name="Net.AsyncResourceHandler_PendingDataCount">
+ <summary>
+ The count of unacknowledged ResourceMsg_DataReceived messages. This message
+ is sent once per chunk of data read from the network.
+ </summary>
+</histogram>
+
+<histogram name="Net.AsyncResourceHandler_PendingDataCount_WhenFull">
+ <summary>
+ The count of unacknowledged ResourceMsg_DataReceived messages at the point
+ where we pause network loading.
+ </summary>
+</histogram>
+
+<histogram name="Net.AsyncResourceHandler_SharedIOBuffer_Alloc" units="bytes">
+ <summary>The size of a SharedIOBuffer allocation.</summary>
+</histogram>
+
+<histogram name="Net.AsyncResourceHandler_SharedIOBuffer_Used" units="bytes">
+ <summary>The number of bytes copied into a SharedIOBuffer.</summary>
+</histogram>
+
+<histogram name="Net.AsyncResourceHandler_SharedIOBuffer_UsedPercentage"
+ units="percentage">
+ <summary>
+ The percentage of a SharedIOBuffer allocation that is actually used.
+ </summary>
+</histogram>
+
+<histogram name="Net.AuthGenerateToken_basic" units="milliseconds">
+ <summary>The time to generate a Basic HTTP authentication token.</summary>
+</histogram>
+
+<histogram name="Net.AuthGenerateToken_digest" units="milliseconds">
+ <summary>The time to generate a Digest HTTP authentication token.</summary>
+</histogram>
+
+<histogram name="Net.AuthGenerateToken_negotiate" units="milliseconds">
+ <summary>
+ The time to generate a Negotiate (or SPNEGO) HTTP authentication token.
+ </summary>
+</histogram>
+
+<histogram name="Net.AuthGenerateToken_ntlm" units="milliseconds">
+ <summary>The time to generate an NTLM HTTP authentication token.</summary>
+</histogram>
+
+<histogram name="Net.CertificatePinSuccess" enum="BooleanSuccess">
+ <obsolete>
+ Renamed to Net.PublicKeyPinSuccess 28 Oct 2011.
+ </obsolete>
+ <summary>
+ A validated certificate chain may be subject to additional
+ &quot;pinning&quot; requirements on a per-domain basis. This records the
+ fraction of successful matches between a certificate chain and a pin list.
+ </summary>
+</histogram>
+
+<histogram name="Net.CertVerifier_Job_Latency" units="milliseconds">
+ <summary>
+ The actual amount of time spent verifying a certificate using the underlying
+ cryptographic APIs. Because parallel verifications for the same certificate
+ may be coalesced, histograms such as Net.SSLCertVerificationTime may be
+ skewed, due to later verifications taking less overall time. This records
+ the overall time spent verifying a single request, regardless of how many
+ parallel requests are being served by the verification.
+ </summary>
+</histogram>
+
+<histogram name="Net.CoalescePotential" enum="CoalescePotentialPackets">
+ <summary>
+ The number of times we sent N packets, but could have sent N-1 packets.
+ </summary>
+</histogram>
+
+<histogram name="Net.ComodoDNSExperimentFailureTime" units="milliseconds">
+ <summary>
+ The amount of time taken before we failed to resolve the Comodo test DNS
+ record. This is an experiment, run in conjuction with Comodo, to test the
+ viability of a DNS based certificate revocation mechanism.
+ </summary>
+</histogram>
+
+<histogram name="Net.ComodoDNSExperimentSuccessTime" units="milliseconds">
+ <summary>
+ The amount of time taken to successfully resolve the Comodo test DNS record.
+ This is an experiment, run in conjuction with Comodo, to test the viability
+ of a DNS based certificate revocation mechanism.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.NoProxy.BytesAfterCompression" units="bytes">
+ <summary>
+ The uncompressed number of bytes received per request that was compressed.
+ Only includes requests which did not go through an explicit proxy and did
+ not go over SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.NoProxy.BytesBeforeCompression" units="bytes">
+ <summary>
+ The compressed number of bytes received per request that was compressed.
+ Only includes requests which did not go through an explicit proxy and did
+ not go over SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.NoProxy.ShouldHaveBeenCompressed" units="bytes">
+ <summary>
+ The uncompressed number of bytes received per request that was not
+ compressed but appears to have been compressible. Only includes requests
+ which did not go through an explicit proxy and did not go over SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.Proxy.BytesAfterCompression" units="bytes">
+ <summary>
+ The uncompressed number of bytes received per request that was compressed.
+ Only includes requests sent through a proxy without SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.Proxy.BytesBeforeCompression" units="bytes">
+ <summary>
+ The compressed number of bytes received per request that was compressed.
+ Only includes requests sent through a proxy without SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.Proxy.ShouldHaveBeenCompressed" units="bytes">
+ <summary>
+ The uncompressed number of bytes received per request that was not
+ compressed but appears to have been compressible. Only includes requests
+ sent through a proxy without SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.SSL.BytesAfterCompression" units="bytes">
+ <summary>
+ The uncompressed number of bytes received per request that was compressed.
+ Only includes requests sent over SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.SSL.BytesBeforeCompression" units="bytes">
+ <summary>
+ The compressed number of bytes received per request that was compressed.
+ Only includes requests sent over SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.Compress.SSL.ShouldHaveBeenCompressed" units="bytes">
+ <summary>
+ The uncompressed number of bytes received per request that was not
+ compressed but appears to have been compressible. Only includes requests
+ sent over SSL.
+ </summary>
+</histogram>
+
+<histogram name="Net.ConnectionTypeCount" enum="ConnectionType">
+ <obsolete>
+ The count was inaccurate (it counted transactions rather than connections)
+ </obsolete>
+ <summary>
+ Each bucket is the number of connections of a particular type that the user
+ has had during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.ConnectionTypeCount2" enum="ConnectionType">
+ <obsolete>
+ Renamed to match HadConnectionType.
+ </obsolete>
+ <summary>
+ Each bucket is the number of successful connections of a particular type
+ that the user has had during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.ConnectionTypeCount3" enum="ConnectionType">
+ <summary>
+ Each bucket is the number of successful connections of a particular type
+ that the user has had during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.ConnectionTypeFailCount2" enum="ConnectionType">
+ <obsolete>
+ No longer collected.
+ </obsolete>
+ <summary>
+ Each bucket is the number of failed connections of a particular type that
+ the user has had during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.ConnectionUsedSSLv3Fallback">
+ <obsolete>
+ Replaced by Net.ConnectionUsedSSLVersionFallback in Chrome 21.
+ </obsolete>
+ <summary>
+ True if the HTTP request was to a server which requires SSLv3 fallback
+ </summary>
+</histogram>
+
+<histogram name="Net.ConnectionUsedSSLVersionFallback"
+ enum="FallbackSSLVersion">
+ <summary>
+ Nonzero if the HTTP request was to a server which requires SSL version
+ fallback. The value indicates the SSL version the request fell back on.
+ </summary>
+</histogram>
+
+<histogram name="net.CookieBackingStoreUpdateResults"
+ enum="BackingStoreResults">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>
+ Whether or not updates to the backing store succeeded or failed, recorded
+ every update.
+ </summary>
+</histogram>
+
+<histogram name="net.CookieBetweenAccessIntervalMinutes" units="minutes">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>Intervals between access time updates for each cookie.</summary>
+</histogram>
+
+<histogram name="net.CookieCount">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>
+ Number of cookies in the store (recorded every 10 minutes of active browsing
+ time)
+ </summary>
+</histogram>
+
+<histogram name="net.CookieDeletionCause" enum="CookieDeletionCause">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>
+ For each cookie removed from the store, the reason it was removed.
+ </summary>
+</histogram>
+
+<histogram name="net.CookieDomainCount">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>
+ For each domain, number of cookies in that domain (recorded every 10 minutes
+ of active browsing time).
+ </summary>
+</histogram>
+
+<histogram name="net.CookieDomainPerEtldp1Count">
+ <summary>
+ For every top level domain, number of subdomains in that top level domain
+ (recorded every 10 minutes of active browsing time).
+ </summary>
+</histogram>
+
+<histogram name="net.CookieEtldp1Count">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>
+ For every top level domain, number of cookies in that domain (recorded every
+ 10 minutes of active browsing time).
+ </summary>
+</histogram>
+
+<histogram name="net.CookieEvictedLastAccessMinutes" units="minutes">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>
+ For each evicted (not expired) cookie, the amount of time since it was last
+ used
+ </summary>
+</histogram>
+
+<histogram name="net.CookieExpirationDurationMinutes" units="minutes">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>Number of minutes until cookie expires when set.</summary>
+</histogram>
+
+<histogram name="net.CookieTimeGet">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>
+ The amount of time (ms) to get cookies for each URL request.
+ </summary>
+</histogram>
+
+<histogram name="net.CookieTimeLoad">
+ <obsolete>
+ Initial typo; only here to get results from builds before r59117. See
+ &quot;Cookie.&quot; group.
+ </obsolete>
+ <summary>
+ The amount of time (ms) to load the persistent cookie store at browser
+ start.
+ </summary>
+</histogram>
+
+<histogram name="Net.CountOfAlternateProtocolServers">
+ <summary>
+ The total number of severs to which alternative protocol was used. This
+ counts the number of servers persisted to prefs file.
+ </summary>
+</histogram>
+
+<histogram name="Net.CountOfPipelineCapableServers">
+ <summary>
+ The total number of severs that support HTTP pipelining. This counts the
+ number of servers persisted to prefs file.
+ </summary>
+</histogram>
+
+<histogram name="Net.CountOfSpdyServers">
+ <summary>
+ The total number of SPDY server names persisted to prefs file.
+ </summary>
+</histogram>
+
+<histogram name="Net.CountOfSpdySettings">
+ <summary>
+ The total number of SPDY Settings properties persisted to prefs file.
+ </summary>
+</histogram>
+
+<histogram name="Net.CRLRequestFailedTimeMs" units="milliseconds">
+ <summary>
+ When validating an HTTPS certificate we may have to block to fetch one or
+ more revocation lists. This measures the amount of time that failures to get
+ CRL information take.
+ </summary>
+</histogram>
+
+<histogram name="Net.CRLRequestSuccess" enum="BooleanSuccess">
+ <summary>
+ When validating an HTTPS certificate we may have to block to fetch one or
+ more revocation lists. This records the fraction of successful requests.
+ </summary>
+</histogram>
+
+<histogram name="Net.CRLRequestTimeMs" units="milliseconds">
+ <summary>
+ When validating an HTTPS certificate we may have to block to fetch one or
+ more revocation lists. This measures the amount of time that each fetch
+ takes.
+ </summary>
+</histogram>
+
+<histogram name="Net.DailyHttpContentLengthViaDataReductionProxy" units="KB">
+ <summary>
+ Total size in KB of all response bodies in the previous calendar day that
+ were received through the data reduction proxy.
+ </summary>
+</histogram>
+
+<histogram name="Net.DailyHttpContentLengthWithDataReductionProxyEnabled"
+ units="KB">
+ <summary>
+ Total size in KB of all response bodies in the previous calendar day that
+ were received when the data reduction proxy was enabled.
+ </summary>
+</histogram>
+
+<histogram name="Net.DailyHttpContentSavings" units="Percent">
+ <summary>
+ The percentage of data saving in the previous calendar day. A negative
+ saving will be shown as zero.
+ </summary>
+</histogram>
+
+<histogram name="Net.DailyHttpContentSavings_DataReductionProxy"
+ units="Percent">
+ <summary>
+ The percentage of data saving in the previous calendar day when the data
+ reduction proxy was enabled for at least some responses during the day. A
+ negative saving will be shown as zero.
+ </summary>
+</histogram>
+
+<histogram name="Net.DailyHttpOriginalContentLength" units="KB">
+ <summary>
+ Total size in KB specified in the X-Original-Content-Length headers of all
+ responses in the previous calendar day. If the header is not present in a
+ response, the size of the response body is used.
+ </summary>
+</histogram>
+
+<histogram name="Net.DailyHttpReceivedContentLength" units="KB">
+ <summary>
+ Total size in KB of all response bodies in the previous calendar day.
+ </summary>
+</histogram>
+
+<histogram name="Net.DailyReceivedContentViaDataReductionProxy" units="Percent">
+ <summary>
+ The percentage of Net.DailyHttpContentLengthViaDataReductionProxy in
+ Net.DailyHttpReceivedContentLength.
+ </summary>
+</histogram>
+
+<histogram name="Net.DailyReceivedContentWithDataReductionProxyEnabled"
+ units="Percent">
+ <summary>
+ The percentage of Net.DailyHttpContentLengthWithDataReductionProxyEnabled in
+ Net.DailyHttpReceivedContentLength.
+ </summary>
+</histogram>
+
+<histogram name="Net.DhcpWpadCancelTime" units="milliseconds">
+ <summary>
+ Measures time from initiating a fetch of a PAC file from DHCP WPAD to
+ cancellation of the fetch. For a given fetch, only one of the cancellation
+ or completion histograms will be added to.
+ </summary>
+</histogram>
+
+<histogram name="Net.DhcpWpadCompletionTime" units="milliseconds">
+ <summary>
+ Measures time from initiating a fetch of a PAC file from DHCP WPAD to
+ completion of the fetch. For a given fetch, only one of the cancellation or
+ completion histograms will be added to.
+ </summary>
+</histogram>
+
+<histogram name="Net.DhcpWpadFetchError" enum="NetErrorCodes">
+ <summary>
+ Tracks the net error codes received when the DHCP WPAD fetch fails to
+ retrieve a PAC file (including PAC_NOT_IN_DHCP, which is not really an error
+ but an indication that a PAC URL was not configured in DHCP).
+ </summary>
+</histogram>
+
+<histogram name="Net.DhcpWpadGetAdaptersAddressesError"
+ enum="ErrorCodesGetAdaptersAddresses">
+ <summary>
+ Tracks the frequency of each of the different known error codes of calling
+ the GetAdaptersAddresses Win32 API.
+ </summary>
+</histogram>
+
+<histogram name="Net.DhcpWpadGetAdaptersAddressesTime" units="milliseconds">
+ <summary>
+ Measures the time taken to call the GetAdaptersAddresses Win32 API, to
+ validate our understanding that it should complete quickly enough to call
+ synchronously from the network thread.
+ </summary>
+</histogram>
+
+<histogram name="Net.DhcpWpadNumAdaptersAtWaitTimer">
+ <summary>
+ Total number of adapters enabled for DHCP as seen when the wait timer in the
+ DHCP WPAD code hits. This timer fires after a timeout from when we get some
+ information from the first adapter to finish.
+ </summary>
+</histogram>
+
+<histogram name="Net.DhcpWpadNumPendingAdaptersAtWaitTimer">
+ <summary>
+ Number of adapters enabled for DHCP that we have not completed retrieving
+ information for, as seen when the wait timer in the DHCP WPAD code hits.
+ This timer fires after a timeout from when we get some information from the
+ first adapter to finish.
+ </summary>
+</histogram>
+
+<histogram name="Net.DhcpWpadUnhandledDhcpError">
+ <summary>
+ Counts the number of errors from the DhcpRequestParams API that we do not
+ have specific handling for, so that we can see if there is an abnormally
+ high rate.
+ </summary>
+</histogram>
+
+<histogram name="Net.DNS_Resolution_And_TCP_Connection_Latency">
+ <obsolete>
+ Deprecated- see Net.DNS_Resolution_And_TCP_Connection_Latency2
+ </obsolete>
+</histogram>
+
+<histogram name="Net.Dns_Resolution_And_TCP_Connection_Latency">
+ <obsolete>
+ Deprecated- see Net.DNS_Resolution_And_TCP_Connection_Latency2
+ </obsolete>
+</histogram>
+
+<histogram name="Net.DNS_Resolution_And_TCP_Connection_Latency2"
+ units="milliseconds">
+ <summary>
+ The time measured before starting DNS lookup until after the connection is
+ complete.
+ </summary>
+</histogram>
+
+<histogram name="Net.Dns_Resolution_And_TCP_Connection_Latency2">
+ <obsolete>
+ Deprecated- see Net.DNS_Resolution_And_TCP_Connection_Latency2
+ </obsolete>
+</histogram>
+
+<histogram name="Net.DoubleGetExperiment_InitialResponseMethod"
+ enum="DoubleGetExperimentMethods">
+ <summary>
+ The number of HTTP request responses with MS Office Docs MIME types. The
+ responses are classified based on their method type and cacheability (POST,
+ cacheable GET and non-cacheable GET). The histogram is used in Double GET
+ Experiment, where successful non-cacheable GET requests are intercepted
+ after initial response and repeated in order to determine how much reissuing
+ non-cacheable GET requests influences their error rate. The histogram tracks
+ only initial requests (not the repeated ones).
+ </summary>
+</histogram>
+
+<histogram name="Net.DoubleGetExperiment_ResponseCode">
+ <summary>
+ The response codes encountered for GET request repeated in Double GET
+ Experiment. In the experiment successful non-cacheable GET requests are
+ intercepted after initial response and repeated. The goal of the experiment
+ is to measure how much reissuing non-cacheable GET requests influences their
+ error rate.
+ </summary>
+</histogram>
+
+<histogram name="Net.DownloadBandwidth">
+ <summary>
+ Kbps on download streams exceeding 25KB. Measures from the beginning of the
+ first byte received until the end of flowing data.
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForImages" enum="NetErrorCodes">
+ <summary>
+ Net error codes that requests for images end with, including net::OK and
+ net:ERR_ABORTED.
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForMainFrame" enum="NetErrorCodes">
+ <obsolete>
+ Deprecated as of 2011/5/24, replaced by Net.ErrorCodesForMainFrame2, which
+ measures the same data but uses a different bucket structure (adds guard
+ buckets).
+ </obsolete>
+ <summary>
+ Positive net error code that a page failed with. Note that this only counts
+ the errors in &quot;main frames&quot;, so it is a measure of the error pages
+ that users actually see (it does not for example count the error codes for
+ subresoures on a page).
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForMainFrame2" enum="NetErrorCodes">
+ <obsolete>
+ Deprecated as of 2012/5/16, replaced by Net.ErrorCodesForMainFrame3, which
+ measures the same data but includes ERR_ABORTED and OK.
+ </obsolete>
+ <summary>
+ Positive net error code that a page failed with. Note that this only counts
+ the errors in &quot;main frames&quot;, so it is a measure of the error pages
+ that users actually see (it does not for example count the error codes for
+ subresoures on a page).
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForMainFrame3" enum="NetErrorCodes">
+ <summary>
+ Positive net error codes that requests for pages end with, including net::OK
+ and net::ERR_ABORTED. This only counts loads in &quot;main frames&quot; (it
+ does not for example count the error codes for subresoures on a page).
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForSubresources" enum="NetErrorCodes">
+ <obsolete>
+ Deprecated as of 2012/5/16, replaced by Net.ErrorCodesForSubresources2,
+ which measures the same data but includes ERR_ABORT and OK.
+ </obsolete>
+ <summary>
+ Positive net error code that a page failed with. Note that this only counts
+ the errors in &quot;subresources&quot;.
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForSubresources2" enum="NetErrorCodes">
+ <summary>
+ Net error codes that requests for &quot;subresources&quot; end with,
+ including net::OK and net::ERR_ABORTED.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileError_Flush">
+ <summary>
+ System error code that a file Flush failed with. The code is OS dependent,
+ so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileError_GetSize">
+ <summary>
+ System error code that a file GetSize failed with. The code is OS
+ dependent, so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileError_Open">
+ <summary>
+ System error code that a file Open failed with. The code is OS dependent,
+ so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileError_Read">
+ <summary>
+ System error code that a file Read failed with. The code is OS dependent,
+ so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileError_Seek">
+ <summary>
+ System error code that a file Seek failed with. The code is OS dependent,
+ so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileError_SetEof">
+ <summary>
+ System error code that a file SetEof failed with. The code is OS dependent,
+ so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileError_Write">
+ <summary>
+ System error code that a file Write failed with. The code is OS dependent,
+ so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileErrorRange_Flush">
+ <summary>
+ System error code range that a file Flush failed with. Any value other than
+ 0 indicates that we have received errors in a range outside of the one in
+ which we recorded the specific errors in Net.FileError_Flush. The code is
+ OS dependent, so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileErrorRange_GetSize">
+ <summary>
+ System error code range that a file GetSize failed with. Any value other
+ than 0 indicates that we have received errors in a range outside of the one
+ in which we recorded the specific errors in Net.FileError_GetSize. The code
+ is OS dependent, so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileErrorRange_Open">
+ <summary>
+ System error code range that a file Open failed with. Any value other than
+ 0 indicates that we have received errors in a range outside of the one in
+ which we recorded the specific errors in Net.FileError_Open. The code is OS
+ dependent, so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileErrorRange_Read">
+ <summary>
+ System error code range that a file Read failed with. Any value other than
+ 0 indicates that we have received errors in a range outside of the one in
+ which we recorded the specific errors in Net.FileError_Read. The code is OS
+ dependent, so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileErrorRange_Seek">
+ <summary>
+ System error code range that a file Seek failed with. Any value other than
+ 0 indicates that we have received errors in a range outside of the one in
+ which we recorded the specific errors in Net.FileError_Seek. The code is OS
+ dependent, so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileErrorRange_SetEof">
+ <summary>
+ System error code range that a file SetEof failed with. Any value other
+ than 0 indicates that we have received errors in a range outside of the one
+ in which we recorded the specific errors in Net.FileError_SetEof. The code
+ is OS dependent, so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FileErrorRange_Write">
+ <summary>
+ System error code range that a file Write failed with. Any value other than
+ 0 indicates that we have received errors in a range outside of the one in
+ which we recorded the specific errors in Net.FileError_Write. The code is
+ OS dependent, so when looking at the histogram don't mix OSes.
+ </summary>
+</histogram>
+
+<histogram name="Net.FtpDataConnectionErrorCount" enum="FtpDataConnectionError">
+ <summary>The number of times each FTP Error was observed.</summary>
+</histogram>
+
+<histogram name="Net.FtpDataConnectionErrorHappened"
+ enum="FtpDataConnectionError">
+ <summary>
+ The number of Chrome sessions which encountered the indicates FTP Error.
+ This prevents allowing a user that retried a connection many times (getting
+ an error each time) from biasing the tallies.
+ </summary>
+</histogram>
+
+<histogram name="Net.FtpServerTypeCount" enum="FtpServerType">
+ <summary>
+ Each bucket is the number of FTP server types the user has encountered
+ during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.GetProxyForUrl_FAIL" units="milliseconds">
+ <summary>
+ The time spent waiting for WinHttpGetProxyForUrl to return with error.
+ </summary>
+</histogram>
+
+<histogram name="Net.GetProxyForUrl_OK" units="milliseconds">
+ <summary>
+ The time spent waiting for WinHttpGetProxyForUrl to return with success.
+ </summary>
+</histogram>
+
+<histogram name="Net.GoogleConnectionUsedSSLVersionFallback"
+ enum="FallbackSSLVersion">
+ <summary>
+ Nonzero if the HTTP request was to a Google server which required SSL
+ version fallback. The value indicates the SSL version the request fell back
+ on. Since Google servers support TLS 1.2, any fallback is an indication of
+ network middleware problems.
+ </summary>
+</histogram>
+
+<histogram name="Net.HadConnectionType" enum="ConnectionType">
+ <obsolete>
+ The count was inaccurate (it counted transactions rather than connections).
+ </obsolete>
+ <summary>
+ Each bucket is a boolean (0 or 1) indicating whether the user has had a
+ connection of that type during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.HadConnectionType2" enum="ConnectionType">
+ <obsolete>
+ This statistic measures successful and failed connections, the new one only
+ measures successful ones.
+ </obsolete>
+ <summary>
+ Each bucket is a boolean (0 or 1) indicating whether the user has had a
+ connection of that type during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.HadConnectionType3" enum="ConnectionType">
+ <summary>
+ Each bucket is a boolean (0 or 1) indicating whether the user has had a
+ successful connection of that type during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.HadFtpServerType" enum="FtpServerType">
+ <summary>
+ Each bucket is a boolean (0 or 1) indicating whether the user has had a
+ connection with an FTP server of that type during the session.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpAuthCount" enum="HttpAuthCount">
+ <summary>
+ Per-authentication-scheme counts of authentication attempts and rejections.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpAuthResource" enum="HttpAuthResource">
+ <summary>
+ Count of authentication requests for top level pages vs. sub-resources, such
+ as images or iframes.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpAuthTarget" enum="HttpAuthTarget">
+ <summary>
+ Per-authentication-scheme counts of authentication targets, such as secure
+ servers or proxies.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpConnectionLatency" units="milliseconds">
+ <summary>
+ Time between the HttpNetworkTransaction requesting a connection and the time
+ it connected.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpContentFreshnessLifetime" units="seconds">
+ <summary>Length of time that a received resource will be cacheable.</summary>
+</histogram>
+
+<histogram name="Net.HttpContentLength" units="bytes">
+ <summary>
+ Size of the response body. This is the actual number of bytes received,
+ which usually agrees with but is not necessarily the same as the size
+ specified by the Content-Length header.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpContentLengthCacheable" units="bytes">
+ <summary>
+ Size of the response body if it is cacheable. This is the actual number of
+ bytes received, which usually agrees with but is not necessarily the same as
+ the size specified by the Content-Length header.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpContentLengthCacheable24Hours" units="bytes">
+ <summary>
+ Size of the response body if it is cacheable for at least 24 hours. This is
+ the actual number of bytes received, which usually agrees with but is not
+ necessarily the same as the size specified by the Content-Length header.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpContentLengthCacheable4Hours" units="bytes">
+ <summary>
+ Size of the response body if it is cacheable for at least 4 hours. This is
+ the actual number of bytes received, which usually agrees with but is not
+ necessarily the same as the size specified by the Content-Length header.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpContentLengthDifference" units="bytes">
+ <summary>
+ The difference between the size specified in the X-Original-Content-Length
+ header and the size of teh response body. This is zero if the
+ X-Original-Content-Length header is not present in the response.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpContentLengthDifferenceWithValidOCL" units="bytes">
+ <summary>
+ The difference between the size specified in the X-Original-Content-Length
+ header and the size of the response body. Only includes resources that have
+ the X-Original-Content-Length header.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpContentLengthWithValidOCL" units="bytes">
+ <summary>
+ Size of the response body. Only includes resources that have the
+ X-Original-Content-Length header.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpJob.TotalTime" units="milliseconds">
+ <summary>
+ Time it takes to complete an HttpJob, from starting the transaction until we
+ are done reading.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpJob.TotalTimeCached" units="milliseconds">
+ <summary>
+ Time it takes to complete an HttpJob, from starting the transaction until we
+ are done reading, for jobs served from the cache.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpJob.TotalTimeCancel" units="milliseconds">
+ <summary>
+ Time it takes to complete an HttpJob, from starting the transaction until
+ the job is killed. Note that we didn't detect the end of the data for this
+ job.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpJob.TotalTimeNotCached" units="milliseconds">
+ <summary>
+ Time it takes to complete an HttpJob, from starting the transaction until we
+ are done reading, for jobs not served from the cache.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpJob.TotalTimeSuccess" units="milliseconds">
+ <summary>
+ Time it takes to complete an HttpJob, from starting the transaction until we
+ are done reading, for jobs when we read until no more data is available.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpOriginalContentLength" units="bytes">
+ <summary>
+ Size specified in the X-Original-Content-Length header. If this header is
+ not present in the response, the size of the response body is used.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpOriginalContentLengthWithValidOCL" units="bytes">
+ <summary>
+ Size specified in the X-Original-Content-Length header. Only includes
+ resources that have the X-Original-Content-Length header.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpProxySocketRequestTime" units="milliseconds">
+ <summary>Time it takes to request a new (unused) HTTP proxy socket.</summary>
+</histogram>
+
+<histogram name="Net.HttpResponseCode">
+ <summary>The count of HTTP Response codes encountered.</summary>
+</histogram>
+
+<histogram name="Net.HttpResponseCode_Nxx_MainFrame">
+ <summary>
+ The count of HTTP Response codes encountered, in response to MAIN_FRAME
+ requests only; saving only the hundreds digit, e.g. 100-&gt;1, 300-&gt;3.
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpSocketType" enum="HttpSocketType">
+ <summary>
+ The counts of the type of sockets (all HTTP sockets, regardless of any proxy
+ used) used for HTTP[s].
+ </summary>
+</histogram>
+
+<histogram name="Net.HttpTimeToFirstByte" units="milliseconds">
+ <summary>
+ Time from when an HTTP request is issued to when the first byte is
+ processed.
+ </summary>
+</histogram>
+
+<histogram name="Net.IOError_SocketReuseType" enum="HttpSocketType">
+ <summary>
+ The count of handleable socket errors (connection abort/close/reset) per
+ socket reuse type.
+ </summary>
+</histogram>
+
+<histogram name="Net.IOError_SocketReuseType_disable_late_binding"
+ enum="HttpSocketType">
+ <obsolete>
+ Late bindings are on by default now.
+ </obsolete>
+ <summary>
+ The count of handleable socket errors (connection abort/close/reset) per
+ socket reuse type. Socket late binding is disabled.
+ </summary>
+</histogram>
+
+<histogram name="Net.IOError_SocketReuseType_enable_late_binding"
+ enum="HttpSocketType">
+ <obsolete>
+ Late bindings are on by default now.
+ </obsolete>
+ <summary>
+ The count of handleable socket errors (connection abort/close/reset) per
+ socket reuse type. Socket late binding is enabled.
+ </summary>
+</histogram>
+
+<histogram name="Net.IPv6ConnectDuration" units="milliseconds">
+ <summary>Duration of time spent during the UDP-connect IPv6 probe.</summary>
+</histogram>
+
+<histogram name="Net.IPv6ConnectFailureMatch" enum="BooleanSuccess">
+ <summary>
+ Whether the the interface-enumeration IPv6 probe method failed given that
+ the UDP-connect IPV6 probe failed.
+ </summary>
+</histogram>
+
+<histogram name="Net.IPv6ConnectSuccessMatch" enum="BooleanSuccess">
+ <summary>
+ Whether the the interface-enumeration IPv6 probe method was successful given
+ that the UDP-connect IPV6 probe was successful.
+ </summary>
+</histogram>
+
+<histogram name="Net.IPv6Status" enum="IPV6ProbeResult">
+ <summary>The probe results when a test for IPv6 support is done.</summary>
+</histogram>
+
+<histogram name="Net.IPv6Status_retest" enum="IPV6ProbeResult">
+ <summary>
+ The probe results when a test for IPv6 support is done, after a network
+ change event.
+ </summary>
+</histogram>
+
+<histogram name="Net.MTPR_GetProxyForUrl_Thread_Wait_Time" units="milliseconds">
+ <summary>
+ The time that a (non-cancelled) proxy resolution request was stalled waiting
+ for an execution thread, for MultiThreadedProxyResolver.
+ </summary>
+</histogram>
+
+<histogram name="Net.MTPR_GetProxyForUrl_Time" units="milliseconds">
+ <summary>
+ The total time that it took for a (non-cancelled) proxy resolution request
+ to complete, for MultiThreadedProxyResolver.
+ </summary>
+</histogram>
+
+<histogram name="Net.NetworkErrorsRecovered.MainFrame" enum="NetErrorCodes">
+ <summary>
+ How often automatically retrying to download the main frame of a page in
+ response to specific HTTP network errors succeeds.
+ </summary>
+</histogram>
+
+<histogram name="Net.NetworkErrorsRecovered.Subresource" enum="NetErrorCodes">
+ <summary>
+ How often automatically retrying to download a subresource in response to
+ specific HTTP network errors succeeds.
+ </summary>
+</histogram>
+
+<histogram name="Net.NetworkErrorsUnrecovered.MainFrame" enum="NetErrorCodes">
+ <summary>
+ How often automatically retrying to download the main frame of a page in
+ response to specific HTTP network errors returns another network error.
+ Histogram includes only the error code that triggered the retry.
+ </summary>
+</histogram>
+
+<histogram name="Net.NetworkErrorsUnrecovered.Subresource" enum="NetErrorCodes">
+ <summary>
+ How often automatically retrying to download a subresource in response to
+ specific HTTP network errors returns another network error. Histogram
+ includes only the error code that triggered the retry.
+ </summary>
+</histogram>
+
+<histogram name="Net.NotifyAddrChangeFailures">
+ <summary>
+ On Windows, NetworkChangeNotifierWin calls NotifyAddrChange, which can fail
+ for unknown reasons. This records the number of times it fails in a row
+ before a successful call. If it never succeeds, or takes over 100 tries, a
+ value of 100 is recorded. See http://crbug.com/69198
+ </summary>
+</histogram>
+
+<histogram name="Net.NumDuplicateCookiesInDb">
+ <summary>
+ The number of duplicate cookies that were present in the cookie store during
+ startup.
+ </summary>
+</histogram>
+
+<histogram name="Net.OCSPRequestFailedTimeMs" units="milliseconds">
+ <summary>
+ When validating an HTTPS certificate we may have to make one or more HTTP
+ fetches to OCSP responders in order to get revocation information. This
+ measures the amount of time that failures to get OCSP information take.
+ </summary>
+</histogram>
+
+<histogram name="Net.OCSPRequestSuccess" enum="BooleanSuccess">
+ <summary>
+ When validating an HTTPS certificate we may have to make one or more HTTP
+ fetches to OCSP responders in order to get revocation information. This
+ records the fraction of successful requests.
+ </summary>
+</histogram>
+
+<histogram name="Net.OCSPRequestTimeMs" units="milliseconds">
+ <summary>
+ When validating an HTTPS certificate we may have to make one or more HTTP
+ fetches to OCSP responders in order to get revocation information. This
+ measures the amount of time that each of those requests takes.
+ </summary>
+</histogram>
+
+<histogram name="Net.OSErrorsForGetAddrinfo" enum="ErrorCodesGetaddrinfo_All">
+ <summary>
+ Positive error code that was returned by the system library
+ &quot;getaddrinfo()&quot;. This error code is platform specific, so when
+ there is a Windows/Linux conflict, both decodings are shown.
+ </summary>
+</histogram>
+
+<histogram name="Net.OSErrorsForGetAddrinfo_Linux"
+ enum="ErrorCodesGetaddrinfo_Linux">
+ <summary>
+ Positive error code that was returned by the system library
+ &quot;getaddrinfo()&quot;.
+ </summary>
+</histogram>
+
+<histogram name="Net.OSErrorsForGetAddrinfo_Mac"
+ enum="ErrorCodesGetaddrinfo_Mac">
+ <summary>
+ Positive error code that was returned by the system library
+ &quot;getaddrinfo()&quot;.
+ </summary>
+</histogram>
+
+<histogram name="Net.OSErrorsForGetAddrinfo_Win"
+ enum="ErrorCodesGetaddrinfo_Win">
+ <summary>
+ Positive error code that was returned by the system library
+ &quot;getaddrinfo()&quot;.
+ </summary>
+</histogram>
+
+<histogram name="Net.PreconnectedLinkNavigations" enum="PreconnectedNavigation">
+ <summary>
+ Indicate whether a link navigation was preceded by a recent pre-connect
+ trigger (within 10 seconds). There is a high chance that loading the page
+ used a preconnected TCP session.
+ </summary>
+</histogram>
+
+<histogram name="Net.PreconnectedNavigation" enum="PreconnectedNavigation">
+ <summary>
+ Indicate whether a URLRequest was preceded by a recent pre-connect trigger
+ (within 10 seconds). There is a high chance that loading the resource used a
+ preconnected TCP session.
+ </summary>
+</histogram>
+
+<histogram name="Net.PreconnectMotivation" enum="PreconnectMotivation">
+ <summary>
+ When a preconnection is made, indicate what the motivation was.
+ </summary>
+ <details>
+ Currently, the most common (only?) motivations are SELF_REFERAL,
+ LEARNED_REFERAL and OMNIBOX. The SELF_REFERAL indicates that we made sure a
+ second connection was available for a resource that either was never before
+ seen, or has historically had no subresources. The LEARNED_REFERAL
+ indicates that we &quot;learned&quot; that a subresource was commonly
+ needed, and that motivated the TCP/IP preconnect. The OMNIBOX motivation
+ happens when a search is being suggested, and we preconnect to the search
+ provider. (WARNING: Prior to version 7.517.*, enums 7, 8, and 9 may be
+ confused, as EARLY_LOAD_MOTIVATED was inserted new 6 value.)
+ </details>
+</histogram>
+
+<histogram name="Net.PreconnectProxyStatus" enum="ProxyStatus">
+ <summary>
+ Indicate whether there was a proxy to preclude preconnection.
+ </summary>
+</histogram>
+
+<histogram name="Net.PreconnectSubresourceEval"
+ enum="PreconnectSubresourceEval">
+ <summary>
+ What did we decide to do about a predicted resource, based on the historical
+ expected number of connection that this subresource will require.
+ </summary>
+ <details>
+ This is basically the current thresholding of the SubresourceExpectation,
+ relative to current static thresholds, and taking into account whether
+ preconnection is enabled (i.e., if preconnection is disabled, we'll never
+ decide to preconnect).
+ </details>
+</histogram>
+
+<histogram name="Net.PreconnectSubresourceExpectation">
+ <summary>
+ The expected number of connections, times 100, that we'll make to a given
+ subresource, based on learned history.
+ </summary>
+ <details>
+ By comparing this to thresholds, we decide if we will preconnect,
+ preresolve, or do nothing. This histogram can be used to select those static
+ thresholds.
+ </details>
+</histogram>
+
+<histogram name="Net.PreconnectTriggerUsed" enum="PreconnectTriggerUsed">
+ <summary>
+ Indicate whether if a preconnect trigger is followed by a resource request
+ (from link navigations) to the host or not. This is to measure precision of
+ link-based preconnect triggers.
+ </summary>
+</histogram>
+
+<histogram name="Net.PreconnectUtilization" enum="NetPreconnectUtilization">
+ <obsolete>
+ Sourced data corrected, and replaced by NetPreconnectUtilization2
+ </obsolete>
+ <summary>
+ Indicate final utilization for each attempted socket connection.
+ </summary>
+ <details>
+ We also include stats for non-speculative sockets. Some socket connections
+ may never connect, and others may never be used (as the user may abort
+ before then).
+ </details>
+</histogram>
+
+<histogram name="Net.PreconnectUtilization2" enum="NetPreconnectUtilization">
+ <summary>
+ Indicate final utilization for each attempted socket connection.
+ </summary>
+ <details>
+ We also include stats for non-speculative sockets. Some socket connections
+ may never connect, and others may never be used (as the user may abort
+ before then).
+ </details>
+</histogram>
+
+<histogram name="Net.Priority_High_Latency" units="milliseconds">
+ <obsolete>
+ Replaced by Net.Priority_High_Latency_b.
+ </obsolete>
+ <summary>
+ Time from the start of the http transaction until the first byte of the
+ response for high priority (currently frame and subframe) requests. Only
+ times under 10 minutes are recorded.
+ </summary>
+</histogram>
+
+<histogram name="Net.Priority_High_Latency_b" units="milliseconds">
+ <summary>
+ Time from the start of the http transaction until the first byte of the
+ response for high priority (currently frame and subframe) requests.
+ </summary>
+</histogram>
+
+<histogram name="Net.Priority_Low_Latency" units="milliseconds">
+ <obsolete>
+ Replaced by Net.Priority_Low_Latency_b.
+ </obsolete>
+ <summary>
+ Time from the start of the http transaction until the first byte of the
+ response for low priority (non-frame/subframe) requests. Only times under
+ 10 minutes are recorded.
+ </summary>
+</histogram>
+
+<histogram name="Net.Priority_Low_Latency_b" units="milliseconds">
+ <summary>
+ Time from the start of the http transaction until the first byte of the
+ response for low priority (non-frame/subframe) requests.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyPollConfigurationTime">
+ <summary>
+ The time in milliseconds spent fetch the system proxy configuration, when
+ polling it for changes.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.AbandonedExecutionTotalTime"
+ units="milliseconds">
+ <summary>
+ The total amount of time that was spent executing the proxy script during
+ &quot;tracing&quot; runs (executions of the script which discovered a new
+ DNS dependency and were subsequently abandoned).
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.AbandonedExecutionTotalTime"
+ units="milliseconds">
+ <summary>
+ The total amount of time that was spent executing the proxy script during
+ &quot;tracing&quot; runs (executions of the script which discovered a new
+ DNS dependency and were subsequently abandoned).
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.DnsWaitTotalTime"
+ units="milliseconds">
+ <summary>
+ The total amount of time that was spent in the non-blocking DNS bindings
+ while executing PAC scripts. This includes the times for abandoned
+ executions.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.ExecutionTime"
+ units="milliseconds">
+ <summary>
+ The amount of time inside of V8 that the proxy script spent executing for
+ the final pass. This includes the time spent in the javascript bindings.
+ This does not include the time spent in abandoned execution passes.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.NumAlerts">
+ <summary>
+ The number of times that alert() was called in the final execution of the
+ script.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.NumErrors">
+ <summary>
+ The number of errors that were seen in the final execution of the script.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.NumRestarts">
+ <summary>
+ The number of times that the PAC script execution was restarted.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.TotalTime"
+ units="milliseconds">
+ <summary>
+ The total time that the proxy resolution took. This includes all the time
+ spent waiting for DNS, PAC script execution, and restarts.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.TotalTimeDNS"
+ units="milliseconds">
+ <summary>
+ The total time that proxy resolution spent waiting for DNS. This also
+ includes any queuing delays on the origin thread waiting for the DNS result
+ to be processed.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.BlockingDNSMode.UniqueDNS">
+ <summary>
+ The number of unique DNS hostnames that the PAC script tried to resolve. The
+ *Ex() versions of the bindings count separately.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.DnsWaitTotalTime" units="milliseconds">
+ <summary>
+ The total amount of time that was spent in the non-blocking DNS bindings
+ while executing PAC scripts. This includes the times for abandoned
+ executions.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.ExecutionTime" units="milliseconds">
+ <summary>
+ The amount of time inside of V8 that the proxy script spent executing for
+ the final pass. This includes the time spent in the javascript bindings
+ (which is probably dominated by Net.ProxyResolver.DnsWaitTotalTime). This
+ does not include the time spent in abandoned execution passes.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.NumAlerts">
+ <summary>
+ The number of times that alert() was called in the final execution of the
+ script.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.NumErrors">
+ <summary>
+ The number of errors that were seen in the final execution of the script.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.NumRestarts">
+ <summary>
+ The number of times that the PAC script execution was restarted.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.OriginThreadLatency" units="milliseconds">
+ <summary>
+ The amount of time it took upon completion to run the final task posted back
+ to the IO thread.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.TotalTime" units="milliseconds">
+ <summary>
+ The total time that the proxy resolution took. This includes all the time
+ spent waiting for DNS, PAC script execution, and restarts.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.TotalTimeDNS" units="milliseconds">
+ <summary>
+ The total time that proxy resolution spent waiting for DNS. This also
+ includes any queuing delays on the origin thread waiting for the DNS result
+ to be processed.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.TotalTimeWorkerThread" units="milliseconds">
+ <summary>
+ The total time that the proxy resolution took, not including the post back
+ to the origin thread. This includes all the time spent waiting for DNS, PAC
+ script execution, and restarts.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.UniqueDNS">
+ <summary>
+ The number of unique DNS hostnames that the PAC script tried to resolve. The
+ *Ex() versions of the bindings count separately.
+ </summary>
+</histogram>
+
+<histogram name="Net.ProxyResolver.URLSize">
+ <summary>The length of the URL that was passed into the PAC script.</summary>
+</histogram>
+
+<histogram name="Net.PublicKeyPinFailureDomain" enum="PublicKeyPinFailedDomain">
+ <summary>
+ Second-level domains for which we have observed public key pinning failures.
+ </summary>
+</histogram>
+
+<histogram name="Net.PublicKeyPinSuccess" enum="BooleanSuccess">
+ <summary>
+ A validated certificate chain may be subject to additional
+ &quot;pinning&quot; requirements on a per-domain basis. This records the
+ fraction of successful matches between a certificate chain and a pin list.
+ </summary>
+</histogram>
+
+<histogram name="Net.QuicCryptoHandshakeState" enum="QuicHandshakeState">
+ <summary>
+ The state of a QUIC connection's crypto hanshake as it progresses from
+ starting to confirmation or failure.
+ </summary>
+</histogram>
+
+<histogram name="Net.QuicNumSentClientHellos">
+ <summary>The number of client hello messages sent.</summary>
+</histogram>
+
+<histogram name="Net.QuicNumSentClientHellosCryptoHandshakeConfirmed">
+ <summary>
+ The number of client hello messages sent when the crypto handshake was
+ confirmed.
+ </summary>
+</histogram>
+
+<histogram name="Net.QuicSession.CloseSessionOnError" enum="NetErrorCodes">
+ <summary>
+ The network error code which resulted in the session being closed.
+ </summary>
+</histogram>
+
+<histogram name="Net.QuicSession.ConnectionCloseErrorCode"
+ enum="QuicErrorCodes">
+ <summary>
+ The QUIC error code which resulted in the connection being closed.
+ </summary>
+</histogram>
+
+<histogram name="Net.QuicSession.OutOfOrderPacketsReceived">
+ <summary>
+ The number of times packets the current received packet had a lower sequence
+ number than the previously received packet sequence number.
+ </summary>
+</histogram>
+
+<histogram name="Net.QuicSession.PacketGapReceived">
+ <summary>
+ The number of missing packets between the current received packet and the
+ previously largest received packet sequence number.
+ </summary>
+</histogram>
+
+<histogram name="Net.QuicSession.PacketGapSent">
+ <summary>
+ The number of missing packets between the current received packet and the
+ previously largest received packet sequence number, as reported by the
+ remote end of the connection.
+ </summary>
+</histogram>
+
+<histogram name="Net.QuicSession.QuicVersion">
+ <summary>Version of the QUIC protocol used for this connection.</summary>
+</histogram>
+
+<histogram name="Net.RenegotiationExtensionSupported">
+ <summary>
+ True if the HTTP request was sent to a server which supports the TLS
+ renegotiation extension.
+ </summary>
+</histogram>
+
+<histogram name="Net.ResourceLoader.ReadDeferral" units="milliseconds">
+ <summary>
+ When starting a cross-site navigation, the time between reading the headers
+ and body of the response.
+ </summary>
+</histogram>
+
+<histogram name="Net.SocketIdleTimeBeforeNextUse_ReusedSocket">
+ <summary>The time an already used socket sat idle before being used.</summary>
+</histogram>
+
+<histogram name="Net.SocketIdleTimeBeforeNextUse_UnusedSocket">
+ <summary>
+ The time an unused socket (all HTTP sockets, regardless of any proxy used)
+ sat idle before being used.
+ </summary>
+</histogram>
+
+<histogram name="Net.SocketIdleTimeOnIOError2_ReusedSocket">
+ <summary>
+ The time a previously used socket sat idle before encountering a recoverable
+ socket IO error (connection abort/reset/close).
+ </summary>
+</histogram>
+
+<histogram name="Net.SocketIdleTimeOnIOError2_UnusedSocket">
+ <summary>
+ The time an unused socket sat idle before encountering a recoverable socket
+ IO error (connection abort/reset/close).
+ </summary>
+</histogram>
+
+<histogram name="Net.SocketInitErrorCodes" enum="NetErrorCodes">
+ <summary>
+ Net error codes that socket initializations end with, including net::OK and
+ net::ERR_ABORTED.
+ </summary>
+</histogram>
+
+<histogram name="Net.SocketRequestTime">
+ <summary>
+ Time in milliseconds from initial RequestSocket() call until successfully
+ acquiring a connected socket.
+ </summary>
+</histogram>
+
+<histogram name="Net.SocketStream.ConnectionEstablish" units="milliseconds">
+ <summary>The time from the connection start to connection establish.</summary>
+</histogram>
+
+<histogram name="Net.SocketStream.ConnectionLatency" units="milliseconds">
+ <summary>The time waiting to be ready to start connecting.</summary>
+</histogram>
+
+<histogram name="Net.SocketStream.ConnectionType"
+ enum="SocketStreamConnectionType">
+ <summary>
+ Each bucket is the number of connection type of socket stream.
+ </summary>
+</histogram>
+
+<histogram name="Net.SocketStream.Duration" units="milliseconds">
+ <summary>The time a socket stream was open.</summary>
+</histogram>
+
+<histogram name="Net.SocketStream.ProtocolType" enum="SocketStreamProtocolType">
+ <summary>
+ Each bucket is the number of protocol type on socket stream.
+ </summary>
+</histogram>
+
+<histogram name="Net.SocketStream.ReceivedBytes" units="bytes">
+ <summary>Number of bytes on a socket stream.</summary>
+</histogram>
+
+<histogram name="Net.SocketStream.ReceivedCounts">
+ <summary>Number of reads on a socket stream.</summary>
+</histogram>
+
+<histogram name="Net.SocketStream.SentBytes" units="bytes">
+ <summary>Number of bytes on a socket stream.</summary>
+</histogram>
+
+<histogram name="Net.SocketStream.SentCounts">
+ <summary>Number of Write on a socket stream.</summary>
+</histogram>
+
+<histogram name="Net.SocketType" enum="HttpSocketType">
+ <summary>
+ The counts of the type of sockets returned by the socket pools.
+ </summary>
+</histogram>
+
+<histogram name="Net.SOCKSSocketIdleTimeBeforeNextUse_ReusedSocket">
+ <obsolete>
+ see SocketIdleTimeBeforeNextUse_ReusedSocket_SOCK
+ </obsolete>
+ <summary>
+ The time an already used SOCKS socket sat idle before being used.
+ </summary>
+</histogram>
+
+<histogram name="Net.SOCKSSocketIdleTimeBeforeNextUse_UnusedSocket">
+ <obsolete>
+ see SocketIdleTimeBeforeNextUse_UnusedSocket_SOCK
+ </obsolete>
+ <summary>The time an unused SOCKS socket sat idle before being used.</summary>
+</histogram>
+
+<histogram name="Net.SOCKSSocketRequestTime" units="milliseconds">
+ <obsolete>
+ see SocketRequestTime_SOCK
+ </obsolete>
+ <summary>
+ Time from initial SOCKSClientSocketPool::RequestSocket() call until
+ successfully acquiring a connected SOCKS socket.
+ </summary>
+</histogram>
+
+<histogram name="Net.SocksSocketRequestTime">
+ <summary>Time it takes to request a new (unused) SOCKS proxy socket.</summary>
+</histogram>
+
+<histogram name="Net.SOCKSSocketType" enum="HttpSocketType">
+ <obsolete>
+ see SocketType_SOCK
+ </obsolete>
+ <summary>
+ The counts of the type of sockets returned by the SOCKS pool.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyConnectionLatency" units="milliseconds">
+ <summary>Time from when the Connect() starts until it completes.</summary>
+</histogram>
+
+<histogram name="Net.SpdyFrameStreamAndSessionFlowControlState"
+ enum="SpdyFrameFlowControlState">
+ <summary>
+ The counts of the flow control state of each frame (with stream and session
+ flow control on).
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyFrameStreamFlowControlState"
+ enum="SpdyFrameFlowControlState">
+ <summary>
+ The counts of the flow control state of each frame (with stream flow control
+ on).
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyIPPoolDomainMatch" enum="SpdyIPPoolDomainMatch"
+ units="count">
+ <summary>
+ Status of checking if a SPDY domain can handle a IP match. If a match is
+ found, we successfully used the IP Pooling. If a match is not found, we
+ could have used IP Pooling, except the TLS Cert didn't match the IP-pooled
+ domain.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyPing.RTT" units="milliseconds">
+ <summary>The RTT for SPDY's PING.</summary>
+</histogram>
+
+<histogram name="Net.SpdyPriorityCount">
+ <summary>The count of streams at each priority over Spdy sessions.</summary>
+</histogram>
+
+<histogram name="Net.SpdyRecvBytes" units="bytes">
+ <summary>The number of bytes recevied per stream.</summary>
+</histogram>
+
+<histogram name="Net.SpdySendBytes" units="bytes">
+ <summary>The number of bytes sent per stream.</summary>
+</histogram>
+
+<histogram name="Net.SpdySession.BytesRead.EOF" units="bytes">
+ <summary>
+ Total number of bytes recevied per session before closing session due to
+ EOF.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySession.BytesRead.OtherErrors" units="bytes">
+ <summary>
+ Total number of bytes recevied per session before closing session due to an
+ error during read.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySession.ClosedOnError" enum="NetErrorCodes">
+ <summary>
+ Net error codes when SpdySession was closed, doesn't inlcuding net::OK.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySession.CreateStreamWithSocketConnected"
+ enum="BooleanSuccess">
+ <summary>Socket connected status in SpdySession::CreateStream.</summary>
+</histogram>
+
+<histogram name="Net.SpdySessionErrorDetails" enum="SpdyProtocolErrorDetails"
+ units="count">
+ <obsolete>
+ Replaced by SpdySessionErrorDetails2 on 2013-04-19.
+ </obsolete>
+ <summary>
+ WARNING: r181910 added an enum value in the middle, so don't trust the
+ counts for values 9 and above for Chrome builds after that revision.
+
+ The type of SPDY Protocol error encountered.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySessionErrorDetails2" enum="SpdyProtocolErrorDetails2"
+ units="count">
+ <summary>The type of SPDY Protocol error encountered.</summary>
+</histogram>
+
+<histogram name="Net.SpdySessionErrorDetails_Google"
+ enum="SpdyProtocolErrorDetails" units="count">
+ <obsolete>
+ Replaced by SpdySessionErrorDetails_Google2 on 2013-04-19.
+ </obsolete>
+ <summary>
+ The type of SPDY Protocol error encountered when talking to a google.com
+ server.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySessionErrorDetails_Google2"
+ enum="SpdyProtocolErrorDetails2" units="count">
+ <summary>
+ WARNING: r181910 added an enum value in the middle, so don't trust the
+ counts for values 9 and above for Chrome builds after that revision.
+
+ The type of SPDY Protocol error encountered when talking to a google.com
+ server.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySessionGet" enum="SpdySessionGet" units="count">
+ <summary>The type of SPDY Session used when looking up a session.</summary>
+</histogram>
+
+<histogram name="Net.SpdySessionGetPeerAddressNotConnected"
+ enum="BooleanSuccess">
+ <summary>
+ Whether SpdySession::Get{Peer,Local}Address was called when the connection
+ had no socket.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySessions_DataReductionProxy"
+ enum="BooleanDataReductionProxy">
+ <summary>
+ The count of SPDY sessions using the data reduction proxy and the count of
+ other SPDY sessions.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySessionSocketNotConnectedGetLocalAddress"
+ enum="BooleanSuccess">
+ <summary>
+ SpdySession::GetLocalAddress returned ERR_SOCKET_NOT_CONNECTED.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySessionSocketNotConnectedGetPeerAddress"
+ enum="BooleanSuccess">
+ <summary>
+ SpdySession::GetPeerAddress returned ERR_SOCKET_NOT_CONNECTED.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySessionsWithStalls">
+ <summary>The count of SPDY Sessions with or without stalls.</summary>
+</histogram>
+
+<histogram name="Net.SpdySettingsCwnd" units="packets">
+ <summary>
+ The congestion window (in pkts) received at the end of a SpdySession.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySettingsCwndSent" units="packets">
+ <summary>
+ The congestion window (in pkts) sent at the beginning of a SpdySession.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySettingsReceived" enum="SpdySettingsReceived"
+ units="%">
+ <summary>
+ Percentage of sessions which received settings from the server.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySettingsRetransRate" units="%">
+ <summary>
+ The Download Retransmission Rate (%) received at the end of a SpdySession.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySettingsRTT" units="milliseconds">
+ <summary>The RTT received at the end of a SpdySession.</summary>
+</histogram>
+
+<histogram name="Net.SpdySettingsSent" enum="SpdySettingsSent" units="%">
+ <summary>Percentage of sessions which sent settings to the server.</summary>
+</histogram>
+
+<histogram name="Net.SpdyStreamDownloadTime" units="milliseconds">
+ <summary>
+ The time between receiving the the first chunk and the last chunk of data on
+ a Spdy stream.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyStreamsAbandonedPerSession">
+ <summary>
+ The number of pushed, but abandoned streams over a single session.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyStreamsPerSession">
+ <summary>The number of streams issued over a single session.</summary>
+</histogram>
+
+<histogram name="Net.SpdyStreamsPushedAndClaimedPerSession">
+ <summary>
+ The number of pushed, and used streams over a single session.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyStreamsPushedPerSession">
+ <summary>The number of push streams received over a single session.</summary>
+</histogram>
+
+<histogram name="Net.SpdyStreamStallsPerSession">
+ <summary>The number of stream stalls per session.</summary>
+</histogram>
+
+<histogram name="Net.SpdyStreamTime" units="milliseconds">
+ <summary>
+ The time of a Spdy stream. Measured from sending the first chunk to
+ receiving the last chunk of data.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyStreamTimeToFirstByte" units="milliseconds">
+ <summary>
+ The time between sending the request and receiving the first chunk of data
+ on a Spdy stream.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdySynStreamCompressionPercentage">
+ <summary>
+ The percent compression achieved when compression SYN_STREAM frames.
+ </summary>
+</histogram>
+
+<histogram name="Net.SpdyVersion" enum="ProtocolVersion">
+ <summary>
+ The SPDY protocol version that is used to talk to SPDY servers.
+ </summary>
+</histogram>
+
+<histogram name="Net.SSL_CipherSuite" enum="SSLCipherSuite">
+ <summary>The SSL/TLS cipher suite that was negotiated.</summary>
+</histogram>
+
+<histogram name="Net.SSL_Connection_Latency" units="milliseconds">
+ <summary>Time from when the Connect() starts until it completes.</summary>
+</histogram>
+
+<histogram name="Net.SSL_Connection_Latency_DataReductionProxy"
+ units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes when using the data
+ reduction proxy. This includes certificate retrieval and verification.
+ </summary>
+</histogram>
+
+<histogram name="Net.SSL_Connection_Latency_Google" units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes for google.com and
+ any subdomain of it.
+ </summary>
+</histogram>
+
+<histogram name="Net.SSL_Connection_Latency_Google_No_Revocation_Checking"
+ units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes for google.com and
+ any subdomain of it. This only includes users in a 50% field trial that
+ disables revocation checking for certificate pinned sites.
+ </summary>
+</histogram>
+
+<histogram name="Net.SSL_Connection_Latency_Google_Revocation_Checking"
+ units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes for google.com and
+ any subdomain of it. This only includes users not in a 50% field trail that
+ disables revocation for certificate pinned sites.
+ </summary>
+</histogram>
+
+<histogram name="Net.SSLCertBlacklisted">
+ <summary>
+ Counts the number of times that users have hit blacklisted certificates. The
+ indexes match up to the indexes in
+ net/base/x509_certificate.cc:IsBlacklisted. The details of the certificates
+ in question is confidential.
+ </summary>
+</histogram>
+
+<histogram name="Net.SSLCertVerificationTime" units="milliseconds">
+ <summary>Time to complete a certificate verification (success case).</summary>
+</histogram>
+
+<histogram name="Net.SSLCertVerificationTimeError" units="milliseconds">
+ <summary>Time to complete a certificate verification (error case).</summary>
+</histogram>
+
+<histogram name="Net.SSLHostInfoDNSLookup" units="milliseconds">
+ <summary>Time to complete a DNS lookup for a DNS CAA record.</summary>
+</histogram>
+
+<histogram name="Net.SSLHostInfoDNSLookupDelayMs" units="milliseconds">
+ <summary>
+ Time that we would have wasted had we waited for a CAA lookup in order to
+ validate a certificate.
+ </summary>
+</histogram>
+
+<histogram name="Net.SSLHostInfoVerificationTimeMs" units="milliseconds">
+ <summary>Time to complete a speculative certificate verification.</summary>
+</histogram>
+
+<histogram name="Net.SSLv3FallbackToRenegoPatchedServer"
+ enum="TLSRenegotiationPatched">
+ <summary>
+ The number of times that we have performed SSLv3 fallback and found a TLS
+ renegotiation patched server.
+ </summary>
+</histogram>
+
+<histogram name="Net.SSLVerificationMerged">
+ <summary>Was a speculative certificate verification used?</summary>
+</histogram>
+
+<histogram name="Net.SSLVerificationMergedMsSaved" units="milliseconds">
+ <summary>Time saved by a speculative certificate vertification.</summary>
+</histogram>
+
+<histogram name="Net.TCP_Connection_Idle_Sockets">
+ <summary>Number of idle sockets when the Connect() succeeded.</summary>
+</histogram>
+
+<histogram name="Net.TCP_Connection_Latency" units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes. Only times under 10
+ minutes are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCP_Connection_Latency_IPv4_No_Race" units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes when the network
+ address only contains IPv4 addresses. Only times under 10 minutes are
+ logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCP_Connection_Latency_IPv4_Wins_Race"
+ units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes when the IPv4
+ fallback connection won the race against IPv6. Only times under 10 minutes
+ are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCP_Connection_Latency_IPv6_Raceable" units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes when we race an IPv6
+ connection against an IPv4 connection with a 300ms delay. Only times under
+ 10 minutes are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCP_Connection_Latency_IPv6_Solo" units="milliseconds">
+ <summary>
+ Time from when the Connect() starts until it completes when the network
+ address only contains IPv6 addresses. Only times under 10 minutes are
+ logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.TcpFastOpenSocketConnection" enum="TcpSocketStatus">
+ <summary>
+ For sockets for which a TCP Fast Open protocol might be used, the result of
+ trying to use it.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCPForSOCKSSocketIdleTimeBeforeNextUse_ReusedSocket">
+ <obsolete>
+ see SocketIdleTimeBeforeNextUse_ReusedSocket_TCPforSOCKS
+ </obsolete>
+ <summary>
+ The time an already used TCP socket sat idle before being used for a SOCKS
+ request.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCPForSOCKSSocketIdleTimeBeforeNextUse_UnusedSocket">
+ <obsolete>
+ see SocketIdleTimeBeforeNextUse_UnusedSocket_TCPforSOCKS
+ </obsolete>
+ <summary>
+ The time an unused TCP socket sat idle before being used for a SOCKS
+ request.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCPForSOCKSSocketRequestTime" units="milliseconds">
+ <obsolete>
+ see SocketRequestTime_TCPforSOCKS
+ </obsolete>
+ <summary>
+ Time from initial SOCKSClientSocketPool::RequestSocket() call until
+ successfully acquiring a connected TCP socket.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCPForSOCKSSocketType" enum="HttpSocketType">
+ <obsolete>
+ see SocketType_TCPforSOCKS
+ </obsolete>
+ <summary>
+ The counts of the type of sockets returned by the TCP pool used by the SOCKS
+ pool.
+ </summary>
+</histogram>
+
+<histogram name="Net.TCPSocketType" enum="HttpSocketType">
+ <obsolete>
+ Was only used for HTTP[S] connections, renamed to Net.HTTPSocketType.
+ </obsolete>
+ <summary>The counts of the type of TCP socket returned.</summary>
+</histogram>
+
+<histogram name="Net.Transaction_Bandwidth" units="KB/s">
+ <summary>
+ (discontinued as of 4/12/09) Effective bandwidth in KByte/Second of
+ transactions logged to Transaction_Latency histogram. Note that only
+ samples durations greater than zero ms, and less than 1 hour are tallied
+ into this ratio.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Connected" units="milliseconds">
+ <summary>
+ Time from the when the network transaction is requested, until the first
+ byte of the header is received.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Connected_New" units="milliseconds">
+ <obsolete>
+ Replaced by Net.Transaction_Connected_New_b.
+ </obsolete>
+ <summary>
+ When a new connection is established, the time from the when the network
+ transaction is requested, until the first byte of the header is received.
+ Only items under 10 minutes are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Connected_New_b" units="milliseconds">
+ <summary>
+ When a new connection is established, the time from the when the network
+ transaction is requested, until the first byte of the header is received.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Connected_Under_10" units="milliseconds">
+ <obsolete>
+ Replaced by Net.Transaction_Connected.
+ </obsolete>
+ <summary>
+ Time from the when the network transaction is requested, until the first
+ byte of the header is received. Only items under 10 minutes are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Latency" units="milliseconds">
+ <obsolete>
+ Replaced by Net.Transaction_Latency_b.
+ </obsolete>
+ <summary>
+ Time from first byte sent until last byte received by the new network stack.
+ Only items under 1 hour are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Latency_b" units="milliseconds">
+ <summary>
+ Time from first byte sent until last byte received by the new network stack.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Latency_Total" units="milliseconds">
+ <summary>
+ Time from when a network transaction is requested until last byte received
+ by the new network stack.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Latency_Total_New_Connection"
+ units="milliseconds">
+ <summary>
+ When an existing TCP/IP connection is NOT reused, the time from when a
+ network transaction is requested until last byte received by the new network
+ stack.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Latency_Total_New_Connection_Under_10"
+ units="milliseconds">
+ <obsolete>
+ Replaced by Net.Transaction_Latency_Total_New_Connection.
+ </obsolete>
+ <summary>
+ When an existing TCP/IP connection is NOT reused, the time from when a
+ network transaction is requested until last byte received by the new network
+ stack. Only items under 10 minutes are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Latency_Total_Under_10" units="milliseconds">
+ <obsolete>
+ Replaced by Net.Transaction_Latency_Total.
+ </obsolete>
+ <summary>
+ Time from when a network transaction is requested until last byte received
+ by the new network stack. Only items under 10 minutes are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Latency_Under_10" units="milliseconds">
+ <obsolete>
+ Replaced by Net.Transaction_Latency.
+ </obsolete>
+ <summary>
+ Time from first byte sent until last byte received by the new network stack.
+ Only items under 10 minutes are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.Transaction_Latency_WinHTTP" units="milliseconds">
+ <summary>
+ Time from first byte sent until last byte received with old WinHTTP network
+ stack. Only items under 1 hour are logged.
+ </summary>
+</histogram>
+
+<histogram name="Net.TransportSocketIdleTimeBeforeNextUse_ReusedSocket">
+ <obsolete/>
+ <summary>
+ The time an already used TCP socket sat idle before being used (either for
+ direct or non-socks use).
+ </summary>
+</histogram>
+
+<histogram name="Net.TransportSocketIdleTimeBeforeNextUse_UnusedSocket">
+ <obsolete/>
+ <summary>
+ The time an unused TCP socket sat idle before being used (either for direct
+ or non-socks use).
+ </summary>
+</histogram>
+
+<histogram name="Net.TransportSocketRequestTime" units="milliseconds">
+ <obsolete/>
+ <summary>
+ Time from initial ClientSocketPool::RequestSocket() call until successfully
+ acquiring a connected socket (either for direct or non-socks use).
+ </summary>
+</histogram>
+
+<histogram name="Net.TransportSocketType" enum="HttpSocketType">
+ <obsolete/>
+ <summary>
+ The counts of the type of sockets returned by the TCP pool (either for
+ direct or non-socks use).
+ </summary>
+</histogram>
+
+<histogram name="Net.UDPSocketWinClose" units="milliseconds">
+ <summary>The time spent in closesocket call in UDPSocketWin::Close.</summary>
+</histogram>
+
+<histogram name="Net.Wifi.InterfaceCount">
+ <summary>
+ The number of Wi-fi adapters on the computer. Because the histogram is
+ logged each time Chrome performs a Wi-fi scan, it's better to see results in
+ the &quot;user count&quot; view.
+ </summary>
+</histogram>
+
+<histogram name="Net.Wifi.LbsLatency" units="milliseconds">
+ <summary>The time that a request to Location Based Services takes.</summary>
+</histogram>
+
+<histogram name="Net.Wifi.ScanLatency" units="milliseconds">
+ <summary>The time that a Wi-fi scan takes.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.0.NetworkError" enum="NetErrorCodes">
+ <summary>
+ The network error, if any, of the first pipeline connectivity request.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.0.ResponseCode">
+ <summary>
+ The HTTP response code, if any, of the first pipeline connectivity response.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.0.Status" enum="HttpPipelineStatus">
+ <summary>The result of the first pipeline connectivity request.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.1.NetworkError" enum="NetErrorCodes">
+ <summary>
+ The network error, if any, of the second pipeline connectivity request.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.1.ResponseCode">
+ <summary>
+ The HTTP response code, if any, of the second pipeline connectivity
+ response.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.1.Status" enum="HttpPipelineStatus">
+ <summary>The result of the second pipeline connectivity request.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.2.NetworkError" enum="NetErrorCodes">
+ <summary>
+ The network error, if any, of the third pipeline connectivity request.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.2.ResponseCode">
+ <summary>
+ The HTTP response code, if any, of the third pipeline connectivity response.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.2.Status" enum="HttpPipelineStatus">
+ <summary>The result of the third pipeline connectivity request.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.3.NetworkError" enum="NetErrorCodes">
+ <summary>
+ The network error, if any, of the fourth pipeline connectivity request.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.3.ResponseCode">
+ <summary>
+ The HTTP response code, if any, of the fourth pipeline connectivity
+ response.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.3.Status" enum="HttpPipelineStatus">
+ <summary>The result of the fourth pipeline connectivity request.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.4.NetworkError" enum="NetErrorCodes">
+ <summary>
+ The network error, if any, of the fifth pipeline connectivity request.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.4.ResponseCode">
+ <summary>
+ The HTTP response code, if any, of the fifth pipeline connectivity response.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.4.Status" enum="HttpPipelineStatus">
+ <summary>The result of the fifth pipeline connectivity request.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.5.NetworkError" enum="NetErrorCodes">
+ <summary>
+ The network error, if any, of the stats pipeline connectivity request.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.5.ResponseCode">
+ <summary>
+ The HTTP response code, if any, of the stats pipeline connectivity response.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.5.Status" enum="HttpPipelineStatus">
+ <summary>The result of the stats pipeline connectivity request.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.AllHTTP11" enum="BooleanSuccess">
+ <summary>
+ True if all requests received by the pipelining test server were HTTP/1.1.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.CanarySuccess" enum="BooleanSuccess">
+ <summary>
+ True if the non-pipelined canary request sent immediately before the
+ pipelining test requests succeeded. Note that if this fails, the rest of the
+ NetConnectivity.Pipeline.* stats are not collected.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.Depth">
+ <summary>
+ The maximum depth of pipelined requests received by the test server.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Pipeline.Success" enum="BooleanSuccess">
+ <summary>True if the entire pipeline connectivity trial passed.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.Sent21">
+ <obsolete>
+ Deprecated 6/25/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ In this experiment, 21 packets were sent to Google via UDP at port 6121 as
+ rapidly as possible, just after successfully sending an UMA upload. Each
+ packet was numbered, as was its ACK sent back by Google. If no packets (of
+ the 21) were ever ACKed, then the port is assumed to be blocked, and no data
+ is recorded in this histogram. If the port is not blocked, then this
+ histogram shows the number of echo responses received from the first
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Sent21.AckReceivedForNthPacket">
+ <obsolete>
+ Deprecated 6/25/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ In this experiment, 21 packets were sent to Google via UDP at port 6121 as
+ rapidly as possible, just after successfully sending an UMA upload. Each
+ packet was numbered, as was its ACK sent back by Google. This histogram
+ records, for each packet number, how often we received an ACK for that
+ packet.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.Sent21.GotAnAck" enum="BooleanSuccess">
+ <obsolete>
+ Deprecated 6/25/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ In this experiment, 21 packets were sent to Google via UDP at port 6121 as
+ rapidly as possible, just after successfully sending an UMA upload. If no
+ packets (of the 21) were ever ACKed, then the port is assumed to be blocked.
+ The histogram shows if we ever got an ACK for a packet in our series of 21.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.TCP.Fail.100B.RTT" units="ms">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>The RTT for echoing 100 bytes of TCP data unsuccessfully.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.TCP.Fail.1k.RTT" units="ms">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>The RTT for echoing 1K bytes of TCP data successfully.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.TCP.Status"
+ enum="NetConnectivityProtocolStatus">
+ <summary>Status for TCP protocol for echoing</summary>
+</histogram>
+
+<histogram name="NetConnectivity.TCP.Status.100B" enum="NetConnectivityStatus">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>Status for echoing 100 bytes of TCP data.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.TCP.Status.1K" enum="NetConnectivityStatus">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>Status for echoing 1K bytes of TCP data.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.TCP.Success" units="ms">
+ <summary>The RTT for TCP protocol for echoing</summary>
+</histogram>
+
+<histogram name="NetConnectivity.TCP.Success.100B.RTT" units="ms">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>The RTT for echoing 100 bytes of TCP data successfully.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.TCP.Success.1K.RTT" units="ms">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>The RTT for echoing 1K bytes of TCP data successfully.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.Fail.100B.RTT" units="ms">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>The RTT for echoing 100 bytes of UDP data unsuccessfully.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.Fail.1k.RTT" units="ms">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>The RTT for echoing 1K bytes of UDP data successfully.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.PacketLoss">
+ <obsolete>
+ Deprecated 6/25/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ Chrome sends 4 UDP packets in a row to test to see if there is a
+ probabalistic dependency in packet loss for consecutive packets. We record
+ a bit vector of packets received, where the least significant bit is a 1 if
+ the first packet was received, etc. For example, if packets 1 and 3 are
+ received, but packets 2 and 4 are lost, then we'd record a sample of binary
+ 0101B, or 5.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.PacketLoss6">
+ <obsolete>
+ Deprecated 6/25/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ Chrome sends 6 UDP packets in a row to test to see if there is a
+ probabalistic dependency in packet loss for consecutive packets. We record
+ a bit vector of packets received, where the least significant bit is a 1 if
+ the first packet was received, etc. For example, if all packets other than
+ packet 2 and 4 are responded to, then we'd have a sample (in binary) of
+ 110101B, or 53.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.Status"
+ enum="NetConnectivityProtocolStatus">
+ <summary>Status for UDP protocol for echoing</summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.Status.100B" enum="NetConnectivityStatus">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>Status for echoing 100 bytes of UDP data.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.Status.1K" enum="NetConnectivityStatus">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>Status for echoing 1K bytes of UDP data.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.Success" units="ms">
+ <summary>The RTT for UDP protocol for echoing</summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.Success.100B.RTT" units="ms">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>The RTT for echoing 100 bytes of UDP data successfully.</summary>
+</histogram>
+
+<histogram name="NetConnectivity.UDP.Success.1K.RTT" units="ms">
+ <obsolete>
+ Deprecated 4/2012. No longer tracked.
+ </obsolete>
+ <summary>The RTT for echoing 1k bytes of UDP data successfully.</summary>
+</histogram>
+
+<histogram name="NetConnectivity2.Send6.PacketsSent">
+ <summary>
+ This histogram records how many packets (out of 6 attempted) were sent via
+ UDP as rapidly as possible, just after successfully sending an UMA upload.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity2.Send6.SeriesAcked">
+ <summary>
+ Chrome sends 6 UDP packets in a row to test to see if there is a
+ probabalistic dependency in packet loss for consecutive packets. We record
+ a bit vector of packets received, where the least significant bit is a 1 if
+ the first packet was received, etc. For example, if all packets other than
+ packet 2 and 4 are responded to, then we'd have a sample (in binary) of
+ 110101B, or 53.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity2.Sent21">
+ <summary>
+ In this experiment, 21 packets were sent to Google via UDP as rapidly as
+ possible, just after successfully sending an UMA upload. Each packet was
+ numbered, as was its ACK sent back by Google. If no packets (of the 21) were
+ ever ACKed, then the port is assumed to be blocked, and no data is recorded
+ in this histogram. If the port is not blocked, then this histogram shows the
+ number of echo responses received from the first
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity2.Sent21.AckReceivedForNthPacket">
+ <summary>
+ In this experiment, 21 packets were sent to Google via UDP as rapidly as
+ possible, just after successfully sending an UMA upload. Each packet was
+ numbered, as was its ACK sent back by Google. This histogram records, for
+ each packet number, how often we received an ACK for that packet.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity2.Sent21.GotAnAck" enum="BooleanSuccess">
+ <summary>
+ In this experiment, 21 packets were sent to Google via UDP as rapidly as
+ possible, just after successfully sending an UMA upload. If no packets (of
+ the 21) were ever ACKed, then the port is assumed to be blocked. The
+ histogram shows if we ever got an ACK for a packet in our series of 21.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity2.Sent21.PacketsSent">
+ <summary>
+ This histogram records how many packets (out of 21 attempted) were sent via
+ UDP as rapidly as possible, just after successfully sending an UMA upload.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity3">
+ <summary>
+ In this experiment, 21 packets were sent to Google via UDP on port 443 or
+ 6121.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity3.NonPacedPacket.Sent21.443.100B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.NonPacedPacket.Sent21.443.1200B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.NonPacedPacket.Sent21.443.500B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.NonPacedPacket.Sent21.6121.100B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.NonPacedPacket.Sent21.6121.1200B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.NonPacedPacket.Sent21.6121.500B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.NonPacedPacket.Sent21.GotAnAck"
+ enum="BooleanSuccess">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.NonPacedPacket.Sent21.Success.RTT" units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.PacedPacket.Sent21.443.100B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.PacedPacket.Sent21.443.1200B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.PacedPacket.Sent21.443.500B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.PacedPacket.Sent21.6121.100B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.PacedPacket.Sent21.6121.1200B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.PacedPacket.Sent21.6121.500B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.PacedPacket.Sent21.GotAnAck"
+ enum="BooleanSuccess">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.PacedPacket.Sent21.Success.RTT" units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Send6.PacketsSent">
+ <obsolete>
+ Deprecated 9/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ This histogram records how many packets (out of 6 attempted) were sent via
+ UDP as rapidly as possible, just after successfully sending an UMA upload.
+ </summary>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Sent21.443.100B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Sent21.443.1200B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Sent21.443.500B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Sent21.6121.100B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Sent21.6121.1200B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Sent21.6121.500B.PacketDelay"
+ units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Sent21.GotAnAck"
+ enum="BooleanSuccess">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity3.StartPacket.Sent21.Success.RTT" units="ms">
+ <summary/>
+</histogram>
+
+<histogram name="NetConnectivity4">
+ <summary>
+ In this experiment, a few packets were sent from Google to clients via UDP
+ on port 443 or 80 to perform net connectivity test.
+ </summary>
+</histogram>
+
+<histogram name="Network.3G.Gobi.Activation" units="milliseconds">
+ <summary>The time the Gobi modem takes to complete activation.</summary>
+</histogram>
+
+<histogram name="Network.3G.Gobi.Connect" units="milliseconds">
+ <summary>
+ The time the Gobi modem takes to connect to the cellular network.
+ </summary>
+</histogram>
+
+<histogram name="Network.3G.Gobi.Disconnect" units="milliseconds">
+ <summary>
+ The time the Gobi modem takes to disconnect from the cellular network.
+ </summary>
+</histogram>
+
+<histogram name="Network.3G.Gobi.FirmwareDownload.Attempts">
+ <summary>Number of attempts taken to install Gobi firmware.</summary>
+</histogram>
+
+<histogram name="Network.3G.Gobi.FirmwareDownload.Time" units="milliseconds">
+ <summary>The time it takes to install Gobi firmware.</summary>
+</histogram>
+
+<histogram name="Network.3G.Gobi.Registration" units="milliseconds">
+ <summary>
+ The time the Gobi modem takes to register on the cellular network.
+ </summary>
+</histogram>
+
+<histogram name="Network.3G.Gobi.SetPower" enum="Network3GGobiError">
+ <summary>Errors experienced during Gobi device powerup.</summary>
+</histogram>
+
+<histogram name="Network.Cellular.TimeOnline" units="seconds">
+ <summary>
+ Chrome OS network metric sampling the time spent using Cellular to transport
+ data. These data are mostly useful when summed and compared to TimeOnline
+ for other network technologies (e.g. WiFi vs Cellular).
+ </summary>
+</histogram>
+
+<histogram name="Network.Cellular.TimeToConfig" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join a 3G/Cellular
+ network and configure Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Cellular.TimeToOnline" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that a
+ 3G/Cellular network is online after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Cellular.TimeToPortal" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that a
+ 3G/Cellular network is in a captive portal after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Cellular.UsageRequestStatus"
+ enum="NetworkCellularUsageRequestStatus">
+ <summary>Chrome OS cellular usage API request status codes.</summary>
+</histogram>
+
+<histogram name="Network.Ethernet.TimeOnline" units="seconds">
+ <summary>
+ Chrome OS network metric sampling the time spent using Ethernet to transport
+ data. These data are mostly useful when summed and compared to TimeOnline
+ for other network technologies (e.g. WiFi vs Cellular).
+ </summary>
+</histogram>
+
+<histogram name="Network.Ethernet.TimeToConfig" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join a wired
+ Ethernet network and configure Layer 3 state (typically acquire a DHCP
+ lease).
+ </summary>
+</histogram>
+
+<histogram name="Network.Ethernet.TimeToOnline" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that an
+ Ethernet network is online after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Ethernet.TimeToPortal" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that an
+ Ethernet network is in a captive portal after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.ServiceErrors" enum="NetworkServiceError">
+ <summary>Chrome OS connection manager service errors seen.</summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.3GPPRegistrationDelayedDrop"
+ enum="NetworkCellular3GPPRegistrationDelayedDrop">
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of cellular network
+ flakes. A network flake occurs when the signal strength goes below detection
+ level for a short duration.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.AutoConnectTotalTime"
+ units="milliseconds">
+ <summary>
+ Chrome OS network diagnostic metric sampling the total amount of time spent
+ from the start of the first auto-connect request until when the cellular
+ modem successfully connects to the network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.AutoConnectTries">
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of auto-connect
+ tries that were attempted before the cellular modem successfully connected
+ to the network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.Disconnect"
+ enum="NetworkDisconnectType">
+ <summary>
+ Chrome OS network usage metric that tracks whether the cellular network was
+ disconnected due to an error or was explicitly disconnected by the user.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.Drop" enum="NetworkCellularTechnology">
+ <summary>
+ Chrome OS cellular network metric that tracks the number of drops based on
+ the network technology.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.OutOfCreditsReason"
+ enum="NetworkCellularOutOfCreditsReason">
+ <summary>
+ Chrome OS cellular network metric that tracks the number of out-of-credits
+ detected based on the cause that triggered the out-of-credits.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.PortalAttempts">
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of portal detection
+ attempts per pass for a cellular network. This includes failure, timeout and
+ successful attempts.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.PortalAttemptsToOnline">
+ <summary>
+ Chrome OS network diagnostic metric sampling the total number of portal
+ detection attempts performed for a cellular network between the Connected
+ and Online state. This includes failure, timeout and successful attempts.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.PortalResult"
+ enum="NetworkPortalResult">
+ <summary>
+ Chrome OS network diagnostic metric sampling the result of portal detections
+ for a cellular network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.SignalStrengthBeforeDrop">
+ <summary>
+ Chrome OS network metric sampling the signal strength (0-100) of the
+ cellular modem before it dropped from the network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeOnline" units="seconds">
+ <summary>
+ Chrome OS network metric sampling the time spent using cellular to transport
+ data. These data are mostly useful when summed and compared to TimeOnline
+ for other network technologies (e.g. WiFi vs Cellular).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeToConfig" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join a cellular
+ network and configure Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeToConnect" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to connect a cellular
+ modem.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeToDisable" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to disable a cellular
+ modem.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeToEnable" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to enable a cellular
+ modem.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeToInitialize" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to initialize a
+ cellular modem.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeToOnline" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that a
+ cellular network is online after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeToPortal" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that a
+ cellular network is in a captive portal after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Cellular.TimeToScan" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to scan a cellular
+ network and register a modem.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.CorruptedProfile" enum="NetworkCorruptedProfile">
+ <summary>
+ Chrome OS cellular network metric that tracks the number of corrupted
+ profiles encountered by Shill.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.Disconnect"
+ enum="NetworkDisconnectType">
+ <summary>
+ Chrome OS network usage metric that tracks whether the Ethernet network was
+ disconnected due to an error or was explicitly disconnected by the user.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.LinkMonitorBroadcastErrorsAtFailure">
+ <summary>
+ Chrome OS network performance metric that tracks the number of LinkMonitor
+ broadcast errors that were accrued on an Ethernet network at the time that
+ the link was declaired to be failed.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.LinkMonitorFailure"
+ enum="LinkMonitorFailureType">
+ <summary>
+ Chrome OS metric that signals the type of failure the LinkMonitor
+ encountered which caused it to stop monitoring an Ethernet network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.LinkMonitorResponseTimeSample"
+ units="milliseconds">
+ <summary>
+ Chrome OS network performance metric that tracks the number of milliseconds
+ between an ARP request and a received reply on an Ethernet network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.LinkMonitorSecondsToFailure"
+ units="seconds">
+ <summary>
+ Chrome OS network performance metric that tracks the number of seconds from
+ the start of the LinkMonitor until failure on an Ethernet network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.LinkMonitorUnicastErrorsAtFailure">
+ <summary>
+ Chrome OS network performance metric that tracks the number of LinkMonitor
+ unicast errors that were accrued on an Ethernet network at the time that the
+ link was declaired to be failed.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.PortalAttempts">
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of portal detection
+ attempts per pass for an Ethernet network. This includes failure, timeout
+ and successful attempts.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.PortalAttemptsToOnline">
+ <summary>
+ Chrome OS network diagnostic metric sampling the total number of portal
+ detection attempts performed for an Ethernet network between the Connected
+ and Online state. This includes failure, timeout and successful attempts.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.PortalResult"
+ enum="NetworkPortalResult">
+ <summary>
+ Chrome OS network diagnostic metric sampling the result of portal detections
+ for an Ethernet network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.TimeOnline" units="seconds">
+ <summary>
+ Chrome OS network metric sampling the time spent using Ethernet to transport
+ data. These data are mostly useful when summed and compared to TimeOnline
+ for other network technologies (e.g. WiFi vs Cellular).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.TimeToConfig" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join a wired
+ Ethernet network and configure Layer 3 state (typically acquire a DHCP
+ lease).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.TimeToInitialize" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to initialize an
+ Ethernet device.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.TimeToOnline" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that an
+ Ethernet network is online after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Ethernet.TimeToPortal" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that an
+ Ethernet network is in a captive portal after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.ServiceErrors" enum="NetworkServiceError">
+ <summary>Chrome OS connection manager service errors seen.</summary>
+</histogram>
+
+<histogram name="Network.Shill.TerminationActionResult"
+ enum="ShillTerminationActionResult">
+ <obsolete>
+ Deprecated 10/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of termination
+ actions that successfully complete or fail when shill terminates.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.TerminationActionResult.OnSuspend"
+ enum="ShillTerminationActionResult">
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of termination
+ actions that successfully complete or fail when shill suspends.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.TerminationActionResult.OnTerminate"
+ enum="ShillTerminationActionResult">
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of termination
+ actions that successfully complete or fail when shill terminates.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.TerminationActionTime.OnSuspend"
+ units="milliseconds">
+ <summary>
+ Chrome OS network diagnostic metric sampling the time in milliseconds it
+ takes termination actions to complete when shill suspends.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.TerminationActionTime.OnTerminate"
+ units="milliseconds">
+ <summary>
+ Chrome OS network diagnostic metric sampling the time in milliseconds it
+ takes termination actions to complete when shill terminates.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.TimeToDrop" units="seconds">
+ <summary>
+ Chrome OS network stability metric sampling the time in seconds between the
+ networking going online to going offline. Offline events due to device
+ shutdown or suspend are ignored (along with the online time before that
+ offline event).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Vpn.Driver" enum="VPNDriver">
+ <summary>
+ Chrome OS network usage metric sampled on each successful VPN connection
+ that tracks the VPN connection type.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Vpn.RemoteAuthenticationType"
+ enum="VPNRemoteAuthenticationType">
+ <summary>
+ Chrome OS network usage metric sampled on each successful VPN connection
+ that tracks the remote authentication method.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.VPN.TimeToConfig" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to configure Layer 3
+ state on a VPN network (typically acquire a DHCP lease).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.VPN.TimeToOnline" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that a
+ WiMax network is online after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Vpn.UserAuthenticationType"
+ enum="VPNUserAuthenticationType">
+ <summary>
+ Chrome OS network usage metric sampled on each successful VPN connection
+ that tracks the user authentication method.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiFi.ApDisconnectReason" enum="WiFiReasonCode">
+ <summary>
+ Chrome OS network usage metric. Reason code reported when the AP
+ disconnects a wifi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiFi.ApDisconnectType" enum="WiFiStatusType">
+ <summary>
+ Chrome OS network usage metric. Broad category of reason AP disconnected a
+ WiFi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.ApMode" enum="WiFiApMode">
+ <summary>
+ Chrome OS network usage metric. The AP mode setting for each successful
+ WiFi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.Channel" enum="NetworkChannelType">
+ <summary>
+ Chrome OS network usage metric. The channel used for each successful WiFi
+ connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiFi.ClientDisconnectReason"
+ enum="WiFiReasonCode">
+ <summary>
+ Chrome OS network usage metric. Reason code reported when the client
+ disconnects a wifi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiFi.ClientDisconnectType" enum="WiFiStatusType">
+ <summary>
+ Chrome OS network usage metric. Broad category of reason client
+ disconnected a WiFi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.Disconnect" enum="NetworkDisconnectType">
+ <summary>
+ Chrome OS network usage metric that tracks whether an 802.11 wireless
+ network was disconnected due to an error or was explicitly disconnected by
+ the user.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.EapInnerProtocol" enum="EAPInnerProtocol">
+ <summary>
+ Chrome OS network usage metric sampled on each successful 802.1x wireless
+ connection that tracks the configured inner authentication method.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.EapOuterProtocol" enum="EAPOuterProtocol">
+ <summary>
+ Chrome OS network usage metric sampled on each successful 802.1x wireless
+ connection that tracks the configured outer authentication method.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.FrequenciesConnectedEver">
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of different WiFi
+ frequencies to which the user's machine has ever connected.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.LinkMonitorBroadcastErrorsAtFailure">
+ <summary>
+ Chrome OS network performance metric that tracks the number of LinkMonitor
+ broadcast errors that were accrued on an 802.11 wireiless network at the
+ time that the link was declaired to be failed.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.LinkMonitorFailure"
+ enum="LinkMonitorFailureType">
+ <summary>
+ Chrome OS metric that signals the type of failure the LinkMonitor
+ encountered which caused it to stop monitoring an 802.11 wireless network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.LinkMonitorResponseTimeSample"
+ units="milliseconds">
+ <summary>
+ Chrome OS network performance metric that tracks the number of milliseconds
+ between an ARP request and a received reply on an 802.11 wireless network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.LinkMonitorSecondsToFailure"
+ units="seconds">
+ <summary>
+ Chrome OS network performance metric that tracks the number of seconds from
+ the start of the LinkMonitor until failure on an 802.11 wireless network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.LinkMonitorUnicastErrorsAtFailure">
+ <summary>
+ Chrome OS network performance metric that tracks the number of LinkMonitor
+ unicast errors that were accrued on an 802.11 wireless network at the time
+ that the link was declaired to be failed.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.PhyMode" enum="NetworkPhyModeType">
+ <summary>
+ Chrome OS network usage metric. The channel type used for each successful
+ WiFi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.PortalAttempts">
+ <summary>
+ Chrome OS network diagnostic metric sampling the number of portal detection
+ attempts per pass for an 802.11 wireless network. This includes failure,
+ timeout and successful attempts.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.PortalAttemptsToOnline">
+ <summary>
+ Chrome OS network diagnostic metric sampling the total number of portal
+ detection attempts performed for an 802.11 wireless network between the
+ Connected and Online state. This includes failure, timeout and successful
+ attempts.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.PortalResult" enum="NetworkPortalResult">
+ <summary>
+ Chrome OS network diagnostic metric sampling the result of portal detections
+ for an 802.11 wireless network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiFi.ScanResult" enum="WiFiScanResult">
+ <summary>
+ Chrome OS network usage metric describing, for a wifi scan attempt, what
+ scan method is used and whether it ends in a connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiFi.ScanTimeInEbusy" units="milliseconds">
+ <summary>
+ Chrome OS network usage metric describing, for a wifi scan attempt, how many
+ milliseconds were spent waiting to talk to the kernel/drivers.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.Security" enum="NetworkSecurityType">
+ <summary>
+ Chrome OS network usage metric. The security setting for each successful
+ WiFi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.SignalStrength" units="negative dBm">
+ <summary>
+ Chrome OS network metric indicating the negative of the dBm received signal
+ strength recorded at the time a successful WiFi connection started.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeOnline" units="seconds">
+ <summary>
+ Chrome OS network metric sampling the time spent using WiFi to transport
+ data. These data are mostly useful when summed and compared to TimeOnline
+ for other network technologies (e.g. WiFi vs Cellular).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeResumeToReady" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time from the resume event
+ to the time when an 802.11 wireless network has configured its Layer 3
+ state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeToConfig" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to configure Layer 3
+ state on an 802.11 wireless network (typically acquire a DHCP lease).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeToConnect" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to connect to a WiFi
+ Basic Service Set (which consists of the access point and associated
+ stations on a particular WiFi channel for a specific network).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeToInitialize" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to initialize an
+ 802.11 wireless device.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeToJoin" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join (associate
+ plus authenticate) an 802.11 wireless network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeToOnline" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that an
+ 802.11 wireless network is online after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeToPortal" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that an
+ 802.11 wireless network is in a captive portal after configuring Layer 3
+ state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeToScan" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to scan WiFi until a
+ connection is found.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.Wifi.TimeToScanAndConnect" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time between the beginning
+ of a WiFi scan (if the scan includes both a progressive scan and a full
+ scan, the TimeToScanAndConnect starts with the first scan of the series) and
+ the completion of a successful connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiMax.TimeToConfig" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to configure Layer 3
+ state on a WiMax network (typically acquire a DHCP lease).
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiMax.TimeToInitialize" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to initialize a WiMax
+ device.
+ </summary>
+</histogram>
+
+<histogram name="Network.Shill.WiMax.TimeToOnline" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that a
+ WiMax network is online after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.TimeToConfig.Cellular" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join a 3G/Cellular
+ network and configure Layer 3 state. Note this metric is deprecated; see
+ Network.Cellular.TimeToConfig.
+ </summary>
+</histogram>
+
+<histogram name="Network.TimeToConfig.Ethernet" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join a wired
+ Ethernet network and configure Layer 3 state (typically acquire a DHCP
+ lease). Note this metric is deprecated; see Network.Ethernet.TimeToConfig.
+ </summary>
+</histogram>
+
+<histogram name="Network.TimeToConfig.Wifi" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to configure Layer 3
+ state on an 802.11 wireless network (typically acquire a DHCP lease). Note
+ this metric is deprecated; see Network.Wifi.TimeToConfig.
+ </summary>
+</histogram>
+
+<histogram name="Network.TimeToDrop" units="seconds">
+ <summary>
+ Chrome OS network stability metric sampling the time in seconds between the
+ networking going online to going offline. Offline events due to device
+ shutdown or suspend are ignored (along with the online time before that
+ offline event).
+ </summary>
+</histogram>
+
+<histogram name="Network.TimeToJoin.Wifi" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join (associate
+ plus authenticate) an 802.11 wireless network. Note this metric is
+ deprecated; see Network.Wifi.TimeToJoin.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.AuthMode" enum="NetworkAuthModeType">
+ <summary>
+ Chrome OS network performance metric sampling the time to configure Layer 3
+ state on an 802.11 wireless network (typically acquire a DHCP lease).
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.BitRate" units="bps">
+ <summary>
+ Network metric reporting the download speed test results run at setup time.
+ Recorded at least once per day.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.Channel" enum="NetworkChannelType">
+ <summary>
+ Chrome OS network usage metric. The channel used for each successful WiFi
+ connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.Idle.NoiseLevel" units="negative dBm">
+ <summary>
+ Network metric indicating the negative of the dBm noise level recorded at
+ the time the metric is collected. Reported at least once per day and only
+ when the device is idle.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.Idle.SignalLevel" units="negative dBm">
+ <summary>
+ Network metric indicating the negative of the dBm received signal level
+ recorded at the time the metric is collected. Reported at least once per
+ day and only when the device is idle.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.Idle.SignalToNoiseRatio" units="negative dBm">
+ <summary>
+ Network metric indicating signal minus noise in dBm recorded at the time the
+ metrics is collected. Reported at least once per day and only when the
+ device is idle.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.NoiseLevel" units="negative dBm">
+ <summary>
+ Network metric indicating the negative of the dBm noise level recorded at
+ the time the metric is collected. Reported at least once per day.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.PhyMode" enum="NetworkPhyModeType">
+ <summary>
+ Chrome OS network usage metric. The channel type used for each successful
+ WiFi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.RoundTripTime" units="ms">
+ <summary>
+ Network metric reporting the average round trip time to the wifi gateway.
+ Recorded at least once per day.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.Security" enum="NetworkSecurityType">
+ <summary>
+ Chrome OS network usage metric. The security setting for each successful
+ WiFi connection.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.SignalLevel" units="negative dBm">
+ <summary>
+ Network metric indicating the negative of the dBm received signal level
+ recorded at the time the metric is collected. Reported at least once per
+ day.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.SignalToNoiseRatio" units="negative dBm">
+ <summary>
+ Network metric indicating signal minus noise in dBm recorded at the time the
+ metrics is collected. Reported at least once per day.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.TimeOnline" units="seconds">
+ <summary>
+ Chrome OS network metric sampling the time spent using WiFi to transport
+ data. These data are mostly useful when summed and compared to TimeOnline
+ for other network technologies (e.g. WiFi vs Cellular).
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.TimeResumeToReady" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time from the resume event
+ to the time when an 802.11 wireless network has configured its Layer 3
+ state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.TimeToConfig" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to configure Layer 3
+ state on an 802.11 wireless network (typically acquire a DHCP lease).
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.TimeToJoin" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to join (associate
+ plus authenticate) an 802.11 wireless network.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.TimeToOnline" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that an
+ 802.11 wireless network is online after configuring Layer 3 state.
+ </summary>
+</histogram>
+
+<histogram name="Network.Wifi.TimeToPortal" units="milliseconds">
+ <summary>
+ Chrome OS network performance metric sampling the time to determine that an
+ 802.11 wireless network is in a captive portal after configuring Layer 3
+ state.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.ActionAndroid" enum="NewTabPageActionAndroid">
+ <summary>
+ Actions taken by users from the new tab page on Android. These actions may
+ navigate away from the NTP (e.g. searching in the omnibox or opening a
+ bookmark), but can also happen without navigating away from the NTP (e.g.
+ opening a bookmark in a new tab).
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.AppsPageDragSource" enum="AppsPageDragSource">
+ <summary>
+ Histogram for the source of app page drags. For any succesful drop onto an
+ apps pane of the NTP, this logs where the drag originated.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.DefaultPageType" enum="NtpPaneType">
+ <summary>The default pane when the NTP is first opened.</summary>
+</histogram>
+
+<histogram name="NewTabPage.HoverTimeClicked">
+ <summary>
+ Histogram of the time, in milliseconds, users have the cursor over a most
+ visited thumbnail before clicking.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.HoverTimeNotClicked">
+ <summary>
+ Histogram of the time, in milliseconds, users have the cursor over a most
+ visited thumbnail before moving it away from the thumbnail without clicking.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.MobilePromo" enum="NewTabPageMobilePromo">
+ <summary>
+ Android: Tallies counts for how the user interacted with the NTP promo page.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.MostVisited">
+ <summary>
+ Histogram for user clicks of the most visited thumbnails. The value is equal
+ to the index of the thumbnail.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.MostVisitedAction" enum="NtpFollowAction">
+ <summary>
+ Action taken by the user on the Most Visited NTP pane. If the user switches
+ panes during this use of the NTP, this action is sometimes not recorded. Ask
+ mpearson@ for details.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.MostVisitedTilePlacementExperiment"
+ enum="NtpTileExperimentActions">
+ <summary>
+ Records anomalous events for the Most Visited Tile Placement experiment,
+ where it is unable to operate as expected. These are recorded during New Tab
+ Page load time, once for every NTP.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.NonVisibleScreenshots">
+ <summary>
+ The number of screenshots that were cached for the non-visible but ranked
+ suggestions on the Suggested NTP pane.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.NonVisibleSuggestedSiteRank">
+ <summary>
+ Given that the user has typed a URL, and given that that specific URL was
+ ranked but not visible on the Suggested pane of the NTP, this is the rank
+ that the Suggested pane had for that URL.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.NumberOfMouseOvers">
+ <summary>
+ The total number of times the user hovered the mouse over Most Visited tile
+ or title elements before changing focus away from the NTP, be it by
+ navigating to a URL, switching tabs, changing the active window or closing
+ the tab/shutting down Chrome.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.OtherSessionsMenu" enum="NtpOtherSessionsType">
+ <summary>
+ Histogram for usage of the menu on the NTP that allows the user to access
+ tabs from other devices.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.PreviousSelectedPageType" enum="NtpPaneType">
+ <summary>
+ The pane that had been previously selected when the user switches panes in
+ the NTP.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.Promo.Bubble" enum="NtpPromoAction">
+ <summary>Histogram for NTP bubble promo activity.</summary>
+</histogram>
+
+<histogram name="NewTabPage.Promo.Notification" enum="NtpPromoAction">
+ <summary>Histogram for NTP notification promo activity.</summary>
+</histogram>
+
+<histogram name="NewTabPage.SearchURLs.Total">
+ <summary>TBD.</summary>
+</histogram>
+
+<histogram name="NewTabPage.SelectedPageType" enum="NtpPaneType">
+ <summary>The pane selected when the user switches panes in the NTP.</summary>
+</histogram>
+
+<histogram name="NewTabPage.SessionRestore">
+ <summary>
+ Histogram for user clicks of the Recently Closed items. The value is the
+ recency of the entry being restored (0 is most recent).
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.SingleSessionPageSwitches">
+ <summary>
+ Histogram to track how many times a user switched pages in a single NTP
+ session.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.SuggestedSite">
+ <summary>
+ Histogram for user clicks of the suggested site thumbnails. The value is
+ equal to the index of the thumbnail.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.SuggestedSitesAction" enum="NtpFollowAction">
+ <summary>Action taken by the user on the Suggested Sites NTP pane.</summary>
+</histogram>
+
+<histogram name="NewTabPage.SuggestedSitesLoadTime">
+ <summary>Time to load the Suggested Sites NTP pane, in milliseconds.</summary>
+</histogram>
+
+<histogram name="NewTabPage.SuggestedSitesViewTime">
+ <summary>Time spent on the Suggested Sites NTP pane, in seconds.</summary>
+</histogram>
+
+<histogram name="NewTabPage.ThumbnailErrorRate">
+ <summary>
+ The percentage of errors per attempts to load image thumbnails on the New
+ Tab Page. When an error occurs, a grey tile is shown instead of a thumbnail
+ image. We measure the rate instead of the number of errors because multiple
+ attempts are made to load images at different times during the NTP's
+ lifetime. Each NTP session's error rate is logged after the user navigates
+ to a new URL from that NTP.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.VisibleScreenshots">
+ <summary>
+ The number of screenshots that were cached for the visible suggestions on
+ the Suggested NTP pane.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.VisibleSuggestedSiteRank">
+ <summary>
+ Given that the user has typed a URL, and given that that specific URL was
+ visible on the Suggested pane of the NTP, this is the rank that the
+ Suggested pane had for that URL.
+ </summary>
+</histogram>
+
+<histogram name="ntp.searchurls.total">
+ <summary>TBD</summary>
+</histogram>
+
+<histogram name="NtpHandler.AttachShownPageType" enum="NtpPaneType">
+ <obsolete>
+ Deprecated 10/2011. No longer tracked, replaced with
+ NewTabPage.DefaultPageType
+ </obsolete>
+ <summary>The default pane when the NTP is first opened.</summary>
+</histogram>
+
+<histogram name="NtpHandler.SelectedShownPageType" enum="NtpPaneType">
+ <obsolete>
+ Deprecated 10/2011. No longer tracked, replaced with
+ NewTabPage.SelectedPageType
+ </obsolete>
+ <summary>The pane selected when the user switches panes in the NTP.</summary>
+</histogram>
+
+<histogram name="OfflinePolicy.SuccessfulResourceLoadPercentage" units="%">
+ <summary>
+ When a page is loaded in offline mode, the percentage of resources on that
+ page that were successfully loaded.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.AggressiveHistoryURLProviderFieldTrialBeacon"
+ enum="OmniboxAggressiveHistoryURLProviderFieldTrialBeacon">
+ <obsolete>
+ Aggressive HistoryURL provider field trial deleted in spring 2012.
+ </obsolete>
+ <summary>
+ A number that indicates what omnibox ranking behavior the user is seeing as
+ part of the OmniboxAggressiveHistoryURLProvider field trial
+ (OmniboxAggressiveHistoryURLProvider).
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.EnteredKeywordMode" enum="OmniboxEnteredKeywordMode">
+ <summary>
+ The number of times users enter keyword hint mode &quot;Search ___
+ for:&quot; and how.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.FocusToEditTime" units="ms">
+ <summary>
+ The length of time between when a user focused on the omnibox and first
+ modifies the omnibox.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.FocusToOpenTime" units="ms">
+ <summary>
+ The length of time between when a user focused on the omnibox and opened an
+ omnibox match (which could be what they typed or a suggestion).
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.ProviderTime" units="ms">
+ <summary>
+ The length of time taken by the named provider&quot;s synchronous pass.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.QueryBookmarksTime">
+ <obsolete>
+ Deprecated 2012-11-14. Replaced by Autocomplete.BookmarkProviderMatchTime.
+ </obsolete>
+ <summary>
+ Time the HistoryContentProvider takes to perform a bookmark search.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.QueryTime" units="milliseconds">
+ <summary>
+ Time it takes for the omnibox to become responsive to user input after the
+ user has typed N characters. This measures the time it takes to start all
+ the asynchronous autocomplete providers (but not wait for them to finish).
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.SearchEngine" enum="OmniboxSearchEngine">
+ <summary>
+ The id of search engine that was used for search in omnibox. See
+ src/chrome/browser/search_engines/template_url_prepopulate_data.cc for more
+ info.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.SuggestRequest.Failure.GoogleResponseTime"
+ units="milliseconds">
+ <summary>
+ The time elapsed between the sending of a suggest request to Google until
+ the time the request was returned with status==failed. Ignores requests that
+ were canceled before being returned.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.SuggestRequest.Success.GoogleResponseTime"
+ units="milliseconds">
+ <summary>
+ The time elapsed between the sending of a suggest request to Google until
+ the time the request was returned with status==success. Ignores requests
+ that were canceled before being returned.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.SuggestRequests" enum="OmniboxSuggestRequests">
+ <summary>
+ Counts about the number of suggest requests the omnibox sent, invalidated,
+ and replies received.
+ </summary>
+</histogram>
+
+<histogram name="OutdatedUpgradeBubble.NumLaterPerReinstall">
+ <summary>
+ Counts the number of times the user clicked on the later button of the
+ outdated upgrade bubble, before clicking on the reinstall button in the same
+ Chrome session.
+ </summary>
+</histogram>
+
+<histogram name="Overscroll.Completed" enum="OverscrollMode">
+ <summary>Completed overscroll gestures.</summary>
+ <details>
+ An overscroll gesture starts when user scrolls past the edge of the web page
+ and continues scrolling in the same direction. An overscroll gesture is
+ completed when user stops scrolling (e.g. by lifting the fingers from the
+ touchscreen or touchpad).
+ </details>
+</histogram>
+
+<histogram name="Overscroll.Navigated" enum="OverscrollMode">
+ <summary>
+ Navigations that were triggered due to completed overscroll gesture. Note
+ that not all completed overscroll gestures trigger a navigation.
+ </summary>
+</histogram>
+
+<histogram name="Overscroll.Started" enum="OverscrollMode">
+ <summary>
+ Overscroll gestures initiated by the user. Note that not all overcroll
+ gestures started are completed (e.g. the overscroll gesture is aborted if
+ user clicks or presses a key during the gesture).
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.OtherPossibleUsernamesUsage"
+ enum="OtherPossibleUsernamesUsage">
+ <summary>
+ Breakdown of how other possible usernames are displayed. Recorded every time
+ we autofill a password form.
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.ProvisionalSaveFailure"
+ enum="ProvisionalSaveFailure">
+ <summary>
+ Breakdown of cases where a password is submitted, but we don't even try and
+ save it. Recorded for every password form submit.
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.TimesGeneratedPasswordUsed">
+ <summary>
+ The number of times each generated password has been used to log in.
+ Recorded by iterating over stored passwords once per run. This information
+ is persisted and synced.
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.TimesPasswordUsed">
+ <summary>
+ The number of times each saved password has been used to log in. Does not
+ include generated passwords. Recorded by iterating over stored passwords
+ once per run. This information is persisted and synced.
+ </summary>
+</histogram>
+
+<histogram name="Platform.AsvGroup">
+ <summary>
+ Chrome OS (ARM Chromebooks using Exynos 5250 only) Adaptive Support Voltage
+ Group, recorded once per bootup. Indicates which &quot;bin&quot; the SoC is
+ part of, which sets the voltage that different rails on the system will run
+ at. The values 0-11 are valid. A value of 12 indicates an error parsing
+ dmesg and should be investigated. See also Platform.LotIdEnum.
+ </summary>
+</histogram>
+
+<histogram name="Platform.BootSectorsRead">
+ <summary>
+ Chrome OS number of disk sectors read at boot from kernel start to
+ login-prompt-ready.
+ </summary>
+</histogram>
+
+<histogram name="Platform.BootSectorsWritten">
+ <summary>
+ Chrome OS number of disk sectors written at boot from kernel start to
+ login-prompt-ready.
+ </summary>
+</histogram>
+
+<histogram name="Platform.CompressedSwapSize" units="MB">
+ <summary>
+ Chrome OS size of allocated swap area in megabytes (before compression)
+ </summary>
+</histogram>
+
+<histogram name="Platform.CpuFrequencyThermalScaling" units="percent">
+ <summary>
+ CPU frequency as percent of the baseline frequency, sampled every 30s. This
+ may be throttled down from 100% due to power dissipation issues (too high
+ temperature). It may also be throttled up (turbo), but the kernel does not
+ report the actual turbo frequency, so we put such samples in the 101%
+ bucket.
+ </summary>
+</histogram>
+
+<histogram name="Platform.CpuUsage" units="%">
+ <summary>
+ Peak total (single core) CPU usage for the last sample interval. The sample
+ interval may vary from seconds to several minutes.
+ </summary>
+</histogram>
+
+<histogram name="Platform.CrOSEvent" enum="CrosEventEnum">
+ <summary>
+ Generic event of interest from Chrome OS. Intended mainly to help assess
+ the frequency of rare error conditions.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.Cache_Avg" units="KB">
+ <summary>
+ Average size of user's Cache directory. Logged once a day, if disk usage is
+ high.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.Cache_Max" units="KB">
+ <summary>
+ Maximum size of user's Cache directory. Logged once a day, if disk usage is
+ high.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.Downloads_Avg" units="KB">
+ <summary>
+ Average size of user's Cache directory. Logged once a day, if disk usage is
+ high.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.Downloads_Max" units="KB">
+ <summary>
+ Maximum size of user's Cache directory. Logged once a day, if disk usage is
+ high.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.GCache_Avg" units="KB">
+ <summary>
+ Average size of user's GCache directory. Logged once a day, if disk usage is
+ high.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.GCache_Max" units="KB">
+ <summary>
+ Maximum size of user's GCache directory. Logged once a day, if disk usage is
+ high.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.NumUserHomeDirectories"
+ units="home directories">
+ <summary>
+ Number of users home directories on the device. Logged once a day.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.OldestUserOnDevice">
+ <summary>
+ Days since last login of the least recently user on device. Logged once a
+ day, if disk usage is high.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsage.UsersOnDevice">
+ <summary>
+ Number of user home dirs on device. Logged once a day, if disk usage is
+ high.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsageCache" units="KB">
+ <summary>KB in use in the /cache filesystem tree. Logged once a day.</summary>
+</histogram>
+
+<histogram name="Platform.DiskUsageChronos" units="KB">
+ <summary>
+ Chrome OS KB in use in the /home/chronos filesystem tree. Logged once a day
+ during log file cleanup.
+ </summary>
+</histogram>
+
+<histogram name="Platform.DiskUsageData" units="KB">
+ <summary>KB in use in the /data filesystem tree. Logged once a day.</summary>
+</histogram>
+
+<histogram name="Platform.DiskUsageVar" units="KB">
+ <summary>
+ Chrome OS KB in use in the /var filesystem tree. Logged once a day during
+ log file cleanup.
+ </summary>
+</histogram>
+
+<histogram name="Platform.IntelMaxMicroArchitecture"
+ enum="IntelMaxMicroArchitecture">
+ <summary>
+ The maximum supported micro-architecture on an Intel platform. This value
+ is logged at program start time.
+ </summary>
+</histogram>
+
+<histogram name="Platform.KernelWarningHashes">
+ <summary>
+ The 32-bit hash of a kernel warning. This is the hash of the
+ &quot;file:line&quot; string corresponding to the location of the warning,
+ for instance: &quot;/mnt/host/source/src/third_party/kernel/files/drivers
+ /gpu/drm/i915/intel_dp.c:351&quot; (ignore spurious spaces). The hash is
+ produced by this code: while (*string) hash = (hash &lt;&lt; 5) + hash +
+ *string++; Separately each warning is also collected (with its hash) via
+ the crash reporter, but only its first occurrence in each boot session.
+ Contact semenzato@ for further info.
+ </summary>
+</histogram>
+
+<histogram name="Platform.LotIdEnum" enum="Exynos5250LotIdEnum">
+ <summary>
+ Chrome OS (ARM Chromebooks using Exynos 5250 only) indication about whether
+ we're part of a special lot ID. Special lot IDs are groups of chips that
+ have special case handling in the kernel for the Adaptive Support Voltage
+ code (the normal logic doesn't work). See also Platform.AsvGroup. Note
+ that fused devices are never part of a special lot (currently) and only some
+ unfused lots are &quot;special&quot;.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MeminfoActive">
+ <summary>Chrome OS size of active memory as % of total memory.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoActiveAnon">
+ <summary>
+ Chrome OS active anonymous memory (data segments) as % of total memory.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MeminfoActiveFile">
+ <summary>
+ Chrome OS active file-backed memory (executables, ...) as % of total memory.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MeminfoAnonPages">
+ <summary>Chrome OS size of anonymous memory as % of total memory.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoBuffers">
+ <summary>Chrome OS size of buffer cache as % of total memory.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoCached">
+ <summary>
+ Chrome OS: size of file-backed memory minus swap and buffer cache, as % of
+ total memory.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MeminfoInactive">
+ <summary>Chrome OS size of inactive memory as % of total memory.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoInactiveAnon">
+ <summary>
+ Chrome OS inactive anonymous memory (data segments) as % of total memory.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MeminfoInactiveFile">
+ <summary>Chrome OS inactive file-backed memory as % of total memory.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoMapped">
+ <summary>Chrome OS size of mapped memory as % of total memory.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoMemFree">
+ <summary>Chrome OS size of free memory as % of total memory.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoShmem">
+ <summary>Chrome OS size of shared memory in Kbytes.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoSlab">
+ <summary>Chrome OS size of slab memory in Kbytes.</summary>
+</histogram>
+
+<histogram name="Platform.MeminfoSwapUsed" units="kB">
+ <summary>
+ Chrome OS amount of swapped-out memory in Kbytes. These, and all other
+ MEMINFO stats, are snapshotted every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MeminfoSwapUsedPercent" units="percent">
+ <summary>
+ Chrome OS amount of swapped-out memory as % of total RAM. These, and all
+ other MEMINFO stats, are snapshotted every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MeminfoUnevictable">
+ <summary>
+ Chrome OS unevictable memory (ramfs, SHM_LOCKED, mlocked) in Kbytes.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MemoryBandwidth.ReadWrite" units="MB/s">
+ <summary>
+ Peak memory bandwith (read and write) usage during the last sample interval.
+ The sample interval may vary from seconds to several minutes.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MemuseAnon0">
+ <summary>
+ Chrome OS total anonymous memory (active + inactive) as % of total memory 1
+ minute after boot.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MemuseAnon1">
+ <summary>
+ Chrome OS total anonymous memory (active + inactive) as % of total memory 5
+ minutes after boot.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MemuseAnon2">
+ <summary>
+ Chrome OS total anonymous memory (active + inactive) as % of total memory 30
+ minutes after boot.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MemuseAnon3">
+ <summary>
+ Chrome OS total anonymous memory (active + inactive) as % of total memory
+ 150 minutes after boot.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MemuseAnon4">
+ <summary>
+ Chrome OS total anonymous memory (active + inactive) as % of total memory
+ 750 minutes after boot.
+ </summary>
+</histogram>
+
+<histogram name="Platform.PageFaultsLong" units="page faults/second">
+ <summary>
+ Page faults per second averaged over 30s interval, sampled continuously.
+ </summary>
+</histogram>
+
+<histogram name="Platform.PageFaultsShort" units="page faults/second">
+ <summary>
+ Page faults per second averaged over 1s interval, sampled every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.ReadSectorsLong">
+ <summary>
+ Number of disk sectors per second read by Chrome OS in a long interval
+ (currently 30s)
+ </summary>
+</histogram>
+
+<histogram name="Platform.ReadSectorsShort">
+ <summary>
+ Number of disk sectors per second read by Chrome OS in a short interval
+ (currently 1s, sampled every 30s)
+ </summary>
+</histogram>
+
+<histogram name="Platform.SmartTransferErrors">
+ <summary>Disk communication errors (SMART 199), sent at boot.</summary>
+</histogram>
+
+<histogram name="Platform.SmartUncorrectableErrors">
+ <summary>Uncorrectable disk errors (SMART 187), sent at boot.</summary>
+</histogram>
+
+<histogram name="Platform.StatefulUsage" units="%">
+ <summary>Chrome OS stateful partition usage level.</summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap0.Time1" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap0.Time2" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap0.Time3" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap0.Time4" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap1.Time1" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap1.Time2" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap1.Time3" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap1.Time4" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap2.Time1" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap2.Time2" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap2.Time3" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap2.Time4" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap3.Time1" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap3.Time2" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap3.Time3" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Cpu.Swap3.Time4" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap0.Time1"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap0.Time2"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap0.Time3"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap0.Time4"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap1.Time1"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap1.Time2"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap1.Time3"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap1.Time4"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap2.Time1"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap2.Time2"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap2.Time3"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap2.Time4"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap3.Time1"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap3.Time2"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap3.Time3"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.Scroll.Faults.Swap3.Time4"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ scroll event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap0.Time1" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap0.Time2" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap0.Time3" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap0.Time4" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap1.Time1" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap1.Time2" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap1.Time3" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap1.Time4" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap2.Time1" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap2.Time2" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap2.Time3" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap2.Time4" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap3.Time1" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap3.Time2" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap3.Time3" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Cpu.Swap3.Time4" units="%">
+ <summary>
+ CPU utilization for the specified swap group and time interval after a tab
+ switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap0.Time1"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap0.Time2"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap0.Time3"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap0.Time4"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap1.Time1"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap1.Time2"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap1.Time3"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap1.Time4"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap2.Time1"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap2.Time2"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap2.Time3"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap2.Time4"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap3.Time1"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap3.Time2"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap3.Time3"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.SwapJank.TabSwitch.Faults.Swap3.Time4"
+ units="page faults/second">
+ <summary>
+ Page faults/second for the specified swap group and time interval after a
+ tab switch event. See src/chrome/browser/chromeos/swap_metrics.cc.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Junction" units="Celsius">
+ <summary>
+ Peak junction temperature for the last sample interval, read from TSEN on
+ the SoC. The sample interval may vary from seconds to several minutes.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor00" units="Celsius">
+ <summary>
+ Temperature reading at sensor 0 (I2C_CPU-Die) taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor01" units="Celsius">
+ <summary>
+ Temperature reading at sensor 1 (I2C_CPU-Object) taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor02" units="Celsius">
+ <summary>
+ Temperature reading at sensor 2 (I2C_PCH-Die) taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor03" units="Celsius">
+ <summary>
+ Temperature reading at sensor 3 (I2C_PCH-Object) taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor04" units="Celsius">
+ <summary>
+ Temperature reading at sensor 4 (I2C_DDR-Die) taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor05" units="Celsius">
+ <summary>
+ Temperature reading at sensor 5 (I2C_DDR-Object) taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor06" units="Celsius">
+ <summary>
+ Temperature reading at sensor 6 (Charger-Die), taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor07" units="Celsius">
+ <summary>
+ Temperature reading at sensor 7 (Charger-Object) taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor08" units="Celsius">
+ <summary>
+ Temperature reading at sensor 8 (ECInternal) taken every 30s.
+ </summary>
+</histogram>
+
+<histogram name="Platform.Temperature.Sensor09" units="Celsius">
+ <summary>Temperature reading at sensor 9 (PECI) taken every 30s.</summary>
+</histogram>
+
+<histogram name="Platform.TPMForcedReboot" units="reboots">
+ <summary>
+ Each sample is the number of consecutive reboots performed while attempting
+ to clear a TPM (Trusted Platform Module) error.
+ </summary>
+</histogram>
+
+<histogram name="Platform.WriteSectorsLong">
+ <summary>
+ Number of disk sectors per second written by Chrome OS in a long interval
+ (currently 30s)
+ </summary>
+</histogram>
+
+<histogram name="Platform.WriteSectorsShort">
+ <summary>
+ Number of disk sectors per second written by Chrome OS in a short interval
+ (currently 1s, sampled every 30s)
+ </summary>
+</histogram>
+
+<histogram name="PlatformFile.UnknownCreateFileErrors" units="code">
+ <obsolete>
+ Deprecated as of 2013-05, replaced by
+ PlatformFile.UnknownCreateFileErrorsWin in chrome 29.
+ </obsolete>
+ <summary>
+ Errors returned by CreateFile on windows that PlatformFileError doesn't yet
+ support.
+ </summary>
+</histogram>
+
+<histogram name="PlatformFile.UnknownErrors.Posix" units="errno">
+ <summary>
+ Errors returned by CreateFile on POSIX that PlatformFileError doesn't yet
+ support.
+ </summary>
+</histogram>
+
+<histogram name="PlatformFile.UnknownErrors.Windows" units="GetLastError">
+ <summary>
+ Errors returned by CreateFile on Windows that PlatformFileError doesn't yet
+ support.
+ </summary>
+</histogram>
+
+<histogram name="PLT.Abandoned" enum="Abandoned">
+ <summary>
+ Distribution of actual finished pages, vs abandoned pages, where we needed
+ to declare a finish time prematurely since the page was being closed
+ (exited).
+ </summary>
+</histogram>
+
+<histogram name="PLT.BeginToFinish" units="milliseconds">
+ <summary>TBD</summary>
+</histogram>
+
+<histogram name="PLT.BeginToFinish_AfterPreconnectRequest" units="milliseconds">
+ <summary>
+ PLT.BeginToFinish, but for pages requested just after a new preconnect
+ request.
+ </summary>
+</histogram>
+
+<histogram name="PLT.BeginToFinish_ContentPrefetcher" units="milliseconds">
+ <summary>
+ PLT.BeginToFinish, but for pages which contained prefetch links.
+ </summary>
+</histogram>
+
+<histogram name="PLT.BeginToFinish_ContentPrefetcherReferrer"
+ units="milliseconds">
+ <summary>
+ PLT.BeginToFinish, but for pages which were referred to by pages which
+ contained prefetch links.
+ </summary>
+</histogram>
+
+<histogram name="PLT.BeginToFinishDoc">
+ <summary>TBD</summary>
+</histogram>
+
+<histogram name="PLT.BeginToFinishDoc_AfterPreconnectRequest"
+ units="milliseconds">
+ <summary>
+ PLT.BeginToFinishDoc, but for pages requested just after a new preconnect
+ request.
+ </summary>
+</histogram>
+
+<histogram name="PLT.BeginToFinishDoc_ContentPrefetcher" units="milliseconds">
+ <summary>
+ PLT.BeginToFinishDoc, but for pages which contained prefetch links.
+ </summary>
+</histogram>
+
+<histogram name="PLT.BeginToFinishDoc_ContentPrefetcherReferrer"
+ units="milliseconds">
+ <summary>
+ PLT.BeginToFinishDoc, but for pages which were referred to by pages which
+ contained prefetch links.
+ </summary>
+</histogram>
+
+<histogram name="PLT.BeginToFirstPaint" units="milliseconds">
+ <summary>
+ Time from &quot;begin&quot; to &quot;first paint.&quot; &quot;Begin&quot;==
+ &quot;request&quot; if user requested, and &quot;start&quot; otherwise.
+ &quot;Request&quot;== time when user requested document. &quot;Start&quot;==
+ time when renderer requested load of document, after any unload of last
+ document. &quot;First paint&quot;== time when first paint operation was
+ performed.
+ </summary>
+</histogram>
+
+<histogram name="PLT.CommitToFirstPaint" units="milliseconds">
+ <summary>
+ Time from &quot;commit&quot; to &quot;first paint.&quot;
+ &quot;Commit&quot;== time when renderer got first byte of document.
+ &quot;First paint&quot;== time when first paint operation was performed.
+ </summary>
+</histogram>
+
+<histogram name="PLT.LoadType" enum="LoadType">
+ <summary>
+ Probability distribution for enumerated varieties of page loads.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_Connect" units="milliseconds">
+ <summary>
+ Time from connectStart to connectEnd based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DelayBeforeConnect" units="milliseconds">
+ <summary>
+ Time from domanLookupEnd to connectStart based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DelayBeforeDomainLookup" units="milliseconds">
+ <summary>
+ Time from fetchStart to domainLookupStart based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DelayBeforeDomLoading" units="milliseconds">
+ <summary>
+ Time from responseStart to domLoading based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DelayBeforeFetch" units="milliseconds">
+ <summary>
+ Time from navigationStart to fetchStart based on Navigation Timing when no
+ redirect.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DelayBeforeFetchRedirect" units="milliseconds">
+ <summary>
+ Time from navigationStart to fetchStart excluding time spent on redirects
+ based on Navigation Timing. Only page loads with redirects are considered.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DelayBeforeLoadEvent" units="milliseconds">
+ <summary>
+ Time from domContentLoadedEventEnd to loadEventStart based on Navigation
+ Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DelayBeforeRequest" units="milliseconds">
+ <summary>
+ Time from connectEnd to requestStart based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DomainLookup" units="milliseconds">
+ <summary>
+ Time from domainLookupStart to domainLookupEnd based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DomContentLoaded" units="milliseconds">
+ <summary>
+ Time from domContentLoadedEventStart to domContentLoadedEventEnd based on
+ Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DomInteractive" units="milliseconds">
+ <summary>
+ Time from domInteractive to domContentLoadEventStart based on Navigation
+ Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_DomLoading" units="milliseconds">
+ <summary>
+ Time from domLoading to domInteractive based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_LoadEvent" units="milliseconds">
+ <summary>
+ Time from loadEventStart to loadEventEnd based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_Redirect" units="milliseconds">
+ <summary>
+ Time from redirectStart to redirectEnd based on Navigation Timing when
+ redirects exist.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_Request" units="milliseconds">
+ <summary>
+ Time from requestStart to responseStart based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.NT_Response" units="milliseconds">
+ <summary>
+ Time from responseStart to responseEnd based on Navigation Timing.
+ </summary>
+</histogram>
+
+<histogram name="PLT.PerceivedLoadTime" units="milliseconds">
+ <obsolete>
+ Deprecated as of 5/02/2011, replaced by Prerender.RendererPLT.
+ </obsolete>
+ <summary>
+ Perceived load time of a page. For non-prerendered pages, this is just
+ BeginToFinish. For displayed prerendered pages, this is the time from when
+ the prerendered page is moved into a TabContents until finish.
+ &quot;Finish&quot; == after onload() and all resources are loaded. Note that
+ this is 0 if the loading finishes before the page is moved into a
+ TabContents.
+ </summary>
+</histogram>
+
+<histogram name="PLT.PerceivedLoadTime_PrerenderLoad" units="milliseconds">
+ <obsolete>
+ Deprecated as of 5/02/2011, replaced by
+ Prerender.RendererPerceivedPLTMatched.
+ </obsolete>
+ <summary>
+ Perceived load time of a prerendered page that is displayed. This is the
+ time from when the prerendered page is moved into a TabContents until
+ finish. &quot;Finish&quot; == after onload() and all resources are loaded.
+ Note that this is 0 if the loading finishes before the the page is moved
+ into a TabContents.
+ </summary>
+</histogram>
+
+<histogram name="PLT.RequestToFinish" units="milliseconds">
+ <summary>
+ Time from &quot;request&quot; to &quot;finish.&quot; &quot;Request&quot; ==
+ time when user requested document. &quot;Finish&quot; == after onload() and
+ all resources are loaded.
+ </summary>
+</histogram>
+
+<histogram name="PLT.StartToCommit" units="milliseconds">
+ <summary>
+ Time from &quot;start&quot; to &quot;commit.&quot; &quot;Start&quot;== time
+ when renderer requested load of document, after any unload of last document.
+ &quot;Commit&quot;== time when renderer got first byte of document.
+ </summary>
+</histogram>
+
+<histogram name="PLT.StartToFinish" units="milliseconds">
+ <summary>
+ Time from &quot;start&quot; to &quot;finish.&quot; &quot;Start&quot;== time
+ when renderer requested load of document, after any unload of last document.
+ &quot;Finish&quot;==after onload() and all resources are loaded.
+ </summary>
+</histogram>
+
+<histogram name="Plugin.PpapiBrokerLoadResult" enum="PluginLoadResult">
+ <summary>The result from an attempt to load a PPAPI broker.</summary>
+</histogram>
+
+<histogram name="Plugin.PpapiPluginLoadResult" enum="PluginLoadResult">
+ <summary>The result from an attempt to load a PPAPI plugin.</summary>
+</histogram>
+
+<histogram name="Power.BacklightLevelOnAC" units="%">
+ <summary>
+ The level of the backlight as a percentage when the user is on AC. Sampled
+ every 30 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Power.BacklightLevelOnBattery" units="%">
+ <summary>
+ The level of the backlight as a percentage when the user is on battery.
+ Sampled every 30 seconds.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryChargeHealth" units="%">
+ <summary>
+ Chrome OS battery charge health percentage. Sampled once when device starts
+ charging.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryDischargeRate" units="mW">
+ <summary>
+ Chrome OS battery discharge rate in mW sampled every 30 seconds while the
+ device runs on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryDischargeRateWhileSuspended" units="mW">
+ <summary>
+ Chrome OS battery discharge rate in mW while the system was suspended,
+ sampled at resume. Only reported if the system was on battery power both
+ before suspending and after resuming, if the energy level didn't increase
+ while suspended (which would indicate that an AC adapter was connected), and
+ if the system was suspended for at least a minute.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryInfoSample" enum="BatteryInfoSampleResult">
+ <summary>
+ Counts the number of times we have read the battery status from sysfs and if
+ it gave us sensible values.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryRemainingAtEndOfSessionOnAC" units="%">
+ <summary>
+ Chrome OS remaining battery charge as percent of the maximum battery charge,
+ sampled at the end of a user session when the device is on AC.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryRemainingAtEndOfSessionOnBattery" units="%">
+ <summary>
+ Chrome OS remaining battery charge as percent of the maximum battery charge,
+ sampled at the end of a user session when the device is on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryRemainingAtStartOfSessionOnAC" units="%">
+ <summary>
+ Chrome OS remaining battery charge as percent of the maximum battery charge,
+ sampled at the start of a user session when the device is on AC.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryRemainingAtStartOfSessionOnBattery" units="%">
+ <summary>
+ Chrome OS remaining battery charge as percent of the maximum battery charge,
+ sampled at the start of a user session when the device is on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryRemainingCharge" units="%">
+ <obsolete>
+ Deprecated as of 03/2012, no longer being generated by powerd.
+ </obsolete>
+ <summary>
+ Chrome OS remaining battery charge as percent of the maximum battery charge
+ sampled when the device runs on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryRemainingWhenChargeStarts" units="%">
+ <summary>
+ Chrome OS remaining battery charge as percent of the maximum battery charge,
+ sampled when charging starts.
+ </summary>
+</histogram>
+
+<histogram name="Power.BatteryTimeToEmpty" units="minutes">
+ <obsolete>
+ Deprecated as of 03/2012, no longer being generated by powerd.
+ </obsolete>
+ <summary>
+ Chrome OS remaining time to empty battery in minutes sampled when the device
+ runs on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.BitfixChunks">
+ <summary>
+ Chrome OS (Snow RO firmware 2695.90.0 only) number of 8K chunks that were
+ fixed (memory corruption corrected) for each suspend/resume cycle. Expect 0
+ around 97% of the time and a non-zero value around 3% of the time.
+ </summary>
+</histogram>
+
+<histogram name="Power.BitfixFixes">
+ <summary>
+ Chrome OS (Snow RO firmware 2695.90.0 only) number of 4-byte words that were
+ fixed (memory corruption corrected) for each suspend/resume cycle. Expect 0
+ around 97% of the time and a non-zero value around 3% of the time. Would be
+ exactly equal to Power.BitfixChunks if there were only one corrupted word in
+ each chunk but is sometimes several times higher.
+ </summary>
+</histogram>
+
+<histogram name="Power.BrightnessAdjustOnAC" enum="PowerBrightnessAdjust">
+ <obsolete>
+ Deprecated as of 5/2013. See Accel_BrightnessDown_F6 and
+ Accel_BrightnessUp_F7 user actions instead.
+ </obsolete>
+ <summary>
+ Number of times the user has adjusted brightness up and down while running
+ on battery power.
+ </summary>
+</histogram>
+
+<histogram name="Power.BrightnessAdjustOnBattery" enum="PowerBrightnessAdjust">
+ <obsolete>
+ Deprecated as of 5/2013. See Accel_BrightnessDown_F6 and
+ Accel_BrightnessUp_F7 user actions instead.
+ </obsolete>
+ <summary>
+ Number of times the user has adjusted brightness up and down while running
+ on AC power.
+ </summary>
+</histogram>
+
+<histogram name="Power.FirmwareResumeTimeOnAC" units="milliseconds">
+ <summary>
+ The time that the firmware took to resume the Chrome OS device from
+ suspend-to-RAM state when running on AC at pre-suspend time.
+ </summary>
+</histogram>
+
+<histogram name="Power.FirmwareResumeTimeOnBattery" units="milliseconds">
+ <summary>
+ The time that the firmware took to resume the Chrome OS device from
+ suspend-to-RAM state when running on battery at pre-suspend time.
+ </summary>
+</histogram>
+
+<histogram name="Power.IdleTimeAfterDimOnAC" units="milliseconds">
+ <summary>
+ Chrome OS user idle time since the screen dimmed sampled when the user
+ becomes active again if the device runs on AC.
+ </summary>
+</histogram>
+
+<histogram name="Power.IdleTimeAfterDimOnBattery" units="milliseconds">
+ <summary>
+ Chrome OS user idle time since the screen dimmed sampled when the user
+ becomes active again if the device runs on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.IdleTimeAfterScreenOffOnAC" units="milliseconds">
+ <summary>
+ Chrome OS user idle time since the screen turned off sampled when the user
+ becomes active again if the device runs on AC.
+ </summary>
+</histogram>
+
+<histogram name="Power.IdleTimeAfterScreenOffOnBattery" units="milliseconds">
+ <summary>
+ Chrome OS user idle time since the screen turned off sampled when the user
+ becomes active again if the device runs on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.IdleTimeOnAC" units="milliseconds">
+ <summary>
+ Chrome OS user idle time sampled when the user becomes active again if the
+ device runs on AC.
+ </summary>
+</histogram>
+
+<histogram name="Power.IdleTimeOnBattery" units="milliseconds">
+ <summary>
+ Chrome OS user idle time sampled when the user becomes active again if the
+ device runs on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.KernelResumeTimeOnAC" units="milliseconds">
+ <summary>
+ The time that the kernel took to resume the Chrome OS device from
+ suspend-to-RAM state when running on AC at pre-suspend time.
+ </summary>
+</histogram>
+
+<histogram name="Power.KernelResumeTimeOnBattery" units="milliseconds">
+ <summary>
+ The time that the kernel took to resume the Chrome OS device from
+ suspend-to-RAM state when running on battery at pre-suspend time.
+ </summary>
+</histogram>
+
+<histogram name="Power.KernelSuspendTimeOnAC" units="milliseconds">
+ <summary>
+ The time that the kernel took to suspend-to-RAM the Chrome OS device when
+ running on AC.
+ </summary>
+</histogram>
+
+<histogram name="Power.KernelSuspendTimeOnBattery" units="milliseconds">
+ <summary>
+ The time that the kernel took to suspend-to-RAM the Chrome OS device when
+ running on battery.
+ </summary>
+</histogram>
+
+<histogram name="Power.KeyboardBacklightLevel" units="%">
+ <summary>
+ The level of the keyboard backlight as a percentage. Sampled every 30
+ seconds.
+ </summary>
+</histogram>
+
+<histogram name="Power.LengthOfSession" units="seconds">
+ <summary>
+ The length of time, in seconds, that a user spent in a single session.
+ Values for this metric are clamped to 12 hours, so the last bucket should be
+ considered to be including all metrics above 12 hours.
+ </summary>
+</histogram>
+
+<histogram name="Power.MilliConsumptionPerHourIosOnActive">
+ <summary>
+ The average power consumption, measured in milli-units per hour, when sync
+ invalidator listens to on_application_active events. Values for this metric
+ are per session, i.e. from battery level at application entering foreground
+ to returning to background, and normalized to an hourly average consumption.
+ This is an iOS only measurement. Due to how iOS reports battery levels, it
+ is likely to see many readings of 0.
+ </summary>
+</histogram>
+
+<histogram name="Power.MilliConsumptionPerHourOthers">
+ <summary>
+ The average power consumption, measured in milli-units per hour, for other
+ sync invalidator methods. Values for this metric are per session, i.e. from
+ battery level at application entering foreground to returning to background,
+ and normalized to an hourly average consumption. This is an iOS only
+ measurement. Due to how iOS reports battery levels, it is likely to see many
+ readings of 0.
+ </summary>
+</histogram>
+
+<histogram name="Power.MilliConsumptionPerHourP2P">
+ <summary>
+ The average power consumption, measured in milli-units per hour, when sync
+ invalidator uses peer-to-peer notifications. Values for this metric are per
+ session, i.e. from battery level at application entering foreground to
+ returning to background, and normalized to an hourly average consumption.
+ This is an iOS only measurement. Due to how iOS reports battery levels, it
+ is likely to see many readings of 0.
+ </summary>
+</histogram>
+
+<histogram name="Power.MilliConsumptionPerHourServer">
+ <summary>
+ The average power consumption, measured in milli-units per hour, when sync
+ invalidator uses server-based non-blocking invalidator. Values for this
+ metric are per session, i.e. from battery level at application entering
+ foreground to returning to background, and normalized to an hourly average
+ consumption. This is an iOS only measurement. Due to how iOS reports battery
+ levels, it is likely to see many readings of 0.
+ </summary>
+</histogram>
+
+<histogram name="Power.NumberOfAlsAdjustmentsPerSession">
+ <summary>
+ The number of times that the Automatic Light Sensor (ALS) adjusted the
+ brightness during a session. Values for this metric are clamped to 10k
+ count, so the last bucket should be considered to be including all metrics
+ above 10k.
+ </summary>
+</histogram>
+
+<histogram name="Power.NumberOfSessionsPerCharge">
+ <summary>
+ The number of user sessions that occured since the last time that the device
+ was charged. Values for this metric are clamped at 10k, so the last bucket
+ should be considered to include all metrics about 10k.
+ </summary>
+</histogram>
+
+<histogram name="Power.RetrySuspendCount">
+ <summary>
+ The number of times Chrome OS retried suspend due to previous failure.
+ </summary>
+</histogram>
+
+<histogram name="Power.SuspendStatus" enum="SuspendStatus">
+ <summary>
+ ChromeOS suspend status - either success, failure, or cancelled.
+ </summary>
+</histogram>
+
+<histogram name="Power.ThermalAbortedFanTurnOn" units="%">
+ <summary>
+ The percentage of aborted fan attempts out of total fan attempts per
+ session, where an abort is due to hysteresis. This value is computed from
+ boot and sent when powerd starts and then every 15 minutes afterwards.
+ </summary>
+</histogram>
+
+<histogram name="Power.ThermalMultipleFanTurnOn" units="%">
+ <summary>
+ The percentage of fan trip point passes that are more than one trip point.
+ This value is computed from boot and sent when powerd starts and then every
+ 15 minutes afterwards.
+ </summary>
+</histogram>
+
+<histogram name="Power.TimeInSuspendAtBoot" units="minutes">
+ <summary>
+ Chrome OS time in minutes spent in suspend-to-RAM mode sampled at boot
+ (i.e., the device most likely ran out of battery while in suspend).
+ </summary>
+</histogram>
+
+<histogram name="Power.TimeInSuspendAtResume" units="minutes">
+ <summary>
+ Chrome OS time in minutes spent in suspend-to-RAM mode sampled at resume.
+ </summary>
+</histogram>
+
+<histogram name="Power.UserBrightnessAdjustmentsPerSessionOnAC">
+ <summary>
+ The number of times that the user adjusted the brightness during a session
+ when on AC. Values for this metric are clamped to 10k count, so the last
+ bucket should be considered to be including all metrics above 10k.
+ </summary>
+</histogram>
+
+<histogram name="Power.UserBrightnessAdjustmentsPerSessionOnBattery">
+ <summary>
+ The number of times that the user adjusted the brightness during a session
+ when on battery. Values for this metric are clamped to 10k count, so the
+ last bucket should be considered to be including all metrics above 10k.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.Events" enum="PrerenderHoverEvent">
+ <obsolete>
+ deprecated May 10 2012
+ </obsolete>
+ <summary>Hover Event counts for prerendering.</summary>
+</histogram>
+
+<histogram name="Prerender.FinalStatus" enum="PrerenderFinalStatus">
+ <summary>
+ Final status for prerender pages - either success, or why it was canceled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.FinalStatusMatchComplete"
+ enum="PrerenderFinalStatus">
+ <summary>
+ Final status for prerender pages - either success, or why it was canceled.
+ This is for the MatchComplete set of pages (including some pages that were
+ not actually prerendered), to match the control group.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.FractionPixelsFinalAtSwapin">
+ <summary>
+ For prerenders that are swapped in, the percentage of pixels that is already
+ final at swap-in time compared to when the spinner stops.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.HoverStats_TimeUntilClicked" units="milliseconds">
+ <obsolete>
+ deprecated May 10 2012
+ </obsolete>
+ <summary>
+ Duration that a user hovers a link before clicking on it.
+
+ This is recorded for all pages loaded in a session.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.HoverStats_TimeUntilDiscarded" units="milliseconds">
+ <obsolete>
+ deprecated May 10 2012
+ </obsolete>
+ <summary>
+ Duration that the mouse pointer hovers on a link before the mouse pointer
+ moves off of it.
+
+ This is recorded for all pages loaded in a session.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.LocalPredictorEvent"
+ enum="PrerenderLocalPredictorEvents">
+ <summary>
+ Enumeration of what events related to the local predictor have occurred
+ </summary>
+</histogram>
+
+<histogram name="Prerender.LocalPredictorTimeUntilUsed" units="milliseconds">
+ <summary>
+ Time from when a prerendered page is started to when it is first used due to
+ user navigation. If the page is never used, it is not included in this
+ histogram. This only refers to prerenders based on the local predictor.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.LocalVisitCoreTransition"
+ enum="PrerenderLocalVisitCoreTransition">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>
+ The transition type for each new visit as recorded in the local visits
+ database.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.LocalVisitDatabaseSize">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>Size of the local visits database (number of entries).</summary>
+</histogram>
+
+<histogram name="Prerender.LocalVisitEvents" enum="PrerenderLocalVisitEvents">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>
+ Enumeration of what events related to local visits have occurred
+ </summary>
+</histogram>
+
+<histogram name="Prerender.OmniboxNavigationsCouldPrerender">
+ <summary>
+ A boolean that indicates whether the Omnibox navigation being committed
+ could have been prerendered by the Omnibox Prerender system. This provides
+ an upper bound for Prerender.OmniboxNavigationsUsedPrerenderCount and allows
+ the potential for Omnibox Prerendering coverage to be understood. If Omnibox
+ Prerendering is disabled, this histogram will register a 'false' entry. The
+ total count is the equivalent of the deprecated
+ NetworkActionPredictor.NavigationCount histogram.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.OmniboxNavigationsUsedPrerenderCount">
+ <summary>
+ The number of navigations that use a prerender initiated from the Omnibox.
+ The count is incremented when the Prerendered tab is swapped in if the
+ Prerender was initiated by the Omnibox, which obviously requires
+ Prerendering from the Omnibox to be enabled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.OmniboxPrerenderCount">
+ <summary>
+ The number of prerenders initiated from the Omnibox. This is incremented
+ when the NetworkActionPredictor suggests Prerendering as an optimal strategy
+ given the text the user has entered and the Autocomplete suggestion
+ currently selected. It is only incremented if Prerendering from the Omnibox
+ is enabled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PageviewEvents" enum="PrerenderPageviewEvents">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>Types of pages rendered.</summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPageLoadTime_Control" units="milliseconds">
+ <obsolete>
+ Deprecated 03/24/11. Replaced by
+ Prerender.PerceivedPLT_ContentPrefetchPrerenderControl.
+ </obsolete>
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This particular histogram is for all page loads for users who do not have
+ prerendering enabled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPageLoadTime_PrerenderMatchControl"
+ units="milliseconds">
+ <obsolete>
+ Deprecated 03/24/11. Replaced by
+ Prerender.PerceivedPLTMatched_ContentPrefetchPrerenderControl.
+ </obsolete>
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This particular histogram is only for pages that would have been prerendered
+ if the user had prerender enabled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPageLoadTime_PrerenderMatchTreatment"
+ units="milliseconds">
+ <obsolete>
+ Deprecated 03/24/11. Replaced by
+ Prerender.PerceivedPLTMatched_ContentPrefetchPrerender.
+ </obsolete>
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This particular histogram is for all prerendered page loads for users who
+ have prerender enabled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPageLoadTime_Treatment"
+ units="milliseconds">
+ <obsolete>
+ Deprecated 03/24/11. Replaced by
+ Prerender.PerceivedPLT_ContentPrefetchPrerender.
+ </obsolete>
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This particular histogram is for all page loads for users who have
+ prerendering enabled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPageLoadTime_WindowControl"
+ units="milliseconds">
+ <obsolete>
+ Deprecated 03/24/11. Replaced by
+ Prerender.PerceivedPLTWindowed_ContentPrefetchPrerenderControl.
+ </obsolete>
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This particular histogram is for all page loads within 30 seconds after a
+ prefetch tag is seen for users who do not have prerendering enabled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPageLoadTime_WindowTreatment"
+ units="milliseconds">
+ <obsolete>
+ Deprecated 03/24/11. Replaced by
+ Prerender.PerceivedPLTWindowed_ContentPrefetchPrerender.
+ </obsolete>
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load pre navigation.
+
+ This particular histogram is for all page loads within 30 seconds after a
+ prefetch tag is seen for users who have prerendering enabled.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLT" units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This is recorded for all pages loaded in a session.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTFirstAfterMiss" units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This is recorded for the first page load completing immediately after a
+ prerender.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTFirstAfterMissAnyOnly"
+ units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ &quot;FirstAfterMiss&quot; means the first pageload after a prerender miss.
+ There are two types: Any, and Non-overlapping. The latter only applies to
+ page loads initiated after the prerender. This variable records cases where
+ only Any triggered.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTFirstAfterMissBoth" units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ &quot;FirstAfterMiss&quot; means the first pageload after a prerender miss.
+ There are two types: Any, and Non-overlapping. The latter only applies to
+ page loads initiated after the prerender. This variable records cases where
+ both triggered.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTFirstAfterMissNonOverlapping"
+ units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This is recorded for the first page load completing immediately after a
+ prerender, but which has also started after the prerender has been
+ initiated.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTFirstAfterMissNonOverlappingOnly"
+ units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ &quot;FirstAfterMiss&quot; means the first pageload after a prerender miss.
+ There are two types: Any, and Non-overlapping. The latter only applies to
+ page loads initiated after the prerender. This variable records cases where
+ only Non-overlapping triggered.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTMatched" units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This is recorded only for prerendered pages, or for pages which would have
+ been prerendered in the control case.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTMatchedComplete" units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This is recorded only for prerendered pages, or for pages which would have
+ been prerendered in the control case.
+
+ In MatchedComplete, the prerender group also contains cancelled prerenders,
+ so as to produce a perfect match of page views attributed this group in the
+ prerender group with those attributed to this group in the control group.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTWindowed" units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This is recorded for all page loads which happen within 30 seconds after a
+ prefetch tag is observed.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PerceivedPLTWindowNotMatched" units="milliseconds">
+ <summary>
+ Time from when a user navigates to a page to when it loads. Since the pages
+ may start loading before the user navigates to it, this does not include any
+ portion of load prior to navigation.
+
+ This is recorded for all page loads which happen within 30 seconds after a
+ prefetch tag is observed and which do not correspond to a prerender tag.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PercentLoadDoneAtSwapin">
+ <summary>
+ For prerenders that are swapped in, the percentage of the time from load
+ start until the onload event fires that has elapsed at the time of the
+ swapin.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PrerenderCountOf3Max">
+ <summary>
+ After launching a prerender, how many simultanious prerenders are recorded
+ as running, out of a maximum of three.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PrerenderNotSwappedInPLT" units="milliseconds">
+ <summary>
+ For prerenders that finish loading before they are ever swapped in, their
+ page load time until the onload event fires.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.PrerendersPerSessionCount">
+ <summary>
+ The number of sessions that have at least X successful prerenders.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.RendererIdleTime" units="milliseconds">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>
+ This is the time from when a prerendered page finishes loading to when it is
+ displayed, as measured by the renderer process. When a page is displayed
+ before it finishes loading, no value is recorded in this histogram.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.RendererPerceivedPLT" units="milliseconds">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>
+ Perceived load time of a page, as measured by the renderer process. For
+ non-prerendered pages, this is just BeginToFinish. For displayed prerendered
+ pages, this is the time from when the prerendered page is moved into a
+ TabContents until finish. &quot;Finish&quot; == after onload() and all
+ resources are loaded. Note that this is 0 if the loading finishes before the
+ page is moved into a TabContents.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.RendererPerceivedPLTMatched" units="milliseconds">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>
+ Perceived load time of a prerendered page that is displayed, as measured by
+ the renderer process. This is the time from when the prerendered page is
+ moved into a TabContents until finish. &quot;Finish&quot; == after onload()
+ and all resources are loaded. Note that this is 0 if the loading finishes
+ before the the page is moved into a TabContents.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.RendererTimeUntilDisplay" units="milliseconds">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>
+ The time elapsed between when the prerendering of a page starts and when the
+ page is displayed, as measured by the renderer process. Prerendered pages
+ discarded without being displayed are excluded from this count.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.SchemeCancelReason"
+ enum="PrerenderSchemeCancelReason">
+ <summary>
+ The detailed reason why a prerender is canceled with
+ FINAL_STATUS_UNSUPPORTED_SCHEME
+ </summary>
+</histogram>
+
+<histogram name="Prerender.Sessions" enum="PrerenderMode">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>Enumeration of how prerender was used per session.</summary>
+</histogram>
+
+<histogram name="Prerender.SimulatedLocalBrowsingBaselinePLT"
+ units="milliseconds">
+ <summary>
+ For simulated local browsing prerendering, the baseline PLT of pages without
+ any prerendering for pages that would be prerendered.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.SimulatedLocalBrowsingPLT" units="milliseconds">
+ <summary>
+ For simulated local browsing prerendering, the estimated PLT of pages with
+ prerendering enabled for pages that would be prerendered.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.TabContentsDeleterTimeout">
+ <summary>
+ A boolean that indicates how often we fail to delete an old prerendered tab
+ before the timeout.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.TabHelperEvent" enum="PrerenderTabHelperEvents">
+ <summary>
+ Enumeration of what events related to the TabHelper class have occurred.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.TimeBetweenPrerenderRequests" units="milliseconds">
+ <summary>Time between subsequent prerender requests.</summary>
+</histogram>
+
+<histogram name="Prerender.TimeSinceLastRecentVisit" units="milliseconds">
+ <summary>
+ The time elapsed between the most recent visit to a URL and when an
+ attempted prerender of the same URL is cancelled with
+ FINAL_STATUS_RECENTLY_VISITED.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.TimeToClick" units="milliseconds">
+ <obsolete>
+ deprecated Nov 16 2012
+ </obsolete>
+ <summary>Duration that a user hovers a link before clicking on it.</summary>
+</histogram>
+
+<histogram name="Prerender.TimeUntilUsed" units="milliseconds">
+ <obsolete>
+ deprecated Nov 16 2012. See Prerender.TimeUntilUsed2, which has a larger
+ range.
+ </obsolete>
+ <summary>
+ Time from when a prerendered page is started to when it is first used due to
+ user navigation. If the page is never used, it is not included in this
+ histogram.
+ </summary>
+</histogram>
+
+<histogram name="Prerender.TimeUntilUsed2" units="milliseconds">
+ <summary>
+ Time from when a prerendered page is started to when it is first used due to
+ user navigation. If the page is never used, it is not included in this
+ histogram.
+ </summary>
+</histogram>
+
+<histogram name="Profile.AppCount">
+ <summary>The number of installed apps when a profile is opened.</summary>
+</histogram>
+
+<histogram name="Profile.CreateResult" enum="ProfileCreateResult">
+ <summary>Result (final status) when creating a new profile.</summary>
+</histogram>
+
+<histogram name="Profile.CreateTime" units="milliseconds">
+ <summary>Back-end time elapsed while creating a new profile.</summary>
+</histogram>
+
+<histogram name="Profile.CreateTimeCanceled" units="milliseconds">
+ <summary>
+ Time elapsed before the user decided to cancel creation of a new profile.
+ Since only managed-user profile creation can be canceled, this time comes
+ from managed-user registration.
+ </summary>
+</histogram>
+
+<histogram name="Protector.DefaultSearchProvider" enum="ProtectorError">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ Errors that Protector detects about default search provider in Web Data.
+ Reported once when Web Data is loaded.
+ </summary>
+</histogram>
+
+<histogram name="Protector.Preferences" enum="ProtectorError">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ Errors that Protector detects about protected settings in Preferences.
+ Reported once when profile is loaded.
+ </summary>
+</histogram>
+
+<histogram name="Protector.SearchProvider" enum="SearchEngine">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ When the default search provider setting is changed outside of Chrome, which
+ is detected by the Protector, this histogram reports the new setting.
+ </summary>
+</histogram>
+
+<histogram name="Protector.StartupSettings" enum="SessionStartupType">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ When the startup settings are changed outside of Chrome, which is detected
+ by the Protector, this histogram reports the new setting.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.docPageCount">
+ <summary>
+ Records the page count when a compound binary format document is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.docParagraphCount">
+ <summary>
+ Records the paragraph count when a compound binary format document is
+ opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.docSectionCount">
+ <summary>
+ Records the section count when a compound binary format document is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.docxPageCount">
+ <summary>
+ Records the page count when an OOXML format document is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.docxParagraphCount">
+ <summary>
+ Records the paragraph count when an OOXML format document is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.docxSectionCount">
+ <summary>
+ Records the section count when an OOXML format document is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.ErrorTypes" enum="QuickofficeErrorTypes">
+ <summary>
+ Records the various different error types encountered when opening and
+ reading MS Office file formats in the Quickoffice viewer. These range from
+ Nacl crashes and uncaught javascript exceptions to document errors inside
+ Quickoffice Web Toolkit (eg QOWT). The errors are recorded against the file
+ format in which they occurred.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.FileFormat" enum="QuickofficeFileFormat">
+ <summary>
+ Records the various different file types supported by Quickoffice (like MS
+ Word, Excel, Powerpoint files) when they opened in the browser to measure
+ which file formats are most popular.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.pptMasterCount">
+ <summary>
+ Records the number of slide masters when a compound binary format
+ presentation is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.pptSlideCount">
+ <summary>
+ Records the slide count when a compound binary format presentation is
+ opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.pptxMasterCount">
+ <summary>
+ Records the number of slide masters when an OOXML format presentation is
+ opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.pptxSlideCount">
+ <summary>
+ Records the slide count when an OOXML format presentation is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.xlsNonEmptyCellCount">
+ <summary>
+ Records the number of non-empty cells in the default worksheet when a
+ compound binary format spreadsheet is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.xlsSheetCount">
+ <summary>
+ Records the number of worksheets when a compound binary format spreadsheet
+ is opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.xlsxNonEmptyCellCount">
+ <summary>
+ Records the number of non-empty cells when an OOXML format spreadsheet is
+ opened.
+ </summary>
+</histogram>
+
+<histogram name="Quickoffice.xlsxSheetCount">
+ <summary>
+ Records the number of worksheets when an OOXML format spreadsheet is opened.
+ </summary>
+</histogram>
+
+<histogram name="Renderer.DrawDuration" units="milliseconds">
+ <summary>The time it takes for the compositor to draw a frame.</summary>
+</histogram>
+
+<histogram name="Renderer.DrawDurationOverestimate" units="milliseconds">
+ <summary>
+ The amount by which the compositor's draw duration was overestimated in a
+ particular frame (0 if the duration was perfectly predicted or
+ underestimated).
+ </summary>
+</histogram>
+
+<histogram name="Renderer.DrawDurationUnderestimate" units="milliseconds">
+ <summary>
+ The amount by which the compositor's draw duration was underestimated in a
+ particular frame (0 if the duration was perfectly predicted or
+ overestimated).
+ </summary>
+</histogram>
+
+<histogram name="Renderer.PixelIncreaseFromTransitions">
+ <summary>
+ A lower-bound on the percentage increase in memory that would result from
+ promoting all layers that have a webkit-transition on opacity or transform.
+ </summary>
+</histogram>
+
+<histogram name="Renderer2.FinishDocToFinish">
+ <summary>
+ The time from when a document finished loading to when all it's resources
+ are also loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer2.RequestToFinish">
+ <obsolete>
+ Deprecated 6/15/09. Replaced by Renderer2.RequestToFinish_L
+ </obsolete>
+ <summary>
+ The time from when a page was requested by a user to when it is fully
+ loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer2.RequestToFinish_L">
+ <summary>
+ The time from when a page was requested by a user to when it is fully
+ loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer2.RequestToFirstLayout">
+ <summary>
+ The time from when a page was requested by a user to its first layout.
+ </summary>
+</histogram>
+
+<histogram name="Renderer2.RequestToStart">
+ <summary>
+ The time from when a page was requested by a user to when it starts loading.
+ </summary>
+</histogram>
+
+<histogram name="Renderer2.StartToFinish">
+ <summary>
+ The time from when a page started loading to when it is fully loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer2.StartToFinishDoc">
+ <summary>
+ The time from when a page starts loading to when the main document is
+ finished loading.
+ </summary>
+</histogram>
+
+<histogram name="Renderer2.StartToFirstLayout">
+ <summary>
+ The time from when a page starts loading to its first layout.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.Abandoned" enum="Abandoned">
+ <summary>
+ Distribution of actual finished pages, vs abandoned pages, where we needed
+ to declare a finish time prematurely since the page was being closed
+ (exited).
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.AccelContentPaintDurationMS">
+ <summary>
+ Time spent by WebKit painting the page, in milliseconds, when the GPU
+ acceleration is active, for paints that affect non-root layers.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.AccelContentPaintMegapixPerSecond">
+ <summary>
+ WebKit paint throughput, measured in megapixels per second, when GPU
+ acceleration is active, for paints that affect non-root layers.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.AccelDoDeferredUpdateDelay">
+ <summary>Time between frames when GPU acceleration is active.</summary>
+</histogram>
+
+<histogram name="Renderer4.AccelRootPaintDurationMS">
+ <summary>
+ Time spent by WebKit painting the page, in milliseconds, when the GPU
+ acceleration is active, for paints that affect the root layer.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.AccelRootPaintMegapixPerSecond">
+ <summary>
+ WebKit paint throughput, measured in megapixels per second, when GPU
+ acceleration is active, for paints that affect the root layer.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.AnimationCallbackDelayTime" units="milliseconds">
+ <summary>
+ Time from when the animation callback was posted to when it ran.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.BeginToCommit" units="milliseconds">
+ <summary>
+ Time from &quot;begin&quot; to &quot;commit.&quot; &quot;Begin&quot;==
+ &quot;request&quot; if user requested, and &quot;start&quot; otherwise.
+ &quot;Request&quot;== time when user requested document. &quot;Start&quot;==
+ time when renderer requested load of document, after any unload of last
+ document. &quot;Commit&quot;== time when renderer got first byte of
+ document.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.BeginToFinish">
+ <summary>TBD</summary>
+</histogram>
+
+<histogram name="Renderer4.BeginToFinishDoc">
+ <summary>TBD</summary>
+</histogram>
+
+<histogram name="Renderer4.BeginToFirstPaint" units="milliseconds">
+ <summary>
+ Time from &quot;begin&quot; to &quot;first paint.&quot; &quot;Begin&quot;==
+ &quot;request&quot; if user requested, and &quot;start&quot; otherwise.
+ &quot;Request&quot;== time when user requested document. &quot;Start&quot;==
+ time when renderer requested load of document, after any unload of last
+ document. &quot;First paint&quot;== time when first paint operation was
+ performed.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.BeginToFirstPaintAfterLoad" units="milliseconds">
+ <summary>
+ Time from &quot;big&quot; to &quot;first paint after load.&quot;
+ &quot;Begin&quot;== &quot;request&quot; if user requested, and
+ &quot;start&quot; otherwise. &quot;Request&quot;== time when user requested
+ document. &quot;Start&quot;== time when renderer requested load of document,
+ after any unload of last document. &quot;First paint after load&quot;== time
+ after onload() when first paint operation is performed.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.CommitToFinish" units="milliseconds">
+ <summary>
+ Time from &quot;commit&quot; to &quot;finish.&quot; &quot;Commit&quot;==
+ time when renderer got first byte of document. &quot;Finish&quot;==after
+ onload() and all resources are loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.CommitToFinishDoc" units="milliseconds">
+ <summary>
+ Time from &quot;commit&quot; to &quot;finish doc.&quot; &quot;Commit&quot;==
+ time when renderer got first byte of document. &quot;Finish doc&quot; ==
+ main document loaded, before onload(). &quot;Finish&quot;==after onload()
+ and all resources are loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.CommitToFirstPaint" units="milliseconds">
+ <summary>
+ Time from &quot;commit&quot; to &quot;first paint.&quot;
+ &quot;Commit&quot;== time when renderer got first byte of document.
+ &quot;First paint&quot;== time when first paint operation was performed.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.CommitToFirstPaintAfterLoad" units="milliseconds">
+ <summary>
+ Time from &quot;commit&quot; to &quot;first paint after load.&quot;
+ &quot;Commit&quot;== time when renderer got first byte of document.
+ &quot;First paint after load&quot;== time after onload() when first paint
+ operation is performed.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.CompositorThreadImplDrawDelay" units="milliseconds">
+ <summary>
+ Time between frames, as measured on the compositor thread. This is collected
+ once per frame while it is being drawn to the screen in the compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.drawPixelCountCulled" units="NormalizedPixels">
+ <obsolete>
+ Renamed to Renderer4.pixelCountCulled_Draw.
+ </obsolete>
+ <summary>
+ Number of pixels that culling prevented being drawn to the screen,
+ normalized to the viewport size. This is collected once per frame while it
+ is being drawn to the screen in the compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.drawPixelCountOpaque" units="NormalizedPixels">
+ <obsolete>
+ Renamed to Renderer4.pixelCountOpaque_Draw.
+ </obsolete>
+ <summary>
+ Number of pixels drawn to the screen and known opaque, normalized to the
+ viewport size. This is collected once per frame while it is being drawn to
+ the screen in the compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.drawPixelCountTranslucent" units="NormalizedPixels">
+ <obsolete>
+ Renamed to Renderer4.pixelCountTranslucent_Draw.
+ </obsolete>
+ <summary>
+ Number of pixels drawn to the screen and not known opaque, normalized to the
+ viewport size. This is collected once per frame while it is being drawn to
+ the screen in the compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.FinishDocToFinish" units="milliseconds">
+ <summary>
+ Time from &quot;finish doc&quot; to &quot;finish.&quot; &quot;Finish
+ doc&quot;== main document loaded, before onload(). &quot;Finish&quot;==after
+ onload() and all resources are loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.FinishToFirstPaintAfterLoad" units="milliseconds">
+ <summary>
+ Time from &quot;finish &quot; to &quot;first paint after load.&quot;
+ &quot;Finish&quot;==after onload() and all resources are loaded. &quot;First
+ paint after load&quot;== time after onload() when first paint operation is
+ performed.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.LanguageDetection" units="milliseconds">
+ <summary>
+ Time to determine the page language. This is done after the page has been
+ loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.LCDText.PercentageOfAALayers" units="%">
+ <summary>
+ The ratio of LCDText CC Layers / candidate LCDText layers. Recorded in
+ LayerTreeHost, after LayerTreeHostCommon::CalculateDrawProperties() has
+ computed the properties we need. Only recorded for the first 50 frames of
+ every page.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.LCDText.PercentageOfCandidateLayers" units="%">
+ <summary>
+ The ratio of CC Layers which are candidates for LCDText AA / total picture
+ or content Layers. Recorded in LayerTreeHost, after
+ LayerTreeHostCommon::CalculateDrawProperties() has computed the properties
+ we need. Only recorded for the first 50 frames of every page.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.LoadType" enum="LoadType">
+ <summary>
+ Probability distribution for enumerated varieties of page loads.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.pixelCountCulled_Draw" units="NormalizedPixels">
+ <summary>
+ Number of pixels that culling prevented being drawn to the screen, recorded
+ as 10 times the percentage of the viewport that these pixels cover. This is
+ collected once per frame while it is being drawn to the screen in the
+ compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.pixelCountOpaque" units="NormalizedPixels">
+ <summary>
+ Number of pixels known to be opaque, recorded as 10 times the percentage of
+ the viewport that these pixels cover.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.pixelCountPainted" units="NormalizedPixels">
+ <summary>
+ Number of pixels painted by WebKit into main memory, recorded as 10 times
+ the percentage of the viewport that these pixels cover. This is collected
+ once per commit from WebKit to the compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.pixelCountTranslucent" units="NormalizedPixels">
+ <summary>
+ Number of pixels not known to be opaque opaque, recorded as 10 times the
+ percentage of the viewport that these pixels cover.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.renderPassCount">
+ <summary>
+ The number of render passes (or render targets) in the renderer's frame. If
+ the value is more than one, then an intermediate rendering target must be
+ used during the rendering of the frame for each render pass greater than
+ one.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.RequestToFinish" units="milliseconds">
+ <summary>
+ Time from &quot;request&quot; to &quot;finish.&quot; &quot;Request&quot;==
+ time when user requested document. &quot;Finish&quot;==after onload() and
+ all resources are loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.RequestToStart" units="milliseconds">
+ <summary>
+ Time from &quot;request&quot; to &quot;start.&quot; &quot;Request&quot;==
+ time when user requested document. &quot;Start&quot;== time when renderer
+ requested load of document, after any unload of last document.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.Snapshot">
+ <summary>Time to capture a renderer snapshot.</summary>
+</histogram>
+
+<histogram name="Renderer4.SoftwareDoDeferredUpdateDelay">
+ <summary>Time between frames when the page is not GPU accelerated.</summary>
+</histogram>
+
+<histogram name="Renderer4.SoftwarePaintDurationMS">
+ <summary>
+ Time spent by WebKit painting the page, in milliseconds, when the page is
+ not GPU accelerated.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.SoftwarePaintMegapixPerSecond">
+ <summary>
+ WebKit paint throughput, measured in megapixels per second, when the page is
+ not GPU accelerated.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.StartToCommit" units="milliseconds">
+ <summary>
+ Time from &quot;start&quot; to &quot;commit.&quot; &quot;Start&quot;== time
+ when renderer requested load of document, after any unload of last document.
+ &quot;Commit&quot;== time when renderer got first byte of document.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.StartToFinish" units="milliseconds">
+ <summary>
+ Time from &quot;start&quot; to &quot;finish.&quot; &quot;Start&quot;== time
+ when renderer requested load of document, after any unload of last document.
+ &quot;Finish&quot;==after onload() and all resources are loaded.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.TextureGpuUploadTimeUS">
+ <summary>
+ The number of microseconds it took to upload a tile's full texture as
+ measured on the GPU process.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.Thumbnail">
+ <summary>Time to capture a renderer thumbnail.</summary>
+</histogram>
+
+<histogram name="Renderer4.tileCountCulled_Upload" units="NormalizedTiles">
+ <summary>
+ Number of tiles that culling prevented being uploaded to texture memory.
+ This is an approximation and is recorded as a 100 times the percentage of
+ the number of tiles, of default size, needed to cover the viewport. This is
+ collected once per commit from WebKit to the compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.uploadPixelCountCulled" units="NormalizedPixels">
+ <obsolete>
+ Deprecated as of 04/2012, replaced with Renderer4.tileCountCulled_Upload.
+ </obsolete>
+ <summary>
+ Number of pixels that culling prevented being uploaded to texture memory,
+ normalized to the viewport size. This is collected once per commit from
+ WebKit to the compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.uploadPixelCountOpaque" units="NormalizedPixels">
+ <obsolete>
+ Renamed to Renderer4.pixelCountOpaque_Upload.
+ </obsolete>
+ <summary>
+ Number of pixels uploaded to texture memory and known to be opaque,
+ normalized to the viewport size. This is collected once per commit from
+ WebKit to the compositor.
+ </summary>
+</histogram>
+
+<histogram name="Renderer4.uploadPixelCountTranslucent"
+ units="NormalizedPixels">
+ <obsolete>
+ Renamed to Renderer4.pixelCountTranslucent_Upload.
+ </obsolete>
+ <summary>
+ Number of pixels uploaded to texture memory and not known opaque, normalized
+ to the viewport size. This is collected once per commit from WebKit to the
+ compositor.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.DismissalState"
+ enum="AutofillDialogDismissalState">
+ <summary>
+ The state of the requestAutocomplete() dialog when it was dismissed.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.InitialUserState"
+ enum="AutofillDialogInitialUserState">
+ <summary>
+ The initial state of a user that's interacting with a freshly shown
+ requestAutocomplete() dialog.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.PopupInDialog"
+ enum="AutofillDialogPopupEvent">
+ <summary>
+ User interactions with the Autofill popup shown while filling an
+ requestAutocomplete() dialog.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.Security" enum="AutofillDialogSecurity">
+ <summary>
+ Measures the frequency of security warnings and errors in the
+ RequestAutocomplete dialog.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.UiDuration" units="ms">
+ <summary>
+ Measures the duration for which an requestAutocomplete() dialog was shown.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.UiDuration.Cancel" units="ms">
+ <summary>
+ Measures the duration for which an requestAutocomplete() dialog was shown,
+ in cases where the user ended up canceling out of the dialog.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.UiDuration.Submit" units="ms">
+ <summary>
+ Measures the duration for which an requestAutocomplete() dialog was shown,
+ in cases where the user ended up accepting the dialog.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.UiEvents" enum="AutofillDialogUiEvents">
+ <summary>
+ Measures how users are interacting with the requestAutocomplete() dialog UI.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.UiLatencyToShow" units="ms">
+ <summary>
+ Measures the duration of time it takes for the requestAutocomplete() UI to
+ be actionable by the user after it is shown.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.WalletErrors" enum="WalletErrors">
+ <summary>
+ Measures the frequency of errors in communicating with the Google Online
+ Wallet server.
+ </summary>
+</histogram>
+
+<histogram name="RequestAutocomplete.WalletRequiredActions"
+ enum="WalletRequiredActions">
+ <summary>
+ Measures the frequency of required user actions returned by the Google
+ Online Wallet server.
+ </summary>
+</histogram>
+
+<histogram name="SB.BloomFilter" units="milliseconds">
+ <summary>
+ The first stage check that measures the time that Chrome took to check if a
+ URL is present in our in-memory bloom filter.
+ </summary>
+</histogram>
+
+<histogram name="SB.BuildBloom">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <summary>TBD.</summary>
+</histogram>
+
+<histogram name="SB.Database" units="milliseconds">
+ <summary>
+ The second stage check that measures the time that Chrome took to check if a
+ URL is present in our SQLite database.
+ </summary>
+</histogram>
+
+<histogram name="SB.DBCheck" units="milliseconds">
+ <summary>
+ The second stage check that mesures the time that Chrome took to check if a
+ URL is present in our SQLite database. This time includes the filter check
+ time.
+ </summary>
+</histogram>
+
+<histogram name="SB.Delay" units="milliseconds">
+ <summary>
+ This measures the time that SafeBrowsing actually delayed the browsing
+ experience. It records the difference between the time when Chrome would
+ have started reading the response for a URL and when the SafeBrowsing system
+ completed its check of that URL.
+ </summary>
+</histogram>
+
+<histogram name="SB.FilterCheck" units="milliseconds">
+ <summary>
+ The first stage check that measures the time that Chrome took to check if a
+ URL is present in our in-memory hash table.
+ </summary>
+</histogram>
+
+<histogram name="SB.Network" units="milliseconds">
+ <summary>
+ The third and final stage check that mesures the time that Chrome took to
+ get a response from the Google SafeBrowsing servers for a particular URL.
+ </summary>
+</histogram>
+
+<histogram name="SB.NetworkCheck" units="milliseconds">
+ <summary>
+ The third and final stage check that mesures the time that Chrome took to
+ get a response from the Google SafeBrowsing servers for a particular URL.
+ This time includes the filter and database check time.
+ </summary>
+</histogram>
+
+<histogram name="SB.PauseSafe" units="milliseconds">
+ <summary>
+ This measures the time that SafeBrowsing actually delayed the browsing
+ experience. It records the difference between the time when Chrome would
+ have started reading the response for a URL and when the SafeBrowsing system
+ completed its check of that URL.
+ </summary>
+</histogram>
+
+<histogram name="SB.Update">
+ <summary>TBD.</summary>
+</histogram>
+
+<histogram name="SB2.AddPrefixes">
+ <summary>
+ The number of add prefixes stored in the database after the last update.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BloomFailure" enum="SB2BloomFailure">
+ <summary>
+ Track failures when in processing the safe-browsing database bloom filter.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BloomFilterFalsePositives"
+ enum="SB2BloomFilterFalsePositives">
+ <summary>
+ All prefix misses (server returned no full hashes) and prefix misses due to
+ false positives in the bloom filter.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BloomFilterLoad" units="ms">
+ <summary>Time to load the BloomFilter file.</summary>
+</histogram>
+
+<histogram name="SB2.BrowseDatabaseKilobytes" units="KB">
+ <summary>
+ The size of the browsing SafeBrowsing database file on disk in kilobytes,
+ after an update has occurred.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BuildFilter" units="milliseconds">
+ <summary>
+ The time that it took to regenerate the filter after we have received all
+ the update chunks.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BuildReadBytes" units="bytes">
+ <obsolete>
+ Deprecated because it was exceeding the range. Replaced by
+ SB2.BuildReadKilobytes.
+ </obsolete>
+ <summary>
+ The number of bytes read by the browser process during the bloom filter
+ generation phase.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BuildReadKilobytes" units="KB">
+ <summary>
+ The number of kilobytes read by the browser process during the filter
+ generation phase.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BuildReadOperations">
+ <summary>
+ The number of read operations issued by the browser process during the
+ filter generation phase.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BuildWriteBytes" units="bytes">
+ <obsolete>
+ Deprecated because it was exceeding the range. Replaced by
+ SB2.BuildWriteKilobytes.
+ </obsolete>
+ <summary>
+ The number of bytes written by the browser process during the bloom filter
+ generation phase.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BuildWriteKilobytes" units="KB">
+ <summary>
+ The number of kilobytes written by the browser process during the filter
+ generation phase.
+ </summary>
+</histogram>
+
+<histogram name="SB2.BuildWriteOperations">
+ <summary>
+ The number of write operations issued by the browser process during the
+ filter generation phase.
+ </summary>
+</histogram>
+
+<histogram name="SB2.ChunkInsert" units="milliseconds">
+ <summary>
+ The time that it takes to write one redirect URL (which can contain multiple
+ chunks) to the database.
+ </summary>
+</histogram>
+
+<histogram name="SB2.ChunkRequest" units="milliseconds">
+ <summary>
+ The network time between the request and response for a chunk.
+ </summary>
+</histogram>
+
+<histogram name="SB2.ChunkSize" units="bytes">
+ <summary>The size of one chunk URL.</summary>
+</histogram>
+
+<histogram name="SB2.DatabaseBytes" units="bytes">
+ <obsolete>
+ Deprecated because it was exceeding the range. Replaced by
+ SB2.DatabaseKilobytes.
+ </obsolete>
+ <summary>The size of the SafeBrowsing database file on disk.</summary>
+</histogram>
+
+<histogram name="SB2.DatabaseFailure" enum="SB2DatabaseFailure">
+ <summary>Track failures when updating the safe-browsing database.</summary>
+</histogram>
+
+<histogram name="SB2.DatabaseKilobytes" units="KB">
+ <obsolete>
+ Replaced by SB2.BrowseDatabaseKilobytes.
+ </obsolete>
+ <summary>
+ The size of the SafeBrowsing database file on disk in kilobytes.
+ </summary>
+</histogram>
+
+<histogram name="SB2.DatabaseOpen" units="milliseconds">
+ <summary>
+ The time it takes to initialize the SafeBrowsing storage backend, in
+ milliseconds.
+ </summary>
+</histogram>
+
+<histogram name="SB2.DatabaseUpdateKilobytes" units="KB">
+ <summary>
+ The size of the update file before merging with the database file, in
+ kilobytes.
+ </summary>
+</histogram>
+
+<histogram name="SB2.Delay" units="milliseconds">
+ <summary>
+ The time that SafeBrowsing actually delayed the browsing experience. It
+ records the difference between the time when Chrome would have started
+ reading the response for a URL and when the SafeBrowsing system completed
+ its check of that URL.
+ </summary>
+</histogram>
+
+<histogram name="SB2.DownloadChecks" enum="SB2DownloadChecks">
+ <summary>
+ Records results of SafeBrowsing download check, including both url check and
+ downloaded file hash check.
+ </summary>
+</histogram>
+
+<histogram name="SB2.DownloadDatabaseKilobytes" units="KB">
+ <summary>
+ The size of the downloads SafeBrowsing database file on disk in kilobytes,
+ after an update has occurred.
+ </summary>
+</histogram>
+
+<histogram name="SB2.DownloadDuration" units="milliseconds">
+ <summary>The time it takes for a download to finish.</summary>
+</histogram>
+
+<histogram name="SB2.DownloadHashCheckDuration" units="milliseconds">
+ <summary>
+ The time it takes for SafeBrowsing to check hash of a download file.
+ </summary>
+</histogram>
+
+<histogram name="SB2.DownloadUrlCheckDuration" units="milliseconds">
+ <summary>The time it takes for SafeBrowsing to check a download url.</summary>
+</histogram>
+
+<histogram name="SB2.DownloadUrlChecks" enum="SB2DownloadChecks">
+ <obsolete>
+ Deprecated 3/11/11, and replaced by SB2.DownloadChecks.
+ </obsolete>
+ <summary>Records results of SafeBrowsing download url check.</summary>
+</histogram>
+
+<histogram name="SB2.FailedUpdate">
+ <obsolete>
+ Deprecated, replaced by SB2.DatabaseFailure BROWSE_DB_UPDATE_FINISH.
+ </obsolete>
+ <summary>
+ The count of the number of times an update failed when being committed to
+ the database.
+ </summary>
+</histogram>
+
+<histogram name="SB2.FilterCheck" units="milliseconds">
+ <summary>
+ The time that it took to check a URL against our in-memory filter.
+ </summary>
+</histogram>
+
+<histogram name="SB2.FilterKilobytes" units="KB">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <summary>The size of the current bloom filter in kilobytes.</summary>
+</histogram>
+
+<histogram name="SB2.FilterLoad" enum="SB2FilterLoad">
+ <summary>Which filter file the database loaded from disk.</summary>
+</histogram>
+
+<histogram name="SB2.FilterMissing">
+ <obsolete>
+ Deprecated, replaced by SB2.DatabaseFailure FILTER_MISSING.
+ </obsolete>
+ <summary>
+ The count of the number of times we attempted to load the bloom filter file
+ but it was missing.
+ </summary>
+</histogram>
+
+<histogram name="SB2.FilterReadFail">
+ <obsolete>
+ Deprecated, replaced by SB2.DatabaseFailure FILTER_READ.
+ </obsolete>
+ <summary>
+ The count of the number of times we attempted to load the bloom filter file
+ but failed while reading the file on disk.
+ </summary>
+</histogram>
+
+<histogram name="SB2.FilterSize" units="bytes">
+ <obsolete>
+ Deprecated because it was exceeding the range. Replaced by
+ SB2.FilterKilobytes.
+ </obsolete>
+ <summary>The size of the current bloom filter.</summary>
+</histogram>
+
+<histogram name="SB2.FilterWriteFail">
+ <obsolete>
+ Deprecated, replaced by SB2.DatabaseFailure FILTER_WRITE.
+ </obsolete>
+ <summary>
+ The count of the number of times we attempted to save the bloom filter file
+ but failed while writing the file to disk.
+ </summary>
+</histogram>
+
+<histogram name="SB2.FormatEvent" enum="SB2FormatEvent">
+ <summary>
+ Tracks events involved in upgrading safe-browsing data from SQLite format to
+ new file format.
+ </summary>
+</histogram>
+
+<histogram name="SB2.GetHash200">
+ <obsolete>
+ Deprecated in favor of SB2.GetHashResult STATUS_200.
+ </obsolete>
+ <summary>
+ The number of GetHash requests that returned data (valid requests).
+ </summary>
+</histogram>
+
+<histogram name="SB2.GetHash204">
+ <obsolete>
+ Deprecated in favor of SB2.GetHashResult STATUS_204.
+ </obsolete>
+ <summary>
+ The number of GetHash requests that returned empty data (false positives).
+ </summary>
+</histogram>
+
+<histogram name="SB2.GetHashResult" enum="SB2GetHashResult">
+ <summary>
+ Track return status from GetHash requests to server (STATUS_200 and
+ STATUS_204), and dispensation of returned values (EMPTY, HIT, MISS). EMPTY
+ means the response had no full hashes, and should contain all of the 204
+ responses plus those 200 responses corrosponding to items deleted on the
+ server but not yet deleted on the client. HIT means that one of the full
+ hashes matched. MISS means that none of the hashes matched (there was a
+ prefix collision).
+ </summary>
+</histogram>
+
+<histogram name="SB2.GetHashResultDownload" enum="SB2GetHashResult">
+ <summary>
+ Track return status from GetHash requests to server (STATUS_200 and
+ STATUS_204), and dispensation of returned values (EMPTY, HIT, MISS). EMPTY
+ means the response had no full hashes, and should contain all of the 204
+ responses plus those 200 responses corrosponding to items deleted on the
+ server but not yet deleted on the client. HIT means that one of the full
+ hashes matched. MISS means that none of the hashes matched (there was a
+ prefix collision).
+ </summary>
+</histogram>
+
+<histogram name="SB2.GetHashServerMiss">
+ <obsolete>
+ Deprecated in favor of SB2.GetHashResult FULL_HASH_* and
+ SB2.BloomFilterFalsePositives. It is unclear if this histogram ever
+ reported useful data.
+ </obsolete>
+ <summary>
+ The number of GetHash requests returning full hashes that didn't match the
+ URL that initiated the request.
+ </summary>
+</histogram>
+
+<histogram name="SB2.HandleCorrupt">
+ <obsolete>
+ Deprecated, replaced by SB2.DatabaseFailure CORRUPT.
+ </obsolete>
+ <summary>
+ The count of the number of times a database was found corrupt and reset.
+ </summary>
+</histogram>
+
+<histogram name="SB2.InterstitialAction" enum="SB2InterstitialAction">
+ <summary>
+ Track number of times Safe Browsing interstitials have been shown, and how
+ many times they have been clicked through or not.
+ </summary>
+</histogram>
+
+<histogram name="SB2.MalwareInterstitialTimeClosed" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing malware interstitial and the
+ user navigating away by for example, closing the tab, clicking the browser
+ back button or typing another URL in the address bar.
+ </summary>
+</histogram>
+
+<histogram name="SB2.MalwareInterstitialTimeDiagnostic" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing malware interstitial and the
+ user clicking on diagnostic page link.
+ </summary>
+</histogram>
+
+<histogram name="SB2.MalwareInterstitialTimeExpandedSeeMore"
+ units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing malware interstitial and the
+ user expanding the &quot;see more info&quot; section of the page. (Only
+ applies to field trial version 2 of the interstitial.)
+ </summary>
+</histogram>
+
+<histogram name="SB2.MalwareInterstitialTimeLearnMore" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing malware interstitial and the
+ user clicking on the learn more about malware link.
+ </summary>
+</histogram>
+
+<histogram name="SB2.MalwareInterstitialTimePrivacyPolicy" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing malware interstitial and the
+ user clicking on the privacy policy link.
+ </summary>
+</histogram>
+
+<histogram name="SB2.MalwareInterstitialTimeProceed" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing malware interstitial and the
+ user clicking on the proceed link.
+ </summary>
+</histogram>
+
+<histogram name="SB2.MalwareInterstitialTimeTakeMeBack" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing malware interstitial and the
+ user clicking on the big green back button.
+ </summary>
+</histogram>
+
+<histogram name="SB2.Network" units="milliseconds">
+ <summary>
+ The time that it took to receive a response from the Google SafeBrowsing
+ servers for a GetHash request.
+ </summary>
+</histogram>
+
+<histogram name="SB2.OldDatabaseKilobytes" units="KB">
+ <summary>Size of v1 database deleted from client profile.</summary>
+</histogram>
+
+<histogram name="SB2.PhishingInterstitialTimeClosed" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing phishing interstitial and the
+ user navigating away by for example, closing the tab, clicking the browser
+ back button or typing another URL in the address bar.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PhishingInterstitialTimeExpandedSeeMore"
+ units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing phishing interstitial and the
+ user expanding the &quot;see more info&quot; section of the page. (Only
+ applies to field trial version 2 of the interstitial.)
+ </summary>
+</histogram>
+
+<histogram name="SB2.PhishingInterstitialTimeLearnMore" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing phishing interstitial and the
+ user clicking on the learn more link.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PhishingInterstitialTimeProceed" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing phishing interstitial and the
+ user clicking on the proceed link.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PhishingInterstitialTimeReportError" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing phishing interstitial and the
+ user clicking on the report error link.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PhishingInterstitialTimeTakeMeBack" units="milliseconds">
+ <summary>
+ The time between when we show the SafeBrowsing phishing interstitial and the
+ user clicking on the big green back button.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetBitsPerPrefix" units="bits">
+ <summary>
+ The size of the PrefixSet storage in bits, divided by the number of prefixes
+ represented. Should almost always be 16.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetEvent" enum="SB2PrefixSetEvent">
+ <obsolete>
+ Deprecated 9/2012. No longer generated, BloomFilter being removed.
+ </obsolete>
+ <summary>
+ Records how well the PrefixSet implementation matches the BloomFilter
+ implementation.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetKilobytes" units="KB">
+ <summary>The size of the PrefixSet file in kilobytes.</summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetLoad" units="ms">
+ <summary>Time to load the PrefixSet file.</summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetRestoredExcess">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <summary>
+ For debugging PrefixSet. How many extra results GetPrefixes returns.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetRestoredShortfall">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <summary>
+ For debugging PrefixSet. How many fewer results GetPrefixes returns.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetUnsortedDelta">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <summary>
+ For debugging PrefixSet. How far unsorted deltas are from expected value.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetUnsortedDifference">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <summary>
+ For debugging PrefixSet. Distance of unsorted elements from expected
+ location.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetUnsortedPercent">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <summary>
+ For debugging PrefixSet. How far into the results unsorted elements were
+ found. Interesting values would be 0%, 50%, or 100%.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetUnsortedSize">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <summary>
+ For debugging PrefixSet. Size of unsorted sets. To see if there is a
+ problem with a particular size of dataset.
+ </summary>
+</histogram>
+
+<histogram name="SB2.PrefixSetWrite" units="ms">
+ <summary>Time to store the PrefixSet file.</summary>
+</histogram>
+
+<histogram name="SB2.SideEffectFreeWhitelistDatabaseKilobytes" units="KB">
+ <summary>
+ The size of the Side Effect Free Whitelist SaafeBrowsing database file on
+ disk in kilobytes, after an update has occurred.
+ </summary>
+</histogram>
+
+<histogram name="SB2.SideEffectFreeWhitelistPrefixSetKilobytes" units="KB">
+ <summary>
+ The size of the Side Effect Free Whitelist PrefixSet file in kilobytes,
+ after an udpate has occurred.
+ </summary>
+</histogram>
+
+<histogram name="SB2.SideEffectFreeWhitelistPrefixSetLoad" units="ms">
+ <summary>Time to load the Side Effect Free Whitelist PrefixSet file.</summary>
+</histogram>
+
+<histogram name="SB2.SideEffectFreeWhitelistPrefixSetWrite" units="ms">
+ <summary>
+ Time to store the Side Effect Free Whitelist PrefixSet file.
+ </summary>
+</histogram>
+
+<histogram name="SB2.SideEffectFreeWhitelistStatus"
+ enum="SB2SideEffectFreeWhitelistStatus">
+ <summary>The instantiation status of the SideEffectFreeWhitelist.</summary>
+</histogram>
+
+<histogram name="SB2.SubPrefixes">
+ <summary>
+ The number of sub prefixes stored in the database after the last update.
+ </summary>
+</histogram>
+
+<histogram name="SB2.Update" units="milliseconds">
+ <summary>
+ The time from the receipt of the update request to the receipt of the final
+ update chunk.
+ </summary>
+</histogram>
+
+<histogram name="SB2.UpdateRequestSize" units="bytes">
+ <summary>The payload size of update requests to the server.</summary>
+</histogram>
+
+<histogram name="SB2.UpdateResult" enum="SB2UpdateResult">
+ <summary>Result from trying to update the SafeBrowsing data.</summary>
+</histogram>
+
+<histogram name="SB2.UpdateSize" units="bytes">
+ <summary>The size of all the chunk URLs in an update response.</summary>
+</histogram>
+
+<histogram name="SB2.UpdateUrls">
+ <summary>The number of chunk URLs in an update response.</summary>
+</histogram>
+
+<histogram name="SBClientDownload.CheckDownloadStats"
+ enum="SBClientDownloadCheckDownloadStats">
+ <summary>
+ Records a histogram of the reason why downloads are marked as being
+ malicious or clean by the improved SafeBrowsing binary download protection.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.DownloadExtensions"
+ enum="SBClientDownloadExtensions">
+ <summary>
+ Records a histogram of how often users download a file with a file extension
+ that is possibly dangerous (e.g., exe, class).
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.DownloadRequestDuration" units="milliseconds">
+ <summary>
+ Records the total time it takes for the SafeBrowsing download service to
+ check whether the content of a download is malicious or not. This histogram
+ only includes requests that are sent to the SafeBrowsing server.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.DownloadRequestNetError" enum="NetErrorCodes">
+ <summary>
+ The net error code for all CheckClientDownloadRequest URLFetchers.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.DownloadRequestPayloadSize" units="bytes">
+ <summary>
+ The size of the upload data for CheckClientDownloadRequest URLFetchers.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.DownloadRequestResponseCode">
+ <summary>
+ For CheckClientDownloadRequest URLFetchers with successful status, the HTTP
+ response code that was received.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.SignedBinaryDownload"
+ enum="SBClientDownloadIsSignedBinary">
+ <summary>
+ Records the number of signed vs. unsigned executables that are downloaded.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.SignedOrWhitelistedDownload">
+ <summary>
+ Counter which is incremented whenever an executable is downloaded which is
+ either signed or whose URL matches the download whitelist.
+ </summary>
+</histogram>
+
+<histogram name="SBClientMalware.SentReports" enum="SBClientMalwareSentReports">
+ <summary>
+ Measures the success rate of sending malware reports. Sending a report can
+ fail due to a client reaching the limit on the number of reports it can send
+ per day or due to the report failing to be serialized.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.CancelClassificationReason"
+ enum="SBClientPhishingCancelClassificationReason">
+ <summary>
+ The counts for various reasons why an in-progress phishing classification
+ was canceled.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.CheckNoPendingClassificationFailed">
+ <summary>
+ The number of times client-side phishing classifier expected to have no
+ pending classifications running but that check failed.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.ClassificationStart">
+ <summary>
+ The number of pages that we could have possibly classified (essentially the
+ number of top page navigations by users with SBClientPhishing enabled). The
+ name is slightly misleading as it is recorded before
+ &quot;Preclassification&quot; happens.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.ClientModelStatus"
+ enum="SBClientPhishingClientModelStatus">
+ <summary>
+ The counts for various model status codes that we get after loading a new
+ client-side phishing model.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.DOMFeatureChunkTime" units="milliseconds">
+ <summary>
+ The time that an individual chunk of DOM feature extraction work took.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.DOMFeatureFrameRemoved">
+ <summary>
+ The number of times that DOM feature extraction finished early because the
+ active WebDocument's frame was removed during traversal.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.DOMFeatureIterations">
+ <summary>
+ The number of iterations that the DOM feature extractor took to finish.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.DOMFeatureResumeTime" units="milliseconds">
+ <summary>
+ The time that it took to resume DOM feature extraction for the phishing
+ classifier. Longer times may indicate that the page DOM changed between
+ chunks of work and the extractor had to re-traverse up to the saved
+ position.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.DOMFeatureTimeout">
+ <summary>
+ The number of phishing classifications that were aborted because DOM feature
+ extraction took too long.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.DOMFeatureTotalTime" units="milliseconds">
+ <summary>
+ The time that the DOM feature extarctor took to finish, summed across all
+ chunks of work.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.GrabPhishingThumbnail" units="ms">
+ <summary>Time spent generating the thumbnail.</summary>
+</histogram>
+
+<histogram name="SBClientPhishing.IllegalFeatureValue">
+ <summary>
+ The number of features which were omitted from phishing classification
+ because they were added with an illegal value. This would indicate a bug.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.InitPrivateNetworksFailed">
+ <summary>
+ The number of times that the phishing detection service could not be
+ initialized due to an error parsing the private IP networks. This would
+ indicate a bug.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.InvalidWhitelistExpression">
+ <obsolete>
+ Deprecated 12/2011. Whitelist entries are no longer part of
+ ClientPhishingResponse.
+ </obsolete>
+ <summary>
+ The number of whitelist_expression entries in a ClientPhishingResponse that
+ could not be canonicalized.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.PreClassificationCheckFail"
+ enum="SBClientPhishingPreClassificationCheckFail">
+ <summary>
+ Records the number of phishing classifications that were skipped because a
+ pre-classification check failed.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.ReportLimitSkipped">
+ <summary>
+ The number of phishing classifications that were previously cached as being
+ phishing but that will get re-classified (to possibly fix false positives).
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.RequestNotSerialized">
+ <summary>
+ The number of phishing classifier pingbacks that were skipped because
+ serializing the request protocol buffer to string failed.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.RequestSatisfiedFromCache">
+ <summary>
+ The number of times that a cached phishing classification result was used,
+ rather than pinging the server.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.ScorerCreationStatus"
+ enum="SBClientPhishingScorerCreationStatus">
+ <summary>
+ Records the status when we create a scorer object for the client-side
+ phishing detection classifier.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.TermFeatureBreakIterError">
+ <summary>
+ The number of phishing classifications that were aborted because the term
+ feature extractor failed to initialize an ICU break iterator.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.TermFeatureChunkTime" units="milliseconds">
+ <summary>
+ The time that an individual chunk of term feature extraction work took.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.TermFeatureIterations">
+ <summary>
+ The number of iterations that the term feature extractor took to finish.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.TermFeatureTimeout">
+ <summary>
+ The number of phishing classification that were aborted because term feature
+ extraction took too long.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.TermFeatureTotalTime" units="milliseconds">
+ <summary>
+ The time that the term feature extarctor took to finish, summed across all
+ chunks of work.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.TooManyFeatures">
+ <summary>
+ The number of times that the limit on the number of phishing classifier
+ features for a page was reached. This may indicate a bug, or that
+ kMaxFeatureSize is too small.
+ </summary>
+</histogram>
+
+<histogram name="SBClientPhishing.URLFeatureTime" units="milliseconds">
+ <summary>
+ The time taken to extract URL features for the phishing classifier.
+ </summary>
+</histogram>
+
+<histogram name="SBDownloadFeedback.Activations" enum="DownloadItem.DangerType">
+ <summary>
+ Count of times download feedback has been started, broken down by danger
+ type.
+ </summary>
+</histogram>
+
+<histogram name="SBDownloadFeedback.ActiveFeedbacks">
+ <summary>
+ When a new download feedback request is added, records the number of
+ download requests currently active and/or pending.
+ </summary>
+</histogram>
+
+<histogram name="SBDownloadFeedback.Shown" enum="DownloadItem.DangerType">
+ <summary>
+ Count of times download feedback button has been shown, broken down by
+ danger type.
+ </summary>
+</histogram>
+
+<histogram name="SBDownloadFeedback.SizeEligibleKB" units="KB">
+ <summary>
+ Size of downloads that were of the correct danger type, regardless if they
+ meet the max file size check or if they are actually uploaded or not.
+ </summary>
+</histogram>
+
+<histogram name="SBDownloadFeedback.SizeFailure" units="bytes">
+ <summary>
+ Size of downloads that failed to be uploaded to the feedback service.
+ </summary>
+</histogram>
+
+<histogram name="SBDownloadFeedback.SizeSuccess" units="bytes">
+ <summary>
+ Size of downloads that were successfully uploaded to the feedback service.
+ </summary>
+</histogram>
+
+<histogram name="SBDownloadFeedback.UploadResult"
+ enum="SBDownloadFeedbackUploadResult">
+ <summary>
+ Final result of attempt to upload binary to download feedback service.
+ </summary>
+</histogram>
+
+<histogram name="Search.DefaultSearchProvider" enum="OmniboxSearchEngine">
+ <summary>
+ The id of the default search engine that is loaded after Chrome startup. See
+ src/chrome/browser/search_engines/prepopulate_engines.json for more info.
+ </summary>
+</histogram>
+
+<histogram name="Settings.GivenShowHomeButton_HomePageIsNewTabPage"
+ enum="Boolean">
+ <summary>
+ Whether or not the home page user preference is set to the default NTP value
+ when a profile is loaded. This is only logged if the home button is shown.
+ </summary>
+</histogram>
+
+<histogram name="Settings.HomePageIsNewTabPage" enum="Boolean">
+ <obsolete>
+ Deprecated 08/05/2013. Replaced by
+ Settings.GivenShowHomeButton_HomePageIsNewTabPage.
+ </obsolete>
+ <summary>
+ Whether or not the home page user preference is set to the default NTP value
+ when a profile is loaded.
+ </summary>
+</histogram>
+
+<histogram name="Settings.HomePageIsNewTabPage.PulledFromSync" enum="Boolean">
+ <summary>
+ The value of the home-page-is-new-tab-page pref when pulled down from sync
+ to update an out-of-sync local pref store.
+ </summary>
+</histogram>
+
+<histogram name="Settings.HomePageIsNewTabPage.PushedToSync" enum="Boolean">
+ <summary>
+ The value of the home-page-is-new-tab-page pref when pushed up to sync from
+ a change made locally.
+ </summary>
+</histogram>
+
+<histogram name="Settings.ShowHomeButton" enum="BooleanEnabled">
+ <summary>
+ Whether or not the home button is enabled in user preferences when a profile
+ is loaded.
+ </summary>
+</histogram>
+
+<histogram name="Settings.ShowHomeButton.PulledFromSync" enum="BooleanEnabled">
+ <summary>
+ The enabled state of the Home button pref when pulled down from sync to
+ update an out-of-sync local pref store.
+ </summary>
+</histogram>
+
+<histogram name="Settings.ShowHomeButton.PushedToSync" enum="BooleanEnabled">
+ <summary>
+ The enabled state of the Home button pref when pushed up to sync from a
+ change made locally.
+ </summary>
+</histogram>
+
+<histogram name="Settings.StartupPageLoadSettings" enum="SessionStartupPref">
+ <summary>The startup page settings when a profile is loaded.</summary>
+</histogram>
+
+<histogram name="Settings.StartupPageLoadSettings.PulledFromSync"
+ enum="SessionStartupPref">
+ <summary>
+ The startup page setting when pulled down from sync to update an out-of-sync
+ local pref store.
+ </summary>
+</histogram>
+
+<histogram name="Settings.StartupPageLoadSettings.PushedToSync"
+ enum="SessionStartupPref">
+ <summary>
+ The startup page setting when pushed up to sync from a change made locally.
+ </summary>
+</histogram>
+
+<histogram name="Settings.StartupPageLoadURLs">
+ <summary>
+ The number of URLs to be loaded on startup when a profile is loaded, if the
+ startup page setting is set to load URLs.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.CheckCRCResult" enum="CheckCRCResult">
+ <summary>
+ Whether or not the CRC was checked at the moment when the last reference to
+ a read-only entry stream is closed.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.CreationToIndex" units="milliseconds">
+ <summary>
+ The time from the creation of the simple cache backend until the index has
+ been loaded from disk.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.CreationToIndexFail" units="milliseconds">
+ <summary>
+ The time from the creation of the simple cache backend until the index fails
+ to load.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.EntryCreationResult" enum="BooleanSuccess">
+ <summary>
+ For entry creation operations that were sent to the disk, the result of
+ creation.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.EntryCreationTime" units="milliseconds">
+ <summary>The time, in ms, spent creating a new entry on disk.</summary>
+</histogram>
+
+<histogram name="SimpleCache.EntryOperationsPending">
+ <summary>
+ At the time that operations are run, the number of pending operations on a
+ particular entry.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.CacheSizeOnStart" units="bytes">
+ <summary>The size of the cache at the beginning of an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.CacheSizeOnStart2" units="KB">
+ <summary>The size of the cache at the beginning of an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.EntryCount">
+ <summary>The number of entries to be erased in an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.MaxCacheSizeOnStart" units="bytes">
+ <summary>
+ The maximum allowed size of the cache at the beginning of an eviction.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.MaxCacheSizeOnStart2" units="KB">
+ <summary>
+ The maximum allowed size of the cache at the beginning of an eviction.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.Result" enum="BooleanSuccess">
+ <summary>The result of an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.SizeOfEvicted" units="bytes">
+ <summary>The number of bytes to be erased in an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.SizeOfEvicted2" units="KB">
+ <summary>The amount of memory freed in an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.SizeWhenDone" units="bytes">
+ <summary>The size of the cache after running an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.SizeWhenDone2" units="KB">
+ <summary>The size of the cache after running an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.TimeToDone" units="milliseconds">
+ <summary>Time spent completing an eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.Eviction.TimeToSelectEntries" units="milliseconds">
+ <summary>Time spent selecting entries for eviction.</summary>
+</histogram>
+
+<histogram name="SimpleCache.FileDescriptorLimitHard">
+ <summary>
+ The maximum limit of how many file descriptors a process can open. Emitted
+ each time the browser is launched, if the limit could be retrieved. (This
+ is the highest value we could raise the current limit to if we liked.)
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.FileDescriptorLimitSoft">
+ <summary>
+ The current limit of how many file descriptors a process can open. Emitted
+ each time the browser is launched, if the limit could be retrieved. (We can
+ raise this to the maximum limit if we like, without root access.)
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.FileDescriptorLimitStatus"
+ enum="SimpleCache.FileDescriptorLimitStatus">
+ <summary>
+ The result of trying to get the file descriptor limit. Emitted each time
+ the browser is launched.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.GlobalOpenEntryCount">
+ <summary>
+ The number of open entries across all caches backed by the Simple Cache. An
+ entry is opened whenever a caller asks to open it to read or write cache
+ data, and remains open until the last caller asks to close it. Logged
+ whenever an entry is opened or closed.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.HeaderSize" units="bytes">
+ <summary>
+ The size of the header stream of a Simple Cache entry, emitted every time
+ the headers are written or rewritten.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.HeaderSizeChange"
+ enum="SimpleCacheHeaderSizeChange">
+ <summary>
+ How the header size has changed in a Simple Cache entry, emitted every time
+ a write operation occurs on the header stream. (This includes the initial
+ write, rewrites, and other writes that we couldn't classify.)
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.HeaderSizeDecreaseAbsolute" units="bytes">
+ <summary>
+ The absolute size decrease of the header stream of a Simple Cache entry,
+ emitted every time the headers are rewritten with a smaller size.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.HeaderSizeDecreasePercentage" units="percent">
+ <summary>
+ The relative size decrease of the header stream of a Simple Cache entry,
+ emitted every time the headers are rewritten with a smaller size.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.HeaderSizeIncreaseAbsolute" units="bytes">
+ <summary>
+ The absolute size increase of the header stream of a Simple Cache entry,
+ emitted every time the headers are rewritten with a larger size.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.HeaderSizeIncreasePercentage" units="percent">
+ <summary>
+ The relative size increase of the header stream of a Simple Cache entry,
+ emitted every time the headers are rewritten with a larger size.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexCorrupt" enum="BooleanCorrupt">
+ <summary>For each index load, whether the index file was corrupt.</summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexCreatedEntryCount">
+ <summary>The number of entries in a newly created index file.</summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexEntriesLoaded">
+ <summary>Number of entries loaded from the index file on start.</summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexEntriesRestored">
+ <summary>
+ Number of entries restored from disk when there was no index or the index
+ was corrupted.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexFileStateOnLoad" enum="SimpleIndexState">
+ <summary>
+ The state the index file is at when an attempt is made to load from it.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexInitializationWaiters">
+ <summary>
+ At the time of index initialization, the number of enqueued jobs awaiting
+ index initialization.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexInitializeMethod"
+ enum="SimpleCacheIndexInitializeMethod">
+ <summary>The method used to initialize the simple cache index.</summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexLoadTime" units="milliseconds">
+ <summary>
+ Time (as measured on the worker pool) spent loading the index file.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexNumEntriesOnWrite">
+ <summary>The number of entries written to the index on a flush.</summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexRestoreTime" units="milliseconds">
+ <summary>
+ Time (as measured on the worker pool) spent restoring the index file by
+ iterating directory entries.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexStale" enum="BooleanStale">
+ <obsolete>
+ Deprecated 07/2013, and replaced by IndexFileStateOnLoad.
+ </obsolete>
+ <summary>For each index load, whether the index file was stale.</summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexWriteInterval.Background"
+ units="milliseconds">
+ <summary>
+ The interval between index saves, for apps in the background.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexWriteInterval.Foreground"
+ units="milliseconds">
+ <summary>
+ The interval between index saves, for apps in the foreground.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexWriteToDiskTime" units="milliseconds">
+ <obsolete>
+ Deprecated 2013-05 in favour of
+ SimpleCache.SimpleIndexWriteToDiskTime.Background and
+ SimpleCache.SimpleIndexWriteToDiskTime.Foreground.
+ </obsolete>
+ <summary>
+ The amount of time spend writing the index file to disk, measured starting
+ at the beginning of the write on the callback thread, and calculated using
+ the completion time on the worker pool.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexWriteToDiskTime.Background"
+ units="milliseconds">
+ <summary>
+ The amount of time spend writing the index file to disk, for apps in the
+ background, measured starting at the beginning of the write on the callback
+ thread, and calculated using the completion time on the worker pool.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.IndexWriteToDiskTime.Foreground"
+ units="milliseconds">
+ <summary>
+ The amount of time spend writing the index file to disk, for apps in the
+ foreground, measured starting at the beginning of the write on the callback
+ thread, and calculated using the completion time on the worker pool.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.KeyMatchedOnOpen" enum="BooleanMatched">
+ <summary>
+ For each call to OpenEntry, whether the key on disk matched the request key.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.LastClusterLossPercent" units="percent">
+ <summary>
+ For each file in the Simple Cache, the percentage of disk space used by the
+ cluster loss, the unused disk space in the last 4096 byte cluster of the
+ file.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.LastClusterSize" units="bytes">
+ <summary>
+ For each file in the Simple Cache, the number of bytes in the last 4096 byte
+ cluster when the entry is saved to disk.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.OpenEntryIndexState"
+ enum="SimpleCacheOpenEntryIndexState">
+ <summary>
+ At the time that an entry is opened, the state of that entry in the index.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.ReadIsParallelizable"
+ enum="SimpleCacheReadParallelizable">
+ <summary>
+ For each Read operation, whether it could have been issued in parallel of a
+ previous Read operation.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.ReadResult" enum="SimpleCacheReadResult">
+ <summary>The outcome of Entry::ReadData in the simple cache.</summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCheckEOFHasCrc" enum="BooleanHasCrc">
+ <summary>
+ For each EOFRecord found with a valid magic number, indicates if the record
+ also contains a CRC.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCheckEOFResult"
+ enum="SimpleCacheSyncCheckEOFResult">
+ <summary>
+ The result, at the synchronous layer, of checking the EOF record of a cache
+ entry.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCloseResult" enum="SimpleCacheSyncCloseResult">
+ <summary>
+ The result, at the synchronous layer, of closing a cache entry.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCreatePlatformFileError"
+ enum="PlatformFileError">
+ <summary>
+ The platform error reported when attempting to create a new cache entry at
+ the synchronous layer.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCreatePlatformFileError_WithIndex"
+ enum="PlatformFileError">
+ <summary>
+ The platform error reported when attempting to create a new cache entry at
+ the synchronous layer when the index has already initialized.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCreatePlatformFileError_WithoutIndex"
+ enum="PlatformFileError">
+ <summary>
+ The platform error reported when attempting to create a new cache entry at
+ the synchronous layer when the index has not yet initialized.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCreateResult"
+ enum="SimpleCacheSyncCreateResult">
+ <summary>
+ The result, at the synchronous layer, reported when attempting to create a
+ new cache entry.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCreateResult_WithIndex"
+ enum="SimpleCacheSyncCreateResult">
+ <summary>
+ The result, at the synchronous layer, reported when attempting to create a
+ new cache entry when the index has already initialized.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncCreateResult_WithoutIndex"
+ enum="SimpleCacheSyncCreateResult">
+ <summary>
+ The result, at the synchronous layer, reported when attempting to create a
+ new cache entry when the index has not yet initialized.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncOpenPlatformFileError"
+ enum="PlatformFileError">
+ <summary>
+ The platform error reported when attempting to create a new cache entry at
+ the synchronous layer.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncOpenPlatformFileError_WithIndex"
+ enum="PlatformFileError">
+ <summary>
+ The platform error reported when attempting to create a new cache entry at
+ the synchronous layer when the index has already initialized.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncOpenPlatformFileError_WithoutIndex"
+ enum="PlatformFileError">
+ <summary>
+ The platform error reported when attempting to create a new cache entry at
+ the synchronous layer when the index has not initialized.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncOpenResult" enum="SimpleCacheSyncOpenResult">
+ <summary>
+ The result, at the synchronous layer, reported when attempting to open a new
+ cache entry.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncOpenResult_WithIndex"
+ enum="SimpleCacheSyncOpenResult">
+ <summary>
+ The result, at the synchronous layer, reported when attempting to open a new
+ cache entry when the index has already initialized.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncOpenResult_WithoutIndex"
+ enum="SimpleCacheSyncOpenResult">
+ <summary>
+ The result, at the synchronous layer, reported when attempting to open a new
+ cache entry when the index has not yet initialized.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.SyncWriteResult" enum="SimpleCacheSyncWriteResult">
+ <summary>
+ The result, at the synchronous layer, of writing to a cache entry.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.WriteDependencyType"
+ enum="SimpleCacheWriteDependencyType">
+ <summary>
+ Shows whether a write operation depends on the previous operation in queue
+ particularly in the aspect of its possibility to run in parallel.
+ </summary>
+</histogram>
+
+<histogram name="SimpleCache.WriteResult" enum="SimpleCacheWriteResult">
+ <summary>The outcome of Entry::WriteData in the simple cache.</summary>
+</histogram>
+
+<histogram name="SiteIsolation.BrowsingInstanceCount">
+ <summary>
+ The count of all current BrowsingInstances. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.CurrentRendererProcessCount">
+ <summary>
+ The count of all renderer processes, including WebUI and extensions.
+ Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolateAllSitesProcessCountEstimate">
+ <summary>
+ The upper bound of the predicted renderer process count if we isolated all
+ sites, subject to the process limit. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolateAllSitesProcessCountLowerBound">
+ <summary>
+ The lower bound of the predicted renderer process count if we isolated all
+ sites, subject to the process limit. Happens to be the number of unique
+ sites. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolateAllSitesProcessCountNoLimit">
+ <summary>
+ The predicted renderer process count if we isolated all sites and if there
+ were no process limit. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolateAllSitesTotalProcessCountEstimate">
+ <summary>
+ The predicted total process count if we isolated all sites, subject to the
+ process limit. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolateHttpsSitesProcessCountEstimate">
+ <summary>
+ The upper bound of the predicted renderer process count if we isolated only
+ HTTPS (not HTTP) sites, subject to the process limit. Recorded once per UMA
+ ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolateHttpsSitesProcessCountLowerBound">
+ <summary>
+ The lower bound of the predicted renderer process count if we isolated only
+ HTTPS (not HTTP) sites, subject to the process limit. Happens to be the
+ number of isolated sites. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolateHttpsSitesProcessCountNoLimit">
+ <summary>
+ The predicted renderer process count if we isolated only HTTPS (not HTTP)
+ sites and if there were no process limit. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="SiteIsolation.IsolateHttpsSitesTotalProcessCountEstimate">
+ <summary>
+ The predicted total process count if we isolated only HTTPS (not HTTP)
+ sites, subject to the process limit. Recorded once per UMA ping.
+ </summary>
+</histogram>
+
+<histogram name="Sqlite.AppCache.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite for the appcache db.</summary>
+</histogram>
+
+<histogram name="Sqlite.CloseFailure" enum="SqliteErrorCode">
+ <summary>Error which prevented database close.</summary>
+</histogram>
+
+<histogram name="Sqlite.Cookie.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite the cookie db.</summary>
+</histogram>
+
+<histogram name="Sqlite.DatabaseTracker.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite the websqldb tracker db.</summary>
+</histogram>
+
+<histogram name="Sqlite.DomainBoundCerts.Error" enum="SqliteErrorCode">
+ <summary>
+ Error codes returned by sqlite for the domain-bound certs db.
+ </summary>
+</histogram>
+
+<histogram name="Sqlite.DomStorageDatabase.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite for the domstorage db.</summary>
+</histogram>
+
+<histogram name="Sqlite.Error" enum="SqliteErrorCode">
+ <summary>SQLite extended error codes.</summary>
+</histogram>
+
+<histogram name="Sqlite.Error.IOERR" enum="SqliteIOERRCode">
+ <obsolete>
+ Replaced 5/14/2013 by expanded Sqlite.Error histogram.
+ </obsolete>
+ <summary>SQLite extended SQLITE_IOERR codes for all databases.</summary>
+</histogram>
+
+<histogram name="Sqlite.History.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite for the history db.</summary>
+</histogram>
+
+<histogram name="Sqlite.OpenFailure" enum="SqliteErrorCode">
+ <summary>Error which prevented database open.</summary>
+</histogram>
+
+<histogram name="Sqlite.OpenProbeFailure" enum="SqliteErrorCode">
+ <summary>Error from first read of the database.</summary>
+</histogram>
+
+<histogram name="Sqlite.Quota.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite for the quota db.</summary>
+</histogram>
+
+<histogram name="Sqlite.RazeDatabase" enum="SqliteErrorCode">
+ <summary>Errors attempting to Raze() database.</summary>
+</histogram>
+
+<histogram name="Sqlite.RazeDatabase2" enum="SqliteErrorCode">
+ <summary>Errors on second attempt to Raze() database.</summary>
+</histogram>
+
+<histogram name="Sqlite.RazeDatabaseTruncate" enum="SqliteErrorCode">
+ <summary>Errors truncating database for Raze().</summary>
+</histogram>
+
+<histogram name="Sqlite.SizeKB" units="Kb">
+ <summary>Size in kilobytes of pre-existing database at startup.</summary>
+</histogram>
+
+<histogram name="Sqlite.Text.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite the full text db.</summary>
+</histogram>
+
+<histogram name="Sqlite.Thumbnail.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite for the thumbnail db.</summary>
+</histogram>
+
+<histogram name="Sqlite.Version">
+ <summary>Version of pre-existing database at startup.</summary>
+</histogram>
+
+<histogram name="Sqlite.Web.Error" enum="SqliteErrorCode">
+ <summary>Error codes returned by sqlite the web db.</summary>
+</histogram>
+
+<histogram name="Startup.BrowserMessageLoopStartTime">
+ <summary>
+ Time from browser startup to the start of the main thread's message loop.
+ </summary>
+</histogram>
+
+<histogram name="Startup.BrowserMessageLoopStartTimeFromMainEntry"
+ units="milliseconds">
+ <summary>
+ Time from main entry to the start of the main thread's message loop. This
+ stat is only recorded after 7 minutes of OS uptime to try to mitigate the
+ variance resulting from Chrome being autostarted.
+ </summary>
+</histogram>
+
+<histogram name="Startup.BrowserMessageLoopStartTimeFromMainEntry.FirstRun"
+ units="milliseconds">
+ <summary>
+ Time from main entry to the start of the main thread's message loop on first
+ run. This stat is only recorded after 7 minutes of OS uptime to try to
+ mitigate the variance resulting from Chrome being autostarted.
+ </summary>
+</histogram>
+
+<histogram name="Startup.BrowserOpenTabs">
+ <summary>
+ Time taken to open the initial tab or to restore tabs from previous session.
+ </summary>
+</histogram>
+
+<histogram name="Startup.BrowserWindowDisplay" units="milliseconds">
+ <summary>
+ Time from browser startup to the time the browser window initially becomes
+ visible.
+ </summary>
+</histogram>
+
+<histogram name="Startup.ChromeCast.TimeToDisplayVideo" units="milliseconds">
+ <summary>
+ The elapsed time from the ChromeCast application launch to the first video
+ frame displayed.
+ </summary>
+</histogram>
+
+<histogram name="Startup.Fling.TimeToDisplayVideo" units="milliseconds">
+ <summary>
+ The elapsed time from the Fling application launch to the first video frame
+ displayed.
+ </summary>
+</histogram>
+
+<histogram name="Startup.IsResume">
+ <obsolete>
+ Deprecated 12/2011. Merged into MobileSessionStartType.
+ </obsolete>
+ <summary>Whether a startup is a resume (vs a cold start).</summary>
+</histogram>
+
+<histogram name="Startup.MobileSessionStartAction"
+ enum="MobileSessionStartAction">
+ <summary>
+ The action requested on the application startup when called from another app
+ or the OS.
+ </summary>
+</histogram>
+
+<histogram name="Startup.MobileSessionStartFromApps"
+ enum="MobileSessionCallerApp">
+ <summary>The calling application (if any).</summary>
+</histogram>
+
+<histogram name="Startup.ShowAppListColdStart" units="milliseconds">
+ <summary>
+ Time for a newly created browser process to reach the code that starts
+ showing the app launcher, when started with the --show-app-list flag and
+ with no currently running Chrome processes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.ShowAppListWarmStart" units="milliseconds">
+ <summary>
+ Time for a running browser process to reach the code that starts showing the
+ app launcher. Measured from the time a second Chrome process started, which
+ sent its --show-app-list command line argument to the already-running
+ process and will soon exit.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupBookmarksLoad" units="milliseconds">
+ <summary>
+ Time it takes to load bookmarks from disk. This measurement is only sent for
+ startups that take &gt;10 seconds after an uptime of 7 minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupExtensionServiceInitAfterImport"
+ units="milliseconds">
+ <summary>
+ Time it takes to finish initialization of the extension service including
+ loading built-in extensions. This measurement is only sent for startups that
+ take &gt;10 seconds after an uptime of 7 minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupFinalProfileInit" units="milliseconds">
+ <summary>
+ Time the final stages of profile initialization taking including
+ initialization of profile keyed services. This measurement is only sent for
+ startups that take &gt;10 seconds after an uptime of 7 minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupNSSInit" units="milliseconds">
+ <summary>
+ Time it takes to load the NSS libraries and initialize it. This measurement
+ is only sent for startups that take &gt;10 seconds after an uptime of 7
+ minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupPreferenceLoading" units="milliseconds">
+ <summary>
+ Time it takes to load preferences from disk. This measurement is only sent
+ for startups that take &gt;10 seconds after an uptime of 7 minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupProfileIODataInit" units="milliseconds">
+ <summary>
+ Time it takes to initialize the ProfileIOData object - this includes
+ initialization of the cookie store. This measurement is only sent for
+ startups that take &gt;10 seconds after an uptime of 7 minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupSafeBrowsingGetDatabase"
+ units="milliseconds">
+ <summary>
+ Time it takes to load the safe browsing database from disk. This measurement
+ is only sent for startups that take &gt;10 seconds after an uptime of 7
+ minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupSafeBrowsingServiceInitialize"
+ units="milliseconds">
+ <summary>
+ Time it takes to initialize the safe browsing service. This measurement is
+ only sent for startups that take &gt;10 seconds after an uptime of 7
+ minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.SlowStartupSessionServiceCreateTabsAndWindows"
+ units="milliseconds">
+ <summary>
+ Time it takes for session restore to finish initiating creation of restored
+ tabs and windows. This measurement is only sent for startups that take
+ &gt;10 seconds after an uptime of 7 minutes.
+ </summary>
+</histogram>
+
+<histogram name="Startup.WarmStartTimeFromRemoteProcessStart"
+ units="milliseconds">
+ <summary>
+ Time for a running browser process to start processing the command line
+ passed in by a second Chrome process, which just sent its command line
+ arguments to the already-running process and will soon exit. Measured from
+ the time the second Chrome process started.
+ </summary>
+</histogram>
+
+<histogram name="Sync.AuthInvalidationRejectedTokenAgeLong" units="days">
+ <summary>
+ Age of all auth tokens rejected by the invalidation server. Measured from
+ the time they were created.
+ </summary>
+</histogram>
+
+<histogram name="Sync.AuthInvalidationRejectedTokenAgeShort"
+ units="milliseconds">
+ <summary>
+ Age of auth tokens younger than one hour that were rejected by the
+ invalidation server. Measured from the time they were created.
+ </summary>
+</histogram>
+
+<histogram name="Sync.AuthServerRejectedTokenAgeLong" units="days">
+ <summary>
+ Age of all auth tokens rejected by the sync server. Measured from the time
+ they were created.
+ </summary>
+</histogram>
+
+<histogram name="Sync.AuthServerRejectedTokenAgeShort" units="milliseconds">
+ <summary>
+ Age of auth tokens younger than one hour that were rejected by the sync
+ server. Measured from the time they were created.
+ </summary>
+</histogram>
+
+<histogram name="Sync.RefreshTokenAvailable" enum="BooleanSuccess">
+ <summary>
+ Whether OAuth2 refresh token was available at the time when
+ ProfileSyncService was starting backend.
+ </summary>
+</histogram>
+
+<histogram name="Tab.AgeUponRestoreFromColdStart" units="minutes">
+ <summary>
+ Age (time since the last display in previous sessions) of a tab being
+ restored due to the first tab switch after the browser cold start, recorded
+ upon such restore. When the browser is started from cold, this metric is not
+ recorded for the foreground, automatically restored tab, so that the metric
+ tracks only the restores triggered by direct user decision to switch tabs.
+ </summary>
+</histogram>
+
+<histogram name="Tab.RestoreResult" enum="BooleanSuccess">
+ <summary>
+ When the browser restores a tab, whether the load was successful. Loads can
+ fail for instance when there is no connectivity.
+ </summary>
+</histogram>
+
+<histogram name="Tab.RestoreTime" units="ms">
+ <summary>Load time for a successful tab restore.</summary>
+</histogram>
+
+<histogram name="Tab.RestoreUserPersistence" enum="TabRestoreUserAction">
+ <summary>
+ When the browser restores a tab, whether the user waits for completion of
+ the load or if the user gives up by switching to another tab or leaving
+ Chrome.
+ </summary>
+</histogram>
+
+<histogram name="Tab.StatusWhenDisplayed" enum="TabStatus">
+ <summary>
+ The status of a tab collected each time the tab is displayed on Android,
+ including user switching to the tab and displays of newly created tabs, such
+ as NTP or tabs opened to handle intents.
+ </summary>
+</histogram>
+
+<histogram name="Tab.StatusWhenSwitchedBackToForeground" enum="TabStatus">
+ <summary>
+ The status of a tab collected each time the user switches to it on Android.
+ That does not include tabs being created at the time the user switches to
+ them, such as NTP or tabs opened to handle intents.
+ </summary>
+</histogram>
+
+<histogram name="Tab.SwitchedToForegroundAge" units="ms">
+ <summary>Age (in ms) when the tab was switched to foreground.</summary>
+</histogram>
+
+<histogram name="Tab.SwitchedToForegroundLaunchedWithURL"
+ enum="TabSwitchedToForegroundLaunchedWithURL">
+ <summary>
+ Each time a tab is brought to the foreground, this histogram indicates if
+ chrome was launched without an URL (i.e., from the launcher), or with an URL
+ (i.e., from another app).
+ </summary>
+</histogram>
+
+<histogram name="Tab.SwitchedToForegroundMRURank">
+ <summary>
+ Rank in MRU order (0 being first) when the tab was switched to foreground.
+ </summary>
+</histogram>
+
+<histogram name="Tab.SwitchedToForegroundNumTabs">
+ <summary>Count of all tabs when a tab is switched.</summary>
+</histogram>
+
+<histogram name="Tab.SwitchedToForegroundRevisit"
+ enum="TabSwitchedToForegroundRevisit">
+ <summary>
+ Each time a tab is brought to the foreground, this histogram indicates if
+ this is the first viewing of the tab since Chrome was put into foreground,
+ or if it was a return to a tab that has already been shown in this session.
+ </summary>
+</histogram>
+
+<histogram name="Tabs.ForegroundTabAgeAtStartup" units="minutes">
+ <summary>
+ Age (time since the last display in previous sessions) of the foreground tab
+ being restored on the browser cold start.
+ </summary>
+</histogram>
+
+<histogram name="Touchpad.Device" enum="TouchpadDeviceState">
+ <summary>Tracks touchpad device state.</summary>
+</histogram>
+
+<histogram name="Touchpad.Metrics" enum="TouchpadProblemType">
+ <summary>
+ Tracks unusual CrOS touchpad operational states (e.g. running into the noisy
+ ground issue). This is sampled at every touchpad event.
+ </summary>
+</histogram>
+
+<histogram name="Touchpad.NaturalScroll.Changed" enum="BooleanEnabled">
+ <summary>Tracks touchpad natural scroll setting changes by the user.</summary>
+</histogram>
+
+<histogram name="Touchpad.NaturalScroll.Started" enum="BooleanEnabled">
+ <summary>Tracks touchpad natural scroll setting on startup.</summary>
+</histogram>
+
+<histogram name="Touchpad.PointerSensitivity.Changed" enum="PointerSensitivity">
+ <summary>
+ Tracks touchpad sensitivity setting changes by the user. This replaces the
+ old Touchpad.Sensitivity.Changed metric.
+ </summary>
+</histogram>
+
+<histogram name="Touchpad.PointerSensitivity.Started" enum="PointerSensitivity">
+ <summary>
+ Tracks touchpad sensitivity setting on startup. This replaces the old
+ Touchpad.Sensitivity.Started metric.
+ </summary>
+</histogram>
+
+<histogram name="Touchpad.Sensitivity.Changed" enum="PointerSensitivity">
+ <obsolete>
+ Deprecated as of 6/2013, replaced by Touchpad.PointerSensitivity.Changed.
+ </obsolete>
+ <summary>Tracks touchpad sensitivity setting changes by the user.</summary>
+</histogram>
+
+<histogram name="Touchpad.Sensitivity.Started" enum="PointerSensitivity">
+ <obsolete>
+ Deprecated as of 6/2013, replaced by Touchpad.PointerSensitivity.Started.
+ </obsolete>
+ <summary>Tracks touchpad sensitivity setting on startup.</summary>
+</histogram>
+
+<histogram name="Touchpad.TapDragging.Changed" enum="BooleanEnabled">
+ <summary>Tracks touchpad TapDragging setting changes by the user.</summary>
+</histogram>
+
+<histogram name="Touchpad.TapDragging.Started" enum="BooleanEnabled">
+ <summary>Tracks touchpad TapDragging setting on startup.</summary>
+</histogram>
+
+<histogram name="Touchpad.TapToClick.Changed" enum="BooleanEnabled">
+ <summary>Tracks touchpad TapToClick setting changes by the user.</summary>
+</histogram>
+
+<histogram name="Touchpad.TapToClick.Started" enum="BooleanEnabled">
+ <summary>Tracks touchpad TapToClick setting on startup.</summary>
+</histogram>
+
+<histogram name="Touchpad.ThreeFingerSwipe.Changed" enum="BooleanEnabled">
+ <obsolete>
+ Deprecated as of 7/2013.
+ </obsolete>
+</histogram>
+
+<histogram name="Touchpad.ThreeFingerSwipe.Started" enum="BooleanEnabled">
+ <obsolete>
+ Deprecated as of 7/2013.
+ </obsolete>
+</histogram>
+
+<histogram name="Translate.AlwaysTranslateLang">
+ <summary>
+ The number of times the always translate option was selected in the
+ translate infobar.
+ </summary>
+</histogram>
+
+<histogram name="Translate.CaptureText" units="milliseconds">
+ <summary>
+ The time spent capturing plain text from the DOM. This is reported by
+ ChromeRenderViewObserver when a page is loaded completely.
+ </summary>
+</histogram>
+
+<histogram name="Translate.ContentLanguage" enum="TranslateLanguage">
+ <summary>
+ A page may provide a Content-Language HTTP header or a META tag. For each
+ page load, measures whether the Content-Language header exists and is valid.
+ </summary>
+</histogram>
+
+<histogram name="Translate.DeclineTranslate">
+ <summary>
+ The number of times the &quot;Nope&quot; (don't translate) was clicked in
+ the translate infobar.
+ </summary>
+</histogram>
+
+<histogram name="Translate.DeclineTranslateCloseInfobar">
+ <summary>
+ The number of times the translate infobar was closed without the user
+ translating the page.
+ </summary>
+</histogram>
+
+<histogram name="Translate.HtmlLang" enum="TranslateLanguage">
+ <summary>
+ A page may provide a lang attribute in html tag. For each page load,
+ measures whether the lang attribute exists and is valid.
+ </summary>
+</histogram>
+
+<histogram name="Translate.InitiationStatus" enum="TranslateInitiationStatus">
+ <summary>
+ The reason why Chrome decided to perform the next action (e.g., to show
+ infobar, to translate a page without any prompting, and so on) when Chrome
+ Translate is ready to translate a page.
+ </summary>
+</histogram>
+
+<histogram name="Translate.LanguageVerification"
+ enum="TranslateLanguageVerification">
+ <summary>
+ For each page load, measures whether the provided Content-Language header
+ matches the language determined by CLD. Beyond directly matching or
+ mismatching the Content-Language header, CLD can complement the
+ Content-Language. For example, suppose the Content-Language header
+ specifies 'zh' (general Chinese), a language code that the Translate server
+ does not support. In this case, CLD can detect a subcode like '-TW' or
+ '-CN', resulting in language codes 'zh-TW' and 'zh-CN', which the Translate
+ server supports. This is referred to as &quot;complementing a language
+ subcode&quot;.
+ </summary>
+</histogram>
+
+<histogram name="Translate.LocalesOnDisabledByPrefs" enum="LanguageCode">
+ <summary>
+ Logs the user locale when the Translate feature is disabled by the user.
+ This is recorded each time a webpage is loaded and prefs for translation is
+ checked. This allows us to investigate the correlation between the user
+ locale and the usage rates of the Translate.
+ </summary>
+</histogram>
+
+<histogram name="Translate.ModifyOriginalLang">
+ <summary>
+ The number of times the original language in the translate infobar has been
+ changed.
+ </summary>
+</histogram>
+
+<histogram name="Translate.ModifyTargetLang">
+ <summary>
+ The number of times the target language in the translate infobar has been
+ changed.
+ </summary>
+</histogram>
+
+<histogram name="Translate.NeverTranslateLang">
+ <summary>
+ The number of times the never translate option was selected in the translate
+ infobar.
+ </summary>
+</histogram>
+
+<histogram name="Translate.NeverTranslateSite">
+ <summary>
+ The number of times the never translate site was selected in the translate
+ infobar.
+ </summary>
+</histogram>
+
+<histogram name="Translate.PageScheme" enum="TranslateScheme">
+ <summary>Counts translation target page schemes.</summary>
+</histogram>
+
+<histogram name="Translate.ReportLanguageDetectionError">
+ <summary>
+ The number of times the &quot;report this error&quot; of options menu is
+ selected in the translate infobar.
+ </summary>
+</histogram>
+
+<histogram name="Translate.RevertTranslation">
+ <summary>
+ The number of times the show original button was clicked in the translate
+ infobar.
+ </summary>
+</histogram>
+
+<histogram name="Translate.ServerReportedUnsupportedLanguage">
+ <obsolete>
+ Deprecated 5/2013 by Translate.UndisplayableLanguage
+ </obsolete>
+ <summary>
+ The number of times the detected language is not supported by Translate
+ Element.
+ </summary>
+</histogram>
+
+<histogram name="Translate.ShowBeforeTranslateInfobar">
+ <obsolete>
+ Deprecated 7/2010. No longer tracked.
+ </obsolete>
+ <summary>
+ The number of times an infobar proposing to translate a page has been shown.
+ </summary>
+</histogram>
+
+<histogram name="Translate.ShowErrorInfobar" enum="TranslateError">
+ <summary>
+ Chrome Translate shows an error infobar when an error happens on translation
+ and the infobar message depends on what kind of error happens. This metric
+ counts how often each error message is shown.
+ </summary>
+</histogram>
+
+<histogram name="Translate.SimilarLanguageMatch" enum="BooleanMatched">
+ <summary>
+ This metrics is logged whenever a page is loaded. The logged value is
+ &quot;Mathced&quot; when the CLD-detected language differs from the page
+ language code , and the two languages are such similar languages. In that
+ case, Chrome ignore the CLD-determined language and instead uses the page
+ language code. The page language code is decided by Content-Language and
+ HTML lang attribute.
+ </summary>
+</histogram>
+
+<histogram name="Translate.TimeToBeReady" units="milliseconds">
+ <summary>
+ The time from injecting scripts for Chrome Translate to being ready to
+ perform translation.
+ </summary>
+</histogram>
+
+<histogram name="Translate.TimeToLoad" units="milliseconds">
+ <summary>
+ The time from injecting scripts for Chrome Translate to the finishing loads
+ of all depending libraries.
+ </summary>
+</histogram>
+
+<histogram name="Translate.TimeToTranslate" units="milliseconds">
+ <summary>The time from starting translation to the completion.</summary>
+</histogram>
+
+<histogram name="Translate.Translate">
+ <summary>
+ The number of times the translate button was clicked in the translate
+ infobar.
+ </summary>
+</histogram>
+
+<histogram name="Translate.UndisplayableLanguage" enum="LanguageCode">
+ <summary>
+ Logs an undisplayable language included in the language list sent by the
+ Translate server. The Translate server sends the list each time the user
+ runs Chrome. This metrics tells us that there is a language which UI should
+ support but doesn't.
+ </summary>
+</histogram>
+
+<histogram name="Translate.UnsupportedLanguageAtInitiation" enum="LanguageCode">
+ <summary>
+ Logs an unsupported source language detected during initiation of the
+ Translate feature. This is reported when the language detector successfully
+ detects the language of the webpage, but the language is not supported by
+ the translation server because it is too minor. This metric allows us to
+ assess how important the unsupported language is for Google translate.
+ </summary>
+</histogram>
+
+<histogram name="Translate.UserActionDuration" units="milliseconds">
+ <summary>
+ The time from a page content language being determined to user requesting
+ Chrome Translate.
+ </summary>
+</histogram>
+
+<histogram name="TryScroll.SlowScroll" enum="ScrollThread">
+ <summary>Whether the scroll is executed on main thread.</summary>
+</histogram>
+
+<histogram name="UMA.CollectExternalEventsTime" units="milliseconds">
+ <summary>
+ The time to run the external metrics collection task (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="UMA.Discarded Log Events">
+ <summary>
+ The number of events discarded at log transmission time because the event
+ count was already too large.
+ </summary>
+</histogram>
+
+<histogram name="UMA.FieldTrialsEnabledBenchmarking" enum="BooleanUsage">
+ <summary>
+ Log whether the --enable-benchmarking flag was set, which causes field
+ trials to only use the default group.
+ </summary>
+</histogram>
+
+<histogram name="UMA.GeneratedLowEntropySource" enum="BooleanSuccess">
+ <summary>
+ For each attempt to generate the low entropy source, log whether or not the
+ load required generating a new low entropy source.
+ </summary>
+</histogram>
+
+<histogram name="UMA.Large Accumulated Log Not Persisted" units="bytes">
+ <summary>
+ Number of bytes in an excessively large log that was discarded at shutdown
+ instead of being saved to disk to retry during next chrome run.
+ </summary>
+</histogram>
+
+<histogram name="UMA.Large Rejected Log was Discarded" units="bytes">
+ <summary>
+ Number of bytes in a log was was rejected by server, and then discarded.
+ </summary>
+</histogram>
+
+<histogram name="UMA.LogLoadComplete called">
+ <summary>
+ Simple counter of the number of times LogLoadComplete was called (bug
+ demonstration, as we're called more often than once per page load :-/ )
+ </summary>
+</histogram>
+
+<histogram name="UMA.LowEntropySourceValue">
+ <summary>
+ Distribution of the low entropy source value used for field trial
+ randomization, recorded on startup.
+ </summary>
+</histogram>
+
+<histogram name="UMA.Perf.GetData" enum="GetPerfDataOutcome">
+ <summary>
+ A count of successes and various failure modes related to collecting and
+ processing performance data obtained through &quot;perf&quot; on ChromeOS.
+ </summary>
+</histogram>
+
+<histogram name="UMA.ProtoCompressionRatio" units="%">
+ <summary>
+ Compression ratio of the serialized protobuf that will be uploaded to the
+ UMA server. This serialized protobuf is compressed using gzip.
+ </summary>
+</histogram>
+
+<histogram name="UMA.ProtoGzipped" enum="Boolean">
+ <summary>Was the UMA protobuf uploaded earlier compressed or not.</summary>
+</histogram>
+
+<histogram name="UMA.ProtoGzippedKBSaved" units="KB">
+ <summary>
+ Kilobytes saved from gzipping the protobufs before uploading them.
+ </summary>
+</histogram>
+
+<histogram name="UMA.Unacceptable_Log_Discarded">
+ <obsolete>
+ Deprecated as of May, 2012 (i.e. Chrome 21+). Replaced by the
+ UMA.UploadResponseStatus.XML and UMA.UploadResponseStatus.Protobuf
+ histograms.
+ </obsolete>
+ <summary>The server returned a 400 code, and we discarded a log.</summary>
+ <details>
+ This tends to indicate that a syntax error is present in a log, such as
+ would appear when a bogus XML tag is included, or the XML is not balanced
+ and well structured.
+ </details>
+</histogram>
+
+<histogram name="UMA.UploadCreation" enum="BooleanSuccess">
+ <summary>
+ For each attempted UMA upload, log whether the upload was successfully
+ constructed. An upload might fail to be constructed, for example, if we try
+ to upload before the system is fully initialized; or if serialization of the
+ data fails.
+ </summary>
+</histogram>
+
+<histogram name="UMA.UploadResponseStatus.Protobuf"
+ enum="UmaUploadResponseStatus">
+ <summary>
+ For each upload to the protocol buffer (v2) UMA server, log whether the
+ upload was successful, or whether there was an error.
+ </summary>
+</histogram>
+
+<histogram name="UMA.UploadResponseStatus.XML" enum="UmaUploadResponseStatus">
+ <summary>
+ For each upload to the XML (v1) UMA server, log whether the upload was
+ successful, or whether there was an error.
+ </summary>
+</histogram>
+
+<histogram name="UMA.UsedResetVariationsFlag" enum="BooleanUsage">
+ <summary>
+ Log whether the --reset-variation-state flag was set before the low entropy
+ source was requested.
+ </summary>
+</histogram>
+
+<histogram name="UMA.XMLNodeDumpTime" units="milliseconds">
+ <summary>
+ The time spent in converting the XML tree into a character buffer when
+ closing a metrics log (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="UMA.XMLWriterDestructionTime" units="milliseconds">
+ <summary>
+ The time spent in freeing the XML writer and tree when closing a metrics log
+ (Chrome OS).
+ </summary>
+</histogram>
+
+<histogram name="UserManager.LoginUserType" enum="UserType">
+ <summary>
+ The number of users of different types that log in to the system (Chrome
+ OS).
+ </summary>
+</histogram>
+
+<histogram name="UserManager.LogoutToLoginDelay" units="seconds">
+ <summary>
+ The time between one regular user logging out and a different regular user
+ logging in (Chrome OS). Delays above thirty minutes or which span system
+ reboots or non-regular-user logins are not reported.
+ </summary>
+</histogram>
+
+<histogram name="Variations.DisabledNoEntropyProvider" enum="BooleanHit">
+ <obsolete>
+ Deprecated 1/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ A count of the number of times we hit the code where a field trial is
+ disabled because no entropy provider was provided.
+ </summary>
+</histogram>
+
+<histogram name="Variations.FailedRequestErrorCode" enum="NetErrorCodes">
+ <summary>
+ The counts of network error codes encountered by VariationsService when an
+ attempt to fetch a variations seed from the server fails.
+ </summary>
+</histogram>
+
+<histogram name="Variations.FetchNotModifiedLatency" units="milliseconds">
+ <summary>
+ The latency of a VariationsService seed fetch that results in a not modified
+ response.
+ </summary>
+</histogram>
+
+<histogram name="Variations.FetchOtherLatency" units="milliseconds">
+ <summary>
+ The latency of a VariationsService seed fetch that results in neither a
+ success nor not modified response.
+ </summary>
+</histogram>
+
+<histogram name="Variations.FetchSuccessLatency" units="milliseconds">
+ <summary>
+ The latency of a VariationsService seed fetch that results in a success
+ response.
+ </summary>
+</histogram>
+
+<histogram name="Variations.HeaderConstructionTime" units="microseconds">
+ <summary>How long it took to create the X-Chrome-Variations header.</summary>
+</histogram>
+
+<histogram name="Variations.NetworkAvailability" enum="BooleanSuccess">
+ <obsolete>
+ Deprecated 9/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ Whether or not the network was available when requested by the
+ VariationsService.
+ </summary>
+</histogram>
+
+<histogram name="Variations.ResourceRequestsAllowed"
+ enum="VariationsResourceRequestsAllowedState">
+ <summary>
+ Counts the number of times the VariationsService is allowed or not allowed
+ to make a request due to the ResourceRequestAllowedNotifier.
+ </summary>
+</histogram>
+
+<histogram name="Variations.SeedEmpty" enum="VariationsSeedEmpty">
+ <summary>
+ Records whether the variations seed in local state is empty (does not exist)
+ on startup.
+ </summary>
+</histogram>
+
+<histogram name="Variations.SeedFetchResponseCode">
+ <summary>
+ The counts of HTTP response codes encountered by VariationsService when
+ attempting to fetch a variations seed from the server.
+ </summary>
+</histogram>
+
+<histogram name="Variations.SeedFreshness" units="minutes">
+ <summary>
+ The time interval between when the Variations seed was last downloaded and
+ when it was used.
+ </summary>
+</histogram>
+
+<histogram name="Variations.ServerStudyExpiredUniformity1Percent"
+ enum="BooleanExpired">
+ <obsolete>
+ Deprecated 11/2012. No longer tracked.
+ </obsolete>
+ <summary>
+ Whether or not the 1-Percent uniformity trial from the Variations server was
+ expired when loaded.
+ </summary>
+</histogram>
+
+<histogram name="Variations.TimeSinceLastFetchAttempt" units="minutes">
+ <summary>
+ The time since the previous attempt to fetch the variations seed within the
+ same session, with 0 indicating that this is the first attempt. Recorded
+ when a variations seed fetch is attempted by the VariationsService.
+ </summary>
+</histogram>
+
+<histogram name="Variations.UniformityTrialExpired" enum="BooleanHit">
+ <obsolete>
+ Deprecated 1/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ A count of the number of times we hit the code where the
+ UMA-Uniformity-Trial-1-Percent field trial is disabled as a result of the
+ expiration check.
+ </summary>
+</histogram>
+
+<histogram name="Variations.UniformityTrialGroupNotActive"
+ enum="UniformityTrialGroupNotActive">
+ <obsolete>
+ Deprecated 1/2013. No longer tracked.
+ </obsolete>
+ <summary>
+ Tracks whether the UMA-Uniformity-Trial-1-Percent field trial was not active
+ and which factors contributed to it.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.AcceptLegalDocuments" units="ms">
+ <summary>
+ Measures the time taken by Google Online Wallet server's accept legal
+ document API call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.AuthenticateInstrument" units="ms">
+ <summary>
+ Measures the time taken by Google Online Wallet server's authenticate
+ instrument API call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.GetFullWallet" units="ms">
+ <summary>
+ Measures the time taken by Google Online Wallet server's get full wallet API
+ call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.GetWalletItems" units="ms">
+ <summary>
+ Measures the time taken by Google Online Wallet server's get wallet items
+ API call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.SaveAddress" units="ms">
+ <obsolete>
+ Deprecated as of 7/2013, replaced by Wallet.ApiCallDuration.SaveToWallet.
+ </obsolete>
+ <summary>
+ Measures the time taken by Google Online Wallet server's save address API
+ call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.SaveInstrument" units="ms">
+ <obsolete>
+ Deprecated as of 7/2013, replaced by Wallet.ApiCallDuration.SaveToWallet.
+ </obsolete>
+ <summary>
+ Measures the time taken by Google Online Wallet server's save instrument API
+ call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.SaveInstrumentAndAddress" units="ms">
+ <obsolete>
+ Deprecated as of 7/2013, replaced by Wallet.ApiCallDuration.SaveToWallet.
+ </obsolete>
+ <summary>
+ Measures the time taken by Google Online Wallet server's save instument and
+ address API call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.SaveToWallet" units="ms">
+ <summary>
+ Measures the time taken by Google Online Wallet server's save to wallet API
+ call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.SendStatus" units="ms">
+ <summary>
+ Measures the time taken by Google Online Wallet server's send status API
+ call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.UnknownApiCall" units="ms">
+ <summary>
+ Measures the time taken by Google Online Wallet server's unknown API calls.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.UpdateAddress" units="ms">
+ <obsolete>
+ Deprecated as of 7/2013, replaced by Wallet.ApiCallDuration.SaveToWallet.
+ </obsolete>
+ <summary>
+ Measures the time taken by Google Online Wallet server's update address API
+ call.
+ </summary>
+</histogram>
+
+<histogram name="Wallet.ApiCallDuration.UpdateInstrument" units="ms">
+ <obsolete>
+ Deprecated as of 7/2013, replaced by Wallet.ApiCallDuration.SaveToWallet.
+ </obsolete>
+ <summary>
+ Measures the time taken by Google Online Wallet server's update instument
+ API call.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.Animation.CSSProperties" enum="MappedCSSProperties">
+ <summary>
+ Counts the number of times each CSS property is animated. There is no limit
+ on the number of times each property is counted per page view -- a property
+ that is animated multiple times during a single page view is counted each
+ time it animates.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.FeatureObserver" enum="FeatureObserver">
+ <summary>
+ Count of how many instances of WebCore::Page use various features. Each
+ WebCore::Page instance has a WebCore::UseCounter instance. It records and
+ reports feature usage (e.g. via UseCounter::count() method).
+ </summary>
+</histogram>
+
+<histogram name="WebCore.FeatureObserver.CSSProperties"
+ enum="MappedCSSProperties">
+ <summary>
+ Records usage of CSS properties used on a page, either statically or
+ dynamically, from the time the page is initialised to when it is closed or
+ navigated away from. Each property is counted at most once per page per
+ view.
+ </summary>
+ <details>
+ Every time a CSS property is parsed on a page, that property is recorded as
+ having been used. The histogram is updated with this data whenever a page is
+ closed, or a page navigation happens. Each histogram bucket corresponds to a
+ CSS property (eg width, border-radius). The exception is the bucket numbered
+ '1' - this counts the number of pages that CSS properties were counted on.
+
+ These numbers give the percentage of pages that use a CSS property. For
+ example, if the 'border-radius' histogram bucket has a count of 250, and the
+ page count bucket (i.e. bucket number 1) has a count of 1000 - this means
+ that 1000 pages were recorded, and border-radius was used on 25% of those
+ pages.
+
+ Internally, each WebCore::Page has a WebCore::UseCounter instance, with
+ booleans recording use of each CSS property - one boolean per property. Upon
+ destruction of the WebCore::Page (e.g. by the user closing the tab), or a
+ page navigation happening, the histogram is updated. For each boolean that
+ is set to True, the corresponding histogram bucket for that CSS property is
+ incremented by 1. The page count bucket (i.e. bucket number 1) is always
+ incremented by 1 on each histogram update.
+ </details>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.BackingStore.ConsistencyError"
+ enum="IDBLevelDBBackingStoreInternalErrorType">
+ <summary>
+ Methods that encountered consistency errors. Such errors probably point to a
+ bug in our code.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.BackingStore.InternalError"
+ enum="IDBLevelDBBackingStoreInternalErrorType">
+ <obsolete>
+ As of chrome 26, use {Consistency, Read, Write}Error instead.
+ </obsolete>
+ <summary>
+ Count of internal IndexedDB errors (data corruption, I/O errors, etc)
+ encountered.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.BackingStore.OpenStatus"
+ enum="IDBLevelDBBackingStoreOpenResult">
+ <summary>
+ Count of the different success and failure modes when opening an IndexedDB
+ backing store - clean open, successful open with recovery, failed recovery,
+ etc.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.BackingStore.ReadError"
+ enum="IDBLevelDBBackingStoreInternalErrorType">
+ <summary>
+ Methods that encountered leveldb errors while trying to read from disk.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.BackingStore.WriteError"
+ enum="IDBLevelDBBackingStoreInternalErrorType">
+ <summary>
+ Methods that encountered leveldb errors while trying to write to disk.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.FrontEndAPICalls"
+ enum="IndexedDatabaseMethods">
+ <summary>
+ Count total number of front end API calls of IndexedDB methods.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDB.FreeDiskSpaceFailure"
+ enum="LevelDBErrorCount">
+ <summary>
+ Count of how many times LevelDBDatabase got an error trying to check free
+ disk space.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDB.OpenFailureFreeDiskSpace" units="Kb">
+ <summary>
+ Amount of free disk space on the partition/volume/etc where LevelDB failed
+ to open.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDB.OpenSuccessFreeDiskSpace" units="Kb">
+ <summary>
+ Amount of free disk space on the partition/volume/etc where LevelDB was
+ successfully opened.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBOpenErrors" enum="LevelDBErrorTypes">
+ <summary>
+ Error classes returned by LevelDB when it failed to open a database.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBOpenErrors.Corruption"
+ enum="LevelDBCorruptionTypes">
+ Types of corruption that LevelDB encounters when opening a database.
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBOpenErrors.EnvMethod"
+ enum="LevelDBIOErrorMethods">
+ <summary>
+ LevelDBEnv methods that generated IO errors when opening a database.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBOpenErrors.Errno"
+ enum="OSAgnosticErrno">
+ <summary>
+ Errno errors encountered by a single LevelDBEnv method when opening an
+ IndexedDB instance.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBOpenErrors.PFE"
+ enum="PlatformFileError">
+ <summary>
+ PlatformFileErrors encountered by a single LevelDBEnv method when opening an
+ IndexedDB instance.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBReadErrors" enum="LevelDBErrorTypes">
+ <summary>
+ Error classes returned by LevelDB when it failed to read a database.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBReadErrors.Corruption"
+ enum="LevelDBCorruptionTypes">
+ Types of corruption that LevelDB encounters when reading a database.
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBReadErrors.EnvMethod"
+ enum="LevelDBIOErrorMethods">
+ <summary>
+ LevelDBEnv methods that generated IO errors when reading a database.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBReadErrors.Errno"
+ enum="OSAgnosticErrno">
+ <summary>
+ Errno errors encountered by a single LevelDBEnv method when reading an
+ IndexedDB instance.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBReadErrors.PFE"
+ enum="PlatformFileError">
+ <summary>
+ PlatformFileErrors encountered by a single LevelDBEnv method when opening an
+ IndexedDB instance.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBWriteErrors" enum="LevelDBErrorTypes">
+ <summary>
+ Error classes returned by LevelDB when it failed to write to a database.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBWriteErrors.Corruption"
+ enum="LevelDBCorruptionTypes">
+ Types of corruption returned by LevelDB when it failed to write to a database.
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBWriteErrors.EnvMethod"
+ enum="LevelDBIOErrorMethods">
+ <summary>
+ LevelDBEnv methods that generated IO errors when writing to a database.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBWriteErrors.Errno"
+ enum="OSAgnosticErrno">
+ <summary>
+ Errno errors encountered by a single LevelDBEnv method when writing to an
+ IndexedDB instance.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.IndexedDB.LevelDBWriteErrors.PFE"
+ enum="PlatformFileError">
+ <summary>
+ PlatformFileErrors encountered by a single LevelDBEnv method when writing to
+ an IndexedDB instance.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.PreloadDelayMs" units="milliseconds">
+ <summary>
+ The delay between when the preload scanner discovers a resource on the
+ parser thread and when the preload request is issued on the main thread.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.V8DOMWindowShell.createContext.IsolatedWorld"
+ units="milliseconds">
+ <summary>
+ Duration of time taken to create a V8 Context for an isolated world.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.V8DOMWindowShell.createContext.MainWorld"
+ units="milliseconds">
+ <summary>
+ Duration of time taken to create a V8 Context for the main world.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.WebSocket.HandshakeResult"
+ enum="WebSocketHandshakeResult">
+ <summary>
+ Count the number of WebSocket handshake for each result. Use this histogram
+ as a baseline for investigating feature usage counters.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.WebSocket.PerMessageDeflateContextTakeOverMode"
+ enum="WebSocketPerMessageDeflateContextTakeOverMode">
+ <summary>
+ Count the number of WebSockets that accepted permessage-deflate extension
+ for each context take over mode.
+ </summary>
+</histogram>
+
+<histogram name="WebCore.XHR.send.ArrayBufferOrView"
+ enum="XMLHttpRequestSendArrayBufferOrView">
+ <summary>
+ Count the number of XHR.send() calls for each argument type to see when we
+ can deprecate the ArrayBuffer type support.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.0.Under10KB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of under
+ 10KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.1.10KBTo50KB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 10KB-50KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.2.50KBTo100KB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 50KB-100KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.3.100KBTo1MB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 100KB-1MB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.4.Over1MB" units="milliseconds">
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of over
+ 1MB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.DownloadTime.LoadError" units="milliseconds">
+ <summary>
+ The time taken for a webfont download that failed. Includes aborted
+ requests.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.LoadTime.0.Under10KB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.0.Under10KB.
+ </obsolete>
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of under
+ 10KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.LoadTime.1.10KBTo50KB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.1.10KBTo50KB.
+ </obsolete>
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 10KB-50KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.LoadTime.2.50KBTo100KB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.2.50KBTo100KB.
+ </obsolete>
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 50KB-100KB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.LoadTime.3.100KBTo1MB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.3.100KBTo1MB.
+ </obsolete>
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of
+ 100KB-1MB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.LoadTime.4.Over1MB" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.4.Over1MB.
+ </obsolete>
+ <summary>
+ The time it takes for a webfont download to finish, for webfonts of over
+ 1MB.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.LoadTime.LoadError" units="milliseconds">
+ <obsolete>
+ Deprecated as of 8/2013, replaced by WebFont.DownloadTime.LoadError.
+ </obsolete>
+ <summary>
+ The time taken for a webfont download that failed. Includes aborted
+ requests.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.LocalFontUsed" enum="BooleanUsage">
+ <summary>
+ Whether a locallly installed font is actually used when @font-face had local
+ sources.
+ </summary>
+</histogram>
+
+<histogram name="WebFont.WebFontsInPage">
+ <summary>
+ The number of webfonts used in a page. This is recorded when the first
+ layout is done, and so will not count webfonts dynamically loaded by
+ scripts.
+ </summary>
+</histogram>
+
+<histogram name="WebHistory.LocalResultMissingOnServer" units="%">
+ <summary>
+ Percentage of results that are present locally but are not returned by the
+ web history API call. Recorded every time a signed-in user visits the
+ chrome://history page and the results from the web history are received.
+ </summary>
+</histogram>
+
+<histogram name="WebHistory.OAuthTokenCompletion" enum="BooleanSuccess">
+ <summary>
+ Whether getting the OAuth token was successful for a web history query. On
+ visits to the chrome://history page this token is obtained and then used to
+ get the user's synced web history.
+ </summary>
+</histogram>
+
+<histogram name="WebHistory.OAuthTokenResponseCode" units="code">
+ <summary>
+ HTTP Response code returned by the server when trying to fetch the OAuth
+ token for a web history query.
+ </summary>
+</histogram>
+
+<histogram name="WebHistory.QueryCompletion" enum="WebHistoryStatus">
+ <summary>
+ Whether the web history API call was successful. Every time a signed-in user
+ visits the chrome://history page this query is executed to get the user's
+ synced web history. If successful, the local and remote results are merged
+ and shown in the history page.
+ </summary>
+</histogram>
+
+<histogram name="WebHistory.ResponseTime" units="milliseconds">
+ <summary>
+ Time it took for the web history to reply. Recorded when the web history API
+ call triggered by visiting chrome://history receives the data, measuring how
+ much time it took for the server to reply.
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.AudioCaptureTime" units="milliseconds">
+ <summary>Duration in milliseconds of WebRTC audio capture session.</summary>
+</histogram>
+
+<histogram name="WebRTC.AudioInputChannelLayout" enum="ChannelLayout">
+ <summary>Audio input channel layout in WebRTC.</summary>
+</histogram>
+
+<histogram name="WebRTC.AudioInputFramesPerBuffer" enum="AudioFramesPerBuffer">
+ <summary>Size of WebRTC audio input buffers (in audio frames).</summary>
+</histogram>
+
+<histogram name="WebRTC.AudioInputFramesPerBufferUnexpected"
+ units="audio frames">
+ <summary>
+ Size of WebRTC audio input buffers (atypical values, in audio frames).
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.AudioInputSampleRate" enum="AudioSampleRate">
+ <summary>Audio input sample rate for WebRTC (in Hz).</summary>
+</histogram>
+
+<histogram name="WebRTC.AudioInputSampleRateUnexpected" units="Hz">
+ <summary>
+ Audio input sample rate for WebRTC (atypical values, in Hz).
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.AudioOutputChannelLayout" enum="ChannelLayout">
+ <summary>Audio output channel layout in WebRTC.</summary>
+</histogram>
+
+<histogram name="WebRTC.AudioOutputFramesPerBuffer" enum="AudioFramesPerBuffer">
+ <summary>Size of WebRTC audio output buffers (in audio frames).</summary>
+</histogram>
+
+<histogram name="WebRTC.AudioOutputFramesPerBufferUnexpected"
+ units="audio frames">
+ <summary>
+ Size of WebRTC audio output buffers (atypical values, in audio frames).
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.AudioOutputSampleRate" enum="AudioSampleRate">
+ <summary>Audio output sample rate for WebRTC (in Hz).</summary>
+</histogram>
+
+<histogram name="WebRTC.AudioOutputSampleRateUnexpected" units="Hz">
+ <summary>
+ Audio output sample rate for WebRTC (atypical values, in Hz).
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.AudioRenderTime" units="milliseconds">
+ <summary>Duration in milliseconds of WebRTC audio render session.</summary>
+</histogram>
+
+<histogram name="WebRTC.webkitApiCount" enum="JavaScriptAPIName">
+ <summary>Counts number of calls to WebRTC APIs from JavaScript.</summary>
+</histogram>
+
+<histogram name="WinTimeTicks.FailedToChangeCores" enum="WindowsVersion">
+ <summary>
+ Incremented each time the TimeTicks field trial runs on a machine with
+ multiple cores, but failed to change thread affinity. Broken down by Windows
+ version.
+ </summary>
+</histogram>
+
+<histogram name="WinTimeTicks.MinResolutionNanoseconds" units="nanoseconds">
+ <summary>
+ The smallest non-zero delta reported by subsequent calls to
+ QueryPerformanceCounter.
+ </summary>
+</histogram>
+
+<histogram name="WinTimeTicks.NonStopTsc">
+ <summary>
+ True if the CPU's time stamp counter ticks at a constant rate regardless of
+ CPU frequency.
+ </summary>
+</histogram>
+
+<histogram name="WinTimeTicks.TickedBackwards" enum="WindowsVersion">
+ <summary>
+ The number of times the TimeTicks field trial failed because
+ QueryPerformanceCounter ticked backwards. Broken down by Windows version.
+ </summary>
+</histogram>
+
+<histogram name="WinTimeTicks.VersionSuccessful" enum="WindowsVersion">
+ <summary>
+ The number of times the TimeTicks field trial succeeded. Broken down by
+ Windows version.
+ </summary>
+</histogram>
+
+<histogram name="WinTimeTicks.VersionTotal" enum="WindowsVersion">
+ <summary>
+ The number of times the TimeTicks field trial ran for comparison with
+ WinTimeTicks.VersionSuccess. Broken down by Windows version.
+ </summary>
+</histogram>
+
+<histogram name="WrenchMenu.RecentTabsSubMenu" enum="RecentTabsAction">
+ <summary>
+ The number of times each tab or window restore option in the Recent Tabs
+ submenu is clicked.
+ </summary>
+</histogram>
+
+<histogram name="ZeroSuggest.AllResults">
+ <summary>
+ The number of results (either query or URL) from ZeroSuggest. This is set
+ every time a successful response from ZeroSuggest is recieved, which can be
+ every time the user focuses on the omnibox.
+ </summary>
+</histogram>
+
+<histogram name="ZeroSuggest.QueryResults">
+ <summary>
+ The number of query results returned from ZeroSuggest. This is set every
+ time a successful response from ZeroSuggest is recieved, which can be every
+ time the user focuses on the omnibox.
+ </summary>
+</histogram>
+
+<histogram name="ZeroSuggest.URLResults">
+ <summary>
+ The number of URL results returned from ZeroSuggest. This is set every time
+ a successful response from ZeroSuggest is recieved, which can be every time
+ the user focuses on the omnibox.
+ </summary>
+</histogram>
+
+</histograms>
+
+<!-- Enum types -->
+
+<enums>
+
+<enum name="Abandoned" type="int">
+ <int value="0" label="Finished"/>
+ <int value="1" label="Abandoned"/>
+</enum>
+
+<enum name="AndroidEvictionReason" type="int">
+ <int value="0" label="TabUnusedTooLong"/>
+ <int value="1" label="TabUnusedInSession"/>
+ <int value="2" label="LimitOfActiveTabs"/>
+ <int value="3" label="EvictNTabs"/>
+ <int value="4" label="EvictAll"/>
+</enum>
+
+<enum name="AndroidMemoryNotificationBackground" type="int">
+ <int value="0" label="TrimMemoryUiHidden"/>
+ <int value="1" label="TrimMemoryBackground"/>
+ <int value="2" label="TrimMemoryModerate"/>
+ <int value="3" label="TrimMemoryComplete"/>
+</enum>
+
+<enum name="AndroidMemoryNotificationForeground" type="int">
+ <int value="0" label="TrimMemoryRunningModerate"/>
+ <int value="1" label="TrimMemoryRunningLow"/>
+ <int value="2" label="TrimMemoryRunningCritical"/>
+ <int value="3" label="LowMemory"/>
+</enum>
+
+<enum name="AppLaunch" type="int">
+ <int value="0" label="NTP_APPS_MAXIMIZED"/>
+ <int value="1" label="NTP_APPS_COLLAPSED"/>
+ <int value="2" label="NTP_APPS_MENU"/>
+ <int value="3" label="NTP_MOST_VISITED"/>
+ <int value="4" label="NTP_RECENTLY_CLOSED"/>
+ <int value="5" label="BOOKMARK_BAR"/>
+ <int value="6" label="CONTENT_NAVIGATION"/>
+ <int value="7" label="SESSION_RESTORE"/>
+ <int value="8" label="AUTOLAUNCH"/>
+ <int value="9" label="OMNIBOX_APP"/>
+ <int value="10" label="OMNIBOX_LOCATION"/>
+ <int value="11" label="OMNIBOX_INSTANT"/>
+ <int value="12" label="EXTENSION_API"/>
+ <int value="13" label="CMD_LINE_APP"/>
+ <int value="14" label="CMD_LINE_URL"/>
+ <int value="15" label="NTP_WEBSTORE"/>
+ <int value="16" label="NTP_APP_RE_ENABLE"/>
+ <int value="17" label="CMD_LINE_APP_LEGACY"/>
+ <int value="18" label="NTP_WEBSTORE_FOOTER"/>
+ <int value="19" label="NTP_WEBSTORE_PLUS_ICON"/>
+ <int value="20" label="APP_LIST_MAIN"/>
+ <int value="21" label="APP_LIST_SEARCH"/>
+</enum>
+
+<enum name="AppLaunchContainer" type="int">
+ <int value="0" label="LAUNCH_WINDOW"/>
+ <int value="1" label="LAUNCH_PANEL"/>
+ <int value="2" label="LAUNCH_TAB"/>
+ <int value="3" label="LAUNCH_NONE (v2 packaged apps)"/>
+</enum>
+
+<enum name="AppLauncherPromo" type="int">
+ <int value="0" label="Already installed"/>
+ <int value="1" label="Shown"/>
+ <int value="2" label="Dismissed"/>
+ <int value="3" label="Learn more"/>
+</enum>
+
+<enum name="AppListSearchResult" type="int">
+ <int value="0" label="OMNIBOX"/>
+ <int value="1" label="APP"/>
+ <int value="2" label="WEBSTORE"/>
+ <int value="3" label="SEARCH_WEBSTORE"/>
+</enum>
+
+<enum name="AppPromoAction" type="int">
+ <int value="0" label="PROMO_LAUNCH_APP"/>
+ <int value="1" label="PROMO_LAUNCH_WEB_STORE"/>
+ <int value="2" label="PROMO_CLOSE"/>
+ <int value="3" label="PROMO_EXPIRE"/>
+ <int value="4" label="PROMO_SEEN"/>
+</enum>
+
+<enum name="AppsPageDragSource" type="int">
+ <int value="0" label="Same apps pane"/>
+ <int value="1" label="Different apps pane"/>
+ <int value="2" label="Most visited pane"/>
+ <int value="3" label="Bookmarks pane"/>
+ <int value="4" label="Outside of NTP (e.g. bookmarks bar)"/>
+</enum>
+
+<enum name="AsyncDNSConfigParsePosix" type="int">
+ <int value="0" label="OK"/>
+ <int value="1" label="RES_INIT_FAILED"/>
+ <int value="2" label="RES_INIT_UNSET"/>
+ <int value="3" label="BAD_ADDRESS"/>
+ <int value="4" label="BAD_EXT_STRUCT"/>
+ <int value="5" label="NULL_ADDRESS"/>
+ <int value="6" label="NO_NAMESERVERS"/>
+ <int value="7" label="MISSING_OPTIONS"/>
+ <int value="8" label="UNHANDLED_OPTIONS"/>
+</enum>
+
+<enum name="AsyncDNSConfigParseWin" type="int">
+ <int value="0" label="OK"/>
+ <int value="1" label="READ_IPHELPER"/>
+ <int value="2" label="READ_POLICY_SEARCHLIST"/>
+ <int value="3" label="READ_TCPIP_SEARCHLIST"/>
+ <int value="4" label="READ_DOMAIN"/>
+ <int value="5" label="READ_POLICY_DEVOLUTION"/>
+ <int value="6" label="READ_DNSCACHE_DEVOLUTION"/>
+ <int value="7" label="READ_TCPIP_DEVOLUTION"/>
+ <int value="8" label="READ_APPEND_MULTILABEL"/>
+ <int value="9" label="READ_PRIMARY_SUFFIX"/>
+ <int value="10" label="BAD_ADDRESS"/>
+ <int value="11" label="NO_NAMESERVERS"/>
+</enum>
+
+<enum name="AsyncDNSHostsParseWin" type="int">
+ <int value="0" label="OK"/>
+ <int value="1" label="UNREADABLE_HOSTS_FILE"/>
+ <int value="2" label="COMPUTER_NAME_FAILED"/>
+ <int value="3" label="IPHELPER_FAILED"/>
+ <int value="4" label="BAD_ADDRESS"/>
+</enum>
+
+<enum name="AsyncDNSParseResult" type="int">
+ <summary>Results of DnsResponse::ParseToAddressList.</summary>
+ <int value="0" label="SUCCESS"/>
+ <int value="1" label="MALFORMED_RESPONSE"/>
+ <int value="2" label="MALFORMED_CNAME"/>
+ <int value="3" label="NAME_MISMATCH"/>
+ <int value="4" label="SIZE_MISMATCH"/>
+ <int value="5" label="CNAME_AFTER_ADDRESS"/>
+ <int value="6" label="ADDRESS_TTL_MISMATCH"/>
+ <int value="7" label="NO_ADDRESSES"/>
+</enum>
+
+<enum name="AsyncDNSResolveStatus" type="int">
+ <int value="0" label="DNS_SUCCESS">Succeeded with async DNS.</int>
+ <int value="1" label="PROC_SUCCESS">
+ Succeeded with getaddrinfo after async DNS failed.
+ </int>
+ <int value="2" label="FAIL">Both async DNS and getaddrinfo failed.</int>
+ <int value="3" label="SUSPECT_NETBIOS">
+ Same as PROC_SUCCESS except the hostname fits NetBIOS name criteria.
+ </int>
+</enum>
+
+<enum name="AsyncDNSWatchStatus" type="int">
+ <int value="0" label="STARTED">Started.</int>
+ <int value="1" label="FAILED_TO_START_CONFIG">
+ Failed to start watching config.
+ </int>
+ <int value="2" label="FAILED_TO_START_HOSTS">
+ Failed to start watching HOSTS.
+ </int>
+ <int value="3" label="FAILED_CONFIG">Failed during watching config.</int>
+ <int value="4" label="FAILED_HOSTS">Failed during watching HOSTS.</int>
+</enum>
+
+<enum name="AudioCodec" type="int">
+ <int value="0" label="kUnknownAudioCodec"/>
+ <int value="1" label="kCodecAAC"/>
+ <int value="2" label="kCodecMP3"/>
+ <int value="3" label="kCodecPCM"/>
+ <int value="4" label="kCodecVorbis"/>
+ <int value="5" label="kCodecFLAC"/>
+ <int value="6" label="kCodecAMR_NB"/>
+ <int value="7" label="kCodecAMR_WB"/>
+ <int value="8" label="kCodecPCM_MULAW"/>
+ <int value="9" label="kCodecGSM_MS"/>
+ <int value="10" label="kCodecPCM_S16BE"/>
+ <int value="11" label="kCodecPCM_S24BE"/>
+ <int value="12" label="kCodecOpus"/>
+</enum>
+
+<enum name="AudioFramesPerBuffer" type="int">
+ <int value="0" label="k160"/>
+ <int value="1" label="k320"/>
+ <int value="2" label="k440"/>
+ <int value="3" label="k480"/>
+ <int value="4" label="k640"/>
+ <int value="5" label="k880"/>
+ <int value="6" label="k960"/>
+ <int value="7" label="k1440"/>
+ <int value="8" label="k1920"/>
+</enum>
+
+<enum name="AudioRendererEvents" type="int">
+ <int value="0" label="Initialized"/>
+ <int value="1" label="Runtime error"/>
+</enum>
+
+<enum name="AudioSampleFormat" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Unsigned 8-bit"/>
+ <int value="2" label="Signed 16-bit"/>
+ <int value="3" label="Signed 32-bit"/>
+ <int value="4" label="Float 32-bit"/>
+ <int value="5" label="Signed 16-bit planar"/>
+ <int value="6" label="Float 32-bit planar"/>
+</enum>
+
+<enum name="AudioSampleRate" type="int">
+ <int value="0" label="k8000Hz"/>
+ <int value="1" label="k16000Hz"/>
+ <int value="2" label="k32000Hz"/>
+ <int value="3" label="k48000Hz"/>
+ <int value="4" label="k96000Hz"/>
+ <int value="5" label="k11025Hz"/>
+ <int value="6" label="k22050Hz"/>
+ <int value="7" label="k44100Hz"/>
+ <int value="8" label="k88200Hz"/>
+ <int value="9" label="k176400Hz"/>
+ <int value="10" label="k192000Hz"/>
+</enum>
+
+<enum name="AutocheckoutBubble" type="int">
+ <int value="0" label="Created"/>
+ <int value="1" label="Accepted"/>
+ <int value="2" label="Dismissed"/>
+ <int value="3" label="Ignored"/>
+ <int value="4" label="Could be displayed"/>
+</enum>
+
+<enum name="AutocheckoutBuyFlow" type="int">
+ <int value="0" label="Started"/>
+ <int value="1" label="Success"/>
+ <int value="2" label="Missing field mappings"/>
+ <int value="3" label="Missing advance element"/>
+ <int value="4" label="Cannot proceed"/>
+</enum>
+
+<enum name="AutofillCreditCardInfoBar" type="int">
+ <int value="0" label="Shown"/>
+ <int value="1" label="Accepted"/>
+ <int value="2" label="Denied"/>
+ <int value="3" label="Ignored"/>
+</enum>
+
+<enum name="AutofillDeveloperEngagement" type="int">
+ <int value="0" label="Fillable form parsed"/>
+ <int value="1" label="Includes type hints"/>
+</enum>
+
+<enum name="AutofillDialogDismissalState" type="int">
+ <int value="0" label="Submitted, existing data"/>
+ <int value="1" label="Submitted, saved to Wallet"/>
+ <int value="2" label="Submitted, saved locally"/>
+ <int value="3" label="Submitted, no save"/>
+ <int value="4" label="Canceled, no edits"/>
+ <int value="5" label="Canceled, no invalid fields"/>
+ <int value="6" label="Canceled, 1+ invalid fields"/>
+ <int value="7" label="Canceled during sign-in"/>
+</enum>
+
+<enum name="AutofillDialogInitialUserState" type="int">
+ <int value="0" label="Not signed in, no Autofill"/>
+ <int value="1" label="Not signed in, has Autofill"/>
+ <int value="2" label="Signed in, no Wallet, no Autofill"/>
+ <int value="3" label="Signed in, no Wallet, has Autofill"/>
+ <int value="4" label="Signed in, has Wallet, no Autofill"/>
+ <int value="5" label="Signed in, ha Wallet, has Autofill"/>
+</enum>
+
+<enum name="AutofillDialogPopupEvent" type="int">
+ <int value="0" label="Popup shown"/>
+ <int value="1" label="Form Autofilled"/>
+</enum>
+
+<enum name="AutofillDialogSecurity" type="int">
+ <int value="0" label="Baseline: Dialog shown"/>
+ <int value="1" label="Credit card over HTTP"/>
+ <int value="2" label="Cross-origin frame"/>
+</enum>
+
+<enum name="AutofillDialogUiEvents" type="int">
+ <int value="0" label="Dialog shown"/>
+ <int value="1" label="Dialog submitted"/>
+ <int value="2" label="Dialog canceled"/>
+ <int value="3" label="Account switched: Wallet-&gt;Autofill"/>
+ <int value="4" label="Account switched: Autofill-&gt;Wallet"/>
+ <int value="5" label="Account switched: Wallet-&gt;Wallet"/>
+ <int value="6" label="Sign-in UI shown"/>
+ <int value="7" label="Selected different email suggestion"/>
+ <int value="8" label="Selected different billing suggestion"/>
+ <int value="9" label="Selected different cc+billing suggestion"/>
+ <int value="10" label="Selected different shipping suggestion"/>
+ <int value="11" label="Selected different cc suggestion"/>
+ <int value="12" label="Showed edit UI for email"/>
+ <int value="13" label="Showed edit UI for billing"/>
+ <int value="14" label="Showed edit UI for cc+billing"/>
+ <int value="15" label="Showed edit UI for shipping"/>
+ <int value="16" label="Showed edit UI for cc"/>
+ <int value="17" label="Selected 'Add email' suggestion"/>
+ <int value="18" label="Selected 'Add billing' suggestion"/>
+ <int value="19" label="Selected 'Add cc+billing' suggestion"/>
+ <int value="20" label="Selected 'Add shipping' suggestion"/>
+ <int value="21" label="Selected 'Add cc' suggestion"/>
+</enum>
+
+<enum name="AutofillExperimentId" type="int">
+ <int value="0" label="No Experiment"/>
+ <int value="1" label="Unknown"/>
+ <int value="2" label="ar06"/>
+ <int value="3" label="ar1"/>
+ <int value="4" label="ar2"/>
+ <int value="5" label="ar4"/>
+ <int value="6" label="ar05wlr15"/>
+ <int value="7" label="ar05wlr25"/>
+ <int value="8" label="ar05wlr25fs5"/>
+ <int value="9" label="tbar1"/>
+ <int value="10" label="ar04wr3fs4"/>
+ <int value="11" label="No Server Response"/>
+ <int value="12" label="fp05"/>
+ <int value="13" label="fp025"/>
+ <int value="14" label="fp05cc03"/>
+ <int value="15" label="fp05cco03"/>
+ <int value="16" label="fp05cco03cstd"/>
+ <int value="17" label="fp05cc03e1"/>
+</enum>
+
+<enum name="AutofillQuality" type="int">
+ <int value="0" label="Submitted"/>
+ <int value="1" label="Autofilled"/>
+ <int value="2" label="Autofill failed"/>
+ <int value="3" label="Heuristic Unknown"/>
+ <int value="4" label="Heuristic Match"/>
+ <int value="5" label="Heuristic Mismatch"/>
+ <int value="6" label="Server Unknown"/>
+ <int value="7" label="Server Match"/>
+ <int value="8" label="Server Mismatch"/>
+</enum>
+
+<enum name="AutofillQueryResult" type="int">
+ <int value="0" label="Sent"/>
+ <int value="1" label="Received"/>
+ <int value="2" label="Parsed"/>
+ <int value="3" label="Response matches local"/>
+ <int value="4" label="Response improves local (nonempty)"/>
+ <int value="5" label="Response improves local (empty)"/>
+</enum>
+
+<enum name="AutofillTypeQuality" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Match"/>
+ <int value="2" label="Mismatch"/>
+</enum>
+
+<enum name="AutofillTypeQualityByFieldType" type="int">
+ <int value="0" label="Ambiguous, Unknown"/>
+ <int value="1" label="Ambiguous, Match"/>
+ <int value="2" label="Ambiguous, Mismatch"/>
+ <int value="3" label="Name, Unknown"/>
+ <int value="4" label="Name, Match"/>
+ <int value="5" label="Name, Mismatch"/>
+ <int value="6" label="Company, Unknown"/>
+ <int value="7" label="Company, Match"/>
+ <int value="8" label="Company, Mismatch"/>
+ <int value="9" label="Addr. line 1, Unknown"/>
+ <int value="10" label="Addr. line 1, Match"/>
+ <int value="11" label="Addr. line 1, Mismatch"/>
+ <int value="12" label="Addr. line 2, Unknown"/>
+ <int value="13" label="Addr. line 2, Match"/>
+ <int value="14" label="Addr. line 2, Mismatch"/>
+ <int value="15" label="City, Unknown"/>
+ <int value="16" label="City, Match"/>
+ <int value="17" label="City, Mismatch"/>
+ <int value="18" label="State, Unknown"/>
+ <int value="19" label="State, Match"/>
+ <int value="20" label="State, Mismatch"/>
+ <int value="21" label="ZIP code, Unknown"/>
+ <int value="22" label="ZIP code, Match"/>
+ <int value="23" label="ZIP code, Mismatch"/>
+ <int value="24" label="Country, Unknown"/>
+ <int value="25" label="Country, Match"/>
+ <int value="26" label="Country, Mismatch"/>
+ <int value="27" label="Phone, Unknown"/>
+ <int value="28" label="Phone, Match"/>
+ <int value="29" label="Phone, Mismatch"/>
+ <int value="30" label="Fax, Unknown"/>
+ <int value="31" label="Fax, Match"/>
+ <int value="32" label="Fax, Mismatch"/>
+ <int value="33" label="Email, Unknown"/>
+ <int value="34" label="Email, Match"/>
+ <int value="35" label="Email, Mismatch"/>
+ <int value="36" label="Credit card: name, Unknown"/>
+ <int value="37" label="Credit card: name, Match"/>
+ <int value="38" label="Credit card: name, Mismatch"/>
+ <int value="39" label="Credit card: number, Unknown"/>
+ <int value="40" label="Credit card: number, Match"/>
+ <int value="41" label="Credit card: number, Mismatch"/>
+ <int value="42" label="Credit card: date, Unknown"/>
+ <int value="43" label="Credit card: date, Match"/>
+ <int value="44" label="Credit card: date, Mismatch"/>
+</enum>
+
+<enum name="AutofillUserHappiness" type="int">
+ <int value="0" label="Forms loaded"/>
+ <int value="1" label="Submitted fillable form, autofilled all"/>
+ <int value="2" label="Submitted fillable form, autofilled some"/>
+ <int value="3" label="Submitted fillable form, autofilled none"/>
+ <int value="4" label="Submitted non-fillable form"/>
+ <int value="5" label="User did type"/>
+ <int value="6" label="Suggestions shown"/>
+ <int value="7" label="Suggestions shown (once)"/>
+ <int value="8" label="User did autofill"/>
+ <int value="9" label="User did autofill (once)"/>
+ <int value="10" label="User edited autofilled field"/>
+ <int value="11" label="User edited autofilled field (once)"/>
+</enum>
+
+<enum name="BackingStoreResults" type="int">
+ <int value="0" label="Unused"/>
+ <int value="1" label="Success"/>
+ <int value="2" label="Failure"/>
+</enum>
+
+<enum name="BatteryInfoSampleResult" type="int">
+ <int value="0" label="Read"/>
+ <int value="1" label="Good"/>
+ <int value="2" label="Bad"/>
+</enum>
+
+<enum name="BluetoothPairingMethod" type="int">
+ <int value="0" label="No user interaction required"/>
+ <int value="1" label="PIN Code requested from user"/>
+ <int value="2" label="Passkey requested from user"/>
+ <int value="3" label="PIN Code entered into device"/>
+ <int value="4" label="Passkey entered into device"/>
+ <int value="5" label="Passkey confirmed on both devices"/>
+</enum>
+
+<enum name="BluetoothPairingResult" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Connection already in-progress"/>
+ <int value="2" label="Failed for non-specific reason"/>
+ <int value="3" label="Authentication failed"/>
+ <int value="4" label="Authentication canceled"/>
+ <int value="5" label="Authentication rejected"/>
+ <int value="6" label="Authentication timed out"/>
+ <int value="7" label="Unsupported device"/>
+ <int value="8" label="Unknown or unhandler error"/>
+</enum>
+
+<enum name="Boolean" type="int">
+ <int value="0" label="False"/>
+ <int value="1" label="True"/>
+</enum>
+
+<enum name="BooleanAttempted" type="int">
+ <int value="0" label="Not Attempted"/>
+ <int value="1" label="Attempted"/>
+</enum>
+
+<enum name="BooleanCorrupt" type="int">
+ <int value="0" label="Not Corrupt"/>
+ <int value="1" label="Corrupt"/>
+</enum>
+
+<enum name="BooleanCovered" type="int">
+ <int value="0" label="Not Covered"/>
+ <int value="1" label="Covered"/>
+</enum>
+
+<enum name="BooleanCredentialsLost" type="int">
+ <int value="0" label="Found Credentials"/>
+ <int value="1" label="Missing Credentials"/>
+</enum>
+
+<enum name="BooleanDataReductionProxy" type="int">
+ <int value="0" label="Not Data Reduction Proxy"/>
+ <int value="1" label="Data Reduction Proxy"/>
+</enum>
+
+<enum name="BooleanDelete" type="int">
+ <int value="0" label="Ignored"/>
+ <int value="1" label="Deleted"/>
+</enum>
+
+<enum name="BooleanDuplicate" type="int">
+ <int value="0" label="Not Duplicate"/>
+ <int value="1" label="Duplicate"/>
+</enum>
+
+<enum name="BooleanEnabled" type="int">
+ <int value="0" label="Disabled"/>
+ <int value="1" label="Enabled"/>
+</enum>
+
+<enum name="BooleanExpired" type="int">
+ <int value="0" label="Unexpired"/>
+ <int value="1" label="Expired"/>
+</enum>
+
+<enum name="BooleanHasCrc" type="int">
+ <int value="0" label="No CRC"/>
+ <int value="1" label="Has CRC"/>
+</enum>
+
+<enum name="BooleanHit" type="int">
+ <int value="0" label="Not_reached"/>
+ <int value="1" label="Hit"/>
+</enum>
+
+<enum name="BooleanHttps" type="int">
+ <int value="0" label="HTTP"/>
+ <int value="1" label="HTTPS"/>
+</enum>
+
+<enum name="BooleanMatched" type="int">
+ <int value="0" label="Not matched"/>
+ <int value="1" label="Matched"/>
+</enum>
+
+<enum name="BooleanOrphan" type="int">
+ <int value="0" label="Non-orphan"/>
+ <int value="1" label="Orphan"/>
+</enum>
+
+<enum name="BooleanRaced" type="int">
+ <int value="0" label="Did Not Race"/>
+ <int value="1" label="Raced"/>
+</enum>
+
+<enum name="BooleanRegistered" type="int">
+ <int value="0" label="Not Registered"/>
+ <int value="1" label="Registered"/>
+</enum>
+
+<enum name="BooleanSelected" type="int">
+ <int value="0" label="No selection"/>
+ <int value="1" label="Selected"/>
+</enum>
+
+<enum name="BooleanStale" type="int">
+ <int value="0" label="Fresh"/>
+ <int value="1" label="Stale"/>
+</enum>
+
+<enum name="BooleanSuccess" type="int">
+ <int value="0" label="Failure"/>
+ <int value="1" label="Success"/>
+</enum>
+
+<enum name="BooleanTabDiscard" type="int">
+ <int value="0" label="Memory OK, no discards"/>
+ <int value="1" label="Memory low, tabs discarded"/>
+</enum>
+
+<enum name="BooleanUsage" type="int">
+ <int value="0" label="Not Used"/>
+ <int value="1" label="Used"/>
+</enum>
+
+<enum name="BooleanValid" type="int">
+ <int value="0" label="Invalid"/>
+ <int value="1" label="Valid"/>
+</enum>
+
+<enum name="BooleanWiped" type="int">
+ <int value="0" label="Re-enabled"/>
+ <int value="1" label="Wiped out"/>
+</enum>
+
+<enum name="CanvasContextType" type="int">
+ <int value="0" label="2d"/>
+ <int value="1" label="webkit-3d"/>
+ <int value="2" label="experimental-webgl"/>
+ <int value="3" label="webgl"/>
+</enum>
+
+<enum name="ChannelLayout" type="int">
+ <int value="0" label="CHANNEL_LAYOUT_NONE"/>
+ <int value="1" label="CHANNEL_LAYOUT_UNSUPPORTED"/>
+ <int value="2" label="CHANNEL_LAYOUT_MONO"/>
+ <int value="3" label="CHANNEL_LAYOUT_STEREO"/>
+ <int value="4" label="CHANNEL_LAYOUT_2_1"/>
+ <int value="5" label="CHANNEL_LAYOUT_SURROUND"/>
+ <int value="6" label="CHANNEL_LAYOUT_4POINT0"/>
+ <int value="7" label="CHANNEL_LAYOUT_2_2"/>
+ <int value="8" label="CHANNEL_LAYOUT_QUAD"/>
+ <int value="9" label="CHANNEL_LAYOUT_5POINT0"/>
+ <int value="10" label="CHANNEL_LAYOUT_5POINT1"/>
+ <int value="11" label="CHANNEL_LAYOUT_5POINT0_BACK"/>
+ <int value="12" label="CHANNEL_LAYOUT_5POINT1_BACK"/>
+ <int value="13" label="CHANNEL_LAYOUT_7POINT0"/>
+ <int value="14" label="CHANNEL_LAYOUT_7POINT1"/>
+ <int value="15" label="CHANNEL_LAYOUT_7POINT1_WIDE"/>
+ <int value="16" label="CHANNEL_LAYOUT_STEREO_DOWNMIX"/>
+ <int value="17" label="CHANNEL_LAYOUT_2POINT1"/>
+ <int value="18" label="CHANNEL_LAYOUT_3_1"/>
+ <int value="19" label="CHANNEL_LAYOUT_4_1"/>
+ <int value="20" label="CHANNEL_LAYOUT_6_0"/>
+ <int value="21" label="CHANNEL_LAYOUT_6_0_FRONT"/>
+ <int value="22" label="CHANNEL_LAYOUT_HEXAGONAL"/>
+ <int value="23" label="CHANNEL_LAYOUT_6_1"/>
+ <int value="24" label="CHANNEL_LAYOUT_6_1_BACK"/>
+ <int value="25" label="CHANNEL_LAYOUT_6_1_FRONT"/>
+ <int value="26" label="CHANNEL_LAYOUT_7_0_FRONT"/>
+ <int value="27" label="CHANNEL_LAYOUT_7_1_WIDE_BACK"/>
+ <int value="28" label="CHANNEL_LAYOUT_OCTAGONAL"/>
+ <int value="29" label="CHANNEL_LAYOUT_DISCRETE"/>
+</enum>
+
+<enum name="CheckCRCResult" type="int">
+ <int value="0" label="Stream was never read to end"/>
+ <int value="1" label="CRC check not done"/>
+ <int value="2" label="CRC check done"/>
+ <int value="3" label="Stream was never read at all"/>
+</enum>
+
+<enum name="ChromeDownloadCountType" type="int">
+ <int value="0" label="Initiated by Navigation (Obsolete)"/>
+ <int value="1" label="Initiated by Context Menu (Obsolete)"/>
+ <int value="2" label="Initiated by WebStore Installer (Obsolete)"/>
+ <int value="3" label="Initiated by ImageBurner (Obsolete)"/>
+ <int value="4" label="Blocked by Throttling"/>
+</enum>
+
+<enum name="ChromeDownloadSource" type="int">
+ <int value="0" label="Initiated by Navigation"/>
+ <int value="1" label="Initiated by Context Menu"/>
+ <int value="2" label="Initiated by WebStore Installer"/>
+ <int value="3" label="Initiated by ImageBurner"/>
+ <int value="4" label="Initiated by Plugin Installer"/>
+</enum>
+
+<enum name="ClipboardAction" type="int">
+ <int value="0" label="Write from non-Incognito"/>
+ <int value="1" label="Write from Incognito"/>
+ <int value="2" label="Read Text"/>
+</enum>
+
+<enum name="CoalescePotentialPackets" type="int">
+ <int value="0" label="No Advantage"/>
+ <int value="1" label="Header packets Only"/>
+ <int value="30" label="More Than 30"/>
+</enum>
+
+<enum name="ConnectionType" type="int">
+ <summary>
+ Connection type as defined in net/base/connection_type_histograms.h
+ </summary>
+ <int value="0" label="Any">Any connection (SSL, HTTP, SPDY, etc.)</int>
+ <int value="1" label="SSL">An SSL connection</int>
+ <int value="2" label="SSL-MD5">
+ An SSL connection with an MD5 certificate in the certificate chain
+ (excluding root)
+ </int>
+ <int value="3" label="SSL-MD2">
+ An SSL connection with an MD2 certificate in the certificate chain
+ (excluding root)
+ </int>
+ <int value="4" label="SSL-MD4">
+ An SSL connection with an MD4 certificate in the certificate chain
+ (excluding root)
+ </int>
+ <int value="5" label="SSL-MD5(CA)">
+ An SSL connection with an MD5 CA certificate in the certificate chain
+ (excluding root)
+ </int>
+ <int value="6" label="SSL-MD2(CA)">
+ An SSL connection with an MD2 CA certificate in the cerfificate chain
+ (excluding root)
+ </int>
+ <int value="7" label="HTTP">An HTTP connection</int>
+ <int value="8" label="SPDY">A SPDY connection</int>
+ <int value="9" label="SSL-2.0">An SSL connection that uses SSL 2.0</int>
+ <int value="10" label="SSL-3.0">An SSL connection that uses SSL 3.0</int>
+ <int value="11" label="TLS-1.0">An SSL connection that uses TLS 1.0</int>
+ <int value="12" label="TLS-1.1">An SSL connection that uses TLS 1.1</int>
+ <int value="13" label="TLS-1.2">An SSL connection that uses TLS 1.2</int>
+</enum>
+
+<enum name="CookieDeletionCause" type="int">
+ <summary>Reason why a cookie was removed from the cookie store</summary>
+ <int value="0" label="explicit">
+ The user explicitly requested that we delete a cookie
+ </int>
+ <int value="1" label="overwrite">
+ The value of the cookie was overwritten by a new value
+ </int>
+ <int value="2" label="expired">The cookie expiration time passed</int>
+ <int value="3" label="evicted">
+ The cookie was evicted during garbage collection (replaced by
+ domain_evicted/global_evicted below)
+ </int>
+ <int value="4" label="store_dup">
+ The backing store had two copies of the cookie so one was removed (i.e.
+ problems writing the backing store database)
+ </int>
+ <int value="5" label="dont_record">
+ The cookie deletion should not be recorded because it occurred, e.g., during
+ shutdown (the fact that these values showed up in the histogram is a bug,
+ since fixed)
+ </int>
+ <int value="6" label="domain_evicted">
+ The cookie was evicted during per-domain/eTLD+1 garbage collection
+ </int>
+ <int value="7" label="global_evicted">
+ The cookie was evicted during whole store garbage collection.
+ </int>
+ <int value="8" label="domain_evicted_pre_safe">
+ The cookie evicted during per-domain/eTLD+1 garbage collection, and would
+ have been evicted by the global garbage collection process (because they
+ hadn't been accessed recently enough).
+ </int>
+ <int value="9" label="domain_evicted_post_safe">
+ The cookie evicted during per-domain/eTLD+1 garbage collection, and would
+ not have been evicted by global metrics as well (because they had been
+ accessed recently enough to save).
+ </int>
+ <int value="10" label="expired_overwrite">
+ The cookie deletion occurred because the server overwrote it with an already
+ expired cookie (this is a common idiom for server deletions of cookies).
+ </int>
+</enum>
+
+<enum name="CrosDisksArchiveType" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="ZIP"/>
+ <int value="2" label="RAR"/>
+ <int value="3" label="Tar"/>
+ <int value="4" label="Bzip2-compressed Tar"/>
+ <int value="5" label="Gzip-compressed Tar"/>
+</enum>
+
+<enum name="CrosDisksDeviceMediaType" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="USB Drive"/>
+ <int value="2" label="SD Card"/>
+ <int value="3" label="Optical Disc"/>
+ <int value="4" label="Mobile Device"/>
+ <int value="5" label="DVD"/>
+</enum>
+
+<enum name="CrosDisksFilesystemType" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Others"/>
+ <int value="2" label="FAT"/>
+ <int value="3" label="exFAT"/>
+ <int value="4" label="NTFS"/>
+ <int value="5" label="HFS+"/>
+ <int value="6" label="Ext2"/>
+ <int value="7" label="Ext3"/>
+ <int value="8" label="Ext4"/>
+ <int value="9" label="ISO9660"/>
+ <int value="10" label="UDF"/>
+</enum>
+
+<enum name="CrosEventEnum" type="int">
+ <int value="0" label="ModemManagerCommandSendFailure"/>
+</enum>
+
+<enum name="CrosShelfClickTarget" type="int">
+ <int value="0" label="Chrome"/>
+ <int value="1" label="AppLauncher"/>
+ <int value="2" label="Gmail"/>
+ <int value="3" label="Search"/>
+ <int value="4" label="Youtube"/>
+ <int value="5" label="Doc"/>
+ <int value="6" label="Sheets"/>
+ <int value="7" label="Slides"/>
+ <int value="8" label="PlayMusic"/>
+</enum>
+
+<enum name="DevicePermissionActions" type="int">
+ <int value="0" label="AllowHttps"/>
+ <int value="1" label="AllowHttp"/>
+ <int value="2" label="Deny"/>
+ <int value="3" label="Cancel"/>
+</enum>
+
+<enum name="DNSEmptyAddressListAndNoError" type="int">
+ <int value="0" label="Error reported or Address List is not empty"/>
+ <int value="1" label="Success reported but Address List is empty"/>
+</enum>
+
+<enum name="DnsProbe.JobResult" type="int">
+ <int value="0" label="SERVERS_UNKNOWN"/>
+ <int value="1" label="SERVERS_CORRECT"/>
+ <int value="2" label="SERVERS_INCORRECT"/>
+ <int value="3" label="SERVERS_FAILING"/>
+ <int value="4" label="SERVERS_UNREACHABLE"/>
+</enum>
+
+<enum name="DnsProbe.ObsoleteProbeResult" type="int">
+ <int value="0" label="INCONCLUSIVE"/>
+ <int value="1" label="NO_INTERNET"/>
+ <int value="2" label="BAD_CONFIG"/>
+ <int value="3" label="NXDOMAIN"/>
+</enum>
+
+<enum name="DnsProbe.ProbeStatus" type="int">
+ <int value="0" label="POSSIBLE"/>
+ <int value="1" label="NOT_RUN"/>
+ <int value="2" label="STARTED"/>
+ <int value="3" label="FINISHED_INCONCLUSIVE"/>
+ <int value="4" label="FINISHED_NO_INTERNET"/>
+ <int value="5" label="FINISHED_BAD_CONFIG"/>
+ <int value="6" label="FINISHED_NXDOMAIN"/>
+</enum>
+
+<enum name="DnsProbe.SystemIsLocalhost" type="int">
+ <int value="0" label="Not just 127.0.0.1">
+ 127.0.0.1 was not the only nameserver in the system DNS config.
+ </int>
+ <int value="1" label="Just 127.0.0.1">
+ 127.0.0.1 was the only nameserver in the system DNS config.
+ </int>
+</enum>
+
+<enum name="DomainBoundCerts.GetCertResult" type="int">
+ <int value="0" label="SYNC_SUCCESS"/>
+ <int value="1" label="ASYNC_SUCCESS"/>
+ <int value="2" label="ASYNC_CANCELLED"/>
+ <int value="3" label="ASYNC_FAILURE_KEYGEN"/>
+ <int value="4" label="ASYNC_FAILURE_CREATE_CERT"/>
+ <int value="5" label="ASYNC_FAILURE_EXPORT_KEY"/>
+ <int value="6" label="ASYNC_FAILURE_UNKNOWN"/>
+ <int value="7" label="INVALID_ARGUMENT"/>
+ <int value="8" label="UNSUPPORTED_TYPE"/>
+ <int value="9" label="TYPE_MISMATCH"/>
+ <int value="10" label="WORKER_FAILURE"/>
+</enum>
+
+<enum name="DomainBoundCerts.Support" type="int">
+ <int value="0" label="DISABLED"/>
+ <int value="1" label="CLIENT_ONLY"/>
+ <int value="2" label="CLIENT_AND_SERVER"/>
+ <int value="3" label="CLIENT_NO_ECC">
+ Channel ID was enabled, but the client did not support elliptic curve key
+ generation.
+ </int>
+ <int value="4" label="CLIENT_BAD_SYSTEM_TIME">
+ Channel ID was enabled, but the client had an invalid system time which
+ prevented using it.
+ </int>
+ <int value="5" label="CLIENT_NO_SERVER_BOUND_CERT_SERVICE">
+ The SSLClientSocket was created without a ServerBoundCertService.
+ </int>
+</enum>
+
+<enum name="DoubleGetExperimentMethods" type="int">
+ <int value="0" label="POST"/>
+ <int value="1" label="GET_CACHABLE"/>
+ <int value="2" label="GET_NON_CACHABLE"/>
+</enum>
+
+<enum name="DownloadContentDisposition" type="int">
+ <int value="0" label="Content-Disposition header present"/>
+ <int value="1" label="Valid"/>
+ <int value="2" label="Has disposition-type"/>
+ <int value="3" label="Has unknown disposition-type"/>
+ <int value="4" label="Has 'name' attribute"/>
+ <int value="5" label="Has 'filename' attribute"/>
+ <int value="6" label="Has 'filename*' attribute"/>
+ <int value="7" label="Has non-ASCII strings"/>
+ <int value="8" label="Has percent encoded strings"/>
+ <int value="9" label="Has RFC 2047 encoded strings"/>
+ <int value="10" label="Has 'name' attribute only"/>
+</enum>
+
+<enum name="DownloadContentType" type="int">
+ <int value="0" label="UNRECOGNIZED"/>
+ <int value="1" label="TEXT"/>
+ <int value="2" label="IMAGE"/>
+ <int value="3" label="AUDIO"/>
+ <int value="4" label="VIDEO"/>
+ <int value="5" label="OCTET_STREAM"/>
+ <int value="6" label="PDF"/>
+ <int value="7" label="DOC"/>
+ <int value="8" label="XLS"/>
+ <int value="9" label="PPT"/>
+ <int value="10" label="ARCHIVE"/>
+ <int value="11" label="EXE"/>
+ <int value="12" label="DMG"/>
+ <int value="13" label="CRX"/>
+</enum>
+
+<enum name="DownloadCountType" type="int">
+ <int value="0" label="Initiated by Navigation (Obsolete)"/>
+ <int value="1" label="Initiated by Context Menu (Obsolete)"/>
+ <int value="2" label="Initiated by SavePackage Failure (Obsolete)"/>
+ <int value="3" label="Initiated by Drag-n-drop (Obsolete)"/>
+ <int value="4" label="Initiated by Renderer (Obsolete)"/>
+ <int value="5" label="Initiated and Unthrottled"/>
+ <int value="6" label="Completed"/>
+ <int value="7" label="Cancelled"/>
+ <int value="8" label="Started"/>
+ <int value="9" label="Interrupted"/>
+ <int value="10" label="Calls to AppendDataToFile (Size) (Obsolete)"/>
+ <int value="11" label="Calls to AppendDataToFile (Count) (Obsolete)"/>
+ <int value="12" label="Interrupted at End of Download"/>
+ <int value="13" label="Attempt to Append to Detached File"/>
+ <int value="14" label="File Missing After Successful Scan"/>
+ <int value="15" label="Supports ranges and strong validation"/>
+ <int value="16" label="No WebContents at interruption"/>
+</enum>
+
+<enum name="DownloadDatabaseRecordDroppedType" type="int">
+ <int value="0" label="Bad State"/>
+ <int value="1" label="Bad Danger Type"/>
+</enum>
+
+<enum name="DownloadDOMEvent" type="int">
+ <int value="0" label="GetDownloads"/>
+ <int value="1" label="OpenFile"/>
+ <int value="2" label="Drag"/>
+ <int value="3" label="SaveDangerous"/>
+ <int value="4" label="DiscardDangerous"/>
+ <int value="5" label="Show"/>
+ <int value="6" label="Pause"/>
+ <int value="7" label="Remove"/>
+ <int value="8" label="Cancel"/>
+ <int value="9" label="ClearAll"/>
+ <int value="10" label="OpenFolder"/>
+ <int value="11" label="Resume"/>
+</enum>
+
+<enum name="DownloadFilePickerResult" type="int">
+ <int value="0" label="SAME"/>
+ <int value="1" label="DIFFERENT_DIR"/>
+ <int value="2" label="DIFFERENT_NAME"/>
+ <int value="3" label="CANCEL"/>
+</enum>
+
+<enum name="DownloadFunctions" type="int">
+ <int value="0" label="download"/>
+ <int value="1" label="search"/>
+ <int value="2" label="pause"/>
+ <int value="3" label="resume"/>
+ <int value="4" label="cancel"/>
+ <int value="5" label="erase"/>
+ <int value="6" label="set_destination"/>
+ <int value="7" label="accept_danger"/>
+ <int value="8" label="show"/>
+ <int value="9" label="drag"/>
+</enum>
+
+<enum name="DownloadImageType" type="int">
+ <int value="0" label="Unrecognized"/>
+ <int value="1" label="GIF"/>
+ <int value="2" label="JPEG"/>
+ <int value="3" label="PNG"/>
+ <int value="4" label="TIFF"/>
+ <int value="5" label="ICON"/>
+ <int value="6" label="WEBP"/>
+</enum>
+
+<enum name="DownloadInterruptedUnknownSizeType" type="int">
+ <int value="0" label="Size Known"/>
+ <int value="1" label="Size Unknown"/>
+</enum>
+
+<enum name="DownloadItem.DangerType" type="int">
+ <int value="0" label="NOT_DANGEROUS"/>
+ <int value="1" label="DANGEROUS_FILE"/>
+ <int value="2" label="DANGEROUS_URL"/>
+ <int value="3" label="DANGEROUS_CONTENT"/>
+ <int value="4" label="MAYBE_DANGEROUS_CONTENT"/>
+ <int value="5" label="UNCOMMON_CONTENT"/>
+ <int value="6" label="USER_VALIDATED"/>
+ <int value="7" label="DANGEROUS_HOST"/>
+ <int value="8" label="POTENTIALLY_UNWANTED"/>
+</enum>
+
+<enum name="DownloadSavePackageEvent" type="int">
+ <int value="0" label="Started"/>
+ <int value="1" label="Cancelled"/>
+ <int value="2" label="Finished"/>
+ <int value="3" label="Write to already completed file"/>
+ <int value="4" label="Write to already failed file"/>
+</enum>
+
+<enum name="DownloadSource" type="int">
+ <int value="0" label="Initiated by Save Package on Non-HTML content"/>
+ <int value="1" label="Initiated by Drag-and-drop"/>
+ <int value="2" label="Initiated by RPC from Renderer"/>
+ <int value="3" label="Initiated by Save from Pepper"/>
+ <int value="4" label="Initiated by Resumption"/>
+</enum>
+
+<enum name="DriveCacheDBOpenStatus" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Corrupt database"/>
+ <int value="2" label="Unknown recoverable failure"/>
+ <int value="3" label="Unrecoverable (disk full?) failure"/>
+</enum>
+
+<enum name="DriveEntryKind" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Item"/>
+ <int value="2" label="Site"/>
+ <int value="3" label="Document"/>
+ <int value="4" label="Spereadsheet"/>
+ <int value="5" label="Presentation"/>
+ <int value="6" label="Drawing"/>
+ <int value="7" label="Table"/>
+ <int value="8" label="External app"/>
+ <int value="9" label="Folder"/>
+ <int value="10" label="File"/>
+ <int value="11" label="PDF"/>
+</enum>
+
+<enum name="DriveFileFormat" type="int">
+ <int value="0" label="AAC"/>
+ <int value="1" label="ASF"/>
+ <int value="2" label="AVI"/>
+ <int value="3" label="CSV"/>
+ <int value="4" label="DOC"/>
+ <int value="5" label="DOCX"/>
+ <int value="6" label="FLV"/>
+ <int value="7" label="JPG"/>
+ <int value="8" label="MJPG"/>
+ <int value="9" label="MOV"/>
+ <int value="10" label="MP3"/>
+ <int value="11" label="MP4"/>
+ <int value="12" label="MPG"/>
+ <int value="13" label="OTHER"/>
+ <int value="14" label="PDF"/>
+ <int value="15" label="PPT"/>
+ <int value="16" label="PPTX"/>
+ <int value="17" label="PSD"/>
+ <int value="18" label="RAR"/>
+ <int value="19" label="WMA"/>
+ <int value="20" label="WMV"/>
+ <int value="21" label="XLS"/>
+ <int value="22" label="XLSX"/>
+ <int value="23" label="ZIP"/>
+</enum>
+
+<enum name="DriveMetadataDBInitStatus" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Not found"/>
+ <int value="2" label="Corruption"/>
+ <int value="3" label="IO error"/>
+ <int value="4" label="Failed to open DB for unknown reason"/>
+ <int value="5" label="Incompatible DB format"/>
+ <int value="6" label="DB is broken"/>
+</enum>
+
+<enum name="EAPInnerProtocol" type="int">
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="NONE"/>
+ <int value="2" label="PEAP-MD5"/>
+ <int value="3" label="PEAP-MSCHAPV2"/>
+ <int value="4" label="TTLS-EAP-MD5"/>
+ <int value="5" label="TTLS-EAP-MSCHAPV2"/>
+ <int value="6" label="TTLS-MSCHAPV2"/>
+ <int value="7" label="TTLS-MSCHAP"/>
+ <int value="8" label="TTLS-PAP"/>
+ <int value="9" label="TTLS-CHAP"/>
+</enum>
+
+<enum name="EAPOuterProtocol" type="int">
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="LEAP"/>
+ <int value="2" label="PEAP"/>
+ <int value="3" label="TLS"/>
+ <int value="4" label="TTLS"/>
+</enum>
+
+<enum name="EnterpriseDeviceManagementStatus" type="int">
+ <summary>
+ Status codes produced by DeviceManagementService for requests made to the
+ device management server.
+ </summary>
+ <int value="0" label="SUCCESS"/>
+ <int value="1" label="REQUEST_INVALID"/>
+ <int value="2" label="REQUEST_FAILED"/>
+ <int value="3" label="TEMPORARY_UNAVAILABLE"/>
+ <int value="4" label="HTTP_STATUS_ERROR"/>
+ <int value="5" label="RESPONSE_DECODING_ERROR"/>
+ <int value="6" label="SERVICE_MANAGEMENT_NOT_SUPPORTED"/>
+ <int value="7" label="SERVICE_DEVICE_NOT_FOUND"/>
+ <int value="8" label="SERVICE_MANAGEMENT_TOKEN_INVALID"/>
+ <int value="9" label="SERVICE_ACTIVATION_PENDING"/>
+ <int value="10" label="SERVICE_INVALID_SERIAL_NUMBER"/>
+ <int value="11" label="SERVICE_DEVICE_ID_CONFLICT"/>
+ <int value="12" label="SERVICE_MISSING_LICENSES"/>
+ <int value="902" label="SERVICE_POLICY_NOT_FOUND"/>
+</enum>
+
+<enum name="EnterpriseDMTokenType" type="int">
+ <summary>
+ Result of DMToken operations as defined in
+ chrome/browser/policy/enterprise_metrics.h.
+ </summary>
+ <int value="0" label="Load Succeeded">
+ A cached token was successfully loaded from disk.
+ </int>
+ <int value="1" label="Load Failed">
+ Reading a cached token from disk failed.
+ </int>
+ <int value="2" label="Fetch Requested">
+ A token fetch request was sent to the DM server.
+ </int>
+ <int value="3" label="Fetch Request Failed">
+ The request was invalid, or the HTTP request failed.
+ </int>
+ <int value="4" label="Fetch Server Failed">
+ Error HTTP status received, or the DM server failed in another way.
+ </int>
+ <int value="5" label="Fetch Response Received">
+ A response to the fetch request was received.
+ </int>
+ <int value="6" label="Fetch Bad Response">
+ The response received was invalid. This happens when some expected data was
+ not present in the response.
+ </int>
+ <int value="7" label="Fetch Management Not Supported">
+ DM server reported that management is not supported.
+ </int>
+ <int value="8" label="Fetch Device Not Found">
+ DM server reported that the given device ID was not found.
+ </int>
+ <int value="9" label="Fetch OK">DM token successfully retrieved.</int>
+ <int value="10" label="Store Succeeded">
+ Successfully cached a token to disk.
+ </int>
+ <int value="11" label="Store Failed">Caching a token to disk failed.</int>
+ <int value="12" label="Device ID Conflict">The Device-ID is not unique.</int>
+ <int value="13" label="Invalid Serial">
+ Serial number rejected by DMServer.
+ </int>
+ <int value="14" label="Missing Licenses">
+ No more licenses available for that domain.
+ </int>
+</enum>
+
+<enum name="EnterpriseEnrollmentType" type="int">
+ <summary>
+ Result of device enrollment as defined in
+ chrome/browser/policy/enterprise_metrics.h.
+ </summary>
+ <int value="0" label="Cancelled">
+ The enrollment screen was closed without completing the enrollment process.
+ </int>
+ <int value="1" label="Started">
+ The user submitted credentials and started the enrollment process.
+ </int>
+ <int value="2" label="Network Failed">
+ Enrollment failed due to a network error.
+ </int>
+ <int value="3" label="Login Failed">
+ Enrollment failed because logging in to Gaia failed.
+ </int>
+ <int value="4" label="Not Supported">
+ Enrollment failed because it is not supported for the account used.
+ </int>
+ <int value="5" label="Policy Failed">
+ Enrollment failed because it failed to apply device policy.
+ </int>
+ <int value="6" label="Other Failed">
+ Enrollment failed due to an unexpected error. This currently happens when
+ the Gaia auth token is not issued for the DM service, the device cloud
+ policy subsystem isn't initialized, or when fetching Gaia tokens fails for
+ an unknown reason.
+ </int>
+ <int value="7" label="OK">Enrollment was successful.</int>
+ <int value="8" label="Invalid Serial">
+ Serial number doesn't belong to account domain.
+ </int>
+ <int value="9" label="Auto-enrollment Started">
+ Auto-enrollment started automatically after sign-in.
+ </int>
+ <int value="10" label="Auto-enrollment Failed">Auto-enrollment failed.</int>
+ <int value="11" label="Auto-enrollment Retried">
+ Auto-enrollment started again after a failure.
+ </int>
+ <int value="12" label="Auto-enrollment Cancelled">
+ User opted-out of auto-enrollment.
+ </int>
+ <int value="13" label="Auto-enrollment OK">Auto-enrollment OK.</int>
+ <int value="14" label="Invalid enrollment mode">
+ The enrollment mode has not been sent down or is unknown to the client.
+ </int>
+ <int value="15" label="Auto-enrollment not supported">
+ The enrollment mode can not be set through auto-enrollment.
+ </int>
+ <int value="16" label="Install attributes timeout">
+ Install attributes failed to initialize in time.
+ </int>
+ <int value="17" label="Wrong user name">
+ Re-enrollment attempted with an account from a different domain.
+ </int>
+ <int value="18" label="Missing licenses">
+ No licenses left for that domain.
+ </int>
+</enum>
+
+<enum name="EnterprisePolicies" type="int">
+<!-- Generated from ../../../chrome/app/policy/policy_templates.json -->
+
+ <int value="1" label="Configure the home page URL"/>
+ <int value="2" label="Use New Tab Page as homepage"/>
+ <int value="3" label="Set Chrome as Default Browser"/>
+ <int value="4" label="Application locale"/>
+ <int value="5" label="Enable alternate error pages"/>
+ <int value="6" label="Enable search suggestions"/>
+ <int value="7" label="Enable network prediction"/>
+ <int value="8" label="Disable SPDY protocol"/>
+ <int value="9" label="Enable JavaScript"/>
+ <int value="10" label="Enable Incognito mode"/>
+ <int value="11" label="Disable saving browser history"/>
+ <int value="12" label="Enable printing"/>
+ <int value="13" label="Enable Google Cloud Print proxy"/>
+ <int value="14" label="Enable Safe Browsing"/>
+ <int value="15" label="Enable reporting of usage and crash-related data"/>
+ <int value="16" label="Enable the password manager"/>
+ <int value="17" label="Allow users to show passwords in Password Manager"/>
+ <int value="18" label="Enable AutoFill"/>
+ <int value="19" label="Specify a list of disabled plugins"/>
+ <int value="20" label="Disable synchronization of data with Google"/>
+ <int value="21" label="Choose how to specify proxy server settings"/>
+ <int value="22" label="Choose how to specify proxy server settings"/>
+ <int value="23" label="Address or URL of proxy server"/>
+ <int value="24" label="URL to a proxy .pac file"/>
+ <int value="25" label="Proxy bypass rules"/>
+ <int value="26" label="Supported authentication schemes"/>
+ <int value="27"
+ label="Disable CNAME lookup when negotiating Kerberos authentication"/>
+ <int value="28" label="Include non-standard port in Kerberos SPN"/>
+ <int value="29" label="Authentication server whitelist"/>
+ <int value="30" label="Kerberos delegation server whitelist"/>
+ <int value="31" label="GSSAPI library name"/>
+ <int value="32" label="Configure extension installation blacklist"/>
+ <int value="33" label="Configure extension installation whitelist"/>
+ <int value="34" label="Configure the list of force-installed extensions"/>
+ <int value="35" label="Show Home button on toolbar"/>
+ <int value="36" label="Disable Developer Tools"/>
+ <int value="37" label="Action on startup"/>
+ <int value="38" label="URLs to open on startup"/>
+ <int value="39" label="Block third party cookies"/>
+ <int value="40" label="Enable the default search provider"/>
+ <int value="41" label="Default search provider name"/>
+ <int value="42" label="Default search provider keyword"/>
+ <int value="43" label="Default search provider search URL"/>
+ <int value="44" label="Default search provider suggest URL"/>
+ <int value="45" label="Default search provider instant URL"/>
+ <int value="46" label="Default search provider icon"/>
+ <int value="47" label="Default search provider encodings"/>
+ <int value="48" label="Default cookies setting"/>
+ <int value="49" label="Default images setting"/>
+ <int value="50" label="Default JavaScript setting"/>
+ <int value="51" label="Default plugins setting"/>
+ <int value="52" label="Default popups setting"/>
+ <int value="53" label="Default notification setting"/>
+ <int value="54" label="Default geolocation setting"/>
+ <int value="55" label="Disable support for 3D graphics APIs"/>
+ <int value="56" label="Refresh rate for user policy"/>
+ <int value="57" label="Default HTML renderer for Google Chrome Frame"/>
+ <int value="58"
+ label="Always render the following URL patterns in Google Chrome Frame"/>
+ <int value="59"
+ label="Always render the following URL patterns in the host browser"/>
+ <int value="60"
+ label="Allow Google Chrome Frame to handle the listed content types"/>
+ <int value="61" label="Enable lock when the device become idle or suspended"/>
+ <int value="62" label="Enable Instant"/>
+ <int value="63" label="Set user data directory"/>
+ <int value="64" label="Set download directory"/>
+ <int value="65" label="Clear site data on browser shutdown (deprecated)"/>
+ <int value="66" label="Specify whether the plugin finder should be disabled"/>
+ <int value="67" label="Block cookies on these sites"/>
+ <int value="68" label="Allow session only cookies on these sites"/>
+ <int value="69" label="Allow images on these sites"/>
+ <int value="70" label="Block images on these sites"/>
+ <int value="71" label="Allow JavaScript on these sites"/>
+ <int value="72" label="Block JavaScript on these sites"/>
+ <int value="73" label="Allow plugins on these sites"/>
+ <int value="74" label="Block plugins on these sites"/>
+ <int value="75" label="Allow popups on these sites"/>
+ <int value="76" label="Block popups on these sites"/>
+ <int value="77" label="Allow cookies on these sites"/>
+ <int value="78" label="Specify a list of enabled plugins"/>
+ <int value="79"
+ label="Specify a list of plugins that the user can enable or disable"/>
+ <int value="80" label="Enable Translate"/>
+ <int value="81" label="Allow running plugins that are outdated"/>
+ <int value="82" label="Enable Bookmark Bar"/>
+ <int value="83" label="Enables or disables bookmark editing"/>
+ <int value="84" label="Allow invocation of file selection dialogs"/>
+ <int value="85" label="Disable URL protocol schemes"/>
+ <int value="86" label="Always runs plugins that require authorization"/>
+ <int value="87" label="Set Google Chrome Frame user data directory"/>
+ <int value="88" label="Set disk cache directory"/>
+ <int value="89" label="Cross-origin HTTP Basic Auth prompts"/>
+ <int value="90" label="Refresh rate for Device Policy"/>
+ <int value="91" label="Release channel"/>
+ <int value="92"
+ label="Maximal number of concurrent connections to the proxy server"/>
+ <int value="93" label="Incognito mode availability"/>
+ <int value="94" label="Enable firewall traversal from remote access client"/>
+ <int value="95" label="Enable firewall traversal from remote access host"/>
+ <int value="96"
+ label="Prevent app promotions from appearing on the new tab page"/>
+ <int value="97" label="Import bookmarks from default browser on first run"/>
+ <int value="98"
+ label="Import browsing history from default browser on first run"/>
+ <int value="99" label="Import of homepage from default browser on first run"/>
+ <int value="100"
+ label="Import search engines from default browser on first run"/>
+ <int value="101"
+ label="Import saved passwords from default browser on first run"/>
+ <int value="102"
+ label="Automatically select client certificates for these sites"/>
+ <int value="103" label="Block access to a list of URLs"/>
+ <int value="104" label="Allows access to a list of URLs"/>
+ <int value="105" label="Allow notifications on these sites"/>
+ <int value="106" label="Block notifications on these sites"/>
+ <int value="107" label="User-level network configuration"/>
+ <int value="108" label="Device-level network configuration"/>
+ <int value="109"
+ label="Enable submission of documents to Google Cloud Print"/>
+ <int value="110" label="Set disk cache size in bytes"/>
+ <int value="111" label="Set media disk cache size in bytes"/>
+ <int value="112" label="Enterprise web store URL"/>
+ <int value="113" label="Enterprise web store name"/>
+ <int value="114" label="Enable TLS domain-bound certificates extension"/>
+ <int value="115" label="Enable reporting memory info (JS heap size) to page"/>
+ <int value="116" label="Proxy settings"/>
+ <int value="117" label="Disable Print Preview"/>
+ <int value="118" label="Disable SSL record splitting"/>
+ <int value="119" label="Report OS and firmware version"/>
+ <int value="120" label="Report device activity times"/>
+ <int value="121" label="Report device boot mode"/>
+ <int value="122" label="Login user white list"/>
+ <int value="123" label="Allow creation of new user accounts"/>
+ <int value="124" label="Enable guest mode"/>
+ <int value="125" label="Show usernames on login screen"/>
+ <int value="126" label="Enable data roaming"/>
+ <int value="127" label="Enable metrics reporting"/>
+ <int value="128" label="Wipe user data on sign-out"/>
+ <int value="129" label="Whether online OCSP/CRL checks are performed"/>
+ <int value="130" label="Timeout until idle user log-out is executed"/>
+ <int value="131" label="Duration of the idle log-out warning message"/>
+ <int value="132"
+ label="Screen saver to be used on the sign-in screen in retail mode"/>
+ <int value="133"
+ label="Duration of inactivity before the screen saver is shown on the
+ sign-in screen in retail mode"/>
+ <int value="134"
+ label="Whether the release channel should be configurable by the user"/>
+ <int value="135" label="List of AppPack extensions"/>
+ <int value="136" label="Disables Auto Update"/>
+ <int value="137" label="Load specified urls on demo login"/>
+ <int value="138"
+ label="Continue running background apps when Google Chrome is closed"/>
+ <int value="139" label="Disables Drive"/>
+ <int value="140" label="Disables Google Drive over Cellular connections"/>
+ <int value="141"
+ label="Additional command line parameters for Google Chrome"/>
+ <int value="142" label="Target Auto Update Version"/>
+ <int value="143" label="Report device location"/>
+ <int value="144" label="List of pinned apps to show in the launcher"/>
+ <int value="145" label="Auto update scatter factor"/>
+ <int value="146" label="Connection types allowed for updates"/>
+ <int value="147"
+ label="Restrict which users are allowed to sign in to Google Chrome"/>
+ <int value="148"
+ label="Configure extension, app, and user script install sources"/>
+ <int value="149" label="Default mediastream setting"/>
+ <int value="150"
+ label="Disable proceeding from the Safe Browsing warning page"/>
+ <int value="151" label="Enable or disable spell checking web service"/>
+ <int value="152" label="Disable mounting of external storage"/>
+ <int value="153" label="Disable taking screenshots"/>
+ <int value="154"
+ label="Configure the required domain name for remote access hosts"/>
+ <int value="155"
+ label="Enable two-factor authentication for remote access hosts"/>
+ <int value="156"
+ label="Configure the TalkGadget prefix for remote access hosts"/>
+ <int value="157" label="Enable curtaining of remote access hosts"/>
+ <int value="158" label="Timezone"/>
+ <int value="159" label="Allow playing audio"/>
+ <int value="160" label="Allow or deny audio capture"/>
+ <int value="161"
+ label="List of alternate URLs for the default search provider"/>
+ <int value="162" label="Force SafeSearch"/>
+ <int value="163" label="Device-local accounts"/>
+ <int value="164" label="Add a logout button to the system tray"/>
+ <int value="165" label="Use built-in DNS client"/>
+ <int value="166" label="Control shelf auto-hiding"/>
+ <int value="167" label="Allow or deny video capture"/>
+ <int value="168" label="Configure allowed app/extension types"/>
+ <int value="169" label="Set the display name for device-local accounts"/>
+ <int value="170" label="Limit the session length"/>
+ <int value="171"
+ label="Parameter controlling search term placement for the default
+ search provider"/>
+ <int value="172" label="Screen dim delay when running on AC power"/>
+ <int value="173" label="Screen off delay when running on AC power"/>
+ <int value="174" label="Screen lock delay when running on AC power"/>
+ <int value="175" label="Idle delay when running on AC power"/>
+ <int value="176" label="Screen dim delay when running on battery power"/>
+ <int value="177" label="Screen off delay when running on battery power"/>
+ <int value="178" label="Screen lock delay when running on battery power"/>
+ <int value="179" label="Idle delay when running on battery power"/>
+ <int value="180" label="Action to take when the idle delay is reached"/>
+ <int value="181" label="Action to take when the user closes the lid"/>
+ <int value="182"
+ label="Specify whether audio activity affects power management"/>
+ <int value="183"
+ label="Specify whether video activity affects power management"/>
+ <int value="184"
+ label="Percentage by which to scale the idle delay in presentation mode"/>
+ <int value="185"
+ label="Allow users to redeem offers through Chrome OS Registration."/>
+ <int value="186" label="Set the Terms of Service for a device-local account"/>
+ <int value="187" label="Enable deleting browser and download history"/>
+ <int value="188" label="Show accessibility options in system tray menu"/>
+ <int value="189"
+ label="Hide the web store from the new tab page and app launcher"/>
+ <int value="190" label="Allows sign in to Chrome"/>
+ <int value="191" label="System wide flags to be applied on Chrome start-up"/>
+ <int value="192" label="Limit device uptime by automatically rebooting"/>
+ <int value="193" label="Automatically reboot after update"/>
+ <int value="194" label="Public session for auto-login"/>
+ <int value="195" label="Public session auto-login timer"/>
+ <int value="196"
+ label="Set the restriction on the fetching of the Variations seed"/>
+ <int value="197" label="Idle warning delay when running on AC power"/>
+ <int value="198" label="Idle warning delay when running on battery power"/>
+</enum>
+
+<enum name="EnterprisePolicyInvalidations" type="int">
+ <int value="0" label="No payload"/>
+ <int value="1" label="Payload"/>
+</enum>
+
+<enum name="EnterprisePolicyLoadStatus" type="int">
+ <summary>
+ Status codes produced by the policy loaders that pull policy settings from
+ the platform-specific management infrastructure, such as Windows Group
+ Policy.
+ </summary>
+ <int value="0" label="STARTED">
+ Policy load attempt started. This gets logged for each policy load attempt
+ to get a baseline on the number of requests, and an arbitrary number of the
+ below status codes may get added in addition.
+ </int>
+ <int value="1" label="QUERY_FAILED">
+ System failed to determine whether there's policy.
+ </int>
+ <int value="2" label="NO_POLICY">No policy present.</int>
+ <int value="3" label="INACCCESSIBLE">
+ Data inaccessible, such as non-local policy file.
+ </int>
+ <int value="4" label="MISSING">
+ Data missing, such as policy file not present.
+ </int>
+ <int value="5" label="WOW64_REDIRECTION_DISABLED">
+ Trying with Wow64 redirection disabled.
+ </int>
+ <int value="6" label="READ_ERROR">
+ Data read error, for example file reading errors.
+ </int>
+ <int value="7" label="TOO_BIG">Data too large to process.</int>
+ <int value="8" label="PARSE_ERROR">Parse error.</int>
+</enum>
+
+<enum name="EnterprisePolicyRefresh" type="int">
+ <int value="0" label="Changed"/>
+ <int value="1" label="Changed; Invalidations disabled"/>
+ <int value="2" label="Unchanged"/>
+ <int value="3" label="Invalidated; Changed"/>
+ <int value="4" label="Invalidated; Unchanged"/>
+</enum>
+
+<enum name="EnterprisePolicyType" type="int">
+ <summary>
+ Result of Policy operations as defined in
+ chrome/browser/policy/enterprise_metrics.h.
+ </summary>
+ <int value="0" label="Load Succeeded">
+ A cached policy was successfully loaded from disk.
+ </int>
+ <int value="1" label="Load Failed">
+ Reading a cached policy from disk failed.
+ </int>
+ <int value="2" label="Fetch Requested">
+ A policy fetch request was sent to the DM server.
+ </int>
+ <int value="3" label="Fetch Request Failed">
+ The request was invalid, or the HTTP request failed.
+ </int>
+ <int value="4" label="Fetch Server Failed">
+ Error HTTP status received, or the DM server failed in another way.
+ </int>
+ <int value="5" label="Fetch Not Found">
+ Policy not found for the given user or device.
+ </int>
+ <int value="6" label="Fetch Invalid Token">
+ DM server didn't accept the token used in the request.
+ </int>
+ <int value="7" label="Fetch Response Received">
+ A response to the policy fetch request was received.
+ </int>
+ <int value="8" label="Fetch Bad Response">
+ The policy response message didn't contain a policy, or other data was
+ missing.
+ </int>
+ <int value="9" label="Fetch Invalid Policy">Failed to decode the policy.</int>
+ <int value="10" label="Fetch Bad Signature">
+ The device policy was rejected because its signature was invalid.
+ </int>
+ <int value="11" label="Fetch Timestamp In Future">
+ Rejected policy because its timestamp is in the future.
+ </int>
+ <int value="12" label="Fetch Non Enterprise Device">
+ Device policy rejected because the device is not managed.
+ </int>
+ <int value="13" label="Fetch User Mismatch">
+ The policy was provided for a username that is different from the device
+ owner, and the policy was rejected.
+ </int>
+ <int value="14" label="Fetch Other Failed">
+ The policy was rejected for another reason. Currently this can happen only
+ for device policies, when the SignedSettings fail to store or retrieve a
+ stored policy.
+ </int>
+ <int value="15" label="Fetch OK">The fetched policy was accepted.</int>
+ <int value="16" label="Fetch Not Modified">
+ The policy just fetched didn't have any changes compared to the cached
+ policy.
+ </int>
+ <int value="17" label="Store Succeeded">
+ Successfully cached a policy to disk.
+ </int>
+ <int value="18" label="Store Failed">Caching a policy to disk failed.</int>
+</enum>
+
+<enum name="ErrorCodesGetAdaptersAddresses" type="int">
+ <int value="8" label="ERROR_NOT_ENOUGH_MEMORY"/>
+ <int value="87" label="ERROR_INVALID_PARAMETER"/>
+ <int value="111" label="ERROR_BUFFER_OVERFLOW"/>
+ <int value="232" label="ERROR_NO_DATA"/>
+ <int value="1228" label="ERROR_ADDRESS_NOT_ASSOCIATED"/>
+</enum>
+
+<enum name="ErrorCodesGetaddrinfo_All" type="int">
+ <int value="1" label="EAI_BADFLAGS(L)"/>
+ <int value="2" label="EAI_NONAME(L) EAI_AGAIN(M)"/>
+ <int value="3" label="EAI_AGAIN(L) EAI_BADFLAGS(M)"/>
+ <int value="4" label="EAI_FAIL"/>
+ <int value="5" label="EAI_NODATA(L) EAI_FAMILY(M)"/>
+ <int value="6" label="WSA_INVALID_HANDLE EAI_FAMILY(L) EAI_MEMORY(M)"/>
+ <int value="7" label="EAI_SOCKTYPE(L) EAI_NODATA(M)"/>
+ <int value="8" label="WSA_NOT_ENOUGH_MEMORY EAI_SERVICE(L) EAI_NONAME(M)"/>
+ <int value="9" label="EAI_ADDRFAMILY EAI_SERVICE(M)"/>
+ <int value="10" label="EAI_MEMORY(L) EAI_SOCKTYPE(L)"/>
+ <int value="11" label="EAI_SYSTEM"/>
+ <int value="12" label="EAI_OVERFLOW"/>
+ <int value="10022" label="WSAEINVAL"/>
+ <int value="10044" label="WSAESOCKTNOSUPPORT"/>
+ <int value="10047" label="WSAEAFNOSUPPORT"/>
+ <int value="10093" label="WSANOTINITIALISED"/>
+ <int value="10109" label="WSA_TYPE_NOT_FOUND"/>
+ <int value="11001" label="WSA_HOST_NOT_FOUND"/>
+ <int value="11002" label="WSATRY_AGAIN"/>
+ <int value="11003" label="WSA_ANO_RECOVERY"/>
+ <int value="11004" label="WSANO_DATA"/>
+</enum>
+
+<enum name="ErrorCodesGetaddrinfo_Linux" type="int">
+ <int value="1" label="EAI_BADFLAGS"/>
+ <int value="2" label="EAI_NONAME"/>
+ <int value="3" label="EAI_AGAIN"/>
+ <int value="4" label="EAI_FAIL"/>
+ <int value="5" label="EAI_NODATA"/>
+ <int value="6" label="EAI_FAMILY"/>
+ <int value="7" label="EAI_SOCKTYPE"/>
+ <int value="8" label="EAI_SERVICE"/>
+ <int value="9" label="EAI_ADDRFAMILY"/>
+ <int value="10" label="EAI_MEMORY"/>
+ <int value="11" label="EAI_SYSTEM"/>
+ <int value="12" label="EAI_OVERFLOW"/>
+</enum>
+
+<enum name="ErrorCodesGetaddrinfo_Mac" type="int">
+ <int value="1" label="EAI_ADDRFAMILY"/>
+ <int value="2" label="EAI_AGAIN"/>
+ <int value="3" label="EAI_BADFLAGS"/>
+ <int value="4" label="EAI_FAIL"/>
+ <int value="5" label="EAI_FAMILY"/>
+ <int value="6" label="EAI_MEMORY"/>
+ <int value="7" label="EAI_NODATA"/>
+ <int value="8" label="EAI_NONAME"/>
+ <int value="9" label="EAI_SERVICE"/>
+ <int value="10" label="EAI_SOCKTYPE"/>
+ <int value="11" label="EAI_SYSTEM"/>
+ <int value="12" label="EAI_BADHINTS"/>
+ <int value="13" label="EAI_PROTOCOL"/>
+ <int value="14" label="EAI_OVERFLOW"/>
+</enum>
+
+<enum name="ErrorCodesGetaddrinfo_Win" type="int">
+ <int value="6" label="WSA_INVALID_HANDLE"/>
+ <int value="8" label="WSA_NOT_ENOUGH_MEMORY or EAI_SERVICE"/>
+ <int value="10022" label="WSAEINVAL"/>
+ <int value="10044" label="WSAESOCKTNOSUPPORT"/>
+ <int value="10047" label="WSAEAFNOSUPPORT"/>
+ <int value="10093" label="WSANOTINITIALISED"/>
+ <int value="10109" label="WSA_TYPE_NOT_FOUND"/>
+ <int value="11001" label="WSA_HOST_NOT_FOUND"/>
+ <int value="11002" label="WSATRY_AGAIN"/>
+ <int value="11003" label="WSA_ANO_RECOVERY"/>
+ <int value="11004" label="WSANO_DATA"/>
+</enum>
+
+<enum name="ExtensionBackgroundPageType" type="int">
+ <int value="0" label="None"/>
+ <int value="1" label="Persistent"/>
+ <int value="2" label="Event Page"/>
+</enum>
+
+<enum name="ExtensionDisabledUIUserResponse" type="int">
+ <int value="0" label="IGNORED"/>
+ <int value="1" label="REENABLE"/>
+ <int value="2" label="UNINSTALL"/>
+</enum>
+
+<enum name="ExtensionFileWriteResult" type="int">
+ <int value="0" label="SUCCESS"/>
+ <int value="1" label="CANT_CREATE_TEMP_CRX"/>
+ <int value="2" label="CANT_WRITE_CRX_DATA"/>
+ <int value="3" label="CANT_READ_CRX_FILE"/>
+</enum>
+
+<enum name="ExtensionFromWebstoreInconcistencyEnum" type="int">
+ <int value="0" label="Non-webstore update URL"/>
+ <int value="1" label="External install location"/>
+</enum>
+
+<enum name="ExtensionFunctions" type="int">
+<!-- Generated from ../../../chrome/browser/extensions/extension_function_histogram_value.h -->
+
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="WEBNAVIGATION_GETALLFRAMES"/>
+ <int value="2" label="BROWSINGDATA_REMOVEWEBSQL"/>
+ <int value="3" label="ALARMS_CREATE"/>
+ <int value="4" label="FILEBROWSERPRIVATE_REMOVEFILEWATCH"/>
+ <int value="5" label="COOKIES_GET"/>
+ <int value="6" label="FONTSETTINGS_GETMINIMUMFONTSIZE"/>
+ <int value="7" label="CHROMEOSINFOPRIVATE_GET"/>
+ <int value="8" label="BOOKMARKMANAGERPRIVATE_CUT"/>
+ <int value="9" label="TABS_CAPTUREVISIBLETAB"/>
+ <int value="10" label="MANAGEMENT_SETENABLED"/>
+ <int value="11" label="HISTORY_DELETEALL"/>
+ <int value="12" label="STORAGE_GET"/>
+ <int value="13" label="SOCKET_SETKEEPALIVE"/>
+ <int value="14" label="DOWNLOADS_CANCEL"/>
+ <int value="15" label="BOOKMARKS_CREATE"/>
+ <int value="16" label="BOOKMARKS_UPDATE"/>
+ <int value="17" label="FILEBROWSERPRIVATE_GETDRIVEFILES"/>
+ <int value="18" label="TERMINALPRIVATE_ONTERMINALRESIZE"/>
+ <int value="19" label="DELETED_FILEBROWSERPRIVATE_REQUESTDIRECTORYREFRESH"/>
+ <int value="20" label="BLUETOOTH_GETADAPTERSTATE"/>
+ <int value="21" label="FILEBROWSERPRIVATE_CANCELFILETRANSFERS"/>
+ <int value="22" label="FILEBROWSERPRIVATE_PINDRIVEFILE"/>
+ <int value="23" label="SOCKET_WRITE"/>
+ <int value="24" label="OMNIBOX_SETDEFAULTSUGGESTION"/>
+ <int value="25" label="TTS_SPEAK"/>
+ <int value="26" label="WALLPAPERPRIVATE_RESTOREMINIMIZEDWINDOWS"/>
+ <int value="27" label="BROWSINGDATA_REMOVEHISTORY"/>
+ <int value="28" label="DELETED_FILEBROWSERPRIVATE_ISFULLSCREEN"/>
+ <int value="29" label="AUTOTESTPRIVATE_LOGOUT"/>
+ <int value="30" label="EXPERIMENTAL_HISTORY_GETMOSTVISITED"/>
+ <int value="31" label="BLUETOOTH_DISCONNECT"/>
+ <int value="32" label="BLUETOOTH_SETOUTOFBANDPAIRINGDATA"/>
+ <int value="33" label="BOOKMARKMANAGERPRIVATE_CANPASTE"/>
+ <int value="34" label="AUTOTESTPRIVATE_RESTART"/>
+ <int value="35" label="USB_CLAIMINTERFACE"/>
+ <int value="36" label="MEDIAPLAYERPRIVATE_SETWINDOWHEIGHT"/>
+ <int value="37" label="PROCESSES_GETPROCESSINFO"/>
+ <int value="38" label="HISTORY_GETVISITS"/>
+ <int value="39" label="SOCKET_BIND"/>
+ <int value="40" label="TABS_MOVE"/>
+ <int value="41" label="SOCKET_DISCONNECT"/>
+ <int value="42" label="FILESYSTEM_GETWRITABLEENTRY"/>
+ <int value="43" label="SYNCFILESYSTEM_REQUESTFILESYSTEM"/>
+ <int value="44" label="COMMANDS_GETALL"/>
+ <int value="45" label="EXPERIMENTAL_DISCOVERY_REMOVESUGGESTION"/>
+ <int value="46" label="EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_SENDKEYBOARDEVENT"/>
+ <int value="47" label="BOOKMARKMANAGERPRIVATE_GETSUBTREE"/>
+ <int value="48" label="EXPERIMENTAL_RLZ_RECORDPRODUCTEVENT"/>
+ <int value="49" label="BOOKMARKS_GETRECENT"/>
+ <int value="50" label="APP_CURRENTWINDOWINTERNAL_SETBOUNDS"/>
+ <int value="51" label="CLOUDPRINTPRIVATE_SETUPCONNECTOR"/>
+ <int value="52" label="SERIAL_SETCONTROLSIGNALS"/>
+ <int value="53" label="FILEBROWSERPRIVATE_SETLASTMODIFIED"/>
+ <int value="54" label="IDLE_SETDETECTIONINTERVAL"/>
+ <int value="55" label="FILEBROWSERPRIVATE_GETFILETASKS"/>
+ <int value="56" label="WEBSTOREPRIVATE_GETSTORELOGIN"/>
+ <int value="57" label="SYSTEMPRIVATE_GETINCOGNITOMODEAVAILABILITY"/>
+ <int value="58" label="EXPERIMENTAL_IDLTEST_SENDARRAYBUFFERVIEW"/>
+ <int value="59" label="SOCKET_SETNODELAY"/>
+ <int value="60" label="APP_CURRENTWINDOWINTERNAL_SHOW"/>
+ <int value="61" label="WEBSTOREPRIVATE_GETBROWSERLOGIN"/>
+ <int value="62" label="EXPERIMENTAL_IDENTITY_GETAUTHTOKEN"/>
+ <int value="63" label="SYSTEMINFO_DISPLAY_GETDISPLAYINFO"/>
+ <int value="64" label="BROWSINGDATA_REMOVEPLUGINDATA"/>
+ <int value="65" label="SOCKET_LISTEN"/>
+ <int value="66" label="MEDIAGALLERIES_GETMEDIAFILESYSTEMS"/>
+ <int value="67" label="DOWNLOADS_OPEN"/>
+ <int value="68" label="TABS_EXECUTESCRIPT"/>
+ <int value="69" label="SYNCFILESYSTEM_GETUSAGEANDQUOTA"/>
+ <int value="70" label="INPUTMETHODPRIVATE_GET"/>
+ <int value="71" label="USB_CLOSEDEVICE"/>
+ <int value="72" label="TTS_STOP"/>
+ <int value="73" label="SERIAL_GETPORTS"/>
+ <int value="74" label="FILEBROWSERPRIVATE_CLEARDRIVECACHE"/>
+ <int value="75" label="SERIAL_GETCONTROLSIGNALS"/>
+ <int value="76" label="DEVELOPERPRIVATE_ENABLE"/>
+ <int value="77" label="FILEBROWSERPRIVATE_GETDRIVEFILEPROPERTIES"/>
+ <int value="78" label="USB_FINDDEVICES"/>
+ <int value="79" label="BOOKMARKMANAGERPRIVATE_DROP"/>
+ <int value="80" label="DELETED_FILEBROWSERPRIVATE_GETFILETRANSFERS"/>
+ <int value="81" label="INPUT_IME_SETMENUITEMS"/>
+ <int value="82" label="BOOKMARKS_EXPORT"/>
+ <int value="83" label="HISTORY_SEARCH"/>
+ <int value="84" label="TTSENGINE_SENDTTSEVENT"/>
+ <int value="85" label="EXPERIMENTAL_ACCESSIBILITY_GETALERTSFORTAB"/>
+ <int value="86" label="BOOKMARKS_IMPORT"/>
+ <int value="87" label="SYNCFILESYSTEM_DELETEFILESYSTEM"/>
+ <int value="88" label="DEBUGGER_SENDCOMMAND"/>
+ <int value="89" label="DEBUGGER_DETACH"/>
+ <int value="90" label="METRICSPRIVATE_RECORDSMALLCOUNT"/>
+ <int value="91" label="APP_CURRENTWINDOWINTERNAL_MINIMIZE"/>
+ <int value="92" label="DEVELOPERPRIVATE_AUTOUPDATE"/>
+ <int value="93" label="EXPERIMENTAL_DNS_RESOLVE"/>
+ <int value="94" label="EXPERIMENTAL_SYSTEMINFO_MEMORY_GET"/>
+ <int value="95" label="HISTORY_ADDURL"/>
+ <int value="96" label="TABS_GET"/>
+ <int value="97" label="BROWSERACTION_SETBADGETEXT"/>
+ <int value="98" label="TABS_RELOAD"/>
+ <int value="99" label="WINDOWS_CREATE"/>
+ <int value="100" label="DEVELOPERPRIVATE_LOADUNPACKED"/>
+ <int value="101" label="DELETED_DOWNLOADS_SETDESTINATION"/>
+ <int value="102" label="PROCESSES_GETPROCESSIDFORTAB"/>
+ <int value="103" label="BOOKMARKS_GETCHILDREN"/>
+ <int value="104" label="BROWSERACTION_GETTITLE"/>
+ <int value="105" label="TERMINALPRIVATE_OPENTERMINALPROCESS"/>
+ <int value="106" label="SERIAL_CLOSE"/>
+ <int value="107" label="CONTEXTMENUS_REMOVE"/>
+ <int value="108" label="FILEBROWSERPRIVATE_REQUESTFILESYSTEM"/>
+ <int value="109" label="ECHOPRIVATE_GETREGISTRATIONCODE"/>
+ <int value="110" label="TABS_GETCURRENT"/>
+ <int value="111" label="FONTSETTINGS_CLEARDEFAULTFIXEDFONTSIZE"/>
+ <int value="112" label="MEDIAPLAYERPRIVATE_CLOSEWINDOW"/>
+ <int value="113" label="WEBREQUESTINTERNAL_ADDEVENTLISTENER"/>
+ <int value="114" label="CLOUDPRINTPRIVATE_GETPRINTERS"/>
+ <int value="115" label="STORAGE_SET"/>
+ <int value="116" label="FONTSETTINGS_GETDEFAULTFONTSIZE"/>
+ <int value="117" label="EXTENSION_SETUPDATEURLDATA"/>
+ <int value="118" label="SERIAL_WRITE"/>
+ <int value="119" label="IDLE_QUERYSTATE"/>
+ <int value="120" label="EXPERIMENTAL_RLZ_GETACCESSPOINTRLZ"/>
+ <int value="121" label="WEBSTOREPRIVATE_SETSTORELOGIN"/>
+ <int value="122" label="PAGEACTIONS_ENABLEFORTAB"/>
+ <int value="123" label="COOKIES_SET"/>
+ <int value="124" label="CONTENTSETTINGS_SET"/>
+ <int value="125" label="CONTEXTMENUS_REMOVEALL"/>
+ <int value="126" label="TABS_INSERTCSS"/>
+ <int value="127" label="WEBREQUEST_HANDLERBEHAVIORCHANGED"/>
+ <int value="128" label="INPUT_IME_SETCURSORPOSITION"/>
+ <int value="129" label="OMNIBOX_SENDSUGGESTIONS"/>
+ <int value="130" label="SYSTEMINDICATOR_ENABLE"/>
+ <int value="131" label="EVENTS_GETRULES"/>
+ <int value="132" label="BOOKMARKMANAGERPRIVATE_COPY"/>
+ <int value="133" label="SOCKET_RECVFROM"/>
+ <int value="134" label="TABS_GETALLINWINDOW"/>
+ <int value="135" label="CONTEXTMENUS_UPDATE"/>
+ <int value="136" label="BOOKMARKS_SEARCH"/>
+ <int value="137" label="EXPERIMENTAL_APP_CLEARALLNOTIFICATIONS"/>
+ <int value="138" label="BLUETOOTH_GETLOCALOUTOFBANDPAIRINGDATA"/>
+ <int value="139" label="SYSTEMPRIVATE_GETUPDATESTATUS"/>
+ <int value="140" label="FONTSETTINGS_CLEARMINIMUMFONTSIZE"/>
+ <int value="141" label="DELETED_FILEBROWSERPRIVATE_GETFILELOCATIONS"/>
+ <int value="142" label="EXPERIMENTAL_DISCOVERY_SUGGEST"/>
+ <int value="143" label="FILEBROWSERPRIVATE_SETDEFAULTTASK"/>
+ <int value="144" label="BROWSERACTION_GETBADGETEXT"/>
+ <int value="145" label="APP_CURRENTWINDOWINTERNAL_HIDE"/>
+ <int value="146" label="SOCKET_CONNECT"/>
+ <int value="147" label="BOOKMARKS_GETSUBTREE"/>
+ <int value="148" label="HISTORY_DELETEURL"/>
+ <int value="149"
+ label="DELETED_EXPERIMENTAL_MEDIAGALLERIES_ASSEMBLEMEDIAFILE"/>
+ <int value="150" label="BOOKMARKMANAGERPRIVATE_STARTDRAG"/>
+ <int value="151" label="BROWSINGDATA_REMOVEPASSWORDS"/>
+ <int value="152" label="DOWNLOADS_DRAG"/>
+ <int value="153" label="INPUT_IME_SETCOMPOSITION"/>
+ <int value="154" label="METRICSPRIVATE_RECORDUSERACTION"/>
+ <int value="155" label="USB_RELEASEINTERFACE"/>
+ <int value="156" label="PAGEACTION_GETPOPUP"/>
+ <int value="157" label="SCRIPTBADGE_GETATTENTION"/>
+ <int value="158" label="FONTSETTINGS_GETFONTLIST"/>
+ <int value="159" label="PERMISSIONS_CONTAINS"/>
+ <int value="160" label="SCRIPTBADGE_GETPOPUP"/>
+ <int value="161" label="EXPERIMENTAL_ACCESSIBILITY_GETFOCUSEDCONTROL"/>
+ <int value="162" label="DEVELOPERPRIVATE_GETSTRINGS"/>
+ <int value="163" label="METRICSPRIVATE_RECORDMEDIUMCOUNT"/>
+ <int value="164" label="MANAGEMENT_GET"/>
+ <int value="165" label="PERMISSIONS_GETALL"/>
+ <int value="166" label="DOWNLOADS_SHOW"/>
+ <int value="167" label="EXPERIMENTAL_RLZ_CLEARPRODUCTSTATE"/>
+ <int value="168" label="TABS_REMOVE"/>
+ <int value="169" label="MANAGEMENT_GETPERMISSIONWARNINGSBYID"/>
+ <int value="170" label="WINDOWS_GET"/>
+ <int value="171" label="FILEBROWSERPRIVATE_EXECUTETASK"/>
+ <int value="172" label="TTS_GETVOICES"/>
+ <int value="173" label="MANAGEMENT_GETALL"/>
+ <int value="174" label="MANAGEMENT_GETPERMISSIONWARNINGSBYMANIFEST"/>
+ <int value="175" label="APP_CURRENTWINDOWINTERNAL_CLEARATTENTION"/>
+ <int value="176" label="AUTOTESTPRIVATE_SHUTDOWN"/>
+ <int value="177" label="FONTSETTINGS_CLEARDEFAULTFONTSIZE"/>
+ <int value="178" label="BOOKMARKS_GETTREE"/>
+ <int value="179" label="FILEBROWSERPRIVATE_SELECTFILES"/>
+ <int value="180" label="RUNTIME_GETBACKGROUNDPAGE"/>
+ <int value="181" label="DELETED_EXPERIMENTAL_RECORD_REPLAYURLS"/>
+ <int value="182" label="WEBSTOREPRIVATE_COMPLETEINSTALL"/>
+ <int value="183" label="DELETED_EXPERIMENTAL_SPEECHINPUT_START"/>
+ <int value="184" label="COOKIES_GETALL"/>
+ <int value="185" label="DOWNLOADS_GETFILEICON"/>
+ <int value="186" label="PAGEACTION_GETTITLE"/>
+ <int value="187" label="BROWSINGDATA_REMOVE"/>
+ <int value="188" label="SERIAL_OPEN"/>
+ <int value="189" label="FILESYSTEM_GETDISPLAYPATH"/>
+ <int value="190" label="FILEBROWSERPRIVATE_FORMATDEVICE"/>
+ <int value="191" label="BOOKMARKS_GET"/>
+ <int value="192" label="DELETED_MANAGEDMODEPRIVATE_GET"/>
+ <int value="193" label="ALARMS_CLEAR"/>
+ <int value="194" label="SYNCFILESYSTEM_GETFILESYNCSTATUS"/>
+ <int value="195" label="SOCKET_GETINFO"/>
+ <int value="196" label="WEBSTOREPRIVATE_INSTALLBUNDLE"/>
+ <int value="197" label="BROWSERACTION_ENABLE"/>
+ <int value="198" label="METRICSPRIVATE_RECORDMEDIUMTIME"/>
+ <int value="199" label="PAGEACTION_SETTITLE"/>
+ <int value="200" label="CLOUDPRINTPRIVATE_GETHOSTNAME"/>
+ <int value="201" label="CONTENTSETTINGS_GETRESOURCEIDENTIFIERS"/>
+ <int value="202" label="SOCKET_CREATE"/>
+ <int value="203" label="DEVELOPERPRIVATE_RELOAD"/>
+ <int value="204" label="FILEBROWSERPRIVATE_GETMOUNTPOINTS"/>
+ <int value="205" label="APP_RUNTIME_POSTINTENTRESPONSE"/>
+ <int value="206" label="DELETED_MANAGEDMODEPRIVATE_SETPOLICY"/>
+ <int value="207" label="WEBSTOREPRIVATE_BEGININSTALLWITHMANIFEST3"/>
+ <int value="208" label="WALLPAPERPRIVATE_SETWALLPAPER"/>
+ <int value="209" label="USB_CONTROLTRANSFER"/>
+ <int value="210" label="DELETED_EXPERIMENTAL_SPEECHINPUT_STOP"/>
+ <int value="211" label="USB_BULKTRANSFER"/>
+ <int value="212" label="FILEBROWSERPRIVATE_GETVOLUMEMETADATA"/>
+ <int value="213" label="PAGECAPTURE_SAVEASMHTML"/>
+ <int value="214" label="EXTENSION_ISALLOWEDINCOGNITOACCESS"/>
+ <int value="215" label="BROWSINGDATA_REMOVEAPPCACHE"/>
+ <int value="216" label="APP_CURRENTWINDOWINTERNAL_DRAWATTENTION"/>
+ <int value="217" label="METRICSPRIVATE_RECORDCOUNT"/>
+ <int value="218" label="USB_INTERRUPTTRANSFER"/>
+ <int value="219" label="TYPES_CHROMESETTING_CLEAR"/>
+ <int value="220" label="INPUT_IME_COMMITTEXT"/>
+ <int value="221" label="EXPERIMENTAL_IDLTEST_SENDARRAYBUFFER"/>
+ <int value="222" label="WALLPAPERPRIVATE_SETWALLPAPERIFEXISTS"/>
+ <int value="223" label="SOCKET_ACCEPT"/>
+ <int value="224" label="WEBNAVIGATION_GETFRAME"/>
+ <int value="225" label="EXPERIMENTAL_POWER_RELEASEKEEPAWAKE"/>
+ <int value="226" label="APP_CURRENTWINDOWINTERNAL_SETICON"/>
+ <int value="227" label="PUSHMESSAGING_GETCHANNELID"/>
+ <int value="228" label="EXPERIMENTAL_INFOBARS_SHOW"/>
+ <int value="229" label="INPUT_IME_SETCANDIDATEWINDOWPROPERTIES"/>
+ <int value="230" label="METRICSPRIVATE_RECORDPERCENTAGE"/>
+ <int value="231" label="TYPES_CHROMESETTING_GET"/>
+ <int value="232" label="WINDOWS_GETLASTFOCUSED"/>
+ <int value="233" label="DELETED_MANAGEDMODEPRIVATE_GETPOLICY"/>
+ <int value="234" label="STORAGE_CLEAR"/>
+ <int value="235" label="STORAGE_GETBYTESINUSE"/>
+ <int value="236" label="TABS_QUERY"/>
+ <int value="237" label="PAGEACTION_SETPOPUP"/>
+ <int value="238" label="DEVELOPERPRIVATE_INSPECT"/>
+ <int value="239" label="DOWNLOADS_SEARCH"/>
+ <int value="240" label="FONTSETTINGS_CLEARFONT"/>
+ <int value="241" label="WINDOWS_UPDATE"/>
+ <int value="242" label="BOOKMARKMANAGERPRIVATE_CANOPENNEWWINDOWS"/>
+ <int value="243" label="SERIAL_FLUSH"/>
+ <int value="244" label="BROWSERACTION_SETTITLE"/>
+ <int value="245" label="BOOKMARKMANAGERPRIVATE_CANEDIT"/>
+ <int value="246" label="WALLPAPERPRIVATE_SETCUSTOMWALLPAPER"/>
+ <int value="247" label="BOOKMARKS_REMOVE"/>
+ <int value="248" label="INPUT_IME_SETCANDIDATES"/>
+ <int value="249" label="TERMINALPRIVATE_CLOSETERMINALPROCESS"/>
+ <int value="250" label="HISTORY_DELETERANGE"/>
+ <int value="251" label="EXPERIMENTAL_IDLTEST_GETARRAYBUFFER"/>
+ <int value="252" label="TERMINALPRIVATE_SENDINPUT"/>
+ <int value="253" label="TABS_HIGHLIGHT"/>
+ <int value="254" label="BLUETOOTH_STARTDISCOVERY"/>
+ <int value="255" label="FILEBROWSERPRIVATE_SELECTFILE"/>
+ <int value="256" label="WINDOWS_GETCURRENT"/>
+ <int value="257" label="DEBUGGER_ATTACH"/>
+ <int value="258" label="WALLPAPERPRIVATE_SAVETHUMBNAIL"/>
+ <int value="259" label="INPUT_IME_KEYEVENTHANDLED"/>
+ <int value="260" label="FONTSETTINGS_SETDEFAULTFONTSIZE"/>
+ <int value="261" label="RUNTIME_REQUESTUPDATECHECK"/>
+ <int value="262" label="PAGEACTION_SETICON"/>
+ <int value="263" label="BROWSERACTION_SETBADGEBACKGROUNDCOLOR"/>
+ <int value="264" label="DEVELOPERPRIVATE_GETITEMSINFO"/>
+ <int value="265" label="BLUETOOTH_STOPDISCOVERY"/>
+ <int value="266" label="COOKIES_REMOVE"/>
+ <int value="267" label="EXPERIMENTAL_RLZ_SENDFINANCIALPING"/>
+ <int value="268" label="TABCAPTURE_GETCAPTUREDTABS"/>
+ <int value="269" label="WINDOWS_REMOVE"/>
+ <int value="270" label="WALLPAPERPRIVATE_GETOFFLINEWALLPAPERLIST"/>
+ <int value="271" label="BROWSERACTION_GETBADGEBACKGROUNDCOLOR"/>
+ <int value="272" label="PAGEACTIONS_DISABLEFORTAB"/>
+ <int value="273" label="DEVELOPERPRIVATE_ALLOWFILEACCESS"/>
+ <int value="274" label="FILEBROWSERPRIVATE_REMOVEMOUNT"/>
+ <int value="275" label="BLUETOOTH_CONNECT"/>
+ <int value="276" label="TABCAPTURE_CAPTURE"/>
+ <int value="277" label="NOTIFICATIONS_CREATE"/>
+ <int value="278" label="TABS_DUPLICATE"/>
+ <int value="279" label="BLUETOOTH_WRITE"/>
+ <int value="280" label="PAGEACTION_SHOW"/>
+ <int value="281" label="WALLPAPERPRIVATE_GETTHUMBNAIL"/>
+ <int value="282" label="DOWNLOADS_PAUSE"/>
+ <int value="283" label="PERMISSIONS_REQUEST"/>
+ <int value="284" label="TOPSITES_GET"/>
+ <int value="285" label="BROWSINGDATA_REMOVEDOWNLOADS"/>
+ <int value="286" label="BROWSINGDATA_REMOVELOCALSTORAGE"/>
+ <int value="287" label="FILEBROWSERHANDLERINTERNAL_SELECTFILE"/>
+ <int value="288" label="INPUT_IME_UPDATEMENUITEMS"/>
+ <int value="289" label="FILEBROWSERPRIVATE_GETSTRINGS"/>
+ <int value="290" label="CONTENTSETTINGS_GET"/>
+ <int value="291" label="FONTSETTINGS_SETDEFAULTFIXEDFONTSIZE"/>
+ <int value="292" label="EXPERIMENTAL_APP_NOTIFY"/>
+ <int value="293" label="METRICSPRIVATE_RECORDLONGTIME"/>
+ <int value="294" label="SOCKET_READ"/>
+ <int value="295" label="PROCESSES_TERMINATE"/>
+ <int value="296" label="METRICSPRIVATE_RECORDTIME"/>
+ <int value="297" label="BOOKMARKMANAGERPRIVATE_GETSTRINGS"/>
+ <int value="298" label="USB_ISOCHRONOUSTRANSFER"/>
+ <int value="299" label="PERMISSIONS_REMOVE"/>
+ <int value="300" label="MANAGEMENT_UNINSTALL"/>
+ <int value="301" label="I18N_GETACCEPTLANGUAGES"/>
+ <int value="302" label="MANAGEMENT_LAUNCHAPP"/>
+ <int value="303" label="INPUT_IME_CLEARCOMPOSITION"/>
+ <int value="304" label="ALARMS_GETALL"/>
+ <int value="305" label="DIAL_DISCOVERNOW"/>
+ <int value="306" label="TYPES_CHROMESETTING_SET"/>
+ <int value="307" label="BROWSERACTION_SETICON"/>
+ <int value="308" label="EXPERIMENTAL_ACCESSIBILITY_SETACCESSIBILITYENABLED"/>
+ <int value="309" label="FILEBROWSERPRIVATE_VIEWFILES"/>
+ <int value="310" label="BLUETOOTH_GETSERVICES"/>
+ <int value="311" label="TABS_UPDATE"/>
+ <int value="312" label="BROWSINGDATA_REMOVEFORMDATA"/>
+ <int value="313" label="DELETED_FILEBROWSERPRIVATE_RELOADDRIVE"/>
+ <int value="314" label="ALARMS_GET"/>
+ <int value="315" label="BROWSINGDATA_REMOVEINDEXEDDB"/>
+ <int value="316" label="FILEBROWSERPRIVATE_ADDFILEWATCH"/>
+ <int value="317" label="CONTENTSETTINGS_CLEAR"/>
+ <int value="318" label="FILEBROWSERPRIVATE_GETPREFERENCES"/>
+ <int value="319" label="BOOKMARKMANAGERPRIVATE_PASTE"/>
+ <int value="320" label="FILESYSTEM_ISWRITABLEENTRY"/>
+ <int value="321" label="USB_SETINTERFACEALTERNATESETTING"/>
+ <int value="322" label="FONTSETTINGS_SETMINIMUMFONTSIZE"/>
+ <int value="323" label="BROWSERACTION_GETPOPUP"/>
+ <int value="324" label="SOCKET_DESTROY"/>
+ <int value="325" label="BLUETOOTH_GETDEVICES"/>
+ <int value="326" label="ALARMS_CLEARALL"/>
+ <int value="327" label="FONTSETTINGS_GETDEFAULTFIXEDFONTSIZE"/>
+ <int value="328" label="FILEBROWSERPRIVATE_ZIPSELECTION"/>
+ <int value="329" label="SYSTEMINDICATOR_DISABLE"/>
+ <int value="330" label="SCRIPTBADGE_SETPOPUP"/>
+ <int value="331" label="EXTENSION_ISALLOWEDFILESCHEMEACCESS"/>
+ <int value="332" label="EXPERIMENTAL_IDENTITY_LAUNCHWEBAUTHFLOW"/>
+ <int value="333" label="FILEBROWSERPRIVATE_GETDRIVECONNECTIONSTATE"/>
+ <int value="334" label="TABS_DETECTLANGUAGE"/>
+ <int value="335" label="METRICSPRIVATE_RECORDVALUE"/>
+ <int value="336" label="BOOKMARKMANAGERPRIVATE_SORTCHILDREN"/>
+ <int value="337" label="SERIAL_READ"/>
+ <int value="338" label="APP_CURRENTWINDOWINTERNAL_MAXIMIZE"/>
+ <int value="339" label="EXPERIMENTAL_DISCOVERY_CLEARALLSUGGESTIONS"/>
+ <int value="340" label="DELETED_MANAGEDMODEPRIVATE_ENTER"/>
+ <int value="341" label="DELETED_FILEBROWSERPRIVATE_TRANSFERFILE"/>
+ <int value="342" label="BROWSERACTION_SETPOPUP"/>
+ <int value="343" label="TABS_GETSELECTED"/>
+ <int value="344" label="FONTSETTINGS_GETFONT"/>
+ <int value="345" label="BLUETOOTH_READ"/>
+ <int value="346" label="WEBREQUESTINTERNAL_EVENTHANDLED"/>
+ <int value="347" label="EVENTS_ADDRULES"/>
+ <int value="348" label="CONTEXTMENUS_CREATE"/>
+ <int value="349" label="MEDIAPLAYERPRIVATE_GETPLAYLIST"/>
+ <int value="350" label="DOWNLOADS_ERASE"/>
+ <int value="351" label="DELETED_EXPERIMENTAL_RECORD_CAPTUREURLS"/>
+ <int value="352" label="TTS_ISSPEAKING"/>
+ <int value="353" label="BOOKMARKS_REMOVETREE"/>
+ <int value="354" label="FILEBROWSERPRIVATE_SEARCHDRIVE"/>
+ <int value="355" label="EXPERIMENTAL_SYSTEMINFO_CPU_GET"/>
+ <int value="356" label="FILEBROWSERPRIVATE_SETPREFERENCES"/>
+ <int value="357" label="FONTSETTINGS_SETFONT"/>
+ <int value="358" label="SOCKET_GETNETWORKLIST"/>
+ <int value="359" label="BOOKMARKS_MOVE"/>
+ <int value="360" label="WALLPAPERPRIVATE_MINIMIZEINACTIVEWINDOWS"/>
+ <int value="361" label="STORAGE_REMOVE"/>
+ <int value="362" label="AUTOTESTPRIVATE_LOGINSTATUS"/>
+ <int value="363" label="TABS_CREATE"/>
+ <int value="364" label="FILEBROWSERPRIVATE_CANCELDIALOG"/>
+ <int value="365" label="BROWSINGDATA_REMOVECOOKIES"/>
+ <int value="366" label="FILESYSTEM_CHOOSEENTRY"/>
+ <int value="367" label="MEDIAPLAYERPRIVATE_PLAY"/>
+ <int value="368" label="WEBSTOREPRIVATE_GETWEBGLSTATUS"/>
+ <int value="369" label="SOCKET_SENDTO"/>
+ <int value="370" label="BROWSINGDATA_REMOVEFILESYSTEMS"/>
+ <int value="371" label="WALLPAPERPRIVATE_GETSTRINGS"/>
+ <int value="372" label="BROWSINGDATA_REMOVECACHE"/>
+ <int value="373" label="BOOKMARKMANAGERPRIVATE_RECORDLAUNCH"/>
+ <int value="374" label="BROWSERACTION_DISABLE"/>
+ <int value="375" label="DELETED_EXPERIMENTAL_SPEECHINPUT_ISRECORDING"/>
+ <int value="376" label="APP_WINDOW_CREATE"/>
+ <int value="377" label="RUNTIME_RELOAD"/>
+ <int value="378" label="EXPERIMENTAL_POWER_REQUESTKEEPAWAKE"/>
+ <int value="379" label="SYSTEMINDICATOR_SETICON"/>
+ <int value="380" label="FILEBROWSERPRIVATE_ADDMOUNT"/>
+ <int value="381" label="APP_CURRENTWINDOWINTERNAL_FOCUS"/>
+ <int value="382" label="EVENTS_REMOVERULES"/>
+ <int value="383" label="DOWNLOADS_DOWNLOAD"/>
+ <int value="384" label="WINDOWS_GETALL"/>
+ <int value="385" label="DELETED_FILEBROWSERPRIVATE_TOGGLEFULLSCREEN"/>
+ <int value="386" label="APP_CURRENTWINDOWINTERNAL_RESTORE"/>
+ <int value="387" label="WEBSOCKETPROXYPRIVATE_GETPASSPORTFORTCP"/>
+ <int value="388" label="PAGEACTION_HIDE"/>
+ <int value="389" label="EXPERIMENTAL_SYSTEMINFO_STORAGE_GET"/>
+ <int value="390" label="DOWNLOADS_ACCEPTDANGER"/>
+ <int value="391" label="WEBSOCKETPROXYPRIVATE_GETURLFORTCP"/>
+ <int value="392" label="FILEBROWSERPRIVATE_GETSIZESTATS"/>
+ <int value="393" label="DOWNLOADS_RESUME"/>
+ <int value="394" label="COOKIES_GETALLCOOKIESTORES"/>
+ <int value="395" label="MEDIAGALLERIESPRIVATE_ADDGALLERYWATCH"/>
+ <int value="396" label="MEDIAGALLERIESPRIVATE_REMOVEGALLERYWATCH"/>
+ <int value="397" label="WEBVIEW_EXECUTESCRIPT"/>
+ <int value="398" label="NOTIFICATIONS_UPDATE"/>
+ <int value="399" label="NOTIFICATIONS_CLEAR"/>
+ <int value="400" label="SESSIONRESTORE_GETRECENTLYCLOSED"/>
+ <int value="401" label="SESSIONRESTORE_RESTORE"/>
+ <int value="402" label="MANAGEMENT_UNINSTALLSELF"/>
+ <int value="403" label="ECHOPRIVATE_GETOOBETIMESTAMP"/>
+ <int value="404" label="FILEBROWSERPRIVATE_VALIDATEPATHNAMELENGTH"/>
+ <int value="405" label="BROWSINGDATA_SETTINGS"/>
+ <int value="406" label="WEBSTOREPRIVATE_GETISLAUNCHERENABLED"/>
+ <int value="407" label="NETWORKINGPRIVATE_GETPROPERTIES"/>
+ <int value="408" label="NETWORKINGPRIVATE_GETVISIBLENETWORKS"/>
+ <int value="409" label="NETWORKINGPRIVATE_STARTCONNECT"/>
+ <int value="410" label="NETWORKINGPRIVATE_STARTDISCONNECT"/>
+ <int value="411" label="MEDIAGALLERIESPRIVATE_GETALLGALLERYWATCH"/>
+ <int value="412" label="MEDIAGALLERIESPRIVATE_REMOVEALLGALLERYWATCH"/>
+ <int value="413" label="FILEBROWSERPRIVATE_SEARCHDRIVEMETADATA"/>
+ <int value="414" label="ECHOPRIVATE_CHECKALLOWREDEEMOFFERS"/>
+ <int value="415" label="MEDIAGALLERIESPRIVATE_EJECTDEVICE"/>
+ <int value="416" label="FILEBROWSERPRIVATE_LOGOUTUSER"/>
+ <int value="417" label="DEVELOPERPRIVATE_CHOOSEPATH"/>
+ <int value="418" label="DEVELOPERPRIVATE_PACKDIRECTORY"/>
+ <int value="419" label="NETWORKINGPRIVATE_VERIFYDESTINATION"/>
+ <int value="420" label="NETWORKINGPRIVATE_VERIFYANDENCRYPTCREDENTIALS"/>
+ <int value="421" label="NETWORKINGPRIVATE_VERIFYANDENCRYPTDATA"/>
+ <int value="422" label="DEVELOPERPRIVATE_RESTART"/>
+ <int value="423" label="DEVELOPERPRIVATE_ALLOWINCOGNITO"/>
+ <int value="424" label="INPUT_IME_DELETESURROUNDINGTEXT"/>
+ <int value="425" label="DELETED_FILEBROWSERPRIVATE_OPENNEWWINDOW"/>
+ <int value="426" label="CLOUDPRINTPRIVATE_GETCLIENTID"/>
+ <int value="427" label="ECHOPRIVATE_GETUSERCONSENT"/>
+ <int value="428" label="SYNCFILESYSTEM_SETCONFLICTRESOLUTIONPOLICY"/>
+ <int value="429" label="SYNCFILESYSTEM_GETCONFLICTRESOLUTIONPOLICY"/>
+ <int value="430" label="NETWORKINGPRIVATE_SETPROPERTIES"/>
+ <int value="431" label="NETWORKINGPRIVATE_GETSTATE"/>
+ <int value="432" label="POWER_REQUESTKEEPAWAKE"/>
+ <int value="433" label="POWER_RELEASEKEEPAWAKE"/>
+ <int value="434" label="WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT"/>
+ <int value="435" label="DOWNLOADSINTERNAL_DETERMINEFILENAME"/>
+ <int value="436" label="SYNCFILESYSTEM_GETFILESYNCSTATUSES"/>
+ <int value="437" label="MEDIAGALLERIESPRIVATE_GETHANDLERS"/>
+ <int value="438" label="WALLPAPERPRIVATE_RESETWALLPAPER"/>
+ <int value="439" label="DEVELOPERPRIVATE_PERMISSIONS"/>
+ <int value="440" label="WEBSTOREPRIVATE_ENABLEAPPLAUNCHER"/>
+ <int value="441" label="APP_CURRENTWINDOWINTERNAL_FULLSCREEN"/>
+ <int value="442" label="DEVELOPERPRIVATE_LOADUNPACKEDCROS"/>
+ <int value="443" label="NETWORKINGPRIVATE_REQUESTNETWORKSCAN"/>
+ <int value="444" label="ENTERPRISE_PLATFORMKEYSPRIVATE_CHALLENGEMACHINEKEY"/>
+ <int value="445" label="ENTERPRISE_PLATFORMKEYSPRIVATE_CHALLENGEUSERKEY"/>
+ <int value="446" label="DEVELOPERPRIVATE_LOADPROJECTTOSYNCFS"/>
+ <int value="447" label="DEVELOPERPRIVATE_GETPROJECTSINFO"/>
+ <int value="448" label="DEVELOPERPRIVATE_LOADPROJECT"/>
+ <int value="449" label="COMMANDLINEPRIVATE_HASSWITCH"/>
+ <int value="450" label="NETWORKINGPRIVATE_GETMANAGEDPROPERTIES"/>
+ <int value="451" label="LOCATION_WATCHLOCATION"/>
+ <int value="452" label="LOCATION_CLEARWATCH"/>
+ <int value="453" label="BLUETOOTH_ADDPROFILE"/>
+ <int value="454" label="BLUETOOTH_REMOVEPROFILE"/>
+ <int value="455" label="BLUETOOTH_GETPROFILES"/>
+ <int value="456" label="EXPERIMENTAL_IDENTITY_REMOVECACHEDAUTHTOKEN"/>
+ <int value="457" label="AUDIO_GETINFO"/>
+ <int value="458" label="AUDIO_SETACTIVEDEVICES"/>
+ <int value="459" label="AUDIO_SETPROPERTIES"/>
+ <int value="460" label="USB_RESETDEVICE"/>
+ <int value="461" label="SOCKET_MULTICAST_JOIN_GROUP"/>
+ <int value="462" label="SOCKET_MULTICAST_LEAVE_GROUP"/>
+ <int value="463" label="SOCKET_MULTICAST_SET_TIME_TO_LIVE"/>
+ <int value="464" label="SOCKET_MULTICAST_SET_LOOPBACK_MODE"/>
+ <int value="465" label="SOCKET_MULTICAST_GET_JOINED_GROUPS"/>
+ <int value="466"
+ label="EXPERIMENTAL_ACCESSIBILITY_SETNATIVEACCESSIBILITYENABLED"/>
+ <int value="467" label="RUNTIME_GETPLATFORMINFO"/>
+ <int value="468" label="WEBVIEW_INSERTCSS"/>
+ <int value="469" label="METRICSPRIVATE_GETISCRASHRECORDINGENABLED"/>
+ <int value="470" label="IDENTITYPRIVATE_GETRESOURCES"/>
+ <int value="471" label="NOTIFICATIONS_GET_ALL"/>
+ <int value="472" label="USB_LISTINTERFACES"/>
+ <int value="473" label="FILESYSTEM_RETAINENTRY"/>
+ <int value="474" label="FILESYSTEM_ISRESTORABLE"/>
+ <int value="475" label="FILESYSTEM_RESTOREENTRY"/>
+ <int value="476" label="RUNTIME_SETUNINSTALLURL"/>
+ <int value="477" label="INPUTMETHODPRIVATE_STARTIME"/>
+ <int value="478" label="MUSICMANAGERPRIVATE_GETDEVICEID"/>
+ <int value="479" label="TTS_PAUSE"/>
+ <int value="480" label="TTS_RESUME"/>
+ <int value="481" label="SYSTEMINFO_CPU_GET"/>
+ <int value="482" label="EXPERIMENTAL_SYSTEMINFO_STORAGE_ADDWATCH"/>
+ <int value="483" label="EXPERIMENTAL_SYSTEMINFO_STORAGE_REMOVEWATCH"/>
+ <int value="484" label="EXPERIMENTAL_SYSTEMINFO_STORAGE_GETALLWATCH"/>
+ <int value="485" label="EXPERIMENTAL_SYSTEMINFO_STORAGE_REMOVEALLWATCH"/>
+ <int value="486" label="SYSTEMINFO_MEMORY_GET"/>
+ <int value="487" label="ACTIVITYLOGPRIVATE_GETEXTENSIONACTIVITIES"/>
+ <int value="488" label="RUNTIME_GETPACKAGEDIRECTORYENTRY"/>
+ <int value="489" label="SYSTEMINFO_DISPLAY_SETDISPLAYPROPERTIES"/>
+ <int value="490" label="FEEDBACKPRIVATE_GETUSEREMAIL"/>
+ <int value="491" label="FEEDBACKPRIVATE_GETSYSTEMINFORMATION"/>
+ <int value="492" label="FEEDBACKPRIVATE_SENDFEEDBACK"/>
+ <int value="493" label="EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_INSERTTEXT"/>
+ <int value="494" label="DIAGNOSTICS_SENDPACKET"/>
+ <int value="495" label="METRICSPRIVATE_GETFIELDTRIAL"/>
+ <int value="496" label="FILEBROWSERPRIVATE_ZOOM"/>
+ <int value="497" label="WEBVIEW_GO"/>
+ <int value="498" label="WEBSTOREPRIVATE_ISININCOGNITOMODEFUNCTION"/>
+ <int value="499" label="FILEBROWSERPRIVATE_REQUESTACCESSTOKEN"/>
+ <int value="500" label="WEBVIEW_STOP"/>
+ <int value="501" label="WEBVIEW_RELOAD"/>
+ <int value="502" label="WEBVIEW_TERMINATE"/>
+ <int value="503" label="TYPES_PRIVATE_CHROMEDIRECTSETTING_GET"/>
+ <int value="504" label="TYPES_PRIVATE_CHROMEDIRECTSETTING_SET"/>
+ <int value="505" label="TYPES_PRIVATE_CHROMEDIRECTSETTING_CLEAR"/>
+ <int value="506" label="SYSTEM_CPU_GETINFO"/>
+ <int value="507" label="SYSTEM_DISPLAY_GETINFO"/>
+ <int value="508" label="SYSTEM_DISPLAY_SETDISPLAYPROPERTIES"/>
+ <int value="509" label="SYSTEM_MEMORY_GETINFO"/>
+ <int value="510" label="SYSTEM_STORAGE_GETINFO"/>
+ <int value="511" label="SYSTEM_STORAGE_EJECTDEVICE"/>
+ <int value="512" label="SYSTEM_STORAGE_ADDAVAILABLECAPACITYWATCH"/>
+ <int value="513" label="SYSTEM_STORAGE_REMOVEAVAILABLECAPACITYWATCH"/>
+ <int value="514" label="SYSTEM_STORAGE_GETALLAVAILABLECAPACITYWATCHES"/>
+ <int value="515" label="SYSTEM_STORAGE_REMOVEALLAVAILABLECAPACITYWATCHES"/>
+ <int value="516" label="INFOBARS_SHOW"/>
+ <int value="517" label="EXPERIMENTAL_INPUT_VIRTUALKEYBOARD_MOVECURSOR"/>
+</enum>
+
+<enum name="ExtensionInstallCause" type="int">
+ <int value="0" label="INSTALL_CAUSE_UNSET"/>
+ <int value="1" label="INSTALL_CAUSE_USER_DOWNLOAD"/>
+ <int value="2" label="INSTALL_CAUSE_UPDATE"/>
+ <int value="3" label="INSTALL_CAUSE_EXTERNAL_FILE"/>
+ <int value="4" label="INSTALL_CAUSE_AUTOMATION"/>
+</enum>
+
+<enum name="ExtensionLaunchType" type="int">
+ <int value="0" label="PINNED"/>
+ <int value="1" label="REGULAR"/>
+ <int value="2" label="FULLSCREEN"/>
+</enum>
+
+<enum name="ExtensionLocation" type="int">
+ <int value="0" label="INVALID"/>
+ <int value="1" label="INTERNAL"/>
+ <int value="2" label="EXTERNAL_PREF"/>
+ <int value="3" label="EXTERNAL_REGISTRY"/>
+ <int value="4" label="LOAD"/>
+ <int value="5" label="COMPONENT"/>
+ <int value="6" label="EXTERNAL_PREF_DOWNLOAD"/>
+ <int value="7" label="EXTERNAL_POLICY_DOWNLOAD"/>
+</enum>
+
+<enum name="ExtensionPermission" type="int">
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="NONE"/>
+ <int value="2" label="BOOKMARKS"/>
+ <int value="3" label="GEOLOCATION"/>
+ <int value="4" label="BROWSING_HISTORY"/>
+ <int value="5" label="TABS"/>
+ <int value="6" label="MANAGEMENT"/>
+ <int value="7" label="DEBUGGER"/>
+ <int value="8" label="1_HOST"/>
+ <int value="9" label="2_HOSTS"/>
+ <int value="10" label="3_HOSTS"/>
+ <int value="11" label="4_OR_MORE_HOSTS"/>
+ <int value="12" label="ALL_HOSTS"/>
+ <int value="13" label="FULL_ACCESS"/>
+ <int value="14" label="CLIPBOARD"/>
+ <int value="15" label="TTS_ENGINE"/>
+ <int value="16" label="CONTENT_SETTINGS"/>
+ <int value="17" label="PRIVACY"/>
+ <int value="18" label="MANAGED_MODE"/>
+ <int value="19" label="INPUT"/>
+ <int value="20" label="AUDIO_CAPTURE"/>
+ <int value="21" label="VIDEO_CAPTURE"/>
+ <int value="22" label="DOWNLOADS"/>
+ <int value="23" label="FILE_SYSTEM_WRITE"/>
+ <int value="24" label="ALL_MEDIA_GALLERIES"/>
+ <int value="25" label="SERIAL"/>
+ <int value="26" label="SOCKET_ANY_HOST"/>
+ <int value="27" label="SOCKET_DOMAIN_HOSTS"/>
+ <int value="28" label="SOCKET_SPECIFIC_HOSTS"/>
+</enum>
+
+<enum name="ExtensionType" type="int">
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="EXTENSION"/>
+ <int value="2" label="THEME"/>
+ <int value="3" label="USER_SCRIPT"/>
+ <int value="4" label="HOSTED_APP"/>
+ <int value="5" label="LEGACY_PACKAGED_APP"/>
+ <int value="6" label="PLATFORM_APP"/>
+</enum>
+
+<enum name="ExtensionUnpackFailureReason" type="int">
+ <summary>
+ Reasons the sandboxed extension unpacker can fail. See enum FailureReason
+ in src/chrome/browser/extensions/sandboxed_extension_unpacker.h .
+ </summary>
+ <int value="0" label="COULD_NOT_GET_TEMP_DIRECTORY"/>
+ <int value="1" label="COULD_NOT_CREATE_TEMP_DIRECTORY"/>
+ <int value="2" label="FAILED_TO_COPY_EXTENSION_FILE_TO_TEMP_DIRECTORY"/>
+ <int value="3" label="COULD_NOT_GET_SANDBOX_FRIENDLY_PATH"/>
+ <int value="4" label="COULD_NOT_LOCALIZE_EXTENSION"/>
+ <int value="5" label="INVALID_MANIFEST"/>
+ <int value="6" label="UNPACKER_CLIENT_FAILED"/>
+ <int value="7" label="UTILITY_PROCESS_CRASHED_WHILE_TRYING_TO_INSTALL"/>
+ <int value="8" label="CRX_FILE_NOT_READABLE"/>
+ <int value="9" label="CRX_HEADER_INVALID"/>
+ <int value="10" label="CRX_MAGIC_NUMBER_INVALID"/>
+ <int value="11" label="CRX_VERSION_NUMBER_INVALID"/>
+ <int value="12" label="CRX_EXCESSIVELY_LARGE_KEY_OR_SIGNATURE"/>
+ <int value="13" label="CRX_ZERO_KEY_LENGTH"/>
+ <int value="14" label="CRX_ZERO_SIGNATURE_LENGTH"/>
+ <int value="15" label="CRX_PUBLIC_KEY_INVALID"/>
+ <int value="16" label="CRX_SIGNATURE_INVALID"/>
+ <int value="17" label="CRX_SIGNATURE_VERIFICATION_INITIALIZATION_FAILED"/>
+ <int value="18" label="CRX_SIGNATURE_VERIFICATION_FAILED"/>
+ <int value="19" label="ERROR_SERIALIZING_MANIFEST_JSON"/>
+ <int value="20" label="ERROR_SAVING_MANIFEST_JSON"/>
+ <int value="21" label="COULD_NOT_READ_IMAGE_DATA_FROM_DISK"/>
+ <int value="22" label="DECODED_IMAGES_DO_NOT_MATCH_THE_MANIFEST"/>
+ <int value="23" label="INVALID_PATH_FOR_BROWSER_IMAGE"/>
+ <int value="24" label="ERROR_REMOVING_OLD_IMAGE_FILE"/>
+ <int value="25" label="INVALID_PATH_FOR_BITMAP_IMAGE"/>
+ <int value="26" label="ERROR_RE_ENCODING_THEME_IMAGE"/>
+ <int value="27" label="ERROR_SAVING_THEME_IMAGE"/>
+ <int value="28" label="COULD_NOT_READ_CATALOG_DATA_FROM_DISK"/>
+ <int value="29" label="INVALID_CATALOG_DATA"/>
+ <int value="30" label="INVALID_PATH_FOR_CATALOG"/>
+ <int value="31" label="ERROR_SERIALIZING_CATALOG"/>
+ <int value="32" label="ERROR_SAVING_CATALOG"/>
+</enum>
+
+<enum name="ExternalDeviceAction" type="int">
+ <int value="0" label="Import to Drive"/>
+ <int value="1" label="View files"/>
+ <int value="2" label="View files (automatically)"/>
+ <int value="3" label="Watch video"/>
+ <int value="4" label="Error"/>
+ <int value="5" label="Close (no action)"/>
+</enum>
+
+<enum name="ExternalItemState" type="int">
+ <int value="0" label="DEPRECATED_DISABLED"/>
+ <int value="1" label="DEPRECATED_ENABLED"/>
+ <int value="2" label="DISABLED (in webstore)"/>
+ <int value="3" label="ENABLED (in webstore)"/>
+ <int value="4" label="DISABLED (not in webstore)"/>
+ <int value="5" label="ENABLED (not in webstore)"/>
+</enum>
+
+<enum name="Exynos5250LotIdEnum" type="int">
+ <int value="0" label="Fused device"/>
+ <int value="1" label="Generic unfused device"/>
+ <int value="2" label="Unfused; lot ID NZVPU"/>
+ <int value="3" label="Unfused; lot ID NZVR7"/>
+</enum>
+
+<enum name="FallbackSSLVersion" type="int">
+ <int value="0" label="FALLBACK_NONE">SSL version fallback did not occur.</int>
+ <int value="1" label="FALLBACK_SSL3">Fell back on SSL 3.0.</int>
+ <int value="2" label="FALLBACK_TLS1">Fell back on TLS 1.0.</int>
+ <int value="3" label="FALLBACK_TLS1_1">Fell back on TLS 1.1.</int>
+</enum>
+
+<enum name="FeatureObserver" type="int">
+<!-- See http://src.chromium.org/viewvc/blink/trunk/Source/core/page/UseCounter.h -->
+
+ <int value="0" label="PageDestruction"/>
+ <int value="1" label="LegacyNotifications"/>
+ <int value="2" label="MultipartMainResource"/>
+ <int value="3" label="PrefixedIndexedDB"/>
+ <int value="4" label="WorkerStart"/>
+ <int value="5" label="SharedWorkerStart"/>
+ <int value="6" label="LegacyWebAudioNoteOn"/>
+ <int value="7" label="WebAudioStart"/>
+ <int value="8" label="PrefixedContentSecurityPolicy"/>
+ <int value="9" label="UnprefixedIndexedDB"/>
+ <int value="10" label="OpenWebDatabase"/>
+ <int value="11" label="LegacyHTMLNotifications"/>
+ <int value="12" label="LegacyTextNotifications"/>
+ <int value="13" label="UnprefixedRequestAnimationFrame"/>
+ <int value="14" label="PrefixedRequestAnimationFrame"/>
+ <int value="15" label="ContentSecurityPolicy"/>
+ <int value="16" label="ContentSecurityPolicyReportOnly"/>
+ <int value="17" label="PrefixedContentSecurityPolicyReportOnly"/>
+ <int value="18" label="PrefixedTransitionEndEvent"/>
+ <int value="19" label="UnprefixedTransitionEndEvent"/>
+ <int value="20" label="PrefixedAndUnprefixedTransitionEndEvent"/>
+ <int value="21" label="AutoFocusAttribute"/>
+ <int value="22" label="DeprecatedAutoSaveAttribute"/>
+ <int value="23" label="DataListElement"/>
+ <int value="24" label="FormAttribute"/>
+ <int value="25" label="IncrementalAttribute"/>
+ <int value="26" label="InputTypeColor"/>
+ <int value="27" label="InputTypeDate"/>
+ <int value="28" label="InputTypeDateTime"/>
+ <int value="29" label="InputTypeDateTimeFallback"/>
+ <int value="30" label="InputTypeDateTimeLocal"/>
+ <int value="31" label="InputTypeEmail"/>
+ <int value="32" label="InputTypeMonth"/>
+ <int value="33" label="InputTypeNumber"/>
+ <int value="34" label="InputTypeRange"/>
+ <int value="35" label="InputTypeSearch"/>
+ <int value="36" label="InputTypeTel"/>
+ <int value="37" label="InputTypeTime"/>
+ <int value="38" label="InputTypeURL"/>
+ <int value="39" label="InputTypeWeek"/>
+ <int value="40" label="InputTypeWeekFallback"/>
+ <int value="41" label="ListAttribute"/>
+ <int value="42" label="MaxAttribute"/>
+ <int value="43" label="MinAttribute"/>
+ <int value="44" label="PatternAttribute"/>
+ <int value="45" label="PlaceholderAttribute"/>
+ <int value="46" label="PrecisionAttribute"/>
+ <int value="47" label="PrefixedDirectoryAttribute"/>
+ <int value="48" label="PrefixedSpeechAttribute"/>
+ <int value="49" label="RequiredAttribute"/>
+ <int value="50" label="ResultsAttribute"/>
+ <int value="51" label="StepAttribute"/>
+ <int value="52" label="PageVisits"/>
+ <int value="53" label="HTMLMarqueeElement"/>
+ <int value="54" label="Unused: CSSOverflowMarquee"/>
+ <int value="55" label="Reflection"/>
+ <int value="56" label="CursorVisibility"/>
+ <int value="57" label="StorageInfo"/>
+ <int value="58" label="XFrameOptions"/>
+ <int value="59" label="XFrameOptionsSameOrigin"/>
+ <int value="60" label="XFrameOptionsSameOriginWithBadAncestorChain"/>
+ <int value="61" label="DeprecatedFlexboxWebContent"/>
+ <int value="62" label="DeprecatedFlexboxChrome"/>
+ <int value="63" label="DeprecatedFlexboxChromeExtension"/>
+ <int value="64" label="SVGTRefElement"/>
+ <int value="65" label="UnprefixedPerformanceTimeline"/>
+ <int value="66" label="PrefixedPerformanceTimeline"/>
+ <int value="67" label="UnprefixedUserTiming"/>
+ <int value="68" label="PrefixedUserTiming"/>
+ <int value="69" label="WindowEvent"/>
+ <int value="70" label="ContentSecurityPolicyWithBaseElement"/>
+ <int value="71" label="PrefixedMediaAddKey"/>
+ <int value="72" label="PrefixedMediaGenerateKeyRequest"/>
+ <int value="73" label="WebAudioLooping"/>
+ <int value="74" label="DocumentClear"/>
+ <int value="75" label="PrefixedTransitionMediaFeature"/>
+ <int value="76" label="SVGFontElement"/>
+ <int value="77" label="XMLDocument"/>
+ <int value="78" label="XSLProcessingInstruction"/>
+ <int value="79" label="XSLTProcessor"/>
+ <int value="80" label="SVGSwitchElement"/>
+ <int value="81" label="PrefixedDocumentRegister"/>
+ <int value="82" label="HTMLShadowElementOlderShadowRoot"/>
+ <int value="83" label="Document.all()"/>
+ <int value="84" label="FormElement"/>
+ <int value="85" label="DemotedFormElement"/>
+ <int value="86" label="CaptureAttributeAsEnum"/>
+ <int value="87" label="ShadowDOMPrefixedPseudo"/>
+ <int value="88" label="ShadowDOMPrefixedCreateShadowRoot"/>
+ <int value="89" label="ShadowDOMPrefixedShadowRoot"/>
+ <int value="90" label="SVGAnimationElement"/>
+ <int value="91" label="KeyboardEventKeyLocation"/>
+ <int value="92" label="CaptureEvents"/>
+ <int value="93" label="ReleaseEvents"/>
+ <int value="94" label="CSSDisplayRunIn"/>
+ <int value="95" label="CSSDisplayCompact"/>
+ <int value="96" label="LineClamp"/>
+ <int value="97" label="SubFrameBeforeUnloadRegistered"/>
+ <int value="98" label="SubFrameBeforeUnloadFired"/>
+ <int value="99" label="CSSPseudoElementPrefixedDistributed"/>
+</enum>
+
+<enum name="FFmpegCodecs" type="int">
+ <int value="0" label="NONE"/>
+ <int value="1" label="MPEG1VIDEO"/>
+ <int value="2" label="MPEG2VIDEO"/>
+ <int value="3" label="MPEG2VIDEO_XVMC"/>
+ <int value="4" label="H261"/>
+ <int value="5" label="H263"/>
+ <int value="6" label="RV10"/>
+ <int value="7" label="RV20"/>
+ <int value="8" label="MJPEG"/>
+ <int value="9" label="MJPEGB"/>
+ <int value="10" label="LJPEG"/>
+ <int value="11" label="SP5X"/>
+ <int value="12" label="JPEGLS"/>
+ <int value="13" label="MPEG4"/>
+ <int value="14" label="RAWVIDEO"/>
+ <int value="15" label="MSMPEG4V1"/>
+ <int value="16" label="MSMPEG4V2"/>
+ <int value="17" label="MSMPEG4V3"/>
+ <int value="18" label="WMV1"/>
+ <int value="19" label="WMV2"/>
+ <int value="20" label="H263P"/>
+ <int value="21" label="H263I"/>
+ <int value="22" label="FLV1"/>
+ <int value="23" label="SVQ1"/>
+ <int value="24" label="SVQ3"/>
+ <int value="25" label="DVVIDEO"/>
+ <int value="26" label="HUFFYUV"/>
+ <int value="27" label="CYUV"/>
+ <int value="28" label="H264"/>
+ <int value="29" label="INDEO3"/>
+ <int value="30" label="VP3"/>
+ <int value="31" label="THEORA"/>
+ <int value="32" label="ASV1"/>
+ <int value="33" label="ASV2"/>
+ <int value="34" label="FFV1"/>
+ <int value="35" label="4XM"/>
+ <int value="36" label="VCR1"/>
+ <int value="37" label="CLJR"/>
+ <int value="38" label="MDEC"/>
+ <int value="39" label="ROQ"/>
+ <int value="40" label="INTERPLAY_VIDEO"/>
+ <int value="41" label="XAN_WC3"/>
+ <int value="42" label="XAN_WC4"/>
+ <int value="43" label="RPZA"/>
+ <int value="44" label="CINEPAK"/>
+ <int value="45" label="WS_VQA"/>
+ <int value="46" label="MSRLE"/>
+ <int value="47" label="MSVIDEO1"/>
+ <int value="48" label="IDCIN"/>
+ <int value="49" label="8BPS"/>
+ <int value="50" label="SMC"/>
+ <int value="51" label="FLIC"/>
+ <int value="52" label="TRUEMOTION1"/>
+ <int value="53" label="VMDVIDEO"/>
+ <int value="54" label="MSZH"/>
+ <int value="55" label="ZLIB"/>
+ <int value="56" label="QTRLE"/>
+ <int value="57" label="SNOW"/>
+ <int value="58" label="TSCC"/>
+ <int value="59" label="ULTI"/>
+ <int value="60" label="QDRAW"/>
+ <int value="61" label="VIXL"/>
+ <int value="62" label="QPEG"/>
+ <int value="63" label="PNG"/>
+ <int value="64" label="PPM"/>
+ <int value="65" label="PBM"/>
+ <int value="66" label="PGM"/>
+ <int value="67" label="PGMYUV"/>
+ <int value="68" label="PAM"/>
+ <int value="69" label="FFVHUFF"/>
+ <int value="70" label="RV30"/>
+ <int value="71" label="RV40"/>
+ <int value="72" label="VC1"/>
+ <int value="73" label="WMV3"/>
+ <int value="74" label="LOCO"/>
+ <int value="75" label="WNV1"/>
+ <int value="76" label="AASC"/>
+ <int value="77" label="INDEO2"/>
+ <int value="78" label="FRAPS"/>
+ <int value="79" label="TRUEMOTION2"/>
+ <int value="80" label="BMP"/>
+ <int value="81" label="CSCD"/>
+ <int value="82" label="MMVIDEO"/>
+ <int value="83" label="ZMBV"/>
+ <int value="84" label="AVS"/>
+ <int value="85" label="SMACKVIDEO"/>
+ <int value="86" label="NUV"/>
+ <int value="87" label="KMVC"/>
+ <int value="88" label="FLASHSV"/>
+ <int value="89" label="CAVS"/>
+ <int value="90" label="JPEG2000"/>
+ <int value="91" label="VMNC"/>
+ <int value="92" label="VP5"/>
+ <int value="93" label="VP6"/>
+ <int value="94" label="VP6F"/>
+ <int value="95" label="TARGA"/>
+ <int value="96" label="DSICINVIDEO"/>
+ <int value="97" label="TIERTEXSEQVIDEO"/>
+ <int value="98" label="TIFF"/>
+ <int value="99" label="GIF"/>
+ <int value="100" label="DXA"/>
+ <int value="101" label="DNXHD"/>
+ <int value="102" label="THP"/>
+ <int value="103" label="SGI"/>
+ <int value="104" label="C93"/>
+ <int value="105" label="BETHSOFTVID"/>
+ <int value="106" label="PTX"/>
+ <int value="107" label="TXD"/>
+ <int value="108" label="VP6A"/>
+ <int value="109" label="AMV"/>
+ <int value="110" label="VB"/>
+ <int value="111" label="PCX"/>
+ <int value="112" label="SUNRAST"/>
+ <int value="113" label="INDEO4"/>
+ <int value="114" label="INDEO5"/>
+ <int value="115" label="MIMIC"/>
+ <int value="116" label="RL2"/>
+ <int value="117" label="ESCAPE124"/>
+ <int value="118" label="DIRAC"/>
+ <int value="119" label="BFI"/>
+ <int value="120" label="CMV"/>
+ <int value="121" label="MOTIONPIXELS"/>
+ <int value="122" label="TGV"/>
+ <int value="123" label="TGQ"/>
+ <int value="124" label="TQI"/>
+ <int value="125" label="AURA"/>
+ <int value="126" label="AURA2"/>
+ <int value="127" label="V210X"/>
+ <int value="128" label="TMV"/>
+ <int value="129" label="V210"/>
+ <int value="130" label="DPX"/>
+ <int value="131" label="MAD"/>
+ <int value="132" label="FRWU"/>
+ <int value="133" label="FLASHSV2"/>
+ <int value="134" label="CDGRAPHICS"/>
+ <int value="135" label="R210"/>
+ <int value="136" label="ANM"/>
+ <int value="137" label="BINKVIDEO"/>
+ <int value="138" label="IFF_ILBM"/>
+ <int value="139" label="IFF_BYTERUN1"/>
+ <int value="140" label="KGV1"/>
+ <int value="141" label="YOP"/>
+ <int value="142" label="VP8"/>
+ <int value="143" label="PICTOR"/>
+ <int value="144" label="ANSI"/>
+ <int value="145" label="A64_MULTI"/>
+ <int value="146" label="A64_MULTI5"/>
+ <int value="147" label="R10K"/>
+ <int value="148" label="MXPEG"/>
+ <int value="149" label="LAGARITH"/>
+ <int value="150" label="PRORES"/>
+ <int value="151" label="JV"/>
+ <int value="152" label="DFA"/>
+ <int value="153" label="WMV3IMAGE"/>
+ <int value="154" label="VC1IMAGE"/>
+ <int value="155" label="UTVIDEO"/>
+ <int value="156" label="BMV_VIDEO"/>
+ <int value="157" label="VBLE"/>
+ <int value="158" label="DXTORY"/>
+ <int value="159" label="V410"/>
+ <int value="160" label="XWD"/>
+ <int value="161" label="CDXL"/>
+ <int value="162" label="XBM"/>
+ <int value="163" label="ZEROCODEC"/>
+ <int value="164" label="MSS1"/>
+ <int value="165" label="MSA1"/>
+ <int value="166" label="TSCC2"/>
+ <int value="167" label="MTS2"/>
+ <int value="168" label="CLLC"/>
+ <int value="169" label="MSS2"/>
+ <int value="170" label="VP9"/>
+ <int value="65536" label="PCM_S16LE"/>
+ <int value="65537" label="PCM_S16BE"/>
+ <int value="65538" label="PCM_U16LE"/>
+ <int value="65539" label="PCM_U16BE"/>
+ <int value="65540" label="PCM_S8"/>
+ <int value="65541" label="PCM_U8"/>
+ <int value="65542" label="PCM_MULAW"/>
+ <int value="65543" label="PCM_ALAW"/>
+ <int value="65544" label="PCM_S32LE"/>
+ <int value="65545" label="PCM_S32BE"/>
+ <int value="65546" label="PCM_U32LE"/>
+ <int value="65547" label="PCM_U32BE"/>
+ <int value="65548" label="PCM_S24LE"/>
+ <int value="65549" label="PCM_S24BE"/>
+ <int value="65550" label="PCM_U24LE"/>
+ <int value="65551" label="PCM_U24BE"/>
+ <int value="65552" label="PCM_S24DAUD"/>
+ <int value="65553" label="PCM_ZORK"/>
+ <int value="65554" label="PCM_S16LE_PLANAR"/>
+ <int value="65555" label="PCM_DVD"/>
+ <int value="65556" label="PCM_F32BE"/>
+ <int value="65557" label="PCM_F32LE"/>
+ <int value="65558" label="PCM_F64BE"/>
+ <int value="65559" label="PCM_F64LE"/>
+ <int value="65560" label="PCM_BLURAY"/>
+ <int value="65561" label="PCM_LXF"/>
+ <int value="65562" label="S302M"/>
+ <int value="65563" label="PCM_S8_PLANAR"/>
+ <int value="69632" label="ADPCM_IMA_QT"/>
+ <int value="69633" label="ADPCM_IMA_WAV"/>
+ <int value="69634" label="ADPCM_IMA_DK3"/>
+ <int value="69635" label="ADPCM_IMA_DK4"/>
+ <int value="69636" label="ADPCM_IMA_WS"/>
+ <int value="69637" label="ADPCM_IMA_SMJPEG"/>
+ <int value="69638" label="ADPCM_MS"/>
+ <int value="69639" label="ADPCM_4XM"/>
+ <int value="69640" label="ADPCM_XA"/>
+ <int value="69641" label="ADPCM_ADX"/>
+ <int value="69642" label="ADPCM_EA"/>
+ <int value="69643" label="ADPCM_G726"/>
+ <int value="69644" label="ADPCM_CT"/>
+ <int value="69645" label="ADPCM_SWF"/>
+ <int value="69646" label="ADPCM_YAMAHA"/>
+ <int value="69647" label="ADPCM_SBPRO_4"/>
+ <int value="69648" label="ADPCM_SBPRO_3"/>
+ <int value="69649" label="ADPCM_SBPRO_2"/>
+ <int value="69650" label="ADPCM_THP"/>
+ <int value="69651" label="ADPCM_IMA_AMV"/>
+ <int value="69652" label="ADPCM_EA_R1"/>
+ <int value="69653" label="ADPCM_EA_R3"/>
+ <int value="69654" label="ADPCM_EA_R2"/>
+ <int value="69655" label="ADPCM_IMA_EA_SEAD"/>
+ <int value="69656" label="ADPCM_IMA_EA_EACS"/>
+ <int value="69657" label="ADPCM_EA_XAS"/>
+ <int value="69658" label="ADPCM_EA_MAXIS_XA"/>
+ <int value="69659" label="ADPCM_IMA_ISS"/>
+ <int value="69660" label="ADPCM_G722"/>
+ <int value="69661" label="ADPCM_IMA_APC"/>
+ <int value="73728" label="AMR_NB"/>
+ <int value="73729" label="AMR_WB"/>
+ <int value="77824" label="RA_144"/>
+ <int value="77825" label="RA_288"/>
+ <int value="81920" label="ROQ_DPCM"/>
+ <int value="81921" label="INTERPLAY_DPCM"/>
+ <int value="81922" label="XAN_DPCM"/>
+ <int value="81923" label="SOL_DPCM"/>
+ <int value="86016" label="MP2"/>
+ <int value="86017" label="MP3"/>
+ <int value="86018" label="AAC"/>
+ <int value="86019" label="AC3"/>
+ <int value="86020" label="DTS"/>
+ <int value="86021" label="VORBIS"/>
+ <int value="86022" label="DVAUDIO"/>
+ <int value="86023" label="WMAV1"/>
+ <int value="86024" label="WMAV2"/>
+ <int value="86025" label="MACE3"/>
+ <int value="86026" label="MACE6"/>
+ <int value="86027" label="VMDAUDIO"/>
+ <int value="86028" label="FLAC"/>
+ <int value="86029" label="MP3ADU"/>
+ <int value="86030" label="MP3ON4"/>
+ <int value="86031" label="SHORTEN"/>
+ <int value="86032" label="ALAC"/>
+ <int value="86033" label="WESTWOOD_SND1"/>
+ <int value="86034" label="GSM"/>
+ <int value="86035" label="QDM2"/>
+ <int value="86036" label="COOK"/>
+ <int value="86037" label="TRUESPEECH"/>
+ <int value="86038" label="TTA"/>
+ <int value="86039" label="SMACKAUDIO"/>
+ <int value="86040" label="QCELP"/>
+ <int value="86041" label="WAVPACK"/>
+ <int value="86042" label="DSICINAUDIO"/>
+ <int value="86043" label="IMC"/>
+ <int value="86044" label="MUSEPACK7"/>
+ <int value="86045" label="MLP"/>
+ <int value="86046" label="GSM_MS"/>
+ <int value="86047" label="ATRAC3"/>
+ <int value="86048" label="VOXWARE"/>
+ <int value="86049" label="APE"/>
+ <int value="86050" label="NELLYMOSER"/>
+ <int value="86051" label="MUSEPACK8"/>
+ <int value="86052" label="SPEEX"/>
+ <int value="86053" label="WMAVOICE"/>
+ <int value="86054" label="WMAPRO"/>
+ <int value="86055" label="WMALOSSLESS"/>
+ <int value="86056" label="ATRAC3P"/>
+ <int value="86057" label="EAC3"/>
+ <int value="86058" label="SIPR"/>
+ <int value="86059" label="MP1"/>
+ <int value="86060" label="TWINVQ"/>
+ <int value="86061" label="TRUEHD"/>
+ <int value="86062" label="MP4ALS"/>
+ <int value="86063" label="ATRAC1"/>
+ <int value="86064" label="BINKAUDIO_RDFT"/>
+ <int value="86065" label="BINKAUDIO_DCT"/>
+ <int value="86066" label="AAC_LATM"/>
+ <int value="86067" label="QDMC"/>
+ <int value="86068" label="CELT"/>
+ <int value="86069" label="G723_1"/>
+ <int value="86070" label="G729"/>
+ <int value="86071" label="8SVX_EXP"/>
+ <int value="86072" label="8SVX_FIB"/>
+ <int value="86073" label="BMV_AUDIO"/>
+ <int value="86074" label="RALF"/>
+ <int value="86075" label="IAC"/>
+ <int value="86076" label="ILBC"/>
+ <int value="86077" label="OPUS_DEPRECATED"/>
+ <int value="86078" label="COMFORT_NOISE"/>
+ <int value="86079" label="TAK_DEPRECATED"/>
+ <int value="94208" label="DVD_SUBTITLE"/>
+ <int value="94209" label="DVB_SUBTITLE"/>
+ <int value="94210" label="TEXT"/>
+ <int value="94211" label="XSUB"/>
+ <int value="94212" label="SSA"/>
+ <int value="94213" label="MOV_TEXT"/>
+ <int value="94214" label="HDMV_PGS_SUBTITLE"/>
+ <int value="94215" label="DVB_TELETEXT"/>
+ <int value="94216" label="SRT"/>
+ <int value="98304" label="TTF"/>
+ <int value="102400" label="PROBE"/>
+ <int value="131072" label="MPEG2TS"/>
+ <int value="131073" label="MPEG4SYSTEMS"/>
+ <int value="135168" label="FFMETADATA"/>
+ <int value="4665933" label="G2M"/>
+ <int value="4801606" label="IDF"/>
+ <int value="5198918" label="OTF"/>
+ <int value="407917392" label="PCM_S24LE_PLANAR"/>
+ <int value="542135120" label="PCM_S32LE_PLANAR"/>
+ <int value="808530518" label="012V"/>
+ <int value="809850962" label="EXR"/>
+ <int value="944985688" label="8SVX_RAW"/>
+ <int value="1095123744" label="ADPCM_AFC"/>
+ <int value="1096176208" label="AVRP"/>
+ <int value="1096176238" label="AVRN"/>
+ <int value="1096176969" label="AVUI"/>
+ <int value="1096373590" label="AYUV"/>
+ <int value="1112557912" label="BRENDER_PIX"/>
+ <int value="1112823892" label="BINTEXT"/>
+ <int value="1129335105" label="CPIA"/>
+ <int value="1160852272" label="ESCAPE130"/>
+ <int value="1179014995" label="FFWAVESYNTH"/>
+ <int value="1246975298" label="JACOSUB"/>
+ <int value="1263294017" label="SMPTE_KLV"/>
+ <int value="1297108018" label="MPL2"/>
+ <int value="1297498929" label="MVC1"/>
+ <int value="1297498930" label="MVC2"/>
+ <int value="1330333984" label="ADPCM_IMA_OKI"/>
+ <int value="1330664787" label="OPUS"/>
+ <int value="1346455105" label="PAF_AUDIO"/>
+ <int value="1346455126" label="PAF_VIDEO"/>
+ <int value="1347637264" label="PCM_S16BE_PLANAR"/>
+ <int value="1349012051" label="PJS"/>
+ <int value="1381259348" label="REALTEXT"/>
+ <int value="1396788553" label="SAMI"/>
+ <int value="1396788813" label="SANM"/>
+ <int value="1397180754" label="SGIRLE"/>
+ <int value="1397706307" label="SONIC"/>
+ <int value="1397706316" label="SONIC_LS"/>
+ <int value="1397909872" label="SUBRIP"/>
+ <int value="1398953521" label="SUBVIEWER1"/>
+ <int value="1400201814" label="SUBVIEWER"/>
+ <int value="1412575542" label="TARGA_Y216"/>
+ <int value="1446195256" label="V308"/>
+ <int value="1446260792" label="V408"/>
+ <int value="1447644481" label="VIMA"/>
+ <int value="1448111218" label="VPLAYER"/>
+ <int value="1465275476" label="WEBVTT"/>
+ <int value="1480739150" label="XBIN"/>
+ <int value="1480999235" label="XFACE"/>
+ <int value="1496592720" label="Y41P"/>
+ <int value="1498764852" label="YUV4"/>
+ <int value="1664495672" label="EIA_608"/>
+ <int value="1833195076" label="MICRODVD"/>
+ <int value="1936029283" label="EVRC"/>
+ <int value="1936944502" label="SMV"/>
+ <int value="1950507339" label="TAK"/>
+</enum>
+
+<enum name="FileDialogType" type="int">
+ <int value="0" label="Select folder"/>
+ <int value="1" label="Save as file"/>
+ <int value="2" label="Open file"/>
+ <int value="3" label="Open multiple files"/>
+ <int value="4" label="Full page"/>
+ <int value="5" label="Error"/>
+</enum>
+
+<enum name="FileType" type="int">
+ <int value="0" label="other"/>
+ <int value="1" label=".doc"/>
+ <int value="2" label=".docx"/>
+ <int value="3" label=".odt"/>
+ <int value="4" label=".rtf"/>
+ <int value="5" label=".pdf"/>
+ <int value="6" label=".ppt"/>
+ <int value="7" label=".pptx"/>
+ <int value="8" label=".odp"/>
+ <int value="9" label=".xls"/>
+ <int value="10" label=".xlsx"/>
+ <int value="11" label=".ods"/>
+ <int value="12" label=".csv"/>
+ <int value="13" label=".odf"/>
+ <int value="14" label=".rar"/>
+ <int value="15" label=".asf"/>
+ <int value="16" label=".wma"/>
+ <int value="17" label=".wmv"/>
+ <int value="18" label=".mov"/>
+ <int value="19" label=".mpg"/>
+ <int value="20" label=".log"/>
+</enum>
+
+<enum name="FtpDataConnectionError" type="int">
+ <int value="0">Data connection successful</int>
+ <int value="1">Local firewall blocked the connection</int>
+ <int value="2">Connection timed out</int>
+ <int value="3">
+ Connection has been established, but then got broken (either reset or
+ aborted)
+ </int>
+ <int value="4">Connection has been refused</int>
+ <int value="20">Other kind of error</int>
+</enum>
+
+<enum name="FtpServerType" type="int">
+ <summary>
+ FTP server type as defined in net/ftp/ftp_server_type_histograms.h
+ </summary>
+ <int value="0" label="Unknown">
+ Unknown (could be a server we don't support, a broken server, or a security
+ attack)
+ </int>
+ <int value="1" label="/bin/ls">Server using /bin/ls -l and variants</int>
+ <int value="2" label="/bin/dls">Server using /bin/dls</int>
+ <int value="3" label="EPLF">Server using EPLF format</int>
+ <int value="4" label="WinNT">
+ WinNT server configured for old style listing
+ </int>
+ <int value="5" label="VMS">VMS (including variants)</int>
+ <int value="6" label="IBM VM">IBM VM/CMS, VM/ESA, z/VM formats</int>
+ <int value="7" label="OS/2">OS/2 FTP Server</int>
+ <int value="8" label="win16">
+ win16 hosts: SuperTCP or NetManage Chameleon
+ </int>
+</enum>
+
+<enum name="GDataAuthResult" type="int">
+ <int value="0" label="FAILURE"/>
+ <int value="1" label="SUCCESS"/>
+ <int value="2" label="NO_CONNECTION"/>
+</enum>
+
+<enum name="GDataEntryKind" type="int">
+ <obsolete>
+ Deprecated 9/2012, and replaced by DriveEntryKind
+ </obsolete>
+ <int value="0" label="UNKNOWN"/>
+ <int value="4097" label="ITEM"/>
+ <int value="4098" label="SITE"/>
+ <int value="8449" label="DOCUMENT"/>
+ <int value="8450" label="SPEREADSHEET"/>
+ <int value="8451" label="PRESENTATION"/>
+ <int value="8452" label="DRAWING"/>
+ <int value="8453" label="TABLE"/>
+ <int value="8705" label="EXTERNAL_APP"/>
+ <int value="16385" label="FOLDER"/>
+ <int value="32769" label="FILE"/>
+ <int value="32770" label="PDF"/>
+</enum>
+
+<enum name="GestureActionType" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Omnibox pinch"/>
+ <int value="2" label="Omnibox scroll"/>
+ <int value="3" label="Tabstrip pinch"/>
+ <int value="4" label="Tabstrip scroll"/>
+ <int value="5" label="Bezel scroll"/>
+ <int value="6" label="Desktop scroll"/>
+ <int value="7" label="Desktop pinch"/>
+ <int value="8" label="Webpage pinch"/>
+ <int value="9" label="Webpage scroll"/>
+ <int value="10" label="Webpage tap"/>
+ <int value="11" label="Tabstrip tap"/>
+ <int value="12" label="Bezel down"/>
+ <int value="13" label="Tab switched tap"/>
+ <int value="14" label="Active tab tap"/>
+ <int value="15" label="Tab close button tap"/>
+ <int value="16" label="New tab button tap"/>
+ <int value="17" label="Top edge of window tap"/>
+ <int value="18" label="Window size button tap"/>
+ <int value="19" label="Area surrounding tabstrip tap"/>
+ <int value="20" label="Window resized double tap"/>
+</enum>
+
+<enum name="GetPerfDataOutcome" type="int">
+ <int value="0" label="Success.">
+ Perf data was collected, parsed and attached to the UMA protobuf
+ successfully.
+ </int>
+ <int value="1" label="No perf data ready to be uploaded.">
+ Could not add perf data to the UMA protobuf because no perf data was ready
+ to be uploaded.
+ </int>
+ <int value="2" label="Collection timer triggered but have data already.">
+ Perf timer triggered but the perf provider already had a perf data proto to
+ be added to the UMA protobuf.
+ </int>
+ <int value="3"
+ label="Collection timer triggered but incognito window active.">
+ Perf timer triggered but an incognito window was open.
+ </int>
+ <int value="4" label="Incognito window launched during collection.">
+ Perf data was collected but an incognito window was opened during the
+ collection.
+ </int>
+ <int value="5" label="Protobuf returned by debugd not deserialized.">
+ Perf data was collected and sent to Chrome as a serialized protobuf but it
+ could be deserialized by Chrome.
+ </int>
+</enum>
+
+<enum name="GetUserDataTempDirResult" type="int">
+ <int value="0" label="SUCCESS"/>
+ <int value="1" label="CANT_GET_PARENT_PATH"/>
+ <int value="2" label="CANT_GET_UDT_PATH"/>
+ <int value="3" label="NOT_A_DIRECTORY"/>
+ <int value="4" label="CANT_CREATE_DIR"/>
+ <int value="5" label="CANT_WRITE_TO_PATH"/>
+ <int value="6" label="UNSET"/>
+</enum>
+
+<enum name="GoogleNowEvent" type="int">
+ <summary>
+ Events in Google Now component extension. See GoogleNowEvent in
+ chrome/browser/resources/google_now/background.js.
+ </summary>
+ <int value="0" label="REQUEST_FOR_CARDS_TOTAL"/>
+ <int value="1" label="REQUEST_FOR_CARDS_SUCCESS"/>
+ <int value="2" label="CARDS_PARSE_SUCCESS"/>
+ <int value="3" label="DISMISS_REQUEST_TOTAL"/>
+ <int value="4" label="DISMISS_REQUEST_SUCCESS"/>
+ <int value="5" label="LOCATION_REQUEST"/>
+ <int value="6" label="LOCATION_UPDATE"/>
+ <int value="7" label="EXTENSION_START"/>
+ <int value="8" label="SHOW_WELCOME_TOAST"/>
+ <int value="9" label="STOPPED"/>
+ <int value="10" label="USER_SUPPRESSED"/>
+</enum>
+
+<enum name="HttpAuthCount" type="int">
+ <int value="0" label="Basic Start"/>
+ <int value="1" label="Basic Reject"/>
+ <int value="2" label="Digest Start"/>
+ <int value="3" label="Digest Reject"/>
+ <int value="4" label="NTLM Start"/>
+ <int value="5" label="NTLM Reject"/>
+ <int value="6" label="Negotiate Start"/>
+ <int value="7" label="Negotiate Reject"/>
+</enum>
+
+<enum name="HttpAuthResource" type="int">
+ <int value="0" label="Top Page Allowed"/>
+ <int value="1" label="Same-domain Sub-resource Allowed"/>
+ <int value="2" label="Cross-domain Sub-resource Blocked"/>
+ <int value="3" label="Cross-domain Sub-resource Allowed"/>
+</enum>
+
+<enum name="HttpAuthTarget" type="int">
+ <int value="0" label="Basic Proxy"/>
+ <int value="1" label="Basic Secure Proxy"/>
+ <int value="2" label="Basic Server"/>
+ <int value="3" label="Basic Secure Server"/>
+ <int value="4" label="Digest Proxy"/>
+ <int value="5" label="Digest Secure Proxy"/>
+ <int value="6" label="Digest Server"/>
+ <int value="7" label="Digest Secure Server"/>
+ <int value="8" label="NTLM Proxy"/>
+ <int value="9" label="NTLM Secure Proxy"/>
+ <int value="10" label="NTLM Server"/>
+ <int value="11" label="NTLM Secure Server"/>
+ <int value="12" label="Negotiate Proxy"/>
+ <int value="13" label="Negotiate Secure Proxy"/>
+ <int value="14" label="Negotiate Server"/>
+ <int value="15" label="Negotiate Secure Server"/>
+</enum>
+
+<enum name="HttpPipelineStatus" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Redirected"/>
+ <int value="2" label="Certificate error"/>
+ <int value="3" label="Bad HTTP response code"/>
+ <int value="4" label="Network error"/>
+ <int value="5" label="Response too large"/>
+ <int value="6" label="Response too small"/>
+ <int value="7" label="Response content mismatch"/>
+ <int value="8" label="Bad HTTP version"/>
+ <int value="9" label="Corrupt stats response"/>
+</enum>
+
+<enum name="HttpSocketType" type="int">
+ <int value="0" label="UNUSED">newly connected socket</int>
+ <int value="1" label="UNUSED_IDLE">
+ connected unused socket (idle prior to use)
+ </int>
+ <int value="2" label="REUSED_IDLE">previously used (keep-alive?) socket</int>
+</enum>
+
+<enum name="IDBLevelDBBackingStoreInternalErrorType" type="int">
+ <int value="0" label="IDBLevelDBBackingStoreReadError">
+ IndexedDB encountered an error attempting to read or decode a value from the
+ leveldb backing store, indicative of corruption or I/O error. Unused as of
+ M26.
+ </int>
+ <int value="1" label="IDBLevelDBBackingStoreWriteError">
+ IndexeDB encountered an error attempting to write or commit a value to the
+ leveldb backing store, indicative of I/O error. Unused as of M26.
+ </int>
+ <int value="2" label="IDBLevelDBBackingStoreConsistencyError">
+ IndexedDB encountered a consistency error in the leveldb backing store,
+ indicative of corruption or an coding error. Unused as of M26.
+ </int>
+ <int value="3" label="FindKeyInIndex"/>
+ <int value="4" label="GetIDBDatabaseMetaData"/>
+ <int value="5" label="GetIndexes"/>
+ <int value="6" label="GetKeyGeneratorCurrentNumber"/>
+ <int value="7" label="GetObjectStores"/>
+ <int value="8" label="GetRecord"/>
+ <int value="9" label="KeyExistsInObjectStore"/>
+ <int value="10" label="LoadCurrentRow"/>
+ <int value="11" label="SetupMetadata"/>
+ <int value="12" label="GetPrimaryKeyViaIndex"/>
+ <int value="13" label="KeyExistsInIndex"/>
+ <int value="14" label="VersionExists"/>
+ <int value="15" label="DeleteObjectStore"/>
+ <int value="16" label="SetMaxObjectStoreId"/>
+ <int value="17" label="SetMaxIndexId"/>
+ <int value="18" label="GetNewDatabaseId"/>
+ <int value="19" label="GetNewVersionNumber"/>
+ <int value="20" label="CreateIDBDatabaseMetaData"/>
+ <int value="21" label="DeleteDatabase"/>
+ <int value="22" label="TransactionCommit"/>
+ <int value="23" label="GetDatabaseNames"/>
+</enum>
+
+<enum name="IDBLevelDBBackingStoreOpenResult" type="int">
+ <int value="0" label="OpenMemorySuccess">
+ An in-memory backing store was opened successfully.
+ </int>
+ <int value="1" label="OpenSuccess">
+ An on-disk backing store was opened successfully.
+ </int>
+ <int value="2" label="OpenFailedDirectory">
+ An on-disk backing store could not be opened or created because the
+ directory could not be opened or created. Cleanup will not be attempted.
+ </int>
+ <int value="3" label="OpenFailedUnknownSchema">
+ An on-disk backing store was opened but had an unknown schema version, due
+ to corruption or reverting to a previous version of Chrome. Cleanup will be
+ attempted.
+ </int>
+ <int value="4" label="OpenCleanupDestroyFailed">
+ An on-disk backing store failed to open; cleanup was attempted but the
+ database could not be destroyed.
+ </int>
+ <int value="5" label="OpenCleanupReopenFailed">
+ An on-disk backing store failed to open; cleanup was attempted but
+ re-opening the database failed.
+ </int>
+ <int value="6" label="OpenCleanupReopenSuccess">
+ An on-disk backing store failed to open; cleanup was attempted and the
+ database was then opened successfully.
+ </int>
+ <int value="7" label="OpenFailedIOErrCheckingSchema">
+ An on-disk backing store was opened but leveldb failed to read the schema
+ version.
+ </int>
+ <int value="8" label="OpenFailedUnknownErr"/>
+ <int value="9" label="OpenMemoryFailed">
+ An in-memory backing store failed to open.
+ </int>
+ <int value="10" label="OpenNonASCII">
+ A database with non-ascii characters in its path was opened (with either
+ success or failure).
+ </int>
+ <int value="11" label="OpenAttemptDiskFull">
+ An open failed on a machine with a full disk. No cleanup was attempted.
+ </int>
+</enum>
+
+<enum name="ImporterType" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="IMPORTER_METRICS_IE">IE (Windows-only)</int>
+ <int value="2" label="IMPORTER_METRICS_FIREFOX2">Firefox 2</int>
+ <int value="3" label="IMPORTER_METRICS_FIREFOX3">Firefox 3 (and later)</int>
+ <int value="4" label="IMPORTER_METRICS_SAFARI">Safari (Mac-only)</int>
+ <int value="5" label="IMPORTER_METRICS_GOOGLE_TOOLBAR5">Google Toolbar</int>
+ <int value="6" label="IMPORTER_METRICS_BOOKMARKS_FILE">
+ A bookmarks.html file
+ </int>
+</enum>
+
+<enum name="IndexedDatabaseMethods" type="int">
+ <int value="0" label="CreateObjectStore()"/>
+ <int value="1" label="DeleteObjectStore()"/>
+ <int value="2" label="Transaction()"/>
+ <int value="3" label="DeleteDatabase()"/>
+ <int value="4" label="Open()"/>
+</enum>
+
+<enum name="InstantControllerEvent" type="int">
+ <int value="0" label="URL_ADDED_TO_BLACKLIST"/>
+ <int value="1" label="URL_REMOVED_FROM_BLACKLIST"/>
+ <int value="2" label="URL_BLOCKED_BY_BLACKLIST"/>
+</enum>
+
+<enum name="InstantExtended_FallbackCause" type="int">
+ <int value="0" label="Fallback did not occur"/>
+ <int value="1" label="Page not current: unknown"/>
+ <int value="2" label="Page not current: empty instant url"/>
+ <int value="3" label="Page not current: origin/path mismatch"/>
+ <int value="4" label="Page not current: instant not supported"/>
+ <int value="5" label="No overlay"/>
+ <int value="6" label="Javascript disabled"/>
+</enum>
+
+<enum name="InstantExtended_InstantNavigation" type="int">
+ <int value="0" label="Local click"/>
+ <int value="1" label="Local submit"/>
+ <int value="2" label="Online click"/>
+ <int value="3" label="Online submit"/>
+ <int value="4" label="Non-extended navigation"/>
+</enum>
+
+<enum name="InstantExtended_NewOptInState" type="int">
+ <int value="0" label="Default"/>
+ <int value="1" label="Opted in"/>
+ <int value="2" label="Opted out"/>
+</enum>
+
+<enum name="InstantExtended_OptInState" type="int">
+ <obsolete>
+ Deprecated 2013-06.
+ </obsolete>
+ <int value="0" label="Default"/>
+ <int value="1" label="Opted in"/>
+ <int value="2" label="Opted out"/>
+ <int value="3" label="Opted in local"/>
+ <int value="4" label="Opted out local"/>
+ <int value="5" label="Opted out both"/>
+</enum>
+
+<enum name="InstantSessionStorageNamespace" type="int">
+ <int value="0" label="different"/>
+ <int value="1" label="identical"/>
+</enum>
+
+<enum name="IntelMaxMicroArchitecture" type="int">
+ <int value="0" label="Pentium"/>
+ <int value="1" label="SSE"/>
+ <int value="2" label="SSE2"/>
+ <int value="3" label="SSE3"/>
+ <int value="4" label="SSSE3"/>
+ <int value="5" label="SSE4.1"/>
+ <int value="6" label="SSE4.3"/>
+ <int value="7" label="AVX"/>
+</enum>
+
+<enum name="InterruptReason" type="int">
+ <int value="0" label="NONE"/>
+ <int value="1" label="FILE_FAILED"/>
+ <int value="2" label="FILE_ACCESS_DENIED"/>
+ <int value="3" label="FILE_NO_SPACE"/>
+ <int value="5" label="FILE_NAME_TOO_LONG"/>
+ <int value="6" label="FILE_TOO_LARGE"/>
+ <int value="7" label="FILE_VIRUS_INFECTED"/>
+ <int value="10" label="FILE_TRANSIENT_ERROR"/>
+ <int value="11" label="FILE_BLOCKED"/>
+ <int value="12" label="FILE_SECURITY_CHECK_FAILED"/>
+ <int value="13" label="FILE_TOO_SHORT"/>
+ <int value="20" label="NETWORK_FAILED"/>
+ <int value="21" label="NETWORK_TIMEOUT"/>
+ <int value="22" label="NETWORK_DISCONNECTED"/>
+ <int value="23" label="NETWORK_SERVER_DOWN"/>
+ <int value="30" label="SERVER_FAILED"/>
+ <int value="31" label="SERVER_NO_RANGE"/>
+ <int value="32" label="SERVER_PRECONDITION"/>
+ <int value="33" label="SERVER_BAD_CONTENT"/>
+ <int value="40" label="USER_CANCELED"/>
+ <int value="41" label="USER_SHUTDOWN"/>
+ <int value="50" label="CRASH"/>
+</enum>
+
+<enum name="IPV6ProbeResult" type="int">
+ <int value="0" label="IPV6_CANNOT_CREATE_SOCKETS"/>
+ <int value="1" label="IPV6_CAN_CREATE_SOCKETS"/>
+ <int value="2" label="IPV6_GETIFADDRS_FAILED">
+ getifaddrs or GetAdaptersAddresses failed
+ </int>
+ <int value="3" label="IPV6_GLOBAL_ADDRESS_MISSING"/>
+ <int value="4" label="IPV6_GLOBAL_ADDRESS_PRESENT"/>
+ <int value="5" label="IPV6_INTERFACE_ARRAY_TOO_SHORT"/>
+</enum>
+
+<enum name="JavaScriptAPIName" type="int">
+ <int value="0" label="GetUserMedia"/>
+ <int value="1" label="PeerConnection00"/>
+ <int value="2" label="DeprecatedPeerConnection"/>
+ <int value="3" label="RTCPeerConnection"/>
+</enum>
+
+<enum name="LanguageCode" type="int">
+ <summary>ISO 639 Language Codes.</summary>
+ <int value="24929" label="Afar"/>
+ <int value="24930" label="Abkhazian"/>
+ <int value="24933" label="Avestan"/>
+ <int value="24934" label="Afrikaans"/>
+ <int value="24939" label="Akan"/>
+ <int value="24941" label="Amharic"/>
+ <int value="24942" label="Aragonese"/>
+ <int value="24946" label="Arabic"/>
+ <int value="24947" label="Assamese"/>
+ <int value="24950" label="Avaric"/>
+ <int value="24953" label="Aymara"/>
+ <int value="24954" label="Azerbaijani"/>
+ <int value="25185" label="Bashkir"/>
+ <int value="25189" label="Belarusian"/>
+ <int value="25191" label="Bulgarian"/>
+ <int value="25192" label="Bihari"/>
+ <int value="25193" label="Bislama"/>
+ <int value="25197" label="Bambara"/>
+ <int value="25198" label="Bengali"/>
+ <int value="25199" label="Tibetan"/>
+ <int value="25202" label="Breton"/>
+ <int value="25203" label="Bosnian"/>
+ <int value="25441" label="Catalan"/>
+ <int value="25445" label="Chechen"/>
+ <int value="25448" label="Chamorro"/>
+ <int value="25455" label="Corsican"/>
+ <int value="25458" label="Cree"/>
+ <int value="25459" label="Czech"/>
+ <int value="25461" label="Church Slavic"/>
+ <int value="25462" label="Chuvash"/>
+ <int value="25465" label="Welsh"/>
+ <int value="25697" label="Danish"/>
+ <int value="25701" label="German"/>
+ <int value="25718" label="Divehi"/>
+ <int value="25722" label="Dzongkha"/>
+ <int value="25957" label="Ewe"/>
+ <int value="25964" label="Greek"/>
+ <int value="25966" label="English"/>
+ <int value="25967" label="Esperanto"/>
+ <int value="25971" label="Spanish"/>
+ <int value="25972" label="Estonian"/>
+ <int value="25973" label="Basque"/>
+ <int value="26209" label="Persian"/>
+ <int value="26214" label="Fulah"/>
+ <int value="26217" label="Finnish"/>
+ <int value="26218" label="Fijian"/>
+ <int value="26223" label="Faroese"/>
+ <int value="26226" label="French"/>
+ <int value="26233" label="Western Frisian"/>
+ <int value="26465" label="Irish"/>
+ <int value="26468" label="Scottish Gaelic"/>
+ <int value="26476" label="Galician"/>
+ <int value="26478" label="Guarani"/>
+ <int value="26485" label="Gujarati"/>
+ <int value="26486" label="Manx"/>
+ <int value="26721" label="Hausa"/>
+ <int value="26725" label="Hebrew"/>
+ <int value="26729" label="Hindi"/>
+ <int value="26735" label="Hiri Motu"/>
+ <int value="26738" label="Croatian"/>
+ <int value="26740" label="Haitian"/>
+ <int value="26741" label="Hungarian"/>
+ <int value="26745" label="Armenian"/>
+ <int value="26746" label="Herero"/>
+ <int value="26977" label="Interlingua"/>
+ <int value="26980" label="Indonesian"/>
+ <int value="26981" label="Interlingue"/>
+ <int value="26983" label="Igbo"/>
+ <int value="26985" label="Sichuan Yi"/>
+ <int value="26987" label="Inupiaq"/>
+ <int value="26991" label="Ido"/>
+ <int value="26995" label="Icelandic"/>
+ <int value="26996" label="Italian"/>
+ <int value="26997" label="Inuktitut"/>
+ <int value="27233" label="Japanese"/>
+ <int value="27254" label="Javanese"/>
+ <int value="27489" label="Georgian"/>
+ <int value="27495" label="Kongo"/>
+ <int value="27497" label="Kikuyu"/>
+ <int value="27498" label="Kuanyama"/>
+ <int value="27499" label="Kazakh"/>
+ <int value="27500" label="Kalaallisut"/>
+ <int value="27501" label="Khmer"/>
+ <int value="27502" label="Kannada"/>
+ <int value="27503" label="Korean"/>
+ <int value="27506" label="Kanuri"/>
+ <int value="27507" label="Kashmiri"/>
+ <int value="27509" label="Kurdish"/>
+ <int value="27510" label="Komi"/>
+ <int value="27511" label="Cornish"/>
+ <int value="27513" label="Kirghiz"/>
+ <int value="27745" label="Latin"/>
+ <int value="27746" label="Luxembourgish"/>
+ <int value="27751" label="Ganda"/>
+ <int value="27753" label="Limburgish"/>
+ <int value="27758" label="Lingala"/>
+ <int value="27759" label="Lao"/>
+ <int value="27764" label="Lithuanian"/>
+ <int value="27765" label="Luba-Katanga"/>
+ <int value="27766" label="Latvian"/>
+ <int value="28007" label="Malagasy"/>
+ <int value="28008" label="Marshallese"/>
+ <int value="28009" label="Maori"/>
+ <int value="28011" label="Macedonian"/>
+ <int value="28012" label="Malayalam"/>
+ <int value="28014" label="Mongolian"/>
+ <int value="28015" label="Moldavian"/>
+ <int value="28018" label="Marathi"/>
+ <int value="28019" label="Malay"/>
+ <int value="28020" label="Maltese"/>
+ <int value="28025" label="Burmese"/>
+ <int value="28257" label="Nauru"/>
+ <int value="28258" label="Norwegian Bokmal"/>
+ <int value="28260" label="North Ndebele"/>
+ <int value="28261" label="Nepali"/>
+ <int value="28263" label="Ndonga"/>
+ <int value="28268" label="Dutch"/>
+ <int value="28270" label="Norwegian Nynorsk"/>
+ <int value="28271" label="Norwegian"/>
+ <int value="28274" label="South Ndebele"/>
+ <int value="28278" label="Navajo"/>
+ <int value="28281" label="Nyanja"/>
+ <int value="28515" label="Occitan"/>
+ <int value="28522" label="Ojibwa"/>
+ <int value="28525" label="Oromo"/>
+ <int value="28530" label="Oriya"/>
+ <int value="28531" label="Ossetic"/>
+ <int value="28769" label="Punjabi"/>
+ <int value="28777" label="Pali"/>
+ <int value="28780" label="Polish"/>
+ <int value="28787" label="Pashto"/>
+ <int value="28788" label="Portuguese"/>
+ <int value="29045" label="Quechua"/>
+ <int value="29293" label="Romansh"/>
+ <int value="29294" label="Rundi"/>
+ <int value="29295" label="Romanian"/>
+ <int value="29301" label="Russian"/>
+ <int value="29303" label="Kinyarwanda"/>
+ <int value="29537" label="Sanskrit"/>
+ <int value="29539" label="Sardinian"/>
+ <int value="29540" label="Sindhi"/>
+ <int value="29541" label="Northern Sami"/>
+ <int value="29543" label="Sango"/>
+ <int value="29544" label="Serbo-Croatian"/>
+ <int value="29545" label="Sinhala"/>
+ <int value="29547" label="Slovak"/>
+ <int value="29548" label="Slovenian"/>
+ <int value="29549" label="Samoan"/>
+ <int value="29550" label="Shona"/>
+ <int value="29551" label="Somali"/>
+ <int value="29553" label="Albanian"/>
+ <int value="29554" label="Serbian"/>
+ <int value="29555" label="Swati"/>
+ <int value="29556" label="Southern Sotho"/>
+ <int value="29557" label="Sundanese"/>
+ <int value="29558" label="Swedish"/>
+ <int value="29559" label="Swahili"/>
+ <int value="29793" label="Tamil"/>
+ <int value="29797" label="Telugu"/>
+ <int value="29799" label="Tajik"/>
+ <int value="29800" label="Thai"/>
+ <int value="29801" label="Tigrinya"/>
+ <int value="29803" label="Turkmen"/>
+ <int value="29804" label="Tagalog"/>
+ <int value="29806" label="Tswana"/>
+ <int value="29807" label="Tonga"/>
+ <int value="29810" label="Turkish"/>
+ <int value="29811" label="Tsonga"/>
+ <int value="29812" label="Tatar"/>
+ <int value="29815" label="Twi"/>
+ <int value="29817" label="Tahitian"/>
+ <int value="30055" label="Uighur"/>
+ <int value="30059" label="Ukrainian"/>
+ <int value="30066" label="Urdu"/>
+ <int value="30074" label="Uzbek"/>
+ <int value="30309" label="Venda"/>
+ <int value="30313" label="Vietnamese"/>
+ <int value="30319" label="Volapuk"/>
+ <int value="30561" label="Walloon"/>
+ <int value="30575" label="Wolof"/>
+ <int value="30824" label="Xhosa"/>
+ <int value="31081" label="Yiddish"/>
+ <int value="31087" label="Yoruba"/>
+ <int value="31329" label="Zhuang"/>
+ <int value="31336" label="Chinese"/>
+ <int value="31349" label="Zulu"/>
+ <int value="6382437" label="Achinese"/>
+ <int value="6382440" label="Acoli"/>
+ <int value="6382689" label="Adangme"/>
+ <int value="6382713" label="Adyghe"/>
+ <int value="6383201" label="Afro-Asiatic Language"/>
+ <int value="6383208" label="Afrihili"/>
+ <int value="6383982" label="Ainu"/>
+ <int value="6384491" label="Akkadian"/>
+ <int value="6384741" label="Aleut"/>
+ <int value="6384743" label="Algonquian Language"/>
+ <int value="6384756" label="Southern Altai"/>
+ <int value="6385255" label="Old English"/>
+ <int value="6385264" label="Angika"/>
+ <int value="6385761" label="Apache Language"/>
+ <int value="6386275" label="Aramaic"/>
+ <int value="6386286" label="Araucanian"/>
+ <int value="6386288" label="Arapaho"/>
+ <int value="6386292" label="Artificial Language"/>
+ <int value="6386295" label="Arawak"/>
+ <int value="6386529" label="Asu"/>
+ <int value="6386548" label="Asturian"/>
+ <int value="6386792" label="Athapascan Language"/>
+ <int value="6387059" label="Australian Language"/>
+ <int value="6387553" label="Awadhi"/>
+ <int value="6447460" label="Banda"/>
+ <int value="6447465" label="Bamileke Language"/>
+ <int value="6447468" label="Baluchi"/>
+ <int value="6447470" label="Balinese"/>
+ <int value="6447475" label="Basa"/>
+ <int value="6447476" label="Baltic Language"/>
+ <int value="6448490" label="Beja"/>
+ <int value="6448493" label="Bemba"/>
+ <int value="6448498" label="Berber"/>
+ <int value="6448506" label="Bena"/>
+ <int value="6449263" label="Bhojpuri"/>
+ <int value="6449515" label="Bikol"/>
+ <int value="6449518" label="Bini"/>
+ <int value="6450273" label="Siksika"/>
+ <int value="6450804" label="Bantu"/>
+ <int value="6451809" label="Braj"/>
+ <int value="6451832" label="Bodo"/>
+ <int value="6452331" label="Batak"/>
+ <int value="6452577" label="Buriat"/>
+ <int value="6452583" label="Buginese"/>
+ <int value="6453614" label="Blin"/>
+ <int value="6512996" label="Caddo"/>
+ <int value="6513001" label="Central American Indian Language"/>
+ <int value="6513010" label="Carib"/>
+ <int value="6513013" label="Caucasian Language"/>
+ <int value="6513017" label="Cayuga"/>
+ <int value="6513512" label="Atsam"/>
+ <int value="6514018" label="Cebuano"/>
+ <int value="6514028" label="Celtic Language"/>
+ <int value="6514535" label="Chiga"/>
+ <int value="6514786" label="Chibcha"/>
+ <int value="6514791" label="Chagatai"/>
+ <int value="6514795" label="Chuukese"/>
+ <int value="6514797" label="Mari"/>
+ <int value="6514798" label="Chinook Jargon"/>
+ <int value="6514799" label="Choctaw"/>
+ <int value="6514800" label="Chipewyan"/>
+ <int value="6514802" label="Cherokee"/>
+ <int value="6514809" label="Cheyenne"/>
+ <int value="6516067" label="Chamic Language"/>
+ <int value="6516592" label="Coptic"/>
+ <int value="6516837" label="English-based Creole or Pidgin"/>
+ <int value="6516838" label="French-based Creole or Pidgin"/>
+ <int value="6516848" label="Portuguese-based Creole or Pidgin"/>
+ <int value="6517352" label="Crimean Turkish"/>
+ <int value="6517360" label="Creole or Pidgin"/>
+ <int value="6517602" label="Kashubian"/>
+ <int value="6518131" label="Cushitic Language"/>
+ <int value="6578539" label="Dakota"/>
+ <int value="6578546" label="Dargwa"/>
+ <int value="6578550" label="Taita"/>
+ <int value="6578553" label="Dayak"/>
+ <int value="6579564" label="Delaware"/>
+ <int value="6579566" label="Slave"/>
+ <int value="6580082" label="Dogrib"/>
+ <int value="6580590" label="Dinka"/>
+ <int value="6580837" label="Zarma"/>
+ <int value="6582121" label="Dogri"/>
+ <int value="6582881" label="Dravidian Language"/>
+ <int value="6583138" label="Lower Sorbian"/>
+ <int value="6583649" label="Duala"/>
+ <int value="6583661" label="Middle Dutch"/>
+ <int value="6584693" label="Dyula"/>
+ <int value="6644341" label="Embu"/>
+ <int value="6645353" label="Efik"/>
+ <int value="6645625" label="Ancient Egyptian"/>
+ <int value="6646625" label="Ekajuk"/>
+ <int value="6646904" label="Elamite"/>
+ <int value="6647405" label="Middle English"/>
+ <int value="6649711" label="Ewondo"/>
+ <int value="6709614" label="Fang"/>
+ <int value="6709620" label="Fanti"/>
+ <int value="6711660" label="Filipino"/>
+ <int value="6711669" label="Finno-Ugrian Language"/>
+ <int value="6713198" label="Fon"/>
+ <int value="6713965" label="Middle French"/>
+ <int value="6713967" label="Old French"/>
+ <int value="6713970" label="Northern Frisian"/>
+ <int value="6713971" label="Eastern Frisian"/>
+ <int value="6714738" label="Friulian"/>
+ <int value="6775137" label="Ga"/>
+ <int value="6775161" label="Gayo"/>
+ <int value="6775393" label="Gbaya"/>
+ <int value="6776173" label="Germanic Language"/>
+ <int value="6776186" label="Geez"/>
+ <int value="6777196" label="Gilbertese"/>
+ <int value="6778216" label="Middle High German"/>
+ <int value="6778728" label="Old High German"/>
+ <int value="6778734" label="Gondi"/>
+ <int value="6778738" label="Gorontalo"/>
+ <int value="6778740" label="Gothic"/>
+ <int value="6779490" label="Grebo"/>
+ <int value="6779491" label="Ancient Greek"/>
+ <int value="6779767" label="Swiss German"/>
+ <int value="6780282" label="Gusii"/>
+ <int value="6780777" label="Gwich'in"/>
+ <int value="6840681" label="Haida"/>
+ <int value="6840695" label="Hawaiian"/>
+ <int value="6842732" label="Hiligaynon"/>
+ <int value="6842733" label="Himachali"/>
+ <int value="6842740" label="Hittite"/>
+ <int value="6843758" label="Hmong"/>
+ <int value="6845282" label="Upper Sorbian"/>
+ <int value="6845808" label="Hupa"/>
+ <int value="6906465" label="Iban"/>
+ <int value="6908527" label="Ijo"/>
+ <int value="6909039" label="Iloko"/>
+ <int value="6909539" label="Indic Language"/>
+ <int value="6909541" label="Indo-European Language"/>
+ <int value="6909544" label="Ingush"/>
+ <int value="6910561" label="Iranian Language"/>
+ <int value="6910575" label="Iroquoian Language"/>
+ <int value="6972015" label="Lojban"/>
+ <int value="6974819" label="Machame"/>
+ <int value="6975602" label="Judeo-Persian"/>
+ <int value="6976098" label="Judeo-Arabic"/>
+ <int value="7037281" label="Kara-Kalpak"/>
+ <int value="7037282" label="Kabyle"/>
+ <int value="7037283" label="Kachin"/>
+ <int value="7037290" label="Jju"/>
+ <int value="7037293" label="Kamba"/>
+ <int value="7037298" label="Karen"/>
+ <int value="7037303" label="Kawi"/>
+ <int value="7037540" label="Kabardian"/>
+ <int value="7037799" label="Tyap"/>
+ <int value="7038053" label="Makonde"/>
+ <int value="7038305" label="Kabuverdianu"/>
+ <int value="7038575" label="Koro"/>
+ <int value="7039073" label="Khasi"/>
+ <int value="7039081" label="Khoisan Language"/>
+ <int value="7039087" label="Khotanese"/>
+ <int value="7039089" label="Koyra Chiini"/>
+ <int value="7040110" label="Kalenjin"/>
+ <int value="7040354" label="Kimbundu"/>
+ <int value="7040875" label="Konkani"/>
+ <int value="7040883" label="Kosraean"/>
+ <int value="7041125" label="Kpelle"/>
+ <int value="7041635" label="Karachay-Balkar"/>
+ <int value="7041644" label="Karelian"/>
+ <int value="7041647" label="Kru"/>
+ <int value="7041653" label="Kurukh"/>
+ <int value="7041890" label="Shambala"/>
+ <int value="7041896" label="Colognian"/>
+ <int value="7042413" label="Kumyk"/>
+ <int value="7042420" label="Kutenai"/>
+ <int value="7102820" label="Ladino"/>
+ <int value="7102823" label="Langi"/>
+ <int value="7102824" label="Lahnda"/>
+ <int value="7102829" label="Lamba"/>
+ <int value="7103866" label="Lezghian"/>
+ <int value="7106412" label="Mongo"/>
+ <int value="7106426" label="Lozi"/>
+ <int value="7107937" label="Luba-Lulua"/>
+ <int value="7107945" label="Luiseno"/>
+ <int value="7107950" label="Lunda"/>
+ <int value="7107951" label="Luo"/>
+ <int value="7107955" label="Lushai"/>
+ <int value="7107961" label="Luyia"/>
+ <int value="7168356" label="Madurese"/>
+ <int value="7168359" label="Magahi"/>
+ <int value="7168361" label="Maithili"/>
+ <int value="7168363" label="Makasar"/>
+ <int value="7168366" label="Mandingo"/>
+ <int value="7168368" label="Austronesian Language"/>
+ <int value="7168371" label="Masai"/>
+ <int value="7169126" label="Moksha"/>
+ <int value="7169138" label="Mandar"/>
+ <int value="7169390" label="Mende"/>
+ <int value="7169394" label="Meru"/>
+ <int value="7169637" label="Morisyen"/>
+ <int value="7169889" label="Middle Irish"/>
+ <int value="7170403" label="Micmac"/>
+ <int value="7170414" label="Minangkabau"/>
+ <int value="7170419" label="Miscellaneous Language"/>
+ <int value="7170920" label="Mon-Khmer Language"/>
+ <int value="7171683" label="Manchu"/>
+ <int value="7171689" label="Manipuri"/>
+ <int value="7171695" label="Manobo Language"/>
+ <int value="7171944" label="Mohawk"/>
+ <int value="7171955" label="Mossi"/>
+ <int value="7173484" label="Multiple Languages"/>
+ <int value="7173486" label="Munda Language"/>
+ <int value="7173491" label="Creek"/>
+ <int value="7173996" label="Mirandese"/>
+ <int value="7174002" label="Marwari"/>
+ <int value="7174510" label="Mayan Language"/>
+ <int value="7174518" label="Erzya"/>
+ <int value="7233896" label="Nahuatl"/>
+ <int value="7233897" label="North American Indian Language"/>
+ <int value="7233904" label="Neapolitan"/>
+ <int value="7233905" label="Nama"/>
+ <int value="7234675" label="Low German"/>
+ <int value="7234935" label="Newari"/>
+ <int value="7235937" label="Nias"/>
+ <int value="7235939" label="Niger-Kordofanian Language"/>
+ <int value="7235957" label="Niuean"/>
+ <int value="7237479" label="Nogai"/>
+ <int value="7237486" label="Old Norse"/>
+ <int value="7237999" label="N'Ko"/>
+ <int value="7238511" label="Northern Sotho"/>
+ <int value="7239010" label="Nubian Language"/>
+ <int value="7239523" label="Classical Newari"/>
+ <int value="7240045" label="Nyamwezi"/>
+ <int value="7240046" label="Nyankole"/>
+ <int value="7240047" label="Nyoro"/>
+ <int value="7240297" label="Nzima"/>
+ <int value="7304033" label="Osage"/>
+ <int value="7304289" label="Ottoman Turkish"/>
+ <int value="7304303" label="Otomian Language"/>
+ <int value="7364961" label="Papuan Language"/>
+ <int value="7364967" label="Pangasinan"/>
+ <int value="7364972" label="Pahlavi"/>
+ <int value="7364973" label="Pampanga"/>
+ <int value="7364976" label="Papiamento"/>
+ <int value="7364981" label="Palauan"/>
+ <int value="7365999" label="Old Persian"/>
+ <int value="7366761" label="Philippine Language"/>
+ <int value="7366766" label="Phoenician"/>
+ <int value="7368558" label="Pohnpeian"/>
+ <int value="7369313" label="Prakrit Language"/>
+ <int value="7369327" label="Old Provencal"/>
+ <int value="7496042" label="Rajasthani"/>
+ <int value="7496048" label="Rapanui"/>
+ <int value="7496050" label="Rarotongan"/>
+ <int value="7499617" label="Romance Language"/>
+ <int value="7499622" label="Rombo"/>
+ <int value="7499629" label="Romany"/>
+ <int value="7501168" label="Aromanian"/>
+ <int value="7501675" label="Rwa"/>
+ <int value="7561572" label="Sandawe"/>
+ <int value="7561576" label="Yakut"/>
+ <int value="7561577" label="South American Indian Language"/>
+ <int value="7561580" label="Salishan Language"/>
+ <int value="7561581" label="Samaritan Aramaic"/>
+ <int value="7561585" label="Samburu"/>
+ <int value="7561587" label="Sasak"/>
+ <int value="7561588" label="Santali"/>
+ <int value="7562094" label="Sicilian"/>
+ <int value="7562095" label="Scots"/>
+ <int value="7562597" label="Seneca"/>
+ <int value="7562600" label="Sena"/>
+ <int value="7562604" label="Selkup"/>
+ <int value="7562605" label="Semitic Language"/>
+ <int value="7562611" label="Koyraboro Senni"/>
+ <int value="7563105" label="Old Irish"/>
+ <int value="7563118" label="Sign Language"/>
+ <int value="7563369" label="Tachelhit"/>
+ <int value="7563374" label="Shan"/>
+ <int value="7563620" label="Sidamo"/>
+ <int value="7563631" label="Siouan Language"/>
+ <int value="7563636" label="Sino-Tibetan Language"/>
+ <int value="7564385" label="Slavic Language"/>
+ <int value="7564641" label="Southern Sami"/>
+ <int value="7564649" label="Sami Language"/>
+ <int value="7564650" label="Lule Sami"/>
+ <int value="7564654" label="Inari Sami"/>
+ <int value="7564659" label="Skolt Sami"/>
+ <int value="7564907" label="Soninke"/>
+ <int value="7565159" label="Sogdien"/>
+ <int value="7565166" label="Songhai"/>
+ <int value="7565934" label="Sranan Tongo"/>
+ <int value="7565938" label="Serer"/>
+ <int value="7566177" label="Nilo-Saharan Language"/>
+ <int value="7566201" label="Saho"/>
+ <int value="7566699" label="Sukuma"/>
+ <int value="7566707" label="Susu"/>
+ <int value="7566712" label="Sumerian"/>
+ <int value="7567202" label="Comorian"/>
+ <int value="7567715" label="Classical Syriac"/>
+ <int value="7567730" label="Syriac"/>
+ <int value="7627113" label="Tai Language"/>
+ <int value="7628141" label="Timne"/>
+ <int value="7628143" label="Teso"/>
+ <int value="7628146" label="Tereno"/>
+ <int value="7628148" label="Tetum"/>
+ <int value="7629159" label="Tigre"/>
+ <int value="7629174" label="Tiv"/>
+ <int value="7629676" label="Tokelau"/>
+ <int value="7629928" label="Klingon"/>
+ <int value="7629929" label="Tlingit"/>
+ <int value="7630184" label="Tamashek"/>
+ <int value="7630695" label="Nyasa Tonga"/>
+ <int value="7630953" label="Tok Pisin"/>
+ <int value="7631478" label="Taroko"/>
+ <int value="7631721" label="Tsimshian"/>
+ <int value="7632237" label="Tumbuka"/>
+ <int value="7632240" label="Tupi Language"/>
+ <int value="7632244" label="Altaic Language"/>
+ <int value="7632492" label="Tuvalu"/>
+ <int value="7632753" label="Tasawaq"/>
+ <int value="7633270" label="Tuvinian"/>
+ <int value="7633517" label="Central Morocco Tamazight"/>
+ <int value="7693421" label="Udmurt"/>
+ <int value="7694177" label="Ugaritic"/>
+ <int value="7695714" label="Umbundu"/>
+ <int value="7695972" label="Unknown Language"/>
+ <int value="7758185" label="Vai"/>
+ <int value="7761780" label="Votic"/>
+ <int value="7763310" label="Vunjo"/>
+ <int value="7823723" label="Wakashan Language"/>
+ <int value="7823724" label="Walamo"/>
+ <int value="7823730" label="Waray"/>
+ <int value="7823731" label="Washo"/>
+ <int value="7824750" label="Sorbian Language"/>
+ <int value="7889260" label="Kalmyk"/>
+ <int value="7892839" label="Soga"/>
+ <int value="7954799" label="Yao"/>
+ <int value="7954800" label="Yapese"/>
+ <int value="7958635" label="Yupik Language"/>
+ <int value="7959909" label="Cantonese"/>
+ <int value="8020336" label="Zapotec"/>
+ <int value="8020588" label="Blissymbols"/>
+ <int value="8021358" label="Zenaga"/>
+ <int value="8023652" label="Zande"/>
+ <int value="8025454" label="Zuni"/>
+ <int value="8026232" label="No linguistic content"/>
+ <int value="8026721" label="Zaza"/>
+</enum>
+
+<enum name="LevelDBCorruptionTypes" type="int">
+ <int value="0" label="other"/>
+ <int value="1" label="missing files"/>
+ <int value="2" label="log record too small"/>
+ <int value="3" label="corrupted internal key"/>
+ <int value="4" label="partial record"/>
+ <int value="5" label="missing start of fragmented record"/>
+ <int value="6" label="error in middle of record"/>
+ <int value="7" label="unknown record type"/>
+ <int value="8" label="truncated record at end"/>
+ <int value="9" label="bad record length"/>
+ <int value="10" label="VersionEdit"/>
+ <int value="11" label="FileReader invoked with unexpected value"/>
+ <int value="12" label="corrupted key"/>
+ <int value="13" label="CURRENT file does not end with newline"/>
+ <int value="14" label="no meta-nextfile entry"/>
+ <int value="15" label="no meta-lognumber entry"/>
+ <int value="16" label="no last-sequence-number entry"/>
+ <int value="17" label="malformed WriteBatch"/>
+ <int value="18" label="bad WriteBatch Put"/>
+ <int value="19" label="bad WriteBatch Delete"/>
+ <int value="20" label="unknown WriteBatch tag"/>
+ <int value="21" label="WriteBatch has wrong count"/>
+ <int value="22" label="bad entry in block"/>
+ <int value="23" label="bad block contents"/>
+ <int value="24" label="bad block handle"/>
+ <int value="25" label="truncated block read"/>
+ <int value="26" label="block checksum mismatch"/>
+ <int value="27" label="checksum mismatch"/>
+ <int value="28" label="corrupted compressed block contents"/>
+ <int value="29" label="bad block type"/>
+ <int value="30" label="bad magic number"/>
+ <int value="31" label="file is too short"/>
+</enum>
+
+<enum name="LevelDBErrorCount" type="int">
+ <int value="1" label="Failure"/>
+</enum>
+
+<enum name="LevelDBErrorTypes" type="int">
+ <int value="0" label="NotFound"/>
+ <int value="1" label="Corruption"/>
+ <int value="2" label="IOError"/>
+ <int value="3" label="Other"/>
+</enum>
+
+<enum name="LevelDBIOErrorMethods" type="int">
+ <int value="0" label="SequentialFileRead"/>
+ <int value="1" label="SequentialFileSkip"/>
+ <int value="2" label="RandomAccessFileRead"/>
+ <int value="3" label="WritableFileAppend"/>
+ <int value="4" label="WritableFileClose"/>
+ <int value="5" label="WritableFileFlush"/>
+ <int value="6" label="WritableFileSync"/>
+ <int value="7" label="NewSequentialFile"/>
+ <int value="8" label="NewRandomAccessFile"/>
+ <int value="9" label="NewWritableFile"/>
+ <int value="10" label="DeleteFile"/>
+ <int value="11" label="CreateDir"/>
+ <int value="12" label="DeleteDir"/>
+ <int value="13" label="GetFileSize"/>
+ <int value="14" label="RenameFile"/>
+ <int value="15" label="LockFile"/>
+ <int value="16" label="UnlockFile"/>
+ <int value="17" label="GetTestDirectory"/>
+ <int value="18" label="NewLogger"/>
+ <int value="19" label="SyncParent"/>
+</enum>
+
+<enum name="LinkMonitorFailureType" type="int">
+ <int value="0" label="Local MAC Address Not Found"/>
+ <int value="1" label="Client Startup Failure"/>
+ <int value="2" label="Transmission Failure"/>
+ <int value="3" label="Failure Threshold Reached"/>
+</enum>
+
+<enum name="LinuxAudioIO" type="int">
+ <int value="0" label="PulseAudio"/>
+ <int value="1" label="ALSA"/>
+ <int value="2" label="Cras"/>
+</enum>
+
+<enum name="LinuxGlibcVersion" type="int">
+ <int value="0" label="Not Parseable"/>
+ <int value="1" label="Unknown"/>
+ <int value="2" label="2.11"/>
+ <int value="3" label="2.12"/>
+ <int value="4" label="2.13"/>
+ <int value="5" label="2.14"/>
+ <int value="6" label="2.15"/>
+ <int value="7" label="2.16"/>
+ <int value="8" label="2.17"/>
+ <int value="9" label="2.18"/>
+ <int value="10" label="2.19"/>
+</enum>
+
+<enum name="LoadType" type="int">
+ <int value="0" label="UNDEFINED_LOAD">Not yet initialized</int>
+ <int value="1" label="RELOAD">User pressed reload</int>
+ <int value="2" label="HISTORY_LOAD">Back or forward</int>
+ <int value="3" label="NORMAL_LOAD">User entered URL, or omnibox search</int>
+ <int value="4" label="LINK_LOAD">(deprecated) Included next 4 categories</int>
+ <int value="5" label="LINK_LOAD_NORMAL">Commonly following of link</int>
+ <int value="6" label="LINK_LOAD_RELOAD">JS/link directed reload</int>
+ <int value="7" label="LINK_LOAD_CACHE_STALE_OK">
+ back/forward or encoding change
+ </int>
+ <int value="8" label="LINK_LOAD_CACHE_ONLY">
+ Allow stale data (avoid doing a re-post)
+ </int>
+ <int value="9" label="PRERENDER_LOAD">Speculative prerendering of a page</int>
+</enum>
+
+<enum name="MappedCSSProperties" type="int">
+<!-- See http://src.chromium.org/viewvc/blink/trunk/Source/core/page/UseCounter.cpp -->
+
+ <int value="1" label="Total Pages Measured"/>
+ <int value="2" label="color"/>
+ <int value="3" label="direction"/>
+ <int value="4" label="display"/>
+ <int value="5" label="font"/>
+ <int value="6" label="font-family"/>
+ <int value="7" label="font-size"/>
+ <int value="8" label="font-style"/>
+ <int value="9" label="font-variant"/>
+ <int value="10" label="font-weight"/>
+ <int value="11" label="text-rendering"/>
+ <int value="12" label="webkit-font-feature-settings"/>
+ <int value="13" label="webkit-font-kerning"/>
+ <int value="14" label="webkit-font-smoothing"/>
+ <int value="15" label="webkit-font-variant-ligatures"/>
+ <int value="16" label="webkit-locale"/>
+ <int value="17" label="webkit-text-orientation"/>
+ <int value="18" label="webkit-writing-mode"/>
+ <int value="19" label="zoom"/>
+ <int value="20" label="line-height"/>
+ <int value="21" label="background"/>
+ <int value="22" label="background-attachment"/>
+ <int value="23" label="background-clip"/>
+ <int value="24" label="background-color"/>
+ <int value="25" label="background-image"/>
+ <int value="26" label="background-origin"/>
+ <int value="27" label="background-position"/>
+ <int value="28" label="background-position-x"/>
+ <int value="29" label="background-position-y"/>
+ <int value="30" label="background-repeat"/>
+ <int value="31" label="background-repeat-x"/>
+ <int value="32" label="background-repeat-y"/>
+ <int value="33" label="background-size"/>
+ <int value="34" label="border"/>
+ <int value="35" label="border-bottom"/>
+ <int value="36" label="border-bottom-color"/>
+ <int value="37" label="border-bottom-left-radius"/>
+ <int value="38" label="border-bottom-right-radius"/>
+ <int value="39" label="border-bottom-style"/>
+ <int value="40" label="border-bottom-width"/>
+ <int value="41" label="border-collapse"/>
+ <int value="42" label="border-color"/>
+ <int value="43" label="border-image"/>
+ <int value="44" label="border-image-outset"/>
+ <int value="45" label="border-image-repeat"/>
+ <int value="46" label="border-image-slice"/>
+ <int value="47" label="border-image-source"/>
+ <int value="48" label="border-image-width"/>
+ <int value="49" label="border-left"/>
+ <int value="50" label="border-left-color"/>
+ <int value="51" label="border-left-style"/>
+ <int value="52" label="border-left-width"/>
+ <int value="53" label="border-radius"/>
+ <int value="54" label="border-right"/>
+ <int value="55" label="border-right-color"/>
+ <int value="56" label="border-right-style"/>
+ <int value="57" label="border-right-width"/>
+ <int value="58" label="border-spacing"/>
+ <int value="59" label="border-style"/>
+ <int value="60" label="border-top"/>
+ <int value="61" label="border-top-color"/>
+ <int value="62" label="border-top-left-radius"/>
+ <int value="63" label="border-top-right-radius"/>
+ <int value="64" label="border-top-style"/>
+ <int value="65" label="border-top-width"/>
+ <int value="66" label="border-width"/>
+ <int value="67" label="bottom"/>
+ <int value="68" label="box-shadow"/>
+ <int value="69" label="box-sizing"/>
+ <int value="70" label="caption-side"/>
+ <int value="71" label="clear"/>
+ <int value="72" label="clip"/>
+ <int value="73" label="webkit-clip-path"/>
+ <int value="74" label="content"/>
+ <int value="75" label="counter-increment"/>
+ <int value="76" label="counter-reset"/>
+ <int value="77" label="cursor"/>
+ <int value="78" label="empty-cells"/>
+ <int value="79" label="float"/>
+ <int value="80" label="font-stretch"/>
+ <int value="81" label="height"/>
+ <int value="82" label="image-rendering"/>
+ <int value="83" label="left"/>
+ <int value="84" label="letter-spacing"/>
+ <int value="85" label="list-style"/>
+ <int value="86" label="list-style-image"/>
+ <int value="87" label="list-style-position"/>
+ <int value="88" label="list-style-type"/>
+ <int value="89" label="margin"/>
+ <int value="90" label="margin-bottom"/>
+ <int value="91" label="margin-left"/>
+ <int value="92" label="margin-right"/>
+ <int value="93" label="margin-top"/>
+ <int value="94" label="max-height"/>
+ <int value="95" label="max-width"/>
+ <int value="96" label="min-height"/>
+ <int value="97" label="min-width"/>
+ <int value="98" label="opacity"/>
+ <int value="99" label="orphans"/>
+ <int value="100" label="outline"/>
+ <int value="101" label="outline-color"/>
+ <int value="102" label="outline-offset"/>
+ <int value="103" label="outline-style"/>
+ <int value="104" label="outline-width"/>
+ <int value="105" label="overflow"/>
+ <int value="106" label="overflow-wrap"/>
+ <int value="107" label="overflow-x"/>
+ <int value="108" label="overflow-y"/>
+ <int value="109" label="padding"/>
+ <int value="110" label="padding-bottom"/>
+ <int value="111" label="padding-left"/>
+ <int value="112" label="padding-right"/>
+ <int value="113" label="padding-top"/>
+ <int value="114" label="page"/>
+ <int value="115" label="page-break-after"/>
+ <int value="116" label="page-break-before"/>
+ <int value="117" label="page-break-inside"/>
+ <int value="118" label="pointer-events"/>
+ <int value="119" label="position"/>
+ <int value="120" label="quotes"/>
+ <int value="121" label="resize"/>
+ <int value="122" label="right"/>
+ <int value="123" label="size"/>
+ <int value="124" label="src"/>
+ <int value="125" label="speak"/>
+ <int value="126" label="table-layout"/>
+ <int value="127" label="tab-size"/>
+ <int value="128" label="text-align"/>
+ <int value="129" label="text-decoration"/>
+ <int value="130" label="text-indent"/>
+ <int value="131" label="text-line-through"/>
+ <int value="132" label="text-line-through-color"/>
+ <int value="133" label="text-line-through-mode"/>
+ <int value="134" label="text-line-through-style"/>
+ <int value="135" label="text-line-through-width"/>
+ <int value="136" label="text-overflow"/>
+ <int value="137" label="text-overline"/>
+ <int value="138" label="text-overline-color"/>
+ <int value="139" label="text-overline-mode"/>
+ <int value="140" label="text-overline-style"/>
+ <int value="141" label="text-overline-width"/>
+ <int value="142" label="text-shadow"/>
+ <int value="143" label="text-transform"/>
+ <int value="144" label="text-underline"/>
+ <int value="145" label="text-underline-color"/>
+ <int value="146" label="text-underline-mode"/>
+ <int value="147" label="text-underline-style"/>
+ <int value="148" label="text-underline-width"/>
+ <int value="149" label="top"/>
+ <int value="150" label="transition"/>
+ <int value="151" label="transition-delay"/>
+ <int value="152" label="transition-duration"/>
+ <int value="153" label="transition-property"/>
+ <int value="154" label="transition-timing-function"/>
+ <int value="155" label="unicode-bidi"/>
+ <int value="156" label="unicode-range"/>
+ <int value="157" label="vertical-align"/>
+ <int value="158" label="visibility"/>
+ <int value="159" label="white-space"/>
+ <int value="160" label="widows"/>
+ <int value="161" label="width"/>
+ <int value="162" label="word-break"/>
+ <int value="163" label="word-spacing"/>
+ <int value="164" label="word-wrap"/>
+ <int value="165" label="z-index"/>
+ <int value="166" label="webkit-animation"/>
+ <int value="167" label="webkit-animation-delay"/>
+ <int value="168" label="webkit-animation-direction"/>
+ <int value="169" label="webkit-animation-duration"/>
+ <int value="170" label="webkit-animation-fill-mode"/>
+ <int value="171" label="webkit-animation-iteration-count"/>
+ <int value="172" label="webkit-animation-name"/>
+ <int value="173" label="webkit-animation-play-state"/>
+ <int value="174" label="webkit-animation-timing-function"/>
+ <int value="175" label="webkit-appearance"/>
+ <int value="176" label="webkit-aspect-ratio"/>
+ <int value="177" label="webkit-backface-visibility"/>
+ <int value="178" label="webkit-background-clip"/>
+ <int value="179" label="webkit-background-composite"/>
+ <int value="180" label="webkit-background-origin"/>
+ <int value="181" label="webkit-background-size"/>
+ <int value="182" label="webkit-border-after"/>
+ <int value="183" label="webkit-border-after-color"/>
+ <int value="184" label="webkit-border-after-style"/>
+ <int value="185" label="webkit-border-after-width"/>
+ <int value="186" label="webkit-border-before"/>
+ <int value="187" label="webkit-border-before-color"/>
+ <int value="188" label="webkit-border-before-style"/>
+ <int value="189" label="webkit-border-before-width"/>
+ <int value="190" label="webkit-border-end"/>
+ <int value="191" label="webkit-border-end-color"/>
+ <int value="192" label="webkit-border-end-style"/>
+ <int value="193" label="webkit-border-end-width"/>
+ <int value="194" label="webkit-border-fit"/>
+ <int value="195" label="webkit-border-horizontal-spacing"/>
+ <int value="196" label="webkit-border-image"/>
+ <int value="197" label="webkit-border-radius"/>
+ <int value="198" label="webkit-border-start"/>
+ <int value="199" label="webkit-border-start-color"/>
+ <int value="200" label="webkit-border-start-style"/>
+ <int value="201" label="webkit-border-start-width"/>
+ <int value="202" label="webkit-border-vertical-spacing"/>
+ <int value="203" label="webkit-box-align"/>
+ <int value="204" label="webkit-box-direction"/>
+ <int value="205" label="webkit-box-flex"/>
+ <int value="206" label="webkit-box-flex-group"/>
+ <int value="207" label="webkit-box-lines"/>
+ <int value="208" label="webkit-box-ordinal-group"/>
+ <int value="209" label="webkit-box-orient"/>
+ <int value="210" label="webkit-box-pack"/>
+ <int value="211" label="webkit-box-reflect"/>
+ <int value="212" label="webkit-box-shadow"/>
+ <int value="213" label="webkit-color-correction"/>
+ <int value="214" label="webkit-column-axis"/>
+ <int value="215" label="webkit-column-break-after"/>
+ <int value="216" label="webkit-column-break-before"/>
+ <int value="217" label="webkit-column-break-inside"/>
+ <int value="218" label="webkit-column-count"/>
+ <int value="219" label="webkit-column-gap"/>
+ <int value="220" label="webkit-column-progression"/>
+ <int value="221" label="webkit-column-rule"/>
+ <int value="222" label="webkit-column-rule-color"/>
+ <int value="223" label="webkit-column-rule-style"/>
+ <int value="224" label="webkit-column-rule-width"/>
+ <int value="225" label="webkit-column-span"/>
+ <int value="226" label="webkit-column-width"/>
+ <int value="227" label="webkit-columns"/>
+ <int value="228" label="webkit-box-decoration-break"/>
+ <int value="229" label="webkit-filter"/>
+ <int value="230" label="webkit-align-content"/>
+ <int value="231" label="webkit-align-items"/>
+ <int value="232" label="webkit-align-self"/>
+ <int value="233" label="webkit-flex"/>
+ <int value="234" label="webkit-flex-basis"/>
+ <int value="235" label="webkit-flex-direction"/>
+ <int value="236" label="webkit-flex-flow"/>
+ <int value="237" label="webkit-flex-grow"/>
+ <int value="238" label="webkit-flex-shrink"/>
+ <int value="239" label="webkit-flex-wrap"/>
+ <int value="240" label="webkit-justify-content"/>
+ <int value="241" label="webkit-font-size-delta"/>
+ <int value="242" label="webkit-grid-columns"/>
+ <int value="243" label="webkit-grid-rows"/>
+ <int value="244" label="webkit-grid-start"/>
+ <int value="245" label="webkit-grid-end"/>
+ <int value="246" label="webkit-grid-before"/>
+ <int value="247" label="webkit-grid-after"/>
+ <int value="248" label="webkit-grid-column"/>
+ <int value="249" label="webkit-grid-row"/>
+ <int value="250" label="webkit-grid-auto-flow"/>
+ <int value="251" label="webkit-highlight"/>
+ <int value="252" label="webkit-hyphenate-character"/>
+ <int value="253" label="webkit-hyphenate-limit-after"/>
+ <int value="254" label="webkit-hyphenate-limit-before"/>
+ <int value="255" label="webkit-hyphenate-limit-lines"/>
+ <int value="256" label="webkit-hyphens"/>
+ <int value="257" label="webkit-line-box-contain"/>
+ <int value="258" label="webkit-line-align"/>
+ <int value="259" label="webkit-line-break"/>
+ <int value="260" label="webkit-line-clamp"/>
+ <int value="261" label="webkit-line-grid"/>
+ <int value="262" label="webkit-line-snap"/>
+ <int value="263" label="webkit-logical-width"/>
+ <int value="264" label="webkit-logical-height"/>
+ <int value="265" label="webkit-margin-after-collapse"/>
+ <int value="266" label="webkit-margin-before-collapse"/>
+ <int value="267" label="webkit-margin-bottom-collapse"/>
+ <int value="268" label="webkit-margin-top-collapse"/>
+ <int value="269" label="webkit-margin-collapse"/>
+ <int value="270" label="webkit-margin-after"/>
+ <int value="271" label="webkit-margin-before"/>
+ <int value="272" label="webkit-margin-end"/>
+ <int value="273" label="webkit-margin-start"/>
+ <int value="274" label="webkit-marquee"/>
+ <int value="275" label="webkit-marquee-direction"/>
+ <int value="276" label="webkit-marquee-increment"/>
+ <int value="277" label="webkit-marquee-repetition"/>
+ <int value="278" label="webkit-marquee-speed"/>
+ <int value="279" label="webkit-marquee-style"/>
+ <int value="280" label="webkit-mask"/>
+ <int value="281" label="webkit-mask-box-image"/>
+ <int value="282" label="webkit-mask-box-image-outset"/>
+ <int value="283" label="webkit-mask-box-image-repeat"/>
+ <int value="284" label="webkit-mask-box-image-slice"/>
+ <int value="285" label="webkit-mask-box-image-source"/>
+ <int value="286" label="webkit-mask-box-image-width"/>
+ <int value="287" label="webkit-mask-clip"/>
+ <int value="288" label="webkit-mask-composite"/>
+ <int value="289" label="webkit-mask-image"/>
+ <int value="290" label="webkit-mask-origin"/>
+ <int value="291" label="webkit-mask-position"/>
+ <int value="292" label="webkit-mask-position-x"/>
+ <int value="293" label="webkit-mask-position-y"/>
+ <int value="294" label="webkit-mask-repeat"/>
+ <int value="295" label="webkit-mask-repeat-x"/>
+ <int value="296" label="webkit-mask-repeat-y"/>
+ <int value="297" label="webkit-mask-size"/>
+ <int value="298" label="webkit-max-logical-width"/>
+ <int value="299" label="webkit-max-logical-height"/>
+ <int value="300" label="webkit-min-logical-width"/>
+ <int value="301" label="webkit-min-logical-height"/>
+ <int value="302" label="webkit-nbsp-mode"/>
+ <int value="303" label="webkit-order"/>
+ <int value="304" label="webkit-padding-after"/>
+ <int value="305" label="webkit-padding-before"/>
+ <int value="306" label="webkit-padding-end"/>
+ <int value="307" label="webkit-padding-start"/>
+ <int value="308" label="webkit-perspective"/>
+ <int value="309" label="webkit-perspective-origin"/>
+ <int value="310" label="webkit-perspective-origin-x"/>
+ <int value="311" label="webkit-perspective-origin-y"/>
+ <int value="312" label="webkit-print-color-adjust"/>
+ <int value="313" label="webkit-rtl-ordering"/>
+ <int value="314" label="webkit-ruby-position"/>
+ <int value="315" label="webkit-text-combine"/>
+ <int value="316" label="webkit-text-decorations-in-effect"/>
+ <int value="317" label="webkit-text-emphasis"/>
+ <int value="318" label="webkit-text-emphasis-color"/>
+ <int value="319" label="webkit-text-emphasis-position"/>
+ <int value="320" label="webkit-text-emphasis-style"/>
+ <int value="321" label="webkit-text-fill-color"/>
+ <int value="322" label="webkit-text-security"/>
+ <int value="323" label="webkit-text-stroke"/>
+ <int value="324" label="webkit-text-stroke-color"/>
+ <int value="325" label="webkit-text-stroke-width"/>
+ <int value="326" label="webkit-transform"/>
+ <int value="327" label="webkit-transform-origin"/>
+ <int value="328" label="webkit-transform-origin-x"/>
+ <int value="329" label="webkit-transform-origin-y"/>
+ <int value="330" label="webkit-transform-origin-z"/>
+ <int value="331" label="webkit-transform-style"/>
+ <int value="332" label="webkit-transition"/>
+ <int value="333" label="webkit-transition-delay"/>
+ <int value="334" label="webkit-transition-duration"/>
+ <int value="335" label="webkit-transition-property"/>
+ <int value="336" label="webkit-transition-timing-function"/>
+ <int value="337" label="webkit-user-drag"/>
+ <int value="338" label="webkit-user-modify"/>
+ <int value="339" label="webkit-user-select"/>
+ <int value="340" label="webkit-flow-into"/>
+ <int value="341" label="webkit-flow-from"/>
+ <int value="342" label="webkit-region-overflow"/>
+ <int value="343" label="webkit-region-break-after"/>
+ <int value="344" label="webkit-region-break-before"/>
+ <int value="345" label="webkit-region-break-inside"/>
+ <int value="346" label="webkit-shape-inside"/>
+ <int value="347" label="webkit-shape-outside"/>
+ <int value="348" label="webkit-shape-margin"/>
+ <int value="349" label="webkit-shape-padding"/>
+ <int value="350" label="webkit-wrap-flow"/>
+ <int value="351" label="webkit-wrap-through"/>
+ <int value="352" label="webkit-wrap"/>
+ <int value="353" label="webkit-tap-highlight-color"/>
+ <int value="354" label="webkit-app-region"/>
+ <int value="355" label="clip-path"/>
+ <int value="356" label="clip-rule"/>
+ <int value="357" label="mask"/>
+ <int value="358" label="enable-background"/>
+ <int value="359" label="filter"/>
+ <int value="360" label="flood-color"/>
+ <int value="361" label="flood-opacity"/>
+ <int value="362" label="lighting-color"/>
+ <int value="363" label="stop-color"/>
+ <int value="364" label="stop-opacity"/>
+ <int value="365" label="color-interpolation"/>
+ <int value="366" label="color-interpolation-filters"/>
+ <int value="367" label="color-profile"/>
+ <int value="368" label="color-rendering"/>
+ <int value="369" label="fill"/>
+ <int value="370" label="fill-opacity"/>
+ <int value="371" label="fill-rule"/>
+ <int value="372" label="marker"/>
+ <int value="373" label="marker-end"/>
+ <int value="374" label="marker-mid"/>
+ <int value="375" label="marker-start"/>
+ <int value="376" label="mask-type"/>
+ <int value="377" label="shape-rendering"/>
+ <int value="378" label="stroke"/>
+ <int value="379" label="stroke-dasharray"/>
+ <int value="380" label="stroke-dashoffset"/>
+ <int value="381" label="stroke-linecap"/>
+ <int value="382" label="stroke-linejoin"/>
+ <int value="383" label="stroke-miterlimit"/>
+ <int value="384" label="stroke-opacity"/>
+ <int value="385" label="stroke-width"/>
+ <int value="386" label="alignment-baseline"/>
+ <int value="387" label="baseline-shift"/>
+ <int value="388" label="dominant-baseline"/>
+ <int value="389" label="glyph-orientation-horizontal"/>
+ <int value="390" label="glyph-orientation-vertical"/>
+ <int value="391" label="kerning"/>
+ <int value="392" label="text-anchor"/>
+ <int value="393" label="vector-effect"/>
+ <int value="394" label="writing-mode"/>
+ <int value="395" label="webkit-svg-shadow"/>
+ <int value="396" label="webkit-cursor-visibility"/>
+ <int value="397" label="image-orientation"/>
+ <int value="398" label="image-resolution"/>
+ <int value="399" label="webkit-blend-mode"/>
+ <int value="400" label="webkit-background-blend-mode"/>
+ <int value="401" label="webkit-text-decoration-line"/>
+ <int value="402" label="webkit-text-decoration-style"/>
+ <int value="403" label="webkit-text-decoration-color"/>
+ <int value="404" label="webkit-text-align-last"/>
+ <int value="405" label="webkit-text-underline-position"/>
+ <int value="406" label="max-zoom"/>
+ <int value="407" label="min-zoom"/>
+ <int value="408" label="orientation"/>
+ <int value="409" label="user-zoom"/>
+ <int value="410" label="webkit-dashboard-region"/>
+ <int value="411" label="webkit-overflow-scrolling"/>
+ <int value="412" label="webkit-app-region"/>
+ <int value="413" label="webkit-filter"/>
+ <int value="414" label="webkit-box-decoration-break"/>
+ <int value="415" label="webkit-tap-highlight-color"/>
+ <int value="416" label="buffered-rendering"/>
+ <int value="417" label="grid-auto-rows"/>
+ <int value="418" label="grid-auto-columns"/>
+ <int value="419" label="background-blend-mode"/>
+ <int value="420" label="mix-blend-mode"/>
+ <int value="421" label="touch-action"/>
+ <int value="422" label="grid-area"/>
+</enum>
+
+<enum name="MediaContainers" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="AAC (Advanced Audio Coding)"/>
+ <int value="2" label="AC-3"/>
+ <int value="3" label="AIFF (Audio Interchange File Format)"/>
+ <int value="4" label="AMR (Adaptive Multi-Rate Audio)"/>
+ <int value="5" label="APE (Monkey's Audio)"/>
+ <int value="6" label="ASF (Advanced / Active Streaming Format)"/>
+ <int value="7" label="SSA (SubStation Alpha) subtitle"/>
+ <int value="8" label="AVI (Audio Video Interleaved)"/>
+ <int value="9" label="Bink"/>
+ <int value="10" label="CAF (Apple Core Audio Format)"/>
+ <int value="11" label="DTS"/>
+ <int value="12" label="DTS-HD"/>
+ <int value="13" label="DV (Digital Video)"/>
+ <int value="14" label="DXA"/>
+ <int value="15" label="Enhanced AC-3"/>
+ <int value="16" label="FLAC (Free Lossless Audio Codec)"/>
+ <int value="17" label="FLV (Flash Video)"/>
+ <int value="18" label="GSM (Global System for Mobile Audio)"/>
+ <int value="19" label="H.261"/>
+ <int value="20" label="H.263"/>
+ <int value="21" label="H.264"/>
+ <int value="22" label="HLS (Apple HTTP Live Streaming PlayList)"/>
+ <int value="23" label="Berkeley/IRCAM/CARL Sound Format"/>
+ <int value="24" label="MJPEG video"/>
+ <int value="25" label="QuickTime / MOV / MPEG4"/>
+ <int value="26" label="MP3 (MPEG audio layer 2/3)"/>
+ <int value="27" label="MPEG-2 Program Stream"/>
+ <int value="28" label="MPEG-2 Transport Stream"/>
+ <int value="29" label="MPEG-4 Bitstream"/>
+ <int value="30" label="Ogg"/>
+ <int value="31" label="RM (RealMedia)"/>
+ <int value="32" label="SRT (SubRip subtitle)"/>
+ <int value="33" label="SWF (ShockWave Flash)"/>
+ <int value="34" label="VC-1"/>
+ <int value="35" label="WAV / WAVE (Waveform Audio)"/>
+ <int value="36" label="Matroska / WebM"/>
+ <int value="37" label="WTV (Windows Television)"/>
+</enum>
+
+<enum name="MediaKeyError" type="int">
+ <int value="1" label="kUnknownError"/>
+ <int value="2" label="kClientError"/>
+</enum>
+
+<enum name="MediaKeyException" type="int">
+ <int value="0" label="kUnknownResultId"/>
+ <int value="1" label="kSuccess"/>
+ <int value="2" label="kKeySystemNotSupported"/>
+ <int value="3" label="kInvalidPlayerState"/>
+</enum>
+
+<enum name="MobileSessionCallerApp" type="int">
+ <int value="0" label="Google Search"/>
+ <int value="1" label="GMail"/>
+ <int value="2" label="Google+"/>
+ <int value="3" label="Google Drive"/>
+ <int value="4" label="Google Earth"/>
+ <int value="5" label="Other Google Apps"/>
+ <int value="6" label="Others"/>
+ <int value="7" label="Mobile Safari"/>
+ <int value="8" label="Other Apple Apps"/>
+ <int value="9" label="YouTube"/>
+ <int value="10" label="Google Maps"/>
+</enum>
+
+<enum name="MobileSessionStartAction" type="int">
+ <int value="0" label="Open http"/>
+ <int value="1" label="Open https"/>
+ <int value="2" label="Open file"/>
+ <int value="3" label="x-callback-url open"/>
+ <int value="4" label="x-callback-url other"/>
+ <int value="5" label="Others"/>
+</enum>
+
+<enum name="MouseEventFollowedByClick" type="int">
+ <int value="0" label="Missed event before click"/>
+ <int value="1" label="Caught event before click"/>
+</enum>
+
+<enum name="MSECodec" type="int">
+ <int value="0" label="(Unknown)"/>
+ <int value="1" label="VP8"/>
+ <int value="2" label="VP9"/>
+ <int value="3" label="Vorbis"/>
+ <int value="4" label="H.264"/>
+ <int value="5" label="MPEG2 AAC"/>
+ <int value="6" label="MPEG4 AAC"/>
+ <int value="7" label="EAC3"/>
+</enum>
+
+<enum name="NavigationScheme" type="int">
+ <int value="0" label="(Unknown)"/>
+ <int value="1" label="http"/>
+ <int value="2" label="https"/>
+ <int value="3" label="file"/>
+ <int value="4" label="ftp"/>
+ <int value="5" label="data"/>
+ <int value="6" label="javascript"/>
+ <int value="7" label="about"/>
+ <int value="8" label="chrome"/>
+</enum>
+
+<enum name="NetConnectivityProtocolStatus" type="int">
+ <int value="0" label="SUCCESS"/>
+ <int value="1" label="IP_STRING_PARSE_FAILED"/>
+ <int value="2" label="SOCKET_CREATE_FAILED"/>
+ <int value="3" label="RESOLVE_FAILED"/>
+ <int value="4" label="CONNECT_FAILED"/>
+ <int value="5" label="WRITE_FAILED"/>
+ <int value="6" label="READ_TIMED_OUT"/>
+ <int value="7" label="READ_FAILED"/>
+ <int value="8" label="ZERO_LENGTH_ERROR"/>
+ <int value="9" label="NO_CHECKSUM_ERROR"/>
+ <int value="10" label="NO_KEY_ERROR"/>
+ <int value="11" label="NO_PAYLOAD_SIZE_ERROR"/>
+ <int value="12" label="NO_PAYLOAD_ERROR"/>
+ <int value="13" label="INVALID_KEY_ERROR"/>
+ <int value="14" label="TOO_SHORT_PAYLOAD"/>
+ <int value="15" label="TOO_LONG_PAYLOAD"/>
+ <int value="16" label="INVALID_CHECKSUM"/>
+ <int value="17" label="PATTERN_CHANGED"/>
+ <int value="18" label="INVALID_PACKET_NUMBER"/>
+ <int value="19" label="TOO_MANY_PACKETS"/>
+ <int value="20" label="STATUS_MAX"/>
+</enum>
+
+<enum name="NetConnectivityStatus" type="int">
+ <int value="0" label="SUCCESS"/>
+ <int value="1" label="IP_STRING_PARSE_FAILED"/>
+ <int value="2" label="SOCKET_CREATE_FAILED"/>
+ <int value="3" label="RESOLVE_FAILED"/>
+ <int value="4" label="CONNECT_FAILED"/>
+ <int value="5" label="WRITE_FAILED"/>
+ <int value="6" label="READ_TIMED_OUT"/>
+ <int value="7" label="READ_FAILED"/>
+ <int value="8" label="READ_VERIFY_FAILED"/>
+ <int value="9" label="STATUS_MAX"/>
+</enum>
+
+<enum name="NetErrorCodes" type="int">
+ <int value="0" label="OK"/>
+ <int value="1" label="IO_PENDING"/>
+ <int value="2" label="FAILED"/>
+ <int value="3" label="ABORTED"/>
+ <int value="4" label="INVALID_ARGUMENT"/>
+ <int value="5" label="INVALID_HANDLE"/>
+ <int value="6" label="FILE_NOT_FOUND"/>
+ <int value="7" label="TIMED_OUT"/>
+ <int value="8" label="FILE_TOO_BIG"/>
+ <int value="9" label="UNEXPECTED"/>
+ <int value="10" label="ACCESS_DENIED"/>
+ <int value="11" label="NOT_IMPLEMENTED"/>
+ <int value="12" label="INSUFFICIENT_RESOURCES"/>
+ <int value="13" label="OUT_OF_MEMORY"/>
+ <int value="14" label="UPLOAD_FILE_CHANGED"/>
+ <int value="15" label="SOCKET_NOT_CONNECTED"/>
+ <int value="16" label="FILE_EXISTS"/>
+ <int value="17" label="FILE_PATH_TOO_LONG"/>
+ <int value="18" label="FILE_NO_SPACE"/>
+ <int value="19" label="FILE_VIRUS_INFECTED"/>
+ <int value="20" label="BLOCKED_BY_CLIENT"/>
+ <int value="21" label="NETWORK_CHANGED"/>
+ <int value="22" label="BLOCKED_BY_ADMINISTRATOR"/>
+ <int value="100" label="CONNECTION_CLOSED"/>
+ <int value="101" label="CONNECTION_RESET"/>
+ <int value="102" label="CONNECTION_REFUSED"/>
+ <int value="103" label="CONNECTION_ABORTED"/>
+ <int value="104" label="CONNECTION_FAILED"/>
+ <int value="105" label="NAME_NOT_RESOLVED"/>
+ <int value="106" label="INTERNET_DISCONNECTED"/>
+ <int value="107" label="SSL_PROTOCOL_ERROR"/>
+ <int value="108" label="ADDRESS_INVALID"/>
+ <int value="109" label="ADDRESS_UNREACHABLE"/>
+ <int value="110" label="SSL_CLIENT_AUTH_CERT_NEEDED"/>
+ <int value="111" label="TUNNEL_CONNECTION_FAILED"/>
+ <int value="112" label="NO_SSL_VERSIONS_ENABLED"/>
+ <int value="113" label="SSL_VERSION_OR_CIPHER_MISMATCH"/>
+ <int value="114" label="SSL_RENEGOTIATION_REQUESTED"/>
+ <int value="115" label="PROXY_AUTH_UNSUPPORTED"/>
+ <int value="116" label="CERT_ERROR_IN_SSL_RENEGOTIATION"/>
+ <int value="117" label="BAD_SSL_CLIENT_AUTH_CERT"/>
+ <int value="118" label="CONNECTION_TIMED_OUT"/>
+ <int value="119" label="HOST_RESOLVER_QUEUE_TOO_LARGE"/>
+ <int value="120" label="SOCKS_CONNECTION_FAILED"/>
+ <int value="121" label="SOCKS_CONNECTION_HOST_UNREACHABLE"/>
+ <int value="122" label="NPN_NEGOTIATION_FAILED"/>
+ <int value="123" label="SSL_NO_RENEGOTIATION"/>
+ <int value="124" label="WINSOCK_UNEXPECTED_WRITTEN_BYTES"/>
+ <int value="125" label="SSL_DECOMPRESSION_FAILURE_ALERT"/>
+ <int value="126" label="SSL_BAD_RECORD_MAC_ALERT"/>
+ <int value="127" label="PROXY_AUTH_REQUESTED"/>
+ <int value="128" label="SSL_UNSAFE_NEGOTIATION"/>
+ <int value="129" label="SSL_WEAK_SERVER_EPHEMERAL_DH_KEY"/>
+ <int value="130" label="PROXY_CONNECTION_FAILED"/>
+ <int value="131" label="MANDATORY_PROXY_CONFIGURATION_FAILED"/>
+ <int value="132" label="ESET_ANTI_VIRUS_SSL_INTERCEPTION"/>
+ <int value="133" label="PRECONNECT_MAX_SOCKET_LIMIT"/>
+ <int value="134" label="SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED"/>
+ <int value="135" label="SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY"/>
+ <int value="136" label="PROXY_CERTIFICATE_INVALID"/>
+ <int value="137" label="NAME_RESOLUTION_FAILED"/>
+ <int value="138" label="NETWORK_ACCESS_DENIED"/>
+ <int value="139" label="TEMPORARILY_THROTTLED"/>
+ <int value="140" label="HTTPS_PROXY_TUNNEL_RESPONSE"/>
+ <int value="141" label="SSL_CLIENT_AUTH_SIGNATURE_FAILED"/>
+ <int value="142" label="MSG_TOO_BIG"/>
+ <int value="143" label="KASPERSKY_ANTI_VIRUS_SSL_INTERCEPTION"/>
+ <int value="144" label="LIMIT_VIOLATION"/>
+ <int value="145" label="WS_PROTOCOL_ERROR"/>
+ <int value="146" label="PROTOCOL_SWITCHED"/>
+ <int value="147" label="ADDRESS_IN_USE"/>
+ <int value="148" label="SSL_HANDSHAKE_NOT_COMPLETED"/>
+ <int value="149" label="SSL_BAD_PEER_PUBLIC_KEY"/>
+ <int value="150" label="SSL_PINNED_KEY_NOT_IN_CERT_CHAIN"/>
+ <int value="151" label="CLIENT_AUTH_CERT_TYPE_UNSUPPORTED"/>
+ <int value="152" label="ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH"/>
+ <int value="200" label="CERT_COMMON_NAME_INVALID"/>
+ <int value="201" label="CERT_DATE_INVALID"/>
+ <int value="202" label="CERT_AUTHORITY_INVALID"/>
+ <int value="203" label="CERT_CONTAINS_ERRORS"/>
+ <int value="204" label="CERT_NO_REVOCATION_MECHANISM"/>
+ <int value="205" label="CERT_UNABLE_TO_CHECK_REVOCATION"/>
+ <int value="206" label="CERT_REVOKED"/>
+ <int value="207" label="CERT_INVALID"/>
+ <int value="208" label="CERT_WEAK_SIGNATURE_ALGORITHM"/>
+ <int value="209" label="CERT_NOT_IN_DNS"/>
+ <int value="210" label="CERT_NON_UNIQUE_NAME"/>
+ <int value="211" label="CERT_WEAK_KEY"/>
+ <int value="300" label="INVALID_URL"/>
+ <int value="301" label="DISALLOWED_URL_SCHEME"/>
+ <int value="302" label="UNKNOWN_URL_SCHEME"/>
+ <int value="310" label="TOO_MANY_REDIRECTS"/>
+ <int value="311" label="UNSAFE_REDIRECT"/>
+ <int value="312" label="UNSAFE_PORT"/>
+ <int value="320" label="INVALID_RESPONSE"/>
+ <int value="321" label="INVALID_CHUNKED_ENCODING"/>
+ <int value="322" label="METHOD_NOT_SUPPORTED"/>
+ <int value="323" label="UNEXPECTED_PROXY_AUTH"/>
+ <int value="324" label="EMPTY_RESPONSE"/>
+ <int value="325" label="RESPONSE_HEADERS_TOO_BIG"/>
+ <int value="326" label="PAC_STATUS_NOT_OK"/>
+ <int value="327" label="PAC_SCRIPT_FAILED"/>
+ <int value="328" label="REQUEST_RANGE_NOT_SATISFIABLE"/>
+ <int value="329" label="MALFORMED_IDENTITY"/>
+ <int value="330" label="CONTENT_DECODING_FAILED"/>
+ <int value="331" label="NETWORK_IO_SUSPENDED"/>
+ <int value="332" label="SYN_REPLY_NOT_RECEIVED"/>
+ <int value="333" label="ENCODING_CONVERSION_FAILED"/>
+ <int value="334" label="UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT"/>
+ <int value="335" label="INVALID_SPDY_STREAM"/>
+ <int value="336" label="NO_SUPPORTED_PROXIES"/>
+ <int value="337" label="SPDY_PROTOCOL_ERROR"/>
+ <int value="338" label="INVALID_AUTH_CREDENTIALS"/>
+ <int value="339" label="UNSUPPORTED_AUTH_SCHEME"/>
+ <int value="340" label="ENCODING_DETECTION_FAILED"/>
+ <int value="341" label="MISSING_AUTH_CREDENTIALS"/>
+ <int value="342" label="UNEXPECTED_SECURITY_LIBRARY_STATUS"/>
+ <int value="343" label="MISCONFIGURED_AUTH_ENVIRONMENT"/>
+ <int value="344" label="UNDOCUMENTED_SECURITY_LIBRARY_STATUS"/>
+ <int value="345" label="RESPONSE_BODY_TOO_BIG_TO_DRAIN"/>
+ <int value="346" label="RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH"/>
+ <int value="347" label="INCOMPLETE_SPDY_HEADERS"/>
+ <int value="348" label="PAC_NOT_IN_DHCP"/>
+ <int value="349" label="RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION"/>
+ <int value="350" label="RESPONSE_HEADERS_MULTIPLE_LOCATION"/>
+ <int value="351" label="SPDY_SERVER_REFUSED_STREAM"/>
+ <int value="352" label="SPDY_PING_FAILED"/>
+ <int value="353" label="PIPELINE_EVICTION"/>
+ <int value="354" label="CONTENT_LENGTH_MISMATCH"/>
+ <int value="355" label="INCOMPLETE_CHUNKED_ENCODING"/>
+ <int value="356" label="QUIC_PROTOCOL_ERROR"/>
+ <int value="357" label="RESPONSE_HEADERS_TRUNCATED"/>
+ <int value="400" label="CACHE_MISS"/>
+ <int value="401" label="CACHE_READ_FAILURE"/>
+ <int value="402" label="CACHE_WRITE_FAILURE"/>
+ <int value="403" label="CACHE_OPERATION_NOT_SUPPORTED"/>
+ <int value="404" label="CACHE_OPEN_FAILURE"/>
+ <int value="405" label="CACHE_CREATE_FAILURE"/>
+ <int value="406" label="CACHE_RACE"/>
+ <int value="407" label="CACHE_CACHE_CHECKSUM_READ_FAILURE"/>
+ <int value="408" label="CACHE_CACHE_CHECKSUM_MISMATCH"/>
+ <int value="501" label="INSECURE_RESPONSE"/>
+ <int value="502" label="NO_PRIVATE_KEY_FOR_CERT"/>
+ <int value="503" label="ADD_USER_CERT_FAILED"/>
+ <int value="601" label="FTP_FAILED"/>
+ <int value="602" label="FTP_SERVICE_UNAVAILABLE"/>
+ <int value="603" label="FTP_TRANSFER_ABORTED"/>
+ <int value="604" label="FTP_FILE_BUSY"/>
+ <int value="605" label="FTP_SYNTAX_ERROR"/>
+ <int value="606" label="FTP_COMMAND_NOT_SUPPORTED"/>
+ <int value="607" label="FTP_BAD_COMMAND_SEQUENCE"/>
+ <int value="701" label="PKCS12_IMPORT_BAD_PASSWORD"/>
+ <int value="702" label="PKCS12_IMPORT_FAILED"/>
+ <int value="703" label="IMPORT_CA_CERT_NOT_CA"/>
+ <int value="704" label="IMPORT_CERT_ALREADY_EXISTS"/>
+ <int value="705" label="IMPORT_CA_CERT_FAILED"/>
+ <int value="706" label="IMPORT_SERVER_CERT_FAILED"/>
+ <int value="707" label="PKCS12_IMPORT_INVALID_MAC"/>
+ <int value="708" label="PKCS12_IMPORT_INVALID_FILE"/>
+ <int value="709" label="PKCS12_IMPORT_UNSUPPORTED"/>
+ <int value="710" label="KEY_GENERATION_FAILED"/>
+ <int value="711" label="ORIGIN_BOUND_CERT_GENERATION_FAILED"/>
+ <int value="712" label="PRIVATE_KEY_EXPORT_FAILED"/>
+ <int value="800" label="DNS_MALFORMED_RESPONSE"/>
+ <int value="801" label="DNS_SERVER_REQUIRES_TCP"/>
+ <int value="802" label="DNS_SERVER_FAILED"/>
+ <int value="803" label="DNS_TIMED_OUT"/>
+ <int value="804" label="DNS_CACHE_MISS"/>
+ <int value="805" label="DNS_SEARCH_EMPTY"/>
+ <int value="806" label="DNS_SORT_ERROR"/>
+</enum>
+
+<enum name="NetPreconnectUtilization" type="int">
+ <int value="0" label="non-speculative, never connected"/>
+ <int value="1" label="non-speculative, never used"/>
+ <int value="2" label="non-speculative and used"/>
+ <int value="3" label="omnibox never connected"/>
+ <int value="4" label="omnibox never used"/>
+ <int value="5" label="omnibox and used"/>
+ <int value="6" label="subresource never connected"/>
+ <int value="7" label="subresource never used"/>
+ <int value="8" label="subresource and used"/>
+</enum>
+
+<enum name="Network3GGobiError" type="int">
+ <summary>
+ These error indexes are produced by QCErrorToMetricIndex() in
+ gobi-cromo-plugin.
+ </summary>
+ <int value="0" label="NONE"/>
+ <int value="1" label="QMI_HARDWARE_RESTRICTED"/>
+</enum>
+
+<enum name="NetworkAuthModeType" type="int">
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="EAP-AKA"/>
+ <int value="2" label="EAP-FAST"/>
+ <int value="3" label="EAP-GPSK"/>
+ <int value="4" label="EAP-GTC"/>
+ <int value="5" label="EAP-IKEV2"/>
+ <int value="6" label="EAP-LEAP"/>
+ <int value="7" label="EAP-MD5"/>
+ <int value="8" label="EAP-MSCHAPV2"/>
+ <int value="9" label="EAP-OTP"/>
+ <int value="10" label="EAP-PAX"/>
+ <int value="11" label="EAP-PEAP"/>
+ <int value="12" label="EAP-PSK"/>
+ <int value="13" label="EAP-SAKE"/>
+ <int value="14" label="EAP-SIM"/>
+ <int value="15" label="EAP-TLS"/>
+ <int value="16" label="EAP-TNC"/>
+ <int value="17" label="EAP-TTLS"/>
+</enum>
+
+<enum name="NetworkCellular3GPPRegistrationDelayedDrop" type="int">
+ <int value="0" label="Delayed drop posted">
+ A signal loss in the cellular service was detected and a delayed connection
+ drop request was posted. This request causes the cellular connection to be
+ dropped if it is not cancelled within the delay provided.
+ </int>
+ <int value="1" label="Delayed drop canceled">
+ Signal strength returned to normal soon after a delayed drop request was
+ made, causing the request to be canceled. This indicates a flaky network.
+ </int>
+</enum>
+
+<enum name="NetworkCellularOutOfCreditsReason" type="int">
+ <int value="0" label="Connect-Disconnect Loop"/>
+ <int value="1" label="TX-Queue Congestion"/>
+ <int value="2" label="Elongated Time Wait"/>
+</enum>
+
+<enum name="NetworkCellularTechnology" type="int">
+ <int value="0" label="1XRTT"/>
+ <int value="1" label="EDGE"/>
+ <int value="2" label="EVDO"/>
+ <int value="3" label="GPRS"/>
+ <int value="4" label="GSM"/>
+ <int value="5" label="HSPA"/>
+ <int value="6" label="HSPA_PLUS"/>
+ <int value="7" label="LTE"/>
+ <int value="8" label="UMTS"/>
+ <int value="9" label="Unknown"/>
+</enum>
+
+<enum name="NetworkCellularUsageRequestStatus" type="int">
+ <summary>
+ Status code that we received in response to a cellular usage API request.
+ </summary>
+ <int value="0" label="Failed">
+ This value is distinct from the others in that it indicates that we were
+ unable to issue a request or that we received no reply. The other values
+ represent the status code contained in a reply.
+ </int>
+ <int value="1" label="Ok"/>
+ <int value="2" label="Error"/>
+ <int value="3" label="Malformed Request"/>
+ <int value="4" label="Internal Error"/>
+ <int value="5" label="Service Unavailable"/>
+ <int value="6" label="Request Refused"/>
+ <int value="7" label="Unknown Device"/>
+</enum>
+
+<enum name="NetworkChannelType" type="int">
+ <int value="0" label="UNDEF"/>
+ <int value="1" label="2412"/>
+ <int value="2" label="2417"/>
+ <int value="3" label="2422"/>
+ <int value="4" label="2427"/>
+ <int value="5" label="2432"/>
+ <int value="6" label="2437"/>
+ <int value="7" label="2442"/>
+ <int value="8" label="2447"/>
+ <int value="9" label="2452"/>
+ <int value="10" label="2457"/>
+ <int value="11" label="2462"/>
+ <int value="12" label="2467"/>
+ <int value="13" label="2472"/>
+ <int value="14" label="2484"/>
+ <int value="15" label="5180"/>
+ <int value="16" label="5200"/>
+ <int value="17" label="5220"/>
+ <int value="18" label="5240"/>
+ <int value="19" label="5260"/>
+ <int value="20" label="5280"/>
+ <int value="21" label="5300"/>
+ <int value="22" label="5320"/>
+ <int value="23" label="5500"/>
+ <int value="24" label="5520"/>
+ <int value="25" label="5540"/>
+ <int value="26" label="5560"/>
+ <int value="27" label="5580"/>
+ <int value="28" label="5600"/>
+ <int value="29" label="5620"/>
+ <int value="30" label="5640"/>
+ <int value="31" label="5660"/>
+ <int value="32" label="5680"/>
+ <int value="33" label="5700"/>
+ <int value="34" label="5745"/>
+ <int value="35" label="5765"/>
+ <int value="36" label="5785"/>
+ <int value="37" label="5805"/>
+ <int value="38" label="5825"/>
+ <int value="39" label="5170"/>
+ <int value="40" label="5190"/>
+ <int value="41" label="5210"/>
+ <int value="42" label="5230"/>
+</enum>
+
+<enum name="NetworkCorruptedProfile" type="int">
+ <int value="0" label="Corrupted Profile"/>
+</enum>
+
+<enum name="NetworkDisconnectType" type="int">
+ <int value="0" label="System Disconnect"/>
+ <int value="1" label="User Disconnect"/>
+</enum>
+
+<enum name="NetworkPhyModeType" type="int">
+ <int value="0" label="UNDEF"/>
+ <int value="1" label="802.11a"/>
+ <int value="2" label="802.11b"/>
+ <int value="3" label="802.11g"/>
+ <int value="4" label="802.11n"/>
+ <int value="5" label="PSB 10MHz-wide"/>
+ <int value="6" label="PSB 5MHz-wide"/>
+</enum>
+
+<enum name="NetworkPortalResult" type="int">
+ <summary>
+ The portal result types come from PortalResult in shill/metrics.h
+ </summary>
+ <int value="0" label="Success"/>
+ <int value="1" label="DNS Failure"/>
+ <int value="2" label="DNS Timeout"/>
+ <int value="3" label="Connection Failure"/>
+ <int value="4" label="Connection Timeout"/>
+ <int value="5" label="HTTP Failure"/>
+ <int value="6" label="HTTP Timeout"/>
+ <int value="7" label="Content Failure"/>
+ <int value="8" label="Content Timeout"/>
+ <int value="9" label="Unknown"/>
+</enum>
+
+<enum name="NetworkSecurityType" type="int">
+ <summary>
+ The security types come from the connman_service_security enum in
+ flimflam/include/service.h
+ </summary>
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="NONE"/>
+ <int value="2" label="WEP"/>
+ <int value="3" label="WPA"/>
+ <int value="4" label="802.11i/RSN"/>
+ <int value="5" label="802.1x"/>
+ <int value="6" label="PSK"/>
+</enum>
+
+<enum name="NetworkServiceError" type="int">
+ <summary>
+ The error types come from the connman_service_error enum in
+ flimflam/include/service.h
+ </summary>
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="OUT_OF_RANGE"/>
+ <int value="2" label="PIN_MISSING"/>
+ <int value="3" label="DHCP_FAILED"/>
+ <int value="4" label="CONNECT_FAILED"/>
+ <int value="5" label="BAD_PASSPHRASE"/>
+ <int value="6" label="BAD_WEPKEY"/>
+ <int value="7" label="ACTIVATION_FAILED"/>
+ <int value="8" label="NEED_EVDO"/>
+ <int value="9" label="NEED_HOME_NETWORK"/>
+ <int value="10" label="OTASP_FAILED"/>
+ <int value="11" label="AAA_FAILED"/>
+ <int value="12" label="INTERNAL"/>
+ <int value="13" label="DNS_LOOKUP_FAILED"/>
+ <int value="14" label="HTTP_GET_FAILED"/>
+</enum>
+
+<enum name="NewTabPageActionAndroid" type="int">
+ <int value="0" label="Searched using the omnibox"/>
+ <int value="1" label="Navigated to Google search homepage using the omnibox"/>
+ <int value="2" label="Navigated to any other page using the omnibox"/>
+ <int value="3" label="Opened a most visited page"/>
+ <int value="4" label="Opened a recently closed tab"/>
+ <int value="5" label="Opened a bookmark"/>
+ <int value="6" label="Opened a foreign session (from other devices section)"/>
+</enum>
+
+<enum name="NewTabPageMobilePromo" type="int">
+ <summary>
+ These values are defined inside the PromoImpressionBuckets enum in
+ chrome/browser/ui/webui/ntp/android/promo_handler.cc
+ </summary>
+ <int value="0" label="Shown from most visited page"/>
+ <int value="1" label="Shown from open tabs page"/>
+ <int value="2" label="Shown from sync promo page"/>
+ <int value="3" label="User pressed 'Try Chrome'"/>
+ <int value="4" label="User dismissed the promo"/>
+</enum>
+
+<enum name="NtpFollowAction" type="int">
+ <int value="0" label="PAGE_TRANSITION_LINK"/>
+ <int value="1" label="PAGE_TRANSITION_TYPED"/>
+ <int value="2" label="PAGE_TRANSITION_AUTO_BOOKMARK"/>
+ <int value="3" label="PAGE_TRANSITION_AUTO_SUBFRAME"/>
+ <int value="4" label="PAGE_TRANSITION_MANUAL_SUBFRAME"/>
+ <int value="5" label="PAGE_TRANSITION_GENERATED"/>
+ <int value="6" label="PAGE_TRANSITION_START_PAGE"/>
+ <int value="7" label="PAGE_TRANSITION_FORM_SUBMIT"/>
+ <int value="8" label="PAGE_TRANSITION_RELOAD"/>
+ <int value="9" label="PAGE_TRANSITION_KEYWORD"/>
+ <int value="10" label="PAGE_TRANSITION_KEYWORD_GENERATED"/>
+ <int value="11" label="Clicked on a tile."/>
+ <int value="12" label="Clicked to other NTP pane."/>
+ <int value="13" label="Other action"/>
+</enum>
+
+<enum name="NtpOtherSessionsType" type="int">
+ <int value="0" label="Menu initialized"/>
+ <int value="1" label="Menu shown"/>
+ <int value="2" label="Link clicked"/>
+ <int value="3" label="Link context menu shown"/>
+ <int value="4" label="Device context menu shown"/>
+ <int value="5" label="Unused/previous device context menu shown"/>
+ <int value="6" label="Collapse Session"/>
+ <int value="7" label="Expand Session"/>
+ <int value="8" label="Open All"/>
+</enum>
+
+<enum name="NtpPaneType" type="int">
+ <int value="1" label="MostVisited"/>
+ <int value="2" label="Apps"/>
+ <int value="3" label="Bookmarks"/>
+ <int value="4" label="Suggestions"/>
+</enum>
+
+<enum name="NtpPromoAction" type="int">
+ <int value="0" label="NTP Promo viewed"/>
+ <int value="1" label="NTP Promo closed"/>
+ <int value="2" label="NTP Promo link clicked"/>
+</enum>
+
+<enum name="NtpTileExperimentActions" type="int">
+ <summary>
+ The types of actions performed by the Most Visited Tile Placement
+ experiment, used to identify the cases where the experiment could not
+ operate as expected, and the reason for it.
+ </summary>
+ <int value="0" label="Removed URL that was already open in browser"/>
+ <int value="1" label="Didn't remove URL, too few suggestions in MV"/>
+ <int value="2" label="Too few URLs, didn't flip tiles 1 and 8"/>
+ <int value="3" label="Too few URLs, didn't flip tiles 1 and 4"/>
+</enum>
+
+<enum name="OfflineStatus" type="int">
+ <int value="0" label="Fresh data load from Cache"/>
+ <int value="1" label="Successful network request (validation or fetch)."/>
+ <int value="2" label="Failed network request (non-offline error)."/>
+ <int value="3" label="Server offline and stale data available."/>
+ <int value="4" label="Server offline and stale data not available."/>
+</enum>
+
+<enum name="OmniboxAggressiveHistoryURLProviderFieldTrialBeacon" type="int">
+ <int value="0" label="disabled by flags"/>
+ <int value="1" label="enabled by flags"/>
+ <int value="2" label="auto, not in trial"/>
+ <int value="3" label="auto, disabled in trial"/>
+ <int value="4" label="auto, enabled in trial"/>
+</enum>
+
+<enum name="OmniboxEnteredKeywordMode" type="int">
+ <int value="0" label="via tab"/>
+ <int value="1" label="via space at end"/>
+ <int value="2" label="via space in middle"/>
+</enum>
+
+<enum name="OmniboxSearchEngine" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Google"/>
+ <int value="2" label="Yahoo!"/>
+ <int value="3" label="Bing"/>
+ <int value="4" label="Ask"/>
+ <int value="5" label="Yahoo! Quebec"/>
+ <int value="6" label="OK.hu"/>
+ <int value="7" label="Bing French and Arabic"/>
+ <int value="11" label="Yamli"/>
+ <int value="12" label="Araby"/>
+ <int value="13" label="Maktoob"/>
+ <int value="14" label="Masrawy"/>
+ <int value="15" label="Yandex"/>
+ <int value="16" label="Rambler"/>
+ <int value="17" label="TUT.BY"/>
+ <int value="18" label="hispavista"/>
+ <int value="19" label="Jabse"/>
+ <int value="20" label="NUR.KZ"/>
+ <int value="21" label="Baidu"/>
+ <int value="22" label="search.ch"/>
+ <int value="23" label="goo"/>
+ <int value="24" label="Pogodak!"/>
+ <int value="25" label="Seznam"/>
+ <int value="26" label="Centrum"/>
+ <int value="27" label="Atlas"/>
+ <int value="28" label="Jubii"/>
+ <int value="29" label="Eniro"/>
+ <int value="30" label="NetSprint"/>
+ <int value="32" label="diri"/>
+ <int value="33" label="Custom"/>
+ <int value="35" label="AOL"/>
+ <int value="37" label="Rediff"/>
+ <int value="38" label="guruji"/>
+ <int value="40" label="GO.com"/>
+ <int value="41" label="Rednano"/>
+ <int value="44" label="NETI"/>
+ <int value="45" label="DELFI"/>
+ <int value="46" label="Fonecta 02.fi"/>
+ <int value="51" label="search.ch"/>
+ <int value="54" label="in.gr"/>
+ <int value="55" label="Walla!"/>
+ <int value="59" label="leit.is"/>
+ <int value="62" label="Virgilio"/>
+ <int value="63" label="Libero"/>
+ <int value="67" label="Naver"/>
+ <int value="68" label="Daum"/>
+ <int value="69" label="Nate"/>
+ <int value="71" label="LATNE"/>
+ <int value="72" label="ABC S.k"/>
+ <int value="73" label="Kvasir"/>
+ <int value="75" label="Onet.pl"/>
+ <int value="76" label="Wirtualna Polska"/>
+ <int value="77" label="SAPO"/>
+ <int value="82" label="UOL Busca"/>
+ <int value="83" label="@MAIL.RU"/>
+ <int value="85" label="Zoznam"/>
+ <int value="87" label="Najdi.si"/>
+ <int value="89" label="AltaVista"/>
+ <int value="90" label="Terra"/>
+ <int value="99" label="Spray"/>
+ <int value="100" label="Sanook!"/>
+ <int value="101" label="MYNET"/>
+</enum>
+
+<enum name="OmniboxSuggestRequests" type="int">
+ <int value="1" label="requests sent"/>
+ <int value="2" label="requests invalidated"/>
+ <int value="3" label="(non-invalidated) replies received"/>
+</enum>
+
+<enum name="OSAgnosticErrno" type="int">
+ <summary>Errno values with the same meanings on Mac/Win/Linux.</summary>
+ <int value="0" label="0">No error</int>
+ <int value="1" label="EPERM">Operation not permitted</int>
+ <int value="2" label="ENOENT">No such file or directory</int>
+ <int value="3" label="ESRCH">No such process</int>
+ <int value="4" label="EINTR">Interrupted function call</int>
+ <int value="5" label="EIO">Input/output error</int>
+ <int value="6" label="ENXIO">No such device or address</int>
+ <int value="7" label="E2BIG">Arg list too long</int>
+ <int value="8" label="ENOEXEC">Exec format error</int>
+ <int value="9" label="EBADF">Bad file descriptor</int>
+ <int value="10" label="ECHILD">No child processes</int>
+ <int value="11" label="EDEADLK">Resource deadlock avoided</int>
+ <int value="12" label="ENOMEM">Cannot allocate memory</int>
+ <int value="13" label="EACCES">Permission denied</int>
+ <int value="14" label="EFAULT">Bad address</int>
+ <int value="15" label="ENOTBLK">Not a block device</int>
+ <int value="16" label="EBUSY">Resource busy</int>
+ <int value="17" label="EEXIST">File exists</int>
+ <int value="18" label="EXDEV">Improper link</int>
+ <int value="19" label="ENODEV">Operation not supported by device</int>
+ <int value="20" label="ENOTDIR">Not a directory</int>
+ <int value="21" label="EISDIR">Is a directory</int>
+ <int value="22" label="EINVAL">Invalid argument</int>
+ <int value="23" label="ENFILE">Too many open files in system</int>
+ <int value="24" label="EMFILE">Too many open files</int>
+ <int value="25" label="ENOTTY">Inappropriate ioctl for device</int>
+ <int value="26" label="ETXTBSY">Text file busy</int>
+ <int value="27" label="EFBIG">File too large</int>
+ <int value="28" label="ENOSPC">Device out of space</int>
+ <int value="29" label="ESPIPE">Illegal seek</int>
+ <int value="30" label="EROFS">Read-only file system</int>
+ <int value="31" label="EMLINK">Too many links</int>
+ <int value="32" label="EPIPE">Broken pipe</int>
+ <int value="33" label="EDOM">Numerical argument out of domain</int>
+ <int value="34" label="ERANGE">Numerical result out of range</int>
+</enum>
+
+<enum name="OtherPossibleUsernamesUsage" type="int">
+ <int value="0" label="Nothing to Autofill"/>
+ <int value="1" label="No other possible usernames"/>
+ <int value="2" label="Other possible usernames present, but none were shown"/>
+ <int value="3" label="Other possible username was shown, but not selected"/>
+ <int value="4" label="Other possible username was selected"/>
+</enum>
+
+<enum name="OverscrollMode" type="int">
+ <summary>Direction of the overscroll gesture.</summary>
+ <int value="1" label="North">Scrolled from bottom towards top</int>
+ <int value="2" label="South">Scrolled from top towards the bottom</int>
+ <int value="3" label="West">Scrolled from right towards left</int>
+ <int value="4" label="East">Scrolled from left towards right</int>
+</enum>
+
+<enum name="ParsedCookieStatus" type="int">
+ <int value="0" label="All cookie values valid and without control chars"/>
+ <int value="1" label="Cookie contains control chars"/>
+ <int value="2" label="Cookie is invalid"/>
+ <int value="3" label="Cookie contains both control chars and is invalid"/>
+</enum>
+
+<enum name="PepperVideoDecodeError" type="int">
+ <int value="1" label="Illegal state">
+ An operation was attempted during an incompatible decoder state.
+ </int>
+ <int value="2" label="Invalid argument">
+ Invalid argument was passed to an API method.
+ </int>
+ <int value="3" label="Unreadable input">Encoded input is unreadable.</int>
+ <int value="4" label="Platform failure">
+ A failure occurred at the browser layer or lower. Examples of such failures
+ include GPU hardware failures, GPU driver failures, GPU library failures,
+ browser programming errors, and so on.
+ </int>
+</enum>
+
+<enum name="PhotoEditorFileType" type="int">
+ <int value="0" label="jpg"/>
+ <int value="1" label="png"/>
+ <int value="2" label="gif"/>
+ <int value="3" label="bmp"/>
+ <int value="4" label="webp"/>
+ <int value="5" label="other"/>
+</enum>
+
+<enum name="PhotoEditorLoadMode" type="int">
+ <int value="0" label="From full resolution cache"/>
+ <int value="1" label="From screen resolution cache"/>
+ <int value="2" label="From file"/>
+ <int value="3" label="Other"/>
+</enum>
+
+<enum name="PhotoEditorSaveResult" type="int">
+ <int value="0" label="Failure"/>
+ <int value="1" label="Success"/>
+ <int value="2" label="Other"/>
+</enum>
+
+<enum name="PhotoEditorToolType" type="int">
+ <int value="0" label="Auto-fix"/>
+ <int value="1" label="Crop"/>
+ <int value="2" label="Brightness"/>
+ <int value="3" label="Rotate left"/>
+ <int value="4" label="Rotate right"/>
+ <int value="5" label="Rotate undo"/>
+ <int value="6" label="Rotate redo"/>
+ <int value="7" label="Share"/>
+ <int value="8" label="Other"/>
+</enum>
+
+<enum name="PipelineStatus" type="int">
+ <int value="0" label="PIPELINE_OK"/>
+ <int value="1" label="PIPELINE_ERROR_URL_NOT_FOUND"/>
+ <int value="2" label="PIPELINE_ERROR_NETWORK"/>
+ <int value="3" label="PIPELINE_ERROR_DECODE"/>
+ <int value="4" label="PIPELINE_ERROR_DECRYPT"/>
+ <int value="5" label="PIPELINE_ERROR_ABORT"/>
+ <int value="6" label="PIPELINE_ERROR_INITIALIZATION_FAILED"/>
+ <int value="7" label="PIPELINE_ERROR_REQUIRED_FILTER_MISSING"/>
+ <int value="8" label="PIPELINE_ERROR_COULD_NOT_RENDER"/>
+ <int value="9" label="PIPELINE_ERROR_READ"/>
+ <int value="10" label="PIPELINE_ERROR_OPERATION_PENDING"/>
+ <int value="11" label="PIPELINE_ERROR_INVALID_STATE"/>
+ <int value="12" label="DEMUXER_ERROR_COULD_NOT_OPEN"/>
+ <int value="13" label="DEMUXER_ERROR_COULD_NOT_PARSE"/>
+ <int value="14" label="DEMUXER_ERROR_NO_SUPPORTED_STREAMS"/>
+ <int value="15" label="DECODER_ERROR_NOT_SUPPORTED"/>
+</enum>
+
+<enum name="PlatformFileError" type="int">
+ <int value="0" label="OK"/>
+ <int value="1" label="FAILED"/>
+ <int value="2" label="IN_USE"/>
+ <int value="3" label="EXISTS"/>
+ <int value="4" label="NOT_FOUND"/>
+ <int value="5" label="ACCESS_DENIED"/>
+ <int value="6" label="TOO_MANY_OPENED"/>
+ <int value="7" label="NO_MEMORY"/>
+ <int value="8" label="NO_SPACE"/>
+ <int value="9" label="NOT_A_DIRECTORY"/>
+ <int value="10" label="INVALID_OPERATION"/>
+ <int value="11" label="SECURITY"/>
+ <int value="12" label="ABORT"/>
+ <int value="13" label="NOT_A_FILE"/>
+ <int value="14" label="NOT_EMPTY"/>
+ <int value="15" label="INVALID_URL"/>
+ <int value="16" label="I/O"/>
+</enum>
+
+<enum name="PluginLoadResult" type="int">
+ <int value="0" label="LOAD_SUCCESS"/>
+ <int value="1" label="LOAD_FAILED"/>
+ <int value="2" label="ENTRY_POINT_MISSING"/>
+ <int value="3" label="INIT_FAILED"/>
+</enum>
+
+<enum name="PointerSensitivity" type="int">
+ <int value="1" label="1"/>
+ <int value="2" label="2"/>
+ <int value="3" label="3"/>
+ <int value="4" label="4"/>
+ <int value="5" label="5"/>
+</enum>
+
+<enum name="PowerBrightnessAdjust" type="int">
+ <int value="0" label="Brightness Down"/>
+ <int value="1" label="Brightness Up"/>
+ <int value="2" label="Brightness Absolute"/>
+</enum>
+
+<enum name="PreconnectedNavigation" type="int">
+ <int value="0" label="No recent pre-connect to the page"/>
+ <int value="1" label="Page nav. preceded by a pre-connect"/>
+</enum>
+
+<enum name="PreconnectMotivation" type="int">
+ <int value="0" label="MOUSE_OVER_MOTIVATED"/>
+ <int value="1" label="PAGE_SCAN_MOTIVATED"/>
+ <int value="2" label="UNIT_TEST_MOTIVATED"/>
+ <int value="3" label="LINKED_MAX_MOTIVATED"/>
+ <int value="4" label="OMNIBOX_MOTIVATED"/>
+ <int value="5" label="STARTUP_LIST_MOTIVATED"/>
+ <int value="6" label="EARLY_LOAD_MOTIVATED"/>
+ <int value="7" label="NO_PREFETCH_MOTIVATION"/>
+ <int value="8" label="STATIC_REFERAL_MOTIVATED"/>
+ <int value="9" label="LEARNED_REFERAL_MOTIVATED"/>
+ <int value="10" label="SELF_REFERAL_MOTIVATED"/>
+</enum>
+
+<enum name="PreconnectSubresourceEval" type="int">
+ <int value="0" label="PRECONNECTION"/>
+ <int value="1" label="PRERESOLUTION"/>
+ <int value="2" label="TOO_NEW"/>
+</enum>
+
+<enum name="PreconnectTriggerUsed" type="int">
+ <int value="0" label="The pre-connect triggered host was not accessed"/>
+ <int value="1" label="The pre-connect triggered host was accessed"/>
+</enum>
+
+<enum name="PrerenderFinalStatus" type="int">
+ <int value="0" label="USED"/>
+ <int value="1" label="TIMED_OUT"/>
+ <int value="2" label="EVICTED"/>
+ <int value="3" label="MANAGER_SHUTDOWN"/>
+ <int value="4" label="CLOSED"/>
+ <int value="5" label="CREATE_NEW_WINDOW"/>
+ <int value="6" label="PROFILE_DESTROYED"/>
+ <int value="7" label="APP_TERMINATING"/>
+ <int value="8" label="JAVASCRIPT_ALERT"/>
+ <int value="9" label="AUTH_NEEDED"/>
+ <int value="10" label="HTTPS"/>
+ <int value="11" label="DOWNLOAD"/>
+ <int value="12" label="MEMORY_LIMIT_EXCEEDED"/>
+ <int value="13" label="JS_OUT_OF_MEMORY"/>
+ <int value="14" label="RENDERER_UNRESPONSIVE"/>
+ <int value="15" label="TOO_MANY_PROCESSES"/>
+ <int value="16" label="RATE_LIMIT_EXCEEDED"/>
+ <int value="17" label="PENDING_SKIPPED"/>
+ <int value="18" label="CONTROL_GROUP"/>
+ <int value="19" label="HTML5_MEDIA"/>
+ <int value="20" label="SOURCE_RENDER_VIEW_CLOSED"/>
+ <int value="21" label="RENDERER_CRASHED"/>
+ <int value="22" label="UNSUPPORTED_SCHEME"/>
+ <int value="23" label="INVALID_HTTP_METHOD"/>
+ <int value="24" label="WINDOW_PRINT"/>
+ <int value="25" label="RECENTLY_VISITED"/>
+ <int value="26" label="WINDOW_OPENER"/>
+ <int value="27" label="PAGE_ID_CONFLICT"/>
+ <int value="28" label="SAFE_BROWSING"/>
+ <int value="29" label="FRAGMENT_MISMATCH"/>
+ <int value="30" label="SSL_CLIENT_CERTIFICATE_REQUESTED"/>
+ <int value="31" label="CACHE_OR_HISTORY_CLEARED"/>
+ <int value="32" label="CANCELLED"/>
+ <int value="33" label="SSL_ERROR"/>
+ <int value="34" label="CROSS_SITE_NAVIGATION_PENDING"/>
+ <int value="35" label="DEVTOOLS_ATTACHED"/>
+ <int value="36" label="SESSION_STORAGE_NAMESPACE_MISMATCH"/>
+ <int value="37" label="NO_USE_GROUP"/>
+ <int value="38" label="MATCH_COMPLETE_DUMMY"/>
+ <int value="39" label="DUPLICATE"/>
+ <int value="40" label="OPEN_URL"/>
+ <int value="41" label="WOULD_HAVE_BEEN_USED"/>
+ <int value="42" label="REGISTER_PROTOCOL_HANDLER"/>
+</enum>
+
+<enum name="PrerenderHoverEvent" type="int">
+ <obsolete>
+ deprecated May 10 2012
+ </obsolete>
+ <int value="0" label="HOVER_EVENT_START"/>
+ <int value="1" label="HOVER_EVENT_TOO_SHORT"/>
+ <int value="2" label="HOVER_EVENT_REPLACED"/>
+ <int value="3" label="HOVER_EVENT_CLICK"/>
+</enum>
+
+<enum name="PrerenderLocalPredictorEvents" type="int">
+ <int value="0" label="Constructed"/>
+ <int value="1" label="Init scheduled"/>
+ <int value="2" label="Init started"/>
+ <int value="3" label="Init failed: no history"/>
+ <int value="4" label="Init succeeded"/>
+ <int value="5" label="AddVisit"/>
+ <int value="6" label="AddVisit initialized"/>
+ <int value="7" label="AddVisit prerender identified"/>
+ <int value="8" label="AddVisit relevant transition"/>
+ <int value="9" label="AddVisit identified prerender candidate"/>
+ <int value="10" label="AddVisit prerendering"/>
+ <int value="11" label="Got prerender url"/>
+ <int value="12" label="Error: no prerender url for PLT"/>
+ <int value="13" label="AddVisit prerender rextended"/>
+ <int value="14" label="URL lookup result"/>
+ <int value="15" label="URL lookup result: root page"/>
+ <int value="16" label="URL lookup result: http"/>
+ <int value="17" label="URL lookup result: has query string"/>
+ <int value="18" label="URL lookup result: contains logout"/>
+ <int value="19" label="URL lookup result: contians login"/>
+ <int value="20" label="Start url lookup"/>
+ <int value="21" label="AddVisit not root page"/>
+ <int value="22" label="Whitelist error"/>
+ <int value="23" label="Whitelist ok"/>
+ <int value="24" label="URL lookup result: on whitelist"/>
+ <int value="25" label="URL lookup result: on whitelist root page"/>
+ <int value="26" label="URL lookup result: extended root page"/>
+ <int value="27" label="URL lookup result: root page http"/>
+ <int value="28" label="URL lookup failed"/>
+ <int value="29" label="URL lookup no source webcontents found"/>
+ <int value="30" label="URL lookup no logged in table found"/>
+ <int value="31" label="URL lookup issuing logged in lookup"/>
+ <int value="32" label="Continue prerender check started"/>
+ <int value="33" label="Continue prerender check no url"/>
+ <int value="34" label="Continue prerender check priority too low"/>
+ <int value="35" label="Continue prerender check urls identical but fragemet"/>
+ <int value="36" label="Continue prerender check https"/>
+ <int value="37" label="Continue prerender check root page"/>
+ <int value="38" label="Continue prerender check logout url"/>
+ <int value="39" label="Continue prerender check login url"/>
+ <int value="40" label="Continue prerender check not logged in"/>
+ <int value="41" label="Continue prerender check fallthrough no prerender"/>
+ <int value="42" label="Continue prerender check issuing prerender"/>
+ <int value="43" label="Issuing prerender"/>
+ <int value="44" label="No prerender candidates"/>
+ <int value="45" label="Got history issuing lookup"/>
+ <int value="46" label="Tab Helper URL seen"/>
+ <int value="47" label="Tab Helper URL seen match"/>
+ <int value="48" label="Tab Helper URL seen namespace match"/>
+ <int value="49" label="URL lookup multiple source webcontents"/>
+ <int value="50" label="Continue prerender check side-effect free whitelist"/>
+ <int value="51" label="Continue prerender check Examine next URL"/>
+ <int value="52" label="Issuing prerender, already prerendering"/>
+ <int value="53" label="Issuing prerender, new prerender"/>
+ <int value="54" label="Issuing prerender, cancelled old prerender"/>
+ <int value="55" label="Continue prerender check fallthrough prerendering"/>
+</enum>
+
+<enum name="PrerenderLocalVisitCoreTransition" type="int">
+ <int value="0" label="LINK"/>
+ <int value="1" label="TYPED"/>
+ <int value="2" label="AUTO_BOOKMARK"/>
+ <int value="3" label="AUTO_SUBFRAME"/>
+ <int value="4" label="MANUAL_SUBFRAME"/>
+ <int value="5" label="GENERATED"/>
+ <int value="6" label="START_PAGE"/>
+ <int value="7" label="FORM_SUBMIT"/>
+ <int value="8" label="RELOAD"/>
+ <int value="9" label="KEYWORD"/>
+ <int value="10" label="GENERATED"/>
+</enum>
+
+<enum name="PrerenderLocalVisitEvents" type="int">
+ <int value="0" label="V1_VISIT"/>
+ <int value="1" label="V1_PRERENDER_STARTED_1"/>
+ <int value="2" label="V1_PRERENDER_USED_1"/>
+ <int value="3" label="V1_PRERENDER_STARTED_3"/>
+ <int value="4" label="V1_PRERENDER_USED_3"/>
+ <int value="5" label="V1_PRERENDER_STARTED_5"/>
+ <int value="6" label="V1_PRERENDER_USED_5"/>
+ <int value="10" label="VISIT"/>
+ <int value="11" label="VISIT_EXCLUDE_BACK_FORWARD"/>
+ <int value="12" label="VISIT_EXCLUDE_HOME_PAGE"/>
+ <int value="13" label="VISIT_EXCLUDE_REDIRECT_CHAIN"/>
+ <int value="14" label="PRERENDER_STARTED_1"/>
+ <int value="15" label="PRERENDER_USED_1"/>
+ <int value="16" label="PRERENDER_STARTED_3"/>
+ <int value="17" label="PRERENDER_USED_3"/>
+ <int value="18" label="PRERENDER_STARTED_5"/>
+ <int value="19" label="PRERENDER_USED_5"/>
+</enum>
+
+<enum name="PrerenderMode" type="int">
+ <int value="0" label="PRERENDER_MODE_DISABLED"/>
+ <int value="1" label="PRERENDER_MODE_ENABLED"/>
+ <int value="2" label="PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP"/>
+ <int value="3" label="PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP"/>
+ <int value="4" label="PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP"/>
+ <int value="5" label="PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP"/>
+ <int value="6" label="PRERENDER_MODE_EXPERIMENT_MULTI_PRERENDER_GROUP"/>
+ <int value="7" label="PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP"/>
+</enum>
+
+<enum name="PrerenderPageviewEvents" type="int">
+ <int value="0" label="PAGEVIEW_EVENT_NEW_URL"/>
+ <int value="1" label="PAGEVIEW_EVENT_TOP_SITE_NEW_URL"/>
+ <int value="2" label="PAGEVIEW_EVENT_LOAD_START"/>
+ <int value="3" label="PAGEVIEW_EVENT_TOP_SITE_LOAD_START"/>
+</enum>
+
+<enum name="PrerenderSchemeCancelReason" type="int">
+ <int value="0" label="EXTERNAL_PROTOCOL"/>
+ <int value="1" label="DATA"/>
+ <int value="2" label="BLOB"/>
+ <int value="3" label="FILE"/>
+ <int value="4" label="FILESYSTEM"/>
+ <int value="5" label="WEBSOCKET"/>
+ <int value="6" label="FTP"/>
+ <int value="7" label="CHROME"/>
+ <int value="8" label="CHROME_EXTENSION"/>
+ <int value="9" label="ABOUT"/>
+ <int value="10" label="UNKNOWN"/>
+</enum>
+
+<enum name="PrerenderTabHelperEvents" type="int">
+ <int value="0" label="Table requested"/>
+ <int value="1" label="Table present"/>
+ <int value="2" label="Mainframe change"/>
+ <int value="3" label="Mainframe change, logged in"/>
+ <int value="4" label="Mainframe commit"/>
+ <int value="5" label="Mainframe commit, logged in"/>
+ <int value="6" label="Login action added"/>
+ <int value="7" label="Login action added, Mainframe"/>
+ <int value="8" label="Login action added, Mainframe, pw empty"/>
+ <int value="9" label="Login action added, Subframe"/>
+ <int value="10" label="Login action added, Subframe, pw empty"/>
+</enum>
+
+<enum name="PreTapEvents" type="int">
+ <int value="0" label="no event"/>
+ <int value="1" label="tapdown"/>
+ <int value="2" label="tapunconfirmed"/>
+ <int value="3" label="tapdown + tapunconfirmed"/>
+</enum>
+
+<enum name="ProfileCreateResult" type="int">
+ <int value="0" label="Failed locally"/>
+ <int value="1" label="Failed remotely"/>
+ <int value="2" label="Created but not initialized (should never happen)"/>
+ <int value="3" label="Succeeded"/>
+ <int value="4" label="Canceled"/>
+</enum>
+
+<enum name="ProtectorError" type="int">
+ <obsolete>
+ Deprecated 8/2013. No longer generated.
+ </obsolete>
+ <summary>
+ Codes for errors Protector detects about settings it protects. See
+ chrome/browser/protector/histograms.h for the corresponding enum.
+ </summary>
+ <int value="0" label="Backup invalid"/>
+ <int value="1" label="Value changed"/>
+ <int value="2" label="Value valid"/>
+ <int value="3" label="Value is valid and zero"/>
+</enum>
+
+<enum name="ProtocolVersion" type="int">
+ <int value="0" label="UNKNOWN"/>
+ <int value="1" label="HTTP 1.1"/>
+ <int value="2" label="SPDY 1.0"/>
+ <int value="3" label="SPDY 2.0"/>
+ <int value="4" label="SPDY 2.1"/>
+ <int value="5" label="SPDY 3.0"/>
+</enum>
+
+<enum name="ProvisionalSaveFailure" type="int">
+ <int value="0" label="SAVING_DISABLED"/>
+ <int value="1" label="EMPTY_PASSWORD"/>
+ <int value="2" label="NO_MATCHING_FORM"/>
+ <int value="3" label="MATCHING_NOT_COMPLETE"/>
+ <int value="4" label="FORM_BLACKLISTED"/>
+ <int value="5" label="INVALID_FORM"/>
+ <int value="6" label="AUTOCOMPLETE_OFF"/>
+</enum>
+
+<enum name="ProxyStatus" type="int">
+ <int value="0" label="PROXY_STATUS_IGNORED"/>
+ <int value="1" label="PROXY_UNINITIALIZED"/>
+ <int value="2" label="PROXY_NOT_USED"/>
+ <int value="3" label="PROXY_PAC_RESOLVER"/>
+ <int value="4" label="PROXY_HAS_RULES"/>
+</enum>
+
+<enum name="PublicKeyPinFailedDomain" type="int">
+ <int value="0" label="DOMAIN_NOT_PINNED"/>
+ <int value="1" label="DOMAIN_GOOGLE_COM"/>
+ <int value="2" label="DOMAIN_ANDROID_COM"/>
+ <int value="3" label="DOMAIN_GOOGLE_ANALYTICS_COM"/>
+ <int value="4" label="DOMAIN_GOOGLEPLEX_COM"/>
+ <int value="5" label="DOMAIN_YTIMG_COM"/>
+ <int value="6" label="DOMAIN_GOOGLEUSERCONTENT_COM"/>
+ <int value="7" label="DOMAIN_YOUTUBE_COM"/>
+ <int value="8" label="DOMAIN_GOOGLEAPIS_COM"/>
+ <int value="9" label="DOMAIN_GOOGLEADSERVICES_COM"/>
+ <int value="10" label="DOMAIN_GOOGLECODE_COM"/>
+ <int value="11" label="DOMAIN_APPSPOT_COM"/>
+ <int value="12" label="DOMAIN_GOOGLESYNDICATION_COM"/>
+ <int value="13" label="DOMAIN_DOUBLECLICK_NET"/>
+ <int value="14" label="DOMAIN_GSTATIC_COM"/>
+ <int value="15" label="DOMAIN_GMAIL_COM"/>
+ <int value="16" label="DOMAIN_GOOGLEMAIL_COM"/>
+ <int value="17" label="DOMAIN_GOOGLEGROUPS_COM"/>
+ <int value="18" label="DOMAIN_TORPROJECT_ORG"/>
+ <int value="19" label="DOMAIN_TWITTER_COM"/>
+ <int value="20" label="DOMAIN_TWIMG_COM"/>
+ <int value="21" label="DOMAIN_AKAMAIHD_NET"/>
+ <int value="22" label="DOMAIN_NUM_EVENTS"/>
+</enum>
+
+<enum name="QuicErrorCodes" type="int">
+ <int value="0" label="NO_ERROR"/>
+ <int value="1" label="INTERNAL_ERROR"/>
+ <int value="2" label="STREAM_DATA_AFTER_TERMINATION"/>
+ <int value="3" label="INVALID_PACKET_HEADER"/>
+ <int value="4" label="INVALID_FRAME_DATA"/>
+ <int value="5" label="INVALID_FEC_DATA"/>
+ <int value="6" label="INVALID_RST_STREAM_DATA"/>
+ <int value="7" label="INVALID_CONNECTION_CLOSE_DATA"/>
+ <int value="8" label="INVALID_GOAWAY_DATA"/>
+ <int value="9" label="INVALID_ACK_DATA"/>
+ <int value="10" label="INVALID_VERSION_NEGOTIATION_PACKET"/>
+ <int value="11" label="INVALID_PUBLIC_RST_PACKET"/>
+ <int value="12" label="DECRYPTION_FAILURE"/>
+ <int value="13" label="ENCRYPTION_FAILURE"/>
+ <int value="14" label="PACKET_TOO_LARGE"/>
+ <int value="15" label="PACKET_FOR_NONEXISTENT_STREAM"/>
+ <int value="16" label="PEER_GOING_AWAY"/>
+ <int value="17" label="INVALID_STREAM_ID"/>
+ <int value="18" label="TOO_MANY_OPEN_STREAMS"/>
+ <int value="19" label="PUBLIC_RESET"/>
+ <int value="20" label="INVALID_VERSION"/>
+ <int value="21" label="STREAM_RST_BEFORE_HEADERS_DECOMPRESSED"/>
+ <int value="22" label="INVALID_HEADER_ID"/>
+ <int value="23" label="INVALID_NEGOTIATED_VALUE"/>
+ <int value="24" label="DECOMPRESSION_FAILURE"/>
+ <int value="25" label="CONNECTION_TIMED_OUT"/>
+ <int value="26" label="ERROR_MIGRATING_ADDRESS"/>
+ <int value="27" label="PACKET_WRITE_ERROR"/>
+ <int value="28" label="HANDSHAKE_FAILED"/>
+ <int value="29" label="CRYPTO_TAGS_OUT_OF_ORDER"/>
+ <int value="30" label="CRYPTO_TOO_MANY_ENTRIES"/>
+ <int value="31" label="CRYPTO_INVALID_VALUE_LENGTH"/>
+ <int value="32" label="CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE"/>
+ <int value="33" label="INVALID_CRYPTO_MESSAGE_TYPE"/>
+ <int value="34" label="INVALID_CRYPTO_MESSAGE_PARAMETER"/>
+ <int value="35" label="CRYPTO_MESSAGE_PARAMETER_NOT_FOUND"/>
+ <int value="36" label="CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP"/>
+ <int value="37" label="CRYPTO_MESSAGE_INDEX_NOT_FOUND"/>
+ <int value="38" label="CRYPTO_INTERNAL_ERROR"/>
+ <int value="39" label="CRYPTO_VERSION_NOT_SUPPORTED"/>
+ <int value="40" label="CRYPTO_NO_SUPPORT"/>
+ <int value="41" label="CRYPTO_TOO_MANY_REJECTS"/>
+ <int value="42" label="PROOF_INVALID"/>
+ <int value="43" label="CRYPTO_DUPLICATE_TAG"/>
+ <int value="44" label="CRYPTO_ENCRYPTION_LEVEL_INCORRECT"/>
+ <int value="45" label="CRYPTO_SERVER_CONFIG_EXPIRED"/>
+</enum>
+
+<enum name="QuicHandshakeState" type="int">
+ <int value="0" label="STARTED"/>
+ <int value="1" label="ENCRYPTION_ESTABLISHED"/>
+ <int value="2" label="HANDSHAKE_CONFIRMED"/>
+ <int value="3" label="FAILED"/>
+</enum>
+
+<enum name="QuickofficeErrorTypes" type="int">
+ <int value="0" label="doc uncaught js exception"/>
+ <int value="1" label="docx uncaught js exception"/>
+ <int value="2" label="docm uncaught js exception"/>
+ <int value="3" label="xls uncaught js exception"/>
+ <int value="4" label="xlsx uncaught js exception"/>
+ <int value="5" label="xlsm uncaught js exception"/>
+ <int value="6" label="ppt uncaught js exception"/>
+ <int value="7" label="pptx uncaught js exception"/>
+ <int value="8" label="pptm uncaught js exception"/>
+ <int value="9" label="pps uncaught js exception"/>
+ <int value="10" label="ppsx uncaught js exception"/>
+ <int value="11" label="ppsm uncaught js exception"/>
+ <int value="12" label="doc suspected corrupt file"/>
+ <int value="13" label="docx suspected corrupt file"/>
+ <int value="14" label="docm suspected corrupt file"/>
+ <int value="15" label="xls suspected corrupt file"/>
+ <int value="16" label="xlsx suspected corrupt file"/>
+ <int value="17" label="xlsm suspected corrupt file"/>
+ <int value="18" label="ppt suspected corrupt file"/>
+ <int value="19" label="pptx suspected corrupt file"/>
+ <int value="20" label="pptm suspected corrupt file"/>
+ <int value="21" label="pps suspected corrupt file"/>
+ <int value="22" label="ppsx suspected corrupt file"/>
+ <int value="23" label="ppsm suspected corrupt file"/>
+ <int value="24" label="doc qowt ui warning"/>
+ <int value="25" label="docx qowt ui warning"/>
+ <int value="26" label="docm qowt ui warning"/>
+ <int value="27" label="xls qowt ui warning"/>
+ <int value="28" label="xlsx qowt ui warning"/>
+ <int value="29" label="xlsm qowt ui warning"/>
+ <int value="30" label="ppt qowt ui warning"/>
+ <int value="31" label="pptx qowt ui warning"/>
+ <int value="32" label="pptm qowt ui warning"/>
+ <int value="33" label="pps qowt ui warning"/>
+ <int value="34" label="ppsx qowt ui warning"/>
+ <int value="35" label="ppsm qowt ui warning"/>
+ <int value="36" label="doc nacl error"/>
+ <int value="37" label="docx nacl error"/>
+ <int value="38" label="docm nacl error"/>
+ <int value="39" label="xls nacl error"/>
+ <int value="40" label="xlsx nacl error"/>
+ <int value="41" label="xlsm nacl error"/>
+ <int value="42" label="ppt nacl error"/>
+ <int value="43" label="pptx nacl error"/>
+ <int value="44" label="pptm nacl error"/>
+ <int value="45" label="pps nacl error"/>
+ <int value="46" label="ppsx nacl error"/>
+ <int value="47" label="ppsm nacl error"/>
+ <int value="48" label="doc nacl crash"/>
+ <int value="49" label="docx nacl crash"/>
+ <int value="50" label="docm nacl crash"/>
+ <int value="51" label="xls nacl crash"/>
+ <int value="52" label="xlsx nacl crash"/>
+ <int value="53" label="xlsm nacl crash"/>
+ <int value="54" label="ppt nacl crash"/>
+ <int value="55" label="pptx nacl crash"/>
+ <int value="56" label="pptm nacl crash"/>
+ <int value="57" label="pps nacl crash"/>
+ <int value="58" label="ppsx nacl crash"/>
+ <int value="59" label="ppsm nacl crash"/>
+ <int value="60" label="doc invalid file format"/>
+ <int value="61" label="docx invalid file format"/>
+ <int value="62" label="docm invalid file format"/>
+ <int value="63" label="xls invalid file format"/>
+ <int value="64" label="xlsx invalid file format"/>
+ <int value="65" label="xlsm invalid file format"/>
+ <int value="66" label="ppt invalid file format"/>
+ <int value="67" label="pptx invalid file format"/>
+ <int value="68" label="pptm invalid file format"/>
+ <int value="69" label="pps invalid file format"/>
+ <int value="70" label="ppsx invalid file format"/>
+ <int value="71" label="ppsm invalid file format"/>
+</enum>
+
+<enum name="QuickofficeFileFormat" type="int">
+ <int value="0" label="doc"/>
+ <int value="1" label="docx"/>
+ <int value="2" label="docm"/>
+ <int value="3" label="xls"/>
+ <int value="4" label="xlsx"/>
+ <int value="5" label="xlsm"/>
+ <int value="6" label="ppt"/>
+ <int value="7" label="pptx"/>
+ <int value="8" label="pptm"/>
+ <int value="9" label="pps"/>
+ <int value="10" label="ppsx"/>
+ <int value="11" label="ppsm"/>
+</enum>
+
+<enum name="RecentTabsAction" type="int">
+ <int value="0" label="Local Session Tab"/>
+ <int value="1" label="Other Device Tab"/>
+ <int value="2" label="Restore Window"/>
+ <int value="3" label="Show More"/>
+</enum>
+
+<enum name="ResolutionCategory" type="int">
+ <int value="0" label="RESOLVE_SUCCESS"/>
+ <int value="1" label="RESOLVE_FAIL"/>
+ <int value="2" label="RESOLVE_SPECULATIVE_SUCCESS"/>
+ <int value="3" label="RESOLVE_SPECULATIVE_FAIL"/>
+</enum>
+
+<enum name="ResolutionUnspecWasteCategory" type="int">
+ <int value="0" label="AF_WASTE_IPV4_ONLY">
+ Running in a IPv4-only configuration. No waste.
+ </int>
+ <int value="1" label="AF_WASTE_CACHE_IPV4">
+ Cache contained an UNSPEC result for this IPv4 lookup. Waste.
+ </int>
+ <int value="2" label="AF_WASTE_CACHE_UNSPEC">
+ Cache contained an IPv4 result for this UNSPEC lookup. Waste.
+ </int>
+ <int value="3" label="AF_WASTE_JOB_IPV4">
+ Job pool contained an UNSPEC job for this IPv4 lookup. Waste.
+ </int>
+ <int value="4" label="AF_WASTE_JOB_UNSPEC">
+ Job pool contained an IPv4 job for this UNSPEC lookup. Waste.
+ </int>
+ <int value="5" label="AF_WASTE_NONE_IPV4">
+ A new job was needed for this IPv4 lookup. No waste.
+ </int>
+ <int value="6" label="AF_WASTE_NONE_UNSPEC">
+ A new job was needed for this UNSPEC lookup. No waste.
+ </int>
+</enum>
+
+<enum name="SB2BloomFailure" type="int">
+ <int value="0" label="READ_OPEN"/>
+ <int value="1" label="READ_VERSION"/>
+ <int value="2" label="READ_NUM_KEYS"/>
+ <int value="3" label="READ_KEY"/>
+ <int value="4" label="READ_DATA_MINSIZE"/>
+ <int value="5" label="READ_DATA_MAXSIZE"/>
+ <int value="6" label="READ_DATA_SHORT"/>
+ <int value="7" label="READ_DATA"/>
+</enum>
+
+<enum name="SB2BloomFilterFalsePositives" type="int">
+ <int value="0" label="ALL_MISSES"/>
+ <int value="1" label="FALSE_POSITIVE_MISSES"/>
+</enum>
+
+<enum name="SB2DatabaseFailure" type="int">
+ <int value="0" label="CORRUPT"/>
+ <int value="1" label="CORRUPT_HANDLER"/>
+ <int value="2" label="BROWSE_DB_UPDATE_BEGIN"/>
+ <int value="3" label="BROWSE_DB_UPDATE_FINISH"/>
+ <int value="4" label="FILTER_MISSING"/>
+ <int value="5" label="FILTER_READ"/>
+ <int value="6" label="FILTER_WRITE"/>
+ <int value="7" label="FILTER_DELETE"/>
+ <int value="8" label="STORE_MISSING"/>
+ <int value="9" label="STORE_DELETE"/>
+ <int value="10" label="DOWNLOAD_DB_UPDATE_BEGIN"/>
+ <int value="11" label="DOWNLOAD_DB_UPDATE_FINISH"/>
+ <int value="12" label="CSD_DB_UPDATE_BEGIN"/>
+ <int value="13" label="CSD_DB_UPDATE_FINISH"/>
+ <int value="14" label="BROWSE_PREFIX_SET_MISSING"/>
+ <int value="15" label="BROWSE_PREFIX_SET_READ"/>
+ <int value="16" label="BROWSE_PREFIX_SET_WRITE"/>
+ <int value="17" label="BROWSE_PREFIX_SET_DELETE"/>
+ <int value="18" label="EXTENSION_BLACKLIST_UPDATE_BEGIN"/>
+ <int value="19" label="EXTENSION_BLACKLIST_UPDATE_FINISH"/>
+ <int value="20" label="EXTENSION_BLACKLIST_UPDATE_DELETE"/>
+ <int value="21" label="SIDE_EFFECT_FREE_WHITELIST_UPDATE_BEGIN"/>
+ <int value="22" label="SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH"/>
+ <int value="23" label="SIDE_EFFECT_FREE_WHITELIST_DELETE"/>
+ <int value="24" label="SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_READ"/>
+ <int value="25" label="SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE"/>
+ <int value="26" label="SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_DELETE"/>
+</enum>
+
+<enum name="SB2DownloadChecks" type="int">
+ <int value="0" label="URL_CHECKS_TOTAL"/>
+ <int value="1" label="URL_CHECKS_CANCELED"/>
+ <int value="2" label="URL_CHECKS_MALWARE"/>
+ <int value="3" label="HASH_CHECKS_TOTAL"/>
+ <int value="4" label="HASH_CHECKS_MALWARE"/>
+</enum>
+
+<enum name="SB2FilterLoad" type="int">
+ <int value="0" label="ALL"/>
+ <int value="1" label="PREFIX_SET"/>
+ <int value="2" label="BLOOM_FILTER"/>
+</enum>
+
+<enum name="SB2FormatEvent" type="int">
+ <int value="0" label="FILE_CORRUPT"/>
+ <int value="1" label="SQLITE_CORRUPT"/>
+ <int value="2" label="FOUND_SQLITE"/>
+ <int value="3" label="FOUND_UNKNOWN"/>
+ <int value="4" label="SQLITE_DELETED"/>
+ <int value="5" label="SQLITE_DELETE_FAILED"/>
+ <int value="6" label="SQLITE_DELETED_ORIGINAL"/>
+ <int value="7" label="SQLITE_DELETE_ORIGINAL_FAILED"/>
+</enum>
+
+<enum name="SB2GetHashResult" type="int">
+ <int value="0" label="STATUS_200"/>
+ <int value="1" label="STATUS_204"/>
+ <int value="2" label="FULL_HASH_EMPTY"/>
+ <int value="3" label="FULL_HASH_HIT"/>
+ <int value="4" label="FULL_HASH_MISS"/>
+</enum>
+
+<enum name="SB2InterstitialAction" type="int">
+ <int value="0" label="MALWARE_SHOW"/>
+ <int value="1" label="MALWARE_DONT_PROCEED"/>
+ <int value="2" label="MALWARE_FORCED_DONT_PROCEED"/>
+ <int value="3" label="MALWARE_PROCEED"/>
+ <int value="4" label="MULTIPLE_SHOW"/>
+ <int value="5" label="MULTIPLE_DONT_PROCEED"/>
+ <int value="6" label="MULTIPLE_FORCED_DONT_PROCEED"/>
+ <int value="7" label="MULTIPLE_PROCEED"/>
+ <int value="8" label="PHISHING_SHOW"/>
+ <int value="9" label="PHISHING_DONT_PROCEED"/>
+ <int value="10" label="PHISHING_FORCED_DONT_PROCEED"/>
+ <int value="11" label="PHISHING_PROCEED"/>
+ <int value="12" label="MALWARE_SHOW_ADVANCED"/>
+ <int value="13" label="MULTIPLE_SHOW_ADVANCED"/>
+ <int value="14" label="PHISHING_SHOW_ADVANCED"/>
+</enum>
+
+<enum name="SB2PrefixSetEvent" type="int">
+ <obsolete>
+ Deprecated 9/2012. No longer generated.
+ </obsolete>
+ <int value="0" label="PREFIX_SET_HIT"/>
+ <int value="1" label="BLOOM_HIT"/>
+ <int value="2" label="BLOOM_MISS_PREFIX_SET_HIT"/>
+ <int value="3" label="BLOOM_MISS_PREFIX_HIT_INVALID"/>
+ <int value="4" label="GETPREFIXES_BROKEN"/>
+ <int value="5" label="GETPREFIXES_BROKEN_SIZE"/>
+ <int value="6" label="GETPREFIXES_FIRST_BROKEN"/>
+ <int value="7" label="SBPREFIX_WAS_BROKEN"/>
+ <int value="8" label="GETPREFIXES_BROKEN_SORTING"/>
+ <int value="9" label="GETPREFIXES_BROKEN_DUPLICATION"/>
+ <int value="10" label="GETPREFIX_UNSORTED_IS_DELTA"/>
+ <int value="11" label="GETPREFIX_UNSORTED_IS_INDEX"/>
+ <int value="12" label="CREATE_PREFIX_SET_CHECKSUM"/>
+ <int value="13" label="CREATE_BLOOM_FILTER_CHECKSUM"/>
+ <int value="14" label="CREATE_ADD_PREFIXES_CHECKSUM"/>
+ <int value="15" label="CREATE_PREFIXES_CHECKSUM"/>
+ <int value="16" label="GET_PREFIXES_CHECKSUM"/>
+ <int value="17" label="MISMATCH_PREFIX_SET_CHECKSUM"/>
+ <int value="18" label="MISMATCH_BLOOM_FILTER_CHECKSUM"/>
+ <int value="19" label="BLOOM_MISS_PREFIX_HIT"/>
+</enum>
+
+<enum name="SB2SideEffectFreeWhitelistStatus" type="int">
+ <int value="0" label="Enabled"/>
+ <int value="1" label="Disabled"/>
+</enum>
+
+<enum name="SB2UpdateResult" type="int">
+ <int value="0" label="FAIL"/>
+ <int value="1" label="SUCCESS"/>
+ <int value="2" label="BACKUP_CONNECT_FAIL"/>
+ <int value="3" label="BACKUP_CONNECT_SUCCESS"/>
+ <int value="4" label="BACKUP_HTTP_FAIL"/>
+ <int value="5" label="BACKUP_HTTP_SUCCESS"/>
+ <int value="6" label="BACKUP_NETWORK_FAIL"/>
+ <int value="7" label="BACKUP_NETWORK_SUCCESS"/>
+</enum>
+
+<enum name="SBClientDownloadCheckDownloadStats" type="int">
+ <int value="0" label="INVALID_URL"/>
+ <int value="1" label="SB_DISABLED"/>
+ <int value="2" label="WHITELISTED_URL"/>
+ <int value="3" label="WHITELISTED_REFERRER"/>
+ <int value="4" label="INVALID_REQUEST_PROTO"/>
+ <int value="5" label="SERVER_PING_FAILED"/>
+ <int value="6" label="INVALID_RESPONSE_PROTO"/>
+ <int value="7" label="NOT_BINARY_FILE"/>
+ <int value="8" label="REQUEST_CANCELED"/>
+ <int value="9" label="DOWNLOAD_DANGEROUS"/>
+ <int value="10" label="DOWNLOAD_SAFE"/>
+ <int value="11" label="EMPTY_URL_CHAIN"/>
+ <int value="12" label="HTTPS_URL"/>
+ <int value="13" label="PING_DISABLED"/>
+ <int value="14" label="TRUSTED_EXECUTABLE"/>
+ <int value="15" label="OS_NOT_SUPPORTED"/>
+ <int value="16" label="DOWNLOAD_UNCOMMON"/>
+ <int value="17" label="DOWNLOAD_NOT_SUPPORTED"/>
+ <int value="18" label="INVALID_RESPONSE_VERDICT"/>
+ <int value="19" label="ARCHIVE_WITHOUT_BINARIES"/>
+ <int value="20" label="DOWNLOAD_DANGEROUS_HOST"/>
+ <int value="21" label="DOWNLOAD_POTENTIALLY_UNWANTED"/>
+</enum>
+
+<enum name="SBClientDownloadExtensions" type="int">
+ <int value="0" label="EXE"/>
+ <int value="1" label="MSI"/>
+ <int value="2" label="CAB"/>
+ <int value="3" label="SYS"/>
+ <int value="4" label="SCR"/>
+ <int value="5" label="DRV"/>
+ <int value="6" label="BAT"/>
+ <int value="7" label="ZIP"/>
+ <int value="8" label="RAR"/>
+ <int value="9" label="DLL"/>
+ <int value="10" label="PIF"/>
+ <int value="11" label="COM"/>
+ <int value="12" label="JAR"/>
+ <int value="13" label="CLASS"/>
+ <int value="14" label="PDF"/>
+ <int value="15" label="VB"/>
+ <int value="16" label="REG"/>
+ <int value="17" label="GRP"/>
+ <int value="18" label="OTHER"/>
+ <int value="19" label="CRX"/>
+ <int value="20" label="APK"/>
+</enum>
+
+<enum name="SBClientDownloadIsSignedBinary" type="int">
+ <int value="0" label="Unsigned"/>
+ <int value="1" label="Signed"/>
+</enum>
+
+<enum name="SBClientMalwareSentReports" type="int">
+ <int value="0" label="Sent"/>
+ <int value="1" label="Hit limit"/>
+ <int value="2" label="Failed serialization"/>
+</enum>
+
+<enum name="SBClientPhishingCancelClassificationReason" type="int">
+ <int value="0" label="NAVIGATE_AWAY"/>
+ <int value="1" label="NAVIGATE_WITHIN_PAGE"/>
+ <int value="2" label="PAGE_RECAPTURED"/>
+ <int value="3" label="SHUTDOWN"/>
+ <int value="4" label="NEW_PHISHING_SCORER"/>
+</enum>
+
+<enum name="SBClientPhishingClientModelStatus" type="int">
+ <int value="0" label="MODEL_SUCCESS"/>
+ <int value="1" label="MODEL_NOT_CHANGED"/>
+ <int value="2" label="MODEL_FETCH_FAILED"/>
+ <int value="3" label="MODEL_EMPTY"/>
+ <int value="4" label="MODEL_TOO_LARGE"/>
+ <int value="5" label="MODEL_PARSE_ERROR"/>
+ <int value="6" label="MODEL_MISSING_FIELDS"/>
+ <int value="7" label="MODEL_INVALID_VERSION_NUMBER"/>
+</enum>
+
+<enum name="SBClientPhishingPreClassificationCheckFail" type="int">
+ <int value="0" label="PROXY_FETCH"/>
+ <int value="1" label="PRIVATE_IP"/>
+ <int value="2" label="OFF_THE_RECORD"/>
+ <int value="3" label="MATCH_CSD_WHITELIST"/>
+ <int value="4" label="TOO_MANY_REPORTS"/>
+ <int value="5" label="UNSUPPORTED_MIME_TYPE"/>
+</enum>
+
+<enum name="SBClientPhishingScorerCreationStatus" type="int">
+ <int value="0" label="SUCCESS"/>
+ <int value="1" label="MODEL_OPEN_FAIL"/>
+ <int value="2" label="MODEL_FILE_EMPTY"/>
+ <int value="3" label="MODEL_FILE_TOO_LARGE"/>
+ <int value="4" label="MODEL_PARSE_ERROR"/>
+ <int value="5" label="MODEL_MISSING_FIELDS"/>
+</enum>
+
+<enum name="SBDownloadFeedbackUploadResult" type="int">
+ <int value="0" label="SUCCESS"/>
+ <int value="1" label="UPLOAD_SUCCESS"/>
+ <int value="2" label="UPLOAD_CANCELLED"/>
+ <int value="3" label="UPLOAD_METADATA_NET_ERROR"/>
+ <int value="4" label="UPLOAD_METADATA_RESPONSE_ERROR"/>
+ <int value="5" label="UPLOAD_FILE_NET_ERROR"/>
+ <int value="6" label="UPLOAD_FILE_RESPONSE_ERROR"/>
+ <int value="7" label="UPLOAD_COMPLETE_RESPONSE_ERROR"/>
+</enum>
+
+<enum name="ScrollThread" type="int">
+ <int value="0" label="Scroll on impl-thread"/>
+ <int value="1" label="Scroll on main-thread"/>
+</enum>
+
+<enum name="SearchEngine" type="int">
+ <obsolete>
+ Deprecated 8/2013. No longer generated.
+ </obsolete>
+ <summary>
+ Indices of most popular prepopulated search engines as defined in
+ chrome/browser/search_engines/search_engine_type.h.
+ </summary>
+ <int value="0" label="OTHER"/>
+ <int value="1" label="GOOGLE"/>
+ <int value="2" label="YAHOO"/>
+ <int value="3" label="YAHOOJP"/>
+ <int value="4" label="BING"/>
+ <int value="5" label="ASK"/>
+ <int value="6" label="YANDEX"/>
+ <int value="7" label="SEZNAM"/>
+ <int value="8" label="CENTRUM"/>
+ <int value="9" label="NETSPRINT"/>
+ <int value="10" label="VIRGILIO"/>
+ <int value="11" label="MAILRU"/>
+ <int value="12" label="ABCSOK"/>
+ <int value="13" label="ALTAVISTA"/>
+ <int value="14" label="BAIDU"/>
+ <int value="15" label="DAUM"/>
+ <int value="16" label="DELFI"/>
+ <int value="17" label="DIRI"/>
+ <int value="18" label="GOO"/>
+ <int value="19" label="IN"/>
+ <int value="20" label="NAJDI"/>
+ <int value="21" label="NAVER"/>
+ <int value="22" label="NETI"/>
+ <int value="23" label="OK"/>
+ <int value="24" label="POGODAK"/>
+ <int value="25" label="POGODOK_MK"/>
+ <int value="26" label="RAMBLER"/>
+ <int value="27" label="SANOOK"/>
+ <int value="28" label="SAPO"/>
+ <int value="29" label="TUT"/>
+ <int value="30" label="WALLA"/>
+ <int value="31" label="ZOZNAM"/>
+ <int value="32" label="YAHOOQC"/>
+ <int value="33" label="NONE"/>
+</enum>
+
+<enum name="SessionStartupPref" type="int">
+ <int value="0" label="Open home page (unused)"/>
+ <int value="1" label="Continue from last opened pages"/>
+ <int value="4" label="Open URLs"/>
+ <int value="5" label="Open new tab page"/>
+</enum>
+
+<enum name="SessionStartupType" type="int">
+ <obsolete>
+ Deprecated 8/2013. No longer generated.
+ </obsolete>
+ <int value="0" label="New Tab page"/>
+ <int value="1" label="Homepage (DEPRECATED)"/>
+ <int value="2" label="Last session"/>
+ <int value="3" label="Specified URLs"/>
+</enum>
+
+<enum name="ShillTerminationActionResult" type="int">
+ <summary>
+ The termination action result types come from TerminationActionResult in
+ shill/metrics.h
+ </summary>
+ <int value="0" label="Success"/>
+ <int value="1" label="Failure"/>
+</enum>
+
+<enum name="SideloadUIEvents" type="int">
+ <int value="0" label="Extension installed"/>
+ <int value="1" label="Extension ignored"/>
+ <int value="2" label="Extension re-enabled"/>
+ <int value="3" label="Extension uninstalled"/>
+</enum>
+
+<enum name="SideloadWipeoutBubble" type="int">
+ <int value="0" label="Learn more"/>
+ <int value="1" label="Settings page"/>
+ <int value="2" label="Dismiss"/>
+</enum>
+
+<enum name="SimpleCache.FileDescriptorLimitStatus" type="int">
+ <int value="0" label="Unsupported"/>
+ <int value="1" label="Supported but failed"/>
+ <int value="2" label="Succeeded"/>
+</enum>
+
+<enum name="SimpleCacheHeaderSizeChange" type="int">
+ <int value="0" label="Written for the first time"/>
+ <int value="1" label="Rewritten with same size"/>
+ <int value="2" label="Rewritten with larger size"/>
+ <int value="3" label="Rewritten with smaller size"/>
+ <int value="4" label="Unexpected header stream write"/>
+</enum>
+
+<enum name="SimpleCacheIndexInitializeMethod" type="int">
+ <int value="0" label="Directory Scan"/>
+ <int value="1" label="Index File"/>
+ <int value="2" label="New Cache"/>
+</enum>
+
+<enum name="SimpleCacheOpenEntryIndexState" type="int">
+ <int value="0" label="No index"/>
+ <int value="1" label="Hit"/>
+ <int value="2" label="Miss"/>
+</enum>
+
+<enum name="SimpleCacheReadParallelizable" type="int">
+ <int value="0" label="Standalone Read"/>
+ <int value="1" label="Read in a sequence"/>
+</enum>
+
+<enum name="SimpleCacheReadResult" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Invalid Argument"/>
+ <int value="2" label="Nonblocking Empty Return"/>
+ <int value="3" label="Invalid State"/>
+ <int value="4" label="Fast Empty Return"/>
+ <int value="5" label="Synchronous Read Failure"/>
+ <int value="6" label="Synchronous Checksum Failure"/>
+</enum>
+
+<enum name="SimpleCacheSyncCheckEOFResult" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Read Failure"/>
+ <int value="2" label="Magic Number Mismatch"/>
+ <int value="3" label="CRC Mismatch"/>
+</enum>
+
+<enum name="SimpleCacheSyncCloseResult" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Write Failure"/>
+</enum>
+
+<enum name="SimpleCacheSyncCreateResult" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Platform File Error"/>
+ <int value="2" label="Can't Write Header"/>
+ <int value="3" label="Can't Write Key"/>
+</enum>
+
+<enum name="SimpleCacheSyncOpenResult" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Platform File Error"/>
+ <int value="2" label="Can't Read Header"/>
+ <int value="3" label="Bad Magic Number"/>
+ <int value="4" label="Bad Version"/>
+ <int value="5" label="Can't Read Key"/>
+ <int value="6" label="Key Mismatch (obsolete)"/>
+ <int value="7" label="Hash Mismatch"/>
+</enum>
+
+<enum name="SimpleCacheSyncWriteResult" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Pretruncate Failure"/>
+ <int value="2" label="Write Failure"/>
+ <int value="3" label="Truncate Failure"/>
+</enum>
+
+<enum name="SimpleCacheWriteDependencyType" type="int">
+ <int value="0" label="First operation in the queue (Optimistic)"/>
+ <int value="1" label="Follows conflicting optimistic write"/>
+ <int value="2" label="Follows non conflicting optimistic write"/>
+ <int value="3" label="Follows conflicting conservative write"/>
+ <int value="4" label="Follows non conflicting conservative write"/>
+ <int value="5" label="Follows conflicting read"/>
+ <int value="6" label="Follows non conflicting read"/>
+ <int value="7" label="Follows other operation"/>
+</enum>
+
+<enum name="SimpleCacheWriteResult" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Invalid Argument"/>
+ <int value="2" label="Over Max Size"/>
+ <int value="3" label="Bad State"/>
+ <int value="4" label="Synchronous Write Failure"/>
+</enum>
+
+<enum name="SimpleIndexState" type="int">
+ <int value="0" label="Corrupt"/>
+ <int value="1" label="Stale"/>
+ <int value="2" label="Fresh"/>
+ <int value="3" label="Fresh index with cache updated since backend start"/>
+</enum>
+
+<enum name="SocketStreamConnectionType" type="int">
+ <int value="0" label="none"/>
+ <int value="1" label="all connections"/>
+ <int value="2" label="tunnel connections"/>
+ <int value="3" label="socks connections"/>
+ <int value="4" label="ssl connections"/>
+</enum>
+
+<enum name="SocketStreamProtocolType" type="int">
+ <int value="0" label="unknown"/>
+ <int value="1" label="ws"/>
+ <int value="2" label="wss"/>
+</enum>
+
+<enum name="SpdyFrameFlowControlState" type="int">
+ <int value="0" label="Send not stalled"/>
+ <int value="1" label="Send stalled by stream"/>
+ <int value="2" label="Send stalled by session"/>
+ <int value="3" label="Send stalled by stream and session"/>
+</enum>
+
+<enum name="SpdyIPPoolDomainMatch" type="int">
+ <int value="0" label="mismatch"/>
+ <int value="1" label="match"/>
+</enum>
+
+<!-- Replaced by SpdyProtocolErrorDetails2 on 2013-04-19. -->
+
+<enum name="SpdyProtocolErrorDetails" type="int">
+ <int value="0" label="No error"/>
+ <int value="1" label="Invalid Control Frame"/>
+ <int value="2" label="Control Frame Payload Too Large"/>
+ <int value="3" label="Zlib Init Failure"/>
+ <int value="4" label="Unsupported Version"/>
+ <int value="5" label="Decompress Failure"/>
+ <int value="6" label="Compress Failure"/>
+ <int value="7" label="Credential Frame Corrupt"/>
+ <int value="8" label="Invalid Data Frame Flags"/>
+<!-- r181910 added an enum value here, so don't trust the counts for
+ the values below for Chrome builds after that revision. -->
+
+ <int value="9" label="Invalid Status Code"/>
+ <int value="10" label="Protocol Error"/>
+ <int value="11" label="Invalid Stream"/>
+ <int value="12" label="Refused Stream"/>
+ <int value="13" label="Unsupported Version"/>
+ <int value="14" label="Cancel"/>
+ <int value="15" label="Internal Error"/>
+ <int value="16" label="Flow Control Error"/>
+ <int value="17" label="Stream In Use"/>
+ <int value="18" label="Stream Already Closed"/>
+ <int value="19" label="Invalid Credentials"/>
+ <int value="20" label="Frame Too Large"/>
+ <int value="21" label="Unexpected Ping"/>
+ <int value="22" label="Rst Stream For Non Active Stream"/>
+ <int value="23" label="Spdy Compression Failure"/>
+ <int value="24" label="Request For Secure Content Over Insecure Session"/>
+ <int value="25" label="Protocol Error Syn Reply Not Received"/>
+ <int value="26" label="Num Spdy Protocol Error Details"/>
+</enum>
+
+<enum name="SpdyProtocolErrorDetails2" type="int">
+<!-- SpdyFramer::SpdyErrors -->
+
+ <int value="0" label="No error"/>
+ <int value="1" label="Invalid Control Frame"/>
+ <int value="2" label="Control Frame Payload Too Large"/>
+ <int value="3" label="Zlib Init Failure"/>
+ <int value="4" label="Unsupported Version"/>
+ <int value="5" label="Decompress Failure"/>
+ <int value="6" label="Compress Failure"/>
+ <int value="7" label="Credential Frame Corrupt"/>
+ <int value="8" label="Invalid Data Frame Flags"/>
+ <int value="9" label="Invalid Control Frame Flags"/>
+<!-- SpdyRstStreamStatus -->
+
+ <int value="10" label="(Unused)"/>
+ <int value="11" label="Protocol Error"/>
+ <int value="12" label="Invalid Stream"/>
+ <int value="13" label="Refused Stream"/>
+ <int value="14" label="Unsupported Version"/>
+ <int value="15" label="Cancel"/>
+ <int value="16" label="Internal Error"/>
+ <int value="17" label="Flow Control Error"/>
+ <int value="18" label="Stream In Use"/>
+ <int value="19" label="Stream Already Closed"/>
+ <int value="20" label="Invalid Credentials"/>
+ <int value="21" label="Frame Too Large"/>
+<!-- SpdySession errors -->
+
+ <int value="22" label="Unexpected Ping"/>
+ <int value="23" label="Rst Stream For Non Active Stream"/>
+ <int value="24" label="Spdy Compression Failure"/>
+ <int value="25" label="Request For Secure Content Over Insecure Session"/>
+ <int value="26" label="Syn Reply Not Received"/>
+ <int value="27" label="Invalid Window Update Size"/>
+ <int value="28" label="Receive Window Size Violation"/>
+ <int value="29" label="(Unused)"/>
+</enum>
+
+<enum name="SpdySessionGet" type="int">
+ <int value="0" label="created new"/>
+ <int value="1" label="found existing"/>
+ <int value="2" label="found existing from IP Pool"/>
+ <int value="3" label="imported from socket"/>
+</enum>
+
+<enum name="SpdySettingsReceived" type="int">
+ <int value="0" label="not received"/>
+ <int value="1" label="received"/>
+</enum>
+
+<enum name="SpdySettingsSent" type="int">
+ <int value="0" label="not sent"/>
+ <int value="1" label="sent"/>
+</enum>
+
+<enum name="SpecialShFileOperationCodes" type="int">
+ <summary>Legacy error codes still returned by |ShFileOperation()|</summary>
+ <int value="5" label="Access denied"/>
+ <int value="113" label="Source and Destination are same file"/>
+ <int value="114" label="Multiple source mapped to single destination"/>
+ <int value="115" label="Rename to different directory"/>
+ <int value="116" label="Source root"/>
+ <int value="117" label="Canceled by user"/>
+ <int value="118" label="Destination is subtree of source"/>
+ <int value="120" label="Denied by security settings"/>
+ <int value="121" label="Path length exceeded MAX_PATH"/>
+ <int value="122" label="Multiple destination paths"/>
+ <int value="124" label="Path invalid"/>
+ <int value="125" label="Source and destination have same parent"/>
+ <int value="126" label="Destination exists"/>
+ <int value="128" label="Destination exists as folder"/>
+ <int value="129" label="Name length exceeded MAX_PATH"/>
+ <int value="130" label="Destination read-only CD-ROM"/>
+ <int value="131" label="Destination read-only DVD"/>
+ <int value="132" label="Destination writable CD-ROM"/>
+ <int value="133" label="File too large"/>
+ <int value="134" label="Source read-only CD-ROM"/>
+ <int value="135" label="Source read-only DVD"/>
+ <int value="136" label="Source writable CD-ROM"/>
+ <int value="183" label="Operation exceeded MAX_PATH"/>
+ <int value="1026" label="Invalid path / unknown"/>
+ <int value="65536" label="Unspecified destination error"/>
+ <int value="65652" label="Destination root"/>
+</enum>
+
+<enum name="SqliteErrorCode" type="int">
+ <summary>Error codes returned by SQLite - see sqlite3.h</summary>
+ <int value="0" label="SQLITE_OK">Successful result</int>
+ <int value="1" label="SQLITE_ERROR">SQL error or missing database</int>
+ <int value="2" label="SQLITE_INTERNAL">
+ NOT USED. Internal logic error in SQLite
+ </int>
+ <int value="3" label="SQLITE_PERM">Access permission denied</int>
+ <int value="4" label="SQLITE_ABORT">Callback routine requested an abort</int>
+ <int value="5" label="SQLITE_BUSY">The database file is locked</int>
+ <int value="6" label="SQLITE_LOCKED">A table in the database is locked</int>
+ <int value="7" label="SQLITE_NOMEM">A malloc() failed</int>
+ <int value="8" label="SQLITE_READONLY">
+ Attempt to write a readonly database
+ </int>
+ <int value="9" label="SQLITE_INTERRUPT">
+ Operation terminated by sqlite3_interrupt()
+ </int>
+ <int value="10" label="SQLITE_IOERR">
+ Some kind of disk I/O error occurred
+ </int>
+ <int value="11" label="SQLITE_CORRUPT">
+ The database disk image is malformed
+ </int>
+ <int value="12" label="SQLITE_NOTFOUND">
+ NOT USED. Table or record not found
+ </int>
+ <int value="13" label="SQLITE_FULL">
+ Insertion failed because database is full
+ </int>
+ <int value="14" label="SQLITE_CANTOPEN">Unable to open the database file</int>
+ <int value="15" label="SQLITE_PROTOCOL">
+ NOT USED. Database lock protocol error
+ </int>
+ <int value="16" label="SQLITE_EMPTY">Database is empty</int>
+ <int value="17" label="SQLITE_SCHEMA">The database schema changed</int>
+ <int value="18" label="SQLITE_TOOBIG">String or BLOB exceeds size limit</int>
+ <int value="19" label="SQLITE_CONSTRAINT">
+ Abort due to contraint violation
+ </int>
+ <int value="20" label="SQLITE_MISMATCH">Data type mismatch</int>
+ <int value="21" label="SQLITE_MISUSE">Library used incorrectly</int>
+ <int value="22" label="SQLITE_NOLFS">
+ Uses OS features not supported on host
+ </int>
+ <int value="23" label="SQLITE_AUTH">Authorization denied</int>
+ <int value="24" label="SQLITE_FORMAT">Auxiliary database format error</int>
+ <int value="25" label="SQLITE_RANGE">
+ 2nd parameter to sqlite3_bind() out of range
+ </int>
+ <int value="26" label="SQLITE_NOTADB">
+ File opened that is not a database file
+ </int>
+ <int value="100" label="SQLITE_ROW">sqlite3_step() has another row ready</int>
+ <int value="101" label="SQLITE_DONE">
+ sqlite3_step() has finished executing
+ </int>
+ <int value="261" label="SQLITE_BUSY_RECOVERY">TBD</int>
+ <int value="262" label="SQLITE_LOCKED_SHAREDCACHE">TBD</int>
+ <int value="266" label="SQLITE_IOERR_READ">Error reading from file</int>
+ <int value="270" label="SQLITE_CANTOPEN_NOTEMPDIR">TBD</int>
+ <int value="522" label="SQLITE_IOERR_SHORT_READ">Short read from file</int>
+ <int value="778" label="SQLITE_IOERR_WRITE">
+ Error writing to file (other than SQLITE_FULL)
+ </int>
+ <int value="1034" label="SQLITE_IOERR_FSYNC">Error syncing to disk</int>
+ <int value="1290" label="SQLITE_IOERR_DIR_FSYNC">
+ Error syncing directory changes to disk
+ </int>
+ <int value="1546" label="SQLITE_IOERR_TRUNCATE">Error truncating file</int>
+ <int value="1802" label="SQLITE_IOERR_FSTAT">Error reading file metadata</int>
+ <int value="2058" label="SQLITE_IOERR_UNLOCK">Error unlocking file</int>
+ <int value="2314" label="SQLITE_IOERR_RDLOCK">
+ Error getting read lock - should not be possible
+ </int>
+ <int value="2570" label="SQLITE_IOERR_DELETE">Error deleting file</int>
+ <int value="2826" label="SQLITE_IOERR_BLOCKED">
+ Deadlock due to other process access to SQLite files
+ </int>
+ <int value="3082" label="SQLITE_IOERR_NOMEM">Error mapping shared memory</int>
+ <int value="3338" label="SQLITE_IOERR_ACCESS">
+ Error getting file attributes (other than not found)
+ </int>
+ <int value="3594" label="SQLITE_IOERR_CHECKRESERVEDLOCK">
+ Error while querying lock status
+ </int>
+ <int value="3850" label="SQLITE_IOERR_LOCK">Error acquiring lock</int>
+ <int value="4106" label="SQLITE_IOERR_CLOSE">Error closing file</int>
+ <int value="4362" label="SQLITE_IOERR_DIR_CLOSE">Unused</int>
+ <int value="4618" label="SQLITE_IOERR_SHMOPEN">Error mmapping file</int>
+ <int value="4874" label="SQLITE_IOERR_SHMSIZE">
+ Error in stat while mmapping file
+ </int>
+ <int value="5130" label="SQLITE_IOERR_SHMLOCK">Unused</int>
+</enum>
+
+<enum name="SqliteIOERRCode" type="int">
+ <obsolete>
+ Replaced 5/14/2013 by expanded Sqlite.Error histogram.
+ </obsolete>
+ <summary>Extended error codes returned by SQLite - see sqlite3.h</summary>
+ <int value="0" label="SQLITE_IOERR">No extended code given</int>
+ <int value="1" label="SQLITE_IOERR_READ">Error reading from file</int>
+ <int value="2" label="SQLITE_IOERR_SHORT_READ">Short read from file</int>
+ <int value="3" label="SQLITE_IOERR_WRITE">
+ Error writing to file (other than SQLITE_FULL)
+ </int>
+ <int value="4" label="SQLITE_IOERR_FSYNC">Error syncing to disk</int>
+ <int value="5" label="SQLITE_IOERR_DIR_FSYNC">
+ Error syncing directory changes to disk
+ </int>
+ <int value="6" label="SQLITE_IOERR_TRUNCATE">Error truncating file</int>
+ <int value="7" label="SQLITE_IOERR_FSTAT">Error reading file metadata</int>
+ <int value="8" label="SQLITE_IOERR_UNLOCK">Error unlocking file</int>
+ <int value="9" label="SQLITE_IOERR_RDLOCK">
+ Error getting read lock - should not be possible
+ </int>
+ <int value="10" label="SQLITE_IOERR_DELETE">Error deleting file</int>
+ <int value="11" label="SQLITE_IOERR_BLOCKED">
+ Deadlock due to other process access to SQLite files
+ </int>
+ <int value="12" label="SQLITE_IOERR_NOMEM">Error mapping shared memory</int>
+ <int value="13" label="SQLITE_IOERR_ACCESS">
+ Error getting file attributes (other than not found)
+ </int>
+ <int value="14" label="SQLITE_IOERR_CHECKRESERVEDLOCK">
+ Error while querying lock status
+ </int>
+ <int value="15" label="SQLITE_IOERR_LOCK">Error acquiring lock</int>
+ <int value="16" label="SQLITE_IOERR_CLOSE">Error closing file</int>
+ <int value="17" label="SQLITE_IOERR_DIR_CLOSE">Unused</int>
+ <int value="18" label="SQLITE_IOERR_SHMOPEN">Error mmapping file</int>
+ <int value="19" label="SQLITE_IOERR_SHMSIZE">
+ Error in stat while mmapping file
+ </int>
+ <int value="20" label="SQLITE_IOERR_SHMLOCK">Unused</int>
+</enum>
+
+<enum name="SSLCipherSuite" type="int">
+ <summary>SSL/TLS cipher suites from the IANA registry</summary>
+ <int value="0" label="TLS_NULL_WITH_NULL_NULL"/>
+ <int value="1" label="TLS_RSA_WITH_NULL_MD5"/>
+ <int value="2" label="TLS_RSA_WITH_NULL_SHA"/>
+ <int value="3" label="TLS_RSA_EXPORT_WITH_RC4_40_MD5"/>
+ <int value="4" label="TLS_RSA_WITH_RC4_128_MD5"/>
+ <int value="5" label="TLS_RSA_WITH_RC4_128_SHA"/>
+ <int value="6" label="TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"/>
+ <int value="7" label="TLS_RSA_WITH_IDEA_CBC_SHA"/>
+ <int value="8" label="TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"/>
+ <int value="9" label="TLS_RSA_WITH_DES_CBC_SHA"/>
+ <int value="10" label="TLS_RSA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="11" label="TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"/>
+ <int value="12" label="TLS_DH_DSS_WITH_DES_CBC_SHA"/>
+ <int value="13" label="TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="14" label="TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"/>
+ <int value="15" label="TLS_DH_RSA_WITH_DES_CBC_SHA"/>
+ <int value="16" label="TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="17" label="TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"/>
+ <int value="18" label="TLS_DHE_DSS_WITH_DES_CBC_SHA"/>
+ <int value="19" label="TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="20" label="TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"/>
+ <int value="21" label="TLS_DHE_RSA_WITH_DES_CBC_SHA"/>
+ <int value="22" label="TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="23" label="TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"/>
+ <int value="24" label="TLS_DH_anon_WITH_RC4_128_MD5"/>
+ <int value="25" label="TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"/>
+ <int value="26" label="TLS_DH_anon_WITH_DES_CBC_SHA"/>
+ <int value="27" label="TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="30" label="TLS_KRB5_WITH_DES_CBC_SHA"/>
+ <int value="31" label="TLS_KRB5_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="32" label="TLS_KRB5_WITH_RC4_128_SHA"/>
+ <int value="33" label="TLS_KRB5_WITH_IDEA_CBC_SHA"/>
+ <int value="34" label="TLS_KRB5_WITH_DES_CBC_MD5"/>
+ <int value="35" label="TLS_KRB5_WITH_3DES_EDE_CBC_MD5"/>
+ <int value="36" label="TLS_KRB5_WITH_RC4_128_MD5"/>
+ <int value="37" label="TLS_KRB5_WITH_IDEA_CBC_MD5"/>
+ <int value="38" label="TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"/>
+ <int value="39" label="TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"/>
+ <int value="40" label="TLS_KRB5_EXPORT_WITH_RC4_40_SHA"/>
+ <int value="41" label="TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"/>
+ <int value="42" label="TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"/>
+ <int value="43" label="TLS_KRB5_EXPORT_WITH_RC4_40_MD5"/>
+ <int value="44" label="TLS_PSK_WITH_NULL_SHA"/>
+ <int value="45" label="TLS_DHE_PSK_WITH_NULL_SHA"/>
+ <int value="46" label="TLS_RSA_PSK_WITH_NULL_SHA"/>
+ <int value="47" label="TLS_RSA_WITH_AES_128_CBC_SHA"/>
+ <int value="48" label="TLS_DH_DSS_WITH_AES_128_CBC_SHA"/>
+ <int value="49" label="TLS_DH_RSA_WITH_AES_128_CBC_SHA"/>
+ <int value="50" label="TLS_DHE_DSS_WITH_AES_128_CBC_SHA"/>
+ <int value="51" label="TLS_DHE_RSA_WITH_AES_128_CBC_SHA"/>
+ <int value="52" label="TLS_DH_anon_WITH_AES_128_CBC_SHA"/>
+ <int value="53" label="TLS_RSA_WITH_AES_256_CBC_SHA"/>
+ <int value="54" label="TLS_DH_DSS_WITH_AES_256_CBC_SHA"/>
+ <int value="55" label="TLS_DH_RSA_WITH_AES_256_CBC_SHA"/>
+ <int value="56" label="TLS_DHE_DSS_WITH_AES_256_CBC_SHA"/>
+ <int value="57" label="TLS_DHE_RSA_WITH_AES_256_CBC_SHA"/>
+ <int value="58" label="TLS_DH_anon_WITH_AES_256_CBC_SHA"/>
+ <int value="59" label="TLS_RSA_WITH_NULL_SHA256"/>
+ <int value="60" label="TLS_RSA_WITH_AES_128_CBC_SHA256"/>
+ <int value="61" label="TLS_RSA_WITH_AES_256_CBC_SHA256"/>
+ <int value="62" label="TLS_DH_DSS_WITH_AES_128_CBC_SHA256"/>
+ <int value="63" label="TLS_DH_RSA_WITH_AES_128_CBC_SHA256"/>
+ <int value="64" label="TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"/>
+ <int value="65" label="TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"/>
+ <int value="66" label="TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"/>
+ <int value="67" label="TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"/>
+ <int value="68" label="TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"/>
+ <int value="69" label="TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"/>
+ <int value="70" label="TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"/>
+ <int value="103" label="TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"/>
+ <int value="104" label="TLS_DH_DSS_WITH_AES_256_CBC_SHA256"/>
+ <int value="105" label="TLS_DH_RSA_WITH_AES_256_CBC_SHA256"/>
+ <int value="106" label="TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"/>
+ <int value="107" label="TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"/>
+ <int value="108" label="TLS_DH_anon_WITH_AES_128_CBC_SHA256"/>
+ <int value="109" label="TLS_DH_anon_WITH_AES_256_CBC_SHA256"/>
+ <int value="132" label="TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"/>
+ <int value="133" label="TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"/>
+ <int value="134" label="TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"/>
+ <int value="135" label="TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"/>
+ <int value="136" label="TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"/>
+ <int value="137" label="TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"/>
+ <int value="138" label="TLS_PSK_WITH_RC4_128_SHA"/>
+ <int value="139" label="TLS_PSK_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="140" label="TLS_PSK_WITH_AES_128_CBC_SHA"/>
+ <int value="141" label="TLS_PSK_WITH_AES_256_CBC_SHA"/>
+ <int value="142" label="TLS_DHE_PSK_WITH_RC4_128_SHA"/>
+ <int value="143" label="TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="144" label="TLS_DHE_PSK_WITH_AES_128_CBC_SHA"/>
+ <int value="145" label="TLS_DHE_PSK_WITH_AES_256_CBC_SHA"/>
+ <int value="146" label="TLS_RSA_PSK_WITH_RC4_128_SHA"/>
+ <int value="147" label="TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="148" label="TLS_RSA_PSK_WITH_AES_128_CBC_SHA"/>
+ <int value="149" label="TLS_RSA_PSK_WITH_AES_256_CBC_SHA"/>
+ <int value="150" label="TLS_RSA_WITH_SEED_CBC_SHA"/>
+ <int value="151" label="TLS_DH_DSS_WITH_SEED_CBC_SHA"/>
+ <int value="152" label="TLS_DH_RSA_WITH_SEED_CBC_SHA"/>
+ <int value="153" label="TLS_DHE_DSS_WITH_SEED_CBC_SHA"/>
+ <int value="154" label="TLS_DHE_RSA_WITH_SEED_CBC_SHA"/>
+ <int value="155" label="TLS_DH_anon_WITH_SEED_CBC_SHA"/>
+ <int value="156" label="TLS_RSA_WITH_AES_128_GCM_SHA256"/>
+ <int value="157" label="TLS_RSA_WITH_AES_256_GCM_SHA384"/>
+ <int value="158" label="TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"/>
+ <int value="159" label="TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"/>
+ <int value="160" label="TLS_DH_RSA_WITH_AES_128_GCM_SHA256"/>
+ <int value="161" label="TLS_DH_RSA_WITH_AES_256_GCM_SHA384"/>
+ <int value="162" label="TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"/>
+ <int value="163" label="TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"/>
+ <int value="164" label="TLS_DH_DSS_WITH_AES_128_GCM_SHA256"/>
+ <int value="165" label="TLS_DH_DSS_WITH_AES_256_GCM_SHA384"/>
+ <int value="166" label="TLS_DH_anon_WITH_AES_128_GCM_SHA256"/>
+ <int value="167" label="TLS_DH_anon_WITH_AES_256_GCM_SHA384"/>
+ <int value="168" label="TLS_PSK_WITH_AES_128_GCM_SHA256"/>
+ <int value="169" label="TLS_PSK_WITH_AES_256_GCM_SHA384"/>
+ <int value="170" label="TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"/>
+ <int value="171" label="TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"/>
+ <int value="172" label="TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"/>
+ <int value="173" label="TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"/>
+ <int value="174" label="TLS_PSK_WITH_AES_128_CBC_SHA256"/>
+ <int value="175" label="TLS_PSK_WITH_AES_256_CBC_SHA384"/>
+ <int value="176" label="TLS_PSK_WITH_NULL_SHA256"/>
+ <int value="177" label="TLS_PSK_WITH_NULL_SHA384"/>
+ <int value="178" label="TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"/>
+ <int value="179" label="TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"/>
+ <int value="180" label="TLS_DHE_PSK_WITH_NULL_SHA256"/>
+ <int value="181" label="TLS_DHE_PSK_WITH_NULL_SHA384"/>
+ <int value="182" label="TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"/>
+ <int value="183" label="TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"/>
+ <int value="184" label="TLS_RSA_PSK_WITH_NULL_SHA256"/>
+ <int value="185" label="TLS_RSA_PSK_WITH_NULL_SHA384"/>
+ <int value="186" label="TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="187" label="TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="188" label="TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="189" label="TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="190" label="TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="191" label="TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="192" label="TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"/>
+ <int value="193" label="TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"/>
+ <int value="194" label="TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"/>
+ <int value="195" label="TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"/>
+ <int value="196" label="TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"/>
+ <int value="197" label="TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"/>
+ <int value="255" label="TLS_EMPTY_RENEGOTIATION_INFO_SCSV"/>
+ <int value="49153" label="TLS_ECDH_ECDSA_WITH_NULL_SHA"/>
+ <int value="49154" label="TLS_ECDH_ECDSA_WITH_RC4_128_SHA"/>
+ <int value="49155" label="TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49156" label="TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"/>
+ <int value="49157" label="TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"/>
+ <int value="49158" label="TLS_ECDHE_ECDSA_WITH_NULL_SHA"/>
+ <int value="49159" label="TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"/>
+ <int value="49160" label="TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49161" label="TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"/>
+ <int value="49162" label="TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"/>
+ <int value="49163" label="TLS_ECDH_RSA_WITH_NULL_SHA"/>
+ <int value="49164" label="TLS_ECDH_RSA_WITH_RC4_128_SHA"/>
+ <int value="49165" label="TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49166" label="TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"/>
+ <int value="49167" label="TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"/>
+ <int value="49168" label="TLS_ECDHE_RSA_WITH_NULL_SHA"/>
+ <int value="49169" label="TLS_ECDHE_RSA_WITH_RC4_128_SHA"/>
+ <int value="49170" label="TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49171" label="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"/>
+ <int value="49172" label="TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"/>
+ <int value="49173" label="TLS_ECDH_anon_WITH_NULL_SHA"/>
+ <int value="49174" label="TLS_ECDH_anon_WITH_RC4_128_SHA"/>
+ <int value="49175" label="TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49176" label="TLS_ECDH_anon_WITH_AES_128_CBC_SHA"/>
+ <int value="49177" label="TLS_ECDH_anon_WITH_AES_256_CBC_SHA"/>
+ <int value="49178" label="TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49179" label="TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49180" label="TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49181" label="TLS_SRP_SHA_WITH_AES_128_CBC_SHA"/>
+ <int value="49182" label="TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"/>
+ <int value="49183" label="TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"/>
+ <int value="49184" label="TLS_SRP_SHA_WITH_AES_256_CBC_SHA"/>
+ <int value="49185" label="TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"/>
+ <int value="49186" label="TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"/>
+ <int value="49187" label="TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"/>
+ <int value="49188" label="TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"/>
+ <int value="49189" label="TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"/>
+ <int value="49190" label="TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"/>
+ <int value="49191" label="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"/>
+ <int value="49192" label="TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"/>
+ <int value="49193" label="TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"/>
+ <int value="49194" label="TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"/>
+ <int value="49195" label="TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"/>
+ <int value="49196" label="TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"/>
+ <int value="49197" label="TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"/>
+ <int value="49198" label="TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"/>
+ <int value="49199" label="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"/>
+ <int value="49200" label="TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"/>
+ <int value="49201" label="TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"/>
+ <int value="49202" label="TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"/>
+ <int value="49203" label="TLS_ECDHE_PSK_WITH_RC4_128_SHA"/>
+ <int value="49204" label="TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"/>
+ <int value="49205" label="TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"/>
+ <int value="49206" label="TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"/>
+ <int value="49207" label="TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"/>
+ <int value="49208" label="TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"/>
+ <int value="49209" label="TLS_ECDHE_PSK_WITH_NULL_SHA"/>
+ <int value="49210" label="TLS_ECDHE_PSK_WITH_NULL_SHA256"/>
+ <int value="49211" label="TLS_ECDHE_PSK_WITH_NULL_SHA384"/>
+ <int value="49212" label="TLS_RSA_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49213" label="TLS_RSA_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49214" label="TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49215" label="TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49216" label="TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49217" label="TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49218" label="TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49219" label="TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49220" label="TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49221" label="TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49222" label="TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49223" label="TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49224" label="TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49225" label="TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49226" label="TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49227" label="TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49228" label="TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49229" label="TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49230" label="TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49231" label="TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49232" label="TLS_RSA_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49233" label="TLS_RSA_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49234" label="TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49235" label="TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49236" label="TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49237" label="TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49238" label="TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49239" label="TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49240" label="TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49241" label="TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49242" label="TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49243" label="TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49244" label="TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49245" label="TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49246" label="TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49247" label="TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49248" label="TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49249" label="TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49250" label="TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49251" label="TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49252" label="TLS_PSK_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49253" label="TLS_PSK_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49254" label="TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49255" label="TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49256" label="TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49257" label="TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49258" label="TLS_PSK_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49259" label="TLS_PSK_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49260" label="TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49261" label="TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49262" label="TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"/>
+ <int value="49263" label="TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"/>
+ <int value="49264" label="TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256"/>
+ <int value="49265" label="TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384"/>
+ <int value="49266" label="TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="49267" label="TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"/>
+ <int value="49268" label="TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="49269" label="TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"/>
+ <int value="49270" label="TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="49271" label="TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"/>
+ <int value="49272" label="TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="49273" label="TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384"/>
+ <int value="49274" label="TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49275" label="TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49276" label="TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49277" label="TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49278" label="TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49279" label="TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49280" label="TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49281" label="TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49282" label="TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49283" label="TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49284" label="TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49285" label="TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49286" label="TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49287" label="TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49288" label="TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49289" label="TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49290" label="TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49291" label="TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49292" label="TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49293" label="TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49294" label="TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49295" label="TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49296" label="TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49297" label="TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49298" label="TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"/>
+ <int value="49299" label="TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"/>
+ <int value="49300" label="TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="49301" label="TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"/>
+ <int value="49302" label="TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="49303" label="TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"/>
+ <int value="49304" label="TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="49305" label="TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"/>
+ <int value="49306" label="TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"/>
+ <int value="49307" label="TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"/>
+ <int value="49308" label="TLS_RSA_WITH_AES_128_CCM"/>
+ <int value="49309" label="TLS_RSA_WITH_AES_256_CCM"/>
+ <int value="49310" label="TLS_DHE_RSA_WITH_AES_128_CCM"/>
+ <int value="49311" label="TLS_DHE_RSA_WITH_AES_256_CCM"/>
+ <int value="49312" label="TLS_RSA_WITH_AES_128_CCM_8"/>
+ <int value="49313" label="TLS_RSA_WITH_AES_256_CCM_8"/>
+ <int value="49314" label="TLS_DHE_RSA_WITH_AES_128_CCM_8"/>
+ <int value="49315" label="TLS_DHE_RSA_WITH_AES_256_CCM_8"/>
+ <int value="49316" label="TLS_PSK_WITH_AES_128_CCM"/>
+ <int value="49317" label="TLS_PSK_WITH_AES_256_CCM"/>
+ <int value="49318" label="TLS_DHE_PSK_WITH_AES_128_CCM"/>
+ <int value="49319" label="TLS_DHE_PSK_WITH_AES_256_CCM"/>
+ <int value="49320" label="TLS_PSK_WITH_AES_128_CCM_8"/>
+ <int value="49321" label="TLS_PSK_WITH_AES_256_CCM_8"/>
+ <int value="49322" label="TLS_PSK_DHE_WITH_AES_128_CCM_8"/>
+ <int value="49323" label="TLS_PSK_DHE_WITH_AES_256_CCM_8"/>
+</enum>
+
+<enum name="SSLErrorTypes" type="int">
+ <int value="0" label="CERT_COMMON_NAME_INVALID"/>
+ <int value="1" label="CERT_DATE_INVALID"/>
+ <int value="2" label="CERT_AUTHORITY_INVALID"/>
+ <int value="3" label="CERT_CONTAINS_ERRORS"/>
+ <int value="4" label="CERT_NO_REVOCATION_MECHANISM"/>
+ <int value="5" label="CERT_REVOKED"/>
+ <int value="6" label="CERT_INVALID"/>
+ <int value="7" label="CERT_WEAK_SIGNATURE_ALGORITHM"/>
+ <int value="8" label="CERT_WEAK_KEY"/>
+ <int value="9" label="UNKNOWN"/>
+</enum>
+
+<enum name="SSLResponseTypesV2" type="int">
+ <int value="0" label="SHOW_ALL"/>
+ <int value="1" label="SHOW_OVERRIDABLE"/>
+ <int value="2" label="PROCEED_OVERRIDABLE"/>
+ <int value="3" label="PROCEED_NAME"/>
+ <int value="4" label="PROCEED_DATE"/>
+ <int value="5" label="PROCEED_AUTHORITY"/>
+ <int value="6" label="DONT_PROCEED_OVERRIDABLE"/>
+ <int value="7" label="DONT_PROCEED_NAME"/>
+ <int value="8" label="DONT_PROCEED_DATE"/>
+ <int value="9" label="DONT_PROCEED_AUTHORITY"/>
+ <int value="10" label="MORE"/>
+ <int value="11" label="SHOW_UNDERSTAND"/>
+ <int value="12" label="SHOW_INTERNAL_HOSTNAME"/>
+ <int value="13" label="PROCEED_INTERNAL_HOSTNAME"/>
+ <int value="14" label="SHOW_NEW_SITE"/>
+ <int value="15" label="PROCEED_NEW_SITE"/>
+</enum>
+
+<enum name="SuspendStatus" type="int">
+ <int value="0" label="Success"/>
+ <int value="1" label="Failure"/>
+ <int value="2" label="Cancelled"/>
+ <int value="3" label="Attempted"/>
+</enum>
+
+<enum name="TabRestoreUserAction" type="int">
+ <int value="0" label="Wait for completion"/>
+ <int value="1" label="Leave tab (close tab/switch tab/go to tab switcher)"/>
+ <int value="2" label="Leave Chrome"/>
+</enum>
+
+<enum name="TabStatus" type="int">
+ <int value="0" label="Memory resident"/>
+ <int value="1" label="Evicted and reloaded"/>
+ <int value="2" label="Reloaded due to cold start"/>
+ <int value="3" label="Partially evicted"/>
+ <int value="4" label="Reloaded due to backgrounding"/>
+ <int value="5" label="Reloaded due to incognito"/>
+ <int value="6" label="Reloaded due to cold start (fg tab on start)"/>
+ <int value="7" label="Reloaded due to cold start (bg tab on switch)"/>
+</enum>
+
+<enum name="TabSwitchedToForegroundLaunchedWithURL" type="int">
+ <int value="0" label="Launched without an URL"/>
+ <int value="1" label="Launched with an URL"/>
+</enum>
+
+<enum name="TabSwitchedToForegroundRevisit" type="int">
+ <int value="0" label="First time"/>
+ <int value="1" label="Revisit"/>
+</enum>
+
+<enum name="TcpSocketStatus" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Fast Connection Return"/>
+ <int value="2" label="Slow Connection Return"/>
+ <int value="3" label="Connection Error"/>
+ <int value="4" label="Syn Data Acknowledged"/>
+ <int value="5" label="Syn Data Nacked"/>
+ <int value="6" label="Syn Data Probe Failed"/>
+ <int value="7" label="No syn data + ack (can't happen)"/>
+ <int value="8" label="No syn data + nack"/>
+ <int value="9" label="No syn data + probe failed"/>
+</enum>
+
+<enum name="TLSRenegotiationPatched" type="int">
+ <int value="0" label="Not renegotiation patched"/>
+ <int value="1" label="Renegotiation patched"/>
+</enum>
+
+<enum name="TouchpadDeviceState" type="int">
+ <int value="0" label="NO_TP_PRESENT_NO_TP_EXPECTED">
+ No touchpad detected on a device without built-in touchpad
+ </int>
+ <int value="1" label="TP_PRESENT_NO_TP_EXPECTED">
+ External touchpad detected on a device without built-in touchpad
+ </int>
+ <int value="2" label="NO_TP_PRESENT_TP_EXPECTED_BOOT">
+ Built-in touchpad not detected at boot time on a device with built-in
+ touchpad (touchpad failure at boot time)
+ </int>
+ <int value="3" label="TP_PRESENT_TP_EXPECTED_BOOT">
+ Built-in touchpad detected at boot time on a device with built-in touchpad
+ </int>
+ <int value="4" label="NO_TP_PRESENT_TP_EXPECTED_RESUME">
+ Built-in touchpad not detected at resume time on a device with built-in
+ touchpad (touchpad failure at resume time)
+ </int>
+ <int value="5" label="TP_PRESENT_TP_EXPECTED_RESUME">
+ Built-in touchpad detected at resume time on a device with built-in touchpad
+ </int>
+</enum>
+
+<enum name="TouchpadProblemType" type="int">
+ <int value="0" label="All events">
+ All observed input events from touchpad. Serves as a reference.
+ </int>
+ <int value="1" label="Noisy Ground">
+ The touchpad noise events (e.g. abrupt cursor jumps) caused by the noisy
+ ground.
+ </int>
+</enum>
+
+<enum name="TranslateError" type="int">
+ <int value="0" label="No error"/>
+ <int value="1" label="Network error"/>
+ <int value="2" label="Initialization error"/>
+ <int value="3" label="Unknown language"/>
+ <int value="4" label="Unsupported language"/>
+ <int value="5" label="Identical language"/>
+ <int value="6" label="Translation error"/>
+</enum>
+
+<enum name="TranslateInitiationStatus" type="int">
+ <int value="0" label="Completely disabled by prefs"/>
+ <int value="1" label="Completely disabled by switch"/>
+ <int value="2" label="Disabled by user configuration"/>
+ <int value="3" label="Unsupported Language"/>
+ <int value="4" label="Unsupported URL"/>
+ <int value="5" label="Do nothing for similar languages"/>
+ <int value="6" label="Do nothing for accepted languages"/>
+ <int value="7" label="Auto translation by user configuration"/>
+ <int value="8" label="Auto translation by linked from a translated page"/>
+ <int value="9" label="Show infobar"/>
+</enum>
+
+<enum name="TranslateLanguage" type="int">
+ <int value="0" label="No language code"/>
+ <int value="1" label="Valid language code"/>
+ <int value="2" label="Invalid language code"/>
+</enum>
+
+<enum name="TranslateLanguageVerification" type="int">
+ <int value="0" label="CLD is disabled"/>
+ <int value="1" label="No Content-Language"/>
+ <int value="2" label="CLD can not determine a language"/>
+ <int value="3" label="CLD agrees with Content-Language"/>
+ <int value="4" label="CLD disagrees with Content-Language"/>
+ <int value="5" label="CLD can be trusted"/>
+ <int value="6" label="CLD can complement a sub code"/>
+</enum>
+
+<enum name="TranslateScheme" type="int">
+ <int value="0" label="http"/>
+ <int value="1" label="https"/>
+ <int value="2" label="unexpected other schemes"/>
+</enum>
+
+<enum name="UIEventType" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Touch released"/>
+ <int value="2" label="Touch pressed"/>
+ <int value="3" label="Touch moved"/>
+ <int value="4" label="Touch stationary"/>
+ <int value="5" label="Touch cancelled"/>
+ <int value="6" label="Gesture scroll begin"/>
+ <int value="7" label="Gesture scroll end"/>
+ <int value="8" label="Gesture scroll update"/>
+ <int value="9" label="Gesture tap"/>
+ <int value="10" label="Gesture tap down"/>
+ <int value="11" label="Gesture finger down"/>
+ <int value="12" label="Gesture finger up"/>
+ <int value="13" label="Gesture double tap"/>
+ <int value="14" label="Gesture two-finger tap"/>
+ <int value="15" label="Gesture pinch begin"/>
+ <int value="16" label="Gesture pinch end"/>
+ <int value="17" label="Gesture pinch update (2 fingers)"/>
+ <int value="18" label="Long press"/>
+ <int value="19" label="Multi-finger swipe (2 fingers)"/>
+ <int value="20" label="Scroll"/>
+ <int value="21" label="Scroll fling start"/>
+ <int value="22" label="Scroll fling cancel"/>
+ <int value="23" label="Multi-finger swipe (3 fingers)"/>
+ <int value="24" label="Multi-finger swipe (4+ fingers)"/>
+ <int value="25" label="Gesture scroll update (2 fingers)"/>
+ <int value="26" label="Gesture scroll update (3 fingers)"/>
+ <int value="27" label="Gesture scroll update (4+ fingers)"/>
+ <int value="28" label="Gesture pinch update (3 fingers)"/>
+ <int value="29" label="Gesture pinch update (4+ fingers)"/>
+</enum>
+
+<enum name="UmaUploadResponseStatus" type="int">
+ <int value="0" label="Unknown failure"/>
+ <int value="1" label="Success"/>
+ <int value="2" label="Bad request"/>
+ <int value="3" label="No response"/>
+</enum>
+
+<enum name="UncacheableReason" type="int">
+ <int value="0" label="kNoData"/>
+ <int value="1" label="kPre11PartialResponse"/>
+ <int value="2" label="kNoStrongValidatorOnPartialResponse"/>
+ <int value="3" label="kShortMaxAge"/>
+ <int value="4" label="kExpiresTooSoon"/>
+ <int value="5" label="kHasMustRevalidate"/>
+ <int value="6" label="kNoCache"/>
+ <int value="7" label="kNoStore"/>
+</enum>
+
+<enum name="UniformityTrialGroupNotActive" type="int">
+ <int value="0" label="Invalid"/>
+ <int value="1" label="Group not reported"/>
+ <int value="2" label="Trial was disabled"/>
+ <int value="3" label="Group not reported and trial was disabled"/>
+</enum>
+
+<enum name="UpdateEngineDownloadSources" type="int">
+ <int value="0" label="Other"/>
+ <int value="1" label="HTTPS Server Only"/>
+ <int value="2" label="HTTP Server Only"/>
+ <int value="3" label="Both HTTP and HTTPS Server"/>
+</enum>
+
+<enum name="UpdateEngineErrorCode" type="int">
+ <int value="0" label="kErrorCodeSuccess"/>
+ <int value="1" label="kErrorCodeError"/>
+ <int value="2" label="kErrorCodeOmahaRequestError"/>
+ <int value="3" label="kErrorCodeOmahaResponseHandlerError"/>
+ <int value="4" label="kErrorCodeFilesystemCopierError"/>
+ <int value="5" label="kErrorCodePostinstallRunnerError"/>
+ <int value="6" label="kErrorCodeSetBootableFlagError"/>
+ <int value="7" label="kErrorCodeInstallDeviceOpenError"/>
+ <int value="8" label="kErrorCodeKernelDeviceOpenError"/>
+ <int value="9" label="kErrorCodeDownloadTransferError"/>
+ <int value="10" label="kErrorCodePayloadHashMismatchError"/>
+ <int value="11" label="kErrorCodePayloadSizeMismatchError"/>
+ <int value="12" label="kErrorCodeDownloadPayloadVerificationError"/>
+ <int value="13" label="kErrorCodeDownloadNewPartitionInfoError"/>
+ <int value="14" label="kErrorCodeDownloadWriteError"/>
+ <int value="15" label="kErrorCodeNewRootfsVerificationError"/>
+ <int value="16" label="kErrorCodeNewKernelVerificationError"/>
+ <int value="17" label="kErrorCodeSignedDeltaPayloadExpectedError"/>
+ <int value="18" label="kErrorCodeDownloadPayloadPubKeyVerificationError"/>
+ <int value="19" label="kErrorCodePostinstallBootedFromFirmwareB"/>
+ <int value="20" label="kErrorCodeDownloadStateInitializationError"/>
+ <int value="21" label="kErrorCodeDownloadInvalidMetadataMagicString"/>
+ <int value="22" label="kErrorCodeDownloadSignatureMissingInManifest"/>
+ <int value="23" label="kErrorCodeDownloadManifestParseError"/>
+ <int value="24" label="kErrorCodeDownloadMetadataSignatureError"/>
+ <int value="25" label="kErrorCodeDownloadMetadataSignatureVerificationError"/>
+ <int value="26" label="kErrorCodeDownloadMetadataSignatureMismatch"/>
+ <int value="27" label="kErrorCodeDownloadOperationHashVerificationError"/>
+ <int value="28" label="kErrorCodeDownloadOperationExecutionError"/>
+ <int value="29" label="kErrorCodeDownloadOperationHashMismatch"/>
+ <int value="30" label="kErrorCodeOmahaRequestEmptyResponseError"/>
+ <int value="31" label="kErrorCodeOmahaRequestXMLParseError"/>
+ <int value="32" label="kErrorCodeDownloadInvalidMetadataSize"/>
+ <int value="33" label="kErrorCodeDownloadInvalidMetadataSignature"/>
+ <int value="34" label="kErrorCodeOmahaRequestResponseInvalid"/>
+ <int value="35" label="kErrorCodeOmahaUpdateIgnoredPerPolicy"/>
+ <int value="36" label="kErrorCodeOmahaUpdateDeferredPerPolicy"/>
+ <int value="37" label="kErrorCodeOmahaErrorInHTTPResponse"/>
+ <int value="38" label="kErrorCodeDownloadOperationHashMissingError"/>
+ <int value="39" label="kErrorCodeDownloadMetadataSignatureMissingError"/>
+ <int value="40" label="kErrorCodeOmahaUpdateDeferredForBackoff"/>
+ <int value="41" label="kErrorCodePostinstallPowerwashError"/>
+ <int value="42" label="kErrorCodeUpdateCanceledByChannelChange"/>
+</enum>
+
+<enum name="UrlResolutionResult" type="int">
+ <int value="0" label="Absolute URL"/>
+ <int value="1" label="Resolutions Differ"/>
+ <int value="2" label="Resolutions Agree"/>
+</enum>
+
+<enum name="URLSchemeForHistogram" type="int">
+ <int value="0" label="kUnknownURLScheme"/>
+ <int value="1" label="kMissingURLScheme"/>
+ <int value="2" label="kHttpURLScheme"/>
+ <int value="3" label="kHttpsURLScheme"/>
+ <int value="4" label="kFtpURLScheme"/>
+ <int value="5" label="kChromeExtensionURLScheme"/>
+ <int value="6" label="kJavascriptURLScheme"/>
+ <int value="7" label="kFileURLScheme"/>
+ <int value="8" label="kBlobURLScheme"/>
+ <int value="9" label="kDataURLScheme"/>
+ <int value="10" label="kFileSystemScheme"/>
+</enum>
+
+<enum name="UserType" type="int">
+ <int value="0" label="Regular"/>
+ <int value="1" label="Guest"/>
+ <int value="2" label="Retail Mode"/>
+ <int value="3" label="Public Account"/>
+ <int value="4" label="Locally Managed"/>
+ <int value="5" label="Kiosk App"/>
+</enum>
+
+<enum name="VariationsResourceRequestsAllowedState" type="int">
+ <int value="0" label="Resource requests allowed"/>
+ <int value="1" label="Resource requests not allowed"/>
+ <int value="2" label="Notified that requests became allowed"/>
+</enum>
+
+<enum name="VariationsSeedEmpty" type="int">
+ <int value="0" label="Seed Not Empty"/>
+ <int value="1" label="Seed Empty"/>
+ <int value="2" label="Seed Corrupt"/>
+</enum>
+
+<enum name="VAVDAH264DecoderFailure" type="int">
+ <int value="0" label="FRAME_MBS_ONLY_FLAG_NOT_ONE"/>
+ <int value="1" label="GAPS_IN_FRAME_NUM"/>
+ <int value="2" label="MID_STREAM_RESOLUTION_CHANGE"/>
+ <int value="3" label="INTERLACED_STREAM"/>
+ <int value="4" label="VAAPI_ERROR"/>
+</enum>
+
+<enum name="VideoCodec" type="int">
+ <int value="0" label="kUnknownVideoCodec"/>
+ <int value="1" label="kCodecH264"/>
+ <int value="2" label="kCodecVC1"/>
+ <int value="3" label="kCodecMPEG2"/>
+ <int value="4" label="kCodecMPEG4"/>
+ <int value="5" label="kCodecTheora"/>
+ <int value="6" label="kCodecVP8"/>
+ <int value="7" label="kCodecVP9"/>
+</enum>
+
+<enum name="VideoCodecProfile" type="int">
+ <int value="0" label="H.264 Baseline"/>
+ <int value="1" label="H.264 Main"/>
+ <int value="2" label="H.264 Extended"/>
+ <int value="3" label="H.264 High"/>
+ <int value="4" label="H.264 High10"/>
+ <int value="5" label="H.264 High422"/>
+ <int value="6" label="H.264 High444"/>
+ <int value="7" label="H.264 ScalableBaseline"/>
+ <int value="8" label="H.264 ScalableHigh"/>
+ <int value="9" label="H.264 StereoHigh"/>
+ <int value="10" label="H.264 MultiviewHigh"/>
+ <int value="11" label="VP8"/>
+ <int value="12" label="VP9"/>
+</enum>
+
+<enum name="ViewFileType" type="int">
+ <int value="0" label="other"/>
+ <int value="1" label=".3ga"/>
+ <int value="2" label=".3gp"/>
+ <int value="3" label=".aac"/>
+ <int value="4" label=".alac"/>
+ <int value="5" label=".asf"/>
+ <int value="6" label=".avi"/>
+ <int value="7" label=".bmp"/>
+ <int value="8" label=".csv"/>
+ <int value="9" label=".doc"/>
+ <int value="10" label=".docx"/>
+ <int value="11" label=".flac"/>
+ <int value="12" label=".gif"/>
+ <int value="13" label=".jpeg"/>
+ <int value="14" label=".jpg"/>
+ <int value="15" label=".log"/>
+ <int value="16" label=".m3u"/>
+ <int value="17" label=".m3u8"/>
+ <int value="18" label=".m4a"/>
+ <int value="19" label=".m4v"/>
+ <int value="20" label=".mid"/>
+ <int value="21" label=".mkv"/>
+ <int value="22" label=".mov"/>
+ <int value="23" label=".mp3"/>
+ <int value="24" label=".mp4"/>
+ <int value="25" label=".mpg"/>
+ <int value="26" label=".odf"/>
+ <int value="27" label=".odp"/>
+ <int value="28" label=".ods"/>
+ <int value="29" label=".odt"/>
+ <int value="30" label=".oga"/>
+ <int value="31" label=".ogg"/>
+ <int value="32" label=".ogv"/>
+ <int value="33" label=".pdf"/>
+ <int value="34" label=".png"/>
+ <int value="35" label=".ppt"/>
+ <int value="36" label=".pptx"/>
+ <int value="37" label=".ra"/>
+ <int value="38" label=".ram"/>
+ <int value="39" label=".rar"/>
+ <int value="40" label=".rm"/>
+ <int value="41" label=".rtf"/>
+ <int value="42" label=".wav"/>
+ <int value="43" label=".webm"/>
+ <int value="44" label=".webp"/>
+ <int value="45" label=".wma"/>
+ <int value="46" label=".wmv"/>
+ <int value="47" label=".xls"/>
+ <int value="48" label=".xlsx"/>
+</enum>
+
+<enum name="VPNDriver" type="int">
+ <int value="0" label="OpenVPN"/>
+ <int value="1" label="L2TP/IPSec"/>
+</enum>
+
+<enum name="VPNRemoteAuthenticationType" type="int">
+ <int value="0" label="OpenVPN Default"/>
+ <int value="1" label="OpenVPN Certificate"/>
+ <int value="2" label="L2TP/IPSec Default"/>
+ <int value="3" label="L2TP/IPSec Certificate"/>
+ <int value="4" label="L2TP/IPSec PSK"/>
+</enum>
+
+<enum name="VPNUserAuthenticationType" type="int">
+ <int value="0" label="OpenVPN None"/>
+ <int value="1" label="OpenVPN Certificate"/>
+ <int value="2" label="OpenVPN Username/Password"/>
+ <int value="3" label="OpenVPN Username/Password/OTP"/>
+ <int value="4" label="L2TP/IPSec None"/>
+ <int value="5" label="L2TP/IPSec Certificate"/>
+ <int value="6" label="L2TP/IPSec Username/Password"/>
+</enum>
+
+<enum name="WalletErrors" type="int">
+ <int value="0" label="Baseline: Issued request"/>
+ <int value="1" label="Fatal error (deprecated)"/>
+ <int value="2" label="Malformed response"/>
+ <int value="3" label="Network error"/>
+ <int value="4" label="Bad request"/>
+ <int value="5" label="Internal error"/>
+ <int value="6" label="Invalid params"/>
+ <int value="7" label="Service unavailable"/>
+ <int value="8" label="Spending limit exceeded"/>
+ <int value="9" label="Unsupported API version"/>
+ <int value="10" label="Unknown error"/>
+ <int value="11" label="Unsupported merchant"/>
+ <int value="12" label="Unsupported buyer legal address"/>
+ <int value="13" label="Unverified know your customer status"/>
+</enum>
+
+<enum name="WalletRequiredActions" type="int">
+ <int value="0" label="Baseline: Issued request"/>
+ <int value="1" label="Unknown"/>
+ <int value="2" label="GAIA auth"/>
+ <int value="3" label="Passive GAIA auth"/>
+ <int value="4" label="Set up Wallet"/>
+ <int value="5" label="Accept ToS"/>
+ <int value="6" label="Update expiration date"/>
+ <int value="7" label="Upgrade min address"/>
+ <int value="8" label="Choose another instrument or address"/>
+ <int value="9" label="Verify CVV"/>
+ <int value="10" label="Invalid form field"/>
+ <int value="11" label="Require phone number"/>
+</enum>
+
+<enum name="WebHistoryStatus" type="int">
+ <int value="0" label="WEB_HISTORY_QUERY_FAILED">Failed</int>
+ <int value="1" label="WEB_HISTORY_QUERY_SUCCEEDED">Succeeded</int>
+ <int value="2" label="WEB_HISTORY_QUERY_TIMED_OUT">Timed out</int>
+</enum>
+
+<enum name="WebSocketHandshakeResult" type="int">
+ <int value="0" label="Incomplete"/>
+ <int value="1" label="Normal"/>
+ <int value="2" label="Failed"/>
+ <int value="3" label="Connected"/>
+</enum>
+
+<enum name="WebSocketPerMessageDeflateContextTakeOverMode" type="int">
+ <int value="0" label="DoNotTakeOverContext"/>
+ <int value="1" label="TakeOverContext"/>
+</enum>
+
+<enum name="WiFiApMode" type="int">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Managed"/>
+ <int value="2" label="AdHoc"/>
+</enum>
+
+<enum name="WiFiReasonCode" type="int">
+ <int value="0" label="kReasonReserved0"/>
+ <int value="1" label="kReasonCodeUnspecified"/>
+ <int value="2" label="kReasonCodePreviousAuthenticationInvalid"/>
+ <int value="3" label="kReasonCodeSenderHasLeft"/>
+ <int value="4" label="kReasonCodeInactivity"/>
+ <int value="5" label="kReasonCodeTooManySTAs"/>
+ <int value="6" label="kReasonCodeNonAuthenticated"/>
+ <int value="7" label="kReasonCodeNonAssociated"/>
+ <int value="8" label="kReasonCodeDisassociatedHasLeft"/>
+ <int value="9" label="kReasonCodeReassociationNotAuthenticated"/>
+ <int value="10" label="kReasonCodeUnacceptablePowerCapability"/>
+ <int value="11" label="kReasonCodeUnacceptableSupportedChannelInfo"/>
+ <int value="12" label="kReasonReserved12"/>
+ <int value="13" label="kReasonCodeInvalidInfoElement"/>
+ <int value="14" label="kReasonCodeMICFailure"/>
+ <int value="15" label="kReasonCode4WayTimeout"/>
+ <int value="16" label="kReasonCodeGroupKeyHandshakeTimeout"/>
+ <int value="17" label="kReasonCodeDifferenIE"/>
+ <int value="18" label="kReasonCodeGroupCipherInvalid"/>
+ <int value="19" label="kReasonCodePairwiseCipherInvalid"/>
+ <int value="20" label="kReasonCodeAkmpInvalid"/>
+ <int value="21" label="kReasonCodeUnsupportedRsnIeVersion"/>
+ <int value="22" label="kReasonCodeInvalidRsnIeCaps"/>
+ <int value="23" label="kReasonCode8021XAuth"/>
+ <int value="24" label="kReasonCodeCipherSuiteRejected"/>
+ <int value="25" label="kReasonReserved25"/>
+ <int value="26" label="kReasonReserved26"/>
+ <int value="27" label="kReasonReserved27"/>
+ <int value="28" label="kReasonReserved28"/>
+ <int value="29" label="kReasonReserved29"/>
+ <int value="30" label="kReasonReserved30"/>
+ <int value="31" label="kReasonReserved31"/>
+ <int value="32" label="kReasonCodeUnspecifiedQoS"/>
+ <int value="33" label="kReasonCodeQoSBandwidth"/>
+ <int value="34" label="kReasonCodeiPoorConditions"/>
+ <int value="35" label="kReasonCodeOutsideTxop"/>
+ <int value="36" label="kReasonCodeStaLeaving"/>
+ <int value="37" label="kReasonCodeUnacceptableMechanism"/>
+ <int value="38" label="kReasonCodeSetupRequired"/>
+ <int value="39" label="kReasonCodeTimeout"/>
+ <int value="45" label="kReasonCodeCipherSuiteNotSupported"/>
+</enum>
+
+<enum name="WiFiScanResult" type="int">
+ <int value="0" label="ProgressiveScan connected"/>
+ <int value="1" label="ProgressiveScan error then FullScan didn't connect"/>
+ <int value="2" label="ProgressiveScan error then FullScan connected"/>
+ <int value="3"
+ label="ProgressiveScan didn't connect then FullScan didn't connect"/>
+ <int value="4"
+ label="ProgressiveScan didn't connect then FullScan connected"/>
+ <int value="5" label="FullScan didn't connect"/>
+ <int value="6" label="FullScan connected"/>
+ <int value="7" label="Internal error"/>
+</enum>
+
+<enum name="WiFiStatusType" type="int">
+ <int value="0" label="kStatusCodeTypeByAp"/>
+ <int value="1" label="kStatusCodeTypeByClient"/>
+ <int value="2" label="kStatusCodeTypeByUser"/>
+ <int value="3" label="kStatusCodeTypeConsideredDead"/>
+</enum>
+
+<enum name="WindowsVersion" type="int">
+ <int value="0" label="Pre-XP"/>
+ <int value="1" label="XP"/>
+ <int value="2" label="2003 Server"/>
+ <int value="3" label="Vista"/>
+ <int value="4" label="Windows 7"/>
+ <int value="5" label="Windows 8"/>
+</enum>
+
+<enum name="XMLHttpRequestSendArrayBufferOrView" type="int">
+ <int value="0" label="XMLHttpRequestSendArrayBuffer"/>
+ <int value="1" label="XMLHttpRequestSendArrayBufferView"/>
+</enum>
+
+</enums>
+
+<!-- Field trials -->
+
+<fieldtrials>
+
+<fieldtrial name="AsyncSlowStart">
+ <group name="AsyncSlowStart" label="Async Slow Start on"/>
+ <group name="AsyncSlowStart_off" label="Async Slow Start off"/>
+ <group name="AsyncSlowStart_on" label="Async Slow Start on"/>
+ <affected-histogram name="Net.Transaction_Connected_New"/>
+ <affected-histogram name="Renderer4.StartToFinish"/>
+</fieldtrial>
+
+<fieldtrial name="AutofillServerExperiments">
+ <group name="ar06" label="Acceptance ratio: 0.6"/>
+ <group name="ar1" label="Acceptance ratio: 1.0"/>
+ <group name="ar2" label="Acceptance ratio: 2.0"/>
+ <group name="ar4" label="Acceptance ratio: 4.0"/>
+ <group name="ar04wr3fs4"
+ label="Acceptance ratio: 0.4; winner lead ratio: 3.0; min form score: 4"/>
+ <group name="ar05wlr15"
+ label="Acceptance ratio: 0.5; winner lead ratio: 1.5"/>
+ <group name="ar05wlr25"
+ label="Acceptance ratio: 0.5; winner lead ratio: 2.5"/>
+ <group name="ar05wr15fs5"
+ label="Acceptance ratio: 0.5; winner lead ratio: 1.5; min form score: 5"/>
+ <group name="fp05" label="Probability picker algorithm, p=0.5"/>
+ <group name="fp025" label="Probability picker algorithm, p=0.25"/>
+ <group name="fp05cc03"
+ label="Probability picker algorithm, p=0.5; p_ccname=0.3"/>
+ <group name="fp05cco03"
+ label="Probability picker algorithm, p=0.5;
+ p_ccname_given_other_cc_fields=0.3"/>
+ <group name="fp05cco03cstd"
+ label="Probability picker algorithm, p=0.5;
+ p_ccname_given_other_cc_fields=0.3; with fallback to the default
+ algorithm"/>
+ <group name="fp05cc03e1"
+ label="Probability picker algorithm, p=0.5 for cc and company name
+ fields; p_ccname_given_other_cc_fields=0.3; with fallback to the
+ default algorithm;"/>
+ <group name="tbar1" label="Use only Toolbar upload data"/>
+ <affected-histogram name="Autofill.Quality"/>
+ <affected-histogram name="AutoFill.Quality"/>
+ <affected-histogram name="Autofill.Quality.HeuristicType"/>
+ <affected-histogram name="Autofill.Quality.HeuristicType.ByFieldType"/>
+ <affected-histogram name="Autofill.Quality.PredictedType"/>
+ <affected-histogram name="Autofill.Quality.PredictedType.ByFieldType"/>
+ <affected-histogram name="Autofill.Quality.ServerType"/>
+ <affected-histogram name="Autofill.Quality.ServerType.ByFieldType"/>
+</fieldtrial>
+
+<fieldtrial name="CacheListSize">
+ <group name="CacheListSize_12" label="Control"/>
+ <group name="CacheListSize_13" label="Extended deleted list (2x)"/>
+ <group name="CacheListSize_14" label="Out of the experiment"/>
+ <affected-histogram name="DiskCache.TotalIOTime"/>
+ <affected-histogram name="Net.HttpJob.TotalTime"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeCached"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeCancel"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeNotCached"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeSuccess"/>
+ <affected-histogram name="PLT.Abandoned"/>
+ <affected-histogram name="PLT.BeginToFinish"/>
+ <affected-histogram name="PLT.BeginToFinish_HistoryLoad"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadCacheOnly"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadReload"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadStaleOk"/>
+ <affected-histogram name="PLT.BeginToFinish_NormalLoad"/>
+ <affected-histogram name="PLT.BeginToFinish_Reload"/>
+</fieldtrial>
+
+<fieldtrial name="CacheSensitivityAnalysis">
+ <group name="No" label="Turned off"/>
+ <group name="Control" label="Control group"/>
+ <group name="ControlA" label="Control, Group A"/>
+ <group name="ControlB" label="Control, Group B"/>
+ <group name="100" label="100% slowdown"/>
+ <group name="100A" label="100% slowdown, Group A"/>
+ <group name="100B" label="100% slowdown, Group B"/>
+ <group name="200A" label="200% slowdown, Group A"/>
+ <group name="200B" label="200% slowdown, Group B"/>
+ <group name="400A" label="400% slowdown, Group A"/>
+ <group name="400B" label="400% slowdown, Group B"/>
+ <affected-histogram name="Net.HttpJob.TotalTime"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeCached"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeCancel"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeNotCached"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeSuccess"/>
+ <affected-histogram name="PLT.BeginToFinish_CacheSensitivity"/>
+ <affected-histogram name="PLT.BeginToFinishDoc_CacheSensitivity"/>
+ <affected-histogram name="PLT.BeginToFirstPaint_CacheSensitivity"/>
+ <affected-histogram name="PLT.CommitToFirstPaint_CacheSensitivity"/>
+</fieldtrial>
+
+<fieldtrial name="CacheSensitivityHistograms">
+ <group name="CacheSensitivity" label="Cache Sensivitiy Analysis"/>
+ <affected-histogram name="PLT.BeginToFinish"/>
+ <affected-histogram name="PLT.BeginToFinishDoc"/>
+ <affected-histogram name="PLT.BeginToFirstPaint"/>
+ <affected-histogram name="PLT.CommitToFirstPaint"/>
+</fieldtrial>
+
+<fieldtrial name="CertificateTypeAlgorithms" separator=".">
+ <group name="DH" label="DH"/>
+ <group name="DSA" label="DSA"/>
+ <group name="ECDH" label="ECDH"/>
+ <group name="ECDSA" label="ECDSA"/>
+ <group name="RSA" label="RSA"/>
+ <group name="Unknown" label="SPKI unrecognized by cert library"/>
+ <group name="Unsupported" label="Un-histogrammed type - please fix"/>
+ <affected-histogram name="CertificateType.BR.Intermediate"/>
+ <affected-histogram name="CertificateType.BR.Leaf"/>
+ <affected-histogram name="CertificateType.BR.Root"/>
+ <affected-histogram name="CertificateType.NonBR.Intermediate"/>
+ <affected-histogram name="CertificateType.NonBR.Leaf"/>
+ <affected-histogram name="CertificateType.NonBR.Root"/>
+ <affected-histogram name="CertificateType2.BR.Intermediate"/>
+ <affected-histogram name="CertificateType2.BR.Leaf"/>
+ <affected-histogram name="CertificateType2.BR.Root"/>
+ <affected-histogram name="CertificateType2.NonBR.Intermediate"/>
+ <affected-histogram name="CertificateType2.NonBR.Leaf"/>
+ <affected-histogram name="CertificateType2.NonBR.Root"/>
+</fieldtrial>
+
+<fieldtrial name="CertificateTypeBRValidity" separator=".">
+ <obsolete>
+ Deprecated as of 8/2013. This histogram only considered the leaf certificate
+ expiry date as a proxy for whether a certificate was in-scope for the BRs,
+ but did not consider the issuance date. As some CAs have issued long-lived
+ certs prior to the BRs, this disproportionately reported those certs as
+ being subject to the BRs, but non-compliant, when in reality they're not
+ subject.
+ </obsolete>
+ <group name="BR"
+ label="The *leaf* certificate of the chain expires after 2013-12-31,
+ meaning that it should be in scope for the Baseline
+ Requirement's key size requirements"/>
+ <group name="NonBR"
+ label="The *leaf* certificate of the chain expires on or before
+ 2013-12-31"/>
+ <affected-histogram name="CertificateType"/>
+</fieldtrial>
+
+<fieldtrial name="CertificateTypeBRValidity2" separator=".">
+ <group name="BR"
+ label="The *leaf* certificate of the chain expires after 2013-12-31 and
+ was issued on or after 2012-07-01, as judged by the notBefore,
+ meaning that it should be in scope for the Baseline
+ Requirement's key size requirements"/>
+ <group name="NonBR"
+ label="The *leaf* certificate of the chain expires on or before
+ 2013-12-31 or was issued before 2012-07-01"/>
+ <affected-histogram name="CertificateType2"/>
+</fieldtrial>
+
+<fieldtrial name="CertificateTypeChainPosition" separator=".">
+ <group name="Intermediate" label="Intermediate's SPKI"/>
+ <group name="Leaf" label="Leaf's SPKI"/>
+ <group name="Root" label="Root's SPKI"/>
+ <affected-histogram name="CertificateType.BR"/>
+ <affected-histogram name="CertificateType.NonBR"/>
+ <affected-histogram name="CertificateType2.BR"/>
+ <affected-histogram name="CertificateType2.NonBR"/>
+</fieldtrial>
+
+<fieldtrial name="ConnCountImpact">
+ <group name="conn_count_16" label="with 16 persistent connections per host"/>
+ <group name="conn_count_4" label="with 4 persistent connections per host"/>
+ <group name="conn_count_5" label="with 5 persistent connections per host"/>
+ <group name="conn_count_6" label="with 6 persistent connections per host"/>
+ <group name="conn_count_7" label="with 7 persistent connections per host"/>
+ <group name="conn_count_8" label="with 8 persistent connections per host"/>
+ <group name="conn_count_9" label="with 9 persistent connections per host"/>
+ <affected-histogram name="Net.Transaction_Connected_New"/>
+ <affected-histogram name="PLT.Abandoned"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadReload"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadStaleOk"/>
+ <affected-histogram name="PLT.BeginToFinish_NormalLoad"/>
+ <affected-histogram name="Renderer4.Abandoned"/>
+ <affected-histogram name="Renderer4.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="Renderer4.BeginToFinish_LinkLoadReload"/>
+ <affected-histogram name="Renderer4.BeginToFinish_LinkLoadStaleOk"/>
+ <affected-histogram name="Renderer4.BeginToFinish_NormalLoad"/>
+</fieldtrial>
+
+<fieldtrial name="ConnnectBackupJobs">
+ <group name="ConnectBackupJobsEnabled"/>
+ <group name="ConnectBackupJobsDisabled"/>
+ <affected-histogram name="Net.PreconnectUtilization"/>
+ <affected-histogram name="Net.PreconnectUtilization2"/>
+ <affected-histogram name="PLT.Abandoned"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadReload"/>
+ <affected-histogram name="PLT.BeginToFinish_NormalLoad"/>
+ <affected-histogram name="PLT.LoadType"/>
+</fieldtrial>
+
+<fieldtrial name="DataReductionProxy">
+ <group name="DataReductionProxy"
+ label="Only page loads through the data reduction proxy are considered."/>
+ <affected-histogram name="PLT.NT_Connect"/>
+ <affected-histogram name="PLT.NT_DelayBeforeConnect"/>
+ <affected-histogram name="PLT.NT_DelayBeforeDomainLookup"/>
+ <affected-histogram name="PLT.NT_DelayBeforeDomLoading"/>
+ <affected-histogram name="PLT.NT_DelayBeforeFetch"/>
+ <affected-histogram name="PLT.NT_DelayBeforeFetchRedirect"/>
+ <affected-histogram name="PLT.NT_DelayBeforeLoadEvent"/>
+ <affected-histogram name="PLT.NT_DelayBeforeRequest"/>
+ <affected-histogram name="PLT.NT_DomainLookup"/>
+ <affected-histogram name="PLT.NT_DomContentLoaded"/>
+ <affected-histogram name="PLT.NT_DomInteractive"/>
+ <affected-histogram name="PLT.NT_DomLoading"/>
+ <affected-histogram name="PLT.NT_LoadEvent"/>
+ <affected-histogram name="PLT.NT_Redirect"/>
+ <affected-histogram name="PLT.NT_Request"/>
+ <affected-histogram name="PLT.NT_Response"/>
+</fieldtrial>
+
+<fieldtrial name="DefaultAppsExperiment">
+ <group name="NoDefaultApps" label="User's without default apps installed"/>
+ <group name="WithDefaultApps" label="User's with default apps installed"/>
+ <affected-histogram name="Extensions.AppTabLaunchType"/>
+ <affected-histogram name="Extensions.ExtensionInstalled"/>
+ <affected-histogram name="Extensions.ExtensionUninstalled"/>
+ <affected-histogram name="NewTabPage.DefaultPageType"/>
+ <affected-histogram name="NewTabPage.SelectedPageType"/>
+ <affected-histogram name="NtpHandler.AttachShownPageType"/>
+ <affected-histogram name="NtpHandler.SelectedShownPageType"/>
+ <affected-histogram name="Profile.AppCount"/>
+</fieldtrial>
+
+<fieldtrial name="DefaultPinnedApps">
+ <group name="Existing"/>
+ <group name="Control"/>
+ <group name="Alternate"/>
+ <affected-histogram name="Cros.ClickOnShelf"/>
+</fieldtrial>
+
+<fieldtrial name="DiskUsagePerUserCount" separator=".">
+ <group name="1User" label="Only 1 user exists on device."/>
+ <group name="2Users" label="2 users exist on device."/>
+ <group name="3Users" label="3 users exist on device."/>
+ <group name="4Users" label="4 users exist on device."/>
+ <group name="5Users" label="5 users exist on device."/>
+ <group name="6Users" label="6 users exist on device."/>
+ <group name="7OrMoreUsers" label="7 or more users exist on device."/>
+ <affected-histogram name="Platform.DiskUsage.Cache_Avg"/>
+ <affected-histogram name="Platform.DiskUsage.Cache_Max"/>
+ <affected-histogram name="Platform.DiskUsage.Downloads_Avg"/>
+ <affected-histogram name="Platform.DiskUsage.Downloads_Max"/>
+ <affected-histogram name="Platform.DiskUsage.GCache_Avg"/>
+ <affected-histogram name="Platform.DiskUsage.GCache_Max"/>
+</fieldtrial>
+
+<fieldtrial name="DnsImpact2">
+ <group name="disabled_prefetch"
+ label="DNS pre-resolving is disabled in these clients"/>
+ <group name="disabled_prefetch_4_connections"
+ label="DNS pre-resolving is disabled in these clients, and a maximum of
+ 4 connections per host was allowed"/>
+ <group name="enabled_prefetch_4_connections"
+ label="a maximum of 4 connections per host was allowed in these clients"/>
+ <group name="parallel_4_prefetch"
+ label="DNS pre-resolving was only doing 4 concurrent speculative
+ resolutions in this test"/>
+ <affected-histogram name="Net.Dns_Resolution_And_TCP_Connection_Latency"/>
+ <affected-histogram name="Net.TCP_Connection_Idle_Sockets">
+ <with-group name="disabled_prefetch"/>
+ <with-group name="disabled_prefetch_4_connections"/>
+ <with-group name="enabled_prefetch_4_connections"/>
+ </affected-histogram>
+ <affected-histogram name="Net.TCP_Connection_Latency"/>
+ <affected-histogram name="Net.Transaction_Connected"/>
+ <affected-histogram name="Net.Transaction_Connected_New"/>
+ <affected-histogram name="Net.Transaction_Connected_New_b"/>
+ <affected-histogram name="Net.Transaction_Connected_Under_10"/>
+ <affected-histogram name="Net.Transaction_Latency"/>
+ <affected-histogram name="Net.Transaction_Latency_b"/>
+ <affected-histogram name="Net.Transaction_Latency_Total"/>
+ <affected-histogram name="Net.Transaction_Latency_Total_New_Connection"/>
+ <affected-histogram
+ name="Net.Transaction_Latency_Total_New_Connection_Under_10"/>
+ <affected-histogram name="Net.Transaction_Latency_Total_Under_10"/>
+ <affected-histogram name="Net.Transaction_Latency_Under_10"/>
+ <affected-histogram name="PLT.RequestToFinish">
+ <with-group name="parallel_4_prefetch"/>
+ </affected-histogram>
+</fieldtrial>
+
+<fieldtrial name="DnsImpact3">
+ <group name="disabled_prefetch" label="with DNS pre-resolving disabled"/>
+ <group name="parallel_4_prefetch"
+ label="with only 4 concurrent speculative resolutions done in parallel"/>
+ <affected-histogram name="Net.Transaction_Connected_New">
+ <with-group name="disabled_prefetch"/>
+ </affected-histogram>
+ <affected-histogram name="Renderer2.FinishDocToFinish"/>
+ <affected-histogram name="Renderer2.RequestToFinish"/>
+ <affected-histogram name="Renderer2.RequestToFinish_L">
+ <with-group name="disabled_prefetch"/>
+ </affected-histogram>
+ <affected-histogram name="Renderer2.RequestToFirstLayout"/>
+ <affected-histogram name="Renderer2.RequestToStart"/>
+ <affected-histogram name="Renderer2.StartToFinish"/>
+ <affected-histogram name="Renderer2.StartToFinishDoc"/>
+ <affected-histogram name="Renderer2.StartToFirstLayout"/>
+ <affected-histogram name="Renderer4.RequestToFinish">
+ <with-group name="parallel_4_prefetch"/>
+ </affected-histogram>
+ <affected-histogram name="Renderer4.StartToFinish">
+ <with-group name="parallel_4_prefetch"/>
+ </affected-histogram>
+</fieldtrial>
+
+<fieldtrial name="DnsParallelism">
+ <group name="parallel_10"
+ label="with only 10 concurrent resolutions done in parallel"/>
+ <group name="parallel_14"
+ label="with only 14 concurrent resolutions done in parallel"/>
+ <group name="parallel_20"
+ label="with only 20 concurrent resolutions done in parallel"/>
+ <group name="parallel_6"
+ label="with only 6 concurrent resolutions done in parallel"/>
+ <group name="parallel_7"
+ label="with only 7 concurrent resolutions done in parallel"/>
+ <group name="parallel_8"
+ label="with only 8 concurrent resolutions done in parallel"/>
+ <group name="parallel_9"
+ label="with only 9 concurrent resolutions done in parallel"/>
+ <group name="parallel_default"
+ label="with the default number of concurrent resolutions done in
+ parallel"/>
+ <affected-histogram name="DNS.ResolveCategory"/>
+ <affected-histogram name="DNS.ResolveSuccess"/>
+</fieldtrial>
+
+<fieldtrial name="DomainGoogle" separator="">
+ <group name="Google" label="only Google cookies are recorded."/>
+ <group name="Other" label="only NON-Google cookies are recorded."/>
+ <affected-histogram name="Cookie.ReinstatedCookies"/>
+</fieldtrial>
+
+<fieldtrial name="ExternalExtensionEvent" separator="">
+ <group name="NonWebstore"
+ label="sideloaded extensions that don't update from the webstore"/>
+ <group name="Webstore"
+ label="sideloaded extensions that update from the webstore"/>
+ <affected-histogram name="Extensions.ExternalExtensionEvent"/>
+</fieldtrial>
+
+<fieldtrial name="FileBrowserLoad" separator=".">
+ <group name="Construct"
+ label="Time spent constructing the main Javascript object."/>
+ <group name="DOM" label="Time to initialize DOM."/>
+ <group name="FileSystem"
+ label="Time to get access to the local file system."/>
+ <group name="Parse" label="Time to parse Javascript and CSS."/>
+ <group name="Roots" label="Time to enumerate file system roots."/>
+ <group name="Total"
+ label="Total load time from the moment the Javascript started parsing
+ till the moment the empty file list is displayed."/>
+ <affected-histogram name="FileBrowser.Load"/>
+</fieldtrial>
+
+<fieldtrial name="HttpPipeliningCompatibility">
+ <group name="disable_test" label="Do nothing"/>
+ <group name="enable_test" label="Test connection for HTTP pipelining"/>
+ <affected-histogram name="NetConnectivity.Pipeline.0.NetworkError"/>
+ <affected-histogram name="NetConnectivity.Pipeline.0.ResponseCode"/>
+ <affected-histogram name="NetConnectivity.Pipeline.0.Status"/>
+ <affected-histogram name="NetConnectivity.Pipeline.1.NetworkError"/>
+ <affected-histogram name="NetConnectivity.Pipeline.1.ResponseCode"/>
+ <affected-histogram name="NetConnectivity.Pipeline.1.Status"/>
+ <affected-histogram name="NetConnectivity.Pipeline.2.NetworkError"/>
+ <affected-histogram name="NetConnectivity.Pipeline.2.ResponseCode"/>
+ <affected-histogram name="NetConnectivity.Pipeline.2.Status"/>
+ <affected-histogram name="NetConnectivity.Pipeline.3.NetworkError"/>
+ <affected-histogram name="NetConnectivity.Pipeline.3.ResponseCode"/>
+ <affected-histogram name="NetConnectivity.Pipeline.3.Status"/>
+ <affected-histogram name="NetConnectivity.Pipeline.4.NetworkError"/>
+ <affected-histogram name="NetConnectivity.Pipeline.4.ResponseCode"/>
+ <affected-histogram name="NetConnectivity.Pipeline.4.Status"/>
+ <affected-histogram name="NetConnectivity.Pipeline.5.NetworkError"/>
+ <affected-histogram name="NetConnectivity.Pipeline.5.ResponseCode"/>
+ <affected-histogram name="NetConnectivity.Pipeline.5.Status"/>
+ <affected-histogram name="NetConnectivity.Pipeline.AllHTTP11"/>
+ <affected-histogram name="NetConnectivity.Pipeline.CanarySuccess"/>
+ <affected-histogram name="NetConnectivity.Pipeline.Depth"/>
+ <affected-histogram name="NetConnectivity.Pipeline.Success"/>
+</fieldtrial>
+
+<fieldtrial name="IndexedDBLevelDBErrnoMethods" separator=".">
+ <group name="NewLogger" label="ChromiumEnv::NewLogger"/>
+ <group name="NewSequentialFile" label="ChromiumEnv::NewSequentialFile"/>
+ <group name="NewWritableFile" label="ChromiumEnv::NewWritableFile"/>
+ <group name="SequentialFileRead" label="ChromiumSequentialFile::Read"/>
+ <group name="SequentialFileSkip" label="ChromiumSequentialFile::Skip"/>
+ <group name="WritableFileAppend" label="ChromiumWritableFile::Append"/>
+ <group name="WritableFileClose" label="ChromiumWritableFile::Close"/>
+ <group name="WritableFileFlush" label="ChromiumWritableFile::Flush"/>
+ <group name="WritableFileSync" label="ChromiumWritableFile::Sync"/>
+ <group name="WritableFileSyncParent"
+ label="ChromiumWritableFile::SyncParent"/>
+ <affected-histogram name="WebCore.IndexedDB.LevelDBOpenErrors.Errno"/>
+ <affected-histogram name="WebCore.IndexedDB.LevelDBReadErrors.Errno"/>
+ <affected-histogram name="WebCore.IndexedDB.LevelDBWriteErrors.Errno"/>
+</fieldtrial>
+
+<fieldtrial name="IndexedDBLevelDBPFEMethods" separator=".">
+ <group name="CreateDir" label="ChromiumEnv::CreateDir"/>
+ <group name="DeleteDir" label="ChromiumEnv::DeleteDir"/>
+ <group name="DeleteFile" label="ChromiumEnv::DeleteFile"/>
+ <group name="GetFileSize" label="ChromiumEnv::GetFileSize"/>
+ <group name="LockFile" label="ChromiumEnv::LockFile"/>
+ <group name="NewRandomAccessFile" label="ChromiumEnv::NewRandomAccessFile"/>
+ <group name="RandomAccessFileRead" label="ChromiumRandomAccessFile::Read"/>
+ <group name="RenameFile" label="ChromiumEnv::RenameFile"/>
+ <group name="UnlockFile" label="ChromiumEnv::UnlockFile"/>
+ <affected-histogram name="WebCore.IndexedDB.LevelDBOpenErrors.PFE"/>
+ <affected-histogram name="WebCore.IndexedDB.LevelDBReadErrors.PFE"/>
+ <affected-histogram name="WebCore.IndexedDB.LevelDBWriteErrors.PFE"/>
+</fieldtrial>
+
+<fieldtrial name="InstallerDownloadSources" separator="">
+ <group name="HttpServer" label="Download Source: HTTP Server"/>
+ <group name="HttpsServer" label="Download Source: HTTPS Server"/>
+ <affected-histogram name="Installer.SuccessfulMBsDownloadedFrom"/>
+ <affected-histogram name="Installer.TotalMBsDownloadedFrom"/>
+</fieldtrial>
+
+<fieldtrial name="Instant">
+ <group name="Extended" label="Suggestions + Results"/>
+ <group name="Instant" label="Results"/>
+ <affected-histogram name="Instant.SessionsStorageNamespace"/>
+</fieldtrial>
+
+<fieldtrial name="IPv6_Probe">
+ <group name="IPv6_probe_skipped"
+ label="with IPv6 not probed, and default OS settings used"/>
+ <group name="IPv6_probe_done"
+ label="with IPv6 probed for and possibly disabled"/>
+ <affected-histogram name="DNS.PrefetchResolution"/>
+</fieldtrial>
+
+<fieldtrial name="LateBindingExperiment">
+ <group name="disable_late_binding" label="socket late binding is disabled"/>
+ <group name="enable_late_binding" label="socket late binding is enabled"/>
+ <affected-histogram name="Net.SocketIdleTimeBeforeNextUse_ReusedSocket"/>
+ <affected-histogram name="Net.SocketIdleTimeBeforeNextUse_UnusedSocket"/>
+ <affected-histogram name="Net.SocketIdleTimeOnIOError2_ReusedSocket"/>
+ <affected-histogram name="Net.SocketIdleTimeOnIOError2_UnusedSocket"/>
+ <affected-histogram name="Net.TCPSocketType"/>
+ <affected-histogram name="Net.Transaction_Connected"/>
+ <affected-histogram name="Net.Transaction_Connected_Under_10"/>
+ <affected-histogram name="Net.TransportSocketRequestTime"/>
+ <affected-histogram name="Renderer4.BeginToFinish_LinkLoad"/>
+ <affected-histogram name="Renderer4.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="Renderer4.BeginToFinish_LinkLoadReload"/>
+ <affected-histogram name="Renderer4.BeginToFinish_NormalLoad"/>
+ <affected-histogram name="Renderer4.BeginToFinishDoc_LinkLoad"/>
+ <affected-histogram name="Renderer4.BeginToFinishDoc_LinkLoadNormal"/>
+ <affected-histogram name="Renderer4.BeginToFinishDoc_LinkLoadReload"/>
+ <affected-histogram name="Renderer4.BeginToFinishDoc_NormalLoad"/>
+ <affected-histogram name="Renderer4.RequestToFinish"/>
+ <affected-histogram name="Renderer4.StartToFinish"/>
+</fieldtrial>
+
+<fieldtrial name="LevelDBEnvMaxFDs" separator=".">
+ <group name="Success"
+ label="This histogram shows the limit when open succeeded."/>
+ <group name="TooManyOpened"
+ label="This histogram shows the limit when open failed because the
+ limit had been reached."/>
+ <group name="OtherError"
+ label="This histogram shows the limit when open failed for reasons
+ other than exceeding the limit."/>
+ <affected-histogram name="LevelDBEnv.IDB.MaxFDs"/>
+ <affected-histogram name="LevelDBEnv.MaxFDs"/>
+</fieldtrial>
+
+<fieldtrial name="LevelDBEnvPlatformFileErrors" separator="">
+ <group name="CreateDir" label="ChromiumEnv::CreateDir"/>
+ <group name="LockFile" label="ChromiumEnv::LockFile"/>
+ <group name="NewRandomAccessFile" label="ChromiumEnv::NewRandomAccessFile"/>
+ <group name="RenameFile" label="ChromiumEnv::RenameFile"/>
+ <affected-histogram name="LevelDBEnv.IDB.IOError."/>
+ <affected-histogram name="LevelDBEnv.IOError."/>
+</fieldtrial>
+
+<fieldtrial name="LevelDBEnvRetry" separator="">
+ <group name="RenameFile" label="RenameFile"/>
+ <group name="LockFile" label="LockFile"/>
+ <group name="CreateDir" label="CreateDir"/>
+ <affected-histogram name="LevelDBEnv.IDB.RetryRecoveredFromErrorIn"/>
+ <affected-histogram name="LevelDBEnv.IDB.TimeUntilSuccessFor"/>
+ <affected-histogram name="LevelDBEnv.RetryRecoveredFromErrorIn"/>
+ <affected-histogram name="LevelDBEnv.TimeUntilSuccessFor"/>
+</fieldtrial>
+
+<fieldtrial name="LevelDBEnvRetryTimes" separator="">
+ <obsolete>
+ Deprecated 2013-04 in favor of LevelDBEnvRetry.
+ </obsolete>
+ <group name="Rename" label="RenameFile"/>
+ <group name="LockFile" label="LockFile"/>
+ <affected-histogram name="LevelDBEnv.IDB.TimeTo"/>
+ <affected-histogram name="LevelDBEnv.TimeTo"/>
+</fieldtrial>
+
+<fieldtrial name="MediaAudioInputControllerTime" separator=".">
+ <group name="CloseTime" label="Measures the time taken for DoClose()."/>
+ <group name="CreateTime" label="Measures the time taken for DoCreate()."/>
+ <group name="RecordTime" label="Measures the time taken for DoRecord()."/>
+ <affected-histogram name="Media.AudioInputController"/>
+</fieldtrial>
+
+<fieldtrial name="MediaAudioInputDeviceManagerTime" separator=".">
+ <group name="OpenOnDeviceThreadTime"
+ label="Measures the time taken for OpenOnDeviceThread()."/>
+ <group name="EnumerateOnDeviceThreadTime"
+ label="Measures the time taken for EnumerateOnDeviceThread()."/>
+ <affected-histogram name="Media.AudioInputDeviceManager"/>
+</fieldtrial>
+
+<fieldtrial name="MediaAudioOutputControllerTime" separator=".">
+ <group name="CloseTime" label="Measures the time taken for DoClose()."/>
+ <group name="CreateTime" label="Measures the time taken for DoCreate()."/>
+ <group name="DeviceChangeTime"
+ label="Measures the time taken for OnDeviceChange()."/>
+ <group name="PauseTime" label="Measures the time taken for DoPause()."/>
+ <group name="PlayTime"
+ label="Measures the time taken for DoPlay(). Technically only the
+ worker method AudioOutputController::PollAndStartIfDataReady()."/>
+ <affected-histogram name="Media.AudioOutputController"/>
+</fieldtrial>
+
+<fieldtrial name="MediaVideoCaptureManagerTime" separator=".">
+ <group name="OnEnumerateDevicesTime"
+ label="Measures the time taken for OnEnumerateDevices()."/>
+ <group name="OnOpenTime" label="Measures the time taken for OnOpen()."/>
+ <group name="OnCloseTime" label="Measures the time taken for OnClose()."/>
+ <group name="OnStartTime" label="Measures the time taken for OnStart()."/>
+ <group name="OnStopTime" label="Measures the time taken for OnStop()."/>
+ <affected-histogram name="Media.VideoCaptureManager"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity" separator=".">
+ <group name="53.100B" label="100 bytes of data on port 53."/>
+ <group name="53.100B.NoProxy"
+ label="100 bytes of data on port 53 with no proxy."/>
+ <group name="53.1K" label="1K bytes of data on port 53."/>
+ <group name="53.1K.NoProxy"
+ label="1K bytes of data on port 53 with no proxy."/>
+ <group name="53.100B.RTT" label="100 bytes of data on port 53 successfully."/>
+ <group name="53.100B.RTT.NoProxy"
+ label="100 bytes of data on port 53 successfully with no proxy."/>
+ <group name="53.1K.RTT" label="1K bytes of data on port 53 successfully."/>
+ <group name="53.1K.RTT.NoProxy"
+ label="1K bytes of data on port 53 successfully with no proxy."/>
+ <group name="587.100B" label="100 bytes of data on port 587."/>
+ <group name="587.100B.NoProxy"
+ label="100 bytes of data on port 587 with no proxy."/>
+ <group name="587.1K" label="1K bytes of data on port 587."/>
+ <group name="587.1K.NoProxy"
+ label="1K bytes of data on port 587 with no proxy."/>
+ <group name="587.100B.RTT"
+ label="100 bytes of data on port 587 successfully."/>
+ <group name="587.100B.RTT.NoProxy"
+ label="100 bytes of data on port 587 successfully with no proxy."/>
+ <group name="587.1K.RTT" label="1K bytes of data on port 587 successfully."/>
+ <group name="587.1K.RTT.NoProxy"
+ label="1K bytes of data on port 587 successfully with no proxy."/>
+ <group name="6121.100B" label="100 bytes of data on port 6121."/>
+ <group name="6121.100B.NoProxy"
+ label="100 bytes of data on port 6121 with no proxy."/>
+ <group name="6121.1K" label="1K bytes of data on port 6121."/>
+ <group name="6121.1K.NoProxy"
+ label="1K bytes of data on port 6121 with no proxy."/>
+ <group name="6121.100B.RTT"
+ label="100 bytes of data on port 6121 successfully."/>
+ <group name="6121.100B.RTT.NoProxy"
+ label="100 bytes of data on port 6121 successfully with no proxy."/>
+ <group name="6121.1K.RTT"
+ label="1K bytes of data on port 6121 successfully."/>
+ <group name="6121.1K.RTT.NoProxy"
+ label="1K bytes of data on port 6121 successfully with no proxy."/>
+ <group name="80.100B" label="100 bytes of data on port 80."/>
+ <group name="80.100B.NoProxy"
+ label="100 bytes of data on port 80 with no proxy."/>
+ <group name="80.1K" label="1K bytes of data on port 80."/>
+ <group name="80.1K.NoProxy"
+ label="1K bytes of data on port 80 with no proxy."/>
+ <group name="80.100B.RTT" label="100 bytes of data on port 80 successfully."/>
+ <group name="80.100B.RTT.NoProxy"
+ label="100 bytes of data on port 80 successfully with no proxy."/>
+ <group name="80.1K.RTT" label="1K bytes of data on port 80 successfully."/>
+ <group name="80.1K.RTT.NoProxy"
+ label="1K bytes of data on port 80 successfully with no proxy."/>
+ <group name="8080.100B" label="100 bytes of data on port 8080."/>
+ <group name="8080.100B.NoProxy"
+ label="100 bytes of data on port 8080 with no proxy."/>
+ <group name="8080.1K" label="1K bytes of data on port 8080."/>
+ <group name="8080.1K.NoProxy"
+ label="1K bytes of data on port 8080 with no proxy."/>
+ <group name="8080.100B.RTT"
+ label="100 bytes of data on port 8080 successfully."/>
+ <group name="8080.100B.RTT.NoProxy"
+ label="100 bytes of data on port 8080 successfully with no proxy."/>
+ <group name="8080.1K.RTT"
+ label="1K bytes of data on port 8080 successfully."/>
+ <group name="8080.1K.RTT.NoProxy"
+ label="1K bytes of data on port 8080 successfully with no proxy."/>
+ <affected-histogram name="NetConnectivity.TCP.Status"/>
+ <affected-histogram name="NetConnectivity.TCP.Success"/>
+ <affected-histogram name="NetConnectivity.UDP.PacketLoss"/>
+ <affected-histogram name="NetConnectivity.UDP.PacketLoss6"/>
+ <affected-histogram name="NetConnectivity.UDP.Status"/>
+ <affected-histogram name="NetConnectivity.UDP.Success"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity2" separator=".">
+ <group name="AcksReceivedFromFirst2Packets" label="2 packets."/>
+ <group name="AcksReceivedFromFirst3Packets" label="3 packets."/>
+ <group name="AcksReceivedFromFirst4Packets" label="4 packets."/>
+ <group name="AcksReceivedFromFirst5Packets" label="5 packets."/>
+ <group name="AcksReceivedFromFirst6Packets" label="6 packets."/>
+ <group name="AcksReceivedFromFirst7Packets" label="7 packets."/>
+ <group name="AcksReceivedFromFirst8Packets" label="8 packets."/>
+ <group name="AcksReceivedFromFirst9Packets" label="9 packets."/>
+ <group name="AcksReceivedFromFirst10Packets" label="10 packets."/>
+ <group name="AcksReceivedFromFirst11Packets" label="11 packets."/>
+ <group name="AcksReceivedFromFirst12Packets" label="12 packets."/>
+ <group name="AcksReceivedFromFirst13Packets" label="13 packets."/>
+ <group name="AcksReceivedFromFirst14Packets" label="14 packets."/>
+ <group name="AcksReceivedFromFirst15Packets" label="15 packets."/>
+ <group name="AcksReceivedFromFirst16Packets" label="16 packets."/>
+ <group name="AcksReceivedFromFirst17Packets" label="17 packets."/>
+ <group name="AcksReceivedFromFirst18Packets" label="18 packets."/>
+ <group name="AcksReceivedFromFirst19Packets" label="19 packets."/>
+ <group name="AcksReceivedFromFirst20Packets" label="20 packets."/>
+ <group name="AcksReceivedFromFirst21Packets" label="21 packets."/>
+ <affected-histogram name="NetConnectivity.Sent21"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity2a" separator=".">
+ <group name="6121.100B" label="100 bytes of data is sent on port 6121."/>
+ <group name="6121.500B" label="500 bytes of data is sent on port 6121."/>
+ <group name="6121.1K" label="1K bytes of data is sent on port 6121."/>
+ <affected-histogram name="NetConnectivity2.Sent21.AckReceivedForNthPacket"/>
+ <affected-histogram name="NetConnectivity2.Sent21.GotAnAck"/>
+ <affected-histogram name="NetConnectivity2.Sent21.PacketsSent"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity2b" separator=".">
+ <group name="AcksReceivedFromFirst2Packets.6121.100B"
+ label="2 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst3Packets.6121.100B"
+ label="3 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst4Packets.6121.100B"
+ label="4 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst5Packets.6121.100B"
+ label="5 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst6Packets.6121.100B"
+ label="6 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst7Packets.6121.100B"
+ label="7 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst8Packets.6121.100B"
+ label="8 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst9Packets.6121.100B"
+ label="9 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst10Packets.6121.100B"
+ label="10 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst11Packets.6121.100B"
+ label="11 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst12Packets.6121.100B"
+ label="12 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst13Packets.6121.100B"
+ label="13 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst14Packets.6121.100B"
+ label="14 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst15Packets.6121.100B"
+ label="15 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst16Packets.6121.100B"
+ label="16 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst17Packets.6121.100B"
+ label="17 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst18Packets.6121.100B"
+ label="18 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst19Packets.6121.100B"
+ label="19 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst20Packets.6121.100B"
+ label="20 packets. 100 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst21Packets.6121.100B"
+ label="21 packets. 100 bytes of data is sent on port 6121."/>
+ <affected-histogram name="NetConnectivity2.Sent21"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity2c" separator=".">
+ <group name="6121.100B" label="100 bytes of data is sent on port 6121."/>
+ <group name="6121.100B.NoProxy"
+ label="100 bytes of data is sent on port 6121 with no proxy."/>
+ <group name="6121.500B" label="500 bytes of data is sent on port 6121."/>
+ <group name="6121.500B.NoProxy"
+ label="500 bytes of data is sent on port 6121 with no proxy."/>
+ <group name="6121.1K" label="1K bytes of data is sent on port 6121."/>
+ <group name="6121.1K.NoProxy"
+ label="1K bytes of data is sent on port 6121 with no proxy."/>
+ <affected-histogram name="NetConnectivity2.Send6.PacketsSent"/>
+ <affected-histogram name="NetConnectivity2.Send6.SeriesAcked"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity2d" separator=".">
+ <group name="AcksReceivedFromFirst2Packets.6121.500B"
+ label="2 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst3Packets.6121.500B"
+ label="3 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst4Packets.6121.500B"
+ label="4 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst5Packets.6121.500B"
+ label="5 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst6Packets.6121.500B"
+ label="6 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst7Packets.6121.500B"
+ label="7 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst8Packets.6121.500B"
+ label="8 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst9Packets.6121.500B"
+ label="9 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst10Packets.6121.500B"
+ label="10 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst11Packets.6121.500B"
+ label="11 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst12Packets.6121.500B"
+ label="12 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst13Packets.6121.500B"
+ label="13 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst14Packets.6121.500B"
+ label="14 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst15Packets.6121.500B"
+ label="15 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst16Packets.6121.500B"
+ label="16 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst17Packets.6121.500B"
+ label="17 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst18Packets.6121.500B"
+ label="18 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst19Packets.6121.500B"
+ label="19 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst20Packets.6121.500B"
+ label="20 packets. 500 bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst21Packets.6121.500B"
+ label="21 packets. 500 bytes of data is sent on port 6121."/>
+ <affected-histogram name="NetConnectivity2.Sent21"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity2e" separator=".">
+ <group name="AcksReceivedFromFirst2Packets.6121.1K"
+ label="2 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst3Packets.6121.1K"
+ label="3 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst4Packets.6121.1K"
+ label="4 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst5Packets.6121.1K"
+ label="5 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst6Packets.6121.1K"
+ label="6 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst7Packets.6121.1K"
+ label="7 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst8Packets.6121.1K"
+ label="8 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst9Packets.6121.1K"
+ label="9 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst10Packets.6121.1K"
+ label="10 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst11Packets.6121.1K"
+ label="11 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst12Packets.6121.1K"
+ label="12 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst13Packets.6121.1K"
+ label="13 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst14Packets.6121.1K"
+ label="14 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst15Packets.6121.1K"
+ label="15 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst16Packets.6121.1K"
+ label="16 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst17Packets.6121.1K"
+ label="17 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst18Packets.6121.1K"
+ label="18 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst19Packets.6121.1K"
+ label="19 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst20Packets.6121.1K"
+ label="20 packets. 1K bytes of data is sent on port 6121."/>
+ <group name="AcksReceivedFromFirst21Packets.6121.1K"
+ label="21 packets. 1K bytes of data is sent on port 6121."/>
+ <affected-histogram name="NetConnectivity2.Sent21"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3a" separator=".">
+ <group name="NonPacedPacket"
+ label="In this histogram results are only shown if at least two packets
+ were ACKed in the Startup Test. Packets were sent as rapidly as
+ possible."/>
+ <group name="PacedPacket"
+ label="In this histogram results are only shown if at least two packets
+ were ACKed in the Startup Test. Packets are sent at equal
+ intervals. The interval is selected to match the bandwidth
+ discovered during the StartPacket test."/>
+ <group name="StartPacket"
+ label="Packets are sent as rapidly as possible, just after successfully
+ sending an UMA upload. Each packet was numbered, as was its ACK
+ sent back by Google. If no packets (of the 21) were ever ACKed,
+ then the port is assumed to be blocked, and no data is recorded
+ in this histogram."/>
+ <affected-histogram name="NetConnectivity3"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3aa" separator=".">
+ <group name="Sent21"
+ label="This histogram shows the number of echo responses received from
+ the first"/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket"/>
+ <affected-histogram name="NetConnectivity3.StartPacket"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3AckReceivedForNthPacket" separator=".">
+ <group name="Sent21.AckReceivedForNthPacket"
+ label="Each packet was numbered, as was its ACK sent back by Google.
+ This histogram records, for each packet number, how often we
+ received an ACK for that packet."/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket"/>
+ <affected-histogram name="NetConnectivity3.StartPacket"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3AcksReceivedFromFirst" separator=".">
+ <group name="AcksReceivedFromFirst02Packets" label="2 packets."/>
+ <group name="AcksReceivedFromFirst03Packets" label="3 packets."/>
+ <group name="AcksReceivedFromFirst04Packets" label="4 packets."/>
+ <group name="AcksReceivedFromFirst05Packets" label="5 packets."/>
+ <group name="AcksReceivedFromFirst06Packets" label="6 packets."/>
+ <group name="AcksReceivedFromFirst07Packets" label="7 packets."/>
+ <group name="AcksReceivedFromFirst08Packets" label="8 packets."/>
+ <group name="AcksReceivedFromFirst09Packets" label="9 packets."/>
+ <group name="AcksReceivedFromFirst10Packets" label="10 packets."/>
+ <group name="AcksReceivedFromFirst11Packets" label="11 packets."/>
+ <group name="AcksReceivedFromFirst12Packets" label="12 packets."/>
+ <group name="AcksReceivedFromFirst13Packets" label="13 packets."/>
+ <group name="AcksReceivedFromFirst14Packets" label="14 packets."/>
+ <group name="AcksReceivedFromFirst15Packets" label="15 packets."/>
+ <group name="AcksReceivedFromFirst16Packets" label="16 packets."/>
+ <group name="AcksReceivedFromFirst17Packets" label="17 packets."/>
+ <group name="AcksReceivedFromFirst18Packets" label="18 packets."/>
+ <group name="AcksReceivedFromFirst19Packets" label="19 packets."/>
+ <group name="AcksReceivedFromFirst20Packets" label="20 packets."/>
+ <group name="AcksReceivedFromFirst21Packets" label="21 packets."/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket.Sent21"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket.Sent21"/>
+ <affected-histogram name="NetConnectivity3.StartPacket.Sent21"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3GotAnAck" separator=".">
+ <group name="Sent21.GotAnAck"
+ label="The histogram shows if we ever got an ACK for a packet in our
+ series of 21."/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket"/>
+ <affected-histogram name="NetConnectivity3.StartPacket"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3PacketDelay1" separator=".">
+ <group name="Sent21.443"
+ label="This histogram shows the difference between the time when we
+ have received 1st byte from the server and the last time when we
+ have received data from the server on port 443."/>
+ <group name="Sent21.6121"
+ label="This histogram shows the difference between the time when we
+ have received 1st byte from the server and the last time when we
+ have received data from the server on port 6121."/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket"/>
+ <affected-histogram name="NetConnectivity3.StartPacket"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3PacketDelay2" separator=".">
+ <group name="443.100B.PacketDelay"
+ label="100 bytes of data is sent on port 443."/>
+ <group name="443.1200B.PacketDelay"
+ label="1200 bytes of data is sent on port 443."/>
+ <group name="443.500B.PacketDelay"
+ label="500 bytes of data is sent on port 443."/>
+ <group name="6121.100B.PacketDelay"
+ label="100 bytes of data is sent on port 6121."/>
+ <group name="6121.1200B.PacketDelay"
+ label="1200 bytes of data is sent on port 6121."/>
+ <group name="6121.500B.PacketDelay"
+ label="500 bytes of data is sent on port 6121."/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket.Sent21"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket.Sent21"/>
+ <affected-histogram name="NetConnectivity3.StartPacket.Sent21"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3PacketRTT" separator=".">
+ <group name="Sent21.Success.RTT" label="The histogram shows the RTT for"/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket"/>
+ <affected-histogram name="NetConnectivity3.StartPacket"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3Packets" separator=".">
+ <group name="Packet01" label="1st packet."/>
+ <group name="Packet02" label="2nd packet."/>
+ <group name="Packet03" label="3rd packet."/>
+ <group name="Packet10" label="10th packet."/>
+ <group name="Packet20" label="20th packet."/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.Success.RTT"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket.Sent21.Success.RTT"/>
+ <affected-histogram name="NetConnectivity3.StartPacket.Sent21.Success.RTT"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3PacketsSent" separator=".">
+ <group name="Sent21.PacketsSent"
+ label="This histogram records how many packets (out of 21 attempted)
+ were sent to the server via UDP."/>
+ <group name="Send6.SeriesAcked"
+ label="Chrome sends 6 UDP packets in a row to test to see if there is a
+ probabalistic dependency in packet loss for consecutive packets.
+ We record a bit vector of packets received, where the least
+ significant bit is a 1 if the first packet was received, etc.
+ For example, if all packets other than packet 2 and 4 are
+ responded to, then we'd have a sample (in binary) of 110101B, or
+ 53."/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket"/>
+ <affected-histogram name="NetConnectivity3.StartPacket"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3PacketsSentBytes" separator=".">
+ <group name="443.100B" label="100 bytes of data is sent on port 443."/>
+ <group name="443.500B" label="500 bytes of data is sent on port 443."/>
+ <group name="443.1200B" label="1200 bytes of data is sent on port 443."/>
+ <group name="6121.100B" label="100 bytes of data is sent on port 6121."/>
+ <group name="6121.500B" label="500 bytes of data is sent on port 6121."/>
+ <group name="6121.1200B" label="1200 bytes of data is sent on port 6121."/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AckReceivedForNthPacket"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst02Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst03Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst04Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst05Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst06Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst07Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst08Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst09Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst10Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst11Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst12Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst13Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst14Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst15Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst16Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst17Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst18Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst19Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst20Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.AcksReceivedFromFirst21Packets"/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket.Sent21.GotAnAck"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.PacketsSent"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.Success.RTT.Packet01"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.Success.RTT.Packet02"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.Success.RTT.Packet03"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.Success.RTT.Packet10"/>
+ <affected-histogram
+ name="NetConnectivity3.NonPacedPacket.Sent21.Success.RTT.Packet20"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AckReceivedForNthPacket"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst02Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst03Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst04Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst05Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst06Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst07Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst08Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst09Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst10Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst11Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst12Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst13Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst14Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst15Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst16Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst17Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst18Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst19Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst20Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.AcksReceivedFromFirst21Packets"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket.Sent21.GotAnAck"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket.Sent21.PacketsSent"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.Success.RTT.Packet01"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.Success.RTT.Packet02"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.Success.RTT.Packet03"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.Success.RTT.Packet10"/>
+ <affected-histogram
+ name="NetConnectivity3.PacedPacket.Sent21.Success.RTT.Packet20"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AckReceivedForNthPacket"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst02Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst03Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst04Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst05Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst06Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst07Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst08Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst09Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst10Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst11Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst12Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst13Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst14Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst15Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst16Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst17Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst18Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst19Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst20Packets"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.AcksReceivedFromFirst21Packets"/>
+ <affected-histogram name="NetConnectivity3.StartPacket.Sent21.GotAnAck"/>
+ <affected-histogram name="NetConnectivity3.StartPacket.Sent21.PacketsSent"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.Success.RTT.Packet01"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.Success.RTT.Packet02"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.Success.RTT.Packet03"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.Success.RTT.Packet10"/>
+ <affected-histogram
+ name="NetConnectivity3.StartPacket.Sent21.Success.RTT.Packet20"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity3Send6Acked" separator=".">
+ <group name="443.100B" label="100 bytes of data is sent on port 443."/>
+ <group name="443.100B.NoProxy"
+ label="100 bytes of data is sent on port 443 with no proxy."/>
+ <group name="443.500B" label="500 bytes of data is sent on port 443."/>
+ <group name="443.500B.NoProxy"
+ label="500 bytes of data is sent on port 443 with no proxy."/>
+ <group name="443.1200B" label="1200 bytes of data is sent on port 443."/>
+ <group name="443.1200B.NoProxy"
+ label="1200 bytes of data is sent on port 443 with no proxy."/>
+ <group name="6121.100B" label="100 bytes of data is sent on port 6121."/>
+ <group name="6121.100B.NoProxy"
+ label="100 bytes of data is sent on port 6121 with no proxy."/>
+ <group name="6121.500B" label="500 bytes of data is sent on port 6121."/>
+ <group name="6121.500B.NoProxy"
+ label="500 bytes of data is sent on port 6121 with no proxy."/>
+ <group name="6121.1200B" label="1200 bytes of data is sent on port 6121."/>
+ <group name="6121.1200B.NoProxy"
+ label="1200 bytes of data is sent on port 6121 with no proxy."/>
+ <affected-histogram name="NetConnectivity3.NonPacedPacket.Send6.SeriesAcked"/>
+ <affected-histogram name="NetConnectivity3.PacedPacket.Send6.SeriesAcked"/>
+ <affected-histogram name="NetConnectivity3.StartPacket.Send6.PacketsSent"/>
+ <affected-histogram name="NetConnectivity3.StartPacket.Send6.SeriesAcked"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity4a" separator=".">
+ <group name="NATBind.Sent2"
+ label="Two packets were sent spreading over a random period, to test if
+ the NAT dropped the binding. Afterwords, an extra (short) packet
+ was sent with renewed NAT binding to test whether the network
+ that was used to deliver the first packet is still connected.
+ Results are only shown in this histogram if at least ten packets
+ were received in the StartPacket test."/>
+ <group name="NonPacedPacket"
+ label="21 Packets were sent as rapidly as possible. Results are only
+ shown in this histogram if at least two packets were received in
+ the StartPacket Test."/>
+ <group name="PacedPacket"
+ label="21 Packets were sent at equal intervals, which were selected to
+ match the bandwidth discovered during the StartPacket test.
+ Results are only shown in this histogram if at least two packets
+ were received in the StartPacket Test."/>
+ <group name="StartPacket"
+ label="21 Packets were sent as rapidly as possible, just after the
+ client successfully sent a UMA upload. Each packet was numbered
+ when it was sent by Google."/>
+ <affected-histogram name="NetConnectivity4"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity4NATBindPacketReceives" separator=".">
+ <group name="Bind.Failure"
+ label="Only when the second packet never arrived (we wait for 10 extra
+ seconds) and the first and the extra (short) packets arrived did
+ we record the duration in seconds between the sendings of the
+ first two packets in this histogram."/>
+ <group name="Bind.Success"
+ label="Only when all three packets including the extra (short) packet
+ arrived did we record the duration in seconds between the
+ sendings of the first two packets in this histogram."/>
+ <group name="Connectivity.Failure"
+ label="Only when the extra (short) packet (with renewed NAT binding)
+ never arrived (we wait for 10 extra seconds) did we record the
+ duration in seconds between the sendings of the first two
+ packets in this histogram."/>
+ <group name="Connectivity.Success"
+ label="Only when the extra (short) packet arrived did we record the
+ duration in seconds between the sendings of the first two
+ packets in this histogram."/>
+ <group name="SendToLastRecvDelay"
+ label="This histogram records the time duration (in milliseconds)
+ between the client sending the request and the receiving of the
+ second packet sent from the server, excluding the idle time
+ between sendings of the first two packets. Results are only
+ shown if the first two packets are both received."/>
+ <affected-histogram name="NetConnectivity4.NATBind.Sent2"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity4PacketFirst6" separator=".">
+ <group name="First6.SeriesRecv"
+ label="This histogram records a bit vector of the first 6 packets sent,
+ where the least significant bit is a 1 if the first packet was
+ received, etc. For example, if all packets other than packet 2
+ and 4 are received, then we'd have a sample (in binary) of
+ 110101B, or 53."/>
+ <group name="Sent21"
+ label="This histogram shows the number of packets received from the
+ first"/>
+ <affected-histogram name="NetConnectivity4.NonPacedPacket"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket"/>
+ <affected-histogram name="NetConnectivity4.StartPacket"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity4PacketReceives" separator=".">
+ <group name="NumRecvFromFirst01Packets" label="1 packet."/>
+ <group name="NumRecvFromFirst02Packets" label="2 packets."/>
+ <group name="NumRecvFromFirst03Packets" label="3 packets."/>
+ <group name="NumRecvFromFirst04Packets" label="4 packets."/>
+ <group name="NumRecvFromFirst05Packets" label="5 packets."/>
+ <group name="NumRecvFromFirst06Packets" label="6 packets."/>
+ <group name="NumRecvFromFirst07Packets" label="7 packets."/>
+ <group name="NumRecvFromFirst08Packets" label="8 packets."/>
+ <group name="NumRecvFromFirst09Packets" label="9 packets."/>
+ <group name="NumRecvFromFirst10Packets" label="10 packets."/>
+ <group name="NumRecvFromFirst11Packets" label="11 packets."/>
+ <group name="NumRecvFromFirst12Packets" label="12 packets."/>
+ <group name="NumRecvFromFirst13Packets" label="13 packets."/>
+ <group name="NumRecvFromFirst14Packets" label="14 packets."/>
+ <group name="NumRecvFromFirst15Packets" label="15 packets."/>
+ <group name="NumRecvFromFirst16Packets" label="16 packets."/>
+ <group name="NumRecvFromFirst17Packets" label="17 packets."/>
+ <group name="NumRecvFromFirst18Packets" label="18 packets."/>
+ <group name="NumRecvFromFirst19Packets" label="19 packets."/>
+ <group name="NumRecvFromFirst20Packets" label="20 packets."/>
+ <group name="NumRecvFromFirst21Packets" label="21 packets."/>
+ <affected-histogram name="NetConnectivity4.NonPacedPacket.Sent21"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket.Sent21"/>
+ <affected-histogram name="NetConnectivity4.StartPacket.Sent21"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity4PacketRTT" separator=".">
+ <group name="Sent21.GotAPacket"
+ label="The histogram shows if we ever got at least one packet in our
+ series of 21."/>
+ <group name="Sent21.PacketDelay"
+ label="The histogram shows the average inter-arrival time between every
+ two consecutive packets we receive in our series of 21
+ multiplied by 20 (so this is essentially the time duration
+ between the first and the last received packets)."/>
+ <group name="Sent21.PacketsRecv"
+ label="The histogram shows how many packets we receive in our series of
+ 21."/>
+ <group name="Sent21.RecvNthPacket"
+ label="Each packet was numbered when it was sent by Google. This
+ histogram records, for each packet number, how often we received
+ that packet."/>
+ <group name="Sent21.SendToLastRecvDelay"
+ label="This histogram records the time duration between the client
+ sending the request and the receiving of the last packet sent
+ from the server, excluding the total pacing time requested by
+ the client. Results are only shown if at least two packets are
+ received."/>
+ <group name="Sent21.Success.RTT" label="The histogram shows the RTT for the"/>
+ <affected-histogram name="NetConnectivity4.NonPacedPacket"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket"/>
+ <affected-histogram name="NetConnectivity4.StartPacket"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity4PacketRTTSeries" separator=".">
+ <group name="Packet01" label="1st packet."/>
+ <group name="Packet02" label="2nd packet."/>
+ <group name="Packet03" label="3rd packet."/>
+ <group name="Packet10" label="10th packet."/>
+ <group name="Packet20" label="20th packet."/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.Success.RTT"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket.Sent21.Success.RTT"/>
+ <affected-histogram name="NetConnectivity4.StartPacket.Sent21.Success.RTT"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity4PacketsAll" separator=".">
+ <group name="443.100B" label="100 bytes of data is sent on port 443."/>
+ <group name="443.1200B" label="1200 bytes of data is sent on port 443."/>
+ <group name="443.500B" label="500 bytes of data is sent on port 443."/>
+ <group name="80.100B" label="100 bytes of data is sent on port 80."/>
+ <group name="80.1200B" label="1200 bytes of data is sent on port 80."/>
+ <group name="80.500B" label="500 bytes of data is sent on port 80."/>
+ <affected-histogram name="NetConnectivity4.NATBind.Sent2.Bind.Failure"/>
+ <affected-histogram name="NetConnectivity4.NATBind.Sent2.Bind.Success"/>
+ <affected-histogram
+ name="NetConnectivity4.NATBind.Sent2.Connectivity.Failure"/>
+ <affected-histogram
+ name="NetConnectivity4.NATBind.Sent2.Connectivity.Success"/>
+ <affected-histogram
+ name="NetConnectivity4.NATBind.Sent2.SendToLastRecvDelay"/>
+ <affected-histogram name="NetConnectivity4.NonPacedPacket.Sent21.GotAPacket"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst01Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst02Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst03Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst04Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst05Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst06Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst07Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst08Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst09Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst10Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst11Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst12Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst13Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst14Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst15Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst16Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst17Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst18Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst19Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst20Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.NumRecvFromFirst21Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.PacketDelay"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.PacketsRecv"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.RecvNthPacket"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.SendToLastRecvDelay"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.Success.RTT.Packet01"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.Success.RTT.Packet02"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.Success.RTT.Packet03"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.Success.RTT.Packet10"/>
+ <affected-histogram
+ name="NetConnectivity4.NonPacedPacket.Sent21.Success.RTT.Packet20"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket.Sent21.GotAPacket"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst01Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst02Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst03Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst04Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst05Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst06Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst07Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst08Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst09Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst10Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst11Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst12Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst13Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst14Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst15Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst16Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst17Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst18Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst19Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst20Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.NumRecvFromFirst21Packets"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket.Sent21.PacketDelay"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket.Sent21.PacketsRecv"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket.Sent21.RecvNthPacket"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.SendToLastRecvDelay"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.Success.RTT.Packet01"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.Success.RTT.Packet02"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.Success.RTT.Packet03"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.Success.RTT.Packet10"/>
+ <affected-histogram
+ name="NetConnectivity4.PacedPacket.Sent21.Success.RTT.Packet20"/>
+ <affected-histogram name="NetConnectivity4.StartPacket.Sent21.GotAPacket"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst01Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst02Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst03Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst04Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst05Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst06Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst07Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst08Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst09Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst10Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst11Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst12Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst13Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst14Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst15Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst16Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst17Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst18Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst19Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst20Packets"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.NumRecvFromFirst21Packets"/>
+ <affected-histogram name="NetConnectivity4.StartPacket.Sent21.PacketDelay"/>
+ <affected-histogram name="NetConnectivity4.StartPacket.Sent21.PacketsRecv"/>
+ <affected-histogram name="NetConnectivity4.StartPacket.Sent21.RecvNthPacket"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.SendToLastRecvDelay"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.Success.RTT.Packet01"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.Success.RTT.Packet02"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.Success.RTT.Packet03"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.Success.RTT.Packet10"/>
+ <affected-histogram
+ name="NetConnectivity4.StartPacket.Sent21.Success.RTT.Packet20"/>
+</fieldtrial>
+
+<fieldtrial name="NetConnectivity4SeriesRecv" separator=".">
+ <group name="443.100B" label="100 bytes of data is sent on port 443."/>
+ <group name="443.100B.NoProxy"
+ label="100 bytes of data is sent on port 443 with no proxy."/>
+ <group name="443.1200B" label="1200 bytes of data is sent on port 443."/>
+ <group name="443.1200B.NoProxy"
+ label="1200 bytes of data is sent on port 443 with no proxy."/>
+ <group name="443.500B" label="500 bytes of data is sent on port 443."/>
+ <group name="443.500B.NoProxy"
+ label="500 bytes of data is sent on port 443 with no proxy."/>
+ <group name="80.100B" label="100 bytes of data is sent on port 80."/>
+ <group name="80.100B.NoProxy"
+ label="100 bytes of data is sent on port 80 with no proxy."/>
+ <group name="80.1200B" label="1200 bytes of data is sent on port 80."/>
+ <group name="80.1200B.NoProxy"
+ label="1200 bytes of data is sent on port 80 with no proxy."/>
+ <group name="80.500B" label="500 bytes of data is sent on port 80."/>
+ <group name="80.500B.NoProxy"
+ label="500 bytes of data is sent on port 80 with no proxy."/>
+ <affected-histogram name="NetConnectivity4.NonPacedPacket.First6.SeriesRecv"/>
+ <affected-histogram name="NetConnectivity4.PacedPacket.First6.SeriesRecv"/>
+ <affected-histogram name="NetConnectivity4.StartPacket.First6.SeriesRecv"/>
+</fieldtrial>
+
+<fieldtrial name="NetProxyResolverExecutionTime">
+ <group name="UrlOver2K" label="URL length was over 2K"/>
+ <group name="UrlOver4K" label="URL length was over 4K"/>
+ <group name="UrlOver8K" label="URL length was over 8K"/>
+ <group name="UrlOver128K" label="URL length was over 128K"/>
+ <affected-histogram name="Net.ProxyResolver.ExecutionTime"/>
+</fieldtrial>
+
+<fieldtrial name="OmniboxProviderTime" separator=".">
+ <group name="Bookmark"/>
+ <group name="Builtin"/>
+ <group name="Contact"/>
+ <group name="ExtensionApp"/>
+ <group name="HistoryContents"/>
+ <group name="HistoryQuick"/>
+ <group name="HistoryURL"/>
+ <group name="Keyword"/>
+ <group name="Search"/>
+ <group name="Shortcuts"/>
+ <group name="ZeroSuggest"/>
+ <affected-histogram name="Omnibox.ProviderTime"/>
+</fieldtrial>
+
+<fieldtrial name="OverlappedReadImpact">
+ <group name="OverlappedReadDisabled" label="Non-blocking reads"/>
+ <group name="OverlappedReadEnabled" label="Default, async reads"/>
+ <affected-histogram name="Net.HttpJob.TotalTime"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeCached"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeCancel"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeNotCached"/>
+ <affected-histogram name="Net.HttpJob.TotalTimeSuccess"/>
+ <affected-histogram name="PLT.Abandoned"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadReload"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadStaleOk"/>
+ <affected-histogram name="PLT.BeginToFinish_NormalLoad"/>
+ <affected-histogram name="PLT.LoadType"/>
+</fieldtrial>
+
+<fieldtrial name="PageLoadType">
+ <group name="HistoryLoad" label="but only for user pressing back or forward"/>
+ <group name="LinkLoad"
+ label="deprecated - see LinkLoadReload, LinkLoadNormal,
+ LinkLoadStaleOk, LinkLoadCacheOnly; content initiated, commonly
+ back to a posted page"/>
+ <group name="LinkLoadCacheOnly"
+ label="content initiated, commonly back to a posted page, where browser
+ must ONLY use cache"/>
+ <group name="LinkLoadNormal"
+ label="content initiated, ordinary link traversal or post"/>
+ <group name="LinkLoadReload" label="content initiated, calling reload()"/>
+ <group name="LinkLoadStaleOk"
+ label="content initiated, commonly forward or back where stale cached
+ data is very acceptable"/>
+ <group name="NormalLoad"
+ label="but only for user entered URL or omnibox search"/>
+ <group name="Reload" label="but only for user pressed reload"/>
+ <group name="UndefLoad"
+ label="should never happen... as it is only for an client-code error
+ case which should not exist"/>
+ <affected-histogram name="PLT.BeginToFinish"/>
+ <affected-histogram name="PLT.BeginToFinishDoc"/>
+ <affected-histogram name="PLT.StartToCommit">
+ <with-group name="LinkLoadNormal"/>
+ <with-group name="NormalLoad"/>
+ </affected-histogram>
+ <affected-histogram name="PLT.StartToFinish">
+ <with-group name="LinkLoadNormal"/>
+ <with-group name="NormalLoad"/>
+ </affected-histogram>
+ <affected-histogram name="Renderer4.BeginToFinish"/>
+ <affected-histogram name="Renderer4.BeginToFinishDoc"/>
+</fieldtrial>
+
+<fieldtrial name="PpapiPluginName">
+ <group name="libpepflashplayer.so" label="Flash player on Linux or Cros"/>
+ <group name="libwidevinecdmadapter.so" label="Widevine CDM on Linux or Cros"/>
+ <group name="pepflashplayer.dll" label="Flash player on Windows"/>
+ <group name="PepperFlashPlayer.plugin" label="Flash player on Mac"/>
+ <group name="widevinecdmadapter.dll" label="Widevine CDM on Windows"/>
+ <group name="widevinecdmadapter.plugin" label="Widevine CDM on Mac"/>
+ <affected-histogram name="Plugin.PpapiBrokerLoadResult"/>
+ <affected-histogram name="Plugin.PpapiPluginLoadResult"/>
+</fieldtrial>
+
+<fieldtrial name="Prefetch">
+ <group name="ContentPrefetchPrefetchOff"
+ label="Prefetch is completely disabled."/>
+ <group name="ContentPrefetchPrefetchOn"
+ label="prefetch is enabled but prerender is disabled."/>
+ <affected-histogram name="HttpCache.EntryLockWait"/>
+ <affected-histogram name="Net.HttpTimeToFirstByte"/>
+ <affected-histogram name="PLT.Abandoned"/>
+ <affected-histogram name="PLT.BeginToFinish"/>
+ <affected-histogram name="PLT.BeginToFinish_ContentPrefetcher"/>
+ <affected-histogram name="PLT.BeginToFinish_ContentPrefetcherReferrer"/>
+ <affected-histogram name="PLT.BeginToFinishDoc"/>
+ <affected-histogram name="PLT.BeginToFinishDoc_ContentPrefetcher"/>
+ <affected-histogram name="PLT.BeginToFinishDoc_ContentPrefetcherReferrer"/>
+ <affected-histogram name="PLT.PerceivedLoadTime"/>
+ <affected-histogram name="PLT.PerceivedLoadTime_PrerenderLoad"/>
+</fieldtrial>
+
+<fieldtrial name="Prerender">
+ <group name="PrerenderEnabled" label="prerender is enabled."/>
+ <group name="PrerenderControl" label="prerender is disabled."/>
+ <group name="PrerenderNoUse"
+ label="prerender is enabled, but pages are not swapped in."/>
+ <group name="PrerenderMulti"
+ label="prerender is enabled with multiple simultanious prerenders."/>
+ <group name="Prerender5minTTL"
+ label="prerender is enabled, and the TTL is extended to 5 minutes."/>
+ <affected-histogram name="HttpCache.EntryLockWait"/>
+ <affected-histogram name="Net.HttpTimeToFirstByte"/>
+ <affected-histogram name="PLT.Abandoned"/>
+ <affected-histogram name="PLT.BeginToFinish"/>
+ <affected-histogram name="PLT.BeginToFinish_ContentPrefetcher"/>
+ <affected-histogram name="PLT.BeginToFinish_ContentPrefetcherReferrer"/>
+ <affected-histogram name="PLT.BeginToFinishDoc"/>
+ <affected-histogram name="PLT.BeginToFinishDoc_ContentPrefetcher"/>
+ <affected-histogram name="PLT.BeginToFinishDoc_ContentPrefetcherReferrer"/>
+ <affected-histogram name="PLT.PerceivedLoadTime"/>
+ <affected-histogram name="PLT.PerceivedLoadTime_PrerenderLoad"/>
+ <affected-histogram name="Prerender.FinalStatus"/>
+ <affected-histogram name="Prerender.FinalStatusMatchComplete"/>
+ <affected-histogram name="Prerender.FractionPixelsFinalAtSwapin"/>
+ <affected-histogram name="Prerender.LocalPredictorEvent"/>
+ <affected-histogram name="Prerender.PerceivedPLT"/>
+ <affected-histogram name="Prerender.PerceivedPLTFirstAfterMiss"/>
+ <affected-histogram name="Prerender.PerceivedPLTFirstAfterMissAnyOnly"/>
+ <affected-histogram name="Prerender.PerceivedPLTFirstAfterMissBoth"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlapping"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlappingOnly"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatched"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatchedComplete"/>
+ <affected-histogram name="Prerender.PerceivedPLTWindowed"/>
+ <affected-histogram name="Prerender.PerceivedPLTWindowNotMatched"/>
+ <affected-histogram name="Prerender.PercentLoadDoneAtSwapin"/>
+ <affected-histogram name="Prerender.PrerenderNotSwappedInPLT"/>
+ <affected-histogram name="Prerender.RendererIdleTime"/>
+ <affected-histogram name="Prerender.RendererPerceivedPLT"/>
+ <affected-histogram name="Prerender.RendererPerceivedPLTMatched"/>
+ <affected-histogram name="Prerender.RendererTimeUntilDisplay"/>
+ <affected-histogram name="Prerender.SimulatedLocalBrowsingBaselinePLT"/>
+ <affected-histogram name="Prerender.SimulatedLocalBrowsingPLT"/>
+</fieldtrial>
+
+<fieldtrial name="PrerenderHoverType" ordering="prefix">
+ <obsolete>
+ deprecated May 10 2012
+ </obsolete>
+ <group name="HoverStats_50" label="Hover stats @ threshold 50 ms."/>
+ <group name="HoverStats_75" label="Hover stats @ threshold 75 ms."/>
+ <group name="HoverStats_100" label="Hover stats @ threshold 100 ms."/>
+ <group name="HoverStats_150" label="Hover stats @ threshold 150 ms."/>
+ <group name="HoverStats_200" label="Hover stats @ threshold 200 ms."/>
+ <group name="HoverStats_250" label="Hover stats @ threshold 250 ms."/>
+ <group name="HoverStats_300" label="Hover stats @ threshold 300 ms."/>
+ <group name="HoverStats_400" label="Hover stats @ threshold 400 ms."/>
+ <group name="HoverStats_500" label="Hover stats @ threshold 500 ms."/>
+ <group name="HoverStats_750" label="Hover stats @ threshold 750 ms."/>
+ <group name="HoverStats_1000" label="Hover stats @ threshold 1000 ms."/>
+ <group name="HoverStats_1500" label="Hover stats @ threshold 1500 ms."/>
+ <group name="HoverStats_2000" label="Hover stats @ threshold 2000 ms."/>
+ <group name="HoverStats_3000" label="Hover stats @ threshold 3000 ms."/>
+ <group name="HoverStats_4000" label="Hover stats @ threshold 4000 ms."/>
+ <group name="HoverStats_5000" label="Hover stats @ threshold 5000 ms."/>
+ <affected-histogram name="Prerender.Events"/>
+ <affected-histogram name="Prerender.TimeToClick"/>
+</fieldtrial>
+
+<fieldtrial name="PrerenderSource" ordering="prefix">
+ <group name="" label="All prerenders."/>
+ <group name="exp1" label="Likelihood threshold experiment 1."/>
+ <group name="exp2" label="Likelihood threshold experiment 2."/>
+ <group name="exp3" label="Likelihood threshold experiment 3."/>
+ <group name="exp4" label="Likelihood threshold experiment 4."/>
+ <group name="exp5" label="Likelihood threshold experiment 5."/>
+ <group name="exp6" label="Likelihood threshold experiment 6."/>
+ <group name="exp7" label="Likelihood threshold experiment 7."/>
+ <group name="exp8" label="Likelihood threshold experiment 8."/>
+ <group name="exp9" label="Likelihood threshold experiment 9."/>
+ <group name="gws" label="GWS triggered prerender."/>
+ <group name="localpredictor" label="Local predictor triggered prerender."/>
+ <group name="omnibox" label="Triggered from the omnibox."/>
+ <group name="wash" label="Multiple sources could have triggered."/>
+ <group name="web" label="Link triggered prerender."/>
+ <group name="webcross" label="Link triggered prerender, cross domain."/>
+ <group name="websame" label="Link triggered prerender, same domain."/>
+ <affected-histogram name="Prerender.FinalStatus"/>
+ <affected-histogram name="Prerender.FinalStatus_Prerender5minTTL"/>
+ <affected-histogram name="Prerender.FinalStatus_PrerenderControl"/>
+ <affected-histogram name="Prerender.FinalStatus_PrerenderEnabled"/>
+ <affected-histogram name="Prerender.FinalStatus_PrerenderMulti"/>
+ <affected-histogram name="Prerender.FinalStatus_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.FinalStatusMatchComplete"/>
+ <affected-histogram
+ name="Prerender.FinalStatusMatchComplete_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.FinalStatusMatchComplete_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.FinalStatusMatchComplete_PrerenderEnabled"/>
+ <affected-histogram name="Prerender.FinalStatusMatchComplete_PrerenderMulti"/>
+ <affected-histogram name="Prerender.FinalStatusMatchComplete_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.FractionPixelsFinalAtSwapin"/>
+ <affected-histogram
+ name="Prerender.FractionPixelsFinalAtSwapin_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.FractionPixelsFinalAtSwapin_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.FractionPixelsFinalAtSwapin_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.FractionPixelsFinalAtSwapin_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.FractionPixelsFinalAtSwapin_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.LocalPredictorEvent"/>
+ <affected-histogram name="Prerender.LocalPredictorEvent_Prerender5minTTL"/>
+ <affected-histogram name="Prerender.LocalPredictorEvent_PrerenderControl"/>
+ <affected-histogram name="Prerender.LocalPredictorEvent_PrerenderEnabled"/>
+ <affected-histogram name="Prerender.LocalPredictorEvent_PrerenderMulti"/>
+ <affected-histogram name="Prerender.LocalPredictorEvent_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.LocalPredictorTimeUntilUsed"/>
+ <affected-histogram name="Prerender.PerceivedPLT"/>
+ <affected-histogram name="Prerender.PerceivedPLT_Prerender5minTTL"/>
+ <affected-histogram name="Prerender.PerceivedPLT_PrerenderControl"/>
+ <affected-histogram name="Prerender.PerceivedPLT_PrerenderEnabled"/>
+ <affected-histogram name="Prerender.PerceivedPLT_PrerenderMulti"/>
+ <affected-histogram name="Prerender.PerceivedPLT_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PerceivedPLTFirstAfterMiss"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMiss_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMiss_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMiss_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMiss_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMiss_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PerceivedPLTFirstAfterMissAnyOnly"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissAnyOnly_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissAnyOnly_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissAnyOnly_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissAnyOnly_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissAnyOnly_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PerceivedPLTFirstAfterMissBoth"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissBoth_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissBoth_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissBoth_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissBoth_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissBoth_PrerenderNoUse"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlapping"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlapping_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlapping_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlapping_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlapping_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlapping_PrerenderNoUse"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlappingOnly"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlappingOnly_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlappingOnly_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlappingOnly_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlappingOnly_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTFirstAfterMissNonOverlappingOnly_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatched"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatched_Prerender5minTTL"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatched_PrerenderControl"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatched_PrerenderEnabled"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatched_PrerenderMulti"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatched_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PerceivedPLTMatchedComplete"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTMatchedComplete_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTMatchedComplete_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTMatchedComplete_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTMatchedComplete_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTMatchedComplete_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PerceivedPLTWindowed"/>
+ <affected-histogram name="Prerender.PerceivedPLTWindowed_PrerenderEnabled"/>
+ <affected-histogram name="Prerender.PerceivedPLTWindowNotMatched"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTWindowNotMatched_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTWindowNotMatched_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTWindowNotMatched_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTWindowNotMatched_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.PerceivedPLTWindowNotMatched_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PercentLoadDoneAtSwapin"/>
+ <affected-histogram
+ name="Prerender.PercentLoadDoneAtSwapin_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PercentLoadDoneAtSwapin_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PercentLoadDoneAtSwapin_PrerenderEnabled"/>
+ <affected-histogram name="Prerender.PercentLoadDoneAtSwapin_PrerenderMulti"/>
+ <affected-histogram name="Prerender.PercentLoadDoneAtSwapin_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PrerenderNotSwappedInPLT"/>
+ <affected-histogram
+ name="Prerender.PrerenderNotSwappedInPLT_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.PrerenderNotSwappedInPLT_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.PrerenderNotSwappedInPLT_PrerenderEnabled"/>
+ <affected-histogram name="Prerender.PrerenderNotSwappedInPLT_PrerenderMulti"/>
+ <affected-histogram name="Prerender.PrerenderNotSwappedInPLT_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.PrerendersPerSessionCount"/>
+ <affected-histogram name="Prerender.SimulatedLocalBrowsingBaselinePLT"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingBaselinePLT_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingBaselinePLT_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingBaselinePLT_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingBaselinePLT_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingBaselinePLT_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.SimulatedLocalBrowsingPLT"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingPLT_Prerender5minTTL"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingPLT_PrerenderControl"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingPLT_PrerenderEnabled"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingPLT_PrerenderMulti"/>
+ <affected-histogram
+ name="Prerender.SimulatedLocalBrowsingPLT_PrerenderNoUse"/>
+ <affected-histogram name="Prerender.TimeBetweenPrerenderRequests"/>
+ <affected-histogram name="Prerender.TimeSinceLastRecentVisit"/>
+ <affected-histogram name="Prerender.TimeUntilUsed2"/>
+</fieldtrial>
+
+<fieldtrial name="ProgressiveScan">
+ <group name="FullScan" label="Using WPA_supplicant to scan."/>
+ <group name="33Percent_4MinMax"
+ label="Progressive scan @ 33%, 4 frequency bins."/>
+ <group name="50Percent_4MinMax"
+ label="Progressive scan @ 50%, 4 frequency bins."/>
+ <group name="50Percent_8MinMax"
+ label="Progressive scan @ 50%, 8 frequency bins."/>
+ <group name="100Percent_8MinMax"
+ label="Progressive scan @ 100%, 8 frequency bins."/>
+ <affected-histogram name="Network.Shill.WiFi.ScanResult"/>
+ <affected-histogram name="Network.Shill.Wifi.TimeToScan"/>
+ <affected-histogram name="Network.Shill.Wifi.TimeToScanAndConnect"/>
+</fieldtrial>
+
+<fieldtrial name="ProtectorSettingChange" separator=".">
+ <obsolete>
+ Deprecated 8/2013. No longer tracked.
+ </obsolete>
+ <group name="Applied" label="change has been accepted by user"/>
+ <group name="Corrupt" label="possibly hijacked, backup invalid"/>
+ <group name="Discarded" label="change has been reverted by user"/>
+ <group name="Fallback" label="fallback provider used (no backup available)"/>
+ <group name="Hijacked" label="hijacked, with a valid backup"/>
+ <group name="Missing" label="fallback provider missing, added"/>
+ <group name="New" label="(obsolete, was sum of Corrupt+Hijacked)"/>
+ <group name="Restored"
+ label="search provider restored by Protector before showing the bubble"/>
+ <group name="Timeout" label="change has been ignored by user (timed out)"/>
+ <affected-histogram name="Protector.SearchProvider"/>
+ <affected-histogram name="Protector.StartupSettings"/>
+</fieldtrial>
+
+<fieldtrial name="ProxyConnectionImpact">
+ <group name="proxy_connections_16"
+ label="with 16 connections per proxy server"/>
+ <group name="proxy_connections_32"
+ label="with 32 connections per proxy server"/>
+ <group name="proxy_connections_64"
+ label="with 64 connections per proxy server"/>
+ <group name="proxy_connections_8"
+ label="with 8 connections per proxy server"/>
+ <affected-histogram name="Net.HttpProxySocketRequestTime"/>
+ <affected-histogram name="Net.SocksSocketRequestTime"/>
+ <affected-histogram name="PLT.Abandoned"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadReload"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadStaleOk"/>
+ <affected-histogram name="PLT.BeginToFinish_NormalLoad"/>
+</fieldtrial>
+
+<fieldtrial name="QueryTimeSuffix" separator=".">
+ <group name="0" label="N = 0"/>
+ <group name="1" label="N = 1"/>
+ <group name="2" label="N = 2"/>
+ <group name="3" label="N = 3"/>
+ <group name="4" label="N = 4"/>
+ <group name="5" label="N = 5"/>
+ <affected-histogram name="Omnibox.QueryTime"/>
+</fieldtrial>
+
+<fieldtrial name="RemoteProcessWarmStartFast" separator="">
+ <group name="" label="Normal start."/>
+ <group name="Fast" label="Fast start by skipping normal chrome.dll startup."/>
+ <affected-histogram name="Startup.WarmStartTimeFromRemoteProcessStart"/>
+</fieldtrial>
+
+<fieldtrial name="SBInterstitial">
+ <group name="V1" label="original interstitial"/>
+ <group name="V2" label="version 2 (new interstitial)"/>
+ <affected-histogram name="SB2.InterstitialAction"/>
+ <affected-histogram name="SB2.MalwareInterstitialTimeClosed"/>
+ <affected-histogram name="SB2.MalwareInterstitialTimeDiagnostic"/>
+ <affected-histogram name="SB2.MalwareInterstitialTimeLearnMore"/>
+ <affected-histogram name="SB2.MalwareInterstitialTimePrivacyPolicy"/>
+ <affected-histogram name="SB2.MalwareInterstitialTimeProceed"/>
+ <affected-histogram name="SB2.MalwareInterstitialTimeTakeMeBack"/>
+</fieldtrial>
+
+<fieldtrial name="ShowAppListWarmStartFast" separator="">
+ <group name="" label="Normal start."/>
+ <group name="Fast" label="Fast start by skipping normal chrome.dll startup."/>
+ <affected-histogram name="Startup.ShowAppListWarmStart"/>
+</fieldtrial>
+
+<fieldtrial name="SideloadWipeout">
+ <group name="Enabled" label="Sideload Wipeout Active."/>
+ <group name="Disabled" label="Control group."/>
+ <affected-histogram name="DisabledExtension.ExtensionWipedStatus"/>
+ <affected-histogram name="DisabledExtension.SideloadWipeoutCount"/>
+ <affected-histogram name="DisabledExtension.SideloadWipeoutNeeded"/>
+ <affected-histogram name="DisabledExtension.UserSelection"/>
+ <affected-histogram name="Extensions.ExternalExtensionEvent"/>
+ <affected-histogram name="Extensions.InstallSource"/>
+ <affected-histogram name="Extensions.UpdateSource"/>
+</fieldtrial>
+
+<fieldtrial name="SocketType">
+ <group name="HTTPProxy" label="HTTP proxy socket"/>
+ <group name="SOCK" label="SOCKS socket"/>
+ <group name="SSL" label="(Obsolete, SSL socket)"/>
+ <group name="SSL2" label="SSL2 socket"/>
+ <group name="SSLForProxies"
+ label="SSLClientSocket wrapping the TCPClient socket eventually used
+ for connection to a proxy"/>
+ <group name="SSLforHTTPSProxy"
+ label="SSLClientSocket wrapping the TCPClient socket eventually used
+ for connection to an HTTPS proxy"/>
+ <group name="TCP" label="plain, no proxy, no SSL socket"/>
+ <group name="TCPforHTTPProxy"
+ label="TCPClientSocket eventually used for connection to an HTTP proxy"/>
+ <group name="TCPforHTTPSProxy"
+ label="TCPClientSocket eventually used for connection to an HTTPS proxy"/>
+ <group name="TCPforSOCKS"
+ label="TCPClientSocket eventually used for connection to a SOCKS proxy"/>
+ <affected-histogram name="Net.SocketIdleTimeBeforeNextUse_ReusedSocket"/>
+ <affected-histogram name="Net.SocketIdleTimeBeforeNextUse_UnusedSocket"/>
+ <affected-histogram name="Net.SocketInitErrorCodes"/>
+ <affected-histogram name="Net.SocketRequestTime"/>
+ <affected-histogram name="Net.SocketType"/>
+</fieldtrial>
+
+<fieldtrial name="SpdyImpact">
+ <group name="npn_with_http"
+ label="with NPN negotiated but using HTTP instead of SPDY"/>
+ <group name="npn_with_spdy" label="with NPN negotiated and using SPDY"/>
+ <affected-histogram name="Net.Transaction_Connected"/>
+ <affected-histogram name="Net.Transaction_Connected_New"/>
+ <affected-histogram name="Net.Transaction_Connected_New_b"/>
+ <affected-histogram name="Net.Transaction_Connected_Under_10"/>
+ <affected-histogram name="PLT.Abandoned"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="PLT.BeginToFinish_NormalLoad"/>
+ <affected-histogram name="PLT.StartToCommit_LinkLoadNormal"/>
+ <affected-histogram name="PLT.StartToCommit_NormalLoad"/>
+ <affected-histogram name="PLT.StartToFinish_LinkLoadNormal"/>
+ <affected-histogram name="PLT.StartToFinish_NormalLoad"/>
+</fieldtrial>
+
+<fieldtrial name="SpdySettingsCwnd" separator="">
+ <group name="10K" label="where at least 10KB was transferred."/>
+ <group name="25K" label="where at least 25KB was transferred."/>
+ <group name="50K" label="where at least 50KB was transferred."/>
+ <group name="100K" label="where at least 100KB was transferred."/>
+ <affected-histogram name="Net.SpdySettingsCwnd"/>
+</fieldtrial>
+
+<fieldtrial name="SqliteDatabases" separator=".">
+ <group name="Activity" label="Activity"/>
+ <group name="AppCache" label="AppCache"/>
+ <group name="Cookie" label="Cookie"/>
+ <group name="DatabaseTracker" label="DatabaseTracker"/>
+ <group name="DomainBoundCerts" label="DomainBoundCerts"/>
+ <group name="DomStorageDatabase" label="DomStorageDatabase"/>
+ <group name="History" label="History"/>
+ <group name="Predictor" label="Predictor"/>
+ <group name="Quota" label="Quota"/>
+ <group name="SyncDirectory" label="SyncDirectory"/>
+ <group name="Text" label="Text"/>
+ <group name="Thumbnail" label="Thumbnail"/>
+ <group name="TopSites" label="TopSites"/>
+ <group name="Web" label="Web"/>
+ <affected-histogram name="Sqlite.Error"/>
+ <affected-histogram name="Sqlite.SizeKB"/>
+ <affected-histogram name="Sqlite.Version"/>
+</fieldtrial>
+
+<fieldtrial name="SSLFalseStart">
+ <group name="FalseStart_enabled"/>
+ <group name="FalseStart_disabled"/>
+ <affected-histogram name="Net.SSL_Connection_Latency"/>
+ <affected-histogram name="PLT.BeginToFinish_LinkLoadNormal"/>
+ <affected-histogram name="PLT.BeginToFinish_NormalLoad"/>
+</fieldtrial>
+
+<fieldtrial name="SSLResumption">
+ <group name="Resume_Handshake" label="Session Resumption"/>
+ <group name="Full_Handshake" label="Full"/>
+ <affected-histogram name="Net.SSL_Connection_Latency"/>
+ <affected-histogram name="Net.SSL_Connection_Latency_Google"/>
+</fieldtrial>
+
+<fieldtrial name="SyzygyStartupTime">
+ <group name="PreReadEnabled"/>
+ <group name="PreReadDisabled"/>
+ <group name="XP_PreReadEnabled"/>
+ <group name="XP_PreReadDisabled"/>
+ <group name="PreRead_0"/>
+ <group name="PreRead_5"/>
+ <group name="PreRead_10"/>
+ <group name="PreRead_15"/>
+ <group name="PreRead_20"/>
+ <group name="PreRead_25"/>
+ <group name="PreRead_30"/>
+ <group name="PreRead_35"/>
+ <group name="PreRead_40"/>
+ <group name="PreRead_45"/>
+ <group name="PreRead_50"/>
+ <group name="PreRead_55"/>
+ <group name="PreRead_60"/>
+ <group name="PreRead_65"/>
+ <group name="PreRead_70"/>
+ <group name="PreRead_75"/>
+ <group name="PreRead_80"/>
+ <group name="PreRead_85"/>
+ <group name="PreRead_90"/>
+ <group name="PreRead_95"/>
+ <group name="PreRead_100"/>
+ <group name="XP_PreRead_0"/>
+ <group name="XP_PreRead_5"/>
+ <group name="XP_PreRead_10"/>
+ <group name="XP_PreRead_15"/>
+ <group name="XP_PreRead_20"/>
+ <group name="XP_PreRead_25"/>
+ <group name="XP_PreRead_30"/>
+ <group name="XP_PreRead_35"/>
+ <group name="XP_PreRead_40"/>
+ <group name="XP_PreRead_45"/>
+ <group name="XP_PreRead_50"/>
+ <group name="XP_PreRead_55"/>
+ <group name="XP_PreRead_60"/>
+ <group name="XP_PreRead_65"/>
+ <group name="XP_PreRead_70"/>
+ <group name="XP_PreRead_75"/>
+ <group name="XP_PreRead_80"/>
+ <group name="XP_PreRead_85"/>
+ <group name="XP_PreRead_90"/>
+ <group name="XP_PreRead_95"/>
+ <group name="XP_PreRead_100"/>
+ <affected-histogram name="Startup.BrowserMessageLoopStartTime"/>
+ <affected-histogram name="Startup.BrowserOpenTabs"/>
+</fieldtrial>
+
+<fieldtrial name="WebStoreLinkExperiment">
+ <group name="Disabled" label="Neither extra webstore link is visible"/>
+ <group name="FooterLink" label="Link in bottom right of footer"/>
+ <group name="PlusIcon" label="Plus icon in apps page"/>
+ <affected-histogram name="Extensions.AppLaunch"/>
+ <affected-histogram name="NewTabPage.DefaultPageType"/>
+</fieldtrial>
+
+</fieldtrials>
+
+</histogram-configuration>
diff --git a/chromium/tools/metrics/histograms/pretty_print.py b/chromium/tools/metrics/histograms/pretty_print.py
new file mode 100755
index 00000000000..f1001b1ce96
--- /dev/null
+++ b/chromium/tools/metrics/histograms/pretty_print.py
@@ -0,0 +1,358 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Pretty-prints the histograms.xml file, alphabetizing tags, wrapping text
+at 80 chars, enforcing standard attribute ordering, and standardizing
+indentation.
+
+This is quite a bit more complicated than just calling tree.toprettyxml();
+we need additional customization, like special attribute ordering in tags
+and wrapping text nodes, so we implement our own full custom XML pretty-printer.
+"""
+
+from __future__ import with_statement
+
+import diffutil
+import json
+import logging
+import shutil
+import sys
+import textwrap
+import xml.dom.minidom
+
+
+WRAP_COLUMN = 80
+
+# Desired order for tag attributes; attributes listed here will appear first,
+# and in the same order as in these lists.
+# { tag_name: [attribute_name, ...] }
+ATTRIBUTE_ORDER = {
+ 'enum': ['name', 'type'],
+ 'histogram': ['name', 'enum', 'units'],
+ 'int': ['value', 'label'],
+ 'fieldtrial': ['name', 'separator', 'ordering'],
+ 'group': ['name', 'label'],
+ 'affected-histogram': ['name'],
+ 'with-group': ['name'],
+}
+
+# Tag names for top-level nodes whose children we don't want to indent.
+TAGS_THAT_DONT_INDENT = [
+ 'histogram-configuration',
+ 'histograms',
+ 'fieldtrials',
+ 'enums'
+]
+
+# Extra vertical spacing rules for special tag names.
+# {tag_name: (newlines_after_open, newlines_before_close, newlines_after_close)}
+TAGS_THAT_HAVE_EXTRA_NEWLINE = {
+ 'histogram-configuration': (2, 1, 1),
+ 'histograms': (2, 1, 1),
+ 'fieldtrials': (2, 1, 1),
+ 'enums': (2, 1, 1),
+ 'histogram': (1, 1, 1),
+ 'enum': (1, 1, 1),
+ 'fieldtrial': (1, 1, 1),
+}
+
+# Tags that we allow to be squished into a single line for brevity.
+TAGS_THAT_ALLOW_SINGLE_LINE = [
+ 'summary',
+ 'int',
+]
+
+# Tags whose children we want to alphabetize. The key is the parent tag name,
+# and the value is a pair of the tag name of the children we want to sort,
+# and a key function that maps each child node to the desired sort key.
+ALPHABETIZATION_RULES = {
+ 'histograms': ('histogram', lambda n: n.attributes['name'].value.lower()),
+ 'enums': ('enum', lambda n: n.attributes['name'].value.lower()),
+ 'enum': ('int', lambda n: int(n.attributes['value'].value)),
+ 'fieldtrials': ('fieldtrial', lambda n: n.attributes['name'].value.lower()),
+ 'fieldtrial': ('affected-histogram',
+ lambda n: n.attributes['name'].value.lower()),
+}
+
+
+class Error(Exception):
+ pass
+
+
+def LastLineLength(s):
+ """Returns the length of the last line in s.
+
+ Args:
+ s: A multi-line string, including newlines.
+
+ Returns:
+ The length of the last line in s, in characters.
+ """
+ if s.rfind('\n') == -1: return len(s)
+ return len(s) - s.rfind('\n') - len('\n')
+
+
+def XmlEscape(s):
+ """XML-escapes the given string, replacing magic characters (&<>") with their
+ escaped equivalents."""
+ s = s.replace("&", "&amp;").replace("<", "&lt;")
+ s = s.replace("\"", "&quot;").replace(">", "&gt;")
+ return s
+
+
+def PrettyPrintNode(node, indent=0):
+ """Pretty-prints the given XML node at the given indent level.
+
+ Args:
+ node: The minidom node to pretty-print.
+ indent: The current indent level.
+
+ Returns:
+ The pretty-printed string (including embedded newlines).
+
+ Raises:
+ Error if the XML has unknown tags or attributes.
+ """
+ # Handle the top-level document node.
+ if node.nodeType == xml.dom.minidom.Node.DOCUMENT_NODE:
+ return '\n'.join([PrettyPrintNode(n) for n in node.childNodes])
+
+ # Handle text nodes.
+ if node.nodeType == xml.dom.minidom.Node.TEXT_NODE:
+ # Wrap each paragraph in the text to fit in the 80 column limit.
+ wrapper = textwrap.TextWrapper()
+ wrapper.initial_indent = ' ' * indent
+ wrapper.subsequent_indent = ' ' * indent
+ wrapper.break_on_hyphens = False
+ wrapper.break_long_words = False
+ wrapper.width = WRAP_COLUMN
+ text = XmlEscape(node.data)
+ # Remove any common indent.
+ text = textwrap.dedent(text.strip('\n'))
+ lines = text.split('\n')
+ # Split the text into paragraphs at blank line boundaries.
+ paragraphs = [[]]
+ for l in lines:
+ if len(l.strip()) == 0 and len(paragraphs[-1]) > 0:
+ paragraphs.append([])
+ else:
+ paragraphs[-1].append(l)
+ # Remove trailing empty paragraph if present.
+ if len(paragraphs) > 0 and len(paragraphs[-1]) == 0:
+ paragraphs = paragraphs[:-1]
+ # Wrap each paragraph and separate with two newlines.
+ return '\n\n'.join([wrapper.fill('\n'.join(p)) for p in paragraphs])
+
+ # Handle element nodes.
+ if node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE:
+ newlines_after_open, newlines_before_close, newlines_after_close = (
+ TAGS_THAT_HAVE_EXTRA_NEWLINE.get(node.tagName, (1, 1, 0)))
+ # Open the tag.
+ s = ' ' * indent + '<' + node.tagName
+
+ # Calculate how much space to allow for the '>' or '/>'.
+ closing_chars = 1
+ if not node.childNodes:
+ closing_chars = 2
+
+ # Pretty-print the attributes.
+ attributes = node.attributes.keys()
+ if attributes:
+ # Reorder the attributes.
+ if not node.tagName in ATTRIBUTE_ORDER:
+ unrecognized_attributes = attributes;
+ else:
+ unrecognized_attributes = (
+ [a for a in attributes if not a in ATTRIBUTE_ORDER[node.tagName]])
+ attributes = (
+ [a for a in ATTRIBUTE_ORDER[node.tagName] if a in attributes])
+
+ for a in unrecognized_attributes:
+ logging.error(
+ 'Unrecognized attribute "%s" in tag "%s"' % (a, node.tagName))
+ if unrecognized_attributes:
+ raise Error()
+
+ for a in attributes:
+ value = XmlEscape(node.attributes[a].value)
+ # Replace sequences of whitespace with single spaces.
+ words = value.split()
+ a_str = ' %s="%s"' % (a, ' '.join(words))
+ # Start a new line if the attribute will make this line too long.
+ if LastLineLength(s) + len(a_str) + closing_chars > WRAP_COLUMN:
+ s += '\n' + ' ' * (indent + 3)
+ # Output everything up to the first quote.
+ s += ' %s="' % (a)
+ value_indent_level = LastLineLength(s)
+ # Output one word at a time, splitting to the next line where necessary.
+ column = value_indent_level
+ for i, word in enumerate(words):
+ # This is slightly too conservative since not every word will be
+ # followed by the closing characters...
+ if i > 0 and (column + len(word) + 1 + closing_chars > WRAP_COLUMN):
+ s = s.rstrip() # remove any trailing whitespace
+ s += '\n' + ' ' * value_indent_level
+ column = value_indent_level
+ s += word + ' '
+ column += len(word) + 1
+ s = s.rstrip() # remove any trailing whitespace
+ s += '"'
+ s = s.rstrip() # remove any trailing whitespace
+
+ # Pretty-print the child nodes.
+ if node.childNodes:
+ s += '>'
+ # Calculate the new indent level for child nodes.
+ new_indent = indent
+ if node.tagName not in TAGS_THAT_DONT_INDENT:
+ new_indent += 2
+ child_nodes = node.childNodes
+
+ # Recursively pretty-print the child nodes.
+ child_nodes = [PrettyPrintNode(n, indent=new_indent) for n in child_nodes]
+ child_nodes = [c for c in child_nodes if len(c.strip()) > 0]
+
+ # Determine whether we can fit the entire node on a single line.
+ close_tag = '</%s>' % node.tagName
+ space_left = WRAP_COLUMN - LastLineLength(s) - len(close_tag)
+ if (node.tagName in TAGS_THAT_ALLOW_SINGLE_LINE and
+ len(child_nodes) == 1 and len(child_nodes[0].strip()) <= space_left):
+ s += child_nodes[0].strip()
+ else:
+ s += '\n' * newlines_after_open + '\n'.join(child_nodes)
+ s += '\n' * newlines_before_close + ' ' * indent
+ s += close_tag
+ else:
+ s += '/>'
+ s += '\n' * newlines_after_close
+ return s
+
+ # Handle comment nodes.
+ if node.nodeType == xml.dom.minidom.Node.COMMENT_NODE:
+ return '<!--%s-->\n' % node.data
+
+ # Ignore other node types. This could be a processing instruction (<? ... ?>)
+ # or cdata section (<![CDATA[...]]!>), neither of which are legal in the
+ # histograms XML at present.
+ logging.error('Ignoring unrecognized node data: %s' % node.toxml())
+ raise Error()
+
+
+def unsafeAppendChild(parent, child):
+ """Append child to parent's list of children, ignoring the possibility that it
+ is already in another node's childNodes list. Requires that the previous
+ parent of child is discarded (to avoid non-tree DOM graphs).
+ This can provide a significant speedup as O(n^2) operations are removed (in
+ particular, each child insertion avoids the need to traverse the old parent's
+ entire list of children)."""
+ child.parentNode = None
+ parent.appendChild(child)
+ child.parentNode = parent
+
+
+def TransformByAlphabetizing(node):
+ """Transform the given XML by alphabetizing specific node types according to
+ the rules in ALPHABETIZATION_RULES.
+
+ Args:
+ node: The minidom node to transform.
+
+ Returns:
+ The minidom node, with children appropriately alphabetized. Note that the
+ transformation is done in-place, i.e. the original minidom tree is modified
+ directly.
+ """
+ if node.nodeType != xml.dom.minidom.Node.ELEMENT_NODE:
+ for c in node.childNodes: TransformByAlphabetizing(c)
+ return node
+
+ # Element node with a tag name that we alphabetize the children of?
+ if node.tagName in ALPHABETIZATION_RULES:
+ # Put subnodes in a list of node,key pairs to allow for custom sorting.
+ subtag, key_function = ALPHABETIZATION_RULES[node.tagName]
+ subnodes = []
+ last_key = -1
+ for c in node.childNodes:
+ if (c.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and
+ c.tagName == subtag):
+ last_key = key_function(c)
+ # Subnodes that we don't want to rearrange use the last node's key,
+ # so they stay in the same relative position.
+ subnodes.append( (c, last_key) )
+
+ # Sort the subnode list.
+ subnodes.sort(key=lambda pair: pair[1])
+
+ # Re-add the subnodes, transforming each recursively.
+ while node.firstChild:
+ node.removeChild(node.firstChild)
+ for (c, _) in subnodes:
+ unsafeAppendChild(node, TransformByAlphabetizing(c))
+ return node
+
+ # Recursively handle other element nodes and other node types.
+ for c in node.childNodes: TransformByAlphabetizing(c)
+ return node
+
+
+def PrettyPrint(raw_xml):
+ """Pretty-print the given XML.
+
+ Args:
+ xml: The contents of the histograms XML file, as a string.
+
+ Returns:
+ The pretty-printed version.
+ """
+ tree = xml.dom.minidom.parseString(raw_xml)
+ tree = TransformByAlphabetizing(tree)
+ return PrettyPrintNode(tree)
+
+
+def main():
+ logging.basicConfig(level=logging.INFO)
+
+ presubmit = ('--presubmit' in sys.argv)
+
+ logging.info('Loading histograms.xml...')
+ with open('histograms.xml', 'rb') as f:
+ xml = f.read()
+
+ # Check there are no CR ('\r') characters in the file.
+ if '\r' in xml:
+ logging.info('DOS-style line endings (CR characters) detected - these are '
+ 'not allowed. Please run dos2unix histograms.xml')
+ sys.exit(1)
+
+ logging.info('Pretty-printing...')
+ try:
+ pretty = PrettyPrint(xml)
+ except Error:
+ logging.error('Aborting parsing due to fatal errors.')
+ sys.exit(1)
+
+ if xml == pretty:
+ logging.info('histograms.xml is correctly pretty-printed.')
+ sys.exit(0)
+ if presubmit:
+ logging.info('histograms.xml is not formatted correctly; run '
+ 'pretty_print.py to fix.')
+ sys.exit(1)
+ if not diffutil.PromptUserToAcceptDiff(
+ xml, pretty,
+ 'Is the prettified version acceptable?'):
+ logging.error('Aborting')
+ return
+
+ logging.info('Creating backup file histograms.before.pretty-print.xml')
+ shutil.move('histograms.xml', 'histograms.before.pretty-print.xml')
+
+ logging.info('Writing new histograms.xml file')
+ with open('histograms.xml', 'wb') as f:
+ f.write(pretty)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/metrics/histograms/update_extension_functions.py b/chromium/tools/metrics/histograms/update_extension_functions.py
new file mode 100644
index 00000000000..1925c6e4e4e
--- /dev/null
+++ b/chromium/tools/metrics/histograms/update_extension_functions.py
@@ -0,0 +1,148 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Updates ExtensionFunctions enum in histograms.xml file with values read from
+extension_function_histogram_value.h.
+
+If the file was pretty-printed, the updated version is pretty-printed too.
+"""
+
+import logging
+import re
+import sys
+
+from xml.dom import minidom
+
+from diffutil import PromptUserToAcceptDiff
+from pretty_print import PrettyPrintNode
+
+HISTOGRAMS_PATH = 'histograms.xml'
+ENUM_NAME = 'ExtensionFunctions'
+
+EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH = \
+ '../../../chrome/browser/extensions/extension_function_histogram_value.h'
+ENUM_START_MARKER = "^enum HistogramValue {"
+ENUM_END_MARKER = "^ENUM_BOUNDARY"
+
+
+class UserError(Exception):
+ def __init__(self, message):
+ Exception.__init__(self, message)
+
+ @property
+ def message(self):
+ return self.args[0]
+
+def ExtractRegexGroup(line, regex):
+ m = re.match(regex, line)
+ if m:
+ return m.group(1)
+ else:
+ return None
+
+
+def ReadHistogramValues(filename):
+ """Returns a list of pairs (label, value) corresponding to HistogramValue.
+
+ Reads the extension_functions_histogram_value.h file, locates the
+ HistogramValue enum definition and returns a pair for each entry.
+ """
+
+ # Read the file as a list of lines
+ with open(filename) as f:
+ content = f.readlines()
+
+ # Locate the enum definition and collect all entries in it
+ inside_enum = False # We haven't found the enum definition yet
+ result = []
+ for line in content:
+ line = line.strip()
+ if inside_enum:
+ # Exit condition: we reached last enum value
+ if re.match(ENUM_END_MARKER, line):
+ inside_enum = False
+ else:
+ # Inside enum: generate new xml entry
+ label = ExtractRegexGroup(line.strip(), "^([\w]+)")
+ if label:
+ result.append((label, enum_value))
+ enum_value += 1
+ else:
+ if re.match(ENUM_START_MARKER, line):
+ inside_enum = True
+ enum_value = 0 # Start at 'UNKNOWN'
+ return result
+
+
+def UpdateHistogramDefinitions(histogram_values, document):
+ """Sets the children of <enum name="ExtensionFunctions" ...> node in
+ |document| to values generated from policy ids contained in
+ |policy_templates|.
+
+ Args:
+ histogram_values: A list of pairs (label, value) defining each extension
+ function
+ document: A minidom.Document object representing parsed histogram
+ definitions XML file.
+
+ """
+ # Find ExtensionFunctions enum.
+ for enum_node in document.getElementsByTagName('enum'):
+ if enum_node.attributes['name'].value == ENUM_NAME:
+ extension_functions_enum_node = enum_node
+ break
+ else:
+ raise UserError('No policy enum node found')
+
+ # Remove existing values.
+ while extension_functions_enum_node.hasChildNodes():
+ extension_functions_enum_node.removeChild(
+ extension_functions_enum_node.lastChild)
+
+ # Add a "Generated from (...)" comment
+ comment = ' Generated from {0} '.format(
+ EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH)
+ extension_functions_enum_node.appendChild(document.createComment(comment))
+
+ # Add values generated from policy templates.
+ for (label, value) in histogram_values:
+ node = document.createElement('int')
+ node.attributes['value'] = str(value)
+ node.attributes['label'] = label
+ extension_functions_enum_node.appendChild(node)
+
+def Log(message):
+ logging.info(message)
+
+def main():
+ if len(sys.argv) > 1:
+ print >>sys.stderr, 'No arguments expected!'
+ sys.stderr.write(__doc__)
+ sys.exit(1)
+
+ Log('Reading histogram enum definition from "%s".'
+ % (EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH))
+ histogram_values = ReadHistogramValues(
+ EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH)
+
+ Log('Reading existing histograms from "%s".' % (HISTOGRAMS_PATH))
+ with open(HISTOGRAMS_PATH, 'rb') as f:
+ histograms_doc = minidom.parse(f)
+ f.seek(0)
+ xml = f.read()
+
+ Log('Comparing histograms enum with new enum definition.')
+ UpdateHistogramDefinitions(histogram_values, histograms_doc)
+
+ Log('Writing out new histograms file.')
+ new_xml = PrettyPrintNode(histograms_doc)
+ if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'):
+ with open(HISTOGRAMS_PATH, 'wb') as f:
+ f.write(new_xml)
+
+ Log('Done.')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/metrics/histograms/update_policies.py b/chromium/tools/metrics/histograms/update_policies.py
new file mode 100644
index 00000000000..dd0447fb901
--- /dev/null
+++ b/chromium/tools/metrics/histograms/update_policies.py
@@ -0,0 +1,132 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Updates EnterprisePolicies enum in histograms.xml file with policy
+definitions read from policy_templates.json.
+
+If the file was pretty-printed, the updated version is pretty-printed too.
+"""
+
+import re
+import sys
+
+from ast import literal_eval
+from optparse import OptionParser
+from xml.dom import minidom
+
+from diffutil import PromptUserToAcceptDiff
+from pretty_print import PrettyPrintNode
+
+HISTOGRAMS_PATH = 'histograms.xml'
+POLICY_TEMPLATES_PATH = '../../../chrome/app/policy/policy_templates.json'
+ENUM_NAME = 'EnterprisePolicies'
+
+class UserError(Exception):
+ def __init__(self, message):
+ Exception.__init__(self, message)
+
+ @property
+ def message(self):
+ return self.args[0]
+
+
+def FlattenPolicies(policy_definitions, policy_list):
+ """Appends a list of policies defined in |policy_definitions| to
+ |policy_list|, flattening subgroups.
+
+ Args:
+ policy_definitions: A list of policy definitions and groups, as in
+ policy_templates.json file.
+ policy_list: A list that has policy definitions appended to it.
+ """
+ for policy in policy_definitions:
+ if policy['type'] == 'group':
+ FlattenPolicies(policy['policies'], policy_list)
+ else:
+ policy_list.append(policy)
+
+
+def ParsePlaceholders(text):
+ """Parse placeholders in |text|, making it more human-readable. The format of
+ |text| is exactly the same as in captions in policy_templates.json: it can
+ contain XML tags (ph, ex) and $1-like substitutions. Note that this function
+ does only a very simple parsing that is not fully correct, but should be
+ enough for all practical situations.
+
+ Args:
+ text: A string containing placeholders.
+
+ Returns:
+ |text| with placeholders removed or replaced by readable text.
+ """
+ text = re.sub(r'\$\d+', '', text) # Remove $1-like substitutions.
+ text = re.sub(r'<[^>]+>', '', text) # Remove XML tags.
+ return text
+
+
+def UpdateHistogramDefinitions(policy_templates, doc):
+ """Sets the children of <enum name="EnterprisePolicies" ...> node in |doc| to
+ values generated from policy ids contained in |policy_templates|.
+
+ Args:
+ policy_templates: A list of dictionaries, defining policies or policy
+ groups. The format is exactly the same as in
+ policy_templates.json file.
+ doc: A minidom.Document object representing parsed histogram definitions
+ XML file.
+ """
+ # Find EnterprisePolicies enum.
+ for enum_node in doc.getElementsByTagName('enum'):
+ if enum_node.attributes['name'].value == ENUM_NAME:
+ policy_enum_node = enum_node
+ break
+ else:
+ raise UserError('No policy enum node found')
+
+ # Remove existing values.
+ while policy_enum_node.hasChildNodes():
+ policy_enum_node.removeChild(policy_enum_node.lastChild)
+
+ # Add a "Generated from (...)" comment
+ comment = ' Generated from {0} '.format(POLICY_TEMPLATES_PATH)
+ policy_enum_node.appendChild(doc.createComment(comment))
+
+ # Add values generated from policy templates.
+ ordered_policies = []
+ FlattenPolicies(policy_templates['policy_definitions'], ordered_policies)
+ ordered_policies.sort(key=lambda policy: policy['id'])
+ for policy in ordered_policies:
+ node = doc.createElement('int')
+ node.attributes['value'] = str(policy['id'])
+ node.attributes['label'] = ParsePlaceholders(policy['caption'])
+ policy_enum_node.appendChild(node)
+
+
+def main():
+ if len(sys.argv) > 1:
+ print >>sys.stderr, 'No arguments expected!'
+ sys.stderr.write(__doc__)
+ sys.exit(1)
+
+ with open(POLICY_TEMPLATES_PATH, 'rb') as f:
+ policy_templates = literal_eval(f.read())
+ with open(HISTOGRAMS_PATH, 'rb') as f:
+ histograms_doc = minidom.parse(f)
+ f.seek(0)
+ xml = f.read()
+
+ UpdateHistogramDefinitions(policy_templates, histograms_doc)
+
+ new_xml = PrettyPrintNode(histograms_doc)
+ if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'):
+ with open(HISTOGRAMS_PATH, 'wb') as f:
+ f.write(new_xml)
+
+
+if __name__ == '__main__':
+ try:
+ main()
+ except UserError as e:
+ print >>sys.stderr, e.message
+ sys.exit(1)
diff --git a/chromium/tools/metrics/histograms/validate_format.py b/chromium/tools/metrics/histograms/validate_format.py
new file mode 100644
index 00000000000..f337e6ed2ce
--- /dev/null
+++ b/chromium/tools/metrics/histograms/validate_format.py
@@ -0,0 +1,17 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Verifies that the histograms XML file is well-formatted."""
+
+import extract_histograms
+
+
+def main():
+ # This will raise an exception if the file is not well-formatted.
+ histograms = extract_histograms.ExtractHistograms('histograms.xml')
+
+
+if __name__ == '__main__':
+ main()
+
diff --git a/chromium/tools/nocompile_driver.py b/chromium/tools/nocompile_driver.py
new file mode 100755
index 00000000000..5a8a081afb1
--- /dev/null
+++ b/chromium/tools/nocompile_driver.py
@@ -0,0 +1,472 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Implements a simple "negative compile" test for C++ on linux.
+
+Sometimes a C++ API needs to ensure that various usages cannot compile. To
+enable unittesting of these assertions, we use this python script to
+invoke gcc on a source file and assert that compilation fails.
+
+For more info, see:
+ http://dev.chromium.org/developers/testing/no-compile-tests
+"""
+
+import ast
+import locale
+import os
+import re
+import select
+import shlex
+import subprocess
+import sys
+import time
+
+
+# Matches lines that start with #if and have the substring TEST in the
+# conditional. Also extracts the comment. This allows us to search for
+# lines like the following:
+#
+# #ifdef NCTEST_NAME_OF_TEST // [r'expected output']
+# #if defined(NCTEST_NAME_OF_TEST) // [r'expected output']
+# #if NCTEST_NAME_OF_TEST // [r'expected output']
+# #elif NCTEST_NAME_OF_TEST // [r'expected output']
+# #elif DISABLED_NCTEST_NAME_OF_TEST // [r'expected output']
+#
+# inside the unittest file.
+NCTEST_CONFIG_RE = re.compile(r'^#(?:el)?if.*\s+(\S*NCTEST\S*)\s*(//.*)?')
+
+
+# Matches and removes the defined() preprocesor predicate. This is useful
+# for test cases that use the preprocessor if-statement form:
+#
+# #if defined(NCTEST_NAME_OF_TEST)
+#
+# Should be used to post-process the results found by NCTEST_CONFIG_RE.
+STRIP_DEFINED_RE = re.compile(r'defined\((.*)\)')
+
+
+# Used to grab the expectation from comment at the end of an #ifdef. See
+# NCTEST_CONFIG_RE's comment for examples of what the format should look like.
+#
+# The extracted substring should be a python array of regular expressions.
+EXTRACT_EXPECTATION_RE = re.compile(r'//\s*(\[.*\])')
+
+
+# The header for the result file so that it can be compiled.
+RESULT_FILE_HEADER = """
+// This file is generated by the no compile test from:
+// %s
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+"""
+
+
+# The GUnit test function to output on a successful test completion.
+SUCCESS_GUNIT_TEMPLATE = """
+TEST(%s, %s) {
+ LOG(INFO) << "Took %f secs. Started at %f, ended at %f";
+}
+"""
+
+# The GUnit test function to output for a disabled test.
+DISABLED_GUNIT_TEMPLATE = """
+TEST(%s, %s) { }
+"""
+
+
+# Timeout constants.
+NCTEST_TERMINATE_TIMEOUT_SEC = 60
+NCTEST_KILL_TIMEOUT_SEC = NCTEST_TERMINATE_TIMEOUT_SEC + 2
+BUSY_LOOP_MAX_TIME_SEC = NCTEST_KILL_TIMEOUT_SEC * 2
+
+
+def ValidateInput(parallelism, sourcefile_path, cflags, resultfile_path):
+ """Make sure the arguments being passed in are sane."""
+ assert parallelism >= 1
+ assert type(sourcefile_path) is str
+ assert type(cflags) is str
+ assert type(resultfile_path) is str
+
+
+def ParseExpectation(expectation_string):
+ """Extracts expectation definition from the trailing comment on the ifdef.
+
+ See the comment on NCTEST_CONFIG_RE for examples of the format we are parsing.
+
+ Args:
+ expectation_string: A string like "// [r'some_regex']"
+
+ Returns:
+ A list of compiled regular expressions indicating all possible valid
+ compiler outputs. If the list is empty, all outputs are considered valid.
+ """
+ assert expectation_string is not None
+
+ match = EXTRACT_EXPECTATION_RE.match(expectation_string)
+ assert match
+
+ raw_expectation = ast.literal_eval(match.group(1))
+ assert type(raw_expectation) is list
+
+ expectation = []
+ for regex_str in raw_expectation:
+ assert type(regex_str) is str
+ expectation.append(re.compile(regex_str))
+ return expectation
+
+
+def ExtractTestConfigs(sourcefile_path):
+ """Parses the soruce file for test configurations.
+
+ Each no-compile test in the file is separated by an ifdef macro. We scan
+ the source file with the NCTEST_CONFIG_RE to find all ifdefs that look like
+ they demark one no-compile test and try to extract the test configuration
+ from that.
+
+ Args:
+ sourcefile_path: The path to the source file.
+
+ Returns:
+ A list of test configurations. Each test configuration is a dictionary of
+ the form:
+
+ { name: 'NCTEST_NAME'
+ suite_name: 'SOURCE_FILE_NAME'
+ expectations: [re.Pattern, re.Pattern] }
+
+ The |suite_name| is used to generate a pretty gtest output on successful
+ completion of the no compile test.
+
+ The compiled regexps in |expectations| define the valid outputs of the
+ compiler. If any one of the listed patterns matches either the stderr or
+ stdout from the compilation, and the compilation failed, then the test is
+ considered to have succeeded. If the list is empty, than we ignore the
+ compiler output and just check for failed compilation. If |expectations|
+ is actually None, then this specifies a compiler sanity check test, which
+ should expect a SUCCESSFUL compilation.
+ """
+ sourcefile = open(sourcefile_path, 'r')
+
+ # Convert filename from underscores to CamelCase.
+ words = os.path.splitext(os.path.basename(sourcefile_path))[0].split('_')
+ words = [w.capitalize() for w in words]
+ suite_name = 'NoCompile' + ''.join(words)
+
+ # Start with at least the compiler sanity test. You need to always have one
+ # sanity test to show that compiler flags and configuration are not just
+ # wrong. Otherwise, having a misconfigured compiler, or an error in the
+ # shared portions of the .nc file would cause all tests to erroneously pass.
+ test_configs = [{'name': 'NCTEST_SANITY',
+ 'suite_name': suite_name,
+ 'expectations': None}]
+
+ for line in sourcefile:
+ match_result = NCTEST_CONFIG_RE.match(line)
+ if not match_result:
+ continue
+
+ groups = match_result.groups()
+
+ # Grab the name and remove the defined() predicate if there is one.
+ name = groups[0]
+ strip_result = STRIP_DEFINED_RE.match(name)
+ if strip_result:
+ name = strip_result.group(1)
+
+ # Read expectations if there are any.
+ test_configs.append({'name': name,
+ 'suite_name': suite_name,
+ 'expectations': ParseExpectation(groups[1])})
+ sourcefile.close()
+ return test_configs
+
+
+def StartTest(sourcefile_path, cflags, config):
+ """Start one negative compile test.
+
+ Args:
+ sourcefile_path: The path to the source file.
+ cflags: A string with all the CFLAGS to give to gcc. This string will be
+ split by shelex so be careful with escaping.
+ config: A dictionary describing the test. See ExtractTestConfigs
+ for a description of the config format.
+
+ Returns:
+ A dictionary containing all the information about the started test. The
+ fields in the dictionary are as follows:
+ { 'proc': A subprocess object representing the compiler run.
+ 'cmdline': The exectued command line.
+ 'name': The name of the test.
+ 'suite_name': The suite name to use when generating the gunit test
+ result.
+ 'terminate_timeout': The timestamp in seconds since the epoch after
+ which the test should be terminated.
+ 'kill_timeout': The timestamp in seconds since the epoch after which
+ the test should be given a hard kill signal.
+ 'started_at': A timestamp in seconds since the epoch for when this test
+ was started.
+ 'aborted_at': A timestamp in seconds since the epoch for when this test
+ was aborted. If the test completed successfully,
+ this value is 0.
+ 'finished_at': A timestamp in seconds since the epoch for when this
+ test was successfully complete. If the test is aborted,
+ or running, this value is 0.
+ 'expectations': A dictionary with the test expectations. See
+ ParseExpectation() for the structure.
+ }
+ """
+ # TODO(ajwong): Get the compiler from gyp.
+ cmdline = ['g++']
+ cmdline.extend(shlex.split(cflags))
+ name = config['name']
+ expectations = config['expectations']
+ if expectations is not None:
+ cmdline.append('-D%s' % name)
+ cmdline.extend(['-o', '/dev/null', '-c', '-x', 'c++', sourcefile_path])
+
+ process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ now = time.time()
+ return {'proc': process,
+ 'cmdline': ' '.join(cmdline),
+ 'name': name,
+ 'suite_name': config['suite_name'],
+ 'terminate_timeout': now + NCTEST_TERMINATE_TIMEOUT_SEC,
+ 'kill_timeout': now + NCTEST_KILL_TIMEOUT_SEC,
+ 'started_at': now,
+ 'aborted_at': 0,
+ 'finished_at': 0,
+ 'expectations': expectations}
+
+
+def PassTest(resultfile, test):
+ """Logs the result of a test started by StartTest(), or a disabled test
+ configuration.
+
+ Args:
+ resultfile: File object for .cc file that results are written to.
+ test: An instance of the dictionary returned by StartTest(), a
+ configuration from ExtractTestConfigs().
+ """
+ # The 'started_at' key is only added if a test has been started.
+ if 'started_at' in test:
+ resultfile.write(SUCCESS_GUNIT_TEMPLATE % (
+ test['suite_name'], test['name'],
+ test['finished_at'] - test['started_at'],
+ test['started_at'], test['finished_at']))
+ else:
+ resultfile.write(DISABLED_GUNIT_TEMPLATE % (
+ test['suite_name'], test['name']))
+
+
+def FailTest(resultfile, test, error, stdout=None, stderr=None):
+ """Logs the result of a test started by StartTest()
+
+ Args:
+ resultfile: File object for .cc file that results are written to.
+ test: An instance of the dictionary returned by StartTest()
+ error: The printable reason for the failure.
+ stdout: The test's output to stdout.
+ stderr: The test's output to stderr.
+ """
+ resultfile.write('#error "%s Failed: %s"\n' % (test['name'], error))
+ resultfile.write('#error "compile line: %s"\n' % test['cmdline'])
+ if stdout and len(stdout) != 0:
+ resultfile.write('#error "%s stdout:"\n' % test['name'])
+ for line in stdout.split('\n'):
+ resultfile.write('#error " %s:"\n' % line)
+
+ if stderr and len(stderr) != 0:
+ resultfile.write('#error "%s stderr:"\n' % test['name'])
+ for line in stderr.split('\n'):
+ resultfile.write('#error " %s"\n' % line)
+ resultfile.write('\n')
+
+
+def WriteStats(resultfile, suite_name, timings):
+ """Logs the peformance timings for each stage of the script into a fake test.
+
+ Args:
+ resultfile: File object for .cc file that results are written to.
+ suite_name: The name of the GUnit suite this test belongs to.
+ timings: Dictionary with timestamps for each stage of the script run.
+ """
+ stats_template = ("Started %f, Ended %f, Total %fs, Extract %fs, "
+ "Compile %fs, Process %fs")
+ total_secs = timings['results_processed'] - timings['started']
+ extract_secs = timings['extract_done'] - timings['started']
+ compile_secs = timings['compile_done'] - timings['extract_done']
+ process_secs = timings['results_processed'] - timings['compile_done']
+ resultfile.write('TEST(%s, Stats) { LOG(INFO) << "%s"; }\n' % (
+ suite_name, stats_template % (
+ timings['started'], timings['results_processed'], total_secs,
+ extract_secs, compile_secs, process_secs)))
+
+
+def ProcessTestResult(resultfile, test):
+ """Interprets and logs the result of a test started by StartTest()
+
+ Args:
+ resultfile: File object for .cc file that results are written to.
+ test: The dictionary from StartTest() to process.
+ """
+ # Snap a copy of stdout and stderr into the test dictionary immediately
+ # cause we can only call this once on the Popen object, and lots of stuff
+ # below will want access to it.
+ proc = test['proc']
+ (stdout, stderr) = proc.communicate()
+
+ if test['aborted_at'] != 0:
+ FailTest(resultfile, test, "Compile timed out. Started %f ended %f." %
+ (test['started_at'], test['aborted_at']))
+ return
+
+ if test['expectations'] is None:
+ # This signals a compiler sanity check test. Fail iff compilation failed.
+ if proc.poll() == 0:
+ PassTest(resultfile, test)
+ return
+ else:
+ FailTest(resultfile, test, 'Sanity compile failed. Is compiler borked?',
+ stdout, stderr)
+ return
+ elif proc.poll() == 0:
+ # Handle failure due to successful compile.
+ FailTest(resultfile, test,
+ 'Unexpected successful compilation.',
+ stdout, stderr)
+ return
+ else:
+ # Check the output has the right expectations. If there are no
+ # expectations, then we just consider the output "matched" by default.
+ if len(test['expectations']) == 0:
+ PassTest(resultfile, test)
+ return
+
+ # Otherwise test against all expectations.
+ for regexp in test['expectations']:
+ if (regexp.search(stdout) is not None or
+ regexp.search(stderr) is not None):
+ PassTest(resultfile, test)
+ return
+ expectation_str = ', '.join(
+ ["r'%s'" % regexp.pattern for regexp in test['expectations']])
+ FailTest(resultfile, test,
+ 'Expectations [%s] did not match output.' % expectation_str,
+ stdout, stderr)
+ return
+
+
+def CompleteAtLeastOneTest(resultfile, executing_tests):
+ """Blocks until at least one task is removed from executing_tests.
+
+ This function removes completed tests from executing_tests, logging failures
+ and output. If no tests can be removed, it will enter a poll-loop until one
+ test finishes or times out. On a timeout, this function is responsible for
+ terminating the process in the appropriate fashion.
+
+ Args:
+ executing_tests: A dict mapping a string containing the test name to the
+ test dict return from StartTest().
+
+ Returns:
+ A list of tests that have finished.
+ """
+ finished_tests = []
+ busy_loop_timeout = time.time() + BUSY_LOOP_MAX_TIME_SEC
+ while len(finished_tests) == 0:
+ # If we don't make progress for too long, assume the code is just dead.
+ assert busy_loop_timeout > time.time()
+
+ # Select on the output pipes.
+ read_set = []
+ for test in executing_tests.values():
+ read_set.extend([test['proc'].stderr, test['proc'].stdout])
+ result = select.select(read_set, [], read_set, NCTEST_TERMINATE_TIMEOUT_SEC)
+
+ # Now attempt to process results.
+ now = time.time()
+ for test in executing_tests.values():
+ proc = test['proc']
+ if proc.poll() is not None:
+ test['finished_at'] = now
+ finished_tests.append(test)
+ elif test['terminate_timeout'] < now:
+ proc.terminate()
+ test['aborted_at'] = now
+ elif test['kill_timeout'] < now:
+ proc.kill()
+ test['aborted_at'] = now
+
+ for test in finished_tests:
+ del executing_tests[test['name']]
+ return finished_tests
+
+
+def main():
+ if len(sys.argv) != 5:
+ print ('Usage: %s <parallelism> <sourcefile> <cflags> <resultfile>' %
+ sys.argv[0])
+ sys.exit(1)
+
+ # Force us into the "C" locale so the compiler doesn't localize its output.
+ # In particular, this stops gcc from using smart quotes when in english UTF-8
+ # locales. This makes the expectation writing much easier.
+ os.environ['LC_ALL'] = 'C'
+
+ parallelism = int(sys.argv[1])
+ sourcefile_path = sys.argv[2]
+ cflags = sys.argv[3]
+ resultfile_path = sys.argv[4]
+
+ timings = {'started': time.time()}
+
+ ValidateInput(parallelism, sourcefile_path, cflags, resultfile_path)
+
+ test_configs = ExtractTestConfigs(sourcefile_path)
+ timings['extract_done'] = time.time()
+
+ resultfile = open(resultfile_path, 'w')
+ resultfile.write(RESULT_FILE_HEADER % sourcefile_path)
+
+ # Run the no-compile tests, but ensure we do not run more than |parallelism|
+ # tests at once.
+ timings['header_written'] = time.time()
+ executing_tests = {}
+ finished_tests = []
+ for config in test_configs:
+ # CompleteAtLeastOneTest blocks until at least one test finishes. Thus, this
+ # acts as a semaphore. We cannot use threads + a real semaphore because
+ # subprocess forks, which can cause all sorts of hilarity with threads.
+ if len(executing_tests) >= parallelism:
+ finished_tests.extend(CompleteAtLeastOneTest(resultfile, executing_tests))
+
+ if config['name'].startswith('DISABLED_'):
+ PassTest(resultfile, config)
+ else:
+ test = StartTest(sourcefile_path, cflags, config)
+ assert test['name'] not in executing_tests
+ executing_tests[test['name']] = test
+
+ # If there are no more test to start, we still need to drain the running
+ # ones.
+ while len(executing_tests) > 0:
+ finished_tests.extend(CompleteAtLeastOneTest(resultfile, executing_tests))
+ timings['compile_done'] = time.time()
+
+ for test in finished_tests:
+ ProcessTestResult(resultfile, test)
+ timings['results_processed'] = time.time()
+
+ # We always know at least a sanity test was run.
+ WriteStats(resultfile, finished_tests[0]['suite_name'], timings)
+
+ resultfile.close()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/omahaproxy.py b/chromium/tools/omahaproxy.py
new file mode 100755
index 00000000000..75bf43ddef3
--- /dev/null
+++ b/chromium/tools/omahaproxy.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Chrome Version Tool
+
+Scrapes Chrome channel information and prints out the requested nugget of
+information.
+"""
+
+import json
+import optparse
+import os
+import string
+import sys
+import urllib
+
+URL = 'https://omahaproxy.appspot.com/json'
+
+
+def main():
+ try:
+ data = json.load(urllib.urlopen(URL))
+ except Exception as e:
+ print 'Error: could not load %s\n\n%s' % (URL, str(e))
+ return 1
+
+ # Iterate to find out valid values for OS, channel, and field options.
+ oses = set()
+ channels = set()
+ fields = set()
+
+ for os_versions in data:
+ oses.add(os_versions['os'])
+
+ for version in os_versions['versions']:
+ for field in version:
+ if field == 'channel':
+ channels.add(version['channel'])
+ else:
+ fields.add(field)
+
+ oses = sorted(oses)
+ channels = sorted(channels)
+ fields = sorted(fields)
+
+ # Command line parsing fun begins!
+ usage = ('%prog [options]\n'
+ 'Print out information about a particular Chrome channel.')
+ parser = optparse.OptionParser(usage=usage)
+
+ parser.add_option('-o', '--os',
+ choices=oses,
+ default='win',
+ help='The operating system of interest: %s '
+ '[default: %%default]' % ', '.join(oses))
+ parser.add_option('-c', '--channel',
+ choices=channels,
+ default='stable',
+ help='The channel of interest: %s '
+ '[default: %%default]' % ', '.join(channels))
+ parser.add_option('-f', '--field',
+ choices=fields,
+ default='version',
+ help='The field of interest: %s '
+ '[default: %%default] ' % ', '.join(fields))
+ (opts, args) = parser.parse_args()
+
+ # Print out requested data if available.
+ for os_versions in data:
+ if os_versions['os'] != opts.os:
+ continue
+
+ for version in os_versions['versions']:
+ if version['channel'] != opts.channel:
+ continue
+
+ if opts.field not in version:
+ continue
+
+ print version[opts.field]
+ return 0
+
+ print 'Error: unable to find %s for Chrome %s %s.' % (
+ opts.field, opts.os, opts.channel)
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/oopif/OWNERS b/chromium/tools/oopif/OWNERS
new file mode 100644
index 00000000000..7952d1b4dfb
--- /dev/null
+++ b/chromium/tools/oopif/OWNERS
@@ -0,0 +1,4 @@
+ajwong@chromium.org
+creis@chromium.org
+kenrb@chromium.org
+nasko@chromium.org
diff --git a/chromium/tools/oopif/iframe_server.py b/chromium/tools/oopif/iframe_server.py
new file mode 100644
index 00000000000..ace58422003
--- /dev/null
+++ b/chromium/tools/oopif/iframe_server.py
@@ -0,0 +1,224 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Test server for generating nested iframes with different sites.
+
+Very simple python server for creating a bunch of iframes. The page generation
+is randomized based on query parameters. See the __init__ function of the
+Params class for a description of the parameters.
+
+This server relies on gevent. On Ubuntu, install it via:
+
+ sudo apt-get install python-gevent
+
+Run the server using
+
+ python iframe_server.py
+
+To use the server, run chrome as follows:
+
+ google-chrome --host-resolver-rules='map *.invalid 127.0.0.1'
+
+Change 127.0.0.1 to be the IP of the machine this server is running on. Then
+in this chrome instance, navigate to any domain in .invalid
+(eg., http://1.invalid:8090) to run this test.
+
+"""
+
+import colorsys
+import copy
+import random
+import urllib
+import urlparse
+
+from gevent import pywsgi # pylint: disable=F0401
+
+MAIN_PAGE = """
+<html>
+ <head>
+ <style>
+ body {
+ background-color: %(color)s;
+ }
+ </style>
+ </head>
+ <body>
+ <center>
+ <h1><a href="%(url)s">%(site)s</a></h1>
+ <p><small>%(url)s</small>
+ </center>
+ <br />
+ %(iframe_html)s
+ </body>
+</html>
+"""
+
+IFRAME_FRAGMENT = """
+<iframe src="%(src)s" width="%(width)s" height="%(height)s">
+</iframe>
+"""
+
+class Params(object):
+ """Simple object for holding parameters"""
+ def __init__(self, query_dict):
+ # Basic params:
+ # nframes is how many frames per page.
+ # nsites is how many sites to random choose out of.
+ # depth is how deep to make the frame tree
+ # pattern specifies how the sites are layed out per depth. An empty string
+ # uses a random N = [0, nsites] each time to generate a N.invalid URL.
+ # Otherwise sepcify with single letters like 'ABCA' and frame
+ # A.invalid will embed B.invalid will embed C.invalid will embed A.
+ # jitter is the amount of randomness applied to nframes and nsites.
+ # Should be from [0,1]. 0.0 means no jitter.
+ # size_jitter is like jitter, but for width and height.
+ self.nframes = int(query_dict.get('nframes', [4] )[0])
+ self.nsites = int(query_dict.get('nsites', [10] )[0])
+ self.depth = int(query_dict.get('depth', [1] )[0])
+ self.jitter = float(query_dict.get('jitter', [0] )[0])
+ self.size_jitter = float(query_dict.get('size_jitter', [0.5] )[0])
+ self.pattern = query_dict.get('pattern', [''] )[0]
+ self.pattern_pos = int(query_dict.get('pattern_pos', [0] )[0])
+
+ # Size parameters. Values are percentages.
+ self.width = int(query_dict.get('width', [60])[0])
+ self.height = int(query_dict.get('height', [50])[0])
+
+ # Pass the random seed so our pages are reproduceable.
+ self.seed = int(query_dict.get('seed',
+ [random.randint(0, 2147483647)])[0])
+
+
+def get_site(urlpath):
+ """Takes a urlparse object and finds its approximate site.
+
+ Site is defined as registered domain name + scheme. We approximate
+ registered domain name by preserving the last 2 elements of the DNS
+ name. This breaks for domains like co.uk.
+ """
+ no_port = urlpath.netloc.split(':')[0]
+ host_parts = no_port.split('.')
+ site_host = '.'.join(host_parts[-2:])
+ return '%s://%s' % (urlpath.scheme, site_host)
+
+
+def generate_host(rand, params):
+ """Generates the host to be used as an iframes source.
+
+ Uses the .invalid domain to ensure DNS will not resolve to any real
+ address.
+ """
+ if params.pattern:
+ host = params.pattern[params.pattern_pos]
+ params.pattern_pos = (params.pattern_pos + 1) % len(params.pattern)
+ else:
+ host = rand.randint(1, apply_jitter(rand, params.jitter, params.nsites))
+ return '%s.invalid' % host
+
+
+def apply_jitter(rand, jitter, n):
+ """Reduce n by random amount from [0, jitter]. Ensures result is >=1."""
+ if jitter <= 0.001:
+ return n
+ v = n - int(n * rand.uniform(0, jitter))
+ if v:
+ return v
+ else:
+ return 1
+
+
+def get_color_for_site(site):
+ """Generate a stable (and pretty-ish) color for a site."""
+ val = hash(site)
+ # The constants below are arbitrary chosen emperically to look "pretty."
+ # HSV is used because it is easier to control the color than RGB.
+ # Reducing the H to 0.6 produces a good range of colors. Preserving
+ # > 0.5 saturation and value means the colors won't be too washed out.
+ h = (val % 100)/100.0 * 0.6
+ s = 1.0 - (int(val/100) % 100)/200.
+ v = 1.0 - (int(val/10000) % 100)/200.0
+ (r, g, b) = colorsys.hsv_to_rgb(h, s, v)
+ return 'rgb(%d, %d, %d)' % (int(r * 255), int(g * 255), int(b * 255))
+
+
+def make_src(scheme, netloc, path, params):
+ """Constructs the src url that will recreate the given params."""
+ if path == '/':
+ path = ''
+ return '%(scheme)s://%(netloc)s%(path)s?%(params)s' % {
+ 'scheme': scheme,
+ 'netloc': netloc,
+ 'path': path,
+ 'params': urllib.urlencode(params.__dict__),
+ }
+
+
+def make_iframe_html(urlpath, params):
+ """Produces the HTML fragment for the iframe."""
+ if (params.depth <= 0):
+ return ''
+ # Ensure a stable random number per iframe.
+ rand = random.Random()
+ rand.seed(params.seed)
+
+ netloc_paths = urlpath.netloc.split(':')
+ netloc_paths[0] = generate_host(rand, params)
+
+ width = apply_jitter(rand, params.size_jitter, params.width)
+ height = apply_jitter(rand, params.size_jitter, params.height)
+ iframe_params = {
+ 'src': make_src(urlpath.scheme, ':'.join(netloc_paths),
+ urlpath.path, params),
+ 'width': '%d%%' % width,
+ 'height': '%d%%' % height,
+ }
+ return IFRAME_FRAGMENT % iframe_params
+
+
+def create_html(environ):
+ """Creates the current HTML page. Also parses out query parameters."""
+ urlpath = urlparse.urlparse('%s://%s%s?%s' % (
+ environ['wsgi.url_scheme'],
+ environ['HTTP_HOST'],
+ environ['PATH_INFO'],
+ environ['QUERY_STRING']))
+ site = get_site(urlpath)
+ params = Params(urlparse.parse_qs(urlpath.query))
+
+ rand = random.Random()
+ rand.seed(params.seed)
+
+ iframe_htmls = []
+ for frame in xrange(0, apply_jitter(rand, params.jitter, params.nframes)):
+ # Copy current parameters into iframe and make modifications
+ # for the recursive generation.
+ iframe_params = copy.copy(params)
+ iframe_params.depth = params.depth - 1
+ # Base the new seed off the current seed, but have it skip enough that
+ # different frame trees are unlikely to collide. Numbers and skips
+ # not chosen in any scientific manner at all.
+ iframe_params.seed = params.seed + (frame + 1) * (
+ 1000000 + params.depth + 333)
+ iframe_htmls.append(make_iframe_html(urlpath, iframe_params))
+ template_params = dict(params.__dict__)
+ template_params.update({
+ 'color': get_color_for_site(site),
+ 'iframe_html': '\n'.join(iframe_htmls),
+ 'site': site,
+ 'url': make_src(urlpath.scheme, urlpath.netloc, urlpath.path, params),
+ })
+ return MAIN_PAGE % template_params
+
+
+def application(environ, start_response):
+ start_response('200 OK', [('Content-Type', 'text/html')])
+ if environ['PATH_INFO'] == '/favicon.ico':
+ yield ''
+ else:
+ yield create_html(environ)
+
+
+server = pywsgi.WSGIServer(('', 8090), application)
+
+server.serve_forever()
diff --git a/chromium/tools/page_cycler/acid3/LICENSE b/chromium/tools/page_cycler/acid3/LICENSE
new file mode 100644
index 00000000000..85265b0a8ea
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/LICENSE
@@ -0,0 +1 @@
+Public domain
diff --git a/chromium/tools/page_cycler/acid3/README.chromium b/chromium/tools/page_cycler/acid3/README.chromium
new file mode 100644
index 00000000000..5e482735a90
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/README.chromium
@@ -0,0 +1,14 @@
+Name: Acid3
+URL: http://acid3.acidtests.org
+License: Public domain
+License File: NOT_SHIPPED
+
+This is Chromium's copy of the Acid3 page layout tests.
+
+Originally obtained from the Web Standards Project on June
+19, 2009:
+
+Some changes have been made to Acid3 to permit it to run in
+an offline mode. The included JS test harness is copyright
+Google and licensed under the main Chromium license (see
+trunk/src/LICENSE).
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.css b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.css
new file mode 100644
index 00000000000..65c8751c34d
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.css
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML><html><head><title>FAIL</title><style>
+<!-- this file is sent as text/html, not text/css, which is why it is
+ called "empty.css" despite the following lines -->
+
+ body { background: white; color: black; }
+ h1 { color: red; }
+
+</style><body><h1>FAIL</h1></body></html> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.html b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.html
new file mode 100644
index 00000000000..734c5a1c09b
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.html
@@ -0,0 +1 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"><html><head><title></title></head><body></body></html> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.png b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.png
new file mode 100644
index 00000000000..fd5b91ea07b
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.png
Binary files differ
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.txt b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.txt
new file mode 100644
index 00000000000..957d6f8e582
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.txt
@@ -0,0 +1 @@
+<!DOCTYPE html><html><head><title>FAIL</title></head><body><p>FAIL</p><script>parent.notify("empty.txt")</script></body></html> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.xml b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.xml
new file mode 100644
index 00000000000..3f6063f4db6
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/empty.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- chase added XML 1.0 UTF-8 DTD -->
+<root>
+ <fail> This is an invalid byte in UTF-8: ¿ </fail>
+ <test/> <!-- shouldn't ever be parsed, as the parser should abort at the first sign of non-well-formedness -->
+</root>
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/favicon.ico b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/favicon.ico
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/favicon.ico
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/font.svg b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/font.svg
new file mode 100644
index 00000000000..13683d7d37b
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/font.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><font horiz-adv-x="500" id="mini"><font-face font-family="ACID3svgfont" units-per-em="4000" ascent="800" descent="-200" alphabetic="0"/><missing-glyph horiz-adv-x="10000" d="M0 0 4000 0"/><glyph unicode="a" glyph-name="a" horiz-adv-x="42"/><glyph unicode="b" glyph-name="b" horiz-adv-x="23"/><glyph unicode="c" glyph-name="c" horiz-adv-x="4711"/></font></defs></svg> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/font.ttf b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/font.ttf
new file mode 100644
index 00000000000..ac81cb03165
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/font.ttf
Binary files differ
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/head.js b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/head.js
new file mode 100644
index 00000000000..67c5d234269
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/head.js
@@ -0,0 +1,139 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+var __c = ""; // that's good enough for me.
+var __td;
+var __tf;
+var __tl;
+var __iterations;
+var __cycle;
+var __results = false;
+var __page;
+var __TIMEOUT = 15;
+function __get_cookie(name) {
+ var cookies = document.cookie.split("; ");
+ for (var i = 0; i < cookies.length; ++i) {
+ var t = cookies[i].split("=");
+ if (t[0] == name && t[1])
+ return t[1];
+ }
+ return "";
+}
+function __pages() { // fetch lazily
+ if (!("data" in this))
+ this.data = __get_cookie("__pc_pages").split(",");
+ return this.data;
+}
+function __get_timings() {
+ return __get_cookie("__pc_timings");
+}
+function __set_timings(timings) {
+ document.cookie = "__pc_timings=" + timings + "; path=/";
+}
+function __ontimeout() {
+ var doc;
+
+ // Call GC twice to cleanup JS heap before starting a new test.
+ if (window.gc) {
+ window.gc();
+ window.gc();
+ }
+
+ var ts = (new Date()).getTime();
+ var tlag = (ts - __te) - __TIMEOUT;
+ if (tlag > 0)
+ __tf = __tf + tlag;
+ if (__cycle == (__pages().length * __iterations)) {
+ document.cookie = "__pc_done=1; path=/";
+ doc = "../../common/report.html";
+ } else {
+ doc = "../" + __pages()[__page] + "/index.html"
+ }
+
+ var timings = __tl;
+ var oldTimings = __get_timings();
+ if (oldTimings != "") {
+ timings = oldTimings + "," + timings;
+ }
+ __set_timings(timings);
+
+ var url = doc + "?n=" + __iterations + "&i=" + __cycle + "&p=" + __page + "&ts=" + ts + "&td=" + __td + "&tf=" + __tf;
+ document.location.href = url;
+}
+
+function test_complete(errors, elapsed_time) {
+ if (__results)
+ return;
+ var unused = document.body.offsetHeight; // force layout
+
+ var ts = 0, td = 0, te = (new Date()).getTime(), tf = 0;
+
+ var s = document.location.search;
+ if (s) {
+ var params = s.substring(1).split('&');
+ for (var i = 0; i < params.length; ++i) {
+ var f = params[i].split('=');
+ switch (f[0]) {
+ case 'skip':
+ // No calculation, just viewing
+ return;
+ case 'n':
+ __iterations = f[1];
+ break;
+ case 'i':
+ __cycle = (f[1] - 0) + 1;
+ break;
+ case 'p':
+ __page = ((f[1] - 0) + 1) % __pages().length;
+ break;
+ case 'ts':
+ ts = (f[1] - 0);
+ break;
+ case 'td':
+ td = (f[1] - 0);
+ break;
+ case 'tf':
+ tf = (f[1] - 0);
+ break;
+ }
+ }
+ }
+ __tl = (te - ts);
+ __td = td + __tl;
+ __te = te;
+ __tf = tf; // record t-fudge
+
+ setTimeout("__ontimeout()", __TIMEOUT);
+}
+
+/*
+if (window.attachEvent)
+ window.attachEvent("onload", __onload);
+else
+ addEventListener("load", __onload, false);
+ */
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/index.html b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/index.html
new file mode 100644
index 00000000000..be41d540b5c
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/index.html
@@ -0,0 +1,3493 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <title>The Acid3 Test</title>
+ <script type="text/javascript">
+ var startTime = new Date();
+ </script>
+ <style type="text/css">
+
+ /* set some basic styles so that we can get reliably exact results */
+ * { margin: 0; border: 1px blue; padding: 0; border-spacing: 0; font: inherit; line-height: 1.2; color: inherit; background: transparent; }
+ :link, :visited { color: blue; }
+
+ /* header and general layout */
+ html { font: 20px Arial, sans-serif; border: 2cm solid gray; width: 32em; margin: 1em; }
+ :root { background: silver; color: black; border-width: 0 0.2em 0.2em 0; } /* left and top content edges: 1*20px = 20px */
+ body { padding: 2em 2em 0; background: url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAABGdBTUEAAK%2FINwWK6QAAAAlwSFlzAAAASAAAAEgARslrPgAAABtJREFUOMtj%2FM9APmCiQO%2Bo5lHNo5pHNVNBMwAinAEnIWw89gAAACJ6VFh0U29mdHdhcmUAAHjac0zJT0pV8MxNTE8NSk1MqQQAL5wF1K4MqU0AAAAASUVORK5CYII%3D) no-repeat 99.8392283% 1px white; border: solid 1px black; margin: -0.2em 0 0 -0.2em; } /* left and top content edges: 20px-0.2*20px+1px+2*20px = 57px */
+ h1:first-child { cursor: help; font-size: 5em; font-weight: bolder; margin-bottom: -0.4em; text-shadow: rgba(192, 192, 192, 1.0) 3px 3px; } /* (left:57px, top:57px) */
+ #result { font-weight: bolder; width: 5.68em; text-align: right; }
+ #result { font-size: 5em; margin: -2.19em 0 0; } /* (right:57px+5.2*5*20px = 577px, top:57px+1.2*5*20px-0.4*5*20px+1px+1*40px+1*40px+1px+2*40px+150px-2.19*5*20px = 230px) */
+ .hidden { visibility: hidden; }
+ #slash { color: red; color: hsla(0, 0%, 0%, 1.0); }
+ #instructions { margin-top: 0; font-size: 0.8em; color: gray; color: -acid3-bogus; height: 6.125em; } /* (left:57px, top:230px+1.2*5*20+0 = 350px) */
+ #instructions { margin-right: -20px; padding-right: 20px; background: url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAABGdBTUEAAK%2FINwWK6QAAAAlwSFlzAAAASAAAAEgARslrPgAAABtJREFUOMtj%2FM9APmCiQO%2Bo5lHNo5pHNVNBMwAinAEnIWw89gAAACJ6VFh0U29mdHdhcmUAAHjac0zJT0pV8MxNTE8NSk1MqQQAL5wF1K4MqU0AAAAASUVORK5CYII%3D) no-repeat top right; }
+ #instructions span { float: right; width: 20px; margin-right: -20px; background: white; height: 20px; }
+ @font-face { font-family: "AcidAhemTest"; src: url(font.ttf); }
+ map::after { position: absolute; top: 18px; left: 638px; content: "X"; background: fuchsia; color: white; font: 20px/1 AcidAhemTest; }
+ iframe { float: left; height: 0; width: 0; } /* hide iframes but don't make them display: none */
+ object { position: fixed; left: 130.5px; top: 84.3px; background: transparent; } /* show objects if they have content */
+ .removed { position: absolute; top: 80px; left: 380px; height: 100px; width: 100px; opacity: 0; }
+
+ /* set the line height of the line of coloured boxes so we can add them without the layout changing height */
+ .buckets { font: 0/0 Arial, sans-serif; }
+ .buckets { padding: 0 0 150px 3px; }
+
+ /* the next two rules give the six coloured blocks their default styles (they match the same elements); the third hides them */
+ :first-child + * .buckets p { display: inline-block; vertical-align: 2em; border: 2em dotted red; padding: 1.0em 0 1.0em 2em; }
+ * + * > * > p { margin: 0; border: 1px solid ! important; }
+ .z { visibility: hidden; } /* only matches the buckets with no score */
+
+ /* sizes for the six buckets */
+ #bucket1 { font-size: 20px; margin-left: 0.2em; padding-left: 1.3em; padding-right: 1.3em; margin-right: 0.0001px; }
+ #bucket2 { font-size: 24px; margin-left: 0.375em; padding-left: 30px; padding-right: 32px; margin-right: 2px; }
+ #bucket3 { font-size: 28px; margin-left: 8.9999px; padding-left: 17px; padding-right: 55px; margin-right: 12px; }
+ #bucket4 { font-size: 32px; margin-left: 0; padding-left: 84px; padding-right: 0; margin-right: 0; }
+ #bucket5 { font-size: 36px; margin-left: 13px; padding-left: 0; padding-right: 94px; margin-right: 25px; }
+ #bucket6 { font-size: 40px; margin-left: -10px; padding-left: 104px; padding-right: -10px; }
+
+ /* colours for them */
+ .z, .zP, .zPP, .zPPP, .zPPPP, .zPPPPP { background: black; }
+ .zPPPPPP, .zPPPPPPP, .zPPPPPPPP, .zPPPPPPPP, .zPPPPPPPPP,
+ .zPPPPPPPPPP { background: grey; }
+ .zPPPPPPPPPPP, .zPPPPPPPPPPPP, .zPPPPPPPPPPPPP,
+ .zPPPPPPPPPPPPPP, .zPPPPPPPPPPPPPPP { background: silver; }
+ #bucket1.zPPPPPPPPPPPPPPPP { background: red; }
+ #bucket2.zPPPPPPPPPPPPPPPP { background: orange; }
+ #bucket3.zPPPPPPPPPPPPPPPP { background: yellow; }
+ #bucket4.zPPPPPPPPPPPPPPPP { background: lime; }
+ #bucket5.zPPPPPPPPPPPPPPPP { background: blue; }
+ #bucket6.zPPPPPPPPPPPPPPPP { background: purple; }
+
+ /* The line-height for the .bucket div is worked out as follows:
+ *
+ * The div.bucket element has a line box with a few
+ * inline-blocks. Each inline-block consists of:
+ *
+ * 2.0em vertical-align from baseline to bottom of inline-block
+ * 1px bottom border
+ * 1.0em bottom padding
+ * 1.0em top padding
+ * 1px top border
+ *
+ * The biggest inline-block has font-size: 40px.
+ *
+ * Thus the distance from the baseline to the top of the biggest
+ * inline-block is (2em+1em+1em)*2em*20px+2px = 162px.
+ *
+ * The line box itself has no other contents, and its strut has zero
+ * height and there is no half-leading, so the height of the
+ * div.bucket is 162px.
+ *
+ * (Why use line-height:0 and font-size:0? Well:
+ *
+ * The div.bucket line box would have a height that is the maximum
+ * of the following two sums:
+ *
+ * 1: half-leading + font descent at 1em + font ascent at 1em + half-leading
+ * 2: half-leading + font descent at 1em + 162px
+ *
+ * Now the half-leading is (line-height - (font-ascent + font-descent))/2, so that is really:
+ *
+ * 1: (line-height - (font-ascent + font-descent))/2 + font descent + font ascent + (line-height - (font-ascent + font-descent))/2
+ * 2: (line-height - (font-ascent + font-descent))/2 + font descent + 162px
+ *
+ * Which simplify to:
+ *
+ * 1: line-height
+ * 2: line-height/2 + (font descent - font-ascent)/2 + 162px
+ *
+ * So if the following expression is true:
+ *
+ * line-height > line-height/2 + (font descent - font-ascent)/2 + 162px
+ *
+ * That is, if this is true:
+ *
+ * line-height > font descent - font-ascent + 324px
+ *
+ * ...then the line-height matters, otherwise the font does. Note
+ * that font descent - font-ascent will be in the region of
+ * 10px-30px (with Ahem, exactly 12px). However, if we make the
+ * line-height big, then the _positioning_ of the inline-blocks will
+ * depend on the font descent, since that is what will decide the
+ * distance from the bottom of the line box to the baseline of the
+ * block (since the baseline is set by the strut).
+ *
+ * However, in Acid2 a dependency on the font metrics was introduced
+ * and this caused all kinds of problems. And we can't require Ahem
+ * in the Acid tests, since it's unlikely most people will have it
+ * installed.
+ *
+ * What we want is for the font to not matter, and the baseline to
+ * be as high as possible. We can do that by saying that the font
+ * and the line-height are zero.
+ *
+ * One word of warning. If your browser has a minimum font size feature
+ * that forces font sizes up even when there is no text, you will need
+ * to disable it before running this test.
+ *
+ */
+
+ /* rules specific to the tests below */
+ #instructions:last-child { white-space: pre-wrap; white-space: x-bogus; }
+ #linktest:link { display: block; color: red; text-align: center; text-decoration: none; }
+ #linktest.pending, #linktest:visited { display: none; }
+ #\ { color: transparent; color: hsla(0, 0, 0, 1); position: fixed; top: 10px; left: 10px; font: 40px Arial, sans-serif; }
+ #\ #result, #\ #score { position: fixed; top: 10%; left: 10%; width: 4em; z-index: 1; color: yellow; font-size: 50px; background: fuchsia; border: solid 1em purple; }
+ </style>
+
+ <!-- part of the HTTP tests -->
+ <link rel="stylesheet" href="empty.css"><!-- text/html file (should be ignored, <h1> will go red if it isn't) -->
+
+ <!-- the next five script blocks are part of one of the tests -->
+ <script type="text/javascript">
+ var d1 = "fail";
+ var d2 = "fail";
+ var d3 = "fail";
+ var d4 = "fail";
+ var d5 = "fail";
+ </script>
+ <script type="text/javascript" src="data:text/javascript,d1%20%3D%20'one'%3B"></script>
+ <script type="text/javascript" src="data:text/javascript;base64,ZDIgPSAndHdvJzs%3D"></script>
+ <script type="text/javascript" src="data:text/javascript;base64,%5a%44%4d%67%50%53%41%6e%64%47%68%79%5a%57%55%6e%4f%77%3D%3D"></script>
+ <script type="text/javascript" src="data:text/javascript;base64,%20ZD%20Qg%0D%0APS%20An%20Zm91cic%0D%0A%207%20"></script>
+ <script type="text/javascript" src="data:text/javascript,d5%20%3D%20'five%5Cu0027s'%3B"></script>
+
+ <!-- part of the JS regexp and \0 value tests test -->
+ <script type="text/javascript">
+ var nullInRegexpArgumentResult = 0 < /script/.test('\0script') ? "passed" : "failed";
+ </script>
+
+ <!-- main test body -->
+ <script type="text/javascript">
+ var notifications = {};
+ function notify(file) {
+ // used in cross-file tests
+ notifications[file] = 1;
+ }
+ function fail(message) {
+ throw { message: message };
+ }
+ function assert(condition, message) {
+ if (!condition)
+ fail(message);
+ }
+ function assertEquals(expression, value, message) {
+ if (expression != value) {
+ expression = (""+expression).replace(/[\r\n]+/g, "\\n");
+ value = (""+value).replace(/\r?\n/g, "\\n");
+ fail("expected '" + value + "' but got '" + expression + "' - " + message);
+ }
+ }
+ function getTestDocument() {
+ var iframe = document.getElementById("selectors");
+ var doc = iframe.contentDocument;
+ //alert(doc);
+ for (var i = doc.documentElement.childNodes.length-1; i >= 0; i -= 1) {
+ doc.documentElement.removeChild(doc.documentElement.childNodes[i]);
+ }
+ doc.documentElement.appendChild(doc.createElement('head'));
+ doc.documentElement.firstChild.appendChild(doc.createElement('title'));
+ doc.documentElement.appendChild(doc.createElement('body'));
+ return doc;
+ }
+ function selectorTest(tester) {
+ var doc = getTestDocument();
+ var style = doc.createElement('style');
+ style.appendChild(doc.createTextNode("* { z-index: 0; position: absolute; }\n"));
+ doc.documentElement.firstChild.appendChild(style);
+ var ruleCount = 0;
+ tester(doc, function (selector) {
+ ruleCount += 1;
+ style.appendChild(doc.createTextNode(selector + " { z-index: " + ruleCount + "; }\n"));
+ return ruleCount;
+ }, function(node, rule, message) {
+ var value = doc.defaultView.getComputedStyle(node, "").zIndex;
+ assert(value != 'auto', "underlying problems prevent this test from running properly");
+ assertEquals(value, rule, message);
+ });
+ }
+ var kungFuDeathGrip = null; // used to hold things from test to test
+ var tests = [
+
+ // there are 6 buckets with 16 tests each, plus four special tests (0, 97, 98, and 99).
+
+ // Remove the "JS required" message and the <script> element in the <body>
+ function () {
+ // test 0: whether removing an element that is the last child correctly recomputes styles for the new last child
+ // also tests support for getComputedStyle, :last-child, pre-wrap, removing a <script> element
+ // removing script:
+ var scripts = document.getElementsByTagName('script');
+ document.body.removeChild(scripts[scripts.length-1]);
+ // removing last child:
+ var last = document.getElementById('remove-last-child-test');
+ var penultimate = last.previousSibling; // this should be the whitespace node
+ penultimate = penultimate.previousSibling; // this should now be the actual penultimate element
+ last.parentNode.removeChild(last);
+ assertEquals(document.defaultView.getComputedStyle(penultimate, '').whiteSpace, 'pre-wrap', "found unexpected computed style");
+ return 7;
+ },
+
+ // bucket 1: DOM Traversal, DOM Range, HTTP
+ // DOM Traversal
+ function () {
+ // test 1: NodeFilters and Exceptions
+ var doc = getTestDocument(); // looks like <!DOCTYPE><html><head><title/><\head><body/><\html> (the '\'s are to avoid validation errors)
+ var iteration = 0;
+ var exception = "Roses";
+ var test = function(node) {
+ iteration += 1;
+ switch (iteration) {
+ case 1: case 3: case 4: case 6: case 7: case 8: case 9: case 14: case 15: throw exception;
+ case 2: case 5: case 10: case 11: case 12: case 13: return true; // ToNumber(true) => 1
+ default: throw 0;
+ };
+ };
+ var check = function(o, method) {
+ var ok = false;
+ try {
+ o[method]();
+ } catch (e) {
+ if (e === exception)
+ ok = true;
+ }
+ assert(ok, "method " + o + "." + method + "() didn't forward exception");
+ };
+ var i = doc.createNodeIterator(doc.documentElement, 0xFFFFFFFF, test, true);
+ check(i, "nextNode"); // 1
+ assertEquals(i.nextNode(), doc.documentElement, "i.nextNode() didn't return the right node"); // 2
+ check(i, "previousNode"); // 3
+ var w = document.createTreeWalker(doc.documentElement, 0xFFFFFFFF, test, true);
+ check(w, "nextNode"); // 4
+ assertEquals(w.nextNode(), doc.documentElement.firstChild, "w.nextNode() didn't return the right node"); // 5
+ check(w, "previousNode"); // 6
+ check(w, "firstChild"); // 7
+ check(w, "lastChild"); // 8
+ check(w, "nextSibling"); // 9
+ assertEquals(iteration, 9, "iterations went wrong");
+ assertEquals(w.previousSibling(), null, "w.previousSibling() didn't return the right node"); // doesn't call filter
+ assertEquals(iteration, 9, "filter called incorrectly for previousSibling()");
+ assertEquals(w.lastChild(), doc.getElementsByTagName('title')[0], "w.lastChild() didn't return the right node"); // 10
+ assertEquals(w.nextSibling(), null, "w.nextSibling() didn't return the right node"); // 11 (filter called on parent, to see if it's included, otherwise it could skip that and find a nextsibling elsewhere)
+ assertEquals(iteration, 11, "filter called incorrectly for nextSibling()");
+ assertEquals(w.parentNode(), doc.documentElement.firstChild, "w.parentNode() didn't return the right node"); // 12
+ assertEquals(w.nextSibling(), doc.documentElement.lastChild, "w.nextSibling() didn't return the right node"); // 13
+ check(w, "previousSibling"); // 14
+ check(w, "parentNode"); // 15
+ return 1;
+ },
+ function () {
+ // test 2: Removing nodes during iteration
+ var count = 0;
+ var expect = function(n, node1, node2) {
+ count += 1;
+ assert(n == count, "reached expectation " + n + " when expecting expectation " + count);
+ assertEquals(node1, node2, "expectation " + count + " failed");
+ };
+ var doc = getTestDocument();
+ var t1 = doc.body.appendChild(doc.createElement('t1'));
+ var t2 = doc.body.appendChild(doc.createElement('t2'));
+ var t3 = doc.body.appendChild(doc.createElement('t3'));
+ var t4 = doc.body.appendChild(doc.createElement('t4'));
+ var callCount = 0;
+ var filterFunctions = [
+ function (node) { expect(1, node, doc.body); return true; }, // filter 0
+ function (node) { expect(3, node, t1); return true; }, // filter 1
+ function (node) { expect(5, node, t2); return true; }, // filter 2
+ function (node) { expect(7, node, t3); doc.body.removeChild(t4); return true; }, // filter 3
+ function (node) { expect(9, node, t4); return true; }, // filter 4
+ function (node) { expect(11, node, t4); doc.body.removeChild(t4); return 2 /* REJECT */; }, // filter 5
+ function (node) { expect(12, node, t3); return true; }, // filter 6
+ function (node) { expect(14, node, t2); doc.body.removeChild(t2); return true; }, // filter 7
+ function (node) { expect(16, node, t1); return true; }, // filter 8
+ ];
+ var i = doc.createNodeIterator(doc.documentElement.lastChild, 0xFFFFFFFF, function (node) { return filterFunctions[callCount++](node); }, true);
+ // * B 1 2 3 4
+ expect(2, i.nextNode(), doc.body); // filter 0
+ // [B] * 1 2 3 4
+ expect(4, i.nextNode(), t1); // filter 1
+ // B [1] * 2 3 4
+ expect(6, i.nextNode(), t2); // filter 2
+ // B 1 [2] * 3 4
+ expect(8, i.nextNode(), t3); // filter 3
+ // B 1 2 [3] *
+ doc.body.appendChild(t4);
+ // B 1 2 [3] * 4
+ expect(10, i.nextNode(), t4); // filter 4
+ // B 1 2 3 [4] *
+ expect(13, i.previousNode(), t3); // filters 5, 6
+ // B 1 2 3 * (4) // filter 5
+ // B 1 2 [3] * // between 5 and 6
+ // B 1 2 * (3) // filter 6
+ // B 1 2 * [3]
+ expect(15, i.previousNode(), t2); // filter 7
+ // B 1 * (2) [3]
+ // -- spec says "For instance, if a NodeFilter removes a node
+ // from a document, it can still accept the node, which
+ // means that the node may be returned by the NodeIterator
+ // or TreeWalker even though it is no longer in the subtree
+ // being traversed."
+ // -- but it also says "If changes to the iterated list do not
+ // remove the reference node, they do not affect the state
+ // of the NodeIterator."
+ // B 1 * [3]
+ expect(17, i.previousNode(), t1); // filter 8
+ // B [1] * 3
+ return 1;
+ },
+ function () {
+ // test 3: the infinite iterator
+ var doc = getTestDocument();
+ for (var i = 0; i < 5; i += 1) {
+ doc.body.appendChild(doc.createElement('section'));
+ doc.body.lastChild.title = i;
+ }
+ var count = 0;
+ var test = function() {
+ if (count > 3 && count < 12)
+ doc.body.appendChild(doc.body.firstChild);
+ count += 1;
+ return (count % 2 == 0) ? 1 : 2;
+ };
+ var i = doc.createNodeIterator(doc.body, 0xFFFFFFFF, test, true);
+ assertEquals(i.nextNode().title, "0", "failure 1");
+ assertEquals(i.nextNode().title, "2", "failure 2");
+ assertEquals(i.nextNode().title, "4", "failure 3");
+ assertEquals(i.nextNode().title, "1", "failure 4");
+ assertEquals(i.nextNode().title, "3", "failure 5");
+ assertEquals(i.nextNode().title, "0", "failure 6");
+ assertEquals(i.nextNode().title, "2", "failure 7");
+ assertEquals(i.nextNode(), null, "failure 8");
+ return 1;
+ },
+ function () {
+ // test 4: ignoring whitespace text nodes with node iterators
+ var count = 0;
+ var expect = function(node1, node2) {
+ count += 1;
+ assertEquals(node1, node2, "expectation " + count + " failed");
+ };
+ var allButWS = function (node) {
+ if (node.nodeType == 3 && node.data.match(/^\s*$/))
+ return 2;
+ return 1;
+ };
+ var i = document.createNodeIterator(document.body, 0x01 | 0x04 | 0x08 | 0x10 | 0x20, allButWS, true);
+ // now walk the document body and make sure everything is in the right place
+ expect(i.nextNode(), document.body); // 1
+ expect(i.nextNode(), document.getElementsByTagName('h1')[0]);
+ expect(i.nextNode(), document.getElementsByTagName('h1')[0].firstChild);
+ expect(i.nextNode(), document.getElementsByTagName('div')[0]);
+ expect(i.nextNode(), document.getElementById('bucket1'));
+ expect(i.nextNode(), document.getElementById('bucket2'));
+ expect(i.nextNode(), document.getElementById('bucket3'));
+ expect(i.nextNode(), document.getElementById('bucket4'));
+ expect(i.nextNode(), document.getElementById('bucket5'));
+ expect(i.nextNode(), document.getElementById('bucket6')); // 10
+ expect(i.nextNode(), document.getElementById('result'));
+ expect(i.nextNode(), document.getElementById('score'));
+ expect(i.nextNode(), document.getElementById('score').firstChild);
+ expect(i.nextNode(), document.getElementById('slash'));
+ expect(i.nextNode(), document.getElementById('slash').firstChild);
+ expect(i.nextNode(), document.getElementById('slash').nextSibling);
+ expect(i.nextNode(), document.getElementById('slash').nextSibling.firstChild);
+ expect(i.nextNode(), document.getElementsByTagName('map')[0]);
+ expect(i.nextNode(), document.getElementsByTagName('area')[0]);
+ expect(i.nextNode(), document.getElementsByTagName('iframe')[0]); // 20
+ expect(i.nextNode(), document.getElementsByTagName('iframe')[0].firstChild);
+ expect(i.nextNode(), document.getElementsByTagName('iframe')[1]);
+ expect(i.nextNode(), document.getElementsByTagName('iframe')[1].firstChild);
+ expect(i.nextNode(), document.getElementsByTagName('iframe')[2]);
+ expect(i.nextNode(), document.forms[0]);
+ expect(i.nextNode(), document.forms.form.elements[0]);
+ expect(i.nextNode(), document.getElementsByTagName('table')[0]);
+ expect(i.nextNode(), document.getElementsByTagName('tbody')[0]);
+ expect(i.nextNode(), document.getElementsByTagName('tr')[0]);
+ expect(i.nextNode(), document.getElementsByTagName('td')[0]);
+ expect(i.nextNode(), document.getElementsByTagName('td')[0].getElementsByTagName('p')[0]);
+ expect(i.nextNode(), document.getElementById('instructions'));
+ expect(i.nextNode(), document.getElementById('instructions').firstChild);
+ expect(i.nextNode().nodeName, "SPAN");
+ expect(i.nextNode().nodeName, "#text");
+ expect(i.nextNode(), document.links[1]);
+ expect(i.nextNode(), document.links[1].firstChild);
+ expect(i.nextNode(), document.getElementById('instructions').lastChild);
+ expect(i.nextNode(), null);
+ // walk it backwards for good measure
+ expect(i.previousNode(), document.getElementById('instructions').lastChild);
+ expect(i.previousNode(), document.links[1].firstChild);
+ expect(i.previousNode(), document.links[1]);
+ expect(i.previousNode().nodeName, "#text");
+ expect(i.previousNode().nodeName, "SPAN");
+ expect(i.previousNode(), document.getElementById('instructions').firstChild);
+ expect(i.previousNode(), document.getElementById('instructions'));
+ expect(i.previousNode(), document.getElementsByTagName('td')[0].getElementsByTagName('p')[0]);
+ expect(i.previousNode(), document.getElementsByTagName('td')[0]);
+ expect(i.previousNode(), document.getElementsByTagName('tr')[0]);
+ expect(i.previousNode(), document.getElementsByTagName('tbody')[0]);
+ expect(i.previousNode(), document.getElementsByTagName('table')[0]);
+ expect(i.previousNode(), document.forms.form.elements[0]);
+ expect(i.previousNode(), document.forms[0]);
+ expect(i.previousNode(), document.getElementsByTagName('iframe')[2]);
+ expect(i.previousNode(), document.getElementsByTagName('iframe')[1].firstChild);
+ expect(i.previousNode(), document.getElementsByTagName('iframe')[1]);
+ expect(i.previousNode(), document.getElementsByTagName('iframe')[0].firstChild);
+ expect(i.previousNode(), document.getElementsByTagName('iframe')[0]); // 20
+ expect(i.previousNode(), document.getElementsByTagName('area')[0]);
+ expect(i.previousNode(), document.getElementsByTagName('map')[0]);
+ expect(i.previousNode(), document.getElementById('slash').nextSibling.firstChild);
+ expect(i.previousNode(), document.getElementById('slash').nextSibling);
+ expect(i.previousNode(), document.getElementById('slash').firstChild);
+ expect(i.previousNode(), document.getElementById('slash'));
+ expect(i.previousNode(), document.getElementById('score').firstChild);
+ expect(i.previousNode(), document.getElementById('score'));
+ expect(i.previousNode(), document.getElementById('result'));
+ expect(i.previousNode(), document.getElementById('bucket6'));
+ expect(i.previousNode(), document.getElementById('bucket5'));
+ expect(i.previousNode(), document.getElementById('bucket4'));
+ expect(i.previousNode(), document.getElementById('bucket3'));
+ expect(i.previousNode(), document.getElementById('bucket2'));
+ expect(i.previousNode(), document.getElementById('bucket1'));
+ expect(i.previousNode(), document.getElementsByTagName('div')[0]);
+ expect(i.previousNode(), document.getElementsByTagName('h1')[0].firstChild);
+ expect(i.previousNode(), document.getElementsByTagName('h1')[0]);
+ expect(i.previousNode(), document.body);
+ expect(i.previousNode(), null);
+ return 1;
+ },
+ function () {
+ // test 5: ignoring whitespace text nodes with tree walkers
+ var count = 0;
+ var expect = function(node1, node2) {
+ count += 1;
+ assertEquals(node1, node2, "expectation " + count + " failed");
+ };
+ var allButWS = function (node) {
+ if (node.nodeType == 3 && node.data.match(/^\s*$/))
+ return 3;
+ return 1;
+ };
+ var w = document.createTreeWalker(document.body, 0x01 | 0x04 | 0x08 | 0x10 | 0x20, allButWS, true);
+ expect(w.currentNode, document.body);
+ expect(w.parentNode(), null);
+ expect(w.currentNode, document.body);
+ expect(w.firstChild(), document.getElementsByTagName('h1')[0]);
+ expect(w.firstChild().nodeType, 3);
+ expect(w.parentNode(), document.getElementsByTagName('h1')[0]);
+ expect(w.nextSibling().previousSibling.nodeType, 3);
+ expect(w.nextSibling(), document.getElementsByTagName('p')[6]);
+ expect(w.nextSibling(), document.getElementsByTagName('map')[0]);
+ expect(w.lastChild(), document.getElementsByTagName('table')[0]);
+ expect(w.lastChild(), document.getElementsByTagName('tbody')[0]);
+ expect(w.nextNode(), document.getElementsByTagName('tr')[0]);
+ expect(w.nextNode(), document.getElementsByTagName('td')[0]);
+ expect(w.nextNode(), document.getElementsByTagName('p')[7]);
+ expect(w.nextNode(), document.getElementsByTagName('p')[8]); // instructions.inc paragraph
+ expect(w.previousSibling(), document.getElementsByTagName('map')[0]);
+ expect(w.previousNode().data, "100");
+ expect(w.parentNode().tagName, "SPAN");
+ expect(w.parentNode(), document.getElementById('result'));
+ expect(w.parentNode(), document.body);
+ expect(w.lastChild().id, "instructions");
+ expect(w.lastChild().data.substr(0,1), ".");
+ expect(w.previousNode(), document.links[1].firstChild);
+ return 1;
+ },
+ function () {
+ // test 6: walking outside a tree
+ var doc = getTestDocument();
+ var p = doc.createElement('p');
+ doc.body.appendChild(p);
+ var b = doc.body;
+ var w = document.createTreeWalker(b, 0xFFFFFFFF, null, true);
+ assertEquals(w.currentNode, b, "basic use of TreeWalker failed: currentNode");
+ assertEquals(w.lastChild(), p, "basic use of TreeWalker failed: lastChild()");
+ assertEquals(w.previousNode(), b, "basic use of TreeWalker failed: previousNode()");
+ doc.documentElement.removeChild(b);
+ assertEquals(w.lastChild(), p, "TreeWalker failed after removing the current node from the tree");
+ assertEquals(w.nextNode(), null, "failed to walk into the end of a subtree");
+ doc.documentElement.appendChild(p);
+ assertEquals(w.previousNode(), doc.getElementsByTagName('title')[0], "failed to handle regrafting correctly");
+ p.appendChild(b);
+ assertEquals(w.nextNode(), p, "couldn't retrace steps");
+ assertEquals(w.nextNode(), b, "couldn't step back into root");
+ assertEquals(w.previousNode(), null, "root didn't retake its rootish position");
+ return 1;
+ },
+
+ // DOM Range
+ function () {
+ // test 7: basic ranges tests
+ var r = document.createRange();
+ assert(r, "range not created");
+ assert(r.collapsed, "new range wasn't collapsed");
+ assertEquals(r.commonAncestorContainer, document, "new range's common ancestor wasn't the document");
+ assertEquals(r.startContainer, document, "new range's start container wasn't the document");
+ assertEquals(r.startOffset, 0, "new range's start offset wasn't zero");
+ assertEquals(r.endContainer, document, "new range's end container wasn't the document");
+ assertEquals(r.endOffset, 0, "new range's end offset wasn't zero");
+ assert(r.cloneContents(), "cloneContents() didn't return an object");
+ assertEquals(r.cloneContents().childNodes.length, 0, "nothing cloned was more than nothing");
+ assertEquals(r.cloneRange().toString(), "", "nothing cloned stringifed to more than nothing");
+ r.collapse(true); // no effect
+ assertEquals(r.compareBoundaryPoints(r.START_TO_END, r.cloneRange()), 0, "starting boundary point of range wasn't the same as the end boundary point of the clone range");
+ r.deleteContents(); // no effect
+ assertEquals(r.extractContents().childNodes.length, 0, "nothing removed was more than nothing");
+ var endOffset = r.endOffset;
+ r.insertNode(document.createComment("commented inserted to test ranges"));
+ r.setEnd(r.endContainer, endOffset + 1); // added to work around spec bug that smaug is blocking the errata for
+ try {
+ assert(!r.collapsed, "range with inserted comment is collapsed");
+ assertEquals(r.commonAncestorContainer, document, "range with inserted comment has common ancestor that isn't the document");
+ assertEquals(r.startContainer, document, "range with inserted comment has start container that isn't the document");
+ assertEquals(r.startOffset, 0, "range with inserted comment has start offset that isn't zero");
+ assertEquals(r.endContainer, document, "range with inserted comment has end container that isn't the document");
+ assertEquals(r.endOffset, 1, "range with inserted comment has end offset that isn't after the comment");
+ } finally {
+ document.removeChild(document.firstChild);
+ }
+ return 1;
+ },
+ function () {
+ // test 8: moving boundary points
+ var doc = document.implementation.createDocument(null, null, null);
+ var root = doc.createElement("root");
+ doc.appendChild(root);
+ var e1 = doc.createElement("e");
+ root.appendChild(e1);
+ var e2 = doc.createElement("e");
+ root.appendChild(e2);
+ var e3 = doc.createElement("e");
+ root.appendChild(e3);
+ var r = doc.createRange();
+ r.setStart(e2, 0);
+ r.setEnd(e3, 0);
+ assert(!r.collapsed, "non-empty range claims to be collapsed");
+ r.setEnd(e1, 0);
+ assert(r.collapsed, "setEnd() didn't collapse the range");
+ assertEquals(r.startContainer, e1, "startContainer is wrong after setEnd()");
+ assertEquals(r.startOffset, 0, "startOffset is wrong after setEnd()");
+ assertEquals(r.endContainer, e1, "endContainer is wrong after setEnd()");
+ assertEquals(r.endOffset, 0, "endOffset is wrong after setEnd()");
+ r.setStartBefore(e3);
+ assert(r.collapsed, "setStartBefore() didn't collapse the range");
+ assertEquals(r.startContainer, root, "startContainer is wrong after setStartBefore()");
+ assertEquals(r.startOffset, 2, "startOffset is wrong after setStartBefore()");
+ assertEquals(r.endContainer, root, "endContainer is wrong after setStartBefore()");
+ assertEquals(r.endOffset, 2, "endOffset is wrong after setStartBefore()");
+ r.setEndAfter(root);
+ assert(!r.collapsed, "setEndAfter() didn't uncollapse the range");
+ assertEquals(r.startContainer, root, "startContainer is wrong after setEndAfter()");
+ assertEquals(r.startOffset, 2, "startOffset is wrong after setEndAfter()");
+ assertEquals(r.endContainer, doc, "endContainer is wrong after setEndAfter()");
+ assertEquals(r.endOffset, 1, "endOffset is wrong after setEndAfter()");
+ r.setStartAfter(e2);
+ assert(!r.collapsed, "setStartAfter() collapsed the range");
+ assertEquals(r.startContainer, root, "startContainer is wrong after setStartAfter()");
+ assertEquals(r.startOffset, 2, "startOffset is wrong after setStartAfter()");
+ assertEquals(r.endContainer, doc, "endContainer is wrong after setStartAfter()");
+ assertEquals(r.endOffset, 1, "endOffset is wrong after setStartAfter()");
+ var msg = '';
+ try {
+ r.setEndBefore(doc);
+ msg = "no exception thrown for setEndBefore() the document itself";
+ } catch (e) {
+ if (e.BAD_BOUNDARYPOINTS_ERR != 1)
+ msg = 'not a RangeException';
+ else if (e.INVALID_NODE_TYPE_ERR != 2)
+ msg = 'RangeException has no INVALID_NODE_TYPE_ERR';
+ else if ("INVALID_ACCESS_ERR" in e)
+ msg = 'RangeException has DOMException constants';
+ else if (e.code != e.INVALID_NODE_TYPE_ERR)
+ msg = 'wrong exception raised from setEndBefore()';
+ }
+ assert(msg == "", msg);
+ assert(!r.collapsed, "setEndBefore() collapsed the range");
+ assertEquals(r.startContainer, root, "startContainer is wrong after setEndBefore()");
+ assertEquals(r.startOffset, 2, "startOffset is wrong after setEndBefore()");
+ assertEquals(r.endContainer, doc, "endContainer is wrong after setEndBefore()");
+ assertEquals(r.endOffset, 1, "endOffset is wrong after setEndBefore()");
+ r.collapse(false);
+ assert(r.collapsed, "collapse() collapsed the range");
+ assertEquals(r.startContainer, doc, "startContainer is wrong after collapse()");
+ assertEquals(r.startOffset, 1, "startOffset is wrong after collapse()");
+ assertEquals(r.endContainer, doc, "endContainer is wrong after collapse()");
+ assertEquals(r.endOffset, 1, "endOffset is wrong after collapse()");
+ r.selectNodeContents(root);
+ assert(!r.collapsed, "collapsed is wrong after selectNodeContents()");
+ assertEquals(r.startContainer, root, "startContainer is wrong after selectNodeContents()");
+ assertEquals(r.startOffset, 0, "startOffset is wrong after selectNodeContents()");
+ assertEquals(r.endContainer, root, "endContainer is wrong after selectNodeContents()");
+ assertEquals(r.endOffset, 3, "endOffset is wrong after selectNodeContents()");
+ r.selectNode(e2);
+ assert(!r.collapsed, "collapsed is wrong after selectNode()");
+ assertEquals(r.startContainer, root, "startContainer is wrong after selectNode()");
+ assertEquals(r.startOffset, 1, "startOffset is wrong after selectNode()");
+ assertEquals(r.endContainer, root, "endContainer is wrong after selectNode()");
+ assertEquals(r.endOffset, 2, "endOffset is wrong after selectNode()");
+ return 1;
+ },
+ function () {
+ // test 9: extractContents() in a Document
+ var doc = getTestDocument();
+ var h1 = doc.createElement('h1');
+ var t1 = doc.createTextNode('Hello ');
+ h1.appendChild(t1);
+ var em = doc.createElement('em');
+ var t2 = doc.createTextNode('Wonderful');
+ em.appendChild(t2);
+ h1.appendChild(em);
+ var t3 = doc.createTextNode(' Kitty');
+ h1.appendChild(t3);
+ doc.body.appendChild(h1);
+ var p = doc.createElement('p');
+ var t4 = doc.createTextNode('How are you?');
+ p.appendChild(t4);
+ doc.body.appendChild(p);
+ var r = doc.createRange();
+ r.selectNodeContents(doc);
+ assertEquals(r.toString(), "Hello Wonderful KittyHow are you?", "toString() on range selecting Document gave wrong output");
+ r.setStart(t2, 6);
+ r.setEnd(p, 0);
+ // <body><h1>Hello <em>Wonder ful<\em> Kitty<\h1><p> How are you?<\p><\body> (the '\'s are to avoid validation errors)
+ // ^----------------------^
+ assertEquals(r.toString(), "ful Kitty", "toString() on range crossing text nodes gave wrong output");
+ var f = r.extractContents();
+ // <h1><em>ful<\em> Kitty<\h1><p><\p>
+ // ccccccccccccccccMMMMMMcccccccccccc
+ assertEquals(f.nodeType, 11, "failure 1");
+ assert(f.childNodes.length == 2, "expected two children in the result, got " + f.childNodes.length);
+ assertEquals(f.childNodes[0].tagName, "H1", "failure 3");
+ assert(f.childNodes[0] != h1, "failure 4");
+ assertEquals(f.childNodes[0].childNodes.length, 2, "failure 5");
+ assertEquals(f.childNodes[0].childNodes[0].tagName, "EM", "failure 6");
+ assert(f.childNodes[0].childNodes[0] != em, "failure 7");
+ assertEquals(f.childNodes[0].childNodes[0].childNodes.length, 1, "failure 8");
+ assertEquals(f.childNodes[0].childNodes[0].childNodes[0].data, "ful", "failure 9");
+ assert(f.childNodes[0].childNodes[0].childNodes[0] != t2, "failure 10");
+ assertEquals(f.childNodes[0].childNodes[1], t3, "failure 11");
+ assert(f.childNodes[0].childNodes[1] != em, "failure 12");
+ assertEquals(f.childNodes[1].tagName, "P", "failure 13");
+ assertEquals(f.childNodes[1].childNodes.length, 0, "failure 14");
+ assert(f.childNodes[1] != p, "failure 15");
+ return 1;
+ },
+ function () {
+ // test 10: Ranges and Attribute Nodes
+ var e = document.getElementById('result');
+ if (!e.getAttributeNode)
+ return 1; // support for attribute nodes is optional in Acid3, because attribute nodes might be removed from DOM Core in the future.
+ // however, if they're supported, they'd better work:
+ var a = e.getAttributeNode('id');
+ var r = document.createRange();
+ r.selectNodeContents(a);
+ assertEquals(r.toString(), "result", "toString() didn't work for attribute node");
+ var t = a.firstChild;
+ var f = r.extractContents();
+ assertEquals(f.childNodes.length, 1, "extracted contents were the wrong length");
+ assertEquals(f.childNodes[0], t, "extracted contents were the wrong node");
+ assertEquals(t.textContent, 'result', "extracted contents didn't match old attribute value");
+ assertEquals(r.toString(), '', "extracting contents didn't empty attribute value; instead equals '" + r.toString() + "'");
+ assertEquals(e.getAttribute('id'), '', "extracting contents didn't change 'id' attribute to empty string");
+ e.id = 'result';
+ return 1;
+ },
+ function () {
+ // test 11: Ranges and Comments
+ var msg;
+ var doc = getTestDocument();
+ var c1 = doc.createComment("11111");
+ doc.appendChild(c1);
+ var r = doc.createRange();
+ r.selectNode(c1);
+ msg = 'wrong exception raised';
+ try {
+ r.surroundContents(doc.createElement('a'));
+ msg = 'no exception raised';
+ } catch (e) {
+ if ('code' in e)
+ msg += '; code = ' + e.code;
+ if (e.code == 3)
+ msg = '';
+ }
+ assert(msg == '', "when inserting <a> into Document with another child: " + msg);
+ var c2 = doc.createComment("22222");
+ doc.body.appendChild(c2);
+ var c3 = doc.createComment("33333");
+ doc.body.appendChild(c3);
+ r.setStart(c2, 2);
+ r.setEnd(c3, 3);
+ var msg = 'wrong exception raised';
+ try {
+ r.surroundContents(doc.createElement('a'));
+ msg = 'no exception raised';
+ } catch (e) {
+ if ('code' in e)
+ msg += '; code = ' + e.code;
+ if (e.code == 1)
+ msg = '';
+ }
+ assert(msg == '', "when trying to surround two halves of comment: " + msg);
+ assertEquals(r.toString(), "", "comments returned text");
+ return 1;
+ },
+ function () {
+ // test 12: Ranges under mutations: insertion into text nodes
+ var doc = getTestDocument();
+ var p = doc.createElement('p');
+ var t1 = doc.createTextNode('12345');
+ p.appendChild(t1);
+ var t2 = doc.createTextNode('ABCDE');
+ p.appendChild(t2);
+ doc.body.appendChild(p);
+ var r = doc.createRange();
+ r.setStart(p.firstChild, 2);
+ r.setEnd(p.firstChild, 3);
+ assert(!r.collapsed, "collapsed is wrong at start");
+ assertEquals(r.commonAncestorContainer, p.firstChild, "commonAncestorContainer is wrong at start");
+ assertEquals(r.startContainer, p.firstChild, "startContainer is wrong at start");
+ assertEquals(r.startOffset, 2, "startOffset is wrong at start");
+ assertEquals(r.endContainer, p.firstChild, "endContainer is wrong at start");
+ assertEquals(r.endOffset, 3, "endOffset is wrong at start");
+ assertEquals(r.toString(), "3", "range in text node stringification failed");
+ r.insertNode(p.lastChild);
+ assertEquals(p.childNodes.length, 3, "insertion of node made wrong number of child nodes");
+ assertEquals(p.childNodes[0], t1, "unexpected first text node");
+ assertEquals(p.childNodes[0].data, "12", "unexpected first text node contents");
+ assertEquals(p.childNodes[1], t2, "unexpected second text node");
+ assertEquals(p.childNodes[1].data, "ABCDE", "unexpected second text node");
+ assertEquals(p.childNodes[2].data, "345", "unexpected third text node contents");
+ // The spec is very vague about what exactly should be in the range afterwards:
+ // the insertion results in a splitText(), which it says is equivalent to a truncation
+ // followed by an insertion, but it doesn't say what to do when you have a truncation,
+ // so we don't know where either the start or the end boundary points end up.
+ // The spec really should be clarified for how to handle splitText() and
+ // text node truncation in general
+ // The only thing that seems very clear is that the inserted text node should
+ // be in the range, and it has to be at the start, since insertion always puts it at
+ // the start.
+ assert(!r.collapsed, "collapsed is wrong after insertion");
+ assert(r.toString().match(/^ABCDE/), "range didn't start with the expected text; range stringified to '" + r.toString() + "'");
+ return 1;
+ },
+ function () {
+ // test 13: Ranges under mutations: deletion
+ var doc = getTestDocument();
+ var p = doc.createElement('p');
+ p.appendChild(doc.createTextNode("12345"));
+ doc.body.appendChild(p);
+ var r = doc.createRange();
+ r.setEnd(doc.body, 1);
+ r.setStart(p.firstChild, 2);
+ assert(!r.collapsed, "collapsed is wrong at start");
+ assertEquals(r.commonAncestorContainer, doc.body, "commonAncestorContainer is wrong at start");
+ assertEquals(r.startContainer, p.firstChild, "startContainer is wrong at start");
+ assertEquals(r.startOffset, 2, "startOffset is wrong at start");
+ assertEquals(r.endContainer, doc.body, "endContainer is wrong at start");
+ assertEquals(r.endOffset, 1, "endOffset is wrong at start");
+ doc.body.removeChild(p);
+ assert(r.collapsed, "collapsed is wrong after deletion");
+ assertEquals(r.commonAncestorContainer, doc.body, "commonAncestorContainer is wrong after deletion");
+ assertEquals(r.startContainer, doc.body, "startContainer is wrong after deletion");
+ assertEquals(r.startOffset, 0, "startOffset is wrong after deletion");
+ assertEquals(r.endContainer, doc.body, "endContainer is wrong after deletion");
+ assertEquals(r.endOffset, 0, "endOffset is wrong after deletion");
+ return 1;
+ },
+
+ // HTTP
+ function () {
+ // test 14: HTTP - Content-Type: image/png
+ assert(!notifications['empty.png'], "privilege escalation security bug: PNG ran script");
+ var iframe = document.getElementsByTagName('iframe')[0];
+ assert(iframe, "no <iframe> support");
+ if (iframe && iframe.contentDocument) {
+ var ps = iframe.contentDocument.getElementsByTagName('p');
+ if (ps.length > 0) {
+ if (ps[0].firstChild && ps[0].firstChild.data && ps[0].firstChild.data == 'FAIL')
+ fail("PNG was parsed as HTML.");
+ }
+ }
+ return 1;
+ },
+ function () {
+ // test 15: HTTP - Content-Type: text/plain
+ assert(!notifications['empty.txt'], "privilege escalation security bug: text file ran script");
+ var iframe = document.getElementsByTagName('iframe')[1];
+ assert(iframe, "no <iframe> support");
+ if (iframe && iframe.contentDocument) {
+ var ps = iframe.contentDocument.getElementsByTagName('p');
+ if (ps.length > 0) {
+ if (ps[0].firstChild && ps[0].firstChild.data && ps[0].firstChild.data == 'FAIL')
+ fail("text/plain file was parsed as HTML");
+ }
+ }
+ return 1;
+ },
+ function () {
+ // test 16: <object> handling and HTTP status codes
+ var oC = document.createElement('object');
+ //oC.appendChild(document.createTextNode("FAIL"));
+ var oB = document.createElement('object');
+ var oA = document.createElement('object');
+ oA.data = "support-a.png";
+ oB.data = "support-b.png";
+ oB.appendChild(oC);
+ oC.data = "support-c.png";
+ oA.appendChild(oB);
+ document.getElementsByTagName("map")[0].appendChild(oA);
+ // assuming the above didn't raise any exceptions, this test has passed
+ // (the real test is whether the rendering is correct)
+ return 1;
+ },
+
+ // bucket 2: DOM2 Core and DOM2 Events
+ // Core
+ function () {
+ // test 17: hasAttribute
+ // missing attribute
+ assert(!document.getElementsByTagName('map')[0].hasAttribute('id'), "hasAttribute failure for 'id' on map");
+ // implied attribute
+ assert(!document.getElementsByTagName('form')[0].hasAttribute('method'), "hasAttribute failure for 'method' on form");
+ // actually present attribute
+ assert(document.getElementsByTagName('form')[0].hasAttribute('action'), "hasAttribute failure for 'action' on form");
+ assertEquals(document.getElementsByTagName('form')[0].getAttribute('action'), '', "attribute 'action' on form has wrong value");
+ return 2;
+ },
+ function () {
+ // test 18: nodeType (this test also relies on accurate parsing of the document)
+ assertEquals(document.nodeType, 9, "document nodeType wrong");
+ assertEquals(document.documentElement.nodeType, 1, "element nodeType wrong");
+ if (document.createAttribute) // support for attribute nodes is optional in Acid3, because attribute nodes might be removed from DOM Core in the future.
+ assertEquals(document.createAttribute('test').nodeType, 2, "attribute nodeType wrong"); // however, if they're supported, they'd better work
+ assertEquals(document.getElementById('score').firstChild.nodeType, 3, "text node nodeType wrong");
+ assertEquals(document.firstChild.nodeType, 10, "DOCTYPE nodeType wrong");
+ return 2;
+ },
+ function () {
+ // test 19: value of constants
+ var e = null;
+ try {
+ document.body.appendChild(document.documentElement);
+ // raises a HIERARCHY_REQUEST_ERR
+ } catch (err) {
+ e = err;
+ }
+ assertEquals(document.DOCUMENT_FRAGMENT_NODE, 11, "document DOCUMENT_FRAGMENT_NODE constant missing or wrong");
+ assertEquals(document.body.COMMENT_NODE, 8, "element COMMENT_NODE constant missing or wrong");
+ assertEquals(document.createTextNode('').ELEMENT_NODE, 1, "text node ELEMENT_NODE constant missing or wrong");
+ assert(e.HIERARCHY_REQUEST_ERR == 3, "exception HIERARCHY_REQUEST_ERR constant missing or wrong")
+ assertEquals(e.code, 3, "incorrect exception raised from appendChild()");
+ return 2;
+ },
+ function () {
+ // test 20: nulls bytes in various places
+ assert(!document.getElementById('bucket1\0error'), "null in getElementById() probably terminated string");
+ var ok = true;
+ try {
+ document.createElement('form\0div');
+ ok = false;
+ } catch (e) {
+ if (e.code != 5)
+ ok = false;
+ }
+ assert(ok, "didn't raise the right exception for null byte in createElement()");
+ return 2;
+ },
+ function () {
+ // test 21: basic namespace stuff
+ var element = document.createElementNS('http://ns.example.com/', 'prefix:localname');
+ assertEquals(element.tagName, 'prefix:localname', "wrong tagName");
+ assertEquals(element.nodeName, 'prefix:localname', "wrong nodeName");
+ assertEquals(element.prefix, 'prefix', "wrong prefix");
+ assertEquals(element.localName, 'localname', "wrong localName");
+ assertEquals(element.namespaceURI, 'http://ns.example.com/', "wrong namespaceURI");
+ return 2;
+ },
+ function () {
+ // test 22: createElement() with invalid tag names
+ var test = function (name) {
+ var result;
+ try {
+ var div = document.createElement(name);
+ } catch (e) {
+ result = e;
+ }
+ assert(result, "no exception for createElement('" + name + "')");
+ assertEquals(result.code, 5, "wrong exception for createElement('" + name + "')"); // INVALID_CHARACTER_ERR
+ }
+ test('<div>');
+ test('0div');
+ test('di v');
+ test('di<v');
+ test('-div');
+ test('.div');
+ return 2;
+ },
+ function () {
+ // test 23: createElementNS() with invalid tag names
+ var test = function (name, ns, code) {
+ var result;
+ try {
+ var div = document.createElementNS(ns, name);
+ } catch (e) {
+ result = e;
+ }
+ assert(result, "no exception for createElementNS('" + ns + "', '" + name + "')");
+ assertEquals(result.code, code, "wrong exception for createElementNS('" + ns + "', '" + name + "')");
+ }
+ test('<div>', null, 5);
+ test('0div', null, 5);
+ test('di v', null, 5);
+ test('di<v', null, 5);
+ test('-div', null, 5);
+ test('.div', null, 5);
+ test('<div>', "http://example.com/", 5);
+ test('0div', "http://example.com/", 5);
+ test('di<v', "http://example.com/", 5);
+ test('-div', "http://example.com/", 5);
+ test('.div', "http://example.com/", 5);
+ test(':div', null, 14);
+ test(':div', "http://example.com/", 14);
+ test('d:iv', null, 14);
+ test('xml:test', "http://example.com/", 14);
+ test('xmlns:test', "http://example.com/", 14); // (technically a DOM3 Core test)
+ test('x:test', "http://www.w3.org/2000/xmlns/", 14); // (technically a DOM3 Core test)
+ document.createElementNS("http://www.w3.org/2000/xmlns/", 'xmlns:test'); // (technically a DOM3 Core test)
+ return 2;
+ },
+ function () {
+ // test 24: event handler attributes
+ assertEquals(document.body.getAttribute('onload'), "update() /* this attribute's value is tested in one of the tests */ ", "onload value wrong");
+ return 2;
+ },
+ function () {
+ // test 25: test namespace checking in createDocumentType, and
+ // check that exceptions that are thrown are DOMException objects
+ var message = "";
+ try {
+ document.implementation.createDocumentType('a:', '', ''); /* doesn't contain an illegal character; is malformed */
+ message = "failed to raise exception";
+ } catch (e) {
+ if (e.code != e.NAMESPACE_ERR)
+ message = "wrong exception";
+ else if (e.INVALID_ACCESS_ERR != 15)
+ message = "exceptions don't have all the constants";
+ }
+ if (message)
+ fail(message);
+ return 2;
+ },
+ function () {
+ // test 26: check that document tree survives while still accessible
+ var d;
+ // e1 - an element that's in a document
+ d = document.implementation.createDocument(null, null, null);
+ var e1 = d.createElement('test');
+ d.appendChild(d.createElement('root'));
+ d.documentElement.appendChild(e1);
+ assert(e1.parentNode, "e1 - parent element doesn't exist");
+ assert(e1.parentNode.ownerDocument, "e1 - document doesn't exist");
+ // e2 - an element that's not in a document
+ d = document.implementation.createDocument(null, null, null);
+ var e2 = d.createElement('test');
+ d.createElement('root').appendChild(e2);
+ assert(e2.parentNode, "e2 - parent element doesn't exist");
+ assert(e2.parentNode.ownerDocument, "e2 - document doesn't exist");
+ // now try to decouple them
+ d = null;
+ kungFuDeathGrip = [e1, e2];
+ assert(e1.parentNode, "e1 - parent element doesn't exist after dropping reference to document");
+ assert(e1.parentNode.ownerDocument, "e1 - document doesn't exist after dropping reference to document");
+ assert(e2.parentNode, "e2 - parent element doesn't exist after dropping reference to document");
+ assert(e2.parentNode.ownerDocument, "e2 - document doesn't exist after dropping reference to document");
+ var loops = new Date().valueOf() * 2.813435e-9 - 2412; // increases linearly over time
+ for (var i = 0; i < loops; i += 1) {
+ // we want to force a GC here, so we use up lots of memory
+ // we take the opportunity to sneak in a perf test to make DOM and JS stuff faster...
+ d = new Date();
+ d = new (function (x) { return { toString: function () { return x.toString() } } })(d.valueOf());
+ d = document.createTextNode("iteration " + i + " at " + d);
+ document.createElement('a').appendChild(d);
+ d = d.parentNode;
+ document.body.insertBefore(d, document.getElementById('bucket1').parentNode);
+ assert(document.getElementById('bucket2').nextSibling.parentNode.previousSibling.firstChild.data.match(/AT\W/i), "iteration " + i + " failed");
+ d.setAttribute('class', d.textContent);
+ document.body.removeChild(d);
+ }
+ assert(e1.parentNode, "e1 - parent element doesn't exist after looping");
+ assert(e1.parentNode.ownerDocument, "e1 - document doesn't exist after looping");
+ assertEquals(e1.parentNode.ownerDocument.nodeType, 9, "e1 - document node type has wrong node type");
+ assert(e2.parentNode, "e2 - parent element doesn't exist after looping");
+ assert(e2.parentNode.ownerDocument, "e2 - document doesn't exist after looping");
+ assertEquals(e2.parentNode.ownerDocument.nodeType, 9, "e2 - document node type has wrong node type");
+ return 2;
+ },
+ function () {
+ // test 27: a continuation of the previous test
+ var e1 = kungFuDeathGrip[0];
+ var e2 = kungFuDeathGrip[1];
+ kungFuDeathGrip = null;
+ assert(e1, "e1 - element itself didn't survive across tests");
+ assert(e1.parentNode, "e1 - parent element doesn't exist after waiting");
+ assert(e1.parentNode.ownerDocument, "e1 - document doesn't exist after waiting");
+ assertEquals(e1.parentNode.ownerDocument.nodeType, 9, "e1 - document node type has wrong node type after waiting");
+ assert(e2, "e2 - element itself didn't survive across tests");
+ assert(e2.parentNode, "e2 - parent element doesn't exist after waiting");
+ assert(e2.parentNode.ownerDocument, "e2 - document doesn't exist after waiting");
+ assertEquals(e2.parentNode.ownerDocument.nodeType, 9, "e2 - document node type has wrong node type after waiting");
+ return 2;
+ },
+ function () {
+ // test 28: getElementById()
+ // ...and name=""
+ assert(document.getElementById('form') !== document.getElementsByTagName('form')[0], "getElementById() searched on 'name'");
+ // ...and a space character as the ID
+ var div = document.createElement('div');
+ div.appendChild(document.createTextNode('FAIL'));
+ div.id = " ";
+ document.body.appendChild(div); // it's hidden by CSS
+ assert(div === document.getElementById(" "), "getElementById() didn't return the right element");
+ return 2;
+ },
+ function () {
+ // test 29: check that whitespace survives cloning
+ var t1 = document.getElementsByTagName('table')[0];
+ var t2 = t1.cloneNode(true);
+ assertEquals(t2.tBodies[0].rows[0].cells[0].firstChild.tagName, 'P', "<p> didn't clone right");
+ assertEquals(t2.tBodies[0].rows[0].cells[0].firstChild.childNodes.length, 0, "<p> got child nodes after cloning");
+ assertEquals(t2.childNodes.length, 2, "cloned table had wrong number of children");
+ assertEquals(t2.lastChild.data, " ", "cloned table lost whitespace text node");
+ return 2;
+ },
+
+ // Events
+ function () {
+ // test 30: dispatchEvent()
+ var count = 0;
+ var ok = true;
+ var test = function (event) {
+ if (event.detail != 6)
+ ok = false;
+ count++;
+ };
+ // test event listener addition
+ document.getElementById('result').addEventListener('test', test, false);
+ // test event creation
+ var event = document.createEvent('UIEvents');
+ event.initUIEvent('test', true, false, null, 6);
+ // test event dispatch on elements and text nodes
+ assert(document.getElementById('score').dispatchEvent(event), "dispatchEvent #1 failed");
+ assert(document.getElementById('score').nextSibling.dispatchEvent(event), "dispatchEvent #2 failed");
+ // test event listener removal
+ document.getElementById('result').removeEventListener('test', test, false);
+ assert(document.getElementById('score').dispatchEvent(event), "dispatchEvent #3 failed");
+ assertEquals(count, 2, "unexpected number of events handled");
+ assert(ok, "unexpected events handled");
+ return 2;
+ },
+ function () {
+ // test 31: event.stopPropagation() and capture
+ // we're going to use an input element because we can cause events to bubble from it
+ var input = document.createElement('input');
+ var div = document.createElement('div');
+ div.appendChild(input);
+ document.body.appendChild(div);
+ // the test will consist of two event handlers:
+ var ok = true;
+ var captureCount = 0;
+ var testCapture = function (event) {
+ ok = ok &&
+ (event.type == 'click') &&
+ (event.target == input) &&
+ (event.currentTarget == div) &&
+ (event.eventPhase == 1) &&
+ (event.bubbles) &&
+ (event.cancelable);
+ captureCount++;
+ event.stopPropagation(); // this shouldn't stop it from firing both times on the div element
+ };
+ var testBubble = function (event) {
+ ok = false;
+ };
+ // one of which is added twice:
+ div.addEventListener('click', function (event) { testCapture(event) }, true);
+ div.addEventListener('click', function (event) { testCapture(event) }, true);
+ div.addEventListener('click', testBubble, false);
+ // we cause an event to bubble like this:
+ input.type = 'reset';
+ input.click();
+ // cleanup afterwards
+ document.body.removeChild(div);
+ // capture handler should have been called twice
+ assertEquals(captureCount, 2, "capture handler called the wrong number of times");
+ assert(ok, "capture handler called incorrectly");
+ return 2;
+ },
+ function () {
+ // test 32: events bubbling through Document node
+ // event handler:
+ var ok = true;
+ var count = 0;
+ var test = function (event) {
+ count += 1;
+ if (event.eventPhase != 3)
+ ok = false;
+ }
+ // register event handler
+ document.body.addEventListener('click', test, false);
+ // create an element that bubbles an event, and bubble it
+ var input = document.createElement('input');
+ var div = document.createElement('div');
+ div.appendChild(input);
+ document.body.appendChild(div);
+ input.type = 'reset';
+ input.click();
+ // unregister event handler
+ document.body.removeEventListener('click', test, false);
+ // check that it's removed for good
+ input.click();
+ // remove the newly added elements
+ document.body.removeChild(div);
+ assertEquals(count, 1, "capture handler called the wrong number of times");
+ assert(ok, "capture handler called incorrectly");
+ return 2;
+ },
+
+ // bucket 3: DOM2 Views, DOM2 Style, and Selectors
+ function () {
+ // test 33: basic tests for selectors - classes, attributes
+ var p;
+ var builder = function(doc) {
+ p = doc.createElement("p");
+ doc.body.appendChild(p);
+ };
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ p.className = "selectorPingTest";
+ var good = add(".selectorPingTest");
+ add(".SelectorPingTest");
+ add(".selectorpingtest");
+ expect(doc.body, 0, "failure 1");
+ expect(p, good, "failure 2");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ p.className = 'a\u0020b\u0009c\u000Ad\u000De\u000Cf\u2003g\u3000h';
+ var good = add(".a.b.c.d.e.f\\2003g\\3000h");
+ expect(p, good, "whitespace error in class processing");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ p.className = "selectorPingTest";
+ var good = add("[class=selectorPingTest]");
+ add("[class=SelectorPingTest]");
+ add("[class=selectorpingtest]");
+ expect(doc.body, 0, "failure 3");
+ expect(p, good, "class attribute matching failed");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ p.className = "selectorPingTest";
+ var good = add("[title=selectorPingTest]");
+ add("[title=SelectorPingTest]");
+ add("[title=selectorpingtest]");
+ expect(doc.body, 0, "failure 4");
+ expect(p, 0, "failure 5");
+ p.title = "selectorPingTest";
+ expect(doc.body, 0, "failure 6");
+ expect(p, good, "failure 7");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ p.setAttribute('align', 'right and left');
+ var good = add("[align=\"right and left\"]");
+ add("[align=left]");
+ add("[align=right]");
+ expect(p, good, "align attribute mismatch");
+ });
+ return 3;
+ },
+ function () {
+ // test 34: :lang() and [|=]
+ var div1;
+ var div2;
+ var p;
+ var builder = function(doc) {
+ div1 = doc.createElement('div');
+ div1.setAttribute("lang", "english");
+ div1.setAttribute("class", "widget-tree");
+ doc.body.appendChild(div1);
+ div2 = doc.createElement('div');
+ div2.setAttribute("lang", "en-GB");
+ div2.setAttribute("class", "WIDGET");
+ doc.body.appendChild(div2);
+ p = doc.createElement('p');
+ div2.appendChild(p);
+ };
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var lang_en = add(":lang(en)");
+ expect(div1, 0, "lang=english should not be matched by :lang(en)");
+ expect(div2, lang_en, "lang=en-GB should be matched by :lang(en)");
+ expect(p, lang_en, "descendants inheriting lang=en-GB should be matched by :lang(en)");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var class_widget = add("[class|=widget]");
+ expect(div1, class_widget, "class attribute should be supported by |= attribute selectors");
+ expect(div2, 0, "class attribute is case-sensitive");
+ });
+ return 3;
+ },
+ function () {
+ // test 35: :first-child
+ selectorTest(function (doc, add, expect) {
+ var notFirst = 0;
+ var first = add(":first-child");
+ var p1 = doc.createElement("p");
+ doc.body.appendChild(doc.createTextNode(" TEST "));
+ doc.body.appendChild(p1);
+ expect(doc.documentElement, notFirst, "root element, with no parent node, claims to be a :first-child");
+ expect(doc.documentElement.firstChild, first, "first child of root node didn't match :first-child");
+ expect(doc.documentElement.firstChild.firstChild, first, "failure 3");
+ expect(doc.body, notFirst, "failure 4");
+ expect(p1, first, "failure 5");
+ var p2 = doc.createElement("p");
+ doc.body.appendChild(p2);
+ expect(doc.body, notFirst, "failure 6");
+ expect(p1, first, "failure 7");
+ expect(p2, notFirst, "failure 8");
+ var p0 = doc.createElement("p");
+ doc.body.insertBefore(p0, p1);
+ expect(doc.body, notFirst, "failure 9");
+ expect(p0, first, "failure 10");
+ expect(p1, notFirst, ":first-child still applies to element that was previously a first child");
+ expect(p2, notFirst, "failure 12");
+ doc.body.insertBefore(p0, p2);
+ expect(doc.body, notFirst, "failure 13");
+ expect(p1, first, "failure 14");
+ expect(p0, notFirst, "failure 15");
+ expect(p2, notFirst, "failure 16");
+ });
+ return 3;
+ },
+ function () {
+ // test 36: :last-child
+ var p1;
+ var p2;
+ var builder = function(doc) {
+ p1 = doc.createElement('p');
+ p2 = doc.createElement('p');
+ doc.body.appendChild(p1);
+ doc.body.appendChild(p2);
+ };
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var last = add(":last-child");
+ expect(p1, 0, "control test for :last-child failed");
+ expect(p2, last, "last child did not match :last-child");
+ doc.body.appendChild(p1);
+ expect(p2, 0, ":last-child matched element with a following sibling");
+ expect(p1, last, "failure 4");
+ p1.appendChild(p2);
+ expect(p2, last, "failure 5");
+ expect(p1, last, "failure 6");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var last = add(":last-child");
+ expect(p1, 0, "failure 7");
+ expect(p2, last, "failure 8");
+ doc.body.insertBefore(p2, p1);
+ expect(p2, 0, "failure 9");
+ expect(p1, last, "failure 10");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var last = add(":last-child");
+ expect(p1, 0, "failure 11");
+ expect(p2, last, "failure 12");
+ doc.body.removeChild(p2);
+ expect(p1, last, "failure 13");
+ assertEquals(p1.nextSibling, null, "failure 14");
+ assertEquals(p2.parentNode, null, "failure 15");
+ });
+ return 3;
+ },
+ function () {
+ // test 37: :only-child
+ var p1;
+ var p2;
+ var builder = function(doc) {
+ p1 = doc.createElement('p');
+ p2 = doc.createElement('p');
+ doc.body.appendChild(p1);
+ doc.body.appendChild(p2);
+ };
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var only = add(":only-child");
+ expect(p1, 0, "control test for :only-child failed");
+ expect(p2, 0, "failure 2");
+ doc.body.removeChild(p2);
+ expect(p1, only, ":only-child did not match only child");
+ p1.appendChild(p2);
+ expect(p2, only, "failure 4");
+ expect(p1, only, "failure 5");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var only = add(":only-child");
+ expect(p1, 0, "failure 6");
+ expect(p2, 0, "failure 7");
+ doc.body.removeChild(p1);
+ expect(p2, only, "failure 8");
+ p2.appendChild(p1);
+ expect(p2, only, "failure 9");
+ expect(p1, only, "failure 10");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var only = add(":only-child");
+ expect(p1, 0, "failure 11");
+ expect(p2, 0, "failure 12");
+ var span1 = doc.createElement('span');
+ p1.appendChild(span1);
+ expect(p1, 0, "failure 13");
+ expect(p2, 0, "failure 14");
+ expect(span1, only, "failure 15");
+ var span2 = doc.createElement('span');
+ p1.appendChild(span2);
+ expect(p1, 0, "failure 16");
+ expect(p2, 0, "failure 17");
+ expect(span1, 0, "failure 18");
+ expect(span2, 0, "failure 19");
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var only = add(":only-child");
+ expect(p1, 0, "failure 20");
+ expect(p2, 0, "failure 21");
+ var span1 = doc.createElement('span');
+ p2.appendChild(span1);
+ expect(p1, 0, "failure 22");
+ expect(p2, 0, "failure 23");
+ expect(span1, only, "failure 24");
+ var span2 = doc.createElement('span');
+ p2.insertBefore(span2, span1);
+ expect(p1, 0, "failure 25");
+ expect(p2, 0, "failure 26");
+ expect(span1, 0, "failure 27");
+ expect(span2, 0, "failure 28");
+ });
+ return 3;
+ },
+ function () {
+ // test 38: :empty
+ selectorTest(function (doc, add, expect) {
+ var empty = add(":empty");
+ var p = doc.createElement('p');
+ doc.body.appendChild(p);
+ expect(p, empty, "empty p element didn't match :empty");
+ var span = doc.createElement('span');
+ p.appendChild(span);
+ expect(p, 0, "adding children didn't stop the element matching :empty");
+ expect(span, empty, "empty span element didn't match :empty");
+ p.removeChild(span);
+ expect(p, empty, "removing all children didn't make the element match :empty");
+ p.appendChild(doc.createComment("c"));
+ p.appendChild(doc.createTextNode(""));
+ expect(p, empty, "element with a comment node and an empty text node didn't match :empty");
+ p.appendChild(doc.createTextNode(""));
+ expect(p, empty, "element with a comment node and two empty text nodes didn't match :empty");
+ p.lastChild.data = " ";
+ expect(p, 0, "adding text to a text node didn't make the element non-:empty");
+ assertEquals(p.childNodes.length, 3, "text nodes may have merged");
+ p.childNodes[1].replaceWholeText("");
+ assertEquals(p.childNodes.length, 1, "replaceWholeText('') didn't remove text nodes");
+ expect(p, empty, "element with a comment node only didn't match :empty");
+ p.appendChild(doc.createElementNS("http://example.com/", "test"));
+ expect(p, 0, "adding an element in a namespace didn't make the element non-:empty");
+ });
+ return 3;
+ },
+ function () {
+ // test 39: :nth-child, :nth-last-child
+ var ps;
+ var builder = function(doc) {
+ ps = [
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p')
+ ];
+ for (var i = 0; i < ps.length; i += 1)
+ doc.body.appendChild(ps[i]);
+ };
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-child(odd)");
+ for (var i = 0; i < ps.length; i += 1)
+ expect(ps[i], i % 2 ? 0 : match, ":nth-child(odd) failed with child " + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-child(even)");
+ for (var i = 0; i < ps.length; i += 1)
+ expect(ps[i], i % 2 ? match : 0 , ":nth-child(even) failed with child " + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-child(odd)");
+ doc.body.removeChild(ps[5]);
+ for (var i = 0; i < 5; i += 1)
+ expect(ps[i], i % 2 ? 0 : match, ":nth-child(odd) failed after removal with child " + i);
+ for (var i = 6; i < ps.length; i += 1)
+ expect(ps[i], i % 2 ? match : 0, ":nth-child(odd) failed after removal with child " + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-child(even)");
+ doc.body.removeChild(ps[5]);
+ for (var i = 0; i < 5; i += 1)
+ expect(ps[i], i % 2 ? match : 0, ":nth-child(even) failed after removal with child " + i);
+ for (var i = 6; i < ps.length; i += 1)
+ expect(ps[i], i % 2 ? 0 : match, ":nth-child(even) failed after removal with child " + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-child(-n+3)");
+ for (var i = 0; i < 3; i += 1)
+ expect(ps[i], match, ":nth-child(-n+3) failed with child " + i);
+ for (var i = 3; i < ps.length; i += 1)
+ expect(ps[i], 0, ":nth-child(-n+3) failed with child " + i);
+ });
+ return 3;
+ },
+ function () {
+ // test 40: :first-of-type, :last-of-type, :only-of-type, :nth-of-type, :nth-last-of-type
+ var elements;
+ var builder = function(doc) {
+ elements = [
+ doc.createElement('p'),
+ doc.createElement('div'),
+ doc.createElement('div'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('p'),
+ doc.createElement('div'),
+ doc.createElement('address'),
+ doc.createElement('div'),
+ doc.createElement('div'),
+ doc.createElement('div'),
+ doc.createElement('p'),
+ doc.createElement('div'),
+ doc.createElement('p')
+ ];
+ for (var i = 0; i < elements.length; i += 1)
+ doc.body.appendChild(elements[i]);
+ };
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":first-of-type");
+ var values = [1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 1:" + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":last-of-type");
+ var values = [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 2:" + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":only-of-type");
+ var values = [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 3:" + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-of-type(3n-1)");
+ var values = [0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 4:" + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-of-type(3n+1)");
+ var values = [1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 5:" + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-last-of-type(2n)");
+ var values = [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 6:" + i);
+ });
+ selectorTest(function (doc, add, expect) {
+ builder(doc);
+ var match = add(":nth-last-of-type(-5n+3)");
+ var values;
+ values = [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 7:" + i);
+ doc.body.appendChild(doc.createElement('blockquote'));
+ values = [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 8:" + i);
+ doc.body.appendChild(doc.createElement('div'));
+ values = [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0];
+ for (var i = 0; i < elements.length; i += 1)
+ expect(elements[i], values[i] ? match : 0, "part 9:" + i);
+ });
+ return 3;
+ },
+ function () {
+ // test 41: :root, :not()
+ selectorTest(function (doc, add, expect) {
+ var match = add(":not(:root)");
+ var p = doc.createElement('p');
+ doc.body.appendChild(p);
+ expect(doc.documentElement, 0, "root was :not(:root)");
+ expect(doc.documentElement.childNodes[0], match,"head was not :not(:root)");
+ expect(doc.documentElement.childNodes[1], match,"body was not :not(:root)");
+ expect(doc.documentElement.childNodes[0].firstChild, match,"title was not :not(:root)");
+ expect(p, match,"p was not :not(:root)");
+ });
+ return 3;
+ },
+ function () {
+ // test 42: +, ~, >, and ' ' in dynamic situations
+ selectorTest(function (doc, add, expect) {
+ var div1 = doc.createElement('div');
+ div1.id = "div1";
+ doc.body.appendChild(div1);
+ var div2 = doc.createElement('div');
+ doc.body.appendChild(div2);
+ var div3 = doc.createElement('div');
+ doc.body.appendChild(div3);
+ var div31 = doc.createElement('div');
+ div3.appendChild(div31);
+ var div311 = doc.createElement('div');
+ div31.appendChild(div311);
+ var div3111 = doc.createElement('div');
+ div311.appendChild(div3111);
+ var match = add("#div1 ~ div div + div > div");
+ expect(div1, 0, "failure 1");
+ expect(div2, 0, "failure 2");
+ expect(div3, 0, "failure 3");
+ expect(div31, 0, "failure 4");
+ expect(div311, 0, "failure 5");
+ expect(div3111, 0, "failure 6");
+ var div310 = doc.createElement('div');
+ div31.insertBefore(div310, div311);
+ expect(div1, 0, "failure 7");
+ expect(div2, 0, "failure 8");
+ expect(div3, 0, "failure 9");
+ expect(div31, 0, "failure 10");
+ expect(div310, 0, "failure 11");
+ expect(div311, 0, "failure 12");
+ expect(div3111, match, "rule did not start matching after change");
+ });
+ selectorTest(function (doc, add, expect) {
+ var div1 = doc.createElement('div');
+ div1.id = "div1";
+ doc.body.appendChild(div1);
+ var div2 = doc.createElement('div');
+ div1.appendChild(div2);
+ var div3 = doc.createElement('div');
+ div2.appendChild(div3);
+ var div4 = doc.createElement('div');
+ div3.appendChild(div4);
+ var div5 = doc.createElement('div');
+ div4.appendChild(div5);
+ var div6 = doc.createElement('div');
+ div5.appendChild(div6);
+ var match = add("#div1 > div div > div");
+ expect(div1, 0, "failure 14");
+ expect(div2, 0, "failure 15");
+ expect(div3, 0, "failure 16");
+ expect(div4, match, "failure 17");
+ expect(div5, match, "failure 18");
+ expect(div6, match, "failure 19");
+ var p34 = doc.createElement('p');
+ div3.insertBefore(p34, div4);
+ p34.insertBefore(div4, null);
+ expect(div1, 0, "failure 20");
+ expect(div2, 0, "failure 21");
+ expect(div3, 0, "failure 22");
+ expect(p34, 0, "failure 23");
+ expect(div4, 0, "failure 24");
+ expect(div5, match, "failure 25");
+ expect(div6, match, "failure 26");
+ });
+ selectorTest(function (doc, add, expect) {
+ var div1 = doc.createElement('div');
+ div1.id = "div1";
+ doc.body.appendChild(div1);
+ var div2 = doc.createElement('div');
+ div1.appendChild(div2);
+ var div3 = doc.createElement('div');
+ div2.appendChild(div3);
+ var div4 = doc.createElement('div');
+ div3.appendChild(div4);
+ var div5 = doc.createElement('div');
+ div4.appendChild(div5);
+ var div6 = doc.createElement('div');
+ div5.appendChild(div6);
+ var match = add("#div1 > div div > div");
+ expect(div1, 0, "failure 27");
+ expect(div2, 0, "failure 28");
+ expect(div3, 0, "failure 29");
+ expect(div4, match, "failure 30");
+ expect(div5, match, "failure 31");
+ expect(div6, match, "failure 32");
+ var p23 = doc.createElement('p');
+ div2.insertBefore(p23, div3);
+ p23.insertBefore(div3, null);
+ expect(div1, 0, "failure 33");
+ expect(div2, 0, "failure 34");
+ expect(div3, 0, "failure 35");
+ expect(p23, 0, "failure 36");
+ expect(div4, match, "failure 37");
+ expect(div5, match, "failure 38");
+ expect(div6, match, "failure 39");
+ });
+ return 3;
+ },
+ function () {
+ // test 43: :enabled, :disabled, :checked, etc
+ selectorTest(function (doc, add, expect) {
+ var input = doc.createElement('input');
+ input.type = 'checkbox';
+ doc.body.appendChild(input);
+ var neither = 0;
+ var both = add(":checked:enabled");
+ var checked = add(":checked");
+ var enabled = add(":enabled");
+ expect(doc.body, neither, "control failure");
+ expect(input, enabled, "input element didn't match :enabled");
+ input.click();
+ expect(input, both, "input element didn't match :checked");
+ input.disabled = true;
+ expect(input, checked, "failure 3");
+ input.checked = false;
+ expect(input, neither, "failure 4");
+ expect(doc.body, neither, "failure 5");
+ });
+ selectorTest(function (doc, add, expect) {
+ var input1 = doc.createElement('input');
+ input1.type = 'radio';
+ input1.name = 'radio';
+ doc.body.appendChild(input1);
+ var input2 = doc.createElement('input');
+ input2.type = 'radio';
+ input2.name = 'radio';
+ doc.body.appendChild(input2);
+ var checked = add(":checked");
+ expect(input1, 0, "failure 6");
+ expect(input2, 0, "failure 7");
+ input2.click();
+ expect(input1, 0, "failure 6");
+ expect(input2, checked, "failure 7");
+ input1.checked = true;
+ expect(input1, checked, "failure 8");
+ expect(input2, 0, "failure 9");
+ input2.setAttribute("checked", "checked"); // sets defaultChecked, doesn't change actual state
+ expect(input1, checked, "failure 10");
+ expect(input2, 0, "failure 11");
+ input1.type = "text";
+ expect(input1, 0, "text field matched :checked");
+ });
+ selectorTest(function (doc, add, expect) {
+ var input = doc.createElement('input');
+ input.type = 'button';
+ doc.body.appendChild(input);
+ var neither = 0;
+ var enabled = add(":enabled");
+ var disabled = add(":disabled");
+ add(":enabled:disabled");
+ expect(input, enabled, "failure 12");
+ input.disabled = true;
+ expect(input, disabled, "failure 13");
+ input.removeAttribute("disabled");
+ expect(input, enabled, "failure 14");
+ expect(doc.body, neither, "failure 15");
+ });
+ return 3;
+ },
+ function () {
+ // test 44: selectors without spaces before a "*"
+ selectorTest(function (doc, add, expect) {
+ doc.body.className = "test";
+ var p = doc.createElement('p');
+ p.className = "test";
+ doc.body.appendChild(p);
+ add("html*.test");
+ expect(doc.body, 0, "misparsed selectors");
+ expect(p, 0, "really misparsed selectors");
+ });
+ return 3;
+ },
+ function () {
+ // test 45: cssFloat and the style attribute
+ assert(!document.body.style.cssFloat, "body has floatation");
+ document.body.setAttribute("style", "float: right");
+ assertEquals(document.body.style.cssFloat, "right", "body doesn't have floatation");
+ document.body.setAttribute("style", "float: none");
+ assertEquals(document.body.style.cssFloat, "none", "body didn't lose floatation");
+ return 3;
+ },
+ function () {
+ // test 46: media queries
+ var doc = getTestDocument();
+ var style = doc.createElement('style');
+ style.setAttribute('type', 'text/css');
+ style.appendChild(doc.createTextNode('@media all and (min-color: 0) { #a { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media not all and (min-color: 0) { #b { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media only all and (min-color: 0) { #c { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media (bogus) { #d { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media all and (bogus) { #e { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media not all and (bogus) { #f { text-transform: uppercase; } }')); // commentd out but should not match
+ style.appendChild(doc.createTextNode('@media only all and (bogus) { #g { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media (bogus), all { #h { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media all and (bogus), all { #i { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media not all and (bogus), all { #j { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media only all and (bogus), all { #k { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media all, (bogus) { #l { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media all, all and (bogus) { #m { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media all, not all and (bogus) { #n { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media all, only all and (bogus) { #o { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media all and color { #p { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media all and min-color: 0 { #q { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media all, all and color { #r { text-transform: uppercase; } }')); // commented out but should match
+ style.appendChild(doc.createTextNode('@media all, all and min-color: 0 { #s { text-transform: uppercase; } }')); // commented out but should match
+ style.appendChild(doc.createTextNode('@media all and min-color: 0, all { #t { text-transform: uppercase; } }')); // commented out but should match
+ style.appendChild(doc.createTextNode('@media (max-color: 0) and (max-monochrome: 0) { #u { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media (min-color: 1), (min-monochrome: 1) { #v { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media all and (min-color: 0) and (min-monochrome: 0) { #w { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media not all and (min-color: 1), not all and (min-monochrome: 1) { #x { text-transform: uppercase; } }')); // matches
+ style.appendChild(doc.createTextNode('@media all and (min-height: 1em) and (min-width: 1em) { #y1 { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media all and (max-height: 1em) and (min-width: 1em) { #y2 { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media all and (min-height: 1em) and (max-width: 1em) { #y3 { text-transform: uppercase; } }'));
+ style.appendChild(doc.createTextNode('@media all and (max-height: 1em) and (max-width: 1em) { #y4 { text-transform: uppercase; } }')); // matches
+ doc.getElementsByTagName('head')[0].appendChild(style);
+ var names = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y1', 'y2', 'y3', 'y4'];
+ for (var i in names) {
+ var p = doc.createElement('p');
+ p.id = names[i];
+ doc.body.appendChild(p);
+ }
+ var count = 0;
+ var check = function (c, e) {
+ count += 1;
+ var p = doc.getElementById(c);
+ assertEquals(doc.defaultView.getComputedStyle(p, '').textTransform, e ? 'uppercase' : 'none', "case " + c + " failed (index " + count + ")");
+ }
+ check('a', true); // 1
+ check('b', false);
+ check('c', true);
+ check('d', false);
+ check('e', false);
+/* COMMENTED OUT BECAUSE THE CSSWG KEEP CHANGING THE RIGHT ANSWER FOR THIS CASE
+ * check('f', false);
+ */
+ check('g', false);
+ check('h', true);
+ check('i', true);
+ check('j', true); // 10
+ check('k', true);
+ check('l', true);
+ check('m', true);
+ check('n', true);
+ check('o', true);
+ check('p', false);
+ check('q', false);
+/* COMMENTED OUT BECAUSE THE CSSWG KEEP CHANGING THE RIGHT ANSWER FOR THESE TOO APPARENTLY
+ * check('r', true);
+ * check('s', true);
+ * check('t', true); // 20
+ */
+ check('u', false);
+ check('v', true);
+ check('w', true);
+ check('x', true);
+ // here the viewport is 0x0
+ check('y1', false); // 25
+ check('y2', false);
+ check('y3', false);
+ check('y4', true);
+ document.getElementById("selectors").setAttribute("style", "height: 100px; width: 100px");
+ // now the viewport is more than 1em by 1em
+ check('y1', true); // 29
+ check('y2', false);
+ check('y3', false);
+ check('y4', false);
+ document.getElementById("selectors").removeAttribute("style");
+ // here the viewport is 0x0 again
+ check('y1', false); // 33
+ check('y2', false);
+ check('y3', false);
+ check('y4', true);
+ return 3;
+ },
+ function () {
+ // test 47: 'cursor' and CSS3 values
+ var doc = getTestDocument();
+ var style = doc.createElement('style');
+ style.setAttribute('type', 'text/css');
+ var cursors = ['auto', 'default', 'none', 'context-menu', 'help', 'pointer', 'progress', 'wait', 'cell', 'crosshair', 'text', 'vertical-text', 'alias', 'copy', 'move', 'no-drop', 'not-allowed', 'e-resize', 'n-resize', 'ne-resize', 'nw-resize', 's-resize', 'se-resize', 'sw-resize', 'w-resize', 'ew-resize', 'ns-resize', 'nesw-resize', 'nwse-resize', 'col-resize', 'row-resize', 'all-scroll'];
+ for (var i in cursors) {
+ var c = cursors[i];
+ style.appendChild(doc.createTextNode('#' + c + ' { cursor: ' + c + '; }'));
+ }
+ style.appendChild(doc.createTextNode('#bogus { cursor: bogus; }'));
+ doc.body.previousSibling.appendChild(style);
+ doc.body.id = "bogus";
+ assertEquals(doc.defaultView.getComputedStyle(doc.body, '').cursor, "auto", "control failed");
+ for (var i in cursors) {
+ var c = cursors[i];
+ doc.body.id = c;
+ assertEquals(doc.defaultView.getComputedStyle(doc.body, '').cursor, c, "cursor " + c + " not supported");
+ }
+ return 3;
+ },
+ function () {
+ // test 48: :link and :visited
+ var iframe = document.getElementById("selectors");
+ var number = (new Date()).valueOf();
+ var a = document.createElement('a');
+ a.appendChild(document.createTextNode('LINKTEST FAILED'));
+ a.setAttribute('id', 'linktest');
+ a.setAttribute('class', 'pending');
+ a.setAttribute('href', iframe.getAttribute('src') + "?" + number);
+ document.getElementsByTagName('map')[0].appendChild(a);
+ iframe.setAttribute("onload", "document.getElementById('linktest').removeAttribute('class')");
+ iframe.src = a.getAttribute("href");
+ return 3;
+ },
+
+ // bucket 4: HTML and the DOM
+ // Tables
+ function () {
+ // test 49: basic table accessor ping test create*, delete*, and *
+ // where * is caption, tHead, tFoot.
+ var table = document.createElement('table');
+ assert(!table.caption, "initially: caption");
+ assert(table.tBodies, "initially: tBodies");
+ assertEquals(table.tBodies.length, 0, "initially: tBodies.length");
+ assert(table.rows, "initially: rows");
+ assertEquals(table.rows.length, 0, "initially: rows.length");
+ assert(!table.tFoot, "initially: tFoot");
+ assert(!table.tHead, "initially: tHead");
+ var caption = table.createCaption();
+ var thead = table.createTHead();
+ var tfoot = table.createTFoot();
+ assertEquals(table.caption, caption, "after creation: caption");
+ assert(table.tBodies, "after creation: tBodies");
+ assertEquals(table.tBodies.length, 0, "after creation: tBodies.length");
+ assert(table.rows, "after creation: rows");
+ assertEquals(table.rows.length, 0, "after creation: rows.length");
+ assertEquals(table.tFoot, tfoot, "after creation: tFoot");
+ assertEquals(table.tHead, thead, "after creation: tHead");
+ assertEquals(table.childNodes.length, 3, "after creation: childNodes.length");
+ table.caption = caption; // no-op
+ table.tHead = thead; // no-op
+ table.tFoot = tfoot; // no-op
+ assertEquals(table.caption, caption, "after setting: caption");
+ assert(table.tBodies, "after setting: tBodies");
+ assertEquals(table.tBodies.length, 0, "after setting: tBodies.length");
+ assert(table.rows, "after setting: rows");
+ assertEquals(table.rows.length, 0, "after setting: rows.length");
+ assertEquals(table.tFoot, tfoot, "after setting: tFoot");
+ assertEquals(table.tHead, thead, "after setting: tHead");
+ assertEquals(table.childNodes.length, 3, "after setting: childNodes.length");
+ table.deleteCaption();
+ table.deleteTHead();
+ table.deleteTFoot();
+ assert(!table.caption, "after deletion: caption");
+ assert(table.tBodies, "after deletion: tBodies");
+ assertEquals(table.tBodies.length, 0, "after deletion: tBodies.length");
+ assert(table.rows, "after deletion: rows");
+ assertEquals(table.rows.length, 0, "after deletion: rows.length");
+ assert(!table.tFoot, "after deletion: tFoot");
+ assert(!table.tHead, "after deletion: tHead");
+ assert(!table.hasChildNodes(), "after deletion: hasChildNodes()");
+ assertEquals(table.childNodes.length, 0, "after deletion: childNodes.length");
+ return 4;
+ },
+ function () {
+ // test 50: construct a table, and see if the table is as expected
+ var table = document.createElement('table');
+ table.appendChild(document.createElement('tbody'));
+ var tr1 = document.createElement('tr');
+ table.appendChild(tr1);
+ table.appendChild(document.createElement('caption'));
+ table.appendChild(document.createElement('thead'));
+ // <table><tbody/><tr/><caption/><thead/>
+ table.insertBefore(table.firstChild.nextSibling, null); // move the <tr/> to the end
+ // <table><tbody/><caption/><thead/><tr/>
+ table.replaceChild(table.firstChild, table.lastChild); // move the <tbody/> to the end and remove the <tr>
+ // <table><caption/><thead/><tbody/>
+ var tr2 = table.tBodies[0].insertRow(0);
+ // <table><caption/><thead/><tbody><tr/><\tbody> (the '\' is to avoid validation errors)
+ assertEquals(table.tBodies[0].rows[0].rowIndex, 0, "rowIndex broken");
+ assertEquals(table.tBodies[0].rows[0].sectionRowIndex, 0, "sectionRowIndex broken");
+ assertEquals(table.childNodes.length, 3, "wrong number of children");
+ assert(table.caption, "caption broken");
+ assert(table.tHead, "tHead broken");
+ assert(!table.tFoot, "tFoot broken");
+ assertEquals(table.tBodies.length, 1, "wrong number of tBodies");
+ assertEquals(table.rows.length, 1, "wrong number of rows");
+ assert(!tr1.parentNode, "orphan row has unexpected parent");
+ assertEquals(table.caption, table.createCaption(), "caption creation failed");
+ assertEquals(table.tFoot, null, "table has unexpected footer");
+ assertEquals(table.tHead, table.createTHead(), "header creation failed");
+ assertEquals(table.createTFoot(), table.tFoot, "footer creation failed");
+ // either: <table><caption/><thead/><tbody><tr/><\tbody><tfoot/>
+ // or: <table><caption/><thead/><tfoot/><tbody><tr/><\tbody>
+ table.tHead.appendChild(tr1);
+ // either: <table><caption/><thead><tr/><\thead><tbody><tr/><\tbody><tfoot/>
+ // or: <table><caption/><thead><tr/><\thead><tfoot/><tbody><tr/><\tbody>
+ assertEquals(table.rows[0], table.tHead.firstChild, "top row not in expected position");
+ assertEquals(table.rows.length, 2, "wrong number of rows after appending one");
+ assertEquals(table.rows[1], table.tBodies[0].firstChild, "second row not in expected position");
+ return 4;
+ },
+ function () {
+ // test 51: test the ordering and creation of rows
+ var table = document.createElement('table');
+ var rows = [
+ document.createElement('tr'), // 0: ends up first child of the tfoot
+ document.createElement('tr'), // 1: goes at the end of the table
+ document.createElement('tr'), // 2: becomes second child of thead
+ document.createElement('tr'), // 3: becomes third child of the thead
+ document.createElement('tr'), // 4: not in the table
+ table.insertRow(0), // 5: not in the table
+ table.createTFoot().insertRow(0) // 6: ends up second in the tfoot
+ ];
+ rows[6].parentNode.appendChild(rows[0]);
+ table.appendChild(rows[1]);
+ table.insertBefore(document.createElement('thead'), table.firstChild);
+ table.firstChild.appendChild(rows[2]);
+ rows[2].parentNode.appendChild(rows[3]);
+ rows[4].appendChild(rows[5].parentNode);
+ table.insertRow(0);
+ table.tFoot.appendChild(rows[6]);
+ assertEquals(table.rows.length, 6, "wrong number of rows");
+ assertEquals(table.getElementsByTagName('tr').length, 6, "wrong number of tr elements");
+ assertEquals(table.childNodes.length, 3, "table has wrong number of children");
+ assertEquals(table.childNodes[0], table.tHead, "tHead isn't first");
+ assertEquals(table.getElementsByTagName('tr')[0], table.tHead.childNodes[0], "first tr isn't in tHead correctly");
+ assertEquals(table.getElementsByTagName('tr')[1], table.tHead.childNodes[1], "second tr isn't in tHead correctly");
+ assertEquals(table.getElementsByTagName('tr')[1], rows[2], "second tr is the wrong row");
+ assertEquals(table.getElementsByTagName('tr')[2], table.tHead.childNodes[2], "third tr isn't in tHead correctly");
+ assertEquals(table.getElementsByTagName('tr')[2], rows[3], "third tr is the wrong row");
+ assertEquals(table.childNodes[1], table.tFoot, "tFoot isn't second");
+ assertEquals(table.getElementsByTagName('tr')[3], table.tFoot.childNodes[0], "fourth tr isn't in tFoot correctly");
+ assertEquals(table.getElementsByTagName('tr')[3], rows[0], "fourth tr is the wrong row");
+ assertEquals(table.getElementsByTagName('tr')[4], table.tFoot.childNodes[1], "fifth tr isn't in tFoot correctly");
+ assertEquals(table.getElementsByTagName('tr')[4], rows[6], "fifth tr is the wrong row");
+ assertEquals(table.getElementsByTagName('tr')[5], table.childNodes[2], "sixth tr isn't in tFoot correctly");
+ assertEquals(table.getElementsByTagName('tr')[5], rows[1], "sixth tr is the wrong row");
+ assertEquals(table.tBodies.length, 0, "non-zero number of tBodies");
+ return 4;
+ },
+
+ // Forms
+ function () {
+ // test 52: <form> and .elements
+ test = document.getElementsByTagName('form')[0];
+ assert(test.elements !== test, "form.elements === form");
+ assert(test.elements !== test.getAttribute('elements'), "form element has an elements content attribute");
+ assertEquals(test.elements.length, 1, "form element has unexpected number of controls");
+ assertEquals(test.elements.length, test.length, "form element has inconsistent numbers of controls");
+ return 4;
+ },
+ function () {
+ // test 53: changing an <input> dynamically
+ var f = document.createElement('form');
+ var i = document.createElement('input');
+ i.name = 'first';
+ i.type = 'text';
+ i.value = 'test';
+ f.appendChild(i);
+ assertEquals(i.getAttribute('name'), 'first', "name attribute wrong");
+ assertEquals(i.name, 'first', "name property wrong");
+ assertEquals(i.getAttribute('type'), 'text', "type attribute wrong");
+ assertEquals(i.type, 'text', "type property wrong");
+ assert(!i.hasAttribute('value'), "value attribute wrong");
+ assertEquals(i.value, 'test', "value property wrong");
+ assertEquals(f.elements.length, 1, "form's elements array has wrong size");
+ assertEquals(f.elements[0], i, "form's element array doesn't have input control by index");
+ assertEquals(f.elements.first, i, "form's element array doesn't have input control by name");
+ assertEquals(f.elements.second, null, "form's element array has unexpected controls by name");
+ i.name = 'second';
+ i.type = 'password';
+ i.value = 'TEST';
+ assertEquals(i.getAttribute('name'), 'second', "name attribute wrong after change");
+ assertEquals(i.name, 'second', "name property wrong after change");
+ assertEquals(i.getAttribute('type'), 'password', "type attribute wrong after change");
+ assertEquals(i.type, 'password', "type property wrong after change");
+ assert(!i.hasAttribute('value'), "value attribute wrong after change");
+ assertEquals(i.value, 'TEST', "value property wrong after change");
+ assertEquals(f.elements.length, 1, "form's elements array has wrong size after change");
+ assertEquals(f.elements[0], i, "form's element array doesn't have input control by index after change");
+ assertEquals(f.elements.second, i, "form's element array doesn't have input control by name after change");
+ assertEquals(f.elements.first, null, "form's element array has unexpected controls by name after change");
+ return 4;
+ },
+ function () {
+ // test 54: changing a parsed <input>
+ var i = document.getElementsByTagName('input')[0];
+ // initial values
+ assertEquals(i.getAttribute('type'), 'HIDDEN', "input control's type content attribute was wrong");
+ assertEquals(i.type, 'hidden', "input control's type DOM attribute was wrong");
+ // change values
+ i.name = 'test';
+ assertEquals(i.parentNode.elements.test, i, "input control's form didn't update");
+ // check event handlers
+ i.parentNode.action = 'javascript:';
+ var called = false;
+ i.parentNode.onsubmit = function (arg) {
+ arg.preventDefault();
+ called = true;
+ };
+ i.type = 'submit';
+ i.click(); // synchronously dispatches a click event to the submit button, which submits the form, which calls onsubmit
+ assert(called, "click handler didn't dispatch properly");
+ i.type = 'hIdDeN';
+ // check numeric attributes
+ i.setAttribute('maxLength', '2');
+ var s = i.getAttribute('maxLength');
+ assert(s.match, "attribute is not a String");
+ assert(!s.MIN_VALUE, "attribute is a Number");
+ return 4;
+ },
+ function () {
+ // test 55: moved checkboxes should keep their state
+ var container = document.getElementsByTagName("iframe")[0];
+ var input1 = document.createElement('input');
+ container.appendChild(input1);
+ input1.type = "checkbox";
+ input1.checked = true;
+ assert(input1.checked, "checkbox not checked after being checked (inserted first)");
+ var input2 = document.createElement('input');
+ input2.type = "checkbox";
+ container.appendChild(input2);
+ input2.checked = true;
+ assert(input2.checked, "checkbox not checked after being checked (inserted after type set)");
+ var input3 = document.createElement('input');
+ input3.type = "checkbox";
+ input3.checked = true;
+ container.appendChild(input3);
+ assert(input3.checked, "checkbox not checked after being checked (inserted after being checked)");
+ var target = document.getElementsByTagName("iframe")[1];
+ target.appendChild(input1);
+ target.appendChild(input2);
+ target.appendChild(input3);
+ assert(input1.checked, "checkbox 1 not checked after being moved");
+ assert(input2.checked, "checkbox 2 not checked after being moved");
+ assert(input3.checked, "checkbox 3 not checked after being moved");
+ return 4;
+ },
+ function () {
+ // test 56: cloned radio buttons should keep their state
+ var form = document.getElementsByTagName("form")[0];
+ var input1 = document.createElement('input');
+ input1.type = "radio";
+ input1.name = "radioGroup1";
+ form.appendChild(input1);
+ var input2 = input1.cloneNode(true);
+ input1.parentNode.appendChild(input2);
+ input1.checked = true;
+ assert(form.elements.radioGroup1, "radio group absent");
+ assert(input1.checked, "first radio button not checked");
+ assert(!input2.checked, "second radio button checked");
+ input2.checked = true;
+ assert(!input1.checked, "first radio button checked");
+ assert(input2.checked, "second radio button not checked");
+ var input3 = document.createElement('input');
+ input3.type = "radio";
+ input3.name = "radioGroup2";
+ form.appendChild(input3);
+ assert(!input3.checked, "third radio button checked");
+ input3.checked = true;
+ assert(!input1.checked, "first radio button newly checked");
+ assert(input2.checked, "second radio button newly not checked");
+ assert(input3.checked, "third radio button not checked");
+ input1.checked = true;
+ assert(input1.checked, "first radio button ended up not checked");
+ assert(!input2.checked, "second radio button ended up checked");
+ assert(input3.checked, "third radio button ended up not checked");
+ input1.parentNode.removeChild(input1);
+ input2.parentNode.removeChild(input2);
+ input3.parentNode.removeChild(input3);
+ return 4;
+ },
+ function () {
+ // test 57: HTMLSelectElement.add()
+ var s = document.createElement('select');
+ var o = document.createElement('option');
+ s.add(o, null);
+ assert(s.firstChild === o, "add() didn't add to firstChild");
+ assertEquals(s.childNodes.length, 1, "add() didn't add to childNodes");
+ assert(s.childNodes[0] === o, "add() didn't add to childNodes correctly");
+ assertEquals(s.options.length, 1, "add() didn't add to options");
+ assert(s.options[0] === o, "add() didn't add to options correctly");
+ return 4;
+ },
+ function () {
+ // test 58: HTMLOptionElement.defaultSelected
+ var s = document.createElement('select');
+ var o1 = document.createElement('option');
+ var o2 = document.createElement('option');
+ o2.defaultSelected = true;
+ var o3 = document.createElement('option');
+ s.appendChild(o1);
+ s.appendChild(o2);
+ s.appendChild(o3);
+ assert(s.options[s.selectedIndex] === o2, "defaultSelected didn't take");
+ return 4;
+ },
+ function () {
+ // test 59: attributes of <button> elements
+ var button = document.createElement('button');
+ assertEquals(button.type, "submit", "<button> doesn't have type=submit");
+ button.setAttribute("type", "button");
+ assertEquals(button.type, "button", "<button type=button> doesn't have type=button");
+ button.removeAttribute("type");
+ assertEquals(button.type, "submit", "<button> doesn't have type=submit back");
+ button.setAttribute('value', 'apple');
+ button.appendChild(document.createTextNode('banana'));
+ assertEquals(button.value, 'apple', "wrong button value");
+ return 4;
+ },
+
+ // Misc DOM2 HTML
+ function () {
+ // test 60: className vs "class" vs attribute nodes
+ var span = document.getElementsByTagName('span')[0];
+ span.setAttribute('class', 'kittens');
+ if (!span.getAttributeNode)
+ return 4; // support for attribute nodes is optional in Acid3, because attribute nodes might be removed from DOM Core in the future.
+ var attr = span.getAttributeNode('class');
+ // however, if they're supported, they'd better work:
+ assert(attr.specified, "attribute not specified");
+ assertEquals(attr.value, 'kittens', "attribute value wrong");
+ assertEquals(attr.name, 'class', "attribute name wrong");
+ attr.value = 'ocelots';
+ assertEquals(attr.value, 'ocelots', "attribute value wrong");
+ assertEquals(span.className, 'ocelots', "setting attribute value failed to be reflected in className");
+ span.className = 'cats';
+ assertEquals(attr.ownerElement.getAttribute('class'), 'cats', "setting attribute value failed to be reflected in getAttribute()");
+ span.removeAttributeNode(attr);
+ assert(attr.specified, "attribute not specified after removal");
+ assert(!attr.ownerElement, "attribute still owned after removal");
+ assert(!span.className, "element had class after removal");
+ return 4;
+ },
+ function () {
+ // test 61: className and the class attribute: space preservation
+ var p = document.createElement('p');
+ assert(!p.hasAttribute('class'), "element had attribute on creation");
+ p.setAttribute('class', ' te st ');
+ assert(p.hasAttribute('class'), "element did not have attribute after setting");
+ assertEquals(p.getAttribute('class'), ' te st ', "class attribute's value was wrong");
+ assertEquals(p.className, ' te st ', "className was wrong");
+ p.className = p.className.replace(/ /g, '\n');
+ assert(p.hasAttribute('class'), "element did not have attribute after replacement");
+ assertEquals(p.getAttribute('class'), '\nte\n\nst\n', "class attribute's value was wrong after replacement");
+ assertEquals(p.className, '\nte\n\nst\n', "className was wrong after replacement");
+ p.className = '';
+ assert(p.hasAttribute('class'), "element lost attribute after being set to empty string");
+ assertEquals(p.getAttribute('class'), '', "class attribute's value was wrong after being emptied");
+ assertEquals(p.className, '', "className was wrong after being emptied");
+ return 4;
+ },
+ function () {
+ // test 62: check that DOM attributes and content attributes aren't equivalent
+ var test;
+ // <div class="">
+ test = document.getElementsByTagName('div')[0];
+ assertEquals(test.className, 'buckets', "buckets: className wrong");
+ assertEquals(test.getAttribute('class'), 'buckets', "buckets: class wrong");
+ assert(!test.hasAttribute('className'), "buckets: element has className attribute");
+ assert(test.className != test.getAttribute('className'), "buckets: className attribute equals className property");
+ assert(!('class' in test), "buckets: element has class property")
+ test['class'] = "oil";
+ assert(test.className != "oil", "buckets: class property affected className");
+ // <label for="">
+ test = document.createElement('label');
+ test.htmlFor = 'jars';
+ assertEquals(test.htmlFor, 'jars', "jars: htmlFor wrong");
+ assertEquals(test.getAttribute('for'), 'jars', "jars: for wrong");
+ assert(!test.hasAttribute('htmlFor'), "jars: element has htmlFor attribute");
+ assert(test.htmlFor != test.getAttribute('htmlFor'), "jars: htmlFor attribute equals htmlFor property");
+ test = document.createElement('label');
+ test.setAttribute('for', 'pots');
+ assertEquals(test.htmlFor, 'pots', "pots: htmlFor wrong");
+ assertEquals(test.getAttribute('for'), 'pots', "pots: for wrong");
+ assert(!test.hasAttribute('htmlFor'), "pots: element has htmlFor attribute");
+ assert(test.htmlFor != test.getAttribute('htmlFor'), "pots: htmlFor attribute equals htmlFor property");
+ assert(!('for' in test), "pots: element has for property");
+ test['for'] = "oil";
+ assert(test.htmlFor != "oil", "pots: for property affected htmlFor");
+ // <meta http-equiv="">
+ test = document.createElement('meta');
+ test.setAttribute('http-equiv', 'boxes');
+ assertEquals(test.httpEquiv, 'boxes', "boxes: httpEquiv wrong");
+ assertEquals(test.getAttribute('http-equiv'), 'boxes', "boxes: http-equiv wrong");
+ assert(!test.hasAttribute('httpEquiv'), "boxes: element has httpEquiv attribute");
+ assert(test.httpEquiv != test.getAttribute('httpEquiv'), "boxes: httpEquiv attribute equals httpEquiv property");
+ test = document.createElement('meta');
+ test.httpEquiv = 'cans';
+ assertEquals(test.httpEquiv, 'cans', "cans: httpEquiv wrong");
+ assertEquals(test.getAttribute('http-equiv'), 'cans', "cans: http-equiv wrong");
+ assert(!test.hasAttribute('httpEquiv'), "cans: element has httpEquiv attribute");
+ assert(test.httpEquiv != test.getAttribute('httpEquiv'), "cans: httpEquiv attribute equals httpEquiv property");
+ assert(!('http-equiv' in test), "cans: element has http-equiv property");
+ test['http-equiv'] = "oil";
+ assert(test.httpEquiv != "oil", "cans: http-equiv property affected httpEquiv");
+ return 4;
+ },
+ function () {
+ // test 63: attributes of the <area> element
+ var area = document.getElementsByTagName('area')[0];
+ assertEquals(area.getAttribute('href'), '', "wrong value for href=''");
+ assertEquals(area.getAttribute('shape'), 'rect', "wrong value for shape=''");
+ assertEquals(area.getAttribute('coords'), '2,2,4,4', "wrong value for coords=''");
+ assertEquals(area.getAttribute('alt'), '<\'>', "wrong value for alt=''");
+ return 4;
+ },
+ function () {
+ // test 64: more attribute tests
+ // attributes of the <object> element
+ var obj1 = document.createElement('object');
+ obj1.setAttribute('data', 'test.html');
+ var obj2 = document.createElement('object');
+ obj2.setAttribute('data', './test.html');
+ assertEquals(obj1.data, obj2.data, "object elements didn't resolve URIs correctly");
+ assert(obj1.data.match(/^file:/), "object.data isn't absolute"); // changed by chase from /^http:/
+ obj1.appendChild(document.createElement('param'));
+ assertEquals(obj1.getElementsByTagName('param').length, 1, "object is missing its only child");
+ // non-existent attributes
+ var test = document.createElement('p');
+ assert(!('TWVvdywgbWV3Li4u' in test), "TWVvdywgbWV3Li4u unexpectedly found");
+ assertEquals(test.TWVvdywgbWV3Li4u, undefined, ".TWVvdywgbWV3Li4u wasn't undefined");
+ assertEquals(test['TWVvdywgbWV3Li4u'], undefined, "['TWVvdywgbWV3Li4u'] wasn't undefined");
+ test.setAttribute('TWVvdywgbWV3Li4u', 'woof');
+ assert(!('TWVvdywgbWV3Li4u' in test), "TWVvdywgbWV3Li4u unexpectedly found after setting");
+ assertEquals(test.TWVvdywgbWV3Li4u, undefined, ".TWVvdywgbWV3Li4u wasn't undefined after setting");
+ assertEquals(test['TWVvdywgbWV3Li4u'], undefined, "['TWVvdywgbWV3Li4u'] wasn't undefined after setting");
+ assertEquals(test.getAttribute('TWVvdywgbWV3Li4u'), 'woof', "TWVvdywgbWV3Li4u has wrong value after setting");
+ return 4;
+ },
+
+ // bucket 5: Tests from the Acid3 Competition
+ function () {
+ // test 65: bring in a couple of SVG files and some HTML files dynamically - preparation for later tests in this bucket
+ kungFuDeathGrip = document.createElement('p');
+ kungFuDeathGrip.className = 'removed';
+ var iframe, object;
+ // svg iframe
+ iframe = document.createElement('iframe');
+ iframe.onload = function () { kungFuDeathGrip.title += '1' };
+ iframe.src = "svg.svg"; // changed by chase from 'svg.xml'
+ kungFuDeathGrip.appendChild(iframe);
+ // object iframe
+ object = document.createElement('object');
+ object.onload = function () { kungFuDeathGrip.title += '2' };
+ object.data = "svg.svg"; // changed by chase from 'svg.xml'
+ kungFuDeathGrip.appendChild(object);
+ // xml iframe
+ iframe = document.createElement('iframe');
+ iframe.onload = function () { kungFuDeathGrip.title += '3' };
+ iframe.src = "empty.xml";
+ kungFuDeathGrip.appendChild(iframe);
+ // html iframe
+ iframe = document.createElement('iframe');
+ iframe.onload = function () { kungFuDeathGrip.title += '4' };
+ iframe.src = "empty.html";
+ kungFuDeathGrip.appendChild(iframe);
+ // html iframe
+ iframe = document.createElement('iframe');
+ iframe.onload = function () { kungFuDeathGrip.title += '5' };
+ iframe.src = "xhtml.1.xhtml"; // changed by chase from 'xhtml.1'
+ kungFuDeathGrip.appendChild(iframe);
+ // html iframe
+ iframe = document.createElement('iframe');
+ iframe.onload = function () { kungFuDeathGrip.title += '6' };
+ iframe.src = "xhtml.2.xhtml"; // changed by chase from 'xhtml.2'
+ kungFuDeathGrip.appendChild(iframe);
+ // html iframe
+ iframe = document.createElement('iframe');
+ iframe.onload = function () { kungFuDeathGrip.title += '7' };
+ iframe.src = "xhtml.3.xhtml"; // changed by chase from 'xhtml.3'
+ kungFuDeathGrip.appendChild(iframe);
+ // add the lot to the document
+ document.getElementsByTagName('map')[0].appendChild(kungFuDeathGrip);
+ return 5;
+ },
+ function () {
+ // test 66: localName on text nodes (and now other things), from Sylvain Pasche
+ assertEquals(document.createTextNode("test").localName, null, 'wrong localName for text node');
+ assertEquals(document.createComment("test").localName, null, 'wrong localName for comment node');
+ assertEquals(document.localName, null, 'wrong localName for document node');
+ return 5;
+ },
+ function () {
+ // test 67: removedNamedItemNS on missing attributes, from Sylvain Pasche
+ var p = document.createElement("p");
+ var msg = 'wrong exception raised';
+ try {
+ p.attributes.removeNamedItemNS("http://www.example.com/", "absent");
+ msg = 'no exception raised';
+ } catch (e) {
+ if ('code' in e) {
+ if (e.code == 8)
+ msg = '';
+ else
+ msg += '; code = ' + e.code;
+ }
+ }
+ assert(msg == '', "when calling removeNamedItemNS in a non existent attribute: " + msg);
+ return 5;
+ },
+ function () {
+ // test 68: UTF-16 surrogate pairs, from David Chan
+ //
+ // In The Unicode Standard 5.0, it is explicitly permitted to
+ // allow malformed UTF-16, that is, to leave the string alone.
+ // (http://www.unicode.org/versions/Unicode5.0.0):
+ //
+ // section 2.7: "...strings in ... ECMAScript are Unicode 16-bit
+ // strings, but are not necessarily well-formed UTF-16
+ // sequences. In normal processing, it can be far more
+ // efficient to allow such strings to contain code unit
+ // sequences that are not well-formed UTF-16 -- that is,
+ // isolated surrogates"
+ //
+ // On the other hand, if the application wishes to ensure
+ // well-formed character sequences, it may not permit the
+ // malformed sequence and it must regard the first codepoint as
+ // an error:
+ //
+ // Section 3.2: "C10. When a process interprets a code sequence
+ // which purports to be in a Unicode character encoding form, it
+ // shall treat ill-formed code unit sequences as an error
+ // condition and shall not interpret such sequences as
+ // characters.
+ // [...]
+ // For example, in UTF-8 every code unit of the form 110....2
+ // must be followed by a code unit of the form 10......2. A
+ // sequence such as 110.....2 0.......2 is ill-formed and must
+ // never be generated. When faced with this ill-formed code unit
+ // sequence while transforming or interpreting text, a
+ // conformant process must treat the first code unit 110.....2
+ // as an illegally terminated code unit sequence~Wfor example,
+ // by signaling an error, filtering the code unit out, or
+ // representing the code unit with a marker such as U+FFFD
+ // replacement character."
+ //
+ // So it would be permitted to do any of the following:
+ // 1) Leave the string alone
+ // 2) Remove the unpaired surrogate
+ // 3) Replace the unpaired surrogate with U+FFFD
+ // 4) Throw an exception
+
+ try {
+ var unpaired = String.fromCharCode(0xd863); // half a surrogate pair
+ var before = unpaired + "text";
+ var elt = document.createElement("input");
+ elt.value = before;
+ var after = elt.value;
+ }
+ catch(ex) {
+ return 5; // Unpaired surrogate caused an exception - ok
+ }
+ if (after == before && before.length == 5)
+ return 5; // Unpaired surrogate kept - ok
+ if (after == "text")
+ return 5; // Unpaired surrogate removed - ok
+ var replacement = String.fromCharCode(0xfffd);
+ if (after == replacement + "text")
+ return 5; // Unpaired surrogate replaced - ok
+ fail("Unpaired surrogate handled wrongly (input was '" + before + "', output was '" + after + "')");
+ },
+ function () {
+ // test 69: check that the support files loaded -- preparation for the rest of the tests in this bucket
+ assert(!(kungFuDeathGrip == null), "kungFuDeathGrip was null");
+ assert(!(kungFuDeathGrip.title == null), "kungFuDeathGrip.title was null");
+ if (kungFuDeathGrip.title.length < 7)
+ return "retry";
+ assert(!(kungFuDeathGrip.firstChild == null), "kungFuDeathGrip.firstChild was null");
+ assert(!(kungFuDeathGrip.firstChild.contentDocument == null), "kungFuDeathGrip.firstChild.contentDocument was null");
+ assert(!(kungFuDeathGrip.firstChild.contentDocument.getElementsByTagName == null), "kungFuDeathGrip.firstChild.contentDocument.getElementsByTagName was null");
+ var t = kungFuDeathGrip.firstChild.contentDocument.getElementsByTagName('text')[0];
+ assert(!(t == null), "t was null");
+ assert(!(t.parentNode == null), "t.parentNode was null");
+ assert(!(t.parentNode.removeChild == null), "t.parentNode.removeChild was null");
+ t.parentNode.removeChild(t);
+ return 5;
+ },
+ function () {
+ // test 70: XML encoding test
+ // the third child in kungFuDeathGrip is an ISO-8859-1 document sent as UTF-8.
+ // q.v. XML 1.0, section 4.3.3 Character Encoding in Entities
+ // this only tests one of a large number of conditions that should cause fatal errors
+ var doc = kungFuDeathGrip.childNodes[2].contentDocument;
+ if (!doc)
+ return 5;
+ if (doc.documentElement.tagName != "root")
+ return 5;
+ if (doc.documentElement.getElementsByTagName('test').length < 1)
+ return 5;
+ fail("UTF-8 encoded XML document with invalid character did not have a well-formedness error");
+ },
+ function () {
+ // test 71: HTML parsing, from Simon Pieters and Anne van Kesteren
+ var doc = kungFuDeathGrip.childNodes[3].contentDocument;
+ assert(doc, "missing document for test");
+ try {
+ // siblings
+ doc.open();
+ doc.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"><title><\/title><span><\/span><script type=\"text/javascript\"><\/script>");
+ doc.close();
+ assertEquals(doc.childNodes.length, 2, "wrong number of children in #document (first test)");
+ assertEquals(doc.firstChild.name, "HTML", "name wrong (first test)");
+ assertEquals(doc.firstChild.publicId, "-//W3C//DTD HTML 4.0 Transitional//EN", "publicId wrong (first test)");
+ if ((doc.firstChild.systemId != null) && (doc.firstChild.systemId != ""))
+ fail("systemId wrong (first test)");
+ if (('internalSubset' in doc.firstChild) || doc.firstChild.internalSubset)
+ assertEquals(doc.firstChild.internalSubset, null, "internalSubset wrong (first test)");
+ assertEquals(doc.documentElement.childNodes.length, 2, "wrong number of children in HTML (first test)");
+ assertEquals(doc.documentElement.firstChild.nodeName, "HEAD", "misplaced HEAD element (first test)");
+ assertEquals(doc.documentElement.firstChild.childNodes.length, 1, "wrong number of children in HEAD (first test)");
+ assertEquals(doc.documentElement.firstChild.firstChild.tagName, "TITLE", "misplaced TITLE element (first test)");
+ assertEquals(doc.documentElement.lastChild.nodeName, "BODY", "misplaced BODY element (first test)");
+ assertEquals(doc.documentElement.lastChild.childNodes.length, 2, "wrong number of children in BODY (first test)");
+ assertEquals(doc.documentElement.lastChild.firstChild.tagName, "SPAN", "misplaced SPAN element (first test)");
+ assertEquals(doc.documentElement.lastChild.lastChild.tagName, "SCRIPT", "misplaced SCRIPT element (first test)");
+ // parent/child
+ doc.open();
+ doc.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><title><\/title><span><script type=\"text/javascript\"><\/script><\/span>");
+ doc.close();
+ assertEquals(doc.childNodes.length, 2, "wrong number of children in #document (first test)");
+ assertEquals(doc.firstChild.name, "HTML", "name wrong (second test)");
+ assertEquals(doc.firstChild.publicId, "-//W3C//DTD HTML 4.01 Transitional//EN", "publicId wrong (second test)");
+ assertEquals(doc.firstChild.systemId, "http://www.w3.org/TR/html4/loose.dtd", "systemId wrong (second test)");
+ if (('internalSubset' in doc.firstChild) || doc.firstChild.internalSubset)
+ assertEquals(doc.firstChild.internalSubset, null, "internalSubset wrong (second test)");
+ assertEquals(doc.documentElement.childNodes.length, 2, "wrong number of children in HTML (second test)");
+ assertEquals(doc.documentElement.firstChild.nodeName, "HEAD", "misplaced HEAD element (second test)");
+ assertEquals(doc.documentElement.firstChild.childNodes.length, 1, "wrong number of children in HEAD (second test)");
+ assertEquals(doc.documentElement.firstChild.firstChild.tagName, "TITLE", "misplaced TITLE element (second test)");
+ assertEquals(doc.documentElement.lastChild.nodeName, "BODY", "misplaced BODY element (second test)");
+ assertEquals(doc.documentElement.lastChild.childNodes.length, 1, "wrong number of children in BODY (second test)");
+ assertEquals(doc.documentElement.lastChild.firstChild.tagName, "SPAN", "misplaced SPAN element (second test)");
+ assertEquals(doc.documentElement.lastChild.firstChild.firstChild.tagName, "SCRIPT", "misplaced SCRIPT element (second test)");
+ } finally {
+ // prepare the file for the next test
+ doc.open();
+ doc.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"><head><title><\/title><style type=\"text/css\">img { height: 10px; }<\/style><body><p><img src=\"data:image/gif;base64,R0lGODlhAQABAID%2FAMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw%3D%3D\" alt=\"\">");
+ doc.close();
+ }
+ return 5;
+ },
+ function () {
+ // test 72: dynamic modification of <style> blocks' text nodes, from Jonas Sicking and Garret Smith
+ var doc = kungFuDeathGrip.childNodes[3].contentDocument;
+ assert(doc, "missing document for test");
+ assert(doc.images[0], "prerequisite failed: no image");
+ assertEquals(doc.images[0].height, 10, "prerequisite failed: style didn't affect image");
+ doc.styleSheets[0].ownerNode.firstChild.data = "img { height: 20px; }";
+ assertEquals(doc.images[0].height, 20, "change failed to take effect");
+ doc.styleSheets[0].ownerNode.appendChild(doc.createTextNode("img { height: 30px; }"));
+ assertEquals(doc.images[0].height, 30, "append failed to take effect");
+ var rules = doc.styleSheets[0].cssRules; // "All CSS objects in the DOM are "live"" says section 2.1, Overview of the DOM Level 2 CSS Interfaces
+ doc.styleSheets[0].insertRule("img { height: 40px; }", 2);
+ assertEquals(doc.images[0].height, 40, "insertRule failed to take effect");
+ assertEquals(doc.styleSheets[0].cssRules.length, 3, "count of rules is wrong");
+ assertEquals(rules.length, 3, "cssRules isn't live");
+ // while we're at it, check some other things on doc.styleSheets:
+ assert(doc.styleSheets[0].href === null, "internal stylesheet had a URI: " + doc.styleSheets[0].href);
+ assert(document.styleSheets[0].href === null, "internal acid3 stylesheet had a URI: " + document.styleSheets[0].href);
+ return 5;
+ },
+ function () {
+ // test 73: nested events, from Jonas Sicking
+ var doc = kungFuDeathGrip.childNodes[3].contentDocument;
+ // implied events
+ var up = 0;
+ var down = 0;
+ var button = doc.createElement("button");
+ button.type = "button";
+ button.onclick = function () { up += 1; if (up < 10) button.click(); down += up; }; // not called
+ button.addEventListener('test', function () { up += 1; var e = doc.createEvent("HTMLEvents"); e.initEvent('test', false, false); if (up < 20) button.dispatchEvent(e); down += up; }, false);
+ var evt = doc.createEvent("HTMLEvents");
+ evt.initEvent('test', false, false);
+ button.dispatchEvent(evt);
+ assertEquals(up, 20, "test event handler called the wrong number of times");
+ assertEquals(down, 400, "test event handler called in the wrong order");
+ return 5;
+ },
+ function () {
+ // test 74: check getSVGDocument(), from Erik Dahlstrom
+ // GetSVGDocument[6]: "In the case where an SVG document is
+ // embedded by reference, such as when an XHTML document has an
+ // 'object' element whose href (or equivalent) attribute
+ // references an SVG document (i.e., a document whose MIME type
+ // is "image/svg+xml" and whose root element is thus an 'svg'
+ // element), the SVG user agent is required to implement the
+ // GetSVGDocument interface for the element which references the
+ // SVG document (e.g., the HTML 'object' or comparable
+ // referencing elements)."
+ //
+ // [6] http://www.w3.org/TR/SVG11/struct.html#InterfaceGetSVGDocument
+ //
+ // iframe
+ var iframe = kungFuDeathGrip.childNodes[0];
+ assert(iframe, "Failed finding svg iframe.");
+ assert(iframe.contentDocument, "contentDocument failed for <iframe> referencing an svg document.");
+ if (!iframe.getSVGDocument)
+ fail("getSVGDocument missing on <iframe> element.");
+ assert(iframe.getSVGDocument(), "getSVGDocument failed for <iframe> referencing an svg document.");
+ assert(iframe.getSVGDocument() == iframe.contentDocument, "Mismatch between getSVGDocument and contentDocument #1.");
+ // object
+ var object = kungFuDeathGrip.childNodes[1];
+ assert(object, "Failed finding svg object.");
+ assert(object.contentDocument, "contentDocument failed for <object> referencing an svg document.");
+ if (!object.getSVGDocument)
+ fail("getSVGDocument missing on <object> element.");
+ assert(object.getSVGDocument(), "getSVGDocument failed for <object> referencing an svg document.");
+ assert(object.getSVGDocument() == object.contentDocument, "Mismatch between getSVGDocument and contentDocument #2.");
+ return 5;
+ },
+ function () {
+ // test 75: SMIL in SVG, from Erik Dahlstrom
+ //
+ // The test begins by creating a few elements, among those is a
+ // <set> element. This element is prevented from running by
+ // setting begin="indefinite", which means that the animation
+ // doesn't start until the 'beginElement' DOM method is called
+ // on the <set> element. The animation is a simple animation
+ // that sets the value of the width attribute to 0. The duration
+ // of the animation is 'indefinite' which means that the value
+ // will stay 0 indefinitely. The target of the animation is the
+ // 'width' attribute of the <rect> element that is the parent of
+ // the <set> element. When 'width' is 0 the rect is not rendered
+ // according to the spec[7].
+ //
+ // Some properties of the SVGAnimatedLength[2] and SVGLength[8]
+ // are also inspected. Before the animation starts both baseVal
+ // and animVal contain the same values[2]. Then the animation is
+ // started by calling the beginElement method[9]. To make sure
+ // that time passes between the triggering of the animation and
+ // the time that the values are read out (in test #66), the
+ // current time is set to 1000 seconds using the setCurrentTime
+ // method[10].
+ //
+ // [2] http://www.w3.org/TR/SVG11/types.html#InterfaceSVGAnimatedLength
+ // [7] http://www.w3.org/TR/SVG11/shapes.html#RectElement
+ // [8] http://www.w3.org/TR/SVG11/types.html#InterfaceSVGLength
+ // [9] http://www.w3.org/TR/SVG11/animate.html#DOMInterfaces
+ // [10] http://www.w3.org/TR/SVG11/struct.html#InterfaceSVGSVGElement
+
+ var svgns = "http://www.w3.org/2000/svg";
+ var svgdoc = kungFuDeathGrip.firstChild.contentDocument;
+ assert(svgdoc, "contentDocument failed on <iframe> for svg document.");
+ var svg = svgdoc.documentElement;
+ var rect = svgdoc.createElementNS(svgns, "rect");
+ rect.setAttribute("fill", "red");
+ rect.setAttribute("width", "100");
+ rect.setAttribute("height", "100");
+ rect.setAttribute("id", "rect");
+ var anim = svgdoc.createElementNS(svgns, "set");
+ anim.setAttribute("begin", "indefinite");
+ anim.setAttribute("to", "0");
+ anim.setAttribute("attributeName", "width");
+ anim.setAttribute("dur", "indefinite");
+ anim.setAttribute("fill", "freeze");
+ rect.appendChild(anim);
+ svg.appendChild(rect);
+ assert(rect.width, "SVG DOM interface SVGRectElement not supported.");
+ assert(rect.width.baseVal, "SVG DOM base type SVGAnimatedLength not supported.");
+ assert(rect.width.animVal, "SVG DOM base type SVGAnimatedLength not supported.");
+ assertEquals(SVGLength.SVG_LENGTHTYPE_NUMBER, 1, "Incorrect SVGLength.SVG_LENGTHTYPE_NUMBER constant value.");
+ assertEquals(rect.width.baseVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER, "Incorrect unitType on width attribute.");
+ assertEquals(rect.getAttribute("width"), "100", "Incorrect value from getAttribute.");
+ assertEquals(rect.width.baseVal.valueInSpecifiedUnits, 100, "Incorrect valueInSpecifiedUnits value.");
+ assertEquals(rect.width.baseVal.value, 100, "Incorrect baseVal value before animation.");
+ assertEquals(rect.width.animVal.value, 100, "Incorrect animVal value before animation.");
+ anim.beginElement();
+ assertEquals(rect.width.baseVal.value, 100, "Incorrect baseVal value after starting animation.");
+ svg.setCurrentTime(1000); // setting 1 second to make sure that time != 0s when we check the animVal value
+ // the animation is then tested in the next test
+ return 5;
+ },
+ function () {
+ // test 76: SMIL in SVG, part 2, from Erik Dahlstrom
+ //
+ // About animVal[2]: "If the given attribute or property is
+ // being animated, contains the current animated value of the
+ // attribute or property, and both the object itself and its
+ // contents are readonly. If the given attribute or property is
+ // not currently being animated, contains the same value as
+ // 'baseVal'."
+ //
+ // Since the duration of the animation is indefinite the value
+ // is still being animated at the time it's queried. Now since
+ // the 'width' attribute was animated from its original value of
+ // "100" to the new value of "0" the animVal property must
+ // contain the value 0.
+ //
+ // [2] http://www.w3.org/TR/SVG11/types.html#InterfaceSVGAnimatedLength
+
+ var svgdoc = kungFuDeathGrip.firstChild.contentDocument;
+ assert(svgdoc, "contentDocument failed on <object> for svg document.");
+ var rect = svgdoc.getElementById("rect");
+ assert(rect, "Failed to find <rect> element in svg document.");
+ assertEquals(rect.width.animVal.value, 0, "Incorrect animVal value after svg animation.");
+ return 5;
+ },
+ function () {
+ // test 77: external SVG fonts, from Erik Dahlstrom
+ //
+ // SVGFonts are described here[3], and the relevant DOM methods
+ // used in the test are defined here[4].
+ //
+ // Note that in order to be more predictable the svg should be
+ // visible, so that clause "For non-rendering environments, the
+ // user agent shall make reasonable assumptions about glyph
+ // metrics." doesn't influence the results. We use 'opacity:0'
+ // to hide the SVG, but arguably it's still a "rendering
+ // environment".
+ //
+ // The font-size 4000 was chosen because that matches the
+ // unitsPerEm value in the svgfont, which makes it easy to check
+ // the glyph advances since they will then be exactly what was
+ // specified in the svgfont.
+ //
+ // [3] http://www.w3.org/TR/SVG11/fonts.html
+ // [4] http://www.w3.org/TR/SVG11/text.html#InterfaceSVGTextContentElement
+
+ var svgns = "http://www.w3.org/2000/svg";
+ var xlinkns = "http://www.w3.org/1999/xlink";
+ var svgdoc = kungFuDeathGrip.firstChild.contentDocument;
+ assert(svgdoc, "contentDocument failed on <object> for svg document.");
+ var svg = svgdoc.documentElement;
+ var text = svgdoc.createElementNS(svgns, "text");
+ text.setAttribute("y", "1em");
+ text.setAttribute("font-size", "4000");
+ text.setAttribute("font-family", "ACID3svgfont");
+ var textContent = svgdoc.createTextNode("abc");
+ text.appendChild(textContent);
+ svg.appendChild(text);
+ // The font-size 4000 was chosen because that matches the unitsPerEm value in the svgfont,
+ // which makes it easy to check the glyph advances since they will then be exactly what was specified in the svgfont.
+ assert(text.getNumberOfChars, "SVGTextContentElement.getNumberOfChars() not supported.");
+ assertEquals(text.getNumberOfChars(), 3, "getNumberOfChars returned incorrect string length.");
+ assertEquals(text.getComputedTextLength(), 4711+42+23, "getComputedTextLength failed.");
+ assertEquals(text.getSubStringLength(0,1), 42, "getSubStringLength #1 failed.");
+ assertEquals(text.getSubStringLength(0,2), 42+23, "getSubStringLength #2 failed.");
+ assertEquals(text.getSubStringLength(1,1), 23, "getSubStringLength #3 failed.");
+ assertEquals(text.getSubStringLength(1,0), 0, "getSubStringLength #4 failed.");
+/* COMMENTED OUT BECAUSE SVGWG KEEPS CHANGING THIS
+ * var code = -1000;
+ * try {
+ * var sl = text.getSubStringLength(1,3);
+ * } catch(e) {
+ * code = e.code;
+ * }
+ * assertEquals(code, DOMException.INDEX_SIZE_ERR, "getSubStringLength #1 didn't throw exception.");
+ * code = -1000;
+ * try {
+ * var sl = text.getSubStringLength(0,4);
+ * } catch(e) {
+ * code = e.code;
+ * }
+ * assertEquals(code, DOMException.INDEX_SIZE_ERR, "getSubStringLength #2 didn't throw exception.");
+ * code = -1000;
+ * try {
+ * var sl = text.getSubStringLength(3,0);
+ * } catch(e) {
+ * code = e.code;
+ * }
+ * assertEquals(code, DOMException.INDEX_SIZE_ERR, "getSubStringLength #3 didn't throw exception.");
+ */
+ code = -1000;
+ try {
+ var sl = text.getSubStringLength(-17,20);
+ } catch(e) {
+ code = 0; // negative values might throw native exception since the api accepts only unsigned values
+ }
+ assert(code == 0, "getSubStringLength #4 didn't throw exception.");
+ assertEquals(text.getStartPositionOfChar(0).x, 0, "getStartPositionOfChar(0).x returned invalid value.");
+ assertEquals(text.getStartPositionOfChar(1).x, 42, "getStartPositionOfChar(1).x returned invalid value.");
+ assertEquals(text.getStartPositionOfChar(2).x, 42+23, "getStartPositionOfChar(2).x returned invalid value.");
+ assertEquals(text.getStartPositionOfChar(0).y, 4000, "getStartPositionOfChar(0).y returned invalid value.");
+ code = -1000;
+ try {
+ var val = text.getStartPositionOfChar(-1);
+ } catch(e) {
+ code = 0; // negative values might throw native exception since the api accepts only unsigned values
+ }
+ assert(code == 0, "getStartPositionOfChar #1 exception failed.");
+ code = -1000;
+ try {
+ var val = text.getStartPositionOfChar(4);
+ } catch(e) {
+ code = e.code;
+ }
+ assertEquals(code, DOMException.INDEX_SIZE_ERR, "getStartPositionOfChar #2 exception failed.");
+ assertEquals(text.getEndPositionOfChar(0).x, 42, "getEndPositionOfChar(0).x returned invalid value.");
+ assertEquals(text.getEndPositionOfChar(1).x, 42+23, "getEndPositionOfChar(1).x returned invalid value.");
+ assertEquals(text.getEndPositionOfChar(2).x, 42+23+4711, "getEndPositionOfChar(2).x returned invalid value.");
+ code = -1000;
+ try {
+ var val = text.getEndPositionOfChar(-17);
+ } catch(e) {
+ code = 0; // negative values might throw native exception since the api accepts only unsigned values
+ }
+ assert(code == 0, "getEndPositionOfChar #1 exception failed.");
+ code = -1000;
+ try {
+ var val = text.getEndPositionOfChar(4);
+ } catch(e) {
+ code = e.code;
+ }
+ assertEquals(code, DOMException.INDEX_SIZE_ERR, "getEndPositionOfChar #2 exception failed.");
+ return 5;
+ },
+ function () {
+ // test 78: SVG textPath and getRotationOfChar(), from Erik Dahlstrom
+ //
+ // The getRotationOfChar[4] method fetches the midpoint rotation
+ // of a glyph defined by a character (in this testcase there is
+ // a simple 1:1 correspondence between the two). The path is
+ // defined in the svg.xml file, and consists of first a line
+ // going down, then followed by a line that has a 45 degree
+ // slope and then followed by a horizontal line. The length of
+ // each path segment have been paired with the advance of each
+ // glyph, so that each glyph will be on each of the three
+ // different path segments (see text on a path layout rules[5]).
+ // Thus the rotation of the first glyph is 90 degrees, the
+ // second 45 degrees and the third 0 degrees.
+ //
+ // [4] http://www.w3.org/TR/SVG11/text.html#InterfaceSVGTextContentElement
+ // [5] http://www.w3.org/TR/SVG11/text.html#TextpathLayoutRules
+
+ var svgns = "http://www.w3.org/2000/svg";
+ var xlinkns = "http://www.w3.org/1999/xlink";
+ var svgdoc = kungFuDeathGrip.firstChild.contentDocument;
+ assert(svgdoc, "contentDocument failed on <object> for svg document.");
+ var svg = svgdoc.documentElement;
+ var text = svgdoc.createElementNS(svgns, "text");
+ text.setAttribute("font-size", "4000");
+ text.setAttribute("font-family", "ACID3svgfont");
+ var textpath = svgdoc.createElementNS(svgns, "textPath");
+ textpath.setAttributeNS(xlinkns, "xlink:href", "#path");
+ var textContent = svgdoc.createTextNode("abc");
+ textpath.appendChild(textContent);
+ text.appendChild(textpath);
+ svg.appendChild(text);
+ assertEquals(text.getRotationOfChar(0), 90, "getRotationOfChar(0) failed.");
+ assertEquals(text.getRotationOfChar(1), 45, "getRotationOfChar(1) failed.");
+ assertEquals(text.getRotationOfChar(2), 0, "getRotationOfChar(2) failed.");
+ var code = -1000;
+ try {
+ var val = text.getRotationOfChar(-1)
+ } catch(e) {
+ code = e.code;
+ }
+ assertEquals(code, DOMException.INDEX_SIZE_ERR, "getRotationOfChar #1 exception failed.");
+ code = -1000;
+ try {
+ var val = text.getRotationOfChar(4)
+ } catch(e) {
+ code = e.code;
+ }
+ assertEquals(code, DOMException.INDEX_SIZE_ERR, "getRotationOfChar #2 exception failed.");
+ return 5;
+ },
+ function () {
+ // test 79: a giant test for <svg:font>, from Cameron McCormack
+ // This tests various features of SVG fonts from SVG 1.1. It consists of
+ // a <text> element with 33 characters, styled using an SVG font that has
+ // different advance values for each glyph. The script uses
+ // SVGTextElementContent.getStartPositionOfChar() to determine where the
+ // glyph corresponding to each character was placed, and thus to work out
+ // whether the SVG font was used correctly.
+ //
+ // The font uses 100 units per em, and the text is set in 100px. Since
+ // font-size gives the size of the em box
+ // (http://www.w3.org/TR/SVG11/text.html#DOMInterfaces), the scale of the
+ // coordinate system for the glyphs is the same as the SVG document.
+ //
+ // The expectedAdvances array holds the expected advance value for each
+ // character, and expectedKerning holds the (negative) kerning for each
+ // character. getPositionOfChar() returns the actual x coordinate for the
+ // glyph, corresponding to the given character, and if multiple characters
+ // correspond to the same glyph, the same position value is returned for
+ // each of those characters.
+ //
+ // Here are the reasonings for the advance/kerning values. Note that for
+ // a given character at index i, the expected position is
+ // sum(expectedAdvances[0:i-1] + expectedKerning[0:i-1]).
+ //
+ // char advance kerning reasoning
+ // ------- ------- ------- --------------------------------------------------
+ // A 10000 0 Normal character mapping to a single glyph.
+ // B 0 0 First character of a two character glyph, so the
+ // current position isn't advanced until the second
+ // character.
+ // C 200 0 Second character of a two character glyph, so now
+ // the position is advanced.
+ // B 300 0 Although there is a glyph for "BC" in the font,
+ // it appears after the glyph for "B", so the single
+ // character glyph for "B" should be chosen instead.
+ // D 1100 0 Normal character mapping to a single glyph.
+ // A 10000 200 Kerning of -200 is specified in the font between
+ // the "A" and "EE" glyphs.
+ // E 0 0 The first character of a two character glyph "EE".
+ // E 1300 0 The second character of a two character glyph.
+ // U 0 0 This is a glyph for the six characters "U+0046",
+ // which happen to look like a valid unicode range.
+ // This tests that the <glyph unicode=""> in the
+ // font matches exact strings rather than a range,
+ // as used in the kerning elements.
+ // + 0 0 Second character of six character glyph.
+ // 0 0 0 Third character of six character glyph.
+ // 0 0 0 Fourth character of six character glyph.
+ // 4 0 0 Fifth character of six character glyph.
+ // 6 1700 0 Sixth character of six character glyph.
+ // U 0 0 The same six character glyph that looks like a
+ // Unicode range. One of the kerning elements has
+ // u1="U+0046" u2="U+0046", which shouldn't match
+ // this, because those attributes are interpreted
+ // as Unicode ranges if they are, and normal
+ // strings otherwise. Thus there should be no
+ // kerning between these two glyphs.
+ // G 2300 200 Kerning is between this character and the next
+ // "G", since there is an <hkern> element that
+ // uses a Unicode range on its u1="" attribute
+ // and a glyph name on its g2="" attribute which
+ // both match "G".
+ // G 2300 0 Normal character with kerning before it.
+ // H 3100 0 A glyph with graphical content describing the
+ // glyph, rather than a d="" attribute.
+ // I 4300 0 Glyphs are checked in document order for one
+ // that matches, but the first glyph with
+ // unicode="I" also has lang="zh", which disqualifies
+ // it. Thus the second glyph with unicode="I"
+ // is chosen.
+ // I 4100 0 Since this I has xml:lang="zh" on it in the text,
+ // the first glyph with lang="zh" matches.
+ // J 4700 -4700 A normal glyph with kerning between the "J" and the
+ // next glyph "A" equal to the advance of the "J"
+ // glyph, so the position should stay the same.
+ // A 10000 0 Normal glyph with kerning before it.
+ // K 5900 0 The first glyph with unicode="K" does not match,
+ // since it has orientation="v", so the second
+ // glyph with unicode="K" is chosen.
+ // <spc> 6100 0 The space character should select the glyph with
+ // unicode=" ", despite it having a misleading
+ // glyph-name="L".
+ // L 6700 0 The "L" character should select the glyph with
+ // unicode=" ", despite it having a misleading
+ // glyph-name="spacev".
+ // A 2900 0 An <altGlyph> element is used to select the
+ // glyph for U+10085 instead of the one for "A".
+ // U+10085 2900 0 Tests glyph selection with a non-plane-0
+ // character.
+ // A 10000 0 A final normal character.
+ //
+ // In addition, the script tests the value returned by
+ // SVGTextContentElement.getNumberOfChars(), which in this case should be 34.
+ // If it returned 33, then it incorrectly counted Unicode characters instead
+ // of UTF-16 codepoints (probably).
+ //
+ // See http://www.w3.org/TR/SVG11/fonts.html for a description of the glyph
+ // matching rules, and http://www.w3.org/TR/SVG11/text.html#DOMInterfaces
+ // for a description of getStartPositionOfChar() and getNumberOfChars().
+ //
+ // Note also that the test uses DOMImplementation.createDocument() to create
+ // the SVG document. This seems to cause browsers trouble for the SVG DOM
+ // interfaces, since the document isn't being "rendered" as it might be
+ // if it were in an <iframe>. Changing the test to use an <iframe> will
+ // at least let you see the main part of the test running.
+
+ var NS = {
+ svg: 'http://www.w3.org/2000/svg',
+ xml: 'http://www.w3.org/XML/1998/namespace',
+ xlink: 'http://www.w3.org/1999/xlink'
+ };
+
+ var doc = kungFuDeathGrip.childNodes[1].contentDocument;
+ while (doc.hasChildNodes())
+ doc.removeChild(doc.firstChild);
+ doc.appendChild(doc.createElementNS(NS.svg, "svg:svg"));
+
+ var e = function (n, as, cs) {
+ var elt = doc.createElementNS(NS.svg, n);
+ if (as) {
+ for (var an in as) {
+ var idx = an.indexOf(':');
+ var ns = null;
+ if (idx != -1)
+ ns = NS[an.substring(0, idx)];
+ elt.setAttributeNS(ns, an, as[an]);
+ }
+ }
+ if (cs) {
+ for (var i in cs) {
+ var c = cs[i];
+ elt.appendChild(typeof c == 'string' ? doc.createTextNode(c) : c);
+ }
+ }
+ return elt;
+ }
+
+ doc.documentElement.appendChild(e('font', { 'horiz-adv-x': '10000'}, [e('font-face', { 'font-family': 'HCl', 'units-per-em': '100', 'ascent': '1000', 'descent': '500'}), e('missing-glyph', null, [e('path', { 'd': 'M100,0 h800 v-100 h-800 z'})]), e('glyph', { 'unicode': 'A', 'd': 'M100,0 h100 v-100 h-100 z'}), e('glyph', { 'unicode': 'BC', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '200'}), e('glyph', { 'unicode': 'B', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '300'}), e('glyph', { 'unicode': 'C', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '500'}), e('glyph', { 'unicode': 'BD', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '700'}), e('glyph', { 'unicode': 'D', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '1100'}), e('glyph', { 'unicode': 'EE', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '1300', 'glyph-name': 'grapefruit'}), e('glyph', { 'unicode': 'U+0046', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '1700'}), e('glyph', { 'unicode': 'F', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '1900'}), e('glyph', { 'unicode': 'G', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '2300', 'glyph-name': 'gee'}), e('glyph', { 'unicode': '\uD800\uDC85', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '2900', 'id': 'astral'}), e('glyph', { 'unicode': 'H', 'horiz-adv-x': '3100'}, [e('path', { 'd': 'M100,0 h100 v-100 h-100 z'})]), e('glyph', { 'unicode': 'I', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '4100', 'lang': 'zh'}), e('glyph', { 'unicode': 'I', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '4300'}), e('glyph', { 'unicode': 'J', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '4700'}), e('glyph', { 'unicode': 'K', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '5300', 'orientation': 'v'}), e('glyph', { 'unicode': 'K', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '5900'}), e('glyph', { 'unicode': ' ', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '6100', 'glyph-name': 'L'}), e('glyph', { 'unicode': 'L', 'd': 'M100,0 h100 v-100 h-100 z', 'horiz-adv-x': '6700', 'glyph-name': 'space'}), e('hkern', { 'u1': 'A', 'u2': 'EE', 'k': '1000'}), e('hkern', { 'u1': 'A', 'g2': 'grapefruit', 'k': '-200'}), e('hkern', { 'u1': 'U+0046', 'u2': 'U+0046', 'k': '-200'}), e('hkern', { 'u1': 'U+0047-0047', 'g2': 'gee', 'k': '-200'}), e('hkern', { 'u1': 'J', 'u2': 'A', 'k': '4700'})]));
+ doc.documentElement.appendChild(e('text', { 'y': '100', 'font-family': 'HCl', 'font-size': '100px', 'letter-spacing': '0px', 'word-spacing': '0px'}, ['ABCBDAEEU+0046U+0046GGHI', e('tspan', { 'xml:lang': 'zh'}, ['I']), 'JAK L', e('altGlyph', { 'xlink:href': '#astral'}, ['A']), '\uD800\uDC85A']));
+
+ var t = doc.documentElement.lastChild;
+
+ var characterDescriptions = [
+ "a normal character",
+ "the first character of a two-character glyph",
+ "the second character of a two-character glyph",
+ "a normal character, which shouldn't be the first character of a two-character glyph",
+ "a normal character, which shouldn't be the second character of a two-character glyph",
+ "a normal character, which has some kerning after it",
+ "the first character of a two-character glyph, which has some kerning before it",
+ "the second character of a two-character glyph, which has some kerning before it",
+ "the first character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning after it, but this glyph does not",
+ "the second character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning after it, but this glyph does not",
+ "the third character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning after it, but this glyph does not",
+ "the fourth character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning after it, but this glyph does not",
+ "the fifth character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning after it, but this glyph does not",
+ "the sixth character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning after it, but this glyph does not",
+ "the first character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning before it, but this glyph does not",
+ "the second character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning before it, but this glyph does not",
+ "the third character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning before it, but this glyph does not",
+ "the fourth character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning before it, but this glyph does not",
+ "the fifth character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning before it, but this glyph does not",
+ "the sixth character of a six-character glyph, which happens to look like a Unicode range, where the range-specified glyph has kerning before it, but this glyph does not",
+ "a normal character, which has some kerning after it that is specified by glyph name",
+ "a normal character, which has some kerning before it that is specified by glyph name",
+ "a normal character, whose glyph is given by child graphical content of the <glyph> element",
+ "a normal character, whose glyph should not match the one with a lang=\"\" attribute on it",
+ "a normal character, whose glyph should match the one with a lang=\"\" attribute on it",
+ "a normal character, which has some kerning after it that is equal to the advance of the character",
+ "a normal character, which has some kerning before it that is equal to the advance of the previous character",
+ "a normal character, whose glyph should not match the one with an orientation=\"v\" attribute on it",
+ "a space character, which has a misleading glyph-name=\"\" attribute",
+ "a normal character, which has a misleading glyph-name=\"\" attribute",
+ "a normal character, whose glyph is chosen to be another by using <altGlyph>",
+ "a character not in Plane 0 (high surrogate pair)",
+ "a character not in Plane 0 (low surrogate pair)",
+ "a normal character",
+ ];
+
+ var expectedAdvances = [
+ 10000, // A
+ 0, // BC [0]
+ 200, // BC [1]
+ 300, // B
+ 1100, // D
+ 10000, // A
+ 0, // EE [0]
+ 1300, // EE [1]
+ 0, // U+0046 [0]
+ 0, // U+0046 [1]
+ 0, // U+0046 [2]
+ 0, // U+0046 [3]
+ 0, // U+0046 [4]
+ 1700, // U+0046 [5]
+ 0, // U+0046 [0]
+ 0, // U+0046 [1]
+ 0, // U+0046 [2]
+ 0, // U+0046 [3]
+ 0, // U+0046 [4]
+ 1700, // U+0046 [5]
+ 2300, // G
+ 2300, // G
+ 3100, // H
+ 4300, // I
+ 4100, // I (zh)
+ 4700, // J
+ 10000, // A
+ 5900, // K
+ 6100, // <space>
+ 6700, // L
+ 2900, // A (using &#x10085; altGlyph)
+ 0, // &#x10085; high surrogate pair
+ 2900, // &#x10085; low surrogate pair
+ 10000, // A
+ ];
+
+ var expectedKerning = [
+ 0, // A
+ 0, // BC [0]
+ 0, // BC [1]
+ 0, // B
+ 0, // D
+ 200, // A
+ 0, // EE [0]
+ 0, // EE [1]
+ 0, // U+0046 [0]
+ 0, // U+0046 [1]
+ 0, // U+0046 [2]
+ 0, // U+0046 [3]
+ 0, // U+0046 [4]
+ 0, // U+0046 [5]
+ 0, // U+0046 [0]
+ 0, // U+0046 [1]
+ 0, // U+0046 [2]
+ 0, // U+0046 [3]
+ 0, // U+0046 [4]
+ 0, // U+0046 [5]
+ 200, // G
+ 0, // G
+ 0, // H
+ 0, // I
+ 0, // I (zh)
+ -4700, // J
+ 0, // A
+ 0, // K
+ 0, // <space>
+ 0, // L
+ 0, // A (using &#x10085; altGlyph)
+ 0, // &#x10085; high surrogate pair
+ 0, // &#x10085; low surrogate pair
+ 0, // A
+ ];
+
+ assertEquals(t.getNumberOfChars(), expectedAdvances.length, 'SVGSVGTextElement.getNumberOfChars() incorrect');
+
+ var expectedPositions = [0];
+ for (var i = 0; i < expectedAdvances.length; i++)
+ expectedPositions.push(expectedPositions[i] + expectedAdvances[i] + expectedKerning[i]);
+
+ var actualPositions = [];
+ for (var i = 0; i < t.getNumberOfChars(); i++)
+ actualPositions.push(t.getStartPositionOfChar(i).x);
+ actualPositions.push(t.getEndPositionOfChar(t.getNumberOfChars() - 1).x);
+
+ for (var i = 0; i < expectedPositions.length; i++) {
+ if (expectedPositions[i] != actualPositions[i]) {
+ var s = "character position " + i + ", which is ";
+ if (i == 0) {
+ s += "before " + characterDescriptions[0];
+ } else if (i == expectedPositions.length - 1) {
+ s += "after " + characterDescriptions[characterDescriptions.length - 1];
+ } else {
+ s += "between " + characterDescriptions[i - 1] + " and " + characterDescriptions[i];
+ }
+ s += ", is " + actualPositions[i] + " but should be " + expectedPositions[i] + ".";
+ fail(s);
+ }
+ }
+ return 5;
+ },
+ function () {
+ // test 80: remove the iframes and the object
+ assert(!(kungFuDeathGrip == null), "kungFuDeathGrip was null");
+ assert(!(kungFuDeathGrip.parentNode == null), "kungFuDeathGrip.parentNode was null");
+ kungFuDeathGrip.parentNode.removeChild(kungFuDeathGrip);
+ kungFuDeathGrip = null;
+ // check that the xhtml files worked right
+ assert(notifications['xhtml.1'], "Script in XHTML didn't execute");
+ assert(!notifications['xhtml.2'], "XML well-formedness error didn't stop script from executing");
+ assert(!notifications['xhtml.3'], "Script executed despite having wrong namespace");
+ // while we're at it, check that the linktest is loaded
+ // since the other iframes have forcibly loaded by now, we assume that
+ // there's no way this can't have loaded by now
+ // (probably a safe bet)
+ var a = document.links[1];
+ assert(!(a == null), "linktest was null");
+ assert(a.textContent == "LINKTEST FAILED", "linktest link couldn't be found");
+ if (a.hasAttribute('class'))
+ return "retry"; // linktest onload didn't fire -- could be a networking issue, check that first
+ return 5;
+ },
+
+ // bucket 6: ECMAScript
+ function () {
+ // test 81: length of arrays with elisions at end
+ var t1 = [,];
+ var t2 = [,,];
+ assertEquals(t1.length, 1, "[,] doesn't have length 1");
+ assertEquals(t2.length, 2, "[,,] doesn't have length 2");
+ return 6;
+ },
+ function () {
+ // test 82: length of arrays with elisions in the middle
+ var t3 = ['a', , 'c'];
+ assertEquals(t3.length, 3, "['a',,'c'] doesn't have length 3");
+ assert(0 in t3, "no 0 in t3");
+ assert(!(1 in t3), "unexpected 1 in t3");
+ assert(2 in t3, "no 2 in t3");
+ assertEquals(t3[0], 'a', "t3[0] wrong");
+ assertEquals(t3[2], 'c', "t3[2] wrong");
+ return 6;
+ },
+ function () {
+ // test 83: array methods
+ var x = ['a', 'b', 'c'];
+ assertEquals(x.unshift('A', 'B', 'C'), 6, "array.unshift() returned the wrong value");
+ var s = x.join(undefined);
+ assertEquals(s, 'A,B,C,a,b,c', "array.join(undefined) used wrong separator"); // qv 15.4.4.5:3
+ return 6;
+ },
+ function () {
+ // test 84: converting numbers to strings
+ assertEquals((0.0).toFixed(4), "0.0000", "toFixed(4) wrong for 0");
+ assertEquals((-0.0).toFixed(4), "0.0000", "toFixed(4) wrong for -0");
+ assertEquals((0.00006).toFixed(4), "0.0001", "toFixed(4) wrong for 0.00006");
+ assertEquals((-0.00006).toFixed(4), "-0.0001", "toFixed(4) wrong for -0.00006");
+ assertEquals((0.0).toExponential(4), "0.0000e+0", "toExponential(4) wrong for 0");
+ assertEquals((-0.0).toExponential(4), "0.0000e+0", "toExponential(4) wrong for -0");
+ var x = 7e-4;
+ assertEquals(x.toPrecision(undefined), x.toString(undefined), "toPrecision(undefined) was wrong");
+ return 6;
+ },
+ function () {
+ // test 85: strings and string-related operations
+ // substr() and negative numbers
+ assertEquals("scathing".substr(-7, 3), "cat", "substr() wrong with negative numbers");
+ return 6;
+ },
+ function () {
+ // test 86: Date tests -- methods passed no arguments
+ var d = new Date();
+ assert(isNaN(d.setMilliseconds()), "calling setMilliseconds() with no arguments didn't result in NaN");
+ assert(isNaN(d), "date wasn't made NaN");
+ assert(isNaN(d.getDay()), "date wasn't made NaN");
+ return 6;
+ },
+ function () {
+ // test 87: Date tests -- years
+ var d1 = new Date(Date.UTC(99.9, 6));
+ assertEquals(d1.getUTCFullYear(), 1999, "Date.UTC() didn't do proper 1900 year offsetting");
+ var d2 = new Date(98.9, 6);
+ assertEquals(d2.getFullYear(), 1998, "new Date() didn't do proper 1900 year offsetting");
+ return 6;
+ },
+ function () {
+ // test 88: ES3 section 7.6:3 (unicode escapes can't be used to put non-identifier characters into identifiers)
+ // and there's no other place for them in the syntax (other than strings, of course)
+ var ok = false;
+ try {
+ eval("var test = { };\ntest.i= 0;\ntest.i\\u002b= 1;\ntest.i;\n");
+ } catch (e) {
+ ok = true;
+ }
+ assert(ok, "\\u002b was not considered a parse error in script");
+ return 6;
+ },
+ function () {
+ // test 89: Regular Expressions
+ var ok = true;
+ // empty classes in regexps
+ try {
+ eval("/TA[])]/.exec('TA]')");
+ // JS regexps aren't like Perl regexps, if their character
+ // classes start with a ] that means they're empty. So this
+ // is a syntax error; if we get here it's a bug.
+ ok = false;
+ } catch (e) { }
+ assert(ok, "orphaned bracket not considered parse error in regular expression literal");
+ try {
+ if (eval("/[]/.exec('')"))
+ ok = false;
+ } catch (e) {
+ ok = false;
+ }
+ assert(ok, "/[]/ either failed to parse or matched something");
+ return 6;
+ },
+ function () {
+ // test 90: Regular Expressions
+ // not back references.
+ assert(!(/(1)\0(2)/.test("12")), "NUL in regexp incorrectly ignored");
+ assert((/(1)\0(2)/.test("1" + "\0" + "2")), "NUL in regexp didn't match correctly");
+ assert(!(/(1)\0(2)/.test("1\02")), "octal 2 unexpectedly matched NUL");
+ assertEquals(nullInRegexpArgumentResult, "passed", "failed //.test() check"); // nothing to see here, move along now
+ // back reference to future capture
+ var x = /(\3)(\1)(a)/.exec('cat'); // the \3 matches the empty string, qv. ES3:15.10.2.9
+ assert(x, "/(\\3)(\\1)(a)/ failed to match 'cat'");
+ assertEquals(x.length, 4, "/(\\3)(\\1)(a)/ failed to return four components");
+ assertEquals(x[0], "a", "/(\\3)(\\1)(a)/ failed to find 'a' in 'cat'");
+ assert(x[1] === "", "/(\\3)(\\1)(a)/ failed to find '' in 'cat' as first part");
+ assert(x[2] === "", "/(\\3)(\\1)(a)/ failed to find '' in 'cat' as second part");
+ assertEquals(x[3], "a", "/(\\3)(\\1)(a)/ failed to find 'a' in 'cat' as third part");
+ // negative lookahead
+ x = /(?!(text))(te.t)/.exec("text testing");
+ assertEquals(x.length, 3, "negative lookahead test failed to return the right number of bits");
+ assertEquals(x[0], "test", "negative lookahead test failed to find the right text");
+ assert(x[1] === undefined, "negative lookahead test failed to return undefined for negative lookahead capture");
+ assert(x[2] === "test", "negative lookahead test failed to find the right second capture");
+ return 6;
+ },
+ function () {
+ // test 91: check that properties are enumerable by default
+ var test = {
+ constructor: function() { return 1; },
+ toString: function() { return 2; },
+ toLocaleString: function() { return 3; },
+ valueOf: function() { return 4; },
+ hasOwnProperty: function() { return 5; },
+ isPrototypeOf: function() { return 6; },
+ propertyIsEnumerable: function() { return 7; },
+ prototype: function() { return 8; },
+ length: function() { return 9; },
+ unique: function() { return 10; }
+ };
+ var results = [];
+ for (var property in test)
+ results.push([test[property](), property]);
+ results.sort(function(a, b) {
+ if (a[0] < b[0]) return -1;
+ if (a[0] > b[0]) return 1;
+ return 0;
+ });
+ assertEquals(results.length, 10, "missing properties");
+ for (var index = 0; index < 10; index += 1)
+ assertEquals(results[index][0], index+1, "order wrong at results["+index+"] == ");
+ var index = 0;
+ assertEquals(results[index++][1], "constructor", "failed to find constructor in expected position");
+ assertEquals(results[index++][1], "toString", "failed to find toString in expected position");
+ assertEquals(results[index++][1], "toLocaleString", "failed to find toLocaleString in expected position");
+ assertEquals(results[index++][1], "valueOf", "failed to find valueOf in expected position");
+ assertEquals(results[index++][1], "hasOwnProperty", "failed to find hasOwnProperty in expected position");
+ assertEquals(results[index++][1], "isPrototypeOf", "failed to find isPrototypeOf in expected position");
+ assertEquals(results[index++][1], "propertyIsEnumerable", "failed to find propertyIsEnumerable in expected position");
+ assertEquals(results[index++][1], "prototype", "failed to find prototype in expected position");
+ assertEquals(results[index++][1], "length", "failed to find length in expected position");
+ assertEquals(results[index++][1], "unique", "failed to find unique in expected position");
+ return 6;
+ },
+ function () {
+ // test 92: internal properties of Function objects
+ // constructor is not ReadOnly
+ var f1 = function () { 1 };
+ f1.prototype.constructor = "hello world";
+ var f1i = new f1();
+ assert(f1i.constructor === "hello world", "Function object's prototype's constructor was ReadOnly");
+ // constructor is DontEnum (indeed, no properties at all on a new Function object)
+ var f2 = function () { 2 };
+ var f2i = new f2();
+ var count = 0;
+ for (var property in f2i) {
+ assert(property != "constructor", "Function object's prototype's constructor was not DontEnum");
+ count += 1;
+ }
+ assertEquals(count, 0, "Function object had unexpected properties");
+ // constructor is not DontDelete
+ var f3 = function (a, b) { 3 };
+ delete f3.prototype.constructor;
+ var f3i = new f3();
+ assertEquals(f3i.constructor, Object.prototype.constructor, "Function object's prototype's constructor was DontDelete (or got magically replaced)");
+ return 6;
+ },
+ function () {
+ // test 93: FunctionExpression semantics
+ var functest;
+ var vartest = 0;
+ var value = (function functest(arg) {
+ if (arg)
+ return 1;
+ vartest = 1;
+ functest = function (arg) { return 2; }; // this line does nothing as 'functest' is ReadOnly here
+ return functest(true); // this is therefore tail recursion and returns 1
+ })(false);
+ assertEquals(vartest, 1, "rules in 10.1.4 not followed in FunctionBody");
+ assertEquals(value, 1, "semantics of FunctionExpression: function Identifier ... not followed");
+ assert(!functest, "Property in step 4 of FunctionExpression: function Identifier ... leaked to parent scope");
+ return 6;
+ },
+ function () {
+ // test 94: exception scope
+ var test = 'pass';
+ try {
+ throw 'fail';
+ } catch (test) {
+ test += 'ing';
+ }
+ assertEquals(test, 'pass', 'outer scope poisoned by exception catch{} block');
+ return 6;
+ },
+ function () {
+ // test 95: types of expressions
+ var a = []; var s;
+ s = a.length = "2147483648";
+ assertEquals(typeof s, "string", "type of |\"2147483648\"| is not string");
+ return 6;
+ },
+ function () {
+ // test 96: encodeURI() and encodeURIComponent() and null bytes
+ assertEquals(encodeURIComponent(String.fromCharCode(0)), '%00', "encodeURIComponent failed to encode U+0000");
+ assertEquals(encodeURI(String.fromCharCode(0)), '%00', "encodeURI failed to encode U+0000");
+ return 6;
+ },
+
+ // URIs
+ function () {
+ // test 97: data: URI parsing
+ assertEquals(d1, "one", "data: failed as escaped");
+ assertEquals(d2, "two", "data: failed as base64");
+ assertEquals(d3, "three", "data: failed as base64 escaped");
+ assertEquals(d4, "four", "data: failed as base64 with spaces");
+ assertEquals(d5, "five's", "data: failed with backslash");
+ return 7;
+ },
+
+ // XHTML
+ function () {
+ // test 98: XHTML and the DOM
+ // (special test)
+ var doctype = document.implementation.createDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
+ assertEquals(doctype.ownerDocument, null, "doctype's ownerDocument was wrong after creation");
+ var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", doctype);
+ doc.documentElement.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "head"));
+ doc.documentElement.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "body"));
+ var t = doc.createElementNS("http://www.w3.org/1999/xhtml", "title");
+ doc.documentElement.firstChild.appendChild(t);
+ // ok we have a conforming XHTML1 doc in |doc| now.
+ assertEquals(doctype.ownerDocument, doc, "doctype's ownerDocument didn't change when it was assigned to another document");
+ assertEquals(doc.title, "", "document had unexpected title");
+ t.textContent = "Sparrow";
+ assertEquals(doc.title, "Sparrow", "document.title did not update dynamically");
+ doc.body.appendChild(doc.createElementNS("http://www.w3.org/1999/xhtml", "form"));
+ assertEquals(doc.forms.length, 1, "document.forms not updated after inserting a form");
+ return 7;
+ },
+
+ // Sanity
+ function () {
+ // test 99: check for the weirdest bug ever
+ var a = document.createElement('a');
+ a.setAttribute('href', 'http://www.example.com/');
+ a.appendChild(document.createTextNode('www.example.com'));
+ a.href = 'http://hixie.ch/';
+ assertEquals(a.firstChild.data, "www.example.com", "sanity did not prevail");
+ a.href = 'http://damowmow.com/';
+ assertEquals(a.firstChild.data, "www.example.com", "final test failed");
+ return 7;
+ }
+
+ ];
+ var log = '';
+ var delay = 10;
+ var score = 0, index = 0, retry = 0, errors = 0;
+ function update() {
+ var span = document.getElementById('score'); // not cached by JS
+ span.nextSibling.removeAttribute('class'); // no-op after first loop
+ span.nextSibling.nextSibling.firstChild.data = tests.length; // no-op after first loop
+ if (index < tests.length) {
+ var zeroPaddedIndex = index < 10 ? '0' + index : index;
+ try {
+ var beforeTest = new Date();
+ var result = tests[index]();
+ var elapsedTest = new Date() - beforeTest;
+ if (result == "retry") {
+ // some tests uses this magical mechanism to wait for support files to load
+ // we will give this test 500 attempts (5000ms) before aborting
+ retry += 1;
+ if (retry < 500) {
+ setTimeout(update, delay);
+ return;
+ }
+ fail("timeout -- could be a networking issue");
+ } else if (result) {
+ var bucket = document.getElementById('bucket' + result);
+ if (bucket)
+ bucket.className += 'P';
+ score += 1;
+ if (retry > 0) {
+ errors += 1;
+ log += "Test " + zeroPaddedIndex + " passed, but took " + retry + " attempts (less than perfect).\n";
+ } else if (elapsedTest > 33) { // 30fps
+ errors += 1;
+ log += "Test " + zeroPaddedIndex + " passed, but took " + elapsedTest + "ms (less than 30fps)\n";
+ }
+ } else {
+ fail("no error message");
+ }
+ } catch (e) {
+ var s;
+ if (e.message)
+ s = e.message.replace(/\s+$/, "");
+ else
+ s = e;
+ errors += 1;
+ log += "Test " + zeroPaddedIndex + " failed: " + s + "\n";
+ };
+ retry = 0;
+ index += 1;
+ span.firstChild.data = score;
+ setTimeout(update, delay);
+ } else {
+ var endTime = new Date();
+ var elapsedTime = ((endTime - startTime) - (delay * tests.length)) / 1000;
+ log += "Total elapsed time: " + elapsedTime.toFixed(2) + "s";
+ if (errors == 0)
+ log += "\nNo JS errors and no timing issues.\nWas the rendering pixel-for-pixel perfect too?";
+ test_complete(tests.length - score, endTime - startTime);
+ }
+ }
+ function running() {
+ if (index < tests.length) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ function report(event) {
+ // for debugging either click the "A" in "Acid3" (to get an alert) or shift-click it (to get a report)
+ if (event.shiftKey) {
+ var w = window.open();
+ w.document.write('<pre>Failed ' + (tests.length - score) + ' of ' + tests.length + ' tests.\n' +
+ log.replace(/&/g,'&amp;').replace(RegExp('<', 'g'), '&lt;').replace('\0', '\\0') +
+ '<\/pre>');
+ w.document.close();
+ } else {
+ alert('Failed ' + (tests.length - score) + ' test' + (score == 1 ? '' : 's') + '.\n' + log)
+ }
+ }
+ </script>
+ <script src="head.js"></script>
+ <body onload="update() /* this attribute's value is tested in one of the tests */ ">
+ <h1 onclick="report(event)">Acid3</h1>
+ <div class="buckets"
+ ><p id="bucket1" class="z"></p
+ ><p id="bucket2" class="z"></p
+ ><p id="bucket3" class="z"></p
+ ><p id="bucket4" class="z"></p
+ ><p id="bucket5" class="z"></p
+ ><p id="bucket6" class="z"></p>
+ </div>
+ <p id="result"><span id="score">JS</span><span id="slash" class="hidden">/</span><span>?</span></p>
+ <!-- The following line is used in a number of the tests. It is done using document.write() to sidestep complaints of validity. -->
+ <script type="text/javascript">document.write('<map name=""><area href="" shape="rect" coords="2,2,4,4" alt="<\'>"><iframe src="empty.png">FAIL<\/iframe><iframe src="empty.txt">FAIL<\/iframe><iframe src="empty.html" id="selectors"><\/iframe><form action="" name="form"><input type=HIDDEN><\/form><table><tr><td><p><\/tbody> <\/table><\/map>');</script>
+ <p id="instructions">To pass the test,<span></span> a browser must use its default settings, the animation has to be smooth, the score has to end on 100/100, and the final page has to look exactly, pixel for pixel, like <a href="reference.html">this reference rendering</a>.</p>
+ <p id="remove-last-child-test">Scripting must be enabled to use this test.</p>
+ </body>
+</html>
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/reference.html b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/reference.html
new file mode 100644
index 00000000000..22b10f2a99c
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/reference.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+ <title>The Acid3 Test (Reference Rendering)</title>
+ <link rel="icon" href="http://example.invalid/">
+ <style type="text/css">
+ html { margin: 0; padding: 0; }
+ body { background: #c0c0c0 url(reference.png) top left no-repeat; margin: 0; padding: 0; }
+ #a { font: bold 100px/120px Arial, sans-serif; position: absolute; top: 57px; left: 57px; color: #000000; z-index: 1; }
+ #a0 { font: bold 100px/120px Arial, sans-serif; position: absolute; top: 60px; left: 60px; color: #C0C0C0; z-index: 0; }
+ #b { position: absolute; top: 230px; left: 625px; width: 0; white-space: pre; }
+ #b div { font: bold 100px/120px Arial, sans-serif; position: absolute; right: 0; text-align: right; color: #000000; }
+ #c { font: 16px/19.2px Arial, sans-serif; color: #808080; width: 562px; position: absolute; top: 350px; left: 57px; }
+ #c a { color: #0000FF; }
+ </style>
+ <body>
+ <div id="a">Acid3</div>
+ <div id="a0">Acid3</div>
+ <div id="b"><div>100/100</div></div>
+ <div id="c">To pass the test,<span></span> a browser must use its default settings, the animation has to be smooth, the score has to end on 100/100, and the final page has to look exactly, pixel for pixel, like <a href="reference.html">this reference rendering</a>.</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/support-b.png b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/support-b.png
new file mode 100644
index 00000000000..752ee7ec05c
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/support-b.png
@@ -0,0 +1 @@
+<!DOCTYPE html><html><head><title>FAIL</title><style> * { background: transparent; } </style></head><body><p><!-- this file is transparent --></p></body></html> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/support-c.png b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/support-c.png
new file mode 100644
index 00000000000..9f240083deb
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/support-c.png
Binary files differ
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/svg.svg b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/svg.svg
new file mode 100644
index 00000000000..0c7737a68d4
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/svg.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- chase added XML 1.0 UTF-8 DTD -->
+<?xml-stylesheet href="data:text/css,text%7Bfont-family%3AACID3svgfont%7D"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100"><defs><font-face font-family="ACID3svgfont"><font-face-src><font-face-uri xlink:href="font.svg#mini"/></font-face-src></font-face><path id="path" d="M0 0l0 42l16 16l4711 0"/></defs><text>X</text></svg>
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.1.xhtml b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.1.xhtml
new file mode 100644
index 00000000000..5d2d430361b
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.1.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test</title>
+ </head>
+ <body>
+ <p> <strong> XHTML Test </strong> </p>
+ <script type="text/javascript">
+ parent.notify("xhtml.1")
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.2.xhtml b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.2.xhtml
new file mode 100644
index 00000000000..ab4017c501a
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.2.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Test</title>
+ </head>
+ <body>
+ <p> <strong/> Parsing Test </strong> </p>
+ <script type="text/javascript">
+ parent.notify("xhtml.2")
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.3.xhtml b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.3.xhtml
new file mode 100644
index 00000000000..6ed6b5dd49a
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/acid3.acidtests.org/xhtml.3.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml#">
+ <head>
+ <title>Test</title>
+ </head>
+ <body>
+ <p> <strong> Namespace Test </strong> </p>
+ <script type="text/javascript">
+ parent.notify("xhtml.3")
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/page_cycler/acid3/pages.js b/chromium/tools/page_cycler/acid3/pages.js
new file mode 100644
index 00000000000..466e1161e69
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/pages.js
@@ -0,0 +1,31 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+var __pages = [
+ "acid3.acidtests.org",
+];
diff --git a/chromium/tools/page_cycler/acid3/start.html b/chromium/tools/page_cycler/acid3/start.html
new file mode 100644
index 00000000000..c30e8d840e1
--- /dev/null
+++ b/chromium/tools/page_cycler/acid3/start.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for this test to work manually.</h3>
+<script src="pages.js"></script>
+<script src="../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/common/head.js b/chromium/tools/page_cycler/common/head.js
new file mode 100644
index 00000000000..dddaa7ee0ac
--- /dev/null
+++ b/chromium/tools/page_cycler/common/head.js
@@ -0,0 +1,128 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var __c = ""; // that's good enough for me.
+var __td;
+var __tf;
+var __tl;
+var __iterations;
+var __cycle;
+var __results = false;
+var __page;
+var __TIMEOUT = 15;
+function __get_cookie(name) {
+ var cookies = document.cookie.split("; ");
+ for (var i = 0; i < cookies.length; ++i) {
+ var t = cookies[i].split("=");
+ if (t[0] == name && t[1])
+ return t[1];
+ }
+ return "";
+}
+function __pages() { // fetch lazily
+ if (!("data" in this))
+ this.data = __get_cookie("__pc_pages").split(",");
+ return this.data;
+}
+function __get_timings() {
+ if (sessionStorage != null &&
+ sessionStorage.getItem("__pc_timings") != null) {
+ return sessionStorage["__pc_timings"];
+ } else {
+ return __get_cookie("__pc_timings");
+ }
+}
+function __set_timings(timings) {
+ if (sessionStorage == null)
+ document.cookie = "__pc_timings=" + timings + "; path=/";
+ else
+ sessionStorage["__pc_timings"]=timings;
+}
+function __ontimeout() {
+ var doc;
+
+ // Call GC twice to cleanup JS heap before starting a new test.
+ if (window.gc) {
+ window.gc();
+ window.gc();
+ }
+
+ var timings = __tl;
+ var oldTimings = __get_timings();
+ if (oldTimings != "") {
+ timings = oldTimings + "," + timings;
+ }
+ __set_timings(timings);
+
+ var ts = (new Date()).getTime();
+ var tlag = (ts - __te) - __TIMEOUT;
+ if (tlag > 0)
+ __tf = __tf + tlag;
+ if (__cycle == (__pages().length * __iterations)) {
+ document.cookie = "__pc_done=1; path=/";
+ doc = "../../common/report.html";
+ if (window.console) {
+ console.log("Pages: [" + __get_cookie('__pc_pages') + "]");
+ console.log("times: [" + __get_timings() + "]");
+ }
+ } else {
+ doc = "../" + __pages()[__page] + "/index.html";
+ }
+
+ var url = doc + "?n=" + __iterations + "&i=" + __cycle + "&p=" + __page +
+ "&ts=" + ts + "&td=" + __td + "&tf=" + __tf;
+ document.location.href = url;
+}
+function __onload() {
+ if (__results) {
+ // Set a variable to indicate that the result report page is loaded.
+ document.cookie = "__navigated_to_report=1; path=/";
+ return;
+ }
+ var unused = document.body.offsetHeight; // force layout
+
+ var ts = 0, td = 0, te = (new Date()).getTime(), tf = 0;
+
+ var s = document.location.search;
+ if (s) {
+ var params = s.substring(1).split('&');
+ for (var i = 0; i < params.length; ++i) {
+ var f = params[i].split('=');
+ switch (f[0]) {
+ case 'skip':
+ // No calculation, just viewing
+ return;
+ case 'n':
+ __iterations = f[1];
+ break;
+ case 'i':
+ __cycle = (f[1] - 0) + 1;
+ break;
+ case 'p':
+ __page = ((f[1] - 0) + 1) % __pages().length;
+ break;
+ case 'ts':
+ ts = (f[1] - 0);
+ break;
+ case 'td':
+ td = (f[1] - 0);
+ break;
+ case 'tf':
+ tf = (f[1] - 0);
+ break;
+ }
+ }
+ }
+ __tl = (te - ts);
+ __td = td + __tl;
+ __te = te;
+ __tf = tf; // record t-fudge
+
+ setTimeout("__ontimeout()", __TIMEOUT);
+}
+
+if (window.attachEvent)
+ window.attachEvent("onload", __onload);
+else
+ addEventListener("load", __onload, false);
diff --git a/chromium/tools/page_cycler/common/report.html b/chromium/tools/page_cycler/common/report.html
new file mode 100644
index 00000000000..9833fbe8ee1
--- /dev/null
+++ b/chromium/tools/page_cycler/common/report.html
@@ -0,0 +1,183 @@
+<html>
+<head>
+<style>
+.discarded {
+ color: #C0C0C0;
+}
+</style>
+<h2>Summary</h2>
+<dl>
+<script src="head.js"></script>
+<script>
+var __results = true;
+var cycles = 0;
+var s = document.location.search.substring(1);
+var params = s.split('&');
+var iterations, pages, totalTime, fudgeTime;
+for (var i = 0; i < params.length; ++i) {
+ var f = params[i].split('=');
+ switch (f[0]) {
+ case 'n':
+ iterations = (f[1] - 0);
+ break;
+ case 'i':
+ cycle = (f[1] - 0);
+ break;
+ case 'td':
+ totalTime = (f[1] - 0);
+ break;
+ case 'tf':
+ fudgeTime = (f[1] - 0);
+ break;
+ }
+}
+var pages = cycle / iterations;
+document.write("<table border=1>");
+document.write("<tr><td>iterations</td><td>" + iterations + "</td></tr>");
+document.write("<tr><td>pages</td><td>" + pages + "</td></tr>");
+document.write("<tr><td>milliseconds</td><td>" + totalTime + "</td></tr>");
+document.write("<tr><td>mean per set</td><td>" + (totalTime / iterations).toFixed(2) + "</td></tr>");
+document.write("<tr><td>mean per page</td><td>" + (totalTime / iterations / pages).toFixed(2) + "</td></tr>");
+document.write("<tr><td>timer lag</td><td>" + (fudgeTime).toFixed(2) + "</td></tr>");
+document.write("<tr><td>timer lag per page</td><td>" + (fudgeTime / iterations / pages).toFixed(2) + "</td></tr>");
+document.write("</table>");
+
+ // returns an object with the following properties:
+ // min : min value of array elements
+ // max : max value of array elements
+ // mean : mean value of array elements
+ // vari : variance computation
+ // stdd : standard deviation, sqrt(vari)
+ // indexOfMax : index of max element (the element that is
+ // removed from the mean computation)
+ function getArrayStats(ary) {
+ var r = {};
+ r.min = ary[0];
+ r.max = ary[0];
+ r.indexOfMax = 0;
+ var sum = 0;
+ for (var i = 0; i < ary.length; ++i) {
+ if (ary[i] < r.min) {
+ r.min = ary[i];
+ } else if (ary[i] > r.max) {
+ r.max = ary[i];
+ r.indexOfMax = i;
+ }
+ sum = sum + ary[i];
+ }
+
+ // ignore max value when computing mean and stddev
+ r.mean = (sum - r.max) / (ary.length - 1);
+
+ r.vari = 0;
+ for (var i = 0; i < ary.length; ++i) {
+ if (i == r.indexOfMax)
+ continue;
+ var d = r.mean - ary[i];
+ r.vari = r.vari + d * d;
+ }
+
+ r.vari = r.vari / (ary.length - 1);
+ r.stdd = Math.sqrt(r.vari);
+ r.errp = r.stdd / Math.sqrt((ary.length - 1) / 2) / r.mean * 100;
+ return r;
+ }
+
+ function appendTableCol(tr, text, linkify) {
+ var doc = tr.ownerDocument;
+ var td = doc.createElement("TD");
+
+ if (linkify) {
+ var anchor = doc.createElement("A");
+ if (text.indexOf('http://localhost:') == 0 ||
+ text.indexOf('file://') == 0) {
+ // URLs for page cycler HTTP and file tests.
+ anchor.href = text + "/index.html?skip=true";
+ } else {
+ // For Web Page Replay, URLs are same as recorded pages.
+ anchor.href = text;
+ }
+ anchor.appendChild(doc.createTextNode(text));
+ td.appendChild(anchor);
+ }
+ else
+ td.appendChild(doc.createTextNode(text));
+ tr.appendChild(td);
+ return td;
+ }
+
+ function getTimeVals() {
+ var rawData = __get_timings().split(",");
+ var timeVals = [];
+ for (var i = 0; i < iterations; ++i) {
+ for (var j = 0; j < pages; ++j) {
+ if (!timeVals[j])
+ timeVals[j] = [];
+ timeVals[j].push(parseInt(rawData[j + i*pages]));
+ }
+ }
+ return timeVals;
+ }
+
+ function showReport() {
+ var tbody = document.getElementById("tbody");
+ var colsums = [0,0,0,0,0];
+ var timeVals = getTimeVals();
+ for (var i = 0; i < timeVals.length; ++i) {
+ var tr = document.createElement("TR");
+
+ appendTableCol(tr, __pages()[i], true);
+
+ var r = getArrayStats(timeVals[i]);
+ appendTableCol(tr, r.min.toFixed(2));
+ appendTableCol(tr, r.max.toFixed(2));
+ appendTableCol(tr, r.mean.toFixed(2));
+ appendTableCol(tr, r.stdd.toFixed(2));
+ appendTableCol(tr, r.errp.toFixed(2));
+ //appendTableCol(tr, r.chi2.toFixed(2));
+
+ for (var j = 0; j < timeVals[i].length; ++j) {
+ var tv = timeVals[i][j];
+ var td = appendTableCol(tr, tv);
+ if (j == r.indexOfMax)
+ td.setAttribute("class", "discarded");
+ }
+
+ colsums[0] = colsums[0] + r.min;
+ colsums[1] = colsums[1] + r.max;
+ colsums[2] = colsums[2] + r.mean;
+ colsums[3] = colsums[3] + r.stdd;
+ colsums[4] = colsums[4] + r.errp;
+
+ tbody.appendChild(tr);
+ }
+
+ var tr = document.createElement("TR");
+ appendTableCol(tr, "totals:");
+ for (var k = 0; k < colsums.length; ++k)
+ appendTableCol(tr, colsums[k].toFixed(2));
+ tbody.appendChild(tr);
+ }
+ window.onload = showReport;
+
+</script>
+</dl>
+</head>
+<body>
+<h2>Complete Statistics</h2>
+<table border="1">
+<thead>
+<tr>
+ <th>Site</th>
+ <th>Min</th>
+ <th>Max</th>
+ <th>Mean</th>
+ <th>Std.d</th>
+ <th>Err %</th>
+ <th colspan="10">Runs</th>
+</tr>
+</thead>
+<tbody id="tbody"></tbody>
+</table>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/common/start.js b/chromium/tools/page_cycler/common/start.js
new file mode 100644
index 00000000000..f43994e369f
--- /dev/null
+++ b/chromium/tools/page_cycler/common/start.js
@@ -0,0 +1,82 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+document.title = 'page cycler';
+
+// The __pages is assumed an array which containing the directories for
+// various pages to exercise. Some page cycler tests don't have this variable.
+
+var initialPage;
+var hasVariablePages = (typeof __pages != 'undefined') &&
+ (__pages instanceof Array);
+if (hasVariablePages)
+ initialPage = __pages[0];
+
+document.cookie = '__navigated_to_report=0; path=/';
+document.cookie = '__pc_done=0; path=/';
+if (hasVariablePages)
+ document.cookie = '__pc_pages=' + __pages + '; path=/';
+document.cookie = '__pc_timings=; path=/';
+
+var options = location.search.substring(1).split('&');
+
+function getopt(name) {
+ var r = new RegExp('^' + name + '=');
+ for (var i = 0; i < options.length; ++i) {
+ if (options[i].match(r)) {
+ return options[i].substring(name.length + 1);
+ }
+ }
+ return null;
+}
+
+function start() {
+ var iterations = document.getElementById('iterations').value;
+ window.resizeTo(800, 800);
+ var ts = (new Date()).getTime();
+ var url = '';
+ if (hasVariablePages)
+ url = initialPage + '/';
+ url += 'index.html?n=' + iterations + '&i=0&p=0&ts=' + ts + '&td=0';
+ window.location = url;
+}
+
+function render_form() {
+ var form = document.createElement('FORM');
+ form.onsubmit = function(e) {
+ start();
+ e.preventDefault();
+ };
+
+ var label = document.createTextNode('Iterations: ');
+ form.appendChild(label);
+
+ var input = document.createElement('INPUT');
+ input.setAttribute('id', 'iterations');
+ input.setAttribute('type', 'number');
+ var iterations = getopt('iterations');
+ input.setAttribute('value', iterations ? iterations : '5');
+ form.appendChild(input);
+
+ input = document.createElement('INPUT');
+ input.setAttribute('type', 'submit');
+ input.setAttribute('value', 'Start');
+ form.appendChild(input);
+
+ document.body.appendChild(form);
+}
+
+render_form();
+
+// should we start automatically?
+if (location.search.match('auto=1')) {
+ start();
+} else {
+ if (!window.gc) {
+ document.write('<h3 style=\'color:red\'>WARNING: window.gc is not ' +
+ 'defined. Test results may be unreliable! You must ' +
+ 'started chrome also with <tt>--js-flags=\"--expose_gc\"' +
+ '</tt> for this test to work manually</h3>');
+ }
+}
diff --git a/chromium/tools/page_cycler/database/common.js b/chromium/tools/page_cycler/database/common.js
new file mode 100644
index 00000000000..6ada5676a4f
--- /dev/null
+++ b/chromium/tools/page_cycler/database/common.js
@@ -0,0 +1,109 @@
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A collection of common functions used by all database
+ * performance tests.
+ */
+
+var CANNOT_OPEN_DB = -1;
+var SETUP_FAILED = -2;
+var TEST_FAILED = -3;
+
+var TRANSACTIONS = 1000; // number of transactions; number of rows in the DB
+var RANDOM_STRING_LENGTH = 20; // the length of the string on each row
+
+/**
+ * Generates a random string of upper-case letters of
+ * RANDOM_STRING_LENGTH length.
+ */
+function getRandomString() {
+ var s = '';
+ for (var i = 0; i < RANDOM_STRING_LENGTH; i++)
+ s += String.fromCharCode(Math.floor(Math.random() * 26) + 64);
+ return s;
+}
+
+/**
+ * Sets up and runs a performance test.
+ * @param {!Object} params An object which must have the following fields:
+ * dbName: The database name.
+ * readOnly: If true, transactions will be run using the readTransaction()
+ * method. Otherwise, transaction() will be used.
+ * insertRowsAtSetup: Determines if setting up the database should include
+ * inserting TRANSACTIONS rows in it.
+ * transactionCallback: The transaction callback that should be timed. This
+ * function will be run TRANSACTIONS times and must take a transaction
+ * object as its only parameter.
+ * customRunTransactions: A custom function for running and timing
+ * transactions. If this parameter is not null, runPerformanceTest() will
+ * ignore the txFnct parameter and will call customRunTransactions() as
+ * soon as the setup is complete. In this case, the user is responsible
+ * for running and timing the transactions. If not null, this parameter
+ * must be a function that takes a database object as its only parameter.
+ */
+function runPerformanceTest(params) {
+ var db = openTestDatabase(params.dbName);
+ if (!db) {
+ testComplete(CANNOT_OPEN_DB);
+ return;
+ }
+
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Test (ID INT, Foo TEXT)', [],
+ function(tx, data) {}, function(tx, error) {});
+ tx.executeSql('DELETE FROM Test');
+ if (params.insertRowsAtSetup) {
+ var randomString = getRandomString();
+ for (var i = 0; i < TRANSACTIONS; i++) {
+ tx.executeSql('INSERT INTO Test VALUES (?, ?)',
+ [i, randomString]);
+ }
+ }
+ }, function(error) {
+ testComplete(SETUP_FAILED);
+ }, function() {
+ if (params.customRunTransactions)
+ params.customRunTransactions(db);
+ else
+ runTransactions(db, params.readOnly, params.transactionCallback);
+ });
+}
+
+/**
+ * Opens a database with the given name.
+ * @param {string} name The name of the database.
+ */
+function openTestDatabase(name) {
+ if (window.openDatabase) {
+ return window.openDatabase(name, '1.0', 'Test database.',
+ TRANSACTIONS * RANDOM_STRING_LENGTH);
+ }
+
+ return null;
+}
+
+/**
+ * Runs the given transaction TRANSACTIONS times.
+ * @param {!Object} db The database to run transactions on.
+ * @param {boolean} readOnly If true, all transactions will be run using the
+ * db.readTransaction() call. Otherwise, the transactions will be run
+ * using the db.transaction() call.
+ * @param {function(!Object)} The transaction callback.
+ */
+function runTransactions(db, readOnly, transactionCallback) {
+ var transactionsCompleted = 0;
+ var transactionFunction = readOnly ? db.readTransaction : db.transaction;
+ var startTime = Date.now();
+ for (var i = 0; i < TRANSACTIONS; i++) {
+ transactionFunction.call(db, transactionCallback,
+ function(error) {
+ testComplete(TEST_FAILED);
+ }, function() {
+ if (++transactionsCompleted == TRANSACTIONS)
+ testComplete(Date.now() - startTime);
+ });
+ }
+}
diff --git a/chromium/tools/page_cycler/database/delete-transactions/index.html b/chromium/tools/page_cycler/database/delete-transactions/index.html
new file mode 100644
index 00000000000..b5e565148a7
--- /dev/null
+++ b/chromium/tools/page_cycler/database/delete-transactions/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<title>Delete transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('DELETE FROM Test WHERE ID = ?', [idCounter++],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "DeleteTransactions",
+ readOnly: false,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/delete-transactions/start.html b/chromium/tools/page_cycler/database/delete-transactions/start.html
new file mode 100644
index 00000000000..4f5d3eb1663
--- /dev/null
+++ b/chromium/tools/page_cycler/database/delete-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=delete-transactions; path=/";</script>
+<script src="../../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/head.js b/chromium/tools/page_cycler/database/head.js
new file mode 100644
index 00000000000..a36ce77cbff
--- /dev/null
+++ b/chromium/tools/page_cycler/database/head.js
@@ -0,0 +1,125 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var totalTime;
+var fudgeTime;
+var elapsedTime;
+var endTime;
+var iterations;
+var cycle;
+var results = false;
+var TIMEOUT = 15;
+
+/**
+ * Returns the value of the given property stored in the cookie.
+ * @param {string} name The property name.
+ * @return {string} The value of the given property, or empty string
+ * if the property was not found.
+ */
+function __get_cookie(name) {
+ var cookies = document.cookie.split('; ');
+ for (var i = 0; i < cookies.length; ++i) {
+ var t = cookies[i].split('=');
+ if ((t[0] == name) && t[1])
+ return t[1];
+ }
+ return '';
+}
+
+function __get_timings() {
+ if (sessionStorage == null)
+ return __get_cookie("__pc_timings");
+ else {
+ if (sessionStorage.getItem("__pc_timings") == null)
+ return "";
+ else
+ return sessionStorage["__pc_timings"];
+ }
+}
+function __set_timings(timings) {
+ if (sessionStorage == null)
+ document.cookie = "__pc_timings=" + timings + "; path=/";
+ else
+ sessionStorage["__pc_timings"]=timings;
+}
+
+/**
+ * Starts the next test cycle or redirects the browser to the results page.
+ */
+function nextCycleOrResults() {
+ // Call GC twice to cleanup JS heap before starting a new test.
+ if (window.gc) {
+ window.gc();
+ window.gc();
+ }
+
+ var timings = elapsedTime;
+ var oldTimings = __get_timings();
+ if (oldTimings != '')
+ timings = oldTimings + ',' + timings;
+ __set_timings(timings);
+
+ var tLag = Date.now() - endTime - TIMEOUT;
+ if (tLag > 0)
+ fudgeTime += tLag;
+
+ var doc;
+ if (cycle == iterations) {
+ document.cookie = '__pc_done=1; path=/';
+ doc = '../../common/report.html';
+ if (window.console) {
+ console.log("Pages: [" + __get_cookie('__pc_pages') + "]");
+ console.log("times: [" + __get_timings() + "]");
+ }
+ } else {
+ doc = 'index.html';
+ }
+
+ var url = doc + '?n=' + iterations + '&i=' + cycle +
+ '&td=' + totalTime + '&tf=' + fudgeTime;
+ document.location.href = url;
+}
+
+/**
+ * Computes various running times and updates the stats reported at the end.
+ * @param {!number} cycleTime The running time of the test cycle.
+ */
+function testComplete(cycleTime) {
+ if (results)
+ return;
+
+ var oldTotalTime = 0;
+ var cycleEndTime = Date.now();
+ var cycleFudgeTime = 0;
+
+ var s = document.location.search;
+ if (s) {
+ var params = s.substring(1).split('&');
+ for (var i = 0; i < params.length; i++) {
+ var f = params[i].split('=');
+ switch (f[0]) {
+ case 'skip':
+ return; // No calculation, just viewing
+ case 'n':
+ iterations = f[1];
+ break;
+ case 'i':
+ cycle = f[1] - 0 + 1;
+ break;
+ case 'td':
+ oldTotalTime = f[1] - 0;
+ break;
+ case 'tf':
+ cycleFudgeTime = f[1] - 0;
+ break;
+ }
+ }
+ }
+ elapsedTime = cycleTime;
+ totalTime = oldTotalTime + elapsedTime;
+ endTime = cycleEndTime;
+ fudgeTime = cycleFudgeTime;
+
+ setTimeout(nextCycleOrResults, TIMEOUT);
+}
diff --git a/chromium/tools/page_cycler/database/insert-transactions/index.html b/chromium/tools/page_cycler/database/insert-transactions/index.html
new file mode 100644
index 00000000000..f17b977ffe6
--- /dev/null
+++ b/chromium/tools/page_cycler/database/insert-transactions/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<title>Insert transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var randomString = getRandomString();
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('INSERT INTO Test VALUES (?, ?)',
+ [idCounter++, randomString],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "InsertTransactions",
+ readOnly: false,
+ insertRowsAtSetup: false,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/insert-transactions/start.html b/chromium/tools/page_cycler/database/insert-transactions/start.html
new file mode 100644
index 00000000000..6c18a36b9fd
--- /dev/null
+++ b/chromium/tools/page_cycler/database/insert-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=insert-transactions; path=/";</script>
+<script src="../../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/pseudo-random-transactions/index.html b/chromium/tools/page_cycler/database/pseudo-random-transactions/index.html
new file mode 100644
index 00000000000..3732bce4269
--- /dev/null
+++ b/chromium/tools/page_cycler/database/pseudo-random-transactions/index.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<title>Pseudo-random transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var SELECT_STATEMENT_IN_READ_TRANSACTION = 0;
+var SELECT_STATEMENT_IN_TRANSACTION = 1;
+var INSERT_STATEMENT = 2;
+var UPDATE_STATEMENT = 3;
+var DELETE_STATEMENT = 4;
+var STATEMENTS =
+ [2, 0, 4, 2, 2, 2, 2, 2, 1, 4, 1, 1, 0, 2, 0, 0, 2, 1, 2, 0,
+ 4, 4, 2, 3, 3, 4, 3, 1, 3, 3, 2, 4, 3, 3, 2, 3, 1, 1, 4, 2,
+ 4, 1, 4, 2, 3, 0, 4, 2, 4, 0, 4, 3, 3, 2, 0, 2, 1, 4, 4, 4,
+ 4, 2, 3, 2, 0, 3, 3, 0, 4, 4, 4, 2, 3, 1, 4, 2, 4, 2, 3, 0,
+ 2, 4, 0, 4, 2, 2, 4, 0, 3, 2, 3, 2, 3, 2, 0, 0, 4, 0, 2, 0];
+
+var transactionsCompleted = 0;
+var startTime = 0;
+
+function statementSuccessCallback(tx, data) {}
+function statementErrorCallback(tx, error) {}
+
+function transactionSuccessCallback() {
+ if (++transactionsCompleted == TRANSACTIONS)
+ testComplete(Date.now() - startTime);
+}
+
+function transactionErrorCallback(error) {
+ testComplete(TEST_FAILED);
+}
+
+function customRunTransactions(db) {
+ var selectIDCounter = 0;
+ var insertIDCounter = 0;
+ var updateIDCounter = 0;
+ var deleteIDCounter = 0;
+ var randomString = getRandomString();
+ var randomStringForUpdates = getRandomString();
+ startTime = Date.now();
+ for (var i = 0; i < TRANSACTIONS; i++) {
+ switch (STATEMENTS[i % STATEMENTS.length]) {
+ case SELECT_STATEMENT_IN_READ_TRANSACTION:
+ db.readTransaction(
+ function(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?',
+ [selectIDCounter++],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ case SELECT_STATEMENT_IN_TRANSACTION:
+ db.transaction(
+ function(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?',
+ [selectIDCounter++],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ case INSERT_STATEMENT:
+ db.transaction(
+ function(tx) {
+ tx.executeSql('INSERT INTO Test VALUES (?, ?)',
+ [insertIDCounter++, randomString],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ case UPDATE_STATEMENT:
+ db.transaction(
+ function(tx) {
+ tx.executeSql('UPDATE Test SET Foo = ? WHERE ID = ?',
+ [randomStringForUpdates, updateIDCounter++],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ case DELETE_STATEMENT:
+ db.transaction(
+ function(tx) {
+ tx.executeSql('DELETE FROM Test WHERE ID = ?',
+ [deleteIDCounter++],
+ statementSuccessCallback, statementErrorCallback);
+ }, transactionErrorCallback, transactionSuccessCallback);
+ break;
+ default:
+ testComplete(TEST_FAILED);
+ return;
+ }
+ }
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "PseudoRandomTransactions",
+ readOnly: false,
+ insertRowsAtSetup: true,
+ transactionCallback: null,
+ customRunTransactions: customRunTransactions
+ });
+</script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/pseudo-random-transactions/start.html b/chromium/tools/page_cycler/database/pseudo-random-transactions/start.html
new file mode 100644
index 00000000000..f2dd9c6ae3f
--- /dev/null
+++ b/chromium/tools/page_cycler/database/pseudo-random-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=pseudo-random-transactions; path=/";</script>
+<script src="../../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/select-readtransactions-read-results/index.html b/chromium/tools/page_cycler/database/select-readtransactions-read-results/index.html
new file mode 100644
index 00000000000..40a2d87008e
--- /dev/null
+++ b/chromium/tools/page_cycler/database/select-readtransactions-read-results/index.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<title>Select read-transactions (store results in JS variables)</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var idCounter = 0;
+var resultId = 0;
+var resultString = '';
+
+function transactionCallback(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?', [idCounter++],
+ function(tx, data) {
+ for (var i = 0; i < data.rows.length; i++) {
+ resultId = data.rows.item(i).ID;
+ resultString = data.rows.item(i).Foo;
+ }
+ }, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "SelectReadTransactionsReadResults",
+ readOnly: true,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/select-readtransactions-read-results/start.html b/chromium/tools/page_cycler/database/select-readtransactions-read-results/start.html
new file mode 100644
index 00000000000..ee4038cf595
--- /dev/null
+++ b/chromium/tools/page_cycler/database/select-readtransactions-read-results/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=select-readtransactions-read-results; path=/";</script>
+<script src="../../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/select-readtransactions/index.html b/chromium/tools/page_cycler/database/select-readtransactions/index.html
new file mode 100644
index 00000000000..e923bc2ea7a
--- /dev/null
+++ b/chromium/tools/page_cycler/database/select-readtransactions/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<title>Select read-transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?', [idCounter++],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "SelectReadTransactions",
+ readOnly: true,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/select-readtransactions/start.html b/chromium/tools/page_cycler/database/select-readtransactions/start.html
new file mode 100644
index 00000000000..383fb20233c
--- /dev/null
+++ b/chromium/tools/page_cycler/database/select-readtransactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=select-readtransactions; path=/";</script>
+<script src="../../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/select-transactions/index.html b/chromium/tools/page_cycler/database/select-transactions/index.html
new file mode 100644
index 00000000000..bfd0b39ac4b
--- /dev/null
+++ b/chromium/tools/page_cycler/database/select-transactions/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<title>Select transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('SELECT * FROM Test WHERE ID = ?', [idCounter++],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "SelectTransactions",
+ readOnly: false,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });</script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/select-transactions/start.html b/chromium/tools/page_cycler/database/select-transactions/start.html
new file mode 100644
index 00000000000..33da99fa150
--- /dev/null
+++ b/chromium/tools/page_cycler/database/select-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=select-transactions; path=/";</script>
+<script src="../../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/update-transactions/index.html b/chromium/tools/page_cycler/database/update-transactions/index.html
new file mode 100644
index 00000000000..75d3c570cca
--- /dev/null
+++ b/chromium/tools/page_cycler/database/update-transactions/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<title>Update transactions</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+var randomString = getRandomString();
+var idCounter = 0;
+
+function transactionCallback(tx) {
+ tx.executeSql('UPDATE Test SET Foo = ? WHERE ID = ?',
+ [randomString, idCounter++],
+ function(tx, data) {}, function(tx, error) {});
+}
+</script>
+
+<body>
+<script>
+ runPerformanceTest({
+ dbName: "UpdateTransactions",
+ readOnly: false,
+ insertRowsAtSetup: true,
+ transactionCallback: transactionCallback,
+ customRunTransactions: null
+ });
+</script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/database/update-transactions/start.html b/chromium/tools/page_cycler/database/update-transactions/start.html
new file mode 100644
index 00000000000..aa346f7f4ae
--- /dev/null
+++ b/chromium/tools/page_cycler/database/update-transactions/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=update-transactions; path=/";</script>
+<script src="../../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/indexed_db/basic_insert/index.html b/chromium/tools/page_cycler/indexed_db/basic_insert/index.html
new file mode 100644
index 00000000000..146355db7eb
--- /dev/null
+++ b/chromium/tools/page_cycler/indexed_db/basic_insert/index.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<html>
+<title>Basic Insert</title>
+<script src="../head.js"></script>
+<script src="../common.js"></script>
+<script>
+ var RECORDS = 3000;
+
+ var failed = false;
+ function error(event) {
+ log('Error ' + event.target.errorCode + ': '
+ + event.target.webkitErrorMessage);
+
+ if (!failed)
+ testComplete(TEST_FAILED);
+ failed = true;
+ }
+
+ function start() {
+ if (!setup())
+ testComplete(SETUP_FAILED);
+
+ var request = indexedDB.deleteDatabase('idb_basic_insert');
+ request.onsuccess = onDelete;
+ request.onerror = error;
+ request.onblocked = function(e) {
+ console.log("delete got blocked event");
+ };
+ }
+
+ function onDelete() {
+ request = indexedDB.open('idb_basic_insert');
+ request.onblocked = function(e) { console.log("open got blocked event"); };
+ request.onerror = error;
+ request.onupgradeneeded = function(e) {
+ createObjectStores(e.target.result);
+ };
+ request.onsuccess = function(e) {
+ db = request.result;
+ var curVersion = db.version;
+ if (curVersion !== 1) {
+ // Old reference build that doesn't have upgradeneeded.
+ // TODO(dgrogan): Remove when reference build is version 23 or later.
+ var setVersionRequest = db.setVersion("1");
+ setVersionRequest.onerror = error;
+ setVersionRequest.onsuccess = function(e) {
+ createObjectStores(db);
+ var versionTransaction = setVersionRequest.result;
+ versionTransaction.onerror = error;
+ versionTransaction.oncomplete = storeCreated;
+ }
+ } else {
+ storeCreated();
+ }
+ };
+ }
+
+ function createObjectStores(db) {
+ db.createObjectStore('store');
+ }
+
+ function storeCreated() {
+ var transaction = db.transaction(['store'], 'readwrite');
+ transaction.oncomplete = insertsDone;
+ transaction.onabort = function(e) {
+ console.log("readwrite transaction aborted");
+ };
+
+ var objectStore = transaction.objectStore('store');
+ log('Inserting ' + RECORDS + ' records with explicit key.');
+ startTime = new Date();
+ for (var i = 0; i < RECORDS; i++) {
+ var x = Math.floor(Math.random() * 1000000);
+ objectStore.put(x, x).onerror = error;
+ }
+ }
+
+ function insertsDone() {
+ var now = Date.now();
+ var diff = now - startTime;
+ log('Inserted ' + RECORDS + ' records in ' + diff + ' ms (' + diff /
+ RECORDS + ' ms per record)');
+
+ if (!failed)
+ testComplete(now - startTime);
+ }
+</script>
+
+<body onLoad="start()">
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/indexed_db/basic_insert/start.html b/chromium/tools/page_cycler/indexed_db/basic_insert/start.html
new file mode 100644
index 00000000000..971186928a9
--- /dev/null
+++ b/chromium/tools/page_cycler/indexed_db/basic_insert/start.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for
+ this test to work manually.</h3>
+<script>document.cookie = "__pc_pages=basic_insert; path=/";</script>
+<script src="../../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/indexed_db/common.js b/chromium/tools/page_cycler/indexed_db/common.js
new file mode 100644
index 00000000000..18d360761a8
--- /dev/null
+++ b/chromium/tools/page_cycler/indexed_db/common.js
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var CANNOT_OPEN_DB = -1;
+var SETUP_FAILED = -2;
+var TEST_FAILED = -3;
+
+function setup() {
+ window.indexedDB = window.indexedDB || window.webkitIndexedDB;
+ window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
+
+ if ('indexedDB' in window)
+ return true;
+
+ return false;
+}
+
+function getOrAddElement(id, type) {
+ var elem = document.getElementById(id);
+ if (!elem) {
+ elem = document.createElement(type);
+ elem.id = id;
+ document.body.appendChild(elem);
+ }
+ return elem;
+}
+
+function log(msg) {
+ var logElem = getOrAddElement('logElem', 'DIV');
+ logElem.innerHTML += msg + '<br>';
+} \ No newline at end of file
diff --git a/chromium/tools/page_cycler/indexed_db/head.js b/chromium/tools/page_cycler/indexed_db/head.js
new file mode 100644
index 00000000000..a36ce77cbff
--- /dev/null
+++ b/chromium/tools/page_cycler/indexed_db/head.js
@@ -0,0 +1,125 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var totalTime;
+var fudgeTime;
+var elapsedTime;
+var endTime;
+var iterations;
+var cycle;
+var results = false;
+var TIMEOUT = 15;
+
+/**
+ * Returns the value of the given property stored in the cookie.
+ * @param {string} name The property name.
+ * @return {string} The value of the given property, or empty string
+ * if the property was not found.
+ */
+function __get_cookie(name) {
+ var cookies = document.cookie.split('; ');
+ for (var i = 0; i < cookies.length; ++i) {
+ var t = cookies[i].split('=');
+ if ((t[0] == name) && t[1])
+ return t[1];
+ }
+ return '';
+}
+
+function __get_timings() {
+ if (sessionStorage == null)
+ return __get_cookie("__pc_timings");
+ else {
+ if (sessionStorage.getItem("__pc_timings") == null)
+ return "";
+ else
+ return sessionStorage["__pc_timings"];
+ }
+}
+function __set_timings(timings) {
+ if (sessionStorage == null)
+ document.cookie = "__pc_timings=" + timings + "; path=/";
+ else
+ sessionStorage["__pc_timings"]=timings;
+}
+
+/**
+ * Starts the next test cycle or redirects the browser to the results page.
+ */
+function nextCycleOrResults() {
+ // Call GC twice to cleanup JS heap before starting a new test.
+ if (window.gc) {
+ window.gc();
+ window.gc();
+ }
+
+ var timings = elapsedTime;
+ var oldTimings = __get_timings();
+ if (oldTimings != '')
+ timings = oldTimings + ',' + timings;
+ __set_timings(timings);
+
+ var tLag = Date.now() - endTime - TIMEOUT;
+ if (tLag > 0)
+ fudgeTime += tLag;
+
+ var doc;
+ if (cycle == iterations) {
+ document.cookie = '__pc_done=1; path=/';
+ doc = '../../common/report.html';
+ if (window.console) {
+ console.log("Pages: [" + __get_cookie('__pc_pages') + "]");
+ console.log("times: [" + __get_timings() + "]");
+ }
+ } else {
+ doc = 'index.html';
+ }
+
+ var url = doc + '?n=' + iterations + '&i=' + cycle +
+ '&td=' + totalTime + '&tf=' + fudgeTime;
+ document.location.href = url;
+}
+
+/**
+ * Computes various running times and updates the stats reported at the end.
+ * @param {!number} cycleTime The running time of the test cycle.
+ */
+function testComplete(cycleTime) {
+ if (results)
+ return;
+
+ var oldTotalTime = 0;
+ var cycleEndTime = Date.now();
+ var cycleFudgeTime = 0;
+
+ var s = document.location.search;
+ if (s) {
+ var params = s.substring(1).split('&');
+ for (var i = 0; i < params.length; i++) {
+ var f = params[i].split('=');
+ switch (f[0]) {
+ case 'skip':
+ return; // No calculation, just viewing
+ case 'n':
+ iterations = f[1];
+ break;
+ case 'i':
+ cycle = f[1] - 0 + 1;
+ break;
+ case 'td':
+ oldTotalTime = f[1] - 0;
+ break;
+ case 'tf':
+ cycleFudgeTime = f[1] - 0;
+ break;
+ }
+ }
+ }
+ elapsedTime = cycleTime;
+ totalTime = oldTotalTime + elapsedTime;
+ endTime = cycleEndTime;
+ fudgeTime = cycleFudgeTime;
+
+ setTimeout(nextCycleOrResults, TIMEOUT);
+}
diff --git a/chromium/tools/page_cycler/sample/page1/index.html b/chromium/tools/page_cycler/sample/page1/index.html
new file mode 100644
index 00000000000..26a2e3a8022
--- /dev/null
+++ b/chromium/tools/page_cycler/sample/page1/index.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <title>Page1</title>
+ <script src="../../common/head.js"></script>
+ </head>
+ <body>
+ <h1>Page1</h1>
+ </body>
+</html>
diff --git a/chromium/tools/page_cycler/sample/page2/index.html b/chromium/tools/page_cycler/sample/page2/index.html
new file mode 100644
index 00000000000..a020a97929e
--- /dev/null
+++ b/chromium/tools/page_cycler/sample/page2/index.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <title>Page2</title>
+ <script src="../../common/head.js"></script>
+ </head>
+ <body>
+ <h1>Page2</h1>
+ </body>
+</html>
diff --git a/chromium/tools/page_cycler/sample/page3/index.html b/chromium/tools/page_cycler/sample/page3/index.html
new file mode 100644
index 00000000000..1f819a26ef7
--- /dev/null
+++ b/chromium/tools/page_cycler/sample/page3/index.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <title>Page3</title>
+ <script src="../../common/head.js"></script>
+ </head>
+ <body>
+ <h1>Page3</h1>
+ </body>
+</html>
diff --git a/chromium/tools/page_cycler/sample/page4/index.html b/chromium/tools/page_cycler/sample/page4/index.html
new file mode 100644
index 00000000000..0079dd931c5
--- /dev/null
+++ b/chromium/tools/page_cycler/sample/page4/index.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <title>Page4</title>
+ <script src="../../common/head.js"></script>
+ </head>
+ <body>
+ <h1>Page4</h1>
+ </body>
+</html>
diff --git a/chromium/tools/page_cycler/sample/pages.js b/chromium/tools/page_cycler/sample/pages.js
new file mode 100644
index 00000000000..a5121314837
--- /dev/null
+++ b/chromium/tools/page_cycler/sample/pages.js
@@ -0,0 +1,10 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var __pages = [
+ "page1",
+ "page2",
+ "page3",
+ "page4",
+];
diff --git a/chromium/tools/page_cycler/sample/start.html b/chromium/tools/page_cycler/sample/start.html
new file mode 100644
index 00000000000..c30e8d840e1
--- /dev/null
+++ b/chromium/tools/page_cycler/sample/start.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<h3>Note: You must have started chrome with <tt>--enable-file-cookies</tt> for this test to work manually.</h3>
+<script src="pages.js"></script>
+<script src="../common/start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/startup_test_common/README b/chromium/tools/page_cycler/startup_test_common/README
new file mode 100644
index 00000000000..4054b08b52b
--- /dev/null
+++ b/chromium/tools/page_cycler/startup_test_common/README
@@ -0,0 +1,4 @@
+This directory is meant to override the common/ directory in order to allow
+page cycler data to be used for startup tests. It works primarily by
+substituting head.js for a version that doesn't redirect to the next page in the
+suite and instead only performs a consle.log() when the page has loaded.
diff --git a/chromium/tools/page_cycler/startup_test_common/blank.html b/chromium/tools/page_cycler/startup_test_common/blank.html
new file mode 100644
index 00000000000..acb46db51c6
--- /dev/null
+++ b/chromium/tools/page_cycler/startup_test_common/blank.html
@@ -0,0 +1,5 @@
+<script>
+ window.onload = function() {
+ console.log("PAGE_ONLOAD_EVENT" + location.hash);
+ };
+</script>
diff --git a/chromium/tools/page_cycler/startup_test_common/head.js b/chromium/tools/page_cycler/startup_test_common/head.js
new file mode 100644
index 00000000000..768ec54b0a9
--- /dev/null
+++ b/chromium/tools/page_cycler/startup_test_common/head.js
@@ -0,0 +1,7 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+window.onload = function() {
+ console.log("PAGE_ONLOAD_EVENT" + location.hash);
+};
diff --git a/chromium/tools/page_cycler/webpagereplay/README b/chromium/tools/page_cycler/webpagereplay/README
new file mode 100644
index 00000000000..6fce3e96bbe
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/README
@@ -0,0 +1,15 @@
+Page Cycler Tests with Web Page Replay
+---------------------------------------------------------------------------
+Web Page Replay is a proxy that can record and "play" web pages with
+simulated network characteristics -- without having to edit the pages
+by hand. With WPR, tests can use "real" web content, and catch
+performance issues that may result from introducing network delays and
+bandwidth throttling.
+
+The Chromium extension here is used to load URLs, record the times,
+and set the appropriate cookies for src/tools/page_cycler/common/report.html.
+
+For more information:
+https://sites.google.com/a/chromium.org/dev/developers/testing/page-cyclers-wpr
+https://sites.google.com/a/chromium.org/dev/developers/testing/page-cyclers
+http://code.google.com/p/web-page-replay
diff --git a/chromium/tools/page_cycler/webpagereplay/extension/background.html b/chromium/tools/page_cycler/webpagereplay/extension/background.html
new file mode 100644
index 00000000000..61a2902d2af
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/extension/background.html
@@ -0,0 +1,2 @@
+<script src="background.js"></script>
+<script src="page_cycler.js"></script>
diff --git a/chromium/tools/page_cycler/webpagereplay/extension/background.js b/chromium/tools/page_cycler/webpagereplay/extension/background.js
new file mode 100644
index 00000000000..e03c230b86e
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/extension/background.js
@@ -0,0 +1,328 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// start.js sends a "start" message to set this.
+window.benchmarkConfiguration = {};
+
+// The callback (e.g. report writer) is set via AddBenchmarckCallback.
+window.benchmarkCallback;
+
+// Url to load before loading target page.
+var kWaitUrl = "http://wprwprwpr/web-page-replay-generate-200";
+
+// Constant StatCounter Names
+var kTcpReadBytes = "tcp.read_bytes";
+var kTcpWriteBytes = "tcp.write_bytes";
+var kRequestCount = "HttpNetworkTransaction.Count";
+var kConnectCount = "tcp.connect";
+
+function CHECK(expr, comment) {
+ if (!expr) {
+ console.log(comment);
+ alert(comment);
+ }
+}
+
+function Result() {
+ var me_ = this;
+ this.url = "";
+ this.firstPaintTime = 0;
+ this.readBytesKB = 0;
+ this.writeBytesKB = 0;
+ this.numRequests = 0;
+ this.numConnects = 0;
+ this.timing = {}; // window.performance.timing
+ this.getTotalTime = function() {
+ var totalTime = 0
+ if (me_.timing.navigationStart && me_.timing.loadEventEnd) {
+ totalTime = me_.timing.loadEventEnd - me_.timing.navigationStart;
+ }
+ CHECK(totalTime >= 0);
+ return totalTime;
+ }
+}
+
+// Collect all the results for a session (i.e. different pages).
+function ResultsCollection() {
+ var results_ = [];
+ var pages_ = [];
+ var pageResults_ = {};
+
+ this.addResult = function(result) {
+ results_.push(result);
+ var url = result.url;
+ if (!(url in pageResults_)) {
+ pages_.push(url);
+ pageResults_[url] = [];
+ }
+ pageResults_[url].push(result);
+ }
+
+ this.getPages = function() {
+ return pages_;
+ }
+
+ this.getResults = function() {
+ return results_;
+ }
+
+ this.getTotalTimes = function() {
+ return results_.map(function (t) { return t.getTotalTime(); });
+ }
+}
+
+// Load a url in the default tab and record the time.
+function PageLoader(url, resultReadyCallback) {
+ var me_ = this;
+ var url_ = url;
+ var resultReadyCallback_ = resultReadyCallback;
+
+ // If it record mode, wait a little longer for lazy loaded resources.
+ var postLoadGraceMs_ = window.isRecordMode ? 5000 : 0;
+ var loadInterval_ = window.loadInterval;
+ var checkInterval_ = window.checkInterval;
+ var timeout_ = window.timeout;
+ var maxLoadChecks_ = window.maxLoadChecks;
+
+ var preloadFunc_;
+ var timeoutId_;
+ var isFinished_;
+ var result_;
+
+ var initialReadBytes_;
+ var initialWriteBytes_;
+ var initialRequestCount_;
+ var initialConnectCount_;
+
+ this.result = function() { return result_; };
+
+ this.run = function() {
+ timeoutId_ = null;
+ isFinished_ = false;
+ result_ = null;
+ initialReadBytes_ = chrome.benchmarking.counter(kTcpReadBytes);
+ initialWriteBytes_ = chrome.benchmarking.counter(kTcpWriteBytes);
+ initialRequestCount_ = chrome.benchmarking.counter(kRequestCount);
+ initialConnectCount_ = chrome.benchmarking.counter(kConnectCount);
+
+ if (me_.preloadFunc_) {
+ me_.preloadFunc_(me_.load_);
+ } else {
+ me_.load_();
+ }
+ };
+
+ this.setClearAll = function() {
+ me_.preloadFunc_ = me_.clearAll_;
+ };
+
+ this.setClearConnections = function() {
+ me_.preloadFunc_ = me_.clearConnections_;
+ };
+
+ this.clearAll_ = function(callback) {
+ chrome.tabs.getSelected(null, function(tab) {
+ chrome.tabs.update(tab.id, {"url": kWaitUrl}, function() {
+ chrome.benchmarking.clearHostResolverCache();
+ chrome.benchmarking.clearPredictorCache();
+ chrome.benchmarking.closeConnections();
+ var dataToRemove = {
+ "appcache": true,
+ "cache": true,
+ "cookies": true,
+ "downloads": true,
+ "fileSystems": true,
+ "formData": true,
+ "history": true,
+ "indexedDB": true,
+ "localStorage": true,
+ "passwords": true,
+ "pluginData": true,
+ "webSQL": true
+ };
+ // Add any items new to the API.
+ for (var prop in chrome.browsingData) {
+ var dataName = prop.replace("remove", "");
+ if (dataName && dataName != prop) {
+ dataName = dataName.charAt(0).toLowerCase() +
+ dataName.substr(1);
+ if (!dataToRemove.hasOwnProperty(dataName)) {
+ console.log("New browsingData API item: " + dataName);
+ dataToRemove[dataName] = true;
+ }
+ }
+ }
+ chrome.browsingData.remove({}, dataToRemove, callback);
+ });
+ });
+ };
+
+ this.clearConnections_ = function(callback) {
+ chrome.benchmarking.closeConnections();
+ callback();
+ };
+
+ this.load_ = function() {
+ console.log("LOAD started: " + url_);
+ setTimeout(function() {
+ chrome.extension.onRequest.addListener(me_.finishLoad_);
+ timeoutId_ = setTimeout(function() {
+ me_.finishLoad_({"loadTimes": null, "timing": null});
+ }, timeout_);
+ chrome.tabs.getSelected(null, function(tab) {
+ chrome.tabs.update(tab.id, {"url": url_});
+ });
+ }, loadInterval_);
+ };
+
+ this.finishLoad_ = function(msg) {
+ if (!isFinished_) {
+ isFinished_ = true;
+ clearTimeout(timeoutId_);
+ chrome.extension.onRequest.removeListener(me_.finishLoad_);
+ me_.saveResult_(msg.loadTimes, msg.timing);
+ }
+ };
+
+ this.saveResult_ = function(loadTimes, timing) {
+ result_ = new Result()
+ result_.url = url_;
+ if (!loadTimes || !timing) {
+ console.log("LOAD INCOMPLETE: " + url_);
+ } else {
+ console.log("LOAD complete: " + url_);
+ result_.timing = timing;
+ var baseTime = timing.navigationStart;
+ CHECK(baseTime);
+ result_.firstPaintTime = Math.max(0,
+ Math.round((1000.0 * loadTimes.firstPaintTime) - baseTime));
+ }
+ result_.readBytesKB = (chrome.benchmarking.counter(kTcpReadBytes) -
+ initialReadBytes_) / 1024;
+ result_.writeBytesKB = (chrome.benchmarking.counter(kTcpWriteBytes) -
+ initialWriteBytes_) / 1024;
+ result_.numRequests = (chrome.benchmarking.counter(kRequestCount) -
+ initialRequestCount_);
+ result_.numConnects = (chrome.benchmarking.counter(kConnectCount) -
+ initialConnectCount_);
+ setTimeout(function() { resultReadyCallback_(me_); }, postLoadGraceMs_);
+ };
+}
+
+// Load page sets and prepare performance results.
+function SessionLoader(resultsReadyCallback) {
+ var me_ = this;
+ var resultsReadyCallback_ = resultsReadyCallback;
+ var pageSets_ = benchmarkConfiguration.pageSets;
+ var iterations_ = window.iterations;
+ var retries_ = window.retries;
+
+ var pageLoaders_ = [];
+ var resultsCollection_ = new ResultsCollection();
+ var loaderIndex_ = 0;
+ var retryIndex_ = 0;
+ var iterationIndex_ = 0;
+
+ this.run = function() {
+ me_.createLoaders_();
+ me_.loadPage_();
+ }
+
+ this.getResultsCollection = function() {
+ return resultsCollection_;
+ }
+
+ this.createLoaders_ = function() {
+ // Each url becomes one benchmark.
+ for (var i = 0; i < pageSets_.length; i++) {
+ for (var j = 0; j < pageSets_[i].length; j++) {
+ // Remove extra space at the beginning or end of a url.
+ var url = pageSets_[i][j].trim();
+ // Alert about and ignore blank page which does not get loaded.
+ if (url == "about:blank") {
+ alert("blank page loaded!");
+ } else if (!url.match(/https?:\/\//)) {
+ // Alert about url that is not in scheme http:// or https://.
+ alert("Skipping url without http:// or https://: " + url);
+ } else {
+ var loader = new PageLoader(url, me_.handleResult_)
+ if (j == 0) {
+ // Clear all browser data for the first page in a sub list.
+ loader.setClearAll();
+ } else {
+ // Otherwise, only clear the connections.
+ loader.setClearConnections();
+ }
+ pageLoaders_.push(loader);
+ }
+ }
+ }
+ }
+
+ this.loadPage_ = function() {
+ console.log("LOAD url " + (loaderIndex_ + 1) + " of " +
+ pageLoaders_.length +
+ ", iteration " + (iterationIndex_ + 1) + " of " +
+ iterations_);
+ pageLoaders_[loaderIndex_].run();
+ }
+
+ this.handleResult_ = function(loader) {
+ var result = loader.result();
+ resultsCollection_.addResult(result);
+ var totalTime = result.getTotalTime();
+ if (!totalTime && retryIndex_ < retries_) {
+ retryIndex_++;
+ console.log("LOAD retry, " + retryIndex_);
+ } else {
+ retryIndex_ = 0;
+ console.log("RESULTS url " + (loaderIndex_ + 1) + " of " +
+ pageLoaders_.length +
+ ", iteration " + (iterationIndex_ + 1) + " of " +
+ iterations_ + ": " + totalTime);
+ loaderIndex_++;
+ if (loaderIndex_ >= pageLoaders_.length) {
+ iterationIndex_++;
+ if (iterationIndex_ < iterations_) {
+ loaderIndex_ = 0;
+ } else {
+ resultsReadyCallback_(me_);
+ return;
+ }
+ }
+ }
+ me_.loadPage_();
+ }
+}
+
+function AddBenchmarkCallback(callback) {
+ window.benchmarkCallback = callback;
+}
+
+function Run() {
+ window.checkInterval = 500;
+ window.loadInterval = 1000;
+ window.timeout = 20000; // max ms before killing page.
+ window.retries = 0;
+ window.isRecordMode = benchmarkConfiguration.isRecordMode;
+ if (window.isRecordMode) {
+ window.iterations = 1;
+ window.timeout = 40000;
+ window.retries = 2;
+ } else {
+ window.iterations = benchmarkConfiguration["iterations"] || 3;
+ }
+ var sessionLoader = new SessionLoader(benchmarkCallback);
+ console.log("pageSets: " + JSON.stringify(benchmarkConfiguration.pageSets));
+ sessionLoader.run();
+}
+
+chrome.runtime.onConnect.addListener(function(port) {
+ port.onMessage.addListener(function(data) {
+ if (data.message == "start") {
+ window.benchmarkConfiguration = data.benchmark;
+ Run()
+ }
+ });
+});
diff --git a/chromium/tools/page_cycler/webpagereplay/extension/content.js b/chromium/tools/page_cycler/webpagereplay/extension/content.js
new file mode 100644
index 00000000000..69713c3b5fb
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/extension/content.js
@@ -0,0 +1,14 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Hook onload and then add a timeout to send timing information
+// after the onload has completed.
+window.addEventListener('load', function() {
+ window.setTimeout(function() {
+ chrome.extension.sendRequest({
+ "timing": window.performance.timing,
+ "loadTimes": chrome.loadTimes(),
+ });
+ }, 0);
+}, false);
diff --git a/chromium/tools/page_cycler/webpagereplay/extension/manifest.json b/chromium/tools/page_cycler/webpagereplay/extension/manifest.json
new file mode 100644
index 00000000000..cb4ded7c9a4
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/extension/manifest.json
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+{
+ "manifest_version": 2,
+ "name": "Chromium Page Cycler with Web Page Replay.",
+ "version": "1.0.0.0",
+ "description": "Chromium Page Cycler with Web Page Replay.",
+ "background": {
+ "page": "background.html"
+ },
+ "content_scripts": [
+ { "matches": ["file:///*/start.html*"],
+ "js": ["start.js"],
+ "run_at": "document_idle"
+ },
+ { "matches": ["http://*/*", "https://*/*"],
+ "js": ["content.js"],
+ "run_at": "document_start"
+ }
+ ],
+ "permissions": [
+ "browsingData",
+ "cookies",
+ "experimental",
+ "tabs",
+ "<all_urls>"
+ ]
+}
diff --git a/chromium/tools/page_cycler/webpagereplay/extension/page_cycler.js b/chromium/tools/page_cycler/webpagereplay/extension/page_cycler.js
new file mode 100644
index 00000000000..76869b2902e
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/extension/page_cycler.js
@@ -0,0 +1,54 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Returns the sum of all values in the array.
+Array.sum = function(array) {
+ var sum = 0;
+ for (var i = array.length - 1; i >= 0; i--) {
+ sum += array[i];
+ }
+ return sum;
+};
+
+
+function WriteReport(sessionLoader) {
+ var iterations = window.iterations;
+ var reportUrl = window.benchmarkConfiguration.reportUrl;
+ var resultsCollection = sessionLoader.getResultsCollection();
+ var times = resultsCollection.getTotalTimes();
+ var pages = resultsCollection.getPages();
+
+ reportUrl += "?n=" + iterations;
+ reportUrl += "&i=" + iterations * pages.length; // "cycles"
+ reportUrl += "&td=" + Array.sum(times); // total time
+ reportUrl += "&tf=" + 0; // fudge time
+ console.log('reportUrl: ' + reportUrl);
+ chrome.cookies.set({
+ "url": reportUrl,
+ "name": "__pc_done",
+ "value": "1",
+ "path": "/",
+ });
+ chrome.cookies.set({
+ "url": reportUrl,
+ "name": "__pc_pages",
+ "value": pages.map(function(x) {
+ return x.replace(/=/g, "%3D");
+ }).join(","),
+ "path": "/",
+ });
+ chrome.cookies.set({
+ "url": reportUrl,
+ "name": "__pc_timings",
+ "value": times.join(","),
+ "path": "/",
+ });
+
+ chrome.tabs.getSelected(null, function(tab) {
+ console.log("Navigate to the report.");
+ chrome.tabs.update(tab.id, {"url": reportUrl}, null);
+ });
+}
+
+AddBenchmarkCallback(WriteReport);
diff --git a/chromium/tools/page_cycler/webpagereplay/extension/start.js b/chromium/tools/page_cycler/webpagereplay/extension/start.js
new file mode 100644
index 00000000000..ef4ce30120d
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/extension/start.js
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+document.cookie = "__navigated_to_report=0; path=/";
+document.cookie = "__pc_done=0; path=/";
+document.cookie = "__pc_timings=; path=/";
+
+function dirname(path) {
+ var match = path.match(/(.*)\//);
+ if (match) {
+ return match[1];
+ } else {
+ return ".";
+ }
+}
+
+function IsWprRecordMode() {
+ var kStatusUrl = "http://wprwprwpr/web-page-replay-command-status";
+ var isRecordMode;
+ var xhr = new XMLHttpRequest();
+ var useAsync = false;
+ xhr.open("GET", kStatusUrl, useAsync);
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4 && xhr.status == 200) {
+ var status = JSON.parse(xhr.responseText);
+ isRecordMode = status["is_record_mode"];
+ console.log("WPR record mode?: " + isRecordMode);
+ }
+ };
+ try {
+ xhr.send();
+ } catch(e) {
+ throw "Web Page Replay is not responding. Start WPR to continue."
+ }
+ return isRecordMode;
+}
+
+
+function TryStart() {
+ console.log("try start");
+ var status_element = document.getElementById("status");
+
+ var config_json;
+ var config;
+ try {
+ config_json = document.getElementById("json").textContent;
+ config = JSON.parse(config_json);
+ } catch(err) {
+ console.log("Bad json data: " + config_json);
+ status_element.textContent = "Exception: " + err + "\njson data: " +
+ config_json;
+ return;
+ }
+ var isRecordMode = false;
+ try {
+ isRecordMode = IsWprRecordMode();
+ } catch (err) {
+ status_element.textContent = err;
+ setTimeout(TryStart, 5000);
+ return;
+ }
+
+ if (!config["shouldStart"]) {
+ status_element.textContent =
+ "Press 'Start' to continue (or load this page with 'auto=1').";
+ return;
+ }
+
+ try {
+ var reportDir = dirname(dirname(window.location.pathname)) + "/common";
+ config["reportUrl"] = "file://" + reportDir + "/report.html";
+ config["isRecordMode"] = isRecordMode;
+ var port = chrome.runtime.connect();
+ port.postMessage({message: "start", benchmark: config});
+ console.log("sending start message: page count, " +
+ config["pageSets"].length);
+ } catch(err) {
+ console.log("TryStart retrying after exception: " + err);
+ status_element.textContent = "Exception: " + err;
+ setTimeout(TryStart, 1000);
+ return;
+ }
+ status_element.textContent = "STARTING";
+}
+
+// We wait before starting the test just to let chrome warm up better.
+setTimeout(TryStart, 250);
diff --git a/chromium/tools/page_cycler/webpagereplay/start.html b/chromium/tools/page_cycler/webpagereplay/start.html
new file mode 100644
index 00000000000..d263a355e2e
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/start.html
@@ -0,0 +1,26 @@
+<html>
+<!-- Copyright (c) 2012 The Chromium Authors. All rights reserved. -->
+<!-- Use of this source code is governed by a BSD-style license that can be -->
+<!-- found in the LICENSE file. -->
+<head>
+<style>
+ .labeledtextarea * {
+ vertical-align: middle;
+ }
+</style>
+</head>
+<body>
+<h3>Page Cycler: Web Page Replay Test</h3>
+
+<p class=labeledtextarea>
+<label for="status">Status:</label>
+<textarea id=status style="width:40em;height:3em;"></textarea>
+</p>
+
+<hr>
+<p>
+<div id=startform></div>
+<textarea id=json style="visibility: hidden;"></textarea>
+<script src="start.js"></script>
+</body>
+</html>
diff --git a/chromium/tools/page_cycler/webpagereplay/start.js b/chromium/tools/page_cycler/webpagereplay/start.js
new file mode 100644
index 00000000000..6ff5e6dc9c6
--- /dev/null
+++ b/chromium/tools/page_cycler/webpagereplay/start.js
@@ -0,0 +1,123 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// webpagereplay/start.js - Start Web Page Replay (WPR) test.
+//
+// This script is included by webpagereplay/start.html.
+// The query parameter "test=TEST_NAME" is required to load the
+// test configuration from webpagereplay/tests/TEST_NAME.js
+// That JavaScript file defines a global, "pageSets", as a list of lists:
+// [ [url_1, url_2], [url_3], ...],
+// - Before each sublist:
+// Run chrome.browingData.remove and close the connections.
+// - Before each url in a sublist:
+// Close the connections.
+//
+// These WPR tests use a Chrome extension to load the test URLs.
+// The extension loads the test configuration via a DOM elemment
+// (id=json). This script sets the content of that DOM element.
+//
+// The test runs immediately after being loaded.
+//
+
+
+var options = location.search.substring(1).split('&');
+function getopt(name) {
+ var r = new RegExp('^' + name + '=');
+ for (i = 0; i < options.length; ++i) {
+ if (options[i].match(r)) {
+ return options[i].substring(name.length + 1);
+ }
+ }
+ return null;
+}
+
+function LoadTestConfigurationScript(testUrl, callback) {
+ var testjs = document.createElement('script');
+ testjs.type = 'text/javascript';
+ testjs.async = true;
+ testjs.src = testUrl
+ var s = document.getElementsByTagName('script')[0];
+ testjs.addEventListener('load', callback, false);
+ s.parentNode.insertBefore(testjs, s);
+}
+
+function ReloadIfStuck() {
+ setTimeout(function() {
+ var status = document.getElementById('status');
+ // The status text is set to 'STARTING' by the extension.
+ if (status.textContent != 'STARTING') {
+ console.log('Benchmark stuck? Reloading.');
+ window.location.reload(true);
+ }
+ }, 30000);
+}
+
+function RenderForm() {
+ var form = document.createElement('FORM');
+ form.setAttribute('action', 'start.html');
+
+ var label = document.createTextNode('Iterations: ');
+ form.appendChild(label);
+
+ var input = document.createElement('INPUT');
+ var iterations = getopt('iterations');
+ input.setAttribute('name', 'iterations');
+ input.setAttribute('value', iterations ? iterations : '5');
+ form.appendChild(input);
+
+ form.appendChild(document.createElement('P'));
+
+ var label = document.createTextNode('Test: ');
+ form.appendChild(label);
+
+ var input = document.createElement('INPUT');
+ input.setAttribute('name', 'test');
+ var test = getopt('test');
+ input.setAttribute('value', test ? test : '');
+ form.appendChild(input);
+
+ var input = document.createElement('INPUT');
+ input.setAttribute('name', 'auto');
+ var auto = getopt('auto');
+ input.setAttribute('value', 1);
+ input.setAttribute('type', 'hidden');
+ form.appendChild(input);
+
+ form.appendChild(document.createElement('P'));
+
+ input = document.createElement('INPUT');
+ input.setAttribute('type', 'submit');
+ input.setAttribute('value', 'Start');
+ form.appendChild(input);
+
+ document.getElementById('startform').appendChild(form);
+}
+
+
+var iterations = getopt('iterations');
+var test_name = getopt('test');
+var is_auto_start = getopt('auto');
+
+RenderForm();
+if (test_name) {
+ var testUrl = 'tests/' + test_name + '.js';
+ LoadTestConfigurationScript(testUrl, function() {
+ var testConfig = {};
+ if (iterations) {
+ testConfig['iterations'] = iterations;
+ }
+ // The pageSets global is set by test configuration script.
+ testConfig['pageSets'] = pageSets;
+
+ if (is_auto_start) {
+ testConfig['shouldStart'] = 1;
+ ReloadIfStuck();
+ }
+ // Write testConfig to "json" DOM element for the Chrome extension.
+ document.getElementById('json').textContent = JSON.stringify(testConfig);
+ });
+} else {
+ console.log('Need "test=TEST_NAME" query parameter.');
+}
diff --git a/chromium/tools/perf/OWNERS b/chromium/tools/perf/OWNERS
new file mode 100644
index 00000000000..4f1e5a2178e
--- /dev/null
+++ b/chromium/tools/perf/OWNERS
@@ -0,0 +1,6 @@
+set noparent
+dtu@chromium.org
+nduca@chromium.org
+tonyg@chromium.org
+hartmanng@chromium.org
+marja@chromium.org
diff --git a/chromium/tools/perf/PRESUBMIT.py b/chromium/tools/perf/PRESUBMIT.py
new file mode 100644
index 00000000000..9bb8eb1a68d
--- /dev/null
+++ b/chromium/tools/perf/PRESUBMIT.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+
+PYLINT_BLACKLIST = []
+PYLINT_DISABLED_WARNINGS = ['R0923', 'R0201', 'E1101']
+
+
+def _CommonChecks(input_api, output_api):
+ results = []
+ old_sys_path = sys.path
+ try:
+ sys.path = [os.path.join(os.pardir, 'telemetry')] + sys.path
+ results.extend(input_api.canned_checks.RunPylint(
+ input_api, output_api,
+ black_list=PYLINT_BLACKLIST,
+ disabled_warnings=PYLINT_DISABLED_WARNINGS))
+ finally:
+ sys.path = old_sys_path
+ return results
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ report = []
+ report.extend(_CommonChecks(input_api, output_api))
+ return report
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ report = []
+ report.extend(_CommonChecks(input_api, output_api))
+ return report
diff --git a/chromium/tools/perf/benchmarks/__init__.py b/chromium/tools/perf/benchmarks/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/__init__.py
diff --git a/chromium/tools/perf/benchmarks/blink_perf.py b/chromium/tools/perf/benchmarks/blink_perf.py
new file mode 100644
index 00000000000..a8a4ecd61e0
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/blink_perf.py
@@ -0,0 +1,19 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+from telemetry import test
+from telemetry.core import util
+
+from measurements import blink_perf
+
+
+class BlinkPerfAll(test.Test):
+ test = blink_perf.BlinkPerf
+
+ def CreatePageSet(self, options):
+ path = os.path.join(
+ util.GetChromiumSrcDir(), 'third_party', 'WebKit', 'PerformanceTests')
+ return blink_perf.CreatePageSetFromPath(path)
diff --git a/chromium/tools/perf/benchmarks/dom_perf.py b/chromium/tools/perf/benchmarks/dom_perf.py
new file mode 100644
index 00000000000..3bc5209e17e
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/dom_perf.py
@@ -0,0 +1,91 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import math
+import os
+
+from telemetry import test
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+
+
+def _GeometricMean(values):
+ """Compute a rounded geometric mean from an array of values."""
+ if not values:
+ return None
+ # To avoid infinite value errors, make sure no value is less than 0.001.
+ new_values = []
+ for value in values:
+ if value > 0.001:
+ new_values.append(value)
+ else:
+ new_values.append(0.001)
+ # Compute the sum of the log of the values.
+ log_sum = sum(map(math.log, new_values))
+ # Raise e to that sum over the number of values.
+ mean = math.pow(math.e, (log_sum / len(new_values)))
+ # Return the rounded mean.
+ return int(round(mean))
+
+
+SCORE_UNIT = 'score (bigger is better)'
+SCORE_TRACE_NAME = 'score'
+
+
+class DomPerfMeasurement(page_measurement.PageMeasurement):
+ @property
+ def results_are_the_same_on_every_page(self):
+ return False
+
+ def MeasurePage(self, page, tab, results):
+ try:
+ def _IsDone():
+ return tab.GetCookieByName('__domperf_finished') == '1'
+ util.WaitFor(_IsDone, 600, poll_interval=5)
+
+ data = json.loads(tab.EvaluateJavaScript('__domperf_result'))
+ for suite in data['BenchmarkSuites']:
+ # Skip benchmarks that we didn't actually run this time around.
+ if len(suite['Benchmarks']) or suite['score']:
+ results.Add(SCORE_TRACE_NAME, SCORE_UNIT,
+ suite['score'], suite['name'], 'unimportant')
+ finally:
+ tab.EvaluateJavaScript('document.cookie = "__domperf_finished=0"')
+
+ def DidRunTest(self, tab, results):
+ # Now give the geometric mean as the total for the combined runs.
+ scores = []
+ for result in results.page_results:
+ scores.append(result[SCORE_TRACE_NAME].output_value)
+ total = _GeometricMean(scores)
+ results.AddSummary(SCORE_TRACE_NAME, SCORE_UNIT, total, 'Total')
+
+
+class DomPerf(test.Test):
+ """A suite of JavaScript benchmarks for exercising the browser's DOM.
+
+ The final score is computed as the geometric mean of the individual results.
+ Scores are not comparable across benchmark suite versions and higher scores
+ means better performance: Bigger is better!"""
+ test = DomPerfMeasurement
+
+ def CreatePageSet(self, options):
+ dom_perf_dir = os.path.join(util.GetChromiumSrcDir(), 'data', 'dom_perf')
+ base_page = 'file:///run.html?reportInJS=1&run='
+ return page_set.PageSet.FromDict({
+ 'pages': [
+ { 'url': base_page + 'Accessors' },
+ { 'url': base_page + 'CloneNodes' },
+ { 'url': base_page + 'CreateNodes' },
+ { 'url': base_page + 'DOMDivWalk' },
+ { 'url': base_page + 'DOMTable' },
+ { 'url': base_page + 'DOMWalk' },
+ { 'url': base_page + 'Events' },
+ { 'url': base_page + 'Get+Elements' },
+ { 'url': base_page + 'GridSort' },
+ { 'url': base_page + 'Template' }
+ ]
+ }, dom_perf_dir)
diff --git a/chromium/tools/perf/benchmarks/dromaeo.py b/chromium/tools/perf/benchmarks/dromaeo.py
new file mode 100644
index 00000000000..ed181cd7ea2
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/dromaeo.py
@@ -0,0 +1,76 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import test
+
+from measurements import dromaeo
+
+
+class DromaeoDomCoreAttr(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/domcoreattr.json'
+
+
+class DromaeoDomCoreModify(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/domcoremodify.json'
+
+
+class DromaeoDomCoreQuery(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/domcorequery.json'
+
+
+class DromaeoDomCoreTraverse(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/domcoretraverse.json'
+
+
+class DromaeoJslibAttrJquery(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibattrjquery.json'
+
+
+class DromaeoJslibAttrPrototype(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibattrprototype.json'
+
+
+class DromaeoJslibEventJquery(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibeventjquery.json'
+
+
+class DromaeoJslibEventPrototype(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibeventprototype.json'
+
+
+class DromaeoJslibModifyJquery(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibmodifyjquery.json'
+
+
+class DromaeoJslibModifyPrototype(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibmodifyprototype.json'
+
+
+class DromaeoJslibStyleJquery(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibstylejquery.json'
+
+
+class DromaeoJslibStylePrototype(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibstyleprototype.json'
+
+
+class DromaeoJslibTraverseJquery(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibtraversejquery.json'
+
+
+class DromaeoJslibTraversePrototype(test.Test):
+ test = dromaeo.Dromaeo
+ page_set = 'page_sets/dromaeo/jslibtraverseprototype.json'
diff --git a/chromium/tools/perf/benchmarks/image_decoding.py b/chromium/tools/perf/benchmarks/image_decoding.py
new file mode 100644
index 00000000000..4b4f9fe0e07
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/image_decoding.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import test
+
+from measurements import image_decoding
+
+
+class ImageDecodingToughImageCases(test.Test):
+ test = image_decoding.ImageDecoding
+ # TODO: Rename this page set to tough_image_cases.json
+ page_set = 'page_sets/image_decoding_measurement.json'
diff --git a/chromium/tools/perf/benchmarks/jsgamebench.py b/chromium/tools/perf/benchmarks/jsgamebench.py
new file mode 100644
index 00000000000..d982f75d711
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/jsgamebench.py
@@ -0,0 +1,39 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs Facebook's JSGameBench benchmark."""
+
+import os
+
+from telemetry import test
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+
+
+class JsgamebenchMeasurement(page_measurement.PageMeasurement):
+ def MeasurePage(self, _, tab, results):
+ tab.ExecuteJavaScript('UI.call({}, "perftest")')
+
+ js_is_done = 'document.getElementById("perfscore0") != null'
+ def _IsDone():
+ return bool(tab.EvaluateJavaScript(js_is_done))
+ util.WaitFor(_IsDone, 1200)
+
+ js_get_results = 'document.getElementById("perfscore0").innerHTML'
+ result = int(tab.EvaluateJavaScript(js_get_results))
+ results.Add('Score', 'score (bigger is better)', result)
+
+
+class Jsgamebench(test.Test):
+ """Counts how many animating sprites can move around on the screen at once."""
+ test = JsgamebenchMeasurement
+
+ def CreatePageSet(self, options):
+ return page_set.PageSet.FromDict({
+ 'archive_data_file': '../data/jsgamebench.json',
+ 'pages': [
+ { 'url': 'http://localhost/' }
+ ]
+ }, os.path.dirname(__file__))
diff --git a/chromium/tools/perf/benchmarks/kraken.py b/chromium/tools/perf/benchmarks/kraken.py
new file mode 100644
index 00000000000..2fda99b6bce
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/kraken.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs Mozilla's Kraken JavaScript benchmark."""
+
+import os
+
+from telemetry import test
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+
+
+def _Mean(l):
+ return float(sum(l)) / len(l) if len(l) > 0 else 0.0
+
+
+class KrakenMeasurement(page_measurement.PageMeasurement):
+ def MeasurePage(self, _, tab, results):
+ js_is_done = """
+document.title.indexOf("Results") != -1 && document.readyState == "complete"
+"""
+ def _IsDone():
+ return bool(tab.EvaluateJavaScript(js_is_done))
+ util.WaitFor(_IsDone, 500, poll_interval=5)
+
+ js_get_results = """
+var formElement = document.getElementsByTagName("input")[0];
+decodeURIComponent(formElement.value.split("?")[1]);
+"""
+ result_dict = eval(tab.EvaluateJavaScript(js_get_results))
+ total = 0
+ for key in result_dict:
+ if key == 'v':
+ continue
+ results.Add(key, 'ms', result_dict[key], data_type='unimportant')
+ total += _Mean(result_dict[key])
+ results.Add('Total', 'ms', total)
+
+
+class Kraken(test.Test):
+ """Mozilla's Kraken JavaScript benchmark."""
+ test = KrakenMeasurement
+
+ def CreatePageSet(self, options):
+ return page_set.PageSet.FromDict({
+ 'archive_data_file': '../data/kraken.json',
+ 'pages': [
+ { 'url': 'http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html' }
+ ]
+ }, os.path.abspath(__file__))
diff --git a/chromium/tools/perf/benchmarks/media.py b/chromium/tools/perf/benchmarks/media.py
new file mode 100644
index 00000000000..e588ce14fcf
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/media.py
@@ -0,0 +1,11 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from measurements import media
+from telemetry import test
+
+
+class Media(test.Test):
+ """Obtains media metrics for key user scenarios."""
+ test = media.Media
+ page_set = 'page_sets/tough_video_cases.json'
diff --git a/chromium/tools/perf/benchmarks/memory.py b/chromium/tools/perf/benchmarks/memory.py
new file mode 100644
index 00000000000..05f3e6aac24
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/memory.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import test
+
+from measurements import memory
+
+
+class MemoryTop25(test.Test):
+ test = memory.Memory
+ page_set = 'page_sets/top_25.json'
+
+
+class Reload2012Q3(test.Test):
+ test = memory.Memory
+ page_set = 'page_sets/2012Q3.json'
diff --git a/chromium/tools/perf/benchmarks/octane.py b/chromium/tools/perf/benchmarks/octane.py
new file mode 100644
index 00000000000..9558a8431e9
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/octane.py
@@ -0,0 +1,56 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+from telemetry import test
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+
+
+class OctaneMeasurement(page_measurement.PageMeasurement):
+ def MeasurePage(self, _, tab, results):
+ js_is_done = """
+completed && !document.getElementById("progress-bar-container")"""
+ def _IsDone():
+ return bool(tab.EvaluateJavaScript(js_is_done))
+ util.WaitFor(_IsDone, 300, poll_interval=5)
+
+ js_get_results = """
+var results = {};
+var result_divs = document.querySelectorAll('.p-result');
+for (var r in result_divs) {
+ if (result_divs[r].id && result_divs[r].id.indexOf('Result-') == 0) {
+ var key = result_divs[r].id.replace('Result-', '');
+ results[key] = result_divs[r].innerHTML;
+ }
+}
+var main_banner = document.getElementById("main-banner").innerHTML;
+var octane_score = main_banner.substr(main_banner.lastIndexOf(':') + 2);
+results['score'] = octane_score;
+JSON.stringify(results);
+"""
+ result_dict = eval(tab.EvaluateJavaScript(js_get_results))
+ for key, value in result_dict.iteritems():
+ if value == '...':
+ continue
+ data_type = 'unimportant'
+ if key == 'score':
+ data_type = 'default'
+ results.Add(key, 'score (bigger is better)', value, data_type=data_type)
+
+
+class Octane(test.Test):
+ """Google's Octane JavaScript benchmark."""
+ test = OctaneMeasurement
+
+ def CreatePageSet(self, options):
+ octane_dir = os.path.join(util.GetChromiumSrcDir(), 'chrome', 'test',
+ 'data', 'perf', 'third_party', 'octane')
+ return page_set.PageSet.FromDict({
+ 'pages': [
+ { 'url': 'file:///index.html?auto=1' }
+ ]
+ }, octane_dir)
diff --git a/chromium/tools/perf/benchmarks/page_cycler.py b/chromium/tools/perf/benchmarks/page_cycler.py
new file mode 100644
index 00000000000..bca43f787fd
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/page_cycler.py
@@ -0,0 +1,91 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import test
+
+from measurements import page_cycler
+
+
+class PageCyclerBloat(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/page_cycler/bloat.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerDhtml(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/page_cycler/dhtml.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerIndexeddb(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/page_cycler/indexed_db/basic_insert.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerIntlArFaHe(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/intl_ar_fa_he.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerIntlEsFrPtBr(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/intl_es_fr_pt-BR.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerIntlHiRu(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/intl_hi_ru.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerIntlJaZh(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/intl_ja_zh.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerIntlKoThVi(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/intl_ko_th_vi.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerMorejs(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/page_cycler/morejs.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerMoz(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/page_cycler/moz.json'
+ options = {'pageset_repeat_iters': 10}
+
+
+class PageCyclerNetsimTop25(test.Test):
+ """Measures load time of the top 25 sites under simulated cable network."""
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/top_25.json'
+ options = {
+ 'extra_wpr_args': [
+ '--shaping_type=proxy',
+ '--net=cable'
+ ],
+ 'pageset_repeat_iters': 5,
+ }
+
+ def __init__(self):
+ super(PageCyclerNetsimTop25, self).__init__()
+ # TODO: This isn't quite right.
+ # This option will still apply to page cyclers that run after this one.
+ self.test.clear_cache_before_each_run = True
+
+
+class PageCyclerTypical25(test.Test):
+ test = page_cycler.PageCycler
+ page_set = 'page_sets/typical_25.json'
+ options = {'pageset_repeat_iters': 10}
diff --git a/chromium/tools/perf/benchmarks/pica.py b/chromium/tools/perf/benchmarks/pica.py
new file mode 100644
index 00000000000..912252f577d
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/pica.py
@@ -0,0 +1,20 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry import test
+from telemetry.page import page_measurement
+
+class PicaMeasurement(page_measurement.PageMeasurement):
+ def CustomizeBrowserOptions(self, options):
+ # Needed for native custom elements (document.register)
+ options.AppendExtraBrowserArg('--enable-experimental-web-platform-features')
+
+ def MeasurePage(self, _, tab, results):
+ result = int(tab.EvaluateJavaScript('__pica_load_time'))
+ results.Add('Total', 'ms', result)
+
+
+class Pica(test.Test):
+ test = PicaMeasurement
+ page_set = 'page_sets/pica.json'
diff --git a/chromium/tools/perf/benchmarks/robohornet_pro.py b/chromium/tools/perf/benchmarks/robohornet_pro.py
new file mode 100644
index 00000000000..f14e7828a0a
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/robohornet_pro.py
@@ -0,0 +1,40 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs Microsoft's RoboHornet Pro benchmark."""
+
+import os
+
+from telemetry import test
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+
+
+class RobohornetProMeasurement(page_measurement.PageMeasurement):
+ def MeasurePage(self, _, tab, results):
+ tab.ExecuteJavaScript('ToggleRoboHornet()')
+
+ done = 'document.getElementById("results").innerHTML.indexOf("Total") != -1'
+ def _IsDone():
+ return tab.EvaluateJavaScript(done)
+ util.WaitFor(_IsDone, 120)
+
+ result = int(tab.EvaluateJavaScript('stopTime - startTime'))
+ results.Add('Total', 'ms', result)
+
+
+class RobohornetPro(test.Test):
+ test = RobohornetProMeasurement
+
+ def CreatePageSet(self, options):
+ return page_set.PageSet.FromDict({
+ 'archive_data_file': '../data/robohornetpro.json',
+ # Measurement require use of real Date.now() for measurement.
+ 'make_javascript_deterministic': False,
+ 'pages': [
+ { 'url':
+ 'http://ie.microsoft.com/testdrive/performance/robohornetpro/' }
+ ]
+ }, os.path.abspath(__file__))
diff --git a/chromium/tools/perf/benchmarks/smoothness.py b/chromium/tools/perf/benchmarks/smoothness.py
new file mode 100644
index 00000000000..4f49b78a2e8
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/smoothness.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import test
+
+from measurements import smoothness
+
+
+class SmoothnessTop25(test.Test):
+ """Measures rendering statistics while scrolling down the top 25 web pages.
+
+ http://www.chromium.org/developers/design-documents/rendering-benchmarks"""
+ test = smoothness.Smoothness
+ page_set = 'page_sets/top_25.json'
+ options = {'report_all_results': False}
diff --git a/chromium/tools/perf/benchmarks/spaceport.py b/chromium/tools/perf/benchmarks/spaceport.py
new file mode 100644
index 00000000000..fa0016b434e
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/spaceport.py
@@ -0,0 +1,66 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs spaceport.io's PerfMarks benchmark."""
+
+import logging
+import os
+
+from telemetry import test
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+
+
+class SpaceportMeasurement(page_measurement.PageMeasurement):
+ def CustomizeBrowserOptions(self, options):
+ options.extra_browser_args.extend(['--disable-gpu-vsync'])
+
+ def MeasurePage(self, _, tab, results):
+ util.WaitFor(lambda: tab.EvaluateJavaScript(
+ '!document.getElementById("start-performance-tests").disabled'), 60)
+
+ tab.ExecuteJavaScript("""
+ window.__results = {};
+ window.console.log = function(str) {
+ if (!str) return;
+ var key_val = str.split(': ');
+ if (!key_val.length == 2) return;
+ __results[key_val[0]] = key_val[1];
+ };
+ document.getElementById('start-performance-tests').click();
+ """)
+
+ js_get_results = 'JSON.stringify(window.__results)'
+ num_tests_complete = [0] # A list to work around closure issue.
+ def _IsDone():
+ num_tests_in_measurement = 24
+ num_results = len(eval(tab.EvaluateJavaScript(js_get_results)))
+ if num_results > num_tests_complete[0]:
+ num_tests_complete[0] = num_results
+ logging.info('Completed measurement %d of %d'
+ % (num_tests_complete[0],
+ num_tests_in_measurement))
+ return num_tests_complete[0] >= num_tests_in_measurement
+ util.WaitFor(_IsDone, 1200, poll_interval=5)
+
+ result_dict = eval(tab.EvaluateJavaScript(js_get_results))
+ for key in result_dict:
+ chart, trace = key.split('.', 1)
+ results.Add(trace, 'objects (bigger is better)', float(result_dict[key]),
+ chart_name=chart, data_type='unimportant')
+ results.Add('Score', 'objects (bigger is better)',
+ [float(x) for x in result_dict.values()])
+
+
+class Spaceport(test.Test):
+ """spaceport.io's PerfMarks benchmark."""
+ test = SpaceportMeasurement
+
+ def CreatePageSet(self, options):
+ spaceport_dir = os.path.join(util.GetChromiumSrcDir(), 'chrome', 'test',
+ 'data', 'third_party', 'spaceport')
+ return page_set.PageSet.FromDict(
+ {'pages': [{'url': 'file:///index.html'}]},
+ spaceport_dir)
diff --git a/chromium/tools/perf/benchmarks/startup.py b/chromium/tools/perf/benchmarks/startup.py
new file mode 100644
index 00000000000..df8d0500ed2
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/startup.py
@@ -0,0 +1,20 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry import test
+
+from measurements import startup
+
+
+class StartupColdBlankPage(test.Test):
+ test = startup.Startup
+ page_set = 'page_sets/blank_page.json'
+ options = {'cold': True,
+ 'pageset_repeat_iters': 5}
+
+
+class StartupWarmBlankPage(test.Test):
+ test = startup.Startup
+ page_set = 'page_sets/blank_page.json'
+ options = {'warm': True,
+ 'pageset_repeat_iters': 20}
diff --git a/chromium/tools/perf/benchmarks/sunspider.py b/chromium/tools/perf/benchmarks/sunspider.py
new file mode 100644
index 00000000000..a309e383ce0
--- /dev/null
+++ b/chromium/tools/perf/benchmarks/sunspider.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import collections
+import json
+import os
+
+from telemetry import test
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+
+
+class SunspiderMeasurement(page_measurement.PageMeasurement):
+ def MeasurePage(self, _, tab, results):
+ js_is_done = ('window.location.pathname.indexOf("results.html") >= 0'
+ '&& typeof(output) != "undefined"')
+ def _IsDone():
+ return tab.EvaluateJavaScript(js_is_done)
+ util.WaitFor(_IsDone, 300, poll_interval=1)
+
+ js_get_results = 'JSON.stringify(output);'
+ js_results = json.loads(tab.EvaluateJavaScript(js_get_results))
+ r = collections.defaultdict(list)
+ totals = []
+ # js_results is: [{'foo': v1, 'bar': v2},
+ # {'foo': v3, 'bar': v4},
+ # ...]
+ for result in js_results:
+ total = 0
+ for key, value in result.iteritems():
+ r[key].append(value)
+ total += value
+ totals.append(total)
+ for key, values in r.iteritems():
+ results.Add(key, 'ms', values, data_type='unimportant')
+ results.Add('Total', 'ms', totals)
+
+
+class Sunspider(test.Test):
+ """Apple's SunSpider JavaScript benchmark."""
+ test = SunspiderMeasurement
+
+ def CreatePageSet(self, options):
+ sunspider_dir = os.path.join(util.GetChromiumSrcDir(),
+ 'chrome', 'test', 'data', 'sunspider')
+ return page_set.PageSet.FromDict(
+ {
+ 'serving_dirs': [''],
+ 'pages': [{ 'url': 'file:///sunspider-1.0/driver.html' }],
+ },
+ sunspider_dir)
diff --git a/chromium/tools/perf/clear_system_cache/clear_system_cache.gyp b/chromium/tools/perf/clear_system_cache/clear_system_cache.gyp
new file mode 100644
index 00000000000..cf6299a03a9
--- /dev/null
+++ b/chromium/tools/perf/clear_system_cache/clear_system_cache.gyp
@@ -0,0 +1,23 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets' : [
+ {
+ 'target_name': 'clear_system_cache',
+ 'type': 'executable',
+ 'toolsets': ['target'],
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../base/base.gyp:test_support_base',
+ ],
+ 'sources': [
+ 'clear_system_cache_main.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/perf/clear_system_cache/clear_system_cache_main.cc b/chromium/tools/perf/clear_system_cache/clear_system_cache_main.cc
new file mode 100644
index 00000000000..9f48c61ca0d
--- /dev/null
+++ b/chromium/tools/perf/clear_system_cache/clear_system_cache_main.cc
@@ -0,0 +1,55 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A utility to clear the operating system's cache for a file or directory.
+//
+// USAGE: clear_system_cache [--recurse] <files or directories>
+
+#include <stdio.h>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/test/test_file_util.h"
+
+void ClearCacheForFile(const base::FilePath& path) {
+ VLOG(1) << "Clearing " << path.MaybeAsASCII();
+ file_util::EvictFileFromSystemCache(path);
+}
+
+int main(int argc, const char* argv[]) {
+ CommandLine::Init(argc, argv);
+ const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
+ bool should_recurse = parsed_command_line.HasSwitch("recurse");
+ const CommandLine::StringVector& args = parsed_command_line.GetArgs();
+
+ if (args.size() < 1) {
+ printf("USAGE: %s [--recurse] <files or directories>\n", argv[0]);
+ return 1;
+ }
+
+ for (size_t i = 0; i < args.size(); ++i) {
+ base::FilePath path(args[i]);
+ if (!base::PathExists(path)) {
+ LOG(ERROR) << "Couldn't find " << path.MaybeAsASCII();
+ return 1;
+ }
+
+ if (base::DirectoryExists(path)) {
+ base::FileEnumerator enumerator(path, should_recurse,
+ base::FileEnumerator::FILES);
+ for (base::FilePath next = enumerator.Next(); !next.empty();
+ next = enumerator.Next()) {
+ ClearCacheForFile(next);
+ }
+ } else {
+ ClearCacheForFile(path);
+ }
+ }
+
+ return 0;
+}
diff --git a/chromium/tools/perf/measurements/__init__.py b/chromium/tools/perf/measurements/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/perf/measurements/__init__.py
diff --git a/chromium/tools/perf/measurements/blink_perf.js b/chromium/tools/perf/measurements/blink_perf.js
new file mode 100644
index 00000000000..155f22fce7b
--- /dev/null
+++ b/chromium/tools/perf/measurements/blink_perf.js
@@ -0,0 +1,20 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+window.testRunner = {};
+window.testRunner.isDone = false;
+
+testRunner.waitUntilDone = function() {};
+testRunner.dumpAsText = function() {};
+testRunner.notifyDone = function() {
+ this.isDone = true;
+};
+
+window.GCController = {};
+
+GCController.collect = function() {
+ gc();
+};
+})();
diff --git a/chromium/tools/perf/measurements/blink_perf.py b/chromium/tools/perf/measurements/blink_perf.py
new file mode 100644
index 00000000000..f21cf98fb84
--- /dev/null
+++ b/chromium/tools/perf/measurements/blink_perf.py
@@ -0,0 +1,104 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This measurement runs a blink performance test and reports the results."""
+
+import os
+import sys
+
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+
+
+def CreatePageSetFromPath(path):
+ assert os.path.exists(path)
+
+ page_set_dict = {'pages': []}
+
+ def _AddPage(path):
+ if not path.endswith('.html'):
+ return
+ if '../' in open(path, 'r').read():
+ # If the page looks like it references its parent dir, include it.
+ page_set_dict['serving_dirs'] = [os.path.dirname(os.path.dirname(path))]
+ page_set_dict['pages'].append({'url':
+ 'file://' + path.replace('\\', '/')})
+
+ def _AddDir(dir_path, skipped):
+ for candidate_path in os.listdir(dir_path):
+ if candidate_path == 'resources':
+ continue
+ candidate_path = os.path.join(dir_path, candidate_path)
+ if candidate_path.startswith(tuple([os.path.join(path, s)
+ for s in skipped])):
+ continue
+ if os.path.isdir(candidate_path):
+ _AddDir(candidate_path, skipped)
+ else:
+ _AddPage(candidate_path)
+
+ if os.path.isdir(path):
+ skipped = []
+ skipped_file = os.path.join(path, 'Skipped')
+ if os.path.exists(skipped_file):
+ for line in open(skipped_file, 'r').readlines():
+ line = line.strip()
+ if line and not line.startswith('#'):
+ skipped.append(line.replace('/', os.sep))
+ _AddDir(path, skipped)
+ else:
+ _AddPage(path)
+ return page_set.PageSet.FromDict(page_set_dict, os.getcwd() + os.sep)
+
+
+class BlinkPerf(page_measurement.PageMeasurement):
+ def __init__(self):
+ super(BlinkPerf, self).__init__('')
+ with open(os.path.join(os.path.dirname(__file__),
+ 'blink_perf.js'), 'r') as f:
+ self._blink_perf_js = f.read()
+
+ def CreatePageSet(self, args, options):
+ if len(args) < 2:
+ print 'Must specify a file or directory to run.'
+ sys.exit(1)
+
+ page_set_arg = args[1]
+
+ if not os.path.exists(page_set_arg):
+ print '%s does not exist.' % page_set_arg
+ sys.exit(1)
+
+ return CreatePageSetFromPath(page_set_arg)
+
+ @property
+ def results_are_the_same_on_every_page(self):
+ return False
+
+ def WillNavigateToPage(self, page, tab):
+ page.script_to_evaluate_on_commit = self._blink_perf_js
+
+ def CustomizeBrowserOptions(self, options):
+ options.AppendExtraBrowserArg('--js-flags=--expose_gc')
+ options.AppendExtraBrowserArg('--enable-experimental-web-platform-features')
+
+ def MeasurePage(self, page, tab, results):
+ def _IsDone():
+ return tab.EvaluateJavaScript('testRunner.isDone')
+ util.WaitFor(_IsDone, 600)
+
+ log = tab.EvaluateJavaScript('document.getElementById("log").innerHTML')
+
+ for line in log.splitlines():
+ if not line.startswith('values '):
+ continue
+ parts = line.split()
+ values = [float(v.replace(',', '')) for v in parts[1:-1]]
+ units = parts[-1]
+ metric = page.display_url.split('.')[0].replace('/', '_')
+ results.Add(metric, units, values)
+ break
+
+ print log
diff --git a/chromium/tools/perf/measurements/dromaeo.py b/chromium/tools/perf/measurements/dromaeo.py
new file mode 100644
index 00000000000..96037eaaca7
--- /dev/null
+++ b/chromium/tools/perf/measurements/dromaeo.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core import util
+from telemetry.page import page_measurement
+
+class Dromaeo(page_measurement.PageMeasurement):
+ def MeasurePage(self, page, tab, results):
+ js_is_done = 'window.document.cookie.indexOf("__done=1") >= 0'
+ def _IsDone():
+ return bool(tab.EvaluateJavaScript(js_is_done))
+ util.WaitFor(_IsDone, 600, poll_interval=5)
+
+ js_get_results = 'JSON.stringify(window.automation.GetResults())'
+ print js_get_results
+ score = eval(tab.EvaluateJavaScript(js_get_results))
+
+ def Escape(k):
+ chars = [' ', '-', '/', '(', ')', '*']
+ for c in chars:
+ k = k.replace(c, '_')
+ return k
+
+ suffix = page.url[page.url.index('?') + 1 : page.url.index('&')]
+ for k, v in score.iteritems():
+ data_type = 'unimportant'
+ if k == suffix:
+ data_type = 'default'
+ results.Add(Escape(k), 'runs/s', v, data_type=data_type)
diff --git a/chromium/tools/perf/measurements/image_decoding.py b/chromium/tools/perf/measurements/image_decoding.py
new file mode 100644
index 00000000000..3f67ae435a4
--- /dev/null
+++ b/chromium/tools/perf/measurements/image_decoding.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page import page_measurement
+
+
+class ImageDecoding(page_measurement.PageMeasurement):
+ def CustomizeBrowserOptions(self, options):
+ options.extra_browser_args.append('--enable-gpu-benchmarking')
+
+ def WillNavigateToPage(self, page, tab):
+ tab.ExecuteJavaScript("""
+ if (window.chrome &&
+ chrome.gpuBenchmarking &&
+ chrome.gpuBenchmarking.clearImageCache) {
+ chrome.gpuBenchmarking.clearImageCache();
+ }
+ """)
+ tab.StartTimelineRecording()
+
+ def NeedsBrowserRestartAfterEachRun(self, tab):
+ return not tab.ExecuteJavaScript("""
+ window.chrome &&
+ chrome.gpuBenchmarking &&
+ chrome.gpuBenchmarking.clearImageCache;
+ """)
+
+ def MeasurePage(self, page, tab, results):
+ tab.StopTimelineRecording()
+ def _IsDone():
+ return tab.EvaluateJavaScript('isDone')
+
+ decode_image_events = \
+ tab.timeline_model.GetAllEventsOfName('DecodeImage')
+
+ # If it is a real image page, then store only the last-minIterations
+ # decode tasks.
+ if (hasattr(page,
+ 'image_decoding_measurement_limit_results_to_min_iterations') and
+ page.image_decoding_measurement_limit_results_to_min_iterations):
+ assert _IsDone()
+ min_iterations = tab.EvaluateJavaScript('minIterations')
+ decode_image_events = decode_image_events[-min_iterations:]
+
+ durations = [d.duration for d in decode_image_events]
+ if not durations:
+ results.Add('ImageDecoding_avg', 'ms', 'unsupported')
+ return
+ image_decoding_avg = sum(durations) / len(durations)
+ results.Add('ImageDecoding_avg', 'ms', image_decoding_avg)
+ results.Add('ImageLoading_avg', 'ms',
+ tab.EvaluateJavaScript('averageLoadingTimeMs()'))
diff --git a/chromium/tools/perf/measurements/loading_measurement_analyzer.py b/chromium/tools/perf/measurements/loading_measurement_analyzer.py
new file mode 100755
index 00000000000..1d2b1839425
--- /dev/null
+++ b/chromium/tools/perf/measurements/loading_measurement_analyzer.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Parses CSV output from the loading_measurement and outputs interesting stats.
+
+Example usage:
+$ tools/perf/run_measurement --browser=release \
+ --output-format=csv --output=/path/to/loading_measurement_output.csv \
+ loading_measurement tools/perf/page_sets/top_1m.json
+$ tools/perf/measurements/loading_measurement_analyzer.py \
+ --num-slowest-urls=100 --rank-csv-file=/path/to/top-1m.csv \
+ /path/to/loading_measurement_output.csv
+"""
+
+import collections
+import csv
+import heapq
+import optparse
+import os
+import re
+import sys
+
+
+class LoadingMeasurementAnalyzer(object):
+
+ def __init__(self, input_file, options):
+ self.ranks = {}
+ self.totals = collections.defaultdict(list)
+ self.maxes = collections.defaultdict(list)
+ self.avgs = collections.defaultdict(list)
+ self.load_times = []
+ self.cpu_times = []
+ self.network_percents = []
+ self.num_rows_parsed = 0
+ self.num_slowest_urls = options.num_slowest_urls
+ if options.rank_csv_file:
+ self._ParseRankCsvFile(os.path.expanduser(options.rank_csv_file))
+ self._ParseInputFile(input_file, options)
+ self._display_zeros = options.display_zeros
+
+ def _ParseInputFile(self, input_file, options):
+ with open(input_file, 'r') as csvfile:
+ row_dict = csv.DictReader(csvfile)
+ for row in row_dict:
+ if (options.rank_limit and
+ self._GetRank(row['url']) > options.rank_limit):
+ continue
+ cpu_time = 0
+ load_time = float(row['load_time (ms)'])
+ if load_time < 0:
+ print 'Skipping %s due to negative load time' % row['url']
+ continue
+ for key, value in row.iteritems():
+ if key in ('url', 'load_time (ms)', 'dom_content_loaded_time (ms)'):
+ continue
+ if not value or value == '-':
+ continue
+ value = float(value)
+ if not value:
+ continue
+ if '_avg' in key:
+ self.avgs[key].append((value, row['url']))
+ elif '_max' in key:
+ self.maxes[key].append((value, row['url']))
+ else:
+ self.totals[key].append((value, row['url']))
+ cpu_time += value
+ self.load_times.append((load_time, row['url']))
+ self.cpu_times.append((cpu_time, row['url']))
+ if options.show_network:
+ network_time = load_time - cpu_time
+ self.totals['Network (ms)'].append((network_time, row['url']))
+ self.network_percents.append((network_time / load_time, row['url']))
+ self.num_rows_parsed += 1
+ if options.max_rows and self.num_rows_parsed == int(options.max_rows):
+ break
+
+ def _ParseRankCsvFile(self, input_file):
+ with open(input_file, 'r') as csvfile:
+ for row in csv.reader(csvfile):
+ assert len(row) == 2
+ self.ranks[row[1]] = int(row[0])
+
+ def _GetRank(self, url):
+ url = url.replace('http://', '')
+ if url in self.ranks:
+ return self.ranks[url]
+ return len(self.ranks)
+
+ def PrintSummary(self, stdout):
+ sum_totals = {}
+ units = None
+ for key, values in self.totals.iteritems():
+ m = re.match('.* [(](.*)[)]', key)
+ assert m, 'All keys should have units.'
+ assert not units or units == m.group(1), 'All units should be the same.'
+ units = m.group(1)
+ sum_totals[key] = sum([v[0] for v in values])
+ total_cpu_time = sum([v[0] for v in self.cpu_times])
+ total_page_load_time = sum([v[0] for v in self.load_times])
+
+ print >> stdout
+ print >> stdout, 'Total URLs:', self.num_rows_parsed
+ print >> stdout, 'Total page load time: %ds' % int(round(
+ total_page_load_time / 1000))
+ print >> stdout, 'Average page load time: %dms' % int(round(
+ total_page_load_time / self.num_rows_parsed))
+ if units == 'ms':
+ print >> stdout, 'Total CPU time: %ds' % int(round(total_cpu_time / 1000))
+ print >> stdout, 'Average CPU time: %dms' % int(round(
+ total_cpu_time / self.num_rows_parsed))
+ print >> stdout
+ for key, value in sorted(sum_totals.iteritems(), reverse=True,
+ key=lambda i: i[1]):
+ if not self._display_zeros and not int(value / 100.):
+ break
+ output_key = '%60s: ' % re.sub(' [(].*[)]', '', key)
+ if units == 'ms':
+ output_value = '%10ds ' % (value / 1000)
+ output_percent = '%.1f%%' % (100 * value / total_page_load_time)
+ else:
+ output_value = '%10d%s ' % (value, units)
+ output_percent = '%.1f%%' % (100 * value / total_cpu_time)
+ print >> stdout, output_key, output_value, output_percent
+
+ if not self.num_slowest_urls:
+ return
+
+ for key, values in sorted(self.totals.iteritems(), reverse=True,
+ key=lambda i: sum_totals[i[0]]):
+ if not self._display_zeros and not int(sum_totals[key] / 100.):
+ break
+ print >> stdout
+ print >> stdout, 'Top %d slowest %s:' % (self.num_slowest_urls,
+ re.sub(' [(].*[)]', '', key))
+ slowest = heapq.nlargest(self.num_slowest_urls, values)
+ for value, url in slowest:
+ print >> stdout, '%10d%s\t%s (#%s)' % (value, units, url,
+ self._GetRank(url))
+
+ if self.network_percents:
+ print >> stdout
+ print >> stdout, 'Top %d highest network to CPU time ratios:' % (
+ self.num_slowest_urls)
+ for percent, url in sorted(
+ self.network_percents, reverse=True)[:self.num_slowest_urls]:
+ percent *= 100
+ print >> stdout, '\t', '%.1f%%' % percent, url, '(#%s)' % (
+ self._GetRank(url))
+
+
+def main(arguments, stdout=sys.stdout):
+ prog_desc = 'Parses CSV output from the loading_measurement'
+ parser = optparse.OptionParser(usage=('%prog [options]' + '\n\n' + prog_desc))
+
+ parser.add_option('--max-rows', type='int',
+ help='Only process this many rows')
+ parser.add_option('--num-slowest-urls', type='int',
+ help='Output this many slowest URLs for each category')
+ parser.add_option('--rank-csv-file', help='A CSV file of <rank,url>')
+ parser.add_option('--rank-limit', type='int',
+ help='Only process pages higher than this rank')
+ parser.add_option('--show-network', action='store_true',
+ help='Whether to display Network as a category')
+ parser.add_option('--display-zeros', action='store_true',
+ help='Whether to display categories with zero time')
+
+ options, args = parser.parse_args(arguments)
+
+ assert len(args) == 1, 'Must pass exactly one CSV file to analyze'
+ if options.rank_limit and not options.rank_csv_file:
+ print 'Must pass --rank-csv-file with --rank-limit'
+ return 1
+
+ LoadingMeasurementAnalyzer(args[0], options).PrintSummary(stdout)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/perf/measurements/loading_measurement_analyzer_unittest.py b/chromium/tools/perf/measurements/loading_measurement_analyzer_unittest.py
new file mode 100644
index 00000000000..88401174c0e
--- /dev/null
+++ b/chromium/tools/perf/measurements/loading_measurement_analyzer_unittest.py
@@ -0,0 +1,54 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import StringIO
+import unittest
+
+from measurements import loading_measurement_analyzer
+from telemetry.core import util
+
+class LoadingMeasurementAnalyzerUnitTest(unittest.TestCase):
+
+ # TODO(tonyg): Remove this backfill when we can assume python 2.7 everywhere.
+ def assertIn(self, first, second, msg=None):
+ self.assertTrue(first in second,
+ msg="'%s' not found in '%s'" % (first, second))
+
+ def testLoadingProfile(self):
+ output = StringIO.StringIO()
+ csv_path = os.path.join(
+ util.GetChromiumSrcDir(),
+ 'tools', 'perf', 'measurements','test_data', 'loading_profile.csv')
+ loading_measurement_analyzer.main([csv_path], stdout=output)
+ output = output.getvalue()
+
+ # Get the summary right.
+ self.assertIn('Total URLs: 9', output)
+ self.assertIn('Total page load time: 51s', output)
+ self.assertIn('Average page load time: 5621ms', output)
+
+ # Spot check a few samples.
+ self.assertIn('WTF::IntHash::hash: 1359797948period 1.1%', output)
+ self.assertIn('WebCore::rangesIntersect: 648335678period 0.5%', output)
+ self.assertIn('v8::internal::Scanner::Scan: 19668346period 0.0', output)
+
+ def testLoadingTimeline(self):
+ output = StringIO.StringIO()
+ csv_path = os.path.join(
+ util.GetChromiumSrcDir(),
+ 'tools', 'perf', 'measurements','test_data', 'loading_timeline.csv')
+ loading_measurement_analyzer.main([csv_path], stdout=output)
+ output = output.getvalue()
+
+ # Get the summary right.
+ self.assertIn('Total URLs: 9', output)
+ self.assertIn('Total page load time: 4s', output)
+ self.assertIn('Average page load time: 422ms', output)
+ self.assertIn('Total CPU time: 4s', output)
+ self.assertIn('Average CPU time: 430ms', output)
+
+ # Spot check a few samples.
+ self.assertIn('EvaluateScript: 0s 19.0%', output)
+ self.assertIn('ParseHTML: 0s 9.4%', output)
+ self.assertIn('GCEvent: 0s 3.7%', output)
diff --git a/chromium/tools/perf/measurements/loading_profile.py b/chromium/tools/perf/measurements/loading_profile.py
new file mode 100644
index 00000000000..efaf4d78394
--- /dev/null
+++ b/chromium/tools/perf/measurements/loading_profile.py
@@ -0,0 +1,58 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import tempfile
+
+from metrics import loading
+from telemetry.core import util
+from telemetry.core.platform.profiler import perf_profiler
+from telemetry.page import page_measurement
+
+class LoadingProfile(page_measurement.PageMeasurement):
+ def __init__(self):
+ super(LoadingProfile, self).__init__(discard_first_result=True)
+
+ if not perf_profiler.PerfProfiler.is_supported(None):
+ raise Exception('This measurement is not supported on this platform')
+
+ @property
+ def results_are_the_same_on_every_page(self):
+ return False
+
+ def AddCommandLineOptions(self, parser):
+ # In order to change the default of an option, we must remove and re-add it.
+ page_repeat_option = parser.get_option('--page-repeat')
+ page_repeat_option.default = 2
+ parser.remove_option('--page-repeat')
+ parser.add_option(page_repeat_option)
+
+ def CustomizeBrowserOptions(self, options):
+ options.AppendExtraBrowserArg('--no-sandbox')
+ perf_profiler.PerfProfiler.CustomizeBrowserOptions(options)
+
+ def WillNavigateToPage(self, page, tab):
+ tab.browser.StartProfiling(perf_profiler.PerfProfiler.name(),
+ os.path.join(tempfile.mkdtemp(),
+ page.url_as_file_safe_name))
+
+ def MeasurePage(self, page, tab, results):
+ # In current telemetry tests, all tests wait for DocumentComplete state,
+ # but we need to wait for the load event.
+ def IsLoaded():
+ return bool(tab.EvaluateJavaScript('performance.timing.loadEventStart'))
+ util.WaitFor(IsLoaded, 300)
+
+ profile_files = tab.browser.StopProfiling()
+
+ loading.LoadingMetric().AddResults(tab, results)
+
+ profile_file = None
+ for profile_file in profile_files:
+ if 'renderer' in profile_file:
+ break
+
+ for function, period in perf_profiler.PerfProfiler.GetTopSamples(
+ profile_file, 10).iteritems():
+ results.Add(function.replace('.', '_'), 'period', period)
diff --git a/chromium/tools/perf/measurements/loading_timeline.py b/chromium/tools/perf/measurements/loading_timeline.py
new file mode 100644
index 00000000000..9ec9e707878
--- /dev/null
+++ b/chromium/tools/perf/measurements/loading_timeline.py
@@ -0,0 +1,34 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from metrics import timeline
+from metrics import loading
+from telemetry.core import util
+from telemetry.page import page_measurement
+
+class LoadingTimeline(page_measurement.PageMeasurement):
+ def __init__(self, *args, **kwargs):
+ super(LoadingTimeline, self).__init__(*args, **kwargs)
+ self._metrics = None
+
+ @property
+ def results_are_the_same_on_every_page(self):
+ return False
+
+ def WillNavigateToPage(self, page, tab):
+ self._metrics = timeline.TimelineMetrics(timeline.TIMELINE_MODE)
+ self._metrics.Start(tab)
+
+ def MeasurePage(self, page, tab, results):
+ # In current telemetry tests, all tests wait for DocumentComplete state,
+ # but we need to wait for the load event.
+ def IsLoaded():
+ return bool(tab.EvaluateJavaScript('performance.timing.loadEventStart'))
+ util.WaitFor(IsLoaded, 300)
+
+ # TODO(nduca): when crbug.com/168431 is fixed, modify the page sets to
+ # recognize loading as a toplevel action.
+ self._metrics.Stop(tab)
+
+ loading.LoadingMetric().AddResults(tab, results)
+ self._metrics.AddResults(results)
diff --git a/chromium/tools/perf/measurements/loading_trace.py b/chromium/tools/perf/measurements/loading_trace.py
new file mode 100644
index 00000000000..68f241b1fe1
--- /dev/null
+++ b/chromium/tools/perf/measurements/loading_trace.py
@@ -0,0 +1,34 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from metrics import loading
+from metrics import timeline
+from telemetry.core import util
+from telemetry.page import page_measurement
+
+class LoadingTrace(page_measurement.PageMeasurement):
+ def __init__(self, *args, **kwargs):
+ super(LoadingTrace, self).__init__(*args, **kwargs)
+ self._metrics = None
+
+ @property
+ def results_are_the_same_on_every_page(self):
+ return False
+
+ def WillNavigateToPage(self, page, tab):
+ self._metrics = timeline.TimelineMetrics(timeline.TRACING_MODE)
+ self._metrics.Start(tab)
+
+ def MeasurePage(self, page, tab, results):
+ # In current telemetry tests, all tests wait for DocumentComplete state,
+ # but we need to wait for the load event.
+ def IsLoaded():
+ return bool(tab.EvaluateJavaScript('performance.timing.loadEventStart'))
+ util.WaitFor(IsLoaded, 300)
+
+ # TODO(nduca): when crbug.com/168431 is fixed, modify the page sets to
+ # recognize loading as a toplevel action.
+ self._metrics.Stop(tab)
+
+ loading.LoadingMetric().AddResults(tab, results)
+ self._metrics.AddResults(results)
diff --git a/chromium/tools/perf/measurements/media.py b/chromium/tools/perf/measurements/media.py
new file mode 100644
index 00000000000..4d2ffcffe65
--- /dev/null
+++ b/chromium/tools/perf/measurements/media.py
@@ -0,0 +1,30 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from metrics import media
+from telemetry.page import page_measurement
+
+class Media(page_measurement.PageMeasurement):
+ """The MediaMeasurement class gathers media-related metrics on a page set.
+
+ Media metrics recorded are controlled by metrics/media.js. At the end of the
+ test each metric for every media element in the page are reported.
+ """
+ def __init__(self):
+ super(Media, self).__init__('media_metrics')
+ self._media_metric = None
+
+ def results_are_the_same_on_every_page(self):
+ """Results can vary from page to page based on media events taking place."""
+ return False
+
+ def DidNavigateToPage(self, page, tab):
+ """Override to do operations right after the page is navigated."""
+ self._media_metric = media.MediaMetric(tab)
+ self._media_metric.Start(page, tab)
+
+ def MeasurePage(self, page, tab, results):
+ """Measure the page's performance."""
+ self._media_metric.Stop(page, tab)
+ self._media_metric.AddResults(tab, results)
diff --git a/chromium/tools/perf/measurements/memory.py b/chromium/tools/perf/measurements/memory.py
new file mode 100644
index 00000000000..f15184af6ac
--- /dev/null
+++ b/chromium/tools/perf/measurements/memory.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from metrics import histogram
+from metrics import memory
+from telemetry.page import page_measurement
+
+
+MEMORY_HISTOGRAMS = [
+ {'name': 'V8.MemoryExternalFragmentationTotal', 'units': 'percent'},
+ {'name': 'V8.MemoryHeapSampleTotalCommitted', 'units': 'kb'},
+ {'name': 'V8.MemoryHeapSampleTotalUsed', 'units': 'kb'},
+ {'name': 'Memory.RendererUsed', 'units': 'kb'}]
+
+
+BROWSER_MEMORY_HISTOGRAMS = [
+ {'name': 'Memory.BrowserUsed', 'units': 'kb'}]
+
+
+class Memory(page_measurement.PageMeasurement):
+ def __init__(self):
+ super(Memory, self).__init__('stress_memory')
+ self.histograms = (
+ [histogram.HistogramMetric(
+ h, histogram.RENDERER_HISTOGRAM)
+ for h in MEMORY_HISTOGRAMS] +
+ [histogram.HistogramMetric(
+ h, histogram.BROWSER_HISTOGRAM)
+ for h in BROWSER_MEMORY_HISTOGRAMS])
+
+ self._memory_metric = None
+
+ def DidStartBrowser(self, browser):
+ self._memory_metric = memory.MemoryMetric(browser)
+ self._memory_metric.Start()
+
+ def DidNavigateToPage(self, page, tab):
+ for h in self.histograms:
+ h.Start(page, tab)
+
+ def CustomizeBrowserOptions(self, options):
+ options.AppendExtraBrowserArg('--enable-stats-collection-bindings')
+ options.AppendExtraBrowserArg('--enable-memory-benchmarking')
+ # For a hard-coded set of Google pages (such as GMail), we produce custom
+ # memory histograms (V8.Something_gmail) instead of the generic histograms
+ # (V8.Something), if we detect that a renderer is only rendering this page
+ # and no other pages. For this test, we need to disable histogram
+ # customizing, so that we get the same generic histograms produced for all
+ # pages.
+ options.AppendExtraBrowserArg('--disable-histogram-customizer')
+ options.AppendExtraBrowserArg('--memory-metrics')
+
+ # Old commandline flags used for reference builds.
+ options.AppendExtraBrowserArg('--dom-automation')
+ options.AppendExtraBrowserArg(
+ '--reduce-security-for-dom-automation-tests')
+
+ def CanRunForPage(self, page):
+ return hasattr(page, 'stress_memory')
+
+ def MeasurePage(self, page, tab, results):
+ for h in self.histograms:
+ h.GetValue(page, tab, results)
+
+ if tab.browser.is_profiler_active('tcmalloc-heap'):
+ # The tcmalloc_heap_profiler dumps files at regular
+ # intervals (~20 secs).
+ # This is a minor optimization to ensure it'll dump the last file when
+ # the test completes.
+ tab.ExecuteJavaScript("""
+ if (chrome && chrome.memoryBenchmarking) {
+ chrome.memoryBenchmarking.heapProfilerDump('final', 'renderer');
+ chrome.memoryBenchmarking.heapProfilerDump('final', 'browser');
+ }
+ """)
+
+ def DidRunTest(self, tab, results):
+ self._memory_metric.Stop()
+ self._memory_metric.AddResults(tab, results)
+
diff --git a/chromium/tools/perf/measurements/page_cycler.js b/chromium/tools/perf/measurements/page_cycler.js
new file mode 100644
index 00000000000..73ded1e2ee5
--- /dev/null
+++ b/chromium/tools/perf/measurements/page_cycler.js
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+// The Mozilla DHTML performance tests need to explicitly call a function to
+// trigger the next page visit, rather than directly using the onload handler.
+// To meet needs of the DHTML performance tests without forking this head.js
+// file, use a variable |__install_onload_handler| to indicate whether the
+// |__onload| handler should be added to onload event listener.
+// Install |__onload| by default if there is no pre-configuration.
+if (typeof(__install_onload_handler) == 'undefined')
+ var __install_onload_handler = true;
+
+// This is the timeout used in setTimeout inside the DHTML tests. Chrome has
+// a much more accurate timer resolution than other browsers do. This results
+// in Chrome running these tests much faster than other browsers. In order to
+// compare Chrome with other browsers on DHTML performance alone, set this
+// value to ~15.
+var __test_timeout = 0;
+
+function __set_cookie(name, value) {
+ document.cookie = name + "=" + value + "; path=/";
+}
+
+function __onbeforeunload() {
+ // Call GC twice to cleanup JS heap before starting a new test.
+ if (window.gc) {
+ window.gc();
+ window.gc();
+ }
+}
+
+// The function |__onload| is used by the DHTML tests.
+window.__onload = function() {
+ // window.storeCreated is used by the Indexed DB tests.
+ if ((!__install_onload_handler || window.storeCreated) &&
+ !performance.timing.loadEventEnd)
+ return;
+
+ var unused = document.body.offsetHeight; // force layout
+
+ testComplete(window.performance.now());
+};
+
+// The function |testComplete| is used by the Indexed DB tests.
+window.testComplete = function(time) {
+ window.__pc_load_time = time;
+};
+
+// The function |__eval_later| now is only used by the DHTML tests.
+window.__eval_later = function(expression) {
+ setTimeout(expression, __test_timeout);
+};
+
+if (window.parent == window) { // Ignore subframes.
+ window.__pc_load_time = null;
+ addEventListener("load", __onload);
+ addEventListener("beforeunload", __onbeforeunload);
+}
+})();
diff --git a/chromium/tools/perf/measurements/page_cycler.py b/chromium/tools/perf/measurements/page_cycler.py
new file mode 100644
index 00000000000..50d11e84109
--- /dev/null
+++ b/chromium/tools/perf/measurements/page_cycler.py
@@ -0,0 +1,104 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The page cycler measurement.
+
+This measurement registers a window load handler in which is forces a layout and
+then records the value of performance.now(). This call to now() measures the
+time from navigationStart (immediately after the previous page's beforeunload
+event) until after the layout in the page's load event. In addition, two garbage
+collections are performed in between the page loads (in the beforeunload event).
+This extra garbage collection time is not included in the measurement times.
+
+Finally, various memory and IO statistics are gathered at the very end of
+cycling all pages.
+"""
+
+import os
+import sys
+
+from metrics import histogram
+from metrics import io
+from metrics import memory
+from telemetry.core import util
+from telemetry.page import page_measurement
+
+
+MEMORY_HISTOGRAMS = [
+ {'name': 'V8.MemoryExternalFragmentationTotal', 'units': 'percent'},
+ {'name': 'V8.MemoryHeapSampleTotalCommitted', 'units': 'kb'},
+ {'name': 'V8.MemoryHeapSampleTotalUsed', 'units': 'kb'}]
+
+
+class PageCycler(page_measurement.PageMeasurement):
+ def __init__(self, *args, **kwargs):
+ super(PageCycler, self).__init__(*args, **kwargs)
+
+ with open(os.path.join(os.path.dirname(__file__),
+ 'page_cycler.js'), 'r') as f:
+ self._page_cycler_js = f.read()
+
+ self._memory_metric = None
+ self._histograms = None
+
+ def AddCommandLineOptions(self, parser):
+ # The page cyclers should default to 10 iterations. In order to change the
+ # default of an option, we must remove and re-add it.
+ # TODO: Remove this after transition to run_benchmark.
+ pageset_repeat_option = parser.get_option('--pageset-repeat')
+ pageset_repeat_option.default = 10
+ parser.remove_option('--pageset-repeat')
+ parser.add_option(pageset_repeat_option)
+
+ def DidStartBrowser(self, browser):
+ """Initialize metrics once right after the browser has been launched."""
+ self._memory_metric = memory.MemoryMetric(browser)
+ self._memory_metric.Start()
+ self._histograms = [histogram.HistogramMetric(
+ h, histogram.RENDERER_HISTOGRAM)
+ for h in MEMORY_HISTOGRAMS]
+
+ def DidStartHTTPServer(self, tab):
+ # Avoid paying for a cross-renderer navigation on the first page on legacy
+ # page cyclers which use the filesystem.
+ tab.Navigate(tab.browser.http_server.UrlOf('nonexistent.html'))
+
+ def WillNavigateToPage(self, page, tab):
+ page.script_to_evaluate_on_commit = self._page_cycler_js
+
+ def DidNavigateToPage(self, page, tab):
+ for h in self._histograms:
+ h.Start(page, tab)
+
+ def CustomizeBrowserOptions(self, options):
+ options.AppendExtraBrowserArg('--enable-stats-collection-bindings')
+ options.AppendExtraBrowserArg('--js-flags=--expose_gc')
+ options.AppendExtraBrowserArg('--no-sandbox')
+
+ # Old commandline flags used for reference builds.
+ options.AppendExtraBrowserArg('--dom-automation')
+
+ # Temporarily disable typical_25 page set on mac.
+ if sys.platform == 'darwin' and sys.argv[-1].endswith('/typical_25.json'):
+ print 'typical_25 is currently disabled on mac. Skipping test.'
+ sys.exit(0)
+
+
+ def MeasurePage(self, page, tab, results):
+ def _IsDone():
+ return bool(tab.EvaluateJavaScript('__pc_load_time'))
+ util.WaitFor(_IsDone, 60)
+
+ for h in self._histograms:
+ h.GetValue(page, tab, results)
+
+ results.Add('page_load_time', 'ms',
+ int(float(tab.EvaluateJavaScript('__pc_load_time'))),
+ chart_name='times')
+
+ def DidRunTest(self, tab, results):
+ self._memory_metric.Stop()
+ self._memory_metric.AddResults(tab, results)
+ io.IOMetric().AddSummaryResults(tab, results)
+
diff --git a/chromium/tools/perf/measurements/rasterize_and_record.py b/chromium/tools/perf/measurements/rasterize_and_record.py
new file mode 100644
index 00000000000..0cab742e4c2
--- /dev/null
+++ b/chromium/tools/perf/measurements/rasterize_and_record.py
@@ -0,0 +1,192 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import time
+
+from metrics import smoothness
+from telemetry.page import page_measurement
+
+class StatsCollector(object):
+ def __init__(self, timeline):
+ """
+ Utility class for collecting rendering stats from timeline model.
+
+ timeline -- The timeline model
+ """
+ self.timeline = timeline
+ self.total_best_rasterize_time = 0
+ self.total_best_record_time = 0
+ self.total_pixels_rasterized = 0
+ self.total_pixels_recorded = 0
+ self.trigger_event = self.FindTriggerEvent()
+ self.renderer_process = self.trigger_event.start_thread.parent
+
+ def FindTriggerEvent(self):
+ events = [s for
+ s in self.timeline.GetAllEventsOfName(
+ 'measureNextFrame')
+ if s.parent_slice == None]
+ if len(events) != 1:
+ raise LookupError, 'no measureNextFrame event found'
+ return events[0]
+
+ def FindFrameNumber(self, trigger_time):
+ start_event = None
+ for event in self.renderer_process.IterAllSlicesOfName(
+ "LayerTreeHost::UpdateLayers"):
+ if event.start > trigger_time:
+ if start_event == None:
+ start_event = event
+ elif event.start < start_event.start:
+ start_event = event
+ if start_event is None:
+ raise LookupError, \
+ 'no LayterTreeHost::UpdateLayers after measureNextFrame found'
+ return start_event.args["source_frame_number"]
+
+ def GatherRasterizeStats(self, frame_number):
+ for event in self.renderer_process.IterAllSlicesOfName(
+ "RasterWorkerPoolTaskImpl::RunRasterOnThread"):
+ if event.args["data"]["source_frame_number"] == frame_number:
+ for raster_loop_event in event.GetAllSubSlicesOfName("RasterLoop"):
+ best_rasterize_time = float("inf")
+ for raster_event in raster_loop_event.GetAllSubSlicesOfName(
+ "Picture::Raster"):
+ if "num_pixels_rasterized" in raster_event.args:
+ best_rasterize_time = min(best_rasterize_time,
+ raster_event.duration)
+ self.total_pixels_rasterized += \
+ raster_event.args["num_pixels_rasterized"]
+ if best_rasterize_time == float('inf'):
+ best_rasterize_time = 0
+ self.total_best_rasterize_time += best_rasterize_time
+
+ def GatherRecordStats(self, frame_number):
+ for event in self.renderer_process.IterAllSlicesOfName(
+ "PictureLayer::Update"):
+ if event.args["source_frame_number"] == frame_number:
+ for record_loop_event in event.GetAllSubSlicesOfName("RecordLoop"):
+ best_record_time = float('inf')
+ for record_event in record_loop_event.GetAllSubSlicesOfName(
+ "Picture::Record"):
+ best_record_time = min(best_record_time, record_event.duration)
+ self.total_pixels_recorded += (
+ record_event.args["data"]["width"] *
+ record_event.args["data"]["height"])
+ if best_record_time == float('inf'):
+ best_record_time = 0
+ self.total_best_record_time += best_record_time
+
+ def GatherRenderingStats(self):
+ trigger_time = self.trigger_event.start
+ frame_number = self.FindFrameNumber(trigger_time)
+ self.GatherRasterizeStats(frame_number)
+ self.GatherRecordStats(frame_number)
+
+def DivideIfPossibleOrZero(numerator, denominator):
+ if denominator == 0:
+ return 0
+ return numerator / denominator
+
+class RasterizeAndRecord(page_measurement.PageMeasurement):
+ def __init__(self):
+ super(RasterizeAndRecord, self).__init__('', True)
+ self._metrics = None
+
+ def AddCommandLineOptions(self, parser):
+ parser.add_option('--report-all-results', dest='report_all_results',
+ action='store_true',
+ help='Reports all data collected')
+ parser.add_option('--raster-record-repeat', dest='raster_record_repeat',
+ default=20,
+ help='Repetitions in raster and record loops.' +
+ 'Higher values reduce variance, but can cause' +
+ 'instability (timeouts, event buffer overflows, etc.).')
+ parser.add_option('--start-wait-time', dest='start_wait_time',
+ default=2,
+ help='Wait time before the benchmark is started ' +
+ '(must be long enought to load all content)')
+ parser.add_option('--stop-wait-time', dest='stop_wait_time',
+ default=5,
+ help='Wait time before measurement is taken ' +
+ '(must be long enough to render one frame)')
+
+ def CustomizeBrowserOptions(self, options):
+ options.extra_browser_args.append('--enable-gpu-benchmarking')
+ # Run each raster task N times. This allows us to report the time for the
+ # best run, effectively excluding cache effects and time when the thread is
+ # de-scheduled.
+ options.extra_browser_args.append(
+ '--slow-down-raster-scale-factor=' + str(options.raster_record_repeat))
+ # Enable impl-side-painting. Current version of benchmark only works for
+ # this mode.
+ options.extra_browser_args.append('--enable-impl-side-painting')
+ options.extra_browser_args.append('--force-compositing-mode')
+ options.extra_browser_args.append('--enable-threaded-compositing')
+
+ def MeasurePage(self, page, tab, results):
+ self._metrics = smoothness.SmoothnessMetrics(tab)
+
+ # Rasterize only what's visible.
+ tab.ExecuteJavaScript(
+ 'chrome.gpuBenchmarking.setRasterizeOnlyVisibleContent();')
+
+ # Wait until the page has loaded and come to a somewhat steady state.
+ # Needs to be adjusted for every device (~2 seconds for workstation).
+ time.sleep(float(self.options.start_wait_time))
+
+ # Render one frame before we start gathering a trace. On some pages, the
+ # first frame requested has more variance in the number of pixels
+ # rasterized.
+ tab.ExecuteJavaScript("""
+ window.__rafFired = false;
+ window.webkitRequestAnimationFrame(function() {
+ chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers();
+ window.__rafFired = true;
+ });
+ """)
+
+ tab.browser.StartTracing('webkit,benchmark', 60)
+ self._metrics.Start()
+
+ tab.ExecuteJavaScript("""
+ console.time("measureNextFrame");
+ window.__rafFired = false;
+ window.webkitRequestAnimationFrame(function() {
+ chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers();
+ window.__rafFired = true;
+ });
+ """)
+ # Wait until the frame was drawn.
+ # Needs to be adjusted for every device and for different
+ # raster_record_repeat counts.
+ # TODO(ernstm): replace by call-back.
+ time.sleep(float(self.options.stop_wait_time))
+ tab.ExecuteJavaScript('console.timeEnd("measureNextFrame")')
+
+ tab.browser.StopTracing()
+ self._metrics.Stop()
+
+ timeline = tab.browser.GetTraceResultAndReset().AsTimelineModel()
+ collector = StatsCollector(timeline)
+ collector.GatherRenderingStats()
+
+ rendering_stats = self._metrics.end_values
+
+ results.Add('best_rasterize_time', 'seconds',
+ collector.total_best_rasterize_time / 1.e3,
+ data_type='unimportant')
+ results.Add('best_record_time', 'seconds',
+ collector.total_best_record_time / 1.e3,
+ data_type='unimportant')
+ results.Add('total_pixels_rasterized', 'pixels',
+ collector.total_pixels_rasterized,
+ data_type='unimportant')
+ results.Add('total_pixels_recorded', 'pixels',
+ collector.total_pixels_recorded,
+ data_type='unimportant')
+
+ if self.options.report_all_results:
+ for k, v in rendering_stats.iteritems():
+ results.Add(k, '', v)
diff --git a/chromium/tools/perf/measurements/skpicture_printer.py b/chromium/tools/perf/measurements/skpicture_printer.py
new file mode 100644
index 00000000000..5a74453e399
--- /dev/null
+++ b/chromium/tools/perf/measurements/skpicture_printer.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.page import page_measurement
+
+
+_JS = 'chrome.gpuBenchmarking.printToSkPicture("{0}");'
+
+
+class SkpicturePrinter(page_measurement.PageMeasurement):
+ def AddCommandLineOptions(self, parser):
+ parser.add_option('-s', '--skp-outdir',
+ help='Output directory for the SKP files')
+
+ def CustomizeBrowserOptions(self, options):
+ options.extra_browser_args.extend(['--enable-gpu-benchmarking',
+ '--no-sandbox',
+ '--enable-deferred-image-decoding',
+ '--force-compositing-mode'])
+
+ def MeasurePage(self, page, tab, results):
+ skp_outdir = self.options.skp_outdir
+ if not skp_outdir:
+ raise Exception('Please specify --skp-outdir')
+ outpath = os.path.abspath(
+ os.path.join(skp_outdir,
+ page.url_as_file_safe_name))
+ # Replace win32 path separator char '\' with '\\'.
+ js = _JS.format(outpath.replace('\\', '\\\\'))
+ tab.EvaluateJavaScript(js)
+ results.Add('output_path', 'path', outpath)
diff --git a/chromium/tools/perf/measurements/smoothness.py b/chromium/tools/perf/measurements/smoothness.py
new file mode 100644
index 00000000000..4bdbe07990f
--- /dev/null
+++ b/chromium/tools/perf/measurements/smoothness.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from metrics import loading
+from metrics import smoothness
+from metrics.gpu_rendering_stats import GpuRenderingStats
+from telemetry.page import page_measurement
+
+class DidNotScrollException(page_measurement.MeasurementFailure):
+ def __init__(self):
+ super(DidNotScrollException, self).__init__('Page did not scroll')
+
+class MissingDisplayFrameRate(page_measurement.MeasurementFailure):
+ def __init__(self, name):
+ super(MissingDisplayFrameRate, self).__init__(
+ 'Missing display frame rate metrics: ' + name)
+
+class Smoothness(page_measurement.PageMeasurement):
+ def __init__(self):
+ super(Smoothness, self).__init__('smoothness')
+ self.force_enable_threaded_compositing = False
+ self.use_gpu_benchmarking_extension = True
+ self._metrics = None
+
+ def AddCommandLineOptions(self, parser):
+ parser.add_option('--report-all-results', dest='report_all_results',
+ action='store_true',
+ help='Reports all data collected, not just FPS')
+
+ def CustomizeBrowserOptions(self, options):
+ if self.use_gpu_benchmarking_extension:
+ options.extra_browser_args.append('--enable-gpu-benchmarking')
+ if self.force_enable_threaded_compositing:
+ options.extra_browser_args.append('--enable-threaded-compositing')
+
+ def CanRunForPage(self, page):
+ return hasattr(page, 'smoothness')
+
+ def WillRunAction(self, page, tab, action):
+ if tab.browser.platform.IsRawDisplayFrameRateSupported():
+ tab.browser.platform.StartRawDisplayFrameRateMeasurement()
+ self._metrics = smoothness.SmoothnessMetrics(tab)
+ if action.CanBeBound():
+ self._metrics.BindToAction(action)
+ else:
+ self._metrics.Start()
+
+ def DidRunAction(self, page, tab, action):
+ if tab.browser.platform.IsRawDisplayFrameRateSupported():
+ tab.browser.platform.StopRawDisplayFrameRateMeasurement()
+ if not action.CanBeBound():
+ self._metrics.Stop()
+
+ def MeasurePage(self, page, tab, results):
+ rendering_stats_deltas = self._metrics.deltas
+
+ if not (rendering_stats_deltas['numFramesSentToScreen'] > 0):
+ raise DidNotScrollException()
+
+ loading.LoadingMetric().AddResults(tab, results)
+
+ smoothness.CalcFirstPaintTimeResults(results, tab)
+
+ benchmark_stats = GpuRenderingStats(rendering_stats_deltas)
+ smoothness.CalcResults(benchmark_stats, results)
+
+ if self.options.report_all_results:
+ for k, v in rendering_stats_deltas.iteritems():
+ results.Add(k, '', v)
+
+ if tab.browser.platform.IsRawDisplayFrameRateSupported():
+ for r in tab.browser.platform.GetRawDisplayFrameRateMeasurements():
+ if r.value is None:
+ raise MissingDisplayFrameRate(r.name)
+ results.Add(r.name, r.unit, r.value)
diff --git a/chromium/tools/perf/measurements/startup.py b/chromium/tools/perf/measurements/startup.py
new file mode 100644
index 00000000000..5792feea2de
--- /dev/null
+++ b/chromium/tools/perf/measurements/startup.py
@@ -0,0 +1,74 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+
+from telemetry.page import page_measurement
+
+class Startup(page_measurement.PageMeasurement):
+ """Performs a measurement of Chromium's startup performance.
+
+ This test must be invoked with either --warm or --cold on the command line. A
+ cold start means none of the Chromium files are in the disk cache. A warm
+ start assumes the OS has already cached much of Chromium's content. For warm
+ tests, you should repeat the page set to ensure it's cached.
+ """
+
+ HISTOGRAMS_TO_RECORD = {
+ 'messageloop_start_time' :
+ 'Startup.BrowserMessageLoopStartTimeFromMainEntry',
+ 'window_display_time' : 'Startup.BrowserWindowDisplay',
+ 'open_tabs_time' : 'Startup.BrowserOpenTabs'}
+
+ def __init__(self):
+ super(Startup, self).__init__(needs_browser_restart_after_each_run=True)
+ self._cold = False
+
+ def AddCommandLineOptions(self, parser):
+ parser.add_option('--cold', action='store_true',
+ help='Clear the OS disk cache before performing the test')
+ parser.add_option('--warm', action='store_true',
+ help='Start up with everything already cached')
+
+ def CustomizeBrowserOptions(self, options):
+ # TODO: Once the bots start running benchmarks, enforce that either --warm
+ # or --cold is explicitly specified.
+ # assert options.warm != options.cold, \
+ # "You must specify either --warm or --cold"
+ self._cold = options.cold
+
+ if self._cold:
+ options.clear_sytem_cache_for_browser_and_profile_on_start = True
+ else:
+ self.discard_first_result = True
+
+ options.AppendExtraBrowserArg('--enable-stats-collection-bindings')
+
+ # Old commandline flags used for reference builds.
+ options.AppendExtraBrowserArg('--dom-automation')
+ options.AppendExtraBrowserArg(
+ '--reduce-security-for-dom-automation-tests')
+
+ def MeasurePage(self, page, tab, results):
+ # TODO(jeremy): Remove references to
+ # domAutomationController.getBrowserHistogram when we update the reference
+ # builds.
+ get_histogram_js = ('(window.statsCollectionController ?'
+ 'statsCollectionController :'
+ 'domAutomationController).getBrowserHistogram("%s")')
+
+ for display_name, histogram_name in self.HISTOGRAMS_TO_RECORD.iteritems():
+ result = tab.EvaluateJavaScript(get_histogram_js % histogram_name)
+ result = json.loads(result)
+ measured_time = 0
+
+ if 'sum' in result:
+ # For all the histograms logged here, there's a single entry so sum
+ # is the exact value for that entry.
+ measured_time = result['sum']
+ elif 'buckets' in result:
+ measured_time = \
+ (result['buckets'][0]['high'] + result['buckets'][0]['low']) / 2
+
+ results.Add(display_name, 'ms', measured_time)
diff --git a/chromium/tools/perf/measurements/tab_switching.py b/chromium/tools/perf/measurements/tab_switching.py
new file mode 100644
index 00000000000..d4d8e58d10a
--- /dev/null
+++ b/chromium/tools/perf/measurements/tab_switching.py
@@ -0,0 +1,64 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""The tab switching measurement.
+
+This measurement opens pages in different tabs. After all the tabs have opened,
+it cycles through each tab in sequence, and records a histogram of the time
+between when a tab was first requested to be shown, and when it was painted.
+"""
+
+from metrics import histogram_util
+from telemetry.core import util
+from telemetry.page import page_measurement
+from telemetry.page import page_runner
+
+# TODO: Revisit this test once multitab support is finalized.
+
+class TabSwitching(page_measurement.PageMeasurement):
+ def CustomizeBrowserOptions(self, options):
+ options.AppendExtraBrowserArg('--enable-stats-collection-bindings')
+ options.AppendExtraBrowserArg('--dom-automation')
+
+ def CanRunForPage(self, page):
+ return not page.page_set.pages.index(page)
+
+ def DidNavigateToPage(self, page, tab):
+ for i in xrange(1, len(page.page_set.pages)):
+ t = tab.browser.tabs.New()
+
+ page_state = page_runner.PageState()
+ page_state.PreparePage(page.page_set.pages[i], t)
+
+ def MeasurePage(self, _, tab, results):
+ """Although this is called MeasurePage, we're actually using this function
+ to cycle through each tab that was opened via DidNavigateToPage and
+ thenrecord a single histogram for the tab switching metric.
+ """
+ histogram_name = 'MPArch.RWH_TabSwitchPaintDuration'
+ histogram_type = 'getBrowserHistogram'
+ first_histogram = histogram_util.GetHistogramFromDomAutomation(
+ histogram_type, histogram_name, tab)
+ prev_histogram = first_histogram
+
+ for i in xrange(len(tab.browser.tabs)):
+ t = tab.browser.tabs[i]
+ t.Activate()
+ def _IsDone():
+ cur_histogram = histogram_util.GetHistogramFromDomAutomation(
+ histogram_type, histogram_name, tab)
+ diff_histogram = histogram_util.SubtractHistogram(
+ cur_histogram, prev_histogram)
+ return diff_histogram
+ util.WaitFor(_IsDone, 30)
+ prev_histogram = histogram_util.GetHistogramFromDomAutomation(
+ histogram_type, histogram_name, tab)
+
+ last_histogram = histogram_util.GetHistogramFromDomAutomation(
+ histogram_type, histogram_name, tab)
+ diff_histogram = histogram_util.SubtractHistogram(last_histogram,
+ first_histogram)
+
+ results.AddSummary(histogram_name, '', diff_histogram,
+ data_type='unimportant-histogram')
diff --git a/chromium/tools/perf/measurements/test_data/loading_profile.csv b/chromium/tools/perf/measurements/test_data/loading_profile.csv
new file mode 100644
index 00000000000..aac896ea0e7
--- /dev/null
+++ b/chromium/tools/perf/measurements/test_data/loading_profile.csv
@@ -0,0 +1,10 @@
+url,OT::SubstLookup::apply_string const (period),SkPaint::descriptorProc const (period),WTF::HashTable::expand (period),"WTF::HashTableAddResult WTF::HashTable<WebCore::QualifiedName::QualifiedNameImpl*, WebCore::QualifiedName::QualifiedNameImpl*, WTF::IdentityExtractor, WebCore::QualifiedNameHash, WebCore::QualifiedNameHashTraits, WebCore::Qualifie (period)",WTF::HashTableAddResult::add<WTF::Iden (period),WTF::HashTableAddResult::add<WTF::Identit (period),WTF::HashTableConstIterator::find<WTF::IdentityHashTranslator<W (period),WTF::HashTableConstIterator::find<WTF::IdentityHashTranslator<WTF: (period),WTF::IntHash::hash (period),"WTF::ListHashSetNode, WTF::HashTraits<WTF::ListHashSetNode<WebCore (period)","WTF::ListHashSetNode, WTF::HashTraits<WTF::ListHashSetNode<WebCore::R (period)",WebCore::BidiResolver::createBidiRunsForLine (period),WebCore::ElementRuleCollector::collectRuleIfMatches (period),WebCore::LayoutUnit::LayoutUnit (period),WebCore::NodeRenderingContext::parentRenderer const (period),WebCore::PODFreeListArena::Node*) (period),WebCore::PODIntervalTree::Node*) (period),WebCore::PODRedBlackTree::Node*) (period),WebCore::RenderBlock::FloatingObjects::computePlacedFloatsTree (period),WebCore::RenderBlock::LineBreaker::nextSegmentBreak (period),WebCore::RenderBlock::adjustLogicalLeftOffsetForLine const (period),WebCore::RenderBlock::computeLogicalLocationForFloat const (period),WebCore::RenderBlock::floatingObjects const (period),WebCore::RenderBlock::insertIntoFloatingObjectMaps (period),WebCore::RenderBlock::logicalLeftFloatOffsetForLine const (period),WebCore::RenderBlock::logicalRightFloatOffsetForLine const (period),WebCore::RenderBlock::lowestFloatLogicalBottom const (period),WebCore::RenderBlock::nextFloatLogicalBottomBelow const (period),WebCore::RenderBox::computeRectForRepaint const (period),WebCore::RenderBox::outlineBoundsForRepaint const (period),WebCore::RenderLayer::updateLayerPosition (period),WebCore::RenderStyle::getRoundedBorderFor const (period),WebCore::SelectorChecker::Match WebCore::SelectorChecker::match const (period),WebCore::SelectorFilter::fastRejectSelector const (period),WebCore::StyleBuilder::applyProperty (period),WebCore::minimumValueForLength (period),WebCore::rangesIntersect (period),WebCore::selectorIdentifierHash (period),_ZN12_GLOBAL__N_121do_free_with_callbackEPvPFvS0_E_constprop_42 (period),__memcpy_ssse3_back (period),base::TaskQueue::Swap (period),bool WebCore::SelectorChecker::checkOne const (period),cssyyparse (period),dom_content_loaded_time (ms),int v8::internal::Search (period),load_time (ms),operator new (period),tc_malloc (period),tcmalloc::CentralFreeList::Populate (period),v8::internal::CallIC_Miss (period),v8::internal::Code::CopyFrom (period),v8::internal::CopyDictionaryToObjectElements (period),v8::internal::DescriptorArray::Append (period),v8::internal::HEnvironmentLivenessAnalysisPhase::HEnvironmentLivenessAnalysisPhase (period),v8::internal::HeapObject::Size (period),v8::internal::RelocIterator::next (period),v8::internal::Scanner::Scan (period),v8::internal::StaticMarkingVisitor::MarkMapContents (period),void WebCore::PODIntervalTree&) const (period)
+http://oilevent.com,-,-,-,-,-,413571536,-,184348474,203099732,-,372245525,-,-,-,-,49868758788,206832196,375727286,6122064621,-,-,-,-,-,-,-,240389896,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,16595.0,-,16595.0,-,142794992,-,-,-,-,-,-,-,-,-,-,-
+http://www.muzoboss.ru,-,-,-,-,-,-,-,-,370302641,-,-,-,-,281959723,-,-,-,220563937,-,-,-,150844650,760029437,-,247939378,-,153380251,165612799,-,-,-,-,-,-,-,-,225505263,-,-,-,-,-,-,1016.0,-,4199.0,-,-,-,-,-,-,-,-,-,-,-,-,3576233162
+http://natunkantha.com,64884090,56328987,-,-,-,-,-,-,-,-,-,-,74101028,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,129853065,39592203,-,-,-,-,33537645,41371675,-,225103388,-,917.0,-,1039.0,33516277,-,-,-,-,38386948,-,-,-,-,-,-,-
+http://www.mossiella.com,-,-,-,-,349075782,-,138286105,-,198786255,378890061,-,-,-,-,-,38956515722,-,286157861,6259623904,-,-,-,-,97663664,-,-,176704041,-,-,-,-,-,-,-,-,-,-,-,100273258,-,-,-,-,13910.0,-,14380.0,-,-,-,-,-,-,-,-,-,-,-,-,-
+http://bookish.com,-,-,-,-,-,-,-,-,523148050,-,-,-,-,469200723,-,-,-,-,-,-,415781213,414507076,1026826271,-,735907577,332771610,-,-,-,-,-,-,-,320185761,-,-,422830415,-,-,-,-,-,-,3488.0,-,4610.0,-,-,-,-,-,-,-,-,-,-,-,-,7286434096
+http://mydiyclub.com,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,22779903,20635568,-,-,-,1061.0,26061116,1274.0,18160812,24966650,-,-,19849956,-,47313020,-,20318738,19461641,19668346,-,-
+http://picarisimo.es,-,-,-,-,-,-,-,-,64461270,-,-,-,-,-,-,-,-,-,-,45431297,-,-,134821145,-,-,-,-,-,241747188,45932320,50720826,66880639,-,-,-,64262492,-,-,-,-,-,-,-,134.0,-,1427.0,52066645,-,-,-,-,-,-,-,-,-,-,-,159678148
+http://chinaapache.com,-,-,5860490,14652832,-,-,-,-,-,-,-,7454931,-,-,16602032,-,-,-,-,5245336,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,7387582,-,-,50.0,-,61.0,-,-,5464891,9396782,-,-,-,5303760,-,23515886,-,-,-
+http://indoritel.com,-,-,-,-,-,-,-,-,-,-,-,-,349191621,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,-,899417137,279502507,-,-,243204300,326516135,275771420,-,-,357085022,2073.0,-,7000.0,208980001,-,-,-,-,-,235552426,-,-,-,-,262461381,-
diff --git a/chromium/tools/perf/measurements/test_data/loading_timeline.csv b/chromium/tools/perf/measurements/test_data/loading_timeline.csv
new file mode 100644
index 00000000000..c62f2a2fb7d
--- /dev/null
+++ b/chromium/tools/perf/measurements/test_data/loading_timeline.csv
@@ -0,0 +1,10 @@
+CompositeLayers_avg (ms),ResizeImage (ms),Layout (ms),EvaluateScript (ms),ResourceReceivedData (ms),FireAnimationFrame_max (ms),EvaluateScript_avg (ms),Paint_max (ms),ResourceReceiveResponse (ms),ResizeImage_avg (ms),TimerFire_max (ms),Program_max (ms),XHRReadyStateChange (ms),ResourceReceivedData_avg (ms),DecodeImage_avg (ms),ResourceReceiveResponse_avg (ms),ParseHTML_avg (ms),Layout_avg (ms),XHRLoad_avg (ms),EventDispatch (ms),FireAnimationFrame_avg (ms),FunctionCall (ms),FireAnimationFrame (ms),RecalculateStyles_max (ms),ParseHTML_max (ms),PaintSetup_max (ms),dom_content_loaded_time (ms),CompositeLayers_max (ms),DecodeImage (ms),FunctionCall_avg (ms),FunctionCall_max (ms),ScrollLayer (ms),GCEvent_avg (ms),TimerFire_avg (ms),PaintSetup (ms),Layout_max (ms),Paint (ms),Program (ms),XHRLoad_max (ms),load_time (ms),RecalculateStyles (ms),ResourceReceiveResponse_max (ms),EventDispatch_max (ms),ScrollLayer_max (ms),EventDispatch_avg (ms),XHRReadyStateChange_avg (ms),RecalculateStyles_avg (ms),ResourceReceivedData_max (ms),GCEvent (ms),url,Paint_avg (ms),GCEvent_max (ms),XHRLoad (ms),PaintSetup_avg (ms),Program_avg (ms),ScrollLayer_avg (ms),DecodeImage_max (ms),CompositeLayers (ms),ParseHTML (ms),TimerFire (ms),ResizeImage_max (ms),XHRReadyStateChange_max (ms),EvaluateScript_max (ms)
+0.0,9.67211914062,74.990234375,102.824462891,20.4689941406,0.0,6.42652893066,8.82690429688,0.369873046875,1.93442382812,0.043212890625,2.44506835938,0.0,0.165072533392,1.03696076766,0.00672496448864,0.448876953125,2.88423978365,0.0,1.87133789062,0.0,16.7358398438,0.0,5.55297851562,8.67944335938,0.0,343.0,0.0,23.8500976562,0.278930664062,3.76123046875,0.0,1.07039388021,0.0315755208333,0.0,61.8430175781,52.1069335938,50.3095703125,0.0,355.0,13.6887207031,0.010986328125,0.18896484375,0.0,0.0693088107639,0.0,0.80521886489,13.45703125,3.21118164062,http://joniec.pl,3.25668334961,1.6279296875,0.0,0.0,0.0898385184152,0.0,9.787109375,0.0,15.7106933594,0.189453125,3.708984375,0.0,32.9047851562
+0.0,0.0,60.2717285156,86.1184082031,16.7585449219,0.0,7.82894620028,5.44482421875,0.28076171875,0.0,0.2900390625,6.43408203125,0.0,0.138500371255,0.518965871711,0.00501360212054,0.455252075195,1.33937174479,0.0,1.1005859375,0.0,104.036132812,0.0,10.3190917969,25.0598144531,0.0,282.0,0.0,9.8603515625,0.444598858173,55.0568847656,0.0,1.07751464844,0.0307851938101,0.0,32.0119628906,58.6887207031,60.5893554688,0.0,407.0,50.4760742188,0.010986328125,0.10205078125,0.0,0.0524088541667,0.0,0.327766715706,12.7951660156,4.31005859375,http://horecastyle.nl,2.0960257394,1.4130859375,0.0,0.0,0.0694832058128,0.0,3.34594726562,0.0,36.4201660156,6.4033203125,0.0,0.0,59.2209472656
+0.0,0.098876953125,94.2145996094,178.46484375,37.2844238281,0.0,6.60980902778,13.0551757812,0.159912109375,0.098876953125,0.1669921875,7.7001953125,0.0,0.621407063802,0.135064019097,0.00695270040761,0.482793280419,2.47933156867,0.0,0.641845703125,0.0,133.328125,0.0,6.75,28.1760253906,0.0,233.0,0.0,1.21557617188,7.40711805556,63.5759277344,0.0,1.86834716797,0.06396484375,0.0,59.6840820312,88.4216308594,42.271484375,0.0,542.0,23.703125,0.010009765625,0.27099609375,0.0,0.106974283854,0.0,0.464767156863,13.5078125,14.9467773438,http://aionarabic.net,2.76317596436,5.05615234375,0.0,0.0,0.112424160572,0.0,0.552001953125,0.0,45.3825683594,0.31982421875,0.098876953125,0.0,45.9221191406
+3.92171223958,9.00244140625,143.793945312,89.5949707031,18.7126464844,0.0,7.46624755859,5.33837890625,0.200927734375,4.50122070312,0.053955078125,10.9738769531,0.239013671875,0.283524946733,1.08168945313,0.00590963924632,1.58981323242,5.7517578125,0.0,0.306884765625,0.0,11.0261230469,0.0,121.806884766,15.7854003906,2.02099609375,129.0,10.1799316406,5.40844726562,1.22512478299,4.64501953125,0.0,1.08093261719,0.0463053385417,5.3564453125,93.5776367188,34.6059570312,53.7485351562,0.0,393.0,167.385253906,0.01611328125,0.23974609375,0.0,0.153442382812,0.0796712239583,5.57950846354,13.1740722656,2.16186523438,http://pennystockmaster.net,1.28170211227,1.14892578125,0.0,0.669555664062,0.146853921192,0.0,3.50830078125,11.7651367188,25.4370117188,0.138916015625,8.05126953125,0.179931640625,35.9499511719
+0.0,0.0,114.902099609,37.3405761719,44.8813476562,0.0,0.122028026705,5.52856445312,1.86303710938,0.0,0.14794921875,3.10595703125,0.0,0.0517066217238,0.453446237664,0.00602924630866,6.24307411595,8.83862304688,0.0,0.0,0.0,0.44287109375,0.0,21.9528808594,23.7131347656,0.0,273.0,0.0,8.61547851562,0.44287109375,0.44287109375,0.0,0.0,0.0164871976225,0.0,43.2739257812,23.775390625,171.98828125,0.0,1003.0,61.640625,0.01416015625,0.0,0.0,0.0,0.0,0.200131899351,13.0100097656,0.0,http://asiator.com,3.396484375,0.0,0.0,0.0,0.0484064962708,0.0,2.06396484375,0.0,118.618408203,4.96264648438,0.0,0.0,5.13623046875
+0.0,0.0,36.2736816406,0.5048828125,15.6623535156,0.0,0.5048828125,6.08471679688,0.06005859375,0.0,0.0,2.92529296875,0.0,0.489448547363,0.717041015625,0.0050048828125,2.22094726562,4.53421020508,0.0,0.0,0.0,0.435791015625,0.0,1.994140625,4.552734375,0.0,59.0,0.0,5.01928710938,0.435791015625,0.435791015625,0.0,0.0,0.0,0.0,33.1640625,17.9816894531,15.80859375,0.0,104.0,3.080078125,0.009033203125,0.0,0.0,0.0,0.0,0.77001953125,13.4809570312,0.0,http://plnunn.com,2.99694824219,0.0,0.0,0.0,0.102653206169,0.0,4.1279296875,0.0,8.8837890625,0.0,0.0,0.0,0.5048828125
+0.0,0.0,68.8752441406,226.928955078,62.7219238281,0.0,2.46661907694,6.42333984375,0.64697265625,0.0,0.311767578125,5.572265625,0.0,0.56506237683,0.337795681424,0.00735196200284,0.623560935074,0.782673228871,0.0,8.18090820312,0.0,185.92578125,0.0,6.35180664062,9.87109375,0.0,361.0,0.0,12.1606445312,0.628127639358,28.7446289062,0.0,9.53627522786,0.0359129802489,0.0,22.2741699219,28.0166015625,74.6743164062,0.0,840.0,26.4306640625,0.014892578125,0.867919921875,0.0,0.215287057977,0.0,0.191526551178,13.8371582031,114.435302734,http://triviacafe.com,0.311295572917,19.8920898438,0.0,0.0,0.0904047414119,0.0,2.81396484375,0.0,100.393310547,8.2958984375,0.0,0.0,42.8920898438
+0.0,0.0,4.33374023438,0.0,42.6137695312,0.0,0.0,2.7763671875,0.008056640625,0.0,0.0,3.53735351562,0.0,42.6137695312,0.0,0.008056640625,0.311889648438,0.333364633413,0.0,0.0,0.0,0.455810546875,0.0,0.2578125,0.560791015625,0.0,80.0,0.0,0.0,0.455810546875,0.455810546875,0.0,0.0,0.0,0.0,2.85498046875,15.8295898438,13.2143554688,0.0,80.0,0.490966796875,0.008056640625,0.0,0.0,0.0,0.0,0.163655598958,42.6137695312,0.0,http://mmm.co.uk,1.75884331597,0.0,0.0,0.0,0.167270322389,0.0,0.0,0.0,0.623779296875,0.0,0.0,0.0,0.0
+0.0,0.0,11.8352050781,0.296875,13.5771484375,0.0,0.296875,3.51196289062,0.02880859375,0.0,0.0,3.08984375,0.0,2.7154296875,0.385986328125,0.00960286458333,1.16162109375,1.07592773438,0.0,0.0,0.0,0.43798828125,0.0,0.44580078125,2.8779296875,0.0,55.0,0.0,0.77197265625,0.43798828125,0.43798828125,0.0,0.0,0.0,0.0,10.3369140625,16.1049804688,12.9384765625,0.0,70.0,0.861572265625,0.014892578125,0.0,0.0,0.0,0.0,0.215393066406,13.4321289062,0.0,http://wootw.com,2.30071149554,0.0,0.0,0.0,0.143760850694,0.0,0.640869140625,0.0,3.48486328125,0.0,0.0,0.0,0.296875
diff --git a/chromium/tools/perf/metrics/__init__.py b/chromium/tools/perf/metrics/__init__.py
new file mode 100644
index 00000000000..d46cf7ef23e
--- /dev/null
+++ b/chromium/tools/perf/metrics/__init__.py
@@ -0,0 +1,41 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class Metric(object):
+ """Base class for all the metrics that are used by telemetry measurements.
+
+ The Metric class represents a way of measuring something. Metrics are
+ helper classes used by PageMeasurements. Each PageMeasurement may use
+ multiple metrics; each metric should be focussed on collecting data
+ about one thing.
+ """
+
+ def CustomizeBrowserOptions(self, options):
+ """Add browser options that are required by this metric.
+
+ Some metrics do not have any special browser options that need
+ to be added, and they do not need to override this method; by
+ default, no browser options are added.
+
+ To add options here, call options.AppendExtraBrowserArg(arg).
+ """
+ pass
+
+ def Start(self, page, tab):
+ """Start collecting data for this metric."""
+ raise NotImplementedError()
+
+ def Stop(self, page, tab):
+ """Stop collecting data for this metric (if applicable)."""
+ raise NotImplementedError()
+
+ def AddResults(self, tab, results):
+ """Add the data collected into the results object for a measurement.
+
+ Metrics may implement AddResults to provide a common way to add results
+ to the PageMeasurementResults in PageMeasurement.AddMeasurement --
+ results should be added with results.Add(trace_name, unit, value).
+ """
+ raise NotImplementedError()
+
diff --git a/chromium/tools/perf/metrics/gpu_rendering_stats.py b/chromium/tools/perf/metrics/gpu_rendering_stats.py
new file mode 100644
index 00000000000..9af9f9e1bf6
--- /dev/null
+++ b/chromium/tools/perf/metrics/gpu_rendering_stats.py
@@ -0,0 +1,47 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class GpuRenderingStats(object):
+ def __init__(self, rendering_stats_deltas):
+ rs = rendering_stats_deltas
+
+ # Scroll Stats
+ self.total_time = rs.get('totalTimeInSeconds', 0)
+ self.screen_frame_count = rs.get('numFramesSentToScreen', 0)
+ self.dropped_frame_count = rs.get('droppedFrameCount', 0)
+ self.impl_thread_scroll_count = rs.get('numImplThreadScrolls', 0)
+ self.main_thread_scroll_count = rs.get('numMainThreadScrolls', 0)
+ self.drawn_layers_count = rs.get('numLayersDrawn', 0)
+ self.missing_tile_count = rs.get('numMissingTiles', 0)
+
+ # Texture Upload Stats
+ self.texture_upload_count = rs.get('textureUploadCount', 0)
+ self.texture_upload_time = rs.get('totalTextureUploadTimeInSeconds', 0)
+ self.commit_count = rs.get('totalCommitCount', 0)
+ self.commit_time = rs.get('totalCommitTimeInSeconds', 0)
+
+ # Image Decoding Stats
+ self.deferred_image_decode_count = rs.get(
+ 'totalDeferredImageDecodeCount', 0)
+ self.deferred_image_decode_time = rs.get(
+ 'totalDeferredImageDecodeTimeInSeconds', 0)
+ self.deferred_image_cache_hits = rs.get(
+ 'totalDeferredImageCacheHitCount', 0)
+ self.image_gathering_count = rs.get('totalImageGatheringCount', 0)
+ self.image_gathering_time = rs.get('totalImageGatheringTimeInSeconds', 0)
+
+ # Tile Analysis Stats
+ self.tile_analysis_count = rs.get('totalTilesAnalyzed', 0)
+ self.tile_analysis_time = rs.get('totalTileAnalysisTimeInSeconds', 0)
+ self.solid_color_tile_analysis_count = rs.get('solidColorTilesAnalyzed', 0)
+
+ # Latency Stats
+ self.input_event_count = rs.get('inputEventCount', 0)
+ self.input_event_latency = rs.get('totalInputLatency', 0)
+ self.touch_ui_count = rs.get('touchUICount', 0)
+ self.touch_ui_latency = rs.get('totalTouchUILatency', 0)
+ self.touch_acked_count = rs.get('touchAckedCount', 0)
+ self.touch_acked_latency = rs.get('totalTouchAckedLatency', 0)
+ self.scroll_update_count = rs.get('scrollUpdateCount', 0)
+ self.scroll_update_latency = rs.get('totalScrollUpdateLatency', 0)
diff --git a/chromium/tools/perf/metrics/histogram.py b/chromium/tools/perf/metrics/histogram.py
new file mode 100644
index 00000000000..147ae966321
--- /dev/null
+++ b/chromium/tools/perf/metrics/histogram.py
@@ -0,0 +1,40 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from metrics import histogram_util
+
+BROWSER_HISTOGRAM = 'browser_histogram'
+RENDERER_HISTOGRAM = 'renderer_histogram'
+
+class HistogramMetric(object):
+ def __init__(self, histogram, histogram_type):
+ self.name = histogram['name']
+ self.units = histogram['units']
+ self.histogram_type = histogram_type
+ self._start_values = dict()
+
+ def Start(self, page, tab):
+ """Get the starting value for the histogram. This value will then be
+ subtracted from the actual measurement."""
+ data = self._GetHistogramFromDomAutomation(tab)
+ if data:
+ self._start_values[page.url + self.name] = data
+
+ def GetValue(self, page, tab, results):
+ data = self._GetHistogramFromDomAutomation(tab)
+ if not data:
+ return
+ new_histogram = histogram_util.SubtractHistogram(
+ data, self._start_values[page.url + self.name])
+ results.Add(self.name, self.units, new_histogram,
+ data_type='unimportant-histogram')
+
+ @property
+ def histogram_function(self):
+ if self.histogram_type == BROWSER_HISTOGRAM:
+ return 'getBrowserHistogram'
+ return 'getHistogram'
+
+ def _GetHistogramFromDomAutomation(self, tab):
+ return histogram_util.GetHistogramFromDomAutomation(
+ self.histogram_function, self.name, tab)
diff --git a/chromium/tools/perf/metrics/histogram_util.py b/chromium/tools/perf/metrics/histogram_util.py
new file mode 100644
index 00000000000..5b72f5e83eb
--- /dev/null
+++ b/chromium/tools/perf/metrics/histogram_util.py
@@ -0,0 +1,50 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import logging
+
+def SubtractHistogram(histogram_json, start_histogram_json):
+ """Subtracts a previous histogram from a histogram. Both parameters are json
+ serializations of histograms."""
+ start_histogram = json.loads(start_histogram_json)
+ # It's ok if the start histogram is empty (we had no data, maybe even no
+ # histogram at all, at the start of the test).
+ if 'buckets' not in start_histogram:
+ return histogram_json
+
+ histogram = json.loads(histogram_json)
+ if ('pid' in start_histogram and 'pid' in histogram
+ and start_histogram['pid'] != histogram['pid']):
+ raise Exception(
+ 'Trying to compare histograms from different processes (%d and %d)'
+ % (start_histogram['pid'], histogram['pid']))
+
+ start_histogram_buckets = dict()
+ for b in start_histogram['buckets']:
+ start_histogram_buckets[b['low']] = b['count']
+
+ new_buckets = []
+ for b in histogram['buckets']:
+ new_bucket = b
+ low = b['low']
+ if low in start_histogram_buckets:
+ new_bucket['count'] = b['count'] - start_histogram_buckets[low]
+ if new_bucket['count'] < 0:
+ logging.error('Histogram subtraction error, starting histogram most '
+ 'probably invalid.')
+ if new_bucket['count']:
+ new_buckets.append(new_bucket)
+ histogram['buckets'] = new_buckets
+ histogram['count'] -= start_histogram['count']
+
+ return json.dumps(histogram)
+
+def GetHistogramFromDomAutomation(function, name, tab):
+ # TODO(jeremy): Remove references to
+ # domAutomationController when we update the reference builds.
+ js = ('(window.statsCollectionController ? '
+ 'statsCollectionController : '
+ 'domAutomationController).%s("%s")' %
+ (function, name))
+ return tab.EvaluateJavaScript(js)
diff --git a/chromium/tools/perf/metrics/histogram_util_unittest.py b/chromium/tools/perf/metrics/histogram_util_unittest.py
new file mode 100644
index 00000000000..7db5558fb1a
--- /dev/null
+++ b/chromium/tools/perf/metrics/histogram_util_unittest.py
@@ -0,0 +1,27 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import unittest
+
+from metrics import histogram_util
+
+class TestHistogram(unittest.TestCase):
+ def testSubtractHistogram(self):
+ baseline_histogram = """{"count": 3, "buckets": [
+{"low": 1, "high": 2, "count": 1},
+{"low": 2, "high": 3, "count": 2}]}"""
+
+ histogram = """{"count": 14, "buckets": [
+{"low": 1, "high": 2, "count": 1},
+{"low": 2, "high": 3, "count": 3},
+{"low": 3, "high": 4, "count": 10}]}"""
+
+ new_histogram = json.loads(
+ histogram_util.SubtractHistogram(histogram, baseline_histogram))
+ new_buckets = dict()
+ for b in new_histogram['buckets']:
+ new_buckets[b['low']] = b['count']
+ self.assertFalse(1 in new_buckets)
+ self.assertEquals(1, new_buckets[2])
+ self.assertEquals(10, new_buckets[3])
diff --git a/chromium/tools/perf/metrics/io.py b/chromium/tools/perf/metrics/io.py
new file mode 100644
index 00000000000..29d186405ae
--- /dev/null
+++ b/chromium/tools/perf/metrics/io.py
@@ -0,0 +1,57 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from metrics import Metric
+
+class IOMetric(Metric):
+ """IO-related metrics, obtained via telemetry.core.Browser."""
+
+ def Start(self, page, tab):
+ raise NotImplementedError()
+
+ def Stop(self, page, tab):
+ raise NotImplementedError()
+
+ def AddResults(self, tab, results):
+ # This metric currently only returns summary results, not per-page results.
+ raise NotImplementedError()
+
+ def AddSummaryResults(self, tab, results):
+ """Add summary results to the results object."""
+ io_stats = tab.browser.io_stats
+ if not io_stats['Browser']:
+ return
+
+ def AddSummariesForProcessType(process_type_io, process_type_trace):
+ """For a given process type, add all relevant summary results.
+
+ Args:
+ process_type_io: Type of process (eg Browser or Renderer).
+ process_type_trace: String to be added to the trace name in the results.
+ """
+ if 'ReadOperationCount' in io_stats[process_type_io]:
+ results.AddSummary('read_operations_' + process_type_trace, 'count',
+ io_stats[process_type_io]
+ ['ReadOperationCount'],
+ data_type='unimportant')
+ if 'WriteOperationCount' in io_stats[process_type_io]:
+ results.AddSummary('write_operations_' + process_type_trace, 'count',
+ io_stats[process_type_io]
+ ['WriteOperationCount'],
+ data_type='unimportant')
+ if 'ReadTransferCount' in io_stats[process_type_io]:
+ results.AddSummary('read_bytes_' + process_type_trace, 'kb',
+ io_stats[process_type_io]
+ ['ReadTransferCount'] / 1024,
+ data_type='unimportant')
+ if 'WriteTransferCount' in io_stats[process_type_io]:
+ results.AddSummary('write_bytes_' + process_type_trace, 'kb',
+ io_stats[process_type_io]
+ ['WriteTransferCount'] / 1024,
+ data_type='unimportant')
+
+ AddSummariesForProcessType('Browser', 'browser')
+ AddSummariesForProcessType('Renderer', 'renderer')
+ AddSummariesForProcessType('Gpu', 'gpu')
+
diff --git a/chromium/tools/perf/metrics/loading.py b/chromium/tools/perf/metrics/loading.py
new file mode 100644
index 00000000000..c1d4360f31e
--- /dev/null
+++ b/chromium/tools/perf/metrics/loading.py
@@ -0,0 +1,26 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from metrics import Metric
+
+class LoadingMetric(Metric):
+ """A metric for page loading time based entirely on window.performance"""
+
+ def Start(self, page, tab):
+ raise NotImplementedError()
+
+ def Stop(self, page, tab):
+ raise NotImplementedError()
+
+ def AddResults(self, tab, results):
+ load_timings = tab.EvaluateJavaScript('window.performance.timing')
+ load_time_ms = (
+ float(load_timings['loadEventStart']) -
+ load_timings['navigationStart'])
+ dom_content_loaded_time_ms = (
+ float(load_timings['domContentLoadedEventStart']) -
+ load_timings['navigationStart'])
+ results.Add('load_time', 'ms', load_time_ms)
+ results.Add('dom_content_loaded_time', 'ms',
+ dom_content_loaded_time_ms)
diff --git a/chromium/tools/perf/metrics/media.js b/chromium/tools/perf/metrics/media.js
new file mode 100644
index 00000000000..7cef7cd0c74
--- /dev/null
+++ b/chromium/tools/perf/metrics/media.js
@@ -0,0 +1,176 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains common utilities to find video/audio elements on a page
+// and collect metrics for each.
+
+(function() {
+ // MediaMetric class responsible for collecting metrics on a media element.
+ // It attaches required event listeners in order to collect different metrics.
+ function MediaMetricBase(element) {
+ checkElementIsNotBound(element);
+ this.metrics = {};
+ this.id = '';
+ this.element = element;
+ }
+
+ MediaMetricBase.prototype.getMetrics = function() {
+ return this.metrics;
+ };
+
+ MediaMetricBase.prototype.getSummary = function() {
+ return {
+ 'id': this.id,
+ 'metrics': this.getMetrics()
+ };
+ };
+
+ function HTMLMediaMetric(element) {
+ MediaMetricBase.prototype.constructor.call(this, element);
+ // Set the basic event handlers for HTML5 media element.
+ var metric = this;
+ function onVideoLoad(event) {
+ // If a 'Play' action is performed, then playback_timer != undefined.
+ if (metric.playbackTimer == undefined)
+ metric.playbackTimer = new Timer();
+ }
+ // For the cases where autoplay=true, and without a 'play' action, we want
+ // to start playbackTimer at 'play' or 'loadedmetadata' events.
+ this.element.addEventListener('play', onVideoLoad);
+ this.element.addEventListener('loadedmetadata', onVideoLoad);
+ this.element.addEventListener('playing', function(e) {
+ metric.onPlaying(e);
+ });
+ this.element.addEventListener('ended', function(e) {
+ metric.onEnded(e);
+ });
+ this.setID();
+
+ // Listen to when a Telemetry actions gets called.
+ this.element.addEventListener('willPlay', function (e) {
+ metric.onWillPlay(e);
+ }, false);
+ this.element.addEventListener('willSeek', function (e) {
+ metric.onWillSeek(e);
+ }, false);
+ }
+
+ HTMLMediaMetric.prototype = new MediaMetricBase();
+ HTMLMediaMetric.prototype.constructor = HTMLMediaMetric;
+
+ HTMLMediaMetric.prototype.setID = function() {
+ if (this.element.src)
+ this.id = this.element.src.substring(this.element.src.lastIndexOf("/")+1);
+ else if (this.element.id)
+ this.id = this.element.id;
+ else
+ this.id = 'media_' + window.__globalCounter++;
+ };
+
+ HTMLMediaMetric.prototype.onWillPlay = function(e) {
+ this.playbackTimer = new Timer();
+ };
+
+ HTMLMediaMetric.prototype.onWillSeek = function(e) {
+ var seekLabel = '';
+ if (e.seekLabel)
+ seekLabel = '_' + e.seekLabel;
+ var metric = this;
+ var onSeeked = function(e) {
+ metric.appendMetric('seek' + seekLabel, metric.seekTimer.stop())
+ e.target.removeEventListener('seeked', onSeeked);
+ };
+ this.seekTimer = new Timer();
+ this.element.addEventListener('seeked', onSeeked);
+ };
+
+ HTMLMediaMetric.prototype.appendMetric = function(metric, value) {
+ if (!this.metrics[metric])
+ this.metrics[metric] = [];
+ this.metrics[metric].push(value);
+ }
+
+ HTMLMediaMetric.prototype.onPlaying = function(event) {
+ // Playing event can fire more than once if seeking.
+ if (!this.metrics['time_to_play'])
+ this.metrics['time_to_play'] = this.playbackTimer.stop();
+ };
+
+ HTMLMediaMetric.prototype.onEnded = function(event) {
+ this.metrics['playback_time'] = this.playbackTimer.stop();
+ };
+
+ HTMLMediaMetric.prototype.getMetrics = function() {
+ this.metrics['decoded_frame_count'] = this.element.webkitDecodedFrameCount;
+ this.metrics['dropped_frame_count'] = this.element.webkitDroppedFrameCount;
+ this.metrics['decoded_video_bytes'] =
+ this.element.webkitVideoDecodedByteCount;
+ this.metrics['decoded_audio_bytes'] =
+ this.element.webkitAudioDecodedByteCount;
+ return this.metrics;
+ };
+
+ function MediaMetric(element) {
+ if (element instanceof HTMLMediaElement)
+ return new HTMLMediaMetric(element);
+ throw new Error('Unrecognized media element type.');
+ }
+
+ function Timer() {
+ this.start_ = 0;
+ this.start();
+ }
+
+ Timer.prototype = {
+ start: function() {
+ this.start_ = getCurrentTime();
+ },
+
+ stop: function() {
+ // Return delta time since start in secs.
+ return ((getCurrentTime() - this.start_) / 1000).toFixed(3);
+ }
+ };
+
+ function checkElementIsNotBound(element) {
+ if (!element)
+ return;
+ for (var i = 0; i < window.__mediaMetrics.length; i++) {
+ if (window.__mediaMetrics[i].element == element)
+ throw new Error('Can not create MediaMetric for same element twice.');
+ }
+ }
+
+ function createMediaMetricsForDocument() {
+ // Searches for all video and audio elements on the page and creates a
+ // corresponding media metric instance for each.
+ var mediaElements = document.querySelectorAll('video, audio');
+ for (var i = 0; i < mediaElements.length; i++)
+ window.__mediaMetrics.push(new MediaMetric(mediaElements[i]));
+ }
+
+ function getCurrentTime() {
+ if (window.performance)
+ return (performance.now ||
+ performance.mozNow ||
+ performance.msNow ||
+ performance.oNow ||
+ performance.webkitNow).call(window.performance);
+ else
+ return Date.now();
+ }
+
+ function getAllMetrics() {
+ // Returns a summary (info + metrics) for all media metrics.
+ var metrics = [];
+ for (var i = 0; i < window.__mediaMetrics.length; i++)
+ metrics.push(window.__mediaMetrics[i].getSummary());
+ return metrics;
+ }
+
+ window.__globalCounter = 0;
+ window.__mediaMetrics = [];
+ window.__getAllMetrics = getAllMetrics;
+ window.__createMediaMetricsForDocument = createMediaMetricsForDocument;
+})();
diff --git a/chromium/tools/perf/metrics/media.py b/chromium/tools/perf/metrics/media.py
new file mode 100644
index 00000000000..282c9bd2f3d
--- /dev/null
+++ b/chromium/tools/perf/metrics/media.py
@@ -0,0 +1,68 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+
+from metrics import Metric
+
+class MediaMetric(Metric):
+ """MediaMetric class injects and calls JS responsible for recording metrics.
+
+ Default media metrics are collected for every media element in the page,
+ such as decoded_frame_count, dropped_frame_count, decoded_video_bytes, and
+ decoded_audio_bytes.
+ """
+ def __init__(self, tab):
+ super(MediaMetric, self).__init__()
+ with open(os.path.join(os.path.dirname(__file__), 'media.js')) as f:
+ js = f.read()
+ tab.ExecuteJavaScript(js)
+ self._results = None
+
+ def Start(self, page, tab):
+ """Create the media metrics for all media elements in the document."""
+ tab.ExecuteJavaScript('window.__createMediaMetricsForDocument()')
+
+ def Stop(self, page, tab):
+ self._results = tab.EvaluateJavaScript('window.__getAllMetrics()')
+
+ def AddResults(self, tab, results):
+ """Reports all recorded metrics as Telemetry perf results."""
+ assert self._results
+ for media_metric in self._results:
+ self._AddResultsForMediaElement(media_metric, results)
+
+ def _AddResultsForMediaElement(self, media_metric, results):
+ """Reports metrics for one media element.
+
+ Media metrics contain an ID identifying the media element and values:
+ media_metric = {
+ 'id': 'video_1',
+ 'metrics': {
+ 'time_to_play': 120,
+ 'decoded_bytes': 13233,
+ ...
+ }
+ }
+ """
+ def AddOneResult(metric, unit):
+ metrics = media_metric['metrics']
+ for m in metrics:
+ if m.startswith(metric):
+ special_label = m[len(metric):]
+ results.Add(trace + special_label, unit, str(metrics[m]),
+ chart_name=metric, data_type='default')
+
+ trace = media_metric['id']
+ if not trace:
+ logging.error('Metrics ID is missing in results.')
+ return
+ AddOneResult('decoded_audio_bytes', 'bytes')
+ AddOneResult('decoded_video_bytes', 'bytes')
+ AddOneResult('decoded_frame_count', 'frames')
+ AddOneResult('dropped_frame_count', 'frames')
+ AddOneResult('playback_time', 'sec')
+ AddOneResult('seek', 'sec')
+ AddOneResult('time_to_play', 'sec')
+
diff --git a/chromium/tools/perf/metrics/memory.py b/chromium/tools/perf/metrics/memory.py
new file mode 100644
index 00000000000..cbc0660e548
--- /dev/null
+++ b/chromium/tools/perf/metrics/memory.py
@@ -0,0 +1,79 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import sys
+
+from metrics import Metric
+
+class MemoryMetric(Metric):
+ """MemoryMetric gathers memory statistics from the browser object."""
+
+ def __init__(self, browser):
+ super(MemoryMetric, self).__init__()
+ self._browser = browser
+ self._memory_stats = None
+ self._start_commit_charge = None
+
+ def Start(self, page=None, tab=None):
+ """Record the initial value of 'SystemCommitCharge'."""
+ self._start_commit_charge = self._browser.memory_stats['SystemCommitCharge']
+
+ def Stop(self, page=None, tab=None):
+ """Fetch the browser memory stats."""
+ assert self._start_commit_charge, 'Must call Start() first'
+ self._memory_stats = self._browser.memory_stats
+
+ def AddResults(self, tab, results):
+ """Add summary results to the results object."""
+ assert self._memory_stats, 'Must call Stop() first'
+ if not self._memory_stats['Browser']:
+ return
+
+ metric = 'resident_set_size'
+ if sys.platform == 'win32':
+ metric = 'working_set'
+
+ def AddSummariesForProcessTypes(process_types_memory, process_type_trace):
+ """Add all summaries to the results for a given set of process types.
+
+ Args:
+ process_types_memory: A list of process types, e.g. Browser, 'Renderer'
+ process_type_trace: The name of this set of process types in the output
+ """
+ def AddSummary(value_name_memory, value_name_trace):
+ """Add a summary to the results for a given statistic.
+
+ Args:
+ value_name_memory: Name of some statistic, e.g. VM, WorkingSetSize
+ value_name_trace: Name of this statistic to be used in the output
+ """
+ if len(process_types_memory) > 1 and value_name_memory.endswith('Peak'):
+ return
+ values = []
+ for process_type_memory in process_types_memory:
+ stats = self._memory_stats[process_type_memory]
+ if value_name_memory in stats:
+ values.append(stats[value_name_memory])
+ if values:
+ results.AddSummary(value_name_trace + process_type_trace,
+ 'bytes', sum(values), data_type='unimportant')
+
+ AddSummary('VM', 'vm_final_size_')
+ AddSummary('WorkingSetSize', 'vm_%s_final_size_' % metric)
+ AddSummary('PrivateDirty', 'vm_private_dirty_final_')
+ AddSummary('ProportionalSetSize', 'vm_proportional_set_size_final_')
+ AddSummary('VMPeak', 'vm_peak_size_')
+ AddSummary('WorkingSetSizePeak', '%s_peak_size_' % metric)
+
+ AddSummariesForProcessTypes(['Browser'], 'browser')
+ AddSummariesForProcessTypes(['Renderer'], 'renderer')
+ AddSummariesForProcessTypes(['Gpu'], 'gpu')
+ AddSummariesForProcessTypes(['Browser', 'Renderer', 'Gpu'], 'total')
+
+ end_commit_charge = self._memory_stats['SystemCommitCharge']
+ commit_charge_difference = end_commit_charge - self._start_commit_charge
+ results.AddSummary('commit_charge', 'kb', commit_charge_difference,
+ data_type='unimportant')
+ results.AddSummary('processes', 'count', self._memory_stats['ProcessCount'],
+ data_type='unimportant')
+
diff --git a/chromium/tools/perf/metrics/smoothness.js b/chromium/tools/perf/metrics/smoothness.js
new file mode 100644
index 00000000000..833ac064298
--- /dev/null
+++ b/chromium/tools/perf/metrics/smoothness.js
@@ -0,0 +1,161 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * @fileoverview This file provides the RenderingStats object, used
+ * to characterize rendering smoothness.
+ */
+(function() {
+ var getTimeMs = (function() {
+ if (window.performance)
+ return (performance.now ||
+ performance.mozNow ||
+ performance.msNow ||
+ performance.oNow ||
+ performance.webkitNow).bind(window.performance);
+ else
+ return function() { return new Date().getTime(); };
+ })();
+
+ var requestAnimationFrame = (function() {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback) {
+ window.setTimeout(callback, 1000 / 60);
+ };
+ })().bind(window);
+
+ /**
+ * Tracks rendering performance using the gpuBenchmarking.renderingStats API.
+ * @constructor
+ */
+ function GpuBenchmarkingRenderingStats() {
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.start = function() {
+ this.startTime_ = getTimeMs();
+ this.initialStats_ = this.getRenderingStats_();
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.stop = function() {
+ this.stopTime_ = getTimeMs();
+ this.finalStats_ = this.getRenderingStats_();
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.getStartValues = function() {
+ if (!this.initialStats_)
+ throw new Error('Start not called.');
+
+ if (!this.finalStats_)
+ throw new Error('Stop was not called.');
+
+ return this.initialStats_;
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.getEndValues = function() {
+ if (!this.initialStats_)
+ throw new Error('Start not called.');
+
+ if (!this.finalStats_)
+ throw new Error('Stop was not called.');
+
+ return this.finalStats_;
+ }
+
+ GpuBenchmarkingRenderingStats.prototype.getDeltas = function() {
+ if (!this.initialStats_)
+ throw new Error('Start not called.');
+
+ if (!this.finalStats_)
+ throw new Error('Stop was not called.');
+
+ var stats = {}
+ for (var key in this.finalStats_)
+ stats[key] = this.finalStats_[key] - this.initialStats_[key];
+ return stats;
+ };
+
+ GpuBenchmarkingRenderingStats.prototype.getRenderingStats_ = function() {
+ var stats = chrome.gpuBenchmarking.renderingStats();
+ stats.totalTimeInSeconds = getTimeMs() / 1000;
+ return stats;
+ };
+
+ /**
+ * Tracks rendering performance using requestAnimationFrame.
+ * @constructor
+ */
+ function RafRenderingStats() {
+ this.recording_ = false;
+ this.frameTimes_ = [];
+ }
+
+ RafRenderingStats.prototype.start = function() {
+ if (this.recording_)
+ throw new Error('Already started.');
+ this.recording_ = true;
+ requestAnimationFrame(this.recordFrameTime_.bind(this));
+ }
+
+ RafRenderingStats.prototype.stop = function() {
+ this.recording_ = false;
+ }
+
+ RafRenderingStats.prototype.getStartValues = function() {
+ var results = {};
+ results.numAnimationFrames = 0;
+ results.numFramesSentToScreen = 0;
+ results.droppedFrameCount = 0;
+ return results;
+ }
+
+ RafRenderingStats.prototype.getEndValues = function() {
+ var results = {};
+ results.numAnimationFrames = this.frameTimes_.length - 1;
+ results.numFramesSentToScreen = results.numAnimationFrames;
+ results.droppedFrameCount = this.getDroppedFrameCount_(this.frameTimes_);
+ return results;
+ }
+
+ RafRenderingStats.prototype.getDeltas = function() {
+ var endValues = this.getEndValues();
+ endValues.totalTimeInSeconds = (
+ this.frameTimes_[this.frameTimes_.length - 1] -
+ this.frameTimes_[0]) / 1000;
+ return endValues;
+ };
+
+ RafRenderingStats.prototype.recordFrameTime_ = function(timestamp) {
+ if (!this.recording_)
+ return;
+
+ this.frameTimes_.push(timestamp);
+ requestAnimationFrame(this.recordFrameTime_.bind(this));
+ };
+
+ RafRenderingStats.prototype.getDroppedFrameCount_ = function(frameTimes) {
+ var droppedFrameCount = 0;
+ for (var i = 1; i < frameTimes.length; i++) {
+ var frameTime = frameTimes[i] - frameTimes[i-1];
+ if (frameTime > 1000 / 55)
+ droppedFrameCount++;
+ }
+ return droppedFrameCount;
+ };
+
+ function RenderingStats() {
+ if (window.chrome && chrome.gpuBenchmarking &&
+ chrome.gpuBenchmarking.renderingStats) {
+ return new GpuBenchmarkingRenderingStats();
+ }
+ return new RafRenderingStats();
+ }
+
+ window.__RenderingStats = RenderingStats;
+})();
diff --git a/chromium/tools/perf/metrics/smoothness.py b/chromium/tools/perf/metrics/smoothness.py
new file mode 100644
index 00000000000..c4ec7bc57eb
--- /dev/null
+++ b/chromium/tools/perf/metrics/smoothness.py
@@ -0,0 +1,157 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.core import util
+
+class SmoothnessMetrics(object):
+ def __init__(self, tab):
+ self._tab = tab
+ with open(
+ os.path.join(os.path.dirname(__file__),
+ 'smoothness.js')) as f:
+ js = f.read()
+ tab.ExecuteJavaScript(js)
+
+ def Start(self):
+ self._tab.ExecuteJavaScript(
+ 'window.__renderingStats = new __RenderingStats();'
+ 'window.__renderingStats.start()')
+
+ def SetNeedsDisplayOnAllLayersAndStart(self):
+ self._tab.ExecuteJavaScript(
+ 'chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers();'
+ 'window.__renderingStats = new __RenderingStats();'
+ 'window.__renderingStats.start()')
+
+ def Stop(self):
+ self._tab.ExecuteJavaScript('window.__renderingStats.stop()')
+
+ def BindToAction(self, action):
+ # Make the scroll test start and stop measurement automatically.
+ self._tab.ExecuteJavaScript(
+ 'window.__renderingStats = new __RenderingStats();')
+ action.BindMeasurementJavaScript(self._tab,
+ 'window.__renderingStats.start();',
+ 'window.__renderingStats.stop();')
+
+ @property
+ def start_values(self):
+ return self._tab.EvaluateJavaScript(
+ 'window.__renderingStats.getStartValues()')
+
+ @property
+ def end_values(self):
+ return self._tab.EvaluateJavaScript(
+ 'window.__renderingStats.getEndValues()')
+
+ @property
+ def deltas(self):
+ return self._tab.EvaluateJavaScript(
+ 'window.__renderingStats.getDeltas()')
+
+def Average(numerator, denominator, scale = None, precision = None):
+ if denominator == 0:
+ return 0
+ avg = float(numerator) / float(denominator)
+ if scale:
+ avg *= scale
+ if precision:
+ avg = round(avg, precision)
+ return avg
+
+def CalcFirstPaintTimeResults(results, tab):
+ if tab.browser.is_content_shell:
+ results.Add('first_paint', 'ms', 'unsupported')
+ return
+
+ tab.ExecuteJavaScript("""
+ window.__rafFired = false;
+ window.webkitRequestAnimationFrame(function() {
+ window.__rafFired = true;
+ });
+ """)
+ util.WaitFor(lambda: tab.EvaluateJavaScript('window.__rafFired'), 60)
+
+ first_paint_secs = tab.EvaluateJavaScript(
+ 'window.chrome.loadTimes().firstPaintTime - ' +
+ 'window.chrome.loadTimes().startLoadTime')
+
+ results.Add('first_paint', 'ms', round(first_paint_secs * 1000, 1))
+
+def CalcResults(benchmark_stats, results):
+ s = benchmark_stats
+
+ # Scroll Results
+ results.Add('mean_frame_time', 'ms',
+ Average(s.total_time, s.screen_frame_count, 1000, 3))
+ results.Add('dropped_percent', '%',
+ Average(s.dropped_frame_count, s.screen_frame_count,
+ 100, 1),
+ data_type='unimportant')
+ results.Add('percent_impl_scrolled', '%',
+ Average(s.impl_thread_scroll_count,
+ s.impl_thread_scroll_count +
+ s.main_thread_scroll_count,
+ 100, 1),
+ data_type='unimportant')
+ results.Add('average_num_layers_drawn', '',
+ Average(s.drawn_layers_count, s.screen_frame_count, 1, 1),
+ data_type='unimportant')
+ results.Add('average_num_missing_tiles', '',
+ Average(s.missing_tile_count, s.screen_frame_count, 1, 1),
+ data_type='unimportant')
+
+ # Texture Upload Results
+ results.Add('average_commit_time', 'ms',
+ Average(s.commit_time, s.commit_count, 1000, 3),
+ data_type='unimportant')
+ results.Add('texture_upload_count', 'count',
+ s.texture_upload_count)
+ results.Add('total_texture_upload_time', 'seconds',
+ s.texture_upload_time)
+
+ # Image Decoding Results
+ results.Add('total_deferred_image_decode_count', 'count',
+ s.deferred_image_decode_count,
+ data_type='unimportant')
+ results.Add('total_image_cache_hit_count', 'count',
+ s.deferred_image_cache_hits,
+ data_type='unimportant')
+ results.Add('average_image_gathering_time', 'ms',
+ Average(s.image_gathering_time, s.image_gathering_count,
+ 1000, 3),
+ data_type='unimportant')
+ results.Add('total_deferred_image_decoding_time', 'seconds',
+ s.deferred_image_decode_time,
+ data_type='unimportant')
+
+ # Tile Analysis Results
+ results.Add('total_tiles_analyzed', 'count',
+ s.tile_analysis_count,
+ data_type='unimportant')
+ results.Add('solid_color_tiles_analyzed', 'count',
+ s.solid_color_tile_analysis_count,
+ data_type='unimportant')
+ results.Add('average_tile_analysis_time', 'ms',
+ Average(s.tile_analysis_time, s.tile_analysis_count,
+ 1000, 3),
+ data_type='unimportant')
+
+ # Latency Results
+ results.Add('average_latency', 'ms',
+ Average(s.input_event_latency, s.input_event_count,
+ 1000, 3),
+ data_type='unimportant')
+ results.Add('average_touch_ui_latency', 'ms',
+ Average(s.touch_ui_latency, s.touch_ui_count, 1000, 3),
+ data_type='unimportant')
+ results.Add('average_touch_acked_latency', 'ms',
+ Average(s.touch_acked_latency, s.touch_acked_count,
+ 1000, 3),
+ data_type='unimportant')
+ results.Add('average_scroll_update_latency', 'ms',
+ Average(s.scroll_update_latency, s.scroll_update_count,
+ 1000, 3),
+ data_type='unimportant')
diff --git a/chromium/tools/perf/metrics/smoothness_unittest.py b/chromium/tools/perf/metrics/smoothness_unittest.py
new file mode 100644
index 00000000000..2a42f9dd24e
--- /dev/null
+++ b/chromium/tools/perf/metrics/smoothness_unittest.py
@@ -0,0 +1,113 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from metrics import smoothness
+from metrics.gpu_rendering_stats import GpuRenderingStats
+from telemetry.page import page
+from telemetry.page.page_measurement_results import PageMeasurementResults
+
+class SmoothnessMetricsUnitTest(unittest.TestCase):
+ def testCalcResultsRealRenderStats(self):
+ mock_rendering_stats_deltas = {
+ 'totalTimeInSeconds': 1.0,
+ 'numFramesSentToScreen': 100,
+ 'droppedFrameCount': 20,
+ 'numImplThreadScrolls': 50,
+ 'numMainThreadScrolls': 50,
+ 'numLayersDrawn': 240,
+ 'numMissingTiles': 10,
+ 'textureUploadCount': 120,
+ 'totalTextureUploadTimeInSeconds': 1.2,
+ 'totalCommitCount': 130,
+ 'totalCommitTimeInSeconds': 1.3,
+ 'totalDeferredImageDecodeCount': 140,
+ 'totalDeferredImageDecodeTimeInSeconds': 1.4,
+ 'totalDeferredImageCacheHitCount': 30,
+ 'totalImageGatheringCount': 150,
+ 'totalImageGatheringTimeInSeconds': 1.5,
+ 'totalTilesAnalyzed': 160,
+ 'totalTileAnalysisTimeInSeconds': 1.6,
+ 'solidColorTilesAnalyzed': 40,
+ 'inputEventCount': 170,
+ 'totalInputLatency': 1.7,
+ 'touchUICount': 180,
+ 'totalTouchUILatency': 1.8,
+ 'touchAckedCount': 190,
+ 'totalTouchAckedLatency': 1.9,
+ 'scrollUpdateCount': 200,
+ 'totalScrollUpdateLatency': 2.0}
+ stats = GpuRenderingStats(mock_rendering_stats_deltas)
+
+ res = PageMeasurementResults()
+ res.WillMeasurePage(page.Page('http://foo.com/', None))
+ smoothness.CalcResults(stats, res)
+ res.DidMeasurePage()
+
+ # Scroll Results
+ self.assertAlmostEquals(
+ 1.0 / 100.0 * 1000.0,
+ res.page_results[0]['mean_frame_time'].value, 2)
+ self.assertAlmostEquals(
+ 20.0 / 100.0 * 100.0,
+ res.page_results[0]['dropped_percent'].value)
+ self.assertAlmostEquals(
+ 50.0 / (50.0 + 50.0) * 100.0,
+ res.page_results[0]['percent_impl_scrolled'].value)
+ self.assertAlmostEquals(
+ 240.0 / 100.0,
+ res.page_results[0]['average_num_layers_drawn'].value)
+ self.assertAlmostEquals(
+ 10.0 / 100.0,
+ res.page_results[0]['average_num_missing_tiles'].value)
+
+ # Texture Upload Results
+ self.assertAlmostEquals(
+ 1.3 / 130.0 * 1000.0,
+ res.page_results[0]['average_commit_time'].value)
+ self.assertEquals(
+ 120,
+ res.page_results[0]['texture_upload_count'].value)
+ self.assertEquals(
+ 1.2,
+ res.page_results[0]['total_texture_upload_time'].value)
+
+ # Image Decoding Results
+ self.assertEquals(
+ 140,
+ res.page_results[0]['total_deferred_image_decode_count'].value)
+ self.assertEquals(
+ 30,
+ res.page_results[0]['total_image_cache_hit_count'].value)
+ self.assertAlmostEquals(
+ 1.5 / 150.0 * 1000.0,
+ res.page_results[0]['average_image_gathering_time'].value)
+ self.assertEquals(
+ 1.4,
+ res.page_results[0]['total_deferred_image_decoding_time'].value)
+
+ # Tile Analysis Results
+ self.assertEquals(
+ 160,
+ res.page_results[0]['total_tiles_analyzed'].value)
+ self.assertEquals(
+ 40,
+ res.page_results[0]['solid_color_tiles_analyzed'].value)
+ self.assertAlmostEquals(
+ 1.6 / 160.0 * 1000.0,
+ res.page_results[0]['average_tile_analysis_time'].value)
+
+ # Latency Results
+ self.assertAlmostEquals(
+ 1.7 / 170.0 * 1000.0,
+ res.page_results[0]['average_latency'].value)
+ self.assertAlmostEquals(
+ 1.8 / 180.0 * 1000.0,
+ res.page_results[0]['average_touch_ui_latency'].value)
+ self.assertAlmostEquals(
+ 1.9 / 190.0 * 1000.0,
+ res.page_results[0]['average_touch_acked_latency'].value)
+ self.assertAlmostEquals(
+ 2.0 / 200.0 * 1000.0,
+ res.page_results[0]['average_scroll_update_latency'].value)
diff --git a/chromium/tools/perf/metrics/timeline.py b/chromium/tools/perf/metrics/timeline.py
new file mode 100644
index 00000000000..37bc3e614b2
--- /dev/null
+++ b/chromium/tools/perf/metrics/timeline.py
@@ -0,0 +1,67 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import collections
+
+TRACING_MODE = 'tracing-mode'
+TIMELINE_MODE = 'timeline-mode'
+
+class TimelineMetrics(object):
+ def __init__(self, mode):
+ assert mode in (TRACING_MODE, TIMELINE_MODE)
+ self._mode = mode
+ self._model = None
+ self._thread_for_tab = None
+
+ def Start(self, tab):
+ self._model = None
+ self._thread_for_tab = None
+
+ if self._mode == TRACING_MODE:
+ if not tab.browser.supports_tracing:
+ raise Exception('Not supported')
+ tab.browser.StartTracing()
+ else:
+ assert self._mode == TIMELINE_MODE
+ tab.StartTimelineRecording()
+
+ def Stop(self, tab):
+ if self._mode == TRACING_MODE:
+ # This creates an async trace event in the render process for tab that
+ # will allow us to find that tab during the AddTracingResultsForTab
+ # function.
+ tab.ExecuteJavaScript("""
+ console.time("__loading_measurement_was_here__");
+ console.timeEnd("__loading_measurement_was_here__");
+ """)
+
+ tab.browser.StopTracing()
+ trace_result = tab.browser.GetTraceResultAndReset()
+ self._model = trace_result.AsTimelineModel()
+ events = [s for
+ s in self._model.GetAllEventsOfName(
+ '__loading_measurement_was_here__')
+ if s.parent_slice == None]
+ assert len(events) == 1
+ self._thread_for_tab = events[0].start_thread
+ else:
+ tab.StopTimelineRecording()
+ self._model = tab.timeline_model
+ self._thread_for_tab = self._model.GetAllThreads()[0]
+
+ def AddResults(self, results):
+ assert self._model
+
+ events = self._thread_for_tab.all_slices
+
+ events_by_name = collections.defaultdict(list)
+ for e in events:
+ events_by_name[e.name].append(e)
+
+ for key, group in events_by_name.items():
+ times = [e.self_time for e in group]
+ total = sum(times)
+ biggest_jank = max(times)
+ results.Add(key, 'ms', total)
+ results.Add(key + '_max', 'ms', biggest_jank)
+ results.Add(key + '_avg', 'ms', total / len(times))
diff --git a/chromium/tools/perf/page_sets/2012Q3.json b/chromium/tools/perf/page_sets/2012Q3.json
new file mode 100644
index 00000000000..151a1d650d9
--- /dev/null
+++ b/chromium/tools/perf/page_sets/2012Q3.json
@@ -0,0 +1,228 @@
+{
+ "description": "Pages hand-picked from top-lists in Q32012.",
+ "archive_data_file": "../data/2012Q3.json",
+ "credentials_path": "../data/credentials.json",
+ "smoothness": { "action": "scroll" },
+ "reload_and_gc": [{"action": "reload", "wait_seconds": 1}, {"action": "js_collect_garbage"}],
+ "stress_memory": { "action": "reload_and_gc", "repeat": 3 },
+ "pages": [
+ { "url": "http://www.facebook.com/barackobama" },
+ { "url": "https://www.google.com/search?q=barack%20obama" },
+ { "url": "http://youtube.com" },
+ { "url": "http://yahoo.com" },
+ { "url": "http://www.baidu.com/s?wd=barack+obama" },
+ { "url": "http://en.wikipedia.org/wiki/Wikipedia" },
+ { "url": "http://qq.com" },
+ { "url": "http://www.amazon.com/Kindle-Fire-Amazon-Tablet/dp/B0051VVOB2" },
+ { "url": "http://googleblog.blogspot.com/" },
+ { "url": "http://taobao.com" },
+ { "url": "http://www.linkedin.com/in/linustorvalds" },
+ { "url": "http://yahoo.co.jp" },
+ { "url": "http://sina.com.cn" },
+ { "url": "http://msn.com" },
+ { "url": "http://yandex.ru/yandsearch?text=barack+obama" },
+ { "url": "http://translation.babylon.com/" },
+ { "url": "http://www.bing.com/search?q=barack+obama" },
+ { "url": "http://wordpress.org/news/" },
+ { "url": "http://www.ebay.com/sch/i.html?_nkw=antiques" },
+ { "url": "http://163.com" },
+ { "url": "http://www.soso.com/q?w=barack+obama" },
+ { "url": "http://www.microsoft.com/en-us/default.aspx" },
+ { "url": "http://go.mail.ru/search?mailru=1&mg=1&q=barack+obama" },
+ { "url": "http://vk.com/id118712387" },
+ { "url": "http://staff.tumblr.com/" },
+ { "url": "http://sohu.com" },
+ { "url": "http://sfbay.craigslist.org/mis/" },
+ { "url": "http://www.ask.com/web?q=barack+obama&search=&qsrc=0&o=0&l=dir" },
+ { "url": "http://www.apple.com/ipodtouch/" },
+ { "url": "http://blog.pinterest.com/" },
+ { "url": "http://pinterest.com/backdrophome/" },
+ { "url": "http://paypal.com" },
+ { "url": "http://bbc.co.uk" },
+ { "url": "http://www.avg.com/us-en/avg-premium-security" },
+ { "url": "http://googlesystem.blogspot.com/" },
+ { "url": "http://tudou.com" },
+ { "url": "http://blog.fc2.com/en/" },
+ { "url": "http://imdb.com" },
+ { "url": "http://youku.com" },
+ { "url": "http://www.flickr.com/photos/thomashawk/" },
+ { "url": "http://www.flickr.com/photos/thomashawk/sets/72157600284219965/detail/" },
+ { "url": "http://search.yahoo.com/search?ei=UTF-8&trackingType=go_search_home&p=barack+obama&fr=hsusgo1&sa.x=0&sa.y=0" },
+ { "url": "http://www.conduit.com/" },
+ { "url": "http://ifeng.com" },
+ { "url": "http://tmall.com" },
+ { "url": "http://hao123.com" },
+ { "url": "http://aol.com" },
+ { "url": "http://zedo.com" },
+ { "url": "http://search.mywebsearch.com/mywebsearch/GGmain.jhtml?searchfor=barack+obama" },
+ { "url": "http://cnn.com" },
+ { "url": "http://portal.ebay.de/deutschland-schraubt-angebote" },
+ { "url": "http://www.adobe.com/products/photoshopfamily.html?promoid=JOLIW" },
+ { "url": "http://global.rakuten.com/us/" },
+ { "url": "http://laundry.about.com/od/kidsandlaundry/f/How-Do-I-Wash-A-Backpack.htm" },
+ { "url": "http://thepiratebay.se/search/barack%20obama/0/99/0" },
+ { "url": "http://360buy.com" },
+ { "url": "http://huffingtonpost.com" },
+ { "url": "http://alibaba.com" },
+ { "url": "http://chinaz.com" },
+ { "url": "http://www.sogou.com/web?query=barack+obama" },
+ { "url": "http://www.amazon.de/gp/product/B0051QVF7A/ref=amb_link_170625867_1/275-4711375-4099801?ie=UTF8&nav_sdd=aps&pf_rd_m=A3JWKAKR8XB7XF&pf_rd_s=center-1&pf_rd_r=1C0XDBPB12WHDM63V11R&pf_rd_t=101&pf_rd_p=320475427&pf_rd_i=301128" },
+ { "url": "http://google.pl" },
+ { "url": "http://mediafire.com" },
+ { "url": "http://espn.go.com" },
+ { "url": "http://uol.com.br" },
+ { "url": "http://www.godaddy.com/products/secure-hosting.aspx?ci=72738" },
+ { "url": "http://imgur.com/gallery/b90ZE" },
+ { "url": "http://home.alipay.com/bank/paymentKJ.htm" },
+ { "url": "http://amazon.co.jp" },
+ { "url": "http://stackoverflow.com/questions/11227809/why-is-processing-a-sorted-array-faster-than-an-unsorted-array" },
+ { "url": "http://www.google.com/doubleclick/" },
+ { "url": "http://search.4shared.com/q/CCAD/1/barack%20obama" },
+ { "url": "http://dailymotion.com" },
+ { "url": "http://globo.com" },
+ { "url": "http://instagram.com/developer/" },
+ { "url": "http://livedoor.com" },
+ { "url": "http://wordpress.org/showcase/" },
+ { "url": "http://bp.blogspot.com" },
+ { "url": "http://wigetmedia.com/advertisers" },
+ { "url": "http://www.search-results.com/web?&q=barack%20obama" },
+ { "url": "http://cnet.com" },
+ { "url": "http://nytimes.com" },
+ { "url": "http://torrentz.eu/search?f=barack+obama" },
+ { "url": "http://livejournal.com" },
+ { "url": "http://douban.com" },
+ { "url": "http://www.weather.com/weather/right-now/Mountain+View+CA+94043" },
+ { "url": "http://dailymail.co.uk" },
+ { "url": "http://www.tianya.cn/bbs/index.shtml" },
+ { "url": "http://ehow.com" },
+ { "url": "http://theproject.badoo.com/final.phtml" },
+ { "url": "http://www.bankofamerica.com/deposits/checksave/index.cfm?template=check_eBanking" },
+ { "url": "http://vimeo.com" },
+ { "url": "http://360.cn" },
+ { "url": "http://indiatimes.com" },
+ { "url": "http://deviantart.com" },
+ { "url": "http://reddit.com" },
+ { "url": "http://aweber.com" },
+ { "url": "http://warriorforum.com" },
+ { "url": "http://spiegel.de" },
+ { "url": "http://pconline.com.cn" },
+ { "url": "http://mozilla.org" },
+ { "url": "http://booking.com" },
+ { "url": "http://goo.ne.jp" },
+ { "url": "https://www.chase.com/online/Home-Lending/mortgages.htm" },
+ { "url": "http://addthis.com" },
+ { "url": "http://56.com" },
+ { "url": "http://news.blogfa.com/" },
+ { "url": "http://www.stumbleupon.com/jobs" },
+ { "url": "https://www.dropbox.com/about" },
+ { "url": "http://www.clicksor.com/publishers/adformat" },
+ { "url": "http://answers.com" },
+ { "url": "http://en.softonic.com/" },
+ { "url": "http://walmart.com" },
+ { "url": "http://pengyou.com" },
+ { "url": "http://outbrain.com" },
+ { "url": "http://comcast.net" },
+ { "url": "http://foxnews.com" },
+ { "url": "http://photobucket.com/findstuff/photography%20styles/" },
+ { "url": "http://bleach.wikia.com/?redirect=no" },
+ { "url": "http://sourceforge.net/projects/xoops/?source=frontpage&position=1" },
+ { "url": "http://onet.pl" },
+ { "url": "http://guardian.co.uk" },
+ { "url": "https://www.wellsfargo.com/jump/enterprise/doublediscount?msc=5589&mplx=10918-70119-3408-64" },
+ { "url": "http://wikimediafoundation.org/wiki/Home" },
+ { "url": "http://xunlei.com" },
+ { "url": "http://as.58.com/shuma/" },
+ { "url": "http://skype.com" },
+ { "url": "http://etsy.com" },
+ { "url": "http://bild.de" },
+ { "url": "http://search.naver.com/search.naver?where=nexearch&query=barack+obama&sm=top_hty&fbm=0&ie=utf8" },
+ { "url": "http://statcounter.com/features/?PHPSESSID=bbjcvjr681bcul4vqvgq2qgmo7" },
+ { "url": "http://iqiyi.com" },
+ { "url": "http://fbcdn.net" },
+ { "url": "http://www.myspace.com/browse/people" },
+ { "url": "http://allegro.pl/antyki-i-sztuka" },
+ { "url": "http://yesky.com" },
+ { "url": "http://justbeenpaid.com" },
+ { "url": "http://adultfriendfinder.com" },
+ { "url": "http://fiverr.com" },
+ { "url": "http://www.leboncoin.fr/annonces/offres/centre/" },
+ { "url": "http://dictionary.reference.com/" },
+ { "url": "http://realtime.rediff.com/instasearch#!barack%20obama" },
+ { "url": "http://zol.com.cn" },
+ { "url": "http://optmd.com" },
+ { "url": "http://www.filestube.com/search.html?q=barack+obama&select=All" },
+ { "url": "http://xinhuanet.com" },
+ { "url": "http://www.salesforce.com/sales-cloud/overview/" },
+ { "url": "http://www.squidoo.com/make-cards-and-gift-bags-with-antique-photos" },
+ { "url": "http://www.domaintools.com/research/" },
+ { "url": "http://download.cnet.com/windows/?tag=hdr;brandnav" },
+ { "url": "https://rapidshare.com/#!shop" },
+ { "url": "http://people.com.cn" },
+ { "url": "http://ucoz.ru" },
+ { "url": "http://free.fr" },
+ { "url": "http://nicovideo.jp" },
+ { "url": "http://www.yelp.com/search?find_desc=food&find_loc=San+Jose%2C+CA&ns=1" },
+ { "url": "http://slideshare.net" },
+ { "url": "http://archive.org/web/web.php" },
+ { "url": "http://www.cntv.cn/index.shtml" },
+ { "url": "http://english.cntv.cn/01/index.shtml" },
+ { "url": "http://abonnez-vous.orange.fr/residentiel/accueil/accueil.aspx" },
+ { "url": "http://v.it168.com/" },
+ { "url": "http://nbcolympics.com" },
+ { "url": "http://hootsuite.com" },
+ { "url": "http://www.scribd.com/doc/52210329/The-Masters-Augusta-National-s-Amen-Corner-up-close" },
+ { "url": "http://themeforest.net" },
+ { "url": "http://4399.com" },
+ { "url": "http://www.soku.com/v?keyword=barack%20obama" },
+ { "url": "http://google.se" },
+ { "url": "http://funmoods.com" },
+ { "url": "http://csdn.net" },
+ { "url": "http://telegraph.co.uk" },
+ { "url": "http://taringa.net" },
+ { "url": "http://www.tripadvisor.com/Tourism-g32701-Mendocino_California-Vacations.html" },
+ { "url": "http://pof.com" },
+ { "url": "http://wp.pl" },
+ { "url": "http://soundcloud.com/flosstradamus/tracks" },
+ { "url": "http://w3schools.com/html/default.asp" },
+ { "url": "http://ameblo.jp/staff/" },
+ { "url": "http://wsj.com" },
+ { "url": "http://web.de" },
+ { "url": "http://sweetim.com" },
+ { "url": "http://rambler.ru" },
+ { "url": "http://gmx.net" },
+ { "url": "http://www.indeed.com/jobs?q=software&l=Mountain+View%2C+CA" },
+ { "url": "http://ilivid.com" },
+ { "url": "http://www.xing.com/search/people?search%5Bq%5D=lufthansa" },
+ { "url": "http://reuters.com" },
+ { "url": "http://hostgator.com" },
+ { "url": "http://www.ikea.com/us/en/catalog/categories/departments/living_room/" },
+ { "url": "http://www.kaixin001.com/award2012/wenming/index.php" },
+ { "url": "http://ku6.com" },
+ { "url": "http://libero.it" },
+ { "url": "http://samsung.com" },
+ { "url": "http://hudong.com" },
+ { "url": "http://espncricinfo.com" },
+ { "url": "http://china.com" },
+ { "url": "http://www.ups.com/content/us/en/bussol/browse/smallbiz/new-to-ups.html?WT.svl=SolExp" },
+ { "url": "http://letv.com" },
+ { "url": "http://ero-advertising.com" },
+ { "url": "http://mashable.com" },
+ { "url": "http://iminent.com" },
+ { "url": "http://rutracker.org" },
+ { "url": "http://www.shopping.hp.com/en_US/home-office/-/products/Laptops/Laptops" },
+ { "url": "http://www.clickbank.com/buy_products.htm?dores=true&mainCategoryId=1340&sortField=POPULARITY&b1=1340" },
+ { "url": "http://b.hatena.ne.jp/" },
+ { "url": "http://www.youdao.com/search?q=barack+obama&ue=utf8&keyfrom=web.index" },
+ { "url": "http://forbes.com" },
+ { "url": "http://nbcnews.com" },
+ { "url": "http://bitauto.com" },
+ { "url": "http://php.net" },
+ { "url": "http://www.target.com/c/women/-/N-5xtd3#?lnk=nav_t_spc_1_0" },
+ { "url": "http://dianxin.cn" },
+ { "url": "http://www.aizhan.com/siteall/www.youboy.com/" },
+ { "url": "http://veiculos-home.mercadolivre.com.br/" },
+ { "url": "http://kakaku.com" },
+ { "url": "http://flipkart.com" },
+ { "url": "http://paipai.com" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/PRESUBMIT.py b/chromium/tools/perf/page_sets/PRESUBMIT.py
new file mode 100644
index 00000000000..f161443f808
--- /dev/null
+++ b/chromium/tools/perf/page_sets/PRESUBMIT.py
@@ -0,0 +1,63 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import re
+import sys
+
+
+def _SyncFilesToCloud(input_api, output_api):
+ """Searches for .sha1 files and uploads them to Cloud Storage.
+
+ It validates all the hashes and skips upload if not necessary.
+ """
+ # Because this script will be called from a magic PRESUBMIT demon,
+ # avoid angering it; don't pollute its sys.path.
+ old_sys_path = sys.path
+ try:
+ sys.path = [os.path.join(os.pardir, os.pardir, 'telemetry')] + sys.path
+ from telemetry.page import cloud_storage
+ finally:
+ sys.path = old_sys_path
+
+ hashes_in_cloud_storage = cloud_storage.List(cloud_storage.DEFAULT_BUCKET)
+
+ results = []
+ for hash_path in input_api.AbsoluteLocalPaths():
+ file_path, extension = os.path.splitext(hash_path)
+ if extension != '.sha1':
+ continue
+
+ with open(hash_path, 'rb') as f:
+ file_hash = f.read(1024).rstrip()
+ if file_hash in hashes_in_cloud_storage:
+ results.append(output_api.PresubmitNotifyResult(
+ 'File already in Cloud Storage, skipping upload: %s' % hash_path))
+ continue
+
+ if not re.match('^([A-Za-z0-9]{40})$', file_hash):
+ results.append(output_api.PresubmitError(
+ 'Hash file does not contain a valid SHA-1 hash: %s' % hash_path))
+ continue
+ if not os.path.exists(file_path):
+ results.append(output_api.PresubmitError(
+ 'Hash file exists, but file not found: %s' % hash_path))
+ continue
+ if cloud_storage.GetHash(file_path) != file_hash:
+ results.append(output_api.PresubmitError(
+ 'Hash file does not match file\'s actual hash: %s' % hash_path))
+ continue
+
+ try:
+ cloud_storage.Insert(cloud_storage.DEFAULT_BUCKET, file_hash, file_path)
+ except cloud_storage.CloudStorageError:
+ results.append(output_api.PresubmitError(
+ 'Unable to upload to Cloud Storage: %s' % hash_path))
+
+ return results
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ results = []
+ results += _SyncFilesToCloud(input_api, output_api)
+ return results
diff --git a/chromium/tools/perf/page_sets/__init__.py b/chromium/tools/perf/page_sets/__init__.py
new file mode 100644
index 00000000000..ed3e1cc1a25
--- /dev/null
+++ b/chromium/tools/perf/page_sets/__init__.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+def GetAllPageSetFilenames():
+ results = []
+ start_dir = os.path.dirname(__file__)
+ for dirpath, _, filenames in os.walk(start_dir):
+ for f in filenames:
+ if os.path.splitext(f)[1] != '.json':
+ continue
+ filename = os.path.join(dirpath, f)
+ results.append(filename)
+ return results
diff --git a/chromium/tools/perf/page_sets/blank_page.json b/chromium/tools/perf/page_sets/blank_page.json
new file mode 100644
index 00000000000..79bb01d0478
--- /dev/null
+++ b/chromium/tools/perf/page_sets/blank_page.json
@@ -0,0 +1,6 @@
+{
+ "description": "A single blank page.",
+ "pages": [
+ { "url": "file:///blank_page/blank_page.html" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/blank_page/blank_page.html b/chromium/tools/perf/page_sets/blank_page/blank_page.html
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/perf/page_sets/blank_page/blank_page.html
diff --git a/chromium/tools/perf/page_sets/dromaeo/domcoreattr.json b/chromium/tools/perf/page_sets/dromaeo/domcoreattr.json
new file mode 100644
index 00000000000..3ee0ab946b9
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/domcoreattr.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo DOMCore attr JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?dom-attr&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/domcoremodify.json b/chromium/tools/perf/page_sets/dromaeo/domcoremodify.json
new file mode 100644
index 00000000000..162b57f83bc
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/domcoremodify.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo DOMCore modify JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?dom-modify&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/domcorequery.json b/chromium/tools/perf/page_sets/dromaeo/domcorequery.json
new file mode 100644
index 00000000000..214ad8389c0
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/domcorequery.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo DOMCore query JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?dom-query&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/domcoretraverse.json b/chromium/tools/perf/page_sets/dromaeo/domcoretraverse.json
new file mode 100644
index 00000000000..d60d587f065
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/domcoretraverse.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo DOMCore traverse JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?dom-traverse&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibattrjquery.json b/chromium/tools/perf/page_sets/dromaeo/jslibattrjquery.json
new file mode 100644
index 00000000000..cb5ff944956
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibattrjquery.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib attr jquery JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-attr-jquery&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibattrprototype.json b/chromium/tools/perf/page_sets/dromaeo/jslibattrprototype.json
new file mode 100644
index 00000000000..71c6e2d13f6
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibattrprototype.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib attr prototype JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-attr-prototype&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibeventjquery.json b/chromium/tools/perf/page_sets/dromaeo/jslibeventjquery.json
new file mode 100644
index 00000000000..d9146c7667a
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibeventjquery.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib event jquery JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-event-jquery&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibeventprototype.json b/chromium/tools/perf/page_sets/dromaeo/jslibeventprototype.json
new file mode 100644
index 00000000000..f00578c63e3
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibeventprototype.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib event prototype JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-event-prototype&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibmodifyjquery.json b/chromium/tools/perf/page_sets/dromaeo/jslibmodifyjquery.json
new file mode 100644
index 00000000000..7e14289dce9
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibmodifyjquery.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib modify jquery JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-modify-jquery&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibmodifyprototype.json b/chromium/tools/perf/page_sets/dromaeo/jslibmodifyprototype.json
new file mode 100644
index 00000000000..604f200c16b
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibmodifyprototype.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib modify prototype JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-modify-prototype&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibstylejquery.json b/chromium/tools/perf/page_sets/dromaeo/jslibstylejquery.json
new file mode 100644
index 00000000000..102acff4b89
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibstylejquery.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib style jquery JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-style-jquery&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibstyleprototype.json b/chromium/tools/perf/page_sets/dromaeo/jslibstyleprototype.json
new file mode 100644
index 00000000000..04c39a649b7
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibstyleprototype.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib style prototype JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-style-prototype&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibtraversejquery.json b/chromium/tools/perf/page_sets/dromaeo/jslibtraversejquery.json
new file mode 100644
index 00000000000..9330d1953c5
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibtraversejquery.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib traverse jquery JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-traverse-jquery&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/dromaeo/jslibtraverseprototype.json b/chromium/tools/perf/page_sets/dromaeo/jslibtraverseprototype.json
new file mode 100644
index 00000000000..2d8a7d9ab82
--- /dev/null
+++ b/chromium/tools/perf/page_sets/dromaeo/jslibtraverseprototype.json
@@ -0,0 +1,8 @@
+{
+ "description": "Dromaeo JSLib traverse prototype JavaScript benchmark",
+ "pages": [
+ {
+ "url": "file:///../../../../chrome/test/data/dromaeo/index.html?jslib-traverse-prototype&automated"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/image_decoding_measurement.json b/chromium/tools/perf/page_sets/image_decoding_measurement.json
new file mode 100644
index 00000000000..fcf1ce26195
--- /dev/null
+++ b/chromium/tools/perf/page_sets/image_decoding_measurement.json
@@ -0,0 +1,12 @@
+{
+ "description": "A directed benchmark of image decoding performance",
+ "post_navigate_javascript_to_execute": "runBenchmark();",
+ "wait_for_javascript_expression": "isDone",
+ "image_decoding_measurement_limit_results_to_min_iterations": true,
+ "pages": [
+ { "url": "file:///../../../chrome/test/data/image_decoding/image_decoding.html?gif" },
+ { "url": "file:///../../../chrome/test/data/image_decoding/image_decoding.html?jpg" },
+ { "url": "file:///../../../chrome/test/data/image_decoding/image_decoding.html?png" },
+ { "url": "file:///../../../chrome/test/data/image_decoding/image_decoding.html?webp" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/intl_ar_fa_he.json b/chromium/tools/perf/page_sets/intl_ar_fa_he.json
new file mode 100644
index 00000000000..2983fcdf97b
--- /dev/null
+++ b/chromium/tools/perf/page_sets/intl_ar_fa_he.json
@@ -0,0 +1,32 @@
+{
+ "description": "Popular pages in right-to-left languages Arabic, Farsi and Hebrew.",
+ "archive_data_file": "../data/intl_ar_fa_he.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://msn.co.il/"
+ },
+ {
+ "url": "http://ynet.co.il/"
+ },
+ {
+ "url": "http://www.islamweb.net/"
+ },
+ {
+ "url": "http://farsnews.com/"
+ },
+ {
+ "url": "http://www.masrawy.com/"
+ },
+ {
+ "url": "http://www.startimes.com/f.aspx"
+ },
+ {
+ "url": "http://www.aljayyash.net/"
+ },
+ {
+ "url": "http://www.google.com.sa/"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/intl_es_fr_pt-BR.json b/chromium/tools/perf/page_sets/intl_es_fr_pt-BR.json
new file mode 100644
index 00000000000..227da7c2464
--- /dev/null
+++ b/chromium/tools/perf/page_sets/intl_es_fr_pt-BR.json
@@ -0,0 +1,40 @@
+{
+ "description": "Popular pages in Romance languages Spanish, French and Brazilian Portuguese.",
+ "archive_data_file": "../data/intl_es_fr_pt-BR.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://elmundo.es/"
+ },
+ {
+ "url": "http://terra.es/"
+ },
+ {
+ "url": "http://www.ebay.es/sch/i.html?_sacat=382&_trkparms=clkid%3D6548971389060485883&_qi=RTM1381637"
+ },
+ {
+ "url": "http://www.eltiempo.es/talavera-de-la-reina.html"
+ },
+ {
+ "url": "http://www.free.fr/adsl/index.html"
+ },
+ {
+ "url": "http://www.voila.fr/"
+ },
+ {
+ "url": "http://www.leboncoin.fr/annonces/offres/limousin/"
+ },
+ {
+ "url": "http://www.orange.fr/"
+ },
+ {
+ "url": "http://www.uol.com.br/",
+ "why": "#5 site in Brazil"
+ },
+ {
+ "url": "http://produto.mercadolivre.com.br/MLB-468424957-pelicula-protetora-smartphone-h5500-e-h5300-43-frete-free-_JM",
+ "why": "#10 site in Brazil"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/intl_hi_ru.json b/chromium/tools/perf/page_sets/intl_hi_ru.json
new file mode 100644
index 00000000000..5ec487494a4
--- /dev/null
+++ b/chromium/tools/perf/page_sets/intl_hi_ru.json
@@ -0,0 +1,46 @@
+{
+ "description": "Popular pages in Hindi and Russian.",
+ "archive_data_file": "../data/intl_hi_ru.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://www.rambler.ru/",
+ "why": "#12 site in Russia"
+ },
+ {
+ "url": "http://apeha.ru/"
+ },
+ {
+ "url": "http://yandex.ru/yandsearch?lr=102567&text=%D0%9F%D0%BE%D0%B3%D0%BE%D0%B4%D0%B0"
+ },
+ {
+ "url": "http://photofile.ru/"
+ },
+ {
+ "url": "http://ru.wikipedia.org/"
+ },
+ {
+ "url": "http://narod.yandex.ru/"
+ },
+ {
+ "url": "http://rutracker.org/forum/index.php",
+ "why": "#15 in Russia"
+ },
+ {
+ "url": "http://hindi.webdunia.com/"
+ },
+ {
+ "url": "http://hindi.oneindia.in/",
+ "why": "#49 site in India"
+ },
+ {
+ "url": "http://www.indiatimes.com/",
+ "why": "#9 site in India"
+ },
+ {
+ "url": "http://news.google.co.in/nwshp?tab=in&hl=hi",
+ "why": "#2 site in India"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/intl_ja_zh.json b/chromium/tools/perf/page_sets/intl_ja_zh.json
new file mode 100644
index 00000000000..4a00844a854
--- /dev/null
+++ b/chromium/tools/perf/page_sets/intl_ja_zh.json
@@ -0,0 +1,73 @@
+{
+ "description": "Popular pages in Japanese and Chinese.",
+ "archive_data_file": "../data/intl_ja_zh.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://www.amazon.co.jp",
+ "why": "#5 Japanese site"
+ },
+ {
+ "url": "http://mixi.jp/"
+ },
+ {
+ "url": "http://dtiblog.com/"
+ },
+ {
+ "url": "http://2ch.net/"
+ },
+ {
+ "url": "http://jugem.jp/"
+ },
+ {
+ "url": "http://hatena.ne.jp/"
+ },
+ {
+ "url": "http://goo.ne.jp/"
+ },
+ {
+ "url": "http://www.yahoo.co.jp/",
+ "why": "#1 Japanese site"
+ },
+ {
+ "url": "http://fc2.com/ja/",
+ "why": "#3 Japanese site"
+ },
+ {
+ "url": "http://kakaku.com/"
+ },
+ {
+ "url": "http://zol.com.cn/"
+ },
+ {
+ "url": "http://cn.yahoo.com/"
+ },
+ {
+ "url": "http://www.baidu.com/s?wd=%D0%C2%20%CE%C5",
+ "why": "#1 Chinese site"
+ },
+ {
+ "url": "http://www.qq.com/",
+ "why": "#2 Chinese site"
+ },
+ {
+ "url": "http://www.taobao.com/index_global.php",
+ "why": "#3 Chinese site"
+ },
+ {
+ "url": "http://www.sina.com.cn/",
+ "why": "#4 Chinese site"
+ },
+ {
+ "url": "http://www.google.com.hk/#q=%E9%82%84%E6%8F%90%E4%BE%9B&fp=c44d333e710cb480",
+ "why": "#5 Chinese site"
+ },
+ {
+ "url": "http://udn.com/NEWS/mainpage.shtml"
+ },
+ {
+ "url": "http://ruten.com.tw/"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/intl_ko_th_vi.json b/chromium/tools/perf/page_sets/intl_ko_th_vi.json
new file mode 100644
index 00000000000..5f9dc1f8871
--- /dev/null
+++ b/chromium/tools/perf/page_sets/intl_ko_th_vi.json
@@ -0,0 +1,52 @@
+{
+ "description": "Popular pages in Korean, Thai and Vietnamese.",
+ "archive_data_file": "../data/intl_ko_th_vi.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://us.24h.com.vn/",
+ "why": "#7 site in Vietnam"
+ },
+ {
+ "url": "http://vnexpress.net/",
+ "why": "#6 site in Vietnam"
+ },
+ {
+ "url": "http://vietnamnet.vn/",
+ "why": "#18 site in Vietnam"
+ },
+ {
+ "url": "http://news.zing.vn/the-gioi/ba-dam-thep-margaret-thatcher-qua-doi/a312895.html#home_noibat1",
+ "why": "#5 site in Vietnam"
+ },
+ {
+ "url": "http://kenh14.vn/home.chn"
+ },
+ {
+ "url": "http://www.naver.com/",
+ "why": "#5 site in Korea"
+ },
+ {
+ "url": "http://www.daum.net/",
+ "why": "#9 site in Korea"
+ },
+ {
+ "url": "http://www.donga.com/",
+ "why": "#25 site in Korea"
+ },
+ {
+ "url": "http://www.chosun.com/"
+ },
+ {
+ "url": "http://www.danawa.com/"
+ },
+ {
+ "url": "http://pantip.com/",
+ "why": "#10 site in Thailand"
+ },
+ {
+ "url": "http://thaimisc.com/"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/key_desktop_sites.json b/chromium/tools/perf/page_sets/key_desktop_sites.json
new file mode 100644
index 00000000000..85b05e80734
--- /dev/null
+++ b/chromium/tools/perf/page_sets/key_desktop_sites.json
@@ -0,0 +1,749 @@
+{
+ "description": "Sites of Interest",
+ "archive_data_file": "../data/sites_of_interest.json",
+ "credentials_path": "../data/credentials.json",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://facebook.com",
+ "credentials": "facebook"
+ },
+ { "url": "http://youtube.com" },
+ { "url": "http://twitter.com/nbc" },
+ { "url": "http://bbc.co.uk" },
+ { "url": "http://imdb.com" },
+ { "url": "http://espn.go.com" },
+ { "url": "http://cnn.com" },
+ { "url": "http://bbc.co.uk/news/" },
+ { "url": "http://weather.com" },
+ { "url": "http://livejournal.com" },
+ { "url": "http://deviantart.com" },
+ { "url": "http://foxnews.com" },
+ { "url": "http://nbcnews.com" },
+ { "url": "http://scribd.com" },
+ { "url": "http://movies.yahoo.com" },
+ { "url": "http://tv.yahoo.com" },
+ { "url": "http://pandora.com" },
+ { "url": "http://tmz.com" },
+ { "url": "http://hulu.com" },
+ { "url": "http://abcnews.go.com" },
+ { "url": "http://youtube.com/videos" },
+ { "url": "http://ndtv.com" },
+ { "url": "http://money.cnn.com" },
+ { "url": "http://msn.foxsports.com" },
+ { "url": "http://cbsnews.com" },
+ { "url": "http://wired.com" },
+ { "url": "http://cnbc.com" },
+ { "url": "http://sportsillustrated.cnn.com" },
+ { "url": "http://home.disney.go.com" },
+ { "url": "http://urbandictionary.com" },
+ { "url": "http://rottentomatoes.com" },
+ { "url": "http://foodnetwork.com" },
+ { "url": "http://npr.org" },
+ { "url": "http://gawker.com" },
+ { "url": "http://last.fm" },
+ { "url": "http://sky.com" },
+ { "url": "http://eonline.com" },
+ { "url": "http://egotastic.com" },
+ { "url": "http://copyscape.com" },
+ { "url": "http://mtv.com" },
+ { "url": "http://ultimate-guitar.com" },
+ { "url": "http://comcast.com" },
+ { "url": "http://cbc.ca" },
+ { "url": "http://fanfiction.net" },
+ { "url": "http://discovery.com" },
+ { "url": "http://deezer.com" },
+ { "url": "http://metrolyrics.com" },
+ { "url": "http://foxnews.com/entertainment/" },
+ { "url": "http://cartoonnetwork.com" },
+ { "url": "http://paypal.com" },
+ { "url": "http://finance.yahoo.com" },
+ { "url": "http://alibaba.com" },
+ { "url": "http://bankofamerica.com" },
+ { "url": "http://www.chase.com/" },
+ { "url": "http://wellsfargo.com" },
+ { "url": "http://skype.com" },
+ { "url": "http://online.wsj.com" },
+ { "url": "http://indeed.com" },
+ { "url": "http://samsung.com" },
+ { "url": "http://reuters.com" },
+ { "url": "http://ups.com" },
+ { "url": "http://forbes.com" },
+ { "url": "http://clickbank.com" },
+ { "url": "http://target.com" },
+ { "url": "http://att.com" },
+ { "url": "http://cj.com" },
+ { "url": "http://constantcontact.com" },
+ { "url": "http://ezinearticles.com" },
+ { "url": "http://shutterstock.com" },
+ { "url": "http://americanexpress.com" },
+ { "url": "http://freelancer.com" },
+ { "url": "http://istockphoto.com" },
+ { "url": "http://fedex.com" },
+ { "url": "http://verizonwireless.com" },
+ { "url": "http://capitalone.com" },
+ { "url": "http://bloomberg.com" },
+ { "url": "http://monster.com" },
+ { "url": "http://hdfcbank.com" },
+ { "url": "http://fotolia.com" },
+ { "url": "http://thesun.co.uk" },
+ { "url": "http://zillow.com" },
+ { "url": "http://nokia.com" },
+ { "url": "http://tradedoubler.com" },
+ { "url": "http://icicibank.com" },
+ { "url": "http://123rf.com" },
+ { "url": "http://elance.com" },
+ { "url": "http://icbc.com.cn" },
+ { "url": "http://news.cnet.com" },
+ { "url": "http://verizon.com" },
+ { "url": "http://careerbuilder.com" },
+ { "url": "http://sears.com" },
+ { "url": "http://getresponse.com" },
+ { "url": "http://sitesell.com" },
+ { "url": "http://manta.com" },
+ { "url": "http://www.blogger.com/" },
+ { "url": "http://avg.com" },
+ { "url": "http://google.com/analytics/" },
+ { "url": "http://go.com" },
+ { "url": "http://flickr.com" },
+ { "url": "http://aol.com" },
+ { "url": "http://thepiratebay.se" },
+ { "url": "http://zedo.com" },
+ { "url": "http://about.com" },
+ { "url": "http://stackoverflow.com" },
+ { "url": "http://godaddy.com" },
+ { "url": "http://mediafire.com" },
+ { "url": "http://wordpress.org" },
+ { "url": "http://adwords.google.com" },
+ { "url": "http://imgur.com" },
+ { "url": "http://4shared.com" },
+ { "url": "http://vimeo.com" },
+ { "url": "http://play.google.com/" },
+ { "url": "http://badoo.com" },
+ { "url": "http://aweber.com" },
+ { "url": "http://mozilla.org" },
+ { "url": "http://www.stumbleupon.com/stumbler/chimacintosh" },
+ { "url": "http://www.google.com/adsense/" },
+ { "url": "http://my.yahoo.com" },
+ { "url": "http://sourceforge.net" },
+ { "url": "http://answers.com" },
+ { "url": "http://wordpress.org/extend/plugins/" },
+ { "url": "http://photobucket.com" },
+ { "url": "http://clicksor.com" },
+ { "url": "http://google.com/reader/" },
+ { "url": "http://store.apple.com" },
+ { "url": "http://wikia.com" },
+ { "url": "http://statcounter.com" },
+ { "url": "http://fiverr.com" },
+ { "url": "http://slideshare.net" },
+ { "url": "http://salesforce.com" },
+ { "url": "http://myspace.com" },
+ { "url": "http://hootsuite.com" },
+ { "url": "http://domaintools.com" },
+ { "url": "http://rediff.com" },
+ { "url": "http://soundcloud.com" },
+ { "url": "http://download.cnet.com" },
+ { "url": "http://archive.org" },
+ { "url": "http://filestube.com" },
+ { "url": "http://developers.facebook.com" },
+ { "url": "http://hostgator.com" },
+ { "url": "http://battle.net" },
+ { "url": "http://pch.com" },
+ { "url": "http://ign.com" },
+ { "url": "http://pogo.com" },
+ { "url": "http://miniclip.com" },
+ { "url": "http://888.com" },
+ { "url": "http://gamespot.com" },
+ { "url": "http://steampowered.com" },
+ { "url": "http://gamefaqs.com" },
+ { "url": "http://xbox.com" },
+ { "url": "http://games.yahoo.com" },
+ { "url": "http://betfair.com" },
+ { "url": "http://kongregate.com" },
+ { "url": "http://ea.com" },
+ { "url": "http://leagueoflegends.com" },
+ { "url": "http://roblox.com" },
+ { "url": "http://williamhill.com" },
+ { "url": "http://playstation.com" },
+ { "url": "http://wowhead.com" },
+ { "url": "http://king.com" },
+ { "url": "http://minecraft.net" },
+ { "url": "http://chess.com" },
+ { "url": "http://minecraftwiki.net" },
+ { "url": "http://addictinggames.com" },
+ { "url": "http://mmo-champion.com" },
+ { "url": "http://runescape.com" },
+ { "url": "http://travian.com" },
+ { "url": "http://zone.msn.com" },
+ { "url": "http://ubi.com" },
+ { "url": "http://calottery.com" },
+ { "url": "http://freeonlinegames.com" },
+ { "url": "http://games.com" },
+ { "url": "http://n4g.com" },
+ { "url": "http://nvidia.com" },
+ { "url": "http://callofduty.com" },
+ { "url": "http://us.playstation.com" },
+ { "url": "http://bet-at-home.com" },
+ { "url": "http://gametrailers.com" },
+ { "url": "http://teamliquid.net" },
+ { "url": "http://nick.com/games/" },
+ { "url": "http://planetminecraft.com" },
+ { "url": "http://nintendo.com" },
+ { "url": "http://popcap.com" },
+ { "url": "http://gamehouse.com" },
+ { "url": "http://curse.com" },
+ { "url": "http://bulbagarden.net" },
+ { "url": "http://rockstargames.com" },
+ { "url": "http://partycasino.com" },
+ { "url": "http://square-enix.com" },
+ { "url": "http://perfectworld.com" },
+ { "url": "http://nih.gov" },
+ { "url": "http://webmd.com" },
+ { "url": "http://ncbi.nlm.nih.gov/pubmed/" },
+ { "url": "http://focusoncrohnsdisease.com" },
+ { "url": "http://mayoclinic.com" },
+ { "url": "http://mercola.com" },
+ { "url": "http://drugs.com" },
+ { "url": "http://menshealth.com" },
+ { "url": "http://nlm.nih.gov/medlineplus/" },
+ { "url": "http://weightwatchers.com" },
+ { "url": "http://cdc.gov" },
+ { "url": "http://caloriecount.about.com" },
+ { "url": "http://patents.uspto.gov" },
+ { "url": "http://psychologytoday.com" },
+ { "url": "http://nhs.uk" },
+ { "url": "http://medscape.com" },
+ { "url": "http://foxnews.com/health/" },
+ { "url": "http://who.int" },
+ { "url": "http://healthboards.com" },
+ { "url": "http://self.com" },
+ { "url": "http://health.com" },
+ { "url": "http://kidshealth.org" },
+ { "url": "http://fda.gov" },
+ { "url": "http://netdoctor.co.uk" },
+ { "url": "http://prevention.com" },
+ { "url": "http://makeupalley.com" },
+ { "url": "http://stevepavlina.com" },
+ { "url": "http://realage.com" },
+ { "url": "http://fitnessmagazine.com" },
+ { "url": "http://healthcentral.com" },
+ { "url": "http://rxlist.com" },
+ { "url": "http://vitals.com" },
+ { "url": "http://totalbeauty.com" },
+ { "url": "http://nuance.com" },
+ { "url": "http://telegraph.co.uk/health/" },
+ { "url": "http://drbatras.com" },
+ { "url": "http://emedtv.com" },
+ { "url": "http://bmj.com" },
+ { "url": "http://medcohealth.com" },
+ { "url": "http://webmd.com/skin-problems-and-treatments/default.htm" },
+ { "url": "http://tums.ac.ir" },
+ { "url": "http://apa.org" },
+ { "url": "http://cancer.org" },
+ { "url": "http://healthguru.com" },
+ { "url": "http://earthclinic.com" },
+ { "url": "http://curezone.com" },
+ { "url": "http://beauty.about.com" },
+ { "url": "http://www.kaiserpermanente.org/" },
+ { "url": "http://drweil.com" },
+ { "url": "http://24hourfitness.com" },
+ { "url": "http://ehow.com" },
+ { "url": "http://yelp.com" },
+ { "url": "http://groupon.com/san-francisco" },
+ { "url": "http://engadget.com" },
+ { "url": "http://gsmarena.com" },
+ { "url": "http://reviews.cnet.com" },
+ { "url": "http://allrecipes.com" },
+ { "url": "http://autos.yahoo.com" },
+ { "url": "http://shopping.yahoo.com" },
+ { "url": "http://gizmodo.com" },
+ { "url": "http://marketwatch.com" },
+ { "url": "http://babycenter.com" },
+ { "url": "http://nextag.com" },
+ { "url": "http://fixya.com" },
+ { "url": "http://dpreview.com" },
+ { "url": "http://tomshardware.com" },
+ { "url": "http://theverge.com" },
+ { "url": "http://instructables.com" },
+ { "url": "http://cafemom.com" },
+ { "url": "http://google.com/products" },
+ { "url": "http://bbb.org" },
+ { "url": "http://shopping.com" },
+ { "url": "http://irs.gov" },
+ { "url": "http://kbb.com" },
+ { "url": "http://retailmenot.com" },
+ { "url": "http://edmunds.com" },
+ { "url": "http://mobile9.com" },
+ { "url": "http://bankrate.com" },
+ { "url": "http://fatwallet.com" },
+ { "url": "http://fool.com" },
+ { "url": "http://hgtv.com" },
+ { "url": "http://coupons.com" },
+ { "url": "http://apartmenttherapy.com" },
+ { "url": "http://phonearena.com" },
+ { "url": "http://shopzilla.com" },
+ { "url": "http://marthastewart.com" },
+ { "url": "http://consumerreports.org" },
+ { "url": "http://pricegrabber.com" },
+ { "url": "http://epinions.com" },
+ { "url": "http://cooks.com" },
+ { "url": "http://bhg.com" },
+ { "url": "http://mouthshut.com" },
+ { "url": "http://travel.state.gov" },
+ { "url": "http://realsimple.com" },
+ { "url": "http://opendns.com" },
+ { "url": "http://gardenweb.com" },
+ { "url": "http://blu-ray.com" },
+ { "url": "http://thesaurus.com" },
+ { "url": "http://espncricinfo.com" },
+ { "url": "http://weebly.com" },
+ { "url": "http://bbc.co.uk/sport/0/football/" },
+ { "url": "http://y8.com" },
+ { "url": "http://xe.com/ucc/" },
+ { "url": "http://timeanddate.com" },
+ { "url": "http://soccernet.espn.go.com" },
+ { "url": "http://howstuffworks.com" },
+ { "url": "http://en.wikipedia.org/wiki/Main_Page" },
+ { "url": "http://reverso.net" },
+ { "url": "http://timeanddate.com/worldclock/" },
+ { "url": "http://sitepoint.com" },
+ { "url": "http://usopen.org" },
+ { "url": "http://stardoll.com" },
+ { "url": "http://london2012.com" },
+ { "url": "http://lego.com" },
+ { "url": "http://000webhost.com" },
+ { "url": "http://fifa.com" },
+ { "url": "http://uefa.com" },
+ { "url": "http://nick.com" },
+ { "url": "http://girlsgogames.com" },
+ { "url": "http://pbskids.org" },
+ { "url": "http://thestar.com" },
+ { "url": "http://dynamicdrive.com" },
+ { "url": "http://nickjr.com" },
+ { "url": "http://manutd.com" },
+ { "url": "http://earthquake.usgs.gov" },
+ { "url": "http://khanacademy.org" },
+ { "url": "http://barbie.com" },
+ { "url": "http://sciencedaily.com" },
+ { "url": "http://gocomics.com" },
+ { "url": "http://webdeveloper.com" },
+ { "url": "http://www2.warnerbros.com" },
+ { "url": "http://jpl.nasa.gov" },
+ { "url": "http://yola.com" },
+ { "url": "http://bom.gov.au" },
+ { "url": "http://nationalpost.com" },
+ { "url": "http://booking.com" },
+ { "url": "http://tripadvisor.com" },
+ { "url": "http://agoda.com" },
+ { "url": "http://xe.com" },
+ { "url": "http://expedia.com" },
+ { "url": "http://metacafe.com" },
+ { "url": "http://priceline.com" },
+ { "url": "http://southwest.com" },
+ { "url": "http://cracked.com" },
+ { "url": "http://kayak.com" },
+ { "url": "http://travelocity.com" },
+ { "url": "http://united.com" },
+ { "url": "http://delta.com" },
+ { "url": "http://ryanair.com" },
+ { "url": "http://lonelyplanet.com" },
+ { "url": "http://orbitz.com" },
+ { "url": "http://aa.com" },
+ { "url": "http://easyjet.com" },
+ { "url": "http://hilton.com" },
+ { "url": "http://travel.yahoo.com" },
+ { "url": "http://marriott.com" },
+ { "url": "http://couchsurfing.org" },
+ { "url": "http://hotwire.com" },
+ { "url": "http://autoblog.com" },
+ { "url": "http://lufthansa.com" },
+ { "url": "http://theonion.com" },
+ { "url": "http://britishairways.com" },
+ { "url": "http://travelzoo.com" },
+ { "url": "http://ebaumsworld.com" },
+ { "url": "http://emirates.com" },
+ { "url": "http://venere.com" },
+ { "url": "http://wikitravel.org" },
+ { "url": "http://jal.co.jp" },
+ { "url": "http://collegehumor.com" },
+ { "url": "http://ford.com" },
+ { "url": "http://vrbo.com" },
+ { "url": "http://opentable.com" },
+ { "url": "http://hyatt.com" },
+ { "url": "http://klm.com" },
+ { "url": "http://airberlin.com" },
+ { "url": "http://usairways.com" },
+ { "url": "http://skyscanner.net" },
+ { "url": "http://timeout.com" },
+ { "url": "http://homeaway.com" },
+ { "url": "http://lonelyplanet.com/thorntree/" },
+ { "url": "http://virgin-atlantic.com" },
+ { "url": "http://news.yahoo.com" },
+ { "url": "http://huffingtonpost.com" },
+ { "url": "http://news.google.com" },
+ { "url": "http://reddit.com" },
+ { "url": "http://guardian.co.uk" },
+ { "url": "http://timesofindia.indiatimes.com" },
+ { "url": "http://washingtonpost.com" },
+ { "url": "http://usatoday.com" },
+ { "url": "http://drudgereport.com" },
+ { "url": "http://latimes.com" },
+ { "url": "http://wunderground.com" },
+ { "url": "http://accuweather.com" },
+ { "url": "http://examiner.com" },
+ { "url": "http://news.com.au" },
+ { "url": "http://time.com" },
+ { "url": "http://alarabiya.net" },
+ { "url": "http://businessweek.com" },
+ { "url": "http://smh.com.au" },
+ { "url": "http://weather.yahoo.com" },
+ { "url": "http://foxnews.com/politics/" },
+ { "url": "http://economictimes.indiatimes.com" },
+ { "url": "http://nationalgeographic.com" },
+ { "url": "http://ft.com" },
+ { "url": "http://nypost.com" },
+ { "url": "http://sfgate.com" },
+ { "url": "http://topix.com" },
+ { "url": "http://hindustantimes.com" },
+ { "url": "http://chicagotribune.com" },
+ { "url": "http://newsmax.com" },
+ { "url": "http://breitbart.com" },
+ { "url": "http://economist.com" },
+ { "url": "http://theatlantic.com" },
+ { "url": "http://prweb.com" },
+ { "url": "http://theglobeandmail.com" },
+ { "url": "http://answers.yahoo.com" },
+ { "url": "http://wiki.answers.com" },
+ { "url": "http://wordreference.com" },
+ { "url": "http://thefreedictionary.com" },
+ { "url": "http://dict.leo.org" },
+ { "url": "http://w3.org" },
+ { "url": "http://nlm.nih.gov" },
+ { "url": "http://goodreads.com" },
+ { "url": "http://mapquest.com" },
+ { "url": "http://yellowpages.com" },
+ { "url": "http://wiktionary.org" },
+ { "url": "http://dict.cc" },
+ { "url": "http://bing.com/maps/" },
+ { "url": "http://whitepages.com" },
+ { "url": "http://m-w.com" },
+ { "url": "http://classmates.com" },
+ { "url": "http://blackboard.com" },
+ { "url": "http://justanswer.com" },
+ { "url": "http://mit.edu" },
+ { "url": "http://medterms.com" },
+ { "url": "http://stanford.edu" },
+ { "url": "http://brainyquote.com" },
+ { "url": "http://harvard.edu" },
+ { "url": "http://superpages.com" },
+ { "url": "http://mylife.com" },
+ { "url": "http://en.wiktionary.org" },
+ { "url": "http://investopedia.com" },
+ { "url": "http://lumosity.com" },
+ { "url": "http://phoenix.edu" },
+ { "url": "http://berkeley.edu" },
+ { "url": "http://ecollege.com" },
+ { "url": "http://ed.gov" },
+ { "url": "http://yellowpages.sulekha.com" },
+ { "url": "http://wisegeek.com" },
+ { "url": "http://utexas.edu" },
+ { "url": "http://wwp.greenwichmeantime.com" },
+ { "url": "http://cornell.edu" },
+ { "url": "http://psu.edu" },
+ { "url": "http://maps.yahoo.com" },
+ { "url": "http://linkedin.com/answers" },
+ { "url": "http://yahoo.co.jp" },
+ { "url": "http://translate.google.com" },
+ { "url": "http://noaa.gov" },
+ { "url": "http://ncbi.nlm.nih.gov" },
+ { "url": "http://nhc.noaa.gov" },
+ { "url": "http://ted.com" },
+ { "url": "http://jma.go.jp" },
+ { "url": "http://usgs.gov" },
+ { "url": "http://care2.com" },
+ { "url": "http://sciencedirect.com" },
+ { "url": "http://intellicast.com" },
+ { "url": "http://guardian.co.uk/technology" },
+ { "url": "http://nature.com" },
+ { "url": "http://wunderground.com/tropical/" },
+ { "url": "http://ieee.org" },
+ { "url": "http://elsevier.com" },
+ { "url": "http://usda.gov" },
+ { "url": "http://redorbit.com" },
+ { "url": "http://scientificamerican.com" },
+ { "url": "http://nps.gov" },
+ { "url": "http://metoffice.gov.uk" },
+ { "url": "http://space.com" },
+ { "url": "http://foreignpolicy.com" },
+ { "url": "http://bbc.co.uk/news/technology/" },
+ { "url": "http://newscientist.com" },
+ { "url": "http://livescience.com" },
+ { "url": "http://jstor.org" },
+ { "url": "http://mnn.com" },
+ { "url": "http://foxnews.com/scitech/" },
+ { "url": "http://census.gov" },
+ { "url": "http://epa.gov" },
+ { "url": "http://bls.gov" },
+ { "url": "http://metric-conversions.org" },
+ { "url": "http://news.nationalgeographic.com/index.rss" },
+ { "url": "http://bbc.co.uk/news/science_and_environment/" },
+ { "url": "http://colorado.edu" },
+ { "url": "http://popsci.com" },
+ { "url": "http://amazon.com" },
+ { "url": "http://ebay.com" },
+ { "url": "http://netflix.com" },
+ { "url": "http://amazon.co.uk" },
+ { "url": "http://walmart.com" },
+ { "url": "http://ikea.com" },
+ { "url": "http://bestbuy.com" },
+ { "url": "http://multiply.com" },
+ { "url": "http://newegg.com" },
+ { "url": "http://homedepot.com" },
+ { "url": "http://macys.com" },
+ { "url": "http://livingsocial.com" },
+ { "url": "http://gap.com" },
+ { "url": "http://bodybuilding.com" },
+ { "url": "http://kohls.com" },
+ { "url": "http://barnesandnoble.com" },
+ { "url": "http://lowes.com" },
+ { "url": "http://zappos.com" },
+ { "url": "http://overstock.com" },
+ { "url": "http://legacy.com" },
+ { "url": "http://staples.com" },
+ { "url": "http://shutterfly.com" },
+ { "url": "http://nike.com" },
+ { "url": "http://nordstrom.com" },
+ { "url": "http://pixmania.com" },
+ { "url": "http://costco.com" },
+ { "url": "http://bhphotovideo.com" },
+ { "url": "http://hm.com" },
+ { "url": "http://ticketmaster.com" },
+ { "url": "http://jcpenney.com" },
+ { "url": "http://walgreens.com" },
+ { "url": "http://qvc.com" },
+ { "url": "http://autotrader.com" },
+ { "url": "http://tigerdirect.com" },
+ { "url": "http://trademe.co.nz" },
+ { "url": "http://sony.com" },
+ { "url": "http://directv.com" },
+ { "url": "http://buy.com" },
+ { "url": "http://victoriassecret.com" },
+ { "url": "http://cars.com" },
+ { "url": "http://gamestop.com" },
+ { "url": "http://cvs.com" },
+ { "url": "http://dealextreme.com" },
+ { "url": "http://cafepress.com" },
+ { "url": "http://6pm.com" },
+ { "url": "http://facebook.com/home.php#!/OccupyAirForce" },
+ { "url": "http://deviantart.com/#catpath=anthro" },
+ { "url": "http://shine.yahoo.com" },
+ { "url": "http://match.com" },
+ { "url": "http://siteadvisor.com" },
+ { "url": "http://digg.com" },
+ { "url": "http://hi5.com" },
+ { "url": "http://ancestry.com" },
+ { "url": "http://sulekha.com" },
+ { "url": "http://europa.eu" },
+ { "url": "http://biblegateway.com" },
+ { "url": "http://slate.com" },
+ { "url": "http://correios.com.br" },
+ { "url": "http://wonderwall.msn.com" },
+ { "url": "http://change.org" },
+ { "url": "http://state.gov" },
+ { "url": "http://salon.com" },
+ { "url": "http://askmen.com" },
+ { "url": "http://infowars.com" },
+ { "url": "http://wnd.com" },
+ { "url": "http://ec.europa.eu" },
+ { "url": "http://justjared.com" },
+ { "url": "http://sheknows.com" },
+ { "url": "http://slashdot.org" },
+ { "url": "http://newgrounds.com" },
+ { "url": "http://weeklystandard.com" },
+ { "url": "http://royalmail.com" },
+ { "url": "http://snopes.com" },
+ { "url": "http://lds.org" },
+ { "url": "http://dailykos.com" },
+ { "url": "http://complex.com" },
+ { "url": "http://avaaz.org" },
+ { "url": "http://aarp.org" },
+ { "url": "http://theregister.co.uk" },
+ { "url": "http://creativecommons.org" },
+ { "url": "http://jw.org" },
+ { "url": "http://peoplesmart.com" },
+ { "url": "http://uspto.gov" },
+ { "url": "http://uscis.gov" },
+ { "url": "http://whitehouse.gov" },
+ { "url": "http://townhall.com" },
+ { "url": "http://sec.gov" },
+ { "url": "http://sports.yahoo.com" },
+ { "url": "http://nfl.com" },
+ { "url": "http://mlb.mlb.com" },
+ { "url": "http://cbssports.com" },
+ { "url": "http://bleacherreport.com" },
+ { "url": "http://livescore.com" },
+ { "url": "http://espn.go.com/nfl/" },
+ { "url": "http://sports.yahoo.com/nfl" },
+ { "url": "http://espn.go.com/mlb/" },
+ { "url": "http://premierleague.com" },
+ { "url": "http://skysports.com" },
+ { "url": "http://sports.yahoo.com/mlb" },
+ { "url": "http://games.espn.go.com/frontpage" },
+ { "url": "http://uk.eurosport.yahoo.com" },
+ { "url": "http://baseball.fantasysports.yahoo.com" },
+ { "url": "http://baseball.fantasysports.yahoo.com/b1" },
+ { "url": "http://skysports.com/football/" },
+ { "url": "http://nba.com" },
+ { "url": "http://hattrick.org" },
+ { "url": "http://wwe.com" },
+ { "url": "http://telegraph.co.uk/sport/" },
+ { "url": "http://rivals.com" },
+ { "url": "http://sports.yahoo.com/fantasy" },
+ { "url": "http://espn.go.com/nba/" },
+ { "url": "http://scout.com" },
+ { "url": "http://msn.foxsports.com/nfl" },
+ { "url": "http://sports.yahoo.com/nfl/players/" },
+ { "url": "http://guardian.co.uk/football" },
+ { "url": "http://rotoworld.com" },
+ { "url": "http://nascar.com" },
+ { "url": "http://arsenal.com" },
+ { "url": "http://formula1.com" },
+ { "url": "http://yardbarker.com" },
+ { "url": "http://pgatour.com" },
+ { "url": "http://rei.com" },
+ { "url": "http://liverpoolfc.tv" },
+ { "url": "http://deadspin.com" },
+ { "url": "http://sbnation.com" },
+ { "url": "https://www.google.com" },
+ { "url": "https://www.google.com/search?q=barack%20obama" },
+ {
+ "url": "https://mail.google.com/mail/",
+ "credentials": "google",
+ "scrollable_element_function": "function(callback) { gmonkey.load('2.0', function(api) { callback(api.getScrollableElement()); }); }",
+ "smoothness": {
+ "action": "scroll",
+ "wait_for_javascript_expression": "window.gmonkey !== undefined && document.getElementById('gb') !== null"
+ }
+ },
+ {
+ "url": "https://www.google.com/calendar/",
+ "credentials": "google",
+ "scrollable_element_function": "function(callback) { callback(document.getElementById('scrolltimedeventswk')); }"
+ },
+ {
+ "url": "https://drive.google.com",
+ "credentials": "google",
+ "scrollable_element_function": "function(callback) { callback(document.getElementsByClassName('doclistview-list')[0]); }",
+ "smoothness": {
+ "action": "scroll",
+ "wait_for_javascript_expression": "document.getElementsByClassName('doclistview-list').length"
+ }
+ },
+ {
+ "url": "https://docs.google.com/a/google.com/document/d/1XMAtPiVFZfItsMUOYl39v5YA8bcSPe4LDrVO25OdsCU/edit",
+ "credentials": "google",
+ "scrollable_element_function": "function(callback) { callback(document.getElementsByClassName('kix-appview-editor')[0]); }",
+ "smoothness": {
+ "action": "scroll",
+ "wait_for_javascript_expression": "document.getElementsByClassName('kix-appview-editor').length"
+ }
+ },
+ { "url": "https://maps.google.com" },
+ { "url": "http://reader.google.com" },
+ { "url": "https://plus.google.com/110031535020051778989/posts/2wP4KPPBMG8" },
+ { "url": "https://plus.google.com/110031535020051778989/photos" },
+ { "url": "http://googleblog.blogspot.com/" },
+ { "url": "https://chrome.google.com/webstore/category/home" },
+ { "url": "http://staff.tumblr.com/" },
+ { "url": "http://mashable.com/" },
+ { "url": "http://www.buzzfeed.com/celebrity" },
+ { "url": "http://www.thedailybeast.com/" },
+ { "url": "http://www.theverge.com/" },
+ { "url": "http://techcrunch.com/" },
+ { "url": "http://www.engadget.com/" },
+ { "url": "http://gizmodo.com/" },
+ { "url": "http://thinkprogress.org/?mobile=nc" },
+ { "url": "http://gawker.com/" },
+ { "url": "http://arstechnica.com/" },
+ { "url": "http://boingboing.net/category/featured/" },
+ { "url": "http://thenextweb.com/" },
+ { "url": "http://politicalticker.blogs.cnn.com/" },
+ { "url": "http://deadspin.com/" },
+ { "url": "http://news.yahoo.com/" },
+ { "url": "http://www.cnn.com/" },
+ { "url": "http://www.nbcnews.com/" },
+ { "url": "http://www.bbc.co.uk/news/" },
+ { "url": "http://www.reddit.com/" },
+ { "url": "http://my.yahoo.com/" },
+ { "url": "http://www.foxnews.com/" },
+ { "url": "http://www.guardiannews.com/uk-home" },
+ { "url": "http://timesofindia.indiatimes.com/" },
+ { "url": "http://online.wsj.com/home-page" },
+ { "url": "http://www.forbes.com/home_usa/" },
+ { "url": "http://www.washingtonpost.com/" },
+ { "url": "http://www.usatoday.com/" },
+ { "url": "http://drudgereport.com/" },
+ { "url": "http://abcnews.go.com/" },
+ { "url": "http://www.latimes.com/" },
+ { "url": "http://www.bloomberg.com/" },
+ { "url": "http://money.cnn.com/" },
+ { "url": "http://www.news.com.au/" },
+ { "url": "http://www.cbsnews.com/" },
+ { "url": "http://www.examiner.com/" },
+ { "url": "http://www.cnbc.com/" },
+ { "url": "http://www.alarabiya.net/default.html" },
+ { "url": "http://www.time.com/time/" },
+ { "url": "http://www.foxnews.com/politics/index.html" },
+ { "url": "http://www.smh.com.au/" },
+ { "url": "http://www.businessweek.com/" },
+ { "url": "http://www.nationalgeographic.com/" },
+ { "url": "http://www.wunderground.com/cgi-bin/findweather/getForecast?query=94035&sp=KCAMOUNT24" },
+ { "url": "http://www.accuweather.com/en/search-locations?zipcode=mountain%20view,%20ca" },
+ { "url": "http://www.weather.com/weather/right-now/Mountain+View+CA+94043" },
+ { "url": "http://weather.yahoo.com/united-states/california/mountain-view-12797130/" },
+ { "url": "http://www.yr.no/place/Norway/Oslo/Oslo/Oslo/" },
+ { "url": "http://www.metoffice.gov.uk/" },
+ { "url": "http://www.intellicast.com/Local/Weather.aspx?location=USCA0746" },
+ { "url": "http://www.shutterstock.com/cat.mhtml?searchterm=google&search_group=&lang=en&search_source=search_form" },
+ { "url": "http://www.flickr.com/search/?q=monkeys&f=hp" },
+ { "url": "http://www.flickr.com/photos/davidgutierrez/sets/72157604615916402/?page=3" },
+ { "url": "http://www.flickr.com/photos/davidgutierrez/sets/72157604615916402/show/with/4403158307/" },
+ { "url": "http://www.apple.com/iphone/" },
+ { "url": "http://www.taobao.com/index_global.php" },
+ { "url": "http://hootsuite.com/" },
+ { "url": "http://www.android.com/" },
+ { "url": "https://www.change.org/" },
+ { "url": "http://www.nytimes.com/skimmer/#/Technology" },
+ { "url": "http://www.glennbeck.com/" },
+ { "url": "http://www.pengyou.com/mobile?from=loginAndroid" },
+ { "url": "http://en.wikipedia.org/wiki/Cat" },
+ { "url": "http://en.wikipedia.org/wiki/British_Royal_Family" },
+ { "url": "http://9gag.com/gag/5202885" },
+ { "url": "http://www.wowwiki.com/World_of_Warcraft:_Mists_of_Pandaria" },
+ { "url": "http://twitter.github.com/bootstrap/" },
+ { "url": "http://reviews.cnet.com/8301-13727_7-57431192-263/disable-elastic-scrolling-in-os-x/" },
+ { "url": "http://mlb.com" },
+ { "url": "http://thenounproject.com/zh-cn/" },
+ { "url": "http://allrecipes.com/recipe/chicken-pot-pie-ix/" },
+ { "url": "http://www.gamespot.com/" },
+ { "url": "http://valleywag.com/" },
+ { "url": "http://gawker.com/5939683/based-on-a-true-story-is-a-rotten-lie-i-hope-you-never-believe" },
+ { "url": "http://www.imdb.com/title/tt0910970/" },
+ { "url": "http://www.html5rocks.com/en/" },
+ { "url": "http://athome.kimvallee.com/2010/03/why-to-splurge-on-a-high-end-dishwasher/" },
+ { "url": "http://mlb.mlb.com/mlb/gameday/index.jsp?gid=2012_08_31_sfnmlb_chnmlb_1&mode=wrap#gid=2012_08_31_sfnmlb_chnmlb_1&mode=box" },
+ { "url": "http://nytimes.com" },
+ { "url": "http://arstechnica.com" },
+ { "url": "http://pinterest.com" },
+ { "url": "http://www.theregister.co.uk/" },
+ { "url": "http://forum.xda-developers.com/" },
+ { "url": "http://maps.google.com" },
+ { "url": "https://www.google.com/search?num=10&hl=en&site=&tbm=isch&q=cats" },
+ { "url": "http://code.google.com/p/chromium/issues/list" },
+ { "url": "http://code.google.com/p/chromium/issues/detail?id=142038&q=black%20screen%20amd&colspec=ID%20Pri%20Mstone%20ReleaseBlock%20OS%20Area%20Feature%20Status%20Owner%20Summary" },
+ { "url": "http://mlb.mlb.com/index.jsp" },
+ { "url": "http://www.nfl.com/" },
+ { "url": "http://airbnb.github.com/infinity/demo-on.html" },
+ { "url": "http://habrahabr.ru/post/149892/#habracut" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/key_mobile_sites.json b/chromium/tools/perf/page_sets/key_mobile_sites.json
new file mode 100644
index 00000000000..9e3b68cfde4
--- /dev/null
+++ b/chromium/tools/perf/page_sets/key_mobile_sites.json
@@ -0,0 +1,232 @@
+{
+ "description": "Key mobile sites",
+ "archive_data_file": "../data/key_mobile_sites.json",
+ "credentials_path": "../data/credentials.json",
+ "user_agent_type": "mobile",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://www.androidpolice.com/2012/10/03/rumor-evidence-mounts-that-an-lg-optimus-g-nexus-is-coming-along-with-a-nexus-phone-certification-program/",
+ "why": "crbug.com/242544"
+ },
+ {
+ "url": "http://nytimes.com/",
+ "why": "Top news site"
+ },
+ {
+ "url": "http://iphone.capitolvolkswagen.com/index.htm#new-inventory_p_2Fsb-new_p_2Ehtm_p_3Freset_p_3DInventoryListing",
+ "why": "Typical mobile business site",
+ "wait_for_element_with_text": "Next 35"
+ },
+ {
+ "url": "http://gsp.ro",
+ "why": "crbug.com/149958"
+ },
+ {
+ "url": "http://cuteoverload.com",
+ "why": "Image-heavy site"
+ },
+ {
+ "url": "http://theverge.com",
+ "why": "Top tech blog"
+ },
+ {
+ "url": "http://www.theverge.com/2012/10/28/3568746/amazon-7-inch-fire-hd-ipad-mini-ad-ballsy",
+ "why": "Top tech blog",
+ "wait_for_javascript_expression": "window.Chorus !== undefined && window.Chorus.Comments !== undefined && window.Chorus.Comments.Json !== undefined && (window.Chorus.Comments.loaded || window.Chorus.Comments.Json.load_comments())"
+ },
+ {
+ "url": "http://www.cnn.com/2012/10/03/politics/michelle-obama-debate/index.html",
+ "why": "Top news site",
+ "wait_seconds": 8
+ },
+ {
+ "url": "http://digg.com",
+ "why": "Top tech site"
+ },
+ {
+ "url": "https://www.google.com/#hl=en&q=barack+obama",
+ "why": "Top Google property; a Google tab is often open"
+ },
+ {
+ "url": "https://plus.google.com/app/basic/110031535020051778989/posts?source=apppromo",
+ "why": "Social; top Google property; Public profile; infinite scrolls",
+ "smoothness": {
+ "action": "scroll",
+ "scroll_is_infinite": true
+ }
+ },
+ {
+ "url": "https://facebook.com/barackobama",
+ "why": "#1 (Alexa global)",
+ "wait_for_javascript_expression": "document.getElementById('timelineBody') !== null"
+ },
+ {
+ "url": "http://m.youtube.com/watch?v=9hBpF_Zj4OA",
+ "why": "#3 (Alexa global)",
+ "wait_for_javascript_expression": "document.getElementById('paginatortarget') !== null"
+ },
+ {
+ "name": "Blogger",
+ "url": "http://googlewebmastercentral.blogspot.com/",
+ "why": "#11 (Alexa global), google property; some blogger layouts have infinite scroll but more interesting"
+ },
+ {
+ "name": "Wordpress",
+ "url": "http://en.blog.wordpress.com/2012/09/04/freshly-pressed-editors-picks-for-august-2012/",
+ "why": "#18 (Alexa global), Picked an interesting post"
+ },
+ {
+ "name": "LinkedIn",
+ "url": "https://www.linkedin.com/in/linustorvalds",
+ "why": "#12 (Alexa global),Public profile",
+ "post_navigate_javascript_to_execute": "getAppJs.noApp();",
+ "wait_for_javascript_expression": "document.getElementById('profile-view-scroller') !== null"
+ },
+ {
+ "name": "Wikipedia (1 tab)",
+ "url": "http://en.wikipedia.org/wiki/Wikipedia",
+ "why": "#6 (Alexa) most visited worldwide, picked an interesting page"
+ },
+ {
+ "disabled": "Forbidden (Rate Limit Exceeded)",
+ "name": "Twitter",
+ "url": "http://twitter.com/katyperry",
+ "why": "#8 (Alexa global), picked an interesting page"
+ },
+ {
+ "name": "Pinterest",
+ "url": "http://pinterest.com",
+ "why": "#37 (Alexa global)"
+ },
+ {
+ "disabled": "Fails often; crbug.com/249722",
+ "name": "ESPN",
+ "url": "http://espn.go.com",
+ "why": "#1 sports"
+ },
+ {
+ "url": "http://news.yahoo.com",
+ "why": "#1 news worldwide (Alexa global)"
+ },
+ {
+ "url": "http://www.cnn.com",
+ "why": "#2 news worldwide"
+ },
+ {
+ "url": "http://www.amazon.com/gp/aw/s/ref=is_box_?k=nicolas+cage",
+ "why": "#1 world commerce website by visits; #3 commerce in the US by time spent"
+ },
+ {
+ "url": "http://shop.mobileweb.ebay.com/searchresults?kw=viking+helmet",
+ "why": "#1 commerce website by time spent by users in US"
+ },
+ {
+ "url": "http://www.booking.com/searchresults.html?src=searchresults&latitude=65.0500&longitude=25.4667",
+ "why": "#1 Alexa recreation"
+ },
+ {
+ "url": "http://answers.yahoo.com/question/index?qid=20110117024343AAopj8f",
+ "why": "#1 Alexa reference"
+ },
+ {
+ "url": "http://sports.yahoo.com/",
+ "why": "#1 Alexa sports"
+ },
+ {
+ "url": "http://techcrunch.com",
+ "why": "Top tech blog"
+ },
+ {
+ "url": "https://mail.google.com/mail/",
+ "why": "productivity, top google properties",
+ "credentials": "google",
+ "wait_for_element_with_text": "Inbox",
+ "smoothness": {
+ "action": "scroll",
+ "scrollable_element_function": "function(callback) { callback(document.getElementById('views').childNodes[1].firstChild); }"
+ }
+ },
+ {
+ "url": "https://www.google.com/calendar/",
+ "why": "productivity, top google properties",
+ "credentials": "google",
+ "smoothness": {
+ "action": "scroll",
+ "scrollable_element_function": "function(callback) { callback(document.getElementById('scrolltimedeventswk')); }"
+ }
+ },
+ {
+ "url": "http://mlb.mlb.com/index.jsp",
+ "why": "#6 Alexa sports"
+ },
+ {
+ "url": "http://www.sfgate.com/",
+ "why": "#14 Alexa California"
+ },
+ {
+ "url": "http://slashdot.org/",
+ "why": "crbug.com/169827"
+ },
+ {
+ "url": "http://worldjournal.com/",
+ "why": "Non-latin character set"
+ },
+ {
+ "url": "http://www.wowwiki.com/World_of_Warcraft:_Mists_of_Pandaria",
+ "why": "Mobile wiki"
+ },
+ {
+ "url": "http://online.wsj.com/home-page",
+ "why": "#15 Alexa news"
+ },
+ {
+ "url": "http://www.deviantart.com/",
+ "why": "Image-heavy mobile site"
+ },
+ {
+ "url": "http://www.baidu.com/s?wd=barack+obama&rsv_bp=0&rsv_spt=3&rsv_sug3=9&rsv_sug=0&rsv_sug4=3824&rsv_sug1=3&inputT=4920",
+ "why": "Top search engine"
+ },
+ {
+ "url": "http://www.bing.com/search?q=sloths",
+ "why": "Top search engine"
+ },
+ {
+ "url": "http://www.reddit.com/r/programming/comments/1g96ve",
+ "why": "#5 Alexa news"
+ },
+ {
+ "url": "http://www.boingboing.net",
+ "why": "Problematic use of fixed position elements"
+ },
+ {
+ "url": "http://groupcloned.com",
+ "why": "crbug.com/172906",
+ "wait_for_javascript_expression": "document.getElementById('element-19') !== null && document.getElementById('element-19').contentDocument.getElementById('element-22') !== null",
+ "wait_seconds": 5,
+ "smoothness": {
+ "action": "scroll",
+ "scroll_requires_touch": true,
+ "remaining_scroll_distance_function": "function() { return Math.max(0, 1250 + document.getElementById('element-19').contentDocument.getElementById('element-22').getBoundingClientRect().top); }"
+ }
+ },
+ {
+ "url": "http://mobile-news.sandbox.google.com/news/p#2",
+ "why": "crbug.com/223726",
+ "wait_for_javascript_expression": "document.getElementById(':h') !== null",
+ "wait_seconds": 5,
+ "smoothness": {
+ "action": "scroll",
+ "scroll_requires_touch": true,
+ "scrollable_element_function": "function(callback) { callback(document.getElementById(':5')); }",
+ "remaining_scroll_distance_function": "function() { return Math.max(0, 1500 + document.getElementById(':h').getBoundingClientRect().top); }"
+ }
+ },
+ {
+ "disabled": "Doesn't scroll; crbug.com/249736",
+ "url": "http://forecast.io",
+ "why": "crbug.com/231413"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/mobile_memory.json b/chromium/tools/perf/page_sets/mobile_memory.json
new file mode 100644
index 00000000000..57884749e7f
--- /dev/null
+++ b/chromium/tools/perf/page_sets/mobile_memory.json
@@ -0,0 +1,14 @@
+{
+ "description": "Mobile sites with interesting memory characteristics",
+ "archive_data_file": "../data/mobile_memory.json",
+ "credentials_path": "../data/credentials.json",
+ "user_agent_type": "mobile",
+ "reload_and_gc": [{"action": "reload", "wait_seconds": 15}, {"action": "js_collect_garbage"}],
+ "stress_memory": { "action": "reload_and_gc", "repeat": 3 },
+ "pages": [
+ {
+ "url": "https://mail.google.com/mail/mu",
+ "credentials": "google"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/alexa_us.json b/chromium/tools/perf/page_sets/page_cycler/alexa_us.json
new file mode 100644
index 00000000000..106866a78f0
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/alexa_us.json
@@ -0,0 +1,26 @@
+{
+ "description": "Alexa US page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/alexa_us"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/alexa_us/accountservices.passport.net/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/sfbay.craigslist.org/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.amazon.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.aol.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.bbc.co.uk/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.blogger.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.cnn.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.ebay.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.flickr.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.friendster.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.go.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.google.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.imdb.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.megaupload.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.msn.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.myspace.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.orkut.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.wikipedia.org/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.xanga.com/" },
+ { "url": "file:///../../../../data/page_cycler/alexa_us/www.youtube.com/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/bloat.json b/chromium/tools/perf/page_sets/page_cycler/bloat.json
new file mode 100644
index 00000000000..a42ce32f7a6
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/bloat.json
@@ -0,0 +1,7 @@
+{
+ "description": "Bloat page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/bloat"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/bloat/gmail_load_cleardot/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/dhtml.json b/chromium/tools/perf/page_sets/page_cycler/dhtml.json
new file mode 100644
index 00000000000..04e91e94de3
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/dhtml.json
@@ -0,0 +1,23 @@
+{
+ "description": "DHTML page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/dhtml"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/dhtml/colorfade/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/diagball/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/fadespacing/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/imageslide/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/layers1/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/layers2/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/layers4/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/layers5/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/layers6/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/meter/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/movingtext/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/mozilla/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/replaceimages/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/scrolling/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/slidein/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/slidingballs/" },
+ { "url": "file:///../../../../data/page_cycler/dhtml/zoom/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/dom.json b/chromium/tools/perf/page_sets/page_cycler/dom.json
new file mode 100644
index 00000000000..e2cb7502561
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/dom.json
@@ -0,0 +1,15 @@
+{
+ "description": "DOM page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/dom"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/dom/HTMLDocument_write/" },
+ { "url": "file:///../../../../data/page_cycler/dom/Document_getElementById/" },
+ { "url": "file:///../../../../data/page_cycler/dom/DOMWindow_document/" },
+ { "url": "file:///../../../../data/page_cycler/dom/DOMWindow_window/" },
+ { "url": "file:///../../../../data/page_cycler/dom/Element_getAttribute/" },
+ { "url": "file:///../../../../data/page_cycler/dom/HTMLCollection_length/" },
+ { "url": "file:///../../../../data/page_cycler/dom/HTMLElement_className/" },
+ { "url": "file:///../../../../data/page_cycler/dom/HTMLElement_id/" },
+ { "url": "file:///../../../../data/page_cycler/dom/NodeList_length/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/indexed_db/basic_insert.json b/chromium/tools/perf/page_sets/page_cycler/indexed_db/basic_insert.json
new file mode 100644
index 00000000000..f7caf72a53b
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/indexed_db/basic_insert.json
@@ -0,0 +1,8 @@
+{
+ "description": "Basic insert IndexedDB page_cycler benchmark",
+ "serving_dirs": ["../../../../../tools/page_cycler/indexed_db/basic_insert",
+ "../../../../../tools/page_cycler/indexed_db/common.js"],
+ "pages": [
+ { "url": "file:///../../../../../tools/page_cycler/indexed_db/basic_insert/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/intl1.json b/chromium/tools/perf/page_sets/page_cycler/intl1.json
new file mode 100644
index 00000000000..97c206e536c
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/intl1.json
@@ -0,0 +1,62 @@
+{
+ "description": "Intl1 page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/intl1"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/intl1/126.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/2ch.net/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/6park.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/affili.net/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/allegro.pl/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/apeha.ru/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/baidu.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/bbs.wefong.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/blog.skyrock.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/cmfu.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/cn.yahoo.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/contra.gr/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/dtiblog.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/el.wikipedia.org/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/elmundo.es/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/ettoday.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/exblog.jp/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/excite.co.jp/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/fc2.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/fora.pl/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/free.fr/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/golem.de/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/goo.ne.jp/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/haberturk.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/hatena.ne.jp/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/home.altervista.org/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/hurriyet.com.tr/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/jugem.jp/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/kakaku.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/mixi.jp/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/naftemporiki.gr/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/narod.yandex.ru/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/news.163.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/partyflock.nl/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/pchome.com.tw/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/phoenixtv.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/photofile.ru/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/pl.wikipedia.org/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/ricardo.ch/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/ru.wikipedia.org/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/ruten.com.tw/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/sport24.gr/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/terra.es/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/udn.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/uwants.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/voila.fr/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.alice.it/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.amazon.co.jp/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.auction.co.kr/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.chinaren.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.chosun.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.danawa.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.daum.net/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.dcinside.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/www.eastmoney.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl1/zol.com.cn/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/intl2.json b/chromium/tools/perf/page_sets/page_cycler/intl2.json
new file mode 100644
index 00000000000..b3520b75b2d
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/intl2.json
@@ -0,0 +1,36 @@
+{
+ "description": "Intl2 page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/intl2"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/intl2/arabicnews.google.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/bn.wikipedia.org/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/exteen.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/farsnews.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/hindi.webdunia.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/in.telugu.yahoo.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/isna.ir/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/kapook.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/kooora.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/manager.co.th/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/masrawy.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/ml.wikipedia.org/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/msn.co.il/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/news.bbc.co.uk/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/news.google.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/sh3bwah.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/sgkalesh.blogspot.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/tapuz.co.il/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/thaimisc.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/vietnamnet.vn/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/vnexpress.net/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/walla.co.il/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/www.aljayyash.net/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/www.bbc.co.uk/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/www.google.com.sa/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/www.islamweb.net/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/www.mthai.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/www.startimes2.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/www.jagran.com/" },
+ { "url": "file:///../../../../data/page_cycler/intl2/ynet.co.il/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/morejs.json b/chromium/tools/perf/page_sets/page_cycler/morejs.json
new file mode 100644
index 00000000000..bb8db890684
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/morejs.json
@@ -0,0 +1,15 @@
+{
+ "description": "More JS page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/morejs"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/morejs/blog.chromium.org/" },
+ { "url": "file:///../../../../data/page_cycler/morejs/dev.chromium.org/" },
+ { "url": "file:///../../../../data/page_cycler/morejs/googleblog.blogspot.com1/" },
+ { "url": "file:///../../../../data/page_cycler/morejs/googleblog.blogspot.com2/" },
+ { "url": "file:///../../../../data/page_cycler/morejs/test.blogspot.com/" },
+ { "url": "file:///../../../../data/page_cycler/morejs/www.igoogle.com/" },
+ { "url": "file:///../../../../data/page_cycler/morejs/www.techcrunch.com/" },
+ { "url": "file:///../../../../data/page_cycler/morejs/www.webkit.org/" },
+ { "url": "file:///../../../../data/page_cycler/morejs/www.yahoo.com/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/morejsnp.json b/chromium/tools/perf/page_sets/page_cycler/morejsnp.json
new file mode 100644
index 00000000000..926590a01a1
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/morejsnp.json
@@ -0,0 +1,15 @@
+{
+ "description": "Morejsnp page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/morejsnp"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/morejsnp/blog.chromium.org/" },
+ { "url": "file:///../../../../data/page_cycler/morejsnp/dev.chromium.org/" },
+ { "url": "file:///../../../../data/page_cycler/morejsnp/googleblog.blogspot.com1/" },
+ { "url": "file:///../../../../data/page_cycler/morejsnp/googleblog.blogspot.com2/" },
+ { "url": "file:///../../../../data/page_cycler/morejsnp/test.blogspot.com/" },
+ { "url": "file:///../../../../data/page_cycler/morejsnp/www.igoogle.com/" },
+ { "url": "file:///../../../../data/page_cycler/morejsnp/www.techcrunch.com/" },
+ { "url": "file:///../../../../data/page_cycler/morejsnp/www.webkit.org/" },
+ { "url": "file:///../../../../data/page_cycler/morejsnp/www.yahoo.com/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/moz.json b/chromium/tools/perf/page_sets/page_cycler/moz.json
new file mode 100644
index 00000000000..ed6b17246cf
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/moz.json
@@ -0,0 +1,47 @@
+{
+ "description": "Moz page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/moz"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/moz/bugzilla.mozilla.org/" },
+ { "url": "file:///../../../../data/page_cycler/moz/espn.go.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/home.netscape.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/hotwired.lycos.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/lxr.mozilla.org/" },
+ { "url": "file:///../../../../data/page_cycler/moz/my.netscape.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/news.cnet.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/slashdot.org/" },
+ { "url": "file:///../../../../data/page_cycler/moz/vanilla-page/" },
+ { "url": "file:///../../../../data/page_cycler/moz/web.icq.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.altavista.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.amazon.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.aol.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.apple.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.cnn.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.compuserve.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.digitalcity.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.ebay.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.excite.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.expedia.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.google.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.iplanet.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.mapquest.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.microsoft.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.moviefone.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.msn.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.msnbc.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.nytimes.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.nytimes.com_Table/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.quicken.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.spinner.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.sun.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.time.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.tomshardware.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.travelocity.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.voodooextreme.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.w3.org_DOML2Core/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.wired.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.yahoo.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.zdnet.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz/www.zdnet.com_Gamespot.com/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/page_cycler/moz2.json b/chromium/tools/perf/page_sets/page_cycler/moz2.json
new file mode 100644
index 00000000000..fd1e6ec741d
--- /dev/null
+++ b/chromium/tools/perf/page_sets/page_cycler/moz2.json
@@ -0,0 +1,47 @@
+{
+ "description": "Moz2 page_cycler benchmark",
+ "serving_dirs": ["../../../../data/page_cycler/moz2"],
+ "pages": [
+ { "url": "file:///../../../../data/page_cycler/moz2/bugzilla.mozilla.org/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/espn.go.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/home.netscape.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/hotwired.lycos.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/lxr.mozilla.org/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/my.netscape.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/news.cnet.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/slashdot.org/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/vanilla-page/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/web.icq.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.altavista.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.amazon.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.aol.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.apple.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.cnn.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.compuserve.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.digitalcity.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.ebay.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.excite.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.expedia.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.google.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.iplanet.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.mapquest.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.microsoft.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.moviefone.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.msn.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.msnbc.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.nytimes.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.nytimes.com_Table/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.quicken.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.spinner.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.sun.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.time.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.tomshardware.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.travelocity.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.voodooextreme.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.w3.org_DOML2Core/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.wired.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.yahoo.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.zdnet.com/" },
+ { "url": "file:///../../../../data/page_cycler/moz2/www.zdnet.com_Gamespot.com/" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/pica.json b/chromium/tools/perf/page_sets/pica.json
new file mode 100644
index 00000000000..2315276805a
--- /dev/null
+++ b/chromium/tools/perf/page_sets/pica.json
@@ -0,0 +1,16 @@
+{
+ "description": "Pica demo app for the Polymer UI toolkit",
+ "archive_data_file": "../data/pica.json",
+ "pages": [
+ { "url": "http://www.polymer-project.org/polymer-all/projects/pica/index.html",
+ "script_to_evaluate_on_commit":
+ "document.addEventListener('WebComponentsReady', function(){var unused = document.body.offsetHeight; window.__pica_load_time = performance.now(); setTimeout(function(){window.__web_components_ready=true}, 1000)})",
+ "wait_for_javascript_expression": "window.__web_components_ready",
+ "smoothness": {
+ "action": "tap_element",
+ "find_element_expression": "document.querySelector('pi-app').$.Topics.$.topics.$.container.querySelector('.item > .card')",
+ "wait_for_event": "g-panels-select"
+ }
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/top_10.json b/chromium/tools/perf/page_sets/top_10.json
new file mode 100644
index 00000000000..b14ae24b495
--- /dev/null
+++ b/chromium/tools/perf/page_sets/top_10.json
@@ -0,0 +1,62 @@
+{
+ "description": "10 Pages chosen from Alexa top sites.",
+ "archive_data_file": "../data/top_10.json",
+ "credentials_path": "../data/credentials.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "https://www.google.com/#hl=en&q=barack+obama",
+ "why": "top google property; a google tab is often open",
+ "wait_for_element_with_text": "Next"
+ },
+ {
+ "url": "https://mail.google.com/mail/",
+ "why": "productivity, top google properties",
+ "credentials": "google",
+ "wait_for_javascript_expression": "window.gmonkey !== undefined && document.getElementById('gb') !== null"
+ },
+ {
+ "url": "https://www.google.com/calendar/",
+ "why": "productivity, top google properties",
+ "credentials": "google",
+ "wait_for_element_with_selector": "div[class~=\"navForward\"]",
+ "post_navigate_javascript_to_execute": "(function() { var elem = document.createElement('meta');elem.name='viewport';elem.content='initial-scale=1';document.body.appendChild(elem); })();",
+ "wait_seconds": 2
+ },
+ {
+ "url": "http://www.youtube.com",
+ "why": "#3 (Alexa global)",
+ "wait_seconds": 2,
+ "credentials": "google"
+ },
+ {
+ "name": "Facebook",
+ "url": "http://www.facebook.com/barackobama",
+ "why": "top social,Public profile",
+ "credentials": "facebook",
+ "wait_for_element_with_text": "About"
+ },
+ {
+ "name": "Wikipedia (1 tab)",
+ "url": "http://en.wikipedia.org/wiki/Wikipedia",
+ "why": "#6 (Alexa) most visited worldwide,Picked an interesting page"
+ },
+ {
+ "url": "http://www.amazon.com",
+ "why": "#1 world commerce website by visits; #3 commerce in the US by time spent"
+ },
+ {
+ "url": "http://www.yahoo.com/",
+ "why": "#4 Alexa"
+ },
+ {
+ "url": "http://www.bing.com/",
+ "why": "#16 Alexa"
+ },
+ {
+ "url": "http://www.ask.com/",
+ "why": "#20 Alexa"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/top_25.json b/chromium/tools/perf/page_sets/top_25.json
new file mode 100644
index 00000000000..3f47fa6f30f
--- /dev/null
+++ b/chromium/tools/perf/page_sets/top_25.json
@@ -0,0 +1,413 @@
+{
+ "description": "Pages hand-picked for 2012 CrOS scrolling tuning efforts.",
+ "archive_data_file": "../data/top_25.json",
+ "credentials_path": "../data/credentials.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "https://www.google.com/#hl=en&q=barack+obama",
+ "why": "top google property; a google tab is often open",
+ "wait_for_element_with_text": "Next",
+ "stress_memory": [
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Next",
+ "wait_for_href_change": true,
+ "wait_for_element_with_text": "Next"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Next",
+ "wait_for_href_change": true,
+ "wait_for_element_with_text": "Next"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Next",
+ "wait_for_href_change": true,
+ "wait_for_element_with_text": "Previous"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Previous",
+ "wait_for_href_change": true,
+ "wait_for_element_with_text": "Previous"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Previous",
+ "wait_for_href_change": true,
+ "wait_for_element_with_text": "Previous"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Previous",
+ "wait_for_href_change": true,
+ "wait_for_element_with_text": "Images"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Images",
+ "wait_for_href_change": true,
+ "wait_for_element_with_text": "Images"
+ }
+ ]
+ },
+ {
+ "url": "https://mail.google.com/mail/",
+ "why": "productivity, top google properties",
+ "credentials": "google",
+ "wait_for_javascript_expression": "window.gmonkey !== undefined && document.getElementById('gb') !== null",
+ "smoothness": {
+ "action": "scroll",
+ "scrollable_element_function": "function(callback) { gmonkey.load('2.0', function(api) { callback(api.getScrollableElement()); }); }"
+ },
+ "stress_memory": [
+ {
+ "action": "click_element",
+ "selector": "a[href=\"https://mail.google.com/mail/u/0/?shva=1#starred\"]",
+ "wait_for_href_change": true
+ },
+ {
+ "action": "click_element",
+ "selector": "a[href=\"https://mail.google.com/mail/u/0/?shva=1#inbox\"]",
+ "wait_for_href_change": true
+ }
+ ]
+ },
+ {
+ "url": "https://www.google.com/calendar/",
+ "why": "productivity, top google properties",
+ "credentials": "google",
+ "wait_for_element_with_selector": "div[class~=\"navForward\"]",
+ "post_navigate_javascript_to_execute": "(function() { var elem = document.createElement('meta');elem.name='viewport';elem.content='initial-scale=1';document.body.appendChild(elem); })();",
+ "wait_seconds": 2,
+ "smoothness": {
+ "action": "scroll",
+ "scrollable_element_function": "function(callback) { callback(document.getElementById('scrolltimedeventswk')); }"
+ },
+ "stress_memory": [
+ {
+ "action": "click_element",
+ "selector": "div[class~=\"navForward\"]",
+ "wait_for_seconds": 2,
+ "wait_for_element_with_selector": "div[class~=\"navForward\"]"
+ },
+ {
+ "action": "click_element",
+ "selector": "div[class~=\"navForward\"]",
+ "wait_for_seconds": 2,
+ "wait_for_element_with_selector": "div[class~=\"navForward\"]"
+ },
+ {
+ "action": "click_element",
+ "selector": "div[class~=\"navForward\"]",
+ "wait_for_seconds": 2,
+ "wait_for_element_with_selector": "div[class~=\"navForward\"]"
+ },
+ {
+ "action": "click_element",
+ "selector": "div[class~=\"navForward\"]",
+ "wait_for_seconds": 2,
+ "wait_for_element_with_selector": "div[class~=\"navBack\"]"
+ },
+ {
+ "action": "click_element",
+ "selector": "div[class~=\"navBack\"]",
+ "wait_for_seconds": 2,
+ "wait_for_element_with_selector": "div[class~=\"navBack\"]"
+ },
+ {
+ "action": "click_element",
+ "selector": "div[class~=\"navBack\"]",
+ "wait_for_seconds": 2,
+ "wait_for_element_with_selector": "div[class~=\"navBack\"]"
+ },
+ {
+ "action": "click_element",
+ "selector": "div[class~=\"navBack\"]",
+ "wait_for_seconds": 2,
+ "wait_for_element_with_selector": "div[class~=\"navBack\"]"
+ },
+ {
+ "action": "click_element",
+ "selector": "div[class~=\"navBack\"]",
+ "wait_for_seconds": 2,
+ "wait_for_element_with_selector": "div[class~=\"navBack\"]"
+ }
+ ]
+ },
+ {
+ "url": "https://drive.google.com",
+ "why": "productivity, top google properties",
+ "credentials": "google",
+ "wait_for_javascript_expression": "document.getElementsByClassName('doclistview-list').length",
+ "smoothness": {
+ "action": "scroll",
+ "scrollable_element_function": "function(callback) { callback(document.getElementsByClassName('doclistview-list')[0]); }"
+ }
+ },
+ {
+ "name": "Docs (1 open document tab)",
+ "url": "https://docs.google.com/document/d/1X-IKNjtEnx-WW5JIKRLsyhz5sbsat3mfTpAPUSX3_s4/view",
+ "why": "productivity, top google properties; Sample doc in the link",
+ "credentials": "google",
+ "wait_for_javascript_expression": "document.getElementsByClassName('kix-appview-editor').length",
+ "wait_seconds": 2,
+ "smoothness": {
+ "action": "scroll",
+ "scrollable_element_function": "function(callback) { callback(document.getElementsByClassName('kix-appview-editor')[0]); }"
+ }
+ },
+ {
+ "url": "https://plus.google.com/110031535020051778989/posts",
+ "why": "social; top google property; Public profile; infinite scrolls",
+ "credentials": "google",
+ "wait_for_element_with_text": "Home",
+ "smoothness": {
+ "action": "scroll",
+ "scroll_is_infinite": true
+ },
+ "stress_memory": [
+ {
+ "action": "click_element",
+ "text": "Home",
+ "wait_seconds": 2,
+ "wait_for_element_with_text": "Profile"
+ },
+ {
+ "action": "click_element",
+ "text": "Profile",
+ "wait_seconds": 2,
+ "wait_for_element_with_text": "Explore"
+ },
+ {
+ "action": "click_element",
+ "text": "Explore",
+ "wait_seconds": 2,
+ "wait_for_element_with_text": "Events"
+ },
+ {
+ "action": "click_element",
+ "text": "Events",
+ "wait_seconds": 2,
+ "wait_for_element_with_text": "Communities"
+ },
+ {
+ "action": "click_element",
+ "text": "Communities",
+ "wait_seconds": 2,
+ "wait_for_element_with_text": "Home"
+ }
+ ]
+ },
+ {
+ "url": "http://www.youtube.com",
+ "why": "#3 (Alexa global)",
+ "wait_seconds": 2,
+ "credentials": "google"
+ },
+ {
+ "name": "Blogger",
+ "url": "http://googlewebmastercentral.blogspot.com/",
+ "why": "#11 (Alexa global), google property; some blogger layouts have infinite scroll but more interesting",
+ "wait_for_element_with_text": "accessibility",
+ "stress_memory": [
+ {
+ "action": "click_element",
+ "text": "accessibility",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "advanced"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "advanced",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "beginner"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "beginner",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "Home"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Home",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "Home"
+ }
+ ]
+ },
+ {
+ "name": "Wordpress",
+ "url": "http://en.blog.wordpress.com/2012/09/04/freshly-pressed-editors-picks-for-august-2012/",
+ "why": "#18 (Alexa global), Picked an interesting post",
+ "wait_for_element_with_selector": "a[href=\"http://en.blog.wordpress.com/2012/08/30/new-themes-able-and-sight/\"]",
+ "stress_memory": [
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "selector": "a[href=\"http://en.blog.wordpress.com/2012/08/30/new-themes-able-and-sight/\"]",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "Features"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "Features",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "News"
+ },
+ { "action": "scroll" },
+ {
+ "action": "click_element",
+ "text": "News",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "News"
+ },
+ { "action": "scroll" }
+ ]
+ },
+ {
+ "name": "Facebook",
+ "url": "http://www.facebook.com/barackobama",
+ "why": "top social,Public profile",
+ "credentials": "facebook",
+ "wait_for_element_with_text": "About",
+ "smoothness": {
+ "action": "scroll",
+ "scroll_is_infinite": true
+ },
+ "stress_memory": [
+ {
+ "action": "click_element",
+ "text": "About",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "The Audacity of Hope"
+ },
+ {
+ "action": "click_element",
+ "text": "The Audacity of Hope",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "Back to Barack Obama's Timeline"
+ },
+ {
+ "action": "click_element",
+ "text": "Back to Barack Obama's Timeline",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "About"
+ },
+ {
+ "action": "click_element",
+ "text": "About",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "Elected to U.S. Senate"
+ },
+ {
+ "action": "click_element",
+ "text": "Elected to U.S. Senate",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "Home"
+ },
+ {
+ "action": "click_element",
+ "text": "Home",
+ "wait_for_navigate": true,
+ "wait_for_element_with_text": "Home"
+ }
+ ]
+ },
+ {
+ "name": "LinkedIn",
+ "url": "http://www.linkedin.com/in/linustorvalds",
+ "why": "#12 (Alexa global),Public profile"
+ },
+ {
+ "name": "Wikipedia (1 tab)",
+ "url": "http://en.wikipedia.org/wiki/Wikipedia",
+ "why": "#6 (Alexa) most visited worldwide,Picked an interesting page"
+ },
+ {
+ "name": "Twitter",
+ "url": "https://twitter.com/katyperry",
+ "why": "#8 (Alexa global),Picked an interesting page",
+ "wait_seconds": 2,
+ "smoothness": {
+ "action": "scroll",
+ "scroll_is_infinite": true
+ }
+ },
+ {
+ "name": "Pinterest",
+ "url": "http://pinterest.com",
+ "why": "#37 (Alexa global)",
+ "smoothness": {
+ "action": "scroll",
+ "scroll_is_infinite": true
+ }
+ },
+ {
+ "name": "ESPN",
+ "url": "http://espn.go.com",
+ "why": "#1 sports",
+ "smoothness": {
+ "action": "scroll",
+ "left_start_percentage": 0.1
+ }
+ },
+ {
+ "url": "http://news.yahoo.com",
+ "why": "#1 news worldwide (Alexa global)"
+ },
+ {
+ "url": "http://www.cnn.com",
+ "why": "#2 news worldwide"
+ },
+ {
+ "name": "Weather.com",
+ "url": "http://www.weather.com/weather/right-now/Mountain+View+CA+94043",
+ "why": "#7 (Alexa news); #27 total time spent,Picked interesting page"
+ },
+ {
+ "url": "http://www.amazon.com",
+ "why": "#1 world commerce website by visits; #3 commerce in the US by time spent"
+ },
+ {
+ "url": "http://www.ebay.com",
+ "why": "#1 commerce website by time spent by users in US"
+ },
+ {
+ "url": "http://games.yahoo.com",
+ "why": "#1 games according to Alexa (with actual games in it)",
+ "wait_seconds": 2
+ },
+ {
+ "url": "http://booking.com",
+ "why": "#1 Alexa recreation"
+ },
+ {
+ "url": "http://answers.yahoo.com",
+ "why": "#1 Alexa reference"
+ },
+ {
+ "url": "http://sports.yahoo.com/",
+ "why": "#1 Alexa sports"
+ },
+ {
+ "url": "http://techcrunch.com",
+ "why": "top tech blog"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_animation_cases.json b/chromium/tools/perf/page_sets/tough_animation_cases.json
new file mode 100644
index 00000000000..1e26bcf1342
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_animation_cases.json
@@ -0,0 +1,22 @@
+{
+ "description": "A collection of animation performance tests",
+ "smoothness": { "action": "wait", "condition": "duration", "seconds": 5 },
+ "pages": [
+ {
+ "url": "file:///tough_animation_cases/keyframed_animations.html",
+ "why": "Tests various keyframed animations."
+ },
+ {
+ "url": "file:///tough_animation_cases/transform_transitions.html",
+ "why": "Tests various transitions."
+ },
+ {
+ "url": "http://ie.microsoft.com/testdrive/performance/robohornetpro/",
+ "why": "Login page is slow because of ineffecient transform operations"
+ },
+ {
+ "url": "file:///tough_animation_cases/transform_transition_js_block.html",
+ "why": "JS execution blocks CSS transition unless initial transform is set"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_animation_cases/keyframed_animations.html b/chromium/tools/perf/page_sets/tough_animation_cases/keyframed_animations.html
new file mode 100644
index 00000000000..114b4f42650
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_animation_cases/keyframed_animations.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ @-webkit-keyframes animation1 {
+ 0% { -webkit-transform: translateX(0px); }
+ 50% { -webkit-transform: translateX(100px); }
+ 100% { -webkit-transform: translateX(0px); }
+ }
+
+ @-webkit-keyframes animation2 {
+ 0% { -webkit-transform: rotate(0deg); }
+ 50% { -webkit-transform: rotate(180deg); }
+ 100% { -webkit-transform: rotate(0deg); }
+ }
+
+ @-webkit-keyframes animation3 {
+ 0% { -webkit-transform: scale(1); }
+ 50% { -webkit-transform: scale(3); }
+ 100% { -webkit-transform: scale(1); }
+ }
+
+ @-webkit-keyframes animation4 {
+ 0% { -webkit-transform: matrix(1, 0, 0, 1, 0, 0); }
+ 50% { -webkit-transform: matrix(-1, 0, 0, -1, 0, 0); }
+ 100% { -webkit-transform: matrix(1, 0, 0, 1, 0, 0); }
+ }
+
+ @-webkit-keyframes animation5 {
+ 0% { -webkit-transform: translateX(0px) scale(8); opacity(1); }
+ 50% { -webkit-transform: translateX(100px) scale(0); opacity(0); }
+ 100% { -webkit-transform: translateX(0px) scale(8); opacity(1); }
+ }
+
+ @-webkit-keyframes animation6 {
+ 0% { -webkit-transform: rotate(0deg); opacity(1); }
+ 50% { -webkit-transform: rotate(180deg); opacity(0); }
+ 100% { -webkit-transform: rotate(0deg); opacity(1); }
+ }
+
+ @-webkit-keyframes animation7 {
+ 0% { -webkit-transform: scale(1); opacity(1); }
+ 50% { -webkit-transform: scale(13); opacity(0); }
+ 100% { -webkit-transform: scale(1); opacity(1); }
+ }
+
+ @-webkit-keyframes animation8 {
+ 0% { -webkit-transform: matrix(1, 0, 0, 1, 0, 0); opacity(1); }
+ 50% { -webkit-transform: matrix(-.5, .5, -.5, -1.2, -150, 100); opacity(0); }
+ 100% { -webkit-transform: matrix(1, 0, 0, 1, 0, 0); opacity(1); }
+ }
+
+ @-webkit-keyframes animation9 {
+ 0% { -webkit-transform: translateX(0px) rotate3d(0, 1, 0, 0deg); }
+ 50% { -webkit-transform: translateX(100px) rotate3d(0, 1, 0, 45deg); }
+ 100% { -webkit-transform: translateX(0px) rotate3d(0, 1, 0, 0deg); }
+ }
+
+ @-webkit-keyframes animation10 {
+ 0% { -webkit-transform: rotate(0deg) rotate3d(0, 1, 0, 0deg); }
+ 50% { -webkit-transform: rotate(180deg) rotate3d(0, 1, 0, 45deg); }
+ 100% { -webkit-transform: rotate(0deg) rotate3d(0, 1, 0, 0deg); }
+ }
+
+ @-webkit-keyframes animation11 {
+ 0% { -webkit-transform: scale(1) rotate3d(0, 1, 0, 0deg); }
+ 50% { -webkit-transform: scale(3) rotate3d(0, 1, 0, 45deg); }
+ 100% { -webkit-transform: scale(1) rotate3d(0, 1, 0, 0deg); }
+ }
+
+ @-webkit-keyframes animation12 {
+ 0% { -webkit-transform: matrix(1, 0, 0, 1, 0, 0) rotate3d(0, 1, 0, 0deg); }
+ 50% { -webkit-transform: matrix(-1, .5, .2, -1, 100, 100) rotate3d(0, 1, 0, 45deg); }
+ 100% { -webkit-transform: matrix(1, 0, 0, 1, 0, 0) rotate3d(0, 1, 0, 0deg); }
+ }
+
+ @-webkit-keyframes animation13 {
+ 0% { -webkit-transform: translateX(0px) rotate3d(1, 1, 1, 0deg) scale(1); opacity(1); }
+ 50% { -webkit-transform: translateX(100px) rotate3d(1, 1, 1, 45deg) scale(-10); opacity(0); }
+ 100% { -webkit-transform: translateX(0px) rotate3d(1, 1, 1, 0deg) scale(1); opacity(1); }
+ }
+
+ @-webkit-keyframes animation14 {
+ 0% { -webkit-transform: rotate(0deg) rotate3d(1, 1, 1, 0deg) translateZ(0px); opacity(1); }
+ 50% { -webkit-transform: rotate(180deg) rotate3d(1, 1, 1, 45deg) translateZ(500px); opacity(0); }
+ 100% { -webkit-transform: rotate(0deg) rotate3d(1, 1, 1, 0deg) translateZ(0px); opacity(1); }
+ }
+
+/* @-webkit-keyframes animation15 { */
+/* 0% { -webkit-transform: translateZ(0px) rotate3d(1, 1, 1, 0deg) rotate(0deg); opacity(1); } */
+/* 50% { -webkit-transform: translateZ(500px) rotate3d(1, 1, 1, 45deg) rotate(180deg); opacity(0); }*/
+/* 100% { -webkit-transform: translateZ(0px) rotate3d(1, 1, 1, 0deg) rotate(0deg); opacity(1); } */
+/* } */
+
+ @-webkit-keyframes animation15 {
+ 0% { -webkit-transform: scale(1) rotate3d(1, 1, 1, 0deg); opacity(1); }
+ 50% { -webkit-transform: scale(3) rotate3d(1, 1, 1, 45deg); opacity(0); }
+ 100% { -webkit-transform: scale(1) rotate3d(1, 1, 1, 0deg); opacity(1); }
+ }
+
+ @-webkit-keyframes animation16 {
+ 0% { -webkit-transform: matrix(10, 0, 0, 10, 0, 0) rotate3d(1, 1, 1, 0deg); opacity(1); }
+ 50% { -webkit-transform: matrix(-1, 0, 0, 0, 0, 0) rotate3d(1, 1, 1, 45deg); opacity(0); }
+ 100% { -webkit-transform: matrix(10, 0, 0, 10, 0, 0) rotate3d(1, 1, 1, 0deg); opacity(1); }
+ }
+
+ div {
+ position: absolute;
+ -webkit-transform-style: preserve-3d;
+ }
+
+ .poster {
+ height: 50px;
+ width: 50px;
+ background-color: gray;
+ -webkit-border-radius: 10px;
+ font-family: 'Georgia', serif;
+ border: 2px solid black;
+ font-size: 42px;
+ font-weight: bold;
+ text-align: center;
+ }
+ </style>
+ <script type="text/javascript">
+ function startExperiment()
+ {
+ for (var i = 0; i < 16; ++i) {
+ var elem = document.getElementById("elem" + i.toString());
+ elem.style.left = (i % 4 * 25 + 5).toString() + "%";
+ elem.style.top = (Math.floor(i / 4) * 25 + 5).toString() + "%";
+ elem.style.webkitAnimationName = "animation" + (i + 1).toString();
+ elem.style.webkitAnimationDuration = "2s";
+ elem.style.webkitAnimationIterationCount = "infinite";
+ }
+ }
+
+ window.addEventListener('load', startExperiment, false);
+ </script>
+</head>
+<body>
+<div id="elem0"><p class="poster">?</p></div>
+<div id="elem1"><p class="poster">?</p></div>
+<div id="elem2"><p class="poster">?</p></div>
+<div id="elem3"><p class="poster">?</p></div>
+<div id="elem4"><p class="poster">?</p></div>
+<div id="elem5"><p class="poster">?</p></div>
+<div id="elem6"><p class="poster">?</p></div>
+<div id="elem7"><p class="poster">?</p></div>
+<div id="elem8"><p class="poster">?</p></div>
+<div id="elem9"><p class="poster">?</p></div>
+<div id="elem10"><p class="poster">?</p></div>
+<div id="elem11"><p class="poster">?</p></div>
+<div id="elem12"><p class="poster">?</p></div>
+<div id="elem13"><p class="poster">?</p></div>
+<div id="elem14"><p class="poster">?</p></div>
+<div id="elem15"><p class="poster">?</p></div>
+</body>
+</html>
+
+
diff --git a/chromium/tools/perf/page_sets/tough_animation_cases/transform_transition_js_block.html b/chromium/tools/perf/page_sets/tough_animation_cases/transform_transition_js_block.html
new file mode 100644
index 00000000000..02dfcdcb1f1
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_animation_cases/transform_transition_js_block.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>JS janking CSS transition</title>
+
+<style>
+ html {
+ font-family: sans-serif;
+ }
+
+ .box {
+ background: green;
+ position: relative;
+ width: 100px;
+ height: 100px;
+ -webkit-transition: -webkit-transform 10s linear;
+ transition: transform 10s linear;
+
+ /* Adding these lines fixes the issue
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ */
+ }
+</style>
+</head>
+<body>
+<div class="box"></div>
+<button class="run">Run</button>
+<script>
+ function jankify() {
+ var start = Date.now();
+ while (Date.now() - start < 250);
+ setTimeout(jankify, 750);
+ }
+
+ var box = document.querySelector('.box');
+
+ window.addEventListener('load', function() {
+ box.style.transform = box.style.WebkitTransform = 'translate3d(500px, 0, 0)'
+ jankify();
+ });
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_animation_cases/transform_transitions.html b/chromium/tools/perf/page_sets/tough_animation_cases/transform_transitions.html
new file mode 100644
index 00000000000..ade40f18a94
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_animation_cases/transform_transitions.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ #animatable {
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100px;
+ width: 100px;
+ background-color: green;
+ -webkit-border-radius: 10px;
+ -webkit-transition: -webkit-transform 1s;
+ }
+
+ #poster {
+ font-family: 'Georgia', serif;
+ font-size: 36px;
+ font-weight: bold;
+ text-align: center;
+ margin-top: 28px;
+ }
+
+ #text {
+ position: absolute;
+ left: 20px;
+ top: 400px;
+ }
+
+ #text > p {
+ font-family: 'Verdana', serif;
+ font-size: 12px;
+ font-weight: bold;
+ }
+ </style>
+ <script type="text/javascript">
+ const initialValues = [
+ "translate3d(100px, 100px, 0px)",
+ "rotate3d(0, 1, 0, 0deg)",
+ "scale3d(1, 1, 1)",
+ "perspective(10000)",
+ "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)",
+ "skew(0deg, 0deg)"
+ ];
+
+ const targetValues = [
+ "translate3d(250px, 250px, 0px)",
+ "rotate3d(0, 1, 0, 30deg)",
+ "scale3d(2, 2, 2)",
+ "perspective(200)",
+ "matrix3d(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)",
+ "skew(10deg, 10deg)"
+ ];
+
+ var i = 1;
+ var iterations = Math.pow(2, initialValues.length);
+ var oldStyle = "";
+
+ // For the buffon needle experiment below.
+ var hits = 0;
+ var trials = 0;
+ var estimate = 0;
+
+ function triggerTransition()
+ {
+ var style = "";
+ var elem = document.getElementById("animatable");
+
+ for (var j = 0; j < initialValues.length; ++j) {
+ if (j > 0)
+ style += " ";
+
+ var values = initialValues;
+ if (Math.floor(i / Math.pow(2, j)) % 2 == 1)
+ values = targetValues;
+
+ style += values[j];
+ }
+
+ elem.style.webkitTransform = style;
+ i++;
+
+ document.getElementById("from").innerHTML = "From:<br> " + oldStyle;
+ document.getElementById("to").innerHTML = "To:<br> " + style;
+ document.getElementById("estimate").innerHTML = "Buffon estimate of pi after " + trials.toString() + " needle drops:<br>" + estimate.toString();
+
+ oldStyle = style;
+
+ if (i < iterations)
+ setTimeout(triggerTransition, 1000);
+ }
+
+ function buffonStep()
+ {
+ for (var step = 0; step < 100000; ++step) {
+ var x = 2.0 * Math.random();
+ x = Math.min(x, 2.0 - x);
+
+ if (Math.cos(Math.PI * Math.random() * 0.5) > x)
+ hits++;
+
+ trials++;
+
+ if (hits > 0)
+ estimate = 2 * trials / hits;
+ }
+
+ if (i < iterations)
+ setTimeout(buffonStep, 0);
+ }
+
+ function startExperiment()
+ {
+ triggerTransition();
+ buffonStep();
+ }
+
+ window.addEventListener('load', startExperiment, false);
+ </script>
+</head>
+<body>
+<div id="animatable"><p id="poster">Hi!</p></div>
+<div id="text">
+ <p id="from">From:</p>
+ <p id="to">To:</p>
+ <p id="estimate">Estimate:</p>
+</div>
+</body>
+</html>
+
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases.json b/chromium/tools/perf/page_sets/tough_canvas_cases.json
new file mode 100644
index 00000000000..dde8ef8cc8e
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases.json
@@ -0,0 +1,40 @@
+{
+ "description": "Self-driven Canvas2D animation examples",
+ "archive_data_file": "../data/tough_canvas_cases.json",
+ "make_javascript_deterministic": false,
+ "smoothness": { "action": "wait", "condition": "duration", "seconds": 5 },
+ "pages": [
+ { "url":"http://mudcu.be/labs/JS1k/BreathingGalaxies.html" },
+ { "url":"http://runway.countlessprojects.com/prototype/performance_test.html" },
+ { "url":"http://geoapis.appspot.com/agdnZW9hcGlzchMLEgtFeGFtcGxlQ29kZRjh1wIM" },
+ { "url":"http://ie.microsoft.com/testdrive/Graphics/HowStuffWorksGears/Default.html" },
+ { "url":"http://ie.microsoft.com/testdrive/Performance/FishIETank/Default.html" },
+ { "url":"http://ie.microsoft.com/testdrive/Performance/SpeedReading/Default.html" },
+ { "url":"http://acko.net/dumpx/996b.html" },
+ { "url":"http://www.kevs3d.co.uk/dev/canvask3d/k3d_test.html" },
+ { "url":"http://www.megidish.net/awjs/" },
+ { "url":"http://ie.microsoft.com/testdrive/Performance/Fireflies/Default.html" },
+ { "url":"http://themaninblue.com/experiment/AnimationBenchmark/canvas/" },
+ { "url":"http://mix10k.visitmix.com/Entry/Details/169" },
+ { "url":"http://www.craftymind.com/factory/guimark2/HTML5ChartingTest.html" },
+ { "url":"http://www.chiptune.com/starfield/starfield.html" },
+ { "url":"http://jarrodoverson.com/static/demos/particleSystem/" },
+ { "url":"http://www.effectgames.com/demos/canvascycle/" },
+ { "url":"http://www.thewildernessdowntown.com/" },
+ { "url":"http://spielzeugz.de/html5/liquid-particles.html" },
+ { "url":"http://hakim.se/experiments/html5/magnetic/02/" },
+ { "url":"http://ie.microsoft.com/testdrive/Performance/LetItSnow/" },
+ { "url":"http://ie.microsoft.com/testdrive/Graphics/WorkerFountains/Default.html" },
+ { "url":"http://ie.microsoft.com/testdrive/Graphics/TweetMap/Default.html" },
+ { "url":"http://ie.microsoft.com/testdrive/Graphics/VideoCity/Default.html" },
+ { "url":"http://ie.microsoft.com/testdrive/Performance/AsteroidBelt/Default.html" },
+ { "url":"http://www.smashcat.org/av/canvas_test/" },
+ { "url": "file:///tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=canvas_sprite&back=canvas" },
+ { "url": "file:///tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=image_with_shadow&back=image" },
+ { "url": "file:///tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=filled_path&back=gradient" },
+ { "url": "file:///tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=text&back=white&ball_count=15" },
+ { "url": "file:///tough_canvas_cases/canvas-animation-no-clear.html" },
+ { "url": "file:///../../../chrome/test/data/perf/canvas_bench/single_image.html" },
+ { "url": "file:///../../../chrome/test/data/perf/canvas_bench/many_images.html" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas-animation-no-clear.html b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas-animation-no-clear.html
new file mode 100644
index 00000000000..2f26384a438
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas-animation-no-clear.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <title>Composited canvases with internal animation</title>
+</head>
+<body>
+<script>
+var size = 2048;
+var numCanvases = 2;
+var canvas = new Array();
+var squareSize = size / numCanvases;
+for (i = 0; i < numCanvases; i++) {
+ var c = document.createElement("canvas");
+ c.width = c.height = size;
+ c.style.left = c.style.top = "0px";
+ c.style.position = "absolute";
+ document.body.appendChild(c);
+ canvas[i] = c;
+}
+
+function redraw() {
+ var i;
+ for (i = 0; i < numCanvases; i++) {
+ var c = canvas[i];
+ var ctx = c.getContext("2d");
+ ctx.fillStyle = "rgba(1, 1, 1, 0.01)";
+ ctx.fillRect(0, 0, size, size);
+ ctx.fillStyle = "rgba(0, 255, 0, 0.5)";
+ ctx.fillRect(Math.random() * c.width, Math.random() * c.height, squareSize, squareSize);
+ }
+ window.setTimeout(redraw, 1);
+}
+window.setTimeout(redraw, 1);
+</script>
+<canvas height="2048" width="2048" style="top: 0px; left: 0px; position: absolute;"></canvas><canvas height="2048" width="2048" style="top: 0px; left: 0px; position: absolute;"></canvas>
+</body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html
new file mode 100644
index 00000000000..a7574f865ae
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <script src="parse_url.js"></script>
+ <script src="bouncing_balls.js"></script>
+ <style>
+ html, body {
+ width: 100%;
+ height: 100%;
+ margin: 0px;
+ padding: 0px;
+ overflow: hidden;
+ }
+ </style>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Canvas 2D frame rate test: bouncing balls</title>
+</head>
+<body>
+
+<canvas id="canvas" width="500" height="500">
+</canvas>
+<img id="ballImage" src="chromium.png" height="0" width="0"></img>
+<img id="backImage" src="kiddie_logo.png" height="0" width="0"></img>
+<script>
+ var canvas = document.getElementById('canvas');
+ var canvasContext = canvas.getContext('2d');
+</script>
+</body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.js
new file mode 100644
index 00000000000..89276b3fe03
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.js
@@ -0,0 +1,176 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// demo parameters
+// maybe overridden in test file
+var numBalls = parseInt(getArgValue('ball_count'));
+if (numBalls == 0 || isNaN(numBalls)) {
+ numBalls = 500;
+}
+var ballDiameter = 30;
+var gravity = 0.5; //screen heights per second^2
+var maxInitVelocity = 0.2;
+var maxAngularVelocity = 5; // rad per second
+var elasticity = 0.7;
+var joltInterval = 1.5;
+
+// globals
+var balls = [];
+var canvasWidth;
+var canvasHeight;
+var borderX;
+var borderY;
+var timeOfLastJolt = 0;
+
+function include(filename) {
+ var head = document.getElementsByTagName('head')[0];
+ var script = document.createElement('script');
+ script.src = filename;
+ script.type = 'text/javascript';
+ head.appendChild(script)
+}
+
+include("bouncing_balls_draw_ball_as_" + getArgValue('ball') + ".js");
+include("bouncing_balls_draw_back_as_" + getArgValue('back') + ".js");
+
+window.requestAnimFrame = (function(){
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function( callback ){
+ window.setTimeout(callback, 1000 / 60);
+ };
+})();
+
+window.onload = init;
+
+function init(){
+ handleResize();
+ for (var i = 0; i < numBalls; i++) {
+ balls.push(new Ball());
+ }
+ window.addEventListener("resize", handleResize, false);
+ drawBallInit(ballDiameter); // externally defined
+ window.requestAnimFrame(updateFrame);
+}
+
+function handleResize() {
+ canvasWidth = window.innerWidth;
+ canvasHeight = window.innerHeight;
+ canvas.setAttribute('width', canvasWidth);
+ canvas.setAttribute('height', canvasHeight);
+ borderX = ballDiameter/canvasWidth;
+ borderY = ballDiameter/canvasHeight;
+ prepareBackground(); // externally defined
+}
+
+function updateFrame() {
+ var now = new Date().getTime() / 1000;
+ var jolt = false;
+ if (now - timeOfLastJolt > joltInterval) {
+ jolt = true;
+ timeOfLastJolt = now;
+ }
+ drawBackground(); // externally defined
+ for (var i = 0; i < numBalls; i++) {
+ balls[i].step(jolt);
+ }
+ window.requestAnimFrame(updateFrame);
+}
+
+function Ball(){
+ var x = borderX + Math.random()*(1-2*borderX);
+ var y = borderY + Math.random()*(1-2*borderY);
+ var angle = Math.PI * 2 * Math.random();
+ var velocityY = Math.random()*maxInitVelocity*2 - maxInitVelocity;
+ var velocityX = Math.random()*maxInitVelocity*2 - maxInitVelocity;
+ var angularVelocity = Math.random()*maxAngularVelocity*2 -
+ maxAngularVelocity;
+ var previousFrameTime = new Date().getTime();
+ var previousBounceTime = 0;
+ var alive = true;
+ function step(jolt) {
+ var curTime = new Date().getTime();
+ var timeStep = (curTime - previousFrameTime) / 1000;
+ previousFrameTime = curTime;
+
+ // handle balls that are no longer bouncing
+ if (!alive) {
+ if (jolt) {
+ // If a jolt is applied, bump the rollong balls enough for them to
+ // reach between 0.75x and 1x the height of the window
+ velocityY = -Math.sqrt(2 * gravity * (1-2 * borderY) * (0.75 + 0.25 *
+ Math.random()))
+ velocityX = Math.random()*maxInitVelocity*2 - maxInitVelocity;
+ angularVelocity = Math.random()*maxAngularVelocity*2 -
+ maxAngularVelocity;
+ alive = true;
+ } else {
+ // rolling on the ground
+ angularVelocity = 2*velocityX*canvasWidth/ballDiameter;
+ }
+ }
+
+ // Compute angular motion
+ angle += timeStep*angularVelocity;
+ // Compute horizontal motion
+ var remainingTime = timeStep;
+ var deltaX = velocityX*remainingTime;
+ while ((x+deltaX) < borderX || (x+deltaX) > (1-borderX)){
+ if ((x+deltaX) < borderX) {
+ // left side bounce
+ remainingTime -= (borderX - x)/velocityX;
+ x = borderX;
+ } else {
+ // right side bounce
+ remainingTime -= ((1-borderX) - x)/velocityX;
+ x = 1 - borderX;
+ }
+ velocityX = -elasticity*velocityX;
+ deltaX = velocityX*remainingTime;
+ }
+ x += deltaX;
+
+ // Compute vertical motion
+ remainingTime = timeStep;
+ var deltaY = alive ? velocityY*timeStep+gravity*timeStep*timeStep/2 : 0;
+ //Handle floor bounces
+ //To make sure the floor is air tight, we must be able to process multiple
+ //bounces per time step to avoid the "tunnel effect".
+ while ((y + deltaY) > (1 - borderY) && alive) {
+ // time to hit floor
+ var c = y-(1-borderY);
+ var b = velocityY;
+ var a = gravity/2;
+ // The greater root is always the right one
+ var subStep = (-b + Math.sqrt(b*b-4*a*c))/(2*a);
+ //velocity after floor hit
+ velocityY = -elasticity*(velocityY + gravity*subStep);
+ remainingTime -= subStep;
+ var bounceTime = curTime - remainingTime;
+ if (bounceTime - previousBounceTime < 0.005){
+ // The number of iterations may not be finite within a timestep
+ // with elasticity < 1. This is due to power series convergence.
+ // To gard against hanging, we treat the ball as rolling on the ground
+ // once time between bounces is less than 5ms
+ alive = false;
+ deltaY = 0;
+ } else {
+ deltaY = velocityY*remainingTime+gravity*remainingTime*remainingTime/2;
+ }
+ previousBounceTime = bounceTime;
+ y = (1 - borderY);
+ }
+ y += deltaY;
+ velocityY += gravity*remainingTime;
+
+ drawBall(x * canvasWidth, y * canvasHeight, angle); // externally defined
+ }
+
+ return {
+ step: step
+ }
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_aligned_canvas.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_aligned_canvas.js
new file mode 100644
index 00000000000..79b1b19fdf9
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_aligned_canvas.js
@@ -0,0 +1,18 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var backImageCanvas;
+
+function prepareBackground() {
+ var backImage = document.getElementById('backImage');
+ backImageCanvas = document.createElement('canvas');
+ backImageCanvas.width = canvasWidth;
+ backImageCanvas.height = canvasHeight;
+ var backContext = backImageCanvas.getContext('2d');
+ backContext.drawImage(backImage, 0, 0, canvasWidth, canvasHeight);
+}
+
+function drawBackground() {
+ canvasContext.drawImage(backImageCanvas, 0, 0);
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_aligned_image_data.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_aligned_image_data.js
new file mode 100644
index 00000000000..94fabf6af0a
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_aligned_image_data.js
@@ -0,0 +1,19 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var backImageData;
+
+function prepareBackground() {
+ var backImage = document.getElementById('backImage');
+ var backImageCanvas = document.createElement('canvas');
+ backImageCanvas.width = canvasWidth;
+ backImageCanvas.height = canvasHeight;
+ var backContext = backImageCanvas.getContext('2d');
+ backContext.drawImage(backImage, 0, 0, canvasWidth, canvasHeight);
+ backImageData = backContext.getImageData(0, 0, canvasWidth, canvasHeight)
+}
+
+function drawBackground() {
+ canvasContext.putImageData(backImageData, 0, 0);
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_canvas.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_canvas.js
new file mode 100644
index 00000000000..0b5b93c8773
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_canvas.js
@@ -0,0 +1,18 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var backImageCanvas;
+
+function prepareBackground() {
+ var backImage = document.getElementById('backImage');
+ backImageCanvas = document.createElement('canvas');
+ backImageCanvas.width = backImage.naturalWidth;
+ backImageCanvas.height = backImage.naturalHeight;
+ var backContext = backImageCanvas.getContext('2d');
+ backContext.drawImage(backImage, 0, 0);
+}
+
+function drawBackground() {
+ canvasContext.drawImage(backImageCanvas, 0, 0, canvasWidth, canvasHeight);
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_gradient.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_gradient.js
new file mode 100644
index 00000000000..3317fa5943c
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_gradient.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+var backGradient;
+function prepareBackground() {
+ backGradient = canvasContext.createLinearGradient(0, 0, canvasWidth, 0);
+ backGradient.addColorStop(0, "#FF4040");
+ backGradient.addColorStop(1, "#40FF40");
+}
+
+function drawBackground() {
+ canvasContext.save();
+ canvasContext.fillStyle = backGradient;
+ canvasContext.fillRect(0, 0, canvasWidth, canvasHeight);
+ canvasContext.restore();
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_image.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_image.js
new file mode 100644
index 00000000000..925dcad47f9
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_image.js
@@ -0,0 +1,13 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var backImage;
+
+function prepareBackground() {
+ backImage = document.getElementById('backImage');
+}
+
+function drawBackground() {
+ canvasContext.drawImage(backImage, 0, 0, canvasWidth, canvasHeight);
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_white.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_white.js
new file mode 100644
index 00000000000..a23608c9a4e
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_back_as_white.js
@@ -0,0 +1,13 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function prepareBackground() {
+}
+
+function drawBackground() {
+ canvasContext.save();
+ canvasContext.fillStyle = "#FFFFFF";
+ canvasContext.fillRect(0, 0, canvasWidth, canvasHeight);
+ canvasContext.restore();
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_canvas_sprite.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_canvas_sprite.js
new file mode 100644
index 00000000000..549564f0fec
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_canvas_sprite.js
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var spriteMap;
+var ballRadius;
+var spriteMapSize = 50;
+
+function drawBallInit(diameter) {
+ ballRadius = diameter / 2;
+ var ballImage = document.getElementById('ballImage');
+ spriteMap = document.createElement("canvas");
+ spriteMap.setAttribute('width', ballDiameter*spriteMapSize + 2);
+ spriteMap.setAttribute('height', ballDiameter + 2);
+ ctx = spriteMap.getContext("2d");
+ ctx.clearRect(0,0, ballDiameter*spriteMapSize + 2, ballDiameter + 2);
+ ctx.translate(ballRadius + 1, ballRadius + 1);
+ for (var i = 0; i < spriteMapSize; i++) {
+ ctx.save();
+ ctx.rotate(i * 2 * Math.PI / spriteMapSize );
+ ctx.drawImage(ballImage, -ballRadius, -ballRadius, ballDiameter,
+ ballDiameter);
+ ctx.restore();
+ ctx.translate(ballDiameter, 0);
+ }
+}
+
+function safeMod(a, b) {
+ var q = Math.floor(a / b);
+ return a - q*b;
+}
+
+function drawBall(x, y, angle) {
+ canvasContext.save();
+ canvasContext.translate(x, y);
+ var idx = safeMod(Math.floor(angle * spriteMapSize / (2 * Math.PI)),
+ spriteMapSize);
+ canvasContext.drawImage(spriteMap, idx*ballDiameter + 1, 1, ballDiameter,
+ ballDiameter, -ballRadius, -ballRadius, ballDiameter, ballDiameter);
+ canvasContext.restore();
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_filled_path.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_filled_path.js
new file mode 100644
index 00000000000..7eb267d04f8
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_filled_path.js
@@ -0,0 +1,31 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var ballRadius;
+var ballGradient;
+var segmentCount = 20;
+
+function drawBallInit(diameter) {
+ ballRadius = diameter / 2;
+ ballGradient = canvasContext.createRadialGradient(0, 0, 0, 0, 0, ballRadius);
+ ballGradient.addColorStop(0, "#4040FF");
+ ballGradient.addColorStop(1, "#00FF40");
+}
+
+function drawBall(x, y, angle) {
+ canvasContext.save();
+ canvasContext.fillStyle = ballGradient;
+ canvasContext.translate(x, y);
+ canvasContext.rotate(angle);
+ canvasContext.beginPath();
+ canvasContext.moveTo(ballRadius, 0);
+ for (var i = 1; i < segmentCount; ++i) {
+ var angle = i * 2.0 * Math.PI / segmentCount;
+ canvasContext.lineTo(ballRadius*Math.cos(angle),
+ ballRadius*Math.sin(angle));
+ }
+ canvasContext.fill();
+ canvasContext.closePath();
+ canvasContext.restore();
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_image.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_image.js
new file mode 100644
index 00000000000..7be8bc6f5fe
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_image.js
@@ -0,0 +1,20 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var ballImage;
+var ballRadius;
+
+function drawBallInit(diameter) {
+ ballRadius = diameter / 2;
+ ballImage = document.getElementById('ballImage');
+}
+
+function drawBall(x, y, angle) {
+ canvasContext.save();
+ canvasContext.translate(x, y);
+ canvasContext.rotate(angle);
+ canvasContext.drawImage(ballImage, -ballRadius, -ballRadius, ballDiameter,
+ ballDiameter);
+ canvasContext.restore();
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_image_with_shadow.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_image_with_shadow.js
new file mode 100644
index 00000000000..0c30e665940
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_image_with_shadow.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var ballImage;
+var ballRadius;
+
+function drawBallInit(diameter) {
+ ballRadius = diameter / 2;
+ ballImage = document.getElementById('ballImage');
+}
+
+function drawBall(x, y, angle) {
+ canvasContext.save();
+ canvasContext.shadowColor = 'black';
+ canvasContext.shadowOffsetX = -ballRadius;
+ canvasContext.shadowOffsetY = ballRadius;
+ canvasContext.shadowBlur = ballRadius;
+ canvasContext.translate(x, y);
+ canvasContext.rotate(angle);
+ canvasContext.drawImage(ballImage, -ballRadius, -ballRadius, ballDiameter,
+ ballDiameter);
+ canvasContext.restore();
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_rect.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_rect.js
new file mode 100644
index 00000000000..e4e058b3b48
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_rect.js
@@ -0,0 +1,18 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var ballRadius;
+
+function drawBallInit(diameter) {
+ ballRadius = diameter / 2;
+}
+
+function drawBall(x, y, angle) {
+ canvasContext.save();
+ canvasContext.fillStyle = 'blue';
+ canvasContext.translate(x, y);
+ canvasContext.rotate(angle);
+ canvasContext.fillRect(-ballRadius, -ballRadius, ballDiameter, ballDiameter);
+ canvasContext.restore();
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_text.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_text.js
new file mode 100644
index 00000000000..079280de3c0
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/bouncing_balls_draw_ball_as_text.js
@@ -0,0 +1,21 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var ballScale;
+
+function drawBallInit(diameter) {
+ var metrics = canvasContext.measureText("Chrome");
+ ballScale = diameter/metrics.width
+}
+
+function drawBall(x, y, angle) {
+ canvasContext.save();
+ canvasContext.fillStyle = 'blue';
+ canvasContext.translate(x, y);
+ canvasContext.rotate(angle);
+ canvasContext.scale(ballScale, ballScale);
+ canvasContext.textAlign = "center";
+ canvasContext.fillText("Chrome", 0, 0);
+ canvasContext.restore();
+}
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/chromium.png b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/chromium.png
new file mode 100644
index 00000000000..9085a7901cc
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/chromium.png
Binary files differ
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/kiddie_logo.png b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/kiddie_logo.png
new file mode 100644
index 00000000000..61c70682f83
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/kiddie_logo.png
Binary files differ
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/parse_url.js b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/parse_url.js
new file mode 100644
index 00000000000..5173e34691f
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/canvas2d_balls_common/parse_url.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function getArgValue(argname)
+{
+ var url = window.location.href;
+ var parts = url.split("?");
+ if (parts.length == 0)
+ {
+ return "";
+ }
+ var arglist = parts[1];
+ var args = arglist.split("&");
+ for (i=0;i<args.length;i++)
+ {
+ var parts = args[i].split("=");
+ if (parts[0] == argname)
+ {
+ value = parts[1];
+ value = unescape(value);
+ return value;
+ }
+ }
+ return "";
+} \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/compositing_huge_div/index.html b/chromium/tools/perf/page_sets/tough_canvas_cases/compositing_huge_div/index.html
new file mode 100644
index 00000000000..8251f261c8d
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/compositing_huge_div/index.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<title>Compositing - Huge &lt;div&gt;</title>
+</head>
+<body>
+<div id="big" style="-webkit-transform: translateZ(0);">
+ <div style="left: 0px; top: 0px; width: 100px; height: 100px; position: absolute; background-color: green;"></div>
+ <div style="left: 3000000px; top: 1000000px; width: 100px; height: 100px; position: absolute; background-color: red;" id="bottomRight"></div>
+</div>
+<script>
+window.onload = init;
+
+var raf;
+
+function init() {
+ raf = window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame;
+ tick();
+};
+
+function tick() {
+ update();
+ raf(tick);
+};
+var bottomRight = document.getElementById('bottomRight');
+var x = 3000000;
+var y = 1000000;
+
+function rand255() {
+ return Math.floor(Math.random() * 256);
+}
+
+function update() {
+ y += 1000000;
+ bottomRight.style.left = x + 'px';
+ bottomRight.style.top = y + 'px';
+ bottomRight.style.backgroundColor = "rgb(" + rand255() + ", " + rand255() + ", " + rand255() + ")";
+ scrollTo(x, y);
+};
+
+</script>
+</body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/bench.js b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/bench.js
new file mode 100644
index 00000000000..4a7fee65b99
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/bench.js
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var bench = (function() {
+ var rafFunc;
+ var drawFunc;
+
+ function tick() {
+ drawFunc();
+ rafFunc(tick);
+ };
+
+ function startAnimation() {
+ rafFunc = window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame;
+ rafFunc(tick);
+ };
+
+ var bench = {};
+ bench.run = function(df) {
+ drawFunc = df;
+ startAnimation();
+ };
+ return bench;
+})();
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/images/generate_images.sh b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/images/generate_images.sh
new file mode 100755
index 00000000000..2c67f57f0d3
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/images/generate_images.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Utility to generate random images using ImageMagick.
+
+MIN_DIM=75
+MAX_DIM=100
+NUM_IMAGES=400
+
+for (( i = 1; i <= NUM_IMAGES; ++i )) do
+ # Generate a random binary 0/1.
+ rand_bin=$(( $RANDOM % 2 ))
+ # Generate a random number in the range [MIN_DIM, MAX_DIM].
+ rand_dim=$(( MIN_DIM + ($RANDOM % (MAX_DIM - MIN_DIM + 1)) ))
+
+ # Generate a dimension such that one side is equal to MAX_DIM
+ # and the other is a random number in the range [MIN_DIM, MAX_DIM].
+ width=$(( (rand_bin * MAX_DIM) + ((1 - rand_bin) * rand_dim) ))
+ height=$(( ((1 - rand_bin) * MAX_DIM) + (rand_bin * rand_dim) ))
+
+ # Generate a random image
+ convert -size ${width}x${height} plasma:fractal image${i}_t.png
+done
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/many_images.html b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/many_images.html
new file mode 100644
index 00000000000..f2a85397a67
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/many_images.html
@@ -0,0 +1,443 @@
+<html>
+<head>
+<title>Canvas - Many Images</title>
+<style>
+ #sprite-cache {
+ visibility: hidden;
+ }
+</style>
+<script type="text/javascript" src="bench.js"></script>
+<script type="text/javascript" src="sprites.js"></script>
+<script type="text/javascript">
+window.onload = init;
+
+var NUM_SPRITES = 2000;
+var canvas;
+var context;
+
+function init() {
+ canvas = document.getElementById('canvas');
+ context = canvas.getContext('2d');
+
+ sprites.init(canvas.width, canvas.height);
+ var images = document.getElementById('sprite-cache').children;
+ for (var i = 0, numImages = images.length; i < NUM_SPRITES; ++i) {
+ sprites.add(images[i % numImages]);
+ };
+
+ bench.run(draw);
+};
+
+function draw() {
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ sprites.draw(context);
+};
+</script>
+</head>
+
+<body>
+ <canvas id="canvas" width="800" height = "600">
+ <div id="sprite-cache">
+ <img src="images/image1_t.png" />
+ <img src="images/image2_t.png" />
+ <img src="images/image3_t.png" />
+ <img src="images/image4_t.png" />
+ <img src="images/image5_t.png" />
+ <img src="images/image6_t.png" />
+ <img src="images/image7_t.png" />
+ <img src="images/image8_t.png" />
+ <img src="images/image9_t.png" />
+ <img src="images/image10_t.png" />
+ <img src="images/image11_t.png" />
+ <img src="images/image12_t.png" />
+ <img src="images/image13_t.png" />
+ <img src="images/image14_t.png" />
+ <img src="images/image15_t.png" />
+ <img src="images/image16_t.png" />
+ <img src="images/image17_t.png" />
+ <img src="images/image18_t.png" />
+ <img src="images/image19_t.png" />
+ <img src="images/image20_t.png" />
+ <img src="images/image21_t.png" />
+ <img src="images/image22_t.png" />
+ <img src="images/image23_t.png" />
+ <img src="images/image24_t.png" />
+ <img src="images/image25_t.png" />
+ <img src="images/image26_t.png" />
+ <img src="images/image27_t.png" />
+ <img src="images/image28_t.png" />
+ <img src="images/image29_t.png" />
+ <img src="images/image30_t.png" />
+ <img src="images/image31_t.png" />
+ <img src="images/image32_t.png" />
+ <img src="images/image33_t.png" />
+ <img src="images/image34_t.png" />
+ <img src="images/image35_t.png" />
+ <img src="images/image36_t.png" />
+ <img src="images/image37_t.png" />
+ <img src="images/image38_t.png" />
+ <img src="images/image39_t.png" />
+ <img src="images/image40_t.png" />
+ <img src="images/image41_t.png" />
+ <img src="images/image42_t.png" />
+ <img src="images/image43_t.png" />
+ <img src="images/image44_t.png" />
+ <img src="images/image45_t.png" />
+ <img src="images/image46_t.png" />
+ <img src="images/image47_t.png" />
+ <img src="images/image48_t.png" />
+ <img src="images/image49_t.png" />
+ <img src="images/image50_t.png" />
+ <img src="images/image51_t.png" />
+ <img src="images/image52_t.png" />
+ <img src="images/image53_t.png" />
+ <img src="images/image54_t.png" />
+ <img src="images/image55_t.png" />
+ <img src="images/image56_t.png" />
+ <img src="images/image57_t.png" />
+ <img src="images/image58_t.png" />
+ <img src="images/image59_t.png" />
+ <img src="images/image60_t.png" />
+ <img src="images/image61_t.png" />
+ <img src="images/image62_t.png" />
+ <img src="images/image63_t.png" />
+ <img src="images/image64_t.png" />
+ <img src="images/image65_t.png" />
+ <img src="images/image66_t.png" />
+ <img src="images/image67_t.png" />
+ <img src="images/image68_t.png" />
+ <img src="images/image69_t.png" />
+ <img src="images/image70_t.png" />
+ <img src="images/image71_t.png" />
+ <img src="images/image72_t.png" />
+ <img src="images/image73_t.png" />
+ <img src="images/image74_t.png" />
+ <img src="images/image75_t.png" />
+ <img src="images/image76_t.png" />
+ <img src="images/image77_t.png" />
+ <img src="images/image78_t.png" />
+ <img src="images/image79_t.png" />
+ <img src="images/image80_t.png" />
+ <img src="images/image81_t.png" />
+ <img src="images/image82_t.png" />
+ <img src="images/image83_t.png" />
+ <img src="images/image84_t.png" />
+ <img src="images/image85_t.png" />
+ <img src="images/image86_t.png" />
+ <img src="images/image87_t.png" />
+ <img src="images/image88_t.png" />
+ <img src="images/image89_t.png" />
+ <img src="images/image90_t.png" />
+ <img src="images/image91_t.png" />
+ <img src="images/image92_t.png" />
+ <img src="images/image93_t.png" />
+ <img src="images/image94_t.png" />
+ <img src="images/image95_t.png" />
+ <img src="images/image96_t.png" />
+ <img src="images/image97_t.png" />
+ <img src="images/image98_t.png" />
+ <img src="images/image99_t.png" />
+ <img src="images/image100_t.png" />
+ <img src="images/image101_t.png" />
+ <img src="images/image102_t.png" />
+ <img src="images/image103_t.png" />
+ <img src="images/image104_t.png" />
+ <img src="images/image105_t.png" />
+ <img src="images/image106_t.png" />
+ <img src="images/image107_t.png" />
+ <img src="images/image108_t.png" />
+ <img src="images/image109_t.png" />
+ <img src="images/image110_t.png" />
+ <img src="images/image111_t.png" />
+ <img src="images/image112_t.png" />
+ <img src="images/image113_t.png" />
+ <img src="images/image114_t.png" />
+ <img src="images/image115_t.png" />
+ <img src="images/image116_t.png" />
+ <img src="images/image117_t.png" />
+ <img src="images/image118_t.png" />
+ <img src="images/image119_t.png" />
+ <img src="images/image120_t.png" />
+ <img src="images/image121_t.png" />
+ <img src="images/image122_t.png" />
+ <img src="images/image123_t.png" />
+ <img src="images/image124_t.png" />
+ <img src="images/image125_t.png" />
+ <img src="images/image126_t.png" />
+ <img src="images/image127_t.png" />
+ <img src="images/image128_t.png" />
+ <img src="images/image129_t.png" />
+ <img src="images/image130_t.png" />
+ <img src="images/image131_t.png" />
+ <img src="images/image132_t.png" />
+ <img src="images/image133_t.png" />
+ <img src="images/image134_t.png" />
+ <img src="images/image135_t.png" />
+ <img src="images/image136_t.png" />
+ <img src="images/image137_t.png" />
+ <img src="images/image138_t.png" />
+ <img src="images/image139_t.png" />
+ <img src="images/image140_t.png" />
+ <img src="images/image141_t.png" />
+ <img src="images/image142_t.png" />
+ <img src="images/image143_t.png" />
+ <img src="images/image144_t.png" />
+ <img src="images/image145_t.png" />
+ <img src="images/image146_t.png" />
+ <img src="images/image147_t.png" />
+ <img src="images/image148_t.png" />
+ <img src="images/image149_t.png" />
+ <img src="images/image150_t.png" />
+ <img src="images/image151_t.png" />
+ <img src="images/image152_t.png" />
+ <img src="images/image153_t.png" />
+ <img src="images/image154_t.png" />
+ <img src="images/image155_t.png" />
+ <img src="images/image156_t.png" />
+ <img src="images/image157_t.png" />
+ <img src="images/image158_t.png" />
+ <img src="images/image159_t.png" />
+ <img src="images/image160_t.png" />
+ <img src="images/image161_t.png" />
+ <img src="images/image162_t.png" />
+ <img src="images/image163_t.png" />
+ <img src="images/image164_t.png" />
+ <img src="images/image165_t.png" />
+ <img src="images/image166_t.png" />
+ <img src="images/image167_t.png" />
+ <img src="images/image168_t.png" />
+ <img src="images/image169_t.png" />
+ <img src="images/image170_t.png" />
+ <img src="images/image171_t.png" />
+ <img src="images/image172_t.png" />
+ <img src="images/image173_t.png" />
+ <img src="images/image174_t.png" />
+ <img src="images/image175_t.png" />
+ <img src="images/image176_t.png" />
+ <img src="images/image177_t.png" />
+ <img src="images/image178_t.png" />
+ <img src="images/image179_t.png" />
+ <img src="images/image180_t.png" />
+ <img src="images/image181_t.png" />
+ <img src="images/image182_t.png" />
+ <img src="images/image183_t.png" />
+ <img src="images/image184_t.png" />
+ <img src="images/image185_t.png" />
+ <img src="images/image186_t.png" />
+ <img src="images/image187_t.png" />
+ <img src="images/image188_t.png" />
+ <img src="images/image189_t.png" />
+ <img src="images/image190_t.png" />
+ <img src="images/image191_t.png" />
+ <img src="images/image192_t.png" />
+ <img src="images/image193_t.png" />
+ <img src="images/image194_t.png" />
+ <img src="images/image195_t.png" />
+ <img src="images/image196_t.png" />
+ <img src="images/image197_t.png" />
+ <img src="images/image198_t.png" />
+ <img src="images/image199_t.png" />
+ <img src="images/image200_t.png" />
+ <img src="images/image201_t.png" />
+ <img src="images/image202_t.png" />
+ <img src="images/image203_t.png" />
+ <img src="images/image204_t.png" />
+ <img src="images/image205_t.png" />
+ <img src="images/image206_t.png" />
+ <img src="images/image207_t.png" />
+ <img src="images/image208_t.png" />
+ <img src="images/image209_t.png" />
+ <img src="images/image210_t.png" />
+ <img src="images/image211_t.png" />
+ <img src="images/image212_t.png" />
+ <img src="images/image213_t.png" />
+ <img src="images/image214_t.png" />
+ <img src="images/image215_t.png" />
+ <img src="images/image216_t.png" />
+ <img src="images/image217_t.png" />
+ <img src="images/image218_t.png" />
+ <img src="images/image219_t.png" />
+ <img src="images/image220_t.png" />
+ <img src="images/image221_t.png" />
+ <img src="images/image222_t.png" />
+ <img src="images/image223_t.png" />
+ <img src="images/image224_t.png" />
+ <img src="images/image225_t.png" />
+ <img src="images/image226_t.png" />
+ <img src="images/image227_t.png" />
+ <img src="images/image228_t.png" />
+ <img src="images/image229_t.png" />
+ <img src="images/image230_t.png" />
+ <img src="images/image231_t.png" />
+ <img src="images/image232_t.png" />
+ <img src="images/image233_t.png" />
+ <img src="images/image234_t.png" />
+ <img src="images/image235_t.png" />
+ <img src="images/image236_t.png" />
+ <img src="images/image237_t.png" />
+ <img src="images/image238_t.png" />
+ <img src="images/image239_t.png" />
+ <img src="images/image240_t.png" />
+ <img src="images/image241_t.png" />
+ <img src="images/image242_t.png" />
+ <img src="images/image243_t.png" />
+ <img src="images/image244_t.png" />
+ <img src="images/image245_t.png" />
+ <img src="images/image246_t.png" />
+ <img src="images/image247_t.png" />
+ <img src="images/image248_t.png" />
+ <img src="images/image249_t.png" />
+ <img src="images/image250_t.png" />
+ <img src="images/image251_t.png" />
+ <img src="images/image252_t.png" />
+ <img src="images/image253_t.png" />
+ <img src="images/image254_t.png" />
+ <img src="images/image255_t.png" />
+ <img src="images/image256_t.png" />
+ <img src="images/image257_t.png" />
+ <img src="images/image258_t.png" />
+ <img src="images/image259_t.png" />
+ <img src="images/image260_t.png" />
+ <img src="images/image261_t.png" />
+ <img src="images/image262_t.png" />
+ <img src="images/image263_t.png" />
+ <img src="images/image264_t.png" />
+ <img src="images/image265_t.png" />
+ <img src="images/image266_t.png" />
+ <img src="images/image267_t.png" />
+ <img src="images/image268_t.png" />
+ <img src="images/image269_t.png" />
+ <img src="images/image270_t.png" />
+ <img src="images/image271_t.png" />
+ <img src="images/image272_t.png" />
+ <img src="images/image273_t.png" />
+ <img src="images/image274_t.png" />
+ <img src="images/image275_t.png" />
+ <img src="images/image276_t.png" />
+ <img src="images/image277_t.png" />
+ <img src="images/image278_t.png" />
+ <img src="images/image279_t.png" />
+ <img src="images/image280_t.png" />
+ <img src="images/image281_t.png" />
+ <img src="images/image282_t.png" />
+ <img src="images/image283_t.png" />
+ <img src="images/image284_t.png" />
+ <img src="images/image285_t.png" />
+ <img src="images/image286_t.png" />
+ <img src="images/image287_t.png" />
+ <img src="images/image288_t.png" />
+ <img src="images/image289_t.png" />
+ <img src="images/image290_t.png" />
+ <img src="images/image291_t.png" />
+ <img src="images/image292_t.png" />
+ <img src="images/image293_t.png" />
+ <img src="images/image294_t.png" />
+ <img src="images/image295_t.png" />
+ <img src="images/image296_t.png" />
+ <img src="images/image297_t.png" />
+ <img src="images/image298_t.png" />
+ <img src="images/image299_t.png" />
+ <img src="images/image300_t.png" />
+ <img src="images/image301_t.png" />
+ <img src="images/image302_t.png" />
+ <img src="images/image303_t.png" />
+ <img src="images/image304_t.png" />
+ <img src="images/image305_t.png" />
+ <img src="images/image306_t.png" />
+ <img src="images/image307_t.png" />
+ <img src="images/image308_t.png" />
+ <img src="images/image309_t.png" />
+ <img src="images/image310_t.png" />
+ <img src="images/image311_t.png" />
+ <img src="images/image312_t.png" />
+ <img src="images/image313_t.png" />
+ <img src="images/image314_t.png" />
+ <img src="images/image315_t.png" />
+ <img src="images/image316_t.png" />
+ <img src="images/image317_t.png" />
+ <img src="images/image318_t.png" />
+ <img src="images/image319_t.png" />
+ <img src="images/image320_t.png" />
+ <img src="images/image321_t.png" />
+ <img src="images/image322_t.png" />
+ <img src="images/image323_t.png" />
+ <img src="images/image324_t.png" />
+ <img src="images/image325_t.png" />
+ <img src="images/image326_t.png" />
+ <img src="images/image327_t.png" />
+ <img src="images/image328_t.png" />
+ <img src="images/image329_t.png" />
+ <img src="images/image330_t.png" />
+ <img src="images/image331_t.png" />
+ <img src="images/image332_t.png" />
+ <img src="images/image333_t.png" />
+ <img src="images/image334_t.png" />
+ <img src="images/image335_t.png" />
+ <img src="images/image336_t.png" />
+ <img src="images/image337_t.png" />
+ <img src="images/image338_t.png" />
+ <img src="images/image339_t.png" />
+ <img src="images/image340_t.png" />
+ <img src="images/image341_t.png" />
+ <img src="images/image342_t.png" />
+ <img src="images/image343_t.png" />
+ <img src="images/image344_t.png" />
+ <img src="images/image345_t.png" />
+ <img src="images/image346_t.png" />
+ <img src="images/image347_t.png" />
+ <img src="images/image348_t.png" />
+ <img src="images/image349_t.png" />
+ <img src="images/image350_t.png" />
+ <img src="images/image351_t.png" />
+ <img src="images/image352_t.png" />
+ <img src="images/image353_t.png" />
+ <img src="images/image354_t.png" />
+ <img src="images/image355_t.png" />
+ <img src="images/image356_t.png" />
+ <img src="images/image357_t.png" />
+ <img src="images/image358_t.png" />
+ <img src="images/image359_t.png" />
+ <img src="images/image360_t.png" />
+ <img src="images/image361_t.png" />
+ <img src="images/image362_t.png" />
+ <img src="images/image363_t.png" />
+ <img src="images/image364_t.png" />
+ <img src="images/image365_t.png" />
+ <img src="images/image366_t.png" />
+ <img src="images/image367_t.png" />
+ <img src="images/image368_t.png" />
+ <img src="images/image369_t.png" />
+ <img src="images/image370_t.png" />
+ <img src="images/image371_t.png" />
+ <img src="images/image372_t.png" />
+ <img src="images/image373_t.png" />
+ <img src="images/image374_t.png" />
+ <img src="images/image375_t.png" />
+ <img src="images/image376_t.png" />
+ <img src="images/image377_t.png" />
+ <img src="images/image378_t.png" />
+ <img src="images/image379_t.png" />
+ <img src="images/image380_t.png" />
+ <img src="images/image381_t.png" />
+ <img src="images/image382_t.png" />
+ <img src="images/image383_t.png" />
+ <img src="images/image384_t.png" />
+ <img src="images/image385_t.png" />
+ <img src="images/image386_t.png" />
+ <img src="images/image387_t.png" />
+ <img src="images/image388_t.png" />
+ <img src="images/image389_t.png" />
+ <img src="images/image390_t.png" />
+ <img src="images/image391_t.png" />
+ <img src="images/image392_t.png" />
+ <img src="images/image393_t.png" />
+ <img src="images/image394_t.png" />
+ <img src="images/image395_t.png" />
+ <img src="images/image396_t.png" />
+ <img src="images/image397_t.png" />
+ <img src="images/image398_t.png" />
+ <img src="images/image399_t.png" />
+ <img src="images/image400_t.png" />
+ </div>
+</body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/single_image.html b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/single_image.html
new file mode 100644
index 00000000000..9d21a0ef311
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/single_image.html
@@ -0,0 +1,44 @@
+<html>
+<head>
+<title>Canvas - Single Image</title>
+<style>
+ #sprite-cache {
+ visibility: hidden;
+ }
+</style>
+<script type="text/javascript" src="bench.js"></script>
+<script type="text/javascript" src="sprites.js"></script>
+<script type="text/javascript">
+window.onload = init;
+
+var NUM_SPRITES = 2000;
+var canvas;
+var context;
+
+function init() {
+ canvas = document.getElementById('canvas');
+ context = canvas.getContext('2d');
+
+ sprites.init(canvas.width, canvas.height);
+ var image = document.getElementById('sprite-cache').children[0];
+ for (var i = 0; i < NUM_SPRITES; ++i) {
+ sprites.add(image);
+ };
+
+ bench.run(draw);
+};
+
+function draw() {
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ sprites.draw(context);
+};
+</script>
+</head>
+
+<body>
+ <canvas id="canvas" width="800" height = "600">
+ <div id="sprite-cache">
+ <img src="images/image1_t.png" />
+ </div>
+</body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/sprites.js b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/sprites.js
new file mode 100644
index 00000000000..283c2b37ddb
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_canvas_cases/many_images/sprites.js
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var sprites = (function() {
+ var objs;
+ var width;
+ var height;
+ var SPRITE_SPEED = 2;
+
+ var sprites = {};
+ sprites.init = function(w, h) {
+ objs = [];
+ width = w;
+ height = h;
+ };
+ sprites.add = function(img) {
+ var obj = { img: img,
+ x: Math.random() * (width - img.width),
+ y: Math.random() * (height - img.height),
+ dx: SPRITE_SPEED * (Math.random() < .5 ? -1 : 1),
+ dy: SPRITE_SPEED * (Math.random() < .5 ? -1 : 1) };
+ objs.push(obj);
+ };
+ sprites.draw = function(context) {
+ for (var i = 0, len = objs.length; i < len; ++i) {
+ var obj = objs[i];
+
+ obj.x += obj.dx;
+ if ((obj.x > (width - obj.img.width)) || (obj.x < 0))
+ obj.dx *= -1;
+
+ obj.y += obj.dy;
+ if ((obj.y > (height - obj.img.height)) || (obj.y < 0))
+ obj.dy *= -1;
+
+ context.drawImage(obj.img, obj.x, obj.y);
+ };
+ };
+ return sprites;
+})();
diff --git a/chromium/tools/perf/page_sets/tough_image_cases.json b/chromium/tools/perf/page_sets/tough_image_cases.json
new file mode 100644
index 00000000000..122c4a8fab4
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_image_cases.json
@@ -0,0 +1,8 @@
+{
+ "description": "A collection of image-heavy sites.",
+ "user_agent_type": "desktop",
+ "pages": [
+ { "url": "http://www.free-pictures-photos.com/aviation/airplane-306.jpg" },
+ { "url": "http://upload.wikimedia.org/wikipedia/commons/c/cb/General_history%2C_Alaska_Yukon_Pacific_Exposition%2C_fully_illustrated_-_meet_me_in_Seattle_1909_-_Page_78.jpg" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_layer_cases.json b/chromium/tools/perf/page_sets/tough_layer_cases.json
new file mode 100644
index 00000000000..c9dc16ec99a
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_layer_cases.json
@@ -0,0 +1,6 @@
+{
+ "description": "A collection of tests to measure layer performance",
+ "pages": [
+ { "url": "file://layer_stress_tests/opacity.html" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_layer_cases/opacity.html b/chromium/tools/perf/page_sets/tough_layer_cases/opacity.html
new file mode 100644
index 00000000000..61c675056ab
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_layer_cases/opacity.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Chrome 18 opacity test</title>
+ <style>
+ .ninety-nine{
+ opacity: 0.99;
+ }
+ </style>
+ <script>
+ function toggleOpacity() {
+ var pre = document.getElementById('label');
+ if (document.body.className == '') {
+ document.body.className='ninety-nine';
+ pre.innerHTML = 'opacity: 0.99';
+ } else {
+ document.body.className='';
+ pre.innerHTML = 'opacity: 1.0';
+ }
+ window.setTimeout("toggleOpacity();", 1000);
+ }
+ onload = toggleOpacity;
+ </script>
+ </head>
+ <body>
+ <div style="overflow: hidden">
+ <div style="-webkit-perspective: 10px">
+ Quite a lot of text: Opacity can be thought of as a postprocessing
+ operation. Conceptually, after the element (including its descendants)
+ is rendered into an RGBA offscreen image, the opacity setting specifies
+ how to blend the offscreen rendering into the current composite rendering.
+ The uniform opacity setting to be applied across an entire object. Any
+ values outside the range 0.0 (fully transparent) to 1.0 (fully opaque)
+ will be clamped to this range. If the object is a container element, then
+ the effect is as if the contents of the container element were blended
+ against the current background using a mask where the value of each pixel
+ of the mask is the opacity value
+ </div>
+ <pre id="label"></pre>
+ </div>
+ </body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_layout_cases.json b/chromium/tools/perf/page_sets/tough_layout_cases.json
new file mode 100644
index 00000000000..772bb7b7f33
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_layout_cases.json
@@ -0,0 +1,39 @@
+{
+ "description": "The slowest layouts observed in the alexa top 1 million sites in July 2013.",
+ "archive_data_file": "../data/tough_layout_cases.json",
+ "credentials_path": "../data/credentials.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://oilevent.com"
+ },
+ {
+ "url": "http://www.muzoboss.ru"
+ },
+ {
+ "url": "http://natunkantha.com"
+ },
+ {
+ "url": "http://www.mossiella.com"
+ },
+ {
+ "url": "http://bookish.com"
+ },
+ {
+ "url": "http://mydiyclub.com"
+ },
+ {
+ "url": "http://amarchoti.blogspot.com"
+ },
+ {
+ "url": "http://picarisimo.es"
+ },
+ {
+ "url": "http://chinaapache.com"
+ },
+ {
+ "url": "http://indoritel.com"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases.json b/chromium/tools/perf/page_sets/tough_scrolling_cases.json
new file mode 100644
index 00000000000..7330581cd46
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases.json
@@ -0,0 +1,15 @@
+{
+ "description": "A collection of difficult scrolling tests",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ { "url": "file:///tough_scrolling_cases/background_fixed.html" },
+ { "url": "file:///tough_scrolling_cases/cust_scrollbar.html" },
+ { "url": "file:///tough_scrolling_cases/div_scrolls.html" },
+ { "url": "file:///tough_scrolling_cases/fixed_nonstacking.html" },
+ { "url": "file:///tough_scrolling_cases/fixed_stacking.html" },
+ { "url": "file:///tough_scrolling_cases/iframe_scrolls.html" },
+ { "url": "file:///tough_scrolling_cases/simple.html" },
+ { "url": "file:///tough_scrolling_cases/wheel_body_prevdefault.html" },
+ { "url": "file:///tough_scrolling_cases/wheel_div_prevdefault.html" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/background_fixed.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/background_fixed.html
new file mode 100644
index 00000000000..7de4686629c
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/background_fixed.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<body style="background:url(image.png); background-attachment: fixed">
+<div style="width:60%; margin-left: 20%; background-color: rgba(255, 255, 255, 0.9)">
+<h1>Aaaaa a a a aaaaa</h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/busy.js b/chromium/tools/perf/page_sets/tough_scrolling_cases/busy.js
new file mode 100644
index 00000000000..c22fbb6d3af
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/busy.js
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function busyLoop(millis) {
+ for (var d = Date.now(); Date.now() - d < millis; ) { }
+}
+
+function visible() {
+ if ("webkitVisibilityState" in document
+ && document.webkitVisibilityState == "hidden")
+ return false;
+ if ("mozVisibilityState" in document
+ && document.mozVisibilityState == "hidden")
+ return false;
+ if ("msVisibilityState" in document
+ && document.msVisibilityState == "hidden")
+ return false;
+ return true;
+}
+
+var timerId = 0;
+function loop() {
+ timerId = 0;
+ if (!visible())
+ return;
+ busyLoop(250);
+ timerId = window.setTimeout(loop, 50);
+}
+
+function handler() {
+ if (visible() && !timerId)
+ timerId = window.setTimeout(loop, 50);
+}
+
+document.addEventListener("webkitvisibilitychange", handler, false);
+document.addEventListener("mozvisibilitychange", handler, false);
+document.addEventListener("msvisibilitychange", handler, false);
+
+loop();
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/cust_scrollbar.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/cust_scrollbar.html
new file mode 100644
index 00000000000..5d40d2eef80
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/cust_scrollbar.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<style>
+::-webkit-scrollbar {
+ background-color: blue;
+}
+::-webkit-scrollbar-thumb {
+ background-color: green;
+}</style>
+<body>
+<div style="width:60%; margin-left: 20%">
+<h1>Aaaaaaaaa aaaa a aa aaa</h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/div_scrolls.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/div_scrolls.html
new file mode 100644
index 00000000000..5129816b917
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/div_scrolls.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<body>
+<div style="width:60%; margin-left: 20%">
+<h1>Aaaaaa a aa a </h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<div style="width:500px; height:400px; overflow-y:scroll; position:relative">
+ <div style="position:absolute; height:1000px">This <p>is <p>scrollable <p>content <p>inside <p>a <p>div</div>
+</div>
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/fixed_nonstacking.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/fixed_nonstacking.html
new file mode 100644
index 00000000000..eca5b82464a
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/fixed_nonstacking.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<body>
+<div style="width:60%; margin-left: 20%">
+<div style="position:fixed; width: 500px; height:400px; background-color: blue; color: white; font-size: large;">
+ This is a position:fixed element that does not create a stacking context.
+</div>
+<h1>Aaaaaa aaa aa aa a aaaaaaaa</h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/fixed_stacking.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/fixed_stacking.html
new file mode 100644
index 00000000000..0af5305eec2
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/fixed_stacking.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<body>
+<div style="width:60%; margin-left: 20%">
+<div style="position:fixed; width: 500px; height:400px; background-color: blue; color: white; font-size: large; z-index: 1">
+ This is a position:fixed element that creates a stacking context.
+</div>
+<h1>aaaaaaaa aa aaaaaaa</h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/iframe_scrolls.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/iframe_scrolls.html
new file mode 100644
index 00000000000..a0080cd68eb
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/iframe_scrolls.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<body>
+<div style="width:60%; margin-left: 20%">
+<h1>aaaaaaaa aa aaaaaaa</h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<iframe width="500" height="400" src="data:text/html;charset=utf-8,<!DOCTYPE html><div style='position:absolute;height:1000px'>This <p>is <p>scrollable <p>content <p>inside <p>an <p>iframe</div>"></iframe>
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/image.png b/chromium/tools/perf/page_sets/tough_scrolling_cases/image.png
new file mode 100644
index 00000000000..82c2870df48
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/image.png
Binary files differ
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/simple.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/simple.html
new file mode 100644
index 00000000000..20ecaa545d5
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/simple.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<body>
+<div style="width:60%; margin-left: 20%">
+<h1>aaaaaaaa aa aaaaaaa</h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/wheel_body_prevdefault.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/wheel_body_prevdefault.html
new file mode 100644
index 00000000000..a264e8c424a
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/wheel_body_prevdefault.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<body>
+<script>
+document.body.addEventListener("mousewheel", function(e) {
+ e.preventDefault();
+}, false);
+</script>
+<div style="width:60%; margin-left: 20%">
+<h1>AAAaaaaa a a aa a</h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_scrolling_cases/wheel_div_prevdefault.html b/chromium/tools/perf/page_sets/tough_scrolling_cases/wheel_div_prevdefault.html
new file mode 100644
index 00000000000..b670a4cc408
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_scrolling_cases/wheel_div_prevdefault.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<script src="busy.js"></script>
+<body>
+<div style="width:60%; margin-left: 20%">
+<div id="prevent" style="position:absolute; width:500px; height:400px; background-color: blue; color: white; font-size: large">
+ This box has a mousewheel event handler that prevents the default action.
+</div>
+<script>
+document.querySelector("#prevent").addEventListener("mousewheel", function(e) {
+ e.preventDefault();
+}, false);
+</script>
+<h1>AAAaaaa aaa aa aaaa</h1>
+aaaaa aa aaaaaaa aa aaaaaa aaaaaaaa aaa aaaa aaa aaaa aaaaaaaa aaaaaaa aaaaa aa aa, aaaaa aaaaa aaaaaaaaaa aaaa. aaaaaa aaa aa' aaaaa, aaaaaa aaaaaaaaaaa, aaaaaaaa aaaaaaa, aaaaaaa aaa, aaaa. aaaaaaaaaaaa aaaa aaaaaaaaa. aaaaaa aaaaaa. aaaaa aa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaaa. aaaaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaa aa aaaaaa. aaaaaa aaaaa aaaaaa. aaaaaaaaaaaa aaaaaaaa aaaaaaaaaa aaaa. aa aaa aaaaaa aaaa aaaaaaaa. aaaaaa aaaaaaaaaa. aa aaaaaa aaaaaaa, aaaaa aa aaaa, aaaa aa, aaaaaa a aaa aaaaaaaa aaaaaaa aaa aa aaaaaa aaaa aaaaaaa, aaaaaaaa aaaaa, aaaa. aaaaaa aaaaaaaaaaa. aaaa aaa aa' aaaa aaa aaaaaaa aa aaaa aaaaaaaaaa aaaa.
+<p>
+aaaaaaaaa aaaaaaaa aaaaaaaa aaaaaa. aa aaaaaa aaaaaaaaaa aaaa aaa aaaaaaa aa. aaaaaa aaa aaa. aaaaa aaaaaaaa aaaaa, aaaaaaaa aaa aa aaaaaa, aaaaaaaaaaa aaa, aaaaa aaaaaaa, aa aaaaaaa. aaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaa aa aaaaaa. aaaaaa aaaa aaaaaaaaaa. aaaaaaaaaaaaa aaaaa aaaa aaaaaa aaaa aaaaaa' aaaaaaa. aaaaaaaa aa aa aaaaaa aa aaaaaa aaaaaa aaa aaa aa a aaaaaa, aaaaaaaaaaaaaa aaaaaa aaaa aaaa. aaaaaa aaaaa aaaaaaa. aaaaaaa aaaa ... aaa! aaaaaaaa aaaaaaa aaaaa aa aa, aaaaaaaaaa aaaaa, aaaaaaaa a, aaaaaaaa a, aaaaa aaaaa.
+
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+<p>
+aaaaaa aaaaa aaaaaaaaaaaa aaa aaaa aaaa aaaa'a aaa aaaaaaa aaaaaaaaaaaa. aaaa aaaaaaaaa, aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaa aaaaaaaaa aaaaaaa, aaaaa aaaaa aaaaa aa aaa aaaaaaa, aaaa aaaaaaa aaaaaa aaaaa aaaaaa aaaaaaaa aaaaaa. aaa aaaaa aaa aa aaaaaa aaaaaa aaaaaa aaaaa aaaaaaaaa. aaaaaaaaaaaa aaaaaaa aaaa, a'a aa aaa aaaaaaa aaaaa, aaaaa aaa aaaa aaa aaaa, aaa aaa aaa aaaaa, aaaaa. aaa aaa aa a aaaaaa aaaaaaa aaaaa. aaaa aaaaaaaa aaaaaaaa aaaaaaa aaaaa, aaaaaaaaaaaa aaaa ... aaa! aaaaa aaaaa. aaa aaaa aaaaaa aaaa. aa aaaaa aaa aaaa. aaaaaaaaaaaaa aaaaa aaaaaaa aaaaa aaaaaaaa aaaa aa aaaaaaa. aa aaaaaaaaa aaaaaaa aaaaaa aaaaaaa aaaa. aaaaa aaa aaaa aaaaaa aaaa. aaaa aa aaaa aaaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaaaaaa. aaaaaaaa aaaaaa aaaaa aaaa aaaa aaaaaaaa aaaaaaaaaaa. aaaaaaaaaaa aaaaaaa aaa, aaaaaaaaaaa aaaaa aa aaa, aaaa aaaaa aa aaaa, aaaa, aaaa'a aaa aaaaaaa aaaa, aaaaa aaaaa. aaa aaaaaa aaaaaaa aaaa aa aaaaa aaaaaaa aaaaaa. aaaaaaaaa aaaaaaa aa aaaaaa aaaaaaaaaaa aaaa aaaa aaaaa aa aaaa aaaa aaaaaaa.
+
+<p>
+aa aaaaaa' aaaaaaa aa aaaaaa aaaaaaaaaaa aaaaaa aaa. aaaaaa aa aa aaaaaa. aaaaa aaaaaaaaa. aaaaaaaa aaaa'a aaa aaaaaaa aaaaa a aaaa aa aaaaaaa aaa aaaaaa aa aaaaaa, aaa aaaa a-aaaaaa aaaaaaaa. aaaaaa aa aaaa aa aaaaaaa aa aaaaaa. aaaaaa aaaaaa aaa aa aaa aaaaaa. aaaa'a aaa aaaaaaa a aa aa aaaaaa aaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaaaaaa aaa aaaaaa. aaaaaaa aaaaaaaa a'a aa aaa aaaaaaa aaaaaa aaaaaaaa. aa aaaa aaaaa. aaaaaa aaaa aa aaa aaaaa aa aaaaaa aaaaaaaaa aaaaaaaa. aaaaa aaaaaaaa, aaaa aaaaa aa aaaa aaaaaaa aaaaaaa, aaaa aaa aaa aaaaaa aaaaaa, aaaaaa aaaaaa aa aaaaaaaa aa aaaaa aaa. aaaaaa aaa aaaaaa. aaaa aaaaaaaaaa aa aaaaaaa aaaaa aaaaaaaaa aa aaaaaaaa aaaa aaaaaaaaa aaa aaa aa a aaaaaa aaaaaaaa aaaaa aa aaaa aaaaaaa aaaaa; aa aaaaaaa aaaaaaaa, aaaa aaaa aaaaaa aaaaaaaa aaaaaaa aaaaa aa aa, aa aaaaaaa aaaaaaa aaaaaa, a aa aa aaaaaa aaaa aaaaaa aaaaaaa aaaaaaa. aaaaaa aaaa aaaaaaa aaaaa aaaaa. aaaaaa aaaaa aa aaa. aaa aaaaaa aaaaaa aaaaaaaaaaaa aaa aaaa aaaaaaaaa aaaaaa' aaaaaaaaaa aaaa aaa aaaaaaa aa, aaaaaaaa aaa aaaaaa aaaaaa. aaaaaaa aaaaaaaa aaaaaaa aaaaa aa aa aaaaaa aaaaaaaaa aaaaaaaa aaaaaa aaaaaaa aaaaaa. aaaaaaaa aaa aa.
+
+<p>
+<img src="image.png">
+<p>
+aaaaaa aaaaaa aaaaa aaaaa. aaaaaaaaa aaaaa aa aaa, aaaaa aa aaaaaaaa aaaaaa, aaaaa aaaaaaa aaaaaaaaaaaa aaaaa aaa aaaa, aaaaaa aaaaaaaaaaaa aaaaaaaa aaaaa aaaaaa aaa aaaaaa. aaa aaaaaaaaaa aaaaaaaaa aaaaa. aa aa aaaaaa aaaaaa aaaaaa aaaaaaaaaaa. aaa aaaa aaaaaa aaaaaa aaaaaa aaaa. aaaaaaaaaaaaa aaaa aaaa, aaaaaaaaaa aaaaa, aaaa aaaaaaaaaa aaaa, aaaaaaaa aaaaa, aaaaa. aaaa ... aaa! aaaaaaa aaaaaaaaaa aaaaaa. aa aaaa aaaaaaaaa aaaaaaa aaaaa aaaaa. aaaaa aa aaa aaaa aaaa aaaaaaa aa aaaaa aaaaa aaaaaaaaaaa. aaaaa aaaaaaaaa aaaaaaa aaaaaaa. aaaaa aaaaaaaaaa, aaaaa a aaaaaaa aaaaa aaaaa, aaaa aaaaaaaa aaaaaaa aaaa, aaaaaaaaa aaaaaaaaaaaa aaaa'a aaa aaaaaaa aaaaa aaaaaa aaaaaaaa. aaaa aaaaaaaaa aaaa ... aaa! aaa aaaaaa. aaaaaa aa aaaaaa aaaaaaa aaaaa aa aaa aaaaaaaaaa aa aaaaa aaaaa. aaaaaaaaa aaaaa aaaaaaaa aaaaaa. aaaaaa aaaaa. aaaaaaaaaaa aa aaaa.
+
+<p>
+aaa aaaa aaa aaaa aa aaaaaa. aaaaaa aaaa aa aaaaaaa aa aaaaaa aaaaaaa aaaa aaaaaaaaaa. aaaaaaaa aaaaaaa, aaaaaaa aaaaa aaaaaaaaa aa aaaaa, aaaaaa aaaa aaaaaaaaa aaa, aaa aaaaaaaaaaa aaaa aaaaaa aa aaaa. aaaaa aaaaa aaaaaaaa. aaaaaaaaaaaaa aa aaaa aaaaaaaa. aaa aaaaaa aaaa aaaaaaaaaaa aaaaa. aaaaaaa aaaaa aaaaaa, aa aaaaa aaaaa, aaaaaaaa aaaaaaa, aaaaaa aaaaaaa, aaaa. aaa aaaaaaaa. aaaa aaaa. aaaaaaaaaaaa aa aaaaa aaa aaaaaa aaaa aaaaaaaaaa aaaaaa. aaaaaaa aaaaaaaaa aaaaaaaaa aaaaaa aaaa . aaaaaaaa aaaaaa aaaa aaaaaaaa.
+</div>
+</body>
+
diff --git a/chromium/tools/perf/page_sets/tough_texture_upload_cases.json b/chromium/tools/perf/page_sets/tough_texture_upload_cases.json
new file mode 100644
index 00000000000..8b14979e3d1
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_texture_upload_cases.json
@@ -0,0 +1,10 @@
+{
+ "description": "A collection of texture upload performance tests",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ { "url": "file:///tough_texture_upload_cases/background_color_animation.html" },
+ { "url": "file:///tough_texture_upload_cases/background_color_animation_and_transform_animation.html" },
+ { "url": "file:///tough_texture_upload_cases/background_color_animation_with_gradient.html" },
+ { "url": "file:///tough_texture_upload_cases/background_color_animation_with_gradient_and_transform_animation.html" }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation.html b/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation.html
new file mode 100644
index 00000000000..bb8e3cba00c
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ @-webkit-keyframes color-animation {
+ 0% { background:#000; }
+ 100% { background:#fff; }
+ }
+
+ div {
+ position: absolute;
+ -webkit-transform-style: preserve-3d;
+ }
+ </style>
+ <script type="text/javascript">
+ function startExperiment()
+ {
+ document.body.style.margin = "0";
+ document.body.style.webkitAnimationName = "color-animation";
+ document.body.style.webkitAnimationDuration = "0.5s";
+ document.body.style.webkitAnimationIterationCount = "infinite";
+ document.body.style.webkitAnimationDirection = "alternate";
+ for (var i = 0; i < 2; ++i) {
+ var elem = document.getElementById("elem" + i.toString());
+ elem.style.opacity = "0.5";
+ elem.style.width = "100%";
+ elem.style.height = "900px";
+ elem.style.webkitTransform = "rotate3d(1,1,0," + ((i + 1) * 10).toString() + "deg)";
+ elem.style.webkitAnimationName = "color-animation";
+ elem.style.webkitAnimationDuration = (i + 1).toString() + "s";
+ elem.style.webkitAnimationIterationCount = "infinite";
+ }
+ }
+
+ window.addEventListener('load', startExperiment, false);
+ </script>
+</head>
+<body>
+<div id="elem0"></div>
+<div id="elem1"></div>
+</body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_and_transform_animation.html b/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_and_transform_animation.html
new file mode 100644
index 00000000000..b41ab063b13
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_and_transform_animation.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ @-webkit-keyframes color-animation {
+ 0% { background:#000; }
+ 100% { background:#fff; }
+ }
+
+ @-webkit-keyframes transform-animation {
+ 0% { -webkit-transform: scale(1) rotate3d(1, 1, 1, 0deg); opacity(1); }
+ 50% { -webkit-transform: scale(10) rotate3d(1, 1, 1, 45deg); opacity(0); }
+ 100% { -webkit-transform: scale(1) rotate3d(1, 1, 1, 0deg); opacity(1); }
+ }
+
+ div {
+ position: absolute;
+ -webkit-transform-style: preserve-3d;
+ }
+
+ .poster {
+ height: 50px;
+ width: 50px;
+ background-color: gray;
+ -webkit-border-radius: 10px;
+ font-family: 'Georgia', serif;
+ border: 2px solid black;
+ font-size: 42px;
+ font-weight: bold;
+ text-align: center;
+ }
+ </style>
+ <script type="text/javascript">
+ function startExperiment()
+ {
+ document.body.style.margin = "0";
+ document.body.style.webkitAnimationName = "color-animation";
+ document.body.style.webkitAnimationDuration = "0.5s";
+ document.body.style.webkitAnimationIterationCount = "infinite";
+ document.body.style.webkitAnimationDirection = "alternate";
+ for (var i = 0; i < 2; ++i) {
+ var elem = document.getElementById("elem" + i.toString());
+ elem.style.opacity = "0.5";
+ elem.style.width = "100%";
+ elem.style.height = "900px";
+ elem.style.webkitTransform = "rotate3d(1,1,0," + ((i + 1) * 10).toString() + "deg)";
+ elem.style.webkitAnimationName = "color-animation";
+ elem.style.webkitAnimationDuration = (i + 1).toString() + "s";
+ elem.style.webkitAnimationIterationCount = "infinite";
+ }
+ var transformed_elem = document.getElementById("transformed-elem0");
+ transformed_elem.style.left = "250px";
+ transformed_elem.style.top = "250px";
+ transformed_elem.style.webkitAnimationName = "transform-animation";
+ transformed_elem.style.webkitAnimationDuration = "5s";
+ transformed_elem.style.webkitAnimationIterationCount = "infinite";
+ }
+
+ window.addEventListener('load', startExperiment, false);
+ </script>
+</head>
+<body>
+<div id="elem0"></div>
+<div id="elem1"></div>
+<div id="transformed-elem0"><p class="poster">?</p></div>
+</body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_with_gradient.html b/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_with_gradient.html
new file mode 100644
index 00000000000..a3f83951292
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_with_gradient.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ @-webkit-keyframes color-animation {
+ 0% { background:#000; }
+ 100% { background:#fff; }
+ }
+
+ div {
+ position: absolute;
+ -webkit-transform-style: preserve-3d;
+ }
+
+ .gradient {
+ background:-webkit-repeating-radial-gradient(circle, red, green 5%, blue 10%, red 15%);
+ opacity: 0.25;
+ width:100%;
+ height:900px;
+ }
+ </style>
+ <script type="text/javascript">
+ function startExperiment()
+ {
+ document.body.style.margin = "0";
+ document.body.style.webkitAnimationName = "color-animation";
+ document.body.style.webkitAnimationDuration = "0.5s";
+ document.body.style.webkitAnimationIterationCount = "infinite";
+ document.body.style.webkitAnimationDirection = "alternate";
+ for (var i = 0; i < 2; ++i) {
+ var elem = document.getElementById("elem" + i.toString());
+ elem.style.opacity = "0.5";
+ elem.style.width = "100%";
+ elem.style.height = "900px";
+ elem.style.webkitTransform = "rotate3d(1,1,0," + ((i + 1) * 10).toString() + "deg)";
+ elem.style.webkitAnimationName = "color-animation";
+ elem.style.webkitAnimationDuration = (i + 1).toString() + "s";
+ elem.style.webkitAnimationIterationCount = "infinite";
+ }
+ }
+
+ window.addEventListener('load', startExperiment, false);
+ </script>
+</head>
+<body>
+<div class="gradient"></div>
+<div id="elem0"><div class="gradient"></div></div>
+<div id="elem1"><div class="gradient"></div></div>
+</body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_with_gradient_and_transform_animation.html b/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_with_gradient_and_transform_animation.html
new file mode 100644
index 00000000000..11a2aca82b3
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_texture_upload_cases/background_color_animation_with_gradient_and_transform_animation.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style type="text/css">
+ @-webkit-keyframes color-animation {
+ 0% { background:#000; }
+ 100% { background:#fff; }
+ }
+
+ @-webkit-keyframes transform-animation {
+ 0% { -webkit-transform: scale(1) rotate3d(1, 1, 1, 0deg); opacity(1); }
+ 50% { -webkit-transform: scale(10) rotate3d(1, 1, 1, 45deg); opacity(0); }
+ 100% { -webkit-transform: scale(1) rotate3d(1, 1, 1, 0deg); opacity(1); }
+ }
+
+ div {
+ position: absolute;
+ -webkit-transform-style: preserve-3d;
+ }
+
+ .gradient {
+ background:-webkit-repeating-radial-gradient(circle, red, green 5%, blue 10%, red 15%);
+ opacity: 0.25;
+ width:100%;
+ height:900px;
+ }
+
+ .poster {
+ height: 50px;
+ width: 50px;
+ background-color: gray;
+ -webkit-border-radius: 10px;
+ font-family: 'Georgia', serif;
+ border: 2px solid black;
+ font-size: 42px;
+ font-weight: bold;
+ text-align: center;
+ }
+ </style>
+ <script type="text/javascript">
+ function startExperiment()
+ {
+ document.body.style.margin = "0";
+ document.body.style.webkitAnimationName = "color-animation";
+ document.body.style.webkitAnimationDuration = "0.5s";
+ document.body.style.webkitAnimationIterationCount = "infinite";
+ document.body.style.webkitAnimationDirection = "alternate";
+ for (var i = 0; i < 2; ++i) {
+ var elem = document.getElementById("elem" + i.toString());
+ elem.style.opacity = "0.5";
+ elem.style.width = "100%";
+ elem.style.height = "900px";
+ elem.style.webkitTransform = "rotate3d(1,1,0," + ((i + 1) * 10).toString() + "deg)";
+ elem.style.webkitAnimationName = "color-animation";
+ elem.style.webkitAnimationDuration = (i + 1).toString() + "s";
+ elem.style.webkitAnimationIterationCount = "infinite";
+ }
+ var transformed_elem = document.getElementById("transformed-elem0");
+ transformed_elem.style.left = "250px";
+ transformed_elem.style.top = "250px";
+ transformed_elem.style.webkitAnimationName = "transform-animation";
+ transformed_elem.style.webkitAnimationDuration = "5s";
+ transformed_elem.style.webkitAnimationIterationCount = "infinite";
+ }
+
+ window.addEventListener('load', startExperiment, false);
+ </script>
+</head>
+<body>
+<div class="gradient"></div>
+<div id="elem0"><div class="gradient"></div></div>
+<div id="elem1"><div class="gradient"></div></div>
+<div id="transformed-elem0"><p class="poster">?</p></div>
+</body>
+</html>
diff --git a/chromium/tools/perf/page_sets/tough_video_cases.json b/chromium/tools/perf/page_sets/tough_video_cases.json
new file mode 100644
index 00000000000..5f4f59338b9
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases.json
@@ -0,0 +1,75 @@
+{
+ "description": "Video Stack Perf benchmark",
+ "play_audio": [
+ { "action": "play",
+ "selector": "#audio_1",
+ "wait_for_playing": true,
+ "wait_for_ended": true
+ }
+ ],
+ "play_video": [
+ { "action": "play",
+ "selector": "#video_1",
+ "wait_for_playing": true,
+ "wait_for_ended": true
+ }
+ ],
+ "pages": [
+ {
+ "url": "file:///tough_video_cases/video.html?src=crowd.wav&id=audio_1&type=audio",
+ "media_metrics": {"action": "play_audio"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=crowd.ogg&id=audio_1&type=audio",
+ "media_metrics": {"action": "play_audio"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=crowd1080.mp4&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=crowd1080.ogv&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=crowd1080.webm&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=crowd2160.mp4&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=crowd2160.ogv&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=crowd2160.webm&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=tulip2.mp3&id=audio_1&type=audio",
+ "media_metrics": {"action": "play_audio"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=tulip2.ogg&id=audio_1&type=audio",
+ "media_metrics": {"action": "play_audio"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=tulip2.wav&id=audio_1&type=audio",
+ "media_metrics": {"action": "play_audio"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=tulip2.mp4&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=tulip2.ogv&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ },
+ {
+ "url": "file:///tough_video_cases/video.html?src=tulip2.webm&id=video_1&type=video",
+ "media_metrics": {"action": "play_video"}
+ }
+ ]
+}
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/bear.webm b/chromium/tools/perf/page_sets/tough_video_cases/bear.webm
new file mode 100644
index 00000000000..a1b4150b32f
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/bear.webm
Binary files differ
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd.ogg.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd.ogg.sha1
new file mode 100644
index 00000000000..32e88b381ad
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd.ogg.sha1
@@ -0,0 +1 @@
+99e2eaf71bad8e084885317b5922855f2dcdf133 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd.wav.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd.wav.sha1
new file mode 100644
index 00000000000..065dc001bbf
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd.wav.sha1
@@ -0,0 +1 @@
+17d48d36b74701799999a0d3dc25a67038c75caa \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.mp4.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.mp4.sha1
new file mode 100644
index 00000000000..3ead99b6055
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.mp4.sha1
@@ -0,0 +1 @@
+da1c09dd48dcd2eb76449d97c4fa38460d3a1e8d \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.ogv.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.ogv.sha1
new file mode 100644
index 00000000000..75f88665af6
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.ogv.sha1
@@ -0,0 +1 @@
+c3da321e4f90e9aa61d1237058af65131f027854 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.webm.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.webm.sha1
new file mode 100644
index 00000000000..b4b155a84bb
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd1080.webm.sha1
@@ -0,0 +1 @@
+454ecb15fa314b2f30cdca066e9878d436d91354 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.mp4.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.mp4.sha1
new file mode 100644
index 00000000000..f079662c7d9
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.mp4.sha1
@@ -0,0 +1 @@
+c9651176398fa86932adac7fe534eb018f7862ce \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.ogv.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.ogv.sha1
new file mode 100644
index 00000000000..5b6996125a6
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.ogv.sha1
@@ -0,0 +1 @@
+ece42bcc8c0ffc31625901496d1e89362e84f2b9 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.webm.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.webm.sha1
new file mode 100644
index 00000000000..0cb63a3cd93
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd2160.webm.sha1
@@ -0,0 +1 @@
+c1e3675623f4d2cd72e56dcaad432e0e8cc26d9c \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd360.mp4.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd360.mp4.sha1
new file mode 100644
index 00000000000..2b2c11892dd
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd360.mp4.sha1
@@ -0,0 +1 @@
+47c24efa843893f31215ffd8b076793e306a89c0 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd360.ogv.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd360.ogv.sha1
new file mode 100644
index 00000000000..ff29292ad8a
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd360.ogv.sha1
@@ -0,0 +1 @@
+59ea02c91615499cfa15026de0c3c56821105d44 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd360.webm.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd360.webm.sha1
new file mode 100644
index 00000000000..e7683cde408
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd360.webm.sha1
@@ -0,0 +1 @@
+468b759e2252e6ea5553c68446cb9a92e20a9a93 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd480.webm.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd480.webm.sha1
new file mode 100644
index 00000000000..c2724f329fc
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd480.webm.sha1
@@ -0,0 +1 @@
+470f851bcde812871187afbdf79db1625c8c48fc \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/crowd720.webm.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/crowd720.webm.sha1
new file mode 100644
index 00000000000..6bc8d0d5255
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/crowd720.webm.sha1
@@ -0,0 +1 @@
+7ff870ce89dee7718455ba2eb8e1b0d835fc0d56 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/tulip2.m4a.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.m4a.sha1
new file mode 100644
index 00000000000..5b1efe6d111
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.m4a.sha1
@@ -0,0 +1 @@
+07452b1617444f2da14aaa48e1450855d4e69c26 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/tulip2.mp3.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.mp3.sha1
new file mode 100644
index 00000000000..c39d5081ff2
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.mp3.sha1
@@ -0,0 +1 @@
+a3075f6f73b624e3d8cd3e3db4b992075561d30b \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/tulip2.mp4.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.mp4.sha1
new file mode 100644
index 00000000000..9219a7bf6bd
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.mp4.sha1
@@ -0,0 +1 @@
+bff0bea43cb21eaee851e23d65724b556ff50794 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/tulip2.ogg.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.ogg.sha1
new file mode 100644
index 00000000000..c0004af9136
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.ogg.sha1
@@ -0,0 +1 @@
+f413b908543c2bf05520990cb86bd6648490d576 \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/tulip2.ogv.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.ogv.sha1
new file mode 100644
index 00000000000..e33446ca8a2
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.ogv.sha1
@@ -0,0 +1 @@
+e6e14183467faad4f5800b02ca8c9deb5d59191f \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/tulip2.wav.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.wav.sha1
new file mode 100644
index 00000000000..17a1e9a66de
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.wav.sha1
@@ -0,0 +1 @@
+b689399395345ab9e052caaa2d47ede1a07774ec \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/tulip2.webm.sha1 b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.webm.sha1
new file mode 100644
index 00000000000..cd93dcf5998
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/tulip2.webm.sha1
@@ -0,0 +1 @@
+091425493334b1505aa0fe5b1d0f36fd1d8ac8bb \ No newline at end of file
diff --git a/chromium/tools/perf/page_sets/tough_video_cases/video.html b/chromium/tools/perf/page_sets/tough_video_cases/video.html
new file mode 100644
index 00000000000..2c7c9a08a38
--- /dev/null
+++ b/chromium/tools/perf/page_sets/tough_video_cases/video.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ </body>
+ <script>
+ function getQueryStrings() {
+ // Gets query parameters from the URL; e.g., given a URL like:
+ //
+ // http://<url>/my.html?test=123&bob=456
+ //
+ // returns params["test"] = 123, params["bob"]=456, etc.
+ var params = {};
+
+ // RegEx to split out values by &.
+ var r = /([^&=]+)=?([^&]*)/g;
+
+ // Lambda function for decoding extracted match values. Replaces '+' with
+ // space so decodeURIComponent functions properly.
+ function d(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }
+
+ var match;
+ while (match = r.exec(window.location.search.substring(1)))
+ params[d(match[1])] = d(match[2]);
+
+ return params;
+ }
+ qsParams = getQueryStrings();
+ if (qsParams["type"] != "") {
+ testElement = document.createElement(qsParams["type"]);
+ if (qsParams["id"] != "")
+ testElement.id = qsParams["id"];
+ testElement.src = qsParams["src"];
+ testElement.controls = true;
+ document.body.appendChild(testElement);
+ }
+ </script>
+</html>
diff --git a/chromium/tools/perf/page_sets/typical_25.json b/chromium/tools/perf/page_sets/typical_25.json
new file mode 100644
index 00000000000..b9b5606fcc7
--- /dev/null
+++ b/chromium/tools/perf/page_sets/typical_25.json
@@ -0,0 +1,92 @@
+{
+ "description": "Pages designed to represent the median, not highly optimized web",
+ "archive_data_file": "../data/typical_25.json",
+ "user_agent_type": "desktop",
+ "smoothness": { "action": "scroll" },
+ "pages": [
+ {
+ "url": "http://www.nick.com/games",
+ "why": "Alexa games #48"
+ },
+ {
+ "url": "http://www.rei.com/",
+ "why": "Alexa sports #45"
+ },
+ {
+ "url": "http://www.fifa.com/",
+ "why": "Alexa sports #50"
+ },
+ {
+ "url": "http://www.gamestop.com/ps3",
+ "why": "Alexa shopping #41"
+ },
+ {
+ "url": "http://www.barnesandnoble.com/u/books-bestselling-books/379003057/",
+ "why": "Alexa shopping #25"
+ },
+ {
+ "url": "http://www.economist.com/news/science-and-technology/21573529-small-models-cosmic-phenomena-are-shedding-light-real-thing-how-build",
+ "why": "Alexa news #55"
+ },
+ {
+ "url": "http://www.theonion.com",
+ "why": "Alexa news #67"
+ },
+ {
+ "url": "http://arstechnica.com/"
+ },
+ {
+ "url": "http://allrecipes.com/Recipe/Pull-Apart-Hot-Cross-Buns/Detail.aspx",
+ "why": "Alexa home #10"
+ },
+ {
+ "url": "http://www.html5rocks.com/en/"
+ },
+ {
+ "url": "http://www.mlb.com/"
+ },
+ {
+ "url": "http://gawker.com/5939683/based-on-a-true-story-is-a-rotten-lie-i-hope-you-never-believe"
+ },
+ {
+ "url": "http://www.imdb.com/title/tt0910970/"
+ },
+ {
+ "url": "http://www.flickr.com/search/?q=monkeys&f=hp"
+ },
+ {
+ "url": "http://money.cnn.com/"
+ },
+ {
+ "url": "http://www.nationalgeographic.com/"
+ },
+ {
+ "url": "http://premierleague.com"
+ },
+ {
+ "url": "http://www.osubeavers.com/"
+ },
+ {
+ "url": "http://walgreens.com"
+ },
+ {
+ "url": "http://colorado.edu"
+ },
+ {
+ "url": "http://www.ticketmaster.com/JAY-Z-and-Justin-Timberlake-tickets/artist/1837448?brand=none&tm_link=tm_homeA_rc_name2"
+ },
+ {
+ "url": "http://www.theverge.com/2013/3/5/4061684/inside-ted-the-smartest-bubble-in-the-world"
+ },
+ {
+ "url": "http://www.airbnb.com/"
+ },
+ {
+ "url": "http://www.ign.com/"
+ },
+ {
+ "url": "http://www.fda.gov",
+ "why": "Alexa health #25"
+ }
+ ]
+}
diff --git a/chromium/tools/perf/perf_tools/__init__.py b/chromium/tools/perf/perf_tools/__init__.py
new file mode 100644
index 00000000000..3e13108e2fb
--- /dev/null
+++ b/chromium/tools/perf/perf_tools/__init__.py
@@ -0,0 +1,39 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""A library for Chrome GPU test code."""
+import os
+import sys
+
+
+def _RemoveAllStalePycFiles():
+ for dirname, _, filenames in os.walk(os.path.dirname(__file__)):
+ if '.svn' in dirname or '.git' in dirname:
+ continue
+ for filename in filenames:
+ root, ext = os.path.splitext(filename)
+ if ext != '.pyc':
+ continue
+
+ pyc_path = os.path.join(dirname, filename)
+ py_path = os.path.join(dirname, root + '.py')
+ if not os.path.exists(py_path):
+ os.remove(pyc_path)
+
+ if not os.listdir(dirname):
+ os.removedirs(dirname)
+
+
+def Init():
+ telemetry_path = os.path.join(os.path.dirname(__file__),
+ os.pardir, os.pardir, 'telemetry')
+ absolute_telemetry_path = os.path.abspath(telemetry_path)
+ sys.path.append(absolute_telemetry_path)
+ telemetry_tools_path = os.path.join(os.path.dirname(__file__),
+ os.pardir, os.pardir, 'telemetry_tools')
+ absolute_telemetry_tools_path = os.path.abspath(telemetry_tools_path)
+ sys.path.append(absolute_telemetry_tools_path)
+
+
+_RemoveAllStalePycFiles()
+Init()
diff --git a/chromium/tools/perf/perf_tools/bootstrap_deps b/chromium/tools/perf/perf_tools/bootstrap_deps
new file mode 100644
index 00000000000..18234083764
--- /dev/null
+++ b/chromium/tools/perf/perf_tools/bootstrap_deps
@@ -0,0 +1,29 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file specifies dependencies required to bootstrap tools/perf. It is in a
+# minimal version of the format used by other DEPS files that gclient can read,
+# but it should only be used to bootstrap tools/perf *outside* of a normal
+# Chrome checkout.
+
+deps = {
+ "src/tools/perf/benchmarks":
+ "https://src.chromium.org/chrome/trunk/src/tools/perf/benchmarks",
+ "src/tools/perf/measurements":
+ "https://src.chromium.org/chrome/trunk/src/tools/perf/measurements",
+ "src/tools/perf/page_sets":
+ "https://src.chromium.org/chrome/trunk/src/tools/perf/page_sets",
+ "src/tools/perf/metrics":
+ "https://src.chromium.org/chrome/trunk/src/tools/perf/metrics",
+ "src/tools/perf/perf_tools":
+ "https://src.chromium.org/chrome/trunk/src/tools/perf/perf_tools",
+ "src/tools/perf/profile_creators":
+ "https://src.chromium.org/chrome/trunk/src/tools/perf/profile_creators",
+ }
+
+# tools/perf depends on Telemetry, so pull in the Telemetry deps, too.
+deps_includes = {
+ "src/tools/telemetry_tools/bootstrap_deps":
+ "https://src.chromium.org/chrome/trunk/src/tools/telemetry_tools/bootstrap_deps",
+ }
diff --git a/chromium/tools/perf/profile_creators/__init__.py b/chromium/tools/perf/profile_creators/__init__.py
new file mode 100644
index 00000000000..f1e2bf49a75
--- /dev/null
+++ b/chromium/tools/perf/profile_creators/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Generators for Chrome profiles for testing purposes."""
diff --git a/chromium/tools/perf/profile_creators/small_profile_creator.py b/chromium/tools/perf/profile_creators/small_profile_creator.py
new file mode 100644
index 00000000000..020f81f3fa4
--- /dev/null
+++ b/chromium/tools/perf/profile_creators/small_profile_creator.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+from telemetry.core import profile_creator
+from telemetry.page import page_set
+
+class SmallProfileCreator(profile_creator.ProfileCreator):
+ """
+ Runs a browser through a series of operations to fill in a small test profile.
+ """
+
+ def CreateProfile(self):
+ top_25 = os.path.join(os.path.dirname(__file__),
+ '..', 'page_sets', 'top_25.json')
+ pages_to_load = page_set.PageSet.FromFile(top_25)
+ tab = self._browser.tabs[0]
+ for page in pages_to_load:
+ tab.Navigate(page.url)
+ tab.WaitForDocumentReadyStateToBeComplete()
+ tab.Disconnect()
diff --git a/chromium/tools/perf/record_wpr b/chromium/tools/perf/record_wpr
new file mode 100755
index 00000000000..e12055f2168
--- /dev/null
+++ b/chromium/tools/perf/record_wpr
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+# Add telemetry to sys.path so that it can be imported below
+# Relative path from this file is ../telemetry
+_perf_dir = os.path.dirname(__file__)
+_telemetry_path = os.path.join(_perf_dir, os.pardir, 'telemetry')
+sys.path.append(_telemetry_path)
+
+from telemetry.page import record_wpr
+
+if __name__ == '__main__':
+ sys.exit(record_wpr.Main(_perf_dir))
diff --git a/chromium/tools/perf/run_benchmark b/chromium/tools/perf/run_benchmark
new file mode 100755
index 00000000000..434000e2180
--- /dev/null
+++ b/chromium/tools/perf/run_benchmark
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, 'telemetry'))
+
+from telemetry import test_runner
+
+if __name__ == '__main__':
+ sys.exit(test_runner.Main())
diff --git a/chromium/tools/perf/run_measurement b/chromium/tools/perf/run_measurement
new file mode 100755
index 00000000000..9c103ce5757
--- /dev/null
+++ b/chromium/tools/perf/run_measurement
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import imp
+import os
+import sys
+import urllib
+
+# Directory path in which to save bootstrap files.
+BOOTSTRAPPED_FILES_DIR = 'support/bootstrap_files'
+PERF_DIR = 'src/tools/perf'
+DEPS_FILE = 'bootstrap_deps'
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+def BootstrapIfNeeded(module_name, module_path, module_deps_url):
+ """Ensures that the given module_name is available, grab from URL if not."""
+ try:
+ imp.find_module(module_name)
+ return
+ except ImportError:
+ sys.path.append(os.path.join(BASE_DIR, BOOTSTRAPPED_FILES_DIR, module_path))
+ try:
+ imp.find_module(module_name)
+ return
+ except ImportError:
+ bootstrap_txt = urllib.urlopen('http://src.chromium.org/viewvc/chrome/' +
+ 'trunk/src/tools/telemetry_tools/' +
+ 'telemetry_bootstrap.py').read()
+ bootstrap = imp.new_module('bootstrap')
+ exec bootstrap_txt in bootstrap.__dict__
+ bootstrap.DownloadDepsURL(os.path.join(BASE_DIR, BOOTSTRAPPED_FILES_DIR),
+ module_deps_url)
+ return
+
+def ListBootstrapDeps():
+ """List the deps required for telemetry.
+
+ Returns: a list of telemetry deps.
+ """
+ # Add telemetry_tools to sys.path for the import below
+ telemetry_tools_path = os.path.join(BASE_DIR, os.pardir, 'telemetry_tools')
+ sys.path.append(telemetry_tools_path)
+
+ import perf_tools
+ import telemetry_bootstrap
+ deps_file = os.path.join(os.path.dirname(perf_tools.__file__), DEPS_FILE)
+ return telemetry_bootstrap.ListAllDepsPaths(open(deps_file).read())
+
+def main():
+ BootstrapIfNeeded('perf_tools', PERF_DIR,
+ 'http://src.chromium.org/viewvc/chrome/trunk/src/tools'
+ '/perf/perf_tools/' + DEPS_FILE)
+
+ # Add telemetry to sys.path for the import below
+ telemetry_path = os.path.join(BASE_DIR, os.pardir, 'telemetry')
+ sys.path.append(telemetry_path)
+
+ if '--print-bootstrap-deps' in sys.argv:
+ print ListBootstrapDeps()
+ sys.exit(0)
+
+ from telemetry.page import page_measurement_runner
+ import page_sets
+ page_set_filenames = page_sets.GetAllPageSetFilenames()
+
+ old_benchmark_names = {
+ "image_decoding_benchmark": "image_decoding",
+ "image_decoding_measurement": "image_decoding",
+ "loading_benchmark": "loading",
+ "loading_measurement": "loading",
+ "media_measurement": "media",
+ "memory_benchmark": "memory",
+ "memory_measurement": "memory",
+ "rasterize_and_record_benchmark": "rasterize_and_record",
+ "rasterize_and_record_measurement": "rasterize_and_record",
+ "robohornetpro": "robohornet_pro",
+ "scrolling_benchmark": "smoothness",
+ "smoothness_benchmark": "smoothness",
+ "smoothness_measurement": "smoothness",
+ "startup_benchmark": "startup_warm_blank_page",
+ "startup_measurement": "startup",
+ "tab_switching_measurement": "tab_switching",
+ }
+
+ # There are bots that are hard-coded to run some specific named tests.
+ # Convert these to the current naming conventions by overriding them in the runner.
+ class MeasurementRunner(page_measurement_runner.PageMeasurementRunner):
+ def GetModernizedTestName(self, arg):
+ if arg not in old_benchmark_names:
+ return arg
+ sys.stderr.write(
+ 'An old name %s was given. Please use %s in the future.\n' % (
+ arg,
+ old_benchmark_names.get(arg)))
+ return old_benchmark_names[arg]
+
+ runner = MeasurementRunner()
+ sys.exit(runner.Run(BASE_DIR, page_set_filenames))
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/perf/run_multipage_benchmarks b/chromium/tools/perf/run_multipage_benchmarks
new file mode 100755
index 00000000000..150b51b299e
--- /dev/null
+++ b/chromium/tools/perf/run_multipage_benchmarks
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import imp
+import os
+import sys
+
+run_measurement = imp.load_source(
+ 'run_measurement',
+ os.path.join(os.path.dirname(__file__), 'run_measurement'))
+
+if __name__ == '__main__':
+ print >> sys.stderr, 'This script is deprecated. Use run_measurement instead.'
+ sys.exit(run_measurement.main())
diff --git a/chromium/tools/perf/run_tests b/chromium/tools/perf/run_tests
new file mode 100755
index 00000000000..36eefbb5ef3
--- /dev/null
+++ b/chromium/tools/perf/run_tests
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""This script runs unit tests of the code in the perf directory.
+
+This script DOES NOT run benchmarks. run_benchmarks and run_measurement do that.
+"""
+
+import os
+import sys
+
+import measurements
+import perf_tools
+from telemetry.unittest import gtest_testrunner
+from telemetry.unittest import run_tests
+
+if __name__ == '__main__':
+ top_level_dir = os.path.abspath(os.path.dirname(__file__))
+ runner = gtest_testrunner.GTestTestRunner(print_result_after_run=False)
+
+ start_dir = 'measurements'
+ ret = run_tests.Main(sys.argv[1:], start_dir, top_level_dir, runner)
+
+ start_dir = 'perf_tools'
+ ret += run_tests.Main(sys.argv[1:], start_dir, top_level_dir, runner)
+
+ start_dir = 'metrics'
+ ret += run_tests.Main(sys.argv[1:], start_dir, top_level_dir, runner)
+
+ if runner.result:
+ runner.result.PrintSummary()
+ sys.exit(min(ret + runner.result.num_errors, 255))
+ else:
+ sys.exit(ret)
diff --git a/chromium/tools/perf/test-info.json b/chromium/tools/perf/test-info.json
new file mode 100644
index 00000000000..79caaad9b70
--- /dev/null
+++ b/chromium/tools/perf/test-info.json
@@ -0,0 +1,295 @@
+{
+ "_description": "This file contains info about our performance test suites, used by the perf dashboard (http://chromeperf.appspot.com).",
+ "blink_perf": {
+ "description": "Runs all enabled benchmarks in third_party/WebKit/PerformanceTests/",
+ "code": [
+ "chrome/src/tools/perf/measurements/blink_perf.py",
+ "third_party/WebKit/PerformanceTests/"
+ ]
+ },
+ "bloat": {
+ "description": "Load an image many times and ensure memory usage stays low.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/page_cycler/bloat.json",
+ "chrome/src/tools/perf/measurements/page_cycler.py"
+ ]
+ },
+ "cc_perftests": {
+ "description": "Microbenchmarks for compositor (cc/) component.",
+ "code": [
+ "chrome/src/cc/cc_tests.gyp",
+ "chrome/src/cc/trees/layer_tree_host_perftest.cc"
+ ]
+ },
+ "dhtml": {
+ "description": "Benchmarks for various DHTML operations like simple animations.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/page_cycler/dhtml.json",
+ "chrome/src/tools/perf/measurements/page_cycler.py"
+ ]
+ },
+ "dom_perf": {
+ "description": "Performance of DOM operations.",
+ "code": ["chrome/src/tools/perf/benchmarks/dom_perf.py"]
+ },
+ "dromaeo_domcoreattr": {
+ "description": "Setting and getting DOM node attributes.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/domcoreattr.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_domcoremodify": {
+ "description": "Creating and injecting DOM nodes.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/domcoremodify.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_domcorequery": {
+ "description": "Querying DOM elements in a document.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/domcorequery.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_domcoretraverse": {
+ "description": "Traversing a DOM structure.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/domcoretraverse.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibattrjquery": {
+ "description": "Setting and getting DOM node attributes using the jQuery JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibattrjquery.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibattrprototype": {
+ "description": "Setting and getting DOM node attributes using the Prototype JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibattrprototype.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibeventjquery": {
+ "description": "Binding, removing, and triggering DOM events using the jQuery JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibattrprototype.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibeventprototype": {
+ "description": "Binding, removing, and triggering DOM events using the Prototype JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibeventprototype.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibmodifyjquery": {
+ "description": "Creating and injecting DOM nodes into a document using the jQuery JavaScript Library",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibmodifyjquery.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibmodifyprototype": {
+ "description": "Creating and injecting DOM nodes into a document using the Prototype JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibmodifyprototype.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibstylejquery": {
+ "description": "Getting and setting CSS information on DOM elements using the jQuery JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibstylejquery.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibstyleprototype": {
+ "description": "Getting and setting CSS information on DOM elements using the Prototype JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibstyleprototype.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibtraversejquery": {
+ "description": "Traversing a DOM structure using the jQuery JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibtraversejquery.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "dromaeo_jslibtraverseprototype": {
+ "description": "Traversing a DOM structure using the Prototype JavaScript Library.",
+ "code": [
+ "chrome/src/tools/perf/page_sets/dromaeo/jslibtraverseprototype.json",
+ "chrome/src/tools/perf/measurements/dromaeo.py"
+ ]
+ },
+ "idb_perf": {
+ "description": "Benchmarks for a variety of IndexedDB operations.",
+ "code": [
+ "chrome/src/chrome/test/perf/indexeddb_uitest.cc",
+ "chrome/src/chrome/test/data/indexeddb/perf_test.html"
+ ]
+ },
+ "image_decoding_measurement": {
+ "description": "Milliseconds to decode a large image of various formats (gif, jpg, png, webp).",
+ "code": [
+ "chrome/src/tools/perf/measurements/image_decoding.py",
+ "chrome/src/tools/perf/page_sets/image_decoding_measurement.json"
+ ]
+ },
+ "indexeddb": {
+ "description": "Benchmark for a basic insert operation in Indexed DB.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/page_cycler/indexed_db/basic_insert.json"
+ ]
+ },
+ "intl_ar_fa_he": {
+ "description": "Page load time benchmark for a variety of pages in Arabic, Farsi and Hebrew. Runs against pages recorded in April, 2013.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/intl_ar_fa_he.json"
+ ]
+ },
+ "intl_es_fr_pt-BR": {
+ "description": "Page load time benchmark for a variety of pages in Spanish, French and Brazilian Portuguese. Runs against pages recorded in April, 2013.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/intl_es_fr_pt-BR.json"
+ ]
+ },
+ "intl_hi_ru": {
+ "description": "Page load time benchmark for a variety of pages in Hindi and Russian. Runs against pages recorded in April, 2013.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/intl_hi_ru.json"
+ ]
+ },
+ "intl_ja_zh": {
+ "description": "Page load time benchmark for a variety of pages in Japanese and Chinese. Runs against pages recorded in April, 2013.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/intl_ja_zh.json"
+ ]
+ },
+ "intl_ko_th_vi": {
+ "description": "Page load time benchmark for a variety of pages in Korean, Thai and Vietnamese. Runs against pages recorded in April, 2013.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/intl_ko_th_vi.json"
+ ]
+ },
+ "jsgamebench": {
+ "description": "Score on [Facebook's JSGameBench benchmark](https://github.com/facebook/jsgamebench).\n\nThe focus is sprite performance a player is likely to see. Scoring is how many sprites are drawn, so large scores are better.\n\nFor each render path, JSGameBench draws as many moving, animating sprites as possible at 30fps against a background with both axis-aligned and rotated sprites. We try both because significant performance differences between the two indicate flaws or oversights in current rendering techniques. More importantly, while animation can be used instead of sprite rotations, it is often an unacceptable trade off that game developers should not be forced to make.\n\nThe final score is the geometric mean of the axis aligned and rotated scores. Geometric mean is used to prevent a high axis aligned score from hiding the poor rotated performance.",
+ "code": ["chrome/src/tools/perf/benchmarks/jsgamebench.py"]
+ },
+ "kraken": {
+ "description": "Score on [Mozilla's Kraken JavaScript benchmark](http://krakenbenchmark.mozilla.org/)",
+ "code": ["chrome/src/tools/perf/benchmarks/kraken.py"]
+ },
+ "mach_ports": {
+ "description": "This test spawns a new browser and counts the number of open Mach ports in the browser process. It navigates tabs and closes them, repeatedly measuring the number of open ports. This is used to protect against leaking Mach ports, which was the source of [bug 105513](http://crbug.com/105513).",
+ "code": [
+ "chrome/src/chrome/test/perf/mach_ports_test.cc"
+ ]
+ },
+ "memory_measurement": {
+ "description": "Use (recorded versions of) real world web sites and measure memory consumption.",
+ "code": [
+ "chrome/src/tools/perf/measurements/memory.py",
+ "chrome/src/tools/perf/page_sets/top_25.json"
+ ]
+ },
+ "memory_test": {
+ "description": "Loads a number of URLs across tabs and windows and measures the memory usage.",
+ "code": ["chrome/src/chrome/test/perf/memory_test.cc"]
+ },
+ "morejs": {
+ "description": "Page loading benchmark for a variety of pages that were JavaScript heavy in 2009.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/page_cycler/morejs.json"
+ ]
+ },
+ "moz": {
+ "description": "Page loading benchmark for mozilla's original page set. Recorded in December 2000.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/page_cycler/moz.json"
+ ]
+ },
+ "octane": {
+ "description": "Score on the [V8 team's Octane benchmark](http://octane-benchmark.googlecode.com/svn/latest/index.html)",
+ "code": ["chrome/src/tools/perf/benchmarks/octane.py"]
+ },
+ "pica": {
+ "description": "Loading benchmark for the Polymer toolkit's [Pica](http://www.polymer-project.org/polymer-all/projects/pica/index.html) demo app",
+ "code": ["chrome/src/tools/perf/benchmarks/pica.py"]
+ },
+ "page_cycler_2012Q2-netsim": {
+ "description": "Page loading benchmark for a set of 25 top pages recorded in Q2, 2012. Despite the name, network simulation has not actually been enabled on this test yet.",
+ "code": ["chrome/test/functional/perf.py"]
+ },
+ "robohornetpro": {
+ "description": "Milliseconds to complete the [RoboHornetPro demo by Microsoft](http://ie.microsoft.com/testdrive/performance/robohornetpro/)",
+ "code": ["chrome/src/tools/perf/benchmarks/robohornet_pro.py"]
+ },
+ "sizes": {
+ "description": "Tracks binary sizes and number of static initializers.",
+ "code": ["chrome/tools/build/scripts/slave/chromium/sizes.py"]
+ },
+ "smoothness_measurement": {
+ "description": "Measures frame rate and a variety of other statistics while scrolling down the top 25 web pages. [Documentation](http://www.chromium.org/developers/design-documents/rendering-benchmarks).",
+ "code": [
+ "chrome/src/tools/perf/measurements/smoothness.py",
+ "chrome/src/tools/perf/page_sets/top_25.json"
+ ]
+ },
+ "spaceport": {
+ "description": "Performance on [spaceport.io's perfmarks benchmark](http://spaceport.io/community/perfmarks). This test performs 3 animations (rotate, translate, scale) using a variety of methods (css, webgl, canvas, etc) and reports the number of objects that can be simultaneously animated while still achieving 30FPS.",
+ "code": ["chrome/src/tools/perf/benchmarks/spaceport.py"]
+ },
+ "startup_measurement": {
+ "description": "Measures startup time under various scenarios. This is a port of our old startup_test target to Telemetry.",
+ "code": [
+ "chrome/src/tools/perf/measurements/startup.py",
+ "src/tools/perf/page_sets/blank_page.json"
+ ]
+ },
+ "startup_test": {
+ "description": "Measures startup and shutdown time for 1 tab, 5 tabs, and 10 tabs under a several different user profiles. These tests are in the process of being ported to Telemetry - see the startup_measurement test.",
+ "code": ["chrome/src/chrome/test/perf/startup_test.cc"]
+ },
+ "sunspider": {
+ "description": "Performance on the [SunSpider JavaScript benchmark](http://www.webkit.org/perf/sunspider/sunspider.html)",
+ "code": ["chrome/src/tools/perf/benchmarks/sunspider.py"]
+ },
+ "tough_layout_cases": {
+ "description": "Page loading benchmark for the slowest layouts observed in the Alexa top 1 million sites in July 2013.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/tough_layout_cases.json"
+ ]
+ },
+ "tab_switching_measurement": {
+ "description": "This test records the MPArch.RWH_TabSwitchPaintDuration histogram, which is a measure of the time between when a tab was requested to be shown, and when first paint occurred. The script opens 10 pages in different tabs, waits for them to load, and then switches to each tab and records the metric. The pages were chosen from Alexa top ranking sites.",
+ "code": [
+ "chrome/src/tools/perf/perf_tools/tab_switching_measurement.py",
+ "chrome/src/tools/perf/page_sets/top_10.json"
+ ]
+ },
+ "typical_25": {
+ "description": "Page load time benchmark for a 25 typical web pages. Designed to represent typical, not highly optimized or highly popular web sites. Runs against pages recorded in April, 2013.",
+ "code": [
+ "chrome/src/tools/perf/measurements/page_cycler.py",
+ "chrome/src/tools/perf/page_sets/typical_25.json"
+ ]
+ }
+}
diff --git a/chromium/tools/perf/trace-info.json b/chromium/tools/perf/trace-info.json
new file mode 100644
index 00000000000..963ba4c0349
--- /dev/null
+++ b/chromium/tools/perf/trace-info.json
@@ -0,0 +1,342 @@
+{
+ "_description" : "This file contains info about our performance test traces, used by the perf dashboard (http://chromeperf.appspot.com). Links in test descriptions should be in markdown format. SUITE as the description means the same description as the test suite.",
+
+ "score": {
+ "description": "SUITE"
+ },
+
+ "Score": {
+ "description": "SUITE"
+ },
+
+ "Total": {
+ "description": "SUITE"
+ },
+
+ "ImageDecoding_avg": {
+ "description": "Average decode time of 4 images formats: gif, png, jpg, and webp."
+ },
+ "image_decoding.html?gif": {
+ "description": "Time to decode a 3.1 MB, 2560x1920 gif image. File found at chrome/test/data/image_decoding/droids.gif"
+ },
+ "image_decoding.html?jpg": {
+ "description": "Time to decode a 810 KB, 2560x1920 jpg image. File found at chrome/test/data/image_decoding/droids.jpg"
+ },
+ "image_decoding.html?png": {
+ "description": "Time to decode a 4.6 MB, 2560x1920 png image. File found at chrome/test/data/image_decoding/droids.png"
+ },
+ "image_decoding.html?webp": {
+ "description": "Time to decode a 65 KB, 2560x1920 webp image. File found at chrome/test/data/image_decoding/droids.webp"
+ },
+ "ai-astar": {
+ "description": "This benchmark uses the [A* search algorithm](http://en.wikipedia.org/wiki/A*_search_algorithm) to automatically plot an efficient path between two points, in the presence of obstacles. Adapted from code by [Brian Gringstead](http://www.briangrinstead.com/blog/astar-search-algorithm-in-javascript)."
+ },
+ "audio-beat-detection": {
+ "description": "This benchmark performs [beat detection](http://en.wikipedia.org/wiki/Beat_detection) on an Audio sample using [code](http://beatdetektor.svn.sourceforge.net/viewvc/beatdetektor/trunk/core/js/beatdetektor.js?revision=18&view=markup) from [BeatDetektor](http://www.cubicproductions.com/index.php?option=com_content&view=article&id=67&Itemid=82) and [DSP.js](http://github.com/corbanbrook/dsp.js/)."
+ },
+ "audio-dft": {
+ "description": "This benchmark performs a [Discrete Fourier Transform](http://en.wikipedia.org/wiki/Discrete_Fourier_transform) on an Audio sample using code from [DSP.js](http://github.com/corbanbrook/dsp.js)."
+ },
+ "audio-fft": {
+ "description": "This benchmark performs a [Fast Fourier Transform](http://en.wikipedia.org/wiki/Fast_Fourier_transform) on an Audio sample using code from [DSP.js](http://github.com/corbanbrook/dsp.js/)."
+ },
+ "audio-oscillator": {
+ "description": "This benchmark generates a soundwave using code from [DSP.js](http://github.com/corbanbrook/dsp.js/)."
+ },
+ "imaging-darkroom": {
+ "description": "This benchmark performs a variety of photo manipulations such as Fill, Brightness, Contrast, Saturation, and Temperature."
+ },
+ "imaging-desaturate": {
+ "description": "This benchmark [desaturates](http://en.wikipedia.org/wiki/Colorfulness) a photo using code from [Pixastic](http://www.pixastic.com/)."
+ },
+ "imaging-gaussian-blur": {
+ "description": "This benchmark performs a [Gaussian blur](http://en.wikipedia.org/wiki/Gaussian_blur) on a photo."
+ },
+ "json-parse-financial": {
+ "description": "This benchmark parses [JSON](http://www.json.org) records."
+ },
+ "json-stringify-tinderbox": {
+ "description": "This benchmark serializes [Tinderbox](http://tests.themasta.com/tinderboxpushlog/?tree=Firefox) build data to [JSON](http://www.json.org)."
+ },
+
+ "CodeLoad": {
+ "description": "measures how quickly a JavaScript engine can start executing code after loading a large JavaScript program, social widget being a common example. The source for test is derived from open source libraries (Closure, jQuery) (1,530 lines)."
+ },
+ "Crypto": {
+ "description": "Encryption and decryption benchmark based on code by Tom Wu (1698 lines)."
+ },
+ "DeltaBlue": {
+ "description": "One-way constraint solver, originally written in Smalltalk by John Maloney and Mario Wolczko (880 lines)."
+ },
+ "EarleyBoyer": {
+ "description": "Classic Scheme benchmarks, translated to JavaScript by Florian Loitsch's Scheme2Js compiler (4684 lines)."
+ },
+ "Gameboy": {
+ "description": "Emulate the portable console's architecture and runs a demanding 3D simulation, all in JavaScript (11,097 lines)."
+ },
+ "Mandreel": {
+ "description": "Runs the 3D Bullet Physics Engine ported from C++ to JavaScript via Mandreel (277,377 lines)."
+ },
+ "NavierStokes": {
+ "description": "2D NavierStokes equations solver, heavily manipulates double precision arrays. Based on Oliver Hunt's code (387 lines)."
+ },
+ "PdfJS": {
+ "description": "Mozilla's PDF Reader implemented in JavaScript. It measures decoding and interpretation time (33,056 lines)."
+ },
+ "RayTrace": {
+ "description": "Ray tracer benchmark based on code by Adam Burmister (904 lines)."
+ },
+ "RegExp": {
+ "description": "Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages (1761 lines)."
+ },
+ "Richards": {
+ "description": "OS kernel simulation benchmark, originally written in BCPL by Martin Richards (539 lines)."
+ },
+ "Splay": {
+ "description": "Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (394 lines).."
+ },
+
+ "commit_charge": {
+ "description": "System commit charge (commited memory pages)"
+ },
+ "page_load_time": {
+ "description": "Average page load time. Measured from navigationStart until the completion time of a layout after the window.load event."
+ },
+ "processes": {
+ "description": "Number of processes used by chrome"
+ },
+ "read_bytes_browser": {
+ "description": "Number of IO bytes read by the browser process"
+ },
+ "read_bytes_renderer": {
+ "description": "Number of IO bytes read by the renderer process"
+ },
+ "read_operations_browser": {
+ "description": "Number of IO read operations by the browser process"
+ },
+ "read_operations_renderer": {
+ "description": "Number of IO read operations by the renderer process"
+ },
+ "resident_set_size_peak_size_browser": {
+ "description": "The peak Resident Set Size (physically resident memory) usage achieved by the browser process."
+ },
+ "resident_set_size_peak_size_renderer": {
+ "description": "The peak Resident Set Size (physically resident memory) usage achieved by the renderer process."
+ },
+ "V8.MemoryExternalFragmentationTotal": {
+ "description": "Total external memory fragmentation after each GC in percent."
+ },
+ "V8.MemoryHeapSampleTotalCommitted": {
+ "description": "The total size of committed memory used by V8 after each GC in KB."
+ },
+ "V8.MemoryHeapSampleTotalUsed": {
+ "description": "The total size of live memory used by V8 after each GC in KB."
+ },
+ "vm_final_size_browser": {
+ "description": "Virtual Memory Size (address space allocated) of browser process"
+ },
+ "vm_final_size_gpu": {
+ "description": "Virtual Memory Size (address space allocated) of renderer process"
+ },
+ "vm_final_size_renderer": {
+ "description": "Virtual Memory Size (address space allocated) of renderer process"
+ },
+ "vm_final_size_total": {
+ "description": "Virtual Memory Size (address space allocated) of GPU process"
+ },
+ "vm_peak_size_browser": {
+ "description": "The peak Virtual Memory Size (address space allocated) usage achieved by the browser process."
+ },
+ "vm_peak_size_renderer": {
+ "description": "The peak Virtual Memory Size (address space allocated) usage achieved by the renderer process."
+ },
+ "vm_private_dirty_final_browser": {
+ "description": "Private Dirty is basically the amount of RAM inside the process that can not be paged to disk (it is not backed by the same data on disk), and is not shared with any other processes. Another way to look at this is the RAM that will become available to the system when that process goes away (and probably quickly subsumed into caches and other uses of it)."
+ },
+ "vm_private_dirty_final_renderer": {
+ "description": "Private Dirty is basically the amount of RAM inside the process that can not be paged to disk (it is not backed by the same data on disk), and is not shared with any other processes. Another way to look at this is the RAM that will become available to the system when that process goes away (and probably quickly subsumed into caches and other uses of it)."
+ },
+ "vm_private_dirty_final_total": {
+ "description": "Private Dirty is basically the amount of RAM inside the process that can not be paged to disk (it is not backed by the same data on disk), and is not shared with any other processes. Another way to look at this is the RAM that will become available to the system when that process goes away (and probably quickly subsumed into caches and other uses of it)."
+ },
+ "vm_proportional_set_size_final_browser": {
+ "description": "The PSS number is a metric the kernel computes that takes into account memory sharing -- basically each page of RAM in a process is scaled by a ratio of the number of other processes also using that page. This way you can (in theory) add up the pss across all processes to see the total RAM they are using, and compare pss between processes to get a rough idea of their relative weight."
+ },
+ "vm_proportional_set_size_final_renderer": {
+ "description": "The PSS number is a metric the kernel computes that takes into account memory sharing -- basically each page of RAM in a process is scaled by a ratio of the number of other processes also using that page. This way you can (in theory) add up the pss across all processes to see the total RAM they are using, and compare pss between processes to get a rough idea of their relative weight."
+ },
+ "vm_proportional_set_size_final_total": {
+ "description": "The PSS number is a metric the kernel computes that takes into account memory sharing -- basically each page of RAM in a process is scaled by a ratio of the number of other processes also using that page. This way you can (in theory) add up the pss across all processes to see the total RAM they are using, and compare pss between processes to get a rough idea of their relative weight."
+ },
+ "vm_resident_set_size_final_size_browser": {
+ "description": "Resident Set Size (physically resident memory) of browser process"
+ },
+ "vm_resident_set_size_final_size_gpu": {
+ "description": "Resident Set Size (physically resident memory) of GPU process"
+ },
+ "vm_resident_set_size_final_size_renderer": {
+ "description": "Resident Set Size (physically resident memory) of renderer process"
+ },
+ "vm_resident_set_size_final_size_total": {
+ "description": "Resident Set Size (physically resident memory) of all processes"
+ },
+ "vm_working_set_final_size_browser": {
+ "description": "Working Set size of browser process"
+ },
+ "vm_working_set_final_size_renderer": {
+ "description": "Working Set size of renderer process"
+ },
+ "vm_working_set_final_size_total": {
+ "description": "Working Set size of all processes"
+ },
+ "working_set_peak_size_browser": {
+ "description": "The peak Working Set Size usage achieved by the browser process."
+ },
+ "working_set_peak_size_renderer": {
+ "description": "The peak Working Set Size usage achieved by the renderer process."
+ },
+ "write_bytes_browser": {
+ "description": "Number of IO bytes written by the browser process"
+ },
+ "write_bytes_renderer": {
+ "description": "Number of IO bytes written by the renderer process"
+ },
+ "write_operations_browser": {
+ "description": "Number of write IO operations by browser process"
+ },
+ "write_operations_renderer": {
+ "description": "Number of write IO operations by renderer process"
+ },
+
+ "average_commit_time": {
+ "description": "Time spent pushing the layer tree from the main thread to the compositor thread. Is zero if software rendering."
+ },
+ "average_latency": {
+ "description": "The average latency between input event and corresponding swap to screen."
+ },
+ "average_num_layers_drawn": {
+ "description": "Number of layers in the tree at draw time. Is zero in software mode."
+ },
+ "avg_surface_fps": {
+ "description": "Average frames per second as measured by the platform's SurfaceFlinger."
+ },
+ "dropped_percent": {
+ "description": "Number of frames that missed vsync. The metric is slightly different in each rendering mode but roughly approximates how janky the page was."
+ },
+ "mean_frame_time": {
+ "description": "The frame rate, but reported as an interval."
+ },
+ "percent_impl_scrolled": {
+ "description": "The percent of input events that caused fast scrolling on the impl thread. If you see numbers between 0 and 100, it's probably because the page changed halfway through and became slow scrolling, or vice versa."
+ },
+ "texture_upload_count": {
+ "description": "The number of textures uploaded to the GPU."
+ },
+ "total_texture_upload_time": {
+ "description": "The time spent in texture upload on the GPU process."
+ },
+
+ "canvasDrawImageFullClear": {
+ "description": "Using a canvas element to render. Bitmaps are blitted to the canvas using the 'drawImage' function and the canvas is fully cleared at the beginning of each frame."
+ },
+ "canvasDrawImageFullClearAlign": {
+ "description": "Same as canvasDrawImageFullClear except all 'x' and 'y' values are roudned to the nearest integer. This can be more efficient on translate on certain browsers."
+ },
+ "canvasDrawImagePartialClear": {
+ "description": "Using a canvas element to render. Bitmaps are blitted to the canvas using the 'drawImage' function and pixels drawn in the last frame are cleared to the clear color at the beginning of each frame. This is generally slower on hardware accelerated implementations, but sometimes faster on CPU-based implementations."
+ },
+ "canvasDrawImagePartialClearAlign": {
+ "description": "Same as canvasDrawImageFullClearAlign but only partially clearing the canvas each frame."
+ },
+ "css2dBackground": {
+ "description": "Using div elements that have a background image specified using CSS styles. These div elements are translated, scaled, and rotated using CSS-2D transforms."
+ },
+ "css2dImg": {
+ "description": "Same as css2dBackground, but using img elements instead of div elements."
+ },
+ "css3dBackground": {
+ "description": "Same as css2dBackground, but using CSS-3D transforms."
+ },
+ "css3dImg": {
+ "description": "Same as css2dImage but using CSS-3D tranforms."
+ },
+
+ "3d-cube": {
+ "description": "Pure JavaScript computations of the kind you might use to do 3d rendering, but without the rendering. This ends up mostly hitting floating point math and array access."
+ },
+ "3d-morph": {
+ "description": "Pure JavaScript computations of the kind you might use to do 3d rendering, but without the rendering. This ends up mostly hitting floating point math and array access."
+ },
+ "3d-raytrace": {
+ "description": "Pure JavaScript computations of the kind you might use to do 3d rendering, but without the rendering. This ends up mostly hitting floating point math and array access."
+ },
+ "access-binary-trees": {
+ "description": "Array, object property and variable access."
+ },
+ "access-fannkuch": {
+ "description": "Array, object property and variable access."
+ },
+ "access-nbody": {
+ "description": "Array, object property and variable access."
+ },
+ "access-nsieve": {
+ "description": "Array, object property and variable access."
+ },
+ "bitops-3bit-bits-in-byte": {
+ "description": "Bitwise operations, these can be useful for various things including games, mathematical computations, and various kinds of encoding/decoding. It's also the only kind of math in JavaScript that is done as integer, not floating point."
+ },
+ "bitops-bits-in-byte": {
+ "description": "Bitwise operations, these can be useful for various things including games, mathematical computations, and various kinds of encoding/decoding. It's also the only kind of math in JavaScript that is done as integer, not floating point."
+ },
+ "bitops-bitwise-and": {
+ "description": "Bitwise operations, these can be useful for various things including games, mathematical computations, and various kinds of encoding/decoding. It's also the only kind of math in JavaScript that is done as integer, not floating point."
+ },
+ "bitops-nsieve-bits": {
+ "description": "Bitwise operations, these can be useful for various things including games, mathematical computations, and various kinds of encoding/decoding. It's also the only kind of math in JavaScript that is done as integer, not floating point."
+ },
+ "controlflow-recursive": {
+ "description": "Control flow constructs (looping, recursion, conditionals). Right now it mostly covers recursion, as the others are pretty well covered by other tests."
+ },
+ "crypto-aes": {
+ "description": "Real cryptography code, mostly covers bitwise operations and string operations."
+ },
+ "crypto-md5": {
+ "description": "Real cryptography code, mostly covers bitwise operations and string operations."
+ },
+ "crypto-sha1": {
+ "description": "Real cryptography code, mostly covers bitwise operations and string operations."
+ },
+ "date-format-tofte": {
+ "description": "Performance of JavaScript's 'date' objects."
+ },
+ "date-format-xparb": {
+ "description": "Performance of JavaScript's 'date' objects."
+ },
+ "math-cordic": {
+ "description": "Various mathematical type computations."
+ },
+ "math-partial-sums": {
+ "description": "Various mathematical type computations."
+ },
+ "math-spectral-norm": {
+ "description": "Various mathematical type computations."
+ },
+ "regexp-dna": {
+ "description": "Regular expressions performance"
+ },
+ "string-base64": {
+ "description": "String processing, including code to generate a giant 'tagcloud', extracting compressed JS code, etc."
+ },
+ "string-fasta": {
+ "description": "String processing, including code to generate a giant 'tagcloud', extracting compressed JS code, etc."
+ },
+ "string-tagcloud": {
+ "description": "String processing, including code to generate a giant 'tagcloud', extracting compressed JS code, etc."
+ },
+ "string-unpack-code": {
+ "description": "String processing, including code to generate a giant 'tagcloud', extracting compressed JS code, etc."
+ },
+ "string-validate-input": {
+ "description": "String processing, including code to generate a giant 'tagcloud', extracting compressed JS code, etc."
+ }
+}
diff --git a/chromium/tools/perf/unit-info.json b/chromium/tools/perf/unit-info.json
new file mode 100644
index 00000000000..560d63749dd
--- /dev/null
+++ b/chromium/tools/perf/unit-info.json
@@ -0,0 +1,94 @@
+{
+ "_description" : "This file contains info about our performance test units, used by the perf dashboard (http://chromeperf.appspot.com).",
+
+ "%": {
+ "improvement_direction": "down",
+ "why": "Percent CPU usage"
+ },
+ "bytes": {
+ "improvement_direction": "down"
+ },
+ "count": {
+ "improvement_direction": "down",
+ "why": "Processes"
+ },
+ "files": {
+ "improvement_direction": "down",
+ "why": "Static initializers"
+ },
+ "fps": {
+ "improvement_direction": "up"
+ },
+ "frames": {
+ "improvement_direction": "down",
+ "why": "Dropped frames"
+ },
+ "frames-per-second": {
+ "improvement_direction": "up"
+ },
+ "frame_time": {
+ "improvement_direction": "down"
+ },
+ "kb": {
+ "improvement_direction": "down"
+ },
+ "KB": {
+ "improvement_direction": "down"
+ },
+ "lines": {
+ "improvement_direction": "up",
+ "why": "Coverage"
+ },
+ "load": {
+ "improvement_direction": "down"
+ },
+ "MB": {
+ "improvement_direction": "down"
+ },
+ "ms": {
+ "improvement_direction": "down"
+ },
+ "milliseconds": {
+ "improvement_direction": "down"
+ },
+ "milliseconds-per-frame": {
+ "improvement_direction": "down"
+ },
+ "objects (bigger is better)": {
+ "improvement_direction": "up"
+ },
+ "ObjectsAt30FPS": {
+ "improvement_direction": "up"
+ },
+ "percent": {
+ "improvement_direction": "down"
+ },
+ "ports": {
+ "improvement_direction": "down"
+ },
+ "relocs": {
+ "improvement_direction": "down"
+ },
+ "runs/s": {
+ "improvement_direction": "up"
+ },
+ "runs_per_second": {
+ "improvement_direction": "up"
+ },
+ "score": {
+ "improvement_direction": "up"
+ },
+ "score_(bigger_is_better)": {
+ "improvement_direction": "up"
+ },
+ "score (bigger is better)": {
+ "improvement_direction": "up"
+ },
+ "sec": {
+ "improvement_direction": "down"
+ },
+ "seconds": {
+ "improvement_direction": "down"
+ }
+}
+
diff --git a/chromium/tools/perf/utils/results_viewer/src/base.js b/chromium/tools/perf/utils/results_viewer/src/base.js
new file mode 100644
index 00000000000..df65c760d1d
--- /dev/null
+++ b/chromium/tools/perf/utils/results_viewer/src/base.js
@@ -0,0 +1,84 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+
+/**
+ * The global object.
+ * @type {!Object}
+ * @const
+ */
+var global = this;
+
+
+/** Platform, package, object property, and Event support. */
+this.base = (function() {
+
+ function mLog(text, opt_indentLevel) {
+ if (true)
+ return;
+
+ var spacing = '';
+ var indentLevel = opt_indentLevel || 0;
+ for (var i = 0; i < indentLevel; i++)
+ spacing += ' ';
+ console.log(spacing + text);
+ }
+
+ /**
+ * Builds an object structure for the provided namespace path,
+ * ensuring that names that already exist are not overwritten. For
+ * example:
+ * 'a.b.c' -> a = {};a.b={};a.b.c={};
+ * @param {string} name Name of the object that this file defines.
+ * @param {*=} opt_object The object to expose at the end of the path.
+ * @param {Object=} opt_objectToExportTo The object to add the path to;
+ * default is {@code global}.
+ * @private
+ */
+ function exportPath(name, opt_object, opt_objectToExportTo) {
+ var parts = name.split('.');
+ var cur = opt_objectToExportTo || global;
+
+ for (var part; parts.length && (part = parts.shift());) {
+ if (!parts.length && opt_object !== undefined) {
+ // last part and we have an object; use it
+ cur[part] = opt_object;
+ } else if (part in cur) {
+ cur = cur[part];
+ } else {
+ cur = cur[part] = {};
+ }
+ }
+ return cur;
+ }
+
+ function exportTo(namespace, fn) {
+ var obj = exportPath(namespace);
+ try {
+ var exports = fn();
+ } catch (e) {
+ console.log('While running exports for ', name, ':');
+ console.log(e.stack || e);
+ return;
+ }
+
+ for (var propertyName in exports) {
+ // Maybe we should check the prototype chain here? The current usage
+ // pattern is always using an object literal so we only care about own
+ // properties.
+ var propertyDescriptor = Object.getOwnPropertyDescriptor(exports,
+ propertyName);
+ if (propertyDescriptor) {
+ Object.defineProperty(obj, propertyName, propertyDescriptor);
+ mLog(' +' + propertyName);
+ }
+ }
+ }
+
+ return {
+ exportTo: exportTo
+ };
+})(); \ No newline at end of file
diff --git a/chromium/tools/perf/utils/results_viewer/src/main.css b/chromium/tools/perf/utils/results_viewer/src/main.css
new file mode 100644
index 00000000000..8bb8729d043
--- /dev/null
+++ b/chromium/tools/perf/utils/results_viewer/src/main.css
@@ -0,0 +1,13 @@
+/**
+ * Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+.yui-dt, .viewer {
+ /*Viewer extends yui-dt class*/
+}
+
+.viewer {
+ /*Implementation goes here*/
+}
diff --git a/chromium/tools/perf/utils/results_viewer/src/main.js b/chromium/tools/perf/utils/results_viewer/src/main.js
new file mode 100644
index 00000000000..a889387d2e5
--- /dev/null
+++ b/chromium/tools/perf/utils/results_viewer/src/main.js
@@ -0,0 +1,293 @@
+/**
+ * Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+'use strict';
+
+(function() {
+ /**
+ * Main results viewer component.
+ */
+ var Viewer = ui.define('div');
+ (function() {
+ //"Private" functions for Viewer
+ /**
+ * Determines the appropriate parser for a given column, using it's first
+ * data element.
+ * @param {String} firstElement The first (non-header) element of a given
+ * column.
+ * @return {String} The YUI parser needed for the column.
+ */
+ function getColumnParser(firstElement) {
+ if (isNumeric(firstElement)) {
+ return 'number';
+ } else if (isDate(firstElement)) {
+ return 'date';
+ } else {
+ return 'string';
+ }
+ }
+
+ /**
+ * Determines whether or not the given element is a date.
+ * @param {String} str The string representation of a potential date.
+ * @return {boolean} true/false whether or not str can be parsed to
+ * a date.
+ */
+ function isDate(str) {
+ var timestamp = Date.parse(str);
+ return !isNaN(timestamp);
+ }
+
+ /**
+ * Generates the YUI column definition for the given dataset.
+ * @param {String[][]} dataSet the dataset that will be displayed.
+ * @return {JSON[]} The array containing the column definitions.
+ */
+ function createYUIColumnDefinitions(dataSet) {
+ var header = dataSet[0];
+ var firstRow = dataSet[1];
+ var columnDefinitions = [];
+ header.forEach(function (element, index, array) {
+ columnDefinitions.push({
+ 'key' : index.toString(),
+ 'label':element.toString(),
+ 'maxAutoWidth':95,
+ 'sortable':true,
+ 'parser':getColumnParser(firstRow[index])});
+ });
+ return columnDefinitions;
+ }
+
+ /**
+ * Generates the YUI data source for the given dataset.
+ * @param {String[][]} dataSet the dataset that will be displayed.
+ * @return {YAHOO.util.FunctionDataSource} The YUI data source
+ * derived from the dataset.
+ */
+ function createYUIDataSource(dataSet) {
+ var dataSource = [];
+ //Starts from the first non-header line.
+ for (var i = 1; i < dataSet.length; i++) {
+ var dataSourceLine = {};
+ dataSet[i].forEach(function (element, index, array) {
+ if (isNumeric(element)) {
+ dataSourceLine[index.toString()] = parseFloat(element);
+ } else {
+ dataSourceLine[index.toString()] = element
+ }
+ });
+ dataSource.push(dataSourceLine);
+ }
+ return new YAHOO.util.FunctionDataSource(function() {
+ return dataSource});
+ }
+
+ /**
+ * Un-selects all the columns from the given data table.
+ * @param {YAHOO.widget.DataTable} dataTable The data table that
+ * contains the results.
+ */
+ function unselectAllColumns(dataTable) {
+ var selectedColumns = dataTable.getSelectedColumns();
+ for (var i = 0; i < selectedColumns.length; i++) {
+ dataTable.unselectColumn(selectedColumns[i]);
+ }
+ }
+
+ /**
+ * Generates an array that contains the indices of the selected
+ * columns in the data table.
+ * @param {YAHOO.widget.DataTable} dataTable
+ * @return {int[]} An array with the indices of the selected columns.
+ */
+ function getSelectedColumnIndices(dataTable) {
+ var selectedColumnIndices = [];
+ var selectedColumns = dataTable.getSelectedColumns();
+ for (var i = 0; i < selectedColumns.length; i++) {
+ selectedColumnIndices.push(selectedColumns[i].key);
+ }
+ return selectedColumnIndices;
+ }
+
+ Viewer.prototype = {
+ __proto__: HTMLDivElement.prototype,
+ decorate:function() {
+ /**
+ * The id for the element that contains the barchart (Optional).
+ * @type {String}
+ */
+ this.barChartElementId_ = undefined;
+ /**
+ * The rectangular array that contains the contents of the cvs file.
+ * @type {String[][]}
+ */
+ this.dataSet_ = undefined;
+ },
+ set barChartElementId(e) {
+ this.barChartElementId_ = e;
+ },
+ get barChartElementId() {
+ return this.barChartElementId_;
+ },
+ set dataSet(ds) {
+ this.dataSet_ = ds;
+ },
+ get dataSet() {
+ return this.dataSet_;
+ },
+ /**
+ * Renders the Viewer component.
+ * @expose
+ */
+ render: function() {
+ document.body.appendChild(this);
+ var previousBarChart = this.barChartElementId_ != null ?
+ $(this.barChartElementId_) : null;
+ if (previousBarChart != null) {
+ document.body.removeChild(previousBarChart);
+ window.location.hash = this.id;
+ }
+
+ var columnDefinitions = createYUIColumnDefinitions(this.dataSet_);
+ var dataSource = createYUIDataSource(this.dataSet_);
+ var dataTable = new YAHOO.widget.DataTable(this.id, columnDefinitions,
+ dataSource, {caption:'Results'});
+ var firstRow = this.dataSet_[1];
+ var currentViewer = this;
+
+ dataTable.subscribe('cellClickEvent', function (oArgs) {
+ var selectedColumn = dataTable.getColumn(oArgs.target);
+ var selectedColumnIndex = parseInt(selectedColumn.key);
+
+ if (selectedColumnIndex == 0) {
+ unselectAllColumns(dataTable);
+ return;
+ }
+
+ if (isNumeric(firstRow[selectedColumnIndex])) {
+ dataTable.selectColumn(selectedColumn);
+ if (currentViewer.barChartElementId_ != null) {
+ var viewerBarChart_ =
+ new ViewerBarChart({ownerDocument:window.document});
+ viewerBarChart_.id = currentViewer.barChartElementId_;
+ viewerBarChart_.dataSet = currentViewer.dataSet_;
+ viewerBarChart_.selectedColumnIndices
+ = getSelectedColumnIndices(dataTable);
+ viewerBarChart_.render();
+ }
+ }
+ });
+ }
+ };
+ }());
+
+ /**
+ * BarChart component for the results viewer.
+ */
+ var ViewerBarChart = ui.define('div');
+ (function () {
+ //"Private" functions for ViewerBarChart
+ /**
+ * Generates a new array that contains only the first column, and all
+ * other selected columns.
+ * @param {(string|number)[][]} dataset Array with the csv contents.
+ * @param {int[]} selectedColumnIndices Indices for all the selected
+ * columns.
+ * @return {String[][]} A new array containing the first column
+ * and all selected columns.
+ */
+ function extractColumnsToPlot(dataset, selectedColumnIndices) {
+ var lines = [];
+ var line = [];
+ for (var i = 0; i < dataset.length; ++i) {
+ line.push(dataset[i][0]);
+ for (var j = 0; j < selectedColumnIndices.length; j++) {
+ var elementValue = dataset[i][selectedColumnIndices[j]];
+ line.push(isNumeric(elementValue) ? parseFloat(elementValue) :
+ elementValue);
+ }
+ lines.push(line);
+ line = [];
+ }
+ return lines;
+ }
+
+ ViewerBarChart.prototype = {
+ __proto__:HTMLDivElement.prototype,
+ decorate: function() {
+ /**
+ * Percetage of the window width that will be used for the chart
+ * @const
+ * @type {float}
+ */
+ ViewerBarChart.PERCENTAGE_OF_WINDOW_WIDTH_FOR_CHART = 0.75;
+ /**
+ * Approximate number of pixels that will be used per line
+ * @const
+ * @type {int}
+ */
+ ViewerBarChart.HEIGHT_PER_LINE_IN_PIXELS = 28;
+
+ /**
+ * Raw dataset, which contains the csv file contents.
+ * @type {(String|number)[][]}
+ */
+ this.dataSet_ = undefined;
+ /**
+ * Array that contains the selected indices from the table view.
+ * @type {number[]}
+ */
+ this.selectedColumnIndices_ = undefined;
+ },
+ /**
+ * Renders the ViewerBarChart component.
+ * @expose
+ */
+ render : function() {
+ var existingBarChart = $(this.id);
+ if (existingBarChart != null) {
+ //Remove the previous bar chart
+ document.body.removeChild(existingBarChart);
+ }
+ //Attach this component to the document
+ document.body.appendChild(this);
+ var lines = extractColumnsToPlot(this.dataSet_,
+ this.selectedColumnIndices_);
+ var data = google.visualization.arrayToDataTable(lines);
+
+ var barCharWidth = window.width *
+ ViewerBarChart.PERCENTAGE_OF_WINDOW_WIDTH_FOR_CHART;
+ var barCharHeight = this.dataSet_.length *
+ ViewerBarChart.HEIGHT_PER_LINE_IN_PIXELS;
+ var options = {
+ 'width': barCharWidth,
+ 'height':barCharHeight,
+ 'fontSize':15
+ };
+ new google.visualization.BarChart(this).draw(data, options);
+ window.location.hash = this.id;
+ },
+ set dataSet(ds) {
+ this.dataSet_ = ds;
+ },
+ set selectedColumnIndices(sci) {
+ this.selectedColumnIndices_ = sci;
+ }
+ };
+ }());
+
+ /**
+ * Determines whether or not a string can be parsed to a number.
+ * @param {String} element String representation of the potential number.
+ * @return {boolean} True or false depending on whether the element is
+ * numeric or not.
+ */
+ function isNumeric(element) {
+ return !isNaN(parseFloat(element)) && isFinite(element);
+ }
+
+ window.Viewer = Viewer;
+ window.ViewerBarChart = ViewerBarChart;
+})(); \ No newline at end of file
diff --git a/chromium/tools/perf/utils/results_viewer/src/results_viewer.html b/chromium/tools/perf/utils/results_viewer/src/results_viewer.html
new file mode 100644
index 00000000000..64554ba67f2
--- /dev/null
+++ b/chromium/tools/perf/utils/results_viewer/src/results_viewer.html
@@ -0,0 +1,39 @@
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection">
+ <head>
+ <meta charset="utf-8">
+ <title>
+ Results viewer
+ </title>
+ <link type="text/css" rel="stylesheet" href="http://yui.yahooapis.com/2.9.0/build/datatable/assets/skins/sam/datatable.css">
+ <link type="text/css" rel="stylesheet" href="main.css">
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js"></script>
+ <script src="http://yui.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
+ <script src="http://yui.yahooapis.com/2.9.0/build/element/element-min.js"></script>
+ <script src="http://yui.yahooapis.com/2.9.0/build/datasource/datasource-min.js"></script>
+ <script src="http://yui.yahooapis.com/2.9.0/build/datatable/datatable-min.js"></script>
+ <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+ <script type="text/javascript">
+ google.load("visualization", "1", {packages:["corechart"]});
+ </script>
+ <script type="text/javascript" src="base.js"></script>
+ <script type="text/javascript" src="ui.js"></script>
+ <script type="text/javascript" src="results_viewer.js"></script>
+ <script type="text/javascript" src="main.js"></script>
+ </head>
+ <body class="yui-skin-sam">
+ <form action="">
+ <input type="file" id="fileSelector" name="files[]" />
+ </form>
+ <!--<div id="csvContentsDataTable" class="viewer"></div> TODO remove me!-->
+ <!--<div id="barChart"></div> TODO remove me-->
+ </body>
+</html>
+<script type="text/javascript">
+ $('fileSelector').addEventListener('change', handleFileSelectEvent, false);
+</script> \ No newline at end of file
diff --git a/chromium/tools/perf/utils/results_viewer/src/results_viewer.js b/chromium/tools/perf/utils/results_viewer/src/results_viewer.js
new file mode 100644
index 00000000000..06783c4dce2
--- /dev/null
+++ b/chromium/tools/perf/utils/results_viewer/src/results_viewer.js
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+'use strict';
+
+/**
+ * Main entry point for the rendering of the Viewer component.
+ * @param {Event} evt File select event.
+ */
+function handleFileSelectEvent(evt) {
+ var file = evt.target.files[0];
+ var fileReader = new FileReader();
+
+ fileReader.onload = (function(theFile) {
+ return function(e) {
+ var dataSet = createViewerDataset(e.target.result);
+ var viewer = new Viewer({ownerDocument:window.document});
+ viewer.id = 'csvContentsDataTable';
+ viewer.dataSet = dataSet;
+ viewer.barChartElementId = 'barChart';
+ viewer.render();
+ };
+ })(file);
+ fileReader.readAsText(file);
+}
+
+/**
+ * Splits the csv file contents, and creates a square array of strings for
+ * each token in the line.
+ * @param fileContents
+ * @return {String[][]} The data set with the contents of the csv file.
+ */
+function createViewerDataset(fileContents) {
+ var rows = fileContents.split('\n');
+ var dataset = [];
+ rows.forEach(function (row, index, array) {
+ if (row.trim().length == 0) {
+ //Ignore empty lines
+ return;
+ }
+ var newRow = [];
+ var columns = row.split(',');
+ columns.forEach(function (element, index, array) {
+ newRow.push(element);
+ });
+ dataset.push(newRow);
+ });
+ return dataset;
+} \ No newline at end of file
diff --git a/chromium/tools/perf/utils/results_viewer/src/ui.js b/chromium/tools/perf/utils/results_viewer/src/ui.js
new file mode 100644
index 00000000000..576e87b822a
--- /dev/null
+++ b/chromium/tools/perf/utils/results_viewer/src/ui.js
@@ -0,0 +1,83 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+base.exportTo('ui', function() {
+
+ /**
+ * Helper function for creating new element for define.
+ */
+ function createElementHelper(tagName, opt_bag) {
+ // Allow passing in ownerDocument to create in a different document.
+ var doc;
+ if (opt_bag && opt_bag.ownerDocument)
+ doc = opt_bag.ownerDocument;
+
+ return doc.createElement(tagName);
+ }
+
+ /**
+ * Creates the constructor for a UI element class.
+ *
+ * Usage:
+ * <pre>
+ * var List = base.ui.define('list');
+ * List.prototype = {
+ * __proto__: HTMLUListElement.prototype,
+ * decorate: function() {
+ * ...
+ * },
+ * ...
+ * };
+ * </pre>
+ *
+ * @param {string|Function} tagNameOrFunction The tagName or
+ * function to use for newly created elements. If this is a function it
+ * needs to return a new element when called.
+ * @return {function(Object=):Element} The constructor function which takes
+ * an optional property bag. The function also has a static
+ * {@code decorate} method added to it.
+ */
+ function define(tagNameOrFunction) {
+ var createFunction, tagName;
+ if (typeof tagNameOrFunction == 'function') {
+ createFunction = tagNameOrFunction;
+ tagName = '';
+ } else {
+ createFunction = createElementHelper;
+ tagName = tagNameOrFunction;
+ }
+
+ /**
+ * Creates a new UI element constructor.
+ * @param {Object=} opt_propertyBag Optional bag of properties to set on the
+ * object after created. The property {@code ownerDocument} is special
+ * cased and it allows you to create the element in a different
+ * document than the default.
+ * @constructor
+ */
+ function f(opt_propertyBag) {
+ var el = createFunction(tagName, opt_propertyBag);
+ f.decorate(el);
+ for (var propertyName in opt_propertyBag) {
+ el[propertyName] = opt_propertyBag[propertyName];
+ }
+ return el;
+ }
+
+ /**
+ * Decorates an element as a UI element class.
+ * @param {!Element} el The element to decorate.
+ */
+ f.decorate = function(el) {
+ el.__proto__ = f.prototype;
+ el.decorate();
+ };
+
+ return f;
+ }
+
+ return {
+ define: define
+ };
+});
diff --git a/chromium/tools/perf_expectations/PRESUBMIT.py b/chromium/tools/perf_expectations/PRESUBMIT.py
new file mode 100644
index 00000000000..b74e2e67629
--- /dev/null
+++ b/chromium/tools/perf_expectations/PRESUBMIT.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Presubmit script for perf_expectations.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+PERF_EXPECTATIONS = 'tools/perf_expectations/perf_expectations.json'
+CONFIG_FILE = 'tools/perf_expectations/chromium_perf_expectations.cfg'
+
+def CheckChangeOnUpload(input_api, output_api):
+ run_tests = False
+ for path in input_api.LocalPaths():
+ if (PERF_EXPECTATIONS == path or CONFIG_FILE == path):
+ run_tests = True
+
+ output = []
+ if run_tests:
+ whitelist = [r'.+_unittest\.py$']
+ output.extend(input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, 'tests', whitelist))
+ return output
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ run_tests = False
+ for path in input_api.LocalPaths():
+ if (PERF_EXPECTATIONS == path or CONFIG_FILE == path):
+ run_tests = True
+
+ output = []
+ if run_tests:
+ whitelist = [r'.+_unittest\.py$']
+ output.extend(input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api, 'tests', whitelist))
+
+ output.extend(input_api.canned_checks.CheckDoNotSubmit(input_api,
+ output_api))
+ return output
diff --git a/chromium/tools/perf_expectations/README.txt b/chromium/tools/perf_expectations/README.txt
new file mode 100644
index 00000000000..cc93ca81bb0
--- /dev/null
+++ b/chromium/tools/perf_expectations/README.txt
@@ -0,0 +1,2 @@
+For instructions see
+http://www.chromium.org/developers/tree-sheriffs/perf-sheriffs
diff --git a/chromium/tools/perf_expectations/chromium_perf_expectations.cfg b/chromium/tools/perf_expectations/chromium_perf_expectations.cfg
new file mode 100644
index 00000000000..4d3abe7ad38
--- /dev/null
+++ b/chromium/tools/perf_expectations/chromium_perf_expectations.cfg
@@ -0,0 +1,4 @@
+{
+ "base_url": "http://build.chromium.org/f/chromium/perf",
+ "perf_file": "perf_expectations.json"
+}
diff --git a/chromium/tools/perf_expectations/make_expectations.py b/chromium/tools/perf_expectations/make_expectations.py
new file mode 100755
index 00000000000..6b9efff58ea
--- /dev/null
+++ b/chromium/tools/perf_expectations/make_expectations.py
@@ -0,0 +1,375 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# For instructions see:
+# http://www.chromium.org/developers/tree-sheriffs/perf-sheriffs
+
+import hashlib
+import math
+import optparse
+import os
+import re
+import subprocess
+import sys
+import time
+import urllib2
+
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
+
+
+__version__ = '1.0'
+EXPECTATIONS_DIR = os.path.dirname(os.path.abspath(__file__))
+DEFAULT_CONFIG_FILE = os.path.join(EXPECTATIONS_DIR,
+ 'chromium_perf_expectations.cfg')
+DEFAULT_TOLERANCE = 0.05
+USAGE = ''
+
+
+def ReadFile(filename):
+ try:
+ file = open(filename, 'r')
+ except IOError, e:
+ print >> sys.stderr, ('I/O Error reading file %s(%s): %s' %
+ (filename, e.errno, e.strerror))
+ raise e
+ contents = file.read()
+ file.close()
+ return contents
+
+
+def ConvertJsonIntoDict(string):
+ """Read a JSON string and convert its contents into a Python datatype."""
+ if len(string) == 0:
+ print >> sys.stderr, ('Error could not parse empty string')
+ raise Exception('JSON data missing')
+
+ try:
+ jsondata = json.loads(string)
+ except ValueError, e:
+ print >> sys.stderr, ('Error parsing string: "%s"' % string)
+ raise e
+ return jsondata
+
+
+# Floating point representation of last time we fetched a URL.
+last_fetched_at = None
+def FetchUrlContents(url):
+ global last_fetched_at
+ if last_fetched_at and ((time.time() - last_fetched_at) <= 0.5):
+ # Sleep for half a second to avoid overloading the server.
+ time.sleep(0.5)
+ try:
+ last_fetched_at = time.time()
+ connection = urllib2.urlopen(url)
+ except urllib2.HTTPError, e:
+ if e.code == 404:
+ return None
+ raise e
+ text = connection.read().strip()
+ connection.close()
+ return text
+
+
+def GetRowData(data, key):
+ rowdata = []
+ # reva and revb always come first.
+ for subkey in ['reva', 'revb']:
+ if subkey in data[key]:
+ rowdata.append('"%s": %s' % (subkey, data[key][subkey]))
+ # Strings, like type, come next.
+ for subkey in ['type', 'better']:
+ if subkey in data[key]:
+ rowdata.append('"%s": "%s"' % (subkey, data[key][subkey]))
+ # Finally the main numbers come last.
+ for subkey in ['improve', 'regress', 'tolerance']:
+ if subkey in data[key]:
+ rowdata.append('"%s": %s' % (subkey, data[key][subkey]))
+ return rowdata
+
+
+def GetRowDigest(rowdata, key):
+ sha1 = hashlib.sha1()
+ rowdata = [str(possibly_unicode_string).encode('ascii')
+ for possibly_unicode_string in rowdata]
+ sha1.update(str(rowdata) + key)
+ return sha1.hexdigest()[0:8]
+
+
+def WriteJson(filename, data, keys, calculate_sha1=True):
+ """Write a list of |keys| in |data| to the file specified in |filename|."""
+ try:
+ file = open(filename, 'w')
+ except IOError, e:
+ print >> sys.stderr, ('I/O Error writing file %s(%s): %s' %
+ (filename, e.errno, e.strerror))
+ return False
+ jsondata = []
+ for key in keys:
+ rowdata = GetRowData(data, key)
+ if calculate_sha1:
+ # Include an updated checksum.
+ rowdata.append('"sha1": "%s"' % GetRowDigest(rowdata, key))
+ else:
+ if 'sha1' in data[key]:
+ rowdata.append('"sha1": "%s"' % (data[key]['sha1']))
+ jsondata.append('"%s": {%s}' % (key, ', '.join(rowdata)))
+ jsondata.append('"load": true')
+ jsontext = '{%s\n}' % ',\n '.join(jsondata)
+ file.write(jsontext + '\n')
+ file.close()
+ return True
+
+
+def FloatIsInt(f):
+ epsilon = 1.0e-10
+ return abs(f - int(f)) <= epsilon
+
+
+last_key_printed = None
+def Main(args):
+ def OutputMessage(message, verbose_message=True):
+ global last_key_printed
+ if not options.verbose and verbose_message:
+ return
+
+ if key != last_key_printed:
+ last_key_printed = key
+ print '\n' + key + ':'
+ print ' %s' % message
+
+ parser = optparse.OptionParser(usage=USAGE, version=__version__)
+ parser.add_option('-v', '--verbose', action='store_true', default=False,
+ help='enable verbose output')
+ parser.add_option('-s', '--checksum', action='store_true',
+ help='test if any changes are pending')
+ parser.add_option('-c', '--config', dest='config_file',
+ default=DEFAULT_CONFIG_FILE,
+ help='set the config file to FILE', metavar='FILE')
+ options, args = parser.parse_args(args)
+
+ if options.verbose:
+ print 'Verbose output enabled.'
+
+ config = ConvertJsonIntoDict(ReadFile(options.config_file))
+
+ # Get the list of summaries for a test.
+ base_url = config['base_url']
+ # Make the perf expectations file relative to the path of the config file.
+ perf_file = os.path.join(
+ os.path.dirname(options.config_file), config['perf_file'])
+ perf = ConvertJsonIntoDict(ReadFile(perf_file))
+
+ # Fetch graphs.dat for this combination.
+ perfkeys = perf.keys()
+ # In perf_expectations.json, ignore the 'load' key.
+ perfkeys.remove('load')
+ perfkeys.sort()
+
+ write_new_expectations = False
+ found_checksum_mismatch = False
+ for key in perfkeys:
+ value = perf[key]
+ tolerance = value.get('tolerance', DEFAULT_TOLERANCE)
+ better = value.get('better', None)
+
+ # Verify the checksum.
+ original_checksum = value.get('sha1', '')
+ if 'sha1' in value:
+ del value['sha1']
+ rowdata = GetRowData(perf, key)
+ computed_checksum = GetRowDigest(rowdata, key)
+ if original_checksum == computed_checksum:
+ OutputMessage('checksum matches, skipping')
+ continue
+ elif options.checksum:
+ found_checksum_mismatch = True
+ continue
+
+ # Skip expectations that are missing a reva or revb. We can't generate
+ # expectations for those.
+ if not(value.has_key('reva') and value.has_key('revb')):
+ OutputMessage('missing revision range, skipping')
+ continue
+ revb = int(value['revb'])
+ reva = int(value['reva'])
+
+ # Ensure that reva is less than revb.
+ if reva > revb:
+ temp = reva
+ reva = revb
+ revb = temp
+
+ # Get the system/test/graph/tracename and reftracename for the current key.
+ matchData = re.match(r'^([^/]+)\/([^/]+)\/([^/]+)\/([^/]+)$', key)
+ if not matchData:
+ OutputMessage('cannot parse key, skipping')
+ continue
+ system = matchData.group(1)
+ test = matchData.group(2)
+ graph = matchData.group(3)
+ tracename = matchData.group(4)
+ reftracename = tracename + '_ref'
+
+ # Create the summary_url and get the json data for that URL.
+ # FetchUrlContents() may sleep to avoid overloading the server with
+ # requests.
+ summary_url = '%s/%s/%s/%s-summary.dat' % (base_url, system, test, graph)
+ summaryjson = FetchUrlContents(summary_url)
+ if not summaryjson:
+ OutputMessage('ERROR: cannot find json data, please verify',
+ verbose_message=False)
+ return 0
+
+ # Set value's type to 'relative' by default.
+ value_type = value.get('type', 'relative')
+
+ summarylist = summaryjson.split('\n')
+ trace_values = {}
+ traces = [tracename]
+ if value_type == 'relative':
+ traces += [reftracename]
+ for trace in traces:
+ trace_values.setdefault(trace, {})
+
+ # Find the high and low values for each of the traces.
+ scanning = False
+ for line in summarylist:
+ jsondata = ConvertJsonIntoDict(line)
+ if int(jsondata['rev']) <= revb:
+ scanning = True
+ if int(jsondata['rev']) < reva:
+ break
+
+ # We found the upper revision in the range. Scan for trace data until we
+ # find the lower revision in the range.
+ if scanning:
+ for trace in traces:
+ if trace not in jsondata['traces']:
+ OutputMessage('trace %s missing' % trace)
+ continue
+ if type(jsondata['traces'][trace]) != type([]):
+ OutputMessage('trace %s format not recognized' % trace)
+ continue
+ try:
+ tracevalue = float(jsondata['traces'][trace][0])
+ except ValueError:
+ OutputMessage('trace %s value error: %s' % (
+ trace, str(jsondata['traces'][trace][0])))
+ continue
+
+ for bound in ['high', 'low']:
+ trace_values[trace].setdefault(bound, tracevalue)
+
+ trace_values[trace]['high'] = max(trace_values[trace]['high'],
+ tracevalue)
+ trace_values[trace]['low'] = min(trace_values[trace]['low'],
+ tracevalue)
+
+ if 'high' not in trace_values[tracename]:
+ OutputMessage('no suitable traces matched, skipping')
+ continue
+
+ if value_type == 'relative':
+ # Calculate assuming high deltas are regressions and low deltas are
+ # improvements.
+ regress = (float(trace_values[tracename]['high']) -
+ float(trace_values[reftracename]['low']))
+ improve = (float(trace_values[tracename]['low']) -
+ float(trace_values[reftracename]['high']))
+ elif value_type == 'absolute':
+ # Calculate assuming high absolutes are regressions and low absolutes are
+ # improvements.
+ regress = float(trace_values[tracename]['high'])
+ improve = float(trace_values[tracename]['low'])
+
+ # So far we've assumed better is lower (regress > improve). If the actual
+ # values for regress and improve are equal, though, and better was not
+ # specified, alert the user so we don't let them create a new file with
+ # ambiguous rules.
+ if better == None and regress == improve:
+ OutputMessage('regress (%s) is equal to improve (%s), and "better" is '
+ 'unspecified, please fix by setting "better": "lower" or '
+ '"better": "higher" in this perf trace\'s expectation' % (
+ regress, improve), verbose_message=False)
+ return 1
+
+ # If the existing values assume regressions are low deltas relative to
+ # improvements, swap our regress and improve. This value must be a
+ # scores-like result.
+ if 'regress' in perf[key] and 'improve' in perf[key]:
+ if perf[key]['regress'] < perf[key]['improve']:
+ assert(better != 'lower')
+ better = 'higher'
+ temp = regress
+ regress = improve
+ improve = temp
+ else:
+ # Sometimes values are equal, e.g., when they are both 0,
+ # 'better' may still be set to 'higher'.
+ assert(better != 'higher' or
+ perf[key]['regress'] == perf[key]['improve'])
+ better = 'lower'
+
+ # If both were ints keep as int, otherwise use the float version.
+ originally_ints = False
+ if FloatIsInt(regress) and FloatIsInt(improve):
+ originally_ints = True
+
+ if better == 'higher':
+ if originally_ints:
+ regress = int(math.floor(regress - abs(regress*tolerance)))
+ improve = int(math.ceil(improve + abs(improve*tolerance)))
+ else:
+ regress = regress - abs(regress*tolerance)
+ improve = improve + abs(improve*tolerance)
+ else:
+ if originally_ints:
+ improve = int(math.floor(improve - abs(improve*tolerance)))
+ regress = int(math.ceil(regress + abs(regress*tolerance)))
+ else:
+ improve = improve - abs(improve*tolerance)
+ regress = regress + abs(regress*tolerance)
+
+ # Calculate the new checksum to test if this is the only thing that may have
+ # changed.
+ checksum_rowdata = GetRowData(perf, key)
+ new_checksum = GetRowDigest(checksum_rowdata, key)
+
+ if ('regress' in perf[key] and 'improve' in perf[key] and
+ perf[key]['regress'] == regress and perf[key]['improve'] == improve and
+ original_checksum == new_checksum):
+ OutputMessage('no change')
+ continue
+
+ write_new_expectations = True
+ OutputMessage('traces: %s' % trace_values, verbose_message=False)
+ OutputMessage('before: %s' % perf[key], verbose_message=False)
+ perf[key]['regress'] = regress
+ perf[key]['improve'] = improve
+ OutputMessage('after: %s' % perf[key], verbose_message=False)
+
+ if options.checksum:
+ if found_checksum_mismatch:
+ return 1
+ else:
+ return 0
+
+ if write_new_expectations:
+ print '\nWriting expectations... ',
+ WriteJson(perf_file, perf, perfkeys)
+ print 'done'
+ else:
+ if options.verbose:
+ print ''
+ print 'No changes.'
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv))
diff --git a/chromium/tools/perf_expectations/perf_expectations.json b/chromium/tools/perf_expectations/perf_expectations.json
new file mode 100644
index 00000000000..e510bc6a7a8
--- /dev/null
+++ b/chromium/tools/perf_expectations/perf_expectations.json
@@ -0,0 +1,746 @@
+{"linux-release-64/sizes/chrome-bss/bss": {"reva": 216421, "revb": 216430, "type": "absolute", "better": "lower", "improve": 523892, "regress": 579040, "sha1": "0b0195e2"},
+ "linux-release-64/sizes/chrome-data/data": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 3570183, "regress": 3946094, "sha1": "b0d5e0fc"},
+ "linux-release-64/sizes/chrome-si/initializers": {"reva": 216959, "revb": 216961, "type": "absolute", "better": "lower", "improve": 33, "regress": 33, "tolerance": 0, "sha1": "ebd8c26b"},
+ "linux-release-64/sizes/chrome-text/text": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 94012670, "regress": 103908994, "sha1": "a8dc15a3"},
+ "linux-release-64/sizes/chrome.pak/chrome.pak": {"reva": 214295, "revb": 214296, "type": "absolute", "better": "lower", "improve": 4578193, "regress": 5060109, "sha1": "0785f1c1"},
+ "linux-release-64/sizes/chrome/chrome": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 128793270, "regress": 142351155, "sha1": "193926f5"},
+ "linux-release-64/sizes/nacl_helper-bss/bss": {"reva": 193069, "revb": 193093, "type": "absolute", "better": "lower", "improve": 200024, "regress": 221080, "sha1": "5dfae63b"},
+ "linux-release-64/sizes/nacl_helper-data/data": {"reva": 195191, "revb": 203172, "type": "absolute", "better": "lower", "improve": 22942, "regress": 26878, "sha1": "6d52a881"},
+ "linux-release-64/sizes/nacl_helper-si/initializers": {"reva": 187981, "revb": 188124, "type": "absolute", "better": "lower", "improve": 14, "regress": 16, "sha1": "747e9d1f"},
+ "linux-release-64/sizes/nacl_helper-text/text": {"reva": 202278, "revb": 202303, "type": "absolute", "better": "lower", "improve": 1801689, "regress": 1991341, "sha1": "73c0c6cd"},
+ "linux-release-64/sizes/nacl_helper/nacl_helper": {"reva": 202278, "revb": 202303, "type": "absolute", "better": "lower", "improve": 2186565, "regress": 2416731, "sha1": "a0ba8954"},
+ "linux-release-64/sizes/nacl_helper_bootstrap-bss/bss": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 3898, "regress": 4310, "sha1": "788b809e"},
+ "linux-release-64/sizes/nacl_helper_bootstrap-data/data": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 38, "regress": 42, "sha1": "02fba443"},
+ "linux-release-64/sizes/nacl_helper_bootstrap-si/initializers": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "228221af"},
+ "linux-release-64/sizes/nacl_helper_bootstrap-text/text": {"reva": 150377, "revb": 150377, "type": "absolute", "better": "lower", "improve": 5007, "regress": 5535, "sha1": "db1d84e2"},
+ "linux-release-64/sizes/nacl_helper_bootstrap/nacl_helper_bootstrap": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 9076, "regress": 10032, "sha1": "a2d25af5"},
+ "linux-release/media_tests_av_perf/audio_latency/latency": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 54, "regress": 60, "sha1": "8a2f61f4"},
+ "linux-release/media_tests_av_perf/audio_latency/latency_bg_clip": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 54, "regress": 60, "sha1": "d5f77086"},
+ "linux-release/media_tests_av_perf/audio_pesq/actual": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "higher", "improve": 5, "regress": 4, "sha1": "f4295968"},
+ "linux-release/media_tests_av_perf/audio_pesq/ref": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "higher", "improve": 5, "regress": 4, "sha1": "920a6aee"},
+ "linux-release/media_tests_av_perf/cpu/crowd1080.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 29, "regress": 36, "sha1": "daac54b7"},
+ "linux-release/media_tests_av_perf/cpu/crowd2160.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 44, "regress": 51, "sha1": "782968c9"},
+ "linux-release/media_tests_av_perf/cpu/crowd360.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 7, "regress": 10, "sha1": "4610ecbb"},
+ "linux-release/media_tests_av_perf/cpu/crowd480.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 11, "regress": 15, "sha1": "2387532a"},
+ "linux-release/media_tests_av_perf/cpu/crowd720.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 18, "regress": 24, "sha1": "056a9937"},
+ "linux-release/media_tests_av_perf/cpu/tulip2.m4a": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 0.315478992651, "regress": 0.392327813423, "sha1": "5bc9dd88"},
+ "linux-release/media_tests_av_perf/cpu/tulip2.mp3": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 0.393975797878, "regress": 0.522441418367, "sha1": "14899c83"},
+ "linux-release/media_tests_av_perf/cpu/tulip2.mp4": {"reva": 192736, "revb": 192827, "type": "absolute", "better": "lower", "improve": 12.1021431957, "regress": 15.6047995979, "sha1": "f328bb5f"},
+ "linux-release/media_tests_av_perf/cpu/tulip2.ogg": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 0.315551620367, "regress": 0.43580427209, "sha1": "4aa8af42"},
+ "linux-release/media_tests_av_perf/cpu/tulip2.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 6, "regress": 10, "sha1": "1abd5824"},
+ "linux-release/media_tests_av_perf/cpu/tulip2.wav": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 0.302926668634, "regress": 0.435028397036, "sha1": "5d55dcfa"},
+ "linux-release/media_tests_av_perf/cpu/tulip2.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 13, "regress": 18, "sha1": "7b022336"},
+ "linux-release/media_tests_av_perf/dropped_fps/crowd1080.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "fafd719d"},
+ "linux-release/media_tests_av_perf/dropped_fps/crowd2160.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 21.9960102178, "regress": 27.7360681235, "sha1": "389b837f"},
+ "linux-release/media_tests_av_perf/dropped_fps/crowd360.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "8672d24e"},
+ "linux-release/media_tests_av_perf/dropped_fps/crowd480.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "4854bd65"},
+ "linux-release/media_tests_av_perf/dropped_fps/crowd720.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "adfdba9f"},
+ "linux-release/media_tests_av_perf/dropped_fps/tulip2.m4a": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "4b463ecf"},
+ "linux-release/media_tests_av_perf/dropped_fps/tulip2.mp3": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "fe1f5eff"},
+ "linux-release/media_tests_av_perf/dropped_fps/tulip2.mp4": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "860ec8ca"},
+ "linux-release/media_tests_av_perf/dropped_fps/tulip2.ogg": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "b3ba176e"},
+ "linux-release/media_tests_av_perf/dropped_fps/tulip2.ogv": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "3573037e"},
+ "linux-release/media_tests_av_perf/dropped_fps/tulip2.wav": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "fb8157f9"},
+ "linux-release/media_tests_av_perf/dropped_fps/tulip2.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "c0fb3421"},
+ "linux-release/media_tests_av_perf/dropped_frames/crowd1080.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "fa9582d3"},
+ "linux-release/media_tests_av_perf/dropped_frames/crowd2160.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 166, "regress": 231, "sha1": "ca3a7a47"},
+ "linux-release/media_tests_av_perf/dropped_frames/crowd360.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "e3f6b861"},
+ "linux-release/media_tests_av_perf/dropped_frames/crowd480.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "b988fd20"},
+ "linux-release/media_tests_av_perf/dropped_frames/crowd720.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "21ea385c"},
+ "linux-release/media_tests_av_perf/dropped_frames/tulip2.m4a": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "f6e27427"},
+ "linux-release/media_tests_av_perf/dropped_frames/tulip2.mp3": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "642b1046"},
+ "linux-release/media_tests_av_perf/dropped_frames/tulip2.mp4": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "9c40b5d2"},
+ "linux-release/media_tests_av_perf/dropped_frames/tulip2.ogg": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "6f326241"},
+ "linux-release/media_tests_av_perf/dropped_frames/tulip2.ogv": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "bb6e4ddf"},
+ "linux-release/media_tests_av_perf/dropped_frames/tulip2.wav": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "ac7ce774"},
+ "linux-release/media_tests_av_perf/dropped_frames/tulip2.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "3dff8827"},
+ "linux-release/media_tests_av_perf/epp/Cable_crowd.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "56d9c646"},
+ "linux-release/media_tests_av_perf/epp/Cable_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "558ad3d8"},
+ "linux-release/media_tests_av_perf/epp/Cable_crowd360.ogv": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 0, "regress": 2, "sha1": "537b7126"},
+ "linux-release/media_tests_av_perf/epp/Cable_roller.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "4d57f03a"},
+ "linux-release/media_tests_av_perf/epp/DSL_crowd.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "689ad12b"},
+ "linux-release/media_tests_av_perf/epp/DSL_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "faf3ac4a"},
+ "linux-release/media_tests_av_perf/epp/DSL_crowd360.ogv": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 41, "regress": 58, "sha1": "11421d81"},
+ "linux-release/media_tests_av_perf/epp/DSL_roller.webm": {"reva": 176330, "revb": 176978, "type": "absolute", "better": "lower", "improve": 0, "regress": 2, "sha1": "6ce1bc53"},
+ "linux-release/media_tests_av_perf/epp/NoConstraints_crowd.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "392168f6"},
+ "linux-release/media_tests_av_perf/epp/NoConstraints_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "a8907efa"},
+ "linux-release/media_tests_av_perf/epp/NoConstraints_crowd360.ogv": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 0.0, "regress": 1.575, "sha1": "35311024"},
+ "linux-release/media_tests_av_perf/epp/NoConstraints_roller.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "e687faca"},
+ "linux-release/media_tests_av_perf/epp/Slow_crowd.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "817023bd"},
+ "linux-release/media_tests_av_perf/epp/Slow_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 142, "regress": 234, "sha1": "99c15c9c"},
+ "linux-release/media_tests_av_perf/epp/Slow_crowd360.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 698, "regress": 804, "sha1": "59269f2b"},
+ "linux-release/media_tests_av_perf/epp/Slow_roller.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 255, "regress": 306, "sha1": "fdaf9c39"},
+ "linux-release/media_tests_av_perf/epp/Wifi_crowd.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "22b5926f"},
+ "linux-release/media_tests_av_perf/epp/Wifi_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "830a58e2"},
+ "linux-release/media_tests_av_perf/epp/Wifi_crowd360.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 99, "regress": 119, "sha1": "025cc824"},
+ "linux-release/media_tests_av_perf/epp/Wifi_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 1, "regress": 8, "sha1": "cf168284"},
+ "linux-release/media_tests_av_perf/fps/crowd1080.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 53, "regress": 47, "sha1": "69781b52"},
+ "linux-release/media_tests_av_perf/fps/crowd2160.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "higher", "improve": 35.3377622378, "regress": 30.9306550593, "sha1": "a723b4b3"},
+ "linux-release/media_tests_av_perf/fps/crowd360.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 52, "regress": 47, "sha1": "f2f824ba"},
+ "linux-release/media_tests_av_perf/fps/crowd480.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 53, "regress": 47, "sha1": "95977e31"},
+ "linux-release/media_tests_av_perf/fps/crowd720.webm": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 53, "regress": 47, "sha1": "e8fc6dd8"},
+ "linux-release/media_tests_av_perf/fps/tulip2.m4a": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "847491c2"},
+ "linux-release/media_tests_av_perf/fps/tulip2.mp3": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "c9c5c2d1"},
+ "linux-release/media_tests_av_perf/fps/tulip2.mp4": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 32, "regress": 28, "sha1": "aa400e11"},
+ "linux-release/media_tests_av_perf/fps/tulip2.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "95f6d884"},
+ "linux-release/media_tests_av_perf/fps/tulip2.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 32, "regress": 28, "sha1": "0560e39f"},
+ "linux-release/media_tests_av_perf/fps/tulip2.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "39e92b9d"},
+ "linux-release/media_tests_av_perf/memory/crowd1080.webm": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 62859, "regress": 70350, "sha1": "19057e72"},
+ "linux-release/media_tests_av_perf/memory/crowd2160.webm": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 123595, "regress": 137420, "sha1": "ef1da02b"},
+ "linux-release/media_tests_av_perf/memory/crowd360.webm": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 39713, "regress": 44919, "sha1": "afe6c1c6"},
+ "linux-release/media_tests_av_perf/memory/crowd480.webm": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 42358, "regress": 48128, "sha1": "4f78f54b"},
+ "linux-release/media_tests_av_perf/memory/crowd720.webm": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 48054, "regress": 54689, "sha1": "648d1951"},
+ "linux-release/media_tests_av_perf/memory/tulip2.m4a": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 33326, "regress": 39909, "sha1": "971a1920"},
+ "linux-release/media_tests_av_perf/memory/tulip2.mp3": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 32972, "regress": 39426, "sha1": "8edbf6ef"},
+ "linux-release/media_tests_av_perf/memory/tulip2.mp4": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 53268, "regress": 60955, "sha1": "f9e9838c"},
+ "linux-release/media_tests_av_perf/memory/tulip2.ogg": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 32794, "regress": 39161, "sha1": "1d2783dd"},
+ "linux-release/media_tests_av_perf/memory/tulip2.ogv": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 51938, "regress": 57952, "sha1": "56271a1e"},
+ "linux-release/media_tests_av_perf/memory/tulip2.wav": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 36054, "regress": 42815, "sha1": "8bba77a1"},
+ "linux-release/media_tests_av_perf/memory/tulip2.webm": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 47792, "regress": 54386, "sha1": "0a6beaaf"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.m4a_backward": {"reva": 166121, "revb": 166945, "type": "absolute", "better": "lower", "improve": 3, "regress": 23, "sha1": "f9b24229"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.m4a_forward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 2, "regress": 7, "sha1": "85180a44"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.m4a_mixed": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 3, "regress": 8, "sha1": "c1907194"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.mp3_backward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 6, "regress": 12, "sha1": "53010a2e"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.mp3_forward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 6, "regress": 11, "sha1": "320a2037"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.mp3_mixed": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 3, "regress": 11, "sha1": "0ac18d26"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.mp4_backward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 472, "regress": 564, "sha1": "efc4f1d9"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.mp4_forward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 68, "regress": 89, "sha1": "b5489acf"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.mp4_mixed": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 740, "regress": 844, "sha1": "d5b6b7fd"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.ogg_backward": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 2, "regress": 8, "sha1": "a31b671f"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.ogg_forward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 2, "regress": 8, "sha1": "d8bed0a5"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.ogg_mixed": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 2, "regress": 9, "sha1": "1dd070af"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.ogv_backward": {"reva": 191557, "revb": 192465, "type": "absolute", "better": "lower", "improve": 57, "regress": 177, "sha1": "8a1d0b59"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.ogv_forward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 54, "regress": 110, "sha1": "0a44ddc2"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.ogv_mixed": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 57, "regress": 73, "sha1": "bedf10a3"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.wav_backward": {"reva": 165856, "revb": 166292, "type": "absolute", "better": "lower", "improve": 4, "regress": 66, "sha1": "df06d291"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.wav_forward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 5, "regress": 10, "sha1": "1740661f"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.wav_mixed": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 2, "regress": 8, "sha1": "f6819f04"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.webm_backward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 912, "regress": 1103, "sha1": "ee4ad33a"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.webm_forward": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 61, "regress": 88, "sha1": "88356f58"},
+ "linux-release/media_tests_av_perf/scrubbing/tulip2.webm_mixed": {"reva": 161029, "revb": 161120, "type": "absolute", "better": "lower", "improve": 520, "regress": 637, "sha1": "b14f3f4f"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 565, "regress": 646, "sha1": "37d71692"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd1080.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 59, "regress": 110, "sha1": "c97e8210"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 519, "regress": 618, "sha1": "3f9c9032"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 88, "regress": 135, "sha1": "d9dbce6f"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd360.ogv": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 21.5821000001, "regress": 42.6609749999, "sha1": "5aafdae1"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 89, "regress": 120, "sha1": "26196553"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 8, "regress": 12, "sha1": "1cc42c59"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_dartmoor2.mp3": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 7.04377499998, "regress": 9.92249999989, "sha1": "6bd202b6"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 4, "sha1": "ee7f4cc3"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 5, "regress": 22, "sha1": "67b3615b"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 562, "regress": 651, "sha1": "56571d67"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd1080.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 74, "regress": 145, "sha1": "68c871fc"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd1080.webm": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 528.347725, "regress": 635.011125, "sha1": "ee417810"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 92, "regress": 130, "sha1": "c6564ca2"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd360.ogv": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 24.7930999999, "regress": 40.370925, "sha1": "afca0496"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 89, "regress": 132, "sha1": "c0c9f897"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 8, "regress": 13, "sha1": "93ade19e"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 9, "regress": 15, "sha1": "60bd3253"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 8, "sha1": "10a0c04d"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 8, "regress": 13, "sha1": "1cd58982"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 555, "regress": 672, "sha1": "bf88a3e8"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd1080.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 66, "regress": 88, "sha1": "4397f352"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd1080.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 530.856675, "regress": 649.0701, "sha1": "d1b41170"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 91, "regress": 253, "sha1": "7036569d"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd360.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 22, "regress": 33, "sha1": "56834f63"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 84, "regress": 121, "sha1": "2441b10a"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 5, "regress": 8, "sha1": "3268433e"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 6, "regress": 10, "sha1": "3bfad537"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 4, "sha1": "849c1e30"},
+ "linux-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 6, "regress": 43, "sha1": "b69e3da9"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd1080.mp4": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 673.12535, "regress": 779.83395, "sha1": "6f2bc684"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd1080.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 212, "regress": 447, "sha1": "6d6f0f81"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1815, "regress": 2092, "sha1": "0fa52805"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 92, "regress": 130, "sha1": "51affb01"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd360.ogv": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 79.7795750001, "regress": 153.963075, "sha1": "43ba54cb"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd360.webm": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 266.528675, "regress": 379.000125, "sha1": "c4ecb4f9"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 46, "regress": 61, "sha1": "75d349dd"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 49, "regress": 68, "sha1": "8f313b22"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 5, "sha1": "24405c81"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 33, "regress": 58, "sha1": "d73454f5"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd1080.mp4": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 635.399425, "regress": 727.5282, "sha1": "89afaf85"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd1080.ogv": {"reva": 169114, "revb": 169774, "type": "absolute", "better": "lower", "improve": 83.216675, "regress": 288.69015, "sha1": "169a5996"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1741, "regress": 2004, "sha1": "e7d6de41"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 92, "regress": 130, "sha1": "5263d67e"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd360.ogv": {"reva": 169114, "revb": 169774, "type": "absolute", "better": "lower", "improve": 13.96215, "regress": 49.0271249999, "sha1": "446408eb"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 261, "regress": 350, "sha1": "ca836a17"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 4.17857499998, "regress": 7.69282500009, "sha1": "097172f5"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 5.324275, "regress": 11.4969749999, "sha1": "e5efe7bc"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 191557, "revb": 192465, "type": "absolute", "better": "lower", "improve": 1.51477500001, "regress": 6.71422499994, "sha1": "0233e2d7"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 8, "regress": 15, "sha1": "5e67d71a"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 952, "regress": 1173, "sha1": "6d748214"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd1080.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 254, "regress": 840, "sha1": "d8470cd7"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd1080.webm": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 1835.38955, "regress": 2270.661225, "sha1": "4170989c"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 91, "regress": 132, "sha1": "b8c67309"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd360.ogv": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 120.999125, "regress": 273.634725, "sha1": "670f7de8"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 255, "regress": 343, "sha1": "0cb5aaff"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 147, "regress": 168, "sha1": "f37fb463"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 138, "regress": 163, "sha1": "5607ef7a"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 4, "sha1": "5796e64e"},
+ "linux-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 99, "regress": 228, "sha1": "05ec4dd0"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 550, "regress": 628, "sha1": "c84601af"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd1080.ogv": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 160.80745, "regress": 237.234375, "sha1": "44b1a1c3"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 499, "regress": 583, "sha1": "5f0ad194"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 81, "regress": 117, "sha1": "31d60ce4"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd360.ogv": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 60.11315, "regress": 170.3394, "sha1": "853645b3"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 80, "regress": 104, "sha1": "a045a4fe"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 5, "sha1": "37b1da65"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_dartmoor2.mp3": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 4.75427500004, "regress": 7.28699999986, "sha1": "9249b344"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 2, "regress": 5, "sha1": "4370e14f"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 0, "regress": 3, "sha1": "45b180bd"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 545, "regress": 620, "sha1": "f4167af3"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd1080.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 94, "regress": 224, "sha1": "5f348f6f"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 489, "regress": 563, "sha1": "9235e5f8"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 83, "regress": 119, "sha1": "5fee97a7"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd360.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 27, "regress": 48, "sha1": "1431f765"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 80, "regress": 109, "sha1": "994aa163"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 6, "sha1": "82e6a96f"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 4.80604999996, "regress": 9.46522500003, "sha1": "0928519d"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 2, "regress": 7, "sha1": "0e10f97e"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 5, "sha1": "e542f46b"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 569, "regress": 654, "sha1": "6cd04b3b"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd1080.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 163, "regress": 342, "sha1": "4fb69f8c"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 496, "regress": 575, "sha1": "4cec3987"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 78, "regress": 108, "sha1": "bca16911"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd360.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 58, "regress": 374, "sha1": "90071e6b"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 78, "regress": 110, "sha1": "fa0b0a1a"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 2, "sha1": "a7ca438b"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 4, "regress": 8, "sha1": "3f4ebfc3"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 2, "regress": 4, "sha1": "26b14db8"},
+ "linux-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 3, "sha1": "88290829"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 566, "regress": 642, "sha1": "a97029c2"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd1080.ogv": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 107.03745, "regress": 715.1571, "sha1": "79688e01"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd1080.webm": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 529.5661, "regress": 644.117775, "sha1": "525781ed"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 88, "regress": 125, "sha1": "86c8b42d"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd360.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 24, "regress": 51, "sha1": "87ef4451"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 85, "regress": 114, "sha1": "2f817c54"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 7, "regress": 11, "sha1": "3e1b6941"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_dartmoor2.mp3": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 6.79439999991, "regress": 9.59017499996, "sha1": "9a3b31f4"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 4, "sha1": "9b121d7d"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 6, "regress": 71, "sha1": "1d115baa"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 564, "regress": 647, "sha1": "67a69ad0"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd1080.ogv": {"reva": 169114, "revb": 169774, "type": "absolute", "better": "lower", "improve": 71.5967499997, "regress": 162.206625, "sha1": "9a638a75"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd1080.webm": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 529.968425, "regress": 607.169325, "sha1": "f68b5741"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 93, "regress": 129, "sha1": "2e657006"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd360.ogv": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 24.78455, "regress": 41.2461, "sha1": "c050f6ab"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 89, "regress": 134, "sha1": "a86a0760"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 7, "regress": 12, "sha1": "ee2f1cfc"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 9, "regress": 14, "sha1": "b38fdd66"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 7, "sha1": "cb76fcc0"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 6, "regress": 11, "sha1": "4bf115a8"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 568, "regress": 678, "sha1": "42d98c3d"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd1080.ogv": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 467.501174994, "regress": 602.30415, "sha1": "993cb704"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 506, "regress": 597, "sha1": "c619725f"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 93, "regress": 431, "sha1": "fb51a118"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd360.ogv": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 22.933475, "regress": 35.9897999999, "sha1": "88f84705"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 87, "regress": 140, "sha1": "729c2b47"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 5, "regress": 10, "sha1": "61c4ebcd"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 7, "regress": 12, "sha1": "acf411f5"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 4, "sha1": "2eec910d"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_dartmoor2.wav": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 6.06669999991, "regress": 9.51719999997, "sha1": "ab393a1c"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd1080.mp4": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 3418.29475, "regress": 3827.23845, "sha1": "22ff7f9f"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd1080.ogv": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 2317.3616, "regress": 3513.463275, "sha1": "6afce591"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 10430, "regress": 11629, "sha1": "2eabd1d4"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 3309, "regress": 3698, "sha1": "ad3401dc"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd360.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 423, "regress": 590, "sha1": "12bc6005"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 3159, "regress": 3525, "sha1": "1d2ff311"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_dartmoor2.m4a": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 125.719675, "regress": 150.988425, "sha1": "01429b02"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_dartmoor2.mp3": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 133.874, "regress": 174.861225, "sha1": "bceac5f0"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 4, "sha1": "a86c8c39"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_dartmoor2.wav": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 188.3147, "regress": 239.3328, "sha1": "b4cc6aa3"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd1080.mp4": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 635.555225, "regress": 725.349975, "sha1": "90680b54"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd1080.ogv": {"reva": 169114, "revb": 169774, "type": "absolute", "better": "lower", "improve": 84.280675, "regress": 303.715125, "sha1": "7d939566"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1740, "regress": 1998, "sha1": "ab982dfa"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 92, "regress": 131, "sha1": "d0916b13"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd360.ogv": {"reva": 169114, "revb": 169774, "type": "absolute", "better": "lower", "improve": 15.205225, "regress": 51.9792000001, "sha1": "ab99c9ef"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 265, "regress": 358, "sha1": "bfad200a"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 4, "regress": 9, "sha1": "cfb5b581"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 5.45204999995, "regress": 10.723125, "sha1": "20fdaeb4"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 6, "sha1": "221b2779"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 8, "regress": 14, "sha1": "24915076"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd1080.mp4": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 17700.131625, "regress": 22252.22685, "sha1": "d723eec8"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd1080.ogv": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 10703.4467, "regress": 12187.819875, "sha1": "f4294a15"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 48158, "regress": 53802, "sha1": "e9e8a0bd"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 16454, "regress": 18430, "sha1": "43f51908"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd360.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1602, "regress": 2080, "sha1": "7469a193"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 14977, "regress": 16844, "sha1": "b887f40e"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_dartmoor2.m4a": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 429.81895, "regress": 595.1694, "sha1": "216cfa21"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_dartmoor2.mp3": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 477.789675, "regress": 671.730675, "sha1": "d28b5279"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 4, "sha1": "a25cb81c"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_dartmoor2.wav": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 1582.526625, "regress": 2079.0378, "sha1": "b318f4cd"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 2398, "regress": 2682, "sha1": "f56a1248"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd1080.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1943, "regress": 2775, "sha1": "29afec16"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd1080.webm": {"reva": 191557, "revb": 192465, "type": "absolute", "better": "lower", "improve": 2280.8949, "regress": 2568.1635, "sha1": "598d4cf5"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 411, "regress": 492, "sha1": "85f71ddc"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd360.ogv": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 866.15965, "regress": 1085.622825, "sha1": "9959cc23"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd360.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 439.3902, "regress": 514.402875, "sha1": "c43e9326"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 43, "regress": 126, "sha1": "0c556344"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_dartmoor2.mp3": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 4.81175000006, "regress": 7.62614999997, "sha1": "979bbc98"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 2, "regress": 5, "sha1": "88acbe66"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 4, "sha1": "c865f322"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 542, "regress": 653, "sha1": "607aa114"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd1080.ogv": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 76.36195, "regress": 163.5459, "sha1": "764a75db"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd1080.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 492, "regress": 580, "sha1": "aaf03264"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 83, "regress": 116, "sha1": "9ff7419d"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd360.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 27, "regress": 48, "sha1": "c5813ff7"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd360.webm": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 80, "regress": 105, "sha1": "f9d964da"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 2, "regress": 7, "sha1": "ed3c109d"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 5, "regress": 11, "sha1": "b6741dfe"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 2, "regress": 7, "sha1": "2673dcdd"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1, "regress": 6, "sha1": "d948ffff"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd1080.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 9966, "regress": 11310, "sha1": "92e0f3eb"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd1080.ogv": {"reva": 200515, "revb": 201324, "type": "absolute", "better": "lower", "improve": 8914.107925, "regress": 10075.857225, "sha1": "9f1761b6"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 9612.36125, "regress": 10884.837075, "sha1": "305e4a86"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd360.mp4": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 1802, "regress": 2101, "sha1": "c48a1327"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd360.ogv": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 3723, "regress": 4541, "sha1": "477a5d15"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd360.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 1922.2452, "regress": 2278.272675, "sha1": "d4e8b3dd"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_dartmoor2.m4a": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 272, "regress": 368, "sha1": "fa90189d"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_dartmoor2.mp3": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 5, "regress": 10, "sha1": "7c31a145"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_dartmoor2.ogg": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 2, "regress": 5, "sha1": "de03a74d"},
+ "linux-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_dartmoor2.wav": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "lower", "improve": 0, "regress": 3, "sha1": "82088da1"},
+ "linux-release/media_tests_av_perf/ttp/Cable_crowd.ogg": {"reva": 169114, "revb": 169774, "type": "absolute", "better": "lower", "improve": 343.9, "regress": 391.125, "sha1": "a8a6c271"},
+ "linux-release/media_tests_av_perf/ttp/Cable_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 1590, "regress": 1770, "sha1": "c3987d01"},
+ "linux-release/media_tests_av_perf/ttp/Cable_crowd1080.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 715.35, "regress": 986.475, "sha1": "f1c1c5d0"},
+ "linux-release/media_tests_av_perf/ttp/Cable_crowd1080.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 1546, "regress": 1733, "sha1": "a0ccb161"},
+ "linux-release/media_tests_av_perf/ttp/Cable_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 913.425, "regress": 1037.925, "sha1": "2bd03bda"},
+ "linux-release/media_tests_av_perf/ttp/Cable_crowd360.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 285.95, "regress": 520.275, "sha1": "55a98a4a"},
+ "linux-release/media_tests_av_perf/ttp/Cable_crowd360.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 731, "regress": 830, "sha1": "b29614b5"},
+ "linux-release/media_tests_av_perf/ttp/Cable_crowd360.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 372.4, "regress": 650.475, "sha1": "099f43ad"},
+ "linux-release/media_tests_av_perf/ttp/Cable_dartmoor2.m4a": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 183, "regress": 222, "sha1": "d5463692"},
+ "linux-release/media_tests_av_perf/ttp/Cable_dartmoor2.mp3": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 313, "regress": 364, "sha1": "dc22402e"},
+ "linux-release/media_tests_av_perf/ttp/Cable_dartmoor2.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 2580, "regress": 2922, "sha1": "f5c3cc0a"},
+ "linux-release/media_tests_av_perf/ttp/Cable_dartmoor2.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 1485, "regress": 1665, "sha1": "5c7b4cf8"},
+ "linux-release/media_tests_av_perf/ttp/Cable_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 278.825, "regress": 363.825, "sha1": "10713d86"},
+ "linux-release/media_tests_av_perf/ttp/DSL_crowd.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 817, "regress": 909, "sha1": "0d341c66"},
+ "linux-release/media_tests_av_perf/ttp/DSL_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 4942, "regress": 5582, "sha1": "fe196bfb"},
+ "linux-release/media_tests_av_perf/ttp/DSL_crowd1080.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 1976.95, "regress": 2254.875, "sha1": "3f057935"},
+ "linux-release/media_tests_av_perf/ttp/DSL_crowd1080.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 4200, "regress": 4744, "sha1": "5d2a2d29"},
+ "linux-release/media_tests_av_perf/ttp/DSL_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 2576.875, "regress": 2934.225, "sha1": "f4f53ab8"},
+ "linux-release/media_tests_av_perf/ttp/DSL_crowd360.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 626.525, "regress": 875.175, "sha1": "74cf3935"},
+ "linux-release/media_tests_av_perf/ttp/DSL_crowd360.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 1590, "regress": 1782, "sha1": "04b4b2c4"},
+ "linux-release/media_tests_av_perf/ttp/DSL_crowd360.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 899.65, "regress": 1084.125, "sha1": "6f4aafe0"},
+ "linux-release/media_tests_av_perf/ttp/DSL_dartmoor2.m4a": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 320, "regress": 359, "sha1": "96c6be15"},
+ "linux-release/media_tests_av_perf/ttp/DSL_dartmoor2.mp3": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 746, "regress": 903, "sha1": "4761de2d"},
+ "linux-release/media_tests_av_perf/ttp/DSL_dartmoor2.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 8290, "regress": 9179, "sha1": "27a42c6c"},
+ "linux-release/media_tests_av_perf/ttp/DSL_dartmoor2.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 4630, "regress": 5217, "sha1": "f40f1fba"},
+ "linux-release/media_tests_av_perf/ttp/DSL_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 626.525, "regress": 743.925, "sha1": "93ae252b"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_crowd.ogg": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 10, "regress": 99, "sha1": "9caa19dd"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_crowd.wav": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 16, "regress": 359, "sha1": "60ca99ce"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_crowd1080.mp4": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 144, "regress": 281, "sha1": "df7c0150"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_crowd1080.ogv": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 63, "regress": 445, "sha1": "5af2f858"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_crowd1080.webm": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 83, "regress": 319, "sha1": "e28c132e"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_crowd360.mp4": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 40, "regress": 108, "sha1": "ec392a53"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_crowd360.ogv": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 33, "regress": 248, "sha1": "030d55d3"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_crowd360.webm": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 32, "regress": 122, "sha1": "ad3f6b1f"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_dartmoor2.m4a": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 12, "regress": 61, "sha1": "2c9b0a2d"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_dartmoor2.mp3": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 14, "regress": 99, "sha1": "4fb1877c"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_dartmoor2.ogg": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 14, "regress": 569, "sha1": "e6b2fc80"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_dartmoor2.wav": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 16, "regress": 370, "sha1": "c9ba0dd6"},
+ "linux-release/media_tests_av_perf/ttp/NoConstraints_roller.webm": {"reva": 159431, "revb": 160346, "type": "absolute", "better": "lower", "improve": 24, "regress": 77, "sha1": "a28e53af"},
+ "linux-release/media_tests_av_perf/ttp/Slow_crowd.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 4122, "regress": 4601, "sha1": "94c5898d"},
+ "linux-release/media_tests_av_perf/ttp/Slow_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 29007, "regress": 34806, "sha1": "a4f93cbb"},
+ "linux-release/media_tests_av_perf/ttp/Slow_crowd1080.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 10872, "regress": 13034, "sha1": "328b9f58"},
+ "linux-release/media_tests_av_perf/ttp/Slow_crowd1080.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 22338, "regress": 27063, "sha1": "9e7946bd"},
+ "linux-release/media_tests_av_perf/ttp/Slow_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 14051.925, "regress": 16758.0, "sha1": "271291d4"},
+ "linux-release/media_tests_av_perf/ttp/Slow_crowd360.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 2860, "regress": 3636, "sha1": "b4f09c02"},
+ "linux-release/media_tests_av_perf/ttp/Slow_crowd360.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 7346, "regress": 8669, "sha1": "0ed59713"},
+ "linux-release/media_tests_av_perf/ttp/Slow_crowd360.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 4563, "regress": 5699, "sha1": "75876832"},
+ "linux-release/media_tests_av_perf/ttp/Slow_dartmoor2.m4a": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 1129, "regress": 1256, "sha1": "958dd530"},
+ "linux-release/media_tests_av_perf/ttp/Slow_dartmoor2.mp3": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 3855, "regress": 4533, "sha1": "f15980c3"},
+ "linux-release/media_tests_av_perf/ttp/Slow_dartmoor2.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 49047, "regress": 55499, "sha1": "665ad63d"},
+ "linux-release/media_tests_av_perf/ttp/Slow_dartmoor2.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 26907, "regress": 30622, "sha1": "a130fd0b"},
+ "linux-release/media_tests_av_perf/ttp/Slow_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 2918.4, "regress": 3865.575, "sha1": "991d533e"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_crowd.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 1157, "regress": 1285, "sha1": "00ed690d"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_crowd.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 7396, "regress": 8297, "sha1": "8fe00f1a"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_crowd1080.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 2912.7, "regress": 3301.725, "sha1": "fafc45aa"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_crowd1080.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 6081, "regress": 6860, "sha1": "3a4f825f"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 3773, "regress": 4301, "sha1": "ccd0e0d6"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_crowd360.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 849.3, "regress": 1103.025, "sha1": "87d14c28"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_crowd360.ogv": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 2183, "regress": 2474, "sha1": "98fe35f3"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_crowd360.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 1326.2, "regress": 1538.775, "sha1": "c41669ce"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_dartmoor2.m4a": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 406, "regress": 455, "sha1": "e58e236a"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_dartmoor2.mp3": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 1090, "regress": 1265, "sha1": "2323659f"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_dartmoor2.ogg": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 12393, "regress": 13715, "sha1": "a27bbec2"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_dartmoor2.wav": {"reva": 155180, "revb": 155280, "type": "absolute", "better": "lower", "improve": 6893, "regress": 7758, "sha1": "7a3ab979"},
+ "linux-release/media_tests_av_perf/ttp/Wifi_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 867.35, "regress": 1041.075, "sha1": "d99ce51c"},
+ "linux-release/sizes/chrome-bss/bss": {"reva": 205093, "revb": 206368, "type": "absolute", "better": "lower", "improve": 316939, "regress": 389240, "sha1": "8d78343e"},
+ "linux-release/sizes/chrome-data/data": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 1936814, "regress": 2140724, "sha1": "915f9e72"},
+ "linux-release/sizes/chrome-si/initializers": {"reva": 216959, "revb": 216961, "type": "absolute", "better": "lower", "improve": 34, "regress": 34, "tolerance": 0, "sha1": "69a4e038"},
+ "linux-release/sizes/chrome-text/text": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 79833368, "regress": 88237335, "sha1": "e1b38def"},
+ "linux-release/sizes/chrome-textrel/textrel": {"reva": 135570, "revb": 135664, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "832078e7"},
+ "linux-release/sizes/chrome.pak/chrome.pak": {"reva": 214295, "revb": 214296, "type": "absolute", "better": "lower", "improve": 4578193, "regress": 5060109, "sha1": "a95a611b"},
+ "linux-release/sizes/chrome/chrome": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 108516653, "regress": 119939890, "sha1": "a6649863"},
+ "linux-release/sizes/libffmpegsumo.so-textrel/textrel": {"reva": 200467, "revb": 203456, "type": "absolute", "better": "lower", "improve": 1075, "regress": 1189, "sha1": "a10d4ea4"},
+ "linux-release/sizes/nacl_helper-bss/bss": {"reva": 193069, "revb": 193093, "type": "absolute", "better": "lower", "improve": 100506, "regress": 111086, "sha1": "805988e3"},
+ "linux-release/sizes/nacl_helper-data/data": {"reva": 197112, "revb": 203172, "type": "absolute", "better": "lower", "improve": 13058, "regress": 15186, "sha1": "df291639"},
+ "linux-release/sizes/nacl_helper-si/initializers": {"reva": 193069, "revb": 193093, "type": "absolute", "better": "lower", "improve": 15, "regress": 17, "sha1": "d7d27d7d"},
+ "linux-release/sizes/nacl_helper-text/text": {"reva": 210367, "revb": 210396, "type": "absolute", "better": "lower", "improve": 1123993, "regress": 1243233, "sha1": "f8f2dc58"},
+ "linux-release/sizes/nacl_helper-textrel/textrel": {"reva": 117081, "revb": 117299, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "309d1763"},
+ "linux-release/sizes/nacl_helper/nacl_helper": {"reva": 207276, "revb": 207476, "type": "absolute", "better": "lower", "improve": 1403834, "regress": 1556620, "sha1": "a30b27e9"},
+ "linux-release/sizes/nacl_helper_bootstrap-bss/bss": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 1019980807, "regress": 1127347209, "sha1": "a4ff54ab"},
+ "linux-release/sizes/nacl_helper_bootstrap-data/data": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 19, "regress": 21, "sha1": "6a3e92f4"},
+ "linux-release/sizes/nacl_helper_bootstrap-si/initializers": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "dd908f29"},
+ "linux-release/sizes/nacl_helper_bootstrap-text/text": {"reva": 150377, "revb": 150377, "type": "absolute", "better": "lower", "improve": 4596, "regress": 5080, "sha1": "4bb41c07"},
+ "linux-release/sizes/nacl_helper_bootstrap/nacl_helper_bootstrap": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 8776, "regress": 9700, "sha1": "3f284fed"},
+ "linux-release/sizes/totals-textrel/textrel": {"reva": 205083, "revb": 206071, "type": "absolute", "better": "lower", "improve": 1075, "regress": 1189, "sha1": "69d07fda"},
+ "mac-release/sizes/Chromium.app/Chromium.app": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 109237657, "regress": 120740660, "sha1": "4befe31e"},
+ "mac-release/sizes/Chromium/Chromium": {"reva": 165473, "revb": 165473, "type": "absolute", "better": "lower", "improve": 8132, "regress": 8988, "sha1": "8e448691"},
+ "mac-release/sizes/ChromiumFramework/ChromiumFramework": {"reva": 203454, "revb": 203474, "type": "absolute", "better": "lower", "improve": 75475151, "regress": 83424206, "sha1": "52a77a86"},
+ "mac-release/sizes/chrome-si/initializers": {"reva": 216955, "revb": 216962, "type": "absolute", "better": "lower", "improve": 13, "regress": 13, "tolerance": 0, "sha1": "c937ef20"},
+ "win-release/media_tests_av_perf/audio_latency/latency": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 57, "regress": 69, "sha1": "169d47dd"},
+ "win-release/media_tests_av_perf/audio_latency/latency_bg_clip": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 66, "regress": 78, "sha1": "708a71af"},
+ "win-release/media_tests_av_perf/audio_pesq/actual": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "higher", "improve": 4, "regress": 3, "sha1": "c8beccf7"},
+ "win-release/media_tests_av_perf/audio_pesq/ref": {"reva": 163215, "revb": 163382, "type": "absolute", "better": "higher", "improve": 4, "regress": 3, "sha1": "b17c1404"},
+ "win-release/media_tests_av_perf/cpu/crowd1080.webm": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 76, "sha1": "e656c991"},
+ "win-release/media_tests_av_perf/cpu/crowd2160.webm": {"reva": 176330, "revb": 176978, "type": "absolute", "better": "lower", "improve": 0, "regress": 53, "sha1": "16fa69d2"},
+ "win-release/media_tests_av_perf/cpu/crowd360.webm": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "2fff4dde"},
+ "win-release/media_tests_av_perf/cpu/crowd480.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 0.0, "regress": 34.965, "sha1": "e6190eba"},
+ "win-release/media_tests_av_perf/cpu/crowd720.webm": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 16, "sha1": "9aa94837"},
+ "win-release/media_tests_av_perf/cpu/tulip2.m4a": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "6d1f5272"},
+ "win-release/media_tests_av_perf/cpu/tulip2.mp3": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "dcd1b0c1"},
+ "win-release/media_tests_av_perf/cpu/tulip2.mp4": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 18, "sha1": "c4dc3413"},
+ "win-release/media_tests_av_perf/cpu/tulip2.ogg": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "be248133"},
+ "win-release/media_tests_av_perf/cpu/tulip2.ogv": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 18, "sha1": "dd40e49a"},
+ "win-release/media_tests_av_perf/cpu/tulip2.wav": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "a035aecb"},
+ "win-release/media_tests_av_perf/cpu/tulip2.webm": {"reva": 155313, "revb": 155418, "type": "absolute", "better": "lower", "improve": 0, "regress": 18, "sha1": "dc6fff68"},
+ "win-release/media_tests_av_perf/dropped_fps/crowd1080.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "4935486d"},
+ "win-release/media_tests_av_perf/dropped_fps/crowd2160.webm": {"reva": 191557, "revb": 192465, "type": "absolute", "better": "lower", "improve": 21.163293849, "regress": 26.4, "sha1": "a20b7414"},
+ "win-release/media_tests_av_perf/dropped_fps/crowd360.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "e2ada1dd"},
+ "win-release/media_tests_av_perf/dropped_fps/crowd480.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "5871d7d2"},
+ "win-release/media_tests_av_perf/dropped_fps/crowd720.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "bf00297a"},
+ "win-release/media_tests_av_perf/dropped_fps/tulip2.m4a": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "67db0210"},
+ "win-release/media_tests_av_perf/dropped_fps/tulip2.mp3": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "b5fa89aa"},
+ "win-release/media_tests_av_perf/dropped_fps/tulip2.mp4": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "92244ff2"},
+ "win-release/media_tests_av_perf/dropped_fps/tulip2.ogg": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "93a5ccdc"},
+ "win-release/media_tests_av_perf/dropped_fps/tulip2.ogv": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "e9a3c133"},
+ "win-release/media_tests_av_perf/dropped_fps/tulip2.wav": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "646c02f2"},
+ "win-release/media_tests_av_perf/dropped_fps/tulip2.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "46c97b57"},
+ "win-release/media_tests_av_perf/dropped_frames/crowd1080.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "9b709aab"},
+ "win-release/media_tests_av_perf/dropped_frames/crowd2160.webm": {"reva": 196991, "revb": 197064, "type": "absolute", "better": "lower", "improve": 195, "regress": 223, "sha1": "25a48e0b"},
+ "win-release/media_tests_av_perf/dropped_frames/crowd360.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 2, "sha1": "cc585f85"},
+ "win-release/media_tests_av_perf/dropped_frames/crowd480.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "7f148b33"},
+ "win-release/media_tests_av_perf/dropped_frames/crowd720.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "652cdef1"},
+ "win-release/media_tests_av_perf/dropped_frames/tulip2.m4a": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "2ee9d3b2"},
+ "win-release/media_tests_av_perf/dropped_frames/tulip2.mp3": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "3f7b38ef"},
+ "win-release/media_tests_av_perf/dropped_frames/tulip2.mp4": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "35ce4c32"},
+ "win-release/media_tests_av_perf/dropped_frames/tulip2.ogg": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "204066af"},
+ "win-release/media_tests_av_perf/dropped_frames/tulip2.ogv": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "4fc69c09"},
+ "win-release/media_tests_av_perf/dropped_frames/tulip2.wav": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "7fcbbac5"},
+ "win-release/media_tests_av_perf/dropped_frames/tulip2.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "51b7e5f5"},
+ "win-release/media_tests_av_perf/epp/Cable_crowd.ogg": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "ec4b683b"},
+ "win-release/media_tests_av_perf/epp/Cable_crowd.wav": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "7b9411b3"},
+ "win-release/media_tests_av_perf/epp/Cable_crowd360.ogv": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 7, "sha1": "9fbce84f"},
+ "win-release/media_tests_av_perf/epp/Cable_roller.webm": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "1895e4a4"},
+ "win-release/media_tests_av_perf/epp/DSL_crowd.ogg": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "9e863d94"},
+ "win-release/media_tests_av_perf/epp/DSL_crowd.wav": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "ea185579"},
+ "win-release/media_tests_av_perf/epp/DSL_crowd360.ogv": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 35, "regress": 49, "sha1": "6e658593"},
+ "win-release/media_tests_av_perf/epp/DSL_roller.webm": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 3, "sha1": "48e41b52"},
+ "win-release/media_tests_av_perf/epp/NoConstraints_crowd.ogg": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "7e34c68e"},
+ "win-release/media_tests_av_perf/epp/NoConstraints_crowd.wav": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "32f4eb41"},
+ "win-release/media_tests_av_perf/epp/NoConstraints_crowd360.ogv": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "ecf1c91f"},
+ "win-release/media_tests_av_perf/epp/NoConstraints_roller.webm": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "1f5f0ea0"},
+ "win-release/media_tests_av_perf/epp/Slow_crowd.ogg": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "e02d4552"},
+ "win-release/media_tests_av_perf/epp/Slow_crowd.wav": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 176, "regress": 227, "sha1": "8c55739e"},
+ "win-release/media_tests_av_perf/epp/Slow_crowd360.ogv": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 694, "regress": 781, "sha1": "48a97e33"},
+ "win-release/media_tests_av_perf/epp/Slow_roller.webm": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 256, "regress": 313, "sha1": "72596a9f"},
+ "win-release/media_tests_av_perf/epp/Wifi_crowd.ogg": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "b61c81c4"},
+ "win-release/media_tests_av_perf/epp/Wifi_crowd.wav": {"reva": 154809, "revb": 155280, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "06451f33"},
+ "win-release/media_tests_av_perf/epp/Wifi_crowd360.ogv": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 96.9, "regress": 123.375, "sha1": "2c36e1cb"},
+ "win-release/media_tests_av_perf/epp/Wifi_roller.webm": {"reva": 163449, "revb": 166283, "type": "absolute", "better": "lower", "improve": 0, "regress": 5, "sha1": "9a02da3a"},
+ "win-release/media_tests_av_perf/fps/crowd1080.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 53, "regress": 43, "sha1": "7ad49461"},
+ "win-release/media_tests_av_perf/fps/crowd2160.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "higher", "improve": 31.4818681319, "regress": 26.1771770063, "sha1": "9591dc94"},
+ "win-release/media_tests_av_perf/fps/crowd360.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 51, "regress": 47, "sha1": "7f8ef21c"},
+ "win-release/media_tests_av_perf/fps/crowd480.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 50, "regress": 47, "sha1": "5dc96881"},
+ "win-release/media_tests_av_perf/fps/crowd720.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 52, "regress": 47, "sha1": "4fcfb653"},
+ "win-release/media_tests_av_perf/fps/tulip2.m4a": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "54d94538"},
+ "win-release/media_tests_av_perf/fps/tulip2.mp3": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "113aef17"},
+ "win-release/media_tests_av_perf/fps/tulip2.mp4": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 30, "regress": 28, "sha1": "a22847d0"},
+ "win-release/media_tests_av_perf/fps/tulip2.ogg": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "6ee2e716"},
+ "win-release/media_tests_av_perf/fps/tulip2.ogv": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 32, "regress": 26, "sha1": "dfadb872"},
+ "win-release/media_tests_av_perf/fps/tulip2.wav": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "530c5bf5"},
+ "win-release/media_tests_av_perf/fps/tulip2.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 30, "regress": 28, "sha1": "35b91c8e"},
+ "win-release/media_tests_av_perf/memory/crowd1080.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 49362, "regress": 89486, "sha1": "cbb3c271"},
+ "win-release/media_tests_av_perf/memory/crowd2160.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 108072, "regress": 208383, "sha1": "ffb430e7"},
+ "win-release/media_tests_av_perf/memory/crowd360.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 36411, "regress": 59603, "sha1": "2048db51"},
+ "win-release/media_tests_av_perf/memory/crowd480.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 38079, "regress": 63639, "sha1": "77413228"},
+ "win-release/media_tests_av_perf/memory/crowd720.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 42715, "regress": 73185, "sha1": "89edd4d4"},
+ "win-release/media_tests_av_perf/memory/tulip2.m4a": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 38220, "regress": 46948, "sha1": "f437a73c"},
+ "win-release/media_tests_av_perf/memory/tulip2.mp3": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 38030, "regress": 46667, "sha1": "159906a6"},
+ "win-release/media_tests_av_perf/memory/tulip2.mp4": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 44889, "regress": 63576, "sha1": "2cabbec5"},
+ "win-release/media_tests_av_perf/memory/tulip2.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 37498, "regress": 46188, "sha1": "794b3769"},
+ "win-release/media_tests_av_perf/memory/tulip2.ogv": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 54921, "regress": 72572, "sha1": "c60e1e53"},
+ "win-release/media_tests_av_perf/memory/tulip2.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 39516, "regress": 48561, "sha1": "bd27ef8c"},
+ "win-release/media_tests_av_perf/memory/tulip2.webm": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 51550, "regress": 63786, "sha1": "9dbc3af3"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.m4a_backward": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 2, "regress": 477, "sha1": "45c77e2c"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.m4a_forward": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 0, "regress": 7, "sha1": "348fedf9"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.m4a_mixed": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 2, "regress": 9, "sha1": "209d9f97"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.mp3_backward": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 15, "regress": 27, "sha1": "d75ded98"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.mp3_forward": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 12, "regress": 21, "sha1": "0b4dcccc"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.mp3_mixed": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 15, "regress": 21, "sha1": "8d484197"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.mp4_backward": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 1041, "regress": 1850, "sha1": "c2b3c8f8"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.mp4_forward": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 201, "regress": 246, "sha1": "799f2bf5"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.mp4_mixed": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 1321, "regress": 1503, "sha1": "182b1798"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.ogg_backward": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 3, "regress": 10, "sha1": "38eed2d2"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.ogg_forward": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 3, "regress": 9, "sha1": "0212ffb3"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.ogg_mixed": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 2, "regress": 9, "sha1": "d2737e9b"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.ogv_backward": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 57, "regress": 1410, "sha1": "8e1726fb"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.ogv_forward": {"reva": 168500, "revb": 168878, "type": "absolute", "better": "lower", "improve": 60, "regress": 227, "sha1": "7acb7497"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.ogv_mixed": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 48, "regress": 151, "sha1": "ee3aa5fd"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.wav_backward": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2, "regress": 601, "sha1": "cfcf12b4"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.wav_forward": {"reva": 164549, "revb": 164669, "type": "absolute", "better": "lower", "improve": 0, "regress": 10, "sha1": "0344cbf8"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.wav_mixed": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 2, "regress": 7, "sha1": "570172e2"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.webm_backward": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 953, "regress": 1671, "sha1": "b5291ceb"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.webm_forward": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 54, "regress": 244, "sha1": "a0f5cc2e"},
+ "win-release/media_tests_av_perf/scrubbing/tulip2.webm_mixed": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "lower", "improve": 533, "regress": 649, "sha1": "4b9b4267"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 987.525, "regress": 2243.85, "sha1": "33d35fb0"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd1080.ogv": {"reva": 191557, "revb": 192465, "type": "absolute", "better": "lower", "improve": 67.4500000001, "regress": 112.35, "sha1": "c5570325"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 551.95, "regress": 657.825, "sha1": "186f563f"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 130.15, "regress": 371.175, "sha1": "5fdc529c"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 23.7500000001, "regress": 41.4750000001, "sha1": "5f5e0dc5"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 85.025, "regress": 112.35, "sha1": "d3860613"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 6.17500000039, "regress": 14.175, "sha1": "1d2ff0fe"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 10.9250000001, "regress": 34.6500000001, "sha1": "e9c04942"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999995, "regress": 3.67500000003, "sha1": "95cde93e"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Cable_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 5.69999999987, "regress": 9.44999999978, "sha1": "0a1044ff"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 971, "regress": 3799, "sha1": "ec467c66"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd1080.ogv": {"reva": 176330, "revb": 176978, "type": "absolute", "better": "lower", "improve": 77.9000000001, "regress": 133.875, "sha1": "8497e315"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 527.725, "regress": 616.35, "sha1": "ef8b22b8"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 199.975, "regress": 406.35, "sha1": "895884df"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 25.65, "regress": 36.2250000002, "sha1": "99bf99e0"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 81, "regress": 100, "sha1": "c04856c8"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 6.64999999963, "regress": 15.7499999999, "sha1": "ec36f7ed"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 13.2999999999, "regress": 19.4249999999, "sha1": "1b7ed581"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.90000000017, "regress": 4.19999999991, "sha1": "28d5764f"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 5.69999999987, "regress": 13.125, "sha1": "7bdfb3fc"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 975.175, "regress": 1195.425, "sha1": "2a9d4288"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 69.8250000002, "regress": 86.625, "sha1": "8c0d35b6"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 543.875, "regress": 636.3, "sha1": "16cf14a1"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 177.175, "regress": 302.4, "sha1": "bb8f6341"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 22.325, "regress": 28.8749999999, "sha1": "ff5f04dd"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 81.2249999999, "regress": 105.525, "sha1": "8bfddadf"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 5.70000000009, "regress": 13.6500000001, "sha1": "e24a93d5"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 10.9249999998, "regress": 13.6499999999, "sha1": "62747622"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999995, "regress": 3.67500000003, "sha1": "b13b427e"},
+ "win-release/media_tests_av_perf/seek/CACHED_BUFFERED_SEEK_Wifi_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 5.69999999987, "regress": 38.85, "sha1": "64838ca3"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 1035.975, "regress": 3831.45, "sha1": "71d75918"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd1080.ogv": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 229, "regress": 363, "sha1": "0d3c00c5"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1915.675, "regress": 2227.05, "sha1": "a578c1cc"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 102, "regress": 388, "sha1": "f3e2b55d"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 83, "regress": 164, "sha1": "b84761cd"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_crowd360.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 242.725, "regress": 322.35, "sha1": "2cbd54ec"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 46.0750000001, "regress": 64.575, "sha1": "0683489b"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 70.7749999999, "regress": 80.8499999998, "sha1": "34e97fe3"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999995, "regress": 3.67500000003, "sha1": "20d8eaab"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Cable_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 34.6750000002, "regress": 56.1750000004, "sha1": "2166dab9"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 990.375, "regress": 4422.075, "sha1": "37c2b19c"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 89.7749999999, "regress": 124.425, "sha1": "a892bf81"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1824.0, "regress": 2061.675, "sha1": "1801f8f4"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 181.925, "regress": 332.85, "sha1": "72f0bf1a"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 13.775, "regress": 20.4750000001, "sha1": "37833dc3"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_crowd360.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 250.800000001, "regress": 302.925, "sha1": "7a2cdf67"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2.84999999993, "regress": 9.97500000013, "sha1": "bd48d8f3"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 13.775, "regress": 18.3749999999, "sha1": "a8188299"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999995, "regress": 5.77499999975, "sha1": "73934a1f"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_NoConstraints_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 8.07499999991, "regress": 17.3250000002, "sha1": "f32bd82c"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 1243, "regress": 1543, "sha1": "7271fdbd"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 341.05, "regress": 467.775, "sha1": "894277f8"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1947.975, "regress": 2494.8, "sha1": "6134e0ff"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 166.25, "regress": 221.025, "sha1": "3ac33bd7"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 110, "regress": 238, "sha1": "4bb91772"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_crowd360.webm": {"reva": 176330, "revb": 176978, "type": "absolute", "better": "lower", "improve": 247, "regress": 861, "sha1": "5b620b60"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 132.525, "regress": 165.9, "sha1": "c8740151"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 102, "regress": 147, "sha1": "0f02cf28"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999952, "regress": 3.6749999998, "sha1": "f065e3b4"},
+ "win-release/media_tests_av_perf/seek/CACHED_LONG_SEEK_Wifi_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 124, "regress": 208, "sha1": "25aa47d7"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 992.275, "regress": 2727.375, "sha1": "c6ef891a"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 161.975, "regress": 210.0, "sha1": "0e43f9ea"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 522.025, "regress": 611.625, "sha1": "4b7220a6"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 108.775, "regress": 354.9, "sha1": "df9e12e0"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 64.6, "regress": 171.675, "sha1": "3c04337d"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 75.0499999997, "regress": 90.3000000002, "sha1": "3e9f0b92"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 0.95000000019, "regress": 2.62500000005, "sha1": "3dbdab45"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 16.6249999999, "regress": 21.0, "sha1": "54e6eb80"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2.84999999972, "regress": 4.20000000014, "sha1": "723a57be"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Cable_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 0.949999999762, "regress": 2.09999999995, "sha1": "f77ca8e6"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 988.95, "regress": 1534.575, "sha1": "a9f6ca44"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd1080.ogv": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 92.6250000001, "regress": 147.0, "sha1": "f1e74363"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd1080.webm": {"reva": 192736, "revb": 192827, "type": "absolute", "better": "lower", "improve": 515.375, "regress": 587.474999999, "sha1": "519a35d5"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 163.875, "regress": 306.6, "sha1": "8e903acf"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 28.9749999998, "regress": 38.3250000002, "sha1": "8b71499d"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 74.1, "regress": 88.7249999999, "sha1": "6998b66f"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.42500000008, "regress": 4.20000000014, "sha1": "6c71ec76"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 16.6249999999, "regress": 19.9500000002, "sha1": "02eaff5c"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2.84999999972, "regress": 4.72500000024, "sha1": "ed31c86c"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_NoConstraints_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 0.949999999762, "regress": 2.09999999995, "sha1": "36a540ac"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd1080.mp4": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 959, "regress": 2795, "sha1": "b688a8ff"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 217.075, "regress": 340.2, "sha1": "e25ef1c5"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 520.6, "regress": 637.875, "sha1": "23555ce1"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 165, "regress": 192, "sha1": "5f260df8"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 61.275, "regress": 288.225, "sha1": "540c7265"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 73.6250000001, "regress": 94.4999999999, "sha1": "2274cff8"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 0.95000000019, "regress": 3.15000000017, "sha1": "146a1f7e"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 16.1499999998, "regress": 19.9500000002, "sha1": "bfcb6434"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2.84999999972, "regress": 5.25000000012, "sha1": "c7da5205"},
+ "win-release/media_tests_av_perf/seek/CACHED_SHORT_SEEK_Wifi_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 0.949999999762, "regress": 2.09999999995, "sha1": "aa019189"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 988.475, "regress": 4055.1, "sha1": "59c7c070"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd1080.ogv": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 111.625, "regress": 1031.1, "sha1": "58cb57ff"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 537.7, "regress": 686.175, "sha1": "a3beb08c"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 128, "regress": 236, "sha1": "1cb502bf"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 24.225, "regress": 40.9499999998, "sha1": "9ab25ba3"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_crowd360.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 85.025, "regress": 148.575, "sha1": "fe23cc2e"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 8.07500000013, "regress": 122.85, "sha1": "e759315a"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 11.3999999997, "regress": 22.5749999998, "sha1": "426a80d8"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999952, "regress": 3.15000000017, "sha1": "3f74f535"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Cable_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 9.0249999999, "regress": 49.35, "sha1": "3f111c85"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 986, "regress": 3071, "sha1": "afd9187e"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 89.7749999999, "regress": 133.875, "sha1": "8c4dc27c"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 526.775, "regress": 620.55, "sha1": "78cc6fd1"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 180.975, "regress": 361.725, "sha1": "6f3449c3"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 24.6999999998, "regress": 33.5999999999, "sha1": "260cc5e2"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 80.75, "regress": 97.6499999998, "sha1": "a20a731d"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 6.64999999984, "regress": 11.55, "sha1": "354c30de"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 12.3499999999, "regress": 17.8499999998, "sha1": "1c6dc132"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999952, "regress": 5.25000000012, "sha1": "c48218df"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_NoConstraints_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 5.70000000009, "regress": 58.2749999999, "sha1": "7f790fe6"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 2540.775, "regress": 5914.65, "sha1": "c8e85477"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 723, "regress": 1036, "sha1": "1271637c"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 548, "regress": 721, "sha1": "9ab1200a"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 175.75, "regress": 725.025, "sha1": "5bae2dd0"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 23.7500000001, "regress": 89.2500000003, "sha1": "167e9cfa"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 82.6499999998, "regress": 108.675, "sha1": "ae1a07dd"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 9.0249999999, "regress": 44.1000000001, "sha1": "fd4e2f19"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 10.9250000001, "regress": 20.4750000001, "sha1": "34ad18fe"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999995, "regress": 3.15000000016, "sha1": "63a39f02"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_BUFFERED_SEEK_Wifi_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 9.0249999999, "regress": 190.05, "sha1": "a400265c"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd1080.mp4": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 3859, "regress": 4414, "sha1": "8bc4297e"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2590.175, "regress": 3017.175, "sha1": "c045c543"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 10605.325, "regress": 11805.675, "sha1": "116e794b"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd360.mp4": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 3268.475, "regress": 3664.5, "sha1": "602144d0"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 440, "regress": 528, "sha1": "6b022638"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 3100.8, "regress": 3512.775, "sha1": "fe1e9209"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 152, "regress": 203, "sha1": "c932d808"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 168, "regress": 217, "sha1": "967795ce"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999995, "regress": 3.15000000017, "sha1": "647bc1d3"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Cable_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 266, "regress": 364, "sha1": "f84a0ccd"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 984, "regress": 4370, "sha1": "7dcb4cb8"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd1080.ogv": {"reva": 168480, "revb": 168878, "type": "absolute", "better": "lower", "improve": 94.0499999999, "regress": 197.925, "sha1": "ba166aa1"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1829.225, "regress": 2067.975, "sha1": "bd503bea"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 183.824999999, "regress": 478.800000001, "sha1": "d0cd14e7"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd360.ogv": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 14.2499999999, "regress": 21.5250000001, "sha1": "3715b707"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_crowd360.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 248.425, "regress": 302.4, "sha1": "c69490da"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2.84999999972, "regress": 6.82499999996, "sha1": "82c9be52"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 202427, "revb": 202617, "type": "absolute", "better": "lower", "improve": 54.1499999998, "regress": 205.275, "sha1": "17a78f1a"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999995, "regress": 5.24999999987, "sha1": "4733f175"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_NoConstraints_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 8.55000000001, "regress": 81.3749999999, "sha1": "2846065b"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd1080.mp4": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 14924, "regress": 18891, "sha1": "92f739fb"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 10970.125, "regress": 12768.525, "sha1": "edca7ec4"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 45104.575, "regress": 50352.225, "sha1": "31446ba5"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd360.mp4": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 16283.95, "regress": 18484.725, "sha1": "08783414"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1564.175, "regress": 1879.5, "sha1": "e1b05253"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 15053, "regress": 17054, "sha1": "29bb2c15"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 450.3, "regress": 604.275, "sha1": "fd6e694f"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 537, "regress": 722, "sha1": "9e27576f"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.89999999995, "regress": 3.15000000017, "sha1": "df546514"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_LONG_SEEK_Wifi_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1050.7, "regress": 1339.275, "sha1": "cba8ed1d"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd1080.mp4": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 1121.475, "regress": 2220.225, "sha1": "5bec823f"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1979.8, "regress": 2276.925, "sha1": "defc5761"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd1080.webm": {"reva": 196258, "revb": 196740, "type": "absolute", "better": "lower", "improve": 2307.075, "regress": 2629.725, "sha1": "c6d9b8c2"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 147.725, "regress": 956.025, "sha1": "eb923423"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 942.875, "regress": 1128.225, "sha1": "b9adf05a"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 436.525, "regress": 558.075, "sha1": "16170b59"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 65.0749999999, "regress": 145.425, "sha1": "c0565fd1"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 16.6249999999, "regress": 20.4749999999, "sha1": "7252b8b4"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2.84999999972, "regress": 4.20000000014, "sha1": "baec9b15"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Cable_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 0.949999999762, "regress": 2.10000000043, "sha1": "7932611f"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 1008.425, "regress": 3901.275, "sha1": "aefee0ea"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd1080.ogv": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 89.3000000001, "regress": 308.7, "sha1": "5af6cddf"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd1080.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 542.45, "regress": 633.675, "sha1": "f1ad0018"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 165.775, "regress": 380.625, "sha1": "f00f6ef9"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd360.ogv": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 29.4499999999, "regress": 49.3499999998, "sha1": "f4777947"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 73.6249999999, "regress": 86.0999999999, "sha1": "f695abcb"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1.42499999943, "regress": 4.72499999977, "sha1": "70a45aab"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 17.1, "regress": 22.0500000002, "sha1": "f2715a2d"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_dartmoor2.ogg": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 2.84999999993, "regress": 4.20000000014, "sha1": "31323da3"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_NoConstraints_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 0.949999999762, "regress": 2.62499999982, "sha1": "2302c57f"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 5431.15, "regress": 7732.725, "sha1": "eab4cd43"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd1080.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 8763.275, "regress": 10314.675, "sha1": "3029e8cd"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd1080.webm": {"reva": 176330, "revb": 176978, "type": "absolute", "better": "lower", "improve": 9566.5, "regress": 11275.425, "sha1": "ff6de875"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd360.mp4": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 785.175, "regress": 1954.575, "sha1": "556c0637"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd360.ogv": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 3405.275, "regress": 4163.775, "sha1": "bfad9243"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_crowd360.webm": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 1925.65, "regress": 2569.875, "sha1": "6d5eb099"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_dartmoor2.m4a": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 316.35, "regress": 595.875, "sha1": "a6d1864d"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_dartmoor2.mp3": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 16.1499999998, "regress": 22.5750000001, "sha1": "8092a2f3"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_dartmoor2.ogg": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 2.37499999962, "regress": 4.20000000014, "sha1": "bd439afb"},
+ "win-release/media_tests_av_perf/seek/UNCACHED_SHORT_SEEK_Wifi_dartmoor2.wav": {"reva": 167695, "revb": 168064, "type": "absolute", "better": "lower", "improve": 0.949999999977, "regress": 2.62499999958, "sha1": "d3c9383a"},
+ "win-release/media_tests_av_perf/ttp/Cable_crowd.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 363, "regress": 696, "sha1": "07305273"},
+ "win-release/media_tests_av_perf/ttp/Cable_crowd.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 1614.525, "regress": 4277.175, "sha1": "a3f37b04"},
+ "win-release/media_tests_av_perf/ttp/Cable_crowd1080.mp4": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 1070.175, "regress": 12909.75, "sha1": "2a595265"},
+ "win-release/media_tests_av_perf/ttp/Cable_crowd1080.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 1693.85, "regress": 9540.825, "sha1": "87e95bc3"},
+ "win-release/media_tests_av_perf/ttp/Cable_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 954, "regress": 1328, "sha1": "57896296"},
+ "win-release/media_tests_av_perf/ttp/Cable_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 484.975, "regress": 1063.65, "sha1": "278e7512"},
+ "win-release/media_tests_av_perf/ttp/Cable_crowd360.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 894, "regress": 2939, "sha1": "53d2eae8"},
+ "win-release/media_tests_av_perf/ttp/Cable_crowd360.webm": {"reva": 187207, "revb": 189345, "type": "absolute", "better": "lower", "improve": 406.125, "regress": 855.75, "sha1": "4a976db0"},
+ "win-release/media_tests_av_perf/ttp/Cable_dartmoor2.m4a": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 211.85, "regress": 6298.425, "sha1": "0a9a62f5"},
+ "win-release/media_tests_av_perf/ttp/Cable_dartmoor2.mp3": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 361.0, "regress": 758.625, "sha1": "bb1ac914"},
+ "win-release/media_tests_av_perf/ttp/Cable_dartmoor2.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 2608.7, "regress": 7326.375, "sha1": "102a0ab1"},
+ "win-release/media_tests_av_perf/ttp/Cable_dartmoor2.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 1520, "regress": 2655, "sha1": "f0c1beb0"},
+ "win-release/media_tests_av_perf/ttp/Cable_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 326.325, "regress": 411.075, "sha1": "c20440c8"},
+ "win-release/media_tests_av_perf/ttp/DSL_crowd.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 839.325, "regress": 1122.975, "sha1": "519bcf41"},
+ "win-release/media_tests_av_perf/ttp/DSL_crowd.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 4932.4, "regress": 6609.225, "sha1": "f5713ad0"},
+ "win-release/media_tests_av_perf/ttp/DSL_crowd1080.mp4": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 2932, "regress": 6752, "sha1": "55abdb06"},
+ "win-release/media_tests_av_perf/ttp/DSL_crowd1080.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 4233.2, "regress": 13205.325, "sha1": "d951684c"},
+ "win-release/media_tests_av_perf/ttp/DSL_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 2577.825, "regress": 3105.375, "sha1": "9e6132c4"},
+ "win-release/media_tests_av_perf/ttp/DSL_crowd360.mp4": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 846.45, "regress": 11442.375, "sha1": "d2e6dbaa"},
+ "win-release/media_tests_av_perf/ttp/DSL_crowd360.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 1677.225, "regress": 4562.775, "sha1": "c948a2ca"},
+ "win-release/media_tests_av_perf/ttp/DSL_crowd360.webm": {"reva": 176330, "revb": 176978, "type": "absolute", "better": "lower", "improve": 928.15, "regress": 1230.075, "sha1": "766feb14"},
+ "win-release/media_tests_av_perf/ttp/DSL_dartmoor2.m4a": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 337.725, "regress": 1289.4, "sha1": "f274d60b"},
+ "win-release/media_tests_av_perf/ttp/DSL_dartmoor2.mp3": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 790, "regress": 1148, "sha1": "f7123a9d"},
+ "win-release/media_tests_av_perf/ttp/DSL_dartmoor2.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 8297.775, "regress": 10055.325, "sha1": "0cbd262e"},
+ "win-release/media_tests_av_perf/ttp/DSL_dartmoor2.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 4614.15, "regress": 13385.925, "sha1": "1de28732"},
+ "win-release/media_tests_av_perf/ttp/DSL_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 658, "regress": 878, "sha1": "2bfa82be"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_crowd.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 5.7, "regress": 89.775, "sha1": "bb2e770f"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_crowd.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 14.725, "regress": 495.075, "sha1": "04387b36"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_crowd1080.mp4": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 133.0, "regress": 15728.475, "sha1": "a2d4f8e0"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_crowd1080.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 65, "regress": 1608, "sha1": "36cdf01e"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_crowd1080.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 79.325, "regress": 12255.6, "sha1": "f29dc48f"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_crowd360.mp4": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 36.575, "regress": 672.0, "sha1": "1c0f809c"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_crowd360.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 33, "regress": 971, "sha1": "adf16fef"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_crowd360.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 28.5, "regress": 581.175, "sha1": "032fe754"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_dartmoor2.m4a": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 12, "regress": 642, "sha1": "df4b6183"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_dartmoor2.mp3": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 13.775, "regress": 201.6, "sha1": "947ce545"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_dartmoor2.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 10.925, "regress": 614.775, "sha1": "48300210"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_dartmoor2.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 16.15, "regress": 11969.475, "sha1": "88796c89"},
+ "win-release/media_tests_av_perf/ttp/NoConstraints_roller.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 23, "regress": 205, "sha1": "f3b2028a"},
+ "win-release/media_tests_av_perf/ttp/Slow_crowd.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 4084.525, "regress": 9875.25, "sha1": "a535e349"},
+ "win-release/media_tests_av_perf/ttp/Slow_crowd.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 91.2, "regress": 37941.225, "sha1": "df270d9c"},
+ "win-release/media_tests_av_perf/ttp/Slow_crowd1080.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 27132, "regress": 31624, "sha1": "d18f40ec"},
+ "win-release/media_tests_av_perf/ttp/Slow_crowd1080.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 22291, "regress": 37267, "sha1": "959c8eac"},
+ "win-release/media_tests_av_perf/ttp/Slow_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 14088.975, "regress": 16688.175, "sha1": "f8cc597f"},
+ "win-release/media_tests_av_perf/ttp/Slow_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 5562.25, "regress": 7911.225, "sha1": "be2b87e8"},
+ "win-release/media_tests_av_perf/ttp/Slow_crowd360.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 665, "regress": 23760, "sha1": "567a5244"},
+ "win-release/media_tests_av_perf/ttp/Slow_crowd360.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 4422, "regress": 6209, "sha1": "64809884"},
+ "win-release/media_tests_av_perf/ttp/Slow_dartmoor2.m4a": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 917, "regress": 4424, "sha1": "1a0e4d92"},
+ "win-release/media_tests_av_perf/ttp/Slow_dartmoor2.mp3": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 3694, "regress": 8049, "sha1": "de449588"},
+ "win-release/media_tests_av_perf/ttp/Slow_dartmoor2.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 48983.425, "regress": 64855.875, "sha1": "e402ba9d"},
+ "win-release/media_tests_av_perf/ttp/Slow_dartmoor2.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 26881.675, "regress": 35213.325, "sha1": "9522ef51"},
+ "win-release/media_tests_av_perf/ttp/Slow_roller.webm": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 128.725, "regress": 9402.225, "sha1": "d72f2814"},
+ "win-release/media_tests_av_perf/ttp/Wifi_crowd.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 1173.25, "regress": 1527.225, "sha1": "646ca635"},
+ "win-release/media_tests_av_perf/ttp/Wifi_crowd.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 7324.025, "regress": 11648.7, "sha1": "d5e6bc72"},
+ "win-release/media_tests_av_perf/ttp/Wifi_crowd1080.mp4": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 4302.55, "regress": 10155.075, "sha1": "78437027"},
+ "win-release/media_tests_av_perf/ttp/Wifi_crowd1080.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 6035.825, "regress": 17470.95, "sha1": "f79dfaf4"},
+ "win-release/media_tests_av_perf/ttp/Wifi_crowd1080.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 3747.275, "regress": 4439.4, "sha1": "4c19af6c"},
+ "win-release/media_tests_av_perf/ttp/Wifi_crowd360.mp4": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 1593.625, "regress": 2439.675, "sha1": "51eff7c8"},
+ "win-release/media_tests_av_perf/ttp/Wifi_crowd360.ogv": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 2213.5, "regress": 3969.525, "sha1": "cc4faaaf"},
+ "win-release/media_tests_av_perf/ttp/Wifi_crowd360.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 1288.2, "regress": 1890.525, "sha1": "e5a42c2a"},
+ "win-release/media_tests_av_perf/ttp/Wifi_dartmoor2.m4a": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 394.725, "regress": 1214.325, "sha1": "5154b154"},
+ "win-release/media_tests_av_perf/ttp/Wifi_dartmoor2.mp3": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 1092.5, "regress": 1590.225, "sha1": "a100181a"},
+ "win-release/media_tests_av_perf/ttp/Wifi_dartmoor2.ogg": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 12396.55, "regress": 14062.125, "sha1": "9ca7f6b1"},
+ "win-release/media_tests_av_perf/ttp/Wifi_dartmoor2.wav": {"reva": 17420, "revb": 174996, "type": "absolute", "better": "lower", "improve": 6859.95, "regress": 24904.425, "sha1": "0e5625a5"},
+ "win-release/media_tests_av_perf/ttp/Wifi_roller.webm": {"reva": 175328, "revb": 176157, "type": "absolute", "better": "lower", "improve": 906.775, "regress": 1184.925, "sha1": "d49e638f"},
+ "xp-release/sizes/chrome.dll/chrome.dll": {"reva": 203454, "revb": 203508, "type": "absolute", "better": "lower", "improve": 55459814, "regress": 61312205, "sha1": "b01d47d9"},
+ "xp-release/sizes/chrome.exe/chrome.exe": {"reva": 183841, "revb": 184954, "type": "absolute", "better": "lower", "improve": 720358, "regress": 796186, "sha1": "b5aa4523"},
+ "xp-release/sizes/mini_installer.exe/mini_installer.exe": {"reva": 212973, "revb": 213132, "type": "absolute", "better": "lower", "improve": 28051174, "regress": 31094247, "sha1": "303dac45"},
+ "xp-release/sizes/npchrome_frame.dll/npchrome_frame.dll": {"reva": 213618, "revb": 213647, "type": "absolute", "better": "lower", "improve": 2320128, "regress": 2567040, "sha1": "a9618db1"},
+ "xp-release/sizes/setup.exe/setup.exe": {"reva": 183841, "revb": 184954, "type": "absolute", "better": "lower", "improve": 1080780, "regress": 1195085, "sha1": "c56e884e"},
+ "load": true
+}
diff --git a/chromium/tools/perf_expectations/sample_test_cases.json b/chromium/tools/perf_expectations/sample_test_cases.json
new file mode 100644
index 00000000000..0fb746290c1
--- /dev/null
+++ b/chromium/tools/perf_expectations/sample_test_cases.json
@@ -0,0 +1,28 @@
+{"linux-release/media_tests_av_perf/audio_latency/latency": {"reva": 180005, "revb": 180520, "type": "absolute", "better": "lower", "improve": 190, "regress": 222, "sha1": "fc9815d5"},
+"linux-release/media_tests_av_perf/dropped_fps/tulip2.wav": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "fb8157f9"},
+"linux-release/media_tests_av_perf/dropped_fps/tulip2.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "c0fb3421"},
+"linux-release/media_tests_av_perf/dropped_frames/crowd1080.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "fa9582d3"},
+"linux-release/media_tests_av_perf/dropped_frames/crowd2160.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 166, "regress": 231, "sha1": "ca3a7a47"},
+"linux-release/media_tests_av_perf/fps/tulip2.m4a": {"reva": 34239, "revb": 1298213, "type": "absolute", "better": "higher", "improve": 0, "regress": 0},
+"linux-release/media_tests_av_perf/fps/tulip2.mp3": {"reva": 34239, "revb": 1298213, "type": "absolute", "better": "higher", "improve": 0, "regress": 0},
+"linux-release/media_tests_av_perf/fps/tulip2.mp4": {"reva": 34239, "revb": 1298213, "type": "absolute", "better": "higher", "improve": 32, "regress": 28},
+"linux-release/media_tests_av_perf/fps/tulip2.ogg": {"reva": 34239, "revb": 1298213, "type": "absolute", "better": "higher", "improve": 0, "regress": 0},
+"linux-release/media_tests_av_perf/fps/tulip2.ogv": {"reva": 34239, "revb": 1298213, "type": "absolute", "better": "higher", "improve": 32, "regress": 28},
+"linux-release/media_tests_av_perf/fps/tulip2.wav": {"reva": 34239, "revb": 1298213, "type": "absolute", "better": "higher", "improve": 0, "regress": 0},
+"win-release/media_tests_av_perf/dropped_fps/tulip2.wav": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "646c02f2"},
+"win-release/media_tests_av_perf/dropped_fps/tulip2.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "46c97b57"},
+"win-release/media_tests_av_perf/dropped_frames/crowd1080.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "sha1": "9b709aab"},
+"win-release/media_tests_av_perf/dropped_frames/crowd2160.webm": {"reva": 181131, "revb": 181572, "type": "absolute", "better": "lower", "improve": 174, "regress": 204, "sha1": "4c0270a6"},
+"win-release/media_tests_av_perf/fps/crowd1080.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 53, "regress": 43, "sha1": "7ad49461"},
+"win-release/media_tests_av_perf/fps/crowd2160.webm": {"reva": 176330, "revb": 176978, "type": "absolute", "better": "higher", "improve": 26.0399945997, "regress": 25.9062437562, "sha1": "700526a9"},
+"win-release/media_tests_av_perf/fps/crowd360.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 51, "regress": 47, "sha1": "7f8ef21c"},
+"win-release/media_tests_av_perf/fps/crowd480.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 50, "regress": 47, "sha1": "5dc96881"},
+"win-release/media_tests_av_perf/fps/crowd720.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 52, "regress": 47, "sha1": "4fcfb653"},
+"win-release/media_tests_av_perf/fps/tulip2.m4a": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "54d94538"},
+"win-release/media_tests_av_perf/fps/tulip2.mp3": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "113aef17"},
+"win-release/media_tests_av_perf/fps/tulip2.mp4": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 30, "regress": 28, "sha1": "a22847d0"},
+"win-release/media_tests_av_perf/fps/tulip2.ogg": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "6ee2e716"},
+"win-release/media_tests_av_perf/fps/tulip2.ogv": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 32, "regress": 26, "sha1": "dfadb872"},
+"win-release/media_tests_av_perf/fps/tulip2.wav": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 0, "regress": 0, "sha1": "530c5bf5"},
+"win-release/media_tests_av_perf/fps/tulip2.webm": {"reva": 163299, "revb": 164141, "type": "absolute", "better": "higher", "improve": 30, "regress": 28, "sha1": "35b91c8e"}
+} \ No newline at end of file
diff --git a/chromium/tools/perf_expectations/update_perf_expectations.py b/chromium/tools/perf_expectations/update_perf_expectations.py
new file mode 100755
index 00000000000..d1ce9831ed1
--- /dev/null
+++ b/chromium/tools/perf_expectations/update_perf_expectations.py
@@ -0,0 +1,263 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Prepare tests that require re-baselining for input to make_expectations.py.
+
+The regularly running perf-AV tests require re-baselineing of expectations
+about once a week. The steps involved in rebaselining are:
+
+1.) Identify the tests to update, based off reported e-mail results.
+2.) Figure out reva and revb values, which is the starting and ending revision
+ numbers for the range that we should use to obtain new thresholds.
+3.) Modify lines in perf_expectations.json referring to the tests to be updated,
+ so that they may be used as input to make_expectations.py.
+
+This script automates the last step above.
+
+Here's a sample line from perf_expectations.json:
+
+"win-release/media_tests_av_perf/fps/tulip2.m4a": {"reva": 163299, \
+"revb": 164141, "type": "absolute", "better": "higher", "improve": 0, \
+"regress": 0, "sha1": "54d94538"},
+
+To get the above test ready for input to make_expectations.py, it should become:
+
+"win-release/media_tests_av_perf/fps/tulip2.m4a": {"reva": <new reva>, \
+"revb": <new revb>, "type": "absolute", "better": "higher", "improve": 0, \
+"regress": 0},
+
+Examples:
+
+1.) To update the test specified above and get baseline
+values using the revision range 12345 and 23456, run this script with a command
+line like this:
+ python update_perf_expectations.py -f \
+ win-release/media_tests_av_perf/fps/tulip2.m4a --reva 12345 --revb 23456
+Or, using an input file,
+where the input file contains a single line with text
+ win-release/media_tests_av_perf/fps/tulip2.m4a
+run with this command line:
+ python update_perf_expectations.py -i input.txt --reva 12345 --revb 23456
+
+2.) Let's say you want to update all seek tests on windows, and get baseline
+values using the revision range 12345 and 23456.
+Run this script with this command line:
+ python update_perf_expectations.py -f win-release/media_tests_av_perf/seek/ \
+ --reva 12345 --revb 23456
+Or:
+ python update_perf_expectations.py -f win-release/.*/seek/ --reva 12345 \
+ --revb 23456
+
+Or, using an input file,
+where the input file contains a single line with text win-release/.*/seek/:
+ python update_perf_expectations.py -i input.txt --reva 12345 --revb 23456
+
+3.) Similarly, if you want to update seek tests on all platforms
+ python update_perf_expectations.py -f .*-release/.*/seek/ --reva 12345 \
+ --revb 23456
+
+"""
+
+import logging
+from optparse import OptionParser
+import os
+import re
+
+import make_expectations as perf_ex_lib
+
+# Default logging is INFO. Use --verbose to enable DEBUG logging.
+_DEFAULT_LOG_LEVEL = logging.INFO
+
+
+def GetTestsToUpdate(contents, all_test_keys):
+ """Parses input contents and obtains tests to be re-baselined.
+
+ Args:
+ contents: string containing contents of input file.
+ all_test_keys: list of keys of test dictionary.
+ Returns:
+ A list of keys for tests that should be updated.
+ """
+ # Each line of the input file specifies a test case to update.
+ tests_list = []
+ for test_case_filter in contents.splitlines():
+ # Skip any empty lines.
+ if test_case_filter:
+ # Sample expected line:
+ # win-release/media_tests_av_perf/seek/\
+ # CACHED_BUFFERED_SEEK_NoConstraints_crowd1080.ogv
+ # Or, if reg-ex, then sample line:
+ # win-release/media-tests_av_perf/seek*
+ # Skip any leading spaces if they exist in the input file.
+ logging.debug('Trying to match %s', test_case_filter)
+ tests_list.extend(GetMatchingTests(test_case_filter.strip(),
+ all_test_keys))
+ return tests_list
+
+
+def GetMatchingTests(tests_to_update, all_test_keys):
+ """Parses input reg-ex filter and obtains tests to be re-baselined.
+
+ Args:
+ tests_to_update: reg-ex string specifying tests to be updated.
+ all_test_keys: list of keys of tests dictionary.
+ Returns:
+ A list of keys for tests that should be updated.
+ """
+ tests_list = []
+ search_string = re.compile(tests_to_update)
+ # Get matching tests from the dictionary of tests
+ for test_key in all_test_keys:
+ if search_string.match(test_key):
+ tests_list.append(test_key)
+ logging.debug('%s will be updated', test_key)
+ logging.info('%s tests found matching reg-ex: %s', len(tests_list),
+ tests_to_update)
+ return tests_list
+
+
+def PrepareTestsForUpdate(tests_to_update, all_tests, reva, revb):
+ """Modifies value of tests that are to re-baselined:
+ Set reva and revb values to specified new values. Remove sha1.
+
+ Args:
+ tests_to_update: list of tests to be updated.
+ all_tests: dictionary of all tests.
+ reva: oldest revision in range to use for new values.
+ revb: newest revision in range to use for new values.
+ Raises:
+ ValueError: If reva or revb are not valid ints, or if either
+ of them are negative.
+ """
+ reva = int(reva)
+ revb = int(revb)
+
+ if reva < 0 or revb < 0:
+ raise ValueError('Revision values should be positive.')
+ # Ensure reva is less than revb.
+ # (this is similar to the check done in make_expectations.py)
+ if revb < reva:
+ temp = revb
+ revb = reva
+ reva = temp
+ for test_key in tests_to_update:
+ # Get original test from the dictionary of tests
+ test_value = all_tests[test_key]
+ if test_value:
+ # Sample line in perf_expectations.json:
+ # "linux-release/media_tests _av_perf/dropped_frames/crowd360.webm":\
+ # {"reva": 155180, "revb": 155280, "type": "absolute", \
+ # "better": "lower", "improve": 0, "regress": 3, "sha1": "276ba29c"},
+ # Set new revision range
+ test_value['reva'] = reva
+ test_value['revb'] = revb
+ # Remove sha1 to indicate this test requires an update
+ # Check first to make sure it exist.
+ if 'sha1' in test_value:
+ del test_value['sha1']
+ else:
+ logging.warning('%s does not exist.', test_key)
+ logging.info('Done preparing tests for update.')
+
+
+def GetCommandLineOptions():
+ """Parse command line arguments.
+
+ Returns:
+ An options object containing command line arguments and their values.
+ """
+ parser = OptionParser()
+
+ parser.add_option('--reva', dest='reva', type='int',
+ help='Starting revision of new range.',
+ metavar='START_REVISION')
+ parser.add_option('--revb', dest='revb', type='int',
+ help='Ending revision of new range.',
+ metavar='END_REVISION')
+ parser.add_option('-f', dest='tests_filter',
+ help='Regex to use for filtering tests to be updated. '
+ 'At least one of -filter or -input_file must be provided. '
+ 'If both are provided, then input-file is used.',
+ metavar='FILTER', default='')
+ parser.add_option('-i', dest='input_file',
+ help='Optional path to file with reg-exes for tests to'
+ ' update. If provided, it overrides the filter argument.',
+ metavar='INPUT_FILE', default='')
+ parser.add_option('--config', dest='config_file',
+ default=perf_ex_lib.DEFAULT_CONFIG_FILE,
+ help='Set the config file to FILE.', metavar='FILE')
+ parser.add_option('-v', dest='verbose', action='store_true', default=False,
+ help='Enable verbose output.')
+ options = parser.parse_args()[0]
+ return options
+
+
+def Main():
+ """Main driver function."""
+ options = GetCommandLineOptions()
+
+ _SetLogger(options.verbose)
+ # Do some command-line validation
+ if not options.input_file and not options.tests_filter:
+ logging.error('At least one of input-file or test-filter must be provided.')
+ exit(1)
+ if options.input_file and options.tests_filter:
+ logging.error('Specify only one of input file or test-filter.')
+ exit(1)
+ if not options.reva or not options.revb:
+ logging.error('Start and end revision of range must be specified.')
+ exit(1)
+
+ # Load config.
+ config = perf_ex_lib.ConvertJsonIntoDict(
+ perf_ex_lib.ReadFile(options.config_file))
+
+ # Obtain the perf expectations file from the config file.
+ perf_file = os.path.join(
+ os.path.dirname(options.config_file), config['perf_file'])
+
+ # We should have all the information we require now.
+ # On to the real thang.
+ # First, get all the existing tests from the original perf_expectations file.
+ all_tests = perf_ex_lib.ConvertJsonIntoDict(
+ perf_ex_lib.ReadFile(perf_file))
+ all_test_keys = all_tests.keys()
+ # Remove the load key, because we don't want to modify it.
+ all_test_keys.remove('load')
+ # Keep tests sorted, like in the original file.
+ all_test_keys.sort()
+
+ # Next, get all tests that have been identified for an update.
+ tests_to_update = []
+ if options.input_file:
+ # Tests to update have been specified in an input_file.
+ # Get contents of file.
+ tests_filter = perf_ex_lib.ReadFile(options.input_file)
+ elif options.tests_filter:
+ # Tests to update have been specified as a reg-ex filter.
+ tests_filter = options.tests_filter
+
+ # Get tests to update based on filter specified.
+ tests_to_update = GetTestsToUpdate(tests_filter, all_test_keys)
+ logging.info('Done obtaining matching tests.')
+
+ # Now, prepare tests for update.
+ PrepareTestsForUpdate(tests_to_update, all_tests, options.reva, options.revb)
+
+ # Finally, write modified tests back to perf_expectations file.
+ perf_ex_lib.WriteJson(perf_file, all_tests, all_test_keys,
+ calculate_sha1=False)
+ logging.info('Done writing tests for update to %s.', perf_file)
+
+
+def _SetLogger(verbose):
+ log_level = _DEFAULT_LOG_LEVEL
+ if verbose:
+ log_level = logging.DEBUG
+ logging.basicConfig(level=log_level, format='%(message)s')
+
+
+if __name__ == '__main__':
+ Main()
diff --git a/chromium/tools/perf_expectations/update_perf_expectations_unittest.py b/chromium/tools/perf_expectations/update_perf_expectations_unittest.py
new file mode 100755
index 00000000000..9e54b89d25c
--- /dev/null
+++ b/chromium/tools/perf_expectations/update_perf_expectations_unittest.py
@@ -0,0 +1,204 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Unit tests for update_perf_expectations."""
+import copy
+from StringIO import StringIO
+import unittest
+import make_expectations as perf_ex_lib
+import update_perf_expectations as upe_mod
+
+
+# A separate .json file contains the list of test cases we'll use.
+# The tests used to be defined inline here, but are >80 characters in length.
+# Now they are expected to be defined in file ./sample_test_cases.json.
+# Create a dictionary of tests using .json file.
+all_tests = perf_ex_lib.ConvertJsonIntoDict(
+ perf_ex_lib.ReadFile('sample_test_cases.json'))
+# Get all keys.
+all_tests_keys = all_tests.keys()
+
+
+def VerifyPreparedTests(self, tests_to_update, reva, revb):
+ # Work with a copy of the set of tests.
+ all_tests_copy = copy.deepcopy(all_tests)
+ upe_mod.PrepareTestsForUpdate(tests_to_update, all_tests_copy, reva, revb)
+ # Make sure reva < revb
+ if reva > revb:
+ temp = reva
+ reva = revb
+ revb = temp
+ # Run through all tests and make sure only those that were
+ # specified to be modified had their 'sha1' value removed.
+ for test_key in all_tests_keys:
+ new_test_value = all_tests_copy[test_key]
+ original_test_value = all_tests[test_key]
+ if test_key in tests_to_update:
+ # Make sure there is no "sha1".
+ self.assertFalse('sha1' in new_test_value)
+ # Make sure reva and revb values are correctly set.
+ self.assertEqual(reva, new_test_value['reva'])
+ self.assertEqual(revb, new_test_value['revb'])
+ else:
+ # Make sure there is an "sha1" value
+ self.assertTrue('sha1' in new_test_value)
+ # Make sure the sha1, reva and revb values have not changed.
+ self.assertEqual(original_test_value['sha1'], new_test_value['sha1'])
+ self.assertEqual(original_test_value['reva'], new_test_value['reva'])
+ self.assertEqual(original_test_value['revb'], new_test_value['revb'])
+
+
+class UpdatePerfExpectationsTest(unittest.TestCase):
+ def testFilterMatch(self):
+ """Verifies different regular expressions test filter."""
+ self.maxDiff = None
+ # Tests to update specified by a single literal string.
+ tests_to_update = 'win-release/media_tests_av_perf/fps/tulip2.webm'
+ expected_tests_list = ['win-release/media_tests_av_perf/fps/tulip2.webm']
+ self.assertEqual(expected_tests_list,
+ upe_mod.GetMatchingTests(tests_to_update,
+ all_tests_keys))
+
+ # Tests to update specified by a single reg-ex
+ tests_to_update = 'win-release/media_tests_av_perf/fps.*'
+ expected_tests_list = ['win-release/media_tests_av_perf/fps/crowd1080.webm',
+ 'win-release/media_tests_av_perf/fps/crowd2160.webm',
+ 'win-release/media_tests_av_perf/fps/crowd360.webm',
+ 'win-release/media_tests_av_perf/fps/crowd480.webm',
+ 'win-release/media_tests_av_perf/fps/crowd720.webm',
+ 'win-release/media_tests_av_perf/fps/tulip2.m4a',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp3',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp4',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogg',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogv',
+ 'win-release/media_tests_av_perf/fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/fps/tulip2.webm']
+ actual_list = upe_mod.GetMatchingTests(tests_to_update,
+ all_tests_keys)
+ actual_list.sort()
+ self.assertEqual(expected_tests_list, actual_list)
+
+ # Tests to update are specified by a single reg-ex, spanning multiple OSes.
+ tests_to_update = '.*-release/media_tests_av_perf/fps.*'
+ expected_tests_list = ['linux-release/media_tests_av_perf/fps/tulip2.m4a',
+ 'linux-release/media_tests_av_perf/fps/tulip2.mp3',
+ 'linux-release/media_tests_av_perf/fps/tulip2.mp4',
+ 'linux-release/media_tests_av_perf/fps/tulip2.ogg',
+ 'linux-release/media_tests_av_perf/fps/tulip2.ogv',
+ 'linux-release/media_tests_av_perf/fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/fps/crowd1080.webm',
+ 'win-release/media_tests_av_perf/fps/crowd2160.webm',
+ 'win-release/media_tests_av_perf/fps/crowd360.webm',
+ 'win-release/media_tests_av_perf/fps/crowd480.webm',
+ 'win-release/media_tests_av_perf/fps/crowd720.webm',
+ 'win-release/media_tests_av_perf/fps/tulip2.m4a',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp3',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp4',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogg',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogv',
+ 'win-release/media_tests_av_perf/fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/fps/tulip2.webm']
+ actual_list = upe_mod.GetMatchingTests(tests_to_update,
+ all_tests_keys)
+ actual_list.sort()
+ self.assertEqual(expected_tests_list, actual_list)
+
+ def testLinesFromInputFile(self):
+ """Verifies different string formats specified in input file."""
+
+ # Tests to update have been specified by a single literal string in
+ # an input file.
+ # Use the StringIO class to mock a file object.
+ lines_from_file = StringIO(
+ 'win-release/media_tests_av_perf/fps/tulip2.webm')
+ contents = lines_from_file.read()
+ expected_tests_list = ['win-release/media_tests_av_perf/fps/tulip2.webm']
+ actual_list = upe_mod.GetTestsToUpdate(contents, all_tests_keys)
+ actual_list.sort()
+ self.assertEqual(expected_tests_list, actual_list)
+ lines_from_file.close()
+
+ # Tests to update specified by a single reg-ex in an input file.
+ lines_from_file = StringIO('win-release/media_tests_av_perf/fps/tulip2.*\n')
+ contents = lines_from_file.read()
+ expected_tests_list = ['win-release/media_tests_av_perf/fps/tulip2.m4a',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp3',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp4',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogg',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogv',
+ 'win-release/media_tests_av_perf/fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/fps/tulip2.webm']
+ actual_list = upe_mod.GetTestsToUpdate(contents, all_tests_keys)
+ actual_list.sort()
+ self.assertEqual(expected_tests_list, actual_list)
+ lines_from_file.close()
+
+ # Tests to update specified by multiple lines in an input file.
+ lines_from_file = StringIO(
+ '.*-release/media_tests_av_perf/fps/tulip2.*\n'
+ 'win-release/media_tests_av_perf/dropped_fps/tulip2.*\n'
+ 'linux-release/media_tests_av_perf/audio_latency/latency')
+ contents = lines_from_file.read()
+ expected_tests_list = [
+ 'linux-release/media_tests_av_perf/audio_latency/latency',
+ 'linux-release/media_tests_av_perf/fps/tulip2.m4a',
+ 'linux-release/media_tests_av_perf/fps/tulip2.mp3',
+ 'linux-release/media_tests_av_perf/fps/tulip2.mp4',
+ 'linux-release/media_tests_av_perf/fps/tulip2.ogg',
+ 'linux-release/media_tests_av_perf/fps/tulip2.ogv',
+ 'linux-release/media_tests_av_perf/fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/dropped_fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/dropped_fps/tulip2.webm',
+ 'win-release/media_tests_av_perf/fps/tulip2.m4a',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp3',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp4',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogg',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogv',
+ 'win-release/media_tests_av_perf/fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/fps/tulip2.webm']
+ actual_list = upe_mod.GetTestsToUpdate(contents, all_tests_keys)
+ actual_list.sort()
+ self.assertEqual(expected_tests_list, actual_list)
+ lines_from_file.close()
+
+ def testPreparingForUpdate(self):
+ """Verifies that tests to be modified are changed as expected."""
+ tests_to_update = [
+ 'linux-release/media_tests_av_perf/audio_latency/latency',
+ 'linux-release/media_tests_av_perf/fps/tulip2.m4a',
+ 'linux-release/media_tests_av_perf/fps/tulip2.mp3',
+ 'linux-release/media_tests_av_perf/fps/tulip2.mp4',
+ 'linux-release/media_tests_av_perf/fps/tulip2.ogg',
+ 'linux-release/media_tests_av_perf/fps/tulip2.ogv',
+ 'linux-release/media_tests_av_perf/fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/dropped_fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/dropped_fps/tulip2.webm',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp3',
+ 'win-release/media_tests_av_perf/fps/tulip2.mp4',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogg',
+ 'win-release/media_tests_av_perf/fps/tulip2.ogv',
+ 'win-release/media_tests_av_perf/fps/tulip2.wav',
+ 'win-release/media_tests_av_perf/fps/tulip2.webm']
+ # Test regular positive integers.
+ reva = 12345
+ revb = 54321
+ VerifyPreparedTests(self, tests_to_update, reva, revb)
+ # Test negative values.
+ reva = -54321
+ revb = 12345
+ with self.assertRaises(ValueError):
+ upe_mod.PrepareTestsForUpdate(tests_to_update, all_tests, reva, revb)
+ # Test reva greater than revb.
+ reva = 54321
+ revb = 12345
+ upe_mod.PrepareTestsForUpdate(tests_to_update, all_tests, reva, revb)
+ # Test non-integer values
+ reva = 'sds'
+ revb = 12345
+ with self.assertRaises(ValueError):
+ upe_mod.PrepareTestsForUpdate(tests_to_update, all_tests, reva, revb)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/playback_benchmark/common.js b/chromium/tools/playback_benchmark/common.js
new file mode 100644
index 00000000000..69309aac06b
--- /dev/null
+++ b/chromium/tools/playback_benchmark/common.js
@@ -0,0 +1,320 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Classes and functions used during recording and playback.
+ */
+
+var Benchmark = Benchmark || {};
+
+Benchmark.functionList = [
+ ['setTimeout', 'setTimeout'],
+ ['clearTimeout', 'clearTimeout'],
+ ['setInterval', 'setInterval'],
+ ['clearInterval', 'clearInterval'],
+ ['XMLHttpRequest', 'XMLHttpRequest'],
+ ['addEventListenerToWindow', 'addEventListener'],
+ ['addEventListenerToNode', 'addEventListener', ['Node', 'prototype']],
+ ['removeEventListenerFromNode', 'removeEventListener', ['Node', 'prototype']],
+ ['addEventListenerToXHR', 'addEventListener',
+ ['XMLHttpRequest', 'prototype']],
+ ['random', 'random', ['Math']],
+ ['Date', 'Date'],
+ ['documentWriteln', 'writeln', ['document']],
+ ['documentWrite', 'write', ['document']]
+];
+
+Benchmark.timeoutMapping = [];
+
+Benchmark.ignoredListeners = ['mousemove', 'mouseover', 'mouseout'];
+
+Benchmark.originals = {};
+
+Benchmark.overrides = {
+ setTimeout: function(callback, timeout) {
+ var event = {type: 'timeout', timeout: timeout};
+ var eventId = Benchmark.agent.createAsyncEvent(event);
+ var timerId = Benchmark.originals.setTimeout.call(this, function() {
+ Benchmark.agent.fireAsyncEvent(eventId, callback);
+ }, Benchmark.playback ? 0 : timeout);
+ Benchmark.timeoutMapping[timerId] = eventId;
+ return timerId;
+ },
+
+ clearTimeout: function(timerId) {
+ var eventId = Benchmark.timeoutMapping[timerId];
+ if (eventId == undefined) return;
+ Benchmark.agent.cancelAsyncEvent(eventId);
+ Benchmark.originals.clearTimeout.call(this, timerId);
+ },
+
+ setInterval: function(callback, timeout) {
+ console.warn('setInterval');
+ },
+
+ clearInterval: function(timerId) {
+ console.warn('clearInterval');
+ },
+
+ XMLHttpRequest: function() {
+ return new Benchmark.XMLHttpRequestWrapper();
+ },
+
+ addEventListener: function(type, listener, useCapture, target, targetType,
+ originalFunction) {
+ var event = {type: 'addEventListener', target: targetType, eventType: type};
+ var eventId = Benchmark.agent.createAsyncEvent(event);
+ listener.eventId = eventId;
+ listener.wrapper = function(e) {
+ Benchmark.agent.fireAsyncEvent(eventId, function() {
+ listener.call(target, e);
+ });
+ };
+ originalFunction.call(target, type, listener.wrapper, useCapture);
+ },
+
+ addEventListenerToWindow: function(type, listener, useCapture) {
+ if (Benchmark.ignoredListeners.indexOf(type) != -1) return;
+ Benchmark.overrides.addEventListener(
+ type, listener, useCapture, this, 'window',
+ Benchmark.originals.addEventListenerToWindow);
+ },
+
+ addEventListenerToNode: function(type, listener, useCapture) {
+ if (Benchmark.ignoredListeners.indexOf(type) != -1) return;
+ Benchmark.overrides.addEventListener(
+ type, listener, useCapture, this, 'node',
+ Benchmark.originals.addEventListenerToNode);
+ },
+
+ addEventListenerToXHR: function(type, listener, useCapture) {
+ Benchmark.overrides.addEventListener(
+ type, listener, useCapture, this, 'xhr',
+ Benchmark.originals.addEventListenerToXHR);
+ },
+
+ removeEventListener: function(type, listener, useCapture, target,
+ originalFunction) {
+ Benchmark.agent.cancelAsyncEvent(listener.eventId);
+ originalFunction.call(target, listener.wrapper, useCapture);
+ },
+
+ removeEventListenerFromWindow: function(type, listener, useCapture) {
+ removeEventListener(type, listener, useCapture, this,
+ Benchmark.originals.removeEventListenerFromWindow);
+ },
+
+ removeEventListenerFromNode: function(type, listener, useCapture) {
+ removeEventListener(type, listener, useCapture, this,
+ Benchmark.originals.removeEventListenerFromNode);
+ },
+
+ removeEventListenerFromXHR: function(type, listener, useCapture) {
+ removeEventListener(type, listener, useCapture, this,
+ Benchmark.originals.removeEventListenerFromXHR);
+ },
+
+ random: function() {
+ return Benchmark.agent.random();
+ },
+
+ Date: function() {
+ var a = arguments;
+ var D = Benchmark.originals.Date, d;
+ switch(a.length) {
+ case 0: d = new D(Benchmark.agent.dateNow()); break;
+ case 1: d = new D(a[0]); break;
+ case 2: d = new D(a[0], a[1]); break;
+ case 3: d = new D(a[0], a[1], a[2]); break;
+ default: Benchmark.die('window.Date', arguments);
+ }
+ d.getTimezoneOffset = function() { return -240; };
+ return d;
+ },
+
+ dateNow: function() {
+ return Benchmark.agent.dateNow();
+ },
+
+ documentWriteln: function() {
+ console.warn('writeln');
+ },
+
+ documentWrite: function() {
+ console.warn('write');
+ }
+};
+
+/**
+ * Replaces window functions specified by Benchmark.functionList with overrides
+ * and optionally saves original functions to Benchmark.originals.
+ * @param {Object} wnd Window object.
+ * @param {boolean} storeOriginals When true, original functions are saved to
+ * Benchmark.originals.
+ */
+Benchmark.installOverrides = function(wnd, storeOriginals) {
+ // Substitute window functions with overrides.
+ for (var i = 0; i < Benchmark.functionList.length; ++i) {
+ var info = Benchmark.functionList[i], object = wnd;
+ var propertyName = info[1], pathToProperty = info[2];
+ if (pathToProperty)
+ for (var j = 0; j < pathToProperty.length; ++j)
+ object = object[pathToProperty[j]];
+ if (storeOriginals)
+ Benchmark.originals[info[0]] = object[propertyName];
+ object[propertyName] = Benchmark.overrides[info[0]];
+ }
+ wnd.__defineSetter__('onload', function() {
+ console.warn('window.onload setter')}
+ );
+
+ // Substitute window functions of static frames when DOM content is loaded.
+ Benchmark.originals.addEventListenerToWindow.call(wnd, 'DOMContentLoaded',
+ function() {
+ var frames = document.getElementsByTagName('iframe');
+ for (var i = 0, frame; frame = frames[i]; ++i) {
+ Benchmark.installOverrides(frame.contentWindow);
+ }
+ }, true);
+
+ // Substitute window functions of dynamically added frames.
+ Benchmark.originals.addEventListenerToWindow.call(
+ wnd, 'DOMNodeInsertedIntoDocument', function(e) {
+ if (e.target.tagName && e.target.tagName.toLowerCase() != 'iframe')
+ return;
+ if (e.target.contentWindow)
+ Benchmark.installOverrides(e.target.contentWindow);
+ }, true);
+};
+
+// Install overrides on top window.
+Benchmark.installOverrides(window, true);
+
+/**
+ * window.XMLHttpRequest wrapper. Notifies Benchmark.agent when request is
+ * opened, aborted, and when it's ready state changes to DONE.
+ * @constructor
+ */
+Benchmark.XMLHttpRequestWrapper = function() {
+ this.request = new Benchmark.originals.XMLHttpRequest();
+ this.wrapperReadyState = 0;
+};
+
+// Create XMLHttpRequestWrapper functions and property accessors using original
+// ones.
+(function() {
+ var request = new Benchmark.originals.XMLHttpRequest();
+ for (var property in request) {
+ if (property === 'channel') continue; // Quick fix for FF.
+ if (typeof(request[property]) == 'function') {
+ (function(property) {
+ var f = Benchmark.originals.XMLHttpRequest.prototype[property];
+ Benchmark.XMLHttpRequestWrapper.prototype[property] = function() {
+ f.apply(this.request, arguments);
+ };
+ })(property);
+ } else {
+ (function(property) {
+ Benchmark.XMLHttpRequestWrapper.prototype.__defineGetter__(property,
+ function() { return this.request[property]; });
+ Benchmark.XMLHttpRequestWrapper.prototype.__defineSetter__(property,
+ function(value) {
+ this.request[property] = value;
+ });
+
+ })(property);
+ }
+ }
+})();
+
+// Define onreadystatechange getter.
+Benchmark.XMLHttpRequestWrapper.prototype.__defineGetter__('onreadystatechange',
+ function() { return this.clientOnReadyStateChange; });
+
+// Define onreadystatechange setter.
+Benchmark.XMLHttpRequestWrapper.prototype.__defineSetter__('onreadystatechange',
+ function(value) { this.clientOnReadyStateChange = value; });
+
+Benchmark.XMLHttpRequestWrapper.prototype.__defineGetter__('readyState',
+ function() { return this.wrapperReadyState; });
+
+Benchmark.XMLHttpRequestWrapper.prototype.__defineSetter__('readyState',
+ function() {});
+
+
+/**
+ * Wrapper for XMLHttpRequest.open.
+ */
+Benchmark.XMLHttpRequestWrapper.prototype.open = function() {
+ var url = Benchmark.extractURL(arguments[1]);
+ var event = {type: 'request', method: arguments[0], url: url};
+ this.eventId = Benchmark.agent.createAsyncEvent(event);
+
+ var request = this.request;
+ var requestWrapper = this;
+ Benchmark.originals.XMLHttpRequest.prototype.open.apply(request, arguments);
+ request.onreadystatechange = function() {
+ if (this.readyState != 4 || requestWrapper.cancelled) return;
+ var callback = requestWrapper.clientOnReadyStateChange || function() {};
+ Benchmark.agent.fireAsyncEvent(requestWrapper.eventId, function() {
+ requestWrapper.wrapperReadyState = 4;
+ callback.call(request);
+ });
+ }
+};
+
+/**
+ * Wrapper for XMLHttpRequest.abort.
+ */
+Benchmark.XMLHttpRequestWrapper.prototype.abort = function() {
+ this.cancelled = true;
+ Benchmark.originals.XMLHttpRequest.prototype.abort.apply(
+ this.request, arguments);
+ Benchmark.agent.cancelAsyncEvent(this.eventId);
+};
+
+/**
+ * Driver url for reporting results.
+ * @const {string}
+ */
+Benchmark.DRIVER_URL = '/benchmark/';
+
+/**
+ * Posts request as json to Benchmark.DRIVER_URL.
+ * @param {Object} request Request to post.
+ */
+Benchmark.post = function(request, async) {
+ if (async === undefined) async = true;
+ var xmlHttpRequest = new Benchmark.originals.XMLHttpRequest();
+ xmlHttpRequest.open("POST", Benchmark.DRIVER_URL, async);
+ xmlHttpRequest.setRequestHeader("Content-type", "application/json");
+ xmlHttpRequest.send(JSON.stringify(request));
+};
+
+/**
+ * Extracts url string.
+ * @param {(string|Object)} url Object or string representing url.
+ * @return {string} Extracted url.
+ */
+Benchmark.extractURL = function(url) {
+ if (typeof(url) == 'string') return url;
+ return url.nI || url.G || '';
+};
+
+
+/**
+ * Logs error message to console and throws an exception.
+ * @param {string} message Error message
+ */
+Benchmark.die = function(message) {
+ // Debugging stuff.
+ var position = top.Benchmark.playback ? top.Benchmark.agent.timelinePosition :
+ top.Benchmark.agent.timeline.length;
+ message = message + ' at position ' + position;
+ console.error(message);
+ Benchmark.post({error: message});
+ console.log(Benchmark.originals.setTimeout.call(window, function() {}, 9999));
+ try { (0)() } catch(ex) { console.error(ex.stack); }
+ throw message;
+};
diff --git a/chromium/tools/playback_benchmark/playback.js b/chromium/tools/playback_benchmark/playback.js
new file mode 100644
index 00000000000..49628512f0e
--- /dev/null
+++ b/chromium/tools/playback_benchmark/playback.js
@@ -0,0 +1,258 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Playback agent.
+ */
+
+var Benchmark = Benchmark || {};
+
+/**
+ * Playback agent class.
+ * @param {Object} data Test data.
+ * @constructor
+ */
+Benchmark.Agent = function(data) {
+ this.timeline = data.timeline;
+ this.timelinePosition = 0;
+ this.steps = data.steps;
+ this.stepsPosition = 0;
+ this.randoms = data.randoms;
+ this.randomsPosition = 0;
+ this.ticks = data.ticks;
+ this.ticksPosition = 0;
+ this.delayedScriptElements = {};
+ this.callStackDepth = 0;
+ document.cookie = data.cookie;
+ if (window.innerWidth != data.width || window.innerHeight != data.height) {
+ Benchmark.die('Wrong window size: ' +
+ window.innerWidth + 'x' + window.innerHeight +
+ ' instead of ' + data.width + 'x' + data.height);
+ }
+ this.startTime = Benchmark.originals.Date.now();
+};
+
+/**
+ * Returns current timeline event.
+ * @return {Object} Event.
+ */
+Benchmark.Agent.prototype.getCurrentEvent = function() {
+ return this.timeline[this.timelinePosition];
+};
+
+/**
+ * Returns next recorded event in timeline. If event is the last event in
+ * timeline, posts test results to driver.
+ * @param {Object} event Event that actually happened, should correspond to
+ * the recorded one (used for debug only).
+ * @return {Object} Recorded event from timeline.
+ */
+Benchmark.Agent.prototype.getNextEvent = function(event) {
+ var recordedEvent = this.getCurrentEvent();
+ this.ensureEqual(event, recordedEvent);
+ if (event.type == 'random' || event.type == 'ticks') {
+ recordedEvent.count -= 1;
+ if (recordedEvent.count == 0) {
+ this.timelinePosition += 1;
+ }
+ } else {
+ this.timelinePosition += 1;
+ }
+ if (this.timelinePosition == this.steps[this.stepsPosition][1]) {
+ var score = Benchmark.originals.Date.now() - this.startTime;
+ Benchmark.reportScore(score);
+ }
+ return recordedEvent;
+};
+
+/**
+ * Checks if two events can be considered equal. Throws exception if events
+ * differ.
+ * @param {Object} event Event that actually happened.
+ * @param {Object} recordedEvent Event taken from timeline.
+ */
+Benchmark.Agent.prototype.ensureEqual = function(event, recordedEvent) {
+ var equal = false;
+ if (event.type == recordedEvent.type &&
+ event.type in Benchmark.eventPropertiesMap) {
+ equal = true;
+ var properties = Benchmark.eventPropertiesMap[event.type];
+ for (var i = 0; i < properties.length && equal; ++i)
+ if (event[properties[i]] != recordedEvent[properties[i]])
+ equal = false;
+ }
+ if (!equal) {
+ Benchmark.die('unexpected event: ' + JSON.stringify(event) +
+ ' instead of ' + JSON.stringify(recordedEvent));
+ }
+};
+
+/**
+ * Gets next event from timeline and returns its identifier.
+ * @param {Object} event Object with event information.
+ * @return {number} Event identifier.
+ */
+Benchmark.Agent.prototype.createAsyncEvent = function(event) {
+ return this.getNextEvent(event).id;
+};
+
+/**
+ * Stores callback to be invoked according to timeline order.
+ * @param {number} eventId 'Parent' event identifier.
+ * @param {function} callback Callback.
+ */
+Benchmark.Agent.prototype.fireAsyncEvent = function(eventId, callback) {
+ var event = this.timeline[eventId];
+ if (!event.callbackReference) return;
+ this.timeline[event.callbackReference].callback = callback;
+ this.fireSome();
+};
+
+/**
+ * Ensures that things are happening according to recorded timeline.
+ * @param {number} eventId Identifier of cancelled event.
+ */
+Benchmark.Agent.prototype.cancelAsyncEvent = function(eventId) {
+ this.getNextEvent({type: 'cancel', reference: eventId});
+};
+
+/**
+ * Checks if script isn't going to be executed too early and delays script
+ * execution if necessary.
+ * @param {number} scriptId Unique script identifier.
+ * @param {HTMLElement} doc Document element.
+ * @param {boolean} inlined Indicates whether script is a text block in the page
+ * or resides in a separate file.
+ * @param {string} src Script url (if script is not inlined).
+ */
+Benchmark.Agent.prototype.readyToExecuteScript = function(scriptId, doc,
+ inlined, src) {
+ var event = this.getCurrentEvent();
+ if (event.type == 'willExecuteScript' && event.scriptId == scriptId) {
+ this.timelinePosition += 1;
+ return true;
+ }
+ var element;
+ var elements = doc.getElementsByTagName('script');
+ for (var i = 0, el; (el = elements[i]) && !element; ++i) {
+ if (inlined) {
+ if (el.src) continue;
+ var text = el.textContent;
+ if (scriptId == text.substring(2, text.indexOf("*/")))
+ element = elements[i];
+ } else {
+ if (!el.src) continue;
+ if (el.src.indexOf(src) != -1 || src.indexOf(el.src) != -1) {
+ element = el;
+ }
+ }
+ }
+ if (!element) {
+ Benchmark.die('script element not found', scriptId, src);
+ }
+ for (var el2 = element; el2; el2 = el2.parentElement) {
+ if (el2.onload) {
+ console.log('found', el2);
+ }
+ }
+ this.delayedScriptElements[scriptId] = element;
+ return false;
+};
+
+/**
+ * Ensures that things are happening according to recorded timeline.
+ * @param {Object} event Object with event information.
+ */
+Benchmark.Agent.prototype.didExecuteScript = function(scriptId ) {
+ this.getNextEvent({type: 'didExecuteScript', scriptId: scriptId});
+ this.fireSome();
+};
+
+/**
+ * Invokes async events' callbacks according to timeline order.
+ */
+Benchmark.Agent.prototype.fireSome = function() {
+ while (this.timelinePosition < this.timeline.length) {
+ var event = this.getCurrentEvent();
+ if (event.type == 'willFire') {
+ if(!event.callback) break;
+ this.timelinePosition += 1;
+ this.callStackDepth += 1;
+ event.callback();
+ this.callStackDepth -= 1;
+ this.getNextEvent({type: 'didFire', reference: event.reference});
+ } else if (event.type == 'willExecuteScript') {
+ if (event.scriptId in this.delayedScriptElements) {
+ var element = this.delayedScriptElements[event.scriptId];
+ var parent = element.parentElement;
+ var cloneElement = element.cloneNode();
+ delete this.delayedScriptElements[event.scriptId];
+ parent.replaceChild(cloneElement, element);
+ }
+ break;
+ } else if (this.callStackDepth > 0) {
+ break;
+ } else {
+ Benchmark.die('unexpected event in fireSome:' + JSON.stringify(event));
+ }
+ }
+};
+
+/**
+ * Returns recorded random.
+ * @return {number} Recorded random.
+ */
+Benchmark.Agent.prototype.random = function() {
+ this.getNextEvent({type: 'random'});
+ return this.randoms[this.randomsPosition++];
+};
+
+/**
+ * Returns recorded ticks.
+ * @return {number} Recorded ticks.
+ */
+Benchmark.Agent.prototype.dateNow = function(event) {
+ this.getNextEvent({type: 'ticks'});
+ return this.ticks[this.ticksPosition++];
+};
+
+/**
+ * Event type -> property list mapping used for matching events.
+ * @const
+ */
+Benchmark.eventPropertiesMap = {
+ 'timeout': ['timeout'],
+ 'request': ['url'],
+ 'addEventListener': ['eventType'],
+ 'script load': ['src'],
+ 'willExecuteScript': ['scriptId'],
+ 'didExecuteScript': ['scriptId'],
+ 'willFire': ['reference'],
+ 'didFire': ['reference'],
+ 'cancel': ['reference'],
+ 'random': [],
+ 'ticks': []
+};
+
+/**
+ * Agent used by native window functions wrappers.
+ */
+Benchmark.agent = new Benchmark.Agent(Benchmark.data);
+
+/**
+ * Playback flag.
+ * @const
+ */
+Benchmark.playback = true;
+
+Benchmark.reportScore = function(score) {
+ Benchmark.score = score;
+};
+
+Benchmark.originals.addEventListenerToWindow.call(
+ window, 'message', function(event) {
+ if (Benchmark.score) {
+ event.source.postMessage(Benchmark.score, event.origin);
+ }
+ }, false);
diff --git a/chromium/tools/playback_benchmark/playback_driver.py b/chromium/tools/playback_benchmark/playback_driver.py
new file mode 100644
index 00000000000..ef6c7b4e4ef
--- /dev/null
+++ b/chromium/tools/playback_benchmark/playback_driver.py
@@ -0,0 +1,195 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Playback driver."""
+
+import cgi
+import simplejson as json
+import os
+import string
+import sys
+import threading
+import urlparse
+
+START_PAGE = """<html>
+ <script type="text/javascript">
+var runCount = $run_count;
+var results = [];
+
+function run() {
+ var wnd = window.open('?resource=start_page_popup', '',
+ 'width=$width, height=$height');
+ var timerId = setInterval(function() {
+ wnd.postMessage('ping', '$target_origin');
+ }, 300);
+ var handleMessage = function(event) {
+ clearInterval(timerId);
+ wnd.close();
+ document.writeln('<div>' + event.data + '</div>');
+ results.push(event.data);
+ runCount -= 1;
+ window.removeEventListener('message', handleMessage);
+ if (runCount > 0) {
+ run();
+ } else {
+ var xmlHttpRequest = new XMLHttpRequest();
+ xmlHttpRequest.open("POST", '/benchmark/', true);
+ xmlHttpRequest.setRequestHeader("Content-type", "application/json");
+ xmlHttpRequest.send(JSON.stringify({results: results}));
+ }
+ }
+ window.addEventListener('message', handleMessage, false);
+}
+
+run();
+ </script>
+</html>
+"""
+
+START_PAGE_POPUP = """<html>
+ <script type="text/javascript">
+window.setTimeout(function() {
+ console.log(window.innerWidth, window.innerHeight);
+ if (window.innerWidth == $width && window.innerHeight == $height) {
+ window.location = '$start_url';
+ } else {
+ window.resizeBy($width - window.innerWidth, $height - window.innerHeight);
+ window.location = window.location;
+ }
+}, 200);
+ </script>
+</html>
+"""
+
+DATA_JS = 'Benchmark.data = $data;'
+
+
+def ReadFile(file_name, mode='r'):
+ f = open(file_name, mode)
+ data = f.read()
+ f.close()
+ return data
+
+
+def ReadJSON(file_name):
+ f = open(file_name, 'r')
+ data = json.load(f)
+ f.close()
+ return data
+
+
+class PlaybackRequestHandler(object):
+ """This class is used to process HTTP requests during test playback.
+
+ Attributes:
+ test_dir: directory containing test files.
+ test_callback: function to be called when the test is finished.
+ script_dir: directory where javascript files are located.
+ """
+
+ def __init__(self, test_dir, test_callback=None, script_dir=os.getcwd()):
+ self.test_dir = test_dir
+ self.test_callback = test_callback
+ self.script_dir = script_dir
+
+ def ProcessRequest(self, handler):
+ "Processes single HTTP request."
+
+ parse_result = urlparse.urlparse(handler.path)
+ if parse_result.path.endswith('/benchmark/'):
+ query = cgi.parse_qs(parse_result.query)
+ if 'run_test' in query:
+ run_count = 1
+ if 'run_count' in query:
+ run_count = query['run_count'][0]
+ self._StartTest(handler, self.test_dir, run_count)
+ elif 'resource' in query:
+ self._GetBenchmarkResource(query['resource'][0], handler)
+ else:
+ self._ProcessBenchmarkReport(handler.body, handler)
+ else:
+ self._GetApplicationResource(handler)
+
+ def _StartTest(self, handler, test_dir, run_count):
+ "Sends test start page to browser."
+
+ cache_data = ReadJSON(os.path.join(test_dir, 'cache.json'))
+
+ # Load cached responses.
+ self.cache = {}
+ responses_dir = os.path.join(test_dir, 'responses')
+ for request in cache_data['requests']:
+ response_file = os.path.join(responses_dir, request['response_file'])
+ response = ReadFile(response_file, 'rb')
+ key = (request['method'], request['path'])
+ self.cache[key] = {'response': response, 'headers': request['headers']}
+
+ # Load benchmark scripts.
+ self.benchmark_resources = {}
+ data = ReadFile(os.path.join(test_dir, 'data.json'))
+ data = string.Template(DATA_JS).substitute(data=data)
+ self.benchmark_resources['data.js'] = {'data': data,
+ 'type': 'application/javascript'}
+ for resource in ('common.js', 'playback.js'):
+ resource_file = os.path.join(self.script_dir, resource)
+ self.benchmark_resources[resource] = {'data': ReadFile(resource_file),
+ 'type': 'application/javascript'}
+
+ # Format start page.
+ parse_result = urlparse.urlparse(cache_data['start_url'])
+ target_origin = '%s://%s' % (parse_result.scheme, parse_result.netloc)
+ start_page = string.Template(START_PAGE).substitute(
+ run_count=run_count, target_origin=target_origin,
+ width=cache_data['width'], height=cache_data['height'])
+ self.benchmark_resources['start_page'] = {
+ 'data': start_page,
+ 'type': 'text/html; charset=UTF-8'
+ }
+
+ start_page_popup = string.Template(START_PAGE_POPUP).substitute(
+ start_url=cache_data['start_url'],
+ width=cache_data['width'], height=cache_data['height'])
+ self.benchmark_resources['start_page_popup'] = {
+ 'data': start_page_popup,
+ 'type': 'text/html; charset=UTF-8'
+ }
+
+ self._GetBenchmarkResource('start_page', handler)
+
+ def _GetBenchmarkResource(self, resource, handler):
+ "Sends requested resource to browser."
+
+ if resource in self.benchmark_resources:
+ resource = self.benchmark_resources[resource]
+ handler.send_response(200)
+ handler.send_header('content-length', len(resource['data']))
+ handler.send_header('content-type', resource['type'])
+ handler.end_headers()
+ handler.wfile.write(resource['data'])
+ else:
+ handler.send_response(404)
+ handler.end_headers()
+
+ def _ProcessBenchmarkReport(self, content, handler):
+ "Reads benchmark score from report content and invokes callback."
+
+ handler.send_response(204)
+ handler.end_headers()
+ content = json.loads(content)
+ if 'results' in content:
+ results = content['results']
+ sys.stdout.write('Results: %s\n' % results)
+ if self.test_callback: self.test_callback(results)
+ elif 'error' in content:
+ sys.stderr.write('Error: %s\n' % content['error'])
+
+ def _GetApplicationResource(self, handler):
+ "Searches for response in cache. If not found, responds with 204."
+ key = (handler.command, handler.path)
+ if key in self.cache:
+ sys.stdout.write('%s %s -> found\n' % key)
+ handler.wfile.write(self.cache[key]['response'])
+ else:
+ sys.stderr.write('%s %s -> not found\n' % key)
+ handler.send_response(204, "not in cache")
+ handler.end_headers()
diff --git a/chromium/tools/playback_benchmark/proxy_handler.py b/chromium/tools/playback_benchmark/proxy_handler.py
new file mode 100644
index 00000000000..b45f96067a6
--- /dev/null
+++ b/chromium/tools/playback_benchmark/proxy_handler.py
@@ -0,0 +1,122 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""HTTP proxy request handler with SSL support.
+
+ RequestHandler: Utility class for parsing HTTP requests.
+ ProxyHandler: HTTP proxy handler.
+"""
+
+import BaseHTTPServer
+import cgi
+import OpenSSL
+import os
+import socket
+import SocketServer
+import sys
+import traceback
+import urlparse
+
+
+class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ """Class for reading HTTP requests and writing HTTP responses"""
+
+ protocol_version = "HTTP/1.1"
+ request_version = protocol_version
+
+ class HTTPRequestException(Exception): pass
+
+ def __init__(self, rfile, wfile, server):
+ self.rfile = rfile
+ self.wfile = wfile
+ self.server = server
+
+ def ReadRequest(self):
+ "Reads and parses single HTTP request from self.rfile"
+
+ self.raw_requestline = self.rfile.readline()
+ if not self.raw_requestline:
+ self.close_connection = 1
+ raise HTTPRequestException('failed to read request line')
+ if not self.parse_request():
+ raise HTTPRequestException('failed to parse request')
+ self.headers = dict(self.headers)
+ self.body = None
+ if 'content-length' in self.headers:
+ self.body = self.rfile.read(int(self.headers['content-length']))
+
+ def log_message(self, format, *args):
+ pass
+
+
+class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ "Request handler class for proxy server"
+
+ server_version = "PlaybackProxy/0.0.1"
+ protocol_version = "HTTP/1.1"
+
+ def do_CONNECT(self):
+ "Handles CONNECT HTTP request"
+
+ server = self.path.split(':')[0]
+ certificate_file = os.path.join(self.certificate_directory, server)
+ if not os.path.isfile(certificate_file):
+ sys.stderr.write('request to connect %s is ignored\n' % server)
+ self.send_response(501)
+ self.send_header('Proxy-agent', self.version_string())
+ self.end_headers()
+ return
+
+ # Send confirmation to browser.
+ self.send_response(200, 'Connection established')
+ self.send_header('Proxy-agent', self.version_string())
+ self.end_headers()
+
+ # Create SSL context.
+ context = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
+ context.use_privatekey_file(certificate_file)
+ context.use_certificate_file(certificate_file)
+
+ # Create and initialize SSL connection atop of tcp socket.
+ ssl_connection = OpenSSL.SSL.Connection(context, self.connection)
+ ssl_connection.set_accept_state()
+ ssl_connection.do_handshake()
+ ssl_rfile = socket._fileobject(ssl_connection, "rb", self.rbufsize)
+ ssl_wfile = socket._fileobject(ssl_connection, "wb", self.wbufsize)
+
+ # Handle http requests coming from ssl_connection.
+ handler = RequestHandler(ssl_rfile, ssl_wfile, self.path)
+ try:
+ handler.close_connection = 1
+ while True:
+ handler.ReadRequest()
+ self.driver.ProcessRequest(handler)
+ if handler.close_connection: break
+ except (OpenSSL.SSL.SysCallError, OpenSSL.SSL.ZeroReturnError):
+ pass
+ finally:
+ self.close_connection = 1
+
+ def do_GET(self):
+ self.driver.ProcessRequest(self)
+
+ def do_POST(self):
+ if 'content-length' in self.headers:
+ self.body = self.rfile.read(int(self.headers['content-length']))
+ self.driver.ProcessRequest(self)
+
+ def log_message(self, format, *args):
+ sys.stdout.write((format % args) + '\n')
+
+
+class ThreadingHTTPServer (SocketServer.ThreadingMixIn,
+ BaseHTTPServer.HTTPServer):
+ pass
+
+
+def CreateServer(driver, port, certificate_directory=None):
+ if not certificate_directory:
+ certificate_directory = os.path.join(os.getcwd(), 'certificates')
+ ProxyHandler.driver = driver
+ ProxyHandler.certificate_directory = certificate_directory
+ return ThreadingHTTPServer(('', port), ProxyHandler)
diff --git a/chromium/tools/playback_benchmark/run.py b/chromium/tools/playback_benchmark/run.py
new file mode 100755
index 00000000000..04ed12bc0d3
--- /dev/null
+++ b/chromium/tools/playback_benchmark/run.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests playback.
+
+Prerequisites:
+1. OpenSSL library - http://www.openssl.org/
+2. Python interface to the OpenSSL library - https://launchpad.net/pyopenssl
+
+Example usage:
+python run.py -t <test_dir>
+"""
+
+from optparse import OptionParser
+import sys
+
+import playback_driver
+import proxy_handler
+
+
+def Run(options):
+ driver = playback_driver.PlaybackRequestHandler(options.test_dir)
+ httpd = proxy_handler.CreateServer(driver, options.port)
+ sa = httpd.socket.getsockname()
+ print "Serving HTTP on", sa[0], "port", sa[1], "..."
+ httpd.serve_forever()
+
+
+def main():
+ parser = OptionParser()
+ parser.add_option("-t", "--test-dir", dest="test_dir",
+ help="directory containing recorded test data")
+ parser.add_option("-p", "--port", dest="port", type="int", default=8000)
+ options = parser.parse_args()[0]
+ if not options.test_dir:
+ raise Exception('please specify test directory')
+
+ Run(options)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/prepare-bisect-perf-regression.py b/chromium/tools/prepare-bisect-perf-regression.py
new file mode 100755
index 00000000000..88c62f3dc0f
--- /dev/null
+++ b/chromium/tools/prepare-bisect-perf-regression.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Prepare Performance Test Bisect Tool
+
+This script is used by a trybot to create a working directory and sync an
+initial copy of the depot for use in bisecting performance regressions.
+
+An example usage:
+
+./tools/prepare-bisect-perf-regressions.py --working_directory "~/builds"
+ --output_buildbot_annotations
+
+Would result in creating ~/builds/bisect and then populating it with a copy of
+the depot.
+
+"""
+
+import optparse
+import sys
+
+import bisect_utils
+
+
+def main():
+
+ usage = ('%prog [options] [-- chromium-options]\n'
+ 'Prepares a temporary depot for use on a trybot.')
+
+ parser = optparse.OptionParser(usage=usage)
+
+ parser.add_option('-w', '--working_directory',
+ type='str',
+ help='Path to the working directory where the script will '
+ 'do an initial checkout of the chromium depot. The '
+ 'files will be placed in a subdirectory "bisect" under '
+ 'working_directory and that will be used to perform the '
+ 'bisection.')
+ parser.add_option('--output_buildbot_annotations',
+ action="store_true",
+ help='Add extra annotation output for buildbot.')
+ parser.add_option('--target_platform',
+ type='choice',
+ choices=['chromium', 'cros', 'android'],
+ default='chromium',
+ help='The target platform. Choices are "chromium" (current '
+ 'platform), "cros", or "android". If you specify something '
+ 'other than "chromium", you must be properly set up to '
+ 'build that platform.')
+ (opts, args) = parser.parse_args()
+
+ if not opts.working_directory:
+ print 'Error: missing required parameter: --working_directory'
+ print
+ parser.print_help()
+ return 1
+
+ return bisect_utils.CreateBisectDirectoryAndSetupDepot(opts)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/protoc_wrapper/protoc_wrapper.py b/chromium/tools/protoc_wrapper/protoc_wrapper.py
new file mode 100755
index 00000000000..69a7aec62b3
--- /dev/null
+++ b/chromium/tools/protoc_wrapper/protoc_wrapper.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+A simple wrapper for protoc.
+
+- Adds includes in generated headers.
+- Handles building with system protobuf as an option.
+"""
+
+import optparse
+import os.path
+import shutil
+import subprocess
+import sys
+import tempfile
+
+PROTOC_INCLUDE_POINT = '// @@protoc_insertion_point(includes)\n'
+
+def ModifyHeader(header_file, extra_header):
+ """Adds |extra_header| to |header_file|. Returns 0 on success.
+
+ |extra_header| is the name of the header file to include.
+ |header_file| is a generated protobuf cpp header.
+ """
+ include_point_found = False
+ header_contents = []
+ with open(header_file) as f:
+ for line in f:
+ header_contents.append(line)
+ if line == PROTOC_INCLUDE_POINT:
+ extra_header_msg = '#include "%s"\n' % extra_header
+ header_contents.append(extra_header_msg)
+ include_point_found = True;
+ if not include_point_found:
+ return 1
+
+ with open(header_file, 'wb') as f:
+ f.write(''.join(header_contents))
+ return 0
+
+
+def RewriteProtoFilesForSystemProtobuf(path):
+ wrapper_dir = tempfile.mkdtemp()
+ try:
+ for filename in os.listdir(path):
+ if not filename.endswith('.proto'):
+ continue
+ with open(os.path.join(path, filename), 'r') as src_file:
+ with open(os.path.join(wrapper_dir, filename), 'w') as dst_file:
+ for line in src_file:
+ # Remove lines that break build with system protobuf.
+ # We cannot optimize for lite runtime, because system lite runtime
+ # does not have a Chromium-specific hack to retain unknown fields.
+ # Similarly, it does not understand corresponding option to control
+ # the usage of that hack.
+ if 'LITE_RUNTIME' in line or 'retain_unknown_fields' in line:
+ continue
+ dst_file.write(line)
+
+ return wrapper_dir
+ except:
+ shutil.rmtree(wrapper_dir)
+ raise
+
+
+def main(argv):
+ parser = optparse.OptionParser()
+ parser.add_option('--include', dest='extra_header',
+ help='The extra header to include. This must be specified '
+ 'along with --protobuf.')
+ parser.add_option('--protobuf', dest='generated_header',
+ help='The c++ protobuf header to add the extra header to. '
+ 'This must be specified along with --include.')
+ parser.add_option('--proto-in-dir',
+ help='The directory containing .proto files.')
+ parser.add_option('--proto-in-file', help='Input file to compile.')
+ parser.add_option('--use-system-protobuf', type=int, default=0,
+ help='Option to use system-installed protobuf '
+ 'instead of bundled one.')
+ (options, args) = parser.parse_args(sys.argv)
+ if len(args) < 2:
+ return 1
+
+ proto_path = options.proto_in_dir
+ if options.use_system_protobuf == 1:
+ proto_path = RewriteProtoFilesForSystemProtobuf(proto_path)
+ try:
+ # Run what is hopefully protoc.
+ protoc_args = args[1:]
+ protoc_args += ['--proto_path=%s' % proto_path,
+ os.path.join(proto_path, options.proto_in_file)]
+ ret = subprocess.call(protoc_args)
+ if ret != 0:
+ return ret
+ finally:
+ if options.use_system_protobuf == 1:
+ # Remove temporary directory holding re-written files.
+ shutil.rmtree(proto_path)
+
+ # protoc succeeded, check to see if the generated cpp header needs editing.
+ if not options.extra_header or not options.generated_header:
+ return 0
+ return ModifyHeader(options.generated_header, options.extra_header)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/tools/python/google/__init__.py b/chromium/tools/python/google/__init__.py
new file mode 100644
index 00000000000..8b137891791
--- /dev/null
+++ b/chromium/tools/python/google/__init__.py
@@ -0,0 +1 @@
+
diff --git a/chromium/tools/python/google/gethash_timer.py b/chromium/tools/python/google/gethash_timer.py
new file mode 100755
index 00000000000..9c4bd460895
--- /dev/null
+++ b/chromium/tools/python/google/gethash_timer.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Issue a series of GetHash requests to the SafeBrowsing servers and measure
+the response times.
+
+Usage:
+
+ $ ./gethash_timer.py --period=600 --samples=20 --output=resp.csv
+
+ --period (or -p): The amount of time (in seconds) to wait between GetHash
+ requests. Using a value of more than 300 (5 minutes) to
+ include the effect of DNS.
+
+ --samples (or -s): The number of requests to issue. If this parameter is not
+ specified, the test will run indefinitely.
+
+ --output (or -o): The path to a file where the output will be written in
+ CSV format: sample_number,response_code,elapsed_time_ms
+"""
+
+import getopt
+import httplib
+import sys
+import time
+
+_GETHASH_HOST = 'safebrowsing.clients.google.com'
+_GETHASH_REQUEST = (
+ '/safebrowsing/gethash?client=googleclient&appver=1.0&pver=2.1')
+
+# Global logging file handle.
+g_file_handle = None
+
+
+def IssueGetHash(prefix):
+ '''Issue one GetHash request to the safebrowsing servers.
+ Args:
+ prefix: A 4 byte value to look up on the server.
+ Returns:
+ The HTTP response code for the GetHash request.
+ '''
+ body = '4:4\n' + prefix
+ h = httplib.HTTPConnection(_GETHASH_HOST)
+ h.putrequest('POST', _GETHASH_REQUEST)
+ h.putheader('content-length', str(len(body)))
+ h.endheaders()
+ h.send(body)
+ response_code = h.getresponse().status
+ h.close()
+ return response_code
+
+
+def TimedGetHash(prefix):
+ '''Measure the amount of time it takes to receive a GetHash response.
+ Args:
+ prefix: A 4 byte value to look up on the the server.
+ Returns:
+ A tuple of HTTP resonse code and the response time (in milliseconds).
+ '''
+ start = time.time()
+ response_code = IssueGetHash(prefix)
+ return response_code, (time.time() - start) * 1000
+
+
+def RunTimedGetHash(period, samples=None):
+ '''Runs an experiment to measure the amount of time it takes to receive
+ multiple responses from the GetHash servers.
+
+ Args:
+ period: A floating point value that indicates (in seconds) the delay
+ between requests.
+ samples: An integer value indicating the number of requests to make.
+ If 'None', the test continues indefinitely.
+ Returns:
+ None.
+ '''
+ global g_file_handle
+ prefix = '\x50\x61\x75\x6c'
+ sample_count = 1
+ while True:
+ response_code, elapsed_time = TimedGetHash(prefix)
+ LogResponse(sample_count, response_code, elapsed_time)
+ sample_count += 1
+ if samples is not None and sample_count == samples:
+ break
+ time.sleep(period)
+
+
+def LogResponse(sample_count, response_code, elapsed_time):
+ '''Output the response for one GetHash query.
+ Args:
+ sample_count: The current sample number.
+ response_code: The HTTP response code for the GetHash request.
+ elapsed_time: The round-trip time (in milliseconds) for the
+ GetHash request.
+ Returns:
+ None.
+ '''
+ global g_file_handle
+ output_list = (sample_count, response_code, elapsed_time)
+ print 'Request: %d, status: %d, elapsed time: %f ms' % output_list
+ if g_file_handle is not None:
+ g_file_handle.write(('%d,%d,%f' % output_list) + '\n')
+ g_file_handle.flush()
+
+
+def SetupOutputFile(file_name):
+ '''Open a file for logging results.
+ Args:
+ file_name: A path to a file to store the output.
+ Returns:
+ None.
+ '''
+ global g_file_handle
+ g_file_handle = open(file_name, 'w')
+
+
+def main():
+ period = 10
+ samples = None
+
+ options, args = getopt.getopt(sys.argv[1:],
+ 's:p:o:',
+ ['samples=', 'period=', 'output='])
+ for option, value in options:
+ if option == '-s' or option == '--samples':
+ samples = int(value)
+ elif option == '-p' or option == '--period':
+ period = float(value)
+ elif option == '-o' or option == '--output':
+ file_name = value
+ else:
+ print 'Bad option: %s' % option
+ return 1
+ try:
+ print 'Starting Timed GetHash ----------'
+ SetupOutputFile(file_name)
+ RunTimedGetHash(period, samples)
+ except KeyboardInterrupt:
+ pass
+
+ print 'Timed GetHash complete ----------'
+ g_file_handle.close()
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/python/google/httpd_config/httpd.conf b/chromium/tools/python/google/httpd_config/httpd.conf
new file mode 100644
index 00000000000..0457be4ff30
--- /dev/null
+++ b/chromium/tools/python/google/httpd_config/httpd.conf
@@ -0,0 +1,734 @@
+##
+## httpd.conf -- Apache HTTP server configuration file
+##
+
+#
+# Based upon the NCSA server configuration files originally by Rob McCool.
+#
+# This is the main Apache server configuration file. It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/> for detailed information about
+# the directives.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do. They're here only as hints or reminders. If you are unsure
+# consult the online docs. You have been warned.
+#
+# After this file is processed, the server will look for and process
+# /private/etc/httpd/srm.conf and then /private/etc/httpd/access.conf
+# unless you have overridden these with ResourceConfig and/or
+# AccessConfig directives here.
+#
+# The configuration directives are grouped into three basic sections:
+# 1. Directives that control the operation of the Apache server process as a
+# whole (the 'global environment').
+# 2. Directives that define the parameters of the 'main' or 'default' server,
+# which responds to requests that aren't handled by a virtual host.
+# These directives also provide default values for the settings
+# of all virtual hosts.
+# 3. Settings for virtual hosts, which allow Web requests to be sent to
+# different IP addresses or hostnames and have them handled by the
+# same Apache server process.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path. If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"
+# with ServerRoot set to "/usr/local/apache" will be interpreted by the
+# server as "/usr/local/apache/logs/foo.log".
+#
+
+### Section 1: Global Environment
+#
+# The directives in this section affect the overall operation of Apache,
+# such as the number of concurrent requests it can handle or where it
+# can find its configuration files.
+#
+
+#
+# ServerType is either inetd, or standalone. Inetd mode is only supported on
+# Unix platforms.
+#
+ServerType standalone
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# NOTE! If you intend to place this on an NFS (or otherwise network)
+# mounted filesystem then please read the LockFile documentation
+# (available at <URL:http://www.apache.org/docs/mod/core.html#lockfile>);
+# you will save yourself a lot of trouble.
+#
+#ServerRoot "/usr"
+
+#
+# The LockFile directive sets the path to the lockfile used when Apache
+# is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or
+# USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be left at
+# its default value. The main reason for changing it is if the logs
+# directory is NFS mounted, since the lockfile MUST BE STORED ON A LOCAL
+# DISK. The PID of the main server process is automatically appended to
+# the filename.
+#
+#LockFile "/private/var/run/httpd.lock"
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+#
+PidFile "/tmp/WebKit/httpd.pid"
+
+#
+# ScoreBoardFile: File used to store internal server process information.
+# Not all architectures require this. But if yours does (you'll know because
+# this file will be created when you run Apache) then you *must* ensure that
+# no two invocations of Apache share the same scoreboard file.
+#
+ScoreBoardFile "/tmp/WebKit/httpd.scoreboard"
+
+#
+# In the standard configuration, the server will process httpd.conf (this
+# file, specified by the -f command line option), srm.conf, and access.conf
+# in that order. The latter two files are now distributed empty, as it is
+# recommended that all directives be kept in a single file for simplicity.
+# The commented-out values below are the built-in defaults. You can have the
+# server ignore these files altogether by using "/dev/null" (for Unix) or
+# "nul" (for Win32) for the arguments to the directives.
+#
+ResourceConfig /dev/null
+AccessConfig /dev/null
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 15
+
+#
+# Server-pool size regulation. Rather than making you guess how many
+# server processes you need, Apache dynamically adapts to the load it
+# sees --- that is, it tries to maintain enough server processes to
+# handle the current load, plus a few spare servers to handle transient
+# load spikes (e.g., multiple simultaneous requests from a single
+# Netscape browser).
+#
+# It does this by periodically checking how many servers are waiting
+# for a request. If there are fewer than MinSpareServers, it creates
+# a new spare. If there are more than MaxSpareServers, some of the
+# spares die off. The default values are probably OK for most sites.
+#
+MinSpareServers 1
+MaxSpareServers 5
+
+#
+# Number of servers to start initially --- should be a reasonable ballpark
+# figure.
+#
+StartServers 1
+
+#
+# Limit on total number of servers running, i.e., limit on the number
+# of clients who can simultaneously connect --- if this limit is ever
+# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW.
+# It is intended mainly as a brake to keep a runaway server from taking
+# the system with it as it spirals down...
+#
+MaxClients 150
+
+#
+# MaxRequestsPerChild: the number of requests each child process is
+# allowed to process before the child dies. The child will exit so
+# as to avoid problems after prolonged use when Apache (and maybe the
+# libraries it uses) leak memory or other resources. On most systems, this
+# isn't really needed, but a few (such as Solaris) do have notable leaks
+# in the libraries. For these platforms, set to something like 10000
+# or so; a setting of 0 means unlimited.
+#
+# NOTE: This value does not include keepalive requests after the initial
+# request per connection. For example, if a child process handles
+# an initial request and 10 subsequent "keptalive" requests, it
+# would only count as 1 request towards this limit.
+#
+MaxRequestsPerChild 100000
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#
+Listen 127.0.0.1:8000
+Listen 127.0.0.1:8080
+Listen 127.0.0.1:8081
+Listen 127.0.0.1:9000
+Listen 127.0.0.1:9080
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Please read the file http://httpd.apache.org/docs/dso.html for more
+# details about the DSO mechanism and run `httpd -l' for the list of already
+# built-in (statically linked and thus always available) modules in your httpd
+# binary.
+#
+# Note: The order in which modules are loaded is important. Don't change
+# the order below without expert advice.
+#
+# Example:
+# LoadModule foo_module lib/apache/mod_foo.dll
+#LoadModule vhost_alias_module lib/apache/mod_vhost_alias.dll
+#LoadModule env_module lib/apache/mod_env.dll
+LoadModule config_log_module lib/apache/mod_log_config.dll
+#LoadModule mime_magic_module lib/apache/mod_mime_magic.dll
+LoadModule mime_module lib/apache/mod_mime.dll
+LoadModule negotiation_module lib/apache/mod_negotiation.dll
+#LoadModule status_module lib/apache/mod_status.dll
+#LoadModule info_module lib/apache/mod_info.dll
+LoadModule includes_module lib/apache/mod_include.dll
+LoadModule autoindex_module lib/apache/mod_autoindex.dll
+#LoadModule dir_module lib/apache/mod_dir.dll
+LoadModule cgi_module lib/apache/mod_cgi.dll
+LoadModule asis_module lib/apache/mod_asis.dll
+LoadModule imap_module lib/apache/mod_imap.dll
+LoadModule action_module lib/apache/mod_actions.dll
+#LoadModule speling_module lib/apache/mod_speling.dll
+#LoadModule userdir_module lib/apache/mod_userdir.dll
+LoadModule alias_module lib/apache/mod_alias.dll
+LoadModule rewrite_module lib/apache/mod_rewrite.dll
+LoadModule access_module lib/apache/mod_access.dll
+LoadModule auth_module lib/apache/mod_auth.dll
+#LoadModule anon_auth_module lib/apache/mod_auth_anon.dll
+#LoadModule dbm_auth_module lib/apache/mod_auth_dbm.dll
+#LoadModule digest_module lib/apache/mod_digest.dll
+#LoadModule proxy_module lib/apache/libproxy.dll
+#LoadModule cern_meta_module lib/apache/mod_cern_meta.dll
+#LoadModule expires_module lib/apache/mod_expires.dll
+LoadModule headers_module lib/apache/mod_headers.dll
+#LoadModule usertrack_module lib/apache/mod_usertrack.dll
+#LoadModule log_forensic_module lib/apache/mod_log_forensic.dll
+#LoadModule unique_id_module lib/apache/mod_unique_id.dll
+#LoadModule setenvif_module lib/apache/mod_setenvif.dll
+#LoadModule dav_module lib/apache/libdav.dll
+#LoadModule ssl_module lib/apache/libssl.dll
+#LoadModule perl_module lib/apache/libperl.dll
+#LoadModule php4_module lib/apache/libphp4.dll
+#LoadModule hfs_apple_module lib/apache/mod_hfs_apple.dll
+#LoadModule bonjour_module lib/apache/mod_bonjour.dll
+
+# Reconstruction of the complete module list from all available modules
+# (static and shared ones) to achieve correct module execution order.
+# [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO]
+ClearModuleList
+#AddModule mod_vhost_alias.c
+#AddModule mod_env.c
+AddModule mod_log_config.c
+#AddModule mod_mime_magic.c
+AddModule mod_mime.c
+AddModule mod_negotiation.c
+#AddModule mod_status.c
+#AddModule mod_info.c
+AddModule mod_include.c
+AddModule mod_autoindex.c
+#AddModule mod_dir.c
+AddModule mod_cgi.c
+AddModule mod_asis.c
+AddModule mod_imap.c
+AddModule mod_actions.c
+#AddModule mod_speling.c
+#AddModule mod_userdir.c
+AddModule mod_alias.c
+AddModule mod_rewrite.c
+AddModule mod_access.c
+AddModule mod_auth.c
+#AddModule mod_auth_anon.c
+#AddModule mod_auth_dbm.c
+#AddModule mod_digest.c
+#AddModule mod_proxy.c
+#AddModule mod_cern_meta.c
+#AddModule mod_expires.c
+AddModule mod_headers.c
+#AddModule mod_usertrack.c
+#AddModule mod_log_forensic.c
+#AddModule mod_unique_id.c
+AddModule mod_so.c
+#AddModule mod_setenvif.c
+#AddModule mod_dav.c
+#AddModule mod_ssl.c
+#AddModule mod_perl.c
+#AddModule mod_php4.c
+#AddModule mod_hfs_apple.c
+#AddModule mod_bonjour.c
+
+### Section 2: 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition. These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerName allows you to set a host name which is sent back to clients for
+# your server if it's different than the one the program would get (i.e., use
+# "www" instead of the host's real name).
+#
+# Note: You cannot just invent host names and hope they work. The name you
+# define here must be a valid DNS name for your host. If you don't understand
+# this, ask your network administrator.
+# If your host doesn't have a registered DNS name, enter its IP address here.
+# You will have to access it by its address (e.g., http://123.45.67.89/)
+# anyway, and this will make redirections work in a sensible way.
+#
+# 127.0.0.1 is the TCP/IP local loop-back address, often named localhost. Your
+# machine always knows itself by this address. If you use Apache strictly for
+# local testing and development, you may use 127.0.0.1 as the server name.
+#
+ServerName 127.0.0.1
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#DocumentRoot "/Library/WebServer/Documents"
+
+#
+# Each directory to which Apache has access, can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories).
+#
+<Directory />
+#
+# This may also be "None", "All", or any combination of "Indexes",
+# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews".
+#
+# Note that "MultiViews" must be named *explicitly* --- "Options All"
+# doesn't give it to you.
+#
+ Options Indexes FollowSymLinks MultiViews ExecCGI Includes
+
+#
+# This controls which options the .htaccess files in directories can
+# override. Can also be "All", or any combination of "Options", "FileInfo",
+# "AuthConfig", and "Limit"
+#
+ AllowOverride All
+
+#
+# Controls who can get stuff from this server.
+#
+ Order allow,deny
+ Allow from all
+</Directory>
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for access control information.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess files from being viewed by
+# Web clients. Since .htaccess files often contain authorization
+# information, access is disallowed for security reasons. Comment
+# these lines out if you want Web visitors to see the contents of
+# .htaccess files. If you change the AccessFileName directive above,
+# be sure to make the corresponding changes here.
+#
+# Also, folks tend to use names such as .htpasswd for password
+# files, so this will protect those as well.
+#
+<Files ~ "^\.([Hh][Tt]|[Dd][Ss]_[Ss])">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Files>
+
+#
+# Apple specific filesystem protection.
+#
+
+<Files "rsrc">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Files>
+
+<Directory ~ ".*\.\.namedfork">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Directory>
+
+#
+# CacheNegotiatedDocs: By default, Apache sends "Pragma: no-cache" with each
+# document that was negotiated on the basis of content. This asks proxy
+# servers not to cache the document. Uncommenting the following line disables
+# this behavior, and proxies will be allowed to cache the documents.
+#
+#CacheNegotiatedDocs
+
+#
+# UseCanonicalName: (new for 1.3) With this setting turned on, whenever
+# Apache needs to construct a self-referencing URL (a URL that refers back
+# to the server the response is coming from) it will use ServerName and
+# Port to form a "canonical" name. With this setting off, Apache will
+# use the hostname:port that the client supplied, when possible. This
+# also affects SERVER_NAME and SERVER_PORT in CGI scripts.
+#
+UseCanonicalName On
+
+#
+# TypesConfig describes where the mime.types file (or equivalent) is
+# to be found.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#
+#<IfModule mod_mime.c>
+# TypesConfig /private/etc/httpd/mime.types
+#</IfModule>
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value. If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here. If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#ErrorLog "/tmp/layout-test-results/error_log"
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%p %h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+#
+# The location and format of the access logfile (Common Logfile Format).
+# If you do not define any access logfiles within a <VirtualHost>
+# container, they will be logged here. Contrariwise, if you *do*
+# define per-<VirtualHost> access logfiles, transactions will be
+# logged therein and *not* in this file.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#CustomLog "/tmp/layout-test-results/access_log" common
+
+#
+# If you prefer a single logfile with access, agent, and referer information
+# (Combined Logfile Format) you can use the following directive.
+#
+#CustomLog "/tmp/layout-test-results/access_log" combined
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (error documents, FTP directory listings,
+# mod_status and mod_info output etc., but not CGI generated documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#
+ServerSignature On
+
+#
+# Aliases: Add here as many aliases as you need (with no limit). The format is
+# Alias fakename realname
+#
+<IfModule mod_alias.c>
+</IfModule>
+# End of aliases.
+
+#
+# Redirect allows you to tell clients about documents which used to exist in
+# your server's namespace, but do not anymore. This allows you to tell the
+# clients where to look for the relocated document.
+# Format: Redirect old-URI new-URL
+#
+
+#
+# Document types.
+#
+<IfModule mod_mime.c>
+
+ #
+ # AddLanguage allows you to specify the language of a document. You can
+ # then use content negotiation to give a browser a file in a language
+ # it can understand.
+ #
+ # Note 1: The suffix does not have to be the same as the language
+ # keyword --- those with documents in Polish (whose net-standard
+ # language code is pl) may wish to use "AddLanguage pl .po" to
+ # avoid the ambiguity with the common suffix for perl scripts.
+ #
+ # Note 2: The example entries below illustrate that in quite
+ # some cases the two character 'Language' abbreviation is not
+ # identical to the two character 'Country' code for its country,
+ # E.g. 'Danmark/dk' versus 'Danish/da'.
+ #
+ # Note 3: In the case of 'ltz' we violate the RFC by using a three char
+ # specifier. But there is 'work in progress' to fix this and get
+ # the reference data for rfc1766 cleaned up.
+ #
+ # Danish (da) - Dutch (nl) - English (en) - Estonian (ee)
+ # French (fr) - German (de) - Greek-Modern (el)
+ # Italian (it) - Korean (kr) - Norwegian (no) - Norwegian Nynorsk (nn)
+ # Portugese (pt) - Luxembourgeois* (ltz)
+ # Spanish (es) - Swedish (sv) - Catalan (ca) - Czech(cs)
+ # Polish (pl) - Brazilian Portuguese (pt-br) - Japanese (ja)
+ # Russian (ru)
+ #
+ AddLanguage da .dk
+ AddLanguage nl .nl
+ AddLanguage en .en
+ AddLanguage et .ee
+ AddLanguage fr .fr
+ AddLanguage de .de
+ AddLanguage el .el
+ AddLanguage he .he
+ AddCharset ISO-8859-8 .iso8859-8
+ AddLanguage it .it
+ AddLanguage ja .ja
+ AddCharset ISO-2022-JP .jis
+ AddLanguage kr .kr
+ AddCharset ISO-2022-KR .iso-kr
+ AddLanguage nn .nn
+ AddLanguage no .no
+ AddLanguage pl .po
+ AddCharset ISO-8859-2 .iso-pl
+ AddLanguage pt .pt
+ AddLanguage pt-br .pt-br
+ AddLanguage ltz .lu
+ AddLanguage ca .ca
+ AddLanguage es .es
+ AddLanguage sv .sv
+ AddLanguage cs .cz .cs
+ AddLanguage ru .ru
+ AddLanguage zh-TW .zh-tw
+ AddCharset Big5 .Big5 .big5
+ AddCharset WINDOWS-1251 .cp-1251
+ AddCharset CP866 .cp866
+ AddCharset ISO-8859-5 .iso-ru
+ AddCharset KOI8-R .koi8-r
+ AddCharset UCS-2 .ucs2
+ AddCharset UCS-4 .ucs4
+ AddCharset UTF-8 .utf8
+
+ # LanguagePriority allows you to give precedence to some languages
+ # in case of a tie during content negotiation.
+ #
+ # Just list the languages in decreasing order of preference. We have
+ # more or less alphabetized them here. You probably want to change this.
+ #
+ <IfModule mod_negotiation.c>
+ LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ru ltz ca es sv tw
+ </IfModule>
+
+ #
+ # AddType allows you to tweak mime.types without actually editing it, or to
+ # make certain files to be certain types.
+ #
+ AddType application/x-tar .tgz
+
+ #
+ # AddEncoding allows you to have certain browsers uncompress
+ # information on the fly. Note: Not all browsers support this.
+ # Despite the name similarity, the following Add* directives have nothing
+ # to do with the FancyIndexing customization directives above.
+ #
+ AddEncoding x-compress .Z
+ AddEncoding x-gzip .gz .tgz
+ #
+ # If the AddEncoding directives above are commented-out, then you
+ # probably should define those extensions to indicate media types:
+ #
+ #AddType application/x-compress .Z
+ #AddType application/x-gzip .gz .tgz
+
+ #
+ # AddHandler allows you to map certain file extensions to "handlers",
+ # actions unrelated to filetype. These can be either built into the server
+ # or added with the Action command (see below)
+ #
+ # If you want to use server side includes, or CGI outside
+ # ScriptAliased directories, uncomment the following lines.
+ #
+ # To use CGI scripts:
+ #
+ AddHandler cgi-script .cgi .pl
+
+ #
+ # To use server-parsed HTML files
+ #
+ AddType text/html .shtml
+ AddHandler server-parsed .shtml
+
+ #
+ # Uncomment the following line to enable Apache's send-asis HTTP file
+ # feature
+ #
+ AddHandler send-as-is asis
+
+ #
+ # If you wish to use server-parsed imagemap files, use
+ #
+ #AddHandler imap-file map
+
+ #
+ # To enable type maps, you might want to use
+ #
+ #AddHandler type-map var
+
+</IfModule>
+# End of document types.
+
+#
+# Action lets you define media types that will execute a script whenever
+# a matching file is called. This eliminates the need for repeated URL
+# pathnames for oft-used CGI file processors.
+# Format: Action media/type /cgi-script/location
+# Format: Action handler-name /cgi-script/location
+#
+
+#
+# MetaDir: specifies the name of the directory in which Apache can find
+# meta information files. These files contain additional HTTP headers
+# to include when sending the document
+#
+#MetaDir .web
+
+#
+# MetaSuffix: specifies the file name suffix for the file containing the
+# meta information.
+#
+#MetaSuffix .meta
+
+#
+# Customizable error response (Apache style)
+# these come in three flavors
+#
+# 1) plain text
+#ErrorDocument 500 "The server made a boo boo.
+# n.b. the single leading (") marks it as text, it does not get output
+#
+# 2) local redirects
+#ErrorDocument 404 /missing.html
+# to redirect to local URL /missing.html
+#ErrorDocument 404 /cgi-bin/missing_handler.pl
+# N.B.: You can redirect to a script or a document using server-side-includes.
+#
+# 3) external redirects
+#ErrorDocument 402 http://some.other-server.com/subscription_info.html
+# N.B.: Many of the environment variables associated with the original
+# request will *not* be available to such a script.
+
+#
+# Proxy Server directives. Uncomment the following lines to
+# enable the proxy server:
+#
+#<IfModule mod_proxy.c>
+# ProxyRequests On
+
+# <Directory proxy:*>
+# Order deny,allow
+# Deny from all
+# Allow from .your-domain.com
+# </Directory>
+
+ #
+ # Enable/disable the handling of HTTP/1.1 "Via:" headers.
+ # ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+ # Set to one of: Off | On | Full | Block
+ #
+# ProxyVia On
+
+ #
+ # To enable the cache as well, edit and uncomment the following lines:
+ # (no cacheing without CacheRoot)
+ #
+# CacheRoot "/private/var/run/proxy"
+# CacheSize 5
+# CacheGcInterval 4
+# CacheMaxExpire 24
+# CacheLastModifiedFactor 0.1
+# CacheDefaultExpire 1
+# NoCache a-domain.com another-domain.edu joes.garage-sale.com
+
+#</IfModule>
+# End of proxy directives.
+
+
+<IfModule mod_php4.c>
+ # If php is turned on, we repsect .php and .phps files.
+ AddType application/x-httpd-php .php
+ AddType application/x-httpd-php-source .phps
+
+ # Since most users will want index.php to work we
+ # also automatically enable index.php
+ <IfModule mod_dir.c>
+ DirectoryIndex index.html index.php
+ </IfModule>
+</IfModule>
+
+<IfModule mod_rewrite.c>
+ RewriteEngine On
+ RewriteCond %{REQUEST_METHOD} ^TRACE
+ RewriteRule .* - [F]
+</IfModule>
diff --git a/chromium/tools/python/google/httpd_config/httpd2.conf b/chromium/tools/python/google/httpd_config/httpd2.conf
new file mode 100644
index 00000000000..8c96f757787
--- /dev/null
+++ b/chromium/tools/python/google/httpd_config/httpd2.conf
@@ -0,0 +1,280 @@
+## httpd2.conf -- Apache 2.x HTTP server configuration file
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+Listen 127.0.0.1:8000
+Listen 127.0.0.1:8080
+Listen 127.0.0.1:8081
+Listen 127.0.0.1:8443
+Listen 127.0.0.1:9000
+Listen 127.0.0.1:9080
+Listen 127.0.0.1:9443
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Please read the file http://httpd.apache.org/docs/dso.html for more
+# details about the DSO mechanism and run `httpd -l' for the list of already
+# built-in (statically linked and thus always available) modules in your httpd
+# binary.
+#
+# Note: The order in which modules are loaded is important. Don't change
+# the order below without expert advice.
+#
+#LoadModule authn_file_module lib/apache2/mod_authn_file.so
+#LoadModule authn_dbm_module lib/apache2/mod_authn_dbm.so
+#LoadModule authn_anon_module lib/apache2/mod_authn_anon.so
+#LoadModule authn_dbd_module lib/apache2/mod_authn_dbd.so
+#LoadModule authn_default_module lib/apache2/mod_authn_default.so
+LoadModule authz_host_module lib/apache2/mod_authz_host.so
+#LoadModule authz_groupfile_module lib/apache2/mod_authz_groupfile.so
+#LoadModule authz_user_module lib/apache2/mod_authz_user.so
+#LoadModule authz_dbm_module lib/apache2/mod_authz_dbm.so
+#LoadModule authz_owner_module lib/apache2/mod_authz_owner.so
+#LoadModule authz_default_module lib/apache2/mod_authz_default.so
+#LoadModule auth_basic_module lib/apache2/mod_auth_basic.so
+#LoadModule auth_digest_module lib/apache2/mod_auth_digest.so
+#LoadModule dbd_module lib/apache2/mod_dbd.so
+#LoadModule dumpio_module lib/apache2/mod_dumpio.so
+#LoadModule ext_filter_module lib/apache2/mod_ext_filter.so
+LoadModule include_module lib/apache2/mod_include.so
+#LoadModule filter_module lib/apache2/mod_filter.so
+#LoadModule deflate_module lib/apache2/mod_deflate.so
+LoadModule log_config_module lib/apache2/mod_log_config.so
+#LoadModule log_forensic_module lib/apache2/mod_log_forensic.so
+#LoadModule logio_module lib/apache2/mod_logio.so
+#LoadModule env_module lib/apache2/mod_env.so
+#LoadModule mime_magic_module lib/apache2/mod_mime_magic.so
+#LoadModule cern_meta_module lib/apache2/mod_cern_meta.so
+#LoadModule expires_module lib/apache2/mod_expires.so
+LoadModule headers_module lib/apache2/mod_headers.so
+#LoadModule ident_module lib/apache2/mod_ident.so
+#LoadModule usertrack_module lib/apache2/mod_usertrack.so
+#LoadModule unique_id_module lib/apache2/mod_unique_id.so
+#LoadModule setenvif_module lib/apache2/mod_setenvif.so
+#LoadModule version_module lib/apache2/mod_version.so
+#LoadModule proxy_module lib/apache2/mod_proxy.so
+#LoadModule proxy_connect_module lib/apache2/mod_proxy_connect.so
+#LoadModule proxy_ftp_module lib/apache2/mod_proxy_ftp.so
+#LoadModule proxy_http_module lib/apache2/mod_proxy_http.so
+#LoadModule proxy_ajp_module lib/apache2/mod_proxy_ajp.so
+#LoadModule proxy_balancer_module lib/apache2/mod_proxy_balancer.so
+LoadModule ssl_module lib/apache2/mod_ssl.so
+LoadModule mime_module lib/apache2/mod_mime.so
+#LoadModule dav_module lib/apache2/mod_dav.so
+#LoadModule status_module lib/apache2/mod_status.so
+LoadModule autoindex_module lib/apache2/mod_autoindex.so
+LoadModule asis_module lib/apache2/mod_asis.so
+#LoadModule info_module lib/apache2/mod_info.so
+LoadModule cgi_module lib/apache2/mod_cgi.so
+#LoadModule dav_fs_module lib/apache2/mod_dav_fs.so
+#LoadModule vhost_alias_module lib/apache2/mod_vhost_alias.so
+LoadModule negotiation_module lib/apache2/mod_negotiation.so
+#LoadModule dir_module lib/apache2/mod_dir.so
+LoadModule imagemap_module lib/apache2/mod_imagemap.so
+LoadModule actions_module lib/apache2/mod_actions.so
+#LoadModule speling_module lib/apache2/mod_speling.so
+#LoadModule userdir_module lib/apache2/mod_userdir.so
+LoadModule alias_module lib/apache2/mod_alias.so
+LoadModule rewrite_module lib/apache2/mod_rewrite.so
+LoadModule php5_module lib/apache2/cygphp5.so
+
+#LoadModule imap_module lib/apache/mod_imap.dll
+#LoadModule access_module lib/apache/mod_access.dll
+#LoadModule auth_module lib/apache/mod_auth.dll
+
+
+#
+# Each directory to which Apache has access, can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories).
+#
+<Directory />
+ Options Indexes FollowSymLinks MultiViews ExecCGI Includes
+ AllowOverride All
+ Order allow,deny
+ Allow from all
+</Directory>
+
+
+#
+# Apple specific filesystem protection.
+#
+<Files "rsrc">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Files>
+<Directory ~ ".*\.\.namedfork">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Directory>
+
+
+#
+# UseCanonicalName: (new for 1.3) With this setting turned on, whenever
+# Apache needs to construct a self-referencing URL (a URL that refers back
+# to the server the response is coming from) it will use ServerName and
+# Port to form a "canonical" name. With this setting off, Apache will
+# use the hostname:port that the client supplied, when possible. This
+# also affects SERVER_NAME and SERVER_PORT in CGI scripts.
+#
+UseCanonicalName On
+
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (error documents, FTP directory listings,
+# mod_status and mod_info output etc., but not CGI generated documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#
+ServerSignature On
+
+
+#
+# Document types.
+#
+<IfModule mime_module>
+
+ #
+ # AddLanguage allows you to specify the language of a document. You can
+ # then use content negotiation to give a browser a file in a language
+ # it can understand.
+ #
+ # Note 1: The suffix does not have to be the same as the language
+ # keyword --- those with documents in Polish (whose net-standard
+ # language code is pl) may wish to use "AddLanguage pl .po" to
+ # avoid the ambiguity with the common suffix for perl scripts.
+ #
+ # Note 2: The example entries below illustrate that in quite
+ # some cases the two character 'Language' abbreviation is not
+ # identical to the two character 'Country' code for its country,
+ # E.g. 'Danmark/dk' versus 'Danish/da'.
+ #
+ # Note 3: In the case of 'ltz' we violate the RFC by using a three char
+ # specifier. But there is 'work in progress' to fix this and get
+ # the reference data for rfc1766 cleaned up.
+ #
+ # Danish (da) - Dutch (nl) - English (en) - Estonian (ee)
+ # French (fr) - German (de) - Greek-Modern (el)
+ # Italian (it) - Korean (kr) - Norwegian (no) - Norwegian Nynorsk (nn)
+ # Portugese (pt) - Luxembourgeois* (ltz)
+ # Spanish (es) - Swedish (sv) - Catalan (ca) - Czech(cs)
+ # Polish (pl) - Brazilian Portuguese (pt-br) - Japanese (ja)
+ # Russian (ru)
+ #
+ AddLanguage da .dk
+ AddLanguage nl .nl
+ AddLanguage en .en
+ AddLanguage et .ee
+ AddLanguage fr .fr
+ AddLanguage de .de
+ AddLanguage el .el
+ AddLanguage he .he
+ AddCharset ISO-8859-8 .iso8859-8
+ AddLanguage it .it
+ AddLanguage ja .ja
+ AddCharset ISO-2022-JP .jis
+ AddLanguage kr .kr
+ AddCharset ISO-2022-KR .iso-kr
+ AddLanguage nn .nn
+ AddLanguage no .no
+ AddLanguage pl .po
+ AddCharset ISO-8859-2 .iso-pl
+ AddLanguage pt .pt
+ AddLanguage pt-br .pt-br
+ AddLanguage ltz .lu
+ AddLanguage ca .ca
+ AddLanguage es .es
+ AddLanguage sv .sv
+ AddLanguage cs .cz .cs
+ AddLanguage ru .ru
+ AddLanguage zh-TW .zh-tw
+ AddCharset Big5 .Big5 .big5
+ AddCharset WINDOWS-1251 .cp-1251
+ AddCharset CP866 .cp866
+ AddCharset ISO-8859-5 .iso-ru
+ AddCharset KOI8-R .koi8-r
+ AddCharset UCS-2 .ucs2
+ AddCharset UCS-4 .ucs4
+ AddCharset UTF-8 .utf8
+
+ # LanguagePriority allows you to give precedence to some languages
+ # in case of a tie during content negotiation.
+ #
+ # Just list the languages in decreasing order of preference. We have
+ # more or less alphabetized them here. You probably want to change this.
+ #
+ <IfModule negotiation_module>
+ LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ru ltz ca es sv tw
+ </IfModule>
+
+ #
+ # AddType allows you to tweak mime.types without actually editing it, or to
+ # make certain files to be certain types.
+ #
+ AddType application/x-tar .tgz
+
+ #
+ # AddEncoding allows you to have certain browsers uncompress
+ # information on the fly. Note: Not all browsers support this.
+ # Despite the name similarity, the following Add* directives have nothing
+ # to do with the FancyIndexing customization directives above.
+ #
+ AddEncoding x-compress .Z
+ AddEncoding x-gzip .gz .tgz
+
+ #
+ # AddHandler allows you to map certain file extensions to "handlers",
+ # actions unrelated to filetype. These can be either built into the server
+ # or added with the Action command (see below)
+ #
+ # If you want to use server side includes, or CGI outside
+ # ScriptAliased directories, uncomment the following lines.
+ #
+ # To use CGI scripts:
+ #
+ AddHandler cgi-script .cgi .pl
+
+ #
+ # To use server-parsed HTML files
+ #
+ AddType text/html .shtml
+ AddHandler server-parsed .shtml
+
+ #
+ # Uncomment the following line to enable Apache's send-asis HTTP file
+ # feature
+ #
+ AddHandler send-as-is asis
+</IfModule>
+
+
+<IfModule php5_module>
+ AddType application/x-httpd-php .php
+ AddType application/x-httpd-php-source .phps
+</IfModule>
+
+<IfModule rewrite_module>
+ RewriteEngine On
+ RewriteCond %{REQUEST_METHOD} ^TRACE
+ RewriteRule .* - [F]
+</IfModule>
diff --git a/chromium/tools/python/google/httpd_config/httpd2.pem b/chromium/tools/python/google/httpd_config/httpd2.pem
new file mode 100644
index 00000000000..69d10d2219c
--- /dev/null
+++ b/chromium/tools/python/google/httpd_config/httpd2.pem
@@ -0,0 +1,110 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCbE8ILYEITh9up
+ken6c61zNAibRnq70g7glLy6fHqQJsrIVzmj6b+4dHLYUA3mu13pqZyoK6YP1MPd
+afdh23IrW4vo6xtxCpqQk0rAEa+0cji7E+01JHEvO4Y1Q4NScGj628HDe+dJqiQD
+AZWRDgIodlKrRjD1XZT91U0UsuytDvYQVbEIosgMdEevW8FvqWAhDH6fkb4Q5OdW
+wUxGnX0+cHLINVMJvCoPq+fDQWy4A/2uRiFn/x9NBZEz2AwNta+y6e3pn8gZE9vh
+Feqe3Jv9toIZzsqQZ/fCWK6FKzfkxQNYc5vcSqHx96VuDhqrbnPFdpcQfRB08Yg4
+3TSioKY7AgMBAAECggEAOqImzPxRH2dPs3Z6+/n+y78RvfvQ7fDHNTyneu8TvCse
+os7v+TypA4nr3kOubd3L7Uv28lLGj9fHUpD9Ot+o9CHB7YfvMTdsJ1u5eJN3VoeV
+UY6AMoab0Nr1rG/hWCsuViL+yPWxBlYxFX3k2hps0HWkXiPE4RDIA41BfqEEAY4+
+6V0lvoBZAJbYncGg1BEDxH+erXIFmAu3PeCYEpb2VP7hQH8JITEWco+DmK5impoB
+e+BaEVLqFKUjU+EdvpE4WKB24K9lw35bfGhWd/cQwSaLIPezG1OK9M0JbpPoj5gg
+KBdwrS7EdOur64Ue774KPAFRYU8mEpnnQMKOnNUuSQKBgQDHfriFwjViBdRJGTZ1
+Wa/AgJ7rVU9yMhaUSifYbLQDrYRwagYNtA/NqTgRYl7BbHZpsYmglQoCAWJa+KK2
+xwJ/1uLsNG+I04lSQCsRr4/z23O6Vc2VzmMpru6Upa9mL8aNiUm2+7VJje/NnUW5
+OXiSxbYGchYbO7+sIo8UmSpm7wKBgQDHAFLoBZOeh1BGnD0YNH7WYJ4kH9IriFcB
+QqJL8yFjikbUU976yAyXNbMIVBMkCZoT/l7RvgwLufarKTzRHv88nCPwg8/sbQQT
+WP4TRcxS6zZj4y0VHN2i0KSldAYk1ohgLFXzAQzXVcMBzNNOdSSLtqRbPZo9Gd7U
+DYaHxRIVdQKBgQCFykaV7hk/FAm6vF35dZyYzanGyf/t5gmeid0PGFfh34zilzhY
+GFpA4yvm/MHvln4ThC14tHtxvNvphrYZPn4+ni6xmrjyWmvN7Zr00XkJYjPK06B8
+x11Zpyf6KOPo9EGEyn3Vahm6qqYYj1EjV5e1V0MsL3cD7J4vIz4x4ka9oQKBgQCN
+9tQuQ7Qw1rVU+ia3etO1Wc3XVYAYoDX5ZzDi37rFCSNIW+DppQceZCepXFkfT15E
+vyWjmWF8iBjJuCxzvxo0ges9rLsLHiZXKxhuZU/DI5t0nN9PfX07pn6ereuoIge+
+HELgjbI8eCkawqVIBleg+BW+JW9AAZGuU0vS1ar19QKBgQC3J57JCl6ZZzGKpFpU
+/9qYA0qFFRBIRddHlfelk7EBqg/6C6yEXAqNO+DcurdU6li+lEOKNSPAqii2MC+H
+XqCIdtbZcOX7pUSg5E8N883ruMjsaePTsvA5iEY5QvA8Mn47wpPikYEXQgFWoP+W
+UFlVhwe/E/ebjJZqyTiQaQcMPQ==
+-----END PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 237 (0xed)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=Test Root CA
+ Validity
+ Not Before: Jun 18 19:52:02 2013 GMT
+ Not After : Jun 16 19:52:02 2023 GMT
+ Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:9b:13:c2:0b:60:42:13:87:db:a9:91:e9:fa:73:
+ ad:73:34:08:9b:46:7a:bb:d2:0e:e0:94:bc:ba:7c:
+ 7a:90:26:ca:c8:57:39:a3:e9:bf:b8:74:72:d8:50:
+ 0d:e6:bb:5d:e9:a9:9c:a8:2b:a6:0f:d4:c3:dd:69:
+ f7:61:db:72:2b:5b:8b:e8:eb:1b:71:0a:9a:90:93:
+ 4a:c0:11:af:b4:72:38:bb:13:ed:35:24:71:2f:3b:
+ 86:35:43:83:52:70:68:fa:db:c1:c3:7b:e7:49:aa:
+ 24:03:01:95:91:0e:02:28:76:52:ab:46:30:f5:5d:
+ 94:fd:d5:4d:14:b2:ec:ad:0e:f6:10:55:b1:08:a2:
+ c8:0c:74:47:af:5b:c1:6f:a9:60:21:0c:7e:9f:91:
+ be:10:e4:e7:56:c1:4c:46:9d:7d:3e:70:72:c8:35:
+ 53:09:bc:2a:0f:ab:e7:c3:41:6c:b8:03:fd:ae:46:
+ 21:67:ff:1f:4d:05:91:33:d8:0c:0d:b5:af:b2:e9:
+ ed:e9:9f:c8:19:13:db:e1:15:ea:9e:dc:9b:fd:b6:
+ 82:19:ce:ca:90:67:f7:c2:58:ae:85:2b:37:e4:c5:
+ 03:58:73:9b:dc:4a:a1:f1:f7:a5:6e:0e:1a:ab:6e:
+ 73:c5:76:97:10:7d:10:74:f1:88:38:dd:34:a2:a0:
+ a6:3b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 34:FF:09:84:DB:23:D0:1F:45:72:50:CE:79:28:D3:EF:FB:B1:46:07
+ X509v3 Authority Key Identifier:
+ keyid:2B:88:93:E1:D2:54:50:F4:B8:A4:20:BD:B1:79:E6:0B:AA:EB:EC:1A
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Subject Alternative Name:
+ IP Address:127.0.0.1
+ Signature Algorithm: sha1WithRSAEncryption
+ a6:21:b1:53:7f:ec:a8:23:6f:76:d4:bd:0a:6a:67:a7:a8:9e:
+ 7d:08:38:62:cd:f4:34:d9:41:3a:02:a7:6d:31:7d:33:02:27:
+ ab:06:e6:01:c8:65:32:b5:f3:96:27:4c:5a:82:a5:84:a7:99:
+ 29:4a:b6:b9:57:41:75:a9:e2:a6:87:00:25:ff:5a:85:f6:68:
+ da:e1:5a:19:fb:91:5e:70:27:31:dd:9a:ac:20:9a:d6:27:1c:
+ 55:34:8c:f9:a4:97:ff:81:63:fb:b8:7d:71:d4:42:88:3c:10:
+ db:78:54:e3:42:b1:a4:83:81:b9:92:7a:f6:b2:f2:19:1c:b6:
+ 68:80:2b:14:5a:36:84:e0:67:ad:f9:e4:bc:a1:63:af:a1:13:
+ 13:95:3f:76:5e:2c:81:ed:7c:4a:38:04:bf:dc:03:b0:ca:8b:
+ d3:17:d8:fc:60:d9:83:31:9f:ef:be:a7:e3:05:4f:b4:3e:97:
+ 8a:6d:86:c5:69:ef:93:8c:1b:9e:6e:95:f7:1a:66:f7:1f:bf:
+ 5e:92:c4:ed:15:e1:2e:56:56:11:80:be:02:1d:96:fa:39:6a:
+ e0:dd:04:d7:98:e9:29:72:a5:60:f1:0e:14:5d:08:db:26:18:
+ 42:5b:f3:82:fb:79:83:48:1b:86:8d:9d:8b:5c:87:1a:23:ae:
+ bc:4c:13:46
+-----BEGIN CERTIFICATE-----
+MIIDdDCCAlygAwIBAgICAO0wDQYJKoZIhvcNAQEFBQAwFzEVMBMGA1UEAwwMVGVz
+dCBSb290IENBMB4XDTEzMDYxODE5NTIwMloXDTIzMDYxNjE5NTIwMlowYDELMAkG
+A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWlu
+IFZpZXcxEDAOBgNVBAoMB1Rlc3QgQ0ExEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJsTwgtgQhOH26mR6fpzrXM0CJtG
+ervSDuCUvLp8epAmyshXOaPpv7h0cthQDea7XempnKgrpg/Uw91p92Hbcitbi+jr
+G3EKmpCTSsARr7RyOLsT7TUkcS87hjVDg1JwaPrbwcN750mqJAMBlZEOAih2UqtG
+MPVdlP3VTRSy7K0O9hBVsQiiyAx0R69bwW+pYCEMfp+RvhDk51bBTEadfT5wcsg1
+Uwm8Kg+r58NBbLgD/a5GIWf/H00FkTPYDA21r7Lp7emfyBkT2+EV6p7cm/22ghnO
+ypBn98JYroUrN+TFA1hzm9xKofH3pW4OGqtuc8V2lxB9EHTxiDjdNKKgpjsCAwEA
+AaOBgDB+MAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDT/CYTbI9AfRXJQznko0+/7
+sUYHMB8GA1UdIwQYMBaAFCuIk+HSVFD0uKQgvbF55guq6+waMB0GA1UdJQQWMBQG
+CCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEB
+BQUAA4IBAQCmIbFTf+yoI2921L0KamenqJ59CDhizfQ02UE6AqdtMX0zAierBuYB
+yGUytfOWJ0xagqWEp5kpSra5V0F1qeKmhwAl/1qF9mja4VoZ+5FecCcx3ZqsIJrW
+JxxVNIz5pJf/gWP7uH1x1EKIPBDbeFTjQrGkg4G5knr2svIZHLZogCsUWjaE4Get
++eS8oWOvoRMTlT92XiyB7XxKOAS/3AOwyovTF9j8YNmDMZ/vvqfjBU+0PpeKbYbF
+ae+TjBuebpX3Gmb3H79eksTtFeEuVlYRgL4CHZb6OWrg3QTXmOkpcqVg8Q4UXQjb
+JhhCW/OC+3mDSBuGjZ2LXIcaI668TBNG
+-----END CERTIFICATE-----
diff --git a/chromium/tools/python/google/httpd_config/httpd2_linux.conf b/chromium/tools/python/google/httpd_config/httpd2_linux.conf
new file mode 100644
index 00000000000..27a67e027bf
--- /dev/null
+++ b/chromium/tools/python/google/httpd_config/httpd2_linux.conf
@@ -0,0 +1,144 @@
+# For this to work, you need to have ssl.conf and ssl.load in
+# /etc/apache/mods-enabled. You also need to be able to write to
+# /var/run/apache2. (Tested on Ubuntu Hardy, directory names may
+# vary with other distros.)
+
+Listen 127.0.0.1:8000
+ServerName 127.0.0.1
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 15
+
+##
+## Server-Pool Size Regulation (MPM specific)
+##
+
+# prefork MPM
+# StartServers: number of server processes to start
+# MinSpareServers: minimum number of server processes which are kept spare
+# MaxSpareServers: maximum number of server processes which are kept spare
+# MaxClients: maximum number of server processes allowed to start
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule mpm_prefork_module>
+ StartServers 5
+ MinSpareServers 5
+ MaxSpareServers 10
+ MaxClients 150
+ MaxRequestsPerChild 0
+</IfModule>
+
+# worker MPM
+# StartServers: initial number of server processes to start
+# MaxClients: maximum number of simultaneous client connections
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestsPerChild: maximum number of requests a server process serves
+<IfModule mpm_worker_module>
+ StartServers 2
+ MaxClients 150
+ MinSpareThreads 25
+ MaxSpareThreads 75
+ ThreadsPerChild 25
+ MaxRequestsPerChild 0
+</IfModule>
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for additional configuration directives. See also the AllowOverride
+# directive.
+#
+
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess and .htpasswd files from being
+# viewed by Web clients.
+#
+<Files ~ "^\.ht">
+ Order allow,deny
+ Deny from all
+</Files>
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value. If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+Include /etc/apache2/mods-enabled/*.load
+Include /etc/apache2/mods-enabled/*.conf
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+# If you are behind a reverse proxy, you might want to change %h into %{X-Forwarded-For}i
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+#
+# ServerTokens
+# This directive configures what you return as the Server HTTP response
+# Header. The default is 'Full' which sends information about the OS-Type
+# and compiled in modules.
+# Set to one of: Full | OS | Minor | Minimal | Major | Prod
+# where Full conveys the most information, and Prod the least.
+#
+ServerTokens Full
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (internal error documents, FTP directory
+# listings, mod_status and mod_info output etc., but not CGI generated
+# documents or custom error documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#
+ServerSignature On
diff --git a/chromium/tools/python/google/httpd_config/httpd2_mac.conf b/chromium/tools/python/google/httpd_config/httpd2_mac.conf
new file mode 100644
index 00000000000..07f88999b85
--- /dev/null
+++ b/chromium/tools/python/google/httpd_config/httpd2_mac.conf
@@ -0,0 +1,229 @@
+## httpd2.conf -- Apache 2.x HTTP server configuration file
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+Listen 127.0.0.1:8000
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Please read the file http://httpd.apache.org/docs/dso.html for more
+# details about the DSO mechanism and run `httpd -l' for the list of already
+# built-in (statically linked and thus always available) modules in your httpd
+# binary.
+#
+# Note: The order in which modules are loaded is important. Don't change
+# the order below without expert advice.
+#
+# NOTE: This is not the same set of modules that gets loaded on win.
+LoadModule authz_host_module libexec/apache2/mod_authz_host.so
+LoadModule mime_module libexec/apache2/mod_mime.so
+LoadModule ssl_module libexec/apache2/mod_ssl.so
+LoadModule autoindex_module libexec/apache2/mod_autoindex.so
+LoadModule alias_module libexec/apache2/mod_alias.so
+LoadModule log_config_module libexec/apache2/mod_log_config.so
+
+#LoadModule include_module libexec/apache2/mod_include.so
+#LoadModule headers_module libexec/apache2/mod_headers.so
+#LoadModule asis_module libexec/apache2/mod_asis.so
+#LoadModule cgi_module libexec/apache2/mod_cgi.so
+#LoadModule negotiation_module libexec/apache2/mod_negotiation.so
+#LoadModule imagemap_module libexec/apache2/mod_imagemap.so
+#LoadModule actions_module libexec/apache2/mod_actions.so
+#LoadModule rewrite_module libexec/apache2/mod_rewrite.so
+
+
+#
+# Each directory to which Apache has access, can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories).
+#
+<Directory />
+ Options Indexes FollowSymLinks MultiViews ExecCGI Includes
+ AllowOverride All
+ Order allow,deny
+ Allow from all
+</Directory>
+
+
+#
+# Apple specific filesystem protection.
+
+<Files "rsrc">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Files>
+<Directory ~ ".*\.\.namedfork">
+ Order allow,deny
+ Deny from all
+ Satisfy All
+</Directory>
+
+
+#
+# UseCanonicalName: (new for 1.3) With this setting turned on, whenever
+# Apache needs to construct a self-referencing URL (a URL that refers back
+# to the server the response is coming from) it will use ServerName and
+# Port to form a "canonical" name. With this setting off, Apache will
+# use the hostname:port that the client supplied, when possible. This
+# also affects SERVER_NAME and SERVER_PORT in CGI scripts.
+#
+UseCanonicalName On
+
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (error documents, FTP directory listings,
+# mod_status and mod_info output etc., but not CGI generated documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of: On | Off | EMail
+#
+ServerSignature On
+
+
+#
+# Document types.
+#
+<IfModule mime_module>
+
+ #
+ # AddLanguage allows you to specify the language of a document. You can
+ # then use content negotiation to give a browser a file in a language
+ # it can understand.
+ #
+ # Note 1: The suffix does not have to be the same as the language
+ # keyword --- those with documents in Polish (whose net-standard
+ # language code is pl) may wish to use "AddLanguage pl .po" to
+ # avoid the ambiguity with the common suffix for perl scripts.
+ #
+ # Note 2: The example entries below illustrate that in quite
+ # some cases the two character 'Language' abbreviation is not
+ # identical to the two character 'Country' code for its country,
+ # E.g. 'Danmark/dk' versus 'Danish/da'.
+ #
+ # Note 3: In the case of 'ltz' we violate the RFC by using a three char
+ # specifier. But there is 'work in progress' to fix this and get
+ # the reference data for rfc1766 cleaned up.
+ #
+ # Danish (da) - Dutch (nl) - English (en) - Estonian (ee)
+ # French (fr) - German (de) - Greek-Modern (el)
+ # Italian (it) - Korean (kr) - Norwegian (no) - Norwegian Nynorsk (nn)
+ # Portugese (pt) - Luxembourgeois* (ltz)
+ # Spanish (es) - Swedish (sv) - Catalan (ca) - Czech(cs)
+ # Polish (pl) - Brazilian Portuguese (pt-br) - Japanese (ja)
+ # Russian (ru)
+ #
+ AddLanguage da .dk
+ AddLanguage nl .nl
+ AddLanguage en .en
+ AddLanguage et .ee
+ AddLanguage fr .fr
+ AddLanguage de .de
+ AddLanguage el .el
+ AddLanguage he .he
+ AddCharset ISO-8859-8 .iso8859-8
+ AddLanguage it .it
+ AddLanguage ja .ja
+ AddCharset ISO-2022-JP .jis
+ AddLanguage kr .kr
+ AddCharset ISO-2022-KR .iso-kr
+ AddLanguage nn .nn
+ AddLanguage no .no
+ AddLanguage pl .po
+ AddCharset ISO-8859-2 .iso-pl
+ AddLanguage pt .pt
+ AddLanguage pt-br .pt-br
+ AddLanguage ltz .lu
+ AddLanguage ca .ca
+ AddLanguage es .es
+ AddLanguage sv .sv
+ AddLanguage cs .cz .cs
+ AddLanguage ru .ru
+ AddLanguage zh-TW .zh-tw
+ AddCharset Big5 .Big5 .big5
+ AddCharset WINDOWS-1251 .cp-1251
+ AddCharset CP866 .cp866
+ AddCharset ISO-8859-5 .iso-ru
+ AddCharset KOI8-R .koi8-r
+ AddCharset UCS-2 .ucs2
+ AddCharset UCS-4 .ucs4
+ AddCharset UTF-8 .utf8
+
+ # LanguagePriority allows you to give precedence to some languages
+ # in case of a tie during content negotiation.
+ #
+ # Just list the languages in decreasing order of preference. We have
+ # more or less alphabetized them here. You probably want to change this.
+ #
+ <IfModule negotiation_module>
+ LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ru ltz ca es sv tw
+ </IfModule>
+
+ #
+ # AddType allows you to tweak mime.types without actually editing it, or to
+ # make certain files to be certain types.
+ #
+ AddType application/x-tar .tgz
+
+ #
+ # AddEncoding allows you to have certain browsers uncompress
+ # information on the fly. Note: Not all browsers support this.
+ # Despite the name similarity, the following Add* directives have nothing
+ # to do with the FancyIndexing customization directives above.
+ #
+ AddEncoding x-compress .Z
+ AddEncoding x-gzip .gz .tgz
+
+ #
+ # AddHandler allows you to map certain file extensions to "handlers",
+ # actions unrelated to filetype. These can be either built into the server
+ # or added with the Action command (see below)
+ #
+ # If you want to use server side includes, or CGI outside
+ # ScriptAliased directories, uncomment the following lines.
+ #
+ # To use CGI scripts:
+ #
+ AddHandler cgi-script .cgi .pl
+
+ #
+ # To use server-parsed HTML files
+ #
+ AddType text/html .shtml
+ AddHandler server-parsed .shtml
+
+ #
+ # Uncomment the following line to enable Apache's send-asis HTTP file
+ # feature
+ #
+ AddHandler send-as-is asis
+</IfModule>
+
+
+<IfModule php5_module>
+ AddType application/x-httpd-php .php
+ AddType application/x-httpd-php-source .phps
+</IfModule>
+
+<IfModule rewrite_module>
+ RewriteEngine On
+ RewriteCond %{REQUEST_METHOD} ^TRACE
+ RewriteRule .* - [F]
+</IfModule>
diff --git a/chromium/tools/python/google/httpd_config/mime.types b/chromium/tools/python/google/httpd_config/mime.types
new file mode 100644
index 00000000000..6735f1b0e15
--- /dev/null
+++ b/chromium/tools/python/google/httpd_config/mime.types
@@ -0,0 +1,599 @@
+# This is a comment. I love comments.
+
+# This file controls what Internet media types are sent to the client for
+# given file extension(s). Sending the correct media type to the client
+# is important so they know how to handle the content of the file.
+# Extra types can either be added here or by using an AddType directive
+# in your config files. For more information about Internet media types,
+# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type
+# registry is at <http://www.iana.org/assignments/media-types/>.
+
+# MIME type Extensions
+application/activemessage
+application/andrew-inset ez
+application/applefile
+application/atom+xml atom
+application/atomicmail
+application/batch-smtp
+application/beep+xml
+application/cals-1840
+application/cnrp+xml
+application/commonground
+application/cpl+xml
+application/cybercash
+application/dca-rft
+application/dec-dx
+application/dvcs
+application/edi-consent
+application/edifact
+application/edi-x12
+application/eshop
+application/font-tdpfr
+application/http
+application/hyperstudio
+application/iges
+application/index
+application/index.cmd
+application/index.obj
+application/index.response
+application/index.vnd
+application/iotp
+application/ipp
+application/isup
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+application/macwriteii
+application/marc
+application/mathematica
+application/mathml+xml mathml
+application/msword doc
+application/news-message-id
+application/news-transmission
+application/ocsp-request
+application/ocsp-response
+application/octet-stream bin dms lha lzh exe class so dll dmg
+application/oda oda
+application/ogg ogg
+application/parityfec
+application/pdf pdf
+application/pgp-encrypted
+application/pgp-keys
+application/pgp-signature
+application/pkcs10
+application/pkcs7-mime
+application/pkcs7-signature
+application/pkix-cert
+application/pkix-crl
+application/pkixcmp
+application/postscript ai eps ps
+application/prs.alvestrand.titrax-sheet
+application/prs.cww
+application/prs.nprend
+application/prs.plucker
+application/qsig
+application/rdf+xml rdf
+application/reginfo+xml
+application/remote-printing
+application/riscos
+application/rtf
+application/sdp
+application/set-payment
+application/set-payment-initiation
+application/set-registration
+application/set-registration-initiation
+application/sgml
+application/sgml-open-catalog
+application/sieve
+application/slate
+application/smil smi smil
+application/srgs gram
+application/srgs+xml grxml
+application/timestamp-query
+application/timestamp-reply
+application/tve-trigger
+application/vemmi
+application/vnd.3gpp.pic-bw-large
+application/vnd.3gpp.pic-bw-small
+application/vnd.3gpp.pic-bw-var
+application/vnd.3gpp.sms
+application/vnd.3m.post-it-notes
+application/vnd.accpac.simply.aso
+application/vnd.accpac.simply.imp
+application/vnd.acucobol
+application/vnd.acucorp
+application/vnd.adobe.xfdf
+application/vnd.aether.imp
+application/vnd.amiga.ami
+application/vnd.anser-web-certificate-issue-initiation
+application/vnd.anser-web-funds-transfer-initiation
+application/vnd.audiograph
+application/vnd.blueice.multipass
+application/vnd.bmi
+application/vnd.businessobjects
+application/vnd.canon-cpdl
+application/vnd.canon-lips
+application/vnd.cinderella
+application/vnd.claymore
+application/vnd.commerce-battelle
+application/vnd.commonspace
+application/vnd.contact.cmsg
+application/vnd.cosmocaller
+application/vnd.criticaltools.wbs+xml
+application/vnd.ctc-posml
+application/vnd.cups-postscript
+application/vnd.cups-raster
+application/vnd.cups-raw
+application/vnd.curl
+application/vnd.cybank
+application/vnd.data-vision.rdz
+application/vnd.dna
+application/vnd.dpgraph
+application/vnd.dreamfactory
+application/vnd.dxr
+application/vnd.ecdis-update
+application/vnd.ecowin.chart
+application/vnd.ecowin.filerequest
+application/vnd.ecowin.fileupdate
+application/vnd.ecowin.series
+application/vnd.ecowin.seriesrequest
+application/vnd.ecowin.seriesupdate
+application/vnd.enliven
+application/vnd.epson.esf
+application/vnd.epson.msf
+application/vnd.epson.quickanime
+application/vnd.epson.salt
+application/vnd.epson.ssf
+application/vnd.ericsson.quickcall
+application/vnd.eudora.data
+application/vnd.fdf
+application/vnd.ffsns
+application/vnd.fints
+application/vnd.flographit
+application/vnd.framemaker
+application/vnd.fsc.weblaunch
+application/vnd.fujitsu.oasys
+application/vnd.fujitsu.oasys2
+application/vnd.fujitsu.oasys3
+application/vnd.fujitsu.oasysgp
+application/vnd.fujitsu.oasysprs
+application/vnd.fujixerox.ddd
+application/vnd.fujixerox.docuworks
+application/vnd.fujixerox.docuworks.binder
+application/vnd.fut-misnet
+application/vnd.grafeq
+application/vnd.groove-account
+application/vnd.groove-help
+application/vnd.groove-identity-message
+application/vnd.groove-injector
+application/vnd.groove-tool-message
+application/vnd.groove-tool-template
+application/vnd.groove-vcard
+application/vnd.hbci
+application/vnd.hhe.lesson-player
+application/vnd.hp-hpgl
+application/vnd.hp-hpid
+application/vnd.hp-hps
+application/vnd.hp-pcl
+application/vnd.hp-pclxl
+application/vnd.httphone
+application/vnd.hzn-3d-crossword
+application/vnd.ibm.afplinedata
+application/vnd.ibm.electronic-media
+application/vnd.ibm.minipay
+application/vnd.ibm.modcap
+application/vnd.ibm.rights-management
+application/vnd.ibm.secure-container
+application/vnd.informix-visionary
+application/vnd.intercon.formnet
+application/vnd.intertrust.digibox
+application/vnd.intertrust.nncp
+application/vnd.intu.qbo
+application/vnd.intu.qfx
+application/vnd.irepository.package+xml
+application/vnd.is-xpr
+application/vnd.japannet-directory-service
+application/vnd.japannet-jpnstore-wakeup
+application/vnd.japannet-payment-wakeup
+application/vnd.japannet-registration
+application/vnd.japannet-registration-wakeup
+application/vnd.japannet-setstore-wakeup
+application/vnd.japannet-verification
+application/vnd.japannet-verification-wakeup
+application/vnd.jisp
+application/vnd.kde.karbon
+application/vnd.kde.kchart
+application/vnd.kde.kformula
+application/vnd.kde.kivio
+application/vnd.kde.kontour
+application/vnd.kde.kpresenter
+application/vnd.kde.kspread
+application/vnd.kde.kword
+application/vnd.kenameaapp
+application/vnd.koan
+application/vnd.liberty-request+xml
+application/vnd.llamagraphics.life-balance.desktop
+application/vnd.llamagraphics.life-balance.exchange+xml
+application/vnd.lotus-1-2-3
+application/vnd.lotus-approach
+application/vnd.lotus-freelance
+application/vnd.lotus-notes
+application/vnd.lotus-organizer
+application/vnd.lotus-screencam
+application/vnd.lotus-wordpro
+application/vnd.mcd
+application/vnd.mediastation.cdkey
+application/vnd.meridian-slingshot
+application/vnd.micrografx.flo
+application/vnd.micrografx.igx
+application/vnd.mif mif
+application/vnd.minisoft-hp3000-save
+application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf
+application/vnd.mobius.dis
+application/vnd.mobius.mbk
+application/vnd.mobius.mqy
+application/vnd.mobius.msl
+application/vnd.mobius.plc
+application/vnd.mobius.txf
+application/vnd.mophun.application
+application/vnd.mophun.certificate
+application/vnd.motorola.flexsuite
+application/vnd.motorola.flexsuite.adsi
+application/vnd.motorola.flexsuite.fis
+application/vnd.motorola.flexsuite.gotap
+application/vnd.motorola.flexsuite.kmr
+application/vnd.motorola.flexsuite.ttc
+application/vnd.motorola.flexsuite.wem
+application/vnd.mozilla.xul+xml xul
+application/vnd.ms-artgalry
+application/vnd.ms-asf
+application/vnd.ms-excel xls
+application/vnd.ms-lrm
+application/vnd.ms-powerpoint ppt
+application/vnd.ms-project
+application/vnd.ms-tnef
+application/vnd.ms-works
+application/vnd.ms-wpl
+application/vnd.mseq
+application/vnd.msign
+application/vnd.music-niff
+application/vnd.musician
+application/vnd.netfpx
+application/vnd.noblenet-directory
+application/vnd.noblenet-sealer
+application/vnd.noblenet-web
+application/vnd.novadigm.edm
+application/vnd.novadigm.edx
+application/vnd.novadigm.ext
+application/vnd.obn
+application/vnd.osa.netdeploy
+application/vnd.palm
+application/vnd.pg.format
+application/vnd.pg.osasli
+application/vnd.powerbuilder6
+application/vnd.powerbuilder6-s
+application/vnd.powerbuilder7
+application/vnd.powerbuilder7-s
+application/vnd.powerbuilder75
+application/vnd.powerbuilder75-s
+application/vnd.previewsystems.box
+application/vnd.publishare-delta-tree
+application/vnd.pvi.ptid1
+application/vnd.pwg-multiplexed
+application/vnd.pwg-xhtml-print+xml
+application/vnd.quark.quarkxpress
+application/vnd.rapid
+application/vnd.rn-realmedia rm
+application/vnd.s3sms
+application/vnd.sealed.net
+application/vnd.seemail
+application/vnd.shana.informed.formdata
+application/vnd.shana.informed.formtemplate
+application/vnd.shana.informed.interchange
+application/vnd.shana.informed.package
+application/vnd.smaf
+application/vnd.sss-cod
+application/vnd.sss-dtf
+application/vnd.sss-ntf
+application/vnd.street-stream
+application/vnd.svd
+application/vnd.swiftview-ics
+application/vnd.triscape.mxs
+application/vnd.trueapp
+application/vnd.truedoc
+application/vnd.ufdl
+application/vnd.uplanet.alert
+application/vnd.uplanet.alert-wbxml
+application/vnd.uplanet.bearer-choice
+application/vnd.uplanet.bearer-choice-wbxml
+application/vnd.uplanet.cacheop
+application/vnd.uplanet.cacheop-wbxml
+application/vnd.uplanet.channel
+application/vnd.uplanet.channel-wbxml
+application/vnd.uplanet.list
+application/vnd.uplanet.list-wbxml
+application/vnd.uplanet.listcmd
+application/vnd.uplanet.listcmd-wbxml
+application/vnd.uplanet.signal
+application/vnd.vcx
+application/vnd.vectorworks
+application/vnd.vidsoft.vidconference
+application/vnd.visio
+application/vnd.visionary
+application/vnd.vividence.scriptfile
+application/vnd.vsf
+application/vnd.wap.sic
+application/vnd.wap.slc
+application/vnd.wap.wbxml wbxml
+application/vnd.wap.wmlc wmlc
+application/vnd.wap.wmlscriptc wmlsc
+application/vnd.webturbo
+application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf
+application/vnd.wv.csp+wbxml
+application/vnd.xara
+application/vnd.xfdl
+application/vnd.yamaha.hv-dic
+application/vnd.yamaha.hv-script
+application/vnd.yamaha.hv-voice
+application/vnd.yellowriver-custom-menu
+application/voicexml+xml vxml
+application/watcherinfo+xml
+application/whoispp-query
+application/whoispp-response
+application/wita
+application/wordperfect5.1
+application/x-bcpio bcpio
+application/x-cdlink vcd
+application/x-chess-pgn pgn
+application/x-compress
+application/x-cpio cpio
+application/x-csh csh
+application/x-director dcr dir dxr
+application/x-dvi dvi
+application/x-futuresplash spl
+application/x-gtar gtar
+application/x-gzip
+application/x-hdf hdf
+application/x-javascript js
+application/x-java-jnlp-file jnlp
+application/x-koan skp skd skt skm
+application/x-latex latex
+application/x-netcdf nc cdf
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-stuffit sit
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-texinfo texinfo texi
+application/x-troff t tr roff
+application/x-troff-man man
+application/x-troff-me me
+application/x-troff-ms ms
+application/x-ustar ustar
+application/x-wais-source src
+application/x400-bp
+application/xhtml+xml xhtml xht
+application/xslt+xml xslt
+application/xml xml xsl
+application/xml-dtd dtd
+application/xml-external-parsed-entity
+application/zip zip
+audio/32kadpcm
+audio/amr
+audio/amr-wb
+audio/basic au snd
+audio/cn
+audio/dat12
+audio/dsr-es201108
+audio/dvi4
+audio/evrc
+audio/evrc0
+audio/g722
+audio/g.722.1
+audio/g723
+audio/g726-16
+audio/g726-24
+audio/g726-32
+audio/g726-40
+audio/g728
+audio/g729
+audio/g729D
+audio/g729E
+audio/gsm
+audio/gsm-efr
+audio/l8
+audio/l16
+audio/l20
+audio/l24
+audio/lpc
+audio/midi mid midi kar
+audio/mpa
+audio/mpa-robust
+audio/mp4a-latm m4a m4p
+audio/mpeg mpga mp2 mp3
+audio/parityfec
+audio/pcma
+audio/pcmu
+audio/prs.sid
+audio/qcelp
+audio/red
+audio/smv
+audio/smv0
+audio/telephone-event
+audio/tone
+audio/vdvi
+audio/vnd.3gpp.iufp
+audio/vnd.cisco.nse
+audio/vnd.cns.anp1
+audio/vnd.cns.inf1
+audio/vnd.digital-winds
+audio/vnd.everad.plj
+audio/vnd.lucent.voice
+audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800
+audio/vnd.nuera.ecelp7470
+audio/vnd.nuera.ecelp9600
+audio/vnd.octel.sbc
+audio/vnd.qcelp
+audio/vnd.rhetorex.32kadpcm
+audio/vnd.vmx.cvsd
+audio/x-aiff aif aiff aifc
+audio/x-alaw-basic
+audio/x-mpegurl m3u
+audio/x-pn-realaudio ram ra
+audio/x-pn-realaudio-plugin
+audio/x-wav wav
+chemical/x-pdb pdb
+chemical/x-xyz xyz
+image/bmp bmp
+image/cgm cgm
+image/g3fax
+image/gif gif
+image/ief ief
+image/jpeg jpeg jpg jpe
+image/jp2 jp2
+image/naplps
+image/pict pict pic pct
+image/png png
+image/prs.btif
+image/prs.pti
+image/svg+xml svg
+image/t38
+image/tiff tiff tif
+image/tiff-fx
+image/vnd.cns.inf2
+image/vnd.djvu djvu djv
+image/vnd.dwg
+image/vnd.dxf
+image/vnd.fastbidsheet
+image/vnd.fpx
+image/vnd.fst
+image/vnd.fujixerox.edmics-mmr
+image/vnd.fujixerox.edmics-rlc
+image/vnd.globalgraphics.pgb
+image/vnd.mix
+image/vnd.ms-modi
+image/vnd.net-fpx
+image/vnd.svf
+image/vnd.wap.wbmp wbmp
+image/vnd.xiff
+image/x-cmu-raster ras
+image/x-macpaint pntg pnt mac
+image/x-icon ico
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-quicktime qtif qti
+image/x-rgb rgb
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+message/delivery-status
+message/disposition-notification
+message/external-body
+message/http
+message/news
+message/partial
+message/rfc822
+message/s-http
+message/sip
+message/sipfrag
+model/iges igs iges
+model/mesh msh mesh silo
+model/vnd.dwf
+model/vnd.flatland.3dml
+model/vnd.gdl
+model/vnd.gs-gdl
+model/vnd.gtw
+model/vnd.mts
+model/vnd.parasolid.transmit.binary
+model/vnd.parasolid.transmit.text
+model/vnd.vtu
+model/vrml wrl vrml
+multipart/alternative
+multipart/appledouble
+multipart/byteranges
+multipart/digest
+multipart/encrypted
+multipart/form-data
+multipart/header-set
+multipart/mixed
+multipart/parallel
+multipart/related
+multipart/report
+multipart/signed
+multipart/voice-message
+text/calendar ics ifb
+text/css css
+text/directory
+text/enriched
+text/html html htm
+text/parityfec
+text/plain asc txt
+text/prs.lines.tag
+text/rfc822-headers
+text/richtext rtx
+text/rtf rtf
+text/sgml sgml sgm
+text/t140
+text/tab-separated-values tsv
+text/uri-list
+text/vnd.abc
+text/vnd.curl
+text/vnd.dmclientscript
+text/vnd.fly
+text/vnd.fmi.flexstor
+text/vnd.in3d.3dml
+text/vnd.in3d.spot
+text/vnd.iptc.nitf
+text/vnd.iptc.newsml
+text/vnd.latex-z
+text/vnd.motorola.reflex
+text/vnd.ms-mediapackage
+text/vnd.net2phone.commcenter.command
+text/vnd.sun.j2me.app-descriptor
+text/vnd.wap.si
+text/vnd.wap.sl
+text/vnd.wap.wml wml
+text/vnd.wap.wmlscript wmls
+text/x-setext etx
+text/xml
+text/xml-external-parsed-entity
+video/bmpeg
+video/bt656
+video/celb
+video/dv
+video/h261
+video/h263
+video/h263-1998
+video/h263-2000
+video/jpeg
+video/mp1s
+video/mp2p
+video/mp2t
+video/mp4 mp4
+video/mp4v-es
+video/mpv
+video/mpeg mpeg mpg mpe
+video/nv
+video/parityfec
+video/pointer
+video/quicktime qt mov
+video/smpte292m
+video/vnd.fvt
+video/vnd.motorola.video
+video/vnd.motorola.videop
+video/vnd.mpegurl mxu m4u
+video/vnd.nokia.interleaved-multimedia
+video/vnd.objectvideo
+video/vnd.vivo
+video/x-dv dv dif
+video/x-msvideo avi
+video/x-sgi-movie movie
+x-conference/x-cooltalk ice
diff --git a/chromium/tools/python/google/httpd_config/root_ca_cert.pem b/chromium/tools/python/google/httpd_config/root_ca_cert.pem
new file mode 100644
index 00000000000..0e58f2ab5a9
--- /dev/null
+++ b/chromium/tools/python/google/httpd_config/root_ca_cert.pem
@@ -0,0 +1,102 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAq6OEFgWu9ICFgaeoWfq7Dl57BNzERHpBBTedRaFr3uj+D4nT
+OXjraAFPFcBLE6RMJZXtpLvZrfdUDPEzTtcliLAoXmQB8DN8TTvYXEgEr3dSb+qZ
+sAfmbbtjnjOtGJQwlkb0QdZp4+5V3vrD1DbT0XGHKDu4/Estvzzi+4zo+plEDL1d
+y+Op9g09HOu2gB6+pVG1YAR3ckeWFw2ORO76xF+rMRbcaJqfmnmUBLkPFN/Bmvo3
+q39wuIDdSCXtvUNnAcEynXah/sFk2AB3c9E/IYaScuiRNkWEi7cUXrAyXKPtMNo2
+RdvfVUEYz/42N+270wkf1taR0thfcwJS06oNIwIDAQABAoIBAQCml41KurV3h48N
+qydSPnR0m+uXapftRyP45mP2A5lpwIdnmYS00dLbHfoeyIeWRu/Jw13neJTtr5Ob
+BDmimlxJ8YEdLMBc3fwWErILz7MMhCo1imUlYGWduDYWhV3K73rBQZkulegtXVVn
+mcmdHqI1NZXTzTPdXTLH3VcKhVhUcftA+foSmY5Sr2EgWL34lkF0ciWSbYf4dIAc
+RS+DikEpAM552hPu9+oo0+5aheH9ijuF4SCRZcvToC2YaTUR5OG4j31oGtDMXmeu
+5alBhaUZqS3b8FX8Q2GbqJ4sR+2XrgovrVteOGN0QvoExZeZIdt6ArqArKGQ/hQf
+gPITpX7RAoGBANp/9E3a+CB9fculDW/Vdpo2jVMLFmlMzWCxA5V0BwIgx4yCKgK7
+Zx1gsO+vaOKu1uLfAj5wWd1qNRbAAvL0CpSkEqfteHInyyN6muSWuDEELCIYU/0u
+IdhPH7yU/SYKsZK3qnOZBwSJMI0iJAKXO0qVYepTtN3MXzhIWkaPqoj9AoGBAMkY
+qjS/QDmyIukeUrhpEn6F2nh6/Upek0+xFUP/0SIeaCAfFiJ9+mFLSDLQ0Rvsq5G6
+glfMFaQz/+610+6YZ5ioEPUlVMAx0qNZRS8Gy97MDoe9Z+PmbKdvbZXLTP6nhpGy
+9Nhilog+U8MZCwiklDEKyldQBg/TghMsqhYEyFifAoGBAIGJ9obp2M06WQgQ1ISG
+44fN679eBW1sUR6QE3XZkgYa9PNCgDGadSmfl4aiUeaCjXd3i1cFOOHiA5N3RshP
+Eq7JDx5r1UqoePCR0Z7QFGdK9/dGwRSK8xnQ3xnooqSZFmnLZcye3uA7jYM+yGaY
+zlgLdD9+XO5aKeGuU4cdyZbpAoGAIm8cxgdxoe+E1tIga/9h8VROQo8czB1BsEWs
+VIZ7cxIt1kI8cg+MThir9jeXduahwkRjiVEi64kT6/YqohJqutMchD2uM3LUlK/2
+jsTlJ/NdEZU3MukD9e+4ngu/1WMuQciY8GyBRjcV9LRXFVXJIlSsrSLAxvj6rvnY
+7ghHnhUCgYBiKCwWTxuoh450TwZMv8X3/6+88w6CieUa0EvdVDcmSQ1cnlAw/7Uh
+inzU7HizHG2tq8Rg5HjaXTnkNhacT9tg2WELSH8Cay3287CmIhdkvZMJIPRhMMCW
+NUQMCtufqhgyX4Qn0W1dbhBzyuyfsj1Ec3BrUp1aPHr0QRm4HdsAIA==
+-----END RSA PRIVATE KEY-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 12573969073242583322 (0xae7fb6409b5f311a)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=Test Root CA
+ Validity
+ Not Before: Jun 18 19:52:02 2013 GMT
+ Not After : Jun 16 19:52:02 2023 GMT
+ Subject: CN=Test Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:ab:a3:84:16:05:ae:f4:80:85:81:a7:a8:59:fa:
+ bb:0e:5e:7b:04:dc:c4:44:7a:41:05:37:9d:45:a1:
+ 6b:de:e8:fe:0f:89:d3:39:78:eb:68:01:4f:15:c0:
+ 4b:13:a4:4c:25:95:ed:a4:bb:d9:ad:f7:54:0c:f1:
+ 33:4e:d7:25:88:b0:28:5e:64:01:f0:33:7c:4d:3b:
+ d8:5c:48:04:af:77:52:6f:ea:99:b0:07:e6:6d:bb:
+ 63:9e:33:ad:18:94:30:96:46:f4:41:d6:69:e3:ee:
+ 55:de:fa:c3:d4:36:d3:d1:71:87:28:3b:b8:fc:4b:
+ 2d:bf:3c:e2:fb:8c:e8:fa:99:44:0c:bd:5d:cb:e3:
+ a9:f6:0d:3d:1c:eb:b6:80:1e:be:a5:51:b5:60:04:
+ 77:72:47:96:17:0d:8e:44:ee:fa:c4:5f:ab:31:16:
+ dc:68:9a:9f:9a:79:94:04:b9:0f:14:df:c1:9a:fa:
+ 37:ab:7f:70:b8:80:dd:48:25:ed:bd:43:67:01:c1:
+ 32:9d:76:a1:fe:c1:64:d8:00:77:73:d1:3f:21:86:
+ 92:72:e8:91:36:45:84:8b:b7:14:5e:b0:32:5c:a3:
+ ed:30:da:36:45:db:df:55:41:18:cf:fe:36:37:ed:
+ bb:d3:09:1f:d6:d6:91:d2:d8:5f:73:02:52:d3:aa:
+ 0d:23
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 2B:88:93:E1:D2:54:50:F4:B8:A4:20:BD:B1:79:E6:0B:AA:EB:EC:1A
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha1WithRSAEncryption
+ a8:58:42:e4:7c:b1:46:11:ee:56:b7:09:08:fb:06:44:f0:a9:
+ 60:03:f0:05:23:09:3c:36:d6:28:1b:e5:d6:61:15:a0:6f:de:
+ 69:ac:28:58:05:f1:ce:9b:61:c2:58:b0:5d:ed:6c:75:44:e2:
+ 68:01:91:59:b1:4f:f3:51:f2:23:f6:47:42:41:57:26:4f:87:
+ 1e:d2:9f:94:3a:e2:d0:4e:6f:02:d2:92:76:2c:0a:dd:58:93:
+ e1:47:b9:02:a3:3d:75:b4:ba:24:70:87:32:87:cf:76:4e:a0:
+ 41:8b:86:42:18:55:ed:a5:ae:5d:6a:3a:8c:28:70:4c:f1:c5:
+ 36:6c:ec:01:a9:d6:51:39:32:31:30:24:82:9f:88:d9:f5:c1:
+ 09:6b:5a:6b:f1:95:d3:9d:3f:e0:42:63:fc:b7:32:90:55:56:
+ f2:76:1b:71:38:bd:bd:fb:3b:23:50:46:4c:2c:4e:49:48:52:
+ ea:05:5f:16:f2:98:51:af:2f:79:36:2a:a0:ba:36:68:1b:29:
+ 8b:7b:e8:8c:ea:73:31:e5:86:d7:2c:d8:56:06:43:d7:72:d2:
+ f0:27:4e:64:0a:2b:27:38:36:cd:be:c1:33:db:74:4b:4e:74:
+ be:21:bd:f6:81:66:d2:fd:2b:7f:f4:55:36:c0:ed:a7:44:ca:
+ b1:78:1d:0f
+-----BEGIN CERTIFICATE-----
+MIIC8zCCAdugAwIBAgIJAK5/tkCbXzEaMA0GCSqGSIb3DQEBBQUAMBcxFTATBgNV
+BAMMDFRlc3QgUm9vdCBDQTAeFw0xMzA2MTgxOTUyMDJaFw0yMzA2MTYxOTUyMDJa
+MBcxFTATBgNVBAMMDFRlc3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAKujhBYFrvSAhYGnqFn6uw5eewTcxER6QQU3nUWha97o/g+J0zl4
+62gBTxXASxOkTCWV7aS72a33VAzxM07XJYiwKF5kAfAzfE072FxIBK93Um/qmbAH
+5m27Y54zrRiUMJZG9EHWaePuVd76w9Q209Fxhyg7uPxLLb884vuM6PqZRAy9Xcvj
+qfYNPRzrtoAevqVRtWAEd3JHlhcNjkTu+sRfqzEW3Gian5p5lAS5DxTfwZr6N6t/
+cLiA3Ugl7b1DZwHBMp12of7BZNgAd3PRPyGGknLokTZFhIu3FF6wMlyj7TDaNkXb
+31VBGM/+Njftu9MJH9bWkdLYX3MCUtOqDSMCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUK4iT4dJUUPS4pCC9sXnmC6rr7BowDgYDVR0PAQH/BAQD
+AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCoWELkfLFGEe5WtwkI+wZE8KlgA/AFIwk8
+NtYoG+XWYRWgb95prChYBfHOm2HCWLBd7Wx1ROJoAZFZsU/zUfIj9kdCQVcmT4ce
+0p+UOuLQTm8C0pJ2LArdWJPhR7kCoz11tLokcIcyh892TqBBi4ZCGFXtpa5dajqM
+KHBM8cU2bOwBqdZROTIxMCSCn4jZ9cEJa1pr8ZXTnT/gQmP8tzKQVVbydhtxOL29
++zsjUEZMLE5JSFLqBV8W8phRry95NiqgujZoGymLe+iM6nMx5YbXLNhWBkPXctLw
+J05kCisnODbNvsEz23RLTnS+Ib32gWbS/St/9FU2wO2nRMqxeB0P
+-----END CERTIFICATE-----
diff --git a/chromium/tools/python/google/httpd_utils.py b/chromium/tools/python/google/httpd_utils.py
new file mode 100755
index 00000000000..4a03ffc7fb0
--- /dev/null
+++ b/chromium/tools/python/google/httpd_utils.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A class to help start/stop a local apache http server."""
+
+import logging
+import optparse
+import os
+import subprocess
+import sys
+import time
+import urllib
+
+import google.path_utils
+import google.platform_utils
+
+class HttpdNotStarted(Exception): pass
+
+def UrlIsAlive(url):
+ """Checks to see if we get an http response from |url|.
+ We poll the url 5 times with a 1 second delay. If we don't
+ get a reply in that time, we give up and assume the httpd
+ didn't start properly.
+
+ Args:
+ url: The URL to check.
+ Return:
+ True if the url is alive.
+ """
+ wait_time = 5
+ while wait_time > 0:
+ try:
+ response = urllib.urlopen(url)
+ # Server is up and responding.
+ return True
+ except IOError:
+ pass
+ wait_time -= 1
+ # Wait a second and try again.
+ time.sleep(1)
+
+ return False
+
+def ApacheConfigDir(start_dir):
+ """Returns a path to the directory holding the Apache config files."""
+ return google.path_utils.FindUpward(start_dir, 'tools', 'python',
+ 'google', 'httpd_config')
+
+
+def GetCygserverPath(start_dir, apache2=False):
+ """Returns the path to the directory holding cygserver.exe file."""
+ cygserver_path = None
+ if apache2:
+ cygserver_path = google.path_utils.FindUpward(start_dir, 'third_party',
+ 'cygwin', 'usr', 'sbin')
+ return cygserver_path
+
+
+def StartServer(document_root=None, output_dir=None, apache2=False):
+ """Starts a local server on port 8000 using the basic configuration files.
+
+ Args:
+ document_root: If present, specifies the document root for the server;
+ otherwise, the filesystem's root (e.g., C:/ or /) will be used.
+ output_dir: If present, specifies where to put server logs; otherwise,
+ they'll be placed in the system's temp dir (e.g., $TEMP or /tmp).
+ apache2: boolean if true will cause this function to configure
+ for Apache 2.x as opposed to Apache 1.3.x
+
+ Returns: the ApacheHttpd object that was created
+ """
+ script_dir = google.path_utils.ScriptDir()
+ platform_util = google.platform_utils.PlatformUtility(script_dir)
+ if not output_dir:
+ output_dir = platform_util.GetTempDirectory()
+ if not document_root:
+ document_root = platform_util.GetFilesystemRoot()
+ apache_config_dir = ApacheConfigDir(script_dir)
+ if apache2:
+ httpd_conf_path = os.path.join(apache_config_dir, 'httpd2.conf')
+ else:
+ httpd_conf_path = os.path.join(apache_config_dir, 'httpd.conf')
+ mime_types_path = os.path.join(apache_config_dir, 'mime.types')
+ start_cmd = platform_util.GetStartHttpdCommand(output_dir,
+ httpd_conf_path,
+ mime_types_path,
+ document_root,
+ apache2=apache2)
+ stop_cmd = platform_util.GetStopHttpdCommand()
+ httpd = ApacheHttpd(start_cmd, stop_cmd, [8000],
+ cygserver_path=GetCygserverPath(script_dir, apache2))
+ httpd.StartServer()
+ return httpd
+
+
+def StopServers(apache2=False):
+ """Calls the platform's stop command on a newly created server, forcing it
+ to stop.
+
+ The details depend on the behavior of the platform stop command. For example,
+ it's often implemented to kill all running httpd processes, as implied by
+ the name of this function.
+
+ Args:
+ apache2: boolean if true will cause this function to configure
+ for Apache 2.x as opposed to Apache 1.3.x
+ """
+ script_dir = google.path_utils.ScriptDir()
+ platform_util = google.platform_utils.PlatformUtility(script_dir)
+ httpd = ApacheHttpd('', platform_util.GetStopHttpdCommand(), [],
+ cygserver_path=GetCygserverPath(script_dir, apache2))
+ httpd.StopServer(force=True)
+
+
+class ApacheHttpd(object):
+ def __init__(self, start_command, stop_command, port_list,
+ cygserver_path=None):
+ """Args:
+ start_command: command list to call to start the httpd
+ stop_command: command list to call to stop the httpd if one has been
+ started. May kill all httpd processes running on the machine.
+ port_list: list of ports expected to respond on the local machine when
+ the server has been successfully started.
+ cygserver_path: Path to cygserver.exe. If specified, exe will be started
+ with server as well as stopped when server is stopped.
+ """
+ self._http_server_proc = None
+ self._start_command = start_command
+ self._stop_command = stop_command
+ self._port_list = port_list
+ self._cygserver_path = cygserver_path
+
+ def StartServer(self):
+ if self._http_server_proc:
+ return
+ if self._cygserver_path:
+ cygserver_exe = os.path.join(self._cygserver_path, "cygserver.exe")
+ cygbin = google.path_utils.FindUpward(cygserver_exe, 'third_party',
+ 'cygwin', 'bin')
+ env = os.environ
+ env['PATH'] += ";" + cygbin
+ subprocess.Popen(cygserver_exe, env=env)
+ logging.info('Starting http server')
+ self._http_server_proc = subprocess.Popen(self._start_command)
+
+ # Ensure that the server is running on all the desired ports.
+ for port in self._port_list:
+ if not UrlIsAlive('http://127.0.0.1:%s/' % str(port)):
+ raise HttpdNotStarted('Failed to start httpd on port %s' % str(port))
+
+ def StopServer(self, force=False):
+ """If we started an httpd.exe process, or if force is True, call
+ self._stop_command (passed in on init so it can be platform-dependent).
+ This will presumably kill it, and may also kill any other httpd.exe
+ processes that are running.
+ """
+ if force or self._http_server_proc:
+ logging.info('Stopping http server')
+ kill_proc = subprocess.Popen(self._stop_command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ logging.info('%s\n%s' % (kill_proc.stdout.read(),
+ kill_proc.stderr.read()))
+ self._http_server_proc = None
+ if self._cygserver_path:
+ subprocess.Popen(["taskkill.exe", "/f", "/im", "cygserver.exe"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+
+def main():
+ # Provide some command line params for starting/stopping the http server
+ # manually.
+ option_parser = optparse.OptionParser()
+ option_parser.add_option('-k', '--server', help='Server action (start|stop)')
+ option_parser.add_option('-r', '--root', help='Document root (optional)')
+ option_parser.add_option('-a', '--apache2', action='store_true',
+ default=False, help='Starts Apache 2 instead of Apache 1.3 (default). '
+ 'Ignored on Mac (apache2 is used always)')
+ options, args = option_parser.parse_args()
+
+ if not options.server:
+ print ("Usage: %s -k {start|stop} [-r document_root] [--apache2]" %
+ sys.argv[0])
+ return 1
+
+ document_root = None
+ if options.root:
+ document_root = options.root
+
+ if 'start' == options.server:
+ StartServer(document_root, apache2=options.apache2)
+ else:
+ StopServers(apache2=options.apache2)
+
+
+if '__main__' == __name__:
+ sys.exit(main())
diff --git a/chromium/tools/python/google/logging_utils.py b/chromium/tools/python/google/logging_utils.py
new file mode 100644
index 00000000000..ef2d674950f
--- /dev/null
+++ b/chromium/tools/python/google/logging_utils.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+''' Utility functions and objects for logging.
+'''
+
+import logging
+import sys
+
+class StdoutStderrHandler(logging.Handler):
+ ''' Subclass of logging.Handler which outputs to either stdout or stderr
+ based on a threshold level.
+ '''
+
+ def __init__(self, threshold=logging.WARNING, err=sys.stderr, out=sys.stdout):
+ ''' Args:
+ threshold: below this logging level messages are sent to stdout,
+ otherwise they are sent to stderr
+ err: a stream object that error messages are sent to, defaults to
+ sys.stderr
+ out: a stream object that non-error messages are sent to, defaults to
+ sys.stdout
+ '''
+ logging.Handler.__init__(self)
+ self._err = logging.StreamHandler(err)
+ self._out = logging.StreamHandler(out)
+ self._threshold = threshold
+ self._last_was_err = False
+
+ def setLevel(self, lvl):
+ logging.Handler.setLevel(self, lvl)
+ self._err.setLevel(lvl)
+ self._out.setLevel(lvl)
+
+ def setFormatter(self, formatter):
+ logging.Handler.setFormatter(self, formatter)
+ self._err.setFormatter(formatter)
+ self._out.setFormatter(formatter)
+
+ def emit(self, record):
+ if record.levelno < self._threshold:
+ self._out.emit(record)
+ self._last_was_err = False
+ else:
+ self._err.emit(record)
+ self._last_was_err = False
+
+ def flush(self):
+ # preserve order on the flushing, the stalest stream gets flushed first
+ if self._last_was_err:
+ self._out.flush()
+ self._err.flush()
+ else:
+ self._err.flush()
+ self._out.flush()
+
+
+FORMAT = "%(asctime)s %(filename)s [%(levelname)s] %(message)s"
+DATEFMT = "%H:%M:%S"
+
+def config_root(level=logging.INFO, threshold=logging.WARNING, format=FORMAT,
+ datefmt=DATEFMT):
+ ''' Configure the root logger to use a StdoutStderrHandler and some default
+ formatting.
+ Args:
+ level: messages below this level are ignored
+ threshold: below this logging level messages are sent to stdout,
+ otherwise they are sent to stderr
+ format: format for log messages, see logger.Format
+ datefmt: format for date in log messages
+
+ '''
+ # to set the handler of the root logging object, we need to do setup
+ # manually rather than using basicConfig
+ root = logging.getLogger()
+ root.setLevel(level)
+ formatter = logging.Formatter(format, datefmt)
+ handler = StdoutStderrHandler(threshold=threshold)
+ handler.setLevel(level)
+ handler.setFormatter(formatter)
+ root.addHandler(handler)
diff --git a/chromium/tools/python/google/path_utils.py b/chromium/tools/python/google/path_utils.py
new file mode 100644
index 00000000000..6ab43120434
--- /dev/null
+++ b/chromium/tools/python/google/path_utils.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Some utility methods for getting and manipulating paths."""
+
+# TODO(pamg): Have the buildbot use these, too.
+
+
+import errno
+import os
+import sys
+
+class PathNotFound(Exception): pass
+
+def ScriptDir():
+ """Get the full path to the directory containing the current script."""
+ script_filename = os.path.abspath(sys.argv[0])
+ return os.path.dirname(script_filename)
+
+def FindAncestor(start_dir, ancestor):
+ """Finds an ancestor dir in a path.
+
+ For example, FindAncestor('c:\foo\bar\baz', 'bar') would return
+ 'c:\foo\bar'. Unlike FindUpward*, this only looks at direct path ancestors.
+ """
+ start_dir = os.path.abspath(start_dir)
+ path = start_dir
+ while True:
+ (parent, tail) = os.path.split(path)
+ if tail == ancestor:
+ return path
+ if not tail:
+ break
+ path = parent
+ raise PathNotFound("Unable to find ancestor %s in %s" % (ancestor, start_dir))
+
+def FindUpwardParent(start_dir, *desired_list):
+ """Finds the desired object's parent, searching upward from the start_dir.
+
+ Searches start_dir and all its parents looking for the desired directory
+ or file, which may be given in one or more path components. Returns the
+ first directory in which the top desired path component was found, or raises
+ PathNotFound if it wasn't.
+ """
+ desired_path = os.path.join(*desired_list)
+ last_dir = ''
+ cur_dir = start_dir
+ found_path = os.path.join(cur_dir, desired_path)
+ while not os.path.exists(found_path):
+ last_dir = cur_dir
+ cur_dir = os.path.dirname(cur_dir)
+ if last_dir == cur_dir:
+ raise PathNotFound('Unable to find %s above %s' %
+ (desired_path, start_dir))
+ found_path = os.path.join(cur_dir, desired_path)
+ # Strip the entire original desired path from the end of the one found
+ # and remove a trailing path separator, if present.
+ found_path = found_path[:len(found_path) - len(desired_path)]
+ if found_path.endswith(os.sep):
+ found_path = found_path[:len(found_path) - 1]
+ return found_path
+
+
+def FindUpward(start_dir, *desired_list):
+ """Returns a path to the desired directory or file, searching upward.
+
+ Searches start_dir and all its parents looking for the desired directory
+ or file, which may be given in one or more path components. Returns the full
+ path to the desired object, or raises PathNotFound if it wasn't found.
+ """
+ parent = FindUpwardParent(start_dir, *desired_list)
+ return os.path.join(parent, *desired_list)
+
+
+def MaybeMakeDirectory(*path):
+ """Creates an entire path, if it doesn't already exist."""
+ file_path = os.path.join(*path)
+ try:
+ os.makedirs(file_path)
+ except OSError, e:
+ # errno.EEXIST is "File exists". If we see another error, re-raise.
+ if e.errno != errno.EEXIST:
+ raise
diff --git a/chromium/tools/python/google/platform_utils.py b/chromium/tools/python/google/platform_utils.py
new file mode 100644
index 00000000000..50bfb70cc08
--- /dev/null
+++ b/chromium/tools/python/google/platform_utils.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Platform-specific utilities and pseudo-constants
+
+Any functions whose implementations or values differ from one platform to
+another should be defined in their respective platform_utils_<platform>.py
+modules. The appropriate one of those will be imported into this module to
+provide callers with a common, platform-independent interface.
+"""
+
+import sys
+
+# We may not support the version of Python that a user has installed (Cygwin
+# especially has had problems), but we'll allow the platform utils to be
+# included in any case so we don't get an import error.
+if sys.platform in ('cygwin', 'win32'):
+ from platform_utils_win import *
+elif sys.platform == 'darwin':
+ from platform_utils_mac import *
+elif sys.platform.startswith('linux'):
+ from platform_utils_linux import *
diff --git a/chromium/tools/python/google/platform_utils_linux.py b/chromium/tools/python/google/platform_utils_linux.py
new file mode 100644
index 00000000000..237565e3da8
--- /dev/null
+++ b/chromium/tools/python/google/platform_utils_linux.py
@@ -0,0 +1,148 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Platform-specific utility methods shared by several scripts."""
+
+import os
+import subprocess
+
+import google.path_utils
+
+
+class PlatformUtility(object):
+ def __init__(self, base_dir):
+ """Args:
+ base_dir: the base dir for running tests.
+ """
+ self._base_dir = base_dir
+ self._httpd_cmd_string = None # used for starting/stopping httpd
+ self._bash = "/bin/bash"
+
+ def _UnixRoot(self):
+ """Returns the path to root."""
+ return "/"
+
+ def GetFilesystemRoot(self):
+ """Returns the root directory of the file system."""
+ return self._UnixRoot()
+
+ def GetTempDirectory(self):
+ """Returns the file system temp directory
+
+ Note that this does not use a random subdirectory, so it's not
+ intrinsically secure. If you need a secure subdir, use the tempfile
+ package.
+ """
+ return os.getenv("TMPDIR", "/tmp")
+
+ def FilenameToUri(self, path, use_http=False, use_ssl=False, port=8000):
+ """Convert a filesystem path to a URI.
+
+ Args:
+ path: For an http URI, the path relative to the httpd server's
+ DocumentRoot; for a file URI, the full path to the file.
+ use_http: if True, returns a URI of the form http://127.0.0.1:8000/.
+ If False, returns a file:/// URI.
+ use_ssl: if True, returns HTTPS URL (https://127.0.0.1:8000/).
+ This parameter is ignored if use_http=False.
+ port: The port number to append when returning an HTTP URI
+ """
+ if use_http:
+ protocol = 'http'
+ if use_ssl:
+ protocol = 'https'
+ return "%s://127.0.0.1:%d/%s" % (protocol, port, path)
+ return "file://" + path
+
+ def GetStartHttpdCommand(self, output_dir,
+ httpd_conf_path, mime_types_path,
+ document_root=None, apache2=False):
+ """Prepares the config file and output directory to start an httpd server.
+ Returns a list of strings containing the server's command line+args.
+
+ Args:
+ output_dir: the path to the server's output directory, for log files.
+ It will be created if necessary.
+ httpd_conf_path: full path to the httpd.conf file to be used.
+ mime_types_path: full path to the mime.types file to be used.
+ document_root: full path to the DocumentRoot. If None, the DocumentRoot
+ from the httpd.conf file will be used. Note that the httpd.conf
+ file alongside this script does not specify any DocumentRoot, so if
+ you're using that one, be sure to specify a document_root here.
+ apache2: boolean if true will cause this function to return start
+ command for Apache 2.x as opposed to Apache 1.3.x. This flag
+ is ignored on Linux (but preserved here for compatibility in
+ function signature with win), where apache2 is used always
+ """
+
+ exe_name = "apache2"
+ cert_file = google.path_utils.FindUpward(self._base_dir, 'tools',
+ 'python', 'google',
+ 'httpd_config', 'httpd2.pem')
+ ssl_enabled = os.path.exists('/etc/apache2/mods-enabled/ssl.conf')
+
+ httpd_vars = {
+ "httpd_executable_path":
+ os.path.join(self._UnixRoot(), "usr", "sbin", exe_name),
+ "httpd_conf_path": httpd_conf_path,
+ "ssl_certificate_file": cert_file,
+ "document_root" : document_root,
+ "server_root": os.path.join(self._UnixRoot(), "usr"),
+ "mime_types_path": mime_types_path,
+ "output_dir": output_dir,
+ "ssl_mutex": "file:"+os.path.join(output_dir, "ssl_mutex"),
+ "ssl_session_cache":
+ "shmcb:" + os.path.join(output_dir, "ssl_scache") + "(512000)",
+ "user": os.environ.get("USER", "#%d" % os.geteuid()),
+ "lock_file": os.path.join(output_dir, "accept.lock"),
+ }
+
+ google.path_utils.MaybeMakeDirectory(output_dir)
+
+ # We have to wrap the command in bash
+ # -C: process directive before reading config files
+ # -c: process directive after reading config files
+ # Apache wouldn't run CGIs with permissions==700 unless we add
+ # -c User "<username>"
+ httpd_cmd_string = (
+ '%(httpd_executable_path)s'
+ ' -f %(httpd_conf_path)s'
+ ' -c \'TypesConfig "%(mime_types_path)s"\''
+ ' -c \'CustomLog "%(output_dir)s/access_log.txt" common\''
+ ' -c \'ErrorLog "%(output_dir)s/error_log.txt"\''
+ ' -c \'PidFile "%(output_dir)s/httpd.pid"\''
+ ' -C \'User "%(user)s"\''
+ ' -C \'ServerRoot "%(server_root)s"\''
+ ' -c \'LockFile "%(lock_file)s"\''
+ )
+
+ if document_root:
+ httpd_cmd_string += ' -C \'DocumentRoot "%(document_root)s"\''
+
+ if ssl_enabled:
+ httpd_cmd_string += (
+ ' -c \'SSLCertificateFile "%(ssl_certificate_file)s"\''
+ ' -c \'SSLMutex "%(ssl_mutex)s"\''
+ ' -c \'SSLSessionCache "%(ssl_session_cache)s"\''
+ )
+
+ # Save a copy of httpd_cmd_string to use for stopping httpd
+ self._httpd_cmd_string = httpd_cmd_string % httpd_vars
+
+ httpd_cmd = [self._bash, "-c", self._httpd_cmd_string]
+ return httpd_cmd
+
+ def GetStopHttpdCommand(self):
+ """Returns a list of strings that contains the command line+args needed to
+ stop the http server used in the http tests.
+
+ This tries to fetch the pid of httpd (if available) and returns the
+ command to kill it. If pid is not available, kill all httpd processes
+ """
+
+ if not self._httpd_cmd_string:
+ return ["true"] # Haven't been asked for the start cmd yet. Just pass.
+ # Add a sleep after the shutdown because sometimes it takes some time for
+ # the port to be available again.
+ return [self._bash, "-c", self._httpd_cmd_string + ' -k stop && sleep 5']
diff --git a/chromium/tools/python/google/platform_utils_mac.py b/chromium/tools/python/google/platform_utils_mac.py
new file mode 100644
index 00000000000..c4686fb16eb
--- /dev/null
+++ b/chromium/tools/python/google/platform_utils_mac.py
@@ -0,0 +1,145 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Platform-specific utility methods shared by several scripts."""
+
+import os
+import subprocess
+
+import google.path_utils
+
+
+class PlatformUtility(object):
+ def __init__(self, base_dir):
+ """Args:
+ base_dir: the base dir for running tests.
+ """
+ self._base_dir = base_dir
+ self._httpd_cmd_string = None # used for starting/stopping httpd
+ self._bash = "/bin/bash"
+
+ def _UnixRoot(self):
+ """Returns the path to root."""
+ return "/"
+
+ def GetFilesystemRoot(self):
+ """Returns the root directory of the file system."""
+ return self._UnixRoot()
+
+ def GetTempDirectory(self):
+ """Returns the file system temp directory
+
+ Note that this does not use a random subdirectory, so it's not
+ intrinsically secure. If you need a secure subdir, use the tempfile
+ package.
+ """
+ return os.getenv("TMPDIR", "/tmp")
+
+ def FilenameToUri(self, path, use_http=False, use_ssl=False, port=8000):
+ """Convert a filesystem path to a URI.
+
+ Args:
+ path: For an http URI, the path relative to the httpd server's
+ DocumentRoot; for a file URI, the full path to the file.
+ use_http: if True, returns a URI of the form http://127.0.0.1:8000/.
+ If False, returns a file:/// URI.
+ use_ssl: if True, returns HTTPS URL (https://127.0.0.1:8000/).
+ This parameter is ignored if use_http=False.
+ port: The port number to append when returning an HTTP URI
+ """
+ if use_http:
+ protocol = 'http'
+ if use_ssl:
+ protocol = 'https'
+ return "%s://127.0.0.1:%d/%s" % (protocol, port, path)
+ return "file://" + path
+
+ def GetStartHttpdCommand(self, output_dir,
+ httpd_conf_path, mime_types_path,
+ document_root=None, apache2=False):
+ """Prepares the config file and output directory to start an httpd server.
+ Returns a list of strings containing the server's command line+args.
+
+ Args:
+ output_dir: the path to the server's output directory, for log files.
+ It will be created if necessary.
+ httpd_conf_path: full path to the httpd.conf file to be used.
+ mime_types_path: full path to the mime.types file to be used.
+ document_root: full path to the DocumentRoot. If None, the DocumentRoot
+ from the httpd.conf file will be used. Note that the httpd.conf
+ file alongside this script does not specify any DocumentRoot, so if
+ you're using that one, be sure to specify a document_root here.
+ apache2: boolean if true will cause this function to return start
+ command for Apache 2.x as opposed to Apache 1.3.x. This flag
+ is ignored on Mac (but preserved here for compatibility in
+ function signature with win), where httpd2 is used always
+ """
+
+ exe_name = "httpd"
+ cert_file = google.path_utils.FindUpward(self._base_dir, 'tools',
+ 'python', 'google',
+ 'httpd_config', 'httpd2.pem')
+ ssl_enabled = os.path.exists('/etc/apache2/mods-enabled/ssl.conf')
+
+ httpd_vars = {
+ "httpd_executable_path":
+ os.path.join(self._UnixRoot(), "usr", "sbin", exe_name),
+ "httpd_conf_path": httpd_conf_path,
+ "ssl_certificate_file": cert_file,
+ "document_root" : document_root,
+ "server_root": os.path.join(self._UnixRoot(), "usr"),
+ "mime_types_path": mime_types_path,
+ "output_dir": output_dir,
+ "ssl_mutex": "file:"+os.path.join(output_dir, "ssl_mutex"),
+ "user": os.environ.get("USER", "#%d" % os.geteuid()),
+ "lock_file": os.path.join(output_dir, "accept.lock"),
+ }
+
+ google.path_utils.MaybeMakeDirectory(output_dir)
+
+ # We have to wrap the command in bash
+ # -C: process directive before reading config files
+ # -c: process directive after reading config files
+ # Apache wouldn't run CGIs with permissions==700 unless we add
+ # -c User "<username>"
+ httpd_cmd_string = (
+ '%(httpd_executable_path)s'
+ ' -f %(httpd_conf_path)s'
+ ' -c \'TypesConfig "%(mime_types_path)s"\''
+ ' -c \'CustomLog "%(output_dir)s/access_log.txt" common\''
+ ' -c \'ErrorLog "%(output_dir)s/error_log.txt"\''
+ ' -c \'PidFile "%(output_dir)s/httpd.pid"\''
+ ' -C \'User "%(user)s"\''
+ ' -C \'ServerRoot "%(server_root)s"\''
+ ' -c \'LockFile "%(lock_file)s"\''
+ )
+
+ if document_root:
+ httpd_cmd_string += ' -C \'DocumentRoot "%(document_root)s"\''
+
+ if ssl_enabled:
+ httpd_cmd_string += (
+ ' -c \'SSLCertificateFile "%(ssl_certificate_file)s"\''
+ ' -c \'SSLMutex "%(ssl_mutex)s"\''
+ )
+
+ # Save a copy of httpd_cmd_string to use for stopping httpd
+ self._httpd_cmd_string = httpd_cmd_string % httpd_vars
+
+ httpd_cmd = [self._bash, "-c", self._httpd_cmd_string]
+ return httpd_cmd
+
+ def GetStopHttpdCommand(self):
+ """Returns a list of strings that contains the command line+args needed to
+ stop the http server used in the http tests.
+
+ This tries to fetch the pid of httpd (if available) and returns the
+ command to kill it. If pid is not available, kill all httpd processes
+ """
+
+ if not self._httpd_cmd_string:
+ return ["true"] # Haven't been asked for the start cmd yet. Just pass.
+ # Add a sleep after the shutdown because sometimes it takes some time for
+ # the port to be available again.
+ return [self._bash, "-c", self._httpd_cmd_string + ' -k stop && sleep 5']
diff --git a/chromium/tools/python/google/platform_utils_win.py b/chromium/tools/python/google/platform_utils_win.py
new file mode 100644
index 00000000000..65db96c3faa
--- /dev/null
+++ b/chromium/tools/python/google/platform_utils_win.py
@@ -0,0 +1,194 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Platform-specific utility methods shared by several scripts."""
+
+import os
+import re
+import subprocess
+import sys
+
+import google.path_utils
+
+# Cache a single cygpath process for use throughout, even across instances of
+# the PlatformUtility class.
+_cygpath_proc = None
+
+class PlatformUtility(object):
+ def __init__(self, base_dir):
+ """Args:
+ base_dir: a directory above which third_party/cygwin can be found,
+ used to locate the cygpath executable for path conversions.
+ """
+ self._cygwin_root = None
+ self._base_dir = base_dir
+
+ def _CygwinRoot(self):
+ """Returns the full path to third_party/cygwin/."""
+ if not self._cygwin_root:
+ self._cygwin_root = google.path_utils.FindUpward(self._base_dir,
+ 'third_party', 'cygwin')
+ return self._cygwin_root
+
+ def _PathToExecutable(self, executable):
+ """Returns the full path to an executable in Cygwin's bin dir."""
+ return os.path.join(self._CygwinRoot(), 'bin', executable)
+
+ def GetAbsolutePath(self, path, force=False):
+ """Returns an absolute windows path. If platform is cygwin, converts it to
+ windows style using cygpath.
+
+ For performance reasons, we use a single cygpath process, shared among all
+ instances of this class. Otherwise Python can run out of file handles.
+ """
+ if not force and sys.platform != "cygwin":
+ return os.path.abspath(path)
+ global _cygpath_proc
+ if not _cygpath_proc:
+ cygpath_command = [self._PathToExecutable("cygpath.exe"),
+ "-a", "-m", "-f", "-"]
+ _cygpath_proc = subprocess.Popen(cygpath_command,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ _cygpath_proc.stdin.write(path + "\n")
+ return _cygpath_proc.stdout.readline().rstrip()
+
+ def GetFilesystemRoot(self):
+ """Returns the root directory of the file system."""
+ return os.environ['SYSTEMDRIVE'] + '\\'
+
+ def GetTempDirectory(self):
+ """Returns the file system's base temp directory, or the filesystem root
+ if the standard temp directory can't be determined.
+
+ Note that this does not use a random subdirectory, so it's not
+ intrinsically secure. If you need a secure subdir, use the tempfile
+ package.
+ """
+ return os.environ.get('TEMP', self.GetFilesystemRoot())
+
+ def FilenameToUri(self, path, use_http=False, use_ssl=False, port=8000):
+ """Convert a Windows style path to a URI.
+
+ Args:
+ path: For an http URI, the path relative to the httpd server's
+ DocumentRoot; for a file URI, the full path to the file.
+ use_http: if True, returns a URI of the form http://127.0.0.1:8000/.
+ If False, returns a file:/// URI.
+ use_ssl: if True, returns HTTPS URL (https://127.0.0.1:8000/).
+ This parameter is ignored if use_http=False.
+ port: The port number to append when returning an HTTP URI
+ """
+ if use_http:
+ protocol = 'http'
+ if use_ssl:
+ protocol = 'https'
+ path = path.replace("\\", "/")
+ return "%s://127.0.0.1:%s/%s" % (protocol, str(port), path)
+ return "file:///" + self.GetAbsolutePath(path)
+
+ def GetStartHttpdCommand(self, output_dir,
+ httpd_conf_path, mime_types_path,
+ document_root=None, apache2=False):
+ """Prepares the config file and output directory to start an httpd server.
+ Returns a list of strings containing the server's command line+args.
+
+ Args:
+ output_dir: the path to the server's output directory, for log files.
+ It will be created if necessary.
+ httpd_conf_path: full path to the httpd.conf file to be used.
+ mime_types_path: full path to the mime.types file to be used.
+ document_root: full path to the DocumentRoot. If None, the DocumentRoot
+ from the httpd.conf file will be used. Note that the httpd.conf
+ file alongside this script does not specify any DocumentRoot, so if
+ you're using that one, be sure to specify a document_root here.
+ apache2: boolean if true will cause this function to return start
+ command for Apache 2.x as opposed to Apache 1.3.x
+ """
+
+ if document_root:
+ document_root = GetCygwinPath(document_root)
+ exe_name = "httpd"
+ cert_file = ""
+ if apache2:
+ exe_name = "httpd2"
+ cert_file = google.path_utils.FindUpward(self._base_dir, 'tools',
+ 'python', 'google',
+ 'httpd_config', 'httpd2.pem')
+ httpd_vars = {
+ "httpd_executable_path": GetCygwinPath(
+ os.path.join(self._CygwinRoot(), "usr", "sbin", exe_name)),
+ "httpd_conf_path": GetCygwinPath(httpd_conf_path),
+ "ssl_certificate_file": GetCygwinPath(cert_file),
+ "document_root" : document_root,
+ "server_root": GetCygwinPath(os.path.join(self._CygwinRoot(), "usr")),
+ "mime_types_path": GetCygwinPath(mime_types_path),
+ "output_dir": GetCygwinPath(output_dir),
+ "bindir": GetCygwinPath(os.path.join(self._CygwinRoot(), "bin")),
+ "user": os.environ.get("USERNAME", os.environ.get("USER", "")),
+ }
+ if not httpd_vars["user"]:
+ # Failed to get the username from the environment; use whoami.exe
+ # instead.
+ proc = subprocess.Popen(self._PathToExecutable("whoami.exe"),
+ stdout=subprocess.PIPE)
+ httpd_vars["user"] = proc.stdout.read().strip()
+
+ if not httpd_vars["user"]:
+ raise Exception("Failed to get username.")
+
+ google.path_utils.MaybeMakeDirectory(output_dir)
+
+ # We have to wrap the command in bash because the cygwin environment
+ # is required for httpd to run.
+ # -C: process directive before reading config files
+ # -c: process directive after reading config files
+ # Apache wouldn't run CGIs with permissions==700 unless we add
+ # -c User "<username>"
+ bash = self._PathToExecutable("bash.exe")
+ httpd_cmd_string = (
+ ' PATH=%(bindir)s %(httpd_executable_path)s'
+ ' -f %(httpd_conf_path)s'
+ ' -c \'TypesConfig "%(mime_types_path)s"\''
+ ' -c \'CustomLog "%(output_dir)s/access_log.txt" common\''
+ ' -c \'ErrorLog "%(output_dir)s/error_log.txt"\''
+ ' -c \'PidFile "%(output_dir)s/httpd.pid"\''
+ ' -C \'User "%(user)s"\''
+ ' -C \'ServerRoot "%(server_root)s"\''
+ )
+ if apache2:
+ httpd_cmd_string = ('export CYGWIN=server;' + httpd_cmd_string +
+ ' -c \'SSLCertificateFile "%(ssl_certificate_file)s"\'')
+ if document_root:
+ httpd_cmd_string += ' -C \'DocumentRoot "%(document_root)s"\''
+
+ httpd_cmd = [bash, "-c", httpd_cmd_string % httpd_vars]
+ return httpd_cmd
+
+ def GetStopHttpdCommand(self):
+ """Returns a list of strings that contains the command line+args needed to
+ stop the http server used in the http tests.
+ """
+ # Force kill (/f) *all* httpd processes. This has the side effect of
+ # killing httpd processes that we didn't start.
+ return ["taskkill.exe", "/f", "/im", "httpd*"]
+
+###########################################################################
+# This method is specific to windows, expected to be used only by *_win.py
+# files.
+
+def GetCygwinPath(path):
+ """Convert a Windows path to a cygwin path.
+
+ The cygpath utility insists on converting paths that it thinks are Cygwin
+ root paths to what it thinks the correct roots are. So paths such as
+ "C:\b\slave\webkit-release-kjs\build\third_party\cygwin\bin" are converted to
+ plain "/usr/bin". To avoid this, we do the conversion manually.
+
+ The path is expected to be an absolute path, on any drive.
+ """
+ drive_regexp = re.compile(r'([a-z]):[/\\]', re.IGNORECASE)
+ def LowerDrive(matchobj):
+ return '/cygdrive/%s/' % matchobj.group(1).lower()
+ path = drive_regexp.sub(LowerDrive, path)
+ return path.replace('\\', '/')
diff --git a/chromium/tools/python/google/process_utils.py b/chromium/tools/python/google/process_utils.py
new file mode 100644
index 00000000000..64c92ea9f19
--- /dev/null
+++ b/chromium/tools/python/google/process_utils.py
@@ -0,0 +1,221 @@
+# Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Shared process-related utility functions."""
+
+import errno
+import os
+import subprocess
+import sys
+
+class CommandNotFound(Exception): pass
+
+
+TASKKILL = os.path.join(os.environ['WINDIR'], 'system32', 'taskkill.exe')
+TASKKILL_PROCESS_NOT_FOUND_ERR = 128
+# On windows 2000 there is no taskkill.exe, we need to have pskill somewhere
+# in the path.
+PSKILL = 'pskill.exe'
+PSKILL_PROCESS_NOT_FOUND_ERR = -1
+
+def KillAll(executables):
+ """Tries to kill all copies of each process in the processes list. Returns
+ an error if any running processes couldn't be killed.
+ """
+ result = 0
+ if os.path.exists(TASKKILL):
+ command = [TASKKILL, '/f', '/im']
+ process_not_found_err = TASKKILL_PROCESS_NOT_FOUND_ERR
+ else:
+ command = [PSKILL, '/t']
+ process_not_found_err = PSKILL_PROCESS_NOT_FOUND_ERR
+
+ for name in executables:
+ new_error = RunCommand(command + [name])
+ # Ignore "process not found" error.
+ if new_error != 0 and new_error != process_not_found_err:
+ result = new_error
+ return result
+
+def RunCommandFull(command, verbose=True, collect_output=False,
+ print_output=True):
+ """Runs the command list.
+
+ Prints the given command (which should be a list of one or more strings).
+ If specified, prints its stderr (and optionally stdout) to stdout,
+ line-buffered, converting line endings to CRLF (see note below). If
+ specified, collects the output as a list of lines and returns it. Waits
+ for the command to terminate and returns its status.
+
+ Args:
+ command: the full command to run, as a list of one or more strings
+ verbose: if True, combines all output (stdout and stderr) into stdout.
+ Otherwise, prints only the command's stderr to stdout.
+ collect_output: if True, collects the output of the command as a list of
+ lines and returns it
+ print_output: if True, prints the output of the command
+
+ Returns:
+ A tuple consisting of the process's exit status and output. If
+ collect_output is False, the output will be [].
+
+ Raises:
+ CommandNotFound if the command executable could not be found.
+ """
+ print '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n', ###
+
+ if verbose:
+ out = subprocess.PIPE
+ err = subprocess.STDOUT
+ else:
+ out = file(os.devnull, 'w')
+ err = subprocess.PIPE
+ try:
+ proc = subprocess.Popen(command, stdout=out, stderr=err, bufsize=1)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ raise CommandNotFound('Unable to find "%s"' % command[0])
+ raise
+
+ output = []
+
+ if verbose:
+ read_from = proc.stdout
+ else:
+ read_from = proc.stderr
+ line = read_from.readline()
+ while line:
+ line = line.rstrip()
+
+ if collect_output:
+ output.append(line)
+
+ if print_output:
+ # Windows Python converts \n to \r\n automatically whenever it
+ # encounters it written to a text file (including stdout). The only
+ # way around it is to write to a binary file, which isn't feasible for
+ # stdout. So we end up with \r\n here even though we explicitly write
+ # \n. (We could write \r instead, which doesn't get converted to \r\n,
+ # but that's probably more troublesome for people trying to read the
+ # files.)
+ print line + '\n',
+
+ # Python on windows writes the buffer only when it reaches 4k. This is
+ # not fast enough for all purposes.
+ sys.stdout.flush()
+ line = read_from.readline()
+
+ # Make sure the process terminates.
+ proc.wait()
+
+ if not verbose:
+ out.close()
+ return (proc.returncode, output)
+
+def RunCommand(command, verbose=True):
+ """Runs the command list, printing its output and returning its exit status.
+
+ Prints the given command (which should be a list of one or more strings),
+ then runs it and prints its stderr (and optionally stdout) to stdout,
+ line-buffered, converting line endings to CRLF. Waits for the command to
+ terminate and returns its status.
+
+ Args:
+ command: the full command to run, as a list of one or more strings
+ verbose: if True, combines all output (stdout and stderr) into stdout.
+ Otherwise, prints only the command's stderr to stdout.
+
+ Returns:
+ The process's exit status.
+
+ Raises:
+ CommandNotFound if the command executable could not be found.
+ """
+ return RunCommandFull(command, verbose)[0]
+
+def RunCommandsInParallel(commands, verbose=True, collect_output=False,
+ print_output=True):
+ """Runs a list of commands in parallel, waits for all commands to terminate
+ and returns their status. If specified, the ouput of commands can be
+ returned and/or printed.
+
+ Args:
+ commands: the list of commands to run, each as a list of one or more
+ strings.
+ verbose: if True, combines stdout and stderr into stdout.
+ Otherwise, prints only the command's stderr to stdout.
+ collect_output: if True, collects the output of the each command as a list
+ of lines and returns it.
+ print_output: if True, prints the output of each command.
+
+ Returns:
+ A list of tuples consisting of each command's exit status and output. If
+ collect_output is False, the output will be [].
+
+ Raises:
+ CommandNotFound if any of the command executables could not be found.
+ """
+
+ command_num = len(commands)
+ outputs = [[] for i in xrange(command_num)]
+ procs = [None for i in xrange(command_num)]
+ eofs = [False for i in xrange(command_num)]
+
+ for command in commands:
+ print '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n',
+
+ if verbose:
+ out = subprocess.PIPE
+ err = subprocess.STDOUT
+ else:
+ out = file(os.devnull, 'w')
+ err = subprocess.PIPE
+
+ for i in xrange(command_num):
+ try:
+ command = commands[i]
+ procs[i] = subprocess.Popen(command, stdout=out, stderr=err, bufsize=1)
+ except OSError, e:
+ if e.errno == errno.ENOENT:
+ raise CommandNotFound('Unable to find "%s"' % command[0])
+ raise
+ # We could consider terminating the processes already started.
+ # But Popen.kill() is only available in version 2.6.
+ # For now the clean up is done by KillAll.
+
+ while True:
+ eof_all = True
+ for i in xrange(command_num):
+ if eofs[i]:
+ continue
+ if verbose:
+ read_from = procs[i].stdout
+ else:
+ read_from = procs[i].stderr
+ line = read_from.readline()
+ if line:
+ eof_all = False
+ line = line.rstrip()
+ outputs[i].append(line)
+ if print_output:
+ # Windows Python converts \n to \r\n automatically whenever it
+ # encounters it written to a text file (including stdout). The only
+ # way around it is to write to a binary file, which isn't feasible
+ # for stdout. So we end up with \r\n here even though we explicitly
+ # write \n. (We could write \r instead, which doesn't get converted
+ # to \r\n, but that's probably more troublesome for people trying to
+ # read the files.)
+ print line + '\n',
+ else:
+ eofs[i] = True
+ if eof_all:
+ break
+
+ # Make sure the process terminates.
+ for i in xrange(command_num):
+ procs[i].wait()
+
+ if not verbose:
+ out.close()
+
+ return [(procs[i].returncode, outputs[i]) for i in xrange(command_num)]
diff --git a/chromium/tools/run-bisect-manual-test.py b/chromium/tools/run-bisect-manual-test.py
new file mode 100755
index 00000000000..7b038db2bb2
--- /dev/null
+++ b/chromium/tools/run-bisect-manual-test.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Run Manual Test Bisect Tool"""
+
+import os
+import subprocess
+import sys
+
+CROS_BOARD_ENV = 'BISECT_CROS_BOARD'
+CROS_IP_ENV = 'BISECT_CROS_IP'
+_DIR_TOOLS_ROOT = os.path.abspath(os.path.dirname(__file__))
+
+sys.path.append(os.path.join(_DIR_TOOLS_ROOT, 'telemetry'))
+from telemetry.core import browser_options
+
+
+def _RunBisectionScript(options):
+ """Attempts to execute src/tools/bisect-perf-regression.py with the parameters
+ passed in.
+
+ Args:
+ options: The configuration options to pass to the bisect script.
+
+ Returns:
+ 0 on success, otherwise 1.
+ """
+ test_command = 'python %s --browser=%s' %\
+ (os.path.join(_DIR_TOOLS_ROOT, 'bisect-manual-test.py'),
+ options.browser_type)
+
+ cmd = ['python', os.path.join(_DIR_TOOLS_ROOT, 'bisect-perf-regression.py'),
+ '-c', test_command,
+ '-g', options.good_revision,
+ '-b', options.bad_revision,
+ '-m', 'manual_test/manual_test',
+ '-r', '1',
+ '--working_directory', options.working_directory,
+ '--build_preference', 'ninja',
+ '--use_goma']
+
+ if 'cros' in options.browser_type:
+ cmd.extend(['--target_platform', 'cros'])
+
+ if os.environ[CROS_BOARD_ENV] and os.environ[CROS_IP_ENV]:
+ cmd.extend(['--cros_board', os.environ[CROS_BOARD_ENV]])
+ cmd.extend(['--cros_remote_ip', os.environ[CROS_IP_ENV]])
+ else:
+ print 'Error: Cros build selected, but BISECT_CROS_IP or'\
+ 'BISECT_CROS_BOARD undefined.'
+ print
+ return 1
+ elif 'android' in options.browser_type:
+ cmd.extend(['--target_platform', 'android'])
+
+ cmd = [str(c) for c in cmd]
+
+ return_code = subprocess.call(cmd)
+
+ if return_code:
+ print 'Error: bisect-perf-regression.py returned with error %d' %\
+ return_code
+ print
+
+ return return_code
+
+
+def main():
+ usage = ('%prog [options]\n'
+ 'Used to run the bisection script with a manual test.')
+
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser(usage)
+
+ parser.add_option('-b', '--bad_revision',
+ type='str',
+ help='A bad revision to start bisection. ' +
+ 'Must be later than good revision. May be either a git' +
+ ' or svn revision.')
+ parser.add_option('-g', '--good_revision',
+ type='str',
+ help='A revision to start bisection where performance' +
+ ' test is known to pass. Must be earlier than the ' +
+ 'bad revision. May be either a git or svn revision.')
+ parser.add_option('-w', '--working_directory',
+ type='str',
+ help='A working directory to supply to the bisection '
+ 'script, which will use it as the location to checkout '
+ 'a copy of the chromium depot.')
+ options, args = parser.parse_args()
+
+ error_msg = ''
+ if not options.browser_type:
+ error_msg += 'Error: missing required parameter: --browser\n'
+ if not options.working_directory:
+ error_msg += 'Error: missing required parameter: --working_directory\n'
+ if not options.good_revision:
+ error_msg += 'Error: missing required parameter: --good_revision\n'
+ if not options.bad_revision:
+ error_msg += 'Error: missing required parameter: --bad_revision\n'
+
+ if error_msg:
+ print error_msg
+ parser.print_help()
+ return 1
+
+ return _RunBisectionScript(options)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/run-bisect-perf-regression.cfg b/chromium/tools/run-bisect-perf-regression.cfg
new file mode 100644
index 00000000000..ded25d25937
--- /dev/null
+++ b/chromium/tools/run-bisect-perf-regression.cfg
@@ -0,0 +1,89 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Config file for Run Performance Test Bisect Tool
+
+This script is intended for use by anyone that wants to run a remote bisection
+on a range of revisions to look for a performance regression. Modify the config
+below and add the revision range, performance command, and metric. You can then
+run a git try <bot>.
+
+Changes to this file should never be submitted.
+
+Args:
+ 'command': This is the full command line to pass to the
+ bisect-perf-regression.py script in order to execute the test.
+ 'good_revision': An svn or git revision where the metric hadn't regressed yet.
+ 'bad_revision': An svn or git revision sometime after the metric had
+ regressed.
+ 'metric': The name of the metric to parse out from the results of the
+ performance test. You can retrieve the metric by looking at the stdio of
+ the performance test. Look for lines of the format:
+
+ RESULT <graph>: <trace>= <value> <units>
+
+ The metric name is "<graph>/<trace>".
+ 'repeat_count': The number of times to repeat the performance test.
+ 'max_time_minutes': The script will attempt to run the performance test
+ "repeat_count" times, unless it exceeds "max_time_minutes".
+ 'truncate_percent': Discard the highest/lowest % values from performance test.
+
+Sample config:
+
+config = {
+ 'command': './out/Release/performance_ui_tests' +
+ ' --gtest_filter=PageCyclerTest.Intl1File',
+ 'good_revision': '179755',
+ 'bad_revision': '179782',
+ 'metric': 'times/t',
+ 'repeat_count': '20',
+ 'max_time_minutes': '20',
+ 'truncate_percent': '25',
+}
+
+On Windows:
+ - If you're calling a python script you will need to add "python" to
+the command:
+
+config = {
+ 'command': 'python tools/perf/run_measurement -v --browser=release kraken',
+ 'good_revision': '185319',
+ 'bad_revision': '185364',
+ 'metric': 'Total/Total',
+ 'repeat_count': '20',
+ 'max_time_minutes': '20',
+ 'truncate_percent': '25',
+}
+
+
+On ChromeOS:
+ - Script accepts either ChromeOS versions, or unix timestamps as revisions.
+ - You don't need to specify --identity and --remote, they will be added to
+ the command using the bot's BISECT_CROS_IP and BISECT_CROS_BOARD values.
+
+config = {
+ 'command': './tools/perf/run_measurement -v '\
+ '--browser=cros-chrome-guest '\
+ 'dromaeo tools/perf/page_sets/dromaeo/jslibstylejquery.json',
+ 'good_revision': '4086.0.0',
+ 'bad_revision': '4087.0.0',
+ 'metric': 'jslib/jslib',
+ 'repeat_count': '20',
+ 'max_time_minutes': '20',
+ 'truncate_percent': '25',
+}
+
+"""
+
+config = {
+ 'command': '',
+ 'good_revision': '',
+ 'bad_revision': '',
+ 'metric': '',
+ 'repeat_count':'',
+ 'max_time_minutes': '',
+ 'truncate_percent':'',
+}
+
+# Workaround git try issue, see crbug.com/257689
diff --git a/chromium/tools/run-bisect-perf-regression.py b/chromium/tools/run-bisect-perf-regression.py
new file mode 100755
index 00000000000..77f1748d2d3
--- /dev/null
+++ b/chromium/tools/run-bisect-perf-regression.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Run Performance Test Bisect Tool
+
+This script is used by a trybot to run the src/tools/bisect-perf-regression.py
+script with the parameters specified in run-bisect-perf-regression.cfg. It will
+check out a copy of the depot in a subdirectory 'bisect' of the working
+directory provided, and run the bisect-perf-regression.py script there.
+
+"""
+
+import imp
+import optparse
+import os
+import subprocess
+import sys
+import traceback
+
+CROS_BOARD_ENV = 'BISECT_CROS_BOARD'
+CROS_IP_ENV = 'BISECT_CROS_IP'
+
+def LoadConfigFile(path_to_file):
+ """Attempts to load the file 'run-bisect-perf-regression.cfg' as a module
+ and grab the global config dict.
+
+ Args:
+ path_to_file: Path to the run-bisect-perf-regression.cfg file.
+
+ Returns:
+ The config dict which should be formatted as follows:
+ {'command': string, 'good_revision': string, 'bad_revision': string
+ 'metric': string}.
+ Returns None on failure.
+ """
+ try:
+ local_vars = {}
+ execfile(os.path.join(path_to_file, 'run-bisect-perf-regression.cfg'),
+ local_vars)
+
+ return local_vars['config']
+ except:
+ print
+ traceback.print_exc()
+ print
+ return None
+
+
+def RunBisectionScript(config, working_directory, path_to_file, path_to_goma):
+ """Attempts to execute src/tools/bisect-perf-regression.py with the parameters
+ passed in.
+
+ Args:
+ config: A dict containing the parameters to pass to the script.
+ working_directory: A working directory to provide to the
+ bisect-perf-regression.py script, where it will store it's own copy of
+ the depot.
+ path_to_file: Path to the bisect-perf-regression.py script.
+ path_to_goma: Path to goma directory.
+
+ Returns:
+ 0 on success, otherwise 1.
+ """
+
+ cmd = ['python', os.path.join(path_to_file, 'bisect-perf-regression.py'),
+ '-c', config['command'],
+ '-g', config['good_revision'],
+ '-b', config['bad_revision'],
+ '-m', config['metric'],
+ '--working_directory', working_directory,
+ '--output_buildbot_annotations']
+
+ if config['repeat_count']:
+ cmd.extend(['-r', config['repeat_count']])
+
+ if config['truncate_percent']:
+ cmd.extend(['-t', config['truncate_percent']])
+
+ if config['max_time_minutes']:
+ cmd.extend(['--repeat_test_max_time', config['max_time_minutes']])
+
+ cmd.extend(['--build_preference', 'ninja'])
+
+ if '--browser=cros' in config['command']:
+ cmd.extend(['--target_platform', 'cros'])
+
+ if os.environ[CROS_BOARD_ENV] and os.environ[CROS_IP_ENV]:
+ cmd.extend(['--cros_board', os.environ[CROS_BOARD_ENV]])
+ cmd.extend(['--cros_remote_ip', os.environ[CROS_IP_ENV]])
+ else:
+ print 'Error: Cros build selected, but BISECT_CROS_IP or'\
+ 'BISECT_CROS_BOARD undefined.'
+ print
+ return 1
+
+ if '--browser=android' in config['command']:
+ cmd.extend(['--target_platform', 'android'])
+
+ goma_file = ''
+ if path_to_goma:
+ path_to_goma = os.path.abspath(path_to_goma)
+
+ if os.name == 'nt':
+ os.environ['CC'] = os.path.join(path_to_goma, 'gomacc.exe') + ' cl.exe'
+ os.environ['CXX'] = os.path.join(path_to_goma, 'gomacc.exe') + ' cl.exe'
+ goma_file = os.path.join(path_to_goma, 'goma_ctl.bat')
+ else:
+ os.environ['PATH'] = os.pathsep.join([path_to_goma, os.environ['PATH']])
+ goma_file = os.path.join(path_to_goma, 'goma_ctl.sh')
+
+ cmd.append('--use_goma')
+
+ # Sometimes goma is lingering around if something went bad on a previous
+ # run. Stop it before starting a new process. Can ignore the return code
+ # since it will return an error if it wasn't running.
+ subprocess.call([goma_file, 'stop'])
+
+ return_code = subprocess.call([goma_file, 'start'])
+ if return_code:
+ print 'Error: goma failed to start.'
+ print
+ return return_code
+
+ cmd = [str(c) for c in cmd]
+
+ return_code = subprocess.call(cmd)
+
+ if path_to_goma:
+ subprocess.call([goma_file, 'stop'])
+
+ if return_code:
+ print 'Error: bisect-perf-regression.py returned with error %d' %\
+ return_code
+ print
+
+ return return_code
+
+
+def main():
+
+ usage = ('%prog [options] [-- chromium-options]\n'
+ 'Used by a trybot to run the bisection script using the parameters'
+ ' provided in the run-bisect-perf-regression.cfg file.')
+
+ parser = optparse.OptionParser(usage=usage)
+ parser.add_option('-w', '--working_directory',
+ type='str',
+ help='A working directory to supply to the bisection '
+ 'script, which will use it as the location to checkout '
+ 'a copy of the chromium depot.')
+ parser.add_option('-p', '--path_to_goma',
+ type='str',
+ help='Path to goma directory. If this is supplied, goma '
+ 'builds will be enabled.')
+ (opts, args) = parser.parse_args()
+
+ if not opts.working_directory:
+ print 'Error: missing required parameter: --working_directory'
+ print
+ parser.print_help()
+ return 1
+
+ path_to_file = os.path.abspath(os.path.dirname(sys.argv[0]))
+
+ config = LoadConfigFile(path_to_file)
+ if not config:
+ print 'Error: Could not load config file. Double check your changes to '\
+ 'run-bisect-perf-regression.cfg for syntax errors.'
+ print
+ return 1
+
+ return RunBisectionScript(config, opts.working_directory, path_to_file,
+ opts.path_to_goma)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/safely-roll-blink.py b/chromium/tools/safely-roll-blink.py
new file mode 100755
index 00000000000..581aecd5c6b
--- /dev/null
+++ b/chromium/tools/safely-roll-blink.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generate a CL to roll Blink to the specified revision number and post
+it to Rietveld so that the CL will land automatically if it passes the
+commit-queue's checks.
+"""
+
+import logging
+import optparse
+import os
+import re
+import sys
+
+import find_depot_tools
+import scm
+import subprocess2
+
+
+def die_with_error(msg):
+ print >> sys.stderr, msg
+ sys.exit(1)
+
+
+def process_deps(path, new_rev, is_dry_run):
+ """Update webkit_revision to |new_issue|.
+
+ A bit hacky, could it be made better?
+ """
+ content = open(path).read()
+ old_line = r'(\s+)"webkit_revision": "(\d+)",'
+ new_line = r'\1"webkit_revision": "%d",' % new_rev
+ new_content = re.sub(old_line, new_line, content, 1)
+ old_rev = re.search(old_line, content).group(2)
+ if not old_rev or new_content == content:
+ die_with_error('Failed to update the DEPS file')
+
+ if not is_dry_run:
+ open(path, 'w').write(new_content)
+ return old_rev
+
+
+def main():
+ tool_dir = os.path.dirname(os.path.abspath(__file__))
+ parser = optparse.OptionParser(usage='%prog [options] <new blink rev>')
+ parser.add_option('-v', '--verbose', action='count', default=0)
+ parser.add_option('--dry-run', action='store_true')
+ parser.add_option('--commit', action='store_true', default=True,
+ help='(default) Put change in commit queue on upload.')
+ parser.add_option('--no-commit', action='store_false', dest='commit',
+ help='Don\'t put change in commit queue on upload.')
+ parser.add_option('-r', '--reviewers', default='',
+ help='Add given users as either reviewers or TBR as'
+ ' appropriate.')
+ parser.add_option('--upstream', default='origin/master',
+ help='(default "%default") Use given start point for change'
+ ' to upload. For instance, if you use the old git workflow,'
+ ' you might set it to "origin/trunk".')
+ parser.add_option('--cc', help='CC email addresses for issue.')
+
+ options, args = parser.parse_args()
+ logging.basicConfig(
+ level=
+ [logging.WARNING, logging.INFO, logging.DEBUG][
+ min(2, options.verbose)])
+ if len(args) != 1:
+ parser.print_help()
+ exit(0)
+
+ root_dir = os.path.dirname(tool_dir)
+ os.chdir(root_dir)
+
+ new_rev = int(args[0])
+
+ # Silence the editor.
+ os.environ['EDITOR'] = 'true'
+
+ old_branch = scm.GIT.GetBranch(root_dir)
+ if old_branch == 'blink_roll':
+ parser.error(
+ 'Please delete the branch blink_roll and move to a different branch')
+
+ if not options.dry_run:
+ subprocess2.check_output(
+ ['git', 'checkout', '-b', 'blink_roll', options.upstream])
+
+ try:
+ old_rev = int(process_deps(os.path.join(root_dir, 'DEPS'), new_rev,
+ options.dry_run))
+ print 'Blink roll %s:%s' % (old_rev, new_rev)
+
+ review_field = 'TBR' if options.commit else 'R'
+ commit_msg = ('Blink roll %s:%s\n'
+ '\n'
+ 'http://build.chromium.org/f/chromium/perf/dashboard/ui/'
+ 'changelog_blink.html?url=/trunk&range=%s:%s&mode=html'
+ '\n'
+ '%s=%s\n' % (old_rev, new_rev,
+ old_rev+1, new_rev,
+ review_field,
+ options.reviewers))
+
+ if options.dry_run:
+ print 'Commit message: ' + commit_msg
+ return 0
+
+ subprocess2.check_output(['git', 'commit', '-m', commit_msg, 'DEPS'])
+ subprocess2.check_call(['git', 'diff', options.upstream])
+ upload_cmd = ['git', 'cl', 'upload']
+ if options.commit:
+ upload_cmd.append('--use-commit-queue')
+ if options.reviewers:
+ upload_cmd.append('--send-mail')
+ if options.cc:
+ upload_cmd.extend(['--cc', options.cc])
+ subprocess2.check_call(upload_cmd)
+ finally:
+ if not options.dry_run:
+ subprocess2.check_output(['git', 'checkout', old_branch])
+ subprocess2.check_output(['git', 'branch', '-D', 'blink_roll'])
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/set_default_handler/DEPS b/chromium/tools/set_default_handler/DEPS
new file mode 100644
index 00000000000..12a2df7a3fd
--- /dev/null
+++ b/chromium/tools/set_default_handler/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+ui",
+ "+win8/test",
+]
diff --git a/chromium/tools/set_default_handler/set_default_handler.gyp b/chromium/tools/set_default_handler/set_default_handler.gyp
new file mode 100644
index 00000000000..1093aa3f13e
--- /dev/null
+++ b/chromium/tools/set_default_handler/set_default_handler.gyp
@@ -0,0 +1,25 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ 'target_name': 'set_default_handler',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ '../../win8/win8.gyp:test_support_win8',
+ '../../ui/ui.gyp:ui',
+ ],
+ 'include_dirs': [
+ '../..',
+ ],
+ 'sources': [
+ 'set_default_handler_main.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/tools/set_default_handler/set_default_handler_main.cc b/chromium/tools/set_default_handler/set_default_handler_main.cc
new file mode 100644
index 00000000000..7f2d9da3087
--- /dev/null
+++ b/chromium/tools/set_default_handler/set_default_handler_main.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Makes a given program ("Google Chrome" by default) the default handler for
+// some URL protocol ("http" by default) on Windows 8. These defaults can be
+// overridden via the --program and --protocol command line switches.
+
+#include <windows.h>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "ui/base/win/atl_module.h"
+#include "win8/test/open_with_dialog_controller.h"
+
+namespace {
+
+const char kSwitchProgram[] = "program";
+const char kSwitchProtocol[] = "protocol";
+const wchar_t kDefaultProgram[] = L"Google Chrome";
+const wchar_t kDefaultProtocol[] = L"http";
+
+} // namespace
+
+extern "C"
+int wmain(int argc, wchar_t* argv[]) {
+ // Initialize the commandline singleton from the environment.
+ CommandLine::Init(0, NULL);
+ // The exit manager is in charge of calling the dtors of singletons.
+ base::AtExitManager exit_manager;
+ logging::LoggingSettings settings;
+ settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+ settings.dcheck_state =
+ logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
+ logging::InitLogging(settings);
+ logging::SetMinLogLevel(logging::LOG_VERBOSE);
+
+ ui::win::CreateATLModuleIfNeeded();
+
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ string16 protocol(command_line->GetSwitchValueNative(kSwitchProtocol));
+ if (protocol.empty())
+ protocol = kDefaultProtocol;
+
+ string16 program(command_line->GetSwitchValueNative(kSwitchProgram));
+ if (program.empty())
+ program = kDefaultProgram;
+
+ std::vector<string16> choices;
+ HRESULT result = S_OK;
+ win8::OpenWithDialogController controller;
+ result = controller.RunSynchronously(NULL, protocol, program, &choices);
+
+ if (SUCCEEDED(result)) {
+ printf("success\n");
+ } else if (!choices.empty()) {
+ printf("failed to set program. possible choices: %ls\n",
+ JoinString(choices, L", ").c_str());
+ } else {
+ printf("failed with HRESULT: 0x08X\n", result);
+ }
+
+ return FAILED(result);
+}
diff --git a/chromium/tools/sharding_supervisor/PRESUBMIT.py b/chromium/tools/sharding_supervisor/PRESUBMIT.py
new file mode 100644
index 00000000000..2e12d7756e0
--- /dev/null
+++ b/chromium/tools/sharding_supervisor/PRESUBMIT.py
@@ -0,0 +1,24 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for sharding_supervisor.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+def CommonChecks(input_api, output_api):
+ output = []
+ output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+ return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ output = CommonChecks(input_api, output_api)
+ output.extend(input_api.canned_checks.PanProjectChecks(input_api, output_api))
+ return output
diff --git a/chromium/tools/sharding_supervisor/data/gtest_results.xml0 b/chromium/tools/sharding_supervisor/data/gtest_results.xml0
new file mode 100644
index 00000000000..f6bf83a89c0
--- /dev/null
+++ b/chromium/tools/sharding_supervisor/data/gtest_results.xml0
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites name="AllTests" tests="" failures="" disabled="" errors="" time="">
+ <!-- Suite that is run entirely on shard 0 -->
+ <testsuite name="Suite0" tests="1" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="0" classname="Suite0" />
+ </testsuite>
+
+ <!-- Suite that is run entirely on shard 1 -->
+ <testsuite name="Suite1" tests="1" failures="" disabled="" errors="" time="">
+ </testsuite>
+
+ <!-- Suite that has tests run on both shard 0 and shard 1 -->
+ <testsuite name="Suite2" tests="2" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="0" classname="Suite2" />
+ </testsuite>
+
+ <!-- Suite that has a test run on both shard 0 and shard 1 -->
+ <testsuite name="Suite3" tests="1" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="0" classname="Suite3">
+ <failure message="" type="" ignored="true"></failure>
+ </testcase>
+ </testsuite>
+</testsuites>
diff --git a/chromium/tools/sharding_supervisor/data/gtest_results.xml1 b/chromium/tools/sharding_supervisor/data/gtest_results.xml1
new file mode 100644
index 00000000000..6d8bef886d6
--- /dev/null
+++ b/chromium/tools/sharding_supervisor/data/gtest_results.xml1
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites name="AllTests" tests="" failures="" disabled="" errors="" time="">
+ <!-- See comments in gtest_results.xml0 for what the different suites represent -->
+ <testsuite name="Suite0" tests="1" failures="" disabled="" errors="" time="">
+ </testsuite>
+ <testsuite name="Suite1" tests="1" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="1" classname="Suite1">
+ <failure message="" type="" ignored="true"></failure>
+ </testcase>
+ </testsuite>
+ <testsuite name="Suite2" tests="2" failures="" disabled="" errors="" time="">
+ <testcase name="Test1" status="run" time="0" classname="Suite2" />
+ </testsuite>
+ <testsuite name="Suite3" tests="1" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="0" classname="Suite3">
+ <failure message="" type="" ignored="true"></failure>
+ </testcase>
+ </testsuite>
+</testsuites>
diff --git a/chromium/tools/sharding_supervisor/data/gtest_results_expected.xml b/chromium/tools/sharding_supervisor/data/gtest_results_expected.xml
new file mode 100644
index 00000000000..7af04d4cbe5
--- /dev/null
+++ b/chromium/tools/sharding_supervisor/data/gtest_results_expected.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuites name="AllTests" tests="" failures="" disabled="" errors="" time="">
+ <!-- See comments in gtest_results.xml0 for what the different suites represent -->
+ <testsuite name="Suite0" tests="1" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="0" classname="Suite0" />
+ </testsuite>
+ <testsuite name="Suite1" tests="1" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="1" classname="Suite1">
+ <failure message="" type="" ignored="true"></failure>
+ </testcase>
+ </testsuite>
+ <testsuite name="Suite2" tests="2" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="0" classname="Suite2" />
+ <testcase name="Test1" status="run" time="0" classname="Suite2" />
+ </testsuite>
+ <testsuite name="Suite3" tests="1" failures="" disabled="" errors="" time="">
+ <testcase name="Test0" status="run" time="0" classname="Suite3">
+ <failure message="" type="" ignored="true"></failure>
+ <failure message="" type="" ignored="true"></failure>
+ </testcase>
+ </testsuite>
+</testsuites>
diff --git a/chromium/tools/sharding_supervisor/dummy_test.py b/chromium/tools/sharding_supervisor/dummy_test.py
new file mode 100755
index 00000000000..4b1d0195a1a
--- /dev/null
+++ b/chromium/tools/sharding_supervisor/dummy_test.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Dummy test used by the sharding supervisor unittests."""
+
+import os
+
+total = os.environ['GTEST_TOTAL_SHARDS']
+index = os.environ['GTEST_SHARD_INDEX']
+print 'Running shard %s of %s' % (index, total)
diff --git a/chromium/tools/sharding_supervisor/sharding_supervisor.py b/chromium/tools/sharding_supervisor/sharding_supervisor.py
new file mode 100755
index 00000000000..4bddeb26669
--- /dev/null
+++ b/chromium/tools/sharding_supervisor/sharding_supervisor.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Defer to run_test_cases.py."""
+
+import os
+import optparse
+import sys
+
+ROOT_DIR = os.path.dirname(
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+
+def pop_known_arguments(args):
+ """Extracts known arguments from the args if present."""
+ rest = []
+ run_test_cases_extra_args = []
+ for arg in args:
+ if arg.startswith(('--gtest_filter=', '--gtest_output=')):
+ run_test_cases_extra_args.append(arg)
+ elif arg == '--run-manual':
+ run_test_cases_extra_args.append(arg)
+ elif arg == '--gtest_print_time':
+ # Ignore.
+ pass
+ elif 'interactive_ui_tests' in arg:
+ # Run this test in a single thread. It is useful to run it under
+ # run_test_cases so automatic flaky test workaround is still used.
+ run_test_cases_extra_args.append('-j1')
+ rest.append(arg)
+ elif 'browser_tests' in arg:
+ # Test cases in this executable fire up *a lot* of child processes,
+ # causing huge memory bottleneck. So use less than N-cpus jobs.
+ run_test_cases_extra_args.append('--use-less-jobs')
+ rest.append(arg)
+ else:
+ rest.append(arg)
+ return run_test_cases_extra_args, rest
+
+
+def main():
+ parser = optparse.OptionParser()
+
+ group = optparse.OptionGroup(
+ parser, 'Compability flag with the old sharding_supervisor')
+ group.add_option(
+ '--no-color', action='store_true', help='Ignored')
+ group.add_option(
+ '--retry-failed', action='store_true', help='Ignored')
+ group.add_option(
+ '-t', '--timeout', type='int', help='Kept as --timeout')
+ group.add_option(
+ '--total-slaves', type='int', default=1, help='Converted to --index')
+ group.add_option(
+ '--slave-index', type='int', default=0, help='Converted to --shards')
+ parser.add_option_group(group)
+
+ parser.disable_interspersed_args()
+ options, args = parser.parse_args()
+
+ swarm_client_dir = os.path.join(
+ ROOT_DIR, 'tools', 'swarm_client', 'googletest')
+ sys.path.insert(0, swarm_client_dir)
+
+ cmd = [
+ '--shards', str(options.total_slaves),
+ '--index', str(options.slave_index),
+ '--no-dump',
+ '--no-cr',
+ ]
+ if options.timeout is not None:
+ cmd.extend(['--timeout', str(options.timeout)])
+
+ run_test_cases_extra_args, rest = pop_known_arguments(args)
+
+ import run_test_cases # pylint: disable=F0401
+
+ return run_test_cases.main(cmd + run_test_cases_extra_args + ['--'] + rest)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/sharding_supervisor/stdio_buffer.py b/chromium/tools/sharding_supervisor/stdio_buffer.py
new file mode 100644
index 00000000000..d16220a1981
--- /dev/null
+++ b/chromium/tools/sharding_supervisor/stdio_buffer.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Syncronized Standard IO Linebuffer implemented with cStringIO."""
+
+import cStringIO
+import threading
+import Queue
+
+
+class StdioBuffer(object):
+ def __init__(self, shard):
+ self.queue = Queue.Queue()
+ self.completed = 0
+ self.shard = shard
+
+ def _pipe_handler(self, system_pipe, program_pipe):
+ """Helper method for collecting stdio output. Output is collected until
+ a newline is seen, at which point an event is triggered and the line is
+ pushed to a buffer as a (stdio, line) tuple."""
+ buf = cStringIO.StringIO()
+ pipe_running = True
+ while pipe_running:
+ char = program_pipe.read(1)
+ if not char and self.shard.poll() is not None:
+ pipe_running = False
+ buf.write(char)
+ if char == '\n' or not pipe_running:
+ line = buf.getvalue()
+ if line:
+ self.queue.put((system_pipe, line))
+ if not pipe_running:
+ self.queue.put((system_pipe, None))
+ buf.close()
+ buf = cStringIO.StringIO()
+
+ def handle_pipe(self, system_pipe, program_pipe):
+ t = threading.Thread(target=self._pipe_handler, args=[system_pipe,
+ program_pipe])
+ t.start()
+ return t
+
+ def readline(self):
+ """Emits a tuple of (sys.stderr, line), (sys.stdout, line), or (None, None)
+ if the process has finished. This is a blocking call."""
+ while True:
+ (pipe, line) = self.queue.get(True)
+ if line:
+ return (pipe, line)
+ self.completed += 1
+ if self.completed >= 2:
+ return (None, None)
diff --git a/chromium/tools/site_compare/command_line.py b/chromium/tools/site_compare/command_line.py
new file mode 100755
index 00000000000..de93d18ce0a
--- /dev/null
+++ b/chromium/tools/site_compare/command_line.py
@@ -0,0 +1,802 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Parse a command line, retrieving a command and its arguments.
+
+Supports the concept of command line commands, each with its own set
+of arguments. Supports dependent arguments and mutually exclusive arguments.
+Basically, a better optparse. I took heed of epg's WHINE() in gvn.cmdline
+and dumped optparse in favor of something better.
+"""
+
+import os.path
+import re
+import string
+import sys
+import textwrap
+import types
+
+
+def IsString(var):
+ """Little helper function to see if a variable is a string."""
+ return type(var) in types.StringTypes
+
+
+class ParseError(Exception):
+ """Encapsulates errors from parsing, string arg is description."""
+ pass
+
+
+class Command(object):
+ """Implements a single command."""
+
+ def __init__(self, names, helptext, validator=None, impl=None):
+ """Initializes Command from names and helptext, plus optional callables.
+
+ Args:
+ names: command name, or list of synonyms
+ helptext: brief string description of the command
+ validator: callable for custom argument validation
+ Should raise ParseError if it wants
+ impl: callable to be invoked when command is called
+ """
+ self.names = names
+ self.validator = validator
+ self.helptext = helptext
+ self.impl = impl
+ self.args = []
+ self.required_groups = []
+ self.arg_dict = {}
+ self.positional_args = []
+ self.cmdline = None
+
+ class Argument(object):
+ """Encapsulates an argument to a command."""
+ VALID_TYPES = ['string', 'readfile', 'int', 'flag', 'coords']
+ TYPES_WITH_VALUES = ['string', 'readfile', 'int', 'coords']
+
+ def __init__(self, names, helptext, type, metaname,
+ required, default, positional):
+ """Command-line argument to a command.
+
+ Args:
+ names: argument name, or list of synonyms
+ helptext: brief description of the argument
+ type: type of the argument. Valid values include:
+ string - a string
+ readfile - a file which must exist and be available
+ for reading
+ int - an integer
+ flag - an optional flag (bool)
+ coords - (x,y) where x and y are ints
+ metaname: Name to display for value in help, inferred if not
+ specified
+ required: True if argument must be specified
+ default: Default value if not specified
+ positional: Argument specified by location, not name
+
+ Raises:
+ ValueError: the argument name is invalid for some reason
+ """
+ if type not in Command.Argument.VALID_TYPES:
+ raise ValueError("Invalid type: %r" % type)
+
+ if required and default is not None:
+ raise ValueError("required and default are mutually exclusive")
+
+ if required and type == 'flag':
+ raise ValueError("A required flag? Give me a break.")
+
+ if metaname and type not in Command.Argument.TYPES_WITH_VALUES:
+ raise ValueError("Type %r can't have a metaname" % type)
+
+ # If no metaname is provided, infer it: use the alphabetical characters
+ # of the last provided name
+ if not metaname and type in Command.Argument.TYPES_WITH_VALUES:
+ metaname = (
+ names[-1].lstrip(string.punctuation + string.whitespace).upper())
+
+ self.names = names
+ self.helptext = helptext
+ self.type = type
+ self.required = required
+ self.default = default
+ self.positional = positional
+ self.metaname = metaname
+
+ self.mutex = [] # arguments that are mutually exclusive with
+ # this one
+ self.depends = [] # arguments that must be present for this
+ # one to be valid
+ self.present = False # has this argument been specified?
+
+ def AddDependency(self, arg):
+ """Makes this argument dependent on another argument.
+
+ Args:
+ arg: name of the argument this one depends on
+ """
+ if arg not in self.depends:
+ self.depends.append(arg)
+
+ def AddMutualExclusion(self, arg):
+ """Makes this argument invalid if another is specified.
+
+ Args:
+ arg: name of the mutually exclusive argument.
+ """
+ if arg not in self.mutex:
+ self.mutex.append(arg)
+
+ def GetUsageString(self):
+ """Returns a brief string describing the argument's usage."""
+ if not self.positional:
+ string = self.names[0]
+ if self.type in Command.Argument.TYPES_WITH_VALUES:
+ string += "="+self.metaname
+ else:
+ string = self.metaname
+
+ if not self.required:
+ string = "["+string+"]"
+
+ return string
+
+ def GetNames(self):
+ """Returns a string containing a list of the arg's names."""
+ if self.positional:
+ return self.metaname
+ else:
+ return ", ".join(self.names)
+
+ def GetHelpString(self, width=80, indent=5, names_width=20, gutter=2):
+ """Returns a help string including help for all the arguments."""
+ names = [" "*indent + line +" "*(names_width-len(line)) for line in
+ textwrap.wrap(self.GetNames(), names_width)]
+
+ helpstring = textwrap.wrap(self.helptext, width-indent-names_width-gutter)
+
+ if len(names) < len(helpstring):
+ names += [" "*(indent+names_width)]*(len(helpstring)-len(names))
+
+ if len(helpstring) < len(names):
+ helpstring += [""]*(len(names)-len(helpstring))
+
+ return "\n".join([name_line + " "*gutter + help_line for
+ name_line, help_line in zip(names, helpstring)])
+
+ def __repr__(self):
+ if self.present:
+ string = '= %r' % self.value
+ else:
+ string = "(absent)"
+
+ return "Argument %s '%s'%s" % (self.type, self.names[0], string)
+
+ # end of nested class Argument
+
+ def AddArgument(self, names, helptext, type="string", metaname=None,
+ required=False, default=None, positional=False):
+ """Command-line argument to a command.
+
+ Args:
+ names: argument name, or list of synonyms
+ helptext: brief description of the argument
+ type: type of the argument
+ metaname: Name to display for value in help, inferred if not
+ required: True if argument must be specified
+ default: Default value if not specified
+ positional: Argument specified by location, not name
+
+ Raises:
+ ValueError: the argument already exists or is invalid
+
+ Returns:
+ The newly-created argument
+ """
+ if IsString(names): names = [names]
+
+ names = [name.lower() for name in names]
+
+ for name in names:
+ if name in self.arg_dict:
+ raise ValueError("%s is already an argument"%name)
+
+ if (positional and required and
+ [arg for arg in self.args if arg.positional] and
+ not [arg for arg in self.args if arg.positional][-1].required):
+ raise ValueError(
+ "A required positional argument may not follow an optional one.")
+
+ arg = Command.Argument(names, helptext, type, metaname,
+ required, default, positional)
+
+ self.args.append(arg)
+
+ for name in names:
+ self.arg_dict[name] = arg
+
+ return arg
+
+ def GetArgument(self, name):
+ """Return an argument from a name."""
+ return self.arg_dict[name.lower()]
+
+ def AddMutualExclusion(self, args):
+ """Specifies that a list of arguments are mutually exclusive."""
+ if len(args) < 2:
+ raise ValueError("At least two arguments must be specified.")
+
+ args = [arg.lower() for arg in args]
+
+ for index in xrange(len(args)-1):
+ for index2 in xrange(index+1, len(args)):
+ self.arg_dict[args[index]].AddMutualExclusion(self.arg_dict[args[index2]])
+
+ def AddDependency(self, dependent, depends_on):
+ """Specifies that one argument may only be present if another is.
+
+ Args:
+ dependent: the name of the dependent argument
+ depends_on: the name of the argument on which it depends
+ """
+ self.arg_dict[dependent.lower()].AddDependency(
+ self.arg_dict[depends_on.lower()])
+
+ def AddMutualDependency(self, args):
+ """Specifies that a list of arguments are all mutually dependent."""
+ if len(args) < 2:
+ raise ValueError("At least two arguments must be specified.")
+
+ args = [arg.lower() for arg in args]
+
+ for (arg1, arg2) in [(arg1, arg2) for arg1 in args for arg2 in args]:
+ if arg1 == arg2: continue
+ self.arg_dict[arg1].AddDependency(self.arg_dict[arg2])
+
+ def AddRequiredGroup(self, args):
+ """Specifies that at least one of the named arguments must be present."""
+ if len(args) < 2:
+ raise ValueError("At least two arguments must be in a required group.")
+
+ args = [self.arg_dict[arg.lower()] for arg in args]
+
+ self.required_groups.append(args)
+
+ def ParseArguments(self):
+ """Given a command line, parse and validate the arguments."""
+
+ # reset all the arguments before we parse
+ for arg in self.args:
+ arg.present = False
+ arg.value = None
+
+ self.parse_errors = []
+
+ # look for arguments remaining on the command line
+ while len(self.cmdline.rargs):
+ try:
+ self.ParseNextArgument()
+ except ParseError, e:
+ self.parse_errors.append(e.args[0])
+
+ # after all the arguments are parsed, check for problems
+ for arg in self.args:
+ if not arg.present and arg.required:
+ self.parse_errors.append("'%s': required parameter was missing"
+ % arg.names[0])
+
+ if not arg.present and arg.default:
+ arg.present = True
+ arg.value = arg.default
+
+ if arg.present:
+ for mutex in arg.mutex:
+ if mutex.present:
+ self.parse_errors.append(
+ "'%s', '%s': arguments are mutually exclusive" %
+ (arg.argstr, mutex.argstr))
+
+ for depend in arg.depends:
+ if not depend.present:
+ self.parse_errors.append("'%s': '%s' must be specified as well" %
+ (arg.argstr, depend.names[0]))
+
+ # check for required groups
+ for group in self.required_groups:
+ if not [arg for arg in group if arg.present]:
+ self.parse_errors.append("%s: at least one must be present" %
+ (", ".join(["'%s'" % arg.names[-1] for arg in group])))
+
+ # if we have any validators, invoke them
+ if not self.parse_errors and self.validator:
+ try:
+ self.validator(self)
+ except ParseError, e:
+ self.parse_errors.append(e.args[0])
+
+ # Helper methods so you can treat the command like a dict
+ def __getitem__(self, key):
+ arg = self.arg_dict[key.lower()]
+
+ if arg.type == 'flag':
+ return arg.present
+ else:
+ return arg.value
+
+ def __iter__(self):
+ return [arg for arg in self.args if arg.present].__iter__()
+
+ def ArgumentPresent(self, key):
+ """Tests if an argument exists and has been specified."""
+ return key.lower() in self.arg_dict and self.arg_dict[key.lower()].present
+
+ def __contains__(self, key):
+ return self.ArgumentPresent(key)
+
+ def ParseNextArgument(self):
+ """Find the next argument in the command line and parse it."""
+ arg = None
+ value = None
+ argstr = self.cmdline.rargs.pop(0)
+
+ # First check: is this a literal argument?
+ if argstr.lower() in self.arg_dict:
+ arg = self.arg_dict[argstr.lower()]
+ if arg.type in Command.Argument.TYPES_WITH_VALUES:
+ if len(self.cmdline.rargs):
+ value = self.cmdline.rargs.pop(0)
+
+ # Second check: is this of the form "arg=val" or "arg:val"?
+ if arg is None:
+ delimiter_pos = -1
+
+ for delimiter in [':', '=']:
+ pos = argstr.find(delimiter)
+ if pos >= 0:
+ if delimiter_pos < 0 or pos < delimiter_pos:
+ delimiter_pos = pos
+
+ if delimiter_pos >= 0:
+ testarg = argstr[:delimiter_pos]
+ testval = argstr[delimiter_pos+1:]
+
+ if testarg.lower() in self.arg_dict:
+ arg = self.arg_dict[testarg.lower()]
+ argstr = testarg
+ value = testval
+
+ # Third check: does this begin an argument?
+ if arg is None:
+ for key in self.arg_dict.iterkeys():
+ if (len(key) < len(argstr) and
+ self.arg_dict[key].type in Command.Argument.TYPES_WITH_VALUES and
+ argstr[:len(key)].lower() == key):
+ value = argstr[len(key):]
+ argstr = argstr[:len(key)]
+ arg = self.arg_dict[argstr]
+
+ # Fourth check: do we have any positional arguments available?
+ if arg is None:
+ for positional_arg in [
+ testarg for testarg in self.args if testarg.positional]:
+ if not positional_arg.present:
+ arg = positional_arg
+ value = argstr
+ argstr = positional_arg.names[0]
+ break
+
+ # Push the retrieved argument/value onto the largs stack
+ if argstr: self.cmdline.largs.append(argstr)
+ if value: self.cmdline.largs.append(value)
+
+ # If we've made it this far and haven't found an arg, give up
+ if arg is None:
+ raise ParseError("Unknown argument: '%s'" % argstr)
+
+ # Convert the value, if necessary
+ if arg.type in Command.Argument.TYPES_WITH_VALUES and value is None:
+ raise ParseError("Argument '%s' requires a value" % argstr)
+
+ if value is not None:
+ value = self.StringToValue(value, arg.type, argstr)
+
+ arg.argstr = argstr
+ arg.value = value
+ arg.present = True
+
+ # end method ParseNextArgument
+
+ def StringToValue(self, value, type, argstr):
+ """Convert a string from the command line to a value type."""
+ try:
+ if type == 'string':
+ pass # leave it be
+
+ elif type == 'int':
+ try:
+ value = int(value)
+ except ValueError:
+ raise ParseError
+
+ elif type == 'readfile':
+ if not os.path.isfile(value):
+ raise ParseError("'%s': '%s' does not exist" % (argstr, value))
+
+ elif type == 'coords':
+ try:
+ value = [int(val) for val in
+ re.match("\(\s*(\d+)\s*\,\s*(\d+)\s*\)\s*\Z", value).
+ groups()]
+ except AttributeError:
+ raise ParseError
+
+ else:
+ raise ValueError("Unknown type: '%s'" % type)
+
+ except ParseError, e:
+ # The bare exception is raised in the generic case; more specific errors
+ # will arrive with arguments and should just be reraised
+ if not e.args:
+ e = ParseError("'%s': unable to convert '%s' to type '%s'" %
+ (argstr, value, type))
+ raise e
+
+ return value
+
+ def SortArgs(self):
+ """Returns a method that can be passed to sort() to sort arguments."""
+
+ def ArgSorter(arg1, arg2):
+ """Helper for sorting arguments in the usage string.
+
+ Positional arguments come first, then required arguments,
+ then optional arguments. Pylint demands this trivial function
+ have both Args: and Returns: sections, sigh.
+
+ Args:
+ arg1: the first argument to compare
+ arg2: the second argument to compare
+
+ Returns:
+ -1 if arg1 should be sorted first, +1 if it should be sorted second,
+ and 0 if arg1 and arg2 have the same sort level.
+ """
+ return ((arg2.positional-arg1.positional)*2 +
+ (arg2.required-arg1.required))
+ return ArgSorter
+
+ def GetUsageString(self, width=80, name=None):
+ """Gets a string describing how the command is used."""
+ if name is None: name = self.names[0]
+
+ initial_indent = "Usage: %s %s " % (self.cmdline.prog, name)
+ subsequent_indent = " " * len(initial_indent)
+
+ sorted_args = self.args[:]
+ sorted_args.sort(self.SortArgs())
+
+ return textwrap.fill(
+ " ".join([arg.GetUsageString() for arg in sorted_args]), width,
+ initial_indent=initial_indent,
+ subsequent_indent=subsequent_indent)
+
+ def GetHelpString(self, width=80):
+ """Returns a list of help strings for all this command's arguments."""
+ sorted_args = self.args[:]
+ sorted_args.sort(self.SortArgs())
+
+ return "\n".join([arg.GetHelpString(width) for arg in sorted_args])
+
+ # end class Command
+
+
+class CommandLine(object):
+ """Parse a command line, extracting a command and its arguments."""
+
+ def __init__(self):
+ self.commands = []
+ self.cmd_dict = {}
+
+ # Add the help command to the parser
+ help_cmd = self.AddCommand(["help", "--help", "-?", "-h"],
+ "Displays help text for a command",
+ ValidateHelpCommand,
+ DoHelpCommand)
+
+ help_cmd.AddArgument(
+ "command", "Command to retrieve help for", positional=True)
+ help_cmd.AddArgument(
+ "--width", "Width of the output", type='int', default=80)
+
+ self.Exit = sys.exit # override this if you don't want the script to halt
+ # on error or on display of help
+
+ self.out = sys.stdout # override these if you want to redirect
+ self.err = sys.stderr # output or error messages
+
+ def AddCommand(self, names, helptext, validator=None, impl=None):
+ """Add a new command to the parser.
+
+ Args:
+ names: command name, or list of synonyms
+ helptext: brief string description of the command
+ validator: method to validate a command's arguments
+ impl: callable to be invoked when command is called
+
+ Raises:
+ ValueError: raised if command already added
+
+ Returns:
+ The new command
+ """
+ if IsString(names): names = [names]
+
+ for name in names:
+ if name in self.cmd_dict:
+ raise ValueError("%s is already a command"%name)
+
+ cmd = Command(names, helptext, validator, impl)
+ cmd.cmdline = self
+
+ self.commands.append(cmd)
+ for name in names:
+ self.cmd_dict[name.lower()] = cmd
+
+ return cmd
+
+ def GetUsageString(self):
+ """Returns simple usage instructions."""
+ return "Type '%s help' for usage." % self.prog
+
+ def ParseCommandLine(self, argv=None, prog=None, execute=True):
+ """Does the work of parsing a command line.
+
+ Args:
+ argv: list of arguments, defaults to sys.args[1:]
+ prog: name of the command, defaults to the base name of the script
+ execute: if false, just parse, don't invoke the 'impl' member
+
+ Returns:
+ The command that was executed
+ """
+ if argv is None: argv = sys.argv[1:]
+ if prog is None: prog = os.path.basename(sys.argv[0]).split('.')[0]
+
+ # Store off our parameters, we may need them someday
+ self.argv = argv
+ self.prog = prog
+
+ # We shouldn't be invoked without arguments, that's just lame
+ if not len(argv):
+ self.out.writelines(self.GetUsageString())
+ self.Exit()
+ return None # in case the client overrides Exit
+
+ # Is it a valid command?
+ self.command_string = argv[0].lower()
+ if not self.command_string in self.cmd_dict:
+ self.err.write("Unknown command: '%s'\n\n" % self.command_string)
+ self.out.write(self.GetUsageString())
+ self.Exit()
+ return None # in case the client overrides Exit
+
+ self.command = self.cmd_dict[self.command_string]
+
+ # "rargs" = remaining (unparsed) arguments
+ # "largs" = already parsed, "left" of the read head
+ self.rargs = argv[1:]
+ self.largs = []
+
+ # let the command object do the parsing
+ self.command.ParseArguments()
+
+ if self.command.parse_errors:
+ # there were errors, output the usage string and exit
+ self.err.write(self.command.GetUsageString()+"\n\n")
+ self.err.write("\n".join(self.command.parse_errors))
+ self.err.write("\n\n")
+
+ self.Exit()
+
+ elif execute and self.command.impl:
+ self.command.impl(self.command)
+
+ return self.command
+
+ def __getitem__(self, key):
+ return self.cmd_dict[key]
+
+ def __iter__(self):
+ return self.cmd_dict.__iter__()
+
+
+def ValidateHelpCommand(command):
+ """Checks to make sure an argument to 'help' is a valid command."""
+ if 'command' in command and command['command'] not in command.cmdline:
+ raise ParseError("'%s': unknown command" % command['command'])
+
+
+def DoHelpCommand(command):
+ """Executed when the command is 'help'."""
+ out = command.cmdline.out
+ width = command['--width']
+
+ if 'command' not in command:
+ out.write(command.GetUsageString())
+ out.write("\n\n")
+
+ indent = 5
+ gutter = 2
+
+ command_width = (
+ max([len(cmd.names[0]) for cmd in command.cmdline.commands]) + gutter)
+
+ for cmd in command.cmdline.commands:
+ cmd_name = cmd.names[0]
+
+ initial_indent = (" "*indent + cmd_name + " "*
+ (command_width+gutter-len(cmd_name)))
+ subsequent_indent = " "*(indent+command_width+gutter)
+
+ out.write(textwrap.fill(cmd.helptext, width,
+ initial_indent=initial_indent,
+ subsequent_indent=subsequent_indent))
+ out.write("\n")
+
+ out.write("\n")
+
+ else:
+ help_cmd = command.cmdline[command['command']]
+
+ out.write(textwrap.fill(help_cmd.helptext, width))
+ out.write("\n\n")
+ out.write(help_cmd.GetUsageString(width=width))
+ out.write("\n\n")
+ out.write(help_cmd.GetHelpString(width=width))
+ out.write("\n")
+
+ command.cmdline.Exit()
+
+
+def main():
+ # If we're invoked rather than imported, run some tests
+ cmdline = CommandLine()
+
+ # Since we're testing, override Exit()
+ def TestExit():
+ pass
+ cmdline.Exit = TestExit
+
+ # Actually, while we're at it, let's override error output too
+ cmdline.err = open(os.path.devnull, "w")
+
+ test = cmdline.AddCommand(["test", "testa", "testb"], "test command")
+ test.AddArgument(["-i", "--int", "--integer", "--optint", "--optionalint"],
+ "optional integer parameter", type='int')
+ test.AddArgument("--reqint", "required integer parameter", type='int',
+ required=True)
+ test.AddArgument("pos1", "required positional argument", positional=True,
+ required=True)
+ test.AddArgument("pos2", "optional positional argument", positional=True)
+ test.AddArgument("pos3", "another optional positional arg",
+ positional=True)
+
+ # mutually dependent arguments
+ test.AddArgument("--mutdep1", "mutually dependent parameter 1")
+ test.AddArgument("--mutdep2", "mutually dependent parameter 2")
+ test.AddArgument("--mutdep3", "mutually dependent parameter 3")
+ test.AddMutualDependency(["--mutdep1", "--mutdep2", "--mutdep3"])
+
+ # mutually exclusive arguments
+ test.AddArgument("--mutex1", "mutually exclusive parameter 1")
+ test.AddArgument("--mutex2", "mutually exclusive parameter 2")
+ test.AddArgument("--mutex3", "mutually exclusive parameter 3")
+ test.AddMutualExclusion(["--mutex1", "--mutex2", "--mutex3"])
+
+ # dependent argument
+ test.AddArgument("--dependent", "dependent argument")
+ test.AddDependency("--dependent", "--int")
+
+ # other argument types
+ test.AddArgument("--file", "filename argument", type='readfile')
+ test.AddArgument("--coords", "coordinate argument", type='coords')
+ test.AddArgument("--flag", "flag argument", type='flag')
+
+ test.AddArgument("--req1", "part of a required group", type='flag')
+ test.AddArgument("--req2", "part 2 of a required group", type='flag')
+
+ test.AddRequiredGroup(["--req1", "--req2"])
+
+ # a few failure cases
+ exception_cases = """
+ test.AddArgument("failpos", "can't have req'd pos arg after opt",
+ positional=True, required=True)
++++
+ test.AddArgument("--int", "this argument already exists")
++++
+ test.AddDependency("--int", "--doesntexist")
++++
+ test.AddMutualDependency(["--doesntexist", "--mutdep2"])
++++
+ test.AddMutualExclusion(["--doesntexist", "--mutex2"])
++++
+ test.AddArgument("--reqflag", "required flag", required=True, type='flag')
++++
+ test.AddRequiredGroup(["--req1", "--doesntexist"])
+"""
+ for exception_case in exception_cases.split("+++"):
+ try:
+ exception_case = exception_case.strip()
+ exec exception_case # yes, I'm using exec, it's just for a test.
+ except ValueError:
+ # this is expected
+ pass
+ except KeyError:
+ # ...and so is this
+ pass
+ else:
+ print ("FAILURE: expected an exception for '%s'"
+ " and didn't get it" % exception_case)
+
+ # Let's do some parsing! first, the minimal success line:
+ MIN = "test --reqint 123 param1 --req1 "
+
+ # tuples of (command line, expected error count)
+ test_lines = [
+ ("test --int 3 foo --req1", 1), # missing required named parameter
+ ("test --reqint 3 --req1", 1), # missing required positional parameter
+ (MIN, 0), # success!
+ ("test param1 --reqint 123 --req1", 0), # success, order shouldn't matter
+ ("test param1 --reqint 123 --req2", 0), # success, any of required group ok
+ (MIN+"param2", 0), # another positional parameter is okay
+ (MIN+"param2 param3", 0), # and so are three
+ (MIN+"param2 param3 param4", 1), # but four are just too many
+ (MIN+"--int", 1), # where's the value?
+ (MIN+"--int 456", 0), # this is fine
+ (MIN+"--int456", 0), # as is this
+ (MIN+"--int:456", 0), # and this
+ (MIN+"--int=456", 0), # and this
+ (MIN+"--file c:\\windows\\system32\\kernel32.dll", 0), # yup
+ (MIN+"--file c:\\thisdoesntexist", 1), # nope
+ (MIN+"--mutdep1 a", 2), # no!
+ (MIN+"--mutdep2 b", 2), # also no!
+ (MIN+"--mutdep3 c", 2), # dream on!
+ (MIN+"--mutdep1 a --mutdep2 b", 2), # almost!
+ (MIN+"--mutdep1 a --mutdep2 b --mutdep3 c", 0), # yes
+ (MIN+"--mutex1 a", 0), # yes
+ (MIN+"--mutex2 b", 0), # yes
+ (MIN+"--mutex3 c", 0), # fine
+ (MIN+"--mutex1 a --mutex2 b", 1), # not fine
+ (MIN+"--mutex1 a --mutex2 b --mutex3 c", 3), # even worse
+ (MIN+"--dependent 1", 1), # no
+ (MIN+"--dependent 1 --int 2", 0), # ok
+ (MIN+"--int abc", 1), # bad type
+ (MIN+"--coords abc", 1), # also bad
+ (MIN+"--coords (abc)", 1), # getting warmer
+ (MIN+"--coords (abc,def)", 1), # missing something
+ (MIN+"--coords (123)", 1), # ooh, so close
+ (MIN+"--coords (123,def)", 1), # just a little farther
+ (MIN+"--coords (123,456)", 0), # finally!
+ ("test --int 123 --reqint=456 foo bar --coords(42,88) baz --req1", 0)
+ ]
+
+ badtests = 0
+
+ for (test, expected_failures) in test_lines:
+ cmdline.ParseCommandLine([x.strip() for x in test.strip().split(" ")])
+
+ if not len(cmdline.command.parse_errors) == expected_failures:
+ print "FAILED:\n issued: '%s'\n expected: %d\n received: %d\n\n" % (
+ test, expected_failures, len(cmdline.command.parse_errors))
+ badtests += 1
+
+ print "%d failed out of %d tests" % (badtests, len(test_lines))
+
+ cmdline.ParseCommandLine(["help", "test"])
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/site_compare/commands/__init__.py b/chromium/tools/site_compare/commands/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/site_compare/commands/__init__.py
diff --git a/chromium/tools/site_compare/commands/compare2.py b/chromium/tools/site_compare/commands/compare2.py
new file mode 100644
index 00000000000..7e15559badb
--- /dev/null
+++ b/chromium/tools/site_compare/commands/compare2.py
@@ -0,0 +1,170 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""SiteCompare command to invoke the same page in two versions of a browser.
+
+Does the easiest compatibility test: equality comparison between two different
+versions of the same browser. Invoked with a series of command line options
+that specify which URLs to check, which browser to use, where to store results,
+etc.
+"""
+
+import os # Functions for walking the directory tree
+import tempfile # Get a temporary directory to hold intermediates
+
+import command_line
+import drivers # Functions for driving keyboard/mouse/windows, OS-specific
+import operators # Functions that, given two bitmaps as input, produce
+ # output depending on the performance of an operation
+import scrapers # Functions that know how to capture a render from
+ # particular browsers
+
+
+def CreateCommand(cmdline):
+ """Inserts the command and arguments into a command line for parsing."""
+ cmd = cmdline.AddCommand(
+ ["compare2"],
+ "Compares the output of two browsers on the same URL or list of URLs",
+ ValidateCompare2,
+ ExecuteCompare2)
+
+ cmd.AddArgument(
+ ["-b1", "--browser1"], "Full path to first browser's executable",
+ type="readfile", metaname="PATH", required=True)
+ cmd.AddArgument(
+ ["-b2", "--browser2"], "Full path to second browser's executable",
+ type="readfile", metaname="PATH", required=True)
+ cmd.AddArgument(
+ ["-b", "--browser"], "Which browser to use", type="string",
+ default="chrome")
+ cmd.AddArgument(
+ ["-b1v", "--browser1ver"], "Version of first browser", metaname="VERSION")
+ cmd.AddArgument(
+ ["-b2v", "--browser2ver"], "Version of second browser", metaname="VERSION")
+ cmd.AddArgument(
+ ["-b1n", "--browser1name"], "Optional name for first browser (used in "
+ "directory to hold intermediate files)", metaname="NAME")
+ cmd.AddArgument(
+ ["-b2n", "--browser2name"], "Optional name for second browser (used in "
+ "directory to hold intermediate files)", metaname="NAME")
+ cmd.AddArgument(
+ ["-o", "--outdir"], "Directory to store scrape files", metaname="DIR")
+ cmd.AddArgument(
+ ["-u", "--url"], "URL to compare")
+ cmd.AddArgument(
+ ["-l", "--list"], "List of URLs to compare", type="readfile")
+ cmd.AddMutualExclusion(["--url", "--list"])
+ cmd.AddArgument(
+ ["-s", "--startline"], "First line of URL list", type="int")
+ cmd.AddArgument(
+ ["-e", "--endline"], "Last line of URL list (exclusive)", type="int")
+ cmd.AddArgument(
+ ["-c", "--count"], "Number of lines of URL file to use", type="int")
+ cmd.AddDependency("--startline", "--list")
+ cmd.AddRequiredGroup(["--url", "--list"])
+ cmd.AddDependency("--endline", "--list")
+ cmd.AddDependency("--count", "--list")
+ cmd.AddMutualExclusion(["--count", "--endline"])
+ cmd.AddDependency("--count", "--startline")
+ cmd.AddArgument(
+ ["-t", "--timeout"], "Amount of time (seconds) to wait for browser to "
+ "finish loading",
+ type="int", default=60)
+ cmd.AddArgument(
+ ["-log", "--logfile"], "File to write output", type="string", required=True)
+ cmd.AddArgument(
+ ["-sz", "--size"], "Browser window size", default=(800, 600), type="coords")
+ cmd.AddArgument(
+ ["-m", "--maskdir"], "Path that holds masks to use for comparison")
+ cmd.AddArgument(
+ ["-d", "--diffdir"], "Path to hold the difference of comparisons that fail")
+
+
+def ValidateCompare2(command):
+ """Validate the arguments to compare2. Raises ParseError if failed."""
+ executables = [".exe", ".com", ".bat"]
+ if (os.path.splitext(command["--browser1"])[1].lower() not in executables or
+ os.path.splitext(command["--browser2"])[1].lower() not in executables):
+ raise command_line.ParseError("Browser filename must be an executable")
+
+
+def ExecuteCompare2(command):
+ """Executes the Compare2 command."""
+ if command["--url"]:
+ url_list = [command["--url"]]
+ else:
+ startline = command["--startline"]
+ if command["--count"]:
+ endline = startline+command["--count"]
+ else:
+ endline = command["--endline"]
+ url_list = [url.strip() for url in
+ open(command["--list"], "r").readlines()[startline:endline]]
+
+ log_file = open(command["--logfile"], "w")
+
+ outdir = command["--outdir"]
+ if not outdir: outdir = tempfile.gettempdir()
+
+ scrape_info_list = []
+
+ class ScrapeInfo(object):
+ """Helper class to hold information about a scrape."""
+ __slots__ = ["browser_path", "scraper", "outdir", "result"]
+
+ for index in xrange(1, 3):
+ scrape_info = ScrapeInfo()
+ scrape_info.browser_path = command["--browser%d" % index]
+ scrape_info.scraper = scrapers.GetScraper(
+ (command["--browser"], command["--browser%dver" % index]))
+
+ if command["--browser%dname" % index]:
+ scrape_info.outdir = os.path.join(outdir,
+ command["--browser%dname" % index])
+ else:
+ scrape_info.outdir = os.path.join(outdir, str(index))
+
+ drivers.windowing.PreparePath(scrape_info.outdir)
+ scrape_info_list.append(scrape_info)
+
+ compare = operators.GetOperator("equals_with_mask")
+
+ for url in url_list:
+ success = True
+
+ for scrape_info in scrape_info_list:
+ scrape_info.result = scrape_info.scraper.Scrape(
+ [url], scrape_info.outdir, command["--size"], (0, 0),
+ command["--timeout"], path=scrape_info.browser_path)
+
+ if not scrape_info.result:
+ scrape_info.result = "success"
+ else:
+ success = False
+
+ result = "unknown"
+
+ if success:
+ result = "equal"
+
+ file1 = drivers.windowing.URLtoFilename(
+ url, scrape_info_list[0].outdir, ".bmp")
+ file2 = drivers.windowing.URLtoFilename(
+ url, scrape_info_list[1].outdir, ".bmp")
+
+ comparison_result = compare.Compare(file1, file2,
+ maskdir=command["--maskdir"])
+
+ if comparison_result is not None:
+ result = "not-equal"
+
+ if command["--diffdir"]:
+ comparison_result[1].save(
+ drivers.windowing.URLtoFilename(url, command["--diffdir"], ".bmp"))
+
+ # TODO(jhaas): maybe use the logging module rather than raw file writes
+ log_file.write("%s %s %s %s\n" % (url,
+ scrape_info_list[0].result,
+ scrape_info_list[1].result,
+ result))
diff --git a/chromium/tools/site_compare/commands/maskmaker.py b/chromium/tools/site_compare/commands/maskmaker.py
new file mode 100644
index 00000000000..8aeefcbf005
--- /dev/null
+++ b/chromium/tools/site_compare/commands/maskmaker.py
@@ -0,0 +1,272 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Component for automatically creating masks of changing areas of a website.
+
+Works by repeated invokation of a browser and scraping of the resulting page.
+Areas that differ will be added to the auto-generated mask. The mask generator
+considers the mask complete when further scrapes fail to produce any differences
+in the mask.
+"""
+
+import os # Functions for walking the directory tree
+import tempfile # Get a temporary directory to hold intermediates
+import time # Used for sleep() and naming masks by time
+
+import command_line
+import drivers
+from PIL import Image
+from PIL import ImageChops
+import scrapers
+
+
+def CreateCommand(cmdline):
+ """Inserts the command and arguments into a command line for parsing."""
+ cmd = cmdline.AddCommand(
+ ["maskmaker"],
+ "Automatically generates a mask from a list of URLs",
+ ValidateMaskmaker,
+ ExecuteMaskmaker)
+
+ cmd.AddArgument(
+ ["-bp", "--browserpath"], "Full path to browser's executable",
+ type="readfile", metaname="PATH")
+ cmd.AddArgument(
+ ["-b", "--browser"], "Which browser to use", type="string",
+ default="chrome")
+ cmd.AddArgument(
+ ["-bv", "--browserver"], "Version of the browser", metaname="VERSION")
+ cmd.AddArgument(
+ ["-o", "--outdir"], "Directory to store generated masks", metaname="DIR",
+ required=True)
+ cmd.AddArgument(
+ ["-u", "--url"], "URL to compare")
+ cmd.AddArgument(
+ ["-l", "--list"], "List of URLs to compare", type="readfile")
+ cmd.AddMutualExclusion(["--url", "--list"])
+ cmd.AddArgument(
+ ["-s", "--startline"], "First line of URL list", type="int")
+ cmd.AddArgument(
+ ["-e", "--endline"], "Last line of URL list (exclusive)", type="int")
+ cmd.AddArgument(
+ ["-c", "--count"], "Number of lines of URL file to use", type="int")
+ cmd.AddDependency("--startline", "--list")
+ cmd.AddRequiredGroup(["--url", "--list"])
+ cmd.AddDependency("--endline", "--list")
+ cmd.AddDependency("--count", "--list")
+ cmd.AddMutualExclusion(["--count", "--endline"])
+ cmd.AddDependency("--count", "--startline")
+ cmd.AddArgument(
+ ["-t", "--timeout"], "Amount of time (seconds) to wait for browser to "
+ "finish loading",
+ type="int", default=60)
+ cmd.AddArgument(
+ ["-w", "--wait"],
+ "Amount of time (in seconds) to wait between successive scrapes",
+ type="int", default=60)
+ cmd.AddArgument(
+ ["-sc", "--scrapes"],
+ "Number of successive scrapes which must result in no change to a mask "
+ "before mask creation is considered complete", type="int", default=10)
+ cmd.AddArgument(
+ ["-sz", "--size"], "Browser window size", default=(800, 600), type="coords")
+ cmd.AddArgument(["-sd", "--scrapedir"], "Directory to store scrapes")
+ cmd.AddArgument(
+ ["-gu", "--giveup"],
+ "Number of times to scrape before giving up", type="int", default=50)
+ cmd.AddArgument(
+ ["-th", "--threshhold"],
+ "Percentage of different pixels (0-100) above which the scrape will be"
+ "discarded and the mask not updated.", type="int", default=100)
+ cmd.AddArgument(
+ ["--er", "--errors"],
+ "Number of times a scrape can fail before giving up on the URL.",
+ type="int", default=1)
+
+
+def ValidateMaskmaker(command):
+ """Validate the arguments to maskmaker. Raises ParseError if failed."""
+ executables = [".exe", ".com", ".bat"]
+ if command["--browserpath"]:
+ if os.path.splitext(command["--browserpath"])[1].lower() not in executables:
+ raise command_line.ParseError("Browser filename must be an executable")
+
+
+def ExecuteMaskmaker(command):
+ """Performs automatic mask generation."""
+
+ # Get the list of URLs to generate masks for
+ class MaskmakerURL(object):
+ """Helper class for holding information about a URL passed to maskmaker."""
+ __slots__ = ['url', 'consecutive_successes', 'errors']
+ def __init__(self, url):
+ self.url = url
+ self.consecutive_successes = 0
+ self.errors = 0
+
+ if command["--url"]:
+ url_list = [MaskmakerURL(command["--url"])]
+ else:
+ startline = command["--startline"]
+ if command["--count"]:
+ endline = startline+command["--count"]
+ else:
+ endline = command["--endline"]
+ url_list = [MaskmakerURL(url.strip()) for url in
+ open(command["--list"], "r").readlines()[startline:endline]]
+
+ complete_list = []
+ error_list = []
+
+ outdir = command["--outdir"]
+ scrapes = command["--scrapes"]
+ errors = command["--errors"]
+ size = command["--size"]
+ scrape_pass = 0
+
+ scrapedir = command["--scrapedir"]
+ if not scrapedir: scrapedir = tempfile.gettempdir()
+
+ # Get the scraper
+ scraper = scrapers.GetScraper((command["--browser"], command["--browserver"]))
+
+ # Repeatedly iterate through the list of URLs until either every URL has
+ # a successful mask or too many errors, or we've exceeded the giveup limit
+ while url_list and scrape_pass < command["--giveup"]:
+ # Scrape each URL
+ for url in url_list:
+ print "Processing %r..." % url.url
+ mask_filename = drivers.windowing.URLtoFilename(url.url, outdir, ".bmp")
+
+ # Load the existing mask. This is in a loop so we can try to recover
+ # from error conditions
+ while True:
+ try:
+ mask = Image.open(mask_filename)
+ if mask.size != size:
+ print " %r already exists and is the wrong size! (%r vs %r)" % (
+ mask_filename, mask.size, size)
+ mask_filename = "%s_%r%s" % (
+ mask_filename[:-4], size, mask_filename[-4:])
+ print " Trying again as %r..." % mask_filename
+ continue
+ break
+ except IOError:
+ print " %r does not exist, creating" % mask_filename
+ mask = Image.new("1", size, 1)
+ mask.save(mask_filename)
+
+ # Find the stored scrape path
+ mask_scrape_dir = os.path.join(
+ scrapedir, os.path.splitext(os.path.basename(mask_filename))[0])
+ drivers.windowing.PreparePath(mask_scrape_dir)
+
+ # Find the baseline image
+ mask_scrapes = os.listdir(mask_scrape_dir)
+ mask_scrapes.sort()
+
+ if not mask_scrapes:
+ print " No baseline image found, mask will not be updated"
+ baseline = None
+ else:
+ baseline = Image.open(os.path.join(mask_scrape_dir, mask_scrapes[0]))
+
+ mask_scrape_filename = os.path.join(mask_scrape_dir,
+ time.strftime("%y%m%d-%H%M%S.bmp"))
+
+ # Do the scrape
+ result = scraper.Scrape(
+ [url.url], mask_scrape_dir, size, (0, 0),
+ command["--timeout"], path=command["--browserpath"],
+ filename=mask_scrape_filename)
+
+ if result:
+ # Return value other than None means an error
+ print " Scrape failed with error '%r'" % result
+ url.errors += 1
+ if url.errors >= errors:
+ print " ** Exceeded maximum error count for this URL, giving up"
+ continue
+
+ # Load the new scrape
+ scrape = Image.open(mask_scrape_filename)
+
+ # Calculate the difference between the new scrape and the baseline,
+ # subject to the current mask
+ if baseline:
+ diff = ImageChops.multiply(ImageChops.difference(scrape, baseline),
+ mask.convert(scrape.mode))
+
+ # If the difference is none, there's nothing to update
+ if max(diff.getextrema()) == (0, 0):
+ print " Scrape identical to baseline, no change in mask"
+ url.consecutive_successes += 1
+ if url.consecutive_successes >= scrapes:
+ print " ** No change for %r scrapes, done!" % scrapes
+ else:
+ # convert the difference to black and white, then change all
+ # black pixels (where the scrape and the baseline were identical)
+ # to white, all others (where the scrape and the baseline differed)
+ # to black.
+ #
+ # Since the below command is a little unclear, here's how it works.
+ # 1. convert("L") converts the RGB image to grayscale
+ # 2. point() maps grayscale values (or the individual channels)
+ # of an RGB image) to different ones. Because it operates on
+ # individual channels, the grayscale conversion from step 1
+ # is necessary.
+ # 3. The "1" second parameter to point() outputs the result as
+ # a monochrome bitmap. If the original RGB image were converted
+ # directly to monochrome, PIL would dither it.
+ diff = diff.convert("L").point([255]+[0]*255, "1")
+
+ # count the number of different pixels
+ diff_pixels = diff.getcolors()[0][0]
+
+ # is this too much?
+ diff_pixel_percent = diff_pixels * 100.0 / (mask.size[0]*mask.size[1])
+ if diff_pixel_percent > command["--threshhold"]:
+ print (" Scrape differed from baseline by %.2f percent, ignoring"
+ % diff_pixel_percent)
+ else:
+ print " Scrape differed in %d pixels, updating mask" % diff_pixels
+ mask = ImageChops.multiply(mask, diff)
+ mask.save(mask_filename)
+
+ # reset the number of consecutive "good" scrapes
+ url.consecutive_successes = 0
+
+ # Remove URLs whose mask is deemed done
+ complete_list.extend(
+ [url for url in url_list if url.consecutive_successes >= scrapes])
+ error_list.extend(
+ [url for url in url_list if url.errors >= errors])
+ url_list = [
+ url for url in url_list if
+ url.consecutive_successes < scrapes and
+ url.errors < errors]
+
+ scrape_pass += 1
+ print "**Done with scrape pass %d\n" % scrape_pass
+
+ if scrape_pass >= command["--giveup"]:
+ print "**Exceeded giveup threshhold. Giving up."
+ else:
+ print "Waiting %d seconds..." % command["--wait"]
+ time.sleep(command["--wait"])
+
+ print
+ print "*** MASKMAKER COMPLETE ***"
+ print "Summary report:"
+ print " %d masks successfully generated" % len(complete_list)
+ for url in complete_list:
+ print " ", url.url
+ print " %d masks failed with too many errors" % len(error_list)
+ for url in error_list:
+ print " ", url.url
+ if scrape_pass >= command["--giveup"]:
+ print (" %d masks were not completed before "
+ "reaching the giveup threshhold" % len(url_list))
+ for url in url_list:
+ print " ", url.url
diff --git a/chromium/tools/site_compare/commands/measure.py b/chromium/tools/site_compare/commands/measure.py
new file mode 100644
index 00000000000..2bd71f56034
--- /dev/null
+++ b/chromium/tools/site_compare/commands/measure.py
@@ -0,0 +1,52 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Command for measuring how long pages take to load in a browser.
+
+Prerequisites:
+ 1. The command_line package from tools/site_compare
+ 2. Either the IE BHO or Firefox extension (or both)
+
+Installation:
+ 1. Build the IE BHO, or call regsvr32 on a prebuilt binary
+ 2. Add a file called "measurepageloadtimeextension@google.com" to
+ the default Firefox profile directory under extensions, containing
+ the path to the Firefox extension root
+
+Invoke with the command line arguments as documented within
+the command line.
+"""
+
+import command_line
+import win32process
+
+from drivers import windowing
+from utils import browser_iterate
+
+def CreateCommand(cmdline):
+ """Inserts the command and arguments into a command line for parsing."""
+ cmd = cmdline.AddCommand(
+ ["measure"],
+ "Measures how long a series of URLs takes to load in one or more browsers.",
+ None,
+ ExecuteMeasure)
+
+ browser_iterate.SetupIterationCommandLine(cmd)
+ cmd.AddArgument(
+ ["-log", "--logfile"], "File to write output", type="string", required=True)
+
+
+def ExecuteMeasure(command):
+ """Executes the Measure command."""
+
+ def LogResult(url, proc, wnd, result):
+ """Write the result of the browse to the log file."""
+ log_file.write(result)
+
+ log_file = open(command["--logfile"], "w")
+
+ browser_iterate.Iterate(command, LogResult)
+
+ # Close the log file and return. We're done.
+ log_file.close()
diff --git a/chromium/tools/site_compare/commands/scrape.py b/chromium/tools/site_compare/commands/scrape.py
new file mode 100644
index 00000000000..8fee5a3b3ba
--- /dev/null
+++ b/chromium/tools/site_compare/commands/scrape.py
@@ -0,0 +1,59 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Command for scraping images from a URL or list of URLs.
+
+Prerequisites:
+ 1. The command_line package from tools/site_compare
+ 2. Either the IE BHO or Firefox extension (or both)
+
+Installation:
+ 1. Build the IE BHO, or call regsvr32 on a prebuilt binary
+ 2. Add a file called "measurepageloadtimeextension@google.com" to
+ the default Firefox profile directory under extensions, containing
+ the path to the Firefox extension root
+
+Invoke with the command line arguments as documented within
+the command line.
+"""
+
+import command_line
+
+from drivers import windowing
+from utils import browser_iterate
+
+def CreateCommand(cmdline):
+ """Inserts the command and arguments into a command line for parsing."""
+ cmd = cmdline.AddCommand(
+ ["scrape"],
+ "Scrapes an image from a URL or series of URLs.",
+ None,
+ ExecuteScrape)
+
+ browser_iterate.SetupIterationCommandLine(cmd)
+ cmd.AddArgument(
+ ["-log", "--logfile"], "File to write text output", type="string")
+ cmd.AddArgument(
+ ["-out", "--outdir"], "Directory to store scrapes", type="string", required=True)
+
+
+def ExecuteScrape(command):
+ """Executes the Scrape command."""
+
+ def ScrapeResult(url, proc, wnd, result):
+ """Capture and save the scrape."""
+ if log_file: log_file.write(result)
+
+ # Scrape the page
+ image = windowing.ScrapeWindow(wnd)
+ filename = windowing.URLtoFilename(url, command["--outdir"], ".bmp")
+ image.save(filename)
+
+ if command["--logfile"]: log_file = open(command["--logfile"], "w")
+ else: log_file = None
+
+ browser_iterate.Iterate(command, ScrapeResult)
+
+ # Close the log file and return. We're done.
+ if log_file: log_file.close()
diff --git a/chromium/tools/site_compare/commands/timeload.py b/chromium/tools/site_compare/commands/timeload.py
new file mode 100644
index 00000000000..f34ee1dfeb5
--- /dev/null
+++ b/chromium/tools/site_compare/commands/timeload.py
@@ -0,0 +1,144 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""SiteCompare command to time page loads
+
+Loads a series of URLs in a series of browsers (and browser versions)
+and measures how long the page takes to load in each. Outputs a
+comma-delimited file. The first line is "URL,[browser names", each
+additional line is a URL follored by comma-delimited times (in seconds),
+or the string "timeout" or "crashed".
+
+"""
+
+import os # Functions for walking the directory tree
+import tempfile # Get a temporary directory to hold intermediates
+
+import command_line
+import drivers # Functions for driving keyboard/mouse/windows, OS-specific
+import operators # Functions that, given two bitmaps as input, produce
+ # output depending on the performance of an operation
+import scrapers # Functions that know how to capture a render from
+ # particular browsers
+
+
+def CreateCommand(cmdline):
+ """Inserts the command and arguments into a command line for parsing."""
+ cmd = cmdline.AddCommand(
+ ["timeload"],
+ "Measures how long a series of URLs takes to load in one or more browsers.",
+ None,
+ ExecuteTimeLoad)
+
+ cmd.AddArgument(
+ ["-b", "--browsers"], "List of browsers to use. Comma-separated",
+ type="string", required=True)
+ cmd.AddArgument(
+ ["-bp", "--browserpaths"], "List of paths to browsers. Comma-separated",
+ type="string", required=False)
+ cmd.AddArgument(
+ ["-bv", "--browserversions"],
+ "List of versions of browsers. Comma-separated",
+ type="string", required=False)
+ cmd.AddArgument(
+ ["-u", "--url"], "URL to time")
+ cmd.AddArgument(
+ ["-l", "--list"], "List of URLs to time", type="readfile")
+ cmd.AddMutualExclusion(["--url", "--list"])
+ cmd.AddArgument(
+ ["-s", "--startline"], "First line of URL list", type="int")
+ cmd.AddArgument(
+ ["-e", "--endline"], "Last line of URL list (exclusive)", type="int")
+ cmd.AddArgument(
+ ["-c", "--count"], "Number of lines of URL file to use", type="int")
+ cmd.AddDependency("--startline", "--list")
+ cmd.AddRequiredGroup(["--url", "--list"])
+ cmd.AddDependency("--endline", "--list")
+ cmd.AddDependency("--count", "--list")
+ cmd.AddMutualExclusion(["--count", "--endline"])
+ cmd.AddDependency("--count", "--startline")
+ cmd.AddArgument(
+ ["-t", "--timeout"], "Amount of time (seconds) to wait for browser to "
+ "finish loading",
+ type="int", default=60)
+ cmd.AddArgument(
+ ["-log", "--logfile"], "File to write output", type="string", required=True)
+ cmd.AddArgument(
+ ["-sz", "--size"], "Browser window size", default=(800, 600), type="coords")
+
+
+def ExecuteTimeLoad(command):
+ """Executes the TimeLoad command."""
+ browsers = command["--browsers"].split(",")
+ num_browsers = len(browsers)
+
+ if command["--browserversions"]:
+ browser_versions = command["--browserversions"].split(",")
+ else:
+ browser_versions = [None] * num_browsers
+
+ if command["--browserpaths"]:
+ browser_paths = command["--browserpaths"].split(",")
+ else:
+ browser_paths = [None] * num_browsers
+
+ if len(browser_versions) != num_browsers:
+ raise ValueError(
+ "--browserversions must be same length as --browser_paths")
+ if len(browser_paths) != num_browsers:
+ raise ValueError(
+ "--browserversions must be same length as --browser_paths")
+
+ if [b for b in browsers if b not in ["chrome", "ie", "firefox"]]:
+ raise ValueError("unknown browsers: %r" % b)
+
+ scraper_list = []
+
+ for b in xrange(num_browsers):
+ version = browser_versions[b]
+ if not version: version = None
+
+ scraper = scrapers.GetScraper( (browsers[b], version) )
+ if not scraper:
+ raise ValueError("could not find scraper for (%r, %r)" %
+ (browsers[b], version))
+ scraper_list.append(scraper)
+
+ if command["--url"]:
+ url_list = [command["--url"]]
+ else:
+ startline = command["--startline"]
+ if command["--count"]:
+ endline = startline+command["--count"]
+ else:
+ endline = command["--endline"]
+ url_list = [url.strip() for url in
+ open(command["--list"], "r").readlines()[startline:endline]]
+
+ log_file = open(command["--logfile"], "w")
+
+ log_file.write("URL")
+ for b in xrange(num_browsers):
+ log_file.write(",%s" % browsers[b])
+
+ if browser_versions[b]: log_file.write(" %s" % browser_versions[b])
+ log_file.write("\n")
+
+ results = {}
+ for url in url_list:
+ results[url] = [None] * num_browsers
+
+ for b in xrange(num_browsers):
+ result = scraper_list[b].Time(url_list, command["--size"],
+ command["--timeout"],
+ path=browser_paths[b])
+
+ for (url, time) in result:
+ results[url][b] = time
+
+ # output the results
+ for url in url_list:
+ log_file.write(url)
+ for b in xrange(num_browsers):
+ log_file.write(",%r" % results[url][b])
diff --git a/chromium/tools/site_compare/drivers/__init__.py b/chromium/tools/site_compare/drivers/__init__.py
new file mode 100644
index 00000000000..9b46261b3bb
--- /dev/null
+++ b/chromium/tools/site_compare/drivers/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Imports a set of drivers appropriate to the current OS."""
+
+import sys
+
+platform_dir = sys.platform
+
+keyboard = __import__(platform_dir+".keyboard", globals(), locals(), [''])
+mouse = __import__(platform_dir+".mouse", globals(), locals(), [''])
+windowing = __import__(platform_dir+".windowing", globals(), locals(), [''])
diff --git a/chromium/tools/site_compare/drivers/win32/__init__.py b/chromium/tools/site_compare/drivers/win32/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/site_compare/drivers/win32/__init__.py
diff --git a/chromium/tools/site_compare/drivers/win32/keyboard.py b/chromium/tools/site_compare/drivers/win32/keyboard.py
new file mode 100755
index 00000000000..e3410e1ab77
--- /dev/null
+++ b/chromium/tools/site_compare/drivers/win32/keyboard.py
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""SiteCompare module for simulating keyboard input.
+
+This module contains functions that can be used to simulate a user
+pressing keys on a keyboard. Support is provided for formatted strings
+including special characters to represent modifier keys like CTRL and ALT
+"""
+
+import time # for sleep
+import win32api # for keybd_event and VkKeyCode
+import win32con # Windows constants
+
+# TODO(jhaas): Ask the readability guys if this would be acceptable:
+#
+# from win32con import VK_SHIFT, VK_CONTROL, VK_MENU, VK_LWIN, KEYEVENTF_KEYUP
+#
+# This is a violation of the style guide but having win32con. everywhere
+# is just plain ugly, and win32con is a huge import for just a handful of
+# constants
+
+
+def PressKey(down, key):
+ """Presses or unpresses a key.
+
+ Uses keybd_event to simulate either depressing or releasing
+ a key
+
+ Args:
+ down: Whether the key is to be pressed or released
+ key: Virtual key code of key to press or release
+ """
+
+ # keybd_event injects key events at a very low level (it's the
+ # Windows API keyboard device drivers call) so this is a very
+ # reliable way of simulating user input
+ win32api.keybd_event(key, 0, (not down) * win32con.KEYEVENTF_KEYUP)
+
+
+def TypeKey(key, keystroke_time=0):
+ """Simulate a keypress of a virtual key.
+
+ Args:
+ key: which key to press
+ keystroke_time: length of time (in seconds) to "hold down" the key
+ Note that zero works just fine
+
+ Returns:
+ None
+ """
+
+ # This just wraps a pair of PressKey calls with an intervening delay
+ PressKey(True, key)
+ time.sleep(keystroke_time)
+ PressKey(False, key)
+
+
+def TypeString(string_to_type,
+ use_modifiers=False,
+ keystroke_time=0,
+ time_between_keystrokes=0):
+ """Simulate typing a string on the keyboard.
+
+ Args:
+ string_to_type: the string to print
+ use_modifiers: specifies whether the following modifier characters
+ should be active:
+ {abc}: type characters with ALT held down
+ [abc]: type characters with CTRL held down
+ \ escapes {}[] and treats these values as literal
+ standard escape sequences are valid even if use_modifiers is false
+ \p is "pause" for one second, useful when driving menus
+ \1-\9 is F-key, \0 is F10
+
+ TODO(jhaas): support for explicit control of SHIFT, support for
+ nonprintable keys (F-keys, ESC, arrow keys, etc),
+ support for explicit control of left vs. right ALT or SHIFT,
+ support for Windows key
+
+ keystroke_time: length of time (in secondes) to "hold down" the key
+ time_between_keystrokes: length of time (seconds) to pause between keys
+
+ Returns:
+ None
+ """
+
+ shift_held = win32api.GetAsyncKeyState(win32con.VK_SHIFT ) < 0
+ ctrl_held = win32api.GetAsyncKeyState(win32con.VK_CONTROL) < 0
+ alt_held = win32api.GetAsyncKeyState(win32con.VK_MENU ) < 0
+
+ next_escaped = False
+ escape_chars = {
+ 'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v'}
+
+ for char in string_to_type:
+ vk = None
+ handled = False
+
+ # Check to see if this is the start or end of a modified block (that is,
+ # {abc} for ALT-modified keys or [abc] for CTRL-modified keys
+ if use_modifiers and not next_escaped:
+ handled = True
+ if char == "{" and not alt_held:
+ alt_held = True
+ PressKey(True, win32con.VK_MENU)
+ elif char == "}" and alt_held:
+ alt_held = False
+ PressKey(False, win32con.VK_MENU)
+ elif char == "[" and not ctrl_held:
+ ctrl_held = True
+ PressKey(True, win32con.VK_CONTROL)
+ elif char == "]" and ctrl_held:
+ ctrl_held = False
+ PressKey(False, win32con.VK_CONTROL)
+ else:
+ handled = False
+
+ # If this is an explicitly-escaped character, replace it with the
+ # appropriate code
+ if next_escaped and char in escape_chars: char = escape_chars[char]
+
+ # If this is \p, pause for one second.
+ if next_escaped and char == 'p':
+ time.sleep(1)
+ next_escaped = False
+ handled = True
+
+ # If this is \(d), press F key
+ if next_escaped and char.isdigit():
+ fkey = int(char)
+ if not fkey: fkey = 10
+ next_escaped = False
+ vk = win32con.VK_F1 + fkey - 1
+
+ # If this is the backslash, the next character is escaped
+ if not next_escaped and char == "\\":
+ next_escaped = True
+ handled = True
+
+ # If we make it here, it's not a special character, or it's an
+ # escaped special character which should be treated as a literal
+ if not handled:
+ next_escaped = False
+ if not vk: vk = win32api.VkKeyScan(char)
+
+ # VkKeyScan() returns the scan code in the low byte. The upper
+ # byte specifies modifiers necessary to produce the given character
+ # from the given scan code. The only one we're concerned with at the
+ # moment is Shift. Determine the shift state and compare it to the
+ # current state... if it differs, press or release the shift key.
+ new_shift_held = bool(vk & (1<<8))
+
+ if new_shift_held != shift_held:
+ PressKey(new_shift_held, win32con.VK_SHIFT)
+ shift_held = new_shift_held
+
+ # Type the key with the specified length, then wait the specified delay
+ TypeKey(vk & 0xFF, keystroke_time)
+ time.sleep(time_between_keystrokes)
+
+ # Release the modifier keys, if held
+ if shift_held: PressKey(False, win32con.VK_SHIFT)
+ if ctrl_held: PressKey(False, win32con.VK_CONTROL)
+ if alt_held: PressKey(False, win32con.VK_MENU)
+
+
+def main():
+ # We're being invoked rather than imported. Let's do some tests
+
+ # Press command-R to bring up the Run dialog
+ PressKey(True, win32con.VK_LWIN)
+ TypeKey(ord('R'))
+ PressKey(False, win32con.VK_LWIN)
+
+ # Wait a sec to make sure it comes up
+ time.sleep(1)
+
+ # Invoke Notepad through the Run dialog
+ TypeString("wordpad\n")
+
+ # Wait another sec, then start typing
+ time.sleep(1)
+ TypeString("This is a test of SiteCompare's Keyboard.py module.\n\n")
+ TypeString("There should be a blank line above and below this one.\n\n")
+ TypeString("This line has control characters to make "
+ "[b]boldface text[b] and [i]italic text[i] and normal text.\n\n",
+ use_modifiers=True)
+ TypeString(r"This line should be typed with a visible delay between "
+ "characters. When it ends, there should be a 3-second pause, "
+ "then the menu will select File/Exit, then another 3-second "
+ "pause, then No to exit without saving. Ready?\p\p\p{f}x\p\p\pn",
+ use_modifiers=True,
+ keystroke_time=0.05,
+ time_between_keystrokes=0.05)
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/site_compare/drivers/win32/mouse.py b/chromium/tools/site_compare/drivers/win32/mouse.py
new file mode 100755
index 00000000000..0096af987ca
--- /dev/null
+++ b/chromium/tools/site_compare/drivers/win32/mouse.py
@@ -0,0 +1,222 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""SiteCompare module for simulating mouse input.
+
+This module contains functions that can be used to simulate a user
+navigating using a pointing device. This includes mouse movement,
+clicking with any button, and dragging.
+"""
+
+import time # for sleep
+
+import win32api # for mouse_event
+import win32con # Windows constants
+import win32gui # for window functions
+
+
+def ScreenToMouse(pt):
+ """Convert a value in screen coordinates to mouse coordinates.
+
+ Mouse coordinates are specified as a percentage of screen dimensions,
+ normalized to 16 bits. 0 represents the far left/top of the screen,
+ 65535 represents the far right/bottom. This function assumes that
+ the size of the screen is fixed at module load time and does not change
+
+ Args:
+ pt: the point of the coords to convert
+
+ Returns:
+ the converted point
+ """
+
+ # Initialize the screen dimensions on first execution. Note that this
+ # function assumes that the screen dimensions do not change during run.
+ if not ScreenToMouse._SCREEN_DIMENSIONS:
+ desktop = win32gui.GetClientRect(win32gui.GetDesktopWindow())
+ ScreenToMouse._SCREEN_DIMENSIONS = (desktop[2], desktop[3])
+
+ return ((65535 * pt[0]) / ScreenToMouse._SCREEN_DIMENSIONS[0],
+ (65535 * pt[1]) / ScreenToMouse._SCREEN_DIMENSIONS[1])
+
+ScreenToMouse._SCREEN_DIMENSIONS = None
+
+
+def PressButton(down, button='left'):
+ """Simulate a mouse button press or release at the current mouse location.
+
+ Args:
+ down: whether the button is pressed or released
+ button: which button is pressed
+
+ Returns:
+ None
+ """
+
+ # Put the mouse_event flags in a convenient dictionary by button
+ flags = {
+ 'left': (win32con.MOUSEEVENTF_LEFTUP, win32con.MOUSEEVENTF_LEFTDOWN),
+ 'middle': (win32con.MOUSEEVENTF_MIDDLEUP, win32con.MOUSEEVENTF_MIDDLEDOWN),
+ 'right': (win32con.MOUSEEVENTF_RIGHTUP, win32con.MOUSEEVENTF_RIGHTDOWN)
+ }
+
+ # hit the button
+ win32api.mouse_event(flags[button][down], 0, 0)
+
+
+def ClickButton(button='left', click_time=0):
+ """Press and release a mouse button at the current mouse location.
+
+ Args:
+ button: which button to click
+ click_time: duration between press and release
+
+ Returns:
+ None
+ """
+ PressButton(True, button)
+ time.sleep(click_time)
+ PressButton(False, button)
+
+
+def DoubleClickButton(button='left', click_time=0, time_between_clicks=0):
+ """Double-click a mouse button at the current mouse location.
+
+ Args:
+ button: which button to click
+ click_time: duration between press and release
+ time_between_clicks: time to pause between clicks
+
+ Returns:
+ None
+ """
+ ClickButton(button, click_time)
+ time.sleep(time_between_clicks)
+ ClickButton(button, click_time)
+
+
+def MoveToLocation(pos, duration=0, tick=0.01):
+ """Move the mouse cursor to a specified location, taking the specified time.
+
+ Args:
+ pos: position (in screen coordinates) to move to
+ duration: amount of time the move should take
+ tick: amount of time between successive moves of the mouse
+
+ Returns:
+ None
+ """
+ # calculate the number of moves to reach the destination
+ num_steps = (duration/tick)+1
+
+ # get the current and final mouse position in mouse coords
+ current_location = ScreenToMouse(win32gui.GetCursorPos())
+ end_location = ScreenToMouse(pos)
+
+ # Calculate the step size
+ step_size = ((end_location[0]-current_location[0])/num_steps,
+ (end_location[1]-current_location[1])/num_steps)
+ step = 0
+
+ while step < num_steps:
+ # Move the mouse one step
+ current_location = (current_location[0]+step_size[0],
+ current_location[1]+step_size[1])
+
+ # Coerce the coords to int to avoid a warning from pywin32
+ win32api.mouse_event(
+ win32con.MOUSEEVENTF_MOVE|win32con.MOUSEEVENTF_ABSOLUTE,
+ int(current_location[0]), int(current_location[1]))
+
+ step += 1
+ time.sleep(tick)
+
+
+def ClickAtLocation(pos, button='left', click_time=0):
+ """Simulate a mouse click in a particular location, in screen coordinates.
+
+ Args:
+ pos: position in screen coordinates (x,y)
+ button: which button to click
+ click_time: duration of the click
+
+ Returns:
+ None
+ """
+ MoveToLocation(pos)
+ ClickButton(button, click_time)
+
+
+def ClickInWindow(hwnd, offset=None, button='left', click_time=0):
+ """Simulate a user mouse click in the center of a window.
+
+ Args:
+ hwnd: handle of the window to click in
+ offset: where to click, defaults to dead center
+ button: which button to click
+ click_time: duration of the click
+
+ Returns:
+ Nothing
+ """
+
+ rect = win32gui.GetClientRect(hwnd)
+ if offset is None: offset = (rect[2]/2, rect[3]/2)
+
+ # get the screen coordinates of the window's center
+ pos = win32gui.ClientToScreen(hwnd, offset)
+
+ ClickAtLocation(pos, button, click_time)
+
+
+def DoubleClickInWindow(
+ hwnd, offset=None, button='left', click_time=0, time_between_clicks=0.1):
+ """Simulate a user mouse double click in the center of a window.
+
+ Args:
+ hwnd: handle of the window to click in
+ offset: where to click, defaults to dead center
+ button: which button to click
+ click_time: duration of the clicks
+ time_between_clicks: length of time to pause between clicks
+
+ Returns:
+ Nothing
+ """
+ ClickInWindow(hwnd, offset, button, click_time)
+ time.sleep(time_between_clicks)
+ ClickInWindow(hwnd, offset, button, click_time)
+
+
+def main():
+ # We're being invoked rather than imported. Let's do some tests
+
+ screen_size = win32gui.GetClientRect(win32gui.GetDesktopWindow())
+ screen_size = (screen_size[2], screen_size[3])
+
+ # move the mouse (instantly) to the upper right corner
+ MoveToLocation((screen_size[0], 0))
+
+ # move the mouse (over five seconds) to the lower left corner
+ MoveToLocation((0, screen_size[1]), 5)
+
+ # click the left mouse button. This will open up the Start menu
+ # if the taskbar is at the bottom
+
+ ClickButton()
+
+ # wait a bit, then click the right button to open the context menu
+ time.sleep(3)
+ ClickButton('right')
+
+ # move the mouse away and then click the left button to dismiss the
+ # context menu
+ MoveToLocation((screen_size[0]/2, screen_size[1]/2), 3)
+ MoveToLocation((0, 0), 3)
+ ClickButton()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/site_compare/drivers/win32/windowing.py b/chromium/tools/site_compare/drivers/win32/windowing.py
new file mode 100755
index 00000000000..47d63f02272
--- /dev/null
+++ b/chromium/tools/site_compare/drivers/win32/windowing.py
@@ -0,0 +1,366 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""SiteCompare module for invoking, locating, and manipulating windows.
+
+This module is a catch-all wrapper for operating system UI functionality
+that doesn't belong in other modules. It contains functions for finding
+particular windows, scraping their contents, and invoking processes to
+create them.
+"""
+
+import os
+import string
+import time
+
+import PIL.ImageGrab
+import pywintypes
+import win32event
+import win32gui
+import win32process
+
+
+def FindChildWindows(hwnd, path):
+ """Find a set of windows through a path specification.
+
+ Args:
+ hwnd: Handle of the parent window
+ path: Path to the window to find. Has the following form:
+ "foo/bar/baz|foobar/|foobarbaz"
+ The slashes specify the "path" to the child window.
+ The text is the window class, a pipe (if present) is a title.
+ * is a wildcard and will find all child windows at that level
+
+ Returns:
+ A list of the windows that were found
+ """
+ windows_to_check = [hwnd]
+
+ # The strategy will be to take windows_to_check and use it
+ # to find a list of windows that match the next specification
+ # in the path, then repeat with the list of found windows as the
+ # new list of windows to check
+ for segment in path.split("/"):
+ windows_found = []
+ check_values = segment.split("|")
+
+ # check_values is now a list with the first element being
+ # the window class, the second being the window caption.
+ # If the class is absent (or wildcarded) set it to None
+ if check_values[0] == "*" or not check_values[0]: check_values[0] = None
+
+ # If the window caption is also absent, force it to None as well
+ if len(check_values) == 1: check_values.append(None)
+
+ # Loop through the list of windows to check
+ for window_check in windows_to_check:
+ window_found = None
+ while window_found != 0: # lint complains, but 0 != None
+ if window_found is None: window_found = 0
+ try:
+ # Look for the next sibling (or first sibling if window_found is 0)
+ # of window_check with the specified caption and/or class
+ window_found = win32gui.FindWindowEx(
+ window_check, window_found, check_values[0], check_values[1])
+ except pywintypes.error, e:
+ # FindWindowEx() raises error 2 if not found
+ if e[0] == 2:
+ window_found = 0
+ else:
+ raise e
+
+ # If FindWindowEx struck gold, add to our list of windows found
+ if window_found: windows_found.append(window_found)
+
+ # The windows we found become the windows to check for the next segment
+ windows_to_check = windows_found
+
+ return windows_found
+
+
+def FindChildWindow(hwnd, path):
+ """Find a window through a path specification.
+
+ This method is a simple wrapper for FindChildWindows() for the
+ case (the majority case) where you expect to find a single window
+
+ Args:
+ hwnd: Handle of the parent window
+ path: Path to the window to find. See FindChildWindows()
+
+ Returns:
+ The window that was found
+ """
+ return FindChildWindows(hwnd, path)[0]
+
+
+def ScrapeWindow(hwnd, rect=None):
+ """Scrape a visible window and return its contents as a bitmap.
+
+ Args:
+ hwnd: handle of the window to scrape
+ rect: rectangle to scrape in client coords, defaults to the whole thing
+ If specified, it's a 4-tuple of (left, top, right, bottom)
+
+ Returns:
+ An Image containing the scraped data
+ """
+ # Activate the window
+ SetForegroundWindow(hwnd)
+
+ # If no rectangle was specified, use the fill client rectangle
+ if not rect: rect = win32gui.GetClientRect(hwnd)
+
+ upper_left = win32gui.ClientToScreen(hwnd, (rect[0], rect[1]))
+ lower_right = win32gui.ClientToScreen(hwnd, (rect[2], rect[3]))
+ rect = upper_left+lower_right
+
+ return PIL.ImageGrab.grab(rect)
+
+
+def SetForegroundWindow(hwnd):
+ """Bring a window to the foreground."""
+ win32gui.SetForegroundWindow(hwnd)
+
+
+def InvokeAndWait(path, cmdline="", timeout=10, tick=1.):
+ """Invoke an application and wait for it to bring up a window.
+
+ Args:
+ path: full path to the executable to invoke
+ cmdline: command line to pass to executable
+ timeout: how long (in seconds) to wait before giving up
+ tick: length of time to wait between checks
+
+ Returns:
+ A tuple of handles to the process and the application's window,
+ or (None, None) if it timed out waiting for the process
+ """
+
+ def EnumWindowProc(hwnd, ret):
+ """Internal enumeration func, checks for visibility and proper PID."""
+ if win32gui.IsWindowVisible(hwnd): # don't bother even checking hidden wnds
+ pid = win32process.GetWindowThreadProcessId(hwnd)[1]
+ if pid == ret[0]:
+ ret[1] = hwnd
+ return 0 # 0 means stop enumeration
+ return 1 # 1 means continue enumeration
+
+ # We don't need to change anything about the startupinfo structure
+ # (the default is quite sufficient) but we need to create it just the
+ # same.
+ sinfo = win32process.STARTUPINFO()
+
+ proc = win32process.CreateProcess(
+ path, # path to new process's executable
+ cmdline, # application's command line
+ None, # process security attributes (default)
+ None, # thread security attributes (default)
+ False, # inherit parent's handles
+ 0, # creation flags
+ None, # environment variables
+ None, # directory
+ sinfo) # default startup info
+
+ # Create process returns (prochandle, pid, threadhandle, tid). At
+ # some point we may care about the other members, but for now, all
+ # we're after is the pid
+ pid = proc[2]
+
+ # Enumeration APIs can take an arbitrary integer, usually a pointer,
+ # to be passed to the enumeration function. We'll pass a pointer to
+ # a structure containing the PID we're looking for, and an empty out
+ # parameter to hold the found window ID
+ ret = [pid, None]
+
+ tries_until_timeout = timeout/tick
+ num_tries = 0
+
+ # Enumerate top-level windows, look for one with our PID
+ while num_tries < tries_until_timeout and ret[1] is None:
+ try:
+ win32gui.EnumWindows(EnumWindowProc, ret)
+ except pywintypes.error, e:
+ # error 0 isn't an error, it just meant the enumeration was
+ # terminated early
+ if e[0]: raise e
+
+ time.sleep(tick)
+ num_tries += 1
+
+ # TODO(jhaas): Should we throw an exception if we timeout? Or is returning
+ # a window ID of None sufficient?
+ return (proc[0], ret[1])
+
+
+def WaitForProcessExit(proc, timeout=None):
+ """Waits for a given process to terminate.
+
+ Args:
+ proc: handle to process
+ timeout: timeout (in seconds). None = wait indefinitely
+
+ Returns:
+ True if process ended, False if timed out
+ """
+ if timeout is None:
+ timeout = win32event.INFINITE
+ else:
+ # convert sec to msec
+ timeout *= 1000
+
+ return (win32event.WaitForSingleObject(proc, timeout) ==
+ win32event.WAIT_OBJECT_0)
+
+
+def WaitForThrobber(hwnd, rect=None, timeout=20, tick=0.1, done=10):
+ """Wait for a browser's "throbber" (loading animation) to complete.
+
+ Args:
+ hwnd: window containing the throbber
+ rect: rectangle of the throbber, in client coords. If None, whole window
+ timeout: if the throbber is still throbbing after this long, give up
+ tick: how often to check the throbber
+ done: how long the throbber must be unmoving to be considered done
+
+ Returns:
+ Number of seconds waited, -1 if timed out
+ """
+ if not rect: rect = win32gui.GetClientRect(hwnd)
+
+ # last_throbber will hold the results of the preceding scrape;
+ # we'll compare it against the current scrape to see if we're throbbing
+ last_throbber = ScrapeWindow(hwnd, rect)
+ start_clock = time.clock()
+ timeout_clock = start_clock + timeout
+ last_changed_clock = start_clock;
+
+ while time.clock() < timeout_clock:
+ time.sleep(tick)
+
+ current_throbber = ScrapeWindow(hwnd, rect)
+ if current_throbber.tostring() != last_throbber.tostring():
+ last_throbber = current_throbber
+ last_changed_clock = time.clock()
+ else:
+ if time.clock() - last_changed_clock > done:
+ return last_changed_clock - start_clock
+
+ return -1
+
+
+def MoveAndSizeWindow(wnd, position=None, size=None, child=None):
+ """Moves and/or resizes a window.
+
+ Repositions and resizes a window. If a child window is provided,
+ the parent window is resized so the child window has the given size
+
+ Args:
+ wnd: handle of the frame window
+ position: new location for the frame window
+ size: new size for the frame window (or the child window)
+ child: handle of the child window
+
+ Returns:
+ None
+ """
+ rect = win32gui.GetWindowRect(wnd)
+
+ if position is None: position = (rect[0], rect[1])
+ if size is None:
+ size = (rect[2]-rect[0], rect[3]-rect[1])
+ elif child is not None:
+ child_rect = win32gui.GetWindowRect(child)
+ slop = (rect[2]-rect[0]-child_rect[2]+child_rect[0],
+ rect[3]-rect[1]-child_rect[3]+child_rect[1])
+ size = (size[0]+slop[0], size[1]+slop[1])
+
+ win32gui.MoveWindow(wnd, # window to move
+ position[0], # new x coord
+ position[1], # new y coord
+ size[0], # new width
+ size[1], # new height
+ True) # repaint?
+
+
+def EndProcess(proc, code=0):
+ """Ends a process.
+
+ Wraps the OS TerminateProcess call for platform-independence
+
+ Args:
+ proc: process ID
+ code: process exit code
+
+ Returns:
+ None
+ """
+ win32process.TerminateProcess(proc, code)
+
+
+def URLtoFilename(url, path=None, extension=None):
+ """Converts a URL to a filename, given a path.
+
+ This in theory could cause collisions if two URLs differ only
+ in unprintable characters (eg. http://www.foo.com/?bar and
+ http://www.foo.com/:bar. In practice this shouldn't be a problem.
+
+ Args:
+ url: The URL to convert
+ path: path to the directory to store the file
+ extension: string to append to filename
+
+ Returns:
+ filename
+ """
+ trans = string.maketrans(r'\/:*?"<>|', '_________')
+
+ if path is None: path = ""
+ if extension is None: extension = ""
+ if len(path) > 0 and path[-1] != '\\': path += '\\'
+ url = url.translate(trans)
+ return "%s%s%s" % (path, url, extension)
+
+
+def PreparePath(path):
+ """Ensures that a given path exists, making subdirectories if necessary.
+
+ Args:
+ path: fully-qualified path of directory to ensure exists
+
+ Returns:
+ None
+ """
+ try:
+ os.makedirs(path)
+ except OSError, e:
+ if e[0] != 17: raise e # error 17: path already exists
+
+
+def main():
+ PreparePath(r"c:\sitecompare\scrapes\ie7")
+ # We're being invoked rather than imported. Let's do some tests
+
+ # Hardcode IE's location for the purpose of this test
+ (proc, wnd) = InvokeAndWait(
+ r"c:\program files\internet explorer\iexplore.exe")
+
+ # Find the browser pane in the IE window
+ browser = FindChildWindow(
+ wnd, "TabWindowClass/Shell DocObject View/Internet Explorer_Server")
+
+ # Move and size the window
+ MoveAndSizeWindow(wnd, (0, 0), (1024, 768), browser)
+
+ # Take a screenshot
+ i = ScrapeWindow(browser)
+
+ i.show()
+
+ EndProcess(proc, 0)
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/site_compare/operators/__init__.py b/chromium/tools/site_compare/operators/__init__.py
new file mode 100644
index 00000000000..5d6ffd7555a
--- /dev/null
+++ b/chromium/tools/site_compare/operators/__init__.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Selects the appropriate operator."""
+
+
+def GetOperator(operator):
+ """Given an operator by name, returns its module.
+
+ Args:
+ operator: string describing the comparison
+
+ Returns:
+ module
+ """
+
+ # TODO(jhaas): come up with a happy way of integrating multiple operators
+ # with different, possibly divergent and possibly convergent, operators.
+
+ module = __import__(operator, globals(), locals(), [''])
+
+ return module
diff --git a/chromium/tools/site_compare/operators/equals.py b/chromium/tools/site_compare/operators/equals.py
new file mode 100644
index 00000000000..311f530a059
--- /dev/null
+++ b/chromium/tools/site_compare/operators/equals.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Compare two images for equality."""
+
+from PIL import Image
+from PIL import ImageChops
+
+
+def Compare(file1, file2, **kwargs):
+ """Compares two images to see if they're identical.
+
+ Args:
+ file1: path to first image to compare
+ file2: path to second image to compare
+ kwargs: unused for this operator
+
+ Returns:
+ None if the images are identical
+ A tuple of (errorstring, image) if they're not
+ """
+ kwargs = kwargs # unused parameter
+
+ im1 = Image.open(file1)
+ im2 = Image.open(file2)
+
+ if im1.size != im2.size:
+ return ("The images are of different size (%s vs %s)" %
+ (im1.size, im2.size), im1)
+
+ diff = ImageChops.difference(im1, im2)
+
+ if max(diff.getextrema()) != (0, 0):
+ return ("The images differ", diff)
+ else:
+ return None
diff --git a/chromium/tools/site_compare/operators/equals_with_mask.py b/chromium/tools/site_compare/operators/equals_with_mask.py
new file mode 100644
index 00000000000..e42f7e16a91
--- /dev/null
+++ b/chromium/tools/site_compare/operators/equals_with_mask.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Compare two images for equality, subject to a mask."""
+
+from PIL import Image
+from PIL import ImageChops
+
+import os.path
+
+
+def Compare(file1, file2, **kwargs):
+ """Compares two images to see if they're identical subject to a mask.
+
+ An optional directory containing masks is supplied. If a mask exists
+ which matches file1's name, areas under the mask where it's black
+ are ignored.
+
+ Args:
+ file1: path to first image to compare
+ file2: path to second image to compare
+ kwargs: ["maskdir"] contains the directory holding the masks
+
+ Returns:
+ None if the images are identical
+ A tuple of (errorstring, image) if they're not
+ """
+
+ maskdir = None
+ if "maskdir" in kwargs:
+ maskdir = kwargs["maskdir"]
+
+ im1 = Image.open(file1)
+ im2 = Image.open(file2)
+
+ if im1.size != im2.size:
+ return ("The images are of different size (%r vs %r)" %
+ (im1.size, im2.size), im1)
+
+ diff = ImageChops.difference(im1, im2)
+
+ if maskdir:
+ maskfile = os.path.join(maskdir, os.path.basename(file1))
+ if os.path.exists(maskfile):
+ mask = Image.open(maskfile)
+
+ if mask.size != im1.size:
+ return ("The mask is of a different size than the images (%r vs %r)" %
+ (mask.size, im1.size), mask)
+
+ diff = ImageChops.multiply(diff, mask.convert(diff.mode))
+
+ if max(diff.getextrema()) != (0, 0):
+ return ("The images differ", diff)
+ else:
+ return None
diff --git a/chromium/tools/site_compare/scrapers/__init__.py b/chromium/tools/site_compare/scrapers/__init__.py
new file mode 100755
index 00000000000..5f6d77885b7
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/__init__.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Selects the appropriate scraper for a given browser and version."""
+
+import types
+
+# TODO(jhaas): unify all optional scraper parameters into kwargs
+
+def GetScraper(browser):
+ """Given a browser and an optional version, returns the scraper module.
+
+ Args:
+ browser: either a string (browser name) or a tuple (name, version)
+
+ Returns:
+ module
+ """
+
+ if type(browser) == types.StringType: browser = (browser, None)
+
+ package = __import__(browser[0], globals(), locals(), [''])
+ module = package.GetScraper(browser[1])
+ if browser[1] is not None: module.version = browser[1]
+
+ return module
+
+
+# if invoked rather than imported, do some tests
+if __name__ == "__main__":
+ print GetScraper("IE")
diff --git a/chromium/tools/site_compare/scrapers/chrome/__init__.py b/chromium/tools/site_compare/scrapers/chrome/__init__.py
new file mode 100755
index 00000000000..587a50db735
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/chrome/__init__.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Selects the appropriate scraper for Chrome."""
+
+
+def GetScraper(version):
+ """Returns the scraper module for the given version.
+
+ Args:
+ version: version string of Chrome, or None for most recent
+
+ Returns:
+ scrape module for given version
+ """
+ if version is None:
+ version = "0.1.101.0"
+
+ parsed_version = [int(x) for x in version.split(".")]
+
+ if (parsed_version[0] > 0 or
+ parsed_version[1] > 1 or
+ parsed_version[2] > 97 or
+ parsed_version[3] > 0):
+ scraper_version = "chrome011010"
+ else:
+ scraper_version = "chrome01970"
+
+ return __import__(scraper_version, globals(), locals(), [''])
+
+
+# if invoked rather than imported, test
+if __name__ == "__main__":
+ print GetScraper("0.1.101.0").version
diff --git a/chromium/tools/site_compare/scrapers/chrome/chrome011010.py b/chromium/tools/site_compare/scrapers/chrome/chrome011010.py
new file mode 100644
index 00000000000..6f0dfb4bf7c
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/chrome/chrome011010.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Does scraping for versions of Chrome from 0.1.101.0 up."""
+
+from drivers import windowing
+
+import chromebase
+
+# Default version
+version = "0.1.101.0"
+
+
+def GetChromeRenderPane(wnd):
+ return windowing.FindChildWindow(wnd, "Chrome_TabContents")
+
+
+def Scrape(urls, outdir, size, pos, timeout=20, **kwargs):
+ """Invoke a browser, send it to a series of URLs, and save its output.
+
+ Args:
+ urls: list of URLs to scrape
+ outdir: directory to place output
+ size: size of browser window to use
+ pos: position of browser window
+ timeout: amount of time to wait for page to load
+ kwargs: miscellaneous keyword args
+
+ Returns:
+ None if succeeded, else an error code
+ """
+ chromebase.GetChromeRenderPane = GetChromeRenderPane
+
+ return chromebase.Scrape(urls, outdir, size, pos, timeout, kwargs)
+
+
+def Time(urls, size, timeout, **kwargs):
+ """Forwards the Time command to chromebase."""
+ chromebase.GetChromeRenderPane = GetChromeRenderPane
+
+ return chromebase.Time(urls, size, timeout, kwargs)
diff --git a/chromium/tools/site_compare/scrapers/chrome/chrome01970.py b/chromium/tools/site_compare/scrapers/chrome/chrome01970.py
new file mode 100644
index 00000000000..2f237fa4df4
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/chrome/chrome01970.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Does scraping for versions of Chrome up to 0.1.97.0."""
+
+from drivers import windowing
+
+import chromebase
+
+# Default version
+version = "0.1.97.0"
+
+
+def GetChromeRenderPane(wnd):
+ return windowing.FindChildWindow(wnd, "Chrome_BrowserWindow")
+
+
+def Scrape(urls, outdir, size, pos, timeout=20, **kwargs):
+ """Invoke a browser, send it to a series of URLs, and save its output.
+
+ Args:
+ urls: list of URLs to scrape
+ outdir: directory to place output
+ size: size of browser window to use
+ pos: position of browser window
+ timeout: amount of time to wait for page to load
+ kwargs: miscellaneous keyword args
+
+ Returns:
+ None if succeeded, else an error code
+ """
+ chromebase.GetChromeRenderPane = GetChromeRenderPane
+
+ return chromebase.Scrape(urls, outdir, size, pos, timeout, kwargs)
+
+
+def Time(urls, size, timeout, **kwargs):
+ """Forwards the Time command to chromebase."""
+ chromebase.GetChromeRenderPane = GetChromeRenderPane
+
+ return chromebase.Time(urls, size, timeout, kwargs)
diff --git a/chromium/tools/site_compare/scrapers/chrome/chromebase.py b/chromium/tools/site_compare/scrapers/chrome/chromebase.py
new file mode 100755
index 00000000000..2b8f1774cc4
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/chrome/chromebase.py
@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Does scraping for all currently-known versions of Chrome"""
+
+import pywintypes
+import types
+
+from drivers import keyboard
+from drivers import mouse
+from drivers import windowing
+
+
+# TODO: this has moved, use some logic to find it. For now,
+# expects a subst k:.
+DEFAULT_PATH = r"k:\chrome.exe"
+
+
+def InvokeBrowser(path):
+ """Invoke the Chrome browser.
+
+ Args:
+ path: full path to browser
+
+ Returns:
+ A tuple of (main window, process handle, address bar, render pane)
+ """
+
+ # Reuse an existing instance of the browser if we can find one. This
+ # may not work correctly, especially if the window is behind other windows.
+
+ # TODO(jhaas): make this work with Vista
+ wnds = windowing.FindChildWindows(0, "Chrome_XPFrame")
+ if len(wnds):
+ wnd = wnds[0]
+ proc = None
+ else:
+ # Invoke Chrome
+ (proc, wnd) = windowing.InvokeAndWait(path)
+
+ # Get windows we'll need
+ address_bar = windowing.FindChildWindow(wnd, "Chrome_AutocompleteEdit")
+ render_pane = GetChromeRenderPane(wnd)
+
+ return (wnd, proc, address_bar, render_pane)
+
+
+def Scrape(urls, outdir, size, pos, timeout, kwargs):
+ """Invoke a browser, send it to a series of URLs, and save its output.
+
+ Args:
+ urls: list of URLs to scrape
+ outdir: directory to place output
+ size: size of browser window to use
+ pos: position of browser window
+ timeout: amount of time to wait for page to load
+ kwargs: miscellaneous keyword args
+
+ Returns:
+ None if success, else an error string
+ """
+ if "path" in kwargs and kwargs["path"]: path = kwargs["path"]
+ else: path = DEFAULT_PATH
+
+ (wnd, proc, address_bar, render_pane) = InvokeBrowser(path)
+
+ # Resize and reposition the frame
+ windowing.MoveAndSizeWindow(wnd, pos, size, render_pane)
+
+ # Visit each URL we're given
+ if type(urls) in types.StringTypes: urls = [urls]
+
+ timedout = False
+
+ for url in urls:
+ # Double-click in the address bar, type the name, and press Enter
+ mouse.ClickInWindow(address_bar)
+ keyboard.TypeString(url, 0.1)
+ keyboard.TypeString("\n")
+
+ # Wait for the page to finish loading
+ load_time = windowing.WaitForThrobber(wnd, (20, 16, 36, 32), timeout)
+ timedout = load_time < 0
+
+ if timedout:
+ break
+
+ # Scrape the page
+ image = windowing.ScrapeWindow(render_pane)
+
+ # Save to disk
+ if "filename" in kwargs:
+ if callable(kwargs["filename"]):
+ filename = kwargs["filename"](url)
+ else:
+ filename = kwargs["filename"]
+ else:
+ filename = windowing.URLtoFilename(url, outdir, ".bmp")
+ image.save(filename)
+
+ if proc:
+ windowing.SetForegroundWindow(wnd)
+
+ # Send Alt-F4, then wait for process to end
+ keyboard.TypeString(r"{\4}", use_modifiers=True)
+ if not windowing.WaitForProcessExit(proc, timeout):
+ windowing.EndProcess(proc)
+ return "crashed"
+
+ if timedout:
+ return "timeout"
+
+ return None
+
+
+def Time(urls, size, timeout, kwargs):
+ """Measure how long it takes to load each of a series of URLs
+
+ Args:
+ urls: list of URLs to time
+ size: size of browser window to use
+ timeout: amount of time to wait for page to load
+ kwargs: miscellaneous keyword args
+
+ Returns:
+ A list of tuples (url, time). "time" can be "crashed" or "timeout"
+ """
+ if "path" in kwargs and kwargs["path"]: path = kwargs["path"]
+ else: path = DEFAULT_PATH
+ proc = None
+
+ # Visit each URL we're given
+ if type(urls) in types.StringTypes: urls = [urls]
+
+ ret = []
+ for url in urls:
+ try:
+ # Invoke the browser if necessary
+ if not proc:
+ (wnd, proc, address_bar, render_pane) = InvokeBrowser(path)
+
+ # Resize and reposition the frame
+ windowing.MoveAndSizeWindow(wnd, (0,0), size, render_pane)
+
+ # Double-click in the address bar, type the name, and press Enter
+ mouse.ClickInWindow(address_bar)
+ keyboard.TypeString(url, 0.1)
+ keyboard.TypeString("\n")
+
+ # Wait for the page to finish loading
+ load_time = windowing.WaitForThrobber(wnd, (20, 16, 36, 32), timeout)
+
+ timedout = load_time < 0
+
+ if timedout:
+ load_time = "timeout"
+
+ # Send an alt-F4 to make the browser close; if this times out,
+ # we've probably got a crash
+ windowing.SetForegroundWindow(wnd)
+
+ keyboard.TypeString(r"{\4}", use_modifiers=True)
+ if not windowing.WaitForProcessExit(proc, timeout):
+ windowing.EndProcess(proc)
+ load_time = "crashed"
+ proc = None
+ except pywintypes.error:
+ proc = None
+ load_time = "crashed"
+
+ ret.append( (url, load_time) )
+
+ if proc:
+ windowing.SetForegroundWindow(wnd)
+ keyboard.TypeString(r"{\4}", use_modifiers=True)
+ if not windowing.WaitForProcessExit(proc, timeout):
+ windowing.EndProcess(proc)
+
+ return ret
+
+
+def main():
+ # We're being invoked rather than imported, so run some tests
+ path = r"c:\sitecompare\scrapes\chrome\0.1.97.0"
+ windowing.PreparePath(path)
+
+ # Scrape three sites and save the results
+ Scrape([
+ "http://www.microsoft.com",
+ "http://www.google.com",
+ "http://www.sun.com"],
+ path, (1024, 768), (0, 0))
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/site_compare/scrapers/firefox/__init__.py b/chromium/tools/site_compare/scrapers/firefox/__init__.py
new file mode 100755
index 00000000000..34c0699f072
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/firefox/__init__.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Selects the appropriate scraper for Firefox."""
+
+
+def GetScraper(version):
+ """Returns the scraper module for the given version.
+
+ Args:
+ version: version string of IE, or None for most recent
+
+ Returns:
+ scrape module for given version
+ """
+
+ # Pychecker will warn that the parameter is unused; we only
+ # support one version of Firefox at this time
+
+ # We only have one version of the Firefox scraper for now
+ return __import__("firefox2", globals(), locals(), [''])
+
+
+# if invoked rather than imported, test
+if __name__ == "__main__":
+ print GetScraper("2.0.0.6").version
diff --git a/chromium/tools/site_compare/scrapers/firefox/firefox2.py b/chromium/tools/site_compare/scrapers/firefox/firefox2.py
new file mode 100755
index 00000000000..2181f588f81
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/firefox/firefox2.py
@@ -0,0 +1,249 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Does scraping for Firefox 2.0."""
+
+import pywintypes
+import time
+import types
+
+from drivers import keyboard
+from drivers import mouse
+from drivers import windowing
+
+# Default version
+version = "2.0.0.6"
+
+DEFAULT_PATH = r"c:\program files\mozilla firefox\firefox.exe"
+
+# TODO(jhaas): the Firefox scraper is a bit rickety at the moment. Known
+# issues: 1) won't work if the default profile puts toolbars in different
+# locations, 2) uses sleep() statements rather than more robust checks,
+# 3) fails badly if an existing Firefox window is open when the scrape
+# is invoked. This needs to be fortified at some point.
+
+def GetBrowser(path):
+ """Invoke the Firefox browser and return the process and window.
+
+ Args:
+ path: full path to browser
+
+ Returns:
+ A tuple of (process handle, render pane)
+ """
+ if not path: path = DEFAULT_PATH
+
+ # Invoke Firefox
+ (proc, wnd) = windowing.InvokeAndWait(path)
+
+ # Get the content pane
+ render_pane = windowing.FindChildWindow(
+ wnd,
+ "MozillaWindowClass/MozillaWindowClass/MozillaWindowClass")
+
+ return (proc, wnd, render_pane)
+
+
+def InvokeBrowser(path):
+ """Invoke the Firefox browser.
+
+ Args:
+ path: full path to browser
+
+ Returns:
+ A tuple of (main window, process handle, render pane)
+ """
+ # Reuse an existing instance of the browser if we can find one. This
+ # may not work correctly, especially if the window is behind other windows.
+ wnds = windowing.FindChildWindows(0, "MozillaUIWindowClass")
+ if len(wnds):
+ wnd = wnds[0]
+ proc = None
+ else:
+ # Invoke Firefox
+ (proc, wnd) = windowing.InvokeAndWait(path)
+
+ # Get the content pane
+ render_pane = windowing.FindChildWindow(
+ wnd,
+ "MozillaWindowClass/MozillaWindowClass/MozillaWindowClass")
+
+ return (wnd, proc, render_pane)
+
+
+def Scrape(urls, outdir, size, pos, timeout=20, **kwargs):
+ """Invoke a browser, send it to a series of URLs, and save its output.
+
+ Args:
+ urls: list of URLs to scrape
+ outdir: directory to place output
+ size: size of browser window to use
+ pos: position of browser window
+ timeout: amount of time to wait for page to load
+ kwargs: miscellaneous keyword args
+
+ Returns:
+ None if success, else an error string
+ """
+ if "path" in kwargs and kwargs["path"]: path = kwargs["path"]
+ else: path = DEFAULT_PATH
+
+ (wnd, proc, render_pane) = InvokeBrowser(path)
+
+ # Resize and reposition the frame
+ windowing.MoveAndSizeWindow(wnd, pos, size, render_pane)
+
+ time.sleep(3)
+
+ # Firefox is a bit of a pain: it doesn't use standard edit controls,
+ # and it doesn't display a throbber when there's no tab. Let's make
+ # sure there's at least one tab, then select the first one
+
+ mouse.ClickInWindow(wnd)
+ keyboard.TypeString("[t]", True)
+ mouse.ClickInWindow(wnd, (30, 115))
+ time.sleep(2)
+
+ timedout = False
+
+ # Visit each URL we're given
+ if type(urls) in types.StringTypes: urls = [urls]
+
+ for url in urls:
+
+ # Use keyboard shortcuts
+ keyboard.TypeString("{d}", True)
+ keyboard.TypeString(url)
+ keyboard.TypeString("\n")
+
+ # Wait for the page to finish loading
+ load_time = windowing.WaitForThrobber(wnd, (10, 96, 26, 112), timeout)
+ timedout = load_time < 0
+
+ if timedout:
+ break
+
+ # Scrape the page
+ image = windowing.ScrapeWindow(render_pane)
+
+ # Save to disk
+ if "filename" in kwargs:
+ if callable(kwargs["filename"]):
+ filename = kwargs["filename"](url)
+ else:
+ filename = kwargs["filename"]
+ else:
+ filename = windowing.URLtoFilename(url, outdir, ".bmp")
+ image.save(filename)
+
+ # Close all the tabs, cheesily
+ mouse.ClickInWindow(wnd)
+
+ while len(windowing.FindChildWindows(0, "MozillaUIWindowClass")):
+ keyboard.TypeString("[w]", True)
+ time.sleep(1)
+
+ if timedout:
+ return "timeout"
+
+
+def Time(urls, size, timeout, **kwargs):
+ """Measure how long it takes to load each of a series of URLs
+
+ Args:
+ urls: list of URLs to time
+ size: size of browser window to use
+ timeout: amount of time to wait for page to load
+ kwargs: miscellaneous keyword args
+
+ Returns:
+ A list of tuples (url, time). "time" can be "crashed" or "timeout"
+ """
+ if "path" in kwargs and kwargs["path"]: path = kwargs["path"]
+ else: path = DEFAULT_PATH
+ proc = None
+
+ # Visit each URL we're given
+ if type(urls) in types.StringTypes: urls = [urls]
+
+ ret = []
+ for url in urls:
+ try:
+ # Invoke the browser if necessary
+ if not proc:
+ (wnd, proc, render_pane) = InvokeBrowser(path)
+
+ # Resize and reposition the frame
+ windowing.MoveAndSizeWindow(wnd, (0,0), size, render_pane)
+
+ time.sleep(3)
+
+ # Firefox is a bit of a pain: it doesn't use standard edit controls,
+ # and it doesn't display a throbber when there's no tab. Let's make
+ # sure there's at least one tab, then select the first one
+
+ mouse.ClickInWindow(wnd)
+ keyboard.TypeString("[t]", True)
+ mouse.ClickInWindow(wnd, (30, 115))
+ time.sleep(2)
+
+ # Use keyboard shortcuts
+ keyboard.TypeString("{d}", True)
+ keyboard.TypeString(url)
+ keyboard.TypeString("\n")
+
+ # Wait for the page to finish loading
+ load_time = windowing.WaitForThrobber(wnd, (10, 96, 26, 112), timeout)
+ timedout = load_time < 0
+
+ if timedout:
+ load_time = "timeout"
+
+ # Try to close the browser; if this fails it's probably a crash
+ mouse.ClickInWindow(wnd)
+
+ count = 0
+ while (len(windowing.FindChildWindows(0, "MozillaUIWindowClass"))
+ and count < 5):
+ keyboard.TypeString("[w]", True)
+ time.sleep(1)
+ count = count + 1
+
+ if len(windowing.FindChildWindows(0, "MozillaUIWindowClass")):
+ windowing.EndProcess(proc)
+ load_time = "crashed"
+
+ proc = None
+ except pywintypes.error:
+ proc = None
+ load_time = "crashed"
+
+ ret.append( (url, load_time) )
+
+ if proc:
+ count = 0
+ while (len(windowing.FindChildWindows(0, "MozillaUIWindowClass"))
+ and count < 5):
+ keyboard.TypeString("[w]", True)
+ time.sleep(1)
+ count = count + 1
+ return ret
+
+
+def main():
+ # We're being invoked rather than imported, so run some tests
+ path = r"c:\sitecompare\scrapes\Firefox\2.0.0.6"
+ windowing.PreparePath(path)
+
+ # Scrape three sites and save the results
+ Scrape(
+ ["http://www.microsoft.com", "http://www.google.com",
+ "http://www.sun.com"],
+ path, (1024, 768), (0, 0))
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/site_compare/scrapers/ie/__init__.py b/chromium/tools/site_compare/scrapers/ie/__init__.py
new file mode 100755
index 00000000000..b4dab09e4c2
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/ie/__init__.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Selects the appropriate scraper for Internet Explorer."""
+
+
+def GetScraper(version):
+ """Returns the scraper module for the given version.
+
+ Args:
+ version: version string of IE, or None for most recent
+
+ Returns:
+ scrape module for given version
+ """
+
+ # Pychecker will warn that the parameter is unused; we only
+ # support one version of IE at this time
+
+ # We only have one version of the IE scraper for now
+ return __import__("ie7", globals(), locals(), [''])
+
+
+# if invoked rather than imported, test
+if __name__ == "__main__":
+ print GetScraper("7.0.5370.1").version
diff --git a/chromium/tools/site_compare/scrapers/ie/ie7.py b/chromium/tools/site_compare/scrapers/ie/ie7.py
new file mode 100755
index 00000000000..dcb83ca238f
--- /dev/null
+++ b/chromium/tools/site_compare/scrapers/ie/ie7.py
@@ -0,0 +1,210 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Does scraping for all known versions of IE."""
+
+import pywintypes
+import time
+import types
+
+from drivers import keyboard
+from drivers import mouse
+from drivers import windowing
+
+# Default version
+version = "7.0.5730.1"
+
+DEFAULT_PATH = r"c:\program files\internet explorer\iexplore.exe"
+
+def GetBrowser(path):
+ """Invoke the IE browser and return the process, frame, and content window.
+
+ Args:
+ path: full path to browser
+
+ Returns:
+ A tuple of (process handle, render pane)
+ """
+ if not path: path = DEFAULT_PATH
+
+ (iewnd, ieproc, address_bar, render_pane, tab_window) = InvokeBrowser(path)
+ return (ieproc, iewnd, render_pane)
+
+
+def InvokeBrowser(path):
+ """Invoke the IE browser.
+
+ Args:
+ path: full path to browser
+
+ Returns:
+ A tuple of (main window, process handle, address bar,
+ render_pane, tab_window)
+ """
+ # Invoke IE
+ (ieproc, iewnd) = windowing.InvokeAndWait(path)
+
+ # Get windows we'll need
+ for tries in xrange(10):
+ try:
+ address_bar = windowing.FindChildWindow(
+ iewnd, "WorkerW|Navigation Bar/ReBarWindow32/"
+ "Address Band Root/ComboBoxEx32/ComboBox/Edit")
+ render_pane = windowing.FindChildWindow(
+ iewnd, "TabWindowClass/Shell DocObject View")
+ tab_window = windowing.FindChildWindow(
+ iewnd, "CommandBarClass/ReBarWindow32/TabBandClass/DirectUIHWND")
+ except IndexError:
+ time.sleep(1)
+ continue
+ break
+
+ return (iewnd, ieproc, address_bar, render_pane, tab_window)
+
+
+def Scrape(urls, outdir, size, pos, timeout=20, **kwargs):
+ """Invoke a browser, send it to a series of URLs, and save its output.
+
+ Args:
+ urls: list of URLs to scrape
+ outdir: directory to place output
+ size: size of browser window to use
+ pos: position of browser window
+ timeout: amount of time to wait for page to load
+ kwargs: miscellaneous keyword args
+
+ Returns:
+ None if success, else an error string
+ """
+ path = r"c:\program files\internet explorer\iexplore.exe"
+
+ if "path" in kwargs and kwargs["path"]: path = kwargs["path"]
+
+ (iewnd, ieproc, address_bar, render_pane, tab_window) = (
+ InvokeBrowser(path) )
+
+ # Resize and reposition the frame
+ windowing.MoveAndSizeWindow(iewnd, pos, size, render_pane)
+
+ # Visit each URL we're given
+ if type(urls) in types.StringTypes: urls = [urls]
+
+ timedout = False
+
+ for url in urls:
+
+ # Double-click in the address bar, type the name, and press Enter
+ mouse.DoubleClickInWindow(address_bar)
+ keyboard.TypeString(url)
+ keyboard.TypeString("\n")
+
+ # Wait for the page to finish loading
+ load_time = windowing.WaitForThrobber(
+ tab_window, (6, 8, 22, 24), timeout)
+ timedout = load_time < 0
+
+ if timedout:
+ break
+
+ # Scrape the page
+ image = windowing.ScrapeWindow(render_pane)
+
+ # Save to disk
+ if "filename" in kwargs:
+ if callable(kwargs["filename"]):
+ filename = kwargs["filename"](url)
+ else:
+ filename = kwargs["filename"]
+ else:
+ filename = windowing.URLtoFilename(url, outdir, ".bmp")
+ image.save(filename)
+
+ windowing.EndProcess(ieproc)
+
+ if timedout:
+ return "timeout"
+
+
+def Time(urls, size, timeout, **kwargs):
+ """Measure how long it takes to load each of a series of URLs
+
+ Args:
+ urls: list of URLs to time
+ size: size of browser window to use
+ timeout: amount of time to wait for page to load
+ kwargs: miscellaneous keyword args
+
+ Returns:
+ A list of tuples (url, time). "time" can be "crashed" or "timeout"
+ """
+ if "path" in kwargs and kwargs["path"]: path = kwargs["path"]
+ else: path = DEFAULT_PATH
+ proc = None
+
+ # Visit each URL we're given
+ if type(urls) in types.StringTypes: urls = [urls]
+
+ ret = []
+ for url in urls:
+ try:
+ # Invoke the browser if necessary
+ if not proc:
+ (wnd, proc, address_bar, render_pane, tab_window) = InvokeBrowser(path)
+
+ # Resize and reposition the frame
+ windowing.MoveAndSizeWindow(wnd, (0,0), size, render_pane)
+
+ # Double-click in the address bar, type the name, and press Enter
+ mouse.DoubleClickInWindow(address_bar)
+ keyboard.TypeString(url)
+ keyboard.TypeString("\n")
+
+ # Wait for the page to finish loading
+ load_time = windowing.WaitForThrobber(
+ tab_window, (6, 8, 22, 24), timeout)
+ timedout = load_time < 0
+
+ if timedout:
+ load_time = "timeout"
+
+ # Send an alt-F4 to make the browser close; if this times out,
+ # we've probably got a crash
+ keyboard.TypeString(r"{\4}", use_modifiers=True)
+ if not windowing.WaitForProcessExit(proc, timeout):
+ windowing.EndProcess(proc)
+ load_time = "crashed"
+ proc = None
+ except pywintypes.error:
+ load_time = "crashed"
+ proc = None
+
+ ret.append( (url, load_time) )
+
+ # Send an alt-F4 to make the browser close; if this times out,
+ # we've probably got a crash
+ if proc:
+ keyboard.TypeString(r"{\4}", use_modifiers=True)
+ if not windowing.WaitForProcessExit(proc, timeout):
+ windowing.EndProcess(proc)
+
+ return ret
+
+
+def main():
+ # We're being invoked rather than imported, so run some tests
+ path = r"c:\sitecompare\scrapes\ie7\7.0.5380.11"
+ windowing.PreparePath(path)
+
+ # Scrape three sites and save the results
+ Scrape(
+ ["http://www.microsoft.com",
+ "http://www.google.com",
+ "http://www.sun.com"],
+ path, (1024, 768), (0, 0))
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/site_compare/site_compare.py b/chromium/tools/site_compare/site_compare.py
new file mode 100755
index 00000000000..db9216f2d0c
--- /dev/null
+++ b/chromium/tools/site_compare/site_compare.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""SiteCompare component to handle bulk scrapes.
+
+Invokes a list of browsers and sends them to a list of URLs,
+saving the rendered results to a specified directory, then
+performs comparison operations on the resulting bitmaps and
+saves the results
+"""
+
+
+# This line is necessary to work around a QEMU bug
+import _imaging
+
+import os # Functions for walking the directory tree
+import types # Runtime type-checking
+
+import command_line # command-line parsing
+import drivers # Functions for driving keyboard/mouse/windows, OS-specific
+import operators # Functions that, given two bitmaps as input, produce
+ # output depending on the performance of an operation
+import scrapers # Functions that know how to capture a render from
+ # particular browsers
+
+import commands.compare2 # compare one page in two versions of same browser
+import commands.maskmaker # generate a mask based on repeated scrapes
+import commands.measure # measure length of time a page takes to load
+import commands.scrape # scrape a URL or series of URLs to a bitmap
+
+# The timeload command is obsolete (too flaky); it may be reinstated
+# later but for now it's been superceded by "measure"
+# import commands.timeload # measure length of time a page takes to load
+
+def Scrape(browsers, urls, window_size=(1024, 768),
+ window_pos=(0, 0), timeout=20, save_path=None, **kwargs):
+ """Invoke one or more browsers over one or more URLs, scraping renders.
+
+ Args:
+ browsers: browsers to invoke with optional version strings
+ urls: URLs to visit
+ window_size: size of the browser window to display
+ window_pos: location of browser window
+ timeout: time (in seconds) to wait for page to load
+ save_path: root of save path, automatically appended with browser and
+ version
+ kwargs: miscellaneous keyword args, passed to scraper
+ Returns:
+ None
+
+ @TODO(jhaas): more parameters, or perhaps an indefinite dictionary
+ parameter, for things like length of time to wait for timeout, speed
+ of mouse clicks, etc. Possibly on a per-browser, per-URL, or
+ per-browser-per-URL basis
+ """
+
+ if type(browsers) in types.StringTypes: browsers = [browsers]
+
+ if save_path is None:
+ # default save path is "scrapes" off the current root
+ save_path = os.path.join(os.path.split(__file__)[0], "Scrapes")
+
+ for browser in browsers:
+ # Browsers should be tuples of (browser, version)
+ if type(browser) in types.StringTypes: browser = (browser, None)
+ scraper = scrapers.GetScraper(browser)
+
+ full_path = os.path.join(save_path, browser[0], scraper.version)
+ drivers.windowing.PreparePath(full_path)
+
+ scraper.Scrape(urls, full_path, window_size, window_pos, timeout, kwargs)
+
+
+def Compare(base, compare, ops, root_path=None, out_path=None):
+ """Compares a series of scrapes using a series of operators.
+
+ Args:
+ base: (browser, version) tuple of version to consider the baseline
+ compare: (browser, version) tuple of version to compare to
+ ops: list of operators plus operator arguments
+ root_path: root of the scrapes
+ out_path: place to put any output from the operators
+
+ Returns:
+ None
+
+ @TODO(jhaas): this method will likely change, to provide a robust and
+ well-defined way of chaining operators, applying operators conditionally,
+ and full-featured scripting of the operator chain. There also needs
+ to be better definition of the output; right now it's to stdout and
+ a log.txt file, with operator-dependent images saved for error output
+ """
+ if root_path is None:
+ # default save path is "scrapes" off the current root
+ root_path = os.path.join(os.path.split(__file__)[0], "Scrapes")
+
+ if out_path is None:
+ out_path = os.path.join(os.path.split(__file__)[0], "Compares")
+
+ if type(base) in types.StringTypes: base = (base, None)
+ if type(compare) in types.StringTypes: compare = (compare, None)
+ if type(ops) in types.StringTypes: ops = [ops]
+
+ base_dir = os.path.join(root_path, base[0])
+ compare_dir = os.path.join(root_path, compare[0])
+
+ if base[1] is None:
+ # base defaults to earliest capture
+ base = (base[0], max(os.listdir(base_dir)))
+
+ if compare[1] is None:
+ # compare defaults to latest capture
+ compare = (compare[0], min(os.listdir(compare_dir)))
+
+ out_path = os.path.join(out_path, base[0], base[1], compare[0], compare[1])
+ drivers.windowing.PreparePath(out_path)
+
+ # TODO(jhaas): right now we're just dumping output to a log file
+ # (and the console), which works as far as it goes but isn't nearly
+ # robust enough. Change this after deciding exactly what we want to
+ # change it to.
+ out_file = open(os.path.join(out_path, "log.txt"), "w")
+ description_string = ("Comparing %s %s to %s %s" %
+ (base[0], base[1], compare[0], compare[1]))
+ out_file.write(description_string)
+ print description_string
+
+ base_dir = os.path.join(base_dir, base[1])
+ compare_dir = os.path.join(compare_dir, compare[1])
+
+ for filename in os.listdir(base_dir):
+ out_file.write("%s: " % filename)
+
+ if not os.path.isfile(os.path.join(compare_dir, filename)):
+ out_file.write("Does not exist in target directory\n")
+ print "File %s does not exist in target directory" % filename
+ continue
+
+ base_filename = os.path.join(base_dir, filename)
+ compare_filename = os.path.join(compare_dir, filename)
+
+ for op in ops:
+ if type(op) in types.StringTypes: op = (op, None)
+
+ module = operators.GetOperator(op[0])
+
+ ret = module.Compare(base_filename, compare_filename)
+ if ret is None:
+ print "%s: OK" % (filename,)
+ out_file.write("OK\n")
+ else:
+ print "%s: %s" % (filename, ret[0])
+ out_file.write("%s\n" % (ret[0]))
+ ret[1].save(os.path.join(out_path, filename))
+
+ out_file.close()
+
+
+def main():
+ """Main executable. Parse the command line and invoke the command."""
+ cmdline = command_line.CommandLine()
+
+ # The below two commands are currently unstable so have been disabled
+ # commands.compare2.CreateCommand(cmdline)
+ # commands.maskmaker.CreateCommand(cmdline)
+ commands.measure.CreateCommand(cmdline)
+ commands.scrape.CreateCommand(cmdline)
+
+ cmdline.ParseCommandLine()
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/site_compare/utils/__init__.py b/chromium/tools/site_compare/utils/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/site_compare/utils/__init__.py
diff --git a/chromium/tools/site_compare/utils/browser_iterate.py b/chromium/tools/site_compare/utils/browser_iterate.py
new file mode 100644
index 00000000000..596b475cdcb
--- /dev/null
+++ b/chromium/tools/site_compare/utils/browser_iterate.py
@@ -0,0 +1,199 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility to use a browser to visit multiple URLs.
+
+Prerequisites:
+ 1. The command_line package from tools/site_compare
+ 2. Either the IE BHO or Firefox extension (or both)
+
+Installation:
+ 1. Build the IE BHO, or call regsvr32 on a prebuilt binary
+ 2. Add a file called "measurepageloadtimeextension@google.com" to
+ the default Firefox profile directory under extensions, containing
+ the path to the Firefox extension root
+
+Invoke with the command line arguments as documented within
+the command line.
+"""
+
+import command_line
+import scrapers
+import socket
+import time
+
+from drivers import windowing
+
+# Constants
+MAX_URL = 1024
+PORT = 42492
+
+def SetupIterationCommandLine(cmd):
+ """Adds the necessary flags for iteration to a command.
+
+ Args:
+ cmd: an object created by cmdline.AddCommand
+ """
+ cmd.AddArgument(
+ ["-b", "--browser"], "Browser to use (ie, firefox, chrome)",
+ type="string", required=True)
+ cmd.AddArgument(
+ ["-b1v", "--browserver"], "Version of browser", metaname="VERSION")
+ cmd.AddArgument(
+ ["-p", "--browserpath"], "Path to browser.",
+ type="string", required=False)
+ cmd.AddArgument(
+ ["-u", "--url"], "URL to visit")
+ cmd.AddArgument(
+ ["-l", "--list"], "File containing list of URLs to visit", type="readfile")
+ cmd.AddMutualExclusion(["--url", "--list"])
+ cmd.AddArgument(
+ ["-s", "--startline"], "First line of URL list", type="int")
+ cmd.AddArgument(
+ ["-e", "--endline"], "Last line of URL list (exclusive)", type="int")
+ cmd.AddArgument(
+ ["-c", "--count"], "Number of lines of URL file to use", type="int")
+ cmd.AddDependency("--startline", "--list")
+ cmd.AddRequiredGroup(["--url", "--list"])
+ cmd.AddDependency("--endline", "--list")
+ cmd.AddDependency("--count", "--list")
+ cmd.AddMutualExclusion(["--count", "--endline"])
+ cmd.AddDependency("--count", "--startline")
+ cmd.AddArgument(
+ ["-t", "--timeout"], "Amount of time (seconds) to wait for browser to "
+ "finish loading",
+ type="int", default=300)
+ cmd.AddArgument(
+ ["-sz", "--size"], "Browser window size", default=(800, 600), type="coords")
+
+
+def Iterate(command, iteration_func):
+ """Iterates over a list of URLs, calling a function on each.
+
+ Args:
+ command: the command line containing the iteration flags
+ iteration_func: called for each URL with (proc, wnd, url, result)
+ """
+
+ # Retrieve the browser scraper to use to invoke the browser
+ scraper = scrapers.GetScraper((command["--browser"], command["--browserver"]))
+
+ def AttachToBrowser(path, timeout):
+ """Invoke the browser process and connect to the socket."""
+ (proc, frame, wnd) = scraper.GetBrowser(path)
+
+ if not wnd: raise ValueError("Could not invoke browser.")
+
+ # Try to connect the socket. If it fails, wait and try
+ # again. Do this for ten seconds
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
+
+ for attempt in xrange(10):
+ try:
+ s.connect(("localhost", PORT))
+ except socket.error:
+ time.sleep(1)
+ continue
+ break
+
+ try:
+ s.getpeername()
+ except socket.error:
+ raise ValueError("Could not connect to browser")
+
+ if command["--size"]:
+ # Resize and reposition the frame
+ windowing.MoveAndSizeWindow(frame, (0, 0), command["--size"], wnd)
+
+ s.settimeout(timeout)
+
+ Iterate.proc = proc
+ Iterate.wnd = wnd
+ Iterate.s = s
+
+ def DetachFromBrowser():
+ """Close the socket and kill the process if necessary."""
+ if Iterate.s:
+ Iterate.s.close()
+ Iterate.s = None
+
+ if Iterate.proc:
+ if not windowing.WaitForProcessExit(Iterate.proc, 0):
+ try:
+ windowing.EndProcess(Iterate.proc)
+ windowing.WaitForProcessExit(Iterate.proc, 0)
+ except pywintypes.error:
+ # Exception here most likely means the process died on its own
+ pass
+ Iterate.proc = None
+
+ if command["--browserpath"]:
+ browser = command["--browserpath"]
+ else:
+ browser = None
+
+ # Read the URLs from the file
+ if command["--url"]:
+ url_list = [command["--url"]]
+ else:
+ startline = command["--startline"]
+ if command["--count"]:
+ endline = startline+command["--count"]
+ else:
+ endline = command["--endline"]
+
+ url_list = []
+ file = open(command["--list"], "r")
+
+ for line in xrange(startline-1):
+ file.readline()
+
+ for line in xrange(endline-startline):
+ url_list.append(file.readline().strip())
+
+ timeout = command["--timeout"]
+
+ # Loop through the URLs and send them through the socket
+ Iterate.s = None
+ Iterate.proc = None
+ Iterate.wnd = None
+
+ for url in url_list:
+ # Invoke the browser if necessary
+ if not Iterate.proc:
+ AttachToBrowser(browser, timeout)
+ # Send the URL and wait for a response
+ Iterate.s.send(url + "\n")
+
+ response = ""
+
+ while (response.find("\n") < 0):
+
+ try:
+ recv = Iterate.s.recv(MAX_URL)
+ response = response + recv
+
+ # Workaround for an oddity: when Firefox closes
+ # gracefully, somehow Python doesn't detect it.
+ # (Telnet does)
+ if not recv:
+ raise socket.error
+
+ except socket.timeout:
+ response = url + ",hang\n"
+ DetachFromBrowser()
+ except socket.error:
+ # If there was a socket error, it's probably a crash
+ response = url + ",crash\n"
+ DetachFromBrowser()
+
+ # If we received a timeout response, restart the browser
+ if response[-9:] == ",timeout\n":
+ DetachFromBrowser()
+
+ # Invoke the iteration function
+ iteration_func(url, Iterate.proc, Iterate.wnd, response)
+
+ # We're done
+ DetachFromBrowser()
diff --git a/chromium/tools/sort-headers.py b/chromium/tools/sort-headers.py
new file mode 100755
index 00000000000..42a8be8e52b
--- /dev/null
+++ b/chromium/tools/sort-headers.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Given a filename as an argument, sort the #include/#imports in that file.
+
+Shows a diff and prompts for confirmation before doing the deed.
+Works great with tools/git/for-all-touched-files.py.
+"""
+
+import optparse
+import os
+import sys
+
+
+def YesNo(prompt):
+ """Prompts with a yes/no question, returns True if yes."""
+ print prompt,
+ sys.stdout.flush()
+ # http://code.activestate.com/recipes/134892/
+ if sys.platform == 'win32':
+ import msvcrt
+ ch = msvcrt.getch()
+ else:
+ import termios
+ import tty
+ fd = sys.stdin.fileno()
+ old_settings = termios.tcgetattr(fd)
+ ch = 'n'
+ try:
+ tty.setraw(sys.stdin.fileno())
+ ch = sys.stdin.read(1)
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+ print ch
+ return ch in ('Y', 'y')
+
+
+def IncludeCompareKey(line):
+ """Sorting comparator key used for comparing two #include lines.
+ Returns the filename without the #include/#import prefix.
+ """
+ for prefix in ('#include ', '#import '):
+ if line.startswith(prefix):
+ line = line[len(prefix):]
+ break
+
+ # The win32 api has all sorts of implicit include order dependencies :-/
+ # Give a few headers special sort keys that make sure they appear before all
+ # other headers.
+ if line.startswith('<windows.h>'): # Must be before e.g. shellapi.h
+ return '0'
+ if line.startswith('<atlbase.h>'): # Must be before atlapp.h.
+ return '1' + line
+ if line.startswith('<unknwn.h>'): # Must be before e.g. intshcut.h
+ return '1' + line
+
+ # C++ system headers should come after C system headers.
+ if line.startswith('<'):
+ if line.find('.h>') != -1:
+ return '2' + line.lower()
+ else:
+ return '3' + line.lower()
+
+ return '4' + line
+
+
+def IsInclude(line):
+ """Returns True if the line is an #include/#import line."""
+ return line.startswith('#include ') or line.startswith('#import ')
+
+
+def SortHeader(infile, outfile):
+ """Sorts the headers in infile, writing the sorted file to outfile."""
+ for line in infile:
+ if IsInclude(line):
+ headerblock = []
+ while IsInclude(line):
+ infile_ended_on_include_line = False
+ headerblock.append(line)
+ # Ensure we don't die due to trying to read beyond the end of the file.
+ try:
+ line = infile.next()
+ except StopIteration:
+ infile_ended_on_include_line = True
+ break
+ for header in sorted(headerblock, key=IncludeCompareKey):
+ outfile.write(header)
+ if infile_ended_on_include_line:
+ # We already wrote the last line above; exit to ensure it isn't written
+ # again.
+ return
+ # Intentionally fall through, to write the line that caused
+ # the above while loop to exit.
+ outfile.write(line)
+
+
+def FixFileWithConfirmFunction(filename, confirm_function,
+ perform_safety_checks):
+ """Creates a fixed version of the file, invokes |confirm_function|
+ to decide whether to use the new file, and cleans up.
+
+ |confirm_function| takes two parameters, the original filename and
+ the fixed-up filename, and returns True to use the fixed-up file,
+ false to not use it.
+
+ If |perform_safety_checks| is True, then the function checks whether it is
+ unsafe to reorder headers in this file and skips the reorder with a warning
+ message in that case.
+ """
+ if perform_safety_checks and IsUnsafeToReorderHeaders(filename):
+ print ('Not reordering headers in %s as the script thinks that the '
+ 'order of headers in this file is semantically significant.'
+ % (filename))
+ return
+ fixfilename = filename + '.new'
+ infile = open(filename, 'rb')
+ outfile = open(fixfilename, 'wb')
+ SortHeader(infile, outfile)
+ infile.close()
+ outfile.close() # Important so the below diff gets the updated contents.
+
+ try:
+ if confirm_function(filename, fixfilename):
+ if sys.platform == 'win32':
+ os.unlink(filename)
+ os.rename(fixfilename, filename)
+ finally:
+ try:
+ os.remove(fixfilename)
+ except OSError:
+ # If the file isn't there, we don't care.
+ pass
+
+
+def DiffAndConfirm(filename, should_confirm, perform_safety_checks):
+ """Shows a diff of what the tool would change the file named
+ filename to. Shows a confirmation prompt if should_confirm is true.
+ Saves the resulting file if should_confirm is false or the user
+ answers Y to the confirmation prompt.
+ """
+ def ConfirmFunction(filename, fixfilename):
+ diff = os.system('diff -u %s %s' % (filename, fixfilename))
+ if sys.platform != 'win32':
+ diff >>= 8
+ if diff == 0: # Check exit code.
+ print '%s: no change' % filename
+ return False
+
+ return (not should_confirm or YesNo('Use new file (y/N)?'))
+
+ FixFileWithConfirmFunction(filename, ConfirmFunction, perform_safety_checks)
+
+def IsUnsafeToReorderHeaders(filename):
+ # *_message_generator.cc is almost certainly a file that generates IPC
+ # definitions. Changes in include order in these files can result in them not
+ # building correctly.
+ if filename.find("message_generator.cc") != -1:
+ return True
+ return False
+
+def main():
+ parser = optparse.OptionParser(usage='%prog filename1 filename2 ...')
+ parser.add_option('-f', '--force', action='store_false', default=True,
+ dest='should_confirm',
+ help='Turn off confirmation prompt.')
+ parser.add_option('--no_safety_checks',
+ action='store_false', default=True,
+ dest='perform_safety_checks',
+ help='Do not perform the safety checks via which this '
+ 'script refuses to operate on files for which it thinks '
+ 'the include ordering is semantically significant.')
+ opts, filenames = parser.parse_args()
+
+ if len(filenames) < 1:
+ parser.print_help()
+ return 1
+
+ for filename in filenames:
+ DiffAndConfirm(filename, opts.should_confirm, opts.perform_safety_checks)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/stats_viewer/OpenDialog.Designer.cs b/chromium/tools/stats_viewer/OpenDialog.Designer.cs
new file mode 100644
index 00000000000..96f01f53e80
--- /dev/null
+++ b/chromium/tools/stats_viewer/OpenDialog.Designer.cs
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace StatsViewer
+{
+ partial class OpenDialog
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.name_box_ = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.button1 = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // name_box_
+ //
+ this.name_box_.Location = new System.Drawing.Point(108, 25);
+ this.name_box_.Name = "name_box_";
+ this.name_box_.Size = new System.Drawing.Size(180, 20);
+ this.name_box_.TabIndex = 0;
+ this.name_box_.KeyUp += new System.Windows.Forms.KeyEventHandler(this.OnKeyUp);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(12, 28);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(91, 13);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "Stats File to Open";
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(108, 61);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(75, 23);
+ this.button1.TabIndex = 2;
+ this.button1.Text = "OK";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // OpenDialog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(303, 94);
+ this.Controls.Add(this.button1);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.name_box_);
+ this.Name = "OpenDialog";
+ this.Text = "OpenDialog";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox name_box_;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Button button1;
+ }
+}
diff --git a/chromium/tools/stats_viewer/OpenDialog.cs b/chromium/tools/stats_viewer/OpenDialog.cs
new file mode 100644
index 00000000000..05ca03934fe
--- /dev/null
+++ b/chromium/tools/stats_viewer/OpenDialog.cs
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+namespace StatsViewer
+{
+ public partial class OpenDialog : Form
+ {
+ public OpenDialog()
+ {
+ InitializeComponent();
+ }
+
+ /// <summary>
+ /// Get the user selected filename
+ /// </summary>
+ public string FileName
+ {
+ get {
+ return this.name_box_.Text;
+ }
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+
+ private void OnKeyUp(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter)
+ {
+ this.Close();
+ }
+ }
+ }
+}
diff --git a/chromium/tools/stats_viewer/OpenDialog.resx b/chromium/tools/stats_viewer/OpenDialog.resx
new file mode 100644
index 00000000000..ff31a6db56e
--- /dev/null
+++ b/chromium/tools/stats_viewer/OpenDialog.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/chromium/tools/stats_viewer/Properties/AssemblyInfo.cs b/chromium/tools/stats_viewer/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000000..8ffae142df5
--- /dev/null
+++ b/chromium/tools/stats_viewer/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("StatsViewer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Google")]
+[assembly: AssemblyProduct("StatsViewer")]
+[assembly: AssemblyCopyright("Copyright © Google 2007")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("0c5760e1-3ada-48e2-800d-5b104bef4a95")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/chromium/tools/stats_viewer/Properties/Resources.Designer.cs b/chromium/tools/stats_viewer/Properties/Resources.Designer.cs
new file mode 100644
index 00000000000..4195c5f0de3
--- /dev/null
+++ b/chromium/tools/stats_viewer/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.832
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace StatsViewer.Properties
+{
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("StatsViewer.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/chromium/tools/stats_viewer/Properties/Resources.resx b/chromium/tools/stats_viewer/Properties/Resources.resx
new file mode 100644
index 00000000000..ffecec851ab
--- /dev/null
+++ b/chromium/tools/stats_viewer/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/chromium/tools/stats_viewer/Properties/Settings.Designer.cs b/chromium/tools/stats_viewer/Properties/Settings.Designer.cs
new file mode 100644
index 00000000000..221765adcf5
--- /dev/null
+++ b/chromium/tools/stats_viewer/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.832
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace StatsViewer.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "8.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/chromium/tools/stats_viewer/Properties/Settings.settings b/chromium/tools/stats_viewer/Properties/Settings.settings
new file mode 100644
index 00000000000..abf36c5d3d7
--- /dev/null
+++ b/chromium/tools/stats_viewer/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
diff --git a/chromium/tools/stats_viewer/Resources.Designer.cs b/chromium/tools/stats_viewer/Resources.Designer.cs
new file mode 100644
index 00000000000..2d915e07da8
--- /dev/null
+++ b/chromium/tools/stats_viewer/Resources.Designer.cs
@@ -0,0 +1,77 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.832
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace StatsViewer {
+ using System;
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("StatsViewer.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ internal static System.Drawing.Bitmap kitten {
+ get {
+ object obj = ResourceManager.GetObject("kitten", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ internal static System.Drawing.Bitmap kittenbackground {
+ get {
+ object obj = ResourceManager.GetObject("kittenbackground", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+ }
+}
diff --git a/chromium/tools/stats_viewer/Resources.resx b/chromium/tools/stats_viewer/Resources.resx
new file mode 100644
index 00000000000..9486b218055
--- /dev/null
+++ b/chromium/tools/stats_viewer/Resources.resx
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+ <data name="kitten" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>Resources\kitten.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+ <data name="kittenbackground" type="System.Resources.ResXFileRef, System.Windows.Forms">
+ <value>Resources\kittenbackground.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+ </data>
+</root> \ No newline at end of file
diff --git a/chromium/tools/stats_viewer/Resources/kitten.png b/chromium/tools/stats_viewer/Resources/kitten.png
new file mode 100644
index 00000000000..51cc9b8f51e
--- /dev/null
+++ b/chromium/tools/stats_viewer/Resources/kitten.png
Binary files differ
diff --git a/chromium/tools/stats_viewer/Resources/kittenbackground.png b/chromium/tools/stats_viewer/Resources/kittenbackground.png
new file mode 100644
index 00000000000..09a72687fd6
--- /dev/null
+++ b/chromium/tools/stats_viewer/Resources/kittenbackground.png
Binary files differ
diff --git a/chromium/tools/stats_viewer/program.cs b/chromium/tools/stats_viewer/program.cs
new file mode 100644
index 00000000000..d6a2b928624
--- /dev/null
+++ b/chromium/tools/stats_viewer/program.cs
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+using System;
+using System.Windows.Forms;
+
+namespace StatsViewer
+{
+ static class Program
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new StatsViewer());
+ }
+ }
+}
diff --git a/chromium/tools/stats_viewer/stats_table.cs b/chromium/tools/stats_viewer/stats_table.cs
new file mode 100644
index 00000000000..e5d0894e37c
--- /dev/null
+++ b/chromium/tools/stats_viewer/stats_table.cs
@@ -0,0 +1,546 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace StatsViewer
+{
+ /// <summary>
+ /// The stats table shared memory segment contains this
+ /// header structure.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct StatsFileHeader {
+ public int version;
+ public int size;
+ public int max_counters;
+ public int max_threads;
+ };
+
+ /// <summary>
+ /// An entry in the StatsTable.
+ /// </summary>
+ class StatsTableEntry {
+ public StatsTableEntry(int id, string name, StatsTable table) {
+ id_ = id;
+ name_ = name;
+ table_ = table;
+ }
+
+ /// <summary>
+ /// The unique id for this entry
+ /// </summary>
+ public int id { get { return id_; } }
+
+ /// <summary>
+ /// The name for this entry.
+ /// </summary>
+ public string name { get { return name_; } }
+
+ /// <summary>
+ /// The value of this entry now.
+ /// </summary>
+ public int GetValue(int filter_pid) {
+ return table_.GetValue(id_, filter_pid);
+ }
+
+ private int id_;
+ private string name_;
+ private StatsTable table_;
+ }
+
+ // An interface for StatsCounters
+ interface IStatsCounter {
+ // The name of the counter
+ string name { get; }
+ }
+
+ // A counter.
+ class StatsCounter : IStatsCounter {
+ public StatsCounter(StatsTableEntry entry) {
+ entry_ = entry;
+ }
+
+ public string name {
+ get {
+ return entry_.name;
+ }
+ }
+
+ public int GetValue(int filter_pid) {
+ return entry_.GetValue(filter_pid);
+ }
+
+ private StatsTableEntry entry_;
+ }
+
+ // A timer.
+ class StatsTimer : IStatsCounter {
+ public StatsTimer(StatsTableEntry entry)
+ {
+ entry_ = entry;
+ }
+
+ public string name {
+ get {
+ return entry_.name;
+ }
+ }
+
+ public int GetValue(int filter_pid) {
+ return entry_.GetValue(filter_pid);
+ }
+
+ private StatsTableEntry entry_;
+ }
+
+ // A rate.
+ class StatsCounterRate : IStatsCounter
+ {
+ public StatsCounterRate(StatsCounter counter, StatsTimer timer) {
+ counter_ = counter;
+ timer_ = timer;
+ }
+
+ public string name { get { return counter_.name; } }
+
+ public int GetCount(int filter_pid) {
+ return counter_.GetValue(filter_pid);
+ }
+
+ public int GetTime(int filter_pid) {
+ return timer_.GetValue(filter_pid);
+ }
+
+ private StatsCounter counter_;
+ private StatsTimer timer_;
+ }
+
+ /// <summary>
+ /// This is a C# reader for the chrome stats_table.
+ /// </summary>
+ class StatsTable {
+ internal const int kMaxThreadNameLength = 32;
+ internal const int kMaxCounterNameLength = 32;
+
+ /// <summary>
+ /// Open a StatsTable
+ /// </summary>
+ public StatsTable() {
+ }
+
+ #region Public Properties
+ /// <summary>
+ /// Get access to the counters in the table.
+ /// </summary>
+ public StatsTableCounters Counters() {
+ return new StatsTableCounters(this);
+ }
+
+ /// <summary>
+ /// Get access to the processes in the table
+ /// </summary>
+ public ICollection Processes {
+ get {
+ return new StatsTableProcesses(this);
+ }
+ }
+ #endregion
+
+ #region Internal Properties
+ //
+ // The internal methods are accessible to the enumerators
+ // and helper classes below.
+ //
+
+ /// <summary>
+ /// Access to the table header
+ /// </summary>
+ internal StatsFileHeader Header {
+ get { return header_; }
+ }
+
+ /// <summary>
+ /// Get the offset of the ThreadName table
+ /// </summary>
+ internal long ThreadNamesOffset {
+ get {
+ return memory_.ToInt64() + Marshal.SizeOf(typeof(StatsFileHeader));
+ }
+ }
+
+ /// <summary>
+ /// Get the offset of the PIDs table
+ /// </summary>
+ internal long PidsOffset {
+ get {
+ long offset = ThreadNamesOffset;
+ // Thread names table
+ offset += AlignedSize(header_.max_threads * kMaxThreadNameLength * 2);
+ // Thread TID table
+ offset += AlignedSize(header_.max_threads *
+ Marshal.SizeOf(typeof(int)));
+ return offset;
+ }
+ }
+
+ /// <summary>
+ /// Get the offset of the CounterName table
+ /// </summary>
+ internal long CounterNamesOffset {
+ get {
+ long offset = PidsOffset;
+ // Thread PID table
+ offset += AlignedSize(header_.max_threads *
+ Marshal.SizeOf(typeof(int)));
+ return offset;
+ }
+ }
+
+ /// <summary>
+ /// Get the offset of the Data table
+ /// </summary>
+ internal long DataOffset {
+ get {
+ long offset = CounterNamesOffset;
+ // Counter names table
+ offset += AlignedSize(header_.max_counters *
+ kMaxCounterNameLength * 2);
+ return offset;
+ }
+ }
+ #endregion
+
+ #region Public Methods
+ /// <summary>
+ /// Opens the memory map
+ /// </summary>
+ /// <returns></returns>
+ /// <param name="name">The name of the file to open</param>
+ public bool Open(string name) {
+ map_handle_ =
+ Win32.OpenFileMapping((int)Win32.MapAccess.FILE_MAP_WRITE, false,
+ name);
+ if (map_handle_ == IntPtr.Zero)
+ return false;
+
+ memory_ =
+ Win32.MapViewOfFile(map_handle_, (int)Win32.MapAccess.FILE_MAP_WRITE,
+ 0,0, 0);
+ if (memory_ == IntPtr.Zero) {
+ Win32.CloseHandle(map_handle_);
+ return false;
+ }
+
+ header_ = (StatsFileHeader)Marshal.PtrToStructure(memory_, header_.GetType());
+ return true;
+ }
+
+ /// <summary>
+ /// Close the mapped file.
+ /// </summary>
+ public void Close() {
+ Win32.UnmapViewOfFile(memory_);
+ Win32.CloseHandle(map_handle_);
+ }
+
+ /// <summary>
+ /// Zero out the stats file.
+ /// </summary>
+ public void Zero() {
+ long offset = DataOffset;
+ for (int threads = 0; threads < header_.max_threads; threads++) {
+ for (int counters = 0; counters < header_.max_counters; counters++) {
+ Marshal.WriteInt32((IntPtr) offset, 0);
+ offset += Marshal.SizeOf(typeof(int));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get the value for a StatsCounterEntry now.
+ /// </summary>
+ /// <returns></returns>
+ /// <param name="filter_pid">If a specific PID is being queried, filter to this PID. 0 means use all data.</param>
+ /// <param name="id">The id of the CounterEntry to get the value for.</param>
+ public int GetValue(int id, int filter_pid) {
+ long pid_offset = PidsOffset;
+ long data_offset = DataOffset;
+ data_offset += id * (Header.max_threads *
+ Marshal.SizeOf(typeof(int)));
+ int rv = 0;
+ for (int cols = 0; cols < Header.max_threads; cols++)
+ {
+ int pid = Marshal.ReadInt32((IntPtr)pid_offset);
+ if (filter_pid == 0 || filter_pid == pid)
+ {
+ rv += Marshal.ReadInt32((IntPtr)data_offset);
+ }
+ data_offset += Marshal.SizeOf(typeof(int));
+ pid_offset += Marshal.SizeOf(typeof(int));
+ }
+ return rv;
+ }
+ #endregion
+
+ #region Private Methods
+ /// <summary>
+ /// Align to 4-byte boundaries
+ /// </summary>
+ /// <param name="size"></param>
+ /// <returns></returns>
+ private long AlignedSize(long size) {
+ Debug.Assert(sizeof(int) == 4);
+ return size + (sizeof(int) - (size % sizeof(int))) % sizeof(int);
+ }
+ #endregion
+
+ #region Private Members
+ private IntPtr memory_;
+ private IntPtr map_handle_;
+ private StatsFileHeader header_;
+ #endregion
+ }
+
+ /// <summary>
+ /// Enumerable list of Counters in the StatsTable
+ /// </summary>
+ class StatsTableCounters : ICollection {
+ /// <summary>
+ /// Create the list of counters
+ /// </summary>
+ /// <param name="table"></param>
+ /// pid</param>
+ public StatsTableCounters(StatsTable table) {
+ table_ = table;
+ counter_hi_water_mark_ = -1;
+ counters_ = new List<IStatsCounter>();
+ FindCounters();
+ }
+
+ /// <summary>
+ /// Scans the table for new entries.
+ /// </summary>
+ public void Update() {
+ FindCounters();
+ }
+
+ #region IEnumerable Members
+ public IEnumerator GetEnumerator() {
+ return counters_.GetEnumerator();
+ }
+ #endregion
+
+ #region ICollection Members
+ public void CopyTo(Array array, int index) {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ public int Count {
+ get {
+ return counters_.Count;
+ }
+ }
+
+ public bool IsSynchronized {
+ get {
+ throw new Exception("The method or operation is not implemented.");
+ }
+ }
+
+ public object SyncRoot {
+ get {
+ throw new Exception("The method or operation is not implemented.");
+ }
+ }
+ #endregion
+
+ #region Private Methods
+ /// <summary>
+ /// Create a counter based on an entry
+ /// </summary>
+ /// <param name="id"></param>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ private IStatsCounter NameToCounter(int id, string name)
+ {
+ IStatsCounter rv = null;
+
+ // check if the name has a type encoded
+ if (name.Length > 2 && name[1] == ':')
+ {
+ StatsTableEntry entry = new StatsTableEntry(id, name.Substring(2), table_);
+ switch (name[0])
+ {
+ case 't':
+ rv = new StatsTimer(entry);
+ break;
+ case 'c':
+ rv = new StatsCounter(entry);
+ break;
+ }
+ }
+ else
+ {
+ StatsTableEntry entry = new StatsTableEntry(id, name, table_);
+ rv = new StatsCounter(entry);
+ }
+
+ return rv;
+ }
+
+ // If we have two StatsTableEntries with the same name,
+ // attempt to upgrade them to a higher level type.
+ // Example: A counter + a timer == a rate!
+ private void UpgradeCounter(IStatsCounter old_counter, IStatsCounter counter)
+ {
+ if (old_counter is StatsCounter && counter is StatsTimer)
+ {
+ StatsCounterRate rate = new StatsCounterRate(old_counter as StatsCounter,
+ counter as StatsTimer);
+ counters_.Remove(old_counter);
+ counters_.Add(rate);
+ }
+ else if (old_counter is StatsTimer && counter is StatsCounter)
+ {
+ StatsCounterRate rate = new StatsCounterRate(counter as StatsCounter,
+ old_counter as StatsTimer);
+ counters_.Remove(old_counter);
+ counters_.Add(rate);
+ }
+ }
+
+ /// <summary>
+ /// Find the counters in the table and insert into the counters_
+ /// hash table.
+ /// </summary>
+ private void FindCounters()
+ {
+ Debug.Assert(table_.Header.max_counters > 0);
+
+ int index = counter_hi_water_mark_;
+
+ do
+ {
+ // Find an entry in the table.
+ index++;
+ long offset = table_.CounterNamesOffset +
+ (index * StatsTable.kMaxCounterNameLength * 2);
+ string name = Marshal.PtrToStringUni((IntPtr)offset);
+ if (name.Length == 0)
+ continue;
+
+ // Record that we've already looked at this StatsTableEntry.
+ counter_hi_water_mark_ = index;
+
+ IStatsCounter counter = NameToCounter(index, name);
+
+ if (counter != null)
+ {
+ IStatsCounter old_counter = FindExistingCounter(counter.name);
+ if (old_counter != null)
+ UpgradeCounter(old_counter, counter);
+ else
+ counters_.Add(counter);
+ }
+ } while (index < table_.Header.max_counters - 1);
+ }
+
+ /// <summary>
+ /// Find an existing counter in our table
+ /// </summary>
+ /// <param name="name"></param>
+ private IStatsCounter FindExistingCounter(string name) {
+ foreach (IStatsCounter ctr in counters_)
+ {
+ if (ctr.name == name)
+ return ctr;
+ }
+ return null;
+ }
+ #endregion
+
+ #region Private Members
+ private StatsTable table_;
+ private List<IStatsCounter> counters_;
+ // Highest index of counters processed.
+ private int counter_hi_water_mark_;
+ #endregion
+ }
+
+ /// <summary>
+ /// A collection of processes
+ /// </summary>
+ class StatsTableProcesses : ICollection
+ {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="table"></param>
+ public StatsTableProcesses(StatsTable table) {
+ table_ = table;
+ pids_ = new List<int>();
+ Initialize();
+ }
+
+ #region ICollection Members
+ public void CopyTo(Array array, int index) {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ public int Count {
+ get {
+ return pids_.Count;
+ }
+ }
+
+ public bool IsSynchronized {
+ get {
+ throw new Exception("The method or operation is not implemented.");
+ }
+ }
+
+ public object SyncRoot {
+ get {
+ throw new Exception("The method or operation is not implemented.");
+ }
+ }
+ #endregion
+
+ #region IEnumerable Members
+ public IEnumerator GetEnumerator() {
+ return pids_.GetEnumerator();
+ }
+ #endregion
+
+ /// <summary>
+ /// Initialize the pid list.
+ /// </summary>
+ private void Initialize() {
+ long offset = table_.ThreadNamesOffset;
+
+ for (int index = 0; index < table_.Header.max_threads; index++) {
+ string thread_name = Marshal.PtrToStringUni((IntPtr)offset);
+ if (thread_name.Length > 0) {
+ long pidOffset = table_.PidsOffset + index *
+ Marshal.SizeOf(typeof(int));
+ int pid = Marshal.ReadInt32((IntPtr)pidOffset);
+ if (!pids_.Contains(pid))
+ pids_.Add(pid);
+ }
+ offset += StatsTable.kMaxThreadNameLength * 2;
+ }
+ }
+
+ #region Private Members
+ private StatsTable table_;
+ private List<int> pids_;
+ #endregion
+ }
+}
diff --git a/chromium/tools/stats_viewer/stats_viewer.Designer.cs b/chromium/tools/stats_viewer/stats_viewer.Designer.cs
new file mode 100644
index 00000000000..34a54c9b032
--- /dev/null
+++ b/chromium/tools/stats_viewer/stats_viewer.Designer.cs
@@ -0,0 +1,392 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+namespace StatsViewer
+{
+ partial class StatsViewer
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(StatsViewer));
+ this.listViewCounters = new System.Windows.Forms.ListView();
+ this.columnHeaderName = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderValue = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderDelta = new System.Windows.Forms.ColumnHeader();
+ this.pictureBoxTitle = new System.Windows.Forms.PictureBox();
+ this.panelHeader = new System.Windows.Forms.Panel();
+ this.labelKills = new System.Windows.Forms.Label();
+ this.label1 = new System.Windows.Forms.Label();
+ this.labelInterval = new System.Windows.Forms.Label();
+ this.comboBoxFilter = new System.Windows.Forms.ComboBox();
+ this.panelControls = new System.Windows.Forms.Panel();
+ this.buttonExport = new System.Windows.Forms.Button();
+ this.buttonZero = new System.Windows.Forms.Button();
+ this.comboBoxInterval = new System.Windows.Forms.ComboBox();
+ this.labelFilter = new System.Windows.Forms.Label();
+ this.saveFileDialogExport = new System.Windows.Forms.SaveFileDialog();
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.closeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.listViewRates = new System.Windows.Forms.ListView();
+ this.columnHeaderRateName = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderRateCount = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderRateTotaltime = new System.Windows.Forms.ColumnHeader();
+ this.columnHeaderRateAvgTime = new System.Windows.Forms.ColumnHeader();
+ this.splitContainer1 = new System.Windows.Forms.SplitContainer();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBoxTitle)).BeginInit();
+ this.panelHeader.SuspendLayout();
+ this.panelControls.SuspendLayout();
+ this.menuStrip1.SuspendLayout();
+ this.splitContainer1.Panel1.SuspendLayout();
+ this.splitContainer1.Panel2.SuspendLayout();
+ this.splitContainer1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // listViewCounters
+ //
+ this.listViewCounters.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeaderName,
+ this.columnHeaderValue,
+ this.columnHeaderDelta});
+ this.listViewCounters.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.listViewCounters.FullRowSelect = true;
+ this.listViewCounters.Location = new System.Drawing.Point(0, 0);
+ this.listViewCounters.Name = "listViewCounters";
+ this.listViewCounters.Size = new System.Drawing.Size(505, 221);
+ this.listViewCounters.Sorting = System.Windows.Forms.SortOrder.Descending;
+ this.listViewCounters.TabIndex = 0;
+ this.listViewCounters.UseCompatibleStateImageBehavior = false;
+ this.listViewCounters.View = System.Windows.Forms.View.Details;
+ this.listViewCounters.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.column_Click);
+ //
+ // columnHeaderName
+ //
+ this.columnHeaderName.Text = "Counter Name";
+ this.columnHeaderName.Width = 203;
+ //
+ // columnHeaderValue
+ //
+ this.columnHeaderValue.Text = "Value";
+ this.columnHeaderValue.Width = 69;
+ //
+ // columnHeaderDelta
+ //
+ this.columnHeaderDelta.Text = "Delta";
+ this.columnHeaderDelta.Width = 86;
+ //
+ // pictureBoxTitle
+ //
+ this.pictureBoxTitle.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.pictureBoxTitle.BackColor = System.Drawing.Color.Transparent;
+ this.pictureBoxTitle.Image = ((System.Drawing.Image)(resources.GetObject("pictureBoxTitle.Image")));
+ this.pictureBoxTitle.Location = new System.Drawing.Point(257, 0);
+ this.pictureBoxTitle.Name = "pictureBoxTitle";
+ this.pictureBoxTitle.Size = new System.Drawing.Size(248, 86);
+ this.pictureBoxTitle.TabIndex = 1;
+ this.pictureBoxTitle.TabStop = false;
+ //
+ // panelHeader
+ //
+ this.panelHeader.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("panelHeader.BackgroundImage")));
+ this.panelHeader.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
+ this.panelHeader.Controls.Add(this.labelKills);
+ this.panelHeader.Controls.Add(this.label1);
+ this.panelHeader.Controls.Add(this.pictureBoxTitle);
+ this.panelHeader.Dock = System.Windows.Forms.DockStyle.Top;
+ this.panelHeader.Location = new System.Drawing.Point(0, 24);
+ this.panelHeader.Name = "panelHeader";
+ this.panelHeader.Size = new System.Drawing.Size(505, 86);
+ this.panelHeader.TabIndex = 2;
+ //
+ // labelKills
+ //
+ this.labelKills.AutoSize = true;
+ this.labelKills.BackColor = System.Drawing.Color.Transparent;
+ this.labelKills.Font = new System.Drawing.Font("Arial", 9.75F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.labelKills.Location = new System.Drawing.Point(12, 33);
+ this.labelKills.Name = "labelKills";
+ this.labelKills.Size = new System.Drawing.Size(280, 16);
+ this.labelKills.TabIndex = 3;
+ this.labelKills.Text = "During the World Wide Wait, God Kills Kittens.";
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.BackColor = System.Drawing.Color.Transparent;
+ this.label1.Font = new System.Drawing.Font("Arial", 15.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label1.Location = new System.Drawing.Point(12, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(140, 24);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "Chrome Varz";
+ //
+ // labelInterval
+ //
+ this.labelInterval.AutoSize = true;
+ this.labelInterval.Location = new System.Drawing.Point(11, 9);
+ this.labelInterval.Name = "labelInterval";
+ this.labelInterval.Size = new System.Drawing.Size(73, 13);
+ this.labelInterval.TabIndex = 3;
+ this.labelInterval.Text = "Interval (secs)";
+ //
+ // comboBoxFilter
+ //
+ this.comboBoxFilter.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.comboBoxFilter.FormattingEnabled = true;
+ this.comboBoxFilter.Location = new System.Drawing.Point(302, 5);
+ this.comboBoxFilter.Name = "comboBoxFilter";
+ this.comboBoxFilter.Size = new System.Drawing.Size(121, 21);
+ this.comboBoxFilter.TabIndex = 5;
+ this.comboBoxFilter.SelectedIndexChanged += new System.EventHandler(this.filter_changed);
+ this.comboBoxFilter.DropDownClosed += new System.EventHandler(this.mouse_Leave);
+ this.comboBoxFilter.DropDown += new System.EventHandler(this.mouse_Enter);
+ //
+ // panelControls
+ //
+ this.panelControls.Controls.Add(this.buttonExport);
+ this.panelControls.Controls.Add(this.buttonZero);
+ this.panelControls.Controls.Add(this.comboBoxInterval);
+ this.panelControls.Controls.Add(this.labelFilter);
+ this.panelControls.Controls.Add(this.comboBoxFilter);
+ this.panelControls.Controls.Add(this.labelInterval);
+ this.panelControls.Dock = System.Windows.Forms.DockStyle.Top;
+ this.panelControls.Location = new System.Drawing.Point(0, 110);
+ this.panelControls.Name = "panelControls";
+ this.panelControls.Size = new System.Drawing.Size(505, 32);
+ this.panelControls.TabIndex = 6;
+ //
+ // buttonExport
+ //
+ this.buttonExport.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonExport.Location = new System.Drawing.Point(187, 4);
+ this.buttonExport.Name = "buttonExport";
+ this.buttonExport.Size = new System.Drawing.Size(75, 23);
+ this.buttonExport.TabIndex = 9;
+ this.buttonExport.Text = "Export";
+ this.buttonExport.UseVisualStyleBackColor = true;
+ this.buttonExport.Click += new System.EventHandler(this.buttonExport_Click);
+ //
+ // buttonZero
+ //
+ this.buttonZero.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonZero.Location = new System.Drawing.Point(427, 4);
+ this.buttonZero.Name = "buttonZero";
+ this.buttonZero.Size = new System.Drawing.Size(75, 23);
+ this.buttonZero.TabIndex = 8;
+ this.buttonZero.Text = "Clear All";
+ this.buttonZero.UseVisualStyleBackColor = true;
+ this.buttonZero.Click += new System.EventHandler(this.buttonZero_Click);
+ //
+ // comboBoxInterval
+ //
+ this.comboBoxInterval.FormattingEnabled = true;
+ this.comboBoxInterval.Items.AddRange(new object[] {
+ "1",
+ "2",
+ "5",
+ "10",
+ "30",
+ "60"});
+ this.comboBoxInterval.Location = new System.Drawing.Point(84, 6);
+ this.comboBoxInterval.Name = "comboBoxInterval";
+ this.comboBoxInterval.Size = new System.Drawing.Size(55, 21);
+ this.comboBoxInterval.TabIndex = 7;
+ this.comboBoxInterval.Text = "1";
+ this.comboBoxInterval.SelectedIndexChanged += new System.EventHandler(this.interval_changed);
+ this.comboBoxInterval.DropDownClosed += new System.EventHandler(this.mouse_Leave);
+ this.comboBoxInterval.DropDown += new System.EventHandler(this.mouse_Enter);
+ //
+ // labelFilter
+ //
+ this.labelFilter.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.labelFilter.AutoSize = true;
+ this.labelFilter.Location = new System.Drawing.Point(268, 9);
+ this.labelFilter.Name = "labelFilter";
+ this.labelFilter.Size = new System.Drawing.Size(29, 13);
+ this.labelFilter.TabIndex = 6;
+ this.labelFilter.Text = "Filter";
+ //
+ // saveFileDialogExport
+ //
+ this.saveFileDialogExport.FileName = "results.txt";
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.fileToolStripMenuItem});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Size = new System.Drawing.Size(505, 24);
+ this.menuStrip1.TabIndex = 7;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // fileToolStripMenuItem
+ //
+ this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.openToolStripMenuItem,
+ this.closeToolStripMenuItem,
+ this.quitToolStripMenuItem});
+ this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+ this.fileToolStripMenuItem.Size = new System.Drawing.Size(35, 20);
+ this.fileToolStripMenuItem.Text = "File";
+ //
+ // openToolStripMenuItem
+ //
+ this.openToolStripMenuItem.Name = "openToolStripMenuItem";
+ this.openToolStripMenuItem.Size = new System.Drawing.Size(111, 22);
+ this.openToolStripMenuItem.Text = "Open";
+ this.openToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click);
+ //
+ // closeToolStripMenuItem
+ //
+ this.closeToolStripMenuItem.Name = "closeToolStripMenuItem";
+ this.closeToolStripMenuItem.Size = new System.Drawing.Size(111, 22);
+ this.closeToolStripMenuItem.Text = "Close";
+ this.closeToolStripMenuItem.Click += new System.EventHandler(this.closeToolStripMenuItem_Click);
+ //
+ // quitToolStripMenuItem
+ //
+ this.quitToolStripMenuItem.Name = "quitToolStripMenuItem";
+ this.quitToolStripMenuItem.Size = new System.Drawing.Size(111, 22);
+ this.quitToolStripMenuItem.Text = "Quit";
+ this.quitToolStripMenuItem.Click += new System.EventHandler(this.quitToolStripMenuItem_Click);
+ //
+ // listViewRates
+ //
+ this.listViewRates.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.columnHeaderRateName,
+ this.columnHeaderRateCount,
+ this.columnHeaderRateTotaltime,
+ this.columnHeaderRateAvgTime});
+ this.listViewRates.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.listViewRates.FullRowSelect = true;
+ this.listViewRates.Location = new System.Drawing.Point(0, 0);
+ this.listViewRates.Name = "listViewRates";
+ this.listViewRates.Size = new System.Drawing.Size(505, 270);
+ this.listViewRates.Sorting = System.Windows.Forms.SortOrder.Descending;
+ this.listViewRates.TabIndex = 8;
+ this.listViewRates.UseCompatibleStateImageBehavior = false;
+ this.listViewRates.View = System.Windows.Forms.View.Details;
+ //
+ // columnHeaderRateName
+ //
+ this.columnHeaderRateName.Text = "Rate Name";
+ this.columnHeaderRateName.Width = 205;
+ //
+ // columnHeaderRateCount
+ //
+ this.columnHeaderRateCount.Text = "Count";
+ //
+ // columnHeaderRateTotaltime
+ //
+ this.columnHeaderRateTotaltime.Text = "Total Time (ms)";
+ this.columnHeaderRateTotaltime.Width = 100;
+ //
+ // columnHeaderRateAvgTime
+ //
+ this.columnHeaderRateAvgTime.Text = "Average Time (ms)";
+ this.columnHeaderRateAvgTime.Width = 110;
+ //
+ // splitContainer1
+ //
+ this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.splitContainer1.Location = new System.Drawing.Point(0, 142);
+ this.splitContainer1.Name = "splitContainer1";
+ this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // splitContainer1.Panel1
+ //
+ this.splitContainer1.Panel1.Controls.Add(this.listViewCounters);
+ //
+ // splitContainer1.Panel2
+ //
+ this.splitContainer1.Panel2.Controls.Add(this.listViewRates);
+ this.splitContainer1.Size = new System.Drawing.Size(505, 495);
+ this.splitContainer1.SplitterDistance = 221;
+ this.splitContainer1.TabIndex = 9;
+ //
+ // StatsViewer
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(505, 637);
+ this.Controls.Add(this.splitContainer1);
+ this.Controls.Add(this.panelControls);
+ this.Controls.Add(this.panelHeader);
+ this.Controls.Add(this.menuStrip1);
+ this.DoubleBuffered = true;
+ this.Name = "StatsViewer";
+ this.Text = "Chrome Varz";
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBoxTitle)).EndInit();
+ this.panelHeader.ResumeLayout(false);
+ this.panelHeader.PerformLayout();
+ this.panelControls.ResumeLayout(false);
+ this.panelControls.PerformLayout();
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.splitContainer1.Panel1.ResumeLayout(false);
+ this.splitContainer1.Panel2.ResumeLayout(false);
+ this.splitContainer1.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ListView listViewCounters;
+ private System.Windows.Forms.ColumnHeader columnHeaderName;
+ private System.Windows.Forms.ColumnHeader columnHeaderValue;
+ private System.Windows.Forms.ColumnHeader columnHeaderDelta;
+ private System.Windows.Forms.PictureBox pictureBoxTitle;
+ private System.Windows.Forms.Panel panelHeader;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label labelInterval;
+ private System.Windows.Forms.ComboBox comboBoxFilter;
+ private System.Windows.Forms.Panel panelControls;
+ private System.Windows.Forms.Label labelFilter;
+ private System.Windows.Forms.ComboBox comboBoxInterval;
+ private System.Windows.Forms.Label labelKills;
+ private System.Windows.Forms.Button buttonZero;
+ private System.Windows.Forms.Button buttonExport;
+ private System.Windows.Forms.SaveFileDialog saveFileDialogExport;
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem closeToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem quitToolStripMenuItem;
+ private System.Windows.Forms.ListView listViewRates;
+ private System.Windows.Forms.ColumnHeader columnHeaderRateName;
+ private System.Windows.Forms.ColumnHeader columnHeaderRateCount;
+ private System.Windows.Forms.ColumnHeader columnHeaderRateTotaltime;
+ private System.Windows.Forms.ColumnHeader columnHeaderRateAvgTime;
+ private System.Windows.Forms.SplitContainer splitContainer1;
+ }
+}
diff --git a/chromium/tools/stats_viewer/stats_viewer.cs b/chromium/tools/stats_viewer/stats_viewer.cs
new file mode 100644
index 00000000000..eebb882c540
--- /dev/null
+++ b/chromium/tools/stats_viewer/stats_viewer.cs
@@ -0,0 +1,510 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+
+namespace StatsViewer {
+ public partial class StatsViewer : Form {
+ /// <summary>
+ /// Create a StatsViewer.
+ /// </summary>
+ public StatsViewer() {
+ InitializeComponent();
+ }
+
+ #region Protected Methods
+ /// <summary>
+ /// Callback when the form loads.
+ /// </summary>
+ /// <param name="e"></param>
+ protected override void OnLoad(EventArgs e) {
+ base.OnLoad(e);
+
+ timer_ = new Timer();
+ timer_.Interval = kPollInterval;
+ timer_.Tick += new EventHandler(PollTimerTicked);
+ timer_.Start();
+ }
+ #endregion
+
+ #region Private Methods
+ /// <summary>
+ /// Attempt to open the stats file.
+ /// Return true on success, false otherwise.
+ /// </summary>
+ private bool OpenStatsFile() {
+ StatsTable table = new StatsTable();
+ if (table.Open(kStatsTableName)) {
+ stats_table_ = table;
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Close the open stats file.
+ /// </summary>
+ private void CloseStatsFile() {
+ if (this.stats_table_ != null)
+ {
+ this.stats_table_.Close();
+ this.stats_table_ = null;
+ this.listViewCounters.Items.Clear();
+ }
+ }
+
+ /// <summary>
+ /// Updates the process list in the UI.
+ /// </summary>
+ private void UpdateProcessList() {
+ int current_pids = comboBoxFilter.Items.Count;
+ int table_pids = stats_table_.Processes.Count;
+ if (current_pids != table_pids + 1) // Add one because of the "all" entry.
+ {
+ int selected_index = this.comboBoxFilter.SelectedIndex;
+ this.comboBoxFilter.Items.Clear();
+ this.comboBoxFilter.Items.Add(kStringAllProcesses);
+ foreach (int pid in stats_table_.Processes)
+ this.comboBoxFilter.Items.Add(kStringProcess + pid.ToString());
+ this.comboBoxFilter.SelectedIndex = selected_index;
+ }
+ }
+
+ /// <summary>
+ /// Updates the UI for a counter.
+ /// </summary>
+ /// <param name="counter"></param>
+ private void UpdateCounter(IStatsCounter counter) {
+ ListView view;
+
+ // Figure out which list this counter goes into.
+ if (counter is StatsCounterRate)
+ view = listViewRates;
+ else if (counter is StatsCounter || counter is StatsTimer)
+ view = listViewCounters;
+ else
+ return; // Counter type not supported yet.
+
+ // See if the counter is already in the list.
+ ListViewItem item = view.Items[counter.name];
+ if (item != null)
+ {
+ // Update an existing counter.
+ Debug.Assert(item is StatsCounterListViewItem);
+ StatsCounterListViewItem counter_item = item as StatsCounterListViewItem;
+ counter_item.Update(counter, filter_pid_);
+ }
+ else
+ {
+ // Create a new counter
+ StatsCounterListViewItem new_item = null;
+ if (counter is StatsCounterRate)
+ new_item = new RateListViewItem(counter, filter_pid_);
+ else if (counter is StatsCounter || counter is StatsTimer)
+ new_item = new CounterListViewItem(counter, filter_pid_);
+ Debug.Assert(new_item != null);
+ view.Items.Add(new_item);
+ }
+ }
+
+ /// <summary>
+ /// Sample the data and update the UI
+ /// </summary>
+ private void SampleData() {
+ // If the table isn't open, try to open it again.
+ if (stats_table_ == null)
+ if (!OpenStatsFile())
+ return;
+
+ if (stats_counters_ == null)
+ stats_counters_ = stats_table_.Counters();
+
+ if (pause_updates_)
+ return;
+
+ stats_counters_.Update();
+
+ UpdateProcessList();
+
+ foreach (IStatsCounter counter in stats_counters_)
+ UpdateCounter(counter);
+ }
+
+ /// <summary>
+ /// Set the background color based on the value
+ /// </summary>
+ /// <param name="item"></param>
+ /// <param name="value"></param>
+ private void ColorItem(ListViewItem item, int value)
+ {
+ if (value < 0)
+ item.ForeColor = Color.Red;
+ else if (value > 0)
+ item.ForeColor = Color.DarkGreen;
+ else
+ item.ForeColor = Color.Black;
+ }
+
+ /// <summary>
+ /// Called when the timer fires.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ void PollTimerTicked(object sender, EventArgs e) {
+ SampleData();
+ }
+
+ /// <summary>
+ /// Called when the interval is changed by the user.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void interval_changed(object sender, EventArgs e) {
+ int interval = 1;
+ if (int.TryParse(comboBoxInterval.Text, out interval)) {
+ if (timer_ != null) {
+ timer_.Stop();
+ timer_.Interval = interval * 1000;
+ timer_.Start();
+ }
+ } else {
+ comboBoxInterval.Text = timer_.Interval.ToString();
+ }
+ }
+
+ /// <summary>
+ /// Called when the user changes the filter
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void filter_changed(object sender, EventArgs e) {
+ // While in this event handler, don't allow recursive events!
+ this.comboBoxFilter.SelectedIndexChanged -= new System.EventHandler(this.filter_changed);
+ if (this.comboBoxFilter.Text == kStringAllProcesses)
+ filter_pid_ = 0;
+ else
+ int.TryParse(comboBoxFilter.Text.Substring(kStringProcess.Length), out filter_pid_);
+ SampleData();
+ this.comboBoxFilter.SelectedIndexChanged += new System.EventHandler(this.filter_changed);
+ }
+
+ /// <summary>
+ /// Callback when the mouse enters a control
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void mouse_Enter(object sender, EventArgs e) {
+ // When the dropdown is expanded, we pause
+ // updates, as it messes with the UI.
+ pause_updates_ = true;
+ }
+
+ /// <summary>
+ /// Callback when the mouse leaves a control
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void mouse_Leave(object sender, EventArgs e) {
+ pause_updates_ = false;
+ }
+
+ /// <summary>
+ /// Called when the user clicks the zero-stats button.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void buttonZero_Click(object sender, EventArgs e) {
+ this.stats_table_.Zero();
+ SampleData();
+ }
+
+ /// <summary>
+ /// Called when the user clicks a column heading.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void column_Click(object sender, ColumnClickEventArgs e) {
+ if (e.Column != sort_column_) {
+ sort_column_ = e.Column;
+ this.listViewCounters.Sorting = SortOrder.Ascending;
+ } else {
+ if (this.listViewCounters.Sorting == SortOrder.Ascending)
+ this.listViewCounters.Sorting = SortOrder.Descending;
+ else
+ this.listViewCounters.Sorting = SortOrder.Ascending;
+ }
+
+ this.listViewCounters.ListViewItemSorter =
+ new ListViewItemComparer(e.Column, this.listViewCounters.Sorting);
+ this.listViewCounters.Sort();
+ }
+
+ /// <summary>
+ /// Called when the user clicks the button "Export".
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ private void buttonExport_Click(object sender, EventArgs e) {
+ //Have to pick a textfile to export to.
+ //Saves what is shown in listViewStats in the format: function value
+ //(with a tab in between), so that it is easy to copy paste into a spreadsheet.
+ //(Does not save the delta values.)
+ TextWriter tw = null;
+ try {
+ saveFileDialogExport.CheckFileExists = false;
+ saveFileDialogExport.ShowDialog();
+ tw = new StreamWriter(saveFileDialogExport.FileName);
+
+ for (int i = 0; i < listViewCounters.Items.Count; i++) {
+ tw.Write(listViewCounters.Items[i].SubItems[0].Text + "\t");
+ tw.WriteLine(listViewCounters.Items[i].SubItems[1].Text);
+ }
+ }
+ catch (IOException ex) {
+ MessageBox.Show(string.Format("There was an error while saving your results file. The results might not have been saved correctly.: {0}", ex.Message));
+ }
+ finally{
+ if (tw != null) tw.Close();
+ }
+ }
+
+ #endregion
+
+ class ListViewItemComparer : IComparer {
+ public ListViewItemComparer() {
+ this.col_ = 0;
+ this.order_ = SortOrder.Ascending;
+ }
+
+ public ListViewItemComparer(int column, SortOrder order) {
+ this.col_ = column;
+ this.order_ = order;
+ }
+
+ public int Compare(object x, object y) {
+ int return_value = -1;
+
+ object x_tag = ((ListViewItem)x).SubItems[col_].Tag;
+ object y_tag = ((ListViewItem)y).SubItems[col_].Tag;
+
+ if (Comparable(x_tag, y_tag))
+ return_value = ((IComparable)x_tag).CompareTo(y_tag);
+ else
+ return_value = String.Compare(((ListViewItem)x).SubItems[col_].Text,
+ ((ListViewItem)y).SubItems[col_].Text);
+
+ if (order_ == SortOrder.Descending)
+ return_value *= -1;
+
+ return return_value;
+ }
+
+ #region Private Methods
+ private bool Comparable(object x, object y) {
+ if (x == null || y == null)
+ return false;
+
+ return x is IComparable && y is IComparable;
+ }
+ #endregion
+
+ #region Private Members
+ private int col_;
+ private SortOrder order_;
+ #endregion
+ }
+
+ #region Private Members
+ private const string kStringAllProcesses = "All Processes";
+ private const string kStringProcess = "Process ";
+ private const int kPollInterval = 1000; // 1 second
+ private const string kStatsTableName = "ChromeStats";
+ private StatsTable stats_table_;
+ private StatsTableCounters stats_counters_;
+ private Timer timer_;
+ private int filter_pid_;
+ private bool pause_updates_;
+ private int sort_column_ = -1;
+ #endregion
+
+ #region Private Event Callbacks
+ private void openToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ OpenDialog dialog = new OpenDialog();
+ dialog.ShowDialog();
+
+ CloseStatsFile();
+
+ StatsTable table = new StatsTable();
+ bool rv = table.Open(dialog.FileName);
+ if (!rv)
+ {
+ MessageBox.Show("Could not open statsfile: " + dialog.FileName);
+ }
+ else
+ {
+ stats_table_ = table;
+ }
+ }
+
+ private void closeToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ CloseStatsFile();
+ }
+
+ private void quitToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Application.Exit();
+ }
+ #endregion
+ }
+
+ /// <summary>
+ /// Base class for counter list view items.
+ /// </summary>
+ internal class StatsCounterListViewItem : ListViewItem
+ {
+ /// <summary>
+ /// Create the ListViewItem
+ /// </summary>
+ /// <param name="text"></param>
+ public StatsCounterListViewItem(string text) : base(text) { }
+
+ /// <summary>
+ /// Update the ListViewItem given a new counter value.
+ /// </summary>
+ /// <param name="counter"></param>
+ /// <param name="filter_pid"></param>
+ public virtual void Update(IStatsCounter counter, int filter_pid) { }
+
+ /// <summary>
+ /// Set the background color based on the value
+ /// </summary>
+ /// <param name="value"></param>
+ protected void ColorItem(int value)
+ {
+ if (value < 0)
+ ForeColor = Color.Red;
+ else if (value > 0)
+ ForeColor = Color.DarkGreen;
+ else
+ ForeColor = Color.Black;
+ }
+
+ /// <summary>
+ /// Create a new subitem with a zeroed Tag.
+ /// </summary>
+ /// <returns></returns>
+ protected ListViewSubItem NewSubItem()
+ {
+ ListViewSubItem item = new ListViewSubItem();
+ item.Tag = -1; // Arbitrarily initialize to -1.
+ return item;
+ }
+
+ /// <summary>
+ /// Set the value for a subitem.
+ /// </summary>
+ /// <param name="item"></param>
+ /// <param name="val"></param>
+ /// <returns>True if the value changed, false otherwise</returns>
+ protected bool SetSubItem(ListViewSubItem item, int val)
+ {
+ // The reason for doing this extra compare is because
+ // we introduce flicker if we unnecessarily update the
+ // subitems. The UI is much less likely to cause you
+ // a seizure when we do this.
+ if (val != (int)item.Tag)
+ {
+ item.Text = val.ToString();
+ item.Tag = val;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// A listview item which contains a rate.
+ /// </summary>
+ internal class RateListViewItem : StatsCounterListViewItem
+ {
+ public RateListViewItem(IStatsCounter ctr, int filter_pid) :
+ base(ctr.name)
+ {
+ StatsCounterRate rate = ctr as StatsCounterRate;
+ Name = rate.name;
+ SubItems.Add(NewSubItem());
+ SubItems.Add(NewSubItem());
+ SubItems.Add(NewSubItem());
+ Update(ctr, filter_pid);
+ }
+
+ public override void Update(IStatsCounter counter, int filter_pid)
+ {
+ Debug.Assert(counter is StatsCounterRate);
+
+ StatsCounterRate new_rate = counter as StatsCounterRate;
+ int new_count = new_rate.GetCount(filter_pid);
+ int new_time = new_rate.GetTime(filter_pid);
+ int old_avg = Tag != null ? (int)Tag : 0;
+ int new_avg = new_count > 0 ? (new_time / new_count) : 0;
+ int delta = new_avg - old_avg;
+
+ SetSubItem(SubItems[column_count_index], new_count);
+ SetSubItem(SubItems[column_time_index], new_time);
+ if (SetSubItem(SubItems[column_avg_index], new_avg))
+ ColorItem(delta);
+ Tag = new_avg;
+ }
+
+ private const int column_count_index = 1;
+ private const int column_time_index = 2;
+ private const int column_avg_index = 3;
+ }
+
+ /// <summary>
+ /// A listview item which contains a counter.
+ /// </summary>
+ internal class CounterListViewItem : StatsCounterListViewItem
+ {
+ public CounterListViewItem(IStatsCounter ctr, int filter_pid) :
+ base(ctr.name)
+ {
+ Name = ctr.name;
+ SubItems.Add(NewSubItem());
+ SubItems.Add(NewSubItem());
+ Update(ctr, filter_pid);
+ }
+
+ public override void Update(IStatsCounter counter, int filter_pid) {
+ Debug.Assert(counter is StatsCounter || counter is StatsTimer);
+
+ int new_value = 0;
+ if (counter is StatsCounter)
+ new_value = ((StatsCounter)counter).GetValue(filter_pid);
+ else if (counter is StatsTimer)
+ new_value = ((StatsTimer)counter).GetValue(filter_pid);
+
+ int old_value = Tag != null ? (int)Tag : 0;
+ int delta = new_value - old_value;
+ SetSubItem(SubItems[column_value_index], new_value);
+ if (SetSubItem(SubItems[column_delta_index], delta))
+ ColorItem(delta);
+ Tag = new_value;
+ }
+
+ private const int column_value_index = 1;
+ private const int column_delta_index = 2;
+ }
+}
diff --git a/chromium/tools/stats_viewer/stats_viewer.csproj b/chromium/tools/stats_viewer/stats_viewer.csproj
new file mode 100644
index 00000000000..2b6fa6c8305
--- /dev/null
+++ b/chromium/tools/stats_viewer/stats_viewer.csproj
@@ -0,0 +1,107 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{41735CD9-3E35-47F7-9FD1-4A9950B6B131}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>StatsViewer</RootNamespace>
+ <AssemblyName>stats_viewer</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>$(SolutionDir)$(Configuration)</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>$(SolutionDir)$(Configuration)</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Deployment" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="OpenDialog.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="OpenDialog.Designer.cs">
+ <DependentUpon>OpenDialog.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="stats_viewer.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="stats_viewer.Designer.cs">
+ <DependentUpon>stats_viewer.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <EmbeddedResource Include="OpenDialog.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>OpenDialog.cs</DependentUpon>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Resources.resx">
+ <SubType>Designer</SubType>
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <EmbeddedResource Include="stats_viewer.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>stats_viewer.cs</DependentUpon>
+ </EmbeddedResource>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <Compile Include="stats_table.cs" />
+ <Compile Include="win32.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\kitten.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Resources\kittenbackground.png" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/chromium/tools/stats_viewer/stats_viewer.resx b/chromium/tools/stats_viewer/stats_viewer.resx
new file mode 100644
index 00000000000..117f3891aba
--- /dev/null
+++ b/chromium/tools/stats_viewer/stats_viewer.resx
@@ -0,0 +1,1129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <data name="pictureBoxTitle.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>
+ iVBORw0KGgoAAAANSUhEUgAAAPgAAABWCAIAAABtpczCAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAOxAAA
+ DsQBlSsOGwAA4PdJREFUeF5k/QVAXNf2/4GmdnutvZV4gjPu7oN70KBBEggJcScBgru7u7u7u2sggQTi
+ JLgmaa/1tnnrDGl///de++3umTMDDMPnfGfttdde81nzg+B3vz3/+edf9n3++W+f7fvss88+//zzfb99
+ /O3jr3C07+PHj8g5yR2f/fb5Z59JTnzc93Ef/PPZ55J/4d59+3777TfkzGdwz8fPP/8CTsMDkX8+R87v
+ g9OS7yF5DIzwGORbwQ+AB38BP0jyGPhayXeAx8AT2PspyH/wUyRPA77H3j/IwyR3Sb7hp/8kj5b8VHi4
+ 5CnDEdyUPAz53faeMzJ8hGe79+sgPwueC/JbID9xHzxbyZcgD5c8FeSLkV9Y8v0k5yRPDHk94IuQZ/L7
+ k/r03H5/Wnsvx96vtfddfn8FkG+GvFx7J+CZSJ6G5Bf6DXkCezf++CLJzb1fcu8l3btr74X69KrBr7f3
+ 6/8G3wN+H+R3/PRg+LWQ7yn5Q8Idn++9QvDCS37ZvdcE+Ta//iZ5QSS/oOQvgbzMkh8gOUBuw13Ic4Xv
+ uPc67/0PeSmQZ4P8ADiBfIu9v7Hkzr0fIXll954sPDP4ayLfU/JtADXJS4N829/gGcIvAH8deMrwf+Rb
+ 7n255IF7Z/aQkPxR4FXc+xGffl/kYb/uIbv35fCH3vfZF5/99uvHfakdJ2MGyQFteL9Ogm8nyb+bEtBL
+ Deym+HcTA3pIAd1k5EwPJbCHGtxHCRmkhgyQQwaIIQMkRIPk0CFK2DA1bIgiOaCEjyCKGKNHTjAixkH0
+ yEl61BSIGjFNi5qhg2IegWhxcyBqwiw1ZZ6ZscBOf8pJf8pKf8rMeM7KeM5Mf0FPe0ZLe05LfUZNXqCk
+ PqOlv2CkP2ekP6NlPKNmvKBmvqBmvaJlv6LnLIIYuYv03EVaziI1RzLmvqHkviXnviXlL5Hyl4mgvE83
+ KfnL5PwVcv4yKX+FULJOLt4gF6+TSzZoJZuM4i0acnODVLJJKtkil21RyjYpZRtUicifhJyhlK6Ty7eo
+ lds0UPUOtWaHujfW7tD+UN07Wu07hkT0PdW9p9f/xATBQcMOo36b0bjDaH7Han7PbHxHb3xPh7HhHa3h
+ HbXxPa3hPbXuHaVuV6J3lPr31IYPyMkGyV3I+IGGnJScb/qZ3vgTPIZY/wFf/wFb/wHXgIhQjwhuous/
+ YGrfYepA7/HIw96R6t6R63ZItdvEmm1i3TtS7S6hegdX+45Q+55QvYuv2sFVvsNX7hAqdwmVO8SKbVLF
+ NgXRFrVskwq/fskqsXiVhGiFXLwKrwmtZI0KByUrlOIVSukqtWSFWrRMLl6BA3rJMr1wiZq3TM1foecv
+ M/KXmHlvmXlv2Dmv2Vkv4C/OyHjBTH/KSF2gpy0wUhYYSXP0xFl6/ENK3Aw5bpoc+4AU84AYOYGPGMdG
+ TeAix0FYuBk+hgsZwoQM40KHCcFDhOBBfFA/IbCXENiHC+jDBvRi/bqxfl24gF6ibydhX3aPTXAL1r0S
+ 5VaDca3DuNZi79fjPOpw9+sw9+sxHg0Ej0aiRyPBswnv3ULwbsX7tOK8WzFeLYjgwKcN69eO92nD+bbj
+ /ToI/p1E/05CQDcpoIcMo38XXC3kwD5iUB8+cIAYNEgKHSKFj5BBEaPksCFC+DA+ZpwcP0GNm6AkTCGK
+ nSLFTBJiQVOE2GlC7ANi9CQ+ZgIXN0WMBU0S4idxCQ/widOIkmbwKY+IEhFSHuGTH+JSHkk0iwWlPsal
+ PcamPcakP4ERhMuYJ6Q/wafP49KeYDIWMNnPcVnPEGU/J2S/IGY9J2S9wGU+hfOY3Jf43JeEvJfE/Jek
+ /BfEvBf4vJcSvcDnvyLkwk04eEnIf4kvfIUreo0vfI2HsfgVvmRPrwkli4TiRbxEcEAofg0ilr4hl70l
+ ly6SS16R9lS+SC1/A6KUL5LL4d5FYvlbUsVbMowlyDfEgeCg9A2h7C2hdBFXuoj/fYQDfBnoDaFiiVD+
+ Fu5Cl75Blb5RLHuLKl9Cly9hyt5iyt6gy94iZ+A8cu8inMGCSt/gSl/DN8cUvcSUvMYWv0IVvFIsWkQX
+ vkYXvlIseKmQD2deo/NfofNeYnJfYHKf40A58Io9x8MrBq9exgI+Yx6fuUDIeorPfkbKfkbOWiBlzRMz
+ nxBgzHhMTHuMz3hCSn9CTp0jpsziUx6TUh9TUh9TU2apSbO0xIeMhGla3BQ1dpIaM0GLHCWHDxMjhknh
+ Q+TgPmJIPymoFx/QjduTfxfWp13Ru03Bt0MRDnzaFbzbFL1aFTya5T2aFT2aFD0a0e6NCLFuwG0dyr0O
+ eFZ0q1J0QcBGu1Zh9uX02oa24z1rMO71kscB3I0470a8ZyPWoxHr1UzwbiEB5V4I6DivFiyQ7d2G8W5D
+ +7Zj/DvhGcDzIAT2EGEEBfUR4ZIK6iUF91IQ9ZFD+smhg/DsEb4jJIoao0SNkSJHiDFjhPgJcuw4MWGK
+ nDRNTZgixU0SEmdICaBpQsJDYvwMPu4BHo4TZ4hJM6Skh6TkhyTAOn2WlDEHryAIXk1C6hw+ZRaBO3UO
+ yAbh058A0IQMeNEX4C8B7GIzFrAZ8wA6PuspIec5CcjOegZAY4H1nBf4nBcEEMCd9wqPUP4CU/CaACp8
+ RSx4RYKx6BUeEQD9+wgHCOKv/sAOOAN0sKWvsABQ2Wtc+Rt8+VtsxRts+Vt8xRsQoRyIBIiXyJVvyBWL
+ VFDlW3r1Eq16CRkr31Ar31CQB7whVL4lgsoXCeWLeBAcVy2RqpfJ1ctEUJVk/ENVS4TKJULVErFyCVvx
+ Fl25hNkbK5exlZInADd/F6b8DRzDGTiPA5W9xoDKF+E5IxdJGXJtoIvfoIpeK5bAmUVMySKu8DW24BW2
+ 4CU2H7ns4eKHF4qQ/RxeKEL2MyIIeT2fEbOekhDoF/BAeTYQ/5SUPk/InCenz5OTHxOS5wipQPwTaupj
+ WsocLekRNWGGnjBNj38AYsRNMqNGqQBJBAQFg8AMKbiPFNJHDgSvBN/sIvh3433a0d7tKJ92lHebvFer
+ PIDu2Yxyb5T3aEJ5NiOsArfuDXi3OpxrDcatGuNaiXatxLhUYO7XEl0r8fty+2zDOvFedRjPBuTR7o04
+ gNu3mejdDJTjfFqJXs14j0bwbzByrGczxrcd69eJCK6zwB5AHBFcgkG9YNvE0CEksAkeIIUOUCQihw3C
+ sydFjVKiEb4RgYXHjpMkfJMSp8gJk8SkaQCdnDBFiJvAA+iJj0iJDwlJswA6Lv4BBmw7aYaQAog/JKbM
+ EJIf4lMf4tJmcRlA8xw+bRabPodD9BhBGcjOWgC+4UVHXmvAOusp4tnAetZTbPYzfM5zct4rSu5LIvCN
+ OPQrQv4rIggx71fg1rh8+KO+hr8uYtIFr/AFL8G5cUUv0EUv0TAWvkAVvgRfxJW9QRAHDiQGKRkXJfQs
+ 4irf4Kvf4muWCDXLWERL+JplXN0ysQZgfUMEVb0hVb2lggDxulVG7Qq9eplWtUSpekupfEsG0CVCWN8T
+ UF61RK5ZIdWsEiUiwFiLiFS7BifhB+FrVgjVKzjguwr4BsqXsNUr+KolXOVbOAln9gQ3kbv2BPdKcEeu
+ h/I3mKoVXNUqvmIZW74Mro8qhysEfq+3WPD7olc45Ap/RYALO/8FIQ95iyPmviAVvKSC8p6TEWsHE4FX
+ Hv4EwPcCUfLmCXCTUh6Tk+dISWDqjyXHs5SkR5SEGQrYeTwCOlDOiB5jRo7QwgaBFiowE9JPCewmBnaT
+ A7pIvu0QLODAXr1a0J4t4OLA9ycjd29E3a8H1sGaEZt2q4cwBO9Wi3OrxrtVEO6V4p2LsbcL0a4VRJdy
+ 4r78AbuIbqJPA9a3Ge/djJO4OMQnYOQYwBoOfJCIBX4S8vMgPgHzDgLP7gHbxgf3AeIgfEg/IWyQiNj2
+ MGBNBsEb0J4kFk6OmaDGTlBiwb8nwLaJ8ZOkxGmwZ0rSDDnxAbg1OQk8exoOgGN4myOkPSalPZa83z3E
+ AtNpc3h4KwSlPsKlPsSmPpLADazP4jLnsJmPsZlPEGXN47Ln8dkL8E6KOE32U0LuM0Ie6Dkh5xkW3nbz
+ XkCwQSl4SUZ8+jWxAFCGkGORWLRIKgL/XgQLlwQhb/DFb/GlICRUwJYgAm9Dlb0GoUHli+CaYNVgkMAN
+ kISrAG7eYqvfSsYlXO0yoW4FX7eCrl1B1S6japYxcLN+lVC7BALiidUS1S6T61aptSuUmmVyzTIJVP2W
+ WP2WUA0O/RZfvYSvAoKXgWMQPBhfu0aoXSPWrQPfxD0B5bXrJDhTBwcr+Opl4BsHrMNYs4pHWF/GIZcB
+ IlzNiuTCQ87gqiWgS94K4A0Ewb0KuSDhJlwe+Oo3+MpFQpXkkoN3p+KX2OKXuJIX+JIXhKKXpMKX1MKX
+ tKKXjOJXrKKXrLyn1KwnpOwnxJwFcuY8CQwI/nZpc3t/RErqLC31ETXlERxQkKDlES3hIT1umh47SYsb
+ Z8SN0aNH6JEjjPAhKvAd0gdRAFBO9u8AL4eR7NuGBMwQSniB8wKTTWjAGuRWh3apRrnWIvG2cxXqXhXa
+ pRLjVkW4X0lwLcPfLcY7F+Ju56Nv5CneKcLcLcLvKxiyjeol+DVifMG/94ITCMTbEP8GAdlw81P83YUP
+ 6AIXxwHZiPpxoQP40AFC2BAR+IZoBBQxQoweB8+mIuY9ivh39DhQToqdBKAhBCclTBERsqdJqchvToY4
+ ZM+wkx9CkE1InSWmzhIgDoGABCIQiEPS5zCIVQPKEs/IeAKGAc5ByF4g5s6Tc+fhxSVkz2OzFzCAct5T
+ XC4Ct8RvnuOB8oIX5MKXYDxwgC98AX8wYjFExq/JJa+JEEMj8S6Eqm/wZcD0G0LJW4mQm7jyJVz5Mhbw
+ rUBiAAzic0hIgKl8g6l+C0JwAar+QAogQ0CUMFS7BP6Na1jFNayj69dQ9WvoulVs/Rq+YY0Iql8FkepW
+ ENWvkhvWKKC947pVcu0yqX55716wbUS1q3DBIKqHEb52jdSwToJxT7UrBDjZACdXCXAhwcNqJV8FAtYl
+ uMPJvasOB08DeSYwrsCliNsDHd4ogHUIruBaqlsh1rxFVPuWXPOWUg1vL29J8MoUvoIgHignFj8nFb2g
+ FL1mlLxhFb9i5z9n5D1nwFjwggljzgIta4EGQXnaHIiS8ZiW8YSRNktPfQis09Me0mFMesiIf8iMfcCM
+ mWDGjjJiRxjRw/SIIXpoPzUIpnPdJEiEBHRS/Tsofu1U/3aabxvFq5mIBM/NIIIkwJaEKLU4l2qwcIJL
+ Le5OJfZOOfZeGe5+BdmtjHi3AHcrFwu6k4+9U4C7mYe6mqW4r3DILroX79eA8mnCeDfvzS//j/IAyMN0
+ EiAhgwTivbjAXmxgLyaoDxPcjw0dxIcPw2ySGDFCiBwFvkkQk0SNEWPgYIIMN4H76AlyzCQpbooUP00G
+ C0fi7BkiePZeqA1Yg3nDJFLCNzF1Dt7siMj73Rzu92gbmwFWPf9JWQtYCAFznoE9IzTnv6DkQYD4FJ/z
+ FKZKGAgw8p7j8yA4gXvh7RX4RsJrECH/Ba7wBRbmiGUwHUREKH0N0zjEkmGWVraIhvfuqhVC1Rqxco0I
+ iAPflcu4yhVkBBqqIR5YkTC9jK0FLUmEAI0YZO0qrm4N3BovQZkAONav4OpXsAA6IF6/pli3CiMcI/cC
+ c3A9wAhY71HeuA6gwzECOsL6CqkBoEe4J9aBea+RYES+5yqhYQ/o/xNyEx4GF0/jBtAP3xNXt4KgXLuG
+ q13/XXCdAOur8G6Aq13F1Kyia1ZAmOrlvfci8G8ChPu1qxAakashOgLQ3xBrl8hVSzCFoJQvUUqXyMib
+ 3hty8WsKUF4I3vGaVvKWWbTIArjzXzDznjH2lPuMmf2UlfGEnv6Ymj5Hz3zCyHjCTJtlpj1kpjwCMZJh
+ AjrDiHvAiJ6gR48zIodpgHj4IFBOgxkdBCoBncA3xb+DCnx7t1C8m6ieTRSPRtL9eoJbHZImAb5da3D3
+ qjDOFWjnCuzdCtzNMsz1YtTNYsytQrRzEe5eMf52Pv5mNv5mDgh3Ixt3LRt9KR0B3TaqBy9xdKwEdCwk
+ T8DCfTvAv5F5QCAyy8QH9eLAwoP70cH9qNBBdOggJnwYGzGKjxzFRY7hosZx0RP46EkCkiGZxEcjNyFz
+ QkLyJFP4eJhZQmQi8ey99IgkMYLfAxq0N3dE8iGI4CY2/QmkSjAZ85gsyI08xUmEBSERCIIycib3OQJ0
+ 7jNczjNMznN0/kts3gsITrCQEoEQvOA1Gf42EJAgs6hnqKLnMOVC3oglMzwcTL8k0zJU2Vv58jcKlcvo
+ qlV09Rq2Zg1cEMJcdDWcWcIA4ojeoqqR8ANVs6QI0Uj9CkYioBkBq34N07CObVhDnBLgbgSt4WFsWMPU
+ rQLlChC9wAMa1+E8Yrp7yDauI8bcuEZCDiQ2j9wEre7pE9O/P4wIX9u0ToARrpY9waW1d9C0RmzeBNbh
+ R8AzwTRuYOpXUXXwTrKBrV/H1K1h9qCvWcPUrMHviJIcYKtXkSAeYn2gHEy9bo1SAxEUaIlS85YMXi6Z
+ GVMrlully1TklVykFr2iQcRS+JKS/5Kc/4KW95Ke94KZ+4yV+5SV+5wNB9kLrMwn7IzHADct5SE1BTFy
+ ZspDVso0K3mGlfSQlTDDigMvn6RHjlIjhmlhQ7SQfmpILy24hwYu7ttG9muj+bZSvZop3ohoHvUUd0RU
+ 1xqCcwXmbiUIB+Z9sxh1owh1vRB9tQB1vRhztRB9OVfxSrbitRzU9Sz0jSzcrRzi9Sz8lXTM5TTU5Qz0
+ 5XTMvsJh29gBUmArHlLpvhCIQ0K9g4AkCiFQgbRON04Si+NC+nEhA5iQQcXQIcWwYVTEKDpiFBMFec1x
+ GBFFT2Bjp3CxU9iYSWzMBCbuASH+ASFuCpcwjUucgSkmLvkRZi8x8in3NwfHIAyMvyMO6SokPQIJPkme
+ BJ25gMp+is59DgTjc18g6S04Bklw38MaDy6OJL9eYPJewjxyTxB5kwoXScVvSUVIXg9b/AJV8hJdsYhk
+ P6reIuEvRNKVS6iqZUVQ5ZI8omWF6hXFmlVU7aoksF5ByK5Fgmx07ZJi7YoCUFu/gmpcQTetYprXME2r
+ 2EYIA1YQyiWQIZw1rmGa17EtG/iWDVzTOqZpHQ1qXMO2bOJbNolN6ySAEgR8N20galxHiEcE5+HeDVIz
+ CO5FHkluWqc0bZDh3qZ1YvMGoWWD0LwOWOOb1/BNq3g4aFpHxuY1uAvftIFp2kA3rqP34qWGdeQaq1tT
+ rF9HS0CXUA52voauWUeuZ8klDaAjoQuwXgkTg2UI/Wm1a/TqFZgZw1yZXvWWUblEL12kFL4kFr2kFL+k
+ Fz+nF72g578CxEGMvBec3GecnAU2KHuelfmYnfmYmzHHSXvETJ6hJ88wUmaAcnbyA07SNDdxmhf3gBMz
+ yYoeZ0YgU09aWD89pJce0EUP6KAD4j6tVJ8Wuk8Lw6Oe6tFA9Wpk3K+lu9XQXaupzuWEWyXY26U4GG8U
+ Ya4XYq4VYK7kKl7IVrxagLuci3bKVLicibqShbmSgbqagb6WibmUqngpReEiKE3BKUV+X/GIXfwQOagN
+ F9iG9+/AI5lvMHIkYwjhOFZi5PgQiMUHscEDqNAhhdBhhbBhBSA7cgwNY8wkIA4jNvYBpAKxcVOo+Ck0
+ KOEBVpLnxiXP4JIeYhNnUEkPFVNmMZL0H5LVTp1D/57hRvLcv+cBMVnPIOUHggNU9nP07xADx9g9gXlL
+ sMb+jvUffOMKIBH2GkYcZEsKJZnskje4kjeY0tcYyWQL0hcwBUSmepJZI6pqSbF6WaHqrXzlW/maFVTd
+ KgrxQuTNHQ7QDYgw9YiRy1cvy9SvKjSto5pXFFvXMO0buNZ1YBpMGtgCwjDNm0AzrmUT27aFb93Ete1p
+ C9+2CTcJbVvE1g1iyzqhZY2IaJ3cuiXRJqKWTRIIUAa1bpLaNkitG5SWDXLzOqV5A0RGvhAunnX4oYja
+ Nwjt64S2dXzbOg4ZN/Dtm4SWTXgOmJYtbDOCO0wMgHIFGBs20HXr2Dqw9k+CwAaZqsKkYi80ql2lAOhI
+ ngden1Vq1Qq1cpla/ZZW84ZZvcgof00tfkGWiFr6gl7ynFH0glkAE9BnzLyn7LynPFDOPCf7CSfrMRsQ
+ z5jjp8ywk6clLv6AlTjJTpzgJoxzY8e4MeO8mDFO9Cg7eoQVMcQM62cEddMDu1iBnayADpZvKxMQ92pk
+ ejYw3esYrtU0lyqqSxX9bjnjdin5egH2ah7qWgEWUT72Si72Ujb6QibKKQN1MQtzPhN9Hg7SFC+moi6n
+ oa+koy6lyjslyZxPlAVdSJU/nyyzr2jENm4QH9CCDmjHBiJzTcioECGpgqwt9WACesHFCaHDxJAhWIVC
+ h42gwsfAzhWjxlCRYygJ4ujoKVTsA0zcNDYGKH+gmPAAnTgNOUFcChKrwCIONvEhOvkROmUWlToH+oNv
+ dPo8Gll3mEfWbiRGjpXktveEzgGf/p3mPcT3yP6Dckkme08wW0IEee4iWKB5gytCEn/IsghMJSExXPoW
+ VQGh9gqEoZSqZTKoGtILMJtcgT85GolbVsDwMODiQHkdBLJwAKwvo+uWUaDaZfmaVan6NdnGdYWmVbmW
+ NVQbWPWqYhP4t8RHAfSWDTByRK1bgB2+YxPftU3o2CJ0bBKBSxiRg01S+8YntW0SgM52OLlNbNsiwE1E
+ W8jDQG2b5LYNSusmrWWT2roJB3AG37GB21PnJr5zU3L8x8lNuKLgp8PTQHBHnhJY+5oiEA8RVMM6vmEd
+ ZsaIGjdw9es4JOxBgiUygF6zCuE4JPgJFfDKrFArliiwblX5llb1hlHxmlb6iloMXv4KQnNK4XNq0TNa
+ ISD+jJO7wM1d4Oc9FeYtCHOe8EHZT3hg56kPuUnA9xQzaZKVOMGOH+PGjfDiRvjRw4LIIV54PzuslxnW
+ Sw/toYd2MwPbmf5tLL92tm8r27uJ5dXIcq9jutcy3aoZd8upd8oot0upN4to1wtIV/Nwl3PAwhHEr+Ti
+ LmRizqejHFMVz6bIO6YpOqQqOCTLOybJn0uUO58ofyEZKJc9lyB9Nk7aIUbqXKLs2XhpCF1s4oYIga2Y
+ gDbMJ9AhI46so2ID+zBB/VhYWQ0dIoQNE8JGcOEQkU9ARA5ejihmCowcRnTcNA5Aj55UiH+gAOYNcEsC
+ cXwyZAPnYJESghY0QvljRVDaExSQvUe5JETZAx0sHBZuYJESsXPEy19iQX8gvnewRzkCPbKqRyhBRIT1
+ xeKXsMpIhFxK6SIBMtxlr5GsdjkSgsOioGL5MrpiBV+5SqoEx1qmwvtyDdgYhKeQgFvFISO8j69BvgJJ
+ wNVCQLKOBxeEGAYicjB1IKZ2DUCXalyTbViVbVlTaN1EIdCvoVoRvP5PretYBMQtAqhrm9i5BSJJ2CV1
+ bZM7QVsgCjIisOK74GF7ktxEwN0EwwbBOwC1bYvWtklt26R0IBcAAnfnJlYyfhJ8IfJVG9iOLRw8k+Z1
+ 9B7ryLNCrB3TtAnEQwSFxPf/j5DYCea7tSBJgrIKEi/L5MoVsHZaxRK1DFh/Sy97Qy9ZpBW/pUAQWLhI
+ zn9FzX1BzQM9YwLiufOC3CfC3CeinMfCrFl+1iwva5aTMQuxODPxATNhihE/wYob48QMc2OGBDFD4qhB
+ cXi/MKKHF9bFCumgB4PamQEtTJ8mpk8zx7uJ49nA8mxg30coZ7pUMu+U0m4WUa7nk67mEq/mEq7mES5l
+ Y4H1i9mYCxmYcymKDklyoNMJMqeTZO0SZc4kyDgkyJyNlzkbJ+OISNohVto+WtY+WsYhVvZMtPS+omGb
+ eCgV6MQHdmBhoTUQmXdKcuT92BBAfBApIUAOgPURHDL7HIdJJzZ6Ah09CXxj46Yxv9s5OmpSIWFaMfkh
+ BviG1XhkQX4WUoRIljD1MQQtKED8/x90YH1PMIPMf02C5UkAHew8X5Lk3tOekYMgtQLZbmTZ8iXkCiWg
+ I4gjKgMh6+cgWLKR5M6WYfVbofSNfDlkCVeIVTDTWmXWrbBr37LqV1h1y3TIoMHaTfVbUu0SBVS/RKlb
+ JtcvExtWyY1rZJgRQijcDHHwJrZxU6ZpU6YZtCHXsqnQto1u2UQ1b6CQ4EQSn0hCFBx4+R7lEhG7NkGk
+ TqB8i9S9Te7eQg6Q4y1S7xZxTz1/aJPQs0XoRi4P+FpS+xa1Y4vWvgmigPfDBdC5iekGbWH31LOF7d3G
+ 92zhujfRnRuY9i2IlHDt2/B8cIiv7wnimQ0gHkL8T5JE/zDZJTesQDYTWW9CTH2NVAHRC2RaVmgVK7Ty
+ ZWrxG0rRIhnh+y05Z5GQ84qY85qS84qWAxPQBXb+nFLBnFLeQ3HujChnRpg1zc+a5mbNcDOmOckPICLn
+ Jk5y4sbY4OVRA9zIfkFkn1J4ryi8RxDeww/tZAe10YJa6UEtTP9mllcd06eR59XIvV/DvF/DcqlkOJfR
+ 7pTQbhSQr+QQL2cTLsGcModwOQcHUYpTOupcqoJjsvzZZHn7BDn7BPnT8bK2CTK2cdK2sVKn46TsY6XO
+ REudiTxmF3HMJvyYbZiUXYTs6Sh52wjZfYUjVnEj2BAEcUxAD9YfwpUeTFAvNqgPEizYkAEcpBGhKCV0
+ EBc6hGRaosYJUZNg6sA6zDhxSGg+BeE41J9g4qdQiTMQnaOTZrAgSeUJHlk4gOVfZHEeyaWkPUZL0imS
+ ueZTcHEwdWQEIwc7z4MVylewRI/MPoteE4tfwzoOTCgheQJL8TigHPiG4BsJwSFd+BJX+pJYArHjS2r5
+ a1LlK1wlrGYjC+8I4rWQD1km1L4hVy9S616zml4K2p6Lu1+odS5odcxpdsxqtk+rtU2pto4rt4wptU0o
+ tY+Lu8ZEnQ9E3XMqPfOqfaCnot5XvK4lZhuE1JuYtm1U67Z867ZM67Zsx65i+za2cxt8mgLO3QWOu0Vs
+ g9AZiNwm7glCl27QFhEZt/F7Y88OAdS7S+jfJQzsEPq3CX2fROzbJvbsEHt2ST3bFFD3Nq1ri9aDjHBt
+ wPsDrnsbBw/uBW3he7eRxw/skvp34GrBd2/CvciPg+8AY9s6FiYSrWt4ZGIAQiJ4eItAZgItm5TmdTLM
+ dBvXKPWwVgWzz1UK+HoVsrRErl6lA+UlS5RiJJkIaURy/htqLrjPC1LeAqPwibB4RrVsUqdyxKhi2LB0
+ WL94SLdoSLdgULtoWLtoSCtnUDN1QD21XyOlTzWpWzmhWymmSxTZJYroVgrtEYaAuoWB7Vz/FqZ3I9W3
+ kerXzPauY3nV89xreeDi9yoYt4qpEKhcyyNfziZdSCc6pRHPp+LPpWIdU9AOyQpnkxXsE+XOJMrZJyqe
+ SVCwjZW1i5a2jZGxjZK2jjhuHX7MJuKoTcQx2/CjdqFHbEOO2IBCj9lGSJ0KObqvaPRU7DAmpAsd2IOB
+ cCWgF+3fgwroQQX2ooL7P+XLJSlzKLiBZCIe8oaRE0iyJWYSB6mVOMgeTuEkoAPuGBDgvsf6XvQCC0Bp
+ c8g62e95Q2y6JCgHC98LxyWTTrBwJGiRVJsgNSeQ+QbDBhWCkOBbsmaJ1JkggTgsXkKpUxnkwl/B0g+9
+ +BWt7DVBspQDGXHEuSEfXL9EbX7Nbnkuan6i2jKt0T6m09Gv09mp096k21yr1Vip2VSq2Vyi1VSk2VSg
+ 3lKk0Vyk3lKo1lyq0lGv1d2s292s1duu0T+k1jut1LXA71pkdq/SumAKuKHQtiXXtgMjqmOH1L1D3iOs
+ e5uEOPE2oXOX2P2OhGiX2LtLAiH4ItpDHE4iGkREGtwhDe2QJAfk/h1y3w4ZAR1GhHUqqHcHRrLk+8CX
+ 4/t3gGx4NyDsHYAAd7jZs0f5Flw2yM0uiKCQOSsEPJT2LRKE/ogkE1+I+CGx07SOvGXVr8BCFRVWqWrW
+ kFR6JRThLNHLlhglb+nFizTIrhS+YBS95BY85xbPC0oeqJYN6ZV3m1S3Wtc3nKmrt6tpsK2st65oOFVW
+ b1HRYFnRaFXaaFnYaFXYaJnfYJpbb5TZcCK1SSe+WTO6WS28RSW0WTm4SSmgQeTfyPOuZ3jWUj3rYd7J
+ 8gDKKzh3Shg3i6jX8iBQIV3OJl/KpDilURyTiWeTcA6JWPsE9Ol48G95gNs2VsYuVt4mWu5UpLRNJFAu
+ axclax0uZRV61DL4qFXIUZuwY3ZhQPlh65Ajp2AMO2wZdHhf6aRt/CguqBMqtFCAOEI5eHkfgK64tzC0
+ Z+oAeuQoIWqMEIWELjigHBLkUHGFzEcnINmCiZv85OWJ04id71H+/w06ZA+hQAUqUjAZkgSiJBxHJqAg
+ AB0pCXxFKFgEUwfzxha9wBU9xxUgaz0QjuP3qv9KFpEVTajmQwr63kI4DssZUAVKK4HpFCwEwnLgMrV2
+ mdv0RqnlmWrbjHrroHZLm25DlV5DoV595onaOO3KYLWKAOVKf9Uqf40aP81qH41qX80aP40qP80qX60K
+ f/WqUPW6CM3GKI3mePXWLI2Ocq3OFs2eMZWheZXhN6LeVXonEiEotmzKtW0rdm5jwGjBZft2CH27hN4d
+ fA8Q+Y6IaBfgllC7uycSMiJniD1gxtvkwW3y0A55eIcytEMd3KHAmf5tYJ0kEaVvG0Tu3Sb1wsldOEPs
+ 3SEM7ML1gMD9ifItxNcRuBGB00tA38T3bkA8g0MCpy2I7yltyFwW3nBILeskSTIHyV02rhDrl/B1S8ga
+ Vs0KEVZAyxappW8YpW9YJYus4kVWwQte0TOlsqdaZY9OVI4bV3WbVdVZ15Sebci71Jp1rSXzSmv21eac
+ K825VxrzLjfmXarPu1ib41SXd7Gx4FJd4fmKgjMlhacKSi2zy81Sy42SyvTjSvWiS3TCy7SCKlX9qoUe
+ lZJApQJiFdbtIsaNAtrVXMTIL2dTJF5OOp9KcUgknInHnIlH2cWCf8vZxcnZxMhYR0oD4lYRMlYR0tYS
+ 0AF3i5Cj5iFHLIIR1k+FHgW+rYIPWQUfsQw6YhF00Dzg4L7SqdPxIxCjQ50WGDkaKA/qBy9H9EfcIqmn
+ hRVQxNEjxwDu/wM9agITO4kFyuMmETvf0x9xC9j5nqNDpSEU+kB1G+Lr83uUw7IOVA5CHdwnL8+H+ATm
+ PW9IBYtIYSACN1JNBSO+5CWsZRLLFpEoHKabEuFhrb4USl6B8mVy6SqhbAUHqYPaRWbTS5X2af3GLt3a
+ crXqNNXycNUSH41SV62y2zolV7VKnVTLHFXKz6tXOmnVOOlUOGpVnNOucNKuvKBXdcm46rJh5RXd6qva
+ dTd06m9rN7rrNPrrNkVrtxVq9LfrjD/QHX2t0r/O6NrGtu3IdbyT7dqV793B9u/iB97hBnbhQKJ3+D7Q
+ LqBPAvUijAKvyNi3C9SS+3cBcdrQNnV4mzK8TYZxaIcCpj4A2v1/RQGbB8HJPiB+C2IViuQYgXvP2vfc
+ Hbk24IxECOgSdW/AHJcM6lgnIBlJmOCug0gta+RmCeh1klIFWKmFDHr5ErlkkVLyllayyCh6xSh8xS54
+ Ji55ol31yLRm2Kau9Uxj+fnmrGsdSfd6Yu/3Rd3vjbzfH+PeH+veH+fel3C/O96tPc6lI/Zud9y9rljn
+ joRbrYnXm1Iu1aU5VWaeK892LMs+U5Rlk5N9Ki3XKjbfKLhIw6tIcK+QdbuAeT2fcS2XfiWbeimTfDGD
+ DIifSwEjJ5xNJNnH4+1iUbYx8qci5WyiZa2jZKwipazCpS3CpD4p9LhF6HGzoCOmAYfMgemQo8C6ZAS+
+ D5sHHbYIPGIZeNjM7+C+4onTMUO4oA6MfxfGrxsFoYtk+VNRErpgkYIWSYz+B+jg6LD2idg51ItPIY4O
+ oMdPYiB02eP7/4fyPdAznpAlFYVAPNTKgoUD3EjBt6SKEBkhOv9/QCdCcILYNtD8e2oFWbpfJJa9+T/Q
+ IRwvg0qMt6TiN/iCRagoxNa+YrQ8FTePatSV6JREK+V7cAqu83LP8bJPi/Lt1AptNIpOaRRYKOWfFBSY
+ ikosVMos1QtNVfJNVQvM1YottcosT5Rbnai00a2y0ym306k4o13jpFt9Savqhmq1j0pzkkZfve7QhObI
+ a9HABrVnF931TrrnvSyQPbCLG3iHGdzFDEnGwXdYhPt3eLgAJNcAAdEuYEocfE9C9I488o4yvEsd3aGO
+ bJNHgfVd0hDQ/44Mdw2+ow69p0qIB6wRwZl+xOPhCz+Bvsf3H6BDpP7/A3rPhgT0DWLnOqLfk5vEtrXf
+ QYfKlk+gQ8oFybSUSF7M0jeUkpfU4mfcoseq5dP6VcOWdS32LeWXujJv9sa5Dkf6DYf6D4Z4DYd6j4SD
+ fIbDvQbCPHpD3XtC3fvC3QfC7w9EuPWHu/SEO/dEOXfH3umIv92RcLs94WZL3NX6hMvlKRezUu1i0439
+ 09Xc0nl3MjjXM5mXMhkX0qnnU0iOyXiHRNzZRIJDAvFMHNEuBmcbgzoVKW8eKmUZLmUZJmUOZMMYJmUW
+ chxkGnzsZNBR44BDpoFHzAKOmAUeNQ86ZhZ89GTQYZOAgyb+B0z8DpgFHDT1PbCvZNwueggb2ImsDfl3
+ IdF5UB8qpE8hqO9T6PL/gA41LeDokGGE5U8kdEEWQcHOIUZ/AHzD8hAC+h/ai1v2xvTHJKSubR5qxHFQ
+ N7tXBf475aQ8KPV8CaWzJMi67Jk6xOVg5ODf4OKS0pRPiMN2hDJIIMIyPpTXvYVlDqjeRs5AuWzNa1rL
+ glLLiHpFgSjPhZvhSEu1Iqeb0DONOZkmomxTlXQjcbohP8OYk2HIAmUZc7KN+ekGnBR9dqoBL91QkKUv
+ zj4hzDUSZxkrpxkppZkoZ1uoFp4Sl50WlV0Qld8T1McotVerDT1QH3krHtqk9W4r9u4o9O2Al0Pogh7a
+ lWgHNQi4S1jvf4fph4P3mMH3ONAe/Yh28UO7xJFd0sgOaXQHGUfekYbfkYfek4c+UP6gfOg9IL5n8Aju
+ QPb/G7oA9H9YO4COGD84PXj8JrZ3E9e7iZh9F0yOIYv/KZFPhiw+TKzBzptWSODojQjrUAIABS0wASUX
+ vyVCTVvZa2r5c1bFE+XKqRPVg2bVzbb1Jec6sm/1JroORniMhPgNBfv2h3oMhHoMhtwfDL4/EHy/J9Cl
+ K/BeZ6Bzd/C93tC7QHl/6L3+kHsDIa6DYfeHwu4Ph7sPR7r3h7l0h99ribxTEX0xK9YmMk7PK07pbjzv
+ SiLzfAr9fArVMYmMxCoJuNNxuNOxBJB1JPpUBMoqQl4C9BHT4KMSuI9Kbh4/GXTMJBAoP2Lod8jE/8jJ
+ gCMn/cHaj5oGHjUKOGzoe9DI54CRz35g3cRn/76icZuIAZR/O0xGocQcKMeEDGBDwdQBdziQ2PmeIHRB
+ YvQxyDBCygWRZD6KZF0kM9FPXr4H+qeIBQo155CCxPQ5qN6EqmUoU4atD7BFBQnNP3n5C0jQ0vYEleL5
+ rykFi5QiJDWO5MiLXkIZNJREwz6aPUcnSOoNoU4a1jjIVYvkmjdQxk2G2u7G1/z2ae3aCtVUd0rsSVy8
+ Lj5OkxijTo3VYMfpCaJPCCK0OZG6jHh9avwJSrwuOVGflmzIiD9Bi9GlxurS4/WYSTrMBC16uBrFW0S5
+ r0S7r0T3UaHG6DLyzAXFtqJ8e06RM782TrW3SWd63mhmXWtsi923BhNBiBzIfVu4gR3MMCI04usI6IA4
+ GjT4ATP0AS8B/Xd3f4cfekcYlmjkHXn0PWXkA23kAx2c+5OL74C7U8H74a1g8D1i85IEy/9NQPeg3wtg
+ EPrhMpBcCRC6wDMBQeaxewvy9JCYR5alICnUDjNRJEyHlIuklmaF2CCpcqlYphS/pRa+IcDSBGwxKXnG
+ LplVKh/Xq+owr6i2Kc85W5VwuT7yTlPQ3VZf13af+21+ri0Bd1oDbrf73en0d+7wu9Pqc7PZ52aT363W
+ wDttwbc7Q+72hbkOhroPhXiMhnmPh3hPhPpOhPuOhnoNhnj2BLk1Bd4oCbFPCjMOjFC/Hym+GstxTKKf
+ TaTaxxNPx+JPx+FtozE2UZhTEWiLUEXLMEWLMLmTQVImQUD5MdMQCd8Bx4wDjhkFHDX2P2LoewhAN/Q7
+ DDLyPWTse9jE/6iR31FDn0NGPgcNvQ8Y+R4w8gbQJ20ih1B+bQr+nYoB3ejgXmz4AD6sH9KLSOgCi/97
+ lP/fZBRAn8DC+v8e6JLJ6N5MFMm6/GHnn0BH8i17+gN0ZOcVgJ75FL23DSLnOfUP5b4gg/JekgtfEIue
+ E4pfwL4HZG8LbEUreYPMRKFktPgtDtY+YfZZukQqh1JSycYcWMZrfK5U26mWEkjzM5cNUJIJV8aGKpP9
+ RRRPIc1VTL0nIrsokf20mFF6jGgdWrg6KVqLGqfHjNVhRGjSwjXoUZqMWB1ahBbtDht9Gi/vwKSd57Ev
+ sUjeYmq6kSjfQpRnxc93UipxV69O0Gip0xyZ059c1R5aF3RuQm6EhoTX27iRHezwDqp/BzUAAcwnCwcv
+ Jwx9gKAFyQZK7JkED4asy9B70sgudWSXNvIOEKcNvWMMf2APvGMMbFGG39FGP9CHweDhYe9IoEHw7O3/
+ Yx2YBkf/HX1JukZCOTymbwffu4Xr2sB0bGLaN7HtSKYfybq0IJQTm5FKGyiHJELuFWp3q1cIZcvkwjfk
+ 3EV8DpK0ZZU+Vi8Y1c9rMM1Jt0gLs0r1dshwuZxz51rWtUuZV51yblzMu32pwPlSyd3LFc5Xq+9eq3W5
+ Xn3vWo3LjWq3W/Wedxp9bjf7OncF3e8L9ewP8RwJ952I9J+KDJyICRiJ8B0O8e73d2/3vl3j75QTYhUd
+ ru8drnktimcfTz0TTzkdS7SNxgHl1pEoq3BEFqEoixAFs2AZ0yAp02CIVaSAcmP/Y0Z+xwx9jxj4HzX0
+ O3rC+yAcG/oeNfA5ou992NDnsLHPESNvyehzWN/zgIH3fgOvH/YVTVgD6P7tCn5dKP8uAB0X3o8PR2rN
+ gfK9Wlxi+AgUmpMg6yIRODom+pOpwwEmdgoJ0EHxD9AJ0yBMImRdJNNQSR4dAT39MZTkU/ccPROqbRFH
+ h/kolB9SQDnPqDnP6DDC2hso/xU4OqX4BQnWPvfyiUA5sF70Gtb2sYWLGGRf4yK2aIkIb7iwzFG2SK54
+ yayaEeUWcYMuK7qqH/USyAaIsF48/F024RwRZY2TtyUpOtCxzmJ6sAY7UosTqkoPVaJGqTKi1VnhyoxQ
+ JVaEGidSix6oznAio3WlpI0J1DN8ZUcm8w6bGqPFzzTiZZ3k59qpFtzQyvFQTguhxsdLV7bTRpY0+zY4
+ PZv0vi0KJMWHd3HDu+gBRBjJ3BQsHIAmD3+gSsJrEHg2BNzgwSQIUUY+MAZ3GcPv2EPvuEPvhaP/VB58
+ LxjYZgy/h/MQw8BjSMMfIKohDkJW5/f04h7fiKNDmmULMfU90GHW27ODgyWkLkB8A90OuX9J7Q1SabOF
+ FIRBWSXUh4GdS6qFkYL18hVcMewTB9CRpToIzcVFDwySG00i441DnA28HPU8rU/6mFv7m9r4nbT0MTP1
+ tjTxszYNs7OMOWObaH865cyZdHv7DAeHbKfzeVcul9y6UX77RvmdG/Xud5u8Xdp83Xohmo/wHY8KGIsL
+ HIzxHwjzAdA7vG41+F4uDjqdEG7qG6p9JYx3JppsG0O0icKfisRYRYCFy5uHyFuEKsB4MlD2ZJA0gG4S
+ cNwkQGLVCNYQrhzR8zmo531Q3/ewvvehPel5HTTwOmjkfcTA84i+5yGJDhh47dfzBNDHTkUPogPbMX7t
+ GF+I1LtxIT3YsD4slCvCTFTi6PjIYULUMDF6hBg1QgLFjMKOZgKiMXzsGC4OHH0KYhh07LRi3Aw6bgaW
+ S/GwHS55lpw0C7unSCmwZoRs39wLXWBfLfr3zZpQNQ6g7zk6DVjPfU6H4s+C14yC1zBSkCLE18RCSMIs
+ wvoormBxr2wLNnTCHl4srGggk6dl2DVMqnrKrehVSolm+lrLuyhJuQkVvUUEdzb+KhFtdPyI+rFjxnj8
+ GTrtCovmKqQGaHBC1FmBInKAkBSoRA5WpoUoMSJUWZEazEAV9jUq+cQRKZWDx4xRuNME3C06MVyVmaJH
+ TzdgZ1qJ0pxEMZfIkdeOR7v8kBFzfHhSY3ZLZ2Rd1LUMKzvEvg8QroCdK/bvKEJE3vMO1wvhygfSwAck
+ 0zIIgoDkHQ0gBoceekfs/0Dpf88a+6f62Dvttpfiuse8nhXVoV3R6C4LJqY97/A9PwHrlFHEy3Hd77CQ
+ yUFmtO/gy+G6IiMLq8giFL7nHZK77NqF5Sp8xza4OKZ1Cym/Qcq8NnHNG3hQ0wbUukC1OlKejmw8XSKW
+ LRGB8qK31ILXUHNLzXvKKJlTz+kyCEzUdrmh7Wypd+WExiUtzavq2jfUdG6oaV9V14Sbl7U1buhoOOtq
+ u+npeZw44amn7613ws/IMMjMLOyUVaSNTezp00ln7dOdHHOuOJXcvlrnfqfNz609yLMz3Ae47/R3bfa5
+ 3eh7o8rvfH6oTUS4gXOo8Hw4zTaSYBWJtY5AnQpDmYYonAyRMwcjDzxuFHTMEGJukP8RA7/D+n5HDIBs
+ 38MwnvA6qOuxX9fzgI77j3Cg53kAxhOeB/S9EOKRuzwO6CHjDzoeP+wrHjsVC6C3YfzasL5QBdCJCexE
+ BfegYYMFrB8hFV2DuPAhHLJaBLuHRsgxyL4hUgxsqoDNFiP4mFFcNBLGYGIeoGJmUDEPMXEzuNgZQsIj
+ ctIcJXEW2S8IG2PTnsA+QpiM7oEOK0TIOigSoyOxCuVT6IKAzsh/ycx/xUAKQV9T8l6R9jbkwmb7vYou
+ SXEiwnrha1zpKwri9EsQwROr5/llLUpxPhQPQ1kXgYybAO0lJLqziOfQ8io//sj68YAWCm1LZV6kM5x5
+ FG8VZoAqK0CJ6i0keArxfsrkQBVasBI1WJkapMJ25TLtFFEGR48ZHjvmgJHz4dPjNNgpuowcI262hSDx
+ NCP2HCbx0vGMWwfT7h8caFF9+Ex/5KX64Ipy9waz9z2x/z26fxfVt4OFzDeQ2gv5lg/kvvdInnEvdAHK
+ IWU+tEmE9HnvNmvsJ63JHZOSXrpb5N9u+f05t5Uwsq46scUb2KZ2vCe0Q8CzRR7foAxtk5Dvhpg6rKdK
+ QhSgHFwc1qd28d07+K5dYscOlIXh27axrRIB2U1QPLyG1McjdV0bSGlXzSpsK4GVY1jwJ8GbZOFbqNqn
+ FYC5vGAUzPPyxtVii1WdXTgXLYWXdbWdNDQcVVXPqaheUNG4oKxxXqzmqKLmqKbqqKJ0TlnpgpLKJSXl
+ K8qqV5RUrquo3VRTv6mheUtT+66OrtsJfS9DAz8To2BLszh728xL5/NvXyt3d27wvNfo7dzg69zgc7vB
+ 91pFyPmkSAuPcNULoVSrUIx5mOKpcNSpEMWTQXJGQTInA46Z+B82CDx6IuCofgBEKQD6kRM+R/W8D+t5
+ H9L1PKjneUjHfb+m6w/abgA64L4fpAfnvQ7pehzUcYczgP4BPS/kAthXNmadMIgJgdLFTmSnHIAe1AlZ
+ F4jRoagLSnMRR4c9RNCXAvYTRUgaEsBN5Aw4/SA2YgTqdSFkR0VNKkZOKUZNo6OhugtqYKAGfZaUOEtM
+ miMkPSakwJ78T6DjJfVbku33yDZyUs5zAF3COoQu4Ogv6DArzX9Jhc2dEKwj3SYQ7bEOVS571S/I5uWS
+ l0RItxcuomEjY9UjXnGNMOouyVVN6g7l2F2mgicPf59DtMfIKu3/nvb9d+Ljxy0I5EsMmiuH5MkHkX3E
+ FC8x0UOI9xTgvYUkPyHRX0z0V6Z6iRl3ubSrDNIVCsaNRYxX5WVo8TP0OHnG/BwLXpodI+8qvcaNXn+f
+ UOAsleEtNTZ4cv71mdEXJ4bXVPrWaX1beIhhBnepfbv03neUXpgpvqeCkPQ5ZAl3KbAAhETkEJ9sC6d2
+ DaY3bLLKKV7e/7h34yuXy1/FRR0eeqzyYE1teIvb9Z7W+YHav0UdWacNb9KRVdJdYB0H601/qAtBHN/5
+ Dg+UQ6ELUsu1CRWUuNZtKNEhNG1AuIJs2kC2q6592ksKTQRgeaj8DYCObJaF7UKwiwI2B+U/FmX0qgQl
+ CK5doF8w5F1S13RU07BX0zitom6vrO4oVndUUnNUVnNUVXNQVT2rrOIoVj4nVDrLE5/li51EKhfEqheU
+ 1C4qa1xS0bisqn5VDaR6XUPdWUfLw8gg2MYq4eK5gtvXK1xvV7k713rerve+WRl0OSPawS9K9yKAHoIx
+ hXAlWNYyWM44SE4/UBos3AgB/diJgOMQjgPlBhCR+xzT8zqi53lY1+OwjvtBLbcDWm77YdS+f0DT9UcQ
+ HOh6AOh/6LCE+0MAum3iEC60AxfcRQiGfhXduOBudCgSuuCDYL8FUomOA8rD4DFQ7oKUeUGBF3IGEeL0
+ 2PBRTNgolO8qhk+iIh9goqYRRU+j4x7i4qBGdw6b/ASfOg/dVJCd4RCjI50nJKxL2oPA/nxi5jNSJnQF
+ eUbOBtzhRX8J6ZdPAtx/Zx3KXSC/LglmECEpyIKXEMagSl+Qqh/wC4v4oZdwLjyp25jjt8iyrmzUPRbm
+ AgVlgpLWkD2mryh/lkp1ZjN8uWQfNs6ViXJhodx4GC8RwUuA9xLg/MTEIDEpQEz0E5N9RBQfFVqQGjNC
+ jZWkxsrU4KbpsHONBXkW/FRLcr4TudWF3e3Kar5Hy7+LL4kTPRhxnJyzHn+lP/RWMLhKH9hk9G9x+3cE
+ fTucnm1m9xazd4fds8Pq3mb27LB7d9kDO9zhTeHouu7kW+u6Nl3vu4cCrxxKuSWdfv1YTRRh5aXN8xXj
+ kRVx7zte93tG3zZtYAOuH0b3Dq1jB9e+hYWl2c4tPFJusA0jrn0H375LQLQjAX0L1wT7PCAo3yQ1bpIb
+ Nsj1kj2mdetEmHpWLkM5LkziySVvYIUIiuHIhVCW+IyeNc/OnlFOalLzCuBfOcW4rC26qKJ1RknTWlXT
+ Wk3LRkXTXlnTUVXzvLL6WWVVexVVB2UVeyVlB5HSab6SPU/sKFJ1UtJwUtZ0UtW6qKbtpKZ5QU3zvIrq
+ eWXl80riCypK17S1PMxNE5zO5ty8WuRys9Ltdp3HrUq/K1lhjn5huk6BJIsglGmwnFmgtFmgjEGQzIlA
+ KcOA40b+xwwDpPR9j+v7HAMv1/c+putxRPv+IZ37APoRbbdDmi4A+kFN1wPaMEqO4QAZ7x+CA8kjD2m7
+ H9S5Dyujo7ZJQ/iwdmxwBy6oC4QJ7saE9GBC+5BN0AA6TEmDB6AWAI3MTaG6CxFi82GDOKAfWA8bwoQO
+ o8KB9UnMH6DHzKBjH6JjZxQToEZ3/g/Q91iHcheo6PpUtAhJmIynRETQGwRYf0HJfknNeQmFcrTcV2Dt
+ e6Ajo2TrPlJptKcCCeiFr1EVL8j106LCfEHIeZwbV9YFJ3eTLHWLIXOHIXeDhb7IwjnQcedpxLtsuheb
+ GsQlBnAJHmwMXAn3eWgfEc5XhPMRYf3F+EABIURIChOTQ1TJIRrUcC1GtCYjXo2eoslKPcHNNORlmXET
+ zQiptpiqS5SuO4JeN7UaN+UQJ2xmmPDtK9epecux51rjb1WHl5X7VtUGN3X61jV619RBPevqvZvq3Rsq
+ XesQ4ah0rygNLWk/XD9T06rjdv2Ar8PB7Kvo5nvEfndKrz/+bZ/J7tr50Zeavevi7m1O9xa9CyoZdyit
+ u5Q2KE7cxkMiBSiHcBwqFsHFwbz3LLxlG9e0hWncxDTAjqdNAmwkrYeK83UoZZH0yVghVq6QkLh8kVj8
+ BkrlKAXPSYXPiQXPqdkL9Iw5XtqoalSxuus9wWVj7hU1NUeRpjlHyYCrZChSM1PSsFbSsFfWcBSrAtxn
+ xOIzIkSnhcLTArG9UPmsUMVRpHZeSd1RWf2cioajiuZZFQ0HseoZoZIdl2vL5doJBZe01f0sTePOn8m8
+ eakY0jX3b1T5XM4MsPf21z7rQzD1ByOXMg04bhoopR94XC8IAd3Q75iB7/ET3uDiR3U9j+p5HAV2tVwP
+ /iGNe/vV7/4II5yBEdAHSe6FUXLgcgi+BK6BT6CHtEHEggnuwgZ3oUNhMgpJxj5cGDSxGEBidITyfgyQ
+ HQ55RqSSUZJZH8BDIjIc0jII8RjYXxc+jomYQkU9gOgFoTxmWiFuRjHpMZg6JhnZCQqUQ6MVctZTABrp
+ GQQLRrA4ivQPQvY7Qx8cpBVOLggC9+eU3OdQ/UzLgx3QLxDQC16BIJIBxCl7Qvb2w+701+iql5SGaXFe
+ DjfQAePKlbtHVLxBlb7FPH6XLX2XLX+HjbnFxt9h4iFk92MR/JkYbw7Wkw8ujvfm47zYaD8Ed4jp0f4C
+ YpCAEiqihqlQwzQYYZqMCC1GjBYzUYcLGcYsY1G6KTfekhxjhco5Q6i+yK6+Iiq8phxzmRt8hVKcrNnf
+ bT49Zzn72vLBG4vJJeuRt9Y9LyxAA4tWnc+Mu1+ZDq5YDq5a9Lw1GVg2f7Bk3zVq6e5y/J7tj1lXCa13
+ qJNutNcB3Hl/2kQCe3PO6clb+8G3hn3r6l2bvJZtav07Yv0uoRmi8B0iCAlUdpANTZBOadnCN28C4p/U
+ sIWt38bXbZKgDYYEcXIVUogPQTm+dAl2pRBgp3Mh7I57TYXd5fkvSDlPyZmPaZmPhCn9moHpajcvCa7o
+ K19S0bJiK2sQWAIsXUzl6HCUTvKVrQXKAO5ZschBLDgjFJwW8O34fFs+HCvbC1UcBCoOItXTIhUboYqN
+ QNmKKz7FU7bmK1mxeafYXCse96yq0l0D3UBb86QrZwvvXK5yu1LlcynT387DR83eG2cWIA+gnww8ZhYk
+ rR8opRd43CAAKD+m74OArut5RMf9sK474uJ7KAO7GvcOqN/dr+b8I4yaLgD6AYAb7tW5f0Tn/jFdd9Bx
+ 5MDjqJbb4X3FwzYJULbVig5uxwR3YkI60eHdmIgebHgPLmKAGNGPjxzARQ7iIkADgD4IGzYANwmRg8TI
+ QZJkJCC4I3ulMZHjKGQfxgwGMjAxD+TiHyokz6GTZlHJyCY6KOqCdivI7BNJlkMJ6GvSXq3iXv+33w/g
+ GpC0zkJS7Ajl0LtCYuef4vU/QIfCxoKX6OJFTNUrSt2UIDOD7mUn7cyRvktWvMkAvmXvMaXcWLJubJQb
+ C+vGxHmwcL48oicbf4+NdRUQIUHuL6IF8ilBYkqAOtVHg+YP2RhNQZS2OEZbFK0jCtXkhmgyI7TZUZrM
+ BB12hqEg1ZQfd4oRboWLMkfFGCtEmWLDrWkhZ9ne9mS3s/LjnZfnJq90thvPzF6cenK1oEYnp1y7oFov
+ v1o7s1ytoF6ncciqbdK2esC4bdK6d8zey1Pxut3BpBv02jvsgdvUl16cD2HKSwGCkWDBu1nP5c2gJ5v3
+ prfO9a/rNW5wqnfINbuExm1S8zapZZvQukNELBy27W2TWrdITZvEhi0CqHGb0LBNqN8i1m4Qa9YJ1cD6
+ OgVAr1iFZQdk/UGSwoLKOdhIQcmBN88XFKQuA1pTzIhSuvV8E9SvnhNf0FE9I1DXpwkFGBpFjkCVJ4oI
+ TEO2yJIntuUL7UUggZ2AZ8vn2ggE1gLhaXBusfppoRrIiq9szBLpUXhaBLYOiW1EF5gxBBYsviVXcFqk
+ dFVD3cPUIPKcTeb1syXOTuXeFzL87O77qJ7xxZsC6MFSJ4OPWQTLGARK6QYc10eS5ccNfKUN/aT1vYDa
+ I7ruR2EEyhGa3Q5ruhzSuAd8A/Tg2YiFa7vBY46d8Dx+wlNK30vawFsGxhNex/U8j8KeUdt4SJkD6G2o
+ 4A7FsE50RDcmshsb3o2L6MWH92AjejERYOe94PRocHrE7BH6iVFA+QApauAT63AlhA3Djmk0bK6Le4CK
+ nZKPBdBn5JJmFGD7HOww2gMdci/AumQOiti5BG4csmnoxafNRHvHSFcWsPZn5L2mUL+D/sfcFAJ02MUI
+ 3Vowe6DXPuBn5tB9HWWdxVLONPlbNEVnurwrTcabqejHxnowwcLJfhrsAG2+v66Sv6F6iKlOjKl+uoVx
+ ka1lmZNd8bXTOTfO5N46V+p8qc7lRtPdm023rxY52sYaqYVrciPVGAlqtMwTvDRTQbQlK8iS4Gck76V1
+ zF1P5p6B4n1Lkrc9654t/lGX98KwT2IgLzlCnBijHuQnCPTkezhTPe5RAnw4Pl700DBecCgrIpqflaMT
+ GEC9fvZ4+A1Ozg1R2TlC/yX86/ucDwFqT+6wR4JO/Hsx95//rd/5X8mbnyNG1xwalpWrN+i1W8T6TVLD
+ FrkR9llvwUYKyBjim7fIsIEa6fSygUThtRv42g1czTpsmMJVruEr14lVG+SKVWLZMq7oDbrgFfRSxEJx
+ KKSzcl6RM16QUp4S06Cr1hwtY0qU1Kp7P1zN0VZor6VmLdTQpgu5OAZRnkCQxnBQ5BMMnjlXYMXl2CB8
+ 8234/FN8gZVQfEqsaiNWtxFp2Ai1rISahhwVDTJfhGFx5Wk8Oao6gWtAF5mxlC05yjZcZZizOp/Q9bc1
+ T7x4Ov+WY5H7+TT/Mx7+Wvb+ZOMAOaNgaVj4NAs6bhQoDWG6of9xI18pI39pY39ZA/B1r6P6XkDwMV2g
+ 3PUg6PcABvg+DOjDNQCxjYG3lKGPjKGPrJGvHAgOjP1glEFAj4PirWZUcKticJtieAc6qgsb3YWL7MaF
+ d2LCOlHh3ajQbsWwHlRYNzrsU1QjAb2fCFdCZC8+oo8QAXNWJIhXCBtRjBxXjJ5UjJ2Ui5uUjXsgkzAt
+ B7tFJfugJc0QoU0c0iyOiKwWfQIdyMbkS7S3DpoP0CMdWoh5zyCS2WvnCdG5JFx59X/oF72AanVorIOu
+ fEmufyTMLWYFXFFwVpNyZincpqLuUORdKXLedJQ3C1aOyGEGapkXrUpcLjYGunfFhgwmR0+lJCykpjyN
+ iZmPiXydn7bUVPy2veJVZf7r/Kx3ZWU/1dYspiWXOdiEKLGiVVnp6uxcfRGUvsRY8n1NSW4n5O5pSTnr
+ yV7Xk719Eu9hz/U8y+kuurc0mRR5T3zJ7Pg1W3RqiHnADVXPC7wQZ9WUQGN/Z8FFG+nbF7Aet2jBnsLb
+ FzDuTpTwC7wEG3KuqVynPXr2Km3hMqPfgfos5+ZvO52/fZz578fR3V8qHm24tb01rF8T1G3Sajcp9VuU
+ hi1S4xaxCeaa0DJgk9q4QYFAvG6TXLsB/k1AEIcc4hq2YhWPtKmBus5laMwEqxCwOxGV8wqd8wqTDdu4
+ XhLTn5MSnxKTF4jQnSJtTBTfqOMapH7aSminoXZKSVObJebjWQwUlY2mqZA4hkyBGYdvwWZZ8tiWPL6l
+ QGQuVDIXKVuK1ayUtKyVdK1EOid5WjosFRGBz1RgUWToNGmaGMvToYmNmCqmTJVTLJVzfJWbmtoe5saR
+ DtYZV+2z751N9bH3CtRzCKKeDFI0CZWGmi3zECmTUFnjUHmTIBnjAGkjkJ80Yu0+iGA+qu959AS4+/3D
+ MNGUCAlpQHANwJVg6CNt5Atwy5v4K5wMUASZBaFM/OX3lY7YJsAGiyb5kFb5sHbFqE5sfA8pvpsc00OM
+ 6MKGQyTTBR6PjurFRPfho/oQssP7CRDSIOojhIN6CRDShA4oBg/Kho7IQ/QSNQn7phXipuTip2STZuTT
+ 5hQy5tAZj/GZT4jZ86Qc0FMitNSC9izQwQL2WBQ8wxS+QJQP7VlgVyi0+US6tUCrLUnDreeQW0RCl73o
+ BWnnAmcgA4OU8mJKXmIrX1JqHvFyKhh+N2VvqB68TpW6TpW5Q5N1oyjcpyrcY2IDdZVr7t98XpK91Vq/
+ 29b4U1fbL+NDvz4Y/62raz0m4ekd13cxMR9bGz72df2UnfX89t0dD9+PmVn/io9ptrUIZZFjhMw0NX62
+ vlK2hUaCtbKPOeOGnuJFdamLasev6CpcNSW6OvCDb2rmR54dawhJ9DZxO8t1OcPxdlK5bycKvKDlfVYU
+ cEnZ/5L4mgXuojnG44ooxOWEq6PA11GQeFE525ZWZKLQYoXutEK1W8i3nmdudsR8fD/18ZcXv/z67J//
+ G3zzLql/0b5pRbN+Q9CwzqzfoNZDIgV8fZvauElr2qQ2bVIk2RVa3TpVwjqxcpVQvoovByNfIZctU5CC
+ ROj88ZaQDYi/xmQvYgH0nBekzOeUlAVyyhNyykNG6ohabI2hi6+Og4WKrZqqlVjdgK+sQeerEnmaVLEe
+ S9mYq2TGEVpxOJZsjgWPb8EXmgnEZkIlM6GqhUjDSknXQqB1kq91gq0uJApoaA5ZgUmVo4twHC2qQI/G
+ g3gGTP20UOWimpqL0YkQW/M4J5vk22eSPc74+J84H8I4FaxoHnrULOywefgxs1DZk8EKxsHyJiFykIo5
+ GShjEiAFK/+GvrD4fxxGA29w96Pg8RIdQ+iXIC6hHBLwcib+IHmg3DQQkjko0yD0vvJhm+R+TGizXGir
+ fOge6L3EhB5ydDcBHD2iCxPViwXKI7pQENIA69G9QLkE9D5cVB8hEny9jwTohw0ohgzKhQ3LIzn1CVT0
+ uELMBJi6JHSZVUybVcyYxWc9JmZDk755aCKHz0a6JaKhyVb+c1zRM2SbRcFzdN5zVB5si36GlrQrgi5F
+ cDEgoEP0skc5HMB5OAldFCV2DsJVvCRXz7Fza2n+zjLXVA5cIh6+TD5+kyrrQgVTV7hHw0SeUJsK9//Y
+ 1faxq/N9UupKcNj/Sss/tnf8lpn77NS5XopgVtPg57tuv/gGL546209gTRBZb7UN5vUNKtnMGBw6jk1J
+ UOEk6whTTVXjrFVcDMkO6tJnNKRtxUfOays4n+a5X1CN8TIvT7tZn+tSmnTN+6q68xneDSvWZWO61znN
+ aydp10zJbg788HsGd+y5QfcMEgJOB9464WnPD7Vj5tgzq+woJQbSBVoHu85S+9y0dkezP75/+PG/b3/9
+ beV/H+fe/7fy0frdjmXjhhWl+jVW3RpCM/h33QalFoEeKKc0SUCvX6PWrJOq1wiV0CsUYZ0EoJcuU0uR
+ bluUoiVyzms8KOsVIeslZLdomc/pqc/IafP09IeCzBG92LKT99z0HE4q2ygrWYpUTETKBhyxPl1syFQx
+ 5Kgac5VN2HxzFseSxTXnCMy5IjO+khlfxZSnasZXM+Wqm3HUzfgaBmxVZQqfQ+Sy8FwuhqOC5+mQ+fpU
+ 7kmmyJytZCNQOa+qfldfP8DaKvr86bgbpxPdzwQEG12O4NiFoa0ijllEH7WIOm4ZIWsRLm8WLmseLmsR
+ CrUAcuYhslDxchKSj8FypkGyxv6IzUuiGhkjfxkYIbw5GQAuLmcaqGAWhLi4RBjzYIxlGNYiBLevYsQ2
+ bQAX3qIQ1qYQ1o6K6EBHd2NjIXSR2LnEy7HRfVg4COuCYxy09YJ5aiQQ30+I7iNE9xKj+ylR/RCvY8MG
+ 5RHQR1FRY4rRY/Ix4wjoiQ8UUx8ppj1CZTzCZT0mZAPrj/HZjzHZj1HZT1C5C5jC57hiYB3xdXQeCAEd
+ GikiNP8Beu5zJEyXdFRE0EdAf06Ewi+kmhfabkELtWfMojZmiLvCDbVDl0nHLpGPXwHWiVL3SLKeFFQ4
+ h9Jrb/ufqMhf/IIeaxr3ELkvjaz+dfXOO4szs/LU0T8fHv/u2AKWvEjiPTqCGvvL/omvf5j+9vDg/mNV
+ R49nKcimsEhxquwEPUG8iTjCUnxDB2clOmKhfMz9nEqCp3Woi6nXdb1o71PRftZ+dw1crmoYqUvZm1LO
+ nqSYKEnfPqPkfkHL55rOVRv2ZRuWy2U150tqgW4nwz1M75/lwUQ2y4lXepaRbSCdpnmw3oE+FGS2Opr2
+ 67vJX/75+tf/rX387flvH3vW/x0zsnq6aVG1fpVTu0qvXafUbFCqNwBrcHEaeHzjJnUP9No1sgR0AsTl
+ Fauk8mUokSDDOj/sTYGlfqgMzXtNzX5FyXpBy3rBTn/BSn1By3jKzXqglt1jHJtlce+WnoOBsrVIbCkU
+ nxSKTbhiE7aSMVPZkCmGyagJi2fO5JgzuaYsoRlHyYIHlCubwAXAUTblqJixVU6ylQ3YYngfUKIJlKgi
+ FSJfiygwoAiN6XwTmtCMqWwrVD+vpnNTx8jD1DLEwS7ymm2Mm51/qPHVGJ59JN46WsYqTsoathHFKljH
+ yJ2KkbKEbRYRsGVOHip1AXeofkHKvEIVTYOgBgYhHsY/ZB6iaB6CsghGI2MIxioUZx1OBNlEEq3C8fsq
+ hqzT+rERLYrhCOgKYZ2KEd2oqG50ZBdMSdHRfZiYfkw0xC092OheHHRpjOohRPbgYwaI0PYofoAU10eO
+ 7aPEDJCiB3GRA4oRQ3JRo0C5Ysy4QvyEYvykfNKUYtpDDCjrES57Fpczh8+ZhQN0zhwq7wk6/ym24Cm2
+ 8Bmu8Dm+8Dk2H1ooIgG6pDUXwjRxD+u9cGVvVvopdIGOuC8haicWvkEXQ9fPl9SKfk5UIPam5sEr1GNX
+ KDI3qHIwK/Wko0Np2HisXA2ZNCtUeUEXTO6XH/jLocn90nNSqPnDcs+//uHt59+9/tPfn/3pry+/+Obl
+ l9+++urvb7785uXn30x/9W3b9/sL5Y+lsYlxGpx4fUGciTjwpOCSBuYk/7Ch6Og9J/Xc2Jup4ZfuXdK6
+ dFpw+azIzBCvrnyUgv9aT0ORTf5WmbXfQhdnpU+6eV5dR+mYuuDwGSuWrQX91iX1YHfjGHejpDtaiY7s
+ fEd2oS01zVAhxUihzd9061H+L9sjv/z86tf/rH383+uPH4d/+jXz4daVtrc6jeuChg1Wwxa9bptRu82q
+ 3WLWbTDrN+l1G1TE6ZE2pbDTGfY4k6rWoJ8HBTpYIKCvUgqXaIWwdWiRWfyGkQ+fCPKanvWSk/6Cm/qc
+ m/ZInNajlVxmEhJqcuustr222FogMOPxjbhcxMLZIjOm2IQuMGbwjRkcUwbLjAn2LDDliMz5yic5ImO4
+ GHhKJ3liM67YmCXQZ/G0mFx1pkCdIdaii09AgE4VnqSDBBZsJWsBrK3qXNYwdNY39bKxCrxoGeZi5Rds
+ eD2ady6GZBenaJ0gZ5uIsotH28LeuTgZ6xhp2BtqG6NoE614KgKEsgxDW4ZhrMLBp4F44B7qeOEkcnwq
+ AnsqAncqHJF1BB74tosi2UbB7g1kBNBPJfeiw5sVwlohTJcNbpMO65QN75IL75CP7EbF9gPo6KgeVHQP
+ Jr6PGNtHAEcH1mP68HH9hIQBUsIA4E4G6GMHcVEA+qBc1Ihi3Dg6YQKbALW7k4rJD1CpM5iMR9ish/ic
+ R7jcR8iY/QiTM4fOm8fmLWDy5jEFC3ug4wB0CNCh3ZwkNAfKIVABX5fE67+z/snRIZh5DcXrxLzXirBm
+ VP2SVj0siI8k3tY7dIV2+DpZ5hZN3oWp6MvAJjOIZVhU04FDo3/7YfZP3z/+6vv5r75//OU3j7746/yX
+ f1n57Ovdz75e//zL5c+/2Nj31drnf1r76uvVz79a2ff108//2v33bwql9qcwMHFqrBhtzh7odnxpDco/
+ bA0BX41b5zWvOapePCMy1EWfc1A2MaaQyd9gcX/W1MQQCN8I2Af1tbFGJ0hWpkwy/q+qIiljfbz5SfIF
+ e4H3be2cSPvqaMesW5p5F8U5pzmRJxQ8xQfybmn+d7nx40+Tv354+uvPbyBS//hxaOd/mQ+2r7Yt6TZt
+ CJu3eI077MZddsMOp26bU7/Frt9k1kJ0Dlv6V6n160A8dPVA+m9BcznYJ162QilZpRctM4tgM+hbdulb
+ eglUn7+GOgtu9oI4c049pV8rqkgrIFTH/eaJG5baDmpiax7XjMsx4nJM2dxTHJEdR+UMX81BrGHHV7Fh
+ C62R3AukGkVmPJEJh2/M5ZvwBSY8vgmXb8zmGjBZOky2NpuvBUlGprIBQ2xIE5owhKYMgTlbCMnHM0pa
+ TuonbpwwcTE3dT9r4n/H1C9I/06M8HIc1SEBY5eCPpNKsE8mOySRYKsRbPWHDdGwZ/R0LMomCoS1jsTa
+ ROGgztE6EgrWYfPRXkGvItSv20Yjd9lG4+2iiadjSGdiKTDaxRDt48n2cZR9lSPWKX2K4c1yIa1ywW0y
+ Qa3HgzukQtqPh7ZLR/UoxPYrxvShIrsVIroUYvvwsX3EiE4IabBREN70YRIHcImDxIRBUsIQKX4IGzWs
+ GDkgHzWkkDCOTZrEJk5gkqYwiVOo5AfojEeErIe4nBl83kNC7iw+G3Cfw+U+wQLlwHr+Aq7gKR6UD14O
+ O6ahx8sn0AlAOTTR3YN7T59idKQJDAjplFvyjNT4XFQ/qJYSyXAzkb7FOX6HInOLLO1MlfWnodOouHpF
+ hYHvfpz/6m9Ln/996ctvlj//29Jnf3rz+ddLX/xp+7Ovft735e5nX21+/uXO519vf/n16pdfAPebn339
+ 6vO/Df3t24qjBzMpigkqjBhNVoyRMMhCbME7JiT81VQH63iKb2lIUeEfNjEg2lrzHR01beyUeUIZedSf
+ lVRRLN5RJuugtjbO+pRYUwPP4xzXUscYnoBHck5bMS5a03yuqGT7W9WGnKl0O5lwiumtIXtX+Uium8F/
+ lxp/We/5ZWvq47v5X39+9M//dLx4HzOwdr5lSad5DUDnN+9wW3Y5Ddvsuk2gHAEdCWBWIXShIwHMOoJ7
+ PRLVMGpWadCqpWyFUbbCKV3hlS2zkHgddpS/ZJcsKBXM6KR26oXmarp6K107J75hrX3DRO+cuoodn3dK
+ KDATCKw4/NNM0XUl3QATu4SzN2JOX/I3POVpYO5ldsrT7NRdw5MXNXTOIqUvamdUVGyVxNZ8oQVHYMjk
+ 6jC4J1gifZbYgCHSp/MNGXwTJt+MLbDgia1FqvbKWpe1DW4aGzrbGrhfNvTx0b8fp3onhXcpneSYiT+X
+ TXXKZF1IZzul0s+l4hxToJELyiEJtkhjTsciO4/OwOaMWJxdLAZ22cGOUkQxqDNxuDPxcB4LB7CBwyGB
+ Cjs5QI6JNKc0hlMqA0C3SumTC2uSDm6WCWiWDmg+FtR6NLT9WHgngC77u+QBdCR6gQC9AxPegYrqQccN
+ oBMG0fEDmLgBXOwANnYIFTOsCGPsMCp+FJM4jk0YRydOoBMn0SnT2PSH+OxpYu5DUt5DUs4jAoCeDbjP
+ YbMfYwH3/Hl83jwODD73KQamp5I20IiL72H9/w/63ty0ADpfPiNXPOfUPRY3P9CpbdBO8mHfN5R34cu6
+ MuRvQRUAWdqPgYDeoCA/+v2Pz77668rnf1n7/M8A8da+r9Y//2rji6/fffb1T/v+tPvZnzY+//PGvj+v
+ f/7n1T99vf7VX1a//NvTL7/p+8u3VYcP5pPRaWqsRD1+pLHQx1Jor4c31UXbWDANdDCayjKaajIn9HBm
+ ZqxTNkqnz2pr6FLkMH9ncqV0YcVFJCsQyIqV0ATCfl1t2gldqqEe8ZyD2M6CdsYEd0ZfwcNRUOBrU+Bq
+ 6n+SfEP5mAPnh/g7urtPq9+/bPrPyuDHdw9//Wly50PD9HJAxxv75hW91jVR6yavdZvbvMNp2GJBGNO0
+ xWnaZjduMpvWGQ3A+jq1AShfgyYWIKCfAZ+oUb3KqFrjVqzyy9ZY0J+ocpFV/Uy1Ysogp9U4NFn3lrPo
+ jCXbTld0WV/3qp6Oo7KSLZ9jIxSc4otsGPxzFKGHyKDkvMtkcPqgV0yp/a2yc3f6A2JGwpOa3AOzLtxI
+ drySfuV26uWb0Q5Ofma2rgaWN3RNTitrm/PUTrKUDGl8AxpPH8IeltCULTzJEVgKlOyUNM6r617Q0b1i
+ rHvnjIGni5FPtK5nhurtXMblPMKFfJJTDu1yFvNKFuNSFhFaK17MxDql4c4l4/c2TSObSpPwjsk4x2Ss
+ ZNwT4VwKAbacOibBAflcChUZkylOqTTYjQqdM/ZVjlqk9MuGNh0PapIKaDoe0HQksPlwSNvRiC7pyG6Z
+ 8E4pUGS3bHinPEQvMb2EyE5IsWNi+tBx/YpxAyAUKGZAMXpIIWZIPm5QMRY0oAAHCSOoRIhhxhWTJtGp
+ M7jsaVLeDDn3ESXnESkbDP4RPmsOn/UE0i/4vMcEwD0Hpqfz6OwFNLSBzoauRpKIRdIT/f/L0fc+QAsW
+ jIpekMsXGHWzStX9asUVKumRvEAH3F1lqXssGVem7E2a1E1YMGKhUxm4OkX5wR9/fPz1X15/+ae3X3wJ
+ iG9+9tXaZ18uf/blBkL53zbB6b/45s3n37z98u9v//S3V1/97emf/j7z9x9av/2+6OD+XCImQ4WdoMsP
+ NuL62avdv6F79ZqGmSVVU0PG3IRsZ8szNqFo6eBO2ala22mctFTiCBWk5f/GYEsRiT+IRCgU+gcMZr+p
+ icDhtMalcxq25nR7S9ql0+zzluQrlpTQa5qJt/TvGeLPCg9bcr+PcTV5t9j+01LP+zfdPy/1/bTZu7JZ
+ Pv7aq3PRoXPVsH1d3L7Ba93iNG+xGjcBdHbTFrd5m928xWzaYALoiNapjev0xjUQo3GN2bTGbFxn1q5x
+ gPWydWYlHC+Jauf085vNIuMN7t1QtTVkGvHolnyVC1oGl7R0HZTEdgKOLdg5U2hH4l1E89wIqgWGFybv
+ RPVf9CvVP9d+5t5OUsWvxR1PgtKaLnv2uIa9Sq9Yya+fisxsuBdUeS+wwiMk+dr9O0Y21hw1YwrXmMoz
+ pPGMGEIjupIhQ2AKpQFQLCDWPi1SP62ieslEz+3GyYAIE98MTbci7t0K6o0K0rUSCrRcvFVEu1FIvJYP
+ /eigZRcJOr1czIBmL6RzqYTzaQSndPyFdDyMTum482k46JBxMYN0ARoewV1p5AvpSFsY0MUM2kWkRQwJ
+ 0oumib1SwQ1HA+qP+jccDWw6GtB0OLj5cFjnsfBuqZCOowA9uHtYh2xkFzqmBx/dDTE6JqpPMbZfIW5I
+ MW5QIW5AIWZQIWpQPnJANnpQIXpAIbJPJqpPFohPGEUnjCpCDJPygJA1Tc6ZoeQ+pGY/ImfPkrJmiZkA
+ OiRh5om5SB4GmzWHyXqCzgLQod5rHp31BAsfWYHE6OD0kHGH9v5P4UNaAHH43BwyfMBI+VN67SNhZac4
+ I4MVdp/gZiN7RXjoEvHALfLRe3Spmwzpm2x5Tx46kYMvx8h3Htw/8dc/z//5q+dffvnmM9BXL7/60/O/
+ /PXln/725otvXn357bO//vD6B6nXB6Qf//3H6b99//i43FMqvQuPz5I9nohVSBTSYrU54ebi0GsGrs76
+ TtfUDSzIxhBtX1C7cFHT6CRd34R+9aaFiblYU4dhbq0uh/qHlOyfFdF/JZMPMJnSp6w0zE2Vrl8+ee/G
+ yfO2MG0V3r6seuOc0NGMdNWUHHnzRJCTyjUjvI3KkfQwx1/+Nfuv3cnV561PJopePC5+vZz3YNF/4O3l
+ 3nXTjhVh5wavfYvdssFoBjtfZzVtgoBywJrZuEprXKM1roPgXmbzOlNykoJ0cVln1WxwKtc5NSvC2mfa
+ RV1G0ckGztdUzxnyjThUTTzNhC46p6YHoch5VRV7pJRFdIaldI4guCzNvnuME4nTLOBZ5tBNUjDa1SK7
+ 59ci1zwz+qzd8lTtWu1cd5JqfivpfRqY3XTBu88j7mVW7URSUcI5ZyeBriVFcBIBnWNAExhQlfWpIiOW
+ EGrFLDmq5gwxRO32mtq3zxr5+xoHJOr4FIk8ahl3q/G3K/F3yknOZeRbJcSbxaRbRdTreZSrudDeiH4l
+ h3olm3Ilm4Q0rMuBUXKQTbyaQ76eT72WS72aS7maQ72aQ5eIcT2PdaOAAWf2Fffpx7YdDKo7FgBqPAaU
+ BzYfCm45HNC2P6jjUFDH4aD2Y6EdMqEdcpBKj+0lQKQe3asg4Vgufkg+YVg+fkguFhpJDypEDsjBZBQU
+ PiAb2S8X0Y9wHz+GSX5ATHtIznxEzZ1j5s8yc2dpObPUnFlKNrQGmCNkPgZBYyNM2hPoVofKeAKmjs2B
+ SOYJvmAeOqGR8+cJhQu4oqeEwqdQcMcoekovnCeUL5Ab50R1nao5iZyw6xgXYxknrpQd+qgD6sAN0gE3
+ 2vHb9OPX2dJuQnS0kJRPxjTJSI8dP/ZSXv7FwaPP/vLDk28PL+BJL5XEzynMme+Pjv39x2cE6k9GVu/M
+ bGeFqoMs3vJp+397uj92csji0iLICnHKsIGaFWkpjr5tcvOKhrkt+6Qd395J+8pNk7NXdTWMKCIt/C03
+ B11DPp0j5+x6VkuPgcF/iyH+DYX/i72j5vXrZkyG9I0rloHeTrcuG9y6rO1yXcv1qsYVW85ZQ4L/VZ30
+ gNPJPqfi3E3bK/3/+5+Zd9sTa4t9M2O5C7PZm9vlz9YThpddepZt+lZU+9b5PZvMrnVaJ7RSWoV2eXSk
+ yxw03V1ntW0wkP5EiOCA3bLOal6lNq1B70Vc0xqrcUXUvKTW8vREVZ95fLKhxx21i6aCU0K+HpWmSiAa
+ cBkO2spOmmrnVJQdhKKzAuXzHJWLeMFNKfb9/ayg79lx+wVJ3/OSv+XmHFapp1i0sO0KUSeSj6sU08xm
+ zvgt3orvMr2TybWoM7/51D9jyjslxezyVaaGNVl4EqIXBt+AzjeiCA0oXCMm7yRXpM8Q6JE5JkyBvZqW
+ s8WJkLtGkZEnQ7N1/Mr57jUk+GQ5tzqSaw3NtZp+r4LiXEa5VUQCd4eGdbeKabcLqXcKabcKocsuBVo0
+ wmUA3o+omHq7hHobRuSA7lzKdC5l3ynh3C1jQ4+kfUU9+jGtBwOqjvjXgpcfDWg+FNhyKLj1cGD7Qf/2
+ gwHth4Pajga1HQ/rQEIXJNMySIgfRsUC3AMy8UOySaMKCcNyMUMyYOdAdlifdGifdDg4er8cKH4YnTRB
+ SJ4ipc1QsmcZBU84hU84+Y9ZEtYp2XMI6Olz8PktmIwniqlz8qmP5dOfyIOp5y9gC+ZxBfOE/AUi4F4w
+ jy9YgNkq1JSSixZo5U9p9fPsukF+dgbTx0nuls7hi9yDp7EHreWO2CsevU485sqQBdCv0Y85M+WC2fg0
+ OqmKRl3Q1//v5Ss7p07PctUeKult33H7X0Lyvzz859QMhxmizYs3Pmbmfyyp2I2KWfIL+KW48GNXy7uc
+ pEpboygxNVaNBh0Ewi1F/hc1HWzYBmbk05e1brjZ3HY/fcnV3Payrv4p0W1PJ0t7XRUdWmDk7Ys3TNR1
+ cWzBIRb/YFDohYsX9Gjkw8G+133uO9pZCK9f0Az0tIzyt/O+pX/3vIr7BbW0oDOVqbfaSrzmRtN/+e/4
+ Pz9Mba0OPX5Q9GQ6c3O94s1OzvR60MjG5ZFNw75VUe8Gqw/aMq5Re9bones0SYd1Sscmq2OL3grN1Deh
+ tzqzZZ2DaIMOe6KhsWjLsqBzSbsNGhJ1a6Vn6nncUr1ozrPRYJrwGHockqEy+bSR4KKZ+nldNQdl5dMC
+ 4Rm+2JGtfAEvuC3F8fqRFfotJ/4bfsrfeGl/4Wb9hZv7V37uXwVZf+Wn/ZWb+Z2oGm1cT7bMk9GJPihK
+ xxvUaJ4v0DjrT9e7hBHaEHimNL4hEyJ1vjGVb0SFGIZnxOLrUDlaJIYxU+Cooe1mpR99yyQ+2Dw6VT+8
+ TCWwnuHbSPRqIns00t0bmG610CidcqeMdKeMeK+Cerec5lxGvVvGuFfOdC6jQ9NdGPf6NkJ3UrgLRmg5
+ fa+C5lrFcaviulZyXKtB3H0lfUax7Uf9q4/61R72azjo37Q/sGl/cPOBoLZDfi0HA1uPAOWQignrkIvu
+ QcX1Y2CXRuKoYvyITOzg8YQRmaQxoFkmevB49LBs1KAsIB7WKx3eIx3ZKwuxTcooPm2SnDJBSp+kZD2g
+ 5j9iFs6xCsDUJQGMJHqBj72FShj59Dm5tFmZtDnpjHmZrCdyeQuKBQvoQknmseApCQR5mGxYMX2mWLRA
+ qpnn1o7y8goIAXekr2gevMA47ID/0UL676ZH/2ErdeQKVvY2TeYGODr1+G2SlC8VE0mnlGprrgT6f6yt
+ /a2yajc+dScp47f2ro8PZj52D36IzVj2CP5PfunHicmPc3Mfxyd+7ev5daT/p46Gx4mhBQ4no7V5sRqM
+ 6BOsEAvBNRO6yQm0ngnJ4doJt4AL93yd7vifveHtcMfvgn+s6xWXM2evmQTH3LnuYm5oQdeGOastPyPT
+ /cZ1E2MDTlKcp4eL/eVzuq7OpjFhTplJt6L9T4e4nrx3Tux5TS3ez7Imx/nJZNr/fhl+vz20s9L//FH5
+ k8mspZelWx+qXn5Im1y/N7FtPbih0b3O6tkk926Q+tZoPev0jg1a+wa1ewv6hyGtd1u3aK0brOY1AJ3d
+ tsFq3aQ3rzE73mh2z5+saddNSxb7OQsvm/OtVZkGXMIJMeaUCdH5lqrPfeO7Fw3PG2raKinZQaG5WOkM
+ R+yE598+yvb5jhX1DT/pr4LUPwvSvuJlfc4p2Mcu+oxb8Dkv/0te3he83K/5mV/z0r7iJP6ZE/+tMP6A
+ SshBoesR7lUFvh2eZ0rhGTKQMN2Ewjeh8owZXH06T4vE1ibQYXn1mqFx4BmL+GtmqX4WGSknU0q0ous4
+ Ya3UgHaqZzvNvYUGH31xv57iWk12raFKPgCDIfkMDBiZrlXQYJrhVoW04YVmvG5VDNcquIvmVk2DPuue
+ 9VzPBp5HLYxcz3revpIBk5i2Y/7VR/zqDvs27A9o+iGw8fvg5h+Dmg/CrDSo5Xhwi3Rwi0xIK0xM5WL7
+ UYnD6IQx2biR43HDx+KGjsYNHYuH4xHphAmFWCh0QYxcNrJHJqZXPmkAkzFOzpth5k4zciZp2VOU3AfU
+ nAeU3GmI1CnZj4hZyEcoolJn5dMfyWTOIcp6IpM9L4uMEtbz51EFsHT6lJj3lAIfWJz+VC5rQa58nlwz
+ zs8poYa6St02/OEa/9hlguxZhaMWx78zPvh388M/OKKO36TL3mHK3aEr3CXLeVDRARxqroXJfHzUf7rb
+ Pk4MfBzu+Tjc93Fu8n9Ppv4zPPBTRcVqatpifu5Cfc1CQ/2LhvqFipKH6SmdPm55DhZxhurQBSBBi5lg
+ xA024V7Uwaty9/OVjp2/aXTxjpWZg7a6GY+piedqUyydjFwCbwTFuwXG3LrkbGJgTrO04dxzs0hKdQ2P
+ vBUZ4ZKfG52RHlSQH5aT7VNU4NtUF1WQfi/K3/rGWbbTKaLrFVG4p9Fge8j//ju09qZ9823fq7maJ+PZ
+ zx7mbe/Urf4z/9GGz+TmuaENg951HrRl7N8kDGyQ+9eBdVrXJoBOhhbsEtDhswOYwHr7BqNzk9G2QW9d
+ EbTPG9R1mGXE6/hfF1w349qpsU8KyAZKGFsboneQOKfcKivf3tfd3MlM10ZVxU4ZEiPKpzliCF3uHeEG
+ /IMb+2dB0pf89C+FmV8K8j4XlH4uKvtMWPa5qPRzYclnwoLP+NmfcTM/52R9JUz9nJ/wOTv8TyzP79k3
+ ZLj2WL45GDmTawSgk3gwNz3J5BvS+bpkrh6RZSNSdbU6FXvRPv2aTa6ndVG8VUGhfka9OKaDGdRL9e6j
+ +nTT4MOMvJpI8KlGHo0gqnsD/X497X4dHT4Vw70WPvsFPgcG+YQM9zq6Rx1y7FEPIx0+FgZ6rvu28Hyb
+ eYEdAv82AYB+Mqb9OIDuX3/It/HHwOYfglu+C275Ibj1UAjk1EEt0mFtciFtshCpQ3YlYRSVMCaTMC6V
+ NCaVOAqUH00ck06eUoCFodhRCMpl4yDJ2C+fOIDNHqcWzLCLZ7mls/zSOV7RI2buFDV7kpzzgJzzkJQ9
+ S4DZZ/qcQuojmYyH0llA+Zxs9hOZ3HnZ7MfAulyuxNRBeQv43AXYVArbMtAF8+jyCWpBNT3MS97N7NhN
+ 0SFnltx1nMI5eTlLqUOGR/5mcvyv54iH7jDlnanyt4hy9+io+2yMt4gUbaxWcf38cLjvbEbEQnb005zY
+ ucL4yazIoUivHs+bTVCge/VMzrXz2dec8q9dyHFySLU2izPQCtcQRqrzYlTZ8er0WB16pAnPWZ+mQvmG
+ iP8zVyyroksxtlHH8eSPEg8cIRxUZMkpGwjCkn0iUj2uuViaWvPOXtTyDjqXkuWdlO7n6GRuYKxqdFLV
+ /ryRT+ClmLjbpcWBrQ1RiVGOV88ynWyJN84x7l7hD3aE//rv8fdrwz9vTL1727v4qOzJRObyYtHm+7wX
+ OyFjKxcGlo0GtsRDu9CXFDe0iR9cJ/Wtk3vWyd2b0HYdQIfG0ERoDN2+QemGXmKbjJ4Nbttrtao+g6RE
+ A59rGjdOCu01OFZqNCs93HlHim+USmGrQfPkqaIGm4AAswtWOrYaKnYqynZiZXum6DKG73qEF/QNN/Zr
+ QdLn/IwvhNlfifO+EJV8ISr7QglAL/tcDGPx56KiL0RwARR8Kcr9jJe5j534FTfoO+4dKZ4jTmBJExgz
+ eSZ0rgmJa0LlQDbdhAF1AXxDKu+0WM3dyirxyrnCO+dLvBzKo2wrCkxz6tVjOjjB/VT/EVrgAN2vleLT
+ TPRtJQPuno0kD+RD6ijuDfAJXmDb4Pd0ryamRwMNPtDLu5nu28L0bWX5trH9/k+coG5+UBd/X/GAWUyH
+ dEDtMb+6A951/who+geAHtr6Y2j70VBk5UgqpE0uvFMxpF0uuEMappuxo/Ipk/LpM6i0BwppU/KpU3Jp
+ Uwqp06iESYXYUZnYYbmEYVTiICZthJQ3ySp7JKiYFZU9FFQ+EVY94RfOMHKmKDkPSLkzpJw5AhQCZD6S
+ zZyVzXwknfVQKvuRVPacVO6cdM5j6ZwnsjkL8rlPFfLnFSG/nj9Pyn9KKlwgls/QSproMaEoV+vDd5Tk
+ nNkyd6hSV1DS9nIypjIHDBT/bMv55rrqobscqdsU6ZtEmbsMlAsH5SZAeSkRwnUEySc1Mmx0s+30888a
+ 5547mXnWOMVaO8FEJUZfGKrNCtVghWlyIrWFYWq8ICVmkJgeqgL9XtiRyowYZXK0KilSnx18SuyggxMy
+ f6TS99uf17vt4YjhyCowZGVpsnI0WVmS1C2vyzGpvm7e5x0v6V+/axkef7ewKv6Gi8P+49+gCDJEJkpV
+ n6usSzlpwb1yVTcz7XZ22lX3O6pXz1JtT8oEe5/YXGr477vRf21Nf/z3SyjtWpmvnhlKer2Qtb2TtfQu
+ fGLpyuCS6eCWMnQkHdnFjGxihtbx/esEpGGY5OMGoCMXfB4B8sEb68S+DebwOn/gjWrdiGZShobLNeWL
+ JqLTQLk61cGCfPceNSpDubTXuHX+RNu8XkmHaUCwsZOV2mlNpdMqamcEqueZSlcxvLuHWd5/YYR/zYn/
+ kyDxS17ql/zsLwWFXwhKvwTEBRVfiCo+E5WDvhQXfQHWzsvbx8nex0n6kh38D85dGcFZgtACCl0YvJN0
+ vilNYM4UQG7RkqdiDKUvDCFsMPWzsU65er7Q+UK5l1NNlGNVrlVurU5CtyBsiB48Rg0Zood0UQLbSUHt
+ JP9WENkPPtCr9dMnM/o007ybQFTfFqpfKw3k38aAT0QK7uKGdCMK7mIHdbLD+rmhvdx9hQMnozuPB9Qe
+ 8as/4NvwXVDrP0JavwdHD2k/Etp5PKhNOqhNLrhdIahdNgiSjP0y0cNyKZPojBlc2gN0+gNFYD1tShFA
+ jx+XixmViRlCQE8bI2ZP0AumuOWPxBUPxSVTvLIZbuVjXskjdt4DGoCe84iIVLw8ks96KAOIZz48mjlz
+ OOvh4ZzZI3lzR3OfHM+dl8p6IpU5L53/FIle8h9jCmbxZdP0qn5+djrd3+nYbbUDd9goFyb6DknqouIx
+ K7nDBqg/W4q+9rmCCr1CuKd29Br14A2y1E2SrDND3oUr58aV9+bhAoSUQBV6kCozWJ0drsOP0OWH6/BC
+ NdkBKjQ/JUKwEj5EiRCiTAlWpgRCDwxlSog6I0iDDmeQrIsKOVybGmGj5HNO44Kd0P6s6sXrhq7+54lC
+ +e+k/3wcf+h7mW+/OfpXC3ujqEQf/6Dr125aePg6ZRYEx6X6ssX4/VLfMkVkRYqMQJtK5B6/cM3gyvUT
+ erqyVuZYQ50jBpo/nFD7tqLozsf/Tf53d/S/7x799q/nH3+eXZ6vmR5IWlzI2drKXP8pemH73tSm7TCA
+ vk0a3cWObaGH17FDG7jBTTx0v4DO0V3IdmmkGR1MVYdXlYYXtdtHdXOztf3uKV+2FNrpsKx0iGetia5e
+ 9MQiXvWYVucL/c43wtYX4pIuo6AQw4unlOy1BA6w51+oeZGjehnLu3WMef87RsC3rPBvuWF/YUZ9zUz6
+ EzvzSw5E50Vf8Eu/FFR8KSz/QljylbDgS17WF+z0L1hpn7Pi/8QI+pFzR17gQBZYQgUYW2jGEkKtixVP
+ 2VasbivWtOFr2As07ugahp2xS710Lu/G+fL7F+rCnaoybApq9FN7VGJHODHj9KhhanQfLaKHEtZNDe0C
+ 0YI7qP5tEMHTAiUKaKUFwudndNCD2uEuRlgPO6qfG9HHj+jjRfbxIvrgGD5bhh81wN9X0G8c1XE0oA5m
+ ogcCW/aHdx0I7zwQ3PpjcPuhkM7jge1SAa2ygW3ygeDosH40CDQrJE9i06eJaZOY1AnFlEmFzBlM5iwu
+ cVIhekQ6alAGQpf0cVLOBLPwAb90WlQ+LSqb5JY+4JTP8Upm2QUPAXRi1gw25xE6d1Y+55FM9syRrIcH
+ sh7uz5r5IefRj7lzB/KfHsl7djRz/nDG/NFcBHRU0RNU+SyxapSTV8qKvI/2MD7szD98B9yagblNkHdC
+ yVig95txvrrrdKgkW60wUcPjlOwl7vcwGb1FlL9Nlr3HkoMIxxXZKkrxUaaBfIFmdUaoGogZog59i6jQ
+ BcBfieiLdLygBKhQA9WoAaoUP2Wijwo+QIkQrUyNU2dG6DJCzPlBl7TdbujdczMzPyM0tOEZ2SpRxHKK
+ tCNS+APHsQcNzdX8Am/5+lx1dz8bFnEzuyD46i1LWdR3f//hc3ncEXni4WPYb4Ta2KzCwMwcT3t7trmp
+ 4ilTBauTUvduCF4tlH787cE/t/r+uT3167+effz3439u9r9+VPRkInH5Tcr7/yav/tf3yQeHkU3loW3y
+ 2C52fBsztoEd3cQMb2MGdnDQ7rR7G4v0a98kDa7yR9/odz0wKi06EXtP19Va7cIJvt0J0vkzBK8AdmqF
+ cvWkSveiWteSoGOF2LHIL+02DA4xuGItdNTknFPSPC/Uu8BVuYDjXpNh3pfmRuG0Ugknoo6KQv7BiP2O
+ m/6jUtZ34uy/C7K+5ub9hZ//F0Hm15yMP7FT/8JJ/Asj8U/06L/R/Q9xbqB4p6lCS47YggMpc7EVX8Va
+ pALLog5qeufVDK9rmHiftI5zdMy+dqns7vXq+1erA85VpFgXVBmld6snD/OSRxkJQ7T4AXpsPz2qlxGJ
+ iBnWTQ/uBDHgs77gs5BCOuAyYIV3M8O6GFH97OhP4kf18qP6+NH93OgBbjzyaWECcHSTmK7jIU0Qjh8O
+ bPkxtPNAeMeB0Lb9IV1HQnukg7tkA8HOO1AhsMmoTyFiAGhGJU3g0x6Q0iZwKePo1El09kNC5iwBidHH
+ IEYH0FGpE6TcKVbJQ1HptLhyRlT9UFT5SFg2yy+aZRXOMvMeUrKmMJkP5LNmpHNmjuc8PJQ9+332o28R
+ zf4jb25/wbODuc8PZC78mLlwOHNeLmdOvuwJtvoBtbiBHh2M8bKVvq9y/D5b1pmucIescBMv74g+Zkn5
+ xtHkbwlx+K5+w5pqbb+r8peV/nGTfhz2j94hKdxlKN6gyd1ioO9xSO5CgrsID+1coLNFmDI1WIkSICYh
+ jS5EJF9lKrQX9VOi+YkpkqYXRG8h1k8ZF6JKiFKhxGqxIg3ZAebc8NtGAV6W3iH2Z2+dIIsOm9qLnX0c
+ bro7XLhprWss4omwV66a+3g5Bfo6xUTfjE9wsbASaenQOAK0PHa/NOZbEvfwbQ+rnBJ/ZxfDgACLwrzr
+ mclnwv1ODHSG/PqvoY//Gvmw0fVudfB/H+Y+/ufxx38/WJ6v7Kr3mpsO+9d/M1f/6TO3dWZqW2N8lzG2
+ gxvfwYxto8e2FIe3FQclPXv7oV/SDnFwkzH8VrVn2rC8Rj/eXzvo9AkXE80rJtyb55mhkaL8Bs3GGS2A
+ u3eN3b1G6VrDdL3hVvaeCAvTuWrLO6fJdRJrOwlPnOcrnSNxL2O4EaKTbWfvj1wOKFQ/HaaolEEzaNG5
+ 2KBknymvGfMdO+OIShnGIF9eO/5HXtg3jIjvmTHfs0P+QXc/zLyC4doyRJZcJZAFV/mUUBX23dkpazlp
+ Gl7VNnYzsgi1PZPodC77xqUS56vl9y5VeJ+rSLArLjPL6dTOGOKnjTCSB6lJQ4zEYWb8IDNukBEzyIzu
+ Z0b1siL62FGgXmZEDz28ixbeTYvuY8UMsGMHWbEDzOg+TkyvIK5fEDfAjxvgJY0JEkf4+4oGT8b1SgPo
+ Ia1HwdGD234M7TgQ1n4oFOjvlgrqlAuEAL0bFd6HDh9Ah/ejogawcSOE5AlIGpJTJwhpE4QMWA+axidP
+ YePH5WOHZBJH0WkTkGzhFj8UlUwD4kp1j5Vr58Rlj7gFD1l5DxlZU8S0CVTqpHTm9NGshwezH32fNff3
+ zCd/yZn/W/bsd3mPD+fM789+/l3mi+8ynx/OXpAtnMPVznDLmzlp0QT/s8c8NaV8eRg/FsmVoXCLLHMF
+ f/g08e/2Wn/29jxe1sbtWVCv7WNFeErdUv/HLcqx23i5mxRAHB6pcIeCdmHiXdlYFzbmPhvryyUGCamB
+ fLI/nxwIferENB8x1UeA3ITzEOR4C3BeQmywKjlMlRSqig/XpoUYcoLtNSI9bdy9re1v6lpd0dS34Yi1
+ FJ2uGoRF3Y2OvW93WofDlL54Ts/H/XSgr0Nk2CUfrzPqqlgXlzMFhVFRsS7uPmdcvazOXVG2O0dzvqea
+ l32pofJebpJNdf6lD2t1H/83/tvPE+9X+j6sDvz6fvrjP2H7xaN3y629Td7Tw/4/76SvbvnOr519uKUz
+ scMY3sUMv1MY2ZUb3ZEZ2ZUeeCcHzU0Ht/Bj2/TJNcHAQ9XKKs24YA1vJ1UXC1XnUwLvm/z4RJXKLt2u
+ Z9p9q4LudfjkI+Sjv7pW8b1v+XWDarFxStftOWc1RU7KJ86LdB0EMB8V3ORrFF+8+yaj/H1xy+D98AyT
+ s82X7q/GFz0PSC3Rc4giqJdrnH54OWDY/n46Gzb38CMImil0w1C06m1pzgU835atYs5TsRSoQU2vpVAF
+ tqJCGcwFzRM3dHW8LY0iz1nFOFnFOVklXbLOvG6f7+pYGHa6tMCirMMgd1gpdZSZMEJOHCElj1GSxmiJ
+ w9T4QVr8ID1hkJUwzI4fBLLB46nh3WSIbaL76bFD8Hg2KH6QkzDATxriJ40IQKnjopRR4b6SYbPEfrlQ
+ yCG2Hg1uO4hQ3nkgqudoeO/x0G6p4A6YgyKgh/WiwvpQoT2ocNiHMUhIHCXDj08ZI6WNE9OmCKlTeIhn
+ 4kZhiVQWQE+BGH2SWTAtKJ4WQYxe80hYNcsvmeUWPEJAT5vAJo7Kpk1JZT08kvXoR4A7a+7b7Cd/zVv4
+ W87jH3IeH86a/xFAz3nxY86zYyVPCfWPBTXdStnx9IhLir76x7zF0j5sBW822oUte4Mu5Ujaf07pH+43
+ jhTWMboWVHoWRY3jzJQoRRf9H26QDl3HHr9Glr5Olb1NUnAmoe/S0XeZaFcW1pWJ9eGRg0T0ICE9AMGa
+ 5i+m+4ppvkIqwr2IEiim+oqIPkJcqDIpXJUUooYP1qb6GXIjr50M83O87mKmZ8fRs+NanFfhqcmINRTO
+ OGpeuWpibMQ5aci+4qR39+bJAO8zEUGO7nfNdNWxVy8YlJdEFhcFJSZev+Osa2wqd/E6s6jkRkeLd3Xx
+ lcpcx9nR8J/Wan7799BvP4//a33kP1tj/4PddP+a/fi/Jz9vdPU1eT8aCfzl54Kf/h33Zuf6ow3dyV36
+ 2AfU0AfZoV3pYURSA7vS/ZvyIwD6BmP8laC5i58YzfS4zLlhwb55iul7h5edqdk6qD/wQntoTTy4w4SW
+ 013Qa3cD3bVG7FsStkxoJKer3D7PO6sldlLWO6ekc1osPisUu50wKrvr/jS7eKOqaSYxq9Mv/El60X9b
+ h95Xdgx6RFTZ35zyiv5fWftWRmXDOeckPesKhzt9t4KKza/eZ2mdp4ptuAjl1kLIwcKmOxUbsaa9ig5U
+ 1Dgb6QY5mMRet4q6bBRgr+VroxVibxB96WSKp2le+snSdsO8IdX0MW7KOB3BbJwGSh6jQzCTPMpMHWen
+ jnOSR1mJw3RAP26AGjdASxhiJo7ABcCKHwL7ZyUOciD4SR0TpI4J08eFcACObp7QrxDRLg85lojuY5E9
+ hyN6DsYPHo8ZlInolQkB0JGZqGIgPAB2SfcgXV+iYdfFINTlEpNHyRlTlPRJYjJUn4/KxwxJxw7JQi1X
+ 0gguY4xW9FBY8UStdkG1bl6p+rGw6BErZ5qWOUWExdT44eMpE0cyZw5mzEDQ8o/sx99lP/l77pNvsud+
+ yHp8MOfZgdznP+Q/O1z2DFs3C5SL89J4MdeIQYYofyV5b66MO+PofajF5R6/CEtF3B9czklnF9G6F0R9
+ K9zuZW7bnCAvm+hlfeA67YeruCPXKdI3qDK3SfK3CQq3KQrOTBSY+j0m2oNDCBDRA8V0PwHFh0/yEVD8
+ hTQ/IfBN9oMARkQJUCIHignhyqQodWqwBtFXhxZkoxF577TbPdsr96zOuZraXdezuaRhcpqrb8k4e0X7
+ 2m3TS1cMoSjX1kp4xUnX9Y6ph7Ox5x1T56uGNy7oet41c7IXWJpiLM0VLl2iJyRZl5Rey844Ex2s29vs
+ +nIuaett6W//6v/t35O//fTw44fp394/QED/7+x7cPRG74WJiI//rfrvr1kr7+8+3jZ48I429pPc8M/H
+ hz9IDb+XBUcf3j46uCE9vk2cWucMPOYWlZN83eRv2ZFu2tC979KzMlW6hk9MLUOfRx7Sq/onOrSohqZ5
+ 8AGlnWsEcPT2aZ30XLW7l3jndAUXVLUdVbRsxCJ7ZfFNXd1gG7vsm3cqPXwqvf2qfQM6o5MmM4sfZJX2
+ hCe1+IQ/TM5/39SzVds+HJFU7xk4kZq7WFLXGxAbYnz6PF/DGuJyoboNX82MIzaFzjBizbNq2ld0dFzM
+ T4RdNk2+b5Xobhx4Te2uDfe2OdfdTinojnpignZh84m8QdXMEU7GBDNjkpk+AeYIYqZNsEAZkxxQ+gQ7
+ bZyVOsZMGWWkjDLTxrlpY5yUEU7SECthgJU0wE4e5KQMc1OGeJkTgoxxwb6CPtO4bvnIDlR4l2xE3/Ho
+ /iOxA0eShqUSRuSSRjAJg1CDToiEDl6tChCsB3YA6/joPmLcADlhiJwyRsmYoqWOExKQAl3Z2CHpOPgq
+ cPQRfM4ko2pepeW1XueSQfuiduNz1aI5eIpwbaDih6Uh+548cTD9wY+ZD78D0DNnv8t+/G3e/Hc5T/Zn
+ LxzKfnYgf+FA2YJ89QN6VRM/E7z8Bt7XCO0P80I+wY+L8WHLe3DlrrGPOnJ+uGqyPyGW2Dwh7Fliwbyq
+ c4Xe80pUWccMvX7stvDHK8RDV8hHrxCP3STI3iJA7a4cgH4XkeJ9Lg5aLgLW3gIiNGr0EZDA2n1FFC8R
+ yQu8XESCrEuwEilSmQqt0321yf7mwmyfS1E+V+1O6xrbadhcNTx7y+iah4VLiL2z/+krLqbnr524dddS
+ W5vAYhw6oU00M6CcMqZcP6eek+wSFXguKtghyNfishP7khMtOso0IdH8vhs/LtJwoMPj6XT0aLfvyqui
+ j7+M/PbLzP/ezfxvZ+ojhC4/P/z470fvl9r6G/2m+wL/tVX408/pK7v3F3ZMpnapw++ODL7/cfinI8Mf
+ ZAd3jw/tHBzcPDq6iZraYPZBTVE52t9LyuM6IcCDmV3A7xjRnHyjPr3LGnuPGfsZM/4v2sh7zsB7Vtc7
+ UtcGqXeZ1zKlnpat5HKFfU6P46QKDRY1bJUhQ6Jkrwy7PNUua2pf19N3NjF1tbD0Ou0QfOFa9HXnmCu3
+ Yy/fyr7rWR0U3hod3xQZ2xAd05eVNZ5f0BASEWzj6CjWtBao2IjUrflq5lxlc4GqnZL6eXWtmyd0PG1O
+ RNw0Tg8yz0u0SI028HcROTsy7jjQ799mRcaJcps0ioaVCyd4eVOc7GlO1gN25iTAwwLiQYA+HGdOsLIn
+ 2NkTnKwJdtY4jJzMMW7GGCdjlJM+zEkdYqcNsVMH2SmDcC8vc4y3r6DXNKZTNqIdQId1TZm4EanEkWOp
+ o9Lp44rZk6SCGV7+tDh9hBPZhQ9oVvBtAneHLXbE+H5K0hA1EXbTDeJi+hSje2Uie6XihuWSxtEp47js
+ SUrZnKDuqVrzM62O17rtL7UaFsTg6OnjuIRBmfjBo4mjRySgf58z+0PO7HdpD7/NnvtH/vwPeQsHcp4d
+ znp2sODxkYpJbFEdJT2YGHpBweukjIuqrLsQ48mFJkQkfw7Zk0W4zDx+Qe0foR6y9V28vlfC7lV6xzKx
+ 8y2p6zWjdZifEUJw1zlylXrwEunwZfyRGzjpWwTYXKdwjwU9GSG5jnbn47zFJD9lqq+Y7MUn+PCJ/jyS
+ j5DoKSJ6KZF8xEhH6VAVSqQ6M0iT7mHETrvvUJMZ4uFy3tRGW8NEaHRGw9xR/fR1XddwJ/+EG9c9T111
+ MfMNuXTmrKa83F+OH/lSTupPZNzfr1/SLi3wDQ2wj4m60NQYXFfrXVZ2p6z8Rmq6TXnp5fYm16mBwKaK
+ qzkp1lPD0f/7z8jH3578d3fmX+tj4Oi//TTz8d8PP6x0DDT699TcXXwc99//FO78M2huzXRiiz767vjw
+ ++9Hfzow/P5o3/bB/t0f+ncODm1KjW3gBl6SGgcIBeWE3Fx2aRWv64HwwZLKzDZ38h1h/ANq4p/YiX9R
+ xn5iwkcP9EJz6k1qH4A+qZKWI3K9yjp/gnVeVXxOVcteVdNGDG23YKOnpOEWD2lgZMUX26ponFHXPauh
+ e17rxEUdg6snjO6cNHe3sfV3dAy5dDHq+tWYa9cCzjjc0DWwg35dfKVTQrVTADpE6iK1M8rqlzTUXUx0
+ A88axrga5ySaVZZbllSapGbphIQIvbyYfsGMuBxeboeocJRXNMkpnObkPeTlTHOzp1hZU6yMCXrGBC1z
+ kpE5xcieYEBmL3eSnTPBzhnn5I5zc8Z5OWO8rFFuxiAnbYANSh/kpA6ws0Z5mSMI6Cax4OXtqNBOuahB
+ ueRx+ZQxmewpxcKH5KIZZtkjpao5nYJJ1eQ+Vngb3q8J5dOICmmFxi8EYD2mlxjaLhvaLgXF69H9suDr
+ yWP4jEly8SN2/YJq84JG02O1jmeaoBb4TJzHvLxpctqoQtLw8eSxw+kPDmY9OpD/5ADE6GmPvs15/I+8
+ J9/lLuzPeX4k7/mx0kdyJe245ChUqK2sp/YxNw2puyqyLsoKHkrQJ5HizaK5UPHXhdIe9kdLCkkD87yB
+ ZRbSoXyJ0r0CFSCU/nmlsnROgJnsHc6xW0zYVidzhyTnTFGALrsubLQrB+PGxXoICD5KkECk+ojJ3nyC
+ Nxfvw4EmdQQvJbKvKjVQlR6sQgtVp4dqM/0MOH7nTiQGXg30vmRpq61mKGCqECkiBZqSLE8HY+CgfNXb
+ 9l6w470AB7+Iy2HRN41MOAf3f3Zg/2fm5ryiIv+cXI/snPtFpd7jD3KfPC/tH41vbPEpKLjU0eoz1BMc
+ FaB73lrG7SanrvzeTzt9H39d+OXdo39tTfwGM9H/PPrtnxPLCxV9db4tJTemhwL+90v5f35Lfb5xbmpV
+ NLGDGn1/aOTdj8O7+4d2f+zb/b5v98eB7cMj2zIj65jBV8SBeXr/HH9wgTu1ynywSZ/aok7tkh78RHrw
+ M3nqZ8rUz7TR97ShD7ThXcbomrDroVpOvtL968zz+qzzasoX1XXPq+rZK2nZCSH8ULXiKkOK0IwtQips
+ +ciKD9y04gH9kFERW3KF1gIxspgKTaWh9a6Sqp1QbCtQOiWAZAtsyFK24CvDNmoLoaqDitp1bQ1P8xPh
+ F0ySfE4W5JiWNxoWtWsUdGjn1mullqiklAuymnn5A+yCMXrxFKPwASsfWH/AyZ2CZXVGNhSSTFJzpiBD
+ TcudokPUkDvBzB5n5oyzcsYAdEHOiCB9kJvax07pZaX2cdL7eTAC93BmX1G/YWyPdChsi+6Sh80TyeOK
+ qWPyBQ+J5bOMqllR3ZxW7aMTJaPqmf38mHZKcAvOvxEd1IiKaMPG9hKhTYA/7NhoOR7WLh3fj4rrU4jr
+ Q2dN0mDNv2lBvffliYGX+mOLRhOLRiOv9dtfqdfO84pnyNmTChmTxzKmDmbPHsiDWOXJ99nz3+fOf5f7
+ +B+Qb8l5fiz/qXTJqGJmDirw0lFvzeOeIhlPFcX7yoruKoreahhvZcCRDF2K3IyP58ZQByfEEyucwTVK
+ 9xKpe4WC5BCg2ukpvzSDHmghc48n7cyWvwtrRlTUXZr8HYY8YucS1t2h/aKQCJT7CEnePLwvl+DLwXtx
+ 8eDofioUoDxQDD11Ke7qJD9b9ZSI2/Fxbnfunz1/08rC0UDHTKRIPXgU85djxL/9gPmT+CTFOejMbV9b
+ Z1/b+35nHC/qUBgHBEqy971OxSZdj066Ghl/KSX31sBkev9ESnLOFVcf3WvX+R5uGpHBJ/NTHCN8T+Qm
+ n337tOzX/0x//OXpx38/+/VnyC0++vjL7L93BqcH0uqL7jYUXH82nfDr/xp/+1i+/sHv4fLJyVXm5K7C
+ 2O7B8d0fx94fGHq3f2Dnh8Ht/cM7R0e3ZUY35ad2sDPvSNM7+Jkd3PQ2bmaX8vAdDdF7xsMP9Ec/06d/
+ Zkz+xJr+wJnZVhmY084vUvG4wUZAV1W5oKpzXlkXtkfYCTQsIepgI4lwc4Cbq2wN3swWWyALQCJzKC5n
+ CUyhiRcLtoQKzJg8CzhgwZZqZIeoJH0O1edCKN4y5ypZCVTPKave0dXyszSIuXoyI8S8qORkaYdOXj8/
+ Z4RfOKRSPKBSPCTMH2bkT1CKpqklMwA6M38aWGflP2DmPaDnTgHfNDgAwZn8SWbOGC17lJ41zMga5mSP
+ 8LKG+Km9nJQedjKMvdy0fl5aHz99kJfcy9pXMmgU13s8GNb5e1HRg6iEEcWkIbnscWzJFK1iUlD3SKd2
+ Wr9iTDd/SDW+nRHWTApuwgU3osJboKEXDvrA+DVJ+TUcC22TSehDR0Pw0yGXOkSsmlPqeXVi/K3pzJLF
+ 3Krl4xWr2RWLkRWDjteq9Quc0jli3kO5rOnD2Y8O5D4+gLj4s/05C//Iffz/aeotoNpOu7fd/nXmnZlO
+ FXeXBAhxwb20FChaSmmhSt3djVLaUtzd3d2dACEkgUCE4E4I7uR3Hub9znfOWs/KIim0a9E7O/ez5dqH
+ kwZEE7nSySz51HqVsB8KH1ylXxnIvyaqfNCHvSepf9BT+2yi9t5E6bWx0ptTimEvNFtqLJgTlt18dOu8
+ etOsRv0MrHJSpRponYPPikV8cpR+iJbcD+cI+afaSo8BFwCtAGjRz7GqQO5A6yCoA5sObqJvcRpA5R+w
+ AESq9hLcAfRhnwAxnQR/a6zzzFo39JVXUWFUbPqv97+ePvp44+5Lr5sP3WycSQgDOTnUkSNq/yOl8y9z
+ F6077xzvvXO4ct/ilLM2HH2IZCrjedPg4evTLz85+gV7ZZd+TC988+WX+7X7JAtbyRMnJV2dVFwdFF89
+ MM6Ov1uS8XykPxva7Nufht4aFG72QztMSMhcnq1vrQ6I+eWZHHpxdCAO2muAoIqN3TjuzC3KqAl1Dk4V
+ SFEXj3UtHe9YEm3lH21bOE5ZkupakukUyFCWpXrWJGkrMvQF5V6Bev8ynLmszVxC9C7q9i4h+ldRfWsY
+ xhqudxnXyzdu77dKTjV+fRd7zQZ32cT4irGlp6GFh74ZILGAsA3QRaC6CZR9Fqfvjjc8hwPoUAAkMtjX
+ Ona/JHQWb+iMNwB0AAeMngMYmcMbAHG7YA1AWdQFBXQPRA8QAMbexiavbE9+93AIve8S/8M1Lcc+s8ki
+ gYyK7IQldCHTqLgUKjKxB5bI0Ejp1U6loVOoIHeHSqWDR3Qy0Df1/zspQOgUJBB6Yicqvh0b04KObcHG
+ NOEj6tGhtdjwekJEAymyUQ8coHXwdF/owU1SXyplvtaDUQkwRaEU3CgfWq+Y1ITIJRtUMuzKe+yLqXYZ
+ HZaR9fhfVYhv5Ro+JQq+ZYrfq1V8qxR9KmQ+lUr4VsoEADJjpcKPKqVYsm4ew7CRZ0OfdGNNuXOnz/Om
+ 3Qdn3ajTDk2jVpWDegUc3Uww/L/f0CKRxBZP5IgkgRwL53By/+HkgeNJXIl0tmJarVrgR9k3ZyRf6Mm/
+ xqmCnPdnHMyHoPnVSO2juexba+mwu1o1WQa8QUcO/xR1AU8GSyDmQUpYtWJSqXpKo3EAmxGn9d5J7B5K
+ 5L6O7ENwB9VSeopUeoZRfopWAecJRvU5Xh0E9TdEOPD9r9Cqb9Cqb9FqL1DKL7CqH4gwH3A3BZdUY50X
+ tthE/4eFFQkxuSEfgl88eH/V87bdaSeCnYu+pQNWnSRxRO2/DyockNH5XwM7Ra8HRvfenrp4W8/xIsrG
+ DebgqX3jmem3kItZJe+Scp55PzCwcVK0c1U97aBsbi5uaiRibSLifELyspPKm7vGKRH3J7iVkHBUuDUk
+ 3GJBe0DrvYKZekpzRHTApfDvZ+ktATur9YB+IYQqpxe/MUad6JNoBl+JsShJXZTsFEi2zR/t4B+jLkt1
+ L8l0L0lTlsS6V0Roy1K9C6oDi5qsRThnRZezguxf0u1b1B1YxvStYBmrWMYSto9v1DlwIjXF+M1d3PXT
+ +EuAGW18AnBDz+ubuJGA8TBwxJMAtAgMPp/F6rkBWeP0XTD7Egcx2xG8TjAA3+NCNHTe514Y7tNgCIaO
+ BPAJoO8Kvg1JdEGBRgBDD6IpWA7zycku5Kpb7ONzqYHnsvLt0xuNYtrhoPIYS4HFUeDxVNj++HwvLBEM
+ XnYjk7pBRNdNoSNT6ciUHiQQ/f970Kl0DIjoiV2oxE5sHBkb2YwCdiW8HhNcg/pVgQqpxofX64WBHGst
+ Mbxh//FAVod9QJPExzJJn3q5Hy0KYNYzuEElsEw1rgJTTLZuYrg001xqehxyyJYxTYSQBuTPGs2vpXK+
+ ZfL71ADw9qgS86k6/rVa8nu18tcSZWBp4snYHKpB/cDJ3gkgcS/e5IWRafexOXfurDt1wr5h2Lh0GJsN
+ NuhyFBPY0ols0STOkbTBw+mcY6kDx5PZx5OHRHN4SnkApOEr98b52Btjmff6Kp+IGj54rR9GiG9m6p9O
+ SgdeVqmNMx/jOCysnB0W2FDnSO1zyKYpjdop1app5dpJ9WYWOiVR5ZXboVvIQ3fgUvfgAAqg8ASpAjLo
+ z3DqgKb7BKv2gqgBhP4Sr/4So/ISpfwKHLTKC7TKa6zGJwLcj6Tlb6T70VT3tS0+5vv9+OyArxEfH364
+ deH2aduzWMtTCBMLhJk1AmUkd1D+P/+UPSCP/BfBWsrGQ/X6M9Ljzyfe/XJ59cP59S8X36gLHwIdnn60
+ uuiNOuOqbntGze6MuqmplDbsvwnI386Yi9w9r/7YC/7urp7/O2dObx4EjQi3R/Y2OdDOvtBnRsorCr8G
+ fHUP++beXPpFMFEG7TIhiLGxXTgleMqZNh2YhfXxVWgLql182Y6FY52CI50LYpRF2Z5lmZ5FSdqiNGNR
+ mSmADSzA2QIEbwk9uIRlC9DMBWTfEpq2iKIt6/YtYQf4JhSmdUaK2Zu7+KunCV6mppeMTlzUM/MgmgBZ
+ 73eqACuCA84E2JL9+O2K1XdEEcGwsxPgdeH1HUHwJhr+I3QDJ3CIQOWG4MX9p+DH0fpOSD1XlIEnASzA
+ sPjoYhty7Wzcs3PZYecLis9kNAFImGZkp2pMlyYQOmjkTqIhk+ioZODCu3USuhH/CF03la6bTkemgy96
+ dFOp4KDSqci0LmQiGRnbho5sQUY2IyOaUGH16KBq9K9yTGAFPriKEFyND64hhNYRQmrwB3K6zoB84scK
+ Cd9GWf82ENFVgupU/EtUo0uxeU1WVR22jT1ONT1nsvdtOj6yGR3SpO1XCYQu/aUMNDZK/6iX/l4n/rVK
+ wqdE+kuxgn8VLLoFk9WpX8WwpnBdB0YvsscucoHip9wHZ9wZE/YtwybVo4QCMNrMAW2J0iBxHs/8O5l9
+ OJUtksoSSwX5Fp5oFle2EHTzJqj73BJ/d1LqvaniB0NVHwPYN1P4F0sFv/PyBb8Mx6hX1pYuLW64ja3Y
+ 0vmGHbPopilY3ZRazZxq/ZxGMxeVmqz8/Nyf11B/emuI3VCXugWXuYdQfIhUfYxVfYJTBVkXsO7iFVH9
+ BfgarfQUpfQMpfQcqfQcowrSjh8Imt/04P6myI/mup/PGmeFv0nOCw1I+PHc54HHjVMXrpmdv2h20gZn
+ 44CzOKMjofGbmMZ/GToqOXnr2l1ROu0l6/EAWHarxz4nn361ufPG2OW6+ik3GXt3lbMXtJxcNM1MxEm4
+ v62Mxb+8OlmYfKsi/WZp0tWytLttld/441XCnQHhHkAXDYDi/7qgqYccGx95x+etffj38xXZL8aY6Xur
+ PcLdfghqXdsOGuO7cOcwrH0Xrt4tUKQsi1NWRDoXJLsXFWnLCrRFGZpAniFQYy5qshe1BpeRw8uYoSUM
+ G6icrwOCOl2A6FnUZS7hWHxTCvNkRqrp6zv4qzZELxOLy0bWnkDoJHANNQSR23HfeQPUFngEhgTEacBp
+ Ie7zuv4tdODC9wFG+1+DL8AB4RzMy4HXHYCDRxNB0+JZrMFFkvFdS4sPbvbBN88lvruYG3uhoMI+s40U
+ 3wGL6lQDET2Bqg16/lIY2NReTBoDxGzUvsQZuml03TSaTgYdkUnTzWSgshiYLAYuh4bNoqKS2pExLcio
+ 5n+E3owKqUUGVaKCqvCBFYSgSkJQFeFXBfZXJSqgCgMWAdgGNIp8KBP1qZP60bI/FvQD9G/lKwYXIOPL
+ 9NMrjYtbrAvbT6Q0G0Q1Y2LaURFtWj8A5Khyv0kdTEz71YD5I9HP5aKfikQ+FkgGVMESWgnZnYbFneaV
+ ndYN3fbkPmcaz405do47da5/0r5t2Lh6BFM4rJ3BVUliSsQzQIYR3EGPJLNEU1mSacC3DEukc6Xy+tTz
+ 6nUiApW/XpV/Yyf11krqk6Wij7XCd1e5lI/IvsZzm4uPd3a8BZtuUxsO3GWLXgGhY067cVq9jq8OthC2
+ DWMz0tWee+wL/ZqG2BU1iUtqElc1ZLzhcre1wDip/L/vo+AAs/5AV+Gejtx98DbQVX6AVn2AUnkOyEd4
+ 1Y966m9MtV+dIUb53kvICg6I//n4450bT1zcLhna2OranMacu2jk6kVUw/6JsxK999nyyhuMwy2Z01fF
+ nG4qetzTcr+pc+GWrvsNuPNVVWs3ydNucm5eMHcPmJO93M1LiJyEm8tT2cKVgq25lNXppLW5nJ2V2p2V
+ tt3Nvr3dwa016gq/brA/pabCNz76jt8nJ//PTqkRV4B72VpoEW4B+07d2c2cXbrHnTVhLWgzlzV6llWB
+ KaesiVOWZLsEit0CeapAtge48wWN/iUN7qr28BpydA0zvILmLugOzGsPLOj0LugwljH9SwQQ0aks65ws
+ s7cPwGWUcMnE8pIBELrp+X2hGwGPvp88AYEcWBHQtQJsNyB1oYhAxP9/cf9b8fsHr/9vlZ/BEO2ReHtd
+ vBOKCDw92BFw94TVx/NOofc8Er545qR45NfaZoJsCRUW3wNPpIEshTaonWcM4DP7cVn/52Cy+zFZTFQm
+ UDkDkduLBpDNwn5C8QAJ1MvzevFpnZj4VuDO0RFNuiH1iIBK7cAKVHAVCOfE0Bq94Griz3KMfwXKvxwF
+ aLo2P2sPvy8+6lMr+b1FDkz+fymR+pwr/6sAFVmsF1esn1xulFprHN9IDGvQiWjXjiTDg5tUgpvVwtq1
+ AgFqtE7Jt0r2SzkYUBL9WiIT2YTM6jYp6DEv7DAtaDYtabWuptg19Tl2j7gNTLsyZ+xbx4zLeLp5XM0M
+ jhJoyk1gioCyfzz7WBJHLJUjlcaVTB+SACeLJZtH08iu0UmORga/VvG5IvHVXTL4imKeL55R6bQ0fWtn
+ ++7WztWVzfPzm45jq5bcRRJ1RrtlSrWBDxZ8apPHCNnZmi8v/n0VffCapsRVdZnLGjJXNeSuqslcURX1
+ 1pS8qwPErXRHW+mWlqK3pvxVddkr6nKXNBSvaClfhSve1JJ9jlF8jJS9hZa/Yqj5/fW19MKY4IRf9155
+ O3iY2DggrE9qOTgSLlw2druEMbYRufOWFFvq+SaS6PFGwuHuUdd7cm631S/e1rl6D3n5AcLthpqNh5TD
+ RXmPKxqXLmm8eIiLD3ai1DwfofsujoXuLMRDq1nQRvl+WXSHIdzlCoW83Q3q1Gg+tTOkvORTTOStHz7n
+ Pr+2DfSxbyh5uTpdBa337V9bhU3rOyHD8+f6ZzHMJa2eFY3OZemuVYnOZZmuRUWKQL57QZa+qNq3qNm/
+ pMZZhvOA1ld1h1aQg0sI9oIWOEy+du8SqncBw5zT6+GZF5aYfHyOvG6PvWxq6WVwwhOgufRMgMpBBzkQ
+ +r7hBpkT0KEFhP7viA4yKv/E7/8b1x2wAFW3H+b3YzmWBM4ZMAqNwoOczDmi0SUT80c2p30unAUQ3YRv
+ F/OzLpa0nsmnEdMY2qm9iPQ+VFovKnsAn8cl5bHBIeSx8HksXD4bm8/C5PWh8vuQhUxMETh92BImvqSf
+ WNhHyuzGJ5FxsS0gmYgKr0eF1aLDqnEhVYSQalJojX5IDSmkhhhaRwyswgKPbhfcIvGpTPRrvZRfsyxo
+ zf1UIu1TqPKjEB1apBdXYZJcZZZcZxJejflRphbcqBHVqRVB1oroQMR0o0LJCADu8qtS8SmT+1IsE9YA
+ z2EYlbNPVrJOllGtClrNC5otc5vMC8iWdSx7ysQZysypujH9fC4YoVBJ5ijFMqVimWIxAyLR7GPxXLFE
+ tngKkDtPNHVIJHNYOpenXNivU9pOKiolpkRrJX3XrIzW5zW5bYzfEm7c2t29urPjtb59XrDhML1uNbps
+ 0DuDaBlXrZ9WAdM3HaOEnGz4q4tHrmMOe8NlvGGKN3RUbumo3oQpXVGXuqwqcV1DzltT4aq6vKey3Dl5
+ GScpCTuxY/bSom4aCu4wuUta0k+JqvfQMhd0JG7ZEONDPuRXpHwN/uh+zemsl/l5LyMnF7zbOYPLN8y9
+ buIu3FKJzHFo4N5Ob7d5Favi8fLwuQeSZ28pX7qvc+sZ0uu+xtkbig6XZR0uyly9DXv0QOfTC0xeghOb
+ /Hii7+0s9+u2IH5nOVu4WSfcogn3RiDhFASNC3d7B/oSigtfpKc9jgy78+PrxddPT318YZafcm1uMOef
+ 7oABaJe+JyycX3/DmT3ZNw+yhHDqqjxlXaprRZaypEhdluteku1ZVO5dVO8VAJuuxlqC8dZ0h9dQvGUk
+ d1GXvaADhA7cC30B0Qt+fNywqtng2xetm67aly2MvMBl1MgcXEZBqsSNaALS5yCJvm9aQOIF2PT9rOL+
+ TRRo2uEfTe8HbzBGBGSNIQFK0b8V74DZH7lwwhDd8AYX9E2vm1s/t3fwv+QR+fhC0g+P4sKLlZ0O5Uyj
+ vH5kFlM3dwCTz8YXcojFXL1iLqmYSwCnhIsr4WJLONgyDq6cjavk4KvYhMp+XFkfpqyfWMQk5dKJqZ34
+ +FZMbBMqphEd00iIqidF1OiFVpFCqojhtaSIuv3ES0gNDkT0M2HtciAqg5RLYIeKX4PC53L5ryUaX/N0
+ f+YRoitMEmssYqqN/UuQvsVqYS06caD3oAtUYtExVCB07e91ar5lKj8q1EMaEIndpPw+k5rBU02jZxo5
+ Z6rotgXtVmkNxmktxrndpqX9JmWDBvk8dBpHI3ZAIXpALqxXMowhGsEUixwQieWIx3PEkgfFknkiqcOi
+ WWOymSOKWRz1kgFsLdOwvsuI3GI5TD+7Mn5ld+mqcMNzZ/Pczvb51Q3n2ZWTY4vGPAGRMaNDnlRvmlZr
+ mdcmDxNzcrTeeB0FXek3dGRu6ijcRinfQqrcRChd1Za+DJO8oil9Ha5wWUPeQ0n2jKSo+d9/6f/xv6ai
+ fzjBpVwRkucRxx8aKdwhSV01VAx5d7UwNzQuK+D2y2tOnjZnL1u4eJCcXHAuZ/W871rffGLw8huuuMOj
+ e/ZK+4xzVpf+uxgFrxciDtdEvR6o33uL9Lyv5Hxd0vW67AVvpYePETHhduTae9yup1N9T5eGP2/Ohws3
+ c4XbtXs7VGhvFBIKoL1FCJpbXe0qLnz11cfW39/j+/dLr185Pbpn/vqZcXrMxaGeqM25RtCqDu2yIGHb
+ ljB+ZvlO37QZdUGHvqrasyZHXZHvXlagrsh2L0t3L8nTllToC6o9c8r0eXX2CmJwFc1dwQyuYNhLKOYC
+ gr6IoC8h6AJd0CHTyCCFR2o9vq51zYZ0CWxdBHUfQ9PzIMNoYO5KNAF9tgA4ChyI2z9yB6IHYR6kXPb1
+ jSHaofC2KLw9inBmnz5H+PeL+7pHE10whHM4PVAl9TY78drBIfCye+Qjl/ifDkVlZ2vpjvVci0ousewf
+ NQOyQ8UgqWbEsHoIzIIQKwfxVYM4cGp4+LphPdDZ0Thq2DJq3DRkUM3CVbDwIK4XguG1Hr00UBNtQcc0
+ oGIacLENetF1+hGVxNAKXFSdXkyDflyzPkgYHshsdw5rVflWpfQdGJIuTVA2+lKm+LlY810m7FMG4kcO
+ 9nsm2jcL+aMEHVCNDGtGRu830KCiuhERXZohZMCVVvIpVfpephHWiEmmGObRTGs5dh0T5zpGz1XR7Uqp
+ 9mW9ToV99vn9p3L7jbPZhFSOLqBZRPTLhzNlg+mSgT2iIQyxiD4wYyEVx5FKGBRP4omnDEqmcGVTuEpp
+ bFjBAKaGa9gxYt03ZDc84jg/47q24ra15bq15bS16SpYsR3hG7PmCH1z6O4ZbfKUJsi9tM4iWodxWXmw
+ t1ePXSceuqItclVbzBstdQMjcwMj7U2QuEGQvIGRuo1TuI1R9kYqnlWVsBT90+DIfxlL/5cj+qiHoYiX
+ 4aEnpyQfWIvfd1bPSnxeUBIQnPjp1stL52862LnrO5zDO7riz3mY3H/mcuOJ4csfuHKqW++Cew/fijxl
+ UUoz8UvWvvFO5uZ7tfs+upefKbndlDh/Q+bxS2R2ltdgny8Q9+qoz+rY5/Wpn7vLqdB2LbRH2xMOC6EF
+ IbQBCdcgiL+y3JmVde/RY9zjJ6b3H1jduml2/57Jp/fWhZl3xwZidgRV0Cb1H6H3QlDVxk4Qb/Z8zwyu
+ dwnOWFWhrah0LykBp74vdBDXBSo9C2o9fDXagiZzBTmwimWtYdlruIEVbO8imiZAdi/odM3DO+cQLRxc
+ RgHu0yv0LWfCFUuTi8Ym5w3AqITJOcD5J5ruC/0f0wLCORD6fqkIpw8iN9A0eARCP62LBYBFB7QeEPd+
+ gEfhz6DAKDT+H6GT3Il6NyzNP7ieCbruGP7sVEKIVXGdfT3Lvp5nVs0hVA8CKZMaRvSbx4xaxo2aRvXr
+ eYR6Hq5hCA9O8wixddSgZcSwZcyobcy4dRQkrwm1HFw1m1QxYFjWb5JPN0wl45JaMMnNxKQm/fhavehq
+ UlQVIbqGEFNHSGgmxDXiDmSR3cPAjsVK0Iur9L1Z2Qe0K1apfS6GvcnQeJ2i+Toe9ipG/V0y/Fsxxr8S
+ HVSnGwWyOR2I8C5YRDeYklb4Xi/1pUzWp1g5sAaR1GGQSzGvYzlQJi+2cFyr6I7NQ1dap25Uj3kVDzvn
+ 8ixT2fgElnZUv3IIQzqEJh1Clw7qFg/tkYjqlY0ZUIjnKSQMySbywPicAhiCTuPopPWj8miEqn6zlkGr
+ Do4ZbdBsePrkwoqdYO3k8sbJlXW7aYFV/zShe0qXPA1vndJomdJsmFBvnkM0DqMzi+Ef7opcMzp4Sffw
+ Zd0j1/DHrxFEvEkid8xEH1lJPTCVfGwm98xM5ZGxymW0lJPKYWuF/z2l/R8eZodvOog9dhP9fFnmzQWJ
+ Tw908wsfZ1V8Dkl5f/u116UHLm7XLM644Z3OkryuWN996nzpnoHHfbnQHDxr2a1v0Ygxb8CYt61k2ITm
+ El6GaD0JRN/z1b71Wu3VF1xJ+Z3VpQxoK2tXELY75789/WtrLhraLId2qXvCkV2Ivwet70Fb4BGC5tfX
+ qVnZd69eV3M9p3z2HOLmbdO3b0798DuTm/WA1x++Op+9u94A7fYLhWwI6oCEuQurz/tnTelzIDZr0pZg
+ Pcsa1GWFfwudIlCmLqjTBHD6MoKxgmauE/rXicw1fO8aFvR4dc9jO8Fa6hmNzjntzgliVbt5eJDpk0tG
+ 3qfNL5mbexiZnDMwddMzc8ED97If0cE11BVDArdSQMcFqRjgT/6/iI7E/Z+IjtqP6KBc6rgf0XFA6O44
+ vfP6pJunTD+62wTdson+YJmebFnafqqWa13DM6rnEZuHiO3jBuRx47YRw7ZRg7YRUtsQoX0E3zqKbxnG
+ twwR2kb0W4fBHxm1jBi0jOq3juo1DOLruXq1bKPKAeNihlEGGZvSgk5tJiTXE+NriLHgVBNiawhxtbiE
+ RmxcPRZEdLegRmWfcmXQi/seVH+qFb7Vwb+Uwj/mab3PgL9N0vTNRIVVmgZXGfiVIH5VaUW2ISP2e9AB
+ 71wpolv6e73op1KpN3myviXqkQ24jHazOo5r5+TlSoZjLet8x/TdxokbZcMXi4ZcsrgW8X2YqF4Y2GoU
+ SJUK7JYK7pYJ6pQK7JQK61GIYirHcVTiuIpJQ8opPFXAlY6nA14AOouiV8owL+sxqWYYtrGNacPGnCmj
+ Eb7+1JLR1KI5e4bUNqJVPaRaOapSPaFeP61dN6NVO6NdMaiTXq7x6YWo98k/rxgd9rYUvW593NP0jxun
+ /n5+QfTdFamX58VenpUAHIE7ViKepL/OYv5wxv2Ph/V/P7oi8u6+5K83CnG+GmEflJLCjCqrH8RmPQhJ
+ efvmx/1L913Oe5+4cN383EVTzyvWN+7bnr2MNHc++PqXxsia5+SW9fiG4ciKFXPWsa7PLqJI72Mc5sUv
+ 3UcfteNSzwoEadBWIZ8X1FPr3dd8a4H3U7heKNxqFgo5QmhmD1regzaFwi2hEAh9mr9Ym5l/7fINGTvn
+ Yx6XYU9fWn74aPv1q31C3LX66rc9ZL+JobSt9U4IGhAKu/drpXu/hhddaFO4nnkt+rJW7zqCvgbrWVGi
+ ArMuUO7ha/YsaNMWEbRFJH0JQ1vCdi+iu5dQFD66axZNnkc0zmk2zWu2TGOraObRsZbPb5hdtzW9bGlx
+ wRSsFzU7a2DuQjB1JZiAdYr7SxXx+mdB9hBYlP37qD4ohe6j09EgqAOvQnJAkc4gcWdQ+9P+oPgPRkWB
+ p/cg6IOt6ndszT9csA57dioz4nRFjW01w6qKY1g5TGoa1ydPGJDH9NuGSe3DJPIIsWP0nzNGII8DuRPa
+ ePhWHrF1iEQeNmgeJDUPkVqGiQ0cXDPPoJFrVNVvXNZnlNOJT2lGpzThk+sIibWk5Hq9lAa9pHpiYi0u
+ qQGTUI8+kN5xJrAJJMXlP1cpvS+V+QAQLgAjWof4Xo74VqgVWILJJJ+q414q7XeNbzEIrFIPbgEYaLVY
+ ukICTTKy87hv1ZH3xZIv8+ReZyt8K4IltpoW9DqWc9yLel0rBz3rJq6V8jwK2GfzOU7pLNNYOiaCBg+i
+ Kv6kyP7skv7VIePfJve9STawUzGCoR7dr7Evd7YKIC3GMjViehExoD+zg5DQTkpuIeV1GVb3mjX167ey
+ 0V3D2rQxbeqoTusIrISrmN4vkcGRLhhTKxrXKJ6AFY5qFgzAkytUPn86dsv99xvux+7fkLl187iX5389
+ uPvHJ5/jfj/EfX1EfN6LvH8qcvvibxcd/uOiw39e9/jtyZODfj/FY2MVC3IQDRXE+jIiucmpo+VRaITn
+ z6iHH389uvHY49Yj10s3T7pfNPO4ZHnjnvXFa2ijE78FROqt7Dxc2TmzuGWwsGU0tWrLnnVrYTnlNlvH
+ 5p3yC7ZoankLQbULY7G9TW87y2+0Fl9itL7d3QBZ826hcHgP4guhFQjEcuE2tLsICfv5S1m17d5v/NQ8
+ bx+9clf2wXPU01dmHz+fiYq6lJF6vyT3RQ85cHY8b2u1RbhDhqCaHSh2avVm77QpnY/oWdLoWdGirSBB
+ CKcvqtAESowFOEOgwxAgaAu61HlE1zzYua7TNodom9ECH4PNsxrVcyrls6DWhsqj6PkG4a6cR7qZYd0N
+ 9d0MjV0NwD4ji7Ogs5wA2gFM3PX392G46QGDDkRMcgGlIlAbAnLHGpxB69uj9PfdCwprj0bbYwF6ztiJ
+ YH4Wb3pJz+SOmdXTMzafrtlE+dqVlzi39Tk2AdPCAygOXMOEQduEUdsoEDqRPIwnD2M7RnDto7jWMSx5
+ FN8BXuHhWjiYdh6+a0SvlUvYP4PEFi54Vxg3cw3rBwwrew2yydjUJmxaMzGxHptQi0+t00ttIKXU45Nr
+ sakNqOQ63QMZnacDmsQ+lUp/rlT4UCb7qkD8Y5l8cAsmqA4TVIlJI5u3DF/om7vdM+tdzXOMbNL+WScb
+ RlGIp8sndItHtBz9VnbkfZHkmwLFF5myb7MVgqqw4bX6kQ0miWTbApZHyeDFApZbAcctj+2Q0msY24OO
+ 6UOE09V+dEj7tkn4tUl9bwZwL4XgLrUIOtiNBgunK4OFR0k87bRhbOqgXkKffkQ7MagGHVymCz6Dctr1
+ yumE2gHd2gHlaqZ0zYBMOUc2my2R0HcMpCnTuLJpHDnwmMqWS6Mrx1XIfwk48ujJn89eib3xk3v1U/y5
+ 718+YUdDs6USypRSy1SSCpWj0xR9A0Wefzr40uewb6h0eLpyWplmfSexl2PNG7IbH3GanrjJY72Njrnw
+ 5tuFl1+u3X527tp9e09vkHgxvuxtfcnb5Pod0mmXYzEplpt7z9d2nJY2DJd3TGc3To8uuXEFl1j828zx
+ tyGRdj9+nOyj+i+MpSzw4oX8lFnur+byJysLpTvb3cC37EFLwLQIoc19g743KtxrnFsMHhi9V9J80i9C
+ 8+5LsWv3pW491H71zvy7v2NkuFdO+sPmuk8sWujwQOrKQhUkrBdCqQsbL1lztvR5VPeCWhdfjbKg07N/
+ 0dTsWdz3LYwFLTpfi8rX6ZrT6prTbp2GN03CmibVmiaU6qeUy8flSydUysF2gFrUg5cqNpayVih1W6Qu
+ APvb4vUcwE2UAFptzcFilvNGpu6GYN+isTuA7hqTzhnhXA0wznpYJ+J+f4stWv80GhDncLZYzGk8wY5o
+ 7Gxodd4QjHFY3La0fOxo9cHbMi7YtrndnTbq0j5hUTtKrB4l1o8bto0bkceN2kdAzAbK/rfQ8a1jOBDO
+ wSttPFwzFwvieseIQdsgsZ23H9rJI8YdY6atw8YNbP2KXhAHsZltQOj4hDpsYi3QNzGlnphaT0iuxaU1
+ oveFDjjZoW2iPuWSH8uk3pVJv8wXe50vEdCICK7HRtTiM9qN2gZdeYu32Ys36wbto5u1/SokA5rEI9pE
+ o1uOpXbLJ3Vpfq9UfJMj8yZP/mWWzIs0mVdpiq/TNb+V6EW2nE6hOmf1uWYxHVJolmDWFQxqxDFRkQy4
+ P1nep0nCt1n2B9hBAJrJyGpBVM2IXq2IXgBhVM+YABhvg8xRkzSORWKPZXi9vn+x7s98eEQFLK1dq4Cu
+ VsSUKWeLlw2K5oAWduaR+L5jcX3HQYtYElMsBeieKRbXLRVRK+WfIe4TJ/49Xd6/SMm/RDqgSCSqWiyB
+ LJ5Bky3qVynqU82lqCTUy4VWSAdVycQ2q2Z2wEoYOh2j+pzZE2Pzp6dnHfhz11cE38srn7z8cvbRuwt3
+ Xpy9dMfK85bp+StGnlctPK+ZXLyGuXJbPafYeXX76dKG48qO5eKOxeSq1dDiGa7g3Mz209F5n0fPEEaG
+ v3ueU4oPvdRZ78vu/jEzGDk9lLI4V7q327OzMwrsyp5QuAdt7EGzwIrs7CRP85+N8C+xpt0aek7G5aJ9
+ gtXf+iLe+Rp89LX8FeSalHStpPBhU82b5qov49x0aLcOEmZv7PmNCNx7ptDdc6oUvkr3Apy2pNO9oN4x
+ p0yZ06DyYdR5GE2gQ11AUOZ12mdg4NbeNKPWPKvcOKVUPixfzlMvYiCD0uCXvGXNDWUNtVRM1TWMNWAG
+ GjpmOngblJE9WKGIM3EkGrvombobmV06YXzL2ej+ef277sTLZ/AuplhbAsEaTTyBJpzCEU7h8dY4gjVY
+ 9qJv7mpg7m5gAtZGAwzBy2t6SdGn2qlnaRNn2ifN6sf068YMGieM2oHKR4F2/6/QsW0j+OZhXMswrnkI
+ 0zSIbuSgmwexwMC08Ihtw3odo4aUKQvKlCV5zKRxkFQ9QKgA85ZUfFozNrmJkFRPSKjBJtUBiRNTGvCp
+ TZjEOsSBUuaZRLrMj1rp90Vi74uk3hRIvM4T96/X+lWtG1qtm95KbOg7wZ69wOF71bCsQkBDS6mYf+2x
+ sIajuQw12uIp5qpbQZ+JT77Cx0LFt/nyT9PEn6XJPM9Q/ViE/w6cfcOJ2E6bpG7rGLJBeKtuZIduAhMb
+ 34+OoGvtQ3ebQb8k/Fu92rcWlZ8Ae0SDRTA0ADE9ZxKfO2WQMWyYxjFLZ9rEdloEVGP9imG/ylWjW1RS
+ aXI5A2JFQyL5g4fSmH/E0f6I7v47rvtoCk0svU88pV8kue94AkMqmiwV06YY0aYc1qkUDnad0qQiKSJx
+ PccT+45msI+XTshWTiqUDMvnchRT+xXi+mTi++TSmapFPKAAdO+80YjAem7ZaW39FiQMY/T6v/p8/t7L
+ 83dfnL9408rD28Tjqtk5T+DUjV3OI67eUiupOr+y/Wxx03Vx5+TMuvnYiiVvyYYjcJjdfjgj+HHthipC
+ +4CZ4dHXj09FBl5Lir5KafZbmSlfX6wX7tJ2tof3dtcg4S4ELQoh9q6wdGX949TCxbElO57gFHf+TCfP
+ przTqrDBIaPsfGi8y49gR/+AM6HBdjHhTrkptwYZsdA26PQq2hUGz65eZ04Te2aVuvmgLKpCW4RRF9Qo
+ 86o9ApAv1+nhawHr0s3X7piBk2fgLTMwQIMhCzRaZjUqB5WLaOpptTqfAtQveCqfMIUZ6MAN1DRwSmpI
+ RTWsqraeBtpQA2cCJ5rrGliijECY9zil9/SGyc9P1qE/7d4/NXOx0TJGq+tr6Rhqoc0QODNdnIE2xhCB
+ M0frnUIDP6PnSiRdssa9uaOXlnKyjX6mZ/xkx4Rxy7g+yLG0jhu3jukD2902TCCPEsEdFJyWYWz9IKZ+
+ EF3HRdZydOs4qIZBTOMgtnmI0DpMAlrvnDTtmDAHd9P6QXw1B2QbcflUdHobOKQUoPU6TGoDPr2ZmNyI
+ TWpCxtVpH6gccErrU/CvlflYLPWuQPpltsTLHPHARu3vFbAfxWpJDcjCdnw1xaBlwKqSaRpUIf8p73BA
+ 7fEsuhpVcIIPXV+FHvcveEZUaH7Ok/lULPsmX+J5lviTTPkPJdivFfrfKg3DWs2TqCeSuk0TqHoJNGIC
+ A580QIyk6X5vVP7eoPazSftLrcqXevkfAKZOUY+ggU0v8IJJbOGUXgaPmMrSTx+wTKSbhbbgghoQwc2a
+ UV2KCQyJlIFDmUN/Zg/+kdb/RyL1r3jykYJe5eYJbPOkbhlPoYArk8mWS2bKJferxLFUIthyoSzxMNbx
+ cOaxWObRVNbRwhGxxgVF8opG6yK8ZgZWOKaRATbNshRSOeq5w/DKCWTXvNHYmsPq3uXdvWcQFMfsD3n4
+ yvnW4/PX77udu2rldevkhWunznpYXbhk7XmFdMb1SEK6xbLwpWD3/OyOzX6ZVmDZy7dgzFmPrt6YFPh5
+ XlfD4f/l7oa8dsn03ctzfr4XUuLuzQ+V7K627m50QbvDwp2Ff6w5Twg1bexG81duTCzaji6ZDgqMeEuW
+ nKXTfbPOwAWx5z/Udj/9GWn38Dn6yXPdN69xUSFnGR1B0HotJCzdE0YINu5y541p04qMBdneRSX6ggp7
+ HcHdwHDXSdw10sASjikAExgIIPT2ac22GVj7PLydDwwMvIShnFGvEpuj8/Yz/JInws4KY4xE6Gtp6+lo
+ Y+CaMCVFLSVlhJImUlkHrYZFq6NJWlp2llrPHhFj42yyc51/+hu7OMoZEqSI2ip4VU19DYQ+DEmCofS0
+ MUYIrAWAo6OIrkSDKzakD4+MMjNOtjNsKWPmHRP6beN67WOGLSP6DcOEpiFi8wihZQTfNkZoHsHVDaKr
+ OchKFqJsQLuCjajiIGu4qFoepmEEJBz3047t4H0yZlQ/TKgbwtUMYkr7ASwfk0PFpbVj0lpxqa24tBZc
+ Wis+qQmV2KQT2wA/UEJzTOiS/VEp97lYEXiPu3FHHiYdBdt0/WvgH7OkwipUM5p181sxJV16hT2gzqTy
+ Me9v/6ojBQOI7oXTMztXN6EnvJkLeU3o6BqNn2Uyb3IPPc86/Cxb8lOlzucqjG8VIaLNNJlqmUazyGSa
+ Z7IsEuj6sTR8NBWwCuB+9Zq+NbD3pUrvAYOgVh5sEAjvVEzuVy+eQJdMEnJ4YM8OIYNjnNxvGNODi+xG
+ RgLyEVM5gSWWNHgwY+SPLO7vKbR/FbJk28aJQysO87vnJ7fP9C3oN43DS4dVC0bUc0ZhqSPqMYOyof1H
+ g/sORfQfix84nsMWqZ2S716BMzdQA+vEniX95jm96mlS9iAyqV87m6dbMoprm7YcWXNb3vXeFb6CoEQK
+ xe/uU/s7Ty/cfHTxgret5007Zw8LeyfjU7YYI1MxktGBmBT9DejZ/J7r6JZVv8CEOmvUMWPUNWPOXLgw
+ tvI1q/S2lzfaxELK0lLN1ZXo7W356b0roz12dri4ozGUP9kI7Q5BewMQ1Ly1l8xffz27dn5i7QRvSY+7
+ qMdZMhpYMusTnGAK3NnLj2sZd3zDza/cU716R+neA5jvF8vCzAcTnIS97UIIStjYezOycGpgVou7rM5b
+ hY9uoCZ3iBObhlNbVjO7Jye3LEfWjVmLhJ5ZXfIUDAT1znntdkCuG4MXd6sll6sGx8CevYRfuYB0sESf
+ IKIsiSgbC5yFiTYSIaEDE0PC5BDqqnAVuKaSBlpb4dQJ+RdvdPPK7erIrlGJerfuyJ89q3jSVFUfrkxS
+ VyJoqOprwwzROsYYHXO0zikM+qwB6ao94cNTvYwsi9beE+3Dhq0jhMYhTCMPU81Bl3NQVVxMFRdVztau
+ 4OiUs3TKBhBFTK2CXlh+r1bxAKKcjawE0ueiKtg6Zf1a5WyduiFM/Qi+ZhhTwwM/i6rg7BebipnEjA5k
+ OhmZ0YFJa0cntejGN2jFNmpG16sdyG2zj2iQ8i2U8ylU/1qCeJ2l/CDx2LcKlbAW5Ndi+Z/F8omN2sDm
+ F/YY5dP1Yls0flaJ/6oTSelWL2EQKBybmdnLXK4TjXWSOnoqs0PLp/jQp5Ij+6vtGmA+NVq+VboRbQap
+ PRZZvdYZvZaZA1apfWaRHdjoLlxIG+prtcaHMtV3xcqfy5W/1agGNqpFtCnFUwAvV7N4BFU8Qiwc1c/i
+ EVPYuCQWLpGNje3XjmMpx7JE4zh/JnJ/S+3/PYt5tHkSO7Fzfgt6sAs92ISuzW+7MPkGILTXTCLLJpEF
+ E1qpPPmYvmORjEOx/ccS+48VcEVb55QH1nXHt0nTu5bj27asVXvqol3VmHlKLzaThS8e1GsZPzm0cn5+
+ /cq28DUExbe0vPG+b3r1rv2lW45eN+0ueNucdjU4aY/FEkVUYQfMTv5HaaONALo2sm05sErqmMM2TuEb
+ pvUap4xoAmfO6iva6M9vYa5wzH/iDcT0DOUMTeRcXBGBvp6FWe9uXyXmZb6BIKpQWL22FTu38mZ8+crU
+ luPkjhVv1YC9qN+/ZNC/ot8jIJGnTTqnXXNand4HE7zuK1+8KX/lhtLzF6Rgf6eqoierixkQlL0L+U8v
+ XhieNxpfIsyukxZ3zPgbFkvbp9cg11Whq2DXfmbr5Oiq2YCAQJ3T7ZrV6ZyDt02pNw6pl/ZoJJWpfwtW
+ ffRY9fJ5uIO55ik9DScL7WsX9S556jo5y7m7q3t6YJ3tiUQsXENFCoMSdXGR+xVGIDPODoy5Vzebh0Yg
+ XrxU83CVNydK6CNEidri+hhZUyMVc1NVCwPlEyQ1VwuEtxvy/WvdxGxcNV0flHuquEig17IBeEm/dtEA
+ ohAoe0CrsB+Wx9TM6dXI64Pn9MKy6LBsOrygX7eEg67gYSuHMCUD8CKmeiFTrYwNqxlC1A6jKrn7b4Oq
+ IWLNiH45h5jbg8ihIvLpILqjk9uBytVjGlWiGpUOgC0fgWWSX/MUf5ajk8GARb8TGCP6XCQf1AD/WaX6
+ uUAysFItrgmVTTXKZxql94BxD614mmpcp0p6q05dp/EY79zskNv8zDnBzmXqrHVyt0pgk1hQq7w/oB01
+ gdW7OkEgi9lhlNN7MrnbLJFqmkI3C2zQDWgAg9VY/waEbzX8SyXMt1Lbv0YnuA4e3aIW1SwVT5bO7lMv
+ 4mLyuLgUlk7igE4SC5XIQceztaMGFCKZxyOZ/4pi/k/OiGjzEoq9ZS+AbkMQUOQ7CHq0Dl2e2LDrAbzZ
+ GUCiIlVPY8qntHIHZRLA/DXjYGLfwfzBw218Bdaa1tQ2aQk6LYDOjm64sdfc22ccc0GNjW1cNmjSOmrD
+ E7jPrnourt+HoIiC4iv65oc9rhvdeOR49cEZrzsn3a6YuFzE65kewxn9x8efcPqYJ2vJmraMoKwAtKd2
+ 5f57DFM+gWudP8lYvl/LfPI57KSe9UGimQhM9y9Ftf82MpO8epng6YFyc9FsafaHoMaljWjO1P2BaQ+u
+ wGFo3WpwzZC9QurlE3vm8MxVPHlOq35Mq3HcLKXB7FUQ0uuR6sXbKp7Xle89xHz+ZBkd4TLMC4egMvCe
+ XN16PrfsOr98cnn95NqG7ca6496uuxDy2hZ6rO+dXdw6Ay7KvBXwKUGi8tGgY6JlVKGGJV9IUU4sU/se
+ rv7iJczLTcXWSNLWQPq6K/zbB6vgIKuIKPP0DJfM9Mv+39zPOevhUJLGBqIPHyGKK+0GJy9M8F36uTbV
+ tUaRYfC7NySszQ9aGB4yMzpmYipqbSdrf1bZzlHJ5oSc82nF614q77+ox+TB8ik6hf3wvAF4Th8sp08j
+ p1czu1czk6EB/tOzgcpZ8EymRipDLZWmlk6DZfXqFrIwxSDq87DVo7hyHqKUAysaUCseUC3jqFcOalUO
+ IisGMTXDejXDpFIWuqBPu5CJKB7AFPZhMijaMc0qkQ3yUY1yB9LrnL9kinzKUPpehAmqMQZJksgmfb9S
+ Vd8K+c+lsu/zJH9WakY14+Ja8VkMowKWccGgYQoTFdUKS6lDVzeZj3M9l8eurMxeXN+5NrbuWjkE6ALy
+ YWRZv0bJL7UgqQL/Wasb2oBLp1lHtxqFNhCi20jhoNeMjI2m4EPb0CC986Nex7cM7lcKi2hApnZiE1s0
+ I2tkEtuUMnpgyVS1BIZaMgueykEARHpsv1p0r3QU/WgE/fdoxm8lE7LUTaPBHdfxtev8pXtrq0+3t+5v
+ 711d2HblCix6Z0275y3IcyZdi8YdAlLdlFbFmHIhT6Z0UIw8p8hcVR/a0p2DzGeF9sObzqw11/YZu1Ku
+ RfmQdc3IqdZR297pM0MLjuwx56HRu9V1164/1Pa6Rbj52Mbr7gm3G0bnb5rYnYMRTP/75mNZ5vCN0VVP
+ 2hy+U6AKWFkAk1I+iSgaRxaPoeumzdpnL+R1nXsdgne/rXj5LsraXlEX9S93D/ibdza/fl1sbw8Da0TX
+ NjJ50y8ZE+69fLu+RYv+ddP+NQPmMomxQKDMosiz8NoxxbpxzYZxk+RGsxfB2peeKl97CLtyS+PuA+Sb
+ 10a/fpyidH4T7lVDUO7O9s+VpXsrS17raxe31j13Ny7tbl/eE16FoCt70MX1XefpFcvhZSPWMpE8CW/g
+ yTVwJauZEkUdMmmVKtEZut9/YS55SNqa/O11RubLE0xuolNTnVc3xbuf8ay77WVOyvXn94ztrSQ8XMUj
+ Igx7es9Nz5+bX7AfGT5B6TTKToe9fnX8nNvvzk4H7Z2OnnQ85OApcumB8pV7aq7npV1cJG7ekfsaqhZT
+ oZrSpZzGUE4Dau7VSOtVT2eop9PBo2b6/lONtP79k0hTTaJpZPQhQLNXAQdXyMGUAqGP46vGUKWDmoVs
+ lUKWStGAeglbq5KHqx7Sr+DqlbBwRUxkGQdVxgWBHwWe5vdhEtrVI5rkIppkDuS3ef7Ik/2YpvwpS+tV
+ knpojVFkg+HPMtjnMplX+aDFXO57OSy8ARtWh4prI+SzrPM41gk0/dBq1K8kzaRkHKXJhd5iPz7otr19
+ a37Do3XCNIepE0OR+1Z/7G3psW/1YNk0yrcUHliN8StFfi/VDalDRbYCeDQ+loIKbdUKaoEHNmt/K1X/
+ Xgz6t2zIUxeq++2z2/UyO1DJHWox7TKJdOX0/Y0XsES2ahygS/eIx1KPhHb8bxTl9+Ih+Y5FfQr/VBPb
+ prTBoKaOxOacWl4/t7LpNDpnzpm14C7aDq47je6cm4Y8xoUu7A1rKl+PPArvmlalr6j0bqqyd1GsTQPm
+ mlUX36p21KhiyLScd6Jy8FTLhC119lT3uGkH06yl9dTg4LOxudBn74yMToidOqtu6qSIPyGprfff9u5/
+ 1DQ78te9p9Yd2CsE2rJGmwDwgMB1FlE2gSofx9ZOmTVN2Rb32n5N1L3wQNzrtrL3be1LXqpv35mEx3iQ
+ OwL3dluhvfrllYSRuefMORfKvCFliUhdM6KvGtAExO55ZPssrHZCuZSnWDUGrxs1S2ywfBagceGBxOV7
+ StfuaNx/iHz1Uu/Te+Pc7Nvz89kQBBoKEnZXv2+vvN3bfgPtvtrbfgL6mXf2vIV713Z3PFY27KaWjHlL
+ hD4+aAdSbOBKtwxJtQ7K1PbIVrRrljcZRCdhrl3728P5rw9PtdKjrbrqL42wHk8Mvh5jfRns+dpc/jD2
+ 18kPj9UCvqnX1pgPDTssLNgtzVlP8czpXaSiIrUfv449ePyX9+1DF24edbz6l/uDw/e/yD/xUb3yQPL8
+ 5aMPnssEJGskNGkk9Mgn9MmD1eHxdKX4HoVEcKjKiT1q/xyV+G75eKpCbJdSUg8sg4nK6kfngk5dNqZ4
+ CFc1pVc5iSnkaeSylXIHVIG9ye/TLWERytiABkfIpaFBH2/FIBFIv4SFLOXgCweIaVREHFk5vEX2QBHZ
+ C9w4P2cqvk1VepGk5FcMxjGw38EQdIXyhyKZwDrEz3JYUJVWYIVGQLlaOtU4hWoc2UoMLMN+DFd9/k7s
+ 0wfxkADZ4hIMk2vHnnZoHDYp6AdkArCDV+xjudinMgDS0P5RpuNfjvQp1PpWph1Qgwit106n66fRAUUS
+ GBjAh0H+LNYIKtGmzlwXCH34m58nV1/SZi4W0oiJZKVEhkIa2MbIUo7pl4+mS0dRxKKpIgFt/wrtPJg+
+ IFs+hqoeMc7pIAQmiYfGHW7vwcwt28ysWnH5BtxFq/Et56ldj9kdrxUI/M0XR9ftWAIT+iyia1YJzA6T
+ BdLkecWOaa3OKVLLmGHNoEH1kFk527So17CGY9I2YkodNWdwbZhMV/7cy10opqTy2inHg1izA9iTB7RN
+ D1x5olza5Dy9fGtuzX164/TwGom9odu3ju5axjTOI6umdSqndGumAW3Gon7cNqP1xItfmudvSly8Ku/p
+ Je91RenyDdWIqAtzs0XAtwiFORtC/4nN67R5064FfOciiTyPbZ3VaZ7RqJtWLpuQLRlTqJqC1YKI3mT6
+ +Kfi2VtHLt6WvX5H4+59nQcPdJ49QX7xMe2ift93L3vJwp0w4Q6wQz8h6Ack/ArtvRPuPRDu3Njevriw
+ ajMkIPULkLQ5DfKYQueYHH1GuXdalcpT6+FiKQNmOSWYtx+Of/4on51s1VJ9Yaj/4fz4G/7Ep7kRv9nB
+ n0PU95Rq76YSR3LjaTbLbnzSep5vtsQ3mxo2onfjKqo0ouIlP347/uS9iPfLY+cf/Xn5zaEXIQrvQlUf
+ fpa+9uDvpx9FQ7NVUsiqSQzpWIZENEM6hi4bA/ibPdLxNPl4muL+6ZGL7ZaK7hSP7ZZPpmum0hFpfahs
+ Fi6XjSsawldPGVZO4AuGtHLZatlMtX0Hz9DJZ+LzGficHiwQenE/vopHAm6+hIMqZeML+vHpNFR8h2pY
+ i9yBiu6rsfUaPjmyr9Ok3mWr/KzC/KrDfavS8avQ+FamHtEMyAFIvxKFj1kiX/MlIxu1w+oQvyrQfrmo
+ 91Ga996L3Xj8+6svhyLTVau6jOr6zHIpmCwaKp2hG94GdgfIvi+U/lioFFSNCa0n+pXr/qpF+lfCkjoJ
+ 7QtnG6cdMhkGUW3I2Hbsr0LNyGLM6BLw2dEgnQdBUYu7nzvHzhX3EXO4YG+6CmDqhvdJB1NEwyhiUXSp
+ n60HgzqPRNEkwjulASsmqV0nIOt4ZPbf5H7tEYE+m48BtCrqvB5TcGJoyXl69cLq7tXlLY/JFduhFRPG
+ knbrrHTjvFgTX6J2TLx+WJk8QeiYMOuYPNE5Y9cxfbpxxLSWRWrlGvWOn+aMOk9OXtzaAElGv/Utv4rG
+ s1FZZiFZRr4JKMqIN3/v4diiMyj4z2xYTWzoj2/heZt45hqBsoZtXoJXz6lVTmvVzeLaFiybJhwjS0hX
+ nom6XDns4nnc8dyRW/fVq2peb23VQVCdUJi5CwWtCp9NrJ/tE5i2zeKbJpENE5p1s8pVc3IlM9KlM4qV
+ 8/C6aYPMDoOXoXKut/865y1x8Zri5evK3jeV79xVufdAPb/42tZ2CiSMgYShQmHgHhQohIIgcIDWtx/t
+ rl9b3zg3tWI5sIACbYxUvnLPnEL/gurQMmx0UXtyETu1aDQ2a9kFQJllWuWV+J5OVx7z9tz4c8H069X5
+ r+vzAatT/osjPnzuq1nenYnh8+NjpyemjGbm9RaXjKenDei9qOpGjZR8Of9Y8XdBIve+/n310++3f/71
+ Nk7sY7zUi2CROx/+9/WvPyPLpNN65JKY4jHM41GgPbtPLIx+LKLnWAxdHBBn/zli0d3HIjqPxlKlkuhK
+ gAgAuFfZLEIeh1Q4pF85YVwxpl86gisYBMN16kmdaikUeAYNlU1D5/Sg/xE6rm7EoGoIV8zSLWHji1mk
+ zB50HFktokn+QCPjZgmDGF6l8TFbxqdYI6xVL7LDADAtwpsB6whMQyNCG7XeZR95mfrbtyLRiAZ1/1KV
+ 9+nK75I1PiZpvwpXfeIv/SFSJixPI6+dVEw1TG7FRDVp7QOW6ADgq+FbpfI8XTygGhXZZhTYiA9uQH8r
+ VspjGA9BN3vXPSu4J1IppMQ2QkwltrTDbnnzBwQlQVAaBCULofBB/oNqllXhMDJlUDW6Xz6IKva16a8f
+ bYeCuo9/afzta8vvfu1/fmk4GNwhF9WuFFl7PK3xSA1dqp2n2Daq3DipWT+m0zSEZ0ydHJp3nl9x5687
+ T22cGtk2Afz8wsGDpZNHqxckKiYla8fVKHxD+sIp5qITa+XcwKpz79IpyrRp97gVY9SOO+4qWLyyu3dn
+ T3h3R/hgRfhgdO0mY86TuXSlX+DBW3IZX7MfW7OY2jKb3TWe3zUa3ySywFz9JpK8rl4jkKuel29c0mxf
+ wZEXLUqZpu8iZD3u/+589bfL98XTc8+vreeCNhXhXikEpUNQyB70YXXvFk9g3z6q3zSMbRiG104qV83L
+ lS/IVvCVqgHnf55YxjIMKoBff3fcxfuoo6fI2UuSF69IXr8p+/qdVmEZaFr2E+79EAq/QJCPEPoKCX2h
+ 3W/Q5ivh8pV1gcvcoiUH5NHBGPWCHBg+Ygjkh1Y15jbRixv4zW2T7W2L1Q3Lab7p8KjxEM90ctiFP3Zr
+ afrx6uzrDb7f1kLwjiB8eyFwa953Y+Hl7JQnb9h6eMJgdBY/No/jTuM7WToVnaqp1TKh+eJ+6cdfx/z9
+ JPqPZ/G/v884+DX7yMeUQ69j/sc3/Y/YZtEUulgSSySOcyyKdTyk93AA/e9g2t+h1EORPUej6ceie49G
+ Uv8Kp/wV1S0S1SUVSVZKooKIrlfIMykdNS8dNSnk6RcMEnJYANOlHktWS+iAJXVpp/cgcxiYXDq6qB9b
+ P2ZYN0Ks5uLqeYa1PLMqjnFhHza9U+tAE927nm2U2oz2y1faxxp16Ee3E32KlOM79eI69AJqNL+Xy77K
+ /P1L0aHwFqWMXkJgjfqrFLkP6Zo+2chPGTpfMrX8C7SCSjQTGkHyUg+ANX5WwMOadVNZxuGdup8rFF/k
+ SP6oQUaQTcBb6Hul1qvk42ntOM7W1d4lj5rBk3m9JsnthJwOM9rEjbkVn9WVkLWFyL3NRJAVnlh6Vc08
+ lcvBZvJ0Y5lq/p1i39uOBFOPh/eKhPYeD+47+q7xPz81/SugSyyCIpnSI1Y8IFrJFqlkiZazpSpG1KpH
+ EbU8LHXqxOjK2ZkNt9F1G+6GKYD1lI9KJ/X+Dsi9WWPHCiakamY12xaIrdOGNIEtd819YPUMdcGMMmfa
+ M2NDHbFljTuubV3dhS6vbDksbNrObtt1TxiA9v/OeRvmmhNn2WFo1XZ4w3Jq12oeslqAzCa3iexVBH0d
+ 1rGu3Lgs07om17Wt0rGu1rEM+qgMSnv0gkDz8y/piDQ9Fg/kiLIgKAeCQGYwFoJ+CaFPmztPJvie/ZMO
+ AzO21Am95jH12mnZqnmZqnmFmln1VgGudc6kpN/kZybi+lupM5cPOnkdcvb86+od8ZRs65Gpuxs7L3f3
+ Hu1Bd/f27gih+9DeA2jrgXD16ta83TLfbJwPhv+VugQSbYvHyQsiPQKpkQ3Y0iZhY9NQuGUObZrvbpps
+ rBuvrZisCsxX5+zXprxWJ2+uTj9bm/HdEoRB64nCjfi9jUjh9s/1tacTU659g/oUjlb3qHbHqE4tR6OI
+ rpjeLh3bIB5Sfdyv5IhPyaGPRX/4lP75o/LvnxUHAyoPhjYfius5ltR/PGVQFOA1IwaO/qL//ZN2MJB+
+ MKT7j+DuP8Jof0bQ/4yg/RFG+TOk/XBg87HABpnodp30Pr2iYfPiEctCnmkuWy9rACzGAjAjrYRu7aRu
+ nZRuxL7Q6SDfgitkYisH9ZtGjGizp3rnHemzzn38s8wF565JmwN1lCuVvXpxNTo/C1QT2w2imvAxbfjg
+ OlhUCzq0QTuwFuCKJN/nH/atEI3q0MhmGYY3677NkH+brvwmTeV1qpJfkfbPUs1fZWpB5WphNYiQWuKP
+ cvT3Kt0oil7agGlAs9bbAtkvFfBoikVYq75PkeqbFNEMMr5nzq1z0rGCaZZHN4xu1E1v1+8c8+zheTe1
+ exUVOdN7n67thvIEz0rpJ/LZ+gVjBtG9moFdUvFspbQh5WSebPqEQvyw1Lu6Az4tfwVQxCLp4hks0SLe
+ kdKhIyWDogVsqcw+0NelkD+g3TF7Ymj73OiuW/ecUc2IVuWoej5XLoryt1/Lf/t3/Z7IEauYh9XPo8qH
+ dVpmjegCu65Zi6ZxYs0QoXHYFKDWKUPWM2vnFredxlf0mbMw2qxGw5hq9TiyVWDas3aaseRAm7ftXbYa
+ 3DoxsWs1um0wtIVhbQLgm1rbqmLzsmz7uhx1V4GyLt29okhf1mXwTVvYFuUdJi29ztOCV1u7Pzd3fmzu
+ +G7tft6DPu4K32xtvdjcerm283J999Hi9oWhFWMqH3SkyNTPyDbOqrUvojuXDVrmTuTRzL+lIa59EPV6
+ fujqi79ffpdrpjuv7Hkv71xY3nRe2bKfX7RcXjm9s+a0t+y4y7ddnTJdWdCfWtTqF0h1LB5q4P/ROHew
+ gy/KXladXcWsrhntbVhCGxZ7q/pbK4SNZdLmouEW/8TWnMvatBd/+AZ/7PWGIES4mSTcSRHuJQNjuQd9
+ XVm7xx492TqAqB/UrOCpFXKVsvtlM3plUmhS8d0SoWSRgNZjfk2H/Br+9G/6I4T8d3QPwD0AlYuCA/qR
+ kthS0UzxgO5DPykHAyl/hVD+COr6PZT6r32h0/8MpfwV0HrYv0kEjOpHk5HJdL08rnke1zSbZZA1QARo
+ gGQa2AMHYF3IZCoirQeZSUdl0pC5DExeL6Z4AExpWPTPOQ7Mn2PPewwJLo0uew0tnD9Q2nYhqx0ZWKT+
+ LVctoAwZUoOMaUMnUTDfimU+5Ij7lsq/zhb5WAhWp8v4lMtFtKCC6pAf85RfZyg8jBG9EXzwVYrUp2zZ
+ kCpYYKmGfwk8ttUqpNbkWzHqVxU6m3Minop/ny/7IksuGKQsq1DvsxX88pQqmJbdk851LPMsMiaZjPEv
+ UwooU44BcxvVpNgC0s8YnaRCs67hmy2889mdBoWDxmXT5vFMeBhVNm1IPWNYNYkjnT2plMST/VD7L58m
+ kbAeJVC9T2Mfyx78V+Ho36C8n8WRBtedmG7pJLpq5bgRdcWxd9WZPGNZyNDKpqnn9KnHdcm+Lv7tWcl/
+ BHYfyh1XrAYLaSdhZTx4BRezf2HnAuKkTjYdVUDDVvRi65hoyii+l49sn5RqmBCpmpQpn4HVLhKbl82b
+ pk81jts2T1u3zZp2zBOpoDN2A07bUCWvKjYK5Bv48u1LQOWylGXR3lVpzjocVGqY0xbcORdA/hid8xyZ
+ 8RgYcWBwTw5OOArWrm5sP9jdBd28fiC6QxCwH/dWheATA0WZl2mflyUvqJEFOuQVQuuiWe3EiRy6aWQN
+ KrxCO7oCltOGo0xYc1Ys+vmE/lkd+phKz6DS4ITO3Ize6qTx6qjxwrDhyqzB3DKCtSTTNv9X3dzvdfMH
+ G2eOkqel+uc1JpYIq6vmOxvmexuG2+v49WXcmoC0sWC6wbdZmXMVTF8VzDzdXvOH9mKApYSgFCB0IeS7
+ B72aWznPmDZuHNPN5SpmceUyWNIZbOkUlnTigFRsv1QoXfRHx2Hf5j++t/we3PVXVN/h2P6jgLaZ2CuV
+ yVZO61OMp0pFkEWDWo+Edx0L6/orjPJXRM9fUfSDEbQ/QygHA9pEAJ85olM7tgsX0wny0chYQOSiIOMo
+ OrFdsMQe7RQaMo0G1gcBlaNz+nFA6+mALQegnxzD1jEAz3Kmj7vRR90Gxj1G+V7gV30gs8EpvEr5Z5Hm
+ lxyND9lqwXUoQG2M74T5FIu9SD30PPXo4+Sjb/NlQGB+nScd1ID2LdP6Uqb5pVTjWbLEg6jDr5JFP6RL
+ BFVoRtWjA0oR8S3W4bUWAWWkgHJUYhdxP7XSjnqTKRNYi4voMHqXLf89X7F6wJI+51zHNslo1wmqVPhW
+ IuVbIuFfLhdYqhJejoipJEWWETLbzTM7jdIpuOx+bEqfVnSPUkSPDGi9SmHJgl9Wzrgi2Ob1qfL4zxaV
+ aLp2xjCseEa2ZOZQyfTfBVOiOWNyWcPKGUPqKRyNfND2ueLAWDnLXr1In3Upo5OyOrUS2tX8aiTflv3x
+ tfG31EGJ0mn54lGZHKZUUpdkcrdiKgOWRNdK6tHO6kOUczFNI4TOaSJIZrfMS9QtHCubl8ifVSxd1q3b
+ MKqds66bdKyetC3m6RcOagIAAXlDsXVNqmlJumZOtmpCrmUOzG7KM9YlBrdlpiGtuV2DuU2QFHKdFDhN
+ LNoMz5sxhtFtfSq0IcTEovXa9pV/al4gYRLxT87k8S7kxN/FDG0rM7cV6VsqXeuwzk1C64pB7Zxh5ZRx
+ 5YRB06xB+wKJzMeQBcjaKeXGGfnWKcnGoaN1/YfoI8p8gcHu8gkQ0bfmnbaXbBZWcGyBbPvcX/Vzv9Xx
+ /6ydO9Q0J9a9qDy0iuGvG21vm0GQKSQkbW5gNleJW2umK6tma2sOezu3drae721/3lz7srX2HdoNgaBg
+ CPoEQc+3oMsj61bgXy8cVcocks4akswalkoblk4dkU4Zl0sekw8bEP/RdfB7x+/+lN9C6L9H0v9M7BMr
+ HdchL5p2CMyap/RqR7GVw+jiEVg8QySqByz2AdSTY8DYJLBATkYhsgcWS0Mn0QhxFHRQo5p/rWJQk3J4
+ m0osRSO1X2c/89iHyWZicgYweWxcLqBi9KKyerGFHNAAY9055tA9eraL69I34jGzdG1i1uNAVrObf5HC
+ +1TlT5mw95nq30o0I1p1AmoVPhdJPE87/DT5yMsMcdCT+CJT5mWW4utMtceJCh8KYN/KEa8z5D9lK7xL
+ k3yTLPo9TzGqBhVUovstE/M1Ax9cZuxXgPhWoprWq5/LNv+UB4ZKAYbO7mO+8rsU8YxWbB3bIp+CSm6F
+ BVXL+ZVLgdbfoHqFgCp5/xKliFpsRA0hsh4X24EDNXlw7/5Wefhn4/HIHvmYHtlUllwiUxz0nQe1ir3O
+ FfWtAts1dDIHkVUL8BqBeOH47wXjoqUz8NIZdP4EGmzijWeo5XEAa9dxcvvFCvRtRPCIMnq2mG4c1aj+
+ vea4T/X/hHcezGJLgD6wnH7phC7xJKpiVr8uqFMkUtSA82meIA2snBzasqXOY+onpavmjhfOHk8bE8sY
+ Vyzl4xuX7Jv4Z8vGbHI5hAyQ1h2WLpuVqOCLlc9KlE7KFA3JVI/Ldy6q9q4qD22q8iH0OmS6Bzlv751f
+ 3nBa2LCYXiWyZjQoI9Kdw/LsedzitssedAeCQEeADyj0CqHr25DtGkSYgTSYmzLUNTnKBqx1BV09iyqe
+ QJVNYeoFuI41dNeGduOSXMmUSPbokeKpY2Xjh0rZv1f1/UUbUeEvWUC7HtD2LWjnCbR3c23Tjjuv1T52
+ tGb09/LR30pH/6qbkeha0GAv4WfXTLd3rCHIQrhDWltFrazg1zeNljdNBGs2S+sXBEs3Bgc9u9rPdLc7
+ jbG8N5efQ8JHQujmmtCdu2rSPAMvHJVLAVgetnjaoFTqsEzaqEzKiEzqmHIMV96/+9i39j/82n8LoPwe
+ 0f0XYN5TViwnII9Z6NLk7oXhddeRnXN9m6dKRjSTesWTB8QzhqSzxxTTeCopLHhCLyqOhomjYMLbdb7X
+ KvlUSvk3A/q+WlSHShwF1E11s3sJQOuZTGQaA5ECEF9dyOgWncQOTCHNpIxqnt1IyqkjNFKt2GMunCGH
+ /wd6M4989rNkxAAAAABJRU5ErkJggg==
+</value>
+ </data>
+ <data name="panelHeader.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>
+ iVBORw0KGgoAAAANSUhEUgAAAAcAAABWCAIAAACM4hvWAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAOxAAA
+ DsQBlSsOGwAABnlJREFUSEstlFlvG9cVx6/0Bbxq4b7NcBZKceA4TRAkafoBnMiy5TayaCMFWqDoQ4H2
+ KZZkiZydiyQuWl03iR2L2i2JywxnOCuHHJKS7TZp2iBAP0Qf8hQgyJUT4GCA+5v//M85c++5fdI/+f//
+ +L/vv/8B9Pf/2Af6+vr6+/vBhnoz136NUUhKiyW1Udq4wlivg8/NKb6Ozxyg94+wT8vYp8f4dIUAX1jx
+ VIN8cITNVLDpCna/gs3WCPC4GU9r5FwZe1DFZ2v4TI2Yk2Lgy9bdrDGSqOJJiZyXCPhiTiLBUye+aMWo
+ GpaUiESdmKvjCZkEm87dJYukqmhCxOYlbF7GEgoBaXzRJF9p8VcUp9QY2OzE861RViZhyUmFSMLCId3q
+ 3i06r3EKwSokrZK0PsLoMVDqxgttkqlHmQbO6gRrxjhzBDpMFZwYK2OMgv1CrRFQ6kwVOzFeI1kVp3Wc
+ NUjOgtm6Hxe6uHC2xhgTp034xECpN5nvYIIeZU2MbeKMFaVNFOy8iBd7BKdhtIbCNQymGQU7L+8Vu9AX
+ pzSUMaMQcTYKtp7fyzkEp2K0jlEGCh14Owq2T+8uOTir4ZxF0DqUo1wTBaXTqWwLpRswG84YEGFCCwel
+ F1MLDkopEVpDGCPKW3imRYLS8zuQ0o0IpaO0DimRsSE9mVxqR9kGRjWwJHQ3CMHEwdbJZB5SBaMUPAmb
+ 1jBWQ8HuyZ3lNibAH6aRjE5Ayr2i8RWHSKkEr8d4IwYdeAP21ouvOmS6gfMqwekwMN7AfqGCAj/EeB3n
+ 9WjqLFtnarlFpOQo38B4DRO0aAZqt7rxYgsXIFVQXkXSWjT7My3YOC+hvIzwCpJRo4s6Dna68WUb48Ww
+ IIfTDWRRw4vmKNjrTK3ZWEoKpeRw6mcKd3O/G3/YIjL1SFqJpBtoVo0uGTjYd+48tPFsHcmc0UhaQ7IG
+ CunkmhXNSJG0DK2DvOJPa0Fw0L2z3kQyUkiQQ7wS4GQvr/og/Xi9GUqLfl4KMJKfkTyc7AYHvd+u28GU
+ 6OVEHyN6GdHFSsOwslsrlo+vupmKm666WdHNiMNgq3k9rwxyZQ8Do+aBiJWGQMm8npMHmWcu+hiq3Iw0
+ xNaHwHZzLN9w04du6niYqg7S4mVWvAy2W+M5xUMfuqjycLJ6mREvsrULkN7MNbyQ0pWhZO0SK13k6+fB
+ Vmsip/qZYw9VHpgvn2PEc2d0s3VzSfMyxy6qMpCsnufkc4J8ATy1byyqbqYMUw2w9csZfSCjDUDteE73
+ CqKXl4fZ+qWUNpBRB0CpfbNg+SEVZDfU8sqlFKTbnYkVO5Sq+3nZzSuDEKWhQ6l9e9mOZBvhlOrLGp4F
+ czhrDoKnzVsFI7ygohk9mG16l2xXvuUCT61bOS2YbUAaXrADha5vpeuBdDwPVQ00pYUW26G10/D6SQCU
+ 7I/ypj8F91EPLzmRtVNk4yQMtttjBcvLK6GMhS610eUusuqEzmix6WFlH2+Esna46ESKVhDs9m7kmi5K
+ dHNGINsKFdpIEc7x/uk4LIWquwTLv+hALVrQ4XT3PspZA0lxkNM92VYwf9ZRCJ7J6wva+UTlIqe5M61A
+ xvCxVQ/0HSu2XLQ4yBuetO0XNC9d9ULt+GonICh+WEC+h6bNECMFwU7n9mobTSmRTBMtnpKwF1YMg93u
+ 1GqLFGREMCIZG+FUeAbhZHUmCxbCSQjXQBJ1H90IpfQRsNUbzze9rBhklEii5kvWA4JGgO2TD3PNIbrm
+ ZeRQUvTPHA1TYhDsv/xwxRnkJDcleuZF7/Th0OyhC9T+M/74K19W8ybKQ4my58GRa/bZMJC/nSh9E1rU
+ fFTFM3/knd5zTe8Pg+q/bn1x6s/KAaYSnt71/eWzC397chEcODfWTY9wHOCOcb76+uwu8tfHl0BJH8uL
+ bv5ZeEG69uXLse3/TqSlUbCl32Z3BujtSKb8ZkH9ze43v9tovgcOnU+yz/xUCaF3R2ee4CvqBxvmr0G5
+ +/tVeH3vhOc2I/efRNKVN3LKr0D9xR//YRDcvn+25JnfQxeUN5f0t4D19Z+rX7+zphDUno+rEKvtdzd6
+ 74PmV38yvvtg076WPoxsNN961Hvv7513gP78D/K/3/1MvbJwFH3cef9h8+1Hztug5tzb7VzNl/HUAZYT
+ ry6rVx8518COObGmIAtlkt0nkntYUX/j89NrYNeeXCyHEpsIvRNL7OCpKrnevvITI0lytudA8kUAAAAA
+ SUVORK5CYII=
+</value>
+ </data>
+ <metadata name="saveFileDialogExport.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>17, 17</value>
+ </metadata>
+ <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>171, 17</value>
+ </metadata>
+</root> \ No newline at end of file
diff --git a/chromium/tools/stats_viewer/win32.cs b/chromium/tools/stats_viewer/win32.cs
new file mode 100644
index 00000000000..18c4a8d4792
--- /dev/null
+++ b/chromium/tools/stats_viewer/win32.cs
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace StatsViewer {
+ /// <summary>
+ /// Win32 API constants, structs, and wrappers for access via C#.
+ /// </summary>
+ class Win32 {
+ #region Constants
+ public enum MapAccess {
+ FILE_MAP_COPY = 0x0001,
+ FILE_MAP_WRITE = 0x0002,
+ FILE_MAP_READ = 0x0004,
+ FILE_MAP_ALL_ACCESS = 0x001f,
+ }
+
+ public const int GENERIC_READ = unchecked((int)0x80000000);
+ public const int GENERIC_WRITE = unchecked((int)0x40000000);
+ public const int OPEN_ALWAYS = 4;
+ public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
+ #endregion
+
+ [DllImport("kernel32", SetLastError=true, CharSet=CharSet.Auto)]
+ public static extern IntPtr CreateFile (
+ String lpFileName, int dwDesiredAccess, int dwShareMode,
+ IntPtr lpSecurityAttributes, int dwCreationDisposition,
+ int dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+ [DllImport("kernel32", SetLastError=true)]
+ public static extern IntPtr MapViewOfFile (
+ IntPtr hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh,
+ int dwFileOffsetLow, int dwNumBytesToMap);
+
+ [DllImport("kernel32", SetLastError=true, CharSet=CharSet.Auto)]
+ public static extern IntPtr OpenFileMapping (
+ int dwDesiredAccess, bool bInheritHandle, String lpName);
+
+ [DllImport("kernel32", SetLastError=true)]
+ public static extern bool UnmapViewOfFile (IntPtr lpBaseAddress);
+
+ [DllImport("kernel32", SetLastError = true)]
+ public static extern bool CloseHandle(IntPtr handle);
+ }
+}
diff --git a/chromium/tools/swarm_client/PRESUBMIT.py b/chromium/tools/swarm_client/PRESUBMIT.py
new file mode 100644
index 00000000000..59619ce3506
--- /dev/null
+++ b/chromium/tools/swarm_client/PRESUBMIT.py
@@ -0,0 +1,62 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Top-level presubmit script for swarm_client.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into gcl.
+"""
+
+def CommonChecks(input_api, output_api):
+ import sys
+ def join(*args):
+ return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
+
+ output = []
+ sys_path_backup = sys.path
+ try:
+ sys.path = [
+ input_api.PresubmitLocalPath(),
+ join('googletest'),
+ join('tests', 'gtest_fake'),
+ ] + sys.path
+ output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+ finally:
+ sys.path = sys_path_backup
+
+ integation_tests = []
+ if not input_api.is_committing:
+ # These tests are touching the live infrastructure. It's a pain if your IP
+ # is not whitelisted so only run these on commit.
+ integation_tests = [
+ r'.*isolateserver_archive_smoke_test\.py$',
+ r'.*swarm_get_results_smoke_test\.py$',
+ ]
+
+ output.extend(
+ input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api,
+ input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'),
+ whitelist=[r'.+_test\.py$'],
+ blacklist=integation_tests))
+ output.extend(
+ input_api.canned_checks.RunUnitTestsInDirectory(
+ input_api, output_api,
+ input_api.os_path.join(
+ input_api.PresubmitLocalPath(), 'googletest', 'tests'),
+ whitelist=[r'.+_test\.py$']))
+
+ if input_api.is_committing:
+ output.extend(input_api.canned_checks.PanProjectChecks(input_api,
+ output_api,
+ owners_check=False))
+ return output
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/chromium/tools/swarm_client/README.py b/chromium/tools/swarm_client/README.py
new file mode 100755
index 00000000000..460d1bc2066
--- /dev/null
+++ b/chromium/tools/swarm_client/README.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# coding=utf-8
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+###
+# Run me to generate the documentation!
+###
+
+# Line too long (NN/80)
+# pylint: disable=C0301
+
+"""Test tracing and isolation infrastructure.
+
+Scripts are compartmentalized by their name:
+- isolate_*.py: Executable isolation scripts. See:
+ https://code.google.com/p/swarming/wiki/IsolateDesign
+ https://code.google.com/p/swarming/wiki/IsolateUserGuide
+- isolateserver_*.py: Tools to interact with the CAD server.
+- run_*.py: Tools to run tests.
+- swarm_*.py: Swarm interaction scripts. See
+ https://code.google.com/p/swarming/wiki/SwarmingDesign
+ https://code.google.com/p/swarming/wiki/SwarmingUserGuide
+- trace_*.py: Tracing infrastructure scripts. See
+ https://code.google.com/p/swarming/wiki/TracingToolsDesign
+ https://code.google.com/p/swarming/wiki/TracingToolsUserGuide
+- googletest/*.py: Scripts specifically managing GTest executables. More
+ information about googletest can be found at
+ http://code.google.com/p/googletest/wiki/Primer
+
+A few scripts have strict dependency rules:
+- run_isolated.py and trace_inputs.py depends on no other script so they can be
+ run outside the checkout.
+- The pure tracing scripts (trace_*.py) do not know about isolate
+ infrastructure.
+- Scripts without '_test_cases' suffix do not know about GTest.
+- Scripts without 'isolate_' prefix do not know about the isolation
+ infrastructure.
+"""
+
+import os
+import sys
+
+
+def main():
+ for i in sorted(os.listdir(os.path.dirname(os.path.abspath(__file__)))):
+ if not i.endswith('.py') or i == 'PRESUBMIT.py':
+ continue
+ module = __import__(i[:-3])
+ if hasattr(module, '__doc__'):
+ print module.__name__
+ print ''.join(' %s\n' % i for i in module.__doc__.splitlines())
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/WATCHLISTS b/chromium/tools/swarm_client/WATCHLISTS
new file mode 100755
index 00000000000..62433b6877c
--- /dev/null
+++ b/chromium/tools/swarm_client/WATCHLISTS
@@ -0,0 +1,24 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Watchlist Rules
+# Refer: http://dev.chromium.org/developers/contributing-code/watchlists
+
+{
+
+ 'WATCHLIST_DEFINITIONS': {
+ 'all': {
+ 'filepath': '.+',
+ },
+ },
+
+ 'WATCHLISTS': {
+ 'all': [
+ 'csharp+cc@chromium.org',
+ 'maruel+cc@chromium.org',
+ 'vadimsh+cc@chromium.org',
+ ],
+ },
+
+}
diff --git a/chromium/tools/swarm_client/codereview.settings b/chromium/tools/swarm_client/codereview.settings
new file mode 100644
index 00000000000..888dfc74a1f
--- /dev/null
+++ b/chromium/tools/swarm_client/codereview.settings
@@ -0,0 +1,4 @@
+# This file is used by gcl to get repository specific information.
+CODE_REVIEW_SERVER: https://codereview.chromium.org
+CC_LIST: chromium-reviews@chromium.org
+VIEW_VC: https://src.chromium.org/viewvc/chrome?view=rev&revision=
diff --git a/chromium/tools/swarm_client/example/hello_world.isolate b/chromium/tools/swarm_client/example/hello_world.isolate
new file mode 100644
index 00000000000..7827d3ca1c5
--- /dev/null
+++ b/chromium/tools/swarm_client/example/hello_world.isolate
@@ -0,0 +1,40 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'variables': {
+ 'isolate_dependency_tracked': [
+ 'hello_world.py',
+ ],
+ },
+ #
+ 'conditions': [
+ ['OS=="linux"', {
+ 'variables': {
+ 'command': [
+ 'python',
+ 'hello_world.py',
+ 'Linux',
+ ],
+ },
+ }],
+ ['OS=="mac"', {
+ 'variables': {
+ 'command': [
+ 'python',
+ 'hello_world.py',
+ 'OSX',
+ ],
+ },
+ }],
+ ['OS=="win"', {
+ 'variables': {
+ 'command': [
+ 'python',
+ 'hello_world.py',
+ 'Windows',
+ ],
+ },
+ }],
+ ],
+}
diff --git a/chromium/tools/swarm_client/example/hello_world.py b/chromium/tools/swarm_client/example/hello_world.py
new file mode 100755
index 00000000000..57ed44af2c9
--- /dev/null
+++ b/chromium/tools/swarm_client/example/hello_world.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This script is meant to be run on a Swarm slave."""
+
+import sys
+
+
+def main():
+ print('Hello world: ' + sys.argv[1])
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/example/run_example_cad.py b/chromium/tools/swarm_client/example/run_example_cad.py
new file mode 100755
index 00000000000..6c685e915de
--- /dev/null
+++ b/chromium/tools/swarm_client/example/run_example_cad.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs hello_world.py, through hello_world.isolated, locally in a temporary
+directory with the files fetched from the remote Content-Addressed Datastore.
+"""
+
+import hashlib
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def run(cmd):
+ print('Running: %s' % ' '.join(cmd))
+ cmd = [sys.executable, os.path.join(ROOT_DIR, '..', cmd[0])] + cmd[1:]
+ if sys.platform != 'win32':
+ cmd = ['time', '-p'] + cmd
+ subprocess.check_call(cmd)
+
+
+def main():
+ parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
+ parser.add_option(
+ '-i', '--isolate-server',
+ default='https://isolateserver.appspot.com/',
+ help='Isolate server to use default:%default')
+ parser.add_option('-v', '--verbose', action='store_true')
+ options, args = parser.parse_args()
+ if args:
+ parser.error('Unsupported argument %s' % args)
+ if options.verbose:
+ os.environ['ISOLATE_DEBUG'] = '1'
+
+ try:
+ # All the files are put in a temporary directory. This is optional and
+ # simply done so the current directory doesn't have the following files
+ # created:
+ # - hello_world.isolated
+ # - hello_world.isolated.state
+ # - cache/
+ tempdir = tempfile.mkdtemp(prefix='hello_world')
+ cachedir = os.path.join(tempdir, 'cache')
+ isolateddir = os.path.join(tempdir, 'isolated')
+ isolated = os.path.join(isolateddir, 'hello_world.isolated')
+
+ os.mkdir(isolateddir)
+
+ print('Archiving')
+ run(
+ [
+ 'isolate.py',
+ 'hashtable',
+ '--isolate', os.path.join(ROOT_DIR, 'hello_world.isolate'),
+ '--isolated', isolated,
+ '--outdir', options.isolate_server,
+ ])
+
+ print('\nRunning')
+ # TODO(maruel): This makes it not work with NFS.
+ remote = (
+ options.isolate_server.rstrip('/') + '/content/retrieve/default-gzip/')
+ hashval = hashlib.sha1(open(isolated, 'rb').read()).hexdigest()
+ run(
+ [
+ 'run_isolated.py',
+ '--cache', cachedir,
+ '--remote', remote,
+ '--hash', hashval,
+ ])
+ finally:
+ shutil.rmtree(tempdir)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/example/run_example_local.py b/chromium/tools/swarm_client/example/run_example_local.py
new file mode 100755
index 00000000000..a95c35a33aa
--- /dev/null
+++ b/chromium/tools/swarm_client/example/run_example_local.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs hello_world.py, through hello_world.isolate, locally in a temporary
+directory.
+"""
+
+import hashlib
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def run(cmd):
+ print('Running: %s' % ' '.join(cmd))
+ cmd = [sys.executable, os.path.join(ROOT_DIR, '..', cmd[0])] + cmd[1:]
+ if sys.platform != 'win32':
+ cmd = ['time', '-p'] + cmd
+ subprocess.check_call(cmd)
+
+
+def main():
+ parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
+ parser.add_option('-v', '--verbose', action='store_true')
+ options, args = parser.parse_args()
+ if args:
+ parser.error('Unsupported argument %s' % args)
+
+ if options.verbose:
+ os.environ['ISOLATE_DEBUG'] = '1'
+
+ try:
+ # All the files are put in a temporary directory. This is optional and
+ # simply done so the current directory doesn't have the following files
+ # created:
+ # - hello_world.isolated
+ # - hello_world.isolated.state
+ # - cache/
+ # - hashtable/
+ tempdir = tempfile.mkdtemp(prefix='hello_world')
+ cachedir = os.path.join(tempdir, 'cache')
+ hashtabledir = os.path.join(tempdir, 'hashtable')
+ isolateddir = os.path.join(tempdir, 'isolated')
+ isolated = os.path.join(isolateddir, 'hello_world.isolated')
+
+ os.mkdir(isolateddir)
+
+ print('Archiving')
+ run(
+ [
+ 'isolate.py',
+ 'hashtable',
+ '--isolate', os.path.join(ROOT_DIR, 'hello_world.isolate'),
+ '--isolated', isolated,
+ '--outdir', hashtabledir,
+ ])
+
+ print('\nRunning')
+ hashval = hashlib.sha1(open(isolated, 'rb').read()).hexdigest()
+ run(
+ [
+ 'run_isolated.py',
+ '--cache', cachedir,
+ '--remote', hashtabledir,
+ '--hash', hashval,
+ ])
+
+ finally:
+ shutil.rmtree(tempdir)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/example/run_example_swarm.py b/chromium/tools/swarm_client/example/run_example_swarm.py
new file mode 100755
index 00000000000..78848b2f59a
--- /dev/null
+++ b/chromium/tools/swarm_client/example/run_example_swarm.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs hello_world.py, through hello_world.isolate, remotely on a Swarm slave.
+"""
+
+import datetime
+import getpass
+import hashlib
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+# Default servers.
+ISOLATE_SERVER = 'https://isolateserver.appspot.com/'
+SWARM_SERVER = 'https://chromium-swarm.appspot.com/'
+
+
+def run(cmd, verbose):
+ if verbose:
+ cmd = cmd + ['--verbose']
+ print('Running: %s' % ' '.join(cmd))
+ cmd = [sys.executable, os.path.join(ROOT_DIR, '..', cmd[0])] + cmd[1:]
+ if sys.platform != 'win32':
+ cmd = ['time', '-p'] + cmd
+ subprocess.check_call(cmd)
+
+
+def main():
+ parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
+ parser.add_option(
+ '-i', '--isolate-server',
+ default=ISOLATE_SERVER,
+ help='Isolate server to use default:%default')
+ parser.add_option(
+ '-s', '--swarm-server',
+ default=SWARM_SERVER,
+ help='Isolate server to use default:%default')
+ parser.add_option('-v', '--verbose', action='store_true')
+ options, args = parser.parse_args()
+ if args:
+ parser.error('Unsupported argument %s' % args)
+ prefix = getpass.getuser() + '-' + datetime.datetime.now().isoformat() + '-'
+
+ try:
+ # All the files are put in a temporary directory. This is optional and
+ # simply done so the current directory doesn't have the following files
+ # created:
+ # - hello_world.isolated
+ # - hello_world.isolated.state
+ tempdir = tempfile.mkdtemp(prefix='hello_world')
+ isolated = os.path.join(tempdir, 'hello_world.isolated')
+
+ print('Archiving')
+ run(
+ [
+ 'isolate.py',
+ 'hashtable',
+ '--isolate', os.path.join(ROOT_DIR, 'hello_world.isolate'),
+ '--isolated', isolated,
+ '--outdir', options.isolate_server,
+ ],
+ options.verbose)
+
+ # Note that swarm_trigger_and_get_results.py could be used to run and get
+ # results as a single call.
+ print('\nRunning')
+ hashval = hashlib.sha1(open(isolated, 'rb').read()).hexdigest()
+ run(
+ [
+ 'swarm_trigger_step.py',
+ '--os_image', sys.platform,
+ '--swarm-url', options.swarm_server,
+ '--test-name-prefix', prefix,
+ '--data-server', options.isolate_server,
+ '--run_from_hash', hashval,
+ 'hello_world',
+ # Number of shards.
+ '1',
+ '*',
+ ],
+ options.verbose)
+
+ print('\nGetting results')
+ run(
+ [
+ 'swarm_get_results.py',
+ '--url', options.swarm_server,
+ prefix + 'hello_world',
+ ],
+ options.verbose)
+ finally:
+ shutil.rmtree(tempdir)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/googletest/README.py b/chromium/tools/swarm_client/googletest/README.py
new file mode 100755
index 00000000000..683bb75aa5c
--- /dev/null
+++ b/chromium/tools/swarm_client/googletest/README.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# coding=utf-8
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+###
+# Run me to generate the documentation!
+###
+
+"""Google Test specific tracing and isolation infrastructure.
+
+You will find more general information in the directory above.
+"""
+
+import os
+import sys
+
+
+def main():
+ for i in sorted(os.listdir(os.path.dirname(os.path.abspath(__file__)))):
+ if not i.endswith('.py') or i == 'PRESUBMIT.py':
+ continue
+ module = __import__(i[:-3])
+ if hasattr(module, '__doc__'):
+ print module.__name__
+ print ''.join(' %s\n' % i for i in module.__doc__.splitlines())
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/googletest/fix_test_cases.py b/chromium/tools/swarm_client/googletest/fix_test_cases.py
new file mode 100755
index 00000000000..3a751be8cac
--- /dev/null
+++ b/chromium/tools/swarm_client/googletest/fix_test_cases.py
@@ -0,0 +1,244 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs through isolate_test_cases.py all the tests cases in a google-test
+executable, grabs the failures and traces them to generate a new .isolate.
+
+This scripts requires a .isolated file. This file is generated from a .isolate
+file. You can use 'GYP_DEFINES=test_isolation_mode=check ninja foo_test_run' to
+generate it.
+"""
+
+import json
+import logging
+import os
+import subprocess
+import sys
+import tempfile
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if not ROOT_DIR in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import isolate
+import isolate_test_cases
+import run_isolated
+import run_test_cases
+
+
+
+def with_tempfile(function):
+ """Creates a temporary file and calls the inner function."""
+ def hook(*args, **kwargs):
+ handle, tempfilepath = tempfile.mkstemp(prefix='fix_test_cases')
+ os.close(handle)
+ try:
+ return function(tempfilepath, *args, **kwargs)
+ finally:
+ try:
+ os.remove(tempfilepath)
+ except OSError, e:
+ print >> sys.stderr, 'Failed to remove %s: %s' % (tempfilepath, e)
+ return hook
+
+
+def load_run_test_cases_results(run_test_cases_file):
+ """Loads a .run_test_cases result file.
+
+ Returns a tuple of two lists, (success, failures).
+ """
+ if not os.path.isfile(run_test_cases_file):
+ print >> sys.stderr, 'Failed to find %s' % run_test_cases_file
+ return None, None
+ with open(run_test_cases_file) as f:
+ try:
+ data = json.load(f)
+ except ValueError as e:
+ print >> sys.stderr, ('Unable to load json file, %s: %s' %
+ (run_test_cases_file, str(e)))
+ return None, None
+ failure = [
+ test for test, runs in data['test_cases'].iteritems()
+ if not any(run['returncode'] == 0 for run in runs)
+ ]
+ success = [
+ test for test, runs in data['test_cases'].iteritems()
+ if any(run['returncode'] == 0 for run in runs)
+ ]
+ return success, failure
+
+
+def add_verbosity(cmd, verbosity):
+ """Adds --verbose flags to |cmd| depending on verbosity."""
+ if verbosity:
+ cmd.append('--verbose')
+ if verbosity > 1:
+ cmd.append('--verbose')
+
+
+# This function requires 2 temporary files.
+@with_tempfile
+@with_tempfile
+def run_tests(
+ tempfilepath_cases, tempfilepath_result, isolated, test_cases, verbosity):
+ """Runs all the test cases in an isolated environment."""
+ with open(tempfilepath_cases, 'w') as f:
+ f.write('\n'.join(test_cases))
+ cmd = [
+ sys.executable, os.path.join(ROOT_DIR, 'isolate.py'),
+ 'run',
+ '--isolated', isolated,
+ ]
+ # Make sure isolate.py is verbose.
+ add_verbosity(cmd, verbosity)
+ cmd += [
+ '--',
+ # This assumes run_test_cases.py is used.
+ '--result', tempfilepath_result,
+ '--test-case-file', tempfilepath_cases,
+ # Do not retry; it's faster to trace flaky test than retrying each failing
+ # tests 3 times.
+ # Do not use --run-all, iterate multiple times instead.
+ '--retries', '0',
+ # Trace at most 25 test cases at a time. While this may seem particularly
+ # small, it is because the tracer doesn't scale well on Windows and tends to
+ # generate multi-gigabytes data files, that needs to be read N-times the
+ # number of test cases. On linux and OSX it's not that much a big deal but
+ # if there's 25 test cases that are broken, it's likely that there's a core
+ # file missing anyway.
+ '--max-failures', '25',
+ ]
+ # Make sure run_test_cases.py is verbose.
+ add_verbosity(cmd, verbosity)
+ logging.debug(cmd)
+ retcode = subprocess.call(cmd)
+ success, failures = load_run_test_cases_results(tempfilepath_result)
+ # Returning non-zero must match having failures.
+ assert bool(retcode) == (failures is None or bool(failures))
+ return success, failures
+
+
+@with_tempfile
+def trace_some(tempfilepath, isolated, test_cases, trace_blacklist, verbosity):
+ """Traces the test cases."""
+ with open(tempfilepath, 'w') as f:
+ f.write('\n'.join(test_cases))
+ cmd = [
+ sys.executable, os.path.join(
+ ROOT_DIR, 'googletest', 'isolate_test_cases.py'),
+ '--isolated', isolated,
+ '--test-case-file', tempfilepath,
+ # Do not use --run-all here, we assume the test cases will pass inside the
+ # checkout.
+ ]
+ for i in trace_blacklist:
+ cmd.extend(('--trace-blacklist', i))
+ add_verbosity(cmd, verbosity)
+ logging.debug(cmd)
+ return subprocess.call(cmd)
+
+
+def fix_all(isolated, all_test_cases, trace_blacklist, verbosity):
+ """Runs all the test cases in a gtest executable and trace the failing tests.
+
+ Returns True on success.
+
+ Makes sure the test passes afterward.
+ """
+ # These environment variables could have adverse side-effects.
+ # TODO(maruel): Be more intelligent about it, for now be safe.
+ env_blacklist = set(run_test_cases.KNOWN_GTEST_ENV_VARS) - set([
+ 'GTEST_SHARD_INDEX', 'GTEST_TOTAL_SHARDS'])
+ for i in env_blacklist:
+ if i in os.environ:
+ print >> sys.stderr, 'Please unset %s' % i
+ return False
+
+ # Run until test cases remain to be tested.
+ remaining_test_cases = all_test_cases[:]
+ if not remaining_test_cases:
+ print >> sys.stderr, 'Didn\'t find any test case to run'
+ return 1
+
+ previous_failures = set()
+ had_failure = False
+ while remaining_test_cases:
+ # pylint is confused about with_tempfile.
+ # pylint: disable=E1120
+ print(
+ '\nTotal: %5d; Remaining: %5d' % (
+ len(all_test_cases), len(remaining_test_cases)))
+ success, failures = run_tests(isolated, remaining_test_cases, verbosity)
+ if success is None:
+ if had_failure:
+ print >> sys.stderr, 'Failed to run test cases'
+ return 1
+ # Maybe there's even enough things mapped to start the child process.
+ logging.info('Failed to run, trace one test case.')
+ had_failure = True
+ success = []
+ failures = [remaining_test_cases[0]]
+ print(
+ '\nTotal: %5d; Tried to run: %5d; Ran: %5d; Succeeded: %5d; Failed: %5d'
+ % (
+ len(all_test_cases),
+ len(remaining_test_cases),
+ len(success) + len(failures),
+ len(success),
+ len(failures)))
+
+ if not failures:
+ print('I\'m done. Have a nice day!')
+ return True
+
+ previous_failures.difference_update(success)
+ # If all the failures had already failed at least once.
+ if previous_failures.issuperset(failures):
+ print('The last trace didn\'t help, aborting.')
+ return False
+
+ # Test cases that passed to not need to be retried anymore.
+ remaining_test_cases = [
+ i for i in remaining_test_cases if i not in success and i not in failures
+ ]
+ # Make sure the failures at put at the end. This way if some tests fails
+ # simply because they are broken, and not because of test isolation, the
+ # other tests will still be traced.
+ remaining_test_cases.extend(failures)
+
+ # Trace the test cases and update the .isolate file.
+ print('\nTracing the %d failing tests.' % len(failures))
+ if trace_some(isolated, failures, trace_blacklist, verbosity):
+ logging.info('The tracing itself failed.')
+ return False
+ previous_failures.update(failures)
+
+
+def main():
+ run_isolated.disable_buffering()
+ parser = run_test_cases.OptionParserTestCases(
+ usage='%prog <options> -s <something.isolated>')
+ isolate.add_trace_option(parser)
+ parser.add_option(
+ '-s', '--isolated',
+ help='The isolated file')
+ options, args = parser.parse_args()
+
+ if args:
+ parser.error('Unsupported arg: %s' % args)
+ isolate.parse_isolated_option(parser, options, os.getcwd(), True)
+
+ _, command, test_cases = isolate_test_cases.safely_load_isolated(
+ parser, options)
+ if not command:
+ parser.error('A command must be defined')
+ if not test_cases:
+ parser.error('No test case to run')
+ return not fix_all(
+ options.isolated, test_cases, options.trace_blacklist, options.verbose)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/googletest/isolate_test_cases.py b/chromium/tools/swarm_client/googletest/isolate_test_cases.py
new file mode 100755
index 00000000000..c2ecb126b16
--- /dev/null
+++ b/chromium/tools/swarm_client/googletest/isolate_test_cases.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Traces each test cases of a google-test executable individually and generates
+or updates an .isolate file.
+
+If the trace hangs up, you can still take advantage of the traces up to the
+points it got to by Ctrl-C'ing out, then running isolate.py merge -r
+out/release/foo_test.isolated. the reason it works is because both isolate.py
+and isolate_test_cases.py uses the same filename for the trace by default.
+"""
+
+import logging
+import os
+import subprocess
+import sys
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if not ROOT_DIR in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import isolate
+import run_isolated
+import run_test_cases
+import trace_inputs
+import trace_test_cases
+
+
+def isolate_test_cases(
+ cmd, test_cases, jobs, isolated_file, isolate_file,
+ root_dir, reldir, variables, trace_blacklist):
+ assert os.path.isabs(root_dir) and os.path.isdir(root_dir), root_dir
+
+ logname = isolated_file + '.log'
+ basename = isolated_file.rsplit('.', 1)[0]
+ cwd_dir = os.path.join(root_dir, reldir)
+ # Do the actual tracing.
+ results = trace_test_cases.trace_test_cases(
+ cmd, cwd_dir, test_cases, jobs, logname)
+ api = trace_inputs.get_api()
+ blacklist = trace_inputs.gen_blacklist(trace_blacklist)
+ logs = dict(
+ (i.pop('trace'), i) for i in api.parse_log(logname, blacklist, None))
+ exception = None
+ try:
+ inputs = []
+ for items in results:
+ item = items[-1]
+ assert item['valid']
+ # Load the results;
+ log_dict = logs[item['tracename']]
+ if log_dict.get('exception'):
+ exception = exception or log_dict['exception']
+ logging.error('Got exception: %s', exception)
+ continue
+ files = log_dict['results'].strip_root(root_dir).files
+ tracked, touched = isolate.split_touched(files)
+ value = isolate.generate_isolate(
+ tracked,
+ [],
+ touched,
+ root_dir,
+ variables,
+ reldir,
+ blacklist)
+ # item['test_case'] could be an invalid file name.
+ out = basename + '.' + item['tracename'] + '.isolate'
+ with open(out, 'w') as f:
+ isolate.pretty_print(value, f)
+ inputs.append(out)
+
+ # Merges back. Note that it is possible to blow up the command line
+ # argument length here but writing the files is still useful. Convert to
+ # importing the module instead if necessary.
+ merge_cmd = [
+ sys.executable,
+ os.path.join(ROOT_DIR, 'isolate_merge.py'),
+ isolate_file,
+ '-o', isolate_file,
+ ]
+ merge_cmd.extend(inputs)
+ logging.info(merge_cmd)
+ proc = subprocess.Popen(merge_cmd)
+ proc.communicate()
+ return proc.returncode
+ finally:
+ if exception:
+ raise exception[0], exception[1], exception[2]
+
+
+def test_xvfb(command, rel_dir):
+ """Calls back ourself if not running inside Xvfb and it's on the command line
+ to run.
+
+ Otherwise the X session will die while trying to start too many Xvfb
+ instances.
+ """
+ if os.environ.get('_CHROMIUM_INSIDE_XVFB') == '1':
+ return
+ for index, item in enumerate(command):
+ if item.endswith('xvfb.py'):
+ # Note this has inside knowledge about src/testing/xvfb.py.
+ print('Restarting itself under Xvfb')
+ prefix = command[index:index+2]
+ prefix[0] = os.path.normpath(os.path.join(rel_dir, prefix[0]))
+ prefix[1] = os.path.normpath(os.path.join(rel_dir, prefix[1]))
+ cmd = run_isolated.fix_python_path(prefix + sys.argv)
+ sys.exit(subprocess.call(cmd))
+
+
+def safely_load_isolated(parser, options):
+ """Loads a .isolated.state to extract the executable information.
+
+ Returns the CompleteState instance, the command and the list of test cases.
+ """
+ config = isolate.CompleteState.load_files(options.isolated)
+ logging.debug(
+ 'root_dir: %s relative_cwd: %s isolated: %s',
+ config.root_dir, config.saved_state.relative_cwd, options.isolated)
+ reldir = os.path.join(config.root_dir, config.saved_state.relative_cwd)
+ command = config.saved_state.command
+ test_cases = []
+ if command:
+ command = run_isolated.fix_python_path(command)
+ test_xvfb(command, reldir)
+ test_cases = parser.process_gtest_options(command, reldir, options)
+ return config, command, test_cases
+
+
+def main():
+ """CLI frontend to validate arguments."""
+ run_isolated.disable_buffering()
+ parser = run_test_cases.OptionParserTestCases(
+ usage='%prog <options> --isolated <.isolated>')
+ parser.format_description = lambda *_: parser.description
+ isolate.add_variable_option(parser)
+ isolate.add_trace_option(parser)
+
+ # TODO(maruel): Add support for options.timeout.
+ parser.remove_option('--timeout')
+
+ options, args = parser.parse_args()
+ if args:
+ parser.error('Unsupported arg: %s' % args)
+ isolate.parse_isolated_option(parser, options, os.getcwd(), True)
+ isolate.parse_variable_option(options)
+
+ try:
+ config, command, test_cases = safely_load_isolated(parser, options)
+ if not command:
+ parser.error('A command must be defined')
+ if not test_cases:
+ parser.error('No test case to run with command: %s' % ' '.join(command))
+
+ config.saved_state.variables.update(options.variables)
+ return isolate_test_cases(
+ command,
+ test_cases,
+ options.jobs,
+ config.isolated_filepath,
+ config.saved_state.isolate_filepath,
+ config.root_dir,
+ config.saved_state.relative_cwd,
+ config.saved_state.variables,
+ options.trace_blacklist)
+ except isolate.ExecutionError, e:
+ print >> sys.stderr, str(e)
+ return 1
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/googletest/list_test_cases.py b/chromium/tools/swarm_client/googletest/list_test_cases.py
new file mode 100755
index 00000000000..64cbf198058
--- /dev/null
+++ b/chromium/tools/swarm_client/googletest/list_test_cases.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""List all the test cases for a google test.
+
+See more info at http://code.google.com/p/googletest/.
+"""
+
+import os
+import sys
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if not ROOT_DIR in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import run_isolated
+import run_test_cases
+
+
+def main():
+ """CLI frontend to validate arguments."""
+ run_isolated.disable_buffering()
+ parser = run_test_cases.OptionParserWithTestShardingAndFiltering(
+ usage='%prog <options> [gtest]')
+
+ # Override default seed value to default to 0.
+ parser.set_defaults(seed=0)
+
+ options, args = parser.parse_args()
+ if not args:
+ parser.error('Please provide the executable to run')
+
+ cmd = run_isolated.fix_python_path(args)
+ try:
+ tests = run_test_cases.chromium_list_test_cases(
+ cmd,
+ os.getcwd(),
+ index=options.index,
+ shards=options.shards,
+ seed=options.seed,
+ disabled=options.disabled,
+ fails=options.fails,
+ flaky=options.flaky,
+ pre=False,
+ manual=options.manual)
+ for test in tests:
+ print test
+ except run_test_cases.Failure, e:
+ print e.args[0]
+ return e.args[1]
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/googletest/run_test_cases.py b/chromium/tools/swarm_client/googletest/run_test_cases.py
new file mode 100755
index 00000000000..f8beea42905
--- /dev/null
+++ b/chromium/tools/swarm_client/googletest/run_test_cases.py
@@ -0,0 +1,1736 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs each test cases as a single shard, single process execution.
+
+Similar to sharding_supervisor.py but finer grained. It runs each test case
+individually instead of running per shard. Runs multiple instances in parallel.
+"""
+
+import datetime
+import fnmatch
+import json
+import logging
+import optparse
+import os
+import Queue
+import random
+import re
+import subprocess
+import sys
+import threading
+import time
+from xml.dom import minidom
+import xml.parsers.expat
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if not ROOT_DIR in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import run_isolated
+
+
+# These are known to influence the way the output is generated.
+KNOWN_GTEST_ENV_VARS = [
+ 'GTEST_ALSO_RUN_DISABLED_TESTS',
+ 'GTEST_BREAK_ON_FAILURE',
+ 'GTEST_CATCH_EXCEPTIONS',
+ 'GTEST_COLOR',
+ 'GTEST_FILTER',
+ 'GTEST_OUTPUT',
+ 'GTEST_PRINT_TIME',
+ 'GTEST_RANDOM_SEED',
+ 'GTEST_REPEAT',
+ 'GTEST_SHARD_INDEX',
+ 'GTEST_SHARD_STATUS_FILE',
+ 'GTEST_SHUFFLE',
+ 'GTEST_THROW_ON_FAILURE',
+ 'GTEST_TOTAL_SHARDS',
+]
+
+# These needs to be poped out before running a test.
+GTEST_ENV_VARS_TO_REMOVE = [
+ 'GTEST_ALSO_RUN_DISABLED_TESTS',
+ 'GTEST_FILTER',
+ 'GTEST_OUTPUT',
+ 'GTEST_RANDOM_SEED',
+ # TODO(maruel): Handle.
+ 'GTEST_REPEAT',
+ 'GTEST_SHARD_INDEX',
+ # TODO(maruel): Handle.
+ 'GTEST_SHUFFLE',
+ 'GTEST_TOTAL_SHARDS',
+]
+
+
+RUN_PREFIX = '[ RUN ] '
+OK_PREFIX = '[ OK ] '
+FAILED_PREFIX = '[ FAILED ] '
+
+
+if subprocess.mswindows:
+ import msvcrt # pylint: disable=F0401
+ from ctypes import wintypes
+ from ctypes import windll
+
+ def ReadFile(handle, desired_bytes):
+ """Calls kernel32.ReadFile()."""
+ c_read = wintypes.DWORD()
+ buff = wintypes.create_string_buffer(desired_bytes+1)
+ windll.kernel32.ReadFile(
+ handle, buff, desired_bytes, wintypes.byref(c_read), None)
+ # NULL terminate it.
+ buff[c_read.value] = '\x00'
+ return wintypes.GetLastError(), buff.value
+
+ def PeekNamedPipe(handle):
+ """Calls kernel32.PeekNamedPipe(). Simplified version."""
+ c_avail = wintypes.DWORD()
+ c_message = wintypes.DWORD()
+ success = windll.kernel32.PeekNamedPipe(
+ handle, None, 0, None, wintypes.byref(c_avail),
+ wintypes.byref(c_message))
+ if not success:
+ raise OSError(wintypes.GetLastError())
+ return c_avail.value
+
+ def recv_multi_impl(conns, maxsize, timeout):
+ """Reads from the first available pipe.
+
+ If timeout is None, it's blocking. If timeout is 0, it is not blocking.
+ """
+ # TODO(maruel): Use WaitForMultipleObjects(). Python creates anonymous pipes
+ # for proc.stdout and proc.stderr but they are implemented as named pipes on
+ # Windows. Since named pipes are not waitable object, they can't be passed
+ # as-is to WFMO(). So this means N times CreateEvent(), N times ReadFile()
+ # and finally WFMO(). This requires caching the events handles in the Popen
+ # object and remembering the pending ReadFile() calls. This will require
+ # some re-architecture.
+ maxsize = max(maxsize or 16384, 1)
+ if timeout:
+ start = time.time()
+ handles = [msvcrt.get_osfhandle(conn.fileno()) for conn in conns]
+ while handles:
+ for i, handle in enumerate(handles):
+ try:
+ avail = min(PeekNamedPipe(handle), maxsize)
+ if avail:
+ return i, ReadFile(handle, avail)[1]
+ if (timeout and (time.time() - start) >= timeout) or timeout == 0:
+ return None, None
+ # Polling rocks.
+ time.sleep(0.001)
+ except OSError:
+ handles.pop(i)
+ break
+ # Nothing to wait for.
+ return None, None
+
+else:
+ import fcntl # pylint: disable=F0401
+ import select
+
+ def recv_multi_impl(conns, maxsize, timeout):
+ """Reads from the first available pipe.
+
+ If timeout is None, it's blocking. If timeout is 0, it is not blocking.
+ """
+ try:
+ r, _, _ = select.select(conns, [], [], timeout)
+ except select.error:
+ return None, None
+ if not r:
+ return None, None
+
+ conn = r[0]
+ # Temporarily make it non-blocking.
+ flags = fcntl.fcntl(conn, fcntl.F_GETFL)
+ if not conn.closed:
+ # pylint: disable=E1101
+ fcntl.fcntl(conn, fcntl.F_SETFL, flags | os.O_NONBLOCK)
+ try:
+ data = conn.read(max(maxsize or 16384, 1))
+ return conns.index(conn), data
+ finally:
+ if not conn.closed:
+ fcntl.fcntl(conn, fcntl.F_SETFL, flags)
+
+
+class Failure(Exception):
+ pass
+
+
+class Popen(subprocess.Popen):
+ """Adds timeout support on stdout and stderr.
+
+ Inspired by
+ http://code.activestate.com/recipes/440554-module-to-allow-asynchronous-subprocess-use-on-win/
+ """
+ def __init__(self, *args, **kwargs):
+ self.start = time.time()
+ self.end = None
+ super(Popen, self).__init__(*args, **kwargs)
+
+ def duration(self):
+ """Duration of the child process.
+
+ It is greater or equal to the actual time the child process ran. It can be
+ significantly higher than the real value if neither .wait() nor .poll() was
+ used.
+ """
+ return (self.end or time.time()) - self.start
+
+ def wait(self):
+ ret = super(Popen, self).wait()
+ if not self.end:
+ # communicate() uses wait() internally.
+ self.end = time.time()
+ return ret
+
+ def poll(self):
+ ret = super(Popen, self).poll()
+ if ret is not None and not self.end:
+ self.end = time.time()
+ return ret
+
+ def yield_any(self, timeout=None):
+ """Yields output until the process terminates or is killed by a timeout.
+
+ Yielded values are in the form (pipename, data).
+
+ If timeout is None, it is blocking. If timeout is 0, it doesn't block. This
+ is not generally useful to use timeout=0.
+ """
+ remaining = 0
+ while self.poll() is None:
+ if timeout:
+ # While these float() calls seem redundant, they are to force
+ # ResetableTimeout to "render" itself into a float. At each call, the
+ # resulting value could be different, depending if a .reset() call
+ # occurred.
+ remaining = max(float(timeout) - self.duration(), 0.001)
+ else:
+ remaining = timeout
+ t, data = self.recv_any(timeout=remaining)
+ if data or timeout == 0:
+ yield (t, data)
+ if timeout and self.duration() >= float(timeout):
+ break
+ if self.poll() is None and timeout and self.duration() >= float(timeout):
+ logging.debug('Kill %s %s', self.duration(), float(timeout))
+ self.kill()
+ self.wait()
+ # Read all remaining output in the pipes.
+ while True:
+ t, data = self.recv_any()
+ if not data:
+ break
+ yield (t, data)
+
+ def recv_any(self, maxsize=None, timeout=None):
+ """Reads from stderr and if empty, from stdout.
+
+ If timeout is None, it is blocking. If timeout is 0, it doesn't block.
+ """
+ pipes = [
+ x for x in ((self.stderr, 'stderr'), (self.stdout, 'stdout')) if x[0]
+ ]
+ if len(pipes) == 2 and self.stderr.fileno() == self.stdout.fileno():
+ pipes.pop(0)
+ if not pipes:
+ return None, None
+ conns, names = zip(*pipes)
+ index, data = recv_multi_impl(conns, maxsize, timeout)
+ if index is None:
+ return index, data
+ if not data:
+ self._close(names[index])
+ return None, None
+ if self.universal_newlines:
+ data = self._translate_newlines(data)
+ return names[index], data
+
+ def recv_out(self, maxsize=None, timeout=None):
+ """Reads from stdout asynchronously."""
+ return self._recv('stdout', maxsize, timeout)
+
+ def recv_err(self, maxsize=None, timeout=None):
+ """Reads from stderr asynchronously."""
+ return self._recv('stderr', maxsize, timeout)
+
+ def _close(self, which):
+ getattr(self, which).close()
+ setattr(self, which, None)
+
+ def _recv(self, which, maxsize, timeout):
+ conn = getattr(self, which)
+ if conn is None:
+ return None
+ data = recv_multi_impl([conn], maxsize, timeout)
+ if not data:
+ return self._close(which)
+ if self.universal_newlines:
+ data = self._translate_newlines(data)
+ return data
+
+
+def call_with_timeout(cmd, timeout, **kwargs):
+ """Runs an executable with an optional timeout.
+
+ timeout 0 or None disables the timeout.
+ """
+ proc = Popen(
+ cmd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ **kwargs)
+ if timeout:
+ out = ''
+ err = ''
+ for t, data in proc.yield_any(timeout):
+ if t == 'stdout':
+ out += data
+ else:
+ err += data
+ else:
+ # This code path is much faster.
+ out, err = proc.communicate()
+ return out, err, proc.returncode, proc.duration()
+
+
+class QueueWithProgress(Queue.PriorityQueue):
+ """Implements progress support in join()."""
+ def __init__(self, maxsize, *args, **kwargs):
+ Queue.PriorityQueue.__init__(self, *args, **kwargs)
+ self.progress = Progress(maxsize)
+
+ def set_progress(self, progress):
+ """Replace the current progress, mainly used when a progress should be
+ shared between queues."""
+ self.progress = progress
+
+ def task_done(self):
+ """Contrary to Queue.task_done(), it wakes self.all_tasks_done at each task
+ done.
+ """
+ self.all_tasks_done.acquire()
+ try:
+ unfinished = self.unfinished_tasks - 1
+ if unfinished < 0:
+ raise ValueError('task_done() called too many times')
+ self.unfinished_tasks = unfinished
+ # This is less efficient, because we want the Progress to be updated.
+ self.all_tasks_done.notify_all()
+ except Exception as e:
+ logging.exception('task_done threw an exception.\n%s', e)
+ finally:
+ self.all_tasks_done.release()
+
+ def wake_up(self):
+ """Wakes up all_tasks_done.
+
+ Unlike task_done(), do not substract one from self.unfinished_tasks.
+ """
+ # TODO(maruel): This is highly inefficient, since the listener is awaken
+ # twice; once per output, once per task. There should be no relationship
+ # between the number of output and the number of input task.
+ self.all_tasks_done.acquire()
+ try:
+ self.all_tasks_done.notify_all()
+ finally:
+ self.all_tasks_done.release()
+
+ def join(self):
+ """Calls print_update() whenever possible."""
+ self.progress.print_update()
+ self.all_tasks_done.acquire()
+ try:
+ while self.unfinished_tasks:
+ self.progress.print_update()
+ self.all_tasks_done.wait(60.)
+ self.progress.print_update()
+ finally:
+ self.all_tasks_done.release()
+
+
+class ThreadPool(run_isolated.ThreadPool):
+ QUEUE_CLASS = QueueWithProgress
+
+ def __init__(self, progress, *args, **kwargs):
+ super(ThreadPool, self).__init__(*args, **kwargs)
+ self.tasks.set_progress(progress)
+
+ def _output_append(self, out):
+ """Also wakes up the listener on new completed test_case."""
+ super(ThreadPool, self)._output_append(out)
+ self.tasks.wake_up()
+
+
+class Progress(object):
+ """Prints progress and accepts updates thread-safely."""
+ def __init__(self, size):
+ # To be used in the primary thread
+ self.last_printed_line = ''
+ self.index = 0
+ self.start = time.time()
+ self.size = size
+ self.use_cr_only = True
+ self.unfinished_commands = set()
+
+ # To be used in all threads.
+ self.queued_lines = Queue.Queue()
+
+ def update_item(self, name, index=True, size=False):
+ """Queue information to print out.
+
+ |index| notes that the index should be incremented.
+ |size| note that the total size should be incremented.
+ """
+ # This code doesn't need lock because it's only using self.queued_lines.
+ self.queued_lines.put((name, index, size))
+
+ def print_update(self):
+ """Prints the current status."""
+ # Flush all the logging output so it doesn't appear within this output.
+ for handler in logging.root.handlers:
+ handler.flush()
+
+ while True:
+ try:
+ name, index, size = self.queued_lines.get_nowait()
+ except Queue.Empty:
+ break
+
+ if size:
+ self.size += 1
+ if index:
+ self.index += 1
+ if not name:
+ continue
+
+ if index:
+ alignment = str(len(str(self.size)))
+ next_line = ('[%' + alignment + 'd/%d] %6.2fs %s') % (
+ self.index,
+ self.size,
+ time.time() - self.start,
+ name)
+ # Fill it with whitespace only if self.use_cr_only is set.
+ prefix = ''
+ if self.use_cr_only:
+ if self.last_printed_line:
+ prefix = '\r'
+ if self.use_cr_only:
+ suffix = ' ' * max(0, len(self.last_printed_line) - len(next_line))
+ else:
+ suffix = '\n'
+ line = '%s%s%s' % (prefix, next_line, suffix)
+ self.last_printed_line = next_line
+ else:
+ line = '\n%s\n' % name.strip('\n')
+ self.last_printed_line = ''
+
+ sys.stdout.write(line)
+
+ # Ensure that all the output is flush to prevent it from getting mixed with
+ # other output streams (like the logging streams).
+ sys.stdout.flush()
+
+ if self.unfinished_commands:
+ logging.debug('Waiting for the following commands to finish:\n%s',
+ '\n'.join(self.unfinished_commands))
+
+
+def setup_gtest_env():
+ """Copy the enviroment variables and setup for running a gtest."""
+ env = os.environ.copy()
+ for name in GTEST_ENV_VARS_TO_REMOVE:
+ env.pop(name, None)
+
+ # Forcibly enable color by default, if not already disabled.
+ env.setdefault('GTEST_COLOR', 'on')
+
+ return env
+
+
+def gtest_list_tests(cmd, cwd):
+ """List all the test cases for a google test.
+
+ See more info at http://code.google.com/p/googletest/.
+ """
+ cmd = cmd[:]
+ cmd.append('--gtest_list_tests')
+ env = setup_gtest_env()
+ timeout = 0.
+ try:
+ out, err, returncode, _ = call_with_timeout(
+ cmd,
+ timeout,
+ stderr=subprocess.PIPE,
+ env=env,
+ cwd=cwd)
+ except OSError, e:
+ raise Failure('Failed to run %s\ncwd=%s\n%s' % (' '.join(cmd), cwd, str(e)))
+ if returncode:
+ raise Failure(
+ 'Failed to run %s\nstdout:\n%s\nstderr:\n%s' %
+ (' '.join(cmd), out, err), returncode)
+ # pylint: disable=E1103
+ if err and not err.startswith('Xlib: extension "RANDR" missing on display '):
+ logging.error('Unexpected spew in gtest_list_tests:\n%s\n%s', err, cmd)
+ return out
+
+
+def filter_shards(tests, index, shards):
+ """Filters the shards.
+
+ Watch out about integer based arithmetics.
+ """
+ # The following code could be made more terse but I liked the extra clarity.
+ assert 0 <= index < shards
+ total = len(tests)
+ quotient, remainder = divmod(total, shards)
+ # 1 item of each remainder is distributed over the first 0:remainder shards.
+ # For example, with total == 5, index == 1, shards == 3
+ # min_bound == 2, max_bound == 4.
+ min_bound = quotient * index + min(index, remainder)
+ max_bound = quotient * (index + 1) + min(index + 1, remainder)
+ return tests[min_bound:max_bound]
+
+
+def _starts_with(a, b, prefix):
+ return a.startswith(prefix) or b.startswith(prefix)
+
+
+def is_valid_test_case(test, disabled):
+ """Returns False on malformed or DISABLED_ test cases."""
+ if not '.' in test:
+ logging.error('Ignoring unknown test %s', test)
+ return False
+ fixture, case = test.split('.', 1)
+ if not disabled and _starts_with(fixture, case, 'DISABLED_'):
+ return False
+ return True
+
+
+def filter_bad_tests(tests, disabled):
+ """Filters out malformed or DISABLED_ test cases."""
+ return [test for test in tests if is_valid_test_case(test, disabled)]
+
+
+def chromium_is_valid_test_case(test, disabled, fails, flaky, pre, manual):
+ """Return False on chromium specific bad tests in addition to
+ is_valid_test_case().
+
+ FAILS_, FLAKY_, PRE_, MANUAL_ and other weird Chromium-specific test cases.
+ """
+ if not is_valid_test_case(test, disabled):
+ return False
+ fixture, case = test.split('.', 1)
+ if not fails and _starts_with(fixture, case, 'FAILS_'):
+ return False
+ if not flaky and _starts_with(fixture, case, 'FLAKY_'):
+ return False
+ if not pre and _starts_with(fixture, case, 'PRE_'):
+ return False
+ if not manual and _starts_with(fixture, case, 'MANUAL_'):
+ return False
+ if test == 'InProcessBrowserTest.Empty':
+ return False
+ return True
+
+
+def chromium_filter_bad_tests(tests, disabled, fails, flaky, pre, manual):
+ """Filters out chromium specific bad tests in addition to filter_bad_tests().
+
+ Filters out FAILS_, FLAKY_, PRE_, MANUAL_ and other weird Chromium-specific
+ test cases.
+ """
+ return [
+ test for test in tests if chromium_is_valid_test_case(
+ test, disabled, fails, flaky, pre, manual)
+ ]
+
+
+def chromium_filter_pre_tests(test_case_results):
+ """Filters out PRE_ test case results."""
+ return (
+ i for i in test_case_results if chromium_is_valid_test_case(
+ i['test_case'],
+ disabled=True,
+ fails=True,
+ flaky=True,
+ pre=False,
+ manual=True))
+
+
+def parse_gtest_cases(out, seed):
+ """Returns the flattened list of test cases in the executable.
+
+ The returned list is sorted so it is not dependent on the order of the linked
+ objects. Then |seed| is applied to deterministically shuffle the list if
+ |seed| is a positive value. The rationale is that the probability of two test
+ cases stomping on each other when run simultaneously is high for test cases in
+ the same fixture. By shuffling the tests, the probability of these badly
+ written tests running simultaneously, let alone being in the same shard, is
+ lower.
+
+ Expected format is a concatenation of this:
+ TestFixture1
+ TestCase1
+ TestCase2
+ """
+ tests = []
+ fixture = None
+ lines = out.splitlines()
+ while lines:
+ line = lines.pop(0)
+ if not line:
+ break
+ if not line.startswith(' '):
+ fixture = line
+ else:
+ case = line[2:]
+ if case.startswith('YOU HAVE'):
+ # It's a 'YOU HAVE foo bar' line. We're done.
+ break
+ assert ' ' not in case
+ tests.append(fixture + case)
+ tests = sorted(tests)
+ if seed:
+ # Sadly, python's random module doesn't permit local seeds.
+ state = random.getstate()
+ try:
+ # This is totally deterministic.
+ random.seed(seed)
+ random.shuffle(tests)
+ finally:
+ random.setstate(state)
+ return tests
+
+
+def list_test_cases(cmd, cwd, index, shards, seed, disabled):
+ """Returns the list of test cases according to the specified criterias."""
+ tests = parse_gtest_cases(gtest_list_tests(cmd, cwd), seed)
+
+ # TODO(maruel): Splitting shards before filtering bad test cases could result
+ # in inbalanced shards.
+ if shards:
+ tests = filter_shards(tests, index, shards)
+ return filter_bad_tests(tests, disabled)
+
+
+def chromium_list_test_cases(
+ cmd, cwd, index, shards, seed, disabled, fails, flaky, pre, manual):
+ """Returns the list of test cases according to the specified criterias."""
+ tests = list_test_cases(cmd, cwd, index, shards, seed, disabled)
+ return chromium_filter_bad_tests(tests, disabled, fails, flaky, pre, manual)
+
+
+class RunSome(object):
+ """Thread-safe object deciding if testing should continue."""
+ def __init__(
+ self, expected_count, retries, min_failures, max_failure_ratio,
+ max_failures):
+ """Determines if it is better to give up testing after an amount of failures
+ and successes.
+
+ Arguments:
+ - expected_count is the expected number of elements to run.
+ - retries is how many time a failing element can be retried. retries should
+ be set to the maximum number of retries per failure. This permits
+ dampening the curve to determine threshold where to stop.
+ - min_failures is the minimal number of failures to tolerate, to put a lower
+ limit when expected_count is small. This value is multiplied by the number
+ of retries.
+ - max_failure_ratio is the ratio of permitted failures, e.g. 0.1 to stop
+ after 10% of failed test cases.
+ - max_failures is the absolute maximum number of tolerated failures or None.
+
+ For large values of expected_count, the number of tolerated failures will be
+ at maximum "(expected_count * retries) * max_failure_ratio".
+
+ For small values of expected_count, the number of tolerated failures will be
+ at least "min_failures * retries".
+ """
+ assert 0 < expected_count
+ assert 0 <= retries < 100
+ assert 0 <= min_failures
+ assert 0. < max_failure_ratio < 1.
+ # Constants.
+ self._expected_count = expected_count
+ self._retries = retries
+ self._min_failures = min_failures
+ self._max_failure_ratio = max_failure_ratio
+
+ self._min_failures_tolerated = self._min_failures * (self._retries + 1)
+ # Pre-calculate the maximum number of allowable failures. Note that
+ # _max_failures can be lower than _min_failures.
+ self._max_failures_tolerated = round(
+ (expected_count * (retries + 1)) * max_failure_ratio)
+ if max_failures is not None:
+ # Override the ratio if necessary.
+ self._max_failures_tolerated = min(
+ self._max_failures_tolerated, max_failures)
+ self._min_failures_tolerated = min(
+ self._min_failures_tolerated, max_failures)
+
+ # Variables.
+ self._lock = threading.Lock()
+ self._passed = 0
+ self._failures = 0
+ self.stopped = False
+
+ def should_stop(self):
+ """Stops once a threshold was reached. This includes retries."""
+ with self._lock:
+ if self.stopped:
+ return True
+ # Accept at least the minimum number of failures.
+ if self._failures <= self._min_failures_tolerated:
+ return False
+ if self._failures >= self._max_failures_tolerated:
+ self.stopped = True
+ return self.stopped
+
+ def got_result(self, passed):
+ with self._lock:
+ if passed:
+ self._passed += 1
+ else:
+ self._failures += 1
+
+ def __str__(self):
+ return '%s(%d, %d, %d, %.3f)' % (
+ self.__class__.__name__,
+ self._expected_count,
+ self._retries,
+ self._min_failures,
+ self._max_failure_ratio)
+
+
+class RunAll(object):
+ """Never fails."""
+ stopped = False
+
+ @staticmethod
+ def should_stop():
+ return False
+
+ @staticmethod
+ def got_result(_):
+ pass
+
+
+def process_output(lines, test_cases):
+ """Yield the data of each test cases.
+
+ Expects the test cases to be run in the order of the list.
+
+ Handles the following google-test behavior:
+ - Test case crash causing a partial number of test cases to be run.
+ - Invalid test case name so the test case wasn't run at all.
+
+ This function automatically distribute the startup cost across each test case.
+ """
+ test_cases = test_cases[:]
+ test_case = None
+ test_case_data = None
+ # Accumulates the junk between test cases.
+ accumulation = ''
+ eat_last_lines = False
+
+ for line in lines:
+ if eat_last_lines:
+ test_case_data['output'] += line
+ continue
+
+ i = line.find(RUN_PREFIX)
+ if i > 0 and test_case_data:
+ # This may occur specifically in browser_tests, because the test case is
+ # run in a child process. If the child process doesn't terminate its
+ # output with a LF, it may cause the "[ RUN ]" line to be improperly
+ # printed out in the middle of a line.
+ test_case_data['output'] += line[:i]
+ line = line[i:]
+ i = 0
+ if i >= 0:
+ if test_case:
+ # The previous test case had crashed. No idea about its duration
+ test_case_data['returncode'] = 1
+ test_case_data['duration'] = 0
+ test_case_data['crashed'] = True
+ yield test_case_data
+
+ test_case = line[len(RUN_PREFIX):].strip().split(' ', 1)[0]
+ # Accept the test case even if it was unexpected.
+ if test_case in test_cases:
+ test_cases.remove(test_case)
+ else:
+ logging.warning('Unexpected test case: %s', test_case)
+ test_case_data = {
+ 'test_case': test_case,
+ 'returncode': None,
+ 'duration': None,
+ 'output': accumulation + line,
+ }
+ accumulation = ''
+
+ elif test_case:
+ test_case_data['output'] += line
+ i = line.find(OK_PREFIX)
+ if i >= 0:
+ result = 0
+ line = line[i + len(OK_PREFIX):]
+ else:
+ i = line.find(FAILED_PREFIX)
+ if i >= 0:
+ line = line[i + len(FAILED_PREFIX):]
+ result = 1
+ if i >= 0:
+ # The test completed. It's important to make sure the test case name
+ # match too, since it could be a fake output.
+ if line.startswith(test_case):
+ line = line[len(test_case):]
+ match = re.search(r' \((\d+) ms\)', line)
+ if match:
+ test_case_data['duration'] = float(match.group(1)) / 1000.
+ else:
+ # Make sure duration is at least not None since the test case ran.
+ test_case_data['duration'] = 0
+ test_case_data['returncode'] = result
+ if not test_cases:
+ # Its the last test case. Eat all the remaining lines.
+ eat_last_lines = True
+ continue
+ yield test_case_data
+ test_case = None
+ test_case_data = None
+ else:
+ accumulation += line
+
+ # It's guaranteed here that the lines generator is exhausted.
+ if eat_last_lines:
+ yield test_case_data
+ test_case = None
+ test_case_data = None
+
+ if test_case_data:
+ # This means the last one likely crashed.
+ test_case_data['crashed'] = True
+ test_case_data['duration'] = 0
+ test_case_data['returncode'] = 1
+ test_case_data['output'] += accumulation
+ yield test_case_data
+
+ # If test_cases is not empty, these test cases were not run.
+ for t in test_cases:
+ yield {
+ 'test_case': t,
+ 'returncode': None,
+ 'duration': None,
+ 'output': None,
+ }
+
+
+def convert_to_lines(generator):
+ """Turn input coming from a generator into lines.
+
+ It is Windows-friendly.
+ """
+ accumulator = ''
+ for data in generator:
+ items = (accumulator + data).splitlines(True)
+ for item in items[:-1]:
+ yield item
+ if items[-1].endswith(('\r', '\n')):
+ yield items[-1]
+ accumulator = ''
+ else:
+ accumulator = items[-1]
+ if accumulator:
+ yield accumulator
+
+
+class ResetableTimeout(object):
+ """A resetable timeout that acts as a float.
+
+ At each reset, the timeout is increased so that it still has the equivalent
+ of the original timeout value, but according to 'now' at the time of the
+ reset.
+ """
+ def __init__(self, timeout):
+ assert timeout >= 0.
+ self.timeout = float(timeout)
+ self.last_reset = time.time()
+
+ def reset(self):
+ """Respendish the timeout."""
+ now = time.time()
+ self.timeout += max(0., now - self.last_reset)
+ self.last_reset = now
+ return now
+
+ @staticmethod
+ def __bool__():
+ return True
+
+ def __float__(self):
+ """To be used as a timeout value for a function call."""
+ return self.timeout
+
+
+class GoogleTestRunner(object):
+ """Immutable settings to run many test cases in a loop."""
+ def __init__(
+ self,
+ cmd,
+ cwd_dir,
+ timeout,
+ progress,
+ retries,
+ decider,
+ verbose,
+ add_task,
+ add_serial_task,
+ filter_results):
+ """Defines how to run a googletest executable.
+
+ Arguments:
+ - cmd: command line to start with.
+ - cwd_dir: directory to start the app in.
+ - timeout: timeout while waiting for output.
+ - progress: object to present the user with status updates.
+ - retries: number of allowed retries. For example if 2, the test case will
+ be tried 3 times in total.
+ - decider: object to decide if the run should be stopped early.
+ - verbose: inconditionally prints output.
+ - add_task: function to add the task back when failing, for retry.
+ - add_serial_task: function to add the task back when failing too often so
+ it should be run serially.
+ - filter_results: optional function to filter undesired extraneous test case
+ run without our consent.
+ """
+ self.cmd = cmd[:]
+ self.cwd_dir = cwd_dir
+ self.timeout = timeout
+ self.progress = progress
+ self.retries = retries
+ self.decider = decider
+ self.verbose = verbose
+ self.add_task = add_task
+ self.add_serial_task = add_serial_task
+ self.filter_results = filter_results or (lambda x: x)
+ # It is important to remove the shard environment variables since it could
+ # conflict with --gtest_filter.
+ self.env = setup_gtest_env()
+
+ def map(self, priority, test_cases, try_count):
+ """Traces a single test case and returns its output.
+
+ try_count is 0 based, the original try is 0.
+ """
+ if self.decider.should_stop():
+ raise StopIteration()
+ cmd = self.cmd + ['--gtest_filter=%s' % ':'.join(test_cases)]
+ if '--gtest_print_time' not in cmd:
+ cmd.append('--gtest_print_time')
+ proc = Popen(
+ cmd,
+ cwd=self.cwd_dir,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ env=self.env)
+
+ # Use an intelligent timeout that can be reset. The idea is simple, the
+ # timeout is set to the value of the timeout for a single test case.
+ # Everytime a test case is parsed, the timeout is reset to its full value.
+ # proc.yield_any() uses float() to extract the instantaneous value of
+ # 'timeout'.
+ timeout = ResetableTimeout(self.timeout)
+
+ # Create a pipeline of generators.
+ gen_lines = convert_to_lines(data for _, data in proc.yield_any(timeout))
+ # It needs to be valid utf-8 otherwise it can't be stored.
+ # TODO(maruel): Be more intelligent than decoding to ascii.
+ gen_lines_utf8 = (
+ line.decode('ascii', 'ignore').encode('utf-8') for line in gen_lines)
+ gen_test_cases = process_output(gen_lines_utf8, test_cases)
+ last_timestamp = proc.start
+ got_failure_at_least_once = False
+ results = []
+ for i in self.filter_results(gen_test_cases):
+ results.append(i)
+ now = timeout.reset()
+ test_case_has_passed = (i['returncode'] == 0)
+ if i['duration'] is None:
+ assert not test_case_has_passed
+ # Do not notify self.decider, because an early crash in a large cluster
+ # could cause the test to quit early.
+ else:
+ i['duration'] = max(i['duration'], now - last_timestamp)
+ # A new test_case completed.
+ self.decider.got_result(test_case_has_passed)
+
+ need_to_retry = not test_case_has_passed and try_count < self.retries
+ got_failure_at_least_once |= not test_case_has_passed
+ last_timestamp = now
+
+ # Create the line to print out.
+ if i['duration'] is not None:
+ duration = '(%.2fs)' % i['duration']
+ else:
+ duration = '<unknown>'
+ if try_count:
+ line = '%s %s - retry #%d' % (i['test_case'], duration, try_count)
+ else:
+ line = '%s %s' % (i['test_case'], duration)
+ if self.verbose or not test_case_has_passed or try_count > 0:
+ # Print output in one of three cases:
+ # - --verbose was specified.
+ # - The test failed.
+ # - The wasn't the first attempt (this is needed so the test parser can
+ # detect that a test has been successfully retried).
+ if i['output']:
+ line += '\n' + i['output']
+ self.progress.update_item(line, True, need_to_retry)
+
+ if need_to_retry:
+ priority = self._retry(priority, i['test_case'], try_count)
+
+ # Delay yielding when only one test case is running, in case of a
+ # crash-after-succeed.
+ if len(test_cases) > 1:
+ yield i
+
+ if proc.returncode and not got_failure_at_least_once:
+ if results and len(test_cases) == 1:
+ # Crash after pass.
+ results[-1]['returncode'] = proc.returncode
+
+ if try_count < self.retries:
+ # This is tricky, one of the test case failed but each did print that
+ # they succeeded! Retry them *all* individually.
+ if not self.verbose and not try_count:
+ # Print all the output as one shot when not verbose to be sure the
+ # potential stack trace is printed.
+ output = ''.join(i['output'] for i in results)
+ self.progress.update_item(output, False, False)
+ for i in results:
+ priority = self._retry(priority, i['test_case'], try_count)
+ self.progress.update_item('', False, True)
+
+ # Only yield once the process completed when there is only one test case as
+ # a safety precaution.
+ if results and len(test_cases) == 1:
+ yield results[-1]
+
+ def _retry(self, priority, test_case, try_count):
+ """Adds back the same task again only if relevant.
+
+ It may add it either at lower (e.g. higher value) priority or at the end of
+ the serially executed list.
+ """
+ if try_count + 1 < self.retries:
+ # The test failed and needs to be retried normally.
+ # Leave a buffer of ~40 test cases before retrying.
+ priority += 40
+ self.add_task(priority, self.map, priority, [test_case], try_count + 1)
+ else:
+ # This test only has one retry left, so the final retry should be
+ # done serially.
+ self.add_serial_task(
+ priority, self.map, priority, [test_case], try_count + 1)
+ return priority
+
+
+class ChromiumGoogleTestRunner(GoogleTestRunner):
+ def __init__(self, *args, **kwargs):
+ super(ChromiumGoogleTestRunner, self).__init__(
+ *args, filter_results=chromium_filter_pre_tests, **kwargs)
+
+
+def get_test_cases(
+ cmd, cwd, whitelist, blacklist, index, shards, seed, disabled, fails, flaky,
+ manual):
+ """Returns the filtered list of test cases.
+
+ This is done synchronously.
+ """
+ try:
+ # List all the test cases if a whitelist is used.
+ tests = chromium_list_test_cases(
+ cmd,
+ cwd,
+ index=index,
+ shards=shards,
+ seed=seed,
+ disabled=disabled,
+ fails=fails,
+ flaky=flaky,
+ pre=False,
+ manual=manual)
+ except Failure, e:
+ print('Failed to list test cases')
+ print(e.args[0])
+ return None
+
+ if shards:
+ # This is necessary for Swarm log parsing.
+ print('Note: This is test shard %d of %d.' % (index+1, shards))
+
+ # Filters the test cases with the two lists.
+ if blacklist:
+ tests = [
+ t for t in tests if not any(fnmatch.fnmatch(t, s) for s in blacklist)
+ ]
+ if whitelist:
+ tests = [
+ t for t in tests if any(fnmatch.fnmatch(t, s) for s in whitelist)
+ ]
+ logging.info('Found %d test cases in %s' % (len(tests), ' '.join(cmd)))
+ return tests
+
+
+def dump_results_as_json(result_file, results):
+ """Write the results out to a json file."""
+ base_path = os.path.dirname(result_file)
+ if base_path and not os.path.isdir(base_path):
+ os.makedirs(base_path)
+ with open(result_file, 'wb') as f:
+ json.dump(results, f, sort_keys=True, indent=2)
+
+
+def dump_results_as_xml(gtest_output, results, now):
+ """Write the results out to a xml file in google-test compatible format."""
+ # TODO(maruel): Print all the test cases, including the ones that weren't run
+ # and the retries.
+ test_suites = {}
+ for test_case, result in results['test_cases'].iteritems():
+ suite, case = test_case.split('.', 1)
+ test_suites.setdefault(suite, {})[case] = result[0]
+
+ with open(gtest_output, 'wb') as f:
+ # Sanity warning: hand-rolling XML. What could possibly go wrong?
+ f.write('<?xml version="1.0" ?>\n')
+ # TODO(maruel): File the fields nobody reads anyway.
+ # disabled="%d" errors="%d" failures="%d"
+ f.write(
+ ('<testsuites name="AllTests" tests="%d" time="%f" timestamp="%s">\n')
+ % (results['expected'], results['duration'], now))
+ for suite_name, suite in test_suites.iteritems():
+ # TODO(maruel): disabled="0" errors="0" failures="0" time="0"
+ f.write('<testsuite name="%s" tests="%d">\n' % (suite_name, len(suite)))
+ for case_name, case in suite.iteritems():
+ if case['returncode'] == 0:
+ f.write(
+ ' <testcase classname="%s" name="%s" status="run" time="%f"/>\n' %
+ (suite_name, case_name, case['duration']))
+ else:
+ f.write(
+ ' <testcase classname="%s" name="%s" status="run" time="%f">\n' %
+ (suite_name, case_name, (case['duration'] or 0)))
+ # While at it, hand-roll CDATA escaping too.
+ output = ']]><![CDATA['.join((case['output'] or '').split(']]>'))
+ # TODO(maruel): message="" type=""
+ f.write('<failure><![CDATA[%s]]></failure></testcase>\n' % output)
+ f.write('</testsuite>\n')
+ f.write('</testsuites>')
+
+
+def append_gtest_output_to_xml(final_xml, filepath):
+ """Combines the shard xml file with the final xml file."""
+ try:
+ with open(filepath) as shard_xml_file:
+ shard_xml = minidom.parse(shard_xml_file)
+ except xml.parsers.expat.ExpatError as e:
+ logging.error('Failed to parse %s: %s', filepath, e)
+ return final_xml
+ except IOError as e:
+ logging.error('Failed to load %s: %s', filepath, e)
+ # If the shard crashed, gtest will not have generated an xml file.
+ return final_xml
+
+ if not final_xml:
+ # Out final xml is empty, let's prepopulate it with the first one we see.
+ return shard_xml
+
+ final_testsuites_by_name = dict(
+ (suite.getAttribute('name'), suite)
+ for suite in final_xml.documentElement.getElementsByTagName('testsuite'))
+
+ for testcase in shard_xml.documentElement.getElementsByTagName('testcase'):
+ # Don't bother updating the final xml if there is no data.
+ status = testcase.getAttribute('status')
+ if status == 'notrun':
+ continue
+
+ name = testcase.getAttribute('name')
+ # Look in our final xml to see if it's there.
+ to_remove = []
+ final_testsuite = final_testsuites_by_name[
+ testcase.getAttribute('classname')]
+ for final_testcase in final_testsuite.getElementsByTagName('testcase'):
+ # Trim all the notrun testcase instances to add the new instance there.
+ # This is to make sure it works properly in case of a testcase being run
+ # multiple times.
+ if (final_testcase.getAttribute('name') == name and
+ final_testcase.getAttribute('status') == 'notrun'):
+ to_remove.append(final_testcase)
+
+ for item in to_remove:
+ final_testsuite.removeChild(item)
+ # Reparent the XML node.
+ final_testsuite.appendChild(testcase)
+
+ return final_xml
+
+
+def running_serial_warning():
+ return ['*****************************************************',
+ '*****************************************************',
+ '*****************************************************',
+ 'WARNING: The remaining tests are going to be retried',
+ 'serially. All tests should be isolated and be able to pass',
+ 'regardless of what else is running.',
+ 'If you see a test that can only pass serially, that test is',
+ 'probably broken and should be fixed.',
+ '*****************************************************',
+ '*****************************************************',
+ '*****************************************************']
+
+
+def gen_gtest_output_dir(cwd, gtest_output):
+ """Converts gtest_output to an actual path that can be used in parallel.
+
+ Returns a 'corrected' gtest_output value.
+ """
+ if not gtest_output.startswith('xml'):
+ raise Failure('Can\'t parse --gtest_output=%s' % gtest_output)
+ # Figure out the result filepath in case we can't parse it, it'd be
+ # annoying to error out *after* running the tests.
+ if gtest_output == 'xml':
+ gtest_output = os.path.join(cwd, 'test_detail.xml')
+ else:
+ match = re.match(r'xml\:(.+)', gtest_output)
+ if not match:
+ raise Failure('Can\'t parse --gtest_output=%s' % gtest_output)
+ # If match.group(1) is an absolute path, os.path.join() will do the right
+ # thing.
+ if match.group(1).endswith((os.path.sep, '/')):
+ gtest_output = os.path.join(cwd, match.group(1), 'test_detail.xml')
+ else:
+ gtest_output = os.path.join(cwd, match.group(1))
+
+ base_path = os.path.dirname(gtest_output)
+ if base_path and not os.path.isdir(base_path):
+ os.makedirs(base_path)
+
+ # Emulate google-test' automatic increasing index number.
+ while True:
+ try:
+ # Creates a file exclusively.
+ os.close(os.open(gtest_output, os.O_CREAT|os.O_EXCL|os.O_RDWR, 0666))
+ # It worked, we are done.
+ return gtest_output
+ except OSError:
+ pass
+ logging.debug('%s existed', gtest_output)
+ base, ext = os.path.splitext(gtest_output)
+ match = re.match(r'^(.+?_)(\d+)$', base)
+ if match:
+ base = match.group(1) + str(int(match.group(2)) + 1)
+ else:
+ base = base + '_0'
+ gtest_output = base + ext
+
+
+def calc_cluster_default(num_test_cases, jobs):
+ """Calculates a desired number for clusters depending on the number of test
+ cases and parallel jobs.
+ """
+ if not num_test_cases:
+ return 0
+ chunks = 6 * jobs
+ if chunks >= num_test_cases:
+ # Too many chunks, use 1~5 test case per thread. Not enough to start
+ # chunking.
+ value = num_test_cases / jobs
+ else:
+ # Use chunks that are spread across threads.
+ value = (num_test_cases + chunks - 1) / chunks
+ # Limit to 10 test cases per cluster.
+ return min(10, max(1, value))
+
+
+def run_test_cases(
+ cmd, cwd, test_cases, jobs, timeout, clusters, retries, run_all,
+ max_failures, no_cr, gtest_output, result_file, verbose):
+ """Runs test cases in parallel.
+
+ Arguments:
+ - cmd: command to run.
+ - cwd: working directory.
+ - test_cases: list of preprocessed test cases to run.
+ - jobs: number of parallel execution threads to do.
+ - timeout: individual test case timeout. Modulated when used with
+ clustering.
+ - clusters: number of test cases to lump together in a single execution. 0
+ means the default automatic value which depends on len(test_cases) and
+ jobs. Capped to len(test_cases) / jobs.
+ - retries: number of times a test case can be retried.
+ - run_all: If true, do not early return even if all test cases fail.
+ - max_failures is the absolute maximum number of tolerated failures or None.
+ - no_cr: makes output friendly to piped logs.
+ - gtest_output: saves results as xml.
+ - result_file: saves results as json.
+ - verbose: print more details.
+
+ It may run a subset of the test cases if too many test cases failed, as
+ determined with max_failures, retries and run_all.
+ """
+ assert 0 <= retries <= 100000
+ if not test_cases:
+ return 0
+ if run_all:
+ decider = RunAll()
+ else:
+ # If 10% of test cases fail, just too bad.
+ decider = RunSome(len(test_cases), retries, 2, 0.1, max_failures)
+
+ if not clusters:
+ clusters = calc_cluster_default(len(test_cases), jobs)
+ else:
+ # Limit the value.
+ clusters = min(clusters, len(test_cases) / jobs)
+
+ logging.debug('%d test cases with clusters of %d', len(test_cases), clusters)
+
+ if gtest_output:
+ gtest_output = gen_gtest_output_dir(cwd, gtest_output)
+ progress = Progress(len(test_cases))
+ serial_tasks = QueueWithProgress(0)
+ serial_tasks.set_progress(progress)
+
+ def add_serial_task(priority, func, *args, **kwargs):
+ """Adds a serial task, to be executed later."""
+ assert isinstance(priority, int)
+ assert callable(func)
+ serial_tasks.put((priority, func, args, kwargs))
+
+ with ThreadPool(progress, jobs, jobs, len(test_cases)) as pool:
+ runner = ChromiumGoogleTestRunner(
+ cmd,
+ cwd,
+ timeout,
+ progress,
+ retries,
+ decider,
+ verbose,
+ pool.add_task,
+ add_serial_task)
+ function = runner.map
+ progress.use_cr_only = not no_cr
+ # Cluster the test cases right away.
+ for i in xrange((len(test_cases) + clusters - 1) / clusters):
+ cluster = test_cases[i*clusters : (i+1)*clusters]
+ pool.add_task(i, function, i, cluster, 0)
+ results = pool.join()
+
+ # Retry any failed tests serially.
+ if not serial_tasks.empty():
+ progress.update_item('\n'.join(running_serial_warning()), index=False,
+ size=False)
+ progress.print_update()
+
+ while not serial_tasks.empty():
+ _priority, func, args, kwargs = serial_tasks.get()
+ for out in func(*args, **kwargs):
+ results.append(out)
+ serial_tasks.task_done()
+ progress.print_update()
+
+ # Call join since that is a standard call once a queue has been emptied.
+ serial_tasks.join()
+
+ duration = time.time() - pool.tasks.progress.start
+
+ cleaned = {}
+ for i in results:
+ cleaned.setdefault(i['test_case'], []).append(i)
+ results = cleaned
+
+ # Total time taken to run each test case.
+ test_case_duration = dict(
+ (test_case, sum((i.get('duration') or 0) for i in item))
+ for test_case, item in results.iteritems())
+
+ # Classify the results
+ success = []
+ flaky = []
+ fail = []
+ nb_runs = 0
+ for test_case in sorted(results):
+ items = results[test_case]
+ nb_runs += len(items)
+ if not any(i['returncode'] == 0 for i in items):
+ fail.append(test_case)
+ elif len(items) > 1 and any(i['returncode'] == 0 for i in items):
+ flaky.append(test_case)
+ elif len(items) == 1 and items[0]['returncode'] == 0:
+ success.append(test_case)
+ else:
+ # The test never ran.
+ assert False, items
+ missing = sorted(set(test_cases) - set(success) - set(flaky) - set(fail))
+
+ saved = {
+ 'test_cases': results,
+ 'expected': len(test_cases),
+ 'success': success,
+ 'flaky': flaky,
+ 'fail': fail,
+ 'missing': missing,
+ 'duration': duration,
+ }
+ if result_file:
+ dump_results_as_json(result_file, saved)
+ if gtest_output:
+ dump_results_as_xml(gtest_output, saved, datetime.datetime.now())
+ sys.stdout.write('\n')
+ if not results:
+ return 1
+
+ if flaky:
+ print('Flaky tests:')
+ for test_case in sorted(flaky):
+ items = results[test_case]
+ print(' %s (tried %d times)' % (test_case, len(items)))
+
+ if fail:
+ print('Failed tests:')
+ for test_case in sorted(fail):
+ print(' %s' % test_case)
+
+ if not decider.should_stop() and missing:
+ print('Missing tests:')
+ for test_case in sorted(missing):
+ print(' %s' % test_case)
+
+ print('Summary:')
+ if decider.should_stop():
+ print(' ** STOPPED EARLY due to high failure rate **')
+ output = [
+ ('Success', success),
+ ('Flaky', flaky),
+ ('Fail', fail),
+ ]
+ if missing:
+ output.append(('Missing', missing))
+ total_expected = len(test_cases)
+ for name, items in output:
+ number = len(items)
+ print(
+ ' %7s: %4d %6.2f%% %7.2fs' % (
+ name,
+ number,
+ number * 100. / total_expected,
+ sum(test_case_duration.get(item, 0) for item in items)))
+ print(' %.2fs Done running %d tests with %d executions. %.2f test/s' % (
+ duration,
+ len(results),
+ nb_runs,
+ nb_runs / duration if duration else 0))
+ return int(bool(fail) or decider.stopped or bool(missing))
+
+
+class OptionParserWithLogging(run_isolated.OptionParserWithLogging):
+ def __init__(self, **kwargs):
+ run_isolated.OptionParserWithLogging.__init__(
+ self,
+ log_file=os.environ.get('RUN_TEST_CASES_LOG_FILE', ''),
+ **kwargs)
+
+
+class OptionParserWithTestSharding(OptionParserWithLogging):
+ """Adds automatic handling of test sharding"""
+ def __init__(self, **kwargs):
+ OptionParserWithLogging.__init__(self, **kwargs)
+
+ def as_digit(variable, default):
+ return int(variable) if variable.isdigit() else default
+
+ group = optparse.OptionGroup(self, 'Which shard to select')
+ group.add_option(
+ '-I', '--index',
+ type='int',
+ default=as_digit(os.environ.get('GTEST_SHARD_INDEX', ''), None),
+ help='Shard index to select')
+ group.add_option(
+ '-S', '--shards',
+ type='int',
+ default=as_digit(os.environ.get('GTEST_TOTAL_SHARDS', ''), None),
+ help='Total number of shards to calculate from the --index to select')
+ self.add_option_group(group)
+
+ def parse_args(self, *args, **kwargs):
+ options, args = OptionParserWithLogging.parse_args(self, *args, **kwargs)
+ if bool(options.shards) != bool(options.index is not None):
+ self.error('Use both --index X --shards Y or none of them')
+ return options, args
+
+
+class OptionParserWithTestShardingAndFiltering(OptionParserWithTestSharding):
+ """Adds automatic handling of test sharding and filtering."""
+ def __init__(self, *args, **kwargs):
+ OptionParserWithTestSharding.__init__(self, *args, **kwargs)
+
+ group = optparse.OptionGroup(self, 'Which test cases to select')
+ group.add_option(
+ '-w', '--whitelist',
+ default=[],
+ action='append',
+ help='filter to apply to test cases to run, wildcard-style, defaults '
+ 'to all test')
+ group.add_option(
+ '-b', '--blacklist',
+ default=[],
+ action='append',
+ help='filter to apply to test cases to skip, wildcard-style, defaults '
+ 'to no test')
+ group.add_option(
+ '-T', '--test-case-file',
+ help='File containing the exact list of test cases to run')
+ group.add_option(
+ '--gtest_filter',
+ default=os.environ.get('GTEST_FILTER', ''),
+ help='Select test cases like google-test does, separated with ":"')
+ group.add_option(
+ '--seed',
+ type='int',
+ default=os.environ.get('GTEST_RANDOM_SEED', '1'),
+ help='Deterministically shuffle the test list if non-0. default: '
+ '%default')
+ group.add_option(
+ '-d', '--disabled',
+ action='store_true',
+ default=int(os.environ.get('GTEST_ALSO_RUN_DISABLED_TESTS', '0')),
+ help='Include DISABLED_ tests')
+ group.add_option(
+ '--gtest_also_run_disabled_tests',
+ action='store_true',
+ dest='disabled',
+ help='same as --disabled')
+ self.add_option_group(group)
+
+ group = optparse.OptionGroup(
+ self, 'Which test cases to select; chromium-specific')
+ group.add_option(
+ '-f', '--fails',
+ action='store_true',
+ help='Include FAILS_ tests')
+ group.add_option(
+ '-F', '--flaky',
+ action='store_true',
+ help='Include FLAKY_ tests')
+ group.add_option(
+ '-m', '--manual',
+ action='store_true',
+ help='Include MANUAL_ tests')
+ group.add_option(
+ '--run-manual',
+ action='store_true',
+ dest='manual',
+ help='same as --manual')
+ self.add_option_group(group)
+
+ def parse_args(self, *args, **kwargs):
+ options, args = OptionParserWithTestSharding.parse_args(
+ self, *args, **kwargs)
+
+ if options.gtest_filter:
+ # Override any other option.
+ # Based on UnitTestOptions::FilterMatchesTest() in
+ # http://code.google.com/p/googletest/source/browse/#svn%2Ftrunk%2Fsrc
+ if '-' in options.gtest_filter:
+ options.whitelist, options.blacklist = options.gtest_filter.split('-',
+ 1)
+ else:
+ options.whitelist = options.gtest_filter
+ options.blacklist = ''
+ options.whitelist = [i for i in options.whitelist.split(':') if i]
+ options.blacklist = [i for i in options.blacklist.split(':') if i]
+
+ return options, args
+
+ @staticmethod
+ def process_gtest_options(cmd, cwd, options):
+ """Grabs the test cases."""
+ if options.test_case_file:
+ with open(options.test_case_file, 'r') as f:
+ # Do not shuffle or alter the file in any way in that case except to
+ # strip whitespaces.
+ return [l for l in (l.strip() for l in f) if l]
+ else:
+ return get_test_cases(
+ cmd,
+ cwd,
+ options.whitelist,
+ options.blacklist,
+ options.index,
+ options.shards,
+ options.seed,
+ options.disabled,
+ options.fails,
+ options.flaky,
+ options.manual)
+
+
+class OptionParserTestCases(OptionParserWithTestShardingAndFiltering):
+ def __init__(self, *args, **kwargs):
+ OptionParserWithTestShardingAndFiltering.__init__(self, *args, **kwargs)
+ self.add_option(
+ '-j', '--jobs',
+ type='int',
+ default=run_isolated.num_processors(),
+ help='Number of parallel jobs; default=%default')
+ self.add_option(
+ '--use-less-jobs',
+ action='store_const',
+ const=max(1, run_isolated.num_processors() / 2),
+ dest='jobs',
+ help='Starts less parallel jobs than the default, used to help reduce'
+ 'contention between threads if all the tests are very CPU heavy.')
+ self.add_option(
+ '-t', '--timeout',
+ type='int',
+ default=75,
+ help='Timeout for a single test case, in seconds default:%default')
+ self.add_option(
+ '--clusters',
+ type='int',
+ help='Number of test cases to cluster together, clamped to '
+ 'len(test_cases) / jobs; the default is automatic')
+
+
+def process_args(argv):
+ parser = OptionParserTestCases(
+ usage='%prog <options> [gtest]',
+ verbose=int(os.environ.get('ISOLATE_DEBUG', 0)))
+ parser.add_option(
+ '--run-all',
+ action='store_true',
+ help='Do not fail early when a large number of test cases fail')
+ parser.add_option(
+ '--max-failures', type='int',
+ help='Limit the number of failures before aborting')
+ parser.add_option(
+ '--retries', type='int', default=2,
+ help='Number of times each test case should be retried in case of '
+ 'failure.')
+ parser.add_option(
+ '--no-dump',
+ action='store_true',
+ help='do not generate a .run_test_cases file')
+ parser.add_option(
+ '--no-cr',
+ action='store_true',
+ help='Use LF instead of CR for status progress')
+ parser.add_option(
+ '--result',
+ help='Override the default name of the generated .run_test_cases file')
+
+ group = optparse.OptionGroup(parser, 'google-test compability flags')
+ group.add_option(
+ '--gtest_list_tests',
+ action='store_true',
+ help='List all the test cases unformatted. Keeps compatibility with the '
+ 'executable itself.')
+ group.add_option(
+ '--gtest_output',
+ default=os.environ.get('GTEST_OUTPUT', ''),
+ help='XML output to generate')
+ parser.add_option_group(group)
+
+ options, args = parser.parse_args(argv)
+
+ if not args:
+ parser.error(
+ 'Please provide the executable line to run, if you need fancy things '
+ 'like xvfb, start this script from *inside* xvfb, it\'ll be much faster'
+ '.')
+
+ if options.run_all and options.max_failures is not None:
+ parser.error('Use only one of --run-all or --max-failures')
+ return parser, options, run_isolated.fix_python_path(args)
+
+
+def main(argv):
+ """CLI frontend to validate arguments."""
+ run_isolated.disable_buffering()
+ parser, options, cmd = process_args(argv)
+
+ if options.gtest_list_tests:
+ # Special case, return the output of the target unmodified.
+ return subprocess.call(cmd + ['--gtest_list_tests'])
+
+ cwd = os.getcwd()
+ test_cases = parser.process_gtest_options(cmd, cwd, options)
+
+ if options.no_dump:
+ result_file = None
+ else:
+ result_file = options.result
+ if not result_file:
+ if cmd[0] == sys.executable:
+ result_file = '%s.run_test_cases' % cmd[1]
+ else:
+ result_file = '%s.run_test_cases' % cmd[0]
+
+ if not test_cases:
+ # The fact of not running any test is considered a failure. This is to
+ # prevent silent failure with an invalid --gtest_filter argument or because
+ # of a misconfigured unit test.
+ if test_cases is not None:
+ print('Found no test to run')
+ if result_file:
+ dump_results_as_json(result_file, {
+ 'test_cases': [],
+ 'expected': 0,
+ 'success': [],
+ 'flaky': [],
+ 'fail': [],
+ 'missing': [],
+ 'duration': 0,
+ })
+ return 1
+
+ if options.disabled:
+ cmd.append('--gtest_also_run_disabled_tests')
+ if options.manual:
+ cmd.append('--run-manual')
+
+ try:
+ return run_test_cases(
+ cmd,
+ cwd,
+ test_cases,
+ options.jobs,
+ options.timeout,
+ options.clusters,
+ options.retries,
+ options.run_all,
+ options.max_failures,
+ options.no_cr,
+ options.gtest_output,
+ result_file,
+ options.verbose)
+ except Failure as e:
+ print >> sys.stderr, e.args[0]
+ return 1
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/swarm_client/googletest/shard_test_cases.py b/chromium/tools/swarm_client/googletest/shard_test_cases.py
new file mode 100755
index 00000000000..838a0b6a89a
--- /dev/null
+++ b/chromium/tools/swarm_client/googletest/shard_test_cases.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs a google-test shard.
+
+This makes a simple interface to run a shard on the command line independent of
+the interpreter, e.g. cmd.exe vs bash.
+"""
+
+import optparse
+import os
+import subprocess
+import sys
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if not ROOT_DIR in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import run_isolated
+
+
+def main():
+ run_isolated.disable_buffering()
+ parser = optparse.OptionParser(usage='%prog <options> [gtest]')
+ parser.disable_interspersed_args()
+ parser.add_option(
+ '-I', '--index',
+ type='int',
+ default=os.environ.get('GTEST_SHARD_INDEX'),
+ help='Shard index to run')
+ parser.add_option(
+ '-S', '--shards',
+ type='int',
+ default=os.environ.get('GTEST_TOTAL_SHARDS'),
+ help='Total number of shards to calculate from the --index to run')
+ options, args = parser.parse_args()
+ env = os.environ.copy()
+ env['GTEST_TOTAL_SHARDS'] = str(options.shards)
+ env['GTEST_SHARD_INDEX'] = str(options.index)
+ return subprocess.call(run_isolated.fix_python_path(args), env=env)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/googletest/trace_test_cases.py b/chromium/tools/swarm_client/googletest/trace_test_cases.py
new file mode 100755
index 00000000000..24e562ac094
--- /dev/null
+++ b/chromium/tools/swarm_client/googletest/trace_test_cases.py
@@ -0,0 +1,204 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Traces each test cases of a google-test executable individually.
+
+Gives detailed information about each test case. The logs can be read afterward
+with ./trace_inputs.py read -l /path/to/executable.logs
+"""
+
+import logging
+import multiprocessing
+import os
+import sys
+import time
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if not ROOT_DIR in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import run_isolated
+import run_test_cases
+import trace_inputs
+
+
+def sanitize_test_case_name(test_case):
+ """Removes characters that are valid as test case names but invalid as file
+ names.
+ """
+ return test_case.replace('/', '-')
+
+
+class Tracer(object):
+ def __init__(self, tracer, cmd, cwd_dir, progress):
+ # Constants
+ self.tracer = tracer
+ self.cmd = cmd[:]
+ self.cwd_dir = cwd_dir
+ self.progress = progress
+
+ def map(self, test_case):
+ """Traces a single test case and returns its output."""
+ cmd = self.cmd[:]
+ cmd.append('--gtest_filter=%s' % test_case)
+ tracename = sanitize_test_case_name(test_case)
+
+ out = []
+ for retry in range(5):
+ start = time.time()
+ returncode, output = self.tracer.trace(cmd, self.cwd_dir, tracename, True)
+ duration = time.time() - start
+ # TODO(maruel): Define a way to detect if a strace log is valid.
+ valid = True
+ out.append(
+ {
+ 'test_case': test_case,
+ 'tracename': tracename,
+ 'returncode': returncode,
+ 'duration': duration,
+ 'valid': valid,
+ 'output': output,
+ })
+ logging.debug(
+ 'Tracing %s done: %d, %.1fs' % (test_case, returncode, duration))
+ if retry:
+ self.progress.update_item(
+ '%s - %d' % (test_case, retry), True, not valid)
+ else:
+ self.progress.update_item(test_case, True, not valid)
+ if valid:
+ break
+ return out
+
+
+def trace_test_cases(cmd, cwd_dir, test_cases, jobs, logname):
+ """Traces each test cases individually but all in parallel."""
+ assert os.path.isabs(cwd_dir) and os.path.isdir(cwd_dir), cwd_dir
+
+ if not test_cases:
+ return []
+
+ # Resolve any symlink.
+ cwd_dir = os.path.realpath(cwd_dir)
+ assert os.path.isdir(cwd_dir)
+
+ api = trace_inputs.get_api()
+ api.clean_trace(logname)
+
+ jobs = jobs or multiprocessing.cpu_count()
+ # Try to do black magic here by guessing a few of the run_test_cases.py
+ # flags. It's cheezy but it works.
+ for i, v in enumerate(cmd):
+ if v.endswith('run_test_cases.py'):
+ # Found it. Process the arguments here.
+ _, options, _ = run_test_cases.process_args(cmd[i:])
+ # Always override with the lowest value.
+ jobs = min(options.jobs, jobs)
+ break
+
+ progress = run_test_cases.Progress(len(test_cases))
+ with run_test_cases.ThreadPool(progress, jobs, jobs,
+ len(test_cases)) as pool:
+ with api.get_tracer(logname) as tracer:
+ function = Tracer(tracer, cmd, cwd_dir, progress).map
+ for test_case in test_cases:
+ pool.add_task(0, function, test_case)
+
+ results = pool.join()
+ print('')
+ return results
+
+
+def write_details(logname, outfile, root_dir, blacklist, results):
+ """Writes an .test_cases file with all the information about each test
+ case.
+ """
+ api = trace_inputs.get_api()
+ logs = dict(
+ (i.pop('trace'), i) for i in api.parse_log(logname, blacklist, None))
+ results_processed = {}
+ exception = None
+ for items in results:
+ item = items[-1]
+ assert item['valid']
+ # Load the results;
+ log_dict = logs[item['tracename']]
+ if log_dict.get('exception'):
+ exception = exception or log_dict['exception']
+ continue
+ trace_result = log_dict['results']
+ if root_dir:
+ trace_result = trace_result.strip_root(root_dir)
+ results_processed[item['test_case']] = {
+ 'trace': trace_result.flatten(),
+ 'duration': item['duration'],
+ 'output': item['output'],
+ 'returncode': item['returncode'],
+ }
+
+ # Make it dense if there is more than 20 results.
+ trace_inputs.write_json(
+ outfile,
+ results_processed,
+ len(results_processed) > 20)
+ if exception:
+ raise exception[0], exception[1], exception[2]
+
+
+def main():
+ """CLI frontend to validate arguments."""
+ run_isolated.disable_buffering()
+ parser = run_test_cases.OptionParserTestCases(
+ usage='%prog <options> [gtest]')
+ parser.format_description = lambda *_: parser.description
+ parser.add_option(
+ '-o', '--out',
+ help='output file, defaults to <executable>.test_cases')
+ parser.add_option(
+ '-r', '--root-dir',
+ help='Root directory under which file access should be noted')
+ parser.add_option(
+ '--trace-blacklist', action='append', default=[],
+ help='List of regexp to use as blacklist filter')
+ # TODO(maruel): Add support for options.timeout.
+ parser.remove_option('--timeout')
+ options, args = parser.parse_args()
+
+ if not args:
+ parser.error(
+ 'Please provide the executable line to run, if you need fancy things '
+ 'like xvfb, start this script from *inside* xvfb, it\'ll be much faster'
+ '.')
+
+ cmd = run_isolated.fix_python_path(args)
+ cmd[0] = os.path.abspath(cmd[0])
+ if not os.path.isfile(cmd[0]):
+ parser.error('Tracing failed for: %s\nIt doesn\'t exit' % ' '.join(cmd))
+
+ if not options.out:
+ options.out = '%s.test_cases' % cmd[-1]
+ options.out = os.path.abspath(options.out)
+ if options.root_dir:
+ options.root_dir = os.path.abspath(options.root_dir)
+ logname = options.out + '.log'
+
+ test_cases = parser.process_gtest_options(cmd, os.getcwd(), options)
+
+ # Then run them.
+ print('Tracing...')
+ results = trace_test_cases(
+ cmd,
+ os.getcwd(),
+ test_cases,
+ options.jobs,
+ logname)
+ print('Reading trace logs...')
+ blacklist = trace_inputs.gen_blacklist(options.trace_blacklist)
+ write_details(logname, options.out, options.root_dir, blacklist, results)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/isolate.py b/chromium/tools/swarm_client/isolate.py
new file mode 100755
index 00000000000..49169f06335
--- /dev/null
+++ b/chromium/tools/swarm_client/isolate.py
@@ -0,0 +1,2393 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Front end tool to manage .isolate files and corresponding tests.
+
+Run ./isolate.py --help for more detailed information.
+
+See more information at
+https://code.google.com/p/swarming/wiki/IsolateDesign
+https://code.google.com/p/swarming/wiki/IsolateUserGuide
+"""
+
+import ast
+import copy
+import hashlib
+import itertools
+import logging
+import optparse
+import os
+import posixpath
+import re
+import stat
+import subprocess
+import sys
+
+import isolateserver_archive
+import run_isolated
+import short_expression_finder
+import trace_inputs
+
+# Import here directly so isolate is easier to use as a library.
+from run_isolated import get_flavor
+
+
+PATH_VARIABLES = ('DEPTH', 'PRODUCT_DIR')
+
+# Files that should be 0-length when mapped.
+KEY_TOUCHED = 'isolate_dependency_touched'
+# Files that should be tracked by the build tool.
+KEY_TRACKED = 'isolate_dependency_tracked'
+# Files that should not be tracked by the build tool.
+KEY_UNTRACKED = 'isolate_dependency_untracked'
+
+
+class ExecutionError(Exception):
+ """A generic error occurred."""
+ def __str__(self):
+ return self.args[0]
+
+
+### Path handling code.
+
+
+DEFAULT_BLACKLIST = (
+ # Temporary vim or python files.
+ r'^.+\.(?:pyc|swp)$',
+ # .git or .svn directory.
+ r'^(?:.+' + re.escape(os.path.sep) + r'|)\.(?:git|svn)$',
+)
+
+
+# Chromium-specific.
+DEFAULT_BLACKLIST += (
+ r'^.+\.(?:run_test_cases)$',
+ r'^(?:.+' + re.escape(os.path.sep) + r'|)testserver\.log$',
+)
+
+
+def relpath(path, root):
+ """os.path.relpath() that keeps trailing os.path.sep."""
+ out = os.path.relpath(path, root)
+ if path.endswith(os.path.sep):
+ out += os.path.sep
+ return out
+
+
+def safe_relpath(filepath, basepath):
+ """Do not throw on Windows when filepath and basepath are on different drives.
+
+ Different than relpath() above since this one doesn't keep the trailing
+ os.path.sep and it swallows exceptions on Windows and return the original
+ absolute path in the case of different drives.
+ """
+ try:
+ return os.path.relpath(filepath, basepath)
+ except ValueError:
+ assert sys.platform == 'win32'
+ return filepath
+
+
+def normpath(path):
+ """os.path.normpath() that keeps trailing os.path.sep."""
+ out = os.path.normpath(path)
+ if path.endswith(os.path.sep):
+ out += os.path.sep
+ return out
+
+
+def posix_relpath(path, root):
+ """posix.relpath() that keeps trailing slash."""
+ out = posixpath.relpath(path, root)
+ if path.endswith('/'):
+ out += '/'
+ return out
+
+
+def cleanup_path(x):
+ """Cleans up a relative path. Converts any os.path.sep to '/' on Windows."""
+ if x:
+ x = x.rstrip(os.path.sep).replace(os.path.sep, '/')
+ if x == '.':
+ x = ''
+ if x:
+ x += '/'
+ return x
+
+
+def is_url(path):
+ return bool(re.match(r'^https?://.+$', path))
+
+
+def path_starts_with(prefix, path):
+ """Returns true if the components of the path |prefix| are the same as the
+ initial components of |path| (or all of the components of |path|). The paths
+ must be absolute.
+ """
+ assert os.path.isabs(prefix) and os.path.isabs(path)
+ prefix = os.path.normpath(prefix)
+ path = os.path.normpath(path)
+ assert prefix == trace_inputs.get_native_path_case(prefix), prefix
+ assert path == trace_inputs.get_native_path_case(path), path
+ prefix = prefix.rstrip(os.path.sep) + os.path.sep
+ path = path.rstrip(os.path.sep) + os.path.sep
+ return path.startswith(prefix)
+
+
+def fix_native_path_case(root, path):
+ """Ensures that each component of |path| has the proper native case by
+ iterating slowly over the directory elements of |path|."""
+ native_case_path = root
+ for raw_part in path.split(os.sep):
+ if not raw_part or raw_part == '.':
+ break
+
+ part = trace_inputs.find_item_native_case(native_case_path, raw_part)
+ if not part:
+ raise run_isolated.MappingError(
+ 'Input file %s doesn\'t exist' %
+ os.path.join(native_case_path, raw_part))
+ native_case_path = os.path.join(native_case_path, part)
+
+ return os.path.normpath(native_case_path)
+
+
+def expand_symlinks(indir, relfile):
+ """Follows symlinks in |relfile|, but treating symlinks that point outside the
+ build tree as if they were ordinary directories/files. Returns the final
+ symlink-free target and a list of paths to symlinks encountered in the
+ process.
+
+ The rule about symlinks outside the build tree is for the benefit of the
+ Chromium OS ebuild, which symlinks the output directory to an unrelated path
+ in the chroot.
+
+ Fails when a directory loop is detected, although in theory we could support
+ that case.
+ """
+ is_directory = relfile.endswith(os.path.sep)
+ done = indir
+ todo = relfile.strip(os.path.sep)
+ symlinks = []
+
+ while todo:
+ pre_symlink, symlink, post_symlink = trace_inputs.split_at_symlink(
+ done, todo)
+ if not symlink:
+ todo = fix_native_path_case(done, todo)
+ done = os.path.join(done, todo)
+ break
+ symlink_path = os.path.join(done, pre_symlink, symlink)
+ post_symlink = post_symlink.lstrip(os.path.sep)
+ # readlink doesn't exist on Windows.
+ # pylint: disable=E1101
+ target = os.path.normpath(os.path.join(done, pre_symlink))
+ symlink_target = os.readlink(symlink_path)
+ if os.path.isabs(symlink_target):
+ # Absolute path are considered a normal directories. The use case is
+ # generally someone who puts the output directory on a separate drive.
+ target = symlink_target
+ else:
+ # The symlink itself could be using the wrong path case.
+ target = fix_native_path_case(target, symlink_target)
+
+ if not os.path.exists(target):
+ raise run_isolated.MappingError(
+ 'Symlink target doesn\'t exist: %s -> %s' % (symlink_path, target))
+ target = trace_inputs.get_native_path_case(target)
+ if not path_starts_with(indir, target):
+ done = symlink_path
+ todo = post_symlink
+ continue
+ if path_starts_with(target, symlink_path):
+ raise run_isolated.MappingError(
+ 'Can\'t map recursive symlink reference %s -> %s' %
+ (symlink_path, target))
+ logging.info('Found symlink: %s -> %s', symlink_path, target)
+ symlinks.append(os.path.relpath(symlink_path, indir))
+ # Treat the common prefix of the old and new paths as done, and start
+ # scanning again.
+ target = target.split(os.path.sep)
+ symlink_path = symlink_path.split(os.path.sep)
+ prefix_length = 0
+ for target_piece, symlink_path_piece in zip(target, symlink_path):
+ if target_piece == symlink_path_piece:
+ prefix_length += 1
+ else:
+ break
+ done = os.path.sep.join(target[:prefix_length])
+ todo = os.path.join(
+ os.path.sep.join(target[prefix_length:]), post_symlink)
+
+ relfile = os.path.relpath(done, indir)
+ relfile = relfile.rstrip(os.path.sep) + is_directory * os.path.sep
+ return relfile, symlinks
+
+
+def expand_directory_and_symlink(indir, relfile, blacklist, follow_symlinks):
+ """Expands a single input. It can result in multiple outputs.
+
+ This function is recursive when relfile is a directory.
+
+ Note: this code doesn't properly handle recursive symlink like one created
+ with:
+ ln -s .. foo
+ """
+ if os.path.isabs(relfile):
+ raise run_isolated.MappingError(
+ 'Can\'t map absolute path %s' % relfile)
+
+ infile = normpath(os.path.join(indir, relfile))
+ if not infile.startswith(indir):
+ raise run_isolated.MappingError(
+ 'Can\'t map file %s outside %s' % (infile, indir))
+
+ filepath = os.path.join(indir, relfile)
+ native_filepath = trace_inputs.get_native_path_case(filepath)
+ if filepath != native_filepath:
+ # Special case './'.
+ if filepath != native_filepath + '.' + os.path.sep:
+ # Give up enforcing strict path case on OSX. Really, it's that sad. The
+ # case where it happens is very specific and hard to reproduce:
+ # get_native_path_case(
+ # u'Foo.framework/Versions/A/Resources/Something.nib') will return
+ # u'Foo.framework/Versions/A/resources/Something.nib', e.g. lowercase 'r'.
+ #
+ # Note that this is really something deep in OSX because running
+ # ls Foo.framework/Versions/A
+ # will print out 'Resources', while trace_inputs.get_native_path_case()
+ # returns a lower case 'r'.
+ #
+ # So *something* is happening under the hood resulting in the command 'ls'
+ # and Carbon.File.FSPathMakeRef('path').FSRefMakePath() to disagree. We
+ # have no idea why.
+ if sys.platform != 'darwin':
+ raise run_isolated.MappingError(
+ 'File path doesn\'t equal native file path\n%s != %s' %
+ (filepath, native_filepath))
+
+ symlinks = []
+ if follow_symlinks:
+ relfile, symlinks = expand_symlinks(indir, relfile)
+
+ if relfile.endswith(os.path.sep):
+ if not os.path.isdir(infile):
+ raise run_isolated.MappingError(
+ '%s is not a directory but ends with "%s"' % (infile, os.path.sep))
+
+ # Special case './'.
+ if relfile.startswith('.' + os.path.sep):
+ relfile = relfile[2:]
+ outfiles = symlinks
+ try:
+ for filename in os.listdir(infile):
+ inner_relfile = os.path.join(relfile, filename)
+ if blacklist(inner_relfile):
+ continue
+ if os.path.isdir(os.path.join(indir, inner_relfile)):
+ inner_relfile += os.path.sep
+ outfiles.extend(
+ expand_directory_and_symlink(indir, inner_relfile, blacklist,
+ follow_symlinks))
+ return outfiles
+ except OSError as e:
+ raise run_isolated.MappingError(
+ 'Unable to iterate over directory %s.\n%s' % (infile, e))
+ else:
+ # Always add individual files even if they were blacklisted.
+ if os.path.isdir(infile):
+ raise run_isolated.MappingError(
+ 'Input directory %s must have a trailing slash' % infile)
+
+ if not os.path.isfile(infile):
+ raise run_isolated.MappingError(
+ 'Input file %s doesn\'t exist' % infile)
+
+ return symlinks + [relfile]
+
+
+def expand_directories_and_symlinks(indir, infiles, blacklist,
+ follow_symlinks, ignore_broken_items):
+ """Expands the directories and the symlinks, applies the blacklist and
+ verifies files exist.
+
+ Files are specified in os native path separator.
+ """
+ outfiles = []
+ for relfile in infiles:
+ try:
+ outfiles.extend(expand_directory_and_symlink(indir, relfile, blacklist,
+ follow_symlinks))
+ except run_isolated.MappingError as e:
+ if ignore_broken_items:
+ logging.info('warning: %s', e)
+ else:
+ raise
+ return outfiles
+
+
+def recreate_tree(outdir, indir, infiles, action, as_sha1):
+ """Creates a new tree with only the input files in it.
+
+ Arguments:
+ outdir: Output directory to create the files in.
+ indir: Root directory the infiles are based in.
+ infiles: dict of files to map from |indir| to |outdir|.
+ action: One of accepted action of run_isolated.link_file().
+ as_sha1: Output filename is the sha1 instead of relfile.
+ """
+ logging.info(
+ 'recreate_tree(outdir=%s, indir=%s, files=%d, action=%s, as_sha1=%s)' %
+ (outdir, indir, len(infiles), action, as_sha1))
+
+ assert os.path.isabs(outdir) and outdir == os.path.normpath(outdir), outdir
+ if not os.path.isdir(outdir):
+ logging.info('Creating %s' % outdir)
+ os.makedirs(outdir)
+
+ for relfile, metadata in infiles.iteritems():
+ infile = os.path.join(indir, relfile)
+ if as_sha1:
+ # Do the hashtable specific checks.
+ if 'l' in metadata:
+ # Skip links when storing a hashtable.
+ continue
+ outfile = os.path.join(outdir, metadata['h'])
+ if os.path.isfile(outfile):
+ # Just do a quick check that the file size matches. No need to stat()
+ # again the input file, grab the value from the dict.
+ if not 's' in metadata:
+ raise run_isolated.MappingError(
+ 'Misconfigured item %s: %s' % (relfile, metadata))
+ if metadata['s'] == os.stat(outfile).st_size:
+ continue
+ else:
+ logging.warn('Overwritting %s' % metadata['h'])
+ os.remove(outfile)
+ else:
+ outfile = os.path.join(outdir, relfile)
+ outsubdir = os.path.dirname(outfile)
+ if not os.path.isdir(outsubdir):
+ os.makedirs(outsubdir)
+
+ # TODO(csharp): Fix crbug.com/150823 and enable the touched logic again.
+ # if metadata.get('T') == True:
+ # open(outfile, 'ab').close()
+ if 'l' in metadata:
+ pointed = metadata['l']
+ logging.debug('Symlink: %s -> %s' % (outfile, pointed))
+ # symlink doesn't exist on Windows.
+ os.symlink(pointed, outfile) # pylint: disable=E1101
+ else:
+ run_isolated.link_file(outfile, infile, action)
+
+
+def process_input(filepath, prevdict, read_only, flavor):
+ """Processes an input file, a dependency, and return meta data about it.
+
+ Arguments:
+ - filepath: File to act on.
+ - prevdict: the previous dictionary. It is used to retrieve the cached sha-1
+ to skip recalculating the hash.
+ - read_only: If True, the file mode is manipulated. In practice, only save
+ one of 4 modes: 0755 (rwx), 0644 (rw), 0555 (rx), 0444 (r). On
+ windows, mode is not set since all files are 'executable' by
+ default.
+
+ Behaviors:
+ - Retrieves the file mode, file size, file timestamp, file link
+ destination if it is a file link and calcultate the SHA-1 of the file's
+ content if the path points to a file and not a symlink.
+ """
+ out = {}
+ # TODO(csharp): Fix crbug.com/150823 and enable the touched logic again.
+ # if prevdict.get('T') == True:
+ # # The file's content is ignored. Skip the time and hard code mode.
+ # if get_flavor() != 'win':
+ # out['m'] = stat.S_IRUSR | stat.S_IRGRP
+ # out['s'] = 0
+ # out['h'] = SHA_1_NULL
+ # out['T'] = True
+ # return out
+
+ # Always check the file stat and check if it is a link. The timestamp is used
+ # to know if the file's content/symlink destination should be looked into.
+ # E.g. only reuse from prevdict if the timestamp hasn't changed.
+ # There is the risk of the file's timestamp being reset to its last value
+ # manually while its content changed. We don't protect against that use case.
+ try:
+ filestats = os.lstat(filepath)
+ except OSError:
+ # The file is not present.
+ raise run_isolated.MappingError('%s is missing' % filepath)
+ is_link = stat.S_ISLNK(filestats.st_mode)
+
+ if flavor != 'win':
+ # Ignore file mode on Windows since it's not really useful there.
+ filemode = stat.S_IMODE(filestats.st_mode)
+ # Remove write access for group and all access to 'others'.
+ filemode &= ~(stat.S_IWGRP | stat.S_IRWXO)
+ if read_only:
+ filemode &= ~stat.S_IWUSR
+ if filemode & stat.S_IXUSR:
+ filemode |= stat.S_IXGRP
+ else:
+ filemode &= ~stat.S_IXGRP
+ out['m'] = filemode
+
+ # Used to skip recalculating the hash or link destination. Use the most recent
+ # update time.
+ # TODO(maruel): Save it in the .state file instead of .isolated so the
+ # .isolated file is deterministic.
+ out['t'] = int(round(filestats.st_mtime))
+
+ if not is_link:
+ out['s'] = filestats.st_size
+ # If the timestamp wasn't updated and the file size is still the same, carry
+ # on the sha-1.
+ if (prevdict.get('t') == out['t'] and
+ prevdict.get('s') == out['s']):
+ # Reuse the previous hash if available.
+ out['h'] = prevdict.get('h')
+ if not out.get('h'):
+ out['h'] = isolateserver_archive.sha1_file(filepath)
+ else:
+ # If the timestamp wasn't updated, carry on the link destination.
+ if prevdict.get('t') == out['t']:
+ # Reuse the previous link destination if available.
+ out['l'] = prevdict.get('l')
+ if out.get('l') is None:
+ # The link could be in an incorrect path case. In practice, this only
+ # happen on OSX on case insensitive HFS.
+ # TODO(maruel): It'd be better if it was only done once, in
+ # expand_directory_and_symlink(), so it would not be necessary to do again
+ # here.
+ symlink_value = os.readlink(filepath) # pylint: disable=E1101
+ filedir = trace_inputs.get_native_path_case(os.path.dirname(filepath))
+ native_dest = fix_native_path_case(filedir, symlink_value)
+ out['l'] = os.path.relpath(native_dest, filedir)
+ return out
+
+
+### Variable stuff.
+
+
+def isolatedfile_to_state(filename):
+ """Replaces the file's extension."""
+ return filename + '.state'
+
+
+def determine_root_dir(relative_root, infiles):
+ """For a list of infiles, determines the deepest root directory that is
+ referenced indirectly.
+
+ All arguments must be using os.path.sep.
+ """
+ # The trick used to determine the root directory is to look at "how far" back
+ # up it is looking up.
+ deepest_root = relative_root
+ for i in infiles:
+ x = relative_root
+ while i.startswith('..' + os.path.sep):
+ i = i[3:]
+ assert not i.startswith(os.path.sep)
+ x = os.path.dirname(x)
+ if deepest_root.startswith(x):
+ deepest_root = x
+ logging.debug(
+ 'determine_root_dir(%s, %d files) -> %s' % (
+ relative_root, len(infiles), deepest_root))
+ return deepest_root
+
+
+def replace_variable(part, variables):
+ m = re.match(r'<\(([A-Z_]+)\)', part)
+ if m:
+ if m.group(1) not in variables:
+ raise ExecutionError(
+ 'Variable "%s" was not found in %s.\nDid you forget to specify '
+ '--variable?' % (m.group(1), variables))
+ return variables[m.group(1)]
+ return part
+
+
+def process_variables(cwd, variables, relative_base_dir):
+ """Processes path variables as a special case and returns a copy of the dict.
+
+ For each 'path' variable: first normalizes it based on |cwd|, verifies it
+ exists then sets it as relative to relative_base_dir.
+ """
+ relative_base_dir = trace_inputs.get_native_path_case(relative_base_dir)
+ variables = variables.copy()
+ for i in PATH_VARIABLES:
+ if i not in variables:
+ continue
+ variable = variables[i].strip()
+ # Variables could contain / or \ on windows. Always normalize to
+ # os.path.sep.
+ variable = variable.replace('/', os.path.sep)
+ variable = os.path.join(cwd, variable)
+ variable = os.path.normpath(variable)
+ variable = trace_inputs.get_native_path_case(variable)
+ if not os.path.isdir(variable):
+ raise ExecutionError('%s=%s is not a directory' % (i, variable))
+
+ # All variables are relative to the .isolate file.
+ variable = os.path.relpath(variable, relative_base_dir)
+ logging.debug(
+ 'Translated variable %s from %s to %s', i, variables[i], variable)
+ variables[i] = variable
+ return variables
+
+
+def eval_variables(item, variables):
+ """Replaces the .isolate variables in a string item.
+
+ Note that the .isolate format is a subset of the .gyp dialect.
+ """
+ return ''.join(
+ replace_variable(p, variables) for p in re.split(r'(<\([A-Z_]+\))', item))
+
+
+def classify_files(root_dir, tracked, untracked):
+ """Converts the list of files into a .isolate 'variables' dictionary.
+
+ Arguments:
+ - tracked: list of files names to generate a dictionary out of that should
+ probably be tracked.
+ - untracked: list of files names that must not be tracked.
+ """
+ # These directories are not guaranteed to be always present on every builder.
+ OPTIONAL_DIRECTORIES = (
+ 'test/data/plugin',
+ 'third_party/WebKit/LayoutTests',
+ )
+
+ new_tracked = []
+ new_untracked = list(untracked)
+
+ def should_be_tracked(filepath):
+ """Returns True if it is a file without whitespace in a non-optional
+ directory that has no symlink in its path.
+ """
+ if filepath.endswith('/'):
+ return False
+ if ' ' in filepath:
+ return False
+ if any(i in filepath for i in OPTIONAL_DIRECTORIES):
+ return False
+ # Look if any element in the path is a symlink.
+ split = filepath.split('/')
+ for i in range(len(split)):
+ if os.path.islink(os.path.join(root_dir, '/'.join(split[:i+1]))):
+ return False
+ return True
+
+ for filepath in sorted(tracked):
+ if should_be_tracked(filepath):
+ new_tracked.append(filepath)
+ else:
+ # Anything else.
+ new_untracked.append(filepath)
+
+ variables = {}
+ if new_tracked:
+ variables[KEY_TRACKED] = sorted(new_tracked)
+ if new_untracked:
+ variables[KEY_UNTRACKED] = sorted(new_untracked)
+ return variables
+
+
+def chromium_fix(f, variables):
+ """Fixes an isolate dependnecy with Chromium-specific fixes."""
+ # Skip log in PRODUCT_DIR. Note that these are applied on '/' style path
+ # separator.
+ LOG_FILE = re.compile(r'^\<\(PRODUCT_DIR\)\/[^\/]+\.log$')
+ # Ignored items.
+ IGNORED_ITEMS = (
+ # http://crbug.com/160539, on Windows, it's in chrome/.
+ 'Media Cache/',
+ 'chrome/Media Cache/',
+ # 'First Run' is not created by the compile, but by the test itself.
+ '<(PRODUCT_DIR)/First Run')
+
+ # Blacklist logs and other unimportant files.
+ if LOG_FILE.match(f) or f in IGNORED_ITEMS:
+ logging.debug('Ignoring %s', f)
+ return None
+
+ EXECUTABLE = re.compile(
+ r'^(\<\(PRODUCT_DIR\)\/[^\/\.]+)' +
+ re.escape(variables.get('EXECUTABLE_SUFFIX', '')) +
+ r'$')
+ match = EXECUTABLE.match(f)
+ if match:
+ return match.group(1) + '<(EXECUTABLE_SUFFIX)'
+
+ if sys.platform == 'darwin':
+ # On OSX, the name of the output is dependent on gyp define, it can be
+ # 'Google Chrome.app' or 'Chromium.app', same for 'XXX
+ # Framework.framework'. Furthermore, they are versioned with a gyp
+ # variable. To lower the complexity of the .isolate file, remove all the
+ # individual entries that show up under any of the 4 entries and replace
+ # them with the directory itself. Overall, this results in a bit more
+ # files than strictly necessary.
+ OSX_BUNDLES = (
+ '<(PRODUCT_DIR)/Chromium Framework.framework/',
+ '<(PRODUCT_DIR)/Chromium.app/',
+ '<(PRODUCT_DIR)/Google Chrome Framework.framework/',
+ '<(PRODUCT_DIR)/Google Chrome.app/',
+ )
+ for prefix in OSX_BUNDLES:
+ if f.startswith(prefix):
+ # Note this result in duplicate values, so the a set() must be used to
+ # remove duplicates.
+ return prefix
+ return f
+
+
+def generate_simplified(
+ tracked, untracked, touched, root_dir, variables, relative_cwd,
+ trace_blacklist):
+ """Generates a clean and complete .isolate 'variables' dictionary.
+
+ Cleans up and extracts only files from within root_dir then processes
+ variables and relative_cwd.
+ """
+ root_dir = os.path.realpath(root_dir)
+ logging.info(
+ 'generate_simplified(%d files, %s, %s, %s)' %
+ (len(tracked) + len(untracked) + len(touched),
+ root_dir, variables, relative_cwd))
+
+ # Preparation work.
+ relative_cwd = cleanup_path(relative_cwd)
+ assert not os.path.isabs(relative_cwd), relative_cwd
+ # Creates the right set of variables here. We only care about PATH_VARIABLES.
+ path_variables = dict(
+ ('<(%s)' % k, variables[k].replace(os.path.sep, '/'))
+ for k in PATH_VARIABLES if k in variables)
+ variables = variables.copy()
+ variables.update(path_variables)
+
+ # Actual work: Process the files.
+ # TODO(maruel): if all the files in a directory are in part tracked and in
+ # part untracked, the directory will not be extracted. Tracked files should be
+ # 'promoted' to be untracked as needed.
+ tracked = trace_inputs.extract_directories(
+ root_dir, tracked, trace_blacklist)
+ untracked = trace_inputs.extract_directories(
+ root_dir, untracked, trace_blacklist)
+ # touched is not compressed, otherwise it would result in files to be archived
+ # that we don't need.
+
+ root_dir_posix = root_dir.replace(os.path.sep, '/')
+ def fix(f):
+ """Bases the file on the most restrictive variable."""
+ # Important, GYP stores the files with / and not \.
+ f = f.replace(os.path.sep, '/')
+ logging.debug('fix(%s)' % f)
+ # If it's not already a variable.
+ if not f.startswith('<'):
+ # relative_cwd is usually the directory containing the gyp file. It may be
+ # empty if the whole directory containing the gyp file is needed.
+ # Use absolute paths in case cwd_dir is outside of root_dir.
+ # Convert the whole thing to / since it's isolate's speak.
+ f = posix_relpath(
+ posixpath.join(root_dir_posix, f),
+ posixpath.join(root_dir_posix, relative_cwd)) or './'
+
+ for variable, root_path in path_variables.iteritems():
+ if f.startswith(root_path):
+ f = variable + f[len(root_path):]
+ logging.debug('Converted to %s' % f)
+ break
+ return f
+
+ def fix_all(items):
+ """Reduces the items to convert variables, removes unneeded items, apply
+ chromium-specific fixes and only return unique items.
+ """
+ variables_converted = (fix(f.path) for f in items)
+ chromium_fixed = (chromium_fix(f, variables) for f in variables_converted)
+ return set(f for f in chromium_fixed if f)
+
+ tracked = fix_all(tracked)
+ untracked = fix_all(untracked)
+ touched = fix_all(touched)
+ out = classify_files(root_dir, tracked, untracked)
+ if touched:
+ out[KEY_TOUCHED] = sorted(touched)
+ return out
+
+
+def chromium_filter_flags(variables):
+ """Filters out build flags used in Chromium that we don't want to treat as
+ configuration variables.
+ """
+ # TODO(benrg): Need a better way to determine this.
+ blacklist = set(PATH_VARIABLES + ('EXECUTABLE_SUFFIX', 'FLAG'))
+ return dict((k, v) for k, v in variables.iteritems() if k not in blacklist)
+
+
+def generate_isolate(
+ tracked, untracked, touched, root_dir, variables, relative_cwd,
+ trace_blacklist):
+ """Generates a clean and complete .isolate file."""
+ dependencies = generate_simplified(
+ tracked, untracked, touched, root_dir, variables, relative_cwd,
+ trace_blacklist)
+ config_variables = chromium_filter_flags(variables)
+ config_variable_names, config_values = zip(
+ *sorted(config_variables.iteritems()))
+ out = Configs(None)
+ # The new dependencies apply to just one configuration, namely config_values.
+ out.merge_dependencies(dependencies, config_variable_names, [config_values])
+ return out.make_isolate_file()
+
+
+def split_touched(files):
+ """Splits files that are touched vs files that are read."""
+ tracked = []
+ touched = []
+ for f in files:
+ if f.size:
+ tracked.append(f)
+ else:
+ touched.append(f)
+ return tracked, touched
+
+
+def pretty_print(variables, stdout):
+ """Outputs a gyp compatible list from the decoded variables.
+
+ Similar to pprint.print() but with NIH syndrome.
+ """
+ # Order the dictionary keys by these keys in priority.
+ ORDER = (
+ 'variables', 'condition', 'command', 'relative_cwd', 'read_only',
+ KEY_TRACKED, KEY_UNTRACKED)
+
+ def sorting_key(x):
+ """Gives priority to 'most important' keys before the others."""
+ if x in ORDER:
+ return str(ORDER.index(x))
+ return x
+
+ def loop_list(indent, items):
+ for item in items:
+ if isinstance(item, basestring):
+ stdout.write('%s\'%s\',\n' % (indent, item))
+ elif isinstance(item, dict):
+ stdout.write('%s{\n' % indent)
+ loop_dict(indent + ' ', item)
+ stdout.write('%s},\n' % indent)
+ elif isinstance(item, list):
+ # A list inside a list will write the first item embedded.
+ stdout.write('%s[' % indent)
+ for index, i in enumerate(item):
+ if isinstance(i, basestring):
+ stdout.write(
+ '\'%s\', ' % i.replace('\\', '\\\\').replace('\'', '\\\''))
+ elif isinstance(i, dict):
+ stdout.write('{\n')
+ loop_dict(indent + ' ', i)
+ if index != len(item) - 1:
+ x = ', '
+ else:
+ x = ''
+ stdout.write('%s}%s' % (indent, x))
+ else:
+ assert False
+ stdout.write('],\n')
+ else:
+ assert False
+
+ def loop_dict(indent, items):
+ for key in sorted(items, key=sorting_key):
+ item = items[key]
+ stdout.write("%s'%s': " % (indent, key))
+ if isinstance(item, dict):
+ stdout.write('{\n')
+ loop_dict(indent + ' ', item)
+ stdout.write(indent + '},\n')
+ elif isinstance(item, list):
+ stdout.write('[\n')
+ loop_list(indent + ' ', item)
+ stdout.write(indent + '],\n')
+ elif isinstance(item, basestring):
+ stdout.write(
+ '\'%s\',\n' % item.replace('\\', '\\\\').replace('\'', '\\\''))
+ elif item in (True, False, None):
+ stdout.write('%s\n' % item)
+ else:
+ assert False, item
+
+ stdout.write('{\n')
+ loop_dict(' ', variables)
+ stdout.write('}\n')
+
+
+def union(lhs, rhs):
+ """Merges two compatible datastructures composed of dict/list/set."""
+ assert lhs is not None or rhs is not None
+ if lhs is None:
+ return copy.deepcopy(rhs)
+ if rhs is None:
+ return copy.deepcopy(lhs)
+ assert type(lhs) == type(rhs), (lhs, rhs)
+ if hasattr(lhs, 'union'):
+ # Includes set, ConfigSettings and Configs.
+ return lhs.union(rhs)
+ if isinstance(lhs, dict):
+ return dict((k, union(lhs.get(k), rhs.get(k))) for k in set(lhs).union(rhs))
+ elif isinstance(lhs, list):
+ # Do not go inside the list.
+ return lhs + rhs
+ assert False, type(lhs)
+
+
+def extract_comment(content):
+ """Extracts file level comment."""
+ out = []
+ for line in content.splitlines(True):
+ if line.startswith('#'):
+ out.append(line)
+ else:
+ break
+ return ''.join(out)
+
+
+def eval_content(content):
+ """Evaluates a python file and return the value defined in it.
+
+ Used in practice for .isolate files.
+ """
+ globs = {'__builtins__': None}
+ locs = {}
+ try:
+ value = eval(content, globs, locs)
+ except TypeError as e:
+ e.args = list(e.args) + [content]
+ raise
+ assert locs == {}, locs
+ assert globs == {'__builtins__': None}, globs
+ return value
+
+
+def match_configs(expr, config_variables, all_configs):
+ """Returns the configs from |all_configs| that match the |expr|, where
+ the elements of |all_configs| are tuples of values for the |config_variables|.
+ Example:
+ >>> match_configs(expr = "(foo==1 or foo==2) and bar=='b'",
+ config_variables = ["foo", "bar"],
+ all_configs = [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')])
+ [(1, 'b'), (2, 'b')]
+ """
+ return [
+ config for config in all_configs
+ if eval(expr, dict(zip(config_variables, config)))
+ ]
+
+
+def verify_variables(variables):
+ """Verifies the |variables| dictionary is in the expected format."""
+ VALID_VARIABLES = [
+ KEY_TOUCHED,
+ KEY_TRACKED,
+ KEY_UNTRACKED,
+ 'command',
+ 'read_only',
+ ]
+ assert isinstance(variables, dict), variables
+ assert set(VALID_VARIABLES).issuperset(set(variables)), variables.keys()
+ for name, value in variables.iteritems():
+ if name == 'read_only':
+ assert value in (True, False, None), value
+ else:
+ assert isinstance(value, list), value
+ assert all(isinstance(i, basestring) for i in value), value
+
+
+def verify_ast(expr, variables_and_values):
+ """Verifies that |expr| is of the form
+ expr ::= expr ( "or" | "and" ) expr
+ | identifier "==" ( string | int )
+ Also collects the variable identifiers and string/int values in the dict
+ |variables_and_values|, in the form {'var': set([val1, val2, ...]), ...}.
+ """
+ assert isinstance(expr, (ast.BoolOp, ast.Compare))
+ if isinstance(expr, ast.BoolOp):
+ assert isinstance(expr.op, (ast.And, ast.Or))
+ for subexpr in expr.values:
+ verify_ast(subexpr, variables_and_values)
+ else:
+ assert isinstance(expr.left.ctx, ast.Load)
+ assert len(expr.ops) == 1
+ assert isinstance(expr.ops[0], ast.Eq)
+ var_values = variables_and_values.setdefault(expr.left.id, set())
+ rhs = expr.comparators[0]
+ assert isinstance(rhs, (ast.Str, ast.Num))
+ var_values.add(rhs.n if isinstance(rhs, ast.Num) else rhs.s)
+
+
+def verify_condition(condition, variables_and_values):
+ """Verifies the |condition| dictionary is in the expected format.
+ See verify_ast() for the meaning of |variables_and_values|.
+ """
+ VALID_INSIDE_CONDITION = ['variables']
+ assert isinstance(condition, list), condition
+ assert len(condition) == 2, condition
+ expr, then = condition
+
+ test_ast = compile(expr, '<condition>', 'eval', ast.PyCF_ONLY_AST)
+ verify_ast(test_ast.body, variables_and_values)
+
+ assert isinstance(then, dict), then
+ assert set(VALID_INSIDE_CONDITION).issuperset(set(then)), then.keys()
+ verify_variables(then['variables'])
+
+
+def verify_root(value, variables_and_values):
+ """Verifies that |value| is the parsed form of a valid .isolate file.
+ See verify_ast() for the meaning of |variables_and_values|.
+ """
+ VALID_ROOTS = ['includes', 'conditions']
+ assert isinstance(value, dict), value
+ assert set(VALID_ROOTS).issuperset(set(value)), value.keys()
+
+ includes = value.get('includes', [])
+ assert isinstance(includes, list), includes
+ for include in includes:
+ assert isinstance(include, basestring), include
+
+ conditions = value.get('conditions', [])
+ assert isinstance(conditions, list), conditions
+ for condition in conditions:
+ verify_condition(condition, variables_and_values)
+
+
+def remove_weak_dependencies(values, key, item, item_configs):
+ """Removes any configs from this key if the item is already under a
+ strong key.
+ """
+ if key == KEY_TOUCHED:
+ item_configs = set(item_configs)
+ for stronger_key in (KEY_TRACKED, KEY_UNTRACKED):
+ try:
+ item_configs -= values[stronger_key][item]
+ except KeyError:
+ pass
+
+ return item_configs
+
+
+def remove_repeated_dependencies(folders, key, item, item_configs):
+ """Removes any configs from this key if the item is in a folder that is
+ already included."""
+
+ if key in (KEY_UNTRACKED, KEY_TRACKED, KEY_TOUCHED):
+ item_configs = set(item_configs)
+ for (folder, configs) in folders.iteritems():
+ if folder != item and item.startswith(folder):
+ item_configs -= configs
+
+ return item_configs
+
+
+def get_folders(values_dict):
+ """Returns a dict of all the folders in the given value_dict."""
+ return dict(
+ (item, configs) for (item, configs) in values_dict.iteritems()
+ if item.endswith('/')
+ )
+
+
+def invert_map(variables):
+ """Converts {config: {deptype: list(depvals)}} to
+ {deptype: {depval: set(configs)}}.
+ """
+ KEYS = (
+ KEY_TOUCHED,
+ KEY_TRACKED,
+ KEY_UNTRACKED,
+ 'command',
+ 'read_only',
+ )
+ out = dict((key, {}) for key in KEYS)
+ for config, values in variables.iteritems():
+ for key in KEYS:
+ if key == 'command':
+ items = [tuple(values[key])] if key in values else []
+ elif key == 'read_only':
+ items = [values[key]] if key in values else []
+ else:
+ assert key in (KEY_TOUCHED, KEY_TRACKED, KEY_UNTRACKED)
+ items = values.get(key, [])
+ for item in items:
+ out[key].setdefault(item, set()).add(config)
+ return out
+
+
+def reduce_inputs(values):
+ """Reduces the output of invert_map() to the strictest minimum list.
+
+ Looks at each individual file and directory, maps where they are used and
+ reconstructs the inverse dictionary.
+
+ Returns the minimized dictionary.
+ """
+ KEYS = (
+ KEY_TOUCHED,
+ KEY_TRACKED,
+ KEY_UNTRACKED,
+ 'command',
+ 'read_only',
+ )
+
+ # Folders can only live in KEY_UNTRACKED.
+ folders = get_folders(values.get(KEY_UNTRACKED, {}))
+
+ out = dict((key, {}) for key in KEYS)
+ for key in KEYS:
+ for item, item_configs in values.get(key, {}).iteritems():
+ item_configs = remove_weak_dependencies(values, key, item, item_configs)
+ item_configs = remove_repeated_dependencies(
+ folders, key, item, item_configs)
+ if item_configs:
+ out[key][item] = item_configs
+ return out
+
+
+def convert_map_to_isolate_dict(values, config_variables):
+ """Regenerates back a .isolate configuration dict from files and dirs
+ mappings generated from reduce_inputs().
+ """
+ # Gather a list of configurations for set inversion later.
+ all_mentioned_configs = set()
+ for configs_by_item in values.itervalues():
+ for configs in configs_by_item.itervalues():
+ all_mentioned_configs.update(configs)
+
+ # Invert the mapping to make it dict first.
+ conditions = {}
+ for key in values:
+ for item, configs in values[key].iteritems():
+ then = conditions.setdefault(frozenset(configs), {})
+ variables = then.setdefault('variables', {})
+
+ if item in (True, False):
+ # One-off for read_only.
+ variables[key] = item
+ else:
+ assert item
+ if isinstance(item, tuple):
+ # One-off for command.
+ # Do not merge lists and do not sort!
+ # Note that item is a tuple.
+ assert key not in variables
+ variables[key] = list(item)
+ else:
+ # The list of items (files or dirs). Append the new item and keep
+ # the list sorted.
+ l = variables.setdefault(key, [])
+ l.append(item)
+ l.sort()
+
+ if all_mentioned_configs:
+ config_values = map(set, zip(*all_mentioned_configs))
+ sef = short_expression_finder.ShortExpressionFinder(
+ zip(config_variables, config_values))
+
+ conditions = sorted(
+ [sef.get_expr(configs), then] for configs, then in conditions.iteritems())
+ return {'conditions': conditions}
+
+
+### Internal state files.
+
+
+class ConfigSettings(object):
+ """Represents the dependency variables for a single build configuration.
+ The structure is immutable.
+ """
+ def __init__(self, config, values):
+ self.config = config
+ verify_variables(values)
+ self.touched = sorted(values.get(KEY_TOUCHED, []))
+ self.tracked = sorted(values.get(KEY_TRACKED, []))
+ self.untracked = sorted(values.get(KEY_UNTRACKED, []))
+ self.command = values.get('command', [])[:]
+ self.read_only = values.get('read_only')
+
+ def union(self, rhs):
+ assert not (self.config and rhs.config) or (self.config == rhs.config)
+ assert not (self.command and rhs.command) or (self.command == rhs.command)
+ var = {
+ KEY_TOUCHED: sorted(self.touched + rhs.touched),
+ KEY_TRACKED: sorted(self.tracked + rhs.tracked),
+ KEY_UNTRACKED: sorted(self.untracked + rhs.untracked),
+ 'command': self.command or rhs.command,
+ 'read_only': rhs.read_only if self.read_only is None else self.read_only,
+ }
+ return ConfigSettings(self.config or rhs.config, var)
+
+ def flatten(self):
+ out = {}
+ if self.command:
+ out['command'] = self.command
+ if self.touched:
+ out[KEY_TOUCHED] = self.touched
+ if self.tracked:
+ out[KEY_TRACKED] = self.tracked
+ if self.untracked:
+ out[KEY_UNTRACKED] = self.untracked
+ if self.read_only is not None:
+ out['read_only'] = self.read_only
+ return out
+
+
+class Configs(object):
+ """Represents a processed .isolate file.
+
+ Stores the file in a processed way, split by configuration.
+ """
+ def __init__(self, file_comment):
+ self.file_comment = file_comment
+ # The keys of by_config are tuples of values for the configuration
+ # variables. The names of the variables (which must be the same for
+ # every by_config key) are kept in config_variables. Initially by_config
+ # is empty and we don't know what configuration variables will be used,
+ # so config_variables also starts out empty. It will be set by the first
+ # call to union() or merge_dependencies().
+ self.by_config = {}
+ self.config_variables = ()
+
+ def union(self, rhs):
+ """Adds variables from rhs (a Configs) to the existing variables.
+ """
+ config_variables = self.config_variables
+ if not config_variables:
+ config_variables = rhs.config_variables
+ else:
+ # We can't proceed if this isn't true since we don't know the correct
+ # default values for extra variables. The variables are sorted so we
+ # don't need to worry about permutations.
+ if rhs.config_variables and rhs.config_variables != config_variables:
+ raise ExecutionError(
+ 'Variables in merged .isolate files do not match: %r and %r' % (
+ config_variables, rhs.config_variables))
+
+ # Takes the first file comment, prefering lhs.
+ out = Configs(self.file_comment or rhs.file_comment)
+ out.config_variables = config_variables
+ for config in set(self.by_config) | set(rhs.by_config):
+ out.by_config[config] = union(
+ self.by_config.get(config), rhs.by_config.get(config))
+ return out
+
+ def merge_dependencies(self, values, config_variables, configs):
+ """Adds new dependencies to this object for the given configurations.
+ Arguments:
+ values: A variables dict as found in a .isolate file, e.g.,
+ {KEY_TOUCHED: [...], 'command': ...}.
+ config_variables: An ordered list of configuration variables, e.g.,
+ ["OS", "chromeos"]. If this object already contains any dependencies,
+ the configuration variables must match.
+ configs: a list of tuples of values of the configuration variables,
+ e.g., [("mac", 0), ("linux", 1)]. The dependencies in |values|
+ are added to all of these configurations, and other configurations
+ are unchanged.
+ """
+ if not values:
+ return
+
+ if not self.config_variables:
+ self.config_variables = config_variables
+ else:
+ # See comment in Configs.union().
+ assert self.config_variables == config_variables
+
+ for config in configs:
+ self.by_config[config] = union(
+ self.by_config.get(config), ConfigSettings(config, values))
+
+ def flatten(self):
+ """Returns a flat dictionary representation of the configuration.
+ """
+ return dict((k, v.flatten()) for k, v in self.by_config.iteritems())
+
+ def make_isolate_file(self):
+ """Returns a dictionary suitable for writing to a .isolate file.
+ """
+ dependencies_by_config = self.flatten()
+ configs_by_dependency = reduce_inputs(invert_map(dependencies_by_config))
+ return convert_map_to_isolate_dict(configs_by_dependency,
+ self.config_variables)
+
+
+# TODO(benrg): Remove this function when no old-format files are left.
+def convert_old_to_new_format(value):
+ """Converts from the old .isolate format, which only has one variable (OS),
+ always includes 'linux', 'mac' and 'win' in the set of valid values for OS,
+ and allows conditions that depend on the set of all OSes, to the new format,
+ which allows any set of variables, has no hardcoded values, and only allows
+ explicit positive tests of variable values.
+ """
+ conditions = value.get('conditions', [])
+ if 'variables' not in value and all(len(cond) == 2 for cond in conditions):
+ return value # Nothing to change
+
+ def parse_condition(cond):
+ return re.match(r'OS=="(\w+)"\Z', cond[0]).group(1)
+
+ oses = set(map(parse_condition, conditions))
+ default_oses = set(['linux', 'mac', 'win'])
+ oses = sorted(oses | default_oses)
+
+ def if_not_os(not_os, then):
+ expr = ' or '.join('OS=="%s"' % os for os in oses if os != not_os)
+ return [expr, then]
+
+ conditions = [
+ cond[:2] for cond in conditions if cond[1]
+ ] + [
+ if_not_os(parse_condition(cond), cond[2])
+ for cond in conditions if len(cond) == 3
+ ]
+
+ if 'variables' in value:
+ conditions.append(if_not_os(None, {'variables': value.pop('variables')}))
+ conditions.sort()
+
+ value = value.copy()
+ value['conditions'] = conditions
+ return value
+
+
+def load_isolate_as_config(isolate_dir, value, file_comment):
+ """Parses one .isolate file and returns a Configs() instance.
+
+ |value| is the loaded dictionary that was defined in the gyp file.
+
+ The expected format is strict, anything diverting from the format below will
+ throw an assert:
+ {
+ 'includes': [
+ 'foo.isolate',
+ ],
+ 'conditions': [
+ ['OS=="vms" and foo=42', {
+ 'variables': {
+ 'command': [
+ ...
+ ],
+ 'isolate_dependency_tracked': [
+ ...
+ ],
+ 'isolate_dependency_untracked': [
+ ...
+ ],
+ 'read_only': False,
+ },
+ }],
+ ...
+ ],
+ }
+ """
+ value = convert_old_to_new_format(value)
+
+ variables_and_values = {}
+ verify_root(value, variables_and_values)
+ if variables_and_values:
+ config_variables, config_values = zip(
+ *sorted(variables_and_values.iteritems()))
+ all_configs = list(itertools.product(*config_values))
+ else:
+ config_variables = None
+ all_configs = []
+
+ isolate = Configs(file_comment)
+
+ # Add configuration-specific variables.
+ for expr, then in value.get('conditions', []):
+ configs = match_configs(expr, config_variables, all_configs)
+ isolate.merge_dependencies(then['variables'], config_variables, configs)
+
+ # Load the includes.
+ for include in value.get('includes', []):
+ if os.path.isabs(include):
+ raise ExecutionError(
+ 'Failed to load configuration; absolute include path \'%s\'' %
+ include)
+ included_isolate = os.path.normpath(os.path.join(isolate_dir, include))
+ with open(included_isolate, 'r') as f:
+ included_isolate = load_isolate_as_config(
+ os.path.dirname(included_isolate),
+ eval_content(f.read()),
+ None)
+ isolate = union(isolate, included_isolate)
+
+ return isolate
+
+
+def load_isolate_for_config(isolate_dir, content, variables):
+ """Loads the .isolate file and returns the information unprocessed but
+ filtered for the specific OS.
+
+ Returns the command, dependencies and read_only flag. The dependencies are
+ fixed to use os.path.sep.
+ """
+ # Load the .isolate file, process its conditions, retrieve the command and
+ # dependencies.
+ isolate = load_isolate_as_config(isolate_dir, eval_content(content), None)
+ try:
+ config = tuple(variables[var] for var in isolate.config_variables)
+ except KeyError:
+ raise ExecutionError(
+ 'These configuration variables were missing from the command line: %s' %
+ ', '.join(sorted(set(isolate.config_variables) - set(variables))))
+ config = isolate.by_config.get(config)
+ if not config:
+ raise ExecutionError('Failed to load configuration for (%s)' %
+ ', '.join(isolate.config_variables))
+ # Merge tracked and untracked variables, isolate.py doesn't care about the
+ # trackability of the variables, only the build tool does.
+ dependencies = [
+ f.replace('/', os.path.sep) for f in config.tracked + config.untracked
+ ]
+ touched = [f.replace('/', os.path.sep) for f in config.touched]
+ return config.command, dependencies, touched, config.read_only
+
+
+def save_isolated(isolated, data):
+ """Writes one or multiple .isolated files.
+
+ Note: this reference implementation does not create child .isolated file so it
+ always returns an empty list.
+
+ Returns the list of child isolated files that are included by |isolated|.
+ """
+ trace_inputs.write_json(isolated, data, True)
+ return []
+
+
+def chromium_save_isolated(isolated, data, variables):
+ """Writes one or many .isolated files.
+
+ This slightly increases the cold cache cost but greatly reduce the warm cache
+ cost by splitting low-churn files off the master .isolated file. It also
+ reduces overall isolateserver memcache consumption.
+ """
+ slaves = []
+
+ def extract_into_included_isolated(prefix):
+ new_slave = {'files': {}, 'os': data['os']}
+ for f in data['files'].keys():
+ if f.startswith(prefix):
+ new_slave['files'][f] = data['files'].pop(f)
+ if new_slave['files']:
+ slaves.append(new_slave)
+
+ # Split test/data/ in its own .isolated file.
+ extract_into_included_isolated(os.path.join('test', 'data', ''))
+
+ # Split everything out of PRODUCT_DIR in its own .isolated file.
+ if variables.get('PRODUCT_DIR'):
+ extract_into_included_isolated(variables['PRODUCT_DIR'])
+
+ files = []
+ for index, f in enumerate(slaves):
+ slavepath = isolated[:-len('.isolated')] + '.%d.isolated' % index
+ trace_inputs.write_json(slavepath, f, True)
+ data.setdefault('includes', []).append(
+ isolateserver_archive.sha1_file(slavepath))
+ files.append(os.path.basename(slavepath))
+
+ files.extend(save_isolated(isolated, data))
+ return files
+
+
+class Flattenable(object):
+ """Represents data that can be represented as a json file."""
+ MEMBERS = ()
+
+ def flatten(self):
+ """Returns a json-serializable version of itself.
+
+ Skips None entries.
+ """
+ items = ((member, getattr(self, member)) for member in self.MEMBERS)
+ return dict((member, value) for member, value in items if value is not None)
+
+ @classmethod
+ def load(cls, data, *args, **kwargs):
+ """Loads a flattened version."""
+ data = data.copy()
+ out = cls(*args, **kwargs)
+ for member in out.MEMBERS:
+ if member in data:
+ # Access to a protected member XXX of a client class
+ # pylint: disable=W0212
+ out._load_member(member, data.pop(member))
+ if data:
+ raise ValueError(
+ 'Found unexpected entry %s while constructing an object %s' %
+ (data, cls.__name__), data, cls.__name__)
+ return out
+
+ def _load_member(self, member, value):
+ """Loads a member into self."""
+ setattr(self, member, value)
+
+ @classmethod
+ def load_file(cls, filename, *args, **kwargs):
+ """Loads the data from a file or return an empty instance."""
+ try:
+ out = cls.load(trace_inputs.read_json(filename), *args, **kwargs)
+ logging.debug('Loaded %s(%s)', cls.__name__, filename)
+ except (IOError, ValueError):
+ # On failure, loads the default instance.
+ out = cls(*args, **kwargs)
+ logging.warn('Failed to load %s', filename)
+ return out
+
+
+class SavedState(Flattenable):
+ """Describes the content of a .state file.
+
+ This file caches the items calculated by this script and is used to increase
+ the performance of the script. This file is not loaded by run_isolated.py.
+ This file can always be safely removed.
+
+ It is important to note that the 'files' dict keys are using native OS path
+ separator instead of '/' used in .isolate file.
+ """
+ MEMBERS = (
+ # Cache of the processed command. This value is saved because .isolated
+ # files are never loaded by isolate.py so it's the only way to load the
+ # command safely.
+ 'command',
+ # Cache of the files found so the next run can skip sha1 calculation.
+ 'files',
+ # Path of the original .isolate file. Relative path to isolated_basedir.
+ 'isolate_file',
+ # List of included .isolated files. Used to support/remember 'slave'
+ # .isolated files. Relative path to isolated_basedir.
+ 'child_isolated_files',
+ # If the generated directory tree should be read-only.
+ 'read_only',
+ # Relative cwd to use to start the command.
+ 'relative_cwd',
+ # GYP variables used to generate the .isolated file. Variables are saved so
+ # a user can use isolate.py after building and the GYP variables are still
+ # defined.
+ 'variables',
+ )
+
+ def __init__(self, isolated_basedir):
+ """Creates an empty SavedState.
+
+ |isolated_basedir| is the directory where the .isolated and .isolated.state
+ files are saved.
+ """
+ super(SavedState, self).__init__()
+ assert os.path.isabs(isolated_basedir), isolated_basedir
+ assert os.path.isdir(isolated_basedir), isolated_basedir
+ self.isolated_basedir = isolated_basedir
+
+ self.command = []
+ self.files = {}
+ self.isolate_file = None
+ self.child_isolated_files = []
+ self.read_only = None
+ self.relative_cwd = None
+ self.variables = {'OS': get_flavor()}
+
+ def update(self, isolate_file, variables):
+ """Updates the saved state with new data to keep GYP variables and internal
+ reference to the original .isolate file.
+ """
+ assert os.path.isabs(isolate_file)
+ # Convert back to a relative path. On Windows, if the isolate and
+ # isolated files are on different drives, isolate_file will stay an absolute
+ # path.
+ isolate_file = safe_relpath(isolate_file, self.isolated_basedir)
+
+ # The same .isolate file should always be used to generate the .isolated and
+ # .isolated.state.
+ assert isolate_file == self.isolate_file or not self.isolate_file, (
+ isolate_file, self.isolate_file)
+ self.isolate_file = isolate_file
+ self.variables.update(variables)
+
+ def update_isolated(self, command, infiles, touched, read_only, relative_cwd):
+ """Updates the saved state with data necessary to generate a .isolated file.
+
+ The new files in |infiles| are added to self.files dict but their sha1 is
+ not calculated here.
+ """
+ self.command = command
+ # Add new files.
+ for f in infiles:
+ self.files.setdefault(f, {})
+ for f in touched:
+ self.files.setdefault(f, {})['T'] = True
+ # Prune extraneous files that are not a dependency anymore.
+ for f in set(self.files).difference(set(infiles).union(touched)):
+ del self.files[f]
+ if read_only is not None:
+ self.read_only = read_only
+ self.relative_cwd = relative_cwd
+
+ def to_isolated(self):
+ """Creates a .isolated dictionary out of the saved state.
+
+ https://code.google.com/p/swarming/wiki/IsolateDesign
+ """
+ def strip(data):
+ """Returns a 'files' entry with only the whitelisted keys."""
+ return dict((k, data[k]) for k in ('h', 'l', 'm', 's') if k in data)
+
+ out = {
+ 'files': dict(
+ (filepath, strip(data)) for filepath, data in self.files.iteritems()),
+ 'os': self.variables['OS'],
+ }
+ if self.command:
+ out['command'] = self.command
+ if self.read_only is not None:
+ out['read_only'] = self.read_only
+ if self.relative_cwd:
+ out['relative_cwd'] = self.relative_cwd
+ return out
+
+ @property
+ def isolate_filepath(self):
+ """Returns the absolute path of self.isolate_file."""
+ return os.path.normpath(
+ os.path.join(self.isolated_basedir, self.isolate_file))
+
+ # Arguments number differs from overridden method
+ @classmethod
+ def load(cls, data, isolated_basedir): # pylint: disable=W0221
+ """Special case loading to disallow different OS.
+
+ It is not possible to load a .isolated.state files from a different OS, this
+ file is saved in OS-specific format.
+ """
+ out = super(SavedState, cls).load(data, isolated_basedir)
+ if 'os' in data:
+ out.variables['OS'] = data['os']
+ if out.variables['OS'] != get_flavor():
+ raise run_isolated.ConfigError(
+ 'The .isolated.state file was created on another platform')
+ # The .isolate file must be valid. It could be absolute on Windows if the
+ # drive containing the .isolate and the drive containing the .isolated files
+ # differ.
+ assert not os.path.isabs(out.isolate_file) or sys.platform == 'win32'
+ assert os.path.isfile(out.isolate_filepath), out.isolate_filepath
+ return out
+
+ def __str__(self):
+ out = '%s(\n' % self.__class__.__name__
+ out += ' command: %s\n' % self.command
+ out += ' files: %d\n' % len(self.files)
+ out += ' isolate_file: %s\n' % self.isolate_file
+ out += ' read_only: %s\n' % self.read_only
+ out += ' relative_cwd: %s\n' % self.relative_cwd
+ out += ' child_isolated_files: %s\n' % self.child_isolated_files
+ out += ' variables: %s' % ''.join(
+ '\n %s=%s' % (k, self.variables[k]) for k in sorted(self.variables))
+ out += ')'
+ return out
+
+
+class CompleteState(object):
+ """Contains all the state to run the task at hand."""
+ def __init__(self, isolated_filepath, saved_state):
+ super(CompleteState, self).__init__()
+ assert os.path.isabs(isolated_filepath)
+ self.isolated_filepath = isolated_filepath
+ # Contains the data to ease developer's use-case but that is not strictly
+ # necessary.
+ self.saved_state = saved_state
+
+ @classmethod
+ def load_files(cls, isolated_filepath):
+ """Loads state from disk."""
+ assert os.path.isabs(isolated_filepath), isolated_filepath
+ isolated_basedir = os.path.dirname(isolated_filepath)
+ return cls(
+ isolated_filepath,
+ SavedState.load_file(
+ isolatedfile_to_state(isolated_filepath), isolated_basedir))
+
+ def load_isolate(self, cwd, isolate_file, variables, ignore_broken_items):
+ """Updates self.isolated and self.saved_state with information loaded from a
+ .isolate file.
+
+ Processes the loaded data, deduce root_dir, relative_cwd.
+ """
+ # Make sure to not depend on os.getcwd().
+ assert os.path.isabs(isolate_file), isolate_file
+ isolate_file = trace_inputs.get_native_path_case(isolate_file)
+ logging.info(
+ 'CompleteState.load_isolate(%s, %s, %s, %s)',
+ cwd, isolate_file, variables, ignore_broken_items)
+ relative_base_dir = os.path.dirname(isolate_file)
+
+ # Processes the variables and update the saved state.
+ variables = process_variables(cwd, variables, relative_base_dir)
+ self.saved_state.update(isolate_file, variables)
+ variables = self.saved_state.variables
+
+ with open(isolate_file, 'r') as f:
+ # At that point, variables are not replaced yet in command and infiles.
+ # infiles may contain directory entries and is in posix style.
+ command, infiles, touched, read_only = load_isolate_for_config(
+ os.path.dirname(isolate_file), f.read(), variables)
+ command = [eval_variables(i, variables) for i in command]
+ infiles = [eval_variables(f, variables) for f in infiles]
+ touched = [eval_variables(f, variables) for f in touched]
+ # root_dir is automatically determined by the deepest root accessed with the
+ # form '../../foo/bar'. Note that path variables must be taken in account
+ # too, add them as if they were input files.
+ path_variables = [variables[v] for v in PATH_VARIABLES if v in variables]
+ root_dir = determine_root_dir(
+ relative_base_dir, infiles + touched + path_variables)
+ # The relative directory is automatically determined by the relative path
+ # between root_dir and the directory containing the .isolate file,
+ # isolate_base_dir.
+ relative_cwd = os.path.relpath(relative_base_dir, root_dir)
+ # Now that we know where the root is, check that the PATH_VARIABLES point
+ # inside it.
+ for i in PATH_VARIABLES:
+ if i in variables:
+ if not path_starts_with(
+ root_dir, os.path.join(relative_base_dir, variables[i])):
+ raise run_isolated.MappingError(
+ 'Path variable %s=%r points outside the inferred root directory'
+ ' %s' % (i, variables[i], root_dir))
+ # Normalize the files based to root_dir. It is important to keep the
+ # trailing os.path.sep at that step.
+ infiles = [
+ relpath(normpath(os.path.join(relative_base_dir, f)), root_dir)
+ for f in infiles
+ ]
+ touched = [
+ relpath(normpath(os.path.join(relative_base_dir, f)), root_dir)
+ for f in touched
+ ]
+ follow_symlinks = variables['OS'] != 'win'
+ # Expand the directories by listing each file inside. Up to now, trailing
+ # os.path.sep must be kept. Do not expand 'touched'.
+ infiles = expand_directories_and_symlinks(
+ root_dir,
+ infiles,
+ lambda x: re.match(r'.*\.(git|svn|pyc)$', x),
+ follow_symlinks,
+ ignore_broken_items)
+
+ # If we ignore broken items then remove any missing touched items.
+ if ignore_broken_items:
+ original_touched_count = len(touched)
+ touched = [touch for touch in touched if os.path.exists(touch)]
+
+ if len(touched) != original_touched_count:
+ logging.info('Removed %d invalid touched entries',
+ len(touched) - original_touched_count)
+
+ # Finally, update the new data to be able to generate the foo.isolated file,
+ # the file that is used by run_isolated.py.
+ self.saved_state.update_isolated(
+ command, infiles, touched, read_only, relative_cwd)
+ logging.debug(self)
+
+ def process_inputs(self, subdir):
+ """Updates self.saved_state.files with the files' mode and hash.
+
+ If |subdir| is specified, filters to a subdirectory. The resulting .isolated
+ file is tainted.
+
+ See process_input() for more information.
+ """
+ for infile in sorted(self.saved_state.files):
+ if subdir and not infile.startswith(subdir):
+ self.saved_state.files.pop(infile)
+ else:
+ filepath = os.path.join(self.root_dir, infile)
+ self.saved_state.files[infile] = process_input(
+ filepath,
+ self.saved_state.files[infile],
+ self.saved_state.read_only,
+ self.saved_state.variables['OS'])
+
+ def save_files(self):
+ """Saves self.saved_state and creates a .isolated file."""
+ logging.debug('Dumping to %s' % self.isolated_filepath)
+ self.saved_state.child_isolated_files = chromium_save_isolated(
+ self.isolated_filepath,
+ self.saved_state.to_isolated(),
+ self.saved_state.variables)
+ total_bytes = sum(
+ i.get('s', 0) for i in self.saved_state.files.itervalues())
+ if total_bytes:
+ # TODO(maruel): Stats are missing the .isolated files.
+ logging.debug('Total size: %d bytes' % total_bytes)
+ saved_state_file = isolatedfile_to_state(self.isolated_filepath)
+ logging.debug('Dumping to %s' % saved_state_file)
+ trace_inputs.write_json(saved_state_file, self.saved_state.flatten(), True)
+
+ @property
+ def root_dir(self):
+ """Returns the absolute path of the root_dir to reference the .isolate file
+ via relative_cwd.
+
+ So that join(root_dir, relative_cwd, basename(isolate_file)) is equivalent
+ to isolate_filepath.
+ """
+ if not self.saved_state.isolate_file:
+ raise ExecutionError('Please specify --isolate')
+ isolate_dir = os.path.dirname(self.saved_state.isolate_filepath)
+ # Special case '.'.
+ if self.saved_state.relative_cwd == '.':
+ root_dir = isolate_dir
+ else:
+ assert isolate_dir.endswith(self.saved_state.relative_cwd), (
+ isolate_dir, self.saved_state.relative_cwd)
+ # Walk back back to the root directory.
+ root_dir = isolate_dir[:-(len(self.saved_state.relative_cwd) + 1)]
+ return trace_inputs.get_native_path_case(root_dir)
+
+ @property
+ def resultdir(self):
+ """Returns the absolute path containing the .isolated file.
+
+ It is usually equivalent to the variable PRODUCT_DIR. Uses the .isolated
+ path as the value.
+ """
+ return os.path.dirname(self.isolated_filepath)
+
+ def __str__(self):
+ def indent(data, indent_length):
+ """Indents text."""
+ spacing = ' ' * indent_length
+ return ''.join(spacing + l for l in str(data).splitlines(True))
+
+ out = '%s(\n' % self.__class__.__name__
+ out += ' root_dir: %s\n' % self.root_dir
+ out += ' saved_state: %s)' % indent(self.saved_state, 2)
+ return out
+
+
+def load_complete_state(options, cwd, subdir, skip_update):
+ """Loads a CompleteState.
+
+ This includes data from .isolate and .isolated.state files. Never reads the
+ .isolated file.
+
+ Arguments:
+ options: Options instance generated with OptionParserIsolate. For either
+ options.isolate and options.isolated, if the value is set, it is an
+ absolute path.
+ cwd: base directory to be used when loading the .isolate file.
+ subdir: optional argument to only process file in the subdirectory, relative
+ to CompleteState.root_dir.
+ skip_update: Skip trying to load the .isolate file and processing the
+ dependencies. It is useful when not needed, like when tracing.
+ """
+ assert not options.isolate or os.path.isabs(options.isolate)
+ assert not options.isolated or os.path.isabs(options.isolated)
+ cwd = trace_inputs.get_native_path_case(unicode(cwd))
+ if options.isolated:
+ # Load the previous state if it was present. Namely, "foo.isolated.state".
+ # Note: this call doesn't load the .isolate file.
+ complete_state = CompleteState.load_files(options.isolated)
+ else:
+ # Constructs a dummy object that cannot be saved. Useful for temporary
+ # commands like 'run'.
+ complete_state = CompleteState(None, SavedState())
+
+ if not options.isolate:
+ if not complete_state.saved_state.isolate_file:
+ if not skip_update:
+ raise ExecutionError('A .isolate file is required.')
+ isolate = None
+ else:
+ isolate = complete_state.saved_state.isolate_filepath
+ else:
+ isolate = options.isolate
+ if complete_state.saved_state.isolate_file:
+ rel_isolate = safe_relpath(
+ options.isolate, complete_state.saved_state.isolated_basedir)
+ if rel_isolate != complete_state.saved_state.isolate_file:
+ raise ExecutionError(
+ '%s and %s do not match.' % (
+ options.isolate, complete_state.saved_state.isolate_file))
+
+ if not skip_update:
+ # Then load the .isolate and expands directories.
+ complete_state.load_isolate(
+ cwd, isolate, options.variables, options.ignore_broken_items)
+
+ # Regenerate complete_state.saved_state.files.
+ if subdir:
+ subdir = unicode(subdir)
+ subdir = eval_variables(subdir, complete_state.saved_state.variables)
+ subdir = subdir.replace('/', os.path.sep)
+
+ if not skip_update:
+ complete_state.process_inputs(subdir)
+ return complete_state
+
+
+def read_trace_as_isolate_dict(complete_state, trace_blacklist):
+ """Reads a trace and returns the .isolate dictionary.
+
+ Returns exceptions during the log parsing so it can be re-raised.
+ """
+ api = trace_inputs.get_api()
+ logfile = complete_state.isolated_filepath + '.log'
+ if not os.path.isfile(logfile):
+ raise ExecutionError(
+ 'No log file \'%s\' to read, did you forget to \'trace\'?' % logfile)
+ try:
+ data = api.parse_log(logfile, trace_blacklist, None)
+ exceptions = [i['exception'] for i in data if 'exception' in i]
+ results = (i['results'] for i in data if 'results' in i)
+ results_stripped = (i.strip_root(complete_state.root_dir) for i in results)
+ files = set(sum((result.existent for result in results_stripped), []))
+ tracked, touched = split_touched(files)
+ value = generate_isolate(
+ tracked,
+ [],
+ touched,
+ complete_state.root_dir,
+ complete_state.saved_state.variables,
+ complete_state.saved_state.relative_cwd,
+ trace_blacklist)
+ return value, exceptions
+ except trace_inputs.TracingFailure, e:
+ raise ExecutionError(
+ 'Reading traces failed for: %s\n%s' %
+ (' '.join(complete_state.saved_state.command), str(e)))
+
+
+def print_all(comment, data, stream):
+ """Prints a complete .isolate file and its top-level file comment into a
+ stream.
+ """
+ if comment:
+ stream.write(comment)
+ pretty_print(data, stream)
+
+
+def merge(complete_state, trace_blacklist):
+ """Reads a trace and merges it back into the source .isolate file."""
+ value, exceptions = read_trace_as_isolate_dict(
+ complete_state, trace_blacklist)
+
+ # Now take that data and union it into the original .isolate file.
+ with open(complete_state.saved_state.isolate_filepath, 'r') as f:
+ prev_content = f.read()
+ isolate_dir = os.path.dirname(complete_state.saved_state.isolate_filepath)
+ prev_config = load_isolate_as_config(
+ isolate_dir,
+ eval_content(prev_content),
+ extract_comment(prev_content))
+ new_config = load_isolate_as_config(isolate_dir, value, '')
+ config = union(prev_config, new_config)
+ data = config.make_isolate_file()
+ print('Updating %s' % complete_state.saved_state.isolate_file)
+ with open(complete_state.saved_state.isolate_filepath, 'wb') as f:
+ print_all(config.file_comment, data, f)
+ if exceptions:
+ # It got an exception, raise the first one.
+ raise \
+ exceptions[0][0], \
+ exceptions[0][1], \
+ exceptions[0][2]
+
+
+def CMDcheck(args):
+ """Checks that all the inputs are present and generates .isolated."""
+ parser = OptionParserIsolate(command='check')
+ parser.add_option('--subdir', help='Filters to a subdirectory')
+ options, args = parser.parse_args(args)
+ if args:
+ parser.error('Unsupported argument: %s' % args)
+ complete_state = load_complete_state(
+ options, os.getcwd(), options.subdir, False)
+
+ # Nothing is done specifically. Just store the result and state.
+ complete_state.save_files()
+ return 0
+
+
+def CMDhashtable(args):
+ """Creates a hash table content addressed object store.
+
+ All the files listed in the .isolated file are put in the output directory
+ with the file name being the sha-1 of the file's content.
+ """
+ parser = OptionParserIsolate(command='hashtable')
+ parser.add_option('--subdir', help='Filters to a subdirectory')
+ options, args = parser.parse_args(args)
+ if args:
+ parser.error('Unsupported argument: %s' % args)
+
+ with run_isolated.Profiler('GenerateHashtable'):
+ success = False
+ try:
+ complete_state = load_complete_state(
+ options, os.getcwd(), options.subdir, False)
+ if not options.outdir:
+ options.outdir = os.path.join(
+ os.path.dirname(complete_state.isolated_filepath), 'hashtable')
+ # Make sure that complete_state isn't modified until save_files() is
+ # called, because any changes made to it here will propagate to the files
+ # created (which is probably not intended).
+ complete_state.save_files()
+
+ infiles = complete_state.saved_state.files
+ # Add all the .isolated files.
+ isolated_hash = []
+ isolated_files = [
+ options.isolated,
+ ] + complete_state.saved_state.child_isolated_files
+ for item in isolated_files:
+ item_path = os.path.join(
+ os.path.dirname(complete_state.isolated_filepath), item)
+ # Do not use isolateserver_archive.sha1_file() here because the file is
+ # likely smallish (under 500kb) and its file size is needed.
+ with open(item_path, 'rb') as f:
+ content = f.read()
+ isolated_hash.append(hashlib.sha1(content).hexdigest())
+ isolated_metadata = {
+ 'h': isolated_hash[-1],
+ 's': len(content),
+ 'priority': '0'
+ }
+ infiles[item_path] = isolated_metadata
+
+ logging.info('Creating content addressed object store with %d item',
+ len(infiles))
+
+ if is_url(options.outdir):
+ isolateserver_archive.upload_sha1_tree(
+ base_url=options.outdir,
+ indir=complete_state.root_dir,
+ infiles=infiles,
+ namespace='default-gzip')
+ else:
+ recreate_tree(
+ outdir=options.outdir,
+ indir=complete_state.root_dir,
+ infiles=infiles,
+ action=run_isolated.HARDLINK_WITH_FALLBACK,
+ as_sha1=True)
+ success = True
+ print('%s %s' % (isolated_hash[0], os.path.basename(options.isolated)))
+ finally:
+ # If the command failed, delete the .isolated file if it exists. This is
+ # important so no stale swarm job is executed.
+ if not success and os.path.isfile(options.isolated):
+ os.remove(options.isolated)
+ return not success
+
+
+def CMDmerge(args):
+ """Reads and merges the data from the trace back into the original .isolate.
+
+ Ignores --outdir.
+ """
+ parser = OptionParserIsolate(command='merge', require_isolated=False)
+ add_trace_option(parser)
+ options, args = parser.parse_args(args)
+ if args:
+ parser.error('Unsupported argument: %s' % args)
+ complete_state = load_complete_state(options, os.getcwd(), None, False)
+ blacklist = trace_inputs.gen_blacklist(options.trace_blacklist)
+ merge(complete_state, blacklist)
+ return 0
+
+
+def CMDread(args):
+ """Reads the trace file generated with command 'trace'.
+
+ Ignores --outdir.
+ """
+ parser = OptionParserIsolate(command='read', require_isolated=False)
+ add_trace_option(parser)
+ parser.add_option(
+ '--skip-refresh', action='store_true',
+ help='Skip reading .isolate file and do not refresh the sha1 of '
+ 'dependencies')
+ options, args = parser.parse_args(args)
+ if args:
+ parser.error('Unsupported argument: %s' % args)
+ complete_state = load_complete_state(
+ options, os.getcwd(), None, options.skip_refresh)
+ blacklist = trace_inputs.gen_blacklist(options.trace_blacklist)
+ value, exceptions = read_trace_as_isolate_dict(complete_state, blacklist)
+ pretty_print(value, sys.stdout)
+ if exceptions:
+ # It got an exception, raise the first one.
+ raise \
+ exceptions[0][0], \
+ exceptions[0][1], \
+ exceptions[0][2]
+ return 0
+
+
+def CMDremap(args):
+ """Creates a directory with all the dependencies mapped into it.
+
+ Useful to test manually why a test is failing. The target executable is not
+ run.
+ """
+ parser = OptionParserIsolate(command='remap', require_isolated=False)
+ options, args = parser.parse_args(args)
+ if args:
+ parser.error('Unsupported argument: %s' % args)
+ complete_state = load_complete_state(options, os.getcwd(), None, False)
+
+ if not options.outdir:
+ options.outdir = run_isolated.make_temp_dir(
+ 'isolate', complete_state.root_dir)
+ else:
+ if is_url(options.outdir):
+ raise ExecutionError('Can\'t use url for --outdir with mode remap')
+ if not os.path.isdir(options.outdir):
+ os.makedirs(options.outdir)
+ print('Remapping into %s' % options.outdir)
+ if len(os.listdir(options.outdir)):
+ raise ExecutionError('Can\'t remap in a non-empty directory')
+ recreate_tree(
+ outdir=options.outdir,
+ indir=complete_state.root_dir,
+ infiles=complete_state.saved_state.files,
+ action=run_isolated.HARDLINK_WITH_FALLBACK,
+ as_sha1=False)
+ if complete_state.saved_state.read_only:
+ run_isolated.make_writable(options.outdir, True)
+
+ if complete_state.isolated_filepath:
+ complete_state.save_files()
+ return 0
+
+
+def CMDrewrite(args):
+ """Rewrites a .isolate file into the canonical format."""
+ parser = OptionParserIsolate(command='rewrite', require_isolated=False)
+ options, args = parser.parse_args(args)
+ if args:
+ parser.error('Unsupported argument: %s' % args)
+
+ if options.isolated:
+ # Load the previous state if it was present. Namely, "foo.isolated.state".
+ complete_state = CompleteState.load_files(options.isolated)
+ isolate = options.isolate or complete_state.saved_state.isolate_filepath
+ else:
+ isolate = options.isolate
+ if not isolate:
+ raise ExecutionError('A .isolate file is required.')
+ with open(isolate, 'r') as f:
+ content = f.read()
+ config = load_isolate_as_config(
+ os.path.dirname(os.path.abspath(isolate)),
+ eval_content(content),
+ extract_comment(content))
+ data = config.make_isolate_file()
+ print('Updating %s' % isolate)
+ with open(isolate, 'wb') as f:
+ print_all(config.file_comment, data, f)
+ return 0
+
+
+def CMDrun(args):
+ """Runs the test executable in an isolated (temporary) directory.
+
+ All the dependencies are mapped into the temporary directory and the
+ directory is cleaned up after the target exits. Warning: if --outdir is
+ specified, it is deleted upon exit.
+
+ Argument processing stops at the first non-recognized argument and these
+ arguments are appended to the command line of the target to run. For example,
+ use: isolate.py --isolated foo.isolated -- --gtest_filter=Foo.Bar
+ """
+ parser = OptionParserIsolate(command='run', require_isolated=False)
+ parser.add_option(
+ '--skip-refresh', action='store_true',
+ help='Skip reading .isolate file and do not refresh the sha1 of '
+ 'dependencies')
+ parser.enable_interspersed_args()
+ options, args = parser.parse_args(args)
+ complete_state = load_complete_state(
+ options, os.getcwd(), None, options.skip_refresh)
+ cmd = complete_state.saved_state.command + args
+ if not cmd:
+ raise ExecutionError('No command to run')
+ if options.outdir and is_url(options.outdir):
+ raise ExecutionError('Can\'t use url for --outdir with mode run')
+
+ cmd = trace_inputs.fix_python_path(cmd)
+ try:
+ root_dir = complete_state.root_dir
+ if not options.outdir:
+ if not os.path.isabs(root_dir):
+ root_dir = os.path.join(os.path.dirname(options.isolated), root_dir)
+ options.outdir = run_isolated.make_temp_dir('isolate', root_dir)
+ else:
+ if not os.path.isdir(options.outdir):
+ os.makedirs(options.outdir)
+ recreate_tree(
+ outdir=options.outdir,
+ indir=root_dir,
+ infiles=complete_state.saved_state.files,
+ action=run_isolated.HARDLINK_WITH_FALLBACK,
+ as_sha1=False)
+ cwd = os.path.normpath(
+ os.path.join(options.outdir, complete_state.saved_state.relative_cwd))
+ if not os.path.isdir(cwd):
+ # It can happen when no files are mapped from the directory containing the
+ # .isolate file. But the directory must exist to be the current working
+ # directory.
+ os.makedirs(cwd)
+ if complete_state.saved_state.read_only:
+ run_isolated.make_writable(options.outdir, True)
+ logging.info('Running %s, cwd=%s' % (cmd, cwd))
+ result = subprocess.call(cmd, cwd=cwd)
+ finally:
+ if options.outdir:
+ run_isolated.rmtree(options.outdir)
+
+ if complete_state.isolated_filepath:
+ complete_state.save_files()
+ return result
+
+
+def CMDtrace(args):
+ """Traces the target using trace_inputs.py.
+
+ It runs the executable without remapping it, and traces all the files it and
+ its child processes access. Then the 'merge' command can be used to generate
+ an updated .isolate file out of it or the 'read' command to print it out to
+ stdout.
+
+ Argument processing stops at the first non-recognized argument and these
+ arguments are appended to the command line of the target to run. For example,
+ use: isolate.py --isolated foo.isolated -- --gtest_filter=Foo.Bar
+ """
+ parser = OptionParserIsolate(command='trace')
+ add_trace_option(parser)
+ parser.enable_interspersed_args()
+ parser.add_option(
+ '-m', '--merge', action='store_true',
+ help='After tracing, merge the results back in the .isolate file')
+ parser.add_option(
+ '--skip-refresh', action='store_true',
+ help='Skip reading .isolate file and do not refresh the sha1 of '
+ 'dependencies')
+ options, args = parser.parse_args(args)
+ complete_state = load_complete_state(
+ options, os.getcwd(), None, options.skip_refresh)
+ cmd = complete_state.saved_state.command + args
+ if not cmd:
+ raise ExecutionError('No command to run')
+ cmd = trace_inputs.fix_python_path(cmd)
+ cwd = os.path.normpath(os.path.join(
+ unicode(complete_state.root_dir),
+ complete_state.saved_state.relative_cwd))
+ cmd[0] = os.path.normpath(os.path.join(cwd, cmd[0]))
+ if not os.path.isfile(cmd[0]):
+ raise ExecutionError(
+ 'Tracing failed for: %s\nIt doesn\'t exit' % ' '.join(cmd))
+ logging.info('Running %s, cwd=%s' % (cmd, cwd))
+ api = trace_inputs.get_api()
+ logfile = complete_state.isolated_filepath + '.log'
+ api.clean_trace(logfile)
+ out = None
+ try:
+ with api.get_tracer(logfile) as tracer:
+ result, out = tracer.trace(
+ cmd,
+ cwd,
+ 'default',
+ True)
+ except trace_inputs.TracingFailure, e:
+ raise ExecutionError('Tracing failed for: %s\n%s' % (' '.join(cmd), str(e)))
+
+ if result:
+ logging.error(
+ 'Tracer exited with %d, which means the tests probably failed so the '
+ 'trace is probably incomplete.', result)
+ logging.info(out)
+
+ complete_state.save_files()
+
+ if options.merge:
+ blacklist = trace_inputs.gen_blacklist(options.trace_blacklist)
+ merge(complete_state, blacklist)
+
+ return result
+
+
+def _process_variable_arg(_option, _opt, _value, parser):
+ if not parser.rargs:
+ raise optparse.OptionValueError(
+ 'Please use --variable FOO=BAR or --variable FOO BAR')
+ k = parser.rargs.pop(0)
+ if '=' in k:
+ parser.values.variables.append(tuple(k.split('=', 1)))
+ else:
+ if not parser.rargs:
+ raise optparse.OptionValueError(
+ 'Please use --variable FOO=BAR or --variable FOO BAR')
+ v = parser.rargs.pop(0)
+ parser.values.variables.append((k, v))
+
+
+def add_variable_option(parser):
+ """Adds --isolated and --variable to an OptionParser."""
+ parser.add_option(
+ '-s', '--isolated',
+ metavar='FILE',
+ help='.isolated file to generate or read')
+ # Keep for compatibility. TODO(maruel): Remove once not used anymore.
+ parser.add_option(
+ '-r', '--result',
+ dest='isolated',
+ help=optparse.SUPPRESS_HELP)
+ default_variables = [('OS', get_flavor())]
+ if sys.platform in ('win32', 'cygwin'):
+ default_variables.append(('EXECUTABLE_SUFFIX', '.exe'))
+ else:
+ default_variables.append(('EXECUTABLE_SUFFIX', ''))
+ parser.add_option(
+ '-V', '--variable',
+ action='callback',
+ callback=_process_variable_arg,
+ default=default_variables,
+ dest='variables',
+ metavar='FOO BAR',
+ help='Variables to process in the .isolate file, default: %default. '
+ 'Variables are persistent accross calls, they are saved inside '
+ '<.isolated>.state')
+
+
+def add_trace_option(parser):
+ """Adds --trace-blacklist to the parser."""
+ parser.add_option(
+ '--trace-blacklist',
+ action='append', default=list(DEFAULT_BLACKLIST),
+ help='List of regexp to use as blacklist filter for files to consider '
+ 'important, not to be confused with --blacklist which blacklists '
+ 'test case.')
+
+
+def parse_isolated_option(parser, options, cwd, require_isolated):
+ """Processes --isolated."""
+ if options.isolated:
+ options.isolated = os.path.normpath(
+ os.path.join(cwd, options.isolated.replace('/', os.path.sep)))
+ if require_isolated and not options.isolated:
+ parser.error('--isolated is required.')
+ if options.isolated and not options.isolated.endswith('.isolated'):
+ parser.error('--isolated value must end with \'.isolated\'')
+
+
+def parse_variable_option(options):
+ """Processes --variable."""
+ # TODO(benrg): Maybe we should use a copy of gyp's NameValueListToDict here,
+ # but it wouldn't be backward compatible.
+ def try_make_int(s):
+ """Converts a value to int if possible, converts to unicode otherwise."""
+ try:
+ return int(s)
+ except ValueError:
+ return s.decode('utf-8')
+ options.variables = dict((k, try_make_int(v)) for k, v in options.variables)
+
+
+class OptionParserIsolate(trace_inputs.OptionParserWithNiceDescription):
+ """Adds automatic --isolate, --isolated, --out and --variable handling."""
+ def __init__(self, require_isolated=True, **kwargs):
+ trace_inputs.OptionParserWithNiceDescription.__init__(
+ self,
+ verbose=int(os.environ.get('ISOLATE_DEBUG', 0)),
+ **kwargs)
+ group = optparse.OptionGroup(self, "Common options")
+ group.add_option(
+ '-i', '--isolate',
+ metavar='FILE',
+ help='.isolate file to load the dependency data from')
+ add_variable_option(group)
+ group.add_option(
+ '-o', '--outdir', metavar='DIR',
+ help='Directory used to recreate the tree or store the hash table. '
+ 'Defaults: run|remap: a /tmp subdirectory, others: '
+ 'defaults to the directory containing --isolated')
+ group.add_option(
+ '--ignore_broken_items', action='store_true',
+ default=bool(os.environ.get('ISOLATE_IGNORE_BROKEN_ITEMS')),
+ help='Indicates that invalid entries in the isolated file to be '
+ 'only be logged and not stop processing. Defaults to True if '
+ 'env var ISOLATE_IGNORE_BROKEN_ITEMS is set')
+ self.add_option_group(group)
+ self.require_isolated = require_isolated
+
+ def parse_args(self, *args, **kwargs):
+ """Makes sure the paths make sense.
+
+ On Windows, / and \ are often mixed together in a path.
+ """
+ options, args = trace_inputs.OptionParserWithNiceDescription.parse_args(
+ self, *args, **kwargs)
+ if not self.allow_interspersed_args and args:
+ self.error('Unsupported argument: %s' % args)
+
+ cwd = trace_inputs.get_native_path_case(unicode(os.getcwd()))
+ parse_isolated_option(self, options, cwd, self.require_isolated)
+ parse_variable_option(options)
+
+ if options.isolate:
+ # TODO(maruel): Work with non-ASCII.
+ # The path must be in native path case for tracing purposes.
+ options.isolate = unicode(options.isolate).replace('/', os.path.sep)
+ options.isolate = os.path.normpath(os.path.join(cwd, options.isolate))
+ options.isolate = trace_inputs.get_native_path_case(options.isolate)
+
+ if options.outdir and not is_url(options.outdir):
+ options.outdir = unicode(options.outdir).replace('/', os.path.sep)
+ # outdir doesn't need native path case since tracing is never done from
+ # there.
+ options.outdir = os.path.normpath(os.path.join(cwd, options.outdir))
+
+ return options, args
+
+
+### Glue code to make all the commands works magically.
+
+
+CMDhelp = trace_inputs.CMDhelp
+
+
+def main(argv):
+ try:
+ return trace_inputs.main_impl(argv)
+ except (
+ ExecutionError,
+ run_isolated.MappingError,
+ run_isolated.ConfigError) as e:
+ sys.stderr.write('\nError: ')
+ sys.stderr.write(str(e))
+ sys.stderr.write('\n')
+ return 1
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/swarm_client/isolate_merge.py b/chromium/tools/swarm_client/isolate_merge.py
new file mode 100755
index 00000000000..1b67fc84549
--- /dev/null
+++ b/chromium/tools/swarm_client/isolate_merge.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Merges multiple OS-specific gyp dependency lists into one that works on all
+of them.
+
+The logic is relatively simple. Takes the current conditions, add more
+condition, find the strict subset. Done.
+"""
+
+import logging
+import os
+import sys
+
+from isolate import eval_content, extract_comment
+from isolate import load_isolate_as_config, print_all, union
+import run_isolated
+
+
+def load_isolates(items):
+ """Parses each .isolate file and returns the merged results.
+
+ It only loads what load_isolate_as_config() can process.
+
+ Return values:
+ files: dict(filename, set(OS where this filename is a dependency))
+ dirs: dict(dirame, set(OS where this dirname is a dependency))
+ oses: set(all the OSes referenced)
+ """
+ configs = None
+ for item in items:
+ item = os.path.abspath(item)
+ logging.debug('loading %s' % item)
+ if item == '-':
+ content = sys.stdin.read()
+ else:
+ with open(item, 'r') as f:
+ content = f.read()
+ new_config = load_isolate_as_config(
+ os.path.dirname(item),
+ eval_content(content),
+ extract_comment(content))
+ logging.debug('has configs: ' + ','.join(map(repr, new_config.by_config)))
+ configs = union(configs, new_config)
+ logging.debug('Total configs: ' + ','.join(map(repr, configs.by_config)))
+ return configs
+
+
+def main(args=None):
+ run_isolated.disable_buffering()
+ parser = run_isolated.OptionParserWithLogging(
+ usage='%prog <options> [file1] [file2] ...')
+ parser.add_option(
+ '-o', '--output', help='Output to file instead of stdout')
+
+ options, args = parser.parse_args(args)
+
+ configs = load_isolates(args)
+ data = configs.make_isolate_file()
+ if options.output:
+ with open(options.output, 'wb') as f:
+ print_all(configs.file_comment, data, f)
+ else:
+ print_all(configs.file_comment, data, sys.stdout)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/isolateserver_archive.py b/chromium/tools/swarm_client/isolateserver_archive.py
new file mode 100755
index 00000000000..6d2ef13ef17
--- /dev/null
+++ b/chromium/tools/swarm_client/isolateserver_archive.py
@@ -0,0 +1,400 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Archives a set of files to a server."""
+
+import binascii
+import cStringIO
+import hashlib
+import itertools
+import logging
+import optparse
+import os
+import sys
+import time
+import urllib
+import zlib
+
+import run_isolated
+
+
+# The minimum size of files to upload directly to the blobstore.
+MIN_SIZE_FOR_DIRECT_BLOBSTORE = 20 * 1024
+
+# The number of files to check the isolate server per /contains query. The
+# number here is a trade-off; the more per request, the lower the effect of HTTP
+# round trip latency and TCP-level chattiness. On the other hand, larger values
+# cause longer lookups, increasing the initial latency to start uploading, which
+# is especially an issue for large files. This value is optimized for the "few
+# thousands files to look up with minimal number of large files missing" case.
+ITEMS_PER_CONTAINS_QUERY = 100
+
+# A list of already compressed extension types that should not receive any
+# compression before being uploaded.
+ALREADY_COMPRESSED_TYPES = [
+ '7z', 'avi', 'cur', 'gif', 'h264', 'jar', 'jpeg', 'jpg', 'pdf', 'png',
+ 'wav', 'zip'
+]
+
+
+def randomness():
+ """Generates low-entropy randomness for MIME encoding.
+
+ Exists so it can be mocked out in unit tests.
+ """
+ return str(time.time())
+
+
+def encode_multipart_formdata(fields, files,
+ mime_mapper=lambda _: 'application/octet-stream'):
+ """Encodes a Multipart form data object.
+
+ Args:
+ fields: a sequence (name, value) elements for
+ regular form fields.
+ files: a sequence of (name, filename, value) elements for data to be
+ uploaded as files.
+ mime_mapper: function to return the mime type from the filename.
+ Returns:
+ content_type: for httplib.HTTP instance
+ body: for httplib.HTTP instance
+ """
+ boundary = hashlib.md5(randomness()).hexdigest()
+ body_list = []
+ for (key, value) in fields:
+ if isinstance(key, unicode):
+ value = key.encode('utf-8')
+ if isinstance(value, unicode):
+ value = value.encode('utf-8')
+ body_list.append('--' + boundary)
+ body_list.append('Content-Disposition: form-data; name="%s"' % key)
+ body_list.append('')
+ body_list.append(value)
+ body_list.append('--' + boundary)
+ body_list.append('')
+ for (key, filename, value) in files:
+ if isinstance(key, unicode):
+ value = key.encode('utf-8')
+ if isinstance(filename, unicode):
+ value = filename.encode('utf-8')
+ if isinstance(value, unicode):
+ value = value.encode('utf-8')
+ body_list.append('--' + boundary)
+ body_list.append('Content-Disposition: form-data; name="%s"; '
+ 'filename="%s"' % (key, filename))
+ body_list.append('Content-Type: %s' % mime_mapper(filename))
+ body_list.append('')
+ body_list.append(value)
+ body_list.append('--' + boundary)
+ body_list.append('')
+ if body_list:
+ body_list[-2] += '--'
+ body = '\r\n'.join(body_list)
+ content_type = 'multipart/form-data; boundary=%s' % boundary
+ return content_type, body
+
+
+def sha1_file(filepath):
+ """Calculates the SHA-1 of a file without reading it all in memory at once."""
+ digest = hashlib.sha1()
+ with open(filepath, 'rb') as f:
+ while True:
+ # Read in 1mb chunks.
+ chunk = f.read(1024*1024)
+ if not chunk:
+ break
+ digest.update(chunk)
+ return digest.hexdigest()
+
+
+def url_read(url, **kwargs):
+ result = run_isolated.url_read(url, **kwargs)
+ if result is None:
+ # If we get no response from the server, assume it is down and raise an
+ # exception.
+ raise run_isolated.MappingError('Unable to connect to server %s' % url)
+ return result
+
+
+def upload_hash_content_to_blobstore(
+ generate_upload_url, data, hash_key, content):
+ """Uploads the given hash contents directly to the blobstore via a generated
+ url.
+
+ Arguments:
+ generate_upload_url: The url to get the new upload url from.
+ data: extra POST data.
+ hash_key: sha1 of the uncompressed version of content.
+ content: The contents to upload. Must fit in memory for now.
+ """
+ logging.debug('Generating url to directly upload file to blobstore')
+ assert isinstance(hash_key, str), hash_key
+ assert isinstance(content, str), (hash_key, content)
+ # TODO(maruel): Support large files. This would require streaming support.
+ content_type, body = encode_multipart_formdata(
+ data, [('content', hash_key, content)])
+ for attempt in xrange(run_isolated.URL_OPEN_MAX_ATTEMPTS):
+ # Retry HTTP 50x here.
+ upload_url = run_isolated.url_read(generate_upload_url, data=data)
+ if not upload_url:
+ raise run_isolated.MappingError(
+ 'Unable to connect to server %s' % generate_upload_url)
+
+ # Do not retry this request on HTTP 50x. Regenerate an upload url each time
+ # since uploading "consumes" the upload url.
+ result = run_isolated.url_read(
+ upload_url, data=body, content_type=content_type, retry_50x=False)
+ if result is not None:
+ return result
+ if attempt != run_isolated.URL_OPEN_MAX_ATTEMPTS - 1:
+ run_isolated.HttpService.sleep_before_retry(attempt, None)
+ raise run_isolated.MappingError(
+ 'Unable to connect to server %s' % generate_upload_url)
+
+
+class UploadRemote(run_isolated.Remote):
+ def __init__(self, namespace, base_url, token):
+ self.namespace = str(namespace)
+ self._token = token
+ super(UploadRemote, self).__init__(base_url)
+
+ def get_file_handler(self, base_url):
+ base_url = str(base_url)
+ def upload_file(content, hash_key):
+ # TODO(maruel): Detect failures.
+ hash_key = str(hash_key)
+ content_url = base_url.rstrip('/') + '/content/'
+ if len(content) > MIN_SIZE_FOR_DIRECT_BLOBSTORE:
+ url = '%sgenerate_blobstore_url/%s/%s' % (
+ content_url, self.namespace, hash_key)
+ # self._token is stored already quoted but it is unnecessary here, and
+ # only here.
+ data = [('token', urllib.unquote(self._token))]
+ upload_hash_content_to_blobstore(url, data, hash_key, content)
+ else:
+ url = '%sstore/%s/%s?token=%s' % (
+ content_url, self.namespace, hash_key, self._token)
+ url_read(url, data=content, content_type='application/octet-stream')
+ return upload_file
+
+
+def check_files_exist_on_server(query_url, queries):
+ """Queries the server to see which files from this batch already exist there.
+
+ Arguments:
+ queries: The hash files to potential upload to the server.
+ Returns:
+ missing_files: list of files that are missing on the server.
+ """
+ logging.info('Checking existence of %d files...', len(queries))
+ body = ''.join(
+ (binascii.unhexlify(meta_data['h']) for (_, meta_data) in queries))
+ assert (len(body) % 20) == 0, repr(body)
+
+ response = url_read(
+ query_url, data=body, content_type='application/octet-stream')
+ if len(queries) != len(response):
+ raise run_isolated.MappingError(
+ 'Got an incorrect number of responses from the server. Expected %d, '
+ 'but got %d' % (len(queries), len(response)))
+
+ missing_files = [
+ queries[i] for i, flag in enumerate(response) if flag == chr(0)
+ ]
+ logging.info('Queried %d files, %d cache hit',
+ len(queries), len(queries) - len(missing_files))
+ return missing_files
+
+
+def compression_level(filename):
+ """Given a filename calculates the ideal compression level to use."""
+ file_ext = os.path.splitext(filename)[1].lower()
+ # TODO(csharp): Profile to find what compression level works best.
+ return 0 if file_ext in ALREADY_COMPRESSED_TYPES else 7
+
+
+def read_and_compress(filepath, level):
+ """Reads a file and returns its content gzip compressed."""
+ compressor = zlib.compressobj(level)
+ compressed_data = cStringIO.StringIO()
+ with open(filepath, 'rb') as f:
+ while True:
+ chunk = f.read(run_isolated.ZIPPED_FILE_CHUNK)
+ if not chunk:
+ break
+ compressed_data.write(compressor.compress(chunk))
+ compressed_data.write(compressor.flush(zlib.Z_FINISH))
+ value = compressed_data.getvalue()
+ compressed_data.close()
+ return value
+
+
+def zip_and_trigger_upload(infile, metadata, upload_function):
+ # TODO(csharp): Fix crbug.com/150823 and enable the touched logic again.
+ # if not metadata['T']:
+ compressed_data = read_and_compress(infile, compression_level(infile))
+ priority = (
+ run_isolated.Remote.HIGH if metadata.get('priority', '1') == '0'
+ else run_isolated.Remote.MED)
+ return upload_function(priority, compressed_data, metadata['h'], None)
+
+
+def batch_files_for_check(infiles):
+ """Splits list of files to check for existence on the server into batches.
+
+ Each batch corresponds to a single 'exists?' query to the server.
+
+ Yields:
+ batches: list of batches, each batch is a list of files.
+ """
+ # TODO(maruel): Make this adaptative, e.g. only query a few, like 10 in one
+ # request, for the largest files, since they are the ones most likely to be
+ # missing, then batch larger requests (up to 500) for the tail since they are
+ # likely to be present.
+ next_queries = []
+ items = ((k, v) for k, v in infiles.iteritems() if 's' in v)
+ for relfile, metadata in sorted(items, key=lambda x: -x[1]['s']):
+ next_queries.append((relfile, metadata))
+ if len(next_queries) == ITEMS_PER_CONTAINS_QUERY:
+ yield next_queries
+ next_queries = []
+ if next_queries:
+ yield next_queries
+
+
+def get_files_to_upload(contains_hash_url, infiles):
+ """Yields files that are missing on the server."""
+ with run_isolated.ThreadPool(1, 16, 0, prefix='get_files_to_upload') as pool:
+ for files in batch_files_for_check(infiles):
+ pool.add_task(0, check_files_exist_on_server, contains_hash_url, files)
+ for missing_file in itertools.chain.from_iterable(pool.iter_results()):
+ yield missing_file
+
+
+def upload_sha1_tree(base_url, indir, infiles, namespace):
+ """Uploads the given tree to the given url.
+
+ Arguments:
+ base_url: The base url, it is assume that |base_url|/has/ can be used to
+ query if an element was already uploaded, and |base_url|/store/
+ can be used to upload a new element.
+ indir: Root directory the infiles are based in.
+ infiles: dict of files to upload files from |indir| to |base_url|.
+ namespace: The namespace to use on the server.
+ """
+ logging.info('upload tree(base_url=%s, indir=%s, files=%d)' %
+ (base_url, indir, len(infiles)))
+ assert base_url.startswith('http'), base_url
+ base_url = base_url.rstrip('/')
+
+ # TODO(maruel): Make this request much earlier asynchronously while the files
+ # are being enumerated.
+ token = urllib.quote(url_read(base_url + '/content/get_token'))
+
+ # Create a pool of workers to zip and upload any files missing from
+ # the server.
+ num_threads = run_isolated.num_processors()
+ zipping_pool = run_isolated.ThreadPool(min(2, num_threads),
+ num_threads, 0, 'zip')
+ remote_uploader = UploadRemote(namespace, base_url, token)
+
+ # Starts the zip and upload process for files that are missing
+ # from the server.
+ contains_hash_url = '%s/content/contains/%s?token=%s' % (
+ base_url, namespace, token)
+ uploaded = []
+ for relfile, metadata in get_files_to_upload(contains_hash_url, infiles):
+ infile = os.path.join(indir, relfile)
+ zipping_pool.add_task(0, zip_and_trigger_upload, infile, metadata,
+ remote_uploader.add_item)
+ uploaded.append((relfile, metadata))
+
+ logging.info('Waiting for all files to finish zipping')
+ zipping_pool.join()
+ zipping_pool.close()
+ logging.info('All files zipped.')
+
+ logging.info('Waiting for all files to finish uploading')
+ # Will raise if any exception occurred.
+ remote_uploader.join()
+ remote_uploader.close()
+ logging.info('All files are uploaded')
+
+ total = len(infiles)
+ total_size = sum(metadata.get('s', 0) for metadata in infiles.itervalues())
+ logging.info(
+ 'Total: %6d, %9.1fkb',
+ total,
+ sum(m.get('s', 0) for m in infiles.itervalues()) / 1024.)
+ cache_hit = set(infiles.iterkeys()) - set(x[0] for x in uploaded)
+ cache_hit_size = sum(infiles[i].get('s', 0) for i in cache_hit)
+ logging.info(
+ 'cache hit: %6d, %9.1fkb, %6.2f%% files, %6.2f%% size',
+ len(cache_hit),
+ cache_hit_size / 1024.,
+ len(cache_hit) * 100. / total,
+ cache_hit_size * 100. / total_size if total_size else 0)
+ cache_miss = uploaded
+ cache_miss_size = sum(infiles[i[0]].get('s', 0) for i in cache_miss)
+ logging.info(
+ 'cache miss: %6d, %9.1fkb, %6.2f%% files, %6.2f%% size',
+ len(cache_miss),
+ cache_miss_size / 1024.,
+ len(cache_miss) * 100. / total,
+ cache_miss_size * 100. / total_size if total_size else 0)
+ return 0
+
+
+def main(args):
+ run_isolated.disable_buffering()
+ parser = optparse.OptionParser(
+ usage='%prog [options] <file1..fileN> or - to read from stdin',
+ description=sys.modules[__name__].__doc__)
+ parser.add_option('-r', '--remote', help='Remote server to archive to')
+ parser.add_option(
+ '-v', '--verbose',
+ action='count', default=0,
+ help='Use multiple times to increase verbosity')
+ parser.add_option('--namespace', default='default-gzip',
+ help='The namespace to use on the server.')
+
+ options, files = parser.parse_args(args)
+
+ levels = [logging.ERROR, logging.INFO, logging.DEBUG]
+ logging.basicConfig(
+ level=levels[min(len(levels)-1, options.verbose)],
+ format='[%(threadName)s] %(asctime)s,%(msecs)03d %(levelname)5s'
+ ' %(module)15s(%(lineno)3d): %(message)s',
+ datefmt='%H:%M:%S')
+ if files == ['-']:
+ files = sys.stdin.readlines()
+
+ if not files:
+ parser.error('Nothing to upload')
+ if not options.remote:
+ parser.error('Nowhere to send. Please specify --remote')
+
+ # Load the necessary metadata. This is going to be rewritten eventually to be
+ # more efficient.
+ infiles = dict(
+ (
+ f,
+ {
+ 's': os.stat(f).st_size,
+ 'h': sha1_file(f),
+ }
+ )
+ for f in files)
+
+ with run_isolated.Profiler('Archive'):
+ return upload_sha1_tree(
+ base_url=options.remote,
+ indir=os.getcwd(),
+ infiles=infiles,
+ namespace=options.namespace)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/swarm_client/run_isolated.py b/chromium/tools/swarm_client/run_isolated.py
new file mode 100755
index 00000000000..a81e48bf0c4
--- /dev/null
+++ b/chromium/tools/swarm_client/run_isolated.py
@@ -0,0 +1,2206 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Reads a .isolated, creates a tree of hardlinks and runs the test.
+
+Keeps a local cache.
+"""
+
+import cookielib
+import ctypes
+import functools
+import hashlib
+import httplib
+import inspect
+import itertools
+import json
+import locale
+import logging
+import logging.handlers
+import math
+import optparse
+import os
+import Queue
+import random
+import re
+import shutil
+import socket
+import ssl
+import stat
+import subprocess
+import sys
+import tempfile
+import threading
+import time
+import traceback
+import urllib
+import urllib2
+import urlparse
+import zlib
+
+# Try to import 'upload' module used by AppEngineService for authentication.
+# If it is not there, app engine authentication support will be disabled.
+try:
+ from third_party import upload
+ # Hack out upload logging.info()
+ upload.logging = logging.getLogger('upload')
+ # Mac pylint choke on this line.
+ upload.logging.setLevel(logging.WARNING) # pylint: disable=E1103
+except ImportError:
+ upload = None
+
+
+# Types of action accepted by link_file().
+HARDLINK, HARDLINK_WITH_FALLBACK, SYMLINK, COPY = range(1, 5)
+
+RE_IS_SHA1 = re.compile(r'^[a-fA-F0-9]{40}$')
+
+# The file size to be used when we don't know the correct file size,
+# generally used for .isolated files.
+UNKNOWN_FILE_SIZE = None
+
+# The size of each chunk to read when downloading and unzipping files.
+ZIPPED_FILE_CHUNK = 16 * 1024
+
+# The name of the log file to use.
+RUN_ISOLATED_LOG_FILE = 'run_isolated.log'
+
+# The base directory containing this file.
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+# The name of the log to use for the run_test_cases.py command
+RUN_TEST_CASES_LOG = os.path.join(BASE_DIR, 'run_test_cases.log')
+
+# The delay (in seconds) to wait between logging statements when retrieving
+# the required files. This is intended to let the user (or buildbot) know that
+# the program is still running.
+DELAY_BETWEEN_UPDATES_IN_SECS = 30
+
+# Maximum expected delay (in seconds) between successive file fetches
+# in run_tha_test. If it takes longer than that, a deadlock might be happening
+# and all stack frames for all threads are dumped to log.
+DEADLOCK_TIMEOUT = 5 * 60
+
+# The name of the key to store the count of url attempts.
+COUNT_KEY = 'UrlOpenAttempt'
+
+# Default maximum number of attempts to trying opening a url before aborting.
+URL_OPEN_MAX_ATTEMPTS = 30
+# Default timeout when retrying.
+URL_OPEN_TIMEOUT = 6*60.
+
+# Read timeout in seconds for downloads from isolate storage. If there's no
+# response from the server within this timeout whole download will be aborted.
+DOWNLOAD_READ_TIMEOUT = 60
+
+# Global (for now) map: server URL (http://example.com) -> HttpService instance.
+# Used by get_http_service to cache HttpService instances.
+_http_services = {}
+_http_services_lock = threading.Lock()
+
+# Used by get_flavor().
+FLAVOR_MAPPING = {
+ 'cygwin': 'win',
+ 'win32': 'win',
+ 'darwin': 'mac',
+ 'sunos5': 'solaris',
+ 'freebsd7': 'freebsd',
+ 'freebsd8': 'freebsd',
+}
+
+
+class ConfigError(ValueError):
+ """Generic failure to load a .isolated file."""
+ pass
+
+
+class MappingError(OSError):
+ """Failed to recreate the tree."""
+ pass
+
+
+class TimeoutError(IOError):
+ """Timeout while reading HTTP response."""
+
+ def __init__(self, inner_exc=None):
+ super(TimeoutError, self).__init__(str(inner_exc or 'Timeout'))
+ self.inner_exc = inner_exc
+
+
+def get_flavor():
+ """Returns the system default flavor. Copied from gyp/pylib/gyp/common.py."""
+ return FLAVOR_MAPPING.get(sys.platform, 'linux')
+
+
+def fix_default_encoding():
+ """Forces utf8 solidly on all platforms.
+
+ By default python execution environment is lazy and defaults to ascii
+ encoding.
+
+ http://uucode.com/blog/2007/03/23/shut-up-you-dummy-7-bit-python/
+ """
+ if sys.getdefaultencoding() == 'utf-8':
+ return False
+
+ # Regenerate setdefaultencoding.
+ reload(sys)
+ # Module 'sys' has no 'setdefaultencoding' member
+ # pylint: disable=E1101
+ sys.setdefaultencoding('utf-8')
+ for attr in dir(locale):
+ if attr[0:3] != 'LC_':
+ continue
+ aref = getattr(locale, attr)
+ try:
+ locale.setlocale(aref, '')
+ except locale.Error:
+ continue
+ try:
+ lang = locale.getlocale(aref)[0]
+ except (TypeError, ValueError):
+ continue
+ if lang:
+ try:
+ locale.setlocale(aref, (lang, 'UTF-8'))
+ except locale.Error:
+ os.environ[attr] = lang + '.UTF-8'
+ try:
+ locale.setlocale(locale.LC_ALL, '')
+ except locale.Error:
+ pass
+ return True
+
+
+class Unbuffered(object):
+ """Disable buffering on a file object."""
+ def __init__(self, stream):
+ self.stream = stream
+
+ def write(self, data):
+ self.stream.write(data)
+ if '\n' in data:
+ self.stream.flush()
+
+ def __getattr__(self, attr):
+ return getattr(self.stream, attr)
+
+
+def disable_buffering():
+ """Makes this process and child processes stdout unbuffered."""
+ if not os.environ.get('PYTHONUNBUFFERED'):
+ # Since sys.stdout is a C++ object, it's impossible to do
+ # sys.stdout.write = lambda...
+ sys.stdout = Unbuffered(sys.stdout)
+ os.environ['PYTHONUNBUFFERED'] = 'x'
+
+
+def num_processors():
+ """Returns the number of processors.
+
+ Python on OSX 10.6 raises a NotImplementedError exception.
+ """
+ try:
+ # Multiprocessing
+ import multiprocessing
+ return multiprocessing.cpu_count()
+ except: # pylint: disable=W0702
+ try:
+ # Mac OS 10.6
+ return int(os.sysconf('SC_NPROCESSORS_ONLN')) # pylint: disable=E1101
+ except:
+ # Some of the windows builders seem to get here.
+ return 4
+
+
+def os_link(source, link_name):
+ """Add support for os.link() on Windows."""
+ if sys.platform == 'win32':
+ if not ctypes.windll.kernel32.CreateHardLinkW(
+ unicode(link_name), unicode(source), 0):
+ raise OSError()
+ else:
+ os.link(source, link_name)
+
+
+def readable_copy(outfile, infile):
+ """Makes a copy of the file that is readable by everyone."""
+ shutil.copy2(infile, outfile)
+ read_enabled_mode = (os.stat(outfile).st_mode | stat.S_IRUSR |
+ stat.S_IRGRP | stat.S_IROTH)
+ os.chmod(outfile, read_enabled_mode)
+
+
+def link_file(outfile, infile, action):
+ """Links a file. The type of link depends on |action|."""
+ logging.debug('Mapping %s to %s' % (infile, outfile))
+ if action not in (HARDLINK, HARDLINK_WITH_FALLBACK, SYMLINK, COPY):
+ raise ValueError('Unknown mapping action %s' % action)
+ if not os.path.isfile(infile):
+ raise MappingError('%s is missing' % infile)
+ if os.path.isfile(outfile):
+ raise MappingError(
+ '%s already exist; insize:%d; outsize:%d' %
+ (outfile, os.stat(infile).st_size, os.stat(outfile).st_size))
+
+ if action == COPY:
+ readable_copy(outfile, infile)
+ elif action == SYMLINK and sys.platform != 'win32':
+ # On windows, symlink are converted to hardlink and fails over to copy.
+ os.symlink(infile, outfile) # pylint: disable=E1101
+ else:
+ try:
+ os_link(infile, outfile)
+ except OSError as e:
+ if action == HARDLINK:
+ raise MappingError(
+ 'Failed to hardlink %s to %s: %s' % (infile, outfile, e))
+ # Probably a different file system.
+ logging.warning(
+ 'Failed to hardlink, failing back to copy %s to %s' % (
+ infile, outfile))
+ readable_copy(outfile, infile)
+
+
+def _set_write_bit(path, read_only):
+ """Sets or resets the executable bit on a file or directory."""
+ mode = os.lstat(path).st_mode
+ if read_only:
+ mode = mode & 0500
+ else:
+ mode = mode | 0200
+ if hasattr(os, 'lchmod'):
+ os.lchmod(path, mode) # pylint: disable=E1101
+ else:
+ if stat.S_ISLNK(mode):
+ # Skip symlink without lchmod() support.
+ logging.debug('Can\'t change +w bit on symlink %s' % path)
+ return
+
+ # TODO(maruel): Implement proper DACL modification on Windows.
+ os.chmod(path, mode)
+
+
+def make_writable(root, read_only):
+ """Toggle the writable bit on a directory tree."""
+ assert os.path.isabs(root), root
+ for dirpath, dirnames, filenames in os.walk(root, topdown=True):
+ for filename in filenames:
+ _set_write_bit(os.path.join(dirpath, filename), read_only)
+
+ for dirname in dirnames:
+ _set_write_bit(os.path.join(dirpath, dirname), read_only)
+
+
+def rmtree(root):
+ """Wrapper around shutil.rmtree() to retry automatically on Windows."""
+ make_writable(root, False)
+ if sys.platform == 'win32':
+ for i in range(3):
+ try:
+ shutil.rmtree(root)
+ break
+ except WindowsError: # pylint: disable=E0602
+ delay = (i+1)*2
+ print >> sys.stderr, (
+ 'The test has subprocess outliving it. Sleep %d seconds.' % delay)
+ time.sleep(delay)
+ else:
+ shutil.rmtree(root)
+
+
+def is_same_filesystem(path1, path2):
+ """Returns True if both paths are on the same filesystem.
+
+ This is required to enable the use of hardlinks.
+ """
+ assert os.path.isabs(path1), path1
+ assert os.path.isabs(path2), path2
+ if sys.platform == 'win32':
+ # If the drive letter mismatches, assume it's a separate partition.
+ # TODO(maruel): It should look at the underlying drive, a drive letter could
+ # be a mount point to a directory on another drive.
+ assert re.match(r'^[a-zA-Z]\:\\.*', path1), path1
+ assert re.match(r'^[a-zA-Z]\:\\.*', path2), path2
+ if path1[0].lower() != path2[0].lower():
+ return False
+ return os.stat(path1).st_dev == os.stat(path2).st_dev
+
+
+def get_free_space(path):
+ """Returns the number of free bytes."""
+ if sys.platform == 'win32':
+ free_bytes = ctypes.c_ulonglong(0)
+ ctypes.windll.kernel32.GetDiskFreeSpaceExW(
+ ctypes.c_wchar_p(path), None, None, ctypes.pointer(free_bytes))
+ return free_bytes.value
+ # For OSes other than Windows.
+ f = os.statvfs(path) # pylint: disable=E1101
+ return f.f_bfree * f.f_frsize
+
+
+def make_temp_dir(prefix, root_dir):
+ """Returns a temporary directory on the same file system as root_dir."""
+ base_temp_dir = None
+ if not is_same_filesystem(root_dir, tempfile.gettempdir()):
+ base_temp_dir = os.path.dirname(root_dir)
+ return tempfile.mkdtemp(prefix=prefix, dir=base_temp_dir)
+
+
+def load_isolated(content, os_flavor=None):
+ """Verifies the .isolated file is valid and loads this object with the json
+ data.
+ """
+ try:
+ data = json.loads(content)
+ except ValueError:
+ raise ConfigError('Failed to parse: %s...' % content[:100])
+
+ if not isinstance(data, dict):
+ raise ConfigError('Expected dict, got %r' % data)
+
+ for key, value in data.iteritems():
+ if key == 'command':
+ if not isinstance(value, list):
+ raise ConfigError('Expected list, got %r' % value)
+ if not value:
+ raise ConfigError('Expected non-empty command')
+ for subvalue in value:
+ if not isinstance(subvalue, basestring):
+ raise ConfigError('Expected string, got %r' % subvalue)
+
+ elif key == 'files':
+ if not isinstance(value, dict):
+ raise ConfigError('Expected dict, got %r' % value)
+ for subkey, subvalue in value.iteritems():
+ if not isinstance(subkey, basestring):
+ raise ConfigError('Expected string, got %r' % subkey)
+ if not isinstance(subvalue, dict):
+ raise ConfigError('Expected dict, got %r' % subvalue)
+ for subsubkey, subsubvalue in subvalue.iteritems():
+ if subsubkey == 'l':
+ if not isinstance(subsubvalue, basestring):
+ raise ConfigError('Expected string, got %r' % subsubvalue)
+ elif subsubkey == 'm':
+ if not isinstance(subsubvalue, int):
+ raise ConfigError('Expected int, got %r' % subsubvalue)
+ elif subsubkey == 'h':
+ if not RE_IS_SHA1.match(subsubvalue):
+ raise ConfigError('Expected sha-1, got %r' % subsubvalue)
+ elif subsubkey == 's':
+ if not isinstance(subsubvalue, int):
+ raise ConfigError('Expected int, got %r' % subsubvalue)
+ else:
+ raise ConfigError('Unknown subsubkey %s' % subsubkey)
+ if bool('h' in subvalue) and bool('l' in subvalue):
+ raise ConfigError(
+ 'Did not expect both \'h\' (sha-1) and \'l\' (link), got: %r' %
+ subvalue)
+
+ elif key == 'includes':
+ if not isinstance(value, list):
+ raise ConfigError('Expected list, got %r' % value)
+ if not value:
+ raise ConfigError('Expected non-empty includes list')
+ for subvalue in value:
+ if not RE_IS_SHA1.match(subvalue):
+ raise ConfigError('Expected sha-1, got %r' % subvalue)
+
+ elif key == 'read_only':
+ if not isinstance(value, bool):
+ raise ConfigError('Expected bool, got %r' % value)
+
+ elif key == 'relative_cwd':
+ if not isinstance(value, basestring):
+ raise ConfigError('Expected string, got %r' % value)
+
+ elif key == 'os':
+ expected_value = os_flavor or get_flavor()
+ if value != expected_value:
+ raise ConfigError(
+ 'Expected \'os\' to be \'%s\' but got \'%s\'' %
+ (expected_value, value))
+
+ else:
+ raise ConfigError('Unknown key %s' % key)
+
+ return data
+
+
+def fix_python_path(cmd):
+ """Returns the fixed command line to call the right python executable."""
+ out = cmd[:]
+ if out[0] == 'python':
+ out[0] = sys.executable
+ elif out[0].endswith('.py'):
+ out.insert(0, sys.executable)
+ return out
+
+
+def url_open(url, **kwargs):
+ """Attempts to open the given url multiple times.
+
+ |data| can be either:
+ -None for a GET request
+ -str for pre-encoded data
+ -list for data to be encoded
+ -dict for data to be encoded (COUNT_KEY will be added in this case)
+
+ Returns HttpResponse object, where the response may be read from, or None
+ if it was unable to connect.
+ """
+ urlhost, urlpath = split_server_request_url(url)
+ service = get_http_service(urlhost)
+ return service.request(urlpath, **kwargs)
+
+
+def url_read(url, **kwargs):
+ """Attempts to open the given url multiple times and read all data from it.
+
+ Accepts same arguments as url_open function.
+
+ Returns all data read or None if it was unable to connect or read the data.
+ """
+ response = url_open(url, **kwargs)
+ if not response:
+ return None
+ try:
+ return response.read()
+ except TimeoutError:
+ return None
+
+
+def split_server_request_url(url):
+ """Splits the url into scheme+netloc and path+params+query+fragment."""
+ url_parts = list(urlparse.urlparse(url))
+ urlhost = '%s://%s' % (url_parts[0], url_parts[1])
+ urlpath = urlparse.urlunparse(['', ''] + url_parts[2:])
+ return urlhost, urlpath
+
+
+def get_http_service(urlhost):
+ """Returns existing or creates new instance of HttpService that can send
+ requests to given base urlhost.
+ """
+ # Ensure consistency.
+ urlhost = str(urlhost).lower().rstrip('/')
+ with _http_services_lock:
+ service = _http_services.get(urlhost)
+ if not service:
+ service = AppEngineService(urlhost)
+ _http_services[urlhost] = service
+ return service
+
+
+class HttpService(object):
+ """Base class for a class that provides an API to HTTP based service:
+ - Provides 'request' method.
+ - Supports automatic request retries.
+ - Supports persistent cookies.
+ - Thread safe.
+ """
+
+ # File to use to store all auth cookies.
+ COOKIE_FILE = os.path.join(os.path.expanduser('~'), '.isolated_cookies')
+
+ # CookieJar reused by all services + lock that protects its instantiation.
+ _cookie_jar = None
+ _cookie_jar_lock = threading.Lock()
+
+ def __init__(self, urlhost):
+ self.urlhost = urlhost
+ self.cookie_jar = self.load_cookie_jar()
+ self.opener = self.create_url_opener()
+
+ def authenticate(self): # pylint: disable=R0201
+ """Called when HTTP server asks client to authenticate.
+ Can be implemented in subclasses.
+ """
+ return False
+
+ @staticmethod
+ def load_cookie_jar():
+ """Returns global CoookieJar object that stores cookies in the file."""
+ with HttpService._cookie_jar_lock:
+ if HttpService._cookie_jar is not None:
+ return HttpService._cookie_jar
+ jar = ThreadSafeCookieJar(HttpService.COOKIE_FILE)
+ jar.load()
+ HttpService._cookie_jar = jar
+ return jar
+
+ @staticmethod
+ def save_cookie_jar():
+ """Called when cookie jar needs to be flushed to disk."""
+ with HttpService._cookie_jar_lock:
+ if HttpService._cookie_jar is not None:
+ HttpService._cookie_jar.save()
+
+ def create_url_opener(self): # pylint: disable=R0201
+ """Returns OpenerDirector that will be used when sending requests.
+ Can be reimplemented in subclasses."""
+ return urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookie_jar))
+
+ def request(self, urlpath, data=None, content_type=None, **kwargs):
+ """Attempts to open the given url multiple times.
+
+ |urlpath| is relative to the server root, i.e. '/some/request?param=1'.
+
+ |data| can be either:
+ -None for a GET request
+ -str for pre-encoded data
+ -list for data to be encoded
+ -dict for data to be encoded (COUNT_KEY will be added in this case)
+
+ Returns a file-like object, where the response may be read from, or None
+ if it was unable to connect.
+ """
+ assert urlpath and urlpath[0] == '/'
+
+ if isinstance(data, dict) and COUNT_KEY in data:
+ logging.error('%s already existed in the data passed into UlrOpen. It '
+ 'would be overwritten. Aborting UrlOpen', COUNT_KEY)
+ return None
+
+ method = 'GET' if data is None else 'POST'
+ assert not ((method != 'POST') and content_type), (
+ 'Can\'t use content_type on GET')
+
+ def make_request(extra):
+ """Returns a urllib2.Request instance for this specific retry."""
+ if isinstance(data, str) or data is None:
+ payload = data
+ else:
+ if isinstance(data, dict):
+ payload = data.items()
+ else:
+ payload = data[:]
+ payload.extend(extra.iteritems())
+ payload = urllib.urlencode(payload)
+ new_url = urlparse.urljoin(self.urlhost, urlpath[1:])
+ if isinstance(data, str) or data is None:
+ # In these cases, add the extra parameter to the query part of the url.
+ url_parts = list(urlparse.urlparse(new_url))
+ # Append the query parameter.
+ if url_parts[4] and extra:
+ url_parts[4] += '&'
+ url_parts[4] += urllib.urlencode(extra)
+ new_url = urlparse.urlunparse(url_parts)
+ request = urllib2.Request(new_url, data=payload)
+ if payload is not None:
+ if content_type:
+ request.add_header('Content-Type', content_type)
+ request.add_header('Content-Length', len(payload))
+ return request
+
+ return self._retry_loop(make_request, **kwargs)
+
+ def _retry_loop(
+ self,
+ make_request,
+ max_attempts=URL_OPEN_MAX_ATTEMPTS,
+ retry_404=False,
+ retry_50x=True,
+ timeout=URL_OPEN_TIMEOUT,
+ read_timeout=None):
+ """Runs internal request-retry loop.
+
+ - Optionally retries HTTP 404 and 50x.
+ - Retries up to |max_attempts| times. If None or 0, there's no limit in the
+ number of retries.
+ - Retries up to |timeout| duration in seconds. If None or 0, there's no
+ limit in the time taken to do retries.
+ - If both |max_attempts| and |timeout| are None or 0, this functions retries
+ indefinitely.
+
+ If |read_timeout| is not None will configure underlying socket to
+ raise TimeoutError exception whenever there's no response from the server
+ for more than |read_timeout| seconds. It can happen during any read
+ operation so once you pass non-None |read_timeout| be prepared to handle
+ these exceptions in subsequent reads from the stream.
+ """
+ authenticated = False
+ last_error = None
+ attempt = 0
+ start = self._now()
+ for attempt in itertools.count():
+ if max_attempts and attempt >= max_attempts:
+ # Too many attempts.
+ break
+ if timeout and (self._now() - start) >= timeout:
+ # Retried for too long.
+ break
+ extra = {COUNT_KEY: attempt} if attempt else {}
+ request = make_request(extra)
+ try:
+ url_response = self._url_open(request, timeout=read_timeout)
+ logging.debug('url_open(%s) succeeded', request.get_full_url())
+ return HttpResponse(url_response, request.get_full_url())
+ except urllib2.HTTPError as e:
+ # Unauthorized. Ask to authenticate and then try again.
+ if e.code in (401, 403):
+ # Try to authenticate only once. If it doesn't help, then server does
+ # not support app engine authentication.
+ logging.error(
+ 'Authentication is required for %s on attempt %d.\n%s',
+ request.get_full_url(), attempt,
+ self._format_exception(e, verbose=True))
+ if not authenticated and self.authenticate():
+ authenticated = True
+ # Do not sleep.
+ continue
+ # If authentication failed, return.
+ logging.error(
+ 'Unable to authenticate to %s.\n%s',
+ request.get_full_url(), self._format_exception(e, verbose=True))
+ return None
+
+ if ((e.code < 500 and not (retry_404 and e.code == 404)) or
+ (e.code >= 500 and not retry_50x)):
+ # This HTTPError means we reached the server and there was a problem
+ # with the request, so don't retry.
+ logging.error(
+ 'Able to connect to %s but an exception was thrown.\n%s',
+ request.get_full_url(), self._format_exception(e, verbose=True))
+ return None
+
+ # The HTTPError was due to a server error, so retry the attempt.
+ logging.warning('Able to connect to %s on attempt %d.\n%s',
+ request.get_full_url(), attempt,
+ self._format_exception(e))
+ last_error = e
+
+ except (urllib2.URLError, httplib.HTTPException,
+ socket.timeout, ssl.SSLError) as e:
+ logging.warning('Unable to open url %s on attempt %d.\n%s',
+ request.get_full_url(), attempt,
+ self._format_exception(e))
+ last_error = e
+
+ # Only sleep if we are going to try again.
+ if max_attempts and attempt != max_attempts:
+ remaining = None
+ if timeout:
+ remaining = timeout - (self._now() - start)
+ if remaining <= 0:
+ break
+ self.sleep_before_retry(attempt, remaining)
+
+ logging.error('Unable to open given url, %s, after %d attempts.\n%s',
+ request.get_full_url(), max_attempts,
+ self._format_exception(last_error, verbose=True))
+ return None
+
+ def _url_open(self, request, timeout=None):
+ """Low level method to execute urllib2.Request's.
+
+ To be mocked in tests.
+ """
+ if timeout is not None:
+ return self.opener.open(request, timeout=timeout)
+ else:
+ # Leave original default value for |timeout|. It's nontrivial.
+ return self.opener.open(request)
+
+ @staticmethod
+ def _now():
+ """To be mocked in tests."""
+ return time.time()
+
+ @staticmethod
+ def calculate_sleep_before_retry(attempt, max_duration):
+ # Maximum sleeping time. We're hammering a cloud-distributed service, it'll
+ # survive.
+ MAX_SLEEP = 10.
+ # random.random() returns [0.0, 1.0). Starts with relatively short waiting
+ # time by starting with 1.5/2+1.5^-1 median offset.
+ duration = (random.random() * 1.5) + math.pow(1.5, (attempt - 1))
+ assert duration > 0.1
+ duration = min(MAX_SLEEP, duration)
+ if max_duration:
+ duration = min(max_duration, duration)
+ return duration
+
+ @classmethod
+ def sleep_before_retry(cls, attempt, max_duration):
+ """Sleeps for some amount of time when retrying the request.
+
+ To be mocked in tests.
+ """
+ time.sleep(cls.calculate_sleep_before_retry(attempt, max_duration))
+
+ @staticmethod
+ def _format_exception(exc, verbose=False):
+ """Given an instance of some exception raised by urlopen returns human
+ readable piece of text with detailed information about the error.
+ """
+ out = ['Exception: %s' % (exc,)]
+ if verbose:
+ if isinstance(exc, urllib2.HTTPError):
+ out.append('-' * 10)
+ if exc.hdrs:
+ for header, value in exc.hdrs.items():
+ if not header.startswith('x-'):
+ out.append('%s: %s' % (header.capitalize(), value))
+ out.append('')
+ out.append(exc.read() or '<empty body>')
+ out.append('-' * 10)
+ return '\n'.join(out)
+
+
+class HttpResponse(object):
+ """Response from HttpService."""
+
+ def __init__(self, url_response, url):
+ self._url_response = url_response
+ self._url = url
+ self._read = 0
+
+ @property
+ def content_length(self):
+ """Total length to the response or None if not known in advance."""
+ length = self._url_response.headers.get('Content-Length')
+ return int(length) if length is not None else None
+
+ def read(self, size=None):
+ """Reads up to |size| bytes from the stream and returns them.
+
+ If |size| is None reads all available bytes.
+
+ Raises TimeoutError on read timeout.
+ """
+ try:
+ data = self._url_response.read(size)
+ self._read += len(data)
+ return data
+ except (socket.timeout, ssl.SSLError) as e:
+ logging.error('Timeout while reading from %s, read %d of %s: %s',
+ self._url, self._read, self.content_length, e)
+ raise TimeoutError(e)
+
+
+class AppEngineService(HttpService):
+ """This class implements authentication support for
+ an app engine based services.
+ """
+
+ # This lock ensures that user won't be confused with multiple concurrent
+ # login prompts.
+ _auth_lock = threading.Lock()
+
+ def __init__(self, urlhost, email=None, password=None):
+ super(AppEngineService, self).__init__(urlhost)
+ self.email = email
+ self.password = password
+ self._keyring = None
+
+ def authenticate(self):
+ """Authenticates in the app engine application.
+ Returns True on success.
+ """
+ if not upload:
+ logging.error('\'upload\' module is missing, '
+ 'app engine authentication is disabled.')
+ return False
+ cookie_jar = self.cookie_jar
+ save_cookie_jar = self.save_cookie_jar
+ # RPC server that uses AuthenticationSupport's cookie jar.
+ class AuthServer(upload.AbstractRpcServer):
+ def _GetOpener(self):
+ # Authentication code needs to know about 302 response.
+ # So make OpenerDirector without HTTPRedirectHandler.
+ opener = urllib2.OpenerDirector()
+ opener.add_handler(urllib2.ProxyHandler())
+ opener.add_handler(urllib2.UnknownHandler())
+ opener.add_handler(urllib2.HTTPHandler())
+ opener.add_handler(urllib2.HTTPDefaultErrorHandler())
+ opener.add_handler(urllib2.HTTPSHandler())
+ opener.add_handler(urllib2.HTTPErrorProcessor())
+ opener.add_handler(urllib2.HTTPCookieProcessor(cookie_jar))
+ return opener
+ def PerformAuthentication(self):
+ self._Authenticate()
+ save_cookie_jar()
+ return self.authenticated
+ with AppEngineService._auth_lock:
+ rpc_server = AuthServer(self.urlhost, self.get_credentials)
+ return rpc_server.PerformAuthentication()
+
+ def get_credentials(self):
+ """Called during authentication process to get the credentials.
+ May be called mutliple times if authentication fails.
+ Returns tuple (email, password).
+ """
+ # 'authenticate' calls this only if 'upload' is present.
+ # Ensure other callers (if any) fail non-cryptically if 'upload' is missing.
+ assert upload, '\'upload\' module is required for this to work'
+ if self.email and self.password:
+ return (self.email, self.password)
+ if not self._keyring:
+ self._keyring = upload.KeyringCreds(self.urlhost,
+ self.urlhost,
+ self.email)
+ return self._keyring.GetUserCredentials()
+
+
+class ThreadSafeCookieJar(cookielib.MozillaCookieJar):
+ """MozillaCookieJar with thread safe load and save."""
+
+ def load(self, filename=None, ignore_discard=False, ignore_expires=False):
+ """Loads cookies from the file if it exists."""
+ filename = os.path.expanduser(filename or self.filename)
+ with self._cookies_lock:
+ if os.path.exists(filename):
+ try:
+ cookielib.MozillaCookieJar.load(self, filename,
+ ignore_discard,
+ ignore_expires)
+ logging.debug('Loaded cookies from %s', filename)
+ except (cookielib.LoadError, IOError):
+ pass
+ else:
+ try:
+ fd = os.open(filename, os.O_CREAT, 0600)
+ os.close(fd)
+ except OSError:
+ logging.error('Failed to create %s', filename)
+ try:
+ os.chmod(filename, 0600)
+ except OSError:
+ logging.error('Failed to fix mode for %s', filename)
+
+ def save(self, filename=None, ignore_discard=False, ignore_expires=False):
+ """Saves cookies to the file, completely overwriting it."""
+ logging.debug('Saving cookies to %s', filename or self.filename)
+ with self._cookies_lock:
+ try:
+ cookielib.MozillaCookieJar.save(self, filename,
+ ignore_discard,
+ ignore_expires)
+ except OSError:
+ logging.error('Failed to save %s', filename)
+
+
+class ThreadPoolError(Exception):
+ """Base class for exceptions raised by ThreadPool."""
+
+
+class ThreadPoolEmpty(ThreadPoolError):
+ """Trying to get task result from a thread pool with no pending tasks."""
+
+
+class ThreadPoolClosed(ThreadPoolError):
+ """Trying to do something with a closed thread pool."""
+
+
+class ThreadPool(object):
+ """Implements a multithreaded worker pool oriented for mapping jobs with
+ thread-local result storage.
+
+ Arguments:
+ - initial_threads: Number of threads to start immediately. Can be 0 if it is
+ uncertain that threads will be needed.
+ - max_threads: Maximum number of threads that will be started when all the
+ threads are busy working. Often the number of CPU cores.
+ - queue_size: Maximum number of tasks to buffer in the queue. 0 for unlimited
+ queue. A non-zero value may make add_task() blocking.
+ - prefix: Prefix to use for thread names. Pool's threads will be
+ named '<prefix>-<thread index>'.
+ """
+ QUEUE_CLASS = Queue.PriorityQueue
+
+ def __init__(self, initial_threads, max_threads, queue_size, prefix=None):
+ prefix = prefix or 'tp-0x%0x' % id(self)
+ logging.debug(
+ 'New ThreadPool(%d, %d, %d): %s', initial_threads, max_threads,
+ queue_size, prefix)
+ assert initial_threads <= max_threads
+ # Update this check once 256 cores CPU are common.
+ assert max_threads <= 256
+
+ self.tasks = self.QUEUE_CLASS(queue_size)
+ self._max_threads = max_threads
+ self._prefix = prefix
+
+ # Used to assign indexes to tasks.
+ self._num_of_added_tasks_lock = threading.Lock()
+ self._num_of_added_tasks = 0
+
+ # Lock that protected everything below (including conditional variable).
+ self._lock = threading.Lock()
+
+ # Condition 'bool(_outputs) or bool(_exceptions) or _pending_count == 0'.
+ self._outputs_exceptions_cond = threading.Condition(self._lock)
+ self._outputs = []
+ self._exceptions = []
+
+ # Number of pending tasks (queued or being processed now).
+ self._pending_count = 0
+
+ # List of threads.
+ self._workers = []
+ # Number of threads that are waiting for new tasks.
+ self._ready = 0
+ # Number of threads already added to _workers, but not yet running the loop.
+ self._starting = 0
+ # True if close was called. Forbids adding new tasks.
+ self._is_closed = False
+
+ for _ in range(initial_threads):
+ self._add_worker()
+
+ def _add_worker(self):
+ """Adds one worker thread if there isn't too many. Thread-safe."""
+ with self._lock:
+ if len(self._workers) >= self._max_threads or self._is_closed:
+ return False
+ worker = threading.Thread(
+ name='%s-%d' % (self._prefix, len(self._workers)), target=self._run)
+ self._workers.append(worker)
+ self._starting += 1
+ logging.debug('Starting worker thread %s', worker.name)
+ worker.daemon = True
+ worker.start()
+ return True
+
+ def add_task(self, priority, func, *args, **kwargs):
+ """Adds a task, a function to be executed by a worker.
+
+ |priority| can adjust the priority of the task versus others. Lower priority
+ takes precedence.
+
+ |func| can either return a return value to be added to the output list or
+ be a generator which can emit multiple values.
+
+ Returns the index of the item added, e.g. the total number of enqueued items
+ up to now.
+ """
+ assert isinstance(priority, int)
+ assert callable(func)
+ with self._lock:
+ if self._is_closed:
+ raise ThreadPoolClosed('Can not add a task to a closed ThreadPool')
+ start_new_worker = (
+ # Pending task count plus new task > number of available workers.
+ self.tasks.qsize() + 1 > self._ready + self._starting and
+ # Enough slots.
+ len(self._workers) < self._max_threads
+ )
+ self._pending_count += 1
+ with self._num_of_added_tasks_lock:
+ self._num_of_added_tasks += 1
+ index = self._num_of_added_tasks
+ self.tasks.put((priority, index, func, args, kwargs))
+ if start_new_worker:
+ self._add_worker()
+ return index
+
+ def _run(self):
+ """Worker thread loop. Runs until a None task is queued."""
+ # Thread has started, adjust counters.
+ with self._lock:
+ self._starting -= 1
+ self._ready += 1
+ while True:
+ try:
+ task = self.tasks.get()
+ finally:
+ with self._lock:
+ self._ready -= 1
+ try:
+ if task is None:
+ # We're done.
+ return
+ _priority, _index, func, args, kwargs = task
+ if inspect.isgeneratorfunction(func):
+ for out in func(*args, **kwargs):
+ self._output_append(out)
+ else:
+ out = func(*args, **kwargs)
+ self._output_append(out)
+ except Exception as e:
+ logging.warning('Caught exception: %s', e)
+ exc_info = sys.exc_info()
+ logging.info(''.join(traceback.format_tb(exc_info[2])))
+ with self._outputs_exceptions_cond:
+ self._exceptions.append(exc_info)
+ self._outputs_exceptions_cond.notifyAll()
+ finally:
+ try:
+ # Mark thread as ready again, mark task as processed. Do it before
+ # waking up threads waiting on self.tasks.join(). Otherwise they might
+ # find ThreadPool still 'busy' and perform unnecessary wait on CV.
+ with self._outputs_exceptions_cond:
+ self._ready += 1
+ self._pending_count -= 1
+ if self._pending_count == 0:
+ self._outputs_exceptions_cond.notifyAll()
+ self.tasks.task_done()
+ except Exception as e:
+ # We need to catch and log this error here because this is the root
+ # function for the thread, nothing higher will catch the error.
+ logging.exception('Caught exception while marking task as done: %s',
+ e)
+
+ def _output_append(self, out):
+ if out is not None:
+ with self._outputs_exceptions_cond:
+ self._outputs.append(out)
+ self._outputs_exceptions_cond.notifyAll()
+
+ def join(self):
+ """Extracts all the results from each threads unordered.
+
+ Call repeatedly to extract all the exceptions if desired.
+
+ Note: will wait for all work items to be done before returning an exception.
+ To get an exception early, use get_one_result().
+ """
+ # TODO(maruel): Stop waiting as soon as an exception is caught.
+ self.tasks.join()
+ with self._outputs_exceptions_cond:
+ if self._exceptions:
+ e = self._exceptions.pop(0)
+ raise e[0], e[1], e[2]
+ out = self._outputs
+ self._outputs = []
+ return out
+
+ def get_one_result(self):
+ """Returns the next item that was generated or raises an exception if one
+ occurred.
+
+ Raises:
+ ThreadPoolEmpty - no results available.
+ """
+ # Get first available result.
+ for result in self.iter_results():
+ return result
+ # No results -> tasks queue is empty.
+ raise ThreadPoolEmpty('Task queue is empty')
+
+ def iter_results(self):
+ """Yields results as they appear until all tasks are processed."""
+ while True:
+ # Check for pending results.
+ result = None
+ with self._outputs_exceptions_cond:
+ if self._exceptions:
+ e = self._exceptions.pop(0)
+ raise e[0], e[1], e[2]
+ if self._outputs:
+ # Remember the result to yield it outside of the lock.
+ result = self._outputs.pop(0)
+ else:
+ # No pending tasks -> all tasks are done.
+ if not self._pending_count:
+ return
+ # Some task is queued, wait for its result to appear.
+ # Use non-None timeout so that process reacts to Ctrl+C and other
+ # signals, see http://bugs.python.org/issue8844.
+ self._outputs_exceptions_cond.wait(timeout=5)
+ continue
+ yield result
+
+ def close(self):
+ """Closes all the threads."""
+ # Ensure no new threads can be started, self._workers is effectively
+ # a constant after that and can be accessed outside the lock.
+ with self._lock:
+ if self._is_closed:
+ raise ThreadPoolClosed('Can not close already closed ThreadPool')
+ self._is_closed = True
+ for _ in range(len(self._workers)):
+ # Enqueueing None causes the worker to stop.
+ self.tasks.put(None)
+ for t in self._workers:
+ t.join()
+ logging.debug(
+ 'Thread pool \'%s\' closed: spawned %d threads total',
+ self._prefix, len(self._workers))
+
+ def __enter__(self):
+ """Enables 'with' statement."""
+ return self
+
+ def __exit__(self, _exc_type, _exc_value, _traceback):
+ """Enables 'with' statement."""
+ self.close()
+
+
+def valid_file(filepath, size):
+ """Determines if the given files appears valid (currently it just checks
+ the file's size)."""
+ if size == UNKNOWN_FILE_SIZE:
+ return True
+ actual_size = os.stat(filepath).st_size
+ if size != actual_size:
+ logging.warning(
+ 'Found invalid item %s; %d != %d',
+ os.path.basename(filepath), actual_size, size)
+ return False
+ return True
+
+
+class Profiler(object):
+ def __init__(self, name):
+ self.name = name
+ self.start_time = None
+
+ def __enter__(self):
+ self.start_time = time.time()
+ return self
+
+ def __exit__(self, _exc_type, _exec_value, _traceback):
+ time_taken = time.time() - self.start_time
+ logging.info('Profiling: Section %s took %3.3f seconds',
+ self.name, time_taken)
+
+
+class DeadlockDetector(object):
+ """Context manager that can detect deadlocks.
+
+ It will dump stack frames of all running threads if its 'ping' method isn't
+ called in time.
+
+ Usage:
+ with DeadlockDetector(timeout=60) as detector:
+ for item in some_work():
+ ...
+ detector.ping()
+ ...
+
+ Arguments:
+ timeout - maximum allowed time between calls to 'ping'.
+ """
+
+ def __init__(self, timeout):
+ self.timeout = timeout
+ self._thread = None
+ # Thread stop condition. Also lock for shared variables below.
+ self._stop_cv = threading.Condition()
+ self._stop_flag = False
+ # Time when 'ping' was called last time.
+ self._last_ping = None
+ # True if pings are coming on time.
+ self._alive = True
+
+ def __enter__(self):
+ """Starts internal watcher thread."""
+ assert self._thread is None
+ self.ping()
+ self._thread = threading.Thread(name='deadlock-detector', target=self._run)
+ self._thread.daemon = True
+ self._thread.start()
+ return self
+
+ def __exit__(self, *_args):
+ """Stops internal watcher thread."""
+ assert self._thread is not None
+ with self._stop_cv:
+ self._stop_flag = True
+ self._stop_cv.notify()
+ self._thread.join()
+ self._thread = None
+ self._stop_flag = False
+
+ def ping(self):
+ """Notify detector that main thread is still running.
+
+ Should be called periodically to inform the detector that everything is
+ running as it should.
+ """
+ with self._stop_cv:
+ self._last_ping = time.time()
+ self._alive = True
+
+ def _run(self):
+ """Loop that watches for pings and dumps threads state if ping is late."""
+ with self._stop_cv:
+ while not self._stop_flag:
+ # Skipped deadline? Dump threads and switch to 'not alive' state.
+ if self._alive and time.time() > self._last_ping + self.timeout:
+ self.dump_threads(time.time() - self._last_ping, True)
+ self._alive = False
+
+ # Pings are on time?
+ if self._alive:
+ # Wait until the moment we need to dump stack traces.
+ # Most probably some other thread will call 'ping' to move deadline
+ # further in time. We don't bother to wake up after each 'ping',
+ # only right before initial expected deadline.
+ self._stop_cv.wait(self._last_ping + self.timeout - time.time())
+ else:
+ # Skipped some pings previously. Just periodically silently check
+ # for new pings with some arbitrary frequency.
+ self._stop_cv.wait(self.timeout * 0.1)
+
+ @staticmethod
+ def dump_threads(timeout=None, skip_current_thread=False):
+ """Dumps stack frames of all running threads."""
+ all_threads = threading.enumerate()
+ current_thread_id = threading.current_thread().ident
+
+ # Collect tracebacks: thread name -> traceback string.
+ tracebacks = {}
+
+ # pylint: disable=W0212
+ for thread_id, frame in sys._current_frames().iteritems():
+ # Don't dump deadlock detector's own thread, it's boring.
+ if thread_id == current_thread_id and not skip_current_thread:
+ continue
+
+ # Try to get more informative symbolic thread name.
+ name = 'untitled'
+ for thread in all_threads:
+ if thread.ident == thread_id:
+ name = thread.name
+ break
+ name += ' #%d' % (thread_id,)
+ tracebacks[name] = ''.join(traceback.format_stack(frame))
+
+ # Function to print a message. Makes it easier to change output destination.
+ def output(msg):
+ logging.warning(msg.rstrip())
+
+ # Print tracebacks, sorting them by thread name. That way a thread pool's
+ # threads will be printed as one group.
+ output('=============== Potential deadlock detected ===============')
+ if timeout is not None:
+ output('No pings in last %d sec.' % (timeout,))
+ output('Dumping stack frames for all threads:')
+ for name in sorted(tracebacks):
+ output('Traceback for \'%s\':\n%s' % (name, tracebacks[name]))
+ output('===========================================================')
+
+
+class Remote(object):
+ """Priority based worker queue to fetch or upload files from a
+ content-address server. Any function may be given as the fetcher/upload,
+ as long as it takes two inputs (the item contents, and their relative
+ destination).
+
+ Supports local file system, CIFS or http remotes.
+
+ When the priority of items is equals, works in strict FIFO mode.
+ """
+ # Initial and maximum number of worker threads.
+ INITIAL_WORKERS = 2
+ MAX_WORKERS = 16
+ # Priorities.
+ LOW, MED, HIGH = (1<<8, 2<<8, 3<<8)
+ INTERNAL_PRIORITY_BITS = (1<<8) - 1
+ RETRIES = 5
+
+ def __init__(self, destination_root):
+ # Function to fetch a remote object or upload to a remote location..
+ self._do_item = self.get_file_handler(destination_root)
+ # Contains tuple(priority, obj).
+ self._done = Queue.PriorityQueue()
+ self._pool = ThreadPool(self.INITIAL_WORKERS, self.MAX_WORKERS, 0, 'remote')
+
+ def join(self):
+ """Blocks until the queue is empty."""
+ return self._pool.join()
+
+ def close(self):
+ """Terminates all worker threads."""
+ self._pool.close()
+
+ def add_item(self, priority, obj, dest, size):
+ """Retrieves an object from the remote data store.
+
+ The smaller |priority| gets fetched first.
+
+ Thread-safe.
+ """
+ assert (priority & self.INTERNAL_PRIORITY_BITS) == 0
+ return self._add_item(priority, obj, dest, size)
+
+ def _add_item(self, priority, obj, dest, size):
+ assert isinstance(obj, basestring), obj
+ assert isinstance(dest, basestring), dest
+ assert size is None or isinstance(size, int), size
+ return self._pool.add_task(
+ priority, self._task_executer, priority, obj, dest, size)
+
+ def get_one_result(self):
+ return self._pool.get_one_result()
+
+ def _task_executer(self, priority, obj, dest, size):
+ """Wraps self._do_item to trap and retry on IOError exceptions."""
+ try:
+ self._do_item(obj, dest)
+ if size and not valid_file(dest, size):
+ download_size = os.stat(dest).st_size
+ os.remove(dest)
+ raise IOError('File incorrect size after download of %s. Got %s and '
+ 'expected %s' % (obj, download_size, size))
+ # TODO(maruel): Technically, we'd want to have an output queue to be a
+ # PriorityQueue.
+ return obj
+ except IOError as e:
+ logging.debug('Caught IOError: %s', e)
+ # Remove unfinished download.
+ if os.path.exists(dest):
+ os.remove(dest)
+ # Retry a few times, lowering the priority.
+ if (priority & self.INTERNAL_PRIORITY_BITS) < self.RETRIES:
+ self._add_item(priority + 1, obj, dest, size)
+ return
+ raise
+
+ def get_file_handler(self, file_or_url): # pylint: disable=R0201
+ """Returns a object to retrieve objects from a remote."""
+ if re.match(r'^https?://.+$', file_or_url):
+ return functools.partial(self._download_file, file_or_url)
+ else:
+ return functools.partial(self._copy_file, file_or_url)
+
+ @staticmethod
+ def _download_file(base_url, item, dest):
+ # TODO(maruel): Reuse HTTP connections. The stdlib doesn't make this
+ # easy.
+ try:
+ zipped_source = base_url + item
+ logging.debug('download_file(%s)', zipped_source)
+
+ # Because the app engine DB is only eventually consistent, retry
+ # 404 errors because the file might just not be visible yet (even
+ # though it has been uploaded).
+ connection = url_open(zipped_source, retry_404=True,
+ read_timeout=DOWNLOAD_READ_TIMEOUT)
+ if not connection:
+ raise IOError('Unable to open connection to %s' % zipped_source)
+
+ content_length = connection.content_length
+ decompressor = zlib.decompressobj()
+ size = 0
+ with open(dest, 'wb') as f:
+ while True:
+ chunk = connection.read(ZIPPED_FILE_CHUNK)
+ if not chunk:
+ break
+ size += len(chunk)
+ f.write(decompressor.decompress(chunk))
+ # Ensure that all the data was properly decompressed.
+ uncompressed_data = decompressor.flush()
+ assert not uncompressed_data
+ except IOError as e:
+ logging.error('Failed to download %s at %s.\n%s', item, dest, e)
+ raise
+ except httplib.HTTPException as e:
+ msg = 'HTTPException while retrieving %s at %s.\n%s' % (item, dest, e)
+ logging.error(msg)
+ raise IOError(msg)
+ except zlib.error as e:
+ msg = 'Corrupted zlib for item %s. Processed %d of %s bytes.\n%s' % (
+ item, size, content_length, e)
+ logging.error(msg)
+
+ # Testing seems to show that if a few machines are trying to download
+ # the same blob, they can cause each other to fail. So if we hit a
+ # zip error, this is the most likely cause (it only downloads some of
+ # the data). Randomly sleep for between 5 and 25 seconds to try and
+ # spread out the downloads.
+ # TODO(csharp): Switch from blobstorage to cloud storage and see if
+ # that solves the issue.
+ sleep_duration = (random.random() * 20) + 5
+ time.sleep(sleep_duration)
+
+ raise IOError(msg)
+
+ @staticmethod
+ def _copy_file(base_path, item, dest):
+ source = os.path.join(base_path, item)
+ if source == dest:
+ logging.info('Source and destination are the same, no action required')
+ return
+ logging.debug('copy_file(%s, %s)', source, dest)
+ shutil.copy(source, dest)
+
+
+class CachePolicies(object):
+ def __init__(self, max_cache_size, min_free_space, max_items):
+ """
+ Arguments:
+ - max_cache_size: Trim if the cache gets larger than this value. If 0, the
+ cache is effectively a leak.
+ - min_free_space: Trim if disk free space becomes lower than this value. If
+ 0, it unconditionally fill the disk.
+ - max_items: Maximum number of items to keep in the cache. If 0, do not
+ enforce a limit.
+ """
+ self.max_cache_size = max_cache_size
+ self.min_free_space = min_free_space
+ self.max_items = max_items
+
+
+class NoCache(object):
+ """This class is intended to be usable everywhere the Cache class is.
+ Instead of downloading to a cache, all files are downloaded to the target
+ directory and then moved to where they are needed.
+ """
+
+ def __init__(self, target_directory, remote):
+ self.target_directory = target_directory
+ self.remote = remote
+
+ def retrieve(self, priority, item, size):
+ """Get the request file."""
+ self.remote.add_item(priority, item, self.path(item), size)
+ self.remote.get_one_result()
+
+ def wait_for(self, items):
+ """Download the first item of the given list if it is missing."""
+ item = items.iterkeys().next()
+
+ if not os.path.exists(self.path(item)):
+ self.remote.add_item(Remote.MED, item, self.path(item), UNKNOWN_FILE_SIZE)
+ downloaded = self.remote.get_one_result()
+ assert downloaded == item
+
+ return item
+
+ def path(self, item):
+ return os.path.join(self.target_directory, item)
+
+
+class Cache(object):
+ """Stateful LRU cache.
+
+ Saves its state as json file.
+ """
+ STATE_FILE = 'state.json'
+
+ def __init__(self, cache_dir, remote, policies):
+ """
+ Arguments:
+ - cache_dir: Directory where to place the cache.
+ - remote: Remote where to fetch items from.
+ - policies: cache retention policies.
+ """
+ self.cache_dir = cache_dir
+ self.remote = remote
+ self.policies = policies
+ self.state_file = os.path.join(cache_dir, self.STATE_FILE)
+ # The tuple(file, size) are kept as an array in a LRU style. E.g.
+ # self.state[0] is the oldest item.
+ self.state = []
+ self._state_need_to_be_saved = False
+ # A lookup map to speed up searching.
+ self._lookup = {}
+ self._lookup_is_stale = True
+
+ # Items currently being fetched. Keep it local to reduce lock contention.
+ self._pending_queue = set()
+
+ # Profiling values.
+ self._added = []
+ self._removed = []
+ self._free_disk = 0
+
+ with Profiler('Setup'):
+ if not os.path.isdir(self.cache_dir):
+ os.makedirs(self.cache_dir)
+ if os.path.isfile(self.state_file):
+ try:
+ self.state = json.load(open(self.state_file, 'r'))
+ except (IOError, ValueError), e:
+ # Too bad. The file will be overwritten and the cache cleared.
+ logging.error(
+ 'Broken state file %s, ignoring.\n%s' % (self.STATE_FILE, e))
+ self._state_need_to_be_saved = True
+ if (not isinstance(self.state, list) or
+ not all(
+ isinstance(i, (list, tuple)) and len(i) == 2
+ for i in self.state)):
+ # Discard.
+ self._state_need_to_be_saved = True
+ self.state = []
+
+ # Ensure that all files listed in the state still exist and add new ones.
+ previous = set(filename for filename, _ in self.state)
+ if len(previous) != len(self.state):
+ logging.warning('Cache state is corrupted, found duplicate files')
+ self._state_need_to_be_saved = True
+ self.state = []
+
+ added = 0
+ for filename in os.listdir(self.cache_dir):
+ if filename == self.STATE_FILE:
+ continue
+ if filename in previous:
+ previous.remove(filename)
+ continue
+ # An untracked file.
+ if not RE_IS_SHA1.match(filename):
+ logging.warning('Removing unknown file %s from cache', filename)
+ os.remove(self.path(filename))
+ continue
+ # Insert as the oldest file. It will be deleted eventually if not
+ # accessed.
+ self._add(filename, False)
+ logging.warning('Add unknown file %s to cache', filename)
+ added += 1
+
+ if added:
+ logging.warning('Added back %d unknown files', added)
+ if previous:
+ logging.warning('Removed %d lost files', len(previous))
+ # Set explicitly in case self._add() wasn't called.
+ self._state_need_to_be_saved = True
+ # Filter out entries that were not found while keeping the previous
+ # order.
+ self.state = [
+ (filename, size) for filename, size in self.state
+ if filename not in previous
+ ]
+ self.trim()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, _exc_type, _exec_value, _traceback):
+ with Profiler('CleanupTrimming'):
+ self.trim()
+
+ logging.info(
+ '%5d (%8dkb) added', len(self._added), sum(self._added) / 1024)
+ logging.info(
+ '%5d (%8dkb) current',
+ len(self.state),
+ sum(i[1] for i in self.state) / 1024)
+ logging.info(
+ '%5d (%8dkb) removed', len(self._removed), sum(self._removed) / 1024)
+ logging.info(' %8dkb free', self._free_disk / 1024)
+
+ def remove_file_at_index(self, index):
+ """Removes the file at the given index."""
+ try:
+ self._state_need_to_be_saved = True
+ filename, size = self.state.pop(index)
+ # If the lookup was already stale, its possible the filename was not
+ # present yet.
+ self._lookup_is_stale = True
+ self._lookup.pop(filename, None)
+ self._removed.append(size)
+ os.remove(self.path(filename))
+ except OSError as e:
+ logging.error('Error attempting to delete a file\n%s' % e)
+
+ def remove_lru_file(self):
+ """Removes the last recently used file."""
+ self.remove_file_at_index(0)
+
+ def trim(self):
+ """Trims anything we don't know, make sure enough free space exists."""
+ # Ensure maximum cache size.
+ if self.policies.max_cache_size and self.state:
+ while sum(i[1] for i in self.state) > self.policies.max_cache_size:
+ self.remove_lru_file()
+
+ # Ensure maximum number of items in the cache.
+ if self.policies.max_items and self.state:
+ while len(self.state) > self.policies.max_items:
+ self.remove_lru_file()
+
+ # Ensure enough free space.
+ self._free_disk = get_free_space(self.cache_dir)
+ trimmed_due_to_space = False
+ while (
+ self.policies.min_free_space and
+ self.state and
+ self._free_disk < self.policies.min_free_space):
+ trimmed_due_to_space = True
+ self.remove_lru_file()
+ self._free_disk = get_free_space(self.cache_dir)
+ if trimmed_due_to_space:
+ total = sum(i[1] for i in self.state)
+ logging.warning(
+ 'Trimmed due to not enough free disk space: %.1fkb free, %.1fkb '
+ 'cache (%.1f%% of its maximum capacity)',
+ self._free_disk / 1024.,
+ total / 1024.,
+ 100. * self.policies.max_cache_size / float(total),
+ )
+ self.save()
+
+ def retrieve(self, priority, item, size):
+ """Retrieves a file from the remote, if not already cached, and adds it to
+ the cache.
+
+ If the file is in the cache, verifiy that the file is valid (i.e. it is
+ the correct size), retrieving it again if it isn't.
+ """
+ assert not '/' in item
+ path = self.path(item)
+ self._update_lookup()
+ index = self._lookup.get(item)
+
+ if index is not None:
+ if not valid_file(self.path(item), size):
+ self.remove_file_at_index(index)
+ index = None
+ else:
+ assert index < len(self.state)
+ # Was already in cache. Update it's LRU value by putting it at the end.
+ self._state_need_to_be_saved = True
+ self._lookup_is_stale = True
+ self.state.append(self.state.pop(index))
+
+ if index is None:
+ if item in self._pending_queue:
+ # Already pending. The same object could be referenced multiple times.
+ return
+ # TODO(maruel): It should look at the free disk space, the current cache
+ # size and the size of the new item on every new item:
+ # - Trim the cache as more entries are listed when free disk space is low,
+ # otherwise if the amount of data downloaded during the run > free disk
+ # space, it'll crash.
+ # - Make sure there's enough free disk space to fit all dependencies of
+ # this run! If not, abort early.
+ self.remote.add_item(priority, item, path, size)
+ self._pending_queue.add(item)
+
+ def add(self, filepath, obj):
+ """Forcibly adds a file to the cache."""
+ self._update_lookup()
+ if not obj in self._lookup:
+ link_file(self.path(obj), filepath, HARDLINK_WITH_FALLBACK)
+ self._add(obj, True)
+
+ def path(self, item):
+ """Returns the path to one item."""
+ return os.path.join(self.cache_dir, item)
+
+ def save(self):
+ """Saves the LRU ordering."""
+ if self._state_need_to_be_saved:
+ json.dump(self.state, open(self.state_file, 'wb'), separators=(',',':'))
+ self._state_need_to_be_saved = False
+
+ def wait_for(self, items):
+ """Starts a loop that waits for at least one of |items| to be retrieved.
+
+ Returns the first item retrieved.
+ """
+ # Flush items already present.
+ self._update_lookup()
+ for item in items:
+ if item in self._lookup:
+ return item
+
+ assert all(i in self._pending_queue for i in items), (
+ items, self._pending_queue)
+ # Note that:
+ # len(self._pending_queue) ==
+ # ( len(self.remote._workers) - self.remote._ready +
+ # len(self._remote._queue) + len(self._remote.done))
+ # There is no lock-free way to verify that.
+ while self._pending_queue:
+ item = self.remote.get_one_result()
+ self._pending_queue.remove(item)
+ self._add(item, True)
+ if item in items:
+ return item
+
+ def _add(self, item, at_end):
+ """Adds an item in the internal state.
+
+ If |at_end| is False, self._lookup becomes inconsistent and
+ self._update_lookup() must be called.
+ """
+ size = os.stat(self.path(item)).st_size
+ self._added.append(size)
+ self._state_need_to_be_saved = True
+ if at_end:
+ self.state.append((item, size))
+ self._lookup[item] = len(self.state) - 1
+ else:
+ self._lookup_is_stale = True
+ self.state.insert(0, (item, size))
+
+ def _update_lookup(self):
+ if self._lookup_is_stale:
+ self._lookup = dict(
+ (filename, index) for index, (filename, _) in enumerate(self.state))
+ self._lookup_is_stale = False
+
+
+class IsolatedFile(object):
+ """Represents a single parsed .isolated file."""
+ def __init__(self, obj_hash):
+ """|obj_hash| is really the sha-1 of the file."""
+ logging.debug('IsolatedFile(%s)' % obj_hash)
+ self.obj_hash = obj_hash
+ # Set once all the left-side of the tree is parsed. 'Tree' here means the
+ # .isolate and all the .isolated files recursively included by it with
+ # 'includes' key. The order of each sha-1 in 'includes', each representing a
+ # .isolated file in the hash table, is important, as the later ones are not
+ # processed until the firsts are retrieved and read.
+ self.can_fetch = False
+
+ # Raw data.
+ self.data = {}
+ # A IsolatedFile instance, one per object in self.includes.
+ self.children = []
+
+ # Set once the .isolated file is loaded.
+ self._is_parsed = False
+ # Set once the files are fetched.
+ self.files_fetched = False
+
+ def load(self, content):
+ """Verifies the .isolated file is valid and loads this object with the json
+ data.
+ """
+ logging.debug('IsolatedFile.load(%s)' % self.obj_hash)
+ assert not self._is_parsed
+ self.data = load_isolated(content)
+ self.children = [IsolatedFile(i) for i in self.data.get('includes', [])]
+ self._is_parsed = True
+
+ def fetch_files(self, cache, files):
+ """Adds files in this .isolated file not present in |files| dictionary.
+
+ Preemptively request files.
+
+ Note that |files| is modified by this function.
+ """
+ assert self.can_fetch
+ if not self._is_parsed or self.files_fetched:
+ return
+ logging.debug('fetch_files(%s)' % self.obj_hash)
+ for filepath, properties in self.data.get('files', {}).iteritems():
+ # Root isolated has priority on the files being mapped. In particular,
+ # overriden files must not be fetched.
+ if filepath not in files:
+ files[filepath] = properties
+ if 'h' in properties:
+ # Preemptively request files.
+ logging.debug('fetching %s' % filepath)
+ cache.retrieve(Remote.MED, properties['h'], properties['s'])
+ self.files_fetched = True
+
+
+class Settings(object):
+ """Results of a completely parsed .isolated file."""
+ def __init__(self):
+ self.command = []
+ self.files = {}
+ self.read_only = None
+ self.relative_cwd = None
+ # The main .isolated file, a IsolatedFile instance.
+ self.root = None
+
+ def load(self, cache, root_isolated_hash):
+ """Loads the .isolated and all the included .isolated asynchronously.
+
+ It enables support for "included" .isolated files. They are processed in
+ strict order but fetched asynchronously from the cache. This is important so
+ that a file in an included .isolated file that is overridden by an embedding
+ .isolated file is not fetched needlessly. The includes are fetched in one
+ pass and the files are fetched as soon as all the ones on the left-side
+ of the tree were fetched.
+
+ The prioritization is very important here for nested .isolated files.
+ 'includes' have the highest priority and the algorithm is optimized for both
+ deep and wide trees. A deep one is a long link of .isolated files referenced
+ one at a time by one item in 'includes'. A wide one has a large number of
+ 'includes' in a single .isolated file. 'left' is defined as an included
+ .isolated file earlier in the 'includes' list. So the order of the elements
+ in 'includes' is important.
+ """
+ self.root = IsolatedFile(root_isolated_hash)
+
+ # Isolated files being retrieved now: hash -> IsolatedFile instance.
+ pending = {}
+ # Set of hashes of already retrieved items to refuse recursive includes.
+ seen = set()
+
+ def retrieve(isolated_file):
+ h = isolated_file.obj_hash
+ if h in seen:
+ raise ConfigError('IsolatedFile %s is retrieved recursively' % h)
+ assert h not in pending
+ seen.add(h)
+ pending[h] = isolated_file
+ cache.retrieve(Remote.HIGH, h, UNKNOWN_FILE_SIZE)
+
+ retrieve(self.root)
+
+ while pending:
+ item_hash = cache.wait_for(pending)
+ item = pending.pop(item_hash)
+ item.load(open(cache.path(item_hash), 'r').read())
+ if item_hash == root_isolated_hash:
+ # It's the root item.
+ item.can_fetch = True
+
+ for new_child in item.children:
+ retrieve(new_child)
+
+ # Traverse the whole tree to see if files can now be fetched.
+ self._traverse_tree(cache, self.root)
+
+ def check(n):
+ return all(check(x) for x in n.children) and n.files_fetched
+ assert check(self.root)
+
+ self.relative_cwd = self.relative_cwd or ''
+ self.read_only = self.read_only or False
+
+ def _traverse_tree(self, cache, node):
+ if node.can_fetch:
+ if not node.files_fetched:
+ self._update_self(cache, node)
+ will_break = False
+ for i in node.children:
+ if not i.can_fetch:
+ if will_break:
+ break
+ # Automatically mark the first one as fetcheable.
+ i.can_fetch = True
+ will_break = True
+ self._traverse_tree(cache, i)
+
+ def _update_self(self, cache, node):
+ node.fetch_files(cache, self.files)
+ # Grabs properties.
+ if not self.command and node.data.get('command'):
+ self.command = node.data['command']
+ if self.read_only is None and node.data.get('read_only') is not None:
+ self.read_only = node.data['read_only']
+ if (self.relative_cwd is None and
+ node.data.get('relative_cwd') is not None):
+ self.relative_cwd = node.data['relative_cwd']
+
+
+def create_directories(base_directory, files):
+ """Creates the directory structure needed by the given list of files."""
+ logging.debug('create_directories(%s, %d)', base_directory, len(files))
+ # Creates the tree of directories to create.
+ directories = set(os.path.dirname(f) for f in files)
+ for item in list(directories):
+ while item:
+ directories.add(item)
+ item = os.path.dirname(item)
+ for d in sorted(directories):
+ if d:
+ os.mkdir(os.path.join(base_directory, d))
+
+
+def create_links(base_directory, files):
+ """Creates any links needed by the given set of files."""
+ for filepath, properties in files:
+ if 'l' not in properties:
+ continue
+ if sys.platform == 'win32':
+ # TODO(maruel): Create junctions or empty text files similar to what
+ # cygwin do?
+ logging.warning('Ignoring symlink %s', filepath)
+ continue
+ outfile = os.path.join(base_directory, filepath)
+ # symlink doesn't exist on Windows. So the 'link' property should
+ # never be specified for windows .isolated file.
+ os.symlink(properties['l'], outfile) # pylint: disable=E1101
+ if 'm' in properties:
+ lchmod = getattr(os, 'lchmod', None)
+ if lchmod:
+ lchmod(outfile, properties['m'])
+
+
+def setup_commands(base_directory, cwd, cmd):
+ """Correctly adjusts and then returns the required working directory
+ and command needed to run the test.
+ """
+ assert not os.path.isabs(cwd), 'The cwd must be a relative path, got %s' % cwd
+ cwd = os.path.join(base_directory, cwd)
+ if not os.path.isdir(cwd):
+ os.makedirs(cwd)
+
+ # Ensure paths are correctly separated on windows.
+ cmd[0] = cmd[0].replace('/', os.path.sep)
+ cmd = fix_python_path(cmd)
+
+ return cwd, cmd
+
+
+def generate_remaining_files(files):
+ """Generates a dictionary of all the remaining files to be downloaded."""
+ remaining = {}
+ for filepath, props in files:
+ if 'h' in props:
+ remaining.setdefault(props['h'], []).append((filepath, props))
+
+ return remaining
+
+
+def download_test_data(isolated_hash, target_directory, remote):
+ """Downloads the dependencies to the given directory."""
+ if not os.path.exists(target_directory):
+ os.makedirs(target_directory)
+
+ settings = Settings()
+ no_cache = NoCache(target_directory, Remote(remote))
+
+ # Download all the isolated files.
+ with Profiler('GetIsolateds') as _prof:
+ settings.load(no_cache, isolated_hash)
+
+ if not settings.command:
+ print >> sys.stderr, 'No command to run'
+ return 1
+
+ with Profiler('GetRest') as _prof:
+ create_directories(target_directory, settings.files)
+ create_links(target_directory, settings.files.iteritems())
+
+ cwd, cmd = setup_commands(target_directory, settings.relative_cwd,
+ settings.command[:])
+
+ remaining = generate_remaining_files(settings.files.iteritems())
+
+ # Now block on the remaining files to be downloaded and mapped.
+ logging.info('Retrieving remaining files')
+ last_update = time.time()
+ while remaining:
+ obj = no_cache.wait_for(remaining)
+ files = remaining.pop(obj)
+
+ for i, (filepath, properties) in enumerate(files):
+ outfile = os.path.join(target_directory, filepath)
+ logging.info(no_cache.path(obj))
+
+ if i + 1 == len(files):
+ os.rename(no_cache.path(obj), outfile)
+ else:
+ shutil.copyfile(no_cache.path(obj), outfile)
+
+ if 'm' in properties and not sys.platform == 'win32':
+ # It's not set on Windows. It could be set only in the case of
+ # downloading content generated from another OS. Do not crash in that
+ # case.
+ os.chmod(outfile, properties['m'])
+
+ if time.time() - last_update > DELAY_BETWEEN_UPDATES_IN_SECS:
+ msg = '%d files remaining...' % len(remaining)
+ print msg
+ logging.info(msg)
+ last_update = time.time()
+
+ print('.isolated files successfully downloaded and setup in %s' %
+ target_directory)
+ print('To run this test please run the command %s from the directory %s' %
+ (cmd, cwd))
+
+ return 0
+
+
+def run_tha_test(isolated_hash, cache_dir, remote, policies):
+ """Downloads the dependencies in the cache, hardlinks them into a temporary
+ directory and runs the executable.
+ """
+ settings = Settings()
+ with Cache(cache_dir, Remote(remote), policies) as cache:
+ outdir = make_temp_dir('run_tha_test', cache_dir)
+ try:
+ # Initiate all the files download.
+ with Profiler('GetIsolateds') as _prof:
+ # Optionally support local files.
+ if not RE_IS_SHA1.match(isolated_hash):
+ # Adds it in the cache. While not strictly necessary, this simplifies
+ # the rest.
+ h = hashlib.sha1(open(isolated_hash, 'rb').read()).hexdigest()
+ cache.add(isolated_hash, h)
+ isolated_hash = h
+ settings.load(cache, isolated_hash)
+
+ if not settings.command:
+ print >> sys.stderr, 'No command to run'
+ return 1
+
+ with Profiler('GetRest') as _prof:
+ create_directories(outdir, settings.files)
+ create_links(outdir, settings.files.iteritems())
+ remaining = generate_remaining_files(settings.files.iteritems())
+
+ # Do bookkeeping while files are being downloaded in the background.
+ cwd, cmd = setup_commands(outdir, settings.relative_cwd,
+ settings.command[:])
+
+ # Now block on the remaining files to be downloaded and mapped.
+ logging.info('Retrieving remaining files')
+ last_update = time.time()
+ with DeadlockDetector(DEADLOCK_TIMEOUT) as detector:
+ while remaining:
+ detector.ping()
+ obj = cache.wait_for(remaining)
+ for filepath, properties in remaining.pop(obj):
+ outfile = os.path.join(outdir, filepath)
+ link_file(outfile, cache.path(obj), HARDLINK)
+ if 'm' in properties:
+ # It's not set on Windows.
+ os.chmod(outfile, properties['m'])
+
+ if time.time() - last_update > DELAY_BETWEEN_UPDATES_IN_SECS:
+ msg = '%d files remaining...' % len(remaining)
+ print msg
+ logging.info(msg)
+ last_update = time.time()
+
+ if settings.read_only:
+ logging.info('Making files read only')
+ make_writable(outdir, True)
+ logging.info('Running %s, cwd=%s' % (cmd, cwd))
+
+ # TODO(csharp): This should be specified somewhere else.
+ # Add a rotating log file if one doesn't already exist.
+ env = os.environ.copy()
+ env.setdefault('RUN_TEST_CASES_LOG_FILE', RUN_TEST_CASES_LOG)
+ try:
+ with Profiler('RunTest') as _prof:
+ return subprocess.call(cmd, cwd=cwd, env=env)
+ except OSError:
+ print >> sys.stderr, 'Failed to run %s; cwd=%s' % (cmd, cwd)
+ raise
+ finally:
+ rmtree(outdir)
+
+
+class OptionParserWithLogging(optparse.OptionParser):
+ """Adds --verbose option."""
+ def __init__(self, verbose=0, log_file=None, **kwargs):
+ kwargs.setdefault('description', sys.modules['__main__'].__doc__)
+ optparse.OptionParser.__init__(self, **kwargs)
+ self.add_option(
+ '-v', '--verbose',
+ action='count',
+ default=verbose,
+ help='Use multiple times to increase verbosity')
+ self.add_option(
+ '-l', '--log_file',
+ default=log_file,
+ help='The name of the file to store rotating log details.')
+
+ def parse_args(self, *args, **kwargs):
+ options, args = optparse.OptionParser.parse_args(self, *args, **kwargs)
+ levels = [logging.ERROR, logging.INFO, logging.DEBUG]
+ level = levels[min(len(levels) - 1, options.verbose)]
+
+ logging_console = logging.StreamHandler()
+ logging_console.setFormatter(logging.Formatter(
+ '%(levelname)5s %(module)15s(%(lineno)3d): %(message)s'))
+ logging_console.setLevel(level)
+ logging.getLogger().setLevel(level)
+ logging.getLogger().addHandler(logging_console)
+
+ if options.log_file:
+ # This is necessary otherwise attached handler will miss the messages.
+ logging.getLogger().setLevel(logging.DEBUG)
+
+ logging_rotating_file = logging.handlers.RotatingFileHandler(
+ options.log_file,
+ maxBytes=10 * 1024 * 1024,
+ backupCount=5,
+ encoding='utf-8')
+ # log files are always at DEBUG level.
+ logging_rotating_file.setLevel(logging.DEBUG)
+ logging_rotating_file.setFormatter(logging.Formatter(
+ '%(asctime)s %(levelname)-8s %(module)15s(%(lineno)3d): %(message)s'))
+ logging.getLogger().addHandler(logging_rotating_file)
+
+ return options, args
+
+
+def main():
+ disable_buffering()
+ parser = OptionParserWithLogging(
+ usage='%prog <options>', log_file=RUN_ISOLATED_LOG_FILE)
+
+ group = optparse.OptionGroup(parser, 'Download')
+ group.add_option(
+ '--download', metavar='DEST',
+ help='Downloads files to DEST and returns without running, instead of '
+ 'downloading and then running from a temporary directory.')
+ parser.add_option_group(group)
+
+ group = optparse.OptionGroup(parser, 'Data source')
+ group.add_option(
+ '-s', '--isolated',
+ metavar='FILE',
+ help='File/url describing what to map or run')
+ group.add_option(
+ '-H', '--hash',
+ help='Hash of the .isolated to grab from the hash table')
+ parser.add_option_group(group)
+
+ group.add_option(
+ '-r', '--remote', metavar='URL',
+ default=
+ 'https://isolateserver.appspot.com/content/retrieve/default-gzip/',
+ help='Remote where to get the items. Defaults to %default')
+ group = optparse.OptionGroup(parser, 'Cache management')
+ group.add_option(
+ '--cache',
+ default='cache',
+ metavar='DIR',
+ help='Cache directory, default=%default')
+ group.add_option(
+ '--max-cache-size',
+ type='int',
+ metavar='NNN',
+ default=20*1024*1024*1024,
+ help='Trim if the cache gets larger than this value, default=%default')
+ group.add_option(
+ '--min-free-space',
+ type='int',
+ metavar='NNN',
+ default=2*1024*1024*1024,
+ help='Trim if disk free space becomes lower than this value, '
+ 'default=%default')
+ group.add_option(
+ '--max-items',
+ type='int',
+ metavar='NNN',
+ default=100000,
+ help='Trim if more than this number of items are in the cache '
+ 'default=%default')
+ parser.add_option_group(group)
+
+ options, args = parser.parse_args()
+
+ if bool(options.isolated) == bool(options.hash):
+ logging.debug('One and only one of --isolated or --hash is required.')
+ parser.error('One and only one of --isolated or --hash is required.')
+ if args:
+ logging.debug('Unsupported args %s' % ' '.join(args))
+ parser.error('Unsupported args %s' % ' '.join(args))
+
+ options.cache = os.path.abspath(options.cache)
+ policies = CachePolicies(
+ options.max_cache_size, options.min_free_space, options.max_items)
+
+ if options.download:
+ return download_test_data(options.isolated or options.hash,
+ options.download, options.remote)
+ else:
+ try:
+ return run_tha_test(
+ options.isolated or options.hash,
+ options.cache,
+ options.remote,
+ policies)
+ except Exception, e:
+ # Make sure any exception is logged.
+ logging.exception(e)
+ return 1
+
+
+if __name__ == '__main__':
+ # Ensure that we are always running with the correct encoding.
+ fix_default_encoding()
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/short_expression_finder.py b/chromium/tools/swarm_client/short_expression_finder.py
new file mode 100644
index 00000000000..ffec90e81d2
--- /dev/null
+++ b/chromium/tools/swarm_client/short_expression_finder.py
@@ -0,0 +1,176 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Generates short, hopefully readable Python expressions that test variables
+for certain combinations of values.
+"""
+
+import itertools
+import re
+
+
+class ShortExpressionFinder(object):
+ """Usage:
+ >>> sef = ShortExpressionFinder([('foo', ("a", "b", "c", "d")),
+ ... ('bar', (1, 2))])
+ >>> sef.get_expr([("a", 1)])
+ foo=="a" and bar==1
+ >>> sef.get_expr([("a", 1), ("b", 2), ("c", 1)])
+ ((foo=="a" or foo=="c") and bar==1) or (foo=="b" and bar==2)
+
+ The returned expressions are of the form
+ EXPR ::= EXPR2 ( "or" EXPR2 )*
+ EXPR2 ::= EXPR3 ( "and" EXPR3 )*
+ EXPR3 ::= VAR "==" VALUE ( "or" VAR "==" VALUE )*
+ where all of the comparisons in an EXPR2 involve the same variable.
+ Only positive tests are used so that all expressions will evaluate false if
+ given an unanticipated combination of values.
+
+ A "cheapest" expression is returned. The cost of an expression is a function
+ of the number of var==value comparisons and the number of parentheses.
+
+ The expression is found by exhaustive search, but it seems to be adequately
+ fast even for fairly large sets of configuration variables.
+ """
+
+ # These must be positive integers.
+ COMPARISON_COST = 1
+ PAREN_COST = 1
+
+ def __init__(self, variables_and_values):
+ assert variables_and_values
+ for k, vs in variables_and_values:
+ assert re.match(r'\w+\Z', k)
+ assert vs
+ assert (all(isinstance(v, int) for v in vs) or
+ all(re.match(r'\w+\Z', v) for v in vs))
+
+ variables, values = zip(*((k, sorted(v)) for k, v in variables_and_values))
+ valuecounts = map(len, values)
+ base_tests_by_cost = {}
+
+ # Loop over nonempty subsets of values of each variable. This is about 2^n
+ # cases where n is the total number of values (currently 2+3=5 in Chrome).
+ for subsets in itertools.product(*(range(1, 1 << n) for n in valuecounts)):
+ # Supposing values == [['a', 'b', 'c'], [1, 2]], there are six
+ # configurations: ('a', 1), ('a', 2), ('b', 1), etc. Each gets a bit, in
+ # that order starting from the LSB. Start with the equivalent of
+ # set([('a', 1)]) and massage that into the correct set of configs.
+ bits = 1
+ shift = 1
+ cost = 0
+ for subset, valuecount in zip(subsets, valuecounts):
+ oldbits, bits = bits, 0
+ while subset:
+ if subset & 1:
+ bits |= oldbits
+ cost += self.COMPARISON_COST
+ oldbits <<= shift
+ subset >>= 1
+ shift *= valuecount
+ # Charge an extra set of parens for the whole expression,
+ # which is removed later if appropriate.
+ cost += self.PAREN_COST * (1 + sum(bool(n & (n-1)) for n in subsets))
+ base_tests_by_cost.setdefault(cost, {})[bits] = subsets
+
+ self.variables = variables
+ self.values = values
+ self.base_tests_by_cost = base_tests_by_cost
+
+ def get_expr(self, configs):
+ assert configs
+ for config in configs:
+ assert len(config) == len(self.values)
+ assert all(val in vals for val, vals in zip(config, self.values))
+ return self._format_expr(self._get_expr_internal(configs))
+
+ def _get_expr_internal(self, configs):
+ bits = 0
+ for config in configs:
+ bit = 1
+ n = 1
+ for value, values in zip(config, self.values):
+ bit <<= (n * values.index(value))
+ n *= len(values)
+ bits |= bit
+ notbits = ~bits
+
+ def try_partitions(parts, bits):
+ for cost, subparts in parts:
+ if cost is None:
+ return None if bits else ()
+ try:
+ tests = self.base_tests_by_cost[cost]
+ except KeyError:
+ continue
+ for test in tests:
+ if (test & bits) and not (test & notbits):
+ result = try_partitions(subparts, bits & ~test)
+ if result is not None:
+ return (tests[test],) + result
+ return None
+
+ for total_cost in itertools.count(0):
+ try:
+ return (self.base_tests_by_cost[total_cost + self.PAREN_COST][bits],)
+ except KeyError:
+ result = try_partitions(tuple(partitions(total_cost, self.PAREN_COST)),
+ bits)
+ if result is not None:
+ return result
+
+ def _format_expr(self, expr):
+ out = []
+ for expr2 in expr:
+ out2 = []
+ for name, values, expr3 in zip(self.variables, self.values, expr2):
+ out3 = []
+ for value in values:
+ if expr3 & 1:
+ if isinstance(value, basestring):
+ value = '"%s"' % value
+ out3.append('%s==%s' % (name, value))
+ expr3 >>= 1
+ out2.append(' or '.join(out3))
+ if len(out3) > 1 and len(expr2) > 1:
+ out2[-1] = '(%s)' % out2[-1]
+ out.append(' and '.join(out2))
+ if len(out2) > 1 and len(expr) > 1:
+ out[-1] = '(%s)' % out[-1]
+ return ' or '.join(out)
+
+
+def partitions(n, minimum):
+ """Yields all the ways of expressing n as a sum of integers >= minimum,
+ in a slightly odd tree format. Most of the tree is left unevaluated.
+ Example:
+ partitions(4, 1) ==>
+ [1, <[1, <[1, <[1, <end>]>],
+ [2, <end>]>],
+ [3, <end>]>],
+ [2, <[2, <end>]>],
+ [4, <end>]
+ where <...> is a lazily-evaluated list and end == [None, None].
+ """
+ if n == 0:
+ yield (None, None)
+ for k in range(n, minimum - 1, -1):
+ children = partitions(n - k, k)
+ # We could just yield [k, children] here, but that would create a lot of
+ # blind alleys with no actual partitions.
+ try:
+ yield [k, MemoizedIterable(itertools.chain([next(children)], children))]
+ except StopIteration:
+ pass
+
+
+class MemoizedIterable(object):
+ """Wrapper for an iterable that fully evaluates and caches the values the
+ first time it is iterated over.
+ """
+ def __init__(self, iterable):
+ self.iterable = iterable
+ def __iter__(self):
+ self.iterable = tuple(self.iterable)
+ return iter(self.iterable)
diff --git a/chromium/tools/swarm_client/swarm_get_results.py b/chromium/tools/swarm_client/swarm_get_results.py
new file mode 100755
index 00000000000..1586a4f5b31
--- /dev/null
+++ b/chromium/tools/swarm_client/swarm_get_results.py
@@ -0,0 +1,210 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Retrieves all the output that the Swarm server has produced for requests with
+that name.
+"""
+
+import json
+import logging
+import optparse
+import sys
+import threading
+import time
+import urllib
+
+#from common import find_depot_tools # pylint: disable=W0611
+#
+## From the depot tools
+#import fix_encoding
+
+import run_isolated
+
+
+# The default time to wait for a shard to finish running.
+DEFAULT_SHARD_WAIT_TIME = 40 * 60.
+
+
+class Failure(Exception):
+ """Generic failure."""
+ pass
+
+
+def get_test_keys(swarm_base_url, test_name, _=None):
+ """Returns the Swarm test key for each shards of test_name."""
+ # TODO(maruel): Remove the parameter '_' once the
+ # build/scripts/slave/get_swarm_results.py stops passing it.
+ key_data = urllib.urlencode([('name', test_name)])
+ url = '%s/get_matching_test_cases?%s' % (swarm_base_url, key_data)
+
+ for i in range(run_isolated.URL_OPEN_MAX_ATTEMPTS):
+ response = run_isolated.url_open(url, retry_404=True)
+ if response is None:
+ raise Failure(
+ 'Error: Unable to find any tests with the name, %s, on swarm server'
+ % test_name)
+
+ result = response.read()
+ # TODO(maruel): Compare exact string.
+ if 'No matching' in result:
+ logging.warning('Unable to find any tests with the name, %s, on swarm '
+ 'server' % test_name)
+ if i != run_isolated.URL_OPEN_MAX_ATTEMPTS:
+ run_isolated.HttpService.sleep_before_retry(i, None)
+ continue
+ return json.loads(result)
+
+ raise Failure(
+ 'Error: Unable to find any tests with the name, %s, on swarm server'
+ % test_name)
+
+
+class Bit(object):
+ """Thread safe setable bit."""
+ _lock = threading.Lock()
+ _value = False
+
+ def get(self):
+ with self._lock:
+ return self._value
+
+ def set(self):
+ with self._lock:
+ self._value = True
+
+
+def now():
+ """Exists so it can be mocked easily."""
+ return time.time()
+
+
+def retrieve_results(base_url, test_key, timeout, should_stop):
+ """Retrieves results for a single test_key."""
+ assert isinstance(timeout, float)
+ params = [('r', test_key)]
+ result_url = '%s/get_result?%s' % (base_url, urllib.urlencode(params))
+ start = now()
+ while True:
+ if timeout and (now() - start) >= timeout:
+ logging.error('retrieve_results(%s) timed out', base_url)
+ return {}
+ # Do retries ourselves.
+ response = run_isolated.url_open(
+ result_url, retry_404=False, retry_50x=False)
+ if response is None:
+ # Aggressively poll for results. Do not use retry_404 so
+ # should_stop is polled more often.
+ remaining = min(5, timeout - (now() - start)) if timeout else 5
+ if remaining > 0:
+ run_isolated.HttpService.sleep_before_retry(1, remaining)
+ else:
+ try:
+ data = json.load(response) or {}
+ except (ValueError, TypeError):
+ logging.warning(
+ 'Received corrupted data for test_key %s. Retrying.', test_key)
+ else:
+ if data['output']:
+ return data
+ if should_stop.get():
+ return {}
+
+
+def yield_results(swarm_base_url, test_keys, timeout, max_threads):
+ """Yields swarm test results from the swarm server as (index, result).
+
+ Duplicate shards are ignored, the first one to complete is returned.
+
+ max_threads is optional and is used to limit the number of parallel fetches
+ done. Since in general the number of test_keys is in the range <=10, it's not
+ worth normally to limit the number threads. Mostly used for testing purposes.
+ """
+ shards_remaining = range(len(test_keys))
+ number_threads = (
+ min(max_threads, len(test_keys)) if max_threads else len(test_keys))
+ should_stop = Bit()
+ results_remaining = len(test_keys)
+ with run_isolated.ThreadPool(number_threads, number_threads, 0) as pool:
+ try:
+ for test_key in test_keys:
+ pool.add_task(
+ 0, retrieve_results, swarm_base_url, test_key, timeout, should_stop)
+ while shards_remaining and results_remaining:
+ result = pool.get_one_result()
+ results_remaining -= 1
+ if not result:
+ # Failed to retrieve one key.
+ logging.error('Failed to retrieve the results for a swarm key')
+ continue
+ shard_index = result['config_instance_index']
+ if shard_index in shards_remaining:
+ shards_remaining.remove(shard_index)
+ yield shard_index, result
+ else:
+ logging.warning('Ignoring duplicate shard index %d', shard_index)
+ # Pop the last entry, there's no such shard.
+ shards_remaining.pop()
+ finally:
+ # Done, kill the remaining threads.
+ should_stop.set()
+
+
+def parse_args():
+ run_isolated.disable_buffering()
+ parser = optparse.OptionParser(
+ usage='%prog [options] test_name',
+ description=sys.modules[__name__].__doc__)
+ parser.add_option(
+ '-u', '--url', default='http://localhost:8080',
+ help='Specify the url of the Swarm server, defaults: %default')
+ parser.add_option(
+ '-v', '--verbose', action='store_true',
+ help='Print verbose logging')
+ parser.add_option(
+ '-t', '--timeout',
+ type='float',
+ default=DEFAULT_SHARD_WAIT_TIME,
+ help='Timeout to wait for result, set to 0 for no timeout; default: '
+ '%default s')
+ # TODO(maruel): Remove once the masters have been updated.
+ parser.add_option(
+ '-s', '--shards',
+ help=optparse.SUPPRESS_HELP)
+
+ (options, args) = parser.parse_args()
+ if not args:
+ parser.error('Must specify one test name.')
+ elif len(args) > 1:
+ parser.error('Must specify only one test name.')
+ options.url = options.url.rstrip('/')
+ logging.basicConfig(level=logging.DEBUG if options.verbose else logging.ERROR)
+ return parser, options, args[0]
+
+
+def main():
+ parser, options, test_name = parse_args()
+ try:
+ test_keys = get_test_keys(options.url, test_name)
+ except Failure as e:
+ parser.error(e.args[0])
+ if not test_keys:
+ parser.error('No test keys to get results with.')
+
+ options.shards = len(test_keys) if options.shards == -1 else options.shards
+ exit_code = None
+ for _index, output in yield_results(
+ options.url, test_keys, options.timeout, None):
+ print(
+ '%s/%s: %s' % (
+ output['machine_id'], output['machine_tag'], output['exit_codes']))
+ print(''.join(' %s\n' % l for l in output['output'].splitlines()))
+ exit_code = max(exit_code, max(map(int, output['exit_codes'].split(','))))
+
+ return exit_code
+
+
+if __name__ == '__main__':
+ #fix_encoding.fix_encoding()
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/swarm_trigger_and_get_results.py b/chromium/tools/swarm_client/swarm_trigger_and_get_results.py
new file mode 100755
index 00000000000..b2b9cb55f2b
--- /dev/null
+++ b/chromium/tools/swarm_client/swarm_trigger_and_get_results.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Archives a .isolated file, triggers it on Swarm and get the results."""
+
+import datetime
+import getpass
+import hashlib
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+import run_isolated
+
+
+ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+# Default servers.
+ISOLATE_SERVER = 'https://isolateserver-dev.appspot.com/'
+SWARM_SERVER = 'https://chromium-swarm-dev.appspot.com'
+
+
+def run(cmd, verbose):
+ if verbose:
+ print('Running: %s' % ' '.join(cmd))
+ cmd = [sys.executable, os.path.join(ROOT_DIR, cmd[0])] + cmd[1:]
+ if verbose and sys.platform != 'win32':
+ cmd = ['time', '-p'] + cmd
+ subprocess.check_call(cmd)
+
+
+def doall(isolate, isolated, swarm_server, cad_server, slave_os, verbose):
+ """Does the archive, trigger and get results dance."""
+ prefix = getpass.getuser() + '-' + datetime.datetime.now().isoformat() + '-'
+ shards = 1
+
+ if verbose:
+ os.environ.setdefault('ISOLATE_DEBUG', '2')
+
+ tempdir = None
+ try:
+ if not isolated:
+ # A directory is used because isolated + '.state' will also be created.
+ tempdir = tempfile.mkdtemp(prefix='swarm_trigger_and_get_results')
+ isolated = os.path.join(tempdir, 'swarm_trigger.isolated')
+ step_name = os.path.basename(isolate).split('.', 1)[0]
+ else:
+ step_name = os.path.basename(isolated).split('.', 1)[0]
+
+ print('Archiving')
+ cmd = [
+ 'isolate.py',
+ 'hashtable',
+ '--outdir', cad_server,
+ '--isolated', isolated,
+ ]
+ if isolate:
+ cmd.extend(('--isolate', isolate))
+ if slave_os:
+ cmd.extend(('-V', 'OS', run_isolated.FLAVOR_MAPPING[slave_os]))
+ run(cmd, verbose)
+
+ print('\nRunning')
+ hashval = hashlib.sha1(open(isolated, 'rb').read()).hexdigest()
+ cmd = [
+ 'swarm_trigger_step.py',
+ '--swarm-url', swarm_server,
+ '--test-name-prefix', prefix,
+ '--data-server', cad_server,
+ '--run_from_hash',
+ hashval,
+ step_name,
+ str(shards),
+ '',
+ ]
+ if slave_os:
+ cmd.extend(('--os_image', slave_os))
+ run(cmd, verbose)
+
+ print('\nGetting results')
+ run(
+ [
+ 'swarm_get_results.py',
+ '--url', swarm_server,
+ prefix + step_name,
+ ],
+ verbose)
+ return 0
+ finally:
+ if tempdir:
+ shutil.rmtree(tempdir)
+
+
+def main():
+ run_isolated.disable_buffering()
+ parser = optparse.OptionParser(
+ usage='%prog <options>',
+ description=sys.modules[__name__].__doc__)
+ parser.add_option('-i', '--isolate', help='.isolate file to use')
+ parser.add_option(
+ '-s', '--isolated',
+ help='.isolated file to use. One of -i or -s must be used.')
+ parser.add_option(
+ '-o', '--os_image',
+ metavar='OS',
+ help='Swarm OS image to request. Should be one of the valid sys.platform '
+ 'values like darwin, linux2 or win32.')
+ parser.add_option(
+ '-u', '--swarm-url',
+ metavar='URL',
+ default=SWARM_SERVER,
+ help='Specify the url of the Swarm server. Defaults to %default')
+ parser.add_option(
+ '-d', '--data-server',
+ default=ISOLATE_SERVER,
+ metavar='URL',
+ help='The server where all the test data is stored. Defaults to %default')
+ parser.add_option('-v', '--verbose', action='store_true')
+ options, args = parser.parse_args()
+
+ if args:
+ parser.error('Use one of -i or -s but no unsupported arguments: %s' % args)
+ if not options.isolate and not options.isolated:
+ parser.error('Use one of -i or -s')
+
+ return doall(
+ options.isolate,
+ options.isolated,
+ options.swarm_url,
+ options.data_server,
+ options.os_image,
+ options.verbose)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/swarm_trigger_step.py b/chromium/tools/swarm_client/swarm_trigger_step.py
new file mode 100755
index 00000000000..3cc0fa4f3e9
--- /dev/null
+++ b/chromium/tools/swarm_client/swarm_trigger_step.py
@@ -0,0 +1,317 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Triggers a Swarm request based off of a .isolated file.
+
+This script takes a .isolated file, packages it, and sends a Swarm manifest file
+to the Swarm server. This is expected to be called as a build step with the cwd
+as the parent of the src/ directory.
+"""
+
+import hashlib
+import json
+import optparse
+import os
+import StringIO
+import sys
+import time
+import urllib
+import zipfile
+
+import run_isolated
+
+
+ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
+TOOLS_PATH = os.path.join(ROOT_DIR, 'tools')
+
+
+PLATFORM_MAPPING = {
+ 'cygwin': 'Windows',
+ 'darwin': 'Mac',
+ 'linux2': 'Linux',
+ 'win32': 'Windows',
+}
+
+
+class Failure(Exception):
+ pass
+
+
+class Manifest(object):
+ def __init__(
+ self, manifest_hash, test_name, shards, test_filter, os_image,
+ working_dir, data_server, verbose, profile):
+ """Populates a manifest object.
+ Args:
+ manifest_hash - The manifest's sha-1 that the slave is going to fetch.
+ test_name - The name to give the test request.
+ shards - The number of swarm shards to request.
+ test_filter - The gtest filter to apply when running the test.
+ os_image - OS to run on.
+ working_dir - Relative working directory to start the script.
+ data_server - isolate server url.
+ verbose - if True, have the slave print more details.
+ profile - if True, have the slave print more timing data.
+ """
+ self.manifest_hash = manifest_hash
+ self._test_name = test_name
+ self._shards = shards
+ self._test_filter = test_filter
+ self._target_platform = PLATFORM_MAPPING[os_image]
+ self._working_dir = working_dir
+
+ base_url = data_server.rstrip('/')
+ self.data_server_retrieval = base_url + '/content/retrieve/default/'
+ self._data_server_storage = base_url + '/content/store/default/'
+ self._data_server_has = base_url + '/content/contains/default'
+ self._data_server_get_token = base_url + '/content/get_token'
+
+ self.verbose = bool(verbose)
+ self.profile = bool(profile)
+
+ self._zip_file_hash = ''
+ self._tasks = []
+ self._files = {}
+ self._token_cache = None
+
+ def _token(self):
+ if not self._token_cache:
+ result = run_isolated.url_open(self._data_server_get_token)
+ if not result:
+ # TODO(maruel): Implement authentication.
+ raise Failure('Failed to get token, need authentication')
+ # Quote it right away, so creating the urls is simpler.
+ self._token_cache = urllib.quote(result.read())
+ return self._token_cache
+
+ def add_task(self, task_name, actions, time_out=600):
+ """Appends a new task to the swarm manifest file."""
+ # See swarming/src/common/test_request_message.py TestObject constructor for
+ # the valid flags.
+ self._tasks.append(
+ {
+ 'action': actions,
+ 'decorate_output': self.verbose,
+ 'test_name': task_name,
+ 'time_out': time_out,
+ })
+
+ def add_file(self, source_path, rel_path):
+ self._files[source_path] = rel_path
+
+ def zip_and_upload(self):
+ """Zips up all the files necessary to run a shard and uploads to Swarming
+ master.
+ """
+ assert not self._zip_file_hash
+ start_time = time.time()
+
+ zip_memory_file = StringIO.StringIO()
+ zip_file = zipfile.ZipFile(zip_memory_file, 'w')
+
+ for source, relpath in self._files.iteritems():
+ zip_file.write(source, relpath)
+
+ zip_file.close()
+ print 'Zipping completed, time elapsed: %f' % (time.time() - start_time)
+
+ zip_memory_file.flush()
+ zip_contents = zip_memory_file.getvalue()
+ zip_memory_file.close()
+
+ self._zip_file_hash = hashlib.sha1(zip_contents).hexdigest()
+
+ response = run_isolated.url_open(
+ self._data_server_has + '?token=%s' % self._token(),
+ data=self._zip_file_hash,
+ content_type='application/octet-stream')
+ if response is None:
+ print >> sys.stderr, (
+ 'Unable to query server for zip file presence, aborting.')
+ return False
+
+ if response.read(1) == chr(1):
+ print 'Zip file already on server, no need to reupload.'
+ return True
+
+ print 'Zip file not on server, starting uploading.'
+
+ url = '%s%s?priority=0&token=%s' % (
+ self._data_server_storage, self._zip_file_hash, self._token())
+ response = run_isolated.url_open(
+ url, data=zip_contents, content_type='application/octet-stream')
+ if response is None:
+ print >> sys.stderr, 'Failed to upload the zip file: %s' % url
+ return False
+
+ return True
+
+ def to_json(self):
+ """Exports the current configuration into a swarm-readable manifest file.
+
+ This function doesn't mutate the object.
+ """
+ test_case = {
+ 'test_case_name': self._test_name,
+ 'data': [
+ [self.data_server_retrieval + urllib.quote(self._zip_file_hash),
+ 'swarm_data.zip'],
+ ],
+ 'tests': self._tasks,
+ 'env_vars': {},
+ 'configurations': [
+ {
+ 'min_instances': self._shards,
+ 'config_name': self._target_platform,
+ 'dimensions': {
+ 'os': self._target_platform,
+ },
+ },
+ ],
+ 'working_dir': self._working_dir,
+ 'restart_on_failure': True,
+ 'cleanup': 'root',
+ }
+
+ # These flags are googletest specific.
+ if self._test_filter and self._test_filter != '*':
+ test_case['env_vars']['GTEST_FILTER'] = self._test_filter
+ if self._shards > 1:
+ test_case['env_vars']['GTEST_SHARD_INDEX'] = '%(instance_index)s'
+ test_case['env_vars']['GTEST_TOTAL_SHARDS'] = '%(num_instances)s'
+
+ return json.dumps(test_case, separators=(',',':'))
+
+
+def chromium_setup(manifest):
+ """Sets up the commands to run.
+
+ Highly chromium specific.
+ """
+ cleanup_script_name = 'swarm_cleanup.py'
+ cleanup_script_path = os.path.join(TOOLS_PATH, cleanup_script_name)
+ run_test_name = 'run_isolated.py'
+ run_test_path = os.path.join(ROOT_DIR, run_test_name)
+
+ manifest.add_file(run_test_path, run_test_name)
+ manifest.add_file(cleanup_script_path, cleanup_script_name)
+ run_cmd = [
+ 'python', run_test_name,
+ '--hash', manifest.manifest_hash,
+ '--remote', manifest.data_server_retrieval.rstrip('/') + '-gzip/',
+ ]
+ if manifest.verbose or manifest.profile:
+ # Have it print the profiling section.
+ run_cmd.append('--verbose')
+ manifest.add_task('Run Test', run_cmd)
+
+ # Clean up
+ manifest.add_task('Clean Up', ['python', cleanup_script_name])
+
+
+def process_manifest(
+ file_sha1, test_name, shards, test_filter, os_image, working_dir,
+ data_server, swarm_url, verbose, profile):
+ """Process the manifest file and send off the swarm test request."""
+ try:
+ manifest = Manifest(
+ file_sha1, test_name, shards, test_filter, os_image, working_dir,
+ data_server, verbose, profile)
+ except ValueError as e:
+ print >> sys.stderr, 'Unable to process %s: %s' % (test_name, e)
+ return 1
+
+ chromium_setup(manifest)
+
+ # Zip up relevent files
+ print "Zipping up files..."
+ if not manifest.zip_and_upload():
+ return 1
+
+ # Send test requests off to swarm.
+ print('Sending test requests to swarm.')
+ print('Server: %s' % swarm_url)
+ print('Job name: %s' % test_name)
+ test_url = swarm_url.rstrip('/') + '/test'
+ manifest_text = manifest.to_json()
+ result = run_isolated.url_open(test_url, data={'request': manifest_text})
+ if not result:
+ print >> sys.stderr, 'Failed to send test for %s\n%s' % (
+ test_name, test_url)
+ return 1
+ try:
+ json.load(result)
+ except (ValueError, TypeError) as e:
+ print >> sys.stderr, 'Failed to send test for %s' % test_name
+ print >> sys.stderr, 'Manifest: %s' % manifest_text
+ print >> sys.stderr, str(e)
+ return 1
+ return 0
+
+
+def main(argv):
+ run_isolated.disable_buffering()
+ parser = optparse.OptionParser(
+ usage='%prog [options]', description=sys.modules[__name__].__doc__)
+ parser.add_option('-w', '--working_dir', default='swarm_tests',
+ help='Desired working direction on the swarm slave side. '
+ 'Defaults to %default.')
+ parser.add_option('-o', '--os_image',
+ help='Swarm OS image to request.')
+ parser.add_option('-u', '--swarm-url', default='http://localhost:8080',
+ help='Specify the url of the Swarm server. '
+ 'Defaults to %default')
+ parser.add_option('-d', '--data-server',
+ help='The server where all the test data is stored.')
+ parser.add_option('-t', '--test-name-prefix', default='',
+ help='Specify the prefix to give the swarm test request. '
+ 'Defaults to %default')
+ parser.add_option('--run_from_hash', nargs=4, action='append', default=[],
+ help='Specify a hash to run on swarm. The format is '
+ '(hash, hash_test_name, shards, test_filter). This may be '
+ 'used multiple times to send multiple hashes.')
+ parser.add_option('-v', '--verbose', action='store_true',
+ help='Print verbose logging')
+ parser.add_option('--profile', action='store_true',
+ default=bool(os.environ.get('ISOLATE_DEBUG')),
+ help='Have run_isolated.py print profiling info')
+ (options, args) = parser.parse_args(argv)
+
+ if args:
+ parser.error('Unknown args: %s' % args)
+
+ if not options.os_image or options.os_image == 'None':
+ # This means the Try Server/user wants to use the current OS.
+ options.os_image = sys.platform
+ if not options.data_server:
+ parser.error('Must specify the data directory')
+
+ if not options.run_from_hash:
+ parser.error('At least one --run_from_hash is required.')
+
+ highest_exit_code = 0
+ try:
+ # Send off the hash swarm test requests.
+ for (file_sha1, test_name, shards, testfilter) in options.run_from_hash:
+ exit_code = process_manifest(
+ file_sha1,
+ options.test_name_prefix + test_name,
+ int(shards),
+ testfilter,
+ options.os_image,
+ options.working_dir,
+ options.data_server,
+ options.swarm_url,
+ options.verbose,
+ options.profile)
+ highest_exit_code = max(highest_exit_code, exit_code)
+ except Failure as e:
+ print >> sys.stderr, e.args[0]
+ highest_exit_code = max(1, highest_exit_code)
+ return highest_exit_code
+
+
+if __name__ == '__main__':
+ sys.exit(main(None))
diff --git a/chromium/tools/swarm_client/third_party/README.chromium b/chromium/tools/swarm_client/third_party/README.chromium
new file mode 100644
index 00000000000..ea891126fb8
--- /dev/null
+++ b/chromium/tools/swarm_client/third_party/README.chromium
@@ -0,0 +1,11 @@
+Name: Rietveld's upload.py
+Short Name: rietveld
+URL: https://code.google.com/p/rietveld
+Revision: 4b839e2a9f91
+License: Apache 2.0
+
+Description:
+Used for authentication only until we get OAuth2 sorted out and self-packaged.
+
+Local Modifications:
+None.
diff --git a/chromium/tools/swarm_client/third_party/__init__.py b/chromium/tools/swarm_client/third_party/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/swarm_client/third_party/__init__.py
diff --git a/chromium/tools/swarm_client/third_party/upload.py b/chromium/tools/swarm_client/third_party/upload.py
new file mode 100755
index 00000000000..c88c1ea560c
--- /dev/null
+++ b/chromium/tools/swarm_client/third_party/upload.py
@@ -0,0 +1,2394 @@
+#!/usr/bin/env python
+# coding: utf-8
+#
+# Copyright 2007 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Tool for uploading diffs from a version control system to the codereview app.
+
+Usage summary: upload.py [options] [-- diff_options] [path...]
+
+Diff options are passed to the diff command of the underlying system.
+
+Supported version control systems:
+ Git
+ Mercurial
+ Subversion
+ Perforce
+ CVS
+
+It is important for Git/Mercurial users to specify a tree/node/branch to diff
+against by using the '--rev' option.
+"""
+# This code is derived from appcfg.py in the App Engine SDK (open source),
+# and from ASPN recipe #146306.
+
+import ConfigParser
+import cookielib
+import errno
+import fnmatch
+import getpass
+import logging
+import marshal
+import mimetypes
+import optparse
+import os
+import re
+import socket
+import subprocess
+import sys
+import urllib
+import urllib2
+import urlparse
+
+# The md5 module was deprecated in Python 2.5.
+try:
+ from hashlib import md5
+except ImportError:
+ from md5 import md5
+
+try:
+ import readline
+except ImportError:
+ pass
+
+try:
+ import keyring
+except ImportError:
+ keyring = None
+
+# The logging verbosity:
+# 0: Errors only.
+# 1: Status messages.
+# 2: Info logs.
+# 3: Debug logs.
+verbosity = 1
+
+# The account type used for authentication.
+# This line could be changed by the review server (see handler for
+# upload.py).
+AUTH_ACCOUNT_TYPE = "GOOGLE"
+
+# URL of the default review server. As for AUTH_ACCOUNT_TYPE, this line could be
+# changed by the review server (see handler for upload.py).
+DEFAULT_REVIEW_SERVER = "codereview.appspot.com"
+
+# Max size of patch or base file.
+MAX_UPLOAD_SIZE = 900 * 1024
+
+# Constants for version control names. Used by GuessVCSName.
+VCS_GIT = "Git"
+VCS_MERCURIAL = "Mercurial"
+VCS_SUBVERSION = "Subversion"
+VCS_PERFORCE = "Perforce"
+VCS_CVS = "CVS"
+VCS_UNKNOWN = "Unknown"
+
+VCS_ABBREVIATIONS = {
+ VCS_MERCURIAL.lower(): VCS_MERCURIAL,
+ "hg": VCS_MERCURIAL,
+ VCS_SUBVERSION.lower(): VCS_SUBVERSION,
+ "svn": VCS_SUBVERSION,
+ VCS_PERFORCE.lower(): VCS_PERFORCE,
+ "p4": VCS_PERFORCE,
+ VCS_GIT.lower(): VCS_GIT,
+ VCS_CVS.lower(): VCS_CVS,
+}
+
+# The result of parsing Subversion's [auto-props] setting.
+svn_auto_props_map = None
+
+def GetEmail(prompt):
+ """Prompts the user for their email address and returns it.
+
+ The last used email address is saved to a file and offered up as a suggestion
+ to the user. If the user presses enter without typing in anything the last
+ used email address is used. If the user enters a new address, it is saved
+ for next time we prompt.
+
+ """
+ last_email_file_name = os.path.expanduser("~/.last_codereview_email_address")
+ last_email = ""
+ if os.path.exists(last_email_file_name):
+ try:
+ last_email_file = open(last_email_file_name, "r")
+ last_email = last_email_file.readline().strip("\n")
+ last_email_file.close()
+ prompt += " [%s]" % last_email
+ except IOError, e:
+ pass
+ email = raw_input(prompt + ": ").strip()
+ if email:
+ try:
+ last_email_file = open(last_email_file_name, "w")
+ last_email_file.write(email)
+ last_email_file.close()
+ except IOError, e:
+ pass
+ else:
+ email = last_email
+ return email
+
+
+def StatusUpdate(msg):
+ """Print a status message to stdout.
+
+ If 'verbosity' is greater than 0, print the message.
+
+ Args:
+ msg: The string to print.
+ """
+ if verbosity > 0:
+ print msg
+
+
+def ErrorExit(msg):
+ """Print an error message to stderr and exit."""
+ print >>sys.stderr, msg
+ sys.exit(1)
+
+
+class ClientLoginError(urllib2.HTTPError):
+ """Raised to indicate there was an error authenticating with ClientLogin."""
+
+ def __init__(self, url, code, msg, headers, args):
+ urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
+ self.args = args
+ self._reason = args["Error"]
+ self.info = args.get("Info", None)
+
+ @property
+ def reason(self):
+ # reason is a property on python 2.7 but a member variable on <=2.6.
+ # self.args is modified so it cannot be used as-is so save the value in
+ # self._reason.
+ return self._reason
+
+
+class AbstractRpcServer(object):
+ """Provides a common interface for a simple RPC server."""
+
+ def __init__(self, host, auth_function, host_override=None, extra_headers={},
+ save_cookies=False, account_type=AUTH_ACCOUNT_TYPE):
+ """Creates a new AbstractRpcServer.
+
+ Args:
+ host: The host to send requests to.
+ auth_function: A function that takes no arguments and returns an
+ (email, password) tuple when called. Will be called if authentication
+ is required.
+ host_override: The host header to send to the server (defaults to host).
+ extra_headers: A dict of extra headers to append to every request.
+ save_cookies: If True, save the authentication cookies to local disk.
+ If False, use an in-memory cookiejar instead. Subclasses must
+ implement this functionality. Defaults to False.
+ account_type: Account type used for authentication. Defaults to
+ AUTH_ACCOUNT_TYPE.
+ """
+ self.host = host
+ if (not self.host.startswith("http://") and
+ not self.host.startswith("https://")):
+ self.host = "http://" + self.host
+ self.host_override = host_override
+ self.auth_function = auth_function
+ self.authenticated = False
+ self.extra_headers = extra_headers
+ self.save_cookies = save_cookies
+ self.account_type = account_type
+ self.opener = self._GetOpener()
+ if self.host_override:
+ logging.info("Server: %s; Host: %s", self.host, self.host_override)
+ else:
+ logging.info("Server: %s", self.host)
+
+ def _GetOpener(self):
+ """Returns an OpenerDirector for making HTTP requests.
+
+ Returns:
+ A urllib2.OpenerDirector object.
+ """
+ raise NotImplementedError()
+
+ def _CreateRequest(self, url, data=None):
+ """Creates a new urllib request."""
+ logging.debug("Creating request for: '%s' with payload:\n%s", url, data)
+ req = urllib2.Request(url, data=data, headers={"Accept": "text/plain"})
+ if self.host_override:
+ req.add_header("Host", self.host_override)
+ for key, value in self.extra_headers.iteritems():
+ req.add_header(key, value)
+ return req
+
+ def _GetAuthToken(self, email, password):
+ """Uses ClientLogin to authenticate the user, returning an auth token.
+
+ Args:
+ email: The user's email address
+ password: The user's password
+
+ Raises:
+ ClientLoginError: If there was an error authenticating with ClientLogin.
+ HTTPError: If there was some other form of HTTP error.
+
+ Returns:
+ The authentication token returned by ClientLogin.
+ """
+ account_type = self.account_type
+ if self.host.endswith(".google.com"):
+ # Needed for use inside Google.
+ account_type = "HOSTED"
+ req = self._CreateRequest(
+ url="https://www.google.com/accounts/ClientLogin",
+ data=urllib.urlencode({
+ "Email": email,
+ "Passwd": password,
+ "service": "ah",
+ "source": "rietveld-codereview-upload",
+ "accountType": account_type,
+ }),
+ )
+ try:
+ response = self.opener.open(req)
+ response_body = response.read()
+ response_dict = dict(x.split("=")
+ for x in response_body.split("\n") if x)
+ return response_dict["Auth"]
+ except urllib2.HTTPError, e:
+ if e.code == 403:
+ body = e.read()
+ response_dict = dict(x.split("=", 1) for x in body.split("\n") if x)
+ raise ClientLoginError(req.get_full_url(), e.code, e.msg,
+ e.headers, response_dict)
+ else:
+ raise
+
+ def _GetAuthCookie(self, auth_token):
+ """Fetches authentication cookies for an authentication token.
+
+ Args:
+ auth_token: The authentication token returned by ClientLogin.
+
+ Raises:
+ HTTPError: If there was an error fetching the authentication cookies.
+ """
+ # This is a dummy value to allow us to identify when we're successful.
+ continue_location = "http://localhost/"
+ args = {"continue": continue_location, "auth": auth_token}
+ req = self._CreateRequest("%s/_ah/login?%s" %
+ (self.host, urllib.urlencode(args)))
+ try:
+ response = self.opener.open(req)
+ except urllib2.HTTPError, e:
+ response = e
+ if (response.code != 302 or
+ response.info()["location"] != continue_location):
+ raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg,
+ response.headers, response.fp)
+ self.authenticated = True
+
+ def _Authenticate(self):
+ """Authenticates the user.
+
+ The authentication process works as follows:
+ 1) We get a username and password from the user
+ 2) We use ClientLogin to obtain an AUTH token for the user
+ (see http://code.google.com/apis/accounts/AuthForInstalledApps.html).
+ 3) We pass the auth token to /_ah/login on the server to obtain an
+ authentication cookie. If login was successful, it tries to redirect
+ us to the URL we provided.
+
+ If we attempt to access the upload API without first obtaining an
+ authentication cookie, it returns a 401 response (or a 302) and
+ directs us to authenticate ourselves with ClientLogin.
+ """
+ for i in range(3):
+ credentials = self.auth_function()
+ try:
+ auth_token = self._GetAuthToken(credentials[0], credentials[1])
+ except ClientLoginError, e:
+ print >>sys.stderr, ''
+ if e.reason == "BadAuthentication":
+ if e.info == "InvalidSecondFactor":
+ print >>sys.stderr, (
+ "Use an application-specific password instead "
+ "of your regular account password.\n"
+ "See http://www.google.com/"
+ "support/accounts/bin/answer.py?answer=185833")
+ else:
+ print >>sys.stderr, "Invalid username or password."
+ elif e.reason == "CaptchaRequired":
+ print >>sys.stderr, (
+ "Please go to\n"
+ "https://www.google.com/accounts/DisplayUnlockCaptcha\n"
+ "and verify you are a human. Then try again.\n"
+ "If you are using a Google Apps account the URL is:\n"
+ "https://www.google.com/a/yourdomain.com/UnlockCaptcha")
+ elif e.reason == "NotVerified":
+ print >>sys.stderr, "Account not verified."
+ elif e.reason == "TermsNotAgreed":
+ print >>sys.stderr, "User has not agreed to TOS."
+ elif e.reason == "AccountDeleted":
+ print >>sys.stderr, "The user account has been deleted."
+ elif e.reason == "AccountDisabled":
+ print >>sys.stderr, "The user account has been disabled."
+ break
+ elif e.reason == "ServiceDisabled":
+ print >>sys.stderr, ("The user's access to the service has been "
+ "disabled.")
+ elif e.reason == "ServiceUnavailable":
+ print >>sys.stderr, "The service is not available; try again later."
+ else:
+ # Unknown error.
+ raise
+ print >>sys.stderr, ''
+ continue
+ self._GetAuthCookie(auth_token)
+ return
+
+ def Send(self, request_path, payload=None,
+ content_type="application/octet-stream",
+ timeout=None,
+ extra_headers=None,
+ **kwargs):
+ """Sends an RPC and returns the response.
+
+ Args:
+ request_path: The path to send the request to, eg /api/appversion/create.
+ payload: The body of the request, or None to send an empty request.
+ content_type: The Content-Type header to use.
+ timeout: timeout in seconds; default None i.e. no timeout.
+ (Note: for large requests on OS X, the timeout doesn't work right.)
+ extra_headers: Dict containing additional HTTP headers that should be
+ included in the request (string header names mapped to their values),
+ or None to not include any additional headers.
+ kwargs: Any keyword arguments are converted into query string parameters.
+
+ Returns:
+ The response body, as a string.
+ """
+ # TODO: Don't require authentication. Let the server say
+ # whether it is necessary.
+ if not self.authenticated:
+ self._Authenticate()
+
+ old_timeout = socket.getdefaulttimeout()
+ socket.setdefaulttimeout(timeout)
+ try:
+ tries = 0
+ while True:
+ tries += 1
+ args = dict(kwargs)
+ url = "%s%s" % (self.host, request_path)
+ if args:
+ url += "?" + urllib.urlencode(args)
+ req = self._CreateRequest(url=url, data=payload)
+ req.add_header("Content-Type", content_type)
+ if extra_headers:
+ for header, value in extra_headers.items():
+ req.add_header(header, value)
+ try:
+ f = self.opener.open(req)
+ response = f.read()
+ f.close()
+ return response
+ except urllib2.HTTPError, e:
+ if tries > 3:
+ raise
+ elif e.code == 401 or e.code == 302:
+ self._Authenticate()
+ elif e.code == 301:
+ # Handle permanent redirect manually.
+ url = e.info()["location"]
+ url_loc = urlparse.urlparse(url)
+ self.host = '%s://%s' % (url_loc[0], url_loc[1])
+ elif e.code >= 500:
+ ErrorExit(e.read())
+ else:
+ raise
+ finally:
+ socket.setdefaulttimeout(old_timeout)
+
+
+class HttpRpcServer(AbstractRpcServer):
+ """Provides a simplified RPC-style interface for HTTP requests."""
+
+ def _Authenticate(self):
+ """Save the cookie jar after authentication."""
+ super(HttpRpcServer, self)._Authenticate()
+ if self.save_cookies:
+ StatusUpdate("Saving authentication cookies to %s" % self.cookie_file)
+ self.cookie_jar.save()
+
+ def _GetOpener(self):
+ """Returns an OpenerDirector that supports cookies and ignores redirects.
+
+ Returns:
+ A urllib2.OpenerDirector object.
+ """
+ opener = urllib2.OpenerDirector()
+ opener.add_handler(urllib2.ProxyHandler())
+ opener.add_handler(urllib2.UnknownHandler())
+ opener.add_handler(urllib2.HTTPHandler())
+ opener.add_handler(urllib2.HTTPDefaultErrorHandler())
+ opener.add_handler(urllib2.HTTPSHandler())
+ opener.add_handler(urllib2.HTTPErrorProcessor())
+ if self.save_cookies:
+ self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies")
+ self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file)
+ if os.path.exists(self.cookie_file):
+ try:
+ self.cookie_jar.load()
+ self.authenticated = True
+ StatusUpdate("Loaded authentication cookies from %s" %
+ self.cookie_file)
+ except (cookielib.LoadError, IOError):
+ # Failed to load cookies - just ignore them.
+ pass
+ else:
+ # Create an empty cookie file with mode 600
+ fd = os.open(self.cookie_file, os.O_CREAT, 0600)
+ os.close(fd)
+ # Always chmod the cookie file
+ os.chmod(self.cookie_file, 0600)
+ else:
+ # Don't save cookies across runs of update.py.
+ self.cookie_jar = cookielib.CookieJar()
+ opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
+ return opener
+
+
+class CondensedHelpFormatter(optparse.IndentedHelpFormatter):
+ """Frees more horizontal space by removing indentation from group
+ options and collapsing arguments between short and long, e.g.
+ '-o ARG, --opt=ARG' to -o --opt ARG"""
+
+ def format_heading(self, heading):
+ return "%s:\n" % heading
+
+ def format_option(self, option):
+ self.dedent()
+ res = optparse.HelpFormatter.format_option(self, option)
+ self.indent()
+ return res
+
+ def format_option_strings(self, option):
+ self.set_long_opt_delimiter(" ")
+ optstr = optparse.HelpFormatter.format_option_strings(self, option)
+ optlist = optstr.split(", ")
+ if len(optlist) > 1:
+ if option.takes_value():
+ # strip METAVAR from all but the last option
+ optlist = [x.split()[0] for x in optlist[:-1]] + optlist[-1:]
+ optstr = " ".join(optlist)
+ return optstr
+
+
+parser = optparse.OptionParser(
+ usage="%prog [options] [-- diff_options] [path...]",
+ add_help_option=False,
+ formatter=CondensedHelpFormatter()
+)
+parser.add_option("-h", "--help", action="store_true",
+ help="Show this help message and exit.")
+parser.add_option("-y", "--assume_yes", action="store_true",
+ dest="assume_yes", default=False,
+ help="Assume that the answer to yes/no questions is 'yes'.")
+# Logging
+group = parser.add_option_group("Logging options")
+group.add_option("-q", "--quiet", action="store_const", const=0,
+ dest="verbose", help="Print errors only.")
+group.add_option("-v", "--verbose", action="store_const", const=2,
+ dest="verbose", default=1,
+ help="Print info level logs.")
+group.add_option("--noisy", action="store_const", const=3,
+ dest="verbose", help="Print all logs.")
+group.add_option("--print_diffs", dest="print_diffs", action="store_true",
+ help="Print full diffs.")
+# Review server
+group = parser.add_option_group("Review server options")
+group.add_option("-s", "--server", action="store", dest="server",
+ default=DEFAULT_REVIEW_SERVER,
+ metavar="SERVER",
+ help=("The server to upload to. The format is host[:port]. "
+ "Defaults to '%default'."))
+group.add_option("-e", "--email", action="store", dest="email",
+ metavar="EMAIL", default=None,
+ help="The username to use. Will prompt if omitted.")
+group.add_option("-H", "--host", action="store", dest="host",
+ metavar="HOST", default=None,
+ help="Overrides the Host header sent with all RPCs.")
+group.add_option("--no_cookies", action="store_false",
+ dest="save_cookies", default=True,
+ help="Do not save authentication cookies to local disk.")
+group.add_option("--account_type", action="store", dest="account_type",
+ metavar="TYPE", default=AUTH_ACCOUNT_TYPE,
+ choices=["GOOGLE", "HOSTED"],
+ help=("Override the default account type "
+ "(defaults to '%default', "
+ "valid choices are 'GOOGLE' and 'HOSTED')."))
+# Issue
+group = parser.add_option_group("Issue options")
+group.add_option("-t", "--title", action="store", dest="title",
+ help="New issue subject or new patch set title")
+group.add_option("-m", "--message", action="store", dest="message",
+ default=None,
+ help="New issue description or new patch set message")
+group.add_option("-F", "--file", action="store", dest="file",
+ default=None, help="Read the message above from file.")
+group.add_option("-r", "--reviewers", action="store", dest="reviewers",
+ metavar="REVIEWERS", default=None,
+ help="Add reviewers (comma separated email addresses).")
+group.add_option("--cc", action="store", dest="cc",
+ metavar="CC", default=None,
+ help="Add CC (comma separated email addresses).")
+group.add_option("--private", action="store_true", dest="private",
+ default=False,
+ help="Make the issue restricted to reviewers and those CCed")
+# Upload options
+group = parser.add_option_group("Patch options")
+group.add_option("-i", "--issue", type="int", action="store",
+ metavar="ISSUE", default=None,
+ help="Issue number to which to add. Defaults to new issue.")
+group.add_option("--base_url", action="store", dest="base_url", default=None,
+ help="Base URL path for files (listed as \"Base URL\" when "
+ "viewing issue). If omitted, will be guessed automatically "
+ "for SVN repos and left blank for others.")
+group.add_option("--download_base", action="store_true",
+ dest="download_base", default=False,
+ help="Base files will be downloaded by the server "
+ "(side-by-side diffs may not work on files with CRs).")
+group.add_option("--rev", action="store", dest="revision",
+ metavar="REV", default=None,
+ help="Base revision/branch/tree to diff against. Use "
+ "rev1:rev2 range to review already committed changeset.")
+group.add_option("--send_mail", action="store_true",
+ dest="send_mail", default=False,
+ help="Send notification email to reviewers.")
+group.add_option("-p", "--send_patch", action="store_true",
+ dest="send_patch", default=False,
+ help="Same as --send_mail, but include diff as an "
+ "attachment, and prepend email subject with 'PATCH:'.")
+group.add_option("--vcs", action="store", dest="vcs",
+ metavar="VCS", default=None,
+ help=("Version control system (optional, usually upload.py "
+ "already guesses the right VCS)."))
+group.add_option("--emulate_svn_auto_props", action="store_true",
+ dest="emulate_svn_auto_props", default=False,
+ help=("Emulate Subversion's auto properties feature."))
+# Git-specific
+group = parser.add_option_group("Git-specific options")
+group.add_option("--git_similarity", action="store", dest="git_similarity",
+ metavar="SIM", type="int", default=50,
+ help=("Set the minimum similarity index for detecting renames "
+ "and copies. See `git diff -C`. (default 50)."))
+group.add_option("--git_no_find_copies", action="store_false", default=True,
+ dest="git_find_copies",
+ help=("Prevents git from looking for copies (default off)."))
+# Perforce-specific
+group = parser.add_option_group("Perforce-specific options "
+ "(overrides P4 environment variables)")
+group.add_option("--p4_port", action="store", dest="p4_port",
+ metavar="P4_PORT", default=None,
+ help=("Perforce server and port (optional)"))
+group.add_option("--p4_changelist", action="store", dest="p4_changelist",
+ metavar="P4_CHANGELIST", default=None,
+ help=("Perforce changelist id"))
+group.add_option("--p4_client", action="store", dest="p4_client",
+ metavar="P4_CLIENT", default=None,
+ help=("Perforce client/workspace"))
+group.add_option("--p4_user", action="store", dest="p4_user",
+ metavar="P4_USER", default=None,
+ help=("Perforce user"))
+
+
+class KeyringCreds(object):
+ def __init__(self, server, host, email):
+ self.server = server
+ self.host = host
+ self.email = email
+ self.accounts_seen = set()
+
+ def GetUserCredentials(self):
+ """Prompts the user for a username and password.
+
+ Only use keyring on the initial call. If the keyring contains the wrong
+ password, we want to give the user a chance to enter another one.
+ """
+ # Create a local alias to the email variable to avoid Python's crazy
+ # scoping rules.
+ global keyring
+ email = self.email
+ if email is None:
+ email = GetEmail("Email (login for uploading to %s)" % self.server)
+ password = None
+ if keyring and not email in self.accounts_seen:
+ try:
+ password = keyring.get_password(self.host, email)
+ except:
+ # Sadly, we have to trap all errors here as
+ # gnomekeyring.IOError inherits from object. :/
+ print "Failed to get password from keyring"
+ keyring = None
+ if password is not None:
+ print "Using password from system keyring."
+ self.accounts_seen.add(email)
+ else:
+ password = getpass.getpass("Password for %s: " % email)
+ if keyring:
+ answer = raw_input("Store password in system keyring?(y/N) ").strip()
+ if answer == "y":
+ keyring.set_password(self.host, email, password)
+ self.accounts_seen.add(email)
+ return (email, password)
+
+
+def GetRpcServer(server, email=None, host_override=None, save_cookies=True,
+ account_type=AUTH_ACCOUNT_TYPE):
+ """Returns an instance of an AbstractRpcServer.
+
+ Args:
+ server: String containing the review server URL.
+ email: String containing user's email address.
+ host_override: If not None, string containing an alternate hostname to use
+ in the host header.
+ save_cookies: Whether authentication cookies should be saved to disk.
+ account_type: Account type for authentication, either 'GOOGLE'
+ or 'HOSTED'. Defaults to AUTH_ACCOUNT_TYPE.
+
+ Returns:
+ A new HttpRpcServer, on which RPC calls can be made.
+ """
+
+ # If this is the dev_appserver, use fake authentication.
+ host = (host_override or server).lower()
+ if re.match(r'(http://)?localhost([:/]|$)', host):
+ if email is None:
+ email = "test@example.com"
+ logging.info("Using debug user %s. Override with --email" % email)
+ server = HttpRpcServer(
+ server,
+ lambda: (email, "password"),
+ host_override=host_override,
+ extra_headers={"Cookie":
+ 'dev_appserver_login="%s:False"' % email},
+ save_cookies=save_cookies,
+ account_type=account_type)
+ # Don't try to talk to ClientLogin.
+ server.authenticated = True
+ return server
+
+ return HttpRpcServer(server,
+ KeyringCreds(server, host, email).GetUserCredentials,
+ host_override=host_override,
+ save_cookies=save_cookies,
+ account_type=account_type)
+
+
+def EncodeMultipartFormData(fields, files):
+ """Encode form fields for multipart/form-data.
+
+ Args:
+ fields: A sequence of (name, value) elements for regular form fields.
+ files: A sequence of (name, filename, value) elements for data to be
+ uploaded as files.
+ Returns:
+ (content_type, body) ready for httplib.HTTP instance.
+
+ Source:
+ http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/146306
+ """
+ BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
+ CRLF = '\r\n'
+ lines = []
+ for (key, value) in fields:
+ lines.append('--' + BOUNDARY)
+ lines.append('Content-Disposition: form-data; name="%s"' % key)
+ lines.append('')
+ if isinstance(value, unicode):
+ value = value.encode('utf-8')
+ lines.append(value)
+ for (key, filename, value) in files:
+ lines.append('--' + BOUNDARY)
+ lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
+ (key, filename))
+ lines.append('Content-Type: %s' % GetContentType(filename))
+ lines.append('')
+ if isinstance(value, unicode):
+ value = value.encode('utf-8')
+ lines.append(value)
+ lines.append('--' + BOUNDARY + '--')
+ lines.append('')
+ body = CRLF.join(lines)
+ content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+ return content_type, body
+
+
+def GetContentType(filename):
+ """Helper to guess the content-type from the filename."""
+ return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+
+
+# Use a shell for subcommands on Windows to get a PATH search.
+use_shell = sys.platform.startswith("win")
+
+def RunShellWithReturnCodeAndStderr(command, print_output=False,
+ universal_newlines=True,
+ env=os.environ):
+ """Executes a command and returns the output from stdout, stderr and the return code.
+
+ Args:
+ command: Command to execute.
+ print_output: If True, the output is printed to stdout.
+ If False, both stdout and stderr are ignored.
+ universal_newlines: Use universal_newlines flag (default: True).
+
+ Returns:
+ Tuple (stdout, stderr, return code)
+ """
+ logging.info("Running %s", command)
+ env = env.copy()
+ env['LC_MESSAGES'] = 'C'
+ p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ shell=use_shell, universal_newlines=universal_newlines,
+ env=env)
+ if print_output:
+ output_array = []
+ while True:
+ line = p.stdout.readline()
+ if not line:
+ break
+ print line.strip("\n")
+ output_array.append(line)
+ output = "".join(output_array)
+ else:
+ output = p.stdout.read()
+ p.wait()
+ errout = p.stderr.read()
+ if print_output and errout:
+ print >>sys.stderr, errout
+ p.stdout.close()
+ p.stderr.close()
+ return output, errout, p.returncode
+
+def RunShellWithReturnCode(command, print_output=False,
+ universal_newlines=True,
+ env=os.environ):
+ """Executes a command and returns the output from stdout and the return code."""
+ out, err, retcode = RunShellWithReturnCodeAndStderr(command, print_output,
+ universal_newlines, env)
+ return out, retcode
+
+def RunShell(command, silent_ok=False, universal_newlines=True,
+ print_output=False, env=os.environ):
+ data, retcode = RunShellWithReturnCode(command, print_output,
+ universal_newlines, env)
+ if retcode:
+ ErrorExit("Got error status from %s:\n%s" % (command, data))
+ if not silent_ok and not data:
+ ErrorExit("No output from %s" % command)
+ return data
+
+
+class VersionControlSystem(object):
+ """Abstract base class providing an interface to the VCS."""
+
+ def __init__(self, options):
+ """Constructor.
+
+ Args:
+ options: Command line options.
+ """
+ self.options = options
+
+ def GetGUID(self):
+ """Return string to distinguish the repository from others, for example to
+ query all opened review issues for it"""
+ raise NotImplementedError(
+ "abstract method -- subclass %s must override" % self.__class__)
+
+ def PostProcessDiff(self, diff):
+ """Return the diff with any special post processing this VCS needs, e.g.
+ to include an svn-style "Index:"."""
+ return diff
+
+ def GenerateDiff(self, args):
+ """Return the current diff as a string.
+
+ Args:
+ args: Extra arguments to pass to the diff command.
+ """
+ raise NotImplementedError(
+ "abstract method -- subclass %s must override" % self.__class__)
+
+ def GetUnknownFiles(self):
+ """Return a list of files unknown to the VCS."""
+ raise NotImplementedError(
+ "abstract method -- subclass %s must override" % self.__class__)
+
+ def CheckForUnknownFiles(self):
+ """Show an "are you sure?" prompt if there are unknown files."""
+ unknown_files = self.GetUnknownFiles()
+ if unknown_files:
+ print "The following files are not added to version control:"
+ for line in unknown_files:
+ print line
+ prompt = "Are you sure to continue?(y/N) "
+ answer = raw_input(prompt).strip()
+ if answer != "y":
+ ErrorExit("User aborted")
+
+ def GetBaseFile(self, filename):
+ """Get the content of the upstream version of a file.
+
+ Returns:
+ A tuple (base_content, new_content, is_binary, status)
+ base_content: The contents of the base file.
+ new_content: For text files, this is empty. For binary files, this is
+ the contents of the new file, since the diff output won't contain
+ information to reconstruct the current file.
+ is_binary: True iff the file is binary.
+ status: The status of the file.
+ """
+
+ raise NotImplementedError(
+ "abstract method -- subclass %s must override" % self.__class__)
+
+
+ def GetBaseFiles(self, diff):
+ """Helper that calls GetBase file for each file in the patch.
+
+ Returns:
+ A dictionary that maps from filename to GetBaseFile's tuple. Filenames
+ are retrieved based on lines that start with "Index:" or
+ "Property changes on:".
+ """
+ files = {}
+ for line in diff.splitlines(True):
+ if line.startswith('Index:') or line.startswith('Property changes on:'):
+ unused, filename = line.split(':', 1)
+ # On Windows if a file has property changes its filename uses '\'
+ # instead of '/'.
+ filename = filename.strip().replace('\\', '/')
+ files[filename] = self.GetBaseFile(filename)
+ return files
+
+
+ def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options,
+ files):
+ """Uploads the base files (and if necessary, the current ones as well)."""
+
+ def UploadFile(filename, file_id, content, is_binary, status, is_base):
+ """Uploads a file to the server."""
+ file_too_large = False
+ if is_base:
+ type = "base"
+ else:
+ type = "current"
+ if len(content) > MAX_UPLOAD_SIZE:
+ print ("Not uploading the %s file for %s because it's too large." %
+ (type, filename))
+ file_too_large = True
+ content = ""
+ checksum = md5(content).hexdigest()
+ if options.verbose > 0 and not file_too_large:
+ print "Uploading %s file for %s" % (type, filename)
+ url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id)
+ form_fields = [("filename", filename),
+ ("status", status),
+ ("checksum", checksum),
+ ("is_binary", str(is_binary)),
+ ("is_current", str(not is_base)),
+ ]
+ if file_too_large:
+ form_fields.append(("file_too_large", "1"))
+ if options.email:
+ form_fields.append(("user", options.email))
+ ctype, body = EncodeMultipartFormData(form_fields,
+ [("data", filename, content)])
+ response_body = rpc_server.Send(url, body,
+ content_type=ctype)
+ if not response_body.startswith("OK"):
+ StatusUpdate(" --> %s" % response_body)
+ sys.exit(1)
+
+ patches = dict()
+ [patches.setdefault(v, k) for k, v in patch_list]
+ for filename in patches.keys():
+ base_content, new_content, is_binary, status = files[filename]
+ file_id_str = patches.get(filename)
+ if file_id_str.find("nobase") != -1:
+ base_content = None
+ file_id_str = file_id_str[file_id_str.rfind("_") + 1:]
+ file_id = int(file_id_str)
+ if base_content != None:
+ UploadFile(filename, file_id, base_content, is_binary, status, True)
+ if new_content != None:
+ UploadFile(filename, file_id, new_content, is_binary, status, False)
+
+ def IsImage(self, filename):
+ """Returns true if the filename has an image extension."""
+ mimetype = mimetypes.guess_type(filename)[0]
+ if not mimetype:
+ return False
+ return mimetype.startswith("image/")
+
+ def IsBinaryData(self, data):
+ """Returns true if data contains a null byte."""
+ # Derived from how Mercurial's heuristic, see
+ # http://selenic.com/hg/file/848a6658069e/mercurial/util.py#l229
+ return bool(data and "\0" in data)
+
+
+class SubversionVCS(VersionControlSystem):
+ """Implementation of the VersionControlSystem interface for Subversion."""
+
+ def __init__(self, options):
+ super(SubversionVCS, self).__init__(options)
+ if self.options.revision:
+ match = re.match(r"(\d+)(:(\d+))?", self.options.revision)
+ if not match:
+ ErrorExit("Invalid Subversion revision %s." % self.options.revision)
+ self.rev_start = match.group(1)
+ self.rev_end = match.group(3)
+ else:
+ self.rev_start = self.rev_end = None
+ # Cache output from "svn list -r REVNO dirname".
+ # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev).
+ self.svnls_cache = {}
+ # Base URL is required to fetch files deleted in an older revision.
+ # Result is cached to not guess it over and over again in GetBaseFile().
+ required = self.options.download_base or self.options.revision is not None
+ self.svn_base = self._GuessBase(required)
+
+ def GetGUID(self):
+ return self._GetInfo("Repository UUID")
+
+ def GuessBase(self, required):
+ """Wrapper for _GuessBase."""
+ return self.svn_base
+
+ def _GuessBase(self, required):
+ """Returns base URL for current diff.
+
+ Args:
+ required: If true, exits if the url can't be guessed, otherwise None is
+ returned.
+ """
+ url = self._GetInfo("URL")
+ if url:
+ scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
+ guess = ""
+ # TODO(anatoli) - repository specific hacks should be handled by server
+ if netloc == "svn.python.org" and scheme == "svn+ssh":
+ path = "projects" + path
+ scheme = "http"
+ guess = "Python "
+ elif netloc.endswith(".googlecode.com"):
+ scheme = "http"
+ guess = "Google Code "
+ path = path + "/"
+ base = urlparse.urlunparse((scheme, netloc, path, params,
+ query, fragment))
+ logging.info("Guessed %sbase = %s", guess, base)
+ return base
+ if required:
+ ErrorExit("Can't find URL in output from svn info")
+ return None
+
+ def _GetInfo(self, key):
+ """Parses 'svn info' for current dir. Returns value for key or None"""
+ for line in RunShell(["svn", "info"]).splitlines():
+ if line.startswith(key + ": "):
+ return line.split(":", 1)[1].strip()
+
+ def _EscapeFilename(self, filename):
+ """Escapes filename for SVN commands."""
+ if "@" in filename and not filename.endswith("@"):
+ filename = "%s@" % filename
+ return filename
+
+ def GenerateDiff(self, args):
+ cmd = ["svn", "diff"]
+ if self.options.revision:
+ cmd += ["-r", self.options.revision]
+ cmd.extend(args)
+ data = RunShell(cmd)
+ count = 0
+ for line in data.splitlines():
+ if line.startswith("Index:") or line.startswith("Property changes on:"):
+ count += 1
+ logging.info(line)
+ if not count:
+ ErrorExit("No valid patches found in output from svn diff")
+ return data
+
+ def _CollapseKeywords(self, content, keyword_str):
+ """Collapses SVN keywords."""
+ # svn cat translates keywords but svn diff doesn't. As a result of this
+ # behavior patching.PatchChunks() fails with a chunk mismatch error.
+ # This part was originally written by the Review Board development team
+ # who had the same problem (http://reviews.review-board.org/r/276/).
+ # Mapping of keywords to known aliases
+ svn_keywords = {
+ # Standard keywords
+ 'Date': ['Date', 'LastChangedDate'],
+ 'Revision': ['Revision', 'LastChangedRevision', 'Rev'],
+ 'Author': ['Author', 'LastChangedBy'],
+ 'HeadURL': ['HeadURL', 'URL'],
+ 'Id': ['Id'],
+
+ # Aliases
+ 'LastChangedDate': ['LastChangedDate', 'Date'],
+ 'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'],
+ 'LastChangedBy': ['LastChangedBy', 'Author'],
+ 'URL': ['URL', 'HeadURL'],
+ }
+
+ def repl(m):
+ if m.group(2):
+ return "$%s::%s$" % (m.group(1), " " * len(m.group(3)))
+ return "$%s$" % m.group(1)
+ keywords = [keyword
+ for name in keyword_str.split(" ")
+ for keyword in svn_keywords.get(name, [])]
+ return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content)
+
+ def GetUnknownFiles(self):
+ status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True)
+ unknown_files = []
+ for line in status.split("\n"):
+ if line and line[0] == "?":
+ unknown_files.append(line)
+ return unknown_files
+
+ def ReadFile(self, filename):
+ """Returns the contents of a file."""
+ file = open(filename, 'rb')
+ result = ""
+ try:
+ result = file.read()
+ finally:
+ file.close()
+ return result
+
+ def GetStatus(self, filename):
+ """Returns the status of a file."""
+ if not self.options.revision:
+ status = RunShell(["svn", "status", "--ignore-externals",
+ self._EscapeFilename(filename)])
+ if not status:
+ ErrorExit("svn status returned no output for %s" % filename)
+ status_lines = status.splitlines()
+ # If file is in a cl, the output will begin with
+ # "\n--- Changelist 'cl_name':\n". See
+ # http://svn.collab.net/repos/svn/trunk/notes/changelist-design.txt
+ if (len(status_lines) == 3 and
+ not status_lines[0] and
+ status_lines[1].startswith("--- Changelist")):
+ status = status_lines[2]
+ else:
+ status = status_lines[0]
+ # If we have a revision to diff against we need to run "svn list"
+ # for the old and the new revision and compare the results to get
+ # the correct status for a file.
+ else:
+ dirname, relfilename = os.path.split(filename)
+ if dirname not in self.svnls_cache:
+ cmd = ["svn", "list", "-r", self.rev_start,
+ self._EscapeFilename(dirname) or "."]
+ out, err, returncode = RunShellWithReturnCodeAndStderr(cmd)
+ if returncode:
+ # Directory might not yet exist at start revison
+ # svn: Unable to find repository location for 'abc' in revision nnn
+ if re.match('^svn: Unable to find repository location for .+ in revision \d+', err):
+ old_files = ()
+ else:
+ ErrorExit("Failed to get status for %s:\n%s" % (filename, err))
+ else:
+ old_files = out.splitlines()
+ args = ["svn", "list"]
+ if self.rev_end:
+ args += ["-r", self.rev_end]
+ cmd = args + [self._EscapeFilename(dirname) or "."]
+ out, returncode = RunShellWithReturnCode(cmd)
+ if returncode:
+ ErrorExit("Failed to run command %s" % cmd)
+ self.svnls_cache[dirname] = (old_files, out.splitlines())
+ old_files, new_files = self.svnls_cache[dirname]
+ if relfilename in old_files and relfilename not in new_files:
+ status = "D "
+ elif relfilename in old_files and relfilename in new_files:
+ status = "M "
+ else:
+ status = "A "
+ return status
+
+ def GetBaseFile(self, filename):
+ status = self.GetStatus(filename)
+ base_content = None
+ new_content = None
+
+ # If a file is copied its status will be "A +", which signifies
+ # "addition-with-history". See "svn st" for more information. We need to
+ # upload the original file or else diff parsing will fail if the file was
+ # edited.
+ if status[0] == "A" and status[3] != "+":
+ # We'll need to upload the new content if we're adding a binary file
+ # since diff's output won't contain it.
+ mimetype = RunShell(["svn", "propget", "svn:mime-type",
+ self._EscapeFilename(filename)], silent_ok=True)
+ base_content = ""
+ is_binary = bool(mimetype) and not mimetype.startswith("text/")
+ if is_binary:
+ new_content = self.ReadFile(filename)
+ elif (status[0] in ("M", "D", "R") or
+ (status[0] == "A" and status[3] == "+") or # Copied file.
+ (status[0] == " " and status[1] == "M")): # Property change.
+ args = []
+ if self.options.revision:
+ # filename must not be escaped. We already add an ampersand here.
+ url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+ else:
+ # Don't change filename, it's needed later.
+ url = filename
+ args += ["-r", "BASE"]
+ cmd = ["svn"] + args + ["propget", "svn:mime-type", url]
+ mimetype, returncode = RunShellWithReturnCode(cmd)
+ if returncode:
+ # File does not exist in the requested revision.
+ # Reset mimetype, it contains an error message.
+ mimetype = ""
+ else:
+ mimetype = mimetype.strip()
+ get_base = False
+ # this test for binary is exactly the test prescribed by the
+ # official SVN docs at
+ # http://subversion.apache.org/faq.html#binary-files
+ is_binary = (bool(mimetype) and
+ not mimetype.startswith("text/") and
+ mimetype not in ("image/x-xbitmap", "image/x-xpixmap"))
+ if status[0] == " ":
+ # Empty base content just to force an upload.
+ base_content = ""
+ elif is_binary:
+ get_base = True
+ if status[0] == "M":
+ if not self.rev_end:
+ new_content = self.ReadFile(filename)
+ else:
+ url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end)
+ new_content = RunShell(["svn", "cat", url],
+ universal_newlines=True, silent_ok=True)
+ else:
+ get_base = True
+
+ if get_base:
+ if is_binary:
+ universal_newlines = False
+ else:
+ universal_newlines = True
+ if self.rev_start:
+ # "svn cat -r REV delete_file.txt" doesn't work. cat requires
+ # the full URL with "@REV" appended instead of using "-r" option.
+ url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+ base_content = RunShell(["svn", "cat", url],
+ universal_newlines=universal_newlines,
+ silent_ok=True)
+ else:
+ base_content, ret_code = RunShellWithReturnCode(
+ ["svn", "cat", self._EscapeFilename(filename)],
+ universal_newlines=universal_newlines)
+ if ret_code and status[0] == "R":
+ # It's a replaced file without local history (see issue208).
+ # The base file needs to be fetched from the server.
+ url = "%s/%s" % (self.svn_base, filename)
+ base_content = RunShell(["svn", "cat", url],
+ universal_newlines=universal_newlines,
+ silent_ok=True)
+ elif ret_code:
+ ErrorExit("Got error status from 'svn cat %s'" % filename)
+ if not is_binary:
+ args = []
+ if self.rev_start:
+ url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
+ else:
+ url = filename
+ args += ["-r", "BASE"]
+ cmd = ["svn"] + args + ["propget", "svn:keywords", url]
+ keywords, returncode = RunShellWithReturnCode(cmd)
+ if keywords and not returncode:
+ base_content = self._CollapseKeywords(base_content, keywords)
+ else:
+ StatusUpdate("svn status returned unexpected output: %s" % status)
+ sys.exit(1)
+ return base_content, new_content, is_binary, status[0:5]
+
+
+class GitVCS(VersionControlSystem):
+ """Implementation of the VersionControlSystem interface for Git."""
+
+ def __init__(self, options):
+ super(GitVCS, self).__init__(options)
+ # Map of filename -> (hash before, hash after) of base file.
+ # Hashes for "no such file" are represented as None.
+ self.hashes = {}
+ # Map of new filename -> old filename for renames.
+ self.renames = {}
+
+ def GetGUID(self):
+ revlist = RunShell("git rev-list --parents HEAD".split()).splitlines()
+ # M-A: Return the 1st root hash, there could be multiple when a
+ # subtree is merged. In that case, more analysis would need to
+ # be done to figure out which HEAD is the 'most representative'.
+ for r in revlist:
+ if ' ' not in r:
+ return r
+
+ def PostProcessDiff(self, gitdiff):
+ """Converts the diff output to include an svn-style "Index:" line as well
+ as record the hashes of the files, so we can upload them along with our
+ diff."""
+ # Special used by git to indicate "no such content".
+ NULL_HASH = "0"*40
+
+ def IsFileNew(filename):
+ return filename in self.hashes and self.hashes[filename][0] is None
+
+ def AddSubversionPropertyChange(filename):
+ """Add svn's property change information into the patch if given file is
+ new file.
+
+ We use Subversion's auto-props setting to retrieve its property.
+ See http://svnbook.red-bean.com/en/1.1/ch07.html#svn-ch-7-sect-1.3.2 for
+ Subversion's [auto-props] setting.
+ """
+ if self.options.emulate_svn_auto_props and IsFileNew(filename):
+ svnprops = GetSubversionPropertyChanges(filename)
+ if svnprops:
+ svndiff.append("\n" + svnprops + "\n")
+
+ svndiff = []
+ filecount = 0
+ filename = None
+ for line in gitdiff.splitlines():
+ match = re.match(r"diff --git a/(.*) b/(.*)$", line)
+ if match:
+ # Add auto property here for previously seen file.
+ if filename is not None:
+ AddSubversionPropertyChange(filename)
+ filecount += 1
+ # Intentionally use the "after" filename so we can show renames.
+ filename = match.group(2)
+ svndiff.append("Index: %s\n" % filename)
+ if match.group(1) != match.group(2):
+ self.renames[match.group(2)] = match.group(1)
+ else:
+ # The "index" line in a git diff looks like this (long hashes elided):
+ # index 82c0d44..b2cee3f 100755
+ # We want to save the left hash, as that identifies the base file.
+ match = re.match(r"index (\w+)\.\.(\w+)", line)
+ if match:
+ before, after = (match.group(1), match.group(2))
+ if before == NULL_HASH:
+ before = None
+ if after == NULL_HASH:
+ after = None
+ self.hashes[filename] = (before, after)
+ svndiff.append(line + "\n")
+ if not filecount:
+ ErrorExit("No valid patches found in output from git diff")
+ # Add auto property for the last seen file.
+ assert filename is not None
+ AddSubversionPropertyChange(filename)
+ return "".join(svndiff)
+
+ def GenerateDiff(self, extra_args):
+ extra_args = extra_args[:]
+ if self.options.revision:
+ if ":" in self.options.revision:
+ extra_args = self.options.revision.split(":", 1) + extra_args
+ else:
+ extra_args = [self.options.revision] + extra_args
+
+ # --no-ext-diff is broken in some versions of Git, so try to work around
+ # this by overriding the environment (but there is still a problem if the
+ # git config key "diff.external" is used).
+ env = os.environ.copy()
+ if "GIT_EXTERNAL_DIFF" in env:
+ del env["GIT_EXTERNAL_DIFF"]
+ # -M/-C will not print the diff for the deleted file when a file is renamed.
+ # This is confusing because the original file will not be shown on the
+ # review when a file is renamed. So, get a diff with ONLY deletes, then
+ # append a diff (with rename detection), without deletes.
+ cmd = [
+ "git", "diff", "--no-color", "--no-ext-diff", "--full-index",
+ "--ignore-submodules",
+ ]
+ diff = RunShell(
+ cmd + ["--no-renames", "--diff-filter=D"] + extra_args,
+ env=env, silent_ok=True)
+ if self.options.git_find_copies:
+ similarity_options = ["--find-copies-harder", "-l100000",
+ "-C%s" % self.options.git_similarity ]
+ else:
+ similarity_options = ["-M%s" % self.options.git_similarity ]
+ diff += RunShell(
+ cmd + ["--diff-filter=AMCRT"] + similarity_options + extra_args,
+ env=env, silent_ok=True)
+
+ # The CL could be only file deletion or not. So accept silent diff for both
+ # commands then check for an empty diff manually.
+ if not diff:
+ ErrorExit("No output from %s" % (cmd + extra_args))
+ return diff
+
+ def GetUnknownFiles(self):
+ status = RunShell(["git", "ls-files", "--exclude-standard", "--others"],
+ silent_ok=True)
+ return status.splitlines()
+
+ def GetFileContent(self, file_hash, is_binary):
+ """Returns the content of a file identified by its git hash."""
+ data, retcode = RunShellWithReturnCode(["git", "show", file_hash],
+ universal_newlines=not is_binary)
+ if retcode:
+ ErrorExit("Got error status from 'git show %s'" % file_hash)
+ return data
+
+ def GetBaseFile(self, filename):
+ hash_before, hash_after = self.hashes.get(filename, (None,None))
+ base_content = None
+ new_content = None
+ status = None
+
+ if filename in self.renames:
+ status = "A +" # Match svn attribute name for renames.
+ if filename not in self.hashes:
+ # If a rename doesn't change the content, we never get a hash.
+ base_content = RunShell(
+ ["git", "show", "HEAD:" + filename], silent_ok=True)
+ elif not hash_before:
+ status = "A"
+ base_content = ""
+ elif not hash_after:
+ status = "D"
+ else:
+ status = "M"
+
+ is_binary = self.IsBinaryData(base_content)
+ is_image = self.IsImage(filename)
+
+ # Grab the before/after content if we need it.
+ # Grab the base content if we don't have it already.
+ if base_content is None and hash_before:
+ base_content = self.GetFileContent(hash_before, is_binary)
+ # Only include the "after" file if it's an image; otherwise it
+ # it is reconstructed from the diff.
+ if is_image and hash_after:
+ new_content = self.GetFileContent(hash_after, is_binary)
+
+ return (base_content, new_content, is_binary, status)
+
+
+class CVSVCS(VersionControlSystem):
+ """Implementation of the VersionControlSystem interface for CVS."""
+
+ def __init__(self, options):
+ super(CVSVCS, self).__init__(options)
+
+ def GetGUID(self):
+ """For now we don't know how to get repository ID for CVS"""
+ return
+
+ def GetOriginalContent_(self, filename):
+ RunShell(["cvs", "up", filename], silent_ok=True)
+ # TODO need detect file content encoding
+ content = open(filename).read()
+ return content.replace("\r\n", "\n")
+
+ def GetBaseFile(self, filename):
+ base_content = None
+ new_content = None
+ status = "A"
+
+ output, retcode = RunShellWithReturnCode(["cvs", "status", filename])
+ if retcode:
+ ErrorExit("Got error status from 'cvs status %s'" % filename)
+
+ if output.find("Status: Locally Modified") != -1:
+ status = "M"
+ temp_filename = "%s.tmp123" % filename
+ os.rename(filename, temp_filename)
+ base_content = self.GetOriginalContent_(filename)
+ os.rename(temp_filename, filename)
+ elif output.find("Status: Locally Added"):
+ status = "A"
+ base_content = ""
+ elif output.find("Status: Needs Checkout"):
+ status = "D"
+ base_content = self.GetOriginalContent_(filename)
+
+ return (base_content, new_content, self.IsBinaryData(base_content), status)
+
+ def GenerateDiff(self, extra_args):
+ cmd = ["cvs", "diff", "-u", "-N"]
+ if self.options.revision:
+ cmd += ["-r", self.options.revision]
+
+ cmd.extend(extra_args)
+ data, retcode = RunShellWithReturnCode(cmd)
+ count = 0
+ if retcode in [0, 1]:
+ for line in data.splitlines():
+ if line.startswith("Index:"):
+ count += 1
+ logging.info(line)
+
+ if not count:
+ ErrorExit("No valid patches found in output from cvs diff")
+
+ return data
+
+ def GetUnknownFiles(self):
+ data, retcode = RunShellWithReturnCode(["cvs", "diff"])
+ if retcode not in [0, 1]:
+ ErrorExit("Got error status from 'cvs diff':\n%s" % (data,))
+ unknown_files = []
+ for line in data.split("\n"):
+ if line and line[0] == "?":
+ unknown_files.append(line)
+ return unknown_files
+
+class MercurialVCS(VersionControlSystem):
+ """Implementation of the VersionControlSystem interface for Mercurial."""
+
+ def __init__(self, options, repo_dir):
+ super(MercurialVCS, self).__init__(options)
+ # Absolute path to repository (we can be in a subdir)
+ self.repo_dir = os.path.normpath(repo_dir)
+ # Compute the subdir
+ cwd = os.path.normpath(os.getcwd())
+ assert cwd.startswith(self.repo_dir)
+ self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/")
+ if self.options.revision:
+ self.base_rev = self.options.revision
+ else:
+ self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip()
+
+ def GetGUID(self):
+ # See chapter "Uniquely identifying a repository"
+ # http://hgbook.red-bean.com/read/customizing-the-output-of-mercurial.html
+ info = RunShell("hg log -r0 --template {node}".split())
+ return info.strip()
+
+ def _GetRelPath(self, filename):
+ """Get relative path of a file according to the current directory,
+ given its logical path in the repo."""
+ absname = os.path.join(self.repo_dir, filename)
+ return os.path.relpath(absname)
+
+ def GenerateDiff(self, extra_args):
+ cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args
+ data = RunShell(cmd, silent_ok=True)
+ svndiff = []
+ filecount = 0
+ for line in data.splitlines():
+ m = re.match("diff --git a/(\S+) b/(\S+)", line)
+ if m:
+ # Modify line to make it look like as it comes from svn diff.
+ # With this modification no changes on the server side are required
+ # to make upload.py work with Mercurial repos.
+ # NOTE: for proper handling of moved/copied files, we have to use
+ # the second filename.
+ filename = m.group(2)
+ svndiff.append("Index: %s" % filename)
+ svndiff.append("=" * 67)
+ filecount += 1
+ logging.info(line)
+ else:
+ svndiff.append(line)
+ if not filecount:
+ ErrorExit("No valid patches found in output from hg diff")
+ return "\n".join(svndiff) + "\n"
+
+ def GetUnknownFiles(self):
+ """Return a list of files unknown to the VCS."""
+ args = []
+ status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."],
+ silent_ok=True)
+ unknown_files = []
+ for line in status.splitlines():
+ st, fn = line.split(" ", 1)
+ if st == "?":
+ unknown_files.append(fn)
+ return unknown_files
+
+ def GetBaseFile(self, filename):
+ # "hg status" and "hg cat" both take a path relative to the current subdir,
+ # but "hg diff" has given us the path relative to the repo root.
+ base_content = ""
+ new_content = None
+ is_binary = False
+ oldrelpath = relpath = self._GetRelPath(filename)
+ # "hg status -C" returns two lines for moved/copied files, one otherwise
+ out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath])
+ out = out.splitlines()
+ # HACK: strip error message about missing file/directory if it isn't in
+ # the working copy
+ if out[0].startswith('%s: ' % relpath):
+ out = out[1:]
+ status, _ = out[0].split(' ', 1)
+ if len(out) > 1 and status == "A":
+ # Moved/copied => considered as modified, use old filename to
+ # retrieve base contents
+ oldrelpath = out[1].strip()
+ status = "M"
+ if ":" in self.base_rev:
+ base_rev = self.base_rev.split(":", 1)[0]
+ else:
+ base_rev = self.base_rev
+ if status != "A":
+ base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],
+ silent_ok=True)
+ is_binary = self.IsBinaryData(base_content)
+ if status != "R":
+ new_content = open(relpath, "rb").read()
+ is_binary = is_binary or self.IsBinaryData(new_content)
+ if is_binary and base_content:
+ # Fetch again without converting newlines
+ base_content = RunShell(["hg", "cat", "-r", base_rev, oldrelpath],
+ silent_ok=True, universal_newlines=False)
+ if not is_binary:
+ new_content = None
+ return base_content, new_content, is_binary, status
+
+
+class PerforceVCS(VersionControlSystem):
+ """Implementation of the VersionControlSystem interface for Perforce."""
+
+ def __init__(self, options):
+
+ def ConfirmLogin():
+ # Make sure we have a valid perforce session
+ while True:
+ data, retcode = self.RunPerforceCommandWithReturnCode(
+ ["login", "-s"], marshal_output=True)
+ if not data:
+ ErrorExit("Error checking perforce login")
+ if not retcode and (not "code" in data or data["code"] != "error"):
+ break
+ print "Enter perforce password: "
+ self.RunPerforceCommandWithReturnCode(["login"])
+
+ super(PerforceVCS, self).__init__(options)
+
+ self.p4_changelist = options.p4_changelist
+ if not self.p4_changelist:
+ ErrorExit("A changelist id is required")
+ if (options.revision):
+ ErrorExit("--rev is not supported for perforce")
+
+ self.p4_port = options.p4_port
+ self.p4_client = options.p4_client
+ self.p4_user = options.p4_user
+
+ ConfirmLogin()
+
+ if not options.title:
+ description = self.RunPerforceCommand(["describe", self.p4_changelist],
+ marshal_output=True)
+ if description and "desc" in description:
+ # Rietveld doesn't support multi-line descriptions
+ raw_title = description["desc"].strip()
+ lines = raw_title.splitlines()
+ if len(lines):
+ options.title = lines[0]
+
+ def GetGUID(self):
+ """For now we don't know how to get repository ID for Perforce"""
+ return
+
+ def RunPerforceCommandWithReturnCode(self, extra_args, marshal_output=False,
+ universal_newlines=True):
+ args = ["p4"]
+ if marshal_output:
+ # -G makes perforce format its output as marshalled python objects
+ args.extend(["-G"])
+ if self.p4_port:
+ args.extend(["-p", self.p4_port])
+ if self.p4_client:
+ args.extend(["-c", self.p4_client])
+ if self.p4_user:
+ args.extend(["-u", self.p4_user])
+ args.extend(extra_args)
+
+ data, retcode = RunShellWithReturnCode(
+ args, print_output=False, universal_newlines=universal_newlines)
+ if marshal_output and data:
+ data = marshal.loads(data)
+ return data, retcode
+
+ def RunPerforceCommand(self, extra_args, marshal_output=False,
+ universal_newlines=True):
+ # This might be a good place to cache call results, since things like
+ # describe or fstat might get called repeatedly.
+ data, retcode = self.RunPerforceCommandWithReturnCode(
+ extra_args, marshal_output, universal_newlines)
+ if retcode:
+ ErrorExit("Got error status from %s:\n%s" % (extra_args, data))
+ return data
+
+ def GetFileProperties(self, property_key_prefix = "", command = "describe"):
+ description = self.RunPerforceCommand(["describe", self.p4_changelist],
+ marshal_output=True)
+
+ changed_files = {}
+ file_index = 0
+ # Try depotFile0, depotFile1, ... until we don't find a match
+ while True:
+ file_key = "depotFile%d" % file_index
+ if file_key in description:
+ filename = description[file_key]
+ change_type = description[property_key_prefix + str(file_index)]
+ changed_files[filename] = change_type
+ file_index += 1
+ else:
+ break
+ return changed_files
+
+ def GetChangedFiles(self):
+ return self.GetFileProperties("action")
+
+ def GetUnknownFiles(self):
+ # Perforce doesn't detect new files, they have to be explicitly added
+ return []
+
+ def IsBaseBinary(self, filename):
+ base_filename = self.GetBaseFilename(filename)
+ return self.IsBinaryHelper(base_filename, "files")
+
+ def IsPendingBinary(self, filename):
+ return self.IsBinaryHelper(filename, "describe")
+
+ def IsBinaryHelper(self, filename, command):
+ file_types = self.GetFileProperties("type", command)
+ if not filename in file_types:
+ ErrorExit("Trying to check binary status of unknown file %s." % filename)
+ # This treats symlinks, macintosh resource files, temporary objects, and
+ # unicode as binary. See the Perforce docs for more details:
+ # http://www.perforce.com/perforce/doc.current/manuals/cmdref/o.ftypes.html
+ return not file_types[filename].endswith("text")
+
+ def GetFileContent(self, filename, revision, is_binary):
+ file_arg = filename
+ if revision:
+ file_arg += "#" + revision
+ # -q suppresses the initial line that displays the filename and revision
+ return self.RunPerforceCommand(["print", "-q", file_arg],
+ universal_newlines=not is_binary)
+
+ def GetBaseFilename(self, filename):
+ actionsWithDifferentBases = [
+ "move/add", # p4 move
+ "branch", # p4 integrate (to a new file), similar to hg "add"
+ "add", # p4 integrate (to a new file), after modifying the new file
+ ]
+
+ # We only see a different base for "add" if this is a downgraded branch
+ # after a file was branched (integrated), then edited.
+ if self.GetAction(filename) in actionsWithDifferentBases:
+ # -Or shows information about pending integrations/moves
+ fstat_result = self.RunPerforceCommand(["fstat", "-Or", filename],
+ marshal_output=True)
+
+ baseFileKey = "resolveFromFile0" # I think it's safe to use only file0
+ if baseFileKey in fstat_result:
+ return fstat_result[baseFileKey]
+
+ return filename
+
+ def GetBaseRevision(self, filename):
+ base_filename = self.GetBaseFilename(filename)
+
+ have_result = self.RunPerforceCommand(["have", base_filename],
+ marshal_output=True)
+ if "haveRev" in have_result:
+ return have_result["haveRev"]
+
+ def GetLocalFilename(self, filename):
+ where = self.RunPerforceCommand(["where", filename], marshal_output=True)
+ if "path" in where:
+ return where["path"]
+
+ def GenerateDiff(self, args):
+ class DiffData:
+ def __init__(self, perforceVCS, filename, action):
+ self.perforceVCS = perforceVCS
+ self.filename = filename
+ self.action = action
+ self.base_filename = perforceVCS.GetBaseFilename(filename)
+
+ self.file_body = None
+ self.base_rev = None
+ self.prefix = None
+ self.working_copy = True
+ self.change_summary = None
+
+ def GenerateDiffHeader(diffData):
+ header = []
+ header.append("Index: %s" % diffData.filename)
+ header.append("=" * 67)
+
+ if diffData.base_filename != diffData.filename:
+ if diffData.action.startswith("move"):
+ verb = "rename"
+ else:
+ verb = "copy"
+ header.append("%s from %s" % (verb, diffData.base_filename))
+ header.append("%s to %s" % (verb, diffData.filename))
+
+ suffix = "\t(revision %s)" % diffData.base_rev
+ header.append("--- " + diffData.base_filename + suffix)
+ if diffData.working_copy:
+ suffix = "\t(working copy)"
+ header.append("+++ " + diffData.filename + suffix)
+ if diffData.change_summary:
+ header.append(diffData.change_summary)
+ return header
+
+ def GenerateMergeDiff(diffData, args):
+ # -du generates a unified diff, which is nearly svn format
+ diffData.file_body = self.RunPerforceCommand(
+ ["diff", "-du", diffData.filename] + args)
+ diffData.base_rev = self.GetBaseRevision(diffData.filename)
+ diffData.prefix = ""
+
+ # We have to replace p4's file status output (the lines starting
+ # with +++ or ---) to match svn's diff format
+ lines = diffData.file_body.splitlines()
+ first_good_line = 0
+ while (first_good_line < len(lines) and
+ not lines[first_good_line].startswith("@@")):
+ first_good_line += 1
+ diffData.file_body = "\n".join(lines[first_good_line:])
+ return diffData
+
+ def GenerateAddDiff(diffData):
+ fstat = self.RunPerforceCommand(["fstat", diffData.filename],
+ marshal_output=True)
+ if "headRev" in fstat:
+ diffData.base_rev = fstat["headRev"] # Re-adding a deleted file
+ else:
+ diffData.base_rev = "0" # Brand new file
+ diffData.working_copy = False
+ rel_path = self.GetLocalFilename(diffData.filename)
+ diffData.file_body = open(rel_path, 'r').read()
+ # Replicate svn's list of changed lines
+ line_count = len(diffData.file_body.splitlines())
+ diffData.change_summary = "@@ -0,0 +1"
+ if line_count > 1:
+ diffData.change_summary += ",%d" % line_count
+ diffData.change_summary += " @@"
+ diffData.prefix = "+"
+ return diffData
+
+ def GenerateDeleteDiff(diffData):
+ diffData.base_rev = self.GetBaseRevision(diffData.filename)
+ is_base_binary = self.IsBaseBinary(diffData.filename)
+ # For deletes, base_filename == filename
+ diffData.file_body = self.GetFileContent(diffData.base_filename,
+ None,
+ is_base_binary)
+ # Replicate svn's list of changed lines
+ line_count = len(diffData.file_body.splitlines())
+ diffData.change_summary = "@@ -1"
+ if line_count > 1:
+ diffData.change_summary += ",%d" % line_count
+ diffData.change_summary += " +0,0 @@"
+ diffData.prefix = "-"
+ return diffData
+
+ changed_files = self.GetChangedFiles()
+
+ svndiff = []
+ filecount = 0
+ for (filename, action) in changed_files.items():
+ svn_status = self.PerforceActionToSvnStatus(action)
+ if svn_status == "SKIP":
+ continue
+
+ diffData = DiffData(self, filename, action)
+ # Is it possible to diff a branched file? Stackoverflow says no:
+ # http://stackoverflow.com/questions/1771314/in-perforce-command-line-how-to-diff-a-file-reopened-for-add
+ if svn_status == "M":
+ diffData = GenerateMergeDiff(diffData, args)
+ elif svn_status == "A":
+ diffData = GenerateAddDiff(diffData)
+ elif svn_status == "D":
+ diffData = GenerateDeleteDiff(diffData)
+ else:
+ ErrorExit("Unknown file action %s (svn action %s)." % \
+ (action, svn_status))
+
+ svndiff += GenerateDiffHeader(diffData)
+
+ for line in diffData.file_body.splitlines():
+ svndiff.append(diffData.prefix + line)
+ filecount += 1
+ if not filecount:
+ ErrorExit("No valid patches found in output from p4 diff")
+ return "\n".join(svndiff) + "\n"
+
+ def PerforceActionToSvnStatus(self, status):
+ # Mirroring the list at http://permalink.gmane.org/gmane.comp.version-control.mercurial.devel/28717
+ # Is there something more official?
+ return {
+ "add" : "A",
+ "branch" : "A",
+ "delete" : "D",
+ "edit" : "M", # Also includes changing file types.
+ "integrate" : "M",
+ "move/add" : "M",
+ "move/delete": "SKIP",
+ "purge" : "D", # How does a file's status become "purge"?
+ }[status]
+
+ def GetAction(self, filename):
+ changed_files = self.GetChangedFiles()
+ if not filename in changed_files:
+ ErrorExit("Trying to get base version of unknown file %s." % filename)
+
+ return changed_files[filename]
+
+ def GetBaseFile(self, filename):
+ base_filename = self.GetBaseFilename(filename)
+ base_content = ""
+ new_content = None
+
+ status = self.PerforceActionToSvnStatus(self.GetAction(filename))
+
+ if status != "A":
+ revision = self.GetBaseRevision(base_filename)
+ if not revision:
+ ErrorExit("Couldn't find base revision for file %s" % filename)
+ is_base_binary = self.IsBaseBinary(base_filename)
+ base_content = self.GetFileContent(base_filename,
+ revision,
+ is_base_binary)
+
+ is_binary = self.IsPendingBinary(filename)
+ if status != "D" and status != "SKIP":
+ relpath = self.GetLocalFilename(filename)
+ if is_binary:
+ new_content = open(relpath, "rb").read()
+
+ return base_content, new_content, is_binary, status
+
+# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync.
+def SplitPatch(data):
+ """Splits a patch into separate pieces for each file.
+
+ Args:
+ data: A string containing the output of svn diff.
+
+ Returns:
+ A list of 2-tuple (filename, text) where text is the svn diff output
+ pertaining to filename.
+ """
+ patches = []
+ filename = None
+ diff = []
+ for line in data.splitlines(True):
+ new_filename = None
+ if line.startswith('Index:'):
+ unused, new_filename = line.split(':', 1)
+ new_filename = new_filename.strip()
+ elif line.startswith('Property changes on:'):
+ unused, temp_filename = line.split(':', 1)
+ # When a file is modified, paths use '/' between directories, however
+ # when a property is modified '\' is used on Windows. Make them the same
+ # otherwise the file shows up twice.
+ temp_filename = temp_filename.strip().replace('\\', '/')
+ if temp_filename != filename:
+ # File has property changes but no modifications, create a new diff.
+ new_filename = temp_filename
+ if new_filename:
+ if filename and diff:
+ patches.append((filename, ''.join(diff)))
+ filename = new_filename
+ diff = [line]
+ continue
+ if diff is not None:
+ diff.append(line)
+ if filename and diff:
+ patches.append((filename, ''.join(diff)))
+ return patches
+
+
+def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
+ """Uploads a separate patch for each file in the diff output.
+
+ Returns a list of [patch_key, filename] for each file.
+ """
+ patches = SplitPatch(data)
+ rv = []
+ for patch in patches:
+ if len(patch[1]) > MAX_UPLOAD_SIZE:
+ print ("Not uploading the patch for " + patch[0] +
+ " because the file is too large.")
+ continue
+ form_fields = [("filename", patch[0])]
+ if not options.download_base:
+ form_fields.append(("content_upload", "1"))
+ files = [("data", "data.diff", patch[1])]
+ ctype, body = EncodeMultipartFormData(form_fields, files)
+ url = "/%d/upload_patch/%d" % (int(issue), int(patchset))
+ print "Uploading patch for " + patch[0]
+ response_body = rpc_server.Send(url, body, content_type=ctype)
+ lines = response_body.splitlines()
+ if not lines or lines[0] != "OK":
+ StatusUpdate(" --> %s" % response_body)
+ sys.exit(1)
+ rv.append([lines[1], patch[0]])
+ return rv
+
+
+def GuessVCSName(options):
+ """Helper to guess the version control system.
+
+ This examines the current directory, guesses which VersionControlSystem
+ we're using, and returns an string indicating which VCS is detected.
+
+ Returns:
+ A pair (vcs, output). vcs is a string indicating which VCS was detected
+ and is one of VCS_GIT, VCS_MERCURIAL, VCS_SUBVERSION, VCS_PERFORCE,
+ VCS_CVS, or VCS_UNKNOWN.
+ Since local perforce repositories can't be easily detected, this method
+ will only guess VCS_PERFORCE if any perforce options have been specified.
+ output is a string containing any interesting output from the vcs
+ detection routine, or None if there is nothing interesting.
+ """
+ for attribute, value in options.__dict__.iteritems():
+ if attribute.startswith("p4") and value != None:
+ return (VCS_PERFORCE, None)
+
+ def RunDetectCommand(vcs_type, command):
+ """Helper to detect VCS by executing command.
+
+ Returns:
+ A pair (vcs, output) or None. Throws exception on error.
+ """
+ try:
+ out, returncode = RunShellWithReturnCode(command)
+ if returncode == 0:
+ return (vcs_type, out.strip())
+ except OSError, (errcode, message):
+ if errcode != errno.ENOENT: # command not found code
+ raise
+
+ # Mercurial has a command to get the base directory of a repository
+ # Try running it, but don't die if we don't have hg installed.
+ # NOTE: we try Mercurial first as it can sit on top of an SVN working copy.
+ res = RunDetectCommand(VCS_MERCURIAL, ["hg", "root"])
+ if res != None:
+ return res
+
+ # Subversion from 1.7 has a single centralized .svn folder
+ # ( see http://subversion.apache.org/docs/release-notes/1.7.html#wc-ng )
+ # That's why we use 'svn info' instead of checking for .svn dir
+ res = RunDetectCommand(VCS_SUBVERSION, ["svn", "info"])
+ if res != None:
+ return res
+
+ # Git has a command to test if you're in a git tree.
+ # Try running it, but don't die if we don't have git installed.
+ res = RunDetectCommand(VCS_GIT, ["git", "rev-parse",
+ "--is-inside-work-tree"])
+ if res != None:
+ return res
+
+ # detect CVS repos use `cvs status && $? == 0` rules
+ res = RunDetectCommand(VCS_CVS, ["cvs", "status"])
+ if res != None:
+ return res
+
+ return (VCS_UNKNOWN, None)
+
+
+def GuessVCS(options):
+ """Helper to guess the version control system.
+
+ This verifies any user-specified VersionControlSystem (by command line
+ or environment variable). If the user didn't specify one, this examines
+ the current directory, guesses which VersionControlSystem we're using,
+ and returns an instance of the appropriate class. Exit with an error
+ if we can't figure it out.
+
+ Returns:
+ A VersionControlSystem instance. Exits if the VCS can't be guessed.
+ """
+ vcs = options.vcs
+ if not vcs:
+ vcs = os.environ.get("CODEREVIEW_VCS")
+ if vcs:
+ v = VCS_ABBREVIATIONS.get(vcs.lower())
+ if v is None:
+ ErrorExit("Unknown version control system %r specified." % vcs)
+ (vcs, extra_output) = (v, None)
+ else:
+ (vcs, extra_output) = GuessVCSName(options)
+
+ if vcs == VCS_MERCURIAL:
+ if extra_output is None:
+ extra_output = RunShell(["hg", "root"]).strip()
+ return MercurialVCS(options, extra_output)
+ elif vcs == VCS_SUBVERSION:
+ return SubversionVCS(options)
+ elif vcs == VCS_PERFORCE:
+ return PerforceVCS(options)
+ elif vcs == VCS_GIT:
+ return GitVCS(options)
+ elif vcs == VCS_CVS:
+ return CVSVCS(options)
+
+ ErrorExit(("Could not guess version control system. "
+ "Are you in a working copy directory?"))
+
+
+def CheckReviewer(reviewer):
+ """Validate a reviewer -- either a nickname or an email addres.
+
+ Args:
+ reviewer: A nickname or an email address.
+
+ Calls ErrorExit() if it is an invalid email address.
+ """
+ if "@" not in reviewer:
+ return # Assume nickname
+ parts = reviewer.split("@")
+ if len(parts) > 2:
+ ErrorExit("Invalid email address: %r" % reviewer)
+ assert len(parts) == 2
+ if "." not in parts[1]:
+ ErrorExit("Invalid email address: %r" % reviewer)
+
+
+def LoadSubversionAutoProperties():
+ """Returns the content of [auto-props] section of Subversion's config file as
+ a dictionary.
+
+ Returns:
+ A dictionary whose key-value pair corresponds the [auto-props] section's
+ key-value pair.
+ In following cases, returns empty dictionary:
+ - config file doesn't exist, or
+ - 'enable-auto-props' is not set to 'true-like-value' in [miscellany].
+ """
+ if os.name == 'nt':
+ subversion_config = os.environ.get("APPDATA") + "\\Subversion\\config"
+ else:
+ subversion_config = os.path.expanduser("~/.subversion/config")
+ if not os.path.exists(subversion_config):
+ return {}
+ config = ConfigParser.ConfigParser()
+ config.read(subversion_config)
+ if (config.has_section("miscellany") and
+ config.has_option("miscellany", "enable-auto-props") and
+ config.getboolean("miscellany", "enable-auto-props") and
+ config.has_section("auto-props")):
+ props = {}
+ for file_pattern in config.options("auto-props"):
+ props[file_pattern] = ParseSubversionPropertyValues(
+ config.get("auto-props", file_pattern))
+ return props
+ else:
+ return {}
+
+def ParseSubversionPropertyValues(props):
+ """Parse the given property value which comes from [auto-props] section and
+ returns a list whose element is a (svn_prop_key, svn_prop_value) pair.
+
+ See the following doctest for example.
+
+ >>> ParseSubversionPropertyValues('svn:eol-style=LF')
+ [('svn:eol-style', 'LF')]
+ >>> ParseSubversionPropertyValues('svn:mime-type=image/jpeg')
+ [('svn:mime-type', 'image/jpeg')]
+ >>> ParseSubversionPropertyValues('svn:eol-style=LF;svn:executable')
+ [('svn:eol-style', 'LF'), ('svn:executable', '*')]
+ """
+ key_value_pairs = []
+ for prop in props.split(";"):
+ key_value = prop.split("=")
+ assert len(key_value) <= 2
+ if len(key_value) == 1:
+ # If value is not given, use '*' as a Subversion's convention.
+ key_value_pairs.append((key_value[0], "*"))
+ else:
+ key_value_pairs.append((key_value[0], key_value[1]))
+ return key_value_pairs
+
+
+def GetSubversionPropertyChanges(filename):
+ """Return a Subversion's 'Property changes on ...' string, which is used in
+ the patch file.
+
+ Args:
+ filename: filename whose property might be set by [auto-props] config.
+
+ Returns:
+ A string like 'Property changes on |filename| ...' if given |filename|
+ matches any entries in [auto-props] section. None, otherwise.
+ """
+ global svn_auto_props_map
+ if svn_auto_props_map is None:
+ svn_auto_props_map = LoadSubversionAutoProperties()
+
+ all_props = []
+ for file_pattern, props in svn_auto_props_map.items():
+ if fnmatch.fnmatch(filename, file_pattern):
+ all_props.extend(props)
+ if all_props:
+ return FormatSubversionPropertyChanges(filename, all_props)
+ return None
+
+
+def FormatSubversionPropertyChanges(filename, props):
+ """Returns Subversion's 'Property changes on ...' strings using given filename
+ and properties.
+
+ Args:
+ filename: filename
+ props: A list whose element is a (svn_prop_key, svn_prop_value) pair.
+
+ Returns:
+ A string which can be used in the patch file for Subversion.
+
+ See the following doctest for example.
+
+ >>> print FormatSubversionPropertyChanges('foo.cc', [('svn:eol-style', 'LF')])
+ Property changes on: foo.cc
+ ___________________________________________________________________
+ Added: svn:eol-style
+ + LF
+ <BLANKLINE>
+ """
+ prop_changes_lines = [
+ "Property changes on: %s" % filename,
+ "___________________________________________________________________"]
+ for key, value in props:
+ prop_changes_lines.append("Added: " + key)
+ prop_changes_lines.append(" + " + value)
+ return "\n".join(prop_changes_lines) + "\n"
+
+
+def RealMain(argv, data=None):
+ """The real main function.
+
+ Args:
+ argv: Command line arguments.
+ data: Diff contents. If None (default) the diff is generated by
+ the VersionControlSystem implementation returned by GuessVCS().
+
+ Returns:
+ A 2-tuple (issue id, patchset id).
+ The patchset id is None if the base files are not uploaded by this
+ script (applies only to SVN checkouts).
+ """
+ options, args = parser.parse_args(argv[1:])
+ if options.help:
+ if options.verbose < 2:
+ # hide Perforce options
+ parser.epilog = "Use '--help -v' to show additional Perforce options."
+ parser.option_groups.remove(parser.get_option_group('--p4_port'))
+ parser.print_help()
+ sys.exit(0)
+
+ global verbosity
+ verbosity = options.verbose
+ if verbosity >= 3:
+ logging.getLogger().setLevel(logging.DEBUG)
+ elif verbosity >= 2:
+ logging.getLogger().setLevel(logging.INFO)
+
+ vcs = GuessVCS(options)
+
+ base = options.base_url
+ if isinstance(vcs, SubversionVCS):
+ # Guessing the base field is only supported for Subversion.
+ # Note: Fetching base files may become deprecated in future releases.
+ guessed_base = vcs.GuessBase(options.download_base)
+ if base:
+ if guessed_base and base != guessed_base:
+ print "Using base URL \"%s\" from --base_url instead of \"%s\"" % \
+ (base, guessed_base)
+ else:
+ base = guessed_base
+
+ if not base and options.download_base:
+ options.download_base = True
+ logging.info("Enabled upload of base file")
+ if not options.assume_yes:
+ vcs.CheckForUnknownFiles()
+ if data is None:
+ data = vcs.GenerateDiff(args)
+ data = vcs.PostProcessDiff(data)
+ if options.print_diffs:
+ print "Rietveld diff start:*****"
+ print data
+ print "Rietveld diff end:*****"
+ files = vcs.GetBaseFiles(data)
+ if verbosity >= 1:
+ print "Upload server:", options.server, "(change with -s/--server)"
+ rpc_server = GetRpcServer(options.server,
+ options.email,
+ options.host,
+ options.save_cookies,
+ options.account_type)
+ form_fields = []
+
+ repo_guid = vcs.GetGUID()
+ if repo_guid:
+ form_fields.append(("repo_guid", repo_guid))
+ if base:
+ b = urlparse.urlparse(base)
+ username, netloc = urllib.splituser(b.netloc)
+ if username:
+ logging.info("Removed username from base URL")
+ base = urlparse.urlunparse((b.scheme, netloc, b.path, b.params,
+ b.query, b.fragment))
+ form_fields.append(("base", base))
+ if options.issue:
+ form_fields.append(("issue", str(options.issue)))
+ if options.email:
+ form_fields.append(("user", options.email))
+ if options.reviewers:
+ for reviewer in options.reviewers.split(','):
+ CheckReviewer(reviewer)
+ form_fields.append(("reviewers", options.reviewers))
+ if options.cc:
+ for cc in options.cc.split(','):
+ CheckReviewer(cc)
+ form_fields.append(("cc", options.cc))
+
+ # Process --message, --title and --file.
+ message = options.message or ""
+ title = options.title or ""
+ if options.file:
+ if options.message:
+ ErrorExit("Can't specify both message and message file options")
+ file = open(options.file, 'r')
+ message = file.read()
+ file.close()
+ if options.issue:
+ prompt = "Title describing this patch set: "
+ else:
+ prompt = "New issue subject: "
+ title = (
+ title or message.split('\n', 1)[0].strip() or raw_input(prompt).strip())
+ if not title and not options.issue:
+ ErrorExit("A non-empty title is required for a new issue")
+ # For existing issues, it's fine to give a patchset an empty name. Rietveld
+ # doesn't accept that so use a whitespace.
+ title = title or " "
+ if len(title) > 100:
+ title = title[:99] + '…'
+ if title and not options.issue:
+ message = message or title
+
+ form_fields.append(("subject", title))
+ # If it's a new issue send message as description. Otherwise a new
+ # message is created below on upload_complete.
+ if message and not options.issue:
+ form_fields.append(("description", message))
+
+ # Send a hash of all the base file so the server can determine if a copy
+ # already exists in an earlier patchset.
+ base_hashes = ""
+ for file, info in files.iteritems():
+ if not info[0] is None:
+ checksum = md5(info[0]).hexdigest()
+ if base_hashes:
+ base_hashes += "|"
+ base_hashes += checksum + ":" + file
+ form_fields.append(("base_hashes", base_hashes))
+ if options.private:
+ if options.issue:
+ print "Warning: Private flag ignored when updating an existing issue."
+ else:
+ form_fields.append(("private", "1"))
+ if options.send_patch:
+ options.send_mail = True
+ if not options.download_base:
+ form_fields.append(("content_upload", "1"))
+ if len(data) > MAX_UPLOAD_SIZE:
+ print "Patch is large, so uploading file patches separately."
+ uploaded_diff_file = []
+ form_fields.append(("separate_patches", "1"))
+ else:
+ uploaded_diff_file = [("data", "data.diff", data)]
+ ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file)
+ response_body = rpc_server.Send("/upload", body, content_type=ctype)
+ patchset = None
+ if not options.download_base or not uploaded_diff_file:
+ lines = response_body.splitlines()
+ if len(lines) >= 2:
+ msg = lines[0]
+ patchset = lines[1].strip()
+ patches = [x.split(" ", 1) for x in lines[2:]]
+ else:
+ msg = response_body
+ else:
+ msg = response_body
+ StatusUpdate(msg)
+ if not response_body.startswith("Issue created.") and \
+ not response_body.startswith("Issue updated."):
+ sys.exit(0)
+ issue = msg[msg.rfind("/")+1:]
+
+ if not uploaded_diff_file:
+ result = UploadSeparatePatches(issue, rpc_server, patchset, data, options)
+ if not options.download_base:
+ patches = result
+
+ if not options.download_base:
+ vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files)
+
+ payload = {} # payload for final request
+ if options.send_mail:
+ payload["send_mail"] = "yes"
+ if options.send_patch:
+ payload["attach_patch"] = "yes"
+ if options.issue and message:
+ payload["message"] = message
+ payload = urllib.urlencode(payload)
+ rpc_server.Send("/" + issue + "/upload_complete/" + (patchset or ""),
+ payload=payload)
+ return issue, patchset
+
+
+def main():
+ try:
+ logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:"
+ "%(lineno)s %(message)s "))
+ os.environ['LC_ALL'] = 'C'
+ RealMain(sys.argv)
+ except KeyboardInterrupt:
+ print
+ StatusUpdate("Interrupted.")
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/chromium/tools/swarm_client/tools/harvest_buildbot.py b/chromium/tools/swarm_client/tools/harvest_buildbot.py
new file mode 100755
index 00000000000..504962e16a5
--- /dev/null
+++ b/chromium/tools/swarm_client/tools/harvest_buildbot.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Harvest data on the Try Server.
+
+Please use sparingly. Large values for horizon will trash the Try Server memory.
+"""
+
+import os
+import optparse
+import sys
+
+
+def get_failed_builds(builder, horizon):
+ """Constructs the list of failed builds."""
+ builder.builds.cache()
+ return [
+ builder.builds[i] for i in xrange(-horizon, 0)
+ if not builder.builds[i].simplified_result
+ ]
+
+
+def get_parent_build(build):
+ """Returns the parent build for a triggered build."""
+ parent_buildername = build.properties_as_dict['parent_buildername']
+ parent_builder = build.builders[parent_buildername]
+ return parent_builder.builds[build.properties_as_dict['parent_buildnumber']]
+
+
+def parse(b, horizon):
+ print('Processing last %d entries' % horizon)
+ failed_builds = get_failed_builds(b.builders['swarm_triggered'], horizon)
+ rate = 100. * (1. - float(len(failed_builds)) / float(horizon))
+ print('Success: %3.1f%%' % rate)
+
+ NO_KEY = 'Warning: Unable to find any tests with the name'
+ HTTP_404 = 'threw HTTP Error 404: Not Found'
+ for build in failed_builds:
+ print('%s/%d on %s' % (build.builder.name, build.number, build.slave.name))
+ swarm_trigger_tests = build.steps['swarm_trigger_tests']
+ base_unittests = build.steps['base_unittests']
+ fail = ''
+ if swarm_trigger_tests.simplified_result:
+ fail = 'buildbot failed to pass arguments'
+ elif not swarm_trigger_tests.stdio:
+ fail = 'old swarm_trigger_step.py version'
+ else:
+ stdio = base_unittests.stdio
+ if NO_KEY in stdio:
+ fail = 'Failed to retrieve keys.'
+ elif HTTP_404 in stdio:
+ fail = 'Failed to retrieve keys with 404.'
+
+ if fail:
+ print(' Triggering failed: %s' % fail)
+ else:
+ # Print the first few lines.
+ lines = base_unittests.stdio.splitlines()[:15]
+ print('\n'.join(' ' + l for l in lines))
+ print(' %s %s %s %s' % (
+ build.properties_as_dict['use_swarm_client_revision'],
+ build.properties_as_dict['swarm_hashes'],
+ build.properties_as_dict.get('use_swarm_client_revision'),
+ build.properties_as_dict.get('testfilter')))
+
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option('-b', '--buildbot_json', help='path to buildbot_json.py')
+ parser.add_option(
+ '-u', '--url',
+ default='http://build.chromium.org/p/tryserver.chromium/',
+ help='server url, default: %default')
+ parser.add_option('-H', '--horizon', default=100, type='int')
+ options, args = parser.parse_args(None)
+ if args:
+ parser.error('Unsupported args: %s' % args)
+
+ if options.horizon < 10 or options.horizon > 2000:
+ parser.error('Use reasonable --horizon value')
+
+ if options.buildbot_json:
+ options.buildbot_json = os.path.abspath(options.buildbot_json)
+ if not os.path.isdir(options.buildbot_json):
+ parser.error('Pass a valid directory path to --buildbot_json')
+ sys.path.insert(0, options.buildbot_json)
+
+ try:
+ import buildbot_json # pylint: disable=F0401
+ except ImportError:
+ parser.error('Pass a directory path to buildbot_json.py with -b')
+
+ b = buildbot_json.Buildbot(options.url)
+ parse(b, options.horizon)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/tools/run_a_test.isolate b/chromium/tools/swarm_client/tools/run_a_test.isolate
new file mode 100644
index 00000000000..009199dbcae
--- /dev/null
+++ b/chromium/tools/swarm_client/tools/run_a_test.isolate
@@ -0,0 +1,13 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'variables': {
+ 'command': [
+ '<(TEST_EXECUTABLE)',
+ ],
+ 'isolate_dependency_untracked': [
+ '../',
+ ],
+ },
+}
diff --git a/chromium/tools/swarm_client/tools/run_swarm_tests_on_swarm.py b/chromium/tools/swarm_client/tools/run_swarm_tests_on_swarm.py
new file mode 100755
index 00000000000..b3891c57a4c
--- /dev/null
+++ b/chromium/tools/swarm_client/tools/run_swarm_tests_on_swarm.py
@@ -0,0 +1,245 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs the whole set unit tests on swarm."""
+
+import datetime
+import glob
+import getpass
+import hashlib
+import logging
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+ROOT_DIR = os.path.dirname(BASE_DIR)
+
+sys.path.insert(0, ROOT_DIR)
+
+import run_test_cases
+
+
+# Mapping of the sys.platform value into Swarm OS value.
+OSES = {'win32': 'win', 'linux2': 'linux', 'darwin': 'mac'}
+
+
+# Default servers.
+SWARM_SERVER = 'https://chromium-swarm-dev.appspot.com/'
+ISOLATE_SERVER = 'https://isolateserver-dev.appspot.com/'
+
+
+class Runner(object):
+ def __init__(self, isolate_server, swarm_server, add_task, progress, tempdir):
+ self.isolate_server = isolate_server
+ self.swarm_server = swarm_server
+ self.add_task = add_task
+ self.progress = progress
+ self.tempdir = tempdir
+ self.prefix = (
+ getpass.getuser() + '-' + datetime.datetime.now().isoformat() + '-')
+
+ @staticmethod
+ def _call(args):
+ start = time.time()
+ proc = subprocess.Popen(
+ [sys.executable] + args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ cwd=ROOT_DIR)
+ stdout = proc.communicate()[0]
+ return proc.returncode, stdout, time.time() - start
+
+ def archive(self, test, platform):
+ # Put the .isolated files in a temporary directory. This is simply done so
+ # the current directory doesn't have the following files created:
+ # - swarm_client_tests.isolated
+ # - swarm_client_tests.isolated.state
+ test_name = os.path.basename(test)
+ handle, isolated = tempfile.mkstemp(
+ dir=self.tempdir, prefix='run_swarm_tests_on_swarm_',
+ suffix='.isolated')
+ os.close(handle)
+ try:
+ returncode, stdout, duration = self._call(
+ [
+ 'isolate.py',
+ 'hashtable',
+ '--isolate', os.path.join(BASE_DIR, 'run_a_test.isolate'),
+ '--isolated', isolated,
+ '--outdir', self.isolate_server,
+ '--variable', 'TEST_EXECUTABLE', test,
+ '--variable', 'OS', OSES[platform],
+ ])
+ step_name = '%s/%s (%3.2fs)' % (platform, test_name, duration)
+ if returncode:
+ self.progress.update_item(
+ 'Failed to archive %s\n%s' % (step_name, stdout), True, False)
+ else:
+ hash_value = hashlib.sha1(open(isolated, 'rb').read()).hexdigest()
+ logging.info('%s: %s', step_name, hash_value)
+ self.progress.update_item('Archived %s' % step_name, True, False)
+ self.add_task(0, self.trigger, test, platform, hash_value)
+ finally:
+ try:
+ os.remove(isolated)
+ except OSError:
+ logging.debug('%s was already deleted', isolated)
+ return None
+
+ def trigger(self, test, platform, hash_value):
+ test_name = os.path.basename(test)
+ returncode, stdout, duration = self._call(
+ [
+ 'swarm_trigger_step.py',
+ '--os_image', platform,
+ '--swarm-url', self.swarm_server,
+ '--test-name-prefix', self.prefix,
+ '--data-server', self.isolate_server,
+ '--run_from_hash',
+ # Isolated hash.
+ hash_value,
+ # Test name.
+ 'swarm_client_tests_%s_%s' % (platform, test_name),
+ # Number of shards.
+ '1',
+ # test filter.
+ '*',
+ ])
+ step_name = '%s/%s (%3.2fs)' % (platform, test_name, duration)
+ if returncode:
+ self.progress.update_item(
+ 'Failed to trigger %s\n%s' % (step_name, stdout), True, False)
+ else:
+ self.progress.update_item('Triggered %s' % step_name, True, False)
+ self.add_task(0, self.get_result, test, platform)
+ return None
+
+ def get_result(self, test, platform):
+ test_name = os.path.basename(test)
+ name = '%s_%s' % (platform, test_name)
+ returncode, stdout, duration = self._call(
+ [
+ 'swarm_get_results.py',
+ '--url', self.swarm_server,
+ self.prefix + 'swarm_client_tests_' + name,
+ ])
+ step_name = '%s/%s (%3.2fs)' % (platform, test_name, duration)
+ # Only print the output for failures, successes are unexciting.
+ if returncode:
+ self.progress.update_item(
+ 'Failed %s:\n%s' % (step_name, stdout), True, False)
+ return (test_name, platform, stdout)
+ self.progress.update_item('Passed %s' % step_name, True, False)
+ return None
+
+
+def run_swarm_tests_on_swarm(oses, tests, logs, isolate_server, swarm_server):
+ runs = len(tests) * len(oses)
+ total = 3 * runs
+ progress = run_test_cases.Progress(total)
+ progress.use_cr_only = False
+ tempdir = tempfile.mkdtemp(prefix='swarm_client_tests')
+ try:
+ with run_test_cases.ThreadPool(progress, runs, runs, total) as pool:
+ start = time.time()
+ runner = Runner(
+ isolate_server, swarm_server, pool.add_task, progress, tempdir)
+ for test in tests:
+ for platform in oses:
+ pool.add_task(0, runner.archive, test, platform)
+
+ failed_tests = pool.join()
+ duration = time.time() - start
+ print('')
+ finally:
+ shutil.rmtree(tempdir)
+
+ if logs:
+ os.makedirs(logs)
+ for test, platform, stdout in failed_tests:
+ name = '%s_%s' % (platform, os.path.basename(test))
+ with open(os.path.join(logs, name + '.log'), 'wb') as f:
+ f.write(stdout)
+
+ print('Completed in %3.2fs' % duration)
+ if failed_tests:
+ failed_tests_per_os = {}
+ for test, platform, _ in failed_tests:
+ failed_tests_per_os.setdefault(test, []).append(platform)
+ print('Detected the following failures:')
+ for test, platforms in failed_tests_per_os.iteritems():
+ print(' %s on %s' % (test, ', '.join(sorted(platforms))))
+ return bool(failed_tests)
+
+
+def main():
+ parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
+ parser.add_option(
+ '-i', '--isolate-server',
+ default=ISOLATE_SERVER,
+ help='Isolate server to use default:%default')
+ parser.add_option(
+ '-s', '--swarm-server',
+ default=SWARM_SERVER,
+ help='Isolate server to use default:%default')
+ parser.add_option(
+ '-l', '--logs',
+ help='Destination where to store the failure logs (recommended)')
+ parser.add_option('-o', '--os', help='Run tests only on this OS')
+ parser.add_option('-t', '--test', help='Run only this test')
+ parser.add_option('-v', '--verbose', action='store_true')
+ options, args = parser.parse_args()
+ if args:
+ parser.error('Unsupported argument %s' % args)
+ if options.verbose:
+ os.environ['ISOLATE_DEBUG'] = '1'
+
+ logging.basicConfig(level=logging.DEBUG if options.verbose else logging.ERROR)
+
+ # Note that the swarm and the isolate code use different strings for the
+ # different oses.
+ oses = OSES.keys()
+ tests = [
+ os.path.relpath(i, BASE_DIR)
+ for i in glob.iglob(os.path.join(ROOT_DIR, 'tests', '*_test.py'))
+ ]
+
+ if options.test:
+ valid_tests = sorted(map(os.path.basename, tests))
+ if not options.test in valid_tests:
+ parser.error(
+ '--test %s is unknown. Valid values are:\n%s' % (
+ options.test, '\n'.join(' ' + i for i in valid_tests)))
+ tests = [t for t in tests if t.endswith(os.path.sep + options.test)]
+
+ if options.os:
+ if options.os not in oses:
+ parser.error(
+ '--os %s is unknown. Valid values are %s' % (
+ options.os, ', '.join(sorted(oses))))
+ oses = [options.os]
+
+ if sys.platform in ('win32', 'cygwin'):
+ # If we are on Windows, don't generate the tests for Linux and Mac since
+ # they use symlinks and we can't create symlinks on windows.
+ oses = ['win32']
+ if options.os != 'win32':
+ print('Linux and Mac tests skipped since running on Windows.')
+
+ return run_swarm_tests_on_swarm(
+ oses,
+ tests,
+ options.logs,
+ options.isolate_server,
+ options.swarm_server)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/tools/swarm_cleanup.py b/chromium/tools/swarm_client/tools/swarm_cleanup.py
new file mode 100755
index 00000000000..f3280886b0a
--- /dev/null
+++ b/chromium/tools/swarm_client/tools/swarm_cleanup.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Cleans up a swarm slave after the tests have run."""
+
+import errno
+import glob
+import os
+import tempfile
+import time
+import shutil
+import subprocess
+import sys
+
+
+# This is copied from Chromium's project build/scripts/common/chromium_utils.py.
+def RemoveDirectory(*path):
+ """Recursively removes a directory, even if it's marked read-only.
+
+ Remove the directory located at *path, if it exists.
+
+ shutil.rmtree() doesn't work on Windows if any of the files or directories
+ are read-only, which svn repositories and some .svn files are. We need to
+ be able to force the files to be writable (i.e., deletable) as we traverse
+ the tree.
+
+ Even with all this, Windows still sometimes fails to delete a file, citing
+ a permission error (maybe something to do with antivirus scans or disk
+ indexing). The best suggestion any of the user forums had was to wait a
+ bit and try again, so we do that too. It's hand-waving, but sometimes it
+ works. :/
+ """
+ file_path = os.path.join(*path)
+ if not os.path.exists(file_path):
+ return
+
+ if sys.platform == 'win32':
+ # Give up and use cmd.exe's rd command.
+ file_path = os.path.normcase(file_path)
+ for _ in xrange(3):
+ if not subprocess.call(['cmd.exe', '/c', 'rd', '/q', '/s', file_path]):
+ break
+ time.sleep(3)
+ return
+
+ def RemoveWithRetry_non_win(rmfunc, path):
+ if os.path.islink(path):
+ return os.remove(path)
+ else:
+ return rmfunc(path)
+
+ remove_with_retry = RemoveWithRetry_non_win
+
+ def RmTreeOnError(function, path, excinfo):
+ """This works around a problem whereby python 2.x on Windows has no ability
+ to check for symbolic links. os.path.islink() always returns False but
+ shutil.rmtree() will fail if invoked on a symbolic link whose target was
+ deleted before the link. E.g., reproduce like this:
+ > mkdir test
+ > mkdir test\1
+ > mklink /D test\current test\1
+ > python -c "import shutl; shutil.rmtree('test')"
+ To avoid this issue, we pass this error-handling function to rmtree. If we
+ see the exact sort of failure, we ignore it. All other failures we
+ re-raise.
+ """
+ exception_type = excinfo[0]
+ exception_value = excinfo[1]
+ # If shutil.rmtree encounters a symbolic link on Windows, os.listdir will
+ # fail with a WindowsError exception with an ENOENT errno (i.e., file not
+ # found). We'll ignore that error. Note that WindowsError is not defined
+ # for non-Windows platforms, so we use OSError (of which it is a subclass)
+ # to avoid lint complaints about an undefined global on non-Windows
+ # platforms.
+ if (function is os.listdir) and issubclass(exception_type, OSError):
+ if exception_value.errno == errno.ENOENT:
+ # File does not exist, and we're trying to delete, so we can ignore the
+ # failure.
+ print 'WARNING: Failed to list %s during rmtree. Ignoring.\n' % path
+ else:
+ raise
+ else:
+ raise
+
+ for root, dirs, files in os.walk(file_path, topdown=False):
+ # For POSIX: making the directory writable guarantees removability.
+ # Windows will ignore the non-read-only bits in the chmod value.
+ os.chmod(root, 0770)
+ for name in files:
+ remove_with_retry(os.remove, os.path.join(root, name))
+ for name in dirs:
+ remove_with_retry(lambda p: shutil.rmtree(p, onerror=RmTreeOnError),
+ os.path.join(root, name))
+
+ remove_with_retry(os.rmdir, file_path)
+
+
+def delete(filename):
+ try:
+ if os.path.isdir(filename):
+ RemoveDirectory(filename)
+ else:
+ os.remove(filename)
+ except OSError:
+ pass
+
+
+def main():
+ for filename in glob.iglob('*.zip'):
+ delete(filename)
+
+ # Clear the temp directory.
+ for filename in glob.iglob(os.path.join(tempfile.gettempdir(), '*')):
+ delete(filename)
+
+ # Clears up stale run_isolated.py temporary directories.
+ for filename in glob.iglob('run_tha_test*'):
+ delete(filename)
+ print ''
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/tools/zip_profiler.py b/chromium/tools/swarm_client/tools/zip_profiler.py
new file mode 100755
index 00000000000..db1ba45fef0
--- /dev/null
+++ b/chromium/tools/swarm_client/tools/zip_profiler.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Profiler to compare various compression levels with regards to speed
+and final size when compressing the full set of files from a given
+isolated file.
+"""
+
+import bz2
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+import zlib
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+sys.path.insert(0, ROOT_DIR)
+
+import run_isolated
+
+
+def zip_file(compressor_constructor, compression_level, filename):
+ compressed_size = 0
+ compressor = compressor_constructor(compression_level)
+ with open(filename, 'rb') as f:
+ while True:
+ chunk = f.read(run_isolated.ZIPPED_FILE_CHUNK)
+ if not chunk:
+ break
+ compressed_size += len(compressor.compress(f.read()))
+ compressed_size += len(compressor.flush())
+
+ return compressed_size
+
+
+def zip_directory(compressor_constructor, compression_level, root_dir):
+ compressed_size = 0
+ for root, _, files in os.walk(root_dir):
+ compressed_size += sum(zip_file(compressor_constructor, compression_level,
+ os.path.join(root, name))
+ for name in files)
+ return compressed_size
+
+
+def profile_compress(zip_module_name, compressor_constructor,
+ compression_range, compress_func, compress_target):
+ for i in compression_range:
+ start_time = time.time()
+ compressed_size = compress_func(compressor_constructor, i, compress_target)
+ end_time = time.time()
+
+ print('%4s at compression level %s, total size %11d, time taken %6.3f' %
+ (zip_module_name, i, compressed_size, end_time - start_time))
+
+
+def tree_files(root_dir):
+ file_set = {}
+ for root, _, files in os.walk(root_dir):
+ for name in files:
+ filename = os.path.join(root, name)
+ file_set[filename] = os.stat(filename).st_size
+
+ return file_set
+
+
+def main():
+ run_isolated.disable_buffering()
+ parser = optparse.OptionParser()
+ parser.add_option('-s', '--isolated', help='.isolated file to profile with.')
+ parser.add_option('--largest_files', type='int',
+ help='If this is set, instead of compressing all the '
+ 'files, only the large n files will be compressed')
+ options, args = parser.parse_args()
+
+ if args:
+ parser.error('Unknown args passed in; %s' % args)
+ if not options.isolated:
+ parser.error('The .isolated file must be given.')
+
+ temp_dir = None
+ try:
+ temp_dir = tempfile.mkdtemp()
+
+ # Create a directory of the required files
+ subprocess.check_call([os.path.join(ROOT_DIR, 'isolate.py'),
+ 'remap',
+ '-s', options.isolated,
+ '--outdir', temp_dir])
+
+ file_set = tree_files(temp_dir)
+
+ if options.largest_files:
+ sorted_by_size = sorted(file_set.iteritems(), key=lambda x: x[1],
+ reverse=True)
+ files_to_compress = sorted_by_size[:options.largest_files]
+
+ for filename, size in files_to_compress:
+ print('Compressing %s, uncompressed size %d' % (filename, size))
+
+ profile_compress('zlib', zlib.compressobj, range(10), zip_file,
+ filename)
+ profile_compress('bz2', bz2.BZ2Compressor, range(1, 10), zip_file,
+ filename)
+ else:
+ print('Number of files: %s' % len(file_set))
+ print('Total size: %s' % sum(file_set.itervalues()))
+
+ # Profile!
+ profile_compress('zlib', zlib.compressobj, range(10), zip_directory,
+ temp_dir)
+ profile_compress('bz2', bz2.BZ2Compressor, range(1, 10), zip_directory,
+ temp_dir)
+ finally:
+ shutil.rmtree(temp_dir)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/swarm_client/trace_inputs.py b/chromium/tools/swarm_client/trace_inputs.py
new file mode 100755
index 00000000000..dd9c8045dbe
--- /dev/null
+++ b/chromium/tools/swarm_client/trace_inputs.py
@@ -0,0 +1,3868 @@
+#!/usr/bin/env python
+# coding=utf-8
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Traces an executable and its child processes and extract the files accessed
+by them.
+
+The implementation uses OS-specific API. The native Kernel logger and the ETL
+interface is used on Windows. Dtrace is used on OSX. Strace is used otherwise.
+The OS-specific implementation is hidden in an 'API' interface.
+
+The results are embedded in a Results instance. The tracing is done in two
+phases, the first is to do the actual trace and generate an
+implementation-specific log file. Then the log file is parsed to extract the
+information, including the individual child processes and the files accessed
+from the log.
+"""
+
+import codecs
+import csv
+import errno
+import getpass
+import glob
+import json
+import logging
+import optparse
+import os
+import re
+import stat
+import subprocess
+import sys
+import tempfile
+import threading
+import time
+import unicodedata
+import weakref
+
+## OS-specific imports
+
+if sys.platform == 'win32':
+ from ctypes.wintypes import byref, create_unicode_buffer, c_int, c_wchar_p
+ from ctypes.wintypes import windll, FormatError # pylint: disable=E0611
+ from ctypes.wintypes import GetLastError # pylint: disable=E0611
+elif sys.platform == 'darwin':
+ import Carbon.File # pylint: disable=F0401
+ import MacOS # pylint: disable=F0401
+
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+ROOT_DIR = os.path.dirname(os.path.dirname(BASE_DIR))
+
+
+class TracingFailure(Exception):
+ """An exception occured during tracing."""
+ def __init__(self, description, pid, line_number, line, *args):
+ super(TracingFailure, self).__init__(
+ description, pid, line_number, line, *args)
+ self.description = description
+ self.pid = pid
+ self.line_number = line_number
+ self.line = line
+ self.extra = args
+
+ def __str__(self):
+ out = self.description
+ if self.pid:
+ out += '\npid: %d' % self.pid
+ if self.line_number:
+ out += '\nline: %d' % self.line_number
+ if self.line:
+ out += '\n%s' % self.line
+ if self.extra:
+ out += '\n' + ', '.join(map(str, filter(None, self.extra)))
+ return out
+
+
+## OS-specific functions
+
+if sys.platform == 'win32':
+ def QueryDosDevice(drive_letter):
+ """Returns the Windows 'native' path for a DOS drive letter."""
+ assert re.match(r'^[a-zA-Z]:$', drive_letter), drive_letter
+ assert isinstance(drive_letter, unicode)
+ # Guesswork. QueryDosDeviceW never returns the required number of bytes.
+ chars = 1024
+ drive_letter = drive_letter
+ p = create_unicode_buffer(chars)
+ if 0 == windll.kernel32.QueryDosDeviceW(drive_letter, p, chars):
+ err = GetLastError()
+ if err:
+ # pylint: disable=E0602
+ msg = u'QueryDosDevice(%s): %s (%d)' % (
+ drive_letter, FormatError(err), err)
+ raise WindowsError(err, msg.encode('utf-8'))
+ return p.value
+
+
+ def GetShortPathName(long_path):
+ """Returns the Windows short path equivalent for a 'long' path."""
+ assert isinstance(long_path, unicode), repr(long_path)
+ # Adds '\\\\?\\' when given an absolute path so the MAX_PATH (260) limit is
+ # not enforced.
+ if os.path.isabs(long_path) and not long_path.startswith('\\\\?\\'):
+ long_path = '\\\\?\\' + long_path
+ chars = windll.kernel32.GetShortPathNameW(long_path, None, 0)
+ if chars:
+ p = create_unicode_buffer(chars)
+ if windll.kernel32.GetShortPathNameW(long_path, p, chars):
+ return p.value
+
+ err = GetLastError()
+ if err:
+ # pylint: disable=E0602
+ msg = u'GetShortPathName(%s): %s (%d)' % (
+ long_path, FormatError(err), err)
+ raise WindowsError(err, msg.encode('utf-8'))
+
+
+ def GetLongPathName(short_path):
+ """Returns the Windows long path equivalent for a 'short' path."""
+ assert isinstance(short_path, unicode)
+ # Adds '\\\\?\\' when given an absolute path so the MAX_PATH (260) limit is
+ # not enforced.
+ if os.path.isabs(short_path) and not short_path.startswith('\\\\?\\'):
+ short_path = '\\\\?\\' + short_path
+ chars = windll.kernel32.GetLongPathNameW(short_path, None, 0)
+ if chars:
+ p = create_unicode_buffer(chars)
+ if windll.kernel32.GetLongPathNameW(short_path, p, chars):
+ return p.value
+
+ err = GetLastError()
+ if err:
+ # pylint: disable=E0602
+ msg = u'GetLongPathName(%s): %s (%d)' % (
+ short_path, FormatError(err), err)
+ raise WindowsError(err, msg.encode('utf-8'))
+
+
+ def get_current_encoding():
+ """Returns the 'ANSI' code page associated to the process."""
+ return 'cp%d' % int(windll.kernel32.GetACP())
+
+
+ class DosDriveMap(object):
+ """Maps \Device\HarddiskVolumeN to N: on Windows."""
+ # Keep one global cache.
+ _MAPPING = {}
+
+ def __init__(self):
+ """Lazy loads the cache."""
+ if not self._MAPPING:
+ # This is related to UNC resolver on windows. Ignore that.
+ self._MAPPING[u'\\Device\\Mup'] = None
+ self._MAPPING[u'\\SystemRoot'] = os.environ[u'SystemRoot']
+
+ for letter in (chr(l) for l in xrange(ord('C'), ord('Z')+1)):
+ try:
+ letter = u'%s:' % letter
+ mapped = QueryDosDevice(letter)
+ if mapped in self._MAPPING:
+ logging.warn(
+ ('Two drives: \'%s\' and \'%s\', are mapped to the same disk'
+ '. Drive letters are a user-mode concept and the kernel '
+ 'traces only have NT path, so all accesses will be '
+ 'associated with the first drive letter, independent of the '
+ 'actual letter used by the code') % (
+ self._MAPPING[mapped], letter))
+ else:
+ self._MAPPING[mapped] = letter
+ except WindowsError: # pylint: disable=E0602
+ pass
+
+ def to_win32(self, path):
+ """Converts a native NT path to Win32/DOS compatible path."""
+ match = re.match(r'(^\\Device\\[a-zA-Z0-9]+)(\\.*)?$', path)
+ if not match:
+ raise ValueError(
+ 'Can\'t convert %s into a Win32 compatible path' % path,
+ path)
+ if not match.group(1) in self._MAPPING:
+ # Unmapped partitions may be accessed by windows for the
+ # fun of it while the test is running. Discard these.
+ return None
+ drive = self._MAPPING[match.group(1)]
+ if not drive or not match.group(2):
+ return drive
+ return drive + match.group(2)
+
+
+ def isabs(path):
+ """Accepts X: as an absolute path, unlike python's os.path.isabs()."""
+ return os.path.isabs(path) or len(path) == 2 and path[1] == ':'
+
+
+ def find_item_native_case(root, item):
+ """Gets the native path case of a single item based at root_path."""
+ if item == '..':
+ return item
+
+ root = get_native_path_case(root)
+ return os.path.basename(get_native_path_case(os.path.join(root, item)))
+
+
+ def get_native_path_case(p):
+ """Returns the native path case for an existing file.
+
+ On Windows, removes any leading '\\?\'.
+ """
+ assert isinstance(p, unicode), repr(p)
+ if not isabs(p):
+ raise ValueError(
+ 'get_native_path_case(%r): Require an absolute path' % p, p)
+
+ # Make sure it is normalized to os.path.sep. Do not do it here to keep the
+ # function fast
+ assert '/' not in p, p
+ suffix = ''
+ count = p.count(':')
+ if count > 1:
+ # This means it has an alternate-data stream. There could be 3 ':', since
+ # it could be the $DATA datastream of an ADS. Split the whole ADS suffix
+ # off and add it back afterward. There is no way to know the native path
+ # case of an alternate data stream.
+ items = p.split(':')
+ p = ':'.join(items[0:2])
+ suffix = ''.join(':' + i for i in items[2:])
+
+ # TODO(maruel): Use os.path.normpath?
+ if p.endswith('.\\'):
+ p = p[:-2]
+
+ # Windows used to have an option to turn on case sensitivity on non Win32
+ # subsystem but that's out of scope here and isn't supported anymore.
+ # Go figure why GetShortPathName() is needed.
+ try:
+ out = GetLongPathName(GetShortPathName(p))
+ except OSError, e:
+ if e.args[0] in (2, 3, 5):
+ # The path does not exist. Try to recurse and reconstruct the path.
+ base = os.path.dirname(p)
+ rest = os.path.basename(p)
+ return os.path.join(get_native_path_case(base), rest)
+ raise
+ if out.startswith('\\\\?\\'):
+ out = out[4:]
+ # Always upper case the first letter since GetLongPathName() will return the
+ # drive letter in the case it was given.
+ return out[0].upper() + out[1:] + suffix
+
+
+ def CommandLineToArgvW(command_line):
+ """Splits a commandline into argv using CommandLineToArgvW()."""
+ # http://msdn.microsoft.com/library/windows/desktop/bb776391.aspx
+ size = c_int()
+ assert isinstance(command_line, unicode)
+ ptr = windll.shell32.CommandLineToArgvW(command_line, byref(size))
+ try:
+ return [arg for arg in (c_wchar_p * size.value).from_address(ptr)]
+ finally:
+ windll.kernel32.LocalFree(ptr)
+
+
+elif sys.platform == 'darwin':
+
+
+ # On non-windows, keep the stdlib behavior.
+ isabs = os.path.isabs
+
+
+ def _native_case(p):
+ """Gets the native path case. Warning: this function resolves symlinks."""
+ try:
+ rel_ref, _ = Carbon.File.FSPathMakeRef(p.encode('utf-8'))
+ # The OSX underlying code uses NFD but python strings are in NFC. This
+ # will cause issues with os.listdir() for example. Since the dtrace log
+ # *is* in NFC, normalize it here.
+ out = unicodedata.normalize(
+ 'NFC', rel_ref.FSRefMakePath().decode('utf-8'))
+ if p.endswith(os.path.sep) and not out.endswith(os.path.sep):
+ return out + os.path.sep
+ return out
+ except MacOS.Error, e:
+ if e.args[0] in (-43, -120):
+ # The path does not exist. Try to recurse and reconstruct the path.
+ # -43 means file not found.
+ # -120 means directory not found.
+ base = os.path.dirname(p)
+ rest = os.path.basename(p)
+ return os.path.join(_native_case(base), rest)
+ raise OSError(
+ e.args[0], 'Failed to get native path for %s' % p, p, e.args[1])
+
+
+ def _split_at_symlink_native(base_path, rest):
+ """Returns the native path for a symlink."""
+ base, symlink, rest = split_at_symlink(base_path, rest)
+ if symlink:
+ if not base_path:
+ base_path = base
+ else:
+ base_path = safe_join(base_path, base)
+ symlink = find_item_native_case(base_path, symlink)
+ return base, symlink, rest
+
+
+ def find_item_native_case(root_path, item):
+ """Gets the native path case of a single item based at root_path.
+
+ There is no API to get the native path case of symlinks on OSX. So it
+ needs to be done the slow way.
+ """
+ if item == '..':
+ return item
+
+ item = item.lower()
+ for element in os.listdir(root_path):
+ if element.lower() == item:
+ return element
+
+
+ def get_native_path_case(path):
+ """Returns the native path case for an existing file.
+
+ Technically, it's only HFS+ on OSX that is case preserving and
+ insensitive. It's the default setting on HFS+ but can be changed.
+ """
+ assert isinstance(path, unicode), repr(path)
+ if not isabs(path):
+ raise ValueError(
+ 'get_native_path_case(%r): Require an absolute path' % path, path)
+ if path.startswith('/dev'):
+ # /dev is not visible from Carbon, causing an exception.
+ return path
+
+ # Starts assuming there is no symlink along the path.
+ resolved = _native_case(path)
+ if path.lower() in (resolved.lower(), resolved.lower() + './'):
+ # This code path is incredibly faster.
+ logging.debug('get_native_path_case(%s) = %s' % (path, resolved))
+ return resolved
+
+ # There was a symlink, process it.
+ base, symlink, rest = _split_at_symlink_native(None, path)
+ assert symlink, (path, base, symlink, rest, resolved)
+ prev = base
+ base = safe_join(_native_case(base), symlink)
+ assert len(base) > len(prev)
+ while rest:
+ prev = base
+ relbase, symlink, rest = _split_at_symlink_native(base, rest)
+ base = safe_join(base, relbase)
+ assert len(base) > len(prev), (prev, base, symlink)
+ if symlink:
+ base = safe_join(base, symlink)
+ assert len(base) > len(prev), (prev, base, symlink)
+ # Make sure no symlink was resolved.
+ assert base.lower() == path.lower(), (base, path)
+ logging.debug('get_native_path_case(%s) = %s' % (path, base))
+ return base
+
+
+else: # OSes other than Windows and OSX.
+
+
+ # On non-windows, keep the stdlib behavior.
+ isabs = os.path.isabs
+
+
+ def find_item_native_case(root, item):
+ """Gets the native path case of a single item based at root_path."""
+ if item == '..':
+ return item
+
+ root = get_native_path_case(root)
+ return os.path.basename(get_native_path_case(os.path.join(root, item)))
+
+
+ def get_native_path_case(path):
+ """Returns the native path case for an existing file.
+
+ On OSes other than OSX and Windows, assume the file system is
+ case-sensitive.
+
+ TODO(maruel): This is not strictly true. Implement if necessary.
+ """
+ assert isinstance(path, unicode), repr(path)
+ if not isabs(path):
+ raise ValueError(
+ 'get_native_path_case(%r): Require an absolute path' % path, path)
+ # Give up on cygwin, as GetLongPathName() can't be called.
+ # Linux traces tends to not be normalized so use this occasion to normalize
+ # it. This function implementation already normalizes the path on the other
+ # OS so this needs to be done here to be coherent between OSes.
+ out = os.path.normpath(path)
+ if path.endswith(os.path.sep) and not out.endswith(os.path.sep):
+ return out + os.path.sep
+ return out
+
+
+if sys.platform != 'win32': # All non-Windows OSes.
+
+
+ def safe_join(*args):
+ """Joins path elements like os.path.join() but doesn't abort on absolute
+ path.
+
+ os.path.join('foo', '/bar') == '/bar'
+ but safe_join('foo', '/bar') == 'foo/bar'.
+ """
+ out = ''
+ for element in args:
+ if element.startswith(os.path.sep):
+ if out.endswith(os.path.sep):
+ out += element[1:]
+ else:
+ out += element
+ else:
+ if out.endswith(os.path.sep):
+ out += element
+ else:
+ out += os.path.sep + element
+ return out
+
+
+ def split_at_symlink(base_dir, relfile):
+ """Scans each component of relfile and cut the string at the symlink if
+ there is any.
+
+ Returns a tuple (base_path, symlink, rest), with symlink == rest == None if
+ not symlink was found.
+ """
+ if base_dir:
+ assert relfile
+ assert os.path.isabs(base_dir)
+ index = 0
+ else:
+ assert os.path.isabs(relfile)
+ index = 1
+
+ def at_root(rest):
+ if base_dir:
+ return safe_join(base_dir, rest)
+ return rest
+
+ while True:
+ try:
+ index = relfile.index(os.path.sep, index)
+ except ValueError:
+ index = len(relfile)
+ full = at_root(relfile[:index])
+ if os.path.islink(full):
+ # A symlink!
+ base = os.path.dirname(relfile[:index])
+ symlink = os.path.basename(relfile[:index])
+ rest = relfile[index:]
+ logging.debug(
+ 'split_at_symlink(%s, %s) -> (%s, %s, %s)' %
+ (base_dir, relfile, base, symlink, rest))
+ return base, symlink, rest
+ if index == len(relfile):
+ break
+ index += 1
+ return relfile, None, None
+
+
+class Unbuffered(object):
+ """Disable buffering on a file object."""
+ def __init__(self, stream):
+ self.stream = stream
+
+ def write(self, data):
+ self.stream.write(data)
+ if '\n' in data:
+ self.stream.flush()
+
+ def __getattr__(self, attr):
+ return getattr(self.stream, attr)
+
+
+def disable_buffering():
+ """Makes this process and child processes stdout unbuffered."""
+ if not os.environ.get('PYTHONUNBUFFERED'):
+ # Since sys.stdout is a C++ object, it's impossible to do
+ # sys.stdout.write = lambda...
+ sys.stdout = Unbuffered(sys.stdout)
+ os.environ['PYTHONUNBUFFERED'] = 'x'
+
+
+def fix_python_path(cmd):
+ """Returns the fixed command line to call the right python executable."""
+ out = cmd[:]
+ if out[0] == 'python':
+ out[0] = sys.executable
+ elif out[0].endswith('.py'):
+ out.insert(0, sys.executable)
+ return out
+
+
+def gen_blacklist(regexes):
+ """Returns a lambda to be used as a blacklist."""
+ compiled = [re.compile(i) for i in regexes]
+ def match(f):
+ return any(j.match(f) for j in compiled)
+ return match
+
+
+def create_subprocess_thunk():
+ """Creates a small temporary script to start the child process.
+
+ This thunk doesn't block, its unique name is used to identify it as the
+ parent.
+ """
+ handle, name = tempfile.mkstemp(prefix='trace_inputs_thunk', suffix='.py')
+ try:
+ os.write(
+ handle,
+ (
+ 'import subprocess, sys\n'
+ 'sys.exit(subprocess.call(sys.argv[2:]))\n'
+ ))
+ finally:
+ os.close(handle)
+ return name
+
+
+def create_exec_thunk():
+ """Creates a small temporary script to start the child executable.
+
+ Reads from the file handle provided as the fisrt argument to block, then
+ execv() the command to be traced.
+ """
+ handle, name = tempfile.mkstemp(prefix='trace_inputs_thunk', suffix='.py')
+ try:
+ os.write(
+ handle,
+ (
+ 'import os, sys\n'
+ 'fd = int(sys.argv[1])\n'
+ # This will block until the controlling process writes a byte on the
+ # pipe. It will do so once the tracing tool, e.g. strace, is ready to
+ # trace.
+ 'os.read(fd, 1)\n'
+ 'os.close(fd)\n'
+ 'os.execv(sys.argv[2], sys.argv[2:])\n'
+ ))
+ finally:
+ os.close(handle)
+ return name
+
+
+def strace_process_quoted_arguments(text):
+ """Extracts quoted arguments on a string and return the arguments as a list.
+
+ Implemented as an automaton. Supports incomplete strings in the form
+ '"foo"...'.
+
+ Example:
+ With text = '"foo", "bar"', the function will return ['foo', 'bar']
+
+ TODO(maruel): Implement escaping.
+ """
+ # All the possible states of the DFA.
+ ( NEED_QUOTE, # Begining of a new arguments.
+ INSIDE_STRING, # Inside an argument.
+ ESCAPED, # Found a '\' inside a quote. Treat the next char as-is.
+ NEED_COMMA_OR_DOT, # Right after the closing quote of an argument. Could be
+ # a serie of 3 dots or a comma.
+ NEED_SPACE, # Right after a comma
+ NEED_DOT_2, # Found a dot, need a second one.
+ NEED_DOT_3, # Found second dot, need a third one.
+ NEED_COMMA, # Found third dot, need a comma.
+ ) = range(8)
+
+ state = NEED_QUOTE
+ out = []
+ for index, char in enumerate(text):
+ if char == '"':
+ if state == NEED_QUOTE:
+ state = INSIDE_STRING
+ # A new argument was found.
+ out.append('')
+ elif state == INSIDE_STRING:
+ # The argument is now closed.
+ state = NEED_COMMA_OR_DOT
+ elif state == ESCAPED:
+ out[-1] += char
+ state = INSIDE_STRING
+ else:
+ raise ValueError(
+ 'Can\'t process char \'%s\' at column %d for: %r' % (
+ char, index, text),
+ index,
+ text)
+ elif char == ',':
+ if state in (NEED_COMMA_OR_DOT, NEED_COMMA):
+ state = NEED_SPACE
+ elif state == INSIDE_STRING:
+ out[-1] += char
+ elif state == ESCAPED:
+ out[-1] += char
+ state = INSIDE_STRING
+ else:
+ raise ValueError(
+ 'Can\'t process char \'%s\' at column %d for: %r' % (
+ char, index, text),
+ index,
+ text)
+ elif char == ' ':
+ if state == NEED_SPACE:
+ state = NEED_QUOTE
+ elif state == INSIDE_STRING:
+ out[-1] += char
+ elif state == ESCAPED:
+ out[-1] += char
+ state = INSIDE_STRING
+ else:
+ raise ValueError(
+ 'Can\'t process char \'%s\' at column %d for: %r' % (
+ char, index, text),
+ index,
+ text)
+ elif char == '.':
+ if state in (NEED_QUOTE, NEED_COMMA_OR_DOT):
+ # The string is incomplete, this mean the strace -s flag should be
+ # increased.
+ # For NEED_QUOTE, the input string would look like '"foo", ...'.
+ # For NEED_COMMA_OR_DOT, the input string would look like '"foo"...'
+ state = NEED_DOT_2
+ elif state == NEED_DOT_2:
+ state = NEED_DOT_3
+ elif state == NEED_DOT_3:
+ state = NEED_COMMA
+ elif state == INSIDE_STRING:
+ out[-1] += char
+ elif state == ESCAPED:
+ out[-1] += char
+ state = INSIDE_STRING
+ else:
+ raise ValueError(
+ 'Can\'t process char \'%s\' at column %d for: %r' % (
+ char, index, text),
+ index,
+ text)
+ elif char == '\\':
+ if state == ESCAPED:
+ out[-1] += char
+ state = INSIDE_STRING
+ elif state == INSIDE_STRING:
+ state = ESCAPED
+ else:
+ raise ValueError(
+ 'Can\'t process char \'%s\' at column %d for: %r' % (
+ char, index, text),
+ index,
+ text)
+ else:
+ if state == INSIDE_STRING:
+ out[-1] += char
+ else:
+ raise ValueError(
+ 'Can\'t process char \'%s\' at column %d for: %r' % (
+ char, index, text),
+ index,
+ text)
+ if state not in (NEED_COMMA, NEED_COMMA_OR_DOT):
+ raise ValueError(
+ 'String is incorrectly terminated: %r' % text,
+ text)
+ return out
+
+
+def read_json(filepath):
+ with open(filepath, 'r') as f:
+ return json.load(f)
+
+
+def write_json(filepath_or_handle, data, dense):
+ """Writes data into filepath or file handle encoded as json.
+
+ If dense is True, the json is packed. Otherwise, it is human readable.
+ """
+ if hasattr(filepath_or_handle, 'write'):
+ if dense:
+ filepath_or_handle.write(
+ json.dumps(data, sort_keys=True, separators=(',',':')))
+ else:
+ filepath_or_handle.write(json.dumps(data, sort_keys=True, indent=2))
+ else:
+ with open(filepath_or_handle, 'wb') as f:
+ if dense:
+ json.dump(data, f, sort_keys=True, separators=(',',':'))
+ else:
+ json.dump(data, f, sort_keys=True, indent=2)
+
+
+def assert_is_renderable(pseudo_string):
+ """Asserts the input is a valid object to be processed by render()."""
+ assert (
+ pseudo_string is None or
+ isinstance(pseudo_string, unicode) or
+ hasattr(pseudo_string, 'render')), repr(pseudo_string)
+
+
+def render(pseudo_string):
+ """Converts the pseudo-string to an unicode string."""
+ if pseudo_string is None or isinstance(pseudo_string, unicode):
+ return pseudo_string
+ return pseudo_string.render()
+
+
+class Results(object):
+ """Results of a trace session."""
+
+ class _TouchedObject(object):
+ """Something, a file or a directory, that was accessed."""
+ def __init__(self, root, path, tainted, size, nb_files):
+ logging.debug(
+ '%s(%s, %s, %s, %s, %s)' %
+ (self.__class__.__name__, root, path, tainted, size, nb_files))
+ assert_is_renderable(root)
+ assert_is_renderable(path)
+ self.root = root
+ self.path = path
+ self.tainted = tainted
+ self.nb_files = nb_files
+ # Can be used as a cache or a default value, depending on context. In
+ # particular, once self.tainted is True, because the path was replaced
+ # with a variable, it is not possible to look up the file size.
+ self._size = size
+ # These are cache only.
+ self._real_path = None
+
+ # Check internal consistency.
+ assert path, path
+ assert tainted or bool(root) != bool(isabs(path)), (root, path)
+ assert tainted or (
+ not os.path.exists(self.full_path) or
+ (self.full_path == get_native_path_case(self.full_path))), (
+ tainted, self.full_path, get_native_path_case(self.full_path))
+
+ @property
+ def existent(self):
+ return self.size != -1
+
+ @property
+ def full_path(self):
+ if self.root:
+ return os.path.join(self.root, self.path)
+ return self.path
+
+ @property
+ def real_path(self):
+ """Returns the path with symlinks resolved."""
+ if not self._real_path:
+ self._real_path = os.path.realpath(self.full_path)
+ return self._real_path
+
+ @property
+ def size(self):
+ """File's size. -1 is not existent.
+
+ Once tainted, it is not possible the retrieve the file size anymore since
+ the path is composed of variables.
+ """
+ if self._size is None and not self.tainted:
+ try:
+ self._size = os.stat(self.full_path).st_size
+ except OSError:
+ self._size = -1
+ return self._size
+
+ def flatten(self):
+ """Returns a dict representing this object.
+
+ A 'size' of 0 means the file was only touched and not read.
+ """
+ return {
+ 'path': self.path,
+ 'size': self.size,
+ }
+
+ def replace_variables(self, variables):
+ """Replaces the root of this File with one of the variables if it matches.
+
+ If a variable replacement occurs, the cloned object becomes tainted.
+ """
+ for variable, root_path in variables.iteritems():
+ if self.path.startswith(root_path):
+ return self._clone(
+ self.root, variable + self.path[len(root_path):], True)
+ # No need to clone, returns ourself.
+ return self
+
+ def strip_root(self, root):
+ """Returns a clone of itself with 'root' stripped off.
+
+ Note that the file is kept if it is either accessible from a symlinked
+ path that was used to access the file or through the real path.
+ """
+ # Check internal consistency.
+ assert self.tainted or (isabs(root) and root.endswith(os.path.sep)), root
+ if not self.full_path.startswith(root):
+ # Now try to resolve the symlinks to see if it can be reached this way.
+ # Only try *after* trying without resolving symlink.
+ if not self.real_path.startswith(root):
+ return None
+ path = self.real_path
+ else:
+ path = self.full_path
+ return self._clone(root, path[len(root):], self.tainted)
+
+ def _clone(self, new_root, new_path, tainted):
+ raise NotImplementedError(self.__class__.__name__)
+
+ class File(_TouchedObject):
+ """A file that was accessed. May not be present anymore.
+
+ If tainted is true, it means it is not a real path anymore as a variable
+ replacement occured.
+
+ |mode| can be one of None, TOUCHED, READ or WRITE.
+ """
+ # Was probed for existence, and it is existent, but was never _opened_.
+ TOUCHED = 't'
+ # Opened for read only and guaranteed to not have been written to.
+ READ = 'r'
+ # Opened for write.
+ WRITE = 'w'
+
+ # They are listed in order of priority. E.g. if a file is traced as TOUCHED
+ # then as WRITE, only keep WRITE. None means no idea, which is a problem on
+ # Windows.
+ ACCEPTABLE_MODES = (None, TOUCHED, READ, WRITE)
+
+ def __init__(self, root, path, tainted, size, mode):
+ assert mode in self.ACCEPTABLE_MODES
+ super(Results.File, self).__init__(root, path, tainted, size, 1)
+ self.mode = mode
+
+ def _clone(self, new_root, new_path, tainted):
+ """Clones itself keeping meta-data."""
+ # Keep the self.size and self._real_path caches for performance reason. It
+ # is also important when the file becomes tainted (with a variable instead
+ # of the real path) since self.path is not an on-disk path anymore so
+ # out._size cannot be updated.
+ out = self.__class__(new_root, new_path, tainted, self.size, self.mode)
+ out._real_path = self._real_path
+ return out
+
+ def flatten(self):
+ out = super(Results.File, self).flatten()
+ out['mode'] = self.mode
+ return out
+
+ class Directory(_TouchedObject):
+ """A directory of files. Must exist.
+
+ For a Directory instance, self.size is not a cache, it's an actual value
+ that is never modified and represents the total size of the files contained
+ in this directory. It is possible that the directory is empty so that
+ size==0; this happens if there's only an invalid symlink in it.
+ """
+ def __init__(self, root, path, tainted, size, nb_files):
+ """path='.' is a valid value and must be handled appropriately."""
+ assert not path.endswith(os.path.sep), path
+ super(Results.Directory, self).__init__(
+ root, path + os.path.sep, tainted, size, nb_files)
+
+ def flatten(self):
+ out = super(Results.Directory, self).flatten()
+ out['nb_files'] = self.nb_files
+ return out
+
+ def _clone(self, new_root, new_path, tainted):
+ """Clones itself keeping meta-data."""
+ out = self.__class__(
+ new_root,
+ new_path.rstrip(os.path.sep),
+ tainted,
+ self.size,
+ self.nb_files)
+ out._real_path = self._real_path
+ return out
+
+ class Process(object):
+ """A process that was traced.
+
+ Contains references to the files accessed by this process and its children.
+ """
+ def __init__(self, pid, files, executable, command, initial_cwd, children):
+ logging.debug('Process(%s, %d, ...)' % (pid, len(files)))
+ self.pid = pid
+ self.files = sorted(files, key=lambda x: x.path)
+ self.children = children
+ self.executable = executable
+ self.command = command
+ self.initial_cwd = initial_cwd
+
+ # Check internal consistency.
+ assert len(set(f.path for f in self.files)) == len(self.files), sorted(
+ f.path for f in self.files)
+ assert isinstance(self.children, list)
+ assert isinstance(self.files, list)
+
+ @property
+ def all(self):
+ for child in self.children:
+ for i in child.all:
+ yield i
+ yield self
+
+ def flatten(self):
+ return {
+ 'children': [c.flatten() for c in self.children],
+ 'command': self.command,
+ 'executable': self.executable,
+ 'files': [f.flatten() for f in self.files],
+ 'initial_cwd': self.initial_cwd,
+ 'pid': self.pid,
+ }
+
+ def strip_root(self, root):
+ assert isabs(root) and root.endswith(os.path.sep), root
+ # Loads the files after since they are constructed as objects.
+ out = self.__class__(
+ self.pid,
+ filter(None, (f.strip_root(root) for f in self.files)),
+ self.executable,
+ self.command,
+ self.initial_cwd,
+ [c.strip_root(root) for c in self.children])
+ logging.debug(
+ 'strip_root(%s) %d -> %d' % (root, len(self.files), len(out.files)))
+ return out
+
+ def __init__(self, process):
+ self.process = process
+ # Cache.
+ self._files = None
+
+ def flatten(self):
+ return {
+ 'root': self.process.flatten(),
+ }
+
+ @property
+ def files(self):
+ if self._files is None:
+ self._files = sorted(
+ sum((p.files for p in self.process.all), []),
+ key=lambda x: x.path)
+ return self._files
+
+ @property
+ def existent(self):
+ return [f for f in self.files if f.existent]
+
+ @property
+ def non_existent(self):
+ return [f for f in self.files if not f.existent]
+
+ def strip_root(self, root):
+ """Returns a clone with all the files outside the directory |root| removed
+ and converts all the path to be relative paths.
+
+ It keeps files accessible through the |root| directory or that have been
+ accessed through any symlink which points to the same directory.
+ """
+ # Resolve any symlink
+ root = os.path.realpath(root)
+ root = get_native_path_case(root).rstrip(os.path.sep) + os.path.sep
+ logging.debug('strip_root(%s)' % root)
+ return Results(self.process.strip_root(root))
+
+
+class ApiBase(object):
+ """OS-agnostic API to trace a process and its children."""
+ class Context(object):
+ """Processes one log line at a time and keeps the list of traced processes.
+
+ The parsing is complicated by the fact that logs are traced out of order for
+ strace but in-order for dtrace and logman. In addition, on Windows it is
+ very frequent that processids are reused so a flat list cannot be used. But
+ at the same time, it is impossible to faithfully construct a graph when the
+ logs are processed out of order. So both a tree and a flat mapping are used,
+ the tree is the real process tree, while the flat mapping stores the last
+ valid process for the corresponding processid. For the strace case, the
+ tree's head is guessed at the last moment.
+ """
+ class Process(object):
+ """Keeps context for one traced child process.
+
+ Logs all the files this process touched. Ignores directories.
+ """
+ def __init__(self, blacklist, pid, initial_cwd):
+ # Check internal consistency.
+ assert isinstance(pid, int), repr(pid)
+ assert_is_renderable(initial_cwd)
+ self.pid = pid
+ # children are Process instances.
+ self.children = []
+ self.initial_cwd = initial_cwd
+ self.cwd = None
+ self.files = {}
+ self.executable = None
+ self.command = None
+ self._blacklist = blacklist
+
+ def to_results_process(self):
+ """Resolves file case sensitivity and or late-bound strings."""
+ # When resolving files, it's normal to get dupe because a file could be
+ # opened multiple times with different case. Resolve the deduplication
+ # here.
+ def fix_path(x):
+ """Returns the native file path case.
+
+ Converts late-bound strings.
+ """
+ if not x:
+ # Do not convert None instance to 'None'.
+ return x
+ x = render(x)
+ if os.path.isabs(x):
+ # If the path is not absolute, which tends to happen occasionally on
+ # Windows, it is not possible to get the native path case so ignore
+ # that trace. It mostly happens for 'executable' value.
+ x = get_native_path_case(x)
+ return x
+
+ def fix_and_blacklist_path(x, m):
+ """Receives a tuple (filepath, mode) and processes filepath."""
+ x = fix_path(x)
+ if not x:
+ return
+ # The blacklist needs to be reapplied, since path casing could
+ # influence blacklisting.
+ if self._blacklist(x):
+ return
+ # Filters out directories. Some may have passed through.
+ if os.path.isdir(x):
+ return
+ return x, m
+
+ # Renders all the files as strings, as some could be RelativePath
+ # instances. It is important to do it first since there could still be
+ # multiple entries with the same path but different modes.
+ rendered = (
+ fix_and_blacklist_path(f, m) for f, m in self.files.iteritems())
+ files = sorted(
+ (f for f in rendered if f),
+ key=lambda x: (x[0], Results.File.ACCEPTABLE_MODES.index(x[1])))
+ # Then converting into a dict will automatically clean up lesser
+ # important values.
+ files = [
+ Results.File(None, f, False, None, m)
+ for f, m in dict(files).iteritems()
+ ]
+ return Results.Process(
+ self.pid,
+ files,
+ fix_path(self.executable),
+ self.command,
+ fix_path(self.initial_cwd),
+ [c.to_results_process() for c in self.children])
+
+ def add_file(self, filepath, mode):
+ """Adds a file if it passes the blacklist."""
+ if self._blacklist(render(filepath)):
+ return
+ logging.debug('add_file(%d, %s, %s)', self.pid, filepath, mode)
+ # Note that filepath and not render(filepath) is added. It is because
+ # filepath could be something else than a string, like a RelativePath
+ # instance for dtrace logs.
+ modes = Results.File.ACCEPTABLE_MODES
+ old_mode = self.files.setdefault(filepath, mode)
+ if old_mode != mode and modes.index(old_mode) < modes.index(mode):
+ # Take the highest value.
+ self.files[filepath] = mode
+
+ def __init__(self, blacklist):
+ self.blacklist = blacklist
+ # Initial process.
+ self.root_process = None
+ # dict to accelerate process lookup, to not have to lookup the whole graph
+ # each time.
+ self._process_lookup = {}
+
+ class Tracer(object):
+ """During it's lifetime, the tracing subsystem is enabled."""
+ def __init__(self, logname):
+ self._logname = logname
+ self._lock = threading.RLock()
+ self._traces = []
+ self._initialized = True
+ self._scripts_to_cleanup = []
+
+ def trace(self, cmd, cwd, tracename, output):
+ """Runs the OS-specific trace program on an executable.
+
+ Arguments:
+ - cmd: The command (a list) to run.
+ - cwd: Current directory to start the child process in.
+ - tracename: Name of the trace in the logname file.
+ - output: If False, redirects output to PIPEs.
+
+ Returns a tuple (resultcode, output) and updates the internal trace
+ entries.
+ """
+ # The implementation adds an item to self._traces.
+ raise NotImplementedError(self.__class__.__name__)
+
+ def close(self, _timeout=None):
+ """Saves the meta-data in the logname file.
+
+ For kernel-based tracing, stops the tracing subsystem.
+
+ Must not be used manually when using 'with' construct.
+ """
+ with self._lock:
+ if not self._initialized:
+ raise TracingFailure(
+ 'Called %s.close() on an unitialized object' %
+ self.__class__.__name__,
+ None, None, None)
+ try:
+ while self._scripts_to_cleanup:
+ try:
+ os.remove(self._scripts_to_cleanup.pop())
+ except OSError as e:
+ logging.error('Failed to delete a temporary script: %s', e)
+ write_json(self._logname, self._gen_logdata(), False)
+ finally:
+ self._initialized = False
+
+ def post_process_log(self):
+ """Post-processes the log so it becomes faster to load afterward.
+
+ Must not be used manually when using 'with' construct.
+ """
+ assert not self._initialized, 'Must stop tracing first.'
+
+ def _gen_logdata(self):
+ """Returns the data to be saved in the trace file."""
+ return {
+ 'traces': self._traces,
+ }
+
+ def __enter__(self):
+ """Enables 'with' statement."""
+ return self
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ """Enables 'with' statement."""
+ self.close()
+ # If an exception was thrown, do not process logs.
+ if not exc_type:
+ self.post_process_log()
+
+ def get_tracer(self, logname):
+ """Returns an ApiBase.Tracer instance.
+
+ Initializes the tracing subsystem, which is a requirement for kernel-based
+ tracers. Only one tracer instance should be live at a time!
+
+ logname is the filepath to the json file that will contain the meta-data
+ about the logs.
+ """
+ return self.Tracer(logname)
+
+ @staticmethod
+ def clean_trace(logname):
+ """Deletes an old log."""
+ raise NotImplementedError()
+
+ @classmethod
+ def parse_log(cls, logname, blacklist, trace_name):
+ """Processes trace logs and returns the files opened and the files that do
+ not exist.
+
+ It does not track directories.
+
+ Arguments:
+ - logname: must be an absolute path.
+ - blacklist: must be a lambda.
+ - trace_name: optional trace to read, defaults to reading all traces.
+
+ Most of the time, files that do not exist are temporary test files that
+ should be put in /tmp instead. See http://crbug.com/116251.
+
+ Returns a list of dict with keys:
+ - results: A Results instance.
+ - trace: The corresponding tracename parameter provided to
+ get_tracer().trace().
+ - output: Output gathered during execution, if get_tracer().trace(...,
+ output=False) was used.
+ """
+ raise NotImplementedError(cls.__class__.__name__)
+
+
+class Strace(ApiBase):
+ """strace implies linux."""
+ @staticmethod
+ def load_filename(filename):
+ """Parses a filename in a log."""
+ # TODO(maruel): Be compatible with strace -x.
+ assert isinstance(filename, str)
+ out = ''
+ i = 0
+ while i < len(filename):
+ c = filename[i]
+ if c == '\\':
+ out += chr(int(filename[i+1:i+4], 8))
+ i += 4
+ else:
+ out += c
+ i += 1
+ # TODO(maruel): That's not necessarily true that the current code page is
+ # utf-8.
+ return out.decode('utf-8')
+
+ class Context(ApiBase.Context):
+ """Processes a strace log line and keeps the list of existent and non
+ existent files accessed.
+
+ Ignores directories.
+
+ Uses late-binding to processes the cwd of each process. The problem is that
+ strace generates one log file per process it traced but doesn't give any
+ information about which process was started when and by who. So process the
+ logs out of order and use late binding with RelativePath to be able to
+ deduce the initial directory of each process once all the logs are parsed.
+
+ TODO(maruel): Use the script even in the non-sudo case, so log parsing can
+ be done in two phase: first find the root process, then process the child
+ processes in order. With that, it should be possible to not use RelativePath
+ anymore. This would significantly simplify the code!
+ """
+ class Process(ApiBase.Context.Process):
+ """Represents the state of a process.
+
+ Contains all the information retrieved from the pid-specific log.
+ """
+ # Function names are using ([a-z_0-9]+)
+ # This is the most common format. function(args) = result
+ RE_HEADER = re.compile(r'^([a-z_0-9]+)\((.*?)\)\s+= (.+)$')
+ # An interrupted function call, only grab the minimal header.
+ RE_UNFINISHED = re.compile(r'^([^\(]+)(.*) \<unfinished \.\.\.\>$')
+ # A resumed function call.
+ RE_RESUMED = re.compile(r'^<\.\.\. ([^ ]+) resumed> (.+)$')
+ # A process received a signal.
+ RE_SIGNAL = re.compile(r'^--- SIG[A-Z]+ .+ ---')
+ # A process didn't handle a signal. Ignore any junk appearing before,
+ # because the process was forcibly killed so it won't open any new file.
+ RE_KILLED = re.compile(
+ r'^.*\+\+\+ killed by ([A-Z]+)( \(core dumped\))? \+\+\+$')
+ # The process has exited.
+ RE_PROCESS_EXITED = re.compile(r'^\+\+\+ exited with (\d+) \+\+\+')
+ # A call was canceled. Ignore any prefix.
+ RE_UNAVAILABLE = re.compile(r'^.*\)\s*= \? <unavailable>$')
+ # Happens when strace fails to even get the function name.
+ UNNAMED_FUNCTION = '????'
+
+ # Corner-case in python, a class member function decorator must not be
+ # @staticmethod.
+ def parse_args(regexp, expect_zero): # pylint: disable=E0213
+ """Automatically convert the str 'args' into a list of processed
+ arguments.
+
+ Arguments:
+ - regexp is used to parse args.
+ - expect_zero: one of True, False or None.
+ - True: will check for result.startswith('0') first and will ignore
+ the trace line completely otherwise. This is important because for
+ many functions, the regexp will not process if the call failed.
+ - False: will check for not result.startswith(('?', '-1')) for the
+ same reason than with True.
+ - None: ignore result.
+ """
+ def meta_hook(function):
+ assert function.__name__.startswith('handle_')
+ def hook(self, args, result):
+ if expect_zero is True and not result.startswith('0'):
+ return
+ if expect_zero is False and result.startswith(('?', '-1')):
+ return
+ match = re.match(regexp, args)
+ if not match:
+ raise TracingFailure(
+ 'Failed to parse %s(%s) = %s' %
+ (function.__name__[len('handle_'):], args, result),
+ None, None, None)
+ return function(self, match.groups(), result)
+ return hook
+ return meta_hook
+
+ class RelativePath(object):
+ """A late-bound relative path."""
+ def __init__(self, parent, value):
+ assert_is_renderable(parent)
+ self.parent = parent
+ assert (
+ value is None or
+ (isinstance(value, unicode) and not os.path.isabs(value)))
+ self.value = value
+ if self.value:
+ # TODO(maruel): On POSIX, '\\' is a valid character so remove this
+ # assert.
+ assert '\\' not in self.value, value
+ assert '\\' not in self.value, (repr(value), repr(self.value))
+
+ def render(self):
+ """Returns the current directory this instance is representing.
+
+ This function is used to return the late-bound value.
+ """
+ assert self.parent is not None
+ parent = render(self.parent)
+ if self.value:
+ return os.path.normpath(os.path.join(parent, self.value))
+ return parent
+
+ def __init__(self, root, pid):
+ """Keeps enough information to be able to guess the original process
+ root.
+
+ strace doesn't store which process was the initial process. So more
+ information needs to be kept so the graph can be reconstructed from the
+ flat map.
+ """
+ logging.info('%s(%d)' % (self.__class__.__name__, pid))
+ super(Strace.Context.Process, self).__init__(root.blacklist, pid, None)
+ assert isinstance(root, ApiBase.Context)
+ self._root = weakref.ref(root)
+ # The dict key is the function name of the pending call, like 'open'
+ # or 'execve'.
+ self._pending_calls = {}
+ self._line_number = 0
+ # Current directory when the process started.
+ if isinstance(self._root(), unicode):
+ self.initial_cwd = self._root()
+ else:
+ self.initial_cwd = self.RelativePath(self._root(), None)
+ self.parentid = None
+ self._done = False
+
+ def get_cwd(self):
+ """Returns the best known value of cwd."""
+ return self.cwd or self.initial_cwd
+
+ def render(self):
+ """Returns the string value of the RelativePath() object.
+
+ Used by RelativePath. Returns the initial directory and not the
+ current one since the current directory 'cwd' validity is time-limited.
+
+ The validity is only guaranteed once all the logs are processed.
+ """
+ return self.initial_cwd.render()
+
+ def on_line(self, line):
+ assert isinstance(line, str)
+ self._line_number += 1
+ try:
+ if self._done:
+ raise TracingFailure(
+ 'Found a trace for a terminated process or corrupted log',
+ None, None, None)
+
+ if self.RE_SIGNAL.match(line):
+ # Ignore signals.
+ return
+
+ match = self.RE_KILLED.match(line)
+ if match:
+ # Converts a '+++ killed by Foo +++' trace into an exit_group().
+ self.handle_exit_group(match.group(1), None)
+ return
+
+ match = self.RE_PROCESS_EXITED.match(line)
+ if match:
+ # Converts a '+++ exited with 1 +++' trace into an exit_group()
+ self.handle_exit_group(match.group(1), None)
+ return
+
+ match = self.RE_UNFINISHED.match(line)
+ if match:
+ if match.group(1) in self._pending_calls:
+ raise TracingFailure(
+ 'Found two unfinished calls for the same function',
+ None, None, None,
+ self._pending_calls)
+ self._pending_calls[match.group(1)] = (
+ match.group(1) + match.group(2))
+ return
+
+ match = self.RE_UNAVAILABLE.match(line)
+ if match:
+ # This usually means a process was killed and a pending call was
+ # canceled.
+ # TODO(maruel): Look up the last exit_group() trace just above and
+ # make sure any self._pending_calls[anything] is properly flushed.
+ return
+
+ match = self.RE_RESUMED.match(line)
+ if match:
+ if match.group(1) not in self._pending_calls:
+ raise TracingFailure(
+ 'Found a resumed call that was not logged as unfinished',
+ None, None, None,
+ self._pending_calls)
+ pending = self._pending_calls.pop(match.group(1))
+ # Reconstruct the line.
+ line = pending + match.group(2)
+
+ match = self.RE_HEADER.match(line)
+ if not match:
+ # The line is corrupted. It happens occasionally when a process is
+ # killed forcibly with activity going on. Assume the process died.
+ # No other line can be processed afterward.
+ logging.debug('%d is done: %s', self.pid, line)
+ self._done = True
+ return
+
+ if match.group(1) == self.UNNAMED_FUNCTION:
+ return
+
+ # It's a valid line, handle it.
+ handler = getattr(self, 'handle_%s' % match.group(1), None)
+ if not handler:
+ self._handle_unknown(match.group(1), match.group(2), match.group(3))
+ return handler(match.group(2), match.group(3))
+ except TracingFailure, e:
+ # Hack in the values since the handler could be a static function.
+ e.pid = self.pid
+ e.line = line
+ e.line_number = self._line_number
+ # Re-raise the modified exception.
+ raise
+ except (KeyError, NotImplementedError, ValueError), e:
+ raise TracingFailure(
+ 'Trace generated a %s exception: %s' % (
+ e.__class__.__name__, str(e)),
+ self.pid,
+ self._line_number,
+ line,
+ e)
+
+ @parse_args(r'^\"(.+?)\", [FKORWX_|]+$', True)
+ def handle_access(self, args, _result):
+ self._handle_file(args[0], Results.File.TOUCHED)
+
+ @parse_args(r'^\"(.+?)\"$', True)
+ def handle_chdir(self, args, _result):
+ """Updates cwd."""
+ self.cwd = self._mangle(args[0])
+ logging.debug('handle_chdir(%d, %s)' % (self.pid, self.cwd))
+
+ @parse_args(r'^\"(.+?)\", (\d+), (\d+)$', False)
+ def handle_chown(self, args, _result):
+ # TODO(maruel): Look at result?
+ self._handle_file(args[0], Results.File.WRITE)
+
+ def handle_clone(self, _args, result):
+ self._handling_forking('clone', result)
+
+ def handle_close(self, _args, _result):
+ pass
+
+ @parse_args(r'^\"(.+?)\", (\d+)$', False)
+ def handle_chmod(self, args, _result):
+ self._handle_file(args[0], Results.File.WRITE)
+
+ @parse_args(r'^\"(.+?)\", (\d+)$', False)
+ def handle_creat(self, args, _result):
+ self._handle_file(args[0], Results.File.WRITE)
+
+ @parse_args(r'^\"(.+?)\", \[(.+)\], \[\/\* \d+ vars? \*\/\]$', True)
+ def handle_execve(self, args, _result):
+ # Even if in practice execve() doesn't returns when it succeeds, strace
+ # still prints '0' as the result.
+ filepath = args[0]
+ self._handle_file(filepath, Results.File.READ)
+ self.executable = self._mangle(filepath)
+ try:
+ self.command = strace_process_quoted_arguments(args[1])
+ except ValueError as e:
+ raise TracingFailure(
+ 'Failed to process command line argument:\n%s' % e.args[0],
+ None, None, None)
+
+ def handle_exit_group(self, _args, _result):
+ """Removes cwd."""
+ self.cwd = None
+
+ @parse_args(r'^(\d+|AT_FDCWD), \"(.*?)\", ([A-Z\_\|]+)(|, \d+)$', True)
+ def handle_faccessat(self, args, _results):
+ if args[0] == 'AT_FDCWD':
+ self._handle_file(args[1], Results.File.TOUCHED)
+ else:
+ raise Exception('Relative faccess not implemented.')
+
+ def handle_fallocate(self, _args, result):
+ pass
+
+ def handle_fork(self, args, result):
+ self._handle_unknown('fork', args, result)
+
+ def handle_futex(self, _args, _result):
+ pass
+
+ @parse_args(r'^\"(.+?)\", (\d+)$', False)
+ def handle_getcwd(self, args, _result):
+ if os.path.isabs(args[0]):
+ logging.debug('handle_chdir(%d, %s)' % (self.pid, self.cwd))
+ if not isinstance(self.cwd, unicode):
+ # Take the occasion to reset the path.
+ self.cwd = self._mangle(args[0])
+ else:
+ # It should always match.
+ assert self.cwd == Strace.load_filename(args[0]), (
+ self.cwd, args[0])
+
+ @parse_args(r'^\"(.+?)\", \"(.+?)\"$', True)
+ def handle_link(self, args, _result):
+ self._handle_file(args[0], Results.File.READ)
+ self._handle_file(args[1], Results.File.WRITE)
+
+ @parse_args(r'\"(.+?)\", \{.+?, \.\.\.\}', True)
+ def handle_lstat(self, args, _result):
+ self._handle_file(args[0], Results.File.TOUCHED)
+
+ def handle_mkdir(self, _args, _result):
+ # We track content, not directories.
+ pass
+
+ @parse_args(r'^\"(.*?)\", ([A-Z\_\|]+)(|, \d+)$', False)
+ def handle_open(self, args, _result):
+ if 'O_DIRECTORY' in args[1]:
+ return
+ self._handle_file(
+ args[0],
+ Results.File.READ if 'O_RDONLY' in args[1] else Results.File.WRITE)
+
+ @parse_args(r'^(\d+|AT_FDCWD), \"(.*?)\", ([A-Z\_\|]+)(|, \d+)$', False)
+ def handle_openat(self, args, _result):
+ if 'O_DIRECTORY' in args[2]:
+ return
+ if args[0] == 'AT_FDCWD':
+ self._handle_file(
+ args[1],
+ Results.File.READ if 'O_RDONLY' in args[2]
+ else Results.File.WRITE)
+ else:
+ # TODO(maruel): Implement relative open if necessary instead of the
+ # AT_FDCWD flag, let's hope not since this means tracking all active
+ # directory handles.
+ raise NotImplementedError('Relative open via openat not implemented.')
+
+ @parse_args(r'^\"(.+?)\", \".+?\"(\.\.\.)?, \d+$', False)
+ def handle_readlink(self, args, _result):
+ self._handle_file(args[0], Results.File.READ)
+
+ @parse_args(r'^\"(.+?)\", \"(.+?)\"$', True)
+ def handle_rename(self, args, _result):
+ self._handle_file(args[0], Results.File.READ)
+ self._handle_file(args[1], Results.File.WRITE)
+
+ def handle_rmdir(self, _args, _result):
+ # We track content, not directories.
+ pass
+
+ def handle_setxattr(self, _args, _result):
+ # TODO(maruel): self._handle_file(args[0], Results.File.WRITE)
+ pass
+
+ @parse_args(r'\"(.+?)\", \{.+?, \.\.\.\}', True)
+ def handle_stat(self, args, _result):
+ self._handle_file(args[0], Results.File.TOUCHED)
+
+ @parse_args(r'^\"(.+?)\", \"(.+?)\"$', True)
+ def handle_symlink(self, args, _result):
+ self._handle_file(args[0], Results.File.TOUCHED)
+ self._handle_file(args[1], Results.File.WRITE)
+
+ @parse_args(r'^\"(.+?)\", \d+', True)
+ def handle_truncate(self, args, _result):
+ self._handle_file(args[0], Results.File.WRITE)
+
+ def handle_unlink(self, _args, _result):
+ # In theory, the file had to be created anyway.
+ pass
+
+ def handle_unlinkat(self, _args, _result):
+ # In theory, the file had to be created anyway.
+ pass
+
+ def handle_statfs(self, _args, _result):
+ pass
+
+ def handle_utimensat(self, _args, _result):
+ pass
+
+ def handle_vfork(self, _args, result):
+ self._handling_forking('vfork', result)
+
+ @staticmethod
+ def _handle_unknown(function, args, result):
+ raise TracingFailure(
+ 'Unexpected/unimplemented trace %s(%s)= %s' %
+ (function, args, result),
+ None, None, None)
+
+ def _handling_forking(self, name, result):
+ """Transfers cwd."""
+ if result.startswith(('?', '-1')):
+ # The call failed.
+ return
+ # Update the other process right away.
+ childpid = int(result)
+ child = self._root().get_or_set_proc(childpid)
+ if child.parentid is not None or childpid in self.children:
+ raise TracingFailure(
+ 'Found internal inconsitency in process lifetime detection '
+ 'during a %s() call' % name,
+ None, None, None)
+
+ # Copy the cwd object.
+ child.initial_cwd = self.get_cwd()
+ child.parentid = self.pid
+ # It is necessary because the logs are processed out of order.
+ self.children.append(child)
+
+ def _handle_file(self, filepath, mode):
+ filepath = self._mangle(filepath)
+ self.add_file(filepath, mode)
+
+ def _mangle(self, filepath):
+ """Decodes a filepath found in the log and convert it to a late-bound
+ path if necessary.
+
+ |filepath| is an strace 'encoded' string and the returned value is
+ either an unicode string if the path was absolute or a late bound path
+ otherwise.
+ """
+ filepath = Strace.load_filename(filepath)
+ if os.path.isabs(filepath):
+ return filepath
+ else:
+ if isinstance(self.get_cwd(), unicode):
+ return os.path.normpath(os.path.join(self.get_cwd(), filepath))
+ return self.RelativePath(self.get_cwd(), filepath)
+
+ def __init__(self, blacklist, root_pid, initial_cwd):
+ """|root_pid| may be None when the root process is not known.
+
+ In that case, a search is done after reading all the logs to figure out
+ the root process.
+ """
+ super(Strace.Context, self).__init__(blacklist)
+ assert_is_renderable(initial_cwd)
+ self.root_pid = root_pid
+ self.initial_cwd = initial_cwd
+
+ def render(self):
+ """Returns the string value of the initial cwd of the root process.
+
+ Used by RelativePath.
+ """
+ return self.initial_cwd
+
+ def on_line(self, pid, line):
+ """Transfers control into the Process.on_line() function."""
+ self.get_or_set_proc(pid).on_line(line.strip())
+
+ def to_results(self):
+ """If necessary, finds back the root process and verify consistency."""
+ if not self.root_pid:
+ # The non-sudo case. The traced process was started by strace itself,
+ # so the pid of the traced process is not known.
+ root = [p for p in self._process_lookup.itervalues() if not p.parentid]
+ if len(root) == 1:
+ self.root_process = root[0]
+ # Save it for later.
+ self.root_pid = self.root_process.pid
+ else:
+ # The sudo case. The traced process was started manually so its pid is
+ # known.
+ self.root_process = self._process_lookup.get(self.root_pid)
+ if not self.root_process:
+ raise TracingFailure(
+ 'Found internal inconsitency in process lifetime detection '
+ 'while finding the root process',
+ None,
+ None,
+ None,
+ self.root_pid,
+ sorted(self._process_lookup))
+ process = self.root_process.to_results_process()
+ if sorted(self._process_lookup) != sorted(p.pid for p in process.all):
+ raise TracingFailure(
+ 'Found internal inconsitency in process lifetime detection '
+ 'while looking for len(tree) == len(list)',
+ None,
+ None,
+ None,
+ sorted(self._process_lookup),
+ sorted(p.pid for p in process.all))
+ return Results(process)
+
+ def get_or_set_proc(self, pid):
+ """Returns the Context.Process instance for this pid or creates a new one.
+ """
+ if not pid or not isinstance(pid, int):
+ raise TracingFailure(
+ 'Unpexpected value for pid: %r' % pid,
+ pid,
+ None,
+ None,
+ pid)
+ if pid not in self._process_lookup:
+ self._process_lookup[pid] = self.Process(self, pid)
+ return self._process_lookup[pid]
+
+ @classmethod
+ def traces(cls):
+ """Returns the list of all handled traces to pass this as an argument to
+ strace.
+ """
+ prefix = 'handle_'
+ return [i[len(prefix):] for i in dir(cls.Process) if i.startswith(prefix)]
+
+ class Tracer(ApiBase.Tracer):
+ MAX_LEN = 256
+
+ def __init__(self, logname, use_sudo):
+ super(Strace.Tracer, self).__init__(logname)
+ self.use_sudo = use_sudo
+ if use_sudo:
+ # TODO(maruel): Use the jump script systematically to make it easy to
+ # figure out the root process, so RelativePath is not necessary anymore.
+ self._child_script = create_exec_thunk()
+ self._scripts_to_cleanup.append(self._child_script)
+
+ def trace(self, cmd, cwd, tracename, output):
+ """Runs strace on an executable.
+
+ When use_sudo=True, it is a 3-phases process: start the thunk, start
+ sudo strace with the pid of the thunk and then have the thunk os.execve()
+ the process to trace.
+ """
+ logging.info('trace(%s, %s, %s, %s)' % (cmd, cwd, tracename, output))
+ assert os.path.isabs(cmd[0]), cmd[0]
+ assert os.path.isabs(cwd), cwd
+ assert os.path.normpath(cwd) == cwd, cwd
+ with self._lock:
+ if not self._initialized:
+ raise TracingFailure(
+ 'Called Tracer.trace() on an unitialized object',
+ None, None, None, tracename)
+ assert tracename not in (i['trace'] for i in self._traces)
+ stdout = stderr = None
+ if output:
+ stdout = subprocess.PIPE
+ stderr = subprocess.STDOUT
+
+ # Ensure all file related APIs are hooked.
+ traces = ','.join(Strace.Context.traces() + ['file'])
+ flags = [
+ # Each child process has its own trace file. It is necessary because
+ # strace may generate corrupted log file if multiple processes are
+ # heavily doing syscalls simultaneously.
+ '-ff',
+ # Reduce whitespace usage.
+ '-a1',
+ # hex encode non-ascii strings.
+ # TODO(maruel): '-x',
+ # TODO(maruel): '-ttt',
+ # Signals are unnecessary noise here. Note the parser can cope with them
+ # but reduce the unnecessary output.
+ '-esignal=none',
+ # Print as much data as wanted.
+ '-s', '%d' % self.MAX_LEN,
+ '-e', 'trace=%s' % traces,
+ '-o', self._logname + '.' + tracename,
+ ]
+
+ if self.use_sudo:
+ pipe_r, pipe_w = os.pipe()
+ # Start the child process paused.
+ target_cmd = [sys.executable, self._child_script, str(pipe_r)] + cmd
+ logging.debug(' '.join(target_cmd))
+ child_proc = subprocess.Popen(
+ target_cmd,
+ stdin=subprocess.PIPE,
+ stdout=stdout,
+ stderr=stderr,
+ cwd=cwd)
+
+ # TODO(maruel): both processes must use the same UID for it to work
+ # without sudo. Look why -p is failing at the moment without sudo.
+ trace_cmd = [
+ 'sudo',
+ 'strace',
+ '-p', str(child_proc.pid),
+ ] + flags
+ logging.debug(' '.join(trace_cmd))
+ strace_proc = subprocess.Popen(
+ trace_cmd,
+ cwd=cwd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ line = strace_proc.stderr.readline()
+ if not re.match(r'^Process \d+ attached \- interrupt to quit$', line):
+ # TODO(maruel): Raise an exception.
+ assert False, line
+
+ # Now fire the child process.
+ os.write(pipe_w, 'x')
+
+ out = child_proc.communicate()[0]
+ strace_out = strace_proc.communicate()[0]
+
+ # TODO(maruel): if strace_proc.returncode: Add an exception.
+ saved_out = strace_out if strace_proc.returncode else out
+ root_pid = child_proc.pid
+ else:
+ # Non-sudo case.
+ trace_cmd = [
+ 'strace',
+ ] + flags + cmd
+ logging.debug(' '.join(trace_cmd))
+ child_proc = subprocess.Popen(
+ trace_cmd,
+ cwd=cwd,
+ stdin=subprocess.PIPE,
+ stdout=stdout,
+ stderr=stderr)
+ out = child_proc.communicate()[0]
+ # TODO(maruel): Walk the logs and figure out the root process would
+ # simplify parsing the logs a *lot*.
+ saved_out = out
+ # The trace reader will have to figure out.
+ root_pid = None
+
+ with self._lock:
+ assert tracename not in (i['trace'] for i in self._traces)
+ self._traces.append(
+ {
+ 'cmd': cmd,
+ 'cwd': cwd,
+ 'output': saved_out,
+ 'pid': root_pid,
+ 'trace': tracename,
+ })
+ return child_proc.returncode, out
+
+ def __init__(self, use_sudo=None):
+ super(Strace, self).__init__()
+ self.use_sudo = use_sudo
+
+ def get_tracer(self, logname):
+ return self.Tracer(logname, self.use_sudo)
+
+ @staticmethod
+ def clean_trace(logname):
+ if os.path.isfile(logname):
+ os.remove(logname)
+ # Also delete any pid specific file from previous traces.
+ for i in glob.iglob(logname + '.*'):
+ if i.rsplit('.', 1)[1].isdigit():
+ os.remove(i)
+
+ @classmethod
+ def parse_log(cls, logname, blacklist, trace_name):
+ logging.info('parse_log(%s, ..., %s)', logname, trace_name)
+ assert os.path.isabs(logname)
+ data = read_json(logname)
+ out = []
+ for item in data['traces']:
+ if trace_name and item['trace'] != trace_name:
+ continue
+ result = {
+ 'output': item['output'],
+ 'trace': item['trace'],
+ }
+ try:
+ context = cls.Context(blacklist, item['pid'], item['cwd'])
+ for pidfile in glob.iglob('%s.%s.*' % (logname, item['trace'])):
+ logging.debug('Reading %s', pidfile)
+ pid = pidfile.rsplit('.', 1)[1]
+ if pid.isdigit():
+ pid = int(pid)
+ found_line = False
+ for line in open(pidfile, 'rb'):
+ context.on_line(pid, line)
+ found_line = True
+ if not found_line:
+ # Ensures that a completely empty trace still creates the
+ # corresponding Process instance by logging a dummy line.
+ context.on_line(pid, '')
+ else:
+ logging.warning('Found unexpected file %s', pidfile)
+ result['results'] = context.to_results()
+ except TracingFailure:
+ result['exception'] = sys.exc_info()
+ out.append(result)
+ return out
+
+
+class Dtrace(ApiBase):
+ """Uses DTrace framework through dtrace. Requires root access.
+
+ Implies Mac OSX.
+
+ dtruss can't be used because it has compatibility issues with python.
+
+ Also, the pid->cwd handling needs to be done manually since OSX has no way to
+ get the absolute path of the 'cwd' dtrace variable from the probe.
+
+ Also, OSX doesn't populate curpsinfo->pr_psargs properly, see
+ https://discussions.apple.com/thread/1980539. So resort to handling execve()
+ manually.
+
+ errno is not printed in the log since this implementation currently only cares
+ about files that were successfully opened.
+ """
+ class Context(ApiBase.Context):
+ # Format: index pid function(args)
+ RE_HEADER = re.compile(r'^\d+ (\d+) ([a-zA-Z_\-]+)\((.*?)\)$')
+
+ # Arguments parsing.
+ RE_DTRACE_BEGIN = re.compile(r'^\"(.+?)\"$')
+ RE_CHDIR = re.compile(r'^\"(.+?)\"$')
+ RE_EXECVE = re.compile(r'^\"(.+?)\", \[(\d+), (.+)\]$')
+ RE_OPEN = re.compile(r'^\"(.+?)\", (0x[0-9a-z]+), (0x[0-9a-z]+)$')
+ RE_PROC_START = re.compile(r'^(\d+), \"(.+?)\", (\d+)$')
+ RE_RENAME = re.compile(r'^\"(.+?)\", \"(.+?)\"$')
+
+ # O_DIRECTORY is not defined on Windows and dtrace doesn't exist on Windows.
+ O_DIRECTORY = os.O_DIRECTORY if hasattr(os, 'O_DIRECTORY') else None
+ O_RDWR = os.O_RDWR
+ O_WRONLY = os.O_WRONLY
+
+ class Process(ApiBase.Context.Process):
+ def __init__(self, *args):
+ super(Dtrace.Context.Process, self).__init__(*args)
+ self.cwd = self.initial_cwd
+
+ def __init__(self, blacklist, thunk_pid, initial_cwd):
+ logging.info(
+ '%s(%d, %s)' % (self.__class__.__name__, thunk_pid, initial_cwd))
+ super(Dtrace.Context, self).__init__(blacklist)
+ assert isinstance(initial_cwd, unicode), initial_cwd
+ # Process ID of the temporary script created by create_subprocess_thunk().
+ self._thunk_pid = thunk_pid
+ self._initial_cwd = initial_cwd
+ self._line_number = 0
+
+ def on_line(self, line):
+ assert isinstance(line, unicode), line
+ self._line_number += 1
+ match = self.RE_HEADER.match(line)
+ if not match:
+ raise TracingFailure(
+ 'Found malformed line: %s' % line,
+ None,
+ self._line_number,
+ line)
+ fn = getattr(
+ self,
+ 'handle_%s' % match.group(2).replace('-', '_'),
+ self._handle_ignored)
+ # It is guaranteed to succeed because of the regexp. Or at least I thought
+ # it would.
+ pid = int(match.group(1))
+ try:
+ return fn(pid, match.group(3))
+ except TracingFailure, e:
+ # Hack in the values since the handler could be a static function.
+ e.pid = pid
+ e.line = line
+ e.line_number = self._line_number
+ # Re-raise the modified exception.
+ raise
+ except (KeyError, NotImplementedError, ValueError), e:
+ raise TracingFailure(
+ 'Trace generated a %s exception: %s' % (
+ e.__class__.__name__, str(e)),
+ pid,
+ self._line_number,
+ line,
+ e)
+
+ def to_results(self):
+ process = self.root_process.to_results_process()
+ # Internal concistency check.
+ if sorted(self._process_lookup) != sorted(p.pid for p in process.all):
+ raise TracingFailure(
+ 'Found internal inconsitency in process lifetime detection '
+ 'while looking for len(tree) == len(list)',
+ None,
+ None,
+ None,
+ sorted(self._process_lookup),
+ sorted(p.pid for p in process.all))
+ return Results(process)
+
+ def handle_dtrace_BEGIN(self, _pid, args):
+ if not self.RE_DTRACE_BEGIN.match(args):
+ raise TracingFailure(
+ 'Found internal inconsitency in dtrace_BEGIN log line',
+ None, None, None)
+
+ def handle_proc_start(self, pid, args):
+ """Transfers cwd.
+
+ The dtrace script already takes care of only tracing the processes that
+ are child of the traced processes so there is no need to verify the
+ process hierarchy.
+ """
+ if pid in self._process_lookup:
+ raise TracingFailure(
+ 'Found internal inconsitency in proc_start: %d started two times' %
+ pid,
+ None, None, None)
+ match = self.RE_PROC_START.match(args)
+ if not match:
+ raise TracingFailure(
+ 'Failed to parse arguments: %s' % args,
+ None, None, None)
+ ppid = int(match.group(1))
+ if ppid == self._thunk_pid and not self.root_process:
+ proc = self.root_process = self.Process(
+ self.blacklist, pid, self._initial_cwd)
+ elif ppid in self._process_lookup:
+ proc = self.Process(self.blacklist, pid, self._process_lookup[ppid].cwd)
+ self._process_lookup[ppid].children.append(proc)
+ else:
+ # Another process tree, ignore.
+ return
+ self._process_lookup[pid] = proc
+ logging.debug(
+ 'New child: %s -> %d cwd:%s' %
+ (ppid, pid, render(proc.initial_cwd)))
+
+ def handle_proc_exit(self, pid, _args):
+ """Removes cwd."""
+ if pid in self._process_lookup:
+ # self._thunk_pid is not traced itself and other traces run neither.
+ self._process_lookup[pid].cwd = None
+
+ def handle_execve(self, pid, args):
+ """Sets the process' executable.
+
+ TODO(maruel): Read command line arguments. See
+ https://discussions.apple.com/thread/1980539 for an example.
+ https://gist.github.com/1242279
+
+ Will have to put the answer at http://stackoverflow.com/questions/7556249.
+ :)
+ """
+ if not pid in self._process_lookup:
+ # Another process tree, ignore.
+ return
+ match = self.RE_EXECVE.match(args)
+ if not match:
+ raise TracingFailure(
+ 'Failed to parse arguments: %r' % args,
+ None, None, None)
+ proc = self._process_lookup[pid]
+ proc.executable = match.group(1)
+ self._handle_file(pid, proc.executable, Results.File.READ)
+ proc.command = self.process_escaped_arguments(match.group(3))
+ if int(match.group(2)) != len(proc.command):
+ raise TracingFailure(
+ 'Failed to parse execve() arguments: %s' % args,
+ None, None, None)
+
+ def handle_chdir(self, pid, args):
+ """Updates cwd."""
+ if pid not in self._process_lookup:
+ # Another process tree, ignore.
+ return
+ cwd = self.RE_CHDIR.match(args).group(1)
+ if not cwd.startswith('/'):
+ cwd2 = os.path.join(self._process_lookup[pid].cwd, cwd)
+ logging.debug('handle_chdir(%d, %s) -> %s' % (pid, cwd, cwd2))
+ else:
+ logging.debug('handle_chdir(%d, %s)' % (pid, cwd))
+ cwd2 = cwd
+ self._process_lookup[pid].cwd = cwd2
+
+ def handle_open_nocancel(self, pid, args):
+ """Redirects to handle_open()."""
+ return self.handle_open(pid, args)
+
+ def handle_open(self, pid, args):
+ if pid not in self._process_lookup:
+ # Another process tree, ignore.
+ return
+ match = self.RE_OPEN.match(args)
+ if not match:
+ raise TracingFailure(
+ 'Failed to parse arguments: %s' % args,
+ None, None, None)
+ flag = int(match.group(2), 16)
+ if self.O_DIRECTORY & flag == self.O_DIRECTORY:
+ # Ignore directories.
+ return
+ self._handle_file(
+ pid,
+ match.group(1),
+ Results.File.READ if not ((self.O_RDWR | self.O_WRONLY) & flag)
+ else Results.File.WRITE)
+
+ def handle_rename(self, pid, args):
+ if pid not in self._process_lookup:
+ # Another process tree, ignore.
+ return
+ match = self.RE_RENAME.match(args)
+ if not match:
+ raise TracingFailure(
+ 'Failed to parse arguments: %s' % args,
+ None, None, None)
+ self._handle_file(pid, match.group(1), Results.File.READ)
+ self._handle_file(pid, match.group(2), Results.File.WRITE)
+
+ def _handle_file(self, pid, filepath, mode):
+ if not filepath.startswith('/'):
+ filepath = os.path.join(self._process_lookup[pid].cwd, filepath)
+ # We can get '..' in the path.
+ filepath = os.path.normpath(filepath)
+ # Sadly, still need to filter out directories here;
+ # saw open_nocancel(".", 0, 0) = 0 lines.
+ if os.path.isdir(filepath):
+ return
+ self._process_lookup[pid].add_file(filepath, mode)
+
+ def handle_ftruncate(self, pid, args):
+ """Just used as a signal to kill dtrace, ignoring."""
+ pass
+
+ @staticmethod
+ def _handle_ignored(pid, args):
+ """Is called for all the event traces that are not handled."""
+ raise NotImplementedError('Please implement me')
+
+ @staticmethod
+ def process_escaped_arguments(text):
+ """Extracts escaped arguments on a string and return the arguments as a
+ list.
+
+ Implemented as an automaton.
+
+ Example:
+ With text = '\\001python2.7\\001-c\\001print(\\"hi\\")\\0', the
+ function will return ['python2.7', '-c', 'print("hi")]
+ """
+ if not text.endswith('\\0'):
+ raise ValueError('String is not null terminated: %r' % text, text)
+ text = text[:-2]
+
+ def unescape(x):
+ """Replaces '\\' with '\' and '\?' (where ? is anything) with ?."""
+ out = []
+ escaped = False
+ for i in x:
+ if i == '\\' and not escaped:
+ escaped = True
+ continue
+ escaped = False
+ out.append(i)
+ return ''.join(out)
+
+ return [unescape(i) for i in text.split('\\001')]
+
+ class Tracer(ApiBase.Tracer):
+ # pylint: disable=C0301
+ #
+ # To understand the following code, you'll want to take a look at:
+ # http://developers.sun.com/solaris/articles/dtrace_quickref/dtrace_quickref.html
+ # https://wikis.oracle.com/display/DTrace/Variables
+ # http://docs.oracle.com/cd/E19205-01/820-4221/
+ #
+ # 0. Dump all the valid probes into a text file. It is important, you
+ # want to redirect into a file and you don't want to constantly 'sudo'.
+ # $ sudo dtrace -l > probes.txt
+ #
+ # 1. Count the number of probes:
+ # $ wc -l probes.txt
+ # 81823 # On OSX 10.7, including 1 header line.
+ #
+ # 2. List providers, intentionally skipping all the 'syspolicy10925' and the
+ # likes and skipping the header with NR>1:
+ # $ awk 'NR>1 { print $2 }' probes.txt | sort | uniq | grep -v '[[:digit:]]'
+ # dtrace
+ # fbt
+ # io
+ # ip
+ # lockstat
+ # mach_trap
+ # proc
+ # profile
+ # sched
+ # syscall
+ # tcp
+ # vminfo
+ #
+ # 3. List of valid probes:
+ # $ grep syscall probes.txt | less
+ # or use dtrace directly:
+ # $ sudo dtrace -l -P syscall | less
+ #
+ # trackedpid is an associative array where its value can be 0, 1 or 2.
+ # 0 is for untracked processes and is the default value for items not
+ # in the associative array.
+ # 1 is for tracked processes.
+ # 2 is for the script created by create_subprocess_thunk() only. It is not
+ # tracked itself but all its decendants are.
+ #
+ # The script will kill itself only once waiting_to_die == 1 and
+ # current_processes == 0, so that both getlogin() was called and that
+ # all traced processes exited.
+ #
+ # TODO(maruel): Use cacheable predicates. See
+ # https://wikis.oracle.com/display/DTrace/Performance+Considerations
+ D_CODE = """
+ dtrace:::BEGIN {
+ waiting_to_die = 0;
+ current_processes = 0;
+ logindex = 0;
+ printf("%d %d %s_%s(\\"%s\\")\\n",
+ logindex, PID, probeprov, probename, SCRIPT);
+ logindex++;
+ }
+
+ proc:::start /trackedpid[ppid]/ {
+ trackedpid[pid] = 1;
+ current_processes += 1;
+ printf("%d %d %s_%s(%d, \\"%s\\", %d)\\n",
+ logindex, pid, probeprov, probename,
+ ppid,
+ execname,
+ current_processes);
+ logindex++;
+ }
+ /* Should use SCRIPT but there is no access to this variable at that
+ * point. */
+ proc:::start /ppid == PID && execname == "Python"/ {
+ trackedpid[pid] = 2;
+ current_processes += 1;
+ printf("%d %d %s_%s(%d, \\"%s\\", %d)\\n",
+ logindex, pid, probeprov, probename,
+ ppid,
+ execname,
+ current_processes);
+ logindex++;
+ }
+ proc:::exit /trackedpid[pid] &&
+ current_processes == 1 &&
+ waiting_to_die == 1/ {
+ trackedpid[pid] = 0;
+ current_processes -= 1;
+ printf("%d %d %s_%s(%d)\\n",
+ logindex, pid, probeprov, probename,
+ current_processes);
+ logindex++;
+ exit(0);
+ }
+ proc:::exit /trackedpid[pid]/ {
+ trackedpid[pid] = 0;
+ current_processes -= 1;
+ printf("%d %d %s_%s(%d)\\n",
+ logindex, pid, probeprov, probename,
+ current_processes);
+ logindex++;
+ }
+
+ /* Use an arcane function to detect when we need to die */
+ syscall::ftruncate:entry /pid == PID && arg0 == FILE_ID/ {
+ waiting_to_die = 1;
+ printf("%d %d %s()\\n", logindex, pid, probefunc);
+ logindex++;
+ }
+ syscall::ftruncate:entry /
+ pid == PID && arg0 == FILE_ID && current_processes == 0/ {
+ exit(0);
+ }
+
+ syscall::open*:entry /trackedpid[pid] == 1/ {
+ self->open_arg0 = arg0;
+ self->open_arg1 = arg1;
+ self->open_arg2 = arg2;
+ }
+ syscall::open*:return /trackedpid[pid] == 1 && errno == 0/ {
+ this->open_arg0 = copyinstr(self->open_arg0);
+ printf("%d %d %s(\\"%s\\", 0x%x, 0x%x)\\n",
+ logindex, pid, probefunc,
+ this->open_arg0,
+ self->open_arg1,
+ self->open_arg2);
+ logindex++;
+ this->open_arg0 = 0;
+ }
+ syscall::open*:return /trackedpid[pid] == 1/ {
+ self->open_arg0 = 0;
+ self->open_arg1 = 0;
+ self->open_arg2 = 0;
+ }
+
+ syscall::rename:entry /trackedpid[pid] == 1/ {
+ self->rename_arg0 = arg0;
+ self->rename_arg1 = arg1;
+ }
+ syscall::rename:return /trackedpid[pid] == 1 && errno == 0/ {
+ this->rename_arg0 = copyinstr(self->rename_arg0);
+ this->rename_arg1 = copyinstr(self->rename_arg1);
+ printf("%d %d %s(\\"%s\\", \\"%s\\")\\n",
+ logindex, pid, probefunc,
+ this->rename_arg0,
+ this->rename_arg1);
+ logindex++;
+ this->rename_arg0 = 0;
+ this->rename_arg1 = 0;
+ }
+ syscall::rename:return /trackedpid[pid] == 1/ {
+ self->rename_arg0 = 0;
+ self->rename_arg1 = 0;
+ }
+
+ /* Track chdir, it's painful because it is only receiving relative path.
+ */
+ syscall::chdir:entry /trackedpid[pid] == 1/ {
+ self->chdir_arg0 = arg0;
+ }
+ syscall::chdir:return /trackedpid[pid] == 1 && errno == 0/ {
+ this->chdir_arg0 = copyinstr(self->chdir_arg0);
+ printf("%d %d %s(\\"%s\\")\\n",
+ logindex, pid, probefunc,
+ this->chdir_arg0);
+ logindex++;
+ this->chdir_arg0 = 0;
+ }
+ syscall::chdir:return /trackedpid[pid] == 1/ {
+ self->chdir_arg0 = 0;
+ }
+ """
+
+ # execve-specific code, tends to throw a lot of exceptions.
+ D_CODE_EXECVE = """
+ /* Finally what we care about! */
+ syscall::exec*:entry /trackedpid[pid]/ {
+ self->exec_arg0 = copyinstr(arg0);
+ /* Incrementally probe for a NULL in the argv parameter of execve() to
+ * figure out argc. */
+ /* TODO(maruel): Skip the remaining copyin() when a NULL pointer was
+ * found. */
+ self->exec_argc = 0;
+ /* Probe for argc==1 */
+ this->exec_argv = (user_addr_t*)copyin(
+ arg1, sizeof(user_addr_t) * (self->exec_argc + 1));
+ self->exec_argc = this->exec_argv[self->exec_argc] ?
+ (self->exec_argc + 1) : self->exec_argc;
+
+ /* Probe for argc==2 */
+ this->exec_argv = (user_addr_t*)copyin(
+ arg1, sizeof(user_addr_t) * (self->exec_argc + 1));
+ self->exec_argc = this->exec_argv[self->exec_argc] ?
+ (self->exec_argc + 1) : self->exec_argc;
+
+ /* Probe for argc==3 */
+ this->exec_argv = (user_addr_t*)copyin(
+ arg1, sizeof(user_addr_t) * (self->exec_argc + 1));
+ self->exec_argc = this->exec_argv[self->exec_argc] ?
+ (self->exec_argc + 1) : self->exec_argc;
+
+ /* Probe for argc==4 */
+ this->exec_argv = (user_addr_t*)copyin(
+ arg1, sizeof(user_addr_t) * (self->exec_argc + 1));
+ self->exec_argc = this->exec_argv[self->exec_argc] ?
+ (self->exec_argc + 1) : self->exec_argc;
+
+ /* Copy the inputs strings since there is no guarantee they'll be
+ * present after the call completed. */
+ self->exec_argv0 = (self->exec_argc > 0) ?
+ copyinstr(this->exec_argv[0]) : "";
+ self->exec_argv1 = (self->exec_argc > 1) ?
+ copyinstr(this->exec_argv[1]) : "";
+ self->exec_argv2 = (self->exec_argc > 2) ?
+ copyinstr(this->exec_argv[2]) : "";
+ self->exec_argv3 = (self->exec_argc > 3) ?
+ copyinstr(this->exec_argv[3]) : "";
+ this->exec_argv = 0;
+ }
+ syscall::exec*:return /trackedpid[pid] && errno == 0/ {
+ /* We need to join strings here, as using multiple printf() would
+ * cause tearing when multiple threads/processes are traced.
+ * Since it is impossible to escape a string and join it to another one,
+ * like sprintf("%s%S", previous, more), use hackery.
+ * Each of the elements are split with a \\1. \\0 cannot be used because
+ * it is simply ignored. This will conflict with any program putting a
+ * \\1 in their execve() string but this should be "rare enough" */
+ this->args = "";
+ /* Process exec_argv[0] */
+ this->args = strjoin(
+ this->args, (self->exec_argc > 0) ? self->exec_argv0 : "");
+
+ /* Process exec_argv[1] */
+ this->args = strjoin(
+ this->args, (self->exec_argc > 1) ? "\\1" : "");
+ this->args = strjoin(
+ this->args, (self->exec_argc > 1) ? self->exec_argv1 : "");
+
+ /* Process exec_argv[2] */
+ this->args = strjoin(
+ this->args, (self->exec_argc > 2) ? "\\1" : "");
+ this->args = strjoin(
+ this->args, (self->exec_argc > 2) ? self->exec_argv2 : "");
+
+ /* Process exec_argv[3] */
+ this->args = strjoin(
+ this->args, (self->exec_argc > 3) ? "\\1" : "");
+ this->args = strjoin(
+ this->args, (self->exec_argc > 3) ? self->exec_argv3 : "");
+
+ /* Prints self->exec_argc to permits verifying the internal
+ * consistency since this code is quite fishy. */
+ printf("%d %d %s(\\"%s\\", [%d, %S])\\n",
+ logindex, pid, probefunc,
+ self->exec_arg0,
+ self->exec_argc,
+ this->args);
+ logindex++;
+ this->args = 0;
+ }
+ syscall::exec*:return /trackedpid[pid]/ {
+ self->exec_arg0 = 0;
+ self->exec_argc = 0;
+ self->exec_argv0 = 0;
+ self->exec_argv1 = 0;
+ self->exec_argv2 = 0;
+ self->exec_argv3 = 0;
+ }
+ """
+
+ # Code currently not used.
+ D_EXTRANEOUS = """
+ /* This is a good learning experience, since it traces a lot of things
+ * related to the process and child processes.
+ * Warning: it generates a gigantic log. For example, tracing
+ * "data/trace_inputs/child1.py --child" generates a 2mb log and takes
+ * several minutes to execute.
+ */
+ /*
+ mach_trap::: /trackedpid[pid] == 1 || trackedpid[ppid]/ {
+ printf("%d %d %s_%s() = %d\\n",
+ logindex, pid, probeprov, probefunc, errno);
+ logindex++;
+ }
+ proc::: /trackedpid[pid] == 1 || trackedpid[ppid]/ {
+ printf("%d %d %s_%s() = %d\\n",
+ logindex, pid, probeprov, probefunc, errno);
+ logindex++;
+ }
+ sched::: /trackedpid[pid] == 1 || trackedpid[ppid]/ {
+ printf("%d %d %s_%s() = %d\\n",
+ logindex, pid, probeprov, probefunc, errno);
+ logindex++;
+ }
+ syscall::: /trackedpid[pid] == 1 || trackedpid[ppid]/ {
+ printf("%d %d %s_%s() = %d\\n",
+ logindex, pid, probeprov, probefunc, errno);
+ logindex++;
+ }
+ vminfo::: /trackedpid[pid] == 1 || trackedpid[ppid]/ {
+ printf("%d %d %s_%s() = %d\\n",
+ logindex, pid, probeprov, probefunc, errno);
+ logindex++;
+ }
+ */
+ /* TODO(maruel): *stat* functions and friends
+ syscall::access:return,
+ syscall::chdir:return,
+ syscall::chflags:return,
+ syscall::chown:return,
+ syscall::chroot:return,
+ syscall::getattrlist:return,
+ syscall::getxattr:return,
+ syscall::lchown:return,
+ syscall::lstat64:return,
+ syscall::lstat:return,
+ syscall::mkdir:return,
+ syscall::pathconf:return,
+ syscall::readlink:return,
+ syscall::removexattr:return,
+ syscall::setxattr:return,
+ syscall::stat64:return,
+ syscall::stat:return,
+ syscall::truncate:return,
+ syscall::unlink:return,
+ syscall::utimes:return,
+ */
+ """
+
+ def __init__(self, logname, use_sudo):
+ """Starts the log collection with dtrace.
+
+ Requires root access or chmod 4555 on dtrace. dtrace is asynchronous so
+ this needs to wait for dtrace to be "warmed up".
+ """
+ super(Dtrace.Tracer, self).__init__(logname)
+ # This script is used as a signal to figure out the root process.
+ self._signal_script = create_subprocess_thunk()
+ self._scripts_to_cleanup.append(self._signal_script)
+ # This unique dummy temp file is used to signal the dtrace script that it
+ # should stop as soon as all the child processes are done. A bit hackish
+ # but works fine enough.
+ self._dummy_file_id, self._dummy_file_name = tempfile.mkstemp(
+ prefix='trace_signal_file')
+
+ dtrace_path = '/usr/sbin/dtrace'
+ if not os.path.isfile(dtrace_path):
+ dtrace_path = 'dtrace'
+ elif use_sudo is None and (os.stat(dtrace_path).st_mode & stat.S_ISUID):
+ # No need to sudo. For those following at home, don't do that.
+ use_sudo = False
+
+ # Note: do not use the -p flag. It's useless if the initial process quits
+ # too fast, resulting in missing traces from the grand-children. The D
+ # code manages the dtrace lifetime itself.
+ trace_cmd = [
+ dtrace_path,
+ # Use a larger buffer if getting 'out of scratch space' errors.
+ # Ref: https://wikis.oracle.com/display/DTrace/Options+and+Tunables
+ '-b', '10m',
+ '-x', 'dynvarsize=10m',
+ #'-x', 'dtrace_global_maxsize=1m',
+ '-x', 'evaltime=exec',
+ '-o', '/dev/stderr',
+ '-q',
+ '-n', self._get_dtrace_code(),
+ ]
+ if use_sudo is not False:
+ trace_cmd.insert(0, 'sudo')
+
+ with open(self._logname + '.log', 'wb') as logfile:
+ self._dtrace = subprocess.Popen(
+ trace_cmd, stdout=logfile, stderr=subprocess.STDOUT)
+ logging.debug('Started dtrace pid: %d' % self._dtrace.pid)
+
+ # Reads until one line is printed, which signifies dtrace is up and ready.
+ with open(self._logname + '.log', 'rb') as logfile:
+ while 'dtrace_BEGIN' not in logfile.readline():
+ if self._dtrace.poll() is not None:
+ # Do a busy wait. :/
+ break
+ logging.debug('dtrace started')
+
+ def _get_dtrace_code(self):
+ """Setups the D code to implement child process tracking.
+
+ Injects the cookie in the script so it knows when to stop.
+
+ The script will detect any instance of the script created with
+ create_subprocess_thunk() and will start tracing it.
+ """
+ out = (
+ 'inline int PID = %d;\n'
+ 'inline string SCRIPT = "%s";\n'
+ 'inline int FILE_ID = %d;\n'
+ '\n'
+ '%s') % (
+ os.getpid(),
+ self._signal_script,
+ self._dummy_file_id,
+ self.D_CODE)
+ if os.environ.get('TRACE_INPUTS_DTRACE_ENABLE_EXECVE') == '1':
+ # Do not enable by default since it tends to spew dtrace: error lines
+ # because the execve() parameters are not in valid memory at the time of
+ # logging.
+ # TODO(maruel): Find a way to make this reliable since it's useful but
+ # only works in limited/trivial uses cases for now.
+ out += self.D_CODE_EXECVE
+ return out
+
+ def trace(self, cmd, cwd, tracename, output):
+ """Runs dtrace on an executable.
+
+ This dtruss is broken when it starts the process itself or when tracing
+ child processes, this code starts a wrapper process
+ generated with create_subprocess_thunk() which starts the executable to
+ trace.
+ """
+ logging.info('trace(%s, %s, %s, %s)' % (cmd, cwd, tracename, output))
+ assert os.path.isabs(cmd[0]), cmd[0]
+ assert os.path.isabs(cwd), cwd
+ assert os.path.normpath(cwd) == cwd, cwd
+ with self._lock:
+ if not self._initialized:
+ raise TracingFailure(
+ 'Called Tracer.trace() on an unitialized object',
+ None, None, None, tracename)
+ assert tracename not in (i['trace'] for i in self._traces)
+
+ # Starts the script wrapper to start the child process. This signals the
+ # dtrace script that this process is to be traced.
+ stdout = stderr = None
+ if output:
+ stdout = subprocess.PIPE
+ stderr = subprocess.STDOUT
+ child_cmd = [
+ sys.executable,
+ self._signal_script,
+ tracename,
+ ]
+ # Call a dummy function so that dtrace knows I'm about to launch a process
+ # that needs to be traced.
+ # Yummy.
+ child = subprocess.Popen(
+ child_cmd + fix_python_path(cmd),
+ stdin=subprocess.PIPE,
+ stdout=stdout,
+ stderr=stderr,
+ cwd=cwd)
+ logging.debug('Started child pid: %d' % child.pid)
+
+ out = child.communicate()[0]
+ # This doesn't mean tracing is done, one of the grand-child process may
+ # still be alive. It will be tracked with the dtrace script.
+
+ with self._lock:
+ assert tracename not in (i['trace'] for i in self._traces)
+ self._traces.append(
+ {
+ 'cmd': cmd,
+ 'cwd': cwd,
+ 'pid': child.pid,
+ 'output': out,
+ 'trace': tracename,
+ })
+ return child.returncode, out
+
+ def close(self, timeout=None):
+ """Terminates dtrace."""
+ logging.debug('close(%s)' % timeout)
+ try:
+ try:
+ super(Dtrace.Tracer, self).close(timeout)
+ # Signal dtrace that it should stop now.
+ # ftruncate doesn't exist on Windows.
+ os.ftruncate(self._dummy_file_id, 0) # pylint: disable=E1101
+ if timeout:
+ start = time.time()
+ # Use polling. :/
+ while (self._dtrace.poll() is None and
+ (time.time() - start) < timeout):
+ time.sleep(0.1)
+ self._dtrace.kill()
+ self._dtrace.wait()
+ finally:
+ # Make sure to kill it in any case.
+ if self._dtrace.poll() is None:
+ try:
+ self._dtrace.kill()
+ self._dtrace.wait()
+ except OSError:
+ pass
+
+ if self._dtrace.returncode != 0:
+ # Warn about any dtrace failure but basically ignore it.
+ print 'dtrace failure: %s' % self._dtrace.returncode
+ finally:
+ os.close(self._dummy_file_id)
+ os.remove(self._dummy_file_name)
+
+ def post_process_log(self):
+ """Sorts the log back in order when each call occured.
+
+ dtrace doesn't save the buffer in strict order since it keeps one buffer
+ per CPU.
+ """
+ super(Dtrace.Tracer, self).post_process_log()
+ logname = self._logname + '.log'
+ with open(logname, 'rb') as logfile:
+ lines = [l for l in logfile if l.strip()]
+ errors = [l for l in lines if l.startswith('dtrace:')]
+ if errors:
+ raise TracingFailure(
+ 'Found errors in the trace: %s' % '\n'.join(errors),
+ None, None, None, logname)
+ try:
+ lines = sorted(lines, key=lambda l: int(l.split(' ', 1)[0]))
+ except ValueError:
+ raise TracingFailure(
+ 'Found errors in the trace: %s' % '\n'.join(
+ l for l in lines if l.split(' ', 1)[0].isdigit()),
+ None, None, None, logname)
+ with open(logname, 'wb') as logfile:
+ logfile.write(''.join(lines))
+
+ def __init__(self, use_sudo=None):
+ super(Dtrace, self).__init__()
+ self.use_sudo = use_sudo
+
+ def get_tracer(self, logname):
+ return self.Tracer(logname, self.use_sudo)
+
+ @staticmethod
+ def clean_trace(logname):
+ for ext in ('', '.log'):
+ if os.path.isfile(logname + ext):
+ os.remove(logname + ext)
+
+ @classmethod
+ def parse_log(cls, logname, blacklist, trace_name):
+ logging.info('parse_log(%s, ..., %s)', logname, trace_name)
+ assert os.path.isabs(logname)
+
+ def blacklist_more(filepath):
+ # All the HFS metadata is in the form /.vol/...
+ return blacklist(filepath) or re.match(r'^\/\.vol\/.+$', filepath)
+
+ data = read_json(logname)
+ out = []
+ for item in data['traces']:
+ if trace_name and item['trace'] != trace_name:
+ continue
+ result = {
+ 'output': item['output'],
+ 'trace': item['trace'],
+ }
+ try:
+ context = cls.Context(blacklist_more, item['pid'], item['cwd'])
+ # It's fine to assume the file as UTF-8: OSX enforces the file names to
+ # be valid UTF-8 and we control the log output.
+ for line in codecs.open(logname + '.log', 'rb', encoding='utf-8'):
+ context.on_line(line)
+ result['results'] = context.to_results()
+ except TracingFailure:
+ result['exception'] = sys.exc_info()
+ out.append(result)
+ return out
+
+
+class LogmanTrace(ApiBase):
+ """Uses the native Windows ETW based tracing functionality to trace a child
+ process.
+
+ Caveat: this implementations doesn't track cwd or initial_cwd. It is because
+ the Windows Kernel doesn't have a concept of 'current working directory' at
+ all. A Win32 process has a map of current directories, one per drive letter
+ and it is managed by the user mode kernel32.dll. In kernel, a file is always
+ opened relative to another file_object or as an absolute path. All the current
+ working directory logic is done in user mode.
+ """
+ class Context(ApiBase.Context):
+ """Processes a ETW log line and keeps the list of existent and non
+ existent files accessed.
+
+ Ignores directories.
+ """
+ # These indexes are for the stripped version in json.
+ EVENT_NAME = 0
+ TYPE = 1
+ PID = 2
+ TID = 3
+ PROCESSOR_ID = 4
+ TIMESTAMP = 5
+ USER_DATA = 6
+
+ class Process(ApiBase.Context.Process):
+ def __init__(self, *args):
+ super(LogmanTrace.Context.Process, self).__init__(*args)
+ # Handle file objects that succeeded.
+ self.file_objects = {}
+
+ def __init__(self, blacklist, thunk_pid, trace_name, thunk_cmd):
+ logging.info(
+ '%s(%d, %s, %s)', self.__class__.__name__, thunk_pid, trace_name,
+ thunk_cmd)
+ super(LogmanTrace.Context, self).__init__(blacklist)
+ self._drive_map = DosDriveMap()
+ # Threads mapping to the corresponding process id.
+ self._threads_active = {}
+ # Process ID of the tracer, e.g. the temporary script created by
+ # create_subprocess_thunk(). This is tricky because the process id may
+ # have been reused.
+ self._thunk_pid = thunk_pid
+ self._thunk_cmd = thunk_cmd
+ self._trace_name = trace_name
+ self._line_number = 0
+ self._thunk_process = None
+
+ def on_line(self, line):
+ """Processes a json Event line."""
+ self._line_number += 1
+ try:
+ # By Opcode
+ handler = getattr(
+ self,
+ 'handle_%s_%s' % (line[self.EVENT_NAME], line[self.TYPE]),
+ None)
+ if not handler:
+ raise TracingFailure(
+ 'Unexpected event %s_%s' % (
+ line[self.EVENT_NAME], line[self.TYPE]),
+ None, None, None)
+ handler(line)
+ except TracingFailure, e:
+ # Hack in the values since the handler could be a static function.
+ e.pid = line[self.PID]
+ e.line = line
+ e.line_number = self._line_number
+ # Re-raise the modified exception.
+ raise
+ except (KeyError, NotImplementedError, ValueError), e:
+ raise TracingFailure(
+ 'Trace generated a %s exception: %s' % (
+ e.__class__.__name__, str(e)),
+ line[self.PID],
+ self._line_number,
+ line,
+ e)
+
+ def to_results(self):
+ if not self.root_process:
+ raise TracingFailure(
+ 'Failed to detect the initial process %d' % self._thunk_pid,
+ None, None, None)
+ process = self.root_process.to_results_process()
+ return Results(process)
+
+ def _thread_to_process(self, tid):
+ """Finds the process from the thread id."""
+ tid = int(tid, 16)
+ pid = self._threads_active.get(tid)
+ if not pid or not self._process_lookup.get(pid):
+ return
+ return self._process_lookup[pid]
+
+ @classmethod
+ def handle_EventTrace_Header(cls, line):
+ """Verifies no event was dropped, e.g. no buffer overrun occured."""
+ BUFFER_SIZE = cls.USER_DATA
+ #VERSION = cls.USER_DATA + 1
+ #PROVIDER_VERSION = cls.USER_DATA + 2
+ #NUMBER_OF_PROCESSORS = cls.USER_DATA + 3
+ #END_TIME = cls.USER_DATA + 4
+ #TIMER_RESOLUTION = cls.USER_DATA + 5
+ #MAX_FILE_SIZE = cls.USER_DATA + 6
+ #LOG_FILE_MODE = cls.USER_DATA + 7
+ #BUFFERS_WRITTEN = cls.USER_DATA + 8
+ #START_BUFFERS = cls.USER_DATA + 9
+ #POINTER_SIZE = cls.USER_DATA + 10
+ EVENTS_LOST = cls.USER_DATA + 11
+ #CPU_SPEED = cls.USER_DATA + 12
+ #LOGGER_NAME = cls.USER_DATA + 13
+ #LOG_FILE_NAME = cls.USER_DATA + 14
+ #BOOT_TIME = cls.USER_DATA + 15
+ #PERF_FREQ = cls.USER_DATA + 16
+ #START_TIME = cls.USER_DATA + 17
+ #RESERVED_FLAGS = cls.USER_DATA + 18
+ #BUFFERS_LOST = cls.USER_DATA + 19
+ #SESSION_NAME_STRING = cls.USER_DATA + 20
+ #LOG_FILE_NAME_STRING = cls.USER_DATA + 21
+ if line[EVENTS_LOST] != '0':
+ raise TracingFailure(
+ ( '%s events were lost during trace, please increase the buffer '
+ 'size from %s') % (line[EVENTS_LOST], line[BUFFER_SIZE]),
+ None, None, None)
+
+ def handle_FileIo_Cleanup(self, line):
+ """General wisdom: if a file is closed, it's because it was opened.
+
+ Note that FileIo_Close is not used since if a file was opened properly but
+ not closed before the process exits, only Cleanup will be logged.
+ """
+ #IRP = self.USER_DATA
+ TTID = self.USER_DATA + 1 # Thread ID, that's what we want.
+ FILE_OBJECT = self.USER_DATA + 2
+ #FILE_KEY = self.USER_DATA + 3
+ proc = self._thread_to_process(line[TTID])
+ if not proc:
+ # Not a process we care about.
+ return
+ file_object = line[FILE_OBJECT]
+ if file_object in proc.file_objects:
+ filepath, access_type = proc.file_objects.pop(file_object)
+ proc.add_file(filepath, access_type)
+
+ def handle_FileIo_Create(self, line):
+ """Handles a file open.
+
+ All FileIo events are described at
+ http://msdn.microsoft.com/library/windows/desktop/aa363884.aspx
+ for some value of 'description'.
+
+ " (..) process and thread id values of the IO events (..) are not valid "
+ http://msdn.microsoft.com/magazine/ee358703.aspx
+
+ The FileIo.Create event doesn't return if the CreateFile() call
+ succeeded, so keep track of the file_object and check that it is
+ eventually closed with FileIo_Cleanup.
+ """
+ #IRP = self.USER_DATA
+ TTID = self.USER_DATA + 1 # Thread ID, that's what we want.
+ FILE_OBJECT = self.USER_DATA + 2
+ #CREATE_OPTIONS = self.USER_DATA + 3
+ #FILE_ATTRIBUTES = self.USER_DATA + 4
+ #SHARE_ACCESS = self.USER_DATA + 5
+ OPEN_PATH = self.USER_DATA + 6
+
+ proc = self._thread_to_process(line[TTID])
+ if not proc:
+ # Not a process we care about.
+ return
+
+ raw_path = line[OPEN_PATH]
+ # Ignore directories and bare drive right away.
+ if raw_path.endswith(os.path.sep):
+ return
+ filepath = self._drive_map.to_win32(raw_path)
+ # Ignore bare drive right away. Some may still fall through with format
+ # like '\\?\X:'
+ if len(filepath) == 2:
+ return
+ file_object = line[FILE_OBJECT]
+ if os.path.isdir(filepath):
+ # There is no O_DIRECTORY equivalent on Windows. The closed is
+ # FILE_FLAG_BACKUP_SEMANTICS but it's not exactly right either. So
+ # simply discard directories are they are found.
+ return
+ # Override any stale file object.
+ # TODO(maruel): Figure out a way to detect if the file was opened for
+ # reading or writting. Sadly CREATE_OPTIONS doesn't seem to be of any help
+ # here. For now mark as None to make it clear we have no idea what it is
+ # about.
+ proc.file_objects[file_object] = (filepath, None)
+
+ def handle_FileIo_Rename(self, line):
+ # TODO(maruel): Handle?
+ pass
+
+ def handle_Process_End(self, line):
+ pid = line[self.PID]
+ if self._process_lookup.get(pid):
+ logging.info('Terminated: %d' % pid)
+ self._process_lookup[pid] = None
+ else:
+ logging.debug('Terminated: %d' % pid)
+ if self._thunk_process and self._thunk_process.pid == pid:
+ self._thunk_process = None
+
+ def handle_Process_Start(self, line):
+ """Handles a new child process started by PID."""
+ #UNIQUE_PROCESS_KEY = self.USER_DATA
+ PROCESS_ID = self.USER_DATA + 1
+ #PARENT_PID = self.USER_DATA + 2
+ #SESSION_ID = self.USER_DATA + 3
+ #EXIT_STATUS = self.USER_DATA + 4
+ #DIRECTORY_TABLE_BASE = self.USER_DATA + 5
+ #USER_SID = self.USER_DATA + 6
+ IMAGE_FILE_NAME = self.USER_DATA + 7
+ COMMAND_LINE = self.USER_DATA + 8
+
+ ppid = line[self.PID]
+ pid = int(line[PROCESS_ID], 16)
+ command_line = CommandLineToArgvW(line[COMMAND_LINE])
+ logging.debug(
+ 'New process %d->%d (%s) %s' %
+ (ppid, pid, line[IMAGE_FILE_NAME], command_line))
+
+ if pid == self._thunk_pid:
+ # Need to ignore processes we don't know about because the log is
+ # system-wide. self._thunk_pid shall start only one process.
+ # This is tricky though because Windows *loves* to reuse process id and
+ # it happens often that the process ID of the thunk script created by
+ # create_subprocess_thunk() is reused. So just detecting the pid here is
+ # not sufficient, we must confirm the command line.
+ if command_line[:len(self._thunk_cmd)] != self._thunk_cmd:
+ logging.info(
+ 'Ignoring duplicate pid %d for %s: %s while searching for %s',
+ pid, self._trace_name, command_line, self._thunk_cmd)
+ return
+
+ # TODO(maruel): The check is quite weak. Add the thunk path.
+ if self._thunk_process:
+ raise TracingFailure(
+ ( 'Parent process is _thunk_pid(%d) but thunk_process(%d) is '
+ 'already set') % (self._thunk_pid, self._thunk_process.pid),
+ None, None, None)
+ proc = self.Process(self.blacklist, pid, None)
+ self._thunk_process = proc
+ return
+ elif ppid == self._thunk_pid and self._thunk_process:
+ proc = self.Process(self.blacklist, pid, None)
+ self.root_process = proc
+ ppid = None
+ elif self._process_lookup.get(ppid):
+ proc = self.Process(self.blacklist, pid, None)
+ self._process_lookup[ppid].children.append(proc)
+ else:
+ # Ignore
+ return
+ self._process_lookup[pid] = proc
+
+ proc.command = command_line
+ proc.executable = line[IMAGE_FILE_NAME]
+ # proc.command[0] may be the absolute path of 'executable' but it may be
+ # anything else too. If it happens that command[0] ends with executable,
+ # use it, otherwise defaults to the base name.
+ cmd0 = proc.command[0].lower()
+ if not cmd0.endswith('.exe'):
+ # TODO(maruel): That's not strictly true either.
+ cmd0 += '.exe'
+ if cmd0.endswith(proc.executable) and os.path.isfile(cmd0):
+ # Fix the path.
+ cmd0 = cmd0.replace('/', os.path.sep)
+ cmd0 = os.path.normpath(cmd0)
+ proc.executable = get_native_path_case(cmd0)
+ logging.info(
+ 'New child: %s -> %d %s' % (ppid, pid, proc.executable))
+
+ def handle_Thread_End(self, line):
+ """Has the same parameters as Thread_Start."""
+ tid = int(line[self.TID], 16)
+ self._threads_active.pop(tid, None)
+
+ def handle_Thread_Start(self, line):
+ """Handles a new thread created.
+
+ Do not use self.PID here since a process' initial thread is created by
+ the parent process.
+ """
+ PROCESS_ID = self.USER_DATA
+ TTHREAD_ID = self.USER_DATA + 1
+ #STACK_BASE = self.USER_DATA + 2
+ #STACK_LIMIT = self.USER_DATA + 3
+ #USER_STACK_BASE = self.USER_DATA + 4
+ #USER_STACK_LIMIT = self.USER_DATA + 5
+ #AFFINITY = self.USER_DATA + 6
+ #WIN32_START_ADDR = self.USER_DATA + 7
+ #TEB_BASE = self.USER_DATA + 8
+ #SUB_PROCESS_TAG = self.USER_DATA + 9
+ #BASE_PRIORITY = self.USER_DATA + 10
+ #PAGE_PRIORITY = self.USER_DATA + 11
+ #IO_PRIORITY = self.USER_DATA + 12
+ #THREAD_FLAGS = self.USER_DATA + 13
+ # Do not use self.PID here since a process' initial thread is created by
+ # the parent process.
+ pid = int(line[PROCESS_ID], 16)
+ tid = int(line[TTHREAD_ID], 16)
+ logging.debug('New thread pid:%d, tid:%d' % (pid, tid))
+ self._threads_active[tid] = pid
+
+ @classmethod
+ def supported_events(cls):
+ """Returns all the procesed events."""
+ out = []
+ for member in dir(cls):
+ match = re.match(r'^handle_([A-Za-z]+)_([A-Za-z]+)$', member)
+ if match:
+ out.append(match.groups())
+ return out
+
+ class Tracer(ApiBase.Tracer):
+ # The basic headers.
+ EXPECTED_HEADER = [
+ u'Event Name',
+ u'Type',
+ u'Event ID',
+ u'Version',
+ u'Channel',
+ u'Level', # 5
+ u'Opcode',
+ u'Task',
+ u'Keyword',
+ u'PID',
+ u'TID', # 10
+ u'Processor Number',
+ u'Instance ID',
+ u'Parent Instance ID',
+ u'Activity ID',
+ u'Related Activity ID', # 15
+ u'Clock-Time',
+ u'Kernel(ms)', # Both have a resolution of ~15ms which makes them
+ u'User(ms)', # pretty much useless.
+ u'User Data', # Extra arguments that are event-specific.
+ ]
+ # Only the useful headers common to all entries are listed there. Any column
+ # at 19 or higher is dependent on the specific event.
+ EVENT_NAME = 0
+ TYPE = 1
+ PID = 9
+ TID = 10
+ PROCESSOR_ID = 11
+ TIMESTAMP = 16
+ NULL_GUID = '{00000000-0000-0000-0000-000000000000}'
+ USER_DATA = 19
+
+ class CsvReader(object):
+ """CSV reader that reads files generated by tracerpt.exe.
+
+ csv.reader() fails to read them properly, it mangles file names quoted
+ with "" with a comma in it.
+ """
+ # 0. Had a ',' or one of the following ' ' after a comma, next should
+ # be ' ', '"' or string or ',' for an empty field.
+ ( HAD_DELIMITER,
+ # 1. Processing an unquoted field up to ','.
+ IN_STR,
+ # 2. Processing a new field starting with '"'.
+ STARTING_STR_QUOTED,
+ # 3. Second quote in a row at the start of a field. It could be either
+ # '""foo""' or '""'. Who the hell thought it was a great idea to use
+ # the same character for delimiting and escaping?
+ STARTING_SECOND_QUOTE,
+ # 4. A quote inside a quoted string where the previous character was
+ # not a quote, so the string is not empty. Can be either: end of a
+ # quoted string (a delimiter) or a quote escape. The next char must be
+ # either '"' or ','.
+ HAD_QUOTE_IN_QUOTED,
+ # 5. Second quote inside a quoted string.
+ HAD_SECOND_QUOTE_IN_A_ROW_IN_QUOTED,
+ # 6. Processing a field that started with '"'.
+ IN_STR_QUOTED) = range(7)
+
+ def __init__(self, f):
+ self.f = f
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ """Splits the line in fields."""
+ line = self.f.readline()
+ if not line:
+ raise StopIteration()
+ line = line.strip()
+ fields = []
+ state = self.HAD_DELIMITER
+ for i, c in enumerate(line):
+ if state == self.HAD_DELIMITER:
+ if c == ',':
+ # Empty field.
+ fields.append('')
+ elif c == ' ':
+ # Ignore initial whitespaces
+ pass
+ elif c == '"':
+ state = self.STARTING_STR_QUOTED
+ fields.append('')
+ else:
+ # Start of a new field.
+ state = self.IN_STR
+ fields.append(c)
+
+ elif state == self.IN_STR:
+ # Do not accept quote inside unquoted field.
+ assert c != '"', (i, c, line, fields)
+ if c == ',':
+ fields[-1] = fields[-1].strip()
+ state = self.HAD_DELIMITER
+ else:
+ fields[-1] = fields[-1] + c
+
+ elif state == self.STARTING_STR_QUOTED:
+ if c == '"':
+ # Do not store the character yet.
+ state = self.STARTING_SECOND_QUOTE
+ else:
+ state = self.IN_STR_QUOTED
+ fields[-1] = fields[-1] + c
+
+ elif state == self.STARTING_SECOND_QUOTE:
+ if c == ',':
+ # It was an empty field. '""' == ''.
+ state = self.HAD_DELIMITER
+ else:
+ fields[-1] = fields[-1] + '"' + c
+ state = self.IN_STR_QUOTED
+
+ elif state == self.HAD_QUOTE_IN_QUOTED:
+ if c == ',':
+ # End of the string.
+ state = self.HAD_DELIMITER
+ elif c == '"':
+ state = self.HAD_SECOND_QUOTE_IN_A_ROW_IN_QUOTED
+ else:
+ # The previous double-quote was just an unescaped quote.
+ fields[-1] = fields[-1] + '"' + c
+ state = self.IN_STR_QUOTED
+
+ elif state == self.HAD_SECOND_QUOTE_IN_A_ROW_IN_QUOTED:
+ if c == ',':
+ # End of the string.
+ state = self.HAD_DELIMITER
+ fields[-1] = fields[-1] + '"'
+ else:
+ # That's just how the logger rolls. Revert back to appending the
+ # char and "guess" it was a quote in a double-quoted string.
+ state = self.IN_STR_QUOTED
+ fields[-1] = fields[-1] + '"' + c
+
+ elif state == self.IN_STR_QUOTED:
+ if c == '"':
+ # Could be a delimiter or an escape.
+ state = self.HAD_QUOTE_IN_QUOTED
+ else:
+ fields[-1] = fields[-1] + c
+
+ if state == self.HAD_SECOND_QUOTE_IN_A_ROW_IN_QUOTED:
+ fields[-1] = fields[-1] + '"'
+ else:
+ assert state in (
+ # Terminated with a normal field.
+ self.IN_STR,
+ # Terminated with an empty field.
+ self.STARTING_SECOND_QUOTE,
+ # Terminated with a normal quoted field.
+ self.HAD_QUOTE_IN_QUOTED), (
+ line, state, fields)
+ return fields
+
+ def __init__(self, logname):
+ """Starts the log collection.
+
+ Requires administrative access. logman.exe is synchronous so no need for a
+ "warmup" call. 'Windows Kernel Trace' is *localized* so use its GUID
+ instead. The GUID constant name is SystemTraceControlGuid. Lovely.
+
+ One can get the list of potentially interesting providers with:
+ "logman query providers | findstr /i file"
+ """
+ super(LogmanTrace.Tracer, self).__init__(logname)
+ self._signal_script = create_subprocess_thunk()
+ self._scripts_to_cleanup.append(self._signal_script)
+ cmd_start = [
+ 'logman.exe',
+ 'start',
+ 'NT Kernel Logger',
+ '-p', '{9e814aad-3204-11d2-9a82-006008a86939}',
+ # splitio,fileiocompletion,syscall,file,cswitch,img
+ '(process,fileio,thread)',
+ '-o', self._logname + '.etl',
+ '-ets', # Send directly to kernel
+ # Values extracted out of thin air.
+ # Event Trace Session buffer size in kb.
+ '-bs', '10240',
+ # Number of Event Trace Session buffers.
+ '-nb', '16', '256',
+ ]
+ logging.debug('Running: %s' % cmd_start)
+ try:
+ subprocess.check_call(
+ cmd_start,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError, e:
+ if e.returncode == -2147024891:
+ print >> sys.stderr, 'Please restart with an elevated admin prompt'
+ elif e.returncode == -2144337737:
+ print >> sys.stderr, (
+ 'A kernel trace was already running, stop it and try again')
+ raise
+
+ def trace(self, cmd, cwd, tracename, output):
+ logging.info('trace(%s, %s, %s, %s)' % (cmd, cwd, tracename, output))
+ assert os.path.isabs(cmd[0]), cmd[0]
+ assert os.path.isabs(cwd), cwd
+ assert os.path.normpath(cwd) == cwd, cwd
+ with self._lock:
+ if not self._initialized:
+ raise TracingFailure(
+ 'Called Tracer.trace() on an unitialized object',
+ None, None, None, tracename)
+ assert tracename not in (i['trace'] for i in self._traces)
+
+ # Use "logman -?" for help.
+
+ stdout = stderr = None
+ if output:
+ stdout = subprocess.PIPE
+ stderr = subprocess.STDOUT
+
+ # Run the child process.
+ logging.debug('Running: %s' % cmd)
+ # Use the temporary script generated with create_subprocess_thunk() so we
+ # have a clear pid owner. Since trace_inputs.py can be used as a library
+ # and could trace multiple processes simultaneously, it makes it more
+ # complex if the executable to be traced is executed directly here. It
+ # also solves issues related to logman.exe that needs to be executed to
+ # control the kernel trace.
+ child_cmd = [
+ sys.executable,
+ self._signal_script,
+ tracename,
+ ]
+ child = subprocess.Popen(
+ child_cmd + fix_python_path(cmd),
+ cwd=cwd,
+ stdin=subprocess.PIPE,
+ stdout=stdout,
+ stderr=stderr)
+ logging.debug('Started child pid: %d' % child.pid)
+ out = child.communicate()[0]
+ # This doesn't mean all the grand-children are done. Sadly, we don't have
+ # a good way to determine that.
+
+ with self._lock:
+ assert tracename not in (i['trace'] for i in self._traces)
+ self._traces.append({
+ 'cmd': cmd,
+ 'cwd': cwd,
+ 'output': out,
+ 'pid': child.pid,
+ # Used to figure out the real process when process ids are reused.
+ 'thunk_cmd': child_cmd,
+ 'trace': tracename,
+ })
+
+ return child.returncode, out
+
+ def close(self, _timeout=None):
+ """Stops the kernel log collection and converts the traces to text
+ representation.
+ """
+ with self._lock:
+ try:
+ super(LogmanTrace.Tracer, self).close()
+ finally:
+ cmd_stop = [
+ 'logman.exe',
+ 'stop',
+ 'NT Kernel Logger',
+ '-ets', # Sends the command directly to the kernel.
+ ]
+ logging.debug('Running: %s' % cmd_stop)
+ subprocess.check_call(
+ cmd_stop,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+ def post_process_log(self):
+ """Converts the .etl file into .csv then into .json."""
+ super(LogmanTrace.Tracer, self).post_process_log()
+ logformat = 'csv'
+ self._convert_log(logformat)
+ self._trim_log(logformat)
+
+ def _gen_logdata(self):
+ return {
+ 'format': 'csv',
+ 'traces': self._traces,
+ }
+
+ def _trim_log(self, logformat):
+ """Reduces the amount of data in original log by generating a 'reduced'
+ log.
+ """
+ if logformat == 'csv_utf16':
+ file_handle = codecs.open(
+ self._logname + '.' + logformat, 'r', encoding='utf-16')
+
+ elif logformat == 'csv':
+ assert sys.getfilesystemencoding() == 'mbcs'
+ file_handle = codecs.open(
+ self._logname + '.' + logformat, 'r',
+ encoding=get_current_encoding())
+
+ supported_events = LogmanTrace.Context.supported_events()
+
+ def trim(generator):
+ """Loads items from the generator and returns the interesting data.
+
+ It filters out any uninteresting line and reduce the amount of data in
+ the trace.
+ """
+ for index, line in enumerate(generator):
+ if not index:
+ if line != self.EXPECTED_HEADER:
+ raise TracingFailure(
+ 'Found malformed header: %s' % line,
+ None, None, None)
+ continue
+ # As you can see, the CSV is full of useful non-redundant information:
+ if (line[2] != '0' or # Event ID
+ line[3] not in ('2', '3') or # Version
+ line[4] != '0' or # Channel
+ line[5] != '0' or # Level
+ line[7] != '0' or # Task
+ line[8] != '0x0000000000000000' or # Keyword
+ line[12] != '' or # Instance ID
+ line[13] != '' or # Parent Instance ID
+ line[14] != self.NULL_GUID or # Activity ID
+ line[15] != ''): # Related Activity ID
+ raise TracingFailure(
+ 'Found unexpected values in line: %s' % ' '.join(line),
+ None, None, None)
+
+ if (line[self.EVENT_NAME], line[self.TYPE]) not in supported_events:
+ continue
+
+ yield [
+ line[self.EVENT_NAME],
+ line[self.TYPE],
+ line[self.PID],
+ line[self.TID],
+ line[self.PROCESSOR_ID],
+ line[self.TIMESTAMP],
+ ] + line[self.USER_DATA:]
+
+ # must not convert the trim() call into a list, since it will use too much
+ # memory for large trace. use a csv file as a workaround since the json
+ # parser requires a complete in-memory file.
+ with open('%s.preprocessed' % self._logname, 'wb') as f:
+ # $ and * can't be used in file name on windows, reducing the likelihood
+ # of having to escape a string.
+ out = csv.writer(
+ f, delimiter='$', quotechar='*', quoting=csv.QUOTE_MINIMAL)
+ for line in trim(self.CsvReader(file_handle)):
+ out.writerow([s.encode('utf-8') for s in line])
+
+ def _convert_log(self, logformat):
+ """Converts the ETL trace to text representation.
+
+ Normally, 'csv' is sufficient. If complex scripts are used (like eastern
+ languages), use 'csv_utf16'. If localization gets in the way, use 'xml'.
+
+ Arguments:
+ - logformat: Text format to be generated, csv, csv_utf16 or xml.
+
+ Use "tracerpt -?" for help.
+ """
+ LOCALE_INVARIANT = 0x7F
+ windll.kernel32.SetThreadLocale(LOCALE_INVARIANT)
+ cmd_convert = [
+ 'tracerpt.exe',
+ '-l', self._logname + '.etl',
+ '-o', self._logname + '.' + logformat,
+ '-gmt', # Use UTC
+ '-y', # No prompt
+ # Use -of XML to get the header of each items after column 19, e.g. all
+ # the actual headers of 'User Data'.
+ ]
+
+ if logformat == 'csv':
+ # tracerpt localizes the 'Type' column, for major brainfuck
+ # entertainment. I can't imagine any sane reason to do that.
+ cmd_convert.extend(['-of', 'CSV'])
+ elif logformat == 'csv_utf16':
+ # This causes it to use UTF-16, which doubles the log size but ensures
+ # the log is readable for non-ASCII characters.
+ cmd_convert.extend(['-of', 'CSV', '-en', 'Unicode'])
+ elif logformat == 'xml':
+ cmd_convert.extend(['-of', 'XML'])
+ else:
+ raise ValueError('Unexpected log format \'%s\'' % logformat)
+ logging.debug('Running: %s' % cmd_convert)
+ # This can takes tens of minutes for large logs.
+ # Redirects all output to stderr.
+ subprocess.check_call(
+ cmd_convert,
+ stdin=subprocess.PIPE,
+ stdout=sys.stderr,
+ stderr=sys.stderr)
+
+ def __init__(self, use_sudo=False): # pylint: disable=W0613
+ super(LogmanTrace, self).__init__()
+ # Ignore use_sudo. It's irrelevant on Windows but kept to simplify the API.
+
+ @staticmethod
+ def clean_trace(logname):
+ for ext in ('', '.csv', '.etl', '.json', '.xml', '.preprocessed'):
+ if os.path.isfile(logname + ext):
+ os.remove(logname + ext)
+
+ @classmethod
+ def parse_log(cls, logname, blacklist, trace_name):
+ logging.info('parse_log(%s, ..., %s)', logname, trace_name)
+ assert os.path.isabs(logname)
+
+ def blacklist_more(filepath):
+ # All the NTFS metadata is in the form x:\$EXTEND or stuff like that.
+ return blacklist(filepath) or re.match(r'[A-Z]\:\\\$EXTEND', filepath)
+
+ # Create a list of (Context, result_dict) tuples. This is necessary because
+ # the csv file may be larger than the amount of available memory.
+ contexes = [
+ (
+ cls.Context(
+ blacklist_more, item['pid'], item['trace'], item['thunk_cmd']),
+ {
+ 'output': item['output'],
+ 'trace': item['trace'],
+ },
+ )
+ for item in read_json(logname)['traces']
+ if not trace_name or item['trace'] == trace_name
+ ]
+
+ # The log may be too large to fit in memory and it is not efficient to read
+ # it multiple times, so multiplex the contexes instead, which is slightly
+ # more awkward.
+ with open('%s.preprocessed' % logname, 'rb') as f:
+ lines = csv.reader(
+ f, delimiter='$', quotechar='*', quoting=csv.QUOTE_MINIMAL)
+ for encoded in lines:
+ line = [s.decode('utf-8') for s in encoded]
+ # Convert the PID in-place from hex.
+ line[cls.Context.PID] = int(line[cls.Context.PID], 16)
+ for context in contexes:
+ if 'exception' in context[1]:
+ continue
+ try:
+ context[0].on_line(line)
+ except TracingFailure:
+ context[1]['exception'] = sys.exc_info()
+
+ for context in contexes:
+ if 'exception' in context[1]:
+ continue
+ context[1]['results'] = context[0].to_results()
+
+ return [context[1] for context in contexes]
+
+
+def get_api(**kwargs):
+ """Returns the correct implementation for the current OS."""
+ if sys.platform == 'cygwin':
+ raise NotImplementedError(
+ 'Not implemented for cygwin, start the script from Win32 python')
+ flavors = {
+ 'win32': LogmanTrace,
+ 'darwin': Dtrace,
+ 'sunos5': Dtrace,
+ 'freebsd7': Dtrace,
+ 'freebsd8': Dtrace,
+ }
+ # Defaults to strace.
+ return flavors.get(sys.platform, Strace)(**kwargs)
+
+
+def extract_directories(root_dir, files, blacklist):
+ """Detects if all the files in a directory are in |files| and if so, replace
+ the individual files by a Results.Directory instance.
+
+ Takes a list of Results.File instances and returns a shorter list of
+ Results.File and Results.Directory instances.
+
+ Arguments:
+ - root_dir: Optional base directory that shouldn't be search further.
+ - files: list of Results.File instances.
+ - blacklist: lambda to reject unneeded files, for example r'.+\.pyc'.
+ """
+ logging.info(
+ 'extract_directories(%s, %d files, ...)' % (root_dir, len(files)))
+ assert not (root_dir or '').endswith(os.path.sep), root_dir
+ # It is important for root_dir to not be a symlinked path, make sure to call
+ # os.path.realpath() as needed.
+ assert not root_dir or (
+ os.path.realpath(get_native_path_case(root_dir)) == root_dir)
+ assert not any(isinstance(f, Results.Directory) for f in files)
+ # Remove non existent files.
+ files = [f for f in files if f.existent]
+ if not files:
+ return files
+ # All files must share the same root, which can be None.
+ assert len(set(f.root for f in files)) == 1, set(f.root for f in files)
+
+ # Creates a {directory: {filename: File}} mapping, up to root.
+ buckets = {}
+ if root_dir:
+ buckets[root_dir] = {}
+ for fileobj in files:
+ path = fileobj.full_path
+ directory = os.path.dirname(path)
+ assert directory
+ # Do not use os.path.basename() so trailing os.path.sep is kept.
+ basename = path[len(directory)+1:]
+ files_in_directory = buckets.setdefault(directory, {})
+ files_in_directory[basename] = fileobj
+ # Add all the directories recursively up to root.
+ while True:
+ old_d = directory
+ directory = os.path.dirname(directory)
+ if directory + os.path.sep == root_dir or directory == old_d:
+ break
+ buckets.setdefault(directory, {})
+
+ root_prefix = len(root_dir) + 1 if root_dir else 0
+ for directory in sorted(buckets, reverse=True):
+ if not os.path.isdir(directory):
+ logging.debug(
+ '%s was a directory but doesn\'t exist anymore; ignoring', directory)
+ continue
+ actual = set(f for f in os.listdir(directory) if not blacklist(f))
+ expected = set(buckets[directory])
+ if not (actual - expected):
+ parent = os.path.dirname(directory)
+ buckets[parent][os.path.basename(directory)] = Results.Directory(
+ root_dir,
+ directory[root_prefix:],
+ False,
+ sum(f.size for f in buckets[directory].itervalues()),
+ sum(f.nb_files for f in buckets[directory].itervalues()))
+ # Remove the whole bucket.
+ del buckets[directory]
+
+ # Reverse the mapping with what remains. The original instances are returned,
+ # so the cached meta data is kept.
+ files = sum((x.values() for x in buckets.itervalues()), [])
+ return sorted(files, key=lambda x: x.path)
+
+
+def trace(logfile, cmd, cwd, api, output):
+ """Traces an executable. Returns (returncode, output) from api.
+
+ Arguments:
+ - logfile: file to write to.
+ - cmd: command to run.
+ - cwd: current directory to start the process in.
+ - api: a tracing api instance.
+ - output: if True, returns output, otherwise prints it at the console.
+ """
+ cmd = fix_python_path(cmd)
+ api.clean_trace(logfile)
+ with api.get_tracer(logfile) as tracer:
+ return tracer.trace(cmd, cwd, 'default', output)
+
+
+def CMDclean(args):
+ """Cleans up traces."""
+ parser = OptionParserTraceInputs(command='clean')
+ options, args = parser.parse_args(args)
+ api = get_api()
+ api.clean_trace(options.log)
+ return 0
+
+
+def CMDtrace(args):
+ """Traces an executable."""
+ parser = OptionParserTraceInputs(command='trace')
+ parser.allow_interspersed_args = False
+ parser.add_option(
+ '-q', '--quiet', action='store_true',
+ help='Redirects traced executable output to /dev/null')
+ parser.add_option(
+ '-s', '--sudo', action='store_true',
+ help='Use sudo when shelling out the tracer tool (ignored on Windows)')
+ parser.add_option(
+ '-n', '--no-sudo', action='store_false',
+ help='Don\'t use sudo')
+ options, args = parser.parse_args(args)
+
+ if not args:
+ parser.error('Please provide a command to run')
+
+ if not os.path.isabs(args[0]) and os.access(args[0], os.X_OK):
+ args[0] = os.path.abspath(args[0])
+
+ # options.sudo default value is None, which is to do whatever tracer defaults
+ # do.
+ api = get_api(use_sudo=options.sudo)
+ return trace(options.log, args, os.getcwd(), api, options.quiet)[0]
+
+
+def CMDread(args):
+ """Reads the logs and prints the result."""
+ parser = OptionParserTraceInputs(command='read')
+ parser.add_option(
+ '-V', '--variable',
+ nargs=2,
+ action='append',
+ dest='variables',
+ metavar='VAR_NAME directory',
+ default=[],
+ help=('Variables to replace relative directories against. Example: '
+ '"-v \'$HOME\' \'/home/%s\'" will replace all occurence of your '
+ 'home dir with $HOME') % getpass.getuser())
+ parser.add_option(
+ '--root-dir',
+ help='Root directory to base everything off it. Anything outside of this '
+ 'this directory will not be reported')
+ parser.add_option(
+ '--trace-name',
+ help='Only reads one of the trace. Defaults to reading all traces')
+ parser.add_option(
+ '-j', '--json', action='store_true',
+ help='Outputs raw result data as json')
+ parser.add_option(
+ '--trace-blacklist', action='append', default=[],
+ help='List of regexp to use as blacklist filter')
+ options, args = parser.parse_args(args)
+
+ if options.root_dir:
+ options.root_dir = get_native_path_case(
+ unicode(os.path.abspath(options.root_dir)))
+
+ variables = dict(options.variables)
+ api = get_api()
+ blacklist = gen_blacklist(options.trace_blacklist)
+ data = api.parse_log(options.log, blacklist, options.trace_name)
+ # Process each trace.
+ output_as_json = []
+ try:
+ for item in data:
+ if 'exception' in item:
+ # Do not abort the other traces.
+ print >> sys.stderr, (
+ 'Trace %s: Got an exception: %s' % (
+ item['trace'], item['exception'][1]))
+ continue
+ results = item['results']
+ if options.root_dir:
+ results = results.strip_root(options.root_dir)
+
+ if options.json:
+ output_as_json.append(results.flatten())
+ else:
+ simplified = extract_directories(
+ options.root_dir, results.files, blacklist)
+ simplified = [f.replace_variables(variables) for f in simplified]
+ if len(data) > 1:
+ print('Trace: %s' % item['trace'])
+ print('Total: %d' % len(results.files))
+ print('Non existent: %d' % len(results.non_existent))
+ for f in results.non_existent:
+ print(' %s' % f.path)
+ print(
+ 'Interesting: %d reduced to %d' % (
+ len(results.existent), len(simplified)))
+ for f in simplified:
+ print(' %s' % f.path)
+
+ if options.json:
+ write_json(sys.stdout, output_as_json, False)
+ except KeyboardInterrupt:
+ return 1
+ except IOError as e:
+ if e.errno == errno.EPIPE:
+ # Do not print a stack trace when the output is piped to less and the user
+ # quits before the whole output was written.
+ return 1
+ raise
+ return 0
+
+
+class OptionParserWithLogging(optparse.OptionParser):
+ """Adds --verbose option."""
+ def __init__(self, verbose=0, **kwargs):
+ optparse.OptionParser.__init__(self, **kwargs)
+ self.add_option(
+ '-v', '--verbose',
+ action='count',
+ default=verbose,
+ help='Use multiple times to increase verbosity')
+
+ def parse_args(self, *args, **kwargs):
+ options, args = optparse.OptionParser.parse_args(self, *args, **kwargs)
+ levels = [logging.ERROR, logging.INFO, logging.DEBUG]
+ logging.basicConfig(
+ level=levels[min(len(levels)-1, options.verbose)],
+ format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')
+ return options, args
+
+
+class OptionParserWithNiceDescription(OptionParserWithLogging):
+ """Generates the description with the command's docstring."""
+ def __init__(self, **kwargs):
+ """Sets 'description' and 'usage' if not already specified."""
+ command = kwargs.pop('command', 'help')
+ kwargs.setdefault(
+ 'description',
+ re.sub('[\r\n ]{2,}', ' ', get_command_handler(command).__doc__))
+ kwargs.setdefault('usage', '%%prog %s [options]' % command)
+ OptionParserWithLogging.__init__(self, **kwargs)
+
+
+class OptionParserTraceInputs(OptionParserWithNiceDescription):
+ """Adds automatic --log handling."""
+ def __init__(self, **kwargs):
+ OptionParserWithNiceDescription.__init__(self, **kwargs)
+ self.add_option(
+ '-l', '--log', help='Log file to generate or read, required')
+
+ def parse_args(self, *args, **kwargs):
+ """Makes sure the paths make sense.
+
+ On Windows, / and \ are often mixed together in a path.
+ """
+ options, args = OptionParserWithNiceDescription.parse_args(
+ self, *args, **kwargs)
+ if not options.log:
+ self.error('Must supply a log file with -l')
+ options.log = os.path.abspath(options.log)
+ return options, args
+
+
+def extract_documentation():
+ """Returns a dict {command: description} for each of documented command."""
+ commands = (
+ fn[3:]
+ for fn in dir(sys.modules['__main__'])
+ if fn.startswith('CMD') and get_command_handler(fn[3:]).__doc__)
+ return dict((fn, get_command_handler(fn).__doc__) for fn in commands)
+
+
+def CMDhelp(args):
+ """Prints list of commands or help for a specific command."""
+ doc = extract_documentation()
+ # Calculates the optimal offset.
+ offset = max(len(cmd) for cmd in doc)
+ format_str = ' %-' + str(offset + 2) + 's %s'
+ # Generate a one-liner documentation of each commands.
+ commands_description = '\n'.join(
+ format_str % (cmd, doc[cmd].split('\n')[0]) for cmd in sorted(doc))
+
+ parser = OptionParserWithNiceDescription(
+ usage='%prog <command> [options]',
+ description='Commands are:\n%s\n' % commands_description)
+ parser.format_description = lambda _: parser.description
+
+ # Strip out any -h or --help argument.
+ _, args = parser.parse_args([i for i in args if not i in ('-h', '--help')])
+ if len(args) == 1:
+ if not get_command_handler(args[0]):
+ parser.error('Unknown command %s' % args[0])
+ # The command was "%prog help command", replaces ourself with
+ # "%prog command --help" so help is correctly printed out.
+ return main(args + ['--help'])
+ elif args:
+ parser.error('Unknown argument "%s"' % ' '.join(args))
+ parser.print_help()
+ return 0
+
+
+def get_command_handler(name):
+ """Returns the command handler or CMDhelp if it doesn't exist."""
+ return getattr(sys.modules['__main__'], 'CMD%s' % name, None)
+
+
+def main_impl(argv):
+ command = get_command_handler(argv[0] if argv else 'help')
+ if not command:
+ return CMDhelp(argv)
+ return command(argv[1:])
+
+def main(argv):
+ disable_buffering()
+ try:
+ main_impl(argv)
+ except TracingFailure, e:
+ sys.stderr.write('\nError: ')
+ sys.stderr.write(str(e))
+ sys.stderr.write('\n')
+ return 1
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/swig/swig.py b/chromium/tools/swig/swig.py
new file mode 100755
index 00000000000..8f4babb98ae
--- /dev/null
+++ b/chromium/tools/swig/swig.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Wrapper around swig.
+
+Sets the SWIG_LIB environment var to point to Lib dir
+and defers control to the platform-specific swig binary.
+
+Depends on swig binaries being available at ../../third_party/swig.
+"""
+
+import os
+import subprocess
+import sys
+
+
+def main():
+ swig_dir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]),
+ os.pardir, os.pardir, 'third_party', 'swig'))
+ lib_dir = os.path.join(swig_dir, "Lib")
+ os.putenv("SWIG_LIB", lib_dir)
+ dir_map = {
+ 'darwin': 'mac',
+ 'linux2': 'linux',
+ 'linux3': 'linux',
+ 'win32': 'win',
+ }
+ # Swig documentation lies that platform macros are provided to swig
+ # preprocessor. Provide them ourselves.
+ platform_flags = {
+ 'darwin': '-DSWIGMAC',
+ 'linux2': '-DSWIGLINUX',
+ 'linux3': '-DSWIGLINUX',
+ 'win32': '-DSWIGWIN',
+ }
+ swig_bin = os.path.join(swig_dir, dir_map[sys.platform], 'swig')
+ args = [swig_bin, platform_flags[sys.platform]] + sys.argv[1:]
+ args = [x.replace('/', os.sep) for x in args]
+ return subprocess.call(args)
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/symsrc/COPYING-pefile b/chromium/tools/symsrc/COPYING-pefile
new file mode 100644
index 00000000000..70ca49f5d2e
--- /dev/null
+++ b/chromium/tools/symsrc/COPYING-pefile
@@ -0,0 +1,27 @@
+Copyright (c) 2004, 2005, 2006 Ero Carrera <ero@dkbza.org>. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+3. The name of the author may not be used to endorse or promote products
+derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGE.
+
+
diff --git a/chromium/tools/symsrc/README.chromium b/chromium/tools/symsrc/README.chromium
new file mode 100644
index 00000000000..0398fe0c89f
--- /dev/null
+++ b/chromium/tools/symsrc/README.chromium
@@ -0,0 +1,14 @@
+These files are related to the symbol and source server.
+
+This requires some Microsoft utilities. From a 32-bit WinDbg installation with
+source server support, copy the following files to this directory:
+ dbghelp.dll
+ pdbstr.exe
+ srctool.exe
+
+The follow files were copied from the BSD licensed pefile-1.2.9.1:
+ COPYING-pefile
+ pefile.py
+
+pefile is available from:
+ http://code.google.com/p/pefile/
diff --git a/chromium/tools/symsrc/img_fingerprint.py b/chromium/tools/symsrc/img_fingerprint.py
new file mode 100755
index 00000000000..c4b6395b87f
--- /dev/null
+++ b/chromium/tools/symsrc/img_fingerprint.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Retrieves an image's "fingerprint".
+
+This is used when retrieving the image from the symbol server. The .dll (or cab
+compressed .dl_) or .exe is expected at a path like:
+ foo.dll/FINGERPRINT/foo.dll
+"""
+
+import sys
+import pefile
+
+
+def GetImgFingerprint(filename):
+ """Returns the fingerprint for an image file"""
+ pe = pefile.PE(filename)
+ return "%08X%06x" % (
+ pe.FILE_HEADER.TimeDateStamp, pe.OPTIONAL_HEADER.SizeOfImage)
+
+
+def main():
+ if len(sys.argv) != 2:
+ print "usage: file.dll"
+ return 1
+
+ print GetImgFingerprint(sys.argv[1])
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/symsrc/pdb_fingerprint_from_img.py b/chromium/tools/symsrc/pdb_fingerprint_from_img.py
new file mode 100755
index 00000000000..e99447541a7
--- /dev/null
+++ b/chromium/tools/symsrc/pdb_fingerprint_from_img.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This will retrieve a PDBs "fingerprint" from it's corresponding executable
+image (.dll or .exe). This is used when retrieving the PDB from the symbol
+server. The .pdb (or cab compressed .pd_) is expected at a path like:
+ foo.pdb/FINGERPRINT/foo.pdb
+
+We can retrieve the same information from the .PDB file itself, but this file
+format is much more difficult and undocumented. Instead, we can look at the
+DLL's reference to the PDB, and use that to retrieve the information."""
+
+import sys
+import pefile
+
+
+__CV_INFO_PDB70_format__ = ('CV_INFO_PDB70',
+ ('4s,CvSignature', '16s,Signature', 'L,Age'))
+
+__GUID_format__ = ('GUID',
+ ('L,Data1', 'H,Data2', 'H,Data3', '8s,Data4'))
+
+
+def GetPDBInfoFromImg(filename):
+ """Returns the PDB fingerprint and the pdb filename given an image file"""
+
+ pe = pefile.PE(filename)
+
+ for dbg in pe.DIRECTORY_ENTRY_DEBUG:
+ if dbg.struct.Type == 2: # IMAGE_DEBUG_TYPE_CODEVIEW
+ off = dbg.struct.AddressOfRawData
+ size = dbg.struct.SizeOfData
+ data = pe.get_memory_mapped_image()[off:off+size]
+
+ cv = pefile.Structure(__CV_INFO_PDB70_format__)
+ cv.__unpack__(data)
+ cv.PdbFileName = data[cv.sizeof():]
+ guid = pefile.Structure(__GUID_format__)
+ guid.__unpack__(cv.Signature)
+ guid.Data4_0 = ''.join("%02X" % ord(x) for x in guid.Data4[0:2])
+ guid.Data4_1 = ''.join("%02X" % ord(x) for x in guid.Data4[2:])
+
+ return ("%08X%04X%04X%s%s%d" % (
+ guid.Data1, guid.Data2, guid.Data3,
+ guid.Data4_0, guid.Data4_1, cv.Age),
+ cv.PdbFileName.split('\x00', 1)[0])
+
+ break
+
+
+def main():
+ if len(sys.argv) != 2:
+ print "usage: file.dll"
+ return 1
+
+ (fingerprint, filename) = GetPDBInfoFromImg(sys.argv[1])
+ print "%s %s" % (fingerprint, filename)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/symsrc/pefile.py b/chromium/tools/symsrc/pefile.py
new file mode 100644
index 00000000000..e22fd1ae245
--- /dev/null
+++ b/chromium/tools/symsrc/pefile.py
@@ -0,0 +1,3729 @@
+# -*- coding: Latin-1 -*-
+"""pefile, Portable Executable reader module
+
+
+All the PE file basic structures are available with their default names
+as attributes of the instance returned.
+
+Processed elements such as the import table are made available with lowercase
+names, to differentiate them from the upper case basic structure names.
+
+pefile has been tested against the limits of valid PE headers, that is, malware.
+Lots of packed malware attempt to abuse the format way beyond its standard use.
+To the best of my knowledge most of the abuses are handled gracefully.
+
+Copyright (c) 2005, 2006, 2007, 2008 Ero Carrera <ero@dkbza.org>
+
+All rights reserved.
+
+For detailed copyright information see the file COPYING in
+the root of the distribution archive.
+"""
+
+__author__ = 'Ero Carrera'
+__version__ = '1.2.9.1'
+__contact__ = 'ero@dkbza.org'
+
+
+import os
+import struct
+import time
+import math
+import re
+import exceptions
+import string
+import array
+
+sha1, sha256, sha512, md5 = None, None, None, None
+
+try:
+ import hashlib
+ sha1 = hashlib.sha1
+ sha256 = hashlib.sha256
+ sha512 = hashlib.sha512
+ md5 = hashlib.md5
+except ImportError:
+ try:
+ import sha
+ sha1 = sha.new
+ except ImportError:
+ pass
+ try:
+ import md5
+ md5 = md5.new
+ except ImportError:
+ pass
+
+
+fast_load = False
+
+IMAGE_DOS_SIGNATURE = 0x5A4D
+IMAGE_OS2_SIGNATURE = 0x454E
+IMAGE_OS2_SIGNATURE_LE = 0x454C
+IMAGE_VXD_SIGNATURE = 0x454C
+IMAGE_NT_SIGNATURE = 0x00004550
+IMAGE_NUMBEROF_DIRECTORY_ENTRIES= 16
+IMAGE_ORDINAL_FLAG = 0x80000000L
+IMAGE_ORDINAL_FLAG64 = 0x8000000000000000L
+OPTIONAL_HEADER_MAGIC_PE = 0x10b
+OPTIONAL_HEADER_MAGIC_PE_PLUS = 0x20b
+
+
+directory_entry_types = [
+ ('IMAGE_DIRECTORY_ENTRY_EXPORT', 0),
+ ('IMAGE_DIRECTORY_ENTRY_IMPORT', 1),
+ ('IMAGE_DIRECTORY_ENTRY_RESOURCE', 2),
+ ('IMAGE_DIRECTORY_ENTRY_EXCEPTION', 3),
+ ('IMAGE_DIRECTORY_ENTRY_SECURITY', 4),
+ ('IMAGE_DIRECTORY_ENTRY_BASERELOC', 5),
+ ('IMAGE_DIRECTORY_ENTRY_DEBUG', 6),
+ ('IMAGE_DIRECTORY_ENTRY_COPYRIGHT', 7),
+ ('IMAGE_DIRECTORY_ENTRY_GLOBALPTR', 8),
+ ('IMAGE_DIRECTORY_ENTRY_TLS', 9),
+ ('IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG', 10),
+ ('IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT', 11),
+ ('IMAGE_DIRECTORY_ENTRY_IAT', 12),
+ ('IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT', 13),
+ ('IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR',14),
+ ('IMAGE_DIRECTORY_ENTRY_RESERVED', 15) ]
+
+DIRECTORY_ENTRY = dict([(e[1], e[0]) for e in directory_entry_types]+directory_entry_types)
+
+
+image_characteristics = [
+ ('IMAGE_FILE_RELOCS_STRIPPED', 0x0001),
+ ('IMAGE_FILE_EXECUTABLE_IMAGE', 0x0002),
+ ('IMAGE_FILE_LINE_NUMS_STRIPPED', 0x0004),
+ ('IMAGE_FILE_LOCAL_SYMS_STRIPPED', 0x0008),
+ ('IMAGE_FILE_AGGRESIVE_WS_TRIM', 0x0010),
+ ('IMAGE_FILE_LARGE_ADDRESS_AWARE', 0x0020),
+ ('IMAGE_FILE_16BIT_MACHINE', 0x0040),
+ ('IMAGE_FILE_BYTES_REVERSED_LO', 0x0080),
+ ('IMAGE_FILE_32BIT_MACHINE', 0x0100),
+ ('IMAGE_FILE_DEBUG_STRIPPED', 0x0200),
+ ('IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP', 0x0400),
+ ('IMAGE_FILE_NET_RUN_FROM_SWAP', 0x0800),
+ ('IMAGE_FILE_SYSTEM', 0x1000),
+ ('IMAGE_FILE_DLL', 0x2000),
+ ('IMAGE_FILE_UP_SYSTEM_ONLY', 0x4000),
+ ('IMAGE_FILE_BYTES_REVERSED_HI', 0x8000) ]
+
+IMAGE_CHARACTERISTICS = dict([(e[1], e[0]) for e in
+ image_characteristics]+image_characteristics)
+
+
+section_characteristics = [
+ ('IMAGE_SCN_CNT_CODE', 0x00000020),
+ ('IMAGE_SCN_CNT_INITIALIZED_DATA', 0x00000040),
+ ('IMAGE_SCN_CNT_UNINITIALIZED_DATA', 0x00000080),
+ ('IMAGE_SCN_LNK_OTHER', 0x00000100),
+ ('IMAGE_SCN_LNK_INFO', 0x00000200),
+ ('IMAGE_SCN_LNK_REMOVE', 0x00000800),
+ ('IMAGE_SCN_LNK_COMDAT', 0x00001000),
+ ('IMAGE_SCN_MEM_FARDATA', 0x00008000),
+ ('IMAGE_SCN_MEM_PURGEABLE', 0x00020000),
+ ('IMAGE_SCN_MEM_16BIT', 0x00020000),
+ ('IMAGE_SCN_MEM_LOCKED', 0x00040000),
+ ('IMAGE_SCN_MEM_PRELOAD', 0x00080000),
+ ('IMAGE_SCN_ALIGN_1BYTES', 0x00100000),
+ ('IMAGE_SCN_ALIGN_2BYTES', 0x00200000),
+ ('IMAGE_SCN_ALIGN_4BYTES', 0x00300000),
+ ('IMAGE_SCN_ALIGN_8BYTES', 0x00400000),
+ ('IMAGE_SCN_ALIGN_16BYTES', 0x00500000),
+ ('IMAGE_SCN_ALIGN_32BYTES', 0x00600000),
+ ('IMAGE_SCN_ALIGN_64BYTES', 0x00700000),
+ ('IMAGE_SCN_ALIGN_128BYTES', 0x00800000),
+ ('IMAGE_SCN_ALIGN_256BYTES', 0x00900000),
+ ('IMAGE_SCN_ALIGN_512BYTES', 0x00A00000),
+ ('IMAGE_SCN_ALIGN_1024BYTES', 0x00B00000),
+ ('IMAGE_SCN_ALIGN_2048BYTES', 0x00C00000),
+ ('IMAGE_SCN_ALIGN_4096BYTES', 0x00D00000),
+ ('IMAGE_SCN_ALIGN_8192BYTES', 0x00E00000),
+ ('IMAGE_SCN_ALIGN_MASK', 0x00F00000),
+ ('IMAGE_SCN_LNK_NRELOC_OVFL', 0x01000000),
+ ('IMAGE_SCN_MEM_DISCARDABLE', 0x02000000),
+ ('IMAGE_SCN_MEM_NOT_CACHED', 0x04000000),
+ ('IMAGE_SCN_MEM_NOT_PAGED', 0x08000000),
+ ('IMAGE_SCN_MEM_SHARED', 0x10000000),
+ ('IMAGE_SCN_MEM_EXECUTE', 0x20000000),
+ ('IMAGE_SCN_MEM_READ', 0x40000000),
+ ('IMAGE_SCN_MEM_WRITE', 0x80000000L) ]
+
+SECTION_CHARACTERISTICS = dict([(e[1], e[0]) for e in
+ section_characteristics]+section_characteristics)
+
+
+debug_types = [
+ ('IMAGE_DEBUG_TYPE_UNKNOWN', 0),
+ ('IMAGE_DEBUG_TYPE_COFF', 1),
+ ('IMAGE_DEBUG_TYPE_CODEVIEW', 2),
+ ('IMAGE_DEBUG_TYPE_FPO', 3),
+ ('IMAGE_DEBUG_TYPE_MISC', 4),
+ ('IMAGE_DEBUG_TYPE_EXCEPTION', 5),
+ ('IMAGE_DEBUG_TYPE_FIXUP', 6),
+ ('IMAGE_DEBUG_TYPE_OMAP_TO_SRC', 7),
+ ('IMAGE_DEBUG_TYPE_OMAP_FROM_SRC', 8),
+ ('IMAGE_DEBUG_TYPE_BORLAND', 9),
+ ('IMAGE_DEBUG_TYPE_RESERVED10', 10) ]
+
+DEBUG_TYPE = dict([(e[1], e[0]) for e in debug_types]+debug_types)
+
+
+subsystem_types = [
+ ('IMAGE_SUBSYSTEM_UNKNOWN', 0),
+ ('IMAGE_SUBSYSTEM_NATIVE', 1),
+ ('IMAGE_SUBSYSTEM_WINDOWS_GUI', 2),
+ ('IMAGE_SUBSYSTEM_WINDOWS_CUI', 3),
+ ('IMAGE_SUBSYSTEM_OS2_CUI', 5),
+ ('IMAGE_SUBSYSTEM_POSIX_CUI', 7),
+ ('IMAGE_SUBSYSTEM_WINDOWS_CE_GUI', 9),
+ ('IMAGE_SUBSYSTEM_EFI_APPLICATION', 10),
+ ('IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER', 11),
+ ('IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER', 12),
+ ('IMAGE_SUBSYSTEM_EFI_ROM', 13),
+ ('IMAGE_SUBSYSTEM_XBOX', 14)]
+
+SUBSYSTEM_TYPE = dict([(e[1], e[0]) for e in subsystem_types]+subsystem_types)
+
+
+machine_types = [
+ ('IMAGE_FILE_MACHINE_UNKNOWN', 0),
+ ('IMAGE_FILE_MACHINE_AM33', 0x1d3),
+ ('IMAGE_FILE_MACHINE_AMD64', 0x8664),
+ ('IMAGE_FILE_MACHINE_ARM', 0x1c0),
+ ('IMAGE_FILE_MACHINE_EBC', 0xebc),
+ ('IMAGE_FILE_MACHINE_I386', 0x14c),
+ ('IMAGE_FILE_MACHINE_IA64', 0x200),
+ ('IMAGE_FILE_MACHINE_MR32', 0x9041),
+ ('IMAGE_FILE_MACHINE_MIPS16', 0x266),
+ ('IMAGE_FILE_MACHINE_MIPSFPU', 0x366),
+ ('IMAGE_FILE_MACHINE_MIPSFPU16',0x466),
+ ('IMAGE_FILE_MACHINE_POWERPC', 0x1f0),
+ ('IMAGE_FILE_MACHINE_POWERPCFP',0x1f1),
+ ('IMAGE_FILE_MACHINE_R4000', 0x166),
+ ('IMAGE_FILE_MACHINE_SH3', 0x1a2),
+ ('IMAGE_FILE_MACHINE_SH3DSP', 0x1a3),
+ ('IMAGE_FILE_MACHINE_SH4', 0x1a6),
+ ('IMAGE_FILE_MACHINE_SH5', 0x1a8),
+ ('IMAGE_FILE_MACHINE_THUMB', 0x1c2),
+ ('IMAGE_FILE_MACHINE_WCEMIPSV2',0x169),
+ ]
+
+MACHINE_TYPE = dict([(e[1], e[0]) for e in machine_types]+machine_types)
+
+
+relocation_types = [
+ ('IMAGE_REL_BASED_ABSOLUTE', 0),
+ ('IMAGE_REL_BASED_HIGH', 1),
+ ('IMAGE_REL_BASED_LOW', 2),
+ ('IMAGE_REL_BASED_HIGHLOW', 3),
+ ('IMAGE_REL_BASED_HIGHADJ', 4),
+ ('IMAGE_REL_BASED_MIPS_JMPADDR', 5),
+ ('IMAGE_REL_BASED_SECTION', 6),
+ ('IMAGE_REL_BASED_REL', 7),
+ ('IMAGE_REL_BASED_MIPS_JMPADDR16', 9),
+ ('IMAGE_REL_BASED_IA64_IMM64', 9),
+ ('IMAGE_REL_BASED_DIR64', 10),
+ ('IMAGE_REL_BASED_HIGH3ADJ', 11) ]
+
+RELOCATION_TYPE = dict([(e[1], e[0]) for e in relocation_types]+relocation_types)
+
+
+dll_characteristics = [
+ ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x0001', 0x0001),
+ ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x0002', 0x0002),
+ ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x0004', 0x0004),
+ ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x0008', 0x0008),
+ ('IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE', 0x0040),
+ ('IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY', 0x0080),
+ ('IMAGE_DLL_CHARACTERISTICS_NX_COMPAT', 0x0100),
+ ('IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION', 0x0200),
+ ('IMAGE_DLL_CHARACTERISTICS_NO_SEH', 0x0400),
+ ('IMAGE_DLL_CHARACTERISTICS_NO_BIND', 0x0800),
+ ('IMAGE_DLL_CHARACTERISTICS_RESERVED_0x1000', 0x1000),
+ ('IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER', 0x2000),
+ ('IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE', 0x8000) ]
+
+DLL_CHARACTERISTICS = dict([(e[1], e[0]) for e in dll_characteristics]+dll_characteristics)
+
+
+# Resource types
+resource_type = [
+ ('RT_CURSOR', 1),
+ ('RT_BITMAP', 2),
+ ('RT_ICON', 3),
+ ('RT_MENU', 4),
+ ('RT_DIALOG', 5),
+ ('RT_STRING', 6),
+ ('RT_FONTDIR', 7),
+ ('RT_FONT', 8),
+ ('RT_ACCELERATOR', 9),
+ ('RT_RCDATA', 10),
+ ('RT_MESSAGETABLE', 11),
+ ('RT_GROUP_CURSOR', 12),
+ ('RT_GROUP_ICON', 14),
+ ('RT_VERSION', 16),
+ ('RT_DLGINCLUDE', 17),
+ ('RT_PLUGPLAY', 19),
+ ('RT_VXD', 20),
+ ('RT_ANICURSOR', 21),
+ ('RT_ANIICON', 22),
+ ('RT_HTML', 23),
+ ('RT_MANIFEST', 24) ]
+
+RESOURCE_TYPE = dict([(e[1], e[0]) for e in resource_type]+resource_type)
+
+
+# Language definitions
+lang = [
+ ('LANG_NEUTRAL', 0x00),
+ ('LANG_INVARIANT', 0x7f),
+ ('LANG_AFRIKAANS', 0x36),
+ ('LANG_ALBANIAN', 0x1c),
+ ('LANG_ARABIC', 0x01),
+ ('LANG_ARMENIAN', 0x2b),
+ ('LANG_ASSAMESE', 0x4d),
+ ('LANG_AZERI', 0x2c),
+ ('LANG_BASQUE', 0x2d),
+ ('LANG_BELARUSIAN', 0x23),
+ ('LANG_BENGALI', 0x45),
+ ('LANG_BULGARIAN', 0x02),
+ ('LANG_CATALAN', 0x03),
+ ('LANG_CHINESE', 0x04),
+ ('LANG_CROATIAN', 0x1a),
+ ('LANG_CZECH', 0x05),
+ ('LANG_DANISH', 0x06),
+ ('LANG_DIVEHI', 0x65),
+ ('LANG_DUTCH', 0x13),
+ ('LANG_ENGLISH', 0x09),
+ ('LANG_ESTONIAN', 0x25),
+ ('LANG_FAEROESE', 0x38),
+ ('LANG_FARSI', 0x29),
+ ('LANG_FINNISH', 0x0b),
+ ('LANG_FRENCH', 0x0c),
+ ('LANG_GALICIAN', 0x56),
+ ('LANG_GEORGIAN', 0x37),
+ ('LANG_GERMAN', 0x07),
+ ('LANG_GREEK', 0x08),
+ ('LANG_GUJARATI', 0x47),
+ ('LANG_HEBREW', 0x0d),
+ ('LANG_HINDI', 0x39),
+ ('LANG_HUNGARIAN', 0x0e),
+ ('LANG_ICELANDIC', 0x0f),
+ ('LANG_INDONESIAN', 0x21),
+ ('LANG_ITALIAN', 0x10),
+ ('LANG_JAPANESE', 0x11),
+ ('LANG_KANNADA', 0x4b),
+ ('LANG_KASHMIRI', 0x60),
+ ('LANG_KAZAK', 0x3f),
+ ('LANG_KONKANI', 0x57),
+ ('LANG_KOREAN', 0x12),
+ ('LANG_KYRGYZ', 0x40),
+ ('LANG_LATVIAN', 0x26),
+ ('LANG_LITHUANIAN', 0x27),
+ ('LANG_MACEDONIAN', 0x2f),
+ ('LANG_MALAY', 0x3e),
+ ('LANG_MALAYALAM', 0x4c),
+ ('LANG_MANIPURI', 0x58),
+ ('LANG_MARATHI', 0x4e),
+ ('LANG_MONGOLIAN', 0x50),
+ ('LANG_NEPALI', 0x61),
+ ('LANG_NORWEGIAN', 0x14),
+ ('LANG_ORIYA', 0x48),
+ ('LANG_POLISH', 0x15),
+ ('LANG_PORTUGUESE', 0x16),
+ ('LANG_PUNJABI', 0x46),
+ ('LANG_ROMANIAN', 0x18),
+ ('LANG_RUSSIAN', 0x19),
+ ('LANG_SANSKRIT', 0x4f),
+ ('LANG_SERBIAN', 0x1a),
+ ('LANG_SINDHI', 0x59),
+ ('LANG_SLOVAK', 0x1b),
+ ('LANG_SLOVENIAN', 0x24),
+ ('LANG_SPANISH', 0x0a),
+ ('LANG_SWAHILI', 0x41),
+ ('LANG_SWEDISH', 0x1d),
+ ('LANG_SYRIAC', 0x5a),
+ ('LANG_TAMIL', 0x49),
+ ('LANG_TATAR', 0x44),
+ ('LANG_TELUGU', 0x4a),
+ ('LANG_THAI', 0x1e),
+ ('LANG_TURKISH', 0x1f),
+ ('LANG_UKRAINIAN', 0x22),
+ ('LANG_URDU', 0x20),
+ ('LANG_UZBEK', 0x43),
+ ('LANG_VIETNAMESE', 0x2a),
+ ('LANG_GAELIC', 0x3c),
+ ('LANG_MALTESE', 0x3a),
+ ('LANG_MAORI', 0x28),
+ ('LANG_RHAETO_ROMANCE',0x17),
+ ('LANG_SAAMI', 0x3b),
+ ('LANG_SORBIAN', 0x2e),
+ ('LANG_SUTU', 0x30),
+ ('LANG_TSONGA', 0x31),
+ ('LANG_TSWANA', 0x32),
+ ('LANG_VENDA', 0x33),
+ ('LANG_XHOSA', 0x34),
+ ('LANG_ZULU', 0x35),
+ ('LANG_ESPERANTO', 0x8f),
+ ('LANG_WALON', 0x90),
+ ('LANG_CORNISH', 0x91),
+ ('LANG_WELSH', 0x92),
+ ('LANG_BRETON', 0x93) ]
+
+LANG = dict(lang+[(e[1], e[0]) for e in lang])
+
+
+# Sublanguage definitions
+sublang = [
+ ('SUBLANG_NEUTRAL', 0x00),
+ ('SUBLANG_DEFAULT', 0x01),
+ ('SUBLANG_SYS_DEFAULT', 0x02),
+ ('SUBLANG_ARABIC_SAUDI_ARABIA', 0x01),
+ ('SUBLANG_ARABIC_IRAQ', 0x02),
+ ('SUBLANG_ARABIC_EGYPT', 0x03),
+ ('SUBLANG_ARABIC_LIBYA', 0x04),
+ ('SUBLANG_ARABIC_ALGERIA', 0x05),
+ ('SUBLANG_ARABIC_MOROCCO', 0x06),
+ ('SUBLANG_ARABIC_TUNISIA', 0x07),
+ ('SUBLANG_ARABIC_OMAN', 0x08),
+ ('SUBLANG_ARABIC_YEMEN', 0x09),
+ ('SUBLANG_ARABIC_SYRIA', 0x0a),
+ ('SUBLANG_ARABIC_JORDAN', 0x0b),
+ ('SUBLANG_ARABIC_LEBANON', 0x0c),
+ ('SUBLANG_ARABIC_KUWAIT', 0x0d),
+ ('SUBLANG_ARABIC_UAE', 0x0e),
+ ('SUBLANG_ARABIC_BAHRAIN', 0x0f),
+ ('SUBLANG_ARABIC_QATAR', 0x10),
+ ('SUBLANG_AZERI_LATIN', 0x01),
+ ('SUBLANG_AZERI_CYRILLIC', 0x02),
+ ('SUBLANG_CHINESE_TRADITIONAL', 0x01),
+ ('SUBLANG_CHINESE_SIMPLIFIED', 0x02),
+ ('SUBLANG_CHINESE_HONGKONG', 0x03),
+ ('SUBLANG_CHINESE_SINGAPORE', 0x04),
+ ('SUBLANG_CHINESE_MACAU', 0x05),
+ ('SUBLANG_DUTCH', 0x01),
+ ('SUBLANG_DUTCH_BELGIAN', 0x02),
+ ('SUBLANG_ENGLISH_US', 0x01),
+ ('SUBLANG_ENGLISH_UK', 0x02),
+ ('SUBLANG_ENGLISH_AUS', 0x03),
+ ('SUBLANG_ENGLISH_CAN', 0x04),
+ ('SUBLANG_ENGLISH_NZ', 0x05),
+ ('SUBLANG_ENGLISH_EIRE', 0x06),
+ ('SUBLANG_ENGLISH_SOUTH_AFRICA', 0x07),
+ ('SUBLANG_ENGLISH_JAMAICA', 0x08),
+ ('SUBLANG_ENGLISH_CARIBBEAN', 0x09),
+ ('SUBLANG_ENGLISH_BELIZE', 0x0a),
+ ('SUBLANG_ENGLISH_TRINIDAD', 0x0b),
+ ('SUBLANG_ENGLISH_ZIMBABWE', 0x0c),
+ ('SUBLANG_ENGLISH_PHILIPPINES', 0x0d),
+ ('SUBLANG_FRENCH', 0x01),
+ ('SUBLANG_FRENCH_BELGIAN', 0x02),
+ ('SUBLANG_FRENCH_CANADIAN', 0x03),
+ ('SUBLANG_FRENCH_SWISS', 0x04),
+ ('SUBLANG_FRENCH_LUXEMBOURG', 0x05),
+ ('SUBLANG_FRENCH_MONACO', 0x06),
+ ('SUBLANG_GERMAN', 0x01),
+ ('SUBLANG_GERMAN_SWISS', 0x02),
+ ('SUBLANG_GERMAN_AUSTRIAN', 0x03),
+ ('SUBLANG_GERMAN_LUXEMBOURG', 0x04),
+ ('SUBLANG_GERMAN_LIECHTENSTEIN', 0x05),
+ ('SUBLANG_ITALIAN', 0x01),
+ ('SUBLANG_ITALIAN_SWISS', 0x02),
+ ('SUBLANG_KASHMIRI_SASIA', 0x02),
+ ('SUBLANG_KASHMIRI_INDIA', 0x02),
+ ('SUBLANG_KOREAN', 0x01),
+ ('SUBLANG_LITHUANIAN', 0x01),
+ ('SUBLANG_MALAY_MALAYSIA', 0x01),
+ ('SUBLANG_MALAY_BRUNEI_DARUSSALAM', 0x02),
+ ('SUBLANG_NEPALI_INDIA', 0x02),
+ ('SUBLANG_NORWEGIAN_BOKMAL', 0x01),
+ ('SUBLANG_NORWEGIAN_NYNORSK', 0x02),
+ ('SUBLANG_PORTUGUESE', 0x02),
+ ('SUBLANG_PORTUGUESE_BRAZILIAN', 0x01),
+ ('SUBLANG_SERBIAN_LATIN', 0x02),
+ ('SUBLANG_SERBIAN_CYRILLIC', 0x03),
+ ('SUBLANG_SPANISH', 0x01),
+ ('SUBLANG_SPANISH_MEXICAN', 0x02),
+ ('SUBLANG_SPANISH_MODERN', 0x03),
+ ('SUBLANG_SPANISH_GUATEMALA', 0x04),
+ ('SUBLANG_SPANISH_COSTA_RICA', 0x05),
+ ('SUBLANG_SPANISH_PANAMA', 0x06),
+ ('SUBLANG_SPANISH_DOMINICAN_REPUBLIC', 0x07),
+ ('SUBLANG_SPANISH_VENEZUELA', 0x08),
+ ('SUBLANG_SPANISH_COLOMBIA', 0x09),
+ ('SUBLANG_SPANISH_PERU', 0x0a),
+ ('SUBLANG_SPANISH_ARGENTINA', 0x0b),
+ ('SUBLANG_SPANISH_ECUADOR', 0x0c),
+ ('SUBLANG_SPANISH_CHILE', 0x0d),
+ ('SUBLANG_SPANISH_URUGUAY', 0x0e),
+ ('SUBLANG_SPANISH_PARAGUAY', 0x0f),
+ ('SUBLANG_SPANISH_BOLIVIA', 0x10),
+ ('SUBLANG_SPANISH_EL_SALVADOR', 0x11),
+ ('SUBLANG_SPANISH_HONDURAS', 0x12),
+ ('SUBLANG_SPANISH_NICARAGUA', 0x13),
+ ('SUBLANG_SPANISH_PUERTO_RICO', 0x14),
+ ('SUBLANG_SWEDISH', 0x01),
+ ('SUBLANG_SWEDISH_FINLAND', 0x02),
+ ('SUBLANG_URDU_PAKISTAN', 0x01),
+ ('SUBLANG_URDU_INDIA', 0x02),
+ ('SUBLANG_UZBEK_LATIN', 0x01),
+ ('SUBLANG_UZBEK_CYRILLIC', 0x02),
+ ('SUBLANG_DUTCH_SURINAM', 0x03),
+ ('SUBLANG_ROMANIAN', 0x01),
+ ('SUBLANG_ROMANIAN_MOLDAVIA', 0x02),
+ ('SUBLANG_RUSSIAN', 0x01),
+ ('SUBLANG_RUSSIAN_MOLDAVIA', 0x02),
+ ('SUBLANG_CROATIAN', 0x01),
+ ('SUBLANG_LITHUANIAN_CLASSIC', 0x02),
+ ('SUBLANG_GAELIC', 0x01),
+ ('SUBLANG_GAELIC_SCOTTISH', 0x02),
+ ('SUBLANG_GAELIC_MANX', 0x03) ]
+
+SUBLANG = dict(sublang+[(e[1], e[0]) for e in sublang])
+
+
+class UnicodeStringWrapperPostProcessor:
+ """This class attemps to help the process of identifying strings
+ that might be plain Unicode or Pascal. A list of strings will be
+ wrapped on it with the hope the overlappings will help make the
+ decission about their type."""
+
+ def __init__(self, pe, rva_ptr):
+ self.pe = pe
+ self.rva_ptr = rva_ptr
+ self.string = None
+
+
+ def get_rva(self):
+ """Get the RVA of the string."""
+
+ return self.rva_ptr
+
+
+ def __str__(self):
+ """Return the escaped ASCII representation of the string."""
+
+ def convert_char(char):
+ if char in string.printable:
+ return char
+ else:
+ return r'\x%02x' % ord(char)
+
+ if self.string:
+ return ''.join([convert_char(c) for c in self.string])
+
+ return ''
+
+
+ def invalidate(self):
+ """Make this instance None, to express it's no known string type."""
+
+ self = None
+
+
+ def render_pascal_16(self):
+
+ self.string = self.pe.get_string_u_at_rva(
+ self.rva_ptr+2,
+ max_length=self.__get_pascal_16_length())
+
+
+ def ask_pascal_16(self, next_rva_ptr):
+ """The next RVA is taken to be the one immediately following this one.
+
+ Such RVA could indicate the natural end of the string and will be checked
+ with the possible length contained in the first word.
+ """
+
+ length = self.__get_pascal_16_length()
+
+ if length == (next_rva_ptr - (self.rva_ptr+2)) / 2:
+ self.length = length
+ return True
+
+ return False
+
+
+ def __get_pascal_16_length(self):
+
+ return self.__get_word_value_at_rva(self.rva_ptr)
+
+
+ def __get_word_value_at_rva(self, rva):
+
+ try:
+ data = self.pe.get_data(self.rva_ptr, 2)
+ except PEFormatError, e:
+ return False
+
+ if len(data)<2:
+ return False
+
+ return struct.unpack('<H', data)[0]
+
+
+ #def render_pascal_8(self):
+ # """"""
+
+
+ def ask_unicode_16(self, next_rva_ptr):
+ """The next RVA is taken to be the one immediately following this one.
+
+ Such RVA could indicate the natural end of the string and will be checked
+ to see if there's a Unicode NULL character there.
+ """
+
+ if self.__get_word_value_at_rva(next_rva_ptr-2) == 0:
+ self.length = next_rva_ptr - self.rva_ptr
+ return True
+
+ return False
+
+
+ def render_unicode_16(self):
+ """"""
+
+ self.string = self.pe.get_string_u_at_rva(self.rva_ptr)
+
+
+class PEFormatError(Exception):
+ """Generic PE format error exception."""
+
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return repr(self.value)
+
+
+class Dump:
+ """Convenience class for dumping the PE information."""
+
+ def __init__(self):
+ self.text = ''
+
+
+ def add_lines(self, txt, indent=0):
+ """Adds a list of lines.
+
+ The list can be indented with the optional argument 'indent'.
+ """
+ for line in txt:
+ self.add_line(line, indent)
+
+
+ def add_line(self, txt, indent=0):
+ """Adds a line.
+
+ The line can be indented with the optional argument 'indent'.
+ """
+
+ self.add(txt+'\n', indent)
+
+
+ def add(self, txt, indent=0):
+ """Adds some text, no newline will be appended.
+
+ The text can be indented with the optional argument 'indent'.
+ """
+
+ if isinstance(txt, unicode):
+ s = []
+ for c in txt:
+ try:
+ s.append(str(c))
+ except UnicodeEncodeError, e:
+ s.append(repr(c))
+
+ txt = ''.join(s)
+
+ self.text += ' '*indent+txt
+
+
+ def add_header(self, txt):
+ """Adds a header element."""
+
+ self.add_line('-'*10+txt+'-'*10+'\n')
+
+
+ def add_newline(self):
+ """Adds a newline."""
+
+ self.text += '\n'
+
+
+ def get_text(self):
+ """Get the text in its current state."""
+
+ return self.text
+
+
+
+class Structure:
+ """Prepare structure object to extract members from data.
+
+ Format is a list containing definitions for the elements
+ of the structure.
+ """
+
+
+ def __init__(self, format, name=None, file_offset=None):
+ # Format is forced little endian, for big endian non Intel platforms
+ self.__format__ = '<'
+ self.__keys__ = []
+# self.values = {}
+ self.__format_length__ = 0
+ self.__set_format__(format[1])
+ self._all_zeroes = False
+ self.__unpacked_data_elms__ = None
+ self.__file_offset__ = file_offset
+ if name:
+ self.name = name
+ else:
+ self.name = format[0]
+
+
+ def __get_format__(self):
+ return self.__format__
+
+
+ def get_file_offset(self):
+ return self.__file_offset__
+
+ def set_file_offset(self, offset):
+ self.__file_offset__ = offset
+
+ def all_zeroes(self):
+ """Returns true is the unpacked data is all zeroes."""
+
+ return self._all_zeroes
+
+
+ def __set_format__(self, format):
+
+ for elm in format:
+ if ',' in elm:
+ elm_type, elm_name = elm.split(',', 1)
+ self.__format__ += elm_type
+
+ elm_names = elm_name.split(',')
+ names = []
+ for elm_name in elm_names:
+ if elm_name in self.__keys__:
+ search_list = [x[:len(elm_name)] for x in self.__keys__]
+ occ_count = search_list.count(elm_name)
+ elm_name = elm_name+'_'+str(occ_count)
+ names.append(elm_name)
+ # Some PE header structures have unions on them, so a certain
+ # value might have different names, so each key has a list of
+ # all the possible members referring to the data.
+ self.__keys__.append(names)
+
+ self.__format_length__ = struct.calcsize(self.__format__)
+
+
+ def sizeof(self):
+ """Return size of the structure."""
+
+ return self.__format_length__
+
+
+ def __unpack__(self, data):
+
+ if len(data)>self.__format_length__:
+ data = data[:self.__format_length__]
+
+ # OC Patch:
+ # Some malware have incorrect header lengths.
+ # Fail gracefully if this occurs
+ # Buggy malware: a29b0118af8b7408444df81701ad5a7f
+ #
+ elif len(data)<self.__format_length__:
+ raise PEFormatError('Data length less than expected header length.')
+
+
+ if data.count(chr(0)) == len(data):
+ self._all_zeroes = True
+
+ self.__unpacked_data_elms__ = struct.unpack(self.__format__, data)
+ for i in xrange(len(self.__unpacked_data_elms__)):
+ for key in self.__keys__[i]:
+# self.values[key] = self.__unpacked_data_elms__[i]
+ setattr(self, key, self.__unpacked_data_elms__[i])
+
+
+ def __pack__(self):
+
+ new_values = []
+
+ for i in xrange(len(self.__unpacked_data_elms__)):
+
+ for key in self.__keys__[i]:
+ new_val = getattr(self, key)
+ old_val = self.__unpacked_data_elms__[i]
+
+ # In the case of Unions, when the first changed value
+ # is picked the loop is exited
+ if new_val != old_val:
+ break
+
+ new_values.append(new_val)
+
+ return struct.pack(self.__format__, *new_values)
+
+
+ def __str__(self):
+ return '\n'.join( self.dump() )
+
+ def __repr__(self):
+ return '<Structure: %s>' % (' '.join( [' '.join(s.split()) for s in self.dump()] ))
+
+
+ def dump(self, indentation=0):
+ """Returns a string representation of the structure."""
+
+ dump = []
+
+ dump.append('[%s]' % self.name)
+
+ # Refer to the __set_format__ method for an explanation
+ # of the following construct.
+ for keys in self.__keys__:
+ for key in keys:
+
+ val = getattr(self, key)
+ if isinstance(val, int) or isinstance(val, long):
+ val_str = '0x%-8X' % (val)
+ if key == 'TimeDateStamp' or key == 'dwTimeStamp':
+ try:
+ val_str += ' [%s UTC]' % time.asctime(time.gmtime(val))
+ except exceptions.ValueError, e:
+ val_str += ' [INVALID TIME]'
+ else:
+ val_str = ''.join(filter(lambda c:c != '\0', str(val)))
+
+ dump.append('%-30s %s' % (key+':', val_str))
+
+ return dump
+
+
+
+class SectionStructure(Structure):
+ """Convenience section handling class."""
+
+ def get_data(self, start, length=None):
+ """Get data chunk from a section.
+
+ Allows to query data from the section by passing the
+ addresses where the PE file would be loaded by default.
+ It is then possible to retrieve code and data by its real
+ addresses as it would be if loaded.
+ """
+
+ offset = start - self.VirtualAddress
+
+ if length:
+ end = offset+length
+ else:
+ end = len(self.data)
+
+ return self.data[offset:end]
+
+
+ def get_rva_from_offset(self, offset):
+ return offset - self.PointerToRawData + self.VirtualAddress
+
+
+ def get_offset_from_rva(self, rva):
+ return (rva - self.VirtualAddress) + self.PointerToRawData
+
+
+ def contains_offset(self, offset):
+ """Check whether the section contains the file offset provided."""
+
+ if not self.PointerToRawData:
+ # bss and other sections containing only uninitialized data must have 0
+ # and do not take space in the file
+ return False
+ return self.PointerToRawData <= offset < self.VirtualAddress + self.SizeOfRawData
+
+
+ def contains_rva(self, rva):
+ """Check whether the section contains the address provided."""
+
+ # PECOFF documentation v8 says:
+ # The total size of the section when loaded into memory.
+ # If this value is greater than SizeOfRawData, the section is zero-padded.
+ # This field is valid only for executable images and should be set to zero
+ # for object files.
+
+ if len(self.data) < self.SizeOfRawData:
+ size = self.Misc_VirtualSize
+ else:
+ size = max(self.SizeOfRawData, self.Misc_VirtualSize)
+
+ return self.VirtualAddress <= rva < self.VirtualAddress + size
+
+ def contains(self, rva):
+ #print "DEPRECATION WARNING: you should use contains_rva() instead of contains()"
+ return self.contains_rva(rva)
+
+
+ def set_data(self, data):
+ """Set the data belonging to the section."""
+
+ self.data = data
+
+
+ def get_entropy(self):
+ """Calculate and return the entropy for the section."""
+
+ return self.entropy_H( self.data )
+
+
+ def get_hash_sha1(self):
+ """Get the SHA-1 hex-digest of the section's data."""
+
+ if sha1 is not None:
+ return sha1( self.data ).hexdigest()
+
+
+ def get_hash_sha256(self):
+ """Get the SHA-256 hex-digest of the section's data."""
+
+ if sha256 is not None:
+ return sha256( self.data ).hexdigest()
+
+
+ def get_hash_sha512(self):
+ """Get the SHA-512 hex-digest of the section's data."""
+
+ if sha512 is not None:
+ return sha512( self.data ).hexdigest()
+
+
+ def get_hash_md5(self):
+ """Get the MD5 hex-digest of the section's data."""
+
+ if md5 is not None:
+ return md5( self.data ).hexdigest()
+
+
+ def entropy_H(self, data):
+ """Calculate the entropy of a chunk of data."""
+
+ if len(data) == 0:
+ return 0.0
+
+ occurences = array.array('L', [0]*256)
+
+ for x in data:
+ occurences[ord(x)] += 1
+
+ entropy = 0
+ for x in occurences:
+ if x:
+ p_x = float(x) / len(data)
+ entropy -= p_x*math.log(p_x, 2)
+
+ return entropy
+
+
+
+class DataContainer:
+ """Generic data container."""
+
+ def __init__(self, **args):
+ for key, value in args.items():
+ setattr(self, key, value)
+
+
+
+class ImportDescData(DataContainer):
+ """Holds import descriptor information.
+
+ dll: name of the imported DLL
+ imports: list of imported symbols (ImportData instances)
+ struct: IMAGE_IMPORT_DESCRIPTOR sctruture
+ """
+
+class ImportData(DataContainer):
+ """Holds imported symbol's information.
+
+ ordinal: Ordinal of the symbol
+ name: Name of the symbol
+ bound: If the symbol is bound, this contains
+ the address.
+ """
+
+class ExportDirData(DataContainer):
+ """Holds export directory information.
+
+ struct: IMAGE_EXPORT_DIRECTORY structure
+ symbols: list of exported symbols (ExportData instances)
+"""
+
+class ExportData(DataContainer):
+ """Holds exported symbols' information.
+
+ ordinal: ordinal of the symbol
+ address: address of the symbol
+ name: name of the symbol (None if the symbol is
+ exported by ordinal only)
+ forwarder: if the symbol is forwarded it will
+ contain the name of the target symbol,
+ None otherwise.
+ """
+
+
+class ResourceDirData(DataContainer):
+ """Holds resource directory information.
+
+ struct: IMAGE_RESOURCE_DIRECTORY structure
+ entries: list of entries (ResourceDirEntryData instances)
+ """
+
+class ResourceDirEntryData(DataContainer):
+ """Holds resource directory entry data.
+
+ struct: IMAGE_RESOURCE_DIRECTORY_ENTRY structure
+ name: If the resource is identified by name this
+ attribute will contain the name string. None
+ otherwise. If identified by id, the id is
+ availabe at 'struct.Id'
+ id: the id, also in struct.Id
+ directory: If this entry has a lower level directory
+ this attribute will point to the
+ ResourceDirData instance representing it.
+ data: If this entry has no futher lower directories
+ and points to the actual resource data, this
+ attribute will reference the corresponding
+ ResourceDataEntryData instance.
+ (Either of the 'directory' or 'data' attribute will exist,
+ but not both.)
+ """
+
+class ResourceDataEntryData(DataContainer):
+ """Holds resource data entry information.
+
+ struct: IMAGE_RESOURCE_DATA_ENTRY structure
+ lang: Primary language ID
+ sublang: Sublanguage ID
+ """
+
+class DebugData(DataContainer):
+ """Holds debug information.
+
+ struct: IMAGE_DEBUG_DIRECTORY structure
+ """
+
+class BaseRelocationData(DataContainer):
+ """Holds base relocation information.
+
+ struct: IMAGE_BASE_RELOCATION structure
+ entries: list of relocation data (RelocationData instances)
+ """
+
+class RelocationData(DataContainer):
+ """Holds relocation information.
+
+ type: Type of relocation
+ The type string is can be obtained by
+ RELOCATION_TYPE[type]
+ rva: RVA of the relocation
+ """
+
+class TlsData(DataContainer):
+ """Holds TLS information.
+
+ struct: IMAGE_TLS_DIRECTORY structure
+ """
+
+class BoundImportDescData(DataContainer):
+ """Holds bound import descriptor data.
+
+ This directory entry will provide with information on the
+ DLLs this PE files has been bound to (if bound at all).
+ The structure will contain the name and timestamp of the
+ DLL at the time of binding so that the loader can know
+ whether it differs from the one currently present in the
+ system and must, therefore, re-bind the PE's imports.
+
+ struct: IMAGE_BOUND_IMPORT_DESCRIPTOR structure
+ name: DLL name
+ entries: list of entries (BoundImportRefData instances)
+ the entries will exist if this DLL has forwarded
+ symbols. If so, the destination DLL will have an
+ entry in this list.
+ """
+
+class BoundImportRefData(DataContainer):
+ """Holds bound import forwader reference data.
+
+ Contains the same information as the bound descriptor but
+ for forwarded DLLs, if any.
+
+ struct: IMAGE_BOUND_FORWARDER_REF structure
+ name: dll name
+ """
+
+
+class PE:
+ """A Portable Executable representation.
+
+ This class provides access to most of the information in a PE file.
+
+ It expects to be supplied the name of the file to load or PE data
+ to process and an optional argument 'fast_load' (False by default)
+ which controls whether to load all the directories information,
+ which can be quite time consuming.
+
+ pe = pefile.PE('module.dll')
+ pe = pefile.PE(name='module.dll')
+
+ would load 'module.dll' and process it. If the data would be already
+ available in a buffer the same could be achieved with:
+
+ pe = pefile.PE(data=module_dll_data)
+
+ The "fast_load" can be set to a default by setting its value in the
+ module itself by means,for instance, of a "pefile.fast_load = True".
+ That will make all the subsequent instances not to load the
+ whole PE structure. The "full_load" method can be used to parse
+ the missing data at a later stage.
+
+ Basic headers information will be available in the attributes:
+
+ DOS_HEADER
+ NT_HEADERS
+ FILE_HEADER
+ OPTIONAL_HEADER
+
+ All of them will contain among their attrbitues the members of the
+ corresponding structures as defined in WINNT.H
+
+ The raw data corresponding to the header (from the beginning of the
+ file up to the start of the first section) will be avaiable in the
+ instance's attribute 'header' as a string.
+
+ The sections will be available as a list in the 'sections' attribute.
+ Each entry will contain as attributes all the structure's members.
+
+ Directory entries will be available as attributes (if they exist):
+ (no other entries are processed at this point)
+
+ DIRECTORY_ENTRY_IMPORT (list of ImportDescData instances)
+ DIRECTORY_ENTRY_EXPORT (ExportDirData instance)
+ DIRECTORY_ENTRY_RESOURCE (ResourceDirData instance)
+ DIRECTORY_ENTRY_DEBUG (list of DebugData instances)
+ DIRECTORY_ENTRY_BASERELOC (list of BaseRelocationData instances)
+ DIRECTORY_ENTRY_TLS
+ DIRECTORY_ENTRY_BOUND_IMPORT (list of BoundImportData instances)
+
+ The following dictionary attributes provide ways of mapping different
+ constants. They will accept the numeric value and return the string
+ representation and the opposite, feed in the string and get the
+ numeric constant:
+
+ DIRECTORY_ENTRY
+ IMAGE_CHARACTERISTICS
+ SECTION_CHARACTERISTICS
+ DEBUG_TYPE
+ SUBSYSTEM_TYPE
+ MACHINE_TYPE
+ RELOCATION_TYPE
+ RESOURCE_TYPE
+ LANG
+ SUBLANG
+ """
+
+ #
+ # Format specifications for PE structures.
+ #
+
+ __IMAGE_DOS_HEADER_format__ = ('IMAGE_DOS_HEADER',
+ ('H,e_magic', 'H,e_cblp', 'H,e_cp',
+ 'H,e_crlc', 'H,e_cparhdr', 'H,e_minalloc',
+ 'H,e_maxalloc', 'H,e_ss', 'H,e_sp', 'H,e_csum',
+ 'H,e_ip', 'H,e_cs', 'H,e_lfarlc', 'H,e_ovno', '8s,e_res',
+ 'H,e_oemid', 'H,e_oeminfo', '20s,e_res2',
+ 'L,e_lfanew'))
+
+ __IMAGE_FILE_HEADER_format__ = ('IMAGE_FILE_HEADER',
+ ('H,Machine', 'H,NumberOfSections',
+ 'L,TimeDateStamp', 'L,PointerToSymbolTable',
+ 'L,NumberOfSymbols', 'H,SizeOfOptionalHeader',
+ 'H,Characteristics'))
+
+ __IMAGE_DATA_DIRECTORY_format__ = ('IMAGE_DATA_DIRECTORY',
+ ('L,VirtualAddress', 'L,Size'))
+
+
+ __IMAGE_OPTIONAL_HEADER_format__ = ('IMAGE_OPTIONAL_HEADER',
+ ('H,Magic', 'B,MajorLinkerVersion',
+ 'B,MinorLinkerVersion', 'L,SizeOfCode',
+ 'L,SizeOfInitializedData', 'L,SizeOfUninitializedData',
+ 'L,AddressOfEntryPoint', 'L,BaseOfCode', 'L,BaseOfData',
+ 'L,ImageBase', 'L,SectionAlignment', 'L,FileAlignment',
+ 'H,MajorOperatingSystemVersion', 'H,MinorOperatingSystemVersion',
+ 'H,MajorImageVersion', 'H,MinorImageVersion',
+ 'H,MajorSubsystemVersion', 'H,MinorSubsystemVersion',
+ 'L,Reserved1', 'L,SizeOfImage', 'L,SizeOfHeaders',
+ 'L,CheckSum', 'H,Subsystem', 'H,DllCharacteristics',
+ 'L,SizeOfStackReserve', 'L,SizeOfStackCommit',
+ 'L,SizeOfHeapReserve', 'L,SizeOfHeapCommit',
+ 'L,LoaderFlags', 'L,NumberOfRvaAndSizes' ))
+
+
+ __IMAGE_OPTIONAL_HEADER64_format__ = ('IMAGE_OPTIONAL_HEADER64',
+ ('H,Magic', 'B,MajorLinkerVersion',
+ 'B,MinorLinkerVersion', 'L,SizeOfCode',
+ 'L,SizeOfInitializedData', 'L,SizeOfUninitializedData',
+ 'L,AddressOfEntryPoint', 'L,BaseOfCode',
+ 'Q,ImageBase', 'L,SectionAlignment', 'L,FileAlignment',
+ 'H,MajorOperatingSystemVersion', 'H,MinorOperatingSystemVersion',
+ 'H,MajorImageVersion', 'H,MinorImageVersion',
+ 'H,MajorSubsystemVersion', 'H,MinorSubsystemVersion',
+ 'L,Reserved1', 'L,SizeOfImage', 'L,SizeOfHeaders',
+ 'L,CheckSum', 'H,Subsystem', 'H,DllCharacteristics',
+ 'Q,SizeOfStackReserve', 'Q,SizeOfStackCommit',
+ 'Q,SizeOfHeapReserve', 'Q,SizeOfHeapCommit',
+ 'L,LoaderFlags', 'L,NumberOfRvaAndSizes' ))
+
+
+ __IMAGE_NT_HEADERS_format__ = ('IMAGE_NT_HEADERS', ('L,Signature',))
+
+ __IMAGE_SECTION_HEADER_format__ = ('IMAGE_SECTION_HEADER',
+ ('8s,Name', 'L,Misc,Misc_PhysicalAddress,Misc_VirtualSize',
+ 'L,VirtualAddress', 'L,SizeOfRawData', 'L,PointerToRawData',
+ 'L,PointerToRelocations', 'L,PointerToLinenumbers',
+ 'H,NumberOfRelocations', 'H,NumberOfLinenumbers',
+ 'L,Characteristics'))
+
+ __IMAGE_DELAY_IMPORT_DESCRIPTOR_format__ = ('IMAGE_DELAY_IMPORT_DESCRIPTOR',
+ ('L,grAttrs', 'L,szName', 'L,phmod', 'L,pIAT', 'L,pINT',
+ 'L,pBoundIAT', 'L,pUnloadIAT', 'L,dwTimeStamp'))
+
+ __IMAGE_IMPORT_DESCRIPTOR_format__ = ('IMAGE_IMPORT_DESCRIPTOR',
+ ('L,OriginalFirstThunk,Characteristics',
+ 'L,TimeDateStamp', 'L,ForwarderChain', 'L,Name', 'L,FirstThunk'))
+
+ __IMAGE_EXPORT_DIRECTORY_format__ = ('IMAGE_EXPORT_DIRECTORY',
+ ('L,Characteristics',
+ 'L,TimeDateStamp', 'H,MajorVersion', 'H,MinorVersion', 'L,Name',
+ 'L,Base', 'L,NumberOfFunctions', 'L,NumberOfNames',
+ 'L,AddressOfFunctions', 'L,AddressOfNames', 'L,AddressOfNameOrdinals'))
+
+ __IMAGE_RESOURCE_DIRECTORY_format__ = ('IMAGE_RESOURCE_DIRECTORY',
+ ('L,Characteristics',
+ 'L,TimeDateStamp', 'H,MajorVersion', 'H,MinorVersion',
+ 'H,NumberOfNamedEntries', 'H,NumberOfIdEntries'))
+
+ __IMAGE_RESOURCE_DIRECTORY_ENTRY_format__ = ('IMAGE_RESOURCE_DIRECTORY_ENTRY',
+ ('L,Name',
+ 'L,OffsetToData'))
+
+ __IMAGE_RESOURCE_DATA_ENTRY_format__ = ('IMAGE_RESOURCE_DATA_ENTRY',
+ ('L,OffsetToData', 'L,Size', 'L,CodePage', 'L,Reserved'))
+
+ __VS_VERSIONINFO_format__ = ( 'VS_VERSIONINFO',
+ ('H,Length', 'H,ValueLength', 'H,Type' ))
+
+ __VS_FIXEDFILEINFO_format__ = ( 'VS_FIXEDFILEINFO',
+ ('L,Signature', 'L,StrucVersion', 'L,FileVersionMS', 'L,FileVersionLS',
+ 'L,ProductVersionMS', 'L,ProductVersionLS', 'L,FileFlagsMask', 'L,FileFlags',
+ 'L,FileOS', 'L,FileType', 'L,FileSubtype', 'L,FileDateMS', 'L,FileDateLS'))
+
+ __StringFileInfo_format__ = ( 'StringFileInfo',
+ ('H,Length', 'H,ValueLength', 'H,Type' ))
+
+ __StringTable_format__ = ( 'StringTable',
+ ('H,Length', 'H,ValueLength', 'H,Type' ))
+
+ __String_format__ = ( 'String',
+ ('H,Length', 'H,ValueLength', 'H,Type' ))
+
+ __Var_format__ = ( 'Var', ('H,Length', 'H,ValueLength', 'H,Type' ))
+
+ __IMAGE_THUNK_DATA_format__ = ('IMAGE_THUNK_DATA',
+ ('L,ForwarderString,Function,Ordinal,AddressOfData',))
+
+ __IMAGE_THUNK_DATA64_format__ = ('IMAGE_THUNK_DATA',
+ ('Q,ForwarderString,Function,Ordinal,AddressOfData',))
+
+ __IMAGE_DEBUG_DIRECTORY_format__ = ('IMAGE_DEBUG_DIRECTORY',
+ ('L,Characteristics', 'L,TimeDateStamp', 'H,MajorVersion',
+ 'H,MinorVersion', 'L,Type', 'L,SizeOfData', 'L,AddressOfRawData',
+ 'L,PointerToRawData'))
+
+ __IMAGE_BASE_RELOCATION_format__ = ('IMAGE_BASE_RELOCATION',
+ ('L,VirtualAddress', 'L,SizeOfBlock') )
+
+ __IMAGE_TLS_DIRECTORY_format__ = ('IMAGE_TLS_DIRECTORY',
+ ('L,StartAddressOfRawData', 'L,EndAddressOfRawData',
+ 'L,AddressOfIndex', 'L,AddressOfCallBacks',
+ 'L,SizeOfZeroFill', 'L,Characteristics' ) )
+
+ __IMAGE_TLS_DIRECTORY64_format__ = ('IMAGE_TLS_DIRECTORY',
+ ('Q,StartAddressOfRawData', 'Q,EndAddressOfRawData',
+ 'Q,AddressOfIndex', 'Q,AddressOfCallBacks',
+ 'L,SizeOfZeroFill', 'L,Characteristics' ) )
+
+ __IMAGE_BOUND_IMPORT_DESCRIPTOR_format__ = ('IMAGE_BOUND_IMPORT_DESCRIPTOR',
+ ('L,TimeDateStamp', 'H,OffsetModuleName', 'H,NumberOfModuleForwarderRefs'))
+
+ __IMAGE_BOUND_FORWARDER_REF_format__ = ('IMAGE_BOUND_FORWARDER_REF',
+ ('L,TimeDateStamp', 'H,OffsetModuleName', 'H,Reserved') )
+
+
+ def __init__(self, name=None, data=None, fast_load=None):
+
+ self.sections = []
+
+ self.__warnings = []
+
+ self.PE_TYPE = None
+
+ if not name and not data:
+ return
+
+ # This list will keep track of all the structures created.
+ # That will allow for an easy iteration through the list
+ # in order to save the modifications made
+ self.__structures__ = []
+
+ if not fast_load:
+ fast_load = globals()['fast_load']
+ self.__parse__(name, data, fast_load)
+
+
+
+ def __unpack_data__(self, format, data, file_offset):
+ """Apply structure format to raw data.
+
+ Returns and unpacked structure object if successful, None otherwise.
+ """
+
+ structure = Structure(format, file_offset=file_offset)
+ #if len(data) < structure.sizeof():
+ # return None
+
+ try:
+ structure.__unpack__(data)
+ except PEFormatError, err:
+ self.__warnings.append(
+ 'Corrupt header "%s" at file offset %d. Exception: %s' % (
+ format[0], file_offset, str(err)) )
+ return None
+
+ self.__structures__.append(structure)
+
+ return structure
+
+
+
+ def __parse__(self, fname, data, fast_load):
+ """Parse a Portable Executable file.
+
+ Loads a PE file, parsing all its structures and making them available
+ through the instance's attributes.
+ """
+
+ if fname:
+ fd = file(fname, 'rb')
+ self.__data__ = fd.read()
+ fd.close()
+ elif data:
+ self.__data__ = data
+
+
+ self.DOS_HEADER = self.__unpack_data__(
+ self.__IMAGE_DOS_HEADER_format__,
+ self.__data__, file_offset=0)
+
+ if not self.DOS_HEADER or self.DOS_HEADER.e_magic != IMAGE_DOS_SIGNATURE:
+ raise PEFormatError('DOS Header magic not found.')
+
+ # OC Patch:
+ # Check for sane value in e_lfanew
+ #
+ if self.DOS_HEADER.e_lfanew > len(self.__data__):
+ raise PEFormatError('Invalid e_lfanew value, probably not a PE file')
+
+ nt_headers_offset = self.DOS_HEADER.e_lfanew
+
+ self.NT_HEADERS = self.__unpack_data__(
+ self.__IMAGE_NT_HEADERS_format__,
+ self.__data__[nt_headers_offset:],
+ file_offset = nt_headers_offset)
+
+ # We better check the signature right here, before the file screws
+ # around with sections:
+ # OC Patch:
+ # Some malware will cause the Signature value to not exist at all
+ if not self.NT_HEADERS or not self.NT_HEADERS.Signature:
+ raise PEFormatError('NT Headers not found.')
+
+ if self.NT_HEADERS.Signature != IMAGE_NT_SIGNATURE:
+ raise PEFormatError('Invalid NT Headers signature.')
+
+ self.FILE_HEADER = self.__unpack_data__(
+ self.__IMAGE_FILE_HEADER_format__,
+ self.__data__[nt_headers_offset+4:],
+ file_offset = nt_headers_offset+4)
+ image_flags = self.retrieve_flags(IMAGE_CHARACTERISTICS, 'IMAGE_FILE_')
+
+ if not self.FILE_HEADER:
+ raise PEFormatError('File Header missing')
+
+ # Set the image's flags according the the Characteristics member
+ self.set_flags(self.FILE_HEADER, self.FILE_HEADER.Characteristics, image_flags)
+
+ optional_header_offset = \
+ nt_headers_offset+4+self.FILE_HEADER.sizeof()
+
+ # Note: location of sections can be controlled from PE header:
+ sections_offset = optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader
+
+ self.OPTIONAL_HEADER = self.__unpack_data__(
+ self.__IMAGE_OPTIONAL_HEADER_format__,
+ self.__data__[optional_header_offset:],
+ file_offset = optional_header_offset)
+
+ # According to solardesigner's findings for his
+ # Tiny PE project, the optional header does not
+ # need fields beyond "Subsystem" in order to be
+ # loadable by the Windows loader (given that zeroes
+ # are acceptable values and the header is loaded
+ # in a zeroed memory page)
+ # If trying to parse a full Optional Header fails
+ # we try to parse it again with some 0 padding
+ #
+ MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69
+
+ if ( self.OPTIONAL_HEADER is None and
+ len(self.__data__[optional_header_offset:])
+ >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE ):
+
+ # Add enough zeroes to make up for the unused fields
+ #
+ padding_length = 128
+
+ # Create padding
+ #
+ padded_data = self.__data__[optional_header_offset:] + (
+ '\0' * padding_length)
+
+ self.OPTIONAL_HEADER = self.__unpack_data__(
+ self.__IMAGE_OPTIONAL_HEADER_format__,
+ padded_data,
+ file_offset = optional_header_offset)
+
+
+ # Check the Magic in the OPTIONAL_HEADER and set the PE file
+ # type accordingly
+ #
+ if self.OPTIONAL_HEADER is not None:
+
+ if self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE:
+
+ self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE
+
+ elif self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+
+ self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE_PLUS
+
+ self.OPTIONAL_HEADER = self.__unpack_data__(
+ self.__IMAGE_OPTIONAL_HEADER64_format__,
+ self.__data__[optional_header_offset:],
+ file_offset = optional_header_offset)
+
+ # Again, as explained above, we try to parse
+ # a reduced form of the Optional Header which
+ # is still valid despite not including all
+ # structure members
+ #
+ MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69+4
+
+ if ( self.OPTIONAL_HEADER is None and
+ len(self.__data__[optional_header_offset:])
+ >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE ):
+
+ padding_length = 128
+ padded_data = self.__data__[optional_header_offset:] + (
+ '\0' * padding_length)
+ self.OPTIONAL_HEADER = self.__unpack_data__(
+ self.__IMAGE_OPTIONAL_HEADER64_format__,
+ padded_data,
+ file_offset = optional_header_offset)
+
+
+ if not self.FILE_HEADER:
+ raise PEFormatError('File Header missing')
+
+
+ # OC Patch:
+ # Die gracefully if there is no OPTIONAL_HEADER field
+ # 975440f5ad5e2e4a92c4d9a5f22f75c1
+ if self.PE_TYPE is None or self.OPTIONAL_HEADER is None:
+ raise PEFormatError("No Optional Header found, invalid PE32 or PE32+ file")
+
+ dll_characteristics_flags = self.retrieve_flags(DLL_CHARACTERISTICS, 'IMAGE_DLL_CHARACTERISTICS_')
+
+ # Set the Dll Characteristics flags according the the DllCharacteristics member
+ self.set_flags(
+ self.OPTIONAL_HEADER,
+ self.OPTIONAL_HEADER.DllCharacteristics,
+ dll_characteristics_flags)
+
+
+ self.OPTIONAL_HEADER.DATA_DIRECTORY = []
+ #offset = (optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader)
+ offset = (optional_header_offset + self.OPTIONAL_HEADER.sizeof())
+
+
+ self.NT_HEADERS.FILE_HEADER = self.FILE_HEADER
+ self.NT_HEADERS.OPTIONAL_HEADER = self.OPTIONAL_HEADER
+
+
+ # The NumberOfRvaAndSizes is sanitized to stay within
+ # reasonable limits so can be casted to an int
+ #
+ if self.OPTIONAL_HEADER.NumberOfRvaAndSizes > 0x10:
+ self.__warnings.append(
+ 'Suspicious NumberOfRvaAndSizes in the Optional Header. ' +
+ 'Normal values are never larger than 0x10, the value is: 0x%x' %
+ self.OPTIONAL_HEADER.NumberOfRvaAndSizes )
+
+ for i in xrange(int(0x7fffffffL & self.OPTIONAL_HEADER.NumberOfRvaAndSizes)):
+
+ if len(self.__data__[offset:]) == 0:
+ break
+
+ if len(self.__data__[offset:]) < 8:
+ data = self.__data__[offset:]+'\0'*8
+ else:
+ data = self.__data__[offset:]
+
+ dir_entry = self.__unpack_data__(
+ self.__IMAGE_DATA_DIRECTORY_format__,
+ data,
+ file_offset = offset)
+
+ if dir_entry is None:
+ break
+
+ # Would fail if missing an entry
+ # 1d4937b2fa4d84ad1bce0309857e70ca offending sample
+ try:
+ dir_entry.name = DIRECTORY_ENTRY[i]
+ except (KeyError, AttributeError):
+ break
+
+ offset += dir_entry.sizeof()
+
+ self.OPTIONAL_HEADER.DATA_DIRECTORY.append(dir_entry)
+
+ # If the offset goes outside the optional header,
+ # the loop is broken, regardless of how many directories
+ # NumberOfRvaAndSizes says there are
+ #
+ # We assume a normally sized optional header, hence that we do
+ # a sizeof() instead of reading SizeOfOptionalHeader.
+ # Then we add a default number of drectories times their size,
+ # if we go beyond that, we assume the number of directories
+ # is wrong and stop processing
+ if offset >= (optional_header_offset +
+ self.OPTIONAL_HEADER.sizeof() + 8*16) :
+
+ break
+
+
+ offset = self.parse_sections(sections_offset)
+
+ # OC Patch:
+ # There could be a problem if there are no raw data sections
+ # greater than 0
+ # fc91013eb72529da005110a3403541b6 example
+ # Should this throw an exception in the minimum header offset
+ # can't be found?
+ #
+ rawDataPointers = [
+ s.PointerToRawData for s in self.sections if s.PointerToRawData>0]
+
+ if len(rawDataPointers) > 0:
+ lowest_section_offset = min(rawDataPointers)
+ else:
+ lowest_section_offset = None
+
+ if not lowest_section_offset or lowest_section_offset<offset:
+ self.header = self.__data__[:offset]
+ else:
+ self.header = self.__data__[:lowest_section_offset]
+
+
+ # Check whether the entry point lies within a section
+ #
+ if self.get_section_by_rva(self.OPTIONAL_HEADER.AddressOfEntryPoint) is not None:
+
+ # Check whether the entry point lies within the file
+ #
+ ep_offset = self.get_offset_from_rva(self.OPTIONAL_HEADER.AddressOfEntryPoint)
+ if ep_offset > len(self.__data__):
+
+ self.__warnings.append(
+ 'Possibly corrupt file. AddressOfEntryPoint lies outside the file. ' +
+ 'AddressOfEntryPoint: 0x%x' %
+ self.OPTIONAL_HEADER.AddressOfEntryPoint )
+
+ else:
+
+ self.__warnings.append(
+ 'AddressOfEntryPoint lies outside the sections\' boundaries. ' +
+ 'AddressOfEntryPoint: 0x%x' %
+ self.OPTIONAL_HEADER.AddressOfEntryPoint )
+
+
+ if not fast_load:
+ self.parse_data_directories()
+
+
+ def get_warnings(self):
+ """Return the list of warnings.
+
+ Non-critical problems found when parsing the PE file are
+ appended to a list of warnings. This method returns the
+ full list.
+ """
+
+ return self.__warnings
+
+
+ def show_warnings(self):
+ """Print the list of warnings.
+
+ Non-critical problems found when parsing the PE file are
+ appended to a list of warnings. This method prints the
+ full list to standard output.
+ """
+
+ for warning in self.__warnings:
+ print '>', warning
+
+
+ def full_load(self):
+ """Process the data directories.
+
+ This mathod will load the data directories which might not have
+ been loaded if the "fast_load" option was used.
+ """
+
+ self.parse_data_directories()
+
+
+ def write(self, filename=None):
+ """Write the PE file.
+
+ This function will process all headers and components
+ of the PE file and include all changes made (by just
+ assigning to attributes in the PE objects) and write
+ the changes back to a file whose name is provided as
+ an argument. The filename is optional.
+ The data to be written to the file will be returned
+ as a 'str' object.
+ """
+
+ file_data = list(self.__data__)
+ for struct in self.__structures__:
+
+ struct_data = list(struct.__pack__())
+ offset = struct.get_file_offset()
+
+ file_data[offset:offset+len(struct_data)] = struct_data
+
+ if hasattr(self, 'VS_VERSIONINFO'):
+ if hasattr(self, 'FileInfo'):
+ for entry in self.FileInfo:
+ if hasattr(entry, 'StringTable'):
+ for st_entry in entry.StringTable:
+ for key, entry in st_entry.entries.items():
+
+ offsets = st_entry.entries_offsets[key]
+ lengths = st_entry.entries_lengths[key]
+
+ if len( entry ) > lengths[1]:
+
+ uc = zip(
+ list(entry[:lengths[1]]), ['\0'] * lengths[1] )
+ l = list()
+ map(l.extend, uc)
+
+ file_data[
+ offsets[1] : offsets[1] + lengths[1]*2 ] = l
+
+ else:
+
+ uc = zip(
+ list(entry), ['\0'] * len(entry) )
+ l = list()
+ map(l.extend, uc)
+
+ file_data[
+ offsets[1] : offsets[1] + len(entry)*2 ] = l
+
+ remainder = lengths[1] - len(entry)
+ file_data[
+ offsets[1] + len(entry)*2 :
+ offsets[1] + lengths[1]*2 ] = [
+ u'\0' ] * remainder*2
+
+ new_file_data = ''.join( [ chr(ord(c)) for c in file_data ] )
+
+ if filename:
+ f = file(filename, 'wb+')
+ f.write(new_file_data)
+ f.close()
+
+ return new_file_data
+
+
+
+ def parse_sections(self, offset):
+ """Fetch the PE file sections.
+
+ The sections will be readily available in the "sections" attribute.
+ Its attributes will contain all the section information plus "data"
+ a buffer containing the section's data.
+
+ The "Characteristics" member will be processed and attributes
+ representing the section characteristics (with the 'IMAGE_SCN_'
+ string trimmed from the constant's names) will be added to the
+ section instance.
+
+ Refer to the SectionStructure class for additional info.
+ """
+
+ self.sections = []
+
+ for i in xrange(self.FILE_HEADER.NumberOfSections):
+ section = SectionStructure(self.__IMAGE_SECTION_HEADER_format__)
+ if not section:
+ break
+ section_offset = offset + section.sizeof() * i
+ section.set_file_offset(section_offset)
+ section.__unpack__(self.__data__[section_offset:])
+ self.__structures__.append(section)
+
+ if section.SizeOfRawData > len(self.__data__):
+ self.__warnings.append(
+ ('Error parsing section %d. ' % i) +
+ 'SizeOfRawData is larger than file.')
+
+ if section.PointerToRawData > len(self.__data__):
+ self.__warnings.append(
+ ('Error parsing section %d. ' % i) +
+ 'PointerToRawData points beyond the end of the file.')
+
+ if section.Misc_VirtualSize > 0x10000000:
+ self.__warnings.append(
+ ('Suspicious value found parsing section %d. ' % i) +
+ 'VirtualSize is extremely large > 256MiB.')
+
+ if section.VirtualAddress > 0x10000000:
+ self.__warnings.append(
+ ('Suspicious value found parsing section %d. ' % i) +
+ 'VirtualAddress is beyond 0x10000000.')
+
+ #
+ # Some packer used a non-aligned PointerToRawData in the sections,
+ # which causes several common tools not to load the section data
+ # properly as they blindly read from the indicated offset.
+ # It seems that Windows will round the offset down to the largest
+ # offset multiple of FileAlignment which is smaller than
+ # PointerToRawData. The following code will do the same.
+ #
+
+ #alignment = self.OPTIONAL_HEADER.FileAlignment
+ section_data_start = section.PointerToRawData
+
+ if ( self.OPTIONAL_HEADER.FileAlignment != 0 and
+ (section.PointerToRawData % self.OPTIONAL_HEADER.FileAlignment) != 0):
+ self.__warnings.append(
+ ('Error parsing section %d. ' % i) +
+ 'Suspicious value for FileAlignment in the Optional Header. ' +
+ 'Normally the PointerToRawData entry of the sections\' structures ' +
+ 'is a multiple of FileAlignment, this might imply the file ' +
+ 'is trying to confuse tools which parse this incorrectly')
+
+ section_data_end = section_data_start+section.SizeOfRawData
+ section.set_data(self.__data__[section_data_start:section_data_end])
+
+ section_flags = self.retrieve_flags(SECTION_CHARACTERISTICS, 'IMAGE_SCN_')
+
+ # Set the section's flags according the the Characteristics member
+ self.set_flags(section, section.Characteristics, section_flags)
+
+ if ( section.__dict__.get('IMAGE_SCN_MEM_WRITE', False) and
+ section.__dict__.get('IMAGE_SCN_MEM_EXECUTE', False) ):
+
+ self.__warnings.append(
+ ('Suspicious flags set for section %d. ' % i) +
+ 'Both IMAGE_SCN_MEM_WRITE and IMAGE_SCN_MEM_EXECUTE are set.' +
+ 'This might indicate a packed executable.')
+
+ self.sections.append(section)
+
+ if self.FILE_HEADER.NumberOfSections > 0 and self.sections:
+ return offset + self.sections[0].sizeof()*self.FILE_HEADER.NumberOfSections
+ else:
+ return offset
+
+
+ def retrieve_flags(self, flag_dict, flag_filter):
+ """Read the flags from a dictionary and return them in a usable form.
+
+ Will return a list of (flag, value) for all flags in "flag_dict"
+ matching the filter "flag_filter".
+ """
+
+ return [(f[0], f[1]) for f in flag_dict.items() if
+ isinstance(f[0], str) and f[0].startswith(flag_filter)]
+
+
+ def set_flags(self, obj, flag_field, flags):
+ """Will process the flags and set attributes in the object accordingly.
+
+ The object "obj" will gain attritutes named after the flags provided in
+ "flags" and valued True/False, matching the results of applyin each
+ flag value from "flags" to flag_field.
+ """
+
+ for flag in flags:
+ if flag[1] & flag_field:
+ setattr(obj, flag[0], True)
+ else:
+ setattr(obj, flag[0], False)
+
+
+
+ def parse_data_directories(self):
+ """Parse and process the PE file's data directories."""
+
+ directory_parsing = (
+ ('IMAGE_DIRECTORY_ENTRY_IMPORT', self.parse_import_directory),
+ ('IMAGE_DIRECTORY_ENTRY_EXPORT', self.parse_export_directory),
+ ('IMAGE_DIRECTORY_ENTRY_RESOURCE', self.parse_resources_directory),
+ ('IMAGE_DIRECTORY_ENTRY_DEBUG', self.parse_debug_directory),
+ ('IMAGE_DIRECTORY_ENTRY_BASERELOC', self.parse_relocations_directory),
+ ('IMAGE_DIRECTORY_ENTRY_TLS', self.parse_directory_tls),
+ ('IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT', self.parse_delay_import_directory),
+ ('IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT', self.parse_directory_bound_imports) )
+
+ for entry in directory_parsing:
+ # OC Patch:
+ #
+ try:
+ dir_entry = self.OPTIONAL_HEADER.DATA_DIRECTORY[
+ DIRECTORY_ENTRY[entry[0]]]
+ except IndexError:
+ break
+ if dir_entry.VirtualAddress:
+ value = entry[1](dir_entry.VirtualAddress, dir_entry.Size)
+ if value:
+ setattr(self, entry[0][6:], value)
+
+
+ def parse_directory_bound_imports(self, rva, size):
+ """"""
+
+ bnd_descr = Structure(self.__IMAGE_BOUND_IMPORT_DESCRIPTOR_format__)
+ bnd_descr_size = bnd_descr.sizeof()
+ start = rva
+
+ bound_imports = []
+ while True:
+
+ bnd_descr = self.__unpack_data__(
+ self.__IMAGE_BOUND_IMPORT_DESCRIPTOR_format__,
+ self.__data__[rva:rva+bnd_descr_size],
+ file_offset = rva)
+ if bnd_descr is None:
+ # If can't parse directory then silently return.
+ # This directory does not necesarily have to be valid to
+ # still have a valid PE file
+
+ self.__warnings.append(
+ 'The Bound Imports directory exists but can\'t be parsed.')
+
+ return
+
+ if bnd_descr.all_zeroes():
+ break
+
+ rva += bnd_descr.sizeof()
+
+ forwarder_refs = []
+ for idx in xrange(bnd_descr.NumberOfModuleForwarderRefs):
+ # Both structures IMAGE_BOUND_IMPORT_DESCRIPTOR and
+ # IMAGE_BOUND_FORWARDER_REF have the same size.
+ bnd_frwd_ref = self.__unpack_data__(
+ self.__IMAGE_BOUND_FORWARDER_REF_format__,
+ self.__data__[rva:rva+bnd_descr_size],
+ file_offset = rva)
+ # OC Patch:
+ if not bnd_frwd_ref:
+ raise PEFormatError(
+ "IMAGE_BOUND_FORWARDER_REF cannot be read")
+ rva += bnd_frwd_ref.sizeof()
+
+ name_str = self.get_string_from_data(
+ start+bnd_frwd_ref.OffsetModuleName, self.__data__)
+
+ if not name_str:
+ break
+ forwarder_refs.append(BoundImportRefData(
+ struct = bnd_frwd_ref,
+ name = name_str))
+
+ name_str = self.get_string_from_data(
+ start+bnd_descr.OffsetModuleName, self.__data__)
+
+ if not name_str:
+ break
+ bound_imports.append(
+ BoundImportDescData(
+ struct = bnd_descr,
+ name = name_str,
+ entries = forwarder_refs))
+
+ return bound_imports
+
+
+ def parse_directory_tls(self, rva, size):
+ """"""
+
+ if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
+ format = self.__IMAGE_TLS_DIRECTORY_format__
+
+ elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+ format = self.__IMAGE_TLS_DIRECTORY64_format__
+
+ tls_struct = self.__unpack_data__(
+ format,
+ self.get_data(rva),
+ file_offset = self.get_offset_from_rva(rva))
+
+ if not tls_struct:
+ return None
+
+ return TlsData( struct = tls_struct )
+
+
+ def parse_relocations_directory(self, rva, size):
+ """"""
+
+ rlc = Structure(self.__IMAGE_BASE_RELOCATION_format__)
+ rlc_size = rlc.sizeof()
+ end = rva+size
+
+ relocations = []
+ while rva<end:
+
+ # OC Patch:
+ # Malware that has bad rva entries will cause an error.
+ # Just continue on after an exception
+ #
+ try:
+ rlc = self.__unpack_data__(
+ self.__IMAGE_BASE_RELOCATION_format__,
+ self.get_data(rva, rlc_size),
+ file_offset = self.get_offset_from_rva(rva) )
+ except PEFormatError:
+ self.__warnings.append(
+ 'Invalid relocation information. Can\'t read ' +
+ 'data at RVA: 0x%x' % rva)
+ rlc = None
+
+ if not rlc:
+ break
+
+ reloc_entries = self.parse_relocations(
+ rva+rlc_size, rlc.VirtualAddress, rlc.SizeOfBlock-rlc_size)
+
+ relocations.append(
+ BaseRelocationData(
+ struct = rlc,
+ entries = reloc_entries))
+
+ if not rlc.SizeOfBlock:
+ break
+ rva += rlc.SizeOfBlock
+
+ return relocations
+
+
+ def parse_relocations(self, data_rva, rva, size):
+ """"""
+
+ data = self.get_data(data_rva, size)
+
+ entries = []
+ for idx in xrange(len(data)/2):
+ word = struct.unpack('<H', data[idx*2:(idx+1)*2])[0]
+ reloc_type = (word>>12)
+ reloc_offset = (word&0x0fff)
+ entries.append(
+ RelocationData(
+ type = reloc_type,
+ rva = reloc_offset+rva))
+
+ return entries
+
+
+ def parse_debug_directory(self, rva, size):
+ """"""
+
+ dbg = Structure(self.__IMAGE_DEBUG_DIRECTORY_format__)
+ dbg_size = dbg.sizeof()
+
+ debug = []
+ for idx in xrange(size/dbg_size):
+ try:
+ data = self.get_data(rva+dbg_size*idx, dbg_size)
+ except PEFormatError, e:
+ self.__warnings.append(
+ 'Invalid debug information. Can\'t read ' +
+ 'data at RVA: 0x%x' % rva)
+ return None
+
+ dbg = self.__unpack_data__(
+ self.__IMAGE_DEBUG_DIRECTORY_format__,
+ data, file_offset = self.get_offset_from_rva(rva+dbg_size*idx))
+
+ if not dbg:
+ return None
+
+ debug.append(
+ DebugData(
+ struct = dbg))
+
+ return debug
+
+
+ def parse_resources_directory(self, rva, size=0, base_rva = None, level = 0):
+ """Parse the resources directory.
+
+ Given the rva of the resources directory, it will process all
+ its entries.
+
+ The root will have the corresponding member of its structure,
+ IMAGE_RESOURCE_DIRECTORY plus 'entries', a list of all the
+ entries in the directory.
+
+ Those entries will have, correspondingly, all the structure's
+ members (IMAGE_RESOURCE_DIRECTORY_ENTRY) and an additional one,
+ "directory", pointing to the IMAGE_RESOURCE_DIRECTORY structure
+ representing upper layers of the tree. This one will also have
+ an 'entries' attribute, pointing to the 3rd, and last, level.
+ Another directory with more entries. Those last entries will
+ have a new atribute (both 'leaf' or 'data_entry' can be used to
+ access it). This structure finally points to the resource data.
+ All the members of this structure, IMAGE_RESOURCE_DATA_ENTRY,
+ are available as its attributes.
+ """
+
+ # OC Patch:
+ original_rva = rva
+
+ if base_rva is None:
+ base_rva = rva
+
+ resources_section = self.get_section_by_rva(rva)
+
+ try:
+ # If the RVA is invalid all would blow up. Some EXEs seem to be
+ # specially nasty and have an invalid RVA.
+ data = self.get_data(rva)
+ except PEFormatError, e:
+ self.__warnings.append(
+ 'Invalid resources directory. Can\'t read ' +
+ 'directory data at RVA: 0x%x' % rva)
+ return None
+
+ # Get the resource directory structure, that is, the header
+ # of the table preceding the actual entries
+ #
+ resource_dir = self.__unpack_data__(
+ self.__IMAGE_RESOURCE_DIRECTORY_format__, data,
+ file_offset = self.get_offset_from_rva(rva) )
+ if resource_dir is None:
+ # If can't parse resources directory then silently return.
+ # This directory does not necesarily have to be valid to
+ # still have a valid PE file
+ self.__warnings.append(
+ 'Invalid resources directory. Can\'t parse ' +
+ 'directory data at RVA: 0x%x' % rva)
+ return None
+
+ dir_entries = []
+
+ # Advance the rva to the positon immediately following the directory
+ # table header and pointing to the first entry in the table
+ #
+ rva += resource_dir.sizeof()
+
+ number_of_entries = (
+ resource_dir.NumberOfNamedEntries +
+ resource_dir.NumberOfIdEntries )
+
+ strings_to_postprocess = list()
+
+ for idx in xrange(number_of_entries):
+
+ res = self.parse_resource_entry(rva)
+ if res is None:
+ self.__warnings.append(
+ 'Error parsing the resources directory, ' +
+ 'Entry %d is invalid, RVA = 0x%x. ' %
+ (idx, rva) )
+ break
+
+
+ entry_name = None
+ entry_id = None
+
+ # If all named entries have been processed, only Id ones
+ # remain
+
+ if idx >= resource_dir.NumberOfNamedEntries:
+ entry_id = res.Name
+ else:
+ ustr_offset = base_rva+res.NameOffset
+ try:
+ #entry_name = self.get_string_u_at_rva(ustr_offset, max_length=16)
+ entry_name = UnicodeStringWrapperPostProcessor(self, ustr_offset)
+ strings_to_postprocess.append(entry_name)
+
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing the resources directory, ' +
+ 'attempting to read entry name. ' +
+ 'Can\'t read unicode string at offset 0x%x' %
+ (ustr_offset) )
+
+
+ if res.DataIsDirectory:
+ # OC Patch:
+ #
+ # One trick malware can do is to recursively reference
+ # the next directory. This causes hilarity to ensue when
+ # trying to parse everything correctly.
+ # If the original RVA given to this function is equal to
+ # the next one to parse, we assume that it's a trick.
+ # Instead of raising a PEFormatError this would skip some
+ # reasonable data so we just break.
+ #
+ # 9ee4d0a0caf095314fd7041a3e4404dc is the offending sample
+ if original_rva == (base_rva + res.OffsetToDirectory):
+
+ break
+
+ else:
+ entry_directory = self.parse_resources_directory(
+ base_rva+res.OffsetToDirectory,
+ base_rva=base_rva, level = level+1)
+
+ if not entry_directory:
+ break
+ dir_entries.append(
+ ResourceDirEntryData(
+ struct = res,
+ name = entry_name,
+ id = entry_id,
+ directory = entry_directory))
+
+ else:
+ struct = self.parse_resource_data_entry(
+ base_rva + res.OffsetToDirectory)
+
+ if struct:
+ entry_data = ResourceDataEntryData(
+ struct = struct,
+ lang = res.Name & 0xff,
+ sublang = (res.Name>>8) & 0xff)
+
+ dir_entries.append(
+ ResourceDirEntryData(
+ struct = res,
+ name = entry_name,
+ id = entry_id,
+ data = entry_data))
+
+ else:
+ break
+
+
+
+ # Check if this entry contains version information
+ #
+ if level == 0 and res.Id == RESOURCE_TYPE['RT_VERSION']:
+ if len(dir_entries)>0:
+ last_entry = dir_entries[-1]
+
+ rt_version_struct = None
+ try:
+ rt_version_struct = last_entry.directory.entries[0].directory.entries[0].data.struct
+ except:
+ # Maybe a malformed directory structure...?
+ # Lets ignore it
+ pass
+
+ if rt_version_struct is not None:
+ self.parse_version_information(rt_version_struct)
+
+ rva += res.sizeof()
+
+
+ string_rvas = [s.get_rva() for s in strings_to_postprocess]
+ string_rvas.sort()
+
+ for idx, s in enumerate(strings_to_postprocess):
+ s.render_pascal_16()
+
+
+ resource_directory_data = ResourceDirData(
+ struct = resource_dir,
+ entries = dir_entries)
+
+ return resource_directory_data
+
+
+ def parse_resource_data_entry(self, rva):
+ """Parse a data entry from the resources directory."""
+
+ try:
+ # If the RVA is invalid all would blow up. Some EXEs seem to be
+ # specially nasty and have an invalid RVA.
+ data = self.get_data(rva)
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing a resource directory data entry, ' +
+ 'the RVA is invalid: 0x%x' % ( rva ) )
+ return None
+
+ data_entry = self.__unpack_data__(
+ self.__IMAGE_RESOURCE_DATA_ENTRY_format__, data,
+ file_offset = self.get_offset_from_rva(rva) )
+
+ return data_entry
+
+
+ def parse_resource_entry(self, rva):
+ """Parse a directory entry from the resources directory."""
+
+ resource = self.__unpack_data__(
+ self.__IMAGE_RESOURCE_DIRECTORY_ENTRY_format__, self.get_data(rva),
+ file_offset = self.get_offset_from_rva(rva) )
+
+ if resource is None:
+ return None
+
+ #resource.NameIsString = (resource.Name & 0x80000000L) >> 31
+ resource.NameOffset = resource.Name & 0x7FFFFFFFL
+
+ resource.__pad = resource.Name & 0xFFFF0000L
+ resource.Id = resource.Name & 0x0000FFFFL
+
+ resource.DataIsDirectory = (resource.OffsetToData & 0x80000000L) >> 31
+ resource.OffsetToDirectory = resource.OffsetToData & 0x7FFFFFFFL
+
+ return resource
+
+
+ def parse_version_information(self, version_struct):
+ """Parse version information structure.
+
+ The date will be made available in three attributes of the PE object.
+
+ VS_VERSIONINFO will contain the first three fields of the main structure:
+ 'Length', 'ValueLength', and 'Type'
+
+ VS_FIXEDFILEINFO will hold the rest of the fields, accessible as sub-attributes:
+ 'Signature', 'StrucVersion', 'FileVersionMS', 'FileVersionLS',
+ 'ProductVersionMS', 'ProductVersionLS', 'FileFlagsMask', 'FileFlags',
+ 'FileOS', 'FileType', 'FileSubtype', 'FileDateMS', 'FileDateLS'
+
+ FileInfo is a list of all StringFileInfo and VarFileInfo structures.
+
+ StringFileInfo structures will have a list as an attribute named 'StringTable'
+ containing all the StringTable structures. Each of those structures contains a
+ dictionary 'entries' with all the key/value version information string pairs.
+
+ VarFileInfo structures will have a list as an attribute named 'Var' containing
+ all Var structures. Each Var structure will have a dictionary as an attribute
+ named 'entry' which will contain the name and value of the Var.
+ """
+
+
+ # Retrieve the data for the version info resource
+ #
+ start_offset = self.get_offset_from_rva( version_struct.OffsetToData )
+ raw_data = self.__data__[ start_offset : start_offset+version_struct.Size ]
+
+
+ # Map the main structure and the subsequent string
+ #
+ versioninfo_struct = self.__unpack_data__(
+ self.__VS_VERSIONINFO_format__, raw_data,
+ file_offset = start_offset )
+
+ if versioninfo_struct is None:
+ return
+
+ ustr_offset = version_struct.OffsetToData + versioninfo_struct.sizeof()
+ try:
+ versioninfo_string = self.get_string_u_at_rva( ustr_offset )
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing the version information, ' +
+ 'attempting to read VS_VERSION_INFO string. Can\'t ' +
+ 'read unicode string at offset 0x%x' % (
+ ustr_offset ) )
+
+ versioninfo_string = None
+
+ # If the structure does not contain the expected name, it's assumed to be invalid
+ #
+ if versioninfo_string != u'VS_VERSION_INFO':
+
+ self.__warnings.append('Invalid VS_VERSION_INFO block')
+ return
+
+
+ # Set the PE object's VS_VERSIONINFO to this one
+ #
+ self.VS_VERSIONINFO = versioninfo_struct
+
+ # The the Key attribute to point to the unicode string identifying the structure
+ #
+ self.VS_VERSIONINFO.Key = versioninfo_string
+
+
+ # Process the fixed version information, get the offset and structure
+ #
+ fixedfileinfo_offset = self.dword_align(
+ versioninfo_struct.sizeof() + 2 * (len(versioninfo_string) + 1),
+ version_struct.OffsetToData)
+ fixedfileinfo_struct = self.__unpack_data__(
+ self.__VS_FIXEDFILEINFO_format__,
+ raw_data[fixedfileinfo_offset:],
+ file_offset = start_offset+fixedfileinfo_offset )
+
+ if not fixedfileinfo_struct:
+ return
+
+
+ # Set the PE object's VS_FIXEDFILEINFO to this one
+ #
+ self.VS_FIXEDFILEINFO = fixedfileinfo_struct
+
+
+ # Start parsing all the StringFileInfo and VarFileInfo structures
+ #
+
+ # Get the first one
+ #
+ stringfileinfo_offset = self.dword_align(
+ fixedfileinfo_offset + fixedfileinfo_struct.sizeof(),
+ version_struct.OffsetToData)
+ original_stringfileinfo_offset = stringfileinfo_offset
+
+
+ # Set the PE object's attribute that will contain them all.
+ #
+ self.FileInfo = list()
+
+
+ while True:
+
+ # Process the StringFileInfo/VarFileInfo struct
+ #
+ stringfileinfo_struct = self.__unpack_data__(
+ self.__StringFileInfo_format__,
+ raw_data[stringfileinfo_offset:],
+ file_offset = start_offset+stringfileinfo_offset )
+
+ if stringfileinfo_struct is None:
+ self.__warnings.append(
+ 'Error parsing StringFileInfo/VarFileInfo struct' )
+ return None
+
+ # Get the subsequent string defining the structure.
+ #
+ ustr_offset = ( version_struct.OffsetToData +
+ stringfileinfo_offset + versioninfo_struct.sizeof() )
+ try:
+ stringfileinfo_string = self.get_string_u_at_rva( ustr_offset )
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing the version information, ' +
+ 'attempting to read StringFileInfo string. Can\'t ' +
+ 'read unicode string at offset 0x%x' % ( ustr_offset ) )
+ break
+
+ # Set such string as the Key attribute
+ #
+ stringfileinfo_struct.Key = stringfileinfo_string
+
+
+ # Append the structure to the PE object's list
+ #
+ self.FileInfo.append(stringfileinfo_struct)
+
+
+ # Parse a StringFileInfo entry
+ #
+ if stringfileinfo_string == u'StringFileInfo':
+
+ if stringfileinfo_struct.Type == 1 and stringfileinfo_struct.ValueLength == 0:
+
+ stringtable_offset = self.dword_align(
+ stringfileinfo_offset + stringfileinfo_struct.sizeof() +
+ 2*(len(stringfileinfo_string)+1),
+ version_struct.OffsetToData)
+
+ stringfileinfo_struct.StringTable = list()
+
+ # Process the String Table entries
+ #
+ while True:
+ stringtable_struct = self.__unpack_data__(
+ self.__StringTable_format__,
+ raw_data[stringtable_offset:],
+ file_offset = start_offset+stringtable_offset )
+
+ if not stringtable_struct:
+ break
+
+ ustr_offset = ( version_struct.OffsetToData + stringtable_offset +
+ stringtable_struct.sizeof() )
+ try:
+ stringtable_string = self.get_string_u_at_rva( ustr_offset )
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing the version information, ' +
+ 'attempting to read StringTable string. Can\'t ' +
+ 'read unicode string at offset 0x%x' % ( ustr_offset ) )
+ break
+
+ stringtable_struct.LangID = stringtable_string
+ stringtable_struct.entries = dict()
+ stringtable_struct.entries_offsets = dict()
+ stringtable_struct.entries_lengths = dict()
+ stringfileinfo_struct.StringTable.append(stringtable_struct)
+
+ entry_offset = self.dword_align(
+ stringtable_offset + stringtable_struct.sizeof() +
+ 2*(len(stringtable_string)+1),
+ version_struct.OffsetToData)
+
+ # Process all entries in the string table
+ #
+
+ while entry_offset < stringtable_offset + stringtable_struct.Length:
+
+ string_struct = self.__unpack_data__(
+ self.__String_format__, raw_data[entry_offset:],
+ file_offset = start_offset+entry_offset )
+
+ if not string_struct:
+ break
+
+ ustr_offset = ( version_struct.OffsetToData + entry_offset +
+ string_struct.sizeof() )
+ try:
+ key = self.get_string_u_at_rva( ustr_offset )
+ key_offset = self.get_offset_from_rva( ustr_offset )
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing the version information, ' +
+ 'attempting to read StringTable Key string. Can\'t ' +
+ 'read unicode string at offset 0x%x' % ( ustr_offset ) )
+ break
+
+ value_offset = self.dword_align(
+ 2*(len(key)+1) + entry_offset + string_struct.sizeof(),
+ version_struct.OffsetToData)
+
+ ustr_offset = version_struct.OffsetToData + value_offset
+ try:
+ value = self.get_string_u_at_rva( ustr_offset,
+ max_length = string_struct.ValueLength )
+ value_offset = self.get_offset_from_rva( ustr_offset )
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing the version information, ' +
+ 'attempting to read StringTable Value string. ' +
+ 'Can\'t read unicode string at offset 0x%x' % (
+ ustr_offset ) )
+ break
+
+ if string_struct.Length == 0:
+ entry_offset = stringtable_offset + stringtable_struct.Length
+ else:
+ entry_offset = self.dword_align(
+ string_struct.Length+entry_offset, version_struct.OffsetToData)
+
+ key_as_char = []
+ for c in key:
+ if ord(c)>128:
+ key_as_char.append('\\x%02x' %ord(c))
+ else:
+ key_as_char.append(c)
+
+ key_as_char = ''.join(key_as_char)
+
+ setattr(stringtable_struct, key_as_char, value)
+ stringtable_struct.entries[key] = value
+ stringtable_struct.entries_offsets[key] = (key_offset, value_offset)
+ stringtable_struct.entries_lengths[key] = (len(key), len(value))
+
+
+ stringtable_offset = self.dword_align(
+ stringtable_struct.Length + stringtable_offset,
+ version_struct.OffsetToData)
+ if stringtable_offset >= stringfileinfo_struct.Length:
+ break
+
+ # Parse a VarFileInfo entry
+ #
+ elif stringfileinfo_string == u'VarFileInfo':
+
+ varfileinfo_struct = stringfileinfo_struct
+ varfileinfo_struct.name = 'VarFileInfo'
+
+ if varfileinfo_struct.Type == 1 and varfileinfo_struct.ValueLength == 0:
+
+ var_offset = self.dword_align(
+ stringfileinfo_offset + varfileinfo_struct.sizeof() +
+ 2*(len(stringfileinfo_string)+1),
+ version_struct.OffsetToData)
+
+ varfileinfo_struct.Var = list()
+
+ # Process all entries
+ #
+
+ while True:
+ var_struct = self.__unpack_data__(
+ self.__Var_format__,
+ raw_data[var_offset:],
+ file_offset = start_offset+var_offset )
+
+ if not var_struct:
+ break
+
+ ustr_offset = ( version_struct.OffsetToData + var_offset +
+ var_struct.sizeof() )
+ try:
+ var_string = self.get_string_u_at_rva( ustr_offset )
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing the version information, ' +
+ 'attempting to read VarFileInfo Var string. ' +
+ 'Can\'t read unicode string at offset 0x%x' % (ustr_offset))
+ break
+
+
+ varfileinfo_struct.Var.append(var_struct)
+
+ varword_offset = self.dword_align(
+ 2*(len(var_string)+1) + var_offset + var_struct.sizeof(),
+ version_struct.OffsetToData)
+ orig_varword_offset = varword_offset
+
+ while varword_offset < orig_varword_offset + var_struct.ValueLength:
+ word1 = self.get_word_from_data(
+ raw_data[varword_offset:varword_offset+2], 0)
+ word2 = self.get_word_from_data(
+ raw_data[varword_offset+2:varword_offset+4], 0)
+ varword_offset += 4
+
+ var_struct.entry = {var_string: '0x%04x 0x%04x' % (word1, word2)}
+
+ var_offset = self.dword_align(
+ var_offset+var_struct.Length, version_struct.OffsetToData)
+
+ if var_offset <= var_offset+var_struct.Length:
+ break
+
+
+
+ # Increment and align the offset
+ #
+ stringfileinfo_offset = self.dword_align(
+ stringfileinfo_struct.Length+stringfileinfo_offset,
+ version_struct.OffsetToData)
+
+ # Check if all the StringFileInfo and VarFileInfo items have been processed
+ #
+ if stringfileinfo_struct.Length == 0 or stringfileinfo_offset >= versioninfo_struct.Length:
+ break
+
+
+
+ def parse_export_directory(self, rva, size):
+ """Parse the export directory.
+
+ Given the rva of the export directory, it will process all
+ its entries.
+
+ The exports will be made available through a list "exports"
+ containing a tuple with the following elements:
+
+ (ordinal, symbol_address, symbol_name)
+
+ And also through a dicionary "exports_by_ordinal" whose keys
+ will be the ordinals and the values tuples of the from:
+
+ (symbol_address, symbol_name)
+
+ The symbol addresses are relative, not absolute.
+ """
+
+ try:
+ export_dir = self.__unpack_data__(
+ self.__IMAGE_EXPORT_DIRECTORY_format__, self.get_data(rva),
+ file_offset = self.get_offset_from_rva(rva) )
+ except PEFormatError:
+ self.__warnings.append(
+ 'Error parsing export directory at RVA: 0x%x' % ( rva ) )
+ return
+
+ if not export_dir:
+ return
+
+ try:
+ address_of_names = self.get_data(
+ export_dir.AddressOfNames, export_dir.NumberOfNames*4)
+ address_of_name_ordinals = self.get_data(
+ export_dir.AddressOfNameOrdinals, export_dir.NumberOfNames*4)
+ address_of_functions = self.get_data(
+ export_dir.AddressOfFunctions, export_dir.NumberOfFunctions*4)
+ except PEFormatError:
+ self.__warnings.append(
+ 'Error parsing export directory at RVA: 0x%x' % ( rva ) )
+ return
+
+ exports = []
+
+ for i in xrange(export_dir.NumberOfNames):
+
+
+ symbol_name = self.get_string_at_rva(
+ self.get_dword_from_data(address_of_names, i))
+
+ symbol_ordinal = self.get_word_from_data(
+ address_of_name_ordinals, i)
+
+
+ if symbol_ordinal*4<len(address_of_functions):
+ symbol_address = self.get_dword_from_data(
+ address_of_functions, symbol_ordinal)
+ else:
+ # Corrupt? a bad pointer... we assume it's all
+ # useless, no exports
+ return None
+
+ # If the funcion's rva points within the export directory
+ # it will point to a string with the forwarded symbol's string
+ # instead of pointing the the function start address.
+
+ if symbol_address>=rva and symbol_address<rva+size:
+ forwarder_str = self.get_string_at_rva(symbol_address)
+ else:
+ forwarder_str = None
+
+
+ exports.append(
+ ExportData(
+ ordinal = export_dir.Base+symbol_ordinal,
+ address = symbol_address,
+ name = symbol_name,
+ forwarder = forwarder_str))
+
+ ordinals = [exp.ordinal for exp in exports]
+
+ for idx in xrange(export_dir.NumberOfFunctions):
+
+ if not idx+export_dir.Base in ordinals:
+ symbol_address = self.get_dword_from_data(
+ address_of_functions,
+ idx)
+
+ #
+ # Checking for forwarder again.
+ #
+ if symbol_address>=rva and symbol_address<rva+size:
+ forwarder_str = self.get_string_at_rva(symbol_address)
+ else:
+ forwarder_str = None
+
+ exports.append(
+ ExportData(
+ ordinal = export_dir.Base+idx,
+ address = symbol_address,
+ name = None,
+ forwarder = forwarder_str))
+
+ return ExportDirData(
+ struct = export_dir,
+ symbols = exports)
+
+
+ def dword_align(self, offset, base):
+ offset += base
+ return (offset+3) - ((offset+3)%4) - base
+
+
+
+ def parse_delay_import_directory(self, rva, size):
+ """Walk and parse the delay import directory."""
+
+ import_descs = []
+ while True:
+ try:
+ # If the RVA is invalid all would blow up. Some PEs seem to be
+ # specially nasty and have an invalid RVA.
+ data = self.get_data(rva)
+ except PEFormatError, e:
+ self.__warnings.append(
+ 'Error parsing the Delay import directory at RVA: 0x%x' % ( rva ) )
+ break
+
+ import_desc = self.__unpack_data__(
+ self.__IMAGE_DELAY_IMPORT_DESCRIPTOR_format__,
+ data, file_offset = self.get_offset_from_rva(rva) )
+
+
+ # If the structure is all zeores, we reached the end of the list
+ if not import_desc or import_desc.all_zeroes():
+ break
+
+
+ rva += import_desc.sizeof()
+
+ try:
+ import_data = self.parse_imports(
+ import_desc.pINT,
+ import_desc.pIAT,
+ None)
+ except PEFormatError, e:
+ self.__warnings.append(
+ 'Error parsing the Delay import directory. ' +
+ 'Invalid import data at RVA: 0x%x' % ( rva ) )
+ break
+
+ if not import_data:
+ continue
+
+
+ dll = self.get_string_at_rva(import_desc.szName)
+ if dll:
+ import_descs.append(
+ ImportDescData(
+ struct = import_desc,
+ imports = import_data,
+ dll = dll))
+
+ return import_descs
+
+
+
+ def parse_import_directory(self, rva, size):
+ """Walk and parse the import directory."""
+
+ import_descs = []
+ while True:
+ try:
+ # If the RVA is invalid all would blow up. Some EXEs seem to be
+ # specially nasty and have an invalid RVA.
+ data = self.get_data(rva)
+ except PEFormatError, e:
+ self.__warnings.append(
+ 'Error parsing the Import directory at RVA: 0x%x' % ( rva ) )
+ break
+
+ import_desc = self.__unpack_data__(
+ self.__IMAGE_IMPORT_DESCRIPTOR_format__,
+ data, file_offset = self.get_offset_from_rva(rva) )
+
+ # If the structure is all zeores, we reached the end of the list
+ if not import_desc or import_desc.all_zeroes():
+ break
+
+ rva += import_desc.sizeof()
+
+ try:
+ import_data = self.parse_imports(
+ import_desc.OriginalFirstThunk,
+ import_desc.FirstThunk,
+ import_desc.ForwarderChain)
+ except PEFormatError, excp:
+ self.__warnings.append(
+ 'Error parsing the Import directory. ' +
+ 'Invalid Import data at RVA: 0x%x' % ( rva ) )
+ break
+ #raise excp
+
+ if not import_data:
+ continue
+
+ dll = self.get_string_at_rva(import_desc.Name)
+ if dll:
+ import_descs.append(
+ ImportDescData(
+ struct = import_desc,
+ imports = import_data,
+ dll = dll))
+
+ return import_descs
+
+
+
+ def parse_imports(self, original_first_thunk, first_thunk, forwarder_chain):
+ """Parse the imported symbols.
+
+ It will fill a list, which will be avalable as the dictionary
+ attribute "imports". Its keys will be the DLL names and the values
+ all the symbols imported from that object.
+ """
+
+ imported_symbols = []
+ imports_section = self.get_section_by_rva(first_thunk)
+ if not imports_section:
+ raise PEFormatError, 'Invalid/corrupt imports.'
+
+
+ # Import Lookup Table. Contains ordinals or pointers to strings.
+ ilt = self.get_import_table(original_first_thunk)
+ # Import Address Table. May have identical content to ILT if
+ # PE file is not bounded, Will contain the address of the
+ # imported symbols once the binary is loaded or if it is already
+ # bound.
+ iat = self.get_import_table(first_thunk)
+
+ # OC Patch:
+ # Would crash if iat or ilt had None type
+ if not iat and not ilt:
+ raise PEFormatError(
+ 'Invalid Import Table information. ' +
+ 'Both ILT and IAT appear to be broken.')
+
+ if not iat and ilt:
+ table = ilt
+ elif iat and not ilt:
+ table = iat
+ elif ilt and ((len(ilt) and len(iat)==0) or (len(ilt) == len(iat))):
+ table = ilt
+ elif (ilt and len(ilt))==0 and (iat and len(iat)):
+ table = iat
+ else:
+ return None
+
+ for idx in xrange(len(table)):
+
+ imp_ord = None
+ imp_hint = None
+ imp_name = None
+ hint_name_table_rva = None
+
+ if table[idx].AddressOfData:
+
+ if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
+ ordinal_flag = IMAGE_ORDINAL_FLAG
+ elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+ ordinal_flag = IMAGE_ORDINAL_FLAG64
+
+ # If imported by ordinal, we will append the ordinal number
+ #
+ if table[idx].AddressOfData & ordinal_flag:
+ import_by_ordinal = True
+ imp_ord = table[idx].AddressOfData & 0xffff
+ imp_name = None
+ else:
+ import_by_ordinal = False
+ try:
+ hint_name_table_rva = table[idx].AddressOfData & 0x7fffffff
+ data = self.get_data(hint_name_table_rva, 2)
+ # Get the Hint
+ imp_hint = self.get_word_from_data(data, 0)
+ imp_name = self.get_string_at_rva(table[idx].AddressOfData+2)
+ except PEFormatError, e:
+ pass
+
+ imp_address = first_thunk+self.OPTIONAL_HEADER.ImageBase+idx*4
+
+ if iat and ilt and ilt[idx].AddressOfData != iat[idx].AddressOfData:
+ imp_bound = iat[idx].AddressOfData
+ else:
+ imp_bound = None
+
+ if imp_name != '' and (imp_ord or imp_name):
+ imported_symbols.append(
+ ImportData(
+ import_by_ordinal = import_by_ordinal,
+ ordinal = imp_ord,
+ hint = imp_hint,
+ name = imp_name,
+ bound = imp_bound,
+ address = imp_address,
+ hint_name_table_rva = hint_name_table_rva))
+
+ return imported_symbols
+
+
+
+ def get_import_table(self, rva):
+
+ table = []
+
+ while True and rva:
+ try:
+ data = self.get_data(rva)
+ except PEFormatError, e:
+ self.__warnings.append(
+ 'Error parsing the import table. ' +
+ 'Invalid data at RVA: 0x%x' % ( rva ) )
+ return None
+
+ if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
+ format = self.__IMAGE_THUNK_DATA_format__
+ elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+ format = self.__IMAGE_THUNK_DATA64_format__
+
+ thunk_data = self.__unpack_data__(
+ format, data, file_offset=self.get_offset_from_rva(rva) )
+
+ if not thunk_data or thunk_data.all_zeroes():
+ break
+
+ rva += thunk_data.sizeof()
+
+ table.append(thunk_data)
+
+ return table
+
+
+ def get_memory_mapped_image(self, max_virtual_address=0x10000000, ImageBase=None):
+ """Returns the data corresponding to the memory layout of the PE file.
+
+ The data includes the PE header and the sections loaded at offsets
+ corresponding to their relative virtual addresses. (the VirtualAddress
+ section header member).
+ Any offset in this data corresponds to the absolute memory address
+ ImageBase+offset.
+
+ The optional argument 'max_virtual_address' provides with means of limiting
+ which section are processed.
+ Any section with their VirtualAddress beyond this value will be skipped.
+ Normally, sections with values beyond this range are just there to confuse
+ tools. It's a common trick to see in packed executables.
+
+ If the 'ImageBase' optional argument is supplied, the file's relocations
+ will be applied to the image by calling the 'relocate_image()' method.
+ """
+
+ # Collect all sections in one code block
+ data = self.header
+ for section in self.sections:
+
+ # Miscellanous integrity tests.
+ # Some packer will set these to bogus values to
+ # make tools go nuts.
+ #
+ if section.Misc_VirtualSize == 0 or section.SizeOfRawData == 0:
+ continue
+
+ if section.SizeOfRawData > len(self.__data__):
+ continue
+
+ if section.PointerToRawData > len(self.__data__):
+ continue
+
+ if section.VirtualAddress >= max_virtual_address:
+ continue
+
+ padding_length = section.VirtualAddress - len(data)
+
+ if padding_length>0:
+ data += '\0'*padding_length
+ elif padding_length<0:
+ data = data[:padding_length]
+
+ data += section.data
+
+ return data
+
+
+ def get_data(self, rva, length=None):
+ """Get data regardless of the section where it lies on.
+
+ Given a rva and the size of the chunk to retrieve, this method
+ will find the section where the data lies and return the data.
+ """
+
+ s = self.get_section_by_rva(rva)
+
+ if not s:
+ if rva<len(self.header):
+ if length:
+ end = rva+length
+ else:
+ end = None
+ return self.header[rva:end]
+
+ raise PEFormatError, 'data at RVA can\'t be fetched. Corrupt header?'
+
+ return s.get_data(rva, length)
+
+
+ def get_rva_from_offset(self, offset):
+ """Get the rva corresponding to this file offset. """
+
+ s = self.get_section_by_offset(offset)
+ if not s:
+ raise PEFormatError("specified offset (0x%x) doesn't belong to any section." % offset)
+ return s.get_rva_from_offset(offset)
+
+ def get_offset_from_rva(self, rva):
+ """Get the file offset corresponding to this rva.
+
+ Given a rva , this method will find the section where the
+ data lies and return the offset within the file.
+ """
+
+ s = self.get_section_by_rva(rva)
+ if not s:
+
+ raise PEFormatError, 'data at RVA can\'t be fetched. Corrupt header?'
+
+ return s.get_offset_from_rva(rva)
+
+
+ def get_string_at_rva(self, rva):
+ """Get an ASCII string located at the given address."""
+
+ s = self.get_section_by_rva(rva)
+ if not s:
+ if rva<len(self.header):
+ return self.get_string_from_data(rva, self.header)
+ return None
+
+ return self.get_string_from_data(rva-s.VirtualAddress, s.data)
+
+
+ def get_string_from_data(self, offset, data):
+ """Get an ASCII string from within the data."""
+
+ # OC Patch
+ b = None
+
+ try:
+ b = data[offset]
+ except IndexError:
+ return ''
+
+ s = ''
+ while ord(b):
+ s += b
+ offset += 1
+ try:
+ b = data[offset]
+ except IndexError:
+ break
+
+ return s
+
+
+ def get_string_u_at_rva(self, rva, max_length = 2**16):
+ """Get an Unicode string located at the given address."""
+
+ try:
+ # If the RVA is invalid all would blow up. Some EXEs seem to be
+ # specially nasty and have an invalid RVA.
+ data = self.get_data(rva, 2)
+ except PEFormatError, e:
+ return None
+
+ #length = struct.unpack('<H', data)[0]
+
+ s = u''
+ for idx in xrange(max_length):
+ try:
+ uchr = struct.unpack('<H', self.get_data(rva+2*idx, 2))[0]
+ except struct.error:
+ break
+
+ if unichr(uchr) == u'\0':
+ break
+ s += unichr(uchr)
+
+ return s
+
+
+ def get_section_by_offset(self, offset):
+ """Get the section containing the given file offset."""
+
+ sections = [s for s in self.sections if s.contains_offset(offset)]
+
+ if sections:
+ return sections[0]
+
+ return None
+
+
+ def get_section_by_rva(self, rva):
+ """Get the section containing the given address."""
+
+ sections = [s for s in self.sections if s.contains_rva(rva)]
+
+ if sections:
+ return sections[0]
+
+ return None
+
+ def __str__(self):
+ return self.dump_info()
+
+
+ def print_info(self):
+ """Print all the PE header information in a human readable from."""
+ print self.dump_info()
+
+
+ def dump_info(self, dump=None):
+ """Dump all the PE header information into human readable string."""
+
+
+ if dump is None:
+ dump = Dump()
+
+ warnings = self.get_warnings()
+ if warnings:
+ dump.add_header('Parsing Warnings')
+ for warning in warnings:
+ dump.add_line(warning)
+ dump.add_newline()
+
+
+ dump.add_header('DOS_HEADER')
+ dump.add_lines(self.DOS_HEADER.dump())
+ dump.add_newline()
+
+ dump.add_header('NT_HEADERS')
+ dump.add_lines(self.NT_HEADERS.dump())
+ dump.add_newline()
+
+ dump.add_header('FILE_HEADER')
+ dump.add_lines(self.FILE_HEADER.dump())
+
+ image_flags = self.retrieve_flags(IMAGE_CHARACTERISTICS, 'IMAGE_FILE_')
+
+ dump.add('Flags: ')
+ flags = []
+ for flag in image_flags:
+ if getattr(self.FILE_HEADER, flag[0]):
+ flags.append(flag[0])
+ dump.add_line(', '.join(flags))
+ dump.add_newline()
+
+ if hasattr(self, 'OPTIONAL_HEADER') and self.OPTIONAL_HEADER is not None:
+ dump.add_header('OPTIONAL_HEADER')
+ dump.add_lines(self.OPTIONAL_HEADER.dump())
+
+ dll_characteristics_flags = self.retrieve_flags(DLL_CHARACTERISTICS, 'IMAGE_DLL_CHARACTERISTICS_')
+
+ dump.add('DllCharacteristics: ')
+ flags = []
+ for flag in dll_characteristics_flags:
+ if getattr(self.OPTIONAL_HEADER, flag[0]):
+ flags.append(flag[0])
+ dump.add_line(', '.join(flags))
+ dump.add_newline()
+
+
+ dump.add_header('PE Sections')
+
+ section_flags = self.retrieve_flags(SECTION_CHARACTERISTICS, 'IMAGE_SCN_')
+
+ for section in self.sections:
+ dump.add_lines(section.dump())
+ dump.add('Flags: ')
+ flags = []
+ for flag in section_flags:
+ if getattr(section, flag[0]):
+ flags.append(flag[0])
+ dump.add_line(', '.join(flags))
+ dump.add_line('Entropy: %f (Min=0.0, Max=8.0)' % section.get_entropy() )
+ if md5 is not None:
+ dump.add_line('MD5 hash: %s' % section.get_hash_md5() )
+ if sha1 is not None:
+ dump.add_line('SHA-1 hash: %s' % section.get_hash_sha1() )
+ if sha256 is not None:
+ dump.add_line('SHA-256 hash: %s' % section.get_hash_sha256() )
+ if sha512 is not None:
+ dump.add_line('SHA-512 hash: %s' % section.get_hash_sha512() )
+ dump.add_newline()
+
+
+
+ if (hasattr(self, 'OPTIONAL_HEADER') and
+ hasattr(self.OPTIONAL_HEADER, 'DATA_DIRECTORY') ):
+
+ dump.add_header('Directories')
+ for idx in xrange(len(self.OPTIONAL_HEADER.DATA_DIRECTORY)):
+ directory = self.OPTIONAL_HEADER.DATA_DIRECTORY[idx]
+ dump.add_lines(directory.dump())
+ dump.add_newline()
+
+
+ if hasattr(self, 'VS_VERSIONINFO'):
+ dump.add_header('Version Information')
+ dump.add_lines(self.VS_VERSIONINFO.dump())
+ dump.add_newline()
+
+ if hasattr(self, 'VS_FIXEDFILEINFO'):
+ dump.add_lines(self.VS_FIXEDFILEINFO.dump())
+ dump.add_newline()
+
+ if hasattr(self, 'FileInfo'):
+ for entry in self.FileInfo:
+ dump.add_lines(entry.dump())
+ dump.add_newline()
+
+ if hasattr(entry, 'StringTable'):
+ for st_entry in entry.StringTable:
+ [dump.add_line(' '+line) for line in st_entry.dump()]
+ dump.add_line(' LangID: '+st_entry.LangID)
+ dump.add_newline()
+ for str_entry in st_entry.entries.items():
+ dump.add_line(' '+str_entry[0]+': '+str_entry[1])
+ dump.add_newline()
+
+ elif hasattr(entry, 'Var'):
+ for var_entry in entry.Var:
+ if hasattr(var_entry, 'entry'):
+ [dump.add_line(' '+line) for line in var_entry.dump()]
+ dump.add_line(
+ ' ' + var_entry.entry.keys()[0] +
+ ': ' + var_entry.entry.values()[0])
+
+ dump.add_newline()
+
+
+
+ if hasattr(self, 'DIRECTORY_ENTRY_EXPORT'):
+ dump.add_header('Exported symbols')
+ dump.add_lines(self.DIRECTORY_ENTRY_EXPORT.struct.dump())
+ dump.add_newline()
+ dump.add_line('%-10s %-10s %s' % ('Ordinal', 'RVA', 'Name'))
+ for export in self.DIRECTORY_ENTRY_EXPORT.symbols:
+ dump.add('%-10d 0x%08Xh %s' % (
+ export.ordinal, export.address, export.name))
+ if export.forwarder:
+ dump.add_line(' forwarder: %s' % export.forwarder)
+ else:
+ dump.add_newline()
+
+ dump.add_newline()
+
+ if hasattr(self, 'DIRECTORY_ENTRY_IMPORT'):
+ dump.add_header('Imported symbols')
+ for module in self.DIRECTORY_ENTRY_IMPORT:
+ dump.add_lines(module.struct.dump())
+ dump.add_newline()
+ for symbol in module.imports:
+
+ if symbol.import_by_ordinal is True:
+ dump.add('%s Ordinal[%s] (Imported by Ordinal)' % (
+ module.dll, str(symbol.ordinal)))
+ else:
+ dump.add('%s.%s Hint[%s]' % (
+ module.dll, symbol.name, str(symbol.hint)))
+
+ if symbol.bound:
+ dump.add_line(' Bound: 0x%08X' % (symbol.bound))
+ else:
+ dump.add_newline()
+ dump.add_newline()
+
+
+ if hasattr(self, 'DIRECTORY_ENTRY_BOUND_IMPORT'):
+ dump.add_header('Bound imports')
+ for bound_imp_desc in self.DIRECTORY_ENTRY_BOUND_IMPORT:
+
+ dump.add_lines(bound_imp_desc.struct.dump())
+ dump.add_line('DLL: %s' % bound_imp_desc.name)
+ dump.add_newline()
+
+ for bound_imp_ref in bound_imp_desc.entries:
+ dump.add_lines(bound_imp_ref.struct.dump(), 4)
+ dump.add_line('DLL: %s' % bound_imp_ref.name, 4)
+ dump.add_newline()
+
+
+ if hasattr(self, 'DIRECTORY_ENTRY_DELAY_IMPORT'):
+ dump.add_header('Delay Imported symbols')
+ for module in self.DIRECTORY_ENTRY_DELAY_IMPORT:
+
+ dump.add_lines(module.struct.dump())
+ dump.add_newline()
+
+ for symbol in module.imports:
+ if symbol.import_by_ordinal is True:
+ dump.add('%s Ordinal[%s] (Imported by Ordinal)' % (
+ module.dll, str(symbol.ordinal)))
+ else:
+ dump.add('%s.%s Hint[%s]' % (
+ module.dll, symbol.name, str(symbol.hint)))
+
+ if symbol.bound:
+ dump.add_line(' Bound: 0x%08X' % (symbol.bound))
+ else:
+ dump.add_newline()
+ dump.add_newline()
+
+
+ if hasattr(self, 'DIRECTORY_ENTRY_RESOURCE'):
+ dump.add_header('Resource directory')
+
+ dump.add_lines(self.DIRECTORY_ENTRY_RESOURCE.struct.dump())
+
+ for resource_type in self.DIRECTORY_ENTRY_RESOURCE.entries:
+
+ if resource_type.name is not None:
+ dump.add_line('Name: [%s]' % resource_type.name, 2)
+ else:
+ dump.add_line('Id: [0x%X] (%s)' % (
+ resource_type.struct.Id, RESOURCE_TYPE.get(
+ resource_type.struct.Id, '-')),
+ 2)
+
+ dump.add_lines(resource_type.struct.dump(), 2)
+
+ if hasattr(resource_type, 'directory'):
+
+ dump.add_lines(resource_type.directory.struct.dump(), 4)
+
+ for resource_id in resource_type.directory.entries:
+
+ if resource_id.name is not None:
+ dump.add_line('Name: [%s]' % resource_id.name, 6)
+ else:
+ dump.add_line('Id: [0x%X]' % resource_id.struct.Id, 6)
+
+ dump.add_lines(resource_id.struct.dump(), 6)
+
+ if hasattr(resource_id, 'directory'):
+ dump.add_lines(resource_id.directory.struct.dump(), 8)
+
+ for resource_lang in resource_id.directory.entries:
+ # dump.add_line('\\--- LANG [%d,%d][%s]' % (
+ # resource_lang.data.lang,
+ # resource_lang.data.sublang,
+ # LANG[resource_lang.data.lang]), 8)
+ dump.add_lines(resource_lang.struct.dump(), 10)
+ dump.add_lines(resource_lang.data.struct.dump(), 12)
+ dump.add_newline()
+
+ dump.add_newline()
+
+
+ if ( hasattr(self, 'DIRECTORY_ENTRY_TLS') and
+ self.DIRECTORY_ENTRY_TLS and
+ self.DIRECTORY_ENTRY_TLS.struct ):
+
+ dump.add_header('TLS')
+ dump.add_lines(self.DIRECTORY_ENTRY_TLS.struct.dump())
+ dump.add_newline()
+
+
+ if hasattr(self, 'DIRECTORY_ENTRY_DEBUG'):
+ dump.add_header('Debug information')
+ for dbg in self.DIRECTORY_ENTRY_DEBUG:
+ dump.add_lines(dbg.struct.dump())
+ try:
+ dump.add_line('Type: '+DEBUG_TYPE[dbg.struct.Type])
+ except KeyError:
+ dump.add_line('Type: 0x%x(Unknown)' % dbg.struct.Type)
+ dump.add_newline()
+
+
+ if hasattr(self, 'DIRECTORY_ENTRY_BASERELOC'):
+ dump.add_header('Base relocations')
+ for base_reloc in self.DIRECTORY_ENTRY_BASERELOC:
+ dump.add_lines(base_reloc.struct.dump())
+ for reloc in base_reloc.entries:
+ try:
+ dump.add_line('%08Xh %s' % (
+ reloc.rva, RELOCATION_TYPE[reloc.type][16:]), 4)
+ except KeyError:
+ dump.add_line('0x%08X 0x%x(Unknown)' % (
+ reloc.rva, reloc.type), 4)
+ dump.add_newline()
+
+
+ return dump.get_text()
+
+ # OC Patch
+ def get_physical_by_rva(self, rva):
+ """Gets the physical address in the PE file from an RVA value."""
+ try:
+ return self.get_offset_from_rva(rva)
+ except Exception:
+ return None
+
+
+ ##
+ # Double-Word get/set
+ ##
+
+ def get_data_from_dword(self, dword):
+ """Return a four byte string representing the double word value. (little endian)."""
+ return struct.pack('<L', dword)
+
+
+ def get_dword_from_data(self, data, offset):
+ """Convert four bytes of data to a double word (little endian)
+
+ 'offset' is assumed to index into a dword array. So setting it to
+ N will return a dword out of the data sarting at offset N*4.
+
+ Returns None if the data can't be turned into a double word.
+ """
+
+ if (offset+1)*4 > len(data):
+ return None
+
+ return struct.unpack('<L', data[offset*4:(offset+1)*4])[0]
+
+
+ def get_dword_at_rva(self, rva):
+ """Return the double word value at the given RVA.
+
+ Returns None if the value can't be read, i.e. the RVA can't be mapped
+ to a file offset.
+ """
+
+ try:
+ return self.get_dword_from_data(self.get_data(rva)[:4], 0)
+ except PEFormatError:
+ return None
+
+
+ def get_dword_from_offset(self, offset):
+ """Return the double word value at the given file offset. (little endian)"""
+
+ if offset+4 > len(self.__data__):
+ return None
+
+ return self.get_dword_from_data(self.__data__[offset:offset+4], 0)
+
+
+ def set_dword_at_rva(self, rva, dword):
+ """Set the double word value at the file offset corresponding to the given RVA."""
+ return self.set_bytes_at_rva(rva, self.get_data_from_dword(dword))
+
+
+ def set_dword_at_offset(self, offset, dword):
+ """Set the double word value at the given file offset."""
+ return self.set_bytes_at_offset(offset, self.get_data_from_dword(dword))
+
+
+
+ ##
+ # Word get/set
+ ##
+
+ def get_data_from_word(self, word):
+ """Return a two byte string representing the word value. (little endian)."""
+ return struct.pack('<H', word)
+
+
+ def get_word_from_data(self, data, offset):
+ """Convert two bytes of data to a word (little endian)
+
+ 'offset' is assumed to index into a word array. So setting it to
+ N will return a dword out of the data sarting at offset N*2.
+
+ Returns None if the data can't be turned into a word.
+ """
+
+ if (offset+1)*2 > len(data):
+ return None
+
+ return struct.unpack('<H', data[offset*2:(offset+1)*2])[0]
+
+
+ def get_word_at_rva(self, rva):
+ """Return the word value at the given RVA.
+
+ Returns None if the value can't be read, i.e. the RVA can't be mapped
+ to a file offset.
+ """
+
+ try:
+ return self.get_word_from_data(self.get_data(rva)[:2], 0)
+ except PEFormatError:
+ return None
+
+
+ def get_word_from_offset(self, offset):
+ """Return the word value at the given file offset. (little endian)"""
+
+ if offset+2 > len(self.__data__):
+ return None
+
+ return self.get_word_from_data(self.__data__[offset:offset+2], 0)
+
+
+ def set_word_at_rva(self, rva, word):
+ """Set the word value at the file offset corresponding to the given RVA."""
+ return self.set_bytes_at_rva(rva, self.get_data_from_word(word))
+
+
+ def set_word_at_offset(self, offset, word):
+ """Set the word value at the given file offset."""
+ return self.set_bytes_at_offset(offset, self.get_data_from_word(word))
+
+
+ ##
+ # Quad-Word get/set
+ ##
+
+ def get_data_from_qword(self, word):
+ """Return a eight byte string representing the quad-word value. (little endian)."""
+ return struct.pack('<Q', word)
+
+
+ def get_qword_from_data(self, data, offset):
+ """Convert eight bytes of data to a word (little endian)
+
+ 'offset' is assumed to index into a word array. So setting it to
+ N will return a dword out of the data sarting at offset N*8.
+
+ Returns None if the data can't be turned into a quad word.
+ """
+
+ if (offset+1)*8 > len(data):
+ return None
+
+ return struct.unpack('<Q', data[offset*8:(offset+1)*8])[0]
+
+
+ def get_qword_at_rva(self, rva):
+ """Return the quad-word value at the given RVA.
+
+ Returns None if the value can't be read, i.e. the RVA can't be mapped
+ to a file offset.
+ """
+
+ try:
+ return self.get_qword_from_data(self.get_data(rva)[:8], 0)
+ except PEFormatError:
+ return None
+
+
+ def get_qword_from_offset(self, offset):
+ """Return the quad-word value at the given file offset. (little endian)"""
+
+ if offset+8 > len(self.__data__):
+ return None
+
+ return self.get_qword_from_data(self.__data__[offset:offset+8], 0)
+
+
+ def set_qword_at_rva(self, rva, qword):
+ """Set the quad-word value at the file offset corresponding to the given RVA."""
+ return self.set_bytes_at_rva(rva, self.get_data_from_qword(qword))
+
+
+ def set_qword_at_offset(self, offset, qword):
+ """Set the quad-word value at the given file offset."""
+ return self.set_bytes_at_offset(offset, self.get_data_from_qword(qword))
+
+
+
+ ##
+ # Set bytes
+ ##
+
+
+ def set_bytes_at_rva(self, rva, data):
+ """Overwrite, with the given string, the bytes at the file offset corresponding to the given RVA.
+
+ Return True if successful, False otherwise. It can fail if the
+ offset is outside the file's boundaries.
+ """
+
+ offset = self.get_physical_by_rva(rva)
+ if not offset:
+ raise False
+
+ return self.set_bytes_at_offset(offset, data)
+
+
+ def set_bytes_at_offset(self, offset, data):
+ """Overwrite the bytes at the given file offset with the given string.
+
+ Return True if successful, False otherwise. It can fail if the
+ offset is outside the file's boundaries.
+ """
+
+ if not isinstance(data, str):
+ raise TypeError('data should be of type: str')
+
+ if offset >= 0 and offset < len(self.__data__):
+ self.__data__ = ( self.__data__[:offset] +
+ data +
+ self.__data__[offset+len(data):] )
+ else:
+ return False
+
+ # Refresh the section's data with the modified information
+ #
+ for section in self.sections:
+ section_data_start = section.PointerToRawData
+ section_data_end = section_data_start+section.SizeOfRawData
+ section.data = self.__data__[section_data_start:section_data_end]
+
+ return True
+
+
+
+ def relocate_image(self, new_ImageBase):
+ """Apply the relocation information to the image using the provided new image base.
+
+ This method will apply the relocation information to the image. Given the new base,
+ all the relocations will be processed and both the raw data and the section's data
+ will be fixed accordingly.
+ The resulting image can be retrieved as well through the method:
+
+ get_memory_mapped_image()
+
+ In order to get something that would more closely match what could be found in memory
+ once the Windows loader finished its work.
+ """
+
+ relocation_difference = new_ImageBase - self.OPTIONAL_HEADER.ImageBase
+
+
+ for reloc in self.DIRECTORY_ENTRY_BASERELOC:
+
+ virtual_address = reloc.struct.VirtualAddress
+ size_of_block = reloc.struct.SizeOfBlock
+
+ # We iterate with an index because if the relocation is of type
+ # IMAGE_REL_BASED_HIGHADJ we need to also process the next entry
+ # at once and skip it for the next interation
+ #
+ entry_idx = 0
+ while entry_idx<len(reloc.entries):
+
+ entry = reloc.entries[entry_idx]
+ entry_idx += 1
+
+ if entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_ABSOLUTE']:
+ # Nothing to do for this type of relocation
+ pass
+
+ elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_HIGH']:
+ # Fix the high 16bits of a relocation
+ #
+ # Add high 16bits of relocation_difference to the
+ # 16bit value at RVA=entry.rva
+
+ self.set_word_at_rva(
+ entry.rva,
+ ( self.get_word_at_rva(entry.rva) + relocation_difference>>16)&0xffff )
+
+ elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_LOW']:
+ # Fix the low 16bits of a relocation
+ #
+ # Add low 16 bits of relocation_difference to the 16bit value
+ # at RVA=entry.rva
+
+ self.set_word_at_rva(
+ entry.rva,
+ ( self.get_word_at_rva(entry.rva) + relocation_difference)&0xffff)
+
+ elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_HIGHLOW']:
+ # Handle all high and low parts of a 32bit relocation
+ #
+ # Add relocation_difference to the value at RVA=entry.rva
+
+ self.set_dword_at_rva(
+ entry.rva,
+ self.get_dword_at_rva(entry.rva)+relocation_difference)
+
+ elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_HIGHADJ']:
+ # Fix the high 16bits of a relocation and adjust
+ #
+ # Add high 16bits of relocation_difference to the 32bit value
+ # composed from the (16bit value at RVA=entry.rva)<<16 plus
+ # the 16bit value at the next relocation entry.
+ #
+
+ # If the next entry is beyond the array's limits,
+ # abort... the table is corrupt
+ #
+ if entry_idx == len(reloc.entries):
+ break
+
+ next_entry = reloc.entries[entry_idx]
+ entry_idx += 1
+ self.set_word_at_rva( entry.rva,
+ ((self.get_word_at_rva(entry.rva)<<16) + next_entry.rva +
+ relocation_difference & 0xffff0000) >> 16 )
+
+ elif entry.type == RELOCATION_TYPE['IMAGE_REL_BASED_DIR64']:
+ # Apply the difference to the 64bit value at the offset
+ # RVA=entry.rva
+
+ self.set_qword_at_rva(
+ entry.rva,
+ self.get_qword_at_rva(entry.rva) + relocation_difference)
+
+
+ def verify_checksum(self):
+
+ return self.OPTIONAL_HEADER.CheckSum == self.generate_checksum()
+
+
+ def generate_checksum(self):
+
+ # Get the offset to the CheckSum field in the OptionalHeader
+ #
+ checksum_offset = self.OPTIONAL_HEADER.__file_offset__ + 0x40 # 64
+
+ checksum = 0
+
+ for i in range( len(self.__data__) / 4 ):
+
+ # Skip the checksum field
+ #
+ if i == checksum_offset / 4:
+ continue
+
+ dword = struct.unpack('L', self.__data__[ i*4 : i*4+4 ])[0]
+ checksum = (checksum & 0xffffffff) + dword + (checksum>>32)
+ if checksum > 2**32:
+ checksum = (checksum & 0xffffffff) + (checksum >> 32)
+
+ checksum = (checksum & 0xffff) + (checksum >> 16)
+ checksum = (checksum) + (checksum >> 16)
+ checksum = checksum & 0xffff
+
+ return checksum + len(self.__data__)
diff --git a/chromium/tools/symsrc/source_index.py b/chromium/tools/symsrc/source_index.py
new file mode 100755
index 00000000000..76b04892b0d
--- /dev/null
+++ b/chromium/tools/symsrc/source_index.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Usage: <win-path-to-pdb.pdb>
+This tool will take a PDB on the command line, extract the source files that
+were used in building the PDB, query SVN for which repository and revision
+these files are at, and then finally write this information back into the PDB
+in a format that the debugging tools understand. This allows for automatic
+source debugging, as all of the information is contained in the PDB, and the
+debugger can go out and fetch the source files via SVN.
+
+You most likely want to run these immediately after a build, since the source
+input files need to match the generated PDB, and we want the correct SVN
+revision information for the exact files that were used for the build.
+
+The following files from a windbg + source server installation are expected
+to reside in the same directory as this python script:
+ dbghelp.dll
+ pdbstr.exe
+ srctool.exe
+
+NOTE: Expected to run under a native win32 python, NOT cygwin. All paths are
+dealt with as win32 paths, since we have to interact with the Microsoft tools.
+"""
+
+import sys
+import os
+import time
+import subprocess
+import tempfile
+
+# This serves two purposes. First, it acts as a whitelist, and only files
+# from repositories listed here will be source indexed. Second, it allows us
+# to map from one SVN URL to another, so we can map to external SVN servers.
+REPO_MAP = {
+ "svn://chrome-svn/blink": "http://src.chromium.org/blink",
+ "svn://chrome-svn/chrome": "http://src.chromium.org/chrome",
+ "svn://chrome-svn/multivm": "http://src.chromium.org/multivm",
+ "svn://chrome-svn/native_client": "http://src.chromium.org/native_client",
+ "svn://chrome-svn.corp.google.com/blink": "http://src.chromium.org/blink",
+ "svn://chrome-svn.corp.google.com/chrome": "http://src.chromium.org/chrome",
+ "svn://chrome-svn.corp.google.com/multivm": "http://src.chromium.org/multivm",
+ "svn://chrome-svn.corp.google.com/native_client":
+ "http://src.chromium.org/native_client",
+ "svn://svn-mirror.golo.chromium.org/blink": "http://src.chromium.org/blink",
+ "svn://svn-mirror.golo.chromium.org/chrome": "http://src.chromium.org/chrome",
+ "svn://svn-mirror.golo.chromium.org/multivm":
+ "http://src.chromium.org/multivm",
+ "svn://svn-mirror.golo.chromium.org/native_client":
+ "http://src.chromium.org/native_client",
+ "http://v8.googlecode.com/svn": None,
+ "http://google-breakpad.googlecode.com/svn": None,
+ "http://googletest.googlecode.com/svn": None,
+ "http://open-vcdiff.googlecode.com/svn": None,
+ "http://google-url.googlecode.com/svn": None,
+}
+
+
+def FindFile(filename):
+ """Return the full windows path to a file in the same dir as this code."""
+ thisdir = os.path.dirname(os.path.join(os.path.curdir, __file__))
+ return os.path.abspath(os.path.join(thisdir, filename))
+
+
+def ExtractSourceFiles(pdb_filename):
+ """Extract a list of local paths of the source files from a PDB."""
+ srctool = subprocess.Popen([FindFile('srctool.exe'), '-r', pdb_filename],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ filelist = srctool.stdout.read()
+ res = srctool.wait()
+ if res != 0 or filelist.startswith("srctool: "):
+ raise "srctool failed: " + filelist
+ return [x for x in filelist.split('\r\n') if len(x) != 0]
+
+
+def ReadSourceStream(pdb_filename):
+ """Read the contents of the source information stream from a PDB."""
+ srctool = subprocess.Popen([FindFile('pdbstr.exe'),
+ '-r', '-s:srcsrv',
+ '-p:%s' % pdb_filename],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ data = srctool.stdout.read()
+ res = srctool.wait()
+
+ if (res != 0 and res != -1) or data.startswith("pdbstr: "):
+ raise "pdbstr failed: " + data
+ return data
+
+
+def WriteSourceStream(pdb_filename, data):
+ """Write the contents of the source information stream to a PDB."""
+ # Write out the data to a temporary filename that we can pass to pdbstr.
+ (f, fname) = tempfile.mkstemp()
+ f = os.fdopen(f, "wb")
+ f.write(data)
+ f.close()
+
+ srctool = subprocess.Popen([FindFile('pdbstr.exe'),
+ '-w', '-s:srcsrv',
+ '-i:%s' % fname,
+ '-p:%s' % pdb_filename],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ data = srctool.stdout.read()
+ res = srctool.wait()
+
+ if (res != 0 and res != -1) or data.startswith("pdbstr: "):
+ raise "pdbstr failed: " + data
+
+ os.unlink(fname)
+
+
+# TODO for performance, we should probably work in directories instead of
+# files. I'm scared of DEPS and generated files, so for now we query each
+# individual file, and don't make assumptions that all files in the same
+# directory are part of the same repository or at the same revision number.
+def ExtractSvnInfo(local_filename):
+ """Calls svn info to extract the repository, path, and revision."""
+ # We call svn.bat to make sure and get the depot tools SVN and not cygwin.
+ srctool = subprocess.Popen(['svn.bat', 'info', local_filename],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ info = srctool.stdout.read()
+ res = srctool.wait()
+ if res != 0:
+ return None
+ # Hack up into a dictionary of the fields printed by svn info.
+ vals = dict((y.split(': ', 2) for y in info.split('\r\n') if y))
+
+ root = vals['Repository Root']
+ if not vals['URL'].startswith(root):
+ raise "URL is not inside of the repository root?!?"
+ path = vals['URL'][len(root):]
+ rev = int(vals['Revision'])
+
+ return [root, path, rev]
+
+
+def UpdatePDB(pdb_filename, verbose=False):
+ """Update a pdb file with source information."""
+ dir_blacklist = { }
+ # TODO(deanm) look into "compressing" our output, by making use of vars
+ # and other things, so we don't need to duplicate the repo path and revs.
+ lines = [
+ 'SRCSRV: ini ------------------------------------------------',
+ 'VERSION=1',
+ 'INDEXVERSION=2',
+ 'VERCTRL=Subversion',
+ 'DATETIME=%s' % time.asctime(),
+ 'SRCSRV: variables ------------------------------------------',
+ 'SVN_EXTRACT_TARGET_DIR=%targ%\%fnbksl%(%var3%)\%var4%',
+ 'SVN_EXTRACT_TARGET=%svn_extract_target_dir%\%fnfile%(%var1%)',
+ 'SVN_EXTRACT_CMD=cmd /c mkdir "%svn_extract_target_dir%" && cmd /c svn cat "%var2%%var3%@%var4%" --non-interactive > "%svn_extract_target%"',
+ 'SRCSRVTRG=%SVN_extract_target%',
+ 'SRCSRVCMD=%SVN_extract_cmd%',
+ 'SRCSRV: source files ---------------------------------------',
+ ]
+
+ if ReadSourceStream(pdb_filename):
+ raise "PDB already has source indexing information!"
+
+ filelist = ExtractSourceFiles(pdb_filename)
+ for filename in filelist:
+ filedir = os.path.dirname(filename)
+
+ if verbose:
+ print "Processing: %s" % filename
+ # This directory is blacklisted, either because it's not part of the SVN
+ # repository, or from one we're not interested in indexing.
+ if dir_blacklist.get(filedir, False):
+ if verbose:
+ print " skipping, directory is blacklisted."
+ continue
+
+ info = ExtractSvnInfo(filename)
+
+ # Skip the file if it's not under an svn repository. To avoid constantly
+ # querying SVN for files outside of SVN control (for example, the CRT
+ # sources), check if the directory is outside of SVN and blacklist it.
+ if not info:
+ if not ExtractSvnInfo(filedir):
+ dir_blacklist[filedir] = True
+ if verbose:
+ print " skipping, file is not in an SVN repository"
+ continue
+
+ root = info[0]
+ path = info[1]
+ rev = info[2]
+
+ # Check if file was from a svn repository we don't know about, or don't
+ # want to index. Blacklist the entire directory.
+ if not REPO_MAP.has_key(info[0]):
+ if verbose:
+ print " skipping, file is from an unknown SVN repository %s" % root
+ dir_blacklist[filedir] = True
+ continue
+
+ # We might want to map an internal repository URL to an external repository.
+ if REPO_MAP[root]:
+ root = REPO_MAP[root]
+
+ lines.append('%s*%s*%s*%s' % (filename, root, path, rev))
+ if verbose:
+ print " indexed file."
+
+ lines.append('SRCSRV: end ------------------------------------------------')
+
+ WriteSourceStream(pdb_filename, '\r\n'.join(lines))
+
+
+def main():
+ if len(sys.argv) < 2 or len(sys.argv) > 3:
+ print "usage: file.pdb [-v]"
+ return 1
+
+ verbose = False
+ if len(sys.argv) == 3:
+ verbose = (sys.argv[2] == '-v')
+
+ UpdatePDB(sys.argv[1], verbose=verbose)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/sync-webkit-git.py b/chromium/tools/sync-webkit-git.py
new file mode 100755
index 00000000000..3c7c5484c7d
--- /dev/null
+++ b/chromium/tools/sync-webkit-git.py
@@ -0,0 +1,221 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Update third_party/WebKit using git.
+
+Under the assumption third_party/WebKit is a clone of git.webkit.org,
+we can use git commands to make it match the version requested by DEPS.
+
+See http://code.google.com/p/chromium/wiki/UsingWebKitGit for details on
+how to use this.
+"""
+
+import logging
+import optparse
+import os
+import re
+import subprocess
+import sys
+import urllib
+
+
+def RunGit(command):
+ """Run a git subcommand, returning its output."""
+ # On Windows, use shell=True to get PATH interpretation.
+ command = ['git'] + command
+ logging.info(' '.join(command))
+ shell = (os.name == 'nt')
+ proc = subprocess.Popen(command, shell=shell, stdout=subprocess.PIPE)
+ out = proc.communicate()[0].strip()
+ logging.info('Returned "%s"' % out)
+ return out
+
+
+def GetOverrideShortBranchName():
+ """Returns the user-configured override branch name, if any."""
+ override_config_name = 'chromium.sync-branch'
+ return RunGit(['config', '--get', override_config_name])
+
+
+def GetGClientBranchName():
+ """Returns the name of the magic branch that lets us know that DEPS is
+ managing the update cycle."""
+ # Is there an override branch specified?
+ override_branch_name = GetOverrideShortBranchName()
+ if not override_branch_name:
+ return 'refs/heads/gclient' # No override, so return the default branch.
+
+ # Verify that the branch from config exists.
+ ref_branch = 'refs/heads/' + override_branch_name
+ current_head = RunGit(['show-ref', '--hash', ref_branch])
+ if current_head:
+ return ref_branch
+
+ # Inform the user about the problem and how to fix it.
+ print ("The specified override branch ('%s') doesn't appear to exist." %
+ override_branch_name)
+ print "Please fix your git config value '%s'." % overide_config_name
+ sys.exit(1)
+
+
+def GetWebKitRev():
+ """Extract the 'webkit_revision' variable out of DEPS."""
+ locals = {'Var': lambda _: locals["vars"][_],
+ 'From': lambda *args: None}
+ execfile('DEPS', {}, locals)
+ return locals['vars']['webkit_revision']
+
+
+def GetWebKitRevFromTarball(version):
+ """Extract the 'webkit_revision' variable out of tarball DEPS."""
+ deps_url = "http://src.chromium.org/svn/releases/" + version + "/DEPS"
+ f = urllib.urlopen(deps_url)
+ s = f.read()
+ m = re.search('(?<=/Source@)\w+', s)
+ return m.group(0)
+
+
+def FindSVNRev(branch_name, target_rev):
+ """Map an SVN revision to a git hash.
+ Like 'git svn find-rev' but without the git-svn bits."""
+
+ # We iterate through the commit log looking for "git-svn-id" lines,
+ # which contain the SVN revision of that commit. We can stop once
+ # we've found our target (or hit a revision number lower than what
+ # we're looking for, indicating not found).
+
+ target_rev = int(target_rev)
+
+ # regexp matching the "commit" line from the log.
+ commit_re = re.compile(r'^commit ([a-f\d]{40})$')
+ # regexp matching the git-svn line from the log.
+ git_svn_re = re.compile(r'^\s+git-svn-id: [^@]+@(\d+) ')
+ if not branch_name:
+ branch_name = 'origin/master'
+ cmd = ['git', 'log', '--no-color', '--first-parent', '--pretty=medium',
+ branch_name]
+ logging.info(' '.join(cmd))
+ log = subprocess.Popen(cmd, shell=(os.name == 'nt'), stdout=subprocess.PIPE)
+ # Track whether we saw a revision *later* than the one we're seeking.
+ saw_later = False
+ for line in log.stdout:
+ match = commit_re.match(line)
+ if match:
+ commit = match.group(1)
+ continue
+ match = git_svn_re.match(line)
+ if match:
+ rev = int(match.group(1))
+ if rev <= target_rev:
+ log.stdout.close() # Break pipe.
+ if rev < target_rev:
+ if not saw_later:
+ return None # Can't be sure whether this rev is ok.
+ print ("WARNING: r%d not found, so using next nearest earlier r%d" %
+ (target_rev, rev))
+ return commit
+ else:
+ saw_later = True
+
+ print "Error: reached end of log without finding commit info."
+ print "Something has likely gone horribly wrong."
+ return None
+
+
+def GetRemote():
+ branch = GetOverrideShortBranchName()
+ if not branch:
+ branch = 'gclient'
+
+ remote = RunGit(['config', '--get', 'branch.' + branch + '.remote'])
+ if remote:
+ return remote
+ return 'origin'
+
+
+def UpdateGClientBranch(branch_name, webkit_rev, magic_gclient_branch):
+ """Update the magic gclient branch to point at |webkit_rev|.
+
+ Returns: true if the branch didn't need changes."""
+ target = FindSVNRev(branch_name, webkit_rev)
+ if not target:
+ print "r%s not available; fetching." % webkit_rev
+ subprocess.check_call(['git', 'fetch', GetRemote()],
+ shell=(os.name == 'nt'))
+ target = FindSVNRev(branch_name, webkit_rev)
+ if not target:
+ print "ERROR: Couldn't map r%s to a git revision." % webkit_rev
+ sys.exit(1)
+
+ current = RunGit(['show-ref', '--hash', magic_gclient_branch])
+ if current == target:
+ return False # No change necessary.
+
+ subprocess.check_call(['git', 'update-ref', '-m', 'gclient sync',
+ magic_gclient_branch, target],
+ shell=(os.name == 'nt'))
+ return True
+
+
+def UpdateCurrentCheckoutIfAppropriate(magic_gclient_branch):
+ """Reset the current gclient branch if that's what we have checked out."""
+ branch = RunGit(['symbolic-ref', '-q', 'HEAD'])
+ if branch != magic_gclient_branch:
+ print "We have now updated the 'gclient' branch, but third_party/WebKit"
+ print "has some other branch ('%s') checked out." % branch
+ print "Run 'git checkout gclient' under third_party/WebKit if you want"
+ print "to switch it to the version requested by DEPS."
+ return 1
+
+ if subprocess.call(['git', 'diff-index', '--exit-code', '--shortstat',
+ 'HEAD'], shell=(os.name == 'nt')):
+ print "Resetting tree state to new revision."
+ subprocess.check_call(['git', 'reset', '--hard'], shell=(os.name == 'nt'))
+
+
+def main():
+ parser = optparse.OptionParser()
+ parser.add_option('-v', '--verbose', action='store_true')
+ parser.add_option('-r', '--revision', help="switch to desired revision")
+ parser.add_option('-t', '--tarball', help="switch to desired tarball release")
+ parser.add_option('-b', '--branch', help="branch name that gclient generate")
+ options, args = parser.parse_args()
+ if options.verbose:
+ logging.basicConfig(level=logging.INFO)
+ if not os.path.exists('third_party/WebKit/.git'):
+ if os.path.exists('third_party/WebKit'):
+ print "ERROR: third_party/WebKit appears to not be under git control."
+ else:
+ print "ERROR: third_party/WebKit could not be found."
+ print "Did you run this script from the right directory?"
+
+ print "See http://code.google.com/p/chromium/wiki/UsingWebKitGit for"
+ print "setup instructions."
+ return 1
+
+ if options.revision:
+ webkit_rev = options.revision
+ if options.tarball:
+ print "WARNING: --revision is given, so ignore --tarball"
+ else:
+ if options.tarball:
+ webkit_rev = GetWebKitRevFromTarball(options.tarball)
+ else:
+ webkit_rev = GetWebKitRev()
+
+ print 'Desired revision: r%s.' % webkit_rev
+ os.chdir('third_party/WebKit')
+ magic_gclient_branch = GetGClientBranchName()
+ changed = UpdateGClientBranch(options.branch, webkit_rev,
+ magic_gclient_branch)
+ if changed:
+ return UpdateCurrentCheckoutIfAppropriate(magic_gclient_branch)
+ else:
+ print "Already on correct revision."
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/tcmalloc/print-live-objects.py b/chromium/tools/tcmalloc/print-live-objects.py
new file mode 100755
index 00000000000..dfed9c60999
--- /dev/null
+++ b/chromium/tools/tcmalloc/print-live-objects.py
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Symbolizes and prints live objects as recorded by tcmalloc's
+HeapProfilerDumpLiveObjects.
+"""
+
+import os
+import re
+import subprocess
+import sys
+import tempfile
+
+def usage():
+ print """\
+Usage:
+ tools/tcmalloc/print-live-objects.py out/Debug/chrome leaks.dmp
+"""
+
+def LoadDump(dump_file):
+ result = []
+ leakfmt = re.compile(
+ r"^\s*1:\s*(\d+)\s*\[\s*1:\s*\d+\]\s*@(0x[a-f0-9]+)((\s+0x[a-f0-9]+)*)$")
+ line_no = 0
+ with open(dump_file) as f:
+ for line in f:
+ line_no = line_no + 1
+ matches = leakfmt.match(line)
+ if not matches:
+ print "%s: could not parse line %d, skipping" % (dump_file, line_no)
+ else:
+ trace = { "size": int(matches.group(1)),
+ "address": matches.group(2),
+ "frames": matches.group(3).strip().split(" ")}
+ result.append(trace)
+ return result
+
+
+def Symbolize(binary, traces):
+ addresses = set()
+ for trace in traces:
+ for frame in trace["frames"]:
+ addresses.add(frame)
+ addr_file, addr_filename = tempfile.mkstemp()
+ for addr in addresses:
+ os.write(addr_file, "%s\n" % addr)
+ os.close(addr_file)
+ syms = subprocess.Popen([
+ "addr2line", "-f", "-C", "-e", binary, "@%s" % addr_filename],
+ stdout=subprocess.PIPE).communicate()[0].strip().split("\n")
+ table = {}
+ cwd = os.getcwd()
+ for address, symbol, location in zip(addresses, syms[::2], syms[1::2]):
+ if location != "??:0":
+ filename, line = location.split(":")
+ filename = os.path.realpath(filename)[len(cwd)+1:]
+ location = "%s:%s" % (filename, line)
+ table[address] = { "name": symbol, "location": location }
+ for trace in traces:
+ frames = []
+ for frame in trace["frames"]:
+ frames.append(table[frame])
+ trace["frames"] = frames
+
+
+def Main(argv):
+ if sys.platform != 'linux2':
+ print 'print-live-objects.py requires addr2line only present on Linux.'
+ sys.exit(1)
+
+ if len(argv) != 3:
+ usage()
+ sys.exit(1)
+
+ traces = LoadDump(argv[2])
+ Symbolize(argv[1], traces)
+
+ if not traces:
+ print "No leaks found!"
+
+ for trace in sorted(traces, key=lambda x: -x["size"]):
+ print "Leak of %d bytes at address %s" % (trace["size"], trace["address"])
+ for frame in trace["frames"]:
+ print " %s (%s)" % (frame["name"], frame["location"])
+ print ""
+
+
+if __name__ == '__main__':
+ Main(sys.argv)
diff --git a/chromium/tools/telemetry/OWNERS b/chromium/tools/telemetry/OWNERS
new file mode 100644
index 00000000000..440be181333
--- /dev/null
+++ b/chromium/tools/telemetry/OWNERS
@@ -0,0 +1,11 @@
+# The set noparent is temporary until src/OWNERS isn't *.
+set noparent
+bulach@chromium.org
+dtu@chromium.org
+nduca@chromium.org
+tonyg@chromium.org
+hartmanng@chromium.org
+marja@chromium.org
+
+# for cros-related changes.
+achuith@chromium.org
diff --git a/chromium/tools/telemetry/PRESUBMIT.py b/chromium/tools/telemetry/PRESUBMIT.py
new file mode 100644
index 00000000000..4e485a6b6d6
--- /dev/null
+++ b/chromium/tools/telemetry/PRESUBMIT.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+PYLINT_BLACKLIST = []
+PYLINT_DISABLED_WARNINGS = ['R0923', 'R0201', 'E1101']
+
+def _CommonChecks(input_api, output_api):
+ results = []
+
+ # TODO(nduca): This should call update_docs.IsUpdateDocsNeeded().
+ # Disabled due to crbug.com/255326.
+ if False:
+ update_docs_path = os.path.join(
+ input_api.PresubmitLocalPath(), 'update_docs')
+ assert os.path.exists(update_docs_path)
+ results.append(output_api.PresubmitError(
+ 'Docs are stale. Please run:\n' +
+ '$ %s' % os.path.abspath(update_docs_path)))
+
+ results.extend(input_api.canned_checks.RunPylint(
+ input_api, output_api,
+ black_list=PYLINT_BLACKLIST,
+ disabled_warnings=PYLINT_DISABLED_WARNINGS))
+ return results
+
+def GetPathsToPrepend(input_api):
+ return [input_api.PresubmitLocalPath()]
+
+def RunWithPrependedPath(prepended_path, fn, *args):
+ old_path = sys.path
+
+ try:
+ sys.path = prepended_path + old_path
+ return fn(*args)
+ finally:
+ sys.path = old_path
+
+def CheckChangeOnUpload(input_api, output_api):
+ def go():
+ results = []
+ results.extend(_CommonChecks(input_api, output_api))
+ return results
+ return RunWithPrependedPath(GetPathsToPrepend(input_api), go)
+
+def CheckChangeOnCommit(input_api, output_api):
+ def go():
+ results = []
+ results.extend(_CommonChecks(input_api, output_api))
+ return results
+ return RunWithPrependedPath(GetPathsToPrepend(input_api), go)
diff --git a/chromium/tools/telemetry/README b/chromium/tools/telemetry/README
new file mode 100644
index 00000000000..744f53f6060
--- /dev/null
+++ b/chromium/tools/telemetry/README
@@ -0,0 +1,5 @@
+telemetry provides automation of chrome instances on top of the
+chrome developer tools protocol.
+
+The protocol we use:
+https://developers.google.com/chrome-developer-tools/docs/remote-debugging
diff --git a/chromium/tools/telemetry/build/__init__.py b/chromium/tools/telemetry/build/__init__.py
new file mode 100644
index 00000000000..9228df89b0e
--- /dev/null
+++ b/chromium/tools/telemetry/build/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/telemetry/build/update_docs.py b/chromium/tools/telemetry/build/update_docs.py
new file mode 100644
index 00000000000..8c42b309443
--- /dev/null
+++ b/chromium/tools/telemetry/build/update_docs.py
@@ -0,0 +1,148 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import optparse
+import os
+import pkgutil
+import pydoc
+import re
+import sys
+
+import telemetry
+from telemetry.core import util
+
+telemetry_dir = util.GetTelemetryDir()
+docs_dir = os.path.join(telemetry_dir, 'docs')
+
+def RemoveAllDocs():
+ for dirname, _, filenames in os.walk(docs_dir):
+ for filename in filenames:
+ os.remove(os.path.join(dirname, filename))
+
+def GenerateHTMLForModule(module):
+ html = pydoc.html.page(pydoc.describe(module),
+ pydoc.html.document(module, module.__name__))
+
+ # pydoc writes out html with links in a variety of funky ways. We need
+ # to fix them up.
+ assert not telemetry_dir.endswith(os.sep)
+ links = re.findall('(<a href="(.+?)">(.+?)</a>)', html)
+ for link_match in links:
+ link, href, link_text = link_match
+ if not href.startswith('file:'):
+ continue
+
+ new_href = href.replace('file:', '')
+ new_href = new_href.replace(telemetry_dir, os.pardir)
+ new_href = new_href.replace(os.sep, '/')
+
+ new_link_text = link_text.replace(telemetry_dir + os.sep, '')
+
+ new_link = '<a href="%s">%s</a>' % (new_href, new_link_text)
+ html = html.replace(link, new_link)
+
+ # pydoc writes out html with absolute path file links. This is not suitable
+ # for checked in documentation. So, fix up the HTML after it is generated.
+ #html = re.sub('href="file:%s' % telemetry_dir, 'href="..', html)
+ #html = re.sub(telemetry_dir + os.sep, '', html)
+ return html
+
+def WriteHTMLForModule(module):
+ page = GenerateHTMLForModule(module)
+ path = os.path.join(docs_dir, '%s.html' % module.__name__)
+ with open(path, 'w') as f:
+ sys.stderr.write('Wrote %s\n' % os.path.relpath(path))
+ f.write(page)
+
+def GetAllModulesToDocument(module):
+ modules = [module]
+ for _, modname, _ in pkgutil.walk_packages(
+ module.__path__, module.__name__ + '.'):
+ if modname.endswith('_unittest'):
+ logging.debug("skipping %s due to being a unittest", modname)
+ continue
+
+ module = __import__(modname, fromlist=[""])
+ name, _ = os.path.splitext(module.__file__)
+ if not os.path.exists(name + '.py'):
+ logging.info("skipping %s due to being an orphan .pyc", module.__file__)
+ continue
+
+ modules.append(module)
+ return modules
+
+class AlreadyDocumentedModule(object):
+ def __init__(self, filename):
+ self.filename = filename
+
+ @property
+ def name(self):
+ basename = os.path.basename(self.filename)
+ return os.path.splitext(basename)[0]
+
+ @property
+ def contents(self):
+ with open(self.filename, 'r') as f:
+ return f.read()
+
+def GetAlreadyDocumentedModules():
+ modules = []
+ for dirname, _, filenames in os.walk(docs_dir):
+ for filename in filenames:
+ path = os.path.join(dirname, filename)
+ modules.append(AlreadyDocumentedModule(path))
+ return modules
+
+
+def IsUpdateDocsNeeded():
+ already_documented_modules = GetAlreadyDocumentedModules()
+ already_documented_modules_by_name = dict(
+ (module.name, module) for module in already_documented_modules)
+ current_modules = GetAllModulesToDocument(telemetry)
+
+ # Quick check: if the names of modules has changed, we definitely need
+ # an update.
+ already_documented_module_names = set(
+ m.name for m in already_documented_modules)
+
+ current_module_names = set([m.__name__ for m in current_modules])
+
+ if current_module_names != already_documented_module_names:
+ return True
+
+ # Generate the new docs and compare aganist the old. If changed, then a
+ # an update is needed.
+ for current_module in current_modules:
+ already_documented_module = already_documented_modules_by_name[
+ current_module.__name__]
+ current_html = GenerateHTMLForModule(current_module)
+ if current_html != already_documented_module.contents:
+ return True
+
+ return False
+
+def Main(args):
+ parser = optparse.OptionParser()
+ parser.add_option(
+ '-v', '--verbose', action='count', default=0,
+ help='Increase verbosity level (repeat as needed)')
+ options, args = parser.parse_args(args)
+ if options.verbose >= 2:
+ logging.basicConfig(level=logging.DEBUG)
+ elif options.verbose:
+ logging.basicConfig(level=logging.INFO)
+ else:
+ logging.basicConfig(level=logging.WARNING)
+
+ assert os.path.isdir(docs_dir)
+
+ RemoveAllDocs()
+
+ old_cwd = os.getcwd()
+ try:
+ os.chdir(telemetry_dir)
+ for module in GetAllModulesToDocument(telemetry):
+ WriteHTMLForModule(module)
+ finally:
+ os.chdir(old_cwd)
diff --git a/chromium/tools/telemetry/docs/telemetry.core.browser.html b/chromium/tools/telemetry/docs/telemetry.core.browser.html
new file mode 100644
index 00000000000..78dfc77d1aa
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.browser.html
@@ -0,0 +1,176 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.browser</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.browser</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/browser.py">telemetry/core/browser.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.browser_backend.html">telemetry.core.chrome.browser_backend</a><br>
+<a href="telemetry.core.browser_credentials.html">telemetry.core.browser_credentials</a><br>
+<a href="telemetry.core.extension_dict.html">telemetry.core.extension_dict</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="telemetry.core.platform.html">telemetry.core.platform</a><br>
+<a href="telemetry.core.platform.profiler.profiler_finder.html">telemetry.core.platform.profiler.profiler_finder</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.tab_list.html">telemetry.core.tab_list</a><br>
+<a href="telemetry.core.temporary_http_server.html">telemetry.core.temporary_http_server</a><br>
+<a href="telemetry.core.wpr_modes.html">telemetry.core.wpr_modes</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.wpr_server.html">telemetry.core.wpr_server</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.browser.html#Browser">Browser</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Browser">class <strong>Browser</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;running&nbsp;browser&nbsp;instance&nbsp;that&nbsp;can&nbsp;be&nbsp;controlled&nbsp;in&nbsp;a&nbsp;limited&nbsp;way.<br>
+&nbsp;<br>
+To&nbsp;create&nbsp;a&nbsp;browser&nbsp;instance,&nbsp;use&nbsp;browser_finder.FindBrowser.<br>
+&nbsp;<br>
+Be&nbsp;sure&nbsp;to&nbsp;clean&nbsp;up&nbsp;after&nbsp;yourself&nbsp;by&nbsp;calling&nbsp;<a href="#Browser-Close">Close</a>()&nbsp;when&nbsp;you&nbsp;are&nbsp;done&nbsp;with<br>
+the&nbsp;browser.&nbsp;Or&nbsp;better&nbsp;yet:<br>
+&nbsp;&nbsp;browser_to_create&nbsp;=&nbsp;FindBrowser(options)<br>
+&nbsp;&nbsp;with&nbsp;browser_to_create.Create()&nbsp;as&nbsp;browser:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;do&nbsp;all&nbsp;your&nbsp;operations&nbsp;on&nbsp;browser&nbsp;here<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Browser-Close"><strong>Close</strong></a>(self)</dt><dd><tt>Closes&nbsp;this&nbsp;browser.</tt></dd></dl>
+
+<dl><dt><a name="Browser-GetStackTrace"><strong>GetStackTrace</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Browser-GetStandardOutput"><strong>GetStandardOutput</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Browser-GetTraceResultAndReset"><strong>GetTraceResultAndReset</strong></a>(self)</dt><dd><tt>Returns&nbsp;the&nbsp;result&nbsp;of&nbsp;the&nbsp;trace,&nbsp;as&nbsp;TraceResult&nbsp;<a href="__builtin__.html#object">object</a>.</tt></dd></dl>
+
+<dl><dt><a name="Browser-SetHTTPServerDirectories"><strong>SetHTTPServerDirectories</strong></a>(self, paths)</dt><dd><tt>Returns&nbsp;True&nbsp;if&nbsp;the&nbsp;HTTP&nbsp;server&nbsp;was&nbsp;started,&nbsp;False&nbsp;otherwise.</tt></dd></dl>
+
+<dl><dt><a name="Browser-SetReplayArchivePath"><strong>SetReplayArchivePath</strong></a>(self, archive_path, append_to_existing_wpr<font color="#909090">=False</font>, make_javascript_deterministic<font color="#909090">=True</font>)</dt></dl>
+
+<dl><dt><a name="Browser-StartProfiling"><strong>StartProfiling</strong></a>(self, options, base_output_file)</dt><dd><tt>Starts&nbsp;profiling&nbsp;using&nbsp;|options|.profiler_tool.&nbsp;Results&nbsp;are&nbsp;saved&nbsp;to<br>
+|base_output_file|.&lt;process_name&gt;.</tt></dd></dl>
+
+<dl><dt><a name="Browser-StartTracing"><strong>StartTracing</strong></a>(self, custom_categories<font color="#909090">=None</font>, timeout<font color="#909090">=10</font>)</dt></dl>
+
+<dl><dt><a name="Browser-StopProfiling"><strong>StopProfiling</strong></a>(self)</dt><dd><tt>Stops&nbsp;all&nbsp;active&nbsp;profilers&nbsp;and&nbsp;saves&nbsp;their&nbsp;results.</tt></dd></dl>
+
+<dl><dt><a name="Browser-StopTracing"><strong>StopTracing</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Browser-__enter__"><strong>__enter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Browser-__exit__"><strong>__exit__</strong></a>(self, *args)</dt></dl>
+
+<dl><dt><a name="Browser-__init__"><strong>__init__</strong></a>(self, backend, platform_backend)</dt></dl>
+
+<dl><dt><a name="Browser-is_profiler_active"><strong>is_profiler_active</strong></a>(self, profiler_name)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser_type</strong></dt>
+</dl>
+<dl><dt><strong>extensions</strong></dt>
+<dd><tt>Returns&nbsp;the&nbsp;extension&nbsp;dictionary&nbsp;if&nbsp;it&nbsp;exists.</tt></dd>
+</dl>
+<dl><dt><strong>http_server</strong></dt>
+</dl>
+<dl><dt><strong>io_stats</strong></dt>
+<dd><tt>Returns&nbsp;a&nbsp;dict&nbsp;of&nbsp;IO&nbsp;statistics&nbsp;for&nbsp;the&nbsp;browser:<br>
+{&nbsp;'Browser':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadOperationCount':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteOperationCount':&nbsp;X,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadTransferCount':&nbsp;Y,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteTransferCount':&nbsp;Z<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'Gpu':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadOperationCount':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteOperationCount':&nbsp;X,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadTransferCount':&nbsp;Y,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteTransferCount':&nbsp;Z<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'Renderer':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadOperationCount':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteOperationCount':&nbsp;X,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadTransferCount':&nbsp;Y,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteTransferCount':&nbsp;Z<br>
+&nbsp;&nbsp;}<br>
+}</tt></dd>
+</dl>
+<dl><dt><strong>is_content_shell</strong></dt>
+<dd><tt>Returns&nbsp;whether&nbsp;this&nbsp;browser&nbsp;is&nbsp;a&nbsp;content&nbsp;shell,&nbsp;only.</tt></dd>
+</dl>
+<dl><dt><strong>memory_stats</strong></dt>
+<dd><tt>Returns&nbsp;a&nbsp;dict&nbsp;of&nbsp;memory&nbsp;statistics&nbsp;for&nbsp;the&nbsp;browser:<br>
+{&nbsp;'Browser':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VM':&nbsp;S,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VMPeak':&nbsp;T,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSize':&nbsp;U,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSizePeak':&nbsp;V,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ProportionalSetSize':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'PrivateDirty':&nbsp;X<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'Gpu':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VM':&nbsp;S,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VMPeak':&nbsp;T,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSize':&nbsp;U,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSizePeak':&nbsp;V,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ProportionalSetSize':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'PrivateDirty':&nbsp;X<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'Renderer':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VM':&nbsp;S,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VMPeak':&nbsp;T,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSize':&nbsp;U,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSizePeak':&nbsp;V,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ProportionalSetSize':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'PrivateDirty':&nbsp;X<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'SystemCommitCharge':&nbsp;Y,<br>
+&nbsp;&nbsp;'ProcessCount':&nbsp;Z,<br>
+}<br>
+Any&nbsp;of&nbsp;the&nbsp;above&nbsp;keys&nbsp;may&nbsp;be&nbsp;missing&nbsp;on&nbsp;a&nbsp;per-platform&nbsp;basis.</tt></dd>
+</dl>
+<dl><dt><strong>platform</strong></dt>
+</dl>
+<dl><dt><strong>supports_extensions</strong></dt>
+</dl>
+<dl><dt><strong>supports_tab_control</strong></dt>
+</dl>
+<dl><dt><strong>supports_tracing</strong></dt>
+</dl>
+<dl><dt><strong>tabs</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.browser_credentials.html b/chromium/tools/telemetry/docs/telemetry.core.browser_credentials.html
new file mode 100644
index 00000000000..87ca68b155b
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.browser_credentials.html
@@ -0,0 +1,78 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.browser_credentials</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.browser_credentials</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/browser_credentials.py">telemetry/core/browser_credentials.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.facebook_credentials_backend.html">telemetry.core.chrome.facebook_credentials_backend</a><br>
+<a href="telemetry.core.chrome.google_credentials_backend.html">telemetry.core.chrome.google_credentials_backend</a><br>
+</td><td width="25%" valign=top><a href="json.html">json</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.options_for_unittests.html">telemetry.unittest.options_for_unittests</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.browser_credentials.html#BrowserCredentials">BrowserCredentials</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BrowserCredentials">class <strong>BrowserCredentials</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="BrowserCredentials-Add"><strong>Add</strong></a>(self, credentials_type, data)</dt></dl>
+
+<dl><dt><a name="BrowserCredentials-AddBackend"><strong>AddBackend</strong></a>(self, backend)</dt></dl>
+
+<dl><dt><a name="BrowserCredentials-CanLogin"><strong>CanLogin</strong></a>(self, credentials_type)</dt></dl>
+
+<dl><dt><a name="BrowserCredentials-IsLoggedIn"><strong>IsLoggedIn</strong></a>(self, credentials_type)</dt></dl>
+
+<dl><dt><a name="BrowserCredentials-LoginNeeded"><strong>LoginNeeded</strong></a>(self, tab, credentials_type)</dt></dl>
+
+<dl><dt><a name="BrowserCredentials-LoginNoLongerNeeded"><strong>LoginNoLongerNeeded</strong></a>(self, tab, credentials_type)</dt></dl>
+
+<dl><dt><a name="BrowserCredentials-WarnIfMissingCredentials"><strong>WarnIfMissingCredentials</strong></a>(self, page_set)</dt></dl>
+
+<dl><dt><a name="BrowserCredentials-__init__"><strong>__init__</strong></a>(self, backends<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>credentials_path</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.browser_finder.html b/chromium/tools/telemetry/docs/telemetry.core.browser_finder.html
new file mode 100644
index 00000000000..bccf9bc0c28
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.browser_finder.html
@@ -0,0 +1,179 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.browser_finder</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.browser_finder</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/browser_finder.py">telemetry/core/browser_finder.py</a></font></td></tr></table>
+ <p><tt>Finds&nbsp;browsers&nbsp;that&nbsp;can&nbsp;be&nbsp;controlled&nbsp;by&nbsp;telemetry.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.android_browser_finder.html">telemetry.core.chrome.android_browser_finder</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.cros_browser_finder.html">telemetry.core.chrome.cros_browser_finder</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.desktop_browser_finder.html">telemetry.core.chrome.desktop_browser_finder</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.browser_finder.html#BrowserFinderException">BrowserFinderException</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.browser_finder.html#BrowserTypeRequiredException">BrowserTypeRequiredException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BrowserFinderException">class <strong>BrowserFinderException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.browser_finder.html#BrowserFinderException">BrowserFinderException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="BrowserFinderException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserFinderException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#BrowserFinderException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="BrowserFinderException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserFinderException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="BrowserFinderException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserFinderException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="BrowserFinderException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserFinderException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="BrowserFinderException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserFinderException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="BrowserFinderException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="BrowserFinderException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserFinderException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="BrowserFinderException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserFinderException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="BrowserFinderException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="BrowserFinderException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserFinderException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="BrowserFinderException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BrowserTypeRequiredException">class <strong>BrowserTypeRequiredException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.browser_finder.html#BrowserTypeRequiredException">BrowserTypeRequiredException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="BrowserTypeRequiredException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserTypeRequiredException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#BrowserTypeRequiredException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="BrowserTypeRequiredException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserTypeRequiredException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserTypeRequiredException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserTypeRequiredException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserTypeRequiredException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserTypeRequiredException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserTypeRequiredException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserTypeRequiredException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="BrowserTypeRequiredException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-FindBrowser"><strong>FindBrowser</strong></a>(options)</dt><dd><tt>Finds&nbsp;the&nbsp;best&nbsp;PossibleBrowser&nbsp;object&nbsp;to&nbsp;run&nbsp;given&nbsp;the&nbsp;provided<br>
+BrowserOptions&nbsp;object.&nbsp;The&nbsp;returned&nbsp;possiblity&nbsp;object&nbsp;can&nbsp;then&nbsp;be&nbsp;used&nbsp;to<br>
+connect&nbsp;to&nbsp;and&nbsp;control&nbsp;the&nbsp;located&nbsp;browser.&nbsp;A&nbsp;<a href="#BrowserFinderException">BrowserFinderException</a>&nbsp;will<br>
+be&nbsp;raised&nbsp;if&nbsp;the&nbsp;BrowserOptions&nbsp;argument&nbsp;is&nbsp;improperly&nbsp;set&nbsp;or&nbsp;if&nbsp;an&nbsp;error<br>
+occurs&nbsp;when&nbsp;finding&nbsp;a&nbsp;browser.</tt></dd></dl>
+ <dl><dt><a name="-GetAllAvailableBrowserTypes"><strong>GetAllAvailableBrowserTypes</strong></a>(options)</dt><dd><tt>Returns&nbsp;an&nbsp;array&nbsp;of&nbsp;browser&nbsp;types&nbsp;supported&nbsp;on&nbsp;this&nbsp;system.<br>
+A&nbsp;<a href="#BrowserFinderException">BrowserFinderException</a>&nbsp;will&nbsp;be&nbsp;raised&nbsp;if&nbsp;the&nbsp;BrowserOptions&nbsp;argument&nbsp;is<br>
+improperly&nbsp;set&nbsp;or&nbsp;if&nbsp;an&nbsp;error&nbsp;occurs&nbsp;when&nbsp;finding&nbsp;a&nbsp;browser.</tt></dd></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>ALL_BROWSER_TYPES</strong> = 'exact,release,debug,canary,content-shell-debug,c...chrome,cros-chrome,cros-chrome-guest,system-guest'</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.browser_options.html b/chromium/tools/telemetry/docs/telemetry.core.browser_options.html
new file mode 100644
index 00000000000..66443051bed
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.browser_options.html
@@ -0,0 +1,79 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.browser_options</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.browser_options</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/browser_options.py">telemetry/core/browser_options.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser_finder.html">telemetry.core.browser_finder</a><br>
+<a href="copy.html">copy</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="optparse.html">optparse</a><br>
+<a href="telemetry.core.profile_types.html">telemetry.core.profile_types</a><br>
+<a href="telemetry.core.platform.profiler.profiler_finder.html">telemetry.core.platform.profiler.profiler_finder</a><br>
+</td><td width="25%" valign=top><a href="shlex.html">shlex</a><br>
+<a href="sys.html">sys</a><br>
+<a href="telemetry.core.wpr_modes.html">telemetry.core.wpr_modes</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="optparse.html#Values">optparse.Values</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.browser_options.html#BrowserOptions">BrowserOptions</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BrowserOptions">class <strong>BrowserOptions</strong></a>(<a href="optparse.html#Values">optparse.Values</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Options&nbsp;to&nbsp;be&nbsp;used&nbsp;for&nbsp;discovering&nbsp;and&nbsp;launching&nbsp;a&nbsp;browser.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="BrowserOptions-AppendExtraBrowserArg"><strong>AppendExtraBrowserArg</strong></a>(self, arg)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-Copy"><strong>Copy</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-CreateParser"><strong>CreateParser</strong></a>(self, *args, **kwargs)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-__init__"><strong>__init__</strong></a>(self, browser_type<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="optparse.html#Values">optparse.Values</a>:<br>
+<dl><dt><a name="BrowserOptions-__cmp__"><strong>__cmp__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-__repr__"><strong>__repr__</strong></a> = _repr(self)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-__str__"><strong>__str__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-ensure_value"><strong>ensure_value</strong></a>(self, attr, value)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-read_file"><strong>read_file</strong></a>(self, filename, mode<font color="#909090">='careful'</font>)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-read_module"><strong>read_module</strong></a>(self, modname, mode<font color="#909090">='careful'</font>)</dt></dl>
+
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.adb_commands.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.adb_commands.html
new file mode 100644
index 00000000000..7203e4229bb
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.adb_commands.html
@@ -0,0 +1,173 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.adb_commands</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.adb_commands</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/adb_commands.py">telemetry/core/chrome/adb_commands.py</a></font></td></tr></table>
+ <p><tt>Brings&nbsp;in&nbsp;Chrome&nbsp;Android's&nbsp;android_commands&nbsp;module,&nbsp;which&nbsp;itself&nbsp;is&nbsp;a<br>
+thin(ish)&nbsp;wrapper&nbsp;around&nbsp;adb.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="pylib.android_commands.html">pylib.android_commands</a><br>
+<a href="pylib.cmd_helper.html">pylib.cmd_helper</a><br>
+</td><td width="25%" valign=top><a href="pylib.forwarder.html">pylib.forwarder</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="pylib.ports.html">pylib.ports</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="pylib.valgrind_tools.html">pylib.valgrind_tools</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.adb_commands.html#AdbCommands">AdbCommands</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.chrome.adb_commands.html#Forwarder">Forwarder</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="AdbCommands">class <strong>AdbCommands</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;thin&nbsp;wrapper&nbsp;around&nbsp;ADB<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="AdbCommands-Adb"><strong>Adb</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AdbCommands-CloseApplication"><strong>CloseApplication</strong></a>(self, package)</dt><dd><tt>Attempt&nbsp;to&nbsp;close&nbsp;down&nbsp;the&nbsp;application,&nbsp;using&nbsp;increasing&nbsp;violence.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;package:&nbsp;Name&nbsp;of&nbsp;the&nbsp;process&nbsp;to&nbsp;kill&nbsp;off,&nbsp;e.g.<br>
+&nbsp;&nbsp;com.google.android.apps.chrome</tt></dd></dl>
+
+<dl><dt><a name="AdbCommands-ExtractPid"><strong>ExtractPid</strong></a>(self, process_name)</dt><dd><tt>Extracts&nbsp;Process&nbsp;Ids&nbsp;for&nbsp;a&nbsp;given&nbsp;process&nbsp;name&nbsp;from&nbsp;Android&nbsp;Shell.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;process_name:&nbsp;name&nbsp;of&nbsp;the&nbsp;process&nbsp;on&nbsp;the&nbsp;device.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;List&nbsp;of&nbsp;all&nbsp;the&nbsp;process&nbsp;ids&nbsp;(as&nbsp;strings)&nbsp;that&nbsp;match&nbsp;the&nbsp;given&nbsp;name.<br>
+&nbsp;&nbsp;If&nbsp;the&nbsp;name&nbsp;of&nbsp;a&nbsp;process&nbsp;exactly&nbsp;matches&nbsp;the&nbsp;given&nbsp;name,&nbsp;the&nbsp;pid&nbsp;of<br>
+&nbsp;&nbsp;that&nbsp;process&nbsp;will&nbsp;be&nbsp;inserted&nbsp;to&nbsp;the&nbsp;front&nbsp;of&nbsp;the&nbsp;pid&nbsp;list.</tt></dd></dl>
+
+<dl><dt><a name="AdbCommands-FileExistsOnDevice"><strong>FileExistsOnDevice</strong></a>(self, file_name)</dt></dl>
+
+<dl><dt><a name="AdbCommands-Forward"><strong>Forward</strong></a>(self, local, remote)</dt></dl>
+
+<dl><dt><a name="AdbCommands-IsRootEnabled"><strong>IsRootEnabled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AdbCommands-KillAll"><strong>KillAll</strong></a>(self, process)</dt><dd><tt>Android&nbsp;version&nbsp;of&nbsp;killall,&nbsp;connected&nbsp;via&nbsp;adb.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;process:&nbsp;name&nbsp;of&nbsp;the&nbsp;process&nbsp;to&nbsp;kill&nbsp;off<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;the&nbsp;number&nbsp;of&nbsp;processess&nbsp;killed</tt></dd></dl>
+
+<dl><dt><a name="AdbCommands-Pull"><strong>Pull</strong></a>(self, remote, local)</dt></dl>
+
+<dl><dt><a name="AdbCommands-Push"><strong>Push</strong></a>(self, local, remote)</dt></dl>
+
+<dl><dt><a name="AdbCommands-RunShellCommand"><strong>RunShellCommand</strong></a>(self, command, timeout_time<font color="#909090">=20</font>, log_result<font color="#909090">=False</font>)</dt><dd><tt>Send&nbsp;a&nbsp;command&nbsp;to&nbsp;the&nbsp;adb&nbsp;shell&nbsp;and&nbsp;return&nbsp;the&nbsp;result.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;command:&nbsp;String&nbsp;containing&nbsp;the&nbsp;shell&nbsp;command&nbsp;to&nbsp;send.&nbsp;Must&nbsp;not&nbsp;include<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;single&nbsp;quotes&nbsp;as&nbsp;we&nbsp;use&nbsp;them&nbsp;to&nbsp;escape&nbsp;the&nbsp;whole&nbsp;command.<br>
+&nbsp;&nbsp;timeout_time:&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;to&nbsp;wait&nbsp;for&nbsp;command&nbsp;to&nbsp;respond&nbsp;before<br>
+&nbsp;&nbsp;&nbsp;&nbsp;retrying,&nbsp;used&nbsp;by&nbsp;AdbInterface.SendShellCommand.<br>
+&nbsp;&nbsp;log_result:&nbsp;Boolean&nbsp;to&nbsp;indicate&nbsp;whether&nbsp;we&nbsp;should&nbsp;log&nbsp;the&nbsp;result&nbsp;of&nbsp;the<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell&nbsp;command.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;list&nbsp;containing&nbsp;the&nbsp;lines&nbsp;of&nbsp;output&nbsp;received&nbsp;from&nbsp;running&nbsp;the&nbsp;command</tt></dd></dl>
+
+<dl><dt><a name="AdbCommands-StartActivity"><strong>StartActivity</strong></a>(self, package, activity, wait_for_completion<font color="#909090">=False</font>, action<font color="#909090">='android.intent.action.VIEW'</font>, category<font color="#909090">=None</font>, data<font color="#909090">=None</font>, extras<font color="#909090">=None</font>, trace_file_name<font color="#909090">=None</font>)</dt><dd><tt>Starts&nbsp;|package|'s&nbsp;activity&nbsp;on&nbsp;the&nbsp;device.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;package:&nbsp;Name&nbsp;of&nbsp;package&nbsp;to&nbsp;start&nbsp;(e.g.&nbsp;'com.google.android.apps.chrome').<br>
+&nbsp;&nbsp;activity:&nbsp;Name&nbsp;of&nbsp;activity&nbsp;(e.g.&nbsp;'.Main'&nbsp;or<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'com.google.android.apps.chrome.Main').<br>
+&nbsp;&nbsp;wait_for_completion:&nbsp;wait&nbsp;for&nbsp;the&nbsp;activity&nbsp;to&nbsp;finish&nbsp;launching&nbsp;(-W&nbsp;flag).<br>
+&nbsp;&nbsp;action:&nbsp;string&nbsp;(e.g.&nbsp;'android.intent.action.MAIN').&nbsp;Default&nbsp;is&nbsp;VIEW.<br>
+&nbsp;&nbsp;category:&nbsp;string&nbsp;(e.g.&nbsp;'android.intent.category.HOME')<br>
+&nbsp;&nbsp;data:&nbsp;Data&nbsp;string&nbsp;to&nbsp;pass&nbsp;to&nbsp;activity&nbsp;(e.g.&nbsp;'<a href="http://www.example.com/">http://www.example.com/</a>').<br>
+&nbsp;&nbsp;extras:&nbsp;Dict&nbsp;of&nbsp;extras&nbsp;to&nbsp;pass&nbsp;to&nbsp;activity.&nbsp;Values&nbsp;are&nbsp;significant.<br>
+&nbsp;&nbsp;trace_file_name:&nbsp;If&nbsp;used,&nbsp;turns&nbsp;on&nbsp;and&nbsp;saves&nbsp;the&nbsp;trace&nbsp;to&nbsp;this&nbsp;file&nbsp;name.</tt></dd></dl>
+
+<dl><dt><a name="AdbCommands-__init__"><strong>__init__</strong></a>(self, device)</dt></dl>
+
+<dl><dt><a name="AdbCommands-device"><strong>device</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Forwarder">class <strong>Forwarder</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Forwarder-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Forwarder-__init__"><strong>__init__</strong></a>(self, adb, *port_pairs)</dt></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="Forwarder-KillDevice"><strong>KillDevice</strong></a>(adb)</dt></dl>
+
+<dl><dt><a name="Forwarder-KillHost"><strong>KillHost</strong></a>()</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-AllocateTestServerPort"><strong>AllocateTestServerPort</strong></a>()</dt></dl>
+ <dl><dt><a name="-GetAttachedDevices"><strong>GetAttachedDevices</strong></a>()</dt><dd><tt>Returns&nbsp;a&nbsp;list&nbsp;of&nbsp;attached,&nbsp;online&nbsp;android&nbsp;devices.<br>
+&nbsp;<br>
+If&nbsp;a&nbsp;preferred&nbsp;device&nbsp;has&nbsp;been&nbsp;set&nbsp;with&nbsp;ANDROID_SERIAL,&nbsp;it&nbsp;will&nbsp;be&nbsp;first&nbsp;in<br>
+the&nbsp;returned&nbsp;list.</tt></dd></dl>
+ <dl><dt><a name="-GetOutDirectory"><strong>GetOutDirectory</strong></a>()</dt></dl>
+ <dl><dt><a name="-HasForwarder"><strong>HasForwarder</strong></a>(buildtype<font color="#909090">=None</font>)</dt></dl>
+ <dl><dt><a name="-IsAndroidSupported"><strong>IsAndroidSupported</strong></a>()</dt></dl>
+ <dl><dt><a name="-ResetTestServerPortAllocation"><strong>ResetTestServerPortAllocation</strong></a>()</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.android_browser_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.android_browser_backend.html
new file mode 100644
index 00000000000..f1cd499f374
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.android_browser_backend.html
@@ -0,0 +1,318 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.android_browser_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.android_browser_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/android_browser_backend.py">telemetry/core/chrome/android_browser_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.adb_commands.html">telemetry.core.chrome.adb_commands</a><br>
+<a href="telemetry.core.chrome.browser_backend.html">telemetry.core.chrome.browser_backend</a><br>
+<a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="os.html">os</a><br>
+<a href="subprocess.html">subprocess</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="time.html">time</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.android_browser_backend.html#ChromeBackendSettings">ChromeBackendSettings</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.chrome.android_browser_backend.html#ChromiumTestShellBackendSettings">ChromiumTestShellBackendSettings</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.chrome.android_browser_backend.html#ContentShellBackendSettings">ContentShellBackendSettings</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.chrome.android_browser_backend.html#WebviewBackendSettings">WebviewBackendSettings</a>
+</font></dt></dl>
+</dd>
+</dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackend">AndroidBrowserBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="AndroidBrowserBackend">class <strong>AndroidBrowserBackend</strong></a>(<a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>The&nbsp;backend&nbsp;for&nbsp;controlling&nbsp;a&nbsp;browser&nbsp;instance&nbsp;running&nbsp;on&nbsp;Android.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackend">AndroidBrowserBackend</a></dd>
+<dd><a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="AndroidBrowserBackend-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-CreateForwarder"><strong>CreateForwarder</strong></a>(self, *port_pairs)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-GetBrowserStartupArgs"><strong>GetBrowserStartupArgs</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-GetRemotePort"><strong>GetRemotePort</strong></a>(self, local_port)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-GetStackTrace"><strong>GetStackTrace</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-GetStandardOutput"><strong>GetStandardOutput</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-IsBrowserRunning"><strong>IsBrowserRunning</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-__init__"><strong>__init__</strong></a>(self, options, backend_settings)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>adb</strong></dt>
+</dl>
+<dl><dt><strong>pid</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><a name="AndroidBrowserBackend-GetProcessName"><strong>GetProcessName</strong></a>(self, cmd_line)</dt><dd><tt>Returns&nbsp;a&nbsp;user-friendly&nbsp;name&nbsp;for&nbsp;the&nbsp;process&nbsp;of&nbsp;the&nbsp;given&nbsp;|cmd_line|.</tt></dd></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-GetTraceResultAndReset"><strong>GetTraceResultAndReset</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-Request"><strong>Request</strong></a>(self, path, timeout<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-SetBrowser"><strong>SetBrowser</strong></a>(self, browser)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-StartTracing"><strong>StartTracing</strong></a>(self, custom_categories<font color="#909090">=None</font>, timeout<font color="#909090">=60</font>)</dt><dd><tt>custom_categories&nbsp;is&nbsp;an&nbsp;optional&nbsp;string&nbsp;containing&nbsp;a&nbsp;list&nbsp;of<br>
+comma&nbsp;separated&nbsp;categories&nbsp;that&nbsp;will&nbsp;be&nbsp;traced&nbsp;instead&nbsp;of&nbsp;the<br>
+default&nbsp;category&nbsp;set.&nbsp;&nbsp;Example:&nbsp;use<br>
+"webkit,cc,disabled-by-default-cc.debug"&nbsp;to&nbsp;trace&nbsp;only&nbsp;those&nbsp;three<br>
+event&nbsp;categories.</tt></dd></dl>
+
+<dl><dt><a name="AndroidBrowserBackend-StopTracing"><strong>StopTracing</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser</strong></dt>
+</dl>
+<dl><dt><strong>chrome_branch_number</strong></dt>
+</dl>
+<dl><dt><strong>extension_dict_backend</strong></dt>
+</dl>
+<dl><dt><strong>misc_web_contents_backend</strong></dt>
+<dd><tt>Access&nbsp;to&nbsp;chrome://oobe/login&nbsp;page&nbsp;which&nbsp;is&nbsp;neither&nbsp;a&nbsp;tab&nbsp;nor&nbsp;an<br>
+extension.</tt></dd>
+</dl>
+<dl><dt><strong>supports_extensions</strong></dt>
+<dd><tt>True&nbsp;if&nbsp;this&nbsp;browser&nbsp;backend&nbsp;supports&nbsp;extensions.</tt></dd>
+</dl>
+<dl><dt><strong>supports_tab_control</strong></dt>
+</dl>
+<dl><dt><strong>supports_tracing</strong></dt>
+</dl>
+<dl><dt><strong>tab_list_backend</strong></dt>
+</dl>
+<dl><dt><strong>wpr_mode</strong></dt>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><strong>WEBPAGEREPLAY_HOST</strong> = '127.0.0.1'</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="AndroidBrowserBackendSettings">class <strong>AndroidBrowserBackendSettings</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="AndroidBrowserBackendSettings-GetDevtoolsRemotePort"><strong>GetDevtoolsRemotePort</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackendSettings-PushProfile"><strong>PushProfile</strong></a>(self, _)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackendSettings-RemoveProfile"><strong>RemoveProfile</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidBrowserBackendSettings-__init__"><strong>__init__</strong></a>(self, adb, activity, cmdline_file, package, pseudo_exec_name)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>is_content_shell</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ChromeBackendSettings">class <strong>ChromeBackendSettings</strong></a>(<a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#ChromeBackendSettings">ChromeBackendSettings</a></dd>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ChromeBackendSettings-GetDevtoolsRemotePort"><strong>GetDevtoolsRemotePort</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ChromeBackendSettings-PushProfile"><strong>PushProfile</strong></a>(self, new_profile_dir)</dt></dl>
+
+<dl><dt><a name="ChromeBackendSettings-__init__"><strong>__init__</strong></a>(self, adb, package)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>:<br>
+<dl><dt><a name="ChromeBackendSettings-RemoveProfile"><strong>RemoveProfile</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>is_content_shell</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ChromiumTestShellBackendSettings">class <strong>ChromiumTestShellBackendSettings</strong></a>(<a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#ChromiumTestShellBackendSettings">ChromiumTestShellBackendSettings</a></dd>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ChromiumTestShellBackendSettings-GetDevtoolsRemotePort"><strong>GetDevtoolsRemotePort</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ChromiumTestShellBackendSettings-__init__"><strong>__init__</strong></a>(self, adb, package)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>is_content_shell</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>:<br>
+<dl><dt><a name="ChromiumTestShellBackendSettings-PushProfile"><strong>PushProfile</strong></a>(self, _)</dt></dl>
+
+<dl><dt><a name="ChromiumTestShellBackendSettings-RemoveProfile"><strong>RemoveProfile</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ContentShellBackendSettings">class <strong>ContentShellBackendSettings</strong></a>(<a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#ContentShellBackendSettings">ContentShellBackendSettings</a></dd>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ContentShellBackendSettings-GetDevtoolsRemotePort"><strong>GetDevtoolsRemotePort</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ContentShellBackendSettings-__init__"><strong>__init__</strong></a>(self, adb, package)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>is_content_shell</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>:<br>
+<dl><dt><a name="ContentShellBackendSettings-PushProfile"><strong>PushProfile</strong></a>(self, _)</dt></dl>
+
+<dl><dt><a name="ContentShellBackendSettings-RemoveProfile"><strong>RemoveProfile</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="WebviewBackendSettings">class <strong>WebviewBackendSettings</strong></a>(<a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#WebviewBackendSettings">WebviewBackendSettings</a></dd>
+<dd><a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="WebviewBackendSettings-GetDevtoolsRemotePort"><strong>GetDevtoolsRemotePort</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WebviewBackendSettings-__init__"><strong>__init__</strong></a>(self, adb, package)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>:<br>
+<dl><dt><a name="WebviewBackendSettings-PushProfile"><strong>PushProfile</strong></a>(self, _)</dt></dl>
+
+<dl><dt><a name="WebviewBackendSettings-RemoveProfile"><strong>RemoveProfile</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.android_browser_backend.html#AndroidBrowserBackendSettings">AndroidBrowserBackendSettings</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>is_content_shell</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.android_browser_finder.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.android_browser_finder.html
new file mode 100644
index 00000000000..188c5a8e23f
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.android_browser_finder.html
@@ -0,0 +1,102 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.android_browser_finder</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.android_browser_finder</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/android_browser_finder.py">telemetry/core/chrome/android_browser_finder.py</a></font></td></tr></table>
+ <p><tt>Finds&nbsp;android&nbsp;browsers&nbsp;that&nbsp;can&nbsp;be&nbsp;controlled&nbsp;by&nbsp;telemetry.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.adb_commands.html">telemetry.core.chrome.adb_commands</a><br>
+<a href="telemetry.core.chrome.android_browser_backend.html">telemetry.core.chrome.android_browser_backend</a><br>
+<a href="telemetry.core.platform.android_platform_backend.html">telemetry.core.platform.android_platform_backend</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.browser.html">telemetry.core.browser</a><br>
+<a href="os.html">os</a><br>
+<a href="telemetry.core.possible_browser.html">telemetry.core.possible_browser</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.profile_types.html">telemetry.core.profile_types</a><br>
+<a href="re.html">re</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="subprocess.html">subprocess</a><br>
+<a href="sys.html">sys</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.android_browser_finder.html#PossibleAndroidBrowser">PossibleAndroidBrowser</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PossibleAndroidBrowser">class <strong>PossibleAndroidBrowser</strong></a>(<a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;launchable&nbsp;android&nbsp;browser&nbsp;instance.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.android_browser_finder.html#PossibleAndroidBrowser">PossibleAndroidBrowser</a></dd>
+<dd><a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PossibleAndroidBrowser-Create"><strong>Create</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PossibleAndroidBrowser-SupportsOptions"><strong>SupportsOptions</strong></a>(self, options)</dt></dl>
+
+<dl><dt><a name="PossibleAndroidBrowser-__init__"><strong>__init__</strong></a>(self, browser_type, options, backend_settings)</dt></dl>
+
+<dl><dt><a name="PossibleAndroidBrowser-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser_type</strong></dt>
+</dl>
+<dl><dt><strong>options</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-FindAllAvailableBrowsers"><strong>FindAllAvailableBrowsers</strong></a>(options, logging<font color="#909090">=&lt;module 'logging' from '/System/Library/Framewor...Versions/2.7/lib/python2.7/logging/__init__.pyc'&gt;</font>)</dt><dd><tt>Finds&nbsp;all&nbsp;the&nbsp;desktop&nbsp;browsers&nbsp;available&nbsp;on&nbsp;this&nbsp;machine.</tt></dd></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>ALL_BROWSER_TYPES</strong> = 'android-chromium-testshell,android-content-shell...hrome,android-chrome-dev,android-jb-system-chrome'<br>
+<strong>CHROME_PACKAGE_NAMES</strong> = {'android-chrome': 'com.google.android.apps.chrome', 'android-chrome-beta': 'com.chrome.beta', 'android-chrome-dev': 'com.google.android.apps.chrome_dev', 'android-jb-system-chrome': 'com.android.chrome'}<br>
+<strong>CHROMIUM_TESTSHELL_PACKAGE</strong> = 'org.chromium.chrome.testshell'<br>
+<strong>CONTENT_SHELL_PACKAGE</strong> = 'org.chromium.content_shell_apk'<br>
+<strong>WEBVIEW_PACKAGE</strong> = 'com.android.webview.chromium.shell'</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.browser_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.browser_backend.html
new file mode 100644
index 00000000000..0dc487980f2
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.browser_backend.html
@@ -0,0 +1,218 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.browser_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.browser_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/browser_backend.py">telemetry/core/chrome/browser_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+<a href="telemetry.core.chrome.extension_dict_backend.html">telemetry.core.chrome.extension_dict_backend</a><br>
+<a href="httplib.html">httplib</a><br>
+<a href="json.html">json</a><br>
+<a href="telemetry.core.chrome.misc_web_contents_backend.html">telemetry.core.chrome.misc_web_contents_backend</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.options_for_unittests.html">telemetry.unittest.options_for_unittests</a><br>
+<a href="re.html">re</a><br>
+<a href="socket.html">socket</a><br>
+<a href="sys.html">sys</a><br>
+<a href="telemetry.core.chrome.tab_list_backend.html">telemetry.core.chrome.tab_list_backend</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.tracing_backend.html">telemetry.core.chrome.tracing_backend</a><br>
+<a href="urllib2.html">urllib2</a><br>
+<a href="telemetry.core.user_agent.html">telemetry.core.user_agent</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+<a href="telemetry.core.web_contents.html">telemetry.core.web_contents</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.wpr_modes.html">telemetry.core.wpr_modes</a><br>
+<a href="telemetry.core.wpr_server.html">telemetry.core.wpr_server</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">BrowserBackend</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.chrome.browser_backend.html#DoNothingForwarder">DoNothingForwarder</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.browser_backend.html#ExtensionsNotSupportedException">ExtensionsNotSupportedException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BrowserBackend">class <strong>BrowserBackend</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;base&nbsp;class&nbsp;for&nbsp;browser&nbsp;backends.&nbsp;Provides&nbsp;basic&nbsp;functionality<br>
+once&nbsp;a&nbsp;remote-debugger&nbsp;port&nbsp;has&nbsp;been&nbsp;established.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="BrowserBackend-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-CreateForwarder"><strong>CreateForwarder</strong></a>(self, *port_pairs)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-GetBrowserStartupArgs"><strong>GetBrowserStartupArgs</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-GetProcessName"><strong>GetProcessName</strong></a>(self, cmd_line)</dt><dd><tt>Returns&nbsp;a&nbsp;user-friendly&nbsp;name&nbsp;for&nbsp;the&nbsp;process&nbsp;of&nbsp;the&nbsp;given&nbsp;|cmd_line|.</tt></dd></dl>
+
+<dl><dt><a name="BrowserBackend-GetRemotePort"><strong>GetRemotePort</strong></a>(self, _)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-GetStackTrace"><strong>GetStackTrace</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-GetStandardOutput"><strong>GetStandardOutput</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-GetTraceResultAndReset"><strong>GetTraceResultAndReset</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-IsBrowserRunning"><strong>IsBrowserRunning</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-Request"><strong>Request</strong></a>(self, path, timeout<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-SetBrowser"><strong>SetBrowser</strong></a>(self, browser)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-StartTracing"><strong>StartTracing</strong></a>(self, custom_categories<font color="#909090">=None</font>, timeout<font color="#909090">=60</font>)</dt><dd><tt>custom_categories&nbsp;is&nbsp;an&nbsp;optional&nbsp;string&nbsp;containing&nbsp;a&nbsp;list&nbsp;of<br>
+comma&nbsp;separated&nbsp;categories&nbsp;that&nbsp;will&nbsp;be&nbsp;traced&nbsp;instead&nbsp;of&nbsp;the<br>
+default&nbsp;category&nbsp;set.&nbsp;&nbsp;Example:&nbsp;use<br>
+"webkit,cc,disabled-by-default-cc.debug"&nbsp;to&nbsp;trace&nbsp;only&nbsp;those&nbsp;three<br>
+event&nbsp;categories.</tt></dd></dl>
+
+<dl><dt><a name="BrowserBackend-StopTracing"><strong>StopTracing</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserBackend-__init__"><strong>__init__</strong></a>(self, is_content_shell, supports_extensions, options)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser</strong></dt>
+</dl>
+<dl><dt><strong>chrome_branch_number</strong></dt>
+</dl>
+<dl><dt><strong>extension_dict_backend</strong></dt>
+</dl>
+<dl><dt><strong>misc_web_contents_backend</strong></dt>
+<dd><tt>Access&nbsp;to&nbsp;chrome://oobe/login&nbsp;page&nbsp;which&nbsp;is&nbsp;neither&nbsp;a&nbsp;tab&nbsp;nor&nbsp;an<br>
+extension.</tt></dd>
+</dl>
+<dl><dt><strong>supports_extensions</strong></dt>
+<dd><tt>True&nbsp;if&nbsp;this&nbsp;browser&nbsp;backend&nbsp;supports&nbsp;extensions.</tt></dd>
+</dl>
+<dl><dt><strong>supports_tab_control</strong></dt>
+</dl>
+<dl><dt><strong>supports_tracing</strong></dt>
+</dl>
+<dl><dt><strong>tab_list_backend</strong></dt>
+</dl>
+<dl><dt><strong>wpr_mode</strong></dt>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>WEBPAGEREPLAY_HOST</strong> = '127.0.0.1'</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="DoNothingForwarder">class <strong>DoNothingForwarder</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="DoNothingForwarder-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DoNothingForwarder-__init__"><strong>__init__</strong></a>(self, *port_pairs)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ExtensionsNotSupportedException">class <strong>ExtensionsNotSupportedException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.browser_backend.html#ExtensionsNotSupportedException">ExtensionsNotSupportedException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="ExtensionsNotSupportedException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionsNotSupportedException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#ExtensionsNotSupportedException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="ExtensionsNotSupportedException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionsNotSupportedException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionsNotSupportedException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionsNotSupportedException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionsNotSupportedException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionsNotSupportedException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionsNotSupportedException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionsNotSupportedException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="ExtensionsNotSupportedException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_browser_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_browser_backend.html
new file mode 100644
index 00000000000..77f729c9501
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_browser_backend.html
@@ -0,0 +1,177 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.cros_browser_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.cros_browser_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/cros_browser_backend.py">telemetry/core/chrome/cros_browser_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.browser_backend.html">telemetry.core.chrome.browser_backend</a><br>
+<a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="subprocess.html">subprocess</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.cros_browser_backend.html#SSHForwarder">SSHForwarder</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.cros_browser_backend.html#CrOSBrowserBackend">CrOSBrowserBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="CrOSBrowserBackend">class <strong>CrOSBrowserBackend</strong></a>(<a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.cros_browser_backend.html#CrOSBrowserBackend">CrOSBrowserBackend</a></dd>
+<dd><a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="CrOSBrowserBackend-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-CreateForwarder"><strong>CreateForwarder</strong></a>(self, *port_pairs)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-GetBrowserStartupArgs"><strong>GetBrowserStartupArgs</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-GetRemotePort"><strong>GetRemotePort</strong></a>(self, _)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-GetStackTrace"><strong>GetStackTrace</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-GetStandardOutput"><strong>GetStandardOutput</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-IsBrowserRunning"><strong>IsBrowserRunning</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-__init__"><strong>__init__</strong></a>(self, browser_type, options, cri, is_guest)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>hwid</strong></dt>
+</dl>
+<dl><dt><strong>oobe</strong></dt>
+</dl>
+<dl><dt><strong>pid</strong></dt>
+<dd><tt>Locates&nbsp;the&nbsp;pid&nbsp;of&nbsp;the&nbsp;main&nbsp;chrome&nbsp;browser&nbsp;process.<br>
+&nbsp;<br>
+Chrome&nbsp;on&nbsp;cros&nbsp;is&nbsp;usually&nbsp;in&nbsp;/opt/google/chrome,&nbsp;but&nbsp;could&nbsp;be&nbsp;in<br>
+/usr/local/&nbsp;for&nbsp;developer&nbsp;workflows&nbsp;-&nbsp;debug&nbsp;chrome&nbsp;is&nbsp;too&nbsp;large&nbsp;to&nbsp;fit&nbsp;on<br>
+rootfs.<br>
+&nbsp;<br>
+Chrome&nbsp;spawns&nbsp;multiple&nbsp;processes&nbsp;for&nbsp;renderers.&nbsp;pids&nbsp;wrap&nbsp;around&nbsp;after&nbsp;they<br>
+are&nbsp;exhausted&nbsp;so&nbsp;looking&nbsp;for&nbsp;the&nbsp;smallest&nbsp;pid&nbsp;is&nbsp;not&nbsp;always&nbsp;correct.&nbsp;We<br>
+locate&nbsp;the&nbsp;session_manager's&nbsp;pid,&nbsp;and&nbsp;look&nbsp;for&nbsp;the&nbsp;chrome&nbsp;process&nbsp;that's&nbsp;an<br>
+immediate&nbsp;child.&nbsp;This&nbsp;is&nbsp;the&nbsp;main&nbsp;browser&nbsp;process.</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>CHROME_PATHS</strong> = ['/opt/google/chrome/chrome ', '/usr/local/opt/google/chrome/chrome ']</dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><a name="CrOSBrowserBackend-GetProcessName"><strong>GetProcessName</strong></a>(self, cmd_line)</dt><dd><tt>Returns&nbsp;a&nbsp;user-friendly&nbsp;name&nbsp;for&nbsp;the&nbsp;process&nbsp;of&nbsp;the&nbsp;given&nbsp;|cmd_line|.</tt></dd></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-GetTraceResultAndReset"><strong>GetTraceResultAndReset</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-Request"><strong>Request</strong></a>(self, path, timeout<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-SetBrowser"><strong>SetBrowser</strong></a>(self, browser)</dt></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-StartTracing"><strong>StartTracing</strong></a>(self, custom_categories<font color="#909090">=None</font>, timeout<font color="#909090">=60</font>)</dt><dd><tt>custom_categories&nbsp;is&nbsp;an&nbsp;optional&nbsp;string&nbsp;containing&nbsp;a&nbsp;list&nbsp;of<br>
+comma&nbsp;separated&nbsp;categories&nbsp;that&nbsp;will&nbsp;be&nbsp;traced&nbsp;instead&nbsp;of&nbsp;the<br>
+default&nbsp;category&nbsp;set.&nbsp;&nbsp;Example:&nbsp;use<br>
+"webkit,cc,disabled-by-default-cc.debug"&nbsp;to&nbsp;trace&nbsp;only&nbsp;those&nbsp;three<br>
+event&nbsp;categories.</tt></dd></dl>
+
+<dl><dt><a name="CrOSBrowserBackend-StopTracing"><strong>StopTracing</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser</strong></dt>
+</dl>
+<dl><dt><strong>chrome_branch_number</strong></dt>
+</dl>
+<dl><dt><strong>extension_dict_backend</strong></dt>
+</dl>
+<dl><dt><strong>misc_web_contents_backend</strong></dt>
+<dd><tt>Access&nbsp;to&nbsp;chrome://oobe/login&nbsp;page&nbsp;which&nbsp;is&nbsp;neither&nbsp;a&nbsp;tab&nbsp;nor&nbsp;an<br>
+extension.</tt></dd>
+</dl>
+<dl><dt><strong>supports_extensions</strong></dt>
+<dd><tt>True&nbsp;if&nbsp;this&nbsp;browser&nbsp;backend&nbsp;supports&nbsp;extensions.</tt></dd>
+</dl>
+<dl><dt><strong>supports_tab_control</strong></dt>
+</dl>
+<dl><dt><strong>supports_tracing</strong></dt>
+</dl>
+<dl><dt><strong>tab_list_backend</strong></dt>
+</dl>
+<dl><dt><strong>wpr_mode</strong></dt>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><strong>WEBPAGEREPLAY_HOST</strong> = '127.0.0.1'</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="SSHForwarder">class <strong>SSHForwarder</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="SSHForwarder-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="SSHForwarder-__init__"><strong>__init__</strong></a>(self, cri, forwarding_flag, *port_pairs)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_browser_finder.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_browser_finder.html
new file mode 100644
index 00000000000..6533776ce8d
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_browser_finder.html
@@ -0,0 +1,94 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.cros_browser_finder</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.cros_browser_finder</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/cros_browser_finder.py">telemetry/core/chrome/cros_browser_finder.py</a></font></td></tr></table>
+ <p><tt>Finds&nbsp;CrOS&nbsp;browsers&nbsp;that&nbsp;can&nbsp;be&nbsp;controlled&nbsp;by&nbsp;telemetry.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser.html">telemetry.core.browser</a><br>
+<a href="telemetry.core.chrome.cros_browser_backend.html">telemetry.core.chrome.cros_browser_backend</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.cros_interface.html">telemetry.core.chrome.cros_interface</a><br>
+<a href="telemetry.core.platform.cros_platform_backend.html">telemetry.core.platform.cros_platform_backend</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="telemetry.core.possible_browser.html">telemetry.core.possible_browser</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.profile_types.html">telemetry.core.profile_types</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.cros_browser_finder.html#PossibleCrOSBrowser">PossibleCrOSBrowser</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PossibleCrOSBrowser">class <strong>PossibleCrOSBrowser</strong></a>(<a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;launchable&nbsp;chromeos&nbsp;browser&nbsp;instance.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.cros_browser_finder.html#PossibleCrOSBrowser">PossibleCrOSBrowser</a></dd>
+<dd><a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PossibleCrOSBrowser-Create"><strong>Create</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PossibleCrOSBrowser-SupportsOptions"><strong>SupportsOptions</strong></a>(self, options)</dt></dl>
+
+<dl><dt><a name="PossibleCrOSBrowser-__init__"><strong>__init__</strong></a>(self, browser_type, options, cri, is_guest)</dt></dl>
+
+<dl><dt><a name="PossibleCrOSBrowser-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser_type</strong></dt>
+</dl>
+<dl><dt><strong>options</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-FindAllAvailableBrowsers"><strong>FindAllAvailableBrowsers</strong></a>(options)</dt><dd><tt>Finds&nbsp;all&nbsp;available&nbsp;chromeos&nbsp;browsers,&nbsp;locally&nbsp;and&nbsp;remotely.</tt></dd></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>ALL_BROWSER_TYPES</strong> = 'cros-chrome,cros-chrome-guest,system-guest'</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_interface.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_interface.html
new file mode 100644
index 00000000000..205da414753
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.cros_interface.html
@@ -0,0 +1,250 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.cros_interface</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.cros_interface</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/cros_interface.py">telemetry/core/chrome/cros_interface.py</a></font></td></tr></table>
+ <p><tt>A&nbsp;wrapper&nbsp;around&nbsp;ssh&nbsp;for&nbsp;common&nbsp;operations&nbsp;on&nbsp;a&nbsp;CrOS-based&nbsp;device</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="re.html">re</a><br>
+<a href="subprocess.html">subprocess</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="tempfile.html">tempfile</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.cros_interface.html#CrOSInterface">CrOSInterface</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.cros_interface.html#LoginException">LoginException</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.cros_interface.html#KeylessLoginRequiredException">KeylessLoginRequiredException</a>
+</font></dt></dl>
+</dd>
+</dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="CrOSInterface">class <strong>CrOSInterface</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="CrOSInterface-FileExistsOnDevice"><strong>FileExistsOnDevice</strong></a>(self, file_name, quiet<font color="#909090">=False</font>)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-FilesystemMountedAt"><strong>FilesystemMountedAt</strong></a>(self, path)</dt><dd><tt>Returns&nbsp;the&nbsp;filesystem&nbsp;mounted&nbsp;at&nbsp;|path|</tt></dd></dl>
+
+<dl><dt><a name="CrOSInterface-FormSSHCommandLine"><strong>FormSSHCommandLine</strong></a>(self, args, extra_ssh_args<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-GetFileContents"><strong>GetFileContents</strong></a>(self, filename)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-GetRemotePort"><strong>GetRemotePort</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-IsHTTPServerRunningOnPort"><strong>IsHTTPServerRunningOnPort</strong></a>(self, port)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-IsServiceRunning"><strong>IsServiceRunning</strong></a>(self, service_name)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-KillAllMatching"><strong>KillAllMatching</strong></a>(self, predicate)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-ListProcesses"><strong>ListProcesses</strong></a>(self)</dt><dd><tt>Returns&nbsp;a&nbsp;tuple&nbsp;(pid,&nbsp;cmd,&nbsp;ppid)&nbsp;of&nbsp;all&nbsp;processes&nbsp;on&nbsp;the&nbsp;device.</tt></dd></dl>
+
+<dl><dt><a name="CrOSInterface-PushContents"><strong>PushContents</strong></a>(self, text, remote_filename)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-PushFile"><strong>PushFile</strong></a>(self, filename, remote_filename)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-RmRF"><strong>RmRF</strong></a>(self, filename)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-RunCmdOnDevice"><strong>RunCmdOnDevice</strong></a>(self, args, cwd<font color="#909090">=None</font>, quiet<font color="#909090">=False</font>)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-TryLogin"><strong>TryLogin</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrOSInterface-__init__"><strong>__init__</strong></a>(self, hostname<font color="#909090">=None</font>, ssh_identity<font color="#909090">=None</font>)</dt><dd><tt>#&nbsp;pylint:&nbsp;disable=R0923</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>hostname</strong></dt>
+</dl>
+<dl><dt><strong>local</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="KeylessLoginRequiredException">class <strong>KeylessLoginRequiredException</strong></a>(<a href="telemetry.core.chrome.cros_interface.html#LoginException">LoginException</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.cros_interface.html#KeylessLoginRequiredException">KeylessLoginRequiredException</a></dd>
+<dd><a href="telemetry.core.chrome.cros_interface.html#LoginException">LoginException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.cros_interface.html#LoginException">LoginException</a>:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="KeylessLoginRequiredException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#KeylessLoginRequiredException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#KeylessLoginRequiredException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="KeylessLoginRequiredException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#KeylessLoginRequiredException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#KeylessLoginRequiredException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#KeylessLoginRequiredException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#KeylessLoginRequiredException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#KeylessLoginRequiredException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#KeylessLoginRequiredException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#KeylessLoginRequiredException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="KeylessLoginRequiredException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="LoginException">class <strong>LoginException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.cros_interface.html#LoginException">LoginException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="LoginException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#LoginException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="LoginException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="LoginException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="LoginException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-GetAllCmdOutput"><strong>GetAllCmdOutput</strong></a>(args, cwd<font color="#909090">=None</font>, quiet<font color="#909090">=False</font>)</dt><dd><tt>Open&nbsp;a&nbsp;subprocess&nbsp;to&nbsp;execute&nbsp;a&nbsp;program&nbsp;and&nbsp;returns&nbsp;its&nbsp;output.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;args:&nbsp;A&nbsp;string&nbsp;or&nbsp;a&nbsp;sequence&nbsp;of&nbsp;program&nbsp;arguments.&nbsp;The&nbsp;program&nbsp;to&nbsp;execute&nbsp;is<br>
+&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;string&nbsp;or&nbsp;the&nbsp;first&nbsp;item&nbsp;in&nbsp;the&nbsp;args&nbsp;sequence.<br>
+&nbsp;&nbsp;cwd:&nbsp;If&nbsp;not&nbsp;None,&nbsp;the&nbsp;subprocess's&nbsp;current&nbsp;directory&nbsp;will&nbsp;be&nbsp;changed&nbsp;to<br>
+&nbsp;&nbsp;&nbsp;&nbsp;|cwd|&nbsp;before&nbsp;it's&nbsp;executed.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;Captures&nbsp;and&nbsp;returns&nbsp;the&nbsp;command's&nbsp;stdout.<br>
+&nbsp;&nbsp;Prints&nbsp;the&nbsp;command's&nbsp;stderr&nbsp;to&nbsp;logger&nbsp;(which&nbsp;defaults&nbsp;to&nbsp;stdout).</tt></dd></dl>
+ <dl><dt><a name="-HasSSH"><strong>HasSSH</strong></a>()</dt></dl>
+ <dl><dt><a name="-IsRunningOnCrosDevice"><strong>IsRunningOnCrosDevice</strong></a>()</dt><dd><tt>Returns&nbsp;True&nbsp;if&nbsp;we're&nbsp;on&nbsp;a&nbsp;ChromeOS&nbsp;device.</tt></dd></dl>
+ <dl><dt><a name="-RunCmd"><strong>RunCmd</strong></a>(args, cwd<font color="#909090">=None</font>, quiet<font color="#909090">=False</font>)</dt><dd><tt>Opens&nbsp;a&nbsp;subprocess&nbsp;to&nbsp;execute&nbsp;a&nbsp;program&nbsp;and&nbsp;returns&nbsp;its&nbsp;return&nbsp;value.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;args:&nbsp;A&nbsp;string&nbsp;or&nbsp;a&nbsp;sequence&nbsp;of&nbsp;program&nbsp;arguments.&nbsp;The&nbsp;program&nbsp;to&nbsp;execute&nbsp;is<br>
+&nbsp;&nbsp;&nbsp;&nbsp;the&nbsp;string&nbsp;or&nbsp;the&nbsp;first&nbsp;item&nbsp;in&nbsp;the&nbsp;args&nbsp;sequence.<br>
+&nbsp;&nbsp;cwd:&nbsp;If&nbsp;not&nbsp;None,&nbsp;the&nbsp;subprocess's&nbsp;current&nbsp;directory&nbsp;will&nbsp;be&nbsp;changed&nbsp;to<br>
+&nbsp;&nbsp;&nbsp;&nbsp;|cwd|&nbsp;before&nbsp;it's&nbsp;executed.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;Return&nbsp;code&nbsp;from&nbsp;the&nbsp;command&nbsp;execution.</tt></dd></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.crx_id.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.crx_id.html
new file mode 100644
index 00000000000..f32c030779e
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.crx_id.html
@@ -0,0 +1,41 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.crx_id</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.crx_id</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/crx_id.py">telemetry/core/chrome/crx_id.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="crx_id.crx_id.html">crx_id.crx_id</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-__init__"><strong>__init__</strong></a>()</dt></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>absolute_import</strong> = _Feature((2, 5, 0, 'alpha', 1), (2, 7, 0, 'alpha', 0), 16384)</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.desktop_browser_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.desktop_browser_backend.html
new file mode 100644
index 00000000000..5f2b6ae409f
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.desktop_browser_backend.html
@@ -0,0 +1,140 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.desktop_browser_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.desktop_browser_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/desktop_browser_backend.py">telemetry/core/chrome/desktop_browser_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.browser_backend.html">telemetry.core.chrome.browser_backend</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="shutil.html">shutil</a><br>
+</td><td width="25%" valign=top><a href="subprocess.html">subprocess</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="tempfile.html">tempfile</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.desktop_browser_backend.html#DesktopBrowserBackend">DesktopBrowserBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="DesktopBrowserBackend">class <strong>DesktopBrowserBackend</strong></a>(<a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>The&nbsp;backend&nbsp;for&nbsp;controlling&nbsp;a&nbsp;locally-executed&nbsp;browser&nbsp;instance,&nbsp;on&nbsp;Linux,<br>
+Mac&nbsp;or&nbsp;Windows.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.desktop_browser_backend.html#DesktopBrowserBackend">DesktopBrowserBackend</a></dd>
+<dd><a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="DesktopBrowserBackend-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-CreateForwarder"><strong>CreateForwarder</strong></a>(self, *port_pairs)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-GetBrowserStartupArgs"><strong>GetBrowserStartupArgs</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-GetStackTrace"><strong>GetStackTrace</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-GetStandardOutput"><strong>GetStandardOutput</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-IsBrowserRunning"><strong>IsBrowserRunning</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-SetProfileDirectory"><strong>SetProfileDirectory</strong></a>(self, profile_dir)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-__init__"><strong>__init__</strong></a>(self, options, executable, flash_path, is_content_shell, delete_profile_dir_after_run<font color="#909090">=True</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>pid</strong></dt>
+</dl>
+<dl><dt><strong>profile_directory</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><a name="DesktopBrowserBackend-GetProcessName"><strong>GetProcessName</strong></a>(self, cmd_line)</dt><dd><tt>Returns&nbsp;a&nbsp;user-friendly&nbsp;name&nbsp;for&nbsp;the&nbsp;process&nbsp;of&nbsp;the&nbsp;given&nbsp;|cmd_line|.</tt></dd></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-GetRemotePort"><strong>GetRemotePort</strong></a>(self, _)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-GetTraceResultAndReset"><strong>GetTraceResultAndReset</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-Request"><strong>Request</strong></a>(self, path, timeout<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-SetBrowser"><strong>SetBrowser</strong></a>(self, browser)</dt></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-StartTracing"><strong>StartTracing</strong></a>(self, custom_categories<font color="#909090">=None</font>, timeout<font color="#909090">=60</font>)</dt><dd><tt>custom_categories&nbsp;is&nbsp;an&nbsp;optional&nbsp;string&nbsp;containing&nbsp;a&nbsp;list&nbsp;of<br>
+comma&nbsp;separated&nbsp;categories&nbsp;that&nbsp;will&nbsp;be&nbsp;traced&nbsp;instead&nbsp;of&nbsp;the<br>
+default&nbsp;category&nbsp;set.&nbsp;&nbsp;Example:&nbsp;use<br>
+"webkit,cc,disabled-by-default-cc.debug"&nbsp;to&nbsp;trace&nbsp;only&nbsp;those&nbsp;three<br>
+event&nbsp;categories.</tt></dd></dl>
+
+<dl><dt><a name="DesktopBrowserBackend-StopTracing"><strong>StopTracing</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser</strong></dt>
+</dl>
+<dl><dt><strong>chrome_branch_number</strong></dt>
+</dl>
+<dl><dt><strong>extension_dict_backend</strong></dt>
+</dl>
+<dl><dt><strong>misc_web_contents_backend</strong></dt>
+<dd><tt>Access&nbsp;to&nbsp;chrome://oobe/login&nbsp;page&nbsp;which&nbsp;is&nbsp;neither&nbsp;a&nbsp;tab&nbsp;nor&nbsp;an<br>
+extension.</tt></dd>
+</dl>
+<dl><dt><strong>supports_extensions</strong></dt>
+<dd><tt>True&nbsp;if&nbsp;this&nbsp;browser&nbsp;backend&nbsp;supports&nbsp;extensions.</tt></dd>
+</dl>
+<dl><dt><strong>supports_tab_control</strong></dt>
+</dl>
+<dl><dt><strong>supports_tracing</strong></dt>
+</dl>
+<dl><dt><strong>tab_list_backend</strong></dt>
+</dl>
+<dl><dt><strong>wpr_mode</strong></dt>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="telemetry.core.chrome.browser_backend.html#BrowserBackend">telemetry.core.chrome.browser_backend.BrowserBackend</a>:<br>
+<dl><dt><strong>WEBPAGEREPLAY_HOST</strong> = '127.0.0.1'</dl>
+
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.desktop_browser_finder.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.desktop_browser_finder.html
new file mode 100644
index 00000000000..a7a62d7f64a
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.desktop_browser_finder.html
@@ -0,0 +1,100 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.desktop_browser_finder</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.desktop_browser_finder</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/desktop_browser_finder.py">telemetry/core/chrome/desktop_browser_finder.py</a></font></td></tr></table>
+ <p><tt>Finds&nbsp;desktop&nbsp;browsers&nbsp;that&nbsp;can&nbsp;be&nbsp;controlled&nbsp;by&nbsp;telemetry.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser.html">telemetry.core.browser</a><br>
+<a href="telemetry.core.chrome.cros_interface.html">telemetry.core.chrome.cros_interface</a><br>
+<a href="telemetry.core.chrome.desktop_browser_backend.html">telemetry.core.chrome.desktop_browser_backend</a><br>
+<a href="telemetry.core.platform.linux_platform_backend.html">telemetry.core.platform.linux_platform_backend</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="telemetry.core.platform.mac_platform_backend.html">telemetry.core.platform.mac_platform_backend</a><br>
+<a href="os.html">os</a><br>
+<a href="platform.html">platform</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.possible_browser.html">telemetry.core.possible_browser</a><br>
+<a href="telemetry.core.profile_types.html">telemetry.core.profile_types</a><br>
+<a href="subprocess.html">subprocess</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.win_platform_backend.html">telemetry.core.platform.win_platform_backend</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.desktop_browser_finder.html#PossibleDesktopBrowser">PossibleDesktopBrowser</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PossibleDesktopBrowser">class <strong>PossibleDesktopBrowser</strong></a>(<a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;desktop&nbsp;browser&nbsp;that&nbsp;can&nbsp;be&nbsp;controlled.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.desktop_browser_finder.html#PossibleDesktopBrowser">PossibleDesktopBrowser</a></dd>
+<dd><a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PossibleDesktopBrowser-Create"><strong>Create</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PossibleDesktopBrowser-SupportsOptions"><strong>SupportsOptions</strong></a>(self, options)</dt></dl>
+
+<dl><dt><a name="PossibleDesktopBrowser-__init__"><strong>__init__</strong></a>(self, browser_type, options, executable, flash_path, is_content_shell)</dt></dl>
+
+<dl><dt><a name="PossibleDesktopBrowser-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.possible_browser.html#PossibleBrowser">telemetry.core.possible_browser.PossibleBrowser</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser_type</strong></dt>
+</dl>
+<dl><dt><strong>options</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-FindAllAvailableBrowsers"><strong>FindAllAvailableBrowsers</strong></a>(options)</dt><dd><tt>Finds&nbsp;all&nbsp;the&nbsp;desktop&nbsp;browsers&nbsp;available&nbsp;on&nbsp;this&nbsp;machine.</tt></dd></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>ALL_BROWSER_TYPES</strong> = 'exact,release,debug,canary,content-shell-debug,content-shell-release,system'</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.extension_dict_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.extension_dict_backend.html
new file mode 100644
index 00000000000..9dfe2f2ab75
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.extension_dict_backend.html
@@ -0,0 +1,133 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.extension_dict_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.extension_dict_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/extension_dict_backend.py">telemetry/core/chrome/extension_dict_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+<a href="telemetry.core.extension_page.html">telemetry.core.extension_page</a><br>
+<a href="httplib.html">httplib</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.inspector_backend.html">telemetry.core.chrome.inspector_backend</a><br>
+<a href="json.html">json</a><br>
+<a href="re.html">re</a><br>
+</td><td width="25%" valign=top><a href="socket.html">socket</a><br>
+<a href="urllib2.html">urllib2</a><br>
+<a href="weakref.html">weakref</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.extension_dict_backend.html#ExtensionDictBackend">ExtensionDictBackend</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.extension_dict_backend.html#ExtensionNotFoundException">ExtensionNotFoundException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ExtensionDictBackend">class <strong>ExtensionDictBackend</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="ExtensionDictBackend-__contains__"><strong>__contains__</strong></a>(self, extension_id)</dt></dl>
+
+<dl><dt><a name="ExtensionDictBackend-__getitem__"><strong>__getitem__</strong></a>(self, extension_id)</dt></dl>
+
+<dl><dt><a name="ExtensionDictBackend-__init__"><strong>__init__</strong></a>(self, browser_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ExtensionNotFoundException">class <strong>ExtensionNotFoundException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.extension_dict_backend.html#ExtensionNotFoundException">ExtensionNotFoundException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="ExtensionNotFoundException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionNotFoundException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#ExtensionNotFoundException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="ExtensionNotFoundException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionNotFoundException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionNotFoundException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionNotFoundException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionNotFoundException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionNotFoundException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionNotFoundException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionNotFoundException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="ExtensionNotFoundException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.facebook_credentials_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.facebook_credentials_backend.html
new file mode 100644
index 00000000000..19b0d295a96
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.facebook_credentials_backend.html
@@ -0,0 +1,88 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.facebook_credentials_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.facebook_credentials_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/facebook_credentials_backend.py">telemetry/core/chrome/facebook_credentials_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.form_based_credentials_backend.html">telemetry.core.chrome.form_based_credentials_backend</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.facebook_credentials_backend.html#FacebookCredentialsBackend">FacebookCredentialsBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="FacebookCredentialsBackend">class <strong>FacebookCredentialsBackend</strong></a>(<a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.facebook_credentials_backend.html#FacebookCredentialsBackend">FacebookCredentialsBackend</a></dd>
+<dd><a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="FacebookCredentialsBackend-IsAlreadyLoggedIn"><strong>IsAlreadyLoggedIn</strong></a>(self, tab)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>credentials_type</strong></dt>
+</dl>
+<dl><dt><strong>login_form_id</strong></dt>
+</dl>
+<dl><dt><strong>login_input_id</strong></dt>
+</dl>
+<dl><dt><strong>password_input_id</strong></dt>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a>:<br>
+<dl><dt><a name="FacebookCredentialsBackend-IsLoggedIn"><strong>IsLoggedIn</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FacebookCredentialsBackend-LoginNeeded"><strong>LoginNeeded</strong></a>(self, tab, config)</dt><dd><tt>Logs&nbsp;in&nbsp;to&nbsp;a&nbsp;test&nbsp;account.<br>
+&nbsp;<br>
+Raises:<br>
+&nbsp;&nbsp;RuntimeError:&nbsp;if&nbsp;could&nbsp;not&nbsp;get&nbsp;credential&nbsp;information.</tt></dd></dl>
+
+<dl><dt><a name="FacebookCredentialsBackend-LoginNoLongerNeeded"><strong>LoginNoLongerNeeded</strong></a>(self, tab)</dt></dl>
+
+<dl><dt><a name="FacebookCredentialsBackend-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.form_based_credentials_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.form_based_credentials_backend.html
new file mode 100644
index 00000000000..3a9298ac3d1
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.form_based_credentials_backend.html
@@ -0,0 +1,79 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.form_based_credentials_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.form_based_credentials_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/form_based_credentials_backend.py">telemetry/core/chrome/form_based_credentials_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">FormBasedCredentialsBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="FormBasedCredentialsBackend">class <strong>FormBasedCredentialsBackend</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="FormBasedCredentialsBackend-IsAlreadyLoggedIn"><strong>IsAlreadyLoggedIn</strong></a>(self, tab)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackend-IsLoggedIn"><strong>IsLoggedIn</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackend-LoginNeeded"><strong>LoginNeeded</strong></a>(self, tab, config)</dt><dd><tt>Logs&nbsp;in&nbsp;to&nbsp;a&nbsp;test&nbsp;account.<br>
+&nbsp;<br>
+Raises:<br>
+&nbsp;&nbsp;RuntimeError:&nbsp;if&nbsp;could&nbsp;not&nbsp;get&nbsp;credential&nbsp;information.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackend-LoginNoLongerNeeded"><strong>LoginNoLongerNeeded</strong></a>(self, tab)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackend-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>credentials_type</strong></dt>
+</dl>
+<dl><dt><strong>login_form_id</strong></dt>
+</dl>
+<dl><dt><strong>login_input_id</strong></dt>
+</dl>
+<dl><dt><strong>password_input_id</strong></dt>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.form_based_credentials_backend_unittest_base.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.form_based_credentials_backend_unittest_base.html
new file mode 100644
index 00000000000..6c983452243
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.form_based_credentials_backend_unittest_base.html
@@ -0,0 +1,343 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.form_based_credentials_backend_unittest_base</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.form_based_credentials_backend_unittest_base</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/form_based_credentials_backend_unittest_base.py">telemetry/core/chrome/form_based_credentials_backend_unittest_base.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser_finder.html">telemetry.core.browser_finder</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.options_for_unittests.html">telemetry.unittest.options_for_unittests</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.simple_mock.html">telemetry.unittest.simple_mock</a><br>
+<a href="unittest.html">unittest</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="unittest.case.html#TestCase">unittest.case.TestCase</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.form_based_credentials_backend_unittest_base.html#FormBasedCredentialsBackendUnitTestBase">FormBasedCredentialsBackendUnitTestBase</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="FormBasedCredentialsBackendUnitTestBase">class <strong>FormBasedCredentialsBackendUnitTestBase</strong></a>(<a href="unittest.case.html#TestCase">unittest.case.TestCase</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.form_based_credentials_backend_unittest_base.html#FormBasedCredentialsBackendUnitTestBase">FormBasedCredentialsBackendUnitTestBase</a></dd>
+<dd><a href="unittest.case.html#TestCase">unittest.case.TestCase</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-setUp"><strong>setUp</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-testLoginUsingMock"><strong>testLoginUsingMock</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-testRealLoginIfPossible"><strong>testRealLoginIfPossible</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-testRealLoginWithDontOverrideProfileIfPossible"><strong>testRealLoginWithDontOverrideProfileIfPossible</strong></a>(self)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-__call__"><strong>__call__</strong></a>(self, *args, **kwds)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-__eq__"><strong>__eq__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-__hash__"><strong>__hash__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-__init__"><strong>__init__</strong></a>(self, methodName<font color="#909090">='runTest'</font>)</dt><dd><tt>Create&nbsp;an&nbsp;instance&nbsp;of&nbsp;the&nbsp;class&nbsp;that&nbsp;will&nbsp;use&nbsp;the&nbsp;named&nbsp;test<br>
+method&nbsp;when&nbsp;executed.&nbsp;Raises&nbsp;a&nbsp;ValueError&nbsp;if&nbsp;the&nbsp;instance&nbsp;does<br>
+not&nbsp;have&nbsp;a&nbsp;method&nbsp;with&nbsp;the&nbsp;specified&nbsp;name.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-__ne__"><strong>__ne__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-__str__"><strong>__str__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-addCleanup"><strong>addCleanup</strong></a>(self, function, *args, **kwargs)</dt><dd><tt>Add&nbsp;a&nbsp;function,&nbsp;with&nbsp;arguments,&nbsp;to&nbsp;be&nbsp;called&nbsp;when&nbsp;the&nbsp;test&nbsp;is<br>
+completed.&nbsp;Functions&nbsp;added&nbsp;are&nbsp;called&nbsp;on&nbsp;a&nbsp;LIFO&nbsp;basis&nbsp;and&nbsp;are<br>
+called&nbsp;after&nbsp;tearDown&nbsp;on&nbsp;test&nbsp;failure&nbsp;or&nbsp;success.<br>
+&nbsp;<br>
+Cleanup&nbsp;items&nbsp;are&nbsp;called&nbsp;even&nbsp;if&nbsp;setUp&nbsp;fails&nbsp;(unlike&nbsp;tearDown).</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-addTypeEqualityFunc"><strong>addTypeEqualityFunc</strong></a>(self, typeobj, function)</dt><dd><tt>Add&nbsp;a&nbsp;type&nbsp;specific&nbsp;assertEqual&nbsp;style&nbsp;function&nbsp;to&nbsp;compare&nbsp;a&nbsp;type.<br>
+&nbsp;<br>
+This&nbsp;method&nbsp;is&nbsp;for&nbsp;use&nbsp;by&nbsp;<a href="unittest.case.html#TestCase">TestCase</a>&nbsp;subclasses&nbsp;that&nbsp;need&nbsp;to&nbsp;register<br>
+their&nbsp;own&nbsp;type&nbsp;equality&nbsp;functions&nbsp;to&nbsp;provide&nbsp;nicer&nbsp;error&nbsp;messages.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;typeobj:&nbsp;The&nbsp;data&nbsp;type&nbsp;to&nbsp;call&nbsp;this&nbsp;function&nbsp;on&nbsp;when&nbsp;both&nbsp;values<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;are&nbsp;of&nbsp;the&nbsp;same&nbsp;type&nbsp;in&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertEqual">assertEqual</a>().<br>
+&nbsp;&nbsp;&nbsp;&nbsp;function:&nbsp;The&nbsp;callable&nbsp;taking&nbsp;two&nbsp;arguments&nbsp;and&nbsp;an&nbsp;optional<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg=&nbsp;argument&nbsp;that&nbsp;raises&nbsp;self.<strong>failureException</strong>&nbsp;with&nbsp;a<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;useful&nbsp;error&nbsp;message&nbsp;when&nbsp;the&nbsp;two&nbsp;arguments&nbsp;are&nbsp;not&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertAlmostEqual"><strong>assertAlmostEqual</strong></a>(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;more&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;two&nbsp;objects&nbsp;compare&nbsp;equal&nbsp;then&nbsp;they&nbsp;will&nbsp;automatically<br>
+compare&nbsp;almost&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertAlmostEquals"><strong>assertAlmostEquals</strong></a> = assertAlmostEqual(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;more&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;two&nbsp;objects&nbsp;compare&nbsp;equal&nbsp;then&nbsp;they&nbsp;will&nbsp;automatically<br>
+compare&nbsp;almost&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertDictContainsSubset"><strong>assertDictContainsSubset</strong></a>(self, expected, actual, msg<font color="#909090">=None</font>)</dt><dd><tt>Checks&nbsp;whether&nbsp;actual&nbsp;is&nbsp;a&nbsp;superset&nbsp;of&nbsp;expected.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertDictEqual"><strong>assertDictEqual</strong></a>(self, d1, d2, msg<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertEqual"><strong>assertEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertEquals"><strong>assertEquals</strong></a> = assertEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertFalse"><strong>assertFalse</strong></a>(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;false.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertGreater"><strong>assertGreater</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;&gt;&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertGreaterEqual"><strong>assertGreaterEqual</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;&gt;=&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertIn"><strong>assertIn</strong></a>(self, member, container, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;in&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertIs"><strong>assertIs</strong></a>(self, expr1, expr2, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;is&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertIsInstance"><strong>assertIsInstance</strong></a>(self, obj, cls, msg<font color="#909090">=None</font>)</dt><dd><tt>Same&nbsp;as&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(isinstance(obj,&nbsp;cls)),&nbsp;with&nbsp;a&nbsp;nicer<br>
+default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertIsNone"><strong>assertIsNone</strong></a>(self, obj, msg<font color="#909090">=None</font>)</dt><dd><tt>Same&nbsp;as&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(obj&nbsp;is&nbsp;None),&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertIsNot"><strong>assertIsNot</strong></a>(self, expr1, expr2, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;is&nbsp;not&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertIsNotNone"><strong>assertIsNotNone</strong></a>(self, obj, msg<font color="#909090">=None</font>)</dt><dd><tt>Included&nbsp;for&nbsp;symmetry&nbsp;with&nbsp;assertIsNone.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertItemsEqual"><strong>assertItemsEqual</strong></a>(self, expected_seq, actual_seq, msg<font color="#909090">=None</font>)</dt><dd><tt>An&nbsp;unordered&nbsp;sequence&nbsp;specific&nbsp;comparison.&nbsp;It&nbsp;asserts&nbsp;that<br>
+actual_seq&nbsp;and&nbsp;expected_seq&nbsp;have&nbsp;the&nbsp;same&nbsp;element&nbsp;counts.<br>
+Equivalent&nbsp;to::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertEqual">assertEqual</a>(Counter(iter(actual_seq)),<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Counter(iter(expected_seq)))<br>
+&nbsp;<br>
+Asserts&nbsp;that&nbsp;each&nbsp;element&nbsp;has&nbsp;the&nbsp;same&nbsp;count&nbsp;in&nbsp;both&nbsp;sequences.<br>
+Example:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;[0,&nbsp;1,&nbsp;1]&nbsp;and&nbsp;[1,&nbsp;0,&nbsp;1]&nbsp;compare&nbsp;equal.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;[0,&nbsp;0,&nbsp;1]&nbsp;and&nbsp;[0,&nbsp;1]&nbsp;compare&nbsp;unequal.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertLess"><strong>assertLess</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;&lt;&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertLessEqual"><strong>assertLessEqual</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;&lt;=&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertListEqual"><strong>assertListEqual</strong></a>(self, list1, list2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;list-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;list1:&nbsp;The&nbsp;first&nbsp;list&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;list2:&nbsp;The&nbsp;second&nbsp;list&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertMultiLineEqual"><strong>assertMultiLineEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Assert&nbsp;that&nbsp;two&nbsp;multi-line&nbsp;strings&nbsp;are&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertNotAlmostEqual"><strong>assertNotAlmostEqual</strong></a>(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;less&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+Objects&nbsp;that&nbsp;are&nbsp;equal&nbsp;automatically&nbsp;fail.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertNotAlmostEquals"><strong>assertNotAlmostEquals</strong></a> = assertNotAlmostEqual(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;less&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+Objects&nbsp;that&nbsp;are&nbsp;equal&nbsp;automatically&nbsp;fail.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertNotEqual"><strong>assertNotEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertNotEquals"><strong>assertNotEquals</strong></a> = assertNotEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertNotIn"><strong>assertNotIn</strong></a>(self, member, container, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;not&nbsp;in&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertNotIsInstance"><strong>assertNotIsInstance</strong></a>(self, obj, cls, msg<font color="#909090">=None</font>)</dt><dd><tt>Included&nbsp;for&nbsp;symmetry&nbsp;with&nbsp;assertIsInstance.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertNotRegexpMatches"><strong>assertNotRegexpMatches</strong></a>(self, text, unexpected_regexp, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;the&nbsp;test&nbsp;if&nbsp;the&nbsp;text&nbsp;matches&nbsp;the&nbsp;regular&nbsp;expression.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertRaises"><strong>assertRaises</strong></a>(self, excClass, callableObj<font color="#909090">=None</font>, *args, **kwargs)</dt><dd><tt>Fail&nbsp;unless&nbsp;an&nbsp;exception&nbsp;of&nbsp;class&nbsp;excClass&nbsp;is&nbsp;thrown<br>
+by&nbsp;callableObj&nbsp;when&nbsp;invoked&nbsp;with&nbsp;arguments&nbsp;args&nbsp;and&nbsp;keyword<br>
+arguments&nbsp;kwargs.&nbsp;If&nbsp;a&nbsp;different&nbsp;type&nbsp;of&nbsp;exception&nbsp;is<br>
+thrown,&nbsp;it&nbsp;will&nbsp;not&nbsp;be&nbsp;caught,&nbsp;and&nbsp;the&nbsp;test&nbsp;case&nbsp;will&nbsp;be<br>
+deemed&nbsp;to&nbsp;have&nbsp;suffered&nbsp;an&nbsp;error,&nbsp;exactly&nbsp;as&nbsp;for&nbsp;an<br>
+unexpected&nbsp;exception.<br>
+&nbsp;<br>
+If&nbsp;called&nbsp;with&nbsp;callableObj&nbsp;omitted&nbsp;or&nbsp;None,&nbsp;will&nbsp;return&nbsp;a<br>
+context&nbsp;object&nbsp;used&nbsp;like&nbsp;this::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertRaises">assertRaises</a>(SomeException):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_something()<br>
+&nbsp;<br>
+The&nbsp;context&nbsp;manager&nbsp;keeps&nbsp;a&nbsp;reference&nbsp;to&nbsp;the&nbsp;exception&nbsp;as<br>
+the&nbsp;'exception'&nbsp;attribute.&nbsp;This&nbsp;allows&nbsp;you&nbsp;to&nbsp;inspect&nbsp;the<br>
+exception&nbsp;after&nbsp;the&nbsp;assertion::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertRaises">assertRaises</a>(SomeException)&nbsp;as&nbsp;cm:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_something()<br>
+&nbsp;&nbsp;&nbsp;&nbsp;the_exception&nbsp;=&nbsp;cm.exception<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#FormBasedCredentialsBackendUnitTestBase-assertEqual">assertEqual</a>(the_exception.error_code,&nbsp;3)</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertRaisesRegexp"><strong>assertRaisesRegexp</strong></a>(self, expected_exception, expected_regexp, callable_obj<font color="#909090">=None</font>, *args, **kwargs)</dt><dd><tt>Asserts&nbsp;that&nbsp;the&nbsp;message&nbsp;in&nbsp;a&nbsp;raised&nbsp;exception&nbsp;matches&nbsp;a&nbsp;regexp.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;expected_exception:&nbsp;Exception&nbsp;class&nbsp;expected&nbsp;to&nbsp;be&nbsp;raised.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;expected_regexp:&nbsp;Regexp&nbsp;(re&nbsp;pattern&nbsp;object&nbsp;or&nbsp;string)&nbsp;expected<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;be&nbsp;found&nbsp;in&nbsp;error&nbsp;message.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;callable_obj:&nbsp;Function&nbsp;to&nbsp;be&nbsp;called.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;args:&nbsp;Extra&nbsp;args.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;kwargs:&nbsp;Extra&nbsp;kwargs.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertRegexpMatches"><strong>assertRegexpMatches</strong></a>(self, text, expected_regexp, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;the&nbsp;test&nbsp;unless&nbsp;the&nbsp;text&nbsp;matches&nbsp;the&nbsp;regular&nbsp;expression.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertSequenceEqual"><strong>assertSequenceEqual</strong></a>(self, seq1, seq2, msg<font color="#909090">=None</font>, seq_type<font color="#909090">=None</font>)</dt><dd><tt>An&nbsp;equality&nbsp;assertion&nbsp;for&nbsp;ordered&nbsp;sequences&nbsp;(like&nbsp;lists&nbsp;and&nbsp;tuples).<br>
+&nbsp;<br>
+For&nbsp;the&nbsp;purposes&nbsp;of&nbsp;this&nbsp;function,&nbsp;a&nbsp;valid&nbsp;ordered&nbsp;sequence&nbsp;type&nbsp;is&nbsp;one<br>
+which&nbsp;can&nbsp;be&nbsp;indexed,&nbsp;has&nbsp;a&nbsp;length,&nbsp;and&nbsp;has&nbsp;an&nbsp;equality&nbsp;operator.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq1:&nbsp;The&nbsp;first&nbsp;sequence&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq2:&nbsp;The&nbsp;second&nbsp;sequence&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq_type:&nbsp;The&nbsp;expected&nbsp;datatype&nbsp;of&nbsp;the&nbsp;sequences,&nbsp;or&nbsp;None&nbsp;if&nbsp;no<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;datatype&nbsp;should&nbsp;be&nbsp;enforced.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertSetEqual"><strong>assertSetEqual</strong></a>(self, set1, set2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;set-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;set1:&nbsp;The&nbsp;first&nbsp;set&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;set2:&nbsp;The&nbsp;second&nbsp;set&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.<br>
+&nbsp;<br>
+assertSetEqual&nbsp;uses&nbsp;ducktyping&nbsp;to&nbsp;support&nbsp;different&nbsp;types&nbsp;of&nbsp;sets,&nbsp;and<br>
+is&nbsp;optimized&nbsp;for&nbsp;sets&nbsp;specifically&nbsp;(parameters&nbsp;must&nbsp;support&nbsp;a<br>
+difference&nbsp;method).</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertTrue"><strong>assertTrue</strong></a>(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;true.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assertTupleEqual"><strong>assertTupleEqual</strong></a>(self, tuple1, tuple2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;tuple-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tuple1:&nbsp;The&nbsp;first&nbsp;tuple&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tuple2:&nbsp;The&nbsp;second&nbsp;tuple&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-assert_"><strong>assert_</strong></a> = assertTrue(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;true.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-countTestCases"><strong>countTestCases</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-debug"><strong>debug</strong></a>(self)</dt><dd><tt>Run&nbsp;the&nbsp;test&nbsp;without&nbsp;collecting&nbsp;errors&nbsp;in&nbsp;a&nbsp;TestResult</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-defaultTestResult"><strong>defaultTestResult</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-doCleanups"><strong>doCleanups</strong></a>(self)</dt><dd><tt>Execute&nbsp;all&nbsp;cleanup&nbsp;functions.&nbsp;Normally&nbsp;called&nbsp;for&nbsp;you&nbsp;after<br>
+tearDown.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-fail"><strong>fail</strong></a>(self, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;immediately,&nbsp;with&nbsp;the&nbsp;given&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-failIf"><strong>failIf</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-failIfAlmostEqual"><strong>failIfAlmostEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-failIfEqual"><strong>failIfEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-failUnless"><strong>failUnless</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-failUnlessAlmostEqual"><strong>failUnlessAlmostEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-failUnlessEqual"><strong>failUnlessEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-failUnlessRaises"><strong>failUnlessRaises</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-id"><strong>id</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-run"><strong>run</strong></a>(self, result<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-shortDescription"><strong>shortDescription</strong></a>(self)</dt><dd><tt>Returns&nbsp;a&nbsp;one-line&nbsp;description&nbsp;of&nbsp;the&nbsp;test,&nbsp;or&nbsp;None&nbsp;if&nbsp;no<br>
+description&nbsp;has&nbsp;been&nbsp;provided.<br>
+&nbsp;<br>
+The&nbsp;default&nbsp;implementation&nbsp;of&nbsp;this&nbsp;method&nbsp;returns&nbsp;the&nbsp;first&nbsp;line&nbsp;of<br>
+the&nbsp;specified&nbsp;test&nbsp;method's&nbsp;docstring.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-skipTest"><strong>skipTest</strong></a>(self, reason)</dt><dd><tt>Skip&nbsp;this&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-tearDown"><strong>tearDown</strong></a>(self)</dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;deconstructing&nbsp;the&nbsp;test&nbsp;fixture&nbsp;after&nbsp;testing&nbsp;it.</tt></dd></dl>
+
+<hr>
+Class methods inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-setUpClass"><strong>setUpClass</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;setting&nbsp;up&nbsp;class&nbsp;fixture&nbsp;before&nbsp;running&nbsp;tests&nbsp;in&nbsp;the&nbsp;class.</tt></dd></dl>
+
+<dl><dt><a name="FormBasedCredentialsBackendUnitTestBase-tearDownClass"><strong>tearDownClass</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;deconstructing&nbsp;the&nbsp;class&nbsp;fixture&nbsp;after&nbsp;running&nbsp;all&nbsp;tests&nbsp;in&nbsp;the&nbsp;class.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><strong>failureException</strong> = &lt;type 'exceptions.AssertionError'&gt;<dd><tt>Assertion&nbsp;failed.</tt></dl>
+
+<dl><dt><strong>longMessage</strong> = False</dl>
+
+<dl><dt><strong>maxDiff</strong> = 640</dl>
+
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.google_credentials_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.google_credentials_backend.html
new file mode 100644
index 00000000000..57a53d1f91a
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.google_credentials_backend.html
@@ -0,0 +1,88 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.google_credentials_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.google_credentials_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/google_credentials_backend.py">telemetry/core/chrome/google_credentials_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.form_based_credentials_backend.html">telemetry.core.chrome.form_based_credentials_backend</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.google_credentials_backend.html#GoogleCredentialsBackend">GoogleCredentialsBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="GoogleCredentialsBackend">class <strong>GoogleCredentialsBackend</strong></a>(<a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.google_credentials_backend.html#GoogleCredentialsBackend">GoogleCredentialsBackend</a></dd>
+<dd><a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="GoogleCredentialsBackend-IsAlreadyLoggedIn"><strong>IsAlreadyLoggedIn</strong></a>(self, tab)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>credentials_type</strong></dt>
+</dl>
+<dl><dt><strong>login_form_id</strong></dt>
+</dl>
+<dl><dt><strong>login_input_id</strong></dt>
+</dl>
+<dl><dt><strong>password_input_id</strong></dt>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a>:<br>
+<dl><dt><a name="GoogleCredentialsBackend-IsLoggedIn"><strong>IsLoggedIn</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="GoogleCredentialsBackend-LoginNeeded"><strong>LoginNeeded</strong></a>(self, tab, config)</dt><dd><tt>Logs&nbsp;in&nbsp;to&nbsp;a&nbsp;test&nbsp;account.<br>
+&nbsp;<br>
+Raises:<br>
+&nbsp;&nbsp;RuntimeError:&nbsp;if&nbsp;could&nbsp;not&nbsp;get&nbsp;credential&nbsp;information.</tt></dd></dl>
+
+<dl><dt><a name="GoogleCredentialsBackend-LoginNoLongerNeeded"><strong>LoginNoLongerNeeded</strong></a>(self, tab)</dt></dl>
+
+<dl><dt><a name="GoogleCredentialsBackend-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.chrome.form_based_credentials_backend.html#FormBasedCredentialsBackend">telemetry.core.chrome.form_based_credentials_backend.FormBasedCredentialsBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.html
new file mode 100644
index 00000000000..fc38ab28bd7
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.html
@@ -0,0 +1,65 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry.core.chrome</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.chrome</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/__init__.py">telemetry/core/chrome/__init__.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.adb_commands.html">adb_commands</a><br>
+<a href="telemetry.core.chrome.android_browser_backend.html">android_browser_backend</a><br>
+<a href="telemetry.core.chrome.android_browser_finder.html">android_browser_finder</a><br>
+<a href="telemetry.core.chrome.android_browser_finder_unittest.html">android_browser_finder_unittest</a><br>
+<a href="telemetry.core.chrome.browser_backend.html">browser_backend</a><br>
+<a href="telemetry.core.chrome.cros_browser_backend.html">cros_browser_backend</a><br>
+<a href="telemetry.core.chrome.cros_browser_finder.html">cros_browser_finder</a><br>
+<a href="telemetry.core.chrome.cros_browser_finder_unittest.html">cros_browser_finder_unittest</a><br>
+<a href="telemetry.core.chrome.cros_interface.html">cros_interface</a><br>
+<a href="telemetry.core.chrome.cros_interface_unittest.html">cros_interface_unittest</a><br>
+<a href="telemetry.core.chrome.crx_id.html">crx_id</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.desktop_browser_backend.html">desktop_browser_backend</a><br>
+<a href="telemetry.core.chrome.desktop_browser_finder.html">desktop_browser_finder</a><br>
+<a href="telemetry.core.chrome.desktop_browser_finder_unittest.html">desktop_browser_finder_unittest</a><br>
+<a href="telemetry.core.chrome.extension_dict_backend.html">extension_dict_backend</a><br>
+<a href="telemetry.core.chrome.facebook_credentials_backend.html">facebook_credentials_backend</a><br>
+<a href="telemetry.core.chrome.facebook_credentials_backend_unittest.html">facebook_credentials_backend_unittest</a><br>
+<a href="telemetry.core.chrome.form_based_credentials_backend.html">form_based_credentials_backend</a><br>
+<a href="telemetry.core.chrome.form_based_credentials_backend_unittest_base.html">form_based_credentials_backend_unittest_base</a><br>
+<a href="telemetry.core.chrome.google_credentials_backend.html">google_credentials_backend</a><br>
+<a href="telemetry.core.chrome.google_credentials_backend_unittest.html">google_credentials_backend_unittest</a><br>
+<a href="telemetry.core.chrome.inspector_backend.html">inspector_backend</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.inspector_console.html">inspector_console</a><br>
+<a href="telemetry.core.chrome.inspector_console_unittest.html">inspector_console_unittest</a><br>
+<a href="telemetry.core.chrome.inspector_memory.html">inspector_memory</a><br>
+<a href="telemetry.core.chrome.inspector_memory_unittest.html">inspector_memory_unittest</a><br>
+<a href="telemetry.core.chrome.inspector_network.html">inspector_network</a><br>
+<a href="telemetry.core.chrome.inspector_page.html">inspector_page</a><br>
+<a href="telemetry.core.chrome.inspector_page_unittest.html">inspector_page_unittest</a><br>
+<a href="telemetry.core.chrome.inspector_runtime.html">inspector_runtime</a><br>
+<a href="telemetry.core.chrome.inspector_runtime_unittest.html">inspector_runtime_unittest</a><br>
+<a href="telemetry.core.chrome.inspector_timeline.html">inspector_timeline</a><br>
+<a href="telemetry.core.chrome.inspector_timeline_unittest.html">inspector_timeline_unittest</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.misc_web_contents_backend.html">misc_web_contents_backend</a><br>
+<a href="telemetry.core.chrome.png_bitmap.html">png_bitmap</a><br>
+<a href="telemetry.core.chrome.png_bitmap_unittest.html">png_bitmap_unittest</a><br>
+<a href="telemetry.core.chrome.tab_list_backend.html">tab_list_backend</a><br>
+<a href="telemetry.core.chrome.trace_result.html">trace_result</a><br>
+<a href="telemetry.core.chrome.tracing_backend.html">tracing_backend</a><br>
+<a href="telemetry.core.chrome.tracing_backend_unittest.html">tracing_backend_unittest</a><br>
+<a href="telemetry.core.chrome.websocket.html">websocket</a><br>
+<a href="telemetry.core.chrome.websocket_unittest.html">websocket_unittest</a><br>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_backend.html
new file mode 100644
index 00000000000..34386815587
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_backend.html
@@ -0,0 +1,198 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.inspector_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.inspector_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/inspector_backend.py">telemetry/core/chrome/inspector_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+<a href="telemetry.core.chrome.inspector_console.html">telemetry.core.chrome.inspector_console</a><br>
+<a href="telemetry.core.chrome.inspector_memory.html">telemetry.core.chrome.inspector_memory</a><br>
+<a href="telemetry.core.chrome.inspector_network.html">telemetry.core.chrome.inspector_network</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.inspector_page.html">telemetry.core.chrome.inspector_page</a><br>
+<a href="telemetry.core.chrome.inspector_runtime.html">telemetry.core.chrome.inspector_runtime</a><br>
+<a href="telemetry.core.chrome.inspector_timeline.html">telemetry.core.chrome.inspector_timeline</a><br>
+<a href="json.html">json</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="telemetry.core.chrome.png_bitmap.html">telemetry.core.chrome.png_bitmap</a><br>
+<a href="socket.html">socket</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+<a href="telemetry.core.chrome.websocket.html">telemetry.core.chrome.websocket</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_backend.html#InspectorBackend">InspectorBackend</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_backend.html#InspectorException">InspectorException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorBackend">class <strong>InspectorBackend</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="InspectorBackend-Activate"><strong>Activate</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-ClearCache"><strong>ClearCache</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-CollectGarbage"><strong>CollectGarbage</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-Disconnect"><strong>Disconnect</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-DispatchNotifications"><strong>DispatchNotifications</strong></a>(self, timeout<font color="#909090">=10</font>)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-EvaluateJavaScript"><strong>EvaluateJavaScript</strong></a>(self, expr, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-ExecuteJavaScript"><strong>ExecuteJavaScript</strong></a>(self, expr, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-GetCookieByName"><strong>GetCookieByName</strong></a>(self, name, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-GetDOMStats"><strong>GetDOMStats</strong></a>(self, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-Navigate"><strong>Navigate</strong></a>(self, url, script_to_evaluate_on_commit, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-PerformActionAndWaitForNavigate"><strong>PerformActionAndWaitForNavigate</strong></a>(self, action_function, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-RegisterDomain"><strong>RegisterDomain</strong></a>(self, domain_name, notification_handler, will_close_handler)</dt><dd><tt>Registers&nbsp;a&nbsp;given&nbsp;domain&nbsp;for&nbsp;handling&nbsp;notification&nbsp;methods.<br>
+&nbsp;<br>
+For&nbsp;example,&nbsp;given&nbsp;inspector_backend:<br>
+&nbsp;&nbsp;&nbsp;def&nbsp;OnConsoleNotification(msg):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;msg['method']&nbsp;==&nbsp;'Console.messageAdded':<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print&nbsp;msg['params']['message']<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return<br>
+&nbsp;&nbsp;&nbsp;def&nbsp;OnConsoleClose(self):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br>
+&nbsp;&nbsp;&nbsp;inspector_backend.<a href="#InspectorBackend-RegisterDomain">RegisterDomain</a>('Console',<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OnConsoleNotification,&nbsp;OnConsoleClose)</tt></dd></dl>
+
+<dl><dt><a name="InspectorBackend-Screenshot"><strong>Screenshot</strong></a>(self, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-SendAndIgnoreResponse"><strong>SendAndIgnoreResponse</strong></a>(self, req)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-StartTimelineRecording"><strong>StartTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-StopTimelineRecording"><strong>StopTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-SyncRequest"><strong>SyncRequest</strong></a>(self, req, timeout<font color="#909090">=10</font>)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-UnregisterDomain"><strong>UnregisterDomain</strong></a>(self, domain_name)</dt><dd><tt>Unregisters&nbsp;a&nbsp;previously&nbsp;registered&nbsp;domain.</tt></dd></dl>
+
+<dl><dt><a name="InspectorBackend-WaitForDocumentReadyStateToBeComplete"><strong>WaitForDocumentReadyStateToBeComplete</strong></a>(self, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-WaitForDocumentReadyStateToBeInteractiveOrBetter"><strong>WaitForDocumentReadyStateToBeInteractiveOrBetter</strong></a>(self, timeout)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorBackend-__init__"><strong>__init__</strong></a>(self, browser, browser_backend, debugger_url)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser</strong></dt>
+</dl>
+<dl><dt><strong>message_output_stream</strong></dt>
+</dl>
+<dl><dt><strong>screenshot_supported</strong></dt>
+</dl>
+<dl><dt><strong>timeline_model</strong></dt>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorException">class <strong>InspectorException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.inspector_backend.html#InspectorException">InspectorException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="InspectorException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#InspectorException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="InspectorException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="InspectorException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="InspectorException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="InspectorException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="InspectorException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="InspectorException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="InspectorException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="InspectorException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="InspectorException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="InspectorException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_console.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_console.html
new file mode 100644
index 00000000000..35586f7a571
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_console.html
@@ -0,0 +1,60 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.inspector_console</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.inspector_console</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/inspector_console.py">telemetry/core/chrome/inspector_console.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="json.html">json</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_console.html#InspectorConsole">InspectorConsole</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorConsole">class <strong>InspectorConsole</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="InspectorConsole-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>message_output_stream</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_memory.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_memory.html
new file mode 100644
index 00000000000..762f7991f66
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_memory.html
@@ -0,0 +1,133 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.inspector_memory</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.inspector_memory</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/inspector_memory.py">telemetry/core/chrome/inspector_memory.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="json.html">json</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_memory.html#InspectorMemory">InspectorMemory</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_memory.html#InspectorMemoryException">InspectorMemoryException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorMemory">class <strong>InspectorMemory</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Communicates&nbsp;with&nbsp;the&nbsp;remote&nbsp;inspector's&nbsp;Memory&nbsp;domain.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="InspectorMemory-GetDOMCounters"><strong>GetDOMCounters</strong></a>(self, timeout)</dt><dd><tt>Retrieves&nbsp;DOM&nbsp;element&nbsp;counts.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;timeout:&nbsp;The&nbsp;number&nbsp;of&nbsp;seconds&nbsp;to&nbsp;wait&nbsp;for&nbsp;the&nbsp;inspector&nbsp;backend&nbsp;to<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;service&nbsp;the&nbsp;request&nbsp;before&nbsp;timing&nbsp;out.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;A&nbsp;dictionary&nbsp;containing&nbsp;the&nbsp;counts&nbsp;associated&nbsp;with&nbsp;"nodes",&nbsp;"documents",<br>
+&nbsp;&nbsp;and&nbsp;"jsEventListeners".</tt></dd></dl>
+
+<dl><dt><a name="InspectorMemory-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorMemoryException">class <strong>InspectorMemoryException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.inspector_memory.html#InspectorMemoryException">InspectorMemoryException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="InspectorMemoryException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorMemoryException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#InspectorMemoryException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="InspectorMemoryException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorMemoryException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="InspectorMemoryException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorMemoryException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="InspectorMemoryException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorMemoryException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="InspectorMemoryException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorMemoryException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="InspectorMemoryException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="InspectorMemoryException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorMemoryException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="InspectorMemoryException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorMemoryException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="InspectorMemoryException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="InspectorMemoryException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#InspectorMemoryException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="InspectorMemoryException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_network.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_network.html
new file mode 100644
index 00000000000..1ad67cda458
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_network.html
@@ -0,0 +1,51 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.inspector_network</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.inspector_network</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/inspector_network.py">telemetry/core/chrome/inspector_network.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_network.html#InspectorNetwork">InspectorNetwork</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorNetwork">class <strong>InspectorNetwork</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="InspectorNetwork-ClearCache"><strong>ClearCache</strong></a>(self, timeout<font color="#909090">=60</font>)</dt><dd><tt>Clears&nbsp;the&nbsp;browser's&nbsp;disk&nbsp;and&nbsp;memory&nbsp;cache.</tt></dd></dl>
+
+<dl><dt><a name="InspectorNetwork-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_page.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_page.html
new file mode 100644
index 00000000000..cbc298314dd
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_page.html
@@ -0,0 +1,74 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.inspector_page</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.inspector_page</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/inspector_page.py">telemetry/core/chrome/inspector_page.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="json.html">json</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_page.html#InspectorPage">InspectorPage</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorPage">class <strong>InspectorPage</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="InspectorPage-CollectGarbage"><strong>CollectGarbage</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<dl><dt><a name="InspectorPage-GetCookieByName"><strong>GetCookieByName</strong></a>(self, name, timeout<font color="#909090">=60</font>)</dt><dd><tt>Returns&nbsp;the&nbsp;value&nbsp;of&nbsp;the&nbsp;cookie&nbsp;by&nbsp;the&nbsp;given&nbsp;|name|.</tt></dd></dl>
+
+<dl><dt><a name="InspectorPage-Navigate"><strong>Navigate</strong></a>(self, url, script_to_evaluate_on_commit<font color="#909090">=None</font>, timeout<font color="#909090">=60</font>)</dt><dd><tt>Navigates&nbsp;to&nbsp;|url|.<br>
+&nbsp;<br>
+If&nbsp;|script_to_evaluate_on_commit|&nbsp;is&nbsp;given,&nbsp;the&nbsp;script&nbsp;source&nbsp;string&nbsp;will&nbsp;be<br>
+evaluated&nbsp;when&nbsp;the&nbsp;navigation&nbsp;is&nbsp;committed.&nbsp;This&nbsp;is&nbsp;after&nbsp;the&nbsp;context&nbsp;of<br>
+the&nbsp;page&nbsp;exists,&nbsp;but&nbsp;before&nbsp;any&nbsp;script&nbsp;on&nbsp;the&nbsp;page&nbsp;itself&nbsp;has&nbsp;executed.</tt></dd></dl>
+
+<dl><dt><a name="InspectorPage-PerformActionAndWaitForNavigate"><strong>PerformActionAndWaitForNavigate</strong></a>(self, action_function, timeout<font color="#909090">=60</font>)</dt><dd><tt>Executes&nbsp;action_function,&nbsp;and&nbsp;waits&nbsp;for&nbsp;the&nbsp;navigation&nbsp;to&nbsp;complete.<br>
+&nbsp;<br>
+action_function&nbsp;is&nbsp;expect&nbsp;to&nbsp;result&nbsp;in&nbsp;a&nbsp;navigation.&nbsp;This&nbsp;function&nbsp;returns<br>
+when&nbsp;the&nbsp;navigation&nbsp;is&nbsp;complete&nbsp;or&nbsp;when&nbsp;the&nbsp;timeout&nbsp;has&nbsp;been&nbsp;exceeded.</tt></dd></dl>
+
+<dl><dt><a name="InspectorPage-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_runtime.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_runtime.html
new file mode 100644
index 00000000000..be70c91b49b
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_runtime.html
@@ -0,0 +1,72 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.inspector_runtime</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.inspector_runtime</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/inspector_runtime.py">telemetry/core/chrome/inspector_runtime.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_runtime.html#InspectorRuntime">InspectorRuntime</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorRuntime">class <strong>InspectorRuntime</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="InspectorRuntime-Evaluate"><strong>Evaluate</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Evalutes&nbsp;expr&nbsp;in&nbsp;javascript&nbsp;and&nbsp;returns&nbsp;the&nbsp;JSONized&nbsp;result.<br>
+&nbsp;<br>
+Consider&nbsp;using&nbsp;Execute&nbsp;for&nbsp;cases&nbsp;where&nbsp;the&nbsp;result&nbsp;of&nbsp;the&nbsp;expression&nbsp;is&nbsp;not<br>
+needed.<br>
+&nbsp;<br>
+If&nbsp;evaluation&nbsp;throws&nbsp;in&nbsp;javascript,&nbsp;a&nbsp;python&nbsp;EvaluateException&nbsp;will<br>
+be&nbsp;raised.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;result&nbsp;of&nbsp;the&nbsp;evaluation&nbsp;cannot&nbsp;be&nbsp;JSONized,&nbsp;then&nbsp;an<br>
+EvaluationException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="InspectorRuntime-Execute"><strong>Execute</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Executes&nbsp;expr&nbsp;in&nbsp;javascript.&nbsp;Does&nbsp;not&nbsp;return&nbsp;the&nbsp;result.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;expression&nbsp;failed&nbsp;to&nbsp;evaluate,&nbsp;EvaluateException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="InspectorRuntime-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_timeline.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_timeline.html
new file mode 100644
index 00000000000..6328ad9d871
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.inspector_timeline.html
@@ -0,0 +1,133 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.inspector_timeline</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.inspector_timeline</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/inspector_timeline.py">telemetry/core/chrome/inspector_timeline.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.model.html">telemetry.core.timeline.model</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_timeline.html#InspectorTimeline">InspectorTimeline</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.inspector_timeline.html#TabBackendException">TabBackendException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorTimeline">class <strong>InspectorTimeline</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Implementation&nbsp;of&nbsp;dev&nbsp;tools&nbsp;timeline.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="InspectorTimeline-Start"><strong>Start</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorTimeline-Stop"><strong>Stop</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorTimeline-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>timeline_model</strong></dt>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>Recorder</strong> = &lt;class 'telemetry.core.chrome.inspector_timeline.Recorder'&gt;<dd><tt>Utility&nbsp;class&nbsp;to&nbsp;Start&nbsp;/&nbsp;Stop&nbsp;recording&nbsp;timeline.</tt></dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TabBackendException">class <strong>TabBackendException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.inspector_timeline.html#TabBackendException">TabBackendException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="TabBackendException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#TabBackendException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#TabBackendException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="TabBackendException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#TabBackendException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="TabBackendException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#TabBackendException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="TabBackendException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#TabBackendException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="TabBackendException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#TabBackendException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="TabBackendException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="TabBackendException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#TabBackendException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="TabBackendException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#TabBackendException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="TabBackendException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="TabBackendException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#TabBackendException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="TabBackendException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.misc_web_contents_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.misc_web_contents_backend.html
new file mode 100644
index 00000000000..d733762082b
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.misc_web_contents_backend.html
@@ -0,0 +1,68 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.misc_web_contents_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.misc_web_contents_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/misc_web_contents_backend.py">telemetry/core/chrome/misc_web_contents_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+<a href="httplib.html">httplib</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.inspector_backend.html">telemetry.core.chrome.inspector_backend</a><br>
+<a href="json.html">json</a><br>
+</td><td width="25%" valign=top><a href="socket.html">socket</a><br>
+<a href="urllib2.html">urllib2</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.web_contents.html">telemetry.core.web_contents</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.misc_web_contents_backend.html#MiscWebContentsBackend">MiscWebContentsBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MiscWebContentsBackend">class <strong>MiscWebContentsBackend</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Provides&nbsp;acccess&nbsp;to&nbsp;chrome://oobe/login&nbsp;page,&nbsp;which&nbsp;is&nbsp;neither&nbsp;an&nbsp;extension<br>
+nor&nbsp;a&nbsp;tab.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="MiscWebContentsBackend-GetOobe"><strong>GetOobe</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MiscWebContentsBackend-__init__"><strong>__init__</strong></a>(self, browser_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.png_bitmap.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.png_bitmap.html
new file mode 100644
index 00000000000..a51eb7e0eff
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.png_bitmap.html
@@ -0,0 +1,100 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.png_bitmap</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.png_bitmap</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/png_bitmap.py">telemetry/core/chrome/png_bitmap.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="base64.html">base64</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="png.html">png</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.png_bitmap.html#PngBitmap">PngBitmap</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.chrome.png_bitmap.html#PngColor">PngColor</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PngBitmap">class <strong>PngBitmap</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Utilities&nbsp;for&nbsp;parsing&nbsp;and&nbsp;inspecting&nbsp;inspecting&nbsp;a&nbsp;PNG<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PngBitmap-GetPixelColor"><strong>GetPixelColor</strong></a>(self, x, y)</dt><dd><tt>Returns&nbsp;a&nbsp;<a href="#PngColor">PngColor</a>&nbsp;for&nbsp;the&nbsp;pixel&nbsp;at&nbsp;(x,&nbsp;y)</tt></dd></dl>
+
+<dl><dt><a name="PngBitmap-WriteFile"><strong>WriteFile</strong></a>(self, path)</dt></dl>
+
+<dl><dt><a name="PngBitmap-__init__"><strong>__init__</strong></a>(self, base64_png)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>height</strong></dt>
+<dd><tt>Height&nbsp;of&nbsp;the&nbsp;snapshot</tt></dd>
+</dl>
+<dl><dt><strong>width</strong></dt>
+<dd><tt>Width&nbsp;of&nbsp;the&nbsp;snapshot</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PngColor">class <strong>PngColor</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Encapsulates&nbsp;an&nbsp;RGB&nbsp;color&nbsp;retreived&nbsp;from&nbsp;a&nbsp;<a href="#PngBitmap">PngBitmap</a><br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PngColor-AssertIsRGB"><strong>AssertIsRGB</strong></a>(self, r, g, b, tolerance<font color="#909090">=0</font>)</dt></dl>
+
+<dl><dt><a name="PngColor-AssertIsRGBA"><strong>AssertIsRGBA</strong></a>(self, r, g, b, a, tolerance<font color="#909090">=0</font>)</dt></dl>
+
+<dl><dt><a name="PngColor-IsEqual"><strong>IsEqual</strong></a>(self, expected_color, tolerance<font color="#909090">=0</font>)</dt><dd><tt>Verifies&nbsp;that&nbsp;the&nbsp;color&nbsp;is&nbsp;within&nbsp;a&nbsp;given&nbsp;tolerance&nbsp;of<br>
+the&nbsp;expected&nbsp;color</tt></dd></dl>
+
+<dl><dt><a name="PngColor-__init__"><strong>__init__</strong></a>(self, r, g, b, a<font color="#909090">=255</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.tab_list_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.tab_list_backend.html
new file mode 100644
index 00000000000..67df8f2cc0f
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.tab_list_backend.html
@@ -0,0 +1,85 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.tab_list_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.tab_list_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/tab_list_backend.py">telemetry/core/chrome/tab_list_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+<a href="httplib.html">httplib</a><br>
+<a href="telemetry.core.chrome.inspector_backend.html">telemetry.core.chrome.inspector_backend</a><br>
+</td><td width="25%" valign=top><a href="json.html">json</a><br>
+<a href="socket.html">socket</a><br>
+<a href="telemetry.core.tab.html">telemetry.core.tab</a><br>
+</td><td width="25%" valign=top><a href="urllib2.html">urllib2</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+<a href="weakref.html">weakref</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.tab_list_backend.html#TabListBackend">TabListBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TabListBackend">class <strong>TabListBackend</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TabListBackend-ActivateTab"><strong>ActivateTab</strong></a>(self, debugger_url, timeout<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="TabListBackend-CloseTab"><strong>CloseTab</strong></a>(self, debugger_url, timeout<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="TabListBackend-DoesDebuggerUrlExist"><strong>DoesDebuggerUrlExist</strong></a>(self, debugger_url)</dt></dl>
+
+<dl><dt><a name="TabListBackend-Get"><strong>Get</strong></a>(self, index, ret)</dt><dd><tt>Returns&nbsp;self[index]&nbsp;if&nbsp;it&nbsp;exists,&nbsp;or&nbsp;ret&nbsp;if&nbsp;index&nbsp;is&nbsp;out&nbsp;of&nbsp;bounds.</tt></dd></dl>
+
+<dl><dt><a name="TabListBackend-GetTabUrl"><strong>GetTabUrl</strong></a>(self, debugger_url)</dt></dl>
+
+<dl><dt><a name="TabListBackend-Init"><strong>Init</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabListBackend-New"><strong>New</strong></a>(self, timeout)</dt></dl>
+
+<dl><dt><a name="TabListBackend-__getitem__"><strong>__getitem__</strong></a>(self, index)</dt></dl>
+
+<dl><dt><a name="TabListBackend-__init__"><strong>__init__</strong></a>(self, browser_backend)</dt></dl>
+
+<dl><dt><a name="TabListBackend-__iter__"><strong>__iter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabListBackend-__len__"><strong>__len__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.trace_result.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.trace_result.html
new file mode 100644
index 00000000000..92569ba3d18
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.trace_result.html
@@ -0,0 +1,54 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.trace_result</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.trace_result</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/trace_result.py">telemetry/core/chrome/trace_result.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.trace_result.html#TraceResult">TraceResult</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TraceResult">class <strong>TraceResult</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TraceResult-AsTimelineModel"><strong>AsTimelineModel</strong></a>(self)</dt><dd><tt>Parses&nbsp;the&nbsp;trace&nbsp;result&nbsp;into&nbsp;a&nbsp;timeline&nbsp;model&nbsp;for&nbsp;in-memory<br>
+manipulation.</tt></dd></dl>
+
+<dl><dt><a name="TraceResult-Serialize"><strong>Serialize</strong></a>(self, f)</dt><dd><tt>Serializes&nbsp;the&nbsp;trace&nbsp;result&nbsp;to&nbsp;a&nbsp;file-like&nbsp;<a href="__builtin__.html#object">object</a></tt></dd></dl>
+
+<dl><dt><a name="TraceResult-__init__"><strong>__init__</strong></a>(self, impl)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.tracing_backend.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.tracing_backend.html
new file mode 100644
index 00000000000..e1e7a7fa6e2
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.tracing_backend.html
@@ -0,0 +1,160 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.tracing_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.tracing_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/tracing_backend.py">telemetry/core/chrome/tracing_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="cStringIO.html">cStringIO</a><br>
+<a href="json.html">json</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.model.html">telemetry.core.timeline.model</a><br>
+<a href="socket.html">socket</a><br>
+<a href="threading.html">threading</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.chrome.trace_result.html">telemetry.core.chrome.trace_result</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+<a href="telemetry.core.chrome.websocket.html">telemetry.core.chrome.websocket</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.tracing_backend.html#TraceResultImpl">TraceResultImpl</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.chrome.tracing_backend.html#TracingBackend">TracingBackend</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.chrome.tracing_backend.html#TracingUnsupportedException">TracingUnsupportedException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TraceResultImpl">class <strong>TraceResultImpl</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TraceResultImpl-AsTimelineModel"><strong>AsTimelineModel</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TraceResultImpl-Serialize"><strong>Serialize</strong></a>(self, f)</dt></dl>
+
+<dl><dt><a name="TraceResultImpl-__init__"><strong>__init__</strong></a>(self, tracing_data)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TracingBackend">class <strong>TracingBackend</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TracingBackend-BeginTracing"><strong>BeginTracing</strong></a>(self, custom_categories<font color="#909090">=None</font>, timeout<font color="#909090">=10</font>)</dt></dl>
+
+<dl><dt><a name="TracingBackend-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TracingBackend-EndTracing"><strong>EndTracing</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TracingBackend-GetTraceResultAndReset"><strong>GetTraceResultAndReset</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TracingBackend-__init__"><strong>__init__</strong></a>(self, devtools_port)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TracingUnsupportedException">class <strong>TracingUnsupportedException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.chrome.tracing_backend.html#TracingUnsupportedException">TracingUnsupportedException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="TracingUnsupportedException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#TracingUnsupportedException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#TracingUnsupportedException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="TracingUnsupportedException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#TracingUnsupportedException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#TracingUnsupportedException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#TracingUnsupportedException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#TracingUnsupportedException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#TracingUnsupportedException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#TracingUnsupportedException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#TracingUnsupportedException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="TracingUnsupportedException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.chrome.websocket.html b/chromium/tools/telemetry/docs/telemetry.core.chrome.websocket.html
new file mode 100644
index 00000000000..a752b8a484c
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.chrome.websocket.html
@@ -0,0 +1,40 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.chrome.websocket</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.chrome.html"><font color="#ffffff">chrome</font></a>.websocket</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/chrome/websocket.py">telemetry/core/chrome/websocket.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-__init__"><strong>__init__</strong></a>()</dt></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>absolute_import</strong> = _Feature((2, 5, 0, 'alpha', 1), (2, 7, 0, 'alpha', 0), 16384)</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.discover.html b/chromium/tools/telemetry/docs/telemetry.core.discover.html
new file mode 100644
index 00000000000..ef3323605f9
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.discover.html
@@ -0,0 +1,55 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.discover</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.discover</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/discover.py">telemetry/core/discover.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="fnmatch.html">fnmatch</a><br>
+</td><td width="25%" valign=top><a href="inspect.html">inspect</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="re.html">re</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-DiscoverClasses"><strong>DiscoverClasses</strong></a>(start_dir, top_level_dir, base_class, pattern<font color="#909090">='*'</font>, index_by_class_name<font color="#909090">=False</font>)</dt><dd><tt>Discover&nbsp;all&nbsp;classes&nbsp;in&nbsp;|start_dir|&nbsp;which&nbsp;subclass&nbsp;|base_class|.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;start_dir:&nbsp;The&nbsp;directory&nbsp;to&nbsp;recursively&nbsp;search.<br>
+&nbsp;&nbsp;top_level_dir:&nbsp;The&nbsp;top&nbsp;level&nbsp;of&nbsp;the&nbsp;package,&nbsp;for&nbsp;importing.<br>
+&nbsp;&nbsp;base_class:&nbsp;The&nbsp;base&nbsp;class&nbsp;to&nbsp;search&nbsp;for.<br>
+&nbsp;&nbsp;pattern:&nbsp;Unix&nbsp;shell-style&nbsp;pattern&nbsp;for&nbsp;filtering&nbsp;the&nbsp;filenames&nbsp;to&nbsp;import.<br>
+&nbsp;&nbsp;index_by_class_name:&nbsp;If&nbsp;True,&nbsp;use&nbsp;class&nbsp;name&nbsp;converted&nbsp;to<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lowercase_with_underscores&nbsp;instead&nbsp;of&nbsp;module&nbsp;name&nbsp;in&nbsp;return&nbsp;dict&nbsp;keys.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;dict&nbsp;of&nbsp;{module_name:&nbsp;class}&nbsp;or&nbsp;{underscored_class_name:&nbsp;class}</tt></dd></dl>
+ <dl><dt><a name="-DiscoverModules"><strong>DiscoverModules</strong></a>(start_dir, top_level_dir, pattern<font color="#909090">='*'</font>)</dt><dd><tt>Discover&nbsp;all&nbsp;modules&nbsp;in&nbsp;|start_dir|&nbsp;which&nbsp;match&nbsp;|pattern|.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;start_dir:&nbsp;The&nbsp;directory&nbsp;to&nbsp;recursively&nbsp;search.<br>
+&nbsp;&nbsp;top_level_dir:&nbsp;The&nbsp;top&nbsp;level&nbsp;of&nbsp;the&nbsp;package,&nbsp;for&nbsp;importing.<br>
+&nbsp;&nbsp;pattern:&nbsp;Unix&nbsp;shell-style&nbsp;pattern&nbsp;for&nbsp;filtering&nbsp;the&nbsp;filenames&nbsp;to&nbsp;import.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;list&nbsp;of&nbsp;modules.</tt></dd></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.exceptions.html b/chromium/tools/telemetry/docs/telemetry.core.exceptions.html
new file mode 100644
index 00000000000..04e4ba13052
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.exceptions.html
@@ -0,0 +1,338 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.exceptions</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.exceptions</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/exceptions.py">telemetry/core/exceptions.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.exceptions.html#BrowserGoneException">BrowserGoneException</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.exceptions.html#BrowserConnectionGoneException">BrowserConnectionGoneException</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="telemetry.core.exceptions.html#EvaluateException">EvaluateException</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.exceptions.html#LoginException">LoginException</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.exceptions.html#TabCrashException">TabCrashException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BrowserConnectionGoneException">class <strong>BrowserConnectionGoneException</strong></a>(<a href="telemetry.core.exceptions.html#BrowserGoneException">BrowserGoneException</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.exceptions.html#BrowserConnectionGoneException">BrowserConnectionGoneException</a></dd>
+<dd><a href="telemetry.core.exceptions.html#BrowserGoneException">BrowserGoneException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors inherited from <a href="telemetry.core.exceptions.html#BrowserGoneException">BrowserGoneException</a>:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="BrowserConnectionGoneException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserConnectionGoneException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#BrowserConnectionGoneException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="BrowserConnectionGoneException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserConnectionGoneException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserConnectionGoneException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserConnectionGoneException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserConnectionGoneException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserConnectionGoneException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserConnectionGoneException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserConnectionGoneException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="BrowserConnectionGoneException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BrowserGoneException">class <strong>BrowserGoneException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;a&nbsp;crash&nbsp;of&nbsp;the&nbsp;entire&nbsp;browser.<br>
+&nbsp;<br>
+In&nbsp;this&nbsp;state,&nbsp;all&nbsp;bets&nbsp;are&nbsp;pretty&nbsp;much&nbsp;off.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.exceptions.html#BrowserGoneException">BrowserGoneException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="BrowserGoneException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserGoneException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#BrowserGoneException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="BrowserGoneException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserGoneException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="BrowserGoneException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserGoneException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="BrowserGoneException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserGoneException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="BrowserGoneException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserGoneException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="BrowserGoneException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="BrowserGoneException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserGoneException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="BrowserGoneException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserGoneException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="BrowserGoneException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="BrowserGoneException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#BrowserGoneException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="BrowserGoneException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="EvaluateException">class <strong>EvaluateException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.exceptions.html#EvaluateException">EvaluateException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="EvaluateException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#EvaluateException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#EvaluateException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="EvaluateException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#EvaluateException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="EvaluateException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#EvaluateException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="EvaluateException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#EvaluateException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="EvaluateException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#EvaluateException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="EvaluateException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="EvaluateException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#EvaluateException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="EvaluateException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#EvaluateException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="EvaluateException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="EvaluateException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#EvaluateException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="EvaluateException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="LoginException">class <strong>LoginException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.exceptions.html#LoginException">LoginException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="LoginException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#LoginException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="LoginException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="LoginException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="LoginException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#LoginException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="LoginException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TabCrashException">class <strong>TabCrashException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;a&nbsp;crash&nbsp;of&nbsp;the&nbsp;current&nbsp;tab,&nbsp;but&nbsp;not&nbsp;the&nbsp;overall&nbsp;browser.<br>
+&nbsp;<br>
+In&nbsp;this&nbsp;state,&nbsp;the&nbsp;tab&nbsp;is&nbsp;gone,&nbsp;but&nbsp;the&nbsp;underlying&nbsp;browser&nbsp;is&nbsp;still&nbsp;alive.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.exceptions.html#TabCrashException">TabCrashException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="TabCrashException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#TabCrashException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#TabCrashException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="TabCrashException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#TabCrashException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="TabCrashException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#TabCrashException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="TabCrashException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#TabCrashException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="TabCrashException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#TabCrashException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="TabCrashException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="TabCrashException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#TabCrashException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="TabCrashException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#TabCrashException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="TabCrashException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="TabCrashException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#TabCrashException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="TabCrashException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.extension_dict.html b/chromium/tools/telemetry/docs/telemetry.core.extension_dict.html
new file mode 100644
index 00000000000..fd91c364a01
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.extension_dict.html
@@ -0,0 +1,64 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.extension_dict</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.extension_dict</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/extension_dict.py">telemetry/core/extension_dict.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.extension_to_load.html">telemetry.core.extension_to_load</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.extension_dict.html#ExtensionDict">ExtensionDict</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ExtensionDict">class <strong>ExtensionDict</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Dictionary&nbsp;of&nbsp;ExtensionPage&nbsp;instances,&nbsp;with&nbsp;extension_id&nbsp;as&nbsp;key<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="ExtensionDict-__contains__"><strong>__contains__</strong></a>(self, load_extension)</dt><dd><tt>Checks&nbsp;if&nbsp;this&nbsp;ExtensionToLoad&nbsp;instance&nbsp;has&nbsp;been&nbsp;loaded</tt></dd></dl>
+
+<dl><dt><a name="ExtensionDict-__getitem__"><strong>__getitem__</strong></a>(self, load_extension)</dt><dd><tt>Given&nbsp;an&nbsp;ExtensionToLoad&nbsp;instance,&nbsp;returns&nbsp;the&nbsp;corresponding<br>
+ExtensionPage&nbsp;instance.</tt></dd></dl>
+
+<dl><dt><a name="ExtensionDict-__init__"><strong>__init__</strong></a>(self, extension_dict_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.extension_page.html b/chromium/tools/telemetry/docs/telemetry.core.extension_page.html
new file mode 100644
index 00000000000..49b0f32bbc3
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.extension_page.html
@@ -0,0 +1,103 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.extension_page</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.extension_page</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/extension_page.py">telemetry/core/extension_page.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.web_contents.html">telemetry.core.web_contents</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.extension_page.html#ExtensionPage">ExtensionPage</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ExtensionPage">class <strong>ExtensionPage</strong></a>(<a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;a&nbsp;an&nbsp;extension&nbsp;page&nbsp;in&nbsp;the&nbsp;browser<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.extension_page.html#ExtensionPage">ExtensionPage</a></dd>
+<dd><a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ExtensionPage-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ExtensionPage-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>:<br>
+<dl><dt><a name="ExtensionPage-Close"><strong>Close</strong></a>(self)</dt><dd><tt>Closes&nbsp;this&nbsp;page.<br>
+&nbsp;<br>
+Not&nbsp;all&nbsp;browsers&nbsp;or&nbsp;browser&nbsp;versions&nbsp;support&nbsp;this&nbsp;method.<br>
+Be&nbsp;sure&nbsp;to&nbsp;check&nbsp;browser.supports_tab_control.</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPage-Disconnect"><strong>Disconnect</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ExtensionPage-EvaluateJavaScript"><strong>EvaluateJavaScript</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Evalutes&nbsp;expr&nbsp;in&nbsp;JavaScript&nbsp;and&nbsp;returns&nbsp;the&nbsp;JSONized&nbsp;result.<br>
+&nbsp;<br>
+Consider&nbsp;using&nbsp;ExecuteJavaScript&nbsp;for&nbsp;cases&nbsp;where&nbsp;the&nbsp;result&nbsp;of&nbsp;the<br>
+expression&nbsp;is&nbsp;not&nbsp;needed.<br>
+&nbsp;<br>
+If&nbsp;evaluation&nbsp;throws&nbsp;in&nbsp;JavaScript,&nbsp;a&nbsp;Python&nbsp;EvaluateException&nbsp;will<br>
+be&nbsp;raised.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;result&nbsp;of&nbsp;the&nbsp;evaluation&nbsp;cannot&nbsp;be&nbsp;JSONized,&nbsp;then&nbsp;an<br>
+EvaluationException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPage-ExecuteJavaScript"><strong>ExecuteJavaScript</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Executes&nbsp;expr&nbsp;in&nbsp;JavaScript.&nbsp;Does&nbsp;not&nbsp;return&nbsp;the&nbsp;result.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;expression&nbsp;failed&nbsp;to&nbsp;evaluate,&nbsp;EvaluateException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPage-StartTimelineRecording"><strong>StartTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ExtensionPage-StopTimelineRecording"><strong>StopTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ExtensionPage-WaitForDocumentReadyStateToBeComplete"><strong>WaitForDocumentReadyStateToBeComplete</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<dl><dt><a name="ExtensionPage-WaitForDocumentReadyStateToBeInteractiveOrBetter"><strong>WaitForDocumentReadyStateToBeInteractiveOrBetter</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>message_output_stream</strong></dt>
+</dl>
+<dl><dt><strong>timeline_model</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.extension_to_load.html b/chromium/tools/telemetry/docs/telemetry.core.extension_to_load.html
new file mode 100644
index 00000000000..280afdf9fe7
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.extension_to_load.html
@@ -0,0 +1,194 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.extension_to_load</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.extension_to_load</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/extension_to_load.py">telemetry/core/extension_to_load.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.chrome.crx_id.html">telemetry.core.chrome.crx_id</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.extension_to_load.html#ExtensionToLoad">ExtensionToLoad</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.extension_to_load.html#ExtensionPathNonExistentException">ExtensionPathNonExistentException</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.extension_to_load.html#MissingPublicKeyException">MissingPublicKeyException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ExtensionPathNonExistentException">class <strong>ExtensionPathNonExistentException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.extension_to_load.html#ExtensionPathNonExistentException">ExtensionPathNonExistentException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="ExtensionPathNonExistentException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionPathNonExistentException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#ExtensionPathNonExistentException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="ExtensionPathNonExistentException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionPathNonExistentException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionPathNonExistentException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionPathNonExistentException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionPathNonExistentException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionPathNonExistentException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionPathNonExistentException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#ExtensionPathNonExistentException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="ExtensionPathNonExistentException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ExtensionToLoad">class <strong>ExtensionToLoad</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="ExtensionToLoad-__init__"><strong>__init__</strong></a>(self, path, browser_type, is_component<font color="#909090">=False</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>extension_id</strong></dt>
+<dd><tt>Unique&nbsp;extension&nbsp;id&nbsp;of&nbsp;this&nbsp;extension.</tt></dd>
+</dl>
+<dl><dt><strong>is_component</strong></dt>
+<dd><tt>Whether&nbsp;this&nbsp;extension&nbsp;should&nbsp;be&nbsp;loaded&nbsp;as&nbsp;a&nbsp;component&nbsp;extension.</tt></dd>
+</dl>
+<dl><dt><strong>local_path</strong></dt>
+<dd><tt>Path&nbsp;to&nbsp;extension&nbsp;destination&nbsp;directory,&nbsp;for&nbsp;remote&nbsp;instances&nbsp;of<br>
+chrome</tt></dd>
+</dl>
+<dl><dt><strong>path</strong></dt>
+<dd><tt>Path&nbsp;to&nbsp;extension&nbsp;source&nbsp;directory.</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MissingPublicKeyException">class <strong>MissingPublicKeyException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.extension_to_load.html#MissingPublicKeyException">MissingPublicKeyException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="MissingPublicKeyException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingPublicKeyException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#MissingPublicKeyException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="MissingPublicKeyException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingPublicKeyException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingPublicKeyException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingPublicKeyException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingPublicKeyException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingPublicKeyException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingPublicKeyException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#MissingPublicKeyException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="MissingPublicKeyException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.html b/chromium/tools/telemetry/docs/telemetry.core.html
new file mode 100644
index 00000000000..86325f94744
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.html
@@ -0,0 +1,57 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry.core</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.core</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/__init__.py">telemetry/core/__init__.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser.html">browser</a><br>
+<a href="telemetry.core.browser_credentials.html">browser_credentials</a><br>
+<a href="telemetry.core.browser_credentials_unittest.html">browser_credentials_unittest</a><br>
+<a href="telemetry.core.browser_finder.html">browser_finder</a><br>
+<a href="telemetry.core.browser_options.html">browser_options</a><br>
+<a href="telemetry.core.browser_options_unittest.html">browser_options_unittest</a><br>
+<a href="telemetry.core.browser_unittest.html">browser_unittest</a><br>
+<a href="telemetry.core.chrome.html"><strong>chrome</strong>&nbsp;(package)</a><br>
+<a href="telemetry.core.discover.html">discover</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.discover_unittest.html">discover_unittest</a><br>
+<a href="telemetry.core.exceptions.html">exceptions</a><br>
+<a href="telemetry.core.extension_dict.html">extension_dict</a><br>
+<a href="telemetry.core.extension_page.html">extension_page</a><br>
+<a href="telemetry.core.extension_to_load.html">extension_to_load</a><br>
+<a href="telemetry.core.extension_unittest.html">extension_unittest</a><br>
+<a href="telemetry.core.memory_cache_http_server.html">memory_cache_http_server</a><br>
+<a href="telemetry.core.platform.html"><strong>platform</strong>&nbsp;(package)</a><br>
+<a href="telemetry.core.possible_browser.html">possible_browser</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.profile_creator.html">profile_creator</a><br>
+<a href="telemetry.core.profile_types.html">profile_types</a><br>
+<a href="telemetry.core.profile_types_unittest.html">profile_types_unittest</a><br>
+<a href="telemetry.core.tab.html">tab</a><br>
+<a href="telemetry.core.tab_list.html">tab_list</a><br>
+<a href="telemetry.core.tab_unittest.html">tab_unittest</a><br>
+<a href="telemetry.core.temporary_http_server.html">temporary_http_server</a><br>
+<a href="telemetry.core.temporary_http_server_unittest.html">temporary_http_server_unittest</a><br>
+<a href="telemetry.core.timeline.html"><strong>timeline</strong>&nbsp;(package)</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.user_agent.html">user_agent</a><br>
+<a href="telemetry.core.user_agent_unittest.html">user_agent_unittest</a><br>
+<a href="telemetry.core.util.html">util</a><br>
+<a href="telemetry.core.util_unittest.html">util_unittest</a><br>
+<a href="telemetry.core.web_contents.html">web_contents</a><br>
+<a href="telemetry.core.wpr_modes.html">wpr_modes</a><br>
+<a href="telemetry.core.wpr_server.html">wpr_server</a><br>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.memory_cache_http_server.html b/chromium/tools/telemetry/docs/telemetry.core.memory_cache_http_server.html
new file mode 100644
index 00000000000..de53df5e93f
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.memory_cache_http_server.html
@@ -0,0 +1,560 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.memory_cache_http_server</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.memory_cache_http_server</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/memory_cache_http_server.py">telemetry/core/memory_cache_http_server.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="BaseHTTPServer.html">BaseHTTPServer</a><br>
+<a href="SimpleHTTPServer.html">SimpleHTTPServer</a><br>
+</td><td width="25%" valign=top><a href="SocketServer.html">SocketServer</a><br>
+<a href="StringIO.html">StringIO</a><br>
+</td><td width="25%" valign=top><a href="gzip.html">gzip</a><br>
+<a href="mimetypes.html">mimetypes</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="sys.html">sys</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="BaseHTTPServer.html#HTTPServer">BaseHTTPServer.HTTPServer</a>(<a href="SocketServer.html#TCPServer">SocketServer.TCPServer</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.memory_cache_http_server.html#MemoryCacheHTTPServer">MemoryCacheHTTPServer</a>(<a href="SocketServer.html#ThreadingMixIn">SocketServer.ThreadingMixIn</a>, <a href="BaseHTTPServer.html#HTTPServer">BaseHTTPServer.HTTPServer</a>)
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="SimpleHTTPServer.html#SimpleHTTPRequestHandler">SimpleHTTPServer.SimpleHTTPRequestHandler</a>(<a href="BaseHTTPServer.html#BaseHTTPRequestHandler">BaseHTTPServer.BaseHTTPRequestHandler</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.memory_cache_http_server.html#MemoryCacheHTTPRequestHandler">MemoryCacheHTTPRequestHandler</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="SocketServer.html#ThreadingMixIn">SocketServer.ThreadingMixIn</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.memory_cache_http_server.html#MemoryCacheHTTPServer">MemoryCacheHTTPServer</a>(<a href="SocketServer.html#ThreadingMixIn">SocketServer.ThreadingMixIn</a>, <a href="BaseHTTPServer.html#HTTPServer">BaseHTTPServer.HTTPServer</a>)
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#tuple">__builtin__.tuple</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.memory_cache_http_server.html#ByteRange">ByteRange</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.core.memory_cache_http_server.html#ResourceAndRange">ResourceAndRange</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ByteRange">class <strong>ByteRange</strong></a>(<a href="__builtin__.html#tuple">__builtin__.tuple</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt><a href="#ByteRange">ByteRange</a>(from_byte,&nbsp;to_byte)<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.memory_cache_http_server.html#ByteRange">ByteRange</a></dd>
+<dd><a href="__builtin__.html#tuple">__builtin__.tuple</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ByteRange-__getnewargs__"><strong>__getnewargs__</strong></a>(self)</dt><dd><tt>Return&nbsp;self&nbsp;as&nbsp;a&nbsp;plain&nbsp;<a href="__builtin__.html#tuple">tuple</a>.&nbsp;&nbsp;Used&nbsp;by&nbsp;copy&nbsp;and&nbsp;pickle.</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__repr__"><strong>__repr__</strong></a>(self)</dt><dd><tt>Return&nbsp;a&nbsp;nicely&nbsp;formatted&nbsp;representation&nbsp;string</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-_asdict"><strong>_asdict</strong></a>(self)</dt><dd><tt>Return&nbsp;a&nbsp;new&nbsp;OrderedDict&nbsp;which&nbsp;maps&nbsp;field&nbsp;names&nbsp;to&nbsp;their&nbsp;values</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-_replace"><strong>_replace</strong></a>(_self, **kwds)</dt><dd><tt>Return&nbsp;a&nbsp;new&nbsp;<a href="#ByteRange">ByteRange</a>&nbsp;object&nbsp;replacing&nbsp;specified&nbsp;fields&nbsp;with&nbsp;new&nbsp;values</tt></dd></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="ByteRange-_make"><strong>_make</strong></a>(cls, iterable, new<font color="#909090">=&lt;built-in method __new__ of type object&gt;</font>, len<font color="#909090">=&lt;built-in function len&gt;</font>)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>Make&nbsp;a&nbsp;new&nbsp;<a href="#ByteRange">ByteRange</a>&nbsp;object&nbsp;from&nbsp;a&nbsp;sequence&nbsp;or&nbsp;iterable</tt></dd></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="ByteRange-__new__"><strong>__new__</strong></a>(_cls, from_byte, to_byte)</dt><dd><tt>Create&nbsp;new&nbsp;instance&nbsp;of&nbsp;<a href="#ByteRange">ByteRange</a>(from_byte,&nbsp;to_byte)</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>from_byte</strong></dt>
+<dd><tt>Alias&nbsp;for&nbsp;field&nbsp;number&nbsp;0</tt></dd>
+</dl>
+<dl><dt><strong>to_byte</strong></dt>
+<dd><tt>Alias&nbsp;for&nbsp;field&nbsp;number&nbsp;1</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>_fields</strong> = ('from_byte', 'to_byte')</dl>
+
+<hr>
+Methods inherited from <a href="__builtin__.html#tuple">__builtin__.tuple</a>:<br>
+<dl><dt><a name="ByteRange-__add__"><strong>__add__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__add__">__add__</a>(y)&nbsp;&lt;==&gt;&nbsp;x+y</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__contains__"><strong>__contains__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__contains__">__contains__</a>(y)&nbsp;&lt;==&gt;&nbsp;y&nbsp;in&nbsp;x</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__eq__"><strong>__eq__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__eq__">__eq__</a>(y)&nbsp;&lt;==&gt;&nbsp;x==y</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__ge__"><strong>__ge__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__ge__">__ge__</a>(y)&nbsp;&lt;==&gt;&nbsp;x&gt;=y</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__gt__"><strong>__gt__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__gt__">__gt__</a>(y)&nbsp;&lt;==&gt;&nbsp;x&gt;y</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__hash__"><strong>__hash__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__hash__">__hash__</a>()&nbsp;&lt;==&gt;&nbsp;hash(x)</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__iter__"><strong>__iter__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__iter__">__iter__</a>()&nbsp;&lt;==&gt;&nbsp;iter(x)</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__le__"><strong>__le__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__le__">__le__</a>(y)&nbsp;&lt;==&gt;&nbsp;x&lt;=y</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__len__"><strong>__len__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__len__">__len__</a>()&nbsp;&lt;==&gt;&nbsp;len(x)</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__lt__"><strong>__lt__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__lt__">__lt__</a>(y)&nbsp;&lt;==&gt;&nbsp;x&lt;y</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__mul__"><strong>__mul__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__mul__">__mul__</a>(n)&nbsp;&lt;==&gt;&nbsp;x*n</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__ne__"><strong>__ne__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__ne__">__ne__</a>(y)&nbsp;&lt;==&gt;&nbsp;x!=y</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__rmul__"><strong>__rmul__</strong></a>(...)</dt><dd><tt>x.<a href="#ByteRange-__rmul__">__rmul__</a>(n)&nbsp;&lt;==&gt;&nbsp;n*x</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-__sizeof__"><strong>__sizeof__</strong></a>(...)</dt><dd><tt>T.<a href="#ByteRange-__sizeof__">__sizeof__</a>()&nbsp;--&nbsp;size&nbsp;of&nbsp;T&nbsp;in&nbsp;memory,&nbsp;in&nbsp;bytes</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-count"><strong>count</strong></a>(...)</dt><dd><tt>T.<a href="#ByteRange-count">count</a>(value)&nbsp;-&gt;&nbsp;integer&nbsp;--&nbsp;return&nbsp;number&nbsp;of&nbsp;occurrences&nbsp;of&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="ByteRange-index"><strong>index</strong></a>(...)</dt><dd><tt>T.<a href="#ByteRange-index">index</a>(value,&nbsp;[start,&nbsp;[stop]])&nbsp;-&gt;&nbsp;integer&nbsp;--&nbsp;return&nbsp;first&nbsp;index&nbsp;of&nbsp;value.<br>
+Raises&nbsp;ValueError&nbsp;if&nbsp;the&nbsp;value&nbsp;is&nbsp;not&nbsp;present.</tt></dd></dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MemoryCacheHTTPRequestHandler">class <strong>MemoryCacheHTTPRequestHandler</strong></a>(<a href="SimpleHTTPServer.html#SimpleHTTPRequestHandler">SimpleHTTPServer.SimpleHTTPRequestHandler</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.memory_cache_http_server.html#MemoryCacheHTTPRequestHandler">MemoryCacheHTTPRequestHandler</a></dd>
+<dd><a href="SimpleHTTPServer.html#SimpleHTTPRequestHandler">SimpleHTTPServer.SimpleHTTPRequestHandler</a></dd>
+<dd><a href="BaseHTTPServer.html#BaseHTTPRequestHandler">BaseHTTPServer.BaseHTTPRequestHandler</a></dd>
+<dd><a href="SocketServer.html#StreamRequestHandler">SocketServer.StreamRequestHandler</a></dd>
+<dd><a href="SocketServer.html#BaseRequestHandler">SocketServer.BaseRequestHandler</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-GetByteRange"><strong>GetByteRange</strong></a>(self, total_num_of_bytes)</dt><dd><tt>Parse&nbsp;the&nbsp;header&nbsp;and&nbsp;get&nbsp;the&nbsp;range&nbsp;values&nbsp;specified.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;total_num_of_bytes:&nbsp;Total&nbsp;#&nbsp;of&nbsp;bytes&nbsp;in&nbsp;requested&nbsp;resource,<br>
+&nbsp;&nbsp;used&nbsp;to&nbsp;calculate&nbsp;upper&nbsp;range&nbsp;limit.<br>
+Returns:<br>
+&nbsp;&nbsp;A&nbsp;<a href="#ByteRange">ByteRange</a>&nbsp;namedtuple&nbsp;object&nbsp;with&nbsp;the&nbsp;requested&nbsp;byte-range&nbsp;values.<br>
+&nbsp;&nbsp;If&nbsp;no&nbsp;Range&nbsp;is&nbsp;explicitly&nbsp;requested&nbsp;or&nbsp;there&nbsp;is&nbsp;a&nbsp;failure&nbsp;parsing,<br>
+&nbsp;&nbsp;return&nbsp;None.<br>
+&nbsp;&nbsp;Special&nbsp;case:&nbsp;If&nbsp;range&nbsp;specified&nbsp;is&nbsp;in&nbsp;the&nbsp;format&nbsp;"N-",&nbsp;return&nbsp;N-N.<br>
+&nbsp;&nbsp;If&nbsp;upper&nbsp;range&nbsp;limit&nbsp;is&nbsp;greater&nbsp;than&nbsp;total&nbsp;#&nbsp;of&nbsp;bytes,&nbsp;return&nbsp;upper&nbsp;index.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-SendHead"><strong>SendHead</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-do_GET"><strong>do_GET</strong></a>(self)</dt><dd><tt>Serve&nbsp;a&nbsp;GET&nbsp;request.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-do_HEAD"><strong>do_HEAD</strong></a>(self)</dt><dd><tt>Serve&nbsp;a&nbsp;HEAD&nbsp;request.</tt></dd></dl>
+
+<hr>
+Methods inherited from <a href="SimpleHTTPServer.html#SimpleHTTPRequestHandler">SimpleHTTPServer.SimpleHTTPRequestHandler</a>:<br>
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-copyfile"><strong>copyfile</strong></a>(self, source, outputfile)</dt><dd><tt>Copy&nbsp;all&nbsp;data&nbsp;between&nbsp;two&nbsp;file&nbsp;objects.<br>
+&nbsp;<br>
+The&nbsp;SOURCE&nbsp;argument&nbsp;is&nbsp;a&nbsp;file&nbsp;object&nbsp;open&nbsp;for&nbsp;reading<br>
+(or&nbsp;anything&nbsp;with&nbsp;a&nbsp;read()&nbsp;method)&nbsp;and&nbsp;the&nbsp;DESTINATION<br>
+argument&nbsp;is&nbsp;a&nbsp;file&nbsp;object&nbsp;open&nbsp;for&nbsp;writing&nbsp;(or<br>
+anything&nbsp;with&nbsp;a&nbsp;write()&nbsp;method).<br>
+&nbsp;<br>
+The&nbsp;only&nbsp;reason&nbsp;for&nbsp;overriding&nbsp;this&nbsp;would&nbsp;be&nbsp;to&nbsp;change<br>
+the&nbsp;block&nbsp;size&nbsp;or&nbsp;perhaps&nbsp;to&nbsp;replace&nbsp;newlines&nbsp;by&nbsp;CRLF<br>
+--&nbsp;note&nbsp;however&nbsp;that&nbsp;this&nbsp;the&nbsp;default&nbsp;server&nbsp;uses&nbsp;this<br>
+to&nbsp;copy&nbsp;binary&nbsp;data&nbsp;as&nbsp;well.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-guess_type"><strong>guess_type</strong></a>(self, path)</dt><dd><tt>Guess&nbsp;the&nbsp;type&nbsp;of&nbsp;a&nbsp;file.<br>
+&nbsp;<br>
+Argument&nbsp;is&nbsp;a&nbsp;PATH&nbsp;(a&nbsp;filename).<br>
+&nbsp;<br>
+Return&nbsp;value&nbsp;is&nbsp;a&nbsp;string&nbsp;of&nbsp;the&nbsp;form&nbsp;type/subtype,<br>
+usable&nbsp;for&nbsp;a&nbsp;MIME&nbsp;Content-type&nbsp;header.<br>
+&nbsp;<br>
+The&nbsp;default&nbsp;implementation&nbsp;looks&nbsp;the&nbsp;file's&nbsp;extension<br>
+up&nbsp;in&nbsp;the&nbsp;table&nbsp;self.<strong>extensions_map</strong>,&nbsp;using&nbsp;application/octet-stream<br>
+as&nbsp;a&nbsp;default;&nbsp;however&nbsp;it&nbsp;would&nbsp;be&nbsp;permissible&nbsp;(if<br>
+slow)&nbsp;to&nbsp;look&nbsp;inside&nbsp;the&nbsp;data&nbsp;to&nbsp;make&nbsp;a&nbsp;better&nbsp;guess.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-list_directory"><strong>list_directory</strong></a>(self, path)</dt><dd><tt>Helper&nbsp;to&nbsp;produce&nbsp;a&nbsp;directory&nbsp;listing&nbsp;(absent&nbsp;index.html).<br>
+&nbsp;<br>
+Return&nbsp;value&nbsp;is&nbsp;either&nbsp;a&nbsp;file&nbsp;object,&nbsp;or&nbsp;None&nbsp;(indicating&nbsp;an<br>
+error).&nbsp;&nbsp;In&nbsp;either&nbsp;case,&nbsp;the&nbsp;headers&nbsp;are&nbsp;sent,&nbsp;making&nbsp;the<br>
+interface&nbsp;the&nbsp;same&nbsp;as&nbsp;for&nbsp;<a href="#MemoryCacheHTTPRequestHandler-send_head">send_head</a>().</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-send_head"><strong>send_head</strong></a>(self)</dt><dd><tt>Common&nbsp;code&nbsp;for&nbsp;GET&nbsp;and&nbsp;HEAD&nbsp;commands.<br>
+&nbsp;<br>
+This&nbsp;sends&nbsp;the&nbsp;response&nbsp;code&nbsp;and&nbsp;MIME&nbsp;headers.<br>
+&nbsp;<br>
+Return&nbsp;value&nbsp;is&nbsp;either&nbsp;a&nbsp;file&nbsp;object&nbsp;(which&nbsp;has&nbsp;to&nbsp;be&nbsp;copied<br>
+to&nbsp;the&nbsp;outputfile&nbsp;by&nbsp;the&nbsp;caller&nbsp;unless&nbsp;the&nbsp;command&nbsp;was&nbsp;HEAD,<br>
+and&nbsp;must&nbsp;be&nbsp;closed&nbsp;by&nbsp;the&nbsp;caller&nbsp;under&nbsp;all&nbsp;circumstances),&nbsp;or<br>
+None,&nbsp;in&nbsp;which&nbsp;case&nbsp;the&nbsp;caller&nbsp;has&nbsp;nothing&nbsp;further&nbsp;to&nbsp;do.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-translate_path"><strong>translate_path</strong></a>(self, path)</dt><dd><tt>Translate&nbsp;a&nbsp;/-separated&nbsp;PATH&nbsp;to&nbsp;the&nbsp;local&nbsp;filename&nbsp;syntax.<br>
+&nbsp;<br>
+Components&nbsp;that&nbsp;mean&nbsp;special&nbsp;things&nbsp;to&nbsp;the&nbsp;local&nbsp;file&nbsp;system<br>
+(e.g.&nbsp;drive&nbsp;or&nbsp;directory&nbsp;names)&nbsp;are&nbsp;ignored.&nbsp;&nbsp;(XXX&nbsp;They&nbsp;should<br>
+probably&nbsp;be&nbsp;diagnosed.)</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="SimpleHTTPServer.html#SimpleHTTPRequestHandler">SimpleHTTPServer.SimpleHTTPRequestHandler</a>:<br>
+<dl><dt><strong>extensions_map</strong> = {'': 'application/octet-stream', '.123': 'application/vnd.lotus-1-2-3', '.3dml': 'text/vnd.in3d.3dml', '.3g2': 'video/3gpp2', '.3gp': 'video/3gpp', '.7z': 'application/x-7z-compressed', '.a': 'application/octet-stream', '.aab': 'application/x-authorware-bin', '.aac': 'audio/x-aac', '.aam': 'application/x-authorware-map', ...}</dl>
+
+<dl><dt><strong>server_version</strong> = 'SimpleHTTP/0.6'</dl>
+
+<hr>
+Methods inherited from <a href="BaseHTTPServer.html#BaseHTTPRequestHandler">BaseHTTPServer.BaseHTTPRequestHandler</a>:<br>
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-address_string"><strong>address_string</strong></a>(self)</dt><dd><tt>Return&nbsp;the&nbsp;client&nbsp;address&nbsp;formatted&nbsp;for&nbsp;logging.<br>
+&nbsp;<br>
+This&nbsp;version&nbsp;looks&nbsp;up&nbsp;the&nbsp;full&nbsp;hostname&nbsp;using&nbsp;gethostbyaddr(),<br>
+and&nbsp;tries&nbsp;to&nbsp;find&nbsp;a&nbsp;name&nbsp;that&nbsp;contains&nbsp;at&nbsp;least&nbsp;one&nbsp;dot.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-date_time_string"><strong>date_time_string</strong></a>(self, timestamp<font color="#909090">=None</font>)</dt><dd><tt>Return&nbsp;the&nbsp;current&nbsp;date&nbsp;and&nbsp;time&nbsp;formatted&nbsp;for&nbsp;a&nbsp;message&nbsp;header.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-end_headers"><strong>end_headers</strong></a>(self)</dt><dd><tt>Send&nbsp;the&nbsp;blank&nbsp;line&nbsp;ending&nbsp;the&nbsp;MIME&nbsp;headers.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-handle"><strong>handle</strong></a>(self)</dt><dd><tt>Handle&nbsp;multiple&nbsp;requests&nbsp;if&nbsp;necessary.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-handle_one_request"><strong>handle_one_request</strong></a>(self)</dt><dd><tt>Handle&nbsp;a&nbsp;single&nbsp;HTTP&nbsp;request.<br>
+&nbsp;<br>
+You&nbsp;normally&nbsp;don't&nbsp;need&nbsp;to&nbsp;override&nbsp;this&nbsp;method;&nbsp;see&nbsp;the&nbsp;class<br>
+__doc__&nbsp;string&nbsp;for&nbsp;information&nbsp;on&nbsp;how&nbsp;to&nbsp;handle&nbsp;specific&nbsp;HTTP<br>
+commands&nbsp;such&nbsp;as&nbsp;GET&nbsp;and&nbsp;POST.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-log_date_time_string"><strong>log_date_time_string</strong></a>(self)</dt><dd><tt>Return&nbsp;the&nbsp;current&nbsp;time&nbsp;formatted&nbsp;for&nbsp;logging.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-log_error"><strong>log_error</strong></a>(self, format, *args)</dt><dd><tt>Log&nbsp;an&nbsp;error.<br>
+&nbsp;<br>
+This&nbsp;is&nbsp;called&nbsp;when&nbsp;a&nbsp;request&nbsp;cannot&nbsp;be&nbsp;fulfilled.&nbsp;&nbsp;By<br>
+default&nbsp;it&nbsp;passes&nbsp;the&nbsp;message&nbsp;on&nbsp;to&nbsp;<a href="#MemoryCacheHTTPRequestHandler-log_message">log_message</a>().<br>
+&nbsp;<br>
+Arguments&nbsp;are&nbsp;the&nbsp;same&nbsp;as&nbsp;for&nbsp;<a href="#MemoryCacheHTTPRequestHandler-log_message">log_message</a>().<br>
+&nbsp;<br>
+XXX&nbsp;This&nbsp;should&nbsp;go&nbsp;to&nbsp;the&nbsp;separate&nbsp;error&nbsp;log.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-log_message"><strong>log_message</strong></a>(self, format, *args)</dt><dd><tt>Log&nbsp;an&nbsp;arbitrary&nbsp;message.<br>
+&nbsp;<br>
+This&nbsp;is&nbsp;used&nbsp;by&nbsp;all&nbsp;other&nbsp;logging&nbsp;functions.&nbsp;&nbsp;Override<br>
+it&nbsp;if&nbsp;you&nbsp;have&nbsp;specific&nbsp;logging&nbsp;wishes.<br>
+&nbsp;<br>
+The&nbsp;first&nbsp;argument,&nbsp;FORMAT,&nbsp;is&nbsp;a&nbsp;format&nbsp;string&nbsp;for&nbsp;the<br>
+message&nbsp;to&nbsp;be&nbsp;logged.&nbsp;&nbsp;If&nbsp;the&nbsp;format&nbsp;string&nbsp;contains<br>
+any&nbsp;%&nbsp;escapes&nbsp;requiring&nbsp;parameters,&nbsp;they&nbsp;should&nbsp;be<br>
+specified&nbsp;as&nbsp;subsequent&nbsp;arguments&nbsp;(it's&nbsp;just&nbsp;like<br>
+printf!).<br>
+&nbsp;<br>
+The&nbsp;client&nbsp;host&nbsp;and&nbsp;current&nbsp;date/time&nbsp;are&nbsp;prefixed&nbsp;to<br>
+every&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-log_request"><strong>log_request</strong></a>(self, code<font color="#909090">='-'</font>, size<font color="#909090">='-'</font>)</dt><dd><tt>Log&nbsp;an&nbsp;accepted&nbsp;request.<br>
+&nbsp;<br>
+This&nbsp;is&nbsp;called&nbsp;by&nbsp;<a href="#MemoryCacheHTTPRequestHandler-send_response">send_response</a>().</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-parse_request"><strong>parse_request</strong></a>(self)</dt><dd><tt>Parse&nbsp;a&nbsp;request&nbsp;(internal).<br>
+&nbsp;<br>
+The&nbsp;request&nbsp;should&nbsp;be&nbsp;stored&nbsp;in&nbsp;self.<strong>raw_requestline</strong>;&nbsp;the&nbsp;results<br>
+are&nbsp;in&nbsp;self.<strong>command</strong>,&nbsp;self.<strong>path</strong>,&nbsp;self.<strong>request_version</strong>&nbsp;and<br>
+self.<strong>headers</strong>.<br>
+&nbsp;<br>
+Return&nbsp;True&nbsp;for&nbsp;success,&nbsp;False&nbsp;for&nbsp;failure;&nbsp;on&nbsp;failure,&nbsp;an<br>
+error&nbsp;is&nbsp;sent&nbsp;back.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-send_error"><strong>send_error</strong></a>(self, code, message<font color="#909090">=None</font>)</dt><dd><tt>Send&nbsp;and&nbsp;log&nbsp;an&nbsp;error&nbsp;reply.<br>
+&nbsp;<br>
+Arguments&nbsp;are&nbsp;the&nbsp;error&nbsp;code,&nbsp;and&nbsp;a&nbsp;detailed&nbsp;message.<br>
+The&nbsp;detailed&nbsp;message&nbsp;defaults&nbsp;to&nbsp;the&nbsp;short&nbsp;entry&nbsp;matching&nbsp;the<br>
+response&nbsp;code.<br>
+&nbsp;<br>
+This&nbsp;sends&nbsp;an&nbsp;error&nbsp;response&nbsp;(so&nbsp;it&nbsp;must&nbsp;be&nbsp;called&nbsp;before&nbsp;any<br>
+output&nbsp;has&nbsp;been&nbsp;generated),&nbsp;logs&nbsp;the&nbsp;error,&nbsp;and&nbsp;finally&nbsp;sends<br>
+a&nbsp;piece&nbsp;of&nbsp;HTML&nbsp;explaining&nbsp;the&nbsp;error&nbsp;to&nbsp;the&nbsp;user.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-send_header"><strong>send_header</strong></a>(self, keyword, value)</dt><dd><tt>Send&nbsp;a&nbsp;MIME&nbsp;header.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-send_response"><strong>send_response</strong></a>(self, code, message<font color="#909090">=None</font>)</dt><dd><tt>Send&nbsp;the&nbsp;response&nbsp;header&nbsp;and&nbsp;log&nbsp;the&nbsp;response&nbsp;code.<br>
+&nbsp;<br>
+Also&nbsp;send&nbsp;two&nbsp;standard&nbsp;headers&nbsp;with&nbsp;the&nbsp;server&nbsp;software<br>
+version&nbsp;and&nbsp;the&nbsp;current&nbsp;date.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-version_string"><strong>version_string</strong></a>(self)</dt><dd><tt>Return&nbsp;the&nbsp;server&nbsp;software&nbsp;version&nbsp;string.</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="BaseHTTPServer.html#BaseHTTPRequestHandler">BaseHTTPServer.BaseHTTPRequestHandler</a>:<br>
+<dl><dt><strong>MessageClass</strong> = &lt;class mimetools.Message&gt;</dl>
+
+<dl><dt><strong>default_request_version</strong> = 'HTTP/0.9'</dl>
+
+<dl><dt><strong>error_content_type</strong> = 'text/html'</dl>
+
+<dl><dt><strong>error_message_format</strong> = '&lt;head&gt;<font color="#c040c0">\n</font>&lt;title&gt;Error response&lt;/title&gt;<font color="#c040c0">\n</font>&lt;/head&gt;<font color="#c040c0">\n</font>&lt;bo...ode explanation: %(code)s = %(explain)s.<font color="#c040c0">\n</font>&lt;/body&gt;<font color="#c040c0">\n</font>'</dl>
+
+<dl><dt><strong>monthname</strong> = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']</dl>
+
+<dl><dt><strong>protocol_version</strong> = 'HTTP/1.0'</dl>
+
+<dl><dt><strong>responses</strong> = {100: ('Continue', 'Request received, please continue'), 101: ('Switching Protocols', 'Switching to new protocol; obey Upgrade header'), 200: ('OK', 'Request fulfilled, document follows'), 201: ('Created', 'Document created, URL follows'), 202: ('Accepted', 'Request accepted, processing continues off-line'), 203: ('Non-Authoritative Information', 'Request fulfilled from cache'), 204: ('No Content', 'Request fulfilled, nothing follows'), 205: ('Reset Content', 'Clear input form for further input.'), 206: ('Partial Content', 'Partial content follows.'), 300: ('Multiple Choices', 'Object has several resources -- see URI list'), ...}</dl>
+
+<dl><dt><strong>sys_version</strong> = 'Python/2.7.2'</dl>
+
+<dl><dt><strong>weekdayname</strong> = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']</dl>
+
+<hr>
+Methods inherited from <a href="SocketServer.html#StreamRequestHandler">SocketServer.StreamRequestHandler</a>:<br>
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-finish"><strong>finish</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-setup"><strong>setup</strong></a>(self)</dt></dl>
+
+<hr>
+Data and other attributes inherited from <a href="SocketServer.html#StreamRequestHandler">SocketServer.StreamRequestHandler</a>:<br>
+<dl><dt><strong>disable_nagle_algorithm</strong> = False</dl>
+
+<dl><dt><strong>rbufsize</strong> = -1</dl>
+
+<dl><dt><strong>timeout</strong> = None</dl>
+
+<dl><dt><strong>wbufsize</strong> = 0</dl>
+
+<hr>
+Methods inherited from <a href="SocketServer.html#BaseRequestHandler">SocketServer.BaseRequestHandler</a>:<br>
+<dl><dt><a name="MemoryCacheHTTPRequestHandler-__init__"><strong>__init__</strong></a>(self, request, client_address, server)</dt></dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MemoryCacheHTTPServer">class <strong>MemoryCacheHTTPServer</strong></a>(<a href="SocketServer.html#ThreadingMixIn">SocketServer.ThreadingMixIn</a>, <a href="BaseHTTPServer.html#HTTPServer">BaseHTTPServer.HTTPServer</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.memory_cache_http_server.html#MemoryCacheHTTPServer">MemoryCacheHTTPServer</a></dd>
+<dd><a href="SocketServer.html#ThreadingMixIn">SocketServer.ThreadingMixIn</a></dd>
+<dd><a href="BaseHTTPServer.html#HTTPServer">BaseHTTPServer.HTTPServer</a></dd>
+<dd><a href="SocketServer.html#TCPServer">SocketServer.TCPServer</a></dd>
+<dd><a href="SocketServer.html#BaseServer">SocketServer.BaseServer</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="MemoryCacheHTTPServer-AddDirectoryToResourceMap"><strong>AddDirectoryToResourceMap</strong></a>(self, directory_path)</dt><dd><tt>Loads&nbsp;all&nbsp;files&nbsp;in&nbsp;directory_path&nbsp;into&nbsp;the&nbsp;in-memory&nbsp;resource&nbsp;map.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-AddFileToResourceMap"><strong>AddFileToResourceMap</strong></a>(self, file_path)</dt><dd><tt>Loads&nbsp;file_path&nbsp;into&nbsp;the&nbsp;in-memory&nbsp;resource&nbsp;map.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-__init__"><strong>__init__</strong></a>(self, host_port, handler, paths)</dt></dl>
+
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>request_queue_size</strong> = 128</dl>
+
+<hr>
+Methods inherited from <a href="SocketServer.html#ThreadingMixIn">SocketServer.ThreadingMixIn</a>:<br>
+<dl><dt><a name="MemoryCacheHTTPServer-process_request"><strong>process_request</strong></a>(self, request, client_address)</dt><dd><tt>Start&nbsp;a&nbsp;new&nbsp;thread&nbsp;to&nbsp;process&nbsp;the&nbsp;request.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-process_request_thread"><strong>process_request_thread</strong></a>(self, request, client_address)</dt><dd><tt>Same&nbsp;as&nbsp;in&nbsp;BaseServer&nbsp;but&nbsp;as&nbsp;a&nbsp;thread.<br>
+&nbsp;<br>
+In&nbsp;addition,&nbsp;exception&nbsp;handling&nbsp;is&nbsp;done&nbsp;here.</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="SocketServer.html#ThreadingMixIn">SocketServer.ThreadingMixIn</a>:<br>
+<dl><dt><strong>daemon_threads</strong> = False</dl>
+
+<hr>
+Methods inherited from <a href="BaseHTTPServer.html#HTTPServer">BaseHTTPServer.HTTPServer</a>:<br>
+<dl><dt><a name="MemoryCacheHTTPServer-server_bind"><strong>server_bind</strong></a>(self)</dt><dd><tt>Override&nbsp;server_bind&nbsp;to&nbsp;store&nbsp;the&nbsp;server&nbsp;name.</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="BaseHTTPServer.html#HTTPServer">BaseHTTPServer.HTTPServer</a>:<br>
+<dl><dt><strong>allow_reuse_address</strong> = 1</dl>
+
+<hr>
+Methods inherited from <a href="SocketServer.html#TCPServer">SocketServer.TCPServer</a>:<br>
+<dl><dt><a name="MemoryCacheHTTPServer-close_request"><strong>close_request</strong></a>(self, request)</dt><dd><tt>Called&nbsp;to&nbsp;clean&nbsp;up&nbsp;an&nbsp;individual&nbsp;request.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-fileno"><strong>fileno</strong></a>(self)</dt><dd><tt>Return&nbsp;socket&nbsp;file&nbsp;number.<br>
+&nbsp;<br>
+Interface&nbsp;required&nbsp;by&nbsp;select().</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-get_request"><strong>get_request</strong></a>(self)</dt><dd><tt>Get&nbsp;the&nbsp;request&nbsp;and&nbsp;client&nbsp;address&nbsp;from&nbsp;the&nbsp;socket.<br>
+&nbsp;<br>
+May&nbsp;be&nbsp;overridden.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-server_activate"><strong>server_activate</strong></a>(self)</dt><dd><tt>Called&nbsp;by&nbsp;constructor&nbsp;to&nbsp;activate&nbsp;the&nbsp;server.<br>
+&nbsp;<br>
+May&nbsp;be&nbsp;overridden.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-server_close"><strong>server_close</strong></a>(self)</dt><dd><tt>Called&nbsp;to&nbsp;clean-up&nbsp;the&nbsp;server.<br>
+&nbsp;<br>
+May&nbsp;be&nbsp;overridden.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-shutdown_request"><strong>shutdown_request</strong></a>(self, request)</dt><dd><tt>Called&nbsp;to&nbsp;shutdown&nbsp;and&nbsp;close&nbsp;an&nbsp;individual&nbsp;request.</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="SocketServer.html#TCPServer">SocketServer.TCPServer</a>:<br>
+<dl><dt><strong>address_family</strong> = 2</dl>
+
+<dl><dt><strong>socket_type</strong> = 1</dl>
+
+<hr>
+Methods inherited from <a href="SocketServer.html#BaseServer">SocketServer.BaseServer</a>:<br>
+<dl><dt><a name="MemoryCacheHTTPServer-finish_request"><strong>finish_request</strong></a>(self, request, client_address)</dt><dd><tt>Finish&nbsp;one&nbsp;request&nbsp;by&nbsp;instantiating&nbsp;RequestHandlerClass.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-handle_error"><strong>handle_error</strong></a>(self, request, client_address)</dt><dd><tt>Handle&nbsp;an&nbsp;error&nbsp;gracefully.&nbsp;&nbsp;May&nbsp;be&nbsp;overridden.<br>
+&nbsp;<br>
+The&nbsp;default&nbsp;is&nbsp;to&nbsp;print&nbsp;a&nbsp;traceback&nbsp;and&nbsp;continue.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-handle_request"><strong>handle_request</strong></a>(self)</dt><dd><tt>Handle&nbsp;one&nbsp;request,&nbsp;possibly&nbsp;blocking.<br>
+&nbsp;<br>
+Respects&nbsp;self.<strong>timeout</strong>.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-handle_timeout"><strong>handle_timeout</strong></a>(self)</dt><dd><tt>Called&nbsp;if&nbsp;no&nbsp;new&nbsp;request&nbsp;arrives&nbsp;within&nbsp;self.<strong>timeout</strong>.<br>
+&nbsp;<br>
+Overridden&nbsp;by&nbsp;ForkingMixIn.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-serve_forever"><strong>serve_forever</strong></a>(self, poll_interval<font color="#909090">=0.5</font>)</dt><dd><tt>Handle&nbsp;one&nbsp;request&nbsp;at&nbsp;a&nbsp;time&nbsp;until&nbsp;shutdown.<br>
+&nbsp;<br>
+Polls&nbsp;for&nbsp;shutdown&nbsp;every&nbsp;poll_interval&nbsp;seconds.&nbsp;Ignores<br>
+self.<strong>timeout</strong>.&nbsp;If&nbsp;you&nbsp;need&nbsp;to&nbsp;do&nbsp;periodic&nbsp;tasks,&nbsp;do&nbsp;them&nbsp;in<br>
+another&nbsp;thread.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-shutdown"><strong>shutdown</strong></a>(self)</dt><dd><tt>Stops&nbsp;the&nbsp;serve_forever&nbsp;loop.<br>
+&nbsp;<br>
+Blocks&nbsp;until&nbsp;the&nbsp;loop&nbsp;has&nbsp;finished.&nbsp;This&nbsp;must&nbsp;be&nbsp;called&nbsp;while<br>
+<a href="#MemoryCacheHTTPServer-serve_forever">serve_forever</a>()&nbsp;is&nbsp;running&nbsp;in&nbsp;another&nbsp;thread,&nbsp;or&nbsp;it&nbsp;will<br>
+deadlock.</tt></dd></dl>
+
+<dl><dt><a name="MemoryCacheHTTPServer-verify_request"><strong>verify_request</strong></a>(self, request, client_address)</dt><dd><tt>Verify&nbsp;the&nbsp;request.&nbsp;&nbsp;May&nbsp;be&nbsp;overridden.<br>
+&nbsp;<br>
+Return&nbsp;True&nbsp;if&nbsp;we&nbsp;should&nbsp;proceed&nbsp;with&nbsp;this&nbsp;request.</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="SocketServer.html#BaseServer">SocketServer.BaseServer</a>:<br>
+<dl><dt><strong>timeout</strong> = None</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ResourceAndRange">class <strong>ResourceAndRange</strong></a>(<a href="__builtin__.html#tuple">__builtin__.tuple</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt><a href="#ResourceAndRange">ResourceAndRange</a>(resource,&nbsp;byte_range)<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.memory_cache_http_server.html#ResourceAndRange">ResourceAndRange</a></dd>
+<dd><a href="__builtin__.html#tuple">__builtin__.tuple</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ResourceAndRange-__getnewargs__"><strong>__getnewargs__</strong></a>(self)</dt><dd><tt>Return&nbsp;self&nbsp;as&nbsp;a&nbsp;plain&nbsp;<a href="__builtin__.html#tuple">tuple</a>.&nbsp;&nbsp;Used&nbsp;by&nbsp;copy&nbsp;and&nbsp;pickle.</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__repr__"><strong>__repr__</strong></a>(self)</dt><dd><tt>Return&nbsp;a&nbsp;nicely&nbsp;formatted&nbsp;representation&nbsp;string</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-_asdict"><strong>_asdict</strong></a>(self)</dt><dd><tt>Return&nbsp;a&nbsp;new&nbsp;OrderedDict&nbsp;which&nbsp;maps&nbsp;field&nbsp;names&nbsp;to&nbsp;their&nbsp;values</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-_replace"><strong>_replace</strong></a>(_self, **kwds)</dt><dd><tt>Return&nbsp;a&nbsp;new&nbsp;<a href="#ResourceAndRange">ResourceAndRange</a>&nbsp;object&nbsp;replacing&nbsp;specified&nbsp;fields&nbsp;with&nbsp;new&nbsp;values</tt></dd></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="ResourceAndRange-_make"><strong>_make</strong></a>(cls, iterable, new<font color="#909090">=&lt;built-in method __new__ of type object&gt;</font>, len<font color="#909090">=&lt;built-in function len&gt;</font>)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>Make&nbsp;a&nbsp;new&nbsp;<a href="#ResourceAndRange">ResourceAndRange</a>&nbsp;object&nbsp;from&nbsp;a&nbsp;sequence&nbsp;or&nbsp;iterable</tt></dd></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="ResourceAndRange-__new__"><strong>__new__</strong></a>(_cls, resource, byte_range)</dt><dd><tt>Create&nbsp;new&nbsp;instance&nbsp;of&nbsp;<a href="#ResourceAndRange">ResourceAndRange</a>(resource,&nbsp;byte_range)</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>byte_range</strong></dt>
+<dd><tt>Alias&nbsp;for&nbsp;field&nbsp;number&nbsp;1</tt></dd>
+</dl>
+<dl><dt><strong>resource</strong></dt>
+<dd><tt>Alias&nbsp;for&nbsp;field&nbsp;number&nbsp;0</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>_fields</strong> = ('resource', 'byte_range')</dl>
+
+<hr>
+Methods inherited from <a href="__builtin__.html#tuple">__builtin__.tuple</a>:<br>
+<dl><dt><a name="ResourceAndRange-__add__"><strong>__add__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__add__">__add__</a>(y)&nbsp;&lt;==&gt;&nbsp;x+y</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__contains__"><strong>__contains__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__contains__">__contains__</a>(y)&nbsp;&lt;==&gt;&nbsp;y&nbsp;in&nbsp;x</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__eq__"><strong>__eq__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__eq__">__eq__</a>(y)&nbsp;&lt;==&gt;&nbsp;x==y</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__ge__"><strong>__ge__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__ge__">__ge__</a>(y)&nbsp;&lt;==&gt;&nbsp;x&gt;=y</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__gt__"><strong>__gt__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__gt__">__gt__</a>(y)&nbsp;&lt;==&gt;&nbsp;x&gt;y</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__hash__"><strong>__hash__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__hash__">__hash__</a>()&nbsp;&lt;==&gt;&nbsp;hash(x)</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__iter__"><strong>__iter__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__iter__">__iter__</a>()&nbsp;&lt;==&gt;&nbsp;iter(x)</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__le__"><strong>__le__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__le__">__le__</a>(y)&nbsp;&lt;==&gt;&nbsp;x&lt;=y</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__len__"><strong>__len__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__len__">__len__</a>()&nbsp;&lt;==&gt;&nbsp;len(x)</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__lt__"><strong>__lt__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__lt__">__lt__</a>(y)&nbsp;&lt;==&gt;&nbsp;x&lt;y</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__mul__"><strong>__mul__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__mul__">__mul__</a>(n)&nbsp;&lt;==&gt;&nbsp;x*n</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__ne__"><strong>__ne__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__ne__">__ne__</a>(y)&nbsp;&lt;==&gt;&nbsp;x!=y</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__rmul__"><strong>__rmul__</strong></a>(...)</dt><dd><tt>x.<a href="#ResourceAndRange-__rmul__">__rmul__</a>(n)&nbsp;&lt;==&gt;&nbsp;n*x</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-__sizeof__"><strong>__sizeof__</strong></a>(...)</dt><dd><tt>T.<a href="#ResourceAndRange-__sizeof__">__sizeof__</a>()&nbsp;--&nbsp;size&nbsp;of&nbsp;T&nbsp;in&nbsp;memory,&nbsp;in&nbsp;bytes</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-count"><strong>count</strong></a>(...)</dt><dd><tt>T.<a href="#ResourceAndRange-count">count</a>(value)&nbsp;-&gt;&nbsp;integer&nbsp;--&nbsp;return&nbsp;number&nbsp;of&nbsp;occurrences&nbsp;of&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="ResourceAndRange-index"><strong>index</strong></a>(...)</dt><dd><tt>T.<a href="#ResourceAndRange-index">index</a>(value,&nbsp;[start,&nbsp;[stop]])&nbsp;-&gt;&nbsp;integer&nbsp;--&nbsp;return&nbsp;first&nbsp;index&nbsp;of&nbsp;value.<br>
+Raises&nbsp;ValueError&nbsp;if&nbsp;the&nbsp;value&nbsp;is&nbsp;not&nbsp;present.</tt></dd></dl>
+
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-Main"><strong>Main</strong></a>()</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.android_platform_backend.html b/chromium/tools/telemetry/docs/telemetry.core.platform.android_platform_backend.html
new file mode 100644
index 00000000000..d144345daf6
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.android_platform_backend.html
@@ -0,0 +1,102 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.android_platform_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.android_platform_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/android_platform_backend.py">telemetry/core/platform/android_platform_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="pylib.perf_tests_helper.html">pylib.perf_tests_helper</a><br>
+<a href="telemetry.core.platform.html">telemetry.core.platform</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.platform_backend.html">telemetry.core.platform.platform_backend</a><br>
+<a href="pylib.surface_stats_collector.html">pylib.surface_stats_collector</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="pylib.thermal_throttle.html">pylib.thermal_throttle</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.android_platform_backend.html#AndroidPlatformBackend">AndroidPlatformBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="AndroidPlatformBackend">class <strong>AndroidPlatformBackend</strong></a>(<a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.android_platform_backend.html#AndroidPlatformBackend">AndroidPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="AndroidPlatformBackend-CanMonitorThermalThrottling"><strong>CanMonitorThermalThrottling</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-GetChildPids"><strong>GetChildPids</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-GetCommandLine"><strong>GetCommandLine</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-GetIOStats"><strong>GetIOStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-GetMemoryStats"><strong>GetMemoryStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-GetOSName"><strong>GetOSName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-GetRawDisplayFrameRateMeasurements"><strong>GetRawDisplayFrameRateMeasurements</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-GetSystemCommitCharge"><strong>GetSystemCommitCharge</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-HasBeenThermallyThrottled"><strong>HasBeenThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-IsRawDisplayFrameRateSupported"><strong>IsRawDisplayFrameRateSupported</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-IsThermallyThrottled"><strong>IsThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-SetFullPerformanceModeEnabled"><strong>SetFullPerformanceModeEnabled</strong></a>(self, enabled)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-StartRawDisplayFrameRateMeasurement"><strong>StartRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-StopRawDisplayFrameRateMeasurement"><strong>StopRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AndroidPlatformBackend-__init__"><strong>__init__</strong></a>(self, adb, no_performance_mode)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><a name="AndroidPlatformBackend-GetOSVersionName"><strong>GetOSVersionName</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.cros_platform_backend.html b/chromium/tools/telemetry/docs/telemetry.core.platform.cros_platform_backend.html
new file mode 100644
index 00000000000..9733dd8c8f3
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.cros_platform_backend.html
@@ -0,0 +1,101 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.cros_platform_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.cros_platform_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/cros_platform_backend.py">telemetry/core/platform/cros_platform_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.platform.linux_platform_backend.html">telemetry.core.platform.linux_platform_backend</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.linux_platform_backend.html#LinuxPlatformBackend">telemetry.core.platform.linux_platform_backend.LinuxPlatformBackend</a>(<a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.cros_platform_backend.html#CrosPlatformBackend">CrosPlatformBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="CrosPlatformBackend">class <strong>CrosPlatformBackend</strong></a>(<a href="telemetry.core.platform.linux_platform_backend.html#LinuxPlatformBackend">telemetry.core.platform.linux_platform_backend.LinuxPlatformBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.cros_platform_backend.html#CrosPlatformBackend">CrosPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.linux_platform_backend.html#LinuxPlatformBackend">telemetry.core.platform.linux_platform_backend.LinuxPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="CrosPlatformBackend-GetIOStats"><strong>GetIOStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-GetOSName"><strong>GetOSName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-GetRawDisplayFrameRateMeasurements"><strong>GetRawDisplayFrameRateMeasurements</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-HasBeenThermallyThrottled"><strong>HasBeenThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-IsThermallyThrottled"><strong>IsThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-StartRawDisplayFrameRateMeasurement"><strong>StartRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-StopRawDisplayFrameRateMeasurement"><strong>StopRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-__init__"><strong>__init__</strong></a>(self, cri)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.linux_platform_backend.html#LinuxPlatformBackend">telemetry.core.platform.linux_platform_backend.LinuxPlatformBackend</a>:<br>
+<dl><dt><a name="CrosPlatformBackend-GetMemoryStats"><strong>GetMemoryStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-GetSystemCommitCharge"><strong>GetSystemCommitCharge</strong></a>(self)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a>:<br>
+<dl><dt><a name="CrosPlatformBackend-GetChildPids"><strong>GetChildPids</strong></a>(self, pid)</dt><dd><tt>Returns&nbsp;a&nbsp;list&nbsp;of&nbsp;child&nbsp;pids&nbsp;of&nbsp;|pid|.</tt></dd></dl>
+
+<dl><dt><a name="CrosPlatformBackend-GetCommandLine"><strong>GetCommandLine</strong></a>(self, pid)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><a name="CrosPlatformBackend-CanMonitorThermalThrottling"><strong>CanMonitorThermalThrottling</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-GetOSVersionName"><strong>GetOSVersionName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-IsRawDisplayFrameRateSupported"><strong>IsRawDisplayFrameRateSupported</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CrosPlatformBackend-SetFullPerformanceModeEnabled"><strong>SetFullPerformanceModeEnabled</strong></a>(self, enabled)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.html b/chromium/tools/telemetry/docs/telemetry.core.platform.html
new file mode 100644
index 00000000000..66d420cb0b2
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.html
@@ -0,0 +1,108 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry.core.platform</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.platform</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/__init__.py">telemetry/core/platform/__init__.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.platform.android_platform_backend.html">android_platform_backend</a><br>
+<a href="telemetry.core.platform.cros_platform_backend.html">cros_platform_backend</a><br>
+<a href="telemetry.core.platform.linux_platform_backend.html">linux_platform_backend</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.mac_platform_backend.html">mac_platform_backend</a><br>
+<a href="telemetry.core.platform.platform_backend.html">platform_backend</a><br>
+<a href="telemetry.core.platform.posix_platform_backend.html">posix_platform_backend</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.posix_platform_backend_unittest.html">posix_platform_backend_unittest</a><br>
+<a href="telemetry.core.platform.profiler.html"><strong>profiler</strong>&nbsp;(package)</a><br>
+<a href="telemetry.core.platform.win_platform_backend.html">win_platform_backend</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.html#Platform">Platform</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Platform">class <strong>Platform</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>The&nbsp;platform&nbsp;that&nbsp;the&nbsp;target&nbsp;browser&nbsp;is&nbsp;running&nbsp;on.<br>
+&nbsp;<br>
+Provides&nbsp;a&nbsp;limited&nbsp;interface&nbsp;to&nbsp;interact&nbsp;with&nbsp;the&nbsp;platform&nbsp;itself,&nbsp;where<br>
+possible.&nbsp;It's&nbsp;important&nbsp;to&nbsp;note&nbsp;that&nbsp;platforms&nbsp;may&nbsp;not&nbsp;provide&nbsp;a&nbsp;specific<br>
+API,&nbsp;so&nbsp;check&nbsp;with&nbsp;IsFooBar()&nbsp;for&nbsp;availability.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Platform-CanMonitorThermalThrottling"><strong>CanMonitorThermalThrottling</strong></a>(self)</dt><dd><tt>Platforms&nbsp;may&nbsp;be&nbsp;able&nbsp;to&nbsp;detect&nbsp;thermal&nbsp;throttling.<br>
+&nbsp;<br>
+Some&nbsp;fan-less&nbsp;computers&nbsp;go&nbsp;into&nbsp;a&nbsp;reduced&nbsp;performance&nbsp;mode&nbsp;when&nbsp;their&nbsp;heat<br>
+exceeds&nbsp;a&nbsp;certain&nbsp;threshold.&nbsp;Performance&nbsp;tests&nbsp;in&nbsp;particular&nbsp;should&nbsp;use&nbsp;this<br>
+API&nbsp;to&nbsp;detect&nbsp;if&nbsp;this&nbsp;has&nbsp;happened&nbsp;and&nbsp;interpret&nbsp;results&nbsp;accordingly.</tt></dd></dl>
+
+<dl><dt><a name="Platform-GetOSName"><strong>GetOSName</strong></a>(self)</dt><dd><tt>Returns&nbsp;a&nbsp;string&nbsp;description&nbsp;of&nbsp;the&nbsp;<a href="#Platform">Platform</a>&nbsp;OS.<br>
+&nbsp;<br>
+Examples:&nbsp;WIN,&nbsp;MAC,&nbsp;LINUX,&nbsp;CHROMEOS</tt></dd></dl>
+
+<dl><dt><a name="Platform-GetOSVersionName"><strong>GetOSVersionName</strong></a>(self)</dt><dd><tt>Returns&nbsp;a&nbsp;string&nbsp;description&nbsp;of&nbsp;the&nbsp;<a href="#Platform">Platform</a>&nbsp;OS&nbsp;version.<br>
+&nbsp;<br>
+Examples:&nbsp;VISTA,&nbsp;WIN7,&nbsp;LION,&nbsp;MOUNTAINLION</tt></dd></dl>
+
+<dl><dt><a name="Platform-GetRawDisplayFrameRateMeasurements"><strong>GetRawDisplayFrameRateMeasurements</strong></a>(self)</dt><dd><tt>Returns&nbsp;a&nbsp;list&nbsp;of&nbsp;RawDisplayFrameRateMeasurement.</tt></dd></dl>
+
+<dl><dt><a name="Platform-HasBeenThermallyThrottled"><strong>HasBeenThermallyThrottled</strong></a>(self)</dt><dd><tt>Returns&nbsp;True&nbsp;if&nbsp;the&nbsp;device&nbsp;has&nbsp;been&nbsp;thermally&nbsp;throttled.</tt></dd></dl>
+
+<dl><dt><a name="Platform-IsRawDisplayFrameRateSupported"><strong>IsRawDisplayFrameRateSupported</strong></a>(self)</dt><dd><tt>Platforms&nbsp;may&nbsp;be&nbsp;able&nbsp;to&nbsp;collect&nbsp;GL&nbsp;surface&nbsp;stats.</tt></dd></dl>
+
+<dl><dt><a name="Platform-IsThermallyThrottled"><strong>IsThermallyThrottled</strong></a>(self)</dt><dd><tt>Returns&nbsp;True&nbsp;if&nbsp;the&nbsp;device&nbsp;is&nbsp;currently&nbsp;thermally&nbsp;throttled.</tt></dd></dl>
+
+<dl><dt><a name="Platform-SetFullPerformanceModeEnabled"><strong>SetFullPerformanceModeEnabled</strong></a>(self, enabled)</dt><dd><tt>Platforms&nbsp;may&nbsp;tweak&nbsp;their&nbsp;CPU&nbsp;governor,&nbsp;system&nbsp;status,&nbsp;etc.<br>
+&nbsp;<br>
+Most&nbsp;platforms&nbsp;can&nbsp;operate&nbsp;in&nbsp;a&nbsp;battery&nbsp;saving&nbsp;mode.&nbsp;While&nbsp;good&nbsp;for&nbsp;battery<br>
+life,&nbsp;this&nbsp;can&nbsp;cause&nbsp;confusing&nbsp;performance&nbsp;results&nbsp;and&nbsp;add&nbsp;noise.&nbsp;Turning<br>
+full&nbsp;performance&nbsp;mode&nbsp;on&nbsp;disables&nbsp;these&nbsp;features,&nbsp;which&nbsp;is&nbsp;useful&nbsp;for<br>
+performance&nbsp;testing.</tt></dd></dl>
+
+<dl><dt><a name="Platform-StartRawDisplayFrameRateMeasurement"><strong>StartRawDisplayFrameRateMeasurement</strong></a>(self)</dt><dd><tt>Start&nbsp;measuring&nbsp;GL&nbsp;surface&nbsp;stats.</tt></dd></dl>
+
+<dl><dt><a name="Platform-StopRawDisplayFrameRateMeasurement"><strong>StopRawDisplayFrameRateMeasurement</strong></a>(self)</dt><dd><tt>Stop&nbsp;measuring&nbsp;GL&nbsp;surface&nbsp;stats.</tt></dd></dl>
+
+<dl><dt><a name="Platform-__init__"><strong>__init__</strong></a>(self, platform_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>RawDisplayFrameRateMeasurement</strong> = &lt;class 'telemetry.core.platform.RawDisplayFrameRateMeasurement'&gt;</dl>
+
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.linux_platform_backend.html b/chromium/tools/telemetry/docs/telemetry.core.platform.linux_platform_backend.html
new file mode 100644
index 00000000000..2750c4940c2
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.linux_platform_backend.html
@@ -0,0 +1,97 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.linux_platform_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.linux_platform_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/linux_platform_backend.py">telemetry/core/platform/linux_platform_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.platform.posix_platform_backend.html">telemetry.core.platform.posix_platform_backend</a><br>
+</td><td width="25%" valign=top><a href="resource.html">resource</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a>(<a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.linux_platform_backend.html#LinuxPlatformBackend">LinuxPlatformBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="LinuxPlatformBackend">class <strong>LinuxPlatformBackend</strong></a>(<a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.linux_platform_backend.html#LinuxPlatformBackend">LinuxPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="LinuxPlatformBackend-GetIOStats"><strong>GetIOStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-GetMemoryStats"><strong>GetMemoryStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-GetOSName"><strong>GetOSName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-GetRawDisplayFrameRateMeasurements"><strong>GetRawDisplayFrameRateMeasurements</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-GetSystemCommitCharge"><strong>GetSystemCommitCharge</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-HasBeenThermallyThrottled"><strong>HasBeenThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-IsThermallyThrottled"><strong>IsThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-StartRawDisplayFrameRateMeasurement"><strong>StartRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-StopRawDisplayFrameRateMeasurement"><strong>StopRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a>:<br>
+<dl><dt><a name="LinuxPlatformBackend-GetChildPids"><strong>GetChildPids</strong></a>(self, pid)</dt><dd><tt>Returns&nbsp;a&nbsp;list&nbsp;of&nbsp;child&nbsp;pids&nbsp;of&nbsp;|pid|.</tt></dd></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-GetCommandLine"><strong>GetCommandLine</strong></a>(self, pid)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><a name="LinuxPlatformBackend-CanMonitorThermalThrottling"><strong>CanMonitorThermalThrottling</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-GetOSVersionName"><strong>GetOSVersionName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-IsRawDisplayFrameRateSupported"><strong>IsRawDisplayFrameRateSupported</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="LinuxPlatformBackend-SetFullPerformanceModeEnabled"><strong>SetFullPerformanceModeEnabled</strong></a>(self, enabled)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.mac_platform_backend.html b/chromium/tools/telemetry/docs/telemetry.core.platform.mac_platform_backend.html
new file mode 100644
index 00000000000..85209ba4b46
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.mac_platform_backend.html
@@ -0,0 +1,98 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.mac_platform_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.mac_platform_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/mac_platform_backend.py">telemetry/core/platform/mac_platform_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.posix_platform_backend.html">telemetry.core.platform.posix_platform_backend</a><br>
+</td><td width="25%" valign=top><a href="resource.html">resource</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a>(<a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.mac_platform_backend.html#MacPlatformBackend">MacPlatformBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MacPlatformBackend">class <strong>MacPlatformBackend</strong></a>(<a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.mac_platform_backend.html#MacPlatformBackend">MacPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="MacPlatformBackend-GetMemoryStats"><strong>GetMemoryStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-GetOSName"><strong>GetOSName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-GetOSVersionName"><strong>GetOSVersionName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-GetRawDisplayFrameRateMeasurements"><strong>GetRawDisplayFrameRateMeasurements</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-GetSystemCommitCharge"><strong>GetSystemCommitCharge</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-HasBeenThermallyThrottled"><strong>HasBeenThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-IsThermallyThrottled"><strong>IsThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-StartRawDisplayFrameRateMeasurement"><strong>StartRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-StopRawDisplayFrameRateMeasurement"><strong>StopRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">telemetry.core.platform.posix_platform_backend.PosixPlatformBackend</a>:<br>
+<dl><dt><a name="MacPlatformBackend-GetChildPids"><strong>GetChildPids</strong></a>(self, pid)</dt><dd><tt>Returns&nbsp;a&nbsp;list&nbsp;of&nbsp;child&nbsp;pids&nbsp;of&nbsp;|pid|.</tt></dd></dl>
+
+<dl><dt><a name="MacPlatformBackend-GetCommandLine"><strong>GetCommandLine</strong></a>(self, pid)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><a name="MacPlatformBackend-CanMonitorThermalThrottling"><strong>CanMonitorThermalThrottling</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-GetIOStats"><strong>GetIOStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-IsRawDisplayFrameRateSupported"><strong>IsRawDisplayFrameRateSupported</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="MacPlatformBackend-SetFullPerformanceModeEnabled"><strong>SetFullPerformanceModeEnabled</strong></a>(self, enabled)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.platform_backend.html b/chromium/tools/telemetry/docs/telemetry.core.platform.platform_backend.html
new file mode 100644
index 00000000000..935d4dd0ded
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.platform_backend.html
@@ -0,0 +1,77 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.platform_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.platform_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/platform_backend.py">telemetry/core/platform/platform_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">PlatformBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PlatformBackend">class <strong>PlatformBackend</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PlatformBackend-CanMonitorThermalThrottling"><strong>CanMonitorThermalThrottling</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-GetChildPids"><strong>GetChildPids</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-GetCommandLine"><strong>GetCommandLine</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-GetIOStats"><strong>GetIOStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-GetMemoryStats"><strong>GetMemoryStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-GetOSName"><strong>GetOSName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-GetOSVersionName"><strong>GetOSVersionName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-GetRawDisplayFrameRateMeasurements"><strong>GetRawDisplayFrameRateMeasurements</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-GetSystemCommitCharge"><strong>GetSystemCommitCharge</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-HasBeenThermallyThrottled"><strong>HasBeenThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-IsRawDisplayFrameRateSupported"><strong>IsRawDisplayFrameRateSupported</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-IsThermallyThrottled"><strong>IsThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-SetFullPerformanceModeEnabled"><strong>SetFullPerformanceModeEnabled</strong></a>(self, enabled)</dt></dl>
+
+<dl><dt><a name="PlatformBackend-StartRawDisplayFrameRateMeasurement"><strong>StartRawDisplayFrameRateMeasurement</strong></a>(self)</dt><dd><tt>#&nbsp;pylint:&nbsp;disable=W0613</tt></dd></dl>
+
+<dl><dt><a name="PlatformBackend-StopRawDisplayFrameRateMeasurement"><strong>StopRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.posix_platform_backend.html b/chromium/tools/telemetry/docs/telemetry.core.platform.posix_platform_backend.html
new file mode 100644
index 00000000000..c5fb1913bf3
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.posix_platform_backend.html
@@ -0,0 +1,94 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.posix_platform_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.posix_platform_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/posix_platform_backend.py">telemetry/core/platform/posix_platform_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.platform.platform_backend.html">telemetry.core.platform.platform_backend</a><br>
+</td><td width="25%" valign=top><a href="subprocess.html">subprocess</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">PosixPlatformBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PosixPlatformBackend">class <strong>PosixPlatformBackend</strong></a>(<a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.posix_platform_backend.html#PosixPlatformBackend">PosixPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PosixPlatformBackend-GetChildPids"><strong>GetChildPids</strong></a>(self, pid)</dt><dd><tt>Returns&nbsp;a&nbsp;list&nbsp;of&nbsp;child&nbsp;pids&nbsp;of&nbsp;|pid|.</tt></dd></dl>
+
+<dl><dt><a name="PosixPlatformBackend-GetCommandLine"><strong>GetCommandLine</strong></a>(self, pid)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><a name="PosixPlatformBackend-CanMonitorThermalThrottling"><strong>CanMonitorThermalThrottling</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-GetIOStats"><strong>GetIOStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-GetMemoryStats"><strong>GetMemoryStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-GetOSName"><strong>GetOSName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-GetOSVersionName"><strong>GetOSVersionName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-GetRawDisplayFrameRateMeasurements"><strong>GetRawDisplayFrameRateMeasurements</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-GetSystemCommitCharge"><strong>GetSystemCommitCharge</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-HasBeenThermallyThrottled"><strong>HasBeenThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-IsRawDisplayFrameRateSupported"><strong>IsRawDisplayFrameRateSupported</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-IsThermallyThrottled"><strong>IsThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-SetFullPerformanceModeEnabled"><strong>SetFullPerformanceModeEnabled</strong></a>(self, enabled)</dt></dl>
+
+<dl><dt><a name="PosixPlatformBackend-StartRawDisplayFrameRateMeasurement"><strong>StartRawDisplayFrameRateMeasurement</strong></a>(self)</dt><dd><tt>#&nbsp;pylint:&nbsp;disable=W0613</tt></dd></dl>
+
+<dl><dt><a name="PosixPlatformBackend-StopRawDisplayFrameRateMeasurement"><strong>StopRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.html b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.html
new file mode 100644
index 00000000000..706c5e008f0
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.html
@@ -0,0 +1,73 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry.core.platform.profiler</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.profiler</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/profiler/__init__.py">telemetry/core/platform/profiler/__init__.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.platform.profiler.iprofiler_profiler.html">iprofiler_profiler</a><br>
+<a href="telemetry.core.platform.profiler.java_heap_profiler.html">java_heap_profiler</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.profiler.perf_profiler.html">perf_profiler</a><br>
+<a href="telemetry.core.platform.profiler.profiler_finder.html">profiler_finder</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.profiler.sample_profiler.html">sample_profiler</a><br>
+<a href="telemetry.core.platform.profiler.tcmalloc_heap_profiler.html">tcmalloc_heap_profiler</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.profiler.trace_profiler.html">trace_profiler</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.html#Profiler">Profiler</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Profiler">class <strong>Profiler</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;sampling&nbsp;profiler&nbsp;provided&nbsp;by&nbsp;the&nbsp;platform.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Profiler-CollectProfile"><strong>CollectProfile</strong></a>(self)</dt><dd><tt>Collect&nbsp;the&nbsp;profile&nbsp;from&nbsp;the&nbsp;profiler.</tt></dd></dl>
+
+<dl><dt><a name="Profiler-__init__"><strong>__init__</strong></a>(self, browser_backend, platform_backend, output_path)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="Profiler-is_supported"><strong>is_supported</strong></a>(cls, options)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>True&nbsp;iff&nbsp;this&nbsp;profiler&nbsp;is&nbsp;currently&nbsp;supported&nbsp;by&nbsp;the&nbsp;platform.</tt></dd></dl>
+
+<dl><dt><a name="Profiler-name"><strong>name</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>User-friendly&nbsp;name&nbsp;of&nbsp;this&nbsp;profiler.</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.iprofiler_profiler.html b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.iprofiler_profiler.html
new file mode 100644
index 00000000000..8fc387e2aa8
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.iprofiler_profiler.html
@@ -0,0 +1,76 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.profiler.iprofiler_profiler</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.<a href="telemetry.core.platform.profiler.html"><font color="#ffffff">profiler</font></a>.iprofiler_profiler</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/profiler/iprofiler_profiler.py">telemetry/core/platform/profiler/iprofiler_profiler.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="pexpect.html">pexpect</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.profiler.html">telemetry.core.platform.profiler</a><br>
+<a href="signal.html">signal</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.iprofiler_profiler.html#IprofilerProfiler">IprofilerProfiler</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="IprofilerProfiler">class <strong>IprofilerProfiler</strong></a>(<a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.profiler.iprofiler_profiler.html#IprofilerProfiler">IprofilerProfiler</a></dd>
+<dd><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="IprofilerProfiler-CollectProfile"><strong>CollectProfile</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="IprofilerProfiler-__init__"><strong>__init__</strong></a>(self, browser_backend, platform_backend, output_path)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="IprofilerProfiler-is_supported"><strong>is_supported</strong></a>(cls, options)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<dl><dt><a name="IprofilerProfiler-name"><strong>name</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.java_heap_profiler.html b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.java_heap_profiler.html
new file mode 100644
index 00000000000..998cd0bb85e
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.java_heap_profiler.html
@@ -0,0 +1,77 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.profiler.java_heap_profiler</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.<a href="telemetry.core.platform.profiler.html"><font color="#ffffff">profiler</font></a>.java_heap_profiler</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/profiler/java_heap_profiler.py">telemetry/core/platform/profiler/java_heap_profiler.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="telemetry.core.platform.profiler.html">telemetry.core.platform.profiler</a><br>
+</td><td width="25%" valign=top><a href="subprocess.html">subprocess</a><br>
+<a href="threading.html">threading</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.java_heap_profiler.html#JavaHeapProfiler">JavaHeapProfiler</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="JavaHeapProfiler">class <strong>JavaHeapProfiler</strong></a>(<a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Android-specific,&nbsp;trigger&nbsp;and&nbsp;fetch&nbsp;java&nbsp;heap&nbsp;dumps.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.profiler.java_heap_profiler.html#JavaHeapProfiler">JavaHeapProfiler</a></dd>
+<dd><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="JavaHeapProfiler-CollectProfile"><strong>CollectProfile</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="JavaHeapProfiler-__init__"><strong>__init__</strong></a>(self, browser_backend, platform_backend, output_path)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="JavaHeapProfiler-is_supported"><strong>is_supported</strong></a>(cls, options)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<dl><dt><a name="JavaHeapProfiler-name"><strong>name</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.perf_profiler.html b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.perf_profiler.html
new file mode 100644
index 00000000000..33afaea5942
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.perf_profiler.html
@@ -0,0 +1,76 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.profiler.perf_profiler</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.<a href="telemetry.core.platform.profiler.html"><font color="#ffffff">profiler</font></a>.perf_profiler</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/profiler/perf_profiler.py">telemetry/core/platform/profiler/perf_profiler.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="telemetry.core.platform.profiler.html">telemetry.core.platform.profiler</a><br>
+</td><td width="25%" valign=top><a href="signal.html">signal</a><br>
+<a href="subprocess.html">subprocess</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="tempfile.html">tempfile</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.perf_profiler.html#PerfProfiler">PerfProfiler</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PerfProfiler">class <strong>PerfProfiler</strong></a>(<a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.profiler.perf_profiler.html#PerfProfiler">PerfProfiler</a></dd>
+<dd><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PerfProfiler-CollectProfile"><strong>CollectProfile</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PerfProfiler-__init__"><strong>__init__</strong></a>(self, browser_backend, platform_backend, output_path)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="PerfProfiler-is_supported"><strong>is_supported</strong></a>(cls, options)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<dl><dt><a name="PerfProfiler-name"><strong>name</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.profiler_finder.html b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.profiler_finder.html
new file mode 100644
index 00000000000..f1c64cb6a9f
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.profiler_finder.html
@@ -0,0 +1,38 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.profiler.profiler_finder</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.<a href="telemetry.core.platform.profiler.html"><font color="#ffffff">profiler</font></a>.profiler_finder</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/profiler/profiler_finder.py">telemetry/core/platform/profiler/profiler_finder.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.platform.profiler.iprofiler_profiler.html">telemetry.core.platform.profiler.iprofiler_profiler</a><br>
+<a href="telemetry.core.platform.profiler.java_heap_profiler.html">telemetry.core.platform.profiler.java_heap_profiler</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.profiler.perf_profiler.html">telemetry.core.platform.profiler.perf_profiler</a><br>
+<a href="telemetry.core.platform.profiler.sample_profiler.html">telemetry.core.platform.profiler.sample_profiler</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.profiler.tcmalloc_heap_profiler.html">telemetry.core.platform.profiler.tcmalloc_heap_profiler</a><br>
+<a href="telemetry.core.platform.profiler.trace_profiler.html">telemetry.core.platform.profiler.trace_profiler</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-FindProfiler"><strong>FindProfiler</strong></a>(name)</dt></dl>
+ <dl><dt><a name="-GetAllAvailableProfilers"><strong>GetAllAvailableProfilers</strong></a>()</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.sample_profiler.html b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.sample_profiler.html
new file mode 100644
index 00000000000..ce602779ab5
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.sample_profiler.html
@@ -0,0 +1,76 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.profiler.sample_profiler</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.<a href="telemetry.core.platform.profiler.html"><font color="#ffffff">profiler</font></a>.sample_profiler</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/profiler/sample_profiler.py">telemetry/core/platform/profiler/sample_profiler.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.platform.profiler.html">telemetry.core.platform.profiler</a><br>
+<a href="signal.html">signal</a><br>
+</td><td width="25%" valign=top><a href="subprocess.html">subprocess</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="tempfile.html">tempfile</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.sample_profiler.html#SampleProfiler">SampleProfiler</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="SampleProfiler">class <strong>SampleProfiler</strong></a>(<a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.profiler.sample_profiler.html#SampleProfiler">SampleProfiler</a></dd>
+<dd><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="SampleProfiler-CollectProfile"><strong>CollectProfile</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="SampleProfiler-__init__"><strong>__init__</strong></a>(self, browser_backend, platform_backend, output_path)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="SampleProfiler-is_supported"><strong>is_supported</strong></a>(cls, options)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<dl><dt><a name="SampleProfiler-name"><strong>name</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.tcmalloc_heap_profiler.html b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.tcmalloc_heap_profiler.html
new file mode 100644
index 00000000000..9383ff12518
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.tcmalloc_heap_profiler.html
@@ -0,0 +1,76 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.profiler.tcmalloc_heap_profiler</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.<a href="telemetry.core.platform.profiler.html"><font color="#ffffff">profiler</font></a>.tcmalloc_heap_profiler</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/profiler/tcmalloc_heap_profiler.py">telemetry/core/platform/profiler/tcmalloc_heap_profiler.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.profiler.html">telemetry.core.platform.profiler</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.tcmalloc_heap_profiler.html#TCMallocHeapProfiler">TCMallocHeapProfiler</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TCMallocHeapProfiler">class <strong>TCMallocHeapProfiler</strong></a>(<a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;Factory&nbsp;to&nbsp;instantiate&nbsp;the&nbsp;platform-specific&nbsp;profiler.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.profiler.tcmalloc_heap_profiler.html#TCMallocHeapProfiler">TCMallocHeapProfiler</a></dd>
+<dd><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="TCMallocHeapProfiler-CollectProfile"><strong>CollectProfile</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TCMallocHeapProfiler-__init__"><strong>__init__</strong></a>(self, browser_backend, platform_backend, output_path)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="TCMallocHeapProfiler-is_supported"><strong>is_supported</strong></a>(cls, options)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<dl><dt><a name="TCMallocHeapProfiler-name"><strong>name</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.trace_profiler.html b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.trace_profiler.html
new file mode 100644
index 00000000000..e76e1144924
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.profiler.trace_profiler.html
@@ -0,0 +1,72 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.profiler.trace_profiler</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.<a href="telemetry.core.platform.profiler.html"><font color="#ffffff">profiler</font></a>.trace_profiler</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/profiler/trace_profiler.py">telemetry/core/platform/profiler/trace_profiler.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="codecs.html">codecs</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.platform.profiler.html">telemetry.core.platform.profiler</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.profiler.trace_profiler.html#TraceProfiler">TraceProfiler</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TraceProfiler">class <strong>TraceProfiler</strong></a>(<a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.profiler.trace_profiler.html#TraceProfiler">TraceProfiler</a></dd>
+<dd><a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="TraceProfiler-CollectProfile"><strong>CollectProfile</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TraceProfiler-__init__"><strong>__init__</strong></a>(self, browser_backend, platform_backend, output_path)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="TraceProfiler-is_supported"><strong>is_supported</strong></a>(cls, options)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<dl><dt><a name="TraceProfiler-name"><strong>name</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.profiler.html#Profiler">telemetry.core.platform.profiler.Profiler</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.platform.win_platform_backend.html b/chromium/tools/telemetry/docs/telemetry.core.platform.win_platform_backend.html
new file mode 100644
index 00000000000..abfa8d8c662
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.platform.win_platform_backend.html
@@ -0,0 +1,108 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.platform.win_platform_backend</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.platform.html"><font color="#ffffff">platform</font></a>.win_platform_backend</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/platform/win_platform_backend.py">telemetry/core/platform/win_platform_backend.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="collections.html">collections</a><br>
+<a href="ctypes.html">ctypes</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="telemetry.core.platform.platform_backend.html">telemetry.core.platform.platform_backend</a><br>
+</td><td width="25%" valign=top><a href="re.html">re</a><br>
+<a href="subprocess.html">subprocess</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.platform.win_platform_backend.html#WinPlatformBackend">WinPlatformBackend</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="WinPlatformBackend">class <strong>WinPlatformBackend</strong></a>(<a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.platform.win_platform_backend.html#WinPlatformBackend">WinPlatformBackend</a></dd>
+<dd><a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="WinPlatformBackend-GetChildPids"><strong>GetChildPids</strong></a>(self, pid)</dt><dd><tt>Retunds&nbsp;a&nbsp;list&nbsp;of&nbsp;child&nbsp;pids&nbsp;of&nbsp;|pid|.</tt></dd></dl>
+
+<dl><dt><a name="WinPlatformBackend-GetCommandLine"><strong>GetCommandLine</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-GetIOStats"><strong>GetIOStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-GetMemoryStats"><strong>GetMemoryStats</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-GetOSName"><strong>GetOSName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-GetOSVersionName"><strong>GetOSVersionName</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-GetRawDisplayFrameRateMeasurements"><strong>GetRawDisplayFrameRateMeasurements</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-GetSystemCommitCharge"><strong>GetSystemCommitCharge</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-HasBeenThermallyThrottled"><strong>HasBeenThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-IsThermallyThrottled"><strong>IsThermallyThrottled</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-StartRawDisplayFrameRateMeasurement"><strong>StartRawDisplayFrameRateMeasurement</strong></a>(self)</dt><dd><tt>#&nbsp;pylint:&nbsp;disable=W0613</tt></dd></dl>
+
+<dl><dt><a name="WinPlatformBackend-StopRawDisplayFrameRateMeasurement"><strong>StopRawDisplayFrameRateMeasurement</strong></a>(self)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><a name="WinPlatformBackend-CanMonitorThermalThrottling"><strong>CanMonitorThermalThrottling</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-IsRawDisplayFrameRateSupported"><strong>IsRawDisplayFrameRateSupported</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WinPlatformBackend-SetFullPerformanceModeEnabled"><strong>SetFullPerformanceModeEnabled</strong></a>(self, enabled)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.platform.platform_backend.html#PlatformBackend">telemetry.core.platform.platform_backend.PlatformBackend</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>pywintypes</strong> = None<br>
+<strong>win32api</strong> = None<br>
+<strong>win32con</strong> = None<br>
+<strong>win32process</strong> = None</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.possible_browser.html b/chromium/tools/telemetry/docs/telemetry.core.possible_browser.html
new file mode 100644
index 00000000000..d23432c4e9e
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.possible_browser.html
@@ -0,0 +1,63 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.possible_browser</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.possible_browser</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/possible_browser.py">telemetry/core/possible_browser.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.possible_browser.html#PossibleBrowser">PossibleBrowser</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PossibleBrowser">class <strong>PossibleBrowser</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;browser&nbsp;that&nbsp;can&nbsp;be&nbsp;controlled.<br>
+&nbsp;<br>
+Call&nbsp;<a href="#PossibleBrowser-Create">Create</a>()&nbsp;to&nbsp;launch&nbsp;the&nbsp;browser&nbsp;and&nbsp;begin&nbsp;manipulating&nbsp;it..<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PossibleBrowser-Create"><strong>Create</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PossibleBrowser-SupportsOptions"><strong>SupportsOptions</strong></a>(self, options)</dt><dd><tt>Tests&nbsp;for&nbsp;extension&nbsp;support.</tt></dd></dl>
+
+<dl><dt><a name="PossibleBrowser-__init__"><strong>__init__</strong></a>(self, browser_type, options)</dt></dl>
+
+<dl><dt><a name="PossibleBrowser-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser_type</strong></dt>
+</dl>
+<dl><dt><strong>options</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.profile_creator.html b/chromium/tools/telemetry/docs/telemetry.core.profile_creator.html
new file mode 100644
index 00000000000..5427a9bc395
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.profile_creator.html
@@ -0,0 +1,53 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.profile_creator</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.profile_creator</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/profile_creator.py">telemetry/core/profile_creator.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.profile_creator.html#ProfileCreator">ProfileCreator</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ProfileCreator">class <strong>ProfileCreator</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Base&nbsp;class&nbsp;for&nbsp;an&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;that&nbsp;constructs&nbsp;a&nbsp;Chrome&nbsp;profile.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="ProfileCreator-CreateProfile"><strong>CreateProfile</strong></a>(self)</dt><dd><tt>Fill&nbsp;in&nbsp;the&nbsp;profile&nbsp;in&nbsp;question.</tt></dd></dl>
+
+<dl><dt><a name="ProfileCreator-__init__"><strong>__init__</strong></a>(self, browser)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.profile_types.html b/chromium/tools/telemetry/docs/telemetry.core.profile_types.html
new file mode 100644
index 00000000000..3dddd582a07
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.profile_types.html
@@ -0,0 +1,51 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.profile_types</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.profile_types</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/profile_types.py">telemetry/core/profile_types.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.discover.html">telemetry.core.discover</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.profile_creator.html">telemetry.core.profile_creator</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-ClearProfieCreatorsForTests"><strong>ClearProfieCreatorsForTests</strong></a>()</dt><dd><tt>Clears&nbsp;the&nbsp;discovered&nbsp;profile&nbsp;creator&nbsp;objects.&nbsp;&nbsp;Used&nbsp;for&nbsp;unit&nbsp;tests.</tt></dd></dl>
+ <dl><dt><a name="-FindProfileCreators"><strong>FindProfileCreators</strong></a>(profile_creators_dir, base_dir)</dt><dd><tt>Discover&nbsp;all&nbsp;the&nbsp;ProfileCreator&nbsp;objects&nbsp;in&nbsp;|profile_creators_dir|.</tt></dd></dl>
+ <dl><dt><a name="-GetProfileCreator"><strong>GetProfileCreator</strong></a>(profile_type)</dt><dd><tt>Returns&nbsp;the&nbsp;profile&nbsp;creator&nbsp;object&nbsp;corresponding&nbsp;to&nbsp;the&nbsp;|profile_type|<br>
+string.</tt></dd></dl>
+ <dl><dt><a name="-GetProfileDir"><strong>GetProfileDir</strong></a>(profile_type)</dt><dd><tt>Given&nbsp;a&nbsp;|profile_type|&nbsp;(as&nbsp;returned&nbsp;by&nbsp;<a href="#-GetProfileTypes">GetProfileTypes</a>()),&nbsp;return&nbsp;the<br>
+directory&nbsp;to&nbsp;use&nbsp;for&nbsp;that&nbsp;profile&nbsp;or&nbsp;None&nbsp;if&nbsp;the&nbsp;profile&nbsp;needs&nbsp;to&nbsp;be&nbsp;generated<br>
+or&nbsp;doesn't&nbsp;need&nbsp;a&nbsp;profile&nbsp;directory&nbsp;(e.g.&nbsp;using&nbsp;the&nbsp;browser&nbsp;default&nbsp;profile).</tt></dd></dl>
+ <dl><dt><a name="-GetProfileTypes"><strong>GetProfileTypes</strong></a>()</dt><dd><tt>Returns&nbsp;a&nbsp;list&nbsp;of&nbsp;all&nbsp;command&nbsp;line&nbsp;options&nbsp;that&nbsp;can&nbsp;be&nbsp;specified&nbsp;for<br>
+profile&nbsp;type.</tt></dd></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>BASE_PROFILE_TYPES</strong> = ['clean', 'default']<br>
+<strong>PROFILE_CREATORS</strong> = {}<br>
+<strong>PROFILE_TYPE_MAPPING</strong> = {'power_user': 'chrome/test/data/extensions/profiles/extension_webrequest', 'typical_user': 'chrome/test/data/extensions/profiles/content_scripts1'}</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.tab.html b/chromium/tools/telemetry/docs/telemetry.core.tab.html
new file mode 100644
index 00000000000..91895eefa8f
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.tab.html
@@ -0,0 +1,168 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.tab</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.tab</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/tab.py">telemetry/core/tab.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.web_contents.html">telemetry.core.web_contents</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.tab.html#Tab">Tab</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Tab">class <strong>Tab</strong></a>(<a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;a&nbsp;tab&nbsp;in&nbsp;the&nbsp;browser<br>
+&nbsp;<br>
+The&nbsp;important&nbsp;parts&nbsp;of&nbsp;the&nbsp;<a href="#Tab">Tab</a>&nbsp;object&nbsp;are&nbsp;in&nbsp;the&nbsp;runtime&nbsp;and&nbsp;page&nbsp;objects.<br>
+E.g.:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Navigates&nbsp;the&nbsp;tab&nbsp;to&nbsp;a&nbsp;given&nbsp;url.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tab.<a href="#Tab-Navigate">Navigate</a>('<a href="http://www.google.com/">http://www.google.com/</a>')<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Evaluates&nbsp;1+1&nbsp;in&nbsp;the&nbsp;tab's&nbsp;JavaScript&nbsp;context.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tab.Evaluate('1+1')<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.tab.html#Tab">Tab</a></dd>
+<dd><a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Tab-Activate"><strong>Activate</strong></a>(self)</dt><dd><tt>Brings&nbsp;this&nbsp;tab&nbsp;to&nbsp;the&nbsp;foreground&nbsp;asynchronously.<br>
+&nbsp;<br>
+Not&nbsp;all&nbsp;browsers&nbsp;or&nbsp;browser&nbsp;versions&nbsp;support&nbsp;this&nbsp;method.<br>
+Be&nbsp;sure&nbsp;to&nbsp;check&nbsp;browser.supports_tab_control.<br>
+&nbsp;<br>
+Please&nbsp;note:&nbsp;this&nbsp;is&nbsp;asynchronous.&nbsp;There&nbsp;is&nbsp;a&nbsp;delay&nbsp;between&nbsp;this&nbsp;call<br>
+and&nbsp;the&nbsp;page's&nbsp;documentVisibilityState&nbsp;becoming&nbsp;'visible',&nbsp;and&nbsp;yet&nbsp;more<br>
+delay&nbsp;until&nbsp;the&nbsp;actual&nbsp;tab&nbsp;is&nbsp;visible&nbsp;to&nbsp;the&nbsp;user.&nbsp;None&nbsp;of&nbsp;these&nbsp;delays<br>
+are&nbsp;included&nbsp;in&nbsp;this&nbsp;call.</tt></dd></dl>
+
+<dl><dt><a name="Tab-ClearCache"><strong>ClearCache</strong></a>(self)</dt><dd><tt>Clears&nbsp;the&nbsp;browser's&nbsp;HTTP&nbsp;disk&nbsp;cache&nbsp;and&nbsp;the&nbsp;tab's&nbsp;HTTP&nbsp;memory&nbsp;cache.</tt></dd></dl>
+
+<dl><dt><a name="Tab-CollectGarbage"><strong>CollectGarbage</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-GetCookieByName"><strong>GetCookieByName</strong></a>(self, name, timeout<font color="#909090">=60</font>)</dt><dd><tt>Returns&nbsp;the&nbsp;value&nbsp;of&nbsp;the&nbsp;cookie&nbsp;by&nbsp;the&nbsp;given&nbsp;|name|.</tt></dd></dl>
+
+<dl><dt><a name="Tab-Navigate"><strong>Navigate</strong></a>(self, url, script_to_evaluate_on_commit<font color="#909090">=None</font>, timeout<font color="#909090">=60</font>)</dt><dd><tt>Navigates&nbsp;to&nbsp;url.<br>
+&nbsp;<br>
+If&nbsp;|script_to_evaluate_on_commit|&nbsp;is&nbsp;given,&nbsp;the&nbsp;script&nbsp;source&nbsp;string&nbsp;will&nbsp;be<br>
+evaluated&nbsp;when&nbsp;the&nbsp;navigation&nbsp;is&nbsp;committed.&nbsp;This&nbsp;is&nbsp;after&nbsp;the&nbsp;context&nbsp;of<br>
+the&nbsp;page&nbsp;exists,&nbsp;but&nbsp;before&nbsp;any&nbsp;script&nbsp;on&nbsp;the&nbsp;page&nbsp;itself&nbsp;has&nbsp;executed.</tt></dd></dl>
+
+<dl><dt><a name="Tab-PerformActionAndWaitForNavigate"><strong>PerformActionAndWaitForNavigate</strong></a>(self, action_function, timeout<font color="#909090">=60</font>)</dt><dd><tt>Executes&nbsp;action_function,&nbsp;and&nbsp;waits&nbsp;for&nbsp;the&nbsp;navigation&nbsp;to&nbsp;complete.<br>
+&nbsp;<br>
+action_function&nbsp;must&nbsp;be&nbsp;a&nbsp;Python&nbsp;function&nbsp;that&nbsp;results&nbsp;in&nbsp;a&nbsp;navigation.<br>
+This&nbsp;function&nbsp;returns&nbsp;when&nbsp;the&nbsp;navigation&nbsp;is&nbsp;complete&nbsp;or&nbsp;when<br>
+the&nbsp;timeout&nbsp;has&nbsp;been&nbsp;exceeded.</tt></dd></dl>
+
+<dl><dt><a name="Tab-Screenshot"><strong>Screenshot</strong></a>(self, timeout<font color="#909090">=60</font>)</dt><dd><tt>Capture&nbsp;a&nbsp;screenshot&nbsp;of&nbsp;the&nbsp;window&nbsp;for&nbsp;rendering&nbsp;validation</tt></dd></dl>
+
+<dl><dt><a name="Tab-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>browser</strong></dt>
+<dd><tt>The&nbsp;browser&nbsp;in&nbsp;which&nbsp;this&nbsp;tab&nbsp;resides.</tt></dd>
+</dl>
+<dl><dt><strong>dom_stats</strong></dt>
+<dd><tt>A&nbsp;dictionary&nbsp;populated&nbsp;with&nbsp;measured&nbsp;DOM&nbsp;statistics.<br>
+&nbsp;<br>
+Currently&nbsp;this&nbsp;dictionary&nbsp;contains:<br>
+{<br>
+&nbsp;&nbsp;'document_count':&nbsp;integer,<br>
+&nbsp;&nbsp;'node_count':&nbsp;integer,<br>
+&nbsp;&nbsp;'event_listener_count':&nbsp;integer<br>
+}</tt></dd>
+</dl>
+<dl><dt><strong>screenshot_supported</strong></dt>
+<dd><tt>True&nbsp;if&nbsp;the&nbsp;browser&nbsp;instance&nbsp;is&nbsp;capable&nbsp;of&nbsp;capturing&nbsp;screenshots</tt></dd>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>:<br>
+<dl><dt><a name="Tab-Close"><strong>Close</strong></a>(self)</dt><dd><tt>Closes&nbsp;this&nbsp;page.<br>
+&nbsp;<br>
+Not&nbsp;all&nbsp;browsers&nbsp;or&nbsp;browser&nbsp;versions&nbsp;support&nbsp;this&nbsp;method.<br>
+Be&nbsp;sure&nbsp;to&nbsp;check&nbsp;browser.supports_tab_control.</tt></dd></dl>
+
+<dl><dt><a name="Tab-Disconnect"><strong>Disconnect</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-EvaluateJavaScript"><strong>EvaluateJavaScript</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Evalutes&nbsp;expr&nbsp;in&nbsp;JavaScript&nbsp;and&nbsp;returns&nbsp;the&nbsp;JSONized&nbsp;result.<br>
+&nbsp;<br>
+Consider&nbsp;using&nbsp;ExecuteJavaScript&nbsp;for&nbsp;cases&nbsp;where&nbsp;the&nbsp;result&nbsp;of&nbsp;the<br>
+expression&nbsp;is&nbsp;not&nbsp;needed.<br>
+&nbsp;<br>
+If&nbsp;evaluation&nbsp;throws&nbsp;in&nbsp;JavaScript,&nbsp;a&nbsp;Python&nbsp;EvaluateException&nbsp;will<br>
+be&nbsp;raised.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;result&nbsp;of&nbsp;the&nbsp;evaluation&nbsp;cannot&nbsp;be&nbsp;JSONized,&nbsp;then&nbsp;an<br>
+EvaluationException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="Tab-ExecuteJavaScript"><strong>ExecuteJavaScript</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Executes&nbsp;expr&nbsp;in&nbsp;JavaScript.&nbsp;Does&nbsp;not&nbsp;return&nbsp;the&nbsp;result.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;expression&nbsp;failed&nbsp;to&nbsp;evaluate,&nbsp;EvaluateException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="Tab-StartTimelineRecording"><strong>StartTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-StopTimelineRecording"><strong>StopTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-WaitForDocumentReadyStateToBeComplete"><strong>WaitForDocumentReadyStateToBeComplete</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<dl><dt><a name="Tab-WaitForDocumentReadyStateToBeInteractiveOrBetter"><strong>WaitForDocumentReadyStateToBeInteractiveOrBetter</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>message_output_stream</strong></dt>
+</dl>
+<dl><dt><strong>timeline_model</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>DEFAULT_TAB_TIMEOUT</strong> = 60</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.tab_list.html b/chromium/tools/telemetry/docs/telemetry.core.tab_list.html
new file mode 100644
index 00000000000..897177d1114
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.tab_list.html
@@ -0,0 +1,61 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.tab_list</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.tab_list</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/tab_list.py">telemetry/core/tab_list.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.tab_list.html#TabList">TabList</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TabList">class <strong>TabList</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TabList-New"><strong>New</strong></a>(self, timeout<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="TabList-__getitem__"><strong>__getitem__</strong></a>(self, index)</dt></dl>
+
+<dl><dt><a name="TabList-__init__"><strong>__init__</strong></a>(self, tab_list_backend)</dt></dl>
+
+<dl><dt><a name="TabList-__iter__"><strong>__iter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabList-__len__"><strong>__len__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.temporary_http_server.html b/chromium/tools/telemetry/docs/telemetry.core.temporary_http_server.html
new file mode 100644
index 00000000000..0d4f59caf62
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.temporary_http_server.html
@@ -0,0 +1,76 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.temporary_http_server</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.temporary_http_server</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/temporary_http_server.py">telemetry/core/temporary_http_server.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="socket.html">socket</a><br>
+</td><td width="25%" valign=top><a href="subprocess.html">subprocess</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="urlparse.html">urlparse</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.temporary_http_server.html#TemporaryHTTPServer">TemporaryHTTPServer</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TemporaryHTTPServer">class <strong>TemporaryHTTPServer</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TemporaryHTTPServer-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TemporaryHTTPServer-UrlOf"><strong>UrlOf</strong></a>(self, path)</dt></dl>
+
+<dl><dt><a name="TemporaryHTTPServer-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TemporaryHTTPServer-__enter__"><strong>__enter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TemporaryHTTPServer-__exit__"><strong>__exit__</strong></a>(self, *args)</dt></dl>
+
+<dl><dt><a name="TemporaryHTTPServer-__init__"><strong>__init__</strong></a>(self, browser_backend, paths)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>paths</strong></dt>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.async_slice.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.async_slice.html
new file mode 100644
index 00000000000..ab97bb0abac
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.async_slice.html
@@ -0,0 +1,77 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.async_slice</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.async_slice</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/async_slice.py">telemetry/core/timeline/async_slice.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.event.html">telemetry.core.timeline.event</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.async_slice.html#AsyncSlice">AsyncSlice</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="AsyncSlice">class <strong>AsyncSlice</strong></a>(<a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;<a href="#AsyncSlice">AsyncSlice</a>&nbsp;represents&nbsp;an&nbsp;interval&nbsp;of&nbsp;time&nbsp;during&nbsp;which&nbsp;an<br>
+asynchronous&nbsp;operation&nbsp;is&nbsp;in&nbsp;progress.&nbsp;An&nbsp;<a href="#AsyncSlice">AsyncSlice</a>&nbsp;consumes&nbsp;no&nbsp;CPU&nbsp;time<br>
+itself&nbsp;and&nbsp;so&nbsp;is&nbsp;only&nbsp;associated&nbsp;with&nbsp;Threads&nbsp;at&nbsp;its&nbsp;start&nbsp;and&nbsp;end&nbsp;point.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.timeline.async_slice.html#AsyncSlice">AsyncSlice</a></dd>
+<dd><a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="AsyncSlice-AddSubSlice"><strong>AddSubSlice</strong></a>(self, sub_slice)</dt></dl>
+
+<dl><dt><a name="AsyncSlice-IterEventsInThisContainerRecrusively"><strong>IterEventsInThisContainerRecrusively</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AsyncSlice-__init__"><strong>__init__</strong></a>(self, category, name, timestamp, args<font color="#909090">=None</font>, parent<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>:<br>
+<dl><dt><a name="AsyncSlice-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>end</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.bounds.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.bounds.html
new file mode 100644
index 00000000000..acfa42702b3
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.bounds.html
@@ -0,0 +1,71 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.bounds</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.bounds</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/bounds.py">telemetry/core/timeline/bounds.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.bounds.html#Bounds">Bounds</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Bounds">class <strong>Bounds</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;a&nbsp;min-max&nbsp;bounds.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Bounds-AddBounds"><strong>AddBounds</strong></a>(self, bounds)</dt></dl>
+
+<dl><dt><a name="Bounds-AddValue"><strong>AddValue</strong></a>(self, value)</dt></dl>
+
+<dl><dt><a name="Bounds-Reset"><strong>Reset</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Bounds-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="Bounds-CompareByMinTimes"><strong>CompareByMinTimes</strong></a>(a, b)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>bounds</strong></dt>
+</dl>
+<dl><dt><strong>center</strong></dt>
+</dl>
+<dl><dt><strong>is_empty</strong></dt>
+</dl>
+<dl><dt><strong>max</strong></dt>
+</dl>
+<dl><dt><strong>min</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.counter.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.counter.html
new file mode 100644
index 00000000000..a1d19ac520a
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.counter.html
@@ -0,0 +1,113 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.counter</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.counter</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/counter.py">telemetry/core/timeline/counter.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.event_container.html">telemetry.core.timeline.event_container</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.counter.html#CounterSample">CounterSample</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.counter.html#Counter">Counter</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Counter">class <strong>Counter</strong></a>(<a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Stores&nbsp;all&nbsp;the&nbsp;samples&nbsp;for&nbsp;a&nbsp;given&nbsp;counter.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.timeline.counter.html#Counter">Counter</a></dd>
+<dd><a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Counter-FinalizeImport"><strong>FinalizeImport</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Counter-IterChildContainers"><strong>IterChildContainers</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Counter-IterEventsInThisContainer"><strong>IterEventsInThisContainer</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Counter-__init__"><strong>__init__</strong></a>(self, parent, category, name)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>num_samples</strong></dt>
+</dl>
+<dl><dt><strong>num_series</strong></dt>
+</dl>
+<hr>
+Data descriptors inherited from <a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="CounterSample">class <strong>CounterSample</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>#&nbsp;Doesnt'&nbsp;inherit&nbsp;from&nbsp;TimelineEvent&nbsp;because&nbsp;its&nbsp;only&nbsp;a&nbsp;temporary&nbsp;wrapper&nbsp;of&nbsp;a<br>
+#&nbsp;counter&nbsp;sample&nbsp;into&nbsp;an&nbsp;event.&nbsp;During&nbsp;stable&nbsp;operation,&nbsp;the&nbsp;samples&nbsp;are&nbsp;stored<br>
+#&nbsp;a&nbsp;dense&nbsp;array&nbsp;of&nbsp;values&nbsp;rather&nbsp;than&nbsp;in&nbsp;the&nbsp;long-form&nbsp;done&nbsp;by&nbsp;an&nbsp;Event.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="CounterSample-__init__"><strong>__init__</strong></a>(self, counter, sample_index)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>duration</strong></dt>
+</dl>
+<dl><dt><strong>end</strong></dt>
+</dl>
+<dl><dt><strong>name</strong></dt>
+</dl>
+<dl><dt><strong>start</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.event.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.event.html
new file mode 100644
index 00000000000..c5a35d6e97d
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.event.html
@@ -0,0 +1,55 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.event</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.event</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/event.py">telemetry/core/timeline/event.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.event.html#TimelineEvent">TimelineEvent</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TimelineEvent">class <strong>TimelineEvent</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;a&nbsp;timeline&nbsp;event.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TimelineEvent-__init__"><strong>__init__</strong></a>(self, category, name, start, duration, args<font color="#909090">=None</font>, parent<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="TimelineEvent-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>end</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.event_container.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.event_container.html
new file mode 100644
index 00000000000..a22803f4bfc
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.event_container.html
@@ -0,0 +1,55 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.event_container</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.event_container</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/event_container.py">telemetry/core/timeline/event_container.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">TimelineEventContainer</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TimelineEventContainer">class <strong>TimelineEventContainer</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;a&nbsp;container&nbsp;for&nbsp;events.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TimelineEventContainer-IterChildContainers"><strong>IterChildContainers</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineEventContainer-IterEventsInThisContainer"><strong>IterEventsInThisContainer</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineEventContainer-__init__"><strong>__init__</strong></a>(self, name, parent)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.html
new file mode 100644
index 00000000000..fa5ba5365d9
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.html
@@ -0,0 +1,39 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry.core.timeline</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.timeline</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/__init__.py">telemetry/core/timeline/__init__.py</a></font></td></tr></table>
+ <p></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.async_slice.html">async_slice</a><br>
+<a href="telemetry.core.timeline.bounds.html">bounds</a><br>
+<a href="telemetry.core.timeline.counter.html">counter</a><br>
+<a href="telemetry.core.timeline.event.html">event</a><br>
+<a href="telemetry.core.timeline.event_container.html">event_container</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.event_unittest.html">event_unittest</a><br>
+<a href="telemetry.core.timeline.importer.html">importer</a><br>
+<a href="telemetry.core.timeline.inspector_importer.html">inspector_importer</a><br>
+<a href="telemetry.core.timeline.inspector_importer_unittest.html">inspector_importer_unittest</a><br>
+<a href="telemetry.core.timeline.model.html">model</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.model_unittest.html">model_unittest</a><br>
+<a href="telemetry.core.timeline.process.html">process</a><br>
+<a href="telemetry.core.timeline.sample.html">sample</a><br>
+<a href="telemetry.core.timeline.slice.html">slice</a><br>
+<a href="telemetry.core.timeline.slice_unittest.html">slice_unittest</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.thread.html">thread</a><br>
+<a href="telemetry.core.timeline.trace_event_importer.html">trace_event_importer</a><br>
+<a href="telemetry.core.timeline.trace_event_importer_unittest.html">trace_event_importer_unittest</a><br>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.importer.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.importer.html
new file mode 100644
index 00000000000..19d41f68e0d
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.importer.html
@@ -0,0 +1,61 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.importer</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.importer</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/importer.py">telemetry/core/timeline/importer.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.importer.html#TimelineImporter">TimelineImporter</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TimelineImporter">class <strong>TimelineImporter</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Interface&nbsp;for&nbsp;classes&nbsp;that&nbsp;can&nbsp;add&nbsp;events&nbsp;to<br>
+a&nbsp;timeline&nbsp;model&nbsp;from&nbsp;raw&nbsp;event&nbsp;data.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TimelineImporter-FinalizeImport"><strong>FinalizeImport</strong></a>(self)</dt><dd><tt>Called&nbsp;after&nbsp;all&nbsp;other&nbsp;importers&nbsp;for&nbsp;the&nbsp;model&nbsp;are&nbsp;run.</tt></dd></dl>
+
+<dl><dt><a name="TimelineImporter-ImportEvents"><strong>ImportEvents</strong></a>(self)</dt><dd><tt>Processes&nbsp;the&nbsp;event&nbsp;data&nbsp;and&nbsp;creates&nbsp;and&nbsp;adds<br>
+new&nbsp;timeline&nbsp;events&nbsp;to&nbsp;the&nbsp;model</tt></dd></dl>
+
+<dl><dt><a name="TimelineImporter-__init__"><strong>__init__</strong></a>(self, model, event_data, import_priority<font color="#909090">=0</font>)</dt></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="TimelineImporter-CanImport"><strong>CanImport</strong></a>(event_data)</dt><dd><tt>Returns&nbsp;true&nbsp;if&nbsp;the&nbsp;importer&nbsp;can&nbsp;process&nbsp;the&nbsp;given&nbsp;event&nbsp;data.</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.inspector_importer.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.inspector_importer.html
new file mode 100644
index 00000000000..8785ec171fc
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.inspector_importer.html
@@ -0,0 +1,76 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.inspector_importer</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.inspector_importer</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/inspector_importer.py">telemetry/core/timeline/inspector_importer.py</a></font></td></tr></table>
+ <p><tt>Imports&nbsp;event&nbsp;data&nbsp;obtained&nbsp;from&nbsp;the&nbsp;inspector's&nbsp;timeline.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.importer.html">telemetry.core.timeline.importer</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.thread.html">telemetry.core.timeline.thread</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.importer.html#TimelineImporter">telemetry.core.timeline.importer.TimelineImporter</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.inspector_importer.html#InspectorTimelineImporter">InspectorTimelineImporter</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="InspectorTimelineImporter">class <strong>InspectorTimelineImporter</strong></a>(<a href="telemetry.core.timeline.importer.html#TimelineImporter">telemetry.core.timeline.importer.TimelineImporter</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.timeline.inspector_importer.html#InspectorTimelineImporter">InspectorTimelineImporter</a></dd>
+<dd><a href="telemetry.core.timeline.importer.html#TimelineImporter">telemetry.core.timeline.importer.TimelineImporter</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="InspectorTimelineImporter-FinalizeImport"><strong>FinalizeImport</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorTimelineImporter-ImportEvents"><strong>ImportEvents</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="InspectorTimelineImporter-__init__"><strong>__init__</strong></a>(self, model, event_data)</dt></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="InspectorTimelineImporter-AddRawEventToThreadRecursive"><strong>AddRawEventToThreadRecursive</strong></a>(thread, raw_inspector_event)</dt></dl>
+
+<dl><dt><a name="InspectorTimelineImporter-CanImport"><strong>CanImport</strong></a>(event_data)</dt><dd><tt>Checks&nbsp;if&nbsp;event_data&nbsp;is&nbsp;from&nbsp;the&nbsp;inspector&nbsp;timeline.&nbsp;We&nbsp;assume<br>
+that&nbsp;if&nbsp;the&nbsp;first&nbsp;event&nbsp;is&nbsp;a&nbsp;valid&nbsp;inspector&nbsp;event,&nbsp;we&nbsp;can&nbsp;import&nbsp;the<br>
+entire&nbsp;list.</tt></dd></dl>
+
+<dl><dt><a name="InspectorTimelineImporter-RawEventToTimelineEvent"><strong>RawEventToTimelineEvent</strong></a>(raw_inspector_event)</dt><dd><tt>Converts&nbsp;raw_inspector_event&nbsp;to&nbsp;TimelineEvent.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.timeline.importer.html#TimelineImporter">telemetry.core.timeline.importer.TimelineImporter</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.model.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.model.html
new file mode 100644
index 00000000000..f9bf7487c1f
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.model.html
@@ -0,0 +1,85 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.model</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.model</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/model.py">telemetry/core/timeline/model.py</a></font></td></tr></table>
+ <p><tt>A&nbsp;container&nbsp;for&nbsp;timeline-based&nbsp;events&nbsp;and&nbsp;traces&nbsp;and&nbsp;can&nbsp;handle&nbsp;importing<br>
+raw&nbsp;event&nbsp;data&nbsp;from&nbsp;different&nbsp;sources.&nbsp;This&nbsp;model&nbsp;closely&nbsp;resembles&nbsp;that&nbsp;in&nbsp;the<br>
+trace_viewer&nbsp;project:<br>
+https://code.google.com/p/trace-viewer/</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.bounds.html">telemetry.core.timeline.bounds</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.inspector_importer.html">telemetry.core.timeline.inspector_importer</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.trace_event_importer.html">telemetry.core.timeline.trace_event_importer</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.process.html">telemetry.core.timeline.process</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.model.html#TimelineModel">TimelineModel</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TimelineModel">class <strong>TimelineModel</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="TimelineModel-GetAllContainers"><strong>GetAllContainers</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineModel-GetAllEvents"><strong>GetAllEvents</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineModel-GetAllEventsOfName"><strong>GetAllEventsOfName</strong></a>(self, name)</dt></dl>
+
+<dl><dt><a name="TimelineModel-GetAllProcesses"><strong>GetAllProcesses</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineModel-GetAllThreads"><strong>GetAllThreads</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineModel-GetOrCreateProcess"><strong>GetOrCreateProcess</strong></a>(self, pid)</dt></dl>
+
+<dl><dt><a name="TimelineModel-ImportTraces"><strong>ImportTraces</strong></a>(self, traces, shift_world_to_zero<font color="#909090">=True</font>)</dt></dl>
+
+<dl><dt><a name="TimelineModel-IterAllEvents"><strong>IterAllEvents</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineModel-ShiftWorldToZero"><strong>ShiftWorldToZero</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineModel-UpdateBounds"><strong>UpdateBounds</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TimelineModel-__init__"><strong>__init__</strong></a>(self, event_data<font color="#909090">=None</font>, shift_world_to_zero<font color="#909090">=True</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>bounds</strong></dt>
+</dl>
+<dl><dt><strong>processes</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.process.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.process.html
new file mode 100644
index 00000000000..e834fd03c21
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.process.html
@@ -0,0 +1,87 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.process</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.process</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/process.py">telemetry/core/timeline/process.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.event_container.html">telemetry.core.timeline.event_container</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.counter.html">telemetry.core.timeline.counter</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.thread.html">telemetry.core.timeline.thread</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.process.html#Process">Process</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Process">class <strong>Process</strong></a>(<a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>The&nbsp;<a href="#Process">Process</a>&nbsp;represents&nbsp;a&nbsp;single&nbsp;userland&nbsp;process&nbsp;in&nbsp;the&nbsp;trace.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.timeline.process.html#Process">Process</a></dd>
+<dd><a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Process-AutoCloseOpenSlices"><strong>AutoCloseOpenSlices</strong></a>(self, max_timestamp)</dt></dl>
+
+<dl><dt><a name="Process-FinalizeImport"><strong>FinalizeImport</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Process-GetCounter"><strong>GetCounter</strong></a>(self, category, name)</dt></dl>
+
+<dl><dt><a name="Process-GetOrCreateCounter"><strong>GetOrCreateCounter</strong></a>(self, category, name)</dt></dl>
+
+<dl><dt><a name="Process-GetOrCreateThread"><strong>GetOrCreateThread</strong></a>(self, tid)</dt></dl>
+
+<dl><dt><a name="Process-IterChildContainers"><strong>IterChildContainers</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Process-IterEventsInThisContainer"><strong>IterEventsInThisContainer</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Process-__init__"><strong>__init__</strong></a>(self, parent, pid)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>counters</strong></dt>
+</dl>
+<dl><dt><strong>threads</strong></dt>
+</dl>
+<hr>
+Data descriptors inherited from <a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.sample.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.sample.html
new file mode 100644
index 00000000000..82e93fde66e
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.sample.html
@@ -0,0 +1,77 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.sample</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.sample</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/sample.py">telemetry/core/timeline/sample.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.event.html">telemetry.core.timeline.event</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.sample.html#Sample">Sample</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Sample">class <strong>Sample</strong></a>(<a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;<a href="#Sample">Sample</a>&nbsp;represents&nbsp;a&nbsp;sample&nbsp;taken&nbsp;at&nbsp;an&nbsp;instant&nbsp;in&nbsp;time<br>
+plus&nbsp;parameters&nbsp;associated&nbsp;with&nbsp;that&nbsp;sample.<br>
+&nbsp;<br>
+NOTE:&nbsp;The&nbsp;<a href="#Sample">Sample</a>&nbsp;class&nbsp;implements&nbsp;the&nbsp;same&nbsp;interface&nbsp;as<br>
+Slice.&nbsp;These&nbsp;must&nbsp;be&nbsp;kept&nbsp;in&nbsp;sync.<br>
+&nbsp;<br>
+All&nbsp;time&nbsp;units&nbsp;are&nbsp;stored&nbsp;in&nbsp;milliseconds.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.timeline.sample.html#Sample">Sample</a></dd>
+<dd><a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Sample-__init__"><strong>__init__</strong></a>(self, category, name, timestamp, args<font color="#909090">=None</font>, parent<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>:<br>
+<dl><dt><a name="Sample-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>end</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.slice.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.slice.html
new file mode 100644
index 00000000000..9239b5d9df4
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.slice.html
@@ -0,0 +1,90 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.slice</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.slice</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/slice.py">telemetry/core/timeline/slice.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.event.html">telemetry.core.timeline.event</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.slice.html#Slice">Slice</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Slice">class <strong>Slice</strong></a>(<a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;<a href="#Slice">Slice</a>&nbsp;represents&nbsp;an&nbsp;interval&nbsp;of&nbsp;time&nbsp;plus&nbsp;parameters&nbsp;associated<br>
+with&nbsp;that&nbsp;interval.<br>
+&nbsp;<br>
+NOTE:&nbsp;The&nbsp;Sample&nbsp;class&nbsp;implements&nbsp;the&nbsp;same&nbsp;interface&nbsp;as<br>
+<a href="#Slice">Slice</a>.&nbsp;These&nbsp;must&nbsp;be&nbsp;kept&nbsp;in&nbsp;sync.<br>
+&nbsp;<br>
+All&nbsp;time&nbsp;units&nbsp;are&nbsp;stored&nbsp;in&nbsp;milliseconds.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.timeline.slice.html#Slice">Slice</a></dd>
+<dd><a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Slice-AddSubSlice"><strong>AddSubSlice</strong></a>(self, sub_slice)</dt></dl>
+
+<dl><dt><a name="Slice-GetAllSubSlices"><strong>GetAllSubSlices</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Slice-GetAllSubSlicesOfName"><strong>GetAllSubSlicesOfName</strong></a>(self, name)</dt></dl>
+
+<dl><dt><a name="Slice-IterEventsInThisContainerRecrusively"><strong>IterEventsInThisContainerRecrusively</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Slice-__init__"><strong>__init__</strong></a>(self, category, name, timestamp, args<font color="#909090">=None</font>, parent<font color="#909090">=None</font>, duration<font color="#909090">=0</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>self_time</strong></dt>
+<dd><tt>Time&nbsp;spent&nbsp;in&nbsp;this&nbsp;function&nbsp;less&nbsp;any&nbsp;time&nbsp;spent&nbsp;in&nbsp;child&nbsp;events.</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>:<br>
+<dl><dt><a name="Slice-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.timeline.event.html#TimelineEvent">telemetry.core.timeline.event.TimelineEvent</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>end</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.thread.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.thread.html
new file mode 100644
index 00000000000..081f2ee55a9
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.thread.html
@@ -0,0 +1,118 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.thread</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.thread</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/thread.py">telemetry/core/timeline/thread.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.timeline.event_container.html">telemetry.core.timeline.event_container</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.sample.html">telemetry.core.timeline.sample</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.slice.html">telemetry.core.timeline.slice</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.thread.html#Thread">Thread</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Thread">class <strong>Thread</strong></a>(<a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;<a href="#Thread">Thread</a>&nbsp;stores&nbsp;all&nbsp;the&nbsp;trace&nbsp;events&nbsp;collected&nbsp;for&nbsp;a&nbsp;particular<br>
+thread.&nbsp;We&nbsp;organize&nbsp;the&nbsp;synchronous&nbsp;slices&nbsp;on&nbsp;a&nbsp;thread&nbsp;by&nbsp;"subrows,"&nbsp;where<br>
+subrow&nbsp;0&nbsp;has&nbsp;all&nbsp;the&nbsp;root&nbsp;slices,&nbsp;subrow&nbsp;1&nbsp;those&nbsp;nested&nbsp;1&nbsp;deep,&nbsp;and&nbsp;so&nbsp;on.<br>
+The&nbsp;asynchronous&nbsp;slices&nbsp;are&nbsp;stored&nbsp;in&nbsp;an&nbsp;AsyncSliceGroup&nbsp;object.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.timeline.thread.html#Thread">Thread</a></dd>
+<dd><a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Thread-AddAsyncSlice"><strong>AddAsyncSlice</strong></a>(self, async_slice)</dt></dl>
+
+<dl><dt><a name="Thread-AddSample"><strong>AddSample</strong></a>(self, category, name, timestamp, args<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="Thread-AutoCloseOpenSlices"><strong>AutoCloseOpenSlices</strong></a>(self, max_timestamp)</dt></dl>
+
+<dl><dt><a name="Thread-BeginSlice"><strong>BeginSlice</strong></a>(self, category, name, timestamp, args<font color="#909090">=None</font>)</dt><dd><tt>Opens&nbsp;a&nbsp;new&nbsp;slice&nbsp;for&nbsp;the&nbsp;thread.<br>
+Calls&nbsp;to&nbsp;beginSlice&nbsp;and&nbsp;endSlice&nbsp;must&nbsp;be&nbsp;made&nbsp;with<br>
+non-monotonically-decreasing&nbsp;timestamps.<br>
+&nbsp;<br>
+*&nbsp;category:&nbsp;Category&nbsp;to&nbsp;which&nbsp;the&nbsp;slice&nbsp;belongs.<br>
+*&nbsp;name:&nbsp;Name&nbsp;of&nbsp;the&nbsp;slice&nbsp;to&nbsp;add.<br>
+*&nbsp;timestamp:&nbsp;The&nbsp;timetsamp&nbsp;of&nbsp;the&nbsp;slice,&nbsp;in&nbsp;milliseconds.<br>
+*&nbsp;args:&nbsp;Arguments&nbsp;associated&nbsp;with<br>
+&nbsp;<br>
+Returns&nbsp;newly&nbsp;opened&nbsp;slice</tt></dd></dl>
+
+<dl><dt><a name="Thread-EndSlice"><strong>EndSlice</strong></a>(self, end_timestamp)</dt><dd><tt>Ends&nbsp;the&nbsp;last&nbsp;begun&nbsp;slice&nbsp;in&nbsp;this&nbsp;group&nbsp;and&nbsp;pushes&nbsp;it&nbsp;onto&nbsp;the&nbsp;slice<br>
+array.<br>
+&nbsp;<br>
+*&nbsp;end_timestamp:&nbsp;Timestamp&nbsp;when&nbsp;the&nbsp;slice&nbsp;ended&nbsp;in&nbsp;milliseconds<br>
+&nbsp;<br>
+returns&nbsp;completed&nbsp;slice.</tt></dd></dl>
+
+<dl><dt><a name="Thread-FinalizeImport"><strong>FinalizeImport</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Thread-IsTimestampValidForBeginOrEnd"><strong>IsTimestampValidForBeginOrEnd</strong></a>(self, timestamp)</dt></dl>
+
+<dl><dt><a name="Thread-IterAllSlices"><strong>IterAllSlices</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Thread-IterChildContainers"><strong>IterChildContainers</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Thread-IterEventsInThisContainer"><strong>IterEventsInThisContainer</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Thread-PushSlice"><strong>PushSlice</strong></a>(self, new_slice)</dt></dl>
+
+<dl><dt><a name="Thread-__init__"><strong>__init__</strong></a>(self, process, tid)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>all_slices</strong></dt>
+</dl>
+<dl><dt><strong>async_slices</strong></dt>
+</dl>
+<dl><dt><strong>open_slice_count</strong></dt>
+</dl>
+<dl><dt><strong>samples</strong></dt>
+</dl>
+<dl><dt><strong>toplevel_slices</strong></dt>
+</dl>
+<hr>
+Data descriptors inherited from <a href="telemetry.core.timeline.event_container.html#TimelineEventContainer">telemetry.core.timeline.event_container.TimelineEventContainer</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.timeline.trace_event_importer.html b/chromium/tools/telemetry/docs/telemetry.core.timeline.trace_event_importer.html
new file mode 100644
index 00000000000..6f005aa452b
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.timeline.trace_event_importer.html
@@ -0,0 +1,78 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.timeline.trace_event_importer</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.<a href="telemetry.core.timeline.html"><font color="#ffffff">timeline</font></a>.trace_event_importer</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/timeline/trace_event_importer.py">telemetry/core/timeline/trace_event_importer.py</a></font></td></tr></table>
+ <p><tt>TraceEventImporter&nbsp;imports&nbsp;TraceEvent-formatted&nbsp;data<br>
+into&nbsp;the&nbsp;provided&nbsp;model.<br>
+This&nbsp;is&nbsp;a&nbsp;port&nbsp;of&nbsp;the&nbsp;trace&nbsp;event&nbsp;importer&nbsp;from<br>
+https://code.google.com/p/trace-viewer/</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="copy.html">copy</a><br>
+<a href="telemetry.core.timeline.importer.html">telemetry.core.timeline.importer</a><br>
+</td><td width="25%" valign=top><a href="json.html">json</a><br>
+<a href="re.html">re</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.timeline.async_slice.html">telemetry.core.timeline.async_slice</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.importer.html#TimelineImporter">telemetry.core.timeline.importer.TimelineImporter</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.timeline.trace_event_importer.html#TraceEventTimelineImporter">TraceEventTimelineImporter</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TraceEventTimelineImporter">class <strong>TraceEventTimelineImporter</strong></a>(<a href="telemetry.core.timeline.importer.html#TimelineImporter">telemetry.core.timeline.importer.TimelineImporter</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.timeline.trace_event_importer.html#TraceEventTimelineImporter">TraceEventTimelineImporter</a></dd>
+<dd><a href="telemetry.core.timeline.importer.html#TimelineImporter">telemetry.core.timeline.importer.TimelineImporter</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="TraceEventTimelineImporter-FinalizeImport"><strong>FinalizeImport</strong></a>(self)</dt><dd><tt>Called&nbsp;by&nbsp;the&nbsp;Model&nbsp;after&nbsp;all&nbsp;other&nbsp;importers&nbsp;have&nbsp;imported&nbsp;their<br>
+events.</tt></dd></dl>
+
+<dl><dt><a name="TraceEventTimelineImporter-ImportEvents"><strong>ImportEvents</strong></a>(self)</dt><dd><tt>Walks&nbsp;through&nbsp;the&nbsp;events_&nbsp;list&nbsp;and&nbsp;outputs&nbsp;the&nbsp;structures&nbsp;discovered&nbsp;to<br>
+model_.</tt></dd></dl>
+
+<dl><dt><a name="TraceEventTimelineImporter-__init__"><strong>__init__</strong></a>(self, model, event_data)</dt></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="TraceEventTimelineImporter-CanImport"><strong>CanImport</strong></a>(event_data)</dt><dd><tt>Returns&nbsp;whether&nbsp;obj&nbsp;is&nbsp;a&nbsp;TraceEvent&nbsp;array.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.timeline.importer.html#TimelineImporter">telemetry.core.timeline.importer.TimelineImporter</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.user_agent.html b/chromium/tools/telemetry/docs/telemetry.core.user_agent.html
new file mode 100644
index 00000000000..22e359f9081
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.user_agent.html
@@ -0,0 +1,33 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.user_agent</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.user_agent</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/user_agent.py">telemetry/core/user_agent.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-GetChromeUserAgentArgumentFromType"><strong>GetChromeUserAgentArgumentFromType</strong></a>(user_agent_type)</dt><dd><tt>Returns&nbsp;a&nbsp;chrome&nbsp;user&nbsp;agent&nbsp;based&nbsp;on&nbsp;a&nbsp;user&nbsp;agent&nbsp;type.<br>
+This&nbsp;is&nbsp;derived&nbsp;from:<br>
+https://developers.google.com/chrome/mobile/docs/user-agent</tt></dd></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>UA_TYPE_MAPPING</strong> = {'desktop': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) A...L, like Gecko) Chrome/27.0.1453.111 Safari/537.22', 'mobile': 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus ... Gecko) Chrome/27.0.1453.111 Mobile Safari/535.19', 'tablet': 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus ...L, like Gecko) Chrome/27.0.1453.111 Safari/535.19'}</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.util.html b/chromium/tools/telemetry/docs/telemetry.core.util.html
new file mode 100644
index 00000000000..22e40662c2e
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.util.html
@@ -0,0 +1,138 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.util</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.util</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/util.py">telemetry/core/util.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="inspect.html">inspect</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="socket.html">socket</a><br>
+</td><td width="25%" valign=top><a href="time.html">time</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.util.html#PortPair">PortPair</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.util.html#TimeoutException">TimeoutException</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PortPair">class <strong>PortPair</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PortPair-__init__"><strong>__init__</strong></a>(self, local_port, remote_port)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TimeoutException">class <strong>TimeoutException</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.util.html#TimeoutException">TimeoutException</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="TimeoutException-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#TimeoutException-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#TimeoutException-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="TimeoutException-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#TimeoutException-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="TimeoutException-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#TimeoutException-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="TimeoutException-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#TimeoutException-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="TimeoutException-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#TimeoutException-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="TimeoutException-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="TimeoutException-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#TimeoutException-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="TimeoutException-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#TimeoutException-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="TimeoutException-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="TimeoutException-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#TimeoutException-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="TimeoutException-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-CloseConnections"><strong>CloseConnections</strong></a>(tab)</dt><dd><tt>Closes&nbsp;all&nbsp;TCP&nbsp;sockets&nbsp;held&nbsp;open&nbsp;by&nbsp;the&nbsp;browser.</tt></dd></dl>
+ <dl><dt><a name="-FindElementAndPerformAction"><strong>FindElementAndPerformAction</strong></a>(tab, text, callback_code)</dt><dd><tt>JavaScript&nbsp;snippet&nbsp;for&nbsp;finding&nbsp;an&nbsp;element&nbsp;with&nbsp;a&nbsp;given&nbsp;text&nbsp;on&nbsp;a&nbsp;page.</tt></dd></dl>
+ <dl><dt><a name="-GetAvailableLocalPort"><strong>GetAvailableLocalPort</strong></a>()</dt></dl>
+ <dl><dt><a name="-GetChromiumSrcDir"><strong>GetChromiumSrcDir</strong></a>()</dt></dl>
+ <dl><dt><a name="-GetTelemetryDir"><strong>GetTelemetryDir</strong></a>()</dt></dl>
+ <dl><dt><a name="-GetUnittestDataDir"><strong>GetUnittestDataDir</strong></a>()</dt></dl>
+ <dl><dt><a name="-WaitFor"><strong>WaitFor</strong></a>(condition, timeout, poll_interval<font color="#909090">=0.1</font>, pass_time_left_to_func<font color="#909090">=False</font>)</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.web_contents.html b/chromium/tools/telemetry/docs/telemetry.core.web_contents.html
new file mode 100644
index 00000000000..86bcd14b07c
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.web_contents.html
@@ -0,0 +1,94 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.web_contents</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.web_contents</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/web_contents.py">telemetry/core/web_contents.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.web_contents.html#WebContents">WebContents</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="WebContents">class <strong>WebContents</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;web&nbsp;contents&nbsp;in&nbsp;the&nbsp;browser<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="WebContents-Close"><strong>Close</strong></a>(self)</dt><dd><tt>Closes&nbsp;this&nbsp;page.<br>
+&nbsp;<br>
+Not&nbsp;all&nbsp;browsers&nbsp;or&nbsp;browser&nbsp;versions&nbsp;support&nbsp;this&nbsp;method.<br>
+Be&nbsp;sure&nbsp;to&nbsp;check&nbsp;browser.supports_tab_control.</tt></dd></dl>
+
+<dl><dt><a name="WebContents-Disconnect"><strong>Disconnect</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WebContents-EvaluateJavaScript"><strong>EvaluateJavaScript</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Evalutes&nbsp;expr&nbsp;in&nbsp;JavaScript&nbsp;and&nbsp;returns&nbsp;the&nbsp;JSONized&nbsp;result.<br>
+&nbsp;<br>
+Consider&nbsp;using&nbsp;ExecuteJavaScript&nbsp;for&nbsp;cases&nbsp;where&nbsp;the&nbsp;result&nbsp;of&nbsp;the<br>
+expression&nbsp;is&nbsp;not&nbsp;needed.<br>
+&nbsp;<br>
+If&nbsp;evaluation&nbsp;throws&nbsp;in&nbsp;JavaScript,&nbsp;a&nbsp;Python&nbsp;EvaluateException&nbsp;will<br>
+be&nbsp;raised.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;result&nbsp;of&nbsp;the&nbsp;evaluation&nbsp;cannot&nbsp;be&nbsp;JSONized,&nbsp;then&nbsp;an<br>
+EvaluationException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="WebContents-ExecuteJavaScript"><strong>ExecuteJavaScript</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Executes&nbsp;expr&nbsp;in&nbsp;JavaScript.&nbsp;Does&nbsp;not&nbsp;return&nbsp;the&nbsp;result.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;expression&nbsp;failed&nbsp;to&nbsp;evaluate,&nbsp;EvaluateException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="WebContents-StartTimelineRecording"><strong>StartTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WebContents-StopTimelineRecording"><strong>StopTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WebContents-WaitForDocumentReadyStateToBeComplete"><strong>WaitForDocumentReadyStateToBeComplete</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<dl><dt><a name="WebContents-WaitForDocumentReadyStateToBeInteractiveOrBetter"><strong>WaitForDocumentReadyStateToBeInteractiveOrBetter</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<dl><dt><a name="WebContents-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WebContents-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>message_output_stream</strong></dt>
+</dl>
+<dl><dt><strong>timeline_model</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>DEFAULT_WEB_CONTENTS_TIMEOUT</strong> = 60</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.wpr_modes.html b/chromium/tools/telemetry/docs/telemetry.core.wpr_modes.html
new file mode 100644
index 00000000000..99c8ac01b46
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.wpr_modes.html
@@ -0,0 +1,25 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.wpr_modes</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.wpr_modes</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/wpr_modes.py">telemetry/core/wpr_modes.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>WPR_OFF</strong> = 'wpr-off'<br>
+<strong>WPR_RECORD</strong> = 'wpr-record'<br>
+<strong>WPR_REPLAY</strong> = 'wpr-replay'</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.core.wpr_server.html b/chromium/tools/telemetry/docs/telemetry.core.wpr_server.html
new file mode 100644
index 00000000000..4cfd8cada96
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.core.wpr_server.html
@@ -0,0 +1,74 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.core.wpr_server</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.core.html"><font color="#ffffff">core</font></a>.wpr_server</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/core/wpr_server.py">telemetry/core/wpr_server.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top><a href="webpagereplay.html">webpagereplay</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.wpr_server.html#ReplayServer">ReplayServer</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ReplayServer">class <strong>ReplayServer</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="ReplayServer-Close"><strong>Close</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ReplayServer-__enter__"><strong>__enter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ReplayServer-__exit__"><strong>__exit__</strong></a>(self, *args)</dt></dl>
+
+<dl><dt><a name="ReplayServer-__init__"><strong>__init__</strong></a>(self, browser_backend, path, is_record_mode, is_append_mode, make_javascript_deterministic, webpagereplay_host, webpagereplay_local_http_port, webpagereplay_local_https_port, webpagereplay_remote_http_port, webpagereplay_remote_https_port)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-GetChromeFlags"><strong>GetChromeFlags</strong></a>(replay_host, http_port, https_port)</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.html b/chromium/tools/telemetry/docs/telemetry.html
new file mode 100644
index 00000000000..5b75b23a945
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.html
@@ -0,0 +1,491 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>telemetry</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/__init__.py">telemetry/__init__.py</a></font></td></tr></table>
+ <p><tt>A&nbsp;library&nbsp;for&nbsp;cross-platform&nbsp;browser&nbsp;tests.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.html"><strong>core</strong>&nbsp;(package)</a><br>
+<a href="telemetry.page.html"><strong>page</strong>&nbsp;(package)</a><br>
+</td><td width="25%" valign=top><a href="telemetry.test.html">test</a><br>
+<a href="telemetry.test_runner.html">test_runner</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.html"><strong>unittest</strong>&nbsp;(package)</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.browser.html#Browser">telemetry.core.browser.Browser</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="optparse.html#Values">optparse.Values</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.browser_options.html#BrowserOptions">telemetry.core.browser_options.BrowserOptions</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.core.tab.html#Tab">telemetry.core.tab.Tab</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement.html#PageMeasurement">telemetry.page.page_measurement.PageMeasurement</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Browser">class <strong>Browser</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;running&nbsp;browser&nbsp;instance&nbsp;that&nbsp;can&nbsp;be&nbsp;controlled&nbsp;in&nbsp;a&nbsp;limited&nbsp;way.<br>
+&nbsp;<br>
+To&nbsp;create&nbsp;a&nbsp;browser&nbsp;instance,&nbsp;use&nbsp;browser_finder.FindBrowser.<br>
+&nbsp;<br>
+Be&nbsp;sure&nbsp;to&nbsp;clean&nbsp;up&nbsp;after&nbsp;yourself&nbsp;by&nbsp;calling&nbsp;<a href="#Browser-Close">Close</a>()&nbsp;when&nbsp;you&nbsp;are&nbsp;done&nbsp;with<br>
+the&nbsp;browser.&nbsp;Or&nbsp;better&nbsp;yet:<br>
+&nbsp;&nbsp;browser_to_create&nbsp;=&nbsp;FindBrowser(options)<br>
+&nbsp;&nbsp;with&nbsp;browser_to_create.Create()&nbsp;as&nbsp;browser:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;do&nbsp;all&nbsp;your&nbsp;operations&nbsp;on&nbsp;browser&nbsp;here<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Browser-Close"><strong>Close</strong></a>(self)</dt><dd><tt>Closes&nbsp;this&nbsp;browser.</tt></dd></dl>
+
+<dl><dt><a name="Browser-GetStackTrace"><strong>GetStackTrace</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Browser-GetStandardOutput"><strong>GetStandardOutput</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Browser-GetTraceResultAndReset"><strong>GetTraceResultAndReset</strong></a>(self)</dt><dd><tt>Returns&nbsp;the&nbsp;result&nbsp;of&nbsp;the&nbsp;trace,&nbsp;as&nbsp;TraceResult&nbsp;<a href="__builtin__.html#object">object</a>.</tt></dd></dl>
+
+<dl><dt><a name="Browser-SetHTTPServerDirectories"><strong>SetHTTPServerDirectories</strong></a>(self, paths)</dt><dd><tt>Returns&nbsp;True&nbsp;if&nbsp;the&nbsp;HTTP&nbsp;server&nbsp;was&nbsp;started,&nbsp;False&nbsp;otherwise.</tt></dd></dl>
+
+<dl><dt><a name="Browser-SetReplayArchivePath"><strong>SetReplayArchivePath</strong></a>(self, archive_path, append_to_existing_wpr<font color="#909090">=False</font>, make_javascript_deterministic<font color="#909090">=True</font>)</dt></dl>
+
+<dl><dt><a name="Browser-StartProfiling"><strong>StartProfiling</strong></a>(self, options, base_output_file)</dt><dd><tt>Starts&nbsp;profiling&nbsp;using&nbsp;|options|.profiler_tool.&nbsp;Results&nbsp;are&nbsp;saved&nbsp;to<br>
+|base_output_file|.&lt;process_name&gt;.</tt></dd></dl>
+
+<dl><dt><a name="Browser-StartTracing"><strong>StartTracing</strong></a>(self, custom_categories<font color="#909090">=None</font>, timeout<font color="#909090">=10</font>)</dt></dl>
+
+<dl><dt><a name="Browser-StopProfiling"><strong>StopProfiling</strong></a>(self)</dt><dd><tt>Stops&nbsp;all&nbsp;active&nbsp;profilers&nbsp;and&nbsp;saves&nbsp;their&nbsp;results.</tt></dd></dl>
+
+<dl><dt><a name="Browser-StopTracing"><strong>StopTracing</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Browser-__enter__"><strong>__enter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Browser-__exit__"><strong>__exit__</strong></a>(self, *args)</dt></dl>
+
+<dl><dt><a name="Browser-__init__"><strong>__init__</strong></a>(self, backend, platform_backend)</dt></dl>
+
+<dl><dt><a name="Browser-is_profiler_active"><strong>is_profiler_active</strong></a>(self, profiler_name)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>browser_type</strong></dt>
+</dl>
+<dl><dt><strong>extensions</strong></dt>
+<dd><tt>Returns&nbsp;the&nbsp;extension&nbsp;dictionary&nbsp;if&nbsp;it&nbsp;exists.</tt></dd>
+</dl>
+<dl><dt><strong>http_server</strong></dt>
+</dl>
+<dl><dt><strong>io_stats</strong></dt>
+<dd><tt>Returns&nbsp;a&nbsp;dict&nbsp;of&nbsp;IO&nbsp;statistics&nbsp;for&nbsp;the&nbsp;browser:<br>
+{&nbsp;'Browser':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadOperationCount':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteOperationCount':&nbsp;X,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadTransferCount':&nbsp;Y,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteTransferCount':&nbsp;Z<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'Gpu':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadOperationCount':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteOperationCount':&nbsp;X,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadTransferCount':&nbsp;Y,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteTransferCount':&nbsp;Z<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'Renderer':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadOperationCount':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteOperationCount':&nbsp;X,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ReadTransferCount':&nbsp;Y,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WriteTransferCount':&nbsp;Z<br>
+&nbsp;&nbsp;}<br>
+}</tt></dd>
+</dl>
+<dl><dt><strong>is_content_shell</strong></dt>
+<dd><tt>Returns&nbsp;whether&nbsp;this&nbsp;browser&nbsp;is&nbsp;a&nbsp;content&nbsp;shell,&nbsp;only.</tt></dd>
+</dl>
+<dl><dt><strong>memory_stats</strong></dt>
+<dd><tt>Returns&nbsp;a&nbsp;dict&nbsp;of&nbsp;memory&nbsp;statistics&nbsp;for&nbsp;the&nbsp;browser:<br>
+{&nbsp;'Browser':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VM':&nbsp;S,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VMPeak':&nbsp;T,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSize':&nbsp;U,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSizePeak':&nbsp;V,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ProportionalSetSize':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'PrivateDirty':&nbsp;X<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'Gpu':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VM':&nbsp;S,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VMPeak':&nbsp;T,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSize':&nbsp;U,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSizePeak':&nbsp;V,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ProportionalSetSize':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'PrivateDirty':&nbsp;X<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'Renderer':&nbsp;{<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VM':&nbsp;S,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'VMPeak':&nbsp;T,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSize':&nbsp;U,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'WorkingSetSizePeak':&nbsp;V,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'ProportionalSetSize':&nbsp;W,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;'PrivateDirty':&nbsp;X<br>
+&nbsp;&nbsp;},<br>
+&nbsp;&nbsp;'SystemCommitCharge':&nbsp;Y,<br>
+&nbsp;&nbsp;'ProcessCount':&nbsp;Z,<br>
+}<br>
+Any&nbsp;of&nbsp;the&nbsp;above&nbsp;keys&nbsp;may&nbsp;be&nbsp;missing&nbsp;on&nbsp;a&nbsp;per-platform&nbsp;basis.</tt></dd>
+</dl>
+<dl><dt><strong>platform</strong></dt>
+</dl>
+<dl><dt><strong>supports_extensions</strong></dt>
+</dl>
+<dl><dt><strong>supports_tab_control</strong></dt>
+</dl>
+<dl><dt><strong>supports_tracing</strong></dt>
+</dl>
+<dl><dt><strong>tabs</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BrowserOptions">class <strong>BrowserOptions</strong></a>(<a href="optparse.html#Values">optparse.Values</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Options&nbsp;to&nbsp;be&nbsp;used&nbsp;for&nbsp;discovering&nbsp;and&nbsp;launching&nbsp;a&nbsp;browser.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="BrowserOptions-AppendExtraBrowserArg"><strong>AppendExtraBrowserArg</strong></a>(self, arg)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-Copy"><strong>Copy</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-CreateParser"><strong>CreateParser</strong></a>(self, *args, **kwargs)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-__init__"><strong>__init__</strong></a>(self, browser_type<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="optparse.html#Values">optparse.Values</a>:<br>
+<dl><dt><a name="BrowserOptions-__cmp__"><strong>__cmp__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-__repr__"><strong>__repr__</strong></a> = _repr(self)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-__str__"><strong>__str__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-ensure_value"><strong>ensure_value</strong></a>(self, attr, value)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-read_file"><strong>read_file</strong></a>(self, filename, mode<font color="#909090">='careful'</font>)</dt></dl>
+
+<dl><dt><a name="BrowserOptions-read_module"><strong>read_module</strong></a>(self, modname, mode<font color="#909090">='careful'</font>)</dt></dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageMeasurement">class <strong>PageMeasurement</strong></a>(<a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Glue&nbsp;code&nbsp;for&nbsp;running&nbsp;a&nbsp;measurement&nbsp;across&nbsp;a&nbsp;set&nbsp;of&nbsp;pages.<br>
+&nbsp;<br>
+To&nbsp;use&nbsp;this,&nbsp;subclass&nbsp;from&nbsp;the&nbsp;measurement&nbsp;and&nbsp;override&nbsp;MeasurePage.&nbsp;For<br>
+example:<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;class&nbsp;BodyChildElementMeasurement(<a href="#PageMeasurement">PageMeasurement</a>):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;<a href="#PageMeasurement-MeasurePage">MeasurePage</a>(self,&nbsp;page,&nbsp;tab,&nbsp;results):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;body_child_count&nbsp;=&nbsp;tab.EvaluateJavaScript(<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'document.body.children.length')<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;results.Add('body_children',&nbsp;'count',&nbsp;body_child_count)<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;if&nbsp;__name__&nbsp;==&nbsp;'__main__':<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;page_measurement.Main(BodyChildElementMeasurement())<br>
+&nbsp;<br>
+To&nbsp;add&nbsp;test-specific&nbsp;options:<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;class&nbsp;BodyChildElementMeasurement(<a href="#PageMeasurement">PageMeasurement</a>):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;<a href="#PageMeasurement-AddCommandLineOptions">AddCommandLineOptions</a>(parser):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parser.add_option('--element',&nbsp;action='store',&nbsp;default='body')<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;<a href="#PageMeasurement-MeasurePage">MeasurePage</a>(self,&nbsp;page,&nbsp;tab,&nbsp;results):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;body_child_count&nbsp;=&nbsp;tab.EvaluateJavaScript(<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'document.querySelector('%s').children.length')<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;results.Add('children',&nbsp;'count',&nbsp;child_count)<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.page_measurement.html#PageMeasurement">PageMeasurement</a></dd>
+<dd><a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PageMeasurement-AddOutputOptions"><strong>AddOutputOptions</strong></a>(self, parser)</dt></dl>
+
+<dl><dt><a name="PageMeasurement-MeasurePage"><strong>MeasurePage</strong></a>(self, page, tab, results)</dt><dd><tt>Override&nbsp;to&nbsp;actually&nbsp;measure&nbsp;the&nbsp;page's&nbsp;performance.<br>
+&nbsp;<br>
+page&nbsp;is&nbsp;a&nbsp;page_set.Page<br>
+tab&nbsp;is&nbsp;an&nbsp;instance&nbsp;of&nbsp;telemetry.core.<a href="#Tab">Tab</a><br>
+&nbsp;<br>
+Should&nbsp;call&nbsp;results.Add(name,&nbsp;units,&nbsp;value)&nbsp;for&nbsp;each&nbsp;result,&nbsp;or&nbsp;raise&nbsp;an<br>
+exception&nbsp;on&nbsp;failure.&nbsp;The&nbsp;name&nbsp;and&nbsp;units&nbsp;of&nbsp;each&nbsp;Add()&nbsp;call&nbsp;must&nbsp;be<br>
+the&nbsp;same&nbsp;across&nbsp;all&nbsp;iterations.&nbsp;The&nbsp;name&nbsp;'url'&nbsp;must&nbsp;not&nbsp;be&nbsp;used.<br>
+&nbsp;<br>
+Prefer&nbsp;field&nbsp;names&nbsp;that&nbsp;are&nbsp;in&nbsp;accordance&nbsp;with&nbsp;python&nbsp;variable&nbsp;style.&nbsp;E.g.<br>
+field_name.<br>
+&nbsp;<br>
+Put&nbsp;together:<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;def&nbsp;<a href="#PageMeasurement-MeasurePage">MeasurePage</a>(self,&nbsp;page,&nbsp;tab,&nbsp;results):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&nbsp;=&nbsp;tab.EvaluateJavaScript('2+2')<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;res&nbsp;!=&nbsp;4:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise&nbsp;Exception('Oh,&nbsp;wow.')<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;results.Add('two_plus_two',&nbsp;'count',&nbsp;res)</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-PrepareResults"><strong>PrepareResults</strong></a>(self, options)</dt></dl>
+
+<dl><dt><a name="PageMeasurement-__init__"><strong>__init__</strong></a>(self, action_name_to_run<font color="#909090">=''</font>, needs_browser_restart_after_each_run<font color="#909090">=False</font>, discard_first_result<font color="#909090">=False</font>, clear_cache_before_each_run<font color="#909090">=False</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>output_format_choices</strong></dt>
+</dl>
+<dl><dt><strong>results_are_the_same_on_every_page</strong></dt>
+<dd><tt>By&nbsp;default,&nbsp;measurements&nbsp;are&nbsp;assumed&nbsp;to&nbsp;output&nbsp;the&nbsp;same&nbsp;values&nbsp;for&nbsp;every<br>
+page.&nbsp;This&nbsp;allows&nbsp;incremental&nbsp;output,&nbsp;for&nbsp;example&nbsp;in&nbsp;CSV.&nbsp;If,&nbsp;however,&nbsp;the<br>
+measurement&nbsp;discovers&nbsp;what&nbsp;values&nbsp;it&nbsp;can&nbsp;report&nbsp;as&nbsp;it&nbsp;goes,&nbsp;and&nbsp;those&nbsp;values<br>
+may&nbsp;vary&nbsp;from&nbsp;page&nbsp;to&nbsp;page,&nbsp;you&nbsp;need&nbsp;to&nbsp;override&nbsp;this&nbsp;function&nbsp;and&nbsp;return<br>
+False.&nbsp;Output&nbsp;will&nbsp;not&nbsp;appear&nbsp;in&nbsp;this&nbsp;mode&nbsp;until&nbsp;the&nbsp;entire&nbsp;pageset&nbsp;has<br>
+run.</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>:<br>
+<dl><dt><a name="PageMeasurement-AddCommandLineOptions"><strong>AddCommandLineOptions</strong></a>(self, parser)</dt><dd><tt>Override&nbsp;to&nbsp;expose&nbsp;command-line&nbsp;options&nbsp;for&nbsp;this&nbsp;test.<br>
+&nbsp;<br>
+The&nbsp;provided&nbsp;parser&nbsp;is&nbsp;an&nbsp;optparse.OptionParser&nbsp;instance&nbsp;and&nbsp;accepts&nbsp;all<br>
+normal&nbsp;results.&nbsp;The&nbsp;parsed&nbsp;options&nbsp;are&nbsp;available&nbsp;in&nbsp;Run&nbsp;as<br>
+self.<strong>options</strong>.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-CanRunForPage"><strong>CanRunForPage</strong></a>(self, page)</dt><dd><tt>Override&nbsp;to&nbsp;customize&nbsp;if&nbsp;the&nbsp;test&nbsp;can&nbsp;be&nbsp;ran&nbsp;for&nbsp;the&nbsp;given&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-CreatePageSet"><strong>CreatePageSet</strong></a>(self, args, options)</dt><dd><tt>Override&nbsp;to&nbsp;make&nbsp;this&nbsp;test&nbsp;generate&nbsp;its&nbsp;own&nbsp;page&nbsp;set&nbsp;instead&nbsp;of<br>
+allowing&nbsp;arbitrary&nbsp;page&nbsp;sets&nbsp;entered&nbsp;from&nbsp;the&nbsp;command-line.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;test-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;<a href="#BrowserOptions">BrowserOptions</a>&nbsp;<a href="__builtin__.html#object">object</a></tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-CustomizeBrowserOptionsForPage"><strong>CustomizeBrowserOptionsForPage</strong></a>(self, page, options)</dt><dd><tt>Add&nbsp;options&nbsp;specific&nbsp;to&nbsp;the&nbsp;test&nbsp;and&nbsp;the&nbsp;given&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-DidNavigateToPage"><strong>DidNavigateToPage</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;right&nbsp;after&nbsp;the&nbsp;page&nbsp;is&nbsp;navigated,&nbsp;but&nbsp;before<br>
+any&nbsp;waiting&nbsp;for&nbsp;completion&nbsp;has&nbsp;occurred.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-DidRunAction"><strong>DidRunAction</strong></a>(self, page, tab, action)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;running&nbsp;the&nbsp;action&nbsp;on&nbsp;the&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-DidRunPageSet"><strong>DidRunPageSet</strong></a>(self, tab, results)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;page&nbsp;set&nbsp;is&nbsp;completed,&nbsp;but&nbsp;before&nbsp;browser<br>
+is&nbsp;torn&nbsp;down.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-DidStartHTTPServer"><strong>DidStartHTTPServer</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;the&nbsp;HTTP&nbsp;server&nbsp;is&nbsp;started.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-NeedsBrowserRestartAfterEachRun"><strong>NeedsBrowserRestartAfterEachRun</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;specify&nbsp;browser&nbsp;restart&nbsp;after&nbsp;each&nbsp;run.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-Run"><strong>Run</strong></a>(self, options, page, tab, results)</dt></dl>
+
+<dl><dt><a name="PageMeasurement-SetUpBrowser"><strong>SetUpBrowser</strong></a>(self, browser)</dt><dd><tt>Override&nbsp;to&nbsp;customize&nbsp;the&nbsp;browser&nbsp;right&nbsp;after&nbsp;it&nbsp;has&nbsp;launched.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-WillNavigateToPage"><strong>WillNavigateToPage</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;the&nbsp;page&nbsp;is&nbsp;navigated.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab, action)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;running&nbsp;the&nbsp;action&nbsp;on&nbsp;the&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-WillRunPageSet"><strong>WillRunPageSet</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;the&nbsp;page&nbsp;set&nbsp;is&nbsp;navigated.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>action_name_to_run</strong></dt>
+</dl>
+<dl><dt><strong>clear_cache_before_each_run</strong></dt>
+<dd><tt>When&nbsp;set&nbsp;to&nbsp;True,&nbsp;the&nbsp;browser's&nbsp;disk&nbsp;and&nbsp;memory&nbsp;cache&nbsp;will&nbsp;be&nbsp;cleared<br>
+before&nbsp;each&nbsp;run.</tt></dd>
+</dl>
+<dl><dt><strong>discard_first_result</strong></dt>
+<dd><tt>When&nbsp;set&nbsp;to&nbsp;True,&nbsp;the&nbsp;first&nbsp;run&nbsp;of&nbsp;the&nbsp;test&nbsp;is&nbsp;discarded.&nbsp;&nbsp;This&nbsp;is<br>
+useful&nbsp;for&nbsp;cases&nbsp;where&nbsp;it's&nbsp;desirable&nbsp;to&nbsp;have&nbsp;some&nbsp;test&nbsp;resource&nbsp;cached&nbsp;so<br>
+the&nbsp;first&nbsp;run&nbsp;of&nbsp;the&nbsp;test&nbsp;can&nbsp;warm&nbsp;things&nbsp;up.</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Tab">class <strong>Tab</strong></a>(<a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;a&nbsp;tab&nbsp;in&nbsp;the&nbsp;browser<br>
+&nbsp;<br>
+The&nbsp;important&nbsp;parts&nbsp;of&nbsp;the&nbsp;<a href="#Tab">Tab</a>&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;are&nbsp;in&nbsp;the&nbsp;runtime&nbsp;and&nbsp;page&nbsp;objects.<br>
+E.g.:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Navigates&nbsp;the&nbsp;tab&nbsp;to&nbsp;a&nbsp;given&nbsp;url.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tab.<a href="#Tab-Navigate">Navigate</a>('<a href="http://www.google.com/">http://www.google.com/</a>')<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Evaluates&nbsp;1+1&nbsp;in&nbsp;the&nbsp;tab's&nbsp;JavaScript&nbsp;context.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tab.Evaluate('1+1')<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.core.tab.html#Tab">Tab</a></dd>
+<dd><a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Tab-Activate"><strong>Activate</strong></a>(self)</dt><dd><tt>Brings&nbsp;this&nbsp;tab&nbsp;to&nbsp;the&nbsp;foreground&nbsp;asynchronously.<br>
+&nbsp;<br>
+Not&nbsp;all&nbsp;browsers&nbsp;or&nbsp;browser&nbsp;versions&nbsp;support&nbsp;this&nbsp;method.<br>
+Be&nbsp;sure&nbsp;to&nbsp;check&nbsp;browser.supports_tab_control.<br>
+&nbsp;<br>
+Please&nbsp;note:&nbsp;this&nbsp;is&nbsp;asynchronous.&nbsp;There&nbsp;is&nbsp;a&nbsp;delay&nbsp;between&nbsp;this&nbsp;call<br>
+and&nbsp;the&nbsp;page's&nbsp;documentVisibilityState&nbsp;becoming&nbsp;'visible',&nbsp;and&nbsp;yet&nbsp;more<br>
+delay&nbsp;until&nbsp;the&nbsp;actual&nbsp;tab&nbsp;is&nbsp;visible&nbsp;to&nbsp;the&nbsp;user.&nbsp;None&nbsp;of&nbsp;these&nbsp;delays<br>
+are&nbsp;included&nbsp;in&nbsp;this&nbsp;call.</tt></dd></dl>
+
+<dl><dt><a name="Tab-ClearCache"><strong>ClearCache</strong></a>(self)</dt><dd><tt>Clears&nbsp;the&nbsp;browser's&nbsp;HTTP&nbsp;disk&nbsp;cache&nbsp;and&nbsp;the&nbsp;tab's&nbsp;HTTP&nbsp;memory&nbsp;cache.</tt></dd></dl>
+
+<dl><dt><a name="Tab-CollectGarbage"><strong>CollectGarbage</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-GetCookieByName"><strong>GetCookieByName</strong></a>(self, name, timeout<font color="#909090">=60</font>)</dt><dd><tt>Returns&nbsp;the&nbsp;value&nbsp;of&nbsp;the&nbsp;cookie&nbsp;by&nbsp;the&nbsp;given&nbsp;|name|.</tt></dd></dl>
+
+<dl><dt><a name="Tab-Navigate"><strong>Navigate</strong></a>(self, url, script_to_evaluate_on_commit<font color="#909090">=None</font>, timeout<font color="#909090">=60</font>)</dt><dd><tt>Navigates&nbsp;to&nbsp;url.<br>
+&nbsp;<br>
+If&nbsp;|script_to_evaluate_on_commit|&nbsp;is&nbsp;given,&nbsp;the&nbsp;script&nbsp;source&nbsp;string&nbsp;will&nbsp;be<br>
+evaluated&nbsp;when&nbsp;the&nbsp;navigation&nbsp;is&nbsp;committed.&nbsp;This&nbsp;is&nbsp;after&nbsp;the&nbsp;context&nbsp;of<br>
+the&nbsp;page&nbsp;exists,&nbsp;but&nbsp;before&nbsp;any&nbsp;script&nbsp;on&nbsp;the&nbsp;page&nbsp;itself&nbsp;has&nbsp;executed.</tt></dd></dl>
+
+<dl><dt><a name="Tab-PerformActionAndWaitForNavigate"><strong>PerformActionAndWaitForNavigate</strong></a>(self, action_function, timeout<font color="#909090">=60</font>)</dt><dd><tt>Executes&nbsp;action_function,&nbsp;and&nbsp;waits&nbsp;for&nbsp;the&nbsp;navigation&nbsp;to&nbsp;complete.<br>
+&nbsp;<br>
+action_function&nbsp;must&nbsp;be&nbsp;a&nbsp;Python&nbsp;function&nbsp;that&nbsp;results&nbsp;in&nbsp;a&nbsp;navigation.<br>
+This&nbsp;function&nbsp;returns&nbsp;when&nbsp;the&nbsp;navigation&nbsp;is&nbsp;complete&nbsp;or&nbsp;when<br>
+the&nbsp;timeout&nbsp;has&nbsp;been&nbsp;exceeded.</tt></dd></dl>
+
+<dl><dt><a name="Tab-Screenshot"><strong>Screenshot</strong></a>(self, timeout<font color="#909090">=60</font>)</dt><dd><tt>Capture&nbsp;a&nbsp;screenshot&nbsp;of&nbsp;the&nbsp;window&nbsp;for&nbsp;rendering&nbsp;validation</tt></dd></dl>
+
+<dl><dt><a name="Tab-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-__init__"><strong>__init__</strong></a>(self, inspector_backend)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>browser</strong></dt>
+<dd><tt>The&nbsp;browser&nbsp;in&nbsp;which&nbsp;this&nbsp;tab&nbsp;resides.</tt></dd>
+</dl>
+<dl><dt><strong>dom_stats</strong></dt>
+<dd><tt>A&nbsp;dictionary&nbsp;populated&nbsp;with&nbsp;measured&nbsp;DOM&nbsp;statistics.<br>
+&nbsp;<br>
+Currently&nbsp;this&nbsp;dictionary&nbsp;contains:<br>
+{<br>
+&nbsp;&nbsp;'document_count':&nbsp;integer,<br>
+&nbsp;&nbsp;'node_count':&nbsp;integer,<br>
+&nbsp;&nbsp;'event_listener_count':&nbsp;integer<br>
+}</tt></dd>
+</dl>
+<dl><dt><strong>screenshot_supported</strong></dt>
+<dd><tt>True&nbsp;if&nbsp;the&nbsp;browser&nbsp;instance&nbsp;is&nbsp;capable&nbsp;of&nbsp;capturing&nbsp;screenshots</tt></dd>
+</dl>
+<dl><dt><strong>url</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>:<br>
+<dl><dt><a name="Tab-Close"><strong>Close</strong></a>(self)</dt><dd><tt>Closes&nbsp;this&nbsp;page.<br>
+&nbsp;<br>
+Not&nbsp;all&nbsp;browsers&nbsp;or&nbsp;browser&nbsp;versions&nbsp;support&nbsp;this&nbsp;method.<br>
+Be&nbsp;sure&nbsp;to&nbsp;check&nbsp;browser.supports_tab_control.</tt></dd></dl>
+
+<dl><dt><a name="Tab-Disconnect"><strong>Disconnect</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-EvaluateJavaScript"><strong>EvaluateJavaScript</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Evalutes&nbsp;expr&nbsp;in&nbsp;JavaScript&nbsp;and&nbsp;returns&nbsp;the&nbsp;JSONized&nbsp;result.<br>
+&nbsp;<br>
+Consider&nbsp;using&nbsp;ExecuteJavaScript&nbsp;for&nbsp;cases&nbsp;where&nbsp;the&nbsp;result&nbsp;of&nbsp;the<br>
+expression&nbsp;is&nbsp;not&nbsp;needed.<br>
+&nbsp;<br>
+If&nbsp;evaluation&nbsp;throws&nbsp;in&nbsp;JavaScript,&nbsp;a&nbsp;Python&nbsp;EvaluateException&nbsp;will<br>
+be&nbsp;raised.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;result&nbsp;of&nbsp;the&nbsp;evaluation&nbsp;cannot&nbsp;be&nbsp;JSONized,&nbsp;then&nbsp;an<br>
+EvaluationException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="Tab-ExecuteJavaScript"><strong>ExecuteJavaScript</strong></a>(self, expr, timeout<font color="#909090">=60</font>)</dt><dd><tt>Executes&nbsp;expr&nbsp;in&nbsp;JavaScript.&nbsp;Does&nbsp;not&nbsp;return&nbsp;the&nbsp;result.<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;expression&nbsp;failed&nbsp;to&nbsp;evaluate,&nbsp;EvaluateException&nbsp;will&nbsp;be&nbsp;raised.</tt></dd></dl>
+
+<dl><dt><a name="Tab-StartTimelineRecording"><strong>StartTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-StopTimelineRecording"><strong>StopTimelineRecording</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Tab-WaitForDocumentReadyStateToBeComplete"><strong>WaitForDocumentReadyStateToBeComplete</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<dl><dt><a name="Tab-WaitForDocumentReadyStateToBeInteractiveOrBetter"><strong>WaitForDocumentReadyStateToBeInteractiveOrBetter</strong></a>(self, timeout<font color="#909090">=60</font>)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.core.web_contents.html#WebContents">telemetry.core.web_contents.WebContents</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>message_output_stream</strong></dt>
+</dl>
+<dl><dt><strong>timeline_model</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-RunPage"><strong>RunPage</strong></a> = Run(test, page_set, options)</dt><dd><tt>Runs&nbsp;a&nbsp;given&nbsp;test&nbsp;against&nbsp;a&nbsp;given&nbsp;page_set&nbsp;with&nbsp;the&nbsp;given&nbsp;options.</tt></dd></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>__all__</strong> = ['Browser', 'BrowserOptions', 'PageMeasurement', 'RunPage', 'Tab']</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.all_page_actions.html b/chromium/tools/telemetry/docs/telemetry.page.actions.all_page_actions.html
new file mode 100644
index 00000000000..5427691655b
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.all_page_actions.html
@@ -0,0 +1,36 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.actions.all_page_actions</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.<a href="telemetry.page.actions.html"><font color="#ffffff">actions</font></a>.all_page_actions</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/all_page_actions.py">telemetry/page/actions/all_page_actions.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.discover.html">telemetry.core.discover</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.actions.page_action.html">telemetry.page.actions.page_action</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-FindClassWithName"><strong>FindClassWithName</strong></a>(name)</dt></dl>
+ <dl><dt><a name="-GetAllClasses"><strong>GetAllClasses</strong></a>()</dt></dl>
+ <dl><dt><a name="-RegisterClassForTest"><strong>RegisterClassForTest</strong></a>(name, clazz)</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.click_element.html b/chromium/tools/telemetry/docs/telemetry.page.actions.click_element.html
new file mode 100644
index 00000000000..a55f8fc5b66
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.click_element.html
@@ -0,0 +1,99 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.actions.click_element</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.<a href="telemetry.page.actions.html"><font color="#ffffff">actions</font></a>.click_element</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/click_element.py">telemetry/page/actions/click_element.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.actions.page_action.html">telemetry.page.actions.page_action</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page.html">telemetry.page.page</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.click_element.html#ClickElementAction">ClickElementAction</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ClickElementAction">class <strong>ClickElementAction</strong></a>(<a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.actions.click_element.html#ClickElementAction">ClickElementAction</a></dd>
+<dd><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ClickElementAction-RunAction"><strong>RunAction</strong></a>(self, page, tab, previous_action)</dt></dl>
+
+<dl><dt><a name="ClickElementAction-__init__"><strong>__init__</strong></a>(self, attributes<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><a name="ClickElementAction-BindMeasurementJavaScript"><strong>BindMeasurementJavaScript</strong></a>(self, tab, start_js, stop_js)</dt><dd><tt>Let&nbsp;this&nbsp;action&nbsp;determine&nbsp;when&nbsp;measurements&nbsp;should&nbsp;start&nbsp;and&nbsp;stop.<br>
+&nbsp;<br>
+A&nbsp;measurement&nbsp;can&nbsp;call&nbsp;this&nbsp;method&nbsp;to&nbsp;provide&nbsp;the&nbsp;action<br>
+with&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;and&nbsp;stops&nbsp;measurements.&nbsp;The&nbsp;action<br>
+determines&nbsp;when&nbsp;to&nbsp;execute&nbsp;the&nbsp;provided&nbsp;JavaScript&nbsp;code,&nbsp;for&nbsp;more&nbsp;accurate<br>
+timings.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;tab:&nbsp;The&nbsp;tab&nbsp;to&nbsp;do&nbsp;everything&nbsp;on.<br>
+&nbsp;&nbsp;start_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;measurements.<br>
+&nbsp;&nbsp;stop_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;stops&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="ClickElementAction-CanBeBound"><strong>CanBeBound</strong></a>(self)</dt><dd><tt>If&nbsp;this&nbsp;class&nbsp;implements&nbsp;BindMeasurementJavaScript,&nbsp;override&nbsp;CanBeBound<br>
+to&nbsp;return&nbsp;True&nbsp;so&nbsp;that&nbsp;a&nbsp;test&nbsp;knows&nbsp;it&nbsp;can&nbsp;bind&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="ClickElementAction-CleanUp"><strong>CleanUp</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="ClickElementAction-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;action-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions<br>
+object.</tt></dd></dl>
+
+<dl><dt><a name="ClickElementAction-RunsPreviousAction"><strong>RunsPreviousAction</strong></a>(self)</dt><dd><tt>Some&nbsp;actions&nbsp;require&nbsp;some&nbsp;initialization&nbsp;to&nbsp;be&nbsp;performed&nbsp;before&nbsp;the<br>
+previous&nbsp;action.&nbsp;For&nbsp;example,&nbsp;wait&nbsp;for&nbsp;href&nbsp;change&nbsp;needs&nbsp;to&nbsp;record&nbsp;the&nbsp;old<br>
+href&nbsp;before&nbsp;the&nbsp;previous&nbsp;action&nbsp;changes&nbsp;it.&nbsp;Therefore,&nbsp;we&nbsp;allow&nbsp;actions&nbsp;to<br>
+run&nbsp;the&nbsp;previous&nbsp;action.&nbsp;An&nbsp;action&nbsp;that&nbsp;does&nbsp;this&nbsp;should&nbsp;override&nbsp;this&nbsp;to<br>
+return&nbsp;True&nbsp;in&nbsp;order&nbsp;to&nbsp;prevent&nbsp;the&nbsp;previous&nbsp;action&nbsp;from&nbsp;being&nbsp;run&nbsp;twice.</tt></dd></dl>
+
+<dl><dt><a name="ClickElementAction-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;action-specific&nbsp;setup&nbsp;before<br>
+Test.WillRunAction&nbsp;is&nbsp;called.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.html b/chromium/tools/telemetry/docs/telemetry.page.actions.html
new file mode 100644
index 00000000000..ae1c9533bd2
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.html
@@ -0,0 +1,33 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry.page.actions</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.actions</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/__init__.py">telemetry/page/actions/__init__.py</a></font></td></tr></table>
+ <p></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.actions.all_page_actions.html">all_page_actions</a><br>
+<a href="telemetry.page.actions.click_element.html">click_element</a><br>
+<a href="telemetry.page.actions.click_element_unittest.html">click_element_unittest</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.actions.js_collect_garbage.html">js_collect_garbage</a><br>
+<a href="telemetry.page.actions.page_action.html">page_action</a><br>
+<a href="telemetry.page.actions.play.html">play</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.actions.play_unittest.html">play_unittest</a><br>
+<a href="telemetry.page.actions.reload.html">reload</a><br>
+<a href="telemetry.page.actions.scroll.html">scroll</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.actions.scroll_unittest.html">scroll_unittest</a><br>
+<a href="telemetry.page.actions.wait.html">wait</a><br>
+<a href="telemetry.page.actions.wait_unittest.html">wait_unittest</a><br>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.js_collect_garbage.html b/chromium/tools/telemetry/docs/telemetry.page.actions.js_collect_garbage.html
new file mode 100644
index 00000000000..fee2db59984
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.js_collect_garbage.html
@@ -0,0 +1,96 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.actions.js_collect_garbage</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.<a href="telemetry.page.actions.html"><font color="#ffffff">actions</font></a>.js_collect_garbage</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/js_collect_garbage.py">telemetry/page/actions/js_collect_garbage.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.actions.page_action.html">telemetry.page.actions.page_action</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.js_collect_garbage.html#JsCollectGarbageAction">JsCollectGarbageAction</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="JsCollectGarbageAction">class <strong>JsCollectGarbageAction</strong></a>(<a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.actions.js_collect_garbage.html#JsCollectGarbageAction">JsCollectGarbageAction</a></dd>
+<dd><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="JsCollectGarbageAction-RunAction"><strong>RunAction</strong></a>(self, page, tab, previous_action)</dt></dl>
+
+<dl><dt><a name="JsCollectGarbageAction-__init__"><strong>__init__</strong></a>(self, attributes<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><a name="JsCollectGarbageAction-BindMeasurementJavaScript"><strong>BindMeasurementJavaScript</strong></a>(self, tab, start_js, stop_js)</dt><dd><tt>Let&nbsp;this&nbsp;action&nbsp;determine&nbsp;when&nbsp;measurements&nbsp;should&nbsp;start&nbsp;and&nbsp;stop.<br>
+&nbsp;<br>
+A&nbsp;measurement&nbsp;can&nbsp;call&nbsp;this&nbsp;method&nbsp;to&nbsp;provide&nbsp;the&nbsp;action<br>
+with&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;and&nbsp;stops&nbsp;measurements.&nbsp;The&nbsp;action<br>
+determines&nbsp;when&nbsp;to&nbsp;execute&nbsp;the&nbsp;provided&nbsp;JavaScript&nbsp;code,&nbsp;for&nbsp;more&nbsp;accurate<br>
+timings.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;tab:&nbsp;The&nbsp;tab&nbsp;to&nbsp;do&nbsp;everything&nbsp;on.<br>
+&nbsp;&nbsp;start_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;measurements.<br>
+&nbsp;&nbsp;stop_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;stops&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="JsCollectGarbageAction-CanBeBound"><strong>CanBeBound</strong></a>(self)</dt><dd><tt>If&nbsp;this&nbsp;class&nbsp;implements&nbsp;BindMeasurementJavaScript,&nbsp;override&nbsp;CanBeBound<br>
+to&nbsp;return&nbsp;True&nbsp;so&nbsp;that&nbsp;a&nbsp;test&nbsp;knows&nbsp;it&nbsp;can&nbsp;bind&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="JsCollectGarbageAction-CleanUp"><strong>CleanUp</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="JsCollectGarbageAction-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;action-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions<br>
+object.</tt></dd></dl>
+
+<dl><dt><a name="JsCollectGarbageAction-RunsPreviousAction"><strong>RunsPreviousAction</strong></a>(self)</dt><dd><tt>Some&nbsp;actions&nbsp;require&nbsp;some&nbsp;initialization&nbsp;to&nbsp;be&nbsp;performed&nbsp;before&nbsp;the<br>
+previous&nbsp;action.&nbsp;For&nbsp;example,&nbsp;wait&nbsp;for&nbsp;href&nbsp;change&nbsp;needs&nbsp;to&nbsp;record&nbsp;the&nbsp;old<br>
+href&nbsp;before&nbsp;the&nbsp;previous&nbsp;action&nbsp;changes&nbsp;it.&nbsp;Therefore,&nbsp;we&nbsp;allow&nbsp;actions&nbsp;to<br>
+run&nbsp;the&nbsp;previous&nbsp;action.&nbsp;An&nbsp;action&nbsp;that&nbsp;does&nbsp;this&nbsp;should&nbsp;override&nbsp;this&nbsp;to<br>
+return&nbsp;True&nbsp;in&nbsp;order&nbsp;to&nbsp;prevent&nbsp;the&nbsp;previous&nbsp;action&nbsp;from&nbsp;being&nbsp;run&nbsp;twice.</tt></dd></dl>
+
+<dl><dt><a name="JsCollectGarbageAction-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;action-specific&nbsp;setup&nbsp;before<br>
+Test.WillRunAction&nbsp;is&nbsp;called.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.page_action.html b/chromium/tools/telemetry/docs/telemetry.page.actions.page_action.html
new file mode 100644
index 00000000000..6e22906f864
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.page_action.html
@@ -0,0 +1,205 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.actions.page_action</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.<a href="telemetry.page.actions.html"><font color="#ffffff">actions</font></a>.page_action</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/page_action.py">telemetry/page/actions/page_action.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageAction">PageAction</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageActionFailed">PageActionFailed</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageActionNotSupported">PageActionNotSupported</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageAction">class <strong>PageAction</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Represents&nbsp;an&nbsp;action&nbsp;that&nbsp;a&nbsp;user&nbsp;might&nbsp;try&nbsp;to&nbsp;perform&nbsp;to&nbsp;a&nbsp;page.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PageAction-BindMeasurementJavaScript"><strong>BindMeasurementJavaScript</strong></a>(self, tab, start_js, stop_js)</dt><dd><tt>Let&nbsp;this&nbsp;action&nbsp;determine&nbsp;when&nbsp;measurements&nbsp;should&nbsp;start&nbsp;and&nbsp;stop.<br>
+&nbsp;<br>
+A&nbsp;measurement&nbsp;can&nbsp;call&nbsp;this&nbsp;method&nbsp;to&nbsp;provide&nbsp;the&nbsp;action<br>
+with&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;and&nbsp;stops&nbsp;measurements.&nbsp;The&nbsp;action<br>
+determines&nbsp;when&nbsp;to&nbsp;execute&nbsp;the&nbsp;provided&nbsp;JavaScript&nbsp;code,&nbsp;for&nbsp;more&nbsp;accurate<br>
+timings.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;tab:&nbsp;The&nbsp;tab&nbsp;to&nbsp;do&nbsp;everything&nbsp;on.<br>
+&nbsp;&nbsp;start_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;measurements.<br>
+&nbsp;&nbsp;stop_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;stops&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="PageAction-CanBeBound"><strong>CanBeBound</strong></a>(self)</dt><dd><tt>If&nbsp;this&nbsp;class&nbsp;implements&nbsp;BindMeasurementJavaScript,&nbsp;override&nbsp;CanBeBound<br>
+to&nbsp;return&nbsp;True&nbsp;so&nbsp;that&nbsp;a&nbsp;test&nbsp;knows&nbsp;it&nbsp;can&nbsp;bind&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="PageAction-CleanUp"><strong>CleanUp</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="PageAction-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;action-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions<br>
+<a href="__builtin__.html#object">object</a>.</tt></dd></dl>
+
+<dl><dt><a name="PageAction-RunAction"><strong>RunAction</strong></a>(self, page, tab, previous_action)</dt></dl>
+
+<dl><dt><a name="PageAction-RunsPreviousAction"><strong>RunsPreviousAction</strong></a>(self)</dt><dd><tt>Some&nbsp;actions&nbsp;require&nbsp;some&nbsp;initialization&nbsp;to&nbsp;be&nbsp;performed&nbsp;before&nbsp;the<br>
+previous&nbsp;action.&nbsp;For&nbsp;example,&nbsp;wait&nbsp;for&nbsp;href&nbsp;change&nbsp;needs&nbsp;to&nbsp;record&nbsp;the&nbsp;old<br>
+href&nbsp;before&nbsp;the&nbsp;previous&nbsp;action&nbsp;changes&nbsp;it.&nbsp;Therefore,&nbsp;we&nbsp;allow&nbsp;actions&nbsp;to<br>
+run&nbsp;the&nbsp;previous&nbsp;action.&nbsp;An&nbsp;action&nbsp;that&nbsp;does&nbsp;this&nbsp;should&nbsp;override&nbsp;this&nbsp;to<br>
+return&nbsp;True&nbsp;in&nbsp;order&nbsp;to&nbsp;prevent&nbsp;the&nbsp;previous&nbsp;action&nbsp;from&nbsp;being&nbsp;run&nbsp;twice.</tt></dd></dl>
+
+<dl><dt><a name="PageAction-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;action-specific&nbsp;setup&nbsp;before<br>
+Test.WillRunAction&nbsp;is&nbsp;called.</tt></dd></dl>
+
+<dl><dt><a name="PageAction-__init__"><strong>__init__</strong></a>(self, attributes<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageActionFailed">class <strong>PageActionFailed</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.actions.page_action.html#PageActionFailed">PageActionFailed</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="PageActionFailed-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionFailed-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#PageActionFailed-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="PageActionFailed-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionFailed-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="PageActionFailed-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionFailed-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="PageActionFailed-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionFailed-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="PageActionFailed-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionFailed-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="PageActionFailed-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="PageActionFailed-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionFailed-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="PageActionFailed-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionFailed-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="PageActionFailed-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="PageActionFailed-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionFailed-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="PageActionFailed-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageActionNotSupported">class <strong>PageActionNotSupported</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.actions.page_action.html#PageActionNotSupported">PageActionNotSupported</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="PageActionNotSupported-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionNotSupported-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#PageActionNotSupported-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="PageActionNotSupported-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionNotSupported-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="PageActionNotSupported-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionNotSupported-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="PageActionNotSupported-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionNotSupported-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="PageActionNotSupported-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionNotSupported-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="PageActionNotSupported-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="PageActionNotSupported-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionNotSupported-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="PageActionNotSupported-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionNotSupported-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="PageActionNotSupported-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="PageActionNotSupported-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#PageActionNotSupported-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="PageActionNotSupported-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.play.html b/chromium/tools/telemetry/docs/telemetry.page.actions.play.html
new file mode 100644
index 00000000000..88ece244290
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.play.html
@@ -0,0 +1,107 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.actions.play</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.<a href="telemetry.page.actions.html"><font color="#ffffff">actions</font></a>.play</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/play.py">telemetry/page/actions/play.py</a></font></td></tr></table>
+ <p><tt>A&nbsp;Telemetry&nbsp;page_action&nbsp;that&nbsp;performs&nbsp;the&nbsp;"play"&nbsp;action&nbsp;on&nbsp;media&nbsp;elements.<br>
+&nbsp;<br>
+Media&nbsp;elements&nbsp;can&nbsp;be&nbsp;specified&nbsp;by&nbsp;a&nbsp;selector&nbsp;attribute.&nbsp;If&nbsp;no&nbsp;selector&nbsp;is<br>
+defined&nbsp;then&nbsp;then&nbsp;the&nbsp;action&nbsp;attempts&nbsp;to&nbsp;play&nbsp;the&nbsp;first&nbsp;video&nbsp;element&nbsp;or&nbsp;audio<br>
+element&nbsp;on&nbsp;the&nbsp;page.&nbsp;A&nbsp;selector&nbsp;can&nbsp;also&nbsp;be&nbsp;'all'&nbsp;to&nbsp;play&nbsp;all&nbsp;media&nbsp;elements.<br>
+&nbsp;<br>
+Other&nbsp;attributes&nbsp;to&nbsp;use&nbsp;are:&nbsp;wait_for_playing&nbsp;and&nbsp;wait_for_ended,&nbsp;which&nbsp;forces<br>
+the&nbsp;action&nbsp;to&nbsp;wait&nbsp;until&nbsp;playing&nbsp;and&nbsp;ended&nbsp;events&nbsp;get&nbsp;fired&nbsp;respectively.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.actions.page_action.html">telemetry.page.actions.page_action</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.play.html#PlayAction">PlayAction</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PlayAction">class <strong>PlayAction</strong></a>(<a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.actions.play.html#PlayAction">PlayAction</a></dd>
+<dd><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PlayAction-HasEventCompleted"><strong>HasEventCompleted</strong></a>(self, tab, selector, event_name)</dt></dl>
+
+<dl><dt><a name="PlayAction-RunAction"><strong>RunAction</strong></a>(self, page, tab, previous_action)</dt></dl>
+
+<dl><dt><a name="PlayAction-WaitForEvent"><strong>WaitForEvent</strong></a>(self, tab, selector, event_name, timeout)</dt><dd><tt>Halts&nbsp;play&nbsp;action&nbsp;until&nbsp;the&nbsp;selector's&nbsp;event&nbsp;is&nbsp;fired.</tt></dd></dl>
+
+<dl><dt><a name="PlayAction-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab)</dt><dd><tt>Load&nbsp;the&nbsp;media&nbsp;metrics&nbsp;JS&nbsp;code&nbsp;prior&nbsp;to&nbsp;running&nbsp;the&nbsp;action.</tt></dd></dl>
+
+<dl><dt><a name="PlayAction-__init__"><strong>__init__</strong></a>(self, attributes<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><a name="PlayAction-BindMeasurementJavaScript"><strong>BindMeasurementJavaScript</strong></a>(self, tab, start_js, stop_js)</dt><dd><tt>Let&nbsp;this&nbsp;action&nbsp;determine&nbsp;when&nbsp;measurements&nbsp;should&nbsp;start&nbsp;and&nbsp;stop.<br>
+&nbsp;<br>
+A&nbsp;measurement&nbsp;can&nbsp;call&nbsp;this&nbsp;method&nbsp;to&nbsp;provide&nbsp;the&nbsp;action<br>
+with&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;and&nbsp;stops&nbsp;measurements.&nbsp;The&nbsp;action<br>
+determines&nbsp;when&nbsp;to&nbsp;execute&nbsp;the&nbsp;provided&nbsp;JavaScript&nbsp;code,&nbsp;for&nbsp;more&nbsp;accurate<br>
+timings.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;tab:&nbsp;The&nbsp;tab&nbsp;to&nbsp;do&nbsp;everything&nbsp;on.<br>
+&nbsp;&nbsp;start_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;measurements.<br>
+&nbsp;&nbsp;stop_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;stops&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="PlayAction-CanBeBound"><strong>CanBeBound</strong></a>(self)</dt><dd><tt>If&nbsp;this&nbsp;class&nbsp;implements&nbsp;BindMeasurementJavaScript,&nbsp;override&nbsp;CanBeBound<br>
+to&nbsp;return&nbsp;True&nbsp;so&nbsp;that&nbsp;a&nbsp;test&nbsp;knows&nbsp;it&nbsp;can&nbsp;bind&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="PlayAction-CleanUp"><strong>CleanUp</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="PlayAction-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;action-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions<br>
+object.</tt></dd></dl>
+
+<dl><dt><a name="PlayAction-RunsPreviousAction"><strong>RunsPreviousAction</strong></a>(self)</dt><dd><tt>Some&nbsp;actions&nbsp;require&nbsp;some&nbsp;initialization&nbsp;to&nbsp;be&nbsp;performed&nbsp;before&nbsp;the<br>
+previous&nbsp;action.&nbsp;For&nbsp;example,&nbsp;wait&nbsp;for&nbsp;href&nbsp;change&nbsp;needs&nbsp;to&nbsp;record&nbsp;the&nbsp;old<br>
+href&nbsp;before&nbsp;the&nbsp;previous&nbsp;action&nbsp;changes&nbsp;it.&nbsp;Therefore,&nbsp;we&nbsp;allow&nbsp;actions&nbsp;to<br>
+run&nbsp;the&nbsp;previous&nbsp;action.&nbsp;An&nbsp;action&nbsp;that&nbsp;does&nbsp;this&nbsp;should&nbsp;override&nbsp;this&nbsp;to<br>
+return&nbsp;True&nbsp;in&nbsp;order&nbsp;to&nbsp;prevent&nbsp;the&nbsp;previous&nbsp;action&nbsp;from&nbsp;being&nbsp;run&nbsp;twice.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.reload.html b/chromium/tools/telemetry/docs/telemetry.page.actions.reload.html
new file mode 100644
index 00000000000..31eceae39e5
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.reload.html
@@ -0,0 +1,97 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.actions.reload</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.<a href="telemetry.page.actions.html"><font color="#ffffff">actions</font></a>.reload</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/reload.py">telemetry/page/actions/reload.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.actions.page_action.html">telemetry.page.actions.page_action</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page.html">telemetry.page.page</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.reload.html#ReloadAction">ReloadAction</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ReloadAction">class <strong>ReloadAction</strong></a>(<a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.actions.reload.html#ReloadAction">ReloadAction</a></dd>
+<dd><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ReloadAction-RunAction"><strong>RunAction</strong></a>(self, page, tab, previous_action)</dt></dl>
+
+<dl><dt><a name="ReloadAction-__init__"><strong>__init__</strong></a>(self, attributes<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><a name="ReloadAction-BindMeasurementJavaScript"><strong>BindMeasurementJavaScript</strong></a>(self, tab, start_js, stop_js)</dt><dd><tt>Let&nbsp;this&nbsp;action&nbsp;determine&nbsp;when&nbsp;measurements&nbsp;should&nbsp;start&nbsp;and&nbsp;stop.<br>
+&nbsp;<br>
+A&nbsp;measurement&nbsp;can&nbsp;call&nbsp;this&nbsp;method&nbsp;to&nbsp;provide&nbsp;the&nbsp;action<br>
+with&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;and&nbsp;stops&nbsp;measurements.&nbsp;The&nbsp;action<br>
+determines&nbsp;when&nbsp;to&nbsp;execute&nbsp;the&nbsp;provided&nbsp;JavaScript&nbsp;code,&nbsp;for&nbsp;more&nbsp;accurate<br>
+timings.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;tab:&nbsp;The&nbsp;tab&nbsp;to&nbsp;do&nbsp;everything&nbsp;on.<br>
+&nbsp;&nbsp;start_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;measurements.<br>
+&nbsp;&nbsp;stop_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;stops&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="ReloadAction-CanBeBound"><strong>CanBeBound</strong></a>(self)</dt><dd><tt>If&nbsp;this&nbsp;class&nbsp;implements&nbsp;BindMeasurementJavaScript,&nbsp;override&nbsp;CanBeBound<br>
+to&nbsp;return&nbsp;True&nbsp;so&nbsp;that&nbsp;a&nbsp;test&nbsp;knows&nbsp;it&nbsp;can&nbsp;bind&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="ReloadAction-CleanUp"><strong>CleanUp</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="ReloadAction-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;action-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions<br>
+object.</tt></dd></dl>
+
+<dl><dt><a name="ReloadAction-RunsPreviousAction"><strong>RunsPreviousAction</strong></a>(self)</dt><dd><tt>Some&nbsp;actions&nbsp;require&nbsp;some&nbsp;initialization&nbsp;to&nbsp;be&nbsp;performed&nbsp;before&nbsp;the<br>
+previous&nbsp;action.&nbsp;For&nbsp;example,&nbsp;wait&nbsp;for&nbsp;href&nbsp;change&nbsp;needs&nbsp;to&nbsp;record&nbsp;the&nbsp;old<br>
+href&nbsp;before&nbsp;the&nbsp;previous&nbsp;action&nbsp;changes&nbsp;it.&nbsp;Therefore,&nbsp;we&nbsp;allow&nbsp;actions&nbsp;to<br>
+run&nbsp;the&nbsp;previous&nbsp;action.&nbsp;An&nbsp;action&nbsp;that&nbsp;does&nbsp;this&nbsp;should&nbsp;override&nbsp;this&nbsp;to<br>
+return&nbsp;True&nbsp;in&nbsp;order&nbsp;to&nbsp;prevent&nbsp;the&nbsp;previous&nbsp;action&nbsp;from&nbsp;being&nbsp;run&nbsp;twice.</tt></dd></dl>
+
+<dl><dt><a name="ReloadAction-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;action-specific&nbsp;setup&nbsp;before<br>
+Test.WillRunAction&nbsp;is&nbsp;called.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.scroll.html b/chromium/tools/telemetry/docs/telemetry.page.actions.scroll.html
new file mode 100644
index 00000000000..eca96448620
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.scroll.html
@@ -0,0 +1,85 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.actions.scroll</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.<a href="telemetry.page.actions.html"><font color="#ffffff">actions</font></a>.scroll</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/scroll.py">telemetry/page/actions/scroll.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.actions.page_action.html">telemetry.page.actions.page_action</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.scroll.html#ScrollAction">ScrollAction</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ScrollAction">class <strong>ScrollAction</strong></a>(<a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.actions.scroll.html#ScrollAction">ScrollAction</a></dd>
+<dd><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="ScrollAction-BindMeasurementJavaScript"><strong>BindMeasurementJavaScript</strong></a>(self, tab, start_js, stop_js)</dt></dl>
+
+<dl><dt><a name="ScrollAction-CanBeBound"><strong>CanBeBound</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="ScrollAction-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt></dl>
+
+<dl><dt><a name="ScrollAction-RunAction"><strong>RunAction</strong></a>(self, page, tab, previous_action)</dt></dl>
+
+<dl><dt><a name="ScrollAction-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="ScrollAction-__init__"><strong>__init__</strong></a>(self, attributes<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><a name="ScrollAction-CleanUp"><strong>CleanUp</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="ScrollAction-RunsPreviousAction"><strong>RunsPreviousAction</strong></a>(self)</dt><dd><tt>Some&nbsp;actions&nbsp;require&nbsp;some&nbsp;initialization&nbsp;to&nbsp;be&nbsp;performed&nbsp;before&nbsp;the<br>
+previous&nbsp;action.&nbsp;For&nbsp;example,&nbsp;wait&nbsp;for&nbsp;href&nbsp;change&nbsp;needs&nbsp;to&nbsp;record&nbsp;the&nbsp;old<br>
+href&nbsp;before&nbsp;the&nbsp;previous&nbsp;action&nbsp;changes&nbsp;it.&nbsp;Therefore,&nbsp;we&nbsp;allow&nbsp;actions&nbsp;to<br>
+run&nbsp;the&nbsp;previous&nbsp;action.&nbsp;An&nbsp;action&nbsp;that&nbsp;does&nbsp;this&nbsp;should&nbsp;override&nbsp;this&nbsp;to<br>
+return&nbsp;True&nbsp;in&nbsp;order&nbsp;to&nbsp;prevent&nbsp;the&nbsp;previous&nbsp;action&nbsp;from&nbsp;being&nbsp;run&nbsp;twice.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.actions.wait.html b/chromium/tools/telemetry/docs/telemetry.page.actions.wait.html
new file mode 100644
index 00000000000..b58f6c7d819
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.actions.wait.html
@@ -0,0 +1,98 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.actions.wait</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.<a href="telemetry.page.actions.html"><font color="#ffffff">actions</font></a>.wait</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/actions/wait.py">telemetry/page/actions/wait.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.actions.page_action.html">telemetry.page.actions.page_action</a><br>
+</td><td width="25%" valign=top><a href="time.html">time</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.actions.wait.html#WaitAction">WaitAction</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="WaitAction">class <strong>WaitAction</strong></a>(<a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.actions.wait.html#WaitAction">WaitAction</a></dd>
+<dd><a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="WaitAction-RunAction"><strong>RunAction</strong></a>(self, page, tab, previous_action)</dt></dl>
+
+<dl><dt><a name="WaitAction-RunsPreviousAction"><strong>RunsPreviousAction</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="WaitAction-__init__"><strong>__init__</strong></a>(self, attributes<font color="#909090">=None</font>)</dt></dl>
+
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>DEFAULT_TIMEOUT</strong> = 60</dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><a name="WaitAction-BindMeasurementJavaScript"><strong>BindMeasurementJavaScript</strong></a>(self, tab, start_js, stop_js)</dt><dd><tt>Let&nbsp;this&nbsp;action&nbsp;determine&nbsp;when&nbsp;measurements&nbsp;should&nbsp;start&nbsp;and&nbsp;stop.<br>
+&nbsp;<br>
+A&nbsp;measurement&nbsp;can&nbsp;call&nbsp;this&nbsp;method&nbsp;to&nbsp;provide&nbsp;the&nbsp;action<br>
+with&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;and&nbsp;stops&nbsp;measurements.&nbsp;The&nbsp;action<br>
+determines&nbsp;when&nbsp;to&nbsp;execute&nbsp;the&nbsp;provided&nbsp;JavaScript&nbsp;code,&nbsp;for&nbsp;more&nbsp;accurate<br>
+timings.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;tab:&nbsp;The&nbsp;tab&nbsp;to&nbsp;do&nbsp;everything&nbsp;on.<br>
+&nbsp;&nbsp;start_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;starts&nbsp;measurements.<br>
+&nbsp;&nbsp;stop_js:&nbsp;JavaScript&nbsp;code&nbsp;that&nbsp;stops&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="WaitAction-CanBeBound"><strong>CanBeBound</strong></a>(self)</dt><dd><tt>If&nbsp;this&nbsp;class&nbsp;implements&nbsp;BindMeasurementJavaScript,&nbsp;override&nbsp;CanBeBound<br>
+to&nbsp;return&nbsp;True&nbsp;so&nbsp;that&nbsp;a&nbsp;test&nbsp;knows&nbsp;it&nbsp;can&nbsp;bind&nbsp;measurements.</tt></dd></dl>
+
+<dl><dt><a name="WaitAction-CleanUp"><strong>CleanUp</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="WaitAction-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;action-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions<br>
+object.</tt></dd></dl>
+
+<dl><dt><a name="WaitAction-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;action-specific&nbsp;setup&nbsp;before<br>
+Test.WillRunAction&nbsp;is&nbsp;called.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.actions.page_action.html#PageAction">telemetry.page.actions.page_action.PageAction</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.block_page_measurement_results.html b/chromium/tools/telemetry/docs/telemetry.page.block_page_measurement_results.html
new file mode 100644
index 00000000000..5c9c012ab93
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.block_page_measurement_results.html
@@ -0,0 +1,144 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.block_page_measurement_results</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.block_page_measurement_results</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/block_page_measurement_results.py">telemetry/page/block_page_measurement_results.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_measurement_results.html">telemetry.page.page_measurement_results</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>(<a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.block_page_measurement_results.html#BlockPageMeasurementResults">BlockPageMeasurementResults</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BlockPageMeasurementResults">class <strong>BlockPageMeasurementResults</strong></a>(<a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.block_page_measurement_results.html#BlockPageMeasurementResults">BlockPageMeasurementResults</a></dd>
+<dd><a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a></dd>
+<dd><a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a></dd>
+<dd><a href="unittest.result.html#TestResult">unittest.result.TestResult</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="BlockPageMeasurementResults-DidMeasurePage"><strong>DidMeasurePage</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-__init__"><strong>__init__</strong></a>(self, output_file)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>:<br>
+<dl><dt><a name="BlockPageMeasurementResults-Add"><strong>Add</strong></a>(self, trace_name, units, value, chart_name<font color="#909090">=None</font>, data_type<font color="#909090">='default'</font>)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-AddSummary"><strong>AddSummary</strong></a>(self, trace_name, units, value, chart_name<font color="#909090">=None</font>, data_type<font color="#909090">='default'</font>)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-WillMeasurePage"><strong>WillMeasurePage</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-__getitem__"><strong>__getitem__</strong></a>(self, i)</dt><dd><tt>Shorthand&nbsp;for&nbsp;self.<strong>page_results</strong>[i]</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-__len__"><strong>__len__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>:<br>
+<dl><dt><strong>all_measurements_that_have_been_seen</strong></dt>
+</dl>
+<dl><dt><strong>page_results</strong></dt>
+</dl>
+<dl><dt><strong>values_for_current_page</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>:<br>
+<dl><dt><a name="BlockPageMeasurementResults-AddError"><strong>AddError</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-AddErrorMessage"><strong>AddErrorMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-AddFailure"><strong>AddFailure</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-AddFailureMessage"><strong>AddFailureMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-AddSkip"><strong>AddSkip</strong></a>(self, page, reason)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-AddSuccess"><strong>AddSuccess</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-PrintSummary"><strong>PrintSummary</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-StartTest"><strong>StartTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-StopTest"><strong>StopTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-addSkip"><strong>addSkip</strong></a>(self, test, reason)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-addSuccess"><strong>addSuccess</strong></a>(self, test)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><a name="BlockPageMeasurementResults-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-addError"><strong>addError</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-addExpectedFailure"><strong>addExpectedFailure</strong></a>(self, test, err)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;expected&nbsp;failure/error&nbsp;occured.</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-addFailure"><strong>addFailure</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-addUnexpectedSuccess"><strong>addUnexpectedSuccess</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;a&nbsp;test&nbsp;was&nbsp;expected&nbsp;to&nbsp;fail,&nbsp;but&nbsp;succeed.</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-printErrors"><strong>printErrors</strong></a>(self)</dt><dd><tt>Called&nbsp;by&nbsp;TestRunner&nbsp;after&nbsp;test&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-startTest"><strong>startTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;is&nbsp;about&nbsp;to&nbsp;be&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-startTestRun"><strong>startTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;before&nbsp;any&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;startTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;before&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-stop"><strong>stop</strong></a>(self)</dt><dd><tt>Indicates&nbsp;that&nbsp;the&nbsp;tests&nbsp;should&nbsp;be&nbsp;aborted</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-stopTest"><strong>stopTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;has&nbsp;been&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-stopTestRun"><strong>stopTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;after&nbsp;all&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;stopTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;after&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="BlockPageMeasurementResults-wasSuccessful"><strong>wasSuccessful</strong></a>(self)</dt><dd><tt>Tells&nbsp;whether&nbsp;or&nbsp;not&nbsp;this&nbsp;result&nbsp;was&nbsp;a&nbsp;success</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.buildbot_page_measurement_results.html b/chromium/tools/telemetry/docs/telemetry.page.buildbot_page_measurement_results.html
new file mode 100644
index 00000000000..fd879511fa5
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.buildbot_page_measurement_results.html
@@ -0,0 +1,147 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.buildbot_page_measurement_results</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.buildbot_page_measurement_results</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/buildbot_page_measurement_results.py">telemetry/page/buildbot_page_measurement_results.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.page_measurement_results.html">telemetry.page.page_measurement_results</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.perf_tests_helper.html">telemetry.page.perf_tests_helper</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>(<a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.buildbot_page_measurement_results.html#BuildbotPageMeasurementResults">BuildbotPageMeasurementResults</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="BuildbotPageMeasurementResults">class <strong>BuildbotPageMeasurementResults</strong></a>(<a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.buildbot_page_measurement_results.html#BuildbotPageMeasurementResults">BuildbotPageMeasurementResults</a></dd>
+<dd><a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a></dd>
+<dd><a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a></dd>
+<dd><a href="unittest.result.html#TestResult">unittest.result.TestResult</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="BuildbotPageMeasurementResults-PrintSummary"><strong>PrintSummary</strong></a>(self)</dt><dd><tt>Print&nbsp;summary&nbsp;data&nbsp;in&nbsp;a&nbsp;format&nbsp;expected&nbsp;by&nbsp;buildbot&nbsp;for&nbsp;perf&nbsp;dashboards.<br>
+&nbsp;<br>
+If&nbsp;any&nbsp;failed&nbsp;pages&nbsp;exist,&nbsp;only&nbsp;output&nbsp;individual&nbsp;page&nbsp;results&nbsp;for<br>
+non-failing&nbsp;pages,&nbsp;and&nbsp;do&nbsp;not&nbsp;output&nbsp;any&nbsp;average&nbsp;data.</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-__init__"><strong>__init__</strong></a>(self, trace_tag<font color="#909090">=''</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>:<br>
+<dl><dt><a name="BuildbotPageMeasurementResults-Add"><strong>Add</strong></a>(self, trace_name, units, value, chart_name<font color="#909090">=None</font>, data_type<font color="#909090">='default'</font>)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-AddSummary"><strong>AddSummary</strong></a>(self, trace_name, units, value, chart_name<font color="#909090">=None</font>, data_type<font color="#909090">='default'</font>)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-DidMeasurePage"><strong>DidMeasurePage</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-WillMeasurePage"><strong>WillMeasurePage</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-__getitem__"><strong>__getitem__</strong></a>(self, i)</dt><dd><tt>Shorthand&nbsp;for&nbsp;self.<strong>page_results</strong>[i]</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-__len__"><strong>__len__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>:<br>
+<dl><dt><strong>all_measurements_that_have_been_seen</strong></dt>
+</dl>
+<dl><dt><strong>page_results</strong></dt>
+</dl>
+<dl><dt><strong>values_for_current_page</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>:<br>
+<dl><dt><a name="BuildbotPageMeasurementResults-AddError"><strong>AddError</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-AddErrorMessage"><strong>AddErrorMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-AddFailure"><strong>AddFailure</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-AddFailureMessage"><strong>AddFailureMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-AddSkip"><strong>AddSkip</strong></a>(self, page, reason)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-AddSuccess"><strong>AddSuccess</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-StartTest"><strong>StartTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-StopTest"><strong>StopTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-addSkip"><strong>addSkip</strong></a>(self, test, reason)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-addSuccess"><strong>addSuccess</strong></a>(self, test)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><a name="BuildbotPageMeasurementResults-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-addError"><strong>addError</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-addExpectedFailure"><strong>addExpectedFailure</strong></a>(self, test, err)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;expected&nbsp;failure/error&nbsp;occured.</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-addFailure"><strong>addFailure</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-addUnexpectedSuccess"><strong>addUnexpectedSuccess</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;a&nbsp;test&nbsp;was&nbsp;expected&nbsp;to&nbsp;fail,&nbsp;but&nbsp;succeed.</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-printErrors"><strong>printErrors</strong></a>(self)</dt><dd><tt>Called&nbsp;by&nbsp;TestRunner&nbsp;after&nbsp;test&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-startTest"><strong>startTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;is&nbsp;about&nbsp;to&nbsp;be&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-startTestRun"><strong>startTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;before&nbsp;any&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;startTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;before&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-stop"><strong>stop</strong></a>(self)</dt><dd><tt>Indicates&nbsp;that&nbsp;the&nbsp;tests&nbsp;should&nbsp;be&nbsp;aborted</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-stopTest"><strong>stopTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;has&nbsp;been&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-stopTestRun"><strong>stopTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;after&nbsp;all&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;stopTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;after&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="BuildbotPageMeasurementResults-wasSuccessful"><strong>wasSuccessful</strong></a>(self)</dt><dd><tt>Tells&nbsp;whether&nbsp;or&nbsp;not&nbsp;this&nbsp;result&nbsp;was&nbsp;a&nbsp;success</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.cloud_storage.html b/chromium/tools/telemetry/docs/telemetry.page.cloud_storage.html
new file mode 100644
index 00000000000..153583d1323
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.cloud_storage.html
@@ -0,0 +1,40 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.cloud_storage</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.cloud_storage</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/cloud_storage.py">telemetry/page/cloud_storage.py</a></font></td></tr></table>
+ <p><tt>Wrappers&nbsp;for&nbsp;gsutil,&nbsp;for&nbsp;basic&nbsp;interaction&nbsp;with&nbsp;Google&nbsp;Cloud&nbsp;Storage.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="cStringIO.html">cStringIO</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="subprocess.html">subprocess</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="tarfile.html">tarfile</a><br>
+</td><td width="25%" valign=top><a href="urllib2.html">urllib2</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-Delete"><strong>Delete</strong></a>(bucket, remote_path)</dt></dl>
+ <dl><dt><a name="-Get"><strong>Get</strong></a>(bucket, remote_path, local_path)</dt></dl>
+ <dl><dt><a name="-Insert"><strong>Insert</strong></a>(bucket, remote_path, local_path)</dt></dl>
+ <dl><dt><a name="-List"><strong>List</strong></a>(bucket)</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.csv_page_measurement_results.html b/chromium/tools/telemetry/docs/telemetry.page.csv_page_measurement_results.html
new file mode 100644
index 00000000000..65293909c1b
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.csv_page_measurement_results.html
@@ -0,0 +1,144 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.csv_page_measurement_results</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.csv_page_measurement_results</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/csv_page_measurement_results.py">telemetry/page/csv_page_measurement_results.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="csv.html">csv</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_measurement_results.html">telemetry.page.page_measurement_results</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>(<a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.csv_page_measurement_results.html#CsvPageMeasurementResults">CsvPageMeasurementResults</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="CsvPageMeasurementResults">class <strong>CsvPageMeasurementResults</strong></a>(<a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.csv_page_measurement_results.html#CsvPageMeasurementResults">CsvPageMeasurementResults</a></dd>
+<dd><a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a></dd>
+<dd><a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a></dd>
+<dd><a href="unittest.result.html#TestResult">unittest.result.TestResult</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="CsvPageMeasurementResults-DidMeasurePage"><strong>DidMeasurePage</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-PrintSummary"><strong>PrintSummary</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-__init__"><strong>__init__</strong></a>(self, output_stream, output_after_every_page)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>:<br>
+<dl><dt><a name="CsvPageMeasurementResults-Add"><strong>Add</strong></a>(self, trace_name, units, value, chart_name<font color="#909090">=None</font>, data_type<font color="#909090">='default'</font>)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-AddSummary"><strong>AddSummary</strong></a>(self, trace_name, units, value, chart_name<font color="#909090">=None</font>, data_type<font color="#909090">='default'</font>)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-WillMeasurePage"><strong>WillMeasurePage</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-__getitem__"><strong>__getitem__</strong></a>(self, i)</dt><dd><tt>Shorthand&nbsp;for&nbsp;self.<strong>page_results</strong>[i]</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-__len__"><strong>__len__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">telemetry.page.page_measurement_results.PageMeasurementResults</a>:<br>
+<dl><dt><strong>all_measurements_that_have_been_seen</strong></dt>
+</dl>
+<dl><dt><strong>page_results</strong></dt>
+</dl>
+<dl><dt><strong>values_for_current_page</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>:<br>
+<dl><dt><a name="CsvPageMeasurementResults-AddError"><strong>AddError</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-AddErrorMessage"><strong>AddErrorMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-AddFailure"><strong>AddFailure</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-AddFailureMessage"><strong>AddFailureMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-AddSkip"><strong>AddSkip</strong></a>(self, page, reason)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-AddSuccess"><strong>AddSuccess</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-StartTest"><strong>StartTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-StopTest"><strong>StopTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-addSkip"><strong>addSkip</strong></a>(self, test, reason)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-addSuccess"><strong>addSuccess</strong></a>(self, test)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><a name="CsvPageMeasurementResults-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-addError"><strong>addError</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-addExpectedFailure"><strong>addExpectedFailure</strong></a>(self, test, err)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;expected&nbsp;failure/error&nbsp;occured.</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-addFailure"><strong>addFailure</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-addUnexpectedSuccess"><strong>addUnexpectedSuccess</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;a&nbsp;test&nbsp;was&nbsp;expected&nbsp;to&nbsp;fail,&nbsp;but&nbsp;succeed.</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-printErrors"><strong>printErrors</strong></a>(self)</dt><dd><tt>Called&nbsp;by&nbsp;TestRunner&nbsp;after&nbsp;test&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-startTest"><strong>startTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;is&nbsp;about&nbsp;to&nbsp;be&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-startTestRun"><strong>startTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;before&nbsp;any&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;startTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;before&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-stop"><strong>stop</strong></a>(self)</dt><dd><tt>Indicates&nbsp;that&nbsp;the&nbsp;tests&nbsp;should&nbsp;be&nbsp;aborted</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-stopTest"><strong>stopTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;has&nbsp;been&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-stopTestRun"><strong>stopTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;after&nbsp;all&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;stopTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;after&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="CsvPageMeasurementResults-wasSuccessful"><strong>wasSuccessful</strong></a>(self)</dt><dd><tt>Tells&nbsp;whether&nbsp;or&nbsp;not&nbsp;this&nbsp;result&nbsp;was&nbsp;a&nbsp;success</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.gtest_test_results.html b/chromium/tools/telemetry/docs/telemetry.page.gtest_test_results.html
new file mode 100644
index 00000000000..027e10e6e89
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.gtest_test_results.html
@@ -0,0 +1,125 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.gtest_test_results</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.gtest_test_results</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/gtest_test_results.py">telemetry/page/gtest_test_results.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.page_test_results.html">telemetry.page.page_test_results</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="time.html">time</a><br>
+</td><td width="25%" valign=top><a href="unittest.html">unittest</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>(<a href="unittest.result.html#TestResult">unittest.result.TestResult</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.gtest_test_results.html#GTestTestResults">GTestTestResults</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="GTestTestResults">class <strong>GTestTestResults</strong></a>(<a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.gtest_test_results.html#GTestTestResults">GTestTestResults</a></dd>
+<dd><a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a></dd>
+<dd><a href="unittest.result.html#TestResult">unittest.result.TestResult</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="GTestTestResults-PrintSummary"><strong>PrintSummary</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-addError"><strong>addError</strong></a>(self, test, err)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-addFailure"><strong>addFailure</strong></a>(self, test, err)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-addSuccess"><strong>addSuccess</strong></a>(self, test)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-startTest"><strong>startTest</strong></a>(self, test)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>num_errors</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>:<br>
+<dl><dt><a name="GTestTestResults-AddError"><strong>AddError</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-AddErrorMessage"><strong>AddErrorMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-AddFailure"><strong>AddFailure</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-AddFailureMessage"><strong>AddFailureMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-AddSkip"><strong>AddSkip</strong></a>(self, page, reason)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-AddSuccess"><strong>AddSuccess</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-StartTest"><strong>StartTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-StopTest"><strong>StopTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-addSkip"><strong>addSkip</strong></a>(self, test, reason)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><a name="GTestTestResults-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="GTestTestResults-addExpectedFailure"><strong>addExpectedFailure</strong></a>(self, test, err)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;expected&nbsp;failure/error&nbsp;occured.</tt></dd></dl>
+
+<dl><dt><a name="GTestTestResults-addUnexpectedSuccess"><strong>addUnexpectedSuccess</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;a&nbsp;test&nbsp;was&nbsp;expected&nbsp;to&nbsp;fail,&nbsp;but&nbsp;succeed.</tt></dd></dl>
+
+<dl><dt><a name="GTestTestResults-printErrors"><strong>printErrors</strong></a>(self)</dt><dd><tt>Called&nbsp;by&nbsp;TestRunner&nbsp;after&nbsp;test&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="GTestTestResults-startTestRun"><strong>startTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;before&nbsp;any&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;startTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;before&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="GTestTestResults-stop"><strong>stop</strong></a>(self)</dt><dd><tt>Indicates&nbsp;that&nbsp;the&nbsp;tests&nbsp;should&nbsp;be&nbsp;aborted</tt></dd></dl>
+
+<dl><dt><a name="GTestTestResults-stopTest"><strong>stopTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;has&nbsp;been&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="GTestTestResults-stopTestRun"><strong>stopTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;after&nbsp;all&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;stopTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;after&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="GTestTestResults-wasSuccessful"><strong>wasSuccessful</strong></a>(self)</dt><dd><tt>Tells&nbsp;whether&nbsp;or&nbsp;not&nbsp;this&nbsp;result&nbsp;was&nbsp;a&nbsp;success</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.html b/chromium/tools/telemetry/docs/telemetry.page.html
new file mode 100644
index 00000000000..28b1343da48
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.html
@@ -0,0 +1,54 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry.page</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.page</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/__init__.py">telemetry/page/__init__.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.actions.html"><strong>actions</strong>&nbsp;(package)</a><br>
+<a href="telemetry.page.block_page_measurement_results.html">block_page_measurement_results</a><br>
+<a href="telemetry.page.block_page_measurement_results_unittest.html">block_page_measurement_results_unittest</a><br>
+<a href="telemetry.page.buildbot_page_measurement_results.html">buildbot_page_measurement_results</a><br>
+<a href="telemetry.page.buildbot_page_measurement_results_unittest.html">buildbot_page_measurement_results_unittest</a><br>
+<a href="telemetry.page.cloud_storage.html">cloud_storage</a><br>
+<a href="telemetry.page.csv_page_measurement_results.html">csv_page_measurement_results</a><br>
+<a href="telemetry.page.csv_page_measurement_results_unittest.html">csv_page_measurement_results_unittest</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.gtest_test_results.html">gtest_test_results</a><br>
+<a href="telemetry.page.page.html">page</a><br>
+<a href="telemetry.page.page_filter.html">page_filter</a><br>
+<a href="telemetry.page.page_measurement.html">page_measurement</a><br>
+<a href="telemetry.page.page_measurement_results.html">page_measurement_results</a><br>
+<a href="telemetry.page.page_measurement_results_unittest.html">page_measurement_results_unittest</a><br>
+<a href="telemetry.page.page_measurement_runner.html">page_measurement_runner</a><br>
+<a href="telemetry.page.page_measurement_unittest.html">page_measurement_unittest</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_measurement_unittest_base.html">page_measurement_unittest_base</a><br>
+<a href="telemetry.page.page_measurement_value.html">page_measurement_value</a><br>
+<a href="telemetry.page.page_runner.html">page_runner</a><br>
+<a href="telemetry.page.page_runner_unittest.html">page_runner_unittest</a><br>
+<a href="telemetry.page.page_set.html">page_set</a><br>
+<a href="telemetry.page.page_set_archive_info.html">page_set_archive_info</a><br>
+<a href="telemetry.page.page_set_archive_info_unittest.html">page_set_archive_info_unittest</a><br>
+<a href="telemetry.page.page_set_unittest.html">page_set_unittest</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_test.html">page_test</a><br>
+<a href="telemetry.page.page_test_results.html">page_test_results</a><br>
+<a href="telemetry.page.page_test_runner.html">page_test_runner</a><br>
+<a href="telemetry.page.page_test_unittest.html">page_test_unittest</a><br>
+<a href="telemetry.page.page_unittest.html">page_unittest</a><br>
+<a href="telemetry.page.perf_tests_helper.html">perf_tests_helper</a><br>
+<a href="telemetry.page.record_wpr.html">record_wpr</a><br>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page.html b/chromium/tools/telemetry/docs/telemetry.page.page.html
new file mode 100644
index 00000000000..1f5381fc1b7
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page.html
@@ -0,0 +1,79 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page.py">telemetry/page/page.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="re.html">re</a><br>
+</td><td width="25%" valign=top><a href="time.html">time</a><br>
+<a href="urlparse.html">urlparse</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page.html#Page">Page</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Page">class <strong>Page</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Page-WaitToLoad"><strong>WaitToLoad</strong></a>(self, tab, timeout, poll_interval<font color="#909090">=0.1</font>)</dt></dl>
+
+<dl><dt><a name="Page-__getattr__"><strong>__getattr__</strong></a>(self, name)</dt></dl>
+
+<dl><dt><a name="Page-__init__"><strong>__init__</strong></a>(self, url, page_set, attributes<font color="#909090">=None</font>, base_dir<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="Page-__str__"><strong>__str__</strong></a>(self)</dt></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="Page-WaitForPageToLoad"><strong>WaitForPageToLoad</strong></a>(obj, tab, timeout, poll_interval<font color="#909090">=0.1</font>)</dt><dd><tt>Waits&nbsp;for&nbsp;various&nbsp;wait&nbsp;conditions&nbsp;present&nbsp;in&nbsp;obj.</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>archive_path</strong></dt>
+</dl>
+<dl><dt><strong>display_url</strong></dt>
+</dl>
+<dl><dt><strong>serving_dirs_and_file</strong></dt>
+</dl>
+<dl><dt><strong>url_as_file_safe_name</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_filter.html b/chromium/tools/telemetry/docs/telemetry.page.page_filter.html
new file mode 100644
index 00000000000..1c94adc42ab
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_filter.html
@@ -0,0 +1,66 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_filter</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_filter</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_filter.py">telemetry/page/page_filter.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="optparse.html">optparse</a><br>
+</td><td width="25%" valign=top><a href="re.html">re</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_filter.html#PageFilter">PageFilter</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageFilter">class <strong>PageFilter</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Filters&nbsp;pages&nbsp;in&nbsp;the&nbsp;page&nbsp;set&nbsp;based&nbsp;on&nbsp;command&nbsp;line&nbsp;flags.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PageFilter-IsSelected"><strong>IsSelected</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageFilter-__init__"><strong>__init__</strong></a>(self, options)</dt></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="PageFilter-AddCommandLineOptions"><strong>AddCommandLineOptions</strong></a>(parser)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_measurement.html b/chromium/tools/telemetry/docs/telemetry.page.page_measurement.html
new file mode 100644
index 00000000000..8ca291a85bf
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_measurement.html
@@ -0,0 +1,248 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_measurement</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_measurement</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_measurement.py">telemetry/page/page_measurement.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.block_page_measurement_results.html">telemetry.page.block_page_measurement_results</a><br>
+<a href="telemetry.page.buildbot_page_measurement_results.html">telemetry.page.buildbot_page_measurement_results</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.csv_page_measurement_results.html">telemetry.page.csv_page_measurement_results</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_measurement_results.html">telemetry.page.page_measurement_results</a><br>
+<a href="telemetry.page.page_test.html">telemetry.page.page_test</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test.html#Failure">telemetry.page.page_test.Failure</a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement.html#MeasurementFailure">MeasurementFailure</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement.html#PageMeasurement">PageMeasurement</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MeasurementFailure">class <strong>MeasurementFailure</strong></a>(<a href="telemetry.page.page_test.html#Failure">telemetry.page.page_test.Failure</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Exception&nbsp;that&nbsp;can&nbsp;be&nbsp;thrown&nbsp;from&nbsp;MeasurePage&nbsp;to&nbsp;indicate&nbsp;an&nbsp;undesired&nbsp;but<br>
+designed-for&nbsp;problem.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.page_measurement.html#MeasurementFailure">MeasurementFailure</a></dd>
+<dd><a href="telemetry.page.page_test.html#Failure">telemetry.page.page_test.Failure</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors inherited from <a href="telemetry.page.page_test.html#Failure">telemetry.page.page_test.Failure</a>:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="MeasurementFailure-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#MeasurementFailure-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#MeasurementFailure-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;object&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="MeasurementFailure-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#MeasurementFailure-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="MeasurementFailure-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#MeasurementFailure-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="MeasurementFailure-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#MeasurementFailure-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="MeasurementFailure-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#MeasurementFailure-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="MeasurementFailure-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="MeasurementFailure-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#MeasurementFailure-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="MeasurementFailure-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#MeasurementFailure-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="MeasurementFailure-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="MeasurementFailure-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#MeasurementFailure-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="MeasurementFailure-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageMeasurement">class <strong>PageMeasurement</strong></a>(<a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Glue&nbsp;code&nbsp;for&nbsp;running&nbsp;a&nbsp;measurement&nbsp;across&nbsp;a&nbsp;set&nbsp;of&nbsp;pages.<br>
+&nbsp;<br>
+To&nbsp;use&nbsp;this,&nbsp;subclass&nbsp;from&nbsp;the&nbsp;measurement&nbsp;and&nbsp;override&nbsp;MeasurePage.&nbsp;For<br>
+example:<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;class&nbsp;BodyChildElementMeasurement(<a href="#PageMeasurement">PageMeasurement</a>):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;<a href="#PageMeasurement-MeasurePage">MeasurePage</a>(self,&nbsp;page,&nbsp;tab,&nbsp;results):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;body_child_count&nbsp;=&nbsp;tab.EvaluateJavaScript(<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'document.body.children.length')<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;results.Add('body_children',&nbsp;'count',&nbsp;body_child_count)<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;if&nbsp;__name__&nbsp;==&nbsp;'__main__':<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;page_measurement.Main(BodyChildElementMeasurement())<br>
+&nbsp;<br>
+To&nbsp;add&nbsp;test-specific&nbsp;options:<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;class&nbsp;BodyChildElementMeasurement(<a href="#PageMeasurement">PageMeasurement</a>):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;<a href="#PageMeasurement-AddCommandLineOptions">AddCommandLineOptions</a>(parser):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parser.add_option('--element',&nbsp;action='store',&nbsp;default='body')<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;<a href="#PageMeasurement-MeasurePage">MeasurePage</a>(self,&nbsp;page,&nbsp;tab,&nbsp;results):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;body_child_count&nbsp;=&nbsp;tab.EvaluateJavaScript(<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'document.querySelector('%s').children.length')<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;results.Add('children',&nbsp;'count',&nbsp;child_count)<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.page_measurement.html#PageMeasurement">PageMeasurement</a></dd>
+<dd><a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PageMeasurement-AddOutputOptions"><strong>AddOutputOptions</strong></a>(self, parser)</dt></dl>
+
+<dl><dt><a name="PageMeasurement-MeasurePage"><strong>MeasurePage</strong></a>(self, page, tab, results)</dt><dd><tt>Override&nbsp;to&nbsp;actually&nbsp;measure&nbsp;the&nbsp;page's&nbsp;performance.<br>
+&nbsp;<br>
+page&nbsp;is&nbsp;a&nbsp;page_set.Page<br>
+tab&nbsp;is&nbsp;an&nbsp;instance&nbsp;of&nbsp;telemetry.core.Tab<br>
+&nbsp;<br>
+Should&nbsp;call&nbsp;results.Add(name,&nbsp;units,&nbsp;value)&nbsp;for&nbsp;each&nbsp;result,&nbsp;or&nbsp;raise&nbsp;an<br>
+exception&nbsp;on&nbsp;failure.&nbsp;The&nbsp;name&nbsp;and&nbsp;units&nbsp;of&nbsp;each&nbsp;Add()&nbsp;call&nbsp;must&nbsp;be<br>
+the&nbsp;same&nbsp;across&nbsp;all&nbsp;iterations.&nbsp;The&nbsp;name&nbsp;'url'&nbsp;must&nbsp;not&nbsp;be&nbsp;used.<br>
+&nbsp;<br>
+Prefer&nbsp;field&nbsp;names&nbsp;that&nbsp;are&nbsp;in&nbsp;accordance&nbsp;with&nbsp;python&nbsp;variable&nbsp;style.&nbsp;E.g.<br>
+field_name.<br>
+&nbsp;<br>
+Put&nbsp;together:<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;def&nbsp;<a href="#PageMeasurement-MeasurePage">MeasurePage</a>(self,&nbsp;page,&nbsp;tab,&nbsp;results):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&nbsp;=&nbsp;tab.EvaluateJavaScript('2+2')<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;res&nbsp;!=&nbsp;4:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise&nbsp;Exception('Oh,&nbsp;wow.')<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;results.Add('two_plus_two',&nbsp;'count',&nbsp;res)</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-PrepareResults"><strong>PrepareResults</strong></a>(self, options)</dt></dl>
+
+<dl><dt><a name="PageMeasurement-__init__"><strong>__init__</strong></a>(self, action_name_to_run<font color="#909090">=''</font>, needs_browser_restart_after_each_run<font color="#909090">=False</font>, discard_first_result<font color="#909090">=False</font>, clear_cache_before_each_run<font color="#909090">=False</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>output_format_choices</strong></dt>
+</dl>
+<dl><dt><strong>results_are_the_same_on_every_page</strong></dt>
+<dd><tt>By&nbsp;default,&nbsp;measurements&nbsp;are&nbsp;assumed&nbsp;to&nbsp;output&nbsp;the&nbsp;same&nbsp;values&nbsp;for&nbsp;every<br>
+page.&nbsp;This&nbsp;allows&nbsp;incremental&nbsp;output,&nbsp;for&nbsp;example&nbsp;in&nbsp;CSV.&nbsp;If,&nbsp;however,&nbsp;the<br>
+measurement&nbsp;discovers&nbsp;what&nbsp;values&nbsp;it&nbsp;can&nbsp;report&nbsp;as&nbsp;it&nbsp;goes,&nbsp;and&nbsp;those&nbsp;values<br>
+may&nbsp;vary&nbsp;from&nbsp;page&nbsp;to&nbsp;page,&nbsp;you&nbsp;need&nbsp;to&nbsp;override&nbsp;this&nbsp;function&nbsp;and&nbsp;return<br>
+False.&nbsp;Output&nbsp;will&nbsp;not&nbsp;appear&nbsp;in&nbsp;this&nbsp;mode&nbsp;until&nbsp;the&nbsp;entire&nbsp;pageset&nbsp;has<br>
+run.</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>:<br>
+<dl><dt><a name="PageMeasurement-AddCommandLineOptions"><strong>AddCommandLineOptions</strong></a>(self, parser)</dt><dd><tt>Override&nbsp;to&nbsp;expose&nbsp;command-line&nbsp;options&nbsp;for&nbsp;this&nbsp;test.<br>
+&nbsp;<br>
+The&nbsp;provided&nbsp;parser&nbsp;is&nbsp;an&nbsp;optparse.OptionParser&nbsp;instance&nbsp;and&nbsp;accepts&nbsp;all<br>
+normal&nbsp;results.&nbsp;The&nbsp;parsed&nbsp;options&nbsp;are&nbsp;available&nbsp;in&nbsp;Run&nbsp;as<br>
+self.<strong>options</strong>.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-CanRunForPage"><strong>CanRunForPage</strong></a>(self, page)</dt><dd><tt>Override&nbsp;to&nbsp;customize&nbsp;if&nbsp;the&nbsp;test&nbsp;can&nbsp;be&nbsp;ran&nbsp;for&nbsp;the&nbsp;given&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-CreatePageSet"><strong>CreatePageSet</strong></a>(self, args, options)</dt><dd><tt>Override&nbsp;to&nbsp;make&nbsp;this&nbsp;test&nbsp;generate&nbsp;its&nbsp;own&nbsp;page&nbsp;set&nbsp;instead&nbsp;of<br>
+allowing&nbsp;arbitrary&nbsp;page&nbsp;sets&nbsp;entered&nbsp;from&nbsp;the&nbsp;command-line.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;test-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions&nbsp;object</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-CustomizeBrowserOptionsForPage"><strong>CustomizeBrowserOptionsForPage</strong></a>(self, page, options)</dt><dd><tt>Add&nbsp;options&nbsp;specific&nbsp;to&nbsp;the&nbsp;test&nbsp;and&nbsp;the&nbsp;given&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-DidNavigateToPage"><strong>DidNavigateToPage</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;right&nbsp;after&nbsp;the&nbsp;page&nbsp;is&nbsp;navigated,&nbsp;but&nbsp;before<br>
+any&nbsp;waiting&nbsp;for&nbsp;completion&nbsp;has&nbsp;occurred.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-DidRunAction"><strong>DidRunAction</strong></a>(self, page, tab, action)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;running&nbsp;the&nbsp;action&nbsp;on&nbsp;the&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-DidRunPageSet"><strong>DidRunPageSet</strong></a>(self, tab, results)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;page&nbsp;set&nbsp;is&nbsp;completed,&nbsp;but&nbsp;before&nbsp;browser<br>
+is&nbsp;torn&nbsp;down.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-DidStartHTTPServer"><strong>DidStartHTTPServer</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;the&nbsp;HTTP&nbsp;server&nbsp;is&nbsp;started.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-NeedsBrowserRestartAfterEachRun"><strong>NeedsBrowserRestartAfterEachRun</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;specify&nbsp;browser&nbsp;restart&nbsp;after&nbsp;each&nbsp;run.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-Run"><strong>Run</strong></a>(self, options, page, tab, results)</dt></dl>
+
+<dl><dt><a name="PageMeasurement-SetUpBrowser"><strong>SetUpBrowser</strong></a>(self, browser)</dt><dd><tt>Override&nbsp;to&nbsp;customize&nbsp;the&nbsp;browser&nbsp;right&nbsp;after&nbsp;it&nbsp;has&nbsp;launched.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-WillNavigateToPage"><strong>WillNavigateToPage</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;the&nbsp;page&nbsp;is&nbsp;navigated.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab, action)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;running&nbsp;the&nbsp;action&nbsp;on&nbsp;the&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurement-WillRunPageSet"><strong>WillRunPageSet</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;the&nbsp;page&nbsp;set&nbsp;is&nbsp;navigated.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>action_name_to_run</strong></dt>
+</dl>
+<dl><dt><strong>clear_cache_before_each_run</strong></dt>
+<dd><tt>When&nbsp;set&nbsp;to&nbsp;True,&nbsp;the&nbsp;browser's&nbsp;disk&nbsp;and&nbsp;memory&nbsp;cache&nbsp;will&nbsp;be&nbsp;cleared<br>
+before&nbsp;each&nbsp;run.</tt></dd>
+</dl>
+<dl><dt><strong>discard_first_result</strong></dt>
+<dd><tt>When&nbsp;set&nbsp;to&nbsp;True,&nbsp;the&nbsp;first&nbsp;run&nbsp;of&nbsp;the&nbsp;test&nbsp;is&nbsp;discarded.&nbsp;&nbsp;This&nbsp;is<br>
+useful&nbsp;for&nbsp;cases&nbsp;where&nbsp;it's&nbsp;desirable&nbsp;to&nbsp;have&nbsp;some&nbsp;test&nbsp;resource&nbsp;cached&nbsp;so<br>
+the&nbsp;first&nbsp;run&nbsp;of&nbsp;the&nbsp;test&nbsp;can&nbsp;warm&nbsp;things&nbsp;up.</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_measurement_results.html b/chromium/tools/telemetry/docs/telemetry.page.page_measurement_results.html
new file mode 100644
index 00000000000..4cd75f2f00d
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_measurement_results.html
@@ -0,0 +1,177 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_measurement_results</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_measurement_results</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_measurement_results.py">telemetry/page/page_measurement_results.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.page_measurement_value.html">telemetry.page.page_measurement_value</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_test_results.html">telemetry.page.page_test_results</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement_results.html#ValuesForSinglePage">ValuesForSinglePage</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>(<a href="unittest.result.html#TestResult">unittest.result.TestResult</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">PageMeasurementResults</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageMeasurementResults">class <strong>PageMeasurementResults</strong></a>(<a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.page_measurement_results.html#PageMeasurementResults">PageMeasurementResults</a></dd>
+<dd><a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a></dd>
+<dd><a href="unittest.result.html#TestResult">unittest.result.TestResult</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PageMeasurementResults-Add"><strong>Add</strong></a>(self, trace_name, units, value, chart_name<font color="#909090">=None</font>, data_type<font color="#909090">='default'</font>)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-AddSummary"><strong>AddSummary</strong></a>(self, trace_name, units, value, chart_name<font color="#909090">=None</font>, data_type<font color="#909090">='default'</font>)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-DidMeasurePage"><strong>DidMeasurePage</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-WillMeasurePage"><strong>WillMeasurePage</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-__getitem__"><strong>__getitem__</strong></a>(self, i)</dt><dd><tt>Shorthand&nbsp;for&nbsp;self.<strong>page_results</strong>[i]</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-__init__"><strong>__init__</strong></a>(self, trace_tag<font color="#909090">=''</font>)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-__len__"><strong>__len__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>all_measurements_that_have_been_seen</strong></dt>
+</dl>
+<dl><dt><strong>page_results</strong></dt>
+</dl>
+<dl><dt><strong>values_for_current_page</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.page.page_test_results.html#PageTestResults">telemetry.page.page_test_results.PageTestResults</a>:<br>
+<dl><dt><a name="PageMeasurementResults-AddError"><strong>AddError</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-AddErrorMessage"><strong>AddErrorMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-AddFailure"><strong>AddFailure</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-AddFailureMessage"><strong>AddFailureMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-AddSkip"><strong>AddSkip</strong></a>(self, page, reason)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-AddSuccess"><strong>AddSuccess</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-PrintSummary"><strong>PrintSummary</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-StartTest"><strong>StartTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-StopTest"><strong>StopTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-addSkip"><strong>addSkip</strong></a>(self, test, reason)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-addSuccess"><strong>addSuccess</strong></a>(self, test)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><a name="PageMeasurementResults-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementResults-addError"><strong>addError</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-addExpectedFailure"><strong>addExpectedFailure</strong></a>(self, test, err)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;expected&nbsp;failure/error&nbsp;occured.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-addFailure"><strong>addFailure</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-addUnexpectedSuccess"><strong>addUnexpectedSuccess</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;a&nbsp;test&nbsp;was&nbsp;expected&nbsp;to&nbsp;fail,&nbsp;but&nbsp;succeed.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-printErrors"><strong>printErrors</strong></a>(self)</dt><dd><tt>Called&nbsp;by&nbsp;TestRunner&nbsp;after&nbsp;test&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-startTest"><strong>startTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;is&nbsp;about&nbsp;to&nbsp;be&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-startTestRun"><strong>startTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;before&nbsp;any&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;startTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;before&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-stop"><strong>stop</strong></a>(self)</dt><dd><tt>Indicates&nbsp;that&nbsp;the&nbsp;tests&nbsp;should&nbsp;be&nbsp;aborted</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-stopTest"><strong>stopTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;has&nbsp;been&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-stopTestRun"><strong>stopTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;after&nbsp;all&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;stopTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;after&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementResults-wasSuccessful"><strong>wasSuccessful</strong></a>(self)</dt><dd><tt>Tells&nbsp;whether&nbsp;or&nbsp;not&nbsp;this&nbsp;result&nbsp;was&nbsp;a&nbsp;success</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="ValuesForSinglePage">class <strong>ValuesForSinglePage</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="ValuesForSinglePage-AddValue"><strong>AddValue</strong></a>(self, value)</dt></dl>
+
+<dl><dt><a name="ValuesForSinglePage-FindValueByMeasurementName"><strong>FindValueByMeasurementName</strong></a>(self, measurement_name)</dt></dl>
+
+<dl><dt><a name="ValuesForSinglePage-FindValueByTraceName"><strong>FindValueByTraceName</strong></a>(self, trace_name)</dt></dl>
+
+<dl><dt><a name="ValuesForSinglePage-__contains__"><strong>__contains__</strong></a>(self, trace_name)</dt></dl>
+
+<dl><dt><a name="ValuesForSinglePage-__getitem__"><strong>__getitem__</strong></a>(self, trace_name)</dt></dl>
+
+<dl><dt><a name="ValuesForSinglePage-__init__"><strong>__init__</strong></a>(self, page)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>measurement_names</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_measurement_runner.html b/chromium/tools/telemetry/docs/telemetry.page.page_measurement_runner.html
new file mode 100644
index 00000000000..2eed09b1eb6
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_measurement_runner.html
@@ -0,0 +1,106 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_measurement_runner</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_measurement_runner</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_measurement_runner.py">telemetry/page/page_measurement_runner.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.page_measurement.html">telemetry.page.page_measurement</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_test_runner.html">telemetry.page.page_test_runner</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test_runner.html#PageTestRunner">telemetry.page.page_test_runner.PageTestRunner</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement_runner.html#PageMeasurementRunner">PageMeasurementRunner</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageMeasurementRunner">class <strong>PageMeasurementRunner</strong></a>(<a href="telemetry.page.page_test_runner.html#PageTestRunner">telemetry.page.page_test_runner.PageTestRunner</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.page_measurement_runner.html#PageMeasurementRunner">PageMeasurementRunner</a></dd>
+<dd><a href="telemetry.page.page_test_runner.html#PageTestRunner">telemetry.page.page_test_runner.PageTestRunner</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>test_class</strong></dt>
+</dl>
+<dl><dt><strong>test_class_name</strong></dt>
+</dl>
+<hr>
+Methods inherited from <a href="telemetry.page.page_test_runner.html#PageTestRunner">telemetry.page.page_test_runner.PageTestRunner</a>:<br>
+<dl><dt><a name="PageMeasurementRunner-FindTestConstructors"><strong>FindTestConstructors</strong></a>(self, base_dir)</dt></dl>
+
+<dl><dt><a name="PageMeasurementRunner-FindTestName"><strong>FindTestName</strong></a>(self, test_constructors, args)</dt><dd><tt>Find&nbsp;the&nbsp;test&nbsp;name&nbsp;in&nbsp;an&nbsp;arbitrary&nbsp;argument&nbsp;list.<br>
+&nbsp;<br>
+We&nbsp;can't&nbsp;use&nbsp;the&nbsp;optparse&nbsp;parser,&nbsp;because&nbsp;the&nbsp;test&nbsp;may&nbsp;add&nbsp;its&nbsp;own<br>
+command-line&nbsp;options.&nbsp;If&nbsp;the&nbsp;user&nbsp;passed&nbsp;in&nbsp;any&nbsp;of&nbsp;those,&nbsp;the<br>
+optparse&nbsp;parsing&nbsp;will&nbsp;fail.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;test_name&nbsp;or&nbsp;None</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementRunner-GetModernizedTestName"><strong>GetModernizedTestName</strong></a>(self, arg)</dt><dd><tt>Sometimes&nbsp;tests&nbsp;change&nbsp;names&nbsp;but&nbsp;buildbots&nbsp;keep&nbsp;calling&nbsp;the&nbsp;old&nbsp;name.<br>
+&nbsp;<br>
+If&nbsp;arg&nbsp;matches&nbsp;an&nbsp;old&nbsp;test&nbsp;name,&nbsp;return&nbsp;the&nbsp;new&nbsp;test&nbsp;name&nbsp;instead.<br>
+Otherwise,&nbsp;return&nbsp;the&nbsp;arg.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementRunner-GetPageSet"><strong>GetPageSet</strong></a>(self, test, page_set_filenames)</dt></dl>
+
+<dl><dt><a name="PageMeasurementRunner-ParseCommandLine"><strong>ParseCommandLine</strong></a>(self, args, base_dir, page_set_filenames)</dt></dl>
+
+<dl><dt><a name="PageMeasurementRunner-PrintParseError"><strong>PrintParseError</strong></a>(self, message)</dt></dl>
+
+<dl><dt><a name="PageMeasurementRunner-Run"><strong>Run</strong></a>(self, base_dir, page_set_filenames)</dt></dl>
+
+<dl><dt><a name="PageMeasurementRunner-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.page_test_runner.html#PageTestRunner">telemetry.page.page_test_runner.PageTestRunner</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-Main"><strong>Main</strong></a>(base_dir, page_set_filenames)</dt><dd><tt>Turns&nbsp;a&nbsp;PageMeasurement&nbsp;into&nbsp;a&nbsp;command-line&nbsp;program.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;base_dir:&nbsp;Path&nbsp;to&nbsp;directory&nbsp;containing&nbsp;tests&nbsp;and&nbsp;ProfileCreators.</tt></dd></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_measurement_unittest_base.html b/chromium/tools/telemetry/docs/telemetry.page.page_measurement_unittest_base.html
new file mode 100644
index 00000000000..6f8dbbd2785
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_measurement_unittest_base.html
@@ -0,0 +1,346 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_measurement_unittest_base</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_measurement_unittest_base</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_measurement_unittest_base.py">telemetry/page/page_measurement_unittest_base.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.unittest.options_for_unittests.html">telemetry.unittest.options_for_unittests</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page.html">telemetry.page.page</a><br>
+<a href="telemetry.page.page_runner.html">telemetry.page.page_runner</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_set.html">telemetry.page.page_set</a><br>
+<a href="unittest.html">unittest</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="unittest.case.html#TestCase">unittest.case.TestCase</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement_unittest_base.html#PageMeasurementUnitTestBase">PageMeasurementUnitTestBase</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageMeasurementUnitTestBase">class <strong>PageMeasurementUnitTestBase</strong></a>(<a href="unittest.case.html#TestCase">unittest.case.TestCase</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>unittest.<a href="unittest.case.html#TestCase">TestCase</a>-derived&nbsp;class&nbsp;to&nbsp;help&nbsp;in&nbsp;the&nbsp;construction&nbsp;of&nbsp;unit&nbsp;tests<br>
+for&nbsp;a&nbsp;measurement.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.page_measurement_unittest_base.html#PageMeasurementUnitTestBase">PageMeasurementUnitTestBase</a></dd>
+<dd><a href="unittest.case.html#TestCase">unittest.case.TestCase</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PageMeasurementUnitTestBase-CreatePageSet"><strong>CreatePageSet</strong></a>(self, test_filename)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-CreatePageSetFromFileInUnittestDataDir"><strong>CreatePageSetFromFileInUnittestDataDir</strong></a>(self, test_filename)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-RunMeasurement"><strong>RunMeasurement</strong></a>(self, measurement, ps, options<font color="#909090">=None</font>)</dt><dd><tt>Runs&nbsp;a&nbsp;measurement&nbsp;against&nbsp;a&nbsp;pageset,&nbsp;returning&nbsp;the&nbsp;rows&nbsp;its&nbsp;outputs.</tt></dd></dl>
+
+<hr>
+Methods inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><a name="PageMeasurementUnitTestBase-__call__"><strong>__call__</strong></a>(self, *args, **kwds)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-__eq__"><strong>__eq__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-__hash__"><strong>__hash__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-__init__"><strong>__init__</strong></a>(self, methodName<font color="#909090">='runTest'</font>)</dt><dd><tt>Create&nbsp;an&nbsp;instance&nbsp;of&nbsp;the&nbsp;class&nbsp;that&nbsp;will&nbsp;use&nbsp;the&nbsp;named&nbsp;test<br>
+method&nbsp;when&nbsp;executed.&nbsp;Raises&nbsp;a&nbsp;ValueError&nbsp;if&nbsp;the&nbsp;instance&nbsp;does<br>
+not&nbsp;have&nbsp;a&nbsp;method&nbsp;with&nbsp;the&nbsp;specified&nbsp;name.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-__ne__"><strong>__ne__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-__str__"><strong>__str__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-addCleanup"><strong>addCleanup</strong></a>(self, function, *args, **kwargs)</dt><dd><tt>Add&nbsp;a&nbsp;function,&nbsp;with&nbsp;arguments,&nbsp;to&nbsp;be&nbsp;called&nbsp;when&nbsp;the&nbsp;test&nbsp;is<br>
+completed.&nbsp;Functions&nbsp;added&nbsp;are&nbsp;called&nbsp;on&nbsp;a&nbsp;LIFO&nbsp;basis&nbsp;and&nbsp;are<br>
+called&nbsp;after&nbsp;tearDown&nbsp;on&nbsp;test&nbsp;failure&nbsp;or&nbsp;success.<br>
+&nbsp;<br>
+Cleanup&nbsp;items&nbsp;are&nbsp;called&nbsp;even&nbsp;if&nbsp;setUp&nbsp;fails&nbsp;(unlike&nbsp;tearDown).</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-addTypeEqualityFunc"><strong>addTypeEqualityFunc</strong></a>(self, typeobj, function)</dt><dd><tt>Add&nbsp;a&nbsp;type&nbsp;specific&nbsp;assertEqual&nbsp;style&nbsp;function&nbsp;to&nbsp;compare&nbsp;a&nbsp;type.<br>
+&nbsp;<br>
+This&nbsp;method&nbsp;is&nbsp;for&nbsp;use&nbsp;by&nbsp;<a href="unittest.case.html#TestCase">TestCase</a>&nbsp;subclasses&nbsp;that&nbsp;need&nbsp;to&nbsp;register<br>
+their&nbsp;own&nbsp;type&nbsp;equality&nbsp;functions&nbsp;to&nbsp;provide&nbsp;nicer&nbsp;error&nbsp;messages.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;typeobj:&nbsp;The&nbsp;data&nbsp;type&nbsp;to&nbsp;call&nbsp;this&nbsp;function&nbsp;on&nbsp;when&nbsp;both&nbsp;values<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;are&nbsp;of&nbsp;the&nbsp;same&nbsp;type&nbsp;in&nbsp;<a href="#PageMeasurementUnitTestBase-assertEqual">assertEqual</a>().<br>
+&nbsp;&nbsp;&nbsp;&nbsp;function:&nbsp;The&nbsp;callable&nbsp;taking&nbsp;two&nbsp;arguments&nbsp;and&nbsp;an&nbsp;optional<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg=&nbsp;argument&nbsp;that&nbsp;raises&nbsp;self.<strong>failureException</strong>&nbsp;with&nbsp;a<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;useful&nbsp;error&nbsp;message&nbsp;when&nbsp;the&nbsp;two&nbsp;arguments&nbsp;are&nbsp;not&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertAlmostEqual"><strong>assertAlmostEqual</strong></a>(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;more&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;two&nbsp;objects&nbsp;compare&nbsp;equal&nbsp;then&nbsp;they&nbsp;will&nbsp;automatically<br>
+compare&nbsp;almost&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertAlmostEquals"><strong>assertAlmostEquals</strong></a> = assertAlmostEqual(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;more&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;two&nbsp;objects&nbsp;compare&nbsp;equal&nbsp;then&nbsp;they&nbsp;will&nbsp;automatically<br>
+compare&nbsp;almost&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertDictContainsSubset"><strong>assertDictContainsSubset</strong></a>(self, expected, actual, msg<font color="#909090">=None</font>)</dt><dd><tt>Checks&nbsp;whether&nbsp;actual&nbsp;is&nbsp;a&nbsp;superset&nbsp;of&nbsp;expected.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertDictEqual"><strong>assertDictEqual</strong></a>(self, d1, d2, msg<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertEqual"><strong>assertEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertEquals"><strong>assertEquals</strong></a> = assertEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertFalse"><strong>assertFalse</strong></a>(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;false.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertGreater"><strong>assertGreater</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;&gt;&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertGreaterEqual"><strong>assertGreaterEqual</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;&gt;=&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertIn"><strong>assertIn</strong></a>(self, member, container, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;in&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertIs"><strong>assertIs</strong></a>(self, expr1, expr2, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;is&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertIsInstance"><strong>assertIsInstance</strong></a>(self, obj, cls, msg<font color="#909090">=None</font>)</dt><dd><tt>Same&nbsp;as&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(isinstance(obj,&nbsp;cls)),&nbsp;with&nbsp;a&nbsp;nicer<br>
+default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertIsNone"><strong>assertIsNone</strong></a>(self, obj, msg<font color="#909090">=None</font>)</dt><dd><tt>Same&nbsp;as&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(obj&nbsp;is&nbsp;None),&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertIsNot"><strong>assertIsNot</strong></a>(self, expr1, expr2, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;is&nbsp;not&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertIsNotNone"><strong>assertIsNotNone</strong></a>(self, obj, msg<font color="#909090">=None</font>)</dt><dd><tt>Included&nbsp;for&nbsp;symmetry&nbsp;with&nbsp;assertIsNone.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertItemsEqual"><strong>assertItemsEqual</strong></a>(self, expected_seq, actual_seq, msg<font color="#909090">=None</font>)</dt><dd><tt>An&nbsp;unordered&nbsp;sequence&nbsp;specific&nbsp;comparison.&nbsp;It&nbsp;asserts&nbsp;that<br>
+actual_seq&nbsp;and&nbsp;expected_seq&nbsp;have&nbsp;the&nbsp;same&nbsp;element&nbsp;counts.<br>
+Equivalent&nbsp;to::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#PageMeasurementUnitTestBase-assertEqual">assertEqual</a>(Counter(iter(actual_seq)),<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Counter(iter(expected_seq)))<br>
+&nbsp;<br>
+Asserts&nbsp;that&nbsp;each&nbsp;element&nbsp;has&nbsp;the&nbsp;same&nbsp;count&nbsp;in&nbsp;both&nbsp;sequences.<br>
+Example:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;[0,&nbsp;1,&nbsp;1]&nbsp;and&nbsp;[1,&nbsp;0,&nbsp;1]&nbsp;compare&nbsp;equal.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;[0,&nbsp;0,&nbsp;1]&nbsp;and&nbsp;[0,&nbsp;1]&nbsp;compare&nbsp;unequal.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertLess"><strong>assertLess</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;&lt;&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertLessEqual"><strong>assertLessEqual</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;&lt;=&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertListEqual"><strong>assertListEqual</strong></a>(self, list1, list2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;list-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;list1:&nbsp;The&nbsp;first&nbsp;list&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;list2:&nbsp;The&nbsp;second&nbsp;list&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertMultiLineEqual"><strong>assertMultiLineEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Assert&nbsp;that&nbsp;two&nbsp;multi-line&nbsp;strings&nbsp;are&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertNotAlmostEqual"><strong>assertNotAlmostEqual</strong></a>(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;less&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+Objects&nbsp;that&nbsp;are&nbsp;equal&nbsp;automatically&nbsp;fail.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertNotAlmostEquals"><strong>assertNotAlmostEquals</strong></a> = assertNotAlmostEqual(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;less&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+Objects&nbsp;that&nbsp;are&nbsp;equal&nbsp;automatically&nbsp;fail.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertNotEqual"><strong>assertNotEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertNotEquals"><strong>assertNotEquals</strong></a> = assertNotEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertNotIn"><strong>assertNotIn</strong></a>(self, member, container, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#PageMeasurementUnitTestBase-assertTrue">assertTrue</a>(a&nbsp;not&nbsp;in&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertNotIsInstance"><strong>assertNotIsInstance</strong></a>(self, obj, cls, msg<font color="#909090">=None</font>)</dt><dd><tt>Included&nbsp;for&nbsp;symmetry&nbsp;with&nbsp;assertIsInstance.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertNotRegexpMatches"><strong>assertNotRegexpMatches</strong></a>(self, text, unexpected_regexp, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;the&nbsp;test&nbsp;if&nbsp;the&nbsp;text&nbsp;matches&nbsp;the&nbsp;regular&nbsp;expression.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertRaises"><strong>assertRaises</strong></a>(self, excClass, callableObj<font color="#909090">=None</font>, *args, **kwargs)</dt><dd><tt>Fail&nbsp;unless&nbsp;an&nbsp;exception&nbsp;of&nbsp;class&nbsp;excClass&nbsp;is&nbsp;thrown<br>
+by&nbsp;callableObj&nbsp;when&nbsp;invoked&nbsp;with&nbsp;arguments&nbsp;args&nbsp;and&nbsp;keyword<br>
+arguments&nbsp;kwargs.&nbsp;If&nbsp;a&nbsp;different&nbsp;type&nbsp;of&nbsp;exception&nbsp;is<br>
+thrown,&nbsp;it&nbsp;will&nbsp;not&nbsp;be&nbsp;caught,&nbsp;and&nbsp;the&nbsp;test&nbsp;case&nbsp;will&nbsp;be<br>
+deemed&nbsp;to&nbsp;have&nbsp;suffered&nbsp;an&nbsp;error,&nbsp;exactly&nbsp;as&nbsp;for&nbsp;an<br>
+unexpected&nbsp;exception.<br>
+&nbsp;<br>
+If&nbsp;called&nbsp;with&nbsp;callableObj&nbsp;omitted&nbsp;or&nbsp;None,&nbsp;will&nbsp;return&nbsp;a<br>
+context&nbsp;object&nbsp;used&nbsp;like&nbsp;this::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;<a href="#PageMeasurementUnitTestBase-assertRaises">assertRaises</a>(SomeException):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_something()<br>
+&nbsp;<br>
+The&nbsp;context&nbsp;manager&nbsp;keeps&nbsp;a&nbsp;reference&nbsp;to&nbsp;the&nbsp;exception&nbsp;as<br>
+the&nbsp;'exception'&nbsp;attribute.&nbsp;This&nbsp;allows&nbsp;you&nbsp;to&nbsp;inspect&nbsp;the<br>
+exception&nbsp;after&nbsp;the&nbsp;assertion::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;<a href="#PageMeasurementUnitTestBase-assertRaises">assertRaises</a>(SomeException)&nbsp;as&nbsp;cm:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_something()<br>
+&nbsp;&nbsp;&nbsp;&nbsp;the_exception&nbsp;=&nbsp;cm.exception<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#PageMeasurementUnitTestBase-assertEqual">assertEqual</a>(the_exception.error_code,&nbsp;3)</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertRaisesRegexp"><strong>assertRaisesRegexp</strong></a>(self, expected_exception, expected_regexp, callable_obj<font color="#909090">=None</font>, *args, **kwargs)</dt><dd><tt>Asserts&nbsp;that&nbsp;the&nbsp;message&nbsp;in&nbsp;a&nbsp;raised&nbsp;exception&nbsp;matches&nbsp;a&nbsp;regexp.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;expected_exception:&nbsp;Exception&nbsp;class&nbsp;expected&nbsp;to&nbsp;be&nbsp;raised.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;expected_regexp:&nbsp;Regexp&nbsp;(re&nbsp;pattern&nbsp;object&nbsp;or&nbsp;string)&nbsp;expected<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;be&nbsp;found&nbsp;in&nbsp;error&nbsp;message.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;callable_obj:&nbsp;Function&nbsp;to&nbsp;be&nbsp;called.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;args:&nbsp;Extra&nbsp;args.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;kwargs:&nbsp;Extra&nbsp;kwargs.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertRegexpMatches"><strong>assertRegexpMatches</strong></a>(self, text, expected_regexp, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;the&nbsp;test&nbsp;unless&nbsp;the&nbsp;text&nbsp;matches&nbsp;the&nbsp;regular&nbsp;expression.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertSequenceEqual"><strong>assertSequenceEqual</strong></a>(self, seq1, seq2, msg<font color="#909090">=None</font>, seq_type<font color="#909090">=None</font>)</dt><dd><tt>An&nbsp;equality&nbsp;assertion&nbsp;for&nbsp;ordered&nbsp;sequences&nbsp;(like&nbsp;lists&nbsp;and&nbsp;tuples).<br>
+&nbsp;<br>
+For&nbsp;the&nbsp;purposes&nbsp;of&nbsp;this&nbsp;function,&nbsp;a&nbsp;valid&nbsp;ordered&nbsp;sequence&nbsp;type&nbsp;is&nbsp;one<br>
+which&nbsp;can&nbsp;be&nbsp;indexed,&nbsp;has&nbsp;a&nbsp;length,&nbsp;and&nbsp;has&nbsp;an&nbsp;equality&nbsp;operator.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq1:&nbsp;The&nbsp;first&nbsp;sequence&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq2:&nbsp;The&nbsp;second&nbsp;sequence&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq_type:&nbsp;The&nbsp;expected&nbsp;datatype&nbsp;of&nbsp;the&nbsp;sequences,&nbsp;or&nbsp;None&nbsp;if&nbsp;no<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;datatype&nbsp;should&nbsp;be&nbsp;enforced.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertSetEqual"><strong>assertSetEqual</strong></a>(self, set1, set2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;set-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;set1:&nbsp;The&nbsp;first&nbsp;set&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;set2:&nbsp;The&nbsp;second&nbsp;set&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.<br>
+&nbsp;<br>
+assertSetEqual&nbsp;uses&nbsp;ducktyping&nbsp;to&nbsp;support&nbsp;different&nbsp;types&nbsp;of&nbsp;sets,&nbsp;and<br>
+is&nbsp;optimized&nbsp;for&nbsp;sets&nbsp;specifically&nbsp;(parameters&nbsp;must&nbsp;support&nbsp;a<br>
+difference&nbsp;method).</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertTrue"><strong>assertTrue</strong></a>(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;true.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assertTupleEqual"><strong>assertTupleEqual</strong></a>(self, tuple1, tuple2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;tuple-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tuple1:&nbsp;The&nbsp;first&nbsp;tuple&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tuple2:&nbsp;The&nbsp;second&nbsp;tuple&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-assert_"><strong>assert_</strong></a> = assertTrue(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;true.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-countTestCases"><strong>countTestCases</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-debug"><strong>debug</strong></a>(self)</dt><dd><tt>Run&nbsp;the&nbsp;test&nbsp;without&nbsp;collecting&nbsp;errors&nbsp;in&nbsp;a&nbsp;TestResult</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-defaultTestResult"><strong>defaultTestResult</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-doCleanups"><strong>doCleanups</strong></a>(self)</dt><dd><tt>Execute&nbsp;all&nbsp;cleanup&nbsp;functions.&nbsp;Normally&nbsp;called&nbsp;for&nbsp;you&nbsp;after<br>
+tearDown.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-fail"><strong>fail</strong></a>(self, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;immediately,&nbsp;with&nbsp;the&nbsp;given&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-failIf"><strong>failIf</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-failIfAlmostEqual"><strong>failIfAlmostEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-failIfEqual"><strong>failIfEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-failUnless"><strong>failUnless</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-failUnlessAlmostEqual"><strong>failUnlessAlmostEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-failUnlessEqual"><strong>failUnlessEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-failUnlessRaises"><strong>failUnlessRaises</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-id"><strong>id</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-run"><strong>run</strong></a>(self, result<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-setUp"><strong>setUp</strong></a>(self)</dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;setting&nbsp;up&nbsp;the&nbsp;test&nbsp;fixture&nbsp;before&nbsp;exercising&nbsp;it.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-shortDescription"><strong>shortDescription</strong></a>(self)</dt><dd><tt>Returns&nbsp;a&nbsp;one-line&nbsp;description&nbsp;of&nbsp;the&nbsp;test,&nbsp;or&nbsp;None&nbsp;if&nbsp;no<br>
+description&nbsp;has&nbsp;been&nbsp;provided.<br>
+&nbsp;<br>
+The&nbsp;default&nbsp;implementation&nbsp;of&nbsp;this&nbsp;method&nbsp;returns&nbsp;the&nbsp;first&nbsp;line&nbsp;of<br>
+the&nbsp;specified&nbsp;test&nbsp;method's&nbsp;docstring.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-skipTest"><strong>skipTest</strong></a>(self, reason)</dt><dd><tt>Skip&nbsp;this&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-tearDown"><strong>tearDown</strong></a>(self)</dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;deconstructing&nbsp;the&nbsp;test&nbsp;fixture&nbsp;after&nbsp;testing&nbsp;it.</tt></dd></dl>
+
+<hr>
+Class methods inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><a name="PageMeasurementUnitTestBase-setUpClass"><strong>setUpClass</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;setting&nbsp;up&nbsp;class&nbsp;fixture&nbsp;before&nbsp;running&nbsp;tests&nbsp;in&nbsp;the&nbsp;class.</tt></dd></dl>
+
+<dl><dt><a name="PageMeasurementUnitTestBase-tearDownClass"><strong>tearDownClass</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;deconstructing&nbsp;the&nbsp;class&nbsp;fixture&nbsp;after&nbsp;running&nbsp;all&nbsp;tests&nbsp;in&nbsp;the&nbsp;class.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><strong>failureException</strong> = &lt;type 'exceptions.AssertionError'&gt;<dd><tt>Assertion&nbsp;failed.</tt></dl>
+
+<dl><dt><strong>longMessage</strong> = False</dl>
+
+<dl><dt><strong>maxDiff</strong> = 640</dl>
+
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_measurement_value.html b/chromium/tools/telemetry/docs/telemetry.page.page_measurement_value.html
new file mode 100644
index 00000000000..c633b784af9
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_measurement_value.html
@@ -0,0 +1,61 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_measurement_value</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_measurement_value</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_measurement_value.py">telemetry/page/page_measurement_value.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.perf_tests_helper.html">telemetry.page.perf_tests_helper</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_measurement_value.html#PageMeasurementValue">PageMeasurementValue</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageMeasurementValue">class <strong>PageMeasurementValue</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PageMeasurementValue-__init__"><strong>__init__</strong></a>(self, trace_name, units, value, chart_name, data_type)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>measurement_name</strong></dt>
+</dl>
+<dl><dt><strong>output_value</strong></dt>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_runner.html b/chromium/tools/telemetry/docs/telemetry.page.page_runner.html
new file mode 100644
index 00000000000..7bcba136e5c
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_runner.html
@@ -0,0 +1,84 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_runner</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_runner</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_runner.py">telemetry/page/page_runner.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser_finder.html">telemetry.core.browser_finder</a><br>
+<a href="telemetry.core.exceptions.html">telemetry.core.exceptions</a><br>
+<a href="glob.html">glob</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="telemetry.page.page_filter.html">telemetry.page.page_filter</a><br>
+<a href="telemetry.page.page_test.html">telemetry.page.page_test</a><br>
+<a href="random.html">random</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="tempfile.html">tempfile</a><br>
+<a href="time.html">time</a><br>
+<a href="traceback.html">traceback</a><br>
+</td><td width="25%" valign=top><a href="urlparse.html">urlparse</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+<a href="telemetry.core.wpr_modes.html">telemetry.core.wpr_modes</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_runner.html#PageState">PageState</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageState">class <strong>PageState</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PageState-CleanUpPage"><strong>CleanUpPage</strong></a>(self, page, tab)</dt></dl>
+
+<dl><dt><a name="PageState-PreparePage"><strong>PreparePage</strong></a>(self, page, tab, test<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="PageState-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-AddCommandLineOptions"><strong>AddCommandLineOptions</strong></a>(parser)</dt></dl>
+ <dl><dt><a name="-Run"><strong>Run</strong></a>(test, page_set, options)</dt><dd><tt>Runs&nbsp;a&nbsp;given&nbsp;test&nbsp;against&nbsp;a&nbsp;given&nbsp;page_set&nbsp;with&nbsp;the&nbsp;given&nbsp;options.</tt></dd></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_set.html b/chromium/tools/telemetry/docs/telemetry.page.page_set.html
new file mode 100644
index 00000000000..ac31eaf0111
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_set.html
@@ -0,0 +1,82 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_set</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_set</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_set.py">telemetry/page/page_set.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="csv.html">csv</a><br>
+<a href="json.html">json</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="telemetry.page.page.html">telemetry.page.page</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_set_archive_info.html">telemetry.page.page_set_archive_info</a><br>
+<a href="urlparse.html">urlparse</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_set.html#PageSet">PageSet</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageSet">class <strong>PageSet</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PageSet-ContainsOnlyFileURLs"><strong>ContainsOnlyFileURLs</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageSet-ReorderPageSet"><strong>ReorderPageSet</strong></a>(self, results_file)</dt><dd><tt>Reorders&nbsp;this&nbsp;page&nbsp;set&nbsp;based&nbsp;on&nbsp;the&nbsp;results&nbsp;of&nbsp;a&nbsp;past&nbsp;run.</tt></dd></dl>
+
+<dl><dt><a name="PageSet-WprFilePathForPage"><strong>WprFilePathForPage</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageSet-__getitem__"><strong>__getitem__</strong></a>(self, key)</dt></dl>
+
+<dl><dt><a name="PageSet-__init__"><strong>__init__</strong></a>(self, file_path<font color="#909090">=''</font>, attributes<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="PageSet-__iter__"><strong>__iter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageSet-__len__"><strong>__len__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageSet-__setitem__"><strong>__setitem__</strong></a>(self, key, value)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="PageSet-FromDict"><strong>FromDict</strong></a>(cls, data, file_path)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<dl><dt><a name="PageSet-FromFile"><strong>FromFile</strong></a>(cls, file_path)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_set_archive_info.html b/chromium/tools/telemetry/docs/telemetry.page.page_set_archive_info.html
new file mode 100644
index 00000000000..f3385110aed
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_set_archive_info.html
@@ -0,0 +1,71 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_set_archive_info</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_set_archive_info</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_set_archive_info.py">telemetry/page/page_set_archive_info.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="json.html">json</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+<a href="re.html">re</a><br>
+</td><td width="25%" valign=top><a href="shutil.html">shutil</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_set_archive_info.html#PageSetArchiveInfo">PageSetArchiveInfo</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageSetArchiveInfo">class <strong>PageSetArchiveInfo</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PageSetArchiveInfo-AddNewTemporaryRecording"><strong>AddNewTemporaryRecording</strong></a>(self, temp_target_wpr_file_path)</dt></dl>
+
+<dl><dt><a name="PageSetArchiveInfo-AddRecordedPages"><strong>AddRecordedPages</strong></a>(self, urls)</dt></dl>
+
+<dl><dt><a name="PageSetArchiveInfo-WprFilePathForPage"><strong>WprFilePathForPage</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageSetArchiveInfo-__init__"><strong>__init__</strong></a>(self, archive_data_file_path, page_set_file_path, data)</dt></dl>
+
+<hr>
+Class methods defined here:<br>
+<dl><dt><a name="PageSetArchiveInfo-FromFile"><strong>FromFile</strong></a>(cls, file_path, page_set_file_path)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_test.html b/chromium/tools/telemetry/docs/telemetry.page.page_test.html
new file mode 100644
index 00000000000..07e489c52fc
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_test.html
@@ -0,0 +1,194 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_test</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_test</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_test.py">telemetry/page/page_test.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.actions.all_page_actions.html">telemetry.page.actions.all_page_actions</a><br>
+<a href="telemetry.page.gtest_test_results.html">telemetry.page.gtest_test_results</a><br>
+</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
+<a href="telemetry.page.actions.page_action.html">telemetry.page.actions.page_action</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_test_results.html">telemetry.page.page_test_results</a><br>
+<a href="telemetry.core.util.html">telemetry.core.util</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test.html#PageTest">PageTest</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="exceptions.html#Exception">exceptions.Exception</a>(<a href="exceptions.html#BaseException">exceptions.BaseException</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test.html#Failure">Failure</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Failure">class <strong>Failure</strong></a>(<a href="exceptions.html#Exception">exceptions.Exception</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt><a href="exceptions.html#Exception">Exception</a>&nbsp;that&nbsp;can&nbsp;be&nbsp;thrown&nbsp;from&nbsp;PageMeasurement&nbsp;to&nbsp;indicate&nbsp;an<br>
+undesired&nbsp;but&nbsp;designed-for&nbsp;problem.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.page_test.html#Failure">Failure</a></dd>
+<dd><a href="exceptions.html#Exception">exceptions.Exception</a></dd>
+<dd><a href="exceptions.html#BaseException">exceptions.BaseException</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Methods inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><a name="Failure-__init__"><strong>__init__</strong></a>(...)</dt><dd><tt>x.<a href="#Failure-__init__">__init__</a>(...)&nbsp;initializes&nbsp;x;&nbsp;see&nbsp;help(type(x))&nbsp;for&nbsp;signature</tt></dd></dl>
+
+<hr>
+Data and other attributes inherited from <a href="exceptions.html#Exception">exceptions.Exception</a>:<br>
+<dl><dt><strong>__new__</strong> = &lt;built-in method __new__ of type object&gt;<dd><tt>T.<a href="#Failure-__new__">__new__</a>(S,&nbsp;...)&nbsp;-&gt;&nbsp;a&nbsp;new&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;with&nbsp;type&nbsp;S,&nbsp;a&nbsp;subtype&nbsp;of&nbsp;T</tt></dl>
+
+<hr>
+Methods inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><a name="Failure-__delattr__"><strong>__delattr__</strong></a>(...)</dt><dd><tt>x.<a href="#Failure-__delattr__">__delattr__</a>('name')&nbsp;&lt;==&gt;&nbsp;del&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="Failure-__getattribute__"><strong>__getattribute__</strong></a>(...)</dt><dd><tt>x.<a href="#Failure-__getattribute__">__getattribute__</a>('name')&nbsp;&lt;==&gt;&nbsp;x.name</tt></dd></dl>
+
+<dl><dt><a name="Failure-__getitem__"><strong>__getitem__</strong></a>(...)</dt><dd><tt>x.<a href="#Failure-__getitem__">__getitem__</a>(y)&nbsp;&lt;==&gt;&nbsp;x[y]</tt></dd></dl>
+
+<dl><dt><a name="Failure-__getslice__"><strong>__getslice__</strong></a>(...)</dt><dd><tt>x.<a href="#Failure-__getslice__">__getslice__</a>(i,&nbsp;j)&nbsp;&lt;==&gt;&nbsp;x[i:j]<br>
+&nbsp;<br>
+Use&nbsp;of&nbsp;negative&nbsp;indices&nbsp;is&nbsp;not&nbsp;supported.</tt></dd></dl>
+
+<dl><dt><a name="Failure-__reduce__"><strong>__reduce__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="Failure-__repr__"><strong>__repr__</strong></a>(...)</dt><dd><tt>x.<a href="#Failure-__repr__">__repr__</a>()&nbsp;&lt;==&gt;&nbsp;repr(x)</tt></dd></dl>
+
+<dl><dt><a name="Failure-__setattr__"><strong>__setattr__</strong></a>(...)</dt><dd><tt>x.<a href="#Failure-__setattr__">__setattr__</a>('name',&nbsp;value)&nbsp;&lt;==&gt;&nbsp;x.name&nbsp;=&nbsp;value</tt></dd></dl>
+
+<dl><dt><a name="Failure-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
+
+<dl><dt><a name="Failure-__str__"><strong>__str__</strong></a>(...)</dt><dd><tt>x.<a href="#Failure-__str__">__str__</a>()&nbsp;&lt;==&gt;&nbsp;str(x)</tt></dd></dl>
+
+<dl><dt><a name="Failure-__unicode__"><strong>__unicode__</strong></a>(...)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="exceptions.html#BaseException">exceptions.BaseException</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+</dl>
+<dl><dt><strong>args</strong></dt>
+</dl>
+<dl><dt><strong>message</strong></dt>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageTest">class <strong>PageTest</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>A&nbsp;class&nbsp;styled&nbsp;on&nbsp;unittest.TestCase&nbsp;for&nbsp;creating&nbsp;page-specific&nbsp;tests.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PageTest-AddCommandLineOptions"><strong>AddCommandLineOptions</strong></a>(self, parser)</dt><dd><tt>Override&nbsp;to&nbsp;expose&nbsp;command-line&nbsp;options&nbsp;for&nbsp;this&nbsp;test.<br>
+&nbsp;<br>
+The&nbsp;provided&nbsp;parser&nbsp;is&nbsp;an&nbsp;optparse.OptionParser&nbsp;instance&nbsp;and&nbsp;accepts&nbsp;all<br>
+normal&nbsp;results.&nbsp;The&nbsp;parsed&nbsp;options&nbsp;are&nbsp;available&nbsp;in&nbsp;Run&nbsp;as<br>
+self.<strong>options</strong>.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-AddOutputOptions"><strong>AddOutputOptions</strong></a>(self, parser)</dt></dl>
+
+<dl><dt><a name="PageTest-CanRunForPage"><strong>CanRunForPage</strong></a>(self, page)</dt><dd><tt>Override&nbsp;to&nbsp;customize&nbsp;if&nbsp;the&nbsp;test&nbsp;can&nbsp;be&nbsp;ran&nbsp;for&nbsp;the&nbsp;given&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-CreatePageSet"><strong>CreatePageSet</strong></a>(self, args, options)</dt><dd><tt>Override&nbsp;to&nbsp;make&nbsp;this&nbsp;test&nbsp;generate&nbsp;its&nbsp;own&nbsp;page&nbsp;set&nbsp;instead&nbsp;of<br>
+allowing&nbsp;arbitrary&nbsp;page&nbsp;sets&nbsp;entered&nbsp;from&nbsp;the&nbsp;command-line.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;test-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions&nbsp;<a href="__builtin__.html#object">object</a></tt></dd></dl>
+
+<dl><dt><a name="PageTest-CustomizeBrowserOptionsForPage"><strong>CustomizeBrowserOptionsForPage</strong></a>(self, page, options)</dt><dd><tt>Add&nbsp;options&nbsp;specific&nbsp;to&nbsp;the&nbsp;test&nbsp;and&nbsp;the&nbsp;given&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-DidNavigateToPage"><strong>DidNavigateToPage</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;right&nbsp;after&nbsp;the&nbsp;page&nbsp;is&nbsp;navigated,&nbsp;but&nbsp;before<br>
+any&nbsp;waiting&nbsp;for&nbsp;completion&nbsp;has&nbsp;occurred.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-DidRunAction"><strong>DidRunAction</strong></a>(self, page, tab, action)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;running&nbsp;the&nbsp;action&nbsp;on&nbsp;the&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-DidRunPageSet"><strong>DidRunPageSet</strong></a>(self, tab, results)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;page&nbsp;set&nbsp;is&nbsp;completed,&nbsp;but&nbsp;before&nbsp;browser<br>
+is&nbsp;torn&nbsp;down.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-DidStartHTTPServer"><strong>DidStartHTTPServer</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;the&nbsp;HTTP&nbsp;server&nbsp;is&nbsp;started.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-NeedsBrowserRestartAfterEachRun"><strong>NeedsBrowserRestartAfterEachRun</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;specify&nbsp;browser&nbsp;restart&nbsp;after&nbsp;each&nbsp;run.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-PrepareResults"><strong>PrepareResults</strong></a>(self, options)</dt></dl>
+
+<dl><dt><a name="PageTest-Run"><strong>Run</strong></a>(self, options, page, tab, results)</dt></dl>
+
+<dl><dt><a name="PageTest-SetUpBrowser"><strong>SetUpBrowser</strong></a>(self, browser)</dt><dd><tt>Override&nbsp;to&nbsp;customize&nbsp;the&nbsp;browser&nbsp;right&nbsp;after&nbsp;it&nbsp;has&nbsp;launched.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-WillNavigateToPage"><strong>WillNavigateToPage</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;the&nbsp;page&nbsp;is&nbsp;navigated.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab, action)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;running&nbsp;the&nbsp;action&nbsp;on&nbsp;the&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-WillRunPageSet"><strong>WillRunPageSet</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;the&nbsp;page&nbsp;set&nbsp;is&nbsp;navigated.</tt></dd></dl>
+
+<dl><dt><a name="PageTest-__init__"><strong>__init__</strong></a>(self, test_method_name, action_name_to_run<font color="#909090">=''</font>, needs_browser_restart_after_each_run<font color="#909090">=False</font>, discard_first_result<font color="#909090">=False</font>, clear_cache_before_each_run<font color="#909090">=False</font>)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>action_name_to_run</strong></dt>
+</dl>
+<dl><dt><strong>clear_cache_before_each_run</strong></dt>
+<dd><tt>When&nbsp;set&nbsp;to&nbsp;True,&nbsp;the&nbsp;browser's&nbsp;disk&nbsp;and&nbsp;memory&nbsp;cache&nbsp;will&nbsp;be&nbsp;cleared<br>
+before&nbsp;each&nbsp;run.</tt></dd>
+</dl>
+<dl><dt><strong>discard_first_result</strong></dt>
+<dd><tt>When&nbsp;set&nbsp;to&nbsp;True,&nbsp;the&nbsp;first&nbsp;run&nbsp;of&nbsp;the&nbsp;test&nbsp;is&nbsp;discarded.&nbsp;&nbsp;This&nbsp;is<br>
+useful&nbsp;for&nbsp;cases&nbsp;where&nbsp;it's&nbsp;desirable&nbsp;to&nbsp;have&nbsp;some&nbsp;test&nbsp;resource&nbsp;cached&nbsp;so<br>
+the&nbsp;first&nbsp;run&nbsp;of&nbsp;the&nbsp;test&nbsp;can&nbsp;warm&nbsp;things&nbsp;up.</tt></dd>
+</dl>
+<dl><dt><strong>output_format_choices</strong></dt>
+<dd><tt>Allowed&nbsp;output&nbsp;formats.&nbsp;The&nbsp;default&nbsp;is&nbsp;the&nbsp;first&nbsp;item&nbsp;in&nbsp;the&nbsp;list.</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-GetCompoundActionFromPage"><strong>GetCompoundActionFromPage</strong></a>(page, action_name)</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_test_results.html b/chromium/tools/telemetry/docs/telemetry.page.page_test_results.html
new file mode 100644
index 00000000000..1ffb1b98e51
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_test_results.html
@@ -0,0 +1,120 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_test_results</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_test_results</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_test_results.py">telemetry/page/page_test_results.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="traceback.html">traceback</a><br>
+</td><td width="25%" valign=top><a href="unittest.html">unittest</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="unittest.result.html#TestResult">unittest.result.TestResult</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test_results.html#PageTestResults">PageTestResults</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageTestResults">class <strong>PageTestResults</strong></a>(<a href="unittest.result.html#TestResult">unittest.result.TestResult</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.page_test_results.html#PageTestResults">PageTestResults</a></dd>
+<dd><a href="unittest.result.html#TestResult">unittest.result.TestResult</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="PageTestResults-AddError"><strong>AddError</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="PageTestResults-AddErrorMessage"><strong>AddErrorMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="PageTestResults-AddFailure"><strong>AddFailure</strong></a>(self, page, err)</dt></dl>
+
+<dl><dt><a name="PageTestResults-AddFailureMessage"><strong>AddFailureMessage</strong></a>(self, page, message)</dt></dl>
+
+<dl><dt><a name="PageTestResults-AddSkip"><strong>AddSkip</strong></a>(self, page, reason)</dt></dl>
+
+<dl><dt><a name="PageTestResults-AddSuccess"><strong>AddSuccess</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageTestResults-PrintSummary"><strong>PrintSummary</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageTestResults-StartTest"><strong>StartTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageTestResults-StopTest"><strong>StopTest</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="PageTestResults-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageTestResults-addSkip"><strong>addSkip</strong></a>(self, test, reason)</dt></dl>
+
+<dl><dt><a name="PageTestResults-addSuccess"><strong>addSuccess</strong></a>(self, test)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><a name="PageTestResults-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="PageTestResults-addError"><strong>addError</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-addExpectedFailure"><strong>addExpectedFailure</strong></a>(self, test, err)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;expected&nbsp;failure/error&nbsp;occured.</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-addFailure"><strong>addFailure</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;an&nbsp;error&nbsp;has&nbsp;occurred.&nbsp;'err'&nbsp;is&nbsp;a&nbsp;tuple&nbsp;of&nbsp;values&nbsp;as<br>
+returned&nbsp;by&nbsp;sys.exc_info().</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-addUnexpectedSuccess"><strong>addUnexpectedSuccess</strong></a>(self, *args, **kw)</dt><dd><tt>Called&nbsp;when&nbsp;a&nbsp;test&nbsp;was&nbsp;expected&nbsp;to&nbsp;fail,&nbsp;but&nbsp;succeed.</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-printErrors"><strong>printErrors</strong></a>(self)</dt><dd><tt>Called&nbsp;by&nbsp;TestRunner&nbsp;after&nbsp;test&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-startTest"><strong>startTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;is&nbsp;about&nbsp;to&nbsp;be&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-startTestRun"><strong>startTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;before&nbsp;any&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;startTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;before&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-stop"><strong>stop</strong></a>(self)</dt><dd><tt>Indicates&nbsp;that&nbsp;the&nbsp;tests&nbsp;should&nbsp;be&nbsp;aborted</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-stopTest"><strong>stopTest</strong></a>(self, test)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;given&nbsp;test&nbsp;has&nbsp;been&nbsp;run</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-stopTestRun"><strong>stopTestRun</strong></a>(self)</dt><dd><tt>Called&nbsp;once&nbsp;after&nbsp;all&nbsp;tests&nbsp;are&nbsp;executed.<br>
+&nbsp;<br>
+See&nbsp;stopTest&nbsp;for&nbsp;a&nbsp;method&nbsp;called&nbsp;after&nbsp;each&nbsp;test.</tt></dd></dl>
+
+<dl><dt><a name="PageTestResults-wasSuccessful"><strong>wasSuccessful</strong></a>(self)</dt><dd><tt>Tells&nbsp;whether&nbsp;or&nbsp;not&nbsp;this&nbsp;result&nbsp;was&nbsp;a&nbsp;success</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.result.html#TestResult">unittest.result.TestResult</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.page_test_runner.html b/chromium/tools/telemetry/docs/telemetry.page.page_test_runner.html
new file mode 100644
index 00000000000..6856c9bf6a1
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.page_test_runner.html
@@ -0,0 +1,104 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.page_test_runner</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.page_test_runner</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/page_test_runner.py">telemetry/page/page_test_runner.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser_options.html">telemetry.core.browser_options</a><br>
+<a href="telemetry.core.discover.html">telemetry.core.discover</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_runner.html">telemetry.page.page_runner</a><br>
+<a href="telemetry.page.page_set.html">telemetry.page.page_set</a><br>
+<a href="telemetry.page.page_test.html">telemetry.page.page_test</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.profile_types.html">telemetry.core.profile_types</a><br>
+<a href="sys.html">sys</a><br>
+<a href="telemetry.test.html">telemetry.test</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test_runner.html#PageTestRunner">PageTestRunner</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="PageTestRunner">class <strong>PageTestRunner</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="PageTestRunner-FindTestConstructors"><strong>FindTestConstructors</strong></a>(self, base_dir)</dt></dl>
+
+<dl><dt><a name="PageTestRunner-FindTestName"><strong>FindTestName</strong></a>(self, test_constructors, args)</dt><dd><tt>Find&nbsp;the&nbsp;test&nbsp;name&nbsp;in&nbsp;an&nbsp;arbitrary&nbsp;argument&nbsp;list.<br>
+&nbsp;<br>
+We&nbsp;can't&nbsp;use&nbsp;the&nbsp;optparse&nbsp;parser,&nbsp;because&nbsp;the&nbsp;test&nbsp;may&nbsp;add&nbsp;its&nbsp;own<br>
+command-line&nbsp;options.&nbsp;If&nbsp;the&nbsp;user&nbsp;passed&nbsp;in&nbsp;any&nbsp;of&nbsp;those,&nbsp;the<br>
+optparse&nbsp;parsing&nbsp;will&nbsp;fail.<br>
+&nbsp;<br>
+Returns:<br>
+&nbsp;&nbsp;test_name&nbsp;or&nbsp;None</tt></dd></dl>
+
+<dl><dt><a name="PageTestRunner-GetModernizedTestName"><strong>GetModernizedTestName</strong></a>(self, arg)</dt><dd><tt>Sometimes&nbsp;tests&nbsp;change&nbsp;names&nbsp;but&nbsp;buildbots&nbsp;keep&nbsp;calling&nbsp;the&nbsp;old&nbsp;name.<br>
+&nbsp;<br>
+If&nbsp;arg&nbsp;matches&nbsp;an&nbsp;old&nbsp;test&nbsp;name,&nbsp;return&nbsp;the&nbsp;new&nbsp;test&nbsp;name&nbsp;instead.<br>
+Otherwise,&nbsp;return&nbsp;the&nbsp;arg.</tt></dd></dl>
+
+<dl><dt><a name="PageTestRunner-GetPageSet"><strong>GetPageSet</strong></a>(self, test, page_set_filenames)</dt></dl>
+
+<dl><dt><a name="PageTestRunner-ParseCommandLine"><strong>ParseCommandLine</strong></a>(self, args, base_dir, page_set_filenames)</dt></dl>
+
+<dl><dt><a name="PageTestRunner-PrintParseError"><strong>PrintParseError</strong></a>(self, message)</dt></dl>
+
+<dl><dt><a name="PageTestRunner-Run"><strong>Run</strong></a>(self, base_dir, page_set_filenames)</dt></dl>
+
+<dl><dt><a name="PageTestRunner-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>test_class</strong></dt>
+</dl>
+<dl><dt><strong>test_class_name</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-Main"><strong>Main</strong></a>(base_dir, page_set_filenames)</dt><dd><tt>Turns&nbsp;a&nbsp;PageTest&nbsp;into&nbsp;a&nbsp;command-line&nbsp;program.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;base_dir:&nbsp;Path&nbsp;to&nbsp;directory&nbsp;containing&nbsp;tests&nbsp;and&nbsp;ProfileCreators.</tt></dd></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.perf_tests_helper.html b/chromium/tools/telemetry/docs/telemetry.page.perf_tests_helper.html
new file mode 100644
index 00000000000..8b2466d64e7
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.perf_tests_helper.html
@@ -0,0 +1,41 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.perf_tests_helper</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.perf_tests_helper</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/perf_tests_helper.py">telemetry/page/perf_tests_helper.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="pylib.perf_tests_helper.html">pylib.perf_tests_helper</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-__init__"><strong>__init__</strong></a>()</dt></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>absolute_import</strong> = _Feature((2, 5, 0, 'alpha', 1), (2, 7, 0, 'alpha', 0), 16384)</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.page.record_wpr.html b/chromium/tools/telemetry/docs/telemetry.page.record_wpr.html
new file mode 100644
index 00000000000..a82922f1f0f
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.page.record_wpr.html
@@ -0,0 +1,140 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.page.record_wpr</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.page.html"><font color="#ffffff">page</font></a>.record_wpr</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/page/record_wpr.py">telemetry/page/record_wpr.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser_options.html">telemetry.core.browser_options</a><br>
+<a href="telemetry.core.discover.html">telemetry.core.discover</a><br>
+<a href="logging.html">logging</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_measurement.html">telemetry.page.page_measurement</a><br>
+<a href="telemetry.page.page_runner.html">telemetry.page.page_runner</a><br>
+<a href="telemetry.page.page_set.html">telemetry.page.page_set</a><br>
+<a href="telemetry.page.page_test.html">telemetry.page.page_test</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="tempfile.html">tempfile</a><br>
+<a href="telemetry.test.html">telemetry.test</a><br>
+<a href="time.html">time</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.wpr_modes.html">telemetry.core.wpr_modes</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.page.record_wpr.html#RecordPage">RecordPage</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="RecordPage">class <strong>RecordPage</strong></a>(<a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.page.record_wpr.html#RecordPage">RecordPage</a></dd>
+<dd><a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="RecordPage-CanRunForPage"><strong>CanRunForPage</strong></a>(self, page)</dt></dl>
+
+<dl><dt><a name="RecordPage-CustomizeBrowserOptionsForPage"><strong>CustomizeBrowserOptionsForPage</strong></a>(self, page, options)</dt></dl>
+
+<dl><dt><a name="RecordPage-Run"><strong>Run</strong></a>(self, options, page, tab, results)</dt></dl>
+
+<dl><dt><a name="RecordPage-__init__"><strong>__init__</strong></a>(self, measurements)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>:<br>
+<dl><dt><a name="RecordPage-AddCommandLineOptions"><strong>AddCommandLineOptions</strong></a>(self, parser)</dt><dd><tt>Override&nbsp;to&nbsp;expose&nbsp;command-line&nbsp;options&nbsp;for&nbsp;this&nbsp;test.<br>
+&nbsp;<br>
+The&nbsp;provided&nbsp;parser&nbsp;is&nbsp;an&nbsp;optparse.OptionParser&nbsp;instance&nbsp;and&nbsp;accepts&nbsp;all<br>
+normal&nbsp;results.&nbsp;The&nbsp;parsed&nbsp;options&nbsp;are&nbsp;available&nbsp;in&nbsp;Run&nbsp;as<br>
+self.<strong>options</strong>.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-AddOutputOptions"><strong>AddOutputOptions</strong></a>(self, parser)</dt></dl>
+
+<dl><dt><a name="RecordPage-CreatePageSet"><strong>CreatePageSet</strong></a>(self, args, options)</dt><dd><tt>Override&nbsp;to&nbsp;make&nbsp;this&nbsp;test&nbsp;generate&nbsp;its&nbsp;own&nbsp;page&nbsp;set&nbsp;instead&nbsp;of<br>
+allowing&nbsp;arbitrary&nbsp;page&nbsp;sets&nbsp;entered&nbsp;from&nbsp;the&nbsp;command-line.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;test-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions&nbsp;object</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-DidNavigateToPage"><strong>DidNavigateToPage</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;right&nbsp;after&nbsp;the&nbsp;page&nbsp;is&nbsp;navigated,&nbsp;but&nbsp;before<br>
+any&nbsp;waiting&nbsp;for&nbsp;completion&nbsp;has&nbsp;occurred.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-DidRunAction"><strong>DidRunAction</strong></a>(self, page, tab, action)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;running&nbsp;the&nbsp;action&nbsp;on&nbsp;the&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-DidRunPageSet"><strong>DidRunPageSet</strong></a>(self, tab, results)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;page&nbsp;set&nbsp;is&nbsp;completed,&nbsp;but&nbsp;before&nbsp;browser<br>
+is&nbsp;torn&nbsp;down.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-DidStartHTTPServer"><strong>DidStartHTTPServer</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;after&nbsp;the&nbsp;HTTP&nbsp;server&nbsp;is&nbsp;started.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-NeedsBrowserRestartAfterEachRun"><strong>NeedsBrowserRestartAfterEachRun</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;specify&nbsp;browser&nbsp;restart&nbsp;after&nbsp;each&nbsp;run.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-PrepareResults"><strong>PrepareResults</strong></a>(self, options)</dt></dl>
+
+<dl><dt><a name="RecordPage-SetUpBrowser"><strong>SetUpBrowser</strong></a>(self, browser)</dt><dd><tt>Override&nbsp;to&nbsp;customize&nbsp;the&nbsp;browser&nbsp;right&nbsp;after&nbsp;it&nbsp;has&nbsp;launched.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-WillNavigateToPage"><strong>WillNavigateToPage</strong></a>(self, page, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;the&nbsp;page&nbsp;is&nbsp;navigated.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-WillRunAction"><strong>WillRunAction</strong></a>(self, page, tab, action)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;running&nbsp;the&nbsp;action&nbsp;on&nbsp;the&nbsp;page.</tt></dd></dl>
+
+<dl><dt><a name="RecordPage-WillRunPageSet"><strong>WillRunPageSet</strong></a>(self, tab)</dt><dd><tt>Override&nbsp;to&nbsp;do&nbsp;operations&nbsp;before&nbsp;the&nbsp;page&nbsp;set&nbsp;is&nbsp;navigated.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.page.page_test.html#PageTest">telemetry.page.page_test.PageTest</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>action_name_to_run</strong></dt>
+</dl>
+<dl><dt><strong>clear_cache_before_each_run</strong></dt>
+<dd><tt>When&nbsp;set&nbsp;to&nbsp;True,&nbsp;the&nbsp;browser's&nbsp;disk&nbsp;and&nbsp;memory&nbsp;cache&nbsp;will&nbsp;be&nbsp;cleared<br>
+before&nbsp;each&nbsp;run.</tt></dd>
+</dl>
+<dl><dt><strong>discard_first_result</strong></dt>
+<dd><tt>When&nbsp;set&nbsp;to&nbsp;True,&nbsp;the&nbsp;first&nbsp;run&nbsp;of&nbsp;the&nbsp;test&nbsp;is&nbsp;discarded.&nbsp;&nbsp;This&nbsp;is<br>
+useful&nbsp;for&nbsp;cases&nbsp;where&nbsp;it's&nbsp;desirable&nbsp;to&nbsp;have&nbsp;some&nbsp;test&nbsp;resource&nbsp;cached&nbsp;so<br>
+the&nbsp;first&nbsp;run&nbsp;of&nbsp;the&nbsp;test&nbsp;can&nbsp;warm&nbsp;things&nbsp;up.</tt></dd>
+</dl>
+<dl><dt><strong>output_format_choices</strong></dt>
+<dd><tt>Allowed&nbsp;output&nbsp;formats.&nbsp;The&nbsp;default&nbsp;is&nbsp;the&nbsp;first&nbsp;item&nbsp;in&nbsp;the&nbsp;list.</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-Main"><strong>Main</strong></a>(base_dir)</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.test.html b/chromium/tools/telemetry/docs/telemetry.test.html
new file mode 100644
index 00000000000..34821365ad3
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.test.html
@@ -0,0 +1,74 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.test</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.test</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/test.py">telemetry/test.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2013&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.page_runner.html">telemetry.page.page_runner</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_set.html">telemetry.page.page_set</a><br>
+</td><td width="25%" valign=top><a href="telemetry.page.page_test.html">telemetry.page.page_test</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.test.html#Test">Test</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Test">class <strong>Test</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Base&nbsp;class&nbsp;for&nbsp;a&nbsp;Telemetry&nbsp;test&nbsp;or&nbsp;benchmark.<br>
+&nbsp;<br>
+A&nbsp;test&nbsp;packages&nbsp;a&nbsp;PageTest/PageMeasurement&nbsp;and&nbsp;a&nbsp;PageSet&nbsp;together.<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Test-CreatePageSet"><strong>CreatePageSet</strong></a>(self, options)</dt><dd><tt>Get&nbsp;the&nbsp;page&nbsp;set&nbsp;this&nbsp;test&nbsp;will&nbsp;run&nbsp;on.<br>
+&nbsp;<br>
+By&nbsp;default,&nbsp;it&nbsp;will&nbsp;create&nbsp;a&nbsp;page&nbsp;set&nbsp;from&nbsp;the&nbsp;file&nbsp;at&nbsp;this&nbsp;test's<br>
+page_set&nbsp;attribute.&nbsp;Override&nbsp;to&nbsp;generate&nbsp;a&nbsp;custom&nbsp;page&nbsp;set.</tt></dd></dl>
+
+<dl><dt><a name="Test-Run"><strong>Run</strong></a>(self, options)</dt><dd><tt>Run&nbsp;this&nbsp;test&nbsp;with&nbsp;the&nbsp;given&nbsp;options.</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>enabled</strong> = True</dl>
+
+<dl><dt><strong>options</strong> = {}</dl>
+
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.test_runner.html b/chromium/tools/telemetry/docs/telemetry.test_runner.html
new file mode 100644
index 00000000000..e3974928eb0
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.test_runner.html
@@ -0,0 +1,229 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.test_runner</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.test_runner</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/test_runner.py">telemetry/test_runner.py</a></font></td></tr></table>
+ <p><tt>Parses&nbsp;the&nbsp;command&nbsp;line,&nbsp;discovers&nbsp;the&nbsp;appropriate&nbsp;tests,&nbsp;and&nbsp;runs&nbsp;them.<br>
+&nbsp;<br>
+Handles&nbsp;test&nbsp;configuration,&nbsp;but&nbsp;all&nbsp;the&nbsp;logic&nbsp;for<br>
+actually&nbsp;running&nbsp;the&nbsp;test&nbsp;is&nbsp;in&nbsp;Test&nbsp;and&nbsp;PageRunner.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser_options.html">telemetry.core.browser_options</a><br>
+<a href="telemetry.test.html">telemetry.test</a><br>
+<a href="copy.html">copy</a><br>
+</td><td width="25%" valign=top><a href="telemetry.core.discover.html">telemetry.core.discover</a><br>
+<a href="inspect.html">inspect</a><br>
+<a href="json.html">json</a><br>
+</td><td width="25%" valign=top><a href="optparse.html">optparse</a><br>
+<a href="os.html">os</a><br>
+<a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="telemetry.test.html">telemetry.test</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.test_runner.html#Command">Command</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.test_runner.html#Help">Help</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.test_runner.html#List">List</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.test_runner.html#Run">Run</a>
+</font></dt></dl>
+</dd>
+</dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Command">class <strong>Command</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Command-AddParserOptions"><strong>AddParserOptions</strong></a>(self, parser)</dt></dl>
+
+<dl><dt><a name="Command-CreateParser"><strong>CreateParser</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Command-Run"><strong>Run</strong></a>(self, options, args)</dt></dl>
+
+<dl><dt><a name="Command-ValidateCommandLine"><strong>ValidateCommandLine</strong></a>(self, parser, options, args)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>description</strong></dt>
+</dl>
+<dl><dt><strong>name</strong></dt>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>usage</strong> = ''</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Help">class <strong>Help</strong></a>(<a href="telemetry.test_runner.html#Command">Command</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Display&nbsp;help&nbsp;information<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.test_runner.html#Help">Help</a></dd>
+<dd><a href="telemetry.test_runner.html#Command">Command</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Help-Run"><strong>Run</strong></a>(self, options, args)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.test_runner.html#Command">Command</a>:<br>
+<dl><dt><a name="Help-AddParserOptions"><strong>AddParserOptions</strong></a>(self, parser)</dt></dl>
+
+<dl><dt><a name="Help-CreateParser"><strong>CreateParser</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Help-ValidateCommandLine"><strong>ValidateCommandLine</strong></a>(self, parser, options, args)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.test_runner.html#Command">Command</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>description</strong></dt>
+</dl>
+<dl><dt><strong>name</strong></dt>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="telemetry.test_runner.html#Command">Command</a>:<br>
+<dl><dt><strong>usage</strong> = ''</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="List">class <strong>List</strong></a>(<a href="telemetry.test_runner.html#Command">Command</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt>Lists&nbsp;the&nbsp;available&nbsp;tests<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.test_runner.html#List">List</a></dd>
+<dd><a href="telemetry.test_runner.html#Command">Command</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="List-AddParserOptions"><strong>AddParserOptions</strong></a>(self, parser)</dt></dl>
+
+<dl><dt><a name="List-Run"><strong>Run</strong></a>(self, options, args)</dt></dl>
+
+<hr>
+Methods inherited from <a href="telemetry.test_runner.html#Command">Command</a>:<br>
+<dl><dt><a name="List-CreateParser"><strong>CreateParser</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="List-ValidateCommandLine"><strong>ValidateCommandLine</strong></a>(self, parser, options, args)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.test_runner.html#Command">Command</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>description</strong></dt>
+</dl>
+<dl><dt><strong>name</strong></dt>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="telemetry.test_runner.html#Command">Command</a>:<br>
+<dl><dt><strong>usage</strong> = ''</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Run">class <strong>Run</strong></a>(<a href="telemetry.test_runner.html#Command">Command</a>)</font></td></tr>
+
+<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
+<td colspan=2><tt><a href="#Run">Run</a>&nbsp;one&nbsp;or&nbsp;more&nbsp;tests<br>&nbsp;</tt></td></tr>
+<tr><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.test_runner.html#Run">Run</a></dd>
+<dd><a href="telemetry.test_runner.html#Command">Command</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="Run-CreateParser"><strong>CreateParser</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Run-Run"><strong>Run</strong></a>(self, options, args)</dt></dl>
+
+<dl><dt><a name="Run-ValidateCommandLine"><strong>ValidateCommandLine</strong></a>(self, parser, options, args)</dt></dl>
+
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>usage</strong> = 'test_name [...] [&lt;args&gt;]'</dl>
+
+<hr>
+Methods inherited from <a href="telemetry.test_runner.html#Command">Command</a>:<br>
+<dl><dt><a name="Run-AddParserOptions"><strong>AddParserOptions</strong></a>(self, parser)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="telemetry.test_runner.html#Command">Command</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>description</strong></dt>
+</dl>
+<dl><dt><strong>name</strong></dt>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-Main"><strong>Main</strong></a>()</dt></dl>
+</td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>COMMANDS</strong> = [&lt;telemetry.test_runner.Help object&gt;, &lt;telemetry.test_runner.List object&gt;, &lt;telemetry.test_runner.Run object&gt;]</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.unittest.gtest_testrunner.html b/chromium/tools/telemetry/docs/telemetry.unittest.gtest_testrunner.html
new file mode 100644
index 00000000000..d257dc6452d
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.unittest.gtest_testrunner.html
@@ -0,0 +1,121 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.unittest.gtest_testrunner</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.unittest.html"><font color="#ffffff">unittest</font></a>.gtest_testrunner</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/unittest/gtest_testrunner.py">telemetry/unittest/gtest_testrunner.py</a></font></td></tr></table>
+ <p><tt>Implements&nbsp;a&nbsp;unittest&nbsp;TestRunner&nbsp;with&nbsp;GTest&nbsp;output.<br>
+&nbsp;<br>
+This&nbsp;output&nbsp;is&nbsp;ported&nbsp;from&nbsp;gtest.cc's&nbsp;PrettyUnitTestResultPrinter,&nbsp;but<br>
+designed&nbsp;to&nbsp;be&nbsp;a&nbsp;drop-in&nbsp;replacement&nbsp;for&nbsp;unittest's&nbsp;TextTestRunner.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.page.gtest_test_results.html">telemetry.page.gtest_test_results</a><br>
+</td><td width="25%" valign=top><a href="time.html">time</a><br>
+</td><td width="25%" valign=top><a href="unittest.html">unittest</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.unittest.gtest_testrunner.html#GTestTestRunner">GTestTestRunner</a>
+</font></dt></dl>
+</dd>
+<dt><font face="helvetica, arial"><a href="unittest.suite.html#TestSuite">unittest.suite.TestSuite</a>(<a href="unittest.suite.html#BaseTestSuite">unittest.suite.BaseTestSuite</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.unittest.gtest_testrunner.html#GTestTestSuite">GTestTestSuite</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="GTestTestRunner">class <strong>GTestTestRunner</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="GTestTestRunner-__init__"><strong>__init__</strong></a>(self, print_result_after_run<font color="#909090">=True</font>, runner<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="GTestTestRunner-run"><strong>run</strong></a>(self, test)</dt><dd><tt>Run&nbsp;the&nbsp;given&nbsp;test&nbsp;case&nbsp;or&nbsp;test&nbsp;suite.</tt></dd></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="GTestTestSuite">class <strong>GTestTestSuite</strong></a>(<a href="unittest.suite.html#TestSuite">unittest.suite.TestSuite</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.unittest.gtest_testrunner.html#GTestTestSuite">GTestTestSuite</a></dd>
+<dd><a href="unittest.suite.html#TestSuite">unittest.suite.TestSuite</a></dd>
+<dd><a href="unittest.suite.html#BaseTestSuite">unittest.suite.BaseTestSuite</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="GTestTestSuite-__call__"><strong>__call__</strong></a>(self, *args, **kwargs)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.suite.html#TestSuite">unittest.suite.TestSuite</a>:<br>
+<dl><dt><a name="GTestTestSuite-debug"><strong>debug</strong></a>(self)</dt><dd><tt>Run&nbsp;the&nbsp;tests&nbsp;without&nbsp;collecting&nbsp;errors&nbsp;in&nbsp;a&nbsp;TestResult</tt></dd></dl>
+
+<dl><dt><a name="GTestTestSuite-run"><strong>run</strong></a>(self, result, debug<font color="#909090">=False</font>)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.suite.html#BaseTestSuite">unittest.suite.BaseTestSuite</a>:<br>
+<dl><dt><a name="GTestTestSuite-__eq__"><strong>__eq__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="GTestTestSuite-__init__"><strong>__init__</strong></a>(self, tests<font color="#909090">=()</font>)</dt></dl>
+
+<dl><dt><a name="GTestTestSuite-__iter__"><strong>__iter__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="GTestTestSuite-__ne__"><strong>__ne__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="GTestTestSuite-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="GTestTestSuite-addTest"><strong>addTest</strong></a>(self, test)</dt></dl>
+
+<dl><dt><a name="GTestTestSuite-addTests"><strong>addTests</strong></a>(self, tests)</dt></dl>
+
+<dl><dt><a name="GTestTestSuite-countTestCases"><strong>countTestCases</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.suite.html#BaseTestSuite">unittest.suite.BaseTestSuite</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="unittest.suite.html#BaseTestSuite">unittest.suite.BaseTestSuite</a>:<br>
+<dl><dt><strong>__hash__</strong> = None</dl>
+
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.unittest.html b/chromium/tools/telemetry/docs/telemetry.unittest.html
new file mode 100644
index 00000000000..9f77fb7a111
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.unittest.html
@@ -0,0 +1,41 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: package telemetry.unittest</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.unittest</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/unittest/__init__.py">telemetry/unittest/__init__.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.unittest.gtest_testrunner.html">gtest_testrunner</a><br>
+<a href="telemetry.unittest.options_for_unittests.html">options_for_unittests</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.run_tests.html">run_tests</a><br>
+<a href="telemetry.unittest.simple_mock.html">simple_mock</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.simple_mock_unittest.html">simple_mock_unittest</a><br>
+<a href="telemetry.unittest.system_stub.html">system_stub</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.tab_test_case.html">tab_test_case</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-DisabledTest"><strong>DisabledTest</strong></a>(func)</dt></dl>
+ <dl><dt><a name="-RequiresBrowserOfType"><strong>RequiresBrowserOfType</strong></a>(*types)</dt><dd><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></dd></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.unittest.options_for_unittests.html b/chromium/tools/telemetry/docs/telemetry.unittest.options_for_unittests.html
new file mode 100644
index 00000000000..8a6432f76df
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.unittest.options_for_unittests.html
@@ -0,0 +1,31 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.unittest.options_for_unittests</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.unittest.html"><font color="#ffffff">unittest</font></a>.options_for_unittests</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/unittest/options_for_unittests.py">telemetry/unittest/options_for_unittests.py</a></font></td></tr></table>
+ <p><tt>This&nbsp;module&nbsp;provides&nbsp;the&nbsp;global&nbsp;variable&nbsp;options_for_unittests.<br>
+&nbsp;<br>
+This&nbsp;is&nbsp;set&nbsp;to&nbsp;a&nbsp;BrowserOptions&nbsp;object&nbsp;by&nbsp;the&nbsp;test&nbsp;harness,&nbsp;or&nbsp;None<br>
+if&nbsp;unit&nbsp;tests&nbsp;are&nbsp;not&nbsp;running.<br>
+&nbsp;<br>
+This&nbsp;allows&nbsp;multiple&nbsp;unit&nbsp;tests&nbsp;to&nbsp;use&nbsp;a&nbsp;specific<br>
+browser,&nbsp;in&nbsp;face&nbsp;of&nbsp;multiple&nbsp;options.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-AreSet"><strong>AreSet</strong></a>()</dt></dl>
+ <dl><dt><a name="-GetBrowserType"><strong>GetBrowserType</strong></a>()</dt></dl>
+ <dl><dt><a name="-GetCopy"><strong>GetCopy</strong></a>()</dt></dl>
+ <dl><dt><a name="-Set"><strong>Set</strong></a>(options, browser_type)</dt></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.unittest.run_tests.html b/chromium/tools/telemetry/docs/telemetry.unittest.run_tests.html
new file mode 100644
index 00000000000..3cedf276030
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.unittest.run_tests.html
@@ -0,0 +1,42 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.unittest.run_tests</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.unittest.html"><font color="#ffffff">unittest</font></a>.run_tests</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/unittest/run_tests.py">telemetry/unittest/run_tests.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser_options.html">telemetry.core.browser_options</a><br>
+<a href="telemetry.core.discover.html">telemetry.core.discover</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.gtest_testrunner.html">telemetry.unittest.gtest_testrunner</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.options_for_unittests.html">telemetry.unittest.options_for_unittests</a><br>
+<a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+<a href="unittest.html">unittest</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt><a name="-Discover"><strong>Discover</strong></a>(start_dir, top_level_dir<font color="#909090">=None</font>, pattern<font color="#909090">='test*.py'</font>)</dt></dl>
+ <dl><dt><a name="-DiscoverAndRunTests"><strong>DiscoverAndRunTests</strong></a>(dir_name, args, top_level_dir, runner<font color="#909090">=None</font>, run_disabled_tests<font color="#909090">=False</font>)</dt></dl>
+ <dl><dt><a name="-FilterSuite"><strong>FilterSuite</strong></a>(suite, predicate)</dt></dl>
+ <dl><dt><a name="-Main"><strong>Main</strong></a>(args, start_dir, top_level_dir, runner<font color="#909090">=None</font>)</dt><dd><tt>Unit&nbsp;test&nbsp;suite&nbsp;that&nbsp;collects&nbsp;all&nbsp;test&nbsp;cases&nbsp;for&nbsp;telemetry.</tt></dd></dl>
+</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.unittest.simple_mock.html b/chromium/tools/telemetry/docs/telemetry.unittest.simple_mock.html
new file mode 100644
index 00000000000..1081acc53bc
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.unittest.simple_mock.html
@@ -0,0 +1,106 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.unittest.simple_mock</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.unittest.html"><font color="#ffffff">unittest</font></a>.simple_mock</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/unittest/simple_mock.py">telemetry/unittest/simple_mock.py</a></font></td></tr></table>
+ <p><tt>A&nbsp;very&nbsp;very&nbsp;simple&nbsp;mock&nbsp;<a href="__builtin__.html#object">object</a>&nbsp;harness.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.unittest.simple_mock.html#MockFunctionCall">MockFunctionCall</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.unittest.simple_mock.html#MockObject">MockObject</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.unittest.simple_mock.html#MockTrace">MockTrace</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MockFunctionCall">class <strong>MockFunctionCall</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="MockFunctionCall-VerifyEquals"><strong>VerifyEquals</strong></a>(self, got)</dt></dl>
+
+<dl><dt><a name="MockFunctionCall-WhenCalled"><strong>WhenCalled</strong></a>(self, handler)</dt></dl>
+
+<dl><dt><a name="MockFunctionCall-WillReturn"><strong>WillReturn</strong></a>(self, value)</dt></dl>
+
+<dl><dt><a name="MockFunctionCall-WithArgs"><strong>WithArgs</strong></a>(self, *args)</dt></dl>
+
+<dl><dt><a name="MockFunctionCall-__init__"><strong>__init__</strong></a>(self, name)</dt></dl>
+
+<dl><dt><a name="MockFunctionCall-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MockObject">class <strong>MockObject</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="MockObject-ExpectCall"><strong>ExpectCall</strong></a>(self, func_name, *args)</dt></dl>
+
+<dl><dt><a name="MockObject-__init__"><strong>__init__</strong></a>(self, parent_mock<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="MockObject-__setattr__"><strong>__setattr__</strong></a>(self, name, value)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="MockTrace">class <strong>MockTrace</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="MockTrace-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#55aa55">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
+
+<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><strong>DONT_CARE</strong> = ''</td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.unittest.system_stub.html b/chromium/tools/telemetry/docs/telemetry.unittest.system_stub.html
new file mode 100644
index 00000000000..c78cb03e5ca
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.unittest.system_stub.html
@@ -0,0 +1,164 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.unittest.system_stub</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.unittest.html"><font color="#ffffff">unittest</font></a>.system_stub</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/unittest/system_stub.py">telemetry/unittest/system_stub.py</a></font></td></tr></table>
+ <p><tt>Provides&nbsp;stubs&nbsp;for&nbsp;os,&nbsp;sys&nbsp;and&nbsp;subprocess&nbsp;for&nbsp;testing<br>
+&nbsp;<br>
+This&nbsp;test&nbsp;allows&nbsp;one&nbsp;to&nbsp;test&nbsp;code&nbsp;that&nbsp;itself&nbsp;uses&nbsp;os,&nbsp;sys,&nbsp;and&nbsp;subprocess.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top><a href="re.html">re</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td><td width="25%" valign=top><a href="shlex.html">shlex</a><br>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.unittest.system_stub.html#AdbCommandsModuleStub">AdbCommandsModuleStub</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.unittest.system_stub.html#OsModuleStub">OsModuleStub</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.unittest.system_stub.html#Override">Override</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.unittest.system_stub.html#SubprocessModuleStub">SubprocessModuleStub</a>
+</font></dt><dt><font face="helvetica, arial"><a href="telemetry.unittest.system_stub.html#SysModuleStub">SysModuleStub</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="AdbCommandsModuleStub">class <strong>AdbCommandsModuleStub</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="AdbCommandsModuleStub-GetAttachedDevices"><strong>GetAttachedDevices</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="AdbCommandsModuleStub-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Static methods defined here:<br>
+<dl><dt><a name="AdbCommandsModuleStub-HasForwarder"><strong>HasForwarder</strong></a>(_<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="AdbCommandsModuleStub-IsAndroidSupported"><strong>IsAndroidSupported</strong></a>()</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>AdbCommandsStub</strong> = &lt;class 'telemetry.unittest.system_stub.AdbCommandsStub'&gt;</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="OsModuleStub">class <strong>OsModuleStub</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="OsModuleStub-__init__"><strong>__init__</strong></a>(self, sys_module<font color="#909090">=&lt;module 'sys' (built-in)&gt;</font>)</dt></dl>
+
+<dl><dt><a name="OsModuleStub-getenv"><strong>getenv</strong></a>(self, name)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>OsPathModuleStub</strong> = &lt;class 'telemetry.unittest.system_stub.OsPathModuleStub'&gt;</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="Override">class <strong>Override</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="Override-Restore"><strong>Restore</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Override-__del__"><strong>__del__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="Override-__init__"><strong>__init__</strong></a>(self, base_module, module_list)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="SubprocessModuleStub">class <strong>SubprocessModuleStub</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="SubprocessModuleStub-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="SubprocessModuleStub-call"><strong>call</strong></a>(self, *args, **kwargs)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes defined here:<br>
+<dl><dt><strong>PopenStub</strong> = &lt;class 'telemetry.unittest.system_stub.PopenStub'&gt;</dl>
+
+</td></tr></table> <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="SysModuleStub">class <strong>SysModuleStub</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%">Methods defined here:<br>
+<dl><dt><a name="SysModuleStub-__init__"><strong>__init__</strong></a>(self)</dt></dl>
+
+<hr>
+Data descriptors defined here:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/docs/telemetry.unittest.tab_test_case.html b/chromium/tools/telemetry/docs/telemetry.unittest.tab_test_case.html
new file mode 100644
index 00000000000..304dedd87b2
--- /dev/null
+++ b/chromium/tools/telemetry/docs/telemetry.unittest.tab_test_case.html
@@ -0,0 +1,334 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html><head><title>Python: module telemetry.unittest.tab_test_case</title>
+</head><body bgcolor="#f0f0f8">
+
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
+<tr bgcolor="#7799ee">
+<td valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="telemetry.html"><font color="#ffffff">telemetry</font></a>.<a href="telemetry.unittest.html"><font color="#ffffff">unittest</font></a>.tab_test_case</strong></big></big></font></td
+><td align=right valign=bottom
+><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="../telemetry/unittest/tab_test_case.py">telemetry/unittest/tab_test_case.py</a></font></td></tr></table>
+ <p><tt>#&nbsp;Copyright&nbsp;(c)&nbsp;2012&nbsp;The&nbsp;Chromium&nbsp;Authors.&nbsp;All&nbsp;rights&nbsp;reserved.<br>
+#&nbsp;Use&nbsp;of&nbsp;this&nbsp;source&nbsp;code&nbsp;is&nbsp;governed&nbsp;by&nbsp;a&nbsp;BSD-style&nbsp;license&nbsp;that&nbsp;can&nbsp;be<br>
+#&nbsp;found&nbsp;in&nbsp;the&nbsp;LICENSE&nbsp;file.</tt></p>
+<p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#aa55cc">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
+
+<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="telemetry.core.browser_finder.html">telemetry.core.browser_finder</a><br>
+</td><td width="25%" valign=top><a href="telemetry.unittest.options_for_unittests.html">telemetry.unittest.options_for_unittests</a><br>
+</td><td width="25%" valign=top><a href="unittest.html">unittest</a><br>
+</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ee77aa">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
+
+<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl>
+<dt><font face="helvetica, arial"><a href="unittest.case.html#TestCase">unittest.case.TestCase</a>(<a href="__builtin__.html#object">__builtin__.object</a>)
+</font></dt><dd>
+<dl>
+<dt><font face="helvetica, arial"><a href="telemetry.unittest.tab_test_case.html#TabTestCase">TabTestCase</a>
+</font></dt></dl>
+</dd>
+</dl>
+ <p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#ffc8d8">
+<td colspan=3 valign=bottom>&nbsp;<br>
+<font color="#000000" face="helvetica, arial"><a name="TabTestCase">class <strong>TabTestCase</strong></a>(<a href="unittest.case.html#TestCase">unittest.case.TestCase</a>)</font></td></tr>
+
+<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
+<td width="100%"><dl><dt>Method resolution order:</dt>
+<dd><a href="telemetry.unittest.tab_test_case.html#TabTestCase">TabTestCase</a></dd>
+<dd><a href="unittest.case.html#TestCase">unittest.case.TestCase</a></dd>
+<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
+</dl>
+<hr>
+Methods defined here:<br>
+<dl><dt><a name="TabTestCase-CustomizeBrowserOptions"><strong>CustomizeBrowserOptions</strong></a>(self, options)</dt><dd><tt>Override&nbsp;to&nbsp;add&nbsp;test-specific&nbsp;options&nbsp;to&nbsp;the&nbsp;BrowserOptions&nbsp;object</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-__init__"><strong>__init__</strong></a>(self, *args)</dt></dl>
+
+<dl><dt><a name="TabTestCase-setUp"><strong>setUp</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabTestCase-tearDown"><strong>tearDown</strong></a>(self)</dt></dl>
+
+<hr>
+Methods inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><a name="TabTestCase-__call__"><strong>__call__</strong></a>(self, *args, **kwds)</dt></dl>
+
+<dl><dt><a name="TabTestCase-__eq__"><strong>__eq__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="TabTestCase-__hash__"><strong>__hash__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabTestCase-__ne__"><strong>__ne__</strong></a>(self, other)</dt></dl>
+
+<dl><dt><a name="TabTestCase-__repr__"><strong>__repr__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabTestCase-__str__"><strong>__str__</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabTestCase-addCleanup"><strong>addCleanup</strong></a>(self, function, *args, **kwargs)</dt><dd><tt>Add&nbsp;a&nbsp;function,&nbsp;with&nbsp;arguments,&nbsp;to&nbsp;be&nbsp;called&nbsp;when&nbsp;the&nbsp;test&nbsp;is<br>
+completed.&nbsp;Functions&nbsp;added&nbsp;are&nbsp;called&nbsp;on&nbsp;a&nbsp;LIFO&nbsp;basis&nbsp;and&nbsp;are<br>
+called&nbsp;after&nbsp;tearDown&nbsp;on&nbsp;test&nbsp;failure&nbsp;or&nbsp;success.<br>
+&nbsp;<br>
+Cleanup&nbsp;items&nbsp;are&nbsp;called&nbsp;even&nbsp;if&nbsp;setUp&nbsp;fails&nbsp;(unlike&nbsp;tearDown).</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-addTypeEqualityFunc"><strong>addTypeEqualityFunc</strong></a>(self, typeobj, function)</dt><dd><tt>Add&nbsp;a&nbsp;type&nbsp;specific&nbsp;assertEqual&nbsp;style&nbsp;function&nbsp;to&nbsp;compare&nbsp;a&nbsp;type.<br>
+&nbsp;<br>
+This&nbsp;method&nbsp;is&nbsp;for&nbsp;use&nbsp;by&nbsp;<a href="unittest.case.html#TestCase">TestCase</a>&nbsp;subclasses&nbsp;that&nbsp;need&nbsp;to&nbsp;register<br>
+their&nbsp;own&nbsp;type&nbsp;equality&nbsp;functions&nbsp;to&nbsp;provide&nbsp;nicer&nbsp;error&nbsp;messages.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;typeobj:&nbsp;The&nbsp;data&nbsp;type&nbsp;to&nbsp;call&nbsp;this&nbsp;function&nbsp;on&nbsp;when&nbsp;both&nbsp;values<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;are&nbsp;of&nbsp;the&nbsp;same&nbsp;type&nbsp;in&nbsp;<a href="#TabTestCase-assertEqual">assertEqual</a>().<br>
+&nbsp;&nbsp;&nbsp;&nbsp;function:&nbsp;The&nbsp;callable&nbsp;taking&nbsp;two&nbsp;arguments&nbsp;and&nbsp;an&nbsp;optional<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg=&nbsp;argument&nbsp;that&nbsp;raises&nbsp;self.<strong>failureException</strong>&nbsp;with&nbsp;a<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;useful&nbsp;error&nbsp;message&nbsp;when&nbsp;the&nbsp;two&nbsp;arguments&nbsp;are&nbsp;not&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertAlmostEqual"><strong>assertAlmostEqual</strong></a>(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;more&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;two&nbsp;objects&nbsp;compare&nbsp;equal&nbsp;then&nbsp;they&nbsp;will&nbsp;automatically<br>
+compare&nbsp;almost&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertAlmostEquals"><strong>assertAlmostEquals</strong></a> = assertAlmostEqual(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;more&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+If&nbsp;the&nbsp;two&nbsp;objects&nbsp;compare&nbsp;equal&nbsp;then&nbsp;they&nbsp;will&nbsp;automatically<br>
+compare&nbsp;almost&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertDictContainsSubset"><strong>assertDictContainsSubset</strong></a>(self, expected, actual, msg<font color="#909090">=None</font>)</dt><dd><tt>Checks&nbsp;whether&nbsp;actual&nbsp;is&nbsp;a&nbsp;superset&nbsp;of&nbsp;expected.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertDictEqual"><strong>assertDictEqual</strong></a>(self, d1, d2, msg<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="TabTestCase-assertEqual"><strong>assertEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertEquals"><strong>assertEquals</strong></a> = assertEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;unequal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertFalse"><strong>assertFalse</strong></a>(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;false.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertGreater"><strong>assertGreater</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(a&nbsp;&gt;&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertGreaterEqual"><strong>assertGreaterEqual</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(a&nbsp;&gt;=&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertIn"><strong>assertIn</strong></a>(self, member, container, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(a&nbsp;in&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertIs"><strong>assertIs</strong></a>(self, expr1, expr2, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(a&nbsp;is&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertIsInstance"><strong>assertIsInstance</strong></a>(self, obj, cls, msg<font color="#909090">=None</font>)</dt><dd><tt>Same&nbsp;as&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(isinstance(obj,&nbsp;cls)),&nbsp;with&nbsp;a&nbsp;nicer<br>
+default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertIsNone"><strong>assertIsNone</strong></a>(self, obj, msg<font color="#909090">=None</font>)</dt><dd><tt>Same&nbsp;as&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(obj&nbsp;is&nbsp;None),&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertIsNot"><strong>assertIsNot</strong></a>(self, expr1, expr2, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(a&nbsp;is&nbsp;not&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertIsNotNone"><strong>assertIsNotNone</strong></a>(self, obj, msg<font color="#909090">=None</font>)</dt><dd><tt>Included&nbsp;for&nbsp;symmetry&nbsp;with&nbsp;assertIsNone.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertItemsEqual"><strong>assertItemsEqual</strong></a>(self, expected_seq, actual_seq, msg<font color="#909090">=None</font>)</dt><dd><tt>An&nbsp;unordered&nbsp;sequence&nbsp;specific&nbsp;comparison.&nbsp;It&nbsp;asserts&nbsp;that<br>
+actual_seq&nbsp;and&nbsp;expected_seq&nbsp;have&nbsp;the&nbsp;same&nbsp;element&nbsp;counts.<br>
+Equivalent&nbsp;to::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#TabTestCase-assertEqual">assertEqual</a>(Counter(iter(actual_seq)),<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Counter(iter(expected_seq)))<br>
+&nbsp;<br>
+Asserts&nbsp;that&nbsp;each&nbsp;element&nbsp;has&nbsp;the&nbsp;same&nbsp;count&nbsp;in&nbsp;both&nbsp;sequences.<br>
+Example:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;[0,&nbsp;1,&nbsp;1]&nbsp;and&nbsp;[1,&nbsp;0,&nbsp;1]&nbsp;compare&nbsp;equal.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;[0,&nbsp;0,&nbsp;1]&nbsp;and&nbsp;[0,&nbsp;1]&nbsp;compare&nbsp;unequal.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertLess"><strong>assertLess</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(a&nbsp;&lt;&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertLessEqual"><strong>assertLessEqual</strong></a>(self, a, b, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(a&nbsp;&lt;=&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertListEqual"><strong>assertListEqual</strong></a>(self, list1, list2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;list-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;list1:&nbsp;The&nbsp;first&nbsp;list&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;list2:&nbsp;The&nbsp;second&nbsp;list&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertMultiLineEqual"><strong>assertMultiLineEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Assert&nbsp;that&nbsp;two&nbsp;multi-line&nbsp;strings&nbsp;are&nbsp;equal.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertNotAlmostEqual"><strong>assertNotAlmostEqual</strong></a>(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;less&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+Objects&nbsp;that&nbsp;are&nbsp;equal&nbsp;automatically&nbsp;fail.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertNotAlmostEquals"><strong>assertNotAlmostEquals</strong></a> = assertNotAlmostEqual(self, first, second, places<font color="#909090">=None</font>, msg<font color="#909090">=None</font>, delta<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;their<br>
+difference&nbsp;rounded&nbsp;to&nbsp;the&nbsp;given&nbsp;number&nbsp;of&nbsp;decimal&nbsp;places<br>
+(default&nbsp;7)&nbsp;and&nbsp;comparing&nbsp;to&nbsp;zero,&nbsp;or&nbsp;by&nbsp;comparing&nbsp;that&nbsp;the<br>
+between&nbsp;the&nbsp;two&nbsp;objects&nbsp;is&nbsp;less&nbsp;than&nbsp;the&nbsp;given&nbsp;delta.<br>
+&nbsp;<br>
+Note&nbsp;that&nbsp;decimal&nbsp;places&nbsp;(from&nbsp;zero)&nbsp;are&nbsp;usually&nbsp;not&nbsp;the&nbsp;same<br>
+as&nbsp;significant&nbsp;digits&nbsp;(measured&nbsp;from&nbsp;the&nbsp;most&nbsp;signficant&nbsp;digit).<br>
+&nbsp;<br>
+Objects&nbsp;that&nbsp;are&nbsp;equal&nbsp;automatically&nbsp;fail.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertNotEqual"><strong>assertNotEqual</strong></a>(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertNotEquals"><strong>assertNotEquals</strong></a> = assertNotEqual(self, first, second, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;if&nbsp;the&nbsp;two&nbsp;objects&nbsp;are&nbsp;equal&nbsp;as&nbsp;determined&nbsp;by&nbsp;the&nbsp;'=='<br>
+operator.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertNotIn"><strong>assertNotIn</strong></a>(self, member, container, msg<font color="#909090">=None</font>)</dt><dd><tt>Just&nbsp;like&nbsp;<a href="#TabTestCase-assertTrue">assertTrue</a>(a&nbsp;not&nbsp;in&nbsp;b),&nbsp;but&nbsp;with&nbsp;a&nbsp;nicer&nbsp;default&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertNotIsInstance"><strong>assertNotIsInstance</strong></a>(self, obj, cls, msg<font color="#909090">=None</font>)</dt><dd><tt>Included&nbsp;for&nbsp;symmetry&nbsp;with&nbsp;assertIsInstance.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertNotRegexpMatches"><strong>assertNotRegexpMatches</strong></a>(self, text, unexpected_regexp, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;the&nbsp;test&nbsp;if&nbsp;the&nbsp;text&nbsp;matches&nbsp;the&nbsp;regular&nbsp;expression.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertRaises"><strong>assertRaises</strong></a>(self, excClass, callableObj<font color="#909090">=None</font>, *args, **kwargs)</dt><dd><tt>Fail&nbsp;unless&nbsp;an&nbsp;exception&nbsp;of&nbsp;class&nbsp;excClass&nbsp;is&nbsp;thrown<br>
+by&nbsp;callableObj&nbsp;when&nbsp;invoked&nbsp;with&nbsp;arguments&nbsp;args&nbsp;and&nbsp;keyword<br>
+arguments&nbsp;kwargs.&nbsp;If&nbsp;a&nbsp;different&nbsp;type&nbsp;of&nbsp;exception&nbsp;is<br>
+thrown,&nbsp;it&nbsp;will&nbsp;not&nbsp;be&nbsp;caught,&nbsp;and&nbsp;the&nbsp;test&nbsp;case&nbsp;will&nbsp;be<br>
+deemed&nbsp;to&nbsp;have&nbsp;suffered&nbsp;an&nbsp;error,&nbsp;exactly&nbsp;as&nbsp;for&nbsp;an<br>
+unexpected&nbsp;exception.<br>
+&nbsp;<br>
+If&nbsp;called&nbsp;with&nbsp;callableObj&nbsp;omitted&nbsp;or&nbsp;None,&nbsp;will&nbsp;return&nbsp;a<br>
+context&nbsp;object&nbsp;used&nbsp;like&nbsp;this::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;<a href="#TabTestCase-assertRaises">assertRaises</a>(SomeException):<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_something()<br>
+&nbsp;<br>
+The&nbsp;context&nbsp;manager&nbsp;keeps&nbsp;a&nbsp;reference&nbsp;to&nbsp;the&nbsp;exception&nbsp;as<br>
+the&nbsp;'exception'&nbsp;attribute.&nbsp;This&nbsp;allows&nbsp;you&nbsp;to&nbsp;inspect&nbsp;the<br>
+exception&nbsp;after&nbsp;the&nbsp;assertion::<br>
+&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;<a href="#TabTestCase-assertRaises">assertRaises</a>(SomeException)&nbsp;as&nbsp;cm:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do_something()<br>
+&nbsp;&nbsp;&nbsp;&nbsp;the_exception&nbsp;=&nbsp;cm.exception<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#TabTestCase-assertEqual">assertEqual</a>(the_exception.error_code,&nbsp;3)</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertRaisesRegexp"><strong>assertRaisesRegexp</strong></a>(self, expected_exception, expected_regexp, callable_obj<font color="#909090">=None</font>, *args, **kwargs)</dt><dd><tt>Asserts&nbsp;that&nbsp;the&nbsp;message&nbsp;in&nbsp;a&nbsp;raised&nbsp;exception&nbsp;matches&nbsp;a&nbsp;regexp.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;expected_exception:&nbsp;Exception&nbsp;class&nbsp;expected&nbsp;to&nbsp;be&nbsp;raised.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;expected_regexp:&nbsp;Regexp&nbsp;(re&nbsp;pattern&nbsp;object&nbsp;or&nbsp;string)&nbsp;expected<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;be&nbsp;found&nbsp;in&nbsp;error&nbsp;message.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;callable_obj:&nbsp;Function&nbsp;to&nbsp;be&nbsp;called.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;args:&nbsp;Extra&nbsp;args.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;kwargs:&nbsp;Extra&nbsp;kwargs.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertRegexpMatches"><strong>assertRegexpMatches</strong></a>(self, text, expected_regexp, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;the&nbsp;test&nbsp;unless&nbsp;the&nbsp;text&nbsp;matches&nbsp;the&nbsp;regular&nbsp;expression.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertSequenceEqual"><strong>assertSequenceEqual</strong></a>(self, seq1, seq2, msg<font color="#909090">=None</font>, seq_type<font color="#909090">=None</font>)</dt><dd><tt>An&nbsp;equality&nbsp;assertion&nbsp;for&nbsp;ordered&nbsp;sequences&nbsp;(like&nbsp;lists&nbsp;and&nbsp;tuples).<br>
+&nbsp;<br>
+For&nbsp;the&nbsp;purposes&nbsp;of&nbsp;this&nbsp;function,&nbsp;a&nbsp;valid&nbsp;ordered&nbsp;sequence&nbsp;type&nbsp;is&nbsp;one<br>
+which&nbsp;can&nbsp;be&nbsp;indexed,&nbsp;has&nbsp;a&nbsp;length,&nbsp;and&nbsp;has&nbsp;an&nbsp;equality&nbsp;operator.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq1:&nbsp;The&nbsp;first&nbsp;sequence&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq2:&nbsp;The&nbsp;second&nbsp;sequence&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;seq_type:&nbsp;The&nbsp;expected&nbsp;datatype&nbsp;of&nbsp;the&nbsp;sequences,&nbsp;or&nbsp;None&nbsp;if&nbsp;no<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;datatype&nbsp;should&nbsp;be&nbsp;enforced.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertSetEqual"><strong>assertSetEqual</strong></a>(self, set1, set2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;set-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;set1:&nbsp;The&nbsp;first&nbsp;set&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;set2:&nbsp;The&nbsp;second&nbsp;set&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.<br>
+&nbsp;<br>
+assertSetEqual&nbsp;uses&nbsp;ducktyping&nbsp;to&nbsp;support&nbsp;different&nbsp;types&nbsp;of&nbsp;sets,&nbsp;and<br>
+is&nbsp;optimized&nbsp;for&nbsp;sets&nbsp;specifically&nbsp;(parameters&nbsp;must&nbsp;support&nbsp;a<br>
+difference&nbsp;method).</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertTrue"><strong>assertTrue</strong></a>(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;true.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assertTupleEqual"><strong>assertTupleEqual</strong></a>(self, tuple1, tuple2, msg<font color="#909090">=None</font>)</dt><dd><tt>A&nbsp;tuple-specific&nbsp;equality&nbsp;assertion.<br>
+&nbsp;<br>
+Args:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tuple1:&nbsp;The&nbsp;first&nbsp;tuple&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;tuple2:&nbsp;The&nbsp;second&nbsp;tuple&nbsp;to&nbsp;compare.<br>
+&nbsp;&nbsp;&nbsp;&nbsp;msg:&nbsp;Optional&nbsp;message&nbsp;to&nbsp;use&nbsp;on&nbsp;failure&nbsp;instead&nbsp;of&nbsp;a&nbsp;list&nbsp;of<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;differences.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-assert_"><strong>assert_</strong></a> = assertTrue(self, expr, msg<font color="#909090">=None</font>)</dt><dd><tt>Check&nbsp;that&nbsp;the&nbsp;expression&nbsp;is&nbsp;true.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-countTestCases"><strong>countTestCases</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabTestCase-debug"><strong>debug</strong></a>(self)</dt><dd><tt>Run&nbsp;the&nbsp;test&nbsp;without&nbsp;collecting&nbsp;errors&nbsp;in&nbsp;a&nbsp;TestResult</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-defaultTestResult"><strong>defaultTestResult</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabTestCase-doCleanups"><strong>doCleanups</strong></a>(self)</dt><dd><tt>Execute&nbsp;all&nbsp;cleanup&nbsp;functions.&nbsp;Normally&nbsp;called&nbsp;for&nbsp;you&nbsp;after<br>
+tearDown.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-fail"><strong>fail</strong></a>(self, msg<font color="#909090">=None</font>)</dt><dd><tt>Fail&nbsp;immediately,&nbsp;with&nbsp;the&nbsp;given&nbsp;message.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-failIf"><strong>failIf</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="TabTestCase-failIfAlmostEqual"><strong>failIfAlmostEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="TabTestCase-failIfEqual"><strong>failIfEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="TabTestCase-failUnless"><strong>failUnless</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="TabTestCase-failUnlessAlmostEqual"><strong>failUnlessAlmostEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="TabTestCase-failUnlessEqual"><strong>failUnlessEqual</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="TabTestCase-failUnlessRaises"><strong>failUnlessRaises</strong></a> = deprecated_func(*args, **kwargs)</dt></dl>
+
+<dl><dt><a name="TabTestCase-id"><strong>id</strong></a>(self)</dt></dl>
+
+<dl><dt><a name="TabTestCase-run"><strong>run</strong></a>(self, result<font color="#909090">=None</font>)</dt></dl>
+
+<dl><dt><a name="TabTestCase-shortDescription"><strong>shortDescription</strong></a>(self)</dt><dd><tt>Returns&nbsp;a&nbsp;one-line&nbsp;description&nbsp;of&nbsp;the&nbsp;test,&nbsp;or&nbsp;None&nbsp;if&nbsp;no<br>
+description&nbsp;has&nbsp;been&nbsp;provided.<br>
+&nbsp;<br>
+The&nbsp;default&nbsp;implementation&nbsp;of&nbsp;this&nbsp;method&nbsp;returns&nbsp;the&nbsp;first&nbsp;line&nbsp;of<br>
+the&nbsp;specified&nbsp;test&nbsp;method's&nbsp;docstring.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-skipTest"><strong>skipTest</strong></a>(self, reason)</dt><dd><tt>Skip&nbsp;this&nbsp;test.</tt></dd></dl>
+
+<hr>
+Class methods inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><a name="TabTestCase-setUpClass"><strong>setUpClass</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;setting&nbsp;up&nbsp;class&nbsp;fixture&nbsp;before&nbsp;running&nbsp;tests&nbsp;in&nbsp;the&nbsp;class.</tt></dd></dl>
+
+<dl><dt><a name="TabTestCase-tearDownClass"><strong>tearDownClass</strong></a>(cls)<font color="#909090"><font face="helvetica, arial"> from <a href="__builtin__.html#type">__builtin__.type</a></font></font></dt><dd><tt>Hook&nbsp;method&nbsp;for&nbsp;deconstructing&nbsp;the&nbsp;class&nbsp;fixture&nbsp;after&nbsp;running&nbsp;all&nbsp;tests&nbsp;in&nbsp;the&nbsp;class.</tt></dd></dl>
+
+<hr>
+Data descriptors inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><strong>__dict__</strong></dt>
+<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<dl><dt><strong>__weakref__</strong></dt>
+<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
+</dl>
+<hr>
+Data and other attributes inherited from <a href="unittest.case.html#TestCase">unittest.case.TestCase</a>:<br>
+<dl><dt><strong>failureException</strong> = &lt;type 'exceptions.AssertionError'&gt;<dd><tt>Assertion&nbsp;failed.</tt></dl>
+
+<dl><dt><strong>longMessage</strong> = False</dl>
+
+<dl><dt><strong>maxDiff</strong> = 640</dl>
+
+</td></tr></table></td></tr></table>
+</body></html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/examples/credentials_example.json b/chromium/tools/telemetry/examples/credentials_example.json
new file mode 100644
index 00000000000..c7c53c5da8d
--- /dev/null
+++ b/chromium/tools/telemetry/examples/credentials_example.json
@@ -0,0 +1,10 @@
+{
+ "google": {
+ "username": "<your google account here>",
+ "password": "<your google password here>"
+ }
+ "facebook": {
+ "username": "<your google account here>",
+ "password": "<your google password here>"
+ }
+}
diff --git a/chromium/tools/telemetry/examples/list_available_browsers b/chromium/tools/telemetry/examples/list_available_browsers
new file mode 100755
index 00000000000..58056fafdb3
--- /dev/null
+++ b/chromium/tools/telemetry/examples/list_available_browsers
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+from telemetry.core import browser_options
+
+def Main(args):
+ options = browser_options.BrowserOptions()
+ options.browser_type = 'list';
+ parser = options.CreateParser('list_available_browsers')
+ parser.parse_args()
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
diff --git a/chromium/tools/telemetry/examples/telemetry_perf_test.py b/chromium/tools/telemetry/examples/telemetry_perf_test.py
new file mode 100755
index 00000000000..14f20cc2579
--- /dev/null
+++ b/chromium/tools/telemetry/examples/telemetry_perf_test.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+import time
+
+sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
+
+from telemetry.core import browser_finder
+from telemetry.core import browser_options
+
+def Main(args):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser('telemetry_perf_test.py')
+ options, args = parser.parse_args(args)
+
+ browser_to_create = browser_finder.FindBrowser(options)
+ assert browser_to_create
+ with browser_to_create.Create() as b:
+ tab = b.tabs[0]
+
+ # Measure round-trip-time for evaluate
+ times = []
+ for i in range(1000):
+ start = time.time()
+ tab.EvaluateJavaScript('%i * 2' % i)
+ times.append(time.time() - start)
+ N = float(len(times))
+ avg = sum(times, 0.0) / N
+ squared_diffs = [(t - avg) * (t - avg) for t in times]
+ stdev = sum(squared_diffs, 0.0) / (N - 1)
+ times.sort()
+ percentile_75 = times[int(0.75 * N)]
+
+ print "%s: avg=%f; stdev=%f; min=%f; 75th percentile = %f" % (
+ "Round trip time (seconds)",
+ avg, stdev, min(times), percentile_75)
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
diff --git a/chromium/tools/telemetry/examples/top1k b/chromium/tools/telemetry/examples/top1k
new file mode 100644
index 00000000000..f32a38cc4e7
--- /dev/null
+++ b/chromium/tools/telemetry/examples/top1k
@@ -0,0 +1,999 @@
+youtube.com
+wikipedia.org
+live.com
+twitter.com
+baidu.com
+qq.com
+amazon.com
+blogspot.com
+yahoo.com
+linkedin.com
+taobao.com
+yahoo.co.jp
+sina.com.cn
+msn.com
+wordpress.com
+yandex.ru
+babylon.com
+ebay.com
+bing.com
+163.com
+weibo.com
+microsoft.com
+soso.com
+mail.ru
+tumblr.com
+vk.com
+sohu.com
+t.co
+craigslist.org
+apple.com
+pinterest.com
+paypal.com
+ask.com
+bbc.co.uk
+blogger.com
+avg.com
+xhamster.com
+imdb.com
+xvideos.com
+fc2.com
+tudou.com
+youku.com
+livejasmin.com
+flickr.com
+go.com
+ifeng.com
+conduit.com
+tmall.com
+zedo.com
+aol.com
+hao123.com
+odnoklassniki.ru
+pornhub.com
+cnn.com
+blogspot.in
+ebay.de
+adobe.com
+rakuten.co.jp
+mywebsearch.com
+huffingtonpost.com
+alibaba.com
+about.com
+thepiratebay.se
+chinaz.com
+amazon.de
+mediafire.com
+sogou.com
+360buy.com
+ebay.co.uk
+ameblo.jp
+espn.go.com
+godaddy.com
+uol.com.br
+adf.ly
+netflix.com
+alipay.com
+redtube.com
+london2012.org
+4shared.com
+amazon.co.jp
+stackoverflow.com
+doubleclick.com
+imgur.com
+youporn.com
+globo.com
+livedoor.com
+wordpress.org
+bp.blogspot.com
+instagram.com
+dailymotion.com
+wigetmedia.com
+cnet.com
+searchnu.com
+zeekrewards.com
+nytimes.com
+renren.com
+amazon.co.uk
+douban.com
+weather.com
+search-results.com
+adcash.com
+livejournal.com
+xnxx.com
+dailymail.co.uk
+torrentz.eu
+tianya.cn
+cnzz.com
+bankofamerica.com
+ehow.com
+badoo.com
+tube8.com
+vimeo.com
+deviantart.com
+addthis.com
+mozilla.org
+indiatimes.com
+reddit.com
+secureserver.net
+booking.com
+aweber.com
+goo.ne.jp
+pconline.com.cn
+warriorforum.com
+spiegel.de
+incredibar.com
+clicksor.com
+4dsply.com
+360.cn
+stumbleupon.com
+chase.com
+56.com
+dropbox.com
+blogfa.com
+kat.ph
+answers.com
+pengyou.com
+outbrain.com
+wikia.com
+softonic.com
+yieldmanager.com
+sourceforge.net
+walmart.com
+photobucket.com
+comcast.net
+foxnews.com
+amazonaws.com
+onet.pl
+naver.com
+58.com
+wellsfargo.com
+guardian.co.uk
+wikimedia.org
+fbcdn.net
+xunlei.com
+skype.com
+myspace.com
+salesforce.com
+etsy.com
+depositfiles.com
+justbeenpaid.com
+liveinternet.ru
+statcounter.com
+mgid.com
+iqiyi.com
+adultfriendfinder.com
+bild.de
+filestube.com
+allegro.pl
+rapidshare.com
+reference.com
+fiverr.com
+rediff.com
+download.com
+optmd.com
+domaintools.com
+xinhuanet.com
+squidoo.com
+ucoz.ru
+leboncoin.fr
+zol.com.cn
+youjizz.com
+yelp.com
+slideshare.net
+free.fr
+files.wordpress.com
+hootsuite.com
+people.com.cn
+scribd.com
+archive.org
+nicovideo.jp
+cntv.cn
+themeforest.net
+taringa.net
+cam4.com
+yesky.com
+wsj.com
+csdn.net
+isohunt.com
+imageshack.us
+digg.com
+soku.com
+orange.fr
+w3schools.com
+tripadvisor.com
+soundcloud.com
+it168.com
+ameba.jp
+sweetim.com
+tagged.com
+telegraph.co.uk
+web.de
+hostgator.com
+4399.com
+indeed.com
+xing.com
+rambler.ru
+wp.pl
+reuters.com
+nbcolympics.com
+gmx.net
+pof.com
+samsung.com
+funmoods.com
+ku6.com
+ilivid.com
+blogspot.com.es
+angege.com
+libero.it
+ikea.com
+forbes.com
+hardsextube.com
+kaixin001.com
+ups.com
+ero-advertising.com
+china.com
+hatena.ne.jp
+mashable.com
+hp.com
+aizhan.com
+hudong.com
+9gag.com
+media.tumblr.com
+youdao.com
+adserverplus.com
+php.net
+y8.com
+bitauto.com
+clickbank.com
+espncricinfo.com
+soufun.com
+rutracker.org
+mercadolivre.com.br
+flipkart.com
+target.com
+linkwithin.com
+terra.com.br
+amazon.cn
+wordreference.com
+kakaku.com
+paipai.com
+narod.ru
+twimg.com
+thefreedictionary.com
+getfirebug.com
+kaskus.co.id
+drtuber.com
+weebly.com
+zimbio.com
+typepad.com
+xcar.com.cn
+akamaihd.net
+goal.com
+pandora.com
+milliyet.com.tr
+ezinearticles.com
+groupon.com
+cj.com
+iminent.com
+putlocker.com
+xe.com
+agoda.com
+github.com
+rapidgator.net
+mop.com
+hulu.com
+2345.com
+hurriyet.com.tr
+washingtonpost.com
+maktoob.com
+ganji.com
+dell.com
+ebay.com.au
+blogspot.jp
+daum.net
+mixi.jp
+dianxin.cn
+infusionsoft.com
+homeway.com.cn
+hubpages.com
+aliexpress.com
+ig.com.br
+dianping.com
+tribalfusion.com
+match.com
+leo.org
+ebay.it
+blogspot.de
+gazeta.pl
+mlb.com
+usps.com
+constantcontact.com
+t-online.de
+alimama.com
+uimserv.net
+shutterstock.com
+businessinsider.com
+uploaded.to
+bet365.com
+battle.net
+bestbuy.com
+letv.com
+51.la
+usatoday.com
+foxsports.com
+twoo.com
+abcnews.go.com
+americanexpress.com
+pptv.com
+seznam.cz
+att.com
+in.com
+mycalendarbook.com
+kooora.com
+51job.com
+elpais.com
+admin5.com
+digitalpoint.com
+movie2k.to
+autohome.com.cn
+analyrics.com
+mpnrs.com
+repubblica.it
+varzesh3.com
+webs.com
+yourlust.com
+detik.com
+126.com
+seesaa.net
+marca.com
+gutefrage.net
+nifty.com
+extratorrent.com
+freelancer.com
+huanqiu.com
+expedia.com
+joomla.org
+mailchimp.com
+nih.gov
+zanox.com
+pch.com
+chinanews.com
+2ch.net
+adultadworld.com
+letitbit.net
+pchome.net
+ign.com
+popads.net
+elmundo.es
+10086.cn
+blogspot.mx
+amazon.fr
+vnexpress.net
+latimes.com
+nbcnews.com
+histats.com
+w3.org
+naukri.com
+ebay.fr
+istockphoto.com
+wretch.cc
+youm7.com
+techcrunch.com
+bluehost.com
+nuvid.com
+over-blog.com
+orkut.com
+imesh.com
+twitpic.com
+peyvandha.ir
+jobrapido.com
+arpg2.com
+mihanblog.com
+fedex.com
+ning.com
+bloomberg.com
+bleacherreport.com
+speedtest.net
+yandex.ua
+turbobit.net
+wikihow.com
+tmz.com
+gsmarena.com
+drudgereport.com
+pcauto.com.cn
+1channel.ch
+39.net
+twcczhu.com
+siteadvisor.com
+nasa.gov
+linkbucks.com
+capitalone.com
+multiply.com
+sakura.ne.jp
+jiayuan.com
+hypergames.net
+seomoz.org
+dmm.co.jp
+engadget.com
+rbc.ru
+chip.de
+verizonwireless.com
+avito.ru
+hdfcbank.com
+114so.cn
+rr.com
+irctc.co.in
+warriorplus.com
+enet.com.cn
+meetup.com
+ebay.in
+empowernetwork.com
+jimdo.com
+monster.com
+commentcamarche.net
+beeg.com
+biglobe.ne.jp
+orkut.com.br
+lemonde.fr
+odesk.com
+ask.fm
+dangdang.com
+kijiji.ca
+189.cn
+bravotube.net
+vancl.com
+cnblogs.com
+informer.com
+zillow.com
+fotolia.com
+mynet.com
+etao.com
+goodreads.com
+blogspot.it
+777wyx.com
+wix.com
+naver.jp
+sinaimg.cn
+ovh.net
+21cn.com
+surveymonkey.com
+spankwire.com
+tabelog.com
+mapquest.com
+ndtv.com
+linkbucksmedia.com
+sape.ru
+buzzfeed.com
+miniclip.com
+corriere.it
+lenta.ru
+shaadi.com
+website-unavailable.com
+viadeo.com
+pclady.com.cn
+xda-developers.com
+zing.vn
+softpedia.com
+itau.com.br
+bitly.com
+abril.com.br
+thesun.co.uk
+sahibinden.com
+neobux.com
+lzjl.com
+51.com
+weather.com.cn
+icbc.com.cn
+people.com
+lefigaro.fr
+qunar.com
+webmd.com
+delicious.com
+exoclick.com
+livedoor.biz
+java.com
+microsoftonline.com
+yomiuri.co.jp
+immobilienscout24.de
+shopathome.com
+drupal.org
+eastmoney.com
+keezmovies.com
+virgilio.it
+zhaopin.com
+blackhatworld.com
+mobile.de
+blog.163.com
+myfreecams.com
+newegg.com
+115.com
+accuweather.com
+homedepot.com
+zynga.com
+netlog.com
+lequipe.fr
+msn.com.cn
+cnr.cn
+hupu.com
+ibm.com
+gotomeeting.com
+slutload.com
+icicibank.com
+persianblog.ir
+livestrong.com
+mercadolibre.com.ar
+ya.ru
+news.com.au
+123rf.com
+duowan.com
+alphaporno.com
+888.com
+xtube.com
+taleo.net
+wetter.com
+gc.ca
+jxliu.com
+tradedoubler.com
+pornhublive.com
+pogo.com
+wunderground.com
+hotels.com
+retailmenot.com
+mercadolibre.com.mx
+oneindia.in
+backpage.com
+steampowered.com
+feedburner.com
+nikkei.com
+gi-akademie.com
+livingsocial.com
+largeporntube.com
+webmoney.ru
+masrawy.com
+zwaar.net
+clixsense.com
+disney.go.com
+outlook.com
+gmw.cn
+heise.de
+cbsnews.com
+allrecipes.com
+classifiedsgiant.com
+xyxy.net
+swagbucks.com
+7k7k.com
+imagebam.com
+sponichi.co.jp
+examiner.com
+ancestry.com
+www.net.cn
+mybrowserbar.com
+searchqu.com
+nokia.com
+hotfile.com
+yihaodian.com
+nu.nl
+nhk.or.jp
+gi-backoffice.com
+altervista.org
+careerbuilder.com
+r7.com
+pcgames.com.cn
+macys.com
+exblog.jp
+porn.com
+myegy.com
+tinypic.com
+issuu.com
+porntube.com
+adscale.de
+so-net.ne.jp
+kinopoisk.ru
+priceline.com
+excite.co.jp
+oracle.com
+verizon.com
+jquery.com
+snapdeal.com
+quibids.com
+focus.cn
+yellowpages.com
+way2sms.com
+okwave.jp
+ustream.tv
+verycd.com
+china.com.cn
+interia.pl
+fatakat.com
+asahi.com
+justdial.com
+quikr.com
+folha.uol.com.br
+who.is
+nydailynews.com
+trulia.com
+okcupid.com
+imagevenue.com
+nba.com
+tabnak.ir
+force.com
+manta.com
+bitshare.com
+inbox.com
+aili.com
+lady8844.com
+mp3skull.com
+payza.com
+stackexchange.com
+suning.com
+marketwatch.com
+blekko.com
+elance.com
+shareasale.com
+custhelp.com
+sapo.pt
+yoka.com
+olx.in
+sitesell.com
+bodybuilding.com
+haberturk.com
+discuz.net
+blog.com
+timeanddate.com
+habrahabr.ru
+iteye.com
+baixing.com
+filehippo.com
+pixnet.net
+wiktionary.org
+getresponse.com
+ccb.com
+mangareader.net
+ocn.ne.jp
+time.com
+kickstarter.com
+hi5.com
+infolinks.com
+v9.com
+coupons.com
+moneycontrol.com
+quora.com
+cloob.com
+jumbofiles.com
+friv.com
+wired.com
+adjuggler.net
+sulekha.com
+qidian.com
+freakshare.com
+cheshi.com.cn
+bannersbroker.com
+searchengines.ru
+alarabiya.net
+templatemonster.com
+metacafe.com
+cnbc.com
+cocolog-nifty.com
+welt.de
+japanpost.jp
+watchseries.eu
+onlylady.com
+gap.com
+pixiv.net
+list-manage.com
+alot.com
+gamespot.com
+52pk.net
+118114.cn
+amung.us
+as.com
+hc360.com
+tnaflix.com
+skyrock.com
+h2porn.com
+blogimg.jp
+blackberry.com
+cbslocal.com
+babycenter.com
+nikkeibp.co.jp
+facenama.com
+whitepages.com
+sears.com
+seowhy.com
+kayak.com
+kompas.com
+dict.cc
+codecanyon.net
+ctrip.com
+pornerbros.com
+zippyshare.com
+tutsplus.com
+userapi.com
+zendesk.com
+am10.ru
+focus.de
+kdnet.net
+1und1.de
+geocities.jp
+4tube.com
+indianrail.gov.in
+dantri.com.vn
+bigpoint.com
+18schoolgirlz.com
+ca.gov
+linksynergy.com
+aftonbladet.se
+tubegalore.com
+partypoker.com
+klikbca.com
+idnes.cz
+video-one.com
+24h.com.vn
+justin.tv
+usbank.com
+tataindicom.com
+xtendmedia.com
+lifehacker.com
+urbandictionary.com
+namecheap.com
+chinabyte.com
+motherless.com
+southwest.com
+blogspot.com.ar
+cmbchina.com
+gismeteo.ru
+slickdeals.net
+logsoku.com
+adult-empire.com
+makeuseof.com
+businessweek.com
+mbc.net
+howstuffworks.com
+orf.at
+mtime.com
+telegraaf.nl
+pagesjaunes.fr
+roulettebotplus.com
+exposedwebcams.com
+onlinesbi.com
+kohls.com
+rottentomatoes.com
+dh818.com
+demonoid.me
+barnesandnoble.com
+dmoz.org
+sanook.com
+ucoz.com
+woot.com
+hubspot.com
+intuit.com
+td.com
+gumtree.com
+hsbc.co.uk
+nikkansports.com
+smh.com.au
+bhaskar.com
+marktplaats.nl
+bahn.de
+tom.com
+panet.co.il
+overstock.com
+enterfactory.com
+rakuten.ne.jp
+pcworld.com
+nordstrom.com
+traidnt.net
+acesse.com
+akhbarak.net
+citibank.com
+foodnetwork.com
+gamefaqs.com
+fotostrana.ru
+nextag.com
+mercadolibre.com.ve
+zappos.com
+eastday.com
+jabong.com
+anonym.to
+foursquare.com
+rightmove.co.uk
+softlayer.com
+tenpay.com
+rednet.cn
+nudevista.com
+televisionfanatic.com
+sueddeutsche.de
+hidemyass.com
+cbssports.com
+meituan.com
+discoverbing.com
+cnbeta.com
+rtl.de
+nike.com
+alexa.com
+doorblog.jp
+goo.gl
+allocine.fr
+meilishuo.com
+national-lottery.co.uk
+ahram.org.eg
+solidtrustpay.com
+dpreview.com
+babytree.com
+yxlady.com
+120ask.com
+sanspo.com
+citrixonline.com
+realtor.com
+lowes.com
+video-lyrics.com
+18andabused.com
+admagnet.net
+novinky.cz
+musica.com
+asos.com
+menepe.com
+bartarinha.ir
+yandex.kz
+subito.it
+19lou.com
+eventbrite.com
+alnaddy.com
+klout.com
+yiqifa.com
+yfrog.com
+gizmodo.com
+cracked.com
+posterous.com
+tinyurl.com
+subscene.com
+sfr.fr
+xvideoslive.com
+linternaute.com
+bbc.com
+eyny.com
+smashingmagazine.com
+clickbank.net
+6.cn
+aeriagames.com
+legacy.com
+glispa.com
+npr.org
+impress.co.jp
+beemp3.com
+aljazeera.net
+magentocommerce.com
+51cto.com
+bearshare.net
+farsnews.com
+perfectgirls.net
+auto.ru
+empflix.com
+liveleak.com
+vente-privee.com
+allabout.co.jp
+qq937.com
+ziddu.com
+patch.com
+att.net
+last.fm
+ixxx.com
+zoho.com
+thechive.com
+skysports.com
+android.com
+logmein.com
+subscribe.ru
+zeekler.com
+icontact.com
+earthlink.net
+itmedia.co.jp
+udn.com
+mysql.com
+rt.com
+semrush.com
+17173.com
+onlinedown.net
+meteofrance.com
+trafficholder.com
+qip.ru
+filecrop.com
+marketgid.com
+speedbit.com
+sdo.com
+xbox.com
+europa.eu
+caixa.gov.br
+gamer.com.tw
+zhubajie.com
+4chan.org
+chinabroadcast.cn
+ninemsn.com.au
+cloudfront.net
+ebay.ca
+worldstarhiphop.com
+ppstream.com
+lacaixa.es
+mediaset.it
+dyndns.org
+kuxun.cn
+yobt.com
+freeones.com
+jugem.jp
+flippa.com
+mail.com
+delta.com
+boston.com
+slando.ru
+servads.com
+extremetube.com
+filefactory.com
+tuenti.com
+noaa.gov
+commbank.com.au
+correios.com.br
+piriform.com
+theplanet.com
+blogspot.com.au
+dreamstime.com
+united.com
+mydomainadvisor.com
+bidorbuy.co.za
+liveperson.net
+opera.com
+weather.gov
+craigslist.ca
+radikal.ru
+avast.com
+disqus.com
+nationalgeographic.com
+sky.com
+idealo.de
+quickmeme.com
+nipic.com
+sfgate.com
+sergey-mavrodi.com
+gazzetta.it
+sunporno.com
+ultimatepowerprofits.com
+docin.com
+tf1.fr
+skycn.com
+dtiblog.com
+accountonline.com
+meetcheap.com
+macrumors.com
+opensiteexplorer.org
+nuomi.com
+m-w.com
+laredoute.fr
+lenovo.com
+pornoxo.com
+brothersoft.com
+ticketmaster.com
+eluniversal.com.mx
+mbank.com.pl
+costco.com
+fixya.com
+docstoc.com
+cy-pr.com
+biblegateway.com
+sockshare.com
+usmagazine.com
+makemytrip.com
+jalan.net
+youtube-mp3.org
+uwavou.com
+weblio.jp
+jeuxvideo.com
+nfl.com
+independent.co.uk
+msn.ca
+easyhits4u.com
+ria.ru
+staples.com
+inetgiant.com
+behance.net
+ebay.es
+sendspace.com
diff --git a/chromium/tools/telemetry/run_tests b/chromium/tools/telemetry/run_tests
new file mode 100755
index 00000000000..6b4bd535b84
--- /dev/null
+++ b/chromium/tools/telemetry/run_tests
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+from telemetry.unittest import gtest_testrunner
+from telemetry.unittest import run_tests
+
+if __name__ == '__main__':
+ top_level_dir = os.path.abspath(os.path.dirname(__file__))
+ runner = gtest_testrunner.GTestTestRunner(print_result_after_run=False)
+ start_dir = 'telemetry'
+ ret = run_tests.Main(sys.argv[1:], start_dir, top_level_dir, runner)
+
+ if runner.result:
+ runner.result.PrintSummary()
+ sys.exit(min(ret + runner.result.num_errors, 255))
+ else:
+ sys.exit(ret)
diff --git a/chromium/tools/telemetry/support/html_output/results-template.html b/chromium/tools/telemetry/support/html_output/results-template.html
new file mode 100644
index 00000000000..c6f2317001e
--- /dev/null
+++ b/chromium/tools/telemetry/support/html_output/results-template.html
@@ -0,0 +1,598 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Telemetry Performance Test Results</title>
+<style type="text/css">
+
+section {
+ background: white;
+ padding: 10px;
+ position: relative;
+}
+
+.time-plots {
+ padding-left: 25px;
+}
+
+.time-plots > div {
+ display: inline-block;
+ width: 90px;
+ height: 40px;
+ margin-right: 10px;
+}
+
+section h1 {
+ text-align: center;
+ font-size: 1em;
+}
+
+section .tooltip {
+ position: absolute;
+ text-align: center;
+ background: #ffcc66;
+ border-radius: 5px;
+ padding: 0px 5px;
+}
+
+body {
+ padding: 0px;
+ margin: 0px;
+ font-family: sans-serif;
+}
+
+table {
+ background: white;
+ width: 100%;
+}
+
+table, td, th {
+ border-collapse: collapse;
+ padding: 5px;
+ white-space: nowrap;
+}
+
+tr.even {
+ background: #f6f6f6;
+}
+
+table td {
+ position: relative;
+ font-family: monospace;
+}
+
+th, td {
+ cursor: pointer;
+ cursor: hand;
+}
+
+th {
+ background: #e6eeee;
+ background: -webkit-gradient(linear, left top, left bottom, from(rgb(244, 244, 244)), to(rgb(217, 217, 217)));
+ border: 1px solid #ccc;
+}
+
+th:after {
+ content: ' \25B8';
+}
+
+th.headerSortUp:after {
+ content: ' \25BE';
+}
+
+th.headerSortDown:after {
+ content: ' \25B4';
+}
+
+td.comparison, td.result {
+ text-align: right;
+}
+
+td.better {
+ color: #6c6;
+}
+
+td.worse {
+ color: #c66;
+}
+
+td.missing {
+ text-align: center;
+}
+
+.checkbox {
+ display: inline-block;
+ background: #eee;
+ background: -webkit-gradient(linear, left bottom, left top, from(rgb(220, 220, 220)), to(rgb(200, 200, 200)));
+ border: inset 1px #ddd;
+ border-radius: 5px;
+ margin: 10px;
+ font-size: small;
+ cursor: pointer;
+ cursor: hand;
+ -webkit-user-select: none;
+ font-weight: bold;
+}
+
+.checkbox span {
+ display: inline-block;
+ line-height: 100%;
+ padding: 5px 8px;
+ border: outset 1px transparent;
+}
+
+.checkbox .checked {
+ background: #e6eeee;
+ background: -webkit-gradient(linear, left top, left bottom, from(rgb(255, 255, 255)), to(rgb(235, 235, 235)));
+ border: outset 1px #eee;
+ border-radius: 5px;
+}
+
+</style>
+</head>
+<body onload="init()">
+<div style="padding: 0 10px; white-space: nowrap;">
+Result <span id="time-memory" class="checkbox"><span class="checked">Time</span><span>Memory</span></span>
+Reference <span id="reference" class="checkbox"></span>
+Run Telemetry with --reset-html-results to clear all runs
+</div>
+<table id="container"></table>
+<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
+<script>
+%plugins%
+</script>
+<script>
+function TestResult(metric, values, associatedRun) {
+ if (values[0] instanceof Array) {
+ var flattenedValues = [];
+ for (var i = 0; i < values.length; i++)
+ flattenedValues = flattenedValues.concat(values[i]);
+ values = flattenedValues;
+ }
+
+ this.test = function () { return metric; }
+ this.values = function () { return values.map(function (value) { return metric.scalingFactor() * value; }); }
+ this.unscaledMean = function () { return Statistics.sum(values) / values.length; }
+ this.mean = function () { return metric.scalingFactor() * this.unscaledMean(); }
+ this.min = function () { return metric.scalingFactor() * Statistics.min(values); }
+ this.max = function () { return metric.scalingFactor() * Statistics.max(values); }
+ this.confidenceIntervalDelta = function () {
+ return metric.scalingFactor() * Statistics.confidenceIntervalDelta(0.95, values.length,
+ Statistics.sum(values), Statistics.squareSum(values));
+ }
+ this.confidenceIntervalDeltaRatio = function () { return this.confidenceIntervalDelta() / this.mean(); }
+ this.percentDifference = function(other) { return (other.unscaledMean() - this.unscaledMean()) / this.unscaledMean(); }
+ this.isStatisticallySignificant = function (other) {
+ var diff = Math.abs(other.mean() - this.mean());
+ return diff > this.confidenceIntervalDelta() && diff > other.confidenceIntervalDelta();
+ }
+ this.run = function () { return associatedRun; }
+}
+
+function TestRun(entry) {
+ this.description = function () { return entry['description']; }
+ this.revision = function () { return entry['revision']; }
+ this.label = function () {
+ var label = 'r' + this.revision();
+ if (this.description())
+ label += ' &dash; ' + this.description();
+ return label;
+ }
+}
+
+function PerfTestMetric(name, metric, unit, isImportant) {
+ var testResults = [];
+ var cachedUnit = null;
+ var cachedScalingFactor = null;
+
+ // We can't do this in TestResult because all results for each test need to share the same unit and the same scaling factor.
+ function computeScalingFactorIfNeeded() {
+ // FIXME: We shouldn't be adjusting units on every test result.
+ // We can only do this on the first test.
+ if (!testResults.length || cachedUnit)
+ return;
+
+ var mean = testResults[0].unscaledMean(); // FIXME: We should look at all values.
+ var kilo = unit == 'bytes' ? 1024 : 1000;
+ if (mean > 10 * kilo * kilo && unit != 'ms') {
+ cachedScalingFactor = 1 / kilo / kilo;
+ cachedUnit = 'M ' + unit;
+ } else if (mean > 10 * kilo) {
+ cachedScalingFactor = 1 / kilo;
+ cachedUnit = unit == 'ms' ? 's' : ('K ' + unit);
+ } else {
+ cachedScalingFactor = 1;
+ cachedUnit = unit;
+ }
+ }
+
+ this.name = function () { return name + ':' + metric; }
+ this.isImportant = isImportant;
+ this.isMemoryTest = function () {
+ return (unit == 'kb' ||
+ unit == 'KB' ||
+ unit == 'MB' ||
+ unit == 'bytes' ||
+ unit == 'count' ||
+ !metric.indexOf('V8.'));
+ }
+ this.addResult = function (newResult) {
+ testResults.push(newResult);
+ cachedUnit = null;
+ cachedScalingFactor = null;
+ }
+ this.results = function () { return testResults; }
+ this.scalingFactor = function() {
+ computeScalingFactorIfNeeded();
+ return cachedScalingFactor;
+ }
+ this.unit = function () {
+ computeScalingFactorIfNeeded();
+ return cachedUnit;
+ }
+ this.biggerIsBetter = function () {
+ if (window.unitToBiggerIsBetter == undefined) {
+ window.unitToBiggerIsBetter = {};
+ var units = JSON.parse(document.getElementById('units-json').textContent);
+ for (var unit in units) {
+ if (units[unit].improvement_direction == 'up') {
+ window.unitToBiggerIsBetter[unit] = true;
+ }
+ }
+ }
+ return window.unitToBiggerIsBetter[unit];
+ }
+}
+
+var plotColor = 'rgb(230,50,50)';
+var subpointsPlotOptions = {
+ lines: {show:true, lineWidth: 0},
+ color: plotColor,
+ points: {show: true, radius: 1},
+ bars: {show: false}};
+
+var mainPlotOptions = {
+ xaxis: {
+ min: -0.5,
+ tickSize: 1,
+ },
+ crosshair: { mode: 'y' },
+ series: { shadowSize: 0 },
+ bars: {show: true, align: 'center', barWidth: 0.5},
+ lines: { show: false },
+ points: { show: true },
+ grid: {
+ borderWidth: 1,
+ borderColor: '#ccc',
+ backgroundColor: '#fff',
+ hoverable: true,
+ autoHighlight: false,
+ }
+};
+
+var timePlotOptions = {
+ yaxis: { show: false },
+ xaxis: { show: false },
+ lines: { show: true },
+ grid: { borderWidth: 1, borderColor: '#ccc' },
+ colors: [ plotColor ]
+};
+
+function createPlot(container, test) {
+ var section = $('<section><div class="plot"></div><div class="time-plots"></div>'
+ + '<span class="tooltip"></span></section>');
+ section.children('.plot').css({'width': (100 * test.results().length + 25) + 'px', 'height': '300px'});
+ $(container).append(section);
+
+ var plotContainer = section.children('.plot');
+ var minIsZero = true;
+ attachPlot(test, plotContainer, minIsZero);
+
+ attachTimePlots(test, section.children('.time-plots'));
+
+ var tooltip = section.children('.tooltip');
+ plotContainer.bind('plothover', function (event, position, item) {
+ if (item) {
+ var postfix = item.series.id ? ' (' + item.series.id + ')' : '';
+ tooltip.html(item.datapoint[1].toPrecision(4) + postfix);
+ var sectionOffset = $(section).offset();
+ tooltip.css({left: item.pageX - sectionOffset.left - tooltip.outerWidth() / 2, top: item.pageY - sectionOffset.top + 10});
+ tooltip.fadeIn(200);
+ } else
+ tooltip.hide();
+ });
+ plotContainer.mouseout(function () {
+ tooltip.hide();
+ });
+ plotContainer.click(function (event) {
+ event.preventDefault();
+ minIsZero = !minIsZero;
+ attachPlot(test, plotContainer, minIsZero);
+ });
+
+ return section;
+}
+
+function attachTimePlots(test, container) {
+ var results = test.results();
+ var attachedPlot = false;
+ for (var i = 0; i < results.length; i++) {
+ container.append('<div></div>');
+ var values = results[i].values();
+ if (!values)
+ continue;
+ attachedPlot = true;
+
+ $.plot(container.children().last(), [values.map(function (value, index) { return [index, value]; })],
+ $.extend(true, {}, timePlotOptions, {yaxis: {min: Math.min.apply(Math, values) * 0.9, max: Math.max.apply(Math, values) * 1.1},
+ xaxis: {min: -0.5, max: values.length - 0.5}}));
+ }
+ if (!attachedPlot)
+ container.children().remove();
+}
+
+function attachPlot(test, plotContainer, minIsZero) {
+ var results = test.results();
+
+ var values = results.reduce(function (values, result, index) {
+ var newValues = result.values();
+ return newValues ? values.concat(newValues.map(function (value) { return [index, value]; })) : values;
+ }, []);
+
+ var plotData = [$.extend(true, {}, subpointsPlotOptions, {data: values})];
+ plotData.push({id: '&mu;', data: results.map(function (result, index) { return [index, result.mean()]; }), color: plotColor});
+
+ var overallMax = Statistics.max(results.map(function (result, index) { return result.max(); }));
+ var overallMin = Statistics.min(results.map(function (result, index) { return result.min(); }));
+ var margin = (overallMax - overallMin) * 0.1;
+ var currentPlotOptions = $.extend(true, {}, mainPlotOptions, {yaxis: {
+ min: minIsZero ? 0 : overallMin - margin,
+ max: minIsZero ? overallMax * 1.1 : overallMax + margin}});
+
+ currentPlotOptions.xaxis.max = results.length - 0.5;
+ currentPlotOptions.xaxis.ticks = results.map(function (result, index) { return [index, result.run().label()]; });
+
+ $.plot(plotContainer, plotData, currentPlotOptions);
+}
+
+function toFixedWidthPrecision(value) {
+ var decimal = value.toFixed(2);
+ return decimal;
+}
+
+function formatPercentage(fraction) {
+ var percentage = fraction * 100;
+ return (fraction * 100).toFixed(2) + '%';
+}
+
+function createTable(tests, runs, shouldIgnoreMemory, referenceIndex) {
+ $('#container').html('<thead><tr><th>Test</th><th>Unit</th>' + runs.map(function (run, index) {
+ return '<th colspan="' + (index == referenceIndex ? 2 : 3) + '" class="{sorter: \'comparison\'}">' + run.label() + '</th>';
+ }).reduce(function (markup, cell) { return markup + cell; }, '') + '</tr></head><tbody></tbody>');
+
+ var testNames = [];
+ for (testName in tests)
+ testNames.push(testName);
+
+ testNames.sort().map(function (testName) {
+ var test = tests[testName];
+ if (test.isMemoryTest() != shouldIgnoreMemory)
+ createTableRow(runs, test, referenceIndex);
+ });
+
+ $('#container').tablesorter({widgets: ['zebra']});
+}
+
+function linearRegression(points) {
+ // Implement http://www.easycalculation.com/statistics/learn-correlation.php.
+ // x = magnitude
+ // y = iterations
+ var sumX = 0;
+ var sumY = 0;
+ var sumXSquared = 0;
+ var sumYSquared = 0;
+ var sumXTimesY = 0;
+
+ for (var i = 0; i < points.length; i++) {
+ var x = i;
+ var y = points[i];
+ sumX += x;
+ sumY += y;
+ sumXSquared += x * x;
+ sumYSquared += y * y;
+ sumXTimesY += x * y;
+ }
+
+ var r = (points.length * sumXTimesY - sumX * sumY) /
+ Math.sqrt((points.length * sumXSquared - sumX * sumX) *
+ (points.length * sumYSquared - sumY * sumY));
+
+ if (isNaN(r) || r == Math.Infinity)
+ r = 0;
+
+ var slope = (points.length * sumXTimesY - sumX * sumY) / (points.length * sumXSquared - sumX * sumX);
+ var intercept = sumY / points.length - slope * sumX / points.length;
+ return {slope: slope, intercept: intercept, rSquared: r * r};
+}
+
+var warningSign = '<svg viewBox="0 0 100 100" style="width: 18px; height: 18px; vertical-align: bottom;" version="1.1">'
+ + '<polygon fill="red" points="50,10 90,80 10,80 50,10" stroke="red" stroke-width="10" stroke-linejoin="round" />'
+ + '<polygon fill="white" points="47,30 48,29, 50, 28.7, 52,29 53,30 50,60" stroke="white" stroke-width="10" stroke-linejoin="round" />'
+ + '<circle cx="50" cy="73" r="6" fill="white" />'
+ + '</svg>';
+
+function createTableRow(runs, test, referenceIndex) {
+ var tableRow = $('<tr><td class="test"' + (test.isImportant ? ' style="font-weight:bold"' : '') + '>' + test.name() + '</td><td class="unit">' + test.unit() + '</td></tr>');
+
+ function markupForRun(result, referenceResult) {
+ var comparisonCell = '';
+ var hiddenValue = '';
+ var shouldCompare = result !== referenceResult;
+ if (shouldCompare && referenceResult) {
+ var percentDifference = referenceResult.percentDifference(result);
+ var better = test.biggerIsBetter() ? percentDifference > 0 : percentDifference < 0;
+ var comparison = '';
+ var className = 'comparison';
+ if (referenceResult.isStatisticallySignificant(result)) {
+ comparison = formatPercentage(Math.abs(percentDifference)) + (better ? ' Better' : ' Worse&nbsp;');
+ className += better ? ' better' : ' worse';
+ }
+ hiddenValue = '<span style="display: none">|' + comparison + '</span>';
+ comparisonCell = '<td class="' + className + '">' + comparison + '</td>';
+ } else if (shouldCompare)
+ comparisonCell = '<td class="comparison"></td>';
+
+ var values = result.values();
+ var warning = '';
+ var regressionAnalysis = '';
+ if (values && values.length > 3) {
+ regressionResult = linearRegression(values);
+ regressionAnalysis = 'slope=' + toFixedWidthPrecision(regressionResult.slope)
+ + ', R^2=' + toFixedWidthPrecision(regressionResult.rSquared);
+ if (regressionResult.rSquared > 0.6 && Math.abs(regressionResult.slope) > 0.01) {
+ warning = ' <span class="regression-warning" title="Detected a time dependency with ' + regressionAnalysis + '">' + warningSign + ' </span>';
+ }
+ }
+
+ var statistics = '&sigma;=' + toFixedWidthPrecision(result.confidenceIntervalDelta()) + ', min=' + toFixedWidthPrecision(result.min())
+ + ', max=' + toFixedWidthPrecision(result.max()) + '\n' + regressionAnalysis;
+
+ // Tablesorter doesn't know about the second cell so put the comparison in the invisible element.
+ return '<td class="result" title="' + statistics + '">' + toFixedWidthPrecision(result.mean()) + hiddenValue
+ + '</td><td class="confidenceIntervalDelta" title="' + statistics + '">&plusmn; '
+ + formatPercentage(result.confidenceIntervalDeltaRatio()) + warning + '</td>' + comparisonCell;
+ }
+
+ function markupForMissingRun(isReference) {
+ return '<td colspan="' + (isReference ? 2 : 3) + '" class="missing">Missing</td>';
+ }
+
+ var runIndex = 0;
+ var results = test.results();
+ var referenceResult = undefined;
+ var resultIndexMap = {};
+ for (var i = 0; i < results.length; i++) {
+ while (runs[runIndex] !== results[i].run())
+ runIndex++;
+ if (runIndex == referenceIndex)
+ referenceResult = results[i];
+ resultIndexMap[runIndex] = i;
+ }
+ for (var i = 0; i < runs.length; i++) {
+ var resultIndex = resultIndexMap[i];
+ if (resultIndex == undefined)
+ tableRow.append(markupForMissingRun(i == referenceIndex));
+ else
+ tableRow.append(markupForRun(results[resultIndex], referenceResult));
+ }
+
+ $('#container').children('tbody').last().append(tableRow);
+
+ function toggle() {
+ var firstCell = tableRow.children('td').first();
+ if (firstCell.children('section').length) {
+ firstCell.children('section').remove();
+ tableRow.children('td').css({'padding-bottom': ''});
+ } else {
+ var plot = createPlot(firstCell, test);
+ plot.css({'position': 'absolute', 'z-index': 2});
+ var offset = tableRow.offset();
+ offset.left += 1;
+ offset.top += tableRow.outerHeight();
+ plot.offset(offset);
+ tableRow.children('td').css({'padding-bottom': plot.outerHeight() + 5});
+ }
+
+ return false;
+ };
+
+ tableRow.click(function(event) {
+ if (event.target != tableRow[0] && event.target.parentNode != tableRow[0])
+ return;
+
+ event.preventDefault();
+
+ toggle();
+ });
+
+ if (test.isImportant) {
+ toggle();
+ }
+}
+
+function init() {
+ $.tablesorter.addParser({
+ id: 'comparison',
+ is: function(s) {
+ return s.indexOf('|') >= 0;
+ },
+ format: function(s) {
+ var parsed = parseFloat(s.substring(s.indexOf('|') + 1));
+ return isNaN(parsed) ? 0 : parsed;
+ },
+ type: 'numeric',
+ });
+
+ var runs = [];
+ var metrics = {};
+ $.each(JSON.parse(document.getElementById('results-json').textContent), function (index, entry) {
+ var run = new TestRun(entry);
+ runs.push(run);
+
+ function addTests(tests, parentFullName) {
+ for (var testName in tests) {
+ var fullTestName = parentFullName + '/' + testName;
+ var rawMetrics = tests[testName].metrics;
+
+ for (var metricName in rawMetrics) {
+ var fullMetricName = fullTestName + ':' + metricName;
+ var metric = metrics[fullMetricName];
+ if (!metric) {
+ metric = new PerfTestMetric(fullTestName, metricName, rawMetrics[metricName].units, rawMetrics[metricName].important);
+ metrics[fullMetricName] = metric;
+ }
+ metric.addResult(new TestResult(metric, rawMetrics[metricName].current, run));
+ }
+
+ if (tests[testName].tests)
+ addTests(tests[testName].tests, fullTestName);
+ }
+ }
+
+ addTests(entry.tests, '');
+ });
+
+ var shouldIgnoreMemory= true;
+ var referenceIndex = 0;
+
+ createTable(metrics, runs, shouldIgnoreMemory, referenceIndex);
+
+ $('#time-memory').bind('change', function (event, checkedElement) {
+ shouldIgnoreMemory = checkedElement.textContent == 'Time';
+ createTable(metrics, runs, shouldIgnoreMemory, referenceIndex);
+ });
+
+ runs.map(function (run, index) {
+ $('#reference').append('<span value="' + index + '"' + (index == referenceIndex ? ' class="checked"' : '') + '>' + run.label() + '</span>');
+ })
+
+ $('#reference').bind('change', function (event, checkedElement) {
+ referenceIndex = parseInt(checkedElement.getAttribute('value'));
+ createTable(metrics, runs, shouldIgnoreMemory, referenceIndex);
+ });
+
+ $('.checkbox').each(function (index, checkbox) {
+ $(checkbox).children('span').click(function (event) {
+ if ($(this).hasClass('checked'))
+ return;
+ $(checkbox).children('span').removeClass('checked');
+ $(this).addClass('checked');
+ $(checkbox).trigger('change', $(this));
+ });
+ });
+}
+
+</script>
+<script id="results-json" type="application/json">%json_results%</script>
+<script id="units-json" type="application/json">%json_units%</script>
+</body>
+</html>
diff --git a/chromium/tools/telemetry/telemetry/__init__.py b/chromium/tools/telemetry/telemetry/__init__.py
new file mode 100644
index 00000000000..db26220329c
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/__init__.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+A library for cross-platform browser tests.
+"""
+import inspect
+import os
+import sys
+
+from telemetry.core.browser import Browser
+from telemetry.core.browser_options import BrowserOptions
+from telemetry.core.tab import Tab
+
+from telemetry.page.page_measurement import PageMeasurement
+from telemetry.page.page_runner import Run as RunPage
+
+__all__ = []
+
+# Find all local vars that are classes or functions and make sure they're in the
+# __all__ array so they're included in docs.
+for x in dir():
+ if x.startswith('_'):
+ continue
+ if x in (inspect, sys):
+ continue
+ m = sys.modules[__name__]
+ if (inspect.isclass(getattr(m, x)) or
+ inspect.isfunction(getattr(m, x))):
+ __all__.append(x)
+
+
+def _RemoveAllStalePycFiles():
+ for dirname, _, filenames in os.walk(os.path.dirname(__file__)):
+ if '.svn' in dirname or '.git' in dirname:
+ continue
+ for filename in filenames:
+ root, ext = os.path.splitext(filename)
+ if ext != '.pyc':
+ continue
+
+ pyc_path = os.path.join(dirname, filename)
+ py_path = os.path.join(dirname, root + '.py')
+ if not os.path.exists(py_path):
+ os.remove(pyc_path)
+
+ if not os.listdir(dirname):
+ os.removedirs(dirname)
+
+
+_RemoveAllStalePycFiles()
diff --git a/chromium/tools/telemetry/telemetry/core/__init__.py b/chromium/tools/telemetry/telemetry/core/__init__.py
new file mode 100644
index 00000000000..96196cffb27
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/__init__.py
@@ -0,0 +1,3 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/telemetry/telemetry/core/backends/__init__.py b/chromium/tools/telemetry/telemetry/core/backends/__init__.py
new file mode 100644
index 00000000000..9228df89b0e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/telemetry/telemetry/core/backends/browser_backend.py b/chromium/tools/telemetry/telemetry/core/backends/browser_backend.py
new file mode 100644
index 00000000000..bb120bd34e8
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/browser_backend.py
@@ -0,0 +1,96 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core import util
+from telemetry.core import web_contents
+
+
+class ExtensionsNotSupportedException(Exception):
+ pass
+
+class BrowserBackend(object):
+ """A base class for browser backends."""
+
+ WEBPAGEREPLAY_HOST = '127.0.0.1'
+
+ def __init__(self, is_content_shell, supports_extensions, options,
+ tab_list_backend):
+ self.browser_type = options.browser_type
+ self.is_content_shell = is_content_shell
+ self._supports_extensions = supports_extensions
+ self.options = options
+ self._browser = None
+ self._tab_list_backend = tab_list_backend(self)
+
+ def AddReplayServerOptions(self, options):
+ pass
+
+ def SetBrowser(self, browser):
+ self._browser = browser
+ self._tab_list_backend.Init()
+
+ @property
+ def browser(self):
+ return self._browser
+
+ @property
+ def supports_extensions(self):
+ """True if this browser backend supports extensions."""
+ return self._supports_extensions
+
+ @property
+ def wpr_mode(self):
+ return self.options.wpr_mode
+
+ @property
+ def supports_tab_control(self):
+ raise NotImplementedError()
+
+ @property
+ def tab_list_backend(self):
+ return self._tab_list_backend
+
+ @property
+ def supports_tracing(self):
+ raise NotImplementedError()
+
+ def StartTracing(self, custom_categories=None,
+ timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT):
+ raise NotImplementedError()
+
+ def StopTracing(self):
+ raise NotImplementedError()
+
+ def GetTraceResultAndReset(self):
+ raise NotImplementedError()
+
+ def GetRemotePort(self, _):
+ return util.GetAvailableLocalPort()
+
+ def Start(self):
+ raise NotImplementedError()
+
+ def CreateForwarder(self, *port_pairs):
+ raise NotImplementedError()
+
+ def IsBrowserRunning(self):
+ raise NotImplementedError()
+
+ def GetStandardOutput(self):
+ raise NotImplementedError()
+
+ def GetStackTrace(self):
+ raise NotImplementedError()
+
+class DoNothingForwarder(object):
+ def __init__(self, *port_pairs):
+ self._host_port = port_pairs[0].local_port
+
+ @property
+ def url(self):
+ assert self._host_port
+ return 'http://127.0.0.1:%i' % self._host_port
+
+ def Close(self):
+ self._host_port = None
diff --git a/chromium/tools/telemetry/telemetry/core/backends/chrome/__init__.py b/chromium/tools/telemetry/telemetry/core/backends/chrome/__init__.py
new file mode 100644
index 00000000000..9228df89b0e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/chrome/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py b/chromium/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py
new file mode 100644
index 00000000000..50ca98b3955
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_backend.py
@@ -0,0 +1,231 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import httplib
+import json
+import re
+import socket
+import sys
+import urllib2
+
+from telemetry.core import exceptions
+from telemetry.core import user_agent
+from telemetry.core import util
+from telemetry.core import web_contents
+from telemetry.core import wpr_modes
+from telemetry.core import wpr_server
+from telemetry.core.backends import browser_backend
+from telemetry.core.chrome import extension_dict_backend
+from telemetry.core.chrome import misc_web_contents_backend
+from telemetry.core.chrome import tab_list_backend
+from telemetry.core.chrome import tracing_backend
+from telemetry.unittest import options_for_unittests
+
+class ChromeBrowserBackend(browser_backend.BrowserBackend):
+ """An abstract class for chrome browser backends. Provides basic functionality
+ once a remote-debugger port has been established."""
+ # It is OK to have abstract methods. pylint: disable=W0223
+
+ def __init__(self, is_content_shell, supports_extensions, options):
+ super(ChromeBrowserBackend, self).__init__(
+ is_content_shell=is_content_shell,
+ supports_extensions=supports_extensions,
+ options=options,
+ tab_list_backend=tab_list_backend.TabListBackend)
+ self._port = None
+
+ self._inspector_protocol_version = 0
+ self._chrome_branch_number = 0
+ self._tracing_backend = None
+
+ self.webpagereplay_local_http_port = util.GetAvailableLocalPort()
+ self.webpagereplay_local_https_port = util.GetAvailableLocalPort()
+ self.webpagereplay_remote_http_port = self.webpagereplay_local_http_port
+ self.webpagereplay_remote_https_port = self.webpagereplay_local_https_port
+
+ if options.dont_override_profile and not options_for_unittests.AreSet():
+ sys.stderr.write('Warning: Not overriding profile. This can cause '
+ 'unexpected effects due to profile-specific settings, '
+ 'such as about:flags settings, cookies, and '
+ 'extensions.\n')
+ self._misc_web_contents_backend = (
+ misc_web_contents_backend.MiscWebContentsBackend(self))
+ self._extension_dict_backend = None
+ if supports_extensions:
+ self._extension_dict_backend = (
+ extension_dict_backend.ExtensionDictBackend(self))
+
+ def AddReplayServerOptions(self, options):
+ options.append('--no-dns_forwarding')
+
+ @property
+ def misc_web_contents_backend(self):
+ """Access to chrome://oobe/login page which is neither a tab nor an
+ extension."""
+ return self._misc_web_contents_backend
+
+ @property
+ def extension_dict_backend(self):
+ return self._extension_dict_backend
+
+ def GetBrowserStartupArgs(self):
+ args = []
+ args.extend(self.options.extra_browser_args)
+ args.append('--disable-background-networking')
+ args.append('--metrics-recording-only')
+ args.append('--no-first-run')
+ if self.options.wpr_mode != wpr_modes.WPR_OFF:
+ args.extend(wpr_server.GetChromeFlags(
+ self.WEBPAGEREPLAY_HOST,
+ self.webpagereplay_remote_http_port,
+ self.webpagereplay_remote_https_port))
+ args.extend(user_agent.GetChromeUserAgentArgumentFromType(
+ self.options.browser_user_agent_type))
+
+ extensions = [extension.local_path for extension in
+ self.options.extensions_to_load if not extension.is_component]
+ extension_str = ','.join(extensions)
+ if len(extensions) > 0:
+ args.append('--load-extension=%s' % extension_str)
+
+ component_extensions = [extension.local_path for extension in
+ self.options.extensions_to_load if extension.is_component]
+ component_extension_str = ','.join(component_extensions)
+ if len(component_extensions) > 0:
+ args.append('--load-component-extension=%s' % component_extension_str)
+
+ if self.options.no_proxy_server:
+ args.append('--no-proxy-server')
+
+ return args
+
+ def _WaitForBrowserToComeUp(self, timeout=None):
+ def IsBrowserUp():
+ try:
+ self.Request('', timeout=timeout)
+ except (exceptions.BrowserGoneException,
+ exceptions.BrowserConnectionGoneException):
+ return False
+ else:
+ return True
+ try:
+ util.WaitFor(IsBrowserUp, timeout=30)
+ except util.TimeoutException:
+ raise exceptions.BrowserGoneException(self.GetStackTrace())
+
+ def AllExtensionsLoaded():
+ # Extension pages are loaded from an about:blank page,
+ # so we need to check that the document URL is the extension
+ # page in addition to the ready state.
+ extension_ready_js = """
+ document.URL.lastIndexOf('chrome-extension://%s/', 0) == 0 &&
+ (document.readyState == 'complete' ||
+ document.readyState == 'interactive')
+ """
+ for e in self.options.extensions_to_load:
+ if not e.extension_id in self._extension_dict_backend:
+ return False
+ extension_object = self._extension_dict_backend[e.extension_id]
+ res = extension_object.EvaluateJavaScript(
+ extension_ready_js % e.extension_id)
+ if not res:
+ return False
+ return True
+ if self._supports_extensions:
+ util.WaitFor(AllExtensionsLoaded, timeout=30)
+
+ def _PostBrowserStartupInitialization(self):
+ # Detect version information.
+ data = self.Request('version')
+ resp = json.loads(data)
+ if 'Protocol-Version' in resp:
+ self._inspector_protocol_version = resp['Protocol-Version']
+
+ if 'Browser' in resp:
+ branch_number_match = re.search('Chrome/\d+\.\d+\.(\d+)\.\d+',
+ resp['Browser'])
+ else:
+ branch_number_match = re.search(
+ 'Chrome/\d+\.\d+\.(\d+)\.\d+ (Mobile )?Safari',
+ resp['User-Agent'])
+
+ if branch_number_match:
+ self._chrome_branch_number = int(branch_number_match.group(1))
+ else:
+ # Content Shell returns '' for Browser, for now we have to
+ # fall-back and assume branch 1025.
+ self._chrome_branch_number = 1025
+ return
+
+ # Detection has failed: assume 18.0.1025.168 ~= Chrome Android.
+ self._inspector_protocol_version = 1.0
+ self._chrome_branch_number = 1025
+
+ def Request(self, path, timeout=None, throw_network_exception=False):
+ url = 'http://localhost:%i/json' % self._port
+ if path:
+ url += '/' + path
+ try:
+ req = urllib2.urlopen(url, timeout=timeout)
+ return req.read()
+ except (socket.error, httplib.BadStatusLine, urllib2.URLError) as e:
+ if throw_network_exception:
+ raise e
+ if not self.IsBrowserRunning():
+ raise exceptions.BrowserGoneException()
+ raise exceptions.BrowserConnectionGoneException()
+
+ @property
+ def browser_directory(self):
+ raise NotImplementedError()
+
+ @property
+ def profile_directory(self):
+ raise NotImplementedError()
+
+ @property
+ def chrome_branch_number(self):
+ return self._chrome_branch_number
+
+ @property
+ def supports_tab_control(self):
+ return self._chrome_branch_number >= 1303
+
+ @property
+ def supports_tracing(self):
+ return self.is_content_shell or self._chrome_branch_number >= 1385
+
+ def StartTracing(self, custom_categories=None,
+ timeout=web_contents.DEFAULT_WEB_CONTENTS_TIMEOUT):
+ """ custom_categories is an optional string containing a list of
+ comma separated categories that will be traced instead of the
+ default category set. Example: use
+ "webkit,cc,disabled-by-default-cc.debug" to trace only those three
+ event categories.
+ """
+ if self._tracing_backend is None:
+ self._tracing_backend = tracing_backend.TracingBackend(self._port)
+ self._tracing_backend.BeginTracing(custom_categories, timeout)
+
+ def StopTracing(self):
+ self._tracing_backend.EndTracing()
+
+ def GetTraceResultAndReset(self):
+ return self._tracing_backend.GetTraceResultAndReset()
+
+ def GetProcessName(self, cmd_line):
+ """Returns a user-friendly name for the process of the given |cmd_line|."""
+ if 'nacl_helper_bootstrap' in cmd_line:
+ return 'nacl_helper_bootstrap'
+ if ':sandboxed_process' in cmd_line:
+ return 'renderer'
+ m = re.match(r'.* --type=([^\s]*) .*', cmd_line)
+ if not m:
+ return 'browser'
+ return m.group(1)
+
+ def Close(self):
+ if self._tracing_backend:
+ self._tracing_backend.Close()
+ self._tracing_backend = None
diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/__init__.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/__init__.py
new file mode 100644
index 00000000000..9228df89b0e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/webdriver/__init__.py
@@ -0,0 +1,3 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_browser_backend.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_browser_backend.py
new file mode 100644
index 00000000000..2eb01f2eb27
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_browser_backend.py
@@ -0,0 +1,70 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core.backends import browser_backend
+from telemetry.core.backends.webdriver import webdriver_tab_list_backend
+
+class WebDriverBrowserBackend(browser_backend.BrowserBackend):
+ """The webdriver-based backend for controlling a locally-executed browser
+ instance, on Linux, Mac, and Windows.
+ """
+
+ def __init__(self, driver_creator, supports_extensions, options):
+ super(WebDriverBrowserBackend, self).__init__(
+ is_content_shell=False,
+ supports_extensions=supports_extensions,
+ options=options,
+ tab_list_backend=webdriver_tab_list_backend.WebDriverTabListBackend)
+
+ self._driver_creator = driver_creator
+ self._driver = None
+ self.webpagereplay_local_http_port = 80
+ self.webpagereplay_local_https_port = 443
+ self.webpagereplay_remote_http_port = self.webpagereplay_local_http_port
+ self.webpagereplay_remote_https_port = self.webpagereplay_local_https_port
+
+ def Start(self):
+ assert not self._driver
+ self._driver = self._driver_creator()
+
+ @property
+ def driver(self):
+ assert self._driver
+ return self._driver
+
+ @property
+ def supports_tab_control(self):
+ # Based on webdriver protocol API, only closing a tab is supported while
+ # activating or creating a tab is not. Thus, tab control is not supported.
+ return False
+
+ @property
+ def supports_tracing(self):
+ # Tracing is not available in IE/Firefox yet and not supported through
+ # webdriver API.
+ return False
+
+ def GetProcessName(self, _):
+ # Leave implementation details to subclass as process name depends on the
+ # type of browser.
+ raise NotImplementedError()
+
+ def Close(self):
+ if self._driver:
+ self._driver.quit()
+ self._driver = None
+
+ def CreateForwarder(self, *port_pairs):
+ return browser_backend.DoNothingForwarder(*port_pairs)
+
+ def IsBrowserRunning(self):
+ # Assume the browser is running if not explicitly closed.
+ return self._driver is not None
+
+ def GetStandardOutput(self):
+ # TODO(chrisgao): check if python client can get stdout of browsers.
+ return ''
+
+ def __del__(self):
+ self.Close()
diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_desktop_browser_finder.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_desktop_browser_finder.py
new file mode 100644
index 00000000000..13c298946ec
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_desktop_browser_finder.py
@@ -0,0 +1,103 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Finds desktop browsers that can be controlled by telemetry."""
+
+import logging
+import os
+import sys
+
+from telemetry.core import browser
+from telemetry.core import possible_browser
+from telemetry.core import platform
+from telemetry.core import util
+from telemetry.core.backends.webdriver import webdriver_browser_backend
+
+# Try to import the selenium python lib which may be not available.
+try:
+ from selenium import webdriver # pylint: disable=F0401
+except ImportError:
+ webdriver = None
+ pylib = os.path.join(util.GetChromiumSrcDir(),
+ 'third_party', 'webdriver', 'pylib')
+ if (os.path.isdir(pylib)):
+ sys.path.insert(0, pylib)
+ try:
+ from selenium import webdriver # pylint: disable=F0401
+ except ImportError:
+ webdriver = None
+
+ALL_BROWSER_TYPES = ''
+if webdriver:
+ ALL_BROWSER_TYPES = ','.join([
+ 'internet-explorer',
+ 'internet-explorer-x64'])
+else:
+ logging.warning('Webdriver backend is unsupported without selenium pylib. '
+ 'For installation of selenium pylib, please refer to '
+ 'https://code.google.com/p/selenium/wiki/PythonBindings.')
+
+
+class PossibleWebDriverBrowser(possible_browser.PossibleBrowser):
+ """A browser that can be controlled through webdriver API."""
+
+ def __init__(self, browser_type, options):
+ super(PossibleWebDriverBrowser, self).__init__(browser_type, options)
+
+ def CreateWebDriverBackend(self):
+ raise NotImplementedError()
+
+ def Create(self):
+ backend = self.CreateWebDriverBackend()
+ b = browser.Browser(backend, platform.CreatePlatformBackendForCurrentOS())
+ return b
+
+ def SupportsOptions(self, options):
+ # TODO(chrisgao): Check if some options are not supported.
+ return True
+
+ @property
+ def last_modification_time(self):
+ return -1
+
+ def SelectDefaultBrowser(self, possible_browsers): # pylint: disable=W0613
+ return None
+
+
+class PossibleDesktopIE(PossibleWebDriverBrowser):
+ def __init__(self, browser_type, options, architecture):
+ super(PossibleDesktopIE, self).__init__(browser_type, options)
+ self._architecture = architecture
+
+ def CreateWebDriverBackend(self):
+ assert webdriver
+ def DriverCreator():
+ # TODO(chrisgao): Check in IEDriverServer.exe and specify path to it when
+ # creating the webdriver instance. crbug.com/266170
+ return webdriver.Ie()
+ return webdriver_browser_backend.WebDriverBrowserBackend(
+ DriverCreator, False, self.options)
+
+
+def FindAllAvailableBrowsers(options):
+ """Finds all the desktop browsers available on this machine."""
+ browsers = []
+ if not webdriver:
+ return browsers
+
+ # Look for the IE browser in the standard location.
+ if sys.platform.startswith('win'):
+ ie_path = os.path.join('Internet Explorer', 'iexplore.exe')
+ win_search_paths = {
+ '32' : { 'path' : os.getenv('PROGRAMFILES(X86)'),
+ 'type' : 'internet-explorer'},
+ '64' : { 'path' : os.getenv('PROGRAMFILES'),
+ 'type' : 'internet-explorer-x64'}}
+ for architecture, ie_info in win_search_paths.iteritems():
+ if not ie_info['path']:
+ continue
+ if os.path.exists(os.path.join(ie_info['path'], ie_path)):
+ browsers.append(
+ PossibleDesktopIE(ie_info['type'], options, architecture))
+
+ return browsers
diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_backend.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_backend.py
new file mode 100644
index 00000000000..df2e7ae62e3
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_backend.py
@@ -0,0 +1,120 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+
+# TODO(chrisgao): Make png_bitmap sharable for both chrome and webdriver.
+from telemetry.core.chrome import png_bitmap
+
+class WebDriverTabBackend(object):
+ def __init__(self, browser_backend, window_handle):
+ self._browser_backend = browser_backend
+ self._window_handle = window_handle
+
+ def Disconnect(self):
+ pass
+
+ @property
+ def browser(self):
+ return self._browser_backend.browser
+
+ @property
+ def window_handle(self):
+ return self._window_handle
+
+ @property
+ def url(self):
+ self._browser_backend.driver.switch_to_window(self._window_handle)
+ return self._browser_backend.driver.current_url
+
+ def Activate(self):
+ # Webdriver doesn't support tab control.
+ raise NotImplementedError()
+
+ def Close(self):
+ self._browser_backend.driver.switch_to_window(self._window_handle)
+ self._browser_backend.driver.close()
+
+ def WaitForDocumentReadyStateToBeComplete(self, timeout=None):
+ # TODO(chrisgao): Double check of document state.
+ pass
+
+ def WaitForDocumentReadyStateToBeInteractiveOrBetter(self, timeout=None):
+ # TODO(chrisgao): Double check of document state.
+ pass
+
+ @property
+ def screenshot_supported(self):
+ return True
+
+ def Screenshot(self, timeout=None): # pylint: disable=W0613
+ if timeout:
+ logging.warning('timeout is not supported')
+ self._browser_backend.driver.switch_to_window(self._window_handle)
+ snap = self._browser_backend.driver.get_screenshot_as_base64()
+ if snap:
+ return png_bitmap.PngBitmap(snap)
+ return None
+
+ @property
+ def message_output_stream(self):
+ # Webdriver has no API for grabbing console messages.
+ raise NotImplementedError()
+
+ @message_output_stream.setter
+ def message_output_stream(self, stream):
+ raise NotImplementedError()
+
+ def GetDOMStats(self, timeout=None):
+ # Webdriver has no API for DOM status.
+ raise NotImplementedError()
+
+ def PerformActionAndWaitForNavigate(self, action_function, _):
+ # TODO(chrisgao): Double check of navigation.
+ action_function()
+
+ def Navigate(self, url, script_to_evaluate_on_commit=None, timeout=None):
+ if script_to_evaluate_on_commit:
+ raise NotImplementedError('script_to_evaluate_on_commit is NOT supported')
+ self._browser_backend.driver.switch_to_window(self._window_handle)
+ if timeout:
+ self._browser_backend.driver.set_page_load_timeout(timeout * 1000)
+ self._browser_backend.driver.get(url)
+
+ def GetCookieByName(self, name, timeout=None):
+ if timeout:
+ logging.warning('timeout is not supported')
+ self._browser_backend.driver.switch_to_window(self._window_handle)
+ cookie = self._browser_backend.driver.get_cookie(name)
+ if cookie:
+ return cookie['value']
+ return None
+
+ def ExecuteJavaScript(self, expr, timeout=None):
+ self._browser_backend.driver.switch_to_window(self._window_handle)
+ if timeout:
+ logging.warning('timeout is not supported')
+ self._browser_backend.driver.execute_script(expr)
+
+ def EvaluateJavaScript(self, expr, timeout=None):
+ self._browser_backend.driver.switch_to_window(self._window_handle)
+ if timeout:
+ logging.warning('timeout is not supported')
+ return self._browser_backend.driver.execute_script(
+ 'return eval(\'%s\')' % expr.replace('\'', '\\\'').replace('\n', ' '))
+
+ @property
+ def timeline_model(self):
+ # IE/Firefox has no timeline.
+ raise NotImplementedError()
+
+ def StartTimelineRecording(self):
+ raise NotImplementedError()
+
+ def StopTimelineRecording(self):
+ raise NotImplementedError()
+
+ def ClearCache(self):
+ # Can't find a way to clear cache of a tab in IE/Firefox.
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_list_backend.py b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_list_backend.py
new file mode 100644
index 00000000000..ea9c8346c4b
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/backends/webdriver/webdriver_tab_list_backend.py
@@ -0,0 +1,47 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core.backends.webdriver import webdriver_tab_backend
+
+class WebDriverTabListBackend(object):
+ def __init__(self, browser_backend):
+ self._browser_backend = browser_backend
+ # Stores the window handles.
+ self._tab_list = []
+
+ def Init(self):
+ self._UpdateTabList()
+
+ def New(self, timeout=None):
+ # Webdriver API doesn't support tab controlling.
+ raise NotImplementedError()
+
+ def __iter__(self):
+ self._UpdateTabList()
+ return self._tab_list.__iter__()
+
+ def __len__(self):
+ self._UpdateTabList()
+ return len(self._tab_list)
+
+ def __getitem__(self, index):
+ self._UpdateTabList()
+ if len(self._tab_list) <= index:
+ raise IndexError('list index out of range')
+ return self._tab_list[index]
+
+ def _UpdateTabList(self):
+ window_handles = self._browser_backend.driver.window_handles
+ old_tab_list = self._tab_list
+ self._tab_list = []
+ for window_handle in window_handles:
+ tab = None
+ for old_tab in old_tab_list:
+ if old_tab.window_handle == window_handle:
+ tab = old_tab
+ break
+ else:
+ tab = webdriver_tab_backend.WebDriverTabBackend(
+ self._browser_backend, window_handle)
+ self._tab_list.append(tab)
diff --git a/chromium/tools/telemetry/telemetry/core/browser.py b/chromium/tools/telemetry/telemetry/core/browser.py
new file mode 100644
index 00000000000..a04b05857b9
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/browser.py
@@ -0,0 +1,319 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+from telemetry.core import browser_credentials
+from telemetry.core import extension_dict
+from telemetry.core import platform
+from telemetry.core import tab_list
+from telemetry.core import temporary_http_server
+from telemetry.core import wpr_modes
+from telemetry.core import wpr_server
+from telemetry.core.backends import browser_backend
+from telemetry.core.platform.profiler import profiler_finder
+
+class Browser(object):
+ """A running browser instance that can be controlled in a limited way.
+
+ To create a browser instance, use browser_finder.FindBrowser.
+
+ Be sure to clean up after yourself by calling Close() when you are done with
+ the browser. Or better yet:
+ browser_to_create = FindBrowser(options)
+ with browser_to_create.Create() as browser:
+ ... do all your operations on browser here
+ """
+ def __init__(self, backend, platform_backend):
+ self._browser_backend = backend
+ self._http_server = None
+ self._wpr_server = None
+ self._platform = platform.Platform(platform_backend)
+ self._platform_backend = platform_backend
+ self._tabs = tab_list.TabList(backend.tab_list_backend)
+ self._extensions = None
+ if backend.supports_extensions:
+ self._extensions = extension_dict.ExtensionDict(
+ backend.extension_dict_backend)
+ self.credentials = browser_credentials.BrowserCredentials()
+ self._platform.SetFullPerformanceModeEnabled(True)
+ self._active_profilers = []
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.Close()
+
+ @property
+ def platform(self):
+ return self._platform
+
+ @property
+ def browser_type(self):
+ return self._browser_backend.browser_type
+
+ @property
+ def is_content_shell(self):
+ """Returns whether this browser is a content shell, only."""
+ return self._browser_backend.is_content_shell
+
+ @property
+ def supports_extensions(self):
+ return self._browser_backend.supports_extensions
+
+ @property
+ def supports_tab_control(self):
+ return self._browser_backend.supports_tab_control
+
+ @property
+ def tabs(self):
+ return self._tabs
+
+ @property
+ def extensions(self):
+ """Returns the extension dictionary if it exists."""
+ if not self.supports_extensions:
+ raise browser_backend.ExtensionsNotSupportedException(
+ 'Extensions not supported')
+ return self._extensions
+
+ @property
+ def supports_tracing(self):
+ return self._browser_backend.supports_tracing
+
+ def is_profiler_active(self, profiler_name):
+ return profiler_name in [profiler.name() for
+ profiler in self._active_profilers]
+
+ def _GetStatsCommon(self, pid_stats_function):
+ browser_pid = self._browser_backend.pid
+ result = {
+ 'Browser': dict(pid_stats_function(browser_pid), **{'ProcessCount': 1}),
+ 'Renderer': {'ProcessCount': 0},
+ 'Gpu': {'ProcessCount': 0}
+ }
+ child_process_count = 0
+ for child_pid in self._platform_backend.GetChildPids(browser_pid):
+ child_process_count += 1
+ # Process type detection is causing exceptions.
+ # http://crbug.com/240951
+ try:
+ child_cmd_line = self._platform_backend.GetCommandLine(child_pid)
+ child_process_name = self._browser_backend.GetProcessName(
+ child_cmd_line)
+ except Exception:
+ # The cmd line was unavailable, assume it'll be impossible to track
+ # any further stats about this process.
+ continue
+ process_name_type_key_map = {'gpu-process': 'Gpu', 'renderer': 'Renderer'}
+ if child_process_name in process_name_type_key_map:
+ child_process_type_key = process_name_type_key_map[child_process_name]
+ else:
+ # TODO: identify other process types (zygote, plugin, etc), instead of
+ # lumping them in with renderer processes.
+ child_process_type_key = 'Renderer'
+ child_stats = pid_stats_function(child_pid)
+ result[child_process_type_key]['ProcessCount'] += 1
+ for k, v in child_stats.iteritems():
+ if k in result[child_process_type_key]:
+ result[child_process_type_key][k] += v
+ else:
+ result[child_process_type_key][k] = v
+ for v in result.itervalues():
+ if v['ProcessCount'] > 1:
+ for k in v.keys():
+ if k.endswith('Peak'):
+ del v[k]
+ del v['ProcessCount']
+ result['ProcessCount'] = child_process_count
+ return result
+
+ @property
+ def memory_stats(self):
+ """Returns a dict of memory statistics for the browser:
+ { 'Browser': {
+ 'VM': S,
+ 'VMPeak': T,
+ 'WorkingSetSize': U,
+ 'WorkingSetSizePeak': V,
+ 'ProportionalSetSize': W,
+ 'PrivateDirty': X
+ },
+ 'Gpu': {
+ 'VM': S,
+ 'VMPeak': T,
+ 'WorkingSetSize': U,
+ 'WorkingSetSizePeak': V,
+ 'ProportionalSetSize': W,
+ 'PrivateDirty': X
+ },
+ 'Renderer': {
+ 'VM': S,
+ 'VMPeak': T,
+ 'WorkingSetSize': U,
+ 'WorkingSetSizePeak': V,
+ 'ProportionalSetSize': W,
+ 'PrivateDirty': X
+ },
+ 'SystemCommitCharge': Y,
+ 'ProcessCount': Z,
+ }
+ Any of the above keys may be missing on a per-platform basis.
+ """
+ result = self._GetStatsCommon(self._platform_backend.GetMemoryStats)
+ result['SystemCommitCharge'] = \
+ self._platform_backend.GetSystemCommitCharge()
+ return result
+
+ @property
+ def io_stats(self):
+ """Returns a dict of IO statistics for the browser:
+ { 'Browser': {
+ 'ReadOperationCount': W,
+ 'WriteOperationCount': X,
+ 'ReadTransferCount': Y,
+ 'WriteTransferCount': Z
+ },
+ 'Gpu': {
+ 'ReadOperationCount': W,
+ 'WriteOperationCount': X,
+ 'ReadTransferCount': Y,
+ 'WriteTransferCount': Z
+ },
+ 'Renderer': {
+ 'ReadOperationCount': W,
+ 'WriteOperationCount': X,
+ 'ReadTransferCount': Y,
+ 'WriteTransferCount': Z
+ }
+ }
+ """
+ result = self._GetStatsCommon(self._platform_backend.GetIOStats)
+ del result['ProcessCount']
+ return result
+
+ def StartProfiling(self, profiler_name, base_output_file):
+ """Starts profiling using |profiler_name|. Results are saved to
+ |base_output_file|.<process_name>."""
+ assert not self._active_profilers, 'Already profiling. Must stop first.'
+
+ profiler_class = profiler_finder.FindProfiler(profiler_name)
+
+ if not profiler_class.is_supported(self._browser_backend.options):
+ raise Exception('The %s profiler is not '
+ 'supported on this platform.' % profiler_name)
+
+ self._active_profilers.append(
+ profiler_class(self._browser_backend, self._platform_backend,
+ base_output_file))
+
+ def StopProfiling(self):
+ """Stops all active profilers and saves their results.
+
+ Returns:
+ A list of filenames produced by the profiler.
+ """
+ output_files = []
+ for profiler in self._active_profilers:
+ output_files.extend(profiler.CollectProfile())
+ self._active_profilers = []
+ return output_files
+
+ def StartTracing(self, custom_categories=None, timeout=10):
+ return self._browser_backend.StartTracing(custom_categories, timeout)
+
+ def StopTracing(self):
+ return self._browser_backend.StopTracing()
+
+ def GetTraceResultAndReset(self):
+ """Returns the result of the trace, as TraceResult object."""
+ return self._browser_backend.GetTraceResultAndReset()
+
+ def Start(self):
+ options = self._browser_backend.options
+ if options.clear_sytem_cache_for_browser_and_profile_on_start:
+ if self._platform.CanFlushIndividualFilesFromSystemCache():
+ self._platform.FlushSystemCacheForDirectory(
+ self._browser_backend.profile_directory)
+ self._platform.FlushSystemCacheForDirectory(
+ self._browser_backend.browser_directory)
+ else:
+ self._platform.FlushEntireSystemCache()
+
+ self._browser_backend.Start()
+ self._browser_backend.SetBrowser(self)
+
+ def Close(self):
+ """Closes this browser."""
+ self._platform.SetFullPerformanceModeEnabled(False)
+ if self._wpr_server:
+ self._wpr_server.Close()
+ self._wpr_server = None
+
+ if self._http_server:
+ self._http_server.Close()
+ self._http_server = None
+
+ self._browser_backend.Close()
+ self.credentials = None
+
+ @property
+ def http_server(self):
+ return self._http_server
+
+ def SetHTTPServerDirectories(self, paths):
+ """Returns True if the HTTP server was started, False otherwise."""
+ if not isinstance(paths, list):
+ paths = [paths]
+ paths = [os.path.abspath(p) for p in paths]
+
+ if paths and self._http_server and self._http_server.paths == paths:
+ return False
+
+ if self._http_server:
+ self._http_server.Close()
+ self._http_server = None
+
+ if not paths:
+ return False
+
+ self._http_server = temporary_http_server.TemporaryHTTPServer(
+ self._browser_backend, paths)
+
+ return True
+
+ def SetReplayArchivePath(self, archive_path, append_to_existing_wpr=False,
+ make_javascript_deterministic=True):
+ if self._wpr_server:
+ self._wpr_server.Close()
+ self._wpr_server = None
+
+ if not archive_path:
+ return None
+
+ if self._browser_backend.wpr_mode == wpr_modes.WPR_OFF:
+ return
+
+ use_record_mode = self._browser_backend.wpr_mode == wpr_modes.WPR_RECORD
+ if not use_record_mode:
+ assert os.path.isfile(archive_path)
+
+ self._wpr_server = wpr_server.ReplayServer(
+ self._browser_backend,
+ archive_path,
+ use_record_mode,
+ append_to_existing_wpr,
+ make_javascript_deterministic,
+ self._browser_backend.WEBPAGEREPLAY_HOST,
+ self._browser_backend.webpagereplay_local_http_port,
+ self._browser_backend.webpagereplay_local_https_port,
+ self._browser_backend.webpagereplay_remote_http_port,
+ self._browser_backend.webpagereplay_remote_https_port)
+
+ def GetStandardOutput(self):
+ return self._browser_backend.GetStandardOutput()
+
+ def GetStackTrace(self):
+ return self._browser_backend.GetStackTrace()
diff --git a/chromium/tools/telemetry/telemetry/core/browser_credentials.py b/chromium/tools/telemetry/telemetry/core/browser_credentials.py
new file mode 100644
index 00000000000..fadeaa1e0a9
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/browser_credentials.py
@@ -0,0 +1,145 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import json
+import os
+
+from telemetry.core.chrome import facebook_credentials_backend
+from telemetry.core.chrome import google_credentials_backend
+from telemetry.unittest import options_for_unittests
+
+class BrowserCredentials(object):
+ def __init__(self, backends = None):
+ self._credentials = {}
+ self._credentials_path = None
+ self._extra_credentials = {}
+
+ if backends is None:
+ backends = [
+ facebook_credentials_backend.FacebookCredentialsBackend(),
+ google_credentials_backend.GoogleCredentialsBackend()]
+
+ self._backends = {}
+ for backend in backends:
+ self._backends[backend.credentials_type] = backend
+
+ def AddBackend(self, backend):
+ assert backend.credentials_type not in self._backends
+ self._backends[backend.credentials_type] = backend
+
+ def IsLoggedIn(self, credentials_type):
+ if credentials_type not in self._backends:
+ raise Exception('Unrecognized credentials type: %s', credentials_type)
+ if credentials_type not in self._credentials:
+ return False
+ return self._backends[credentials_type].IsLoggedIn()
+
+ def CanLogin(self, credentials_type):
+ if credentials_type not in self._backends:
+ raise Exception('Unrecognized credentials type: %s', credentials_type)
+ return credentials_type in self._credentials
+
+ def LoginNeeded(self, tab, credentials_type):
+ if credentials_type not in self._backends:
+ raise Exception('Unrecognized credentials type: %s', credentials_type)
+ if credentials_type not in self._credentials:
+ return False
+ return self._backends[credentials_type].LoginNeeded(
+ tab, self._credentials[credentials_type])
+
+ def LoginNoLongerNeeded(self, tab, credentials_type):
+ assert credentials_type in self._backends
+ self._backends[credentials_type].LoginNoLongerNeeded(tab)
+
+ @property
+ def credentials_path(self):
+ return self._credentials_path
+
+ @credentials_path.setter
+ def credentials_path(self, credentials_path):
+ self._credentials_path = credentials_path
+ self._RebuildCredentials()
+
+ def Add(self, credentials_type, data):
+ if credentials_type not in self._extra_credentials:
+ self._extra_credentials[credentials_type] = {}
+ for k, v in data.items():
+ assert k not in self._extra_credentials[credentials_type]
+ self._extra_credentials[credentials_type][k] = v
+ self._RebuildCredentials()
+
+ def _ResetLoggedInState(self):
+ """Makes the backends think we're not logged in even though we are.
+ Should only be used in unit tests to simulate --dont-override-profile.
+ """
+ for backend in self._backends.keys():
+ self._backends[backend]._ResetLoggedInState() # pylint: disable=W0212
+
+ def _RebuildCredentials(self):
+ credentials = {}
+ if self._credentials_path == None:
+ pass
+ elif os.path.exists(self._credentials_path):
+ with open(self._credentials_path, 'r') as f:
+ credentials = json.loads(f.read())
+
+ # TODO(nduca): use system keychain, if possible.
+ homedir_credentials_path = os.path.expanduser('~/.telemetry-credentials')
+ homedir_credentials = {}
+
+ if (not options_for_unittests.GetCopy() and
+ os.path.exists(homedir_credentials_path)):
+ logging.info("Found ~/.telemetry-credentials. Its contents will be used "
+ "when no other credentials can be found.")
+ with open(homedir_credentials_path, 'r') as f:
+ homedir_credentials = json.loads(f.read())
+
+ self._credentials = {}
+ all_keys = set(credentials.keys()).union(
+ homedir_credentials.keys()).union(
+ self._extra_credentials.keys())
+
+ for k in all_keys:
+ if k in credentials:
+ self._credentials[k] = credentials[k]
+ if k in homedir_credentials:
+ logging.info("Will use ~/.telemetry-credentials for %s logins." % k)
+ self._credentials[k] = homedir_credentials[k]
+ if k in self._extra_credentials:
+ self._credentials[k] = self._extra_credentials[k]
+
+ def WarnIfMissingCredentials(self, page_set):
+ num_pages_missing_login = 0
+ missing_credentials = set()
+ for page in page_set:
+ if (page.credentials
+ and not self.CanLogin(page.credentials)):
+ num_pages_missing_login += 1
+ missing_credentials.add(page.credentials)
+
+ if num_pages_missing_login > 0:
+ files_to_tweak = []
+ if page_set.credentials_path:
+ files_to_tweak.append(
+ os.path.relpath(os.path.join(os.path.dirname(page_set.file_path),
+ page_set.credentials_path)))
+ files_to_tweak.append('~/.telemetry-credentials')
+
+ example_credentials_file = (
+ os.path.relpath(
+ os.path.join(
+ os.path.dirname(__file__),
+ '..', 'examples', 'credentials_example.json')))
+
+ logging.warning("""
+ Credentials for %s were not found. %i pages will not be tested.
+
+ To fix this, either add svn-internal to your .gclient using
+ http://goto/read-src-internal, or add your own credentials to:
+ %s
+ An example credentials file you can copy from is here:
+ %s\n""" % (', '.join(missing_credentials),
+ num_pages_missing_login,
+ ' or '.join(files_to_tweak),
+ example_credentials_file))
diff --git a/chromium/tools/telemetry/telemetry/core/browser_credentials_unittest.py b/chromium/tools/telemetry/telemetry/core/browser_credentials_unittest.py
new file mode 100644
index 00000000000..cd77aed5d73
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/browser_credentials_unittest.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import tempfile
+import unittest
+
+from telemetry.core import browser_credentials
+
+SIMPLE_CREDENTIALS_STRING = """
+{
+ "google": {
+ "username": "example",
+ "password": "asdf"
+ }
+}
+"""
+
+class BackendStub(object):
+ def __init__(self, credentials_type):
+ self.login_needed_called = None
+ self.login_no_longer_needed_called = None
+ self.credentials_type = credentials_type
+
+ def LoginNeeded(self, config, tab):
+ self.login_needed_called = (config, tab)
+ return True
+
+ def LoginNoLongerNeeded(self, tab):
+ self.login_no_longer_needed_called = (tab, )
+
+
+class TestBrowserCredentials(unittest.TestCase):
+ def testCredentialsInfrastructure(self):
+ google_backend = BackendStub("google")
+ othersite_backend = BackendStub("othersite")
+ browser_cred = browser_credentials.BrowserCredentials(
+ [google_backend,
+ othersite_backend])
+ try:
+ with tempfile.NamedTemporaryFile(delete=False) as f:
+ f.write(SIMPLE_CREDENTIALS_STRING)
+
+ browser_cred.credentials_path = f.name
+
+ # Should true because it has a password and a backend.
+ self.assertTrue(browser_cred.CanLogin('google'))
+
+ # Should be false succeed because it has no password.
+ self.assertFalse(browser_cred.CanLogin('othersite'))
+
+ # Should fail because it has no backend.
+ self.assertRaises(
+ Exception,
+ lambda: browser_cred.CanLogin('foobar'))
+
+ tab = {}
+ ret = browser_cred.LoginNeeded(tab, 'google')
+ self.assertTrue(ret)
+ self.assertTrue(google_backend.login_needed_called is not None)
+ self.assertEqual(tab, google_backend.login_needed_called[0])
+ self.assertEqual("example",
+ google_backend.login_needed_called[1]["username"])
+ self.assertEqual("asdf",
+ google_backend.login_needed_called[1]["password"])
+
+ browser_cred.LoginNoLongerNeeded(tab, 'google')
+ self.assertTrue(google_backend.login_no_longer_needed_called is not None)
+ self.assertEqual(tab, google_backend.login_no_longer_needed_called[0])
+ finally:
+ os.remove(f.name)
diff --git a/chromium/tools/telemetry/telemetry/core/browser_finder.py b/chromium/tools/telemetry/telemetry/core/browser_finder.py
new file mode 100644
index 00000000000..0248857fb53
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/browser_finder.py
@@ -0,0 +1,106 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Finds browsers that can be controlled by telemetry."""
+
+import logging
+
+from telemetry.core.backends.webdriver import webdriver_desktop_browser_finder
+from telemetry.core.chrome import android_browser_finder
+from telemetry.core.chrome import cros_browser_finder
+from telemetry.core.chrome import desktop_browser_finder
+
+BROWSER_FINDERS = [
+ desktop_browser_finder,
+ android_browser_finder,
+ cros_browser_finder,
+ webdriver_desktop_browser_finder,
+ ]
+
+ALL_BROWSER_TYPES = ','.join([bf.ALL_BROWSER_TYPES for bf in BROWSER_FINDERS])
+
+
+class BrowserTypeRequiredException(Exception):
+ pass
+
+class BrowserFinderException(Exception):
+ pass
+
+def FindBrowser(options):
+ """Finds the best PossibleBrowser object to run given the provided
+ BrowserOptions object. The returned possiblity object can then be used to
+ connect to and control the located browser. A BrowserFinderException will
+ be raised if the BrowserOptions argument is improperly set or if an error
+ occurs when finding a browser.
+ """
+ if options.browser_type == 'exact' and options.browser_executable == None:
+ raise BrowserFinderException(
+ '--browser=exact requires --browser-executable to be set.')
+ if options.browser_type != 'exact' and options.browser_executable != None:
+ raise BrowserFinderException(
+ '--browser-executable requires --browser=exact.')
+
+ if options.browser_type == 'cros-chrome' and options.cros_remote == None:
+ raise BrowserFinderException(
+ 'browser_type=cros-chrome requires cros_remote be set.')
+ if (options.browser_type != 'cros-chrome' and
+ options.browser_type != 'cros-chrome-guest' and
+ options.cros_remote != None):
+ raise BrowserFinderException(
+ 'cros_remote requires browser_type=cros-chrome or cros-chrome-guest.')
+
+ browsers = []
+ default_browser = None
+ for finder in BROWSER_FINDERS:
+ curr_browsers = finder.FindAllAvailableBrowsers(options)
+ if not default_browser:
+ default_browser = finder.SelectDefaultBrowser(curr_browsers)
+ browsers.extend(curr_browsers)
+
+ if options.browser_type == None:
+ if default_browser:
+ logging.warning('--browser omitted. Using most recent local build: %s' %
+ default_browser.browser_type)
+ options.browser_type = default_browser.browser_type
+ return default_browser
+ raise BrowserTypeRequiredException(
+ '--browser must be specified. Available browsers:\n%s' %
+ '\n'.join(sorted(set([b.browser_type for b in browsers]))))
+
+ if options.browser_type == 'any':
+ types = ALL_BROWSER_TYPES.split(',')
+ def compare_browsers_on_type_priority(x, y):
+ x_idx = types.index(x.browser_type)
+ y_idx = types.index(y.browser_type)
+ return x_idx - y_idx
+ browsers.sort(compare_browsers_on_type_priority)
+ if len(browsers) >= 1:
+ return browsers[0]
+ else:
+ return None
+
+ matching_browsers = [b for b in browsers
+ if b.browser_type == options.browser_type and b.SupportsOptions(options)]
+
+ if len(matching_browsers) == 1:
+ return matching_browsers[0]
+ elif len(matching_browsers) > 1:
+ logging.warning('Multiple browsers of the same type found: %s' % (
+ repr(matching_browsers)))
+ return matching_browsers[0]
+ else:
+ return None
+
+def GetAllAvailableBrowserTypes(options):
+ """Returns an array of browser types supported on this system.
+ A BrowserFinderException will be raised if the BrowserOptions argument is
+ improperly set or if an error occurs when finding a browser.
+ """
+ browsers = []
+ for finder in BROWSER_FINDERS:
+ browsers.extend(finder.FindAllAvailableBrowsers(options))
+
+ type_list = set([browser.browser_type for browser in browsers])
+ type_list = list(type_list)
+ type_list.sort()
+ return type_list
diff --git a/chromium/tools/telemetry/telemetry/core/browser_options.py b/chromium/tools/telemetry/telemetry/core/browser_options.py
new file mode 100644
index 00000000000..70d3c1ff340
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/browser_options.py
@@ -0,0 +1,242 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import logging
+import optparse
+import os
+import shlex
+import sys
+
+from telemetry.core import browser_finder
+from telemetry.core import profile_types
+from telemetry.core import repeat_options
+from telemetry.core import util
+from telemetry.core import wpr_modes
+from telemetry.core.platform.profiler import profiler_finder
+
+class BrowserOptions(optparse.Values):
+ """Options to be used for discovering and launching a browser."""
+
+ def __init__(self, browser_type=None):
+ optparse.Values.__init__(self)
+
+ self.browser_type = browser_type
+ self.browser_executable = None
+ self.chrome_root = None
+ self.android_device = None
+ self.cros_ssh_identity = None
+
+ # When set to True, the browser will use the default profile. Telemetry
+ # will not provide an alternate profile directory.
+ self.dont_override_profile = False
+ self.profile_dir = None
+ self.profile_type = None
+ self.extra_browser_args = []
+ self.extra_wpr_args = []
+ self.show_stdout = False
+ self.extensions_to_load = []
+ self.clear_sytem_cache_for_browser_and_profile_on_start = False
+
+ self.cros_remote = None
+ self.wpr_mode = wpr_modes.WPR_OFF
+
+ self.browser_user_agent_type = None
+
+ self.profiler = None
+ self.verbosity = 0
+
+ self.page_filter = None
+ self.page_filter_exclude = None
+
+ self.no_proxy_server = False
+
+ self.repeat_options = repeat_options.RepeatOptions()
+ self.output_file = None
+ self.skip_navigate_on_repeat = False
+
+ def Copy(self):
+ return copy.deepcopy(self)
+
+ def CreateParser(self, *args, **kwargs):
+ parser = optparse.OptionParser(*args, **kwargs)
+
+ # Selection group
+ group = optparse.OptionGroup(parser, 'Which browser to use')
+ group.add_option('--browser',
+ dest='browser_type',
+ default=None,
+ help='Browser type to run, '
+ 'in order of priority. Supported values: list,%s' %
+ browser_finder.ALL_BROWSER_TYPES)
+ group.add_option('--browser-executable',
+ dest='browser_executable',
+ help='The exact browser to run.')
+ group.add_option('--chrome-root',
+ dest='chrome_root',
+ help='Where to look for chrome builds.'
+ 'Defaults to searching parent dirs by default.')
+ group.add_option('--device',
+ dest='android_device',
+ help='The android device ID to use'
+ 'If not specified, only 0 or 1 connected devcies are supported.')
+ group.add_option('--keep_test_server_ports', action='store_true',
+ help='Indicates the test server ports must be '
+ 'kept. When this is run via a sharder '
+ 'the test server ports should be kept and '
+ 'should not be reset.')
+ group.add_option(
+ '--remote',
+ dest='cros_remote',
+ help='The IP address of a remote ChromeOS device to use.')
+ identity = None
+ testing_rsa = os.path.join(
+ util.GetChromiumSrcDir(),
+ 'third_party', 'chromite', 'ssh_keys', 'testing_rsa')
+ if os.path.exists(testing_rsa):
+ identity = testing_rsa
+ group.add_option('--identity',
+ dest='cros_ssh_identity',
+ default=identity,
+ help='The identity file to use when ssh\'ing into the ChromeOS device')
+ parser.add_option_group(group)
+
+ # Browser options
+ group = optparse.OptionGroup(parser, 'Browser options')
+ profile_choices = profile_types.GetProfileTypes()
+ group.add_option('--profile-type',
+ dest='profile_type',
+ type='choice',
+ default='clean',
+ choices=profile_choices,
+ help=('The user profile to use. A clean profile is used by default. '
+ 'Supported values: ' + ', '.join(profile_choices)))
+ group.add_option('--profile-dir',
+ dest='profile_dir',
+ help='Profile directory to launch the browser with. '
+ 'A clean profile is used by default')
+ group.add_option('--extra-browser-args',
+ dest='extra_browser_args_as_string',
+ help='Additional arguments to pass to the browser when it starts')
+ group.add_option('--extra-wpr-args',
+ dest='extra_wpr_args_as_string',
+ help=('Additional arguments to pass to Web Page Replay. '
+ 'See third_party/webpagereplay/replay.py for usage.'))
+ group.add_option('--show-stdout',
+ action='store_true',
+ help='When possible, will display the stdout of the process')
+ parser.add_option_group(group)
+
+ # Page set options
+ group = optparse.OptionGroup(parser, 'Page set options')
+ group.add_option('--pageset-shuffle', action='store_true',
+ dest='pageset_shuffle',
+ help='Shuffle the order of pages within a pageset.')
+ group.add_option('--pageset-shuffle-order-file',
+ dest='pageset_shuffle_order_file', default=None,
+ help='Filename of an output of a previously run test on the current ' +
+ 'pageset. The tests will run in the same order again, overriding ' +
+ 'what is specified by --page-repeat and --pageset-repeat.')
+ parser.add_option_group(group)
+
+ group = optparse.OptionGroup(parser, 'Web Page Replay options')
+ group.add_option('--allow-live-sites',
+ dest='allow_live_sites', action='store_true',
+ help='Run against live sites if the Web Page Replay archives don\'t '
+ 'exist. Without this flag, the test will just fail instead '
+ 'of running against live sites.')
+ parser.add_option_group(group)
+
+ # Debugging options
+ group = optparse.OptionGroup(parser, 'When things go wrong')
+ profiler_choices = profiler_finder.GetAllAvailableProfilers(None)
+ group.add_option(
+ '--profiler', default=None, type='choice',
+ choices=profiler_choices,
+ help=('Record profiling data using this tool. Supported values: ' +
+ ', '.join(profiler_choices)))
+ group.add_option(
+ '-v', '--verbose', action='count', dest='verbosity',
+ help='Increase verbosity level (repeat as needed)')
+ group.add_option('--print-bootstrap-deps',
+ action='store_true',
+ help='Output bootstrap deps list.')
+ parser.add_option_group(group)
+
+ # Platform options
+ group = optparse.OptionGroup(parser, 'Platform options')
+ group.add_option('--no-performance-mode', action='store_true',
+ help='Some platforms run on "full performance mode" where the '
+ 'test is executed at maximum CPU speed in order to minimize noise '
+ '(specially important for dashboards / continuous builds). '
+ 'This option prevents Telemetry from tweaking such platform settings.')
+ parser.add_option_group(group)
+
+ # Repeat options
+ repeat_options.RepeatOptions.AddCommandLineOptions(parser)
+
+ real_parse = parser.parse_args
+ def ParseArgs(args=None):
+ defaults = parser.get_default_values()
+ for k, v in defaults.__dict__.items():
+ if k in self.__dict__ and self.__dict__[k] != None:
+ continue
+ self.__dict__[k] = v
+ ret = real_parse(args, self) # pylint: disable=E1121
+
+ if self.verbosity >= 2:
+ logging.basicConfig(level=logging.DEBUG)
+ elif self.verbosity:
+ logging.basicConfig(level=logging.INFO)
+ else:
+ logging.basicConfig(level=logging.WARNING)
+
+ if self.browser_executable and not self.browser_type:
+ self.browser_type = 'exact'
+ if self.browser_type == 'list':
+ try:
+ types = browser_finder.GetAllAvailableBrowserTypes(self)
+ except browser_finder.BrowserFinderException, ex:
+ sys.stderr.write('ERROR: ' + str(ex))
+ sys.exit(1)
+ sys.stdout.write('Available browsers:\n')
+ sys.stdout.write(' %s\n' % '\n '.join(types))
+ sys.exit(0)
+ if self.extra_browser_args_as_string: # pylint: disable=E1101
+ tmp = shlex.split(
+ self.extra_browser_args_as_string) # pylint: disable=E1101
+ self.extra_browser_args.extend(tmp)
+ delattr(self, 'extra_browser_args_as_string')
+ if self.extra_wpr_args_as_string: # pylint: disable=E1101
+ tmp = shlex.split(
+ self.extra_wpr_args_as_string) # pylint: disable=E1101
+ self.extra_wpr_args.extend(tmp)
+ delattr(self, 'extra_wpr_args_as_string')
+ if self.profile_type == 'default':
+ self.dont_override_profile = True
+
+ if ((hasattr(self, 'output_format') and self.output_format == 'html') and
+ (not hasattr(self, 'output_file') or not self.output_file)):
+ self.output_file = os.path.join(util.GetBaseDir(), 'results.html')
+
+ # Parse repeat options
+ self.repeat_options.UpdateFromParseResults(self, parser)
+
+ # TODO(jeremy): I'm in the process of adding explicit knowledge of profile
+ # directories to Telemetry. As part of this work profile_type needs to be
+ # reworked to not override profile_dir.
+ if not self.profile_dir:
+ self.profile_dir = profile_types.GetProfileDir(self.profile_type)
+
+ return ret
+ parser.parse_args = ParseArgs
+ return parser
+
+ def AppendExtraBrowserArg(self, arg):
+ if arg not in self.extra_browser_args:
+ self.extra_browser_args.append(arg)
+
+ def MergeDefaultValues(self, defaults):
+ for k, v in defaults.__dict__.items():
+ self.ensure_value(k, v)
diff --git a/chromium/tools/telemetry/telemetry/core/browser_options_unittest.py b/chromium/tools/telemetry/telemetry/core/browser_options_unittest.py
new file mode 100644
index 00000000000..9f016fab7bf
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/browser_options_unittest.py
@@ -0,0 +1,99 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import optparse
+import unittest
+
+from telemetry.core import browser_options
+
+class BrowserOptionsTest(unittest.TestCase):
+ def testDefaults(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.add_option('-x', action='store', default=3)
+ parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options.x, 3) # pylint: disable=E1101
+
+ def testDefaultsPlusOverride(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.add_option('-x', action='store', default=3)
+ parser.parse_args(['--browser', 'any', '-x', 10])
+ self.assertEquals(options.x, 10) # pylint: disable=E1101
+
+ def testDefaultsDontClobberPresetValue(self):
+ options = browser_options.BrowserOptions()
+ setattr(options, 'x', 7)
+ parser = options.CreateParser()
+ parser.add_option('-x', action='store', default=3)
+ parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options.x, 7) # pylint: disable=E1101
+
+ def testCount0(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.add_option('-x', action='count', dest='v')
+ parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options.v, None) # pylint: disable=E1101
+
+ def testCount2(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.add_option('-x', action='count', dest='v')
+ parser.parse_args(['--browser', 'any', '-xx'])
+ self.assertEquals(options.v, 2) # pylint: disable=E1101
+
+ def testOptparseMutabilityWhenSpecified(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.add_option('-x', dest='verbosity', action='store_true')
+ options_ret, _ = parser.parse_args(['--browser', 'any', '-x'])
+ self.assertEquals(options_ret, options)
+ self.assertTrue(options.verbosity)
+
+ def testOptparseMutabilityWhenNotSpecified(self):
+ options = browser_options.BrowserOptions()
+
+ parser = options.CreateParser()
+ parser.add_option('-x', dest='verbosity', action='store_true')
+ options_ret, _ = parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options_ret, options)
+ self.assertFalse(options.verbosity)
+
+ def testProfileDirDefault(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.parse_args(['--browser', 'any'])
+ self.assertEquals(options.profile_dir, None)
+
+ def testProfileDir(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser()
+ parser.parse_args(['--browser', 'any', '--profile-dir', 'foo'])
+ self.assertEquals(options.profile_dir, 'foo')
+
+ def testMergeDefaultValues(self):
+ options = browser_options.BrowserOptions()
+ options.already_true = True
+ options.already_false = False
+ options.override_to_true = False
+ options.override_to_false = True
+
+ parser = optparse.OptionParser()
+ parser.add_option('--already_true', action='store_true')
+ parser.add_option('--already_false', action='store_true')
+ parser.add_option('--unset', action='store_true')
+ parser.add_option('--default_true', action='store_true', default=True)
+ parser.add_option('--default_false', action='store_true', default=False)
+ parser.add_option('--override_to_true', action='store_true', default=False)
+ parser.add_option('--override_to_false', action='store_true', default=True)
+
+ options.MergeDefaultValues(parser.get_default_values())
+
+ self.assertTrue(options.already_true)
+ self.assertFalse(options.already_false)
+ self.assertTrue(options.unset is None)
+ self.assertTrue(options.default_true)
+ self.assertFalse(options.default_false)
+ self.assertFalse(options.override_to_true)
+ self.assertTrue(options.override_to_false)
diff --git a/chromium/tools/telemetry/telemetry/core/browser_unittest.py b/chromium/tools/telemetry/telemetry/core/browser_unittest.py
new file mode 100644
index 00000000000..81a80f71b70
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/browser_unittest.py
@@ -0,0 +1,125 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import unittest
+
+from telemetry.core import browser_finder
+from telemetry.unittest import options_for_unittests
+
+class BrowserTest(unittest.TestCase):
+ def setUp(self):
+ self._browser = None
+
+ def CreateBrowser(self,
+ extra_browser_args=None,
+ profile_type=None):
+ assert not self._browser
+
+ options = options_for_unittests.GetCopy()
+
+ if profile_type:
+ # TODO(jeremy): crbug.com/243912 profiles are only implemented on
+ # Desktop.
+ is_running_on_desktop = not (
+ options.browser_type.startswith('android') or
+ options.browser_type.startswith('cros'))
+ if not is_running_on_desktop:
+ logging.warn("Desktop-only test, skipping.")
+ return None
+ options.profile_type = profile_type
+
+ if extra_browser_args:
+ options.extra_browser_args.extend(extra_browser_args)
+
+ browser_to_create = browser_finder.FindBrowser(options)
+ if not browser_to_create:
+ raise Exception('No browser found, cannot continue test.')
+ self._browser = browser_to_create.Create()
+ self._browser.Start()
+
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+
+ return self._browser
+
+ def tearDown(self):
+ if self._browser:
+ self._browser.Close()
+
+ def testBrowserCreation(self):
+ b = self.CreateBrowser()
+ self.assertEquals(1, len(b.tabs))
+
+ # Different browsers boot up to different things.
+ assert b.tabs[0].url
+
+ def testCommandLineOverriding(self):
+ # This test starts the browser with --user-agent=telemetry. This tests
+ # whether the user agent is then set.
+ flag1 = '--user-agent=telemetry'
+ b = self.CreateBrowser(extra_browser_args=[flag1])
+ t = b.tabs[0]
+ t.Navigate(b.http_server.UrlOf('blank.html'))
+ t.WaitForDocumentReadyStateToBeInteractiveOrBetter()
+ self.assertEquals(t.EvaluateJavaScript('navigator.userAgent'),
+ 'telemetry')
+
+ def testVersionDetection(self):
+ b = self.CreateBrowser()
+ v = b._browser_backend._inspector_protocol_version # pylint: disable=W0212
+ self.assertTrue(v > 0)
+
+ v = b._browser_backend._chrome_branch_number > 0 # pylint: disable=W0212
+ self.assertTrue(v > 0)
+
+ def testNewCloseTab(self):
+ b = self.CreateBrowser()
+ if not b.supports_tab_control:
+ logging.warning('Browser does not support tab control, skipping test.')
+ return
+ existing_tab = b.tabs[0]
+ self.assertEquals(1, len(b.tabs))
+ existing_tab_url = existing_tab.url
+
+ new_tab = b.tabs.New()
+ self.assertEquals(2, len(b.tabs))
+ self.assertEquals(existing_tab.url, existing_tab_url)
+ self.assertEquals(new_tab.url, 'about:blank')
+
+ new_tab.Close()
+ self.assertEquals(1, len(b.tabs))
+ self.assertEquals(existing_tab.url, existing_tab_url)
+
+ def testMultipleTabCalls(self):
+ b = self.CreateBrowser()
+ b.tabs[0].Navigate(b.http_server.UrlOf('blank.html'))
+ b.tabs[0].WaitForDocumentReadyStateToBeInteractiveOrBetter()
+
+ def testTabCallByReference(self):
+ b = self.CreateBrowser()
+ tab = b.tabs[0]
+ tab.Navigate(b.http_server.UrlOf('blank.html'))
+ b.tabs[0].WaitForDocumentReadyStateToBeInteractiveOrBetter()
+
+ def testCloseReferencedTab(self):
+ b = self.CreateBrowser()
+ if not b.supports_tab_control:
+ logging.warning('Browser does not support tab control, skipping test.')
+ return
+ b.tabs.New()
+ tab = b.tabs[0]
+ tab.Navigate(b.http_server.UrlOf('blank.html'))
+ tab.Close()
+ self.assertEquals(1, len(b.tabs))
+
+ def testDirtyProfileCreation(self):
+ b = self.CreateBrowser(profile_type = 'small_profile')
+
+ # TODO(jeremy): crbug.com/243912 profiles are only implemented on Desktop
+ if not b:
+ return
+
+ self.assertEquals(1, len(b.tabs))
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/__init__.py b/chromium/tools/telemetry/telemetry/core/chrome/__init__.py
new file mode 100644
index 00000000000..96196cffb27
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/__init__.py
@@ -0,0 +1,3 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/adb_commands.py b/chromium/tools/telemetry/telemetry/core/chrome/adb_commands.py
new file mode 100644
index 00000000000..890327bf19e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/adb_commands.py
@@ -0,0 +1,182 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Brings in Chrome Android's android_commands module, which itself is a
+thin(ish) wrapper around adb."""
+import os
+import sys
+
+# This is currently a thin wrapper around Chrome Android's
+# build scripts, located in chrome/build/android. This file exists mainly to
+# deal with locating the module.
+
+# Get build/android scripts into our path.
+sys.path.append(
+ os.path.abspath(
+ os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', '..', '..', 'build', 'android')))
+try:
+ from pylib import android_commands # pylint: disable=F0401
+ from pylib import cmd_helper # pylint: disable=F0401
+ from pylib import forwarder # pylint: disable=F0401
+ from pylib import ports # pylint: disable=F0401
+except Exception:
+ android_commands = None
+
+
+def IsAndroidSupported():
+ return android_commands != None
+
+
+def GetAttachedDevices():
+ """Returns a list of attached, online android devices.
+
+ If a preferred device has been set with ANDROID_SERIAL, it will be first in
+ the returned list."""
+ return android_commands.GetAttachedDevices()
+
+
+def AllocateTestServerPort():
+ return ports.AllocateTestServerPort()
+
+
+def ResetTestServerPortAllocation():
+ return ports.ResetTestServerPortAllocation()
+
+
+def GetOutDirectory():
+ return cmd_helper.OutDirectory.get()
+
+
+class AdbCommands(object):
+ """A thin wrapper around ADB"""
+
+ def __init__(self, device):
+ self._adb = android_commands.AndroidCommands(device)
+ self._device = device
+
+ def device(self):
+ return self._device
+
+ def Adb(self):
+ return self._adb
+
+ def Forward(self, local, remote):
+ ret = self._adb.Adb().SendCommand('forward %s %s' % (local, remote))
+ assert ret == ''
+
+ def RunShellCommand(self, command, timeout_time=20, log_result=False):
+ """Send a command to the adb shell and return the result.
+
+ Args:
+ command: String containing the shell command to send. Must not include
+ the single quotes as we use them to escape the whole command.
+ timeout_time: Number of seconds to wait for command to respond before
+ retrying, used by AdbInterface.SendShellCommand.
+ log_result: Boolean to indicate whether we should log the result of the
+ shell command.
+
+ Returns:
+ list containing the lines of output received from running the command
+ """
+ return self._adb.RunShellCommand(command, timeout_time, log_result)
+
+ def CloseApplication(self, package):
+ """Attempt to close down the application, using increasing violence.
+
+ Args:
+ package: Name of the process to kill off, e.g.
+ com.google.android.apps.chrome
+ """
+ self._adb.CloseApplication(package)
+
+ def KillAll(self, process):
+ """Android version of killall, connected via adb.
+
+ Args:
+ process: name of the process to kill off
+
+ Returns:
+ the number of processess killed
+ """
+ return self._adb.KillAll(process)
+
+ def ExtractPid(self, process_name):
+ """Extracts Process Ids for a given process name from Android Shell.
+
+ Args:
+ process_name: name of the process on the device.
+
+ Returns:
+ List of all the process ids (as strings) that match the given name.
+ If the name of a process exactly matches the given name, the pid of
+ that process will be inserted to the front of the pid list.
+ """
+ return self._adb.ExtractPid(process_name)
+
+ def StartActivity(self, package, activity, wait_for_completion=False,
+ action='android.intent.action.VIEW',
+ category=None, data=None,
+ extras=None, trace_file_name=None):
+ """Starts |package|'s activity on the device.
+
+ Args:
+ package: Name of package to start (e.g. 'com.google.android.apps.chrome').
+ activity: Name of activity (e.g. '.Main' or
+ 'com.google.android.apps.chrome.Main').
+ wait_for_completion: wait for the activity to finish launching (-W flag).
+ action: string (e.g. 'android.intent.action.MAIN'). Default is VIEW.
+ category: string (e.g. 'android.intent.category.HOME')
+ data: Data string to pass to activity (e.g. 'http://www.example.com/').
+ extras: Dict of extras to pass to activity. Values are significant.
+ trace_file_name: If used, turns on and saves the trace to this file name.
+ """
+ return self._adb.StartActivity(package, activity, wait_for_completion,
+ action,
+ category, data,
+ extras, trace_file_name)
+
+ def Push(self, local, remote):
+ return self._adb.Adb().Push(local, remote)
+
+ def Pull(self, remote, local):
+ return self._adb.Adb().Pull(remote, local)
+
+ def FileExistsOnDevice(self, file_name):
+ return self._adb.FileExistsOnDevice(file_name)
+
+ def IsRootEnabled(self):
+ return self._adb.IsRootEnabled()
+
+def HasForwarder(buildtype=None):
+ if not buildtype:
+ return (HasForwarder(buildtype='Release') or
+ HasForwarder(buildtype='Debug'))
+ return (os.path.exists(os.path.join(GetOutDirectory(), buildtype,
+ 'device_forwarder')) and
+ os.path.exists(os.path.join(GetOutDirectory(), buildtype,
+ 'host_forwarder')))
+
+class Forwarder(object):
+ def __init__(self, adb, *port_pairs):
+ self._adb = adb.Adb()
+ self._host_port = port_pairs[0].local_port
+
+ new_port_pairs = [(port_pair.local_port, port_pair.remote_port)
+ for port_pair in port_pairs]
+
+ self._port_pairs = new_port_pairs
+ forwarder.Forwarder.Map(new_port_pairs, self._adb)
+
+ @staticmethod
+ def _GetBuildType():
+ assert HasForwarder()
+ return 'Debug' if HasForwarder('Debug') else 'Release'
+
+ @property
+ def url(self):
+ return 'http://localhost:%i' % self._host_port
+
+ def Close(self):
+ for (device_port, _) in self._port_pairs:
+ forwarder.Forwarder.UnmapDevicePort(device_port, self._adb)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/android_browser_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/android_browser_backend.py
new file mode 100644
index 00000000000..34aa933ee18
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/android_browser_backend.py
@@ -0,0 +1,304 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import subprocess
+import sys
+import time
+
+from telemetry.core import exceptions
+from telemetry.core import util
+from telemetry.core.backends import browser_backend
+from telemetry.core.backends.chrome import chrome_browser_backend
+from telemetry.core.chrome import adb_commands
+
+
+class AndroidBrowserBackendSettings(object):
+ def __init__(self, adb, activity, cmdline_file, package, pseudo_exec_name):
+ self.adb = adb
+ self.activity = activity
+ self.cmdline_file = cmdline_file
+ self.package = package
+ self.pseudo_exec_name = pseudo_exec_name
+
+ def GetDevtoolsRemotePort(self):
+ raise NotImplementedError()
+
+ def RemoveProfile(self):
+ self.adb.RunShellCommand(
+ 'su -c rm -r "%s"' % self.profile_dir)
+
+ def PushProfile(self, _):
+ logging.critical('Profiles cannot be overriden with current configuration')
+ sys.exit(1)
+
+ @property
+ def is_content_shell(self):
+ return False
+
+ @property
+ def profile_dir(self):
+ raise NotImplementedError()
+
+
+class ChromeBackendSettings(AndroidBrowserBackendSettings):
+ # Stores a default Preferences file, re-used to speed up "--page-repeat".
+ _default_preferences_file = None
+
+ def __init__(self, adb, package):
+ super(ChromeBackendSettings, self).__init__(
+ adb=adb,
+ activity='com.google.android.apps.chrome.Main',
+ cmdline_file='/data/local/chrome-command-line',
+ package=package,
+ pseudo_exec_name='chrome')
+
+ def GetDevtoolsRemotePort(self):
+ return 'localabstract:chrome_devtools_remote'
+
+ def PushProfile(self, new_profile_dir):
+ self.adb.Push(new_profile_dir, self.profile_dir)
+
+ @property
+ def profile_dir(self):
+ return '/data/data/%s/app_chrome/' % self.package
+
+
+class ContentShellBackendSettings(AndroidBrowserBackendSettings):
+ def __init__(self, adb, package):
+ super(ContentShellBackendSettings, self).__init__(
+ adb=adb,
+ activity='org.chromium.content_shell_apk.ContentShellActivity',
+ cmdline_file='/data/local/tmp/content-shell-command-line',
+ package=package,
+ pseudo_exec_name='content_shell')
+
+ def GetDevtoolsRemotePort(self):
+ return 'localabstract:content_shell_devtools_remote'
+
+ @property
+ def is_content_shell(self):
+ return True
+
+ @property
+ def profile_dir(self):
+ return '/data/data/%s/app_content_shell/' % self.package
+
+
+class ChromiumTestShellBackendSettings(AndroidBrowserBackendSettings):
+ def __init__(self, adb, package):
+ super(ChromiumTestShellBackendSettings, self).__init__(
+ adb=adb,
+ activity='org.chromium.chrome.testshell.ChromiumTestShellActivity',
+ cmdline_file='/data/local/tmp/chromium-testshell-command-line',
+ package=package,
+ pseudo_exec_name='chromium_testshell')
+
+ def GetDevtoolsRemotePort(self):
+ return 'localabstract:chromium_testshell_devtools_remote'
+
+ @property
+ def is_content_shell(self):
+ return True
+
+ @property
+ def profile_dir(self):
+ return '/data/data/%s/app_chromiumtestshell/' % self.package
+
+
+class WebviewBackendSettings(AndroidBrowserBackendSettings):
+ def __init__(self, adb, package):
+ super(WebviewBackendSettings, self).__init__(
+ adb=adb,
+ activity='com.android.webview.chromium.shell.TelemetryActivity',
+ cmdline_file='/data/local/tmp/webview-command-line',
+ package=package,
+ pseudo_exec_name='webview')
+
+ def GetDevtoolsRemotePort(self):
+ # The DevTools socket name for WebView depends on the activity PID's.
+ retries = 0
+ timeout = 1
+ pid = None
+ while True:
+ pids = self.adb.ExtractPid(self.package)
+ if (len(pids) > 0):
+ pid = pids[-1]
+ break
+ time.sleep(timeout)
+ retries += 1
+ timeout *= 2
+ if retries == 4:
+ logging.critical('android_browser_backend: Timeout while waiting for '
+ 'activity %s:%s to come up',
+ self.package,
+ self.activity)
+ raise exceptions.BrowserGoneException('Timeout waiting for PID.')
+ return 'localabstract:webview_devtools_remote_%s' % str(pid)
+
+ @property
+ def profile_dir(self):
+ return '/data/data/%s/app_webview/' % self.package
+
+
+class AndroidBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
+ """The backend for controlling a browser instance running on Android.
+ """
+ def __init__(self, options, backend_settings):
+ super(AndroidBrowserBackend, self).__init__(
+ is_content_shell=backend_settings.is_content_shell,
+ supports_extensions=False, options=options)
+ if len(options.extensions_to_load) > 0:
+ raise browser_backend.ExtensionsNotSupportedException(
+ 'Android browser does not support extensions.')
+ # Initialize fields so that an explosion during init doesn't break in Close.
+ self._options = options
+ self._adb = backend_settings.adb
+ self._backend_settings = backend_settings
+ self._saved_cmdline = None
+ if not options.keep_test_server_ports:
+ adb_commands.ResetTestServerPortAllocation()
+ self._port = adb_commands.AllocateTestServerPort()
+
+ # Kill old browser.
+ self._adb.CloseApplication(self._backend_settings.package)
+
+ if self._adb.Adb().CanAccessProtectedFileContents():
+ if not options.dont_override_profile:
+ self._backend_settings.RemoveProfile()
+ if options.profile_dir:
+ self._backend_settings.PushProfile(options.profile_dir)
+
+ # Set up the command line.
+ self._saved_cmdline = ''.join(self._adb.Adb().GetProtectedFileContents(
+ self._backend_settings.cmdline_file) or [])
+ args = [backend_settings.pseudo_exec_name]
+ args.extend(self.GetBrowserStartupArgs())
+ def QuoteIfNeeded(arg):
+ # Escape 'key=valueA valueB' to 'key="valueA valueB"'
+ # Already quoted values, or values without space are left untouched.
+ # This is required so CommandLine.java can parse valueB correctly rather
+ # than as a separate switch.
+ params = arg.split('=')
+ if len(params) != 2:
+ return arg
+ key, values = params
+ if ' ' not in values:
+ return arg
+ if values[0] in '"\'' and values[-1] == values[0]:
+ return arg
+ return '%s="%s"' % (key, values)
+ args = map(QuoteIfNeeded, args)
+ self._adb.Adb().SetProtectedFileContents(
+ self._backend_settings.cmdline_file, ' '.join(args))
+ cmdline = self._adb.Adb().GetProtectedFileContents(
+ self._backend_settings.cmdline_file)
+ if len(cmdline) != 1 or cmdline[0] != ' '.join(args):
+ logging.critical('Failed to set Chrome command line. '
+ 'Fix this by flashing to a userdebug build.')
+ sys.exit(1)
+
+ def Start(self):
+ self._adb.RunShellCommand('logcat -c')
+ self._adb.StartActivity(self._backend_settings.package,
+ self._backend_settings.activity,
+ True,
+ None,
+ 'chrome://newtab/')
+
+ self._adb.Forward('tcp:%d' % self._port,
+ self._backend_settings.GetDevtoolsRemotePort())
+
+ try:
+ self._WaitForBrowserToComeUp()
+ self._PostBrowserStartupInitialization()
+ except exceptions.BrowserGoneException:
+ logging.critical('Failed to connect to browser.')
+ if not self._adb.Adb().CanAccessProtectedFileContents():
+ logging.critical(
+ 'Resolve this by either: '
+ '(1) Flashing to a userdebug build OR '
+ '(2) Manually enabling web debugging in Chrome at '
+ 'Settings > Developer tools > Enable USB Web debugging.')
+ sys.exit(1)
+ except:
+ import traceback
+ traceback.print_exc()
+ self.Close()
+ raise
+
+ def GetBrowserStartupArgs(self):
+ args = super(AndroidBrowserBackend, self).GetBrowserStartupArgs()
+ args.append('--enable-remote-debugging')
+ args.append('--no-restore-state')
+ args.append('--disable-fre')
+ return args
+
+ @property
+ def adb(self):
+ return self._adb
+
+ @property
+ def pid(self):
+ return int(self._adb.ExtractPid(self._backend_settings.package)[0])
+
+ @property
+ def browser_directory(self):
+ return None
+
+ @property
+ def profile_directory(self):
+ return self._backend_settings.profile_dir
+
+ def __del__(self):
+ self.Close()
+
+ def Close(self):
+ super(AndroidBrowserBackend, self).Close()
+
+ if self._saved_cmdline:
+ self._adb.Adb().SetProtectedFileContents(
+ self._backend_settings.cmdline_file,
+ self._saved_cmdline)
+ else:
+ self._adb.RunShellCommand('rm %s' % self._backend_settings.cmdline_file)
+ self._adb.CloseApplication(self._backend_settings.package)
+
+ def IsBrowserRunning(self):
+ pids = self._adb.ExtractPid(self._backend_settings.package)
+ return len(pids) != 0
+
+ def GetRemotePort(self, local_port):
+ return local_port
+
+ def GetStandardOutput(self):
+ return '\n'.join(self._adb.RunShellCommand('logcat -d -t 500'))
+
+ def GetStackTrace(self):
+ def Decorate(title, content):
+ return title + '\n' + content + '\n' + '*' * 80 + '\n'
+ # Get the last lines of logcat (large enough to contain stacktrace)
+ logcat = self.GetStandardOutput()
+ ret = Decorate('Logcat', logcat)
+ stack = os.path.join(util.GetChromiumSrcDir(), 'third_party',
+ 'android_platform', 'development', 'scripts', 'stack')
+ # Try to symbolize logcat.
+ if os.path.exists(stack):
+ p = subprocess.Popen([stack], stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ ret += Decorate('Stack from Logcat', p.communicate(input=logcat)[0])
+
+ # Try to get tombstones.
+ tombstones = os.path.join(util.GetChromiumSrcDir(), 'build', 'android',
+ 'tombstones.py')
+ if os.path.exists(tombstones):
+ ret += Decorate('Tombstones',
+ subprocess.Popen([tombstones, '-w', '--device',
+ self._adb.device()],
+ stdout=subprocess.PIPE).communicate()[0])
+ return ret
+
+ def CreateForwarder(self, *port_pairs):
+ return adb_commands.Forwarder(self._adb, *port_pairs)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder.py b/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder.py
new file mode 100644
index 00000000000..d3a7bdcfc2e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder.py
@@ -0,0 +1,185 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Finds android browsers that can be controlled by telemetry."""
+
+import os
+import logging as real_logging
+import re
+import subprocess
+import sys
+
+from telemetry.core import browser
+from telemetry.core import possible_browser
+from telemetry.core import profile_types
+from telemetry.core.chrome import adb_commands
+from telemetry.core.chrome import android_browser_backend
+from telemetry.core.platform import android_platform_backend
+
+CHROME_PACKAGE_NAMES = {
+ 'android-chrome': 'com.google.android.apps.chrome',
+ 'android-chrome-beta': 'com.chrome.beta',
+ 'android-chrome-dev': 'com.google.android.apps.chrome_dev',
+ 'android-jb-system-chrome': 'com.android.chrome'
+}
+
+ALL_BROWSER_TYPES = ','.join([
+ 'android-chromium-testshell',
+ 'android-content-shell',
+ 'android-webview',
+ ] + CHROME_PACKAGE_NAMES.keys())
+
+CONTENT_SHELL_PACKAGE = 'org.chromium.content_shell_apk'
+CHROMIUM_TESTSHELL_PACKAGE = 'org.chromium.chrome.testshell'
+WEBVIEW_PACKAGE = 'com.android.webview.chromium.shell'
+
+
+# adb shell pm list packages
+# adb
+# intents to run (pass -D url for the rest)
+# com.android.chrome/.Main
+# com.google.android.apps.chrome/.Main
+
+class PossibleAndroidBrowser(possible_browser.PossibleBrowser):
+ """A launchable android browser instance."""
+ def __init__(self, browser_type, options, backend_settings):
+ super(PossibleAndroidBrowser, self).__init__(browser_type, options)
+ self._backend_settings = backend_settings
+
+ def __repr__(self):
+ return 'PossibleAndroidBrowser(browser_type=%s)' % self.browser_type
+
+ def Create(self):
+ if profile_types.GetProfileCreator(self.options.profile_type):
+ raise Exception("Profile creation not currently supported on Android")
+
+ backend = android_browser_backend.AndroidBrowserBackend(
+ self._options, self._backend_settings)
+ platform_backend = android_platform_backend.AndroidPlatformBackend(
+ self._backend_settings.adb.Adb(), self._options.no_performance_mode)
+ b = browser.Browser(backend, platform_backend)
+ return b
+
+ def SupportsOptions(self, options):
+ if len(options.extensions_to_load) != 0:
+ return False
+ return True
+
+def SelectDefaultBrowser(_):
+ return None
+
+adb_works = None
+def CanFindAvailableBrowsers(logging=real_logging):
+ if not adb_commands.IsAndroidSupported():
+ return False
+
+ global adb_works
+
+ if adb_works == None:
+ try:
+ with open(os.devnull, 'w') as devnull:
+ proc = subprocess.Popen(['adb', 'devices'],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdin=devnull)
+ stdout, _ = proc.communicate()
+ if re.search(re.escape('????????????\tno permissions'), stdout) != None:
+ logging.warn(
+ ('adb devices reported a permissions error. Consider '
+ 'restarting adb as root:'))
+ logging.warn(' adb kill-server')
+ logging.warn(' sudo `which adb` devices\n\n')
+ adb_works = True
+ except OSError:
+ platform_tools_path = os.path.join(
+ os.path.dirname(__file__), '..', '..', '..', '..', '..'
+ 'third_party', 'android_tools', 'sdk', 'platform-tools')
+ if (sys.platform.startswith('linux') and
+ os.path.exists(os.path.join(platform_tools_path, 'adb'))):
+ os.environ['PATH'] = os.pathsep.join([platform_tools_path,
+ os.environ['PATH']])
+ adb_works = True
+ else:
+ adb_works = False
+ if adb_works and sys.platform.startswith('linux'):
+ # Workaround for crbug.com/268450
+ import psutil
+ adb_commands.GetAttachedDevices()
+ pids = [p.pid for p in psutil.process_iter() if 'adb' in p.name]
+ with open(os.devnull, 'w') as devnull:
+ for pid in pids:
+ subprocess.check_call(['taskset', '-p', '0x1', str(pid)],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdin=devnull)
+
+ return adb_works
+
+def FindAllAvailableBrowsers(options, logging=real_logging):
+ """Finds all the desktop browsers available on this machine."""
+ if not CanFindAvailableBrowsers(logging=logging):
+ logging.info('No adb command found. ' +
+ 'Will not try searching for Android browsers.')
+ return []
+
+ device = None
+ if options.android_device:
+ devices = [options.android_device]
+ else:
+ devices = adb_commands.GetAttachedDevices()
+
+ if len(devices) == 0:
+ logging.info('No android devices found.')
+ return []
+
+ if len(devices) > 1:
+ logging.warn('Multiple devices attached. ' +
+ 'Please specify a device explicitly.')
+ return []
+
+ device = devices[0]
+
+ adb = adb_commands.AdbCommands(device=device)
+
+ packages = adb.RunShellCommand('pm list packages')
+ possible_browsers = []
+ if 'package:' + CONTENT_SHELL_PACKAGE in packages:
+ b = PossibleAndroidBrowser(
+ 'android-content-shell',
+ options, android_browser_backend.ContentShellBackendSettings(
+ adb, CONTENT_SHELL_PACKAGE))
+ possible_browsers.append(b)
+
+ if 'package:' + CHROMIUM_TESTSHELL_PACKAGE in packages:
+ b = PossibleAndroidBrowser(
+ 'android-chromium-testshell',
+ options, android_browser_backend.ChromiumTestShellBackendSettings(
+ adb, CHROMIUM_TESTSHELL_PACKAGE))
+ possible_browsers.append(b)
+
+ if 'package:' + WEBVIEW_PACKAGE in packages:
+ b = PossibleAndroidBrowser(
+ 'android-webview',
+ options,
+ android_browser_backend.WebviewBackendSettings(adb, WEBVIEW_PACKAGE))
+ possible_browsers.append(b)
+
+ for name, package in CHROME_PACKAGE_NAMES.iteritems():
+ if 'package:' + package in packages:
+ b = PossibleAndroidBrowser(
+ name,
+ options,
+ android_browser_backend.ChromeBackendSettings(adb, package))
+ possible_browsers.append(b)
+
+ # See if the "forwarder" is installed -- we need this to host content locally
+ # but make it accessible to the device.
+ if len(possible_browsers) and not adb_commands.HasForwarder():
+ logging.warn('telemetry detected an android device. However,')
+ logging.warn('Chrome\'s port-forwarder app is not available.')
+ logging.warn('To build:')
+ logging.warn(' ninja -C out/Release forwarder2 md5sum')
+ logging.warn('')
+ logging.warn('')
+ return []
+ return possible_browsers
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder_unittest.py
new file mode 100644
index 00000000000..c1e4fcf02cc
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/android_browser_finder_unittest.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.core import browser_options
+from telemetry.core.chrome import android_browser_finder
+from telemetry.unittest import system_stub
+
+class LoggingStub(object):
+ def __init__(self):
+ self.warnings = []
+
+ def info(self, msg, *args):
+ pass
+
+ def warn(self, msg, *args):
+ self.warnings.append(msg % args)
+
+class AndroidBrowserFinderTest(unittest.TestCase):
+ def setUp(self):
+ self._stubs = system_stub.Override(android_browser_finder,
+ ['adb_commands', 'subprocess'])
+ android_browser_finder.adb_works = None # Blow cache between runs.
+
+ def tearDown(self):
+ self._stubs.Restore()
+
+ def test_no_adb(self):
+ options = browser_options.BrowserOptions()
+
+ def NoAdb(*args, **kargs): # pylint: disable=W0613
+ raise OSError('not found')
+ self._stubs.subprocess.Popen = NoAdb
+ browsers = android_browser_finder.FindAllAvailableBrowsers(options)
+ self.assertEquals(0, len(browsers))
+
+ def test_adb_no_devices(self):
+ options = browser_options.BrowserOptions()
+
+ browsers = android_browser_finder.FindAllAvailableBrowsers(options)
+ self.assertEquals(0, len(browsers))
+
+
+ def test_adb_permissions_error(self):
+ options = browser_options.BrowserOptions()
+
+ self._stubs.subprocess.Popen.communicate_result = (
+ """List of devices attached
+????????????\tno permissions""",
+ """* daemon not running. starting it now on port 5037 *
+* daemon started successfully *
+""")
+
+ log_stub = LoggingStub()
+ browsers = android_browser_finder.FindAllAvailableBrowsers(
+ options, log_stub)
+ self.assertEquals(3, len(log_stub.warnings))
+ self.assertEquals(0, len(browsers))
+
+
+ def test_adb_two_devices(self):
+ options = browser_options.BrowserOptions()
+
+ self._stubs.adb_commands.attached_devices = ['015d14fec128220c',
+ '015d14fec128220d']
+
+ log_stub = LoggingStub()
+ browsers = android_browser_finder.FindAllAvailableBrowsers(
+ options, log_stub)
+ self.assertEquals(1, len(log_stub.warnings))
+ self.assertEquals(0, len(browsers))
+
+ def test_adb_one_device(self):
+ options = browser_options.BrowserOptions()
+
+ self._stubs.adb_commands.attached_devices = ['015d14fec128220c']
+
+ def OnPM(args):
+ assert args[0] == 'pm'
+ assert args[1] == 'list'
+ assert args[2] == 'packages'
+ return ['package:org.chromium.content_shell_apk',
+ 'package.com.google.android.setupwizard']
+
+ self._stubs.adb_commands.shell_command_handlers['pm'] = OnPM
+
+ browsers = android_browser_finder.FindAllAvailableBrowsers(options)
+ self.assertEquals(1, len(browsers))
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/main.html b/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/main.html
new file mode 100644
index 00000000000..07a643c7918
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/main.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <script src="main.js"></script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/main.js b/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/main.js
new file mode 100644
index 00000000000..79e3cfcbd64
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/main.js
@@ -0,0 +1,17 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var PARENT_PAGE = 'chrome://oobe/';
+
+var msg = {
+ 'method': 'loginUILoaded'
+};
+window.parent.postMessage(msg, PARENT_PAGE);
+
+var msg = {
+ 'method': 'completeLogin',
+ 'email': 'test@test.test',
+ 'password': ''
+};
+window.parent.postMessage(msg, PARENT_PAGE);
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/manifest.json b/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/manifest.json
new file mode 100644
index 00000000000..af499d71a90
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/chromeos_login_ext/manifest.json
@@ -0,0 +1,16 @@
+{
+ // chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/
+ "key": "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC4L17nAfeTd6Xhtx96WhQ6DSr8KdHeQmfzgCkieKLCgUkWdwB9G1DCuh0EPMDn1MdtSwUAT7xE36APEzi0X/UpKjOVyX8tCC3aQcLoRAE0aJAvCcGwK7qIaQaczHmHKvPC2lrRdzSoMMTC5esvHX+ZqIBMi123FOL0dGW6OPKzIwIBIw==",
+ "name": "GaiaDummyAuthExtension",
+ "version": "0.0.1",
+ "manifest_version": 2,
+ "content_security_policy": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'",
+ "description": "GAIA Dummy Component Extension",
+ "web_accessible_resources": [
+ "main.html",
+ "main.js"
+ ],
+ "permissions": [
+ "chrome://oobe/"
+ ]
+}
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py
new file mode 100644
index 00000000000..805a48147c5
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_backend.py
@@ -0,0 +1,407 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import subprocess
+
+from telemetry.core import exceptions
+from telemetry.core import util
+from telemetry.core.backends import browser_backend
+from telemetry.core.backends.chrome import chrome_browser_backend
+
+class CrOSBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
+ # Some developers' workflow includes running the Chrome process from
+ # /usr/local/... instead of the default location. We have to check for both
+ # paths in order to support this workflow.
+ CHROME_PATHS = ['/opt/google/chrome/chrome ',
+ '/usr/local/opt/google/chrome/chrome ']
+
+ def __init__(self, browser_type, options, cri, is_guest):
+ super(CrOSBrowserBackend, self).__init__(
+ is_content_shell=False, supports_extensions=not is_guest,
+ options=options)
+ # Initialize fields so that an explosion during init doesn't break in Close.
+ self._browser_type = browser_type
+ self._options = options
+ self._cri = cri
+ self._is_guest = is_guest
+
+ self._remote_debugging_port = self._cri.GetRemotePort()
+ self._port = self._remote_debugging_port
+ self._forwarder = None
+
+ self._login_ext_dir = os.path.join(os.path.dirname(__file__),
+ 'chromeos_login_ext')
+
+ # Push a dummy login extension to the device.
+ # This extension automatically logs in as test@test.test
+ # Note that we also perform this copy locally to ensure that
+ # the owner of the extensions is set to chronos.
+ logging.info('Copying dummy login extension to the device')
+ cri.PushFile(self._login_ext_dir, '/tmp/')
+ self._login_ext_dir = '/tmp/chromeos_login_ext'
+ cri.RunCmdOnDevice(['chown', '-R', 'chronos:chronos',
+ self._login_ext_dir])
+
+ # Copy extensions to temp directories on the device.
+ # Note that we also perform this copy locally to ensure that
+ # the owner of the extensions is set to chronos.
+ for e in options.extensions_to_load:
+ output = cri.RunCmdOnDevice(['mktemp', '-d', '/tmp/extension_XXXXX'])
+ extension_dir = output[0].rstrip()
+ cri.PushFile(e.path, extension_dir)
+ cri.RunCmdOnDevice(['chown', '-R', 'chronos:chronos', extension_dir])
+ e.local_path = os.path.join(extension_dir, os.path.basename(e.path))
+
+ # Ensure the UI is running and logged out.
+ self._RestartUI()
+ util.WaitFor(lambda: self.IsBrowserRunning(), 20) # pylint: disable=W0108
+
+ # Delete test@test.test's cryptohome vault (user data directory).
+ if not options.dont_override_profile:
+ logging.info('Deleting user\'s cryptohome vault (the user data dir)')
+ self._cri.RunCmdOnDevice(
+ ['cryptohome', '--action=remove', '--force', '--user=test@test.test'])
+ if options.profile_dir:
+ profile_dir = '/home/chronos/Default'
+ cri.RunCmdOnDevice(['rm', '-rf', profile_dir])
+ cri.PushFile(options.profile_dir + '/Default', profile_dir)
+ cri.RunCmdOnDevice(['chown', '-R', 'chronos:chronos', profile_dir])
+
+ def GetBrowserStartupArgs(self):
+ self.webpagereplay_remote_http_port = self._cri.GetRemotePort()
+ self.webpagereplay_remote_https_port = self._cri.GetRemotePort()
+
+ args = super(CrOSBrowserBackend, self).GetBrowserStartupArgs()
+
+ args.extend([
+ '--enable-smooth-scrolling',
+ '--enable-threaded-compositing',
+ '--enable-per-tile-painting',
+ '--force-compositing-mode',
+ # Disables the start page, as well as other external apps that can
+ # steal focus or make measurements inconsistent.
+ '--disable-default-apps',
+ # Jump to the login screen, skipping network selection, eula, etc.
+ '--login-screen=login',
+ # Skip user image selection screen, and post login screens.
+ '--oobe-skip-postlogin',
+ # Skip hwid check, for VMs and pre-MP lab devices.
+ '--skip-hwid-check',
+ # Allow devtools to connect to chrome.
+ '--remote-debugging-port=%i' % self._remote_debugging_port,
+ # Open a maximized window.
+ '--start-maximized',
+ # Debug logging for login flake (crbug.com/263527).
+ '--vmodule=*/browser/automation/*=2,*/chromeos/net/*=2,' +
+ '*/chromeos/login/*=2'])
+
+ if not self._is_guest:
+ # This extension bypasses gaia and logs us in.
+ args.append('--auth-ext-path=%s' % self._login_ext_dir)
+
+ return args
+
+ def _GetSessionManagerPid(self, procs):
+ """Returns the pid of the session_manager process, given the list of
+ processes."""
+ for pid, process, _, _ in procs:
+ if process.startswith('/sbin/session_manager '):
+ return pid
+ return None
+
+ def _GetChromeProcess(self):
+ """Locates the the main chrome browser process.
+
+ Chrome on cros is usually in /opt/google/chrome, but could be in
+ /usr/local/ for developer workflows - debug chrome is too large to fit on
+ rootfs.
+
+ Chrome spawns multiple processes for renderers. pids wrap around after they
+ are exhausted so looking for the smallest pid is not always correct. We
+ locate the session_manager's pid, and look for the chrome process that's an
+ immediate child. This is the main browser process.
+ """
+ procs = self._cri.ListProcesses()
+ session_manager_pid = self._GetSessionManagerPid(procs)
+ if not session_manager_pid:
+ return None
+
+ # Find the chrome process that is the child of the session_manager.
+ for pid, process, ppid, _ in procs:
+ if ppid != session_manager_pid:
+ continue
+ for path in self.CHROME_PATHS:
+ if process.startswith(path):
+ return {'pid': pid, 'path': path}
+ return None
+
+ @property
+ def pid(self):
+ result = self._GetChromeProcess()
+ if result and 'pid' in result:
+ return result['pid']
+ return None
+
+ @property
+ def browser_directory(self):
+ result = self._GetChromeProcess()
+ if result and 'path' in result:
+ return result['path']
+ return None
+
+ @property
+ def profile_directory(self):
+ return '/home/chronos/Default'
+
+ @property
+ def hwid(self):
+ return self._cri.RunCmdOnDevice(['/usr/bin/crossystem', 'hwid'])[0]
+
+ def GetRemotePort(self, _):
+ return self._cri.GetRemotePort()
+
+ def __del__(self):
+ self.Close()
+
+ def Start(self):
+ # Escape all commas in the startup arguments we pass to Chrome
+ # because dbus-send delimits array elements by commas
+ startup_args = [a.replace(',', '\\,') for a in self.GetBrowserStartupArgs()]
+
+ # Restart Chrome with the login extension and remote debugging.
+ logging.info('Restarting Chrome with flags and login')
+ args = ['dbus-send', '--system', '--type=method_call',
+ '--dest=org.chromium.SessionManager',
+ '/org/chromium/SessionManager',
+ 'org.chromium.SessionManagerInterface.EnableChromeTesting',
+ 'boolean:true',
+ 'array:string:"%s"' % ','.join(startup_args)]
+ self._cri.RunCmdOnDevice(args)
+
+ if not self._cri.local:
+ # Find a free local port.
+ self._port = util.GetAvailableLocalPort()
+
+ # Forward the remote debugging port.
+ logging.info('Forwarding remote debugging port')
+ self._forwarder = SSHForwarder(
+ self._cri, 'L',
+ util.PortPair(self._port, self._remote_debugging_port))
+
+ # Wait for the browser to come up.
+ logging.info('Waiting for browser to be ready')
+ try:
+ self._WaitForBrowserToComeUp()
+ self._PostBrowserStartupInitialization()
+ except:
+ import traceback
+ traceback.print_exc()
+ self.Close()
+ raise
+
+ # chrome_branch_number is set in _PostBrowserStartupInitialization.
+ # Without --skip-hwid-check (introduced in crrev.com/203397), devices/VMs
+ # will be stuck on the bad hwid screen.
+ if self.chrome_branch_number <= 1500 and not self.hwid:
+ raise exceptions.LoginException(
+ 'Hardware id not set on device/VM. --skip-hwid-check not supported '
+ 'with chrome branches 1500 or earlier.')
+
+ if self._is_guest:
+ pid = self.pid
+ self._NavigateGuestLogin()
+ # Guest browsing shuts down the current browser and launches an incognito
+ # browser in a separate process, which we need to wait for.
+ util.WaitFor(lambda: pid != self.pid, 10)
+ self._WaitForBrowserToComeUp()
+ else:
+ self._NavigateLogin()
+
+ logging.info('Browser is up!')
+
+ def Close(self):
+ super(CrOSBrowserBackend, self).Close()
+
+ self._RestartUI() # Logs out.
+
+ if not self._cri.local:
+ if self._forwarder:
+ self._forwarder.Close()
+ self._forwarder = None
+
+ if self._login_ext_dir:
+ self._cri.RmRF(self._login_ext_dir)
+ self._login_ext_dir = None
+
+ for e in self._options.extensions_to_load:
+ self._cri.RmRF(os.path.dirname(e.local_path))
+
+ self._cri = None
+
+ def IsBrowserRunning(self):
+ return bool(self.pid)
+
+ def GetStandardOutput(self):
+ return 'Cannot get standard output on CrOS'
+
+ def GetStackTrace(self):
+ return 'Cannot get stack trace on CrOS'
+
+ def CreateForwarder(self, *port_pairs):
+ assert self._cri
+ return (browser_backend.DoNothingForwarder(*port_pairs) if self._cri.local
+ else SSHForwarder(self._cri, 'R', *port_pairs))
+
+ def _RestartUI(self):
+ if self._cri:
+ logging.info('(Re)starting the ui (logs the user out)')
+ if self._cri.IsServiceRunning('ui'):
+ self._cri.RunCmdOnDevice(['restart', 'ui'])
+ else:
+ self._cri.RunCmdOnDevice(['start', 'ui'])
+
+ @property
+ def oobe(self):
+ return self.misc_web_contents_backend.GetOobe()
+
+ def _SigninUIState(self):
+ """Returns the signin ui state of the oobe. HIDDEN: 0, GAIA_SIGNIN: 1,
+ ACCOUNT_PICKER: 2, WRONG_HWID_WARNING: 3, MANAGED_USER_CREATION_FLOW: 4.
+ These values are in
+ chrome/browser/resources/chromeos/login/display_manager.js
+ """
+ return self.oobe.EvaluateJavaScript('''
+ loginHeader = document.getElementById('login-header-bar')
+ if (loginHeader) {
+ loginHeader.signinUIState_;
+ }
+ ''')
+
+ def _IsCryptohomeMounted(self):
+ """Returns True if a cryptohome vault is mounted at /home/chronos/user."""
+ return self._cri.FilesystemMountedAt('/home/chronos/user').startswith(
+ '/home/.shadow/')
+
+ def _HandleUserImageSelectionScreen(self):
+ """If we're stuck on the user image selection screen, we click the ok
+ button.
+ """
+ oobe = self.oobe
+ if oobe:
+ try:
+ oobe.EvaluateJavaScript("""
+ var ok = document.getElementById("ok-button");
+ if (ok) {
+ ok.click();
+ }
+ """)
+ except (exceptions.TabCrashException):
+ pass
+
+ def _IsLoggedIn(self):
+ """Returns True if we're logged in (cryptohome has mounted), and the oobe
+ has been dismissed."""
+ if self.chrome_branch_number <= 1547:
+ self._HandleUserImageSelectionScreen()
+ return self._IsCryptohomeMounted() and not self.oobe
+
+ def _StartupWindow(self):
+ """Closes the startup window, which is an extension on official builds,
+ and a webpage on chromiumos"""
+ startup_window_ext_id = 'honijodknafkokifofgiaalefdiedpko'
+ return (self.extension_dict_backend[startup_window_ext_id]
+ if startup_window_ext_id in self.extension_dict_backend
+ else self.tab_list_backend.Get(0, None))
+
+ def _WaitForAccountPicker(self):
+ """Waits for the oobe screen to be in the account picker state."""
+ util.WaitFor(lambda: self._SigninUIState() == 2, 20)
+
+ def _ClickBrowseAsGuest(self):
+ """Click the Browse As Guest button on the account picker screen. This will
+ restart the browser, and we could have a tab crash or a browser crash."""
+ try:
+ self.oobe.EvaluateJavaScript("""
+ var guest = document.getElementById("guest-user-button");
+ if (guest) {
+ guest.click();
+ }
+ """)
+ except (exceptions.TabCrashException,
+ exceptions.BrowserConnectionGoneException):
+ pass
+
+ def _WaitForGuestFsMounted(self):
+ """Waits for /home/chronos/user to be mounted as guestfs"""
+ util.WaitFor(lambda: (self._cri.FilesystemMountedAt('/home/chronos/user') ==
+ 'guestfs'), 20)
+
+ def _NavigateGuestLogin(self):
+ """Navigates through oobe login screen as guest"""
+ assert self.oobe
+ self._WaitForAccountPicker()
+ self._ClickBrowseAsGuest()
+ self._WaitForGuestFsMounted()
+
+ def _NavigateLogin(self):
+ """Navigates through oobe login screen"""
+ # Dismiss the user image selection screen.
+ try:
+ util.WaitFor(lambda: self._IsLoggedIn(), 60) # pylint: disable=W0108
+ except util.TimeoutException:
+ self._cri.TakeScreenShot('login-screen')
+ raise exceptions.LoginException(
+ 'Timed out going through oobe screen. Make sure the custom auth '
+ 'extension passed through --auth-ext-path is valid and belongs '
+ 'to user "chronos".')
+
+ if self.chrome_branch_number < 1500:
+ # Wait for the startup window, then close it. Startup window doesn't exist
+ # post-M27. crrev.com/197900
+ util.WaitFor(lambda: self._StartupWindow() is not None, 20)
+ self._StartupWindow().Close()
+ else:
+ # Open a new window/tab.
+ self.tab_list_backend.New(15)
+
+
+class SSHForwarder(object):
+ def __init__(self, cri, forwarding_flag, *port_pairs):
+ self._proc = None
+
+ if forwarding_flag == 'R':
+ self._host_port = port_pairs[0].remote_port
+ command_line = ['-%s%i:localhost:%i' % (forwarding_flag,
+ port_pair.remote_port,
+ port_pair.local_port)
+ for port_pair in port_pairs]
+ else:
+ self._host_port = port_pairs[0].local_port
+ command_line = ['-%s%i:localhost:%i' % (forwarding_flag,
+ port_pair.local_port,
+ port_pair.remote_port)
+ for port_pair in port_pairs]
+
+ self._device_port = port_pairs[0].remote_port
+
+ self._proc = subprocess.Popen(
+ cri.FormSSHCommandLine(['sleep', '999999999'], command_line),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ shell=False)
+
+ util.WaitFor(lambda: cri.IsHTTPServerRunningOnPort(self._device_port), 60)
+
+ @property
+ def url(self):
+ assert self._proc
+ return 'http://localhost:%i' % self._host_port
+
+ def Close(self):
+ if self._proc:
+ self._proc.kill()
+ self._proc = None
+
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_finder.py b/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_finder.py
new file mode 100644
index 00000000000..da795fadb7a
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_finder.py
@@ -0,0 +1,110 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Finds CrOS browsers that can be controlled by telemetry."""
+
+import logging
+
+from telemetry.core import browser
+from telemetry.core import possible_browser
+from telemetry.core import profile_types
+from telemetry.core.chrome import cros_browser_backend
+from telemetry.core.chrome import cros_interface
+from telemetry.core.platform import cros_platform_backend
+
+ALL_BROWSER_TYPES = ','.join([
+ 'cros-chrome',
+ 'cros-chrome-guest',
+ 'system-guest',
+ ])
+
+class PossibleCrOSBrowser(possible_browser.PossibleBrowser):
+ """A launchable chromeos browser instance."""
+ def __init__(self, browser_type, options, cri, is_guest):
+ super(PossibleCrOSBrowser, self).__init__(browser_type, options)
+ self._cri = cri
+ self._is_guest = is_guest
+
+ def __repr__(self):
+ return 'PossibleCrOSBrowser(browser_type=%s)' % self.browser_type
+
+ def Create(self):
+ if profile_types.GetProfileCreator(self.options.profile_type):
+ raise Exception("Profile creation not currently supported on Chrome OS")
+
+ backend = cros_browser_backend.CrOSBrowserBackend(
+ self.browser_type, self._options, self._cri, self._is_guest)
+ b = browser.Browser(backend,
+ cros_platform_backend.CrosPlatformBackend(self._cri))
+ return b
+
+ def SupportsOptions(self, options):
+ if (len(options.extensions_to_load) != 0) and self._is_guest:
+ return False
+ return True
+
+def SelectDefaultBrowser(possible_browsers):
+ if cros_interface.IsRunningOnCrosDevice():
+ for b in possible_browsers:
+ if b.browser_type == 'system':
+ return b
+ return None
+
+def CanFindAvailableBrowsers(options):
+ return (cros_interface.IsRunningOnCrosDevice() or
+ options.cros_remote or
+ cros_interface.HasSSH())
+
+def FindAllAvailableBrowsers(options):
+ """Finds all available chromeos browsers, locally and remotely."""
+ if cros_interface.IsRunningOnCrosDevice():
+ return [PossibleCrOSBrowser('system', options,
+ cros_interface.CrOSInterface(),
+ is_guest=False),
+ PossibleCrOSBrowser('system-guest', options,
+ cros_interface.CrOSInterface(),
+ is_guest=True)]
+
+ if options.cros_remote == None:
+ logging.debug('No --remote specified, will not probe for CrOS.')
+ return []
+
+ if not cros_interface.HasSSH():
+ logging.debug('ssh not found. Cannot talk to CrOS devices.')
+ return []
+ cri = cros_interface.CrOSInterface(options.cros_remote,
+ options.cros_ssh_identity)
+
+ # Check ssh
+ try:
+ cri.TryLogin()
+ except cros_interface.LoginException, ex:
+ if isinstance(ex, cros_interface.KeylessLoginRequiredException):
+ logging.warn('Could not ssh into %s. Your device must be configured',
+ options.cros_remote)
+ logging.warn('to allow passwordless login as root.')
+ logging.warn('For a test-build device, pass this to your script:')
+ logging.warn(' --identity $(CHROMITE)/ssh_keys/testing_rsa')
+ logging.warn('')
+ logging.warn('For a developer-mode device, the steps are:')
+ logging.warn(' - Ensure you have an id_rsa.pub (etc) on this computer')
+ logging.warn(' - On the chromebook:')
+ logging.warn(' - Control-Alt-T; shell; sudo -s')
+ logging.warn(' - openssh-server start')
+ logging.warn(' - scp <this machine>:.ssh/id_rsa.pub /tmp/')
+ logging.warn(' - mkdir /root/.ssh')
+ logging.warn(' - chown go-rx /root/.ssh')
+ logging.warn(' - cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys')
+ logging.warn(' - chown 0600 /root/.ssh/authorized_keys')
+ logging.warn('There, that was easy!')
+ logging.warn('')
+ logging.warn('P.S. Please, tell your manager how INANE this is.')
+
+ from telemetry.core import browser_finder
+ raise browser_finder.BrowserFinderException(str(ex))
+
+ if not cri.FileExistsOnDevice('/opt/google/chrome/chrome'):
+ logging.warn('Could not find a chrome on ' % cri.hostname)
+
+ return [PossibleCrOSBrowser('cros-chrome', options, cri, is_guest=False),
+ PossibleCrOSBrowser('cros-chrome-guest', options, cri, is_guest=True)]
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_finder_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_finder_unittest.py
new file mode 100644
index 00000000000..07f2e033fbe
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/cros_browser_finder_unittest.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(nduca): Add basic unit test for cros_browser_finder.
+#
+# Here, we should mock the cros_interface module (assuming its working) and
+# verify that the finder does the right thing. Because the finder delegates most
+# of its work to the CRI, the test code here is going to be comparatively
+# simple.
+
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/cros_interface.py b/chromium/tools/telemetry/telemetry/core/chrome/cros_interface.py
new file mode 100644
index 00000000000..6f1f16084eb
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/cros_interface.py
@@ -0,0 +1,345 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""A wrapper around ssh for common operations on a CrOS-based device"""
+import logging
+import os
+import re
+import subprocess
+import sys
+import tempfile
+
+# TODO(nduca): This whole file is built up around making individual ssh calls
+# for each operation. It really could get away with a single ssh session built
+# around pexpect, I suspect, if we wanted it to be faster. But, this was
+# convenient.
+
+def IsRunningOnCrosDevice():
+ """Returns True if we're on a ChromeOS device."""
+ lsb_release = '/etc/lsb-release'
+ if sys.platform.startswith('linux') and os.path.exists(lsb_release):
+ with open(lsb_release, 'r') as f:
+ res = f.read()
+ if res.count('CHROMEOS_RELEASE_NAME'):
+ return True
+ return False
+
+def RunCmd(args, cwd=None, quiet=False):
+ """Opens a subprocess to execute a program and returns its return value.
+
+ Args:
+ args: A string or a sequence of program arguments. The program to execute is
+ the string or the first item in the args sequence.
+ cwd: If not None, the subprocess's current directory will be changed to
+ |cwd| before it's executed.
+
+ Returns:
+ Return code from the command execution.
+ """
+ if not quiet:
+ logging.debug(' '.join(args) + ' ' + (cwd or ''))
+ with open(os.devnull, 'w') as devnull:
+ p = subprocess.Popen(args=args, cwd=cwd, stdout=devnull,
+ stderr=devnull, stdin=devnull, shell=False)
+ return p.wait()
+
+def GetAllCmdOutput(args, cwd=None, quiet=False):
+ """Open a subprocess to execute a program and returns its output.
+
+ Args:
+ args: A string or a sequence of program arguments. The program to execute is
+ the string or the first item in the args sequence.
+ cwd: If not None, the subprocess's current directory will be changed to
+ |cwd| before it's executed.
+
+ Returns:
+ Captures and returns the command's stdout.
+ Prints the command's stderr to logger (which defaults to stdout).
+ """
+ if not quiet:
+ logging.debug(' '.join(args) + ' ' + (cwd or ''))
+ with open(os.devnull, 'w') as devnull:
+ p = subprocess.Popen(args=args, cwd=cwd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, stdin=devnull)
+ stdout, stderr = p.communicate()
+ if not quiet:
+ logging.debug(' > stdout=[%s], stderr=[%s]', stdout, stderr)
+ return stdout, stderr
+
+def HasSSH():
+ try:
+ RunCmd(['ssh'], quiet=True)
+ RunCmd(['scp'], quiet=True)
+ logging.debug("HasSSH()->True")
+ return True
+ except OSError:
+ logging.debug("HasSSH()->False")
+ return False
+
+class LoginException(Exception):
+ pass
+
+class KeylessLoginRequiredException(LoginException):
+ pass
+
+class CrOSInterface(object):
+ # pylint: disable=R0923
+ def __init__(self, hostname = None, ssh_identity = None):
+ self._hostname = hostname
+ # List of ports generated from GetRemotePort() that may not be in use yet.
+ self._reserved_ports = []
+
+ if self.local:
+ return
+
+ self._ssh_identity = None
+ self._hostfile = tempfile.NamedTemporaryFile()
+ self._hostfile.flush()
+ self._ssh_args = ['-o ConnectTimeout=5',
+ '-o StrictHostKeyChecking=no',
+ '-o KbdInteractiveAuthentication=no',
+ '-o PreferredAuthentications=publickey',
+ '-o UserKnownHostsFile=%s' % self._hostfile.name]
+
+ if ssh_identity:
+ self._ssh_identity = os.path.abspath(os.path.expanduser(ssh_identity))
+
+ @property
+ def local(self):
+ return not self._hostname
+
+ @property
+ def hostname(self):
+ return self._hostname
+
+ def FormSSHCommandLine(self, args, extra_ssh_args=None):
+ if self.local:
+ # We run the command through the shell locally for consistency with
+ # how commands are run through SSH (crbug.com/239161). This work
+ # around will be unnecessary once we implement a persistent SSH
+ # connection to run remote commands (crbug.com/239607).
+ return ['sh', '-c', " ".join(args)]
+
+ full_args = ['ssh',
+ '-o ForwardX11=no',
+ '-o ForwardX11Trusted=no',
+ '-n'] + self._ssh_args
+ if self._ssh_identity is not None:
+ full_args.extend(['-i', self._ssh_identity])
+ if extra_ssh_args:
+ full_args.extend(extra_ssh_args)
+ full_args.append('root@%s' % self._hostname)
+ full_args.extend(args)
+ return full_args
+
+ def _RemoveSSHWarnings(self, toClean):
+ """Removes specific ssh warning lines from a string.
+
+ Args:
+ toClean: A string that may be containing multiple lines.
+
+ Returns:
+ A copy of toClean with all the Warning lines removed.
+ """
+ # Remove the Warning about connecting to a new host for the first time.
+ return re.sub('Warning: Permanently added [^\n]* to the list of known '
+ 'hosts.\s\n', '', toClean)
+
+ def RunCmdOnDevice(self, args, cwd=None, quiet=False):
+ stdout, stderr = GetAllCmdOutput(
+ self.FormSSHCommandLine(args), cwd, quiet=quiet)
+ # The initial login will add the host to the hosts file but will also print
+ # a warning to stderr that we need to remove.
+ stderr = self._RemoveSSHWarnings(stderr)
+ return stdout, stderr
+
+ def TryLogin(self):
+ logging.debug('TryLogin()')
+ assert not self.local
+ stdout, stderr = self.RunCmdOnDevice(['echo', '$USER'], quiet=True)
+ if stderr != '':
+ if 'Host key verification failed' in stderr:
+ raise LoginException(('%s host key verification failed. ' +
+ 'SSH to it manually to fix connectivity.') %
+ self._hostname)
+ if 'Operation timed out' in stderr:
+ raise LoginException('Timed out while logging into %s' % self._hostname)
+ if 'UNPROTECTED PRIVATE KEY FILE!' in stderr:
+ raise LoginException('Permissions for %s are too open. To fix this,\n'
+ 'chmod 600 %s' % (self._ssh_identity,
+ self._ssh_identity))
+ if 'Permission denied (publickey,keyboard-interactive)' in stderr:
+ raise KeylessLoginRequiredException(
+ 'Need to set up ssh auth for %s' % self._hostname)
+ raise LoginException('While logging into %s, got %s' % (
+ self._hostname, stderr))
+ if stdout != 'root\n':
+ raise LoginException(
+ 'Logged into %s, expected $USER=root, but got %s.' % (
+ self._hostname, stdout))
+
+ def FileExistsOnDevice(self, file_name):
+ if self.local:
+ return os.path.exists(file_name)
+
+ stdout, stderr = self.RunCmdOnDevice([
+ 'if', 'test', '-e', file_name, ';',
+ 'then', 'echo', '1', ';',
+ 'fi'
+ ], quiet=True)
+ if stderr != '':
+ if "Connection timed out" in stderr:
+ raise OSError('Machine wasn\'t responding to ssh: %s' %
+ stderr)
+ raise OSError('Unepected error: %s' % stderr)
+ exists = stdout == '1\n'
+ logging.debug("FileExistsOnDevice(<text>, %s)->%s" % (file_name, exists))
+ return exists
+
+ def PushFile(self, filename, remote_filename):
+ if self.local:
+ args = ['cp', '-r', filename, remote_filename]
+ stdout, stderr = GetAllCmdOutput(args, quiet=True)
+ if stderr != '':
+ raise OSError('No such file or directory %s' % stderr)
+ return
+
+ args = ['scp', '-r' ] + self._ssh_args
+ if self._ssh_identity:
+ args.extend(['-i', self._ssh_identity])
+
+ args.extend([os.path.abspath(filename),
+ 'root@%s:%s' % (self._hostname, remote_filename)])
+
+ stdout, stderr = GetAllCmdOutput(args, quiet=True)
+ stderr = self._RemoveSSHWarnings(stderr)
+ if stderr != '':
+ raise OSError('No such file or directory %s' % stderr)
+
+ def PushContents(self, text, remote_filename):
+ logging.debug("PushContents(<text>, %s)" % remote_filename)
+ with tempfile.NamedTemporaryFile() as f:
+ f.write(text)
+ f.flush()
+ self.PushFile(f.name, remote_filename)
+
+ def GetFileContents(self, filename):
+ assert not self.local
+ with tempfile.NamedTemporaryFile() as f:
+ args = ['scp'] + self._ssh_args
+ if self._ssh_identity:
+ args.extend(['-i', self._ssh_identity])
+
+ args.extend(['root@%s:%s' % (self._hostname, filename),
+ os.path.abspath(f.name)])
+
+ stdout, stderr = GetAllCmdOutput(args, quiet=True)
+ stderr = self._RemoveSSHWarnings(stderr)
+
+ if stderr != '':
+ raise OSError('No such file or directory %s' % stderr)
+
+ with open(f.name, 'r') as f2:
+ res = f2.read()
+ logging.debug("GetFileContents(%s)->%s" % (filename, res))
+ return res
+
+ def ListProcesses(self):
+ """Returns (pid, cmd, ppid, state) of all processes on the device."""
+ stdout, stderr = self.RunCmdOnDevice([
+ '/bin/ps', '--no-headers',
+ '-A',
+ '-o', 'pid,ppid,args,state'], quiet=True)
+ assert stderr == '', stderr
+ procs = []
+ for l in stdout.split('\n'): # pylint: disable=E1103
+ if l == '':
+ continue
+ m = re.match('^\s*(\d+)\s+(\d+)\s+(.+)\s+(.+)', l, re.DOTALL)
+ assert m
+ procs.append((int(m.group(1)), m.group(3), int(m.group(2)), m.group(4)))
+ logging.debug("ListProcesses(<predicate>)->[%i processes]" % len(procs))
+ return procs
+
+ def RmRF(self, filename):
+ logging.debug("rm -rf %s" % filename)
+ self.RunCmdOnDevice(['rm', '-rf', filename], quiet=True)
+
+ def KillAllMatching(self, predicate):
+ kills = ['kill', '-KILL']
+ for pid, cmd, _, _ in self.ListProcesses():
+ if predicate(cmd):
+ logging.info('Killing %s, pid %d' % cmd, pid)
+ kills.append(pid)
+ logging.debug("KillAllMatching(<predicate>)->%i" % (len(kills) - 2))
+ if len(kills) > 2:
+ self.RunCmdOnDevice(kills, quiet=True)
+ return len(kills) - 2
+
+ def IsServiceRunning(self, service_name):
+ stdout, stderr = self.RunCmdOnDevice([
+ 'status', service_name], quiet=True)
+ assert stderr == '', stderr
+ running = 'running, process' in stdout
+ logging.debug("IsServiceRunning(%s)->%s" % (service_name, running))
+ return running
+
+ def GetRemotePort(self):
+ netstat = self.RunCmdOnDevice(['netstat', '-ant'])
+ netstat = netstat[0].split('\n')
+ ports_in_use = []
+
+ for line in netstat[2:]:
+ if not line:
+ continue
+ address_in_use = line.split()[3]
+ port_in_use = address_in_use.split(':')[-1]
+ ports_in_use.append(int(port_in_use))
+
+ ports_in_use.extend(self._reserved_ports)
+
+ new_port = sorted(ports_in_use)[-1] + 1
+ self._reserved_ports.append(new_port)
+
+ return new_port
+
+ def IsHTTPServerRunningOnPort(self, port):
+ wget_output = self.RunCmdOnDevice(
+ ['wget', 'localhost:%i' % (port), '-T1', '-t1'])
+
+ if 'Connection refused' in wget_output[1]:
+ return False
+
+ return True
+
+ def FilesystemMountedAt(self, path):
+ """Returns the filesystem mounted at |path|"""
+ df_out, _ = self.RunCmdOnDevice(['/bin/df', path])
+ df_ary = df_out.split('\n')
+ # 3 lines for title, mount info, and empty line.
+ if len(df_ary) == 3:
+ line_ary = df_ary[1].split()
+ if line_ary:
+ return line_ary[0]
+ return None
+
+ def TakeScreenShot(self, screenshot_prefix):
+ """Takes a screenshot, useful for debugging failures."""
+ # TODO(achuith): Find a better location for screenshots. Cros autotests
+ # upload everything in /var/log so use /var/log/screenshots for now.
+ SCREENSHOT_DIR = '/var/log/screenshots/'
+ SCREENSHOT_EXT = '.png'
+
+ self.RunCmdOnDevice(['mkdir', '-p', SCREENSHOT_DIR])
+ for i in xrange(25):
+ screenshot_file = ('%s%s-%d%s' %
+ (SCREENSHOT_DIR, screenshot_prefix, i, SCREENSHOT_EXT))
+ if not self.FileExistsOnDevice(screenshot_file):
+ self.RunCmdOnDevice([
+ 'DISPLAY=:0.0 XAUTHORITY=/home/chronos/.Xauthority '
+ '/usr/local/bin/import',
+ '-window root',
+ '-depth 8',
+ screenshot_file])
+ return
+ logging.warning('screenshot directory full.')
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/cros_interface_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/cros_interface_unittest.py
new file mode 100644
index 00000000000..994b05192c0
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/cros_interface_unittest.py
@@ -0,0 +1,158 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(nduca): Rewrite what some of these tests to use mocks instead of
+# actually talking to the device. This would improve our coverage quite
+# a bit.
+import unittest
+import socket
+import sys
+
+from telemetry.core import util
+from telemetry.core.chrome import cros_browser_backend
+from telemetry.core.chrome import cros_interface
+from telemetry.unittest import options_for_unittests
+from telemetry.unittest import RequiresBrowserOfType
+
+class CrOSInterfaceTest(unittest.TestCase):
+ @RequiresBrowserOfType('cros-chrome')
+ def testPushContents(self):
+ remote = options_for_unittests.GetCopy().cros_remote
+ cri = cros_interface.CrOSInterface(
+ remote,
+ options_for_unittests.GetCopy().cros_ssh_identity)
+ cri.RunCmdOnDevice(['rm', '-rf', '/tmp/testPushContents'])
+ cri.PushContents('hello world', '/tmp/testPushContents')
+ contents = cri.GetFileContents('/tmp/testPushContents')
+ self.assertEquals(contents, 'hello world')
+
+ @RequiresBrowserOfType('cros-chrome')
+ def testExists(self):
+ remote = options_for_unittests.GetCopy().cros_remote
+ cri = cros_interface.CrOSInterface(
+ remote,
+ options_for_unittests.GetCopy().cros_ssh_identity)
+ self.assertTrue(cri.FileExistsOnDevice('/proc/cpuinfo'))
+ self.assertTrue(cri.FileExistsOnDevice('/etc/passwd'))
+ self.assertFalse(cri.FileExistsOnDevice('/etc/sdlfsdjflskfjsflj'))
+
+ def testExistsLocal(self):
+ if not sys.platform.startswith('linux'):
+ return
+
+ cri = cros_interface.CrOSInterface()
+ self.assertTrue(cri.FileExistsOnDevice('/proc/cpuinfo'))
+ self.assertTrue(cri.FileExistsOnDevice('/etc/passwd'))
+ self.assertFalse(cri.FileExistsOnDevice('/etc/sdlfsdjflskfjsflj'))
+
+ @RequiresBrowserOfType('cros-chrome')
+ def testGetFileContents(self): # pylint: disable=R0201
+ remote = options_for_unittests.GetCopy().cros_remote
+ cri = cros_interface.CrOSInterface(
+ remote,
+ options_for_unittests.GetCopy().cros_ssh_identity)
+ hosts = cri.GetFileContents('/etc/hosts')
+ assert hosts.startswith('# /etc/hosts')
+
+ @RequiresBrowserOfType('cros-chrome')
+ def testGetFileContentsForSomethingThatDoesntExist(self):
+ remote = options_for_unittests.GetCopy().cros_remote
+ cri = cros_interface.CrOSInterface(
+ remote,
+ options_for_unittests.GetCopy().cros_ssh_identity)
+ self.assertRaises(
+ OSError,
+ lambda: cri.GetFileContents('/tmp/209fuslfskjf/dfsfsf'))
+
+ @RequiresBrowserOfType('cros-chrome')
+ def testIsServiceRunning(self):
+ remote = options_for_unittests.GetCopy().cros_remote
+ cri = cros_interface.CrOSInterface(
+ remote,
+ options_for_unittests.GetCopy().cros_ssh_identity)
+
+ self.assertTrue(cri.IsServiceRunning('openssh-server'))
+
+ def testIsServiceRunningLocal(self):
+ if not sys.platform.startswith('linux'):
+ return
+ cri = cros_interface.CrOSInterface()
+ self.assertTrue(cri.IsServiceRunning('dbus'))
+
+ @RequiresBrowserOfType('cros-chrome')
+ def testGetRemotePortAndIsHTTPServerRunningOnPort(self):
+ remote = options_for_unittests.GetCopy().cros_remote
+ cri = cros_interface.CrOSInterface(
+ remote,
+ options_for_unittests.GetCopy().cros_ssh_identity)
+
+ # Create local server.
+ sock = socket.socket()
+ sock.bind(('', 0))
+ port = sock.getsockname()[1]
+ sock.listen(0)
+
+ # Get remote port and ensure that it was unused.
+ remote_port = cri.GetRemotePort()
+ self.assertFalse(cri.IsHTTPServerRunningOnPort(remote_port))
+
+ # Forward local server's port to remote device's remote_port.
+ forwarder = cros_browser_backend.SSHForwarder(
+ cri, 'R', util.PortPair(port, remote_port))
+
+ # At this point, remote device should be able to connect to local server.
+ self.assertTrue(cri.IsHTTPServerRunningOnPort(remote_port))
+
+ # Next remote port shouldn't be the same as remote_port, since remote_port
+ # is now in use.
+ self.assertTrue(cri.GetRemotePort() != remote_port)
+
+ # Close forwarder and local server ports.
+ forwarder.Close()
+ sock.close()
+
+ # Device should no longer be able to connect to remote_port since it is no
+ # longer in use.
+ self.assertFalse(cri.IsHTTPServerRunningOnPort(remote_port))
+
+ @RequiresBrowserOfType('cros-chrome')
+ def testGetRemotePortReservedPorts(self):
+ remote = options_for_unittests.GetCopy().cros_remote
+ cri = cros_interface.CrOSInterface(
+ remote,
+ options_for_unittests.GetCopy().cros_ssh_identity)
+
+ # Should return 2 separate ports even though the first one isn't technically
+ # being used yet.
+ remote_port_1 = cri.GetRemotePort()
+ remote_port_2 = cri.GetRemotePort()
+
+ self.assertTrue(remote_port_1 != remote_port_2)
+
+ # TODO(tengs): It would be best if we can filter this test and other tests
+ # that need to be run locally based on the platform of the system browser.
+ def testEscapeCmdArguments(self):
+ ''' Commands and their arguments that are executed through the cros
+ interface should follow bash syntax. This test needs to run on remotely
+ and locally on the device to check for consistency.
+ '''
+ if not sys.platform.startswith('linux'):
+ return
+
+ cri = cros_interface.CrOSInterface(
+ options_for_unittests.GetCopy().cros_remote,
+ options_for_unittests.GetCopy().cros_ssh_identity)
+
+ # Check arguments with no special characters
+ stdout, _ = cri.RunCmdOnDevice(['echo', '--arg1=value1', '--arg2=value2',
+ '--arg3="value3"'])
+ assert(stdout.strip() == '--arg1=value1 --arg2=value2 --arg3=value3')
+
+ # Check argument with special characters escaped
+ stdout, _ = cri.RunCmdOnDevice(['echo', '--arg=A\\; echo \\"B\\"'])
+ assert(stdout.strip() == '--arg=A; echo "B"')
+
+ # Check argument with special characters in quotes
+ stdout, _ = cri.RunCmdOnDevice(['echo', "--arg='$HOME;;$PATH'"])
+ assert(stdout.strip() == "--arg=$HOME;;$PATH")
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/crx_id.py b/chromium/tools/telemetry/telemetry/core/chrome/crx_id.py
new file mode 100644
index 00000000000..ebff59c520e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/crx_id.py
@@ -0,0 +1,18 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from __future__ import absolute_import
+
+import os
+import sys
+
+def __init__():
+ path = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
+ sys.path.append(path)
+
+__init__()
+
+from crx_id import crx_id # pylint: disable=F0401
+GetCRXAppID = crx_id.GetCRXAppID
+HasPublicKey = crx_id.HasPublicKey \ No newline at end of file
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_backend.py
new file mode 100644
index 00000000000..834278d015f
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_backend.py
@@ -0,0 +1,190 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import subprocess as subprocess
+import shutil
+import sys
+import tempfile
+
+from telemetry.core import util
+from telemetry.core.backends import browser_backend
+from telemetry.core.backends.chrome import chrome_browser_backend
+
+class DesktopBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
+ """The backend for controlling a locally-executed browser instance, on Linux,
+ Mac or Windows.
+ """
+ def __init__(self, options, executable, flash_path, is_content_shell,
+ browser_directory, delete_profile_dir_after_run=True):
+ super(DesktopBrowserBackend, self).__init__(
+ is_content_shell=is_content_shell,
+ supports_extensions=not is_content_shell,
+ options=options)
+
+ # Initialize fields so that an explosion during init doesn't break in Close.
+ self._proc = None
+ self._tmpdir = None
+ self._tmp_output_file = None
+
+ self._executable = executable
+ if not self._executable:
+ raise Exception('Cannot create browser, no executable found!')
+
+ self._flash_path = flash_path
+ if self._flash_path and not os.path.exists(self._flash_path):
+ logging.warning(('Could not find flash at %s. Running without flash.\n\n'
+ 'To fix this see http://go/read-src-internal') %
+ self._flash_path)
+ self._flash_path = None
+
+ if len(options.extensions_to_load) > 0 and is_content_shell:
+ raise browser_backend.ExtensionsNotSupportedException(
+ 'Content shell does not support extensions.')
+
+ self._browser_directory = browser_directory
+ self._port = util.GetAvailableLocalPort()
+ self._profile_dir = None
+ self._supports_net_benchmarking = True
+ self._delete_profile_dir_after_run = delete_profile_dir_after_run
+
+ self._SetupProfile()
+
+ def _SetupProfile(self):
+ if not self.options.dont_override_profile:
+ self._tmpdir = tempfile.mkdtemp()
+ profile_dir = self._profile_dir or self.options.profile_dir
+ if profile_dir:
+ if self.is_content_shell:
+ logging.critical('Profiles cannot be used with content shell')
+ sys.exit(1)
+ shutil.rmtree(self._tmpdir)
+ shutil.copytree(profile_dir, self._tmpdir)
+
+ def _LaunchBrowser(self):
+ args = [self._executable]
+ args.extend(self.GetBrowserStartupArgs())
+ if not self.options.show_stdout:
+ self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
+ self._proc = subprocess.Popen(
+ args, stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
+ else:
+ self._proc = subprocess.Popen(args)
+
+ try:
+ self._WaitForBrowserToComeUp()
+ self._PostBrowserStartupInitialization()
+ except:
+ self.Close()
+ raise
+
+ def GetBrowserStartupArgs(self):
+ args = super(DesktopBrowserBackend, self).GetBrowserStartupArgs()
+ args.append('--remote-debugging-port=%i' % self._port)
+ if not self.is_content_shell:
+ args.append('--window-size=1280,1024')
+ if self._flash_path:
+ args.append('--ppapi-flash-path=%s' % self._flash_path)
+ if self._supports_net_benchmarking:
+ args.append('--enable-net-benchmarking')
+ else:
+ args.append('--enable-benchmarking')
+ if not self.options.dont_override_profile:
+ args.append('--user-data-dir=%s' % self._tmpdir)
+ return args
+
+ def SetProfileDirectory(self, profile_dir):
+ # Make sure _profile_dir hasn't already been set.
+ assert self._profile_dir is None
+
+ if self.is_content_shell:
+ logging.critical('Profile creation cannot be used with content shell')
+ sys.exit(1)
+
+ self._profile_dir = profile_dir
+
+ def Start(self):
+ self._LaunchBrowser()
+
+ # For old chrome versions, might have to relaunch to have the
+ # correct net_benchmarking switch.
+ if self._chrome_branch_number < 1418:
+ self.Close()
+ self._supports_net_benchmarking = False
+ self._LaunchBrowser()
+
+ @property
+ def pid(self):
+ if self._proc:
+ return self._proc.pid
+ return None
+
+ @property
+ def browser_directory(self):
+ return self._browser_directory
+
+ @property
+ def profile_directory(self):
+ return self._tmpdir
+
+ def IsBrowserRunning(self):
+ return self._proc.poll() == None
+
+ def GetStandardOutput(self):
+ assert self._tmp_output_file, "Can't get standard output with show_stdout"
+ self._tmp_output_file.flush()
+ try:
+ with open(self._tmp_output_file.name) as f:
+ return f.read()
+ except IOError:
+ return ''
+
+ def GetStackTrace(self):
+ # crbug.com/223572, symbolize stack trace for desktop browsers.
+ logging.warning('Stack traces not supported on desktop browsers, '
+ 'returning stdout')
+ return self.GetStandardOutput()
+
+ def __del__(self):
+ self.Close()
+
+ def Close(self):
+ super(DesktopBrowserBackend, self).Close()
+
+ if self._proc:
+
+ def IsClosed():
+ if not self._proc:
+ return True
+ return self._proc.poll() != None
+
+ # Try to politely shutdown, first.
+ self._proc.terminate()
+ try:
+ util.WaitFor(IsClosed, timeout=1)
+ self._proc = None
+ except util.TimeoutException:
+ pass
+
+ # Kill it.
+ if not IsClosed():
+ self._proc.kill()
+ try:
+ util.WaitFor(IsClosed, timeout=5)
+ self._proc = None
+ except util.TimeoutException:
+ self._proc = None
+ raise Exception('Could not shutdown the browser.')
+
+ if self._delete_profile_dir_after_run and \
+ self._tmpdir and os.path.exists(self._tmpdir):
+ shutil.rmtree(self._tmpdir, ignore_errors=True)
+ self._tmpdir = None
+
+ if self._tmp_output_file:
+ self._tmp_output_file.close()
+ self._tmp_output_file = None
+
+ def CreateForwarder(self, *port_pairs):
+ return browser_backend.DoNothingForwarder(*port_pairs)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder.py b/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder.py
new file mode 100644
index 00000000000..93f33d8c677
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder.py
@@ -0,0 +1,254 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Finds desktop browsers that can be controlled by telemetry."""
+
+import logging
+from operator import attrgetter
+import os
+import platform
+import subprocess
+import sys
+
+from telemetry.core import browser
+from telemetry.core import platform as core_platform
+from telemetry.core import possible_browser
+from telemetry.core import profile_types
+from telemetry.core import util
+from telemetry.core.chrome import cros_interface
+from telemetry.core.chrome import desktop_browser_backend
+
+ALL_BROWSER_TYPES = ','.join([
+ 'exact',
+ 'release',
+ 'release_x64',
+ 'debug',
+ 'debug_x64',
+ 'canary',
+ 'content-shell-debug',
+ 'content-shell-release',
+ 'system'])
+
+class PossibleDesktopBrowser(possible_browser.PossibleBrowser):
+ """A desktop browser that can be controlled."""
+
+ def __init__(self, browser_type, options, executable, flash_path,
+ is_content_shell, browser_directory, is_local_build=False):
+ super(PossibleDesktopBrowser, self).__init__(browser_type, options)
+ self._local_executable = executable
+ self._flash_path = flash_path
+ self._is_content_shell = is_content_shell
+ self._browser_directory = browser_directory
+ self.is_local_build = is_local_build
+
+ def __repr__(self):
+ return 'PossibleDesktopBrowser(browser_type=%s)' % self.browser_type
+
+ # Constructs a browser.
+ # Returns a touple of the form: (browser, backend)
+ def _CreateBrowserInternal(self, delete_profile_dir_after_run):
+ backend = desktop_browser_backend.DesktopBrowserBackend(
+ self._options, self._local_executable, self._flash_path,
+ self._is_content_shell, self._browser_directory,
+ delete_profile_dir_after_run=delete_profile_dir_after_run)
+ b = browser.Browser(backend,
+ core_platform.CreatePlatformBackendForCurrentOS())
+ return b
+
+ def Create(self):
+ # If a dirty profile is needed, instantiate an initial browser object and
+ # use that to create a dirty profile.
+ creator_class = profile_types.GetProfileCreator(self.options.profile_type)
+ if creator_class:
+ logging.info(
+ 'Creating a dirty profile of type: %s', self.options.profile_type)
+ (b, backend) = \
+ self._CreateBrowserInternal(delete_profile_dir_after_run=False)
+ with b as b:
+ creator = creator_class(b)
+ creator.CreateProfile()
+ dirty_profile_dir = backend.profile_directory
+ logging.info(
+ "Dirty profile created succesfully in '%s'", dirty_profile_dir)
+
+ # Now create another browser to run tests on using the dirty profile
+ # we just created.
+ b = self._CreateBrowserInternal(delete_profile_dir_after_run=True)
+ backend.SetProfileDirectory(dirty_profile_dir)
+ else:
+ b = self._CreateBrowserInternal(delete_profile_dir_after_run=True)
+ return b
+
+ def SupportsOptions(self, options):
+ if (len(options.extensions_to_load) != 0) and self._is_content_shell:
+ return False
+ return True
+
+ @property
+ def last_modification_time(self):
+ if os.path.exists(self._local_executable):
+ return os.path.getmtime(self._local_executable)
+ return -1
+
+def SelectDefaultBrowser(possible_browsers):
+ local_builds_by_date = [
+ b for b in sorted(possible_browsers,
+ key=attrgetter('last_modification_time'))
+ if b.is_local_build]
+ if local_builds_by_date:
+ return local_builds_by_date[-1]
+ return None
+
+def CanFindAvailableBrowsers():
+ return not cros_interface.IsRunningOnCrosDevice()
+
+def FindAllAvailableBrowsers(options):
+ """Finds all the desktop browsers available on this machine."""
+ browsers = []
+
+ if not CanFindAvailableBrowsers():
+ return []
+
+ has_display = True
+ if (sys.platform.startswith('linux') and
+ os.getenv('DISPLAY') == None):
+ has_display = False
+
+ # Look for a browser in the standard chrome build locations.
+ if options.chrome_root:
+ chrome_root = options.chrome_root
+ else:
+ chrome_root = util.GetChromiumSrcDir()
+
+ if sys.platform == 'darwin':
+ chromium_app_name = 'Chromium.app/Contents/MacOS/Chromium'
+ content_shell_app_name = 'Content Shell.app/Contents/MacOS/Content Shell'
+ mac_dir = 'mac'
+ if platform.architecture()[0] == '64bit':
+ mac_dir = 'mac_64'
+ flash_path = os.path.join(
+ chrome_root, 'third_party', 'adobe', 'flash', 'binaries', 'ppapi',
+ mac_dir, 'PepperFlashPlayer.plugin')
+ elif sys.platform.startswith('linux'):
+ chromium_app_name = 'chrome'
+ content_shell_app_name = 'content_shell'
+ linux_dir = 'linux'
+ if platform.architecture()[0] == '64bit':
+ linux_dir = 'linux_x64'
+ flash_path = os.path.join(
+ chrome_root, 'third_party', 'adobe', 'flash', 'binaries', 'ppapi',
+ linux_dir, 'libpepflashplayer.so')
+ elif sys.platform.startswith('win'):
+ chromium_app_name = 'chrome.exe'
+ content_shell_app_name = 'content_shell.exe'
+ win_dir = 'win'
+ if platform.architecture()[0] == '64bit':
+ win_dir = 'win_x64'
+ flash_path = os.path.join(
+ chrome_root, 'third_party', 'adobe', 'flash', 'binaries', 'ppapi',
+ win_dir, 'pepflashplayer.dll')
+ else:
+ raise Exception('Platform not recognized')
+
+ def IsExecutable(path):
+ return os.path.isfile(path) and os.access(path, os.X_OK)
+
+ # Add the explicit browser executable if given.
+ if options.browser_executable:
+ normalized_executable = os.path.expanduser(options.browser_executable)
+ if IsExecutable(normalized_executable):
+ browser_directory = os.path.dirname(options.browser_executable)
+ browsers.append(PossibleDesktopBrowser('exact', options,
+ normalized_executable, flash_path,
+ False, browser_directory))
+ else:
+ logging.warning('%s specified by browser_executable does not exist',
+ normalized_executable)
+
+ def AddIfFound(browser_type, build_dir, type_dir, app_name, content_shell):
+ browser_directory = os.path.join(chrome_root, build_dir, type_dir)
+ app = os.path.join(browser_directory, app_name)
+ if IsExecutable(app):
+ browsers.append(PossibleDesktopBrowser(browser_type, options,
+ app, flash_path, content_shell,
+ browser_directory,
+ is_local_build=True))
+ return True
+ return False
+
+ # Add local builds
+ for build_dir, build_type in util.GetBuildDirectories():
+ AddIfFound(build_type.lower(), build_dir, build_type,
+ chromium_app_name, False)
+ AddIfFound('content-shell-' + build_type.lower(), build_dir, build_type,
+ content_shell_app_name, True)
+
+ # Mac-specific options.
+ if sys.platform == 'darwin':
+ mac_canary_root = '/Applications/Google Chrome Canary.app/'
+ mac_canary = mac_canary_root + 'Contents/MacOS/Google Chrome Canary'
+ mac_system_root = '/Applications/Google Chrome.app'
+ mac_system = mac_system_root + '/Contents/MacOS/Google Chrome'
+ if IsExecutable(mac_canary):
+ browsers.append(PossibleDesktopBrowser('canary', options,
+ mac_canary, None, False,
+ mac_canary_root))
+
+ if IsExecutable(mac_system):
+ browsers.append(PossibleDesktopBrowser('system', options,
+ mac_system, None, False,
+ mac_system_root))
+
+ # Linux specific options.
+ if sys.platform.startswith('linux'):
+ # Look for a google-chrome instance.
+ found = False
+ try:
+ with open(os.devnull, 'w') as devnull:
+ found = subprocess.call(['google-chrome', '--version'],
+ stdout=devnull, stderr=devnull) == 0
+ except OSError:
+ pass
+ if found:
+ browsers.append(PossibleDesktopBrowser('system', options,
+ 'google-chrome', None, False,
+ '/opt/google/chrome'))
+
+ # Win32-specific options.
+ if sys.platform.startswith('win'):
+ system_path = os.path.join('Google', 'Chrome', 'Application')
+ canary_path = os.path.join('Google', 'Chrome SxS', 'Application')
+
+ win_search_paths = [os.getenv('PROGRAMFILES(X86)'),
+ os.getenv('PROGRAMFILES'),
+ os.getenv('LOCALAPPDATA')]
+
+ def AddIfFoundWin(browser_name, app_path):
+ browser_directory = os.path.join(path, app_path)
+ app = os.path.join(browser_directory, chromium_app_name)
+ if IsExecutable(app):
+ browsers.append(PossibleDesktopBrowser(browser_name, options,
+ app, flash_path, False,
+ browser_directory))
+ return True
+ return False
+
+ for path in win_search_paths:
+ if not path:
+ continue
+ if AddIfFoundWin('canary', canary_path):
+ break
+
+ for path in win_search_paths:
+ if not path:
+ continue
+ if AddIfFoundWin('system', system_path):
+ break
+
+ if len(browsers) and not has_display:
+ logging.warning(
+ 'Found (%s), but you do not have a DISPLAY environment set.' %
+ ','.join([b.browser_type for b in browsers]))
+ return []
+
+ return browsers
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder_unittest.py
new file mode 100644
index 00000000000..fe0e6ae3379
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/desktop_browser_finder_unittest.py
@@ -0,0 +1,188 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.core import browser_options
+from telemetry.core.chrome import desktop_browser_finder
+from telemetry.unittest import system_stub
+
+# This file verifies the logic for finding a browser instance on all platforms
+# at once. It does so by providing stubs for the OS/sys/subprocess primitives
+# that the underlying finding logic usually uses to locate a suitable browser.
+# We prefer this approach to having to run the same test on every platform on
+# which we want this code to work.
+
+class FindTestBase(unittest.TestCase):
+ def setUp(self):
+ self._options = browser_options.BrowserOptions()
+ self._options.chrome_root = '../../../'
+ self._stubs = system_stub.Override(desktop_browser_finder,
+ ['os', 'subprocess', 'sys'])
+
+ def tearDown(self):
+ self._stubs.Restore()
+
+ @property
+ def _files(self):
+ return self._stubs.os.path.files
+
+ def DoFindAll(self):
+ return desktop_browser_finder.FindAllAvailableBrowsers(self._options)
+
+ def DoFindAllTypes(self):
+ browsers = self.DoFindAll()
+ return [b.browser_type for b in browsers]
+
+def has_type(array, browser_type):
+ return len([x for x in array if x.browser_type == browser_type]) != 0
+
+class FindSystemTest(FindTestBase):
+ def setUp(self):
+ super(FindSystemTest, self).setUp()
+ self._stubs.sys.platform = 'win32'
+
+ def testFindProgramFiles(self):
+ self._files.append(
+ 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe')
+ self._stubs.os.program_files = 'C:\\Program Files'
+ self.assertTrue('system' in self.DoFindAllTypes())
+
+ def testFindProgramFilesX86(self):
+ self._files.append(
+ 'C:\\Program Files(x86)\\Google\\Chrome\\Application\\chrome.exe')
+ self._stubs.os.program_files_x86 = 'C:\\Program Files(x86)'
+ self.assertTrue('system' in self.DoFindAllTypes())
+
+ def testFindLocalAppData(self):
+ self._files.append(
+ 'C:\\Local App Data\\Google\\Chrome\\Application\\chrome.exe')
+ self._stubs.os.local_app_data = 'C:\\Local App Data'
+ self.assertTrue('system' in self.DoFindAllTypes())
+
+class FindLocalBuildsTest(FindTestBase):
+ def setUp(self):
+ super(FindLocalBuildsTest, self).setUp()
+ self._stubs.sys.platform = 'win32'
+
+ def testFindBuild(self):
+ self._files.append('..\\..\\..\\build\\Release\\chrome.exe')
+ self.assertTrue('release' in self.DoFindAllTypes())
+
+ def testFindOut(self):
+ self._files.append('..\\..\\..\\out\\Release\\chrome.exe')
+ self.assertTrue('release' in self.DoFindAllTypes())
+
+ def testFindSconsbuild(self):
+ self._files.append('..\\..\\..\\sconsbuild\\Release\\chrome.exe')
+ self.assertTrue('release' in self.DoFindAllTypes())
+
+ def testFindXcodebuild(self):
+ self._files.append('..\\..\\..\\xcodebuild\\Release\\chrome.exe')
+ self.assertTrue('release' in self.DoFindAllTypes())
+
+class OSXFindTest(FindTestBase):
+ def setUp(self):
+ super(OSXFindTest, self).setUp()
+ self._stubs.sys.platform = 'darwin'
+ self._files.append('/Applications/Google Chrome Canary.app/'
+ 'Contents/MacOS/Google Chrome Canary')
+ self._files.append('/Applications/Google Chrome.app/' +
+ 'Contents/MacOS/Google Chrome')
+ self._files.append(
+ '../../../out/Release/Chromium.app/Contents/MacOS/Chromium')
+ self._files.append(
+ '../../../out/Debug/Chromium.app/Contents/MacOS/Chromium')
+ self._files.append(
+ '../../../out/Release/Content Shell.app/Contents/MacOS/Content Shell')
+ self._files.append(
+ '../../../out/Debug/Content Shell.app/Contents/MacOS/Content Shell')
+
+ def testFindAll(self):
+ types = self.DoFindAllTypes()
+ self.assertEquals(
+ set(types),
+ set(['debug', 'release',
+ 'content-shell-debug', 'content-shell-release',
+ 'canary', 'system']))
+
+
+class LinuxFindTest(FindTestBase):
+ def setUp(self):
+ super(LinuxFindTest, self).setUp()
+
+ self._stubs.sys.platform = 'linux2'
+ self._files.append('/foo/chrome')
+ self._files.append('../../../out/Release/chrome')
+ self._files.append('../../../out/Debug/chrome')
+ self._files.append('../../../out/Release/content_shell')
+ self._files.append('../../../out/Debug/content_shell')
+
+ self.has_google_chrome_on_path = False
+ this = self
+ def call_hook(*args, **kwargs): # pylint: disable=W0613
+ if this.has_google_chrome_on_path:
+ return 0
+ raise OSError('Not found')
+ self._stubs.subprocess.call = call_hook
+
+ def testFindAllWithExact(self):
+ types = self.DoFindAllTypes()
+ self.assertEquals(
+ set(types),
+ set(['debug', 'release',
+ 'content-shell-debug', 'content-shell-release']))
+
+ def testFindWithProvidedExecutable(self):
+ self._options.browser_executable = '/foo/chrome'
+ self.assertTrue('exact' in self.DoFindAllTypes())
+
+ def testFindUsingDefaults(self):
+ self.has_google_chrome_on_path = True
+ self.assertTrue('release' in self.DoFindAllTypes())
+
+ del self._files[1]
+ self.has_google_chrome_on_path = True
+ self.assertTrue('system' in self.DoFindAllTypes())
+
+ self.has_google_chrome_on_path = False
+ del self._files[1]
+ self.assertEquals(['content-shell-debug', 'content-shell-release'],
+ self.DoFindAllTypes())
+
+ def testFindUsingRelease(self):
+ self.assertTrue('release' in self.DoFindAllTypes())
+
+
+class WinFindTest(FindTestBase):
+ def setUp(self):
+ super(WinFindTest, self).setUp()
+
+ self._stubs.sys.platform = 'win32'
+ self._stubs.os.local_app_data = 'c:\\Users\\Someone\\AppData\\Local'
+ self._files.append('c:\\tmp\\chrome.exe')
+ self._files.append('..\\..\\..\\build\\Release\\chrome.exe')
+ self._files.append('..\\..\\..\\build\\Debug\\chrome.exe')
+ self._files.append('..\\..\\..\\build\\Release\\content_shell.exe')
+ self._files.append('..\\..\\..\\build\\Debug\\content_shell.exe')
+ self._files.append(self._stubs.os.local_app_data + '\\' +
+ 'Google\\Chrome\\Application\\chrome.exe')
+ self._files.append(self._stubs.os.local_app_data + '\\' +
+ 'Google\\Chrome SxS\\Application\\chrome.exe')
+
+ def testFindAllGivenDefaults(self):
+ types = self.DoFindAllTypes()
+ self.assertEquals(set(types),
+ set(['debug', 'release',
+ 'content-shell-debug', 'content-shell-release',
+ 'system', 'canary']))
+
+ def testFindAllWithExact(self):
+ self._options.browser_executable = 'c:\\tmp\\chrome.exe'
+ types = self.DoFindAllTypes()
+ self.assertEquals(
+ set(types),
+ set(['exact',
+ 'debug', 'release',
+ 'content-shell-debug', 'content-shell-release',
+ 'system', 'canary']))
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/extension_dict_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/extension_dict_backend.py
new file mode 100644
index 00000000000..d84a995a718
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/extension_dict_backend.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import re
+import weakref
+
+from telemetry.core import extension_page
+from telemetry.core.chrome import inspector_backend
+
+class ExtensionNotFoundException(Exception):
+ pass
+
+class ExtensionDictBackend(object):
+ def __init__(self, browser_backend):
+ self._browser_backend = browser_backend
+ # Maps extension ids to ExtensionPage objects.
+ self._extension_dict = weakref.WeakValueDictionary()
+
+ def __getitem__(self, extension_id):
+ extension_object = self._extension_dict.get(extension_id)
+ if not extension_object:
+ extension_object = self._CreateExtensionObject(extension_id)
+ assert extension_object
+ self._extension_dict[extension_id] = extension_object
+ return extension_object
+
+ def __contains__(self, extension_id):
+ return extension_id in self._GetExtensionIds()
+
+ @staticmethod
+ def _ExtractExtensionId(url):
+ m = re.match(r"(chrome-extension://)([^/]+)", url)
+ assert m
+ return m.group(2)
+
+ @staticmethod
+ def _GetExtensionId(extension_info):
+ if 'url' not in extension_info:
+ return None
+ return ExtensionDictBackend._ExtractExtensionId(extension_info['url'])
+
+ def _CreateExtensionObject(self, extension_id):
+ extension_info = self._FindExtensionInfo(extension_id)
+ if not extension_info or not 'webSocketDebuggerUrl' in extension_info:
+ raise ExtensionNotFoundException()
+ return extension_page.ExtensionPage(
+ self._CreateInspectorBackendForDebuggerUrl(
+ extension_info['webSocketDebuggerUrl']))
+
+ def _CreateInspectorBackendForDebuggerUrl(self, debugger_url):
+ return inspector_backend.InspectorBackend(self._browser_backend.browser,
+ self._browser_backend,
+ debugger_url)
+
+ def _FindExtensionInfo(self, extension_id):
+ for extension_info in self._GetExtensionInfoList():
+ if self._GetExtensionId(extension_info) == extension_id:
+ return extension_info
+ return None
+
+ def _GetExtensionInfoList(self, timeout=None):
+ data = self._browser_backend.Request('', timeout=timeout)
+ return self._FilterExtensions(json.loads(data))
+
+ def _FilterExtensions(self, all_pages):
+ return [page_info for page_info in all_pages
+ if page_info['url'].startswith('chrome-extension://')]
+
+ def _GetExtensionIds(self):
+ return map(self._GetExtensionId, self._GetExtensionInfoList())
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/facebook_credentials_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/facebook_credentials_backend.py
new file mode 100644
index 00000000000..b8821320dc8
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/facebook_credentials_backend.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core.chrome import form_based_credentials_backend
+
+class FacebookCredentialsBackend(
+ form_based_credentials_backend.FormBasedCredentialsBackend):
+ def IsAlreadyLoggedIn(self, tab):
+ return tab.EvaluateJavaScript(
+ 'document.getElementById("fbNotificationsList")!== null || '
+ 'document.getElementById("m_home_notice")!== null')
+
+ @property
+ def credentials_type(self):
+ return 'facebook'
+
+ @property
+ def url(self):
+ return 'http://www.facebook.com/'
+
+ @property
+ def login_form_id(self):
+ return 'login_form'
+
+ @property
+ def login_input_id(self):
+ return 'email'
+
+ @property
+ def password_input_id(self):
+ return 'pass'
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/facebook_credentials_backend_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/facebook_credentials_backend_unittest.py
new file mode 100644
index 00000000000..51a25712459
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/facebook_credentials_backend_unittest.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core.chrome import form_based_credentials_backend_unittest_base
+from telemetry.core.chrome import facebook_credentials_backend
+
+class TestFacebookCredentialsBackend(
+ form_based_credentials_backend_unittest_base.
+ FormBasedCredentialsBackendUnitTestBase):
+ def setUp(self):
+ self._credentials_type = 'facebook'
+
+ def testLoginUsingMock(self):
+ self._LoginUsingMock(
+ facebook_credentials_backend.FacebookCredentialsBackend(),
+ 'http://www.facebook.com/', 'email', 'pass')
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/form_based_credentials_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/form_based_credentials_backend.py
new file mode 100644
index 00000000000..1cc7c75560c
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/form_based_credentials_backend.py
@@ -0,0 +1,110 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+
+from telemetry.core import util
+
+
+def _WaitForLoginFormToLoad(backend, login_form_id, tab):
+ def IsFormLoadedOrAlreadyLoggedIn():
+ return tab.EvaluateJavaScript(
+ 'document.querySelector("#%s")!== null' % login_form_id) or \
+ backend.IsAlreadyLoggedIn(tab)
+
+ # Wait until the form is submitted and the page completes loading.
+ util.WaitFor(lambda: IsFormLoadedOrAlreadyLoggedIn(), # pylint: disable=W0108
+ 60)
+
+def _SubmitFormAndWait(form_id, tab):
+ js = 'document.getElementById("%s").submit();' % form_id
+ tab.ExecuteJavaScript(js)
+
+ def IsLoginStillHappening():
+ return tab.EvaluateJavaScript(
+ 'document.querySelector("#%s")!== null' % form_id)
+
+ # Wait until the form is submitted and the page completes loading.
+ util.WaitFor(lambda: not IsLoginStillHappening(), 60)
+
+class FormBasedCredentialsBackend(object):
+ def __init__(self):
+ self._logged_in = False
+
+ def IsAlreadyLoggedIn(self, tab):
+ raise NotImplementedError()
+
+ @property
+ def credentials_type(self):
+ raise NotImplementedError()
+
+ @property
+ def url(self):
+ raise NotImplementedError()
+
+ @property
+ def login_form_id(self):
+ raise NotImplementedError()
+
+ @property
+ def login_input_id(self):
+ raise NotImplementedError()
+
+ @property
+ def password_input_id(self):
+ raise NotImplementedError()
+
+ def IsLoggedIn(self):
+ return self._logged_in
+
+ def _ResetLoggedInState(self):
+ """Makes the backend think we're not logged in even though we are.
+ Should only be used in unit tests to simulate --dont-override-profile.
+ """
+ self._logged_in = False
+
+ def LoginNeeded(self, tab, config):
+ """Logs in to a test account.
+
+ Raises:
+ RuntimeError: if could not get credential information.
+ """
+ if self._logged_in:
+ return True
+
+ if 'username' not in config or 'password' not in config:
+ message = ('Credentials for "%s" must include username and password.' %
+ self.credentials_type)
+ raise RuntimeError(message)
+
+ logging.debug('Logging into %s account...' % self.credentials_type)
+
+ try:
+ logging.info('Loading %s...', self.url)
+ tab.Navigate(self.url)
+ _WaitForLoginFormToLoad(self, self.login_form_id, tab)
+
+ if self.IsAlreadyLoggedIn(tab):
+ self._logged_in = True
+ return True
+
+ tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
+ logging.info('Loaded page: %s', self.url)
+
+ email_id = 'document.querySelector("#%s").%s.value = "%s"; ' % (
+ self.login_form_id, self.login_input_id, config['username'])
+ password = 'document.querySelector("#%s").%s.value = "%s"; ' % (
+ self.login_form_id, self.password_input_id, config['password'])
+ tab.ExecuteJavaScript(email_id)
+ tab.ExecuteJavaScript(password)
+
+ _SubmitFormAndWait(self.login_form_id, tab)
+
+ self._logged_in = True
+ return True
+ except util.TimeoutException:
+ logging.warning('Timed out while loading: %s', self.url)
+ return False
+
+ def LoginNoLongerNeeded(self, tab): # pylint: disable=W0613
+ assert self._logged_in
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/form_based_credentials_backend_unittest_base.py b/chromium/tools/telemetry/telemetry/core/chrome/form_based_credentials_backend_unittest_base.py
new file mode 100644
index 00000000000..6c6449f24e9
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/form_based_credentials_backend_unittest_base.py
@@ -0,0 +1,128 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import unittest
+
+from telemetry.core import browser_finder
+from telemetry.unittest import simple_mock
+from telemetry.unittest import options_for_unittests
+from telemetry.unittest import DisabledTest
+
+_ = simple_mock.DONT_CARE
+
+
+def _GetCredentialsPath():
+ # TODO: This shouldn't depend on tools/perf.
+ credentials_path = os.path.join(
+ os.path.dirname(__file__),
+ '..', '..', '..', '..', 'perf', 'data', 'credentials.json')
+ if not os.path.exists(credentials_path):
+ return None
+ return credentials_path
+
+
+class FormBasedCredentialsBackendUnitTestBase(unittest.TestCase):
+ def setUp(self):
+ self._credentials_type = None
+
+ @DisabledTest
+ def testRealLoginIfPossible(self):
+ credentials_path = _GetCredentialsPath()
+ if not credentials_path:
+ logging.warning('Credentials file not found, skipping test.')
+ return
+
+ options = options_for_unittests.GetCopy()
+ with browser_finder.FindBrowser(options).Create() as b:
+ b.Start()
+ b.credentials.credentials_path = credentials_path
+ if not b.credentials.CanLogin(self._credentials_type):
+ return
+ ret = b.credentials.LoginNeeded(b.tabs[0], self._credentials_type)
+ self.assertTrue(ret)
+
+ @DisabledTest
+ def testRealLoginWithDontOverrideProfileIfPossible(self):
+ credentials_path = _GetCredentialsPath()
+ if not credentials_path:
+ logging.warning('Credentials file not found, skipping test.')
+ return
+
+ options = options_for_unittests.GetCopy()
+
+ # Login once to make sure our default profile is logged in.
+ with browser_finder.FindBrowser(options).Create() as b:
+ b.Start()
+ b.credentials.credentials_path = credentials_path
+
+ if not b.credentials.CanLogin(self._credentials_type):
+ return
+
+ tab = b.tabs[0]
+
+ # Should not be logged in, since this is a fresh credentials
+ # instance.
+ self.assertFalse(b.credentials.IsLoggedIn(self._credentials_type))
+
+ # Log in.
+ ret = b.credentials.LoginNeeded(tab, self._credentials_type)
+
+ # Make sure login was successful.
+ self.assertTrue(ret)
+ self.assertTrue(b.credentials.IsLoggedIn(self._credentials_type))
+
+ # Reset state. Now the backend thinks we're logged out, even
+ # though we are logged in in our current browser session. This
+ # simulates the effects of running with --dont-override-profile.
+ b.credentials._ResetLoggedInState() # pylint: disable=W0212
+
+ # Make sure the backend thinks we're logged out.
+ self.assertFalse(b.credentials.IsLoggedIn(self._credentials_type))
+ self.assertTrue(b.credentials.CanLogin(self._credentials_type))
+
+ # Attempt to login again. This should detect that we've hit
+ # the 'logged in' page instead of the login form, and succeed
+ # instead of timing out.
+ ret = b.credentials.LoginNeeded(tab, self._credentials_type)
+
+ # Make sure our login attempt did in fact succeed and set the
+ # backend's internal state to 'logged in'.
+ self.assertTrue(ret)
+ self.assertTrue(b.credentials.IsLoggedIn(self._credentials_type))
+
+ def testLoginUsingMock(self):
+ raise NotImplementedError()
+
+ def _LoginUsingMock(self, backend, login_page_url, email_element_id,
+ password_element_id): # pylint: disable=R0201
+ tab = simple_mock.MockObject()
+
+ config = {'username': 'blah',
+ 'password': 'blargh'}
+
+ tab.ExpectCall('Navigate', login_page_url)
+ tab.ExpectCall('EvaluateJavaScript', _).WillReturn(False)
+ tab.ExpectCall('EvaluateJavaScript', _).WillReturn(True)
+ tab.ExpectCall('EvaluateJavaScript', _).WillReturn(False)
+ tab.ExpectCall('WaitForDocumentReadyStateToBeInteractiveOrBetter')
+
+ def VerifyEmail(js):
+ assert email_element_id in js
+ assert 'blah' in js
+ tab.ExpectCall('ExecuteJavaScript', _).WhenCalled(VerifyEmail)
+
+ def VerifyPw(js):
+ assert password_element_id in js
+ assert 'largh' in js
+ tab.ExpectCall('ExecuteJavaScript', _).WhenCalled(VerifyPw)
+
+ def VerifySubmit(js):
+ assert '.submit' in js
+ tab.ExpectCall('ExecuteJavaScript', _).WhenCalled(VerifySubmit)
+
+ # Checking for form still up.
+ tab.ExpectCall('EvaluateJavaScript', _).WillReturn(False)
+
+ backend.LoginNeeded(tab, config)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/google_credentials_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/google_credentials_backend.py
new file mode 100644
index 00000000000..1489bd5e696
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/google_credentials_backend.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core.chrome import form_based_credentials_backend
+
+class GoogleCredentialsBackend(
+ form_based_credentials_backend.FormBasedCredentialsBackend):
+ def IsAlreadyLoggedIn(self, tab):
+ return tab.EvaluateJavaScript(
+ 'document.getElementById("gb")!== null')
+
+ @property
+ def credentials_type(self):
+ return 'google'
+
+ @property
+ def url(self):
+ return 'https://accounts.google.com/'
+
+ @property
+ def login_form_id(self):
+ return 'gaia_loginform'
+
+ @property
+ def login_input_id(self):
+ return 'Email'
+
+ @property
+ def password_input_id(self):
+ return 'Passwd'
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/google_credentials_backend_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/google_credentials_backend_unittest.py
new file mode 100644
index 00000000000..42ad8ed5472
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/google_credentials_backend_unittest.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core.chrome import form_based_credentials_backend_unittest_base
+from telemetry.core.chrome import google_credentials_backend
+
+class TestGoogleCredentialsBackend(
+ form_based_credentials_backend_unittest_base.
+ FormBasedCredentialsBackendUnitTestBase):
+ def setUp(self):
+ self._credentials_type = 'google'
+
+ def testLoginUsingMock(self):
+ self._LoginUsingMock(google_credentials_backend.GoogleCredentialsBackend(),
+ 'https://accounts.google.com/', 'Email',
+ 'Passwd')
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_backend.py
new file mode 100644
index 00000000000..1b75024e17c
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_backend.py
@@ -0,0 +1,326 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import logging
+import socket
+import sys
+
+from telemetry.core import util
+from telemetry.core import exceptions
+from telemetry.core.chrome import inspector_console
+from telemetry.core.chrome import inspector_memory
+from telemetry.core.chrome import inspector_network
+from telemetry.core.chrome import inspector_page
+from telemetry.core.chrome import inspector_runtime
+from telemetry.core.chrome import inspector_timeline
+from telemetry.core.chrome import png_bitmap
+from telemetry.core.chrome import websocket
+
+class InspectorException(Exception):
+ pass
+
+class InspectorBackend(object):
+ def __init__(self, browser, browser_backend, debugger_url):
+ assert debugger_url
+ self._browser = browser
+ self._browser_backend = browser_backend
+ self._debugger_url = debugger_url
+ self._socket = None
+ self._domain_handlers = {}
+ self._cur_socket_timeout = 0
+ self._next_request_id = 0
+
+ self._console = inspector_console.InspectorConsole(self)
+ self._memory = inspector_memory.InspectorMemory(self)
+ self._page = inspector_page.InspectorPage(self)
+ self._runtime = inspector_runtime.InspectorRuntime(self)
+ self._timeline = inspector_timeline.InspectorTimeline(self)
+ self._network = inspector_network.InspectorNetwork(self)
+
+ def __del__(self):
+ self.Disconnect()
+
+ def _Connect(self):
+ if self._socket:
+ return
+ try:
+ self._socket = websocket.create_connection(self._debugger_url)
+ except (websocket.WebSocketException):
+ if self._browser_backend.IsBrowserRunning():
+ raise exceptions.TabCrashException(sys.exc_info()[1])
+ else:
+ raise exceptions.BrowserGoneException()
+
+ self._cur_socket_timeout = 0
+ self._next_request_id = 0
+
+ def Disconnect(self):
+ for _, handlers in self._domain_handlers.items():
+ _, will_close_handler = handlers
+ will_close_handler()
+ self._domain_handlers = {}
+
+ if self._socket:
+ self._socket.close()
+ self._socket = None
+
+ # General public methods.
+
+ @property
+ def browser(self):
+ return self._browser
+
+ @property
+ def url(self):
+ self.Disconnect()
+ return self._browser_backend.tab_list_backend.GetTabUrl(self._debugger_url)
+
+ def Activate(self):
+ self._Connect()
+ self._browser_backend.tab_list_backend.ActivateTab(self._debugger_url)
+
+ def Close(self):
+ self.Disconnect()
+ self._browser_backend.tab_list_backend.CloseTab(self._debugger_url)
+
+ # Public methods implemented in JavaScript.
+
+ def WaitForDocumentReadyStateToBeComplete(self, timeout):
+ util.WaitFor(
+ lambda: self._runtime.Evaluate('document.readyState') == 'complete',
+ timeout)
+
+ def WaitForDocumentReadyStateToBeInteractiveOrBetter(
+ self, timeout):
+ def IsReadyStateInteractiveOrBetter():
+ rs = self._runtime.Evaluate('document.readyState')
+ return rs == 'complete' or rs == 'interactive'
+ util.WaitFor(IsReadyStateInteractiveOrBetter, timeout)
+
+ @property
+ def screenshot_supported(self):
+ if self._runtime.Evaluate(
+ 'window.chrome.gpuBenchmarking === undefined'):
+ return False
+
+ if self._runtime.Evaluate(
+ 'window.chrome.gpuBenchmarking.beginWindowSnapshotPNG === undefined'):
+ return False
+
+ return self._browser_backend.chrome_branch_number >= 1391
+
+ def Screenshot(self, timeout):
+ if self._runtime.Evaluate(
+ 'window.chrome.gpuBenchmarking === undefined'):
+ raise Exception("Browser was not started with --enable-gpu-benchmarking")
+
+ if self._runtime.Evaluate(
+ 'window.chrome.gpuBenchmarking.beginWindowSnapshotPNG === undefined'):
+ raise Exception("Browser does not support window snapshot API.")
+
+ self._runtime.Evaluate("""
+ if(!window.__telemetry) {
+ window.__telemetry = {}
+ }
+ window.__telemetry.snapshotComplete = false;
+ window.__telemetry.snapshotData = null;
+ window.chrome.gpuBenchmarking.beginWindowSnapshotPNG(
+ function(snapshot) {
+ window.__telemetry.snapshotData = snapshot;
+ window.__telemetry.snapshotComplete = true;
+ }
+ );
+ """)
+
+ def IsSnapshotComplete():
+ return self._runtime.Evaluate('window.__telemetry.snapshotComplete')
+
+ util.WaitFor(IsSnapshotComplete, timeout)
+
+ snap = self._runtime.Evaluate("""
+ (function() {
+ var data = window.__telemetry.snapshotData;
+ delete window.__telemetry.snapshotComplete;
+ delete window.__telemetry.snapshotData;
+ return data;
+ })()
+ """)
+ if snap:
+ return png_bitmap.PngBitmap(snap['data'])
+ return None
+
+ # Console public methods.
+
+ @property
+ def message_output_stream(self): # pylint: disable=E0202
+ return self._console.message_output_stream
+
+ @message_output_stream.setter
+ def message_output_stream(self, stream): # pylint: disable=E0202
+ self._console.message_output_stream = stream
+
+ # Memory public methods.
+
+ def GetDOMStats(self, timeout):
+ dom_counters = self._memory.GetDOMCounters(timeout)
+ return {
+ 'document_count': dom_counters['documents'],
+ 'node_count': dom_counters['nodes'],
+ 'event_listener_count': dom_counters['jsEventListeners']
+ }
+
+ # Page public methods.
+
+ def PerformActionAndWaitForNavigate(self, action_function, timeout):
+ self._page.PerformActionAndWaitForNavigate(action_function, timeout)
+
+ def Navigate(self, url, script_to_evaluate_on_commit, timeout):
+ self._page.Navigate(url, script_to_evaluate_on_commit, timeout)
+
+ def GetCookieByName(self, name, timeout):
+ return self._page.GetCookieByName(name, timeout)
+
+ # Runtime public methods.
+
+ def ExecuteJavaScript(self, expr, timeout):
+ self._runtime.Execute(expr, timeout)
+
+ def EvaluateJavaScript(self, expr, timeout):
+ return self._runtime.Evaluate(expr, timeout)
+
+ # Timeline public methods.
+
+ @property
+ def timeline_model(self):
+ return self._timeline.timeline_model
+
+ def StartTimelineRecording(self):
+ self._timeline.Start()
+
+ def StopTimelineRecording(self):
+ self._timeline.Stop()
+
+ # Network public methods.
+
+ def ClearCache(self):
+ self._network.ClearCache()
+
+ # Methods used internally by other backends.
+
+ def DispatchNotifications(self, timeout=10):
+ self._Connect()
+ self._SetTimeout(timeout)
+
+ try:
+ data = self._socket.recv()
+ except (socket.error, websocket.WebSocketException):
+ if self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
+ self._debugger_url):
+ return
+ raise exceptions.TabCrashException(sys.exc_info()[1])
+
+ res = json.loads(data)
+ logging.debug('got [%s]', data)
+ if 'method' in res:
+ self._HandleNotification(res)
+
+ def _HandleNotification(self, res):
+ if (res['method'] == 'Inspector.detached' and
+ res.get('params', {}).get('reason','') == 'replaced_with_devtools'):
+ self._WaitForInspectorToGoAwayAndReconnect()
+ return
+ if res['method'] == 'Inspector.targetCrashed':
+ raise exceptions.TabCrashException()
+
+ mname = res['method']
+ dot_pos = mname.find('.')
+ domain_name = mname[:dot_pos]
+ if domain_name in self._domain_handlers:
+ try:
+ self._domain_handlers[domain_name][0](res)
+ except Exception:
+ import traceback
+ traceback.print_exc()
+ else:
+ logging.debug('Unhandled inspector message: %s', res)
+
+ def SendAndIgnoreResponse(self, req):
+ self._Connect()
+ req['id'] = self._next_request_id
+ self._next_request_id += 1
+ data = json.dumps(req)
+ self._socket.send(data)
+ logging.debug('sent [%s]', data)
+
+ def _SetTimeout(self, timeout):
+ if self._cur_socket_timeout != timeout:
+ self._socket.settimeout(timeout)
+ self._cur_socket_timeout = timeout
+
+ def _WaitForInspectorToGoAwayAndReconnect(self):
+ sys.stderr.write('The connection to Chrome was lost to the Inspector UI.\n')
+ sys.stderr.write('Telemetry is waiting for the inspector to be closed...\n')
+ self._socket.close()
+ self._socket = None
+ def IsBack():
+ return self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
+ self._debugger_url)
+ util.WaitFor(IsBack, 512, 0.5)
+ sys.stderr.write('\n')
+ sys.stderr.write('Inspector\'s UI closed. Telemetry will now resume.\n')
+ self._Connect()
+
+ def SyncRequest(self, req, timeout=10):
+ self._Connect()
+ # TODO(nduca): Listen to the timeout argument
+ # pylint: disable=W0613
+ self._SetTimeout(timeout)
+ self.SendAndIgnoreResponse(req)
+
+ while True:
+ try:
+ data = self._socket.recv()
+ except (socket.error, websocket.WebSocketException):
+ if self._browser_backend.tab_list_backend.DoesDebuggerUrlExist(
+ self._debugger_url):
+ raise util.TimeoutException(
+ 'Timed out waiting for reply. This is unusual.')
+ raise exceptions.TabCrashException(sys.exc_info()[1])
+
+ res = json.loads(data)
+ logging.debug('got [%s]', data)
+ if 'method' in res:
+ self._HandleNotification(res)
+ continue
+
+ if res['id'] != req['id']:
+ logging.debug('Dropped reply: %s', json.dumps(res))
+ continue
+ return res
+
+ def RegisterDomain(self,
+ domain_name, notification_handler, will_close_handler):
+ """Registers a given domain for handling notification methods.
+
+ For example, given inspector_backend:
+ def OnConsoleNotification(msg):
+ if msg['method'] == 'Console.messageAdded':
+ print msg['params']['message']
+ return
+ def OnConsoleClose(self):
+ pass
+ inspector_backend.RegisterDomain('Console',
+ OnConsoleNotification, OnConsoleClose)
+ """
+ assert domain_name not in self._domain_handlers
+ self._domain_handlers[domain_name] = (notification_handler,
+ will_close_handler)
+
+ def UnregisterDomain(self, domain_name):
+ """Unregisters a previously registered domain."""
+ assert domain_name in self._domain_handlers
+ self._domain_handlers.pop(domain_name)
+
+ def CollectGarbage(self):
+ self._page.CollectGarbage()
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_console.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_console.py
new file mode 100644
index 00000000000..be374783029
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_console.py
@@ -0,0 +1,61 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import logging
+
+class InspectorConsole(object):
+ def __init__(self, inspector_backend):
+ self._inspector_backend = inspector_backend
+ self._inspector_backend.RegisterDomain(
+ 'Console',
+ self._OnNotification,
+ self._OnClose)
+ self._message_output_stream = None
+ self._last_message = None
+ self._console_enabled = False
+
+ def _OnNotification(self, msg):
+ logging.debug('Notification: %s', json.dumps(msg, indent=2))
+ if msg['method'] == 'Console.messageAdded':
+ if msg['params']['message']['url'] == 'chrome://newtab/':
+ return
+ self._last_message = 'At %s:%i: %s' % (
+ msg['params']['message']['url'],
+ msg['params']['message']['line'],
+ msg['params']['message']['text'])
+ if self._message_output_stream:
+ self._message_output_stream.write(
+ '%s\n' % self._last_message)
+
+ elif msg['method'] == 'Console.messageRepeatCountUpdated':
+ if self._message_output_stream:
+ self._message_output_stream.write(
+ '%s\n' % self._last_message)
+
+ def _OnClose(self):
+ pass
+
+ # False positive in PyLint 0.25.1: http://www.logilab.org/89092
+ @property
+ def message_output_stream(self): # pylint: disable=E0202
+ return self._message_output_stream
+
+ @message_output_stream.setter
+ def message_output_stream(self, stream): # pylint: disable=E0202
+ self._message_output_stream = stream
+ self._UpdateConsoleEnabledState()
+
+ def _UpdateConsoleEnabledState(self):
+ enabled = self._message_output_stream != None
+ if enabled == self._console_enabled:
+ return
+
+ if enabled:
+ method_name = 'enable'
+ else:
+ method_name = 'disable'
+ self._inspector_backend.SyncRequest({
+ 'method': 'Console.%s' % method_name
+ })
+ self._console_enabled = enabled
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_console_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_console_unittest.py
new file mode 100644
index 00000000000..3db6eb411c9
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_console_unittest.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import re
+import StringIO
+
+from telemetry.core import util
+from telemetry.unittest import tab_test_case
+
+class TabConsoleTest(tab_test_case.TabTestCase):
+ def testConsoleOutputStream(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+
+ stream = StringIO.StringIO()
+ self._tab.message_output_stream = stream
+
+ self._tab.Navigate(
+ self._browser.http_server.UrlOf('page_that_logs_to_console.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ initial = self._tab.EvaluateJavaScript('window.__logCount')
+ def GotLog():
+ current = self._tab.EvaluateJavaScript('window.__logCount')
+ return current > initial
+ util.WaitFor(GotLog, 5)
+
+ lines = [l for l in stream.getvalue().split('\n') if len(l)]
+
+ self.assertTrue(len(lines) >= 1)
+ for line in lines:
+ prefix = 'http://(.+)/page_that_logs_to_console.html:9'
+ expected_line = 'At %s: Hello, world' % prefix
+ self.assertTrue(re.match(expected_line, line))
+
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_memory.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_memory.py
new file mode 100644
index 00000000000..931cb6e3ead
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_memory.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+
+class InspectorMemoryException(Exception):
+ pass
+
+class InspectorMemory(object):
+ """Communicates with the remote inspector's Memory domain."""
+
+ def __init__(self, inspector_backend):
+ self._inspector_backend = inspector_backend
+ self._inspector_backend.RegisterDomain(
+ 'Memory',
+ self._OnNotification,
+ self._OnClose)
+
+ def _OnNotification(self, msg):
+ pass
+
+ def _OnClose(self):
+ pass
+
+ def GetDOMCounters(self, timeout):
+ """Retrieves DOM element counts.
+
+ Args:
+ timeout: The number of seconds to wait for the inspector backend to
+ service the request before timing out.
+
+ Returns:
+ A dictionary containing the counts associated with "nodes", "documents",
+ and "jsEventListeners".
+ """
+ res = self._inspector_backend.SyncRequest({
+ 'method': 'Memory.getDOMCounters'
+ }, timeout)
+ if ('result' not in res or
+ 'nodes' not in res['result'] or
+ 'documents' not in res['result'] or
+ 'jsEventListeners' not in res['result']):
+ raise InspectorMemoryException(
+ 'Inspector returned unexpected result for Memory.getDOMCounters:\n' +
+ json.dumps(res, indent=2))
+ return {
+ 'nodes': res['result']['nodes'],
+ 'documents': res['result']['documents'],
+ 'jsEventListeners': res['result']['jsEventListeners']
+ }
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_memory_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_memory_unittest.py
new file mode 100644
index 00000000000..f8c0ad3d29d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_memory_unittest.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.unittest import tab_test_case
+
+class InspectorMemoryTest(tab_test_case.TabTestCase):
+ def testGetDOMStats(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+
+ # Due to an issue with CrOS, we create a new tab here rather than
+ # using self._tab to get a consistent starting page on all platforms
+ tab = self._browser.tabs.New()
+
+ tab.Navigate(
+ self._browser.http_server.UrlOf('dom_counter_sample.html'))
+ tab.WaitForDocumentReadyStateToBeComplete()
+
+ counts = tab.dom_stats
+ self.assertEqual(counts['document_count'], 2)
+ self.assertEqual(counts['node_count'], 18)
+ self.assertEqual(counts['event_listener_count'], 2)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_network.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_network.py
new file mode 100644
index 00000000000..e533a90f991
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_network.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class InspectorNetwork(object):
+ def __init__(self, inspector_backend):
+ self._inspector_backend = inspector_backend
+
+ def ClearCache(self, timeout=60):
+ """Clears the browser's disk and memory cache."""
+ res = self._inspector_backend.SyncRequest({
+ 'method': 'Network.canClearBrowserCache'
+ }, timeout)
+ assert res['result'], 'Cache clearing is not supported by this browser'
+ self._inspector_backend.SyncRequest({
+ 'method': 'Network.clearBrowserCache'
+ }, timeout)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_page.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_page.py
new file mode 100644
index 00000000000..43813edc7be
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_page.py
@@ -0,0 +1,114 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import logging
+
+from telemetry.core import util
+
+class InspectorPage(object):
+ def __init__(self, inspector_backend):
+ self._inspector_backend = inspector_backend
+ self._inspector_backend.RegisterDomain(
+ 'Page',
+ self._OnNotification,
+ self._OnClose)
+ self._navigation_pending = False
+
+ def _OnNotification(self, msg):
+ logging.debug('Notification: %s', json.dumps(msg, indent=2))
+ if msg['method'] == 'Page.frameNavigated' and self._navigation_pending:
+ url = msg['params']['frame']['url']
+ if (not url == 'chrome://newtab/' and not url == 'about:blank'
+ and not 'parentId' in msg['params']['frame']):
+ # Marks the navigation as complete and unblocks the
+ # PerformActionAndWaitForNavigate call.
+ self._navigation_pending = False
+
+ def _OnClose(self):
+ pass
+
+ def PerformActionAndWaitForNavigate(self, action_function, timeout=60):
+ """Executes action_function, and waits for the navigation to complete.
+
+ action_function is expect to result in a navigation. This function returns
+ when the navigation is complete or when the timeout has been exceeded.
+ """
+
+ # Turn on notifications. We need them to get the Page.frameNavigated event.
+ request = {
+ 'method': 'Page.enable'
+ }
+ res = self._inspector_backend.SyncRequest(request, timeout)
+ assert len(res['result'].keys()) == 0
+
+ def DisablePageNotifications():
+ request = {
+ 'method': 'Page.disable'
+ }
+ res = self._inspector_backend.SyncRequest(request, timeout)
+ assert len(res['result'].keys()) == 0
+
+ self._navigation_pending = True
+ try:
+ action_function()
+ except:
+ DisablePageNotifications()
+ raise
+
+ def IsNavigationDone(time_left):
+ self._inspector_backend.DispatchNotifications(time_left)
+ return not self._navigation_pending
+ util.WaitFor(IsNavigationDone, timeout, pass_time_left_to_func=True)
+
+ DisablePageNotifications()
+
+ def Navigate(self, url, script_to_evaluate_on_commit=None, timeout=60):
+ """Navigates to |url|.
+
+ If |script_to_evaluate_on_commit| is given, the script source string will be
+ evaluated when the navigation is committed. This is after the context of
+ the page exists, but before any script on the page itself has executed.
+ """
+
+ def DoNavigate():
+ if script_to_evaluate_on_commit:
+ request = {
+ 'method': 'Page.addScriptToEvaluateOnLoad',
+ 'params': {
+ 'scriptSource': script_to_evaluate_on_commit,
+ }
+ }
+ self._inspector_backend.SyncRequest(request)
+ # Navigate the page. However, there seems to be a bug in chrome devtools
+ # protocol where the request id for this event gets held on the browser
+ # side pretty much indefinitely.
+ #
+ # So, instead of waiting for the event to actually complete, wait for the
+ # Page.frameNavigated event.
+ request = {
+ 'method': 'Page.navigate',
+ 'params': {
+ 'url': url,
+ }
+ }
+ self._inspector_backend.SendAndIgnoreResponse(request)
+ self.PerformActionAndWaitForNavigate(DoNavigate, timeout)
+
+ def GetCookieByName(self, name, timeout=60):
+ """Returns the value of the cookie by the given |name|."""
+ request = {
+ 'method': 'Page.getCookies'
+ }
+ res = self._inspector_backend.SyncRequest(request, timeout)
+ cookies = res['result']['cookies']
+ for cookie in cookies:
+ if cookie['name'] == name:
+ return cookie['value']
+ return None
+
+ def CollectGarbage(self, timeout=60):
+ request = {
+ 'method': 'HeapProfiler.CollectGarbage'
+ }
+ self._inspector_backend.SyncRequest(request, timeout)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_page_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_page_unittest.py
new file mode 100644
index 00000000000..c01c330a843
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_page_unittest.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.unittest import tab_test_case
+
+unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'unittest_data')
+
+class InspectorPageTest(tab_test_case.TabTestCase):
+ def __init__(self, *args):
+ super(InspectorPageTest, self).__init__(*args)
+
+ def setUp(self):
+ super(InspectorPageTest, self).setUp()
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+
+ def testPageNavigateToNormalUrl(self):
+ self._tab.Navigate(self._browser.http_server.UrlOf('blank.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ def testCustomActionToNavigate(self):
+ self._tab.Navigate(
+ self._browser.http_server.UrlOf('page_with_link.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ self.assertEquals(
+ self._tab.EvaluateJavaScript('document.location.pathname;'),
+ '/page_with_link.html')
+
+ custom_action_called = [False]
+ def CustomAction():
+ custom_action_called[0] = True
+ self._tab.ExecuteJavaScript('document.getElementById("clickme").click();')
+
+ self._tab.PerformActionAndWaitForNavigate(CustomAction)
+
+ self.assertTrue(custom_action_called[0])
+ self.assertEquals(
+ self._tab.EvaluateJavaScript('document.location.pathname;'),
+ '/blank.html')
+
+ def testGetCookieByName(self):
+ self._tab.Navigate(
+ self._browser.http_server.UrlOf('blank.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ self._tab.ExecuteJavaScript('document.cookie="foo=bar"')
+ self.assertEquals(self._tab.GetCookieByName('foo'), 'bar')
+
+ def testScriptToEvaluateOnCommit(self):
+ self._tab.Navigate(
+ self._browser.http_server.UrlOf('blank.html'),
+ script_to_evaluate_on_commit='var foo = "bar";')
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ self.assertEquals(self._tab.EvaluateJavaScript('foo'), 'bar')
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_runtime.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_runtime.py
new file mode 100644
index 00000000000..e72ab5ff230
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_runtime.py
@@ -0,0 +1,56 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core import exceptions
+
+class InspectorRuntime(object):
+ def __init__(self, inspector_backend):
+ self._inspector_backend = inspector_backend
+ self._inspector_backend.RegisterDomain(
+ 'Runtime',
+ self._OnNotification,
+ self._OnClose)
+
+ def _OnNotification(self, msg):
+ pass
+
+ def _OnClose(self):
+ pass
+
+ def Execute(self, expr, timeout=60):
+ """Executes expr in javascript. Does not return the result.
+
+ If the expression failed to evaluate, EvaluateException will be raised.
+ """
+ self.Evaluate(expr + '; 0;', timeout)
+
+ def Evaluate(self, expr, timeout=60):
+ """Evalutes expr in javascript and returns the JSONized result.
+
+ Consider using Execute for cases where the result of the expression is not
+ needed.
+
+ If evaluation throws in javascript, a python EvaluateException will
+ be raised.
+
+ If the result of the evaluation cannot be JSONized, then an
+ EvaluationException will be raised.
+ """
+ request = {
+ 'method': 'Runtime.evaluate',
+ 'params': {
+ 'expression': expr,
+ 'returnByValue': True
+ }
+ }
+ res = self._inspector_backend.SyncRequest(request, timeout)
+ if 'error' in res:
+ raise exceptions.EvaluateException(res['error']['message'])
+
+ if 'wasThrown' in res['result'] and res['result']['wasThrown']:
+ # TODO(nduca): propagate stacks from javascript up to the python
+ # exception.
+ raise exceptions.EvaluateException(res['result']['result']['description'])
+ if res['result']['result']['type'] == 'undefined':
+ return None
+ return res['result']['result']['value']
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_runtime_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_runtime_unittest.py
new file mode 100644
index 00000000000..a2d282986fe
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_runtime_unittest.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core import exceptions
+from telemetry.unittest import tab_test_case
+
+class InspectorRuntimeTest(tab_test_case.TabTestCase):
+ def testRuntimeEvaluateSimple(self):
+ res = self._tab.EvaluateJavaScript('1+1')
+ assert res == 2
+
+ def testRuntimeEvaluateThatFails(self):
+ self.assertRaises(exceptions.EvaluateException,
+ lambda: self._tab.EvaluateJavaScript('fsdfsdfsf'))
+
+ def testRuntimeEvaluateOfSomethingThatCantJSONize(self):
+
+ def test():
+ self._tab.EvaluateJavaScript("""
+ var cur = {};
+ var root = {next: cur};
+ for (var i = 0; i < 1000; i++) {
+ next = {};
+ cur.next = next;
+ cur = next;
+ }
+ root;""")
+ self.assertRaises(exceptions.EvaluateException, test)
+
+ def testRuntimeExecuteOfSomethingThatCantJSONize(self):
+ self._tab.ExecuteJavaScript('window')
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_timeline.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_timeline.py
new file mode 100644
index 00000000000..76c9683b058
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_timeline.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core.timeline import model
+
+class TabBackendException(Exception):
+ pass
+
+class InspectorTimeline(object):
+ """Implementation of dev tools timeline."""
+ class Recorder(object):
+ """Utility class to Start / Stop recording timeline."""
+ def __init__(self, tab):
+ self._tab = tab
+
+ def __enter__(self):
+ self._tab.StartTimelineRecording()
+
+ def __exit__(self, *args):
+ self._tab.StopTimelineRecording()
+
+ def __init__(self, inspector_backend):
+ self._inspector_backend = inspector_backend
+ self._is_recording = False
+ self._timeline_model = None
+ self._raw_events = None
+
+ @property
+ def timeline_model(self):
+ return self._timeline_model
+
+ def Start(self):
+ if self._is_recording:
+ return
+ self._is_recording = True
+ self._timeline_model = None
+ self._raw_events = []
+ self._inspector_backend.RegisterDomain('Timeline',
+ self._OnNotification, self._OnClose)
+ req = {'method': 'Timeline.start'}
+ self._SendSyncRequest(req)
+
+ def Stop(self):
+ if not self._is_recording:
+ raise TabBackendException('Stop() called but not started')
+ self._is_recording = False
+ self._timeline_model = model.TimelineModel(event_data=self._raw_events,
+ shift_world_to_zero=False)
+ req = {'method': 'Timeline.stop'}
+ self._SendSyncRequest(req)
+ self._inspector_backend.UnregisterDomain('Timeline')
+
+ def _SendSyncRequest(self, req, timeout=60):
+ res = self._inspector_backend.SyncRequest(req, timeout)
+ if 'error' in res:
+ raise TabBackendException(res['error']['message'])
+ return res['result']
+
+ def _OnNotification(self, msg):
+ if not self._is_recording:
+ return
+ if 'method' in msg and msg['method'] == 'Timeline.eventRecorded':
+ self._OnEventRecorded(msg)
+
+ def _OnEventRecorded(self, msg):
+ record = msg.get('params', {}).get('record')
+ if record:
+ self._raw_events.append(record)
+
+ def _OnClose(self):
+ pass
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/inspector_timeline_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/inspector_timeline_unittest.py
new file mode 100644
index 00000000000..4b7a707c09f
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/inspector_timeline_unittest.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.core import util
+from telemetry.core.chrome import inspector_timeline
+from telemetry.unittest import tab_test_case
+
+class InspectorTimelineTabTest(tab_test_case.TabTestCase):
+ def _StartServer(self):
+ base_dir = os.path.dirname(__file__)
+ self._browser.SetHTTPServerDirectories(os.path.join(base_dir, '..', '..',
+ 'unittest_data'))
+
+ def _WaitForAnimationFrame(self):
+ def _IsDone():
+ js_is_done = """done"""
+ return bool(self._tab.EvaluateJavaScript(js_is_done))
+ util.WaitFor(_IsDone, 5)
+
+ def testGotTimeline(self):
+ with inspector_timeline.InspectorTimeline.Recorder(self._tab):
+ self._tab.ExecuteJavaScript(
+"""
+var done = false;
+function sleep(ms) {
+ var endTime = (new Date().getTime()) + ms;
+ while ((new Date().getTime()) < endTime);
+}
+window.webkitRequestAnimationFrame(function() { sleep(10); done = true; });
+""")
+ self._WaitForAnimationFrame()
+
+ r = self._tab.timeline_model.GetAllEventsOfName('FireAnimationFrame')
+ self.assertTrue(len(r) > 0)
+ self.assertTrue(r[0].duration > 0)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/misc_web_contents_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/misc_web_contents_backend.py
new file mode 100644
index 00000000000..f3a4ab75378
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/misc_web_contents_backend.py
@@ -0,0 +1,38 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+
+from telemetry.core import web_contents
+from telemetry.core.chrome import inspector_backend
+
+class MiscWebContentsBackend(object):
+ """Provides acccess to chrome://oobe/login page, which is neither an extension
+ nor a tab."""
+ def __init__(self, browser_backend):
+ self._browser_backend = browser_backend
+
+ def GetOobe(self):
+ oobe_web_contents_info = self._FindWebContentsInfo()
+ if oobe_web_contents_info:
+ debugger_url = oobe_web_contents_info.get('webSocketDebuggerUrl')
+ if debugger_url:
+ inspector = self._CreateInspectorBackend(debugger_url)
+ return web_contents.WebContents(inspector)
+ return None
+
+ def _CreateInspectorBackend(self, debugger_url):
+ return inspector_backend.InspectorBackend(self._browser_backend.browser,
+ self._browser_backend,
+ debugger_url)
+
+ def _ListWebContents(self, timeout=None):
+ data = self._browser_backend.Request('', timeout=timeout)
+ return json.loads(data)
+
+ def _FindWebContentsInfo(self):
+ for web_contents_info in self._ListWebContents():
+ # Prior to crrev.com/203152, url was chrome://oobe/login.
+ if (web_contents_info.get('url').startswith('chrome://oobe')):
+ return web_contents_info
+ return None
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/png_bitmap.py b/chromium/tools/telemetry/telemetry/core/chrome/png_bitmap.py
new file mode 100644
index 00000000000..fc8d89e679e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/png_bitmap.py
@@ -0,0 +1,72 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import sys
+import os
+import base64
+
+def _EnsurePngIsInPath():
+ png_path = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'third_party', 'png')
+ if png_path not in sys.path:
+ sys.path.append(png_path)
+
+_EnsurePngIsInPath()
+import png # pylint: disable=F0401
+
+class PngColor(object):
+ """Encapsulates an RGB color retreived from a PngBitmap"""
+
+ def __init__(self, r, g, b, a=255):
+ self.r = r
+ self.g = g
+ self.b = b
+ self.a = a
+
+ def IsEqual(self, expected_color, tolerance=0):
+ """Verifies that the color is within a given tolerance of
+ the expected color"""
+ r_diff = abs(self.r - expected_color.r)
+ g_diff = abs(self.g - expected_color.g)
+ b_diff = abs(self.b - expected_color.b)
+ a_diff = abs(self.a - expected_color.a)
+ return (r_diff <= tolerance and g_diff <= tolerance
+ and b_diff <= tolerance and a_diff <= tolerance)
+
+ def AssertIsRGB(self, r, g, b, tolerance=0):
+ assert self.IsEqual(PngColor(r, g, b), tolerance)
+
+ def AssertIsRGBA(self, r, g, b, a, tolerance=0):
+ assert self.IsEqual(PngColor(r, g, b, a), tolerance)
+
+class PngBitmap(object):
+ """Utilities for parsing and inspecting inspecting a PNG"""
+
+ def __init__(self, base64_png):
+ self._png_data = base64.b64decode(base64_png)
+ self._png = png.Reader(bytes=self._png_data)
+ rgba8_data = self._png.asRGBA8()
+ self._width = rgba8_data[0]
+ self._height = rgba8_data[1]
+ self._pixels = list(rgba8_data[2])
+ self._metadata = rgba8_data[3]
+
+ @property
+ def width(self):
+ """Width of the snapshot"""
+ return self._width
+
+ @property
+ def height(self):
+ """Height of the snapshot"""
+ return self._height
+
+ def GetPixelColor(self, x, y):
+ """Returns a PngColor for the pixel at (x, y)"""
+ row = self._pixels[y]
+ offset = x * 4
+ return PngColor(row[offset], row[offset+1], row[offset+2], row[offset+3])
+
+ def WriteFile(self, path):
+ with open(path, "wb") as f:
+ f.write(self._png_data)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/png_bitmap_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/png_bitmap_unittest.py
new file mode 100644
index 00000000000..ae33198f62f
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/png_bitmap_unittest.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.core.chrome import png_bitmap
+
+# This is a simple base64 encoded 2x2 PNG which contains, in order, a single
+# Red, Yellow, Blue, and Green pixel.
+test_png = """
+iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91
+JpzAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACx
+MBAJqcGAAAABZJREFUCNdj/M/AwPCfgYGB4T/DfwY
+AHAAD/iOWZXsAAAAASUVORK5CYII=
+"""
+
+class PngBitmapTest(unittest.TestCase):
+ def testRead(self):
+ png = png_bitmap.PngBitmap(test_png)
+
+ self.assertEquals(2, png.width)
+ self.assertEquals(2, png.height)
+
+ png.GetPixelColor(0, 0).AssertIsRGB(255, 0, 0)
+ png.GetPixelColor(1, 1).AssertIsRGB(0, 255, 0)
+ png.GetPixelColor(0, 1).AssertIsRGB(0, 0, 255)
+ png.GetPixelColor(1, 0).AssertIsRGB(255, 255, 0)
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/tab_list_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/tab_list_backend.py
new file mode 100644
index 00000000000..b61e4abe104
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/tab_list_backend.py
@@ -0,0 +1,135 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import urllib2
+import weakref
+
+from telemetry.core import util
+from telemetry.core import tab
+from telemetry.core.chrome import inspector_backend
+
+class TabListBackend(object):
+ def __init__(self, browser_backend):
+ self._browser_backend = browser_backend
+
+ # Stores web socket debugger URLs in iteration order.
+ self._tab_list = []
+ # Maps debugger URLs to Tab objects.
+ self._tab_dict = weakref.WeakValueDictionary()
+
+ def Init(self):
+ self._UpdateTabList()
+
+ def New(self, timeout):
+ assert self._browser_backend.supports_tab_control
+
+ self._browser_backend.Request('new', timeout=timeout)
+ return self[-1]
+
+ def DoesDebuggerUrlExist(self, debugger_url):
+ return self._FindTabInfo(debugger_url) is not None
+
+ def CloseTab(self, debugger_url, timeout=None):
+ assert self._browser_backend.supports_tab_control
+
+ # TODO(dtu): crbug.com/160946, allow closing the last tab on some platforms.
+ # For now, just create a new tab before closing the last tab.
+ if len(self) <= 1:
+ self.New(timeout)
+
+ tab_id = debugger_url.split('/')[-1]
+ try:
+ response = self._browser_backend.Request('close/%s' % tab_id,
+ timeout=timeout,
+ throw_network_exception=True)
+ except urllib2.HTTPError:
+ raise Exception('Unable to close tab, tab id not found: %s' % tab_id)
+ assert response == 'Target is closing'
+
+ util.WaitFor(lambda: not self._FindTabInfo(debugger_url), timeout=5)
+
+ if debugger_url in self._tab_dict:
+ del self._tab_dict[debugger_url]
+ self._UpdateTabList()
+
+ def ActivateTab(self, debugger_url, timeout=None):
+ assert self._browser_backend.supports_tab_control
+
+ assert debugger_url in self._tab_dict
+ tab_id = debugger_url.split('/')[-1]
+ try:
+ response = self._browser_backend.Request('activate/%s' % tab_id,
+ timeout=timeout,
+ throw_network_exception=True)
+ except urllib2.HTTPError:
+ raise Exception('Unable to activate tab, tab id not found: %s' % tab_id)
+ assert response == 'Target activated'
+
+ def GetTabUrl(self, debugger_url):
+ tab_info = self._FindTabInfo(debugger_url)
+ # TODO(hartmanng): crbug.com/166886 (uncomment the following assert and
+ # remove the extra None check when _ListTabs is fixed):
+ # assert tab_info is not None
+ return tab_info['url'] if tab_info else None
+
+ def __iter__(self):
+ self._UpdateTabList()
+ return self._tab_list.__iter__()
+
+ def __len__(self):
+ self._UpdateTabList()
+ return len(self._tab_list)
+
+ def Get(self, index, ret):
+ """Returns self[index] if it exists, or ret if index is out of bounds.
+ """
+ self._UpdateTabList()
+ if len(self._tab_list) <= index:
+ return ret
+ debugger_url = self._tab_list[index]
+ # Lazily get/create a Tab object.
+ tab_object = self._tab_dict.get(debugger_url)
+ if not tab_object:
+ backend = inspector_backend.InspectorBackend(
+ self._browser_backend.browser,
+ self._browser_backend,
+ debugger_url)
+ tab_object = tab.Tab(backend)
+ self._tab_dict[debugger_url] = tab_object
+ return tab_object
+
+ def __getitem__(self, index):
+ tab_object = self.Get(index, None)
+ if tab_object is None:
+ raise IndexError('list index out of range')
+ return tab_object
+
+ def _ListTabs(self, timeout=None):
+ def _IsTab(context):
+ if 'type' in context:
+ return context['type'] == 'page'
+ # TODO: For compatibility with Chrome before r177683.
+ # This check is not completely correct, see crbug.com/190592.
+ return not context['url'].startswith('chrome-extension://')
+ data = self._browser_backend.Request('', timeout=timeout)
+ all_contexts = json.loads(data)
+ tabs = filter(_IsTab, all_contexts)
+ return tabs
+
+ def _UpdateTabList(self):
+ def GetDebuggerUrl(tab_info):
+ if 'webSocketDebuggerUrl' not in tab_info:
+ return None
+ return tab_info['webSocketDebuggerUrl']
+ new_tab_list = map(GetDebuggerUrl, self._ListTabs())
+ self._tab_list = [t for t in self._tab_list
+ if t in self._tab_dict or t in new_tab_list]
+ self._tab_list += [t for t in new_tab_list
+ if t is not None and t not in self._tab_list]
+
+ def _FindTabInfo(self, debugger_url):
+ for tab_info in self._ListTabs():
+ if tab_info.get('webSocketDebuggerUrl') == debugger_url:
+ return tab_info
+ return None
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/trace_result.py b/chromium/tools/telemetry/telemetry/core/chrome/trace_result.py
new file mode 100644
index 00000000000..e2d851c84d4
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/trace_result.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class TraceResult(object):
+ def __init__(self, impl):
+ self._impl = impl
+
+ def Serialize(self, f):
+ """Serializes the trace result to a file-like object"""
+ return self._impl.Serialize(f)
+
+ def AsTimelineModel(self):
+ """Parses the trace result into a timeline model for in-memory
+ manipulation."""
+ return self._impl.AsTimelineModel()
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/tracing_backend.py b/chromium/tools/telemetry/telemetry/core/chrome/tracing_backend.py
new file mode 100644
index 00000000000..471ff22dbab
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/tracing_backend.py
@@ -0,0 +1,161 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import cStringIO
+import json
+import logging
+import socket
+import threading
+
+
+from telemetry.core import util
+from telemetry.core.chrome import trace_result
+from telemetry.core.chrome import websocket
+from telemetry.core.timeline import model
+
+
+class TracingUnsupportedException(Exception):
+ pass
+
+# This class supports legacy format of trace presentation within DevTools
+# protocol, where trace data were sent as JSON-serialized strings. DevTools
+# now send the data as raw objects within the protocol message JSON, so there's
+# no need in extra de-serialization. We might want to remove this in the future.
+class TraceResultImpl(object):
+ def __init__(self, tracing_data):
+ self._tracing_data = tracing_data
+
+ def Serialize(self, f):
+ f.write('{"traceEvents": [')
+ d = self._tracing_data
+ # Note: we're not using ','.join here because the strings that are in the
+ # tracing data are typically many megabytes in size. In the fast case, f is
+ # just a file, so by skipping the in memory step we keep our memory
+ # footprint low and avoid additional processing.
+ if len(d) == 0:
+ pass
+ elif len(d) == 1:
+ f.write(d[0])
+ else:
+ f.write(d[0])
+ for i in range(1, len(d)):
+ f.write(',')
+ f.write(d[i])
+ f.write(']}')
+
+ def AsTimelineModel(self):
+ f = cStringIO.StringIO()
+ self.Serialize(f)
+ return model.TimelineModel(
+ event_data=f.getvalue(),
+ shift_world_to_zero=False)
+
+# RawTraceResultImpl differs from TraceResultImpl above in that
+# data are kept as a list of dicts, not strings.
+class RawTraceResultImpl(object):
+ def __init__(self, tracing_data):
+ self._tracing_data = tracing_data
+
+ def Serialize(self, f):
+ f.write('{"traceEvents":')
+ json.dump(self._tracing_data, f)
+ f.write('}')
+
+ def AsTimelineModel(self):
+ return model.TimelineModel(self._tracing_data)
+
+class TracingBackend(object):
+ def __init__(self, devtools_port):
+ debugger_url = 'ws://localhost:%i/devtools/browser' % devtools_port
+ self._socket = websocket.create_connection(debugger_url)
+ self._next_request_id = 0
+ self._cur_socket_timeout = 0
+ self._thread = None
+ self._tracing_data = []
+
+ def BeginTracing(self, custom_categories=None, timeout=10):
+ self._CheckNotificationSupported()
+ req = {'method': 'Tracing.start'}
+ if custom_categories:
+ req['params'] = {'categories': custom_categories}
+ self._SyncRequest(req, timeout)
+ # Tracing.start will send asynchronous notifications containing trace
+ # data, until Tracing.end is called.
+ self._thread = threading.Thread(target=self._TracingReader)
+ self._thread.start()
+
+ def EndTracing(self):
+ req = {'method': 'Tracing.end'}
+ self._SyncRequest(req)
+ self._thread.join()
+ self._thread = None
+
+ def GetTraceResultAndReset(self):
+ assert not self._thread
+ if self._tracing_data and type(self._tracing_data[0]) in [str, unicode]:
+ result_impl = TraceResultImpl(self._tracing_data)
+ else:
+ result_impl = RawTraceResultImpl(self._tracing_data)
+ self._tracing_data = []
+ return trace_result.TraceResult(result_impl)
+
+ def Close(self):
+ if self._socket:
+ self._socket.close()
+ self._socket = None
+
+ def _TracingReader(self):
+ while self._socket:
+ try:
+ data = self._socket.recv()
+ if not data:
+ break
+ res = json.loads(data)
+ logging.debug('got [%s]', data)
+ if 'Tracing.dataCollected' == res.get('method'):
+ value = res.get('params', {}).get('value')
+ if type(value) in [str, unicode]:
+ self._tracing_data.append(value)
+ elif type(value) is list:
+ self._tracing_data.extend(value)
+ else:
+ logging.warning('Unexpected type in tracing data')
+ elif 'Tracing.tracingComplete' == res.get('method'):
+ break
+ except (socket.error, websocket.WebSocketException):
+ logging.warning('Timeout waiting for tracing response, unusual.')
+
+ def _SyncRequest(self, req, timeout=10):
+ self._SetTimeout(timeout)
+ req['id'] = self._next_request_id
+ self._next_request_id += 1
+ data = json.dumps(req)
+ logging.debug('will send [%s]', data)
+ self._socket.send(data)
+
+ def _SetTimeout(self, timeout):
+ if self._cur_socket_timeout != timeout:
+ self._socket.settimeout(timeout)
+ self._cur_socket_timeout = timeout
+
+ def _CheckNotificationSupported(self):
+ """Ensures we're running against a compatible version of chrome."""
+ req = {'method': 'Tracing.hasCompleted'}
+ self._SyncRequest(req)
+ while True:
+ try:
+ data = self._socket.recv()
+ except (socket.error, websocket.WebSocketException):
+ raise util.TimeoutException(
+ 'Timed out waiting for reply. This is unusual.')
+ logging.debug('got [%s]', data)
+ res = json.loads(data)
+ if res['id'] != req['id']:
+ logging.debug('Dropped reply: %s', json.dumps(res))
+ continue
+ if res.get('response'):
+ raise TracingUnsupportedException(
+ 'Tracing not supported for this browser')
+ elif 'error' in res:
+ return
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/tracing_backend_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/tracing_backend_unittest.py
new file mode 100644
index 00000000000..69b56e9de84
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/tracing_backend_unittest.py
@@ -0,0 +1,92 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import cStringIO
+import json
+import logging
+import os
+import unittest
+
+from telemetry.core import util
+from telemetry.core.chrome import tracing_backend
+from telemetry.unittest import tab_test_case
+
+
+class TracingBackendTest(tab_test_case.TabTestCase):
+ def _StartServer(self):
+ base_dir = os.path.dirname(__file__)
+ self._browser.SetHTTPServerDirectories(
+ os.path.join(base_dir, '..', '..', '..', 'unittest_data'))
+
+ def _WaitForAnimationFrame(self):
+ def _IsDone():
+ js_is_done = """done"""
+ return bool(self._tab.EvaluateJavaScript(js_is_done))
+ util.WaitFor(_IsDone, 5)
+
+ def testGotTrace(self):
+ if not self._browser.supports_tracing:
+ logging.warning('Browser does not support tracing, skipping test.')
+ return
+ self._StartServer()
+ self._browser.StartTracing()
+ self._browser.StopTracing()
+
+ # TODO(tengs): check model for correctness after trace_event_importer
+ # is implemented (crbug.com/173327).
+
+
+class TracingResultImplTest(unittest.TestCase):
+ # Override TestCase.run to run a test with all possible
+ # implementations of TraceResult.
+ def __init__(self, method_name):
+ self._traceResultImplClass = None
+ super(TracingResultImplTest, self).__init__(method_name)
+
+ def run(self, result=None):
+ def RawTraceResultImplWrapper(strings):
+ return tracing_backend.RawTraceResultImpl(map(json.loads, strings))
+ classes = [
+ tracing_backend.TraceResultImpl,
+ RawTraceResultImplWrapper
+ ]
+ for cls in classes:
+ self._traceResultImplClass = cls
+ super(TracingResultImplTest, self).run(result)
+
+ def testWrite1(self):
+ ri = self._traceResultImplClass([])
+ f = cStringIO.StringIO()
+ ri.Serialize(f)
+ v = f.getvalue()
+
+ j = json.loads(v)
+ assert 'traceEvents' in j
+ self.assertEquals(j['traceEvents'], [])
+
+ def testWrite2(self):
+ ri = self._traceResultImplClass([
+ '"foo"',
+ '"bar"'])
+ f = cStringIO.StringIO()
+ ri.Serialize(f)
+ v = f.getvalue()
+
+ j = json.loads(v)
+ assert 'traceEvents' in j
+ self.assertEquals(j['traceEvents'], ['foo', 'bar'])
+
+ def testWrite3(self):
+ ri = self._traceResultImplClass([
+ '"foo"',
+ '"bar"',
+ '"baz"'])
+ f = cStringIO.StringIO()
+ ri.Serialize(f)
+ v = f.getvalue()
+
+ j = json.loads(v)
+ assert 'traceEvents' in j
+ self.assertEquals(j['traceEvents'],
+ ['foo', 'bar', 'baz'])
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/websocket.py b/chromium/tools/telemetry/telemetry/core/chrome/websocket.py
new file mode 100644
index 00000000000..c4a7f40ef5c
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/websocket.py
@@ -0,0 +1,19 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from __future__ import absolute_import
+import os
+import sys
+
+def __init__():
+ ws_path = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'third_party', 'websocket-client')
+ ws_path = os.path.abspath(ws_path)
+ assert os.path.exists(os.path.join(ws_path, 'websocket.py'))
+ if ws_path not in sys.path:
+ sys.path.append(ws_path)
+
+__init__()
+
+from websocket import create_connection # pylint: disable=W0611
+from websocket import WebSocketException # pylint: disable=W0611
diff --git a/chromium/tools/telemetry/telemetry/core/chrome/websocket_unittest.py b/chromium/tools/telemetry/telemetry/core/chrome/websocket_unittest.py
new file mode 100644
index 00000000000..e1418e8ef36
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/chrome/websocket_unittest.py
@@ -0,0 +1,10 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.core.chrome import websocket
+
+class TestWebSocket(unittest.TestCase):
+ def testExports(self):
+ self.assertNotEqual(websocket.create_connection, None)
diff --git a/chromium/tools/telemetry/telemetry/core/discover.py b/chromium/tools/telemetry/telemetry/core/discover.py
new file mode 100644
index 00000000000..ece12f9fc9d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/discover.py
@@ -0,0 +1,73 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import fnmatch
+import inspect
+import os
+import re
+
+
+def DiscoverModules(start_dir, top_level_dir, pattern='*'):
+ """Discover all modules in |start_dir| which match |pattern|.
+
+ Args:
+ start_dir: The directory to recursively search.
+ top_level_dir: The top level of the package, for importing.
+ pattern: Unix shell-style pattern for filtering the filenames to import.
+
+ Returns:
+ list of modules.
+ """
+ modules = []
+ for dir_path, _, filenames in os.walk(start_dir):
+ for filename in filenames:
+ # Filter out unwanted filenames.
+ if filename.startswith('.') or filename.startswith('_'):
+ continue
+ if os.path.splitext(filename)[1] != '.py':
+ continue
+ if not fnmatch.fnmatch(filename, pattern):
+ continue
+
+ # Find the module.
+ module_rel_path = os.path.relpath(os.path.join(dir_path, filename),
+ top_level_dir)
+ module_name = re.sub(r'[/\\]', '.', os.path.splitext(module_rel_path)[0])
+
+ # Import the module.
+ module = __import__(module_name, fromlist=[True])
+
+ modules.append(module)
+ return modules
+
+
+# TODO(dtu): Normalize all discoverable classes to have corresponding module
+# and class names, then always index by class name.
+def DiscoverClasses(start_dir, top_level_dir, base_class, pattern='*',
+ index_by_class_name=False):
+ """Discover all classes in |start_dir| which subclass |base_class|.
+
+ Args:
+ start_dir: The directory to recursively search.
+ top_level_dir: The top level of the package, for importing.
+ base_class: The base class to search for.
+ pattern: Unix shell-style pattern for filtering the filenames to import.
+ index_by_class_name: If True, use class name converted to
+ lowercase_with_underscores instead of module name in return dict keys.
+
+ Returns:
+ dict of {module_name: class} or {underscored_class_name: class}
+ """
+ modules = DiscoverModules(start_dir, top_level_dir, pattern)
+ classes = {}
+ for module in modules:
+ for _, obj in inspect.getmembers(module):
+ if (inspect.isclass(obj) and obj is not base_class and
+ issubclass(obj, base_class)):
+ if index_by_class_name:
+ key_name = re.sub('(?!^)([A-Z]+)', r'_\1', obj.__name__).lower()
+ else:
+ key_name = module.__name__.split('.')[-1]
+ classes[key_name] = obj
+
+ return classes
diff --git a/chromium/tools/telemetry/telemetry/core/discover_unittest.py b/chromium/tools/telemetry/telemetry/core/discover_unittest.py
new file mode 100644
index 00000000000..49d046d6a8d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/discover_unittest.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from telemetry.core import discover
+
+class DiscoverTest(unittest.TestCase):
+ def testDiscoverClasses(self):
+ telemetry_dir = os.path.join(
+ os.path.dirname(discover.__file__), '..', '..')
+ telemetry_dir = os.path.abspath(telemetry_dir)
+ top_level_dir = os.path.join(telemetry_dir, 'unittest_data')
+ start_dir = os.path.join(top_level_dir, 'discoverable_classes')
+ base_class = Exception
+ classes = discover.DiscoverClasses(start_dir, top_level_dir, base_class)
+ self.assertTrue(len(classes) > 0)
+
+ found_dummy_exception = False
+ for c in classes.values():
+ if c.__name__ == 'DummyException':
+ found_dummy_exception = True
+ self.assertTrue(issubclass(c, Exception))
+
+ self.assertTrue(found_dummy_exception) \ No newline at end of file
diff --git a/chromium/tools/telemetry/telemetry/core/exceptions.py b/chromium/tools/telemetry/telemetry/core/exceptions.py
new file mode 100644
index 00000000000..713b092df09
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/exceptions.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+class BrowserGoneException(Exception):
+ """Represents a crash of the entire browser.
+
+ In this state, all bets are pretty much off."""
+ pass
+
+class BrowserConnectionGoneException(BrowserGoneException):
+ pass
+
+class TabCrashException(Exception):
+ """Represents a crash of the current tab, but not the overall browser.
+
+ In this state, the tab is gone, but the underlying browser is still alive."""
+ pass
+
+class LoginException(Exception):
+ pass
+
+class EvaluateException(Exception):
+ pass
+
+class ProfilingException(Exception):
+ pass
diff --git a/chromium/tools/telemetry/telemetry/core/extension_dict.py b/chromium/tools/telemetry/telemetry/core/extension_dict.py
new file mode 100644
index 00000000000..43cbe784c39
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/extension_dict.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core import extension_to_load
+
+class ExtensionDict(object):
+ """Dictionary of ExtensionPage instances, with extension_id as key"""
+
+ def __init__(self, extension_dict_backend):
+ self._extension_dict_backend = extension_dict_backend
+
+ def __getitem__(self, load_extension):
+ """Given an ExtensionToLoad instance, returns the corresponding
+ ExtensionPage instance."""
+ if not isinstance(load_extension, extension_to_load.ExtensionToLoad):
+ raise Exception("Input param must be of type ExtensionToLoad")
+ return self._extension_dict_backend.__getitem__(
+ load_extension.extension_id)
+
+ def __contains__(self, load_extension):
+ """Checks if this ExtensionToLoad instance has been loaded"""
+ if not isinstance(load_extension, extension_to_load.ExtensionToLoad):
+ raise Exception("Input param must be of type ExtensionToLoad")
+ return self._extension_dict_backend.__contains__(
+ load_extension.extension_id)
diff --git a/chromium/tools/telemetry/telemetry/core/extension_page.py b/chromium/tools/telemetry/telemetry/core/extension_page.py
new file mode 100644
index 00000000000..0ca5d294151
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/extension_page.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core import web_contents
+
+class ExtensionPage(web_contents.WebContents):
+ """Represents a an extension page in the browser"""
+ def __init__(self, inspector_backend):
+ super(ExtensionPage, self).__init__(inspector_backend)
+
+ def __del__(self):
+ super(ExtensionPage, self).__del__()
diff --git a/chromium/tools/telemetry/telemetry/core/extension_to_load.py b/chromium/tools/telemetry/telemetry/core/extension_to_load.py
new file mode 100644
index 00000000000..b5c50009451
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/extension_to_load.py
@@ -0,0 +1,65 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.core.chrome import crx_id
+
+class ExtensionPathNonExistentException(Exception):
+ pass
+
+class MissingPublicKeyException(Exception):
+ pass
+
+class ExtensionToLoad(object):
+ def __init__(self, path, browser_type, is_component=False):
+ if not os.path.isdir(path):
+ raise ExtensionPathNonExistentException(
+ 'Extension path not a directory %s' % path)
+ self._path = path
+ self._local_path = path
+ self._is_component = is_component
+ if is_component and not crx_id.HasPublicKey(path):
+ raise MissingPublicKeyException(
+ 'Component extension %s must have a public key' % path)
+
+ # It is possible that we are running telemetry on Windows targeting
+ # a remote CrOS or Android device. In this case, we need the
+ # browser_type argument to determine how we should encode
+ # the extension path.
+ self._is_win = (os.name == 'nt'
+ and not (browser_type.startswith('android')
+ or browser_type.startswith('cros')))
+
+ @property
+ def extension_id(self):
+ """Unique extension id of this extension."""
+ if crx_id.HasPublicKey(self._path):
+ # Calculate extension id from the public key.
+ return crx_id.GetCRXAppID(os.path.realpath(self._path))
+ else:
+ # Calculate extension id based on the path on the device.
+ return crx_id.GetCRXAppID(
+ os.path.realpath(self._local_path),
+ from_file_path=True,
+ is_win_path=self._is_win)
+
+ @property
+ def path(self):
+ """Path to extension source directory."""
+ return self._path
+
+ @property
+ def local_path(self):
+ """Path to extension destination directory, for remote instances of
+ chrome"""
+ return self._local_path
+
+ @local_path.setter
+ def local_path(self, local_path):
+ self._local_path = local_path
+
+ @property
+ def is_component(self):
+ """Whether this extension should be loaded as a component extension."""
+ return self._is_component
diff --git a/chromium/tools/telemetry/telemetry/core/extension_unittest.py b/chromium/tools/telemetry/telemetry/core/extension_unittest.py
new file mode 100644
index 00000000000..eb3b5961722
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/extension_unittest.py
@@ -0,0 +1,162 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import shutil
+import tempfile
+import unittest
+
+from telemetry.core import browser_finder
+from telemetry.core import extension_to_load
+from telemetry.core.chrome import extension_dict_backend
+from telemetry.unittest import options_for_unittests
+
+class ExtensionTest(unittest.TestCase):
+ def setUp(self):
+ extension_path = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data', 'simple_extension')
+
+ options = options_for_unittests.GetCopy()
+ load_extension = extension_to_load.ExtensionToLoad(
+ extension_path, options.browser_type)
+ options.extensions_to_load = [load_extension]
+ browser_to_create = browser_finder.FindBrowser(options)
+
+ self._browser = None
+ self._extension = None
+ if not browser_to_create:
+ # May not find a browser that supports extensions.
+ return
+ self._browser = browser_to_create.Create()
+ self._browser.Start()
+ self._extension = self._browser.extensions[load_extension]
+ self.assertTrue(self._extension)
+
+ def tearDown(self):
+ if self._browser:
+ self._browser.Close()
+
+ def testExtensionBasic(self):
+ """Test ExtensionPage's ExecuteJavaScript and EvaluateJavaScript."""
+ if not self._extension:
+ logging.warning('Did not find a browser that supports extensions, '
+ 'skipping test.')
+ return
+ self._extension.ExecuteJavaScript('setTestVar("abcdef")')
+ self.assertEquals('abcdef',
+ self._extension.EvaluateJavaScript('_testVar'))
+
+ def testDisconnect(self):
+ """Test that ExtensionPage.Disconnect exists by calling it.
+ EvaluateJavaScript should reconnect."""
+ if not self._extension:
+ logging.warning('Did not find a browser that supports extensions, '
+ 'skipping test.')
+ return
+ self._extension.Disconnect()
+ self.assertEquals(2, self._extension.EvaluateJavaScript('1+1'))
+
+class NonExistentExtensionTest(unittest.TestCase):
+ def testNonExistentExtensionPath(self):
+ """Test that a non-existent extension path will raise an exception."""
+ extension_path = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data', 'foo')
+ options = options_for_unittests.GetCopy()
+ self.assertRaises(extension_to_load.ExtensionPathNonExistentException,
+ lambda: extension_to_load.ExtensionToLoad(
+ extension_path, options.browser_type))
+
+ def testExtensionNotLoaded(self):
+ """Querying an extension that was not loaded will return None"""
+ extension_path = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data', 'simple_extension')
+ options = options_for_unittests.GetCopy()
+ load_extension = extension_to_load.ExtensionToLoad(
+ extension_path, options.browser_type)
+ browser_to_create = browser_finder.FindBrowser(options)
+ with browser_to_create.Create() as b:
+ b.Start()
+ if b.supports_extensions:
+ self.assertRaises(extension_dict_backend.ExtensionNotFoundException,
+ lambda: b.extensions[load_extension])
+
+class MultipleExtensionTest(unittest.TestCase):
+ def setUp(self):
+ """ Copy the manifest and background.js files of simple_extension to a
+ number of temporary directories to load as extensions"""
+ self._extension_dirs = [tempfile.mkdtemp()
+ for i in range(3)] # pylint: disable=W0612
+ src_extension_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data', 'simple_extension'))
+ manifest_path = os.path.join(src_extension_dir, 'manifest.json')
+ script_path = os.path.join(src_extension_dir, 'background.js')
+ for d in self._extension_dirs:
+ shutil.copy(manifest_path, d)
+ shutil.copy(script_path, d)
+ options = options_for_unittests.GetCopy()
+ self._extensions_to_load = [extension_to_load.ExtensionToLoad(
+ d, options.browser_type)
+ for d in self._extension_dirs]
+ options.extensions_to_load = self._extensions_to_load
+ browser_to_create = browser_finder.FindBrowser(options)
+ self._browser = None
+ # May not find a browser that supports extensions.
+ if browser_to_create:
+ self._browser = browser_to_create.Create()
+ self._browser.Start()
+
+ def tearDown(self):
+ if self._browser:
+ self._browser.Close()
+ for d in self._extension_dirs:
+ shutil.rmtree(d)
+
+ def testMultipleExtensions(self):
+ if not self._browser:
+ logging.warning('Did not find a browser that supports extensions, '
+ 'skipping test.')
+ return
+
+ # Test contains.
+ loaded_extensions = filter(lambda e: e in self._browser.extensions,
+ self._extensions_to_load)
+ self.assertEqual(len(loaded_extensions), len(self._extensions_to_load))
+
+ for load_extension in self._extensions_to_load:
+ extension = self._browser.extensions[load_extension]
+ assert extension
+ extension.ExecuteJavaScript('setTestVar("abcdef")')
+ self.assertEquals('abcdef', extension.EvaluateJavaScript('_testVar'))
+
+class ComponentExtensionTest(unittest.TestCase):
+ def testComponentExtensionBasic(self):
+ extension_path = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data', 'component_extension')
+ options = options_for_unittests.GetCopy()
+ load_extension = extension_to_load.ExtensionToLoad(
+ extension_path, options.browser_type, is_component=True)
+
+ options.extensions_to_load = [load_extension]
+ browser_to_create = browser_finder.FindBrowser(options)
+ if not browser_to_create:
+ logging.warning('Did not find a browser that supports extensions, '
+ 'skipping test.')
+ return
+
+ with browser_to_create.Create() as b:
+ b.Start()
+ extension = b.extensions[load_extension]
+ extension.ExecuteJavaScript('setTestVar("abcdef")')
+ self.assertEquals('abcdef', extension.EvaluateJavaScript('_testVar'))
+
+ def testComponentExtensionNoPublicKey(self):
+ # simple_extension does not have a public key.
+ extension_path = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data', 'simple_extension')
+ options = options_for_unittests.GetCopy()
+ self.assertRaises(extension_to_load.MissingPublicKeyException,
+ lambda: extension_to_load.ExtensionToLoad(
+ extension_path,
+ browser_type=options.browser_type,
+ is_component=True))
diff --git a/chromium/tools/telemetry/telemetry/core/memory_cache_http_server.py b/chromium/tools/telemetry/telemetry/core/memory_cache_http_server.py
new file mode 100644
index 00000000000..76023281912
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/memory_cache_http_server.py
@@ -0,0 +1,192 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import BaseHTTPServer
+from collections import namedtuple
+import gzip
+import mimetypes
+import os
+import SimpleHTTPServer
+import SocketServer
+import StringIO
+import sys
+
+
+ByteRange = namedtuple('ByteRange', ['from_byte', 'to_byte'])
+ResourceAndRange = namedtuple('ResourceAndRange', ['resource', 'byte_range'])
+
+
+class MemoryCacheHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+
+ def do_GET(self):
+ """Serve a GET request."""
+ resource_range = self.SendHead()
+
+ if not resource_range or not resource_range.resource:
+ return
+ response = resource_range.resource['response']
+
+ if not resource_range.byte_range:
+ self.wfile.write(response)
+ return
+
+ start_index = resource_range.byte_range.from_byte
+ end_index = resource_range.byte_range.to_byte
+ self.wfile.write(response[start_index:end_index + 1])
+
+ def do_HEAD(self):
+ """Serve a HEAD request."""
+ self.SendHead()
+
+ def SendHead(self):
+ path = self.translate_path(self.path)
+ if path not in self.server.resource_map:
+ self.send_error(404, 'File not found')
+ return None
+
+ resource = self.server.resource_map[path]
+ total_num_of_bytes = resource['content-length']
+ byte_range = self.GetByteRange(total_num_of_bytes)
+ if byte_range:
+ # request specified a range, so set response code to 206.
+ self.send_response(206)
+ self.send_header('Content-Range',
+ 'bytes %d-%d/%d' % (byte_range.from_byte,
+ byte_range.to_byte,
+ total_num_of_bytes))
+ total_num_of_bytes = byte_range.to_byte - byte_range.from_byte + 1
+ else:
+ self.send_response(200)
+
+ self.send_header('Content-Length', str(total_num_of_bytes))
+ self.send_header('Content-Type', resource['content-type'])
+ self.send_header('Last-Modified',
+ self.date_time_string(resource['last-modified']))
+ if resource['zipped']:
+ self.send_header('Content-Encoding', 'gzip')
+ self.end_headers()
+ return ResourceAndRange(resource, byte_range)
+
+ def GetByteRange(self, total_num_of_bytes):
+ """Parse the header and get the range values specified.
+
+ Args:
+ total_num_of_bytes: Total # of bytes in requested resource,
+ used to calculate upper range limit.
+ Returns:
+ A ByteRange namedtuple object with the requested byte-range values.
+ If no Range is explicitly requested or there is a failure parsing,
+ return None.
+ Special case: If range specified is in the format "N-", return N-N.
+ If upper range limit is greater than total # of bytes, return upper index.
+ """
+
+ range_header = self.headers.getheader('Range')
+ if range_header is None:
+ return None
+ if not range_header.startswith('bytes='):
+ return None
+
+ # The range header is expected to be a string in this format:
+ # bytes=0-1
+ # Get the upper and lower limits of the specified byte-range.
+ # We've already confirmed that range_header starts with 'bytes='.
+ byte_range_values = range_header[len('bytes='):].split('-')
+ from_byte = 0
+ to_byte = 0
+
+ if len(byte_range_values) == 2:
+ from_byte = int(byte_range_values[0])
+ if byte_range_values[1]:
+ to_byte = int(byte_range_values[1])
+ else:
+ return None
+
+ # Do some validation.
+ if from_byte < 0:
+ return None
+
+ if to_byte < from_byte:
+ to_byte = from_byte
+
+ if to_byte >= total_num_of_bytes:
+ # End of range requested is greater than length of requested resource.
+ # Only return # of available bytes.
+ to_byte = total_num_of_bytes - 1
+
+ return ByteRange(from_byte, to_byte)
+
+
+class MemoryCacheHTTPServer(SocketServer.ThreadingMixIn,
+ BaseHTTPServer.HTTPServer):
+ # Increase the request queue size. The default value, 5, is set in
+ # SocketServer.TCPServer (the parent of BaseHTTPServer.HTTPServer).
+ # Since we're intercepting many domains through this single server,
+ # it is quite possible to get more than 5 concurrent requests.
+ request_queue_size = 128
+
+ def __init__(self, host_port, handler, paths):
+ BaseHTTPServer.HTTPServer.__init__(self, host_port, handler)
+ self.resource_map = {}
+ for path in paths:
+ if os.path.isdir(path):
+ self.AddDirectoryToResourceMap(path)
+ else:
+ self.AddFileToResourceMap(path)
+
+ def AddDirectoryToResourceMap(self, directory_path):
+ """Loads all files in directory_path into the in-memory resource map."""
+ for root, dirs, files in os.walk(directory_path):
+ # Skip hidden files and folders (like .svn and .git).
+ files = [f for f in files if f[0] != '.']
+ dirs[:] = [d for d in dirs if d[0] != '.']
+
+ for f in files:
+ file_path = os.path.join(root, f)
+ if not os.path.exists(file_path): # Allow for '.#' files
+ continue
+ self.AddFileToResourceMap(file_path)
+
+ def AddFileToResourceMap(self, file_path):
+ """Loads file_path into the in-memory resource map."""
+ with open(file_path, 'rb') as fd:
+ response = fd.read()
+ fs = os.fstat(fd.fileno())
+ content_type = mimetypes.guess_type(file_path)[0]
+ zipped = False
+ if content_type in ['text/html', 'text/css', 'application/javascript']:
+ zipped = True
+ sio = StringIO.StringIO()
+ gzf = gzip.GzipFile(fileobj=sio, compresslevel=9, mode='wb')
+ gzf.write(response)
+ gzf.close()
+ response = sio.getvalue()
+ sio.close()
+ self.resource_map[file_path] = {
+ 'content-type': content_type,
+ 'content-length': len(response),
+ 'last-modified': fs.st_mtime,
+ 'response': response,
+ 'zipped': zipped
+ }
+
+ index = os.path.sep + 'index.html'
+ if file_path.endswith(index):
+ self.resource_map[
+ file_path[:-len(index)]] = self.resource_map[file_path]
+
+
+def Main():
+ assert len(sys.argv) > 2, 'usage: %prog <port> [<path1>, <path2>, ...]'
+
+ port = int(sys.argv[1])
+ paths = sys.argv[2:]
+ server_address = ('127.0.0.1', port)
+ MemoryCacheHTTPRequestHandler.protocol_version = 'HTTP/1.1'
+ httpd = MemoryCacheHTTPServer(server_address, MemoryCacheHTTPRequestHandler,
+ paths)
+ httpd.serve_forever()
+
+
+if __name__ == '__main__':
+ Main()
diff --git a/chromium/tools/telemetry/telemetry/core/platform/__init__.py b/chromium/tools/telemetry/telemetry/core/platform/__init__.py
new file mode 100644
index 00000000000..372915956c5
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/__init__.py
@@ -0,0 +1,123 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+from telemetry.core.platform import linux_platform_backend
+from telemetry.core.platform import mac_platform_backend
+from telemetry.core.platform import win_platform_backend
+
+class Platform(object):
+ """The platform that the target browser is running on.
+
+ Provides a limited interface to interact with the platform itself, where
+ possible. It's important to note that platforms may not provide a specific
+ API, so check with IsFooBar() for availability.
+ """
+ def __init__(self, platform_backend):
+ self._platform_backend = platform_backend
+
+ def IsRawDisplayFrameRateSupported(self):
+ """Platforms may be able to collect GL surface stats."""
+ return self._platform_backend.IsRawDisplayFrameRateSupported()
+
+ def StartRawDisplayFrameRateMeasurement(self):
+ """Start measuring GL surface stats."""
+ return self._platform_backend.StartRawDisplayFrameRateMeasurement()
+
+ def StopRawDisplayFrameRateMeasurement(self):
+ """Stop measuring GL surface stats."""
+ return self._platform_backend.StopRawDisplayFrameRateMeasurement()
+
+ class RawDisplayFrameRateMeasurement(object):
+ def __init__(self, name, value, unit):
+ self._name = name
+ self._value = value
+ self._unit = unit
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def value(self):
+ return self._value
+
+ @property
+ def unit(self):
+ return self._unit
+
+ def GetRawDisplayFrameRateMeasurements(self):
+ """Returns a list of RawDisplayFrameRateMeasurement."""
+ return self._platform_backend.GetRawDisplayFrameRateMeasurements()
+
+ def SetFullPerformanceModeEnabled(self, enabled):
+ """Platforms may tweak their CPU governor, system status, etc.
+
+ Most platforms can operate in a battery saving mode. While good for battery
+ life, this can cause confusing performance results and add noise. Turning
+ full performance mode on disables these features, which is useful for
+ performance testing.
+ """
+ return self._platform_backend.SetFullPerformanceModeEnabled(enabled)
+
+ def CanMonitorThermalThrottling(self):
+ """Platforms may be able to detect thermal throttling.
+
+ Some fan-less computers go into a reduced performance mode when their heat
+ exceeds a certain threshold. Performance tests in particular should use this
+ API to detect if this has happened and interpret results accordingly.
+ """
+ return self._platform_backend.CanMonitorThermalThrottling()
+
+ def IsThermallyThrottled(self):
+ """Returns True if the device is currently thermally throttled."""
+ return self._platform_backend.IsThermallyThrottled()
+
+ def HasBeenThermallyThrottled(self):
+ """Returns True if the device has been thermally throttled."""
+ return self._platform_backend.HasBeenThermallyThrottled()
+
+ def GetOSName(self):
+ """Returns a string description of the Platform OS.
+
+ Examples: WIN, MAC, LINUX, CHROMEOS"""
+ return self._platform_backend.GetOSName()
+
+ def GetOSVersionName(self):
+ """Returns a string description of the Platform OS version.
+
+ Examples: VISTA, WIN7, LION, MOUNTAINLION"""
+ return self._platform_backend.GetOSVersionName()
+
+ def CanFlushIndividualFilesFromSystemCache(self):
+ """Returns true if the disk cache can be flushed for specific files."""
+ return self._platform_backend.CanFlushIndividualFilesFromSystemCache()
+
+ def FlushEntireSystemCache(self):
+ """Flushes the OS's file cache completely.
+
+ This function may require root or administrator access."""
+ return self._platform_backend.FlushEntireSystemCache()
+
+ def FlushSystemCacheForDirectory(self, directory, ignoring=None):
+ """Flushes the OS's file cache for the specified directory.
+
+ Any files or directories inside |directory| matching a name in the
+ |ignoring| list will be skipped.
+
+ This function does not require root or administrator access."""
+ return self._platform_backend.FlushSystemCacheForDirectory(
+ directory, ignoring=ignoring)
+
+
+def CreatePlatformBackendForCurrentOS():
+ if sys.platform.startswith('linux'):
+ return linux_platform_backend.LinuxPlatformBackend()
+ elif sys.platform == 'darwin':
+ return mac_platform_backend.MacPlatformBackend()
+ elif sys.platform == 'win32':
+ return win_platform_backend.WinPlatformBackend()
+ else:
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/core/platform/android_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/android_platform_backend.py
new file mode 100644
index 00000000000..a879a7faac5
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/android_platform_backend.py
@@ -0,0 +1,134 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import sys
+
+from telemetry.core import platform
+from telemetry.core.platform import platform_backend
+
+# Get build/android scripts into our path.
+sys.path.append(
+ os.path.abspath(
+ os.path.join(os.path.dirname(__file__),
+ '../../../build/android')))
+
+from pylib import perf_tests_helper # pylint: disable=F0401
+from pylib import thermal_throttle # pylint: disable=F0401
+
+try:
+ from pylib import surface_stats_collector # pylint: disable=F0401
+except Exception:
+ surface_stats_collector = None
+
+
+class AndroidPlatformBackend(platform_backend.PlatformBackend):
+ def __init__(self, adb, no_performance_mode):
+ super(AndroidPlatformBackend, self).__init__()
+ self._adb = adb
+ self._surface_stats_collector = None
+ self._perf_tests_setup = perf_tests_helper.PerfControl(self._adb)
+ self._thermal_throttle = thermal_throttle.ThermalThrottle(self._adb)
+ self._no_performance_mode = no_performance_mode
+ self._raw_display_frame_rate_measurements = []
+ if self._no_performance_mode:
+ logging.warning('CPU governor will not be set!')
+
+ def IsRawDisplayFrameRateSupported(self):
+ return True
+
+ def StartRawDisplayFrameRateMeasurement(self):
+ assert not self._surface_stats_collector
+ # Clear any leftover data from previous timed out tests
+ self._raw_display_frame_rate_measurements = []
+ self._surface_stats_collector = \
+ surface_stats_collector.SurfaceStatsCollector(self._adb)
+ self._surface_stats_collector.Start()
+
+ def StopRawDisplayFrameRateMeasurement(self):
+ self._surface_stats_collector.Stop()
+ for r in self._surface_stats_collector.GetResults():
+ self._raw_display_frame_rate_measurements.append(
+ platform.Platform.RawDisplayFrameRateMeasurement(
+ r.name, r.value, r.unit))
+
+ self._surface_stats_collector = None
+
+ def GetRawDisplayFrameRateMeasurements(self):
+ ret = self._raw_display_frame_rate_measurements
+ self._raw_display_frame_rate_measurements = []
+ return ret
+
+ def SetFullPerformanceModeEnabled(self, enabled):
+ if self._no_performance_mode:
+ return
+ if enabled:
+ self._perf_tests_setup.SetHighPerfMode()
+ else:
+ self._perf_tests_setup.SetDefaultPerfMode()
+
+ def CanMonitorThermalThrottling(self):
+ return True
+
+ def IsThermallyThrottled(self):
+ return self._thermal_throttle.IsThrottled()
+
+ def HasBeenThermallyThrottled(self):
+ return self._thermal_throttle.HasBeenThrottled()
+
+ def GetSystemCommitCharge(self):
+ for line in self._adb.RunShellCommand('dumpsys meminfo', log_result=False):
+ if line.startswith('Total PSS: '):
+ return int(line.split()[2]) * 1024
+ return 0
+
+ def GetMemoryStats(self, pid):
+ memory_usage = self._adb.GetMemoryUsageForPid(pid)[0]
+ return {'ProportionalSetSize': memory_usage['Pss'] * 1024,
+ 'PrivateDirty': memory_usage['Private_Dirty'] * 1024}
+
+ def GetIOStats(self, pid):
+ return {}
+
+ def GetChildPids(self, pid):
+ child_pids = []
+ ps = self._adb.RunShellCommand('ps', log_result=False)[1:]
+ for line in ps:
+ data = line.split()
+ curr_pid = data[1]
+ curr_name = data[-1]
+ if int(curr_pid) == pid:
+ name = curr_name
+ for line in ps:
+ data = line.split()
+ curr_pid = data[1]
+ curr_name = data[-1]
+ if curr_name.startswith(name) and curr_name != name:
+ child_pids.append(int(curr_pid))
+ break
+ return child_pids
+
+ def GetCommandLine(self, pid):
+ ps = self._adb.RunShellCommand('ps', log_result=False)[1:]
+ for line in ps:
+ data = line.split()
+ curr_pid = data[1]
+ curr_name = data[-1]
+ if int(curr_pid) == pid:
+ return curr_name
+ raise Exception("Could not get command line for %d" % pid)
+
+ def GetOSName(self):
+ return 'android'
+
+ def CanFlushIndividualFilesFromSystemCache(self):
+ return False
+
+ def FlushEntireSystemCache(self):
+ cache_control = perf_tests_helper.CacheControl(self._adb.Adb())
+ cache_control.DropRamCaches()
+
+ def FlushSystemCacheForDirectory(self, directory, ignoring=None):
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/core/platform/cros_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/cros_platform_backend.py
new file mode 100644
index 00000000000..02f6a71b89d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/cros_platform_backend.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core.platform import platform_backend
+from telemetry.core.platform import proc_util
+
+
+class CrosPlatformBackend(platform_backend.PlatformBackend):
+
+ def __init__(self, cri):
+ super(CrosPlatformBackend, self).__init__()
+ self._cri = cri
+
+ def StartRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def StopRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def GetRawDisplayFrameRateMeasurements(self):
+ raise NotImplementedError()
+
+ def IsThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def HasBeenThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def _RunCommand(self, args):
+ return self._cri.RunCmdOnDevice(args)[0]
+
+ def _GetFileContents(self, filename):
+ try:
+ return self._cri.RunCmdOnDevice(['cat', filename])[0]
+ except AssertionError:
+ return ''
+
+ def GetSystemCommitCharge(self):
+ meminfo_contents = self._GetFileContents('/proc/meminfo')
+ return proc_util.GetSystemCommitCharge(meminfo_contents)
+
+ def GetMemoryStats(self, pid):
+ status = self._GetFileContents('/proc/%s/status' % pid)
+ stats = self._GetFileContents('/proc/%s/stat' % pid).split()
+ return proc_util.GetMemoryStats(status, stats)
+
+ def GetIOStats(self, pid):
+ # There is no '/proc/<pid>/io' file on CrOS platforms
+ # Returns empty dict as it does in PlatformBackend.
+ return {}
+
+ def GetOSName(self):
+ return 'chromeos'
+
+ def GetChildPids(self, pid):
+ """Returns a list of child pids of |pid|."""
+ all_process_info = self._cri.ListProcesses()
+ processes = []
+ for pid, _, ppid, state in all_process_info:
+ processes.append((pid, ppid, state))
+ return proc_util.GetChildPids(processes, pid)
+
+ def GetCommandLine(self, pid):
+ command = self._GetPsOutput(['command'], pid)
+ return command[0] if command else None
+
+ def CanFlushIndividualFilesFromSystemCache(self):
+ return True
+
+ def FlushEntireSystemCache(self):
+ raise NotImplementedError()
+
+ def FlushSystemCacheForDirectory(self, directory, ignoring=None):
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/core/platform/desktop_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/desktop_platform_backend.py
new file mode 100644
index 00000000000..b71deab49c9
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/desktop_platform_backend.py
@@ -0,0 +1,54 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+
+from telemetry.core import util
+from telemetry.core.platform import platform_backend
+
+
+class DesktopPlatformBackend(platform_backend.PlatformBackend):
+
+ # This is an abstract class. It is OK to have abstract methods.
+ # pylint: disable=W0223
+
+ def GetFlushUtilityName(self):
+ return NotImplementedError()
+
+ def _FindNewestFlushUtility(self):
+ flush_command = None
+ flush_command_mtime = 0
+
+ chrome_root = util.GetChromiumSrcDir()
+ for build_dir, build_type in util.GetBuildDirectories():
+ candidate = os.path.join(chrome_root, build_dir, build_type,
+ self.GetFlushUtilityName())
+ if os.access(candidate, os.X_OK):
+ candidate_mtime = os.stat(candidate).st_mtime
+ if candidate_mtime > flush_command_mtime:
+ flush_command = candidate
+ flush_command_mtime = candidate_mtime
+
+ return flush_command
+
+ def FlushSystemCacheForDirectory(self, directory, ignoring=None):
+ assert directory and os.path.exists(directory), \
+ 'Target directory %s must exist' % directory
+ flush_command = self._FindNewestFlushUtility()
+ assert flush_command, \
+ 'You must build %s first' % self.GetFlushUtilityName()
+
+ args = [flush_command, '--recurse']
+ directory_contents = os.listdir(directory)
+ for item in directory_contents:
+ if not ignoring or item not in ignoring:
+ args.append(os.path.join(directory, item))
+
+ if len(args) < 3:
+ return
+
+ p = subprocess.Popen(args)
+ p.wait()
+ assert p.returncode == 0, 'Failed to flush system cache'
diff --git a/chromium/tools/telemetry/telemetry/core/platform/linux_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/linux_platform_backend.py
new file mode 100644
index 00000000000..42d6e947a84
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/linux_platform_backend.py
@@ -0,0 +1,50 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import subprocess
+
+from telemetry.core.platform import posix_platform_backend
+from telemetry.core.platform import proc_util
+
+
+class LinuxPlatformBackend(posix_platform_backend.PosixPlatformBackend):
+
+ def StartRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def StopRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def GetRawDisplayFrameRateMeasurements(self):
+ raise NotImplementedError()
+
+ def IsThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def HasBeenThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def GetSystemCommitCharge(self):
+ meminfo_contents = self._GetFileContents('/proc/meminfo')
+ return proc_util.GetSystemCommitCharge(meminfo_contents)
+
+ def GetMemoryStats(self, pid):
+ status = self._GetFileContents('/proc/%s/status' % pid)
+ stats = self._GetFileContents('/proc/%s/stat' % pid).split()
+ return proc_util.GetMemoryStats(status, stats)
+
+ def GetIOStats(self, pid):
+ io_contents = self._GetFileContents('/proc/%s/io' % pid)
+ return proc_util.GetIOStats(io_contents)
+
+ def GetOSName(self):
+ return 'linux'
+
+ def CanFlushIndividualFilesFromSystemCache(self):
+ return True
+
+ def FlushEntireSystemCache(self):
+ p = subprocess.Popen(['/sbin/sysctl', '-w', 'vm.drop_caches=3'])
+ p.wait()
+ assert p.returncode == 0, 'Failed to flush system cache'
diff --git a/chromium/tools/telemetry/telemetry/core/platform/mac_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/mac_platform_backend.py
new file mode 100644
index 00000000000..8e707151fa4
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/mac_platform_backend.py
@@ -0,0 +1,72 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+try:
+ import resource # pylint: disable=F0401
+except ImportError:
+ resource = None # Not available on all platforms
+
+from telemetry.core.platform import posix_platform_backend
+
+
+class MacPlatformBackend(posix_platform_backend.PosixPlatformBackend):
+
+ def StartRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def StopRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def GetRawDisplayFrameRateMeasurements(self):
+ raise NotImplementedError()
+
+ def IsThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def HasBeenThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def GetSystemCommitCharge(self):
+ vm_stat = self._RunCommand(['vm_stat'])
+ for stat in vm_stat.splitlines():
+ key, value = stat.split(':')
+ if key == 'Pages active':
+ pages_active = int(value.strip()[:-1]) # Strip trailing '.'
+ return pages_active * resource.getpagesize() / 1024
+ return 0
+
+ def GetMemoryStats(self, pid):
+ rss_vsz = self._GetPsOutput(['rss', 'vsz'], pid)
+ if rss_vsz:
+ rss, vsz = rss_vsz[0].split()
+ return {'VM': 1024 * int(vsz),
+ 'WorkingSetSize': 1024 * int(rss)}
+ return {}
+
+ def GetOSName(self):
+ return 'mac'
+
+ def GetOSVersionName(self):
+ os_version = os.uname()[2]
+
+ if os_version.startswith('9.'):
+ return 'leopard'
+ if os_version.startswith('10.'):
+ return 'snowleopard'
+ if os_version.startswith('11.'):
+ return 'lion'
+ if os_version.startswith('12.'):
+ return 'mountainlion'
+ #if os_version.startswith('13.'):
+ # return 'mavericks'
+
+ def CanFlushIndividualFilesFromSystemCache(self):
+ return False
+
+ def FlushEntireSystemCache(self):
+ p = subprocess.Popen(['purge'])
+ p.wait()
+ assert p.returncode == 0, 'Failed to flush system cache'
diff --git a/chromium/tools/telemetry/telemetry/core/platform/platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/platform_backend.py
new file mode 100644
index 00000000000..2465cfcc053
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/platform_backend.py
@@ -0,0 +1,59 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class PlatformBackend(object):
+ def IsRawDisplayFrameRateSupported(self):
+ return False
+
+ # pylint: disable=W0613
+ def StartRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def StopRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def GetRawDisplayFrameRateMeasurements(self):
+ raise NotImplementedError()
+
+ def SetFullPerformanceModeEnabled(self, enabled): # pylint: disable=W0613
+ pass
+
+ def CanMonitorThermalThrottling(self):
+ return False
+
+ def IsThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def HasBeenThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def GetSystemCommitCharge(self):
+ raise NotImplementedError()
+
+ def GetMemoryStats(self, pid): # pylint: disable=W0613
+ return {}
+
+ def GetIOStats(self, pid): # pylint: disable=W0613
+ return {}
+
+ def GetChildPids(self, pid): # pylint: disable=W0613
+ raise NotImplementedError()
+
+ def GetCommandLine(self, pid):
+ raise NotImplementedError()
+
+ def GetOSName(self):
+ raise NotImplementedError()
+
+ def GetOSVersionName(self):
+ return None
+
+ def CanFlushIndividualFilesFromSystemCache(self):
+ raise NotImplementedError()
+
+ def FlushEntireSystemCache(self):
+ raise NotImplementedError()
+
+ def FlushSystemCacheForDirectory(self, directory, ignoring=None):
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend.py
new file mode 100644
index 00000000000..fa20b54b930
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend.py
@@ -0,0 +1,51 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import subprocess
+
+from telemetry.core.platform import desktop_platform_backend
+from telemetry.core.platform import proc_util
+
+
+class PosixPlatformBackend(desktop_platform_backend.DesktopPlatformBackend):
+
+ # This is an abstract class. It is OK to have abstract methods.
+ # pylint: disable=W0223
+
+ def _RunCommand(self, args):
+ return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
+
+ def _GetFileContents(self, path):
+ with open(path, 'r') as f:
+ return f.read()
+
+ def _GetPsOutput(self, columns, pid=None):
+ """Returns output of the 'ps' command as a list of lines.
+ Subclass should override this function.
+
+ Args:
+ columns: A list of require columns, e.g., ['pid', 'pss'].
+ pid: If nont None, returns only the information of the process
+ with the pid.
+ """
+ args = ['ps']
+ args.extend(['-p', str(pid)] if pid != None else ['-e'])
+ for c in columns:
+ args.extend(['-o', c + '='])
+ return self._RunCommand(args).splitlines()
+
+ def GetChildPids(self, pid):
+ """Returns a list of child pids of |pid|."""
+ ps_output = self._GetPsOutput(['pid', 'ppid', 'state'])
+ processes = []
+ for pid_ppid_state in ps_output:
+ processes.append(pid_ppid_state.split())
+ return proc_util.GetChildPids(processes, pid)
+
+ def GetCommandLine(self, pid):
+ command = self._GetPsOutput(['command'], pid)
+ return command[0] if command else None
+
+ def GetFlushUtilityName(self):
+ return 'clear_system_cache'
diff --git a/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend_unittest.py b/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend_unittest.py
new file mode 100644
index 00000000000..05ccae43b93
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/posix_platform_backend_unittest.py
@@ -0,0 +1,34 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.core.platform import posix_platform_backend
+
+
+class PosixPlatformBackendTest(unittest.TestCase):
+
+ def _GetChildPids(self, mock_ps_output, pid):
+ class TestBackend(posix_platform_backend.PosixPlatformBackend):
+
+ # pylint: disable=W0223
+
+ def _GetPsOutput(self, columns, pid=None):
+ return mock_ps_output
+
+ return TestBackend().GetChildPids(pid)
+
+ def testGetChildPidsWithGrandChildren(self):
+ lines = ['1 0 S', '2 1 R', '3 2 S', '4 1 R', '5 4 R']
+ result = self._GetChildPids(lines, 1)
+ self.assertEquals(set(result), set([2, 3, 4, 5]))
+
+ def testGetChildPidsWithNoSuchPid(self):
+ lines = ['1 0 S', '2 1 R', '3 2 S', '4 1 R', '5 4 R']
+ result = self._GetChildPids(lines, 6)
+ self.assertEquals(set(result), set())
+
+ def testGetChildPidsWithZombieChildren(self):
+ lines = ['1 0 S', '2 1 R', '3 2 S', '4 1 R', '5 4 Z']
+ result = self._GetChildPids(lines, 1)
+ self.assertEquals(set(result), set([2, 3, 4]))
diff --git a/chromium/tools/telemetry/telemetry/core/platform/proc_util.py b/chromium/tools/telemetry/telemetry/core/platform/proc_util.py
new file mode 100644
index 00000000000..656eb846996
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/proc_util.py
@@ -0,0 +1,65 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from collections import defaultdict
+
+try:
+ import resource # pylint: disable=F0401
+except ImportError:
+ resource = None # Not available on all platforms
+
+
+def _ConvertKbToByte(value):
+ return int(value.replace('kB','')) * 1024
+
+
+def _GetProcFileDict(contents):
+ retval = {}
+ for line in contents.splitlines():
+ key, value = line.split(':')
+ retval[key.strip()] = value.strip()
+ return retval
+
+
+def GetSystemCommitCharge(meminfo_contents):
+ meminfo = _GetProcFileDict(meminfo_contents)
+ return (_ConvertKbToByte(meminfo['MemTotal'])
+ - _ConvertKbToByte(meminfo['MemFree'])
+ - _ConvertKbToByte(meminfo['Buffers'])
+ - _ConvertKbToByte(meminfo['Cached']))
+
+
+def GetMemoryStats(status_contents, stats):
+ status = _GetProcFileDict(status_contents)
+ if not status or not stats or 'Z' in status['State']:
+ return {}
+ return {'VM': int(stats[22]),
+ 'VMPeak': _ConvertKbToByte(status['VmPeak']),
+ 'WorkingSetSize': int(stats[23]) * resource.getpagesize(),
+ 'WorkingSetSizePeak': _ConvertKbToByte(status['VmHWM'])}
+
+
+def GetIOStats(io_contents):
+ io = _GetProcFileDict(io_contents)
+ return {'ReadOperationCount': int(io['syscr']),
+ 'WriteOperationCount': int(io['syscw']),
+ 'ReadTransferCount': int(io['rchar']),
+ 'WriteTransferCount': int(io['wchar'])}
+
+
+def GetChildPids(processes, pid):
+ child_dict = defaultdict(list)
+ for curr_pid, curr_ppid, state in processes:
+ if 'Z' in state:
+ continue # Ignore zombie processes
+ child_dict[int(curr_ppid)].append(int(curr_pid))
+ queue = [pid]
+ child_ids = []
+ while queue:
+ parent = queue.pop()
+ if parent in child_dict:
+ children = child_dict[parent]
+ queue.extend(children)
+ child_ids.extend(children)
+ return child_ids
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/__init__.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/__init__.py
new file mode 100644
index 00000000000..2e48d3316b6
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/__init__.py
@@ -0,0 +1,48 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+
+class Profiler(object):
+ """A sampling profiler provided by the platform."""
+
+ def __init__(self, browser_backend, platform_backend, output_path):
+ self._browser_backend = browser_backend
+ self._platform_backend = platform_backend
+ self._output_path = output_path
+
+ @classmethod
+ def name(cls):
+ """User-friendly name of this profiler."""
+ raise NotImplementedError()
+
+ @classmethod
+ def is_supported(cls, options):
+ """True iff this profiler is currently supported by the platform."""
+ raise NotImplementedError()
+
+ @classmethod
+ def CustomizeBrowserOptions(cls, options):
+ """Override to customize the Browser's options before it is created."""
+ pass
+
+ def _GetProcessOutputFileMap(self):
+ """Returns a dict with pid: output_file."""
+ all_pids = ([self._browser_backend.pid] +
+ self._platform_backend.GetChildPids(self._browser_backend.pid))
+
+ process_name_counts = collections.defaultdict(int)
+ process_output_file_map = {}
+ for pid in all_pids:
+ cmd_line = self._platform_backend.GetCommandLine(pid)
+ process_name = self._browser_backend.GetProcessName(cmd_line)
+ output_file = '%s.%s%s' % (self._output_path, process_name,
+ process_name_counts[process_name])
+ process_name_counts[process_name] += 1
+ process_output_file_map[pid] = output_file
+ return process_output_file_map
+
+ def CollectProfile(self):
+ """Collect the profile from the profiler."""
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/iprofiler_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/iprofiler_profiler.py
new file mode 100644
index 00000000000..4f25b1e9283
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/iprofiler_profiler.py
@@ -0,0 +1,100 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import signal
+import sys
+
+from telemetry.core import exceptions
+from telemetry.core import util
+from telemetry.core.platform import profiler
+
+# pexpect is not available on all platforms so use the third_party version.
+sys.path.append(os.path.join(
+ util.GetChromiumSrcDir(), 'third_party', 'pexpect'))
+try:
+ import pexpect # pylint: disable=F0401
+except ImportError:
+ pass
+
+
+class _SingleProcessIprofilerProfiler(object):
+ """An internal class for using iprofiler for a given process."""
+ def __init__(self, pid, output_path):
+ self._output_path = output_path
+ output_dir = os.path.dirname(self._output_path)
+ output_file = os.path.basename(self._output_path)
+ self._proc = pexpect.spawn(
+ 'iprofiler', ['-timeprofiler', '-T', '300', '-a', str(pid),
+ '-d', output_dir, '-o', output_file],
+ timeout=300)
+ while True:
+ if self._proc.getecho():
+ output = self._proc.readline().strip()
+ if not output:
+ continue
+ if 'iprofiler: Profiling process' in output:
+ break
+ print output
+ self._proc.interact(escape_character='\x0d')
+ if 'Failed to authorize rights' in output:
+ raise exceptions.ProfilingException(
+ 'Failed to authorize rights for iprofiler\n')
+ if 'iprofiler error' in output:
+ raise exceptions.ProfilingException(
+ 'Failed to start iprofiler for process %s\n' %
+ self._output_path.split('.')[1])
+ self._proc.write('\x0d')
+ print
+ def Echo():
+ return self._proc.getecho()
+ util.WaitFor(Echo, timeout=5)
+
+ def CollectProfile(self):
+ self._proc.kill(signal.SIGINT)
+ try:
+ self._proc.wait()
+ except pexpect.ExceptionPexpect:
+ pass
+ finally:
+ self._proc = None
+
+ print 'To view the profile, run:'
+ print ' open -a Instruments %s.dtps' % self._output_path
+ return self._output_path
+
+
+class IprofilerProfiler(profiler.Profiler):
+
+ def __init__(self, browser_backend, platform_backend, output_path):
+ super(IprofilerProfiler, self).__init__(
+ browser_backend, platform_backend, output_path)
+ process_output_file_map = self._GetProcessOutputFileMap()
+ self._process_profilers = []
+ for pid, output_file in process_output_file_map.iteritems():
+ if '.utility' in output_file:
+ # The utility process may not have been started by Telemetry.
+ # So we won't have permissing to profile it
+ continue
+ self._process_profilers.append(
+ _SingleProcessIprofilerProfiler(pid, output_file))
+
+ @classmethod
+ def name(cls):
+ return 'iprofiler'
+
+ @classmethod
+ def is_supported(cls, options):
+ if sys.platform != 'darwin':
+ return False
+ if not options:
+ return True
+ return (not options.browser_type.startswith('android') and
+ not options.browser_type.startswith('cros'))
+
+ def CollectProfile(self):
+ output_files = []
+ for single_process in self._process_profilers:
+ output_files.append(single_process.CollectProfile())
+ return output_files
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py
new file mode 100644
index 00000000000..efc9b649ff6
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/java_heap_profiler.py
@@ -0,0 +1,72 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import subprocess
+import threading
+
+from telemetry.core import util
+from telemetry.core.chrome import android_browser_finder
+from telemetry.core.platform import profiler
+
+class JavaHeapProfiler(profiler.Profiler):
+ """Android-specific, trigger and fetch java heap dumps."""
+
+ _DEFAULT_DEVICE_DIR = '/data/local/tmp/javaheap'
+ # TODO(bulach): expose this as a command line option somehow.
+ _DEFAULT_INTERVAL = 20
+ def __init__(self, browser_backend, platform_backend, output_path):
+ super(JavaHeapProfiler, self).__init__(
+ browser_backend, platform_backend, output_path)
+ self._run_count = 1
+
+ self._DumpJavaHeap(False)
+
+ self._timer = threading.Timer(self._DEFAULT_INTERVAL, self._OnTimer)
+ self._timer.start()
+
+ @classmethod
+ def name(cls):
+ return 'java-heap'
+
+ @classmethod
+ def is_supported(cls, options):
+ if not options:
+ return android_browser_finder.CanFindAvailableBrowsers()
+ return options.browser_type.startswith('android')
+
+ def CollectProfile(self):
+ self._timer.cancel()
+ self._DumpJavaHeap(True)
+ self._browser_backend.adb.Adb().Adb().Pull(
+ self._DEFAULT_DEVICE_DIR, self._output_path)
+ self._browser_backend.adb.RunShellCommand(
+ 'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
+ output_files = []
+ for f in os.listdir(self._output_path):
+ if os.path.splitext(f)[1] == '.aprof':
+ input_file = os.path.join(self._output_path, f)
+ output_file = input_file.replace('.aprof', '.hprof')
+ subprocess.call(['hprof-conv', input_file, output_file])
+ output_files.append(output_file)
+ return output_files
+
+ def _OnTimer(self):
+ self._DumpJavaHeap(False)
+
+ def _DumpJavaHeap(self, wait_for_completion):
+ device_dump_file = None
+ for pid in self._GetProcessOutputFileMap().iterkeys():
+ device_dump_file = '%s%s.%s.aprof' % (self._DEFAULT_DEVICE_DIR, pid,
+ self._run_count)
+ self._browser_backend.adb.RunShellCommand('am dumpheap %s %s' %
+ (pid, device_dump_file))
+ if device_dump_file and wait_for_completion:
+ util.WaitFor(lambda: self._FileSize(device_dump_file) > 0,
+ timeout=2, poll_interval=0.5)
+ self._run_count += 1
+
+ def _FileSize(self, file_name):
+ f = self._browser_backend.adb.Adb().ListPathContents(file_name)
+ return f.get(os.path.basename(file_name), (0, ))[0]
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
new file mode 100644
index 00000000000..cbe770fc440
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/perf_profiler.py
@@ -0,0 +1,128 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import re
+import signal
+import subprocess
+import sys
+import tempfile
+
+from telemetry.core.platform import profiler
+
+
+class _SingleProcessPerfProfiler(object):
+ """An internal class for using perf for a given process."""
+ def __init__(self, pid, output_file, platform_backend):
+ self._pid = pid
+ self._platform_backend = platform_backend
+ self._output_file = output_file
+ self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
+ self._proc = subprocess.Popen(
+ ['perf', 'record', '--call-graph',
+ '--pid', str(pid), '--output', output_file],
+ stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
+
+ def CollectProfile(self):
+ if ('renderer' in self._output_file and
+ not self._platform_backend.GetCommandLine(self._pid)):
+ logging.warning('Renderer was swapped out during profiling. '
+ 'To collect a full profile rerun with '
+ '"--extra-browser-args=--single-process"')
+ self._proc.send_signal(signal.SIGINT)
+ exit_code = self._proc.wait()
+ try:
+ if exit_code == 128:
+ raise Exception(
+ """perf failed with exit code 128.
+Try rerunning this script under sudo or setting
+/proc/sys/kernel/perf_event_paranoid to "-1".\nOutput:\n%s""" %
+ self._GetStdOut())
+ elif exit_code not in (0, -2):
+ raise Exception(
+ 'perf failed with exit code %d. Output:\n%s' % (exit_code,
+ self._GetStdOut()))
+ finally:
+ self._tmp_output_file.close()
+ print 'To view the profile, run:'
+ print ' perf report -n -i %s' % self._output_file
+ return self._output_file
+
+ def _GetStdOut(self):
+ self._tmp_output_file.flush()
+ try:
+ with open(self._tmp_output_file.name) as f:
+ return f.read()
+ except IOError:
+ return ''
+
+
+class PerfProfiler(profiler.Profiler):
+
+ def __init__(self, browser_backend, platform_backend, output_path):
+ super(PerfProfiler, self).__init__(
+ browser_backend, platform_backend, output_path)
+ process_output_file_map = self._GetProcessOutputFileMap()
+ self._process_profilers = []
+ for pid, output_file in process_output_file_map.iteritems():
+ if 'zygote' in output_file:
+ continue
+ self._process_profilers.append(
+ _SingleProcessPerfProfiler(pid, output_file, platform_backend))
+
+ @classmethod
+ def name(cls):
+ return 'perf'
+
+ @classmethod
+ def is_supported(cls, options):
+ if sys.platform != 'linux2':
+ return False
+ if options and (options.browser_type.startswith('android')
+ or options.browser_type.startswith('cros')):
+ return False
+ try:
+ return not subprocess.Popen(['perf', '--version'],
+ stderr=subprocess.STDOUT,
+ stdout=subprocess.PIPE).wait()
+ except OSError:
+ return False
+
+ @classmethod
+ def CustomizeBrowserOptions(cls, options):
+ options.AppendExtraBrowserArg('--no-sandbox')
+ options.AppendExtraBrowserArg('--allow-sandbox-debugging')
+
+ def CollectProfile(self):
+ output_files = []
+ for single_process in self._process_profilers:
+ output_files.append(single_process.CollectProfile())
+ return output_files
+
+ @classmethod
+ def GetTopSamples(cls, file_name, number):
+ """Parses the perf generated profile in |file_name| and returns a
+ {function: period} dict of the |number| hottests functions.
+ """
+ assert os.path.exists(file_name)
+ report = subprocess.Popen(
+ ['perf', 'report', '--show-total-period', '-U', '-t', '^', '-i',
+ file_name],
+ stdout=subprocess.PIPE, stderr=open(os.devnull, 'w')).communicate()[0]
+ period_by_function = {}
+ for line in report.split('\n'):
+ if not line or line.startswith('#'):
+ continue
+ fields = line.split('^')
+ if len(fields) != 5:
+ continue
+ period = int(fields[1])
+ function = fields[4].partition(' ')[2]
+ function = re.sub('<.*>', '', function) # Strip template params.
+ function = re.sub('[(].*[)]', '', function) # Strip function params.
+ period_by_function[function] = period
+ if len(period_by_function) == number:
+ break
+ return period_by_function
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/perf_profiler_unittest.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/perf_profiler_unittest.py
new file mode 100644
index 00000000000..8ca407ff031
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/perf_profiler_unittest.py
@@ -0,0 +1,31 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import logging
+import unittest
+
+from telemetry.core.platform.profiler import perf_profiler
+from telemetry.unittest import options_for_unittests
+
+class TestPerfProfiler(unittest.TestCase):
+ def testPerfProfiler(self):
+ options = options_for_unittests.GetCopy()
+ if not perf_profiler.PerfProfiler.is_supported(options):
+ logging.warning('PerfProfiler is not supported. Skipping test')
+ return
+
+ profile_file = os.path.join(os.path.dirname(__file__),
+ 'testdata', 'perf.profile')
+ self.assertEqual(perf_profiler.PerfProfiler.GetTopSamples(profile_file, 10),
+ { 'v8::internal::StaticMarkingVisitor::MarkMapContents': 63615201,
+ 'v8::internal::RelocIterator::next': 38271931,
+ 'v8::internal::LAllocator::MeetConstraintsBetween': 42913933,
+ 'v8::internal::FlexibleBodyVisitor::Visit': 31909537,
+ 'v8::internal::LiveRange::CreateAssignedOperand': 42913933,
+ 'void v8::internal::RelocInfo::Visit': 96878864,
+ 'WebCore::HTMLTokenizer::nextToken': 48240439,
+ 'v8::internal::Scanner::ScanIdentifierOrKeyword': 46054550,
+ 'sk_memset32_SSE2': 45121317,
+ 'v8::internal::HeapObject::Size': 39786862
+ })
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/profiler_finder.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/profiler_finder.py
new file mode 100644
index 00000000000..8810d8e0cdf
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/profiler_finder.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+from telemetry.core import discover
+from telemetry.core import util
+from telemetry.core.platform import profiler
+
+
+def _DiscoverProfilers():
+ profiler_dir = os.path.dirname(__file__)
+ return discover.DiscoverClasses(profiler_dir, util.GetTelemetryDir(),
+ profiler.Profiler).values()
+
+
+def FindProfiler(name):
+ for p in _DiscoverProfilers():
+ if p.name() == name:
+ return p
+ return None
+
+
+def GetAllAvailableProfilers(options):
+ return sorted([p.name() for p in _DiscoverProfilers()
+ if p.is_supported(options)])
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/sample_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/sample_profiler.py
new file mode 100644
index 00000000000..e5eba03e00f
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/sample_profiler.py
@@ -0,0 +1,90 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import signal
+import subprocess
+import sys
+import tempfile
+
+from telemetry.core import exceptions
+from telemetry.core import util
+from telemetry.core.platform import profiler
+
+
+class _SingleProcessSampleProfiler(object):
+ """An internal class for using iprofiler for a given process."""
+ def __init__(self, pid, output_path):
+ self._output_path = output_path
+ self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
+ self._proc = subprocess.Popen(
+ ['sample', str(pid), '-mayDie', '-file', self._output_path],
+ stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
+ def IsStarted():
+ stdout = self._GetStdOut()
+ if 'sample cannot examine process' in stdout:
+ raise exceptions.ProfilingException(
+ 'Failed to start sample for process %s\n' %
+ self._output_path.split('.')[1])
+ return 'Sampling process' in stdout
+ util.WaitFor(IsStarted, 120)
+
+ def CollectProfile(self):
+ self._proc.send_signal(signal.SIGINT)
+ exit_code = self._proc.wait()
+ try:
+ if exit_code:
+ raise Exception(
+ 'sample failed with exit code %d. Output:\n%s' % (
+ exit_code, self._GetStdOut()))
+ finally:
+ self._proc = None
+ self._tmp_output_file.close()
+
+ print 'To view the profile, run:'
+ print ' open -a TextEdit %s' % self._output_path
+
+ return self._output_path
+
+ def _GetStdOut(self):
+ self._tmp_output_file.flush()
+ try:
+ with open(self._tmp_output_file.name) as f:
+ return f.read()
+ except IOError:
+ return ''
+
+
+class SampleProfiler(profiler.Profiler):
+
+ def __init__(self, browser_backend, platform_backend, output_path):
+ super(SampleProfiler, self).__init__(
+ browser_backend, platform_backend, output_path)
+ process_output_file_map = self._GetProcessOutputFileMap()
+ self._process_profilers = []
+ for pid, output_file in process_output_file_map.iteritems():
+ if '.utility' in output_file:
+ # The utility process may not have been started by Telemetry.
+ # So we won't have permissing to profile it
+ continue
+ self._process_profilers.append(
+ _SingleProcessSampleProfiler(pid, output_file))
+
+ @classmethod
+ def name(cls):
+ return 'sample'
+
+ @classmethod
+ def is_supported(cls, options):
+ if sys.platform != 'darwin':
+ return False
+ if not options:
+ return True
+ return (not options.browser_type.startswith('android') and
+ not options.browser_type.startswith('cros'))
+
+ def CollectProfile(self):
+ output_paths = []
+ for single_process in self._process_profilers:
+ output_paths.append(single_process.CollectProfile())
+ return output_paths
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py
new file mode 100644
index 00000000000..186a8d0025d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/strace_profiler.py
@@ -0,0 +1,251 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import logging
+import re
+import signal
+import subprocess
+import sys
+import tempfile
+
+from telemetry.core.platform import profiler
+
+
+# Parses one line of strace output, for example:
+# 6052 1311456063.159722 read(8, "\1\0\0\0\0\0\0\0", 8) = 8 <0.000022>
+_STRACE_LINE_RE = re.compile(
+ '^(?P<tid>\d+)\s+'
+ '(?P<ts>\d+)'
+ '(?P<micro>.\d+)\s+'
+ '(?P<func>.*?)'
+ '[(](?P<args>.*?)[)]\s+=\s+'
+ '(?P<ret>.*?)\s+'
+ '<(?P<dur>[\d.]+)>$')
+
+_UNFINISHED_LINE_RE = re.compile(
+ '^(?P<tid>\d+)\s+'
+ '(?P<line>.*?)'
+ '<unfinished ...>$')
+
+_RESUMED_LINE_RE = re.compile(
+ '^(?P<tid>\d+)\s+'
+ '(?P<ts>\d+)'
+ '(?P<micro>.\d+)\s+'
+ '<[.][.][.]\s(?P<func>.*?)\sresumed>'
+ '(?P<line>.*?)$')
+
+_KILLED_LINE_RE = re.compile(
+ '^(?P<tid>\d+)\s+'
+ '(?P<ts>\d+)'
+ '(?P<micro>.\d+)\s+'
+ '[+][+][+] killed by SIGKILL [+][+][+]$')
+
+
+def _StraceToChromeTrace(pid, infile):
+ """Returns chrometrace json format for |infile| strace output."""
+ # Map of fd:file_name for open file descriptors. Useful for displaying
+ # file name instead of the descriptor number.
+ fd_map = {}
+
+ # Map of tid:interrupted_call for the interrupted call on each thread. It is
+ # possible to context switch during a system call. In this case we must
+ # match up the lines.
+ interrupted_call_map = {}
+
+ out = []
+ with open(infile, 'r') as f:
+ for line in f.readlines():
+ # Ignore kill lines for now.
+ m = _KILLED_LINE_RE.match(line)
+ if m:
+ continue
+
+ # If this line is interrupted, then remember it and continue.
+ m = _UNFINISHED_LINE_RE.match(line)
+ if m:
+ assert m.group('tid') not in interrupted_call_map
+ interrupted_call_map[m.group('tid')] = line
+ continue
+
+ # If this is a resume of a previous line, stitch it together.
+ interrupted = False
+ m = _RESUMED_LINE_RE.match(line)
+ if m:
+ interrupted = True
+ assert m.group('tid') in interrupted_call_map
+ line = interrupted_call_map[m.group('tid')].replace(
+ '<unfinished ...>', m.group('line'))
+ del interrupted_call_map[m.group('tid')]
+
+ # At this point we can do a normal match.
+ m = _STRACE_LINE_RE.match(line)
+ if not m:
+ if ('exit' not in line and
+ 'Profiling timer expired' not in line and
+ '<unavailable>' not in line):
+ logging.warn('Failed to parse line: %s' % line)
+ continue
+
+ ts_begin = int(1000000 * (int(m.group('ts')) + float(m.group('micro'))))
+ ts_end = ts_begin + int(1000000 * float(m.group('dur')))
+ tid = int(m.group('tid'))
+ function_name = unicode(m.group('func'), errors='ignore')
+ function_args = unicode(m.group('args'), errors='ignore')
+ ret = unicode(m.group('ret'), errors='ignore')
+ cat = 'strace'
+
+ possible_fd_arg = None
+ first_arg = function_args.split(',')[0]
+ if first_arg and first_arg.strip().isdigit():
+ possible_fd_arg = first_arg.strip()
+
+ if function_name == 'open' and ret.isdigit():
+ # 1918 1311606151.649379 open("/foo/bar.so", O_RDONLY) = 7 <0.000088>
+ fd_map[ret] = first_arg
+
+ args = {
+ 'args': function_args,
+ 'ret': ret,
+ }
+ if interrupted:
+ args['interrupted'] = True
+ if possible_fd_arg and possible_fd_arg in fd_map:
+ args['fd%s' % first_arg] = fd_map[possible_fd_arg]
+
+ out.append({
+ 'cat': cat,
+ 'pid': pid,
+ 'tid': tid,
+ 'ts': ts_begin,
+ 'ph': 'B', # Begin
+ 'name': function_name,
+ })
+ out.append({
+ 'cat': cat,
+ 'pid': pid,
+ 'tid': tid,
+ 'ts': ts_end,
+ 'ph': 'E', # End
+ 'name': function_name,
+ 'args': args,
+ })
+
+ return out
+
+
+def _GenerateTraceMetadata(model):
+ out = []
+ for process in model.processes:
+ out.append({
+ 'name': 'process_name',
+ 'ph': 'M', # Metadata
+ 'pid': process,
+ 'args': {
+ 'name': model.processes[process].name
+ }
+ })
+ for thread in model.processes[process].threads:
+ out.append({
+ 'name': 'thread_name',
+ 'ph': 'M', # Metadata
+ 'pid': process,
+ 'tid': thread,
+ 'args': {
+ 'name': model.processes[process].threads[thread].name
+ }
+ })
+ return out
+
+
+class _SingleProcessStraceProfiler(object):
+ """An internal class for using perf for a given process."""
+ def __init__(self, pid, output_file, platform_backend):
+ self._pid = pid
+ self._platform_backend = platform_backend
+ self._output_file = output_file
+ self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
+ self._proc = subprocess.Popen(
+ ['strace', '-ttt', '-f', '-T', '-p', str(pid), '-o', output_file],
+ stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
+
+ def CollectProfile(self):
+ if ('renderer' in self._output_file and
+ not self._platform_backend.GetCommandLine(self._pid)):
+ logging.warning('Renderer was swapped out during profiling. '
+ 'To collect a full profile rerun with '
+ '"--extra-browser-args=--single-process"')
+ self._proc.send_signal(signal.SIGINT)
+ exit_code = self._proc.wait()
+ try:
+ if exit_code:
+ raise Exception('strace failed with exit code %d. Output:\n%s' % (
+ exit_code, self._GetStdOut()))
+ finally:
+ self._tmp_output_file.close()
+
+ return _StraceToChromeTrace(self._pid, self._output_file)
+
+ def _GetStdOut(self):
+ self._tmp_output_file.flush()
+ try:
+ with open(self._tmp_output_file.name) as f:
+ return f.read()
+ except IOError:
+ return ''
+
+
+class StraceProfiler(profiler.Profiler):
+
+ def __init__(self, browser_backend, platform_backend, output_path):
+ super(StraceProfiler, self).__init__(
+ browser_backend, platform_backend, output_path)
+ assert self._browser_backend.supports_tracing
+ self._browser_backend.StartTracing(None, 10)
+ process_output_file_map = self._GetProcessOutputFileMap()
+ self._process_profilers = []
+ self._output_file = output_path + '.json'
+ for pid, output_file in process_output_file_map.iteritems():
+ if 'zygote' in output_file:
+ continue
+ self._process_profilers.append(
+ _SingleProcessStraceProfiler(pid, output_file, platform_backend))
+
+ @classmethod
+ def name(cls):
+ return 'strace'
+
+ @classmethod
+ def is_supported(cls, options):
+ if sys.platform != 'linux2':
+ return False
+ # TODO(tonyg): This should be supported on android and cros.
+ if options and (options.browser_type.startswith('android')
+ or options.browser_type.startswith('cros')):
+ return False
+ return True
+
+ @classmethod
+ def CustomizeBrowserOptions(cls, options):
+ options.AppendExtraBrowserArg('--no-sandbox')
+ options.AppendExtraBrowserArg('--allow-sandbox-debugging')
+
+ def CollectProfile(self):
+ print 'Processing trace...'
+
+ out_json = []
+
+ for single_process in self._process_profilers:
+ out_json.extend(single_process.CollectProfile())
+
+ self._browser_backend.StopTracing()
+ model = self._browser_backend.GetTraceResultAndReset().AsTimelineModel()
+ out_json.extend(_GenerateTraceMetadata(model))
+
+ with open(self._output_file, 'w') as f:
+ f.write(json.dumps(out_json, separators=(',', ':')))
+
+ print 'Trace saved as %s' % self._output_file
+ print 'To view, open in chrome://tracing'
+ return [self._output_file]
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py
new file mode 100644
index 00000000000..939514923e3
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/tcmalloc_heap_profiler.py
@@ -0,0 +1,125 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import sys
+
+from telemetry.core.chrome import android_browser_finder
+from telemetry.core.platform import profiler
+
+# Enviroment variables to (android properties, default value) mapping.
+_ENV_VARIABLES = {
+ 'HEAP_PROFILE_TIME_INTERVAL': ('heapprof.time_interval', 20),
+ 'HEAP_PROFILE_MMAP': ('heapprof.mmap', 1),
+ 'DEEP_HEAP_PROFILE': ('heapprof.deep_heap_profile', 1),
+}
+
+
+class _TCMallocHeapProfilerAndroid(object):
+ """An internal class to set android properties and fetch dumps from device."""
+
+ _DEFAULT_DEVICE_DIR = '/data/local/tmp/heap'
+
+ def __init__(self, browser_backend, output_path):
+ self._browser_backend = browser_backend
+ self._output_path = output_path
+
+ _ENV_VARIABLES['HEAPPROFILE'] = ('heapprof',
+ os.path.join(self._DEFAULT_DEVICE_DIR, 'dmprof'))
+
+ self._SetDeviceProperties(_ENV_VARIABLES)
+
+ def _SetDeviceProperties(self, properties):
+ device_configured = False
+ # This profiler requires adb root to set properties.
+ self._browser_backend.adb.Adb().EnableAdbRoot()
+ for values in properties.itervalues():
+ device_property = self._browser_backend.adb.RunShellCommand(
+ 'getprop ' + values[0])
+ if (not device_property or len(device_property) != 1 or
+ not device_property[0].strip()):
+ print 'Setting device property ', values[0], values[1]
+ self._browser_backend.adb.RunShellCommand(
+ 'setprop ' + values[0] + ' ' + str(values[1]))
+ device_configured = True
+ if not self._browser_backend.adb.Adb().FileExistsOnDevice(
+ self._DEFAULT_DEVICE_DIR):
+ self._browser_backend.adb.RunShellCommand(
+ 'mkdir -p ' + self._DEFAULT_DEVICE_DIR)
+ self._browser_backend.adb.RunShellCommand(
+ 'chmod 777 ' + self._DEFAULT_DEVICE_DIR)
+ device_configured = True
+ if device_configured:
+ raise Exception('Device required special config, run again.')
+
+ def CollectProfile(self):
+ self._browser_backend.adb.Adb().Adb().Pull(
+ self._DEFAULT_DEVICE_DIR, self._output_path)
+ self._browser_backend.adb.RunShellCommand(
+ 'rm ' + os.path.join(self._DEFAULT_DEVICE_DIR, '*'))
+ if os.path.exists(self._output_path):
+ logging.info('TCMalloc dumps pulled to %s', self._output_path)
+ with file(os.path.join(self._output_path,
+ 'browser.pid'), 'w') as pid_file:
+ pid_file.write(str(self._browser_backend.pid).rjust(5, '0'))
+ return [self._output_path]
+
+
+class _TCMallocHeapProfilerLinux(object):
+ """An internal class to set environment variables and fetch dumps."""
+
+ _DEFAULT_DIR = '/tmp/tcmalloc/'
+
+ def __init__(self, browser_backend):
+ self._browser_backend = browser_backend
+ _ENV_VARIABLES['HEAPPROFILE'] = ('heapprof', self._DEFAULT_DIR + 'dmprof')
+ self._CheckEnvironmentVariables(_ENV_VARIABLES)
+
+ def _CheckEnvironmentVariables(self, env_vars):
+ msg = ''
+ for key, values in env_vars.iteritems():
+ if key not in os.environ:
+ msg += '%s=%s ' % (key, str(values[1]))
+ if msg:
+ raise Exception('Need enviroment variables, try again with:\n %s' % msg)
+ if not os.path.exists(os.environ['HEAPPROFILE']):
+ os.makedirs(os.environ['HEAPPROFILE'])
+ assert os.path.isdir(os.environ['HEAPPROFILE']), 'HEAPPROFILE is not a dir'
+
+ def CollectProfile(self):
+ with file(os.path.join(os.path.dirname(os.environ['HEAPPROFILE']),
+ 'browser.pid'), 'w') as pid_file:
+ pid_file.write(str(self._browser_backend.pid))
+ print 'TCMalloc dumps available ', os.environ['HEAPPROFILE']
+ return [os.environ['HEAPPROFILE']]
+
+
+class TCMallocHeapProfiler(profiler.Profiler):
+ """A Factory to instantiate the platform-specific profiler."""
+ def __init__(self, browser_backend, platform_backend, output_path):
+ super(TCMallocHeapProfiler, self).__init__(
+ browser_backend, platform_backend, output_path)
+ if platform_backend.GetOSName() == 'android':
+ self._platform_profiler = _TCMallocHeapProfilerAndroid(
+ browser_backend, output_path)
+ else:
+ self._platform_profiler = _TCMallocHeapProfilerLinux(browser_backend)
+
+ @classmethod
+ def name(cls):
+ return 'tcmalloc-heap'
+
+ @classmethod
+ def is_supported(cls, options):
+ if options and options.browser_type.startswith('cros'):
+ return False
+ if sys.platform.startswith('linux'):
+ return True
+ if not options:
+ return android_browser_finder.CanFindAvailableBrowsers()
+ return options.browser_type.startswith('android')
+
+ def CollectProfile(self):
+ return self._platform_profiler.CollectProfile()
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py
new file mode 100644
index 00000000000..540c2b6cc8d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/tcpdump_profiler.py
@@ -0,0 +1,111 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import signal
+import subprocess
+import sys
+import tempfile
+
+from telemetry.core.chrome import android_browser_finder
+from telemetry.core.platform import profiler
+
+
+_TCP_DUMP_BASE_OPTS = ['-i', 'any', '-p', '-s', '0', '-w']
+
+class _TCPDumpProfilerAndroid(object):
+ """An internal class to collect TCP dumps on android."""
+
+ _TCP_DUMP = '/data/local/tmp/tcpdump'
+ _DEVICE_DUMP_FILE = '/sdcard/capture.pcap'
+
+ def __init__(self, adb, output_path):
+ self._adb = adb
+ self._output_path = output_path
+ self._proc = subprocess.Popen(
+ ['adb', '-s', self._adb.device(),
+ 'shell', self._TCP_DUMP] + _TCP_DUMP_BASE_OPTS +
+ [self._DEVICE_DUMP_FILE])
+
+ def CollectProfile(self):
+ tcpdump_pid = self._adb.ExtractPid('tcpdump')
+ if not tcpdump_pid or not tcpdump_pid[0]:
+ raise Exception('Unable to find TCPDump. Check your device is rooted '
+ 'and tcpdump is installed at ' + self._TCP_DUMP)
+ self._adb.RunShellCommand('kill -term ' + tcpdump_pid[0])
+ self._proc.terminate()
+ host_dump = os.path.join(self._output_path,
+ os.path.basename(self._DEVICE_DUMP_FILE))
+ self._adb.Adb().Adb().Pull(self._DEVICE_DUMP_FILE, host_dump)
+ print 'TCP dump available at: %s ' % host_dump
+ print 'Use Wireshark to open it.'
+
+
+class _TCPDumpProfilerLinux(object):
+ """An internal class to collect TCP dumps on linux desktop."""
+
+ _DUMP_FILE = 'capture.pcap'
+
+ def __init__(self, output_path):
+ if not os.path.exists(output_path):
+ os.makedirs(output_path)
+ self._dump_file = os.path.join(output_path, self._DUMP_FILE)
+ self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
+ try:
+ self._proc = subprocess.Popen(
+ ['tcpdump'] + _TCP_DUMP_BASE_OPTS + [self._dump_file],
+ stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
+ except OSError as e:
+ raise Exception('Unable to execute TCPDump, please check your '
+ 'installation. ' + str(e))
+
+ def CollectProfile(self):
+ self._proc.send_signal(signal.SIGINT)
+ exit_code = self._proc.wait()
+ try:
+ if exit_code:
+ raise Exception(
+ 'tcpdump failed with exit code %d. Output:\n%s' %
+ (exit_code, self._GetStdOut()))
+ finally:
+ self._tmp_output_file.close()
+ print 'TCP dump available at: ', self._dump_file
+ print 'Use Wireshark to open it.'
+
+ def _GetStdOut(self):
+ self._tmp_output_file.flush()
+ try:
+ with open(self._tmp_output_file.name) as f:
+ return f.read()
+ except IOError:
+ return ''
+
+
+class TCPDumpProfiler(profiler.Profiler):
+ """A Factory to instantiate the platform-specific profiler."""
+ def __init__(self, browser_backend, platform_backend, output_path):
+ super(TCPDumpProfiler, self).__init__(
+ browser_backend, platform_backend, output_path)
+ if platform_backend.GetOSName() == 'android':
+ self._platform_profiler = _TCPDumpProfilerAndroid(
+ browser_backend.adb, output_path)
+ else:
+ self._platform_profiler = _TCPDumpProfilerLinux(output_path)
+
+ @classmethod
+ def name(cls):
+ return 'tcpdump'
+
+ @classmethod
+ def is_supported(cls, options):
+ if options and options.browser_type.startswith('cros'):
+ return False
+ if sys.platform.startswith('linux'):
+ return True
+ if not options:
+ return android_browser_finder.CanFindAvailableBrowsers()
+ return options.browser_type.startswith('android')
+
+ def CollectProfile(self):
+ self._platform_profiler.CollectProfile()
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/testdata/perf.profile b/chromium/tools/telemetry/telemetry/core/platform/profiler/testdata/perf.profile
new file mode 100644
index 00000000000..db955dd809f
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/testdata/perf.profile
Binary files differ
diff --git a/chromium/tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py b/chromium/tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py
new file mode 100644
index 00000000000..f0789026805
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/profiler/trace_profiler.py
@@ -0,0 +1,41 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import codecs
+
+from telemetry.core.platform import profiler
+
+
+class TraceProfiler(profiler.Profiler):
+
+ def __init__(self, browser_backend, platform_backend, output_path):
+ super(TraceProfiler, self).__init__(
+ browser_backend, platform_backend, output_path)
+ assert self._browser_backend.supports_tracing
+ self._browser_backend.StartTracing(None, 10)
+
+ @classmethod
+ def name(cls):
+ return 'trace'
+
+ @classmethod
+ def is_supported(cls, options):
+ return True
+
+ def CollectProfile(self):
+ self._browser_backend.StopTracing()
+
+ print 'Processing trace...'
+
+ trace_result = self._browser_backend.GetTraceResultAndReset()
+
+ trace_file = '%s.json' % self._output_path
+
+ with codecs.open(trace_file, 'w', encoding='utf-8') as f:
+ trace_result.Serialize(f)
+
+ print 'Trace saved as %s' % trace_file
+ print 'To view, open in chrome://tracing'
+
+ return [trace_file]
diff --git a/chromium/tools/telemetry/telemetry/core/platform/win_platform_backend.py b/chromium/tools/telemetry/telemetry/core/platform/win_platform_backend.py
new file mode 100644
index 00000000000..71038ecb604
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/platform/win_platform_backend.py
@@ -0,0 +1,167 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import ctypes
+import os
+import re
+import subprocess
+try:
+ import pywintypes # pylint: disable=F0401
+ import win32api # pylint: disable=F0401
+ import win32con # pylint: disable=F0401
+ import win32process # pylint: disable=F0401
+except ImportError:
+ pywintypes = None
+ win32api = None
+ win32con = None
+ win32process = None
+
+from telemetry.core.platform import desktop_platform_backend
+
+
+class WinPlatformBackend(desktop_platform_backend.DesktopPlatformBackend):
+ def _GetProcessHandle(self, pid):
+ mask = (win32con.PROCESS_QUERY_INFORMATION |
+ win32con.PROCESS_VM_READ)
+ return win32api.OpenProcess(mask, False, pid)
+
+ # pylint: disable=W0613
+ def StartRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def StopRawDisplayFrameRateMeasurement(self):
+ raise NotImplementedError()
+
+ def GetRawDisplayFrameRateMeasurements(self):
+ raise NotImplementedError()
+
+ def IsThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def HasBeenThermallyThrottled(self):
+ raise NotImplementedError()
+
+ def GetSystemCommitCharge(self):
+ class PerformanceInfo(ctypes.Structure):
+ """Struct for GetPerformanceInfo() call
+ http://msdn.microsoft.com/en-us/library/ms683210
+ """
+ _fields_ = [('size', ctypes.c_ulong),
+ ('CommitTotal', ctypes.c_size_t),
+ ('CommitLimit', ctypes.c_size_t),
+ ('CommitPeak', ctypes.c_size_t),
+ ('PhysicalTotal', ctypes.c_size_t),
+ ('PhysicalAvailable', ctypes.c_size_t),
+ ('SystemCache', ctypes.c_size_t),
+ ('KernelTotal', ctypes.c_size_t),
+ ('KernelPaged', ctypes.c_size_t),
+ ('KernelNonpaged', ctypes.c_size_t),
+ ('PageSize', ctypes.c_size_t),
+ ('HandleCount', ctypes.c_ulong),
+ ('ProcessCount', ctypes.c_ulong),
+ ('ThreadCount', ctypes.c_ulong)]
+
+ def __init__(self):
+ self.size = ctypes.sizeof(self)
+ super(PerformanceInfo, self).__init__()
+
+ performance_info = PerformanceInfo()
+ ctypes.windll.psapi.GetPerformanceInfo(
+ ctypes.byref(performance_info), performance_info.size)
+ return performance_info.CommitTotal * performance_info.PageSize / 1024
+
+ def GetMemoryStats(self, pid):
+ try:
+ memory_info = win32process.GetProcessMemoryInfo(
+ self._GetProcessHandle(pid))
+ except pywintypes.error, e:
+ errcode = e[0]
+ if errcode == 87: # The process may have been closed.
+ return {}
+ raise
+ return {'VM': memory_info['PagefileUsage'],
+ 'VMPeak': memory_info['PeakPagefileUsage'],
+ 'WorkingSetSize': memory_info['WorkingSetSize'],
+ 'WorkingSetSizePeak': memory_info['PeakWorkingSetSize']}
+
+ def GetIOStats(self, pid):
+ try:
+ io_stats = win32process.GetProcessIoCounters(
+ self._GetProcessHandle(pid))
+ except pywintypes.error, e:
+ errcode = e[0]
+ if errcode == 87: # The process may have been closed.
+ return {}
+ raise
+ return {'ReadOperationCount': io_stats['ReadOperationCount'],
+ 'WriteOperationCount': io_stats['WriteOperationCount'],
+ 'ReadTransferCount': io_stats['ReadTransferCount'],
+ 'WriteTransferCount': io_stats['WriteTransferCount']}
+
+ def GetChildPids(self, pid):
+ """Retunds a list of child pids of |pid|."""
+ creation_ppid_pid_list = subprocess.Popen(
+ ['wmic', 'process', 'get', 'CreationDate,ParentProcessId,ProcessId',
+ '/format:csv'],
+ stdout=subprocess.PIPE).communicate()[0]
+ ppid_map = collections.defaultdict(list)
+ creation_map = {}
+ # [3:] To skip 2 blank lines and header.
+ for creation_ppid_pid in creation_ppid_pid_list.splitlines()[3:]:
+ if not creation_ppid_pid:
+ continue
+ _, creation, curr_ppid, curr_pid = creation_ppid_pid.split(',')
+ ppid_map[int(curr_ppid)].append(int(curr_pid))
+ if creation:
+ creation_map[int(curr_pid)] = float(re.split('[+-]', creation)[0])
+
+ def _InnerGetChildPids(pid):
+ if not pid or pid not in ppid_map:
+ return []
+ ret = [p for p in ppid_map[pid] if creation_map[p] >= creation_map[pid]]
+ for child in ret:
+ if child == pid:
+ continue
+ ret.extend(_InnerGetChildPids(child))
+ return ret
+
+ return _InnerGetChildPids(pid)
+
+ def GetCommandLine(self, pid):
+ command_pid_list = subprocess.Popen(
+ ['wmic', 'process', 'get', 'CommandLine,ProcessId',
+ '/format:csv'],
+ stdout=subprocess.PIPE).communicate()[0]
+ # [3:] To skip 2 blank lines and header.
+ for command_pid in command_pid_list.splitlines()[3:]:
+ if not command_pid:
+ continue
+ parts = command_pid.split(',')
+ curr_pid = parts[-1]
+ if pid == int(curr_pid):
+ command = ','.join(parts[1:-1])
+ return command
+ raise Exception('Could not get command line for %d' % pid)
+
+ def GetOSName(self):
+ return 'win'
+
+ def GetOSVersionName(self):
+ os_version = os.uname()[2]
+
+ if os_version.startswith('5.1.'):
+ return 'xp'
+ if os_version.startswith('6.0.'):
+ return 'vista'
+ if os_version.startswith('6.1.'):
+ return 'win7'
+ if os_version.startswith('6.2.'):
+ return 'win8'
+
+ def CanFlushIndividualFilesFromSystemCache(self):
+ return True
+
+ def GetFlushUtilityName(self):
+ return 'clear_system_cache.exe'
diff --git a/chromium/tools/telemetry/telemetry/core/possible_browser.py b/chromium/tools/telemetry/telemetry/core/possible_browser.py
new file mode 100644
index 00000000000..3c55c228533
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/possible_browser.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+class PossibleBrowser(object):
+ """A browser that can be controlled.
+
+ Call Create() to launch the browser and begin manipulating it..
+ """
+
+ def __init__(self, browser_type, options):
+ self._browser_type = browser_type
+ self._options = options
+
+ def __repr__(self):
+ return 'PossibleBrowser(browser_type=%s)' % self.browser_type
+
+ @property
+ def browser_type(self):
+ return self._browser_type
+
+ @property
+ def options(self):
+ return self._options
+
+ def Create(self):
+ raise NotImplementedError()
+
+ def SupportsOptions(self, options):
+ """Tests for extension support."""
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/core/profile_creator.py b/chromium/tools/telemetry/telemetry/core/profile_creator.py
new file mode 100644
index 00000000000..29a2cbbec57
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/profile_creator.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class ProfileCreator(object):
+ """Base class for an object that constructs a Chrome profile."""
+
+ def __init__(self, browser):
+ self._browser = browser
+
+ def CreateProfile(self):
+ """Fill in the profile in question."""
+ raise NotImplementedError
diff --git a/chromium/tools/telemetry/telemetry/core/profile_types.py b/chromium/tools/telemetry/telemetry/core/profile_types.py
new file mode 100644
index 00000000000..92a8a777aea
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/profile_types.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+from telemetry.core import discover
+from telemetry.core import profile_creator
+
+BASE_PROFILE_TYPES = ['clean', 'default']
+
+PROFILE_CREATORS = {}
+
+PROFILE_TYPE_MAPPING = {
+ 'typical_user': 'chrome/test/data/extensions/profiles/content_scripts1',
+ 'power_user': 'chrome/test/data/extensions/profiles/extension_webrequest',
+}
+
+def _DiscoverCreateableProfiles(profile_creators_dir, base_dir):
+ """Returns a dictionary of all the profile creators we can use to create
+ a Chrome profile for testing located in |profile_creators_dir|.
+ The returned value consists of 'class_name' -> 'test class' dictionary where
+ class_name is the name of the class with the _creator suffix removed e.g.
+ 'small_profile_creator will be 'small_profile'.
+ """
+ profile_creators_unfiltered = discover.DiscoverClasses(
+ profile_creators_dir, base_dir, profile_creator.ProfileCreator)
+
+ # Remove '_creator' suffix from keys.
+ profile_creators = {}
+ for test_name, test_class in profile_creators_unfiltered.iteritems():
+ assert test_name.endswith('_creator')
+ test_name = test_name[:-len('_creator')]
+ profile_creators[test_name] = test_class
+
+ return profile_creators
+
+def ClearProfieCreatorsForTests():
+ """Clears the discovered profile creator objects. Used for unit tests."""
+ PROFILE_CREATORS.clear()
+
+def FindProfileCreators(profile_creators_dir, base_dir):
+ """Discover all the ProfileCreator objects in |profile_creators_dir|."""
+ assert not PROFILE_CREATORS # It's illegal to call this function twice.
+ PROFILE_CREATORS.update(_DiscoverCreateableProfiles(
+ profile_creators_dir, base_dir))
+
+def GetProfileTypes():
+ """Returns a list of all command line options that can be specified for
+ profile type."""
+ return (BASE_PROFILE_TYPES + PROFILE_TYPE_MAPPING.keys() +
+ PROFILE_CREATORS.keys())
+
+def GetProfileDir(profile_type):
+ """Given a |profile_type| (as returned by GetProfileTypes()), return the
+ directory to use for that profile or None if the profile needs to be generated
+ or doesn't need a profile directory (e.g. using the browser default profile).
+ """
+ if (profile_type in BASE_PROFILE_TYPES or
+ profile_type in PROFILE_CREATORS):
+ return None
+
+ path = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', '..', *PROFILE_TYPE_MAPPING[profile_type].split('/')))
+ assert os.path.exists(path)
+ return path
+
+def GetProfileCreator(profile_type):
+ """Returns the profile creator object corresponding to the |profile_type|
+ string."""
+ return PROFILE_CREATORS.get(profile_type)
diff --git a/chromium/tools/telemetry/telemetry/core/profile_types_unittest.py b/chromium/tools/telemetry/telemetry/core/profile_types_unittest.py
new file mode 100644
index 00000000000..3dcab2e6a2a
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/profile_types_unittest.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from telemetry.core import profile_types
+from telemetry.core import util
+
+class ProfileTypesTest(unittest.TestCase):
+ def testGetProfileTypes(self):
+ types = profile_types.GetProfileTypes()
+
+ self.assertTrue('clean' in types)
+ self.assertTrue(len(types) > 0)
+
+ def testGetProfileDir(self):
+ self.assertFalse(profile_types.GetProfileDir('typical_user') is None)
+
+ def testGetProfileCreatorTypes(self):
+ profile_creators_dir = os.path.join(
+ util.GetUnittestDataDir(), 'discoverable_classes')
+ base_dir = util.GetUnittestDataDir()
+
+ profile_types.FindProfileCreators(profile_creators_dir, base_dir)
+ types = profile_types.GetProfileTypes()
+ self.assertTrue(len(types) > 0)
+ self.assertTrue('dummy_profile' in types)
+
+ dummy_profile_creator = profile_types.GetProfileCreator('dummy_profile')
+ self.assertTrue(dummy_profile_creator.__name__ == 'DummyProfileCreator')
+ profile_types.ClearProfieCreatorsForTests()
diff --git a/chromium/tools/telemetry/telemetry/core/repeat_options.py b/chromium/tools/telemetry/telemetry/core/repeat_options.py
new file mode 100644
index 00000000000..9836dea2267
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/repeat_options.py
@@ -0,0 +1,61 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import optparse
+import re
+
+
+class RepeatOptions(object):
+ def __init__(self, page_repeat_secs=None, pageset_repeat_secs=None,
+ page_repeat_iters=None, pageset_repeat_iters=None):
+ self.page_repeat_secs = page_repeat_secs
+ self.pageset_repeat_secs = pageset_repeat_secs
+ self.page_repeat_iters = page_repeat_iters
+ self.pageset_repeat_iters = pageset_repeat_iters
+
+ def __deepcopy__(self, _):
+ return RepeatOptions(self.page_repeat_secs, self.pageset_repeat_secs,
+ self.page_repeat_iters, self.pageset_repeat_iters)
+
+ @staticmethod
+ def AddCommandLineOptions(parser):
+ group = optparse.OptionGroup(parser, 'Repeat options')
+ group.add_option('--page-repeat', dest='page_repeat', default='1',
+ help='Number of iterations or length of time to repeat '
+ 'each individual page in the pageset before proceeding. '
+ 'Append an \'s\' to specify length of time in seconds. '
+ 'e.g., \'10\' to repeat for 10 iterations, or \'30s\' to '
+ 'repeat for 30 seconds.')
+ group.add_option('--pageset-repeat', dest='pageset_repeat', default='1',
+ help='Number of iterations or length of time to repeat '
+ 'the entire pageset before finishing. Append an \'s\' '
+ 'to specify length of time in seconds. e.g., \'10\' to '
+ 'repeat for 10 iterations, or \'30s\' to repeat for 30 '
+ 'seconds.')
+ parser.add_option_group(group)
+
+ def _ParseRepeatOption(self, browser_options, input_str, parser):
+ match = re.match('([0-9]+)([sS]?)$', str(getattr(browser_options,
+ input_str, '')))
+ if match:
+ if match.group(2):
+ setattr(self, input_str + '_secs', float(match.group(1)))
+ # Set _iters to the default value
+ setattr(self, input_str + '_iters', 1)
+ else:
+ setattr(self, input_str + '_iters', int(match.group(1)))
+ delattr(browser_options, input_str)
+ else:
+ parser.error('Usage: --%s only accepts an int '
+ 'followed by only an \'s\' if using time. '
+ 'e.g. \'10\' or \'10s\'\n' % input_str.replace('_','-'))
+
+ def UpdateFromParseResults(self, browser_options, parser):
+ self._ParseRepeatOption(browser_options, 'page_repeat', parser)
+ self._ParseRepeatOption(browser_options, 'pageset_repeat', parser)
+
+ def IsRepeating(self):
+ """Returns True if we will be repeating pages or pagesets."""
+ return (self.page_repeat_iters != 1 or self.pageset_repeat_iters != 1 or
+ self.page_repeat_secs or self.pageset_repeat_secs) \ No newline at end of file
diff --git a/chromium/tools/telemetry/telemetry/core/tab.py b/chromium/tools/telemetry/telemetry/core/tab.py
new file mode 100644
index 00000000000..b129a8371de
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/tab.py
@@ -0,0 +1,104 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core import web_contents
+
+DEFAULT_TAB_TIMEOUT = 60
+
+class Tab(web_contents.WebContents):
+ """Represents a tab in the browser
+
+ The important parts of the Tab object are in the runtime and page objects.
+ E.g.:
+ # Navigates the tab to a given url.
+ tab.Navigate('http://www.google.com/')
+
+ # Evaluates 1+1 in the tab's JavaScript context.
+ tab.Evaluate('1+1')
+ """
+ def __init__(self, inspector_backend):
+ super(Tab, self).__init__(inspector_backend)
+
+ def __del__(self):
+ super(Tab, self).__del__()
+
+ @property
+ def browser(self):
+ """The browser in which this tab resides."""
+ return self._inspector_backend.browser
+
+ @property
+ def url(self):
+ return self._inspector_backend.url
+
+ @property
+ def dom_stats(self):
+ """A dictionary populated with measured DOM statistics.
+
+ Currently this dictionary contains:
+ {
+ 'document_count': integer,
+ 'node_count': integer,
+ 'event_listener_count': integer
+ }
+ """
+ dom_counters = self._inspector_backend.GetDOMStats(
+ timeout=DEFAULT_TAB_TIMEOUT)
+ assert (len(dom_counters) == 3 and
+ all([x in dom_counters for x in ['document_count', 'node_count',
+ 'event_listener_count']]))
+ return dom_counters
+
+
+ def Activate(self):
+ """Brings this tab to the foreground asynchronously.
+
+ Not all browsers or browser versions support this method.
+ Be sure to check browser.supports_tab_control.
+
+ Please note: this is asynchronous. There is a delay between this call
+ and the page's documentVisibilityState becoming 'visible', and yet more
+ delay until the actual tab is visible to the user. None of these delays
+ are included in this call."""
+ self._inspector_backend.Activate()
+
+ @property
+ def screenshot_supported(self):
+ """True if the browser instance is capable of capturing screenshots"""
+ return self._inspector_backend.screenshot_supported
+
+ def Screenshot(self, timeout=DEFAULT_TAB_TIMEOUT):
+ """Capture a screenshot of the window for rendering validation"""
+ return self._inspector_backend.Screenshot(timeout)
+
+ def PerformActionAndWaitForNavigate(
+ self, action_function, timeout=DEFAULT_TAB_TIMEOUT):
+ """Executes action_function, and waits for the navigation to complete.
+
+ action_function must be a Python function that results in a navigation.
+ This function returns when the navigation is complete or when
+ the timeout has been exceeded.
+ """
+ self._inspector_backend.PerformActionAndWaitForNavigate(
+ action_function, timeout)
+
+ def Navigate(self, url, script_to_evaluate_on_commit=None,
+ timeout=DEFAULT_TAB_TIMEOUT):
+ """Navigates to url.
+
+ If |script_to_evaluate_on_commit| is given, the script source string will be
+ evaluated when the navigation is committed. This is after the context of
+ the page exists, but before any script on the page itself has executed.
+ """
+ self._inspector_backend.Navigate(url, script_to_evaluate_on_commit, timeout)
+
+ def GetCookieByName(self, name, timeout=DEFAULT_TAB_TIMEOUT):
+ """Returns the value of the cookie by the given |name|."""
+ return self._inspector_backend.GetCookieByName(name, timeout)
+
+ def CollectGarbage(self):
+ self._inspector_backend.CollectGarbage()
+
+ def ClearCache(self):
+ """Clears the browser's HTTP disk cache and the tab's HTTP memory cache."""
+ self._inspector_backend.ClearCache()
diff --git a/chromium/tools/telemetry/telemetry/core/tab_list.py b/chromium/tools/telemetry/telemetry/core/tab_list.py
new file mode 100644
index 00000000000..3e34bbb2166
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/tab_list.py
@@ -0,0 +1,18 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+class TabList(object):
+ def __init__(self, tab_list_backend):
+ self._tab_list_backend = tab_list_backend
+
+ def New(self, timeout=None):
+ return self._tab_list_backend.New(timeout)
+
+ def __iter__(self):
+ return self._tab_list_backend.__iter__()
+
+ def __len__(self):
+ return self._tab_list_backend.__len__()
+
+ def __getitem__(self, index):
+ return self._tab_list_backend.__getitem__(index)
diff --git a/chromium/tools/telemetry/telemetry/core/tab_unittest.py b/chromium/tools/telemetry/telemetry/core/tab_unittest.py
new file mode 100644
index 00000000000..156c935a787
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/tab_unittest.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import time
+
+from telemetry.core import util
+from telemetry.core import exceptions
+from telemetry.unittest import tab_test_case
+
+
+def _IsDocumentVisible(tab):
+ state = tab.EvaluateJavaScript('document.webkitVisibilityState')
+ # TODO(dtu): Remove when crbug.com/166243 is fixed.
+ tab.Disconnect()
+ return state == 'visible'
+
+
+class TabTest(tab_test_case.TabTestCase):
+ def testNavigateAndWaitToForCompleteState(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+ self._tab.Navigate(self._browser.http_server.UrlOf('blank.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ def testNavigateAndWaitToForInteractiveState(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+ self._tab.Navigate(self._browser.http_server.UrlOf('blank.html'))
+ self._tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
+
+ def testTabBrowserIsRightBrowser(self):
+ self.assertEquals(self._tab.browser, self._browser)
+
+ def testRendererCrash(self):
+ self.assertRaises(exceptions.TabCrashException,
+ lambda: self._tab.Navigate('chrome://crash',
+ timeout=5))
+
+ def testActivateTab(self):
+ if not self._browser.supports_tab_control:
+ logging.warning('Browser does not support tab control, skipping test.')
+ return
+
+ self.assertTrue(_IsDocumentVisible(self._tab))
+ new_tab = self._browser.tabs.New()
+ util.WaitFor(lambda: _IsDocumentVisible(new_tab), timeout=5)
+ self.assertFalse(_IsDocumentVisible(self._tab))
+ self._tab.Activate()
+ util.WaitFor(lambda: _IsDocumentVisible(self._tab), timeout=5)
+ self.assertFalse(_IsDocumentVisible(new_tab))
+
+
+class GpuTabTest(tab_test_case.TabTestCase):
+ def setUp(self):
+ self._extra_browser_args = ['--enable-gpu-benchmarking']
+ super(GpuTabTest, self).setUp()
+
+ def testScreenshot(self):
+ if not self._tab.screenshot_supported:
+ logging.warning('Browser does not support screenshots, skipping test.')
+ return
+
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+ self._tab.Navigate(
+ self._browser.http_server.UrlOf('green_rect.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ pixel_ratio = self._tab.EvaluateJavaScript('window.devicePixelRatio || 1')
+
+ # TODO(bajones): Sleep for a bit to counter BUG 260878.
+ time.sleep(0.5)
+ screenshot = self._tab.Screenshot(5)
+ assert screenshot
+ screenshot.GetPixelColor(0 * pixel_ratio, 0 * pixel_ratio).AssertIsRGB(
+ 0, 255, 0, tolerance=2)
+ screenshot.GetPixelColor(31 * pixel_ratio, 31 * pixel_ratio).AssertIsRGB(
+ 0, 255, 0, tolerance=2)
+ screenshot.GetPixelColor(32 * pixel_ratio, 32 * pixel_ratio).AssertIsRGB(
+ 255, 255, 255, tolerance=2)
diff --git a/chromium/tools/telemetry/telemetry/core/temporary_http_server.py b/chromium/tools/telemetry/telemetry/core/temporary_http_server.py
new file mode 100644
index 00000000000..e6dd42cf125
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/temporary_http_server.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import socket
+import subprocess
+import sys
+import urlparse
+
+from telemetry.core import util
+
+class TemporaryHTTPServer(object):
+ def __init__(self, browser_backend, paths):
+ self._server = None
+ self._devnull = None
+ self._paths = paths
+ self._forwarder = None
+ self._host_port = util.GetAvailableLocalPort()
+
+ for path in self._paths:
+ assert os.path.exists(path), path
+
+ self._devnull = open(os.devnull, 'w')
+ cmd = [sys.executable, '-m', 'memory_cache_http_server',
+ str(self._host_port)]
+ cmd.extend(self._paths)
+ env = os.environ.copy()
+ env['PYTHONPATH'] = os.path.abspath(os.path.dirname(__file__))
+ self._server = subprocess.Popen(cmd, cwd=os.path.commonprefix(self._paths),
+ env=env, stdout=self._devnull, stderr=self._devnull)
+
+ self._forwarder = browser_backend.CreateForwarder(
+ util.PortPair(self._host_port,
+ browser_backend.GetRemotePort(self._host_port)))
+
+ def IsServerUp():
+ return not socket.socket().connect_ex(('localhost', self._host_port))
+ util.WaitFor(IsServerUp, 10)
+
+ @property
+ def paths(self):
+ return self._paths
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.Close()
+
+ def __del__(self):
+ self.Close()
+
+ def Close(self):
+ if self._forwarder:
+ self._forwarder.Close()
+ self._forwarder = None
+ if self._server:
+ self._server.kill()
+ self._server = None
+ if self._devnull:
+ self._devnull.close()
+ self._devnull = None
+
+ @property
+ def url(self):
+ return self._forwarder.url
+
+ def UrlOf(self, path):
+ return urlparse.urljoin(self.url, path)
diff --git a/chromium/tools/telemetry/telemetry/core/temporary_http_server_unittest.py b/chromium/tools/telemetry/telemetry/core/temporary_http_server_unittest.py
new file mode 100644
index 00000000000..984eb213329
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/temporary_http_server_unittest.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from telemetry.core import browser_finder
+from telemetry.unittest import options_for_unittests
+
+class TemporaryHTTPServerTest(unittest.TestCase):
+ def testBasicHosting(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', 'unittest_data')
+ options = options_for_unittests.GetCopy()
+ browser_to_create = browser_finder.FindBrowser(options)
+ with browser_to_create.Create() as b:
+ b.Start()
+ b.SetHTTPServerDirectories(unittest_data_dir)
+ t = b.tabs[0]
+ t.Navigate(b.http_server.UrlOf('/blank.html'))
+ t.WaitForDocumentReadyStateToBeComplete()
+ x = t.EvaluateJavaScript('document.body.innerHTML')
+ x = x.strip()
+
+ self.assertEquals(x, 'Hello world')
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/OWNERS b/chromium/tools/telemetry/telemetry/core/timeline/OWNERS
new file mode 100644
index 00000000000..db4ac41e316
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/OWNERS
@@ -0,0 +1,2 @@
+tengs@chromium.org
+ernstm@chromium.org
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/__init__.py b/chromium/tools/telemetry/telemetry/core/timeline/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/__init__.py
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/async_slice.py b/chromium/tools/telemetry/telemetry/core/timeline/async_slice.py
new file mode 100644
index 00000000000..140eadc651b
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/async_slice.py
@@ -0,0 +1,28 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import telemetry.core.timeline.event as event
+
+class AsyncSlice(event.TimelineEvent):
+ ''' A AsyncSlice represents an interval of time during which an
+ asynchronous operation is in progress. An AsyncSlice consumes no CPU time
+ itself and so is only associated with Threads at its start and end point.
+ '''
+ def __init__(self, category, name, timestamp, args=None):
+ super(AsyncSlice, self).__init__(
+ category, name, timestamp, duration=0, args=args)
+ self.parent_slice = None
+ self.start_thread = None
+ self.end_thread = None
+ self.sub_slices = []
+ self.id = None
+
+ def AddSubSlice(self, sub_slice):
+ assert sub_slice.parent_slice == self
+ self.sub_slices.append(sub_slice)
+
+
+ def IterEventsInThisContainerRecrusively(self):
+ for sub_slice in self.sub_slices:
+ yield sub_slice
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/bounds.py b/chromium/tools/telemetry/telemetry/core/timeline/bounds.py
new file mode 100644
index 00000000000..26f23019e22
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/bounds.py
@@ -0,0 +1,71 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class Bounds(object):
+ """Represents a min-max bounds."""
+ def __init__(self):
+ self.is_empty_ = True
+ self.min_ = None
+ self.max_ = None
+
+ @property
+ def is_empty(self):
+ return self.is_empty_
+
+ @property
+ def min(self):
+ if self.is_empty_:
+ return None
+ return self.min_
+
+ @property
+ def max(self):
+ if self.is_empty_:
+ return None
+ return self.max_
+
+ @property
+ def bounds(self):
+ if self.is_empty_:
+ return None
+ return self.max_ - self.min_
+
+ @property
+ def center(self):
+ return (self.min_ + self.max_) * 0.5
+
+
+ def Reset(self):
+ self.is_empty_ = True
+ self.min_ = None
+ self.max_ = None
+
+ def AddBounds(self, bounds):
+ if bounds.isEmpty:
+ return
+ self.AddValue(bounds.min_)
+ self.AddValue(bounds.max_)
+
+ def AddValue(self, value):
+ if self.is_empty_:
+ self.max_ = value
+ self.min_ = value
+ self.is_empty_ = False
+ return
+
+ self.max_ = max(self.max_, value)
+ self.min_ = min(self.min_, value)
+
+ @staticmethod
+ def CompareByMinTimes(a, b):
+ if not a.is_empty and not b.is_empty:
+ return a.min_ - b.min_
+
+ if a.is_empty and not b.is_empty:
+ return -1
+
+ if not a.is_empty and b.is_empty:
+ return 1
+
+ return 0
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/counter.py b/chromium/tools/telemetry/telemetry/core/timeline/counter.py
new file mode 100644
index 00000000000..f21f5162fe4
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/counter.py
@@ -0,0 +1,82 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import telemetry.core.timeline.event_container as event_container
+
+# Doesn't inherit from TimelineEvent because its only a temporary wrapper of a
+# counter sample into an event. During stable operation, the samples are stored
+# a dense array of values rather than in the long-form done by an Event.
+class CounterSample(object):
+ def __init__(self, counter, sample_index):
+ self._counter = counter
+ self._sample_index = sample_index
+
+ @property
+ def name(self):
+ return None
+
+ @property
+ def start(self):
+ return self._counter.timestamps[self._sample_index]
+
+ @start.setter
+ def start(self, start):
+ self._counter.timestamps[self._sample_index] = start
+
+ @property
+ def duration(self):
+ return 0
+
+ @property
+ def end(self):
+ return self.start
+
+
+class Counter(event_container.TimelineEventContainer):
+ """ Stores all the samples for a given counter.
+ """
+ def __init__(self, parent, category, name):
+ super(Counter, self).__init__(name, parent)
+ self.category = category
+ self.full_name = category + '.' + name
+ self.samples = []
+ self.timestamps = []
+ self.series_names = []
+ self.totals = []
+ self.max_total = 0
+
+ def IterChildContainers(self):
+ return iter([])
+
+ def IterEventsInThisContainer(self):
+ for i in range(len(self.timestamps)):
+ yield CounterSample(self, i)
+
+ @property
+ def num_series(self):
+ return len(self.series_names)
+
+ @property
+ def num_samples(self):
+ return len(self.timestamps)
+
+ def FinalizeImport(self):
+ if self.num_series * self.num_samples != len(self.samples):
+ raise ValueError(
+ 'Length of samples must be a multiple of length of timestamps.')
+
+ self.totals = []
+ self.max_total = 0
+ if not len(self.samples):
+ return
+
+ max_total = None
+ for i in xrange(self.num_samples):
+ total = 0
+ for j in xrange(self.num_series):
+ total += self.samples[i * self.num_series + j]
+ self.totals.append(total)
+ if max_total is None or total > max_total:
+ max_total = total
+ self.max_total = max_total
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/event.py b/chromium/tools/telemetry/telemetry/core/timeline/event.py
new file mode 100644
index 00000000000..8b9db4cef72
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/event.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class TimelineEvent(object):
+ """Represents a timeline event."""
+ def __init__(self, category, name, start, duration, args=None):
+ self.category = category
+ self.name = name
+ self.start = start
+ self.duration = duration
+ self.args = args
+
+ @property
+ def end(self):
+ return self.start + self.duration
+
+ def __repr__(self):
+ if self.args:
+ args_str = ', ' + repr(self.args)
+ else:
+ args_str = ''
+
+ return "TimelineEvent(name='%s', start=%f, duration=%s%s)" % (
+ self.name,
+ self.start,
+ self.duration,
+ args_str)
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/event_container.py b/chromium/tools/telemetry/telemetry/core/timeline/event_container.py
new file mode 100644
index 00000000000..d84cb29c8c0
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/event_container.py
@@ -0,0 +1,15 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class TimelineEventContainer(object):
+ """Represents a container for events."""
+ def __init__(self, name, parent):
+ self.parent = parent
+ self.name = name
+
+ def IterChildContainers(self):
+ raise NotImplementedError()
+
+ def IterEventsInThisContainer(self):
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/event_unittest.py b/chromium/tools/telemetry/telemetry/core/timeline/event_unittest.py
new file mode 100644
index 00000000000..2c80c32146b
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/event_unittest.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+class TimelineEventTest(unittest.TestCase):
+ pass
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/importer.py b/chromium/tools/telemetry/telemetry/core/timeline/importer.py
new file mode 100644
index 00000000000..bfdce016b4e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/importer.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class TimelineImporter(object):
+ """Interface for classes that can add events to
+ a timeline model from raw event data."""
+ def __init__(self, model, event_data, import_priority=0):
+ self._model = model
+ self._event_data = event_data
+ self.import_priority = import_priority
+
+ @staticmethod
+ def CanImport(event_data):
+ """Returns true if the importer can process the given event data."""
+ raise NotImplementedError
+
+ def ImportEvents(self):
+ """Processes the event data and creates and adds
+ new timeline events to the model"""
+ raise NotImplementedError
+
+ def FinalizeImport(self):
+ """Called after all other importers for the model are run."""
+ raise NotImplementedError
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/inspector_importer.py b/chromium/tools/telemetry/telemetry/core/timeline/inspector_importer.py
new file mode 100644
index 00000000000..fa468cbc641
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/inspector_importer.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+'''Imports event data obtained from the inspector's timeline.'''
+
+from telemetry.core.timeline import importer
+import telemetry.core.timeline.thread as timeline_thread
+
+class InspectorTimelineImporter(importer.TimelineImporter):
+ def __init__(self, model, event_data):
+ super(InspectorTimelineImporter, self).__init__(model, event_data)
+
+ @staticmethod
+ def CanImport(event_data):
+ ''' Checks if event_data is from the inspector timeline. We assume
+ that if the first event is a valid inspector event, we can import the
+ entire list.
+ '''
+ if isinstance(event_data, list) and len(event_data):
+ event_datum = event_data[0]
+ return 'startTime' in event_datum and 'endTime' in event_datum
+ return False
+
+ def ImportEvents(self):
+ render_process = self._model.GetOrCreateProcess(0)
+ render_thread = render_process.GetOrCreateThread(0)
+ for raw_event in self._event_data:
+ InspectorTimelineImporter.AddRawEventToThreadRecursive(
+ render_thread, raw_event)
+
+ def FinalizeImport(self):
+ pass
+
+ @staticmethod
+ def AddRawEventToThreadRecursive(thread, raw_inspector_event):
+ did_begin_slice = False
+ if ('startTime' in raw_inspector_event and
+ 'endTime' in raw_inspector_event):
+ args = {}
+ for x in raw_inspector_event:
+ if x in ('startTime', 'endTime', 'children'):
+ continue
+ args[x] = raw_inspector_event[x]
+ if len(args) == 0:
+ args = None
+ thread.BeginSlice('inspector',
+ raw_inspector_event['type'],
+ raw_inspector_event['startTime'],
+ args)
+ did_begin_slice = True
+
+ for child in raw_inspector_event.get('children', []):
+ InspectorTimelineImporter.AddRawEventToThreadRecursive(
+ thread, child)
+
+ if did_begin_slice:
+ thread.EndSlice(raw_inspector_event['endTime'])
+
+ @staticmethod
+ def RawEventToTimelineEvent(raw_inspector_event):
+ """Converts raw_inspector_event to TimelineEvent."""
+ thread = timeline_thread.Thread(None, 0)
+ InspectorTimelineImporter.AddRawEventToThreadRecursive(
+ thread, raw_inspector_event)
+ thread.FinalizeImport()
+ assert len(thread.toplevel_slices) <= 1
+ if len(thread.toplevel_slices) == 0:
+ return None
+ return thread.toplevel_slices[0]
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/inspector_importer_unittest.py b/chromium/tools/telemetry/telemetry/core/timeline/inspector_importer_unittest.py
new file mode 100644
index 00000000000..afb99e6344c
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/inspector_importer_unittest.py
@@ -0,0 +1,112 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.core.timeline import inspector_importer
+from telemetry.core.timeline import model
+
+_SAMPLE_MESSAGE = {
+ 'children': [
+ {'data': {},
+ 'startTime': 1352783525921.823,
+ 'type': 'BeginFrame',
+ 'usedHeapSize': 1870736},
+ {'children': [],
+ 'data': {'height': 723,
+ 'width': 1272,
+ 'x': 0,
+ 'y': 0},
+ 'endTime': 1352783525921.8992,
+ 'frameId': '10.2',
+ 'startTime': 1352783525921.8281,
+ 'type': 'Layout',
+ 'usedHeapSize': 1870736},
+ {'children': [
+ {'children': [],
+ 'data': {'imageType': 'PNG'},
+ 'endTime': 1352783525927.7939,
+ 'startTime': 1352783525922.4241,
+ 'type': 'DecodeImage',
+ 'usedHeapSize': 1870736}
+ ],
+ 'data': {'height': 432,
+ 'width': 1272,
+ 'x': 0,
+ 'y': 8},
+ 'endTime': 1352783525927.9822,
+ 'frameId': '10.2',
+ 'startTime': 1352783525921.9292,
+ 'type': 'Paint',
+ 'usedHeapSize': 1870736}
+ ],
+ 'data': {},
+ 'endTime': 1352783525928.041,
+ 'startTime': 1352783525921.8049,
+ 'type': 'Program'}
+
+class InspectorEventParsingTest(unittest.TestCase):
+ def testParsingWithSampleData(self):
+ root_event = (inspector_importer.InspectorTimelineImporter
+ .RawEventToTimelineEvent(_SAMPLE_MESSAGE))
+ self.assertTrue(root_event)
+ decode_image_event = [
+ child for child in root_event.IterEventsInThisContainerRecrusively()
+ if child.name == 'DecodeImage'][0]
+ self.assertEquals(decode_image_event.args['data']['imageType'], 'PNG')
+ self.assertTrue(decode_image_event.duration > 0)
+
+ def testParsingWithSimpleData(self):
+ raw_event = {'type': 'Foo',
+ 'startTime': 1,
+ 'endTime': 3,
+ 'children': []}
+ event = (inspector_importer.InspectorTimelineImporter
+ .RawEventToTimelineEvent(raw_event))
+ self.assertEquals('Foo', event.name)
+ self.assertEquals(1, event.start)
+ self.assertEquals(3, event.end)
+ self.assertEquals(2, event.duration)
+ self.assertEquals([], event.sub_slices)
+
+ def testParsingWithArgs(self):
+ raw_event = {'type': 'Foo',
+ 'startTime': 1,
+ 'endTime': 3,
+ 'foo': 7,
+ 'bar': {'x': 1}}
+ event = (inspector_importer.InspectorTimelineImporter
+ .RawEventToTimelineEvent(raw_event))
+ self.assertEquals('Foo', event.name)
+ self.assertEquals(1, event.start)
+ self.assertEquals(3, event.end)
+ self.assertEquals(2, event.duration)
+ self.assertEquals([], event.sub_slices)
+ self.assertEquals(7, event.args['foo'])
+ self.assertEquals(1, event.args['bar']['x'])
+
+ def testEventsWithNoStartTimeAreDropped(self):
+ raw_event = {'type': 'Foo',
+ 'endTime': 1,
+ 'children': []}
+ event = (inspector_importer.InspectorTimelineImporter.
+ RawEventToTimelineEvent(raw_event))
+ self.assertEquals(None, event)
+
+ def testEventsWithNoEndTimeAreDropped(self):
+ raw_event = {'type': 'Foo',
+ 'endTime': 1,
+ 'children': []}
+ event = (inspector_importer.InspectorTimelineImporter.
+ RawEventToTimelineEvent(raw_event))
+ self.assertEquals(None, event)
+
+class InspectorImporterTest(unittest.TestCase):
+ def testImport(self):
+ m = model.TimelineModel([_SAMPLE_MESSAGE], shift_world_to_zero=False)
+ self.assertEquals(1, len(m.processes))
+ self.assertEquals(1, len(m.processes.values()[0].threads))
+ renderer_thread = m.GetAllThreads()[0]
+ self.assertEquals(1, len(renderer_thread.toplevel_slices))
+ self.assertEquals('Program',
+ renderer_thread.toplevel_slices[0].name)
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/model.py b/chromium/tools/telemetry/telemetry/core/timeline/model.py
new file mode 100644
index 00000000000..aae0199a162
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/model.py
@@ -0,0 +1,128 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+'''A container for timeline-based events and traces and can handle importing
+raw event data from different sources. This model closely resembles that in the
+trace_viewer project:
+https://code.google.com/p/trace-viewer/
+'''
+
+import telemetry.core.timeline.process as tracing_process
+
+# Register importers for data
+from telemetry.core.timeline import inspector_importer
+from telemetry.core.timeline import bounds
+from telemetry.core.timeline import trace_event_importer
+
+_IMPORTERS = [
+ inspector_importer.InspectorTimelineImporter,
+ trace_event_importer.TraceEventTimelineImporter
+]
+
+class TimelineModel(object):
+ def __init__(self, event_data=None, shift_world_to_zero=True):
+ self._bounds = bounds.Bounds()
+ self._processes = {}
+ self._frozen = False
+ self.import_errors = []
+ self.metadata = []
+
+ if event_data is not None:
+ self.ImportTraces([event_data], shift_world_to_zero=shift_world_to_zero)
+
+ @property
+ def bounds(self):
+ return self._bounds
+
+ @property
+ def processes(self):
+ return self._processes
+
+ def ImportTraces(self, traces, shift_world_to_zero=True):
+ if self._frozen:
+ raise Exception("Cannot add events once recording is done")
+
+ importers = []
+ for event_data in traces:
+ importers.append(self._CreateImporter(event_data))
+
+ importers.sort(cmp=lambda x, y: x.import_priority - y.import_priority)
+
+ for importer in importers:
+ # TODO: catch exceptions here and add it to error list
+ importer.ImportEvents()
+
+ self.UpdateBounds()
+ if not self.bounds.is_empty:
+ for process in self._processes.itervalues():
+ process.AutoCloseOpenSlices(self.bounds.max)
+
+ for importer in importers:
+ importer.FinalizeImport()
+
+ for process in self.processes.itervalues():
+ process.FinalizeImport()
+
+ if shift_world_to_zero:
+ self.ShiftWorldToZero()
+ self.UpdateBounds()
+
+ # Because of FinalizeImport, it would probably be a good idea
+ # to prevent the timeline from from being modified.
+ self._frozen = True
+
+ def ShiftWorldToZero(self):
+ self.UpdateBounds()
+ if self._bounds.is_empty:
+ return
+ shift_amount = -self._bounds.min
+ for event in self.IterAllEvents():
+ event.start += shift_amount
+
+ def UpdateBounds(self):
+ self._bounds.Reset()
+ for event in self.IterAllEvents():
+ self._bounds.AddValue(event.start)
+ self._bounds.AddValue(event.end)
+
+ def GetAllContainers(self):
+ containers = []
+ def Iter(container):
+ containers.append(container)
+ for container in container.IterChildContainers():
+ Iter(container)
+ for process in self._processes.itervalues():
+ Iter(process)
+ return containers
+
+ def IterAllEvents(self):
+ for container in self.GetAllContainers():
+ for event in container.IterEventsInThisContainer():
+ yield event
+
+ def GetAllProcesses(self):
+ return self._processes.values()
+
+ def GetAllThreads(self):
+ threads = []
+ for process in self._processes.values():
+ threads.extend(process.threads.values())
+ return threads
+
+ def GetAllEvents(self):
+ return list(self.IterAllEvents())
+
+ def GetAllEventsOfName(self, name):
+ return [e for e in self.IterAllEvents() if e.name == name]
+
+ def GetOrCreateProcess(self, pid):
+ if pid not in self._processes:
+ assert not self._frozen
+ self._processes[pid] = tracing_process.Process(self, pid)
+ return self._processes[pid]
+
+ def _CreateImporter(self, event_data):
+ for importer_class in _IMPORTERS:
+ if importer_class.CanImport(event_data):
+ return importer_class(self, event_data)
+ raise ValueError("Could not find an importer for the provided event data")
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/model_unittest.py b/chromium/tools/telemetry/telemetry/core/timeline/model_unittest.py
new file mode 100644
index 00000000000..e5a406d6a49
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/model_unittest.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+class TimelineModelUnittest(unittest.TestCase):
+ pass
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/process.py b/chromium/tools/telemetry/telemetry/core/timeline/process.py
new file mode 100644
index 00000000000..1b65d66f416
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/process.py
@@ -0,0 +1,72 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import telemetry.core.timeline.event_container as event_container
+import telemetry.core.timeline.counter as tracing_counter
+import telemetry.core.timeline.thread as tracing_thread
+
+class Process(event_container.TimelineEventContainer):
+ ''' The Process represents a single userland process in the trace.
+ '''
+ def __init__(self, parent, pid):
+ super(Process, self).__init__('process %s' % pid, parent)
+ self.pid = pid
+ self._threads = {}
+ self._counters = {}
+
+ @property
+ def threads(self):
+ return self._threads
+
+ @property
+ def counters(self):
+ return self._counters
+
+ def IterChildContainers(self):
+ for thread in self._threads.itervalues():
+ yield thread
+ for counter in self._counters.itervalues():
+ yield counter
+
+ def IterAllSlicesOfName(self, name):
+ for thread in self._threads.itervalues():
+ for s in thread.IterAllSlicesOfName(name):
+ yield s
+
+ def IterEventsInThisContainer(self):
+ return
+ yield # pylint: disable=W0101
+
+ def GetOrCreateThread(self, tid):
+ thread = self.threads.get(tid, None)
+ if thread:
+ return thread
+ thread = tracing_thread.Thread(self, tid)
+ self._threads[tid] = thread
+ return thread
+
+ def GetCounter(self, category, name):
+ counter_id = category + '.' + name
+ if counter_id in self.counters:
+ return self.counters[counter_id]
+ raise ValueError(
+ 'Counter %s not found in process with id %s.' % (counter_id,
+ self.pid))
+ def GetOrCreateCounter(self, category, name):
+ try:
+ return self.GetCounter(category, name)
+ except ValueError:
+ ctr = tracing_counter.Counter(self, category, name)
+ self._counters[ctr.full_name] = ctr
+ return ctr
+
+ def AutoCloseOpenSlices(self, max_timestamp):
+ for thread in self._threads.itervalues():
+ thread.AutoCloseOpenSlices(max_timestamp)
+
+ def FinalizeImport(self):
+ for thread in self._threads.itervalues():
+ thread.FinalizeImport()
+ for counter in self._counters.itervalues():
+ counter.FinalizeImport()
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/sample.py b/chromium/tools/telemetry/telemetry/core/timeline/sample.py
new file mode 100644
index 00000000000..36a3ab45b43
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/sample.py
@@ -0,0 +1,19 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import telemetry.core.timeline.event as timeline_event
+
+class Sample(timeline_event.TimelineEvent):
+ ''' A Sample represents a sample taken at an instant in time
+ plus parameters associated with that sample.
+
+ NOTE: The Sample class implements the same interface as
+ Slice. These must be kept in sync.
+
+ All time units are stored in milliseconds.
+ '''
+ def __init__(self, parent_thread, category, name, timestamp, args=None):
+ super(Sample, self).__init__(
+ category, name, timestamp, 0, args=args)
+ self.parent_thread = parent_thread
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/slice.py b/chromium/tools/telemetry/telemetry/core/timeline/slice.py
new file mode 100644
index 00000000000..5ce2b28a84d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/slice.py
@@ -0,0 +1,52 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import telemetry.core.timeline.event as timeline_event
+
+class Slice(timeline_event.TimelineEvent):
+ """A Slice represents an interval of time plus parameters associated
+ with that interval.
+
+ NOTE: The Sample class implements the same interface as
+ Slice. These must be kept in sync.
+
+ All time units are stored in milliseconds.
+ """
+ def __init__(self, parent_thread, category, name, timestamp,
+ args=None, duration=0):
+ super(Slice, self).__init__(
+ category, name, timestamp, duration, args=args)
+ self.parent_thread = parent_thread
+ self.parent_slice = None
+ self.sub_slices = []
+ self.did_not_finish = False
+
+ def AddSubSlice(self, sub_slice):
+ assert sub_slice.parent_slice == self
+ self.sub_slices.append(sub_slice)
+
+ def IterEventsInThisContainerRecrusively(self):
+ for sub_slice in self.sub_slices:
+ yield sub_slice
+ for sub_sub in sub_slice.IterEventsInThisContainerRecrusively():
+ yield sub_sub
+
+ @property
+ def self_time(self):
+ """Time spent in this function less any time spent in child events."""
+ child_total = sum(
+ [e.duration for e in self.sub_slices])
+ return self.duration - child_total
+
+ def _GetSubSlicesRecursive(self):
+ for sub_slice in self.sub_slices:
+ for s in sub_slice.GetAllSubSlices():
+ yield s
+ yield sub_slice
+
+ def GetAllSubSlices(self):
+ return list(self._GetSubSlicesRecursive())
+
+ def GetAllSubSlicesOfName(self, name):
+ return [e for e in self.GetAllSubSlices() if e.name == name]
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/slice_unittest.py b/chromium/tools/telemetry/telemetry/core/timeline/slice_unittest.py
new file mode 100644
index 00000000000..e2d6b822700
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/slice_unittest.py
@@ -0,0 +1,26 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+
+from telemetry.core.timeline.slice import Slice
+
+class SliceTest(unittest.TestCase):
+ def testChildrenLogic(self):
+ # [ top ]
+ # [ a ] [ b ]
+ # [x]
+ top = Slice(None, 'cat', 'top', 0, duration=10)
+ a = Slice(None, 'cat', 'a', 1, duration=2)
+ x = Slice(None, 'cat', 'x', 1.5, duration=0.25)
+ b = Slice(None, 'cat', 'b', 5, duration=2)
+ top.sub_slices.extend([a, b])
+ a.sub_slices.append(x)
+
+ all_children = list(top.IterEventsInThisContainerRecrusively())
+ self.assertEquals([a, x, b], all_children)
+
+ self.assertEquals(x.self_time, 0.25)
+ self.assertEquals(a.self_time, 1.75) # 2 - 0.25
+ self.assertEquals(top.self_time, 6) # 10 - 2 -2
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/thread.py b/chromium/tools/telemetry/telemetry/core/timeline/thread.py
new file mode 100644
index 00000000000..47194ac904a
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/thread.py
@@ -0,0 +1,207 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import itertools
+
+import telemetry.core.timeline.event_container as event_container
+import telemetry.core.timeline.sample as tracing_sample
+import telemetry.core.timeline.slice as tracing_slice
+
+class Thread(event_container.TimelineEventContainer):
+ ''' A Thread stores all the trace events collected for a particular
+ thread. We organize the synchronous slices on a thread by "subrows," where
+ subrow 0 has all the root slices, subrow 1 those nested 1 deep, and so on.
+ The asynchronous slices are stored in an AsyncSliceGroup object.
+ '''
+ def __init__(self, process, tid):
+ super(Thread, self).__init__('thread %s' % tid, parent=process)
+ self.tid = tid
+ self._async_slices = []
+ self._samples = []
+ self._toplevel_slices = []
+
+ # State only valid during import.
+ self._open_slices = []
+ self._newly_added_slices = []
+
+ @property
+ def toplevel_slices(self):
+ return self._toplevel_slices
+
+ @property
+ def all_slices(self):
+ return list(self.IterAllSlices())
+
+ @property
+ def samples(self):
+ return self._samples
+
+ @property
+ def async_slices(self):
+ return self._async_slices
+
+ @property
+ def open_slice_count(self):
+ return len(self._open_slices)
+
+ def IterChildContainers(self):
+ return iter([])
+
+ def IterAllSlices(self):
+ for s in self._toplevel_slices:
+ yield s
+ for sub_slice in s.IterEventsInThisContainerRecrusively():
+ yield sub_slice
+
+ def IterAllSlicesOfName(self, name):
+ for s in self.IterAllSlices():
+ if s.name == name:
+ yield s
+
+ def IterAllAsyncSlices(self):
+ for async_slice in self._async_slices:
+ yield async_slice
+ for sub_slice in async_slice.IterEventsInThisContainerRecrusively():
+ yield sub_slice
+
+ def IterEventsInThisContainer(self):
+ return itertools.chain(
+ iter(self._open_slices),
+ iter(self._newly_added_slices),
+ self.IterAllAsyncSlices(),
+ self.IterAllSlices(),
+ iter(self._samples)
+ )
+
+ def AddSample(self, category, name, timestamp, args=None):
+ if len(self._samples) and timestamp < self._samples[-1].start:
+ raise ValueError(
+ 'Samples must be added in increasing timestamp order')
+ sample = tracing_sample.Sample(self,
+ category, name, timestamp, args=args)
+ self._samples.append(sample)
+
+ def AddAsyncSlice(self, async_slice):
+ self._async_slices.append(async_slice)
+
+ def BeginSlice(self, category, name, timestamp, args=None):
+ """Opens a new slice for the thread.
+ Calls to beginSlice and endSlice must be made with
+ non-monotonically-decreasing timestamps.
+
+ * category: Category to which the slice belongs.
+ * name: Name of the slice to add.
+ * timestamp: The timetsamp of the slice, in milliseconds.
+ * args: Arguments associated with
+
+ Returns newly opened slice
+ """
+ if len(self._open_slices) > 0 and timestamp < self._open_slices[-1].start:
+ raise ValueError(
+ 'Slices must be added in increasing timestamp order')
+ self._open_slices.append(
+ tracing_slice.Slice(self, category, name, timestamp, args=args))
+
+ def EndSlice(self, end_timestamp):
+ """ Ends the last begun slice in this group and pushes it onto the slice
+ array.
+
+ * end_timestamp: Timestamp when the slice ended in milliseconds
+
+ returns completed slice.
+ """
+ if not len(self._open_slices):
+ raise ValueError(
+ 'EndSlice called without an open slice')
+ curr_slice = self._open_slices.pop()
+ if end_timestamp < curr_slice.start:
+ raise ValueError(
+ 'Slice %s end time is before its start.' % curr_slice.name)
+ curr_slice.duration = end_timestamp - curr_slice.start
+ return self.PushSlice(curr_slice)
+
+ def PushSlice(self, new_slice):
+ self._newly_added_slices.append(new_slice)
+ return new_slice
+
+ def AutoCloseOpenSlices(self, max_timestamp):
+ while len(self._open_slices) > 0:
+ curr_slice = self.EndSlice(max_timestamp)
+ curr_slice.did_not_finish = True
+
+ def IsTimestampValidForBeginOrEnd(self, timestamp):
+ if not len(self._open_slices):
+ return True
+ return timestamp >= self._open_slices[-1].start
+
+ def FinalizeImport(self):
+ self._BuildSliceSubRows()
+
+ def _BuildSliceSubRows(self):
+ '''This function works by walking through slices by start time.
+
+ The basic idea here is to insert each slice as deep into the subrow
+ list as it can go such that every subslice is fully contained by its
+ parent slice.
+
+ Visually, if we start with this:
+ 0: [ a ]
+ 1: [ b ]
+ 2: [c][d]
+
+ To place this slice:
+ [e]
+ We first check row 2's last item, [d]. [e] wont fit into [d] (they dont
+ even intersect). So we go to row 1. That gives us [b], and [d] wont fit
+ into that either. So, we go to row 0 and its last slice, [a]. That can
+ completely contain [e], so that means we should add [e] as a subslice
+ of [a]. That puts it on row 1, yielding:
+ 0: [ a ]
+ 1: [ b ][e]
+ 2: [c][d]
+
+ If we then get this slice:
+ [f]
+ We do the same deepest-to-shallowest walk of the subrows trying to fit
+ it. This time, it doesn't fit in any open slice. So, we simply append
+ it to row 0 (a root slice):
+ 0: [ a ] [f]
+ 1: [ b ][e]
+ '''
+ def CompareSlices(s1, s2):
+ if s1.start == s2.start:
+ # Break ties by having the slice with the greatest
+ # end timestamp come first.
+ return cmp(s2.end, s1.end)
+ return cmp(s1.start, s2.start)
+
+ assert len(self._toplevel_slices) == 0
+ if not len(self._newly_added_slices):
+ return
+
+ sorted_slices = sorted(self._newly_added_slices, cmp=CompareSlices)
+ root_slice = sorted_slices[0]
+ self._toplevel_slices.append(root_slice)
+ for s in sorted_slices[1:]:
+ if not self._AddSliceIfBounds(root_slice, s):
+ root_slice = s
+ self._toplevel_slices.append(root_slice)
+ self._newly_added_slices = []
+
+ def _AddSliceIfBounds(self, root, child):
+ ''' Adds a child slice to a root slice its proper row.
+ Return False if the child slice is not in the bounds
+ of the root slice.
+
+ Because we know that the start time of child is >= the start time
+ of all other slices seen so far, we can just check the last slice
+ of each row for bounding.
+ '''
+ if child.start >= root.start and child.end <= root.end:
+ if len(root.sub_slices) > 0:
+ if self._AddSliceIfBounds(root.sub_slices[-1], child):
+ return True
+ child.parent_slice = root
+ root.AddSubSlice(child)
+ return True
+ return False
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/trace_event_importer.py b/chromium/tools/telemetry/telemetry/core/timeline/trace_event_importer.py
new file mode 100644
index 00000000000..aff6ec5a005
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/trace_event_importer.py
@@ -0,0 +1,349 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+''' TraceEventImporter imports TraceEvent-formatted data
+into the provided model.
+This is a port of the trace event importer from
+https://code.google.com/p/trace-viewer/
+'''
+
+import copy
+import json
+import re
+
+from telemetry.core.timeline import importer
+import telemetry.core.timeline.async_slice as tracing_async_slice
+
+class TraceEventTimelineImporter(importer.TimelineImporter):
+ def __init__(self, model, event_data):
+ super(TraceEventTimelineImporter, self).__init__(
+ model, event_data, import_priority=1)
+
+ self._events_were_from_string = False
+ self._all_async_events = []
+ self._all_object_events = []
+
+ if type(event_data) is str:
+ # If the event data begins with a [, then we know it should end with a ].
+ # The reason we check for this is because some tracing implementations
+ # cannot guarantee that a ']' gets written to the trace file. So, we are
+ # forgiving and if this is obviously the case, we fix it up before
+ # throwing the string at JSON.parse.
+ if event_data[0] == '[':
+ event_data = re.sub(r'[\r|\n]*$', '', event_data)
+ event_data = re.sub(r'\s*,\s*$', '', event_data)
+ if event_data[-1] != ']':
+ event_data = event_data + ']'
+
+ self._events = json.loads(event_data)
+ self._events_were_from_string = True
+ else:
+ self._events = event_data
+
+ # Some trace_event implementations put the actual trace events
+ # inside a container. E.g { ... , traceEvents: [ ] }
+ # If we see that, just pull out the trace events.
+ if 'traceEvents' in self._events:
+ container = self._events
+ self._events = self._events['traceEvents']
+ for field_name in container:
+ if field_name == 'traceEvents':
+ continue
+
+ # Any other fields in the container should be treated as metadata.
+ self._model.metadata.append({
+ 'name' : field_name,
+ 'value' : container['field_name']})
+
+ @staticmethod
+ def CanImport(event_data):
+ ''' Returns whether obj is a TraceEvent array. '''
+ # May be encoded JSON. But we dont want to parse it fully yet.
+ # Use a simple heuristic:
+ # - event_data that starts with [ are probably trace_event
+ # - event_data that starts with { are probably trace_event
+ # May be encoded JSON. Treat files that start with { as importable by us.
+ if isinstance(event_data, str):
+ return len(event_data) > 0 and (event_data[0] == '{'
+ or event_data[0] == '[')
+
+ # Might just be an array of events
+ if (isinstance(event_data, list) and len(event_data)
+ and 'ph' in event_data[0]):
+ return True
+
+ # Might be an object with a traceEvents field in it.
+ if 'traceEvents' in event_data:
+ trace_events = event_data.get('traceEvents', None)
+ return (type(trace_events) is list and
+ len(trace_events) > 0 and 'ph' in trace_events[0])
+
+ return False
+
+ def _GetOrCreateProcess(self, pid):
+ return self._model.GetOrCreateProcess(pid)
+
+ def _DeepCopyIfNeeded(self, obj):
+ if self._events_were_from_string:
+ return obj
+ return copy.deepcopy(obj)
+
+ def _ProcessAsyncEvent(self, event):
+ '''Helper to process an 'async finish' event, which will close an
+ open slice.
+ '''
+ thread = (self._GetOrCreateProcess(event['pid'])
+ .GetOrCreateThread(event['tid']))
+ self._all_async_events.append({
+ 'event': event,
+ 'thread': thread})
+
+ def _ProcessCounterEvent(self, event):
+ '''Helper that creates and adds samples to a Counter object based on
+ 'C' phase events.
+ '''
+ if 'id' in event:
+ ctr_name = event['name'] + '[' + str(event['id']) + ']'
+ else:
+ ctr_name = event['name']
+
+ ctr = (self._GetOrCreateProcess(event['pid'])
+ .GetOrCreateCounter(event['cat'], ctr_name))
+ # Initialize the counter's series fields if needed.
+ if len(ctr.series_names) == 0:
+ #TODO: implement counter object
+ for series_name in event['args']:
+ ctr.series_names.append(series_name)
+ if len(ctr.series_names) == 0:
+ self._model.import_errors.append('Expected counter ' + event['name'] +
+ ' to have at least one argument to use as a value.')
+ # Drop the counter.
+ del ctr.parent.counters[ctr.full_name]
+ return
+
+ # Add the sample values.
+ ctr.timestamps.append(event['ts'] / 1000.0)
+ for series_name in ctr.series_names:
+ if series_name not in event['args']:
+ ctr.samples.append(0)
+ continue
+ ctr.samples.append(event['args'][series_name])
+
+ def _ProcessObjectEvent(self, event):
+ thread = (self._GetOrCreateProcess(event['pid'])
+ .GetOrCreateThread(event['tid']))
+ self._all_object_events.append({
+ 'event': event,
+ 'thread': thread})
+
+ def _ProcessDurationEvent(self, event):
+ thread = (self._GetOrCreateProcess(event['pid'])
+ .GetOrCreateThread(event['tid']))
+ if not thread.IsTimestampValidForBeginOrEnd(event['ts'] / 1000.0):
+ self._model.import_errors.append(
+ 'Timestamps are moving backward.')
+ return
+
+ if event['ph'] == 'B':
+ thread.BeginSlice(event['cat'],
+ event['name'],
+ event['ts'] / 1000.0,
+ event['args'])
+ elif event['ph'] == 'E':
+ thread = (self._GetOrCreateProcess(event['pid'])
+ .GetOrCreateThread(event['tid']))
+ if not thread.IsTimestampValidForBeginOrEnd(event['ts'] / 1000.0):
+ self._model.import_errors.append(
+ 'Timestamps are moving backward.')
+ return
+ if not thread.open_slice_count:
+ self._model.import_errors.append(
+ 'E phase event without a matching B phase event.')
+ return
+
+ new_slice = thread.EndSlice(event['ts'] / 1000.0)
+ for arg_name, arg_value in event.get('args', {}).iteritems():
+ if arg_name in new_slice.args:
+ self._model.import_errors.append(
+ 'Both the B and E phases of ' + new_slice.name +
+ ' provided values for argument ' + arg_name + '. ' +
+ 'The value of the E phase event will be used.')
+ new_slice.args[arg_name] = arg_value
+
+ def _ProcessMetadataEvent(self, event):
+ if event['name'] == 'thread_name':
+ thread = (self._GetOrCreateProcess(event['pid'])
+ .GetOrCreateThread(event['tid']))
+ thread.name = event['args']['name']
+ if event['name'] == 'process_name':
+ process = self._GetOrCreateProcess(event['pid'])
+ process.name = event['args']['name']
+ else:
+ self._model.import_errors.append(
+ 'Unrecognized metadata name: ' + event['name'])
+
+ def _ProcessInstantEvent(self, event):
+ # Treat an Instant event as a duration 0 slice.
+ # SliceTrack's redraw() knows how to handle this.
+ thread = (self._GetOrCreateProcess(event['pid'])
+ .GetOrCreateThread(event['tid']))
+ thread.BeginSlice(event['cat'],
+ event['name'],
+ event['ts'] / 1000.0,
+ event.get('args'))
+ thread.EndSlice(event['ts'] / 1000.0)
+
+ def _ProcessSampleEvent(self, event):
+ thread = (self._GetOrCreateProcess(event['pid'])
+ .GetOrCreateThread(event['tid']))
+ thread.AddSample(event['cat'],
+ event['name'],
+ event['ts'] / 1000.0,
+ args=event.get('args'))
+
+ def ImportEvents(self):
+ ''' Walks through the events_ list and outputs the structures discovered to
+ model_.
+ '''
+ for event in self._events:
+ phase = event.get('ph', None)
+ if phase == 'B' or phase == 'E':
+ self._ProcessDurationEvent(event)
+ elif phase == 'S' or phase == 'F' or phase == 'T':
+ self._ProcessAsyncEvent(event)
+ # Note, I is historic. The instant event marker got changed, but we
+ # want to support loading load trace files so we have both I and i.
+ elif phase == 'I' or phase == 'i':
+ self._ProcessInstantEvent(event)
+ elif phase == 'P':
+ self._ProcessSampleEvent(event)
+ elif phase == 'C':
+ self._ProcessCounterEvent(event)
+ elif phase == 'M':
+ self._ProcessMetadataEvent(event)
+ elif phase == 'N' or phase == 'D' or phase == 'O':
+ self._ProcessObjectEvent(event)
+ elif phase == 's' or phase == 't' or phase == 'f':
+ # NB: toss until there's proper support
+ pass
+ else:
+ self._model.import_errors.append('Unrecognized event phase: ' +
+ phase + '(' + event['name'] + ')')
+
+ return self._model
+
+ def FinalizeImport(self):
+ '''Called by the Model after all other importers have imported their
+ events.'''
+ self._model.UpdateBounds()
+
+ # We need to reupdate the bounds in case the minimum start time changes
+ self._model.UpdateBounds()
+ self._CreateAsyncSlices()
+ self._CreateExplicitObjects()
+ self._CreateImplicitObjects()
+
+ def _CreateAsyncSlices(self):
+ if len(self._all_async_events) == 0:
+ return
+
+ self._all_async_events.sort(
+ cmp=lambda x, y: x['event']['ts'] - y['event']['ts'])
+
+ async_event_states_by_name_then_id = {}
+
+ all_async_events = self._all_async_events
+ for async_event_state in all_async_events:
+ event = async_event_state['event']
+ name = event.get('name', None)
+ if name is None:
+ self._model.import_errors.append(
+ 'Async events (ph: S, T or F) require an name parameter.')
+ continue
+
+ event_id = event.get('id')
+ if event_id is None:
+ self._model.import_errors.append(
+ 'Async events (ph: S, T or F) require an id parameter.')
+ continue
+
+ # TODO(simonjam): Add a synchronous tick on the appropriate thread.
+
+ if event['ph'] == 'S':
+ if not name in async_event_states_by_name_then_id:
+ async_event_states_by_name_then_id[name] = {}
+ if event_id in async_event_states_by_name_then_id[name]:
+ self._model.import_errors.append(
+ 'At ' + event['ts'] + ', a slice of the same id ' + event_id +
+ ' was alrady open.')
+ continue
+
+ async_event_states_by_name_then_id[name][event_id] = []
+ async_event_states_by_name_then_id[name][event_id].append(
+ async_event_state)
+ else:
+ if name not in async_event_states_by_name_then_id:
+ self._model.import_errors.append(
+ 'At ' + str(event['ts']) + ', no slice named ' + name +
+ ' was open.')
+ continue
+ if event_id not in async_event_states_by_name_then_id[name]:
+ self._model.import_errors.append(
+ 'At ' + str(event['ts']) + ', no slice named ' + name +
+ ' with id=' + event_id + ' was open.')
+ continue
+ events = async_event_states_by_name_then_id[name][event_id]
+ events.append(async_event_state)
+
+ if event['ph'] == 'F':
+ # Create a slice from start to end.
+ async_slice = tracing_async_slice.AsyncSlice(
+ events[0]['event']['cat'],
+ name,
+ events[0]['event']['ts'] / 1000.0)
+
+ async_slice.duration = ((event['ts'] / 1000.0)
+ - (events[0]['event']['ts'] / 1000.0))
+
+ async_slice.start_thread = events[0]['thread']
+ async_slice.end_thread = async_event_state['thread']
+ async_slice.id = event_id
+ async_slice.args = events[0]['event']['args']
+
+ # Create sub_slices for each step.
+ for j in xrange(1, len(events)):
+ sub_name = name
+ if events[j - 1]['event']['ph'] == 'T':
+ sub_name = name + ':' + events[j - 1]['event']['args']['step']
+ sub_slice = tracing_async_slice.AsyncSlice(
+ events[0]['event']['cat'],
+ sub_name,
+ events[j - 1]['event']['ts'] / 1000.0)
+ sub_slice.parent_slice = async_slice
+
+ sub_slice.duration = ((events[j]['event']['ts'] / 1000.0)
+ - (events[j - 1]['event']['ts'] / 1000.0))
+
+ sub_slice.start_thread = events[j - 1]['thread']
+ sub_slice.end_thread = events[j]['thread']
+ sub_slice.id = event_id
+ sub_slice.args = events[j - 1]['event']['args']
+
+ async_slice.AddSubSlice(sub_slice)
+
+ # The args for the finish event go in the last sub_slice.
+ last_slice = async_slice.sub_slices[-1]
+ for arg_name, arg_value in event['args'].iteritems():
+ last_slice.args[arg_name] = arg_value
+
+ # Add |async_slice| to the start-thread's async_slices.
+ async_slice.start_thread.AddAsyncSlice(async_slice)
+ del async_event_states_by_name_then_id[name][event_id]
+
+ def _CreateExplicitObjects(self):
+ # TODO(tengs): Implement object instance parsing
+ pass
+
+ def _CreateImplicitObjects(self):
+ # TODO(tengs): Implement object instance parsing
+ pass
diff --git a/chromium/tools/telemetry/telemetry/core/timeline/trace_event_importer_unittest.py b/chromium/tools/telemetry/telemetry/core/timeline/trace_event_importer_unittest.py
new file mode 100644
index 00000000000..1aa6a3bc480
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/timeline/trace_event_importer_unittest.py
@@ -0,0 +1,921 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import unittest
+
+from telemetry.core.timeline import trace_event_importer
+import telemetry.core.timeline.model as timeline_model
+import telemetry.core.timeline.counter as tracing_counter
+
+def FindEventNamed(events, name):
+ for event in events:
+ if event.name == name:
+ return event
+ raise ValueError('No event found with name %s' % name)
+
+class TraceEventTimelineImporterTest(unittest.TestCase):
+ def testCanImportEmpty(self):
+ self.assertFalse(
+ trace_event_importer.TraceEventTimelineImporter.CanImport([]))
+ self.assertFalse(
+ trace_event_importer.TraceEventTimelineImporter.CanImport(''))
+
+ def testBasicSingleThreadNonnestedParsing(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 520, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'},
+ {'name': 'b', 'args': {}, 'pid': 52, 'ts': 629, 'cat': 'bar',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 52, 'ts': 631, 'cat': 'bar',
+ 'tid': 53, 'ph': 'E'}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ p = processes[0]
+ self.assertEqual(52, p.pid)
+
+ self.assertEqual(1, len(p.threads))
+ t = p.threads[53]
+ self.assertEqual(2, len(t.all_slices))
+ self.assertEqual(53, t.tid)
+ slice_event = t.all_slices[0]
+ self.assertEqual('a', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+ self.assertAlmostEqual(0, slice_event.start)
+ self.assertAlmostEqual((560 - 520) / 1000.0, slice_event.duration)
+ self.assertEqual(0, len(slice_event.sub_slices))
+
+ slice_event = t.all_slices[1]
+ self.assertEqual('b', slice_event.name)
+ self.assertEqual('bar', slice_event.category)
+ self.assertAlmostEqual((629 - 520) / 1000.0, slice_event.start)
+ self.assertAlmostEqual((631 - 629) / 1000.0, slice_event.duration)
+ self.assertEqual(0, len(slice_event.sub_slices))
+
+ def testArgumentDupeCreatesNonFailingImportError(self):
+ events = [
+ {'name': 'a', 'args': {'x': 1}, 'pid': 1, 'ts': 520, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'a', 'args': {'x': 2}, 'pid': 1, 'ts': 560, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ processes = m.GetAllProcesses()
+ t = processes[0].threads[1]
+ slice_a = FindEventNamed(t.all_slices, 'a')
+
+ self.assertEqual(2, slice_a.args['x'])
+ self.assertEqual(1, len(m.import_errors))
+
+ def testCategoryBeginEndMismatchPreferslice_begin(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 520, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 560, 'cat': 'bar',
+ 'tid': 53, 'ph': 'E'}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ p = processes[0]
+ self.assertEqual(52, p.pid)
+
+ self.assertEqual(1, len(p.threads))
+ t = p.threads[53]
+ self.assertEqual(1, len(t.all_slices))
+ self.assertEqual(53, t.tid)
+ slice_event = t.all_slices[0]
+ self.assertEqual('a', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+
+ def testNestedParsing(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'bar',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 3, 'cat': 'bar',
+ 'tid': 1, 'ph': 'E'},
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 4, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events,
+ shift_world_to_zero=False)
+ t = m.GetAllProcesses()[0].threads[1]
+
+ slice_a = FindEventNamed(t.all_slices, 'a')
+ slice_b = FindEventNamed(t.all_slices, 'b')
+
+ self.assertEqual('a', slice_a.name)
+ self.assertEqual('foo', slice_a.category)
+ self.assertAlmostEqual(0.001, slice_a.start)
+ self.assertAlmostEqual(0.003, slice_a.duration)
+
+ self.assertEqual('b', slice_b.name)
+ self.assertEqual('bar', slice_b.category)
+ self.assertAlmostEqual(0.002, slice_b.start)
+ self.assertAlmostEqual(0.001, slice_b.duration)
+
+ def testAutoclosing(self):
+ events = [
+ # Slice that doesn't finish.
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+
+ # Slice that does finish to give an 'end time' to make autoclosing work.
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'bar',
+ 'tid': 2, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'bar',
+ 'tid': 2, 'ph': 'E'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ p = m.GetAllProcesses()[0]
+ t = p.threads[1]
+ slice_event = t.all_slices[0]
+ self.assertEqual('a', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+ self.assertTrue(slice_event.did_not_finish)
+ self.assertAlmostEqual(0, slice_event.start)
+ self.assertAlmostEqual((2 - 1) / 1000.0, slice_event.duration)
+
+ def testAutoclosingLoneBegin(self):
+ events = [
+ # Slice that doesn't finish.
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ p = m.GetAllProcesses()[0]
+ t = p.threads[1]
+ slice_event = t.all_slices[0]
+ self.assertEqual('a', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+ self.assertTrue(slice_event.did_not_finish)
+ self.assertAlmostEqual(0, slice_event.start)
+ self.assertAlmostEqual(0, slice_event.duration)
+
+ def testAutoclosingWithSubTasks(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'b1', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'b1', 'args': {}, 'pid': 1, 'ts': 3, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'},
+ {'name': 'b2', 'args': {}, 'pid': 1, 'ts': 3, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events,
+ shift_world_to_zero=False)
+ t = m.GetAllProcesses()[0].threads[1]
+
+ slice_a = FindEventNamed(t.all_slices, 'a')
+ slice_b1 = FindEventNamed(t.all_slices, 'b1')
+ slice_b2 = FindEventNamed(t.all_slices, 'b2')
+
+ self.assertAlmostEqual(0.003, slice_a.end)
+ self.assertAlmostEqual(0.003, slice_b1.end)
+ self.assertAlmostEqual(0.003, slice_b2.end)
+
+ def testAutoclosingWithEventsOutsideBounds(self):
+ events = [
+ # Slice that begins before min and ends after max of the other threads.
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 0, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 3, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+
+ # Slice that does finish to give an 'end time' to establish a basis
+ {'name': 'c', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'bar',
+ 'tid': 2, 'ph': 'B'},
+ {'name': 'c', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'bar',
+ 'tid': 2, 'ph': 'E'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events,
+ shift_world_to_zero=False)
+ p = m.GetAllProcesses()[0]
+ t = p.threads[1]
+ self.assertEqual(2, len(t.all_slices))
+
+ slice_event = FindEventNamed(t.all_slices, 'a')
+ self.assertEqual('a', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+ self.assertAlmostEqual(0, slice_event.start)
+ self.assertAlmostEqual(0.003, slice_event.duration)
+
+ t2 = p.threads[2]
+ slice2 = FindEventNamed(t2.all_slices, 'c')
+ self.assertEqual('c', slice2.name)
+ self.assertEqual('bar', slice2.category)
+ self.assertAlmostEqual(0.001, slice2.start)
+ self.assertAlmostEqual(0.001, slice2.duration)
+
+ self.assertAlmostEqual(0.000, m.bounds.min)
+ self.assertAlmostEqual(0.003, m.bounds.max)
+
+ def testNestedAutoclosing(self):
+ events = [
+ # Tasks that don't finish.
+ {'name': 'a1', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'a2', 'args': {}, 'pid': 1, 'ts': 1.5, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+
+ # Slice that does finish to give an 'end time' to make autoclosing work.
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 2, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'foo',
+ 'tid': 2, 'ph': 'E'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events,
+ shift_world_to_zero=False)
+ t1 = m.GetAllProcesses()[0].threads[1]
+ t2 = m.GetAllProcesses()[0].threads[2]
+
+ slice_a1 = FindEventNamed(t1.all_slices, 'a1')
+ slice_a2 = FindEventNamed(t1.all_slices, 'a2')
+ FindEventNamed(t2.all_slices, 'b')
+
+ self.assertAlmostEqual(0.002, slice_a1.end)
+ self.assertAlmostEqual(0.002, slice_a2.end)
+
+ def testMultipleThreadParsing(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'},
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 3, 'cat': 'bar',
+ 'tid': 2, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 1, 'ts': 4, 'cat': 'bar',
+ 'tid': 2, 'ph': 'E'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ p = processes[0]
+
+ self.assertEqual(2, len(p.threads))
+
+ # Check thread 1.
+ t = p.threads[1]
+ self.assertAlmostEqual(1, len(t.all_slices))
+ self.assertAlmostEqual(1, t.tid)
+
+ slice_event = t.all_slices[0]
+ self.assertEqual('a', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+ self.assertAlmostEqual(0, slice_event.start)
+ self.assertAlmostEqual((2 - 1) / 1000.0, slice_event.duration)
+
+ # Check thread 2.
+ t = p.threads[2]
+ self.assertAlmostEqual(1, len(t.all_slices))
+ self.assertAlmostEqual(2, t.tid)
+
+ slice_event = t.all_slices[0]
+ self.assertEqual('b', slice_event.name)
+ self.assertEqual('bar', slice_event.category)
+ self.assertAlmostEqual((3 - 1) / 1000.0, slice_event.start)
+ self.assertAlmostEqual((4 - 3) / 1000.0, slice_event.duration)
+
+ def testMultiplePidParsing(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'},
+ {'name': 'b', 'args': {}, 'pid': 2, 'ts': 3, 'cat': 'bar',
+ 'tid': 2, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 2, 'ts': 4, 'cat': 'bar',
+ 'tid': 2, 'ph': 'E'}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ processes = m.GetAllProcesses()
+ self.assertEqual(2, len(processes))
+
+ p = processes[0]
+ self.assertEqual(1, p.pid)
+ self.assertEqual(1, len(p.threads))
+
+ # Check process 1 thread 1.
+ t = p.threads[1]
+ self.assertEqual(1, len(t.all_slices))
+ self.assertEqual(1, t.tid)
+
+ slice_event = t.all_slices[0]
+ self.assertEqual('a', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+ self.assertAlmostEqual(0, slice_event.start)
+ self.assertAlmostEqual((2 - 1) / 1000.0, slice_event.duration)
+
+ # Check process 2 thread 2.
+ # TODO: will this be in deterministic order?
+ p = processes[1]
+ self.assertEqual(2, p.pid)
+ self.assertEqual(1, len(p.threads))
+ t = p.threads[2]
+ self.assertEqual(1, len(t.all_slices))
+ self.assertEqual(2, t.tid)
+
+ slice_event = t.all_slices[0]
+ self.assertEqual('b', slice_event.name)
+ self.assertEqual('bar', slice_event.category)
+ self.assertAlmostEqual((3 - 1) / 1000.0, slice_event.start)
+ self.assertAlmostEqual((4 - 3) / 1000.0, slice_event.duration)
+
+ # Check getAllThreads.
+ self.assertEqual([processes[0].threads[1],
+ processes[1].threads[2]],
+ m.GetAllThreads())
+
+ def testThreadNames(self):
+ events = [
+ {'name': 'thread_name', 'args': {'name': 'Thread 1'},
+ 'pid': 1, 'ts': 0, 'tid': 1, 'ph': 'M'},
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'},
+ {'name': 'b', 'args': {}, 'pid': 2, 'ts': 3, 'cat': 'foo',
+ 'tid': 2, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 2, 'ts': 4, 'cat': 'foo',
+ 'tid': 2, 'ph': 'E'},
+ {'name': 'thread_name', 'args': {'name': 'Thread 2'},
+ 'pid': 2, 'ts': 0, 'tid': 2, 'ph': 'M'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ processes = m.GetAllProcesses()
+ self.assertEqual('Thread 1', processes[0].threads[1].name)
+ self.assertEqual('Thread 2', processes[1].threads[2].name)
+
+ def testParsingWhenEndComesFirst(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'},
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 4, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 5, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events,
+ shift_world_to_zero=False)
+ p = m.GetAllProcesses()[0]
+ t = p.threads[1]
+ self.assertEqual(1, len(t.all_slices))
+ self.assertEqual('a', t.all_slices[0].name)
+ self.assertEqual('foo', t.all_slices[0].category)
+ self.assertEqual(0.004, t.all_slices[0].start)
+ self.assertEqual(0.001, t.all_slices[0].duration)
+ self.assertEqual(1, len(m.import_errors))
+
+ def testImmediateParsing(self):
+ events = [
+ # Need to include immediates inside a task so the timeline
+ # recentering/zeroing doesn't clobber their timestamp.
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 1, 'cat': 'foo',
+ 'tid': 1, 'ph': 'B'},
+ {'name': 'immediate', 'args': {}, 'pid': 1, 'ts': 2, 'cat': 'bar',
+ 'tid': 1, 'ph': 'I'},
+ {'name': 'slower', 'args': {}, 'pid': 1, 'ts': 4, 'cat': 'baz',
+ 'tid': 1, 'ph': 'i'},
+ {'name': 'a', 'args': {}, 'pid': 1, 'ts': 4, 'cat': 'foo',
+ 'tid': 1, 'ph': 'E'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events,
+ shift_world_to_zero=False)
+ p = m.GetAllProcesses()[0]
+ t = p.threads[1]
+ self.assertEqual(3, len(t.all_slices))
+
+ i = m.GetAllEventsOfName('immediate')[0]
+ self.assertAlmostEqual(0.002, i.start)
+ self.assertAlmostEqual(0, i.duration)
+
+ slower = m.GetAllEventsOfName('slower')[0]
+ self.assertAlmostEqual(0.004, slower.start)
+
+ a = m.GetAllEventsOfName('a')[0]
+ self.assertAlmostEqual(0.001, a.start)
+ self.assertAlmostEqual(0.003, a.duration)
+
+ self.assertEqual('a', a.name)
+ self.assertEqual('foo', a.category)
+ self.assertEqual(0.003, a.duration)
+
+ self.assertEqual('immediate', i.name)
+ self.assertEqual('bar', i.category)
+ self.assertAlmostEqual(0.002, i.start)
+ self.assertAlmostEqual(0, i.duration)
+
+ self.assertEqual('slower', slower.name)
+ self.assertEqual('baz', slower.category)
+ self.assertAlmostEqual(0.004, slower.start)
+ self.assertAlmostEqual(0, slower.duration)
+
+ def testSimpleCounter(self):
+ events = [
+ {'name': 'ctr', 'args': {'value': 0}, 'pid': 1, 'ts': 0, 'cat': 'foo',
+ 'tid': 1, 'ph': 'C'},
+ {'name': 'ctr', 'args': {'value': 10}, 'pid': 1, 'ts': 10, 'cat': 'foo',
+ 'tid': 1, 'ph': 'C'},
+ {'name': 'ctr', 'args': {'value': 0}, 'pid': 1, 'ts': 20, 'cat': 'foo',
+ 'tid': 1, 'ph': 'C'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ p = m.GetAllProcesses()[0]
+ ctr = p.counters['foo.ctr']
+
+ self.assertEqual('ctr', ctr.name)
+ self.assertEqual('foo', ctr.category)
+ self.assertEqual(3, ctr.num_samples)
+ self.assertEqual(1, ctr.num_series)
+
+ self.assertEqual(['value'], ctr.series_names)
+ self.assertEqual([0, 0.01, 0.02], ctr.timestamps)
+ self.assertEqual([0, 10, 0], ctr.samples)
+ self.assertEqual([0, 10, 0], ctr.totals)
+ self.assertEqual(10, ctr.max_total)
+
+ def testInstanceCounter(self):
+ events = [
+ {'name': 'ctr', 'args': {'value': 0}, 'pid': 1, 'ts': 0, 'cat': 'foo',
+ 'tid': 1,
+ 'ph': 'C', 'id': 0},
+ {'name': 'ctr', 'args': {'value': 10}, 'pid': 1, 'ts': 10, 'cat': 'foo',
+ 'tid': 1,
+ 'ph': 'C', 'id': 0},
+ {'name': 'ctr', 'args': {'value': 10}, 'pid': 1, 'ts': 10, 'cat': 'foo',
+ 'tid': 1,
+ 'ph': 'C', 'id': 1},
+ {'name': 'ctr', 'args': {'value': 20}, 'pid': 1, 'ts': 15, 'cat': 'foo',
+ 'tid': 1,
+ 'ph': 'C', 'id': 1},
+ {'name': 'ctr', 'args': {'value': 30}, 'pid': 1, 'ts': 18, 'cat': 'foo',
+ 'tid': 1,
+ 'ph': 'C', 'id': 1},
+ {'name': 'ctr', 'args': {'value': 40}, 'pid': 1, 'ts': 20, 'cat': 'bar',
+ 'tid': 1,
+ 'ph': 'C', 'id': 2}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ p = m.GetAllProcesses()[0]
+ ctr = p.counters['foo.ctr[0]']
+ self.assertEqual('ctr[0]', ctr.name)
+ self.assertEqual('foo', ctr.category)
+ self.assertEqual(2, ctr.num_samples)
+ self.assertEqual(1, ctr.num_series)
+ self.assertEqual([0, 0.01], ctr.timestamps)
+ self.assertEqual([0, 10], ctr.samples)
+
+ ctr = m.GetAllProcesses()[0].counters['foo.ctr[1]']
+ self.assertEqual('ctr[1]', ctr.name)
+ self.assertEqual('foo', ctr.category)
+ self.assertEqual(3, ctr.num_samples)
+ self.assertEqual(1, ctr.num_series)
+ self.assertEqual([0.01, 0.015, 0.018], ctr.timestamps)
+ self.assertEqual([10, 20, 30], ctr.samples)
+
+ ctr = m.GetAllProcesses()[0].counters['bar.ctr[2]']
+ self.assertEqual('ctr[2]', ctr.name)
+ self.assertEqual('bar', ctr.category)
+ self.assertEqual(1, ctr.num_samples)
+ self.assertEqual(1, ctr.num_series)
+ self.assertEqual([0.02], ctr.timestamps)
+ self.assertEqual([40], ctr.samples)
+
+ def testMultiCounterUpdateBounds(self):
+ ctr = tracing_counter.Counter(None, 'testBasicCounter',
+ 'testBasicCounter')
+ ctr.series_names = ['value1', 'value2']
+ ctr.timestamps = [0, 1, 2, 3, 4, 5, 6, 7]
+ ctr.samples = [0, 0,
+ 1, 0,
+ 1, 1,
+ 2, 1.1,
+ 3, 0,
+ 1, 7,
+ 3, 0,
+ 3.1, 0.5]
+ ctr.FinalizeImport()
+ self.assertEqual(8, ctr.max_total)
+ self.assertEqual([0, 0,
+ 1, 1,
+ 1, 2,
+ 2, 3.1,
+ 3, 3,
+ 1, 8,
+ 3, 3,
+ 3.1, 3.6], ctr.totals)
+
+ def testMultiCounter(self):
+ events = [
+ {'name': 'ctr', 'args': {'value1': 0, 'value2': 7}, 'pid': 1, 'ts': 0,
+ 'cat': 'foo', 'tid': 1, 'ph': 'C'},
+ {'name': 'ctr', 'args': {'value1': 10, 'value2': 4}, 'pid': 1, 'ts': 10,
+ 'cat': 'foo', 'tid': 1, 'ph': 'C'},
+ {'name': 'ctr', 'args': {'value1': 0, 'value2': 1 }, 'pid': 1, 'ts': 20,
+ 'cat': 'foo', 'tid': 1, 'ph': 'C'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ p = m.GetAllProcesses()[0]
+ ctr = p.counters['foo.ctr']
+ self.assertEqual('ctr', ctr.name)
+
+ self.assertEqual('ctr', ctr.name)
+ self.assertEqual('foo', ctr.category)
+ self.assertEqual(3, ctr.num_samples)
+ self.assertEqual(2, ctr.num_series)
+
+ self.assertEqual(sorted(['value1', 'value2']), sorted(ctr.series_names))
+ self.assertEqual(sorted([0, 0.01, 0.02]), sorted(ctr.timestamps))
+ self.assertEqual(sorted([0, 7, 10, 4, 0, 1]), sorted(ctr.samples))
+ # We can't check ctr.totals here because it can change depending on
+ # the order in which the series names are added.
+ self.assertEqual(14, ctr.max_total)
+
+ def testImportObjectInsteadOfArray(self):
+ events = { 'traceEvents': [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 524, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'}
+ ] }
+
+ m = timeline_model.TimelineModel(event_data=events)
+ self.assertEqual(1, len(m.GetAllProcesses()))
+
+ def testImportString(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 524, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=json.dumps(events))
+ self.assertEqual(1, len(m.GetAllProcesses()))
+
+ def testImportStringWithTrailingNewLine(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 524, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=json.dumps(events) + '\n')
+ self.assertEqual(1, len(m.GetAllProcesses()))
+
+ def testImportStringWithMissingCloseSquareBracket(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 524, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'}
+ ]
+
+ tmp = json.dumps(events)
+ self.assertEqual(']', tmp[-1])
+
+ # Drop off the trailing ]
+ dropped = tmp[:-1]
+ m = timeline_model.TimelineModel(event_data=dropped)
+ self.assertEqual(1, len(m.GetAllProcesses()))
+
+ def testImportStringWithEndingCommaButMissingCloseSquareBracket(self):
+ lines = [
+ '[',
+ '{"name": "a", "args": {}, "pid": 52, "ts": 524, "cat": "foo", '
+ '"tid": 53, "ph": "B"},',
+ '{"name": "a", "args": {}, "pid": 52, "ts": 560, "cat": "foo", '
+ '"tid": 53, "ph": "E"},'
+ ]
+ text = '\n'.join(lines)
+
+ m = timeline_model.TimelineModel(event_data=text)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ self.assertEqual(1, len(processes[0].threads[53].all_slices))
+
+ def testImportStringWithMissingCloseSquareBracketAndNewline(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 524, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'}
+ ]
+
+ tmp = json.dumps(events)
+ self.assertEqual(']', tmp[-1])
+
+ # Drop off the trailing ] and add a newline
+ dropped = tmp[:-1]
+ m = timeline_model.TimelineModel(event_data=dropped + '\n')
+ self.assertEqual(1, len(m.GetAllProcesses()))
+
+ def testImportStringWithEndingCommaButMissingCloseSquareBracketCRLF(self):
+ lines = [
+ '[',
+ '{"name": "a", "args": {}, "pid": 52, "ts": 524, "cat": "foo", '
+ '"tid": 53, "ph": "B"},',
+ '{"name": "a", "args": {}, "pid": 52, "ts": 560, "cat": "foo", '
+ '"tid": 53, "ph": "E"},'
+ ]
+ text = '\r\n'.join(lines)
+
+ m = timeline_model.TimelineModel(event_data=text)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ self.assertEqual(1, len(processes[0].threads[53].all_slices))
+
+ def testImportOldFormat(self):
+ lines = [
+ '[',
+ '{"cat":"a","pid":9,"tid":8,"ts":194,"ph":"E","name":"I","args":{}},',
+ '{"cat":"b","pid":9,"tid":8,"ts":194,"ph":"B","name":"I","args":{}}',
+ ']'
+ ]
+ text = '\n'.join(lines)
+ m = timeline_model.TimelineModel(event_data=text)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ self.assertEqual(1, len(processes[0].threads[8].all_slices))
+
+ def testStartFinishOneSliceOneThread(self):
+ events = [
+ # Time is intentionally out of order.
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 560, 'cat': 'cat',
+ 'tid': 53,
+ 'ph': 'F', 'id': 72},
+ {'name': 'a', 'pid': 52, 'ts': 524, 'cat': 'cat',
+ 'tid': 53,
+ 'ph': 'S', 'id': 72, 'args': {'foo': 'bar'}}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+
+ self.assertEqual(2, len(m.GetAllEvents()))
+
+ processes = m.GetAllProcesses()
+ t = processes[0].threads[53]
+ slices = t.async_slices
+ self.assertEqual(1, len(slices))
+ self.assertEqual('a', slices[0].name)
+ self.assertEqual('cat', slices[0].category)
+ self.assertEqual(72, slices[0].id)
+ self.assertEqual('bar', slices[0].args['foo'])
+ self.assertEqual(0, slices[0].start)
+ self.assertAlmostEqual((60 - 24) / 1000.0, slices[0].duration)
+ self.assertEqual(t, slices[0].start_thread)
+ self.assertEqual(t, slices[0].end_thread)
+
+ def testEndArgsAddedToSlice(self):
+ events = [
+ {'name': 'a', 'args': {'x': 1}, 'pid': 52, 'ts': 520, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {'y': 2}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ p = processes[0]
+
+ self.assertEqual(1, len(p.threads))
+ t = p.threads[53]
+ self.assertEqual(1, len(t.all_slices))
+ self.assertEqual(53, t.tid)
+ slice_event = t.all_slices[0]
+ self.assertEqual('a', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+ self.assertEqual(0, slice_event.start)
+ self.assertEqual(1, slice_event.args['x'])
+ self.assertEqual(2, slice_event.args['y'])
+
+ def testEndArgOverrwritesOriginalArgValueIfDuplicated(self):
+ events = [
+ {'name': 'b', 'args': {'z': 3}, 'pid': 52, 'ts': 629, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'b', 'args': {'z': 4}, 'pid': 52, 'ts': 631, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ p = processes[0]
+
+ self.assertEqual(1, len(p.threads))
+ t = p.threads[53]
+ slice_event = t.all_slices[0]
+ self.assertEqual('b', slice_event.name)
+ self.assertEqual('foo', slice_event.category)
+ self.assertEqual(0, slice_event.start)
+ self.assertEqual(4, slice_event.args['z'])
+
+ def testSliceHierarchy(self):
+ ''' The slice hierarchy should look something like this:
+ [ a ]
+ [ b ] [ d ]
+ [ c ] [ e ]
+ '''
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 100, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 200, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'},
+ {'name': 'b', 'args': {}, 'pid': 52, 'ts': 125, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'b', 'args': {}, 'pid': 52, 'ts': 165, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'},
+ {'name': 'c', 'args': {}, 'pid': 52, 'ts': 125, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'c', 'args': {}, 'pid': 52, 'ts': 135, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'},
+ {'name': 'd', 'args': {}, 'pid': 52, 'ts': 175, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'd', 'args': {}, 'pid': 52, 'ts': 190, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'},
+ {'name': 'e', 'args': {}, 'pid': 52, 'ts': 155, 'cat': 'foo',
+ 'tid': 53, 'ph': 'B'},
+ {'name': 'e', 'args': {}, 'pid': 52, 'ts': 165, 'cat': 'foo',
+ 'tid': 53, 'ph': 'E'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events,
+ shift_world_to_zero=False)
+ processes = m.GetAllProcesses()
+ self.assertEqual(1, len(processes))
+ p = processes[0]
+
+ self.assertEqual(1, len(p.threads))
+ t = p.threads[53]
+
+ slice_a = t.all_slices[0]
+ self.assertEqual(4, len(slice_a.GetAllSubSlices()))
+ self.assertEqual('a', slice_a.name)
+ self.assertEqual(100 / 1000.0, slice_a.start)
+ self.assertEqual(200 / 1000.0, slice_a.end)
+ self.assertEqual(2, len(slice_a.sub_slices))
+
+ slice_b = slice_a.sub_slices[0]
+ self.assertEqual('b', slice_b.name)
+ self.assertEqual(2, len(slice_b.sub_slices))
+ self.assertEqual('c', slice_b.sub_slices[0].name)
+ self.assertEqual('e', slice_b.sub_slices[1].name)
+
+ slice_d = slice_a.sub_slices[1]
+ self.assertEqual('d', slice_d.name)
+ self.assertEqual(0, len(slice_d.sub_slices))
+
+ def testAsyncEndArgAddedToSlice(self):
+ events = [
+ # Time is intentionally out of order.
+ {'name': 'c', 'args': {'y': 2}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53,
+ 'ph': 'F', 'id': 72},
+ {'name': 'c', 'args': {'x': 1}, 'pid': 52, 'ts': 524, 'cat': 'foo',
+ 'tid': 53,
+ 'ph': 'S', 'id': 72}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ t = m.GetAllProcesses()[0].threads[53]
+ self.assertEqual(1, len(t.async_slices))
+ parent_slice = t.async_slices[0]
+ self.assertEqual('c', parent_slice.name)
+ self.assertEqual('foo', parent_slice.category)
+
+ self.assertEqual(1, len(parent_slice.sub_slices))
+ sub_slice = parent_slice.sub_slices[0]
+ self.assertEqual(1, sub_slice.args['x'])
+ self.assertEqual(2, sub_slice.args['y'])
+
+ def testAsyncEndArgOverrwritesOriginalArgValueIfDuplicated(self):
+ events = [
+ # Time is intentionally out of order.
+ {'name': 'd', 'args': {'z': 4}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53,
+ 'ph': 'F', 'id': 72},
+ {'name': 'd', 'args': {'z': 3}, 'pid': 52, 'ts': 524, 'cat': 'foo',
+ 'tid': 53,
+ 'ph': 'S', 'id': 72}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ t = m.GetAllProcesses()[0].threads[53]
+ self.assertEqual(1, len(t.async_slices))
+ parent_slice = t.async_slices[0]
+ self.assertEqual('d', parent_slice.name)
+ self.assertEqual('foo', parent_slice.category)
+
+ self.assertEqual(1, len(parent_slice.sub_slices))
+ sub_slice = parent_slice.sub_slices[0]
+ self.assertEqual(4, sub_slice.args['z'])
+
+ def testAsyncStepsInOneThread(self):
+ events = [
+ # Time is intentionally out of order.
+ {'name': 'a', 'args': {'z': 3}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'F', 'id': 72},
+ {'name': 'a', 'args': {'step': 's1', 'y': 2}, 'pid': 52, 'ts': 548,
+ 'cat': 'foo', 'tid': 53, 'ph': 'T', 'id': 72},
+ {'name': 'a', 'args': {'x': 1}, 'pid': 52, 'ts': 524, 'cat': 'foo',
+ 'tid': 53, 'ph': 'S', 'id': 72}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ t = m.GetAllProcesses()[0].threads[53]
+ self.assertEqual(1, len(t.async_slices))
+ parent_slice = t.async_slices[0]
+ self.assertEqual('a', parent_slice.name)
+ self.assertEqual('foo', parent_slice.category)
+ self.assertEqual(0, parent_slice.start)
+
+ self.assertEqual(2, len(parent_slice.sub_slices))
+ sub_slice = parent_slice.sub_slices[0]
+ self.assertEqual('a', sub_slice.name)
+ self.assertEqual('foo', sub_slice.category)
+ self.assertAlmostEqual(0, sub_slice.start)
+ self.assertAlmostEqual((548 - 524) / 1000.0, sub_slice.duration)
+ self.assertEqual(1, sub_slice.args['x'])
+
+ sub_slice = parent_slice.sub_slices[1]
+ self.assertEqual('a:s1', sub_slice.name)
+ self.assertEqual('foo', sub_slice.category)
+ self.assertAlmostEqual((548 - 524) / 1000.0, sub_slice.start)
+ self.assertAlmostEqual((560 - 548) / 1000.0, sub_slice.duration)
+ self.assertEqual(2, sub_slice.args['y'])
+ self.assertEqual(3, sub_slice.args['z'])
+
+ def testAsyncStepsMissingStart(self):
+ events = [
+ # Time is intentionally out of order.
+ {'name': 'a', 'args': {'z': 3}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'F', 'id': 72},
+ {'name': 'a', 'args': {'step': 's1', 'y': 2}, 'pid': 52, 'ts': 548,
+ 'cat': 'foo', 'tid': 53, 'ph': 'T', 'id': 72}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ t = m.GetAllProcesses()[0].threads[53]
+ self.assertTrue(t is not None)
+
+ def testAsyncStepsMissingFinish(self):
+ events = [
+ # Time is intentionally out of order.
+ {'name': 'a', 'args': {'step': 's1', 'y': 2}, 'pid': 52, 'ts': 548,
+ 'cat': 'foo', 'tid': 53, 'ph': 'T', 'id': 72},
+ {'name': 'a', 'args': {'z': 3}, 'pid': 52, 'ts': 560, 'cat': 'foo',
+ 'tid': 53, 'ph': 'S', 'id': 72}
+ ]
+
+ m = timeline_model.TimelineModel(event_data=events)
+ t = m.GetAllProcesses()[0].threads[53]
+ self.assertTrue(t is not None)
+
+ def testImportSamples(self):
+ events = [
+ {'name': 'a', 'args': {}, 'pid': 52, 'ts': 548, 'cat': 'test',
+ 'tid': 53, 'ph': 'P'},
+ {'name': 'b', 'args': {}, 'pid': 52, 'ts': 548, 'cat': 'test',
+ 'tid': 53, 'ph': 'P'},
+ {'name': 'c', 'args': {}, 'pid': 52, 'ts': 558, 'cat': 'test',
+ 'tid': 53, 'ph': 'P'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ p = m.GetAllProcesses()[0]
+ t = p.threads[53]
+ self.assertEqual(3, len(t.samples))
+ self.assertEqual(0.0, t.samples[0].start)
+ self.assertEqual(0.0, t.samples[1].start)
+ self.assertAlmostEqual(0.01, t.samples[2].start)
+ self.assertEqual('a', t.samples[0].name)
+ self.assertEqual('b', t.samples[1].name)
+ self.assertEqual('c', t.samples[2].name)
+ self.assertEqual(0, len(m.import_errors))
+
+ def testImportSamplesMissingArgs(self):
+ events = [
+ {'name': 'a', 'pid': 52, 'ts': 548, 'cat': 'test',
+ 'tid': 53, 'ph': 'P'},
+ {'name': 'b', 'pid': 52, 'ts': 548, 'cat': 'test',
+ 'tid': 53, 'ph': 'P'},
+ {'name': 'c', 'pid': 52, 'ts': 549, 'cat': 'test',
+ 'tid': 53, 'ph': 'P'}
+ ]
+ m = timeline_model.TimelineModel(event_data=events)
+ p = m.GetAllProcesses()[0]
+ t = p.threads[53]
+ self.assertEqual(3, len(t.samples))
+ self.assertEqual(0, len(m.import_errors))
diff --git a/chromium/tools/telemetry/telemetry/core/user_agent.py b/chromium/tools/telemetry/telemetry/core/user_agent.py
new file mode 100644
index 00000000000..811aca2bd72
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/user_agent.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+UA_TYPE_MAPPING = {
+ 'desktop':
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) '
+ 'AppleWebKit/537.22 (KHTML, like Gecko) '
+ 'Chrome/27.0.1453.111 Safari/537.22',
+ 'mobile':
+ 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) '
+ 'AppleWebKit/535.19 (KHTML, like Gecko) Chrome/27.0.1453.111 Mobile '
+ 'Safari/535.19',
+ 'tablet':
+ 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus 7 Build/IMM76B) '
+ 'AppleWebKit/535.19 (KHTML, like Gecko) Chrome/27.0.1453.111 '
+ 'Safari/535.19',
+}
+
+
+def GetChromeUserAgentArgumentFromType(user_agent_type):
+ """Returns a chrome user agent based on a user agent type.
+ This is derived from:
+ https://developers.google.com/chrome/mobile/docs/user-agent
+ """
+ if user_agent_type:
+ return ['--user-agent=%s' % UA_TYPE_MAPPING[user_agent_type]]
+ return []
diff --git a/chromium/tools/telemetry/telemetry/core/user_agent_unittest.py b/chromium/tools/telemetry/telemetry/core/user_agent_unittest.py
new file mode 100644
index 00000000000..32cbbb70567
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/user_agent_unittest.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core import user_agent
+from telemetry.unittest import tab_test_case
+
+
+class UserAgentTest(tab_test_case.TabTestCase):
+ def CustomizeBrowserOptions(self, options):
+ options.browser_user_agent_type = 'tablet'
+
+ def testUserAgent(self):
+ ua = self._tab.EvaluateJavaScript('window.navigator.userAgent')
+ self.assertEquals(ua, user_agent.UA_TYPE_MAPPING['tablet'])
diff --git a/chromium/tools/telemetry/telemetry/core/util.py b/chromium/tools/telemetry/telemetry/core/util.py
new file mode 100644
index 00000000000..fddab1c3c5e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/util.py
@@ -0,0 +1,108 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import inspect
+import os
+import socket
+import sys
+import time
+
+class TimeoutException(Exception):
+ pass
+
+def GetBaseDir():
+ main_module = sys.modules['__main__']
+ if hasattr(main_module, '__file__'):
+ return os.path.dirname(os.path.abspath(main_module.__file__))
+ else:
+ return os.getcwd()
+
+def GetTelemetryDir():
+ return os.path.normpath(os.path.join(
+ __file__, os.pardir, os.pardir, os.pardir))
+
+def GetUnittestDataDir():
+ return os.path.join(GetTelemetryDir(), 'unittest_data')
+
+def GetChromiumSrcDir():
+ return os.path.normpath(os.path.join(GetTelemetryDir(), os.pardir, os.pardir))
+
+def WaitFor(condition,
+ timeout, poll_interval=0.1,
+ pass_time_left_to_func=False):
+ assert isinstance(condition, type(lambda: None)) # is function
+ start_time = time.time()
+ while True:
+ if pass_time_left_to_func:
+ res = condition(max((start_time + timeout) - time.time(), 0.0))
+ else:
+ res = condition()
+ if res:
+ break
+ if time.time() - start_time > timeout:
+ if condition.__name__ == '<lambda>':
+ try:
+ condition_string = inspect.getsource(condition).strip()
+ except IOError:
+ condition_string = condition.__name__
+ else:
+ condition_string = condition.__name__
+ raise TimeoutException('Timed out while waiting %ds for %s.' %
+ (timeout, condition_string))
+ time.sleep(poll_interval)
+
+def FindElementAndPerformAction(tab, text, callback_code):
+ """JavaScript snippet for finding an element with a given text on a page."""
+ code = """
+ (function() {
+ var callback_function = """ + callback_code + """;
+ function _findElement(element, text) {
+ if (element.innerHTML == text) {
+ callback_function
+ return element;
+ }
+ for (var i in element.childNodes) {
+ var found = _findElement(element.childNodes[i], text);
+ if (found)
+ return found;
+ }
+ return null;
+ }
+ var _element = _findElement(document, \"""" + text + """\");
+ return callback_function(_element);
+ })();"""
+ return tab.EvaluateJavaScript(code)
+
+class PortPair(object):
+ def __init__(self, local_port, remote_port):
+ self.local_port = local_port
+ self.remote_port = remote_port
+
+def GetAvailableLocalPort():
+ tmp = socket.socket()
+ tmp.bind(('', 0))
+ port = tmp.getsockname()[1]
+ tmp.close()
+
+ return port
+
+def CloseConnections(tab):
+ """Closes all TCP sockets held open by the browser."""
+ try:
+ tab.ExecuteJavaScript("""window.chrome && chrome.benchmarking &&
+ chrome.benchmarking.closeConnections()""")
+ except Exception:
+ pass
+
+def GetBuildDirectories():
+ """Yields all combination of Chromium build output directories."""
+ build_dirs = ['build',
+ 'out',
+ 'sconsbuild',
+ 'xcodebuild']
+
+ build_types = ['Debug', 'Debug_x64', 'Release', 'Release_x64']
+
+ for build_dir in build_dirs:
+ for build_type in build_types:
+ yield build_dir, build_type
diff --git a/chromium/tools/telemetry/telemetry/core/util_unittest.py b/chromium/tools/telemetry/telemetry/core/util_unittest.py
new file mode 100644
index 00000000000..03d878e7934
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/util_unittest.py
@@ -0,0 +1,18 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.core import util
+
+class TestWait(unittest.TestCase):
+ @staticmethod
+ def testNonTimeout():
+ def test():
+ return True
+ util.WaitFor(test, 0.1)
+
+ def testTimeout(self):
+ def test():
+ return False
+ self.assertRaises(util.TimeoutException, lambda: util.WaitFor(test, 0.1))
diff --git a/chromium/tools/telemetry/telemetry/core/web_contents.py b/chromium/tools/telemetry/telemetry/core/web_contents.py
new file mode 100644
index 00000000000..837c084f46a
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/web_contents.py
@@ -0,0 +1,73 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+DEFAULT_WEB_CONTENTS_TIMEOUT = 60
+
+# TODO(achuith, dtu, nduca): Add unit tests specifically for WebContents,
+# independent of Tab.
+class WebContents(object):
+ """Represents web contents in the browser"""
+ def __init__(self, inspector_backend):
+ self._inspector_backend = inspector_backend
+
+ def __del__(self):
+ self.Disconnect()
+
+ def Disconnect(self):
+ self._inspector_backend.Disconnect()
+
+ def Close(self):
+ """Closes this page.
+
+ Not all browsers or browser versions support this method.
+ Be sure to check browser.supports_tab_control."""
+ self._inspector_backend.Close()
+
+ def WaitForDocumentReadyStateToBeComplete(self,
+ timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
+ self._inspector_backend.WaitForDocumentReadyStateToBeComplete(timeout)
+
+ def WaitForDocumentReadyStateToBeInteractiveOrBetter(self,
+ timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
+ self._inspector_backend.WaitForDocumentReadyStateToBeInteractiveOrBetter(
+ timeout)
+
+ def ExecuteJavaScript(self, expr, timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
+ """Executes expr in JavaScript. Does not return the result.
+
+ If the expression failed to evaluate, EvaluateException will be raised.
+ """
+ self._inspector_backend.ExecuteJavaScript(expr, timeout)
+
+ def EvaluateJavaScript(self, expr, timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
+ """Evalutes expr in JavaScript and returns the JSONized result.
+
+ Consider using ExecuteJavaScript for cases where the result of the
+ expression is not needed.
+
+ If evaluation throws in JavaScript, a Python EvaluateException will
+ be raised.
+
+ If the result of the evaluation cannot be JSONized, then an
+ EvaluationException will be raised.
+ """
+ return self._inspector_backend.EvaluateJavaScript(expr, timeout)
+
+ @property
+ def message_output_stream(self):
+ return self._inspector_backend.message_output_stream
+
+ @message_output_stream.setter
+ def message_output_stream(self, stream):
+ self._inspector_backend.message_output_stream = stream
+
+ @property
+ def timeline_model(self):
+ return self._inspector_backend.timeline_model
+
+ def StartTimelineRecording(self):
+ self._inspector_backend.StartTimelineRecording()
+
+ def StopTimelineRecording(self):
+ self._inspector_backend.StopTimelineRecording()
diff --git a/chromium/tools/telemetry/telemetry/core/wpr_modes.py b/chromium/tools/telemetry/telemetry/core/wpr_modes.py
new file mode 100644
index 00000000000..64ffe08853c
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/wpr_modes.py
@@ -0,0 +1,7 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+WPR_OFF = 'wpr-off'
+WPR_RECORD = 'wpr-record'
+WPR_REPLAY = 'wpr-replay'
+
diff --git a/chromium/tools/telemetry/telemetry/core/wpr_server.py b/chromium/tools/telemetry/telemetry/core/wpr_server.py
new file mode 100644
index 00000000000..88abc5bba55
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/core/wpr_server.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+from telemetry.core import util
+
+# Get chrome/test/functional scripts into our path.
+# TODO(tonyg): Move webpagereplay.py to a common location.
+sys.path.append(
+ os.path.abspath(
+ os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', '..', 'chrome', 'test', 'functional')))
+import webpagereplay # pylint: disable=F0401
+
+def GetChromeFlags(replay_host, http_port, https_port):
+ return webpagereplay.GetChromeFlags(replay_host, http_port, https_port)
+
+class _WebPageReplayServer(webpagereplay.ReplayServer): # pylint: disable=W0232
+ def _AddDefaultReplayOptions(self):
+ """Override. Because '--no-dns_forwarding' is added by default in parent
+ while webdriver-based backends need dns forwarding."""
+ self.replay_options += [
+ '--port', str(self._http_port),
+ '--ssl_port', str(self._https_port),
+ '--use_closest_match',
+ '--log_level', 'warning'
+ ]
+
+class ReplayServer(object):
+ def __init__(self, browser_backend, path, is_record_mode, is_append_mode,
+ make_javascript_deterministic, webpagereplay_host,
+ webpagereplay_local_http_port, webpagereplay_local_https_port,
+ webpagereplay_remote_http_port, webpagereplay_remote_https_port):
+ self._browser_backend = browser_backend
+ self._forwarder = None
+ self._web_page_replay = None
+ self._is_record_mode = is_record_mode
+ self._is_append_mode = is_append_mode
+ self._webpagereplay_host = webpagereplay_host
+ self._webpagereplay_local_http_port = webpagereplay_local_http_port
+ self._webpagereplay_local_https_port = webpagereplay_local_https_port
+ self._webpagereplay_remote_http_port = webpagereplay_remote_http_port
+ self._webpagereplay_remote_https_port = webpagereplay_remote_https_port
+
+ self._forwarder = browser_backend.CreateForwarder(
+ util.PortPair(self._webpagereplay_local_http_port,
+ self._webpagereplay_remote_http_port),
+ util.PortPair(self._webpagereplay_local_https_port,
+ self._webpagereplay_remote_https_port))
+
+ options = browser_backend.options.extra_wpr_args
+ if self._is_record_mode:
+ if self._is_append_mode:
+ options.append('--append')
+ else:
+ options.append('--record')
+ if not make_javascript_deterministic:
+ options.append('--inject_scripts=')
+ browser_backend.AddReplayServerOptions(options)
+ self._web_page_replay = _WebPageReplayServer(
+ path,
+ self._webpagereplay_host,
+ self._webpagereplay_local_http_port,
+ self._webpagereplay_local_https_port,
+ options)
+ self._web_page_replay.StartServer()
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ self.Close()
+
+ def Close(self):
+ if self._forwarder:
+ self._forwarder.Close()
+ self._forwarder = None
+ if self._web_page_replay:
+ self._web_page_replay.StopServer()
+ self._web_page_replay = None
diff --git a/chromium/tools/telemetry/telemetry/page/__init__.py b/chromium/tools/telemetry/telemetry/page/__init__.py
new file mode 100644
index 00000000000..96196cffb27
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/__init__.py
@@ -0,0 +1,3 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/telemetry/telemetry/page/actions/__init__.py b/chromium/tools/telemetry/telemetry/page/actions/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/__init__.py
diff --git a/chromium/tools/telemetry/telemetry/page/actions/all_page_actions.py b/chromium/tools/telemetry/telemetry/page/actions/all_page_actions.py
new file mode 100644
index 00000000000..115bb451908
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/all_page_actions.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.core import discover
+from telemetry.page.actions import page_action
+
+_page_action_classes = discover.DiscoverClasses(
+ os.path.dirname(__file__),
+ os.path.join(os.path.dirname(__file__), '..', '..', '..'),
+ page_action.PageAction)
+
+def GetAllClasses():
+ return list(_page_action_classes.values())
+
+def FindClassWithName(name):
+ return _page_action_classes.get(name)
+
+def RegisterClassForTest(name, clazz):
+ _page_action_classes[name] = clazz
diff --git a/chromium/tools/telemetry/telemetry/page/actions/click_element.py b/chromium/tools/telemetry/telemetry/page/actions/click_element.py
new file mode 100644
index 00000000000..8d4aa790a59
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/click_element.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.core import util
+from telemetry.core import exceptions
+from telemetry.page import page as page_module
+from telemetry.page.actions import page_action
+
+class ClickElementAction(page_action.PageAction):
+ def __init__(self, attributes=None):
+ super(ClickElementAction, self).__init__(attributes)
+
+ def RunAction(self, page, tab, previous_action):
+ def DoClick():
+ assert hasattr(self, 'selector') or hasattr(self, 'text')
+ if hasattr(self, 'selector'):
+ code = 'document.querySelector(\'' + self.selector + '\').click();'
+ try:
+ tab.ExecuteJavaScript(code)
+ except exceptions.EvaluateException:
+ raise page_action.PageActionFailed(
+ 'Cannot find element with selector ' + self.selector)
+ else:
+ callback_code = 'function(element) { element.click(); }'
+ try:
+ util.FindElementAndPerformAction(tab, self.text, callback_code)
+ except exceptions.EvaluateException:
+ raise page_action.PageActionFailed(
+ 'Cannot find element with text ' + self.text)
+
+ if hasattr(self, 'wait_for_navigate'):
+ tab.PerformActionAndWaitForNavigate(DoClick)
+ elif hasattr(self, 'wait_for_href_change'):
+ old_url = tab.EvaluateJavaScript('document.location.href')
+ DoClick()
+ util.WaitFor(lambda: tab.EvaluateJavaScript(
+ 'document.location.href') != old_url, 60)
+ else:
+ DoClick()
+
+ page_module.Page.WaitForPageToLoad(self, tab, 60)
+ tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
diff --git a/chromium/tools/telemetry/telemetry/page/actions/click_element_unittest.py b/chromium/tools/telemetry/telemetry/page/actions/click_element_unittest.py
new file mode 100644
index 00000000000..03eb87aa383
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/click_element_unittest.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.page.actions import click_element
+from telemetry.unittest import tab_test_case
+
+class ClickElementActionTest(tab_test_case.TabTestCase):
+ def testClickWithSelectorWaitForNavigation(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+ self._tab.Navigate(
+ self._browser.http_server.UrlOf('page_with_link.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ self.assertEquals(
+ self._tab.EvaluateJavaScript('document.location.pathname;'),
+ '/page_with_link.html')
+
+ data = {'selector': 'a[id="clickme"]', 'wait_for_href_change': True}
+ i = click_element.ClickElementAction(data)
+ i.RunAction(None, self._tab, None)
+
+ self.assertEquals(
+ self._tab.EvaluateJavaScript('document.location.pathname;'),
+ '/blank.html')
+
+ def testClickWithTextWaitForRefChange(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+ self._tab.Navigate(
+ self._browser.http_server.UrlOf('page_with_link.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ self.assertEquals(
+ self._tab.EvaluateJavaScript('document.location.pathname;'),
+ '/page_with_link.html')
+
+ data = {'text': 'Click me', 'wait_for_href_change': True}
+ i = click_element.ClickElementAction(data)
+ i.RunAction(None, self._tab, None)
+
+ self.assertEquals(
+ self._tab.EvaluateJavaScript('document.location.pathname;'),
+ '/blank.html')
diff --git a/chromium/tools/telemetry/telemetry/page/actions/js_collect_garbage.py b/chromium/tools/telemetry/telemetry/page/actions/js_collect_garbage.py
new file mode 100644
index 00000000000..3ba9f53b307
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/js_collect_garbage.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.page.actions import page_action
+
+class JsCollectGarbageAction(page_action.PageAction):
+ def __init__(self, attributes=None):
+ super(JsCollectGarbageAction, self).__init__(attributes)
+
+ def RunAction(self, page, tab, previous_action):
+ tab.CollectGarbage()
diff --git a/chromium/tools/telemetry/telemetry/page/actions/media_action.js b/chromium/tools/telemetry/telemetry/page/actions/media_action.js
new file mode 100644
index 00000000000..96f6ffa658e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/media_action.js
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+// This file provides common functions for media actions.
+window.__findMediaElements = function(selector) {
+ // Returns elements matching the selector, otherwise returns the first video
+ // or audio tag element that can be found.
+ // If selector == 'all', returns all media elements.
+ if (selector == 'all') {
+ return document.querySelectorAll('video, audio');
+ } else if (selector) {
+ return document.querySelectorAll(selector);
+ } else {
+ var media = document.getElementsByTagName('video');
+ if (media.length > 0) {
+ return [media[0]];
+ } else {
+ media = document.getElementsByTagName('audio');
+ if (media.length > 0) {
+ return [media[0]];
+ }
+ }
+ }
+ console.error('Could not find any media elements matching: ' + selector);
+ return [];
+};
+
+window.__hasEventCompleted = function(selector, event_name) {
+ // Return true if the event_name fired for media satisfying the selector.
+ var mediaElements = window.__findMediaElements(selector);
+ for (var i = 0; i < mediaElements.length; i++) {
+ if (!mediaElements[i][event_name + '_completed'])
+ return false;
+ }
+ return true;
+};
diff --git a/chromium/tools/telemetry/telemetry/page/actions/media_action.py b/chromium/tools/telemetry/telemetry/page/actions/media_action.py
new file mode 100644
index 00000000000..7f3829b3f10
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/media_action.py
@@ -0,0 +1,46 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Common media action functions."""
+
+import os
+
+from telemetry.core import util
+from telemetry.page.actions import page_action
+
+
+class MediaAction(page_action.PageAction):
+ def __init__(self, attributes=None):
+ super(MediaAction, self).__init__(attributes)
+
+ def WillRunAction(self, page, tab):
+ """Loads the common media action JS code prior to running the action."""
+ self.LoadJS(tab, 'media_action.js')
+
+ def RunAction(self, page, tab, previous_action):
+ super(MediaAction, self).RunAction(page, tab, previous_action)
+
+ def LoadJS(self, tab, js_file_name):
+ """Loads and executes a JS file in the tab."""
+ with open(os.path.join(os.path.dirname(__file__), js_file_name)) as f:
+ js = f.read()
+ tab.ExecuteJavaScript(js)
+
+ def WaitForEvent(self, tab, selector, event_name, timeout,
+ poll_interval=0.5):
+ """Halts media action until the selector's event is fired.
+
+ Args:
+ tab: The tab to check for event on.
+ selector: Media element selector.
+ event_name: Name of the event to check if fired or not.
+ timeout: Timeout to check for event, throws an exception if not fired.
+ poll_interval: Interval to poll for event firing status.
+ """
+ util.WaitFor(lambda: self.HasEventCompleted(tab, selector, event_name),
+ timeout=timeout, poll_interval=poll_interval)
+
+ def HasEventCompleted(self, tab, selector, event_name):
+ return tab.EvaluateJavaScript(
+ 'window.__hasEventCompleted("%s", "%s");' % (selector, event_name)) \ No newline at end of file
diff --git a/chromium/tools/telemetry/telemetry/page/actions/page_action.py b/chromium/tools/telemetry/telemetry/page/actions/page_action.py
new file mode 100644
index 00000000000..c6da0801348
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/page_action.py
@@ -0,0 +1,61 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class PageActionNotSupported(Exception):
+ pass
+
+class PageActionFailed(Exception):
+ pass
+
+class PageAction(object):
+ """Represents an action that a user might try to perform to a page."""
+ def __init__(self, attributes=None):
+ if attributes:
+ for k, v in attributes.iteritems():
+ setattr(self, k, v)
+
+ def CustomizeBrowserOptions(self, options):
+ """Override to add action-specific options to the BrowserOptions
+ object."""
+ pass
+
+ def WillRunAction(self, page, tab):
+ """Override to do action-specific setup before
+ Test.WillRunAction is called."""
+ pass
+
+ def RunAction(self, page, tab, previous_action):
+ raise NotImplementedError()
+
+ def RunsPreviousAction(self):
+ """Some actions require some initialization to be performed before the
+ previous action. For example, wait for href change needs to record the old
+ href before the previous action changes it. Therefore, we allow actions to
+ run the previous action. An action that does this should override this to
+ return True in order to prevent the previous action from being run twice."""
+ return False
+
+ def CleanUp(self, page, tab):
+ pass
+
+ def CanBeBound(self):
+ """If this class implements BindMeasurementJavaScript, override CanBeBound
+ to return True so that a test knows it can bind measurements."""
+ return False
+
+ def BindMeasurementJavaScript(
+ self, tab, start_js, stop_js): # pylint: disable=W0613
+ """Let this action determine when measurements should start and stop.
+
+ A measurement can call this method to provide the action
+ with JavaScript code that starts and stops measurements. The action
+ determines when to execute the provided JavaScript code, for more accurate
+ timings.
+
+ Args:
+ tab: The tab to do everything on.
+ start_js: JavaScript code that starts measurements.
+ stop_js: JavaScript code that stops measurements.
+ """
+ raise Exception('This action cannot be bound.')
diff --git a/chromium/tools/telemetry/telemetry/page/actions/play.js b/chromium/tools/telemetry/telemetry/page/actions/play.js
new file mode 100644
index 00000000000..80e42c42f6e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/play.js
@@ -0,0 +1,42 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file performs actions on media elements.
+(function() {
+ function playMedia(selector) {
+ // Performs the "Play" action on media satisfying selector.
+ var mediaElements = window.__findMediaElements(selector);
+ for (var i = 0; i < mediaElements.length; i++) {
+ console.log('Playing element: ' + mediaElements[i].src);
+ play(mediaElements[i]);
+ }
+ }
+
+ function play(element) {
+ if (element instanceof HTMLMediaElement)
+ playHTML5Element(element);
+ else
+ throw new Error('Can not play non HTML5 media elements.');
+ }
+
+ function playHTML5Element(element) {
+ function logEventHappened(e) {
+ element[e.type + '_completed'] = true;
+ }
+ function onError(e) {
+ throw new Error('Error playing media :' + e.type);
+ }
+ element.addEventListener('playing', logEventHappened);
+ element.addEventListener('ended', logEventHappened);
+ element.addEventListener('error', onError);
+ element.addEventListener('abort', onError);
+
+ var willPlayEvent = document.createEvent('Event');
+ willPlayEvent.initEvent('willPlay', false, false);
+ element.dispatchEvent(willPlayEvent);
+ element.play();
+ }
+
+ window.__playMedia = playMedia;
+})();
diff --git a/chromium/tools/telemetry/telemetry/page/actions/play.py b/chromium/tools/telemetry/telemetry/page/actions/play.py
new file mode 100644
index 00000000000..3f673711a4f
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/play.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A Telemetry page_action that performs the "play" action on media elements.
+
+Media elements can be specified by a selector attribute. If no selector is
+defined then then the action attempts to play the first video element or audio
+element on the page. A selector can also be 'all' to play all media elements.
+
+Other attributes to use are: wait_for_playing and wait_for_ended, which forces
+the action to wait until playing and ended events get fired respectively.
+"""
+
+from telemetry.page.actions.media_action import MediaAction
+from telemetry.core import exceptions
+from telemetry.page.actions import page_action
+
+
+class PlayAction(MediaAction):
+ def __init__(self, attributes=None):
+ super(PlayAction, self).__init__(attributes)
+
+ def WillRunAction(self, page, tab):
+ """Load the media metrics JS code prior to running the action."""
+ super(PlayAction, self).WillRunAction(page, tab)
+ self.LoadJS(tab, 'play.js')
+
+ def RunAction(self, page, tab, previous_action):
+ try:
+ selector = self.selector if hasattr(self, 'selector') else ''
+ tab.ExecuteJavaScript('window.__playMedia("%s");' % selector)
+ timeout = self.wait_timeout if hasattr(self, 'wait_timeout') else 60
+ # Check if we need to wait for 'playing' event to fire.
+ if hasattr(self, 'wait_for_playing') and self.wait_for_playing:
+ self.WaitForEvent(tab, selector, 'playing', timeout)
+ # Check if we need to wait for 'ended' event to fire.
+ if hasattr(self, 'wait_for_ended') and self.wait_for_ended:
+ self.WaitForEvent(tab, selector, 'ended', timeout)
+ except exceptions.EvaluateException:
+ raise page_action.PageActionFailed('Cannot play media element(s) with '
+ 'selector = %s.' % selector)
diff --git a/chromium/tools/telemetry/telemetry/page/actions/play_unittest.py b/chromium/tools/telemetry/telemetry/page/actions/play_unittest.py
new file mode 100644
index 00000000000..b29f8f8bb2f
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/play_unittest.py
@@ -0,0 +1,108 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core import util
+from telemetry.page.actions import play
+from telemetry.unittest import tab_test_case
+
+AUDIO_1_PLAYING_CHECK = 'window.__hasEventCompleted("#audio_1", "playing");'
+VIDEO_1_PLAYING_CHECK = 'window.__hasEventCompleted("#video_1", "playing");'
+VIDEO_1_ENDED_CHECK = 'window.__hasEventCompleted("#video_1", "ended");'
+
+
+class PlayActionTest(tab_test_case.TabTestCase):
+
+ def setUp(self):
+ tab_test_case.TabTestCase.setUp(self)
+ self._browser.SetHTTPServerDirectories(util.GetUnittestDataDir())
+ self._tab.Navigate(self._browser.http_server.UrlOf('video_test.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ def testPlayWithNoSelector(self):
+ """Tests that with no selector Play action plays first video element."""
+ data = {'wait_for_playing': True}
+ action = play.PlayAction(data)
+ action.WillRunAction(None, self._tab)
+ # Both videos not playing before running action.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_PLAYING_CHECK))
+ action.RunAction(None, self._tab, None)
+ # Assert only first video has played.
+ self.assertTrue(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_PLAYING_CHECK))
+
+ def testPlayWithVideoSelector(self):
+ """Tests that Play action plays video element matching selector."""
+ data = {'selector': '#video_1', 'wait_for_playing': True}
+ action = play.PlayAction(data)
+ action.WillRunAction(None, self._tab)
+ # Both videos not playing before running action.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_PLAYING_CHECK))
+ action.RunAction(None, self._tab, None)
+ # Assert only video matching selector has played.
+ self.assertTrue(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_PLAYING_CHECK))
+
+ def testPlayWithAllSelector(self):
+ """Tests that Play action plays all video elements with selector='all'."""
+ data = {'selector': 'all', 'wait_for_playing': True}
+ action = play.PlayAction(data)
+ action.WillRunAction(None, self._tab)
+ # Both videos not playing before running action.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_PLAYING_CHECK))
+ action.RunAction(None, self._tab, None)
+ # Assert all media elements played.
+ self.assertTrue(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertTrue(self._tab.EvaluateJavaScript(AUDIO_1_PLAYING_CHECK))
+
+ def testPlayWaitForPlayTimeout(self):
+ """Tests that wait_for_playing timeouts if video does not play."""
+ data = {'selector': '#video_1',
+ 'wait_for_playing': True,
+ 'wait_timeout': 1}
+ action = play.PlayAction(data)
+ action.WillRunAction(None, self._tab)
+ self._tab.EvaluateJavaScript('document.getElementById("video_1").src = ""')
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertRaises(util.TimeoutException, action.RunAction, None, self._tab,
+ None)
+
+ def testPlayWaitForEnded(self):
+ """Tests that wait_for_ended waits for video to end."""
+ data = {'selector': '#video_1', 'wait_for_ended': True}
+ action = play.PlayAction(data)
+ action.WillRunAction(None, self._tab)
+ # Assert video not playing before running action.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_ENDED_CHECK))
+ action.RunAction(None, self._tab, None)
+ # Assert video ended.
+ self.assertTrue(self._tab.EvaluateJavaScript(VIDEO_1_ENDED_CHECK))
+
+ def testPlayWithoutWaitForEnded(self):
+ """Tests that wait_for_ended waits for video to end."""
+ data = {'selector': '#video_1', 'wait_for_ended': False}
+ action = play.PlayAction(data)
+ action.WillRunAction(None, self._tab)
+ # Assert video not playing before running action.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_ENDED_CHECK))
+ action.RunAction(None, self._tab, None)
+ # Assert video did not end.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_ENDED_CHECK))
+
+ def testPlayWaitForEndedTimeout(self):
+ """Tests that action raises exception if timeout is reached."""
+ data = {'selector': '#video_1', 'wait_for_ended': True, 'wait_timeout': 1}
+ action = play.PlayAction(data)
+ action.WillRunAction(None, self._tab)
+ # Assert video not playing before running action.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_PLAYING_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_ENDED_CHECK))
+ self.assertRaises(util.TimeoutException, action.RunAction, None, self._tab,
+ None)
+ # Assert video did not end.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_ENDED_CHECK))
diff --git a/chromium/tools/telemetry/telemetry/page/actions/reload.py b/chromium/tools/telemetry/telemetry/page/actions/reload.py
new file mode 100644
index 00000000000..caa362e8bbb
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/reload.py
@@ -0,0 +1,14 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.page import page as page_module
+from telemetry.page.actions import page_action
+
+class ReloadAction(page_action.PageAction):
+ def __init__(self, attributes=None):
+ super(ReloadAction, self).__init__(attributes)
+
+ def RunAction(self, page, tab, previous_action):
+ tab.ExecuteJavaScript('window.location.reload()')
+ page_module.Page.WaitForPageToLoad(self, tab, 60)
+ tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
diff --git a/chromium/tools/telemetry/telemetry/page/actions/scroll.js b/chromium/tools/telemetry/telemetry/page/actions/scroll.js
new file mode 100644
index 00000000000..4d336f02575
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/scroll.js
@@ -0,0 +1,182 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file provides the ScrollAction object, which scrolls a page
+// from top to bottom:
+// 1. var action = new __ScrollAction(callback)
+// 2. action.start(scroll_options)
+'use strict';
+
+(function() {
+ var MAX_SCROLL_LENGTH_PIXELS = 5000;
+
+ var getTimeMs = (function() {
+ if (window.performance)
+ return (performance.now ||
+ performance.mozNow ||
+ performance.msNow ||
+ performance.oNow ||
+ performance.webkitNow).bind(window.performance);
+ else
+ return function() { return new Date().getTime(); };
+ })();
+
+ var requestAnimationFrame = (function() {
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback) {
+ window.setTimeout(callback, 1000 / 60);
+ };
+ })().bind(window);
+
+ function ScrollGestureOptions(opt_options) {
+ if (opt_options) {
+ this.element_ = opt_options.element;
+ this.left_start_percentage_ = opt_options.left_start_percentage;
+ this.top_start_percentage_ = opt_options.top_start_percentage;
+ } else {
+ this.element_ = document.body;
+ this.left_start_percentage_ = 0.5;
+ this.top_start_percentage_ = 0.5;
+ }
+ }
+
+ /**
+ * Scrolls a given element down a certain amount to emulate user scroll.
+ * Uses smooth scroll capabilities provided by the platform, if available.
+ * @constructor
+ */
+ function SmoothScrollDownGesture(options) {
+ this.options_ = options;
+ };
+
+ function min(a, b) {
+ if (a > b) {
+ return b;
+ }
+ return a;
+ };
+
+ function getBoundingVisibleRect(el) {
+ var bound = el.getBoundingClientRect();
+ var rect = { top: bound.top,
+ left: bound.left,
+ width: bound.width,
+ height: bound.height };
+ var outsideHeight = (rect.top + rect.height) - window.innerHeight;
+ var outsideWidth = (rect.left + rect.width) - window.innerWidth;
+
+ if (outsideHeight > 0) {
+ rect.height -= outsideHeight;
+ }
+ if (outsideWidth > 0) {
+ rect.width -= outsideWidth;
+ }
+ return rect;
+ };
+
+ SmoothScrollDownGesture.prototype.start = function(distance, callback) {
+ this.callback_ = callback;
+ if (window.chrome &&
+ chrome.gpuBenchmarking &&
+ chrome.gpuBenchmarking.smoothScrollBy) {
+ var rect = getBoundingVisibleRect(this.options_.element_);
+ var start_left =
+ rect.left + rect.width * this.options_.left_start_percentage_;
+ var start_top =
+ rect.top + rect.height * this.options_.top_start_percentage_;
+ chrome.gpuBenchmarking.smoothScrollBy(distance, function() {
+ callback();
+ }, start_left, start_top);
+ return;
+ }
+
+ var SCROLL_DELTA = 100;
+ this.options_.element_.scrollTop += SCROLL_DELTA;
+ requestAnimationFrame(callback);
+ };
+
+ // This class scrolls a page from the top to the bottom once.
+ //
+ // The page is scrolled down by a set of scroll gestures. These gestures
+ // correspond to a reading gesture on that platform.
+ //
+ // start -> startPass_ -> ...scroll... -> onGestureComplete_ ->
+ // -> startPass_ -> .. scroll... -> onGestureComplete_ -> callback_
+ function ScrollAction(opt_callback, opt_remaining_distance_func) {
+ var self = this;
+
+ this.beginMeasuringHook = function() {}
+ this.endMeasuringHook = function() {}
+
+ this.callback_ = opt_callback;
+ this.remaining_distance_func_ = opt_remaining_distance_func;
+ }
+
+ ScrollAction.prototype.getRemainingScrollDistance_ = function() {
+ if (this.remaining_distance_func_)
+ return this.remaining_distance_func_();
+
+ var clientHeight;
+ // clientHeight is "special" for the body element.
+ if (this.element_ == document.body)
+ clientHeight = window.innerHeight;
+ else
+ clientHeight = this.element_.clientHeight;
+
+ return this.scrollHeight_ - this.element_.scrollTop - clientHeight;
+ }
+
+ ScrollAction.prototype.start = function(opt_options) {
+ this.options_ = new ScrollGestureOptions(opt_options);
+ // Assign this.element_ here instead of constructor, because the constructor
+ // ensures this method will be called after the document is loaded.
+ this.element_ = this.options_.element_;
+ // Some pages load more content when you scroll to the bottom. Record
+ // the original element height here and only scroll to that point.
+ // -1 to allow for rounding errors on scaled viewports (like mobile).
+ this.scrollHeight_ = Math.min(MAX_SCROLL_LENGTH_PIXELS,
+ this.element_.scrollHeight - 1);
+ requestAnimationFrame(this.startPass_.bind(this));
+ };
+
+ ScrollAction.prototype.startPass_ = function() {
+ this.element_.scrollTop = 0;
+
+ this.beginMeasuringHook();
+
+ this.gesture_ = new SmoothScrollDownGesture(this.options_);
+ this.gesture_.start(this.getRemainingScrollDistance_(),
+ this.onGestureComplete_.bind(this));
+ };
+
+ ScrollAction.prototype.getResults = function() {
+ return this.renderingStats_;
+ }
+
+ ScrollAction.prototype.onGestureComplete_ = function() {
+ // If the scrollHeight went down, only scroll to the new scrollHeight.
+ // -1 to allow for rounding errors on scaled viewports (like mobile).
+ this.scrollHeight_ = Math.min(this.scrollHeight_,
+ this.element_.scrollHeight - 1);
+
+ if (this.getRemainingScrollDistance_() > 0) {
+ this.gesture_.start(this.getRemainingScrollDistance_(),
+ this.onGestureComplete_.bind(this));
+ return;
+ }
+
+ this.endMeasuringHook();
+
+ // We're done.
+ if (this.callback_)
+ this.callback_();
+ };
+
+ window.__ScrollAction = ScrollAction;
+ window.__ScrollAction_GetBoundingVisibleRect = getBoundingVisibleRect;
+})();
diff --git a/chromium/tools/telemetry/telemetry/page/actions/scroll.py b/chromium/tools/telemetry/telemetry/page/actions/scroll.py
new file mode 100644
index 00000000000..f7df4ad93e8
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/scroll.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.core import util
+from telemetry.page.actions import page_action
+
+class ScrollAction(page_action.PageAction):
+ def __init__(self, attributes=None):
+ super(ScrollAction, self).__init__(attributes)
+
+ def WillRunAction(self, page, tab):
+ with open(
+ os.path.join(os.path.dirname(__file__),
+ 'scroll.js')) as f:
+ js = f.read()
+ tab.ExecuteJavaScript(js)
+
+ # Fail if this action requires touch and we can't send touch events.
+ if (hasattr(self, 'scroll_requires_touch') and
+ self.scroll_requires_touch and not
+ tab.EvaluateJavaScript(
+ 'chrome.gpuBenchmarking.smoothScrollBySendsTouch()')):
+ raise page_action.PageActionNotSupported(
+ 'Touch scroll not supported for this browser')
+
+ distance_func = 'null'
+ if hasattr(self, 'remaining_scroll_distance_function'):
+ distance_func = self.remaining_scroll_distance_function
+
+ done_callback = 'function() { window.__scrollActionDone = true; }'
+ tab.ExecuteJavaScript("""
+ window.__scrollActionDone = false;
+ window.__scrollAction = new __ScrollAction(%s, %s);"""
+ % (done_callback, distance_func))
+
+ def RunAction(self, page, tab, previous_action):
+ # scrollable_element_function is a function that passes the scrollable
+ # element on the page to a callback. For example:
+ # function (callback) {
+ # callback(document.getElementById('foo'));
+ # }
+ left_start_percentage = 0.5
+ top_start_percentage = 0.5
+ if hasattr(self, 'left_start_percentage'):
+ left_start_percentage = self.left_start_percentage
+ if hasattr(self, 'top_start_percentage'):
+ top_start_percentage = self.top_start_percentage
+ if hasattr(self, 'scrollable_element_function'):
+ tab.ExecuteJavaScript("""
+ (%s)(function(element) { window.__scrollAction.start(
+ { element: element,
+ left_start_percentage: %s,
+ top_start_percentage: %s })
+ });""" % (self.scrollable_element_function,
+ left_start_percentage,
+ top_start_percentage))
+ else:
+ tab.ExecuteJavaScript("""
+ window.__scrollAction.start(
+ { element: document.body,
+ left_start_percentage: %s,
+ top_start_percentage: %s });"""
+ % (left_start_percentage, top_start_percentage))
+
+ # Poll for scroll action completion.
+ util.WaitFor(lambda: tab.EvaluateJavaScript(
+ 'window.__scrollActionDone'), 60)
+
+ def CanBeBound(self):
+ return True
+
+ def CustomizeBrowserOptions(self, options):
+ options.AppendExtraBrowserArg('--enable-gpu-benchmarking')
+
+ def BindMeasurementJavaScript(self, tab, start_js, stop_js):
+ # Make the scroll action start and stop measurement automatically.
+ tab.ExecuteJavaScript("""
+ window.__scrollAction.beginMeasuringHook = function() { %s };
+ window.__scrollAction.endMeasuringHook = function() { %s };
+ """ % (start_js, stop_js))
diff --git a/chromium/tools/telemetry/telemetry/page/actions/scroll_unittest.py b/chromium/tools/telemetry/telemetry/page/actions/scroll_unittest.py
new file mode 100644
index 00000000000..29b3da201b4
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/scroll_unittest.py
@@ -0,0 +1,98 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.page import page as page_module
+from telemetry.page.actions import scroll
+from telemetry.unittest import tab_test_case
+
+class ScrollActionTest(tab_test_case.TabTestCase):
+ def CreateAndNavigateToPageFromUnittestDataDir(
+ self, filename, page_attributes):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+ page = page_module.Page(
+ self._browser.http_server.UrlOf(filename),
+ None, # In this test, we don't need a page set.
+ attributes=page_attributes)
+
+ self._tab.Navigate(page.url)
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ return page
+
+ def testScrollAction(self):
+ page = self.CreateAndNavigateToPageFromUnittestDataDir(
+ "blank.html",
+ page_attributes={"smoothness": {
+ "action": "scroll"
+ }})
+ # Make page bigger than window so it's scrollable.
+ self._tab.ExecuteJavaScript("""document.body.style.height =
+ (2 * window.innerHeight + 1) + 'px';""")
+
+ self.assertEquals(
+ self._tab.EvaluateJavaScript('document.body.scrollTop'), 0)
+
+ i = scroll.ScrollAction()
+ i.WillRunAction(page, self._tab)
+
+ self._tab.ExecuteJavaScript("""
+ window.__scrollAction.beginMeasuringHook = function() {
+ window.__didBeginMeasuring = true;
+ };
+ window.__scrollAction.endMeasuringHook = function() {
+ window.__didEndMeasuring = true;
+ };""")
+ i.RunAction(page, self._tab, None)
+
+ self.assertTrue(self._tab.EvaluateJavaScript('window.__didBeginMeasuring'))
+ self.assertTrue(self._tab.EvaluateJavaScript('window.__didEndMeasuring'))
+
+ # Allow for roundoff error in scaled viewport.
+ scroll_position = self._tab.EvaluateJavaScript(
+ 'document.body.scrollTop + window.innerHeight')
+ scroll_height = self._tab.EvaluateJavaScript('document.body.scrollHeight')
+ difference = scroll_position - scroll_height
+ self.assertTrue(abs(difference) <= 1)
+
+ def testBoundingClientRect(self):
+ self.CreateAndNavigateToPageFromUnittestDataDir('blank.html', {})
+ with open(
+ os.path.join(os.path.dirname(__file__),
+ 'scroll.js')) as f:
+ js = f.read()
+ self._tab.ExecuteJavaScript(js)
+
+ # Verify that the rect returned by getBoundingVisibleRect() in scroll.js is
+ # completely contained within the viewport. Scroll events dispatched by the
+ # scrolling API use the center of this rect as their location, and this
+ # location needs to be within the viewport bounds to correctly decide
+ # between main-thread and impl-thread scroll. If the scrollable area were
+ # not clipped to the viewport bounds, then the instance used here (the
+ # scrollable area being more than twice as tall as the viewport) would
+ # result in a scroll location outside of the viewport bounds.
+ self._tab.ExecuteJavaScript("""document.body.style.height =
+ (2 * window.innerHeight + 1) + 'px';""")
+
+ rect_top = int(self._tab.EvaluateJavaScript(
+ '__ScrollAction_GetBoundingVisibleRect(document.body).top'))
+ rect_height = int(self._tab.EvaluateJavaScript(
+ '__ScrollAction_GetBoundingVisibleRect(document.body).height'))
+ rect_bottom = rect_top + rect_height
+
+ rect_left = int(self._tab.EvaluateJavaScript(
+ '__ScrollAction_GetBoundingVisibleRect(document.body).left'))
+ rect_width = int(self._tab.EvaluateJavaScript(
+ '__ScrollAction_GetBoundingVisibleRect(document.body).width'))
+ rect_right = rect_left + rect_width
+
+ viewport_height = int(self._tab.EvaluateJavaScript('window.innerHeight'))
+ viewport_width = int(self._tab.EvaluateJavaScript('window.innerWidth'))
+
+ self.assertTrue(rect_bottom <= viewport_height,
+ msg='%s + %s <= %s' % (rect_top, rect_height, viewport_height))
+ self.assertTrue(rect_right <= viewport_width,
+ msg='%s + %s <= %s' % (rect_left, rect_width, viewport_width))
diff --git a/chromium/tools/telemetry/telemetry/page/actions/seek.js b/chromium/tools/telemetry/telemetry/page/actions/seek.js
new file mode 100644
index 00000000000..1a06ed10e98
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/seek.js
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file performs actions on media elements.
+(function() {
+ function seekMedia(selector, seekTime, logSeekTime) {
+ // Performs the "Seek" action on media satisfying selector.
+ var mediaElements = window.__findMediaElements(selector);
+ for (var i = 0; i < mediaElements.length; i++) {
+ seek(mediaElements[i], seekTime, logSeekTime);
+ }
+ }
+
+ function seek(element, seekTime, logSeekTime) {
+ if (element instanceof HTMLMediaElement)
+ seekHTML5Element(element, seekTime, logSeekTime);
+ else
+ throw new Error('Can not seek non HTML5 media elements.');
+ }
+
+ function seekHTML5Element(element, seekTime, logSeekTime) {
+ if (element.readyState == element.HAVE_NOTHING) {
+ var onLoadedMetaData = function(e) {
+ element.removeEventListener('loadedmetadata', onLoadedMetaData);
+ seekHTML5ElementPostLoad(element, seekTime, logSeekTime);
+ };
+ element.addEventListener('loadedmetadata', onLoadedMetaData);
+ element.load();
+ } else {
+ seekHTML5ElementPostLoad(element, seekTime, logSeekTime);
+ }
+ }
+
+ function seekHTML5ElementPostLoad(element, seekTime, logSeekTime) {
+ var onSeeked = function(e) {
+ element[e.type + '_completed'] = true;
+ element.removeEventListener('seeked', onSeeked);
+ };
+ function onError(e) {
+ throw new Error('Error playing media :' + e.type);
+ }
+
+ element['seeked_completed'] = false;
+ element.addEventListener('error', onError);
+ element.addEventListener('abort', onError);
+ element.addEventListener('seeked', onSeeked);
+
+ if (logSeekTime) {
+ var willSeekEvent = document.createEvent('Event');
+ willSeekEvent.initEvent('willSeek', false, false);
+ willSeekEvent.seekLabel = seekTime;
+ element.dispatchEvent(willSeekEvent);
+ }
+ try {
+ element.currentTime = seekTime;
+ } catch (err) {
+ throw new Error('Cannot seek in network state: ' + element.networkState);
+ }
+ }
+
+ window.__seekMedia = seekMedia;
+})();
diff --git a/chromium/tools/telemetry/telemetry/page/actions/seek.py b/chromium/tools/telemetry/telemetry/page/actions/seek.py
new file mode 100644
index 00000000000..12f66141076
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/seek.py
@@ -0,0 +1,47 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A Telemetry page_action that performs the "seek" action on media elements.
+
+Action attributes are:
+- seek_time: The media time to seek to. Test fails if not provided.
+- selector: If no selector is defined then the action attempts to seek the first
+ media element on the page. If 'all' then seek all media elements.
+- log_seek_time: If true the seek time is recorded, otherwise media measurement
+ will not be aware of the seek action. Used to perform multiple
+ seeks. Default true.
+- wait_for_seeked: If true forces the action to wait for seeked event to fire.
+ Default false.
+- wait_timeout: Timeout to wait for seeked event. Only valid with
+ wait_for_seeked=true
+"""
+
+from telemetry.page.actions.media_action import MediaAction
+from telemetry.core import exceptions
+from telemetry.page.actions import page_action
+
+
+class SeekAction(MediaAction):
+ def __init__(self, attributes=None):
+ super(SeekAction, self).__init__(attributes)
+
+ def WillRunAction(self, page, tab):
+ """Load the media metrics JS code prior to running the action."""
+ super(SeekAction, self).WillRunAction(page, tab)
+ self.LoadJS(tab, 'seek.js')
+
+ def RunAction(self, page, tab, previous_action):
+ try:
+ assert hasattr(self, 'seek_time')
+ selector = self.selector if hasattr(self, 'selector') else ''
+ log_seek = self.log_seek == True if hasattr(self, 'log_seek') else True
+ tab.ExecuteJavaScript('window.__seekMedia("%s", "%s", %i);' %
+ (selector, self.seek_time, log_seek))
+ timeout = self.wait_timeout if hasattr(self, 'wait_timeout') else 60
+ # Check if we need to wait for 'seeked' event to fire.
+ if hasattr(self, 'wait_for_seeked') and self.wait_for_seeked:
+ self.WaitForEvent(tab, selector, 'seeked', timeout)
+ except exceptions.EvaluateException:
+ raise page_action.PageActionFailed('Cannot seek media element(s) with '
+ 'selector = %s.' % selector)
diff --git a/chromium/tools/telemetry/telemetry/page/actions/seek_unittest.py b/chromium/tools/telemetry/telemetry/page/actions/seek_unittest.py
new file mode 100644
index 00000000000..2f9d5a92caf
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/seek_unittest.py
@@ -0,0 +1,76 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core import util
+from telemetry.page.actions import seek
+from telemetry.unittest import tab_test_case
+
+AUDIO_1_SEEKED_CHECK = 'window.__hasEventCompleted("#audio_1", "seeked");'
+VIDEO_1_SEEKED_CHECK = 'window.__hasEventCompleted("#video_1", "seeked");'
+
+
+class SeekActionTest(tab_test_case.TabTestCase):
+
+ def setUp(self):
+ tab_test_case.TabTestCase.setUp(self)
+ self._browser.SetHTTPServerDirectories(util.GetUnittestDataDir())
+ self._tab.Navigate(self._browser.http_server.UrlOf('video_test.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+
+ def testSeekWithNoSelector(self):
+ """Tests that with no selector Seek action seeks first media element."""
+ data = {'wait_for_seeked': True, 'seek_time': 1}
+ action = seek.SeekAction(data)
+ action.WillRunAction(None, self._tab)
+ action.RunAction(None, self._tab, None)
+ # Assert only first video has played.
+ self.assertTrue(self._tab.EvaluateJavaScript(VIDEO_1_SEEKED_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_SEEKED_CHECK))
+
+ def testSeekWithVideoSelector(self):
+ """Tests that Seek action seeks video element matching selector."""
+ data = {'selector': '#video_1', 'wait_for_seeked': True, 'seek_time': 1}
+ action = seek.SeekAction(data)
+ action.WillRunAction(None, self._tab)
+ # Both videos not playing before running action.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_SEEKED_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_SEEKED_CHECK))
+ action.RunAction(None, self._tab, None)
+ # Assert only video matching selector has played.
+ self.assertTrue(self._tab.EvaluateJavaScript(VIDEO_1_SEEKED_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_SEEKED_CHECK))
+
+ def testSeekWithAllSelector(self):
+ """Tests that Seek action seeks all video elements with selector='all'."""
+ data = {'selector': 'all', 'wait_for_seeked': True, 'seek_time': 1}
+ action = seek.SeekAction(data)
+ action.WillRunAction(None, self._tab)
+ # Both videos not playing before running action.
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_SEEKED_CHECK))
+ self.assertFalse(self._tab.EvaluateJavaScript(AUDIO_1_SEEKED_CHECK))
+ action.RunAction(None, self._tab, None)
+ # Assert all media elements played.
+ self.assertTrue(self._tab.EvaluateJavaScript(VIDEO_1_SEEKED_CHECK))
+ self.assertTrue(self._tab.EvaluateJavaScript(AUDIO_1_SEEKED_CHECK))
+
+ def testSeekWaitForSeekTimeout(self):
+ """Tests that wait_for_seeked timeouts if video does not seek."""
+ data = {'selector': '#video_1',
+ 'wait_for_seeked': True,
+ 'wait_timeout': 1,
+ 'seek_time': 1}
+ action = seek.SeekAction(data)
+ action.WillRunAction(None, self._tab)
+ self._tab.EvaluateJavaScript('document.getElementById("video_1").src = ""')
+ self.assertFalse(self._tab.EvaluateJavaScript(VIDEO_1_SEEKED_CHECK))
+ self.assertRaises(util.TimeoutException, action.RunAction, None, self._tab,
+ None)
+
+ def testSeekWithoutSeekTime(self):
+ """Tests that seek action fails with no seek time."""
+ data = {'wait_for_seeked': True}
+ action = seek.SeekAction(data)
+ action.WillRunAction(None, self._tab)
+ self.assertRaises(AssertionError, action.RunAction, None, self._tab,
+ None)
diff --git a/chromium/tools/telemetry/telemetry/page/actions/tap_element.py b/chromium/tools/telemetry/telemetry/page/actions/tap_element.py
new file mode 100644
index 00000000000..f3a4734a20e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/tap_element.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core import exceptions
+from telemetry.core import util
+from telemetry.page import page as page_module
+from telemetry.page.actions import page_action
+
+class TapElementAction(page_action.PageAction):
+ """Page action that dispatches a custom 'tap' event at an element.
+
+ For pages that don't respond to 'click' events, this action offers
+ an alternative to ClickElementAction.
+
+ Configuration options:
+ find_element_expression: a JavaScript expression that should yield
+ the element to tap.
+ wait_for_event: an event name that will be listened for on the Document.
+ """
+ def __init__(self, attributes=None):
+ super(TapElementAction, self).__init__(attributes)
+
+ def RunAction(self, page, tab, previous_action):
+ def DoTap():
+ assert hasattr(self, 'find_element_expression')
+ event = 'new CustomEvent("tap", {bubbles: true})'
+ code = '(%s).dispatchEvent(%s)' % (self.find_element_expression, event)
+ try:
+ tab.ExecuteJavaScript(code)
+ except exceptions.EvaluateException:
+ raise page_action.PageActionFailed(
+ 'Cannot find element with code ' + self.find_element_javascript)
+
+ if hasattr(self, 'wait_for_event'):
+ code = ('document.addEventListener("%s", '
+ 'function(){window.__tap_event_finished=true})')
+ tab.ExecuteJavaScript(code % self.wait_for_event)
+ DoTap()
+ util.WaitFor(lambda: tab.EvaluateJavaScript(
+ 'window.__tap_event_finished'), 60)
+ else:
+ DoTap()
+
+ page_module.Page.WaitForPageToLoad(self, tab, 60)
diff --git a/chromium/tools/telemetry/telemetry/page/actions/wait.py b/chromium/tools/telemetry/telemetry/page/actions/wait.py
new file mode 100644
index 00000000000..39f061ae149
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/wait.py
@@ -0,0 +1,61 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import time
+
+from telemetry.core import util
+from telemetry.page.actions import page_action
+
+class WaitAction(page_action.PageAction):
+ DEFAULT_TIMEOUT = 60
+
+ def __init__(self, attributes=None):
+ super(WaitAction, self).__init__(attributes)
+
+ def RunsPreviousAction(self):
+ assert hasattr(self, 'condition')
+ return self.condition == 'navigate' or self.condition == 'href_change'
+
+ def RunAction(self, page, tab, previous_action):
+ assert hasattr(self, 'condition')
+
+ if self.condition == 'duration':
+ assert hasattr(self, 'seconds')
+ time.sleep(self.seconds)
+
+ elif self.condition == 'navigate':
+ if not previous_action:
+ raise page_action.PageActionFailed('You need to perform an action '
+ 'before waiting for navigate.')
+ previous_action.WillRunAction()
+ action_to_perform = lambda: previous_action.RunAction(page, tab, None)
+ tab.PerformActionAndWaitForNavigate(action_to_perform)
+
+ elif self.condition == 'href_change':
+ if not previous_action:
+ raise page_action.PageActionFailed('You need to perform an action '
+ 'before waiting for a href change.')
+ previous_action.WillRunAction()
+ old_url = tab.EvaluateJavaScript('document.location.href')
+ previous_action.RunAction(page, tab, None)
+ util.WaitFor(lambda: tab.EvaluateJavaScript(
+ 'document.location.href') != old_url, self.DEFAULT_TIMEOUT)
+
+ elif self.condition == 'element':
+ assert hasattr(self, 'text') or hasattr(self, 'selector')
+ if hasattr(self, 'text'):
+ callback_code = 'function(element) { return element != null; }'
+ util.WaitFor(
+ lambda: util.FindElementAndPerformAction(
+ tab, self.text, callback_code), self.DEFAULT_TIMEOUT)
+ else:
+ util.WaitFor(lambda: tab.EvaluateJavaScript(
+ 'document.querySelector("%s") != null' % re.escape(self.selector)),
+ self.DEFAULT_TIMEOUT)
+
+ elif self.condition == 'javascript':
+ assert hasattr(self, 'javascript')
+ util.WaitFor(lambda: tab.EvaluateJavaScript(self.javascript),
+ self.DEFAULT_TIMEOUT)
diff --git a/chromium/tools/telemetry/telemetry/page/actions/wait_unittest.py b/chromium/tools/telemetry/telemetry/page/actions/wait_unittest.py
new file mode 100644
index 00000000000..589870bee0e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/actions/wait_unittest.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import time
+
+from telemetry.page.actions import wait
+from telemetry.unittest import tab_test_case
+
+class WaitActionTest(tab_test_case.TabTestCase):
+ def testWaitAction(self):
+ unittest_data_dir = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', 'unittest_data')
+ self._browser.SetHTTPServerDirectories(unittest_data_dir)
+ self._tab.Navigate(
+ self._browser.http_server.UrlOf('blank.html'))
+ self._tab.WaitForDocumentReadyStateToBeComplete()
+ self.assertEquals(
+ self._tab.EvaluateJavaScript('document.location.pathname;'),
+ '/blank.html')
+
+ i = wait.WaitAction({ 'condition': 'duration', 'seconds': 1 })
+
+ start_time = time.time()
+ i.RunAction(None, self._tab, None)
+ self.assertAlmostEqual(time.time() - start_time, 1, places=1)
diff --git a/chromium/tools/telemetry/telemetry/page/block_page_measurement_results.py b/chromium/tools/telemetry/telemetry/page/block_page_measurement_results.py
new file mode 100644
index 00000000000..625c5c8ad7e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/block_page_measurement_results.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+
+from telemetry.page import page_measurement_results
+
+class BlockPageMeasurementResults(
+ page_measurement_results.PageMeasurementResults):
+ def __init__(self, output_file):
+ super(BlockPageMeasurementResults, self).__init__()
+ self._output_file = output_file
+
+ def DidMeasurePage(self):
+ page_values = self.values_for_current_page
+
+ lines = ['url: %s' %
+ self.values_for_current_page.page.url]
+ sorted_measurement_names = page_values.measurement_names
+ sorted_measurement_names.sort()
+
+ for measurement_name in sorted_measurement_names:
+ value = page_values.FindValueByMeasurementName(measurement_name)
+ lines.append('%s (%s): %s' %
+ (measurement_name,
+ value.units,
+ value.output_value))
+ for line in lines:
+ self._output_file.write(line)
+ self._output_file.write(os.linesep)
+ self._output_file.write(os.linesep)
+
+ super(BlockPageMeasurementResults, self).DidMeasurePage()
diff --git a/chromium/tools/telemetry/telemetry/page/block_page_measurement_results_unittest.py b/chromium/tools/telemetry/telemetry/page/block_page_measurement_results_unittest.py
new file mode 100644
index 00000000000..21af60eaf5d
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/block_page_measurement_results_unittest.py
@@ -0,0 +1,63 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import StringIO
+import os
+import unittest
+
+from telemetry.page import block_page_measurement_results
+from telemetry.page import page_set
+
+BlockPageMeasurementResults = \
+ block_page_measurement_results.BlockPageMeasurementResults
+
+def _MakePageSet():
+ return page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "http://www.foo.com/"},
+ {"url": "http://www.bar.com/"}
+ ]
+ }, os.path.dirname(__file__))
+
+class NonPrintingBlockPageMeasurementResults(BlockPageMeasurementResults):
+ def __init__(self, *args):
+ super(NonPrintingBlockPageMeasurementResults, self).__init__(*args)
+
+ def _PrintPerfResult(self, *args):
+ pass
+
+class BlockPageMeasurementResultsTest(unittest.TestCase):
+ def setUp(self):
+ self._output = StringIO.StringIO()
+ self._page_set = _MakePageSet()
+
+ @property
+ def lines(self):
+ lines = StringIO.StringIO(self._output.getvalue()).readlines()
+ return [line.strip() for line in lines]
+
+ @property
+ def data(self):
+ return [line.split(': ', 1) for line in self.lines]
+
+ def test_with_output_after_every_page(self):
+ results = NonPrintingBlockPageMeasurementResults(self._output)
+ results.WillMeasurePage(self._page_set[0])
+ results.Add('foo', 'seconds', 3)
+ results.DidMeasurePage()
+
+ results.WillMeasurePage(self._page_set[1])
+ results.Add('bar', 'seconds', 4)
+ results.DidMeasurePage()
+
+ expected = [
+ ['url', 'http://www.foo.com/'],
+ ['foo (seconds)', '3'],
+ [''],
+ ['url', 'http://www.bar.com/'],
+ ['bar (seconds)', '4'],
+ ['']
+ ]
+ self.assertEquals(self.data, expected)
diff --git a/chromium/tools/telemetry/telemetry/page/buildbot_page_measurement_results.py b/chromium/tools/telemetry/telemetry/page/buildbot_page_measurement_results.py
new file mode 100644
index 00000000000..20b7da9af57
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/buildbot_page_measurement_results.py
@@ -0,0 +1,119 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from collections import defaultdict
+from itertools import chain
+
+from telemetry.page import page_measurement_results
+from telemetry.page import perf_tests_helper
+
+class BuildbotPageMeasurementResults(
+ page_measurement_results.PageMeasurementResults):
+ def __init__(self, trace_tag=''):
+ super(BuildbotPageMeasurementResults, self).__init__()
+ self._trace_tag = trace_tag
+
+ def _PrintPerfResult(self, measurement, trace, values, units,
+ result_type='default'):
+ perf_tests_helper.PrintPerfResult(
+ measurement, trace, values, units, result_type)
+
+ def PrintSummary(self):
+ """Print summary data in a format expected by buildbot for perf dashboards.
+
+ If any failed pages exist, only output individual page results for
+ non-failing pages, and do not output any average data.
+ """
+ if self.errors or self.failures:
+ success_page_results = [r for r in self._page_results
+ if r.page.url not in
+ zip(*self.errors + self.failures)[0]]
+ else:
+ success_page_results = self._page_results
+
+ # Print out the list of unique pages.
+ # Use a set and a list to efficiently create an order preserving list of
+ # unique URLs.
+ unique_page_urls = []
+ unique_page_urls_set = set()
+ for page_values in success_page_results:
+ url = page_values.page.display_url
+ if url in unique_page_urls_set:
+ continue
+ unique_page_urls.append(url)
+ unique_page_urls_set.add(url)
+ perf_tests_helper.PrintPages(unique_page_urls)
+
+ # Build the results summary.
+ results_summary = defaultdict(list)
+ for measurement_name in \
+ self._all_measurements_that_have_been_seen.iterkeys():
+ for page_values in success_page_results:
+ value = page_values.FindValueByMeasurementName(measurement_name)
+ if not value:
+ continue
+ measurement_units_type = (measurement_name,
+ value.units,
+ value.data_type)
+ value_url = (value.value, page_values.page.display_url)
+ results_summary[measurement_units_type].append(value_url)
+
+ # Output the results summary sorted by name, then units, then data type.
+ for measurement_units_type, value_url_list in sorted(
+ results_summary.iteritems()):
+ measurement, units, data_type = measurement_units_type
+
+ if 'histogram' in data_type:
+ by_url_data_type = 'unimportant-histogram'
+ else:
+ by_url_data_type = 'unimportant'
+ if '.' in measurement and 'histogram' not in data_type:
+ measurement, trace = measurement.split('.', 1)
+ trace += self._trace_tag
+ else:
+ trace = measurement + self._trace_tag
+
+ # Print individual _by_url results if there's more than 1 successful page,
+ # or if there's exactly 1 successful page but a failure exists.
+ if not self._trace_tag and (len(value_url_list) > 1 or
+ ((self.errors or self.failures) and len(value_url_list) == 1)):
+ url_value_map = defaultdict(list)
+ for value, url in value_url_list:
+ if 'histogram' in data_type and url_value_map[url]:
+ # TODO(tonyg/marja): The histogram processing code only accepts one
+ # histogram, so we only report the first histogram. Once histograms
+ # support aggregating multiple values, this can be removed.
+ continue
+ url_value_map[url].append(value)
+ for url in unique_page_urls:
+ if not len(url_value_map[url]):
+ continue
+ self._PrintPerfResult(measurement + '_by_url', url,
+ url_value_map[url], units, by_url_data_type)
+
+ # If there were no page failures, print the average data.
+ # For histograms, we don't print the average data, only the _by_url,
+ # unless there is only 1 page in which case the _by_urls are omitted.
+ if not (self.errors or self.failures):
+ if 'histogram' not in data_type or len(value_url_list) == 1:
+ values = [i[0] for i in value_url_list]
+ if isinstance(values[0], list):
+ values = list(chain.from_iterable(values))
+ self._PrintPerfResult(measurement, trace, values, units, data_type)
+
+ # If there were no failed pages, output the overall results (results not
+ # associated with a page).
+ if not (self.errors or self.failures):
+ for value in self._overall_results:
+ values = value.value
+ if not isinstance(values, list):
+ values = [values]
+ measurement_name = value.chart_name
+ if not measurement_name:
+ measurement_name = value.trace_name
+ self._PrintPerfResult(measurement_name,
+ value.trace_name + self._trace_tag,
+ values, value.units, value.data_type)
+
+ super(BuildbotPageMeasurementResults, self).PrintSummary()
diff --git a/chromium/tools/telemetry/telemetry/page/buildbot_page_measurement_results_unittest.py b/chromium/tools/telemetry/telemetry/page/buildbot_page_measurement_results_unittest.py
new file mode 100644
index 00000000000..04505aab980
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/buildbot_page_measurement_results_unittest.py
@@ -0,0 +1,270 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from telemetry.page import buildbot_page_measurement_results
+from telemetry.page import page_set
+from telemetry.page import perf_tests_helper
+
+def _MakePageSet():
+ return page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "http://www.foo.com/"},
+ {"url": "http://www.bar.com/"},
+ {"url": "http://www.baz.com/"}
+ ]
+ }, os.path.dirname(__file__))
+
+class SummarySavingPageMeasurementResults(
+ buildbot_page_measurement_results.BuildbotPageMeasurementResults):
+ def __init__(self, trace_tag=''):
+ super(SummarySavingPageMeasurementResults, self).__init__(trace_tag)
+ self.results = []
+
+ def _PrintPerfResult(self, *args):
+ res = perf_tests_helper.PrintPerfResult(*args, print_to_stdout=False)
+ self.results.append(res)
+
+class BuildbotPageMeasurementResultsTest(unittest.TestCase):
+ def test_basic_summary(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 7)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.PrintSummary()
+ expected = ['RESULT a_by_url: http___www.foo.com_= 3 seconds',
+ 'RESULT a_by_url: http___www.bar.com_= 7 seconds',
+ '*RESULT a: a= [3,7] seconds\nAvg a: 5.000000seconds\n' +
+ 'Sd a: 2.828427seconds']
+ self.assertEquals(measurement_results.results, expected)
+
+ def test_basic_summary_nonuniform_results(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.Add('b', 'seconds', 10)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.Add('b', 'seconds', 10)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[2])
+ measurement_results.Add('a', 'seconds', 7)
+ # Note, page[2] does not report a 'b' metric.
+ measurement_results.DidMeasurePage()
+
+ measurement_results.PrintSummary()
+ expected = ['RESULT a_by_url: http___www.foo.com_= 3 seconds',
+ 'RESULT a_by_url: http___www.bar.com_= 3 seconds',
+ 'RESULT a_by_url: http___www.baz.com_= 7 seconds',
+ '*RESULT a: a= [3,3,7] seconds\nAvg a: 4.333333seconds\n' +
+ 'Sd a: 2.309401seconds',
+ 'RESULT b_by_url: http___www.foo.com_= 10 seconds',
+ 'RESULT b_by_url: http___www.bar.com_= 10 seconds',
+ '*RESULT b: b= [10,10] seconds\nAvg b: 10.000000seconds']
+ self.assertEquals(measurement_results.results, expected)
+
+ def test_basic_summary_pass_and_fail_page(self):
+ """If a page failed, only print summary for individual passing pages."""
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+ measurement_results.AddFailureMessage(test_page_set.pages[0], 'message')
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 7)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.PrintSummary()
+ expected = ['RESULT a_by_url: http___www.bar.com_= 7 seconds']
+ self.assertEquals(measurement_results.results, expected)
+
+ def test_repeated_pageset_one_iteration_one_page_fails(self):
+ """Page fails on one iteration, no results for that page should print."""
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 7)
+ measurement_results.DidMeasurePage()
+ measurement_results.AddFailureMessage(test_page_set.pages[1], 'message')
+
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 4)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 8)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.PrintSummary()
+ expected = ['RESULT a_by_url: http___www.foo.com_= [3,4] seconds\n' +
+ 'Avg a_by_url: 3.500000seconds\nSd a_by_url: 0.707107seconds']
+ self.assertEquals(measurement_results.results, expected)
+
+ def test_repeated_pageset(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 7)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 4)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 8)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.PrintSummary()
+ expected = ['RESULT a_by_url: http___www.foo.com_= [3,4] seconds\n' +
+ 'Avg a_by_url: 3.500000seconds\nSd a_by_url: 0.707107seconds',
+ 'RESULT a_by_url: http___www.bar.com_= [7,8] seconds\n' +
+ 'Avg a_by_url: 7.500000seconds\nSd a_by_url: 0.707107seconds',
+ '*RESULT a: a= [3,7,4,8] seconds\n' +
+ 'Avg a: 5.500000seconds\nSd a: 2.380476seconds'
+ ]
+ self.assertEquals(
+ measurement_results.results,
+ expected)
+
+ def test_repeated_pages(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 4)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 7)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 8)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.PrintSummary()
+ expected = ['RESULT a_by_url: http___www.foo.com_= [3,4] seconds\n' +
+ 'Avg a_by_url: 3.500000seconds\nSd a_by_url: 0.707107seconds',
+ 'RESULT a_by_url: http___www.bar.com_= [7,8] seconds\n' +
+ 'Avg a_by_url: 7.500000seconds\nSd a_by_url: 0.707107seconds',
+ '*RESULT a: a= [3,4,7,8] seconds\n' +
+ 'Avg a: 5.500000seconds\nSd a: 2.380476seconds'
+ ]
+ self.assertEquals(
+ measurement_results.results,
+ expected)
+
+ def test_overall_results(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+
+ measurement_results.AddSummary('a', 'seconds', 1)
+
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('b', 'seconds', 2)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('b', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.AddSummary('c', 'seconds', 4)
+
+ measurement_results.PrintSummary()
+
+ self.assertEquals(
+ measurement_results.results,
+ ['RESULT b_by_url: http___www.foo.com_= 2 seconds',
+ 'RESULT b_by_url: http___www.bar.com_= 3 seconds',
+ '*RESULT b: b= [2,3] seconds\n' +
+ 'Avg b: 2.500000seconds\nSd b: 0.707107seconds',
+ '*RESULT a: a= 1 seconds',
+ '*RESULT c: c= 4 seconds'])
+
+ def test_overall_results_trace_tag(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults(trace_tag='_ref')
+
+ measurement_results.AddSummary('a', 'seconds', 1)
+
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('b', 'seconds', 2)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('b', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.AddSummary('c', 'seconds', 4)
+
+ measurement_results.PrintSummary()
+
+ self.assertEquals(
+ measurement_results.results,
+ ['*RESULT b: b_ref= [2,3] seconds\n' +
+ 'Avg b: 2.500000seconds\nSd b: 0.707107seconds',
+ '*RESULT a: a_ref= 1 seconds',
+ '*RESULT c: c_ref= 4 seconds'])
+
+ def test_histogram(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', '',
+ '{"buckets": [{"low": 1, "high": 2, "count": 1}]}',
+ data_type='histogram')
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', '',
+ '{"buckets": [{"low": 2, "high": 3, "count": 1}]}',
+ data_type='histogram')
+ measurement_results.DidMeasurePage()
+
+ measurement_results.PrintSummary()
+
+ expected = [
+ 'HISTOGRAM a_by_url: http___www.foo.com_= ' +
+ '{"buckets": [{"low": 1, "high": 2, "count": 1}]}\n' +
+ 'Avg a_by_url: 1.500000',
+ 'HISTOGRAM a_by_url: http___www.bar.com_= ' +
+ '{"buckets": [{"low": 2, "high": 3, "count": 1}]}\n' +
+ 'Avg a_by_url: 2.500000']
+ self.assertEquals(measurement_results.results, expected)
diff --git a/chromium/tools/telemetry/telemetry/page/cloud_storage.py b/chromium/tools/telemetry/telemetry/page/cloud_storage.py
new file mode 100644
index 00000000000..5d537c822ac
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/cloud_storage.py
@@ -0,0 +1,128 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Wrappers for gsutil, for basic interaction with Google Cloud Storage."""
+
+import cStringIO
+import hashlib
+import logging
+import os
+import subprocess
+import sys
+import tarfile
+import urllib2
+
+from telemetry.core import util
+
+
+DEFAULT_BUCKET = 'chromium-wpr'
+
+
+_GSUTIL_URL = 'http://storage.googleapis.com/pub/gsutil.tar.gz'
+_DOWNLOAD_PATH = os.path.join(util.GetTelemetryDir(), 'third_party', 'gsutil')
+
+
+class CloudStorageError(Exception):
+ pass
+
+
+class CredentialsError(CloudStorageError):
+ def __init__(self, gsutil_path):
+ super(CredentialsError, self).__init__(
+ 'Attempted to download a file from Cloud Storage but you have no '
+ 'configured credentials. Run "%s config" to configure your '
+ 'credentials. The project-id field can be left blank.' % gsutil_path)
+
+
+def _DownloadGsutil():
+ logging.info('Downloading gsutil')
+ response = urllib2.urlopen(_GSUTIL_URL)
+ with tarfile.open(fileobj=cStringIO.StringIO(response.read())) as tar_file:
+ tar_file.extractall(os.path.dirname(_DOWNLOAD_PATH))
+ logging.info('Downloaded gsutil to %s' % _DOWNLOAD_PATH)
+
+ return os.path.join(_DOWNLOAD_PATH, 'gsutil')
+
+
+def _FindGsutil():
+ """Return the gsutil executable path. If we can't find it, download it."""
+ search_paths = [_DOWNLOAD_PATH] + os.environ['PATH'].split(os.pathsep)
+
+ # Look for a depot_tools installation.
+ for path in search_paths:
+ gsutil_path = os.path.join(path, 'third_party', 'gsutil', 'gsutil')
+ if os.path.isfile(gsutil_path):
+ return gsutil_path
+
+ # Look for a gsutil installation.
+ for path in search_paths:
+ gsutil_path = os.path.join(path, 'gsutil')
+ if os.path.isfile(gsutil_path):
+ return gsutil_path
+
+ # Failed to find it. Download it!
+ return _DownloadGsutil()
+
+
+def _RunCommand(args):
+ gsutil_path = _FindGsutil()
+ gsutil = subprocess.Popen([sys.executable, gsutil_path] + args,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = gsutil.communicate()
+
+ if gsutil.returncode:
+ if ('You are attempting to access protected data with '
+ 'no configured credentials.' in stderr):
+ raise CredentialsError(gsutil_path)
+ raise CloudStorageError(stderr)
+
+ return stdout
+
+
+def List(bucket):
+ stdout = _RunCommand(['ls', 'gs://%s' % bucket])
+ return [url.split('/')[-1] for url in stdout.splitlines()]
+
+
+def Delete(bucket, remote_path):
+ url = 'gs://%s/%s' % (bucket, remote_path)
+ logging.info('Deleting %s' % url)
+ _RunCommand(['rm', url])
+
+
+def Get(bucket, remote_path, local_path):
+ url = 'gs://%s/%s' % (bucket, remote_path)
+ logging.info('Downloading %s to %s' % (url, local_path))
+ _RunCommand(['cp', url, local_path])
+
+
+def Insert(bucket, remote_path, local_path):
+ url = 'gs://%s/%s' % (bucket, remote_path)
+ logging.info('Uploading %s to %s' % (local_path, url))
+ _RunCommand(['cp', local_path, url])
+
+
+def GetIfChanged(bucket, file_path):
+ """Gets the file at file_path if it has a hash file that doesn't match."""
+ hash_path = file_path + '.sha1'
+ if not os.path.exists(hash_path):
+ return
+
+ with open(hash_path, 'rb') as f:
+ expected_hash = f.read(1024).rstrip()
+ if not os.path.exists(file_path) or GetHash(file_path) != expected_hash:
+ Get(bucket, expected_hash, file_path)
+
+
+def GetHash(file_path):
+ """Calculates and returns the hash of the file at file_path."""
+ sha1 = hashlib.sha1()
+ with open(file_path, 'rb') as f:
+ while True:
+ # Read in 1mb chunks, so it doesn't all have to be loaded into memory.
+ chunk = f.read(1024*1024)
+ if not chunk:
+ break
+ sha1.update(chunk)
+ return sha1.hexdigest()
diff --git a/chromium/tools/telemetry/telemetry/page/csv_page_measurement_results.py b/chromium/tools/telemetry/telemetry/page/csv_page_measurement_results.py
new file mode 100644
index 00000000000..2440dd86e73
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/csv_page_measurement_results.py
@@ -0,0 +1,85 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import csv
+
+from telemetry.page import page_measurement_results
+
+class CsvPageMeasurementResults(
+ page_measurement_results.PageMeasurementResults):
+ def __init__(self, output_stream=None, output_after_every_page=None):
+ super(CsvPageMeasurementResults, self).__init__()
+ if output_stream:
+ self._results_writer = csv.writer(output_stream)
+ self._did_output_header = False
+ self._header_names_written_to_writer = None
+ self._output_after_every_page = output_after_every_page
+
+ def DidMeasurePage(self):
+ assert self.values_for_current_page, 'Failed to call WillMeasurePage'
+ if not self._output_after_every_page:
+ super(CsvPageMeasurementResults, self).DidMeasurePage()
+ return
+
+ if not self._did_output_header:
+ self._OutputHeader()
+ else:
+ self._ValidateOutputNamesForCurrentPage()
+
+ self._OutputValuesForPage(self.values_for_current_page)
+
+ super(CsvPageMeasurementResults, self).DidMeasurePage()
+
+ def PrintSummary(self):
+ if not self._output_after_every_page:
+ self._OutputHeader()
+ for page_values in self.page_results:
+ self._OutputValuesForPage(page_values)
+
+ super(CsvPageMeasurementResults, self).PrintSummary()
+
+ def _ValidateOutputNamesForCurrentPage(self):
+ assert self._did_output_header
+ current_page_measurement_names = \
+ set(self.values_for_current_page.measurement_names)
+ header_names_written_to_writer = \
+ set(self._header_names_written_to_writer)
+ if header_names_written_to_writer == current_page_measurement_names:
+ return
+ assert False, """To use CsvPageMeasurementResults, you must add the same
+result names for every page. In this case, first page output:
+%s
+
+Thus, all subsequent pages must output this as well. Instead, the current page
+output:
+%s
+
+Change your test to produce the same thing each time, or modify
+PageMeasurement.results_are_the_same_on_every_page to return False.
+""" % (repr(header_names_written_to_writer),
+ repr(current_page_measurement_names))
+
+ def _OutputHeader(self):
+ assert not self._did_output_header
+ all_measurement_names = list(
+ self.all_measurements_that_have_been_seen.keys())
+ all_measurement_names.sort()
+ self._did_output_header = True
+ self._header_names_written_to_writer = list(all_measurement_names)
+
+ row = ['url']
+ for measurement_name in all_measurement_names:
+ measurement_data = \
+ self.all_measurements_that_have_been_seen[measurement_name]
+ row.append('%s (%s)' % (measurement_name, measurement_data['units']))
+ self._results_writer.writerow(row)
+
+ def _OutputValuesForPage(self, page_values):
+ row = [page_values.page.display_url]
+ for measurement_name in self._header_names_written_to_writer:
+ value = page_values.FindValueByMeasurementName(measurement_name)
+ if value:
+ row.append('%s' % value.output_value)
+ else:
+ row.append('-')
+ self._results_writer.writerow(row)
diff --git a/chromium/tools/telemetry/telemetry/page/csv_page_measurement_results_unittest.py b/chromium/tools/telemetry/telemetry/page/csv_page_measurement_results_unittest.py
new file mode 100644
index 00000000000..b9e096f6cf9
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/csv_page_measurement_results_unittest.py
@@ -0,0 +1,127 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import StringIO
+import csv
+import os
+import unittest
+
+from telemetry.page import csv_page_measurement_results
+from telemetry.page import page_set
+
+def _MakePageSet():
+ return page_set.PageSet.FromDict({
+ "description": "hello",
+ "pages": [
+ {"url": "http://www.foo.com/"},
+ {"url": "http://www.bar.com/"}
+ ]
+ }, os.path.dirname(__file__))
+
+class NonPrintingCsvPageMeasurementResults(
+ csv_page_measurement_results.CsvPageMeasurementResults):
+ def __init__(self, *args):
+ super(NonPrintingCsvPageMeasurementResults, self).__init__(*args)
+
+ def _PrintPerfResult(self, *args):
+ pass
+
+class CsvPageMeasurementResultsTest(unittest.TestCase):
+ def setUp(self):
+ self._output = StringIO.StringIO()
+ self._page_set = _MakePageSet()
+
+ @property
+ def lines(self):
+ lines = StringIO.StringIO(self._output.getvalue()).readlines()
+ return lines
+
+ @property
+ def output_header_row(self):
+ rows = list(csv.reader(self.lines))
+ return rows[0]
+
+ @property
+ def output_data_rows(self):
+ rows = list(csv.reader(self.lines))
+ return rows[1:]
+
+ def test_with_output_after_every_page(self):
+ results = NonPrintingCsvPageMeasurementResults(self._output, True)
+ results.WillMeasurePage(self._page_set[0])
+ results.Add('foo', 'seconds', 3)
+ results.DidMeasurePage()
+ self.assertEquals(
+ self.output_header_row,
+ ['url', 'foo (seconds)'])
+ self.assertEquals(
+ self.output_data_rows[0],
+ [self._page_set[0].url, '3'])
+
+ results.WillMeasurePage(self._page_set[1])
+ results.Add('foo', 'seconds', 4)
+ results.DidMeasurePage()
+ self.assertEquals(
+ len(self.output_data_rows),
+ 2)
+ self.assertEquals(
+ self.output_data_rows[1],
+ [self._page_set[1].url, '4'])
+
+ def test_with_output_after_every_page_and_inconsistency(self):
+ results = NonPrintingCsvPageMeasurementResults(self._output, True)
+ results.WillMeasurePage(self._page_set[0])
+ results.Add('foo', 'seconds', 3)
+ results.DidMeasurePage()
+
+ # We printed foo, now change to bar
+ results.WillMeasurePage(self._page_set[1])
+ results.Add('bar', 'seconds', 4)
+
+ self.assertRaises(
+ Exception,
+ lambda: results.DidMeasurePage()) # pylint: disable=W0108
+
+ def test_with_output_at_print_summary_time(self):
+ results = NonPrintingCsvPageMeasurementResults(self._output, False)
+ results.WillMeasurePage(self._page_set[0])
+ results.Add('foo', 'seconds', 3)
+ results.DidMeasurePage()
+
+ results.WillMeasurePage(self._page_set[1])
+ results.Add('bar', 'seconds', 4)
+ results.DidMeasurePage()
+
+ results.PrintSummary()
+
+ self.assertEquals(
+ self.output_header_row,
+ ['url', 'bar (seconds)', 'foo (seconds)'])
+ self.assertEquals(
+ self.output_data_rows,
+ [[self._page_set[0].url, '-', '3'],
+ [self._page_set[1].url, '4', '-']])
+
+ def test_histogram(self):
+ results = NonPrintingCsvPageMeasurementResults(self._output, False)
+ results.WillMeasurePage(self._page_set[0])
+ results.Add('a', '',
+ '{"buckets": [{"low": 1, "high": 2, "count": 1}]}',
+ data_type='histogram')
+ results.DidMeasurePage()
+
+ results.WillMeasurePage(self._page_set[1])
+ results.Add('a', '',
+ '{"buckets": [{"low": 2, "high": 3, "count": 1}]}',
+ data_type='histogram')
+ results.DidMeasurePage()
+
+ results.PrintSummary()
+
+ self.assertEquals(
+ self.output_header_row,
+ ['url', 'a ()'])
+ self.assertEquals(
+ self.output_data_rows,
+ [[self._page_set[0].url, '1.5'],
+ [self._page_set[1].url, '2.5']])
diff --git a/chromium/tools/telemetry/telemetry/page/gtest_test_results.py b/chromium/tools/telemetry/telemetry/page/gtest_test_results.py
new file mode 100644
index 00000000000..31e85f9c686
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/gtest_test_results.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import time
+import unittest
+
+from telemetry.page import page_test_results
+
+class GTestTestResults(page_test_results.PageTestResults):
+ def __init__(self):
+ super(GTestTestResults, self).__init__()
+ self.timestamp = None
+ self.num_successes = 0
+
+ def _GetMs(self):
+ return (time.time() - self.timestamp) * 1000
+
+ @property
+ def num_errors(self):
+ return len(self.errors) + len(self.failures)
+
+ @staticmethod
+ def _formatTestname(test):
+ if isinstance(test, unittest.TestCase):
+ chunks = test.id().split('.')[-2:]
+ return '.'.join(chunks)
+ else:
+ return str(test)
+
+ def _emitFailure(self, test, err):
+ print self._exc_info_to_string(err, test)
+ test_name = GTestTestResults._formatTestname(test)
+ print '[ FAILED ]', test_name, '(%0.f ms)' % self._GetMs()
+ sys.stdout.flush()
+
+ def addError(self, test, err):
+ self._emitFailure(test, err)
+ super(GTestTestResults, self).addError(test, err)
+
+ def addFailure(self, test, err):
+ self._emitFailure(test, err)
+ super(GTestTestResults, self).addFailure(test, err)
+
+ def startTest(self, test):
+ print '[ RUN ]', GTestTestResults._formatTestname(test)
+ sys.stdout.flush()
+ self.timestamp = time.time()
+ super(GTestTestResults, self).startTest(test)
+
+ def addSuccess(self, test):
+ self.num_successes = self.num_successes + 1
+ test_name = GTestTestResults._formatTestname(test)
+ print '[ OK ]', test_name, '(%0.f ms)' % self._GetMs()
+ sys.stdout.flush()
+ super(GTestTestResults, self).addSuccess(test)
+
+ def PrintSummary(self):
+ unit = 'test' if self.num_successes == 1 else 'tests'
+ print '[ PASSED ] %d %s.' % (self.num_successes, unit)
+ if self.errors or self.failures:
+ all_errors = self.errors[:]
+ all_errors.extend(self.failures)
+ unit = 'test' if len(all_errors) == 1 else 'tests'
+ print '[ FAILED ] %d %s, listed below:' % (len(all_errors), unit)
+ for test, _ in all_errors:
+ print '[ FAILED ] ', GTestTestResults._formatTestname(test)
+ if not self.wasSuccessful():
+ print
+ count = len(self.errors) + len(self.failures)
+ unit = 'TEST' if count == 1 else 'TESTS'
+ print '%d FAILED %s' % (count, unit)
+ print
+ sys.stdout.flush()
diff --git a/chromium/tools/telemetry/telemetry/page/html_page_measurement_results.py b/chromium/tools/telemetry/telemetry/page/html_page_measurement_results.py
new file mode 100644
index 00000000000..6c6e3ccfb97
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/html_page_measurement_results.py
@@ -0,0 +1,112 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import datetime
+import json
+import logging
+import os
+import re
+import sys
+
+from telemetry.core import util
+from telemetry.page import buildbot_page_measurement_results
+
+# Get build/util scripts into our path.
+sys.path.append(os.path.abspath(os.path.join(
+ util.GetChromiumSrcDir(), 'build', 'util')))
+import lastchange # pylint: disable=F0401
+
+
+_TEMPLATE_HTML_PATH = os.path.join(
+ util.GetTelemetryDir(), 'support', 'html_output', 'results-template.html')
+_PLUGINS = [('third_party', 'flot', 'jquery.flot.min.js'),
+ ('third_party', 'WebKit', 'PerformanceTests', 'resources',
+ 'jquery.tablesorter.min.js'),
+ ('third_party', 'WebKit', 'PerformanceTests', 'resources',
+ 'statistics.js')]
+_UNIT_JSON = ('tools', 'perf', 'unit-info.json')
+
+
+class HtmlPageMeasurementResults(
+ buildbot_page_measurement_results.BuildbotPageMeasurementResults):
+ def __init__(self, output_stream, test_name, reset_results, browser_type,
+ trace_tag=''):
+ super(HtmlPageMeasurementResults, self).__init__(trace_tag)
+
+ self._output_stream = output_stream
+ self._reset_results = reset_results
+ self._test_name = test_name
+ self._result_json = {
+ 'buildTime': self._GetBuildTime(),
+ 'revision': self._GetRevision(),
+ 'platform': browser_type,
+ 'tests': {}
+ }
+
+ def _GetBuildTime(self):
+ def _DatetimeInEs5CompatibleFormat(dt):
+ return dt.strftime('%Y-%m-%dT%H:%M:%S.%f')
+ return _DatetimeInEs5CompatibleFormat(datetime.datetime.utcnow())
+
+ def _GetRevision(self):
+ return lastchange.FetchVersionInfo(None).revision
+
+ def _GetHtmlTemplate(self):
+ return open(_TEMPLATE_HTML_PATH, 'r').read()
+
+ def _GetPlugins(self):
+ plugins = ''
+ for p in _PLUGINS:
+ plugins += open(os.path.join(util.GetChromiumSrcDir(), *p), 'r').read()
+ return plugins
+
+ def _GetUnitJson(self):
+ return open(os.path.join(util.GetChromiumSrcDir(), *_UNIT_JSON), 'r').read()
+
+ def _GetResultsJson(self):
+ results_html = self._output_stream.read()
+ if self._reset_results or not results_html:
+ return []
+ m = re.search(
+ '^<script id="results-json" type="application/json">(.*?)</script>$',
+ results_html, re.MULTILINE | re.DOTALL)
+ if not m:
+ logging.warn('Failed to extract previous results from HTML output')
+ return []
+ return json.loads(m.group(1))
+
+ def _SaveResults(self, results):
+ self._output_stream.seek(0)
+ self._output_stream.write(results)
+ self._output_stream.truncate()
+
+ def _PrintPerfResult(self, measurement, trace, values, units,
+ result_type='default'):
+ super(HtmlPageMeasurementResults, self)._PrintPerfResult(
+ measurement, trace, values, units, result_type)
+
+ metric_name = measurement
+ if trace != measurement:
+ metric_name += '.' + trace
+ self._result_json['tests'].setdefault(self._test_name, {})
+ self._result_json['tests'][self._test_name].setdefault('metrics', {})
+ self._result_json['tests'][self._test_name]['metrics'][metric_name] = {
+ 'current': values,
+ 'units': units,
+ 'important': result_type == 'default'
+ }
+
+ def PrintSummary(self):
+ super(HtmlPageMeasurementResults, self).PrintSummary()
+
+ json_results = self._GetResultsJson()
+ json_results.append(self._result_json)
+ html = self._GetHtmlTemplate()
+ html = html.replace('%json_results%', json.dumps(json_results))
+ html = html.replace('%json_units%', self._GetUnitJson())
+ html = html.replace('%plugins%', self._GetPlugins())
+ self._SaveResults(html)
+
+ print
+ print 'View result at file://%s' % os.path.abspath(self._output_stream.name)
diff --git a/chromium/tools/telemetry/telemetry/page/html_page_measurement_results_unittest.py b/chromium/tools/telemetry/telemetry/page/html_page_measurement_results_unittest.py
new file mode 100644
index 00000000000..2a422082fa3
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/html_page_measurement_results_unittest.py
@@ -0,0 +1,203 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import StringIO
+import unittest
+
+from telemetry.page import html_page_measurement_results
+from telemetry.page import page_set
+
+
+def _MakePageSet():
+ return page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "http://www.foo.com/"},
+ {"url": "http://www.bar.com/"},
+ {"url": "http://www.baz.com/"}
+ ]
+ }, os.path.dirname(__file__))
+
+
+class DeterministicHtmlPageMeasurementResults(
+ html_page_measurement_results.HtmlPageMeasurementResults):
+ def _GetBuildTime(self):
+ return 'build_time'
+
+ def _GetRevision(self):
+ return 'revision'
+
+
+# Wrap string IO with a .name property so that it behaves more like a file.
+class StringIOFile(StringIO.StringIO):
+ name = 'fake_output_file'
+
+
+class HtmlPageMeasurementResultsTest(unittest.TestCase):
+
+ # TODO(tonyg): Remove this backfill when we can assume python 2.7 everywhere.
+ def assertIn(self, first, second, msg=None):
+ self.assertTrue(first in second,
+ msg="'%s' not found in '%s'" % (first, second))
+
+ def test_basic_summary(self):
+ test_page_set = _MakePageSet()
+ output_file = StringIOFile()
+
+ # Run the first time and verify the results are written to the HTML file.
+ results = DeterministicHtmlPageMeasurementResults(
+ output_file, 'test_name', False, 'browser_type')
+ results.WillMeasurePage(test_page_set.pages[0])
+ results.Add('a', 'seconds', 3)
+ results.DidMeasurePage()
+ results.WillMeasurePage(test_page_set.pages[1])
+ results.Add('a', 'seconds', 7)
+ results.DidMeasurePage()
+
+ results.PrintSummary()
+ expected = (
+ '<script id="results-json" type="application/json">'
+ '[{'
+ '"platform": "browser_type", '
+ '"buildTime": "build_time", '
+ '"tests": {'
+ '"test_name": {'
+ '"metrics": {'
+ '"a": {'
+ '"current": [3, 7], '
+ '"units": "seconds", '
+ '"important": true'
+ '}, '
+ '"a_by_url.http://www.bar.com/": {'
+ '"current": [7], '
+ '"units": "seconds", '
+ '"important": false'
+ '}, '
+ '"a_by_url.http://www.foo.com/": {'
+ '"current": [3], '
+ '"units": "seconds", '
+ '"important": false'
+ '}'
+ '}'
+ '}'
+ '}, '
+ '"revision": "revision"'
+ '}]'
+ '</script>')
+ self.assertIn(expected, output_file.getvalue())
+
+ # Run the second time and verify the results are appended to the HTML file.
+ output_file.seek(0)
+ results = DeterministicHtmlPageMeasurementResults(
+ output_file, 'test_name', False, 'browser_type')
+ results.WillMeasurePage(test_page_set.pages[0])
+ results.Add('a', 'seconds', 4)
+ results.DidMeasurePage()
+ results.WillMeasurePage(test_page_set.pages[1])
+ results.Add('a', 'seconds', 8)
+ results.DidMeasurePage()
+
+ results.PrintSummary()
+ expected = (
+ '<script id="results-json" type="application/json">'
+ '[{'
+ '"platform": "browser_type", '
+ '"buildTime": "build_time", '
+ '"tests": {'
+ '"test_name": {'
+ '"metrics": {'
+ '"a": {'
+ '"current": [3, 7], '
+ '"units": "seconds", '
+ '"important": true'
+ '}, '
+ '"a_by_url.http://www.bar.com/": {'
+ '"current": [7], '
+ '"units": "seconds", '
+ '"important": false'
+ '}, '
+ '"a_by_url.http://www.foo.com/": {'
+ '"current": [3], '
+ '"units": "seconds", '
+ '"important": false'
+ '}'
+ '}'
+ '}'
+ '}, '
+ '"revision": "revision"'
+ '}, '
+ '{'
+ '"platform": "browser_type", '
+ '"buildTime": "build_time", '
+ '"tests": {'
+ '"test_name": {'
+ '"metrics": {'
+ '"a": {'
+ '"current": [4, 8], '
+ '"units": "seconds", '
+ '"important": true'
+ '}, '
+ '"a_by_url.http://www.bar.com/": {'
+ '"current": [8], '
+ '"units": "seconds", '
+ '"important": false'
+ '}, '
+ '"a_by_url.http://www.foo.com/": {'
+ '"current": [4], '
+ '"units": "seconds", '
+ '"important": false'
+ '}'
+ '}'
+ '}'
+ '}, '
+ '"revision": "revision"'
+ '}]'
+ '</script>')
+ self.assertIn(expected, output_file.getvalue())
+ last_output_len = len(output_file.getvalue())
+
+ # Now reset the results and verify the old ones are gone.
+ output_file.seek(0)
+ results = DeterministicHtmlPageMeasurementResults(
+ output_file, 'test_name', True, 'browser_type')
+ results.WillMeasurePage(test_page_set.pages[0])
+ results.Add('a', 'seconds', 5)
+ results.DidMeasurePage()
+ results.WillMeasurePage(test_page_set.pages[1])
+ results.Add('a', 'seconds', 9)
+ results.DidMeasurePage()
+
+ results.PrintSummary()
+ expected = (
+ '<script id="results-json" type="application/json">'
+ '[{'
+ '"platform": "browser_type", '
+ '"buildTime": "build_time", '
+ '"tests": {'
+ '"test_name": {'
+ '"metrics": {'
+ '"a": {'
+ '"current": [5, 9], '
+ '"units": "seconds", '
+ '"important": true'
+ '}, '
+ '"a_by_url.http://www.bar.com/": {'
+ '"current": [9], '
+ '"units": "seconds", '
+ '"important": false'
+ '}, '
+ '"a_by_url.http://www.foo.com/": {'
+ '"current": [5], '
+ '"units": "seconds", '
+ '"important": false'
+ '}'
+ '}'
+ '}'
+ '}, '
+ '"revision": "revision"'
+ '}]'
+ '</script>')
+ self.assertIn(expected, output_file.getvalue())
+ self.assertTrue(len(output_file.getvalue()) < last_output_len)
diff --git a/chromium/tools/telemetry/telemetry/page/page.py b/chromium/tools/telemetry/telemetry/page/page.py
new file mode 100644
index 00000000000..5d06076a538
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page.py
@@ -0,0 +1,140 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import re
+import time
+import urlparse
+
+from telemetry.core import util
+
+def _UrlPathJoin(*args):
+ """Joins each path in |args| for insertion into a URL path.
+
+ This is distinct from os.path.join in that:
+ 1. Forward slashes are always used.
+ 2. Paths beginning with '/' are not treated as absolute.
+
+ For example:
+ _UrlPathJoin('a', 'b') => 'a/b'
+ _UrlPathJoin('a/', 'b') => 'a/b'
+ _UrlPathJoin('a', '/b') => 'a/b'
+ _UrlPathJoin('a/', '/b') => 'a/b'
+ """
+ if not args:
+ return ''
+ if len(args) == 1:
+ return str(args[0])
+ else:
+ args = [str(arg).replace('\\', '/') for arg in args]
+ work = [args[0]]
+ for arg in args[1:]:
+ if not arg:
+ continue
+ if arg.startswith('/'):
+ work.append(arg[1:])
+ else:
+ work.append(arg)
+ joined = reduce(os.path.join, work)
+ return joined.replace('\\', '/')
+
+class Page(object):
+ def __init__(self, url, page_set, attributes=None, base_dir=None):
+ parsed_url = urlparse.urlparse(url)
+ if not parsed_url.scheme:
+ abspath = os.path.abspath(os.path.join(base_dir, parsed_url.path))
+ if os.path.exists(abspath):
+ url = 'file://%s' % os.path.abspath(os.path.join(base_dir, url))
+ else:
+ raise Exception('URLs must be fully qualified: %s' % url)
+ self.url = url
+ self.page_set = page_set
+ self.base_dir = base_dir
+
+ # These attributes can be set dynamically by the page.
+ self.credentials = None
+ self.disabled = False
+ self.script_to_evaluate_on_commit = None
+
+ if attributes:
+ for k, v in attributes.iteritems():
+ setattr(self, k, v)
+
+ def __getattr__(self, name):
+ if self.page_set and hasattr(self.page_set, name):
+ return getattr(self.page_set, name)
+
+ raise AttributeError()
+
+ @property
+ def is_file(self):
+ parsed_url = urlparse.urlparse(self.url)
+ return parsed_url.scheme == 'file'
+
+ @property
+ def is_local(self):
+ parsed_url = urlparse.urlparse(self.url)
+ return parsed_url.scheme == 'file' or parsed_url.scheme == 'chrome'
+
+ @property
+ def serving_dirs_and_file(self):
+ parsed_url = urlparse.urlparse(self.url)
+ path = _UrlPathJoin(self.base_dir, parsed_url.netloc, parsed_url.path)
+
+ if hasattr(self.page_set, 'serving_dirs'):
+ url_base_dir = os.path.commonprefix(self.page_set.serving_dirs)
+ base_path = _UrlPathJoin(self.base_dir, url_base_dir)
+ return ([_UrlPathJoin(self.base_dir, d)
+ for d in self.page_set.serving_dirs],
+ path.replace(base_path, ''))
+
+ return os.path.split(path)
+
+ # A version of this page's URL that's safe to use as a filename.
+ @property
+ def url_as_file_safe_name(self):
+ # Just replace all special characters in the url with underscore.
+ return re.sub('[^a-zA-Z0-9]', '_', self.display_url)
+
+ @property
+ def display_url(self):
+ if not self.is_local:
+ return self.url
+ url_paths = ['/'.join(p.url.strip('/').split('/')[:-1])
+ for p in self.page_set if p.is_file]
+ common_prefix = os.path.commonprefix(url_paths)
+ return self.url[len(common_prefix):].strip('/')
+
+ @property
+ def archive_path(self):
+ return self.page_set.WprFilePathForPage(self)
+
+ def __str__(self):
+ return self.url
+
+ def WaitToLoad(self, tab, timeout, poll_interval=0.1):
+ Page.WaitForPageToLoad(self, tab, timeout, poll_interval)
+
+ # TODO(dtu): Remove this method when no page sets use a click interaction
+ # with a wait condition. crbug.com/168431
+ @staticmethod
+ def WaitForPageToLoad(obj, tab, timeout, poll_interval=0.1):
+ """Waits for various wait conditions present in obj."""
+ if hasattr(obj, 'wait_seconds'):
+ time.sleep(obj.wait_seconds)
+ if hasattr(obj, 'wait_for_element_with_text'):
+ callback_code = 'function(element) { return element != null; }'
+ util.WaitFor(
+ lambda: util.FindElementAndPerformAction(
+ tab, obj.wait_for_element_with_text, callback_code),
+ timeout, poll_interval)
+ if hasattr(obj, 'wait_for_element_with_selector'):
+ util.WaitFor(lambda: tab.EvaluateJavaScript(
+ 'document.querySelector(\'' + obj.wait_for_element_with_selector +
+ '\') != null'), timeout, poll_interval)
+ if hasattr(obj, 'post_navigate_javascript_to_execute'):
+ tab.EvaluateJavaScript(obj.post_navigate_javascript_to_execute)
+ if hasattr(obj, 'wait_for_javascript_expression'):
+ util.WaitFor(
+ lambda: tab.EvaluateJavaScript(obj.wait_for_javascript_expression),
+ timeout, poll_interval)
diff --git a/chromium/tools/telemetry/telemetry/page/page_filter.py b/chromium/tools/telemetry/telemetry/page/page_filter.py
new file mode 100644
index 00000000000..dcf30b864e6
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_filter.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import optparse
+import re
+
+class PageFilter(object):
+ """Filters pages in the page set based on command line flags."""
+
+ def __init__(self, options):
+ if options.page_filter:
+ try:
+ self._page_regex = re.compile(options.page_filter)
+ except re.error:
+ raise Exception('--page-filter: invalid regex')
+ else:
+ self._page_regex = None
+
+ if options.page_filter_exclude:
+ try:
+ self._page_exclude_regex = re.compile(options.page_filter_exclude)
+ except re.error:
+ raise Exception('--page-filter-exclude: invalid regex')
+ else:
+ self._page_exclude_regex = None
+
+ def IsSelected(self, page):
+ if self._page_exclude_regex and self._page_exclude_regex.search(page.url):
+ return False
+ if self._page_regex:
+ return self._page_regex.search(page.url)
+ return True
+
+ @staticmethod
+ def AddCommandLineOptions(parser):
+ group = optparse.OptionGroup(parser, 'Page filtering options')
+ group.add_option('--page-filter', dest='page_filter',
+ help='Use only pages whose URLs match the given filter regexp.')
+ group.add_option('--page-filter-exclude', dest='page_filter_exclude',
+ help='Exclude pages whose URLs match the given filter regexp.')
+ parser.add_option_group(group)
diff --git a/chromium/tools/telemetry/telemetry/page/page_measurement.py b/chromium/tools/telemetry/telemetry/page/page_measurement.py
new file mode 100644
index 00000000000..be3bb51aca3
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_measurement.py
@@ -0,0 +1,143 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+from telemetry.page import block_page_measurement_results
+from telemetry.page import buildbot_page_measurement_results
+from telemetry.page import csv_page_measurement_results
+from telemetry.page import html_page_measurement_results
+from telemetry.page import page_measurement_results
+from telemetry.page import page_test
+
+class MeasurementFailure(page_test.Failure):
+ """Exception that can be thrown from MeasurePage to indicate an undesired but
+ designed-for problem."""
+ pass
+
+class PageMeasurement(page_test.PageTest):
+ """Glue code for running a measurement across a set of pages.
+
+ To use this, subclass from the measurement and override MeasurePage. For
+ example:
+
+ class BodyChildElementMeasurement(PageMeasurement):
+ def MeasurePage(self, page, tab, results):
+ body_child_count = tab.EvaluateJavaScript(
+ 'document.body.children.length')
+ results.Add('body_children', 'count', body_child_count)
+
+ if __name__ == '__main__':
+ page_measurement.Main(BodyChildElementMeasurement())
+
+ To add test-specific options:
+
+ class BodyChildElementMeasurement(PageMeasurement):
+ def AddCommandLineOptions(parser):
+ parser.add_option('--element', action='store', default='body')
+
+ def MeasurePage(self, page, tab, results):
+ body_child_count = tab.EvaluateJavaScript(
+ 'document.querySelector('%s').children.length')
+ results.Add('children', 'count', child_count)
+ """
+ def __init__(self,
+ action_name_to_run='',
+ needs_browser_restart_after_each_run=False,
+ discard_first_result=False,
+ clear_cache_before_each_run=False):
+ super(PageMeasurement, self).__init__(
+ '_RunTest',
+ action_name_to_run,
+ needs_browser_restart_after_each_run,
+ discard_first_result,
+ clear_cache_before_each_run)
+
+ def _RunTest(self, page, tab, results):
+ results.WillMeasurePage(page)
+ self.MeasurePage(page, tab, results)
+ results.DidMeasurePage()
+
+ def AddOutputOptions(self, parser):
+ super(PageMeasurement, self).AddOutputOptions(parser)
+ parser.add_option('-o', '--output',
+ dest='output_file',
+ help='Redirects output to a file. Defaults to stdout.')
+ parser.add_option('--output-trace-tag',
+ default='',
+ help='Append a tag to the key of each result trace.')
+ parser.add_option('--reset-html-results', action='store_true',
+ help='Delete all stored runs in HTML output')
+
+ @property
+ def output_format_choices(self):
+ return ['html', 'buildbot', 'block', 'csv', 'none']
+
+ def PrepareResults(self, options):
+ if hasattr(options, 'output_file') and options.output_file:
+ output_file = os.path.expanduser(options.output_file)
+ open(output_file, 'a').close() # Create file if it doesn't exist.
+ output_stream = open(output_file, 'r+')
+ else:
+ output_stream = sys.stdout
+ if not hasattr(options, 'output_format'):
+ options.output_format = self.output_format_choices[0]
+ if not hasattr(options, 'output_trace_tag'):
+ options.output_trace_tag = ''
+
+ if options.output_format == 'csv':
+ return csv_page_measurement_results.CsvPageMeasurementResults(
+ output_stream,
+ self.results_are_the_same_on_every_page)
+ elif options.output_format == 'block':
+ return block_page_measurement_results.BlockPageMeasurementResults(
+ output_stream)
+ elif options.output_format == 'buildbot':
+ return buildbot_page_measurement_results.BuildbotPageMeasurementResults(
+ trace_tag=options.output_trace_tag)
+ elif options.output_format == 'html':
+ return html_page_measurement_results.HtmlPageMeasurementResults(
+ output_stream, self.__class__.__name__, options.reset_html_results,
+ options.browser_type, trace_tag=options.output_trace_tag)
+ elif options.output_format == 'none':
+ return page_measurement_results.PageMeasurementResults(
+ trace_tag=options.output_trace_tag)
+ else:
+ # Should never be reached. The parser enforces the choices.
+ raise Exception('Invalid --output-format "%s". Valid choices are: %s'
+ % (options.output_format,
+ ', '.join(self.output_format_choices)))
+
+ @property
+ def results_are_the_same_on_every_page(self):
+ """By default, measurements are assumed to output the same values for every
+ page. This allows incremental output, for example in CSV. If, however, the
+ measurement discovers what values it can report as it goes, and those values
+ may vary from page to page, you need to override this function and return
+ False. Output will not appear in this mode until the entire pageset has
+ run."""
+ return True
+
+ def MeasurePage(self, page, tab, results):
+ """Override to actually measure the page's performance.
+
+ page is a page_set.Page
+ tab is an instance of telemetry.core.Tab
+
+ Should call results.Add(name, units, value) for each result, or raise an
+ exception on failure. The name and units of each Add() call must be
+ the same across all iterations. The name 'url' must not be used.
+
+ Prefer field names that are in accordance with python variable style. E.g.
+ field_name.
+
+ Put together:
+
+ def MeasurePage(self, page, tab, results):
+ res = tab.EvaluateJavaScript('2+2')
+ if res != 4:
+ raise Exception('Oh, wow.')
+ results.Add('two_plus_two', 'count', res)
+ """
+ raise NotImplementedError()
diff --git a/chromium/tools/telemetry/telemetry/page/page_measurement_results.py b/chromium/tools/telemetry/telemetry/page/page_measurement_results.py
new file mode 100644
index 00000000000..9b8f088830b
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_measurement_results.py
@@ -0,0 +1,112 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page import page_test_results
+from telemetry.page import page_measurement_value
+
+class ValuesForSinglePage(object):
+ def __init__(self, page):
+ self.page = page
+ self.values = []
+
+ def AddValue(self, value):
+ self.values.append(value)
+
+ @property
+ def measurement_names(self):
+ return [value.measurement_name for value in self.values]
+
+ def FindValueByMeasurementName(self, measurement_name):
+ values = [value for value in self.values
+ if value.measurement_name == measurement_name]
+ assert len(values) <= 1
+ if len(values):
+ return values[0]
+ return None
+
+ def __getitem__(self, trace_name):
+ return self.FindValueByTraceName(trace_name)
+
+ def __contains__(self, trace_name):
+ return self.FindValueByTraceName(trace_name) != None
+
+ def FindValueByTraceName(self, trace_name):
+ values = [value for value in self.values
+ if value.trace_name == trace_name]
+ assert len(values) <= 1
+ if len(values):
+ return values[0]
+ return None
+
+class PageMeasurementResults(page_test_results.PageTestResults):
+ def __init__(self, trace_tag=''):
+ super(PageMeasurementResults, self).__init__()
+ self._trace_tag = trace_tag
+ self._page_results = []
+ self._overall_results = []
+
+ self._all_measurements_that_have_been_seen = {}
+
+ self._values_for_current_page = {}
+
+ def __getitem__(self, i):
+ """Shorthand for self.page_results[i]"""
+ return self._page_results[i]
+
+ def __len__(self):
+ return len(self._page_results)
+
+ @property
+ def values_for_current_page(self):
+ return self._values_for_current_page
+
+ @property
+ def page_results(self):
+ return self._page_results
+
+ def WillMeasurePage(self, page):
+ self._values_for_current_page = ValuesForSinglePage(page)
+
+ @property
+ def all_measurements_that_have_been_seen(self):
+ return self._all_measurements_that_have_been_seen
+
+ def Add(self, trace_name, units, value, chart_name=None, data_type='default'):
+ value = self._GetPageMeasurementValue(trace_name, units, value, chart_name,
+ data_type)
+ self._values_for_current_page.AddValue(value)
+
+ def AddSummary(self, trace_name, units, value, chart_name=None,
+ data_type='default'):
+ value = self._GetPageMeasurementValue(trace_name, units, value, chart_name,
+ data_type)
+ self._overall_results.append(value)
+
+ def _GetPageMeasurementValue(self, trace_name, units, value, chart_name,
+ data_type):
+ value = page_measurement_value.PageMeasurementValue(
+ trace_name, units, value, chart_name, data_type)
+ measurement_name = value.measurement_name
+
+ # Sanity checks.
+ assert measurement_name != 'url', 'The name url cannot be used'
+ if measurement_name in self._all_measurements_that_have_been_seen:
+ measurement_data = \
+ self._all_measurements_that_have_been_seen[measurement_name]
+ last_seen_units = measurement_data['units']
+ last_seen_data_type = measurement_data['type']
+ assert last_seen_units == units, \
+ 'Unit cannot change for a name once it has been provided'
+ assert last_seen_data_type == data_type, \
+ 'Unit cannot change for a name once it has been provided'
+ else:
+ self._all_measurements_that_have_been_seen[measurement_name] = {
+ 'units': units,
+ 'type': data_type}
+ return value
+
+ def DidMeasurePage(self):
+ assert self._values_for_current_page, 'Failed to call WillMeasurePage'
+ self._page_results.append(self._values_for_current_page)
+ self._values_for_current_page = None
diff --git a/chromium/tools/telemetry/telemetry/page/page_measurement_results_unittest.py b/chromium/tools/telemetry/telemetry/page/page_measurement_results_unittest.py
new file mode 100644
index 00000000000..727eeb612d8
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_measurement_results_unittest.py
@@ -0,0 +1,105 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from telemetry.page import page_measurement_results
+from telemetry.page import page_set
+from telemetry.page import perf_tests_helper
+
+def _MakePageSet():
+ return page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "http://www.foo.com/"},
+ {"url": "http://www.bar.com/"}
+ ]
+ }, os.path.dirname(__file__))
+
+class NonPrintingPageMeasurementResults(
+ page_measurement_results.PageMeasurementResults):
+ def __init__(self):
+ super(NonPrintingPageMeasurementResults, self).__init__()
+
+ def _PrintPerfResult(self, *args):
+ pass
+
+class SummarySavingPageMeasurementResults(
+ page_measurement_results.PageMeasurementResults):
+ def __init__(self):
+ super(SummarySavingPageMeasurementResults, self).__init__()
+ self.results = []
+
+ def _PrintPerfResult(self, *args):
+ res = perf_tests_helper.PrintPerfResult(*args, print_to_stdout=False)
+ self.results.append(res)
+
+class PageMeasurementResultsTest(unittest.TestCase):
+ def test_basic(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = NonPrintingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.PrintSummary()
+
+ def test_url_is_invalid_value(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = NonPrintingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ self.assertRaises(
+ AssertionError,
+ lambda: measurement_results.Add('url', 'string', 'foo'))
+
+ def test_unit_change(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = NonPrintingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ self.assertRaises(
+ AssertionError,
+ lambda: measurement_results.Add('a', 'foobgrobbers', 3))
+
+ def test_type_change(self):
+ test_page_set = _MakePageSet()
+
+ measurement_results = NonPrintingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ self.assertRaises(
+ AssertionError,
+ lambda: measurement_results.Add('a', 'seconds', 3, data_type='histogram'))
+
+ def test_basic_summary_all_pages_fail(self):
+ """If all pages fail, no summary is printed."""
+ test_page_set = _MakePageSet()
+
+ measurement_results = SummarySavingPageMeasurementResults()
+ measurement_results.WillMeasurePage(test_page_set.pages[0])
+ measurement_results.Add('a', 'seconds', 3)
+ measurement_results.DidMeasurePage()
+ measurement_results.AddFailureMessage(test_page_set.pages[0], 'message')
+
+ measurement_results.WillMeasurePage(test_page_set.pages[1])
+ measurement_results.Add('a', 'seconds', 7)
+ measurement_results.DidMeasurePage()
+ measurement_results.AddFailureMessage(test_page_set.pages[1], 'message')
+
+ measurement_results.PrintSummary()
+ self.assertEquals(measurement_results.results, [])
diff --git a/chromium/tools/telemetry/telemetry/page/page_measurement_runner.py b/chromium/tools/telemetry/telemetry/page/page_measurement_runner.py
new file mode 100755
index 00000000000..a10fd0b8732
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_measurement_runner.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import sys
+
+from telemetry.page import page_measurement
+from telemetry.page import page_test_runner
+
+def Main(base_dir, page_set_filenames):
+ """Turns a PageMeasurement into a command-line program.
+
+ Args:
+ base_dir: Path to directory containing tests and ProfileCreators.
+ """
+ runner = PageMeasurementRunner()
+ sys.exit(runner.Run(base_dir, page_set_filenames))
+
+class PageMeasurementRunner(page_test_runner.PageTestRunner):
+ @property
+ def test_class(self):
+ return page_measurement.PageMeasurement
+
+ @property
+ def test_class_name(self):
+ return 'measurement'
diff --git a/chromium/tools/telemetry/telemetry/page/page_measurement_unittest.py b/chromium/tools/telemetry/telemetry/page/page_measurement_unittest.py
new file mode 100644
index 00000000000..873ba2e8e27
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_measurement_unittest.py
@@ -0,0 +1,147 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import os
+
+from telemetry.core import wpr_modes
+from telemetry.page import page_measurement
+from telemetry.page import page_measurement_unittest_base
+from telemetry.page import page as page_module
+from telemetry.page import page_set
+from telemetry.page import page_set_archive_info
+from telemetry.page.actions import all_page_actions
+from telemetry.page.actions import page_action
+from telemetry.unittest import options_for_unittests
+
+class MeasurementThatFails(page_measurement.PageMeasurement):
+ def MeasurePage(self, page, tab, results):
+ raise page_measurement.MeasurementFailure('Intentional failure.')
+
+class MeasurementThatHasDefaults(page_measurement.PageMeasurement):
+ def AddCommandLineOptions(self, parser):
+ parser.add_option('-x', dest='x', default=3)
+
+ def MeasurePage(self, page, tab, results):
+ assert self.options.x == 3
+ results.Add('x', 'ms', 7)
+
+class MeasurementForBlank(page_measurement.PageMeasurement):
+ def MeasurePage(self, page, tab, results):
+ contents = tab.EvaluateJavaScript('document.body.textContent')
+ assert contents.strip() == 'Hello world'
+
+class MeasurementForReplay(page_measurement.PageMeasurement):
+ def MeasurePage(self, page, tab, results):
+ # Web Page Replay returns '404 Not found' if a page is not in the archive.
+ contents = tab.EvaluateJavaScript('document.body.textContent')
+ if '404 Not Found' in contents.strip():
+ raise page_measurement.MeasurementFailure('Page not in archive.')
+
+class MeasurementQueryParams(page_measurement.PageMeasurement):
+ def MeasurePage(self, page, tab, results):
+ query = tab.EvaluateJavaScript('window.location.search')
+ assert query.strip() == '?foo=1'
+
+class MeasurementWithAction(page_measurement.PageMeasurement):
+ def __init__(self):
+ super(MeasurementWithAction, self).__init__('test_action')
+
+ def MeasurePage(self, page, tab, results):
+ pass
+
+class PageMeasurementUnitTest(
+ page_measurement_unittest_base.PageMeasurementUnitTestBase):
+
+ def setUp(self):
+ self._options = options_for_unittests.GetCopy()
+ self._options.wpr_mode = wpr_modes.WPR_OFF
+
+ def testGotToBlank(self):
+ ps = self.CreatePageSetFromFileInUnittestDataDir('blank.html')
+ measurement = MeasurementForBlank()
+ all_results = self.RunMeasurement(measurement, ps, options=self._options)
+ self.assertEquals(0, len(all_results.failures))
+
+ def testGotQueryParams(self):
+ ps = self.CreatePageSet('file:///../../unittest_data/blank.html?foo=1')
+ measurement = MeasurementQueryParams()
+ ps.pages[-1].query_params = '?foo=1'
+ all_results = self.RunMeasurement(measurement, ps, options=self._options)
+ self.assertEquals(0, len(all_results.failures))
+
+ def testFailure(self):
+ ps = self.CreatePageSetFromFileInUnittestDataDir('blank.html')
+ measurement = MeasurementThatFails()
+ all_results = self.RunMeasurement(measurement, ps, options=self._options)
+ self.assertEquals(1, len(all_results.failures))
+
+ def testDefaults(self):
+ ps = self.CreatePageSetFromFileInUnittestDataDir('blank.html')
+ measurement = MeasurementThatHasDefaults()
+ all_results = self.RunMeasurement(measurement, ps, options=self._options)
+ self.assertEquals(len(all_results.page_results), 1)
+ self.assertEquals(
+ all_results.page_results[0].FindValueByTraceName('x').value, 7)
+
+ def disabled_testRecordAndReplay(self):
+ # This test is disabled because it runs against live sites, and needs to be
+ # fixed. crbug.com/179038
+ test_archive = '/tmp/google.wpr'
+ google_url = 'http://www.google.com/'
+ foo_url = 'http://www.foo.com/'
+ archive_info_template = ("""
+{
+"archives": {
+ "%s": ["%s"]
+}
+}
+""")
+ try:
+ ps = page_set.PageSet()
+ measurement = MeasurementForReplay()
+
+ # First record an archive with only www.google.com.
+ self._options.wpr_mode = wpr_modes.WPR_RECORD
+
+ ps.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo(
+ '', '', json.loads(archive_info_template %
+ (test_archive, google_url)))
+ ps.pages = [page_module.Page(google_url, ps)]
+ all_results = self.RunMeasurement(measurement, ps, options=self._options)
+ self.assertEquals(0, len(all_results.failures))
+
+ # Now replay it and verify that google.com is found but foo.com is not.
+ self._options.wpr_mode = wpr_modes.WPR_REPLAY
+
+ ps.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo(
+ '', '', json.loads(archive_info_template % (test_archive, foo_url)))
+ ps.pages = [page_module.Page(foo_url, ps)]
+ all_results = self.RunMeasurement(measurement, ps, options=self._options)
+ self.assertEquals(1, len(all_results.failures))
+
+ ps.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo(
+ '', '', json.loads(archive_info_template %
+ (test_archive, google_url)))
+ ps.pages = [page_module.Page(google_url, ps)]
+ all_results = self.RunMeasurement(measurement, ps, options=self._options)
+ self.assertEquals(0, len(all_results.failures))
+
+ self.assertTrue(os.path.isfile(test_archive))
+
+ finally:
+ if os.path.isfile(test_archive):
+ os.remove(test_archive)
+
+ def testActions(self):
+ action_called = [False]
+ class MockAction(page_action.PageAction):
+ def RunAction(self, page, tab, previous_action):
+ action_called[0] = True
+ all_page_actions.RegisterClassForTest('mock', MockAction)
+
+ ps = self.CreatePageSetFromFileInUnittestDataDir('blank.html')
+ setattr(ps.pages[0], 'test_action', {'action': 'mock'})
+ measurement = MeasurementWithAction()
+ self.RunMeasurement(measurement, ps, options=self._options)
+ self.assertTrue(action_called[0])
diff --git a/chromium/tools/telemetry/telemetry/page/page_measurement_unittest_base.py b/chromium/tools/telemetry/telemetry/page/page_measurement_unittest_base.py
new file mode 100644
index 00000000000..6c570c84237
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_measurement_unittest_base.py
@@ -0,0 +1,48 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from telemetry.page import page_runner
+from telemetry.page import page as page_module
+from telemetry.page import page_set
+from telemetry.page import test_expectations
+from telemetry.unittest import options_for_unittests
+
+class PageMeasurementUnitTestBase(unittest.TestCase):
+ """unittest.TestCase-derived class to help in the construction of unit tests
+ for a measurement."""
+
+ def CreatePageSetFromFileInUnittestDataDir(self, test_filename):
+ return self.CreatePageSet('file:///' + os.path.join(
+ '..', '..', 'unittest_data', test_filename))
+
+ def CreatePageSet(self, test_filename):
+ base_dir = os.path.dirname(__file__)
+ ps = page_set.PageSet(file_path=os.path.join(base_dir, 'foo.json'))
+ page = page_module.Page(test_filename, ps, base_dir=base_dir)
+ setattr(page, 'smoothness', {'action': 'scroll'})
+ ps.pages.append(page)
+ return ps
+
+ def RunMeasurement(self, measurement, ps,
+ expectations=test_expectations.TestExpectations(),
+ options=None):
+ """Runs a measurement against a pageset, returning the rows its outputs."""
+ if options is None:
+ options = options_for_unittests.GetCopy()
+ assert options
+ temp_parser = options.CreateParser()
+ measurement.AddCommandLineOptions(temp_parser)
+ defaults = temp_parser.get_default_values()
+ for k, v in defaults.__dict__.items():
+ if hasattr(options, k):
+ continue
+ setattr(options, k, v)
+
+ measurement.CustomizeBrowserOptions(options)
+ options.output_file = None
+ options.output_format = 'none'
+ options.output_trace_tag = None
+ return page_runner.Run(measurement, ps, expectations, options)
diff --git a/chromium/tools/telemetry/telemetry/page/page_measurement_value.py b/chromium/tools/telemetry/telemetry/page/page_measurement_value.py
new file mode 100644
index 00000000000..c2c8e0e0912
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_measurement_value.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.page import perf_tests_helper
+
+def _Mean(l):
+ return float(sum(l)) / len(l) if len(l) > 0 else 0.0
+
+class PageMeasurementValue(object):
+ def __init__(self, trace_name, units, value, chart_name, data_type):
+ self.trace_name = trace_name
+ self.units = units
+ self.value = value
+ self.chart_name = chart_name
+ self.data_type = data_type
+
+ @property
+ def measurement_name(self):
+ if self.chart_name:
+ return '%s.%s' % (self.chart_name, self.trace_name)
+ else:
+ return self.trace_name
+
+ @property
+ def output_value(self):
+ if 'histogram' in self.data_type:
+ (mean, _) = perf_tests_helper.GeomMeanAndStdDevFromHistogram(self.value)
+ return mean
+ elif isinstance(self.value, list):
+ return _Mean(self.value)
+ else:
+ return self.value
diff --git a/chromium/tools/telemetry/telemetry/page/page_runner.py b/chromium/tools/telemetry/telemetry/page/page_runner.py
new file mode 100644
index 00000000000..89ab3115de7
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_runner.py
@@ -0,0 +1,447 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import collections
+import glob
+import logging
+import os
+import sys
+import tempfile
+import time
+import traceback
+import random
+
+from telemetry.core import browser_finder
+from telemetry.core import exceptions
+from telemetry.core import util
+from telemetry.core import wpr_modes
+from telemetry.core.platform.profiler import profiler_finder
+from telemetry.page import page_filter as page_filter_module
+from telemetry.page import page_measurement_results
+from telemetry.page import page_runner_repeat
+from telemetry.page import page_test
+
+
+class _RunState(object):
+ def __init__(self):
+ self.browser = None
+ self.tab = None
+
+ self._append_to_existing_wpr = False
+ self._last_archive_path = None
+ self._first_browser = True
+ self.first_page = collections.defaultdict(lambda: True)
+ self.profiler_dir = None
+ self.repeat_state = None
+
+ def StartBrowser(self, test, page_set, page, possible_browser,
+ credentials_path, archive_path):
+ # Create a browser.
+ if not self.browser:
+ assert not self.tab
+ self.browser = possible_browser.Create()
+ self.browser.credentials.credentials_path = credentials_path
+
+ test.WillStartBrowser(self.browser)
+ self.browser.Start()
+ test.DidStartBrowser(self.browser)
+
+ if self._first_browser:
+ self._first_browser = False
+ self.browser.credentials.WarnIfMissingCredentials(page_set)
+
+ # Set up WPR path on the new browser.
+ self.browser.SetReplayArchivePath(archive_path,
+ self._append_to_existing_wpr,
+ page_set.make_javascript_deterministic)
+ self._last_archive_path = page.archive_path
+ else:
+ # Set up WPR path if it changed.
+ if page.archive_path and self._last_archive_path != page.archive_path:
+ self.browser.SetReplayArchivePath(
+ page.archive_path,
+ self._append_to_existing_wpr,
+ page_set.make_javascript_deterministic)
+ self._last_archive_path = page.archive_path
+
+ if self.browser.supports_tab_control:
+ # Create a tab if there's none.
+ if len(self.browser.tabs) == 0:
+ self.browser.tabs.New()
+
+ # Ensure only one tab is open.
+ while len(self.browser.tabs) > 1:
+ self.browser.tabs[-1].Close()
+
+ if not self.tab:
+ self.tab = self.browser.tabs[0]
+
+ if self.first_page[page]:
+ self.first_page[page] = False
+
+ def StopBrowser(self):
+ if self.tab:
+ self.tab.Disconnect()
+ self.tab = None
+
+ if self.browser:
+ self.browser.Close()
+ self.browser = None
+
+ # Restarting the state will also restart the wpr server. If we're
+ # recording, we need to continue adding into the same wpr archive,
+ # not overwrite it.
+ self._append_to_existing_wpr = True
+
+ def StartProfiling(self, page, options):
+ if not self.profiler_dir:
+ self.profiler_dir = tempfile.mkdtemp()
+ output_file = os.path.join(self.profiler_dir, page.url_as_file_safe_name)
+ if options.repeat_options.IsRepeating():
+ output_file = _GetSequentialFileName(output_file)
+ self.browser.StartProfiling(options.profiler, output_file)
+
+ def StopProfiling(self):
+ self.browser.StopProfiling()
+
+
+class PageState(object):
+ def __init__(self):
+ self._did_login = False
+
+ def PreparePage(self, page, tab, test=None):
+ if page.is_file:
+ serving_dirs = page.serving_dirs_and_file[0]
+ if tab.browser.SetHTTPServerDirectories(serving_dirs) and test:
+ test.DidStartHTTPServer(tab)
+
+ if page.credentials:
+ if not tab.browser.credentials.LoginNeeded(tab, page.credentials):
+ raise page_test.Failure('Login as ' + page.credentials + ' failed')
+ self._did_login = True
+
+ if test:
+ if test.clear_cache_before_each_run:
+ tab.ClearCache()
+
+ def ImplicitPageNavigation(self, page, tab, test=None):
+ """Executes the implicit navigation that occurs for every page iteration.
+
+ This function will be called once per page before any actions are executed.
+ """
+ if page.is_file:
+ filename = page.serving_dirs_and_file[1]
+ target_side_url = tab.browser.http_server.UrlOf(filename)
+ else:
+ target_side_url = page.url
+
+ if test:
+ test.WillNavigateToPage(page, tab)
+ tab.Navigate(target_side_url, page.script_to_evaluate_on_commit)
+ if test:
+ test.DidNavigateToPage(page, tab)
+
+ page.WaitToLoad(tab, 60)
+ tab.WaitForDocumentReadyStateToBeInteractiveOrBetter()
+
+ def CleanUpPage(self, page, tab):
+ if page.credentials and self._did_login:
+ tab.browser.credentials.LoginNoLongerNeeded(tab, page.credentials)
+
+
+def AddCommandLineOptions(parser):
+ page_filter_module.PageFilter.AddCommandLineOptions(parser)
+
+
+def _LogStackTrace(title, browser):
+ if browser:
+ stack_trace = browser.GetStackTrace()
+ else:
+ stack_trace = 'Browser object is empty, no stack trace.'
+ stack_trace = (('\nStack Trace:\n') +
+ ('*' * 80) +
+ '\n\t' + stack_trace.replace('\n', '\n\t') + '\n' +
+ ('*' * 80))
+ logging.warning('%s%s', title, stack_trace)
+
+
+def _PrepareAndRunPage(test, page_set, expectations, options, page,
+ credentials_path, possible_browser, results, state):
+ if options.wpr_mode != wpr_modes.WPR_RECORD:
+ if page.archive_path and os.path.isfile(page.archive_path):
+ possible_browser.options.wpr_mode = wpr_modes.WPR_REPLAY
+ else:
+ possible_browser.options.wpr_mode = wpr_modes.WPR_OFF
+ results_for_current_run = results
+ if state.first_page[page] and test.discard_first_result:
+ # If discarding results, substitute a dummy object.
+ results_for_current_run = page_measurement_results.PageMeasurementResults()
+ results_for_current_run.StartTest(page)
+ tries = 3
+ while tries:
+ try:
+ state.StartBrowser(test, page_set, page, possible_browser,
+ credentials_path, page.archive_path)
+
+ _WaitForThermalThrottlingIfNeeded(state.browser.platform)
+
+ if options.profiler:
+ state.StartProfiling(page, options)
+
+ expectation = expectations.GetExpectationForPage(
+ state.browser.platform, page)
+
+ try:
+ _RunPage(test, page, state, expectation,
+ results_for_current_run, options)
+ _CheckThermalThrottling(state.browser.platform)
+ except exceptions.TabCrashException:
+ _LogStackTrace('Tab crashed: %s' % page.url, state.browser)
+ state.StopBrowser()
+
+ if options.profiler:
+ state.StopProfiling()
+
+ if test.NeedsBrowserRestartAfterEachRun(state.tab):
+ state.StopBrowser()
+
+ break
+ except exceptions.BrowserGoneException:
+ _LogStackTrace('Browser crashed', state.browser)
+ logging.warning('Lost connection to browser. Retrying.')
+ state.StopBrowser()
+ tries -= 1
+ if not tries:
+ logging.error('Lost connection to browser 3 times. Failing.')
+ raise
+ results_for_current_run.StopTest(page)
+
+
+def Run(test, page_set, expectations, options):
+ """Runs a given test against a given page_set with the given options."""
+ results = test.PrepareResults(options)
+
+ # Create a possible_browser with the given options.
+ test.CustomizeBrowserOptions(options)
+ if options.profiler:
+ profiler_class = profiler_finder.FindProfiler(options.profiler)
+ profiler_class.CustomizeBrowserOptions(options)
+ try:
+ possible_browser = browser_finder.FindBrowser(options)
+ except browser_finder.BrowserTypeRequiredException, e:
+ sys.stderr.write(str(e) + '\n')
+ sys.exit(1)
+ if not possible_browser:
+ sys.stderr.write(
+ 'No browser found. Available browsers:\n' +
+ '\n'.join(browser_finder.GetAllAvailableBrowserTypes(options)) + '\n')
+ sys.exit(1)
+
+ # Reorder page set based on options.
+ pages = _ShuffleAndFilterPageSet(page_set, options)
+
+ if (not options.allow_live_sites and
+ options.wpr_mode != wpr_modes.WPR_RECORD):
+ pages = _CheckArchives(page_set, pages, results)
+
+ # Verify credentials path.
+ credentials_path = None
+ if page_set.credentials_path:
+ credentials_path = os.path.join(os.path.dirname(page_set.file_path),
+ page_set.credentials_path)
+ if not os.path.exists(credentials_path):
+ credentials_path = None
+
+ # Set up user agent.
+ if page_set.user_agent_type:
+ options.browser_user_agent_type = page_set.user_agent_type
+
+ for page in pages:
+ test.CustomizeBrowserOptionsForPage(page, possible_browser.options)
+
+ for page in list(pages):
+ if not test.CanRunForPage(page):
+ logging.warning('Skipping test: it cannot run for %s', page.url)
+ results.AddSkip(page, 'Test cannot run')
+ pages.remove(page)
+
+ if not pages:
+ return results
+
+ state = _RunState()
+ # TODO(dtu): Move results creation and results_for_current_run into RunState.
+
+ try:
+ test.WillRunTest(state.tab)
+ state.repeat_state = page_runner_repeat.PageRunnerRepeatState(
+ options.repeat_options)
+
+ state.repeat_state.WillRunPageSet()
+ while state.repeat_state.ShouldRepeatPageSet():
+ for page in pages:
+ state.repeat_state.WillRunPage()
+ while state.repeat_state.ShouldRepeatPage():
+ # execute test on page
+ _PrepareAndRunPage(test, page_set, expectations, options, page,
+ credentials_path, possible_browser, results, state)
+ state.repeat_state.DidRunPage()
+ state.repeat_state.DidRunPageSet()
+
+ test.DidRunTest(state.tab, results)
+ finally:
+ state.StopBrowser()
+
+ return results
+
+
+def _ShuffleAndFilterPageSet(page_set, options):
+ if options.pageset_shuffle_order_file and not options.pageset_shuffle:
+ raise Exception('--pageset-shuffle-order-file requires --pageset-shuffle.')
+
+ if options.pageset_shuffle_order_file:
+ return page_set.ReorderPageSet(options.pageset_shuffle_order_file)
+
+ page_filter = page_filter_module.PageFilter(options)
+ pages = [page for page in page_set.pages[:]
+ if not page.disabled and page_filter.IsSelected(page)]
+
+ if options.pageset_shuffle:
+ random.Random().shuffle(pages)
+
+ return pages
+
+
+def _CheckArchives(page_set, pages, results):
+ """Returns a subset of pages that are local or have WPR archives.
+
+ Logs warnings if any are missing."""
+ page_set_has_live_sites = False
+ for page in pages:
+ if not page.is_local:
+ page_set_has_live_sites = True
+ break
+
+ # Potential problems with the entire page set.
+ if page_set_has_live_sites:
+ if not page_set.archive_data_file:
+ logging.warning('The page set is missing an "archive_data_file" '
+ 'property. Skipping any live sites. To include them, '
+ 'pass the flag --allow-live-sites.')
+ if not page_set.wpr_archive_info:
+ logging.warning('The archive info file is missing. '
+ 'To fix this, either add svn-internal to your '
+ '.gclient using http://goto/read-src-internal, '
+ 'or create a new archive using record_wpr.')
+
+ # Potential problems with individual pages.
+ pages_missing_archive_path = []
+ pages_missing_archive_data = []
+
+ for page in pages:
+ if page.is_local:
+ continue
+
+ if not page.archive_path:
+ pages_missing_archive_path.append(page)
+ elif not os.path.isfile(page.archive_path):
+ pages_missing_archive_data.append(page)
+
+ if pages_missing_archive_path:
+ logging.warning('The page set archives for some pages do not exist. '
+ 'Skipping those pages. To fix this, record those pages '
+ 'using record_wpr. To ignore this warning and run '
+ 'against live sites, pass the flag --allow-live-sites.')
+ if pages_missing_archive_data:
+ logging.warning('The page set archives for some pages are missing. '
+ 'Someone forgot to check them in, or they were deleted. '
+ 'Skipping those pages. To fix this, record those pages '
+ 'using record_wpr. To ignore this warning and run '
+ 'against live sites, pass the flag --allow-live-sites.')
+
+ for page in pages_missing_archive_path + pages_missing_archive_data:
+ results.StartTest(page)
+ results.AddErrorMessage(page, 'Page set archive doesn\'t exist.')
+ results.StopTest(page)
+
+ return [page for page in pages if page not in
+ pages_missing_archive_path + pages_missing_archive_data]
+
+
+def _RunPage(test, page, state, expectation, results, options):
+ logging.info('Running %s' % page.url)
+
+ page_state = PageState()
+ tab = state.tab
+
+ def ProcessError():
+ logging.error('%s:\n%s', page.url, traceback.format_exc())
+ if expectation == 'fail':
+ logging.info('Error was expected\n')
+ results.AddSuccess(page)
+ else:
+ results.AddError(page, sys.exc_info())
+
+ try:
+ page_state.PreparePage(page, tab, test)
+ if state.repeat_state.ShouldNavigate(options.skip_navigate_on_repeat):
+ page_state.ImplicitPageNavigation(page, tab, test)
+ test.Run(options, page, tab, results)
+ util.CloseConnections(tab)
+ except page_test.Failure:
+ logging.warning('%s:\n%s', page.url, traceback.format_exc())
+ if expectation == 'fail':
+ logging.info('Failure was expected\n')
+ results.AddSuccess(page)
+ else:
+ results.AddFailure(page, sys.exc_info())
+ except (util.TimeoutException, exceptions.LoginException,
+ exceptions.ProfilingException):
+ ProcessError()
+ except (exceptions.TabCrashException, exceptions.BrowserGoneException):
+ ProcessError()
+ # Run() catches these exceptions to relaunch the tab/browser, so re-raise.
+ raise
+ except Exception:
+ raise
+ else:
+ if expectation == 'fail':
+ logging.warning('%s was expected to fail, but passed.\n', page.url)
+ results.AddSuccess(page)
+ finally:
+ page_state.CleanUpPage(page, tab)
+
+
+def _GetSequentialFileName(base_name):
+ """Returns the next sequential file name based on |base_name| and the
+ existing files."""
+ index = 0
+ while True:
+ output_name = '%s_%03d' % (base_name, index)
+ if not glob.glob(output_name + '.*'):
+ break
+ index = index + 1
+ return output_name
+
+
+def _WaitForThermalThrottlingIfNeeded(platform):
+ if not platform.CanMonitorThermalThrottling():
+ return
+ thermal_throttling_retry = 0
+ while (platform.IsThermallyThrottled() and
+ thermal_throttling_retry < 3):
+ logging.warning('Thermally throttled, waiting (%d)...',
+ thermal_throttling_retry)
+ thermal_throttling_retry += 1
+ time.sleep(thermal_throttling_retry * 2)
+
+ if thermal_throttling_retry and platform.IsThermallyThrottled():
+ logging.error('Device is thermally throttled before running '
+ 'performance tests, results will vary.')
+
+
+def _CheckThermalThrottling(platform):
+ if not platform.CanMonitorThermalThrottling():
+ return
+ if platform.HasBeenThermallyThrottled():
+ logging.error('Device has been thermally throttled during '
+ 'performance tests, results will vary.')
diff --git a/chromium/tools/telemetry/telemetry/page/page_runner_repeat.py b/chromium/tools/telemetry/telemetry/page/page_runner_repeat.py
new file mode 100644
index 00000000000..5c80f5c68fd
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_runner_repeat.py
@@ -0,0 +1,61 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import time
+
+
+class PageRunnerRepeatState(object):
+ def __init__(self, repeat_options):
+ self.pageset_start_time = None
+ self.pageset_iters = None
+ self.page_start_time = None
+ self.page_iters = None
+
+ self.options = repeat_options
+
+ def WillRunPage(self):
+ """Runs before we start repeating a page"""
+ self.page_start_time = time.time()
+ self.page_iters = 0
+
+ def WillRunPageSet(self):
+ """Runs before we start repeating a pageset"""
+ self.pageset_start_time = time.time()
+ self.pageset_iters = 0
+
+ def DidRunPage(self):
+ """Runs after each completion of a page iteration"""
+ self.page_iters += 1
+
+ def DidRunPageSet(self):
+ """Runs after each completion of a pageset iteration"""
+ self.pageset_iters += 1
+
+ def ShouldRepeatPageSet(self):
+ """Returns True if we need to repeat this pageset more times"""
+ if (self.options.pageset_repeat_secs and
+ time.time() - self.pageset_start_time >
+ self.options.pageset_repeat_secs):
+ return False
+ elif (not self.options.pageset_repeat_secs and
+ self.pageset_iters >= self.options.pageset_repeat_iters):
+ return False
+ return True
+
+ def ShouldRepeatPage(self):
+ """Returns True if we need to repeat this page more times"""
+ if (self.options.page_repeat_secs and
+ time.time() - self.page_start_time > self.options.page_repeat_secs):
+ return False
+ elif (not self.options.page_repeat_secs and
+ self.page_iters >= self.options.page_repeat_iters):
+ return False
+ return True
+
+ def ShouldNavigate(self, skip_navigate_on_repeat):
+ """Returns whether we are navigating to pages on page repeats.
+
+ Always navigate on the first iteration of a page and on every new pageset.
+ """
+ return self.page_iters == 0 or not skip_navigate_on_repeat \ No newline at end of file
diff --git a/chromium/tools/telemetry/telemetry/page/page_runner_unittest.py b/chromium/tools/telemetry/telemetry/page/page_runner_unittest.py
new file mode 100644
index 00000000000..815683b56c6
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_runner_unittest.py
@@ -0,0 +1,280 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import tempfile
+import unittest
+
+from telemetry.core import user_agent
+from telemetry.core import util
+from telemetry.page import page as page_module
+from telemetry.page import page_measurement
+from telemetry.page import page_set
+from telemetry.page import page_test
+from telemetry.page import page_runner
+from telemetry.unittest import options_for_unittests
+from telemetry.page import test_expectations
+
+SIMPLE_CREDENTIALS_STRING = """
+{
+ "test": {
+ "username": "example",
+ "password": "asdf"
+ }
+}
+"""
+class StubCredentialsBackend(object):
+ def __init__(self, login_return_value):
+ self.did_get_login = False
+ self.did_get_login_no_longer_needed = False
+ self.login_return_value = login_return_value
+
+ @property
+ def credentials_type(self): # pylint: disable=R0201
+ return 'test'
+
+ def LoginNeeded(self, tab, config): # pylint: disable=W0613
+ self.did_get_login = True
+ return self.login_return_value
+
+ def LoginNoLongerNeeded(self, tab): # pylint: disable=W0613
+ self.did_get_login_no_longer_needed = True
+
+class PageRunnerTests(unittest.TestCase):
+ # TODO(nduca): Move the basic "test failed, test succeeded" tests from
+ # page_measurement_unittest to here.
+
+ def testHandlingOfCrashedTab(self):
+ ps = page_set.PageSet()
+ expectations = test_expectations.TestExpectations()
+ page1 = page_module.Page('chrome://crash', ps)
+ ps.pages.append(page1)
+
+ class Test(page_test.PageTest):
+ def RunTest(self, *args):
+ pass
+
+ options = options_for_unittests.GetCopy()
+ options.output_format = 'none'
+ results = page_runner.Run(Test('RunTest'), ps, expectations, options)
+ self.assertEquals(0, len(results.successes))
+ self.assertEquals(0, len(results.failures))
+ self.assertEquals(1, len(results.errors))
+
+ def testHandlingOfCrashedTabWithExpectedFailure(self):
+ ps = page_set.PageSet()
+ expectations = test_expectations.TestExpectations()
+ expectations.Fail('chrome://crash')
+ page1 = page_module.Page('chrome://crash', ps)
+ ps.pages.append(page1)
+
+ class Test(page_test.PageTest):
+ def RunTest(self, *args):
+ pass
+
+ options = options_for_unittests.GetCopy()
+ options.output_format = 'none'
+ results = page_runner.Run(Test('RunTest'), ps, expectations, options)
+ self.assertEquals(1, len(results.successes))
+ self.assertEquals(0, len(results.failures))
+ self.assertEquals(0, len(results.errors))
+
+ def testDiscardFirstResult(self):
+ ps = page_set.PageSet()
+ expectations = test_expectations.TestExpectations()
+ ps.pages.append(page_module.Page(
+ 'file:///' + os.path.join(util.GetUnittestDataDir(), 'blank.html'),
+ ps,
+ base_dir=os.path.dirname(__file__)))
+ ps.pages.append(page_module.Page(
+ 'file:///' + os.path.join(util.GetUnittestDataDir(), 'blank.html'),
+ ps,
+ base_dir=os.path.dirname(__file__)))
+
+ class Measurement(page_measurement.PageMeasurement):
+ @property
+ def discard_first_result(self):
+ return True
+ def MeasurePage(self, *args):
+ pass
+
+ options = options_for_unittests.GetCopy()
+ options.output_format = 'none'
+ options.reset_html_results = None
+
+ options.repeat_options.page_repeat_iters = 1
+ options.repeat_options.pageset_repeat_iters = 1
+ results = page_runner.Run(Measurement(), ps, expectations, options)
+ self.assertEquals(0, len(results.successes))
+ self.assertEquals(0, len(results.failures))
+
+ options.repeat_options.page_repeat_iters = 1
+ options.repeat_options.pageset_repeat_iters = 2
+ results = page_runner.Run(Measurement(), ps, expectations, options)
+ self.assertEquals(2, len(results.successes))
+ self.assertEquals(0, len(results.failures))
+
+ options.repeat_options.page_repeat_iters = 2
+ options.repeat_options.pageset_repeat_iters = 1
+ results = page_runner.Run(Measurement(), ps, expectations, options)
+ self.assertEquals(2, len(results.successes))
+ self.assertEquals(0, len(results.failures))
+
+ options.output_format = 'html'
+ options.repeat_options.page_repeat_iters = 1
+ options.repeat_options.pageset_repeat_iters = 1
+ results = page_runner.Run(Measurement(), ps, expectations, options)
+ self.assertEquals(0, len(results.successes))
+ self.assertEquals(0, len(results.failures))
+
+ def testCredentialsWhenLoginFails(self):
+ credentials_backend = StubCredentialsBackend(login_return_value=False)
+ did_run = self.runCredentialsTest(credentials_backend)
+ assert credentials_backend.did_get_login == True
+ assert credentials_backend.did_get_login_no_longer_needed == False
+ assert did_run == False
+
+ def testCredentialsWhenLoginSucceeds(self):
+ credentials_backend = StubCredentialsBackend(login_return_value=True)
+ did_run = self.runCredentialsTest(credentials_backend)
+ assert credentials_backend.did_get_login == True
+ assert credentials_backend.did_get_login_no_longer_needed == True
+ assert did_run
+
+ def runCredentialsTest(self, # pylint: disable=R0201
+ credentials_backend):
+ ps = page_set.PageSet()
+ expectations = test_expectations.TestExpectations()
+ page = page_module.Page(
+ 'file:///' + os.path.join(util.GetUnittestDataDir(), 'blank.html'),
+ ps,
+ base_dir=os.path.dirname(__file__))
+ page.credentials = "test"
+ ps.pages.append(page)
+
+ did_run = [False]
+
+ try:
+ with tempfile.NamedTemporaryFile(delete=False) as f:
+ f.write(SIMPLE_CREDENTIALS_STRING)
+ ps.credentials_path = f.name
+
+ class TestThatInstallsCredentialsBackend(page_test.PageTest):
+ def __init__(self, credentials_backend):
+ super(TestThatInstallsCredentialsBackend, self).__init__('RunTest')
+ self._credentials_backend = credentials_backend
+
+ def DidStartBrowser(self, browser):
+ browser.credentials.AddBackend(self._credentials_backend)
+
+ def RunTest(self, page, tab, results): # pylint: disable=W0613,R0201
+ did_run[0] = True
+
+ test = TestThatInstallsCredentialsBackend(credentials_backend)
+ options = options_for_unittests.GetCopy()
+ options.output_format = 'none'
+ page_runner.Run(test, ps, expectations, options)
+ finally:
+ os.remove(f.name)
+
+ return did_run[0]
+
+ def testUserAgent(self):
+ ps = page_set.PageSet()
+ expectations = test_expectations.TestExpectations()
+ page = page_module.Page(
+ 'file:///' + os.path.join(util.GetUnittestDataDir(), 'blank.html'),
+ ps,
+ base_dir=os.path.dirname(__file__))
+ ps.pages.append(page)
+ ps.user_agent_type = 'tablet'
+
+ class TestUserAgent(page_test.PageTest):
+ def RunTest(self, page, tab, results): # pylint: disable=W0613,R0201
+ actual_user_agent = tab.EvaluateJavaScript('window.navigator.userAgent')
+ expected_user_agent = user_agent.UA_TYPE_MAPPING['tablet']
+ assert actual_user_agent.strip() == expected_user_agent
+
+ # This is so we can check later that the test actually made it into this
+ # function. Previously it was timing out before even getting here, which
+ # should fail, but since it skipped all the asserts, it slipped by.
+ self.hasRun = True # pylint: disable=W0201
+
+ test = TestUserAgent('RunTest')
+ options = options_for_unittests.GetCopy()
+ options.output_format = 'none'
+ page_runner.Run(test, ps, expectations, options)
+
+ self.assertTrue(hasattr(test, 'hasRun') and test.hasRun)
+
+ # Ensure that page_runner forces exactly 1 tab before running a page.
+ def testOneTab(self):
+ ps = page_set.PageSet()
+ expectations = test_expectations.TestExpectations()
+ page = page_module.Page(
+ 'file:///' + os.path.join(util.GetUnittestDataDir(), 'blank.html'),
+ ps,
+ base_dir=os.path.dirname(__file__))
+ ps.pages.append(page)
+
+ class TestOneTab(page_test.PageTest):
+ def __init__(self,
+ test_method_name,
+ action_name_to_run='',
+ needs_browser_restart_after_each_run=False):
+ super(TestOneTab, self).__init__(test_method_name, action_name_to_run,
+ needs_browser_restart_after_each_run)
+ self._browser = None
+
+ def DidStartBrowser(self, browser):
+ self._browser = browser
+ if self._browser.supports_tab_control:
+ self._browser.tabs.New()
+
+ def RunTest(self, page, tab, results): # pylint: disable=W0613,R0201
+ if not self._browser.supports_tab_control:
+ logging.warning('Browser does not support tab control, skipping test')
+ return
+ assert len(self._browser.tabs) == 1
+
+ test = TestOneTab('RunTest')
+ options = options_for_unittests.GetCopy()
+ options.output_format = 'none'
+ page_runner.Run(test, ps, expectations, options)
+
+ # Ensure that page_runner allows the test to customize the browser before it
+ # launches.
+ def testBrowserBeforeLaunch(self):
+ ps = page_set.PageSet()
+ expectations = test_expectations.TestExpectations()
+ page = page_module.Page(
+ 'file:///' + os.path.join(util.GetUnittestDataDir(), 'blank.html'),
+ ps,
+ base_dir=os.path.dirname(__file__))
+ ps.pages.append(page)
+
+ class TestBeforeLaunch(page_test.PageTest):
+ def __init__(self,
+ test_method_name,
+ action_name_to_run=''):
+ super(TestBeforeLaunch, self).__init__(
+ test_method_name, action_name_to_run, False)
+ self._did_call_will_start = False
+ self._did_call_did_start = False
+
+ def WillStartBrowser(self, browser):
+ self._did_call_will_start = True
+ # TODO(simonjam): Test that the profile is available.
+
+ def DidStartBrowser(self, browser):
+ assert self._did_call_will_start
+ self._did_call_did_start = True
+
+ def RunTest(self, page, tab, results): # pylint: disable=W0613,R0201
+ assert self._did_call_did_start
+
+ test = TestBeforeLaunch('RunTest')
+ options = options_for_unittests.GetCopy()
+ options.output_format = 'none'
+ page_runner.Run(test, ps, expectations, options)
diff --git a/chromium/tools/telemetry/telemetry/page/page_set.py b/chromium/tools/telemetry/telemetry/page/page_set.py
new file mode 100644
index 00000000000..807c365532b
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_set.py
@@ -0,0 +1,122 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import csv
+import json
+import os
+
+from telemetry.page import cloud_storage
+from telemetry.page import page as page_module
+from telemetry.page import page_set_archive_info
+
+class PageSet(object):
+ def __init__(self, file_path='', attributes=None):
+ self.description = ''
+ self.archive_data_file = ''
+ self.file_path = file_path
+ self.credentials_path = None
+ self.user_agent_type = None
+ self.make_javascript_deterministic = True
+
+ if attributes:
+ for k, v in attributes.iteritems():
+ setattr(self, k, v)
+
+ self.pages = []
+
+ if self.archive_data_file:
+ self.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile(
+ os.path.join(self._base_dir, self.archive_data_file), file_path)
+ else:
+ self.wpr_archive_info = None
+
+ @classmethod
+ def FromFile(cls, file_path):
+ with open(file_path, 'r') as f:
+ contents = f.read()
+ data = json.loads(contents)
+ return cls.FromDict(data, file_path)
+
+ @classmethod
+ def FromDict(cls, data, file_path):
+ page_set = cls(file_path, data)
+
+ for page_attributes in data['pages']:
+ url = page_attributes.pop('url')
+
+ page = page_module.Page(url, page_set, attributes=page_attributes,
+ base_dir=page_set._base_dir) # pylint: disable=W0212
+ page_set.pages.append(page)
+
+ all_serving_dirs = set()
+ for page in page_set:
+ if page.is_file:
+ serving_dirs, _ = page.serving_dirs_and_file
+ if isinstance(serving_dirs, list):
+ all_serving_dirs |= set(serving_dirs)
+ else:
+ all_serving_dirs.add(serving_dirs)
+ for serving_dir in all_serving_dirs:
+ for dirpath, _, filenames in os.walk(serving_dir):
+ for filename in filenames:
+ file_path, extension = os.path.splitext(
+ os.path.join(dirpath, filename))
+ if extension != '.sha1':
+ continue
+ cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, file_path)
+
+ return page_set
+
+ @property
+ def _base_dir(self):
+ if os.path.isdir(self.file_path):
+ return self.file_path
+ else:
+ return os.path.dirname(self.file_path)
+
+ def ContainsOnlyFileURLs(self):
+ for page in self.pages:
+ if not page.is_file:
+ return False
+ return True
+
+ def ReorderPageSet(self, results_file):
+ """Reorders this page set based on the results of a past run."""
+ page_set_dict = {}
+ for page in self.pages:
+ page_set_dict[page.url] = page
+
+ pages = []
+ with open(results_file, 'rb') as csv_file:
+ csv_reader = csv.reader(csv_file)
+ csv_header = csv_reader.next()
+
+ if 'url' not in csv_header:
+ raise Exception('Unusable results_file.')
+
+ url_index = csv_header.index('url')
+
+ for csv_row in csv_reader:
+ if csv_row[url_index] in page_set_dict:
+ pages.append(page_set_dict[csv_row[url_index]])
+ else:
+ raise Exception('Unusable results_file.')
+
+ return pages
+
+ def WprFilePathForPage(self, page):
+ if not self.wpr_archive_info:
+ return None
+ return self.wpr_archive_info.WprFilePathForPage(page)
+
+ def __iter__(self):
+ return self.pages.__iter__()
+
+ def __len__(self):
+ return len(self.pages)
+
+ def __getitem__(self, key):
+ return self.pages[key]
+
+ def __setitem__(self, key, value):
+ self.pages[key] = value
diff --git a/chromium/tools/telemetry/telemetry/page/page_set_archive_info.py b/chromium/tools/telemetry/telemetry/page/page_set_archive_info.py
new file mode 100644
index 00000000000..adb76250dd9
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_set_archive_info.py
@@ -0,0 +1,145 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import json
+import logging
+import os
+import re
+import shutil
+
+from telemetry.page import cloud_storage
+
+
+def _UpdateHashFile(file_path):
+ with open(file_path + '.sha1', 'wb') as f:
+ f.write(cloud_storage.GetHash(file_path))
+ f.flush()
+
+
+class PageSetArchiveInfo(object):
+ def __init__(self, archive_data_file_path, page_set_file_path, data):
+ self._archive_data_file_path = archive_data_file_path
+ self._archive_data_file_dir = os.path.dirname(archive_data_file_path)
+ # Back pointer to the page set file.
+ self._page_set_file_path = page_set_file_path
+
+ for archive_path in data['archives']:
+ cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, archive_path)
+
+ # Map from the relative path (as it appears in the metadata file) of the
+ # .wpr file to a list of urls it supports.
+ self._wpr_file_to_urls = data['archives']
+
+ # Map from the page url to a relative path (as it appears in the metadata
+ # file) of the .wpr file.
+ self._url_to_wpr_file = dict()
+ # Find out the wpr file names for each page.
+ for wpr_file in data['archives']:
+ page_urls = data['archives'][wpr_file]
+ for url in page_urls:
+ self._url_to_wpr_file[url] = wpr_file
+ self.temp_target_wpr_file_path = None
+
+ @classmethod
+ def FromFile(cls, file_path, page_set_file_path):
+ cloud_storage.GetIfChanged(cloud_storage.DEFAULT_BUCKET, file_path)
+
+ if os.path.exists(file_path):
+ with open(file_path, 'r') as f:
+ data = json.load(f)
+ return cls(file_path, page_set_file_path, data)
+ return cls(file_path, page_set_file_path, {'archives': {}})
+
+ def WprFilePathForPage(self, page):
+ if self.temp_target_wpr_file_path:
+ return self.temp_target_wpr_file_path
+ wpr_file = self._url_to_wpr_file.get(page.url, None)
+ if wpr_file:
+ return self._WprFileNameToPath(wpr_file)
+ return None
+
+ def AddNewTemporaryRecording(self, temp_target_wpr_file_path):
+ self.temp_target_wpr_file_path = temp_target_wpr_file_path
+
+ def AddRecordedPages(self, urls):
+ (target_wpr_file, target_wpr_file_path) = self._NextWprFileName()
+ for url in urls:
+ self._SetWprFileForPage(url, target_wpr_file)
+ shutil.move(self.temp_target_wpr_file_path, target_wpr_file_path)
+ _UpdateHashFile(target_wpr_file_path)
+ self._WriteToFile()
+ self._DeleteAbandonedWprFiles()
+
+ def _DeleteAbandonedWprFiles(self):
+ # Update the metadata so that the abandoned wpr files don't have empty url
+ # arrays.
+ abandoned_wpr_files = self._AbandonedWprFiles()
+ for wpr_file in abandoned_wpr_files:
+ del self._wpr_file_to_urls[wpr_file]
+ # Don't fail if we're unable to delete some of the files.
+ wpr_file_path = self._WprFileNameToPath(wpr_file)
+ try:
+ os.remove(wpr_file_path)
+ except Exception:
+ logging.warning('Failed to delete file: %s' % wpr_file_path)
+
+ def _AbandonedWprFiles(self):
+ abandoned_wpr_files = []
+ for wpr_file, urls in self._wpr_file_to_urls.iteritems():
+ if not urls:
+ abandoned_wpr_files.append(wpr_file)
+ return abandoned_wpr_files
+
+ def _WriteToFile(self):
+ """Writes the metadata into the file passed as constructor parameter."""
+ metadata = dict()
+ metadata['description'] = (
+ 'Describes the Web Page Replay archives for a page set. Don\'t edit by '
+ 'hand! Use record_wpr for updating.')
+ # Pointer from the metadata to the page set .json file.
+ metadata['page_set'] = os.path.relpath(self._page_set_file_path,
+ self._archive_data_file_dir)
+ metadata['archives'] = self._wpr_file_to_urls.copy()
+ # Don't write data for abandoned archives.
+ abandoned_wpr_files = self._AbandonedWprFiles()
+ for wpr_file in abandoned_wpr_files:
+ del metadata['archives'][wpr_file]
+
+ with open(self._archive_data_file_path, 'w') as f:
+ json.dump(metadata, f, indent=4)
+ f.flush()
+ _UpdateHashFile(self._archive_data_file_path)
+
+ def _WprFileNameToPath(self, wpr_file):
+ return os.path.abspath(os.path.join(self._archive_data_file_dir, wpr_file))
+
+ def _NextWprFileName(self):
+ """Creates a new file name for a wpr archive file."""
+ # The names are of the format "some_thing_number.wpr". Read the numbers.
+ highest_number = -1
+ base = None
+ for wpr_file in self._wpr_file_to_urls:
+ match = re.match(r'(?P<BASE>.*)_(?P<NUMBER>[0-9]+)\.wpr', wpr_file)
+ if not match:
+ raise Exception('Illegal wpr file name ' + wpr_file)
+ highest_number = max(int(match.groupdict()['NUMBER']), highest_number)
+ if base and match.groupdict()['BASE'] != base:
+ raise Exception('Illegal wpr file name ' + wpr_file +
+ ', doesn\'t begin with ' + base)
+ base = match.groupdict()['BASE']
+ if not base:
+ # If we're creating a completely new info file, use the base name of the
+ # page set file.
+ base = os.path.splitext(os.path.basename(self._page_set_file_path))[0]
+ new_filename = '%s_%03d.wpr' % (base, highest_number + 1)
+ return new_filename, self._WprFileNameToPath(new_filename)
+
+ def _SetWprFileForPage(self, url, wpr_file):
+ """For modifying the metadata when we're going to record a new archive."""
+ old_wpr_file = self._url_to_wpr_file.get(url, None)
+ if old_wpr_file:
+ self._wpr_file_to_urls[old_wpr_file].remove(url)
+ self._url_to_wpr_file[url] = wpr_file
+ if wpr_file not in self._wpr_file_to_urls:
+ self._wpr_file_to_urls[wpr_file] = []
+ self._wpr_file_to_urls[wpr_file].append(url)
diff --git a/chromium/tools/telemetry/telemetry/page/page_set_archive_info_unittest.py b/chromium/tools/telemetry/telemetry/page/page_set_archive_info_unittest.py
new file mode 100644
index 00000000000..e72f76bcc7e
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_set_archive_info_unittest.py
@@ -0,0 +1,161 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import shutil
+import tempfile
+import unittest
+
+from telemetry.page import cloud_storage
+from telemetry.page import page_set_archive_info
+
+
+class MockPage(object):
+ def __init__(self, url):
+ self.url = url
+
+
+url1 = 'http://www.foo.com/'
+url2 = 'http://www.bar.com/'
+url3 = 'http://www.baz.com/'
+recording1 = 'data_001.wpr'
+recording2 = 'data_002.wpr'
+archive_info_contents = ("""
+{
+"archives": {
+ "%s": ["%s", "%s"],
+ "%s": ["%s"]
+}
+}
+""" % (recording1, url1, url2, recording2, url3))
+page1 = MockPage(url1)
+page2 = MockPage(url2)
+page3 = MockPage(url3)
+
+
+class TestPageSetArchiveInfo(unittest.TestCase):
+ def setUp(self):
+ self.tmp_dir = tempfile.mkdtemp()
+ # Write the metadata.
+ self.page_set_archive_info_file = os.path.join(self.tmp_dir, 'info.json')
+ with open(self.page_set_archive_info_file, 'w') as f:
+ f.write(archive_info_contents)
+
+ # Write the existing .wpr files.
+ for i in [1, 2]:
+ with open(os.path.join(self.tmp_dir, ('data_00%d.wpr' % i)), 'w') as f:
+ f.write(archive_info_contents)
+
+ # Create the PageSetArchiveInfo object to be tested.
+ self.archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile(
+ self.page_set_archive_info_file,
+ os.path.join(tempfile.gettempdir(), 'pageset.json'))
+
+ def tearDown(self):
+ shutil.rmtree(self.tmp_dir)
+
+ def assertCorrectHashFile(self, file_path):
+ self.assertTrue(os.path.exists(file_path + '.sha1'))
+ with open(file_path + '.sha1', 'rb') as f:
+ self.assertEquals(cloud_storage.GetHash(file_path), f.read())
+
+ def testReadingArchiveInfo(self):
+ self.assertEquals(recording1, os.path.basename(
+ self.archive_info.WprFilePathForPage(page1)))
+ self.assertEquals(recording1, os.path.basename(
+ self.archive_info.WprFilePathForPage(page2)))
+ self.assertEquals(recording2, os.path.basename(
+ self.archive_info.WprFilePathForPage(page3)))
+
+ def testModifications(self):
+ recording1_path = os.path.join(self.tmp_dir, recording1)
+ recording2_path = os.path.join(self.tmp_dir, recording2)
+
+ new_recording1 = os.path.join(self.tmp_dir, 'data_003.wpr')
+ new_temp_recording = os.path.join(self.tmp_dir, 'recording.wpr')
+ with open(new_temp_recording, 'w') as f:
+ f.write('wpr data')
+
+ self.archive_info.AddNewTemporaryRecording(new_temp_recording)
+
+ self.assertEquals(new_temp_recording,
+ self.archive_info.WprFilePathForPage(page1))
+ self.assertEquals(new_temp_recording,
+ self.archive_info.WprFilePathForPage(page2))
+ self.assertEquals(new_temp_recording,
+ self.archive_info.WprFilePathForPage(page3))
+
+ self.archive_info.AddRecordedPages([page2.url])
+
+ self.assertTrue(os.path.exists(new_recording1))
+ self.assertFalse(os.path.exists(new_temp_recording))
+
+ self.assertTrue(os.path.exists(recording1_path))
+ self.assertTrue(os.path.exists(recording2_path))
+ self.assertCorrectHashFile(new_recording1)
+
+ new_recording2 = os.path.join(self.tmp_dir, 'data_004.wpr')
+ with open(new_temp_recording, 'w') as f:
+ f.write('wpr data')
+
+ self.archive_info.AddNewTemporaryRecording(new_temp_recording)
+ self.archive_info.AddRecordedPages([page3.url])
+
+ self.assertTrue(os.path.exists(new_recording2))
+ self.assertCorrectHashFile(new_recording2)
+ self.assertFalse(os.path.exists(new_temp_recording))
+
+ self.assertTrue(os.path.exists(recording1_path))
+ # recording2 is no longer needed, so it was deleted.
+ self.assertFalse(os.path.exists(recording2_path))
+
+ def testCreatingNewArchiveInfo(self):
+ # Write only the page set without the corresponding metadata file.
+ page_set_contents = ("""
+ {
+ archive_data_file": "new-metadata.json",
+ "pages": [
+ {
+ "url": "%s",
+ }
+ ]
+ }""" % url1)
+
+ page_set_file = os.path.join(self.tmp_dir, 'new.json')
+ with open(page_set_file, 'w') as f:
+ f.write(page_set_contents)
+
+ self.page_set_archive_info_file = os.path.join(self.tmp_dir,
+ 'new-metadata.json')
+
+ # Create the PageSetArchiveInfo object to be tested.
+ self.archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile(
+ self.page_set_archive_info_file, page_set_file)
+
+ # Add a recording for all the pages.
+ new_temp_recording = os.path.join(self.tmp_dir, 'recording.wpr')
+ with open(new_temp_recording, 'w') as f:
+ f.write('wpr data')
+
+ self.archive_info.AddNewTemporaryRecording(new_temp_recording)
+
+ self.assertEquals(new_temp_recording,
+ self.archive_info.WprFilePathForPage(page1))
+
+ self.archive_info.AddRecordedPages([page1.url])
+
+ # Expected name for the recording (decided by PageSetArchiveInfo).
+ new_recording = os.path.join(self.tmp_dir, 'new_000.wpr')
+
+ self.assertTrue(os.path.exists(new_recording))
+ self.assertFalse(os.path.exists(new_temp_recording))
+ self.assertCorrectHashFile(new_recording)
+
+ # Check that the archive info was written correctly.
+ self.assertTrue(os.path.exists(self.page_set_archive_info_file))
+ read_archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile(
+ self.page_set_archive_info_file,
+ os.path.join(tempfile.gettempdir(), 'pageset.json'))
+ self.assertEquals(new_recording,
+ read_archive_info.WprFilePathForPage(page1))
+ self.assertCorrectHashFile(self.page_set_archive_info_file)
diff --git a/chromium/tools/telemetry/telemetry/page/page_set_unittest.py b/chromium/tools/telemetry/telemetry/page/page_set_unittest.py
new file mode 100644
index 00000000000..fdb2f0571ac
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_set_unittest.py
@@ -0,0 +1,59 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import tempfile
+import unittest
+
+from telemetry.page import page_set
+
+simple_archive_info = """
+{
+"archives": {
+ "data_01.wpr": ["http://www.foo.com/"],
+ "data_02.wpr": ["http://www.bar.com/"]
+}
+}
+"""
+
+simple_set = """
+{"description": "hello",
+ "archive_data_file": "%s",
+ "pages": [
+ {"url": "http://www.foo.com/"},
+ {"url": "http://www.bar.com/"}
+ ]
+}
+"""
+
+class TestPageSet(unittest.TestCase):
+ def testSimpleSet(self):
+ try:
+ with tempfile.NamedTemporaryFile(delete=False) as f:
+ f.write(simple_archive_info)
+
+ with tempfile.NamedTemporaryFile(delete=False) as f2:
+ f2.write(simple_set % f.name.replace('\\', '\\\\'))
+
+ ps = page_set.PageSet.FromFile(f2.name)
+ finally:
+ os.remove(f.name)
+ os.remove(f2.name)
+
+ self.assertEquals('hello', ps.description)
+ self.assertEquals(f.name, ps.archive_data_file)
+ self.assertEquals(2, len(ps.pages))
+ self.assertEquals('http://www.foo.com/', ps.pages[0].url)
+ self.assertEquals('http://www.bar.com/', ps.pages[1].url)
+ self.assertEquals('data_01.wpr', os.path.basename(ps.pages[0].archive_path))
+ self.assertEquals('data_02.wpr', os.path.basename(ps.pages[1].archive_path))
+
+ def testDirectoryFilePath(self):
+ directory_path = tempfile.mkdtemp()
+ try:
+ ps = page_set.PageSet.FromDict({'pages': [{'url': 'file:///test.html'}]},
+ directory_path)
+ finally:
+ os.rmdir(directory_path)
+
+ self.assertEquals(ps[0].base_dir, directory_path)
diff --git a/chromium/tools/telemetry/telemetry/page/page_test.py b/chromium/tools/telemetry/telemetry/page/page_test.py
new file mode 100644
index 00000000000..12940bd1dcc
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_test.py
@@ -0,0 +1,220 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+
+from telemetry.core import util
+from telemetry.page import gtest_test_results
+from telemetry.page import test_expectations
+from telemetry.page import page_test_results
+from telemetry.page.actions import all_page_actions
+from telemetry.page.actions import page_action
+
+def _GetActionFromData(action_data):
+ action_name = action_data['action']
+ action = all_page_actions.FindClassWithName(action_name)
+ if not action:
+ logging.critical('Could not find an action named %s.', action_name)
+ logging.critical('Check the page set for a typo and check the error '
+ 'log for possible Python loading/compilation errors.')
+ raise Exception('Action "%s" not found.' % action_name)
+ return action(action_data)
+
+def GetCompoundActionFromPage(page, action_name):
+ if not action_name:
+ return []
+
+ action_data_list = getattr(page, action_name)
+ if not isinstance(action_data_list, list):
+ action_data_list = [action_data_list]
+
+ action_list = []
+ for subaction_data in action_data_list:
+ subaction_name = subaction_data['action']
+ if hasattr(page, subaction_name):
+ subaction = GetCompoundActionFromPage(page, subaction_name)
+ else:
+ subaction = [_GetActionFromData(subaction_data)]
+ action_list += subaction * subaction_data.get('repeat', 1)
+ return action_list
+
+class Failure(Exception):
+ """Exception that can be thrown from PageMeasurement to indicate an
+ undesired but designed-for problem."""
+ pass
+
+class PageTest(object):
+ """A class styled on unittest.TestCase for creating page-specific tests."""
+
+ def __init__(self,
+ test_method_name,
+ action_name_to_run='',
+ needs_browser_restart_after_each_run=False,
+ discard_first_result=False,
+ clear_cache_before_each_run=False):
+ self.options = None
+ try:
+ self._test_method = getattr(self, test_method_name)
+ except AttributeError:
+ raise ValueError, 'No such method %s.%s' % (
+ self.__class_, test_method_name) # pylint: disable=E1101
+ self._action_name_to_run = action_name_to_run
+ self._needs_browser_restart_after_each_run = (
+ needs_browser_restart_after_each_run)
+ self._discard_first_result = discard_first_result
+ self._clear_cache_before_each_run = clear_cache_before_each_run
+
+ @property
+ def discard_first_result(self):
+ """When set to True, the first run of the test is discarded. This is
+ useful for cases where it's desirable to have some test resource cached so
+ the first run of the test can warm things up. """
+ return self._discard_first_result
+
+ @discard_first_result.setter
+ def discard_first_result(self, discard):
+ self._discard_first_result = discard
+
+ @property
+ def clear_cache_before_each_run(self):
+ """When set to True, the browser's disk and memory cache will be cleared
+ before each run."""
+ return self._clear_cache_before_each_run
+
+ def NeedsBrowserRestartAfterEachRun(self, tab): # pylint: disable=W0613
+ """Override to specify browser restart after each run."""
+ return self._needs_browser_restart_after_each_run
+
+ def AddCommandLineOptions(self, parser):
+ """Override to expose command-line options for this test.
+
+ The provided parser is an optparse.OptionParser instance and accepts all
+ normal results. The parsed options are available in Run as
+ self.options."""
+ pass
+
+ def CustomizeBrowserOptions(self, options):
+ """Override to add test-specific options to the BrowserOptions object"""
+ pass
+
+ def CustomizeBrowserOptionsForPage(self, page, options):
+ """Add options specific to the test and the given page."""
+ if not self.CanRunForPage(page):
+ return
+ for action in GetCompoundActionFromPage(page, self._action_name_to_run):
+ action.CustomizeBrowserOptions(options)
+
+ def WillStartBrowser(self, browser):
+ """Override to manipulate the browser environment before it launches."""
+ pass
+
+ def DidStartBrowser(self, browser):
+ """Override to customize the browser right after it has launched."""
+ pass
+
+ def CanRunForPage(self, page): #pylint: disable=W0613
+ """Override to customize if the test can be ran for the given page."""
+ return True
+
+ def WillRunTest(self, tab):
+ """Override to do operations before the page set(s) are navigated."""
+ pass
+
+ def DidRunTest(self, tab, results):
+ """Override to do operations after all page set(s) are completed.
+
+ This will occur before the browser is torn down.
+ """
+ pass
+
+ def DidStartHTTPServer(self, tab):
+ """Override to do operations after the HTTP server is started."""
+ pass
+
+ def WillNavigateToPage(self, page, tab):
+ """Override to do operations before the page is navigated."""
+ pass
+
+ def DidNavigateToPage(self, page, tab):
+ """Override to do operations right after the page is navigated, but before
+ any waiting for completion has occurred."""
+ pass
+
+ def WillRunAction(self, page, tab, action):
+ """Override to do operations before running the action on the page."""
+ pass
+
+ def DidRunAction(self, page, tab, action):
+ """Override to do operations after running the action on the page."""
+ pass
+
+ def CreatePageSet(self, args, options): # pylint: disable=W0613
+ """Override to make this test generate its own page set instead of
+ allowing arbitrary page sets entered from the command-line."""
+ return None
+
+ def CreateExpectations(self, page_set): # pylint: disable=W0613
+ """Override to make this test generate its own expectations instead of
+ any that may have been defined in the page set."""
+ return test_expectations.TestExpectations()
+
+ def AddOutputOptions(self, parser):
+ parser.add_option('--output-format',
+ default=self.output_format_choices[0],
+ choices=self.output_format_choices,
+ help='Output format. Defaults to "%%default". '
+ 'Can be %s.' % ', '.join(self.output_format_choices))
+
+ @property
+ def output_format_choices(self):
+ """Allowed output formats. The default is the first item in the list."""
+ return ['gtest', 'none']
+
+ def PrepareResults(self, options):
+ if not hasattr(options, 'output_format'):
+ options.output_format = self.output_format_choices[0]
+
+ if options.output_format == 'gtest':
+ return gtest_test_results.GTestTestResults()
+ elif options.output_format == 'none':
+ return page_test_results.PageTestResults()
+ else:
+ # Should never be reached. The parser enforces the choices.
+ raise Exception('Invalid --output-format "%s". Valid choices are: %s'
+ % (options.output_format,
+ ', '.join(self.output_format_choices)))
+
+ def Run(self, options, page, tab, results):
+ self.options = options
+ compound_action = GetCompoundActionFromPage(page, self._action_name_to_run)
+ self._RunCompoundAction(page, tab, compound_action)
+ try:
+ self._test_method(page, tab, results)
+ finally:
+ self.options = None
+
+ def _RunCompoundAction(self, page, tab, actions):
+ for i, action in enumerate(actions):
+ prev_action = actions[i - 1] if i > 0 else None
+ next_action = actions[i + 1] if i < len(actions) - 1 else None
+
+ if (action.RunsPreviousAction() and
+ next_action and next_action.RunsPreviousAction()):
+ raise page_action.PageActionFailed('Consecutive actions cannot both '
+ 'have RunsPreviousAction() == True.')
+
+ if not (next_action and next_action.RunsPreviousAction()):
+ action.WillRunAction(page, tab)
+ self.WillRunAction(page, tab, action)
+ try:
+ action.RunAction(page, tab, prev_action)
+ finally:
+ self.DidRunAction(page, tab, action)
+
+ # Closing the connections periodically is needed; otherwise we won't be
+ # able to open enough sockets, and the pages will time out.
+ util.CloseConnections(tab)
+
+ @property
+ def action_name_to_run(self):
+ return self._action_name_to_run
diff --git a/chromium/tools/telemetry/telemetry/page/page_test_results.py b/chromium/tools/telemetry/telemetry/page/page_test_results.py
new file mode 100644
index 00000000000..5a2e6ff1740
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_test_results.py
@@ -0,0 +1,66 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import sys
+import traceback
+import unittest
+
+class PageTestResults(unittest.TestResult):
+ def __init__(self):
+ super(PageTestResults, self).__init__()
+ self.successes = []
+ self.skipped = []
+
+ def _exc_info_to_string(self, err, test):
+ if isinstance(test, unittest.TestCase):
+ return super(PageTestResults, self)._exc_info_to_string(err, test)
+ else:
+ return ''.join(traceback.format_exception(*err))
+
+ def addSuccess(self, test):
+ self.successes.append(test)
+
+ def addSkip(self, test, reason): # Python 2.7 has this in unittest.TestResult
+ self.skipped.append((test, reason))
+
+ def StartTest(self, page):
+ self.startTest(page.url)
+
+ def StopTest(self, page):
+ self.stopTest(page.url)
+
+ def AddError(self, page, err):
+ self.addError(page.url, err)
+
+ def AddFailure(self, page, err):
+ self.addFailure(page.url, err)
+
+ def AddSuccess(self, page):
+ self.addSuccess(page.url)
+
+ def AddSkip(self, page, reason):
+ self.addSkip(page.url, reason)
+
+ def AddFailureMessage(self, page, message):
+ try:
+ raise Exception(message)
+ except Exception:
+ self.AddFailure(page, sys.exc_info())
+
+ def AddErrorMessage(self, page, message):
+ try:
+ raise Exception(message)
+ except Exception:
+ self.AddError(page, sys.exc_info())
+
+ def PrintSummary(self):
+ if self.failures:
+ logging.warning('Failed pages:\n%s', '\n'.join(zip(*self.failures)[0]))
+
+ if self.errors:
+ logging.warning('Errored pages:\n%s', '\n'.join(zip(*self.errors)[0]))
+
+ if self.skipped:
+ logging.warning('Skipped pages:\n%s', '\n'.join(zip(*self.skipped)[0]))
diff --git a/chromium/tools/telemetry/telemetry/page/page_test_runner.py b/chromium/tools/telemetry/telemetry/page/page_test_runner.py
new file mode 100644
index 00000000000..6b8fa9bef04
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_test_runner.py
@@ -0,0 +1,177 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+from telemetry import test as test_module
+from telemetry.core import browser_options
+from telemetry.core import discover
+from telemetry.core import profile_types
+from telemetry.page import page_test as page_test_module
+from telemetry.page import page_runner
+from telemetry.page import page_set
+
+def Main(base_dir, page_set_filenames):
+ """Turns a PageTest into a command-line program.
+
+ Args:
+ base_dir: Path to directory containing tests and ProfileCreators.
+ """
+ runner = PageTestRunner()
+ sys.exit(runner.Run(base_dir, page_set_filenames))
+
+class PageTestRunner(object):
+ def __init__(self):
+ self._parser = None
+ self._options = None
+ self._args = None
+
+ @property
+ def test_class(self):
+ return page_test_module.PageTest
+
+ @property
+ def test_class_name(self):
+ return 'test'
+
+ def Run(self, base_dir, page_set_filenames):
+ test, ps, expectations = self.ParseCommandLine(sys.argv, base_dir,
+ page_set_filenames)
+ results = page_runner.Run(test, ps, expectations, self._options)
+ results.PrintSummary()
+ return min(255, len(results.failures + results.errors))
+
+ def FindTestConstructors(self, base_dir):
+ # Look for both Tests and PageTests, but Tests get priority, because
+ test_constructors = discover.DiscoverClasses(
+ base_dir, base_dir, self.test_class)
+ test_constructors.update(discover.DiscoverClasses(
+ base_dir, base_dir, test_module.Test, index_by_class_name=True))
+ return test_constructors
+
+ def FindTestName(self, test_constructors, args):
+ """Find the test name in an arbitrary argument list.
+
+ We can't use the optparse parser, because the test may add its own
+ command-line options. If the user passed in any of those, the
+ optparse parsing will fail.
+
+ Returns:
+ test_name or None
+ """
+ test_name = None
+ for arg in [self.GetModernizedTestName(a) for a in args]:
+ if arg in test_constructors:
+ test_name = arg
+
+ return test_name
+
+ def GetModernizedTestName(self, arg):
+ """Sometimes tests change names but buildbots keep calling the old name.
+
+ If arg matches an old test name, return the new test name instead.
+ Otherwise, return the arg.
+ """
+ return arg
+
+ def GetPageSet(self, test, page_set_filenames):
+ ps = test.CreatePageSet(self._args, self._options)
+ if ps:
+ return ps
+
+ if len(self._args) < 2:
+ page_set_list = ',\n'.join(
+ sorted([os.path.relpath(f) for f in page_set_filenames]))
+ self.PrintParseError(
+ 'No page set, file, or URL specified.\n'
+ 'Available page sets:\n'
+ '%s' % page_set_list)
+
+ page_set_arg = self._args[1]
+
+ # We've been given a URL. Create a page set with just that URL.
+ if (page_set_arg.startswith('http://') or
+ page_set_arg.startswith('https://')):
+ self._options.allow_live_sites = True
+ return page_set.PageSet.FromDict({
+ 'pages': [{'url': page_set_arg}]
+ }, os.path.dirname(__file__))
+
+ # We've been given a page set JSON. Load it.
+ if page_set_arg.endswith('.json'):
+ return page_set.PageSet.FromFile(page_set_arg)
+
+ # We've been given a file or directory. Create a page set containing it.
+ if os.path.exists(page_set_arg):
+ page_set_dict = {'pages': []}
+
+ def _AddFile(file_path):
+ page_set_dict['pages'].append({'url': 'file://' + file_path})
+
+ def _AddDir(dir_path):
+ for path in os.listdir(dir_path):
+ path = os.path.join(dir_path, path)
+ _AddPath(path)
+
+ def _AddPath(path):
+ if os.path.isdir(path):
+ _AddDir(path)
+ else:
+ _AddFile(path)
+
+ _AddPath(page_set_arg)
+ return page_set.PageSet.FromDict(page_set_dict, os.getcwd() + os.sep)
+
+ raise Exception('Did not understand "%s". Pass a page set, file or URL.' %
+ page_set_arg)
+
+ def ParseCommandLine(self, args, base_dir, page_set_filenames):
+ # Need to collect profile creators before creating command line parser.
+ profile_types.FindProfileCreators(base_dir, base_dir)
+
+ self._options = browser_options.BrowserOptions()
+ self._parser = self._options.CreateParser(
+ '%%prog [options] %s page_set' % self.test_class_name)
+
+ test_constructors = self.FindTestConstructors(base_dir)
+ test_name = self.FindTestName(test_constructors, args)
+ test = None
+ if test_name:
+ test = test_constructors[test_name]()
+ if isinstance(test, test_module.Test):
+ page_test = test.test()
+ else:
+ page_test = test
+ page_test.AddOutputOptions(self._parser)
+ page_test.AddCommandLineOptions(self._parser)
+ page_runner.AddCommandLineOptions(self._parser)
+
+ _, self._args = self._parser.parse_args()
+
+ if len(self._args) < 1:
+ error_message = 'No %s specified.\nAvailable %ss:\n' % (
+ self.test_class_name, self.test_class_name)
+ test_list_string = ',\n'.join(sorted(test_constructors.keys()))
+ self.PrintParseError(error_message + test_list_string)
+
+ if not test:
+ error_message = 'No %s named %s.\nAvailable %ss:\n' % (
+ self.test_class_name, self._args[0], self.test_class_name)
+ test_list_string = ',\n'.join(sorted(test_constructors.keys()))
+ self.PrintParseError(error_message + test_list_string)
+
+ if isinstance(test, test_module.Test):
+ ps = test.CreatePageSet(self._options)
+ expectations = test.CreateExpectations(ps)
+ else:
+ ps = self.GetPageSet(test, page_set_filenames)
+ expectations = test.CreateExpectations(ps)
+
+ if len(self._args) > 2:
+ self.PrintParseError('Too many arguments.')
+
+ return page_test, ps, expectations
+
+ def PrintParseError(self, message):
+ self._parser.error(message)
diff --git a/chromium/tools/telemetry/telemetry/page/page_test_unittest.py b/chromium/tools/telemetry/telemetry/page/page_test_unittest.py
new file mode 100644
index 00000000000..6b68d9d2cd4
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_test_unittest.py
@@ -0,0 +1,117 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from telemetry.page import page as page_module
+from telemetry.page import page_test
+from telemetry.page.actions import all_page_actions
+from telemetry.page.actions import page_action
+
+def _CreatePage(test_filename):
+ url = 'file:///' + os.path.join('..', '..', 'unittest_data', test_filename)
+ base_dir = os.path.dirname(__file__)
+ page = page_module.Page(url, None, base_dir=base_dir)
+ return page
+
+class DoNothingPageTest(page_test.PageTest):
+ def __init__(self, action_name_to_run=''):
+ super(DoNothingPageTest, self).__init__('DoNothing', action_name_to_run)
+
+ def DoNothing(self, page, tab, results):
+ pass
+
+class AppendAction(page_action.PageAction):
+ def RunAction(self, page, tab, previous_action):
+ self.var.append(True)
+
+class WrapAppendAction(page_action.PageAction):
+ def RunsPreviousAction(self):
+ return True
+
+ def RunAction(self, page, tab, previous_action):
+ self.var.append('before')
+ previous_action.WillRunAction(page, tab)
+ previous_action.RunAction(page, tab, None)
+ self.var.append('after')
+
+class PageTestUnitTest(unittest.TestCase):
+ def setUp(self):
+ super(PageTestUnitTest, self).setUp()
+ all_page_actions.RegisterClassForTest('append', AppendAction)
+ all_page_actions.RegisterClassForTest('wrap_append', WrapAppendAction)
+
+ self._page_test = DoNothingPageTest('action_to_run')
+ self._page = _CreatePage('blank.html')
+
+ def testRunActions(self):
+ action_called = []
+ action_to_run = [
+ { 'action': 'append', 'var': action_called }
+ ]
+ setattr(self._page, 'action_to_run', action_to_run)
+
+ self._page_test.Run(None, self._page, None, None)
+
+ self.assertTrue(action_called)
+
+ def testPreviousAction(self):
+ action_list = []
+ action_to_run = [
+ { 'action': 'append', 'var': action_list },
+ { 'action': 'wrap_append', 'var': action_list }
+ ]
+ setattr(self._page, 'action_to_run', action_to_run)
+
+ self._page_test.Run(None, self._page, None, None)
+
+ self.assertEqual(action_list, ['before', True, 'after'])
+
+ def testReferenceAction(self):
+ action_list = []
+ action_to_run = [
+ { 'action': 'referenced_action_1' },
+ { 'action': 'referenced_action_2' }
+ ]
+ referenced_action_1 = { 'action': 'append', 'var': action_list }
+ referenced_action_2 = { 'action': 'wrap_append', 'var': action_list }
+ setattr(self._page, 'action_to_run', action_to_run)
+ setattr(self._page, 'referenced_action_1', referenced_action_1)
+ setattr(self._page, 'referenced_action_2', referenced_action_2)
+
+ self._page_test.Run(None, self._page, None, None)
+
+ self.assertEqual(action_list, ['before', True, 'after'])
+
+ def testRepeatAction(self):
+ action_list = []
+ action_to_run = { 'action': 'append', 'var': action_list, 'repeat': 10 }
+ setattr(self._page, 'action_to_run', action_to_run)
+
+ self._page_test.Run(None, self._page, None, None)
+
+ self.assertEqual(len(action_list), 10)
+
+ def testRepeatReferenceAction(self):
+ action_list = []
+ action_to_run = { 'action': 'referenced_action', 'repeat': 2 }
+ referenced_action = [
+ { 'action': 'append', 'var': action_list },
+ { 'action': 'wrap_append', 'var': action_list }
+ ]
+ setattr(self._page, 'action_to_run', action_to_run)
+ setattr(self._page, 'referenced_action', referenced_action)
+
+ self._page_test.Run(None, self._page, None, None)
+
+ self.assertEqual(action_list,
+ ['before', True, 'after', 'before', True, 'after'])
+
+ def testRepeatPreviousActionFails(self):
+ action_list = []
+ action_to_run = { 'action': 'wrap_append', 'var': action_list, 'repeat': 2 }
+ setattr(self._page, 'action_to_run', action_to_run)
+
+ self.assertRaises(page_action.PageActionFailed,
+ lambda: self._page_test.Run(None, self._page, None, None))
diff --git a/chromium/tools/telemetry/telemetry/page/page_unittest.py b/chromium/tools/telemetry/telemetry/page/page_unittest.py
new file mode 100644
index 00000000000..3e068f3e813
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/page_unittest.py
@@ -0,0 +1,141 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import unittest
+
+from telemetry.page import page
+from telemetry.page import page_set
+
+class TestPage(unittest.TestCase):
+ def testUrlPathJoin(self):
+ # pylint: disable=W0212
+ self.assertEqual('a/b', page._UrlPathJoin('a', 'b'))
+ self.assertEqual('a/b', page._UrlPathJoin('a/', 'b'))
+ self.assertEqual('a/b', page._UrlPathJoin('a', '/b'))
+ self.assertEqual('a/b', page._UrlPathJoin('a/', '/b'))
+ self.assertEqual('a/b/c', page._UrlPathJoin('a', 'b', 'c'))
+ self.assertEqual('a/b/c', page._UrlPathJoin('a', 'b/', 'c'))
+ self.assertEqual('a/b/c', page._UrlPathJoin('a', 'b', '/c'))
+ self.assertEqual('a/b/c', page._UrlPathJoin('a', 'b/', '/c'))
+ self.assertEqual('a/b', page._UrlPathJoin('a', 'b', ''))
+
+ def testGetUrlBaseDirAndFileForAbsolutePath(self):
+ apage = page.Page('file:///somedir/otherdir/file.html',
+ None, # In this test, we don't need a page set.
+ base_dir='basedir')
+ serving_dirs, filename = apage.serving_dirs_and_file
+ self.assertEqual(serving_dirs, 'basedir/somedir/otherdir')
+ self.assertEqual(filename, 'file.html')
+
+ def testGetUrlBaseDirAndFileForRelativePath(self):
+ apage = page.Page('file:///../../otherdir/file.html',
+ None, # In this test, we don't need a page set.
+ base_dir='basedir')
+ serving_dirs, filename = apage.serving_dirs_and_file
+ self.assertEqual(serving_dirs, 'basedir/../../otherdir')
+ self.assertEqual(filename, 'file.html')
+
+ def testGetUrlBaseDirAndFileForUrlBaseDir(self):
+ ps = page_set.PageSet.FromDict({
+ 'description': 'hello',
+ 'archive_path': 'foo.wpr',
+ 'serving_dirs': ['../../somedir/'],
+ 'pages': [
+ {'url': 'file:///../../somedir/otherdir/file.html'}
+ ]}, 'basedir/')
+ serving_dirs, filename = ps[0].serving_dirs_and_file
+ self.assertEqual(serving_dirs, ['basedir/../../somedir/'])
+ self.assertEqual(filename, 'otherdir/file.html')
+
+ def testDisplayUrlForHttp(self):
+ ps = page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "http://www.foo.com/"},
+ {"url": "http://www.bar.com/"}
+ ]
+ }, os.path.dirname(__file__))
+ self.assertEquals(ps[0].display_url, 'http://www.foo.com/')
+ self.assertEquals(ps[1].display_url, 'http://www.bar.com/')
+
+ def testDisplayUrlForHttps(self):
+ ps = page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "http://www.foo.com/"},
+ {"url": "https://www.bar.com/"}
+ ]
+ }, os.path.dirname(__file__))
+ self.assertEquals(ps[0].display_url, 'http://www.foo.com/')
+ self.assertEquals(ps[1].display_url, 'https://www.bar.com/')
+
+ def testDisplayUrlForFile(self):
+ ps = page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "file:///../../otherdir/foo.html"},
+ {"url": "file:///../../otherdir/bar.html"},
+ ]
+ }, os.path.dirname(__file__))
+ self.assertEquals(ps[0].display_url, 'foo.html')
+ self.assertEquals(ps[1].display_url, 'bar.html')
+
+ def testDisplayUrlForFilesDifferingBySuffix(self):
+ ps = page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "file:///../../otherdir/foo.html"},
+ {"url": "file:///../../otherdir/foo1.html"},
+ ]
+ }, os.path.dirname(__file__))
+ self.assertEquals(ps[0].display_url, 'foo.html')
+ self.assertEquals(ps[1].display_url, 'foo1.html')
+
+ def testDisplayUrlForFileOfDifferentPaths(self):
+ ps = page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "file:///../../somedir/foo.html"},
+ {"url": "file:///../../otherdir/bar.html"},
+ ]
+ }, os.path.dirname(__file__))
+ self.assertEquals(ps[0].display_url, 'somedir/foo.html')
+ self.assertEquals(ps[1].display_url, 'otherdir/bar.html')
+
+ def testDisplayUrlForFileDirectories(self):
+ ps = page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "file:///../../otherdir/foo/"},
+ {"url": "file:///../../otherdir/bar/"},
+ ]
+ }, os.path.dirname(__file__))
+ self.assertEquals(ps[0].display_url, 'foo')
+ self.assertEquals(ps[1].display_url, 'bar')
+
+ def testDisplayUrlForSingleFile(self):
+ ps = page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "file:///../../otherdir/foo.html"},
+ ]
+ }, os.path.dirname(__file__))
+ self.assertEquals(ps[0].display_url, 'foo.html')
+
+ def testDisplayUrlForSingleDirectory(self):
+ ps = page_set.PageSet.FromDict({
+ "description": "hello",
+ "archive_path": "foo.wpr",
+ "pages": [
+ {"url": "file:///../../otherdir/foo/"},
+ ]
+ }, os.path.dirname(__file__))
+ self.assertEquals(ps[0].display_url, 'foo')
diff --git a/chromium/tools/telemetry/telemetry/page/perf_tests_helper.py b/chromium/tools/telemetry/telemetry/page/perf_tests_helper.py
new file mode 100644
index 00000000000..285e032379f
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/perf_tests_helper.py
@@ -0,0 +1,27 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from __future__ import absolute_import
+
+import os
+import sys
+
+def __init__():
+ path = os.path.join(os.path.dirname(__file__),
+ '..', '..', '..', '..', 'build', 'android')
+ path = os.path.abspath(path)
+ assert os.path.exists(os.path.join(path,
+ 'pylib', '__init__.py'))
+ if path not in sys.path:
+ sys.path.append(path)
+
+__init__()
+
+from pylib import perf_tests_helper # pylint: disable=F0401
+GeomMeanAndStdDevFromHistogram = \
+ perf_tests_helper.GeomMeanAndStdDevFromHistogram
+PrintPerfResult = \
+ perf_tests_helper.PrintPerfResult
+PrintPages = \
+ perf_tests_helper.PrintPages
+
diff --git a/chromium/tools/telemetry/telemetry/page/record_wpr.py b/chromium/tools/telemetry/telemetry/page/record_wpr.py
new file mode 100755
index 00000000000..ff295e45f58
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/record_wpr.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import sys
+import tempfile
+import time
+
+from telemetry import test
+from telemetry.core import browser_options
+from telemetry.core import discover
+from telemetry.core import wpr_modes
+from telemetry.page import page_measurement
+from telemetry.page import page_runner
+from telemetry.page import page_set
+from telemetry.page import page_test
+from telemetry.page import test_expectations
+
+
+class RecordPage(page_test.PageTest):
+ def __init__(self, measurements):
+ # This class overwrites PageTest.Run, so that the test method name is not
+ # really used (except for throwing an exception if it doesn't exist).
+ super(RecordPage, self).__init__('Run')
+ self._action_names = set(
+ [measurement().action_name_to_run
+ for measurement in measurements.values()
+ if measurement().action_name_to_run])
+
+ def CanRunForPage(self, page):
+ return page.url.startswith('http')
+
+ def CustomizeBrowserOptionsForPage(self, page, options):
+ for compound_action in self._CompoundActionsForPage(page):
+ for action in compound_action:
+ action.CustomizeBrowserOptions(options)
+
+ def Run(self, options, page, tab, results):
+ # When recording, sleep to catch any resources that load post-onload.
+ tab.WaitForDocumentReadyStateToBeComplete()
+ time.sleep(3)
+
+ # Run the actions for all measurements. Reload the page between
+ # actions.
+ should_reload = False
+ for compound_action in self._CompoundActionsForPage(page):
+ if should_reload:
+ tab.Navigate(page.url)
+ tab.WaitForDocumentReadyStateToBeComplete()
+ self._RunCompoundAction(page, tab, compound_action)
+ should_reload = True
+
+ def _CompoundActionsForPage(self, page):
+ actions = []
+ for action_name in self._action_names:
+ if not hasattr(page, action_name):
+ continue
+ actions.append(page_test.GetCompoundActionFromPage(page, action_name))
+ return actions
+
+
+def Main(base_dir):
+ measurements = discover.DiscoverClasses(base_dir, base_dir,
+ page_measurement.PageMeasurement)
+ tests = discover.DiscoverClasses(base_dir, base_dir, test.Test,
+ index_by_class_name=True)
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser('%prog <PageSet|Measurement|Test>')
+ page_runner.AddCommandLineOptions(parser)
+
+ recorder = RecordPage(measurements)
+ recorder.AddCommandLineOptions(parser)
+ recorder.AddOutputOptions(parser)
+
+ _, args = parser.parse_args()
+
+ if len(args) != 1:
+ parser.print_usage()
+ sys.exit(1)
+
+ if args[0].endswith('.json'):
+ ps = page_set.PageSet.FromFile(args[0])
+ elif args[0] in tests:
+ ps = tests[args[0]]().CreatePageSet(options)
+ elif args[0] in measurements:
+ ps = measurements[args[0]]().CreatePageSet(args, options)
+ else:
+ parser.print_usage()
+ sys.exit(1)
+
+ expectations = test_expectations.TestExpectations()
+
+ # Set the archive path to something temporary.
+ temp_target_wpr_file_path = tempfile.mkstemp()[1]
+ ps.wpr_archive_info.AddNewTemporaryRecording(temp_target_wpr_file_path)
+
+ # Do the actual recording.
+ options.wpr_mode = wpr_modes.WPR_RECORD
+ options.no_proxy_server = True
+ recorder.CustomizeBrowserOptions(options)
+ results = page_runner.Run(recorder, ps, expectations, options)
+
+ if results.errors or results.failures:
+ logging.warning('Some pages failed. The recording has not been updated for '
+ 'these pages.')
+ logging.warning('Failed pages:\n%s',
+ '\n'.join(zip(*results.errors + results.failures)[0]))
+
+ if results.skipped:
+ logging.warning('Some pages were skipped. The recording has not been '
+ 'updated for these pages.')
+ logging.warning('Skipped pages:\n%s', '\n'.join(zip(*results.skipped)[0]))
+
+ if results.successes:
+ # Update the metadata for the pages which were recorded.
+ ps.wpr_archive_info.AddRecordedPages(results.successes)
+ else:
+ os.remove(temp_target_wpr_file_path)
+
+ return min(255, len(results.failures))
diff --git a/chromium/tools/telemetry/telemetry/page/test_expectations.py b/chromium/tools/telemetry/telemetry/page/test_expectations.py
new file mode 100644
index 00000000000..2ed9faa30a0
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/test_expectations.py
@@ -0,0 +1,72 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import fnmatch
+
+OS_MODIFIERS = ['win', 'xp', 'vista', 'win7',
+ 'mac', 'leopard', 'snowleopard', 'lion', 'mountainlion',
+ 'linux', 'chromeos', 'android']
+GPU_MODIFIERS = ['nvidia', 'amd', 'intel']
+CONFIG_MODIFIERS = ['debug', 'release']
+
+class Expectation(object):
+ def __init__(self, expectation, url_pattern, conditions=None, bug=None):
+ self.expectation = expectation.lower()
+ self.url_pattern = url_pattern
+ self.bug = bug
+
+ self.os_conditions = []
+ self.gpu_conditions = []
+ self.config_conditions = []
+
+ # Make sure that non-absolute paths are searchable
+ if not '://' in self.url_pattern:
+ self.url_pattern = '*/' + self.url_pattern
+
+ if conditions:
+ for c in conditions:
+ condition = c.lower()
+ if condition in OS_MODIFIERS:
+ self.os_conditions.append(condition)
+ elif condition in GPU_MODIFIERS:
+ self.gpu_conditions.append(condition)
+ elif condition in CONFIG_MODIFIERS:
+ self.config_conditions.append(condition)
+ else:
+ raise ValueError('Unknown expectation condition: "%s"' % condition)
+
+class TestExpectations(object):
+ """A class which defines the expectations for a page set test execution"""
+
+ def __init__(self):
+ self.expectations = []
+ self.SetExpectations()
+
+ def SetExpectations(self):
+ """Called on creation. Override to set up custom expectations."""
+ pass
+
+ def Fail(self, url_pattern, conditions=None, bug=None):
+ self._Expect('fail', url_pattern, conditions, bug)
+
+ def _Expect(self, expectation, url_pattern, conditions=None, bug=None):
+ self.expectations.append(Expectation(expectation, url_pattern, conditions,
+ bug))
+
+ def GetExpectationForPage(self, platform, page):
+ for e in self.expectations:
+ if fnmatch.fnmatch(page.url, e.url_pattern):
+ if self._ModifiersApply(platform, e):
+ return e.expectation
+ return 'pass'
+
+ def _ModifiersApply(self, platform, expectation):
+ """Determines if the conditions for an expectation apply to this system."""
+ os_matches = (not expectation.os_conditions or
+ platform.GetOSName() in expectation.os_conditions or
+ platform.GetOSVersionName() in expectation.os_conditions)
+
+ # TODO: Add checks against other modifiers (GPU, configuration, etc.)
+
+ return os_matches \ No newline at end of file
diff --git a/chromium/tools/telemetry/telemetry/page/test_expectations_unittest.py b/chromium/tools/telemetry/telemetry/page/test_expectations_unittest.py
new file mode 100644
index 00000000000..ee4a1b82d1b
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/page/test_expectations_unittest.py
@@ -0,0 +1,85 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.page import page as page_module
+from telemetry.page import page_set
+from telemetry.page import test_expectations
+
+class StubPlatform(object):
+ def __init__(self, os_name, os_version_name=None):
+ self.os_name = os_name
+ self.os_version_name = os_version_name
+
+ def GetOSName(self):
+ return self.os_name
+
+ def GetOSVersionName(self):
+ return self.os_version_name
+
+class SampleTestExpectations(test_expectations.TestExpectations):
+ def SetExpectations(self):
+ self.Fail('page1.html', ['win', 'mac'], bug=123)
+ self.Fail('page2.html', ['vista'], bug=123)
+ self.Fail('page3.html', bug=123)
+ self.Fail('page4.*', bug=123)
+ self.Fail('http://test.com/page5.html', bug=123)
+
+class TestExpectationsTest(unittest.TestCase):
+ def setUp(self):
+ self.expectations = SampleTestExpectations()
+
+ def assertExpectationEquals(self, expected, platform, page):
+ result = self.expectations.GetExpectationForPage(platform, page)
+ self.assertEquals(expected, result)
+
+ # Pages with no expectations should always return 'pass'
+ def testNoExpectations(self):
+ ps = page_set.PageSet()
+ page = page_module.Page('http://test.com/page0.html', ps)
+ self.assertExpectationEquals('pass', StubPlatform('win'), page)
+
+ # Pages with expectations for an OS should only return them when running on
+ # that OS
+ def testOSExpectations(self):
+ ps = page_set.PageSet()
+ page = page_module.Page('http://test.com/page1.html', ps)
+ self.assertExpectationEquals('fail', StubPlatform('win'), page)
+ self.assertExpectationEquals('fail', StubPlatform('mac'), page)
+ self.assertExpectationEquals('pass', StubPlatform('linux'), page)
+
+ # Pages with expectations for an OS version should only return them when
+ # running on that OS version
+ def testOSVersionExpectations(self):
+ ps = page_set.PageSet()
+ page = page_module.Page('http://test.com/page2.html', ps)
+ self.assertExpectationEquals('fail', StubPlatform('win', 'vista'), page)
+ self.assertExpectationEquals('pass', StubPlatform('win', 'win7'), page)
+
+ # Pages with non-conditional expectations should always return that
+ # expectation regardless of OS or OS version
+ def testConditionlessExpectations(self):
+ ps = page_set.PageSet()
+ page = page_module.Page('http://test.com/page3.html', ps)
+ self.assertExpectationEquals('fail', StubPlatform('win'), page)
+ self.assertExpectationEquals('fail', StubPlatform('mac', 'lion'), page)
+ self.assertExpectationEquals('fail', StubPlatform('linux'), page)
+
+ # Expectations with wildcard characters should return for matching patterns
+ def testWildcardExpectations(self):
+ ps = page_set.PageSet()
+ page = page_module.Page('http://test.com/page4.html', ps)
+ page_js = page_module.Page('http://test.com/page4.html', ps)
+ self.assertExpectationEquals('fail', StubPlatform('win'), page)
+ self.assertExpectationEquals('fail', StubPlatform('win'), page_js)
+
+ # Expectations with absolute paths should match the entire path
+ def testAbsoluteExpectations(self):
+ ps = page_set.PageSet()
+ page = page_module.Page('http://test.com/page5.html', ps)
+ page_org = page_module.Page('http://test.org/page5.html', ps)
+ page_https = page_module.Page('https://test.com/page5.html', ps)
+ self.assertExpectationEquals('fail', StubPlatform('win'), page)
+ self.assertExpectationEquals('pass', StubPlatform('win'), page_org)
+ self.assertExpectationEquals('pass', StubPlatform('win'), page_https)
diff --git a/chromium/tools/telemetry/telemetry/test.py b/chromium/tools/telemetry/telemetry/test.py
new file mode 100644
index 00000000000..3b5bcf39a75
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/test.py
@@ -0,0 +1,74 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import optparse
+import os
+
+from telemetry.core import repeat_options
+from telemetry.core import util
+from telemetry.page import page_runner
+from telemetry.page import page_set
+from telemetry.page import page_test
+from telemetry.page import test_expectations
+
+
+class Test(object):
+ """Base class for a Telemetry test or benchmark.
+
+ A test packages a PageTest/PageMeasurement and a PageSet together.
+ """
+ options = {}
+ enabled = True
+
+ def Run(self, options):
+ """Run this test with the given options."""
+ assert hasattr(self, 'test'), 'This test has no "test" attribute.'
+ assert issubclass(self.test, page_test.PageTest), (
+ '"%s" is not a PageTest.' % self.test.__name__)
+
+ for key, value in self.options.iteritems():
+ setattr(options, key, value)
+
+ options.repeat_options = self._CreateRepeatOptions(options)
+
+ test = self.test()
+ ps = self.CreatePageSet(options)
+ expectations = self.CreateExpectations(ps)
+
+ # Ensure the test's default options are set if needed.
+ parser = optparse.OptionParser()
+ test.AddCommandLineOptions(parser)
+ options.MergeDefaultValues(parser.get_default_values())
+
+ results = page_runner.Run(test, ps, expectations, options)
+ results.PrintSummary()
+ return len(results.failures) + len(results.errors)
+
+ def _CreateRepeatOptions(self, options):
+ return repeat_options.RepeatOptions(
+ getattr(options, 'page_repeat_secs', None),
+ getattr(options, 'pageset_repeat_secs', None),
+ getattr(options, 'page_repeat_iters', 1),
+ getattr(options, 'pageset_repeat_iters', 1),
+ )
+
+ def CreatePageSet(self, options): # pylint: disable=W0613
+ """Get the page set this test will run on.
+
+ By default, it will create a page set from the file at this test's
+ page_set attribute. Override to generate a custom page set.
+ """
+ assert hasattr(self, 'page_set'), 'This test has no "page_set" attribute.'
+ return page_set.PageSet.FromFile(
+ os.path.join(util.GetBaseDir(), self.page_set))
+
+ def CreateExpectations(self, ps): # pylint: disable=W0613
+ """Get the expectations this test will run with.
+
+ By default, it will create an empty expectations set. Override to generate
+ custom expectations.
+ """
+ if hasattr(self, 'expectations'):
+ return self.expectations
+ else:
+ return test_expectations.TestExpectations()
diff --git a/chromium/tools/telemetry/telemetry/test_runner.py b/chromium/tools/telemetry/telemetry/test_runner.py
new file mode 100644
index 00000000000..ebae40cfa43
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/test_runner.py
@@ -0,0 +1,162 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Parses the command line, discovers the appropriate tests, and runs them.
+
+Handles test configuration, but all the logic for
+actually running the test is in Test and PageRunner."""
+
+import copy
+import inspect
+import json
+import optparse
+import os
+import sys
+
+from telemetry import test
+from telemetry.core import browser_options
+from telemetry.core import discover
+from telemetry.core import util
+
+
+class Command(object):
+ usage = ''
+
+ @property
+ def name(self):
+ return self.__class__.__name__.lower()
+
+ @property
+ def description(self):
+ return self.__doc__
+
+ def CreateParser(self):
+ return optparse.OptionParser('%%prog %s %s' % (self.name, self.usage))
+
+ def AddParserOptions(self, parser):
+ pass
+
+ def ValidateCommandLine(self, parser, options, args):
+ pass
+
+ def Run(self, options, args):
+ raise NotImplementedError()
+
+
+class Help(Command):
+ """Display help information"""
+
+ def Run(self, options, args):
+ print ('usage: %s <command> [<args>]' % _GetScriptName())
+ print 'Available commands are:'
+ for command in COMMANDS:
+ print ' %-10s %s' % (command.name, command.description)
+ return 0
+
+
+class List(Command):
+ """Lists the available tests"""
+
+ def AddParserOptions(self, parser):
+ parser.add_option('-j', '--json', action='store_true')
+
+ def Run(self, options, args):
+ if options.json:
+ test_list = []
+ for test_name, test_class in sorted(_GetTests().items()):
+ test_list.append({
+ 'name': test_name,
+ 'description': test_class.__doc__,
+ 'enabled': test_class.enabled,
+ 'options': test_class.options,
+ })
+ print json.dumps(test_list)
+ else:
+ print 'Available tests are:'
+ for test_name, test_class in sorted(_GetTests().items()):
+ if test_class.__doc__:
+ print ' %-20s %s' % (test_name,
+ test_class.__doc__.splitlines()[0])
+ else:
+ print ' %-20s' % test_name
+ return 0
+
+
+class Run(Command):
+ """Run one or more tests"""
+
+ usage = 'test_name [...] [<args>]'
+
+ def CreateParser(self):
+ options = browser_options.BrowserOptions()
+ parser = options.CreateParser('%%prog %s %s' % (self.name, self.usage))
+ return parser
+
+ def ValidateCommandLine(self, parser, options, args):
+ if not args:
+ parser.error('Must provide at least one test name')
+ for test_name in args:
+ if test_name not in _GetTests():
+ parser.error('No test named "%s"' % test_name)
+
+ def Run(self, options, args):
+ total_failures = 0
+ for test_name in args:
+ test_failures = _GetTests()[test_name]().Run(copy.copy(options))
+ total_failures += test_failures
+
+ return min(255, total_failures)
+
+
+COMMANDS = [cls() for _, cls in inspect.getmembers(sys.modules[__name__])
+ if inspect.isclass(cls)
+ and cls is not Command and issubclass(cls, Command)]
+
+
+def _GetScriptName():
+ return os.path.basename(sys.argv[0])
+
+
+def _GetTests():
+ # Lazy load and cache results.
+ if not hasattr(_GetTests, 'tests'):
+ base_dir = util.GetBaseDir()
+ _GetTests.tests = discover.DiscoverClasses(base_dir, base_dir, test.Test,
+ index_by_class_name=True)
+ return _GetTests.tests
+
+
+def Main():
+ # Get the command name from the command line.
+ if len(sys.argv) > 1 and sys.argv[1] == '--help':
+ sys.argv[1] = 'help'
+
+ command_name = 'run'
+ for arg in sys.argv[1:]:
+ if not arg.startswith('-'):
+ command_name = arg
+ break
+
+ # Validate and interpret the command name.
+ commands = [command for command in COMMANDS
+ if command.name.startswith(command_name)]
+ if len(commands) > 1:
+ print >> sys.stderr, ('"%s" is not a %s command. Did you mean one of these?'
+ % (command_name, _GetScriptName()))
+ for command in commands:
+ print >> sys.stderr, ' %-10s %s' % (command.name, command.description)
+ return 1
+ if commands:
+ command = commands[0]
+ else:
+ command = Run()
+
+ # Parse and run the command.
+ parser = command.CreateParser()
+ command.AddParserOptions(parser)
+ options, args = parser.parse_args()
+ if commands:
+ args = args[1:]
+ command.ValidateCommandLine(parser, options, args)
+ return command.Run(options, args)
diff --git a/chromium/tools/telemetry/telemetry/unittest/__init__.py b/chromium/tools/telemetry/telemetry/unittest/__init__.py
new file mode 100644
index 00000000000..053e441dc63
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/unittest/__init__.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+def RequiresBrowserOfType(*types):
+ def wrap(func):
+ func._requires_browser_types = types
+ return func
+ return wrap
+
+def DisabledTest(func):
+ func._disabled_test = True
+ return func
diff --git a/chromium/tools/telemetry/telemetry/unittest/gtest_testrunner.py b/chromium/tools/telemetry/telemetry/unittest/gtest_testrunner.py
new file mode 100755
index 00000000000..0d885553f06
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/unittest/gtest_testrunner.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Implements a unittest TestRunner with GTest output.
+
+This output is ported from gtest.cc's PrettyUnitTestResultPrinter, but
+designed to be a drop-in replacement for unittest's TextTestRunner.
+"""
+
+import time
+import unittest
+
+from telemetry.page import gtest_test_results
+
+
+class GTestTestSuite(unittest.TestSuite):
+ def __call__(self, *args, **kwargs):
+ result = args[0]
+ timestamp = time.time()
+ unit = 'test' if len(self._tests) == 1 else 'tests'
+ if not any(isinstance(x, unittest.TestSuite) for x in self._tests):
+ print '[----------] %d %s' % (len(self._tests), unit)
+ for test in self._tests:
+ if result.shouldStop:
+ break
+ test(result)
+ endts = time.time()
+ ms = (endts - timestamp) * 1000
+ if not any(isinstance(x, unittest.TestSuite) for x in self._tests):
+ print '[----------] %d %s (%d ms total)' % (len(self._tests), unit, ms)
+ print
+ return result
+
+
+class GTestTestRunner(object):
+ def __init__(self, print_result_after_run=True, runner=None):
+ self.print_result_after_run = print_result_after_run
+ self.result = None
+ if runner:
+ self.result = runner.result
+
+ def run(self, test):
+ "Run the given test case or test suite."
+ if not self.result:
+ self.result = gtest_test_results.GTestTestResults()
+ test(self.result)
+ if self.print_result_after_run:
+ self.result.PrintSummary()
+ return self.result
diff --git a/chromium/tools/telemetry/telemetry/unittest/options_for_unittests.py b/chromium/tools/telemetry/telemetry/unittest/options_for_unittests.py
new file mode 100644
index 00000000000..766a6413b94
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/unittest/options_for_unittests.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This module provides the global variable options_for_unittests.
+
+This is set to a BrowserOptions object by the test harness, or None
+if unit tests are not running.
+
+This allows multiple unit tests to use a specific
+browser, in face of multiple options."""
+_options = None
+_browser_type = None
+def Set(options, browser_type):
+ global _options
+ global _browser_type
+
+ _options = options
+ _browser_type = browser_type
+
+def GetCopy():
+ if not _options:
+ return None
+
+ return _options.Copy()
+
+def AreSet():
+ if _options:
+ return True
+ return False
+
+def GetBrowserType():
+ return _browser_type
diff --git a/chromium/tools/telemetry/telemetry/unittest/run_tests.py b/chromium/tools/telemetry/telemetry/unittest/run_tests.py
new file mode 100644
index 00000000000..bc8b1b1889c
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/unittest/run_tests.py
@@ -0,0 +1,142 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+import os
+import sys
+import unittest
+
+from telemetry.core import browser_options
+from telemetry.core import discover
+from telemetry.unittest import gtest_testrunner
+from telemetry.unittest import options_for_unittests
+
+def Discover(start_dir, top_level_dir=None, pattern='test*.py'):
+ loader = unittest.defaultTestLoader
+ loader.suiteClass = gtest_testrunner.GTestTestSuite
+ subsuites = []
+
+ modules = discover.DiscoverModules(start_dir, top_level_dir, pattern)
+ for module in modules:
+ if hasattr(module, 'suite'):
+ new_suite = module.suite()
+ else:
+ new_suite = loader.loadTestsFromModule(module)
+ if new_suite.countTestCases():
+ subsuites.append(new_suite)
+ return gtest_testrunner.GTestTestSuite(subsuites)
+
+
+def FilterSuite(suite, predicate):
+ new_suite = suite.__class__()
+ for x in suite:
+ if isinstance(x, unittest.TestSuite):
+ subsuite = FilterSuite(x, predicate)
+ if subsuite.countTestCases() == 0:
+ continue
+
+ new_suite.addTest(subsuite)
+ continue
+
+ assert isinstance(x, unittest.TestCase)
+ if predicate(x):
+ new_suite.addTest(x)
+
+ return new_suite
+
+
+def DiscoverAndRunTests(
+ dir_name, args, top_level_dir,
+ runner=None, run_disabled_tests=False):
+ if not runner:
+ runner = gtest_testrunner.GTestTestRunner(inner=True)
+
+ suite = Discover(dir_name, top_level_dir, '*_unittest.py')
+
+ def IsTestSelected(test):
+ if len(args) != 0:
+ found = False
+ for name in args:
+ if name in test.id():
+ found = True
+ if not found:
+ return False
+
+ if hasattr(test, '_testMethodName'):
+ method = getattr(test, test._testMethodName) # pylint: disable=W0212
+ if hasattr(method, '_requires_browser_types'):
+ types = method._requires_browser_types # pylint: disable=W0212
+ if options_for_unittests.GetBrowserType() not in types:
+ logging.debug('Skipping test %s because it requires %s' %
+ (test.id(), types))
+ return False
+ if hasattr(method, '_disabled_test'):
+ if not run_disabled_tests:
+ return False
+
+ return True
+
+ filtered_suite = FilterSuite(suite, IsTestSelected)
+ test_result = runner.run(filtered_suite)
+ return test_result
+
+
+def Main(args, start_dir, top_level_dir, runner=None):
+ """Unit test suite that collects all test cases for telemetry."""
+ # Add unittest_data to the path so we can import packages from it.
+ unittest_data_dir = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '..', '..', 'unittest_data'))
+ sys.path.append(unittest_data_dir)
+
+ default_options = browser_options.BrowserOptions()
+ default_options.browser_type = 'any'
+
+ parser = default_options.CreateParser('run_tests [options] [test names]')
+ parser.add_option('--repeat-count', dest='run_test_repeat_count',
+ type='int', default=1,
+ help='Repeats each a provided number of times.')
+ parser.add_option('-d', '--also-run-disabled-tests',
+ dest='run_disabled_tests',
+ action='store_true', default=False,
+ help='Also run tests decorated with @DisabledTest.')
+
+ _, args = parser.parse_args(args)
+
+ logging_level = logging.getLogger().getEffectiveLevel()
+ if default_options.verbosity == 0:
+ logging.getLogger().setLevel(logging.WARN)
+
+ from telemetry.core import browser_finder
+ try:
+ browser_to_create = browser_finder.FindBrowser(default_options)
+ except browser_finder.BrowserFinderException, ex:
+ logging.error(str(ex))
+ return 1
+
+ if browser_to_create == None:
+ logging.error('No browser found of type %s. Cannot run tests.',
+ default_options.browser_type)
+ logging.error('Re-run with --browser=list to see available browser types.')
+ return 1
+
+ options_for_unittests.Set(default_options,
+ browser_to_create.browser_type)
+ olddir = os.getcwd()
+ try:
+ os.chdir(top_level_dir)
+ success = True
+ for _ in range(
+ default_options.run_test_repeat_count): # pylint: disable=E1101
+ success = success and DiscoverAndRunTests(
+ start_dir, args, top_level_dir,
+ runner, default_options.run_disabled_tests)
+ if success:
+ return 0
+ finally:
+ os.chdir(olddir)
+ options_for_unittests.Set(None, None)
+ if default_options.verbosity == 0:
+ # Restore logging level.
+ logging.getLogger().setLevel(logging_level)
+
+ return 1
diff --git a/chromium/tools/telemetry/telemetry/unittest/simple_mock.py b/chromium/tools/telemetry/telemetry/unittest/simple_mock.py
new file mode 100644
index 00000000000..6f7afb637d0
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/unittest/simple_mock.py
@@ -0,0 +1,98 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""A very very simple mock object harness."""
+
+DONT_CARE = ''
+
+class MockFunctionCall(object):
+ def __init__(self, name):
+ self.name = name
+ self.args = tuple()
+ self.return_value = None
+ self.when_called_handlers = []
+
+ def WithArgs(self, *args):
+ self.args = args
+ return self
+
+ def WillReturn(self, value):
+ self.return_value = value
+ return self
+
+ def WhenCalled(self, handler):
+ self.when_called_handlers.append(handler)
+
+ def VerifyEquals(self, got):
+ if self.name != got.name:
+ raise Exception('Self %s, got %s' % (repr(self), repr(got)))
+ if len(self.args) != len(got.args):
+ raise Exception('Self %s, got %s' % (repr(self), repr(got)))
+ for i in range(len(self.args)):
+ self_a = self.args[i]
+ got_a = got.args[i]
+ if self_a == DONT_CARE:
+ continue
+ if self_a != got_a:
+ raise Exception('Self %s, got %s' % (repr(self), repr(got)))
+
+ def __repr__(self):
+ def arg_to_text(a):
+ if a == DONT_CARE:
+ return '_'
+ return repr(a)
+ args_text = ', '.join([arg_to_text(a) for a in self.args])
+ if self.return_value in (None, DONT_CARE):
+ return '%s(%s)' % (self.name, args_text)
+ return '%s(%s)->%s' % (self.name, args_text, repr(self.return_value))
+
+class MockTrace(object):
+ def __init__(self):
+ self.expected_calls = []
+ self.next_call_index = 0
+
+class MockObject(object):
+ def __init__(self, parent_mock = None):
+ if parent_mock:
+ self._trace = parent_mock._trace # pylint: disable=W0212
+ else:
+ self._trace = MockTrace()
+
+ def __setattr__(self, name, value):
+ if (not hasattr(self, '_trace') or
+ hasattr(value, 'is_hook')):
+ object.__setattr__(self, name, value)
+ return
+ assert isinstance(value, MockObject)
+ object.__setattr__(self, name, value)
+
+ def ExpectCall(self, func_name, *args):
+ assert self._trace.next_call_index == 0
+ if not hasattr(self, func_name):
+ self._install_hook(func_name)
+
+ call = MockFunctionCall(func_name)
+ self._trace.expected_calls.append(call)
+ call.WithArgs(*args)
+ return call
+
+ def _install_hook(self, func_name):
+ def handler(*args):
+ got_call = MockFunctionCall(
+ func_name).WithArgs(*args).WillReturn(DONT_CARE)
+ if self._trace.next_call_index >= len(self._trace.expected_calls):
+ raise Exception(
+ 'Call to %s was not expected, at end of programmed trace.' %
+ repr(got_call))
+ expected_call = self._trace.expected_calls[
+ self._trace.next_call_index]
+ expected_call.VerifyEquals(got_call)
+ self._trace.next_call_index += 1
+ for h in expected_call.when_called_handlers:
+ h(*args)
+ return expected_call.return_value
+ handler.is_hook = True
+ setattr(self, func_name, handler)
+
+
+
diff --git a/chromium/tools/telemetry/telemetry/unittest/simple_mock_unittest.py b/chromium/tools/telemetry/telemetry/unittest/simple_mock_unittest.py
new file mode 100644
index 00000000000..f62febc6909
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/unittest/simple_mock_unittest.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.unittest import simple_mock
+
+_ = simple_mock.DONT_CARE
+
+class SimpleMockUnitTest(unittest.TestCase):
+ def testBasic(self):
+ mock = simple_mock.MockObject()
+ mock.ExpectCall('foo')
+
+ mock.foo()
+
+ def testReturn(self):
+ mock = simple_mock.MockObject()
+ mock.ExpectCall('foo').WillReturn(7)
+
+ ret = mock.foo()
+ self.assertEquals(ret, 7)
+
+ def testArgs(self):
+ mock = simple_mock.MockObject()
+ mock.ExpectCall('foo').WithArgs(3, 4)
+
+ mock.foo(3, 4)
+
+ def testArgs2(self):
+ mock = simple_mock.MockObject()
+ mock.ExpectCall('foo', 3, 4)
+
+ mock.foo(3, 4)
+
+ def testArgsMismatch(self):
+ mock = simple_mock.MockObject()
+ mock.ExpectCall('foo').WithArgs(3, 4)
+
+ self.assertRaises(Exception,
+ lambda: mock.foo(4, 4))
+
+
+ def testArgsDontCare(self):
+ mock = simple_mock.MockObject()
+ mock.ExpectCall('foo').WithArgs(_, 4)
+
+ mock.foo(4, 4)
+
+ def testOnCall(self):
+ mock = simple_mock.MockObject()
+
+ handler_called = []
+ def Handler(arg0):
+ assert arg0 == 7
+ handler_called.append(True)
+ mock.ExpectCall('baz', 7).WhenCalled(Handler)
+
+ mock.baz(7)
+ self.assertTrue(len(handler_called) > 0)
+
+
+ def testSubObject(self):
+ mock = simple_mock.MockObject()
+ mock.bar = simple_mock.MockObject(mock)
+
+ mock.ExpectCall('foo').WithArgs(_, 4)
+ mock.bar.ExpectCall('baz')
+
+ mock.foo(0, 4)
+ mock.bar.baz()
+
+ def testSubObjectMismatch(self):
+ mock = simple_mock.MockObject()
+ mock.bar = simple_mock.MockObject(mock)
+
+ mock.ExpectCall('foo').WithArgs(_, 4)
+ mock.bar.ExpectCall('baz')
+
+ self.assertRaises(
+ Exception,
+ lambda: mock.bar.baz()) # pylint: disable=W0108
+
+
diff --git a/chromium/tools/telemetry/telemetry/unittest/system_stub.py b/chromium/tools/telemetry/telemetry/unittest/system_stub.py
new file mode 100644
index 00000000000..b647f5fb593
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/unittest/system_stub.py
@@ -0,0 +1,165 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Provides stubs for os, sys and subprocess for testing
+
+This test allows one to test code that itself uses os, sys, and subprocess.
+"""
+
+import os
+import re
+import shlex
+import sys as real_sys
+
+class Override(object):
+ def __init__(self, base_module, module_list):
+ stubs = {'adb_commands': AdbCommandsModuleStub,
+ 'os': OsModuleStub,
+ 'subprocess': SubprocessModuleStub,
+ 'sys': SysModuleStub,
+ }
+ self.adb_commands = None
+ self.os = None
+ self.subprocess = None
+ self.sys = None
+
+ self._base_module = base_module
+ self._overrides = {}
+
+ for module_name in module_list:
+ self._overrides[module_name] = getattr(base_module, module_name)
+ setattr(self, module_name, stubs[module_name]())
+ setattr(base_module, module_name, getattr(self, module_name))
+
+ if self.os and self.sys:
+ self.os.path.sys = self.sys
+
+ def __del__(self):
+ assert not len(self._overrides)
+
+ def Restore(self):
+ for module_name, original_module in self._overrides.iteritems():
+ setattr(self._base_module, module_name, original_module)
+ self._overrides = {}
+
+class AdbCommandsModuleStub(object):
+# adb not even found
+# android_browser_finder not returning
+ class AdbCommandsStub(object):
+ def __init__(self, module, device):
+ self._module = module
+ self._device = device
+ self.is_root_enabled = True
+
+ def RunShellCommand(self, args):
+ if isinstance(args, basestring):
+ args = shlex.split(args)
+ handler = self._module.shell_command_handlers[args[0]]
+ return handler(args)
+
+ def IsRootEnabled(self):
+ return self.is_root_enabled
+
+ def __init__(self):
+ self.attached_devices = []
+ self.shell_command_handlers = {}
+
+ def AdbCommandsStubConstructor(device=None):
+ return AdbCommandsModuleStub.AdbCommandsStub(self, device)
+ self.AdbCommands = AdbCommandsStubConstructor
+
+ @staticmethod
+ def IsAndroidSupported():
+ return True
+
+ def GetAttachedDevices(self):
+ return self.attached_devices
+
+ @staticmethod
+ def HasForwarder(_=None):
+ return True
+
+class OsModuleStub(object):
+ class OsPathModuleStub(object):
+ def __init__(self, sys_module):
+ self.sys = sys_module
+ self.files = []
+
+ def exists(self, path):
+ return path in self.files
+
+ def isfile(self, path):
+ return path in self.files
+
+ def join(self, *paths):
+ def IsAbsolutePath(path):
+ if self.sys.platform.startswith('win'):
+ return re.match('[a-zA-Z]:\\\\', path)
+ else:
+ return path.startswith('/')
+
+ # Per Python specification, if any component is an absolute path,
+ # discard previous components.
+ for index, path in reversed(list(enumerate(paths))):
+ if IsAbsolutePath(path):
+ paths = paths[index:]
+ break
+
+ if self.sys.platform.startswith('win'):
+ tmp = os.path.join(*paths)
+ return tmp.replace('/', '\\')
+ else:
+ tmp = os.path.join(*paths)
+ return tmp.replace('\\', '/')
+
+ def expanduser(self, filename):
+ return os.path.expanduser(filename)
+
+ def dirname(self, filename): # pylint: disable=R0201
+ return os.path.dirname(filename)
+
+ X_OK = os.X_OK
+
+ def __init__(self, sys_module=real_sys):
+ self.path = OsModuleStub.OsPathModuleStub(sys_module)
+ self.display = ':0'
+ self.local_app_data = None
+ self.program_files = None
+ self.program_files_x86 = None
+ self.devnull = os.devnull
+
+ def access(self, path, _):
+ return path in self.path.files
+
+ def getenv(self, name):
+ if name == 'DISPLAY':
+ return self.display
+ elif name == 'LOCALAPPDATA':
+ return self.local_app_data
+ elif name == 'PROGRAMFILES':
+ return self.program_files
+ elif name == 'PROGRAMFILES(X86)':
+ return self.program_files_x86
+ raise Exception('Unsupported getenv')
+
+class SubprocessModuleStub(object):
+ class PopenStub(object):
+ def __init__(self):
+ self.communicate_result = ('', '')
+
+ def __call__(self, args, **kwargs):
+ return self
+
+ def communicate(self):
+ return self.communicate_result
+
+ def __init__(self):
+ self.Popen = SubprocessModuleStub.PopenStub()
+ self.PIPE = None
+
+ def call(self, *args, **kwargs):
+ raise NotImplementedError()
+
+class SysModuleStub(object):
+ def __init__(self):
+ self.platform = ''
diff --git a/chromium/tools/telemetry/telemetry/unittest/tab_test_case.py b/chromium/tools/telemetry/telemetry/unittest/tab_test_case.py
new file mode 100644
index 00000000000..480da88604c
--- /dev/null
+++ b/chromium/tools/telemetry/telemetry/unittest/tab_test_case.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import unittest
+
+from telemetry.core import browser_finder
+from telemetry.unittest import options_for_unittests
+
+class TabTestCase(unittest.TestCase):
+ def __init__(self, *args):
+ self._extra_browser_args = []
+ super(TabTestCase, self).__init__(*args)
+
+ def setUp(self):
+ self._browser = None
+ self._tab = None
+ options = options_for_unittests.GetCopy()
+
+ self.CustomizeBrowserOptions(options)
+
+ if self._extra_browser_args:
+ for arg in self._extra_browser_args:
+ options.extra_browser_args.append(arg)
+
+ browser_to_create = browser_finder.FindBrowser(options)
+ if not browser_to_create:
+ raise Exception('No browser found, cannot continue test.')
+ try:
+ self._browser = browser_to_create.Create()
+ self._browser.Start()
+ self._tab = self._browser.tabs[0]
+ except:
+ self.tearDown()
+ raise
+
+ def tearDown(self):
+ if self._tab:
+ self._tab.Disconnect()
+ if self._browser:
+ self._browser.Close()
+
+ def CustomizeBrowserOptions(self, options):
+ """Override to add test-specific options to the BrowserOptions object"""
+ pass
diff --git a/chromium/tools/telemetry/third_party/davclient/README.chromium b/chromium/tools/telemetry/third_party/davclient/README.chromium
new file mode 100644
index 00000000000..47acf8d4a8c
--- /dev/null
+++ b/chromium/tools/telemetry/third_party/davclient/README.chromium
@@ -0,0 +1,17 @@
+Name: Davclient
+Short Name: davclient
+URL: http://svn.osafoundation.org/tools/davclient/
+Version: 0.2.1
+Date: Undated, retrieved Dec 14, 2012
+Revision: r1008
+License: Apache 2.0
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+A simple Python WebDAV client. Used for the Telemetry bootstrap to easily
+fetch files from SVN servers.
+
+Local Modifications:
+None. However packaging and installation code from original repository have not
+been copied.
diff --git a/chromium/tools/telemetry/third_party/davclient/davclient.py b/chromium/tools/telemetry/third_party/davclient/davclient.py
new file mode 100644
index 00000000000..2d9107aa9fb
--- /dev/null
+++ b/chromium/tools/telemetry/third_party/davclient/davclient.py
@@ -0,0 +1,312 @@
+# Copyright (c) 2006-2007 Open Source Applications Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import urlparse, httplib, copy, base64, StringIO
+import urllib
+
+try:
+ from xml.etree import ElementTree
+except:
+ from elementtree import ElementTree
+
+__all__ = ['DAVClient']
+
+def object_to_etree(parent, obj, namespace=''):
+ """This function takes in a python object, traverses it, and adds it to an existing etree object"""
+
+ if type(obj) is int or type(obj) is float or type(obj) is str:
+ # If object is a string, int, or float just add it
+ obj = str(obj)
+ if obj.startswith('{') is False:
+ ElementTree.SubElement(parent, '{%s}%s' % (namespace, obj))
+ else:
+ ElementTree.SubElement(parent, obj)
+
+ elif type(obj) is dict:
+ # If the object is a dictionary we'll need to parse it and send it back recusively
+ for key, value in obj.items():
+ if key.startswith('{') is False:
+ key_etree = ElementTree.SubElement(parent, '{%s}%s' % (namespace, key))
+ object_to_etree(key_etree, value, namespace=namespace)
+ else:
+ key_etree = ElementTree.SubElement(parent, key)
+ object_to_etree(key_etree, value, namespace=namespace)
+
+ elif type(obj) is list:
+ # If the object is a list parse it and send it back recursively
+ for item in obj:
+ object_to_etree(parent, item, namespace=namespace)
+
+ else:
+ # If it's none of previous types then raise
+ raise TypeError, '%s is an unsupported type' % type(obj)
+
+
+class DAVClient(object):
+
+ def __init__(self, url='http://localhost:8080'):
+ """Initialization"""
+
+ self._url = urlparse.urlparse(url)
+
+ self.headers = {'Host':self._url[1],
+ 'User-Agent': 'python.davclient.DAVClient/0.1'}
+
+
+ def _request(self, method, path='', body=None, headers=None):
+ """Internal request method"""
+ self.response = None
+
+ if headers is None:
+ headers = copy.copy(self.headers)
+ else:
+ new_headers = copy.copy(self.headers)
+ new_headers.update(headers)
+ headers = new_headers
+
+ if self._url.scheme == 'http':
+ self._connection = httplib.HTTPConnection(self._url[1])
+ elif self._url.scheme == 'https':
+ self._connection = httplib.HTTPSConnection(self._url[1])
+ else:
+ raise Exception, 'Unsupported scheme'
+
+ self._connection.request(method, path, body, headers)
+
+ self.response = self._connection.getresponse()
+
+ self.response.body = self.response.read()
+
+ # Try to parse and get an etree
+ try:
+ self._get_response_tree()
+ except:
+ pass
+
+
+ def _get_response_tree(self):
+ """Parse the response body into an elementree object"""
+ self.response.tree = ElementTree.fromstring(self.response.body)
+ return self.response.tree
+
+ def set_basic_auth(self, username, password):
+ """Set basic authentication"""
+ auth = 'Basic %s' % base64.encodestring('%s:%s' % (username, password)).strip()
+ self._username = username
+ self._password = password
+ self.headers['Authorization'] = auth
+
+ ## HTTP DAV methods ##
+
+ def get(self, path, headers=None):
+ """Simple get request"""
+ self._request('GET', path, headers=headers)
+ return self.response.body
+
+ def head(self, path, headers=None):
+ """Basic HEAD request"""
+ self._request('HEAD', path, headers=headers)
+
+ def put(self, path, body=None, f=None, headers=None):
+ """Put resource with body"""
+ if f is not None:
+ body = f.read()
+
+ self._request('PUT', path, body=body, headers=headers)
+
+ def post(self, path, body=None, headers=None):
+ """POST resource with body"""
+
+ self._request('POST', path, body=body, headers=headers)
+
+ def mkcol(self, path, headers=None):
+ """Make DAV collection"""
+ self._request('MKCOL', path=path, headers=headers)
+
+ make_collection = mkcol
+
+ def delete(self, path, headers=None):
+ """Delete DAV resource"""
+ self._request('DELETE', path=path, headers=headers)
+
+ def copy(self, source, destination, body=None, depth='infinity', overwrite=True, headers=None):
+ """Copy DAV resource"""
+ # Set all proper headers
+ if headers is None:
+ headers = {'Destination':destination}
+ else:
+ headers['Destination'] = self._url.geturl() + destination
+ if overwrite is False:
+ headers['Overwrite'] = 'F'
+ headers['Depth'] = depth
+
+ self._request('COPY', source, body=body, headers=headers)
+
+
+ def copy_collection(self, source, destination, depth='infinity', overwrite=True, headers=None):
+ """Copy DAV collection"""
+ body = '<?xml version="1.0" encoding="utf-8" ?><d:propertybehavior xmlns:d="DAV:"><d:keepalive>*</d:keepalive></d:propertybehavior>'
+
+ # Add proper headers
+ if headers is None:
+ headers = {}
+ headers['Content-Type'] = 'text/xml; charset="utf-8"'
+
+ self.copy(source, destination, body=unicode(body, 'utf-8'), depth=depth, overwrite=overwrite, headers=headers)
+
+
+ def move(self, source, destination, body=None, depth='infinity', overwrite=True, headers=None):
+ """Move DAV resource"""
+ # Set all proper headers
+ if headers is None:
+ headers = {'Destination':destination}
+ else:
+ headers['Destination'] = self._url.geturl() + destination
+ if overwrite is False:
+ headers['Overwrite'] = 'F'
+ headers['Depth'] = depth
+
+ self._request('MOVE', source, body=body, headers=headers)
+
+
+ def move_collection(self, source, destination, depth='infinity', overwrite=True, headers=None):
+ """Move DAV collection and copy all properties"""
+ body = '<?xml version="1.0" encoding="utf-8" ?><d:propertybehavior xmlns:d="DAV:"><d:keepalive>*</d:keepalive></d:propertybehavior>'
+
+ # Add proper headers
+ if headers is None:
+ headers = {}
+ headers['Content-Type'] = 'text/xml; charset="utf-8"'
+
+ self.move(source, destination, unicode(body, 'utf-8'), depth=depth, overwrite=overwrite, headers=headers)
+
+
+ def propfind(self, path, properties='allprop', namespace='DAV:', depth=None, headers=None):
+ """Property find. If properties arg is unspecified it defaults to 'allprop'"""
+ # Build propfind xml
+ root = ElementTree.Element('{DAV:}propfind')
+ if type(properties) is str:
+ ElementTree.SubElement(root, '{DAV:}%s' % properties)
+ else:
+ props = ElementTree.SubElement(root, '{DAV:}prop')
+ object_to_etree(props, properties, namespace=namespace)
+ tree = ElementTree.ElementTree(root)
+
+ # Etree won't just return a normal string, so we have to do this
+ body = StringIO.StringIO()
+ tree.write(body)
+ body = body.getvalue()
+
+ # Add proper headers
+ if headers is None:
+ headers = {}
+ if depth is not None:
+ headers['Depth'] = depth
+ headers['Content-Type'] = 'text/xml; charset="utf-8"'
+
+ # Body encoding must be utf-8, 207 is proper response
+ self._request('PROPFIND', path, body=unicode('<?xml version="1.0" encoding="utf-8" ?>\n'+body, 'utf-8'), headers=headers)
+
+ if self.response is not None and hasattr(self.response, 'tree') is True:
+ property_responses = {}
+ for response in self.response.tree._children:
+ property_href = response.find('{DAV:}href')
+ property_stat = response.find('{DAV:}propstat')
+
+ def parse_props(props):
+ property_dict = {}
+ for prop in props:
+ if prop.tag.find('{DAV:}') is not -1:
+ name = prop.tag.split('}')[-1]
+ else:
+ name = prop.tag
+ if len(prop._children) is not 0:
+ property_dict[name] = parse_props(prop._children)
+ else:
+ property_dict[name] = prop.text
+ return property_dict
+
+ if property_href is not None and property_stat is not None:
+ property_dict = parse_props(property_stat.find('{DAV:}prop')._children)
+ property_responses[property_href.text] = property_dict
+ return property_responses
+
+ def proppatch(self, path, set_props=None, remove_props=None, namespace='DAV:', headers=None):
+ """Patch properties on a DAV resource. If namespace is not specified the DAV namespace is used for all properties"""
+ root = ElementTree.Element('{DAV:}propertyupdate')
+
+ if set_props is not None:
+ prop_set = ElementTree.SubElement(root, '{DAV:}set')
+ object_to_etree(prop_set, set_props, namespace=namespace)
+ if remove_props is not None:
+ prop_remove = ElementTree.SubElement(root, '{DAV:}remove')
+ object_to_etree(prop_remove, remove_props, namespace=namespace)
+
+ tree = ElementTree.ElementTree(root)
+
+ # Add proper headers
+ if headers is None:
+ headers = {}
+ headers['Content-Type'] = 'text/xml; charset="utf-8"'
+
+ self._request('PROPPATCH', path, body=unicode('<?xml version="1.0" encoding="utf-8" ?>\n'+body, 'utf-8'), headers=headers)
+
+
+ def set_lock(self, path, owner, locktype='exclusive', lockscope='write', depth=None, headers=None):
+ """Set a lock on a dav resource"""
+ root = ElementTree.Element('{DAV:}lockinfo')
+ object_to_etree(root, {'locktype':locktype, 'lockscope':lockscope, 'owner':{'href':owner}}, namespace='DAV:')
+ tree = ElementTree.ElementTree(root)
+
+ # Add proper headers
+ if headers is None:
+ headers = {}
+ if depth is not None:
+ headers['Depth'] = depth
+ headers['Content-Type'] = 'text/xml; charset="utf-8"'
+ headers['Timeout'] = 'Infinite, Second-4100000000'
+
+ self._request('LOCK', path, body=unicode('<?xml version="1.0" encoding="utf-8" ?>\n'+body, 'utf-8'), headers=headers)
+
+ locks = self.response.etree.finall('.//{DAV:}locktoken')
+ lock_list = []
+ for lock in locks:
+ lock_list.append(lock.getchildren()[0].text.strip().strip('\n'))
+ return lock_list
+
+
+ def refresh_lock(self, path, token, headers=None):
+ """Refresh lock with token"""
+
+ if headers is None:
+ headers = {}
+ headers['If'] = '(<%s>)' % token
+ headers['Timeout'] = 'Infinite, Second-4100000000'
+
+ self._request('LOCK', path, body=None, headers=headers)
+
+
+ def unlock(self, path, token, headers=None):
+ """Unlock DAV resource with token"""
+ if headers is None:
+ headers = {}
+ headers['Lock-Tocken'] = '<%s>' % token
+
+ self._request('UNLOCK', path, body=None, headers=headers)
+
+
+
+
+
+
diff --git a/chromium/tools/telemetry/third_party/png/README.chromium b/chromium/tools/telemetry/third_party/png/README.chromium
new file mode 100644
index 00000000000..d838ece145e
--- /dev/null
+++ b/chromium/tools/telemetry/third_party/png/README.chromium
@@ -0,0 +1,17 @@
+Name: Pure Python PNG Reader/Writer
+Short Name: pypng
+URL: https://github.com/drj11/pypng/
+Version: 0
+Date: 2009-03-11
+Revision: dd1797c361eafa443878b0915f767b75bd518d3b
+License: MIT
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+A png encoder and decoder for python. Used by telemetry to decode screenshots
+captured via the gpuBenchmark.windowSnapshot API, which are returned as
+Base64-encoded PNG files.
+
+Local Modifications:
+None. \ No newline at end of file
diff --git a/chromium/tools/telemetry/third_party/png/png.py b/chromium/tools/telemetry/third_party/png/png.py
new file mode 100755
index 00000000000..b55dd3aba4b
--- /dev/null
+++ b/chromium/tools/telemetry/third_party/png/png.py
@@ -0,0 +1,3857 @@
+#!/usr/bin/env python
+
+# $URL$
+# $Rev$
+
+# png.py - PNG encoder/decoder in pure Python
+#
+# Copyright (C) 2006 Johann C. Rocholl <johann@browsershots.org>
+# Portions Copyright (C) 2009 David Jones <drj@pobox.com>
+# And probably portions Copyright (C) 2006 Nicko van Someren <nicko@nicko.org>
+#
+# Original concept by Johann C. Rocholl.
+#
+# LICENSE (The MIT License)
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# Changelog (recent first):
+# 2009-03-11 David: interlaced bit depth < 8 (writing).
+# 2009-03-10 David: interlaced bit depth < 8 (reading).
+# 2009-03-04 David: Flat and Boxed pixel formats.
+# 2009-02-26 David: Palette support (writing).
+# 2009-02-23 David: Bit-depths < 8; better PNM support.
+# 2006-06-17 Nicko: Reworked into a class, faster interlacing.
+# 2006-06-17 Johann: Very simple prototype PNG decoder.
+# 2006-06-17 Nicko: Test suite with various image generators.
+# 2006-06-17 Nicko: Alpha-channel, grey-scale, 16-bit/plane support.
+# 2006-06-15 Johann: Scanline iterator interface for large input files.
+# 2006-06-09 Johann: Very simple prototype PNG encoder.
+
+# Incorporated into Bangai-O Development Tools by drj on 2009-02-11 from
+# http://trac.browsershots.org/browser/trunk/pypng/lib/png.py?rev=2885
+
+# Incorporated into pypng by drj on 2009-03-12 from
+# //depot/prj/bangaio/master/code/png.py#67
+
+
+"""
+Pure Python PNG Reader/Writer
+
+This Python module implements support for PNG images (see PNG
+specification at http://www.w3.org/TR/2003/REC-PNG-20031110/ ). It reads
+and writes PNG files with all allowable bit depths (1/2/4/8/16/24/32/48/64
+bits per pixel) and colour combinations: greyscale (1/2/4/8/16 bit); RGB,
+RGBA, LA (greyscale with alpha) with 8/16 bits per channel; colour mapped
+images (1/2/4/8 bit). Adam7 interlacing is supported for reading and
+writing. A number of optional chunks can be specified (when writing)
+and understood (when reading): ``tRNS``, ``bKGD``, ``gAMA``.
+
+For help, type ``import png; help(png)`` in your python interpreter.
+
+A good place to start is the :class:`Reader` and :class:`Writer` classes.
+
+Requires Python 2.3. Limited support is available for Python 2.2, but
+not everything works. Best with Python 2.4 and higher. Installation is
+trivial, but see the ``README.txt`` file (with the source distribution)
+for details.
+
+This file can also be used as a command-line utility to convert
+`Netpbm <http://netpbm.sourceforge.net/>`_ PNM files to PNG, and the reverse conversion from PNG to
+PNM. The interface is similar to that of the ``pnmtopng`` program from
+Netpbm. Type ``python png.py --help`` at the shell prompt
+for usage and a list of options.
+
+A note on spelling and terminology
+----------------------------------
+
+Generally British English spelling is used in the documentation. So
+that's "greyscale" and "colour". This not only matches the author's
+native language, it's also used by the PNG specification.
+
+The major colour models supported by PNG (and hence by PyPNG) are:
+greyscale, RGB, greyscale--alpha, RGB--alpha. These are sometimes
+referred to using the abbreviations: L, RGB, LA, RGBA. In this case
+each letter abbreviates a single channel: *L* is for Luminance or Luma or
+Lightness which is the channel used in greyscale images; *R*, *G*, *B* stand
+for Red, Green, Blue, the components of a colour image; *A* stands for
+Alpha, the opacity channel (used for transparency effects, but higher
+values are more opaque, so it makes sense to call it opacity).
+
+A note on formats
+-----------------
+
+When getting pixel data out of this module (reading) and presenting
+data to this module (writing) there are a number of ways the data could
+be represented as a Python value. Generally this module uses one of
+three formats called "flat row flat pixel", "boxed row flat pixel", and
+"boxed row boxed pixel". Basically the concern is whether each pixel
+and each row comes in its own little tuple (box), or not.
+
+Consider an image that is 3 pixels wide by 2 pixels high, and each pixel
+has RGB components:
+
+Boxed row flat pixel::
+
+ list([R,G,B, R,G,B, R,G,B],
+ [R,G,B, R,G,B, R,G,B])
+
+Each row appears as its own list, but the pixels are flattened so that
+three values for one pixel simply follow the three values for the previous
+pixel. This is the most common format used, because it provides a good
+compromise between space and convenience. PyPNG regards itself as
+at liberty to replace any sequence type with any sufficiently compatible
+other sequence type; in practice each row is an array (from the array
+module), and the outer list is sometimes an iterator rather than an
+explicit list (so that streaming is possible).
+
+Flat row flat pixel::
+
+ [R,G,B, R,G,B, R,G,B,
+ R,G,B, R,G,B, R,G,B]
+
+The entire image is one single giant sequence of colour values.
+Generally an array will be used (to save space), not a list.
+
+Boxed row boxed pixel::
+
+ list([ (R,G,B), (R,G,B), (R,G,B) ],
+ [ (R,G,B), (R,G,B), (R,G,B) ])
+
+Each row appears in its own list, but each pixel also appears in its own
+tuple. A serious memory burn in Python.
+
+In all cases the top row comes first, and for each row the pixels are
+ordered from left-to-right. Within a pixel the values appear in the
+order, R-G-B-A (or L-A for greyscale--alpha).
+
+There is a fourth format, mentioned because it is used internally,
+is close to what lies inside a PNG file itself, and has some support
+from the public API. This format is called packed. When packed,
+each row is a sequence of bytes (integers from 0 to 255), just as
+it is before PNG scanline filtering is applied. When the bit depth
+is 8 this is essentially the same as boxed row flat pixel; when the
+bit depth is less than 8, several pixels are packed into each byte;
+when the bit depth is 16 (the only value more than 8 that is supported
+by the PNG image format) each pixel value is decomposed into 2 bytes
+(and `packed` is a misnomer). This format is used by the
+:meth:`Writer.write_packed` method. It isn't usually a convenient
+format, but may be just right if the source data for the PNG image
+comes from something that uses a similar format (for example, 1-bit
+BMPs, or another PNG file).
+
+And now, my famous members
+--------------------------
+"""
+
+# http://www.python.org/doc/2.2.3/whatsnew/node5.html
+from __future__ import generators
+
+__version__ = "$URL$ $Rev$"
+
+from array import array
+try: # See :pyver:old
+ import itertools
+except:
+ pass
+import math
+# http://www.python.org/doc/2.4.4/lib/module-operator.html
+import operator
+import struct
+import sys
+import zlib
+# http://www.python.org/doc/2.4.4/lib/module-warnings.html
+import warnings
+try:
+ import pyximport
+ pyximport.install()
+ import cpngfilters as pngfilters
+except ImportError:
+ pass
+
+
+__all__ = ['Image', 'Reader', 'Writer', 'write_chunks', 'from_array']
+
+
+# The PNG signature.
+# http://www.w3.org/TR/PNG/#5PNG-file-signature
+_signature = struct.pack('8B', 137, 80, 78, 71, 13, 10, 26, 10)
+
+_adam7 = ((0, 0, 8, 8),
+ (4, 0, 8, 8),
+ (0, 4, 4, 8),
+ (2, 0, 4, 4),
+ (0, 2, 2, 4),
+ (1, 0, 2, 2),
+ (0, 1, 1, 2))
+
+def group(s, n):
+ # See
+ # http://www.python.org/doc/2.6/library/functions.html#zip
+ return zip(*[iter(s)]*n)
+
+def isarray(x):
+ """Same as ``isinstance(x, array)`` except on Python 2.2, where it
+ always returns ``False``. This helps PyPNG work on Python 2.2.
+ """
+
+ try:
+ return isinstance(x, array)
+ except:
+ return False
+
+try: # see :pyver:old
+ array.tostring
+except:
+ def tostring(row):
+ l = len(row)
+ return struct.pack('%dB' % l, *row)
+else:
+ def tostring(row):
+ """Convert row of bytes to string. Expects `row` to be an
+ ``array``.
+ """
+ return row.tostring()
+
+# Conditionally convert to bytes. Works on Python 2 and Python 3.
+try:
+ bytes('', 'ascii')
+ def strtobytes(x): return bytes(x, 'iso8859-1')
+ def bytestostr(x): return str(x, 'iso8859-1')
+except:
+ strtobytes = str
+ bytestostr = str
+
+def interleave_planes(ipixels, apixels, ipsize, apsize):
+ """
+ Interleave (colour) planes, e.g. RGB + A = RGBA.
+
+ Return an array of pixels consisting of the `ipsize` elements of data
+ from each pixel in `ipixels` followed by the `apsize` elements of data
+ from each pixel in `apixels`. Conventionally `ipixels` and
+ `apixels` are byte arrays so the sizes are bytes, but it actually
+ works with any arrays of the same type. The returned array is the
+ same type as the input arrays which should be the same type as each other.
+ """
+
+ itotal = len(ipixels)
+ atotal = len(apixels)
+ newtotal = itotal + atotal
+ newpsize = ipsize + apsize
+ # Set up the output buffer
+ # See http://www.python.org/doc/2.4.4/lib/module-array.html#l2h-1356
+ out = array(ipixels.typecode)
+ # It's annoying that there is no cheap way to set the array size :-(
+ out.extend(ipixels)
+ out.extend(apixels)
+ # Interleave in the pixel data
+ for i in range(ipsize):
+ out[i:newtotal:newpsize] = ipixels[i:itotal:ipsize]
+ for i in range(apsize):
+ out[i+ipsize:newtotal:newpsize] = apixels[i:atotal:apsize]
+ return out
+
+def check_palette(palette):
+ """Check a palette argument (to the :class:`Writer` class) for validity.
+ Returns the palette as a list if okay; raises an exception otherwise.
+ """
+
+ # None is the default and is allowed.
+ if palette is None:
+ return None
+
+ p = list(palette)
+ if not (0 < len(p) <= 256):
+ raise ValueError("a palette must have between 1 and 256 entries")
+ seen_triple = False
+ for i,t in enumerate(p):
+ if len(t) not in (3,4):
+ raise ValueError(
+ "palette entry %d: entries must be 3- or 4-tuples." % i)
+ if len(t) == 3:
+ seen_triple = True
+ if seen_triple and len(t) == 4:
+ raise ValueError(
+ "palette entry %d: all 4-tuples must precede all 3-tuples" % i)
+ for x in t:
+ if int(x) != x or not(0 <= x <= 255):
+ raise ValueError(
+ "palette entry %d: values must be integer: 0 <= x <= 255" % i)
+ return p
+
+class Error(Exception):
+ prefix = 'Error'
+ def __str__(self):
+ return self.prefix + ': ' + ' '.join(self.args)
+
+class FormatError(Error):
+ """Problem with input file format. In other words, PNG file does
+ not conform to the specification in some way and is invalid.
+ """
+
+ prefix = 'FormatError'
+
+class ChunkError(FormatError):
+ prefix = 'ChunkError'
+
+
+class Writer:
+ """
+ PNG encoder in pure Python.
+ """
+
+ def __init__(self, width=None, height=None,
+ size=None,
+ greyscale=False,
+ alpha=False,
+ bitdepth=8,
+ palette=None,
+ transparent=None,
+ background=None,
+ gamma=None,
+ compression=None,
+ interlace=False,
+ bytes_per_sample=None, # deprecated
+ planes=None,
+ colormap=None,
+ maxval=None,
+ chunk_limit=2**20):
+ """
+ Create a PNG encoder object.
+
+ Arguments:
+
+ width, height
+ Image size in pixels, as two separate arguments.
+ size
+ Image size (w,h) in pixels, as single argument.
+ greyscale
+ Input data is greyscale, not RGB.
+ alpha
+ Input data has alpha channel (RGBA or LA).
+ bitdepth
+ Bit depth: from 1 to 16.
+ palette
+ Create a palette for a colour mapped image (colour type 3).
+ transparent
+ Specify a transparent colour (create a ``tRNS`` chunk).
+ background
+ Specify a default background colour (create a ``bKGD`` chunk).
+ gamma
+ Specify a gamma value (create a ``gAMA`` chunk).
+ compression
+ zlib compression level: 0 (none) to 9 (more compressed); default: -1 or None.
+ interlace
+ Create an interlaced image.
+ chunk_limit
+ Write multiple ``IDAT`` chunks to save memory.
+
+ The image size (in pixels) can be specified either by using the
+ `width` and `height` arguments, or with the single `size`
+ argument. If `size` is used it should be a pair (*width*,
+ *height*).
+
+ `greyscale` and `alpha` are booleans that specify whether
+ an image is greyscale (or colour), and whether it has an
+ alpha channel (or not).
+
+ `bitdepth` specifies the bit depth of the source pixel values.
+ Each source pixel value must be an integer between 0 and
+ ``2**bitdepth-1``. For example, 8-bit images have values
+ between 0 and 255. PNG only stores images with bit depths of
+ 1,2,4,8, or 16. When `bitdepth` is not one of these values,
+ the next highest valid bit depth is selected, and an ``sBIT``
+ (significant bits) chunk is generated that specifies the original
+ precision of the source image. In this case the supplied pixel
+ values will be rescaled to fit the range of the selected bit depth.
+
+ The details of which bit depth / colour model combinations the
+ PNG file format supports directly, are somewhat arcane
+ (refer to the PNG specification for full details). Briefly:
+ "small" bit depths (1,2,4) are only allowed with greyscale and
+ colour mapped images; colour mapped images cannot have bit depth
+ 16.
+
+ For colour mapped images (in other words, when the `palette`
+ argument is specified) the `bitdepth` argument must match one of
+ the valid PNG bit depths: 1, 2, 4, or 8. (It is valid to have a
+ PNG image with a palette and an ``sBIT`` chunk, but the meaning
+ is slightly different; it would be awkward to press the
+ `bitdepth` argument into service for this.)
+
+ The `palette` option, when specified, causes a colour mapped image
+ to be created: the PNG colour type is set to 3; greyscale
+ must not be set; alpha must not be set; transparent must
+ not be set; the bit depth must be 1,2,4, or 8. When a colour
+ mapped image is created, the pixel values are palette indexes
+ and the `bitdepth` argument specifies the size of these indexes
+ (not the size of the colour values in the palette).
+
+ The palette argument value should be a sequence of 3- or
+ 4-tuples. 3-tuples specify RGB palette entries; 4-tuples
+ specify RGBA palette entries. If both 4-tuples and 3-tuples
+ appear in the sequence then all the 4-tuples must come
+ before all the 3-tuples. A ``PLTE`` chunk is created; if there
+ are 4-tuples then a ``tRNS`` chunk is created as well. The
+ ``PLTE`` chunk will contain all the RGB triples in the same
+ sequence; the ``tRNS`` chunk will contain the alpha channel for
+ all the 4-tuples, in the same sequence. Palette entries
+ are always 8-bit.
+
+ If specified, the `transparent` and `background` parameters must
+ be a tuple with three integer values for red, green, blue, or
+ a simple integer (or singleton tuple) for a greyscale image.
+
+ If specified, the `gamma` parameter must be a positive number
+ (generally, a float). A ``gAMA`` chunk will be created. Note that
+ this will not change the values of the pixels as they appear in
+ the PNG file, they are assumed to have already been converted
+ appropriately for the gamma specified.
+
+ The `compression` argument specifies the compression level to
+ be used by the ``zlib`` module. Values from 1 to 9 specify
+ compression, with 9 being "more compressed" (usually smaller
+ and slower, but it doesn't always work out that way). 0 means
+ no compression. -1 and ``None`` both mean that the default
+ level of compession will be picked by the ``zlib`` module
+ (which is generally acceptable).
+
+ If `interlace` is true then an interlaced image is created
+ (using PNG's so far only interace method, *Adam7*). This does not
+ affect how the pixels should be presented to the encoder, rather
+ it changes how they are arranged into the PNG file. On slow
+ connexions interlaced images can be partially decoded by the
+ browser to give a rough view of the image that is successively
+ refined as more image data appears.
+
+ .. note ::
+
+ Enabling the `interlace` option requires the entire image
+ to be processed in working memory.
+
+ `chunk_limit` is used to limit the amount of memory used whilst
+ compressing the image. In order to avoid using large amounts of
+ memory, multiple ``IDAT`` chunks may be created.
+ """
+
+ # At the moment the `planes` argument is ignored;
+ # its purpose is to act as a dummy so that
+ # ``Writer(x, y, **info)`` works, where `info` is a dictionary
+ # returned by Reader.read and friends.
+ # Ditto for `colormap`.
+
+ # A couple of helper functions come first. Best skipped if you
+ # are reading through.
+
+ def isinteger(x):
+ try:
+ return int(x) == x
+ except:
+ return False
+
+ def check_color(c, which):
+ """Checks that a colour argument for transparent or
+ background options is the right form. Also "corrects" bare
+ integers to 1-tuples.
+ """
+
+ if c is None:
+ return c
+ if greyscale:
+ try:
+ l = len(c)
+ except TypeError:
+ c = (c,)
+ if len(c) != 1:
+ raise ValueError("%s for greyscale must be 1-tuple" %
+ which)
+ if not isinteger(c[0]):
+ raise ValueError(
+ "%s colour for greyscale must be integer" %
+ which)
+ else:
+ if not (len(c) == 3 and
+ isinteger(c[0]) and
+ isinteger(c[1]) and
+ isinteger(c[2])):
+ raise ValueError(
+ "%s colour must be a triple of integers" %
+ which)
+ return c
+
+ if size:
+ if len(size) != 2:
+ raise ValueError(
+ "size argument should be a pair (width, height)")
+ if width is not None and width != size[0]:
+ raise ValueError(
+ "size[0] (%r) and width (%r) should match when both are used."
+ % (size[0], width))
+ if height is not None and height != size[1]:
+ raise ValueError(
+ "size[1] (%r) and height (%r) should match when both are used."
+ % (size[1], height))
+ width,height = size
+ del size
+
+ if width <= 0 or height <= 0:
+ raise ValueError("width and height must be greater than zero")
+ if not isinteger(width) or not isinteger(height):
+ raise ValueError("width and height must be integers")
+ # http://www.w3.org/TR/PNG/#7Integers-and-byte-order
+ if width > 2**32-1 or height > 2**32-1:
+ raise ValueError("width and height cannot exceed 2**32-1")
+
+ if alpha and transparent is not None:
+ raise ValueError(
+ "transparent colour not allowed with alpha channel")
+
+ if bytes_per_sample is not None:
+ warnings.warn('please use bitdepth instead of bytes_per_sample',
+ DeprecationWarning)
+ if bytes_per_sample not in (0.125, 0.25, 0.5, 1, 2):
+ raise ValueError(
+ "bytes per sample must be .125, .25, .5, 1, or 2")
+ bitdepth = int(8*bytes_per_sample)
+ del bytes_per_sample
+ if not isinteger(bitdepth) or bitdepth < 1 or 16 < bitdepth:
+ raise ValueError("bitdepth (%r) must be a postive integer <= 16" %
+ bitdepth)
+
+ self.rescale = None
+ if palette:
+ if bitdepth not in (1,2,4,8):
+ raise ValueError("with palette, bitdepth must be 1, 2, 4, or 8")
+ if transparent is not None:
+ raise ValueError("transparent and palette not compatible")
+ if alpha:
+ raise ValueError("alpha and palette not compatible")
+ if greyscale:
+ raise ValueError("greyscale and palette not compatible")
+ else:
+ # No palette, check for sBIT chunk generation.
+ if alpha or not greyscale:
+ if bitdepth not in (8,16):
+ targetbitdepth = (8,16)[bitdepth > 8]
+ self.rescale = (bitdepth, targetbitdepth)
+ bitdepth = targetbitdepth
+ del targetbitdepth
+ else:
+ assert greyscale
+ assert not alpha
+ if bitdepth not in (1,2,4,8,16):
+ if bitdepth > 8:
+ targetbitdepth = 16
+ elif bitdepth == 3:
+ targetbitdepth = 4
+ else:
+ assert bitdepth in (5,6,7)
+ targetbitdepth = 8
+ self.rescale = (bitdepth, targetbitdepth)
+ bitdepth = targetbitdepth
+ del targetbitdepth
+
+ if bitdepth < 8 and (alpha or not greyscale and not palette):
+ raise ValueError(
+ "bitdepth < 8 only permitted with greyscale or palette")
+ if bitdepth > 8 and palette:
+ raise ValueError(
+ "bit depth must be 8 or less for images with palette")
+
+ transparent = check_color(transparent, 'transparent')
+ background = check_color(background, 'background')
+
+ # It's important that the true boolean values (greyscale, alpha,
+ # colormap, interlace) are converted to bool because Iverson's
+ # convention is relied upon later on.
+ self.width = width
+ self.height = height
+ self.transparent = transparent
+ self.background = background
+ self.gamma = gamma
+ self.greyscale = bool(greyscale)
+ self.alpha = bool(alpha)
+ self.colormap = bool(palette)
+ self.bitdepth = int(bitdepth)
+ self.compression = compression
+ self.chunk_limit = chunk_limit
+ self.interlace = bool(interlace)
+ self.palette = check_palette(palette)
+
+ self.color_type = 4*self.alpha + 2*(not greyscale) + 1*self.colormap
+ assert self.color_type in (0,2,3,4,6)
+
+ self.color_planes = (3,1)[self.greyscale or self.colormap]
+ self.planes = self.color_planes + self.alpha
+ # :todo: fix for bitdepth < 8
+ self.psize = (self.bitdepth/8) * self.planes
+
+ def make_palette(self):
+ """Create the byte sequences for a ``PLTE`` and if necessary a
+ ``tRNS`` chunk. Returned as a pair (*p*, *t*). *t* will be
+ ``None`` if no ``tRNS`` chunk is necessary.
+ """
+
+ p = array('B')
+ t = array('B')
+
+ for x in self.palette:
+ p.extend(x[0:3])
+ if len(x) > 3:
+ t.append(x[3])
+ p = tostring(p)
+ t = tostring(t)
+ if t:
+ return p,t
+ return p,None
+
+ def write(self, outfile, rows):
+ """Write a PNG image to the output file. `rows` should be
+ an iterable that yields each row in boxed row flat pixel format.
+ The rows should be the rows of the original image, so there
+ should be ``self.height`` rows of ``self.width * self.planes`` values.
+ If `interlace` is specified (when creating the instance), then
+ an interlaced PNG file will be written. Supply the rows in the
+ normal image order; the interlacing is carried out internally.
+
+ .. note ::
+
+ Interlacing will require the entire image to be in working memory.
+ """
+
+ if self.interlace:
+ fmt = 'BH'[self.bitdepth > 8]
+ a = array(fmt, itertools.chain(*rows))
+ return self.write_array(outfile, a)
+ else:
+ nrows = self.write_passes(outfile, rows)
+ if nrows != self.height:
+ raise ValueError(
+ "rows supplied (%d) does not match height (%d)" %
+ (nrows, self.height))
+
+ def write_passes(self, outfile, rows, packed=False):
+ """
+ Write a PNG image to the output file.
+
+ Most users are expected to find the :meth:`write` or
+ :meth:`write_array` method more convenient.
+
+ The rows should be given to this method in the order that
+ they appear in the output file. For straightlaced images,
+ this is the usual top to bottom ordering, but for interlaced
+ images the rows should have already been interlaced before
+ passing them to this function.
+
+ `rows` should be an iterable that yields each row. When
+ `packed` is ``False`` the rows should be in boxed row flat pixel
+ format; when `packed` is ``True`` each row should be a packed
+ sequence of bytes.
+
+ """
+
+ # http://www.w3.org/TR/PNG/#5PNG-file-signature
+ outfile.write(_signature)
+
+ # http://www.w3.org/TR/PNG/#11IHDR
+ write_chunk(outfile, 'IHDR',
+ struct.pack("!2I5B", self.width, self.height,
+ self.bitdepth, self.color_type,
+ 0, 0, self.interlace))
+
+ # See :chunk:order
+ # http://www.w3.org/TR/PNG/#11gAMA
+ if self.gamma is not None:
+ write_chunk(outfile, 'gAMA',
+ struct.pack("!L", int(round(self.gamma*1e5))))
+
+ # See :chunk:order
+ # http://www.w3.org/TR/PNG/#11sBIT
+ if self.rescale:
+ write_chunk(outfile, 'sBIT',
+ struct.pack('%dB' % self.planes,
+ *[self.rescale[0]]*self.planes))
+
+ # :chunk:order: Without a palette (PLTE chunk), ordering is
+ # relatively relaxed. With one, gAMA chunk must precede PLTE
+ # chunk which must precede tRNS and bKGD.
+ # See http://www.w3.org/TR/PNG/#5ChunkOrdering
+ if self.palette:
+ p,t = self.make_palette()
+ write_chunk(outfile, 'PLTE', p)
+ if t:
+ # tRNS chunk is optional. Only needed if palette entries
+ # have alpha.
+ write_chunk(outfile, 'tRNS', t)
+
+ # http://www.w3.org/TR/PNG/#11tRNS
+ if self.transparent is not None:
+ if self.greyscale:
+ write_chunk(outfile, 'tRNS',
+ struct.pack("!1H", *self.transparent))
+ else:
+ write_chunk(outfile, 'tRNS',
+ struct.pack("!3H", *self.transparent))
+
+ # http://www.w3.org/TR/PNG/#11bKGD
+ if self.background is not None:
+ if self.greyscale:
+ write_chunk(outfile, 'bKGD',
+ struct.pack("!1H", *self.background))
+ else:
+ write_chunk(outfile, 'bKGD',
+ struct.pack("!3H", *self.background))
+
+ # http://www.w3.org/TR/PNG/#11IDAT
+ if self.compression is not None:
+ compressor = zlib.compressobj(self.compression)
+ else:
+ compressor = zlib.compressobj()
+
+ # Choose an extend function based on the bitdepth. The extend
+ # function packs/decomposes the pixel values into bytes and
+ # stuffs them onto the data array.
+ data = array('B')
+ if self.bitdepth == 8 or packed:
+ extend = data.extend
+ elif self.bitdepth == 16:
+ # Decompose into bytes
+ def extend(sl):
+ fmt = '!%dH' % len(sl)
+ data.extend(array('B', struct.pack(fmt, *sl)))
+ else:
+ # Pack into bytes
+ assert self.bitdepth < 8
+ # samples per byte
+ spb = int(8/self.bitdepth)
+ def extend(sl):
+ a = array('B', sl)
+ # Adding padding bytes so we can group into a whole
+ # number of spb-tuples.
+ l = float(len(a))
+ extra = math.ceil(l / float(spb))*spb - l
+ a.extend([0]*int(extra))
+ # Pack into bytes
+ l = group(a, spb)
+ l = map(lambda e: reduce(lambda x,y:
+ (x << self.bitdepth) + y, e), l)
+ data.extend(l)
+ if self.rescale:
+ oldextend = extend
+ factor = \
+ float(2**self.rescale[1]-1) / float(2**self.rescale[0]-1)
+ def extend(sl):
+ oldextend(map(lambda x: int(round(factor*x)), sl))
+
+ # Build the first row, testing mostly to see if we need to
+ # changed the extend function to cope with NumPy integer types
+ # (they cause our ordinary definition of extend to fail, so we
+ # wrap it). See
+ # http://code.google.com/p/pypng/issues/detail?id=44
+ enumrows = enumerate(rows)
+ del rows
+
+ # First row's filter type.
+ data.append(0)
+ # :todo: Certain exceptions in the call to ``.next()`` or the
+ # following try would indicate no row data supplied.
+ # Should catch.
+ i,row = enumrows.next()
+ try:
+ # If this fails...
+ extend(row)
+ except:
+ # ... try a version that converts the values to int first.
+ # Not only does this work for the (slightly broken) NumPy
+ # types, there are probably lots of other, unknown, "nearly"
+ # int types it works for.
+ def wrapmapint(f):
+ return lambda sl: f(map(int, sl))
+ extend = wrapmapint(extend)
+ del wrapmapint
+ extend(row)
+
+ for i,row in enumrows:
+ # Add "None" filter type. Currently, it's essential that
+ # this filter type be used for every scanline as we do not
+ # mark the first row of a reduced pass image; that means we
+ # could accidentally compute the wrong filtered scanline if
+ # we used "up", "average", or "paeth" on such a line.
+ data.append(0)
+ extend(row)
+ if len(data) > self.chunk_limit:
+ compressed = compressor.compress(tostring(data))
+ if len(compressed):
+ # print >> sys.stderr, len(data), len(compressed)
+ write_chunk(outfile, 'IDAT', compressed)
+ # Because of our very witty definition of ``extend``,
+ # above, we must re-use the same ``data`` object. Hence
+ # we use ``del`` to empty this one, rather than create a
+ # fresh one (which would be my natural FP instinct).
+ del data[:]
+ if len(data):
+ compressed = compressor.compress(tostring(data))
+ else:
+ compressed = ''
+ flushed = compressor.flush()
+ if len(compressed) or len(flushed):
+ # print >> sys.stderr, len(data), len(compressed), len(flushed)
+ write_chunk(outfile, 'IDAT', compressed + flushed)
+ # http://www.w3.org/TR/PNG/#11IEND
+ write_chunk(outfile, 'IEND')
+ return i+1
+
+ def write_array(self, outfile, pixels):
+ """
+ Write an array in flat row flat pixel format as a PNG file on
+ the output file. See also :meth:`write` method.
+ """
+
+ if self.interlace:
+ self.write_passes(outfile, self.array_scanlines_interlace(pixels))
+ else:
+ self.write_passes(outfile, self.array_scanlines(pixels))
+
+ def write_packed(self, outfile, rows):
+ """
+ Write PNG file to `outfile`. The pixel data comes from `rows`
+ which should be in boxed row packed format. Each row should be
+ a sequence of packed bytes.
+
+ Technically, this method does work for interlaced images but it
+ is best avoided. For interlaced images, the rows should be
+ presented in the order that they appear in the file.
+
+ This method should not be used when the source image bit depth
+ is not one naturally supported by PNG; the bit depth should be
+ 1, 2, 4, 8, or 16.
+ """
+
+ if self.rescale:
+ raise Error("write_packed method not suitable for bit depth %d" %
+ self.rescale[0])
+ return self.write_passes(outfile, rows, packed=True)
+
+ def convert_pnm(self, infile, outfile):
+ """
+ Convert a PNM file containing raw pixel data into a PNG file
+ with the parameters set in the writer object. Works for
+ (binary) PGM, PPM, and PAM formats.
+ """
+
+ if self.interlace:
+ pixels = array('B')
+ pixels.fromfile(infile,
+ (self.bitdepth/8) * self.color_planes *
+ self.width * self.height)
+ self.write_passes(outfile, self.array_scanlines_interlace(pixels))
+ else:
+ self.write_passes(outfile, self.file_scanlines(infile))
+
+ def convert_ppm_and_pgm(self, ppmfile, pgmfile, outfile):
+ """
+ Convert a PPM and PGM file containing raw pixel data into a
+ PNG outfile with the parameters set in the writer object.
+ """
+ pixels = array('B')
+ pixels.fromfile(ppmfile,
+ (self.bitdepth/8) * self.color_planes *
+ self.width * self.height)
+ apixels = array('B')
+ apixels.fromfile(pgmfile,
+ (self.bitdepth/8) *
+ self.width * self.height)
+ pixels = interleave_planes(pixels, apixels,
+ (self.bitdepth/8) * self.color_planes,
+ (self.bitdepth/8))
+ if self.interlace:
+ self.write_passes(outfile, self.array_scanlines_interlace(pixels))
+ else:
+ self.write_passes(outfile, self.array_scanlines(pixels))
+
+ def file_scanlines(self, infile):
+ """
+ Generates boxed rows in flat pixel format, from the input file
+ `infile`. It assumes that the input file is in a "Netpbm-like"
+ binary format, and is positioned at the beginning of the first
+ pixel. The number of pixels to read is taken from the image
+ dimensions (`width`, `height`, `planes`) and the number of bytes
+ per value is implied by the image `bitdepth`.
+ """
+
+ # Values per row
+ vpr = self.width * self.planes
+ row_bytes = vpr
+ if self.bitdepth > 8:
+ assert self.bitdepth == 16
+ row_bytes *= 2
+ fmt = '>%dH' % vpr
+ def line():
+ return array('H', struct.unpack(fmt, infile.read(row_bytes)))
+ else:
+ def line():
+ scanline = array('B', infile.read(row_bytes))
+ return scanline
+ for y in range(self.height):
+ yield line()
+
+ def array_scanlines(self, pixels):
+ """
+ Generates boxed rows (flat pixels) from flat rows (flat pixels)
+ in an array.
+ """
+
+ # Values per row
+ vpr = self.width * self.planes
+ stop = 0
+ for y in range(self.height):
+ start = stop
+ stop = start + vpr
+ yield pixels[start:stop]
+
+ def array_scanlines_interlace(self, pixels):
+ """
+ Generator for interlaced scanlines from an array. `pixels` is
+ the full source image in flat row flat pixel format. The
+ generator yields each scanline of the reduced passes in turn, in
+ boxed row flat pixel format.
+ """
+
+ # http://www.w3.org/TR/PNG/#8InterlaceMethods
+ # Array type.
+ fmt = 'BH'[self.bitdepth > 8]
+ # Value per row
+ vpr = self.width * self.planes
+ for xstart, ystart, xstep, ystep in _adam7:
+ if xstart >= self.width:
+ continue
+ # Pixels per row (of reduced image)
+ ppr = int(math.ceil((self.width-xstart)/float(xstep)))
+ # number of values in reduced image row.
+ row_len = ppr*self.planes
+ for y in range(ystart, self.height, ystep):
+ if xstep == 1:
+ offset = y * vpr
+ yield pixels[offset:offset+vpr]
+ else:
+ row = array(fmt)
+ # There's no easier way to set the length of an array
+ row.extend(pixels[0:row_len])
+ offset = y * vpr + xstart * self.planes
+ end_offset = (y+1) * vpr
+ skip = self.planes * xstep
+ for i in range(self.planes):
+ row[i::self.planes] = \
+ pixels[offset+i:end_offset:skip]
+ yield row
+
+def write_chunk(outfile, tag, data=strtobytes('')):
+ """
+ Write a PNG chunk to the output file, including length and
+ checksum.
+ """
+
+ # http://www.w3.org/TR/PNG/#5Chunk-layout
+ outfile.write(struct.pack("!I", len(data)))
+ tag = strtobytes(tag)
+ outfile.write(tag)
+ outfile.write(data)
+ checksum = zlib.crc32(tag)
+ checksum = zlib.crc32(data, checksum)
+ checksum &= 2**32-1
+ outfile.write(struct.pack("!I", checksum))
+
+def write_chunks(out, chunks):
+ """Create a PNG file by writing out the chunks."""
+
+ out.write(_signature)
+ for chunk in chunks:
+ write_chunk(out, *chunk)
+
+def filter_scanline(type, line, fo, prev=None):
+ """Apply a scanline filter to a scanline. `type` specifies the
+ filter type (0 to 4); `line` specifies the current (unfiltered)
+ scanline as a sequence of bytes; `prev` specifies the previous
+ (unfiltered) scanline as a sequence of bytes. `fo` specifies the
+ filter offset; normally this is size of a pixel in bytes (the number
+ of bytes per sample times the number of channels), but when this is
+ < 1 (for bit depths < 8) then the filter offset is 1.
+ """
+
+ assert 0 <= type < 5
+
+ # The output array. Which, pathetically, we extend one-byte at a
+ # time (fortunately this is linear).
+ out = array('B', [type])
+
+ def sub():
+ ai = -fo
+ for x in line:
+ if ai >= 0:
+ x = (x - line[ai]) & 0xff
+ out.append(x)
+ ai += 1
+ def up():
+ for i,x in enumerate(line):
+ x = (x - prev[i]) & 0xff
+ out.append(x)
+ def average():
+ ai = -fo
+ for i,x in enumerate(line):
+ if ai >= 0:
+ x = (x - ((line[ai] + prev[i]) >> 1)) & 0xff
+ else:
+ x = (x - (prev[i] >> 1)) & 0xff
+ out.append(x)
+ ai += 1
+ def paeth():
+ # http://www.w3.org/TR/PNG/#9Filter-type-4-Paeth
+ ai = -fo # also used for ci
+ for i,x in enumerate(line):
+ a = 0
+ b = prev[i]
+ c = 0
+
+ if ai >= 0:
+ a = line[ai]
+ c = prev[ai]
+ p = a + b - c
+ pa = abs(p - a)
+ pb = abs(p - b)
+ pc = abs(p - c)
+ if pa <= pb and pa <= pc: Pr = a
+ elif pb <= pc: Pr = b
+ else: Pr = c
+
+ x = (x - Pr) & 0xff
+ out.append(x)
+ ai += 1
+
+ if not prev:
+ # We're on the first line. Some of the filters can be reduced
+ # to simpler cases which makes handling the line "off the top"
+ # of the image simpler. "up" becomes "none"; "paeth" becomes
+ # "left" (non-trivial, but true). "average" needs to be handled
+ # specially.
+ if type == 2: # "up"
+ return line # type = 0
+ elif type == 3:
+ prev = [0]*len(line)
+ elif type == 4: # "paeth"
+ type = 1
+ if type == 0:
+ out.extend(line)
+ elif type == 1:
+ sub()
+ elif type == 2:
+ up()
+ elif type == 3:
+ average()
+ else: # type == 4
+ paeth()
+ return out
+
+
+def from_array(a, mode=None, info={}):
+ """Create a PNG :class:`Image` object from a 2- or 3-dimensional array.
+ One application of this function is easy PIL-style saving:
+ ``png.from_array(pixels, 'L').save('foo.png')``.
+
+ .. note :
+
+ The use of the term *3-dimensional* is for marketing purposes
+ only. It doesn't actually work. Please bear with us. Meanwhile
+ enjoy the complimentary snacks (on request) and please use a
+ 2-dimensional array.
+
+ Unless they are specified using the *info* parameter, the PNG's
+ height and width are taken from the array size. For a 3 dimensional
+ array the first axis is the height; the second axis is the width;
+ and the third axis is the channel number. Thus an RGB image that is
+ 16 pixels high and 8 wide will use an array that is 16x8x3. For 2
+ dimensional arrays the first axis is the height, but the second axis
+ is ``width*channels``, so an RGB image that is 16 pixels high and 8
+ wide will use a 2-dimensional array that is 16x24 (each row will be
+ 8*3==24 sample values).
+
+ *mode* is a string that specifies the image colour format in a
+ PIL-style mode. It can be:
+
+ ``'L'``
+ greyscale (1 channel)
+ ``'LA'``
+ greyscale with alpha (2 channel)
+ ``'RGB'``
+ colour image (3 channel)
+ ``'RGBA'``
+ colour image with alpha (4 channel)
+
+ The mode string can also specify the bit depth (overriding how this
+ function normally derives the bit depth, see below). Appending
+ ``';16'`` to the mode will cause the PNG to be 16 bits per channel;
+ any decimal from 1 to 16 can be used to specify the bit depth.
+
+ When a 2-dimensional array is used *mode* determines how many
+ channels the image has, and so allows the width to be derived from
+ the second array dimension.
+
+ The array is expected to be a ``numpy`` array, but it can be any
+ suitable Python sequence. For example, a list of lists can be used:
+ ``png.from_array([[0, 255, 0], [255, 0, 255]], 'L')``. The exact
+ rules are: ``len(a)`` gives the first dimension, height;
+ ``len(a[0])`` gives the second dimension; ``len(a[0][0])`` gives the
+ third dimension, unless an exception is raised in which case a
+ 2-dimensional array is assumed. It's slightly more complicated than
+ that because an iterator of rows can be used, and it all still
+ works. Using an iterator allows data to be streamed efficiently.
+
+ The bit depth of the PNG is normally taken from the array element's
+ datatype (but if *mode* specifies a bitdepth then that is used
+ instead). The array element's datatype is determined in a way which
+ is supposed to work both for ``numpy`` arrays and for Python
+ ``array.array`` objects. A 1 byte datatype will give a bit depth of
+ 8, a 2 byte datatype will give a bit depth of 16. If the datatype
+ does not have an implicit size, for example it is a plain Python
+ list of lists, as above, then a default of 8 is used.
+
+ The *info* parameter is a dictionary that can be used to specify
+ metadata (in the same style as the arguments to the
+ :class:``png.Writer`` class). For this function the keys that are
+ useful are:
+
+ height
+ overrides the height derived from the array dimensions and allows
+ *a* to be an iterable.
+ width
+ overrides the width derived from the array dimensions.
+ bitdepth
+ overrides the bit depth derived from the element datatype (but
+ must match *mode* if that also specifies a bit depth).
+
+ Generally anything specified in the
+ *info* dictionary will override any implicit choices that this
+ function would otherwise make, but must match any explicit ones.
+ For example, if the *info* dictionary has a ``greyscale`` key then
+ this must be true when mode is ``'L'`` or ``'LA'`` and false when
+ mode is ``'RGB'`` or ``'RGBA'``.
+ """
+
+ # We abuse the *info* parameter by modifying it. Take a copy here.
+ # (Also typechecks *info* to some extent).
+ info = dict(info)
+
+ # Syntax check mode string.
+ bitdepth = None
+ try:
+ mode = mode.split(';')
+ if len(mode) not in (1,2):
+ raise Error()
+ if mode[0] not in ('L', 'LA', 'RGB', 'RGBA'):
+ raise Error()
+ if len(mode) == 2:
+ try:
+ bitdepth = int(mode[1])
+ except:
+ raise Error()
+ except Error:
+ raise Error("mode string should be 'RGB' or 'L;16' or similar.")
+ mode = mode[0]
+
+ # Get bitdepth from *mode* if possible.
+ if bitdepth:
+ if info.get('bitdepth') and bitdepth != info['bitdepth']:
+ raise Error("mode bitdepth (%d) should match info bitdepth (%d)." %
+ (bitdepth, info['bitdepth']))
+ info['bitdepth'] = bitdepth
+
+ # Fill in and/or check entries in *info*.
+ # Dimensions.
+ if 'size' in info:
+ # Check width, height, size all match where used.
+ for dimension,axis in [('width', 0), ('height', 1)]:
+ if dimension in info:
+ if info[dimension] != info['size'][axis]:
+ raise Error(
+ "info[%r] shhould match info['size'][%r]." %
+ (dimension, axis))
+ info['width'],info['height'] = info['size']
+ if 'height' not in info:
+ try:
+ l = len(a)
+ except:
+ raise Error(
+ "len(a) does not work, supply info['height'] instead.")
+ info['height'] = l
+ # Colour format.
+ if 'greyscale' in info:
+ if bool(info['greyscale']) != ('L' in mode):
+ raise Error("info['greyscale'] should match mode.")
+ info['greyscale'] = 'L' in mode
+ if 'alpha' in info:
+ if bool(info['alpha']) != ('A' in mode):
+ raise Error("info['alpha'] should match mode.")
+ info['alpha'] = 'A' in mode
+
+ planes = len(mode)
+ if 'planes' in info:
+ if info['planes'] != planes:
+ raise Error("info['planes'] should match mode.")
+
+ # In order to work out whether we the array is 2D or 3D we need its
+ # first row, which requires that we take a copy of its iterator.
+ # We may also need the first row to derive width and bitdepth.
+ a,t = itertools.tee(a)
+ row = t.next()
+ del t
+ try:
+ row[0][0]
+ threed = True
+ testelement = row[0]
+ except:
+ threed = False
+ testelement = row
+ if 'width' not in info:
+ if threed:
+ width = len(row)
+ else:
+ width = len(row) // planes
+ info['width'] = width
+
+ # Not implemented yet
+ assert not threed
+
+ if 'bitdepth' not in info:
+ try:
+ dtype = testelement.dtype
+ # goto the "else:" clause. Sorry.
+ except:
+ try:
+ # Try a Python array.array.
+ bitdepth = 8 * testelement.itemsize
+ except:
+ # We can't determine it from the array element's
+ # datatype, use a default of 8.
+ bitdepth = 8
+ else:
+ # If we got here without exception, we now assume that
+ # the array is a numpy array.
+ if dtype.kind == 'b':
+ bitdepth = 1
+ else:
+ bitdepth = 8 * dtype.itemsize
+ info['bitdepth'] = bitdepth
+
+ for thing in 'width height bitdepth greyscale alpha'.split():
+ assert thing in info
+ return Image(a, info)
+
+# So that refugee's from PIL feel more at home. Not documented.
+fromarray = from_array
+
+class Image:
+ """A PNG image.
+ You can create an :class:`Image` object from an array of pixels by calling
+ :meth:`png.from_array`. It can be saved to disk with the
+ :meth:`save` method."""
+ def __init__(self, rows, info):
+ """
+ .. note ::
+
+ The constructor is not public. Please do not call it.
+ """
+
+ self.rows = rows
+ self.info = info
+
+ def save(self, file):
+ """Save the image to *file*. If *file* looks like an open file
+ descriptor then it is used, otherwise it is treated as a
+ filename and a fresh file is opened.
+
+ In general, you can only call this method once; after it has
+ been called the first time and the PNG image has been saved, the
+ source data will have been streamed, and cannot be streamed
+ again.
+ """
+
+ w = Writer(**self.info)
+
+ try:
+ file.write
+ def close(): pass
+ except:
+ file = open(file, 'wb')
+ def close(): file.close()
+
+ try:
+ w.write(file, self.rows)
+ finally:
+ close()
+
+class _readable:
+ """
+ A simple file-like interface for strings and arrays.
+ """
+
+ def __init__(self, buf):
+ self.buf = buf
+ self.offset = 0
+
+ def read(self, n):
+ r = self.buf[self.offset:self.offset+n]
+ if isarray(r):
+ r = r.tostring()
+ self.offset += n
+ return r
+
+
+class Reader:
+ """
+ PNG decoder in pure Python.
+ """
+
+ def __init__(self, _guess=None, **kw):
+ """
+ Create a PNG decoder object.
+
+ The constructor expects exactly one keyword argument. If you
+ supply a positional argument instead, it will guess the input
+ type. You can choose among the following keyword arguments:
+
+ filename
+ Name of input file (a PNG file).
+ file
+ A file-like object (object with a read() method).
+ bytes
+ ``array`` or ``string`` with PNG data.
+
+ """
+ if ((_guess is not None and len(kw) != 0) or
+ (_guess is None and len(kw) != 1)):
+ raise TypeError("Reader() takes exactly 1 argument")
+
+ # Will be the first 8 bytes, later on. See validate_signature.
+ self.signature = None
+ self.transparent = None
+ # A pair of (len,type) if a chunk has been read but its data and
+ # checksum have not (in other words the file position is just
+ # past the 4 bytes that specify the chunk type). See preamble
+ # method for how this is used.
+ self.atchunk = None
+
+ if _guess is not None:
+ if isarray(_guess):
+ kw["bytes"] = _guess
+ elif isinstance(_guess, str):
+ kw["filename"] = _guess
+ elif isinstance(_guess, file):
+ kw["file"] = _guess
+
+ if "filename" in kw:
+ self.file = open(kw["filename"], "rb")
+ elif "file" in kw:
+ self.file = kw["file"]
+ elif "bytes" in kw:
+ self.file = _readable(kw["bytes"])
+ else:
+ raise TypeError("expecting filename, file or bytes array")
+
+
+ def chunk(self, seek=None, lenient=False):
+ """
+ Read the next PNG chunk from the input file; returns a
+ (*type*,*data*) tuple. *type* is the chunk's type as a string
+ (all PNG chunk types are 4 characters long). *data* is the
+ chunk's data content, as a string.
+
+ If the optional `seek` argument is
+ specified then it will keep reading chunks until it either runs
+ out of file or finds the type specified by the argument. Note
+ that in general the order of chunks in PNGs is unspecified, so
+ using `seek` can cause you to miss chunks.
+
+ If the optional `lenient` argument evaluates to True,
+ checksum failures will raise warnings rather than exceptions.
+ """
+
+ self.validate_signature()
+
+ while True:
+ # http://www.w3.org/TR/PNG/#5Chunk-layout
+ if not self.atchunk:
+ self.atchunk = self.chunklentype()
+ length,type = self.atchunk
+ self.atchunk = None
+ data = self.file.read(length)
+ if len(data) != length:
+ raise ChunkError('Chunk %s too short for required %i octets.'
+ % (type, length))
+ checksum = self.file.read(4)
+ if len(checksum) != 4:
+ raise ValueError('Chunk %s too short for checksum.', tag)
+ if seek and type != seek:
+ continue
+ verify = zlib.crc32(strtobytes(type))
+ verify = zlib.crc32(data, verify)
+ # Whether the output from zlib.crc32 is signed or not varies
+ # according to hideous implementation details, see
+ # http://bugs.python.org/issue1202 .
+ # We coerce it to be positive here (in a way which works on
+ # Python 2.3 and older).
+ verify &= 2**32 - 1
+ verify = struct.pack('!I', verify)
+ if checksum != verify:
+ # print repr(checksum)
+ (a, ) = struct.unpack('!I', checksum)
+ (b, ) = struct.unpack('!I', verify)
+ message = "Checksum error in %s chunk: 0x%08X != 0x%08X." % (type, a, b)
+ if lenient:
+ warnings.warn(message, RuntimeWarning)
+ else:
+ raise ChunkError(message)
+ return type, data
+
+ def chunks(self):
+ """Return an iterator that will yield each chunk as a
+ (*chunktype*, *content*) pair.
+ """
+
+ while True:
+ t,v = self.chunk()
+ yield t,v
+ if t == 'IEND':
+ break
+
+ def undo_filter(self, filter_type, scanline, previous):
+ """Undo the filter for a scanline. `scanline` is a sequence of
+ bytes that does not include the initial filter type byte.
+ `previous` is decoded previous scanline (for straightlaced
+ images this is the previous pixel row, but for interlaced
+ images, it is the previous scanline in the reduced image, which
+ in general is not the previous pixel row in the final image).
+ When there is no previous scanline (the first row of a
+ straightlaced image, or the first row in one of the passes in an
+ interlaced image), then this argument should be ``None``.
+
+ The scanline will have the effects of filtering removed, and the
+ result will be returned as a fresh sequence of bytes.
+ """
+
+ # :todo: Would it be better to update scanline in place?
+ # Yes, with the Cython extension making the undo_filter fast,
+ # updating scanline inplace makes the code 3 times faster
+ # (reading 50 images of 800x800 went from 40s to 16s)
+ result = scanline
+
+ if filter_type == 0:
+ return result
+
+ if filter_type not in (1,2,3,4):
+ raise FormatError('Invalid PNG Filter Type.'
+ ' See http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters .')
+
+ # Filter unit. The stride from one pixel to the corresponding
+ # byte from the previous previous. Normally this is the pixel
+ # size in bytes, but when this is smaller than 1, the previous
+ # byte is used instead.
+ fu = max(1, self.psize)
+
+ # For the first line of a pass, synthesize a dummy previous
+ # line. An alternative approach would be to observe that on the
+ # first line 'up' is the same as 'null', 'paeth' is the same
+ # as 'sub', with only 'average' requiring any special case.
+ if not previous:
+ previous = array('B', [0]*len(scanline))
+
+ def sub():
+ """Undo sub filter."""
+
+ ai = 0
+ # Loops starts at index fu. Observe that the initial part
+ # of the result is already filled in correctly with
+ # scanline.
+ for i in range(fu, len(result)):
+ x = scanline[i]
+ a = result[ai]
+ result[i] = (x + a) & 0xff
+ ai += 1
+
+ def up():
+ """Undo up filter."""
+
+ for i in range(len(result)):
+ x = scanline[i]
+ b = previous[i]
+ result[i] = (x + b) & 0xff
+
+ def average():
+ """Undo average filter."""
+
+ ai = -fu
+ for i in range(len(result)):
+ x = scanline[i]
+ if ai < 0:
+ a = 0
+ else:
+ a = result[ai]
+ b = previous[i]
+ result[i] = (x + ((a + b) >> 1)) & 0xff
+ ai += 1
+
+ def paeth():
+ """Undo Paeth filter."""
+
+ # Also used for ci.
+ ai = -fu
+ for i in range(len(result)):
+ x = scanline[i]
+ if ai < 0:
+ a = c = 0
+ else:
+ a = result[ai]
+ c = previous[ai]
+ b = previous[i]
+ p = a + b - c
+ pa = abs(p - a)
+ pb = abs(p - b)
+ pc = abs(p - c)
+ if pa <= pb and pa <= pc:
+ pr = a
+ elif pb <= pc:
+ pr = b
+ else:
+ pr = c
+ result[i] = (x + pr) & 0xff
+ ai += 1
+
+ # Call appropriate filter algorithm. Note that 0 has already
+ # been dealt with.
+ (None,
+ pngfilters.undo_filter_sub,
+ pngfilters.undo_filter_up,
+ pngfilters.undo_filter_average,
+ pngfilters.undo_filter_paeth)[filter_type](fu, scanline, previous, result)
+ return result
+
+ def deinterlace(self, raw):
+ """
+ Read raw pixel data, undo filters, deinterlace, and flatten.
+ Return in flat row flat pixel format.
+ """
+
+ # print >> sys.stderr, ("Reading interlaced, w=%s, r=%s, planes=%s," +
+ # " bpp=%s") % (self.width, self.height, self.planes, self.bps)
+ # Values per row (of the target image)
+ vpr = self.width * self.planes
+
+ # Make a result array, and make it big enough. Interleaving
+ # writes to the output array randomly (well, not quite), so the
+ # entire output array must be in memory.
+ fmt = 'BH'[self.bitdepth > 8]
+ a = array(fmt, [0]*vpr*self.height)
+ source_offset = 0
+
+ for xstart, ystart, xstep, ystep in _adam7:
+ # print >> sys.stderr, "Adam7: start=%s,%s step=%s,%s" % (
+ # xstart, ystart, xstep, ystep)
+ if xstart >= self.width:
+ continue
+ # The previous (reconstructed) scanline. None at the
+ # beginning of a pass to indicate that there is no previous
+ # line.
+ recon = None
+ # Pixels per row (reduced pass image)
+ ppr = int(math.ceil((self.width-xstart)/float(xstep)))
+ # Row size in bytes for this pass.
+ row_size = int(math.ceil(self.psize * ppr))
+ for y in range(ystart, self.height, ystep):
+ filter_type = raw[source_offset]
+ source_offset += 1
+ scanline = raw[source_offset:source_offset+row_size]
+ source_offset += row_size
+ recon = self.undo_filter(filter_type, scanline, recon)
+ # Convert so that there is one element per pixel value
+ flat = self.serialtoflat(recon, ppr)
+ if xstep == 1:
+ assert xstart == 0
+ offset = y * vpr
+ a[offset:offset+vpr] = flat
+ else:
+ offset = y * vpr + xstart * self.planes
+ end_offset = (y+1) * vpr
+ skip = self.planes * xstep
+ for i in range(self.planes):
+ a[offset+i:end_offset:skip] = \
+ flat[i::self.planes]
+ return a
+
+ def iterboxed(self, rows):
+ """Iterator that yields each scanline in boxed row flat pixel
+ format. `rows` should be an iterator that yields the bytes of
+ each row in turn.
+ """
+
+ def asvalues(raw):
+ """Convert a row of raw bytes into a flat row. Result may
+ or may not share with argument"""
+
+ if self.bitdepth == 8:
+ return raw
+ if self.bitdepth == 16:
+ raw = tostring(raw)
+ return array('H', struct.unpack('!%dH' % (len(raw)//2), raw))
+ assert self.bitdepth < 8
+ width = self.width
+ # Samples per byte
+ spb = 8//self.bitdepth
+ out = array('B')
+ mask = 2**self.bitdepth - 1
+ shifts = map(self.bitdepth.__mul__, reversed(range(spb)))
+ for o in raw:
+ out.extend(map(lambda i: mask&(o>>i), shifts))
+ return out[:width]
+
+ return itertools.imap(asvalues, rows)
+
+ def serialtoflat(self, bytes, width=None):
+ """Convert serial format (byte stream) pixel data to flat row
+ flat pixel.
+ """
+
+ if self.bitdepth == 8:
+ return bytes
+ if self.bitdepth == 16:
+ bytes = tostring(bytes)
+ return array('H',
+ struct.unpack('!%dH' % (len(bytes)//2), bytes))
+ assert self.bitdepth < 8
+ if width is None:
+ width = self.width
+ # Samples per byte
+ spb = 8//self.bitdepth
+ out = array('B')
+ mask = 2**self.bitdepth - 1
+ shifts = map(self.bitdepth.__mul__, reversed(range(spb)))
+ l = width
+ for o in bytes:
+ out.extend([(mask&(o>>s)) for s in shifts][:l])
+ l -= spb
+ if l <= 0:
+ l = width
+ return out
+
+ def iterstraight(self, raw):
+ """Iterator that undoes the effect of filtering, and yields each
+ row in serialised format (as a sequence of bytes). Assumes input
+ is straightlaced. `raw` should be an iterable that yields the
+ raw bytes in chunks of arbitrary size."""
+
+ # length of row, in bytes
+ rb = self.row_bytes
+ a = array('B')
+ # The previous (reconstructed) scanline. None indicates first
+ # line of image.
+ recon = None
+ for some in raw:
+ a.extend(some)
+ while len(a) >= rb + 1:
+ filter_type = a[0]
+ scanline = a[1:rb+1]
+ del a[:rb+1]
+ recon = self.undo_filter(filter_type, scanline, recon)
+ yield recon
+ if len(a) != 0:
+ # :file:format We get here with a file format error: when the
+ # available bytes (after decompressing) do not pack into exact
+ # rows.
+ raise FormatError(
+ 'Wrong size for decompressed IDAT chunk.')
+ assert len(a) == 0
+
+ def validate_signature(self):
+ """If signature (header) has not been read then read and
+ validate it; otherwise do nothing.
+ """
+
+ if self.signature:
+ return
+ self.signature = self.file.read(8)
+ if self.signature != _signature:
+ raise FormatError("PNG file has invalid signature.")
+
+ def preamble(self, lenient=False):
+ """
+ Extract the image metadata by reading the initial part of the PNG
+ file up to the start of the ``IDAT`` chunk. All the chunks that
+ precede the ``IDAT`` chunk are read and either processed for
+ metadata or discarded.
+
+ If the optional `lenient` argument evaluates to True,
+ checksum failures will raise warnings rather than exceptions.
+ """
+
+ self.validate_signature()
+
+ while True:
+ if not self.atchunk:
+ self.atchunk = self.chunklentype()
+ if self.atchunk is None:
+ raise FormatError(
+ 'This PNG file has no IDAT chunks.')
+ if self.atchunk[1] == 'IDAT':
+ return
+ self.process_chunk(lenient=lenient)
+
+ def chunklentype(self):
+ """Reads just enough of the input to determine the next
+ chunk's length and type, returned as a (*length*, *type*) pair
+ where *type* is a string. If there are no more chunks, ``None``
+ is returned.
+ """
+
+ x = self.file.read(8)
+ if not x:
+ return None
+ if len(x) != 8:
+ raise FormatError(
+ 'End of file whilst reading chunk length and type.')
+ length,type = struct.unpack('!I4s', x)
+ type = bytestostr(type)
+ if length > 2**31-1:
+ raise FormatError('Chunk %s is too large: %d.' % (type,length))
+ return length,type
+
+ def process_chunk(self, lenient=False):
+ """Process the next chunk and its data. This only processes the
+ following chunk types, all others are ignored: ``IHDR``,
+ ``PLTE``, ``bKGD``, ``tRNS``, ``gAMA``, ``sBIT``.
+
+ If the optional `lenient` argument evaluates to True,
+ checksum failures will raise warnings rather than exceptions.
+ """
+
+ type, data = self.chunk(lenient=lenient)
+ if type == 'IHDR':
+ # http://www.w3.org/TR/PNG/#11IHDR
+ if len(data) != 13:
+ raise FormatError('IHDR chunk has incorrect length.')
+ (self.width, self.height, self.bitdepth, self.color_type,
+ self.compression, self.filter,
+ self.interlace) = struct.unpack("!2I5B", data)
+
+ # Check that the header specifies only valid combinations.
+ if self.bitdepth not in (1,2,4,8,16):
+ raise Error("invalid bit depth %d" % self.bitdepth)
+ if self.color_type not in (0,2,3,4,6):
+ raise Error("invalid colour type %d" % self.color_type)
+ # Check indexed (palettized) images have 8 or fewer bits
+ # per pixel; check only indexed or greyscale images have
+ # fewer than 8 bits per pixel.
+ if ((self.color_type & 1 and self.bitdepth > 8) or
+ (self.bitdepth < 8 and self.color_type not in (0,3))):
+ raise FormatError("Illegal combination of bit depth (%d)"
+ " and colour type (%d)."
+ " See http://www.w3.org/TR/2003/REC-PNG-20031110/#table111 ."
+ % (self.bitdepth, self.color_type))
+ if self.compression != 0:
+ raise Error("unknown compression method %d" % self.compression)
+ if self.filter != 0:
+ raise FormatError("Unknown filter method %d,"
+ " see http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters ."
+ % self.filter)
+ if self.interlace not in (0,1):
+ raise FormatError("Unknown interlace method %d,"
+ " see http://www.w3.org/TR/2003/REC-PNG-20031110/#8InterlaceMethods ."
+ % self.interlace)
+
+ # Derived values
+ # http://www.w3.org/TR/PNG/#6Colour-values
+ colormap = bool(self.color_type & 1)
+ greyscale = not (self.color_type & 2)
+ alpha = bool(self.color_type & 4)
+ color_planes = (3,1)[greyscale or colormap]
+ planes = color_planes + alpha
+
+ self.colormap = colormap
+ self.greyscale = greyscale
+ self.alpha = alpha
+ self.color_planes = color_planes
+ self.planes = planes
+ self.psize = float(self.bitdepth)/float(8) * planes
+ if int(self.psize) == self.psize:
+ self.psize = int(self.psize)
+ self.row_bytes = int(math.ceil(self.width * self.psize))
+ # Stores PLTE chunk if present, and is used to check
+ # chunk ordering constraints.
+ self.plte = None
+ # Stores tRNS chunk if present, and is used to check chunk
+ # ordering constraints.
+ self.trns = None
+ # Stores sbit chunk if present.
+ self.sbit = None
+ elif type == 'PLTE':
+ # http://www.w3.org/TR/PNG/#11PLTE
+ if self.plte:
+ warnings.warn("Multiple PLTE chunks present.")
+ self.plte = data
+ if len(data) % 3 != 0:
+ raise FormatError(
+ "PLTE chunk's length should be a multiple of 3.")
+ if len(data) > (2**self.bitdepth)*3:
+ raise FormatError("PLTE chunk is too long.")
+ if len(data) == 0:
+ raise FormatError("Empty PLTE is not allowed.")
+ elif type == 'bKGD':
+ try:
+ if self.colormap:
+ if not self.plte:
+ warnings.warn(
+ "PLTE chunk is required before bKGD chunk.")
+ self.background = struct.unpack('B', data)
+ else:
+ self.background = struct.unpack("!%dH" % self.color_planes,
+ data)
+ except struct.error:
+ raise FormatError("bKGD chunk has incorrect length.")
+ elif type == 'tRNS':
+ # http://www.w3.org/TR/PNG/#11tRNS
+ self.trns = data
+ if self.colormap:
+ if not self.plte:
+ warnings.warn("PLTE chunk is required before tRNS chunk.")
+ else:
+ if len(data) > len(self.plte)/3:
+ # Was warning, but promoted to Error as it
+ # would otherwise cause pain later on.
+ raise FormatError("tRNS chunk is too long.")
+ else:
+ if self.alpha:
+ raise FormatError(
+ "tRNS chunk is not valid with colour type %d." %
+ self.color_type)
+ try:
+ self.transparent = \
+ struct.unpack("!%dH" % self.color_planes, data)
+ except struct.error:
+ raise FormatError("tRNS chunk has incorrect length.")
+ elif type == 'gAMA':
+ try:
+ self.gamma = struct.unpack("!L", data)[0] / 100000.0
+ except struct.error:
+ raise FormatError("gAMA chunk has incorrect length.")
+ elif type == 'sBIT':
+ self.sbit = data
+ if (self.colormap and len(data) != 3 or
+ not self.colormap and len(data) != self.planes):
+ raise FormatError("sBIT chunk has incorrect length.")
+
+ def read(self, lenient=False):
+ """
+ Read the PNG file and decode it. Returns (`width`, `height`,
+ `pixels`, `metadata`).
+
+ May use excessive memory.
+
+ `pixels` are returned in boxed row flat pixel format.
+
+ If the optional `lenient` argument evaluates to True,
+ checksum failures will raise warnings rather than exceptions.
+ """
+
+ def iteridat():
+ """Iterator that yields all the ``IDAT`` chunks as strings."""
+ while True:
+ try:
+ type, data = self.chunk(lenient=lenient)
+ except ValueError, e:
+ raise ChunkError(e.args[0])
+ if type == 'IEND':
+ # http://www.w3.org/TR/PNG/#11IEND
+ break
+ if type != 'IDAT':
+ continue
+ # type == 'IDAT'
+ # http://www.w3.org/TR/PNG/#11IDAT
+ if self.colormap and not self.plte:
+ warnings.warn("PLTE chunk is required before IDAT chunk")
+ yield data
+
+ def iterdecomp(idat):
+ """Iterator that yields decompressed strings. `idat` should
+ be an iterator that yields the ``IDAT`` chunk data.
+ """
+
+ # Currently, with no max_length paramter to decompress, this
+ # routine will do one yield per IDAT chunk. So not very
+ # incremental.
+ d = zlib.decompressobj()
+ # Each IDAT chunk is passed to the decompressor, then any
+ # remaining state is decompressed out.
+ for data in idat:
+ # :todo: add a max_length argument here to limit output
+ # size.
+ yield array('B', d.decompress(data))
+ yield array('B', d.flush())
+
+ self.preamble(lenient=lenient)
+ raw = iterdecomp(iteridat())
+
+ if self.interlace:
+ raw = array('B', itertools.chain(*raw))
+ arraycode = 'BH'[self.bitdepth>8]
+ # Like :meth:`group` but producing an array.array object for
+ # each row.
+ pixels = itertools.imap(lambda *row: array(arraycode, row),
+ *[iter(self.deinterlace(raw))]*self.width*self.planes)
+ else:
+ pixels = self.iterboxed(self.iterstraight(raw))
+ meta = dict()
+ for attr in 'greyscale alpha planes bitdepth interlace'.split():
+ meta[attr] = getattr(self, attr)
+ meta['size'] = (self.width, self.height)
+ for attr in 'gamma transparent background'.split():
+ a = getattr(self, attr, None)
+ if a is not None:
+ meta[attr] = a
+ if self.plte:
+ meta['palette'] = self.palette()
+ return self.width, self.height, pixels, meta
+
+
+ def read_flat(self):
+ """
+ Read a PNG file and decode it into flat row flat pixel format.
+ Returns (*width*, *height*, *pixels*, *metadata*).
+
+ May use excessive memory.
+
+ `pixels` are returned in flat row flat pixel format.
+
+ See also the :meth:`read` method which returns pixels in the
+ more stream-friendly boxed row flat pixel format.
+ """
+
+ x, y, pixel, meta = self.read()
+ arraycode = 'BH'[meta['bitdepth']>8]
+ pixel = array(arraycode, itertools.chain(*pixel))
+ return x, y, pixel, meta
+
+ def palette(self, alpha='natural'):
+ """Returns a palette that is a sequence of 3-tuples or 4-tuples,
+ synthesizing it from the ``PLTE`` and ``tRNS`` chunks. These
+ chunks should have already been processed (for example, by
+ calling the :meth:`preamble` method). All the tuples are the
+ same size: 3-tuples if there is no ``tRNS`` chunk, 4-tuples when
+ there is a ``tRNS`` chunk. Assumes that the image is colour type
+ 3 and therefore a ``PLTE`` chunk is required.
+
+ If the `alpha` argument is ``'force'`` then an alpha channel is
+ always added, forcing the result to be a sequence of 4-tuples.
+ """
+
+ if not self.plte:
+ raise FormatError(
+ "Required PLTE chunk is missing in colour type 3 image.")
+ plte = group(array('B', self.plte), 3)
+ if self.trns or alpha == 'force':
+ trns = array('B', self.trns or '')
+ trns.extend([255]*(len(plte)-len(trns)))
+ plte = map(operator.add, plte, group(trns, 1))
+ return plte
+
+ def asDirect(self):
+ """Returns the image data as a direct representation of an
+ ``x * y * planes`` array. This method is intended to remove the
+ need for callers to deal with palettes and transparency
+ themselves. Images with a palette (colour type 3)
+ are converted to RGB or RGBA; images with transparency (a
+ ``tRNS`` chunk) are converted to LA or RGBA as appropriate.
+ When returned in this format the pixel values represent the
+ colour value directly without needing to refer to palettes or
+ transparency information.
+
+ Like the :meth:`read` method this method returns a 4-tuple:
+
+ (*width*, *height*, *pixels*, *meta*)
+
+ This method normally returns pixel values with the bit depth
+ they have in the source image, but when the source PNG has an
+ ``sBIT`` chunk it is inspected and can reduce the bit depth of
+ the result pixels; pixel values will be reduced according to
+ the bit depth specified in the ``sBIT`` chunk (PNG nerds should
+ note a single result bit depth is used for all channels; the
+ maximum of the ones specified in the ``sBIT`` chunk. An RGB565
+ image will be rescaled to 6-bit RGB666).
+
+ The *meta* dictionary that is returned reflects the `direct`
+ format and not the original source image. For example, an RGB
+ source image with a ``tRNS`` chunk to represent a transparent
+ colour, will have ``planes=3`` and ``alpha=False`` for the
+ source image, but the *meta* dictionary returned by this method
+ will have ``planes=4`` and ``alpha=True`` because an alpha
+ channel is synthesized and added.
+
+ *pixels* is the pixel data in boxed row flat pixel format (just
+ like the :meth:`read` method).
+
+ All the other aspects of the image data are not changed.
+ """
+
+ self.preamble()
+
+ # Simple case, no conversion necessary.
+ if not self.colormap and not self.trns and not self.sbit:
+ return self.read()
+
+ x,y,pixels,meta = self.read()
+
+ if self.colormap:
+ meta['colormap'] = False
+ meta['alpha'] = bool(self.trns)
+ meta['bitdepth'] = 8
+ meta['planes'] = 3 + bool(self.trns)
+ plte = self.palette()
+ def iterpal(pixels):
+ for row in pixels:
+ row = map(plte.__getitem__, row)
+ yield array('B', itertools.chain(*row))
+ pixels = iterpal(pixels)
+ elif self.trns:
+ # It would be nice if there was some reasonable way of doing
+ # this without generating a whole load of intermediate tuples.
+ # But tuples does seem like the easiest way, with no other way
+ # clearly much simpler or much faster. (Actually, the L to LA
+ # conversion could perhaps go faster (all those 1-tuples!), but
+ # I still wonder whether the code proliferation is worth it)
+ it = self.transparent
+ maxval = 2**meta['bitdepth']-1
+ planes = meta['planes']
+ meta['alpha'] = True
+ meta['planes'] += 1
+ typecode = 'BH'[meta['bitdepth']>8]
+ def itertrns(pixels):
+ for row in pixels:
+ # For each row we group it into pixels, then form a
+ # characterisation vector that says whether each pixel
+ # is opaque or not. Then we convert True/False to
+ # 0/maxval (by multiplication), and add it as the extra
+ # channel.
+ row = group(row, planes)
+ opa = map(it.__ne__, row)
+ opa = map(maxval.__mul__, opa)
+ opa = zip(opa) # convert to 1-tuples
+ yield array(typecode,
+ itertools.chain(*map(operator.add, row, opa)))
+ pixels = itertrns(pixels)
+ targetbitdepth = None
+ if self.sbit:
+ sbit = struct.unpack('%dB' % len(self.sbit), self.sbit)
+ targetbitdepth = max(sbit)
+ if targetbitdepth > meta['bitdepth']:
+ raise Error('sBIT chunk %r exceeds bitdepth %d' %
+ (sbit,self.bitdepth))
+ if min(sbit) <= 0:
+ raise Error('sBIT chunk %r has a 0-entry' % sbit)
+ if targetbitdepth == meta['bitdepth']:
+ targetbitdepth = None
+ if targetbitdepth:
+ shift = meta['bitdepth'] - targetbitdepth
+ meta['bitdepth'] = targetbitdepth
+ def itershift(pixels):
+ for row in pixels:
+ yield map(shift.__rrshift__, row)
+ pixels = itershift(pixels)
+ return x,y,pixels,meta
+
+ def asFloat(self, maxval=1.0):
+ """Return image pixels as per :meth:`asDirect` method, but scale
+ all pixel values to be floating point values between 0.0 and
+ *maxval*.
+ """
+
+ x,y,pixels,info = self.asDirect()
+ sourcemaxval = 2**info['bitdepth']-1
+ del info['bitdepth']
+ info['maxval'] = float(maxval)
+ factor = float(maxval)/float(sourcemaxval)
+ def iterfloat():
+ for row in pixels:
+ yield map(factor.__mul__, row)
+ return x,y,iterfloat(),info
+
+ def _as_rescale(self, get, targetbitdepth):
+ """Helper used by :meth:`asRGB8` and :meth:`asRGBA8`."""
+
+ width,height,pixels,meta = get()
+ maxval = 2**meta['bitdepth'] - 1
+ targetmaxval = 2**targetbitdepth - 1
+ factor = float(targetmaxval) / float(maxval)
+ meta['bitdepth'] = targetbitdepth
+ def iterscale():
+ for row in pixels:
+ yield map(lambda x: int(round(x*factor)), row)
+ if maxval == targetmaxval:
+ return width, height, pixels, meta
+ else:
+ return width, height, iterscale(), meta
+
+ def asRGB8(self):
+ """Return the image data as an RGB pixels with 8-bits per
+ sample. This is like the :meth:`asRGB` method except that
+ this method additionally rescales the values so that they
+ are all between 0 and 255 (8-bit). In the case where the
+ source image has a bit depth < 8 the transformation preserves
+ all the information; where the source image has bit depth
+ > 8, then rescaling to 8-bit values loses precision. No
+ dithering is performed. Like :meth:`asRGB`, an alpha channel
+ in the source image will raise an exception.
+
+ This function returns a 4-tuple:
+ (*width*, *height*, *pixels*, *metadata*).
+ *width*, *height*, *metadata* are as per the :meth:`read` method.
+
+ *pixels* is the pixel data in boxed row flat pixel format.
+ """
+
+ return self._as_rescale(self.asRGB, 8)
+
+ def asRGBA8(self):
+ """Return the image data as RGBA pixels with 8-bits per
+ sample. This method is similar to :meth:`asRGB8` and
+ :meth:`asRGBA`: The result pixels have an alpha channel, *and*
+ values are rescaled to the range 0 to 255. The alpha channel is
+ synthesized if necessary (with a small speed penalty).
+ """
+
+ return self._as_rescale(self.asRGBA, 8)
+
+ def asRGB(self):
+ """Return image as RGB pixels. RGB colour images are passed
+ through unchanged; greyscales are expanded into RGB
+ triplets (there is a small speed overhead for doing this).
+
+ An alpha channel in the source image will raise an
+ exception.
+
+ The return values are as for the :meth:`read` method
+ except that the *metadata* reflect the returned pixels, not the
+ source image. In particular, for this method
+ ``metadata['greyscale']`` will be ``False``.
+ """
+
+ width,height,pixels,meta = self.asDirect()
+ if meta['alpha']:
+ raise Error("will not convert image with alpha channel to RGB")
+ if not meta['greyscale']:
+ return width,height,pixels,meta
+ meta['greyscale'] = False
+ typecode = 'BH'[meta['bitdepth'] > 8]
+ def iterrgb():
+ for row in pixels:
+ a = array(typecode, [0]) * 3 * width
+ for i in range(3):
+ a[i::3] = row
+ yield a
+ return width,height,iterrgb(),meta
+
+ def asRGBA(self):
+ """Return image as RGBA pixels. Greyscales are expanded into
+ RGB triplets; an alpha channel is synthesized if necessary.
+ The return values are as for the :meth:`read` method
+ except that the *metadata* reflect the returned pixels, not the
+ source image. In particular, for this method
+ ``metadata['greyscale']`` will be ``False``, and
+ ``metadata['alpha']`` will be ``True``.
+ """
+
+ width,height,pixels,meta = self.asDirect()
+ if meta['alpha'] and not meta['greyscale']:
+ return width,height,pixels,meta
+ typecode = 'BH'[meta['bitdepth'] > 8]
+ maxval = 2**meta['bitdepth'] - 1
+ maxbuffer = struct.pack('=' + typecode, maxval) * 4 * width
+ def newarray():
+ return array(typecode, maxbuffer)
+
+ if meta['alpha'] and meta['greyscale']:
+ # LA to RGBA
+ def convert():
+ for row in pixels:
+ # Create a fresh target row, then copy L channel
+ # into first three target channels, and A channel
+ # into fourth channel.
+ a = newarray()
+ pngfilters.convert_la_to_rgba(row, a)
+ yield a
+ elif meta['greyscale']:
+ # L to RGBA
+ def convert():
+ for row in pixels:
+ a = newarray()
+ pngfilters.convert_l_to_rgba(row, a)
+ yield a
+ else:
+ assert not meta['alpha'] and not meta['greyscale']
+ # RGB to RGBA
+ def convert():
+ for row in pixels:
+ a = newarray()
+ pngfilters.convert_rgb_to_rgba(row, a)
+ yield a
+ meta['alpha'] = True
+ meta['greyscale'] = False
+ return width,height,convert(),meta
+
+
+# === Legacy Version Support ===
+
+# :pyver:old: PyPNG works on Python versions 2.3 and 2.2, but not
+# without some awkward problems. Really PyPNG works on Python 2.4 (and
+# above); it works on Pythons 2.3 and 2.2 by virtue of fixing up
+# problems here. It's a bit ugly (which is why it's hidden down here).
+#
+# Generally the strategy is one of pretending that we're running on
+# Python 2.4 (or above), and patching up the library support on earlier
+# versions so that it looks enough like Python 2.4. When it comes to
+# Python 2.2 there is one thing we cannot patch: extended slices
+# http://www.python.org/doc/2.3/whatsnew/section-slices.html.
+# Instead we simply declare that features that are implemented using
+# extended slices will not work on Python 2.2.
+#
+# In order to work on Python 2.3 we fix up a recurring annoyance involving
+# the array type. In Python 2.3 an array cannot be initialised with an
+# array, and it cannot be extended with a list (or other sequence).
+# Both of those are repeated issues in the code. Whilst I would not
+# normally tolerate this sort of behaviour, here we "shim" a replacement
+# for array into place (and hope no-ones notices). You never read this.
+#
+# In an amusing case of warty hacks on top of warty hacks... the array
+# shimming we try and do only works on Python 2.3 and above (you can't
+# subclass array.array in Python 2.2). So to get it working on Python
+# 2.2 we go for something much simpler and (probably) way slower.
+try:
+ array('B').extend([])
+ array('B', array('B'))
+except:
+ # Expect to get here on Python 2.3
+ try:
+ class _array_shim(array):
+ true_array = array
+ def __new__(cls, typecode, init=None):
+ super_new = super(_array_shim, cls).__new__
+ it = super_new(cls, typecode)
+ if init is None:
+ return it
+ it.extend(init)
+ return it
+ def extend(self, extension):
+ super_extend = super(_array_shim, self).extend
+ if isinstance(extension, self.true_array):
+ return super_extend(extension)
+ if not isinstance(extension, (list, str)):
+ # Convert to list. Allows iterators to work.
+ extension = list(extension)
+ return super_extend(self.true_array(self.typecode, extension))
+ array = _array_shim
+ except:
+ # Expect to get here on Python 2.2
+ def array(typecode, init=()):
+ if type(init) == str:
+ return map(ord, init)
+ return list(init)
+
+# Further hacks to get it limping along on Python 2.2
+try:
+ enumerate
+except:
+ def enumerate(seq):
+ i=0
+ for x in seq:
+ yield i,x
+ i += 1
+
+try:
+ reversed
+except:
+ def reversed(l):
+ l = list(l)
+ l.reverse()
+ for x in l:
+ yield x
+
+try:
+ itertools
+except:
+ class _dummy_itertools:
+ pass
+ itertools = _dummy_itertools()
+ def _itertools_imap(f, seq):
+ for x in seq:
+ yield f(x)
+ itertools.imap = _itertools_imap
+ def _itertools_chain(*iterables):
+ for it in iterables:
+ for element in it:
+ yield element
+ itertools.chain = _itertools_chain
+
+
+# === Support for users without Cython ===
+
+try:
+ pngfilters
+except:
+ class pngfilters(object):
+ def undo_filter_sub(filter_unit, scanline, previous, result):
+ """Undo sub filter."""
+
+ ai = 0
+ # Loops starts at index fu. Observe that the initial part
+ # of the result is already filled in correctly with
+ # scanline.
+ for i in range(filter_unit, len(result)):
+ x = scanline[i]
+ a = result[ai]
+ result[i] = (x + a) & 0xff
+ ai += 1
+ undo_filter_sub = staticmethod(undo_filter_sub)
+
+ def undo_filter_up(filter_unit, scanline, previous, result):
+ """Undo up filter."""
+
+ for i in range(len(result)):
+ x = scanline[i]
+ b = previous[i]
+ result[i] = (x + b) & 0xff
+ undo_filter_up = staticmethod(undo_filter_up)
+
+ def undo_filter_average(filter_unit, scanline, previous, result):
+ """Undo up filter."""
+
+ ai = -filter_unit
+ for i in range(len(result)):
+ x = scanline[i]
+ if ai < 0:
+ a = 0
+ else:
+ a = result[ai]
+ b = previous[i]
+ result[i] = (x + ((a + b) >> 1)) & 0xff
+ ai += 1
+ undo_filter_average = staticmethod(undo_filter_average)
+
+ def undo_filter_paeth(filter_unit, scanline, previous, result):
+ """Undo Paeth filter."""
+
+ # Also used for ci.
+ ai = -filter_unit
+ for i in range(len(result)):
+ x = scanline[i]
+ if ai < 0:
+ a = c = 0
+ else:
+ a = result[ai]
+ c = previous[ai]
+ b = previous[i]
+ p = a + b - c
+ pa = abs(p - a)
+ pb = abs(p - b)
+ pc = abs(p - c)
+ if pa <= pb and pa <= pc:
+ pr = a
+ elif pb <= pc:
+ pr = b
+ else:
+ pr = c
+ result[i] = (x + pr) & 0xff
+ ai += 1
+ undo_filter_paeth = staticmethod(undo_filter_paeth)
+
+ def convert_la_to_rgba(row, result):
+ for i in range(3):
+ result[i::4] = row[0::2]
+ result[3::4] = row[1::2]
+ convert_la_to_rgba = staticmethod(convert_la_to_rgba)
+
+ def convert_l_to_rgba(row, result):
+ """Convert a grayscale image to RGBA. This method assumes the alpha
+ channel in result is already correctly initialized."""
+ for i in range(3):
+ result[i::4] = row
+ convert_l_to_rgba = staticmethod(convert_l_to_rgba)
+
+ def convert_rgb_to_rgba(row, result):
+ """Convert an RGB image to RGBA. This method assumes the alpha
+ channel in result is already correctly initialized."""
+ for i in range(3):
+ result[i::4] = row[i::3]
+ convert_rgb_to_rgba = staticmethod(convert_rgb_to_rgba)
+
+
+# === Internal Test Support ===
+
+# This section comprises the tests that are internally validated (as
+# opposed to tests which produce output files that are externally
+# validated). Primarily they are unittests.
+
+# Note that it is difficult to internally validate the results of
+# writing a PNG file. The only thing we can do is read it back in
+# again, which merely checks consistency, not that the PNG file we
+# produce is valid.
+
+# Run the tests from the command line:
+# python -c 'import png;png.test()'
+
+# (For an in-memory binary file IO object) We use BytesIO where
+# available, otherwise we use StringIO, but name it BytesIO.
+try:
+ from io import BytesIO
+except:
+ from StringIO import StringIO as BytesIO
+import tempfile
+# http://www.python.org/doc/2.4.4/lib/module-unittest.html
+import unittest
+
+
+def test():
+ unittest.main(__name__)
+
+def topngbytes(name, rows, x, y, **k):
+ """Convenience function for creating a PNG file "in memory" as a
+ string. Creates a :class:`Writer` instance using the keyword arguments,
+ then passes `rows` to its :meth:`Writer.write` method. The resulting
+ PNG file is returned as a string. `name` is used to identify the file for
+ debugging.
+ """
+
+ import os
+
+ print name
+ f = BytesIO()
+ w = Writer(x, y, **k)
+ w.write(f, rows)
+ if os.environ.get('PYPNG_TEST_TMP'):
+ w = open(name, 'wb')
+ w.write(f.getvalue())
+ w.close()
+ return f.getvalue()
+
+def testWithIO(inp, out, f):
+ """Calls the function `f` with ``sys.stdin`` changed to `inp`
+ and ``sys.stdout`` changed to `out`. They are restored when `f`
+ returns. This function returns whatever `f` returns.
+ """
+
+ import os
+
+ try:
+ oldin,sys.stdin = sys.stdin,inp
+ oldout,sys.stdout = sys.stdout,out
+ x = f()
+ finally:
+ sys.stdin = oldin
+ sys.stdout = oldout
+ if os.environ.get('PYPNG_TEST_TMP') and hasattr(out,'getvalue'):
+ name = mycallersname()
+ if name:
+ w = open(name+'.png', 'wb')
+ w.write(out.getvalue())
+ w.close()
+ return x
+
+def mycallersname():
+ """Returns the name of the caller of the caller of this function
+ (hence the name of the caller of the function in which
+ "mycallersname()" textually appears). Returns None if this cannot
+ be determined."""
+
+ # http://docs.python.org/library/inspect.html#the-interpreter-stack
+ import inspect
+
+ frame = inspect.currentframe()
+ if not frame:
+ return None
+ frame_,filename_,lineno_,funname,linelist_,listi_ = (
+ inspect.getouterframes(frame)[2])
+ return funname
+
+def seqtobytes(s):
+ """Convert a sequence of integers to a *bytes* instance. Good for
+ plastering over Python 2 / Python 3 cracks.
+ """
+
+ return strtobytes(''.join(chr(x) for x in s))
+
+class Test(unittest.TestCase):
+ # This member is used by the superclass. If we don't define a new
+ # class here then when we use self.assertRaises() and the PyPNG code
+ # raises an assertion then we get no proper traceback. I can't work
+ # out why, but defining a new class here means we get a proper
+ # traceback.
+ class failureException(Exception):
+ pass
+
+ def helperLN(self, n):
+ mask = (1 << n) - 1
+ # Use small chunk_limit so that multiple chunk writing is
+ # tested. Making it a test for Issue 20.
+ w = Writer(15, 17, greyscale=True, bitdepth=n, chunk_limit=99)
+ f = BytesIO()
+ w.write_array(f, array('B', map(mask.__and__, range(1, 256))))
+ r = Reader(bytes=f.getvalue())
+ x,y,pixels,meta = r.read()
+ self.assertEqual(x, 15)
+ self.assertEqual(y, 17)
+ self.assertEqual(list(itertools.chain(*pixels)),
+ map(mask.__and__, range(1,256)))
+ def testL8(self):
+ return self.helperLN(8)
+ def testL4(self):
+ return self.helperLN(4)
+ def testL2(self):
+ "Also tests asRGB8."
+ w = Writer(1, 4, greyscale=True, bitdepth=2)
+ f = BytesIO()
+ w.write_array(f, array('B', range(4)))
+ r = Reader(bytes=f.getvalue())
+ x,y,pixels,meta = r.asRGB8()
+ self.assertEqual(x, 1)
+ self.assertEqual(y, 4)
+ for i,row in enumerate(pixels):
+ self.assertEqual(len(row), 3)
+ self.assertEqual(list(row), [0x55*i]*3)
+ def testP2(self):
+ "2-bit palette."
+ a = (255,255,255)
+ b = (200,120,120)
+ c = (50,99,50)
+ w = Writer(1, 4, bitdepth=2, palette=[a,b,c])
+ f = BytesIO()
+ w.write_array(f, array('B', (0,1,1,2)))
+ r = Reader(bytes=f.getvalue())
+ x,y,pixels,meta = r.asRGB8()
+ self.assertEqual(x, 1)
+ self.assertEqual(y, 4)
+ self.assertEqual(map(list, pixels), map(list, [a, b, b, c]))
+ def testPtrns(self):
+ "Test colour type 3 and tRNS chunk (and 4-bit palette)."
+ a = (50,99,50,50)
+ b = (200,120,120,80)
+ c = (255,255,255)
+ d = (200,120,120)
+ e = (50,99,50)
+ w = Writer(3, 3, bitdepth=4, palette=[a,b,c,d,e])
+ f = BytesIO()
+ w.write_array(f, array('B', (4, 3, 2, 3, 2, 0, 2, 0, 1)))
+ r = Reader(bytes=f.getvalue())
+ x,y,pixels,meta = r.asRGBA8()
+ self.assertEqual(x, 3)
+ self.assertEqual(y, 3)
+ c = c+(255,)
+ d = d+(255,)
+ e = e+(255,)
+ boxed = [(e,d,c),(d,c,a),(c,a,b)]
+ flat = map(lambda row: itertools.chain(*row), boxed)
+ self.assertEqual(map(list, pixels), map(list, flat))
+ def testRGBtoRGBA(self):
+ "asRGBA8() on colour type 2 source."""
+ # Test for Issue 26
+ r = Reader(bytes=_pngsuite['basn2c08'])
+ x,y,pixels,meta = r.asRGBA8()
+ # Test the pixels at row 9 columns 0 and 1.
+ row9 = list(pixels)[9]
+ self.assertEqual(list(row9[0:8]),
+ [0xff, 0xdf, 0xff, 0xff, 0xff, 0xde, 0xff, 0xff])
+ def testLtoRGBA(self):
+ "asRGBA() on grey source."""
+ # Test for Issue 60
+ r = Reader(bytes=_pngsuite['basi0g08'])
+ x,y,pixels,meta = r.asRGBA()
+ row9 = list(list(pixels)[9])
+ self.assertEqual(row9[0:8],
+ [222, 222, 222, 255, 221, 221, 221, 255])
+ def testCtrns(self):
+ "Test colour type 2 and tRNS chunk."
+ # Test for Issue 25
+ r = Reader(bytes=_pngsuite['tbrn2c08'])
+ x,y,pixels,meta = r.asRGBA8()
+ # I just happen to know that the first pixel is transparent.
+ # In particular it should be #7f7f7f00
+ row0 = list(pixels)[0]
+ self.assertEqual(tuple(row0[0:4]), (0x7f, 0x7f, 0x7f, 0x00))
+ def testAdam7read(self):
+ """Adam7 interlace reading.
+ Specifically, test that for images in the PngSuite that
+ have both an interlaced and straightlaced pair that both
+ images from the pair produce the same array of pixels."""
+ for candidate in _pngsuite:
+ if not candidate.startswith('basn'):
+ continue
+ candi = candidate.replace('n', 'i')
+ if candi not in _pngsuite:
+ continue
+ print 'adam7 read', candidate
+ straight = Reader(bytes=_pngsuite[candidate])
+ adam7 = Reader(bytes=_pngsuite[candi])
+ # Just compare the pixels. Ignore x,y (because they're
+ # likely to be correct?); metadata is ignored because the
+ # "interlace" member differs. Lame.
+ straight = straight.read()[2]
+ adam7 = adam7.read()[2]
+ self.assertEqual(map(list, straight), map(list, adam7))
+ def testAdam7write(self):
+ """Adam7 interlace writing.
+ For each test image in the PngSuite, write an interlaced
+ and a straightlaced version. Decode both, and compare results.
+ """
+ # Not such a great test, because the only way we can check what
+ # we have written is to read it back again.
+
+ for name,bytes in _pngsuite.items():
+ # Only certain colour types supported for this test.
+ if name[3:5] not in ['n0', 'n2', 'n4', 'n6']:
+ continue
+ it = Reader(bytes=bytes)
+ x,y,pixels,meta = it.read()
+ pngi = topngbytes('adam7wn'+name+'.png', pixels,
+ x=x, y=y, bitdepth=it.bitdepth,
+ greyscale=it.greyscale, alpha=it.alpha,
+ transparent=it.transparent,
+ interlace=False)
+ x,y,ps,meta = Reader(bytes=pngi).read()
+ it = Reader(bytes=bytes)
+ x,y,pixels,meta = it.read()
+ pngs = topngbytes('adam7wi'+name+'.png', pixels,
+ x=x, y=y, bitdepth=it.bitdepth,
+ greyscale=it.greyscale, alpha=it.alpha,
+ transparent=it.transparent,
+ interlace=True)
+ x,y,pi,meta = Reader(bytes=pngs).read()
+ self.assertEqual(map(list, ps), map(list, pi))
+ def testPGMin(self):
+ """Test that the command line tool can read PGM files."""
+ def do():
+ return _main(['testPGMin'])
+ s = BytesIO()
+ s.write(strtobytes('P5 2 2 3\n'))
+ s.write(strtobytes('\x00\x01\x02\x03'))
+ s.flush()
+ s.seek(0)
+ o = BytesIO()
+ testWithIO(s, o, do)
+ r = Reader(bytes=o.getvalue())
+ x,y,pixels,meta = r.read()
+ self.assertTrue(r.greyscale)
+ self.assertEqual(r.bitdepth, 2)
+ def testPAMin(self):
+ """Test that the command line tool can read PAM file."""
+ def do():
+ return _main(['testPAMin'])
+ s = BytesIO()
+ s.write(strtobytes('P7\nWIDTH 3\nHEIGHT 1\nDEPTH 4\nMAXVAL 255\n'
+ 'TUPLTYPE RGB_ALPHA\nENDHDR\n'))
+ # The pixels in flat row flat pixel format
+ flat = [255,0,0,255, 0,255,0,120, 0,0,255,30]
+ asbytes = seqtobytes(flat)
+ s.write(asbytes)
+ s.flush()
+ s.seek(0)
+ o = BytesIO()
+ testWithIO(s, o, do)
+ r = Reader(bytes=o.getvalue())
+ x,y,pixels,meta = r.read()
+ self.assertTrue(r.alpha)
+ self.assertTrue(not r.greyscale)
+ self.assertEqual(list(itertools.chain(*pixels)), flat)
+ def testLA4(self):
+ """Create an LA image with bitdepth 4."""
+ bytes = topngbytes('la4.png', [[5, 12]], 1, 1,
+ greyscale=True, alpha=True, bitdepth=4)
+ sbit = Reader(bytes=bytes).chunk('sBIT')[1]
+ self.assertEqual(sbit, strtobytes('\x04\x04'))
+ def testPal(self):
+ """Test that a palette PNG returns the palette in info."""
+ r = Reader(bytes=_pngsuite['basn3p04'])
+ x,y,pixels,info = r.read()
+ self.assertEqual(x, 32)
+ self.assertEqual(y, 32)
+ self.assertTrue('palette' in info)
+ def testPalWrite(self):
+ """Test metadata for paletted PNG can be passed from one PNG
+ to another."""
+ r = Reader(bytes=_pngsuite['basn3p04'])
+ x,y,pixels,info = r.read()
+ w = Writer(**info)
+ o = BytesIO()
+ w.write(o, pixels)
+ o.flush()
+ o.seek(0)
+ r = Reader(file=o)
+ _,_,_,again_info = r.read()
+ # Same palette
+ self.assertEqual(again_info['palette'], info['palette'])
+ def testPalExpand(self):
+ """Test that bitdepth can be used to fiddle with pallete image."""
+ r = Reader(bytes=_pngsuite['basn3p04'])
+ x,y,pixels,info = r.read()
+ pixels = [list(row) for row in pixels]
+ info['bitdepth'] = 8
+ w = Writer(**info)
+ o = BytesIO()
+ w.write(o, pixels)
+ o.flush()
+ o.seek(0)
+ r = Reader(file=o)
+ _,_,again_pixels,again_info = r.read()
+ # Same pixels
+ again_pixels = [list(row) for row in again_pixels]
+ self.assertEqual(again_pixels, pixels)
+
+ def testPNMsbit(self):
+ """Test that PNM files can generates sBIT chunk."""
+ def do():
+ return _main(['testPNMsbit'])
+ s = BytesIO()
+ s.write(strtobytes('P6 8 1 1\n'))
+ for pixel in range(8):
+ s.write(struct.pack('<I', (0x4081*pixel)&0x10101)[:3])
+ s.flush()
+ s.seek(0)
+ o = BytesIO()
+ testWithIO(s, o, do)
+ r = Reader(bytes=o.getvalue())
+ sbit = r.chunk('sBIT')[1]
+ self.assertEqual(sbit, strtobytes('\x01\x01\x01'))
+ def testLtrns0(self):
+ """Create greyscale image with tRNS chunk."""
+ return self.helperLtrns(0)
+ def testLtrns1(self):
+ """Using 1-tuple for transparent arg."""
+ return self.helperLtrns((0,))
+ def helperLtrns(self, transparent):
+ """Helper used by :meth:`testLtrns*`."""
+ pixels = zip([0x00, 0x38, 0x4c, 0x54, 0x5c, 0x40, 0x38, 0x00])
+ o = BytesIO()
+ w = Writer(8, 8, greyscale=True, bitdepth=1, transparent=transparent)
+ w.write_packed(o, pixels)
+ r = Reader(bytes=o.getvalue())
+ x,y,pixels,meta = r.asDirect()
+ self.assertTrue(meta['alpha'])
+ self.assertTrue(meta['greyscale'])
+ self.assertEqual(meta['bitdepth'], 1)
+ def testWinfo(self):
+ """Test the dictionary returned by a `read` method can be used
+ as args for :meth:`Writer`.
+ """
+ r = Reader(bytes=_pngsuite['basn2c16'])
+ info = r.read()[3]
+ w = Writer(**info)
+ def testPackedIter(self):
+ """Test iterator for row when using write_packed.
+
+ Indicative for Issue 47.
+ """
+ w = Writer(16, 2, greyscale=True, alpha=False, bitdepth=1)
+ o = BytesIO()
+ w.write_packed(o, [itertools.chain([0x0a], [0xaa]),
+ itertools.chain([0x0f], [0xff])])
+ r = Reader(bytes=o.getvalue())
+ x,y,pixels,info = r.asDirect()
+ pixels = list(pixels)
+ self.assertEqual(len(pixels), 2)
+ self.assertEqual(len(pixels[0]), 16)
+ def testInterlacedArray(self):
+ """Test that reading an interlaced PNG yields each row as an
+ array."""
+ r = Reader(bytes=_pngsuite['basi0g08'])
+ list(r.read()[2])[0].tostring
+ def testTrnsArray(self):
+ """Test that reading a type 2 PNG with tRNS chunk yields each
+ row as an array (using asDirect)."""
+ r = Reader(bytes=_pngsuite['tbrn2c08'])
+ list(r.asDirect()[2])[0].tostring
+
+ # Invalid file format tests. These construct various badly
+ # formatted PNG files, then feed them into a Reader. When
+ # everything is working properly, we should get FormatError
+ # exceptions raised.
+ def testEmpty(self):
+ """Test empty file."""
+
+ r = Reader(bytes='')
+ self.assertRaises(FormatError, r.asDirect)
+ def testSigOnly(self):
+ """Test file containing just signature bytes."""
+
+ r = Reader(bytes=_signature)
+ self.assertRaises(FormatError, r.asDirect)
+ def testExtraPixels(self):
+ """Test file that contains too many pixels."""
+
+ def eachchunk(chunk):
+ if chunk[0] != 'IDAT':
+ return chunk
+ data = zlib.decompress(chunk[1])
+ data += strtobytes('\x00garbage')
+ data = zlib.compress(data)
+ chunk = (chunk[0], data)
+ return chunk
+ self.assertRaises(FormatError, self.helperFormat, eachchunk)
+ def testNotEnoughPixels(self):
+ def eachchunk(chunk):
+ if chunk[0] != 'IDAT':
+ return chunk
+ # Remove last byte.
+ data = zlib.decompress(chunk[1])
+ data = data[:-1]
+ data = zlib.compress(data)
+ return (chunk[0], data)
+ self.assertRaises(FormatError, self.helperFormat, eachchunk)
+ def helperFormat(self, f):
+ r = Reader(bytes=_pngsuite['basn0g01'])
+ o = BytesIO()
+ def newchunks():
+ for chunk in r.chunks():
+ yield f(chunk)
+ write_chunks(o, newchunks())
+ r = Reader(bytes=o.getvalue())
+ return list(r.asDirect()[2])
+ def testBadFilter(self):
+ def eachchunk(chunk):
+ if chunk[0] != 'IDAT':
+ return chunk
+ data = zlib.decompress(chunk[1])
+ # Corrupt the first filter byte
+ data = strtobytes('\x99') + data[1:]
+ data = zlib.compress(data)
+ return (chunk[0], data)
+ self.assertRaises(FormatError, self.helperFormat, eachchunk)
+
+ def testFlat(self):
+ """Test read_flat."""
+ import hashlib
+
+ r = Reader(bytes=_pngsuite['basn0g02'])
+ x,y,pixel,meta = r.read_flat()
+ d = hashlib.md5(seqtobytes(pixel)).digest()
+ self.assertEqual(_enhex(d), '255cd971ab8cd9e7275ff906e5041aa0')
+ def testfromarray(self):
+ img = from_array([[0, 0x33, 0x66], [0xff, 0xcc, 0x99]], 'L')
+ img.save('testfromarray.png')
+ def testfromarrayL16(self):
+ img = from_array(group(range(2**16), 256), 'L;16')
+ img.save('testL16.png')
+ def testfromarrayRGB(self):
+ img = from_array([[0,0,0, 0,0,1, 0,1,0, 0,1,1],
+ [1,0,0, 1,0,1, 1,1,0, 1,1,1]], 'RGB;1')
+ o = BytesIO()
+ img.save(o)
+ def testfromarrayIter(self):
+ import itertools
+
+ i = itertools.islice(itertools.count(10), 20)
+ i = itertools.imap(lambda x: [x, x, x], i)
+ img = from_array(i, 'RGB;5', dict(height=20))
+ f = open('testiter.png', 'wb')
+ img.save(f)
+ f.close()
+
+ # numpy dependent tests. These are skipped (with a message to
+ # sys.stderr) if numpy cannot be imported.
+ def testNumpyuint16(self):
+ """numpy uint16."""
+
+ try:
+ import numpy
+ except ImportError:
+ print >>sys.stderr, "skipping numpy test"
+ return
+
+ rows = [map(numpy.uint16, range(0,0x10000,0x5555))]
+ b = topngbytes('numpyuint16.png', rows, 4, 1,
+ greyscale=True, alpha=False, bitdepth=16)
+ def testNumpyuint8(self):
+ """numpy uint8."""
+
+ try:
+ import numpy
+ except ImportError:
+ print >>sys.stderr, "skipping numpy test"
+ return
+
+ rows = [map(numpy.uint8, range(0,0x100,0x55))]
+ b = topngbytes('numpyuint8.png', rows, 4, 1,
+ greyscale=True, alpha=False, bitdepth=8)
+ def testNumpybool(self):
+ """numpy bool."""
+
+ try:
+ import numpy
+ except ImportError:
+ print >>sys.stderr, "skipping numpy test"
+ return
+
+ rows = [map(numpy.bool, [0,1])]
+ b = topngbytes('numpybool.png', rows, 2, 1,
+ greyscale=True, alpha=False, bitdepth=1)
+ def testNumpyarray(self):
+ """numpy array."""
+ try:
+ import numpy
+ except ImportError:
+ print >>sys.stderr, "skipping numpy test"
+ return
+
+ pixels = numpy.array([[0,0x5555],[0x5555,0xaaaa]], numpy.uint16)
+ img = from_array(pixels, 'L')
+ img.save('testnumpyL16.png')
+
+ def paeth(self, x, a, b, c):
+ p = a + b - c
+ pa = abs(p - a)
+ pb = abs(p - b)
+ pc = abs(p - c)
+ if pa <= pb and pa <= pc:
+ pr = a
+ elif pb <= pc:
+ pr = b
+ else:
+ pr = c
+ return x - pr
+
+ # test filters and unfilters
+ def testFilterScanlineFirstLine(self):
+ fo = 3 # bytes per pixel
+ line = [30, 31, 32, 230, 231, 232]
+ out = filter_scanline(0, line, fo, None) # none
+ self.assertEqual(list(out), [0, 30, 31, 32, 230, 231, 232])
+ out = filter_scanline(1, line, fo, None) # sub
+ self.assertEqual(list(out), [1, 30, 31, 32, 200, 200, 200])
+ out = filter_scanline(2, line, fo, None) # up
+ # TODO: All filtered scanlines start with a byte indicating the filter
+ # algorithm, except "up". Is this a bug? Should the expected output
+ # start with 2 here?
+ self.assertEqual(list(out), [30, 31, 32, 230, 231, 232])
+ out = filter_scanline(3, line, fo, None) # average
+ self.assertEqual(list(out), [3, 30, 31, 32, 215, 216, 216])
+ out = filter_scanline(4, line, fo, None) # paeth
+ self.assertEqual(list(out), [
+ 4, self.paeth(30, 0, 0, 0), self.paeth(31, 0, 0, 0),
+ self.paeth(32, 0, 0, 0), self.paeth(230, 30, 0, 0),
+ self.paeth(231, 31, 0, 0), self.paeth(232, 32, 0, 0)
+ ])
+ def testFilterScanline(self):
+ prev = [20, 21, 22, 210, 211, 212]
+ line = [30, 32, 34, 230, 233, 236]
+ fo = 3
+ out = filter_scanline(0, line, fo, prev) # none
+ self.assertEqual(list(out), [0, 30, 32, 34, 230, 233, 236])
+ out = filter_scanline(1, line, fo, prev) # sub
+ self.assertEqual(list(out), [1, 30, 32, 34, 200, 201, 202])
+ out = filter_scanline(2, line, fo, prev) # up
+ self.assertEqual(list(out), [2, 10, 11, 12, 20, 22, 24])
+ out = filter_scanline(3, line, fo, prev) # average
+ self.assertEqual(list(out), [3, 20, 22, 23, 110, 112, 113])
+ out = filter_scanline(4, line, fo, prev) # paeth
+ self.assertEqual(list(out), [
+ 4, self.paeth(30, 0, 20, 0), self.paeth(32, 0, 21, 0),
+ self.paeth(34, 0, 22, 0), self.paeth(230, 30, 210, 20),
+ self.paeth(233, 32, 211, 21), self.paeth(236, 34, 212, 22)
+ ])
+ def testUnfilterScanline(self):
+ reader = Reader(bytes='')
+ reader.psize = 3
+ scanprev = array('B', [20, 21, 22, 210, 211, 212])
+ scanline = array('B', [30, 32, 34, 230, 233, 236])
+ def cp(a):
+ return array('B', a)
+
+ out = reader.undo_filter(0, cp(scanline), cp(scanprev))
+ self.assertEqual(list(out), list(scanline)) # none
+ out = reader.undo_filter(1, cp(scanline), cp(scanprev))
+ self.assertEqual(list(out), [30, 32, 34, 4, 9, 14]) # sub
+ out = reader.undo_filter(2, cp(scanline), cp(scanprev))
+ self.assertEqual(list(out), [50, 53, 56, 184, 188, 192]) # up
+ out = reader.undo_filter(3, cp(scanline), cp(scanprev))
+ self.assertEqual(list(out), [40, 42, 45, 99, 103, 108]) # average
+ out = reader.undo_filter(4, cp(scanline), cp(scanprev))
+ self.assertEqual(list(out), [50, 53, 56, 184, 188, 192]) # paeth
+ def testUnfilterScanlinePaeth(self):
+ # This tests more edge cases in the paeth unfilter
+ reader = Reader(bytes='')
+ reader.psize = 3
+ scanprev = array('B', [2, 0, 0, 0, 9, 11])
+ scanline = array('B', [6, 10, 9, 100, 101, 102])
+
+ out = reader.undo_filter(4, scanline, scanprev)
+ self.assertEqual(list(out), [8, 10, 9, 108, 111, 113]) # paeth
+ def testIterstraight(self):
+ def arraify(list_of_str):
+ return [array('B', s) for s in list_of_str]
+ reader = Reader(bytes='')
+ reader.row_bytes = 6
+ reader.psize = 3
+ rows = reader.iterstraight(arraify(['\x00abcdef', '\x00ghijkl']))
+ self.assertEqual(list(rows), arraify(['abcdef', 'ghijkl']))
+
+ rows = reader.iterstraight(arraify(['\x00abc', 'def\x00ghijkl']))
+ self.assertEqual(list(rows), arraify(['abcdef', 'ghijkl']))
+
+ rows = reader.iterstraight(arraify(['\x00abcdef\x00ghijkl']))
+ self.assertEqual(list(rows), arraify(['abcdef', 'ghijkl']))
+
+ rows = reader.iterstraight(arraify(['\x00abcdef\x00ghi', 'jkl']))
+ self.assertEqual(list(rows), arraify(['abcdef', 'ghijkl']))
+
+# === Command Line Support ===
+
+def _dehex(s):
+ """Liberally convert from hex string to binary string."""
+ import re
+ import binascii
+
+ # Remove all non-hexadecimal digits
+ s = re.sub(r'[^a-fA-F\d]', '', s)
+ # binscii.unhexlify works in Python 2 and Python 3 (unlike
+ # thing.decode('hex')).
+ return binascii.unhexlify(strtobytes(s))
+def _enhex(s):
+ """Convert from binary string (bytes) to hex string (str)."""
+
+ import binascii
+
+ return bytestostr(binascii.hexlify(s))
+
+# Copies of PngSuite test files taken
+# from http://www.schaik.com/pngsuite/pngsuite_bas_png.html
+# on 2009-02-19 by drj and converted to hex.
+# Some of these are not actually in PngSuite (but maybe they should
+# be?), they use the same naming scheme, but start with a capital
+# letter.
+_pngsuite = {
+ 'basi0g01': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002001000000012c0677
+cf0000000467414d41000186a031e8965f0000009049444154789c2d8d310ec2
+300c45dfc682c415187a00a42e197ab81e83b127e00c5639001363a580d8582c
+65c910357c4b78b0bfbfdf4f70168c19e7acb970a3f2d1ded9695ce5bf5963df
+d92aaf4c9fd927ea449e6487df5b9c36e799b91bdf082b4d4bd4014fe4014b01
+ab7a17aee694d28d328a2d63837a70451e1648702d9a9ff4a11d2f7a51aa21e5
+a18c7ffd0094e3511d661822f20000000049454e44ae426082
+"""),
+ 'basi0g02': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002002000000016ba60d
+1f0000000467414d41000186a031e8965f0000005149444154789c635062e860
+00e17286bb609c93c370ec189494960631366e4467b3ae675dcf10f521ea0303
+90c1ca006444e11643482064114a4852c710baea3f18c31918020c30410403a6
+0ac1a09239009c52804d85b6d97d0000000049454e44ae426082
+"""),
+ 'basi0g04': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200400000001e4e6f8
+bf0000000467414d41000186a031e8965f000000ae49444154789c658e5111c2
+301044171c141c141c041c843a287510ea20d441c041c141c141c04191102454
+03994998cecd7edcecedbb9bdbc3b2c2b6457545fbc4bac1be437347f7c66a77
+3c23d60db15e88f5c5627338a5416c2e691a9b475a89cd27eda12895ae8dfdab
+43d61e590764f5c83a226b40d669bec307f93247701687723abf31ff83a2284b
+a5b4ae6b63ac6520ad730ca4ed7b06d20e030369bd6720ed383290360406d24e
+13811f2781eba9d34d07160000000049454e44ae426082
+"""),
+ 'basi0g08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200800000001211615
+be0000000467414d41000186a031e8965f000000b549444154789cb5905d0ac2
+3010849dbac81c42c47bf843cf253e8878b0aa17110f214bdca6be240f5d21a5
+94ced3e49bcd322c1624115515154998aa424822a82a5624a1aa8a8b24c58f99
+999908130989a04a00d76c2c09e76cf21adcb209393a6553577da17140a2c59e
+70ecbfa388dff1f03b82fb82bd07f05f7cb13f80bb07ad2fd60c011c3c588eef
+f1f4e03bbec7ce832dca927aea005e431b625796345307b019c845e6bfc3bb98
+769d84f9efb02ea6c00f9bb9ff45e81f9f280000000049454e44ae426082
+"""),
+ 'basi0g16': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002010000000017186c9
+fd0000000467414d41000186a031e8965f000000e249444154789cb5913b0ec2
+301044c7490aa8f85d81c3e4301c8f53a4ca0da8902c8144b3920b4043111282
+23bc4956681a6bf5fc3c5a3ba0448912d91a4de2c38dd8e380231eede4c4f7a1
+4677700bec7bd9b1d344689315a3418d1a6efbe5b8305ba01f8ff4808c063e26
+c60d5c81edcf6c58c535e252839e93801b15c0a70d810ae0d306b205dc32b187
+272b64057e4720ff0502154034831520154034c3df81400510cdf0015c86e5cc
+5c79c639fddba9dcb5456b51d7980eb52d8e7d7fa620a75120d6064641a05120
+b606771a05626b401a05f1f589827cf0fe44c1f0bae0055698ee8914fffffe00
+00000049454e44ae426082
+"""),
+ 'basi2c08': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002008020000018b1fdd
+350000000467414d41000186a031e8965f000000f249444154789cd59341aa04
+210c44abc07b78133d59d37333bd89d76868b566d10cf4675af8596431a11662
+7c5688919280e312257dd6a0a4cf1a01008ee312a5f3c69c37e6fcc3f47e6776
+a07f8bdaf5b40feed2d33e025e2ff4fe2d4a63e1a16d91180b736d8bc45854c5
+6d951863f4a7e0b66dcf09a900f3ffa2948d4091e53ca86c048a64390f662b50
+4a999660ced906182b9a01a8be00a56404a6ede182b1223b4025e32c4de34304
+63457680c93aada6c99b73865aab2fc094920d901a203f5ddfe1970d28456783
+26cffbafeffcd30654f46d119be4793f827387fc0d189d5bc4d69a3c23d45a7f
+db803146578337df4d0a3121fc3d330000000049454e44ae426082
+"""),
+ 'basi2c16': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000201002000001db8f01
+760000000467414d41000186a031e8965f0000020a49444154789cd5962173e3
+3010853fcf1838cc61a1818185a53e56787fa13fa130852e3b5878b4b0b03081
+b97f7030070b53e6b057a0a8912bbb9163b9f109ececbc59bd7dcf2b45492409
+d66f00eb1dd83cb5497d65456aeb8e1040913b3b2c04504c936dd5a9c7e2c6eb
+b1b8f17a58e8d043da56f06f0f9f62e5217b6ba3a1b76f6c9e99e8696a2a72e2
+c4fb1e4d452e92ec9652b807486d12b6669be00db38d9114b0c1961e375461a5
+5f76682a85c367ad6f682ff53a9c2a353191764b78bb07d8ddc3c97c1950f391
+6745c7b9852c73c2f212605a466a502705c8338069c8b9e84efab941eb393a97
+d4c9fd63148314209f1c1d3434e847ead6380de291d6f26a25c1ebb5047f5f24
+d85c49f0f22cc1d34282c72709cab90477bf25b89d49f0f351822297e0ea9704
+f34c82bc94002448ede51866e5656aef5d7c6a385cb4d80e6a538ceba04e6df2
+480e9aa84ddedb413bb5c97b3838456df2d4fec2c7a706983e7474d085fae820
+a841776a83073838973ac0413fea2f1dc4a06e71108fda73109bdae48954ad60
+bf867aac3ce44c7c1589a711cf8a81df9b219679d96d1cec3d8bbbeaa2012626
+df8c7802eda201b2d2e0239b409868171fc104ba8b76f10b4da09f6817ffc609
+c413ede267fd1fbab46880c90f80eccf0013185eb48b47ba03df2bdaadef3181
+cb8976f18e13188768170f98c0f844bb78cb04c62ddac59d09fc3fa25dfc1da4
+14deb3df1344f70000000049454e44ae426082
+"""),
+ 'basi3p08': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020080300000133a3ba
+500000000467414d41000186a031e8965f00000300504c5445224400f5ffed77
+ff77cbffff110a003a77002222ffff11ff110000222200ffac5566ff66ff6666
+ff01ff221200dcffffccff994444ff005555220000cbcbff44440055ff55cbcb
+00331a00ffecdcedffffe4ffcbffdcdc44ff446666ff330000442200ededff66
+6600ffa444ffffaaeded0000cbcbfefffffdfffeffff0133ff33552a000101ff
+8888ff00aaaa010100440000888800ffe4cbba5b0022ff22663200ffff99aaaa
+ff550000aaaa00cb630011ff11d4ffaa773a00ff4444dc6b0066000001ff0188
+4200ecffdc6bdc00ffdcba00333300ed00ed7300ffff88994a0011ffff770000
+ff8301ffbabafe7b00fffeff00cb00ff999922ffff880000ffff77008888ffdc
+ff1a33000000aa33ffff009900990000000001326600ffbaff44ffffffaaff00
+770000fefeaa00004a9900ffff66ff22220000998bff1155ffffff0101ff88ff
+005500001111fffffefffdfea4ff4466ffffff66ff003300ffff55ff77770000
+88ff44ff00110077ffff006666ffffed000100fff5ed1111ffffff44ff22ffff
+eded11110088ffff00007793ff2200dcdc3333fffe00febabaff99ffff333300
+63cb00baba00acff55ffffdcffff337bfe00ed00ed5555ffaaffffdcdcff5555
+00000066dcdc00dc00dc83ff017777fffefeffffffcbff5555777700fefe00cb
+00cb0000fe010200010000122200ffff220044449bff33ffd4aa0000559999ff
+999900ba00ba2a5500ffcbcbb4ff66ff9b33ffffbaaa00aa42880053aa00ffaa
+aa0000ed00babaffff1100fe00000044009999990099ffcc99ba000088008800
+dc00ff93220000dcfefffeaa5300770077020100cb0000000033ffedff00ba00
+ff3333edffedffc488bcff7700aa00660066002222dc0000ffcbffdcffdcff8b
+110000cb00010155005500880000002201ffffcbffcbed0000ff88884400445b
+ba00ffbc77ff99ff006600baffba00777773ed00fe00003300330000baff77ff
+004400aaffaafffefe000011220022c4ff8800eded99ff99ff55ff002200ffb4
+661100110a1100ff1111dcffbabaffff88ff88010001ff33ffb98ed362000002
+a249444154789c65d0695c0b001806f03711a9904a94d24dac63292949e5a810
+d244588a14ca5161d1a1323973252242d62157d12ae498c8124d25ca3a11398a
+16e55a3cdffab0ffe7f77d7fcff3528645349b584c3187824d9d19d4ec2e3523
+9eb0ae975cf8de02f2486d502191841b42967a1ad49e5ddc4265f69a899e26b5
+e9e468181baae3a71a41b95669da8df2ea3594c1b31046d7b17bfb86592e4cbe
+d89b23e8db0af6304d756e60a8f4ad378bdc2552ae5948df1d35b52143141533
+33bbbbababebeb3b3bc9c9c9c6c6c0c0d7b7b535323225a5aa8a02024a4bedec
+0a0a2a2bcdcd7d7cf2f3a9a9c9cdcdd8b8adcdd5b5ababa828298982824a4ab2
+b21212acadbdbc1414e2e24859b9a72730302f4f49292c4c57373c9c0a0b7372
+8c8c1c1c3a3a92936d6dfdfd293e3e26262a4a4eaea2424b4b5fbfbc9c323278
+3c0b0ba1303abaae8ecdeeed950d6669a9a7a7a141d4de9e9d5d5cdcd2229b94
+c572716132f97cb1d8db9bc3110864a39795d9db6b6a26267a7a9a98d4d6a6a7
+cb76090ef6f030354d4d75766e686030545464cb393a1a1ac6c68686eae8f8f9
+a9aa4644c8b66d6e1689dcdd2512a994cb35330b0991ad9f9b6b659596a6addd
+d8282fafae5e5323fb8f41d01f76c22fd8061be01bfc041a0323e1002c81cd30
+0b9ec027a0c930014ec035580fc3e112bc069a0b53e11c0c8095f00176c163a0
+e5301baec06a580677600ddc05ba0f13e120bc81a770133ec355a017300d4ec2
+0c7800bbe1219c02fa08f3e13c1c85dbb00a2ec05ea0dff00a6ec15a98027360
+070c047a06d7e1085c84f1b014f6c03fa0b33018b6c0211801ebe018fc00da0a
+6f61113c877eb01d4ec317a085700f26c130f80efbe132bc039a0733e106fc81
+f7f017f6c10aa0d1300a0ec374780943e1382c06fa0a9b60238c83473016cec0
+02f80f73fefe1072afc1e50000000049454e44ae426082
+"""),
+ 'basi6a08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200806000001047d4a
+620000000467414d41000186a031e8965f0000012049444154789cc595414ec3
+3010459fa541b8bbb26641b8069b861e8b4d12c1c112c1452a710a2a65d840d5
+949041fc481ec98ae27c7f3f8d27e3e4648047600fec0d1f390fbbe2633a31e2
+9389e4e4ea7bfdbf3d9a6b800ab89f1bd6b553cfcbb0679e960563d72e0a9293
+b7337b9f988cc67f5f0e186d20e808042f1c97054e1309da40d02d7e27f92e03
+6cbfc64df0fc3117a6210a1b6ad1a00df21c1abcf2a01944c7101b0cb568a001
+909c9cf9e399cf3d8d9d4660a875405d9a60d000b05e2de55e25780b7a5268e0
+622118e2399aab063a815808462f1ab86890fc2e03e48bb109ded7d26ce4bf59
+0db91bac0050747fec5015ce80da0e5700281be533f0ce6d5900b59bcb00ea6d
+200314cf801faab200ea752803a8d7a90c503a039f824a53f4694e7342000000
+0049454e44ae426082
+"""),
+ 'basn0g01': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002001000000005b0147
+590000000467414d41000186a031e8965f0000005b49444154789c2dccb10903
+300c05d1ebd204b24a200b7a346f90153c82c18d0a61450751f1e08a2faaead2
+a4846ccea9255306e753345712e211b221bf4b263d1b427325255e8bdab29e6f
+6aca30692e9d29616ee96f3065f0bf1f1087492fd02f14c90000000049454e44
+ae426082
+"""),
+ 'basn0g02': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002002000000001ca13d
+890000000467414d41000186a031e8965f0000001f49444154789c6360085df5
+1f8cf1308850c20053868f0133091f6390b90700bd497f818b0989a900000000
+49454e44ae426082
+"""),
+ # A version of basn0g04 dithered down to 3 bits.
+ 'Basn0g03': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
+2900000001734249540371d88211000000fd49444154789c6d90d18906210c84
+c356f22356b2889588604301b112112b11d94a96bb495cf7fe87f32d996f2689
+44741cc658e39c0b118f883e1f63cc89dafbc04c0f619d7d898396c54b875517
+83f3a2e7ac09a2074430e7f497f00f1138a5444f82839c5206b1f51053cca968
+63258821e7f2b5438aac16fbecc052b646e709de45cf18996b29648508728612
+952ca606a73566d44612b876845e9a347084ea4868d2907ff06be4436c4b41a3
+a3e1774285614c5affb40dbd931a526619d9fa18e4c2be420858de1df0e69893
+a0e3e5523461be448561001042b7d4a15309ce2c57aef2ba89d1c13794a109d7
+b5880aa27744fc5c4aecb5e7bcef5fe528ec6293a930690000000049454e44ae
+426082
+"""),
+ 'basn0g04': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
+290000000467414d41000186a031e8965f0000004849444154789c6360601014
+545232367671090d4d4b2b2f6720430095dbd1418e002a77e64c720450b9ab56
+912380caddbd9b1c0154ee9933e408a072efde25470095fbee1d1902001f14ee
+01eaff41fa0000000049454e44ae426082
+"""),
+ 'basn0g08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200800000000561125
+280000000467414d41000186a031e8965f0000004149444154789c6364602400
+1408c8b30c05058c0f0829f8f71f3f6079301c1430ca11906764a2795c0c0605
+8c8ff0cafeffcff887e67131181430cae0956564040050e5fe7135e2d8590000
+000049454e44ae426082
+"""),
+ 'basn0g16': _dehex("""
+89504e470d0a1a0a0000000d49484452000000200000002010000000000681f9
+6b0000000467414d41000186a031e8965f0000005e49444154789cd5d2310ac0
+300c4351395bef7fc6dca093c0287b32d52a04a3d98f3f3880a7b857131363a0
+3a82601d089900dd82f640ca04e816dc06422640b7a03d903201ba05b7819009
+d02d680fa44c603f6f07ec4ff41938cf7f0016d84bd85fae2b9fd70000000049
+454e44ae426082
+"""),
+ 'basn2c08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200802000000fc18ed
+a30000000467414d41000186a031e8965f0000004849444154789cedd5c10900
+300c024085ec91fdb772133b442bf4a1f8cee12bb40d043b800a14f81ca0ede4
+7d4c784081020f4a871fc284071428f0a0743823a94081bb7077a3c00182b1f9
+5e0f40cf4b0000000049454e44ae426082
+"""),
+ 'basn2c16': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000201002000000ac8831
+e00000000467414d41000186a031e8965f000000e549444154789cd596c10a83
+301044a7e0417fcb7eb7fdadf6961e06039286266693cc7a188645e43dd6a08f
+1042003e2fe09aef6472737e183d27335fcee2f35a77b702ebce742870a23397
+f3edf2705dd10160f3b2815fe8ecf2027974a6b0c03f74a6e4192843e75c6c03
+35e8ec3202f5e84c0181bbe8cca967a00d9df3491bb040671f2e6087ce1c2860
+8d1e05f8c7ee0f1d00b667e70df44467ef26d01fbd9bc028f42860f71d188bce
+fb8d3630039dbd59601e7ab3c06cf428507f0634d039afdc80123a7bb1801e7a
+b1802a7a14c89f016d74ce331bf080ce9e08f8414f04bca133bfe642fe5e07bb
+c4ec0000000049454e44ae426082
+"""),
+ 'basn3p04': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200403000000815467
+c70000000467414d41000186a031e8965f000000037342495404040477f8b5a3
+0000002d504c54452200ff00ffff8800ff22ff000099ffff6600dd00ff77ff00
+ff000000ff99ddff00ff00bbffbb000044ff00ff44d2b049bd00000047494441
+54789c63e8e8080d3d7366d5aaf27263e377ef66ce64204300952b28488e002a
+d7c5851c0154eeddbbe408a07119c81140e52a29912380ca4d4b23470095bb7b
+37190200e0c4ead10f82057d0000000049454e44ae426082
+"""),
+ 'basn6a08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7a
+f40000000467414d41000186a031e8965f0000006f49444154789cedd6310a80
+300c46e12764684fa1f73f55048f21c4ddc545781d52e85028fc1f4d28d98a01
+305e7b7e9cffba33831d75054703ca06a8f90d58a0074e351e227d805c8254e3
+1bb0420f5cdc2e0079208892ffe2a00136a07b4007943c1004d900195036407f
+011bf00052201a9c160fb84c0000000049454e44ae426082
+"""),
+ 'cs3n3p08': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
+c60000000467414d41000186a031e8965f0000000373424954030303a392a042
+00000054504c544592ff0000ff9200ffff00ff0000dbff00ff6dffb600006dff
+b6ff00ff9200dbff000049ffff2400ff000024ff0049ff0000ffdb00ff4900ff
+b6ffff0000ff2400b6ffffdb000092ffff6d000024ffff49006dff00df702b17
+0000004b49444154789c85cac70182000000b1b3625754b0edbfa72324ef7486
+184ed0177a437b680bcdd0031c0ed00ea21f74852ed00a1c9ed0086da0057487
+6ed0121cd6d004bda0013a421ff803224033e177f4ae260000000049454e44ae
+426082
+"""),
+ 's09n3p02': _dehex("""
+89504e470d0a1a0a0000000d49484452000000090000000902030000009dffee
+830000000467414d41000186a031e8965f000000037342495404040477f8b5a3
+0000000c504c544500ff000077ffff00ffff7700ff5600640000001f49444154
+789c63600002fbff0c0c56ab19182ca381581a4283f82071200000696505c36a
+437f230000000049454e44ae426082
+"""),
+ 'tbgn3p08': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
+c60000000467414d41000186a031e8965f00000207504c54457f7f7fafafafab
+abab110000222200737300999999510d00444400959500959595e6e600919191
+8d8d8d620d00898989666600b7b700911600000000730d007373736f6f6faaaa
+006b6b6b676767c41a00cccc0000f30000ef00d51e0055555567670000dd0051
+515100d1004d4d4de61e0038380000b700160d0d00ab00560d00090900009500
+009100008d003333332f2f2f2f2b2f2b2b000077007c7c001a05002b27000073
+002b2b2b006f00bb1600272727780d002323230055004d4d00cc1e00004d00cc
+1a000d00003c09006f6f00002f003811271111110d0d0d55554d090909001100
+4d0900050505000d00e2e200000900000500626200a6a6a6a2a2a29e9e9e8484
+00fb00fbd5d500801100800d00ea00ea555500a6a600e600e6f7f700e200e233
+0500888888d900d9848484c01a007777003c3c05c8c8008080804409007c7c7c
+bb00bbaa00aaa600a61e09056262629e009e9a009af322005e5e5e05050000ee
+005a5a5adddd00a616008d008d00e20016050027270088110078780000c40078
+00787300736f006f44444400aa00c81e004040406600663c3c3c090000550055
+1a1a00343434d91e000084004d004d007c004500453c3c00ea1e00222222113c
+113300331e1e1efb22001a1a1a004400afaf00270027003c001616161e001e0d
+160d2f2f00808000001e00d1d1001100110d000db7b7b7090009050005b3b3b3
+6d34c4230000000174524e530040e6d86600000001624b474402660b7c640000
+01f249444154789c6360c0048c8c58049100575f215ee92e6161ef109cd2a15e
+4b9645ce5d2c8f433aa4c24f3cbd4c98833b2314ab74a186f094b9c2c27571d2
+6a2a58e4253c5cda8559057a392363854db4d9d0641973660b0b0bb76bb16656
+06970997256877a07a95c75a1804b2fbcd128c80b482a0b0300f8a824276a9a8
+ec6e61612b3e57ee06fbf0009619d5fac846ac5c60ed20e754921625a2daadc6
+1967e29e97d2239c8aec7e61fdeca9cecebef54eb36c848517164514af16169e
+866444b2b0b7b55534c815cc2ec22d89cd1353800a8473100a4485852d924a6a
+412adc74e7ad1016ceed043267238c901716f633a812022998a4072267c4af02
+92127005c0f811b62830054935ce017b38bf0948cc5c09955f030a24617d9d46
+63371fd940b0827931cbfdf4956076ac018b592f72d45594a9b1f307f3261b1a
+084bc2ad50018b1900719ba6ba4ca325d0427d3f6161449486f981144cf3100e
+2a5f2a1ce8683e4ddf1b64275240c8438d98af0c729bbe07982b8a1c94201dc2
+b3174c9820bcc06201585ad81b25b64a2146384e3798290c05ad280a18c0a62e
+e898260c07fca80a24c076cc864b777131a00190cdfa3069035eccbc038c30e1
+3e88b46d16b6acc5380d6ac202511c392f4b789aa7b0b08718765990111606c2
+9e854c38e5191878fbe471e749b0112bb18902008dc473b2b2e8e72700000000
+49454e44ae426082
+"""),
+ 'Tp2n3p08': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020080300000044a48a
+c60000000467414d41000186a031e8965f00000300504c544502ffff80ff05ff
+7f0703ff7f0180ff04ff00ffff06ff000880ff05ff7f07ffff06ff000804ff00
+0180ff02ffff03ff7f02ffff80ff0503ff7f0180ffff0008ff7f0704ff00ffff
+06ff000802ffffff7f0704ff0003ff7fffff0680ff050180ff04ff000180ffff
+0008ffff0603ff7f80ff05ff7f0702ffffff000880ff05ffff0603ff7f02ffff
+ff7f070180ff04ff00ffff06ff000880ff050180ffff7f0702ffff04ff0003ff
+7fff7f0704ff0003ff7f0180ffffff06ff000880ff0502ffffffff0603ff7fff
+7f0702ffff04ff000180ff80ff05ff0008ff7f07ffff0680ff0504ff00ff0008
+0180ff03ff7f02ffff02ffffffff0604ff0003ff7f0180ffff000880ff05ff7f
+0780ff05ff00080180ff02ffffff7f0703ff7fffff0604ff00ff7f07ff0008ff
+ff0680ff0504ff0002ffff0180ff03ff7fff0008ffff0680ff0504ff000180ff
+02ffff03ff7fff7f070180ff02ffff04ff00ffff06ff0008ff7f0780ff0503ff
+7fffff06ff0008ff7f0780ff0502ffff03ff7f0180ff04ff0002ffffff7f07ff
+ff0604ff0003ff7fff00080180ff80ff05ffff0603ff7f0180ffff000804ff00
+80ff0502ffffff7f0780ff05ffff0604ff000180ffff000802ffffff7f0703ff
+7fff0008ff7f070180ff03ff7f02ffff80ff05ffff0604ff00ff0008ffff0602
+ffff0180ff04ff0003ff7f80ff05ff7f070180ff04ff00ff7f0780ff0502ffff
+ff000803ff7fffff0602ffffff7f07ffff0680ff05ff000804ff0003ff7f0180
+ff02ffff0180ffff7f0703ff7fff000804ff0080ff05ffff0602ffff04ff00ff
+ff0603ff7fff7f070180ff80ff05ff000803ff7f0180ffff7f0702ffffff0008
+04ff00ffff0680ff0503ff7f0180ff04ff0080ff05ffff06ff000802ffffff7f
+0780ff05ff0008ff7f070180ff03ff7f04ff0002ffffffff0604ff00ff7f07ff
+000880ff05ffff060180ff02ffff03ff7f80ff05ffff0602ffff0180ff03ff7f
+04ff00ff7f07ff00080180ffff000880ff0502ffff04ff00ff7f0703ff7fffff
+06ff0008ffff0604ff00ff7f0780ff0502ffff03ff7f0180ffdeb83387000000
+f874524e53000000000000000008080808080808081010101010101010181818
+1818181818202020202020202029292929292929293131313131313131393939
+393939393941414141414141414a4a4a4a4a4a4a4a52525252525252525a5a5a
+5a5a5a5a5a62626262626262626a6a6a6a6a6a6a6a73737373737373737b7b7b
+7b7b7b7b7b83838383838383838b8b8b8b8b8b8b8b94949494949494949c9c9c
+9c9c9c9c9ca4a4a4a4a4a4a4a4acacacacacacacacb4b4b4b4b4b4b4b4bdbdbd
+bdbdbdbdbdc5c5c5c5c5c5c5c5cdcdcdcdcdcdcdcdd5d5d5d5d5d5d5d5dedede
+dededededee6e6e6e6e6e6e6e6eeeeeeeeeeeeeeeef6f6f6f6f6f6f6f6b98ac5
+ca0000012c49444154789c6360e7169150d230b475f7098d4ccc28a96ced9e32
+63c1da2d7b8e9fb97af3d1fb8f3f18e8a0808953544a4dd7c4c2c9233c2621bf
+b4aab17fdacce5ab36ee3a72eafaad87efbefea68702362e7159652d031b07cf
+c0b8a4cce28aa68e89f316aedfb4ffd0b92bf79fbcfcfe931e0a183904e55435
+8decdcbcc22292b3caaadb7b27cc5db67af3be63e72fdf78fce2d31f7a2860e5
+119356d037b374f10e8a4fc92eaa6fee99347fc9caad7b0f9ebd74f7c1db2fbf
+e8a180995f484645dbdccad12f38363dafbcb6a573faeca5ebb6ed3e7ce2c29d
+e76fbefda38702063e0149751d537b67ff80e8d4dcc29a86bea97316add9b0e3
+c0e96bf79ebdfafc971e0a587885e515f58cad5d7d43a2d2720aeadaba26cf5a
+bc62fbcea3272fde7efafac37f3a28000087c0fe101bc2f85f0000000049454e
+44ae426082
+"""),
+ 'tbbn1g04': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020040000000093e1c8
+290000000467414d41000186a031e8965f0000000274524e530007e8f7589b00
+000002624b47440000aa8d23320000013e49444154789c55d1cd4b024118c7f1
+efbe6419045b6a48a72d352808b435284f9187ae9b098627a1573a19945beba5
+e8129e8222af11d81e3a4545742de8ef6af6d5762e0fbf0fc33c33f36085cb76
+bc4204778771b867260683ee57e13f0c922df5c719c2b3b6c6c25b2382cea4b9
+9f7d4f244370746ac71f4ca88e0f173a6496749af47de8e44ba8f3bf9bdfa98a
+0faf857a7dd95c7dc8d7c67c782c99727997f41eb2e3c1e554152465bb00fe8e
+b692d190b718d159f4c0a45c4435915a243c58a7a4312a7a57913f05747594c6
+46169866c57101e4d4ce4d511423119c419183a3530cc63db88559ae28e7342a
+1e9c8122b71139b8872d6e913153224bc1f35b60e4445bd4004e20ed6682c759
+1d9873b3da0fbf50137dc5c9bde84fdb2ec8bde1189e0448b63584735993c209
+7a601bd2710caceba6158797285b7f2084a2f82c57c01a0000000049454e44ae
+426082
+"""),
+ 'tbrn2c08': _dehex("""
+89504e470d0a1a0a0000000d4948445200000020000000200802000000fc18ed
+a30000000467414d41000186a031e8965f0000000674524e53007f007f007f8a
+33334f00000006624b474400ff0000000033277cf3000004d649444154789cad
+965f68537714c73fd912d640235e692f34d0406fa0c1663481045ab060065514
+56660a295831607df0a1488715167060840a1614e6431e9cb34fd2c00a762c85
+f6a10f816650c13b0cf40612e1822ddc4863bd628a8924d23d6464f9d3665dd9
+f7e977ce3dbff3cd3939bfdfef6bb87dfb364782dbed065ebe7cd93acc78b4ec
+a228debd7bb7bfbfbfbbbbfb7f261045311a8d261209405194274f9ea4d3e916
+f15f1c3eb5dd6e4fa5fecce526239184a2b0b8486f6f617171b1f5ae4311381c
+8e57af5e5dbd7a351088150a78bd389d44222c2f93cdfe66b7db8f4ee07038b6
+b6b6bebf766d7e7e7e60a06432313b4ba984c3c1c4049a46b95c5a58583822c1
+dbb76f27272733d1b9df853c3030c0f232562b9108cf9eb1b888d7cbf030abab
+31abd5fa1f08dc6ef7e7cf9f1f3f7e1c8944745d4f1400c62c001313acad21cb
+b8dd2c2c603271eb1640341aad4c6d331aa7e8c48913a150a861307ecc11e964
+74899919bc5e14e56fffc404f1388502f178dceff7ef4bf0a5cfe7abb533998c
+e5f9ea2f1dd88c180d64cb94412df3dd57e83a6b3b3c7a84c98420100c72fd3a
+636348bae726379fe69e8e8d8dbd79f3a6558b0607079796965256479b918085
+7b02db12712b6181950233023f3f647494ee6e2e5ea45864cce5b8a7fe3acffc
+3aebb22c2bd5d20e22d0757d7b7bbbbdbd3d94a313bed1b0aa3cd069838b163a
+8d4c59585f677292d0b84d9a995bd337def3fe6bbe5e6001989b9b6bfe27ea08
+36373781542ab56573248b4c5bc843ac4048c7ab21aa24ca00534c25482828a3
+8c9ee67475bbaaaab22cb722c8e57240a150301a8d219de94e44534d7d90e885
+87acb0e2c4f9800731629b6c5ee14a35a6b9887d2a0032994cb9cf15dbe59650
+ff7b46a04c9a749e7cc5112214266cc65c31354d5b5d5d3d90209bcd5616a552
+a95c2e87f2a659bd9ee01c2cd73964e438f129a6aa9e582c363838b80f81d7eb
+5555b56a2a8ad2d9d7affd0409f8015c208013fea00177b873831b0282c964f2
+783c1e8fa7582cee5f81a669b5e6eeeeaee58e8559b0c233d8843c7c0b963a82
+34e94b5cb2396d7d7d7db22c8ba258fb0afd43f0e2c58b919191ba9de9b4d425
+118329b0c3323c8709d02041b52b4ea7f39de75d2a934a2693c0a953a76a93d4
+5d157ebf7f6565a5542a553df97c5e10045dd731c130b86113cc300cbd489224
+08422a952a140a95788fc763b1d41558d7a2d7af5f5fb870a1d6a3aaaacd6603
+18802da84c59015bd2e6897b745d9765b99a1df0f97c0daf74e36deaf7fbcd66
+73ad2797cb89a2c839880188a2e8743a8bc5a22ccbba5e376466b3b9bdbdbd21
+6123413a9d0e0402b51e4dd3bababa788eb022b85caeb6b6364551b6b7b76942
+43f7f727007a7a7a04a1ee8065b3595fde2768423299ac1ec6669c3973e65004
+c0f8f878ad69341a33994ced2969c0d0d0502412f9f8f163f3a7fd654b474787
+288ad53e74757535df6215b85cae60302849d2410aecc037f9f2e5cbd5b5c160
+680eb0dbede170381c0e7ff8f0a185be3b906068684892a4ca7a6f6faff69328
+8ad3d3d3f7efdfdfdbdbfb57e96868a14d0d0643381c96242997cbe5f3794010
+84603078fcf8f1d6496bd14a3aba5c2ea7d369341a5555b5582c8140e0fcf9f3
+1b1b1b87cf4eeb0a8063c78e45a3d19e9e1ebfdfdf5a831e844655d18093274f
+9e3d7bf6d3a74f3b3b3b47c80efc05ff7af28fefb70d9b0000000049454e44ae
+426082
+"""),
+ 'basn6a16': _dehex("""
+89504e470d0a1a0a0000000d494844520000002000000020100600000023eaa6
+b70000000467414d41000186a031e8965f00000d2249444154789cdd995f6c1c
+d775c67ff38fb34b724d2ee55a8e4b04a0ac87049100cab4dbd8c6528902cb4d
+10881620592e52d4325ac0905bc98a94025e71fd622cb5065ac98a0c283050c0
+728a00b6e542a1d126885cd3298928891d9a0444037e904434951d4b90b84b2f
+c9dde1fcebc33977a95555348f411e16dfce9d3b77ee77eebde77ce78c95a669
+0ad07c17009a13edd898b87dfb1fcb7d2b4d1bff217f33df80deb1e6267df0ff
+c1e6e6dfafdf1f5a7fd30f9aef66b6d546dd355bf02c40662e3307f9725a96c6
+744c3031f83782f171c148dbc3bf1774f5dad1e79d6f095a3f54d4fbec5234ef
+d9a2f8d73afe4f14f57ef4f42def7b44f19060f06b45bddf1c5534d77fd922be
+2973a15a82e648661c6e3240aa3612ead952b604bde57458894f29deaf133bac
+13d2766f5227a4a3b8cf08da7adfd6fbd6bd8a4fe9dbb43d35e3dfa3f844fbf8
+9119bf4f7144094fb56333abf8a86063ca106f94b3a3b512343765e60082097f
+1bb86ba72439a653519b09f5cee1ce61c897d37eedf5553580ae60f4af8af33a
+b14fd400b6a0f34535c0434afc0b3a9f07147527a5fa7ca218ff56c74d74dc3f
+155cfd3325fc278acf2ae1cb4a539f5f9937c457263b0bd51234c732a300cdd1
+cc1840f0aaff54db0e4874ed5a9b5d6d27d4bb36746d80de72baa877ff4b275a
+d7895ed1897ea4139b5143fcbb1a62560da1ed9662aaed895ec78a91c18795b8
+5e07ab4af8ba128e95e682e0728bf8f2e5ae815a091a53d902ac1920d8e05f06
+589de8d8d66680789f4e454fb9d9ec66cd857af796ee2d902fa73fd5bba775a2
+153580ae44705ed0d37647d15697cb8f14bfa3e3e8fdf8031d47af571503357c
+f30d25acedcbbf135c9a35c49766ba07ab255859e8ec03684e66860182dff8f7
+0304bff6ff1c20fc81b7afdd00a71475539a536e36bb5973a19e3b923b02bde5
+e4efd4003ac170eb2d13fe274157afedbd82d6fb3a9a1e85e4551d47cf7078f8
+9671fe4289ebf5f2bf08d63f37c4eb4773c55a0996efeefa0ca011671d8060ca
+2f0004c7fcc300e166ef0240f825efe3361f106d57d423d0723f7acacd66376b
+2ed47b7a7a7a205f4ef4ac4691e0aad9aa0d41cf13741c3580a506487574ddca
+61a8c403c1863ebfbcac3475168b2de28b8b3d77544bb05ce92a02aceced3c0d
+d0cc65ea371b201cf1c601c24dde1c4078cedbdeb60322f50126a019bf6edc9b
+39e566b39b3517eaf97c3e0fbde5e4491d45bd74537145d155b476aa0176e868
+c6abebf30dbd5e525c54ac8e18e2d56abeb756827a3d970358a97416019a6f64
+f60004fdfe1580d5c98e618070cc1b05887eee7e0d209a70db7d8063029889b4
+c620ead78d7b33a7dc6c76b3e6427ddddbebde867c393aa7845e5403e8ca794a
+d0d6fb897af5f03525fe5782f5e7046bdaef468bf88d1debc6ab25583cd17310
+6079b9ab0ba059c914018245bf076075b5a303200c3c1f209a733701444fbbaf
+00c4134ebb016c5d0b23614c243701cdf875e3decce9349bddacb9505fbf7dfd
+76e82d87736a00f5d2b5ffd4b7dce2719a4d25ae717ee153c1abef18e257cfad
+7fa45682da48ef38c052b53b0fd06864b300c151ff08c0ea431de701a287dd5f
+004497dc7b01a253ee3e80b8c7f91c20f967fb6fdb7c80ada7d8683723614c24
+3701cdf875e3decc29379bddacb950ef3fd47f08f2e5a61ea4aa2a3eb757cd55
+13345efcfa59c12b2f19e2578ef77fb75a82854ffbee01a83f977b11a031931d
+040802df07082b5e11207cc17b1e209a770700e2df0a83e409fb7580f827c230
+99b06fd901fb058d6835dacd481813c94d40337eddb83773cacd66376b2ed437
+bebcf165e82d2f4e4beb7f3fa6e652c2d7ee10bc78c010bfb87fe3c95a09ae9f
+bd732740bd2fb700d0f865f64180e059ff044018ca0ca28a5b04883f701e0088
+bfec7c0c909cb71f0448c6ec518074b375012079d9dedf66004bcfbc51eb2dd1
+aadacd481813c94d40337eddb83773cacd66376b2ed487868686205fbe7c49ef
+5605a73f34c4a7a787eeab96e0da81bb4e022c15ba27019a5b339300e16bf286
+a8eae601e25866907cdf3e0890acb36f00245fb57f05904e59c300e92561946e
+b2e600d209ab7d07f04d458dfb46ad1bd16ab49b913026929b8066fcba716fe6
+949bcd6ed65ca8ef7e7cf7e3d05b7e7c8f217ee6cdddbb6a25a856f37980e0c7
+fe4e80a82623c48193014846ec7180f4acf518409aca0cd28a5504e03b32c374
+de1a00608a0240faaa327a4b19fe946fb6f90054dbb5f2333d022db56eb4966a
+3723614c243701cdf8f556bea8a7dc6c76b3e66bd46584ddbbcebc0990cf4b0f
+ff4070520c282338a7e26700ec725202b01e4bcf0258963c6f1d4d8f0030cb20
+805549c520930c03584fa522b676f11600ffc03fde3e1b3489a9c9054c9aa23b
+c08856a3dd8c843191dc0434e3d78d7b33a75c36fb993761f7ae5a69f72ef97f
+e6ad336fed7e1c60e8bee96980bbdebbb60da07b7069062033d9dc0ae03d296f
+70ab511ec071640676252902d833c916007b3e1900b0a6d2028035968e025861
+ea01581369fb11488c34d18cbc95989afccca42baad65ba2d5683723614c24d7
+8066fcbab8b7e96918baaf5aaa56219f975fb50a43f7c9bde90fa73f1c1a02d8
+78f2e27e803b77ca08b90519315b6fe400fc1392097a9eccc0ad444500e70199
+a1331f0f00d8934901c07e5d526ceb87c2d07e2579badd005a2b31a5089391b7
+1253358049535a6add8856dd0146c298482e01ede27ed878b256ba7600ee3a09
+c18fc1df09fe01084ec25defc1b56db0f1a4f4bd78e0e2818d2f0334e7330300
+7df7c888b917e50dd9c1c60c80efcb0cbc63e1f700bce7c31700dccbd1060027
+8add9b0de06c8e2f00d84962b7d7030e2a61538331b98051f92631bd253f336a
+dd8856a3dd44c25c390efddfad96ae9f853b77c25201ba27c533b8bdf28b6ad0
+3d084b33d2e7fa59099e9901b8f2d29597fa0f01848f78e70082117f1ca07b76
+6910209b9519f895a008d031bbba05c09d8f06005c5b18b8fba25300cea6780e
+c03e911c6ccf06d507b48a4fa606634a114609de929f9934c5a87511ad57cfc1
+fa476aa5854fa1ef1e3910b905686e85cc24c40138198915f133d2d6dc2a7dea
+7df2ccc2a752faf2cec1d577aebeb37e3b4034eeee0008dff3be0e6b923773b4
+7904c0ef9119767cb4fa1500ef1361e08e452500f71561e84cc4ed3e20fab6a2
+c905f40cb76a3026bf3319b91ac2e46792a6dcd801ebc6aba5da08f48ecb81c8
+bd088d5f42f6417191de93908c803d0e76199292b485af41b60e8d9c3c537f0e
+8211f0c7211a077707dc18b931b2ee6d80a4d7ae024491ebc24d4a708ff70680
+7f25e807e8785f1878e322d6ddaf453f0770ff2dfa769b01423dbbad72a391b6
+5a7c3235985629423372494cab55c8f7d64a8b27a0e7202c55a13b0f8d19c80e
+4ae9ca3f015115dc3ca467c17a4c7ee95970ab10e5a54ff0ac3cd39881ee5958
+1a84f03df0be0e492fd855a8d6aa35d10b4962dbb0a604a3d3ee5e80a8eee600
+a24977f8660378bf0bbf00e01d0a8fb7f980f04b8aa6ce6aca8d5a7533c52753
+839152c4e222f4dc512dd5eb90cbc981e8ea12cf90cd8a8bf47d89159e2741d3
+7124f65b96fcd254dae258fa84a13c13043246a32129574787e49eae2b49b86d
+c3e2e78b9ff7f4002415bb08907c66df0d103b4e0c104db90500ff70700c203a
+ee1e82dba4c3e16e256c0acca6ceaae9afd1f612d7eb472157ac95962bd05594
+7dd1598466053245088e827f44628657942a825b84e4fb601f84b4025611aca3
+901e01bb024911dc0a4445f08e41f83df02b10142173149ab71baf027611ea95
+7a257704201d14cd9af4d90b00f194530088cb4e09c0df1c5c0088f7393f6833
+c0aa3ac156655de3bca9b34ab9716906ba07aba5e5bba1eb3358d90b9da7c533
+64f6888bf47b60f521e8380fe10be03d2feac17900927560df40f4e48f805960
+50328d648bf4893f9067c217a0631656b7c898c122847bc07b03a2d3e0ee85e4
+33b0ef867450c4fad2ecd26cf7168074c0ba0c904cdac300c9cfec4701924df6
+1cdca61e10685c6f7d52d0caba1498972f43d740adb4b2009d7d7220b20e3473
+90a943d00ffe959bb6eac3e0fe42ea49ee00c45f06e76329b1dabf127d690d80
+5581b408f63c2403e0cc433c00ee658836803b0fd100747c04ab5f917704fd10
+d5c1cd41ec801343d207f602a403605d86e5f9e5f9ae0d00e994556833806685
+c931fb709b0f08b4e869bea5c827859549e82c544b8d29c816a0390999613920
+7e610d5727a16318c2003c1fa24be0de2b32caf92224e7c17e5004b6350c4c01
+05601218066b0ad28224e149019c086257ca315102de2712903bde97b8144d82
+3b2c6ac52d403c054e019249b087f53d0558995a99ea946c70cc927458b3c1ff
+550f30050df988d4284376b4566a8e416654cc921985e037e0df0fc131f00f4b
+acf0c6211c036f14a239703741740adc7da227edd7e56b833d0ae92549b4d357
+25dfb49ed2ff63908e6adf27d6d0dda7638d4154d2778daca17f58e61297c129
+41f233b01f5dc3740cac51688c35c6b22580f48224fee9b83502569a66b629f1
+09f3713473413e2666e7fe6f6c6efefdfafda1f56f6e06f93496d9d67cb7366a
+9964b6f92e64b689196ec6c604646fd3fe4771ff1bf03f65d8ecc3addbb5f300
+00000049454e44ae426082
+"""),
+}
+
+def read_pam_header(infile):
+ """
+ Read (the rest of a) PAM header. `infile` should be positioned
+ immediately after the initial 'P7' line (at the beginning of the
+ second line). Returns are as for `read_pnm_header`.
+ """
+
+ # Unlike PBM, PGM, and PPM, we can read the header a line at a time.
+ header = dict()
+ while True:
+ l = infile.readline().strip()
+ if l == strtobytes('ENDHDR'):
+ break
+ if not l:
+ raise EOFError('PAM ended prematurely')
+ if l[0] == strtobytes('#'):
+ continue
+ l = l.split(None, 1)
+ if l[0] not in header:
+ header[l[0]] = l[1]
+ else:
+ header[l[0]] += strtobytes(' ') + l[1]
+
+ required = ['WIDTH', 'HEIGHT', 'DEPTH', 'MAXVAL']
+ required = [strtobytes(x) for x in required]
+ WIDTH,HEIGHT,DEPTH,MAXVAL = required
+ present = [x for x in required if x in header]
+ if len(present) != len(required):
+ raise Error('PAM file must specify WIDTH, HEIGHT, DEPTH, and MAXVAL')
+ width = int(header[WIDTH])
+ height = int(header[HEIGHT])
+ depth = int(header[DEPTH])
+ maxval = int(header[MAXVAL])
+ if (width <= 0 or
+ height <= 0 or
+ depth <= 0 or
+ maxval <= 0):
+ raise Error(
+ 'WIDTH, HEIGHT, DEPTH, MAXVAL must all be positive integers')
+ return 'P7', width, height, depth, maxval
+
+def read_pnm_header(infile, supported=('P5','P6')):
+ """
+ Read a PNM header, returning (format,width,height,depth,maxval).
+ `width` and `height` are in pixels. `depth` is the number of
+ channels in the image; for PBM and PGM it is synthesized as 1, for
+ PPM as 3; for PAM images it is read from the header. `maxval` is
+ synthesized (as 1) for PBM images.
+ """
+
+ # Generally, see http://netpbm.sourceforge.net/doc/ppm.html
+ # and http://netpbm.sourceforge.net/doc/pam.html
+
+ supported = [strtobytes(x) for x in supported]
+
+ # Technically 'P7' must be followed by a newline, so by using
+ # rstrip() we are being liberal in what we accept. I think this
+ # is acceptable.
+ type = infile.read(3).rstrip()
+ if type not in supported:
+ raise NotImplementedError('file format %s not supported' % type)
+ if type == strtobytes('P7'):
+ # PAM header parsing is completely different.
+ return read_pam_header(infile)
+ # Expected number of tokens in header (3 for P4, 4 for P6)
+ expected = 4
+ pbm = ('P1', 'P4')
+ if type in pbm:
+ expected = 3
+ header = [type]
+
+ # We have to read the rest of the header byte by byte because the
+ # final whitespace character (immediately following the MAXVAL in
+ # the case of P6) may not be a newline. Of course all PNM files in
+ # the wild use a newline at this point, so it's tempting to use
+ # readline; but it would be wrong.
+ def getc():
+ c = infile.read(1)
+ if not c:
+ raise Error('premature EOF reading PNM header')
+ return c
+
+ c = getc()
+ while True:
+ # Skip whitespace that precedes a token.
+ while c.isspace():
+ c = getc()
+ # Skip comments.
+ while c == '#':
+ while c not in '\n\r':
+ c = getc()
+ if not c.isdigit():
+ raise Error('unexpected character %s found in header' % c)
+ # According to the specification it is legal to have comments
+ # that appear in the middle of a token.
+ # This is bonkers; I've never seen it; and it's a bit awkward to
+ # code good lexers in Python (no goto). So we break on such
+ # cases.
+ token = strtobytes('')
+ while c.isdigit():
+ token += c
+ c = getc()
+ # Slight hack. All "tokens" are decimal integers, so convert
+ # them here.
+ header.append(int(token))
+ if len(header) == expected:
+ break
+ # Skip comments (again)
+ while c == '#':
+ while c not in '\n\r':
+ c = getc()
+ if not c.isspace():
+ raise Error('expected header to end with whitespace, not %s' % c)
+
+ if type in pbm:
+ # synthesize a MAXVAL
+ header.append(1)
+ depth = (1,3)[type == strtobytes('P6')]
+ return header[0], header[1], header[2], depth, header[3]
+
+def write_pnm(file, width, height, pixels, meta):
+ """Write a Netpbm PNM/PAM file."""
+
+ bitdepth = meta['bitdepth']
+ maxval = 2**bitdepth - 1
+ # Rudely, the number of image planes can be used to determine
+ # whether we are L (PGM), LA (PAM), RGB (PPM), or RGBA (PAM).
+ planes = meta['planes']
+ # Can be an assert as long as we assume that pixels and meta came
+ # from a PNG file.
+ assert planes in (1,2,3,4)
+ if planes in (1,3):
+ if 1 == planes:
+ # PGM
+ # Could generate PBM if maxval is 1, but we don't (for one
+ # thing, we'd have to convert the data, not just blat it
+ # out).
+ fmt = 'P5'
+ else:
+ # PPM
+ fmt = 'P6'
+ file.write('%s %d %d %d\n' % (fmt, width, height, maxval))
+ if planes in (2,4):
+ # PAM
+ # See http://netpbm.sourceforge.net/doc/pam.html
+ if 2 == planes:
+ tupltype = 'GRAYSCALE_ALPHA'
+ else:
+ tupltype = 'RGB_ALPHA'
+ file.write('P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\n'
+ 'TUPLTYPE %s\nENDHDR\n' %
+ (width, height, planes, maxval, tupltype))
+ # Values per row
+ vpr = planes * width
+ # struct format
+ fmt = '>%d' % vpr
+ if maxval > 0xff:
+ fmt = fmt + 'H'
+ else:
+ fmt = fmt + 'B'
+ for row in pixels:
+ file.write(struct.pack(fmt, *row))
+ file.flush()
+
+def color_triple(color):
+ """
+ Convert a command line colour value to a RGB triple of integers.
+ FIXME: Somewhere we need support for greyscale backgrounds etc.
+ """
+ if color.startswith('#') and len(color) == 4:
+ return (int(color[1], 16),
+ int(color[2], 16),
+ int(color[3], 16))
+ if color.startswith('#') and len(color) == 7:
+ return (int(color[1:3], 16),
+ int(color[3:5], 16),
+ int(color[5:7], 16))
+ elif color.startswith('#') and len(color) == 13:
+ return (int(color[1:5], 16),
+ int(color[5:9], 16),
+ int(color[9:13], 16))
+
+def _add_common_options(parser):
+ """Call *parser.add_option* for each of the options that are
+ common between this PNG--PNM conversion tool and the gen
+ tool.
+ """
+ parser.add_option("-i", "--interlace",
+ default=False, action="store_true",
+ help="create an interlaced PNG file (Adam7)")
+ parser.add_option("-t", "--transparent",
+ action="store", type="string", metavar="#RRGGBB",
+ help="mark the specified colour as transparent")
+ parser.add_option("-b", "--background",
+ action="store", type="string", metavar="#RRGGBB",
+ help="save the specified background colour")
+ parser.add_option("-g", "--gamma",
+ action="store", type="float", metavar="value",
+ help="save the specified gamma value")
+ parser.add_option("-c", "--compression",
+ action="store", type="int", metavar="level",
+ help="zlib compression level (0-9)")
+ return parser
+
+def _main(argv):
+ """
+ Run the PNG encoder with options from the command line.
+ """
+
+ # Parse command line arguments
+ from optparse import OptionParser
+ import re
+ version = '%prog ' + re.sub(r'( ?\$|URL: |Rev:)', '', __version__)
+ parser = OptionParser(version=version)
+ parser.set_usage("%prog [options] [imagefile]")
+ parser.add_option('-r', '--read-png', default=False,
+ action='store_true',
+ help='Read PNG, write PNM')
+ parser.add_option("-a", "--alpha",
+ action="store", type="string", metavar="pgmfile",
+ help="alpha channel transparency (RGBA)")
+ _add_common_options(parser)
+
+ (options, args) = parser.parse_args(args=argv[1:])
+
+ # Convert options
+ if options.transparent is not None:
+ options.transparent = color_triple(options.transparent)
+ if options.background is not None:
+ options.background = color_triple(options.background)
+
+ # Prepare input and output files
+ if len(args) == 0:
+ infilename = '-'
+ infile = sys.stdin
+ elif len(args) == 1:
+ infilename = args[0]
+ infile = open(infilename, 'rb')
+ else:
+ parser.error("more than one input file")
+ outfile = sys.stdout
+ if sys.platform == "win32":
+ import msvcrt, os
+ msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
+
+ if options.read_png:
+ # Encode PNG to PPM
+ png = Reader(file=infile)
+ width,height,pixels,meta = png.asDirect()
+ write_pnm(outfile, width, height, pixels, meta)
+ else:
+ # Encode PNM to PNG
+ format, width, height, depth, maxval = \
+ read_pnm_header(infile, ('P5','P6','P7'))
+ # When it comes to the variety of input formats, we do something
+ # rather rude. Observe that L, LA, RGB, RGBA are the 4 colour
+ # types supported by PNG and that they correspond to 1, 2, 3, 4
+ # channels respectively. So we use the number of channels in
+ # the source image to determine which one we have. We do not
+ # care about TUPLTYPE.
+ greyscale = depth <= 2
+ pamalpha = depth in (2,4)
+ supported = map(lambda x: 2**x-1, range(1,17))
+ try:
+ mi = supported.index(maxval)
+ except ValueError:
+ raise NotImplementedError(
+ 'your maxval (%s) not in supported list %s' %
+ (maxval, str(supported)))
+ bitdepth = mi+1
+ writer = Writer(width, height,
+ greyscale=greyscale,
+ bitdepth=bitdepth,
+ interlace=options.interlace,
+ transparent=options.transparent,
+ background=options.background,
+ alpha=bool(pamalpha or options.alpha),
+ gamma=options.gamma,
+ compression=options.compression)
+ if options.alpha:
+ pgmfile = open(options.alpha, 'rb')
+ format, awidth, aheight, adepth, amaxval = \
+ read_pnm_header(pgmfile, 'P5')
+ if amaxval != '255':
+ raise NotImplementedError(
+ 'maxval %s not supported for alpha channel' % amaxval)
+ if (awidth, aheight) != (width, height):
+ raise ValueError("alpha channel image size mismatch"
+ " (%s has %sx%s but %s has %sx%s)"
+ % (infilename, width, height,
+ options.alpha, awidth, aheight))
+ writer.convert_ppm_and_pgm(infile, pgmfile, outfile)
+ else:
+ writer.convert_pnm(infile, outfile)
+
+
+if __name__ == '__main__':
+ try:
+ _main(sys.argv)
+ except Error, e:
+ print >>sys.stderr, e
diff --git a/chromium/tools/telemetry/third_party/websocket-client/LICENSE b/chromium/tools/telemetry/third_party/websocket-client/LICENSE
new file mode 100644
index 00000000000..c255f4aae1d
--- /dev/null
+++ b/chromium/tools/telemetry/third_party/websocket-client/LICENSE
@@ -0,0 +1,506 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
diff --git a/chromium/tools/telemetry/third_party/websocket-client/README.chromium b/chromium/tools/telemetry/third_party/websocket-client/README.chromium
new file mode 100644
index 00000000000..d5b6b0e8ce2
--- /dev/null
+++ b/chromium/tools/telemetry/third_party/websocket-client/README.chromium
@@ -0,0 +1,20 @@
+Name: Python websocket-client
+Short Name: websocket-client
+URL: https://github.com/liris/websocket-client
+Version: 0
+Revision: 861f9cf354833fe3992315b60292865c5245c821
+Date: Tue Jul 10 19:57:00 2012 -0700
+License: LGPL-2.1
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+
+websocket-client module is WebSocket client for python. This provide the low
+level APIs for WebSocket. All APIs are the synchronous functions.
+
+Used by the python code in devtools-auto to communicate with a running Chrome instance.
+
+Local Modifications:
+None. However, test, example and packaging code from the upstream repository has
+not been copied downstream. \ No newline at end of file
diff --git a/chromium/tools/telemetry/third_party/websocket-client/README.rst b/chromium/tools/telemetry/third_party/websocket-client/README.rst
new file mode 100644
index 00000000000..1b7faeb8274
--- /dev/null
+++ b/chromium/tools/telemetry/third_party/websocket-client/README.rst
@@ -0,0 +1,140 @@
+=================
+websocket-client
+=================
+
+websocket-client module is WebSocket client for python. This provide the low level APIs for WebSocket. All APIs are the synchronous functions.
+
+websocket-client supports only hybi-13.
+
+License
+============
+
+ - LGPL
+
+Installation
+=============
+
+This module is tested on only Python 2.7.
+
+Type "python setup.py install" or "pip install websocket-client" to install.
+
+This module does not depend on any other module.
+
+Example
+============
+
+Low Level API example::
+
+ from websocket import create_connection
+ ws = create_connection("ws://echo.websocket.org/")
+ print "Sending 'Hello, World'..."
+ ws.send("Hello, World")
+ print "Sent"
+ print "Reeiving..."
+ result = ws.recv()
+ print "Received '%s'" % result
+ ws.close()
+
+
+JavaScript websocket-like API example::
+
+ import websocket
+ import thread
+ import time
+
+ def on_message(ws, message):
+ print message
+
+ def on_error(ws, error):
+ print error
+
+ def on_close(ws):
+ print "### closed ###"
+
+ def on_open(ws):
+ def run(*args):
+ for i in range(3):
+ time.sleep(1)
+ ws.send("Hello %d" % i)
+ time.sleep(1)
+ ws.close()
+ print "thread terminating..."
+ thread.start_new_thread(run, ())
+
+
+ if __name__ == "__main__":
+ websocket.enableTrace(True)
+ ws = websocket.WebSocketApp("ws://echo.websocket.org/",
+ on_message = on_message,
+ on_error = on_error,
+ on_close = on_close)
+ ws.on_open = on_open
+
+ ws.run_forever()
+
+
+wsdump.py
+============
+
+wsdump.py is simple WebSocket test(debug) tool.
+
+sample for echo.websocket.org::
+
+ $ wsdump.py ws://echo.websocket.org/
+ Press Ctrl+C to quit
+ > Hello, WebSocket
+ < Hello, WebSocket
+ > How are you?
+ < How are you?
+
+Usage
+---------
+
+usage::
+ wsdump.py [-h] [-v [VERBOSE]] ws_url
+
+WebSocket Simple Dump Tool
+
+positional arguments:
+ ws_url websocket url. ex. ws://echo.websocket.org/
+
+optional arguments:
+ -h, --help show this help message and exit
+
+ -v VERBOSE, --verbose VERBOSE set verbose mode. If set to 1, show opcode. If set to 2, enable to trace websocket module
+
+example::
+
+ $ wsdump.py ws://echo.websocket.org/
+ $ wsdump.py ws://echo.websocket.org/ -v
+ $ wsdump.py ws://echo.websocket.org/ -vv
+
+ChangeLog
+============
+
+- v0.7.0
+
+ - fixed problem to read long data.(ISSUE#12)
+ - fix buffer size boundary violation
+
+- v0.6.0
+
+ - Patches: UUID4, self.keep_running, mask_key (ISSUE#11)
+ - add wsdump.py tool
+
+- v0.5.2
+
+ - fix Echo App Demo Throw Error: 'NoneType' object has no attribute 'opcode (ISSUE#10)
+
+- v0.5.1
+
+ - delete invalid print statement.
+
+- v0.5.0
+
+ - support hybi-13 protocol.
+
+- v0.4.1
+
+ - fix incorrect custom header order(ISSUE#1)
+
diff --git a/chromium/tools/telemetry/third_party/websocket-client/websocket.py b/chromium/tools/telemetry/third_party/websocket-client/websocket.py
new file mode 100644
index 00000000000..480bfc0053d
--- /dev/null
+++ b/chromium/tools/telemetry/third_party/websocket-client/websocket.py
@@ -0,0 +1,756 @@
+"""
+websocket - WebSocket client library for Python
+
+Copyright (C) 2010 Hiroki Ohtani(liris)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+
+
+import socket
+from urlparse import urlparse
+import os
+import struct
+import uuid
+import hashlib
+import base64
+import logging
+
+"""
+websocket python client.
+=========================
+
+This version support only hybi-13.
+Please see http://tools.ietf.org/html/rfc6455 for protocol.
+"""
+
+
+# websocket supported version.
+VERSION = 13
+
+# closing frame status codes.
+STATUS_NORMAL = 1000
+STATUS_GOING_AWAY = 1001
+STATUS_PROTOCOL_ERROR = 1002
+STATUS_UNSUPPORTED_DATA_TYPE = 1003
+STATUS_STATUS_NOT_AVAILABLE = 1005
+STATUS_ABNORMAL_CLOSED = 1006
+STATUS_INVALID_PAYLOAD = 1007
+STATUS_POLICY_VIOLATION = 1008
+STATUS_MESSAGE_TOO_BIG = 1009
+STATUS_INVALID_EXTENSION = 1010
+STATUS_UNEXPECTED_CONDITION = 1011
+STATUS_TLS_HANDSHAKE_ERROR = 1015
+
+logger = logging.getLogger()
+
+class WebSocketException(Exception):
+ """
+ websocket exeception class.
+ """
+ pass
+
+class WebSocketConnectionClosedException(WebSocketException):
+ """
+ If remote host closed the connection or some network error happened,
+ this exception will be raised.
+ """
+ pass
+
+default_timeout = None
+traceEnabled = False
+
+def enableTrace(tracable):
+ """
+ turn on/off the tracability.
+
+ tracable: boolean value. if set True, tracability is enabled.
+ """
+ global traceEnabled
+ traceEnabled = tracable
+ if tracable:
+ if not logger.handlers:
+ logger.addHandler(logging.StreamHandler())
+ logger.setLevel(logging.DEBUG)
+
+def setdefaulttimeout(timeout):
+ """
+ Set the global timeout setting to connect.
+
+ timeout: default socket timeout time. This value is second.
+ """
+ global default_timeout
+ default_timeout = timeout
+
+def getdefaulttimeout():
+ """
+ Return the global timeout setting(second) to connect.
+ """
+ return default_timeout
+
+def _parse_url(url):
+ """
+ parse url and the result is tuple of
+ (hostname, port, resource path and the flag of secure mode)
+
+ url: url string.
+ """
+ if ":" not in url:
+ raise ValueError("url is invalid")
+
+ scheme, url = url.split(":", 1)
+
+ parsed = urlparse(url, scheme="http")
+ if parsed.hostname:
+ hostname = parsed.hostname
+ else:
+ raise ValueError("hostname is invalid")
+ port = 0
+ if parsed.port:
+ port = parsed.port
+
+ is_secure = False
+ if scheme == "ws":
+ if not port:
+ port = 80
+ elif scheme == "wss":
+ is_secure = True
+ if not port:
+ port = 443
+ else:
+ raise ValueError("scheme %s is invalid" % scheme)
+
+ if parsed.path:
+ resource = parsed.path
+ else:
+ resource = "/"
+
+ if parsed.query:
+ resource += "?" + parsed.query
+
+ return (hostname, port, resource, is_secure)
+
+def create_connection(url, timeout=None, **options):
+ """
+ connect to url and return websocket object.
+
+ Connect to url and return the WebSocket object.
+ Passing optional timeout parameter will set the timeout on the socket.
+ If no timeout is supplied, the global default timeout setting returned by getdefauttimeout() is used.
+ You can customize using 'options'.
+ If you set "header" dict object, you can set your own custom header.
+
+ >>> conn = create_connection("ws://echo.websocket.org/",
+ ... header={"User-Agent: MyProgram",
+ ... "x-custom: header"})
+
+
+ timeout: socket timeout time. This value is integer.
+ if you set None for this value, it means "use default_timeout value"
+
+ options: current support option is only "header".
+ if you set header as dict value, the custom HTTP headers are added.
+ """
+ websock = WebSocket()
+ websock.settimeout(timeout != None and timeout or default_timeout)
+ websock.connect(url, **options)
+ return websock
+
+_MAX_INTEGER = (1 << 32) -1
+_AVAILABLE_KEY_CHARS = range(0x21, 0x2f + 1) + range(0x3a, 0x7e + 1)
+_MAX_CHAR_BYTE = (1<<8) -1
+
+# ref. Websocket gets an update, and it breaks stuff.
+# http://axod.blogspot.com/2010/06/websocket-gets-update-and-it-breaks.html
+
+def _create_sec_websocket_key():
+ uid = uuid.uuid4()
+ return base64.encodestring(uid.bytes).strip()
+
+_HEADERS_TO_CHECK = {
+ "upgrade": "websocket",
+ "connection": "upgrade",
+ }
+
+class _SSLSocketWrapper(object):
+ def __init__(self, sock):
+ self.ssl = socket.ssl(sock)
+
+ def recv(self, bufsize):
+ return self.ssl.read(bufsize)
+
+ def send(self, payload):
+ return self.ssl.write(payload)
+
+_BOOL_VALUES = (0, 1)
+def _is_bool(*values):
+ for v in values:
+ if v not in _BOOL_VALUES:
+ return False
+
+ return True
+
+class ABNF(object):
+ """
+ ABNF frame class.
+ see http://tools.ietf.org/html/rfc5234
+ and http://tools.ietf.org/html/rfc6455#section-5.2
+ """
+
+ # operation code values.
+ OPCODE_TEXT = 0x1
+ OPCODE_BINARY = 0x2
+ OPCODE_CLOSE = 0x8
+ OPCODE_PING = 0x9
+ OPCODE_PONG = 0xa
+
+ # available operation code value tuple
+ OPCODES = (OPCODE_TEXT, OPCODE_BINARY, OPCODE_CLOSE,
+ OPCODE_PING, OPCODE_PONG)
+
+ # opcode human readable string
+ OPCODE_MAP = {
+ OPCODE_TEXT: "text",
+ OPCODE_BINARY: "binary",
+ OPCODE_CLOSE: "close",
+ OPCODE_PING: "ping",
+ OPCODE_PONG: "pong"
+ }
+
+ # data length threashold.
+ LENGTH_7 = 0x7d
+ LENGTH_16 = 1 << 16
+ LENGTH_63 = 1 << 63
+
+ def __init__(self, fin = 0, rsv1 = 0, rsv2 = 0, rsv3 = 0,
+ opcode = OPCODE_TEXT, mask = 1, data = ""):
+ """
+ Constructor for ABNF.
+ please check RFC for arguments.
+ """
+ self.fin = fin
+ self.rsv1 = rsv1
+ self.rsv2 = rsv2
+ self.rsv3 = rsv3
+ self.opcode = opcode
+ self.mask = mask
+ self.data = data
+ self.get_mask_key = os.urandom
+
+ @staticmethod
+ def create_frame(data, opcode):
+ """
+ create frame to send text, binary and other data.
+
+ data: data to send. This is string value(byte array).
+ if opcode is OPCODE_TEXT and this value is uniocde,
+ data value is conveted into unicode string, automatically.
+
+ opcode: operation code. please see OPCODE_XXX.
+ """
+ if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode):
+ data = data.encode("utf-8")
+ # mask must be set if send data from client
+ return ABNF(1, 0, 0, 0, opcode, 1, data)
+
+ def format(self):
+ """
+ format this object to string(byte array) to send data to server.
+ """
+ if not _is_bool(self.fin, self.rsv1, self.rsv2, self.rsv3):
+ raise ValueError("not 0 or 1")
+ if self.opcode not in ABNF.OPCODES:
+ raise ValueError("Invalid OPCODE")
+ length = len(self.data)
+ if length >= ABNF.LENGTH_63:
+ raise ValueError("data is too long")
+
+ frame_header = chr(self.fin << 7
+ | self.rsv1 << 6 | self.rsv2 << 5 | self.rsv3 << 4
+ | self.opcode)
+ if length < ABNF.LENGTH_7:
+ frame_header += chr(self.mask << 7 | length)
+ elif length < ABNF.LENGTH_16:
+ frame_header += chr(self.mask << 7 | 0x7e)
+ frame_header += struct.pack("!H", length)
+ else:
+ frame_header += chr(self.mask << 7 | 0x7f)
+ frame_header += struct.pack("!Q", length)
+
+ if not self.mask:
+ return frame_header + self.data
+ else:
+ mask_key = self.get_mask_key(4)
+ return frame_header + self._get_masked(mask_key)
+
+ def _get_masked(self, mask_key):
+ s = ABNF.mask(mask_key, self.data)
+ return mask_key + "".join(s)
+
+ @staticmethod
+ def mask(mask_key, data):
+ """
+ mask or unmask data. Just do xor for each byte
+
+ mask_key: 4 byte string(byte).
+
+ data: data to mask/unmask.
+ """
+ _m = map(ord, mask_key)
+ _d = map(ord, data)
+ for i in range(len(_d)):
+ _d[i] ^= _m[i % 4]
+ s = map(chr, _d)
+ return "".join(s)
+
+class WebSocket(object):
+ """
+ Low level WebSocket interface.
+ This class is based on
+ The WebSocket protocol draft-hixie-thewebsocketprotocol-76
+ http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
+
+ We can connect to the websocket server and send/recieve data.
+ The following example is a echo client.
+
+ >>> import websocket
+ >>> ws = websocket.WebSocket()
+ >>> ws.connect("ws://echo.websocket.org")
+ >>> ws.send("Hello, Server")
+ >>> ws.recv()
+ 'Hello, Server'
+ >>> ws.close()
+
+ get_mask_key: a callable to produce new mask keys, see the set_mask_key
+ function's docstring for more details
+ """
+ def __init__(self, get_mask_key = None):
+ """
+ Initalize WebSocket object.
+ """
+ self.connected = False
+ self.io_sock = self.sock = socket.socket()
+ self.get_mask_key = get_mask_key
+
+ def set_mask_key(self, func):
+ """
+ set function to create musk key. You can custumize mask key generator.
+ Mainly, this is for testing purpose.
+
+ func: callable object. the fuct must 1 argument as integer.
+ The argument means length of mask key.
+ This func must be return string(byte array),
+ which length is argument specified.
+ """
+ self.get_mask_key = func
+
+ def settimeout(self, timeout):
+ """
+ Set the timeout to the websocket.
+
+ timeout: timeout time(second).
+ """
+ self.sock.settimeout(timeout)
+
+ def gettimeout(self):
+ """
+ Get the websocket timeout(second).
+ """
+ return self.sock.gettimeout()
+
+ def connect(self, url, **options):
+ """
+ Connect to url. url is websocket url scheme. ie. ws://host:port/resource
+ You can customize using 'options'.
+ If you set "header" dict object, you can set your own custom header.
+
+ >>> ws = WebSocket()
+ >>> ws.connect("ws://echo.websocket.org/",
+ ... header={"User-Agent: MyProgram",
+ ... "x-custom: header"})
+
+ timeout: socket timeout time. This value is integer.
+ if you set None for this value,
+ it means "use default_timeout value"
+
+ options: current support option is only "header".
+ if you set header as dict value,
+ the custom HTTP headers are added.
+
+ """
+ hostname, port, resource, is_secure = _parse_url(url)
+ # TODO: we need to support proxy
+ self.sock.connect((hostname, port))
+ if is_secure:
+ self.io_sock = _SSLSocketWrapper(self.sock)
+ self._handshake(hostname, port, resource, **options)
+
+ def _handshake(self, host, port, resource, **options):
+ sock = self.io_sock
+ headers = []
+ headers.append("GET %s HTTP/1.1" % resource)
+ headers.append("Upgrade: websocket")
+ headers.append("Connection: Upgrade")
+ if port == 80:
+ hostport = host
+ else:
+ hostport = "%s:%d" % (host, port)
+ headers.append("Host: %s" % hostport)
+ headers.append("Origin: %s" % hostport)
+
+ key = _create_sec_websocket_key()
+ headers.append("Sec-WebSocket-Key: %s" % key)
+ headers.append("Sec-WebSocket-Version: %s" % VERSION)
+ if "header" in options:
+ headers.extend(options["header"])
+
+ headers.append("")
+ headers.append("")
+
+ header_str = "\r\n".join(headers)
+ sock.send(header_str)
+ if traceEnabled:
+ logger.debug( "--- request header ---")
+ logger.debug( header_str)
+ logger.debug("-----------------------")
+
+ status, resp_headers = self._read_headers()
+ if status != 101:
+ self.close()
+ raise WebSocketException("Handshake Status %d" % status)
+
+ success = self._validate_header(resp_headers, key)
+ if not success:
+ self.close()
+ raise WebSocketException("Invalid WebSocket Header")
+
+ self.connected = True
+
+ def _validate_header(self, headers, key):
+ for k, v in _HEADERS_TO_CHECK.iteritems():
+ r = headers.get(k, None)
+ if not r:
+ return False
+ r = r.lower()
+ if v != r:
+ return False
+
+ result = headers.get("sec-websocket-accept", None)
+ if not result:
+ return False
+ result = result.lower()
+
+ value = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+ hashed = base64.encodestring(hashlib.sha1(value).digest()).strip().lower()
+ return hashed == result
+
+ def _read_headers(self):
+ status = None
+ headers = {}
+ if traceEnabled:
+ logger.debug("--- response header ---")
+
+ while True:
+ line = self._recv_line()
+ if line == "\r\n":
+ break
+ line = line.strip()
+ if traceEnabled:
+ logger.debug(line)
+ if not status:
+ status_info = line.split(" ", 2)
+ status = int(status_info[1])
+ else:
+ kv = line.split(":", 1)
+ if len(kv) == 2:
+ key, value = kv
+ headers[key.lower()] = value.strip().lower()
+ else:
+ raise WebSocketException("Invalid header")
+
+ if traceEnabled:
+ logger.debug("-----------------------")
+
+ return status, headers
+
+ def send(self, payload, opcode = ABNF.OPCODE_TEXT):
+ """
+ Send the data as string.
+
+ payload: Payload must be utf-8 string or unicoce,
+ if the opcode is OPCODE_TEXT.
+ Otherwise, it must be string(byte array)
+
+ opcode: operation code to send. Please see OPCODE_XXX.
+ """
+ frame = ABNF.create_frame(payload, opcode)
+ if self.get_mask_key:
+ frame.get_mask_key = self.get_mask_key
+ data = frame.format()
+ self.io_sock.send(data)
+ if traceEnabled:
+ logger.debug("send: " + repr(data))
+
+ def ping(self, payload = ""):
+ """
+ send ping data.
+
+ payload: data payload to send server.
+ """
+ self.send(payload, ABNF.OPCODE_PING)
+
+ def pong(self, payload):
+ """
+ send pong data.
+
+ payload: data payload to send server.
+ """
+ self.send(payload, ABNF.OPCODE_PONG)
+
+ def recv(self):
+ """
+ Receive string data(byte array) from the server.
+
+ return value: string(byte array) value.
+ """
+ opcode, data = self.recv_data()
+ return data
+
+ def recv_data(self):
+ """
+ Recieve data with operation code.
+
+ return value: tuple of operation code and string(byte array) value.
+ """
+ while True:
+ frame = self.recv_frame()
+ if not frame:
+ # handle error:
+ # 'NoneType' object has no attribute 'opcode'
+ raise WebSocketException("Not a valid frame %s" % frame)
+ elif frame.opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY):
+ return (frame.opcode, frame.data)
+ elif frame.opcode == ABNF.OPCODE_CLOSE:
+ self.send_close()
+ return (frame.opcode, None)
+ elif frame.opcode == ABNF.OPCODE_PING:
+ self.pong("Hi!")
+
+
+ def recv_frame(self):
+ """
+ recieve data as frame from server.
+
+ return value: ABNF frame object.
+ """
+ header_bytes = self._recv(2)
+ if not header_bytes:
+ return None
+ b1 = ord(header_bytes[0])
+ fin = b1 >> 7 & 1
+ rsv1 = b1 >> 6 & 1
+ rsv2 = b1 >> 5 & 1
+ rsv3 = b1 >> 4 & 1
+ opcode = b1 & 0xf
+ b2 = ord(header_bytes[1])
+ mask = b2 >> 7 & 1
+ length = b2 & 0x7f
+
+ length_data = ""
+ if length == 0x7e:
+ length_data = self._recv(2)
+ length = struct.unpack("!H", length_data)[0]
+ elif length == 0x7f:
+ length_data = self._recv(8)
+ length = struct.unpack("!Q", length_data)[0]
+
+ mask_key = ""
+ if mask:
+ mask_key = self._recv(4)
+ data = self._recv_strict(length)
+ if traceEnabled:
+ recieved = header_bytes + length_data + mask_key + data
+ logger.debug("recv: " + repr(recieved))
+
+ if mask:
+ data = ABNF.mask(mask_key, data)
+
+ frame = ABNF(fin, rsv1, rsv2, rsv3, opcode, mask, data)
+ return frame
+
+ def send_close(self, status = STATUS_NORMAL, reason = ""):
+ """
+ send close data to the server.
+
+ status: status code to send. see STATUS_XXX.
+
+ reason: the reason to close. This must be string.
+ """
+ if status < 0 or status >= ABNF.LENGTH_16:
+ raise ValueError("code is invalid range")
+ self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE)
+
+
+
+ def close(self, status = STATUS_NORMAL, reason = ""):
+ """
+ Close Websocket object
+
+ status: status code to send. see STATUS_XXX.
+
+ reason: the reason to close. This must be string.
+ """
+ if self.connected:
+ if status < 0 or status >= ABNF.LENGTH_16:
+ raise ValueError("code is invalid range")
+
+ try:
+ self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE)
+ timeout = self.sock.gettimeout()
+ self.sock.settimeout(3)
+ try:
+ frame = self.recv_frame()
+ if logger.isEnabledFor(logging.DEBUG):
+ logger.error("close status: " + repr(frame.data))
+ except:
+ pass
+ self.sock.settimeout(timeout)
+ self.sock.shutdown(socket.SHUT_RDWR)
+ except:
+ pass
+ self._closeInternal()
+
+ def _closeInternal(self):
+ self.connected = False
+ self.sock.close()
+ self.io_sock = self.sock
+
+ def _recv(self, bufsize):
+ bytes = self.io_sock.recv(bufsize)
+ if bytes == 0:
+ raise WebSocketConnectionClosedException()
+ return bytes
+
+ def _recv_strict(self, bufsize):
+ remaining = bufsize
+ bytes = ""
+ while remaining:
+ bytes += self._recv(remaining)
+ remaining = bufsize - len(bytes)
+
+ return bytes
+
+ def _recv_line(self):
+ line = []
+ while True:
+ c = self._recv(1)
+ line.append(c)
+ if c == "\n":
+ break
+ return "".join(line)
+
+class WebSocketApp(object):
+ """
+ Higher level of APIs are provided.
+ The interface is like JavaScript WebSocket object.
+ """
+ def __init__(self, url,
+ on_open = None, on_message = None, on_error = None,
+ on_close = None, keep_running = True, get_mask_key = None):
+ """
+ url: websocket url.
+ on_open: callable object which is called at opening websocket.
+ this function has one argument. The arugment is this class object.
+ on_message: callbale object which is called when recieved data.
+ on_message has 2 arguments.
+ The 1st arugment is this class object.
+ The passing 2nd arugment is utf-8 string which we get from the server.
+ on_error: callable object which is called when we get error.
+ on_error has 2 arguments.
+ The 1st arugment is this class object.
+ The passing 2nd arugment is exception object.
+ on_close: callable object which is called when closed the connection.
+ this function has one argument. The arugment is this class object.
+ keep_running: a boolean flag indicating whether the app's main loop should
+ keep running, defaults to True
+ get_mask_key: a callable to produce new mask keys, see the WebSocket.set_mask_key's
+ docstring for more information
+ """
+ self.url = url
+ self.on_open = on_open
+ self.on_message = on_message
+ self.on_error = on_error
+ self.on_close = on_close
+ self.keep_running = keep_running
+ self.get_mask_key = get_mask_key
+ self.sock = None
+
+ def send(self, data):
+ """
+ send message. data must be utf-8 string or unicode.
+ """
+ if self.sock.send(data) == 0:
+ raise WebSocketConnectionClosedException()
+
+ def close(self):
+ """
+ close websocket connection.
+ """
+ self.keep_running = False
+ self.sock.close()
+
+ def run_forever(self):
+ """
+ run event loop for WebSocket framework.
+ This loop is infinite loop and is alive during websocket is available.
+ """
+ if self.sock:
+ raise WebSocketException("socket is already opened")
+ try:
+ self.sock = WebSocket(self.get_mask_key)
+ self.sock.connect(self.url)
+ self._run_with_no_err(self.on_open)
+ while self.keep_running:
+ data = self.sock.recv()
+ if data is None:
+ break
+ self._run_with_no_err(self.on_message, data)
+ except Exception, e:
+ self._run_with_no_err(self.on_error, e)
+ finally:
+ self.sock.close()
+ self._run_with_no_err(self.on_close)
+ self.sock = None
+
+ def _run_with_no_err(self, callback, *args):
+ if callback:
+ try:
+ callback(self, *args)
+ except Exception, e:
+ if logger.isEnabledFor(logging.DEBUG):
+ logger.error(e)
+
+
+if __name__ == "__main__":
+ enableTrace(True)
+ ws = create_connection("ws://echo.websocket.org/")
+ print "Sending 'Hello, World'..."
+ ws.send("Hello, World")
+ print "Sent"
+ print "Receiving..."
+ result = ws.recv()
+ print "Received '%s'" % result
+ ws.close()
diff --git a/chromium/tools/telemetry/unittest_data/bear.webm b/chromium/tools/telemetry/unittest_data/bear.webm
new file mode 100644
index 00000000000..a1b4150b32f
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/bear.webm
Binary files differ
diff --git a/chromium/tools/telemetry/unittest_data/blank.html b/chromium/tools/telemetry/unittest_data/blank.html
new file mode 100644
index 00000000000..8d0ce09a924
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/blank.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+</head>
+<body>
+Hello world
+</body>
+</html>
diff --git a/chromium/tools/telemetry/unittest_data/component_extension/background.js b/chromium/tools/telemetry/unittest_data/component_extension/background.js
new file mode 100644
index 00000000000..28b57606a0e
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/component_extension/background.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var _testVar;
+function setTestVar(x) {
+ _testVar = x;
+}
diff --git a/chromium/tools/telemetry/unittest_data/component_extension/manifest.json b/chromium/tools/telemetry/unittest_data/component_extension/manifest.json
new file mode 100644
index 00000000000..da1b970bfce
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/component_extension/manifest.json
@@ -0,0 +1,10 @@
+{
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDuUZGKCDbff6IRaxa4Pue7PPkxwPaNhGT3JEqppEsNWFjM80imEdqMbf3lrWqEfaHgaNku7nlpwPO1mu3/4Hr+XdNa5MhfnOnuPee4hyTLwOs3Vzz81wpbdzUxZSi2OmqMyI5oTaBYICfNHLwcuc65N5dbt6WKGeKgTpp4v7j7zwIDAQAB",
+ "description": "Simple test component extension which has just a background script",
+ "name": "Simple Telemetry Test Component Extension",
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "manifest_version": 2,
+ "version": "0.1"
+}
diff --git a/chromium/tools/telemetry/unittest_data/discoverable_classes/__init__.py b/chromium/tools/telemetry/unittest_data/discoverable_classes/__init__.py
new file mode 100644
index 00000000000..4e943c4b362
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/discoverable_classes/__init__.py
@@ -0,0 +1,3 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
diff --git a/chromium/tools/telemetry/unittest_data/discoverable_classes/discover_dummyclass.py b/chromium/tools/telemetry/unittest_data/discoverable_classes/discover_dummyclass.py
new file mode 100644
index 00000000000..afda1e54599
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/discoverable_classes/discover_dummyclass.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A dummy exception subclasses used by core/discover.py's unit tests."""
+
+class DummyException(Exception):
+ pass
diff --git a/chromium/tools/telemetry/unittest_data/discoverable_classes/dummy_profile_creator.py b/chromium/tools/telemetry/unittest_data/discoverable_classes/dummy_profile_creator.py
new file mode 100644
index 00000000000..867ded3e557
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/discoverable_classes/dummy_profile_creator.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.core import profile_creator
+
+class DummyProfileCreator(profile_creator.ProfileCreator):
+ def CreateProfile(self):
+ pass
diff --git a/chromium/tools/telemetry/unittest_data/dom_counter_sample.html b/chromium/tools/telemetry/unittest_data/dom_counter_sample.html
new file mode 100644
index 00000000000..483d1e0fcc2
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/dom_counter_sample.html
@@ -0,0 +1,12 @@
+<html>
+ <title>DOM counter unit test page</title>
+ <body>
+ <h1 onclick="">Webpage to be used for DOM counter unit testing.</h1>
+ <p onclick="">
+ This webpage is meant to be used by a unit test that checks DOM element
+ counters. The test expects there to be exactly 1 document, 14 nodes,
+ and 2 event listeners. Beware, modifying the HTML of this page may
+ change the element count, causing the unit test to fail!
+ </p>
+ </body>
+</html>
diff --git a/chromium/tools/telemetry/unittest_data/green_rect.html b/chromium/tools/telemetry/unittest_data/green_rect.html
new file mode 100644
index 00000000000..478c755d283
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/green_rect.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <style>
+ html, body {
+ margin: 0;
+ padding: 0;
+ }
+ #green {
+ width: 32px;
+ height: 32px;
+ background-color: rgb(0, 255, 0);
+ }
+ </style>
+</head>
+<body>
+ <div id="green"></div>
+</body>
+</html> \ No newline at end of file
diff --git a/chromium/tools/telemetry/unittest_data/image.png b/chromium/tools/telemetry/unittest_data/image.png
new file mode 100644
index 00000000000..82c2870df48
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/image.png
Binary files differ
diff --git a/chromium/tools/telemetry/unittest_data/image_decoding.html b/chromium/tools/telemetry/unittest_data/image_decoding.html
new file mode 100644
index 00000000000..59c1f0dfe27
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/image_decoding.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+</head>
+<body>
+ <img src="image.png">
+</body>
+</html>
diff --git a/chromium/tools/telemetry/unittest_data/non_scrollable_page.html b/chromium/tools/telemetry/unittest_data/non_scrollable_page.html
new file mode 100644
index 00000000000..57704087fef
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/non_scrollable_page.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html>
+ <head>
+ <style type="text/css">
+ </style>
+ </head>
+ <body>
+ Hello, world.
+ </body>
+</html>
diff --git a/chromium/tools/telemetry/unittest_data/page_that_logs_to_console.html b/chromium/tools/telemetry/unittest_data/page_that_logs_to_console.html
new file mode 100644
index 00000000000..373eebc60a8
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/page_that_logs_to_console.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+</head>
+<body>
+<script>
+ window.__logCount = 0;
+ setInterval(function() {
+ console.log("Hello, world")
+ window.__logCount += 1
+ }, 100);
+</script>
+</body>
+</html>
diff --git a/chromium/tools/telemetry/unittest_data/page_with_link.html b/chromium/tools/telemetry/unittest_data/page_with_link.html
new file mode 100644
index 00000000000..dc3c008b3eb
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/page_with_link.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+</head>
+<body>
+<a id="clickme" href="blank.html">Click me</a>
+</body>
+</html>
diff --git a/chromium/tools/telemetry/unittest_data/scrollable_page.html b/chromium/tools/telemetry/unittest_data/scrollable_page.html
new file mode 100644
index 00000000000..c5102cea994
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/scrollable_page.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<html>
+ <head>
+ <style type="text/css">
+ body { height: 1500px; }
+ </style>
+ </head>
+ <body></body>
+</html>
diff --git a/chromium/tools/telemetry/unittest_data/simple_extension/background.js b/chromium/tools/telemetry/unittest_data/simple_extension/background.js
new file mode 100644
index 00000000000..28b57606a0e
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/simple_extension/background.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var _testVar;
+function setTestVar(x) {
+ _testVar = x;
+}
diff --git a/chromium/tools/telemetry/unittest_data/simple_extension/manifest.json b/chromium/tools/telemetry/unittest_data/simple_extension/manifest.json
new file mode 100644
index 00000000000..d4bb6a3dc44
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/simple_extension/manifest.json
@@ -0,0 +1,9 @@
+{
+ "description": "Simple test extension which has just a background script",
+ "name": "Simple Telemetry Test Extension",
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "manifest_version": 2,
+ "version": "0.1"
+}
diff --git a/chromium/tools/telemetry/unittest_data/video_test.html b/chromium/tools/telemetry/unittest_data/video_test.html
new file mode 100644
index 00000000000..ce8529cc930
--- /dev/null
+++ b/chromium/tools/telemetry/unittest_data/video_test.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <video id="video_1" src="bear.webm" controls></video>
+ <audio id="audio_1" src="bear.webm" controls></audio>
+ </body>
+</html>
diff --git a/chromium/tools/telemetry/update_docs b/chromium/tools/telemetry/update_docs
new file mode 100755
index 00000000000..f2f92ac6068
--- /dev/null
+++ b/chromium/tools/telemetry/update_docs
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import sys
+
+from build import update_docs
+
+if __name__ == '__main__':
+ sys.exit(update_docs.Main(sys.argv[1:]))
diff --git a/chromium/tools/telemetry_tools/__init__.py b/chromium/tools/telemetry_tools/__init__.py
new file mode 100644
index 00000000000..d6646bc8cd7
--- /dev/null
+++ b/chromium/tools/telemetry_tools/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""A library for bootstrapping Telemetry preformance testing.""" \ No newline at end of file
diff --git a/chromium/tools/telemetry_tools/bootstrap_deps b/chromium/tools/telemetry_tools/bootstrap_deps
new file mode 100644
index 00000000000..30527ea4b31
--- /dev/null
+++ b/chromium/tools/telemetry_tools/bootstrap_deps
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file specifies dependencies required to bootstrap Telemetry. It is in a
+# minimal version of the format used by other DEPS files that gclient can read,
+# but it should only be used to bootstrap Telemetry *outside* of a normal
+# Chrome checkout.
+
+deps = {
+ "src/tools/telemetry":
+ "https://src.chromium.org/chrome/trunk/src/tools/telemetry",
+ "src/third_party/webpagereplay":
+ "https://web-page-replay.googlecode.com/svn/trunk",
+ "src/chrome/test/functional/webpagereplay.py":
+ "https://src.chromium.org/chrome/trunk/src/chrome/test/functional/webpagereplay.py",
+ "src/build/android":
+ "https://src.chromium.org/chrome/trunk/src/build/android",
+ "src/third_party/android_testrunner":
+ "https://src.chromium.org/chrome/trunk/src/third_party/android_testrunner",
+ "src/tools/crx_id":
+ "https://src.chromium.org/chrome/trunk/src/tools/crx_id",
+ "src/chrome/test/data/extensions/profiles":
+ "https://src.chromium.org/chrome/trunk/src/chrome/test/data/extensions/profiles",
+ "src/build/util":
+ "https://src.chromium.org/chrome/trunk/src/build/util",
+ "src/third_party/flot/jquery.flot.min.js":
+ "https://src.chromium.org/chrome/trunk/src/third_party/flot/jquery.flot.min.js",
+ "src/third_party/WebKit/PerformanceTests/resources/jquery.tablesorter.min.js":
+ "https://src.chromium.org/blink/trunk/PerformanceTests/resources/jquery.tablesorter.min.js",
+ "src/third_party/WebKit/PerformanceTests/resources/statistics.js":
+ "https://src.chromium.org/blink/trunk/PerformanceTests/resources/statistics.js",
+ "src/tools/perf/unit-info.json":
+ "https://src.chromium.org/chrome/trunk/src/tools/perf/unit-info.json"
+ }
diff --git a/chromium/tools/telemetry_tools/telemetry_bootstrap.py b/chromium/tools/telemetry_tools/telemetry_bootstrap.py
new file mode 100644
index 00000000000..67740c8695b
--- /dev/null
+++ b/chromium/tools/telemetry_tools/telemetry_bootstrap.py
@@ -0,0 +1,162 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Bootstrap Chrome Telemetry by downloading all its files from SVN servers.
+
+Requires a DEPS file to specify which directories on which SVN servers
+are required to run Telemetry. Format of that DEPS file is a subset of the
+normal DEPS file format[1]; currently only only the "deps" dictionary is
+supported and nothing else.
+
+Fetches all files in the specified directories using WebDAV (SVN is WebDAV under
+the hood).
+
+[1] http://dev.chromium.org/developers/how-tos/depottools#TOC-DEPS-file
+"""
+
+import imp
+import logging
+import os
+import urllib
+import urlparse
+
+# Link to file containing the 'davclient' WebDAV client library.
+_DAVCLIENT_URL = ('https://src.chromium.org/viewvc/chrome/trunk/src/tools/' +
+ 'telemetry/third_party/davclient/davclient.py')
+
+# Dummy module for Davclient.
+_davclient = None
+
+def _download_and_import_davclient_module():
+ """Dynamically import davclient helper library."""
+ global _davclient
+ davclient_src = urllib.urlopen(_DAVCLIENT_URL).read()
+ _davclient = imp.new_module('davclient')
+ exec davclient_src in _davclient.__dict__
+
+
+class DAVClientWrapper():
+ """Knows how to retrieve subdirectories and files from WebDAV/SVN servers."""
+
+ def __init__(self, root_url):
+ """Initialize SVN server root_url, save files to local dest_dir.
+
+ Args:
+ root_url: string url of SVN/WebDAV server
+ """
+ self.root_url = root_url
+ self.client = _davclient.DAVClient(root_url)
+
+ @staticmethod
+ def __norm_path_keys(dict_with_path_keys):
+ """Returns a dictionary with os.path.normpath called on every key."""
+ return dict((os.path.normpath(k), v) for (k, v) in
+ dict_with_path_keys.items())
+
+ def GetDirList(self, path):
+ """Returns string names of all files and subdirs of path on the server."""
+ props = self.__norm_path_keys(self.client.propfind(path, depth=1))
+ # remove this path
+ del props[os.path.normpath(path)]
+ return [os.path.basename(p) for p in props.keys()]
+
+ def IsFile(self, path):
+ """Returns True if the path is a file on the server, False if directory."""
+ props = self.__norm_path_keys(self.client.propfind(path, depth=1))
+ return props[os.path.normpath(path)]['resourcetype'] is None
+
+ def Traverse(self, src_path, dst_path):
+ """Walks the directory hierarchy pointed to by src_path download all files.
+
+ Recursively walks src_path and saves all files and subfolders into
+ dst_path.
+
+ Args:
+ src_path: string path on SVN server to save (absolute path on server).
+ dest_path: string local path (relative or absolute) to save to.
+ """
+ if self.IsFile(src_path):
+ if not os.path.exists(os.path.dirname(dst_path)):
+ logging.info("creating %s", os.path.dirname(dst_path))
+ os.makedirs(os.path.dirname(dst_path))
+ logging.info("Saving %s to %s", self.root_url + src_path, dst_path)
+ urllib.urlretrieve(self.root_url + src_path, dst_path)
+ return
+ else:
+ for subdir in self.GetDirList(src_path):
+ self.Traverse(os.path.join(src_path, subdir),
+ os.path.join(dst_path, subdir))
+
+
+def ListAllDepsPaths(deps_content):
+ """Recursively returns a list of all paths indicated in this deps file.
+
+ Note that this discards information about where path dependencies come from,
+ so this is only useful in the context of a Chromium source checkout that has
+ already fetched all dependencies.
+
+ Args:
+ deps_content: String containing deps information to be evaluated, in the
+ format given in the header of this file.
+ Returns: A list of string paths starting under src that are required by the
+ given deps file, and all of its sub-dependencies. This amounts to
+ the keys of the 'deps' dictionary.
+ """
+ chrome_root = os.path.dirname(__file__)
+ while os.path.basename(chrome_root) != 'src':
+ chrome_root = os.path.abspath(os.path.join(chrome_root, '..'))
+ deps = imp.new_module('deps')
+ exec deps_content in deps.__dict__
+
+ deps_paths = deps.deps.keys()
+
+ if hasattr(deps, 'deps_includes'):
+ for path in deps.deps_includes.keys():
+ # Need to localize the paths.
+ path = os.path.join(chrome_root, '..', path)
+ deps_paths = deps_paths + ListAllDepsPaths(open(path).read())
+
+ return deps_paths
+
+
+def DownloadDepsURL(destination_dir, url):
+ """Wrapper around DownloadDeps that takes a string URL to the deps file.
+
+ Args:
+ destination_dir: String path to local directory to download files into.
+ url: URL of deps file (see DownloadDeps for format).
+ """
+ logging.warning('Downloading deps from %s...', url)
+ DownloadDeps(destination_dir, urllib.urlopen(url).read())
+
+
+def DownloadDeps(destination_dir, deps_content):
+ """Saves all the dependencies in deps_path.
+
+ Reads deps_content, assuming the contents are in the simple DEPS-like file
+ format specified in the header of this file, then download all
+ files/directories listed to the destination_dir.
+
+ Args:
+ destination_dir: String path to directory to download files into.
+ deps_content: String containing deps information to be evaluated.
+ """
+ # TODO(wiltzius): Add a parameter for which revision to pull.
+ _download_and_import_davclient_module()
+
+ deps = imp.new_module('deps')
+ exec deps_content in deps.__dict__
+
+ for dst_path, src_path in deps.deps.iteritems():
+ full_dst_path = os.path.join(destination_dir, dst_path)
+ parsed_url = urlparse.urlparse(src_path)
+ root_url = parsed_url.scheme + '://' + parsed_url.netloc
+
+ dav_client = DAVClientWrapper(root_url)
+ dav_client.Traverse(parsed_url.path, full_dst_path)
+
+ if hasattr(deps, 'deps_includes'):
+ for url in deps.deps_includes.values():
+ DownloadDepsURL(destination_dir, url)
+
diff --git a/chromium/tools/trace/trace.html b/chromium/tools/trace/trace.html
new file mode 100644
index 00000000000..e14bbaef686
--- /dev/null
+++ b/chromium/tools/trace/trace.html
@@ -0,0 +1,287 @@
+<html>
+<head>
+<title>
+Trace Events
+</title>
+<style>
+body {
+ font-family: "Courier New";
+ font-size: 9pt;
+}
+
+#header {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ border-bottom: 1px dashed black;
+ background-color: #F0F0F0;
+ z-index: 3;
+}
+
+#outer {
+ position: relative;
+ height: 200px;
+}
+
+#time_scale {
+ height: 15px;
+ width: 100%;
+}
+
+#tooltip {
+ position: absolute;
+ background-color: #FFFFCC;
+ display: none;
+ font-family: "Courier New";
+ font-size: 9pt;
+ padding: 5px;
+ border: 1px solid #CCCC88;
+ z-index: 3;
+}
+
+#legend {
+ position: fixed;
+ left: 10px;
+ bottom: 10px;
+ padding: 5px;
+ border: 1px solid silver;
+ z-index: 10;
+ background-color: #f0f0f0;
+}
+
+h2 {
+ margin: 5px;
+}
+
+#instructions {
+ position: absolute;
+ top:
+ float: right;
+ display: none;
+}
+
+li.time_tick {
+ background-color: #FFFFCC;
+ height: 15px;
+}
+
+li {
+ background: pink;
+ position: absolute;
+ height: 10px;
+ list-style: none;
+ margin: 0px;
+ padding: 0px;
+ z-index: 2;
+}
+
+li:hover {
+ border: 1px solid red;
+}
+
+.url {
+ background-color: green;
+}
+
+.http {
+ background-color: blue;
+}
+
+.socket {
+ background-color: black;
+}
+
+.v8 {
+ background-color: orange;
+}
+
+</style>
+
+<script src='trace_data.js'></script>
+<script>
+var scale = 100000;
+var row_height = 15;
+var trace_initial_time = 0;
+var trace_threads = {};
+var heartbeats = [];
+var trace_total_time = 0;
+
+function process_raw_events() {
+ trace_initial_time = raw_trace_events[0].usec_begin;
+ var stack = [];
+ var e;
+ for (var i in raw_trace_events) {
+ e = raw_trace_events[i];
+ var trace_events = trace_threads["e.tid"];
+ if (!trace_events) {
+ trace_events = [];
+ trace_threads["e.tid"] = trace_events;
+ }
+ if (e.name.indexOf("heartbeat.") == 0) {
+ heartbeats.push(e);
+ } else if (e.type == "BEGIN") {
+ trace_events.push(e);
+ stack.unshift(e);
+ } else if (e.type == "END") {
+ for (var s in stack) {
+ var begin = stack[s];
+ if ((begin.id == e.id) && (begin.name == e.name) &&
+ (begin.pid == e.pid) && (begin.tid == e.tid)) {
+ begin.usec_end = e.usec_begin;
+ begin.duration = begin.usec_end - begin.usec_begin;
+ stack.splice(s, 1);
+ break;
+ }
+ }
+ } else if (e.type == "INSTANT") {
+ trace_events.push(e);
+ e.duration = 0;
+ }
+ }
+ if (e.usec_end)
+ trace_total_time = e.usec_end - trace_initial_time;
+ else
+ trace_total_time = e.usec_begin - trace_initial_time;
+}
+
+function compute_scale() {
+ var outer = document.getElementById("outer");
+ scale = Math.floor(trace_total_time / (outer.offsetWidth - (row_height * 2)));
+};
+
+function show_details(tid, i, event) {
+ var trace_events = trace_threads["e.tid"];
+ var inner = trace_events[i].name + " " +
+ trace_events[i].duration / 1000 + "ms<br />" +
+ trace_events[i].id + "<br />" +
+ trace_events[i].extra + "<br />";
+ var tooltip = document.getElementById("tooltip");
+ tooltip.innerHTML = inner;
+ if (window.event)
+ event = window.event;
+ tooltip.style.top = event.pageY + 3;
+ tooltip.style.left = event.pageX + 3;
+ tooltip.style.display = "block";
+};
+
+function generate_time_scale() {
+ var view_size = window.clientWidth;
+ var body_size = document.body.scrollWidth;
+ var inner = "";
+
+ var step_ms = Math.floor(scale / 10); // ms per 100px
+ var pow10 = Math.pow(10, Math.floor(Math.log(step_ms) / Math.log(10)));
+ var round = .5 * pow10;
+ step_ms = round * (Math.floor(step_ms / round)); // round to a multiple of round
+ for (var i = step_ms; i < trace_total_time / 1000; i += step_ms) {
+ var x = Math.floor(i * 1000 / scale);
+ inner += "<li class='time_tick' style='left: " + x + "px'>" + i + "</li>";
+ }
+ var time_scale = document.getElementById("time_scale");
+ time_scale.innerHTML = inner;
+ time_scale.style.width = document.body.scrollWidth;
+}
+
+function generate_subchart(trace_events, top) {
+ var inner = "";
+ var last_max_time = 0;
+ var last_max_x = 0;
+ for (var i in trace_events) {
+ var e = trace_events[i];
+ var start_time = e.usec_begin - trace_initial_time;
+ var left = row_height + Math.floor(start_time / scale);
+ var width = Math.floor(e.duration / scale);
+ if (width == 0)
+ width = 1;
+ if (start_time < last_max_time)
+ top += row_height;
+ var style = "top: " + top + "px; left: " + left + "px; width: " + width + "px;";
+ var js = 'javascript:show_details("' + e.tid + '", ' + i + ', event);';
+ var cls = e.name.split('.')[0];
+ inner += "<li class='" + cls + "' onmouseover='" + js + "' id='li-" + i + "' style='" + style + "'></li>\n";
+ last_max_time = start_time + e.duration;
+ last_max_x = left + width;
+ }
+ var subchart = document.createElement('div');
+ subchart.setAttribute("class", "subchart");
+ subchart.setAttribute("id", trace_events[0].tid);
+ subchart.innerHTML = inner;
+ subchart.style.height = top + row_height;
+ subchart.style.width = row_height + last_max_x;
+ var chart = document.getElementById("chart");
+ chart.appendChild(subchart);
+
+ return top;
+};
+
+function generate_chart() {
+ var chart = document.getElementById("chart");
+ chart.innerHTML = "";
+ var top = 60;
+ for (var t in trace_threads) {
+ top = generate_subchart(trace_threads[t], top);
+ }
+ generate_time_scale();
+}
+
+function change_scale(event) {
+ if (!event)
+ event = window.event;
+ if (!event.shiftKey)
+ return;
+ var delta = 0;
+ if (event.wheelDelta) {
+ delta = event.wheelDelta / 120;
+ } else if (event.detail) {
+ delta = - event.detail / 3;
+ }
+ if (delta) {
+ var tooltip = document.getElementById("tooltip");
+ tooltip.style.display = "none";
+ var factor = 1.1;
+ if (delta < 0)
+ scale = Math.floor(scale * factor);
+ else
+ scale = Math.floor(scale / factor);
+ if (scale > 300000)
+ scale = 300000;
+ generate_chart();
+ if (event.preventDefault)
+ event.preventDefault();
+ }
+ event.returnValue = false;
+};
+
+function initial_load() {
+ if (window.addEventListener)
+ window.addEventListener('DOMMouseScroll', change_scale, false);
+ window.onmousewheel = document.onmousewheel = change_scale;
+
+ process_raw_events();
+ compute_scale();
+ generate_chart();
+};
+
+</script>
+</head>
+<body onload='initial_load();'>
+<div id="header">
+<h2>Trace Events</h2>
+<div id="instructions">
+Use shift+mouse-wheel to zoom in and out.
+</div>
+<div id="time_scale"></div>
+</div>
+<div id="legend">
+<span class="url">&nbsp;</span> URL<br />
+<span class="http">&nbsp;</span> HTTP<br />
+<span class="socket">&nbsp;</span> Socket<br />
+<span class="v8">&nbsp;</span> V8<br />
+</div>
+<div id="chart">
+<div id="outer">
+</div>
+</div>
+<div id="tooltip" ondblclick="this.style.display = 'none';"></div>
+</body>
+</html>
diff --git a/chromium/tools/trace/trace_data.js b/chromium/tools/trace/trace_data.js
new file mode 100644
index 00000000000..2531d3ce065
--- /dev/null
+++ b/chromium/tools/trace/trace_data.js
@@ -0,0 +1,1050 @@
+var raw_trace_events = [
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x16e8260', 'extra':'http://mail.google.com', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_shell.cc', 'line_number':'825', 'usec_begin': 246537},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1', 'extra':'http://mail.google.com/', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 250373},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 300584},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 301820},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 301844},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 302652},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'frame.load', 'id':'0x16e8488', 'extra':'http://mail.google.com/', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'310', 'usec_begin': 302786},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x1', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 302866},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x2', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 303348},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 304497},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 304548},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 304569},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 304627},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 304640},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 306405},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 306425},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 306443},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 308431},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 308477},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 308560},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 308606},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'439 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 308637},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 308651},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 308663},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 308675},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'1279 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 367678},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x17b8e60', 'extra':'http://mail.google.com/mail/', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 368149},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 368763},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x2', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 368799},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 368991},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 369014},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 369028},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 369063},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 369130},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 370934},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 370964},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 370996},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 372273},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 373127},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'70 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 373160},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 373185},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'1718 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 379657},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 387342},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'186 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 387405},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 387424},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'47 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 391679},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 423698},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 433561},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 433582},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 433661},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'628 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 433705},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 433719},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 433732},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 433748},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'1425 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 466568},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 467724},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 467913},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 467931},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 470106},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 470143},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'4233 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'169', 'usec_begin': 470177},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 470231},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x3', 'extra':'https://mail.google.com/mail?view=page&name=browser&ver=1k96igf4806cy', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 473833},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 474818},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 474867},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 477174},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 477224},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 477615},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x1828c00', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 477662},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 480476},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 480728},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 480744},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 488153},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 488720},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 489077},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 489092},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 489249},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 489309},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 489346},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 489360},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 489384},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 489544},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 489664},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 489678},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x4', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 490180},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 490442},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x3', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 490470},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 490597},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 490622},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 490636},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 490674},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 490688},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x2', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 490772},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 492500},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 492527},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 492546},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 513216},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 513450},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x17c4d58', 'extra':'70 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 513480},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 513509},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'1171 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 543672},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 545326},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x17c4d58', 'extra':'314 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 545366},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 545386},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'47 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 579036},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 579232},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 579251},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 579307},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x17c4d58', 'extra':'611 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 579341},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 579354},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 579367},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 579394},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'1425 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 604199},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 604781},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 605139},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 605157},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 605470},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 605487},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'1234 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'169', 'usec_begin': 605508},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x17b8e60', 'extra':'https://ssl.google-analytics.com/siteopt.js?v=1&utmxkey=1206330561&utmx=&utmxx=&utmxtime=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 605550},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 605881},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 606445},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 606461},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 608174},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 612014},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 612070},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 612084},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 612669},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x5', 'extra':'https://mail.google.com/mail/help/images/logo.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 613155},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x6', 'extra':'https://mail.google.com/mail/images/corner_tl.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 614484},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 614782},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 614828},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 614842},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 614872},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x7', 'extra':'https://mail.google.com/mail/images/corner_tr.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 615312},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x8', 'extra':'https://mail.google.com/mail/images/corner_bl.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 615792},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x9', 'extra':'https://mail.google.com/mail/images/corner_br.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 616264},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 616610},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 616653},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 616667},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 616688},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0xa', 'extra':'https://mail.google.com/mail/help/images/icons/spam_new.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 617692},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0xb', 'extra':'https://mail.google.com/mail/help/images/icons/cell.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 618471},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0xc', 'extra':'https://mail.google.com/mail/help/images/icons/storage.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 619165},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 619695},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 619744},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 619758},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 619784},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 619894},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 619930},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 619944},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 619962},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 620183},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 620277},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 620292},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 620313},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0xd', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 625447},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 626010},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 626071},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 626085},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 626104},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x1844b80', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 626259},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x1844b80', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 626283},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x1844b80', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 626296},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x1844b80', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 626420},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x1844b80', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 626436},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 626507},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x1808ae8', 'extra':'668 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 626554},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x1844b80', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 626569},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x1844b80', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 626581},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 626604},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 631563},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 631620},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 631634},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0xe', 'extra':'https://mail.google.com/mail/help/images/button_1_1.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 632318},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0xf', 'extra':'https://www.google.com/mail/help/images/clear.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 632749},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x10', 'extra':'https://mail.google.com/mail/help/images/button_1_2.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 633222},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x11', 'extra':'https://mail.google.com/mail/help/images/button_1_3.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 633704},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x12', 'extra':'https://mail.google.com/mail/help/images/button_2_1.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 634280},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x13', 'extra':'https://mail.google.com/mail/help/images/button_2_2.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 634918},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x14', 'extra':'https://mail.google.com/mail/help/images/button_2_3.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 635476},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x15', 'extra':'https://mail.google.com/mail/help/images/button_3_1.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 635969},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x16', 'extra':'https://mail.google.com/mail/help/images/button_3_2.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 636515},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x17', 'extra':'https://mail.google.com/mail/help/images/button_3_3.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 636987},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 637536},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 637742},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 637796},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 637812},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 637838},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 637905},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 637940},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 637954},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 640514},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x18', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 642073},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x4', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 642324},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x17c35e8', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 643004},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x17c35e8', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 643029},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x17c35e8', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 643042},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x17c35e8', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 643078},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x17c35e8', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 643092},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 643146},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x17c4d58', 'extra':'601 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 643196},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x17c35e8', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 643215},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x17c35e8', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 643228},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 643248},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x1808ae8', 'extra':'406 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 664360},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x1844b80', 'extra':'https://www.google.com/accounts/google_transparent.gif', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 664656},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x1808ae8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 665032},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x17c4d58', 'extra':'390 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 667425},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x17c35e8', 'extra':'https://ssl.google-analytics.com/urchin.js', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 667652},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x17c4d58', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 668023},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'25', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 674638},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x5', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 685812},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x6', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 692814},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x7', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 693201},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x8', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 698519},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x9', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 698776},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0xa', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 703813},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0xb', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 704060},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0xc', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 704264},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0xe', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 704483},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0xf', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 704744},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x10', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 705404},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x11', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 705684},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x12', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 705929},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x13', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 706155},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x14', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 706620},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x15', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 706805},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x16', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 707344},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x17', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 707631},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0xd', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 707885},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 708860},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 710721},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 710737},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 711495},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 711663},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 711730},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 711744},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 724816},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 724869},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 724883},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 724905},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x19', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 725598},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 726084},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 726112},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 726128},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 726168},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 726185},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 726504},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 726523},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 726544},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1a', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 728532},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 728968},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 728992},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 729008},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 729096},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 729113},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 729407},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 729426},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 729446},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 730189},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x18', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 730637},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 746070},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 746305},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x265a568', 'extra':'70 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 746339},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 746360},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 749792},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 750021},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x265aeb0', 'extra':'70 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 750051},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 750073},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x265a568', 'extra':'1171 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 771135},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 772294},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x265a568', 'extra':'314 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 772351},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 772369},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x265aeb0', 'extra':'1171 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 775944},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 776955},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x265aeb0', 'extra':'314 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 776990},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 777007},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x265a568', 'extra':'47 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 804626},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 804813},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 804835},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 804905},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x265a568', 'extra':'1003 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 804939},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 804952},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 804968},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 804989},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x265aeb0', 'extra':'47 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 823698},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 823868},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 823902},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 823964},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x265aeb0', 'extra':'993 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 823993},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 824006},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 824022},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 824039},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x265a568', 'extra':'554 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 826462},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 827124},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 827368},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x184aed0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1300046089&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmcn=1&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/mail/gaia/homepage&utmac=UA-992684-1&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 827398},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x19', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 827721},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x265aeb0', 'extra':'551 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 847745},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 848279},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 848496},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'https://ssl.google-analytics.com/__utm.gif?utmwv=1.3&utmn=1449512545&utmcs=UTF-8&utmsr=1920x1200&utmsc=32-bit&utmul=en-us&utmje=1&utmfl=9.0%20%20r115&utmdt=%0A%20%20Gmail%3A%20Email%20from%20Google%0A&utmhn=www.google.com&utmhid=1875579123&utmr=-&utmp=/1206330561/test&utmac=UA-1923148-3&utmcc=__utma%3D173272373.1300046089.1221584154.1221584154.1221584154.1%3B%2B__utmx%3D173272373.%3B%2B__utmz%3D173272373.1221584154.1.1.utmccn%3D(direct)%7Cutmcsr%3D(direct)%7Cutmcmd%3D(none)%3B%2B', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 848542},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1b', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 850184},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 850670},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 850693},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 850706},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 850740},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 850759},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 851028},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 851047},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 851062},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x1a', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 851484},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 853022},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 853209},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26d7910', 'extra':'70 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 853244},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 853286},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26d7910', 'extra':'1719 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 855598},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 856827},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26d7910', 'extra':'186 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 856864},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 856882},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26d7910', 'extra':'47 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 861150},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 861377},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 861394},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 861449},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26d7910', 'extra':'582 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 861482},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 861495},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 861515},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 861534},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26d7910', 'extra':'565 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 892717},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 893171},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 893394},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail/images/c.gif?t=1221584153332', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 893421},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'frame.load', 'id':'0x16e8488', 'extra':'https://www.google.com/accounts/ServiceLogin?service=mail&passive=true&rm=false&continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3Fui%3Dhtml%26zy%3Dl&bsv=1k96igf4806cy&ltmpl=default&ltmplcache=2', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'310', 'usec_begin': 893699},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x1b', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 893847},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'12', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 923735},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 1173749},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 1423773},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 1673792},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'3', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 1924790},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 2174817},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 2424843},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1c', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 2657744},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 2658189},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 2658239},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 2658254},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 2658292},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 2658306},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 2658367},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26d7910', 'extra':'597 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 2658414},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 2658428},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 2658440},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 2658455},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 2674849},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26d7910', 'extra':'498 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 2712401},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 2712952},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'https://mail.google.com/mail?gxlu=erikkay&zx=1221584155500', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 2713157},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 2713174},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 2924878},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 3175861},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 3425898},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 3675905},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 3925923},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 4175951},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 4425962},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 4675987},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 4926016},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 5034304},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1d', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5034619},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 5035008},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 5035035},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 5035049},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 5035082},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 5035096},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 5035375},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 5035392},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 5035409},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 5036730},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5036969},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26d7910', 'extra':'70 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5037014},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5037064},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26d7910', 'extra':'1718 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5039568},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5040730},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26d7910', 'extra':'186 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5040764},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5040782},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26d7910', 'extra':'47 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5044663},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 5044830},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 5044855},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5044964},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26d7910', 'extra':'1067 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5044992},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 5045007},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_body', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'306', 'usec_begin': 5045020},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5045043},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26d7910', 'extra':'219 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5045061},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_body', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'311', 'usec_begin': 5045074},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 5045087},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5045100},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26d7910', 'extra':'1425 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5136971},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 5137031},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 5137045},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5137059},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26d7910', 'extra':'547 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'169', 'usec_begin': 5137078},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'https://www.google.com/accounts/ServiceLoginAuth?service=mail', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 5137821},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x26d7910', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 5138262},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1d', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5138291},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 5138722},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 5138744},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 5138757},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 5138779},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 5138793},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 5139038},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 5139055},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 5139075},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 5140266},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5140480},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26c29a8', 'extra':'70 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5140522},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5140563},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26c29a8', 'extra':'1718 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5142351},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5143531},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26c29a8', 'extra':'186 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5143565},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5143582},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26c29a8', 'extra':'47 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5147388},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 5147552},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 5147586},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5147647},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26c29a8', 'extra':'1572 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5147681},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 5147695},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 5147709},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5147723},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 5176025},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26c29a8', 'extra':'1425 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5179942},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 5180371},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 5180747},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 5180766},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 5180999},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5181037},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26c29a8', 'extra':'114 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'169', 'usec_begin': 5181057},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x184aed0', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 5181094},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5184752},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5184865},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5184880},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5185121},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'frame.load', 'id':'0x16e8488', 'extra':'https://www.google.com/accounts/CheckCookie?continue=http%3A%2F%2Fmail.google.com%2Fmail%2F%3F&service=mail&ltmpl=default&chtml=LoginDoneHtml', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'310', 'usec_begin': 5185249},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x1d', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 5185368},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1e', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5186094},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 5186490},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 5186836},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 5186855},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 5186955},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 5186972},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 5187271},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 5187289},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x26c1c50', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 5187304},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x26c1c50', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 5188602},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 5188632},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 5188663},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x26c1c50', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5188736},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x26c1c50', 'extra':'935 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5188786},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 5188799},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 5188813},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x26c1c50', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5188831},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 5426048},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x26c1c50', 'extra':'1403 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5448207},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x184aed0', 'extra':'http://mail.google.com/mail/?auth=DQAAAIcAAADbe-apndwa7Xx20a4Fl-4priInNZo_bihPly3fHKKz17I0Sgr02B1EXCHhvGL6Ifi3JHFN9Z08Jsq7_3ZNuqdau5F6rcqTxLAHgQuLykwgkwch36z_ge541j7ef1hfCkal7F4ThC42jFkBiXD5Ia9K09lkrSl7uQlDfcnH-Qzz18TuHBIlaTTo60x3wF13E4w&gausr=erikkay%40gmail.com', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 5448754},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x26c1c50', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 5449221},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1e', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5449247},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 5449521},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 5449543},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 5449565},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 5449588},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 5449601},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 5449875},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 5449891},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 5449919},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 5451177},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 5451207},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 5451226},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 5451267},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x183c9d0', 'extra':'1076 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 5451306},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 5451326},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 5451344},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5451377},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'4096 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5659772},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 5660050},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 5660264},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 5660286},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 5660572},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5660590},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'194 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'169', 'usec_begin': 5660609},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 5660621},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5663002},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5663067},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5663082},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5663444},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x1f', 'extra':'http://mail.google.com/mail/?view=page&name=browser&ver=1k96igf4806cy', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5663617},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 5664187},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5664204},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'1243 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'169', 'usec_begin': 5664228},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 5664242},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 5664497},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 5664513},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5664666},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5664846},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5664861},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5666301},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5666531},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5666638},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5666653},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5669200},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5672512},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5673323},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5673340},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5673454},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x20', 'extra':'http://mail.google.com/mail/?ui=2&view=js&name=js&ver=vuagRBgWwto&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5674043},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x21', 'extra':'http://mail.google.com/mail/?ui=2&view=bsp&ver=1qygpcgurkovy', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5674722},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x22', 'extra':'http://mail.google.com/mail/?ui=2&view=bsp&ver=1qygpcgurkovy', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5675392},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x23', 'extra':'http://mail.google.com/mail/?ui=2&view=bsp&ver=1qygpcgurkovy', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5676060},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x1f', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 5676230},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'3', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 5676274},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5678859},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5679537},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5679553},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5679962},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5681218},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5682436},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5682452},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5685626},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5686710},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5687420},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5687436},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5687815},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5690191},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5691313},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5691330},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5692120},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5693609},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5694734},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5694750},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5695974},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5697446},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5698579},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5698595},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5704025},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'frame.load', 'id':'0x16e8488', 'extra':'http://mail.google.com/mail/?ui=2&view=bsp&ver=1qygpcgurkovy', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'310', 'usec_begin': 5704226},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x21', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 5704446},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5707224},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5708662},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5708678},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5710175},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5711076},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5711922},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5711939},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5712496},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'frame.load', 'id':'0x16e8488', 'extra':'http://mail.google.com/mail/?ui=2&view=bsp&ver=1qygpcgurkovy', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'310', 'usec_begin': 5713037},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x22', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 5713115},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5714839},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5715817},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5715834},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5716464},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5717330},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5718018},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5718057},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5719545},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5720612},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5721545},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5721568},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x24', 'extra':'http://mail.google.com/mail/?ui=2&view=ss&ver=gh1z9bhrf433&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 5725484},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5725885},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'frame.load', 'id':'0x16e8488', 'extra':'http://mail.google.com/mail/?ui=2&view=bsp&ver=1qygpcgurkovy', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'310', 'usec_begin': 5726725},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x23', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 5726810},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5728493},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5729806},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5729822},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5730693},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5731723},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5732590},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5732605},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5733440},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5734576},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5735554},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5735570},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5736975},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5739862},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5741391},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5741412},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5742147},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5744058},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5744928},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5744944},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5745594},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5746916},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5747953},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5747968},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5748623},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5749906},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5750861},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5750877},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5751605},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5753859},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5754954},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5754970},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5755731},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5760132},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5763002},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5763019},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5770324},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5771435},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5772394},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5772410},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5772744},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5774818},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5775747},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5775763},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5778463},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5780166},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5781529},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5781563},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5781924},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5782823},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5783630},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5783646},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5783866},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'12378 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 5784462},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x26b99b0', 'extra':'http://mail.google.com/mail/?shva=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 5784507},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5785901},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5786613},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5786637},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5786935},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5787995},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5788741},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5788757},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5788967},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5789815},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5790442},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5790458},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5790690},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5794789},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5796229},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5796246},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5797596},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x24', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 5804084},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5807913},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5809711},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5809728},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5810930},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5812241},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5813376},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5813399},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5813829},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5814801},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5815619},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5815635},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5815922},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5820052},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5821491},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5821507},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5823413},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5824726},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5825918},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5825934},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5827542},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5833240},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5838020},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5838036},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5838178},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5839050},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5839934},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5839951},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5840288},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5841576},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5842569},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5842585},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5842837},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5843917},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5844784},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5844800},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5845056},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5845915},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5846647},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5846663},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5847032},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x1e', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 5847198},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5848983},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5849929},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5849944},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5850203},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5851279},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5852131},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5852147},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5852588},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5854731},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5856045},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5856061},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5856517},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5857483},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5858279},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5858295},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5858530},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5860092},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5861295},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5861312},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5862046},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5863334},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5864083},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5864099},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5865299},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5866376},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5867211},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5867227},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5867534},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5868822},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5869580},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5869595},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5869966},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5870945},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5871949},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5871965},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5872419},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5874482},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5875635},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5875652},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5875959},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5876958},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5877753},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5877771},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5878074},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5879102},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5880039},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5880056},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5880498},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5883196},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5884790},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5884807},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5886935},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5887846},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5888900},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5888916},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5889562},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5891077},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5892318},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5892334},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5893038},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5894495},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5895265},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5895281},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5895541},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5896804},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5897890},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5897906},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5898425},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5899375},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5900216},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5900232},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5900602},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5902004},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5902825},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5902840},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5903198},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5904155},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5904843},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5904859},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5905208},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5906386},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5907352},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5907368},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5908413},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5909685},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5910618},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5910634},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5911162},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5912612},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5913905},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5913926},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5914786},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5916583},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5917588},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5917603},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5923655},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5925193},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5926428},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5926444},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5927406},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5929316},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5930373},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5930390},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5930859},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5932088},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5933072},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5933087},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5933405},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5934363},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5935105},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5935121},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5937089},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5939306},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5940982},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5940999},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5941663},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5942543},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5943167},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5943183},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5943375},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5944287},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5945048},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5945064},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5945312},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5946902},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5947689},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5947704},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5947982},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5949161},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5950128},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5950144},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5950491},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5951885},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5952879},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5952895},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5954060},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5956682},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5958366},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5958382},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5958904},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5959774},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5960572},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5960589},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5960975},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5962060},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5963319},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5963336},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5963754},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5965412},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5966375},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5966391},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5966925},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5969748},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5971857},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5971880},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5972629},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5974254},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5974979},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5974996},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5975798},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5976827},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5977665},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5977681},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5977957},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5989725},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5991102},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5991119},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5991574},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5992621},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5993420},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5993436},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5993890},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5994770},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5995430},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5995454},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5995644},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 5997509},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 5998368},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 5998384},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 5998878},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'50', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 6000447},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 6004922},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 6008518},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 6008536},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 6016226},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 6017496},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 6018313},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 6018329},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 6018656},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 6018958},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 6019128},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 6019143},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 6019395},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 6019530},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 6019634},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 6019657},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 6019730},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 6020006},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 6020069},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 6020084},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x25', 'extra':'about:blank', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6154931},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'frame.load', 'id':'0x16e8488', 'extra':'about:blank', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'310', 'usec_begin': 6155294},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x25', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6155359},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x26', 'extra':'http://mail.google.com/mail/images/cleardot.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6190721},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x27', 'extra':'http://mail.google.com/mail/rc?a=af&c=fff1a8&w=4&h=4', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6222057},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x28', 'extra':'http://mail.google.com/mail/rc?a=af&c=c3d9ff&w=4&h=4', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6223307},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x29', 'extra':'http://mail.google.com/mail/images/2/5/c/icons1c.png', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6227933},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x2a', 'extra':'http://mail.google.com/mail/images/2/icons_ns2a.png', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6229889},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x2b', 'extra':'http://mail.google.com/mail/rc?a=af&c=ccc&w=4&h=4', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6235619},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x2c', 'extra':'http://mail.google.com/mail/rc?a=af&c=c3d9ff&w=3&h=3', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6240936},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x2d', 'extra':'http://mail.google.com/mail/rc?a=af&c=b5edbc&w=3&h=3', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6241168},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x2e', 'extra':'http://mail.google.com/mail/rc?a=af&c=e0ecff&w=3&h=3', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6256964},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x2f', 'extra':'http://mail.google.com/mail/images/2/5/logo.png', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6362778},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 6474842},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'50', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 6475026},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 6640799},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 6640862},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 6640876},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 6640892},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x30', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6641172},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 6641558},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 6641587},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 6641601},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 6641640},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 6641655},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 6642083},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 6642103},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x318d410', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 6642117},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x318d410', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 6643324},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 6643353},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 6643373},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x318d410', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 6643409},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x318d410', 'extra':'648 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 6643437},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 6643451},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 6643463},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x318d410', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 6643484},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x318d410', 'extra':'530 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 6665182},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 6665381},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x3123180', 'extra':'http://www.google.com/setgmail?zx=li65sohl5bca', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 6665704},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x318d410', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 6665721},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x31', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6670763},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 6671109},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 6671134},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 6671147},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 6671181},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 6671195},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 6671242},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x183c9d0', 'extra':'1237 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 6671295},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 6671309},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 6671322},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 6671346},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'4096 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 6705526},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 6705775},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 6705906},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 6705926},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x20', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6724041},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'52', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 6829332},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 6829507},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 6829528},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'145 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'169', 'usec_begin': 6829554},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/?ui=2&ik=2f47b34cd6&view=au&rt=j', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 6829578},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x32', 'extra':'http://mail.google.com/mail/?ui=2&view=jsm&name=ld%2Cml&ver=vuagRBgWwto&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 6831901},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x26', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6836122},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x27', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6836346},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x28', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6862988},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x29', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6864446},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x2a', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6892630},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x2b', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6909888},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x2c', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6910021},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x2d', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6913268},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x2e', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6916383},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x2f', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6916484},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x31', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 6926048},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x33', 'extra':'http://mail.google.com/mail/?ui=2&view=jsm&name=cv&ver=vuagRBgWwto&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7006135},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x32', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7006601},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x34', 'extra':'http://mail.google.com/mail/?ui=2&view=jsm&name=mo%2Ccw%2Cch&ver=vuagRBgWwto&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7069712},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x33', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7070044},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x35', 'extra':'http://mail.google.com/mail/?ui=2&view=jsm&name=cm&ver=vuagRBgWwto&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7124934},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x34', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7125262},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'50', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 7125318},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x36', 'extra':'http://mail.google.com/mail/?ui=2&view=jsm&name=pc&ver=vuagRBgWwto&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7154226},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x35', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7154552},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x37', 'extra':'http://mail.google.com/mail/?ui=2&view=jsm&name=ca&ver=vuagRBgWwto&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7161100},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x36', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7161380},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x38', 'extra':'http://mail.google.com/mail/?ui=2&view=jsm&name=e&ver=vuagRBgWwto&am=R_E4pcQ3aAGDQefb', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7167291},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x37', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7167559},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x38', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7217361},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x39', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7231075},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 7232017},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 7232053},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 7232074},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 7232126},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 7232148},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 7232197},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x183c9d0', 'extra':'1217 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 7232247},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 7232261},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 7232274},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 7232301},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x3a', 'extra':'http://mail.google.com/mail/images/cleardot.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7236419},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x3a', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7236457},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x3b', 'extra':'http://mail.google.com/mail/images/cleardot.gif', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7245353},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x3b', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7245394},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x3c', 'extra':'http://mail.google.com/mail/images/2/icons_ns2a.png', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7247637},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x3c', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7247672},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'597 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 7268945},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 7269174},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 7269424},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x2f33910', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1086&MODE=init&zx=gsd2cum2kqx0&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 7269459},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'47', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 7375719},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x3d', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7377167},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x39', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7377400},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 7377570},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 7377597},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 7377618},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 7377657},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_host', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'270', 'usec_begin': 7377672},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_host', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'275', 'usec_begin': 7378021},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.connect', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'279', 'usec_begin': 7378038},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.connect', 'id':'0x2e8fea0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'73', 'usec_begin': 7378053},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.connect', 'id':'0x2e8fea0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'238', 'usec_begin': 7401287},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.connect', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'284', 'usec_begin': 7401329},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 7401345},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x2e8fea0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 7401386},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x2e8fea0', 'extra':'803 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 7401417},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 7401430},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 7401444},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x2e8fea0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 7401462},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x2e8fea0', 'extra':'544 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 7433482},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 7433788},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 7434023},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x185c988', 'extra':'http://chatenabled.mail.google.com/mail/images/cleardot.gif?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1234&zx=ycda9of1csnp', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 7434055},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'url.load', 'id':'0x3d', 'extra':'', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'196', 'usec_begin': 7434302},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'url.load', 'id':'0x3e', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\webkit\tools\test_shell\test_webview_delegate.cc', 'line_number':'189', 'usec_begin': 7435539},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.resolve_proxy', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'252', 'usec_begin': 7436159},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.resolve_proxy', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'257', 'usec_begin': 7436193},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.init_conn', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'261', 'usec_begin': 7436214},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.init_conn', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'266', 'usec_begin': 7436260},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.write_headers', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'297', 'usec_begin': 7436282},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.write', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'192', 'usec_begin': 7436335},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.write', 'id':'0x183c9d0', 'extra':'1220 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'201', 'usec_begin': 7436389},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.write_headers', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'302', 'usec_begin': 7436419},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_headers', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'315', 'usec_begin': 7436437},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 7436451},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'548 bytes', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'279', 'usec_begin': 7468253},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_headers', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'320', 'usec_begin': 7468524},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 7468734},
+{'pid':'0x854', 'tid':'0xa20', 'type':'END', 'name':'http.read_body', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'329', 'usec_begin': 7468755},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'http.read_body', 'id':'0x185c988', 'extra':'http://mail.google.com/mail/channel/test?at=xn3j339j0a8vwew777x485j2ygbokt&VER=6&it=1291&TYPE=xmlhttp&zx=ev050ueswmrg&t=1', 'file':'E:\src\cr\src\net\http\http_network_transaction.cc', 'line_number':'324', 'usec_begin': 7468881},
+{'pid':'0x854', 'tid':'0xa20', 'type':'BEGIN', 'name':'socket.read', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'160', 'usec_begin': 7468898},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'6', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 7626418},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 7876733},
+{'pid':'0x854', 'tid':'0x208', 'type':'INSTANT', 'name':'heartbeat.cpu', 'id':'0x0', 'extra':'0', 'file':'E:\src\cr\src\base\trace_event.cc', 'line_number':'76', 'usec_begin': 8126490},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 8309792},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 8309858},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 8309873},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 8326339},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'965', 'usec_begin': 8326394},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.compile', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'967', 'usec_begin': 8326477},
+{'pid':'0x854', 'tid':'0x208', 'type':'BEGIN', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'972', 'usec_begin': 8326505},
+{'pid':'0x854', 'tid':'0x208', 'type':'END', 'name':'v8.run', 'id':'0x0', 'extra':'', 'file':'E:\src\cr\src\webkit\port\bindings\v8\v8_proxy.cpp', 'line_number':'974', 'usec_begin': 8341241},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x183c9d0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 8341596},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x318d410', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 8341826},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x2e8fea0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 8375190},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x265a568', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 8375275},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x265aeb0', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 8375394},
+{'pid':'0x854', 'tid':'0xa20', 'type':'INSTANT', 'name':'socket.disconnect', 'id':'0x26c29a8', 'extra':'', 'file':'E:\src\cr\src\net\base\tcp_client_socket.cc', 'line_number':'113', 'usec_begin': 8375490},
+];
diff --git a/chromium/tools/traceline/svgui/README b/chromium/tools/traceline/svgui/README
new file mode 100644
index 00000000000..1a113e281bc
--- /dev/null
+++ b/chromium/tools/traceline/svgui/README
@@ -0,0 +1,12 @@
+This is a small "web application" to display traceline trace data. It uses
+xhtml, SVG, and JavaScript to interpret the JSON data in a timeline format.
+Events can be moused over to show details, stack traces, etc.
+
+The name of the JSON file should be supplied behind a # in the URL. Multiple
+JSON files can be listed (comma separated), allowing you to compare multiple
+sets of data. Examples:
+
+http://blah/traceline.xml#startup-release.json
+http://blah/traceline.xml#mydata1.json,mydata2.json
+
+Dean McNamee <deanm@chromium.org>
diff --git a/chromium/tools/traceline/svgui/startup-release.json b/chromium/tools/traceline/svgui/startup-release.json
new file mode 100644
index 00000000000..37a36201da2
--- /dev/null
+++ b/chromium/tools/traceline/svgui/startup-release.json
@@ -0,0 +1,178 @@
+parseEvents([
+{'stacktrace': [], 'thread': 3956, 'eventtype': 'EVENT_TYPE_APC', 'func_addr_name': 'ntdll.dll!LdrInitializeThunk+0x0', 'ret_addr': 2089872071, 'done': 23.106567999999999, 'func_addr': 2089816446, 'ms': 6.3611440000000004, 'cpu': 2147742720},
+{'stacktrace': [[2089816487, 'ntdll.dll!LdrpCallInitRoutine+0x14'], [2089929643, 'ntdll.dll!LdrpRunInitializeRoutines+0x1c7'], [2089917304, 'ntdll.dll!LdrpGetProcedureAddress+0x1c3'], [2089917344, 'ntdll.dll!LdrGetProcedureAddress+0x18'], [2089952052, 'ntdll.dll!LdrpInitializeProcess+0x878'], [2089948729, 'ntdll.dll!_LdrpInitialize+0x88d3'], [1717963930, 'failed']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 2147323904, 'startaddr': 2088763392, 'ms': 7.0830229999999998, 'cpu': 2147742720},
+{'stacktrace': [[2118314946, 'USER32.dll!_UserClientDllInitialize+0x246'], [2089816487, 'ntdll.dll!LdrpCallInitRoutine+0x14'], [2089929643, 'ntdll.dll!LdrpRunInitializeRoutines+0x1c7'], [2089948990, 'ntdll.dll!LdrpInitializeProcess+0xfffffc82'], [2089948729, 'ntdll.dll!_LdrpInitialize+0x88d3'], [1717963930, 'failed']], 'thread': 3956, 'syscall': 4316, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!NtGdiInit', 'done': 12.667252, 'ms': 11.086605, 'syscallargs': [1242536, 1243632, 2118314946], 'cpu': 2147742720},
+{'stacktrace': [[2088853969, 'kernel32.dll!CsrBasepCreateActCtx+0xa2'], [2088853339, 'kernel32.dll!BasepCreateActCtx+0x63a'], [2088851440, 'kernel32.dll!CreateActCtxW+0x394'], [2091021301, 'SHELL32.dll!SHFusionInitializeIDCC+0x6d'], [2091021175, 'SHELL32.dll!SHFusionInitializeFromModuleID+0x3a'], [2091020981, 'SHELL32.dll!_ProcessAttach+0x2f'], [2091020914, 'SHELL32.dll!DllMain+0x3fe1a'], [2090759390, 'SHELL32.dll!_DllMainCRTStartup+0x48'], [2089816487, 'ntdll.dll!LdrpCallInitRoutine+0x14'], [2089929643, 'ntdll.dll!LdrpRunInitializeRoutines+0x1c7'], [2089948990, 'ntdll.dll!LdrpInitializeProcess+0xfffffc82'], [2089948729, 'ntdll.dll!_LdrpInitialize+0x88d3'], [1717963930, 'failed']], 'thread': 3956, 'syscall': 200, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtRequestWaitReplyPort', 'done': 16.840966999999999, 'ms': 13.546135, 'syscallargs': [32, 1240476, 1240476], 'cpu': 2147742720},
+{'stacktrace': [[2088853969, 'kernel32.dll!CsrBasepCreateActCtx+0xa2'], [2088853339, 'kernel32.dll!BasepCreateActCtx+0x63a'], [2088851440, 'kernel32.dll!CreateActCtxW+0x394'], [2001057805, 'comctl32.dll!SHFusionInitializeIDCC+0x83'], [2001057855, 'comctl32.dll!SHFusionInitializeID+0x12'], [2001057879, 'comctl32.dll!SHFusionInitialize+0xf'], [2000503209, 'comctl32.dll!_ProcessAttach+0x32'], [2000503399, 'comctl32.dll!LibMain+0x21'], [2089816487, 'ntdll.dll!LdrpCallInitRoutine+0x14'], [2089929643, 'ntdll.dll!LdrpRunInitializeRoutines+0x1c7'], [2089902456, 'ntdll.dll!LdrpLoadDll+0xfffffe4f'], [2089902810, 'ntdll.dll!LdrLoadDll+0x110'], [2088770489, 'kernel32.dll!LoadLibraryExW+0xc8'], [2088808028, 'kernel32.dll!LoadLibraryW+0x11'], [2091021388, 'SHELL32.dll!SHFusionLoadLibrary+0x2a'], [2090759619, 'SHELL32.dll!DelayLoadCC+0x15']], 'thread': 3956, 'syscall': 200, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtRequestWaitReplyPort', 'done': 21.051558, 'ms': 17.985804999999999, 'syscallargs': [32, 1237992, 1237992], 'cpu': 2147742720},
+{'stacktrace': [[2089888951, 'ntdll.dll!LdrAccessResource+0x15'], [2009076731, 'VERSION.dll!GetFileVersionInfoSizeW+0x6a'], [4315331, 'chrome.exe!FileVersionInfo::CreateFileVersionInfo+0x23 [ c:\\g\\trunk\\src\\base\\file_version_info.cc:46 ]'], [4202450, "chrome.exe!`anonymous namespace'::GetCustomInfo+0x22 [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:63 ]"], [4204639, 'chrome.exe!InitCrashReporter+0x13f [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:238 ]'], [4205528, 'chrome.exe!wWinMain+0x2b8 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:95 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 178, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtQueryVirtualMemory', 'done': 24.995356000000001, 'ms': 24.501438, 'syscallargs': [4294967295, 19333120, 0], 'cpu': 2147742720},
+{'stacktrace': [[2089888951, 'ntdll.dll!LdrAccessResource+0x15'], [2009076752, 'VERSION.dll!GetFileVersionInfoSizeW+0x7f'], [4315331, 'chrome.exe!FileVersionInfo::CreateFileVersionInfo+0x23 [ c:\\g\\trunk\\src\\base\\file_version_info.cc:46 ]'], [4202450, "chrome.exe!`anonymous namespace'::GetCustomInfo+0x22 [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:63 ]"], [4204639, 'chrome.exe!InitCrashReporter+0x13f [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:238 ]'], [4205528, 'chrome.exe!wWinMain+0x2b8 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:95 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 178, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtQueryVirtualMemory', 'done': 25.491229000000001, 'ms': 24.997869999999999, 'syscallargs': [4294967295, 19333120, 0], 'cpu': 2147742720},
+{'stacktrace': [[2089888951, 'ntdll.dll!LdrAccessResource+0x15'], [2009077479, 'VERSION.dll!GetFileVersionInfoW+0x68'], [4315373, 'chrome.exe!FileVersionInfo::CreateFileVersionInfo+0x4d [ c:\\g\\trunk\\src\\base\\file_version_info.cc:54 ]'], [4202450, "chrome.exe!`anonymous namespace'::GetCustomInfo+0x22 [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:63 ]"], [4204639, 'chrome.exe!InitCrashReporter+0x13f [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:238 ]'], [4205528, 'chrome.exe!wWinMain+0x2b8 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:95 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 178, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtQueryVirtualMemory', 'done': 26.258085999999999, 'ms': 25.763888999999999, 'syscallargs': [4294967295, 19333120, 0], 'cpu': 2147742720},
+{'eventid': 1718060360, 'stacktrace': [[2088839620, 'kernel32.dll!BaseCreateThreadPoolThread+0x44'], [2089982739, 'ntdll.dll!RtlpStartThreadpoolThread+0x4e'], [2089993072, 'ntdll.dll!RtlpInitializeTimerThreadPool+0xb7'], [2089992706, 'ntdll.dll!RtlpInitializeWorkerThreadPool+0x1c'], [2089993149, 'ntdll.dll!RtlQueueWorkItem+0x4ce5'], [2088962678, 'kernel32.dll!QueueUserWorkItem+0x14'], [4204696, 'chrome.exe!InitCrashReporter+0x178 [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:250 ]'], [4205528, 'chrome.exe!wWinMain+0x2b8 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:95 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 26.361730000000001, 'cpu': 2147742720},
+{'stacktrace': [], 'thread': 3380, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718060360, 'startaddr': 2089974157, 'ms': 26.482137000000002, 'cpu': 3124053392},
+{'eventid': 1718062684, 'stacktrace': [[2088839620, 'kernel32.dll!BaseCreateThreadPoolThread+0x44'], [2089982739, 'ntdll.dll!RtlpStartThreadpoolThread+0x4e'], [2089982839, 'ntdll.dll!RtlpStartWorkerThread+0x16'], [2089982906, 'ntdll.dll!RtlQueueWorkItem+0x24e2'], [2088962678, 'kernel32.dll!QueueUserWorkItem+0x14'], [4204696, 'chrome.exe!InitCrashReporter+0x178 [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:250 ]'], [4205528, 'chrome.exe!wWinMain+0x2b8 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:95 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 26.58634, 'cpu': 2147742720},
+{'stacktrace': [], 'thread': 2440, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718062684, 'startaddr': 2089879392, 'ms': 26.691939999999999, 'cpu': 3124053392},
+{'stacktrace': [[2089816139, 'ntdll.dll!RtlEnterCriticalSection+0x46'], [2088809487, 'kernel32.dll!GetModuleFileNameW+0x3a'], [2089167589, 'kernel32.dll!FillUEFInfo+0x51'], [2089043624, 'kernel32.dll!SetUnhandledExceptionFilter+0x2b'], [4203570, 'chrome.exe!InitCrashReporterThread+0x1b2 [ c:\\g\\trunk\\src\\chrome\\app\\breakpad.cc:181 ]'], [2089973061, 'ntdll.dll!RtlpWorkerCallout+0x65'], [2089973123, 'ntdll.dll!RtlpExecuteWorkerRequest+0x1a'], [2089973317, 'ntdll.dll!RtlpApcCallout+0x11'], [2089973276, 'ntdll.dll!RtlpWorkerThread+0x16ebc'], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2440, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 51.803511, 'ms': 26.820167999999999, 'syscallargs': [120, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[2089934922, 'ntdll.dll!LdrpMapDll+0x1b0b'], [2089902193, 'ntdll.dll!LdrpLoadDll+0xfffffd48'], [2089902810, 'ntdll.dll!LdrLoadDll+0x110'], [2088770489, 'kernel32.dll!LoadLibraryExW+0xc8'], [4205549, 'chrome.exe!wWinMain+0x2cd [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:99 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 137, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwProtectVirtualMemory', 'done': 44.387484999999998, 'ms': 43.193758000000003, 'syscallargs': [4294967295, 1242540, 1242544], 'cpu': 2147742720},
+{'stacktrace': [[2088853969, 'kernel32.dll!CsrBasepCreateActCtx+0xa2'], [2088853339, 'kernel32.dll!BasepCreateActCtx+0x63a'], [2088851440, 'kernel32.dll!CreateActCtxW+0x394'], [2088959197, 'kernel32.dll!BasepProbeForDllManifest+0x1eacd'], [2089928717, 'ntdll.dll!LdrpWalkImportDescriptor+0x84'], [2089902276, 'ntdll.dll!LdrpLoadDll+0xfffffd9b'], [2089902810, 'ntdll.dll!LdrLoadDll+0x110'], [2088770489, 'kernel32.dll!LoadLibraryExW+0xc8'], [4205549, 'chrome.exe!wWinMain+0x2cd [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:99 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 200, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtRequestWaitReplyPort', 'done': 45.075840999999997, 'ms': 44.847599000000002, 'syscallargs': [32, 1240632, 1240632], 'cpu': 2147742720},
+{'stacktrace': [[2011010674, 'ADVAPI32.dll!GatherRandomKeyFastUserMode+0xba'], [2011006756, 'ADVAPI32.dll!RandomFillBuffer+0xa3'], [2011006564, 'ADVAPI32.dll!GenRandom+0x25'], [2011006503, 'ADVAPI32.dll!NewGenRandomEx+0x4d'], [2011006415, 'ADVAPI32.dll!NewGenRandom+0x34'], [2011006354, 'ADVAPI32.dll!SystemFunction036+0x14'], [2011652938, 'RPCRT4.dll!GenerateRandomNumber+0x2ff'], [2011652709, 'RPCRT4.dll!UuidCreate+0x11'], [2001932179, 'ole32.dll!DllMain+0x33e86'], [2001719529, 'ole32.dll!_DllMainCRTStartup+0x48'], [2089816487, 'ntdll.dll!LdrpCallInitRoutine+0x14'], [2089929643, 'ntdll.dll!LdrpRunInitializeRoutines+0x1c7'], [2089902456, 'ntdll.dll!LdrpLoadDll+0xfffffe4f'], [2089902810, 'ntdll.dll!LdrLoadDll+0x110'], [2088770489, 'kernel32.dll!LoadLibraryExW+0xc8'], [4205549, 'chrome.exe!wWinMain+0x2cd [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:99 ]']], 'thread': 3956, 'syscall': 66, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwDeviceIoControlFile', 'done': 47.469441000000003, 'ms': 47.221643999999998, 'syscallargs': [128, 0, 0], 'cpu': 2147742720},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2440, 'syscall': 190, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwRemoveIoCompletion', 'waiting': 1, 'done': 146.87732700000001, 'ms': 51.840667000000003, 'syscallargs': [112, 13500332, 13500336], 'cpu': 3124053392},
+{'stacktrace': [[2118254284, 'USER32.dll!_CreateWindowEx+0xb1'], [2118253656, 'USER32.dll!CreateWindowExW+0x33'], [2001923724, 'ole32.dll!InitMainThreadWnd+0x3c'], [2001727537, 'ole32.dll!CoInitializeEx+0xc6'], [2001729284, 'ole32.dll!OleInitializeEx+0x12'], [2001729257, 'ole32.dll!OleInitialize+0xf'], [19354461, 'chrome.dll!ChromeMain+0x7dd [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:223 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4439, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserCreateWindowEx', 'done': 53.857683000000002, 'ms': 53.325772000000001, 'syscallargs': [0, 49208, 49208], 'cpu': 2147742720},
+{'stacktrace': [[19417443, 'chrome.dll!PlatformThread::SetName+0x63 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:62 ]'], [20401225, 'chrome.dll!BrowserMain+0xc9 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:294 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_THREADNAME', 'threadname': 'Chromium_BrowserMain', 'ms': 54.000996999999998, 'cpu': 2147742720},
+{'eventid': 1718170996, 'stacktrace': [[2088830549, 'kernel32.dll!CreateThread+0x1e'], [19417542, 'chrome.dll!PlatformThread::Create+0x36 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:83 ]'], [23799365, 'chrome.dll!base::Thread::StartWithOptions+0xb5 [ c:\\g\\trunk\\src\\base\\thread.cc:82 ]'], [20506130, 'chrome.dll!BrowserProcessImpl::CreateFileThread+0xa2 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:300 ]'], [20398585, 'chrome.dll!BrowserProcessImpl::file_thread+0x19 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.h:61 ]'], [20852807, 'chrome.dll!ProfileImpl::GetPrefs+0xc7 [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:720 ]'], [20855066, 'chrome.dll!ProfileImpl::ProfileImpl+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:565 ]'], [20856220, 'chrome.dll!Profile::CreateProfile+0x1c [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:69 ]'], [20602496, 'chrome.dll!ProfileManager::GetDefaultProfile+0x1c0 [ c:\\g\\trunk\\src\\chrome\\browser\\profile_manager.cc:96 ]'], [20402403, 'chrome.dll!BrowserMain+0x563 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:374 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 59.869340999999999, 'cpu': 2147742720},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19495803, 'chrome.dll!base::WaitableEvent::Wait+0x1b [ c:\\g\\trunk\\src\\base\\waitable_event_win.cc:42 ]'], [23799422, 'chrome.dll!base::Thread::StartWithOptions+0xee [ c:\\g\\trunk\\src\\base\\thread.cc:91 ]'], [20506130, 'chrome.dll!BrowserProcessImpl::CreateFileThread+0xa2 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:300 ]'], [20398585, 'chrome.dll!BrowserProcessImpl::file_thread+0x19 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.h:61 ]'], [20852807, 'chrome.dll!ProfileImpl::GetPrefs+0xc7 [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:720 ]'], [20855066, 'chrome.dll!ProfileImpl::ProfileImpl+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:565 ]'], [20856220, 'chrome.dll!Profile::CreateProfile+0x1c [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:69 ]'], [20602496, 'chrome.dll!ProfileManager::GetDefaultProfile+0x1c0 [ c:\\g\\trunk\\src\\chrome\\browser\\profile_manager.cc:96 ]'], [20402403, 'chrome.dll!BrowserMain+0x563 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:374 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 60.171892999999997, 'ms': 59.965162999999997, 'syscallargs': [152, 0, 0], 'cpu': 2147742720},
+{'stacktrace': [], 'thread': 2736, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718170996, 'startaddr': 19417280, 'ms': 60.031652000000001, 'cpu': 3124053392},
+{'stacktrace': [[19417443, 'chrome.dll!PlatformThread::SetName+0x63 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:62 ]'], [23799603, 'chrome.dll!base::Thread::ThreadMain+0x53 [ c:\\g\\trunk\\src\\base\\thread.cc:145 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2736, 'eventtype': 'EVENT_TYPE_THREADNAME', 'threadname': 'Chrome_FileThread', 'ms': 60.136972999999998, 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19467175, 'chrome.dll!base::MessagePumpForUI::WaitForWork+0x27 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:408 ]'], [19470141, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0xbd [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:393 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2736, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 64.683081000000001, 'ms': 60.200668, 'syscallargs': [1, 15858672, 1], 'cpu': 3124053392},
+{'stacktrace': [[2089175867, 'kernel32.dll!CreateToolhelp32Snapshot+0x2c'], [19416396, 'chrome.dll!process_util::KillProcesses+0x6c [ c:\\g\\trunk\\src\\base\\process_util_win.cc:296 ]'], [20567056, 'chrome.dll!BrowserInit::MessageWindow::HuntForZombieChromeProcesses+0x40 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:367 ]'], [20403945, 'chrome.dll!BrowserMain+0xb69 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:444 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 173, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtQuerySystemInformation', 'done': 61.949773, 'ms': 61.741366999999997, 'syscallargs': [5, 15859712, 65536], 'cpu': 2147742720},
+{'eventid': 1718192188, 'stacktrace': [[2088830549, 'kernel32.dll!CreateThread+0x1e'], [20819991, 'chrome.dll!chrome_browser_net::DnsMaster::PreLockedCreateNewSlaveIfNeeded+0x87 [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_master.cc:303 ]'], [20824704, 'chrome.dll!chrome_browser_net::DnsMaster::Resolve+0x30 [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_master.cc:70 ]'], [20522363, 'chrome.dll!chrome_browser_net::DnsPrefetchHostNamesAtStartup+0x2cb [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_global.cc:430 ]'], [20404113, 'chrome.dll!BrowserMain+0xc11 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:462 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 63.390737999999999, 'cpu': 2147742720},
+{'stacktrace': [], 'thread': 2812, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718192188, 'startaddr': 21429184, 'ms': 63.532375999999999, 'cpu': 3124053392},
+{'stacktrace': [[19417443, 'chrome.dll!PlatformThread::SetName+0x63 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:62 ]'], [21429081, 'chrome.dll!chrome_browser_net::DnsSlave::Run+0xa9 [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_slave.cc:57 ]'], [21429195, 'chrome.dll!chrome_browser_net::DnsSlave::ThreadStart+0xb [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_slave.cc:45 ]'], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2812, 'eventtype': 'EVENT_TYPE_THREADNAME', 'threadname': 'dns_prefetcher_1_of_8', 'ms': 63.553328999999998, 'cpu': 3124053392},
+{'eventid': 1718197540, 'stacktrace': [[2088830549, 'kernel32.dll!CreateThread+0x1e'], [4216426, 'chrome.exe!sandbox::BrokerServicesBase::Init+0x5a [ c:\\g\\trunk\\src\\sandbox\\src\\broker_services.cc:70 ]'], [20404275, 'chrome.dll!BrowserMain+0xcb3 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:523 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 63.831575999999998, 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19467175, 'chrome.dll!base::MessagePumpForUI::WaitForWork+0x27 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:408 ]'], [19470141, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0xbd [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:393 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2736, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 133.03087400000001, 'ms': 64.752364, 'syscallargs': [1, 15858672, 1], 'cpu': 3124053392},
+{'stacktrace': [], 'thread': 2428, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718197540, 'startaddr': 4215808, 'ms': 64.816618000000005, 'cpu': 3124053392},
+{'eventid': 1718207424, 'stacktrace': [[2088830549, 'kernel32.dll!CreateThread+0x1e'], [19417542, 'chrome.dll!PlatformThread::Create+0x36 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:83 ]'], [23799365, 'chrome.dll!base::Thread::StartWithOptions+0xb5 [ c:\\g\\trunk\\src\\base\\thread.cc:82 ]'], [20505911, 'chrome.dll!BrowserProcessImpl::CreateIOThread+0xa7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:287 ]'], [20398537, 'chrome.dll!BrowserProcessImpl::io_thread+0x19 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.h:54 ]'], [20576442, 'chrome.dll!InstallJankometer+0x19a [ c:\\g\\trunk\\src\\chrome\\browser\\jankometer.cc:210 ]'], [20404892, 'chrome.dll!BrowserMain+0xf1c [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:565 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 64.829469000000003, 'cpu': 2147742720},
+{'stacktrace': [[4340339, 'chrome.exe!PlatformThread::SetName+0x63 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:62 ]'], [4215848, 'chrome.exe!sandbox::BrokerServicesBase::TargetEventsThread+0x28 [ c:\\g\\trunk\\src\\sandbox\\src\\broker_services.cc:147 ]'], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2428, 'eventtype': 'EVENT_TYPE_THREADNAME', 'threadname': 'BrokerEventThread', 'ms': 64.838966999999997, 'cpu': 3124053392},
+{'stacktrace': [[4215906, 'chrome.exe!sandbox::BrokerServicesBase::TargetEventsThread+0x62 [ c:\\g\\trunk\\src\\sandbox\\src\\broker_services.cc:151 ]'], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2428, 'syscall': 190, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwRemoveIoCompletion', 'waiting': 1, 'done': 115.701297, 'ms': 64.856288000000006, 'syscallargs': [168, 17039276, 17038976], 'cpu': 3124053392},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19495803, 'chrome.dll!base::WaitableEvent::Wait+0x1b [ c:\\g\\trunk\\src\\base\\waitable_event_win.cc:42 ]'], [23799422, 'chrome.dll!base::Thread::StartWithOptions+0xee [ c:\\g\\trunk\\src\\base\\thread.cc:91 ]'], [20505911, 'chrome.dll!BrowserProcessImpl::CreateIOThread+0xa7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:287 ]'], [20398537, 'chrome.dll!BrowserProcessImpl::io_thread+0x19 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.h:54 ]'], [20576442, 'chrome.dll!InstallJankometer+0x19a [ c:\\g\\trunk\\src\\chrome\\browser\\jankometer.cc:210 ]'], [20404892, 'chrome.dll!BrowserMain+0xf1c [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:565 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 65.134815000000003, 'ms': 64.898751000000004, 'syscallargs': [192, 0, 0], 'cpu': 2147742720},
+{'stacktrace': [], 'thread': 708, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718207424, 'startaddr': 19417280, 'ms': 64.96105, 'cpu': 3124053392},
+{'stacktrace': [[19417443, 'chrome.dll!PlatformThread::SetName+0x63 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:62 ]'], [23799603, 'chrome.dll!base::Thread::ThreadMain+0x53 [ c:\\g\\trunk\\src\\base\\thread.cc:145 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'eventtype': 'EVENT_TYPE_THREADNAME', 'threadname': 'Chrome_IOThread', 'ms': 65.062179999999998, 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 101.74421599999999, 'ms': 65.212478000000004, 'syscallargs': [1, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118254284, 'USER32.dll!_CreateWindowEx+0xb1'], [2118253656, 'USER32.dll!CreateWindowExW+0x33'], [27144714, 'chrome.dll!views::ContainerWin::Init+0x11a [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:161 ]'], [27116867, 'chrome.dll!views::Window::Init+0x93 [ c:\\g\\trunk\\src\\chrome\\views\\window.cc:305 ]'], [27291723, 'chrome.dll!views::CustomFrameWindow::Init+0x3b [ c:\\g\\trunk\\src\\chrome\\views\\custom_frame_window.cc:917 ]'], [23006205, 'chrome.dll!BrowserFrame::CreateForBrowserView+0x4d [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_window_factory.cc:58 ]'], [23006465, 'chrome.dll!BrowserWindow::CreateBrowserWindow+0x51 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_window_factory.cc:34 ]'], [20656275, 'chrome.dll!Browser::Browser+0x263 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:229 ]'], [20564706, 'chrome.dll!BrowserInit::LaunchWithProfile::CreateTabbedBrowser+0x52 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:489 ]'], [20567260, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0x9c [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:536 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]']], 'thread': 3956, 'syscall': 4439, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserCreateWindowEx', 'done': 72.739132999999995, 'ms': 70.077900999999997, 'syscallargs': [0, 1241012, 1239776], 'cpu': 2147742720},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [23834872, 'chrome.dll!ConditionVariable::TimedWait+0xb8 [ c:\\g\\trunk\\src\\base\\condition_variable_win.cc:66 ]'], [23834961, 'chrome.dll!ConditionVariable::Wait+0x21 [ c:\\g\\trunk\\src\\base\\condition_variable_win.cc:48 ]'], [20821313, 'chrome.dll!chrome_browser_net::DnsMaster::GetNextAssignment+0x31 [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_master.cc:245 ]'], [21429120, 'chrome.dll!chrome_browser_net::DnsSlave::Run+0xd0 [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_slave.cc:63 ]'], [21429195, 'chrome.dll!chrome_browser_net::DnsSlave::ThreadStart+0xb [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_slave.cc:45 ]'], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2812, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 302.163543, 'ms': 70.703958, 'syscallargs': [232, 0, 0], 'cpu': 2147742720},
+{'stacktrace': [[2118254284, 'USER32.dll!_CreateWindowEx+0xb1'], [2118253656, 'USER32.dll!CreateWindowExW+0x33'], [27264799, 'chrome.dll!views::TooltipManager::Init+0x2f [ c:\\g\\trunk\\src\\chrome\\views\\tooltip_manager.cc:114 ]'], [27145071, 'chrome.dll!views::ContainerWin::Init+0x27f [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:187 ]'], [27116867, 'chrome.dll!views::Window::Init+0x93 [ c:\\g\\trunk\\src\\chrome\\views\\window.cc:305 ]'], [27291723, 'chrome.dll!views::CustomFrameWindow::Init+0x3b [ c:\\g\\trunk\\src\\chrome\\views\\custom_frame_window.cc:917 ]'], [23006205, 'chrome.dll!BrowserFrame::CreateForBrowserView+0x4d [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_window_factory.cc:58 ]'], [23006465, 'chrome.dll!BrowserWindow::CreateBrowserWindow+0x51 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_window_factory.cc:34 ]'], [20656275, 'chrome.dll!Browser::Browser+0x263 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:229 ]'], [20564706, 'chrome.dll!BrowserInit::LaunchWithProfile::CreateTabbedBrowser+0x52 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:489 ]'], [20567260, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0x9c [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:536 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]']], 'thread': 3956, 'syscall': 4439, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserCreateWindowEx', 'done': 74.146016000000003, 'ms': 72.944186999999999, 'syscallargs': [32, 1240832, 1239596], 'cpu': 3124053392},
+{'stacktrace': [[2118254284, 'USER32.dll!_CreateWindowEx+0xb1'], [2118253656, 'USER32.dll!CreateWindowExW+0x33'], [27969145, 'chrome.dll!ATL::CWindowImplBaseT<ATL::CWindow,ATL::CWinTraits<47120384,0> >::Create+0xb9 [ c:\\program files\\microsoft visual studio 8\\vc\\atlmfc\\include\\atlwin.h:3139 ]'], [21304605, 'chrome.dll!ATL::CWindowImpl<AutocompleteEditView,WTL::CRichEditCtrlT<ATL::CWindow>,ATL::CWinTraits<1342177664,0> >::Create+0x6d [ c:\\program files\\microsoft visual studio 8\\vc\\atlmfc\\include\\atlwin.h:3215 ]'], [21312331, 'chrome.dll!AutocompleteEditView::AutocompleteEditView+0x2cb [ c:\\g\\trunk\\src\\chrome\\browser\\autocomplete\\autocomplete_edit.cc:694 ]'], [23005496, 'chrome.dll!LocationBarView::Init+0x168 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\location_bar_view.cc:131 ]'], [23207043, 'chrome.dll!BrowserToolbarView::CreateCenterStack+0x253 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\toolbar_view.cc:186 ]'], [23210088, 'chrome.dll!BrowserToolbarView::Init+0x18 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\toolbar_view.cc:96 ]'], [23149860, 'chrome.dll!BrowserView2::Init+0x134 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:283 ]'], [23145656, 'chrome.dll!BrowserView2::ViewHierarchyChanged+0x38 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:788 ]'], [27129880, 'chrome.dll!views::View::PropagateAddNotifications+0x88 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:674 ]'], [27131408, 'chrome.dll!views::View::AddChildView+0xb0 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:585 ]'], [27131647, 'chrome.dll!views::View::AddChildView+0x2f [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:561 ]'], [23201897, 'chrome.dll!OpaqueNonClientView::ViewHierarchyChanged+0xd9 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\opaque_non_client_view.cc:670 ]'], [27129880, 'chrome.dll!views::View::PropagateAddNotifications+0x88 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:674 ]'], [27131408, 'chrome.dll!views::View::AddChildView+0xb0 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:585 ]']], 'thread': 3956, 'syscall': 4439, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserCreateWindowEx', 'done': 88.230208000000005, 'ms': 86.457915999999997, 'syscallargs': [0, 49640, 49640], 'cpu': 2147742720},
+{'stacktrace': [[27278917, 'chrome.dll!views::HWNDView::DidChangeBounds+0x5 [ c:\\g\\trunk\\src\\chrome\\views\\hwnd_view.cc:137 ]'], [21099029, 'chrome.dll!views::View::SetBounds+0x45 [ c:\\g\\trunk\\src\\chrome\\views\\view.h:164 ]'], [23005111, 'chrome.dll!LocationBarView::DoLayout+0x227 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\location_bar_view.cc:431 ]'], [23006103, 'chrome.dll!LocationBarView::Layout+0x7 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\location_bar_view.cc:218 ]'], [21099029, 'chrome.dll!views::View::SetBounds+0x45 [ c:\\g\\trunk\\src\\chrome\\views\\view.h:164 ]'], [23203355, 'chrome.dll!BrowserToolbarView::Layout+0x20b [ c:\\g\\trunk\\src\\chrome\\browser\\views\\toolbar_view.cc:311 ]'], [27117623, 'chrome.dll!views::View::DidChangeBounds+0x7 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:192 ]'], [23143722, 'chrome.dll!BrowserView2::LayoutToolbar+0xea [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:920 ]'], [23143963, 'chrome.dll!BrowserView2::Layout+0x1b [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:768 ]'], [27117623, 'chrome.dll!views::View::DidChangeBounds+0x7 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:192 ]'], [23198989, 'chrome.dll!OpaqueNonClientView::Layout+0x4d [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\opaque_non_client_view.cc:633 ]'], [27117623, 'chrome.dll!views::View::DidChangeBounds+0x7 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:192 ]'], [27138473, 'chrome.dll!views::FillLayout::Layout+0x69 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:57 ]'], [27122596, 'chrome.dll!views::View::Layout+0x14 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:214 ]'], [27142349, 'chrome.dll!views::ContainerWin::ChangeSize+0x8d [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:815 ]'], [27141386, 'chrome.dll!views::ContainerWin::SetContentsView+0xea [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:214 ]']], 'thread': 3956, 'syscall': 4642, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetWindowPos', 'done': 97.329130000000006, 'ms': 96.881028000000001, 'syscallargs': [8979080, 0, 137], 'cpu': 3124053392},
+{'eventid': 1718457244, 'stacktrace': [[2088839620, 'kernel32.dll!BaseCreateThreadPoolThread+0x44'], [2089982739, 'ntdll.dll!RtlpStartThreadpoolThread+0x4e'], [2090037459, 'ntdll.dll!RtlpStartWaitThread+0x51'], [2090031864, 'ntdll.dll!RtlRegisterWait+0x105'], [2088899101, 'kernel32.dll!RegisterWaitForSingleObject+0x50'], [27049362, 'chrome.dll!WorkerThreadTicker::Start+0xc2 [ c:\\g\\trunk\\src\\chrome\\common\\worker_thread_ticker.cc:66 ]'], [20653873, 'chrome.dll!Browser::InitHangMonitor+0xd1 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1579 ]'], [20656498, 'chrome.dll!Browser::Browser+0x342 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:247 ]'], [20564706, 'chrome.dll!BrowserInit::LaunchWithProfile::CreateTabbedBrowser+0x52 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:489 ]'], [20567260, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0x9c [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:536 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 98.261930000000007, 'cpu': 3124053392},
+{'stacktrace': [], 'thread': 3500, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718457244, 'startaddr': 2089983918, 'ms': 98.425916999999998, 'cpu': 2147742720},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 103.631327, 'ms': 98.535987000000006, 'syscallargs': [2, 32505136, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118254284, 'USER32.dll!_CreateWindowEx+0xb1'], [2118253656, 'USER32.dll!CreateWindowExW+0x33'], [27264799, 'chrome.dll!views::TooltipManager::Init+0x2f [ c:\\g\\trunk\\src\\chrome\\views\\tooltip_manager.cc:114 ]'], [27145071, 'chrome.dll!views::ContainerWin::Init+0x27f [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:187 ]'], [21603024, 'chrome.dll!WebContentsViewWin::CreateView+0x20 [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents_view_win.cc:61 ]'], [21357991, 'chrome.dll!TabContents::CreateWithType+0x67 [ c:\\g\\trunk\\src\\chrome\\browser\\tab_contents_factory.cc:92 ]'], [20652484, 'chrome.dll!Browser::CreateTabContentsForURL+0xb4 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1349 ]'], [20651898, 'chrome.dll!Browser::AddTabWithURL+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1228 ]'], [20567357, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0xfd [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:540 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]']], 'thread': 3956, 'syscall': 4439, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserCreateWindowEx', 'done': 99.715187, 'ms': 99.146679000000006, 'syscallargs': [32, 1240616, 1239380], 'cpu': 3124053392},
+{'eventid': 1718479108, 'stacktrace': [[2088830549, 'kernel32.dll!CreateThread+0x1e'], [19417542, 'chrome.dll!PlatformThread::Create+0x36 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:83 ]'], [23799365, 'chrome.dll!base::Thread::StartWithOptions+0xb5 [ c:\\g\\trunk\\src\\base\\thread.cc:82 ]'], [23799735, 'chrome.dll!base::Thread::Start+0x17 [ c:\\g\\trunk\\src\\base\\thread.cc:72 ]'], [20506336, 'chrome.dll!BrowserProcessImpl::CreateDBThread+0x90 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:311 ]'], [20398633, 'chrome.dll!BrowserProcessImpl::db_thread+0x19 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.h:68 ]'], [20857407, 'chrome.dll!ProfileImpl::RequestContext::RequestContext+0x2ef [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:144 ]'], [20862571, 'chrome.dll!ProfileImpl::GetRequestContext+0x11b [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:739 ]'], [20852186, 'chrome.dll!ProfileImpl::InitializeSpellChecker+0xfa [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:929 ]'], [20852480, 'chrome.dll!ProfileImpl::GetSpellChecker+0x10 [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:960 ]'], [21339442, 'chrome.dll!RenderViewHost::CreateRenderView+0x82 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:123 ]'], [21021101, 'chrome.dll!WebContents::CreateRenderViewForRenderManager+0x2d [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:1367 ]'], [21556055, 'chrome.dll!RenderViewHostManager::Navigate+0x57 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:103 ]'], [21021786, 'chrome.dll!WebContents::NavigateToPendingEntry+0x1a [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:354 ]'], [21011780, 'chrome.dll!NavigationController::NavigateToPendingEntry+0x144 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:1040 ]'], [21012234, 'chrome.dll!NavigationController::LoadEntry+0x6a [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:276 ]']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 101.072622, 'cpu': 3124053392},
+{'stacktrace': [], 'thread': 1884, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718479108, 'startaddr': 19417280, 'ms': 101.217613, 'cpu': 2147742720},
+{'stacktrace': [[19417443, 'chrome.dll!PlatformThread::SetName+0x63 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:62 ]'], [23799603, 'chrome.dll!base::Thread::ThreadMain+0x53 [ c:\\g\\trunk\\src\\base\\thread.cc:145 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 1884, 'eventtype': 'EVENT_TYPE_THREADNAME', 'threadname': 'Chrome_DBThread', 'ms': 101.24918099999999, 'cpu': 2147742720},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19495803, 'chrome.dll!base::WaitableEvent::Wait+0x1b [ c:\\g\\trunk\\src\\base\\waitable_event_win.cc:42 ]'], [19485939, 'chrome.dll!base::MessagePumpDefault::Run+0xc3 [ c:\\g\\trunk\\src\\base\\message_pump_default.cc:43 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 1884, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 299.45342199999999, 'ms': 101.293041, 'syscallargs': [284, 0, 0], 'cpu': 2147742720},
+{'eventid': 1718482060, 'stacktrace': [[2088830549, 'kernel32.dll!CreateThread+0x1e'], [19417542, 'chrome.dll!PlatformThread::Create+0x36 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:83 ]'], [23799365, 'chrome.dll!base::Thread::StartWithOptions+0xb5 [ c:\\g\\trunk\\src\\base\\thread.cc:82 ]'], [23799735, 'chrome.dll!base::Thread::Start+0x17 [ c:\\g\\trunk\\src\\base\\thread.cc:72 ]'], [20811109, 'chrome.dll!SafeBrowsingService::Start+0xa5 [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_service.cc:61 ]'], [20812754, 'chrome.dll!SafeBrowsingService::Initialize+0x72 [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_service.cc:54 ]'], [20696885, 'chrome.dll!ResourceDispatcherHost::Initialize+0x75 [ c:\\g\\trunk\\src\\chrome\\browser\\resource_dispatcher_host.cc:1439 ]'], [20505550, 'chrome.dll!BrowserProcessImpl::CreateResourceDispatcherHost+0xae [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:263 ]'], [20398441, 'chrome.dll!BrowserProcessImpl::resource_dispatcher_host+0x19 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.h:40 ]'], [20390068, 'chrome.dll!RenderProcessHost::Init+0xa4 [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:223 ]'], [21339442, 'chrome.dll!RenderViewHost::CreateRenderView+0x82 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:123 ]'], [21021101, 'chrome.dll!WebContents::CreateRenderViewForRenderManager+0x2d [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:1367 ]'], [21556055, 'chrome.dll!RenderViewHostManager::Navigate+0x57 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:103 ]'], [21021786, 'chrome.dll!WebContents::NavigateToPendingEntry+0x1a [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:354 ]'], [21011780, 'chrome.dll!NavigationController::NavigateToPendingEntry+0x144 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:1040 ]'], [21012234, 'chrome.dll!NavigationController::LoadEntry+0x6a [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:276 ]']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 101.49222899999999, 'cpu': 3124053392},
+{'stacktrace': [], 'thread': 2136, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718482060, 'startaddr': 19417280, 'ms': 101.625765, 'cpu': 2147742720},
+{'stacktrace': [[19417443, 'chrome.dll!PlatformThread::SetName+0x63 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:62 ]'], [23799603, 'chrome.dll!base::Thread::ThreadMain+0x53 [ c:\\g\\trunk\\src\\base\\thread.cc:145 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2136, 'eventtype': 'EVENT_TYPE_THREADNAME', 'threadname': 'Chrome_SafeBrowsingThread', 'ms': 101.65426100000001, 'cpu': 2147742720},
+{'stacktrace': [[2011711194, 'RPCRT4.dll!NMP_Open+0x122'], [2011709069, 'RPCRT4.dll!OSF_CCONNECTION::TransOpen+0x5e'], [2011710455, 'RPCRT4.dll!OSF_CCONNECTION::OpenConnectionAndBind+0x98'], [2011710849, 'RPCRT4.dll!OSF_CCALL::BindToServer+0x88'], [2011710672, 'RPCRT4.dll!OSF_BINDING_HANDLE::AllocateCCall+0x4b04'], [2011691420, 'RPCRT4.dll!OSF_BINDING_HANDLE::NegotiateTransferSyntax+0x28'], [2011664833, 'RPCRT4.dll!I_RpcGetBufferWithObject+0x48'], [2011664888, 'RPCRT4.dll!I_RpcGetBuffer+0xf'], [2011666469, 'RPCRT4.dll!NdrGetBuffer+0x28'], [2012169739, 'RPCRT4.dll!NdrClientCall2+0x13b'], [2011045072, 'ADVAPI32.dll!LsarOpenPolicy2+0x1b'], [2011044946, 'ADVAPI32.dll!LsaOpenPolicy+0x43'], [2011053296, 'ADVAPI32.dll!InitializeSidLookupTable+0xef'], [2011049382, 'ADVAPI32.dll!LocalConvertStringSDToSD_Rev1+0x7a'], [2011049228, 'ADVAPI32.dll!ConvertStringSecurityDescriptorToSecurityDescriptorW+0x2e'], [19488210, 'chrome.dll!win_util::GetLogonSessionOnlyDACL+0x1a2 [ c:\\g\\trunk\\src\\base\\win_util.cc:227 ]']], 'thread': 3956, 'syscall': 224, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwSetInformationFile', 'done': 102.443746, 'ms': 102.131416, 'syscallargs': [340, 1236548, 1236564], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 103.014769, 'ms': 102.43620300000001, 'syscallargs': [1, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[19462999, 'chrome.dll!file_util::ReadFile+0x77 [ c:\\g\\trunk\\src\\base\\file_util_win.cc:508 ]'], [21425417, 'chrome.dll!SafeBrowsingDatabase::LoadBloomFilter+0xe9 [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_database.cc:81 ]'], [21806924, 'chrome.dll!SafeBrowsingDatabaseImpl::Init+0xfc [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_database_impl.cc:105 ]'], [20805565, 'chrome.dll!SafeBrowsingService::GetDatabase+0x16d [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_service.cc:381 ]'], [20807180, 'chrome.dll!SafeBrowsingService::OnDBInitialize+0x6c [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_service.cc:106 ]'], [19405904, 'chrome.dll!MessageLoop::RunTask+0x80 [ c:\\g\\trunk\\src\\base\\message_loop.cc:309 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19486017, 'chrome.dll!base::MessagePumpDefault::Run+0x111 [ c:\\g\\trunk\\src\\base\\message_pump_default.cc:50 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2136, 'syscall': 183, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtReadFile', 'done': 103.483823, 'ms': 102.872013, 'syscallargs': [340, 0, 0], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 103.86767, 'ms': 103.13768899999999, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118302493, 'USER32.dll!CreateDesktopW+0x42'], [20392388, 'chrome.dll!RenderProcessHost::Init+0x9b4 [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:374 ]'], [21339442, 'chrome.dll!RenderViewHost::CreateRenderView+0x82 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:123 ]'], [21021101, 'chrome.dll!WebContents::CreateRenderViewForRenderManager+0x2d [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:1367 ]'], [21556055, 'chrome.dll!RenderViewHostManager::Navigate+0x57 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:103 ]'], [21021786, 'chrome.dll!WebContents::NavigateToPendingEntry+0x1a [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:354 ]'], [21011780, 'chrome.dll!NavigationController::NavigateToPendingEntry+0x144 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:1040 ]'], [21012234, 'chrome.dll!NavigationController::LoadEntry+0x6a [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:276 ]'], [21013144, 'chrome.dll!NavigationController::LoadURL+0x28 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:520 ]'], [20652523, 'chrome.dll!Browser::CreateTabContentsForURL+0xdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1358 ]'], [20651898, 'chrome.dll!Browser::AddTabWithURL+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1228 ]'], [20567357, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0xfd [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:540 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]']], 'thread': 3956, 'syscall': 4436, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserCreateDesktop', 'done': 103.842527, 'ms': 103.254464, 'syscallargs': [1239256, 0, 0], 'cpu': 2147742720},
+{'stacktrace': [[19407956, 'chrome.dll!MessageLoop::PostTask+0x14 [ c:\\g\\trunk\\src\\base\\message_loop.cc:231 ]'], [20805662, 'chrome.dll!SafeBrowsingService::GetDatabase+0x1ce [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_service.cc:383 ]'], [20807180, 'chrome.dll!SafeBrowsingService::OnDBInitialize+0x6c [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_service.cc:106 ]'], [19405904, 'chrome.dll!MessageLoop::RunTask+0x80 [ c:\\g\\trunk\\src\\base\\message_loop.cc:309 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19486017, 'chrome.dll!base::MessagePumpDefault::Run+0x111 [ c:\\g\\trunk\\src\\base\\message_pump_default.cc:50 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2136, 'syscall': 4571, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserPostMessage', 'done': 103.852026, 'ms': 103.507289, 'syscallargs': [6685238, 1025, 13825696], 'cpu': 3124053392},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 115.36522100000001, 'ms': 103.633562, 'syscallargs': [4, 32505136, 1], 'cpu': 3124053392},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19495803, 'chrome.dll!base::WaitableEvent::Wait+0x1b [ c:\\g\\trunk\\src\\base\\waitable_event_win.cc:42 ]'], [19485939, 'chrome.dll!base::MessagePumpDefault::Run+0xc3 [ c:\\g\\trunk\\src\\base\\message_pump_default.cc:43 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2136, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 299.48722500000002, 'ms': 103.86012700000001, 'syscallargs': [292, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 118.02812900000001, 'ms': 104.123289, 'syscallargs': [2, 18348996, 1], 'cpu': 3124053392},
+{'eventid': 1718553012, 'stacktrace': [[2011134008, 'ADVAPI32.dll!CreateProcessAsUserW+0xc3'], [4226929, 'chrome.exe!sandbox::TargetProcess::Create+0xe1 [ c:\\g\\trunk\\src\\sandbox\\src\\target_process.cc:158 ]'], [4215094, 'chrome.exe!sandbox::BrokerServicesBase::SpawnTarget+0x146 [ c:\\g\\trunk\\src\\sandbox\\src\\broker_services.cc:262 ]'], [20393087, 'chrome.dll!RenderProcessHost::Init+0xc6f [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:400 ]'], [21339442, 'chrome.dll!RenderViewHost::CreateRenderView+0x82 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:123 ]'], [21021101, 'chrome.dll!WebContents::CreateRenderViewForRenderManager+0x2d [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:1367 ]'], [21556055, 'chrome.dll!RenderViewHostManager::Navigate+0x57 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:103 ]'], [21021786, 'chrome.dll!WebContents::NavigateToPendingEntry+0x1a [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:354 ]'], [21011780, 'chrome.dll!NavigationController::NavigateToPendingEntry+0x144 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:1040 ]'], [21012234, 'chrome.dll!NavigationController::LoadEntry+0x6a [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:276 ]'], [21013144, 'chrome.dll!NavigationController::LoadURL+0x28 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:520 ]'], [20652523, 'chrome.dll!Browser::CreateTabContentsForURL+0xdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1358 ]'], [20651898, 'chrome.dll!Browser::AddTabWithURL+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1228 ]'], [20567357, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0xfd [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:540 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830565, 'ms': 109.568395, 'cpu': 3124053392},
+{'stacktrace': [[2088869567, 'kernel32.dll!CreateProcessInternalW+0x9ac'], [2011134008, 'ADVAPI32.dll!CreateProcessAsUserW+0xc3'], [4226929, 'chrome.exe!sandbox::TargetProcess::Create+0xe1 [ c:\\g\\trunk\\src\\sandbox\\src\\target_process.cc:158 ]'], [4215094, 'chrome.exe!sandbox::BrokerServicesBase::SpawnTarget+0x146 [ c:\\g\\trunk\\src\\sandbox\\src\\broker_services.cc:262 ]'], [20393087, 'chrome.dll!RenderProcessHost::Init+0xc6f [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:400 ]'], [21339442, 'chrome.dll!RenderViewHost::CreateRenderView+0x82 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:123 ]'], [21021101, 'chrome.dll!WebContents::CreateRenderViewForRenderManager+0x2d [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:1367 ]'], [21556055, 'chrome.dll!RenderViewHostManager::Navigate+0x57 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:103 ]'], [21021786, 'chrome.dll!WebContents::NavigateToPendingEntry+0x1a [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:354 ]'], [21011780, 'chrome.dll!NavigationController::NavigateToPendingEntry+0x144 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:1040 ]'], [21012234, 'chrome.dll!NavigationController::LoadEntry+0x6a [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:276 ]'], [21013144, 'chrome.dll!NavigationController::LoadURL+0x28 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:520 ]'], [20652523, 'chrome.dll!Browser::CreateTabContentsForURL+0xdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1358 ]'], [20651898, 'chrome.dll!Browser::AddTabWithURL+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1228 ]'], [20567357, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0xfd [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:540 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]']], 'thread': 3956, 'syscall': 200, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtRequestWaitReplyPort', 'done': 112.819925, 'ms': 109.602198, 'syscallargs': [32, 1237344, 1237344], 'cpu': 3124053392},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 132.609871, 'ms': 115.64011600000001, 'syscallargs': [11, 32505136, 1], 'cpu': 2147742720},
+{'stacktrace': [[4216265, 'chrome.exe!sandbox::BrokerServicesBase::TargetEventsThread+0x1c9 [ c:\\g\\trunk\\src\\sandbox\\src\\broker_services.cc:151 ]'], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2428, 'syscall': 190, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwRemoveIoCompletion', 'waiting': 1, 'done': 304.12608299999999, 'ms': 115.711634, 'syscallargs': [168, 17039276, 17038976], 'cpu': 2147742720},
+{'stacktrace': [[20454796, 'chrome.dll!VisitedLinkMaster::ReadFromFile+0x2c [ c:\\g\\trunk\\src\\chrome\\browser\\visitedlink_master.cc:966 ]'], [20463804, 'chrome.dll!VisitedLinkMaster::InitFromFile+0x18c [ c:\\g\\trunk\\src\\chrome\\browser\\visitedlink_master.cc:577 ]'], [20464344, 'chrome.dll!VisitedLinkMaster::Init+0x8 [ c:\\g\\trunk\\src\\chrome\\browser\\visitedlink_master.cc:256 ]'], [20393352, 'chrome.dll!RenderProcessHost::Init+0xd78 [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:438 ]'], [21339442, 'chrome.dll!RenderViewHost::CreateRenderView+0x82 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:123 ]'], [21021101, 'chrome.dll!WebContents::CreateRenderViewForRenderManager+0x2d [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:1367 ]'], [21556055, 'chrome.dll!RenderViewHostManager::Navigate+0x57 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:103 ]'], [21021786, 'chrome.dll!WebContents::NavigateToPendingEntry+0x1a [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:354 ]'], [21011780, 'chrome.dll!NavigationController::NavigateToPendingEntry+0x144 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:1040 ]'], [21012234, 'chrome.dll!NavigationController::LoadEntry+0x6a [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:276 ]'], [21013144, 'chrome.dll!NavigationController::LoadURL+0x28 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:520 ]'], [20652523, 'chrome.dll!Browser::CreateTabContentsForURL+0xdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1358 ]'], [20651898, 'chrome.dll!Browser::AddTabWithURL+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1228 ]'], [20567357, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0xfd [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:540 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]']], 'thread': 3956, 'syscall': 183, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtReadFile', 'done': 116.641361, 'ms': 115.943507, 'syscallargs': [428, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 126.694035, 'ms': 118.164739, 'syscallargs': [2, 18348996, 1], 'cpu': 3124053392},
+{'stacktrace': [[2118254284, 'USER32.dll!_CreateWindowEx+0xb1'], [2118253656, 'USER32.dll!CreateWindowExW+0x33'], [21895768, 'chrome.dll!RenderWidgetHostViewWin::EnsureTooltip+0x58 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.cc:897 ]'], [21896123, 'chrome.dll!RenderWidgetHostViewWin::SetSize+0x3b [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.cc:140 ]'], [21021157, 'chrome.dll!WebContents::CreateRenderViewForRenderManager+0x65 [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:1374 ]'], [21556055, 'chrome.dll!RenderViewHostManager::Navigate+0x57 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:103 ]'], [21021786, 'chrome.dll!WebContents::NavigateToPendingEntry+0x1a [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:354 ]'], [21011780, 'chrome.dll!NavigationController::NavigateToPendingEntry+0x144 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:1040 ]'], [21012234, 'chrome.dll!NavigationController::LoadEntry+0x6a [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:276 ]'], [21013144, 'chrome.dll!NavigationController::LoadURL+0x28 [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:520 ]'], [20652523, 'chrome.dll!Browser::CreateTabContentsForURL+0xdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1358 ]'], [20651898, 'chrome.dll!Browser::AddTabWithURL+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1228 ]'], [20567357, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0xfd [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:540 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]']], 'thread': 3956, 'syscall': 4439, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserCreateWindowEx', 'done': 125.14244100000001, 'ms': 124.58874, 'syscallargs': [32, 1240148, 1238912], 'cpu': 2147742720},
+{'stacktrace': [[19469642, 'chrome.dll!base::MessagePumpForIO::ProcessNextObject+0xba [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:668 ]'], [19470272, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0x70 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:537 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 127.571521, 'ms': 126.896575, 'syscallargs': [1, 18349136, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 129.02449899999999, 'ms': 127.671254, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[27279557, 'chrome.dll!views::HWNDView::Attach+0x95 [ c:\\g\\trunk\\src\\chrome\\views\\hwnd_view.cc:46 ]'], [23096819, 'chrome.dll!TabContentsContainerView::SetTabContents+0xc3 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\tab_contents_container_view.cc:83 ]'], [23148817, 'chrome.dll!BrowserView2::TabSelectedAt+0x81 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:530 ]'], [21206163, 'chrome.dll!TabStripModel::ChangeSelectedContentsFrom+0xe3 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:585 ]'], [21208866, 'chrome.dll!TabStripModel::InsertTabContentsAt+0x142 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:103 ]'], [21209292, 'chrome.dll!TabStripModel::AddTabContents+0xac [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:378 ]'], [20651916, 'chrome.dll!Browser::AddTabWithURL+0x13c [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1232 ]'], [20567357, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0xfd [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:540 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4642, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetWindowPos', 'done': 129.14797799999999, 'ms': 128.71188900000001, 'syscallargs': [24969860, 0, 5], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 147.204184, 'ms': 129.097972, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2088925701, 'kernel32.dll!BasepCopyFileExW+0x3f2'], [2088926059, 'kernel32.dll!CopyFileExW+0x39'], [2088958097, 'kernel32.dll!CopyFileW+0x1e'], [19457905, 'chrome.dll!base::CopyFileW+0x41 [ c:\\g\\trunk\\src\\base\\file_util_win.cc:115 ]'], [19447294, 'chrome.dll!base::CopyFileW+0x2e [ c:\\g\\trunk\\src\\base\\file_util.cc:324 ]'], [21848115, 'chrome.dll!BookmarkStorageBackend::BookmarkStorageBackend+0xc3 [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_storage.cc:123 ]'], [21848622, 'chrome.dll!BookmarkStorage::BookmarkStorage+0x12e [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_storage.cc:41 ]'], [21452155, 'chrome.dll!BookmarkModel::Load+0xcb [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_model.cc:137 ]'], [20848903, 'chrome.dll!ProfileImpl::GetBookmarkModel+0x47 [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:853 ]'], [22957786, 'chrome.dll!BookmarkBarView::BookmarkBarView+0x13a [ c:\\g\\trunk\\src\\chrome\\browser\\views\\bookmark_bar_view.cc:692 ]'], [23141288, 'chrome.dll!BrowserView2::GetBookmarkBarView+0x48 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:444 ]'], [23147457, 'chrome.dll!BrowserView2::UpdateUIForContents+0x11 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:1020 ]'], [23148906, 'chrome.dll!BrowserView2::TabSelectedAt+0xda [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:538 ]'], [21206163, 'chrome.dll!TabStripModel::ChangeSelectedContentsFrom+0xe3 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:585 ]'], [21208866, 'chrome.dll!TabStripModel::InsertTabContentsAt+0x142 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:103 ]'], [21209292, 'chrome.dll!TabStripModel::AddTabContents+0xac [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:378 ]']], 'thread': 3956, 'syscall': 37, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtCreateFile', 'done': 132.690607, 'ms': 132.46627699999999, 'syscallargs': [1238200, 1074856064, 1237976], 'cpu': 2147742720},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 146.83514199999999, 'ms': 132.61238499999999, 'syscallargs': [12, 32505136, 1], 'cpu': 3124053392},
+{'stacktrace': [[19407956, 'chrome.dll!MessageLoop::PostTask+0x14 [ c:\\g\\trunk\\src\\base\\message_loop.cc:231 ]'], [21849655, 'chrome.dll!BookmarkStorage::LoadBookmarks+0x87 [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_storage.cc:53 ]'], [21452202, 'chrome.dll!BookmarkModel::Load+0xfa [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_model.cc:138 ]'], [20848903, 'chrome.dll!ProfileImpl::GetBookmarkModel+0x47 [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:853 ]'], [22957786, 'chrome.dll!BookmarkBarView::BookmarkBarView+0x13a [ c:\\g\\trunk\\src\\chrome\\browser\\views\\bookmark_bar_view.cc:692 ]'], [23141288, 'chrome.dll!BrowserView2::GetBookmarkBarView+0x48 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:444 ]'], [23147457, 'chrome.dll!BrowserView2::UpdateUIForContents+0x11 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:1020 ]'], [23148906, 'chrome.dll!BrowserView2::TabSelectedAt+0xda [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:538 ]'], [21206163, 'chrome.dll!TabStripModel::ChangeSelectedContentsFrom+0xe3 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:585 ]'], [21208866, 'chrome.dll!TabStripModel::InsertTabContentsAt+0x142 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:103 ]'], [21209292, 'chrome.dll!TabStripModel::AddTabContents+0xac [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:378 ]'], [20651916, 'chrome.dll!Browser::AddTabWithURL+0x13c [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:1232 ]'], [20567357, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0xfd [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:540 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]']], 'thread': 3956, 'syscall': 4571, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserPostMessage', 'done': 135.53007400000001, 'ms': 133.02305200000001, 'syscallargs': [8585726, 1025, 13802976], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19467175, 'chrome.dll!base::MessagePumpForUI::WaitForWork+0x27 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:408 ]'], [19470141, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0xbd [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:393 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2736, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 220.41153299999999, 'ms': 135.494316, 'syscallargs': [1, 15858672, 1], 'cpu': 3124053392},
+{'stacktrace': [[27112751, 'chrome.dll!views::Window::Show+0xf [ c:\\g\\trunk\\src\\chrome\\views\\window.cc:93 ]'], [23139435, 'chrome.dll!BrowserView2::Show+0x1b [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:304 ]'], [20641529, 'chrome.dll!Browser::ShowAndFit+0x29 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:335 ]'], [20567444, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0x154 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:544 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4651, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserShowWindow', 'done': 166.489037, 'ms': 135.654112, 'syscallargs': [9961988, 10, 13830668], 'cpu': 3124053392},
+{'stacktrace': [[27287730, 'chrome.dll!views::CustomFrameWindow::OnNCActivate+0x42 [ c:\\g\\trunk\\src\\chrome\\views\\custom_frame_window.cc:1068 ]'], [23138561, 'chrome.dll!OpaqueFrame::OnNCActivate+0x21 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\opaque_frame.cc:104 ]'], [27136100, 'chrome.dll!views::ContainerWin::_ProcessWindowMessage+0x6c4 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.h:214 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27112751, 'chrome.dll!views::Window::Show+0xf [ c:\\g\\trunk\\src\\chrome\\views\\window.cc:93 ]'], [23139435, 'chrome.dll!BrowserView2::Show+0x1b [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:304 ]']], 'thread': 3956, 'syscall': 4583, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserRedrawWindow', 'done': 164.93828099999999, 'ms': 137.03361699999999, 'syscallargs': [9961988, 1240560, 0], 'cpu': 2147742720},
+{'stacktrace': [[27139267, 'chrome.dll!views::ContainerWin::OnPaint+0x13 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:623 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27287730, 'chrome.dll!views::CustomFrameWindow::OnNCActivate+0x42 [ c:\\g\\trunk\\src\\chrome\\views\\custom_frame_window.cc:1068 ]'], [23138561, 'chrome.dll!OpaqueFrame::OnNCActivate+0x21 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\opaque_frame.cc:104 ]'], [27136100, 'chrome.dll!views::ContainerWin::_ProcessWindowMessage+0x6c4 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.h:214 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]']], 'thread': 3956, 'syscall': 4404, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserBeginPaint', 'done': 147.41705999999999, 'ms': 137.187827, 'syscallargs': [9961988, 1239308, 0], 'cpu': 2147742720},
+{'stacktrace': [[2011005211, 'ADVAPI32.dll!RegEnumValueW+0x9a'], [1960473629, 'USP10.dll!CacheFontLinkingData+0x1e1'], [1960474061, 'USP10.dll!IsFontRegLinked+0x21'], [1960477397, 'USP10.dll!LoadFont+0x165'], [1960464506, 'USP10.dll!FindOrCreateFaceCache+0x9c'], [1960466474, 'USP10.dll!FindOrCreateSizeCacheWithoutRealizationID+0xc7'], [1960467102, 'USP10.dll!FindOrCreateSizeCacheUsingRealizationID+0x5d'], [1960468147, 'USP10.dll!UpdateCache+0x2c'], [1960468379, 'USP10.dll!ScriptCheckCache+0x67'], [1960460694, 'USP10.dll!ScriptStringAnalyse+0x143'], [1654409458, 'LPK.DLL!LpkStringAnalyse+0xfd'], [1654408779, 'LPK.DLL!LpkCharsetDraw+0x2f3'], [1654395497, 'LPK.DLL!LpkDrawTextEx+0x34'], [2118444036, 'USER32.dll!DT_DrawStr+0x30249'], [2118246821, 'USER32.dll!DT_DrawJustifiedLine+0x31'], [2118248132, 'USER32.dll!AddEllipsisAndDrawLine+0x5d']], 'thread': 3956, 'syscall': 73, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtEnumerateValueKey', 'done': 143.77721199999999, 'ms': 142.97459599999999, 'syscallargs': [508, 1, 1], 'cpu': 2147742720},
+{'stacktrace': [[2012320926, 'GDI32.dll!CreateFontIndirectW+0x46'], [1960473724, 'USP10.dll!CacheFontLinkingData+0x240'], [1960474061, 'USP10.dll!IsFontRegLinked+0x21'], [1960477397, 'USP10.dll!LoadFont+0x165'], [1960464506, 'USP10.dll!FindOrCreateFaceCache+0x9c'], [1960466474, 'USP10.dll!FindOrCreateSizeCacheWithoutRealizationID+0xc7'], [1960467102, 'USP10.dll!FindOrCreateSizeCacheUsingRealizationID+0x5d'], [1960468147, 'USP10.dll!UpdateCache+0x2c'], [1960468379, 'USP10.dll!ScriptCheckCache+0x67'], [1960460694, 'USP10.dll!ScriptStringAnalyse+0x143'], [1654409458, 'LPK.DLL!LpkStringAnalyse+0xfd'], [1654408779, 'LPK.DLL!LpkCharsetDraw+0x2f3'], [1654395497, 'LPK.DLL!LpkDrawTextEx+0x34'], [2118444036, 'USER32.dll!DT_DrawStr+0x30249'], [2118246821, 'USER32.dll!DT_DrawJustifiedLine+0x31'], [2118248132, 'USER32.dll!AddEllipsisAndDrawLine+0x5d']], 'thread': 3956, 'syscall': 4314, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!NtGdiHfontCreate', 'done': 145.325174, 'ms': 143.78643099999999, 'syscallargs': [1233740, 356, 0], 'cpu': 2147742720},
+{'stacktrace': [[26995006, 'chrome.dll!gfx::BitmapPlatformDeviceWin::drawToHDC+0x9e [ c:\\g\\trunk\\src\\base\\gfx\\bitmap_platform_device_win.cc:378 ]'], [21604437, 'chrome.dll!gfx::CanvasPaintT<ChromeCanvas>::~CanvasPaintT<ChromeCanvas>+0x55 [ c:\\g\\trunk\\src\\base\\gfx\\platform_canvas_win.h:127 ]'], [27136650, 'chrome.dll!views::ContainerWin::_ProcessWindowMessage+0x8ea [ c:\\g\\trunk\\src\\chrome\\views\\container_win.h:224 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27139267, 'chrome.dll!views::ContainerWin::OnPaint+0x13 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:623 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]']], 'thread': 3956, 'syscall': 4109, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!NtGdiBitBlt', 'done': 146.987955, 'ms': 146.60997399999999, 'syscallargs': [771819156, 0, 0], 'cpu': 2147742720},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 214.033627, 'ms': 146.85358099999999, 'syscallargs': [12, 32505136, 1], 'cpu': 3124053392},
+{'stacktrace': [[26996791, 'chrome.dll!gfx::BitmapPlatformDeviceWin::~BitmapPlatformDeviceWin+0x37 [ c:\\g\\trunk\\src\\base\\gfx\\bitmap_platform_device_win.cc:328 ]'], [23980661, 'chrome.dll!DeviceCM::~DeviceCM+0x35 [ c:\\g\\trunk\\src\\skia\\sgl\\skcanvas.cpp:83 ]'], [23986073, 'chrome.dll!SkCanvas::~SkCanvas+0x29 [ c:\\g\\trunk\\src\\skia\\sgl\\skcanvas.cpp:410 ]'], [27136650, 'chrome.dll!views::ContainerWin::_ProcessWindowMessage+0x8ea [ c:\\g\\trunk\\src\\chrome\\views\\container_win.h:224 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27139267, 'chrome.dll!views::ContainerWin::OnPaint+0x13 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:623 ]']], 'thread': 3956, 'syscall': 4218, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!DeleteObject', 'done': 147.34358700000001, 'ms': 147.01589200000001, 'syscallargs': [2181367073, 14636032, 14636232], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 149.87212099999999, 'ms': 147.65116800000001, 'syscallargs': [2, 18348996, 1], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 155.44461699999999, 'ms': 149.96458999999999, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[26995006, 'chrome.dll!gfx::BitmapPlatformDeviceWin::drawToHDC+0x9e [ c:\\g\\trunk\\src\\base\\gfx\\bitmap_platform_device_win.cc:378 ]'], [21604437, 'chrome.dll!gfx::CanvasPaintT<ChromeCanvas>::~CanvasPaintT<ChromeCanvas>+0x55 [ c:\\g\\trunk\\src\\base\\gfx\\platform_canvas_win.h:127 ]'], [27139267, 'chrome.dll!views::ContainerWin::OnPaint+0x13 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:623 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27287730, 'chrome.dll!views::CustomFrameWindow::OnNCActivate+0x42 [ c:\\g\\trunk\\src\\chrome\\views\\custom_frame_window.cc:1068 ]'], [23138561, 'chrome.dll!OpaqueFrame::OnNCActivate+0x21 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\opaque_frame.cc:104 ]']], 'thread': 3956, 'syscall': 4109, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!NtGdiBitBlt', 'done': 153.59857199999999, 'ms': 153.273112, 'syscallargs': [771819156, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[26996791, 'chrome.dll!gfx::BitmapPlatformDeviceWin::~BitmapPlatformDeviceWin+0x37 [ c:\\g\\trunk\\src\\base\\gfx\\bitmap_platform_device_win.cc:328 ]'], [23980661, 'chrome.dll!DeviceCM::~DeviceCM+0x35 [ c:\\g\\trunk\\src\\skia\\sgl\\skcanvas.cpp:83 ]'], [23986073, 'chrome.dll!SkCanvas::~SkCanvas+0x29 [ c:\\g\\trunk\\src\\skia\\sgl\\skcanvas.cpp:410 ]'], [27139267, 'chrome.dll!views::ContainerWin::OnPaint+0x13 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:623 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27287730, 'chrome.dll!views::CustomFrameWindow::OnNCActivate+0x42 [ c:\\g\\trunk\\src\\chrome\\views\\custom_frame_window.cc:1068 ]']], 'thread': 3956, 'syscall': 4218, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!DeleteObject', 'done': 153.84329600000001, 'ms': 153.641594, 'syscallargs': [2198144289, 14636032, 14636144], 'cpu': 3124053392},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [20447362, 'chrome.dll!RenderWidgetHelper::WaitForPaintMsg+0x102 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_helper.cc:121 ]'], [21729909, 'chrome.dll!RenderWidgetHost::GetBackingStore+0x125 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:742 ]'], [21898819, 'chrome.dll!RenderWidgetHostViewWin::OnPaint+0xa3 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.cc:402 ]'], [21900924, 'chrome.dll!RenderWidgetHostViewWin::ProcessWindowMessage+0xbc [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.h:76 ]'], [21752349, 'chrome.dll!ATL::CWindowImplBaseT<ATL::CWindow,ATL::CWinTraits<1174405120,0> >::WindowProc+0x5d [ c:\\program files\\microsoft visual studio 8\\vc\\atlmfc\\include\\atlwin.h:3078 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13']], 'thread': 3956, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 158.746712, 'ms': 154.248096, 'syscallargs': [260, 0, 1238856], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 158.69866099999999, 'ms': 155.524236, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 162.17675700000001, 'ms': 158.787779, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[21721107, 'chrome.dll!RenderWidgetHost::BackingStore::Refresh+0x133 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:95 ]'], [21726483, 'chrome.dll!RenderWidgetHost::BackingStoreManager::PrepareBackingStore+0x103 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:197 ]'], [21726586, 'chrome.dll!RenderWidgetHost::PaintRect+0x5a [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:770 ]'], [21727344, 'chrome.dll!RenderWidgetHost::OnMsgPaintRect+0x250 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:379 ]'], [21728798, 'chrome.dll!IPC::MessageWithTuple<ViewHostMsg_PaintRect_Params>::Dispatch<RenderWidgetHost,void (__thiscall RenderWidgetHost::*)(ViewHostMs+0x3e [ c:\\g\\trunk\\src\\chrome\\common\\ipc_message_utils.h:990 ]'], [21729932, 'chrome.dll!RenderWidgetHost::GetBackingStore+0x13c [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:747 ]'], [21898819, 'chrome.dll!RenderWidgetHostViewWin::OnPaint+0xa3 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.cc:402 ]'], [21900924, 'chrome.dll!RenderWidgetHostViewWin::ProcessWindowMessage+0xbc [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.h:76 ]'], [21752349, 'chrome.dll!ATL::CWindowImplBaseT<ATL::CWindow,ATL::CWinTraits<1174405120,0> >::WindowProc+0x5d [ c:\\program files\\microsoft visual studio 8\\vc\\atlmfc\\include\\atlwin.h:3078 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7']], 'thread': 3956, 'syscall': 4389, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!NtGdiStretchDIBitsInternal', 'done': 161.89711299999999, 'ms': 158.891423, 'syscallargs': [3825272163, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[21721114, 'chrome.dll!RenderWidgetHost::BackingStore::Refresh+0x13a [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:96 ]'], [21726483, 'chrome.dll!RenderWidgetHost::BackingStoreManager::PrepareBackingStore+0x103 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:197 ]'], [21726586, 'chrome.dll!RenderWidgetHost::PaintRect+0x5a [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:770 ]'], [21727344, 'chrome.dll!RenderWidgetHost::OnMsgPaintRect+0x250 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:379 ]'], [21728798, 'chrome.dll!IPC::MessageWithTuple<ViewHostMsg_PaintRect_Params>::Dispatch<RenderWidgetHost,void (__thiscall RenderWidgetHost::*)(ViewHostMs+0x3e [ c:\\g\\trunk\\src\\chrome\\common\\ipc_message_utils.h:990 ]'], [21729932, 'chrome.dll!RenderWidgetHost::GetBackingStore+0x13c [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host.cc:747 ]'], [21898819, 'chrome.dll!RenderWidgetHostViewWin::OnPaint+0xa3 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.cc:402 ]'], [21900924, 'chrome.dll!RenderWidgetHostViewWin::ProcessWindowMessage+0xbc [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.h:76 ]'], [21752349, 'chrome.dll!ATL::CWindowImplBaseT<ATL::CWindow,ATL::CWinTraits<1174405120,0> >::WindowProc+0x5d [ c:\\program files\\microsoft visual studio 8\\vc\\atlmfc\\include\\atlwin.h:3078 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7']], 'thread': 3956, 'syscall': 267, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtUnmapViewOfSection', 'done': 162.12954400000001, 'ms': 161.902421, 'syscallargs': [4294967295, 43974656, 1239104], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 170.10988800000001, 'ms': 162.27425600000001, 'syscallargs': [2, 18348996, 1], 'cpu': 3124053392},
+{'stacktrace': [[21898949, 'chrome.dll!RenderWidgetHostViewWin::OnPaint+0x125 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.cc:424 ]'], [21900924, 'chrome.dll!RenderWidgetHostViewWin::ProcessWindowMessage+0xbc [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.h:76 ]'], [21752349, 'chrome.dll!ATL::CWindowImplBaseT<ATL::CWindow,ATL::CWinTraits<1174405120,0> >::WindowProc+0x5d [ c:\\program files\\microsoft visual studio 8\\vc\\atlmfc\\include\\atlwin.h:3078 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27287730, 'chrome.dll!views::CustomFrameWindow::OnNCActivate+0x42 [ c:\\g\\trunk\\src\\chrome\\views\\custom_frame_window.cc:1068 ]'], [23138561, 'chrome.dll!OpaqueFrame::OnNCActivate+0x21 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\opaque_frame.cc:104 ]'], [27136100, 'chrome.dll!views::ContainerWin::_ProcessWindowMessage+0x6c4 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.h:214 ]']], 'thread': 3956, 'syscall': 4109, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!NtGdiBitBlt', 'done': 164.14181099999999, 'ms': 162.369798, 'syscallargs': [3389065955, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[27151840, 'chrome.dll!views::FocusWindowCallback+0x130 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:175 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27112751, 'chrome.dll!views::Window::Show+0xf [ c:\\g\\trunk\\src\\chrome\\views\\window.cc:93 ]'], [23139435, 'chrome.dll!BrowserView2::Show+0x1b [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:304 ]'], [20641529, 'chrome.dll!Browser::ShowAndFit+0x29 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:335 ]'], [20567444, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0x154 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:544 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]']], 'thread': 3956, 'syscall': 4611, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetFocus', 'done': 166.26107500000001, 'ms': 164.97012899999999, 'syscallargs': [9961988, 9961988, 13872320], 'cpu': 3124053392},
+{'stacktrace': [[2118254284, 'USER32.dll!_CreateWindowEx+0xb1'], [2118253656, 'USER32.dll!CreateWindowExW+0x33'], [2118563099, 'USER32.dll!CreateIMEUI+0xa4'], [2118566246, 'USER32.dll!ImeSetContextHandler+0x40'], [2118567660, 'USER32.dll!ImeWndProcWorker+0x2f6'], [2118304721, 'USER32.dll!SendMessageWorker+0x10bfe'], [2118431811, 'USER32.dll!RealDefWindowProcWorker+0x3022c'], [2118235129, 'USER32.dll!RealDefWindowProcW+0x27'], [2118235027, 'USER32.dll!DefWindowProcW+0x57'], [27142877, 'chrome.dll!views::ContainerWin::WndProc+0xdd [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:918 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28']], 'thread': 3956, 'syscall': 4439, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserCreateWindowEx', 'done': 165.93449699999999, 'ms': 165.35397699999999, 'syscallargs': [0, 1238728, 1237492], 'cpu': 3124053392},
+{'stacktrace': [[27208659, 'chrome.dll!views::RootView::FocusView+0xe3 [ c:\\g\\trunk\\src\\chrome\\views\\root_view.cc:499 ]'], [27118902, 'chrome.dll!views::View::RequestFocus+0x16 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:1423 ]'], [23139435, 'chrome.dll!BrowserView2::Show+0x1b [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:304 ]'], [20641529, 'chrome.dll!Browser::ShowAndFit+0x29 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:335 ]'], [20567444, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0x154 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:544 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4611, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetFocus', 'done': 168.39933600000001, 'ms': 166.56362799999999, 'syscallargs': [8979080, 27145854, 13872320], 'cpu': 3124053392},
+{'stacktrace': [[20641581, 'chrome.dll!Browser::ShowAndFit+0x5d [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:351 ]'], [20567444, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0x154 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:544 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4611, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetFocus', 'done': 170.63230100000001, 'ms': 168.406599, 'syscallargs': [24969860, 21048886, 13857560], 'cpu': 3124053392},
+{'stacktrace': [[27208659, 'chrome.dll!views::RootView::FocusView+0xe3 [ c:\\g\\trunk\\src\\chrome\\views\\root_view.cc:499 ]'], [27146912, 'chrome.dll!views::FocusManager::OnSetFocus+0x40 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:273 ]'], [27151783, 'chrome.dll!views::FocusWindowCallback+0xf7 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:158 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [20641581, 'chrome.dll!Browser::ShowAndFit+0x5d [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:351 ]'], [20567444, 'chrome.dll!BrowserInit::LaunchWithProfile::OpenURLsInBrowser+0x154 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:544 ]'], [20570295, 'chrome.dll!BrowserInit::LaunchWithProfile::Launch+0x5d7 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:472 ]'], [20571326, 'chrome.dll!BrowserInit::LaunchBrowserImpl+0x2de [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:720 ]'], [20572818, 'chrome.dll!BrowserInit::ProcessCommandLine+0x522 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_init.cc:659 ]'], [20405083, 'chrome.dll!BrowserMain+0xfdb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:579 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]']], 'thread': 3956, 'syscall': 4611, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetFocus', 'done': 170.61889199999999, 'ms': 169.63636399999999, 'syscallargs': [9896426, 13833040, 27145854], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 170.620847, 'ms': 170.203755, 'syscallargs': [2, 18348996, 1], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 171.51900599999999, 'ms': 170.68761499999999, 'syscallargs': [2, 18348996, 1], 'cpu': 3124053392},
+{'stacktrace': [[2118226946, 'USER32.dll!PeekMessageW+0x167'], [19465953, 'chrome.dll!base::MessagePumpWin::ProcessPumpReplacementMessage+0x21 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:307 ]'], [19466558, 'chrome.dll!base::MessagePumpWin::ProcessMessageHelper+0x3e [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:280 ]'], [19470020, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x44 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:364 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19407817, 'chrome.dll!MessageLoop::RunInternal+0xa9 [ c:\\g\\trunk\\src\\base\\message_loop.cc:192 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19409081, 'chrome.dll!MessageLoopForUI::Run+0x49 [ c:\\g\\trunk\\src\\base\\message_loop.cc:559 ]'], [20405134, 'chrome.dll!BrowserMain+0x100e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:583 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4570, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!PeekMessageW', 'done': 171.181253, 'ms': 170.81500600000001, 'syscallargs': [1242820, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 181.74991499999999, 'ms': 171.734117, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[27201618, 'chrome.dll!views::RootView::PaintNow+0x42 [ c:\\g\\trunk\\src\\chrome\\views\\root_view.cc:183 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19407817, 'chrome.dll!MessageLoop::RunInternal+0xa9 [ c:\\g\\trunk\\src\\base\\message_loop.cc:192 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19409081, 'chrome.dll!MessageLoopForUI::Run+0x49 [ c:\\g\\trunk\\src\\base\\message_loop.cc:559 ]'], [20405134, 'chrome.dll!BrowserMain+0x100e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:583 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4583, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserRedrawWindow', 'done': 176.42074600000001, 'ms': 171.76652300000001, 'syscallargs': [9961988, 1242600, 0], 'cpu': 3124053392},
+{'stacktrace': [[21898949, 'chrome.dll!RenderWidgetHostViewWin::OnPaint+0x125 [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.cc:424 ]'], [21900924, 'chrome.dll!RenderWidgetHostViewWin::ProcessWindowMessage+0xbc [ c:\\g\\trunk\\src\\chrome\\browser\\render_widget_host_view_win.h:76 ]'], [21752349, 'chrome.dll!ATL::CWindowImplBaseT<ATL::CWindow,ATL::CWinTraits<1174405120,0> >::WindowProc+0x5d [ c:\\program files\\microsoft visual studio 8\\vc\\atlmfc\\include\\atlwin.h:3078 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [27201618, 'chrome.dll!views::RootView::PaintNow+0x42 [ c:\\g\\trunk\\src\\chrome\\views\\root_view.cc:183 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]']], 'thread': 3956, 'syscall': 4109, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!NtGdiBitBlt', 'done': 175.758092, 'ms': 174.02686700000001, 'syscallargs': [2231437465, 0, 0], 'cpu': 3124053392},
+{'eventid': 1718825704, 'stacktrace': [[2088830549, 'kernel32.dll!CreateThread+0x1e'], [19417542, 'chrome.dll!PlatformThread::Create+0x36 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:83 ]'], [23799365, 'chrome.dll!base::Thread::StartWithOptions+0xb5 [ c:\\g\\trunk\\src\\base\\thread.cc:82 ]'], [23799735, 'chrome.dll!base::Thread::Start+0x17 [ c:\\g\\trunk\\src\\base\\thread.cc:72 ]'], [20426734, 'chrome.dll!HistoryService::Init+0xe [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history.cc:128 ]'], [20850347, 'chrome.dll!ProfileImpl::GetHistoryService+0x6b [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:752 ]'], [21456458, 'chrome.dll!BookmarkModel::LoadFavIcon+0x7a [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_model.cc:685 ]'], [21457734, 'chrome.dll!BookmarkNode::GetFavIcon+0x16 [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_model.cc:46 ]'], [22945986, 'chrome.dll!BookmarkBarView::CreateBookmarkButton+0x152 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\bookmark_bar_view.cc:1486 ]'], [22951285, 'chrome.dll!BookmarkBarView::Loaded+0x95 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\bookmark_bar_view.cc:1210 ]'], [21458349, 'chrome.dll!BookmarkModel::DoneLoading+0x8d [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_model.cc:524 ]'], [21461574, 'chrome.dll!BookmarkModel::OnBookmarkStorageLoadedBookmarks+0x166 [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_model.cc:468 ]'], [21847663, 'chrome.dll!BookmarkStorage::LoadedBookmarks+0x2f [ c:\\g\\trunk\\src\\chrome\\browser\\bookmarks\\bookmark_storage.cc:90 ]'], [21847724, 'chrome.dll!RunnableMethod<BookmarkStorage,void (__thiscall BookmarkStorage::*)(Value *,bool,bool),Tuple3<Value *,bool,bool> >::Run+0x1c [ c:\\g\\trunk\\src\\base\\task.h:313 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]']], 'thread': 3956, 'eventtype': 'EVENT_TYPE_CREATETHREAD', 'startaddr': 2088830553, 'ms': 177.017191, 'cpu': 3124053392},
+{'stacktrace': [], 'thread': 2688, 'eventtype': 'EVENT_TYPE_THREADBEGIN', 'parenteventid': 1718825704, 'startaddr': 19417280, 'ms': 177.216937, 'cpu': 2147742720},
+{'stacktrace': [[19417443, 'chrome.dll!PlatformThread::SetName+0x63 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:62 ]'], [23799603, 'chrome.dll!base::Thread::ThreadMain+0x53 [ c:\\g\\trunk\\src\\base\\thread.cc:145 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2688, 'eventtype': 'EVENT_TYPE_THREADNAME', 'threadname': 'Chrome_HistoryThread', 'ms': 177.250461, 'cpu': 2147742720},
+{'stacktrace': [[27392208, 'chrome.dll!winRead+0x20 [ c:\\g\\trunk\\src\\third_party\\sqlite\\os_win.c:1003 ]'], [27524918, 'chrome.dll!sqlite3OsRead+0x16 [ c:\\g\\trunk\\src\\third_party\\sqlite\\os.c:39 ]'], [27491281, 'chrome.dll!sqlite3PagerLoadall+0x71 [ c:\\g\\trunk\\src\\third_party\\sqlite\\pager.c:4512 ]'], [27324147, 'chrome.dll!sqlite3Preload+0x33 [ c:\\g\\trunk\\src\\third_party\\sqlite\\build.c:3381 ]'], [21199165, 'chrome.dll!history::HistoryDatabase::PrimeCache+0x5d [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_database.cc:106 ]'], [21200727, 'chrome.dll!history::HistoryDatabase::Init+0x117 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_database.cc:71 ]'], [20616681, 'chrome.dll!history::HistoryBackend::InitImpl+0x1d9 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_backend.cc:508 ]'], [20622856, 'chrome.dll!history::HistoryBackend::Init+0x8 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_backend.cc:238 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19486017, 'chrome.dll!base::MessagePumpDefault::Run+0x111 [ c:\\g\\trunk\\src\\base\\message_pump_default.cc:50 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2688, 'syscall': 183, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtReadFile', 'done': 192.485637, 'ms': 178.359261, 'syscallargs': [512, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[21555953, 'chrome.dll!RenderViewHostManager::Shutdown+0xb1 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:84 ]'], [21036462, 'chrome.dll!WebContents::Destroy+0xee [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:312 ]'], [21008223, 'chrome.dll!NavigationController::Destroy+0x2df [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:458 ]'], [21208053, 'chrome.dll!TabStripModel::InternalCloseTabContentsAt+0x175 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:560 ]'], [20661873, 'chrome.dll!Browser::CloseContents+0xa1 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:810 ]'], [21019423, 'chrome.dll!WebContents::Close+0x1f [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:836 ]'], [21356349, 'chrome.dll!RenderViewHost::OnMessageReceived+0x1fd [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:616 ]'], [20394864, 'chrome.dll!RenderProcessHost::OnMessageReceived+0x170 [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:624 ]'], [21472487, 'chrome.dll!RunnableMethod<ProfileWriter,void (__thiscall ProfileWriter::*)(std::vector<history::URLRow,std::allocator<history::URLRow> > c+0x17 [ c:\\g\\trunk\\src\\base\\task.h:312 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19407817, 'chrome.dll!MessageLoop::RunInternal+0xa9 [ c:\\g\\trunk\\src\\base\\message_loop.cc:192 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19409081, 'chrome.dll!MessageLoopForUI::Run+0x49 [ c:\\g\\trunk\\src\\base\\message_loop.cc:559 ]'], [20405134, 'chrome.dll!BrowserMain+0x100e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:583 ]']], 'thread': 3956, 'syscall': 4451, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserDestroyWindow', 'done': 190.82481200000001, 'ms': 181.75131200000001, 'syscallargs': [9896426, 21722045, 14286272], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 182.32261399999999, 'ms': 181.84853100000001, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 182.77937600000001, 'ms': 182.413128, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 184.039592, 'ms': 182.86486099999999, 'syscallargs': [2, 18348996, 1], 'cpu': 3124053392},
+{'stacktrace': [[27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [21555953, 'chrome.dll!RenderViewHostManager::Shutdown+0xb1 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:84 ]'], [21036462, 'chrome.dll!WebContents::Destroy+0xee [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:312 ]'], [21008223, 'chrome.dll!NavigationController::Destroy+0x2df [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:458 ]'], [21208053, 'chrome.dll!TabStripModel::InternalCloseTabContentsAt+0x175 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:560 ]'], [20661873, 'chrome.dll!Browser::CloseContents+0xa1 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:810 ]']], 'thread': 3956, 'syscall': 4611, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetFocus', 'done': 184.892214, 'ms': 183.500696, 'syscallargs': [9896426, 14286908, 27137217], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 184.75420800000001, 'ms': 184.13038499999999, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 185.30260100000001, 'ms': 185.07575700000001, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 186.651376, 'ms': 185.397865, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [21555953, 'chrome.dll!RenderViewHostManager::Shutdown+0xb1 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:84 ]'], [21036462, 'chrome.dll!WebContents::Destroy+0xee [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:312 ]'], [21008223, 'chrome.dll!NavigationController::Destroy+0x2df [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:458 ]'], [21208053, 'chrome.dll!TabStripModel::InternalCloseTabContentsAt+0x175 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:560 ]'], [20661873, 'chrome.dll!Browser::CloseContents+0xa1 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:810 ]']], 'thread': 3956, 'syscall': 4611, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetFocus', 'done': 187.67385200000001, 'ms': 186.08454399999999, 'syscallargs': [9896426, 14286908, 27137217], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 187.526906, 'ms': 186.76451900000001, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 187.99735699999999, 'ms': 187.62943300000001, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 188.40103999999999, 'ms': 188.08507800000001, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 189.66041799999999, 'ms': 188.47507200000001, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [21555953, 'chrome.dll!RenderViewHostManager::Shutdown+0xb1 [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host_manager.cc:84 ]'], [21036462, 'chrome.dll!WebContents::Destroy+0xee [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:312 ]'], [21008223, 'chrome.dll!NavigationController::Destroy+0x2df [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:458 ]'], [21208053, 'chrome.dll!TabStripModel::InternalCloseTabContentsAt+0x175 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:560 ]'], [20661873, 'chrome.dll!Browser::CloseContents+0xa1 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:810 ]']], 'thread': 3956, 'syscall': 4611, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetFocus', 'done': 190.59852599999999, 'ms': 189.094424, 'syscallargs': [9896426, 14286908, 27137217], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 190.48985300000001, 'ms': 189.77244300000001, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 191.10529399999999, 'ms': 190.58735100000001, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 214.03893500000001, 'ms': 191.18016399999999, 'syscallargs': [2, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[23141617, 'chrome.dll!BrowserView2::TabDetachedAt+0x21 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:513 ]'], [21209929, 'chrome.dll!TabStripModel::DetachTabContentsAt+0x169 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:129 ]'], [21211607, 'chrome.dll!TabStripModel::Observe+0x77 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:522 ]'], [19680002, 'chrome.dll!NotificationService::Notify+0x2c2 [ c:\\g\\trunk\\src\\chrome\\common\\notification_service.cc:94 ]'], [21045731, 'chrome.dll!TabContents::Destroy+0x73 [ c:\\g\\trunk\\src\\chrome\\browser\\tab_contents.cc:93 ]'], [21036469, 'chrome.dll!WebContents::Destroy+0xf5 [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:312 ]'], [21008223, 'chrome.dll!NavigationController::Destroy+0x2df [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:458 ]'], [21208053, 'chrome.dll!TabStripModel::InternalCloseTabContentsAt+0x175 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:560 ]'], [20661873, 'chrome.dll!Browser::CloseContents+0xa1 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:810 ]'], [21019423, 'chrome.dll!WebContents::Close+0x1f [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:836 ]'], [21356349, 'chrome.dll!RenderViewHost::OnMessageReceived+0x1fd [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:616 ]'], [20394864, 'chrome.dll!RenderProcessHost::OnMessageReceived+0x170 [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:624 ]'], [21472487, 'chrome.dll!RunnableMethod<ProfileWriter,void (__thiscall ProfileWriter::*)(std::vector<history::URLRow,std::allocator<history::URLRow> > c+0x17 [ c:\\g\\trunk\\src\\base\\task.h:312 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]']], 'thread': 3956, 'syscall': 4651, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserShowWindow', 'done': 191.54417699999999, 'ms': 191.24218300000001, 'syscallargs': [24969860, 0, 13791504], 'cpu': 2147742720},
+{'stacktrace': [[23141617, 'chrome.dll!BrowserView2::TabDetachedAt+0x21 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:513 ]'], [21209929, 'chrome.dll!TabStripModel::DetachTabContentsAt+0x169 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:129 ]'], [21211607, 'chrome.dll!TabStripModel::Observe+0x77 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:522 ]'], [19680002, 'chrome.dll!NotificationService::Notify+0x2c2 [ c:\\g\\trunk\\src\\chrome\\common\\notification_service.cc:94 ]'], [21045731, 'chrome.dll!TabContents::Destroy+0x73 [ c:\\g\\trunk\\src\\chrome\\browser\\tab_contents.cc:93 ]'], [21036469, 'chrome.dll!WebContents::Destroy+0xf5 [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:312 ]'], [21008223, 'chrome.dll!NavigationController::Destroy+0x2df [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:458 ]'], [21208053, 'chrome.dll!TabStripModel::InternalCloseTabContentsAt+0x175 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:560 ]'], [20661873, 'chrome.dll!Browser::CloseContents+0xa1 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:810 ]'], [21019423, 'chrome.dll!WebContents::Close+0x1f [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:836 ]'], [21356349, 'chrome.dll!RenderViewHost::OnMessageReceived+0x1fd [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:616 ]'], [20394864, 'chrome.dll!RenderProcessHost::OnMessageReceived+0x170 [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:624 ]'], [21472487, 'chrome.dll!RunnableMethod<ProfileWriter,void (__thiscall ProfileWriter::*)(std::vector<history::URLRow,std::allocator<history::URLRow> > c+0x17 [ c:\\g\\trunk\\src\\base\\task.h:312 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]']], 'thread': 3956, 'syscall': 4625, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetParent', 'done': 191.86209400000001, 'ms': 191.546412, 'syscallargs': [24969860, 0, 13791504], 'cpu': 2147742720},
+{'stacktrace': [[2118236921, 'USER32.dll!GetPropW+0x1e'], [27148313, 'chrome.dll!views::FocusManager::GetFocusManager+0x69 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:228 ]'], [27117841, 'chrome.dll!views::View::GetFocusManager+0x21 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:299 ]'], [27129730, 'chrome.dll!views::View::PropagateRemoveNotifications+0xb2 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:665 ]'], [27129647, 'chrome.dll!views::View::PropagateRemoveNotifications+0x5f [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:660 ]'], [27130426, 'chrome.dll!views::View::DoRemoveChildView+0x10a [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:642 ]'], [27130610, 'chrome.dll!views::View::RemoveChildView+0x12 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:604 ]'], [23146904, 'chrome.dll!BrowserView2::UpdateChildViewAndLayout+0xb8 [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:1049 ]'], [23148971, 'chrome.dll!BrowserView2::TabStripEmpty+0x2b [ c:\\g\\trunk\\src\\chrome\\browser\\views\\frame\\browser_view2.cc:545 ]'], [21209949, 'chrome.dll!TabStripModel::DetachTabContentsAt+0x17d [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:130 ]'], [21211607, 'chrome.dll!TabStripModel::Observe+0x77 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:522 ]'], [19680002, 'chrome.dll!NotificationService::Notify+0x2c2 [ c:\\g\\trunk\\src\\chrome\\common\\notification_service.cc:94 ]'], [21045731, 'chrome.dll!TabContents::Destroy+0x73 [ c:\\g\\trunk\\src\\chrome\\browser\\tab_contents.cc:93 ]'], [21036469, 'chrome.dll!WebContents::Destroy+0xf5 [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:312 ]'], [21008223, 'chrome.dll!NavigationController::Destroy+0x2df [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:458 ]'], [21208053, 'chrome.dll!TabStripModel::InternalCloseTabContentsAt+0x175 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:560 ]']], 'thread': 3956, 'syscall': 4680, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserValidateHandleSecure', 'done': 206.04797500000001, 'ms': 193.17455200000001, 'syscallargs': [9961988, 1, 0], 'cpu': 2147742720},
+{'stacktrace': [[21036469, 'chrome.dll!WebContents::Destroy+0xf5 [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:312 ]'], [21008223, 'chrome.dll!NavigationController::Destroy+0x2df [ c:\\g\\trunk\\src\\chrome\\browser\\navigation_controller.cc:458 ]'], [21208053, 'chrome.dll!TabStripModel::InternalCloseTabContentsAt+0x175 [ c:\\g\\trunk\\src\\chrome\\browser\\tabs\\tab_strip_model.cc:560 ]'], [20661873, 'chrome.dll!Browser::CloseContents+0xa1 [ c:\\g\\trunk\\src\\chrome\\browser\\browser.cc:810 ]'], [21019423, 'chrome.dll!WebContents::Close+0x1f [ c:\\g\\trunk\\src\\chrome\\browser\\web_contents.cc:836 ]'], [21356349, 'chrome.dll!RenderViewHost::OnMessageReceived+0x1fd [ c:\\g\\trunk\\src\\chrome\\browser\\render_view_host.cc:616 ]'], [20394864, 'chrome.dll!RenderProcessHost::OnMessageReceived+0x170 [ c:\\g\\trunk\\src\\chrome\\browser\\render_process_host.cc:624 ]'], [21472487, 'chrome.dll!RunnableMethod<ProfileWriter,void (__thiscall ProfileWriter::*)(std::vector<history::URLRow,std::allocator<history::URLRow> > c+0x17 [ c:\\g\\trunk\\src\\base\\task.h:312 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19407817, 'chrome.dll!MessageLoop::RunInternal+0xa9 [ c:\\g\\trunk\\src\\base\\message_loop.cc:192 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19409081, 'chrome.dll!MessageLoopForUI::Run+0x49 [ c:\\g\\trunk\\src\\base\\message_loop.cc:559 ]'], [20405134, 'chrome.dll!BrowserMain+0x100e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:583 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]']], 'thread': 3956, 'syscall': 4451, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserDestroyWindow', 'done': 206.599163, 'ms': 206.26448300000001, 'syscallargs': [24969860, 14286184, 0], 'cpu': 2147742720},
+{'stacktrace': [[2118224400, 'USER32.dll!DispatchMessageW+0xf'], [27107759, 'chrome.dll!views::AcceleratorHandler::Dispatch+0x4f [ c:\\g\\trunk\\src\\chrome\\views\\accelerator_handler.cc:32 ]'], [19466592, 'chrome.dll!base::MessagePumpWin::ProcessMessageHelper+0x60 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:285 ]'], [19470020, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x44 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:364 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19407817, 'chrome.dll!MessageLoop::RunInternal+0xa9 [ c:\\g\\trunk\\src\\base\\message_loop.cc:192 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19409081, 'chrome.dll!MessageLoopForUI::Run+0x49 [ c:\\g\\trunk\\src\\base\\message_loop.cc:559 ]'], [20405134, 'chrome.dll!BrowserMain+0x100e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:583 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4453, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserDispatchMessage', 'done': 213.76627500000001, 'ms': 207.22298499999999, 'syscallargs': [1242896, 1242896, 1242896], 'cpu': 2147742720},
+{'stacktrace': [[26995006, 'chrome.dll!gfx::BitmapPlatformDeviceWin::drawToHDC+0x9e [ c:\\g\\trunk\\src\\base\\gfx\\bitmap_platform_device_win.cc:378 ]'], [21604437, 'chrome.dll!gfx::CanvasPaintT<ChromeCanvas>::~CanvasPaintT<ChromeCanvas>+0x55 [ c:\\g\\trunk\\src\\base\\gfx\\platform_canvas_win.h:127 ]'], [27139267, 'chrome.dll!views::ContainerWin::OnPaint+0x13 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:623 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [2118224400, 'USER32.dll!DispatchMessageW+0xf'], [27107759, 'chrome.dll!views::AcceleratorHandler::Dispatch+0x4f [ c:\\g\\trunk\\src\\chrome\\views\\accelerator_handler.cc:32 ]']], 'thread': 3956, 'syscall': 4109, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!NtGdiBitBlt', 'done': 211.82440800000001, 'ms': 209.57859199999999, 'syscallargs': [2231437465, 5, 79], 'cpu': 2147742720},
+{'stacktrace': [[26996791, 'chrome.dll!gfx::BitmapPlatformDeviceWin::~BitmapPlatformDeviceWin+0x37 [ c:\\g\\trunk\\src\\base\\gfx\\bitmap_platform_device_win.cc:328 ]'], [23980661, 'chrome.dll!DeviceCM::~DeviceCM+0x35 [ c:\\g\\trunk\\src\\skia\\sgl\\skcanvas.cpp:83 ]'], [23986073, 'chrome.dll!SkCanvas::~SkCanvas+0x29 [ c:\\g\\trunk\\src\\skia\\sgl\\skcanvas.cpp:410 ]'], [27139267, 'chrome.dll!views::ContainerWin::OnPaint+0x13 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:623 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151927, 'chrome.dll!views::FocusWindowCallback+0x187 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:187 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [2118224400, 'USER32.dll!DispatchMessageW+0xf']], 'thread': 3956, 'syscall': 4218, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'gdi32.dll!DeleteObject', 'done': 213.752027, 'ms': 211.89536699999999, 'syscallargs': [3875865955, 14288496, 14663680], 'cpu': 2147742720},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 214.63649699999999, 'ms': 214.08056099999999, 'syscallargs': [10, 32505136, 1], 'cpu': 3124053392},
+{'stacktrace': [[2089998945, 'ntdll.dll!RtlDeregisterWaitEx+0xe6'], [2088960121, 'kernel32.dll!UnregisterWaitEx+0x17'], [23815564, 'chrome.dll!base::ObjectWatcher::StopWatching+0x7c [ c:\\g\\trunk\\src\\base\\object_watcher.cc:84 ]'], [19696699, 'chrome.dll!IPC::SyncChannel::SyncContext::OnChannelClosed+0xb [ c:\\g\\trunk\\src\\chrome\\common\\ipc_sync_channel.cc:339 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470254, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0x5e [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:533 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 214.64711299999999, 'ms': 214.09145599999999, 'syscallargs': [2, 18348976, 1], 'cpu': 2147742720},
+{'stacktrace': [[27141588, 'chrome.dll!views::ContainerWin::Hide+0x14 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:350 ]'], [27116658, 'chrome.dll!views::Window::Close+0x32 [ c:\\g\\trunk\\src\\chrome\\views\\window.cc:130 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19407817, 'chrome.dll!MessageLoop::RunInternal+0xa9 [ c:\\g\\trunk\\src\\base\\message_loop.cc:192 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19409081, 'chrome.dll!MessageLoopForUI::Run+0x49 [ c:\\g\\trunk\\src\\base\\message_loop.cc:559 ]'], [20405134, 'chrome.dll!BrowserMain+0x100e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:583 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4642, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserSetWindowPos', 'done': 214.54654199999999, 'ms': 214.19063, 'syscallargs': [9961988, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[19405904, 'chrome.dll!MessageLoop::RunTask+0x80 [ c:\\g\\trunk\\src\\base\\message_loop.cc:309 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19407817, 'chrome.dll!MessageLoop::RunInternal+0xa9 [ c:\\g\\trunk\\src\\base\\message_loop.cc:192 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19409081, 'chrome.dll!MessageLoopForUI::Run+0x49 [ c:\\g\\trunk\\src\\base\\message_loop.cc:559 ]'], [20405134, 'chrome.dll!BrowserMain+0x100e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:583 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4451, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserDestroyWindow', 'done': 218.16459900000001, 'ms': 214.58872600000001, 'syscallargs': [9961988, 13966744, 0], 'cpu': 3124053392},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 220.37158400000001, 'ms': 214.64068800000001, 'syscallargs': [10, 32505136, 1], 'cpu': 3124053392},
+{'stacktrace': [[27117134, 'chrome.dll!views::Window::OnActivate+0xe [ c:\\g\\trunk\\src\\chrome\\views\\window.cc:364 ]'], [27134780, 'chrome.dll!views::ContainerWin::_ProcessWindowMessage+0x19c [ c:\\g\\trunk\\src\\chrome\\views\\container_win.h:184 ]'], [27142851, 'chrome.dll!views::ContainerWin::WndProc+0xc3 [ c:\\g\\trunk\\src\\chrome\\views\\container_win.cc:917 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118239807, 'USER32.dll!CallWindowProcAorW+0x51'], [2118239845, 'USER32.dll!CallWindowProcW+0x1b'], [27151819, 'chrome.dll!views::FocusWindowCallback+0x11b [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:173 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [19405904, 'chrome.dll!MessageLoop::RunTask+0x80 [ c:\\g\\trunk\\src\\base\\message_loop.cc:309 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]']], 'thread': 3956, 'syscall': 4536, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserGetWindowPlacement', 'done': 215.06532300000001, 'ms': 214.72868800000001, 'syscallargs': [9961988, 1241292, 13830668], 'cpu': 2147742720},
+{'stacktrace': [[2089816330, 'ntdll.dll!RtlLeaveCriticalSection+0x1d'], [22426797, 'chrome.dll!malloc+0x7a [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\malloc.c:163 ]']], 'thread': 2688, 'syscall': 220, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtSetEventBoostPriority', 'done': 215.099684, 'ms': 214.74600799999999, 'syscallargs': [264, 4248, 45021424], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 219.80195800000001, 'ms': 214.832053, 'syscallargs': [1, 18348996, 1], 'cpu': 2147742720},
+{'stacktrace': [[19407956, 'chrome.dll!MessageLoop::PostTask+0x14 [ c:\\g\\trunk\\src\\base\\message_loop.cc:231 ]'], [27201478, 'chrome.dll!views::RootView::SchedulePaint+0xb6 [ c:\\g\\trunk\\src\\chrome\\views\\root_view.cc:109 ]'], [27119984, 'chrome.dll!views::View::SchedulePaint+0x60 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:328 ]'], [27119984, 'chrome.dll!views::View::SchedulePaint+0x60 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:328 ]'], [27119984, 'chrome.dll!views::View::SchedulePaint+0x60 [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:328 ]'], [27117948, 'chrome.dll!views::View::SchedulePaint+0x2c [ c:\\g\\trunk\\src\\chrome\\views\\view.cc:333 ]'], [27151048, 'chrome.dll!views::FocusManager::OnPostActivate+0x48 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:405 ]'], [27151840, 'chrome.dll!views::FocusWindowCallback+0x130 [ c:\\g\\trunk\\src\\chrome\\views\\focus_manager.cc:175 ]'], [2118223668, 'USER32.dll!InternalCallWinProc+0x28'], [2118223894, 'USER32.dll!UserCallWinProcCheckWow+0xb7'], [2118235328, 'USER32.dll!DispatchClientMessage+0x4d'], [2118235404, 'USER32.dll!__fnDWORD+0x24'], [2089872099, 'ntdll.dll!KiUserCallbackDispatcher+0x13'], [19405904, 'chrome.dll!MessageLoop::RunTask+0x80 [ c:\\g\\trunk\\src\\base\\message_loop.cc:309 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470042, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0x5a [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:369 ]']], 'thread': 3956, 'syscall': 4571, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserPostMessage', 'done': 215.729094, 'ms': 215.09437700000001, 'syscallargs': [9437720, 1025, 13662856], 'cpu': 2147742720},
+{'stacktrace': [[2089910840, 'ntdll.dll!RtlpExtendHeap+0x88'], [2089884790, 'ntdll.dll!RtlAllocateHeap+0x16a2'], [22426797, 'chrome.dll!malloc+0x7a [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\malloc.c:163 ]']], 'thread': 2688, 'syscall': 17, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtAllocateVirtualMemory', 'done': 216.601551, 'ms': 215.89811, 'syscallargs': [4294967295, 45020820, 0], 'cpu': 2147742720},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'eventtype': 'EVENT_TYPE_APC', 'func_addr_name': 'ntdll.dll!RtlpDeregisterWait+0x0', 'ret_addr': 2089872071, 'done': 220.35901200000001, 'func_addr': 2089998983, 'ms': 217.798351, 'cpu': 3124053392},
+{'stacktrace': [[2089999079, 'ntdll.dll!RtlpDeregisterWait+0x60'], [1717963930, 'failed'], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 219, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtSetEvent', 'done': 220.35677699999999, 'ms': 217.836904, 'syscallargs': [256, 0, 1465296], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19469071, 'chrome.dll!base::MessagePumpForIO::WaitForWork+0x18f [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:613 ]'], [19470371, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0xd3 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:562 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 285.42538200000001, 'ms': 219.85503700000001, 'syscallargs': [1, 18348996, 1], 'cpu': 3124053392},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 302.48732699999999, 'ms': 220.374098, 'syscallargs': [9, 32505136, 1], 'cpu': 3124053392},
+{'stacktrace': [[2089911260, 'ntdll.dll!RtlpDeCommitFreeBlock+0x672c'], [2089881290, 'ntdll.dll!RtlFreeHeap+0xa8d'], [22426564, 'chrome.dll!free+0x6e [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\free.c:110 ]'], [27028667, 'chrome.dll!PrefService::SavePersistentPrefs+0x15b [ c:\\g\\trunk\\src\\chrome\\common\\pref_service.cc:209 ]'], [20562380, 'chrome.dll!browser_shutdown::Shutdown+0x11c [ c:\\g\\trunk\\src\\chrome\\browser\\browser_shutdown.cc:118 ]'], [20405156, 'chrome.dll!BrowserMain+0x1024 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:604 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 83, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtFreeVirtualMemory', 'done': 221.13285300000001, 'ms': 220.45483400000001, 'syscallargs': [4294967295, 1242484, 1242488], 'cpu': 2147742720},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19467175, 'chrome.dll!base::MessagePumpForUI::WaitForWork+0x27 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:408 ]'], [19470141, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0xbd [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:393 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2736, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 287.21471600000001, 'ms': 221.18006600000001, 'syscallargs': [1, 15858672, 1], 'cpu': 3124053392},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19417840, 'chrome.dll!PlatformThread::Join+0x60 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:94 ]'], [23799942, 'chrome.dll!base::Thread::Stop+0xc6 [ c:\\g\\trunk\\src\\base\\thread.cc:112 ]'], [23800270, 'chrome.dll!base::Thread::~Thread+0xe [ c:\\g\\trunk\\src\\base\\thread.cc:45 ]'], [20409619, 'chrome.dll!HistoryService::Cleanup+0xc3 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history.cc:174 ]'], [20855337, 'chrome.dll!ProfileImpl::~ProfileImpl+0xc9 [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:605 ]'], [20856251, "chrome.dll!ProfileImpl::`scalar deleting destructor'+0xb"], [20599735, 'chrome.dll!ProfileManager::~ProfileManager+0x67 [ c:\\g\\trunk\\src\\chrome\\browser\\profile_manager.cc:47 ]'], [20600411, "chrome.dll!ProfileManager::`scalar deleting destructor'+0xb"], [20507748, 'chrome.dll!BrowserProcessImpl::~BrowserProcessImpl+0x64 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:154 ]'], [20508459, "chrome.dll!BrowserProcessImpl::`scalar deleting destructor'+0xb"], [20562398, 'chrome.dll!browser_shutdown::Shutdown+0x12e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_shutdown.cc:119 ]'], [20405156, 'chrome.dll!BrowserMain+0x1024 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:604 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]']], 'thread': 3956, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 285.39185800000001, 'ms': 221.208282, 'syscallargs': [516, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[2088803065, 'kernel32.dll!VirtualFree+0x15'], [27491400, 'chrome.dll!sqlite3PagerLoadall+0xe8 [ c:\\g\\trunk\\src\\third_party\\sqlite\\pager.c:4532 ]'], [27324147, 'chrome.dll!sqlite3Preload+0x33 [ c:\\g\\trunk\\src\\third_party\\sqlite\\build.c:3381 ]'], [21199165, 'chrome.dll!history::HistoryDatabase::PrimeCache+0x5d [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_database.cc:106 ]'], [21200727, 'chrome.dll!history::HistoryDatabase::Init+0x117 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_database.cc:71 ]'], [20616681, 'chrome.dll!history::HistoryBackend::InitImpl+0x1d9 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_backend.cc:508 ]'], [20622856, 'chrome.dll!history::HistoryBackend::Init+0x8 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_backend.cc:238 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19486017, 'chrome.dll!base::MessagePumpDefault::Run+0x111 [ c:\\g\\trunk\\src\\base\\message_pump_default.cc:50 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2688, 'syscall': 83, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtFreeVirtualMemory', 'done': 227.42667, 'ms': 226.69361599999999, 'syscallargs': [4294967295, 45021524, 45021528], 'cpu': 2147742720},
+{'stacktrace': [[27392208, 'chrome.dll!winRead+0x20 [ c:\\g\\trunk\\src\\third_party\\sqlite\\os_win.c:1003 ]'], [27524918, 'chrome.dll!sqlite3OsRead+0x16 [ c:\\g\\trunk\\src\\third_party\\sqlite\\os.c:39 ]'], [27484071, 'chrome.dll!readDbPage+0x37 [ c:\\g\\trunk\\src\\third_party\\sqlite\\pager.c:2811 ]'], [27491450, 'chrome.dll!sqlite3PagerAcquire+0x1a [ c:\\g\\trunk\\src\\third_party\\sqlite\\pager.c:3113 ]'], [27352637, 'chrome.dll!sqlite3BtreeGetPage+0x1d [ c:\\g\\trunk\\src\\third_party\\sqlite\\btree.c:938 ]'], [27358074, 'chrome.dll!moveToChild+0x2a [ c:\\g\\trunk\\src\\third_party\\sqlite\\btree.c:2971 ]'], [27358534, 'chrome.dll!moveToLeftmost+0x36 [ c:\\g\\trunk\\src\\third_party\\sqlite\\btree.c:3086 ]'], [27516795, 'chrome.dll!sqlite3VdbeExec+0x318b [ c:\\g\\trunk\\src\\third_party\\sqlite\\vdbe.c:3838 ]'], [27336190, 'chrome.dll!sqlite3Step+0x11e [ c:\\g\\trunk\\src\\third_party\\sqlite\\vdbeapi.c:247 ]'], [27336432, 'chrome.dll!sqlite3_step+0x10 [ c:\\g\\trunk\\src\\third_party\\sqlite\\vdbeapi.c:303 ]'], [27314864, 'chrome.dll!sqlite3_exec+0xb0 [ c:\\g\\trunk\\src\\third_party\\sqlite\\legacy.c:76 ]'], [21366866, 'chrome.dll!history::InMemoryDatabase::InitFromDisk+0x162 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\in_memory_database.cc:82 ]'], [20617111, 'chrome.dll!history::HistoryBackend::InitImpl+0x387 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_backend.cc:528 ]'], [20622856, 'chrome.dll!history::HistoryBackend::Init+0x8 [ c:\\g\\trunk\\src\\chrome\\browser\\history\\history_backend.cc:238 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19486017, 'chrome.dll!base::MessagePumpDefault::Run+0x111 [ c:\\g\\trunk\\src\\base\\message_pump_default.cc:50 ]']], 'thread': 2688, 'syscall': 183, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtReadFile', 'done': 257.96155700000003, 'ms': 257.69392499999998, 'syscallargs': [272, 0, 0], 'cpu': 2147742720},
+{'thread': 2688, 'eventtype': 'EVENT_TYPE_THREADEXIT', 'cpu': 2147742720, 'ms': 284.95968099999999, 'stacktrace': [[2088810121, 'kernel32.dll!BaseThreadStart+0x3d']]},
+{'stacktrace': [[19407956, 'chrome.dll!MessageLoop::PostTask+0x14 [ c:\\g\\trunk\\src\\base\\message_loop.cc:231 ]'], [20855572, 'chrome.dll!ProfileImpl::~ProfileImpl+0x1b4 [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:621 ]'], [20856251, "chrome.dll!ProfileImpl::`scalar deleting destructor'+0xb"], [20599735, 'chrome.dll!ProfileManager::~ProfileManager+0x67 [ c:\\g\\trunk\\src\\chrome\\browser\\profile_manager.cc:47 ]'], [20600411, "chrome.dll!ProfileManager::`scalar deleting destructor'+0xb"], [20507748, 'chrome.dll!BrowserProcessImpl::~BrowserProcessImpl+0x64 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:154 ]'], [20508459, "chrome.dll!BrowserProcessImpl::`scalar deleting destructor'+0xb"], [20562398, 'chrome.dll!browser_shutdown::Shutdown+0x12e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_shutdown.cc:119 ]'], [20405156, 'chrome.dll!BrowserMain+0x1024 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:604 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4571, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserPostMessage', 'done': 286.96077300000002, 'ms': 285.515897, 'syscallargs': [6685238, 1025, 13825696], 'cpu': 2147742720},
+{'stacktrace': [[19407956, 'chrome.dll!MessageLoop::PostTask+0x14 [ c:\\g\\trunk\\src\\base\\message_loop.cc:231 ]'], [27028623, 'chrome.dll!PrefService::SavePersistentPrefs+0x12f [ c:\\g\\trunk\\src\\chrome\\common\\pref_service.cc:204 ]'], [20855685, 'chrome.dll!ProfileImpl::~ProfileImpl+0x225 [ c:\\g\\trunk\\src\\chrome\\browser\\profile.cc:633 ]'], [20856251, "chrome.dll!ProfileImpl::`scalar deleting destructor'+0xb"], [20599735, 'chrome.dll!ProfileManager::~ProfileManager+0x67 [ c:\\g\\trunk\\src\\chrome\\browser\\profile_manager.cc:47 ]'], [20600411, "chrome.dll!ProfileManager::`scalar deleting destructor'+0xb"], [20507748, 'chrome.dll!BrowserProcessImpl::~BrowserProcessImpl+0x64 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:154 ]'], [20508459, "chrome.dll!BrowserProcessImpl::`scalar deleting destructor'+0xb"], [20562398, 'chrome.dll!browser_shutdown::Shutdown+0x12e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_shutdown.cc:119 ]'], [20405156, 'chrome.dll!BrowserMain+0x1024 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:604 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 4571, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'user32.dll!NtUserPostMessage', 'done': 287.78713499999998, 'ms': 287.20828999999998, 'syscallargs': [8585726, 1025, 13802976], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19467175, 'chrome.dll!base::MessagePumpForUI::WaitForWork+0x27 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:408 ]'], [19470141, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0xbd [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:393 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2736, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 287.99358599999999, 'ms': 287.77847500000001, 'syscallargs': [1, 15858672, 1], 'cpu': 3124053392},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19417840, 'chrome.dll!PlatformThread::Join+0x60 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:94 ]'], [23799942, 'chrome.dll!base::Thread::Stop+0xc6 [ c:\\g\\trunk\\src\\base\\thread.cc:112 ]'], [20503505, "chrome.dll!`anonymous namespace'::BrowserProcessSubThread::`scalar deleting destructor'+0x11"], [20507877, 'chrome.dll!BrowserProcessImpl::~BrowserProcessImpl+0xe5 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:172 ]'], [20508459, "chrome.dll!BrowserProcessImpl::`scalar deleting destructor'+0xb"], [20562398, 'chrome.dll!browser_shutdown::Shutdown+0x12e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_shutdown.cc:119 ]'], [20405156, 'chrome.dll!BrowserMain+0x1024 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:604 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 300.546019, 'ms': 287.99023299999999, 'syscallargs': [196, 0, 0], 'cpu': 3124053392},
+{'stacktrace': [[2118227449, 'USER32.dll!RealMsgWaitForMultipleObjectsEx+0xd9'], [19467175, 'chrome.dll!base::MessagePumpForUI::WaitForWork+0x27 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:408 ]'], [19470141, 'chrome.dll!base::MessagePumpForUI::DoRunLoop+0xbd [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:393 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 2736, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 300.57563199999998, 'ms': 288.06845600000003, 'syscallargs': [1, 15858672, 1], 'cpu': 3124053392},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19417840, 'chrome.dll!PlatformThread::Join+0x60 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:94 ]'], [23799942, 'chrome.dll!base::Thread::Stop+0xc6 [ c:\\g\\trunk\\src\\base\\thread.cc:112 ]'], [23800337, "chrome.dll!base::Thread::`scalar deleting destructor'+0x11"], [20807416, 'chrome.dll!SafeBrowsingService::OnIOShutdown+0xd8 [ c:\\g\\trunk\\src\\chrome\\browser\\safe_browsing\\safe_browsing_service.cc:124 ]'], [19405904, 'chrome.dll!MessageLoop::RunTask+0x80 [ c:\\g\\trunk\\src\\base\\message_loop.cc:309 ]'], [19408986, 'chrome.dll!MessageLoop::DoWork+0x1ea [ c:\\g\\trunk\\src\\base\\message_loop.cc:416 ]'], [19470254, 'chrome.dll!base::MessagePumpForIO::DoRunLoop+0x5e [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:533 ]'], [19464514, 'chrome.dll!base::MessagePumpWin::RunWithDispatcher+0x42 [ c:\\g\\trunk\\src\\base\\message_pump_win.cc:134 ]'], [19397518, 'chrome.dll!base::MessagePumpWin::Run+0xe [ c:\\g\\trunk\\src\\base\\message_pump_win.h:124 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 708, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 300.18396200000001, 'ms': 299.48918099999997, 'syscallargs': [288, 0, 0], 'cpu': 2147742720},
+{'thread': 2136, 'eventtype': 'EVENT_TYPE_THREADEXIT', 'cpu': 3124053392, 'ms': 299.871352, 'stacktrace': [[2088810121, 'kernel32.dll!BaseThreadStart+0x3d']]},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19495803, 'chrome.dll!base::WaitableEvent::Wait+0x1b [ c:\\g\\trunk\\src\\base\\waitable_event_win.cc:42 ]'], [19485939, 'chrome.dll!base::MessagePumpDefault::Run+0xc3 [ c:\\g\\trunk\\src\\base\\message_pump_default.cc:43 ]'], [19407831, 'chrome.dll!MessageLoop::RunInternal+0xb7 [ c:\\g\\trunk\\src\\base\\message_loop.cc:197 ]'], [19408240, 'chrome.dll!MessageLoop::RunHandler+0xa0 [ c:\\g\\trunk\\src\\base\\message_loop.cc:181 ]'], [19410461, 'chrome.dll!MessageLoop::Run+0x3d [ c:\\g\\trunk\\src\\base\\message_loop.cc:155 ]'], [23799658, 'chrome.dll!base::Thread::ThreadMain+0x8a [ c:\\g\\trunk\\src\\base\\thread.cc:159 ]'], [19417293, "chrome.dll!`anonymous namespace'::ThreadFunc+0xd [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:27 ]"], [2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 1884, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 301.27013299999999, 'ms': 299.88085100000001, 'syscallargs': [284, 0, 0], 'cpu': 2147742720},
+{'thread': 708, 'eventtype': 'EVENT_TYPE_THREADEXIT', 'cpu': 3124053392, 'ms': 300.33398099999999, 'stacktrace': [[2088810121, 'kernel32.dll!BaseThreadStart+0x3d']]},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19417840, 'chrome.dll!PlatformThread::Join+0x60 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:94 ]'], [23799942, 'chrome.dll!base::Thread::Stop+0xc6 [ c:\\g\\trunk\\src\\base\\thread.cc:112 ]'], [20503505, "chrome.dll!`anonymous namespace'::BrowserProcessSubThread::`scalar deleting destructor'+0x11"], [20507946, 'chrome.dll!BrowserProcessImpl::~BrowserProcessImpl+0x12a [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:183 ]'], [20508459, "chrome.dll!BrowserProcessImpl::`scalar deleting destructor'+0xb"], [20562398, 'chrome.dll!browser_shutdown::Shutdown+0x12e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_shutdown.cc:119 ]'], [20405156, 'chrome.dll!BrowserMain+0x1024 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:604 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 300.95026000000001, 'ms': 300.57758699999999, 'syscallargs': [156, 0, 0], 'cpu': 2147742720},
+{'thread': 2736, 'eventtype': 'EVENT_TYPE_THREADEXIT', 'cpu': 3124053392, 'ms': 300.73039999999997, 'stacktrace': [[2088810121, 'kernel32.dll!BaseThreadStart+0x3d']]},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [19417840, 'chrome.dll!PlatformThread::Join+0x60 [ c:\\g\\trunk\\src\\base\\platform_thread_win.cc:94 ]'], [23799942, 'chrome.dll!base::Thread::Stop+0xc6 [ c:\\g\\trunk\\src\\base\\thread.cc:112 ]'], [20503505, "chrome.dll!`anonymous namespace'::BrowserProcessSubThread::`scalar deleting destructor'+0x11"], [20508363, 'chrome.dll!BrowserProcessImpl::~BrowserProcessImpl+0x2cb [ c:\\g\\trunk\\src\\chrome\\browser\\browser_process_impl.cc:203 ]'], [20508459, "chrome.dll!BrowserProcessImpl::`scalar deleting destructor'+0xb"], [20562398, 'chrome.dll!browser_shutdown::Shutdown+0x12e [ c:\\g\\trunk\\src\\chrome\\browser\\browser_shutdown.cc:119 ]'], [20405156, 'chrome.dll!BrowserMain+0x1024 [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:604 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 301.49865399999999, 'ms': 301.267899, 'syscallargs': [280, 0, 0], 'cpu': 2147742720},
+{'thread': 1884, 'eventtype': 'EVENT_TYPE_THREADEXIT', 'cpu': 3124053392, 'ms': 301.33801899999997, 'stacktrace': [[2088810121, 'kernel32.dll!BaseThreadStart+0x3d']]},
+{'stacktrace': [[2088804469, 'kernel32.dll!WaitForMultipleObjects+0x18'], [20822595, 'chrome.dll!chrome_browser_net::DnsMaster::ShutdownSlaves+0x243 [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_master.cc:358 ]'], [20522695, 'chrome.dll!chrome_browser_net::ShutdownDnsPrefetch+0x77 [ c:\\g\\trunk\\src\\chrome\\browser\\net\\dns_global.cc:372 ]'], [20405195, 'chrome.dll!BrowserMain+0x104b [ c:\\g\\trunk\\src\\chrome\\browser\\browser_main.cc:604 ]'], [19354554, 'chrome.dll!ChromeMain+0x83a [ c:\\g\\trunk\\src\\chrome\\app\\chrome_dll_main.cc:224 ]'], [4205604, 'chrome.exe!wWinMain+0x304 [ c:\\g\\trunk\\src\\chrome\\app\\chrome_exe_main.cc:103 ]'], [4482934, 'chrome.exe!__tmainCRTStartup+0x176 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c:324 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 302.38675599999999, 'ms': 302.15851500000002, 'syscallargs': [1, 1242668, 0], 'cpu': 3124053392},
+{'thread': 2812, 'eventtype': 'EVENT_TYPE_THREADEXIT', 'cpu': 2147742720, 'ms': 302.17639400000002, 'stacktrace': [[2088810121, 'kernel32.dll!BaseThreadStart+0x3d']]},
+{'stacktrace': [[2088810115, 'kernel32.dll!BaseThreadStart+0x37']], 'thread': 3500, 'syscall': 270, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!NtWaitForMultipleObjects', 'waiting': 1, 'done': 324.76809200000002, 'ms': 302.48956199999998, 'syscallargs': [8, 32505136, 1], 'cpu': 3124053392},
+{'thread': 2428, 'eventtype': 'EVENT_TYPE_THREADEXIT', 'cpu': 3124053392, 'ms': 304.13334700000001, 'stacktrace': [[2088810121, 'kernel32.dll!BaseThreadStart+0x3d']]},
+{'stacktrace': [[2088772914, 'kernel32.dll!WaitForSingleObject+0x12'], [4226553, 'chrome.exe!sandbox::TargetProcess::~TargetProcess+0x19 [ c:\\g\\trunk\\src\\sandbox\\src\\target_process.cc:103 ]'], [4228125, 'chrome.exe!sandbox::PolicyBase::OnJobEmpty+0xdd [ c:\\g\\trunk\\src\\sandbox\\src\\sandbox_policy_base.cc:171 ]'], [4215782, 'chrome.exe!sandbox::BrokerServicesBase::FreeResources+0xc6 [ c:\\g\\trunk\\src\\sandbox\\src\\broker_services.cc:124 ]'], [4216698, 'chrome.exe!sandbox::BrokerServicesBase::~BrokerServicesBase+0xfa [ c:\\g\\trunk\\src\\sandbox\\src\\broker_services.cc:101 ]'], [4212403, 'chrome.exe!sandbox::SingletonBase<sandbox::BrokerServicesBase>::OnExit+0x13 [ c:\\g\\trunk\\src\\sandbox\\src\\win_utils.h:58 ]'], [4484605, 'chrome.exe!exit+0xd [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0dat.c:398 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 271, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwWaitForSingleObject', 'waiting': 1, 'done': 324.702721, 'ms': 304.33728300000001, 'syscallargs': [424, 0, 1244444], 'cpu': 2147742720},
+{'stacktrace': [[2088881646, 'kernel32.dll!ExitProcess+0x14'], [4484030, 'chrome.exe!__crtExitProcess+0x14 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0dat.c:683 ]'], [4484605, 'chrome.exe!exit+0xd [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0dat.c:398 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']], 'thread': 3956, 'syscall': 257, 'eventtype': 'EVENT_TYPE_SYSCALL', 'syscallname': 'ntdll.dll!ZwTerminateProcess', 'done': 325.70620000000002, 'ms': 325.44387599999999, 'syscallargs': [0, 0, 241550694], 'cpu': 2147742720},
+{'thread': 3956, 'eventtype': 'EVENT_TYPE_PROCESSEXIT', 'cpu': 3124053392, 'ms': 325.70871399999999, 'stacktrace': [[2088881646, 'kernel32.dll!ExitProcess+0x14'], [4484030, 'chrome.exe!__crtExitProcess+0x14 [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0dat.c:683 ]'], [4484605, 'chrome.exe!exit+0xd [ f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0dat.c:398 ]'], [2088857559, 'kernel32.dll!BaseProcessStart+0x23']]},
+])
diff --git a/chromium/tools/traceline/svgui/traceline.css b/chromium/tools/traceline/svgui/traceline.css
new file mode 100644
index 00000000000..98bf4450a77
--- /dev/null
+++ b/chromium/tools/traceline/svgui/traceline.css
@@ -0,0 +1,73 @@
+@namespace url(http://www.w3.org/1999/xhtml);
+@namespace svg url(http://www.w3.org/2000/svg);
+
+body {
+ /* Trim down the default top margin of 8px, so we have a bit more space. */
+ margin-top: 4px;
+}
+
+div.threadnamediv {
+ height: 16px;
+}
+div.threadnamesdiv {
+ margin-right: 2px;
+ position: absolute;
+ font-family: monospace;
+ z-index: -1;
+}
+
+/* The fakescrolldiv will have the scroll bar, the amount it scrolls is
+ controlled by the size of fattydiv within it. */
+div.fakescrolldiv {
+ /* This needs to be at least 16px, the height of the scrollbar, to have the
+ scrollbar renderer in firefox */
+ /* Making the height 16px in webkit causes the computed width to be 16px
+ shorter than what we specify. 17px is enough to cause it to be correct */
+ height: 17px;
+ width: 1008px;
+ overflow: auto;
+}
+
+div.fattydiv {
+ /* the div needs to have a height for the scrollbar to render in firefox */
+ height: 1px;
+}
+
+div.infoareadiv {
+ margin-top: 4px;
+ padding: 4px;
+ border: 1px solid gray;
+ height: 350px;
+ overflow: auto;
+ font-family: monospace;
+ white-space: pre;
+}
+
+svg|rect.thread {
+ /* fill: #f4f4f6; */
+ fill: #efeff2;
+ opacity: 0.7;
+}
+
+svg|rect.event {
+ fill: #f6a120;
+}
+
+svg|rect.eventwaiting {
+ fill: #62ccf3;
+}
+
+svg|rect.event:hover, svg|rect.eventwaiting:hover {
+ fill: #d92129;
+}
+
+svg|line.eventline {
+ stroke: #bad432;
+ stroke-width: 2px;
+ stroke-opacity: 0.7;
+}
+
+svg|line.eventline:hover {
+ stroke: #d92129;
+ stroke-opacity: 1;
+}
diff --git a/chromium/tools/traceline/svgui/traceline.js b/chromium/tools/traceline/svgui/traceline.js
new file mode 100644
index 00000000000..33cc2dfa388
--- /dev/null
+++ b/chromium/tools/traceline/svgui/traceline.js
@@ -0,0 +1,693 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO
+// - spacial partitioning of the data so that we don't have to scan the
+// entire scene every time we render.
+// - properly clip the SVG elements when they render, right now we are just
+// letting them go negative or off the screen. This might give us a little
+// bit better performance?
+// - make the lines for thread creation work again. Figure out a better UI
+// than these lines, because they can be a bit distracting.
+// - Implement filters, so that you can filter on specific event types, etc.
+// - Make the callstack box collapsable or scrollable or something, it takes
+// up a lot of screen realestate now.
+// - Figure out better ways to preserve screen realestate.
+// - Make the thread bar heights configurable, figure out a better way to
+// handle overlapping events (the pushdown code).
+// - "Sticky" info, so you can click on something, and it will stay. Now
+// if you need to scroll the page you usually lose the info because you
+// will mouse over something else on your way to scrolling.
+// - Help / legend
+// - Loading indicator / debug console.
+// - OH MAN BETTER COLORS PLEASE
+//
+// Dean McNamee <deanm@chromium.org>
+
+// Man... namespaces are such a pain.
+var svgNS = 'http://www.w3.org/2000/svg';
+var xhtmlNS = 'http://www.w3.org/1999/xhtml';
+
+function toHex(num) {
+ var str = "";
+ var table = "0123456789abcdef";
+ for (var i = 0; i < 8; ++i) {
+ str = table.charAt(num & 0xf) + str;
+ num >>= 4;
+ }
+ return str;
+}
+
+// a TLThread represents information about a thread in the traceline data.
+// A thread has a list of all events that happened on that thread, the start
+// and end time of the thread, the thread id, and name, etc.
+function TLThread(id, startms, endms) {
+ this.id = id;
+ // Default the name to the thread id, but if the application uses
+ // thread naming, we might see a THREADNAME event later and update.
+ this.name = "thread_" + id;
+ this.startms = startms;
+ this.endms = endms;
+ this.events = [ ];
+};
+
+TLThread.prototype.duration_ms =
+function() {
+ return this.endms - this.startms;
+};
+
+TLThread.prototype.AddEvent =
+function(e) {
+ this.events.push(e);
+};
+
+TLThread.prototype.toString =
+function() {
+ var res = "TLThread -- id: " + this.id + " name: " + this.name +
+ " startms: " + this.startms + " endms: " + this.endms +
+ " parent: " + this.parent;
+ return res;
+};
+
+// A TLEvent represents a single logged event that happened on a thread.
+function TLEvent(e) {
+ this.eventtype = e['eventtype'];
+ this.thread = toHex(e['thread']);
+ this.cpu = toHex(e['cpu']);
+ this.ms = e['ms'];
+ this.done = e['done'];
+ this.e = e;
+}
+
+function HTMLEscape(str) {
+ return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+}
+
+TLEvent.prototype.toString =
+function() {
+ var res = "<b>ms:</b> " + this.ms + " " +
+ "<b>event:</b> " + this.eventtype + " " +
+ "<b>thread:</b> " + this.thread + " " +
+ "<b>cpu:</b> " + this.cpu + "<br/>";
+ if ('ldrinfo' in this.e) {
+ res += "<b>ldrinfo:</b> " + this.e['ldrinfo'] + "<br/>";
+ }
+ if ('done' in this.e && this.e['done'] > 0) {
+ res += "<b>done:</b> " + this.e['done'] + " ";
+ res += "<b>duration:</b> " + (this.e['done'] - this.ms) + "<br/>";
+ }
+ if ('syscall' in this.e) {
+ res += "<b>syscall:</b> " + this.e['syscall'];
+ if ('syscallname' in this.e) {
+ res += " <b>syscallname:</b> " + this.e['syscallname'];
+ }
+ if ('retval' in this.e) {
+ res += " <b>retval:</b> " + this.e['retval'];
+ }
+ res += "<br/>"
+ }
+ if ('func_addr' in this.e) {
+ res += "<b>func_addr:</b> " + toHex(this.e['func_addr']);
+ if ('func_addr_name' in this.e) {
+ res += " <b>func_addr_name:</b> " + HTMLEscape(this.e['func_addr_name']);
+ }
+ res += "<br/>"
+ }
+ if ('stacktrace' in this.e) {
+ var stack = this.e['stacktrace'];
+ res += "<b>stacktrace:</b><br/>";
+ for (var i = 0; i < stack.length; ++i) {
+ res += "0x" + toHex(stack[i][0]) + " - " +
+ HTMLEscape(stack[i][1]) + "<br/>";
+ }
+ }
+
+ return res;
+}
+
+// The trace logger dumps all log events to a simple JSON array. We delay
+// and background load the JSON, since it can be large. When the JSON is
+// loaded, parseEvents(...) is called and passed the JSON data. To make
+// things easier, we do a few passes on the data to group them together by
+// thread, gather together some useful pieces of data in a single place,
+// and form more of a structure out of the data. We also build links
+// between related events, for example a thread creating a new thread, and
+// the new thread starting to run. This structure is fairly close to what
+// we want to represent in the interface.
+
+// Delay load the JSON data. We want to display the order in the order it was
+// passed to us. Since we have no way of correlating the json callback to
+// which script element it was called on, we load them one at a time.
+
+function JSONLoader(json_urls) {
+ this.urls_to_load = json_urls;
+ this.script_element = null;
+}
+
+JSONLoader.prototype.IsFinishedLoading =
+function() { return this.urls_to_load.length == 0; };
+
+// Start loading of the next JSON URL.
+JSONLoader.prototype.LoadNext =
+function() {
+ var sc = document.createElementNS(
+ 'http://www.w3.org/1999/xhtml', 'script');
+ this.script_element = sc;
+
+ sc.setAttribute("src", this.urls_to_load[0]);
+ document.getElementsByTagNameNS(xhtmlNS, 'body')[0].appendChild(sc);
+};
+
+// Callback counterpart to load_next, should be called when the script element
+// is finished loading. Returns the URL that was just loaded.
+JSONLoader.prototype.DoneLoading =
+function() {
+ // Remove the script element from the DOM.
+ this.script_element.parentNode.removeChild(this.script_element);
+ this.script_element = null;
+ // Return the URL that had just finished loading.
+ return this.urls_to_load.shift();
+};
+
+var loader = null;
+
+function loadJSON(json_urls) {
+ loader = new JSONLoader(json_urls);
+ if (!loader.IsFinishedLoading())
+ loader.LoadNext();
+}
+
+var traceline = new Traceline();
+
+// Called from the JSON with the log event array.
+function parseEvents(json) {
+ loader.DoneLoading();
+
+ var done = loader.IsFinishedLoading();
+ if (!done)
+ loader.LoadNext();
+
+ traceline.ProcessJSON(json);
+
+ if (done)
+ traceline.Render();
+}
+
+// The Traceline class represents our entire state, all of the threads from
+// all sets of data, all of the events, DOM elements, etc.
+function Traceline() {
+ // The array of threads that existed in the program. Hopefully in order
+ // they were created. This includes all threads from all sets of data.
+ this.threads = [ ];
+
+ // Keep a mapping of where in the list of threads a set starts...
+ this.thread_set_indexes = [ ];
+
+ // Map a thread id to the index in the threads array. A thread ID is the
+ // unique ID from the OS, along with our set id of which data file we were.
+ this.threads_by_id = { };
+
+ // The last event time of all of our events.
+ this.endms = 0;
+
+ // Constants for SVG rendering...
+ this.kThreadHeightPx = 16;
+ this.kTimelineWidthPx = 1008;
+}
+
+// Called to add another set of data into the traceline.
+Traceline.prototype.ProcessJSON =
+function(json_data) {
+ // Keep track of which threads belong to which sets of data...
+ var set_id = this.thread_set_indexes.length;
+ this.thread_set_indexes.push(this.threads.length);
+
+ // TODO make this less hacky. Used to connect related events, like creating
+ // a thread and then having that thread run (two separate events which are
+ // related but come in at different times, etc).
+ var tiez = { };
+
+ // Run over the data, building TLThread's and TLEvents, and doing some
+ // processing to put things in an easier to display form...
+ for (var i = 0, il = json_data.length; i < il; ++i) {
+ var e = new TLEvent(json_data[i]);
+
+ // Create a unique identifier for a thread by using the id of this data
+ // set, so that they are isolated from other sets of data with the same
+ // thread id, etc. TODO don't overwrite the original...
+ e.thread = set_id + '_' + e.thread;
+
+ // If this is the first event ever seen on this thread, create a new
+ // thread object and add it to our lists of threads.
+ if (!(e.thread in this.threads_by_id)) {
+ var end_ms = e.done ? e.done : e.ms;
+ var new_thread = new TLThread(e.thread, e.ms, end_ms);
+ this.threads_by_id[new_thread.id] = this.threads.length;
+ this.threads.push(new_thread);
+ }
+
+ var thread = this.threads[this.threads_by_id[e.thread]];
+ thread.AddEvent(e);
+
+ // Keep trace of the time of the last event seen.
+ var end_ms = e.done ? e.done : e.ms;
+ if (end_ms > this.endms) this.endms = end_ms;
+ if (end_ms > thread.endms) thread.endms = end_ms;
+
+ switch(e.eventtype) {
+ case 'EVENT_TYPE_THREADNAME':
+ thread.name = e.e['threadname'];
+ break;
+ case 'EVENT_TYPE_CREATETHREAD':
+ tiez[e.e['eventid']] = e;
+ break;
+ case 'EVENT_TYPE_THREADBEGIN':
+ var pei = e.e['parenteventid'];
+ if (pei in tiez) {
+ e.parentevent = tiez[pei];
+ tiez[pei].childevent = e;
+ }
+ break;
+ }
+ }
+};
+
+Traceline.prototype.Render =
+function() { this.RenderSVG(); };
+
+Traceline.prototype.RenderText =
+function() {
+ var z = document.getElementsByTagNameNS(xhtmlNS, 'body')[0];
+ for (var i = 0, il = this.threads.length; i < il; ++i) {
+ var p = document.createElementNS(
+ 'http://www.w3.org/1999/xhtml', 'p');
+ p.innerHTML = this.threads[i].toString();
+ z.appendChild(p);
+ }
+};
+
+// Oh man, so here we go. For two reasons, I implement my own scrolling
+// system. First off, is that in order to scale, we want to have as little
+// on the DOM as possible. This means not having off-screen elements in the
+// DOM, as this slows down everything. This comes at a cost of more expensive
+// scrolling performance since you have to re-render the scene. The second
+// reason is a bug I stumbled into:
+// https://bugs.webkit.org/show_bug.cgi?id=21968
+// This means that scrolling an SVG element doesn't really work properly
+// anyway. So what the code does is this. We have our layout that looks like:
+// [ thread names ] [ svg timeline ]
+// [ scroll bar ]
+// We make a fake scrollbar, which doesn't actually have the SVG inside of it,
+// we want for when this scrolls, with some debouncing, and then when it has
+// scrolled we rerender the scene. This means that the SVG element is never
+// scrolled, and coordinates are always at 0. We keep the scene in millisecond
+// units which also helps for zooming. We do our own hit testing and decide
+// what needs to be renderer, convert from milliseconds to SVG pixels, and then
+// draw the update into the static SVG element... Y coordinates are still
+// always in pixels (since we aren't paging along the Y axis), but this might
+// be something to fix up later.
+
+function SVGSceneLine(msg, klass, x1, y1, x2, y2) {
+ this.type = SVGSceneLine;
+ this.msg = msg;
+ this.klass = klass;
+
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+
+ this.hittest = function(startms, dur) {
+ return true;
+ };
+}
+
+function SVGSceneRect(msg, klass, x, y, width, height) {
+ this.type = SVGSceneRect;
+ this.msg = msg;
+ this.klass = klass;
+
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+
+ this.hittest = function(startms, dur) {
+ return this.x <= (startms + dur) &&
+ (this.x + this.width) >= startms;
+ };
+}
+
+Traceline.prototype.RenderSVG =
+function() {
+ var threadnames = this.RenderSVGCreateThreadNames();
+ var scene = this.RenderSVGCreateScene();
+
+ var curzoom = 8;
+
+ // The height is static after we've created the scene
+ var dom = this.RenderSVGCreateDOM(threadnames, scene.height);
+
+ dom.zoom(curzoom);
+
+ dom.attach();
+
+ var draw = (function(obj) {
+ return function(scroll, total) {
+ var startms = (scroll / total) * obj.endms;
+
+ var start = (new Date).getTime();
+ var count = obj.RenderSVGRenderScene(dom, scene, startms, curzoom);
+ var total = (new Date).getTime() - start;
+
+ dom.infoareadiv.innerHTML =
+ 'Scene render of ' + count + ' nodes took: ' + total + ' ms';
+ };
+ })(this, dom, scene);
+
+ // Paint the initial paint with no scroll
+ draw(0, 1);
+
+ // Hook us up to repaint on scrolls.
+ dom.redraw = draw;
+};
+
+
+// Create all of the DOM elements for the SVG scene.
+Traceline.prototype.RenderSVGCreateDOM =
+function(threadnames, svgheight) {
+
+ // Total div holds the container and the info area.
+ var totaldiv = document.createElementNS(xhtmlNS, 'div');
+
+ // Container holds the thread names, SVG element, and fake scroll bar.
+ var container = document.createElementNS(xhtmlNS, 'div');
+ container.className = 'container';
+
+ // This is the div that holds the thread names along the left side, this is
+ // done in HTML for easier/better text support than SVG.
+ var threadnamesdiv = document.createElementNS(xhtmlNS, 'div');
+ threadnamesdiv.className = 'threadnamesdiv';
+
+ // Add all of the names into the div, these are static and don't update.
+ for (var i = 0, il = threadnames.length; i < il; ++i) {
+ var div = document.createElementNS(xhtmlNS, 'div');
+ div.className = 'threadnamediv';
+ div.appendChild(document.createTextNode(threadnames[i]));
+ threadnamesdiv.appendChild(div);
+ }
+
+ // SVG div goes along the right side, it holds the SVG element and our fake
+ // scroll bar.
+ var svgdiv = document.createElementNS(xhtmlNS, 'div');
+ svgdiv.className = 'svgdiv';
+
+ // The SVG element, static width, and we will update the height after we've
+ // walked through how many threads we have and know the size.
+ var svg = document.createElementNS(svgNS, 'svg');
+ svg.setAttributeNS(null, 'height', svgheight);
+ svg.setAttributeNS(null, 'width', this.kTimelineWidthPx);
+
+ // The fake scroll div is an outer div with a fixed size with a scroll.
+ var fakescrolldiv = document.createElementNS(xhtmlNS, 'div');
+ fakescrolldiv.className = 'fakescrolldiv';
+
+ // Fatty is inside the fake scroll div to give us the size we want to scroll.
+ var fattydiv = document.createElementNS(xhtmlNS, 'div');
+ fattydiv.className = 'fattydiv';
+ fakescrolldiv.appendChild(fattydiv);
+
+ var infoareadiv = document.createElementNS(xhtmlNS, 'div');
+ infoareadiv.className = 'infoareadiv';
+ infoareadiv.innerHTML = 'Hover an event...';
+
+ // Set the SVG mouseover handler to write the data to the infoarea.
+ svg.addEventListener('mouseover', (function(infoarea) {
+ return function(e) {
+ if ('msg' in e.target && e.target.msg) {
+ infoarea.innerHTML = e.target.msg;
+ }
+ e.stopPropagation(); // not really needed, but might as well.
+ };
+ })(infoareadiv), true);
+
+
+ svgdiv.appendChild(svg);
+ svgdiv.appendChild(fakescrolldiv);
+
+ container.appendChild(threadnamesdiv);
+ container.appendChild(svgdiv);
+
+ totaldiv.appendChild(container);
+ totaldiv.appendChild(infoareadiv);
+
+ var widthms = Math.floor(this.endms + 2);
+ // Make member variables out of the things we want to 'export', things that
+ // will need to be updated each time we redraw the scene.
+ var obj = {
+ // The root of our piece of the DOM.
+ 'totaldiv': totaldiv,
+ // We will want to listen for scrolling on the fakescrolldiv
+ 'fakescrolldiv': fakescrolldiv,
+ // The SVG element will of course need updating.
+ 'svg': svg,
+ // The area we update with the info on mouseovers.
+ 'infoareadiv': infoareadiv,
+ // Called when we detected new scroll a should redraw
+ 'redraw': function() { },
+ 'attached': false,
+ 'attach': function() {
+ document.getElementsByTagNameNS(xhtmlNS, 'body')[0].appendChild(
+ this.totaldiv);
+ this.attached = true;
+ },
+ // The fatty div will have its width adjusted based on the zoom level and
+ // the duration of the graph, to get the scrolling correct for the size.
+ 'zoom': function(curzoom) {
+ var width = widthms * curzoom;
+ fattydiv.style.width = width + 'px';
+ },
+ 'detach': function() {
+ this.totaldiv.parentNode.removeChild(this.totaldiv);
+ this.attached = false;
+ },
+ };
+
+ // Watch when we get scroll events on the fake scrollbar and debounce. We
+ // need to give it a pointer to use in the closer to call this.redraw();
+ fakescrolldiv.addEventListener('scroll', (function(theobj) {
+ var seqnum = 0;
+ return function(e) {
+ seqnum = (seqnum + 1) & 0xffff;
+ window.setTimeout((function(myseqnum) {
+ return function() {
+ if (seqnum == myseqnum) {
+ theobj.redraw(e.target.scrollLeft, e.target.scrollWidth);
+ }
+ };
+ })(seqnum), 100);
+ };
+ })(obj), false);
+
+ return obj;
+};
+
+Traceline.prototype.RenderSVGCreateThreadNames =
+function() {
+ // This names is the list to show along the left hand size.
+ var threadnames = [ ];
+
+ for (var i = 0, il = this.threads.length; i < il; ++i) {
+ var thread = this.threads[i];
+
+ // TODO make this not so stupid...
+ if (i != 0) {
+ for (var j = 0; j < this.thread_set_indexes.length; j++) {
+ if (i == this.thread_set_indexes[j]) {
+ threadnames.push('------');
+ break;
+ }
+ }
+ }
+
+ threadnames.push(thread.name);
+ }
+
+ return threadnames;
+};
+
+Traceline.prototype.RenderSVGCreateScene =
+function() {
+ // This scene is just a list of SVGSceneRect and SVGSceneLine, in no great
+ // order. In the future they should be structured to make range checking
+ // faster.
+ var scene = [ ];
+
+ // Remember, for now, Y (height) coordinates are still in pixels, since we
+ // don't zoom or scroll in this direction. X coordinates are milliseconds.
+
+ var lasty = 0;
+ for (var i = 0, il = this.threads.length; i < il; ++i) {
+ var thread = this.threads[i];
+
+ // TODO make this not so stupid...
+ if (i != 0) {
+ for (var j = 0; j < this.thread_set_indexes.length; j++) {
+ if (i == this.thread_set_indexes[j]) {
+ lasty += this.kThreadHeightPx;
+ break;
+ }
+ }
+ }
+
+ // For this thread, create the background thread (blue band);
+ scene.push(new SVGSceneRect(null,
+ 'thread',
+ thread.startms,
+ 1 + lasty,
+ thread.duration_ms(),
+ this.kThreadHeightPx - 2));
+
+ // Now create all of the events...
+ var pushdown = [ 0, 0, 0, 0 ];
+ for (var j = 0, jl = thread.events.length; j < jl; ++j) {
+ var e = thread.events[j];
+
+ var y = 2 + lasty;
+
+ // TODO this is a hack just so that we know the correct why position
+ // so we can create the threadline...
+ if (e.childevent) {
+ e.marky = y;
+ }
+
+ // Handle events that we want to represent as lines and not event blocks,
+ // right now this is only thread creation. We map an event back to its
+ // "parent" event, and now lets add a line to represent that.
+ if (e.parentevent) {
+ var eparent = e.parentevent;
+ var msg = eparent.toString() + '<br/>' + e.toString();
+ scene.push(
+ new SVGSceneLine(msg, 'eventline',
+ eparent.ms, eparent.marky + 5, e.ms, lasty + 5));
+ }
+
+ // We get negative done values (well, really, it was 0 and then made
+ // relative to start time) when a syscall never returned...
+ var dur = 0;
+ if ('done' in e.e && e.e['done'] > 0) {
+ dur = e.e['done'] - e.ms;
+ }
+
+ // TODO skip short events for now, but eventually we should figure out
+ // a way to control this from the UI, etc.
+ if (dur < 0.2)
+ continue;
+
+ var width = dur;
+
+ // Try to find an available horizontal slot for our event.
+ for (var z = 0; z < pushdown.length; ++z) {
+ var found = false;
+ var slot = z;
+ if (pushdown[z] < e.ms) {
+ found = true;
+ }
+ if (!found) {
+ if (z != pushdown.length - 1)
+ continue;
+ slot = Math.floor(Math.random() * pushdown.length);
+ alert('blah');
+ }
+
+ pushdown[slot] = e.ms + dur;
+ y += slot * 4;
+ break;
+ }
+
+
+ // Create the event
+ klass = e.e.waiting ? 'eventwaiting' : 'event';
+ scene.push(
+ new SVGSceneRect(e.toString(), klass, e.ms, y, width, 3));
+
+ // If there is a "parentevent", we want to make a line there.
+ // TODO
+ }
+
+ lasty += this.kThreadHeightPx;
+ }
+
+ return {
+ 'scene': scene,
+ 'width': this.endms + 2,
+ 'height': lasty,
+ };
+};
+
+Traceline.prototype.RenderSVGRenderScene =
+function(dom, scene, startms, curzoom) {
+ var stuff = scene.scene;
+ var svg = dom.svg;
+
+ var count = 0;
+
+ // Remove everything from the DOM.
+ while (svg.firstChild)
+ svg.removeChild(svg.firstChild);
+
+ // Don't actually need this, but you can't transform on an svg element,
+ // so it's nice to have a <g> around for transforms...
+ var svgg = document.createElementNS(svgNS, 'g');
+
+ var dur = this.kTimelineWidthPx / curzoom;
+
+ function min(a, b) {
+ return a < b ? a : b;
+ }
+
+ function max(a, b) {
+ return a > b ? a : b;
+ }
+
+ function timeToPixel(x) {
+ // TODO(deanm): This clip is a bit shady.
+ var x = min(max(Math.floor(x*curzoom), -100), 2000);
+ return (x == 0 ? 1 : x);
+ }
+
+ for (var i = 0, il = stuff.length; i < il; ++i) {
+ var thing = stuff[i];
+ if (!thing.hittest(startms, startms+dur))
+ continue;
+
+
+ if (thing.type == SVGSceneRect) {
+ var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
+ rect.setAttributeNS(null, 'class', thing.klass)
+ rect.setAttributeNS(null, 'x', timeToPixel(thing.x - startms));
+ rect.setAttributeNS(null, 'y', thing.y);
+ rect.setAttributeNS(null, 'width', timeToPixel(thing.width));
+ rect.setAttributeNS(null, 'height', thing.height);
+ rect.msg = thing.msg;
+ svgg.appendChild(rect);
+ } else if (thing.type == SVGSceneLine) {
+ var line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
+ line.setAttributeNS(null, 'class', thing.klass)
+ line.setAttributeNS(null, 'x1', timeToPixel(thing.x1 - startms));
+ line.setAttributeNS(null, 'y1', thing.y1);
+ line.setAttributeNS(null, 'x2', timeToPixel(thing.x2 - startms));
+ line.setAttributeNS(null, 'y2', thing.y2);
+ line.msg = thing.msg;
+ svgg.appendChild(line);
+ }
+
+ ++count;
+ }
+
+ // Append the 'g' element on after we've build it.
+ svg.appendChild(svgg);
+
+ return count;
+};
diff --git a/chromium/tools/traceline/svgui/traceline.xml b/chromium/tools/traceline/svgui/traceline.xml
new file mode 100644
index 00000000000..375744d069b
--- /dev/null
+++ b/chromium/tools/traceline/svgui/traceline.xml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>Traceline SVG</title>
+
+ <link href="traceline.css" rel="stylesheet" type="text/css" />
+ <script src="traceline.js"></script>
+</head>
+
+<body onload="loadJSON(document.location.hash.substr(1).split(','));">
+</body>
+</html>
diff --git a/chromium/tools/traceline/traceline/Makefile b/chromium/tools/traceline/traceline/Makefile
new file mode 100644
index 00000000000..d5ac5b626a2
--- /dev/null
+++ b/chromium/tools/traceline/traceline/Makefile
@@ -0,0 +1,30 @@
+all:
+ cl \
+ sidestep/ia32_modrm_map.cc \
+ sidestep/ia32_opcode_map.cc \
+ sidestep/mini_disassembler.cc \
+ main.cc \
+ /Fetraceline.exe \
+ /D_WIN32_WINNT=0x0500 \
+ /D_HAS_EXCEPTIONS=0 \
+ "/I." \
+ /Zi \
+ /link \
+ kernel32.lib user32.lib dbghelp.lib powrprof.lib
+
+tests:
+ cl \
+ assembler_unittest.cc \
+ /Fassembler_unittest.exe \
+ /D_WIN32_WINNT=0x0500 \
+ /D_HAS_EXCEPTIONS=0 \
+ /Zi \
+ /link \
+ kernel32.lib user32.lib dbghelp.lib powrprof.lib
+
+stubs : stubs.asm
+ nasm -o stubs stubs.asm
+ ndisasm -u stubs
+
+clean:
+ rm -f *.obj {cpuinfo,traceline,assembler_unittest,vc80}.{exe,ilk,pdb} stubs
diff --git a/chromium/tools/traceline/traceline/README b/chromium/tools/traceline/traceline/README
new file mode 100644
index 00000000000..97ceec8b664
--- /dev/null
+++ b/chromium/tools/traceline/traceline/README
@@ -0,0 +1,21 @@
+Traceline is a Windows utility to intercept, time, and log system calls. This
+is achieved by injecting code into a target process, along with dynamically
+generated assembly hook stubs. One of the major goals was to skew performance
+timings as little as possible. This lead to a design in which the log buffer
+(which is called the playground) is kept within the process, and the logger
+routines use atomic instructions to log their events to this buffer. At the
+end of the processes lifetime, this buffer is pulled out of the process and
+used to generated JSON output. In addition to hooking system call activity,
+other hooks of interest have been written, including heap allocation functions.
+Symbols are supported with a command line flag. This works by capturing the
+process shutdown, and doing an intrusive symbol attach with dbghelp.dll
+
+NOTES:
+ - You should copy dbghelp.dll from a windbg installation into this directory.
+ The version shipped with Windows is old, and symbol support won't work.
+ - You will need a bit of cygwin if you want to use the Makefile. Otherwise
+ it is pretty clear how to build the files manually.
+ - The output JSON data will be printed out stdout. It is likely that you
+ will want to pipe the output of this program into a file.
+
+Dean McNamee <deanm@chromium.org>
diff --git a/chromium/tools/traceline/traceline/assembler.h b/chromium/tools/traceline/traceline/assembler.h
new file mode 100644
index 00000000000..6ae69587020
--- /dev/null
+++ b/chromium/tools/traceline/traceline/assembler.h
@@ -0,0 +1,576 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// - Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// - Redistribution in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// - Neither the name of Sun Microsystems or the names of contributors may
+// be used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The original source code covered by the above license above has been
+// modified significantly by Google Inc.
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+
+// This implements a C++ assembler for dynamically generating machine code.
+// It is heavily based on the v8 assembler, which has a long history of its
+// own. Relocation information has been removed, and in general things were
+// made a bit simpler (and slower). Everything is implemented inline.
+
+#ifndef TRACELINE_ASSEMBLER_H_
+#define TRACELINE_ASSEMBLER_H_
+
+#include <windows.h>
+#include <stdio.h>
+#include <string>
+
+#include "logging.h"
+
+#define ASSERT(x) CHECK(x)
+
+enum Register {
+ EAX = 0,
+ ECX = 1,
+ EDX = 2,
+ EBX = 3,
+ ESP = 4,
+ EBP = 5,
+ ESI = 6,
+ EDI = 7
+};
+
+enum Condition {
+ overflow = 0,
+ no_overflow = 1,
+ below = 2,
+ above_equal = 3,
+ equal = 4,
+ not_equal = 5,
+ below_equal = 6,
+ above = 7,
+ sign = 8,
+ not_sign = 9,
+ parity_even = 10,
+ parity_odd = 11,
+ less = 12,
+ greater_equal = 13,
+ less_equal = 14,
+ greater = 15,
+
+ // aliases
+ zero = equal,
+ not_zero = not_equal,
+ negative = sign,
+ positive = not_sign
+};
+
+// Labels are used for branching, and marks an offset in the CodeBuffer.
+// A label can be in 3 states:
+// - Unused, the label has never be used in an instruction.
+// - Linked, the label has been referenced (by a jump, for example), but the
+// target is not yet known, because the label is unbound.
+// - Bound, the label has been bound so the offset is known.
+class Label {
+ public:
+ Label() { Unuse(); }
+ ~Label() { ASSERT(!is_linked()); }
+
+ void Unuse() {
+ num_ = 0;
+ }
+
+ bool is_unused() const { return num_ == 0; }
+ bool is_bound() const { return num_ == -1; }
+ bool is_linked() const { return num_ > 0; }
+
+ int binding_pos() const {
+ ASSERT(is_bound());
+ return table_[0];
+ }
+
+ int num_links() const {
+ ASSERT(!is_bound());
+ return num_; // Will return 0 if unused.
+ }
+
+ int link_pos(int i) const {
+ ASSERT(is_linked());
+ ASSERT(i < num_);
+ return table_[i];
+ }
+
+ private:
+ void bind_to(int pos) {
+ ASSERT(!is_bound());
+ table_[0] = pos;
+ num_ = -1;
+ }
+ void link_to(int pos) {
+ ASSERT(!is_bound());
+ ASSERT(num_ < kTableSize);
+
+ table_[num_] = pos;
+ ++num_;
+ }
+
+ static const int kTableSize = 3;
+
+ // We store all links in a fixed size table. When we're bound, we store the
+ // binding position in the first entry of the table.
+ int table_[kTableSize];
+ // The number of entries in our table, if we're linked. If 0, then we're
+ // unusued. If -1, then we are bound (and the pos is at table_[0]).
+ int num_;
+
+ friend class CodeBuffer; // For binding, linking, etc
+};
+
+
+enum ScaleFactor {
+ SCALE_TIMES_1 = 0,
+ SCALE_TIMES_2 = 1,
+ SCALE_TIMES_4 = 2,
+ SCALE_TIMES_8 = 3
+};
+
+
+class Operand {
+ public:
+ explicit Operand(const Operand& x) : len_(x.len_) {
+ memcpy(buf_, x.buf_, sizeof(buf_));
+ }
+
+ // reg
+ explicit Operand(Register reg) {
+ Init(reg);
+ }
+
+ // [disp/r]
+ explicit Operand(int disp) {
+ Init(disp);
+ }
+
+ // [base + disp/r]
+ Operand(Register base, int disp) {
+ Init(base, disp);
+ }
+
+ // [base + index*scale + disp/r]
+ Operand(Register base, Register index, ScaleFactor scale, int disp) {
+ Init(base, index, scale, disp);
+ }
+
+ // [index*scale + disp/r]
+ Operand(Register index, ScaleFactor scale, int disp) {
+ Init(index, scale, disp);
+ }
+
+ void set_reg(Register reg) {
+ ASSERT(len_ > 0);
+ buf_[0] = (buf_[0] & ~0x38) | static_cast<char>(reg << 3);
+ }
+
+ char* data() { return buf_; }
+ int length() { return len_; }
+
+ private:
+ // reg
+ void Init(Register reg) {
+ set_modrm(3, reg);
+ }
+
+ // [disp/r]
+ void Init(int disp) {
+ set_modrm(0, EBP);
+ set_dispr(disp);
+ }
+
+ // [base + disp/r]
+ void Init(Register base, int disp) {
+ if (disp == 0) {
+ // [base]
+ set_modrm(0, base);
+ if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
+ } else if (is_int8(disp)) {
+ // [base + disp8]
+ set_modrm(1, base);
+ if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
+ set_disp8(disp);
+ } else {
+ // [base + disp/r]
+ set_modrm(2, base);
+ if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
+ set_dispr(disp);
+ }
+ }
+
+ // [base + index*scale + disp/r]
+ void Init(Register base,
+ Register index,
+ ScaleFactor scale,
+ int disp) {
+ ASSERT(index != ESP); // illegal addressing mode
+ if (disp == 0 && base != EBP) {
+ // [base + index*scale]
+ set_modrm(0, ESP);
+ set_sib(scale, index, base);
+ } else if (is_int8(disp)) {
+ // [base + index*scale + disp8]
+ set_modrm(1, ESP);
+ set_sib(scale, index, base);
+ set_disp8(disp);
+ } else {
+ // [base + index*scale + disp/r]
+ set_modrm(2, ESP);
+ set_sib(scale, index, base);
+ set_dispr(disp);
+ }
+ }
+
+ // [index*scale + disp/r]
+ void Init(Register index,
+ ScaleFactor scale,
+ int disp) {
+ ASSERT(index != ESP); // illegal addressing mode
+ // We can reduce instruction size by translating instructions of the form:
+ // 8D044510000000 lea eax,[eax*2+0x10]
+ // To the more concise scale=1 version:
+ // 8D440010 lea eax,[eax+eax+0x10]
+ if (scale == SCALE_TIMES_2) {
+ Init(index, index, SCALE_TIMES_1, disp);
+ } else {
+ set_modrm(0, ESP);
+ set_sib(scale, index, EBP);
+ set_dispr(disp);
+ }
+ }
+
+ // Returns true if this Operand is a wrapper for the specified register.
+ bool is_reg(Register reg) const {
+ return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
+ && ((buf_[0] & 0x07) == reg); // register codes match.
+ }
+
+ void set_modrm(int mod, Register rm) { // reg == 0
+ ASSERT((mod & -4) == 0);
+ buf_[0] = mod << 6 | rm;
+ len_ = 1;
+ }
+
+ void set_sib(ScaleFactor scale, Register index, Register base) {
+ ASSERT(len_ == 1);
+ ASSERT((scale & -4) == 0);
+ buf_[1] = scale << 6 | index << 3 | base;
+ len_ = 2;
+ }
+
+ void set_disp8(char disp) {
+ ASSERT(len_ == 1 || len_ == 2);
+ *reinterpret_cast<char*>(&buf_[len_++]) = disp;
+ }
+
+ void set_dispr(int disp) {
+ ASSERT(len_ == 1 || len_ == 2);
+ *reinterpret_cast<int*>(&buf_[len_]) = disp;
+ len_ += sizeof(int);
+ }
+
+ bool is_int8(int x) { return x >= -128 && x <= 127; }
+
+ // Mutable because reg in ModR/M byte is set by Assembler via set_reg().
+ char buf_[6];
+ // The number of bytes in buf_.
+ unsigned int len_;
+};
+
+// A convenient wrapper around a buffer for emitting code or data, etc.
+class CodeBuffer {
+ public:
+ // Use an externally managed buffer
+ explicit CodeBuffer(char* buf) : pos_(0), buf_(buf) { }
+
+ void* data() { return buf_; }
+ int size() { return pos_; }
+
+ void emit(unsigned char b) {
+ buf_[pos_++] = b;
+ }
+ void emit_word(unsigned short w) {
+ *reinterpret_cast<unsigned short*>(&buf_[pos_]) = w;
+ pos_ += 2;
+ }
+ void emit_dword(unsigned int d) {
+ *reinterpret_cast<unsigned int*>(&buf_[pos_]) = d;
+ pos_ += 4;
+ }
+
+ void emit_bytes(const char* bytes, size_t size) {
+ for (size_t i = 0; i < size; ++i)
+ emit(bytes[i]);
+ }
+
+ void emit_bytes(const std::string& bytes) {
+ emit_bytes(bytes.data(), bytes.size());
+ }
+
+ void put_dword_at(int pos, unsigned int d) {
+ *reinterpret_cast<unsigned int*>(&buf_[pos]) = d;
+ }
+
+ // We pass by value so that we get a copy that we can modify.
+ void emit_operand(Register reg, Operand operand) {
+ operand.set_reg(reg);
+ memcpy(&buf_[pos_], operand.data(), operand.length());
+ pos_ += operand.length();
+ }
+
+ void bind(Label* l) {
+ ASSERT(!l->is_bound());
+ for (int i = 0; i < l->num_links(); ++i) {
+ put_dword_at(l->link_pos(i), pos_ - (l->link_pos(i) + 4));
+ }
+ l->bind_to(pos_);
+ }
+
+ // TODO deprecate blah_imm and use blah(Immediate)
+
+ void add(Register dst, Register src) {
+ emit(0x01); emit(0xc0 | (src << 3) | dst);
+ }
+ void add_imm(Register dst, int d) {
+ if (d >= -128 && d <= 127) {
+ emit(0x83); emit(0xc0 | dst); emit(d & 0xff);
+ } else {
+ emit(0x81); emit(0xc0 | dst); emit_dword(d);
+ }
+ }
+
+ void and_(Register r, unsigned int mask) {
+ emit(0x81); emit(0xe0 | r); emit_dword(mask);
+ }
+
+ void call(Register r) {
+ call(Operand(r));
+ }
+ void call(const Operand& dst) {
+ emit(0xff); emit_operand(EDX, dst);
+ }
+
+ void cmp(Register r1, Register r2) {
+ emit(0x39); emit(0xc0 | (r2 << 3) | r1);
+ }
+
+ void cmp_imm(Register r, int d) {
+ if (d >= -128 && d <= 127) {
+ emit(0x83); emit(0xf8 | r); emit(d & 0xff);
+ } else {
+ emit(0x81); emit(0xf8 | r); emit_dword(d);
+ }
+ }
+
+ void fs() {
+ emit(0x64);
+ }
+
+ // Atomically increment the dword at |mem| with the increment amount in the
+ // register |inc|. Will replace |inc| with the old unincremented value.
+ void inc_atomic(Register mem, Register inc) {
+ // lock xadd [mem], inc
+ emit(0xF0); emit(0x0F); emit(0xC1); emit((inc << 3) | mem);
+ }
+
+ void int3() {
+ emit(0xcc);
+ }
+
+ void jcc(Condition cc, Label* l) {
+ emit(0x0f); emit(0x80 | cc);
+ if (l->is_bound()) {
+ emit_dword(l->binding_pos() - (pos_ + 4));
+ } else {
+ // Will fix up when the label is bound.
+ l->link_to(pos_);
+ emit_dword(0);
+ }
+ }
+
+ void jmp(Register r) {
+ emit(0xff); emit(0xe0 | r);
+ }
+
+ void jmp(Label* l) {
+ if (l->is_bound()) {
+ jmp_rel(l->binding_pos() - (pos_ + 5));
+ } else {
+ // Will fix up when the label is bound.
+ l->link_to(pos_ + 1);
+ jmp_rel(0);
+ }
+ }
+
+ void jmp_rel(int i) {
+ emit(0xe9); emit_dword(i);
+ }
+
+ void jmp_rel_short(char c) {
+ emit(0xeb); emit(c);
+ }
+
+ void lea(Register dst, const Operand& src) {
+ emit(0x8d); emit_operand(dst, src);
+ }
+
+ void lodsb() {
+ emit(0xac);
+ }
+ void lodsd() {
+ emit(0xad);
+ }
+
+ void loop(Label* l) {
+ ASSERT(l->is_bound());
+ int pos = l->binding_pos() - (pos_ + 2);
+ ASSERT(pos >= -128 && pos < 0);
+
+ emit(0xe2); emit(pos & 0xff);
+ }
+
+ void mov(Register dst, Register src) {
+ emit(0x89); emit(0xc0 | (src << 3) | dst);
+ }
+ void mov(Register dst, const Operand& src) {
+ emit(0x8b); emit_operand(dst, src);
+ }
+ void mov_imm(Register r, unsigned int d) {
+ emit(0xb8 | r); emit_dword(d);
+ }
+
+ void movsb() {
+ emit(0xa4);
+ }
+ void movsd() {
+ emit(0xa5);
+ }
+
+ void or_(Register r, unsigned int mask) {
+ emit(0x81); emit(0xc8 | r); emit_dword(mask);
+ }
+
+ void pop(Register r) {
+ emit(0x58 | r);
+ }
+ void pop(const Operand& dst) {
+ emit(0x8f); emit_operand(EAX, dst);
+ }
+
+ void push(Register r) {
+ emit(0x50 | r);
+ }
+ void push(const Operand& src) {
+ emit(0xff); emit_operand(ESI, src);
+ }
+ void push_imm(int i) {
+ if (i >= -128 && i <= 127) {
+ emit(0x6a); emit(i & 0xff);
+ } else {
+ emit(0x68); emit_dword(i);
+ }
+ }
+
+ // Puts the cycle counter into edx:eax.
+ void rdtsc() {
+ emit(0x0F); emit(0x31);
+ }
+
+ void rep() {
+ emit(0xf3);
+ }
+
+ void ret() {
+ ret(0);
+ }
+ void ret(short c) {
+ if (c == 0) {
+ emit(0xc3);
+ } else {
+ emit(0xc2); emit_word(c);
+ }
+ }
+
+ void spin() {
+ jmp_rel_short(-2);
+ }
+
+ void stosb() {
+ emit(0xaa);
+ }
+ void stosd() {
+ emit(0xab);
+ }
+
+ void sysenter() {
+ emit(0x0f); emit(0x34);
+ }
+
+ // Puts a unique cpu identifier into eax, using sidt to fingerprint cores.
+ void which_cpu() {
+ // Make space
+ push(EAX);
+ push(EAX);
+ // sidt [esp+2]
+ emit(0x0f); emit(0x01); emit_operand(ECX, Operand(ESP, 2));
+ pop(EAX);
+ pop(EAX); // sidt address
+ }
+
+ // Puts a unique identifier for the thread we're executing on into eax.
+ void which_thread() {
+ // mov eax, [fs:0x24]
+ emit(0x64); emit(0xa1); emit_dword(0x24);
+ // TODO: We could do this but it will use an encoding that is 1 byte bigger.
+ // fs(); mov(EAX, Operand(0x24));
+ }
+
+ void xchg(Register r1, Register r2) {
+ if (r1 == EAX) {
+ emit(0x90 | r2);
+ } else if (r2 == EAX) {
+ emit(0x90 | r1);
+ } else {
+ xchg(r1, Operand(r2));
+ }
+ }
+ void xchg(Register r1, const Operand& oper) {
+ emit(0x87); emit_operand(r1, oper);
+ }
+
+ private:
+ int pos_;
+ char* buf_;
+};
+
+#endif // TRACELINE_ASSEMBLER_H_
diff --git a/chromium/tools/traceline/traceline/assembler_unittest.cc b/chromium/tools/traceline/traceline/assembler_unittest.cc
new file mode 100644
index 00000000000..e2c17b66012
--- /dev/null
+++ b/chromium/tools/traceline/traceline/assembler_unittest.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdio.h>
+
+#include "assembler.h"
+
+int main(int argc, char** argv) {
+ char buf[1024];
+
+ CodeBuffer cb(buf);
+
+ // Branching tests first so the offsets are not always adjusting in the
+ // output diassembler when we add new tests.
+
+ cb.spin();
+
+ cb.call(EAX);
+ cb.call(Operand(EAX));
+ cb.call(Operand(EDX, 15));
+
+ cb.fs(); cb.mov(EAX, Operand(3));
+ cb.fs(); cb.mov(EDX, Operand(0x04));
+
+ cb.lea(EAX, Operand(EAX));
+ cb.lea(EAX, Operand(0x12345678));
+ cb.lea(EAX, Operand(EBX, 0x12345678));
+ cb.lea(EAX, Operand(EBX, ECX, SCALE_TIMES_2, 0x12345678));
+ cb.lea(EAX, Operand(ECX, SCALE_TIMES_2, 0x12345678));
+ cb.lea(EAX, Operand(EAX, SCALE_TIMES_2, 0));
+ cb.lea(EAX, Operand(EBX, SCALE_TIMES_2, 0));
+ cb.lea(EBP, Operand(EBP, SCALE_TIMES_2, 1));
+
+ cb.lodsb();
+ cb.lodsd();
+
+ cb.mov(EAX, ECX);
+ cb.mov(ESI, ESP);
+ cb.mov(EAX, Operand(ESP, 0x20));
+ cb.mov(EAX, Operand(EBP, 8));
+ cb.mov_imm(ESP, 1);
+ cb.mov_imm(EAX, 0x12345678);
+
+ cb.pop(EBX);
+ cb.pop(Operand(EBX));
+ cb.pop(Operand(EBX, 0));
+ cb.pop(Operand(EBX, 12));
+
+ cb.push(EBX);
+ cb.push(Operand(EBX));
+ cb.push(Operand(EBX, 0));
+ cb.push(Operand(EDI, -4));
+ cb.push(Operand(EDI, -8));
+ cb.push_imm(0x12);
+ cb.push_imm(0x1234);
+ cb.push(Operand(EBX, 12));
+ cb.push(Operand(ESP, 0x1234));
+
+ cb.ret();
+ cb.ret(0);
+ cb.ret(12);
+
+ cb.stosb();
+ cb.stosd();
+
+ cb.sysenter();
+
+ cb.which_cpu();
+ cb.which_thread();
+
+ cb.xchg(EAX, EAX);
+ cb.xchg(EBX, EAX);
+ cb.xchg(EAX, EBX);
+ cb.xchg(ECX, ESP);
+ cb.xchg(ECX, Operand(ESP));
+ cb.xchg(ECX, Operand(ESP, 5));
+ cb.xchg(ECX, Operand(EDX, 4));
+
+ fwrite(buf, 1, cb.size(), stdout);
+
+ return 0;
+}
diff --git a/chromium/tools/traceline/traceline/assembler_unittest.sh b/chromium/tools/traceline/traceline/assembler_unittest.sh
new file mode 100755
index 00000000000..6be6191bf12
--- /dev/null
+++ b/chromium/tools/traceline/traceline/assembler_unittest.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+./assembler_unittest.exe | ndisasm -u - | cut -c 11-
diff --git a/chromium/tools/traceline/traceline/assembler_unittest.sh.expected b/chromium/tools/traceline/traceline/assembler_unittest.sh.expected
new file mode 100644
index 00000000000..a0d3af30a2d
--- /dev/null
+++ b/chromium/tools/traceline/traceline/assembler_unittest.sh.expected
@@ -0,0 +1,54 @@
+EBFE jmp short 0x0
+FFD0 call eax
+FFD0 call eax
+FF520F call dword near [edx+0xf]
+648B0503000000 mov eax,[dword fs:0x3]
+648B1504000000 mov edx,[dword fs:0x4]
+8D db 0x8D
+C08D0578563412 ror byte [ebp+0x34567805],0x12
+8D8378563412 lea eax,[ebx+0x12345678]
+8D844B78563412 lea eax,[ebx+ecx*2+0x12345678]
+8D840978563412 lea eax,[ecx+ecx+0x12345678]
+8D0400 lea eax,[eax+eax]
+8D041B lea eax,[ebx+ebx]
+8D6C2D01 lea ebp,[ebp+ebp+0x1]
+AC lodsb
+AD lodsd
+89C8 mov eax,ecx
+89E6 mov esi,esp
+8B442420 mov eax,[esp+0x20]
+8B4508 mov eax,[ebp+0x8]
+BC01000000 mov esp,0x1
+B878563412 mov eax,0x12345678
+5B pop ebx
+8FC3 pop ebx
+8F03 pop dword [ebx]
+8F430C pop dword [ebx+0xc]
+53 push ebx
+FFF3 push ebx
+FF33 push dword [ebx]
+FF77FC push dword [edi-0x4]
+FF77F8 push dword [edi-0x8]
+6A12 push byte +0x12
+6834120000 push 0x1234
+FF730C push dword [ebx+0xc]
+FFB42434120000 push dword [esp+0x1234]
+C3 ret
+C3 ret
+C20C00 ret 0xc
+AA stosb
+AB stosd
+0F34 sysenter
+50 push eax
+50 push eax
+0F014C2402 sidt [esp+0x2]
+58 pop eax
+58 pop eax
+64A124000000 mov eax,[fs:0x24]
+90 nop
+93 xchg eax,ebx
+93 xchg eax,ebx
+87CC xchg ecx,esp
+87CC xchg ecx,esp
+874C2405 xchg ecx,[esp+0x5]
+874A04 xchg ecx,[edx+0x4]
diff --git a/chromium/tools/traceline/traceline/dump_syscalls_idarub.rb b/chromium/tools/traceline/traceline/dump_syscalls_idarub.rb
new file mode 100755
index 00000000000..6e0fb8fe9d7
--- /dev/null
+++ b/chromium/tools/traceline/traceline/dump_syscalls_idarub.rb
@@ -0,0 +1,32 @@
+#!/usr/bin/env ruby
+
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is an idarub script for extracting system call numbers from a DLL that
+# has been loaded into the IDA disassembler. The interesting system call stubs
+# are contained in ntdll.dll, user32.dll, gdi32.dll, and imm32.dll.
+
+require 'idarub'
+
+ida, = IdaRub.auto_client
+
+curea = 0
+
+filename = ida.get_root_filename
+
+while true
+ curea = ida.find_binary(
+ curea, ida.BADADDR, 'ba 00 03 fe 7f', 16, ida.SEARCH_DOWN)
+ break if curea == ida.BADADDR
+
+ raise "z" if ida.get_byte(curea - 5) != 0xb8
+
+ syscall = ida.get_long(curea - 4)
+ # Remove the IDA _ prefix and the @argsize trailing decorator...
+ funcname = ida.get_func_name(curea).split('@', 2)[0].split('_', 2)[-1]
+ puts '%d: "%s!%s",' % [syscall, filename, funcname]
+
+ curea += 1
+end
diff --git a/chromium/tools/traceline/traceline/logging.h b/chromium/tools/traceline/traceline/logging.h
new file mode 100644
index 00000000000..bf2e4fa0684
--- /dev/null
+++ b/chromium/tools/traceline/traceline/logging.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TRACELINE_LOGGING_H_
+#define TRACELINE_LOGGING_H_
+
+#include <windows.h>
+#include <stdio.h>
+
+#define CHECK(exp, ...) \
+ if (!(exp)) { \
+ printf("FAILED CHECK: %s\n %s:%d\n", #exp, __FILE__, __LINE__); \
+ printf("\naborted.\n"); \
+ if (::IsDebuggerPresent()) __debugbreak(); \
+ exit(1); \
+ }
+
+#define NOTREACHED(...) \
+ if (1) { \
+ printf("NOTREACHED:\n %s:%d\n", __FILE__, __LINE__); \
+ printf(__VA_ARGS__); \
+ printf("\naborted.\n"); \
+ if (::IsDebuggerPresent()) __debugbreak(); \
+ exit(1); \
+ }
+
+#endif // TRACELINE_LOGGING_H_
diff --git a/chromium/tools/traceline/traceline/main.cc b/chromium/tools/traceline/traceline/main.cc
new file mode 100644
index 00000000000..11d9e52437c
--- /dev/null
+++ b/chromium/tools/traceline/traceline/main.cc
@@ -0,0 +1,1339 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO
+// - Make capturing system call arguments optional and the number configurable.
+// - Lots of places depend on the ABI so that we can modify EAX or EDX, this
+// is safe, but these could be moved to be saved and restored anyway.
+// - Understand the loader better, and make some more meaningful hooks with
+// proper data collection and durations. Right now it's just noise.
+// - Get the returned pointer from AllocateHeap.
+
+#include <windows.h>
+
+#include <stdio.h>
+
+#include <map>
+#include <string>
+
+#include "assembler.h"
+#include "logging.h"
+#include "rdtsc.h"
+#include "sym_resolver.h"
+#include "syscall_map.h"
+
+#include "sidestep/mini_disassembler.h"
+
+namespace {
+
+std::string JSONString(const std::string& str) {
+ static const char hextable[] = "0123456789abcdef";
+ std::string out;
+ out.push_back('"');
+ for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
+ unsigned char c = static_cast<unsigned char>(*it);
+ switch (c) {
+ case '\\':
+ case '"':
+ case '\'':
+ out.push_back('\\'); out.push_back(c);
+ break;
+ default:
+ if (c < 20 || c >= 127) {
+ out.push_back('\\'); out.push_back('x');
+ out.push_back(hextable[c >> 4]); out.push_back(hextable[c & 0xf]);
+ } else {
+ // Unescaped.
+ out.push_back(c);
+ }
+ break;
+ }
+ }
+ out.push_back('"');
+ return out;
+}
+
+} // namespace
+
+class Playground {
+ public:
+ static const int kPlaygroundSize = 64 * 1024 * 1024;
+
+ // Encapsulate the configuration options to the playground.
+ class Options {
+ public:
+ Options()
+ : stack_unwind_depth_(0),
+ log_heap_(false),
+ log_lock_(false),
+ vista_(false) { }
+
+
+ // The maximum amount of frames we should unwind from the call stack.
+ int stack_unwind_depth() { return stack_unwind_depth_; }
+ void set_stack_unwind_depth(int depth) { stack_unwind_depth_ = depth; }
+
+ // Whether we should log heap operations (alloc / free).
+ bool log_heap() { return log_heap_; }
+ void set_log_heap(bool x) { log_heap_ = x; }
+
+ // Whether we should log lock (critical section) operations.
+ bool log_lock() { return log_lock_; }
+ void set_log_lock(bool x) { log_lock_ = x; }
+
+ // Whether we are running on Vista.
+ bool vista() { return vista_; }
+ void set_vista(bool x) { vista_ = x; }
+
+ private:
+ int stack_unwind_depth_;
+ bool log_heap_;
+ bool log_lock_;
+ bool vista_;
+ };
+
+ Playground(HANDLE proc, const Options& options)
+ : proc_(proc),
+ remote_addr_(NULL),
+ resolver_("ntdll.dll"),
+ options_(options) {
+ // We copy the entire playground into the remote process, and we have
+ // fields that we expect to be zero. TODO this could be a lot better.
+ memset(buf_, 0, sizeof(buf_));
+ }
+
+ void AllocateInRemote() {
+ // Try to get something out of the way and easy to debug.
+ static void* kPlaygroundAddr = reinterpret_cast<void*>(0x66660000);
+ // Allocate our playground memory in the target process. This is a big
+ // slab of read/write/execute memory that we use for our code
+ // instrumentation, and the memory for writing out our logging events.
+ remote_addr_ = reinterpret_cast<char*>(
+ VirtualAllocEx(proc_,
+ kPlaygroundAddr,
+ kPlaygroundSize,
+ MEM_COMMIT | MEM_RESERVE,
+ PAGE_EXECUTE_READWRITE));
+ if (remote_addr_ == NULL || remote_addr_ != kPlaygroundAddr) {
+ NOTREACHED("Falied to allocate playground: 0x%08x", remote_addr_);
+ }
+ }
+
+ void CopyToRemote() {
+ WriteProcessMemory(proc_,
+ remote_addr_,
+ buf_,
+ sizeof(buf_),
+ NULL);
+ }
+
+ void CopyFromRemote() {
+ SIZE_T size = 0;
+ ReadProcessMemory(proc_,
+ remote_addr_,
+ buf_,
+ sizeof(buf_),
+ &size);
+ }
+
+ enum EventRecordType {
+ EVENT_TYPE_LDR = 0,
+ EVENT_TYPE_THREADBEGIN = 1,
+ EVENT_TYPE_THREADNAME = 2,
+ EVENT_TYPE_EXCEPTION = 3,
+ EVENT_TYPE_PROCESSEXIT = 4,
+ EVENT_TYPE_CREATETHREAD = 5,
+ EVENT_TYPE_THREADEXIT = 6,
+ EVENT_TYPE_ALLOCHEAP = 7,
+ EVENT_TYPE_FREEHEAP = 8,
+ EVENT_TYPE_SYSCALL = 9,
+ EVENT_TYPE_ENTER_CS = 10,
+ EVENT_TYPE_TRYENTER_CS = 11,
+ EVENT_TYPE_LEAVE_CS = 12,
+ EVENT_TYPE_APC = 13
+ };
+
+ static const int kThreadNameBufSize = 64;
+ static const int kLdrBufSize = 512; // Looks like internal buffer is 512.
+
+ static const int kCodeBlockSize = 256;
+
+ static const int kOffLdrCode = 0 * kCodeBlockSize;
+ static const int kOffCreateThreadCode = 1 * kCodeBlockSize;
+ static const int kOffThreadCode = 2 * kCodeBlockSize;
+ static const int kOffExpCode = 3 * kCodeBlockSize;
+ static const int kOffExitCode = 4 * kCodeBlockSize;
+ static const int kOffThreadExitCode = 5 * kCodeBlockSize;
+ static const int kOffAllocHeapCode = 6 * kCodeBlockSize;
+ static const int kOffFreeHeapCode = 7 * kCodeBlockSize;
+ static const int kOffSyscallCode = 8 * kCodeBlockSize;
+ static const int kOffEnterCritSecCode = 9 * kCodeBlockSize;
+ static const int kOffTryEnterCritSecCode = 10 * kCodeBlockSize;
+ static const int kOffLeaveCritSecCode = 11 * kCodeBlockSize;
+ static const int kOffApcDispCode = 12 * kCodeBlockSize;
+
+ static const int kOffLogAreaPtr = 4096;
+ static const int kOffLogAreaData = 4096 + 4;
+
+ static const int kRecordHeaderSize = 8 + 4 + 4 + 4;
+
+ // Given the address to the start of a function, patch the function to jump
+ // to a given offset into the playground. This function will try to take
+ // advantage of hotpatch code, if the function is prefixed with 5 0x90 bytes.
+ // Returns a std::string of any assembly instructions that must be relocated,
+ // as they were overwritten during patching.
+ std::string PatchPreamble(int func_addr, int playground_off) {
+ sidestep::MiniDisassembler disas;
+ int stub_addr = reinterpret_cast<int>(remote_addr_ + playground_off);
+
+ std::string instrs;
+
+ char buf[15];
+ if (ReadProcessMemory(proc_,
+ reinterpret_cast<void*>(func_addr - 5),
+ buf,
+ sizeof(buf),
+ NULL) == 0) {
+ NOTREACHED("ReadProcessMemory(0x%08x) failed: %d",
+ func_addr - 5, GetLastError());
+ }
+
+ // TODO(deanm): It seems in more recent updates the compiler is generating
+ // complicated sequences for padding / alignment. For example:
+ // 00000000 8DA42400000000 lea esp,[esp+0x0]
+ // 00000007 8D4900 lea ecx,[ecx+0x0]
+ // is used for a 16 byte alignment. We need a better way of handling this.
+ if (memcmp(buf, "\x90\x90\x90\x90\x90", 5) == 0 ||
+ memcmp(buf, "\x00\x8D\x64\x24\x00", 5) == 0 ||
+ memcmp(buf, "\x00\x00\x8D\x49\x00", 5) == 0) {
+ unsigned int instr_bytes = 0;
+
+ // We might have a hotpatch no-op of mov edi, edi "\x8b\xff". It is a
+ // bit of a waste to relocate it, but it makes everything simpler.
+
+ while (instr_bytes < 2) {
+ if (disas.Disassemble(
+ reinterpret_cast<unsigned char*>(buf + 5 + instr_bytes),
+ &instr_bytes) != sidestep::IT_GENERIC) {
+ NOTREACHED("Could not disassemble or relocate instruction.");
+ }
+ // We only read 10 bytes worth of instructions.
+ CHECK(instr_bytes < 10);
+ }
+
+ instrs.assign(buf + 5, instr_bytes);
+
+ // We have a hotpatch prefix of 5 nop bytes. We can use this for our
+ // long jump, and then overwrite the first 2 bytes to jump back to there.
+ CodeBuffer patch(buf);
+ int off = stub_addr - func_addr;
+ patch.jmp_rel(off);
+ patch.jmp_rel_short(-2 - 5);
+ } else {
+ // We need a full 5 bytes for the jump.
+ unsigned int instr_bytes = 0;
+ while (instr_bytes < 5) {
+ if (disas.Disassemble(
+ reinterpret_cast<unsigned char*>(buf + 5 + instr_bytes),
+ &instr_bytes) != sidestep::IT_GENERIC) {
+ NOTREACHED("Could not disassemble or relocate instruction.");
+ }
+ // We only read 10 bytes worth of instructions.
+ CHECK(instr_bytes < 10);
+ }
+
+ instrs.assign(buf + 5, instr_bytes);
+
+ // Overwrite the first 5 bytes with a relative jump to our stub.
+ CodeBuffer patch(buf + 5);
+ int off = stub_addr - (func_addr + 5);
+ patch.jmp_rel(off);
+ }
+
+ // Write back the bytes, we are really probably writing more back than we
+ // need to, but it shouldn't really matter.
+ if (WriteProcessMemory(proc_,
+ reinterpret_cast<void*>(func_addr - 5),
+ buf,
+ sizeof(buf),
+ NULL) == 0) {
+ NOTREACHED("WriteProcessMemory(0x%08x) failed: %d",
+ func_addr - 5, GetLastError());
+ }
+
+ return instrs;
+ }
+
+ std::string PatchPreamble(const char* func_name, int playground_off) {
+ return PatchPreamble(
+ reinterpret_cast<int>(resolver_.Resolve(func_name)), playground_off);
+ }
+
+ // Restore any instructions that needed to be moved to make space for our
+ // patch and jump back to the original code.
+ void ResumeOriginalFunction(const char* func_name,
+ const std::string& moved_instructions,
+ int stub_offset,
+ CodeBuffer* cb) {
+ cb->emit_bytes(moved_instructions);
+ int off = resolver_.Resolve(func_name) +
+ moved_instructions.size() -
+ (remote_addr_ + stub_offset + cb->size() + 5);
+ cb->jmp_rel(off);
+ }
+
+ // Makes a call to NtQueryPerformanceCounter, writing the timestamp to the
+ // buffer pointed to by EDI. EDI it not incremented. EAX is not preserved.
+ void AssembleQueryPerformanceCounter(CodeBuffer* cb) {
+ // Make a call to NtQueryPerformanceCounter and write the result into
+ // the log area. The buffer we write to should be aligned, but we should
+ // garantee that anyway for the logging area for performance.
+ cb->push_imm(0); // PerformanceFrequency
+ cb->push(EDI); // PerformanceCounter
+ cb->mov_imm(EAX, reinterpret_cast<int>(
+ resolver_.Resolve("ntdll!NtQueryPerformanceCounter")));
+ cb->call(EAX);
+ }
+
+ // This is the common log setup routine. It will allocate a new log entry,
+ // and write out the common log header to the event entry. The header is:
+ // is [ 64bit QPC ] [ 32bit cpu id ] [ 32bit thread id ] [ 32bit rec id ]
+ // EDI will be left pointing to the log entry, with |space| bytes left for
+ // type specific data. All other registers should not be clobbered.
+ void AssembleHeaderCode(CodeBuffer* cb, EventRecordType rt, int space) {
+ cb->push(EAX);
+ cb->push(EDX);
+ cb->push(ECX);
+ cb->push(ESI);
+
+ int unwind_depth = options_.stack_unwind_depth();
+
+ // Load EDI with the number of bytes we want for our log entry, this will
+ // be used in the atomic increment to allocate the log entry.
+ cb->mov_imm(EDI, kRecordHeaderSize + (unwind_depth * 4) + space);
+ // Do the increment and have EDI point to our log entry buffer space.
+ cb->mov_imm(EDX, reinterpret_cast<int>(remote_addr_ + kOffLogAreaPtr));
+ cb->inc_atomic(EDX, EDI);
+ // EDI is the buffer offset, make it a pointer to the record entry.
+ cb->add_imm(EDI, reinterpret_cast<int>(remote_addr_ + kOffLogAreaData));
+
+ AssembleQueryPerformanceCounter(cb);
+ cb->add_imm(EDI, 8);
+
+ cb->which_cpu();
+ cb->stosd();
+
+ cb->which_thread();
+ cb->stosd();
+
+ // Stack unwinding, follow EBP to the maximum number of frames, and make
+ // sure that it stays on the stack (between ESP and TEB.StackBase).
+ if (unwind_depth > 0) {
+ cb->mov_imm(ECX, unwind_depth);
+ cb->fs(); cb->mov(EDX, Operand(0x04)); // get TEB.StackBase
+
+ // Start at EBP.
+ cb->mov(EAX, EBP);
+
+ Label unwind_loop, bail;
+ cb->bind(&unwind_loop);
+
+ // Bail if (EAX < ESP) (below the stack)
+ cb->cmp(EAX, ESP);
+ cb->jcc(below, &bail);
+ // Bail if (EAX >= EDX) (above the stack)
+ cb->cmp(EAX, EDX);
+ cb->jcc(above_equal, &bail);
+
+ // We have a valid stack pointer, it should point to something like:
+ // [ saved frame pointer ] [ return address ] [ arguments ... ]
+ cb->mov(ESI, EAX);
+ cb->lodsd(); // Get the new stack pointer to follow in EAX
+ cb->movsd(); // Copy the return address to the log area.
+
+ cb->loop(&unwind_loop);
+
+ cb->bind(&bail);
+ // If we did managed to unwind to the max, fill the rest with 0 (really
+ // we just want to inc EDI to the end, and this is an easy way).
+ cb->mov_imm(EAX, 0); // TODO use an xor
+ cb->rep(); cb->stosd();
+ }
+
+ // Store the type for this record entry.
+ cb->mov_imm(EAX, rt);
+ cb->stosd();
+
+ cb->pop(ESI);
+ cb->pop(ECX);
+ cb->pop(EDX);
+ cb->pop(EAX);
+ }
+
+ void PatchLoader() {
+ static const EventRecordType kRecordType = EVENT_TYPE_LDR;
+ static const char* kFuncName = "ntdll!DebugPrint";
+ static const int kStubOffset = kOffLdrCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ // Set ShowSnaps to one to get the print routines to be called.
+ char enabled = 1;
+ WriteProcessMemory(
+ proc_, resolver_.Resolve("ntdll!ShowSnaps"), &enabled, 1, NULL);
+
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.pop(EDX); // return address
+ cb.pop(EAX); // First param in eax
+ cb.push(ESI);
+ cb.push(EDI);
+ cb.push(EDX);
+
+ cb.mov(ESI, EAX); // ESI points at the string structure.
+
+ // We used to do variable length based on the length supplied in the str
+ // structure, but it's easier (and sloppier) to just copy a fixed amount.
+ AssembleHeaderCode(&cb, kRecordType, kLdrBufSize);
+
+ cb.lodsd(); // Load the character count
+ cb.lodsd(); // Load the char*
+ cb.mov(ESI, EAX);
+ cb.mov_imm(ECX, kLdrBufSize / 4); // load the char count as the rep count
+ cb.rep(); cb.movsb(); // Copy the string to the logging buffer
+
+ // Return
+ cb.pop(EDX);
+ cb.pop(EDI);
+ cb.pop(ESI);
+ cb.pop(ECX); // don't care
+ cb.pop(ECX); // don't care
+ cb.jmp(EDX);
+ }
+
+ void PatchCreateThread() {
+ static const EventRecordType kRecordType = EVENT_TYPE_CREATETHREAD;
+ static const char* kFuncName =
+ options_.vista() ? "ntdll!NtCreateThreadEx" : "ntdll!NtCreateThread";
+ static const int kStubOffset = kOffCreateThreadCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.push(EDI);
+ cb.push(ESI);
+
+ AssembleHeaderCode(&cb, kRecordType, 8);
+
+ cb.mov(EAX, Operand(ESP, 0x18 + 8));
+
+ // Super ugly hack. To coorrelate between creating a thread and the new
+ // thread running, we stash something to identify the creating event when
+ // we log the created event. We just use a pointer to the event log data
+ // since this will be unique and can tie the two events together. We pass
+ // it by writing into the context structure, so it will be passed in ESI.
+ cb.add_imm(EAX, 0xa0);
+ cb.push(EDI);
+ cb.mov(EDI, EAX);
+ cb.pop(EAX);
+ cb.push(EAX);
+ cb.stosd();
+
+ // Get and save CONTEXT.Eip
+ cb.mov(ESI, EDI);
+ cb.add_imm(ESI, 20);
+ cb.pop(EDI);
+ cb.mov(EAX, EDI);
+ cb.stosd(); // Record the event identifier to tie together the events.
+ cb.movsd(); // write Eip to the log event
+
+ cb.pop(ESI);
+ cb.pop(EDI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+ void PatchThreadBegin() {
+ static const EventRecordType kRecordType = EVENT_TYPE_THREADBEGIN;
+ static const char* kFuncName = "ntdll!CsrNewThread";
+ static const int kStubOffset = kOffThreadCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.push(EDI);
+
+ AssembleHeaderCode(&cb, kRecordType, 8);
+
+ cb.mov(EAX, ESI); // We stashed the creator's eventid in the context ESI.
+ cb.stosd();
+
+ // TODO(deanm): The pointer is going to point into the CRT or something,
+ // should we dig deeper to get more information about the real entry?
+ cb.mov(EAX, Operand(EBP, 0x8));
+ cb.stosd();
+ cb.pop(EDI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+ void PatchThreadBeginVista() {
+ static const EventRecordType kRecordType = EVENT_TYPE_THREADBEGIN;
+ static const char* kFuncName = "ntdll!_RtlUserThreadStart";
+ static const int kStubOffset = kOffThreadCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.push(EDI);
+
+ AssembleHeaderCode(&cb, kRecordType, 8);
+
+ cb.mov(EAX, ESI); // We stashed the creator's eventid in the context ESI.
+ cb.stosd();
+
+ // TODO(deanm): The pointer is going to point into the CRT or something,
+ // should we dig deeper to get more information about the real entry?
+ //cb.mov(EAX, Operand(EBP, 0x8));
+ cb.mov_imm(EAX, 0);
+ cb.stosd();
+ cb.pop(EDI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+ // Intercept exception dispatching so we can catch when threads set a thread
+ // name (which is an exception with a special code). TODO it could be
+ // useful to log all exceptions.
+ void PatchSetThreadName() {
+ static const EventRecordType kRecordType = EVENT_TYPE_THREADNAME;
+ static const char* kFuncName = "ntdll!RtlDispatchException";
+ static const int kStubOffset = kOffExpCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.pop(EDX); // return address
+ cb.pop(EAX); // ExceptionRecord
+ cb.push(EAX);
+ cb.push(EDX);
+
+ cb.push(ESI);
+
+ cb.mov(ESI, EAX);
+ cb.lodsd();
+
+ Label bail;
+ // exception code
+ cb.cmp_imm(EAX, 0x406D1388);
+ cb.jcc(not_equal, &bail);
+
+ cb.push(EDI);
+
+ AssembleHeaderCode(&cb, kRecordType, kThreadNameBufSize);
+
+ // Fetch the second parameter.
+ for (int i = 0; i < 6; ++i) {
+ cb.lodsd();
+ }
+
+ // TODO This is sloppy and we could run into unmapped memory...
+ cb.mov(ESI, EAX);
+ cb.mov_imm(ECX, kThreadNameBufSize / 4);
+ cb.rep(); cb.movsd();
+
+ cb.pop(EDI);
+
+ cb.bind(&bail);
+ cb.pop(ESI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+
+ void PatchThreadExit() {
+ static const EventRecordType kRecordType = EVENT_TYPE_THREADEXIT;
+ static const char* kFuncName = "ntdll!LdrShutdownThread";
+ static const int kStubOffset = kOffThreadExitCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.push(EDI);
+ AssembleHeaderCode(&cb, kRecordType, 0);
+ cb.pop(EDI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+ void PatchAllocateHeap() {
+ static const EventRecordType kRecordType = EVENT_TYPE_ALLOCHEAP;
+ static const char* kFuncName = "ntdll!RtlAllocateHeap";
+ static const int kStubOffset = kOffAllocHeapCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.push(EDI);
+ cb.push(ESI);
+
+ AssembleHeaderCode(&cb, kRecordType, 12);
+
+ cb.mov(ESI, ESP);
+ cb.add_imm(ESI, 12); // Skip over our saved and the return address
+ cb.movsd(); cb.movsd(); cb.movsd(); // Copy the 3 parameters
+
+ cb.pop(ESI);
+ cb.pop(EDI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+ void PatchFreeHeap() {
+ static const EventRecordType kRecordType = EVENT_TYPE_FREEHEAP;
+ static const char* kFuncName = "ntdll!RtlFreeHeap";
+ static const int kStubOffset = kOffFreeHeapCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.push(EDI);
+ cb.push(ESI);
+
+ AssembleHeaderCode(&cb, kRecordType, 12);
+
+ cb.mov(ESI, ESP);
+ cb.add_imm(ESI, 12); // Skip over our saved and the return address
+ cb.movsd(); cb.movsd(); cb.movsd(); // Copy the 3 parameters
+
+ cb.pop(ESI);
+ cb.pop(EDI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+ // Don't even bother going back to the original code, just implement our
+ // own KiFastSystemCall. The original looks like:
+ // .text:7C90EB8B mov edx, esp
+ // .text:7C90EB8D sysenter
+ // .text:7C90EB8F nop
+ // .text:7C90EB90 nop
+ // .text:7C90EB91 nop
+ // .text:7C90EB92 nop
+ // .text:7C90EB93 nop
+ void PatchSyscall() {
+ static const EventRecordType kRecordType = EVENT_TYPE_SYSCALL;
+ static const char* kFuncName = "ntdll!KiFastSystemCall";
+ static const int kStubOffset = kOffSyscallCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ {
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ Label skip;
+
+ // Skip 0xa5 which is QueryPerformanceCounter, to make sure we don't log
+ // our own logging's QPC. Disabled for now, using ret addr check...
+ // cb.cmp_imm(EAX, 0xa5);
+ // cb.jcc(equal, &skip);
+
+ // Check if the return address is from 0x6666 (our code region).
+ // 66817C24066666 cmp word [esp+0x6],0x6666
+ cb.emit(0x66); cb.emit(0x81); cb.emit(0x7C);
+ cb.emit(0x24); cb.emit(0x06); cb.emit(0x66); cb.emit(0x66);
+ cb.jcc(equal, &skip);
+
+ // This is all a bit shit. Originally I thought I could store some state
+ // on the stack above ESP, however, it seems that when APCs, etc are
+ // queued, they will use the stack above ESP. Well, not above ESP, above
+ // what was passed in as EDX into the systemcall, not matter if ESP was
+ // different than this :(. So we need to store our state in the event
+ // log record, and then we stick a pointer to that over a ret addr...
+
+ // Our stack starts like:
+ // [ ret addr ] [ ret addr 2 ] [ arguments ]
+ // We will update it to look like
+ // [ ret stub addr ] [ event entry ptr ] [ arguments ]
+
+ cb.push(EDI); // save EDI since we're using it
+ AssembleHeaderCode(&cb, kRecordType, 16 + 16 + 8);
+ cb.mov(EDX, EAX); // Save EAX...
+ cb.stosd(); // eax is the syscall number
+ cb.pop(EAX);
+ cb.stosd(); // store the saved EDI
+ cb.pop(EAX);
+ cb.stosd(); // store the real return address
+ cb.pop(EAX);
+ cb.stosd(); // store the real (secondary) return address;
+
+ cb.push(ESI);
+ cb.mov(ESI, ESP);
+ cb.lodsd();
+ cb.movsd(); // argument 1
+ cb.movsd(); // argument 2
+ cb.movsd(); // argument 3
+ cb.pop(ESI);
+
+ cb.push(EDI); // store our event ptr over the secondary ret addr.
+ cb.push_imm(reinterpret_cast<int>(remote_addr_ + kOffSyscallCode + 200));
+ cb.mov(EAX, EDX); // restore EAX
+
+ cb.bind(&skip);
+ cb.mov(EDX, ESP);
+ cb.sysenter();
+
+ if (cb.size() > 200) {
+ NOTREACHED("code too big: %d", cb.size());
+ }
+ }
+
+ {
+ CodeBuffer cb(buf_ + kStubOffset + 200);
+
+ // TODO share the QPC code, this is a copy and paste...
+
+ cb.pop(EDI); // get the log area
+
+ cb.stosd(); // Log the system call return value.
+
+ // QPC will clobber EAX, and it's very important to save it since it
+ // is the return value from the system call. TODO validate if there is
+ // anything else we need to save...
+ cb.push(EAX);
+ AssembleQueryPerformanceCounter(&cb);
+ cb.pop(EAX);
+
+ // We need to:
+ // - Restore the original "seconary" return address
+ // - Restore the original value of the EDI register
+ // - Jump control flow to the original return address
+ // All 3 of these values are stored in the log record...
+ // [ syscall num ] [ saved edi ] [ real rets ] [ args ] [ retval ] [ ts ]
+ // currently edi points here ----^
+
+ cb.push(Operand(EDI, -4 - 16)); // push the real 2nd ret
+ cb.push(Operand(EDI, -8 - 16)); // push the real ret
+ cb.push(Operand(EDI, -12 - 16)); // push the saved EDI
+
+ cb.pop(EDI); // restore EDI that was saved in the record
+ cb.ret(); // jmp back to the real ret ...
+
+ if (cb.size() > 56) {
+ NOTREACHED("ug");
+ }
+ }
+ }
+
+ // Patch lock (criticial section) holding.
+ void PatchEnterCriticalSection() {
+ static const EventRecordType kRecordType = EVENT_TYPE_ENTER_CS;
+ static const char* kFuncName = "ntdll!RtlEnterCriticalSection";
+ static const int kStubOffset = kOffEnterCritSecCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ // We just want to capture the return address and original argument, so
+ // we know when EnterCriticalSection returned, we don't want to know when
+ // it entered because it could sit waiting. We want to know when the lock
+ // actually started being held. The compiler will sometimes generated code
+ // that overwrites arguments, so we'll keep a copy of the argument just in
+ // case code like this is ever generated in the future. TODO is it enough
+ // to just assume a LPCRITICAL_SECTION uniquely identifies the lock, or
+ // can the same lock have multiple different copies, I would assume not.
+ {
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ // Set up an additional frame so that we capture the return.
+ // TODO use memory instructions instead of using registers.
+ cb.pop(EAX); // return address
+ cb.pop(EDX); // first argument (critical section pointer)
+
+ cb.push(EDX);
+ cb.push(EAX);
+ cb.push(EDX);
+ cb.push_imm(
+ reinterpret_cast<int>(remote_addr_ + kStubOffset + 40));
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ CHECK(cb.size() < 40);
+ }
+
+ {
+ CodeBuffer cb(buf_ + kStubOffset + 40);
+
+ cb.push(ESI);
+ cb.mov(ESI, ESP);
+ cb.push(EAX);
+ cb.push(EDI);
+
+ AssembleHeaderCode(&cb, kRecordType, 4);
+
+ cb.lodsd(); // Skip over our saved ESI
+ cb.lodsd(); // Skip over the return address
+ cb.movsd(); // Write the CRITICAL_SECTION* to the event record.
+
+ cb.pop(EDI);
+ cb.pop(EAX);
+ cb.pop(ESI);
+
+ cb.ret(0x04);
+ }
+ }
+
+ void PatchTryEnterCriticalSection() {
+ static const EventRecordType kRecordType = EVENT_TYPE_TRYENTER_CS;
+ static const char* kFuncName = "ntdll!RtlTryEnterCriticalSection";
+ static const int kStubOffset = kOffTryEnterCritSecCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ {
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ // Set up an additional frame so that we capture the return.
+ // TODO use memory instructions instead of using registers.
+ cb.pop(EAX); // return address
+ cb.pop(EDX); // first argument (critical section pointer)
+
+ cb.push(EDX);
+ cb.push(EAX);
+ cb.push(EDX);
+ cb.push_imm(reinterpret_cast<int>(remote_addr_ + kStubOffset + 40));
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ CHECK(cb.size() < 40);
+ }
+
+ {
+ CodeBuffer cb(buf_ + kStubOffset + 40);
+
+ cb.push(ESI);
+ cb.mov(ESI, ESP);
+ cb.push(EDI);
+
+ cb.push(EAX);
+
+ AssembleHeaderCode(&cb, kRecordType, 8);
+
+ cb.lodsd(); // Skip over our saved ESI
+ cb.lodsd(); // Skip over the return address
+ cb.movsd(); // Write the CRITICAL_SECTION* to the event record.
+
+ cb.pop(EAX);
+ cb.stosd(); // Write the return value to the event record.
+
+ cb.pop(EDI);
+ cb.pop(ESI);
+
+ cb.ret(0x04);
+ }
+ }
+
+ void PatchLeaveCriticalSection() {
+ static const EventRecordType kRecordType = EVENT_TYPE_LEAVE_CS;
+ static const char* kFuncName = "ntdll!RtlLeaveCriticalSection";
+ static const int kStubOffset = kOffLeaveCritSecCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ // TODO use memory instructions instead of using registers.
+ cb.pop(EDX); // return address
+ cb.pop(EAX); // first argument (critical section pointer)
+ cb.push(EAX);
+ cb.push(EDX);
+
+ cb.push(EDI);
+ AssembleHeaderCode(&cb, kRecordType, 4);
+ cb.stosd(); // Write the CRITICAL_SECTION* to the event record.
+ cb.pop(EDI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+ // Patch APC dispatching. This is a bit hacky, since the return to kernel
+ // mode is done with NtContinue, we have to shim in a stub return address to
+ // catch when the callback is finished. It is probably a bit fragile.
+ void PatchApcDispatcher() {
+ static const EventRecordType kRecordType = EVENT_TYPE_APC;
+ static const char* kFuncName = "ntdll!KiUserApcDispatcher";
+ static const int kStubOffset = kOffApcDispCode;
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+
+ {
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ // We don't really need to preserve these since we're the first thing
+ // executing from the kernel dispatch, but yeah, it is good practice.
+ cb.push(EDI);
+ cb.push(EAX);
+
+ AssembleHeaderCode(&cb, kRecordType, 4 + 4 + 8);
+
+ cb.mov_imm(EAX, reinterpret_cast<int>(remote_addr_ + kStubOffset + 140));
+ cb.xchg(EAX, Operand(ESP, 8)); // Swap the callback address with ours.
+ cb.stosd(); // Store the original callback function address.
+
+ // TODO for now we're lazy and depend that ESI will be preserved, and we
+ // use it to store the pointer into our log record. EDI isn't preserved.
+ cb.mov(ESI, EDI);
+
+ cb.pop(EAX);
+ cb.pop(EDI);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+
+ CHECK(cb.size() < 140);
+ }
+ {
+ CodeBuffer cb(buf_ + kStubOffset + 140);
+
+ // This is our shim, we need to call the original callback function, then
+ // we can catch the return and log when it was completed.
+ cb.pop(EAX); // The real return address, safe to use EAX w/ the ABI?
+ cb.push(EDI);
+
+ cb.mov(EDI, ESI);
+ cb.stosd(); // Store the real return address, we'll need it.
+
+ cb.add_imm(ESI, -4);
+ cb.lodsd(); // Load the real callback address.
+
+ cb.mov(ESI, EDI);
+ cb.pop(EDI);
+
+ cb.call(EAX); // Call the original callback address.
+
+ cb.push(EAX);
+ cb.push(EDI);
+
+ cb.mov(EDI, ESI);
+ AssembleQueryPerformanceCounter(&cb);
+
+ cb.pop(EDI);
+ cb.pop(EAX);
+
+ cb.push(Operand(ESI, -4)); // Push the real return address.
+ cb.ret(); // Return back to the APC Dispatcher.
+
+ CHECK(cb.size() < 50);
+ }
+ }
+
+ // We need to hook into process shutdown for two reasons. Most importantly,
+ // we need to copy the playground back from the process before the address
+ // space goes away. We could avoid this with shared memory, however, there
+ // is a reason two. In order to capture symbols for all of the libraries
+ // loaded into arbitrary applications, on shutdown we do an instrusive load
+ // of symbols into the traced process.
+ //
+ // ntdll!LdrShutdownProcess
+ // - NtSetEvent(event, 0);
+ // - NtWaitForSingleObject(event, FALSE, NULL);
+ // - jmp back
+ void PatchExit(HANDLE exiting, HANDLE exited) {
+ static const EventRecordType kRecordType = EVENT_TYPE_PROCESSEXIT;
+ static const char* kFuncName = "ntdll!LdrShutdownProcess";
+ static const int kStubOffset = kOffExitCode;
+
+ HANDLE rexiting, rexited;
+ if (!DuplicateHandle(::GetCurrentProcess(),
+ exiting,
+ proc_,
+ &rexiting,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ NOTREACHED("");
+ }
+ if (!DuplicateHandle(::GetCurrentProcess(),
+ exited,
+ proc_,
+ &rexited,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS)) {
+ NOTREACHED("");
+ }
+
+ std::string moved_instructions = PatchPreamble(kFuncName, kStubOffset);
+ CodeBuffer cb(buf_ + kStubOffset);
+
+ cb.push(EDI);
+ AssembleHeaderCode(&cb, kRecordType, 0);
+ cb.pop(EDI);
+
+ // NtSetEvent(exiting, 0);
+ cb.push_imm(0);
+ cb.push_imm(reinterpret_cast<int>(rexiting));
+ cb.mov_imm(EAX, reinterpret_cast<int>(
+ resolver_.Resolve("ntdll!NtSetEvent")));
+ cb.call(EAX);
+
+ // NtWaitForSingleObject(exited, FALSE, INFINITE);
+ cb.push_imm(0);
+ cb.push_imm(0);
+ cb.push_imm(reinterpret_cast<int>(rexited));
+ cb.mov_imm(EAX, reinterpret_cast<int>(
+ resolver_.Resolve("ntdll!NtWaitForSingleObject")));
+ cb.call(EAX);
+
+ ResumeOriginalFunction(kFuncName, moved_instructions, kStubOffset, &cb);
+ }
+
+
+ void Patch() {
+ if (options_.vista()) {
+ // TODO(deanm): Make PatchCreateThread work on Vista.
+ PatchThreadBeginVista();
+ } else {
+ PatchCreateThread();
+ PatchThreadBegin();
+ }
+
+ PatchThreadExit();
+ PatchSetThreadName();
+ PatchSyscall();
+
+ PatchApcDispatcher();
+
+ // The loader logging needs to be improved a bit to really be useful.
+ //PatchLoader();
+
+ // These are interesting, but will collect a ton of data:
+ if (options_.log_heap()) {
+ PatchAllocateHeap();
+ PatchFreeHeap();
+ }
+ if (options_.log_lock()) {
+ PatchEnterCriticalSection();
+ PatchTryEnterCriticalSection();
+ PatchLeaveCriticalSection();
+ }
+ }
+
+ // Dump the event records from the playground to stdout in a JSON format.
+ // TODO: Drop RDTSCNormalizer, it was from old code that tried to use the
+ // rdtsc counters from the CPU, and this required a bunch of normalization
+ // to account for non-syncronized timestamps across different cores, etc.
+ void DumpJSON(RDTSCNormalizer* rdn, SymResolver* res) {
+ int pos = kOffLogAreaPtr;
+ int i = IntAt(pos);
+ pos += 4;
+
+ std::map<int, const char*> syscalls = CreateSyscallMap();
+
+ printf("parseEvents([\n");
+ for (int end = pos + i; pos < end; ) {
+ printf("{\n");
+ __int64 ts = Int64At(pos);
+ pos += 8;
+ void* cpuid = reinterpret_cast<void*>(IntAt(pos));
+ pos += 4;
+ printf("'ms': %f,\n", rdn->MsFromStart(cpuid, ts));
+
+ printf("'cpu': 0x%x,\n'thread': 0x%x,\n", cpuid, IntAt(pos));
+ pos += 4;
+
+ if (options_.stack_unwind_depth() > 0) {
+ printf("'stacktrace': [\n");
+ for (int i = 0; i < options_.stack_unwind_depth(); ++i) {
+ int retaddr = IntAt(pos + (i * 4));
+ if (!retaddr)
+ break;
+ printf(" [ 0x%x, %s ],\n",
+ retaddr,
+ res ? JSONString(res->Unresolve(retaddr)).c_str() : "\"\"");
+ }
+ printf("],\n");
+ pos += (options_.stack_unwind_depth() * 4);
+ }
+
+
+ EventRecordType rt = static_cast<EventRecordType>(IntAt(pos));
+ pos += 4;
+
+ switch (rt) {
+ case EVENT_TYPE_LDR:
+ {
+ printf("'eventtype': 'EVENT_TYPE_LDR',\n");
+ std::string str(&buf_[pos], kLdrBufSize);
+ str = str.substr(0, str.find('\0'));
+ printf("'ldrinfo': %s,\n", JSONString(str).c_str());
+ pos += kLdrBufSize;
+ break;
+ }
+ case EVENT_TYPE_CREATETHREAD:
+ {
+ printf("'eventtype': 'EVENT_TYPE_CREATETHREAD',\n"
+ "'eventid': 0x%x,\n"
+ "'startaddr': 0x%x,\n",
+ IntAt(pos), IntAt(pos+4));
+ pos += 8;
+ break;
+ }
+ case EVENT_TYPE_THREADBEGIN:
+ {
+ printf("'eventtype': 'EVENT_TYPE_THREADBEGIN',\n"
+ "'parenteventid': 0x%x,\n"
+ "'startaddr': 0x%x,\n",
+ IntAt(pos), IntAt(pos+4));
+ pos += 8;
+ break;
+ }
+ case EVENT_TYPE_THREADNAME:
+ {
+ std::string str(&buf_[pos], kThreadNameBufSize);
+ str = str.substr(0, str.find('\0'));
+ printf("'eventtype': 'EVENT_TYPE_THREADNAME',\n"
+ "'threadname': %s,\n",
+ JSONString(str).c_str());
+ pos += kThreadNameBufSize;
+ break;
+ }
+ case EVENT_TYPE_PROCESSEXIT:
+ {
+ printf("'eventtype': 'EVENT_TYPE_PROCESSEXIT',\n");
+ break;
+ }
+ case EVENT_TYPE_THREADEXIT:
+ {
+ printf("'eventtype': 'EVENT_TYPE_THREADEXIT',\n");
+ break;
+ }
+ case EVENT_TYPE_ALLOCHEAP:
+ {
+ printf("'eventtype': 'EVENT_TYPE_ALLOCHEAP',\n"
+ "'heaphandle': 0x%x,\n"
+ "'heapflags': 0x%x,\n"
+ "'heapsize': %d,\n",
+ IntAt(pos), IntAt(pos+4), IntAt(pos+8));
+ pos += 12;
+ break;
+ }
+ case EVENT_TYPE_FREEHEAP:
+ {
+ printf("'eventtype': 'EVENT_TYPE_FREEHEAP',\n"
+ "'heaphandle': 0x%x,\n"
+ "'heapflags': 0x%x,\n"
+ "'heapptr': %d,\n",
+ IntAt(pos), IntAt(pos+4), IntAt(pos+8));
+ pos += 12;
+ break;
+ }
+ case EVENT_TYPE_SYSCALL:
+ {
+ int syscall = IntAt(pos);
+ printf("'eventtype': 'EVENT_TYPE_SYSCALL',\n"
+ "'syscall': 0x%x,\n", syscall);
+ pos += 16;
+
+ printf("'syscallargs': [\n");
+ for (int i = 0; i < 3; ++i) {
+ printf(" 0x%x,\n", IntAt(pos));
+ pos += 4;
+ }
+ printf("],\n");
+
+ printf("'retval': 0x%x,\n"
+ "'done': %f,\n",
+ IntAt(pos), rdn->MsFromStart(0, Int64At(pos+4)));
+ pos += 12;
+
+ if (syscalls.count(syscall) == 1) {
+ std::string sname = syscalls[syscall];
+ printf("'syscallname': %s,\n",
+ JSONString(sname).c_str());
+ // Mark system calls that we should consider "waiting" system
+ // calls, where we are not actually active.
+ if (sname.find("WaitFor") != std::string::npos ||
+ sname.find("RemoveIoCompletion") != std::string::npos) {
+ printf("'waiting': 1,\n");
+ }
+ }
+ break;
+ }
+ case EVENT_TYPE_ENTER_CS:
+ {
+ printf("'eventtype': 'EVENT_TYPE_ENTER_CS',\n"
+ "'critical_section': 0x%x,\n", IntAt(pos));
+ pos += 4;
+ break;
+ }
+ case EVENT_TYPE_TRYENTER_CS:
+ {
+ printf("'eventtype': 'EVENT_TYPE_TRYENTER_CS',\n"
+ "'critical_section': 0x%x,\n"
+ "'retval': 0x%x,\n",
+ IntAt(pos), IntAt(pos+4));
+ pos += 8;
+ break;
+ }
+ case EVENT_TYPE_LEAVE_CS:
+ {
+ printf("'eventtype': 'EVENT_TYPE_LEAVE_CS',\n"
+ "'critical_section': 0x%x,\n", IntAt(pos));
+ pos += 4;
+ break;
+ }
+ case EVENT_TYPE_APC:
+ {
+ int func_addr = IntAt(pos);
+ printf("'eventtype': 'EVENT_TYPE_APC',\n"
+ "'func_addr': 0x%x,\n"
+ "'func_addr_name': %s,\n"
+ "'ret_addr': 0x%x,\n"
+ "'done': %f,\n",
+ func_addr,
+ res ? JSONString(res->Unresolve(func_addr)).c_str() : "\"\"",
+ IntAt(pos+4), rdn->MsFromStart(0, Int64At(pos+8)));
+ pos += 16;
+ break;
+ }
+ default:
+ NOTREACHED("Unknown event type: %d", rt);
+ break;
+ }
+ printf("},\n");
+ }
+ printf("]);");
+ }
+
+ int IntAt(int pos) { return *reinterpret_cast<int*>(&buf_[pos]); }
+ __int64 Int64At(int pos) { return *reinterpret_cast<__int64*>(&buf_[pos]); }
+
+
+ private:
+ // Handle the process we install into or read back from.
+ HANDLE proc_;
+ // The address where we will keep our playground in the remote process.
+ char* remote_addr_;
+ // Lookup addresses from symbol names for ntdll.dll.
+ SymResolver resolver_;
+ Options options_;
+ // A local copy of the playground data, we copy it into the remote process.
+ char buf_[kPlaygroundSize];
+};
+
+
+int main(int argc, char** argv) {
+ std::string command_line;
+ bool use_symbols = false;
+ bool attaching = false;
+ bool launched = false;
+ bool manual_quit = false;
+
+ Playground::Options options;
+
+ PROCESS_INFORMATION info = {0};
+
+ argc--; argv++;
+
+ while (argc > 0) {
+ if (std::string("--symbols") == argv[0]) {
+ use_symbols = true;
+ } else if (std::string("--vista") == argv[0]) {
+ options.set_vista(true);
+ } else if (std::string("--log-heap") == argv[0]) {
+ options.set_log_heap(true);
+ } else if (std::string("--log-lock") == argv[0]) {
+ options.set_log_lock(true);
+ } else if (std::string("--manual-quit") == argv[0]) {
+ manual_quit = true;
+ } else if (argc >= 2 && std::string("--unwind") == argv[0]) {
+ options.set_stack_unwind_depth(atoi(argv[1]));
+ argc--; argv++;
+ } else if (argc >= 2 && !launched && std::string("--attach") == argv[0]) {
+ attaching = true;
+ info.hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, atoi(argv[1]));
+ launched = true;
+ argc--; argv++;
+ } else if (!launched) {
+ STARTUPINFOA start_info = {0};
+ start_info.cb = sizeof(start_info);
+
+ if (!CreateProcessA(NULL,
+ argv[0],
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_SUSPENDED,
+ NULL,
+ NULL,
+ &start_info,
+ &info)) {
+ NOTREACHED("Failed to launch \"%s\": %d\n", argv[0], GetLastError());
+ return 1;
+ }
+ launched = true;
+ } else {
+ NOTREACHED("error parsing command line.");
+ }
+ argc--; argv++;
+ }
+
+ if (!launched) {
+ printf("usage: traceline.exe \"app.exe my arguments\"\n"
+ " --attach 123: buggy support for attaching to a process\n"
+ " --unwind 16: unwind the stack to the specified max depth\n"
+ " --symbols: use symbols for stacktraces\n"
+ " --log-heap: log heap operations (alloc / free).\n"
+ " --log-lock: log lock (critical section) operations.\n");
+ return 1;
+ }
+
+
+ HANDLE exiting = CreateEvent(NULL, FALSE, FALSE, NULL);
+ HANDLE exited = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ // The playground object is big (32MB), dynamically alloc.
+ Playground* pg = new Playground(info.hProcess, options);
+
+ pg->AllocateInRemote();
+ pg->Patch();
+ pg->PatchExit(exiting, exited);
+ pg->CopyToRemote();
+
+ RDTSCNormalizer rdn;
+ rdn.Start();
+
+ if (!attaching)
+ ResumeThread(info.hThread);
+
+ // Wait until we have been notified that it's exiting.
+ if (manual_quit) {
+ fprintf(stderr, "Press enter when you want stop tracing and collect.\n");
+ fflush(stderr);
+ getchar();
+ } else {
+ HANDLE whs[] = {exiting, info.hProcess};
+ if (WaitForMultipleObjects(2, whs, FALSE, INFINITE) != WAIT_OBJECT_0) {
+ NOTREACHED("Failed to correctly capture process shutdown.");
+ }
+ }
+
+ pg->CopyFromRemote();
+
+ if (use_symbols) {
+ // Break in and get the symbols...
+ SymResolver res(NULL, info.hProcess);
+ pg->DumpJSON(&rdn, &res);
+ } else {
+ pg->DumpJSON(&rdn, NULL);
+ }
+
+ // Notify that it can exit now, we are done.
+ SetEvent(exited);
+
+ CloseHandle(info.hProcess);
+ CloseHandle(info.hThread);
+
+ delete pg;
+}
diff --git a/chromium/tools/traceline/traceline/rdtsc.h b/chromium/tools/traceline/traceline/rdtsc.h
new file mode 100644
index 00000000000..7c3cb1a9676
--- /dev/null
+++ b/chromium/tools/traceline/traceline/rdtsc.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TRACELINE_RDTSC_H_
+#define TRACELINE_RDTSC_H_
+
+#include <windows.h>
+#include <powrprof.h>
+
+#include <map>
+
+#include "logging.h"
+
+class RDTSCNormalizer {
+ public:
+ RDTSCNormalizer() { }
+ ~RDTSCNormalizer() { }
+
+ void Start() {
+ LARGE_INTEGER freq, now;
+ if (QueryPerformanceFrequency(&freq) == 0) {
+ NOTREACHED("");
+ }
+ freq_ = freq.QuadPart;
+
+ if (QueryPerformanceCounter(&now) == 0) {
+ NOTREACHED("");
+ }
+ start_ = now.QuadPart;
+ }
+
+ // Calculate the time from start for a given processor.
+ double MsFromStart(void* procid, __int64 stamp) {
+ return (stamp - start_) / (freq_ / 1000.0);
+ }
+
+ private:
+ __int64 freq_;
+ __int64 start_;
+};
+
+#endif // TRACELINE_RDTSC_H_
diff --git a/chromium/tools/traceline/traceline/scripts/__init__.py b/chromium/tools/traceline/traceline/scripts/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/__init__.py
diff --git a/chromium/tools/traceline/traceline/scripts/alloc.py b/chromium/tools/traceline/traceline/scripts/alloc.py
new file mode 100755
index 00000000000..ee4af220d59
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/alloc.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+from syscalls import syscalls
+
+
+def parseEvents(z):
+ calls = { }
+ for e in z:
+ if e['eventtype'] == 'EVENT_TYPE_SYSCALL' and e['syscall'] == 17:
+ delta = e['done'] - e['ms']
+ tid = e['thread']
+ ms = e['ms']
+ print '%f - %f - %x' % (
+ delta, ms, tid)
+
+
+def main():
+ execfile(sys.argv[1])
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/traceline/traceline/scripts/crit_sec.js b/chromium/tools/traceline/traceline/scripts/crit_sec.js
new file mode 100644
index 00000000000..906bba10f0a
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/crit_sec.js
@@ -0,0 +1,87 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// You should run this with v8, like v8_shell alloc.js datafile.json
+
+function toHex(num) {
+ var str = "";
+ var table = "0123456789abcdef";
+ while (num != 0) {
+ str = table.charAt(num & 0xf) + str;
+ num >>= 4;
+ }
+ return str;
+}
+
+function parseEvents(z) {
+ var crits = { }
+ var calls = { }
+
+ for (var i = 0, il = z.length; i < il; ++i) {
+ var e = z[i];
+
+ if (e['eventtype'] == 'EVENT_TYPE_ENTER_CS' ||
+ e['eventtype'] == 'EVENT_TYPE_TRYENTER_CS' ||
+ e['eventtype'] == 'EVENT_TYPE_LEAVE_CS') {
+ cs = e['critical_section'];
+ if (!(cs in crits)) {
+ crits[cs] = [ ];
+ }
+ crits[cs].push(e);
+ }
+ }
+
+ // Verify that the locks get unlocked, and operations stay on the same thread.
+ for (var key in crits) {
+ var cs = key;
+ var es = crits[key];
+
+ var tid_stack = [ ];
+ for (var j = 0, jl = es.length; j < jl; ++j) {
+ var e = es[j];
+ if (e['eventtype'] == 'EVENT_TYPE_ENTER_CS') {
+ tid_stack.push(e);
+ } else if (e['eventtype'] == 'EVENT_TYPE_TRYENTER_CS') {
+ if (e['retval'] != 0)
+ tid_stack.push(e);
+ } else if (e['eventtype'] == 'EVENT_TYPE_LEAVE_CS') {
+ if (tid_stack.length == 0) {
+ print('fail ' + e);
+ }
+ var tid = tid_stack.pop()
+ if (tid['thread'] != e['thread']) {
+ print('fail ' + tid);
+ }
+ }
+ }
+ }
+
+ // Look for long-held / contended locks. We can't really know it is
+ // contended without looking if anyone is waiting on the embedded event...
+ // Just look for locks are are held a long time? Not so good...
+ for (var key in crits) {
+ var cs = key;
+ var es = crits[key];
+
+ var tid_stack = [ ];
+ for (var j = 0, jl = es.length; j < jl; ++j) {
+ var e = es[j];
+ if (e['eventtype'] == 'EVENT_TYPE_ENTER_CS') {
+ tid_stack.push(e);
+ } else if (e['eventtype'] == 'EVENT_TYPE_TRYENTER_CS') {
+ if (e['retval'] != 0)
+ tid_stack.push(e);
+ } else if (e['eventtype'] == 'EVENT_TYPE_LEAVE_CS') {
+ if (tid_stack.length == 0) {
+ print('fail ' + e);
+ }
+ var tid = tid_stack.pop();
+ var dur = e['ms'] - tid['ms'];
+ if (dur > 0.1) {
+ print('Lock: 0x' + toHex(cs) + ' for ' + dur + ' at: ' + e['ms']);
+ }
+ }
+ }
+ }
+}
diff --git a/chromium/tools/traceline/traceline/scripts/crit_sec.py b/chromium/tools/traceline/traceline/scripts/crit_sec.py
new file mode 100755
index 00000000000..ee710bd2032
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/crit_sec.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import os
+
+from syscalls import syscalls
+
+
+def parseEvents(z):
+ crits = { }
+ calls = { }
+ for e in z:
+ if (e['eventtype'] == 'EVENT_TYPE_ENTER_CS' or
+ e['eventtype'] == 'EVENT_TYPE_TRYENTER_CS' or
+ e['eventtype'] == 'EVENT_TYPE_LEAVE_CS'):
+ cs = e['critical_section']
+ if not crits.has_key(cs):
+ crits[cs] = [ ]
+ crits[cs].append(e)
+
+# for cs, es in crits.iteritems():
+# print 'cs: 0x%08x' % cs
+# for e in es:
+# print ' 0x%08x - %s - %f' % (e['thread'], e['eventtype'], e['ms'])
+
+ for cs, es in crits.iteritems():
+ print 'cs: 0x%08x' % cs
+
+ tid_stack = [ ]
+ for e in es:
+ if e['eventtype'] == 'EVENT_TYPE_ENTER_CS':
+ tid_stack.append(e)
+ elif e['eventtype'] == 'EVENT_TYPE_TRYENTER_CS':
+ if e['retval'] != 0:
+ tid_stack.append(e)
+ elif e['eventtype'] == 'EVENT_TYPE_LEAVE_CS':
+ if not tid_stack:
+ raise repr(e)
+ tid = tid_stack.pop()
+ if tid['thread'] != e['thread']:
+ raise repr(tid) + '--' + repr(e)
+
+ # Critical section left locked?
+ if tid_stack:
+ #raise repr(tid_stack)
+ pass
+
+
+def main():
+ execfile(sys.argv[1])
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/traceline/traceline/scripts/filter_short.py b/chromium/tools/traceline/traceline/scripts/filter_short.py
new file mode 100755
index 00000000000..1b73bf96af0
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/filter_short.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Takes an input JSON, and filters out all system call events that
+took less than 0.2ms.
+
+This helps trim down the JSON data to only the most interesting / time critical
+events.
+"""
+
+import sys
+import re
+
+
+def parseEvents(z):
+ print 'parseEvents(['
+ for e in z:
+ if e.has_key('ms') and e.has_key('done'):
+ dur = e['done'] - e['ms']
+ if dur < 0.2:
+ continue
+ # Ugly regex to remove the L suffix on large python numbers.
+ print '%s,' % re.sub('([0-9])L\\b', '\\1', str(e))
+ print '])'
+
+
+def main():
+ execfile(sys.argv[1])
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/traceline/traceline/scripts/filter_split.sh b/chromium/tools/traceline/traceline/scripts/filter_split.sh
new file mode 100755
index 00000000000..876488e3111
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/filter_split.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Runs filter_short on the individual splits of a json file, and puts
+# everything back together into a single output json. This is useful when you
+# want to filter a large json file that would otherwise OOM Python.
+
+echo "parseEvents([" > totalsplit
+for f in split.*; do
+ ./scripts/filter_short.py "$f" | tail -n +2 | head -n -1 >> totalsplit
+done
+echo "]);" >> totalsplit
diff --git a/chromium/tools/traceline/traceline/scripts/heap.js b/chromium/tools/traceline/traceline/scripts/heap.js
new file mode 100644
index 00000000000..9025ac3d95f
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/heap.js
@@ -0,0 +1,69 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// You should run this with v8, like v8_shell alloc.js datafile.json
+
+function toHex(num) {
+ var str = "";
+ var table = "0123456789abcdef";
+ while (num != 0) {
+ str = table.charAt(num & 0xf) + str;
+ num >>= 4;
+ }
+ return str;
+}
+
+function dump(obj) {
+ for (var key in obj) {
+ print('key: ' + key);
+ print(' ' + obj[key]);
+ }
+}
+
+function TopN(n) {
+ this.n = n;
+ this.min = 0;
+ this.sorted = [ ];
+}
+
+TopN.prototype.add =
+function(num, data) {
+ if (num < this.min)
+ return;
+
+ this.sorted.push([num, data]);
+ this.sorted.sort(function(a, b) { return b[0] - a[0] });
+ if (this.sorted.length > this.n)
+ this.sorted.pop();
+
+ this.min = this.sorted[this.sorted.lenth - 1];
+};
+
+TopN.prototype.datas =
+function() {
+ var datas = [ ];
+ for (var i = 0, il = this.sorted.length; i < il; ++i) {
+ datas.push(this.sorted[i][1]);
+ }
+ return datas;
+};
+
+function parseEvents(z) {
+ var topper = new TopN(1000);
+
+ // Find the largest allocation.
+ for (var i = 0, il = z.length; i < il; ++i) {
+ var e = z[i];
+
+ if (e['eventtype'] == 'EVENT_TYPE_ALLOCHEAP') {
+ var size = e['heapsize'];
+ topper.add(e['heapsize'], e);
+ }
+ }
+
+ var datas = topper.datas();
+ for (var i = 0, il = datas.length; i < il; ++i) {
+ dump(datas[i]);
+ }
+}
diff --git a/chromium/tools/traceline/traceline/scripts/scstats.py b/chromium/tools/traceline/traceline/scripts/scstats.py
new file mode 100755
index 00000000000..e2f28dc94a1
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/scstats.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+from syscalls import syscalls
+
+
+def parseEvents(z):
+ calls = { }
+ for e in z:
+ if e['eventtype'] == 'EVENT_TYPE_SYSCALL' and e['done'] > 0:
+ delta = e['done'] - e['ms']
+ syscall = e['syscall']
+ tid = e['thread']
+ ms = e['ms']
+ calls[syscall] = calls.get(syscall, 0) + delta
+ print '%f - %f - %x - %d %s' % (
+ delta, ms, tid, syscall, syscalls.get(syscall, 'unknown'))
+
+ #for syscall, delta in calls.items():
+ # print '%f - %d %s' % (delta, syscall, syscalls.get(syscall, 'unknown'))
+
+
+def main():
+ execfile(sys.argv[1])
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/traceline/traceline/scripts/split.py b/chromium/tools/traceline/traceline/scripts/split.py
new file mode 100755
index 00000000000..6f20e0457e4
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/split.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Splits a single json file (read from stdin) into separate files of 40k
+records, named split.X.
+"""
+
+import sys
+
+
+def main():
+ filecount = 0
+ count = 0
+ f = open('split.0', 'wb')
+ for l in sys.stdin:
+ if l == "},\r\n":
+ count += 1
+ if count == 40000:
+ f.write("}]);\r\n")
+ count = 0
+ filecount += 1
+ f = open('split.%d' % filecount, 'wb')
+ f.write("parseEvents([\r\n")
+ continue
+ f.write(l)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/traceline/traceline/scripts/syscalls.py b/chromium/tools/traceline/traceline/scripts/syscalls.py
new file mode 100644
index 00000000000..6800b45c128
--- /dev/null
+++ b/chromium/tools/traceline/traceline/scripts/syscalls.py
@@ -0,0 +1,942 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+syscalls = {
+0: "ntdll.dll!NtAcceptConnectPort",
+1: "ntdll.dll!NtAccessCheck",
+2: "ntdll.dll!ZwAccessCheckAndAuditAlarm",
+3: "ntdll.dll!NtAccessCheckByType",
+4: "ntdll.dll!NtAccessCheckByTypeAndAuditAlarm",
+5: "ntdll.dll!NtAccessCheckByTypeResultList",
+6: "ntdll.dll!NtAccessCheckByTypeResultListAndAuditAlarm",
+7: "ntdll.dll!ZwAccessCheckByTypeResultListAndAuditAlarmByHandle",
+8: "ntdll.dll!NtAddAtom",
+9: "ntdll.dll!ZwAddBootEntry",
+10: "ntdll.dll!ZwAdjustGroupsToken",
+11: "ntdll.dll!ZwAdjustPrivilegesToken",
+12: "ntdll.dll!NtAlertResumeThread",
+13: "ntdll.dll!NtAlertThread",
+14: "ntdll.dll!ZwAllocateLocallyUniqueId",
+15: "ntdll.dll!NtAllocateUserPhysicalPages",
+16: "ntdll.dll!NtAllocateUuids",
+17: "ntdll.dll!NtAllocateVirtualMemory",
+18: "ntdll.dll!ZwAreMappedFilesTheSame",
+19: "ntdll.dll!ZwAssignProcessToJobObject",
+20: "ntdll.dll!ZwCallbackReturn",
+21: "ntdll.dll!NtCancelDeviceWakeupRequest",
+22: "ntdll.dll!ZwCancelIoFile",
+23: "ntdll.dll!ZwCancelTimer",
+24: "ntdll.dll!NtClearEvent",
+25: "ntdll.dll!NtClose",
+26: "ntdll.dll!ZwCloseObjectAuditAlarm",
+27: "ntdll.dll!NtCompactKeys",
+28: "ntdll.dll!ZwCompareTokens",
+29: "ntdll.dll!NtCompleteConnectPort",
+30: "ntdll.dll!ZwCompressKey",
+31: "ntdll.dll!NtConnectPort",
+32: "ntdll.dll!ZwContinue",
+33: "ntdll.dll!ZwCreateDebugObject",
+34: "ntdll.dll!ZwCreateDirectoryObject",
+35: "ntdll.dll!NtCreateEvent",
+36: "ntdll.dll!NtCreateEventPair",
+37: "ntdll.dll!NtCreateFile",
+38: "ntdll.dll!NtCreateIoCompletion",
+39: "ntdll.dll!ZwCreateJobObject",
+40: "ntdll.dll!NtCreateJobSet",
+41: "ntdll.dll!ZwCreateKey",
+42: "ntdll.dll!ZwCreateMailslotFile",
+43: "ntdll.dll!ZwCreateMutant",
+44: "ntdll.dll!ZwCreateNamedPipeFile",
+45: "ntdll.dll!NtCreatePagingFile",
+46: "ntdll.dll!ZwCreatePort",
+47: "ntdll.dll!ZwCreateProcess",
+48: "ntdll.dll!ZwCreateProcessEx",
+49: "ntdll.dll!ZwCreateProfile",
+50: "ntdll.dll!NtCreateSection",
+51: "ntdll.dll!NtCreateSemaphore",
+52: "ntdll.dll!ZwCreateSymbolicLinkObject",
+53: "ntdll.dll!NtCreateThread",
+54: "ntdll.dll!ZwCreateTimer",
+55: "ntdll.dll!NtCreateToken",
+56: "ntdll.dll!ZwCreateWaitablePort",
+57: "ntdll.dll!NtDebugActiveProcess",
+58: "ntdll.dll!ZwDebugContinue",
+59: "ntdll.dll!ZwDelayExecution",
+60: "ntdll.dll!ZwDeleteAtom",
+61: "ntdll.dll!NtDeleteBootEntry",
+62: "ntdll.dll!NtDeleteFile",
+63: "ntdll.dll!ZwDeleteKey",
+64: "ntdll.dll!NtDeleteObjectAuditAlarm",
+65: "ntdll.dll!NtDeleteValueKey",
+66: "ntdll.dll!ZwDeviceIoControlFile",
+67: "ntdll.dll!NtDisplayString",
+68: "ntdll.dll!ZwDuplicateObject",
+69: "ntdll.dll!NtDuplicateToken",
+70: "ntdll.dll!ZwEnumerateBootEntries",
+71: "ntdll.dll!ZwEnumerateKey",
+72: "ntdll.dll!ZwEnumerateSystemEnvironmentValuesEx",
+73: "ntdll.dll!NtEnumerateValueKey",
+74: "ntdll.dll!ZwExtendSection",
+75: "ntdll.dll!NtFilterToken",
+76: "ntdll.dll!NtFindAtom",
+77: "ntdll.dll!ZwFlushBuffersFile",
+78: "ntdll.dll!ZwFlushInstructionCache",
+79: "ntdll.dll!NtFlushKey",
+80: "ntdll.dll!ZwFlushVirtualMemory",
+81: "ntdll.dll!NtFlushWriteBuffer",
+82: "ntdll.dll!NtFreeUserPhysicalPages",
+83: "ntdll.dll!NtFreeVirtualMemory",
+84: "ntdll.dll!NtFsControlFile",
+85: "ntdll.dll!NtGetContextThread",
+86: "ntdll.dll!NtGetDevicePowerState",
+87: "ntdll.dll!ZwGetPlugPlayEvent",
+88: "ntdll.dll!NtGetWriteWatch",
+89: "ntdll.dll!NtImpersonateAnonymousToken",
+90: "ntdll.dll!ZwImpersonateClientOfPort",
+91: "ntdll.dll!ZwImpersonateThread",
+92: "ntdll.dll!ZwInitializeRegistry",
+93: "ntdll.dll!NtInitiatePowerAction",
+94: "ntdll.dll!ZwIsProcessInJob",
+95: "ntdll.dll!NtIsSystemResumeAutomatic",
+96: "ntdll.dll!ZwListenPort",
+97: "ntdll.dll!NtLoadDriver",
+98: "ntdll.dll!NtLoadKey",
+99: "ntdll.dll!NtLoadKey2",
+100: "ntdll.dll!NtLockFile",
+101: "ntdll.dll!ZwLockProductActivationKeys",
+102: "ntdll.dll!NtLockRegistryKey",
+103: "ntdll.dll!ZwLockVirtualMemory",
+104: "ntdll.dll!ZwMakePermanentObject",
+105: "ntdll.dll!NtMakeTemporaryObject",
+106: "ntdll.dll!NtMapUserPhysicalPages",
+107: "ntdll.dll!ZwMapUserPhysicalPagesScatter",
+108: "ntdll.dll!ZwMapViewOfSection",
+109: "ntdll.dll!NtModifyBootEntry",
+110: "ntdll.dll!NtNotifyChangeDirectoryFile",
+111: "ntdll.dll!NtNotifyChangeKey",
+112: "ntdll.dll!NtNotifyChangeMultipleKeys",
+113: "ntdll.dll!ZwOpenDirectoryObject",
+114: "ntdll.dll!NtOpenEvent",
+115: "ntdll.dll!NtOpenEventPair",
+116: "ntdll.dll!NtOpenFile",
+117: "ntdll.dll!ZwOpenIoCompletion",
+118: "ntdll.dll!ZwOpenJobObject",
+119: "ntdll.dll!ZwOpenKey",
+120: "ntdll.dll!NtOpenMutant",
+121: "ntdll.dll!ZwOpenObjectAuditAlarm",
+122: "ntdll.dll!ZwOpenProcess",
+123: "ntdll.dll!ZwOpenProcessToken",
+124: "ntdll.dll!ZwOpenProcessTokenEx",
+125: "ntdll.dll!NtOpenSection",
+126: "ntdll.dll!NtOpenSemaphore",
+127: "ntdll.dll!NtOpenSymbolicLinkObject",
+128: "ntdll.dll!ZwOpenThread",
+129: "ntdll.dll!NtOpenThreadToken",
+130: "ntdll.dll!NtOpenThreadTokenEx",
+131: "ntdll.dll!ZwOpenTimer",
+132: "ntdll.dll!NtPlugPlayControl",
+133: "ntdll.dll!ZwPowerInformation",
+134: "ntdll.dll!ZwPrivilegeCheck",
+135: "ntdll.dll!ZwPrivilegeObjectAuditAlarm",
+136: "ntdll.dll!NtPrivilegedServiceAuditAlarm",
+137: "ntdll.dll!ZwProtectVirtualMemory",
+138: "ntdll.dll!ZwPulseEvent",
+139: "ntdll.dll!ZwQueryAttributesFile",
+140: "ntdll.dll!ZwQueryBootEntryOrder",
+141: "ntdll.dll!ZwQueryBootOptions",
+142: "ntdll.dll!NtQueryDebugFilterState",
+143: "ntdll.dll!NtQueryDefaultLocale",
+144: "ntdll.dll!ZwQueryDefaultUILanguage",
+145: "ntdll.dll!ZwQueryDirectoryFile",
+146: "ntdll.dll!ZwQueryDirectoryObject",
+147: "ntdll.dll!ZwQueryEaFile",
+148: "ntdll.dll!NtQueryEvent",
+149: "ntdll.dll!ZwQueryFullAttributesFile",
+150: "ntdll.dll!NtQueryInformationAtom",
+151: "ntdll.dll!ZwQueryInformationFile",
+152: "ntdll.dll!ZwQueryInformationJobObject",
+153: "ntdll.dll!ZwQueryInformationPort",
+154: "ntdll.dll!ZwQueryInformationProcess",
+155: "ntdll.dll!NtQueryInformationThread",
+156: "ntdll.dll!ZwQueryInformationToken",
+157: "ntdll.dll!NtQueryInstallUILanguage",
+158: "ntdll.dll!NtQueryIntervalProfile",
+159: "ntdll.dll!NtQueryIoCompletion",
+160: "ntdll.dll!ZwQueryKey",
+161: "ntdll.dll!NtQueryMultipleValueKey",
+162: "ntdll.dll!NtQueryMutant",
+163: "ntdll.dll!NtQueryObject",
+164: "ntdll.dll!NtQueryOpenSubKeys",
+165: "ntdll.dll!NtQueryPerformanceCounter",
+166: "ntdll.dll!ZwQueryQuotaInformationFile",
+167: "ntdll.dll!ZwQuerySection",
+168: "ntdll.dll!NtQuerySecurityObject",
+169: "ntdll.dll!ZwQuerySemaphore",
+170: "ntdll.dll!ZwQuerySymbolicLinkObject",
+171: "ntdll.dll!ZwQuerySystemEnvironmentValue",
+172: "ntdll.dll!ZwQuerySystemEnvironmentValueEx",
+173: "ntdll.dll!NtQuerySystemInformation",
+174: "ntdll.dll!NtQuerySystemTime",
+175: "ntdll.dll!ZwQueryTimer",
+176: "ntdll.dll!NtQueryTimerResolution",
+177: "ntdll.dll!ZwQueryValueKey",
+178: "ntdll.dll!NtQueryVirtualMemory",
+179: "ntdll.dll!NtQueryVolumeInformationFile",
+180: "ntdll.dll!NtQueueApcThread",
+181: "ntdll.dll!ZwRaiseException",
+182: "ntdll.dll!ZwRaiseHardError",
+183: "ntdll.dll!NtReadFile",
+184: "ntdll.dll!NtReadFileScatter",
+185: "ntdll.dll!ZwReadRequestData",
+186: "ntdll.dll!NtReadVirtualMemory",
+187: "ntdll.dll!ZwRegisterThreadTerminatePort",
+188: "ntdll.dll!ZwReleaseMutant",
+189: "ntdll.dll!NtReleaseSemaphore",
+190: "ntdll.dll!ZwRemoveIoCompletion",
+191: "ntdll.dll!ZwRemoveProcessDebug",
+192: "ntdll.dll!ZwRenameKey",
+193: "ntdll.dll!ZwReplaceKey",
+194: "ntdll.dll!ZwReplyPort",
+195: "ntdll.dll!NtReplyWaitReceivePort",
+196: "ntdll.dll!NtReplyWaitReceivePortEx",
+197: "ntdll.dll!NtReplyWaitReplyPort",
+198: "ntdll.dll!ZwRequestDeviceWakeup",
+199: "ntdll.dll!ZwRequestPort",
+200: "ntdll.dll!NtRequestWaitReplyPort",
+201: "ntdll.dll!ZwRequestWakeupLatency",
+202: "ntdll.dll!NtResetEvent",
+203: "ntdll.dll!ZwResetWriteWatch",
+204: "ntdll.dll!NtRestoreKey",
+205: "ntdll.dll!ZwResumeProcess",
+206: "ntdll.dll!ZwResumeThread",
+207: "ntdll.dll!NtSaveKey",
+208: "ntdll.dll!NtSaveKeyEx",
+209: "ntdll.dll!NtSaveMergedKeys",
+210: "ntdll.dll!NtSecureConnectPort",
+211: "ntdll.dll!ZwSetBootEntryOrder",
+212: "ntdll.dll!ZwSetBootOptions",
+213: "ntdll.dll!ZwSetContextThread",
+214: "ntdll.dll!NtSetDebugFilterState",
+215: "ntdll.dll!NtSetDefaultHardErrorPort",
+216: "ntdll.dll!NtSetDefaultLocale",
+217: "ntdll.dll!ZwSetDefaultUILanguage",
+218: "ntdll.dll!ZwSetEaFile",
+219: "ntdll.dll!NtSetEvent",
+220: "ntdll.dll!NtSetEventBoostPriority",
+221: "ntdll.dll!NtSetHighEventPair",
+222: "ntdll.dll!NtSetHighWaitLowEventPair",
+223: "ntdll.dll!ZwSetInformationDebugObject",
+224: "ntdll.dll!ZwSetInformationFile",
+225: "ntdll.dll!ZwSetInformationJobObject",
+226: "ntdll.dll!ZwSetInformationKey",
+227: "ntdll.dll!ZwSetInformationObject",
+228: "ntdll.dll!ZwSetInformationProcess",
+229: "ntdll.dll!ZwSetInformationThread",
+230: "ntdll.dll!ZwSetInformationToken",
+231: "ntdll.dll!NtSetIntervalProfile",
+232: "ntdll.dll!NtSetIoCompletion",
+233: "ntdll.dll!ZwSetLdtEntries",
+234: "ntdll.dll!ZwSetLowEventPair",
+235: "ntdll.dll!ZwSetLowWaitHighEventPair",
+236: "ntdll.dll!ZwSetQuotaInformationFile",
+237: "ntdll.dll!NtSetSecurityObject",
+238: "ntdll.dll!ZwSetSystemEnvironmentValue",
+239: "ntdll.dll!ZwSetSystemEnvironmentValueEx",
+240: "ntdll.dll!ZwSetSystemInformation",
+241: "ntdll.dll!ZwSetSystemPowerState",
+242: "ntdll.dll!ZwSetSystemTime",
+243: "ntdll.dll!ZwSetThreadExecutionState",
+244: "ntdll.dll!ZwSetTimer",
+245: "ntdll.dll!NtSetTimerResolution",
+246: "ntdll.dll!ZwSetUuidSeed",
+247: "ntdll.dll!ZwSetValueKey",
+248: "ntdll.dll!NtSetVolumeInformationFile",
+249: "ntdll.dll!ZwShutdownSystem",
+250: "ntdll.dll!ZwSignalAndWaitForSingleObject",
+251: "ntdll.dll!NtStartProfile",
+252: "ntdll.dll!ZwStopProfile",
+253: "ntdll.dll!ZwSuspendProcess",
+254: "ntdll.dll!ZwSuspendThread",
+255: "ntdll.dll!NtSystemDebugControl",
+256: "ntdll.dll!ZwTerminateJobObject",
+257: "ntdll.dll!ZwTerminateProcess",
+258: "ntdll.dll!ZwTerminateThread",
+259: "ntdll.dll!NtTestAlert",
+260: "ntdll.dll!NtTraceEvent",
+261: "ntdll.dll!NtTranslateFilePath",
+262: "ntdll.dll!ZwUnloadDriver",
+263: "ntdll.dll!NtUnloadKey",
+264: "ntdll.dll!ZwUnloadKeyEx",
+265: "ntdll.dll!ZwUnlockFile",
+266: "ntdll.dll!NtUnlockVirtualMemory",
+267: "ntdll.dll!NtUnmapViewOfSection",
+268: "ntdll.dll!NtVdmControl",
+269: "ntdll.dll!NtWaitForDebugEvent",
+270: "ntdll.dll!NtWaitForMultipleObjects",
+271: "ntdll.dll!ZwWaitForSingleObject",
+272: "ntdll.dll!ZwWaitHighEventPair",
+273: "ntdll.dll!NtWaitLowEventPair",
+274: "ntdll.dll!NtWriteFile",
+275: "ntdll.dll!NtWriteFileGather",
+276: "ntdll.dll!NtWriteRequestData",
+277: "ntdll.dll!NtWriteVirtualMemory",
+278: "ntdll.dll!ZwYieldExecution",
+279: "ntdll.dll!ZwCreateKeyedEvent",
+280: "ntdll.dll!NtOpenKeyedEvent",
+281: "ntdll.dll!NtReleaseKeyedEvent",
+282: "ntdll.dll!NtWaitForKeyedEvent",
+283: "ntdll.dll!ZwQueryPortInformationProcess",
+4096: "gdi32.dll!NtGdiAbortDoc",
+4097: "gdi32.dll!NtGdiAbortPath",
+4098: "gdi32.dll!NtGdiAddFontResourceW",
+4099: "gdi32.dll!NtGdiAddRemoteFontToDC",
+4100: "gdi32.dll!NtGdiAddFontMemResourceEx",
+4101: "gdi32.dll!NtGdiRemoveMergeFont",
+4102: "gdi32.dll!NtGdiAddRemoteMMInstanceToDC",
+4103: "gdi32.dll!NtGdiAlphaBlend",
+4104: "gdi32.dll!NtGdiAngleArc",
+4105: "gdi32.dll!NtGdiAnyLinkedFonts",
+4106: "gdi32.dll!NtGdiFontIsLinked",
+4107: "gdi32.dll!NtGdiArcInternal",
+4108: "gdi32.dll!NtGdiBeginPath",
+4109: "gdi32.dll!NtGdiBitBlt",
+4110: "gdi32.dll!NtGdiCancelDC",
+4111: "gdi32.dll!NtGdiCheckBitmapBits",
+4112: "gdi32.dll!NtGdiCloseFigure",
+4113: "gdi32.dll!NtGdiClearBitmapAttributes",
+4114: "gdi32.dll!NtGdiClearBrushAttributes",
+4115: "gdi32.dll!NtGdiColorCorrectPalette",
+4116: "gdi32.dll!NtGdiCombineRgn",
+4117: "gdi32.dll!CombineTransform",
+4118: "gdi32.dll!NtGdiComputeXformCoefficients",
+4119: "gdi32.dll!NtGdiConsoleTextOut",
+4120: "gdi32.dll!NtGdiConvertMetafileRect",
+4121: "gdi32.dll!NtGdiCreateBitmap",
+4122: "gdi32.dll!NtGdiCreateClientObj",
+4123: "gdi32.dll!NtGdiCreateColorSpace",
+4124: "gdi32.dll!NtGdiCreateColorTransform",
+4125: "gdi32.dll!NtGdiCreateCompatibleBitmap",
+4126: "gdi32.dll!NtGdiCreateCompatibleDC",
+4127: "gdi32.dll!NtGdiCreateDIBBrush",
+4128: "gdi32.dll!NtGdiCreateDIBitmapInternal",
+4129: "gdi32.dll!NtGdiCreateDIBSection",
+4130: "gdi32.dll!NtGdiCreateEllipticRgn",
+4131: "gdi32.dll!NtGdiCreateHalftonePalette",
+4132: "gdi32.dll!NtGdiCreateHatchBrushInternal",
+4133: "gdi32.dll!NtGdiCreateMetafileDC",
+4134: "gdi32.dll!NtGdiCreatePaletteInternal",
+4135: "gdi32.dll!NtGdiCreatePatternBrushInternal",
+4136: "gdi32.dll!CreatePen",
+4137: "gdi32.dll!NtGdiCreateRectRgn",
+4138: "gdi32.dll!CreateRoundRectRgn",
+4139: "gdi32.dll!NtGdiCreateServerMetaFile",
+4140: "gdi32.dll!NtGdiCreateSolidBrush",
+4141: "gdi32.dll!NtGdiD3dContextCreate",
+4142: "gdi32.dll!NtGdiD3dContextDestroy",
+4143: "gdi32.dll!NtGdiD3dContextDestroyAll",
+4144: "gdi32.dll!NtGdiD3dValidateTextureStageState",
+4145: "gdi32.dll!NtGdiD3dDrawPrimitives2",
+4146: "gdi32.dll!NtGdiDdGetDriverState",
+4147: "gdi32.dll!NtGdiDdAddAttachedSurface",
+4148: "gdi32.dll!NtGdiDdAlphaBlt",
+4149: "gdi32.dll!NtGdiDdAttachSurface",
+4150: "gdi32.dll!NtGdiDdBeginMoCompFrame",
+4151: "gdi32.dll!NtGdiDdBlt",
+4152: "gdi32.dll!NtGdiDdCanCreateSurface",
+4153: "gdi32.dll!NtGdiDdCanCreateD3DBuffer",
+4154: "gdi32.dll!NtGdiDdColorControl",
+4155: "gdi32.dll!NtGdiDdCreateDirectDrawObject",
+4156: "gdi32.dll!NtGdiDdCreateSurface",
+4157: "gdi32.dll!NtGdiDdCreateD3DBuffer",
+4158: "gdi32.dll!NtGdiDdCreateMoComp",
+4159: "gdi32.dll!NtGdiDdCreateSurfaceObject",
+4160: "gdi32.dll!NtGdiDdDeleteDirectDrawObject",
+4161: "gdi32.dll!NtGdiDdDeleteSurfaceObject",
+4162: "gdi32.dll!NtGdiDdDestroyMoComp",
+4163: "gdi32.dll!NtGdiDdDestroySurface",
+4164: "gdi32.dll!NtGdiDdDestroyD3DBuffer",
+4165: "gdi32.dll!NtGdiDdEndMoCompFrame",
+4166: "gdi32.dll!NtGdiDdFlip",
+4167: "gdi32.dll!NtGdiDdFlipToGDISurface",
+4168: "gdi32.dll!NtGdiDdGetAvailDriverMemory",
+4169: "gdi32.dll!NtGdiDdGetBltStatus",
+4170: "gdi32.dll!NtGdiDdGetDC",
+4171: "gdi32.dll!NtGdiDdGetDriverInfo",
+4172: "gdi32.dll!NtGdiDdGetDxHandle",
+4173: "gdi32.dll!NtGdiDdGetFlipStatus",
+4174: "gdi32.dll!NtGdiDdGetInternalMoCompInfo",
+4175: "gdi32.dll!NtGdiDdGetMoCompBuffInfo",
+4176: "gdi32.dll!NtGdiDdGetMoCompGuids",
+4177: "gdi32.dll!NtGdiDdGetMoCompFormats",
+4178: "gdi32.dll!NtGdiDdGetScanLine",
+4179: "gdi32.dll!NtGdiDdLock",
+4180: "gdi32.dll!NtGdiDdLockD3D",
+4181: "gdi32.dll!NtGdiDdQueryDirectDrawObject",
+4182: "gdi32.dll!NtGdiDdQueryMoCompStatus",
+4183: "gdi32.dll!NtGdiDdReenableDirectDrawObject",
+4184: "gdi32.dll!NtGdiDdReleaseDC",
+4185: "gdi32.dll!NtGdiDdRenderMoComp",
+4186: "gdi32.dll!NtGdiDdResetVisrgn",
+4187: "gdi32.dll!NtGdiDdSetColorKey",
+4188: "gdi32.dll!NtGdiDdSetExclusiveMode",
+4189: "gdi32.dll!NtGdiDdSetGammaRamp",
+4190: "gdi32.dll!NtGdiDdCreateSurfaceEx",
+4191: "gdi32.dll!NtGdiDdSetOverlayPosition",
+4192: "gdi32.dll!NtGdiDdUnattachSurface",
+4193: "gdi32.dll!NtGdiDdUnlock",
+4194: "gdi32.dll!NtGdiDdUnlockD3D",
+4195: "gdi32.dll!NtGdiDdUpdateOverlay",
+4196: "gdi32.dll!NtGdiDdWaitForVerticalBlank",
+4197: "gdi32.dll!NtGdiDvpCanCreateVideoPort",
+4198: "gdi32.dll!NtGdiDvpColorControl",
+4199: "gdi32.dll!NtGdiDvpCreateVideoPort",
+4200: "gdi32.dll!NtGdiDvpDestroyVideoPort",
+4201: "gdi32.dll!NtGdiDvpFlipVideoPort",
+4202: "gdi32.dll!NtGdiDvpGetVideoPortBandwidth",
+4203: "gdi32.dll!NtGdiDvpGetVideoPortField",
+4204: "gdi32.dll!NtGdiDvpGetVideoPortFlipStatus",
+4205: "gdi32.dll!NtGdiDvpGetVideoPortInputFormats",
+4206: "gdi32.dll!NtGdiDvpGetVideoPortLine",
+4207: "gdi32.dll!NtGdiDvpGetVideoPortOutputFormats",
+4208: "gdi32.dll!NtGdiDvpGetVideoPortConnectInfo",
+4209: "gdi32.dll!NtGdiDvpGetVideoSignalStatus",
+4210: "gdi32.dll!NtGdiDvpUpdateVideoPort",
+4211: "gdi32.dll!NtGdiDvpWaitForVideoPortSync",
+4212: "gdi32.dll!NtGdiDvpAcquireNotification",
+4213: "gdi32.dll!NtGdiDvpReleaseNotification",
+4214: "gdi32.dll!NtGdiDxgGenericThunk",
+4215: "gdi32.dll!NtGdiDeleteClientObj",
+4216: "gdi32.dll!NtGdiDeleteColorSpace",
+4217: "gdi32.dll!NtGdiDeleteColorTransform",
+4218: "gdi32.dll!DeleteObject",
+4219: "gdi32.dll!NtGdiDescribePixelFormat",
+4220: "gdi32.dll!NtGdiGetPerBandInfo",
+4221: "gdi32.dll!NtGdiDoBanding",
+4222: "gdi32.dll!NtGdiDoPalette",
+4223: "gdi32.dll!NtGdiDrawEscape",
+4224: "gdi32.dll!NtGdiEllipse",
+4225: "gdi32.dll!NtGdiEnableEudc",
+4226: "gdi32.dll!NtGdiEndDoc",
+4227: "gdi32.dll!NtGdiEndPage",
+4228: "gdi32.dll!NtGdiEndPath",
+4229: "gdi32.dll!NtGdiEnumFontChunk",
+4230: "gdi32.dll!NtGdiEnumFontClose",
+4231: "gdi32.dll!NtGdiEnumFontOpen",
+4232: "gdi32.dll!NtGdiEnumObjects",
+4233: "gdi32.dll!NtGdiEqualRgn",
+4234: "gdi32.dll!NtGdiEudcLoadUnloadLink",
+4235: "gdi32.dll!NtGdiExcludeClipRect",
+4236: "gdi32.dll!NtGdiExtCreatePen",
+4237: "gdi32.dll!NtGdiExtCreateRegion",
+4238: "gdi32.dll!NtGdiExtEscape",
+4239: "gdi32.dll!NtGdiExtFloodFill",
+4240: "gdi32.dll!NtGdiExtGetObjectW",
+4241: "gdi32.dll!ExtSelectClipRgn",
+4242: "gdi32.dll!NtGdiExtTextOutW",
+4243: "gdi32.dll!NtGdiFillPath",
+4244: "gdi32.dll!NtGdiFillRgn",
+4245: "gdi32.dll!NtGdiFlattenPath",
+4247: "gdi32.dll!NtGdiFlush",
+4248: "gdi32.dll!NtGdiForceUFIMapping",
+4249: "gdi32.dll!NtGdiFrameRgn",
+4250: "gdi32.dll!NtGdiFullscreenControl",
+4251: "gdi32.dll!NtGdiGetAndSetDCDword",
+4252: "gdi32.dll!GetClipBox",
+4253: "gdi32.dll!GetBitmapBits",
+4254: "gdi32.dll!NtGdiGetBitmapDimension",
+4255: "gdi32.dll!NtGdiGetBoundsRect",
+4256: "gdi32.dll!NtGdiGetCharABCWidthsW",
+4257: "gdi32.dll!NtGdiGetCharacterPlacementW",
+4258: "gdi32.dll!NtGdiGetCharSet",
+4259: "gdi32.dll!NtGdiGetCharWidthW",
+4260: "gdi32.dll!NtGdiGetCharWidthInfo",
+4261: "gdi32.dll!NtGdiGetColorAdjustment",
+4263: "gdi32.dll!NtGdiGetDCDword",
+4264: "gdi32.dll!NtGdiGetDCforBitmap",
+4265: "gdi32.dll!NtGdiGetDCObject",
+4266: "gdi32.dll!NtGdiGetDCPoint",
+4267: "gdi32.dll!NtGdiGetDeviceCaps",
+4268: "gdi32.dll!NtGdiGetDeviceGammaRamp",
+4269: "gdi32.dll!NtGdiGetDeviceCapsAll",
+4270: "gdi32.dll!NtGdiGetDIBitsInternal",
+4271: "gdi32.dll!NtGdiGetETM",
+4272: "gdi32.dll!NtGdiGetEudcTimeStampEx",
+4273: "gdi32.dll!GetFontData",
+4274: "gdi32.dll!NtGdiGetFontResourceInfoInternalW",
+4275: "gdi32.dll!NtGdiGetGlyphIndicesW",
+4276: "gdi32.dll!NtGdiGetGlyphIndicesWInternal",
+4277: "gdi32.dll!NtGdiGetGlyphOutline",
+4278: "gdi32.dll!NtGdiGetKerningPairs",
+4279: "gdi32.dll!NtGdiGetLinkedUFIs",
+4280: "gdi32.dll!GetMiterLimit",
+4281: "gdi32.dll!NtGdiGetMonitorID",
+4282: "gdi32.dll!GetNearestColor",
+4283: "gdi32.dll!NtGdiGetNearestPaletteIndex",
+4284: "gdi32.dll!NtGdiGetObjectBitmapHandle",
+4285: "gdi32.dll!NtGdiGetOutlineTextMetricsInternalW",
+4286: "gdi32.dll!NtGdiGetPath",
+4287: "gdi32.dll!NtGdiGetPixel",
+4288: "gdi32.dll!NtGdiGetRandomRgn",
+4289: "gdi32.dll!GetRasterizerCaps",
+4290: "gdi32.dll!NtGdiGetRealizationInfo",
+4291: "gdi32.dll!GetRegionData",
+4292: "gdi32.dll!NtGdiGetRgnBox",
+4293: "gdi32.dll!NtGdiGetServerMetaFileBits",
+4294: "gdi32.dll!NtGdiGetSpoolMessage",
+4296: "gdi32.dll!NtGdiGetStockObject",
+4297: "gdi32.dll!NtGdiGetStringBitmapW",
+4298: "gdi32.dll!GetSystemPaletteUse",
+4299: "gdi32.dll!NtGdiGetTextCharsetInfo",
+4300: "gdi32.dll!NtGdiGetTextExtent",
+4301: "gdi32.dll!NtGdiGetTextExtentExW",
+4302: "gdi32.dll!NtGdiGetTextFaceW",
+4303: "gdi32.dll!NtGdiGetTextMetricsW",
+4304: "gdi32.dll!NtGdiGetTransform",
+4305: "gdi32.dll!NtGdiGetUFI",
+4306: "gdi32.dll!NtGdiGetEmbUFI",
+4307: "gdi32.dll!NtGdiGetUFIPathname",
+4308: "gdi32.dll!NtGdiGetEmbedFonts",
+4309: "gdi32.dll!NtGdiChangeGhostFont",
+4310: "gdi32.dll!NtGdiAddEmbFontToDC",
+4311: "gdi32.dll!NtGdiGetFontUnicodeRanges",
+4312: "gdi32.dll!NtGdiGetWidthTable",
+4313: "gdi32.dll!NtGdiGradientFill",
+4314: "gdi32.dll!NtGdiHfontCreate",
+4315: "gdi32.dll!NtGdiIcmBrushInfo",
+4316: "gdi32.dll!NtGdiInit",
+4317: "gdi32.dll!NtGdiInitSpool",
+4318: "gdi32.dll!NtGdiIntersectClipRect",
+4319: "gdi32.dll!NtGdiInvertRgn",
+4320: "gdi32.dll!NtGdiLineTo",
+4321: "gdi32.dll!NtGdiMakeFontDir",
+4322: "gdi32.dll!NtGdiMakeInfoDC",
+4323: "gdi32.dll!NtGdiMaskBlt",
+4324: "gdi32.dll!NtGdiModifyWorldTransform",
+4325: "gdi32.dll!NtGdiMonoBitmap",
+4327: "gdi32.dll!NtGdiOffsetClipRgn",
+4328: "gdi32.dll!NtGdiOffsetRgn",
+4329: "gdi32.dll!NtGdiOpenDCW",
+4330: "gdi32.dll!NtGdiPatBlt",
+4331: "gdi32.dll!NtGdiPolyPatBlt",
+4332: "gdi32.dll!NtGdiPathToRegion",
+4333: "gdi32.dll!NtGdiPlgBlt",
+4334: "gdi32.dll!NtGdiPolyDraw",
+4335: "gdi32.dll!NtGdiPolyPolyDraw",
+4336: "gdi32.dll!NtGdiPolyTextOutW",
+4337: "gdi32.dll!NtGdiPtInRegion",
+4338: "gdi32.dll!NtGdiPtVisible",
+4339: "gdi32.dll!NtGdiQueryFonts",
+4340: "gdi32.dll!NtGdiQueryFontAssocInfo",
+4341: "gdi32.dll!NtGdiRectangle",
+4342: "gdi32.dll!NtGdiRectInRegion",
+4343: "gdi32.dll!RectVisible",
+4344: "gdi32.dll!NtGdiRemoveFontResourceW",
+4345: "gdi32.dll!NtGdiRemoveFontMemResourceEx",
+4346: "gdi32.dll!NtGdiResetDC",
+4347: "gdi32.dll!NtGdiResizePalette",
+4348: "gdi32.dll!NtGdiRestoreDC",
+4349: "gdi32.dll!NtGdiRoundRect",
+4350: "gdi32.dll!NtGdiSaveDC",
+4351: "gdi32.dll!NtGdiScaleViewportExtEx",
+4352: "gdi32.dll!NtGdiScaleWindowExtEx",
+4353: "gdi32.dll!NtGdiSelectBitmap",
+4355: "gdi32.dll!NtGdiSelectClipPath",
+4356: "gdi32.dll!NtGdiSelectFont",
+4357: "gdi32.dll!NtGdiSelectPen",
+4358: "gdi32.dll!NtGdiSetBitmapAttributes",
+4359: "gdi32.dll!SetBitmapBits",
+4360: "gdi32.dll!NtGdiSetBitmapDimension",
+4361: "gdi32.dll!NtGdiSetBoundsRect",
+4362: "gdi32.dll!NtGdiSetBrushAttributes",
+4363: "gdi32.dll!NtGdiSetBrushOrg",
+4364: "gdi32.dll!NtGdiSetColorAdjustment",
+4365: "gdi32.dll!NtGdiSetColorSpace",
+4366: "gdi32.dll!NtGdiSetDeviceGammaRamp",
+4367: "gdi32.dll!NtGdiSetDIBitsToDeviceInternal",
+4368: "gdi32.dll!NtGdiSetFontEnumeration",
+4369: "gdi32.dll!NtGdiSetFontXform",
+4370: "gdi32.dll!NtGdiSetIcmMode",
+4371: "gdi32.dll!NtGdiSetLinkedUFIs",
+4372: "gdi32.dll!NtGdiSetMagicColors",
+4373: "gdi32.dll!NtGdiSetMetaRgn",
+4374: "gdi32.dll!NtGdiSetMiterLimit",
+4375: "gdi32.dll!NtGdiGetDeviceWidth",
+4376: "gdi32.dll!NtGdiMirrorWindowOrg",
+4377: "gdi32.dll!NtGdiSetLayout",
+4378: "gdi32.dll!NtGdiSetPixel",
+4379: "gdi32.dll!NtGdiSetPixelFormat",
+4380: "gdi32.dll!NtGdiSetRectRgn",
+4381: "gdi32.dll!NtGdiSetSystemPaletteUse",
+4383: "gdi32.dll!NtGdiSetupPublicCFONT",
+4384: "gdi32.dll!NtGdiSetVirtualResolution",
+4385: "gdi32.dll!NtGdiSetSizeDevice",
+4386: "gdi32.dll!NtGdiStartDoc",
+4387: "gdi32.dll!NtGdiStartPage",
+4388: "gdi32.dll!NtGdiStretchBlt",
+4389: "gdi32.dll!NtGdiStretchDIBitsInternal",
+4390: "gdi32.dll!NtGdiStrokeAndFillPath",
+4391: "gdi32.dll!NtGdiStrokePath",
+4392: "gdi32.dll!NtGdiSwapBuffers",
+4393: "gdi32.dll!NtGdiTransformPoints",
+4394: "gdi32.dll!NtGdiTransparentBlt",
+4395: "gdi32.dll!NtGdiUnloadPrinterDriver",
+4397: "gdi32.dll!NtGdiUnrealizeObject",
+4398: "gdi32.dll!NtGdiUpdateColors",
+4399: "gdi32.dll!NtGdiWidenPath",
+4400: "user32.dll!NtUserActivateKeyboardLayout",
+4401: "user32.dll!NtUserAlterWindowStyle",
+4402: "imm32.dll!NtUserAssociateInputContext",
+4403: "user32.dll!NtUserAttachThreadInput",
+4404: "user32.dll!NtUserBeginPaint",
+4405: "user32.dll!NtUserBitBltSysBmp",
+4406: "user32.dll!NtUserBlockInput",
+4407: "imm32.dll!NtUserBuildHimcList",
+4408: "user32.dll!NtUserBuildHwndList",
+4409: "user32.dll!NtUserBuildNameList",
+4410: "user32.dll!NtUserBuildPropList",
+4411: "user32.dll!NtUserCallHwnd",
+4412: "user32.dll!NtUserCallHwndLock",
+4413: "user32.dll!NtUserCallHwndOpt",
+4414: "user32.dll!NtUserCallHwndParam",
+4415: "user32.dll!NtUserCallHwndParamLock",
+4416: "user32.dll!NtUserCallMsgFilter",
+4417: "user32.dll!NtUserCallNextHookEx",
+4418: "user32.dll!NtUserCallNoParam",
+4419: "imm32.dll!NtUserCallOneParam",
+4419: "user32.dll!NtUserCallOneParam",
+4420: "user32.dll!NtUserCallTwoParam",
+4421: "user32.dll!NtUserChangeClipboardChain",
+4422: "user32.dll!NtUserChangeDisplaySettings",
+4424: "user32.dll!NtUserCheckMenuItem",
+4425: "user32.dll!NtUserChildWindowFromPointEx",
+4426: "user32.dll!NtUserClipCursor",
+4427: "user32.dll!NtUserCloseClipboard",
+4428: "user32.dll!NtUserCloseDesktop",
+4429: "user32.dll!NtUserCloseWindowStation",
+4431: "user32.dll!NtUserConvertMemHandle",
+4432: "user32.dll!NtUserCopyAcceleratorTable",
+4433: "user32.dll!NtUserCountClipboardFormats",
+4434: "user32.dll!NtUserCreateAcceleratorTable",
+4435: "user32.dll!NtUserCreateCaret",
+4436: "user32.dll!NtUserCreateDesktop",
+4437: "imm32.dll!NtUserCreateInputContext",
+4438: "user32.dll!NtUserCreateLocalMemHandle",
+4439: "user32.dll!NtUserCreateWindowEx",
+4440: "user32.dll!NtUserCreateWindowStation",
+4441: "user32.dll!NtUserDdeGetQualityOfService",
+4442: "user32.dll!NtUserDdeInitialize",
+4443: "user32.dll!NtUserDdeSetQualityOfService",
+4444: "user32.dll!NtUserDeferWindowPos",
+4445: "user32.dll!NtUserDefSetText",
+4446: "user32.dll!NtUserDeleteMenu",
+4447: "user32.dll!DestroyAcceleratorTable",
+4448: "user32.dll!NtUserDestroyCursor",
+4449: "imm32.dll!NtUserDestroyInputContext",
+4450: "user32.dll!NtUserDestroyMenu",
+4451: "user32.dll!NtUserDestroyWindow",
+4452: "imm32.dll!NtUserDisableThreadIme",
+4453: "user32.dll!NtUserDispatchMessage",
+4454: "user32.dll!NtUserDragDetect",
+4455: "user32.dll!NtUserDragObject",
+4456: "user32.dll!NtUserDrawAnimatedRects",
+4457: "user32.dll!NtUserDrawCaption",
+4458: "user32.dll!NtUserDrawCaptionTemp",
+4459: "user32.dll!NtUserDrawIconEx",
+4460: "user32.dll!NtUserDrawMenuBarTemp",
+4461: "user32.dll!NtUserEmptyClipboard",
+4462: "user32.dll!NtUserEnableMenuItem",
+4463: "user32.dll!NtUserEnableScrollBar",
+4464: "user32.dll!NtUserEndDeferWindowPosEx",
+4465: "user32.dll!NtUserEndMenu",
+4466: "user32.dll!NtUserEndPaint",
+4467: "user32.dll!NtUserEnumDisplayDevices",
+4468: "user32.dll!NtUserEnumDisplayMonitors",
+4469: "user32.dll!NtUserEnumDisplaySettings",
+4470: "user32.dll!NtUserEvent",
+4471: "user32.dll!NtUserExcludeUpdateRgn",
+4472: "user32.dll!NtUserFillWindow",
+4473: "user32.dll!NtUserFindExistingCursorIcon",
+4474: "user32.dll!NtUserFindWindowEx",
+4475: "user32.dll!NtUserFlashWindowEx",
+4476: "user32.dll!NtUserGetAltTabInfo",
+4477: "user32.dll!NtUserGetAncestor",
+4478: "imm32.dll!NtUserGetAppImeLevel",
+4479: "user32.dll!GetAsyncKeyState",
+4480: "user32.dll!NtUserGetAtomName",
+4481: "user32.dll!NtUserGetCaretBlinkTime",
+4482: "user32.dll!NtUserGetCaretPos",
+4483: "user32.dll!NtUserGetClassInfo",
+4484: "user32.dll!NtUserGetClassName",
+4485: "user32.dll!NtUserGetClipboardData",
+4486: "user32.dll!NtUserGetClipboardFormatName",
+4487: "user32.dll!NtUserGetClipboardOwner",
+4488: "user32.dll!NtUserGetClipboardSequenceNumber",
+4489: "user32.dll!NtUserGetClipboardViewer",
+4490: "user32.dll!NtUserGetClipCursor",
+4491: "user32.dll!NtUserGetComboBoxInfo",
+4492: "user32.dll!NtUserGetControlBrush",
+4493: "user32.dll!NtUserGetControlColor",
+4494: "user32.dll!NtUserGetCPD",
+4495: "user32.dll!NtUserGetCursorFrameInfo",
+4496: "user32.dll!NtUserGetCursorInfo",
+4497: "user32.dll!NtUserGetDC",
+4498: "user32.dll!NtUserGetDCEx",
+4499: "user32.dll!NtUserGetDoubleClickTime",
+4500: "user32.dll!NtUserGetForegroundWindow",
+4501: "user32.dll!NtUserGetGuiResources",
+4502: "user32.dll!NtUserGetGUIThreadInfo",
+4503: "user32.dll!NtUserGetIconInfo",
+4504: "user32.dll!NtUserGetIconSize",
+4505: "imm32.dll!NtUserGetImeHotKey",
+4505: "user32.dll!NtUserGetImeHotKey",
+4506: "imm32.dll!NtUserGetImeInfoEx",
+4507: "user32.dll!NtUserGetInternalWindowPos",
+4508: "user32.dll!NtUserGetKeyboardLayoutList",
+4509: "user32.dll!NtUserGetKeyboardLayoutName",
+4510: "user32.dll!NtUserGetKeyboardState",
+4511: "user32.dll!NtUserGetKeyNameText",
+4512: "user32.dll!NtUserGetKeyState",
+4513: "user32.dll!NtUserGetListBoxInfo",
+4514: "user32.dll!NtUserGetMenuBarInfo",
+4515: "user32.dll!NtUserGetMenuIndex",
+4516: "user32.dll!NtUserGetMenuItemRect",
+4517: "user32.dll!NtUserGetMessage",
+4518: "user32.dll!NtUserGetMouseMovePointsEx",
+4519: "user32.dll!NtUserGetObjectInformation",
+4520: "user32.dll!NtUserGetOpenClipboardWindow",
+4521: "user32.dll!NtUserGetPriorityClipboardFormat",
+4522: "user32.dll!NtUserGetProcessWindowStation",
+4523: "user32.dll!NtUserGetRawInputBuffer",
+4524: "user32.dll!NtUserGetRawInputData",
+4525: "user32.dll!NtUserGetRawInputDeviceInfo",
+4526: "user32.dll!NtUserGetRawInputDeviceList",
+4527: "user32.dll!NtUserGetRegisteredRawInputDevices",
+4528: "user32.dll!NtUserGetScrollBarInfo",
+4529: "user32.dll!NtUserGetSystemMenu",
+4530: "user32.dll!NtUserGetThreadDesktop",
+4531: "imm32.dll!NtUserGetThreadState",
+4531: "user32.dll!NtUserGetThreadState",
+4532: "user32.dll!NtUserGetTitleBarInfo",
+4533: "user32.dll!GetUpdateRect",
+4534: "user32.dll!GetUpdateRgn",
+4535: "user32.dll!NtUserGetWindowDC",
+4536: "user32.dll!NtUserGetWindowPlacement",
+4537: "user32.dll!NtUserGetWOWClass",
+4539: "user32.dll!NtUserHideCaret",
+4540: "user32.dll!NtUserHiliteMenuItem",
+4541: "user32.dll!NtUserImpersonateDdeClientWindow",
+4543: "user32.dll!NtUserInitializeClientPfnArrays",
+4544: "user32.dll!NtUserInitTask",
+4545: "user32.dll!NtUserInternalGetWindowText",
+4546: "user32.dll!NtUserInvalidateRect",
+4547: "user32.dll!NtUserInvalidateRgn",
+4548: "user32.dll!NtUserIsClipboardFormatAvailable",
+4549: "user32.dll!NtUserKillTimer",
+4550: "user32.dll!NtUserLoadKeyboardLayoutEx",
+4551: "user32.dll!NtUserLockWindowStation",
+4552: "user32.dll!NtUserLockWindowUpdate",
+4553: "user32.dll!NtUserLockWorkStation",
+4554: "user32.dll!NtUserMapVirtualKeyEx",
+4555: "user32.dll!NtUserMenuItemFromPoint",
+4556: "user32.dll!NtUserMessageCall",
+4557: "user32.dll!NtUserMinMaximize",
+4558: "user32.dll!NtUserMNDragLeave",
+4559: "user32.dll!NtUserMNDragOver",
+4560: "user32.dll!NtUserModifyUserStartupInfoFlags",
+4561: "user32.dll!NtUserMoveWindow",
+4562: "imm32.dll!NtUserNotifyIMEStatus",
+4562: "user32.dll!NtUserNotifyIMEStatus",
+4564: "user32.dll!NtUserNotifyWinEvent",
+4565: "user32.dll!NtUserOpenClipboard",
+4566: "user32.dll!NtUserOpenDesktop",
+4567: "user32.dll!NtUserOpenInputDesktop",
+4568: "user32.dll!NtUserOpenWindowStation",
+4569: "user32.dll!NtUserPaintDesktop",
+4570: "user32.dll!PeekMessageW",
+4571: "user32.dll!NtUserPostMessage",
+4572: "user32.dll!NtUserPostThreadMessage",
+4573: "user32.dll!NtUserPrintWindow",
+4574: "user32.dll!NtUserProcessConnect",
+4576: "imm32.dll!NtUserQueryInputContext",
+4577: "user32.dll!NtUserQuerySendMessage",
+4578: "user32.dll!NtUserQueryUserCounters",
+4579: "imm32.dll!NtUserQueryWindow",
+4579: "user32.dll!NtUserQueryWindow",
+4580: "user32.dll!NtUserRealChildWindowFromPoint",
+4581: "user32.dll!NtUserRealInternalGetMessage",
+4582: "user32.dll!NtUserRealWaitMessageEx",
+4583: "user32.dll!NtUserRedrawWindow",
+4584: "user32.dll!NtUserRegisterClassExWOW",
+4585: "user32.dll!NtUserRegisterUserApiHook",
+4586: "user32.dll!NtUserRegisterHotKey",
+4587: "user32.dll!NtUserRegisterRawInputDevices",
+4588: "user32.dll!NtUserRegisterTasklist",
+4589: "user32.dll!NtUserRegisterWindowMessage",
+4590: "user32.dll!NtUserRemoveMenu",
+4591: "user32.dll!NtUserRemoveProp",
+4593: "user32.dll!NtUserResolveDesktopForWOW",
+4594: "user32.dll!NtUserSBGetParms",
+4595: "user32.dll!ScrollDC",
+4596: "user32.dll!NtUserScrollWindowEx",
+4597: "gdi32.dll!NtUserSelectPalette",
+4598: "user32.dll!NtUserSendInput",
+4599: "user32.dll!NtUserSetActiveWindow",
+4600: "imm32.dll!NtUserSetAppImeLevel",
+4601: "user32.dll!NtUserSetCapture",
+4602: "user32.dll!NtUserSetClassLong",
+4603: "user32.dll!NtUserSetClassWord",
+4604: "user32.dll!NtUserSetClipboardData",
+4605: "user32.dll!NtUserSetClipboardViewer",
+4606: "user32.dll!NtUserSetConsoleReserveKeys",
+4607: "user32.dll!NtUserSetCursor",
+4608: "user32.dll!NtUserSetCursorContents",
+4609: "user32.dll!NtUserSetCursorIconData",
+4610: "user32.dll!NtUserSetDbgTag",
+4611: "user32.dll!NtUserSetFocus",
+4612: "user32.dll!NtUserSetImeHotKey",
+4613: "imm32.dll!NtUserSetImeInfoEx",
+4614: "user32.dll!NtUserSetImeOwnerWindow",
+4616: "user32.dll!NtUserSetInformationThread",
+4617: "user32.dll!NtUserSetInternalWindowPos",
+4618: "user32.dll!NtUserSetKeyboardState",
+4619: "user32.dll!NtUserSetLogonNotifyWindow",
+4620: "user32.dll!NtUserSetMenu",
+4621: "user32.dll!NtUserSetMenuContextHelpId",
+4622: "user32.dll!NtUserSetMenuDefaultItem",
+4623: "user32.dll!NtUserSetMenuFlagRtoL",
+4624: "user32.dll!NtUserSetObjectInformation",
+4625: "user32.dll!NtUserSetParent",
+4626: "user32.dll!NtUserSetProcessWindowStation",
+4627: "user32.dll!NtUserSetProp",
+4628: "user32.dll!NtUserSetRipFlags",
+4629: "user32.dll!NtUserSetScrollInfo",
+4630: "user32.dll!NtUserSetShellWindowEx",
+4631: "user32.dll!NtUserSetSysColors",
+4632: "user32.dll!NtUserSetSystemCursor",
+4633: "user32.dll!NtUserSetSystemMenu",
+4634: "user32.dll!NtUserSetSystemTimer",
+4635: "user32.dll!NtUserSetThreadDesktop",
+4636: "imm32.dll!NtUserSetThreadLayoutHandles",
+4637: "user32.dll!NtUserSetThreadState",
+4638: "user32.dll!NtUserSetTimer",
+4639: "user32.dll!NtUserSetWindowFNID",
+4640: "user32.dll!NtUserSetWindowLong",
+4641: "user32.dll!NtUserSetWindowPlacement",
+4642: "user32.dll!NtUserSetWindowPos",
+4643: "user32.dll!NtUserSetWindowRgn",
+4644: "user32.dll!NtUserSetWindowsHookAW",
+4645: "user32.dll!NtUserSetWindowsHookEx",
+4646: "user32.dll!NtUserSetWindowStationUser",
+4647: "user32.dll!NtUserSetWindowWord",
+4648: "user32.dll!NtUserSetWinEventHook",
+4649: "user32.dll!NtUserShowCaret",
+4650: "user32.dll!NtUserShowScrollBar",
+4651: "user32.dll!NtUserShowWindow",
+4652: "user32.dll!NtUserShowWindowAsync",
+4654: "user32.dll!NtUserSwitchDesktop",
+4655: "user32.dll!NtUserSystemParametersInfo",
+4657: "user32.dll!NtUserThunkedMenuInfo",
+4658: "user32.dll!NtUserThunkedMenuItemInfo",
+4659: "user32.dll!NtUserToUnicodeEx",
+4660: "user32.dll!NtUserTrackMouseEvent",
+4661: "user32.dll!NtUserTrackPopupMenuEx",
+4662: "user32.dll!NtUserCalcMenuBar",
+4663: "user32.dll!NtUserPaintMenuBar",
+4664: "user32.dll!TranslateAcceleratorA",
+4665: "user32.dll!NtUserTranslateMessage",
+4666: "user32.dll!NtUserUnhookWindowsHookEx",
+4667: "user32.dll!NtUserUnhookWinEvent",
+4668: "user32.dll!NtUserUnloadKeyboardLayout",
+4669: "user32.dll!NtUserUnlockWindowStation",
+4670: "user32.dll!NtUserUnregisterClass",
+4671: "user32.dll!NtUserUnregisterUserApiHook",
+4672: "user32.dll!NtUserUnregisterHotKey",
+4673: "imm32.dll!NtUserUpdateInputContext",
+4673: "user32.dll!NtUserUpdateInputContext",
+4674: "user32.dll!NtUserUpdateInstance",
+4675: "user32.dll!NtUserUpdateLayeredWindow",
+4676: "user32.dll!NtUserGetLayeredWindowAttributes",
+4677: "user32.dll!NtUserSetLayeredWindowAttributes",
+4678: "user32.dll!NtUserUpdatePerUserSystemParameters",
+4679: "user32.dll!NtUserUserHandleGrantAccess",
+4680: "imm32.dll!NtUserValidateHandleSecure",
+4680: "user32.dll!NtUserValidateHandleSecure",
+4681: "user32.dll!NtUserValidateRect",
+4682: "user32.dll!NtUserValidateTimerCallback",
+4683: "user32.dll!NtUserVkKeyScanEx",
+4684: "user32.dll!NtUserWaitForInputIdle",
+4685: "user32.dll!NtUserWaitForMsgAndEvent",
+4686: "user32.dll!NtUserWaitMessage",
+4687: "user32.dll!NtUserWin32PoolAllocationStats",
+4688: "user32.dll!NtUserWindowFromPoint",
+4689: "user32.dll!NtUserYieldTask",
+4695: "gdi32.dll!NtGdiEngAssociateSurface",
+4696: "gdi32.dll!NtGdiEngCreateBitmap",
+4697: "gdi32.dll!NtGdiEngCreateDeviceSurface",
+4698: "gdi32.dll!NtGdiEngCreateDeviceBitmap",
+4699: "gdi32.dll!NtGdiEngCreatePalette",
+4700: "gdi32.dll!NtGdiEngComputeGlyphSet",
+4701: "gdi32.dll!NtGdiEngCopyBits",
+4702: "gdi32.dll!NtGdiEngDeletePalette",
+4703: "gdi32.dll!NtGdiEngDeleteSurface",
+4704: "gdi32.dll!NtGdiEngEraseSurface",
+4705: "gdi32.dll!NtGdiEngUnlockSurface",
+4706: "gdi32.dll!NtGdiEngLockSurface",
+4707: "gdi32.dll!NtGdiEngBitBlt",
+4708: "gdi32.dll!NtGdiEngStretchBlt",
+4709: "gdi32.dll!NtGdiEngPlgBlt",
+4710: "gdi32.dll!NtGdiEngMarkBandingSurface",
+4711: "gdi32.dll!NtGdiEngStrokePath",
+4712: "gdi32.dll!NtGdiEngFillPath",
+4713: "gdi32.dll!NtGdiEngStrokeAndFillPath",
+4714: "gdi32.dll!NtGdiEngPaint",
+4715: "gdi32.dll!NtGdiEngLineTo",
+4716: "gdi32.dll!NtGdiEngAlphaBlend",
+4717: "gdi32.dll!NtGdiEngGradientFill",
+4718: "gdi32.dll!NtGdiEngTransparentBlt",
+4719: "gdi32.dll!NtGdiEngTextOut",
+4720: "gdi32.dll!NtGdiEngStretchBltROP",
+4721: "gdi32.dll!NtGdiXLATEOBJ_cGetPalette",
+4722: "gdi32.dll!NtGdiXLATEOBJ_iXlate",
+4723: "gdi32.dll!NtGdiXLATEOBJ_hGetColorTransform",
+4724: "gdi32.dll!NtGdiCLIPOBJ_bEnum",
+4725: "gdi32.dll!NtGdiCLIPOBJ_cEnumStart",
+4726: "gdi32.dll!NtGdiCLIPOBJ_ppoGetPath",
+4727: "gdi32.dll!NtGdiEngDeletePath",
+4728: "gdi32.dll!NtGdiEngCreateClip",
+4729: "gdi32.dll!NtGdiEngDeleteClip",
+4730: "gdi32.dll!NtGdiBRUSHOBJ_ulGetBrushColor",
+4731: "gdi32.dll!NtGdiBRUSHOBJ_pvAllocRbrush",
+4732: "gdi32.dll!NtGdiBRUSHOBJ_pvGetRbrush",
+4733: "gdi32.dll!NtGdiBRUSHOBJ_hGetColorTransform",
+4734: "gdi32.dll!NtGdiXFORMOBJ_bApplyXform",
+4735: "gdi32.dll!NtGdiXFORMOBJ_iGetXform",
+4736: "gdi32.dll!NtGdiFONTOBJ_vGetInfo",
+4737: "gdi32.dll!NtGdiFONTOBJ_pxoGetXform",
+4738: "gdi32.dll!NtGdiFONTOBJ_cGetGlyphs",
+4739: "gdi32.dll!NtGdiFONTOBJ_pifi",
+4740: "gdi32.dll!NtGdiFONTOBJ_pfdg",
+4741: "gdi32.dll!NtGdiFONTOBJ_pQueryGlyphAttrs",
+4742: "gdi32.dll!NtGdiFONTOBJ_pvTrueTypeFontFile",
+4743: "gdi32.dll!NtGdiFONTOBJ_cGetAllGlyphHandles",
+4744: "gdi32.dll!NtGdiSTROBJ_bEnum",
+4745: "gdi32.dll!NtGdiSTROBJ_bEnumPositionsOnly",
+4746: "gdi32.dll!NtGdiSTROBJ_bGetAdvanceWidths",
+4747: "gdi32.dll!NtGdiSTROBJ_vEnumStart",
+4748: "gdi32.dll!NtGdiSTROBJ_dwGetCodePage",
+4749: "gdi32.dll!NtGdiPATHOBJ_vGetBounds",
+4750: "gdi32.dll!NtGdiPATHOBJ_bEnum",
+4751: "gdi32.dll!NtGdiPATHOBJ_vEnumStart",
+4752: "gdi32.dll!NtGdiPATHOBJ_vEnumStartClipLines",
+4753: "gdi32.dll!NtGdiPATHOBJ_bEnumClipLines",
+4754: "gdi32.dll!NtGdiGetDhpdev",
+4755: "gdi32.dll!NtGdiEngCheckAbort",
+4756: "gdi32.dll!NtGdiHT_Get8BPPFormatPalette",
+4757: "gdi32.dll!NtGdiHT_Get8BPPMaskPalette",
+4758: "gdi32.dll!NtGdiUpdateTransform",
+4759: "gdi32.dll!NtGdiSetPUMPDOBJ",
+4760: "gdi32.dll!NtGdiBRUSHOBJ_DeleteRbrush",
+4761: "gdi32.dll!NtGdiUMPDEngFreeUserMem",
+4762: "gdi32.dll!NtGdiDrawStream",
+}
diff --git a/chromium/tools/traceline/traceline/sidestep/ia32_modrm_map.cc b/chromium/tools/traceline/traceline/sidestep/ia32_modrm_map.cc
new file mode 100644
index 00000000000..e1aeec6765d
--- /dev/null
+++ b/chromium/tools/traceline/traceline/sidestep/ia32_modrm_map.cc
@@ -0,0 +1,92 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Table of relevant information about how to decode the ModR/M byte.
+// Based on information in the IA-32 Intel Architecture
+// Software Developer's Manual Volume 2: Instruction Set Reference.
+
+#include "sidestep/mini_disassembler.h"
+#include "sidestep/mini_disassembler_types.h"
+
+namespace sidestep {
+
+const ModrmEntry MiniDisassembler::s_ia16_modrm_map_[] = {
+// mod == 00
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { true, false, OS_WORD },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+// mod == 01
+ /* r/m == 000 */ { true, false, OS_BYTE },
+ /* r/m == 001 */ { true, false, OS_BYTE },
+ /* r/m == 010 */ { true, false, OS_BYTE },
+ /* r/m == 011 */ { true, false, OS_BYTE },
+ /* r/m == 100 */ { true, false, OS_BYTE },
+ /* r/m == 101 */ { true, false, OS_BYTE },
+ /* r/m == 110 */ { true, false, OS_BYTE },
+ /* r/m == 111 */ { true, false, OS_BYTE },
+// mod == 10
+ /* r/m == 000 */ { true, false, OS_WORD },
+ /* r/m == 001 */ { true, false, OS_WORD },
+ /* r/m == 010 */ { true, false, OS_WORD },
+ /* r/m == 011 */ { true, false, OS_WORD },
+ /* r/m == 100 */ { true, false, OS_WORD },
+ /* r/m == 101 */ { true, false, OS_WORD },
+ /* r/m == 110 */ { true, false, OS_WORD },
+ /* r/m == 111 */ { true, false, OS_WORD },
+// mod == 11
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO }
+};
+
+const ModrmEntry MiniDisassembler::s_ia32_modrm_map_[] = {
+// mod == 00
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, true, OS_ZERO },
+ /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+// mod == 01
+ /* r/m == 000 */ { true, false, OS_BYTE },
+ /* r/m == 001 */ { true, false, OS_BYTE },
+ /* r/m == 010 */ { true, false, OS_BYTE },
+ /* r/m == 011 */ { true, false, OS_BYTE },
+ /* r/m == 100 */ { true, true, OS_BYTE },
+ /* r/m == 101 */ { true, false, OS_BYTE },
+ /* r/m == 110 */ { true, false, OS_BYTE },
+ /* r/m == 111 */ { true, false, OS_BYTE },
+// mod == 10
+ /* r/m == 000 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 001 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 010 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 011 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 100 */ { true, true, OS_DOUBLE_WORD },
+ /* r/m == 101 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 110 */ { true, false, OS_DOUBLE_WORD },
+ /* r/m == 111 */ { true, false, OS_DOUBLE_WORD },
+// mod == 11
+ /* r/m == 000 */ { false, false, OS_ZERO },
+ /* r/m == 001 */ { false, false, OS_ZERO },
+ /* r/m == 010 */ { false, false, OS_ZERO },
+ /* r/m == 011 */ { false, false, OS_ZERO },
+ /* r/m == 100 */ { false, false, OS_ZERO },
+ /* r/m == 101 */ { false, false, OS_ZERO },
+ /* r/m == 110 */ { false, false, OS_ZERO },
+ /* r/m == 111 */ { false, false, OS_ZERO },
+};
+
+}; // namespace sidestep
diff --git a/chromium/tools/traceline/traceline/sidestep/ia32_opcode_map.cc b/chromium/tools/traceline/traceline/sidestep/ia32_opcode_map.cc
new file mode 100644
index 00000000000..4600cfa25b9
--- /dev/null
+++ b/chromium/tools/traceline/traceline/sidestep/ia32_opcode_map.cc
@@ -0,0 +1,1159 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Opcode decoding maps. Based on the IA-32 Intel Architecture
+// Software Developer's Manual Volume 2: Instruction Set Reference. Idea
+// for how to lay out the tables in memory taken from the implementation
+// in the Bastard disassembly environment.
+
+#include "sidestep/mini_disassembler.h"
+
+namespace sidestep {
+
+/*
+* This is the first table to be searched; the first field of each
+* Opcode in the table is either 0 to indicate you're in the
+* right table, or an index to the correct table, in the global
+* map g_pentiumOpcodeMap
+*/
+const Opcode s_first_opcode_byte[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF */ { 1, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x10 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x11 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x12 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x13 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x14 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x15 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x16 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x17 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x18 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x19 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1E */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1F */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x20 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x21 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x22 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x23 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x24 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x25 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x26 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x27 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "daa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x28 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x29 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "das", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x30 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x31 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x32 */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x33 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x34 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x35 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x36 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x37 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aaa", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x38 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x39 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3C */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3E */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "aas", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x40 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x41 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x42 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x43 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x44 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x45 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x46 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x47 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x48 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x49 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x50 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x51 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x52 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x53 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x54 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x55 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x56 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x57 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x58 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x59 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5A */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5B */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5C */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5D */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5E */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x60 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x61 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x62 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_A, AM_NOT_USED, "bound", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x63 */ { 0, IT_GENERIC, AM_E | OT_W, AM_G | OT_W, AM_NOT_USED, "arpl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x64 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x65 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x66 */ { 0, IT_PREFIX_OPERAND, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x67 */ { 0, IT_PREFIX_ADDRESS, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x68 */ { 0, IT_GENERIC, AM_I | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x69 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_V, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6A */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_I | OT_B, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6C */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "insb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6D */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "insd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6E */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X | OT_B, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6F */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X | OT_V, AM_NOT_USED, "outsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x70 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x71 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x72 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x73 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x74 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x75 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x76 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x77 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x78 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x79 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7A */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7B */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7C */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7D */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7E */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7F */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x80 */ { 2, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x81 */ { 3, IT_REFERENCE, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x82 */ { 4, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x83 */ { 5, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x84 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x85 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x86 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x87 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x88 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x89 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8A */ { 0, IT_GENERIC, AM_G | OT_B, AM_E | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8C */ { 0, IT_GENERIC, AM_E | OT_W, AM_S | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8D */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, "lea", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8E */ { 0, IT_GENERIC, AM_S | OT_W, AM_E | OT_W, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8F */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x90 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "nop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x91 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x92 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x93 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x94 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x95 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x96 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x97 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "xchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x98 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cwde", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x99 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cdq", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9A */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "callf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9B */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wait", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "pushfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "popfd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9E */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9F */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lahf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_O | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_O | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA2 */ { 0, IT_GENERIC, AM_O | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA3 */ { 0, IT_GENERIC, AM_O | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA4 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "movsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA5 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "movsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA6 */ { 0, IT_GENERIC, AM_X | OT_B, AM_Y | OT_B, AM_NOT_USED, "cmpsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA7 */ { 0, IT_GENERIC, AM_X | OT_V, AM_Y | OT_V, AM_NOT_USED, "cmpsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAA */ { 0, IT_GENERIC, AM_Y | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "stosb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAB */ { 0, IT_GENERIC, AM_Y | OT_V, AM_REGISTER | OT_V, AM_NOT_USED, "stosd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_X| OT_B, AM_NOT_USED, "lodsb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_X| OT_V, AM_NOT_USED, "lodsd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAE */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_Y | OT_B, AM_NOT_USED, "scasb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_Y | OT_V, AM_NOT_USED, "scasd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB0 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB1 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB2 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB3 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB8 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB9 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBA */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBB */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBC */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBD */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBE */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBF */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC0 */ { 6, IT_REFERENCE, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC1 */ { 7, IT_REFERENCE, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC2 */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC3 */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC4 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "les", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_V, AM_M | OT_P, AM_NOT_USED, "lds", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC8 */ { 0, IT_GENERIC, AM_I | OT_W, AM_I | OT_B, AM_NOT_USED, "enter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "leave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCA */ { 0, IT_RETURN, AM_I | OT_W, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCB */ { 0, IT_RETURN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "retf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "int3", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCD */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "int", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCE */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "into", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCF */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "iret", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD0 */ { 8, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD1 */ { 9, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD2 */ { 10, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD3 */ { 11, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD4 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aam", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD5 */ { 0, IT_GENERIC, AM_I | OT_B, AM_NOT_USED, AM_NOT_USED, "aad", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "xlat", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+
+ // The following 8 lines would be references to the FPU tables, but we currently
+ // do not support the FPU instructions in this disassembler.
+
+ /* 0xD8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDA */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDB */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDC */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDD */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDE */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xDF */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+
+
+ /* 0xE0 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE1 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loopz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE2 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "loop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE3 */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jcxz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE4 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE5 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_I | OT_B, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE6 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE7 */ { 0, IT_GENERIC, AM_I | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE8 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE9 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEA */ { 0, IT_JUMP, AM_A | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEB */ { 0, IT_JUMP, AM_J | OT_B, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEC */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xED */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_REGISTER | OT_W, AM_NOT_USED, "in", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEE */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_B, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xEF */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_REGISTER | OT_V, AM_NOT_USED, "out", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF0 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lock:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF2 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "repne:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF3 */ { 0, IT_PREFIX, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rep:", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF4 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "hlt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF6 */ { 12, IT_REFERENCE, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF7 */ { 13, IT_REFERENCE, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cli", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFB */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFC */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFD */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "std", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFE */ { 14, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xFF */ { 15, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f[] = {
+ /* 0x0 */ { 16, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 17, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "lsl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "invd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wbinvd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud2", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xE */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x10 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movups", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "movsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "movss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movupd" } },
+ /* 0x11 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movups", true,
+ /* F2h */ { 0, IT_GENERIC, AM_W | OT_SD, AM_V | OT_SD, AM_NOT_USED, "movsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_W | OT_SS, AM_V | OT_SS, AM_NOT_USED, "movss" },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movupd" } },
+ /* 0x12 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // only one of ...
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhlps" }, // ...these two is correct, Intel doesn't specify which
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_S, AM_NOT_USED, "movlpd" } },
+ /* 0x13 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movlpd" } },
+ /* 0x14 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpcklps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpcklpd" } },
+ /* 0x15 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_Q, AM_NOT_USED, "unpckhps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_Q, AM_NOT_USED, "unpckhpd" } },
+ /* 0x16 */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // only one of...
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movlhps" }, // ...these two is correct, Intel doesn't specify which
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movhpd" } },
+ /* 0x17 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movhpd" } },
+ /* 0x18 */ { 18, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x19 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1C */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x20 */ { 0, IT_GENERIC, AM_R | OT_D, AM_C | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x21 */ { 0, IT_GENERIC, AM_R | OT_D, AM_D | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x22 */ { 0, IT_GENERIC, AM_C | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x23 */ { 0, IT_GENERIC, AM_D | OT_D, AM_R | OT_D, AM_NOT_USED, "mov", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x24 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x25 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x26 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x27 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x28 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "movaps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "movapd" } },
+ /* 0x29 */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movaps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movapd" } },
+ /* 0x2A */ { 0, IT_GENERIC, AM_V | OT_PS, AM_Q | OT_Q, AM_NOT_USED, "cvtpi2ps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_E | OT_D, AM_NOT_USED, "cvtsi2sd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_E | OT_D, AM_NOT_USED, "cvtsi2ss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_Q | OT_DQ, AM_NOT_USED, "cvtpi2pd" } },
+ /* 0x2B */ { 0, IT_GENERIC, AM_W | OT_PS, AM_V | OT_PS, AM_NOT_USED, "movntps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_PD, AM_V | OT_PD, AM_NOT_USED, "movntpd" } },
+ /* 0x2C */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvttps2pi", true,
+ /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvttsd2si" },
+ /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvttss2si" },
+ /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2pi" } },
+ /* 0x2D */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_W | OT_PS, AM_NOT_USED, "cvtps2pi", true,
+ /* F2h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SD, AM_NOT_USED, "cvtsd2si" },
+ /* F3h */ { 0, IT_GENERIC, AM_G | OT_D, AM_W | OT_SS, AM_NOT_USED, "cvtss2si" },
+ /* 66h */ { 0, IT_GENERIC, AM_Q | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2pi" } },
+ /* 0x2E */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "ucomiss", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "ucomisd" } },
+ /* 0x2F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_SS, AM_NOT_USED, "comiss", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "comisd" } },
+ /* 0x30 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "wrmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x31 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdtsc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x32 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdmsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x33 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rdpmc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x34 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysenter", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x35 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "sysexit", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x36 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x37 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x38 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x39 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3A */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3B */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3D */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3E */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3F */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x40 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x41 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x42 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x43 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x44 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x45 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x46 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x47 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmova", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x48 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x49 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4A */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4B */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4C */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4D */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4E */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4F */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "cmovg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x50 */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PS, AM_NOT_USED, "movmskps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_PD, AM_NOT_USED, "movmskpd" } },
+ /* 0x51 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "sqrtps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "sqrtsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "sqrtss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "sqrtpd" } },
+ /* 0x52 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rsqrtps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rsqrtss" },
+ /* 66h */ { 0 } },
+ /* 0x53 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "rcpps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "rcpss" },
+ /* 66h */ { 0 } },
+ /* 0x54 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andpd" } },
+ /* 0x55 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "andnps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "andnpd" } },
+ /* 0x56 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "orps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "orpd" } },
+ /* 0x57 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "xorps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "xorpd" } },
+ /* 0x58 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "addps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "addsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "addss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "addpd" } },
+ /* 0x59 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "mulps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "mulsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "mulss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "mulpd" } },
+ /* 0x5A */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PS, AM_NOT_USED, "cvtps2pd", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "cvtsd2ss" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "cvtss2sd" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PD, AM_NOT_USED, "cvtpd2ps" } },
+ /* 0x5B */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2ps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvttps2dq" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PS, AM_NOT_USED, "cvtps2dq" } },
+ /* 0x5C */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "subps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "subsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "subss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "subpd" } },
+ /* 0x5D */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "minps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "minsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "minss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "minpd" } },
+ /* 0x5E */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "divps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "divsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "divss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "divpd" } },
+ /* 0x5F */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_NOT_USED, "maxps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_NOT_USED, "maxsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_NOT_USED, "maxss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_NOT_USED, "maxpd" } },
+ /* 0x60 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklbw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklbw" } },
+ /* 0x61 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpcklwd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklwd" } },
+ /* 0x62 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckldq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpckldq" } },
+ /* 0x63 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packsswb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packsswb" } },
+ /* 0x64 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtb" } },
+ /* 0x65 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtw" } },
+ /* 0x66 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "pcmpgtd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpgtd" } },
+ /* 0x67 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packuswb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "packuswb" } },
+ /* 0x68 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhbw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhbw" } },
+ /* 0x69 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhwd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhwd" } },
+ /* 0x6A */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "punpckhdq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "punpckhdq" } },
+ /* 0x6B */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "packssdw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_Q | OT_DQ, AM_NOT_USED, "packssdw" } },
+ /* 0x6C */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
+ /* 0x6D */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "punpcklqdq" } },
+ /* 0x6E */ { 0, IT_GENERIC, AM_P | OT_D, AM_E | OT_D, AM_NOT_USED, "movd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_NOT_USED, "movd" } },
+ /* 0x6F */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_D, AM_NOT_USED, "movq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqu" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "movdqa" } },
+ /* 0x70 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_I | OT_B, "pshuf", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshuflw" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufhw" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_I | OT_B, "pshufd" } },
+ /* 0x71 */ { 19, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x72 */ { 20, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x73 */ { 21, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x74 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqb" } },
+ /* 0x75 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqw" } },
+ /* 0x76 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pcmpeqd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pcmpeqd" } },
+ /* 0x77 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "emms", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+
+ // The following six opcodes are escapes into the MMX stuff, which this disassembler does not support.
+ /* 0x78 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x79 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7A */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7B */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7C */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7D */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+
+ /* 0x7E */ { 0, IT_GENERIC, AM_E | OT_D, AM_P | OT_D, AM_NOT_USED, "movd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movq" },
+ /* 66h */ { 0, IT_GENERIC, AM_E | OT_D, AM_V | OT_DQ, AM_NOT_USED, "movd" } },
+ /* 0x7F */ { 0, IT_GENERIC, AM_Q | OT_Q, AM_P | OT_Q, AM_NOT_USED, "movq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqu" },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movdqa" } },
+ /* 0x80 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x81 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x82 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x83 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x84 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x85 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x86 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x87 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "ja", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x88 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "js", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x89 */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8A */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8B */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8C */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8D */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8E */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x8F */ { 0, IT_JUMP, AM_J | OT_V, AM_NOT_USED, AM_NOT_USED, "jg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x90 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seto", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x91 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setno", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x92 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x93 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x94 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x95 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setnz", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x96 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setbe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x97 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "seta", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x98 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "sets", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x99 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setns", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9A */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpe", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9B */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setpo", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9C */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9D */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setge", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9E */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setle", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x9F */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "setg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA0 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA1 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "cpuid", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shld", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA6 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA7 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA8 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xA9 */ { 0, IT_GENERIC, AM_REGISTER | OT_W, AM_NOT_USED, AM_NOT_USED, "pop", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAA */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "rsm", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAC */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAD */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_I | OT_B | AM_REGISTER, "shrd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAE */ { 22, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xAF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "cmpxchg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB2 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lss", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB4 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lfs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB5 */ { 0, IT_GENERIC, AM_M | OT_P, AM_NOT_USED, AM_NOT_USED, "lgs", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB6 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB7 */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movzx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB8 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xB9 */ { 0, IT_UNKNOWN, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ud1", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBA */ { 23, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBB */ { 0, IT_GENERIC, AM_E | OT_V, AM_G | OT_V, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBC */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsf", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBD */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_V, AM_NOT_USED, "bsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBE */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_B, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xBF */ { 0, IT_GENERIC, AM_G | OT_V, AM_E | OT_W, AM_NOT_USED, "movsx", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_G | OT_B, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "xadd", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC2 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "cmpps", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_SD, AM_W | OT_SD, AM_I | OT_B, "cmpsd" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_SS, AM_W | OT_SS, AM_I | OT_B, "cmpss" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "cmppd" } },
+ /* 0xC3 */ { 0, IT_GENERIC, AM_E | OT_D, AM_G | OT_D, AM_NOT_USED, "movnti", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_E | OT_D, AM_I | OT_B, "pinsrw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_E | OT_D, AM_I | OT_B, "pinsrw" } },
+ /* 0xC5 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_I | OT_B, "pextrw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_I | OT_B, "pextrw" } },
+ /* 0xC6 */ { 0, IT_GENERIC, AM_V | OT_PS, AM_W | OT_PS, AM_I | OT_B, "shufps", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_PD, AM_I | OT_B, "shufpd" } },
+ /* 0xC7 */ { 24, IT_REFERENCE, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC8 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xC9 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCA */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCB */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCC */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCD */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCE */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xCF */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "bswap", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xD1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlw" } },
+ /* 0xD2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrld", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrld" } },
+ /* 0xD3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrlq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrlq" } },
+ /* 0xD4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddq" } },
+ /* 0xD5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmullw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmullw" } },
+ /* 0xD6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "unused without prefix", true,
+ /* F2h */ { 0, IT_GENERIC, AM_P | OT_Q, AM_W | OT_Q, AM_NOT_USED, "movdq2q" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_Q | OT_Q, AM_NOT_USED, "movq2dq" },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movq" } },
+ /* 0xD7 */ { 0, IT_GENERIC, AM_G | OT_D, AM_P | OT_Q, AM_NOT_USED, "pmovmskb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_G | OT_D, AM_V | OT_DQ, AM_NOT_USED, "pmovmskb" } },
+ /* 0xD8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusb" } },
+ /* 0xD9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubusw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubusw" } },
+ /* 0xDA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminub", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminub" } },
+ /* 0xDB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pand", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pand" } },
+ /* 0xDC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusb" } },
+ /* 0xDD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddusw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddusw" } },
+ /* 0xDE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxub", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxub" } },
+ /* 0xDF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pandn", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pandn" } },
+ /* 0xE0 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgb" } },
+ /* 0xE1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psraw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrqw" } },
+ /* 0xE2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psrad", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psrad" } },
+ /* 0xE3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pavgw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pavgw" } },
+ /* 0xE4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhuw" } },
+ /* 0xE5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmulhuw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmulhw" } },
+ /* 0xE6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "not used without prefix", true,
+ /* F2h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvtpd2dq" },
+ /* F3h */ { 0, IT_GENERIC, AM_V | OT_PD, AM_W | OT_DQ, AM_NOT_USED, "cvtdq2pd" },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_PD, AM_NOT_USED, "cvttpd2dq" } },
+ /* 0xE7 */ { 0, IT_GENERIC, AM_W | OT_Q, AM_V | OT_Q, AM_NOT_USED, "movntq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_V | OT_DQ, AM_NOT_USED, "movntdq" } },
+ /* 0xE8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsb" } },
+ /* 0xE9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubsw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubsw" } },
+ /* 0xEA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pminsw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pminsw" } },
+ /* 0xEB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "por", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "por" } },
+ /* 0xEC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsb" } },
+ /* 0xED */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddsw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddsw" } },
+ /* 0xEE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaxsw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaxsw" } },
+ /* 0xEF */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pxor", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pxor" } },
+ /* 0xF0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0xF1 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllw" } },
+ /* 0xF2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pslld", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pslld" } },
+ /* 0xF3 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psllq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psllq" } },
+ /* 0xF4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmuludq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmuludq" } },
+ /* 0xF5 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "pmaddwd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "pmaddwd" } },
+ /* 0xF6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psadbw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psadbw" } },
+ /* 0xF7 */ { 0, IT_GENERIC, AM_P | OT_PI, AM_Q | OT_PI, AM_NOT_USED, "maskmovq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "maskmovdqu" } },
+ /* 0xF8 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubb" } },
+ /* 0xF9 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubw" } },
+ /* 0xFA */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubd" } },
+ /* 0xFB */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "psubq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "psubq" } },
+ /* 0xFC */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddb", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddb" } },
+ /* 0xFD */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddw" } },
+ /* 0xFE */ { 0, IT_GENERIC, AM_P | OT_Q, AM_Q | OT_Q, AM_NOT_USED, "paddd", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_V | OT_DQ, AM_W | OT_DQ, AM_NOT_USED, "paddd" } },
+ /* 0xFF */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f00[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "sldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "str", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lldt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "ltr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "verw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f01[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "sidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lgdt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_M | OT_S, AM_NOT_USED, AM_NOT_USED, "lidt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "smsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_W, AM_NOT_USED, AM_NOT_USED, "lmsw", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_M | OT_B, AM_NOT_USED, AM_NOT_USED, "invlpg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f18[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_M | OT_ADDRESS_MODE_M, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_REGISTER | OT_D, AM_NOT_USED, AM_NOT_USED, "prefetch", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f71[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlw" } },
+ /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psraw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psraw" } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllw", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_P | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllw" } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f72[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrld", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrld" } },
+ /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrad", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrad" } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "pslld", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslld" } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0f73[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psrlq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psrlq" } },
+ /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_P | OT_Q, AM_I | OT_B, AM_NOT_USED, "psllq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "psllq" } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq", true,
+ /* F2h */ { 0 },
+ /* F3h */ { 0 },
+ /* 66h */ { 0, IT_GENERIC, AM_W | OT_DQ, AM_I | OT_B, AM_NOT_USED, "pslldq" } },
+};
+
+const Opcode s_opcode_byte_after_0fae[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxsave", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "fxrstor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "ldmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "stmxcsr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "lfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "mfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, "clflush/sfence", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+};
+
+const Opcode s_opcode_byte_after_0fba[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bt", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "bts", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "btc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_0fc7[] = {
+ /* 0x0 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_M | OT_Q, AM_NOT_USED, AM_NOT_USED, "cmpxch8b", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_80[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_81[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_82[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_83[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "add", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "or", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "adc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sbb", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "and", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sub", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "xor", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "cmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_c0[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_c1[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d0[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d1[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_IMPLICIT, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d2[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_B, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_d3[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rol", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "ror", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "rcr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shl", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "shr", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sal", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_E | OT_V, AM_REGISTER | OT_B, AM_NOT_USED, "sar", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_f6[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_I | OT_B, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, OT_B | AM_REGISTER, AM_E | OT_B, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_B, AM_E | OT_B, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_f7[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_I | OT_V, AM_NOT_USED, "test", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "not", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "neg", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "mul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "imul", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "div", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_GENERIC, AM_REGISTER | OT_V, AM_E | OT_V, AM_NOT_USED, "idiv", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_fe[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_B, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+const Opcode s_opcode_byte_after_ff[] = {
+ /* 0x0 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "inc", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x1 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "dec", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x2 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x3 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "call", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x4 */ { 0, IT_JUMP, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x5 */ { 0, IT_JUMP, AM_E | OT_P, AM_NOT_USED, AM_NOT_USED, "jmp", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x6 */ { 0, IT_GENERIC, AM_E | OT_V, AM_NOT_USED, AM_NOT_USED, "push", false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } },
+ /* 0x7 */ { 0, IT_UNUSED, AM_NOT_USED, AM_NOT_USED, AM_NOT_USED, 0, false, /* F2h */ { 0 }, /* F3h */ { 0 }, /* 66h */ { 0 } }
+};
+
+/*
+* A table of all the other tables, containing some extra information, e.g.
+* how to mask out the byte we're looking at.
+*/
+const OpcodeTable MiniDisassembler::s_ia32_opcode_map_[]={
+ // One-byte opcodes and jumps to larger
+ /* 0 */ {s_first_opcode_byte, 0, 0xff, 0, 0xff},
+ // Two-byte opcodes (second byte)
+ /* 1 */ {s_opcode_byte_after_0f, 0, 0xff, 0, 0xff},
+ // Start of tables for opcodes using ModR/M bits as extension
+ /* 2 */ {s_opcode_byte_after_80, 3, 0x07, 0, 0x07},
+ /* 3 */ {s_opcode_byte_after_81, 3, 0x07, 0, 0x07},
+ /* 4 */ {s_opcode_byte_after_82, 3, 0x07, 0, 0x07},
+ /* 5 */ {s_opcode_byte_after_83, 3, 0x07, 0, 0x07},
+ /* 6 */ {s_opcode_byte_after_c0, 3, 0x07, 0, 0x07},
+ /* 7 */ {s_opcode_byte_after_c1, 3, 0x07, 0, 0x07},
+ /* 8 */ {s_opcode_byte_after_d0, 3, 0x07, 0, 0x07},
+ /* 9 */ {s_opcode_byte_after_d1, 3, 0x07, 0, 0x07},
+ /* 10 */ {s_opcode_byte_after_d2, 3, 0x07, 0, 0x07},
+ /* 11 */ {s_opcode_byte_after_d3, 3, 0x07, 0, 0x07},
+ /* 12 */ {s_opcode_byte_after_f6, 3, 0x07, 0, 0x07},
+ /* 13 */ {s_opcode_byte_after_f7, 3, 0x07, 0, 0x07},
+ /* 14 */ {s_opcode_byte_after_fe, 3, 0x07, 0, 0x01},
+ /* 15 */ {s_opcode_byte_after_ff, 3, 0x07, 0, 0x07},
+ /* 16 */ {s_opcode_byte_after_0f00, 3, 0x07, 0, 0x07},
+ /* 17 */ {s_opcode_byte_after_0f01, 3, 0x07, 0, 0x07},
+ /* 18 */ {s_opcode_byte_after_0f18, 3, 0x07, 0, 0x07},
+ /* 19 */ {s_opcode_byte_after_0f71, 3, 0x07, 0, 0x07},
+ /* 20 */ {s_opcode_byte_after_0f72, 3, 0x07, 0, 0x07},
+ /* 21 */ {s_opcode_byte_after_0f73, 3, 0x07, 0, 0x07},
+ /* 22 */ {s_opcode_byte_after_0fae, 3, 0x07, 0, 0x07},
+ /* 23 */ {s_opcode_byte_after_0fba, 3, 0x07, 0, 0x07},
+ /* 24 */ {s_opcode_byte_after_0fc7, 3, 0x07, 0, 0x01}
+};
+
+}; // namespace sidestep
diff --git a/chromium/tools/traceline/traceline/sidestep/mini_disassembler.cc b/chromium/tools/traceline/traceline/sidestep/mini_disassembler.cc
new file mode 100644
index 00000000000..a603ebe637a
--- /dev/null
+++ b/chromium/tools/traceline/traceline/sidestep/mini_disassembler.cc
@@ -0,0 +1,416 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Implementation of MiniDisassembler.
+
+#include "sidestep/mini_disassembler.h"
+
+namespace sidestep {
+
+MiniDisassembler::MiniDisassembler(bool operand_default_is_32_bits,
+ bool address_default_is_32_bits)
+ : operand_default_is_32_bits_(operand_default_is_32_bits),
+ address_default_is_32_bits_(address_default_is_32_bits) {
+ Initialize();
+}
+
+MiniDisassembler::MiniDisassembler()
+ : operand_default_is_32_bits_(true),
+ address_default_is_32_bits_(true) {
+ Initialize();
+}
+
+InstructionType MiniDisassembler::Disassemble(
+ unsigned char* start_byte,
+ unsigned int* instruction_bytes) {
+ // Clean up any state from previous invocations.
+ Initialize();
+
+ // Start by processing any prefixes.
+ unsigned char* current_byte = start_byte;
+ unsigned int size = 0;
+ InstructionType instruction_type = ProcessPrefixes(current_byte, &size);
+
+ if (IT_UNKNOWN == instruction_type)
+ return instruction_type;
+
+ current_byte += size;
+ size = 0;
+
+ // Invariant: We have stripped all prefixes, and the operand_is_32_bits_
+ // and address_is_32_bits_ flags are correctly set.
+
+ instruction_type = ProcessOpcode(current_byte, 0, &size);
+
+ // Check for error processing instruction
+ if ((IT_UNKNOWN == instruction_type_) || (IT_UNUSED == instruction_type_)) {
+ return IT_UNKNOWN;
+ }
+
+ current_byte += size;
+
+ // Invariant: operand_bytes_ indicates the total size of operands
+ // specified by the opcode and/or ModR/M byte and/or SIB byte.
+ // pCurrentByte points to the first byte after the ModR/M byte, or after
+ // the SIB byte if it is present (i.e. the first byte of any operands
+ // encoded in the instruction).
+
+ // We get the total length of any prefixes, the opcode, and the ModR/M and
+ // SIB bytes if present, by taking the difference of the original starting
+ // address and the current byte (which points to the first byte of the
+ // operands if present, or to the first byte of the next instruction if
+ // they are not). Adding the count of bytes in the operands encoded in
+ // the instruction gives us the full length of the instruction in bytes.
+ *instruction_bytes += operand_bytes_ + (current_byte - start_byte);
+
+ // Return the instruction type, which was set by ProcessOpcode().
+ return instruction_type_;
+}
+
+void MiniDisassembler::Initialize() {
+ operand_is_32_bits_ = operand_default_is_32_bits_;
+ address_is_32_bits_ = address_default_is_32_bits_;
+ operand_bytes_ = 0;
+ have_modrm_ = false;
+ should_decode_modrm_ = false;
+ instruction_type_ = IT_UNKNOWN;
+ got_f2_prefix_ = false;
+ got_f3_prefix_ = false;
+ got_66_prefix_ = false;
+}
+
+InstructionType MiniDisassembler::ProcessPrefixes(unsigned char* start_byte,
+ unsigned int* size) {
+ InstructionType instruction_type = IT_GENERIC;
+ const Opcode& opcode = s_ia32_opcode_map_[0].table_[*start_byte];
+
+ switch (opcode.type_) {
+ case IT_PREFIX_ADDRESS:
+ address_is_32_bits_ = !address_default_is_32_bits_;
+ goto nochangeoperand;
+ case IT_PREFIX_OPERAND:
+ operand_is_32_bits_ = !operand_default_is_32_bits_;
+ nochangeoperand:
+ case IT_PREFIX:
+
+ if (0xF2 == (*start_byte))
+ got_f2_prefix_ = true;
+ else if (0xF3 == (*start_byte))
+ got_f3_prefix_ = true;
+ else if (0x66 == (*start_byte))
+ got_66_prefix_ = true;
+
+ instruction_type = opcode.type_;
+ (*size)++;
+ // we got a prefix, so add one and check next byte
+ ProcessPrefixes(start_byte + 1, size);
+ default:
+ break; // not a prefix byte
+ }
+
+ return instruction_type;
+}
+
+InstructionType MiniDisassembler::ProcessOpcode(unsigned char* start_byte,
+ unsigned int table_index,
+ unsigned int* size) {
+ const OpcodeTable& table = s_ia32_opcode_map_[table_index]; // Get our table
+ unsigned char current_byte = (*start_byte) >> table.shift_;
+ current_byte = current_byte & table.mask_; // Mask out the bits we will use
+
+ // Check whether the byte we have is inside the table we have.
+ if (current_byte < table.min_lim_ || current_byte > table.max_lim_) {
+ instruction_type_ = IT_UNKNOWN;
+ return instruction_type_;
+ }
+
+ const Opcode& opcode = table.table_[current_byte];
+ if (IT_UNUSED == opcode.type_) {
+ // This instruction is not used by the IA-32 ISA, so we indicate
+ // this to the user. Probably means that we were pointed to
+ // a byte in memory that was not the start of an instruction.
+ instruction_type_ = IT_UNUSED;
+ return instruction_type_;
+ } else if (IT_REFERENCE == opcode.type_) {
+ // We are looking at an opcode that has more bytes (or is continued
+ // in the ModR/M byte). Recursively find the opcode definition in
+ // the table for the opcode's next byte.
+ (*size)++;
+ ProcessOpcode(start_byte + 1, opcode.table_index_, size);
+ return instruction_type_;
+ }
+
+ const SpecificOpcode* specific_opcode = reinterpret_cast<
+ const SpecificOpcode*>(&opcode);
+ if (opcode.is_prefix_dependent_) {
+ if (got_f2_prefix_ && opcode.opcode_if_f2_prefix_.mnemonic_ != 0) {
+ specific_opcode = &opcode.opcode_if_f2_prefix_;
+ } else if (got_f3_prefix_ && opcode.opcode_if_f3_prefix_.mnemonic_ != 0) {
+ specific_opcode = &opcode.opcode_if_f3_prefix_;
+ } else if (got_66_prefix_ && opcode.opcode_if_66_prefix_.mnemonic_ != 0) {
+ specific_opcode = &opcode.opcode_if_66_prefix_;
+ }
+ }
+
+ // Inv: The opcode type is known.
+ instruction_type_ = specific_opcode->type_;
+
+ // Let's process the operand types to see if we have any immediate
+ // operands, and/or a ModR/M byte.
+
+ ProcessOperand(specific_opcode->flag_dest_);
+ ProcessOperand(specific_opcode->flag_source_);
+ ProcessOperand(specific_opcode->flag_aux_);
+
+ // Inv: We have processed the opcode and incremented operand_bytes_
+ // by the number of bytes of any operands specified by the opcode
+ // that are stored in the instruction (not registers etc.). Now
+ // we need to return the total number of bytes for the opcode and
+ // for the ModR/M or SIB bytes if they are present.
+
+ if (table.mask_ != 0xff) {
+ if (have_modrm_) {
+ // we're looking at a ModR/M byte so we're not going to
+ // count that into the opcode size
+ ProcessModrm(start_byte, size);
+ return IT_GENERIC;
+ } else {
+ // need to count the ModR/M byte even if it's just being
+ // used for opcode extension
+ (*size)++;
+ return IT_GENERIC;
+ }
+ } else {
+ if (have_modrm_) {
+ // The ModR/M byte is the next byte.
+ (*size)++;
+ ProcessModrm(start_byte + 1, size);
+ return IT_GENERIC;
+ } else {
+ (*size)++;
+ return IT_GENERIC;
+ }
+ }
+}
+
+bool MiniDisassembler::ProcessOperand(int flag_operand) {
+ bool succeeded = true;
+ if (AM_NOT_USED == flag_operand)
+ return succeeded;
+
+ // Decide what to do based on the addressing mode.
+ switch (flag_operand & AM_MASK) {
+ // No ModR/M byte indicated by these addressing modes, and no
+ // additional (e.g. immediate) parameters.
+ case AM_A: // Direct address
+ case AM_F: // EFLAGS register
+ case AM_X: // Memory addressed by the DS:SI register pair
+ case AM_Y: // Memory addressed by the ES:DI register pair
+ case AM_IMPLICIT: // Parameter is implicit, occupies no space in
+ // instruction
+ break;
+
+ // There is a ModR/M byte but it does not necessarily need
+ // to be decoded.
+ case AM_C: // reg field of ModR/M selects a control register
+ case AM_D: // reg field of ModR/M selects a debug register
+ case AM_G: // reg field of ModR/M selects a general register
+ case AM_P: // reg field of ModR/M selects an MMX register
+ case AM_R: // mod field of ModR/M may refer only to a general register
+ case AM_S: // reg field of ModR/M selects a segment register
+ case AM_T: // reg field of ModR/M selects a test register
+ case AM_V: // reg field of ModR/M selects a 128-bit XMM register
+ have_modrm_ = true;
+ break;
+
+ // In these addressing modes, there is a ModR/M byte and it needs to be
+ // decoded. No other (e.g. immediate) params than indicated in ModR/M.
+ case AM_E: // Operand is either a general-purpose register or memory,
+ // specified by ModR/M byte
+ case AM_M: // ModR/M byte will refer only to memory
+ case AM_Q: // Operand is either an MMX register or memory (complex
+ // evaluation), specified by ModR/M byte
+ case AM_W: // Operand is either a 128-bit XMM register or memory (complex
+ // eval), specified by ModR/M byte
+ have_modrm_ = true;
+ should_decode_modrm_ = true;
+ break;
+
+ // These addressing modes specify an immediate or an offset value
+ // directly, so we need to look at the operand type to see how many
+ // bytes.
+ case AM_I: // Immediate data.
+ case AM_J: // Jump to offset.
+ case AM_O: // Operand is at offset.
+ switch (flag_operand & OT_MASK) {
+ case OT_B: // Byte regardless of operand-size attribute.
+ operand_bytes_ += OS_BYTE;
+ break;
+ case OT_C: // Byte or word, depending on operand-size attribute.
+ if (operand_is_32_bits_)
+ operand_bytes_ += OS_WORD;
+ else
+ operand_bytes_ += OS_BYTE;
+ break;
+ case OT_D: // Doubleword, regardless of operand-size attribute.
+ operand_bytes_ += OS_DOUBLE_WORD;
+ break;
+ case OT_DQ: // Double-quadword, regardless of operand-size attribute.
+ operand_bytes_ += OS_DOUBLE_QUAD_WORD;
+ break;
+ case OT_P: // 32-bit or 48-bit pointer, depending on operand-size
+ // attribute.
+ if (operand_is_32_bits_)
+ operand_bytes_ += OS_48_BIT_POINTER;
+ else
+ operand_bytes_ += OS_32_BIT_POINTER;
+ break;
+ case OT_PS: // 128-bit packed single-precision floating-point data.
+ operand_bytes_ += OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING;
+ break;
+ case OT_Q: // Quadword, regardless of operand-size attribute.
+ operand_bytes_ += OS_QUAD_WORD;
+ break;
+ case OT_S: // 6-byte pseudo-descriptor.
+ operand_bytes_ += OS_PSEUDO_DESCRIPTOR;
+ break;
+ case OT_SD: // Scalar Double-Precision Floating-Point Value
+ case OT_PD: // Unaligned packed double-precision floating point value
+ operand_bytes_ += OS_DOUBLE_PRECISION_FLOATING;
+ break;
+ case OT_SS:
+ // Scalar element of a 128-bit packed single-precision
+ // floating data.
+ // We simply return enItUnknown since we don't have to support
+ // floating point
+ succeeded = false;
+ break;
+ case OT_V: // Word or doubleword, depending on operand-size attribute.
+ if (operand_is_32_bits_)
+ operand_bytes_ += OS_DOUBLE_WORD;
+ else
+ operand_bytes_ += OS_WORD;
+ break;
+ case OT_W: // Word, regardless of operand-size attribute.
+ operand_bytes_ += OS_WORD;
+ break;
+
+ // Can safely ignore these.
+ case OT_A: // Two one-word operands in memory or two double-word
+ // operands in memory
+ case OT_PI: // Quadword MMX technology register (e.g. mm0)
+ case OT_SI: // Doubleword integer register (e.g., eax)
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return succeeded;
+}
+
+bool MiniDisassembler::ProcessModrm(unsigned char* start_byte,
+ unsigned int* size) {
+ // If we don't need to decode, we just return the size of the ModR/M
+ // byte (there is never a SIB byte in this case).
+ if (!should_decode_modrm_) {
+ (*size)++;
+ return true;
+ }
+
+ // We never care about the reg field, only the combination of the mod
+ // and r/m fields, so let's start by packing those fields together into
+ // 5 bits.
+ unsigned char modrm = (*start_byte);
+ unsigned char mod = modrm & 0xC0; // mask out top two bits to get mod field
+ modrm = modrm & 0x07; // mask out bottom 3 bits to get r/m field
+ mod = mod >> 3; // shift the mod field to the right place
+ modrm = mod | modrm; // combine the r/m and mod fields as discussed
+ mod = mod >> 3; // shift the mod field to bits 2..0
+
+ // Invariant: modrm contains the mod field in bits 4..3 and the r/m field
+ // in bits 2..0, and mod contains the mod field in bits 2..0
+
+ const ModrmEntry* modrm_entry = 0;
+ if (address_is_32_bits_)
+ modrm_entry = &s_ia32_modrm_map_[modrm];
+ else
+ modrm_entry = &s_ia16_modrm_map_[modrm];
+
+ // Invariant: modrm_entry points to information that we need to decode
+ // the ModR/M byte.
+
+ // Add to the count of operand bytes, if the ModR/M byte indicates
+ // that some operands are encoded in the instruction.
+ if (modrm_entry->is_encoded_in_instruction_)
+ operand_bytes_ += modrm_entry->operand_size_;
+
+ // Process the SIB byte if necessary, and return the count
+ // of ModR/M and SIB bytes.
+ if (modrm_entry->use_sib_byte_) {
+ (*size)++;
+ return ProcessSib(start_byte + 1, mod, size);
+ } else {
+ (*size)++;
+ return true;
+ }
+}
+
+bool MiniDisassembler::ProcessSib(unsigned char* start_byte,
+ unsigned char mod,
+ unsigned int* size) {
+ // get the mod field from the 2..0 bits of the SIB byte
+ unsigned char sib_base = (*start_byte) & 0x07;
+ if (0x05 == sib_base) {
+ switch (mod) {
+ case 0x00: // mod == 00
+ case 0x02: // mod == 10
+ operand_bytes_ += OS_DOUBLE_WORD;
+ break;
+ case 0x01: // mod == 01
+ operand_bytes_ += OS_BYTE;
+ break;
+ case 0x03: // mod == 11
+ // According to the IA-32 docs, there does not seem to be a disp
+ // value for this value of mod
+ default:
+ break;
+ }
+ }
+
+ (*size)++;
+ return true;
+}
+
+}; // namespace sidestep
diff --git a/chromium/tools/traceline/traceline/sidestep/mini_disassembler.h b/chromium/tools/traceline/traceline/sidestep/mini_disassembler.h
new file mode 100644
index 00000000000..2c3ea2f2d5e
--- /dev/null
+++ b/chromium/tools/traceline/traceline/sidestep/mini_disassembler.h
@@ -0,0 +1,156 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Definition of MiniDisassembler.
+
+#ifndef TRACELINE_SIDESTEP_MINI_DISASSEMBLER_H_
+#define TRACELINE_SIDESTEP_MINI_DISASSEMBLER_H_
+
+#include "sidestep/mini_disassembler_types.h"
+
+namespace sidestep {
+
+// This small disassembler is very limited
+// in its functionality, and in fact does only the bare minimum required by the
+// preamble patching utility. It may be useful for other purposes, however.
+//
+// The limitations include at least the following:
+// -# No support for coprocessor opcodes, MMX, etc.
+// -# No machine-readable identification of opcodes or decoding of
+// assembly parameters. The name of the opcode (as a string) is given,
+// however, to aid debugging.
+//
+// You may ask what this little disassembler actually does, then? The answer is
+// that it does the following, which is exactly what the patching utility needs:
+// -# Indicates if opcode is a jump (any kind) or a return (any kind)
+// because this is important for the patching utility to determine if
+// a function is too short or there are jumps too early in it for it
+// to be preamble patched.
+// -# The opcode length is always calculated, so that the patching utility
+// can figure out where the next instruction starts, and whether it
+// already has enough instructions to replace with the absolute jump
+// to the patching code.
+//
+// The usage is quite simple; just create a MiniDisassembler and use its
+// Disassemble() method.
+//
+// If you would like to extend this disassembler, please refer to the
+// IA-32 Intel Architecture Software Developer's Manual Volume 2:
+// Instruction Set Reference for information about operand decoding
+// etc.
+class MiniDisassembler {
+ public:
+
+ // Creates a new instance and sets defaults.
+ //
+ // operand_default_32_bits: If true, the default operand size is
+ // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
+ // address_default_32_bits: If true, the default address size is
+ // set to 32 bits, which is the default under Win32. Otherwise it is 16 bits.
+ MiniDisassembler(bool operand_default_32_bits,
+ bool address_default_32_bits);
+
+ // Equivalent to MiniDisassembler(true, true);
+ MiniDisassembler();
+
+ // Attempts to disassemble a single instruction starting from the
+ // address in memory it is pointed to.
+ //
+ // start: Address where disassembly should start.
+ // instruction_bytes: Variable that will be incremented by
+ // the length in bytes of the instruction.
+ // Returns enItJump, enItReturn or enItGeneric on success. enItUnknown
+ // if unable to disassemble, enItUnused if this seems to be an unused
+ // opcode. In the last two (error) cases, cbInstruction will be set
+ // to 0xffffffff.
+ //
+ // Postcondition: This instance of the disassembler is ready to be used again,
+ // with unchanged defaults from creation time.
+ InstructionType Disassemble(unsigned char* start,
+ unsigned int* instruction_bytes);
+
+ private:
+
+ // Makes the disassembler ready for reuse.
+ void Initialize();
+
+ // Sets the flags for address and operand sizes.
+ // Returns Number of prefix bytes.
+ InstructionType ProcessPrefixes(unsigned char* start, unsigned int* size);
+
+ // Sets the flag for whether we have ModR/M, and increments
+ // operand_bytes_ if any are specifies by the opcode directly.
+ // Returns Number of opcode bytes.
+ InstructionType ProcessOpcode(unsigned char* start,
+ unsigned int table,
+ unsigned int* size);
+
+ // Checks the type of the supplied operand. Increments
+ // operand_bytes_ if it directly indicates an immediate etc.
+ // operand. Asserts have_modrm_ if the operand specifies
+ // a ModR/M byte.
+ bool ProcessOperand(int flag_operand);
+
+ // Increments operand_bytes_ by size specified by ModR/M and
+ // by SIB if present.
+ // Returns 0 in case of error, 1 if there is just a ModR/M byte,
+ // 2 if there is a ModR/M byte and a SIB byte.
+ bool ProcessModrm(unsigned char* start, unsigned int* size);
+
+ // Processes the SIB byte that it is pointed to.
+ // start: Pointer to the SIB byte.
+ // mod: The mod field from the ModR/M byte.
+ // Returns 1 to indicate success (indicates 1 SIB byte)
+ bool ProcessSib(unsigned char* start, unsigned char mod, unsigned int* size);
+
+ // The instruction type we have decoded from the opcode.
+ InstructionType instruction_type_;
+
+ // Counts the number of bytes that is occupied by operands in
+ // the current instruction (note: we don't care about how large
+ // operands stored in registers etc. are).
+ unsigned int operand_bytes_;
+
+ // True iff there is a ModR/M byte in this instruction.
+ bool have_modrm_;
+
+ // True iff we need to decode the ModR/M byte (sometimes it just
+ // points to a register, we can tell by the addressing mode).
+ bool should_decode_modrm_;
+
+ // Current operand size is 32 bits if true, 16 bits if false.
+ bool operand_is_32_bits_;
+
+ // Default operand size is 32 bits if true, 16 bits if false.
+ bool operand_default_is_32_bits_;
+
+ // Current address size is 32 bits if true, 16 bits if false.
+ bool address_is_32_bits_;
+
+ // Default address size is 32 bits if true, 16 bits if false.
+ bool address_default_is_32_bits_;
+
+ // Huge big opcode table based on the IA-32 manual, defined
+ // in Ia32OpcodeMap.cpp
+ static const OpcodeTable s_ia32_opcode_map_[];
+
+ // Somewhat smaller table to help with decoding ModR/M bytes
+ // when 16-bit addressing mode is being used. Defined in
+ // Ia32ModrmMap.cpp
+ static const ModrmEntry s_ia16_modrm_map_[];
+
+ // Somewhat smaller table to help with decoding ModR/M bytes
+ // when 32-bit addressing mode is being used. Defined in
+ // Ia32ModrmMap.cpp
+ static const ModrmEntry s_ia32_modrm_map_[];
+
+ // Indicators of whether we got certain prefixes that certain
+ // silly Intel instructions depend on in nonstandard ways for
+ // their behaviors.
+ bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_;
+};
+
+}; // namespace sidestep
+
+#endif // TRACELINE_SIDESTEP_MINI_DISASSEMBLER_H_
diff --git a/chromium/tools/traceline/traceline/sidestep/mini_disassembler_types.h b/chromium/tools/traceline/traceline/sidestep/mini_disassembler_types.h
new file mode 100644
index 00000000000..cb9e0062456
--- /dev/null
+++ b/chromium/tools/traceline/traceline/sidestep/mini_disassembler_types.h
@@ -0,0 +1,197 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Several simple types used by the disassembler and some of the patching
+// mechanisms.
+
+#ifndef TRACELINE_SIDESTEP_MINI_DISASSEMBLER_TYPES_H_
+#define TRACELINE_SIDESTEP_MINI_DISASSEMBLER_TYPES_H_
+
+namespace sidestep {
+
+// Categories of instructions that we care about
+enum InstructionType {
+ // This opcode is not used
+ IT_UNUSED,
+ // This disassembler does not recognize this opcode (error)
+ IT_UNKNOWN,
+ // This is not an instruction but a reference to another table
+ IT_REFERENCE,
+ // This byte is a prefix byte that we can ignore
+ IT_PREFIX,
+ // This is a prefix byte that switches to the nondefault address size
+ IT_PREFIX_ADDRESS,
+ // This is a prefix byte that switches to the nondefault operand size
+ IT_PREFIX_OPERAND,
+ // A jump or call instruction
+ IT_JUMP,
+ // A return instruction
+ IT_RETURN,
+ // Any other type of instruction (in this case we don't care what it is)
+ IT_GENERIC,
+};
+
+// Lists IA-32 operand sizes in multiples of 8 bits
+enum OperandSize {
+ OS_ZERO = 0,
+ OS_BYTE = 1,
+ OS_WORD = 2,
+ OS_DOUBLE_WORD = 4,
+ OS_QUAD_WORD = 8,
+ OS_DOUBLE_QUAD_WORD = 16,
+ OS_32_BIT_POINTER = 32/8,
+ OS_48_BIT_POINTER = 48/8,
+ OS_SINGLE_PRECISION_FLOATING = 32/8,
+ OS_DOUBLE_PRECISION_FLOATING = 64/8,
+ OS_DOUBLE_EXTENDED_PRECISION_FLOATING = 80/8,
+ OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING = 128/8,
+ OS_PSEUDO_DESCRIPTOR = 6
+};
+
+// Operand addressing methods from the IA-32 manual. The enAmMask value
+// is a mask for the rest. The other enumeration values are named for the
+// names given to the addressing methods in the manual, e.g. enAm_D is for
+// the D addressing method.
+//
+// The reason we use a full 4 bytes and a mask, is that we need to combine
+// these flags with the enOperandType to store the details
+// on the operand in a single integer.
+enum AddressingMethod {
+ AM_NOT_USED = 0, // This operand is not used for this instruction
+ AM_MASK = 0x00FF0000, // Mask for the rest of the values in this enumeration
+ AM_A = 0x00010000, // A addressing type
+ AM_C = 0x00020000, // C addressing type
+ AM_D = 0x00030000, // D addressing type
+ AM_E = 0x00040000, // E addressing type
+ AM_F = 0x00050000, // F addressing type
+ AM_G = 0x00060000, // G addressing type
+ AM_I = 0x00070000, // I addressing type
+ AM_J = 0x00080000, // J addressing type
+ AM_M = 0x00090000, // M addressing type
+ AM_O = 0x000A0000, // O addressing type
+ AM_P = 0x000B0000, // P addressing type
+ AM_Q = 0x000C0000, // Q addressing type
+ AM_R = 0x000D0000, // R addressing type
+ AM_S = 0x000E0000, // S addressing type
+ AM_T = 0x000F0000, // T addressing type
+ AM_V = 0x00100000, // V addressing type
+ AM_W = 0x00110000, // W addressing type
+ AM_X = 0x00120000, // X addressing type
+ AM_Y = 0x00130000, // Y addressing type
+ AM_REGISTER = 0x00140000, // Specific register is always used as this op
+ AM_IMPLICIT = 0x00150000, // An implicit, fixed value is used
+};
+
+// Operand types from the IA-32 manual. The enOtMask value is
+// a mask for the rest. The rest of the values are named for the
+// names given to these operand types in the manual, e.g. enOt_ps
+// is for the ps operand type in the manual.
+//
+// The reason we use a full 4 bytes and a mask, is that we need
+// to combine these flags with the enAddressingMethod to store the details
+// on the operand in a single integer.
+enum OperandType {
+ OT_MASK = 0xFF000000,
+ OT_A = 0x01000000,
+ OT_B = 0x02000000,
+ OT_C = 0x03000000,
+ OT_D = 0x04000000,
+ OT_DQ = 0x05000000,
+ OT_P = 0x06000000,
+ OT_PI = 0x07000000,
+ OT_PS = 0x08000000, // actually unsupported for (we don't know its size)
+ OT_Q = 0x09000000,
+ OT_S = 0x0A000000,
+ OT_SS = 0x0B000000,
+ OT_SI = 0x0C000000,
+ OT_V = 0x0D000000,
+ OT_W = 0x0E000000,
+ OT_SD = 0x0F000000, // scalar double-precision floating-point value
+ OT_PD = 0x10000000, // double-precision floating point
+ // dummy "operand type" for address mode M - which doesn't specify
+ // operand type
+ OT_ADDRESS_MODE_M = 0x80000000
+};
+
+// Everything that's in an Opcode (see below) except the three
+// alternative opcode structs for different prefixes.
+struct SpecificOpcode {
+ // Index to continuation table, or 0 if this is the last
+ // byte in the opcode.
+ int table_index_;
+
+ // The opcode type
+ InstructionType type_;
+
+ // Description of the type of the dest, src and aux operands,
+ // put together from an enOperandType flag and an enAddressingMethod
+ // flag.
+ int flag_dest_;
+ int flag_source_;
+ int flag_aux_;
+
+ // We indicate the mnemonic for debugging purposes
+ const char* mnemonic_;
+};
+
+// The information we keep in our tables about each of the different
+// valid instructions recognized by the IA-32 architecture.
+struct Opcode {
+ // Index to continuation table, or 0 if this is the last
+ // byte in the opcode.
+ int table_index_;
+
+ // The opcode type
+ InstructionType type_;
+
+ // Description of the type of the dest, src and aux operands,
+ // put together from an enOperandType flag and an enAddressingMethod
+ // flag.
+ int flag_dest_;
+ int flag_source_;
+ int flag_aux_;
+
+ // We indicate the mnemonic for debugging purposes
+ const char* mnemonic_;
+
+ // Alternative opcode info if certain prefixes are specified.
+ // In most cases, all of these are zeroed-out. Only used if
+ // bPrefixDependent is true.
+ bool is_prefix_dependent_;
+ SpecificOpcode opcode_if_f2_prefix_;
+ SpecificOpcode opcode_if_f3_prefix_;
+ SpecificOpcode opcode_if_66_prefix_;
+};
+
+// Information about each table entry.
+struct OpcodeTable {
+ // Table of instruction entries
+ const Opcode* table_;
+ // How many bytes left to shift ModR/M byte <b>before</b> applying mask
+ unsigned char shift_;
+ // Mask to apply to byte being looked at before comparing to table
+ unsigned char mask_;
+ // Minimum/maximum indexes in table.
+ unsigned char min_lim_;
+ unsigned char max_lim_;
+};
+
+// Information about each entry in table used to decode ModR/M byte.
+struct ModrmEntry {
+ // Is the operand encoded as bytes in the instruction (rather than
+ // if it's e.g. a register in which case it's just encoded in the
+ // ModR/M byte)
+ bool is_encoded_in_instruction_;
+
+ // Is there a SIB byte? In this case we always need to decode it.
+ bool use_sib_byte_;
+
+ // What is the size of the operand (only important if it's encoded
+ // in the instruction)?
+ OperandSize operand_size_;
+};
+
+}; // namespace sidestep
+
+#endif // TRACELINE_SIDESTEP_MINI_DISASSEMBLER_TYPES_H_
diff --git a/chromium/tools/traceline/traceline/stubs.asm b/chromium/tools/traceline/traceline/stubs.asm
new file mode 100644
index 00000000000..d556b6bba59
--- /dev/null
+++ b/chromium/tools/traceline/traceline/stubs.asm
@@ -0,0 +1,132 @@
+; Copyright (c) 2009 The Chromium Authors. All rights reserved.
+; Use of this source code is governed by a BSD-style license that can be
+; found in the LICENSE file.
+
+; This file is just a convenient place for experimenting with x86 encodings.
+
+BITS 32
+
+; sldt to detect which processor we are running on.
+sldt eax
+sidt [esp]
+sidt [esp+2]
+
+lea eax, [fs:0]
+
+mov eax, [fs:0x18]
+
+mov ebx, 0x1234567
+mov eax, 0x1234567
+
+rdtsc
+
+push eax
+pop eax
+
+mov eax, [ecx]
+mov eax, [esp+4]
+mov ebx, [esp+4]
+
+lock xadd [eax], eax
+lock xadd [ecx], ecx
+lock xadd [ecx], eax
+
+jmp eax
+jmp edx
+
+lodsd
+
+rep stosb
+
+rep movsb
+
+mov eax, ebx
+mov edx, edx
+
+mov eax, eax
+
+stosd
+
+add eax, eax
+add edi, ecx
+
+and eax, 0x0000ffff
+and ecx, 0x0000ffff
+and edx, 0x0000ffff
+
+add edi, 0x12345
+add eax, 0x12345
+add ecx, 0x12345
+
+push 0x12
+push BYTE 0x12
+
+mov eax, [ebp+8]
+
+mov eax, 0x1234
+mov [fs:0], eax
+
+call 0x1234
+
+call eax
+call ecx
+
+add ebx, BYTE 3
+or ecx, 0xffff
+or eax, 0xffff
+
+mov eax, [esp+24]
+
+movsd
+movsb
+
+jmp blah
+blah:
+jmp blah
+
+cmp eax, 0x1234567
+cmp ecx, 0x1234567
+je NEAR blah2
+jo NEAR blah2
+blah2:
+
+add esp, 12
+add esp, BYTE 12
+sub esp, BYTE 12
+
+cmp eax, 12
+cmp ecx, BYTE 12
+
+cmp WORD [esp+6], 0x6666
+
+push DWORD [edi-4]
+push DWORD [edi-8]
+push DWORD [edi-12]
+push DWORD [edi-16]
+push DWORD [edi-20]
+
+x:
+loop x
+
+mov edx, [fs:0x4]
+
+cmp ecx, ecx
+cmp ecx, ebx
+cmp ebx, ebx
+
+mov eax,[dword fs:0x24]
+mov eax,[fs:0x24]
+
+mov ecx,[dword fs:0x24]
+mov ecx,[fs:0x24]
+
+mov eax, [ebx+12]
+mov ebx, [ebx+12]
+
+cmovo eax, eax
+
+mov eax, eax
+
+xchg eax, ebx
+xchg ebx, ecx
+xchg ebx, [esp+4]
diff --git a/chromium/tools/traceline/traceline/sym_resolver.h b/chromium/tools/traceline/traceline/sym_resolver.h
new file mode 100644
index 00000000000..eb7e06c08af
--- /dev/null
+++ b/chromium/tools/traceline/traceline/sym_resolver.h
@@ -0,0 +1,167 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A smaller wrapper around the dbghelp symbol resolution routines.
+// For example:
+// SymResolver resolver("ntdll.dll");
+// resolver.Resolve("ntdll!NtBlahBlah");
+
+#ifndef TRACELINE_SYM_RESOLVER_H_
+#define TRACELINE_SYM_RESOLVER_H_
+
+#include <windows.h>
+#include <dbghelp.h>
+
+#include <vector>
+#include <string>
+#include <map>
+
+static BOOL CALLBACK SymEnumer(PCSTR name, DWORD64 base, PVOID context) {
+ reinterpret_cast<std::vector<DWORD64>*>(context)->push_back(base);
+ return TRUE;
+}
+
+class SymResolver {
+ public:
+
+ // Constructor to load a single DLL.
+ SymResolver(const char* dllname, HANDLE proc = ::GetCurrentProcess())
+ : proc_(proc) {
+
+ // TODO(deanm): Would be nice to get this from WinDBG, but it's buried
+ // in the workspace data blob... _NT_SYMBOL_PATH is not usually set...
+ static char* kSymbolPath =
+ "C:\\Program Files\\Debugging Tools for Windows (x86)\\sym;"
+ "C:\\Program Files\\Debugging Tools for Windows\\sym";
+
+ // If we want to load a specific DLL, or we want to load all.
+ if (::SymInitialize(proc_, kSymbolPath, dllname ? FALSE : TRUE) != TRUE) {
+ NOTREACHED("SymInitialize failed: %d", GetLastError());
+ }
+
+ base_ = 0;
+
+ if (dllname) {
+ base_ = ::SymLoadModuleEx(proc_,
+ NULL,
+ const_cast<char*>(dllname),
+ NULL,
+ reinterpret_cast<DWORD64>(
+ GetModuleHandleA(dllname)),
+ 0,
+ NULL,
+ 0);
+ if (base_ == 0) {
+ NOTREACHED("SymLoadModuleEx(%s) failed: %d", dllname, GetLastError());
+ }
+ }
+
+ std::vector<DWORD64> bases;
+ // The name returned from SymEnumerateModules64 doesn't include the ext,
+ // so we can't differentiate between a dll and exe of the same name. So
+ // collect all of the base addresses and query for more info.
+ // The prototype changed from PSTR to PCSTR, so in order to support older
+ // SDKs we have to cast SymEnumer.
+ PSYM_ENUMMODULES_CALLBACK64 enumer =
+ reinterpret_cast<PSYM_ENUMMODULES_CALLBACK64>(&SymEnumer);
+ if (SymEnumerateModules64(proc_, enumer, &bases) != TRUE) {
+ NOTREACHED("SymEnumerateModules64 failed: %d\n", GetLastError());
+ }
+ for (size_t i = 0; i < bases.size(); ++i) {
+ // This was failing, turns out I was just using the system32
+ // dbghelp.dll which is old, use the one from windbg :(
+ IMAGEHLP_MODULE64 info;
+ info.SizeOfStruct = sizeof(info);
+ if (SymGetModuleInfo64(proc_, bases[i], &info) != TRUE) {
+ NOTREACHED("SymGetModuleInfo64 failed: %d\n", GetLastError());
+ }
+ std::string filename(info.ImageName);
+ size_t last_slash = filename.find_last_of('\\');
+ if (last_slash != std::string::npos)
+ filename = filename.substr(filename.find_last_of('\\') + 1);
+
+ // Map the base address to the image name...
+ dlls_[static_cast<int>(bases[i])] = filename;
+ }
+
+ // TODO(deanm): check the symbols are rad and stuff...
+ }
+
+ char* Resolve(const char* name) {
+ // The API writes to the space after SYMBOL_INFO...
+ struct {
+ SYMBOL_INFO info;
+ char buf[128];
+ } info = {0};
+
+ info.info.SizeOfStruct = sizeof(info.info);
+ info.info.ModBase = base_;
+ info.info.MaxNameLen = 127;
+
+ if (SymFromName(proc_, const_cast<char*>(name), &info.info) != TRUE) {
+ NOTREACHED("SymFromName(%s) failed: %d", name, GetLastError());
+ }
+
+ return reinterpret_cast<char*>(info.info.Address);
+ }
+
+ std::string Unresolve(int ptr) {
+ // The API writes to the space after SYMBOL_INFO...
+ struct {
+ SYMBOL_INFO info;
+ char buf[128];
+ } info = {0};
+
+ info.info.SizeOfStruct = sizeof(info.info);
+ info.info.ModBase = base_;
+ info.info.MaxNameLen = 127;
+ if (!::SymFromAddr(proc_, static_cast<DWORD64>(ptr), NULL, &info.info)) {
+ return std::string("failed");
+ }
+
+ std::string name;
+ int addr = static_cast<int>(info.info.Address);
+ int base = static_cast<int>(info.info.ModBase);
+
+ if (dlls_.count(base) == 1) {
+ name.append(dlls_[base]);
+ } else {
+ name.append("unknown_mod");
+ }
+ name.push_back('!');
+ name.append(info.info.Name);
+
+ char buf[32];
+ _itoa_s(ptr - addr, buf, sizeof(buf), 16);
+ name.append("+0x");
+ name.append(buf);
+
+ DWORD disp;
+ IMAGEHLP_LINE64 line;
+ if (::SymGetLineFromAddr64(
+ proc_, static_cast<DWORD64>(ptr), &disp, &line)) {
+ name.append(" [ ");
+ name.append(line.FileName);
+ name.append(":");
+ _itoa_s(line.LineNumber, buf, sizeof(buf), 10);
+ name.append(buf);
+ name.append(" ]");
+ }
+
+ return name;
+ }
+
+ ~SymResolver() {
+ if (::SymCleanup(proc_) != TRUE) {
+ NOTREACHED("SymCleanup failed: %d", GetLastError());
+ }
+ }
+
+ private:
+ HANDLE proc_;
+ ULONG64 base_;
+ std::map<int, std::string> dlls_;
+};
+
+#endif // TRACELINE_SYM_RESOLVER_H_
diff --git a/chromium/tools/traceline/traceline/syscall_map.h b/chromium/tools/traceline/traceline/syscall_map.h
new file mode 100644
index 00000000000..515e9c7863b
--- /dev/null
+++ b/chromium/tools/traceline/traceline/syscall_map.h
@@ -0,0 +1,2116 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This table is a dump of system call numbers -> function names on an XP
+// system. These numbers change between kernel versions, so it's likely they
+// will have to be regenerated for your system. See the idarub script.
+
+// Define a global map used for resolving a syscall number to name.
+// Call CreateSyscallMap() to create a return a std::map<int, const char*>
+// which maps from a system call number to its function name.
+
+#ifndef TRACELINE_SYSCALL_MAP_H_
+#define TRACELINE_SYSCALL_MAP_H_
+
+#include <map>
+
+// TODO(deanm): Right now these tables are manually extracted and hardcoded
+// here. It would be great (but possibly difficult) to do it on startup. We
+// should at least checksum the DLLs to make sure they match.
+
+std::map<int, const char*> CreateSyscallMap() {
+ std::map<int, const char*> table;
+if (1) { // XP table.
+ table[0] = "ntdll.dll!NtAcceptConnectPort";
+ table[1] = "ntdll.dll!NtAccessCheck";
+ table[2] = "ntdll.dll!ZwAccessCheckAndAuditAlarm";
+ table[3] = "ntdll.dll!NtAccessCheckByType";
+ table[4] = "ntdll.dll!NtAccessCheckByTypeAndAuditAlarm";
+ table[5] = "ntdll.dll!NtAccessCheckByTypeResultList";
+ table[6] = "ntdll.dll!NtAccessCheckByTypeResultListAndAuditAlarm";
+ table[7] = "ntdll.dll!ZwAccessCheckByTypeResultListAndAuditAlarmByHandle";
+ table[8] = "ntdll.dll!NtAddAtom";
+ table[9] = "ntdll.dll!ZwAddBootEntry";
+ table[10] = "ntdll.dll!ZwAdjustGroupsToken";
+ table[11] = "ntdll.dll!ZwAdjustPrivilegesToken";
+ table[12] = "ntdll.dll!NtAlertResumeThread";
+ table[13] = "ntdll.dll!NtAlertThread";
+ table[14] = "ntdll.dll!ZwAllocateLocallyUniqueId";
+ table[15] = "ntdll.dll!NtAllocateUserPhysicalPages";
+ table[16] = "ntdll.dll!NtAllocateUuids";
+ table[17] = "ntdll.dll!NtAllocateVirtualMemory";
+ table[18] = "ntdll.dll!ZwAreMappedFilesTheSame";
+ table[19] = "ntdll.dll!ZwAssignProcessToJobObject";
+ table[20] = "ntdll.dll!ZwCallbackReturn";
+ table[21] = "ntdll.dll!NtCancelDeviceWakeupRequest";
+ table[22] = "ntdll.dll!ZwCancelIoFile";
+ table[23] = "ntdll.dll!ZwCancelTimer";
+ table[24] = "ntdll.dll!NtClearEvent";
+ table[25] = "ntdll.dll!NtClose";
+ table[26] = "ntdll.dll!ZwCloseObjectAuditAlarm";
+ table[27] = "ntdll.dll!NtCompactKeys";
+ table[28] = "ntdll.dll!ZwCompareTokens";
+ table[29] = "ntdll.dll!NtCompleteConnectPort";
+ table[30] = "ntdll.dll!ZwCompressKey";
+ table[31] = "ntdll.dll!NtConnectPort";
+ table[32] = "ntdll.dll!ZwContinue";
+ table[33] = "ntdll.dll!ZwCreateDebugObject";
+ table[34] = "ntdll.dll!ZwCreateDirectoryObject";
+ table[35] = "ntdll.dll!NtCreateEvent";
+ table[36] = "ntdll.dll!NtCreateEventPair";
+ table[37] = "ntdll.dll!NtCreateFile";
+ table[38] = "ntdll.dll!NtCreateIoCompletion";
+ table[39] = "ntdll.dll!ZwCreateJobObject";
+ table[40] = "ntdll.dll!NtCreateJobSet";
+ table[41] = "ntdll.dll!ZwCreateKey";
+ table[42] = "ntdll.dll!ZwCreateMailslotFile";
+ table[43] = "ntdll.dll!ZwCreateMutant";
+ table[44] = "ntdll.dll!ZwCreateNamedPipeFile";
+ table[45] = "ntdll.dll!NtCreatePagingFile";
+ table[46] = "ntdll.dll!ZwCreatePort";
+ table[47] = "ntdll.dll!ZwCreateProcess";
+ table[48] = "ntdll.dll!ZwCreateProcessEx";
+ table[49] = "ntdll.dll!ZwCreateProfile";
+ table[50] = "ntdll.dll!NtCreateSection";
+ table[51] = "ntdll.dll!NtCreateSemaphore";
+ table[52] = "ntdll.dll!ZwCreateSymbolicLinkObject";
+ table[53] = "ntdll.dll!NtCreateThread";
+ table[54] = "ntdll.dll!ZwCreateTimer";
+ table[55] = "ntdll.dll!NtCreateToken";
+ table[56] = "ntdll.dll!ZwCreateWaitablePort";
+ table[57] = "ntdll.dll!NtDebugActiveProcess";
+ table[58] = "ntdll.dll!ZwDebugContinue";
+ table[59] = "ntdll.dll!ZwDelayExecution";
+ table[60] = "ntdll.dll!ZwDeleteAtom";
+ table[61] = "ntdll.dll!NtDeleteBootEntry";
+ table[62] = "ntdll.dll!NtDeleteFile";
+ table[63] = "ntdll.dll!ZwDeleteKey";
+ table[64] = "ntdll.dll!NtDeleteObjectAuditAlarm";
+ table[65] = "ntdll.dll!NtDeleteValueKey";
+ table[66] = "ntdll.dll!ZwDeviceIoControlFile";
+ table[67] = "ntdll.dll!NtDisplayString";
+ table[68] = "ntdll.dll!ZwDuplicateObject";
+ table[69] = "ntdll.dll!NtDuplicateToken";
+ table[70] = "ntdll.dll!ZwEnumerateBootEntries";
+ table[71] = "ntdll.dll!ZwEnumerateKey";
+ table[72] = "ntdll.dll!ZwEnumerateSystemEnvironmentValuesEx";
+ table[73] = "ntdll.dll!NtEnumerateValueKey";
+ table[74] = "ntdll.dll!ZwExtendSection";
+ table[75] = "ntdll.dll!NtFilterToken";
+ table[76] = "ntdll.dll!NtFindAtom";
+ table[77] = "ntdll.dll!ZwFlushBuffersFile";
+ table[78] = "ntdll.dll!ZwFlushInstructionCache";
+ table[79] = "ntdll.dll!NtFlushKey";
+ table[80] = "ntdll.dll!ZwFlushVirtualMemory";
+ table[81] = "ntdll.dll!NtFlushWriteBuffer";
+ table[82] = "ntdll.dll!NtFreeUserPhysicalPages";
+ table[83] = "ntdll.dll!NtFreeVirtualMemory";
+ table[84] = "ntdll.dll!NtFsControlFile";
+ table[85] = "ntdll.dll!NtGetContextThread";
+ table[86] = "ntdll.dll!NtGetDevicePowerState";
+ table[87] = "ntdll.dll!ZwGetPlugPlayEvent";
+ table[88] = "ntdll.dll!NtGetWriteWatch";
+ table[89] = "ntdll.dll!NtImpersonateAnonymousToken";
+ table[90] = "ntdll.dll!ZwImpersonateClientOfPort";
+ table[91] = "ntdll.dll!ZwImpersonateThread";
+ table[92] = "ntdll.dll!ZwInitializeRegistry";
+ table[93] = "ntdll.dll!NtInitiatePowerAction";
+ table[94] = "ntdll.dll!ZwIsProcessInJob";
+ table[95] = "ntdll.dll!NtIsSystemResumeAutomatic";
+ table[96] = "ntdll.dll!ZwListenPort";
+ table[97] = "ntdll.dll!NtLoadDriver";
+ table[98] = "ntdll.dll!NtLoadKey";
+ table[99] = "ntdll.dll!NtLoadKey2";
+ table[100] = "ntdll.dll!NtLockFile";
+ table[101] = "ntdll.dll!ZwLockProductActivationKeys";
+ table[102] = "ntdll.dll!NtLockRegistryKey";
+ table[103] = "ntdll.dll!ZwLockVirtualMemory";
+ table[104] = "ntdll.dll!ZwMakePermanentObject";
+ table[105] = "ntdll.dll!NtMakeTemporaryObject";
+ table[106] = "ntdll.dll!NtMapUserPhysicalPages";
+ table[107] = "ntdll.dll!ZwMapUserPhysicalPagesScatter";
+ table[108] = "ntdll.dll!ZwMapViewOfSection";
+ table[109] = "ntdll.dll!NtModifyBootEntry";
+ table[110] = "ntdll.dll!NtNotifyChangeDirectoryFile";
+ table[111] = "ntdll.dll!NtNotifyChangeKey";
+ table[112] = "ntdll.dll!NtNotifyChangeMultipleKeys";
+ table[113] = "ntdll.dll!ZwOpenDirectoryObject";
+ table[114] = "ntdll.dll!NtOpenEvent";
+ table[115] = "ntdll.dll!NtOpenEventPair";
+ table[116] = "ntdll.dll!NtOpenFile";
+ table[117] = "ntdll.dll!ZwOpenIoCompletion";
+ table[118] = "ntdll.dll!ZwOpenJobObject";
+ table[119] = "ntdll.dll!ZwOpenKey";
+ table[120] = "ntdll.dll!NtOpenMutant";
+ table[121] = "ntdll.dll!ZwOpenObjectAuditAlarm";
+ table[122] = "ntdll.dll!ZwOpenProcess";
+ table[123] = "ntdll.dll!ZwOpenProcessToken";
+ table[124] = "ntdll.dll!ZwOpenProcessTokenEx";
+ table[125] = "ntdll.dll!NtOpenSection";
+ table[126] = "ntdll.dll!NtOpenSemaphore";
+ table[127] = "ntdll.dll!NtOpenSymbolicLinkObject";
+ table[128] = "ntdll.dll!ZwOpenThread";
+ table[129] = "ntdll.dll!NtOpenThreadToken";
+ table[130] = "ntdll.dll!NtOpenThreadTokenEx";
+ table[131] = "ntdll.dll!ZwOpenTimer";
+ table[132] = "ntdll.dll!NtPlugPlayControl";
+ table[133] = "ntdll.dll!ZwPowerInformation";
+ table[134] = "ntdll.dll!ZwPrivilegeCheck";
+ table[135] = "ntdll.dll!ZwPrivilegeObjectAuditAlarm";
+ table[136] = "ntdll.dll!NtPrivilegedServiceAuditAlarm";
+ table[137] = "ntdll.dll!ZwProtectVirtualMemory";
+ table[138] = "ntdll.dll!ZwPulseEvent";
+ table[139] = "ntdll.dll!ZwQueryAttributesFile";
+ table[140] = "ntdll.dll!ZwQueryBootEntryOrder";
+ table[141] = "ntdll.dll!ZwQueryBootOptions";
+ table[142] = "ntdll.dll!NtQueryDebugFilterState";
+ table[143] = "ntdll.dll!NtQueryDefaultLocale";
+ table[144] = "ntdll.dll!ZwQueryDefaultUILanguage";
+ table[145] = "ntdll.dll!ZwQueryDirectoryFile";
+ table[146] = "ntdll.dll!ZwQueryDirectoryObject";
+ table[147] = "ntdll.dll!ZwQueryEaFile";
+ table[148] = "ntdll.dll!NtQueryEvent";
+ table[149] = "ntdll.dll!ZwQueryFullAttributesFile";
+ table[150] = "ntdll.dll!NtQueryInformationAtom";
+ table[151] = "ntdll.dll!ZwQueryInformationFile";
+ table[152] = "ntdll.dll!ZwQueryInformationJobObject";
+ table[153] = "ntdll.dll!ZwQueryInformationPort";
+ table[154] = "ntdll.dll!ZwQueryInformationProcess";
+ table[155] = "ntdll.dll!NtQueryInformationThread";
+ table[156] = "ntdll.dll!ZwQueryInformationToken";
+ table[157] = "ntdll.dll!NtQueryInstallUILanguage";
+ table[158] = "ntdll.dll!NtQueryIntervalProfile";
+ table[159] = "ntdll.dll!NtQueryIoCompletion";
+ table[160] = "ntdll.dll!ZwQueryKey";
+ table[161] = "ntdll.dll!NtQueryMultipleValueKey";
+ table[162] = "ntdll.dll!NtQueryMutant";
+ table[163] = "ntdll.dll!NtQueryObject";
+ table[164] = "ntdll.dll!NtQueryOpenSubKeys";
+ table[165] = "ntdll.dll!NtQueryPerformanceCounter";
+ table[166] = "ntdll.dll!ZwQueryQuotaInformationFile";
+ table[167] = "ntdll.dll!ZwQuerySection";
+ table[168] = "ntdll.dll!NtQuerySecurityObject";
+ table[169] = "ntdll.dll!ZwQuerySemaphore";
+ table[170] = "ntdll.dll!ZwQuerySymbolicLinkObject";
+ table[171] = "ntdll.dll!ZwQuerySystemEnvironmentValue";
+ table[172] = "ntdll.dll!ZwQuerySystemEnvironmentValueEx";
+ table[173] = "ntdll.dll!NtQuerySystemInformation";
+ table[174] = "ntdll.dll!NtQuerySystemTime";
+ table[175] = "ntdll.dll!ZwQueryTimer";
+ table[176] = "ntdll.dll!NtQueryTimerResolution";
+ table[177] = "ntdll.dll!ZwQueryValueKey";
+ table[178] = "ntdll.dll!NtQueryVirtualMemory";
+ table[179] = "ntdll.dll!NtQueryVolumeInformationFile";
+ table[180] = "ntdll.dll!NtQueueApcThread";
+ table[181] = "ntdll.dll!ZwRaiseException";
+ table[182] = "ntdll.dll!ZwRaiseHardError";
+ table[183] = "ntdll.dll!NtReadFile";
+ table[184] = "ntdll.dll!NtReadFileScatter";
+ table[185] = "ntdll.dll!ZwReadRequestData";
+ table[186] = "ntdll.dll!NtReadVirtualMemory";
+ table[187] = "ntdll.dll!ZwRegisterThreadTerminatePort";
+ table[188] = "ntdll.dll!ZwReleaseMutant";
+ table[189] = "ntdll.dll!NtReleaseSemaphore";
+ table[190] = "ntdll.dll!ZwRemoveIoCompletion";
+ table[191] = "ntdll.dll!ZwRemoveProcessDebug";
+ table[192] = "ntdll.dll!ZwRenameKey";
+ table[193] = "ntdll.dll!ZwReplaceKey";
+ table[194] = "ntdll.dll!ZwReplyPort";
+ table[195] = "ntdll.dll!NtReplyWaitReceivePort";
+ table[196] = "ntdll.dll!NtReplyWaitReceivePortEx";
+ table[197] = "ntdll.dll!NtReplyWaitReplyPort";
+ table[198] = "ntdll.dll!ZwRequestDeviceWakeup";
+ table[199] = "ntdll.dll!ZwRequestPort";
+ table[200] = "ntdll.dll!NtRequestWaitReplyPort";
+ table[201] = "ntdll.dll!ZwRequestWakeupLatency";
+ table[202] = "ntdll.dll!NtResetEvent";
+ table[203] = "ntdll.dll!ZwResetWriteWatch";
+ table[204] = "ntdll.dll!NtRestoreKey";
+ table[205] = "ntdll.dll!ZwResumeProcess";
+ table[206] = "ntdll.dll!ZwResumeThread";
+ table[207] = "ntdll.dll!NtSaveKey";
+ table[208] = "ntdll.dll!NtSaveKeyEx";
+ table[209] = "ntdll.dll!NtSaveMergedKeys";
+ table[210] = "ntdll.dll!NtSecureConnectPort";
+ table[211] = "ntdll.dll!ZwSetBootEntryOrder";
+ table[212] = "ntdll.dll!ZwSetBootOptions";
+ table[213] = "ntdll.dll!ZwSetContextThread";
+ table[214] = "ntdll.dll!NtSetDebugFilterState";
+ table[215] = "ntdll.dll!NtSetDefaultHardErrorPort";
+ table[216] = "ntdll.dll!NtSetDefaultLocale";
+ table[217] = "ntdll.dll!ZwSetDefaultUILanguage";
+ table[218] = "ntdll.dll!ZwSetEaFile";
+ table[219] = "ntdll.dll!NtSetEvent";
+ table[220] = "ntdll.dll!NtSetEventBoostPriority";
+ table[221] = "ntdll.dll!NtSetHighEventPair";
+ table[222] = "ntdll.dll!NtSetHighWaitLowEventPair";
+ table[223] = "ntdll.dll!ZwSetInformationDebugObject";
+ table[224] = "ntdll.dll!ZwSetInformationFile";
+ table[225] = "ntdll.dll!ZwSetInformationJobObject";
+ table[226] = "ntdll.dll!ZwSetInformationKey";
+ table[227] = "ntdll.dll!ZwSetInformationObject";
+ table[228] = "ntdll.dll!ZwSetInformationProcess";
+ table[229] = "ntdll.dll!ZwSetInformationThread";
+ table[230] = "ntdll.dll!ZwSetInformationToken";
+ table[231] = "ntdll.dll!NtSetIntervalProfile";
+ table[232] = "ntdll.dll!NtSetIoCompletion";
+ table[233] = "ntdll.dll!ZwSetLdtEntries";
+ table[234] = "ntdll.dll!ZwSetLowEventPair";
+ table[235] = "ntdll.dll!ZwSetLowWaitHighEventPair";
+ table[236] = "ntdll.dll!ZwSetQuotaInformationFile";
+ table[237] = "ntdll.dll!NtSetSecurityObject";
+ table[238] = "ntdll.dll!ZwSetSystemEnvironmentValue";
+ table[239] = "ntdll.dll!ZwSetSystemEnvironmentValueEx";
+ table[240] = "ntdll.dll!ZwSetSystemInformation";
+ table[241] = "ntdll.dll!ZwSetSystemPowerState";
+ table[242] = "ntdll.dll!ZwSetSystemTime";
+ table[243] = "ntdll.dll!ZwSetThreadExecutionState";
+ table[244] = "ntdll.dll!ZwSetTimer";
+ table[245] = "ntdll.dll!NtSetTimerResolution";
+ table[246] = "ntdll.dll!ZwSetUuidSeed";
+ table[247] = "ntdll.dll!ZwSetValueKey";
+ table[248] = "ntdll.dll!NtSetVolumeInformationFile";
+ table[249] = "ntdll.dll!ZwShutdownSystem";
+ table[250] = "ntdll.dll!ZwSignalAndWaitForSingleObject";
+ table[251] = "ntdll.dll!NtStartProfile";
+ table[252] = "ntdll.dll!ZwStopProfile";
+ table[253] = "ntdll.dll!ZwSuspendProcess";
+ table[254] = "ntdll.dll!ZwSuspendThread";
+ table[255] = "ntdll.dll!NtSystemDebugControl";
+ table[256] = "ntdll.dll!ZwTerminateJobObject";
+ table[257] = "ntdll.dll!ZwTerminateProcess";
+ table[258] = "ntdll.dll!ZwTerminateThread";
+ table[259] = "ntdll.dll!NtTestAlert";
+ table[260] = "ntdll.dll!NtTraceEvent";
+ table[261] = "ntdll.dll!NtTranslateFilePath";
+ table[262] = "ntdll.dll!ZwUnloadDriver";
+ table[263] = "ntdll.dll!NtUnloadKey";
+ table[264] = "ntdll.dll!ZwUnloadKeyEx";
+ table[265] = "ntdll.dll!ZwUnlockFile";
+ table[266] = "ntdll.dll!NtUnlockVirtualMemory";
+ table[267] = "ntdll.dll!NtUnmapViewOfSection";
+ table[268] = "ntdll.dll!NtVdmControl";
+ table[269] = "ntdll.dll!NtWaitForDebugEvent";
+ table[270] = "ntdll.dll!NtWaitForMultipleObjects";
+ table[271] = "ntdll.dll!ZwWaitForSingleObject";
+ table[272] = "ntdll.dll!ZwWaitHighEventPair";
+ table[273] = "ntdll.dll!NtWaitLowEventPair";
+ table[274] = "ntdll.dll!NtWriteFile";
+ table[275] = "ntdll.dll!NtWriteFileGather";
+ table[276] = "ntdll.dll!NtWriteRequestData";
+ table[277] = "ntdll.dll!NtWriteVirtualMemory";
+ table[278] = "ntdll.dll!ZwYieldExecution";
+ table[279] = "ntdll.dll!ZwCreateKeyedEvent";
+ table[280] = "ntdll.dll!NtOpenKeyedEvent";
+ table[281] = "ntdll.dll!NtReleaseKeyedEvent";
+ table[282] = "ntdll.dll!NtWaitForKeyedEvent";
+ table[283] = "ntdll.dll!ZwQueryPortInformationProcess";
+ table[4096] = "gdi32.dll!NtGdiAbortDoc";
+ table[4097] = "gdi32.dll!NtGdiAbortPath";
+ table[4098] = "gdi32.dll!NtGdiAddFontResourceW";
+ table[4099] = "gdi32.dll!NtGdiAddRemoteFontToDC";
+ table[4100] = "gdi32.dll!NtGdiAddFontMemResourceEx";
+ table[4101] = "gdi32.dll!NtGdiRemoveMergeFont";
+ table[4102] = "gdi32.dll!NtGdiAddRemoteMMInstanceToDC";
+ table[4103] = "gdi32.dll!NtGdiAlphaBlend";
+ table[4104] = "gdi32.dll!NtGdiAngleArc";
+ table[4105] = "gdi32.dll!NtGdiAnyLinkedFonts";
+ table[4106] = "gdi32.dll!NtGdiFontIsLinked";
+ table[4107] = "gdi32.dll!NtGdiArcInternal";
+ table[4108] = "gdi32.dll!NtGdiBeginPath";
+ table[4109] = "gdi32.dll!NtGdiBitBlt";
+ table[4110] = "gdi32.dll!NtGdiCancelDC";
+ table[4111] = "gdi32.dll!NtGdiCheckBitmapBits";
+ table[4112] = "gdi32.dll!NtGdiCloseFigure";
+ table[4113] = "gdi32.dll!NtGdiClearBitmapAttributes";
+ table[4114] = "gdi32.dll!NtGdiClearBrushAttributes";
+ table[4115] = "gdi32.dll!NtGdiColorCorrectPalette";
+ table[4116] = "gdi32.dll!NtGdiCombineRgn";
+ table[4117] = "gdi32.dll!CombineTransform";
+ table[4118] = "gdi32.dll!NtGdiComputeXformCoefficients";
+ table[4119] = "gdi32.dll!NtGdiConsoleTextOut";
+ table[4120] = "gdi32.dll!NtGdiConvertMetafileRect";
+ table[4121] = "gdi32.dll!NtGdiCreateBitmap";
+ table[4122] = "gdi32.dll!NtGdiCreateClientObj";
+ table[4123] = "gdi32.dll!NtGdiCreateColorSpace";
+ table[4124] = "gdi32.dll!NtGdiCreateColorTransform";
+ table[4125] = "gdi32.dll!NtGdiCreateCompatibleBitmap";
+ table[4126] = "gdi32.dll!NtGdiCreateCompatibleDC";
+ table[4127] = "gdi32.dll!NtGdiCreateDIBBrush";
+ table[4128] = "gdi32.dll!NtGdiCreateDIBitmapInternal";
+ table[4129] = "gdi32.dll!NtGdiCreateDIBSection";
+ table[4130] = "gdi32.dll!NtGdiCreateEllipticRgn";
+ table[4131] = "gdi32.dll!NtGdiCreateHalftonePalette";
+ table[4132] = "gdi32.dll!NtGdiCreateHatchBrushInternal";
+ table[4133] = "gdi32.dll!NtGdiCreateMetafileDC";
+ table[4134] = "gdi32.dll!NtGdiCreatePaletteInternal";
+ table[4135] = "gdi32.dll!NtGdiCreatePatternBrushInternal";
+ table[4136] = "gdi32.dll!CreatePen";
+ table[4137] = "gdi32.dll!NtGdiCreateRectRgn";
+ table[4138] = "gdi32.dll!CreateRoundRectRgn";
+ table[4139] = "gdi32.dll!NtGdiCreateServerMetaFile";
+ table[4140] = "gdi32.dll!NtGdiCreateSolidBrush";
+ table[4141] = "gdi32.dll!NtGdiD3dContextCreate";
+ table[4142] = "gdi32.dll!NtGdiD3dContextDestroy";
+ table[4143] = "gdi32.dll!NtGdiD3dContextDestroyAll";
+ table[4144] = "gdi32.dll!NtGdiD3dValidateTextureStageState";
+ table[4145] = "gdi32.dll!NtGdiD3dDrawPrimitives2";
+ table[4146] = "gdi32.dll!NtGdiDdGetDriverState";
+ table[4147] = "gdi32.dll!NtGdiDdAddAttachedSurface";
+ table[4148] = "gdi32.dll!NtGdiDdAlphaBlt";
+ table[4149] = "gdi32.dll!NtGdiDdAttachSurface";
+ table[4150] = "gdi32.dll!NtGdiDdBeginMoCompFrame";
+ table[4151] = "gdi32.dll!NtGdiDdBlt";
+ table[4152] = "gdi32.dll!NtGdiDdCanCreateSurface";
+ table[4153] = "gdi32.dll!NtGdiDdCanCreateD3DBuffer";
+ table[4154] = "gdi32.dll!NtGdiDdColorControl";
+ table[4155] = "gdi32.dll!NtGdiDdCreateDirectDrawObject";
+ table[4156] = "gdi32.dll!NtGdiDdCreateSurface";
+ table[4157] = "gdi32.dll!NtGdiDdCreateD3DBuffer";
+ table[4158] = "gdi32.dll!NtGdiDdCreateMoComp";
+ table[4159] = "gdi32.dll!NtGdiDdCreateSurfaceObject";
+ table[4160] = "gdi32.dll!NtGdiDdDeleteDirectDrawObject";
+ table[4161] = "gdi32.dll!NtGdiDdDeleteSurfaceObject";
+ table[4162] = "gdi32.dll!NtGdiDdDestroyMoComp";
+ table[4163] = "gdi32.dll!NtGdiDdDestroySurface";
+ table[4164] = "gdi32.dll!NtGdiDdDestroyD3DBuffer";
+ table[4165] = "gdi32.dll!NtGdiDdEndMoCompFrame";
+ table[4166] = "gdi32.dll!NtGdiDdFlip";
+ table[4167] = "gdi32.dll!NtGdiDdFlipToGDISurface";
+ table[4168] = "gdi32.dll!NtGdiDdGetAvailDriverMemory";
+ table[4169] = "gdi32.dll!NtGdiDdGetBltStatus";
+ table[4170] = "gdi32.dll!NtGdiDdGetDC";
+ table[4171] = "gdi32.dll!NtGdiDdGetDriverInfo";
+ table[4172] = "gdi32.dll!NtGdiDdGetDxHandle";
+ table[4173] = "gdi32.dll!NtGdiDdGetFlipStatus";
+ table[4174] = "gdi32.dll!NtGdiDdGetInternalMoCompInfo";
+ table[4175] = "gdi32.dll!NtGdiDdGetMoCompBuffInfo";
+ table[4176] = "gdi32.dll!NtGdiDdGetMoCompGuids";
+ table[4177] = "gdi32.dll!NtGdiDdGetMoCompFormats";
+ table[4178] = "gdi32.dll!NtGdiDdGetScanLine";
+ table[4179] = "gdi32.dll!NtGdiDdLock";
+ table[4180] = "gdi32.dll!NtGdiDdLockD3D";
+ table[4181] = "gdi32.dll!NtGdiDdQueryDirectDrawObject";
+ table[4182] = "gdi32.dll!NtGdiDdQueryMoCompStatus";
+ table[4183] = "gdi32.dll!NtGdiDdReenableDirectDrawObject";
+ table[4184] = "gdi32.dll!NtGdiDdReleaseDC";
+ table[4185] = "gdi32.dll!NtGdiDdRenderMoComp";
+ table[4186] = "gdi32.dll!NtGdiDdResetVisrgn";
+ table[4187] = "gdi32.dll!NtGdiDdSetColorKey";
+ table[4188] = "gdi32.dll!NtGdiDdSetExclusiveMode";
+ table[4189] = "gdi32.dll!NtGdiDdSetGammaRamp";
+ table[4190] = "gdi32.dll!NtGdiDdCreateSurfaceEx";
+ table[4191] = "gdi32.dll!NtGdiDdSetOverlayPosition";
+ table[4192] = "gdi32.dll!NtGdiDdUnattachSurface";
+ table[4193] = "gdi32.dll!NtGdiDdUnlock";
+ table[4194] = "gdi32.dll!NtGdiDdUnlockD3D";
+ table[4195] = "gdi32.dll!NtGdiDdUpdateOverlay";
+ table[4196] = "gdi32.dll!NtGdiDdWaitForVerticalBlank";
+ table[4197] = "gdi32.dll!NtGdiDvpCanCreateVideoPort";
+ table[4198] = "gdi32.dll!NtGdiDvpColorControl";
+ table[4199] = "gdi32.dll!NtGdiDvpCreateVideoPort";
+ table[4200] = "gdi32.dll!NtGdiDvpDestroyVideoPort";
+ table[4201] = "gdi32.dll!NtGdiDvpFlipVideoPort";
+ table[4202] = "gdi32.dll!NtGdiDvpGetVideoPortBandwidth";
+ table[4203] = "gdi32.dll!NtGdiDvpGetVideoPortField";
+ table[4204] = "gdi32.dll!NtGdiDvpGetVideoPortFlipStatus";
+ table[4205] = "gdi32.dll!NtGdiDvpGetVideoPortInputFormats";
+ table[4206] = "gdi32.dll!NtGdiDvpGetVideoPortLine";
+ table[4207] = "gdi32.dll!NtGdiDvpGetVideoPortOutputFormats";
+ table[4208] = "gdi32.dll!NtGdiDvpGetVideoPortConnectInfo";
+ table[4209] = "gdi32.dll!NtGdiDvpGetVideoSignalStatus";
+ table[4210] = "gdi32.dll!NtGdiDvpUpdateVideoPort";
+ table[4211] = "gdi32.dll!NtGdiDvpWaitForVideoPortSync";
+ table[4212] = "gdi32.dll!NtGdiDvpAcquireNotification";
+ table[4213] = "gdi32.dll!NtGdiDvpReleaseNotification";
+ table[4214] = "gdi32.dll!NtGdiDxgGenericThunk";
+ table[4215] = "gdi32.dll!NtGdiDeleteClientObj";
+ table[4216] = "gdi32.dll!NtGdiDeleteColorSpace";
+ table[4217] = "gdi32.dll!NtGdiDeleteColorTransform";
+ table[4218] = "gdi32.dll!DeleteObject";
+ table[4219] = "gdi32.dll!NtGdiDescribePixelFormat";
+ table[4220] = "gdi32.dll!NtGdiGetPerBandInfo";
+ table[4221] = "gdi32.dll!NtGdiDoBanding";
+ table[4222] = "gdi32.dll!NtGdiDoPalette";
+ table[4223] = "gdi32.dll!NtGdiDrawEscape";
+ table[4224] = "gdi32.dll!NtGdiEllipse";
+ table[4225] = "gdi32.dll!NtGdiEnableEudc";
+ table[4226] = "gdi32.dll!NtGdiEndDoc";
+ table[4227] = "gdi32.dll!NtGdiEndPage";
+ table[4228] = "gdi32.dll!NtGdiEndPath";
+ table[4229] = "gdi32.dll!NtGdiEnumFontChunk";
+ table[4230] = "gdi32.dll!NtGdiEnumFontClose";
+ table[4231] = "gdi32.dll!NtGdiEnumFontOpen";
+ table[4232] = "gdi32.dll!NtGdiEnumObjects";
+ table[4233] = "gdi32.dll!NtGdiEqualRgn";
+ table[4234] = "gdi32.dll!NtGdiEudcLoadUnloadLink";
+ table[4235] = "gdi32.dll!NtGdiExcludeClipRect";
+ table[4236] = "gdi32.dll!NtGdiExtCreatePen";
+ table[4237] = "gdi32.dll!NtGdiExtCreateRegion";
+ table[4238] = "gdi32.dll!NtGdiExtEscape";
+ table[4239] = "gdi32.dll!NtGdiExtFloodFill";
+ table[4240] = "gdi32.dll!NtGdiExtGetObjectW";
+ table[4241] = "gdi32.dll!ExtSelectClipRgn";
+ table[4242] = "gdi32.dll!NtGdiExtTextOutW";
+ table[4243] = "gdi32.dll!NtGdiFillPath";
+ table[4244] = "gdi32.dll!NtGdiFillRgn";
+ table[4245] = "gdi32.dll!NtGdiFlattenPath";
+ table[4247] = "gdi32.dll!NtGdiFlush";
+ table[4248] = "gdi32.dll!NtGdiForceUFIMapping";
+ table[4249] = "gdi32.dll!NtGdiFrameRgn";
+ table[4250] = "gdi32.dll!NtGdiFullscreenControl";
+ table[4251] = "gdi32.dll!NtGdiGetAndSetDCDword";
+ table[4252] = "gdi32.dll!GetClipBox";
+ table[4253] = "gdi32.dll!GetBitmapBits";
+ table[4254] = "gdi32.dll!NtGdiGetBitmapDimension";
+ table[4255] = "gdi32.dll!NtGdiGetBoundsRect";
+ table[4256] = "gdi32.dll!NtGdiGetCharABCWidthsW";
+ table[4257] = "gdi32.dll!NtGdiGetCharacterPlacementW";
+ table[4258] = "gdi32.dll!NtGdiGetCharSet";
+ table[4259] = "gdi32.dll!NtGdiGetCharWidthW";
+ table[4260] = "gdi32.dll!NtGdiGetCharWidthInfo";
+ table[4261] = "gdi32.dll!NtGdiGetColorAdjustment";
+ table[4263] = "gdi32.dll!NtGdiGetDCDword";
+ table[4264] = "gdi32.dll!NtGdiGetDCforBitmap";
+ table[4265] = "gdi32.dll!NtGdiGetDCObject";
+ table[4266] = "gdi32.dll!NtGdiGetDCPoint";
+ table[4267] = "gdi32.dll!NtGdiGetDeviceCaps";
+ table[4268] = "gdi32.dll!NtGdiGetDeviceGammaRamp";
+ table[4269] = "gdi32.dll!NtGdiGetDeviceCapsAll";
+ table[4270] = "gdi32.dll!NtGdiGetDIBitsInternal";
+ table[4271] = "gdi32.dll!NtGdiGetETM";
+ table[4272] = "gdi32.dll!NtGdiGetEudcTimeStampEx";
+ table[4273] = "gdi32.dll!GetFontData";
+ table[4274] = "gdi32.dll!NtGdiGetFontResourceInfoInternalW";
+ table[4275] = "gdi32.dll!NtGdiGetGlyphIndicesW";
+ table[4276] = "gdi32.dll!NtGdiGetGlyphIndicesWInternal";
+ table[4277] = "gdi32.dll!NtGdiGetGlyphOutline";
+ table[4278] = "gdi32.dll!NtGdiGetKerningPairs";
+ table[4279] = "gdi32.dll!NtGdiGetLinkedUFIs";
+ table[4280] = "gdi32.dll!GetMiterLimit";
+ table[4281] = "gdi32.dll!NtGdiGetMonitorID";
+ table[4282] = "gdi32.dll!GetNearestColor";
+ table[4283] = "gdi32.dll!NtGdiGetNearestPaletteIndex";
+ table[4284] = "gdi32.dll!NtGdiGetObjectBitmapHandle";
+ table[4285] = "gdi32.dll!NtGdiGetOutlineTextMetricsInternalW";
+ table[4286] = "gdi32.dll!NtGdiGetPath";
+ table[4287] = "gdi32.dll!NtGdiGetPixel";
+ table[4288] = "gdi32.dll!NtGdiGetRandomRgn";
+ table[4289] = "gdi32.dll!GetRasterizerCaps";
+ table[4290] = "gdi32.dll!NtGdiGetRealizationInfo";
+ table[4291] = "gdi32.dll!GetRegionData";
+ table[4292] = "gdi32.dll!NtGdiGetRgnBox";
+ table[4293] = "gdi32.dll!NtGdiGetServerMetaFileBits";
+ table[4294] = "gdi32.dll!NtGdiGetSpoolMessage";
+ table[4296] = "gdi32.dll!NtGdiGetStockObject";
+ table[4297] = "gdi32.dll!NtGdiGetStringBitmapW";
+ table[4298] = "gdi32.dll!GetSystemPaletteUse";
+ table[4299] = "gdi32.dll!NtGdiGetTextCharsetInfo";
+ table[4300] = "gdi32.dll!NtGdiGetTextExtent";
+ table[4301] = "gdi32.dll!NtGdiGetTextExtentExW";
+ table[4302] = "gdi32.dll!NtGdiGetTextFaceW";
+ table[4303] = "gdi32.dll!NtGdiGetTextMetricsW";
+ table[4304] = "gdi32.dll!NtGdiGetTransform";
+ table[4305] = "gdi32.dll!NtGdiGetUFI";
+ table[4306] = "gdi32.dll!NtGdiGetEmbUFI";
+ table[4307] = "gdi32.dll!NtGdiGetUFIPathname";
+ table[4308] = "gdi32.dll!NtGdiGetEmbedFonts";
+ table[4309] = "gdi32.dll!NtGdiChangeGhostFont";
+ table[4310] = "gdi32.dll!NtGdiAddEmbFontToDC";
+ table[4311] = "gdi32.dll!NtGdiGetFontUnicodeRanges";
+ table[4312] = "gdi32.dll!NtGdiGetWidthTable";
+ table[4313] = "gdi32.dll!NtGdiGradientFill";
+ table[4314] = "gdi32.dll!NtGdiHfontCreate";
+ table[4315] = "gdi32.dll!NtGdiIcmBrushInfo";
+ table[4316] = "gdi32.dll!NtGdiInit";
+ table[4317] = "gdi32.dll!NtGdiInitSpool";
+ table[4318] = "gdi32.dll!NtGdiIntersectClipRect";
+ table[4319] = "gdi32.dll!NtGdiInvertRgn";
+ table[4320] = "gdi32.dll!NtGdiLineTo";
+ table[4321] = "gdi32.dll!NtGdiMakeFontDir";
+ table[4322] = "gdi32.dll!NtGdiMakeInfoDC";
+ table[4323] = "gdi32.dll!NtGdiMaskBlt";
+ table[4324] = "gdi32.dll!NtGdiModifyWorldTransform";
+ table[4325] = "gdi32.dll!NtGdiMonoBitmap";
+ table[4327] = "gdi32.dll!NtGdiOffsetClipRgn";
+ table[4328] = "gdi32.dll!NtGdiOffsetRgn";
+ table[4329] = "gdi32.dll!NtGdiOpenDCW";
+ table[4330] = "gdi32.dll!NtGdiPatBlt";
+ table[4331] = "gdi32.dll!NtGdiPolyPatBlt";
+ table[4332] = "gdi32.dll!NtGdiPathToRegion";
+ table[4333] = "gdi32.dll!NtGdiPlgBlt";
+ table[4334] = "gdi32.dll!NtGdiPolyDraw";
+ table[4335] = "gdi32.dll!NtGdiPolyPolyDraw";
+ table[4336] = "gdi32.dll!NtGdiPolyTextOutW";
+ table[4337] = "gdi32.dll!NtGdiPtInRegion";
+ table[4338] = "gdi32.dll!NtGdiPtVisible";
+ table[4339] = "gdi32.dll!NtGdiQueryFonts";
+ table[4340] = "gdi32.dll!NtGdiQueryFontAssocInfo";
+ table[4341] = "gdi32.dll!NtGdiRectangle";
+ table[4342] = "gdi32.dll!NtGdiRectInRegion";
+ table[4343] = "gdi32.dll!RectVisible";
+ table[4344] = "gdi32.dll!NtGdiRemoveFontResourceW";
+ table[4345] = "gdi32.dll!NtGdiRemoveFontMemResourceEx";
+ table[4346] = "gdi32.dll!NtGdiResetDC";
+ table[4347] = "gdi32.dll!NtGdiResizePalette";
+ table[4348] = "gdi32.dll!NtGdiRestoreDC";
+ table[4349] = "gdi32.dll!NtGdiRoundRect";
+ table[4350] = "gdi32.dll!NtGdiSaveDC";
+ table[4351] = "gdi32.dll!NtGdiScaleViewportExtEx";
+ table[4352] = "gdi32.dll!NtGdiScaleWindowExtEx";
+ table[4353] = "gdi32.dll!NtGdiSelectBitmap";
+ table[4355] = "gdi32.dll!NtGdiSelectClipPath";
+ table[4356] = "gdi32.dll!NtGdiSelectFont";
+ table[4357] = "gdi32.dll!NtGdiSelectPen";
+ table[4358] = "gdi32.dll!NtGdiSetBitmapAttributes";
+ table[4359] = "gdi32.dll!SetBitmapBits";
+ table[4360] = "gdi32.dll!NtGdiSetBitmapDimension";
+ table[4361] = "gdi32.dll!NtGdiSetBoundsRect";
+ table[4362] = "gdi32.dll!NtGdiSetBrushAttributes";
+ table[4363] = "gdi32.dll!NtGdiSetBrushOrg";
+ table[4364] = "gdi32.dll!NtGdiSetColorAdjustment";
+ table[4365] = "gdi32.dll!NtGdiSetColorSpace";
+ table[4366] = "gdi32.dll!NtGdiSetDeviceGammaRamp";
+ table[4367] = "gdi32.dll!NtGdiSetDIBitsToDeviceInternal";
+ table[4368] = "gdi32.dll!NtGdiSetFontEnumeration";
+ table[4369] = "gdi32.dll!NtGdiSetFontXform";
+ table[4370] = "gdi32.dll!NtGdiSetIcmMode";
+ table[4371] = "gdi32.dll!NtGdiSetLinkedUFIs";
+ table[4372] = "gdi32.dll!NtGdiSetMagicColors";
+ table[4373] = "gdi32.dll!NtGdiSetMetaRgn";
+ table[4374] = "gdi32.dll!NtGdiSetMiterLimit";
+ table[4375] = "gdi32.dll!NtGdiGetDeviceWidth";
+ table[4376] = "gdi32.dll!NtGdiMirrorWindowOrg";
+ table[4377] = "gdi32.dll!NtGdiSetLayout";
+ table[4378] = "gdi32.dll!NtGdiSetPixel";
+ table[4379] = "gdi32.dll!NtGdiSetPixelFormat";
+ table[4380] = "gdi32.dll!NtGdiSetRectRgn";
+ table[4381] = "gdi32.dll!NtGdiSetSystemPaletteUse";
+ table[4383] = "gdi32.dll!NtGdiSetupPublicCFONT";
+ table[4384] = "gdi32.dll!NtGdiSetVirtualResolution";
+ table[4385] = "gdi32.dll!NtGdiSetSizeDevice";
+ table[4386] = "gdi32.dll!NtGdiStartDoc";
+ table[4387] = "gdi32.dll!NtGdiStartPage";
+ table[4388] = "gdi32.dll!NtGdiStretchBlt";
+ table[4389] = "gdi32.dll!NtGdiStretchDIBitsInternal";
+ table[4390] = "gdi32.dll!NtGdiStrokeAndFillPath";
+ table[4391] = "gdi32.dll!NtGdiStrokePath";
+ table[4392] = "gdi32.dll!NtGdiSwapBuffers";
+ table[4393] = "gdi32.dll!NtGdiTransformPoints";
+ table[4394] = "gdi32.dll!NtGdiTransparentBlt";
+ table[4395] = "gdi32.dll!NtGdiUnloadPrinterDriver";
+ table[4397] = "gdi32.dll!NtGdiUnrealizeObject";
+ table[4398] = "gdi32.dll!NtGdiUpdateColors";
+ table[4399] = "gdi32.dll!NtGdiWidenPath";
+ table[4400] = "user32.dll!NtUserActivateKeyboardLayout";
+ table[4401] = "user32.dll!NtUserAlterWindowStyle";
+ table[4402] = "imm32.dll!NtUserAssociateInputContext";
+ table[4403] = "user32.dll!NtUserAttachThreadInput";
+ table[4404] = "user32.dll!NtUserBeginPaint";
+ table[4405] = "user32.dll!NtUserBitBltSysBmp";
+ table[4406] = "user32.dll!NtUserBlockInput";
+ table[4407] = "imm32.dll!NtUserBuildHimcList";
+ table[4408] = "user32.dll!NtUserBuildHwndList";
+ table[4409] = "user32.dll!NtUserBuildNameList";
+ table[4410] = "user32.dll!NtUserBuildPropList";
+ table[4411] = "user32.dll!NtUserCallHwnd";
+ table[4412] = "user32.dll!NtUserCallHwndLock";
+ table[4413] = "user32.dll!NtUserCallHwndOpt";
+ table[4414] = "user32.dll!NtUserCallHwndParam";
+ table[4415] = "user32.dll!NtUserCallHwndParamLock";
+ table[4416] = "user32.dll!NtUserCallMsgFilter";
+ table[4417] = "user32.dll!NtUserCallNextHookEx";
+ table[4418] = "user32.dll!NtUserCallNoParam";
+ table[4419] = "imm32.dll!NtUserCallOneParam";
+ table[4419] = "user32.dll!NtUserCallOneParam";
+ table[4420] = "user32.dll!NtUserCallTwoParam";
+ table[4421] = "user32.dll!NtUserChangeClipboardChain";
+ table[4422] = "user32.dll!NtUserChangeDisplaySettings";
+ table[4424] = "user32.dll!NtUserCheckMenuItem";
+ table[4425] = "user32.dll!NtUserChildWindowFromPointEx";
+ table[4426] = "user32.dll!NtUserClipCursor";
+ table[4427] = "user32.dll!NtUserCloseClipboard";
+ table[4428] = "user32.dll!NtUserCloseDesktop";
+ table[4429] = "user32.dll!NtUserCloseWindowStation";
+ table[4431] = "user32.dll!NtUserConvertMemHandle";
+ table[4432] = "user32.dll!NtUserCopyAcceleratorTable";
+ table[4433] = "user32.dll!NtUserCountClipboardFormats";
+ table[4434] = "user32.dll!NtUserCreateAcceleratorTable";
+ table[4435] = "user32.dll!NtUserCreateCaret";
+ table[4436] = "user32.dll!NtUserCreateDesktop";
+ table[4437] = "imm32.dll!NtUserCreateInputContext";
+ table[4438] = "user32.dll!NtUserCreateLocalMemHandle";
+ table[4439] = "user32.dll!NtUserCreateWindowEx";
+ table[4440] = "user32.dll!NtUserCreateWindowStation";
+ table[4441] = "user32.dll!NtUserDdeGetQualityOfService";
+ table[4442] = "user32.dll!NtUserDdeInitialize";
+ table[4443] = "user32.dll!NtUserDdeSetQualityOfService";
+ table[4444] = "user32.dll!NtUserDeferWindowPos";
+ table[4445] = "user32.dll!NtUserDefSetText";
+ table[4446] = "user32.dll!NtUserDeleteMenu";
+ table[4447] = "user32.dll!DestroyAcceleratorTable";
+ table[4448] = "user32.dll!NtUserDestroyCursor";
+ table[4449] = "imm32.dll!NtUserDestroyInputContext";
+ table[4450] = "user32.dll!NtUserDestroyMenu";
+ table[4451] = "user32.dll!NtUserDestroyWindow";
+ table[4452] = "imm32.dll!NtUserDisableThreadIme";
+ table[4453] = "user32.dll!NtUserDispatchMessage";
+ table[4454] = "user32.dll!NtUserDragDetect";
+ table[4455] = "user32.dll!NtUserDragObject";
+ table[4456] = "user32.dll!NtUserDrawAnimatedRects";
+ table[4457] = "user32.dll!NtUserDrawCaption";
+ table[4458] = "user32.dll!NtUserDrawCaptionTemp";
+ table[4459] = "user32.dll!NtUserDrawIconEx";
+ table[4460] = "user32.dll!NtUserDrawMenuBarTemp";
+ table[4461] = "user32.dll!NtUserEmptyClipboard";
+ table[4462] = "user32.dll!NtUserEnableMenuItem";
+ table[4463] = "user32.dll!NtUserEnableScrollBar";
+ table[4464] = "user32.dll!NtUserEndDeferWindowPosEx";
+ table[4465] = "user32.dll!NtUserEndMenu";
+ table[4466] = "user32.dll!NtUserEndPaint";
+ table[4467] = "user32.dll!NtUserEnumDisplayDevices";
+ table[4468] = "user32.dll!NtUserEnumDisplayMonitors";
+ table[4469] = "user32.dll!NtUserEnumDisplaySettings";
+ table[4470] = "user32.dll!NtUserEvent";
+ table[4471] = "user32.dll!NtUserExcludeUpdateRgn";
+ table[4472] = "user32.dll!NtUserFillWindow";
+ table[4473] = "user32.dll!NtUserFindExistingCursorIcon";
+ table[4474] = "user32.dll!NtUserFindWindowEx";
+ table[4475] = "user32.dll!NtUserFlashWindowEx";
+ table[4476] = "user32.dll!NtUserGetAltTabInfo";
+ table[4477] = "user32.dll!NtUserGetAncestor";
+ table[4478] = "imm32.dll!NtUserGetAppImeLevel";
+ table[4479] = "user32.dll!GetAsyncKeyState";
+ table[4480] = "user32.dll!NtUserGetAtomName";
+ table[4481] = "user32.dll!NtUserGetCaretBlinkTime";
+ table[4482] = "user32.dll!NtUserGetCaretPos";
+ table[4483] = "user32.dll!NtUserGetClassInfo";
+ table[4484] = "user32.dll!NtUserGetClassName";
+ table[4485] = "user32.dll!NtUserGetClipboardData";
+ table[4486] = "user32.dll!NtUserGetClipboardFormatName";
+ table[4487] = "user32.dll!NtUserGetClipboardOwner";
+ table[4488] = "user32.dll!NtUserGetClipboardSequenceNumber";
+ table[4489] = "user32.dll!NtUserGetClipboardViewer";
+ table[4490] = "user32.dll!NtUserGetClipCursor";
+ table[4491] = "user32.dll!NtUserGetComboBoxInfo";
+ table[4492] = "user32.dll!NtUserGetControlBrush";
+ table[4493] = "user32.dll!NtUserGetControlColor";
+ table[4494] = "user32.dll!NtUserGetCPD";
+ table[4495] = "user32.dll!NtUserGetCursorFrameInfo";
+ table[4496] = "user32.dll!NtUserGetCursorInfo";
+ table[4497] = "user32.dll!NtUserGetDC";
+ table[4498] = "user32.dll!NtUserGetDCEx";
+ table[4499] = "user32.dll!NtUserGetDoubleClickTime";
+ table[4500] = "user32.dll!NtUserGetForegroundWindow";
+ table[4501] = "user32.dll!NtUserGetGuiResources";
+ table[4502] = "user32.dll!NtUserGetGUIThreadInfo";
+ table[4503] = "user32.dll!NtUserGetIconInfo";
+ table[4504] = "user32.dll!NtUserGetIconSize";
+ table[4505] = "imm32.dll!NtUserGetImeHotKey";
+ table[4505] = "user32.dll!NtUserGetImeHotKey";
+ table[4506] = "imm32.dll!NtUserGetImeInfoEx";
+ table[4507] = "user32.dll!NtUserGetInternalWindowPos";
+ table[4508] = "user32.dll!NtUserGetKeyboardLayoutList";
+ table[4509] = "user32.dll!NtUserGetKeyboardLayoutName";
+ table[4510] = "user32.dll!NtUserGetKeyboardState";
+ table[4511] = "user32.dll!NtUserGetKeyNameText";
+ table[4512] = "user32.dll!NtUserGetKeyState";
+ table[4513] = "user32.dll!NtUserGetListBoxInfo";
+ table[4514] = "user32.dll!NtUserGetMenuBarInfo";
+ table[4515] = "user32.dll!NtUserGetMenuIndex";
+ table[4516] = "user32.dll!NtUserGetMenuItemRect";
+ table[4517] = "user32.dll!NtUserGetMessage";
+ table[4518] = "user32.dll!NtUserGetMouseMovePointsEx";
+ table[4519] = "user32.dll!NtUserGetObjectInformation";
+ table[4520] = "user32.dll!NtUserGetOpenClipboardWindow";
+ table[4521] = "user32.dll!NtUserGetPriorityClipboardFormat";
+ table[4522] = "user32.dll!NtUserGetProcessWindowStation";
+ table[4523] = "user32.dll!NtUserGetRawInputBuffer";
+ table[4524] = "user32.dll!NtUserGetRawInputData";
+ table[4525] = "user32.dll!NtUserGetRawInputDeviceInfo";
+ table[4526] = "user32.dll!NtUserGetRawInputDeviceList";
+ table[4527] = "user32.dll!NtUserGetRegisteredRawInputDevices";
+ table[4528] = "user32.dll!NtUserGetScrollBarInfo";
+ table[4529] = "user32.dll!NtUserGetSystemMenu";
+ table[4530] = "user32.dll!NtUserGetThreadDesktop";
+ table[4531] = "imm32.dll!NtUserGetThreadState";
+ table[4531] = "user32.dll!NtUserGetThreadState";
+ table[4532] = "user32.dll!NtUserGetTitleBarInfo";
+ table[4533] = "user32.dll!GetUpdateRect";
+ table[4534] = "user32.dll!GetUpdateRgn";
+ table[4535] = "user32.dll!NtUserGetWindowDC";
+ table[4536] = "user32.dll!NtUserGetWindowPlacement";
+ table[4537] = "user32.dll!NtUserGetWOWClass";
+ table[4539] = "user32.dll!NtUserHideCaret";
+ table[4540] = "user32.dll!NtUserHiliteMenuItem";
+ table[4541] = "user32.dll!NtUserImpersonateDdeClientWindow";
+ table[4543] = "user32.dll!NtUserInitializeClientPfnArrays";
+ table[4544] = "user32.dll!NtUserInitTask";
+ table[4545] = "user32.dll!NtUserInternalGetWindowText";
+ table[4546] = "user32.dll!NtUserInvalidateRect";
+ table[4547] = "user32.dll!NtUserInvalidateRgn";
+ table[4548] = "user32.dll!NtUserIsClipboardFormatAvailable";
+ table[4549] = "user32.dll!NtUserKillTimer";
+ table[4550] = "user32.dll!NtUserLoadKeyboardLayoutEx";
+ table[4551] = "user32.dll!NtUserLockWindowStation";
+ table[4552] = "user32.dll!NtUserLockWindowUpdate";
+ table[4553] = "user32.dll!NtUserLockWorkStation";
+ table[4554] = "user32.dll!NtUserMapVirtualKeyEx";
+ table[4555] = "user32.dll!NtUserMenuItemFromPoint";
+ table[4556] = "user32.dll!NtUserMessageCall";
+ table[4557] = "user32.dll!NtUserMinMaximize";
+ table[4558] = "user32.dll!NtUserMNDragLeave";
+ table[4559] = "user32.dll!NtUserMNDragOver";
+ table[4560] = "user32.dll!NtUserModifyUserStartupInfoFlags";
+ table[4561] = "user32.dll!NtUserMoveWindow";
+ table[4562] = "imm32.dll!NtUserNotifyIMEStatus";
+ table[4562] = "user32.dll!NtUserNotifyIMEStatus";
+ table[4564] = "user32.dll!NtUserNotifyWinEvent";
+ table[4565] = "user32.dll!NtUserOpenClipboard";
+ table[4566] = "user32.dll!NtUserOpenDesktop";
+ table[4567] = "user32.dll!NtUserOpenInputDesktop";
+ table[4568] = "user32.dll!NtUserOpenWindowStation";
+ table[4569] = "user32.dll!NtUserPaintDesktop";
+ table[4570] = "user32.dll!PeekMessageW";
+ table[4571] = "user32.dll!NtUserPostMessage";
+ table[4572] = "user32.dll!NtUserPostThreadMessage";
+ table[4573] = "user32.dll!NtUserPrintWindow";
+ table[4574] = "user32.dll!NtUserProcessConnect";
+ table[4576] = "imm32.dll!NtUserQueryInputContext";
+ table[4577] = "user32.dll!NtUserQuerySendMessage";
+ table[4578] = "user32.dll!NtUserQueryUserCounters";
+ table[4579] = "imm32.dll!NtUserQueryWindow";
+ table[4579] = "user32.dll!NtUserQueryWindow";
+ table[4580] = "user32.dll!NtUserRealChildWindowFromPoint";
+ table[4581] = "user32.dll!NtUserRealInternalGetMessage";
+ table[4582] = "user32.dll!NtUserRealWaitMessageEx";
+ table[4583] = "user32.dll!NtUserRedrawWindow";
+ table[4584] = "user32.dll!NtUserRegisterClassExWOW";
+ table[4585] = "user32.dll!NtUserRegisterUserApiHook";
+ table[4586] = "user32.dll!NtUserRegisterHotKey";
+ table[4587] = "user32.dll!NtUserRegisterRawInputDevices";
+ table[4588] = "user32.dll!NtUserRegisterTasklist";
+ table[4589] = "user32.dll!NtUserRegisterWindowMessage";
+ table[4590] = "user32.dll!NtUserRemoveMenu";
+ table[4591] = "user32.dll!NtUserRemoveProp";
+ table[4593] = "user32.dll!NtUserResolveDesktopForWOW";
+ table[4594] = "user32.dll!NtUserSBGetParms";
+ table[4595] = "user32.dll!ScrollDC";
+ table[4596] = "user32.dll!NtUserScrollWindowEx";
+ table[4597] = "gdi32.dll!NtUserSelectPalette";
+ table[4598] = "user32.dll!NtUserSendInput";
+ table[4599] = "user32.dll!NtUserSetActiveWindow";
+ table[4600] = "imm32.dll!NtUserSetAppImeLevel";
+ table[4601] = "user32.dll!NtUserSetCapture";
+ table[4602] = "user32.dll!NtUserSetClassLong";
+ table[4603] = "user32.dll!NtUserSetClassWord";
+ table[4604] = "user32.dll!NtUserSetClipboardData";
+ table[4605] = "user32.dll!NtUserSetClipboardViewer";
+ table[4606] = "user32.dll!NtUserSetConsoleReserveKeys";
+ table[4607] = "user32.dll!NtUserSetCursor";
+ table[4608] = "user32.dll!NtUserSetCursorContents";
+ table[4609] = "user32.dll!NtUserSetCursorIconData";
+ table[4610] = "user32.dll!NtUserSetDbgTag";
+ table[4611] = "user32.dll!NtUserSetFocus";
+ table[4612] = "user32.dll!NtUserSetImeHotKey";
+ table[4613] = "imm32.dll!NtUserSetImeInfoEx";
+ table[4614] = "user32.dll!NtUserSetImeOwnerWindow";
+ table[4616] = "user32.dll!NtUserSetInformationThread";
+ table[4617] = "user32.dll!NtUserSetInternalWindowPos";
+ table[4618] = "user32.dll!NtUserSetKeyboardState";
+ table[4619] = "user32.dll!NtUserSetLogonNotifyWindow";
+ table[4620] = "user32.dll!NtUserSetMenu";
+ table[4621] = "user32.dll!NtUserSetMenuContextHelpId";
+ table[4622] = "user32.dll!NtUserSetMenuDefaultItem";
+ table[4623] = "user32.dll!NtUserSetMenuFlagRtoL";
+ table[4624] = "user32.dll!NtUserSetObjectInformation";
+ table[4625] = "user32.dll!NtUserSetParent";
+ table[4626] = "user32.dll!NtUserSetProcessWindowStation";
+ table[4627] = "user32.dll!NtUserSetProp";
+ table[4628] = "user32.dll!NtUserSetRipFlags";
+ table[4629] = "user32.dll!NtUserSetScrollInfo";
+ table[4630] = "user32.dll!NtUserSetShellWindowEx";
+ table[4631] = "user32.dll!NtUserSetSysColors";
+ table[4632] = "user32.dll!NtUserSetSystemCursor";
+ table[4633] = "user32.dll!NtUserSetSystemMenu";
+ table[4634] = "user32.dll!NtUserSetSystemTimer";
+ table[4635] = "user32.dll!NtUserSetThreadDesktop";
+ table[4636] = "imm32.dll!NtUserSetThreadLayoutHandles";
+ table[4637] = "user32.dll!NtUserSetThreadState";
+ table[4638] = "user32.dll!NtUserSetTimer";
+ table[4639] = "user32.dll!NtUserSetWindowFNID";
+ table[4640] = "user32.dll!NtUserSetWindowLong";
+ table[4641] = "user32.dll!NtUserSetWindowPlacement";
+ table[4642] = "user32.dll!NtUserSetWindowPos";
+ table[4643] = "user32.dll!NtUserSetWindowRgn";
+ table[4644] = "user32.dll!NtUserSetWindowsHookAW";
+ table[4645] = "user32.dll!NtUserSetWindowsHookEx";
+ table[4646] = "user32.dll!NtUserSetWindowStationUser";
+ table[4647] = "user32.dll!NtUserSetWindowWord";
+ table[4648] = "user32.dll!NtUserSetWinEventHook";
+ table[4649] = "user32.dll!NtUserShowCaret";
+ table[4650] = "user32.dll!NtUserShowScrollBar";
+ table[4651] = "user32.dll!NtUserShowWindow";
+ table[4652] = "user32.dll!NtUserShowWindowAsync";
+ table[4654] = "user32.dll!NtUserSwitchDesktop";
+ table[4655] = "user32.dll!NtUserSystemParametersInfo";
+ table[4657] = "user32.dll!NtUserThunkedMenuInfo";
+ table[4658] = "user32.dll!NtUserThunkedMenuItemInfo";
+ table[4659] = "user32.dll!NtUserToUnicodeEx";
+ table[4660] = "user32.dll!NtUserTrackMouseEvent";
+ table[4661] = "user32.dll!NtUserTrackPopupMenuEx";
+ table[4662] = "user32.dll!NtUserCalcMenuBar";
+ table[4663] = "user32.dll!NtUserPaintMenuBar";
+ table[4664] = "user32.dll!TranslateAcceleratorA";
+ table[4665] = "user32.dll!NtUserTranslateMessage";
+ table[4666] = "user32.dll!NtUserUnhookWindowsHookEx";
+ table[4667] = "user32.dll!NtUserUnhookWinEvent";
+ table[4668] = "user32.dll!NtUserUnloadKeyboardLayout";
+ table[4669] = "user32.dll!NtUserUnlockWindowStation";
+ table[4670] = "user32.dll!NtUserUnregisterClass";
+ table[4671] = "user32.dll!NtUserUnregisterUserApiHook";
+ table[4672] = "user32.dll!NtUserUnregisterHotKey";
+ table[4673] = "imm32.dll!NtUserUpdateInputContext";
+ table[4673] = "user32.dll!NtUserUpdateInputContext";
+ table[4674] = "user32.dll!NtUserUpdateInstance";
+ table[4675] = "user32.dll!NtUserUpdateLayeredWindow";
+ table[4676] = "user32.dll!NtUserGetLayeredWindowAttributes";
+ table[4677] = "user32.dll!NtUserSetLayeredWindowAttributes";
+ table[4678] = "user32.dll!NtUserUpdatePerUserSystemParameters";
+ table[4679] = "user32.dll!NtUserUserHandleGrantAccess";
+ table[4680] = "imm32.dll!NtUserValidateHandleSecure";
+ table[4680] = "user32.dll!NtUserValidateHandleSecure";
+ table[4681] = "user32.dll!NtUserValidateRect";
+ table[4682] = "user32.dll!NtUserValidateTimerCallback";
+ table[4683] = "user32.dll!NtUserVkKeyScanEx";
+ table[4684] = "user32.dll!NtUserWaitForInputIdle";
+ table[4685] = "user32.dll!NtUserWaitForMsgAndEvent";
+ table[4686] = "user32.dll!NtUserWaitMessage";
+ table[4687] = "user32.dll!NtUserWin32PoolAllocationStats";
+ table[4688] = "user32.dll!NtUserWindowFromPoint";
+ table[4689] = "user32.dll!NtUserYieldTask";
+ table[4695] = "gdi32.dll!NtGdiEngAssociateSurface";
+ table[4696] = "gdi32.dll!NtGdiEngCreateBitmap";
+ table[4697] = "gdi32.dll!NtGdiEngCreateDeviceSurface";
+ table[4698] = "gdi32.dll!NtGdiEngCreateDeviceBitmap";
+ table[4699] = "gdi32.dll!NtGdiEngCreatePalette";
+ table[4700] = "gdi32.dll!NtGdiEngComputeGlyphSet";
+ table[4701] = "gdi32.dll!NtGdiEngCopyBits";
+ table[4702] = "gdi32.dll!NtGdiEngDeletePalette";
+ table[4703] = "gdi32.dll!NtGdiEngDeleteSurface";
+ table[4704] = "gdi32.dll!NtGdiEngEraseSurface";
+ table[4705] = "gdi32.dll!NtGdiEngUnlockSurface";
+ table[4706] = "gdi32.dll!NtGdiEngLockSurface";
+ table[4707] = "gdi32.dll!NtGdiEngBitBlt";
+ table[4708] = "gdi32.dll!NtGdiEngStretchBlt";
+ table[4709] = "gdi32.dll!NtGdiEngPlgBlt";
+ table[4710] = "gdi32.dll!NtGdiEngMarkBandingSurface";
+ table[4711] = "gdi32.dll!NtGdiEngStrokePath";
+ table[4712] = "gdi32.dll!NtGdiEngFillPath";
+ table[4713] = "gdi32.dll!NtGdiEngStrokeAndFillPath";
+ table[4714] = "gdi32.dll!NtGdiEngPaint";
+ table[4715] = "gdi32.dll!NtGdiEngLineTo";
+ table[4716] = "gdi32.dll!NtGdiEngAlphaBlend";
+ table[4717] = "gdi32.dll!NtGdiEngGradientFill";
+ table[4718] = "gdi32.dll!NtGdiEngTransparentBlt";
+ table[4719] = "gdi32.dll!NtGdiEngTextOut";
+ table[4720] = "gdi32.dll!NtGdiEngStretchBltROP";
+ table[4721] = "gdi32.dll!NtGdiXLATEOBJ_cGetPalette";
+ table[4722] = "gdi32.dll!NtGdiXLATEOBJ_iXlate";
+ table[4723] = "gdi32.dll!NtGdiXLATEOBJ_hGetColorTransform";
+ table[4724] = "gdi32.dll!NtGdiCLIPOBJ_bEnum";
+ table[4725] = "gdi32.dll!NtGdiCLIPOBJ_cEnumStart";
+ table[4726] = "gdi32.dll!NtGdiCLIPOBJ_ppoGetPath";
+ table[4727] = "gdi32.dll!NtGdiEngDeletePath";
+ table[4728] = "gdi32.dll!NtGdiEngCreateClip";
+ table[4729] = "gdi32.dll!NtGdiEngDeleteClip";
+ table[4730] = "gdi32.dll!NtGdiBRUSHOBJ_ulGetBrushColor";
+ table[4731] = "gdi32.dll!NtGdiBRUSHOBJ_pvAllocRbrush";
+ table[4732] = "gdi32.dll!NtGdiBRUSHOBJ_pvGetRbrush";
+ table[4733] = "gdi32.dll!NtGdiBRUSHOBJ_hGetColorTransform";
+ table[4734] = "gdi32.dll!NtGdiXFORMOBJ_bApplyXform";
+ table[4735] = "gdi32.dll!NtGdiXFORMOBJ_iGetXform";
+ table[4736] = "gdi32.dll!NtGdiFONTOBJ_vGetInfo";
+ table[4737] = "gdi32.dll!NtGdiFONTOBJ_pxoGetXform";
+ table[4738] = "gdi32.dll!NtGdiFONTOBJ_cGetGlyphs";
+ table[4739] = "gdi32.dll!NtGdiFONTOBJ_pifi";
+ table[4740] = "gdi32.dll!NtGdiFONTOBJ_pfdg";
+ table[4741] = "gdi32.dll!NtGdiFONTOBJ_pQueryGlyphAttrs";
+ table[4742] = "gdi32.dll!NtGdiFONTOBJ_pvTrueTypeFontFile";
+ table[4743] = "gdi32.dll!NtGdiFONTOBJ_cGetAllGlyphHandles";
+ table[4744] = "gdi32.dll!NtGdiSTROBJ_bEnum";
+ table[4745] = "gdi32.dll!NtGdiSTROBJ_bEnumPositionsOnly";
+ table[4746] = "gdi32.dll!NtGdiSTROBJ_bGetAdvanceWidths";
+ table[4747] = "gdi32.dll!NtGdiSTROBJ_vEnumStart";
+ table[4748] = "gdi32.dll!NtGdiSTROBJ_dwGetCodePage";
+ table[4749] = "gdi32.dll!NtGdiPATHOBJ_vGetBounds";
+ table[4750] = "gdi32.dll!NtGdiPATHOBJ_bEnum";
+ table[4751] = "gdi32.dll!NtGdiPATHOBJ_vEnumStart";
+ table[4752] = "gdi32.dll!NtGdiPATHOBJ_vEnumStartClipLines";
+ table[4753] = "gdi32.dll!NtGdiPATHOBJ_bEnumClipLines";
+ table[4754] = "gdi32.dll!NtGdiGetDhpdev";
+ table[4755] = "gdi32.dll!NtGdiEngCheckAbort";
+ table[4756] = "gdi32.dll!NtGdiHT_Get8BPPFormatPalette";
+ table[4757] = "gdi32.dll!NtGdiHT_Get8BPPMaskPalette";
+ table[4758] = "gdi32.dll!NtGdiUpdateTransform";
+ table[4759] = "gdi32.dll!NtGdiSetPUMPDOBJ";
+ table[4760] = "gdi32.dll!NtGdiBRUSHOBJ_DeleteRbrush";
+ table[4761] = "gdi32.dll!NtGdiUMPDEngFreeUserMem";
+ table[4762] = "gdi32.dll!NtGdiDrawStream";
+} else { // Vista table.
+ table[4272] = "gdi32.dll!NtGdiGetDeviceCaps";
+ table[4220] = "gdi32.dll!NtGdiDeleteObjectApp";
+ table[4249] = "gdi32.dll!NtGdiFlush";
+ table[4120] = "gdi32.dll!NtGdiConsoleTextOut";
+ table[4825] = "gdi32.dll!NtGdiDdDDIEscape";
+ table[4299] = "gdi32.dll!GetRgnBox";
+ table[4828] = "gdi32.dll!NtGdiDdDDIGetPresentHistory";
+ table[4835] = "gdi32.dll!NtGdiDdDDIGetDeviceState";
+ table[4850] = "gdi32.dll!NtGdiDdDDICheckExclusiveOwnership";
+ table[4849] = "gdi32.dll!NtGdiDdDDICheckMonitorPowerState";
+ table[4833] = "gdi32.dll!NtGdiDdDDIWaitForVerticalBlankEvent";
+ table[4298] = "gdi32.dll!GetRegionData";
+ table[4796] = "gdi32.dll!NtGdiDwmGetDirtyRgn";
+ table[4820] = "gdi32.dll!NtGdiDdDDIRender";
+ table[4819] = "gdi32.dll!NtGdiDdDDIPresent";
+ table[4815] = "gdi32.dll!NtGdiDdDDIUnlock";
+ table[4814] = "gdi32.dll!NtGdiDdDDILock";
+ table[4240] = "gdi32.dll!NtGdiExtCreateRegion";
+ table[4339] = "gdi32.dll!NtGdiPolyPatBlt";
+ table[4361] = "gdi32.dll!NtGdiSelectBitmap";
+ table[4127] = "gdi32.dll!NtGdiCreateCompatibleDC";
+ table[4142] = "gdi32.dll!NtGdiCreateSolidBrush";
+ table[4122] = "gdi32.dll!CreateBitmap";
+ table[4303] = "gdi32.dll!CreateBitmap";
+ table[4348] = "gdi32.dll!NtGdiQueryFontAssocInfo";
+ table[4126] = "gdi32.dll!NtGdiCreateCompatibleBitmap";
+ table[4109] = "gdi32.dll!NtGdiBitBlt";
+ table[4243] = "gdi32.dll!NtGdiExtGetObjectW";
+ table[4270] = "gdi32.dll!NtGdiGetDCObject";
+ table[4620] = "gdi32.dll!NtUserSelectPalette";
+ table[4338] = "gdi32.dll!NtGdiPatBlt";
+ table[4275] = "gdi32.dll!NtGdiGetDIBitsInternal";
+ table[4398] = "gdi32.dll!NtGdiStretchDIBitsInternal";
+ table[4130] = "gdi32.dll!NtGdiCreateDIBSection";
+ table[4356] = "gdi32.dll!NtGdiRestoreDC";
+ table[4358] = "gdi32.dll!NtGdiSaveDC";
+ table[4103] = "gdi32.dll!NtGdiAlphaBlend";
+ table[4349] = "gdi32.dll!NtGdiRectangle";
+ table[4295] = "gdi32.dll!NtGdiGetRandomRgn";
+ table[4244] = "gdi32.dll!NtGdiExtSelectClipRgn";
+ table[4268] = "gdi32.dll!NtGdiGetDCDword";
+ table[4245] = "gdi32.dll!NtGdiExtTextOutW";
+ table[4254] = "gdi32.dll!GetClipBox";
+ table[4397] = "gdi32.dll!NtGdiStretchBlt";
+ table[4331] = "gdi32.dll!NtGdiMaskBlt";
+ table[4324] = "gdi32.dll!NtGdiInit";
+ table[4262] = "gdi32.dll!NtGdiGetCharSet";
+ table[4336] = "gdi32.dll!NtGdiOffsetRgn";
+ table[4326] = "gdi32.dll!NtGdiIntersectClipRect";
+ table[4795] = "gdi32.dll!NtGdiDrawStream";
+ table[4364] = "gdi32.dll!NtGdiSelectFont";
+ table[4116] = "gdi32.dll!NtGdiCombineRgn";
+ table[4238] = "gdi32.dll!NtGdiExcludeClipRect";
+ table[4802] = "gdi32.dll!NtGdiDdDDISetAllocationPriority";
+ table[4798] = "gdi32.dll!NtGdiDdDDICreateAllocation";
+ table[4801] = "gdi32.dll!NtGdiDdDDIDestroyAllocation";
+ table[4797] = "gdi32.dll!NtGdiDwmGetSurfaceData";
+ table[4140] = "gdi32.dll!CreateRoundRectRgn";
+ table[4840] = "gdi32.dll!NtGdiDdDDISetProcessSchedulingPriorityClass";
+ table[4307] = "gdi32.dll!NtGdiGetTextCharsetInfo";
+ table[4351] = "gdi32.dll!RectVisible";
+ table[4139] = "gdi32.dll!NtGdiCreateRectRgn";
+ table[4369] = "gdi32.dll!NtGdiSetBoundsRect";
+ table[4257] = "gdi32.dll!NtGdiGetBoundsRect";
+ table[4309] = "gdi32.dll!NtGdiGetTextExtentExW";
+ table[4402] = "gdi32.dll!NtGdiTransformPoints";
+ table[4118] = "gdi32.dll!NtGdiComputeXformCoefficients";
+ table[4337] = "gdi32.dll!NtGdiOpenDCW";
+ table[4813] = "gdi32.dll!NtGdiDdDDIQueryAdapterInfo";
+ table[4822] = "gdi32.dll!NtGdiDdDDIOpenAdapterFromHdc";
+ table[4816] = "gdi32.dll!NtGdiDdDDIGetDisplayModeList";
+ table[4823] = "gdi32.dll!NtGdiDdDDICloseAdapter";
+ table[4804] = "gdi32.dll!NtGdiDdDDICreateDevice";
+ table[4806] = "gdi32.dll!NtGdiDdDDICreateContext";
+ table[4271] = "gdi32.dll!NtGdiGetDCPoint";
+ table[4225] = "gdi32.dll!NtGdiDoPalette";
+ table[4288] = "gdi32.dll!GetNearestColor";
+ table[4129] = "gdi32.dll!NtGdiCreateDIBitmapInternal";
+ table[4322] = "gdi32.dll!NtGdiHfontCreate";
+ table[4137] = "gdi32.dll!NtGdiCreatePatternBrushInternal";
+ table[4136] = "gdi32.dll!NtGdiCreatePaletteInternal";
+ table[4132] = "gdi32.dll!NtGdiCreateHalftonePalette";
+ table[4375] = "gdi32.dll!NtGdiSetDIBitsToDeviceInternal";
+ table[4269] = "gdi32.dll!NtGdiGetDCforBitmap";
+ table[4392] = "gdi32.dll!NtGdiSetupPublicCFONT";
+ table[4836] = "gdi32.dll!NtGdiDdDDICreateDCFromMemory";
+ table[4264] = "gdi32.dll!NtGdiGetCharWidthInfo";
+ table[4367] = "gdi32.dll!SetBitmapBits";
+ table[4255] = "gdi32.dll!GetBitmapBits";
+ table[4311] = "gdi32.dll!NtGdiGetTextMetricsW";
+ table[4297] = "gdi32.dll!NtGdiGetRealizationInfo";
+ table[4310] = "gdi32.dll!NtGdiGetTextFaceW";
+ table[4292] = "gdi32.dll!NtGdiGetOutlineTextMetricsInternalW";
+ table[4280] = "gdi32.dll!NtGdiGetGlyphIndicesW";
+ table[4320] = "gdi32.dll!NtGdiGetWidthTable";
+ table[4234] = "gdi32.dll!NtGdiEnumFontOpen";
+ table[4233] = "gdi32.dll!NtGdiEnumFontClose";
+ table[4232] = "gdi32.dll!NtGdiEnumFontChunk";
+ table[4260] = "gdi32.dll!NtGdiGetCharABCWidthsW";
+ table[4105] = "gdi32.dll!NtGdiAnyLinkedFonts";
+ table[4278] = "gdi32.dll!NtGdiGetFontData";
+ table[4106] = "gdi32.dll!NtGdiFontIsLinked";
+ table[4332] = "gdi32.dll!NtGdiModifyWorldTransform";
+ table[4312] = "gdi32.dll!NtGdiGetTransform";
+ table[4321] = "gdi32.dll!NtGdiGradientFill";
+ table[4294] = "gdi32.dll!NtGdiGetPixel";
+ table[4403] = "gdi32.dll!NtGdiTransparentBlt";
+ table[4319] = "gdi32.dll!NtGdiGetFontUnicodeRanges";
+ table[4817] = "gdi32.dll!NtGdiDdDDISetDisplayMode";
+ table[4827] = "gdi32.dll!NtGdiDdDDISetVidPnSourceOwner";
+ table[4273] = "gdi32.dll!NtGdiGetDeviceGammaRamp";
+ table[4374] = "gdi32.dll!NtGdiSetDeviceGammaRamp";
+ table[4366] = "gdi32.dll!NtGdiSetBitmapAttributes";
+ table[4098] = "gdi32.dll!NtGdiAddFontResourceW";
+ table[4376] = "gdi32.dll!NtGdiSetFontEnumeration";
+ table[4228] = "gdi32.dll!NtGdiEnableEudc";
+ table[4343] = "gdi32.dll!NtGdiPolyPolyDraw";
+ table[4328] = "gdi32.dll!NtGdiLineTo";
+ table[4138] = "gdi32.dll!NtGdiCreatePen";
+ table[4236] = "gdi32.dll!EqualRgn";
+ table[4805] = "gdi32.dll!NtGdiDdDDIDestroyDevice";
+ table[4807] = "gdi32.dll!NtGdiDdDDIDestroyContext";
+ table[4799] = "gdi32.dll!NtGdiDdDDIQueryResourceInfo";
+ table[4800] = "gdi32.dll!NtGdiDdDDIOpenResource";
+ table[4838] = "gdi32.dll!NtGdiDdDDISetContextSchedulingPriority";
+ table[4263] = "gdi32.dll!NtGdiGetCharWidthW";
+ table[4837] = "gdi32.dll!NtGdiDdDDIDestroyDCFromMemory";
+ table[4803] = "gdi32.dll!NtGdiDdDDIQueryAllocationResidency";
+ table[4824] = "gdi32.dll!NtGdiDdDDIGetSharedPrimaryHandle";
+ table[4385] = "gdi32.dll!NtGdiSetLayout";
+ table[4371] = "gdi32.dll!NtGdiSetBrushOrg";
+ table[4157] = "gdi32.dll!NtGdiDdCreateDirectDrawObject";
+ table[4128] = "gdi32.dll!NtGdiCreateDIBBrush";
+ table[4387] = "gdi32.dll!NtGdiSetPixel";
+ table[4345] = "gdi32.dll!PtInRegion";
+ table[4821] = "gdi32.dll!NtGdiDdDDIOpenAdapterFromDeviceName";
+ table[4253] = "gdi32.dll!NtGdiGetAndSetDCDword";
+ table[4274] = "gdi32.dll!NtGdiGetDeviceCapsAll";
+ table[4247] = "gdi32.dll!NtGdiFillRgn";
+ table[4289] = "gdi32.dll!GetNearestPaletteIndex";
+ table[4378] = "gdi32.dll!NtGdiSetIcmMode";
+ table[4327] = "gdi32.dll!NtGdiInvertRgn";
+ table[4792] = "gdi32.dll!NtGdiSetPUMPDOBJ";
+ table[4735] = "gdi32.dll!NtGdiEngDeletePalette";
+ table[4732] = "gdi32.dll!NtGdiEngCreatePalette";
+ table[4241] = "gdi32.dll!NtGdiExtEscape";
+ table[4217] = "gdi32.dll!NtGdiDeleteClientObj";
+ table[4123] = "gdi32.dll!NtGdiCreateClientObj";
+ table[4354] = "gdi32.dll!NtGdiResetDC";
+ table[4235] = "gdi32.dll!NtGdiEnumObjects";
+ table[4135] = "gdi32.dll!NtGdiCreateOPMProtectedOutputs";
+ table[4222] = "gdi32.dll!NtGdiDestroyOPMProtectedOutput";
+ table[4258] = "gdi32.dll!NtGdiGetCertificate";
+ table[4259] = "gdi32.dll!NtGdiGetCertificateSize";
+ table[4291] = "gdi32.dll!NtGdiGetOPMRandomNumber";
+ table[4305] = "gdi32.dll!NtGdiGetSuggestedOPMProtectedOutputArraySize";
+ table[4386] = "gdi32.dll!NtGdiSetOPMSigningKeyAndSequenceNumbers";
+ table[4844] = "gdi32.dll!NtGdiDdDDISetQueuedLimit";
+ table[4341] = "gdi32.dll!NtGdiPlgBlt";
+ table[4117] = "gdi32.dll!CombineTransform";
+ table[4134] = "gdi32.dll!NtGdiCreateMetafileDC";
+ table[4393] = "gdi32.dll!NtGdiSetVirtualResolution";
+ table[4394] = "gdi32.dll!NtGdiSetSizeDevice";
+ table[4381] = "gdi32.dll!NtGdiSetMetaRgn";
+ table[4382] = "gdi32.dll!NtGdiSetMiterLimit";
+ table[4377] = "gdi32.dll!NtGdiSetFontXform";
+ table[4333] = "gdi32.dll!NtGdiMonoBitmap";
+ table[4768] = "gdi32.dll!NtGdiXFORMOBJ_iGetXform";
+ table[4770] = "gdi32.dll!NtGdiFONTOBJ_pxoGetXform";
+ table[4239] = "gdi32.dll!NtGdiExtCreatePen";
+ table[4286] = "gdi32.dll!GetMiterLimit";
+ table[4290] = "gdi32.dll!NtGdiGetObjectBitmapHandle";
+ table[4287] = "gdi32.dll!NtGdiGetMonitorID";
+ table[4284] = "gdi32.dll!NtGdiGetKerningPairs";
+ table[4357] = "gdi32.dll!NtGdiRoundRect";
+ table[4242] = "gdi32.dll!NtGdiExtFloodFill";
+ table[4306] = "gdi32.dll!GetSystemPaletteUse";
+ table[4096] = "gdi32.dll!NtGdiAbortDoc";
+ table[4097] = "gdi32.dll!NtGdiAbortPath";
+ table[4099] = "gdi32.dll!NtGdiAddRemoteFontToDC";
+ table[4100] = "gdi32.dll!NtGdiAddFontMemResourceEx";
+ table[4101] = "gdi32.dll!NtGdiRemoveMergeFont";
+ table[4102] = "gdi32.dll!NtGdiAddRemoteMMInstanceToDC";
+ table[4104] = "gdi32.dll!NtGdiAngleArc";
+ table[4107] = "gdi32.dll!NtGdiArcInternal";
+ table[4108] = "gdi32.dll!NtGdiBeginPath";
+ table[4110] = "gdi32.dll!NtGdiCancelDC";
+ table[4111] = "gdi32.dll!NtGdiCheckBitmapBits";
+ table[4112] = "gdi32.dll!NtGdiCloseFigure";
+ table[4113] = "gdi32.dll!NtGdiClearBitmapAttributes";
+ table[4114] = "gdi32.dll!NtGdiClearBrushAttributes";
+ table[4115] = "gdi32.dll!NtGdiColorCorrectPalette";
+ table[4119] = "gdi32.dll!NtGdiConfigureOPMProtectedOutput";
+ table[4121] = "gdi32.dll!NtGdiConvertMetafileRect";
+ table[4124] = "gdi32.dll!NtGdiCreateColorSpace";
+ table[4125] = "gdi32.dll!NtGdiCreateColorTransform";
+ table[4131] = "gdi32.dll!NtGdiCreateEllipticRgn";
+ table[4133] = "gdi32.dll!NtGdiCreateHatchBrushInternal";
+ table[4141] = "gdi32.dll!NtGdiCreateServerMetaFile";
+ table[4143] = "gdi32.dll!NtGdiD3dContextCreate";
+ table[4144] = "gdi32.dll!NtGdiD3dContextDestroy";
+ table[4145] = "gdi32.dll!NtGdiD3dContextDestroyAll";
+ table[4146] = "gdi32.dll!NtGdiD3dValidateTextureStageState";
+ table[4147] = "gdi32.dll!NtGdiD3dDrawPrimitives2";
+ table[4148] = "gdi32.dll!NtGdiDdGetDriverState";
+ table[4149] = "gdi32.dll!NtGdiDdAddAttachedSurface";
+ table[4150] = "gdi32.dll!NtGdiDdAlphaBlt";
+ table[4151] = "gdi32.dll!NtGdiDdAttachSurface";
+ table[4152] = "gdi32.dll!NtGdiDdBeginMoCompFrame";
+ table[4153] = "gdi32.dll!NtGdiDdBlt";
+ table[4154] = "gdi32.dll!NtGdiDdCanCreateSurface";
+ table[4155] = "gdi32.dll!NtGdiDdCanCreateD3DBuffer";
+ table[4156] = "gdi32.dll!NtGdiDdColorControl";
+ table[4158] = "gdi32.dll!NtGdiDdCreateSurface";
+ table[4159] = "gdi32.dll!NtGdiDdCreateD3DBuffer";
+ table[4160] = "gdi32.dll!NtGdiDdCreateMoComp";
+ table[4161] = "gdi32.dll!NtGdiDdCreateSurfaceObject";
+ table[4162] = "gdi32.dll!NtGdiDdDeleteDirectDrawObject";
+ table[4163] = "gdi32.dll!NtGdiDdDeleteSurfaceObject";
+ table[4164] = "gdi32.dll!NtGdiDdDestroyMoComp";
+ table[4165] = "gdi32.dll!NtGdiDdDestroySurface";
+ table[4166] = "gdi32.dll!NtGdiDdDestroyD3DBuffer";
+ table[4167] = "gdi32.dll!NtGdiDdEndMoCompFrame";
+ table[4168] = "gdi32.dll!NtGdiDdFlip";
+ table[4169] = "gdi32.dll!NtGdiDdFlipToGDISurface";
+ table[4170] = "gdi32.dll!NtGdiDdGetAvailDriverMemory";
+ table[4171] = "gdi32.dll!NtGdiDdGetBltStatus";
+ table[4172] = "gdi32.dll!NtGdiDdGetDC";
+ table[4173] = "gdi32.dll!NtGdiDdGetDriverInfo";
+ table[4174] = "gdi32.dll!NtGdiDdGetDxHandle";
+ table[4175] = "gdi32.dll!NtGdiDdGetFlipStatus";
+ table[4176] = "gdi32.dll!NtGdiDdGetInternalMoCompInfo";
+ table[4177] = "gdi32.dll!NtGdiDdGetMoCompBuffInfo";
+ table[4178] = "gdi32.dll!NtGdiDdGetMoCompGuids";
+ table[4179] = "gdi32.dll!NtGdiDdGetMoCompFormats";
+ table[4180] = "gdi32.dll!NtGdiDdGetScanLine";
+ table[4181] = "gdi32.dll!NtGdiDdLock";
+ table[4182] = "gdi32.dll!NtGdiDdLockD3D";
+ table[4183] = "gdi32.dll!NtGdiDdQueryDirectDrawObject";
+ table[4184] = "gdi32.dll!NtGdiDdQueryMoCompStatus";
+ table[4185] = "gdi32.dll!NtGdiDdReenableDirectDrawObject";
+ table[4186] = "gdi32.dll!NtGdiDdReleaseDC";
+ table[4187] = "gdi32.dll!NtGdiDdRenderMoComp";
+ table[4188] = "gdi32.dll!NtGdiDdResetVisrgn";
+ table[4189] = "gdi32.dll!NtGdiDdSetColorKey";
+ table[4190] = "gdi32.dll!NtGdiDdSetExclusiveMode";
+ table[4191] = "gdi32.dll!NtGdiDdSetGammaRamp";
+ table[4192] = "gdi32.dll!NtGdiDdCreateSurfaceEx";
+ table[4193] = "gdi32.dll!NtGdiDdSetOverlayPosition";
+ table[4194] = "gdi32.dll!NtGdiDdUnattachSurface";
+ table[4195] = "gdi32.dll!NtGdiDdUnlock";
+ table[4196] = "gdi32.dll!NtGdiDdUnlockD3D";
+ table[4197] = "gdi32.dll!NtGdiDdUpdateOverlay";
+ table[4198] = "gdi32.dll!NtGdiDdWaitForVerticalBlank";
+ table[4199] = "gdi32.dll!NtGdiDvpCanCreateVideoPort";
+ table[4200] = "gdi32.dll!NtGdiDvpColorControl";
+ table[4201] = "gdi32.dll!NtGdiDvpCreateVideoPort";
+ table[4202] = "gdi32.dll!NtGdiDvpDestroyVideoPort";
+ table[4203] = "gdi32.dll!NtGdiDvpFlipVideoPort";
+ table[4204] = "gdi32.dll!NtGdiDvpGetVideoPortBandwidth";
+ table[4205] = "gdi32.dll!NtGdiDvpGetVideoPortField";
+ table[4206] = "gdi32.dll!NtGdiDvpGetVideoPortFlipStatus";
+ table[4207] = "gdi32.dll!NtGdiDvpGetVideoPortInputFormats";
+ table[4208] = "gdi32.dll!NtGdiDvpGetVideoPortLine";
+ table[4209] = "gdi32.dll!NtGdiDvpGetVideoPortOutputFormats";
+ table[4210] = "gdi32.dll!NtGdiDvpGetVideoPortConnectInfo";
+ table[4211] = "gdi32.dll!NtGdiDvpGetVideoSignalStatus";
+ table[4212] = "gdi32.dll!NtGdiDvpUpdateVideoPort";
+ table[4213] = "gdi32.dll!NtGdiDvpWaitForVideoPortSync";
+ table[4214] = "gdi32.dll!NtGdiDvpAcquireNotification";
+ table[4215] = "gdi32.dll!NtGdiDvpReleaseNotification";
+ table[4216] = "gdi32.dll!NtGdiDxgGenericThunk";
+ table[4218] = "gdi32.dll!NtGdiDeleteColorSpace";
+ table[4219] = "gdi32.dll!NtGdiDeleteColorTransform";
+ table[4221] = "gdi32.dll!NtGdiDescribePixelFormat";
+ table[4223] = "gdi32.dll!NtGdiGetPerBandInfo";
+ table[4224] = "gdi32.dll!NtGdiDoBanding";
+ table[4226] = "gdi32.dll!NtGdiDrawEscape";
+ table[4227] = "gdi32.dll!NtGdiEllipse";
+ table[4229] = "gdi32.dll!NtGdiEndDoc";
+ table[4230] = "gdi32.dll!NtGdiEndPage";
+ table[4231] = "gdi32.dll!NtGdiEndPath";
+ table[4237] = "gdi32.dll!NtGdiEudcLoadUnloadLink";
+ table[4246] = "gdi32.dll!NtGdiFillPath";
+ table[4248] = "gdi32.dll!NtGdiFlattenPath";
+ table[4250] = "gdi32.dll!NtGdiForceUFIMapping";
+ table[4251] = "gdi32.dll!NtGdiFrameRgn";
+ table[4252] = "gdi32.dll!NtGdiFullscreenControl";
+ table[4256] = "gdi32.dll!NtGdiGetBitmapDimension";
+ table[4261] = "gdi32.dll!NtGdiGetCharacterPlacementW";
+ table[4265] = "gdi32.dll!NtGdiGetColorAdjustment";
+ table[4267] = "gdi32.dll!NtGdiGetCOPPCompatibleOPMInformation";
+ table[4276] = "gdi32.dll!NtGdiGetETM";
+ table[4277] = "gdi32.dll!NtGdiGetEudcTimeStampEx";
+ table[4279] = "gdi32.dll!NtGdiGetFontResourceInfoInternalW";
+ table[4281] = "gdi32.dll!NtGdiGetGlyphIndicesWInternal";
+ table[4282] = "gdi32.dll!NtGdiGetGlyphOutline";
+ table[4283] = "gdi32.dll!NtGdiGetOPMInformation";
+ table[4285] = "gdi32.dll!NtGdiGetLinkedUFIs";
+ table[4293] = "gdi32.dll!NtGdiGetPath";
+ table[4296] = "gdi32.dll!NtGdiGetRasterizerCaps";
+ table[4300] = "gdi32.dll!NtGdiGetServerMetaFileBits";
+ table[4301] = "gdi32.dll!NtGdiGetSpoolMessage";
+ table[4304] = "gdi32.dll!NtGdiGetStringBitmapW";
+ table[4308] = "gdi32.dll!NtGdiGetTextExtent";
+ table[4313] = "gdi32.dll!NtGdiGetUFI";
+ table[4314] = "gdi32.dll!NtGdiGetEmbUFI";
+ table[4315] = "gdi32.dll!NtGdiGetUFIPathname";
+ table[4316] = "gdi32.dll!NtGdiGetEmbedFonts";
+ table[4317] = "gdi32.dll!NtGdiChangeGhostFont";
+ table[4318] = "gdi32.dll!NtGdiAddEmbFontToDC";
+ table[4323] = "gdi32.dll!NtGdiIcmBrushInfo";
+ table[4325] = "gdi32.dll!NtGdiInitSpool";
+ table[4329] = "gdi32.dll!NtGdiMakeFontDir";
+ table[4330] = "gdi32.dll!NtGdiMakeInfoDC";
+ table[4335] = "gdi32.dll!NtGdiOffsetClipRgn";
+ table[4340] = "gdi32.dll!NtGdiPathToRegion";
+ table[4342] = "gdi32.dll!NtGdiPolyDraw";
+ table[4344] = "gdi32.dll!NtGdiPolyTextOutW";
+ table[4346] = "gdi32.dll!NtGdiPtVisible";
+ table[4347] = "gdi32.dll!NtGdiQueryFonts";
+ table[4350] = "gdi32.dll!NtGdiRectInRegion";
+ table[4352] = "gdi32.dll!NtGdiRemoveFontResourceW";
+ table[4353] = "gdi32.dll!NtGdiRemoveFontMemResourceEx";
+ table[4355] = "gdi32.dll!NtGdiResizePalette";
+ table[4359] = "gdi32.dll!NtGdiScaleViewportExtEx";
+ table[4360] = "gdi32.dll!NtGdiScaleWindowExtEx";
+ table[4363] = "gdi32.dll!NtGdiSelectClipPath";
+ table[4365] = "gdi32.dll!NtGdiSelectPen";
+ table[4368] = "gdi32.dll!NtGdiSetBitmapDimension";
+ table[4370] = "gdi32.dll!NtGdiSetBrushAttributes";
+ table[4372] = "gdi32.dll!NtGdiSetColorAdjustment";
+ table[4373] = "gdi32.dll!NtGdiSetColorSpace";
+ table[4379] = "gdi32.dll!NtGdiSetLinkedUFIs";
+ table[4380] = "gdi32.dll!NtGdiSetMagicColors";
+ table[4383] = "gdi32.dll!NtGdiGetDeviceWidth";
+ table[4384] = "gdi32.dll!NtGdiMirrorWindowOrg";
+ table[4388] = "gdi32.dll!NtGdiSetPixelFormat";
+ table[4389] = "gdi32.dll!NtGdiSetRectRgn";
+ table[4390] = "gdi32.dll!NtGdiSetSystemPaletteUse";
+ table[4395] = "gdi32.dll!NtGdiStartDoc";
+ table[4396] = "gdi32.dll!NtGdiStartPage";
+ table[4399] = "gdi32.dll!NtGdiStrokeAndFillPath";
+ table[4400] = "gdi32.dll!NtGdiStrokePath";
+ table[4401] = "gdi32.dll!NtGdiSwapBuffers";
+ table[4404] = "gdi32.dll!NtGdiUnloadPrinterDriver";
+ table[4406] = "gdi32.dll!NtGdiUnrealizeObject";
+ table[4407] = "gdi32.dll!NtGdiUpdateColors";
+ table[4408] = "gdi32.dll!NtGdiWidenPath";
+ table[4728] = "gdi32.dll!NtGdiEngAssociateSurface";
+ table[4729] = "gdi32.dll!NtGdiEngCreateBitmap";
+ table[4730] = "gdi32.dll!NtGdiEngCreateDeviceSurface";
+ table[4731] = "gdi32.dll!NtGdiEngCreateDeviceBitmap";
+ table[4733] = "gdi32.dll!NtGdiEngComputeGlyphSet";
+ table[4734] = "gdi32.dll!NtGdiEngCopyBits";
+ table[4736] = "gdi32.dll!NtGdiEngDeleteSurface";
+ table[4737] = "gdi32.dll!NtGdiEngEraseSurface";
+ table[4738] = "gdi32.dll!NtGdiEngUnlockSurface";
+ table[4739] = "gdi32.dll!NtGdiEngLockSurface";
+ table[4740] = "gdi32.dll!NtGdiEngBitBlt";
+ table[4741] = "gdi32.dll!NtGdiEngStretchBlt";
+ table[4742] = "gdi32.dll!NtGdiEngPlgBlt";
+ table[4743] = "gdi32.dll!NtGdiEngMarkBandingSurface";
+ table[4744] = "gdi32.dll!NtGdiEngStrokePath";
+ table[4745] = "gdi32.dll!NtGdiEngFillPath";
+ table[4746] = "gdi32.dll!NtGdiEngStrokeAndFillPath";
+ table[4747] = "gdi32.dll!NtGdiEngPaint";
+ table[4748] = "gdi32.dll!NtGdiEngLineTo";
+ table[4749] = "gdi32.dll!NtGdiEngAlphaBlend";
+ table[4750] = "gdi32.dll!NtGdiEngGradientFill";
+ table[4751] = "gdi32.dll!NtGdiEngTransparentBlt";
+ table[4752] = "gdi32.dll!NtGdiEngTextOut";
+ table[4753] = "gdi32.dll!NtGdiEngStretchBltROP";
+ table[4754] = "gdi32.dll!NtGdiXLATEOBJ_cGetPalette";
+ table[4755] = "gdi32.dll!NtGdiXLATEOBJ_iXlate";
+ table[4756] = "gdi32.dll!NtGdiXLATEOBJ_hGetColorTransform";
+ table[4757] = "gdi32.dll!NtGdiCLIPOBJ_bEnum";
+ table[4758] = "gdi32.dll!NtGdiCLIPOBJ_cEnumStart";
+ table[4759] = "gdi32.dll!NtGdiCLIPOBJ_ppoGetPath";
+ table[4760] = "gdi32.dll!NtGdiEngDeletePath";
+ table[4761] = "gdi32.dll!NtGdiEngCreateClip";
+ table[4762] = "gdi32.dll!NtGdiEngDeleteClip";
+ table[4763] = "gdi32.dll!NtGdiBRUSHOBJ_ulGetBrushColor";
+ table[4764] = "gdi32.dll!NtGdiBRUSHOBJ_pvAllocRbrush";
+ table[4765] = "gdi32.dll!NtGdiBRUSHOBJ_pvGetRbrush";
+ table[4766] = "gdi32.dll!NtGdiBRUSHOBJ_hGetColorTransform";
+ table[4767] = "gdi32.dll!NtGdiXFORMOBJ_bApplyXform";
+ table[4769] = "gdi32.dll!NtGdiFONTOBJ_vGetInfo";
+ table[4771] = "gdi32.dll!NtGdiFONTOBJ_cGetGlyphs";
+ table[4772] = "gdi32.dll!NtGdiFONTOBJ_pifi";
+ table[4773] = "gdi32.dll!NtGdiFONTOBJ_pfdg";
+ table[4774] = "gdi32.dll!NtGdiFONTOBJ_pQueryGlyphAttrs";
+ table[4775] = "gdi32.dll!NtGdiFONTOBJ_pvTrueTypeFontFile";
+ table[4776] = "gdi32.dll!NtGdiFONTOBJ_cGetAllGlyphHandles";
+ table[4777] = "gdi32.dll!NtGdiSTROBJ_bEnum";
+ table[4778] = "gdi32.dll!NtGdiSTROBJ_bEnumPositionsOnly";
+ table[4779] = "gdi32.dll!NtGdiSTROBJ_bGetAdvanceWidths";
+ table[4780] = "gdi32.dll!NtGdiSTROBJ_vEnumStart";
+ table[4781] = "gdi32.dll!NtGdiSTROBJ_dwGetCodePage";
+ table[4782] = "gdi32.dll!NtGdiPATHOBJ_vGetBounds";
+ table[4783] = "gdi32.dll!NtGdiPATHOBJ_bEnum";
+ table[4784] = "gdi32.dll!NtGdiPATHOBJ_vEnumStart";
+ table[4785] = "gdi32.dll!NtGdiPATHOBJ_vEnumStartClipLines";
+ table[4786] = "gdi32.dll!NtGdiPATHOBJ_bEnumClipLines";
+ table[4787] = "gdi32.dll!NtGdiGetDhpdev";
+ table[4788] = "gdi32.dll!NtGdiEngCheckAbort";
+ table[4789] = "gdi32.dll!NtGdiHT_Get8BPPFormatPalette";
+ table[4790] = "gdi32.dll!NtGdiHT_Get8BPPMaskPalette";
+ table[4791] = "gdi32.dll!NtGdiUpdateTransform";
+ table[4793] = "gdi32.dll!NtGdiBRUSHOBJ_DeleteRbrush";
+ table[4794] = "gdi32.dll!NtGdiUMPDEngFreeUserMem";
+ table[4808] = "gdi32.dll!NtGdiDdDDICreateSynchronizationObject";
+ table[4809] = "gdi32.dll!NtGdiDdDDIDestroySynchronizationObject";
+ table[4810] = "gdi32.dll!NtGdiDdDDIWaitForSynchronizationObject";
+ table[4811] = "gdi32.dll!NtGdiDdDDISignalSynchronizationObject";
+ table[4812] = "gdi32.dll!NtGdiDdDDIGetRuntimeData";
+ table[4818] = "gdi32.dll!NtGdiDdDDIGetMultisampleMethodList";
+ table[4826] = "gdi32.dll!NtGdiDdDDIQueryStatistics";
+ table[4829] = "gdi32.dll!NtGdiDdDDICreateOverlay";
+ table[4830] = "gdi32.dll!NtGdiDdDDIUpdateOverlay";
+ table[4831] = "gdi32.dll!NtGdiDdDDIFlipOverlay";
+ table[4832] = "gdi32.dll!NtGdiDdDDIDestroyOverlay";
+ table[4834] = "gdi32.dll!NtGdiDdDDISetGammaRamp";
+ table[4839] = "gdi32.dll!NtGdiDdDDIGetContextSchedulingPriority";
+ table[4841] = "gdi32.dll!NtGdiDdDDIGetProcessSchedulingPriorityClass";
+ table[4842] = "gdi32.dll!NtGdiDdDDIReleaseProcessVidPnSourceOwners";
+ table[4843] = "gdi32.dll!NtGdiDdDDIGetScanLine";
+ table[4845] = "gdi32.dll!NtGdiDdDDIPollDisplayChildren";
+ table[4846] = "gdi32.dll!NtGdiDdDDIInvalidateActiveVidPn";
+ table[4847] = "gdi32.dll!NtGdiDdDDICheckOcclusion";
+ table[4848] = "gdi32.dll!NtGdiDdDDIWaitForIdle";
+ table[4851] = "gdi32.dll!NtGdiDdDDISetDisplayPrivateDriverFormat";
+ table[4852] = "gdi32.dll!NtGdiDdDDISharedPrimaryLockNotification";
+ table[4853] = "gdi32.dll!NtGdiDdDDISharedPrimaryUnLockNotification";
+ table[4856] = "gdi32.dll!NtGdiGetNumberOfPhysicalMonitors";
+ table[4857] = "gdi32.dll!NtGdiGetPhysicalMonitors";
+ table[4858] = "gdi32.dll!NtGdiGetPhysicalMonitorDescription";
+ table[4859] = "gdi32.dll!NtGdiDestroyPhysicalMonitor";
+ table[4860] = "gdi32.dll!NtGdiDDCCIGetVCPFeature";
+ table[4861] = "gdi32.dll!NtGdiDDCCISetVCPFeature";
+ table[4862] = "gdi32.dll!NtGdiDDCCISaveCurrentSettings";
+ table[4863] = "gdi32.dll!NtGdiDDCCIGetCapabilitiesStringLength";
+ table[4864] = "gdi32.dll!NtGdiDDCCIGetCapabilitiesString";
+ table[4865] = "gdi32.dll!NtGdiDDCCIGetTimingReport";
+ table[0] = "ntdll.dll!NtAcceptConnectPort";
+ table[1] = "ntdll.dll!NtAccessCheck";
+ table[2] = "ntdll.dll!ZwAccessCheckAndAuditAlarm";
+ table[3] = "ntdll.dll!NtAccessCheckByType";
+ table[4] = "ntdll.dll!NtAccessCheckByTypeAndAuditAlarm";
+ table[5] = "ntdll.dll!NtAccessCheckByTypeResultList";
+ table[6] = "ntdll.dll!NtAccessCheckByTypeResultListAndAuditAlarm";
+ table[7] = "ntdll.dll!ZwAccessCheckByTypeResultListAndAuditAlarmByHandle";
+ table[8] = "ntdll.dll!NtAddAtom";
+ table[9] = "ntdll.dll!ZwAddBootEntry";
+ table[10] = "ntdll.dll!NtAddDriverEntry";
+ table[11] = "ntdll.dll!ZwAdjustGroupsToken";
+ table[12] = "ntdll.dll!ZwAdjustPrivilegesToken";
+ table[13] = "ntdll.dll!NtAlertResumeThread";
+ table[14] = "ntdll.dll!NtAlertThread";
+ table[15] = "ntdll.dll!ZwAllocateLocallyUniqueId";
+ table[16] = "ntdll.dll!NtAllocateUserPhysicalPages";
+ table[17] = "ntdll.dll!NtAllocateUuids";
+ table[18] = "ntdll.dll!NtAllocateVirtualMemory";
+ table[19] = "ntdll.dll!NtAlpcAcceptConnectPort";
+ table[20] = "ntdll.dll!ZwAlpcCancelMessage";
+ table[21] = "ntdll.dll!ZwAlpcConnectPort";
+ table[22] = "ntdll.dll!ZwAlpcCreatePort";
+ table[23] = "ntdll.dll!NtAlpcCreatePortSection";
+ table[24] = "ntdll.dll!ZwAlpcCreateResourceReserve";
+ table[25] = "ntdll.dll!ZwAlpcCreateSectionView";
+ table[26] = "ntdll.dll!ZwAlpcCreateSecurityContext";
+ table[27] = "ntdll.dll!ZwAlpcDeletePortSection";
+ table[28] = "ntdll.dll!NtAlpcDeleteResourceReserve";
+ table[29] = "ntdll.dll!NtAlpcDeleteSectionView";
+ table[30] = "ntdll.dll!NtAlpcDeleteSecurityContext";
+ table[31] = "ntdll.dll!NtAlpcDisconnectPort";
+ table[32] = "ntdll.dll!ZwAlpcImpersonateClientOfPort";
+ table[33] = "ntdll.dll!ZwAlpcOpenSenderProcess";
+ table[34] = "ntdll.dll!ZwAlpcOpenSenderThread";
+ table[35] = "ntdll.dll!ZwAlpcQueryInformation";
+ table[36] = "ntdll.dll!ZwAlpcQueryInformationMessage";
+ table[37] = "ntdll.dll!NtAlpcRevokeSecurityContext";
+ table[38] = "ntdll.dll!NtAlpcSendWaitReceivePort";
+ table[39] = "ntdll.dll!NtAlpcSetInformation";
+ table[40] = "ntdll.dll!NtApphelpCacheControl";
+ table[41] = "ntdll.dll!ZwAreMappedFilesTheSame";
+ table[42] = "ntdll.dll!ZwAssignProcessToJobObject";
+ table[43] = "ntdll.dll!ZwCallbackReturn";
+ table[44] = "ntdll.dll!NtCancelDeviceWakeupRequest";
+ table[45] = "ntdll.dll!ZwCancelIoFile";
+ table[46] = "ntdll.dll!ZwCancelTimer";
+ table[47] = "ntdll.dll!NtClearEvent";
+ table[48] = "ntdll.dll!NtClose";
+ table[49] = "ntdll.dll!ZwCloseObjectAuditAlarm";
+ table[50] = "ntdll.dll!NtCompactKeys";
+ table[51] = "ntdll.dll!ZwCompareTokens";
+ table[52] = "ntdll.dll!NtCompleteConnectPort";
+ table[53] = "ntdll.dll!ZwCompressKey";
+ table[54] = "ntdll.dll!NtConnectPort";
+ table[55] = "ntdll.dll!ZwContinue";
+ table[56] = "ntdll.dll!ZwCreateDebugObject";
+ table[57] = "ntdll.dll!ZwCreateDirectoryObject";
+ table[58] = "ntdll.dll!NtCreateEvent";
+ table[59] = "ntdll.dll!NtCreateEventPair";
+ table[60] = "ntdll.dll!NtCreateFile";
+ table[61] = "ntdll.dll!NtCreateIoCompletion";
+ table[62] = "ntdll.dll!ZwCreateJobObject";
+ table[63] = "ntdll.dll!NtCreateJobSet";
+ table[64] = "ntdll.dll!ZwCreateKey";
+ table[65] = "ntdll.dll!NtCreateKeyTransacted";
+ table[66] = "ntdll.dll!ZwCreateMailslotFile";
+ table[67] = "ntdll.dll!ZwCreateMutant";
+ table[68] = "ntdll.dll!ZwCreateNamedPipeFile";
+ table[69] = "ntdll.dll!NtCreatePrivateNamespace";
+ table[70] = "ntdll.dll!NtCreatePagingFile";
+ table[71] = "ntdll.dll!ZwCreatePort";
+ table[72] = "ntdll.dll!ZwCreateProcess";
+ table[73] = "ntdll.dll!ZwCreateProcessEx";
+ table[74] = "ntdll.dll!ZwCreateProfile";
+ table[75] = "ntdll.dll!NtCreateSection";
+ table[76] = "ntdll.dll!NtCreateSemaphore";
+ table[77] = "ntdll.dll!ZwCreateSymbolicLinkObject";
+ table[78] = "ntdll.dll!NtCreateThread";
+ table[79] = "ntdll.dll!ZwCreateTimer";
+ table[80] = "ntdll.dll!NtCreateToken";
+ table[81] = "ntdll.dll!NtCreateTransaction";
+ table[82] = "ntdll.dll!ZwOpenTransaction";
+ table[83] = "ntdll.dll!ZwQueryInformationTransaction";
+ table[84] = "ntdll.dll!NtQueryInformationTransactionManager";
+ table[85] = "ntdll.dll!NtPrePrepareEnlistment";
+ table[86] = "ntdll.dll!ZwPrepareEnlistment";
+ table[87] = "ntdll.dll!NtCommitEnlistment";
+ table[88] = "ntdll.dll!ZwReadOnlyEnlistment";
+ table[89] = "ntdll.dll!ZwRollbackComplete";
+ table[90] = "ntdll.dll!NtRollbackEnlistment";
+ table[91] = "ntdll.dll!NtCommitTransaction";
+ table[92] = "ntdll.dll!NtRollbackTransaction";
+ table[93] = "ntdll.dll!ZwPrePrepareComplete";
+ table[94] = "ntdll.dll!NtPrepareComplete";
+ table[95] = "ntdll.dll!ZwCommitComplete";
+ table[96] = "ntdll.dll!ZwSinglePhaseReject";
+ table[97] = "ntdll.dll!ZwSetInformationTransaction";
+ table[98] = "ntdll.dll!ZwSetInformationTransactionManager";
+ table[99] = "ntdll.dll!ZwSetInformationResourceManager";
+ table[100] = "ntdll.dll!ZwCreateTransactionManager";
+ table[101] = "ntdll.dll!ZwOpenTransactionManager";
+ table[102] = "ntdll.dll!NtRenameTransactionManager";
+ table[103] = "ntdll.dll!NtRollforwardTransactionManager";
+ table[104] = "ntdll.dll!NtRecoverEnlistment";
+ table[105] = "ntdll.dll!NtRecoverResourceManager";
+ table[106] = "ntdll.dll!ZwRecoverTransactionManager";
+ table[107] = "ntdll.dll!ZwCreateResourceManager";
+ table[108] = "ntdll.dll!ZwOpenResourceManager";
+ table[109] = "ntdll.dll!ZwGetNotificationResourceManager";
+ table[110] = "ntdll.dll!ZwQueryInformationResourceManager";
+ table[111] = "ntdll.dll!ZwCreateEnlistment";
+ table[112] = "ntdll.dll!ZwOpenEnlistment";
+ table[113] = "ntdll.dll!NtSetInformationEnlistment";
+ table[114] = "ntdll.dll!ZwQueryInformationEnlistment";
+ table[115] = "ntdll.dll!ZwCreateWaitablePort";
+ table[116] = "ntdll.dll!NtDebugActiveProcess";
+ table[117] = "ntdll.dll!ZwDebugContinue";
+ table[118] = "ntdll.dll!ZwDelayExecution";
+ table[119] = "ntdll.dll!ZwDeleteAtom";
+ table[120] = "ntdll.dll!NtDeleteBootEntry";
+ table[121] = "ntdll.dll!ZwDeleteDriverEntry";
+ table[122] = "ntdll.dll!NtDeleteFile";
+ table[123] = "ntdll.dll!ZwDeleteKey";
+ table[124] = "ntdll.dll!NtDeletePrivateNamespace";
+ table[125] = "ntdll.dll!NtDeleteObjectAuditAlarm";
+ table[126] = "ntdll.dll!NtDeleteValueKey";
+ table[127] = "ntdll.dll!ZwDeviceIoControlFile";
+ table[128] = "ntdll.dll!NtDisplayString";
+ table[129] = "ntdll.dll!ZwDuplicateObject";
+ table[130] = "ntdll.dll!NtDuplicateToken";
+ table[131] = "ntdll.dll!ZwEnumerateBootEntries";
+ table[132] = "ntdll.dll!NtEnumerateDriverEntries";
+ table[133] = "ntdll.dll!ZwEnumerateKey";
+ table[134] = "ntdll.dll!ZwEnumerateSystemEnvironmentValuesEx";
+ table[135] = "ntdll.dll!ZwEnumerateTransactionObject";
+ table[136] = "ntdll.dll!NtEnumerateValueKey";
+ table[137] = "ntdll.dll!ZwExtendSection";
+ table[138] = "ntdll.dll!NtFilterToken";
+ table[139] = "ntdll.dll!NtFindAtom";
+ table[140] = "ntdll.dll!ZwFlushBuffersFile";
+ table[141] = "ntdll.dll!ZwFlushInstructionCache";
+ table[142] = "ntdll.dll!NtFlushKey";
+ table[143] = "ntdll.dll!ZwFlushProcessWriteBuffers";
+ table[144] = "ntdll.dll!ZwFlushVirtualMemory";
+ table[145] = "ntdll.dll!NtFlushWriteBuffer";
+ table[146] = "ntdll.dll!NtFreeUserPhysicalPages";
+ table[147] = "ntdll.dll!NtFreeVirtualMemory";
+ table[148] = "ntdll.dll!NtFreezeRegistry";
+ table[149] = "ntdll.dll!ZwFreezeTransactions";
+ table[150] = "ntdll.dll!NtFsControlFile";
+ table[151] = "ntdll.dll!NtGetContextThread";
+ table[152] = "ntdll.dll!NtGetDevicePowerState";
+ table[153] = "ntdll.dll!NtGetNlsSectionPtr";
+ table[154] = "ntdll.dll!ZwGetPlugPlayEvent";
+ table[155] = "ntdll.dll!NtGetWriteWatch";
+ table[156] = "ntdll.dll!NtImpersonateAnonymousToken";
+ table[157] = "ntdll.dll!ZwImpersonateClientOfPort";
+ table[158] = "ntdll.dll!ZwImpersonateThread";
+ table[159] = "ntdll.dll!ZwInitializeNlsFiles";
+ table[160] = "ntdll.dll!ZwInitializeRegistry";
+ table[161] = "ntdll.dll!NtInitiatePowerAction";
+ table[162] = "ntdll.dll!ZwIsProcessInJob";
+ table[163] = "ntdll.dll!NtIsSystemResumeAutomatic";
+ table[164] = "ntdll.dll!ZwListenPort";
+ table[165] = "ntdll.dll!NtLoadDriver";
+ table[166] = "ntdll.dll!NtLoadKey";
+ table[167] = "ntdll.dll!NtLoadKey2";
+ table[168] = "ntdll.dll!NtLoadKeyEx";
+ table[169] = "ntdll.dll!NtLockFile";
+ table[170] = "ntdll.dll!ZwLockProductActivationKeys";
+ table[171] = "ntdll.dll!NtLockRegistryKey";
+ table[172] = "ntdll.dll!ZwLockVirtualMemory";
+ table[173] = "ntdll.dll!ZwMakePermanentObject";
+ table[174] = "ntdll.dll!NtMakeTemporaryObject";
+ table[175] = "ntdll.dll!NtMapUserPhysicalPages";
+ table[176] = "ntdll.dll!ZwMapUserPhysicalPagesScatter";
+ table[177] = "ntdll.dll!ZwMapViewOfSection";
+ table[178] = "ntdll.dll!NtModifyBootEntry";
+ table[179] = "ntdll.dll!ZwModifyDriverEntry";
+ table[180] = "ntdll.dll!NtNotifyChangeDirectoryFile";
+ table[181] = "ntdll.dll!NtNotifyChangeKey";
+ table[182] = "ntdll.dll!NtNotifyChangeMultipleKeys";
+ table[183] = "ntdll.dll!ZwOpenDirectoryObject";
+ table[184] = "ntdll.dll!NtOpenEvent";
+ table[185] = "ntdll.dll!NtOpenEventPair";
+ table[186] = "ntdll.dll!NtOpenFile";
+ table[187] = "ntdll.dll!ZwOpenIoCompletion";
+ table[188] = "ntdll.dll!ZwOpenJobObject";
+ table[189] = "ntdll.dll!ZwOpenKey";
+ table[190] = "ntdll.dll!NtOpenKeyTransacted";
+ table[191] = "ntdll.dll!NtOpenMutant";
+ table[192] = "ntdll.dll!NtOpenPrivateNamespace";
+ table[193] = "ntdll.dll!ZwOpenObjectAuditAlarm";
+ table[194] = "ntdll.dll!ZwOpenProcess";
+ table[195] = "ntdll.dll!ZwOpenProcessToken";
+ table[196] = "ntdll.dll!ZwOpenProcessTokenEx";
+ table[197] = "ntdll.dll!NtOpenSection";
+ table[198] = "ntdll.dll!NtOpenSemaphore";
+ table[199] = "ntdll.dll!NtOpenSession";
+ table[200] = "ntdll.dll!NtOpenSymbolicLinkObject";
+ table[201] = "ntdll.dll!ZwOpenThread";
+ table[202] = "ntdll.dll!NtOpenThreadToken";
+ table[203] = "ntdll.dll!NtOpenThreadTokenEx";
+ table[204] = "ntdll.dll!ZwOpenTimer";
+ table[205] = "ntdll.dll!NtPlugPlayControl";
+ table[206] = "ntdll.dll!ZwPowerInformation";
+ table[207] = "ntdll.dll!ZwPrivilegeCheck";
+ table[208] = "ntdll.dll!ZwPrivilegeObjectAuditAlarm";
+ table[209] = "ntdll.dll!NtPrivilegedServiceAuditAlarm";
+ table[210] = "ntdll.dll!ZwProtectVirtualMemory";
+ table[211] = "ntdll.dll!ZwPulseEvent";
+ table[212] = "ntdll.dll!ZwQueryAttributesFile";
+ table[213] = "ntdll.dll!ZwQueryBootEntryOrder";
+ table[214] = "ntdll.dll!ZwQueryBootOptions";
+ table[215] = "ntdll.dll!NtQueryDebugFilterState";
+ table[216] = "ntdll.dll!NtQueryDefaultLocale";
+ table[217] = "ntdll.dll!ZwQueryDefaultUILanguage";
+ table[218] = "ntdll.dll!ZwQueryDirectoryFile";
+ table[219] = "ntdll.dll!ZwQueryDirectoryObject";
+ table[220] = "ntdll.dll!NtQueryDriverEntryOrder";
+ table[221] = "ntdll.dll!ZwQueryEaFile";
+ table[222] = "ntdll.dll!NtQueryEvent";
+ table[223] = "ntdll.dll!ZwQueryFullAttributesFile";
+ table[224] = "ntdll.dll!NtQueryInformationAtom";
+ table[225] = "ntdll.dll!ZwQueryInformationFile";
+ table[226] = "ntdll.dll!ZwQueryInformationJobObject";
+ table[227] = "ntdll.dll!ZwQueryInformationPort";
+ table[228] = "ntdll.dll!ZwQueryInformationProcess";
+ table[229] = "ntdll.dll!NtQueryInformationThread";
+ table[230] = "ntdll.dll!ZwQueryInformationToken";
+ table[231] = "ntdll.dll!NtQueryInstallUILanguage";
+ table[232] = "ntdll.dll!NtQueryIntervalProfile";
+ table[233] = "ntdll.dll!NtQueryIoCompletion";
+ table[234] = "ntdll.dll!ZwQueryKey";
+ table[235] = "ntdll.dll!NtQueryMultipleValueKey";
+ table[236] = "ntdll.dll!NtQueryMutant";
+ table[237] = "ntdll.dll!NtQueryObject";
+ table[238] = "ntdll.dll!NtQueryOpenSubKeys";
+ table[239] = "ntdll.dll!NtQueryOpenSubKeysEx";
+ table[240] = "ntdll.dll!NtQueryPerformanceCounter";
+ table[241] = "ntdll.dll!ZwQueryQuotaInformationFile";
+ table[242] = "ntdll.dll!ZwQuerySection";
+ table[243] = "ntdll.dll!NtQuerySecurityObject";
+ table[244] = "ntdll.dll!ZwQuerySemaphore";
+ table[245] = "ntdll.dll!ZwQuerySymbolicLinkObject";
+ table[246] = "ntdll.dll!ZwQuerySystemEnvironmentValue";
+ table[247] = "ntdll.dll!ZwQuerySystemEnvironmentValueEx";
+ table[248] = "ntdll.dll!NtQuerySystemInformation";
+ table[249] = "ntdll.dll!NtQuerySystemTime";
+ table[250] = "ntdll.dll!ZwQueryTimer";
+ table[251] = "ntdll.dll!NtQueryTimerResolution";
+ table[252] = "ntdll.dll!ZwQueryValueKey";
+ table[253] = "ntdll.dll!NtQueryVirtualMemory";
+ table[254] = "ntdll.dll!NtQueryVolumeInformationFile";
+ table[255] = "ntdll.dll!NtQueueApcThread";
+ table[256] = "ntdll.dll!ZwRaiseException";
+ table[257] = "ntdll.dll!ZwRaiseHardError";
+ table[258] = "ntdll.dll!NtReadFile";
+ table[259] = "ntdll.dll!NtReadFileScatter";
+ table[260] = "ntdll.dll!ZwReadRequestData";
+ table[261] = "ntdll.dll!NtReadVirtualMemory";
+ table[262] = "ntdll.dll!ZwRegisterThreadTerminatePort";
+ table[263] = "ntdll.dll!ZwReleaseMutant";
+ table[264] = "ntdll.dll!NtReleaseSemaphore";
+ table[265] = "ntdll.dll!ZwRemoveIoCompletion";
+ table[266] = "ntdll.dll!ZwRemoveProcessDebug";
+ table[267] = "ntdll.dll!ZwRenameKey";
+ table[268] = "ntdll.dll!ZwReplaceKey";
+ table[269] = "ntdll.dll!NtReplacePartitionUnit";
+ table[270] = "ntdll.dll!ZwReplyPort";
+ table[271] = "ntdll.dll!NtReplyWaitReceivePort";
+ table[272] = "ntdll.dll!NtReplyWaitReceivePortEx";
+ table[273] = "ntdll.dll!NtReplyWaitReplyPort";
+ table[274] = "ntdll.dll!ZwRequestDeviceWakeup";
+ table[275] = "ntdll.dll!ZwRequestPort";
+ table[276] = "ntdll.dll!NtRequestWaitReplyPort";
+ table[277] = "ntdll.dll!ZwRequestWakeupLatency";
+ table[278] = "ntdll.dll!NtResetEvent";
+ table[279] = "ntdll.dll!ZwResetWriteWatch";
+ table[280] = "ntdll.dll!NtRestoreKey";
+ table[281] = "ntdll.dll!ZwResumeProcess";
+ table[282] = "ntdll.dll!ZwResumeThread";
+ table[283] = "ntdll.dll!NtSaveKey";
+ table[284] = "ntdll.dll!NtSaveKeyEx";
+ table[285] = "ntdll.dll!NtSaveMergedKeys";
+ table[286] = "ntdll.dll!NtSecureConnectPort";
+ table[287] = "ntdll.dll!ZwSetBootEntryOrder";
+ table[288] = "ntdll.dll!ZwSetBootOptions";
+ table[289] = "ntdll.dll!ZwSetContextThread";
+ table[290] = "ntdll.dll!NtSetDebugFilterState";
+ table[291] = "ntdll.dll!NtSetDefaultHardErrorPort";
+ table[292] = "ntdll.dll!NtSetDefaultLocale";
+ table[293] = "ntdll.dll!ZwSetDefaultUILanguage";
+ table[294] = "ntdll.dll!NtSetDriverEntryOrder";
+ table[295] = "ntdll.dll!ZwSetEaFile";
+ table[296] = "ntdll.dll!NtSetEvent";
+ table[297] = "ntdll.dll!NtSetEventBoostPriority";
+ table[298] = "ntdll.dll!NtSetHighEventPair";
+ table[299] = "ntdll.dll!NtSetHighWaitLowEventPair";
+ table[300] = "ntdll.dll!ZwSetInformationDebugObject";
+ table[301] = "ntdll.dll!ZwSetInformationFile";
+ table[302] = "ntdll.dll!ZwSetInformationJobObject";
+ table[303] = "ntdll.dll!ZwSetInformationKey";
+ table[304] = "ntdll.dll!ZwSetInformationObject";
+ table[305] = "ntdll.dll!ZwSetInformationProcess";
+ table[306] = "ntdll.dll!ZwSetInformationThread";
+ table[307] = "ntdll.dll!ZwSetInformationToken";
+ table[308] = "ntdll.dll!NtSetIntervalProfile";
+ table[309] = "ntdll.dll!NtSetIoCompletion";
+ table[310] = "ntdll.dll!ZwSetLdtEntries";
+ table[311] = "ntdll.dll!ZwSetLowEventPair";
+ table[312] = "ntdll.dll!ZwSetLowWaitHighEventPair";
+ table[313] = "ntdll.dll!ZwSetQuotaInformationFile";
+ table[314] = "ntdll.dll!NtSetSecurityObject";
+ table[315] = "ntdll.dll!ZwSetSystemEnvironmentValue";
+ table[316] = "ntdll.dll!ZwSetSystemEnvironmentValueEx";
+ table[317] = "ntdll.dll!ZwSetSystemInformation";
+ table[318] = "ntdll.dll!ZwSetSystemPowerState";
+ table[319] = "ntdll.dll!ZwSetSystemTime";
+ table[320] = "ntdll.dll!ZwSetThreadExecutionState";
+ table[321] = "ntdll.dll!ZwSetTimer";
+ table[322] = "ntdll.dll!NtSetTimerResolution";
+ table[323] = "ntdll.dll!ZwSetUuidSeed";
+ table[324] = "ntdll.dll!ZwSetValueKey";
+ table[325] = "ntdll.dll!NtSetVolumeInformationFile";
+ table[326] = "ntdll.dll!ZwShutdownSystem";
+ table[327] = "ntdll.dll!ZwSignalAndWaitForSingleObject";
+ table[328] = "ntdll.dll!NtStartProfile";
+ table[329] = "ntdll.dll!ZwStopProfile";
+ table[330] = "ntdll.dll!ZwSuspendProcess";
+ table[331] = "ntdll.dll!ZwSuspendThread";
+ table[332] = "ntdll.dll!NtSystemDebugControl";
+ table[333] = "ntdll.dll!ZwTerminateJobObject";
+ table[334] = "ntdll.dll!ZwTerminateProcess";
+ table[335] = "ntdll.dll!ZwTerminateThread";
+ table[336] = "ntdll.dll!NtTestAlert";
+ table[337] = "ntdll.dll!ZwThawRegistry";
+ table[338] = "ntdll.dll!NtThawTransactions";
+ table[339] = "ntdll.dll!NtTraceEvent";
+ table[340] = "ntdll.dll!ZwTraceControl";
+ table[341] = "ntdll.dll!NtTranslateFilePath";
+ table[342] = "ntdll.dll!ZwUnloadDriver";
+ table[343] = "ntdll.dll!NtUnloadKey";
+ table[344] = "ntdll.dll!ZwUnloadKey2";
+ table[345] = "ntdll.dll!ZwUnloadKeyEx";
+ table[346] = "ntdll.dll!ZwUnlockFile";
+ table[347] = "ntdll.dll!NtUnlockVirtualMemory";
+ table[348] = "ntdll.dll!NtUnmapViewOfSection";
+ table[349] = "ntdll.dll!NtVdmControl";
+ table[350] = "ntdll.dll!NtWaitForDebugEvent";
+ table[351] = "ntdll.dll!NtWaitForMultipleObjects";
+ table[352] = "ntdll.dll!ZwWaitForSingleObject";
+ table[353] = "ntdll.dll!ZwWaitHighEventPair";
+ table[354] = "ntdll.dll!NtWaitLowEventPair";
+ table[355] = "ntdll.dll!NtWriteFile";
+ table[356] = "ntdll.dll!NtWriteFileGather";
+ table[357] = "ntdll.dll!NtWriteRequestData";
+ table[358] = "ntdll.dll!NtWriteVirtualMemory";
+ table[359] = "ntdll.dll!ZwYieldExecution";
+ table[360] = "ntdll.dll!ZwCreateKeyedEvent";
+ table[361] = "ntdll.dll!NtOpenKeyedEvent";
+ table[362] = "ntdll.dll!NtReleaseKeyedEvent";
+ table[363] = "ntdll.dll!NtWaitForKeyedEvent";
+ table[364] = "ntdll.dll!ZwQueryPortInformationProcess";
+ table[365] = "ntdll.dll!NtGetCurrentProcessorNumber";
+ table[366] = "ntdll.dll!NtWaitForMultipleObjects32";
+ table[367] = "ntdll.dll!ZwGetNextProcess";
+ table[368] = "ntdll.dll!ZwGetNextThread";
+ table[369] = "ntdll.dll!NtCancelIoFileEx";
+ table[370] = "ntdll.dll!NtCancelSynchronousIoFile";
+ table[371] = "ntdll.dll!ZwRemoveIoCompletionEx";
+ table[372] = "ntdll.dll!ZwRegisterProtocolAddressInformation";
+ table[373] = "ntdll.dll!NtPropagationComplete";
+ table[374] = "ntdll.dll!ZwPropagationFailed";
+ table[375] = "ntdll.dll!NtCreateWorkerFactory";
+ table[376] = "ntdll.dll!ZwReleaseWorkerFactoryWorker";
+ table[377] = "ntdll.dll!NtWaitForWorkViaWorkerFactory";
+ table[378] = "ntdll.dll!ZwSetInformationWorkerFactory";
+ table[379] = "ntdll.dll!ZwQueryInformationWorkerFactory";
+ table[380] = "ntdll.dll!NtWorkerFactoryWorkerReady";
+ table[381] = "ntdll.dll!NtShutdownWorkerFactory";
+ table[382] = "ntdll.dll!NtCreateThreadEx";
+ table[383] = "ntdll.dll!NtCreateUserProcess";
+ table[384] = "ntdll.dll!NtQueryLicenseValue";
+ table[385] = "ntdll.dll!ZwMapCMFModule";
+ table[386] = "ntdll.dll!ZwIsUILanguageComitted";
+ table[387] = "ntdll.dll!ZwFlushInstallUILanguage";
+ table[388] = "ntdll.dll!NtGetMUIRegistryInfo";
+ table[389] = "ntdll.dll!ZwAcquireCMFViewOwnership";
+ table[390] = "ntdll.dll!NtReleaseCMFViewOwnership";
+ table[4545] = "imm32.dll!NtUserGetThreadState";
+ table[4520] = "imm32.dll!NtUserGetImeInfoEx";
+ table[4600] = "imm32.dll!NtUserQueryWindow";
+ table[4598] = "imm32.dll!NtUserQueryInputContext";
+ table[4581] = "imm32.dll!NtUserNotifyIMEStatus";
+ table[4412] = "imm32.dll!NtUserAssociateInputContext";
+ table[4429] = "imm32.dll!NtUserCallOneParam";
+ table[4463] = "imm32.dll!NtUserDisableThreadIme";
+ table[4635] = "imm32.dll!NtUserSetImeInfoEx";
+ table[4697] = "imm32.dll!NtUserUpdateInputContext";
+ table[4417] = "imm32.dll!NtUserBuildHimcList";
+ table[4704] = "imm32.dll!NtUserValidateHandleSecure";
+ table[4450] = "imm32.dll!NtUserCreateInputContext";
+ table[4460] = "imm32.dll!NtUserDestroyInputContext";
+ table[4492] = "imm32.dll!NtUserGetAppImeLevel";
+ table[4519] = "imm32.dll!NtUserGetImeHotKey";
+ table[4623] = "imm32.dll!NtUserSetAppImeLevel";
+ table[4657] = "imm32.dll!NtUserSetThreadLayoutHandles";
+ table[4560] = "user32.dll!NtUserInitializeClientPfnArrays";
+ table[4596] = "user32.dll!NtUserProcessConnect";
+ table[4453] = "user32.dll!NtUserCreateWindowStation";
+ table[4449] = "user32.dll!NtUserCreateDesktopEx";
+ table[4695] = "user32.dll!NtUserUnregisterUserApiHook";
+ table[4607] = "user32.dll!NtUserRegisterUserApiHook";
+ table[4634] = "user32.dll!NtUserSetImeHotKey";
+ table[4670] = "user32.dll!NtUserSetWindowStationUser";
+ table[4568] = "user32.dll!NtUserLoadKeyboardLayoutEx";
+ table[4702] = "user32.dll!NtUserUpdatePerUserSystemParameters";
+ table[4465] = "user32.dll!NtUserDoSoundConnect";
+ table[4720] = "user32.dll!NtUserRegisterSessionPort";
+ table[4423] = "user32.dll!NtUserCallHwndOpt";
+ table[4651] = "user32.dll!NtUserSetShellWindowEx";
+ table[4421] = "user32.dll!NtUserCallHwnd";
+ table[4723] = "user32.dll!NtUserDwmStartRedirection";
+ table[4609] = "user32.dll!NtUserRegisterRawInputDevices";
+ table[4495] = "user32.dll!NtUserGetCaretBlinkTime";
+ table[4681] = "user32.dll!NtUserThunkedMenuInfo";
+ table[4570] = "user32.dll!NtUserLockWindowUpdate";
+ table[4445] = "user32.dll!NtUserCopyAcceleratorTable";
+ table[4478] = "user32.dll!NtUserEndMenu";
+ table[4458] = "user32.dll!DestroyAcceleratorTable";
+ table[4625] = "user32.dll!NtUserSetClassLong";
+ table[4613] = "user32.dll!NtUserRemoveMenu";
+ table[4643] = "user32.dll!NtUserSetMenuDefaultItem";
+ table[4461] = "user32.dll!NtUserDestroyMenu";
+ table[4553] = "user32.dll!NtUserGhostWindowFromHungWindow";
+ table[4590] = "user32.dll!NtUserPaintMonitor";
+ table[4589] = "user32.dll!NtUserPaintDesktop";
+ table[4454] = "user32.dll!NtUserDdeInitialize";
+ table[4663] = "user32.dll!NtUserSetWindowPlacement";
+ table[4669] = "user32.dll!NtUserSetWindowsHookEx";
+ table[4457] = "user32.dll!NtUserDeleteMenu";
+ table[4565] = "user32.dll!NtUserInvalidateRgn";
+ table[4638] = "user32.dll!NtUserSetInformationThread";
+ table[4493] = "user32.dll!NtUserGetAsyncKeyState";
+ table[4434] = "user32.dll!NtUserCheckDesktopByThreadId";
+ table[4727] = "user32.dll!NtUserGetWindowMinimizeRect";
+ table[4672] = "user32.dll!NtUserSetWinEventHook";
+ table[4508] = "user32.dll!NtUserGetCPD";
+ table[4665] = "user32.dll!NtUserSetWindowRgn";
+ table[4569] = "user32.dll!NtUserLockWindowStation";
+ table[4485] = "user32.dll!NtUserFillWindow";
+ table[4677] = "user32.dll!NtUserSoundSentry";
+ table[4696] = "user32.dll!NtUserUnregisterHotKey";
+ table[4524] = "user32.dll!NtUserGetKeyboardState";
+ table[4691] = "user32.dll!NtUserUnhookWinEvent";
+ table[4621] = "user32.dll!NtUserSendInput";
+ table[4658] = "user32.dll!NtUserSetThreadState";
+ table[4624] = "user32.dll!NtUserSetCapture";
+ table[4633] = "user32.dll!NtUserSetFocus";
+ table[4636] = "user32.dll!NtUserSetImeOwnerWindow";
+ table[4425] = "user32.dll!NtUserCallHwndParamLock";
+ table[4686] = "user32.dll!NtUserCalcMenuBar";
+ table[4546] = "user32.dll!NtUserGetTitleBarInfo";
+ table[4512] = "user32.dll!NtUserGetDCEx";
+ table[4528] = "user32.dll!NtUserGetMenuBarInfo";
+ table[4678] = "user32.dll!NtUserSwitchDesktop";
+ table[4522] = "user32.dll!NtUserGetKeyboardLayoutList";
+ table[4675] = "user32.dll!NtUserShowWindow";
+ table[4660] = "user32.dll!NtUserSetProcessDPIAware";
+ table[4646] = "user32.dll!NtUserSetParent";
+ table[4693] = "user32.dll!NtUserUnlockWindowStation";
+ table[4684] = "user32.dll!NtUserTrackMouseEvent";
+ table[4608] = "user32.dll!NtUserRegisterHotKey";
+ table[4701] = "user32.dll!NtUserSetLayeredWindowAttributes";
+ table[4580] = "user32.dll!NtUserMoveWindow";
+ table[4699] = "user32.dll!NtUserUpdateLayeredWindow";
+ table[4542] = "user32.dll!NtUserGetScrollBarInfo";
+ table[4447] = "user32.dll!NtUserCreateAcceleratorTable";
+ table[4630] = "user32.dll!NtUserSetCursor";
+ table[4586] = "user32.dll!NtUserOpenInputDesktop";
+ table[4514] = "user32.dll!NtUserGetForegroundWindow";
+ table[4548] = "user32.dll!GetUpdateRect";
+ table[4656] = "user32.dll!NtUserSetThreadDesktop";
+ table[4536] = "user32.dll!NtUserGetProcessWindowStation";
+ table[4647] = "user32.dll!NtUserSetProcessWindowStation";
+ table[4605] = "user32.dll!NtUserRegisterClassExWOW";
+ table[4494] = "user32.dll!NtUserGetAtomName";
+ table[4697] = "user32.dll!NtUserUpdateInputContext";
+ table[4661] = "user32.dll!NtUserSetWindowFNID";
+ table[4498] = "user32.dll!NtUserGetClassName";
+ table[4516] = "user32.dll!NtUserGetGUIThreadInfo";
+ table[4585] = "user32.dll!NtUserOpenDesktop";
+ table[4419] = "user32.dll!NtUserBuildNameList";
+ table[4617] = "user32.dll!NtUserSBGetParms";
+ table[4674] = "user32.dll!NtUserShowScrollBar";
+ table[4588] = "user32.dll!NtUserOpenWindowStation";
+ table[4694] = "user32.dll!NtUserUnregisterClass";
+ table[4481] = "user32.dll!NtUserEnumDisplayMonitors";
+ table[4462] = "user32.dll!NtUserDestroyWindow";
+ table[4441] = "user32.dll!NtUserCloseDesktop";
+ table[4459] = "user32.dll!NtUserDestroyCursor";
+ table[4442] = "user32.dll!NtUserCloseWindowStation";
+ table[4418] = "user32.dll!NtUserBuildHwndList";
+ table[4594] = "user32.dll!NtUserPostThreadMessage";
+ table[4614] = "user32.dll!NtUserRemoveProp";
+ table[4662] = "user32.dll!NtUserSetWindowLong";
+ table[4664] = "user32.dll!NtUserSetWindowPos";
+ table[4422] = "user32.dll!NtUserCallHwndLock";
+ table[4649] = "user32.dll!NtUserSetProp";
+ table[4477] = "user32.dll!NtUserEndDeferWindowPosEx";
+ table[4455] = "user32.dll!NtUserDeferWindowPos";
+ table[4632] = "user32.dll!NtUserSetCursorIconData";
+ table[4486] = "user32.dll!NtUserFindExistingCursorIcon";
+ table[4533] = "user32.dll!NtUserGetObjectInformation";
+ table[4452] = "user32.dll!NtUserCreateWindowEx";
+ table[4682] = "user32.dll!NtUserThunkedMenuItemInfo";
+ table[4543] = "user32.dll!NtUserGetSystemMenu";
+ table[4676] = "user32.dll!NtUserShowWindowAsync";
+ table[4600] = "user32.dll!NtUserQueryWindow";
+ table[4517] = "user32.dll!NtUserGetIconInfo";
+ table[4518] = "user32.dll!NtUserGetIconSize";
+ table[4583] = "user32.dll!NtUserNotifyWinEvent";
+ table[4562] = "user32.dll!NtUserInternalGetWindowText";
+ table[4666] = "user32.dll!NtUserGetWindowRgnEx";
+ table[4472] = "user32.dll!NtUserDrawIconEx";
+ table[4424] = "user32.dll!NtUserCallHwndParam";
+ table[4409] = "user32.dll!NtUserActivateKeyboardLayout";
+ table[4629] = "user32.dll!NtUserSetConsoleReserveKeys";
+ table[4557] = "user32.dll!NtUserHungWindowFromGhostWindow";
+ table[4622] = "user32.dll!NtUserSetActiveWindow";
+ table[4544] = "user32.dll!NtUserGetThreadDesktop";
+ table[4497] = "user32.dll!NtUserGetClassInfoEx";
+ table[4480] = "user32.dll!NtUserEnumDisplayDevices";
+ table[4482] = "user32.dll!NtUserEnumDisplaySettings";
+ table[4650] = "user32.dll!NtUserSetScrollInfo";
+ table[4526] = "user32.dll!NtUserGetKeyState";
+ table[4575] = "user32.dll!NtUserMessageCall";
+ table[4706] = "user32.dll!NtUserValidateTimerCallback";
+ table[4611] = "user32.dll!NtUserRegisterWindowMessage";
+ table[4511] = "user32.dll!NtUserGetDC";
+ table[4602] = "user32.dll!NtUserRealInternalGetMessage";
+ table[4487] = "user32.dll!NtUserFindWindowEx";
+ table[4500] = "user32.dll!NtUserGetClipboardFormatName";
+ table[4545] = "user32.dll!NtUserGetThreadState";
+ table[4679] = "user32.dll!NtUserSystemParametersInfo";
+ table[4593] = "user32.dll!NtUserPostMessage";
+ table[4659] = "user32.dll!NtUserSetTimer";
+ table[4567] = "user32.dll!NtUserKillTimer";
+ table[4414] = "user32.dll!NtUserBeginPaint";
+ table[4479] = "user32.dll!NtUserEndPaint";
+ table[4604] = "user32.dll!NtUserRedrawWindow";
+ table[4491] = "user32.dll!NtUserGetAncestor";
+ table[4555] = "user32.dll!NtUserHideCaret";
+ table[4673] = "user32.dll!NtUserShowCaret";
+ table[4448] = "user32.dll!NtUserCreateCaret";
+ table[4531] = "user32.dll!NtUserGetMessage";
+ table[4591] = "user32.dll!PeekMessageW";
+ table[4429] = "user32.dll!NtUserCallOneParam";
+ table[4428] = "user32.dll!NtUserCallNoParam";
+ table[4464] = "user32.dll!NtUserDispatchMessage";
+ table[4648] = "user32.dll!NtUserGetProp";
+ table[4550] = "user32.dll!NtUserGetWindowDC";
+ table[4513] = "user32.dll!NtUserGetDoubleClickTime";
+ table[4710] = "user32.dll!NtUserWaitMessage";
+ table[4564] = "user32.dll!NtUserInvalidateRect";
+ table[4430] = "user32.dll!NtUserCallTwoParam";
+ table[4618] = "user32.dll!NtUserScrollDC";
+ table[4704] = "user32.dll!NtUserValidateHandleSecure";
+ table[4439] = "user32.dll!NtUserClipCursor";
+ table[4571] = "user32.dll!NtUserLockWorkStation";
+ table[4724] = "user32.dll!NtUserDwmStopRedirection";
+ table[4534] = "user32.dll!NtUserGetOpenClipboardWindow";
+ table[4484] = "user32.dll!NtUserExcludeUpdateRgn";
+ table[4707] = "user32.dll!NtUserVkKeyScanEx";
+ table[4654] = "user32.dll!NtUserSetSystemMenu";
+ table[4438] = "user32.dll!NtUserChildWindowFromPointEx";
+ table[4671] = "user32.dll!NtUserSetWindowWord";
+ table[4476] = "user32.dll!NtUserEnableScrollBar";
+ table[4415] = "user32.dll!NtUserBitBltSysBmp";
+ table[4509] = "user32.dll!NtUserGetCursorFrameInfo";
+ table[4427] = "user32.dll!NtUserCallNextHookEx";
+ table[4628] = "user32.dll!NtUserSetClipboardViewer";
+ table[4437] = "user32.dll!CheckMenuItem";
+ table[4566] = "user32.dll!NtUserIsClipboardFormatAvailable";
+ table[4440] = "user32.dll!NtUserCloseClipboard";
+ table[4584] = "user32.dll!NtUserOpenClipboard";
+ table[4502] = "user32.dll!NtUserGetClipboardSequenceNumber";
+ table[4431] = "user32.dll!NtUserChangeClipboardChain";
+ table[4688] = "user32.dll!NtUserTranslateAccelerator";
+ table[4705] = "user32.dll!NtUserValidateRect";
+ table[4667] = "user32.dll!NtUserSetWindowRgnEx";
+ table[4475] = "user32.dll!NtUserEnableMenuItem";
+ table[4496] = "user32.dll!NtUserGetCaretPos";
+ table[4505] = "user32.dll!NtUserGetComboBoxInfo";
+ table[4426] = "user32.dll!NtUserCallMsgFilter";
+ table[4690] = "user32.dll!NtUserUnhookWindowsHookEx";
+ table[4416] = "user32.dll!NtUserBlockInput";
+ table[4595] = "user32.dll!NtUserPrintWindow";
+ table[4501] = "user32.dll!NtUserGetClipboardOwner";
+ table[4413] = "user32.dll!NtUserAttachThreadInput";
+ table[4446] = "user32.dll!NtUserCountClipboardFormats";
+ table[4572] = "user32.dll!NtUserLogicalToPhysicalPoint";
+ table[4592] = "user32.dll!NtUserPhysicalToLogicalPoint";
+ table[4712] = "user32.dll!NtUserWindowFromPhysicalPoint";
+ table[4685] = "user32.dll!NtUserTrackPopupMenuEx";
+ table[4641] = "user32.dll!NtUserSetMenu";
+ table[4432] = "user32.dll!NtUserChangeDisplaySettings";
+ table[4726] = "user32.dll!NtUserDwmGetDxRgn";
+ table[4725] = "user32.dll!NtUserDwmHintDxUpdate";
+ table[4573] = "user32.dll!NtUserMapVirtualKeyEx";
+ table[4640] = "user32.dll!NtUserSetKeyboardState";
+ table[4708] = "user32.dll!NtUserWaitForInputIdle";
+ table[4549] = "user32.dll!NtUserGetUpdateRgn";
+ table[4456] = "user32.dll!NtUserDefSetText";
+ table[4506] = "user32.dll!NtUserGetControlBrush";
+ table[4488] = "user32.dll!NtUserFlashWindowEx";
+ table[4689] = "user32.dll!NtUserTranslateMessage";
+ table[4619] = "user32.dll!NtUserScrollWindowEx";
+ table[4687] = "user32.dll!NtUserPaintMenuBar";
+ table[4551] = "user32.dll!NtUserGetWindowPlacement";
+ table[4713] = "user32.dll!NtUserWindowFromPoint";
+ table[4410] = "user32.dll!NtUserAddClipboardFormatListener";
+ table[4411] = "user32.dll!NtUserAlterWindowStyle";
+ table[4420] = "user32.dll!NtUserBuildPropList";
+ table[4433] = "user32.dll!NtUserCheckAccessForIntegrityLevel";
+ table[4435] = "user32.dll!NtUserCheckWindowThreadDesktop";
+ table[4444] = "user32.dll!NtUserConvertMemHandle";
+ table[4451] = "user32.dll!NtUserCreateLocalMemHandle";
+ table[4466] = "user32.dll!NtUserDoSoundDisconnect";
+ table[4467] = "user32.dll!NtUserDragDetect";
+ table[4468] = "user32.dll!NtUserDragObject";
+ table[4469] = "user32.dll!NtUserDrawAnimatedRects";
+ table[4470] = "user32.dll!NtUserDrawCaption";
+ table[4471] = "user32.dll!NtUserDrawCaptionTemp";
+ table[4473] = "user32.dll!NtUserDrawMenuBarTemp";
+ table[4474] = "user32.dll!NtUserEmptyClipboard";
+ table[4483] = "user32.dll!NtUserEvent";
+ table[4489] = "user32.dll!NtUserFrostCrashedWindow";
+ table[4490] = "user32.dll!NtUserGetAltTabInfo";
+ table[4499] = "user32.dll!NtUserGetClipboardData";
+ table[4503] = "user32.dll!NtUserGetClipboardViewer";
+ table[4504] = "user32.dll!NtUserGetClipCursor";
+ table[4507] = "user32.dll!NtUserGetControlColor";
+ table[4510] = "user32.dll!NtUserGetCursorInfo";
+ table[4515] = "user32.dll!NtUserGetGuiResources";
+ table[4519] = "user32.dll!NtUserGetImeHotKey";
+ table[4521] = "user32.dll!NtUserGetInternalWindowPos";
+ table[4523] = "user32.dll!NtUserGetKeyboardLayoutName";
+ table[4525] = "user32.dll!NtUserGetKeyNameText";
+ table[4527] = "user32.dll!NtUserGetListBoxInfo";
+ table[4529] = "user32.dll!NtUserGetMenuIndex";
+ table[4530] = "user32.dll!NtUserGetMenuItemRect";
+ table[4532] = "user32.dll!NtUserGetMouseMovePointsEx";
+ table[4535] = "user32.dll!NtUserGetPriorityClipboardFormat";
+ table[4537] = "user32.dll!NtUserGetRawInputBuffer";
+ table[4538] = "user32.dll!NtUserGetRawInputData";
+ table[4539] = "user32.dll!NtUserGetRawInputDeviceInfo";
+ table[4540] = "user32.dll!NtUserGetRawInputDeviceList";
+ table[4541] = "user32.dll!NtUserGetRegisteredRawInputDevices";
+ table[4547] = "user32.dll!NtUserGetUpdatedClipboardFormats";
+ table[4552] = "user32.dll!NtUserGetWOWClass";
+ table[4556] = "user32.dll!NtUserHiliteMenuItem";
+ table[4558] = "user32.dll!NtUserImpersonateDdeClientWindow";
+ table[4561] = "user32.dll!NtUserInitTask";
+ table[4563] = "user32.dll!NtUserInternalGetWindowIcon";
+ table[4574] = "user32.dll!NtUserMenuItemFromPoint";
+ table[4576] = "user32.dll!NtUserMinMaximize";
+ table[4577] = "user32.dll!NtUserMNDragLeave";
+ table[4578] = "user32.dll!NtUserMNDragOver";
+ table[4579] = "user32.dll!NtUserModifyUserStartupInfoFlags";
+ table[4581] = "user32.dll!NtUserNotifyIMEStatus";
+ table[4587] = "user32.dll!NtUserOpenThreadDesktop";
+ table[4599] = "user32.dll!NtUserQuerySendMessage";
+ table[4601] = "user32.dll!NtUserRealChildWindowFromPoint";
+ table[4603] = "user32.dll!NtUserRealWaitMessageEx";
+ table[4606] = "user32.dll!NtUserRegisterErrorReportingDialog";
+ table[4610] = "user32.dll!NtUserRegisterTasklist";
+ table[4612] = "user32.dll!NtUserRemoveClipboardFormatListener";
+ table[4616] = "user32.dll!NtUserResolveDesktopForWOW";
+ table[4626] = "user32.dll!NtUserSetClassWord";
+ table[4627] = "user32.dll!NtUserSetClipboardData";
+ table[4631] = "user32.dll!NtUserSetCursorContents";
+ table[4639] = "user32.dll!NtUserSetInternalWindowPos";
+ table[4642] = "user32.dll!NtUserSetMenuContextHelpId";
+ table[4644] = "user32.dll!NtUserSetMenuFlagRtoL";
+ table[4645] = "user32.dll!NtUserSetObjectInformation";
+ table[4652] = "user32.dll!NtUserSetSysColors";
+ table[4653] = "user32.dll!NtUserSetSystemCursor";
+ table[4655] = "user32.dll!NtUserSetSystemTimer";
+ table[4668] = "user32.dll!NtUserSetWindowsHookAW";
+ table[4680] = "user32.dll!NtUserTestForInteractiveUser";
+ table[4683] = "user32.dll!NtUserToUnicodeEx";
+ table[4692] = "user32.dll!NtUserUnloadKeyboardLayout";
+ table[4698] = "user32.dll!NtUserUpdateInstance";
+ table[4700] = "user32.dll!NtUserGetLayeredWindowAttributes";
+ table[4703] = "user32.dll!NtUserUserHandleGrantAccess";
+ table[4709] = "user32.dll!NtUserWaitForMsgAndEvent";
+ table[4711] = "user32.dll!NtUserWin32PoolAllocationStats";
+ table[4714] = "user32.dll!NtUserYieldTask";
+ table[4721] = "user32.dll!NtUserUnregisterSessionPort";
+ table[4722] = "user32.dll!NtUserUpdateWindowTransform";
+ table[4866] = "user32.dll!NtUserSetMirrorRendering";
+ table[4867] = "user32.dll!NtUserShowSystemCursor";
+}
+
+ return table;
+}
+
+#endif // TRACELINE_SYSCALL_MAP_H_
diff --git a/chromium/tools/unused-symbols-report.py b/chromium/tools/unused-symbols-report.py
new file mode 100755
index 00000000000..900bf16e120
--- /dev/null
+++ b/chromium/tools/unused-symbols-report.py
@@ -0,0 +1,171 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Prints a report of symbols stripped by the linker due to being unused.
+
+To use, build with these linker flags:
+ -Wl,--gc-sections
+ -Wl,--print-gc-sections
+the first one is the default in Release; search build/common.gypi for it
+and to see where to add the other.
+
+Then build, saving the output into a file:
+ make chrome 2>&1 | tee buildlog
+and run this script on it:
+ ./tools/unused-symbols-report.py buildlog > report.html
+"""
+
+import cgi
+import optparse
+import os
+import re
+import subprocess
+import sys
+
+cppfilt_proc = None
+def Demangle(sym):
+ """Demangle a C++ symbol by passing it through c++filt."""
+ global cppfilt_proc
+ if cppfilt_proc is None:
+ cppfilt_proc = subprocess.Popen(['c++filt'], stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ print >>cppfilt_proc.stdin, sym
+ return cppfilt_proc.stdout.readline().strip()
+
+
+def Unyuck(sym):
+ """Attempt to prettify a C++ symbol by some basic heuristics."""
+ sym = sym.replace('std::basic_string<char, std::char_traits<char>, '
+ 'std::allocator<char> >', 'std::string')
+ sym = sym.replace('std::basic_string<wchar_t, std::char_traits<wchar_t>, '
+ 'std::allocator<wchar_t> >', 'std::wstring')
+ sym = sym.replace('std::basic_string<unsigned short, '
+ 'base::string16_char_traits, '
+ 'std::allocator<unsigned short> >', 'string16')
+ sym = re.sub(r', std::allocator<\S+\s+>', '', sym)
+ return sym
+
+
+def Parse(input, skip_paths=None, only_paths=None):
+ """Parse the --print-gc-sections build output.
+
+ Args:
+ input: iterable over the lines of the build output
+
+ Yields:
+ (target name, path to .o file, demangled symbol)
+ """
+ symbol_re = re.compile(r"'\.text\.(\S+)' in file '(\S+)'$")
+ path_re = re.compile(r"^out/[^/]+/[^/]+/([^/]+)/(.*)$")
+ for line in input:
+ match = symbol_re.search(line)
+ if not match:
+ continue
+ symbol, path = match.groups()
+ symbol = Unyuck(Demangle(symbol))
+ path = os.path.normpath(path)
+ if skip_paths and skip_paths in path:
+ continue
+ if only_paths and only_paths not in path:
+ continue
+ match = path_re.match(path)
+ if not match:
+ print >>sys.stderr, "Skipping weird path", path
+ continue
+ target, path = match.groups()
+ yield target, path, symbol
+
+
+# HTML header for our output page.
+TEMPLATE_HEADER = """<!DOCTYPE html>
+<head>
+<style>
+body {
+ font-family: sans-serif;
+ font-size: 0.8em;
+}
+h1, h2 {
+ font-weight: normal;
+ margin: 0.5em 0;
+}
+h2 {
+ margin-top: 1em;
+}
+tr:hover {
+ background: #eee;
+}
+.permalink {
+ padding-left: 1ex;
+ font-size: 80%;
+ text-decoration: none;
+ color: #ccc;
+}
+.symbol {
+ font-family: WebKitWorkAround, monospace;
+ margin-left: 4ex;
+ text-indent: -4ex;
+ padding: 0.5ex 1ex;
+}
+.file {
+ padding: 0.5ex 1ex;
+ padding-left: 2ex;
+ font-family: WebKitWorkAround, monospace;
+ font-size: 90%;
+ color: #777;
+}
+</style>
+</head>
+<body>
+<h1>chrome symbols deleted at link time</h1>
+"""
+
+
+def Output(iter):
+ """Print HTML given an iterable of (target, path, symbol) tuples."""
+ targets = {}
+ for target, path, symbol in iter:
+ entries = targets.setdefault(target, [])
+ entries.append((symbol, path))
+
+ print TEMPLATE_HEADER
+ print "<p>jump to target:"
+ print "<select onchange='document.location.hash = this.value'>"
+ for target in sorted(targets.keys()):
+ print "<option>%s</option>" % target
+ print "</select></p>"
+
+ for target in sorted(targets.keys()):
+ print "<h2>%s" % target
+ print "<a class=permalink href='#%s' name='%s'>#</a>" % (target, target)
+ print "</h2>"
+ print "<table width=100% cellspacing=0>"
+ for symbol, path in sorted(targets[target]):
+ htmlsymbol = cgi.escape(symbol).replace('::', '::<wbr>')
+ print "<tr><td><div class=symbol>%s</div></td>" % htmlsymbol
+ print "<td valign=top><div class=file>%s</div></td></tr>" % path
+ print "</table>"
+
+
+def main():
+ parser = optparse.OptionParser(usage='%prog [options] buildoutput\n\n' +
+ __doc__)
+ parser.add_option("--skip-paths", metavar="STR", default="third_party",
+ help="skip paths matching STR [default=%default]")
+ parser.add_option("--only-paths", metavar="STR",
+ help="only include paths matching STR [default=%default]")
+ opts, args = parser.parse_args()
+
+ if len(args) < 1:
+ parser.print_help()
+ sys.exit(1)
+
+ iter = Parse(open(args[0]),
+ skip_paths=opts.skip_paths,
+ only_paths=opts.only_paths)
+ Output(iter)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/update_reference_build.py b/chromium/tools/update_reference_build.py
new file mode 100755
index 00000000000..bffccd9f3d8
--- /dev/null
+++ b/chromium/tools/update_reference_build.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Updates the Chrome reference builds.
+
+Usage:
+ $ cd /tmp
+ $ /path/to/update_reference_build.py -r <revision>
+ $ cd reference_builds/reference_builds
+ $ gcl change
+ $ gcl upload <change>
+ $ gcl commit <change>
+"""
+
+import errno
+import logging
+import optparse
+import os
+import shutil
+import subprocess
+import sys
+import time
+import urllib
+import urllib2
+import zipfile
+
+
+class BuildUpdater(object):
+ _PLATFORM_FILES_MAP = {
+ 'Win': [
+ 'chrome-win32.zip',
+ 'chrome-win32-syms.zip',
+ 'chrome-win32.test/_pyautolib.pyd',
+ 'chrome-win32.test/pyautolib.py',
+ ],
+ 'Mac': [
+ 'chrome-mac.zip',
+ 'chrome-mac.test/_pyautolib.so',
+ 'chrome-mac.test/pyautolib.py',
+ ],
+ 'Linux': [
+ 'chrome-linux.zip',
+ ],
+ 'Linux_x64': [
+ 'chrome-linux.zip',
+ ],
+ }
+
+ _PLATFORM_DEST_MAP = {
+ 'Linux': 'chrome_linux',
+ 'Linux_x64': 'chrome_linux64',
+ 'Win': 'chrome_win',
+ 'Mac': 'chrome_mac',
+ }
+
+ def __init__(self, options):
+ self._platforms = options.platforms.split(',')
+ self._revision = int(options.revision)
+
+ @staticmethod
+ def _GetCmdStatusAndOutput(args, cwd=None, shell=False):
+ """Executes a subprocess and returns its exit code and output.
+
+ Args:
+ args: A string or a sequence of program arguments.
+ cwd: If not None, the subprocess's current directory will be changed to
+ |cwd| before it's executed.
+ shell: Whether to execute args as a shell command.
+
+ Returns:
+ The tuple (exit code, output).
+ """
+ logging.info(str(args) + ' ' + (cwd or ''))
+ p = subprocess.Popen(args=args, cwd=cwd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, shell=shell)
+ stdout, stderr = p.communicate()
+ exit_code = p.returncode
+ if stderr:
+ logging.critical(stderr)
+ logging.info(stdout)
+ return (exit_code, stdout)
+
+ def _GetBuildUrl(self, platform, revision, filename):
+ URL_FMT = ('http://commondatastorage.googleapis.com/'
+ 'chromium-browser-snapshots/%s/%s/%s')
+ return URL_FMT % (urllib.quote_plus(platform), revision, filename)
+
+ def _FindBuildRevision(self, platform, revision, filename):
+ MAX_REVISIONS_PER_BUILD = 100
+ for revision_guess in xrange(revision, revision + MAX_REVISIONS_PER_BUILD):
+ r = urllib2.Request(self._GetBuildUrl(platform, revision_guess, filename))
+ r.get_method = lambda: 'HEAD'
+ try:
+ response = urllib2.urlopen(r)
+ return revision_guess
+ except urllib2.HTTPError, err:
+ if err.code == 404:
+ time.sleep(.1)
+ continue
+ return None
+
+ def _DownloadBuilds(self):
+ for platform in self._platforms:
+ for f in BuildUpdater._PLATFORM_FILES_MAP[platform]:
+ output = os.path.join('dl', platform,
+ '%s_%s_%s' % (platform, self._revision, f))
+ if os.path.exists(output):
+ logging.info('%s alread exists, skipping download' % output)
+ continue
+ build_revision = self._FindBuildRevision(platform, self._revision, f)
+ if not build_revision:
+ logging.critical('Failed to find %s build for r%s\n' % (
+ platform, self._revision))
+ sys.exit(1)
+ dirname = os.path.dirname(output)
+ if dirname and not os.path.exists(dirname):
+ os.makedirs(dirname)
+ url = self._GetBuildUrl(platform, build_revision, f)
+ logging.info('Downloading %s, saving to %s' % (url, output))
+ r = urllib2.urlopen(url)
+ with file(output, 'wb') as f:
+ f.write(r.read())
+
+ def _FetchSvnRepos(self):
+ if not os.path.exists('reference_builds'):
+ os.makedirs('reference_builds')
+ BuildUpdater._GetCmdStatusAndOutput(
+ ['gclient', 'config',
+ 'svn://svn.chromium.org/chrome/trunk/deps/reference_builds'],
+ 'reference_builds')
+ BuildUpdater._GetCmdStatusAndOutput(
+ ['gclient', 'sync'], 'reference_builds')
+
+ def _UnzipFile(self, dl_file, dest_dir):
+ if not zipfile.is_zipfile(dl_file):
+ return False
+ logging.info('Opening %s' % dl_file)
+ with zipfile.ZipFile(dl_file, 'r') as z:
+ for content in z.namelist():
+ dest = os.path.join(dest_dir, content[content.find('/')+1:])
+ if not os.path.basename(dest):
+ if not os.path.isdir(dest):
+ os.makedirs(dest)
+ continue
+ with z.open(content) as unzipped_content:
+ logging.info('Extracting %s to %s (%s)' % (content, dest, dl_file))
+ with file(dest, 'wb') as dest_file:
+ dest_file.write(unzipped_content.read())
+ permissions = z.getinfo(content).external_attr >> 16
+ if permissions:
+ os.chmod(dest, permissions)
+ return True
+
+ def _ClearDir(self, dir):
+ """Clears all files in |dir| except for hidden files and folders."""
+ for root, dirs, files in os.walk(dir):
+ # Skip hidden files and folders (like .svn and .git).
+ files = [f for f in files if f[0] != '.']
+ dirs[:] = [d for d in dirs if d[0] != '.']
+
+ for f in files:
+ os.remove(os.path.join(root, f))
+
+ def _ExtractBuilds(self):
+ for platform in self._platforms:
+ if os.path.exists('tmp_unzip'):
+ os.path.unlink('tmp_unzip')
+ dest_dir = os.path.join('reference_builds', 'reference_builds',
+ BuildUpdater._PLATFORM_DEST_MAP[platform])
+ self._ClearDir(dest_dir)
+ for root, _, dl_files in os.walk(os.path.join('dl', platform)):
+ for dl_file in dl_files:
+ dl_file = os.path.join(root, dl_file)
+ if not self._UnzipFile(dl_file, dest_dir):
+ logging.info('Copying %s to %s' % (dl_file, dest_dir))
+ shutil.copy(dl_file, dest_dir)
+
+ def _SvnAddAndRemove(self):
+ svn_dir = os.path.join('reference_builds', 'reference_builds')
+ stat = BuildUpdater._GetCmdStatusAndOutput(['svn', 'stat'], svn_dir)[1]
+ for line in stat.splitlines():
+ action, filename = line.split(None, 1)
+ if action == '?':
+ BuildUpdater._GetCmdStatusAndOutput(
+ ['svn', 'add', filename], svn_dir)
+ elif action == '!':
+ BuildUpdater._GetCmdStatusAndOutput(
+ ['svn', 'delete', filename], svn_dir)
+ filepath = os.path.join(svn_dir, filename)
+ if not os.path.isdir(filepath) and os.access(filepath, os.X_OK):
+ BuildUpdater._GetCmdStatusAndOutput(
+ ['svn', 'propset', 'svn:executable', 'true', filename], svn_dir)
+
+ def DownloadAndUpdateBuilds(self):
+ self._DownloadBuilds()
+ self._FetchSvnRepos()
+ self._ExtractBuilds()
+ self._SvnAddAndRemove()
+
+
+def ParseOptions(argv):
+ parser = optparse.OptionParser()
+ usage = 'usage: %prog <options>'
+ parser.set_usage(usage)
+ parser.add_option('-r', dest='revision',
+ help='Revision to pickup')
+ parser.add_option('-p', dest='platforms',
+ default='Win,Mac,Linux,Linux_x64',
+ help='Comma separated list of platforms to download '
+ '(as defined by the chromium builders).')
+ (options, _) = parser.parse_args(argv)
+ if not options.revision:
+ logging.critical('Must specify -r\n')
+ sys.exit(1)
+
+ return options
+
+
+def main(argv):
+ logging.getLogger().setLevel(logging.DEBUG)
+ options = ParseOptions(argv)
+ b = BuildUpdater(options)
+ b.DownloadAndUpdateBuilds()
+ logging.info('Successfully updated reference builds. Move to '
+ 'reference_builds/reference_builds and make a change with gcl.')
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/chromium/tools/usb_ids/usb_ids.py b/chromium/tools/usb_ids/usb_ids.py
new file mode 100644
index 00000000000..e07bd4ca6f7
--- /dev/null
+++ b/chromium/tools/usb_ids/usb_ids.py
@@ -0,0 +1,110 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import itertools
+import optparse
+import re
+
+VENDOR_PATTERN = re.compile("^(?P<id>[0-9a-fA-F]{4})\s+(?P<name>.+)$")
+PRODUCT_PATTERN = re.compile("^\t(?P<id>[0-9a-fA-F]{4})\s+(?P<name>.+)$")
+
+def EscapeName(name):
+ name = name.replace("\\", "\\\\")
+ name = name.replace("\"", "\\\"")
+ name = name.replace("?", "\?")
+ return name
+
+def ParseTable(input_path):
+ input_file = open(input_path, "r")
+ input = input_file.read().split("\n")
+ input_file.close()
+
+ table = {}
+ vendor = None
+
+ for line in input:
+ vendor_match = VENDOR_PATTERN.match(line)
+ if vendor_match:
+ if vendor:
+ table[vendor["id"]] = vendor
+ vendor = {}
+ vendor["id"] = int(vendor_match.group("id"), 16)
+ vendor["name"] = vendor_match.group("name")
+ vendor["products"] = []
+ continue
+
+ product_match = PRODUCT_PATTERN.match(line)
+ if product_match:
+ if not vendor:
+ raise Exception("Product seems to appear before vendor.")
+ product = {}
+ product["id"] = int(product_match.group("id"), 16)
+ product["name"] = product_match.group("name")
+ vendor["products"].append(product)
+
+ return table
+
+def GenerateDeviceDefinitions(table):
+ output = ""
+
+ for vendor_id in sorted(table.keys()):
+ vendor = table[vendor_id]
+ if len(vendor["products"]) == 0:
+ continue
+
+ output += "static const UsbProduct vendor_%.4x_products[] = {\n" % \
+ vendor["id"]
+ for product in vendor["products"]:
+ output += " {0x%.4x, \"%s\"},\n" % (product["id"],
+ EscapeName(product["name"]))
+ output += "};\n"
+
+ return output
+
+def GenerateVendorDefinitions(table):
+ output = "const size_t UsbIds::vendor_size_ = %d;\n" % len(table.keys())
+ output += "const UsbVendor UsbIds::vendors_[] = {\n"
+
+ for vendor_id in sorted(table.keys()):
+ vendor = table[vendor_id]
+
+ product_table = "NULL"
+ if len(vendor["products"]) != 0:
+ product_table = "vendor_%.4x_products" % (vendor["id"])
+ output += " {0x%.4x, \"%s\", %d, %s},\n" % (vendor["id"],
+ EscapeName(vendor["name"]), len(vendor["products"]), product_table)
+
+ output += "};\n"
+ return output
+
+if __name__ == "__main__":
+ parser = optparse.OptionParser(
+ description="Generates a C++ USB ID lookup table.")
+ parser.add_option("-i", "--input", help="Path to usb.ids")
+ parser.add_option("-o", "--output", help="Output file path")
+
+ (opts, args) = parser.parse_args()
+ table = ParseTable(opts.input)
+
+ output = """// Generated from %s
+#ifndef GENERATED_USB_IDS_H_
+#define GENERATED_USB_IDS_H_
+
+#include "device/usb/usb_ids.h"
+
+namespace device {
+
+""" % (opts.input)
+ output += GenerateDeviceDefinitions(table)
+ output += GenerateVendorDefinitions(table)
+ output += """
+
+} // namespace device
+
+#endif // GENERATED_USB_IDS_H_
+"""
+
+ output_file = open(opts.output, "w+")
+ output_file.write(output)
+ output_file.close()
diff --git a/chromium/tools/valgrind/OWNERS b/chromium/tools/valgrind/OWNERS
new file mode 100644
index 00000000000..73ce47c70ef
--- /dev/null
+++ b/chromium/tools/valgrind/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+bruening@chromium.org
+glider@chromium.org
+thestig@chromium.org
+timurrrr@chromium.org
diff --git a/chromium/tools/valgrind/asan/asan_symbolize.py b/chromium/tools/valgrind/asan/asan_symbolize.py
new file mode 100755
index 00000000000..c1f93bd16e8
--- /dev/null
+++ b/chromium/tools/valgrind/asan/asan_symbolize.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from third_party import asan_symbolize
+
+import re
+import sys
+
+def fix_filename(file_name):
+ for path_to_cut in sys.argv[1:]:
+ file_name = re.sub(".*" + path_to_cut, "", file_name)
+ file_name = re.sub(".*asan_[a-z_]*.cc:[0-9]*", "_asan_rtl_", file_name)
+ file_name = re.sub(".*crtstuff.c:0", "???:0", file_name)
+ return file_name
+
+def main():
+ loop = asan_symbolize.SymbolizationLoop(binary_name_filter=fix_filename)
+ loop.process_stdin()
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/valgrind/asan/asan_wrapper.sh b/chromium/tools/valgrind/asan/asan_wrapper.sh
new file mode 100755
index 00000000000..4e34fed5a09
--- /dev/null
+++ b/chromium/tools/valgrind/asan/asan_wrapper.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# A wrapper that runs the program and filters the output through
+# asan_symbolize.py and c++filt
+#
+# TODO(glider): this should be removed once EmbeddedTool in valgrind_test.py
+# starts supporting pipes.
+
+export THISDIR=`dirname $0`
+"$@" 2>&1 |
+ $THISDIR/asan_symbolize.py |
+ c++filt
diff --git a/chromium/tools/valgrind/asan/third_party/README.chromium b/chromium/tools/valgrind/asan/third_party/README.chromium
new file mode 100644
index 00000000000..f9e6c9be5bc
--- /dev/null
+++ b/chromium/tools/valgrind/asan/third_party/README.chromium
@@ -0,0 +1,6 @@
+Name: asan_symbolize.py
+License: University of Illinois Open Source License.
+Version: 183006
+URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/scripts/asan_symbolize.py?view=co&content-type=text%2Fplain
+
+asan_symbolize.py is a verbatim copy of asan_symbolize.py in the LLVM trunk.
diff --git a/chromium/tools/valgrind/asan/third_party/__init__.py b/chromium/tools/valgrind/asan/third_party/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/chromium/tools/valgrind/asan/third_party/__init__.py
diff --git a/chromium/tools/valgrind/asan/third_party/asan_symbolize.py b/chromium/tools/valgrind/asan/third_party/asan_symbolize.py
new file mode 100755
index 00000000000..207928f6eae
--- /dev/null
+++ b/chromium/tools/valgrind/asan/third_party/asan_symbolize.py
@@ -0,0 +1,365 @@
+#!/usr/bin/env python
+#===- lib/asan/scripts/asan_symbolize.py -----------------------------------===#
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+import bisect
+import getopt
+import os
+import re
+import subprocess
+import sys
+
+llvm_symbolizer = None
+symbolizers = {}
+DEBUG = False
+demangle = False;
+
+
+# FIXME: merge the code that calls fix_filename().
+def fix_filename(file_name):
+ for path_to_cut in sys.argv[1:]:
+ file_name = re.sub('.*' + path_to_cut, '', file_name)
+ file_name = re.sub('.*asan_[a-z_]*.cc:[0-9]*', '_asan_rtl_', file_name)
+ file_name = re.sub('.*crtstuff.c:0', '???:0', file_name)
+ return file_name
+
+
+class Symbolizer(object):
+ def __init__(self):
+ pass
+
+ def symbolize(self, addr, binary, offset):
+ """Symbolize the given address (pair of binary and offset).
+
+ Overriden in subclasses.
+ Args:
+ addr: virtual address of an instruction.
+ binary: path to executable/shared object containing this instruction.
+ offset: instruction offset in the @binary.
+ Returns:
+ list of strings (one string for each inlined frame) describing
+ the code locations for this instruction (that is, function name, file
+ name, line and column numbers).
+ """
+ return None
+
+
+class LLVMSymbolizer(Symbolizer):
+ def __init__(self, symbolizer_path):
+ super(LLVMSymbolizer, self).__init__()
+ self.symbolizer_path = symbolizer_path
+ self.pipe = self.open_llvm_symbolizer()
+
+ def open_llvm_symbolizer(self):
+ if not os.path.exists(self.symbolizer_path):
+ return None
+ cmd = [self.symbolizer_path,
+ '--use-symbol-table=true',
+ '--demangle=%s' % demangle,
+ '--functions=true',
+ '--inlining=true']
+ if DEBUG:
+ print ' '.join(cmd)
+ return subprocess.Popen(cmd, stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+
+ def symbolize(self, addr, binary, offset):
+ """Overrides Symbolizer.symbolize."""
+ if not self.pipe:
+ return None
+ result = []
+ try:
+ symbolizer_input = '%s %s' % (binary, offset)
+ if DEBUG:
+ print symbolizer_input
+ print >> self.pipe.stdin, symbolizer_input
+ while True:
+ function_name = self.pipe.stdout.readline().rstrip()
+ if not function_name:
+ break
+ file_name = self.pipe.stdout.readline().rstrip()
+ file_name = fix_filename(file_name)
+ if (not function_name.startswith('??') and
+ not file_name.startswith('??')):
+ # Append only valid frames.
+ result.append('%s in %s %s' % (addr, function_name,
+ file_name))
+ except Exception:
+ result = []
+ if not result:
+ result = None
+ return result
+
+
+def LLVMSymbolizerFactory(system):
+ symbolizer_path = os.getenv('LLVM_SYMBOLIZER_PATH')
+ if not symbolizer_path:
+ # Assume llvm-symbolizer is in PATH.
+ symbolizer_path = 'llvm-symbolizer'
+ return LLVMSymbolizer(symbolizer_path)
+
+
+class Addr2LineSymbolizer(Symbolizer):
+ def __init__(self, binary):
+ super(Addr2LineSymbolizer, self).__init__()
+ self.binary = binary
+ self.pipe = self.open_addr2line()
+
+ def open_addr2line(self):
+ cmd = ['addr2line', '-f']
+ if demangle:
+ cmd += ['--demangle']
+ cmd += ['-e', self.binary]
+ if DEBUG:
+ print ' '.join(cmd)
+ return subprocess.Popen(cmd,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+
+ def symbolize(self, addr, binary, offset):
+ """Overrides Symbolizer.symbolize."""
+ if self.binary != binary:
+ return None
+ try:
+ print >> self.pipe.stdin, offset
+ function_name = self.pipe.stdout.readline().rstrip()
+ file_name = self.pipe.stdout.readline().rstrip()
+ except Exception:
+ function_name = ''
+ file_name = ''
+ file_name = fix_filename(file_name)
+ return ['%s in %s %s' % (addr, function_name, file_name)]
+
+
+class DarwinSymbolizer(Symbolizer):
+ def __init__(self, addr, binary):
+ super(DarwinSymbolizer, self).__init__()
+ self.binary = binary
+ # Guess which arch we're running. 10 = len('0x') + 8 hex digits.
+ if len(addr) > 10:
+ self.arch = 'x86_64'
+ else:
+ self.arch = 'i386'
+ self.pipe = None
+
+ def write_addr_to_pipe(self, offset):
+ print >> self.pipe.stdin, '0x%x' % int(offset, 16)
+
+ def open_atos(self):
+ if DEBUG:
+ print 'atos -o %s -arch %s' % (self.binary, self.arch)
+ cmdline = ['atos', '-o', self.binary, '-arch', self.arch]
+ self.pipe = subprocess.Popen(cmdline,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ def symbolize(self, addr, binary, offset):
+ """Overrides Symbolizer.symbolize."""
+ if self.binary != binary:
+ return None
+ self.open_atos()
+ self.write_addr_to_pipe(offset)
+ self.pipe.stdin.close()
+ atos_line = self.pipe.stdout.readline().rstrip()
+ # A well-formed atos response looks like this:
+ # foo(type1, type2) (in object.name) (filename.cc:80)
+ match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line)
+ if DEBUG:
+ print 'atos_line: ', atos_line
+ if match:
+ function_name = match.group(1)
+ function_name = re.sub('\(.*?\)', '', function_name)
+ file_name = fix_filename(match.group(3))
+ return ['%s in %s %s' % (addr, function_name, file_name)]
+ else:
+ return ['%s in %s' % (addr, atos_line)]
+
+
+# Chain several symbolizers so that if one symbolizer fails, we fall back
+# to the next symbolizer in chain.
+class ChainSymbolizer(Symbolizer):
+ def __init__(self, symbolizer_list):
+ super(ChainSymbolizer, self).__init__()
+ self.symbolizer_list = symbolizer_list
+
+ def symbolize(self, addr, binary, offset):
+ """Overrides Symbolizer.symbolize."""
+ for symbolizer in self.symbolizer_list:
+ if symbolizer:
+ result = symbolizer.symbolize(addr, binary, offset)
+ if result:
+ return result
+ return None
+
+ def append_symbolizer(self, symbolizer):
+ self.symbolizer_list.append(symbolizer)
+
+
+def BreakpadSymbolizerFactory(binary):
+ suffix = os.getenv('BREAKPAD_SUFFIX')
+ if suffix:
+ filename = binary + suffix
+ if os.access(filename, os.F_OK):
+ return BreakpadSymbolizer(filename)
+ return None
+
+
+def SystemSymbolizerFactory(system, addr, binary):
+ if system == 'Darwin':
+ return DarwinSymbolizer(addr, binary)
+ elif system == 'Linux':
+ return Addr2LineSymbolizer(binary)
+
+
+class BreakpadSymbolizer(Symbolizer):
+ def __init__(self, filename):
+ super(BreakpadSymbolizer, self).__init__()
+ self.filename = filename
+ lines = file(filename).readlines()
+ self.files = []
+ self.symbols = {}
+ self.address_list = []
+ self.addresses = {}
+ # MODULE mac x86_64 A7001116478B33F18FF9BEDE9F615F190 t
+ fragments = lines[0].rstrip().split()
+ self.arch = fragments[2]
+ self.debug_id = fragments[3]
+ self.binary = ' '.join(fragments[4:])
+ self.parse_lines(lines[1:])
+
+ def parse_lines(self, lines):
+ cur_function_addr = ''
+ for line in lines:
+ fragments = line.split()
+ if fragments[0] == 'FILE':
+ assert int(fragments[1]) == len(self.files)
+ self.files.append(' '.join(fragments[2:]))
+ elif fragments[0] == 'PUBLIC':
+ self.symbols[int(fragments[1], 16)] = ' '.join(fragments[3:])
+ elif fragments[0] in ['CFI', 'STACK']:
+ pass
+ elif fragments[0] == 'FUNC':
+ cur_function_addr = int(fragments[1], 16)
+ if not cur_function_addr in self.symbols.keys():
+ self.symbols[cur_function_addr] = ' '.join(fragments[4:])
+ else:
+ # Line starting with an address.
+ addr = int(fragments[0], 16)
+ self.address_list.append(addr)
+ # Tuple of symbol address, size, line, file number.
+ self.addresses[addr] = (cur_function_addr,
+ int(fragments[1], 16),
+ int(fragments[2]),
+ int(fragments[3]))
+ self.address_list.sort()
+
+ def get_sym_file_line(self, addr):
+ key = None
+ if addr in self.addresses.keys():
+ key = addr
+ else:
+ index = bisect.bisect_left(self.address_list, addr)
+ if index == 0:
+ return None
+ else:
+ key = self.address_list[index - 1]
+ sym_id, size, line_no, file_no = self.addresses[key]
+ symbol = self.symbols[sym_id]
+ filename = self.files[file_no]
+ if addr < key + size:
+ return symbol, filename, line_no
+ else:
+ return None
+
+ def symbolize(self, addr, binary, offset):
+ if self.binary != binary:
+ return None
+ res = self.get_sym_file_line(int(offset, 16))
+ if res:
+ function_name, file_name, line_no = res
+ result = ['%s in %s %s:%d' % (
+ addr, function_name, file_name, line_no)]
+ print result
+ return result
+ else:
+ return None
+
+
+class SymbolizationLoop(object):
+ def __init__(self, binary_name_filter=None):
+ # Used by clients who may want to supply a different binary name.
+ # E.g. in Chrome several binaries may share a single .dSYM.
+ self.binary_name_filter = binary_name_filter
+ self.system = os.uname()[0]
+ if self.system in ['Linux', 'Darwin']:
+ self.llvm_symbolizer = LLVMSymbolizerFactory(self.system)
+ else:
+ raise Exception('Unknown system')
+
+ def symbolize_address(self, addr, binary, offset):
+ # Use the chain of symbolizers:
+ # Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos
+ # (fall back to next symbolizer if the previous one fails).
+ if not binary in symbolizers:
+ symbolizers[binary] = ChainSymbolizer(
+ [BreakpadSymbolizerFactory(binary), self.llvm_symbolizer])
+ result = symbolizers[binary].symbolize(addr, binary, offset)
+ if result is None:
+ # Initialize system symbolizer only if other symbolizers failed.
+ symbolizers[binary].append_symbolizer(
+ SystemSymbolizerFactory(self.system, addr, binary))
+ result = symbolizers[binary].symbolize(addr, binary, offset)
+ # The system symbolizer must produce some result.
+ assert result
+ return result
+
+ def print_symbolized_lines(self, symbolized_lines):
+ if not symbolized_lines:
+ print self.current_line
+ else:
+ for symbolized_frame in symbolized_lines:
+ print ' #' + str(self.frame_no) + ' ' + symbolized_frame.rstrip()
+ self.frame_no += 1
+
+ def process_stdin(self):
+ self.frame_no = 0
+ while True:
+ line = sys.stdin.readline()
+ if not line:
+ break
+ self.current_line = line.rstrip()
+ #0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45)
+ stack_trace_line_format = (
+ '^( *#([0-9]+) *)(0x[0-9a-f]+) *\((.*)\+(0x[0-9a-f]+)\)')
+ match = re.match(stack_trace_line_format, line)
+ if not match:
+ print self.current_line
+ continue
+ if DEBUG:
+ print line
+ _, frameno_str, addr, binary, offset = match.groups()
+ if frameno_str == '0':
+ # Assume that frame #0 is the first frame of new stack trace.
+ self.frame_no = 0
+ original_binary = binary
+ if self.binary_name_filter:
+ binary = self.binary_name_filter(binary)
+ symbolized_line = self.symbolize_address(addr, binary, offset)
+ if not symbolized_line:
+ if original_binary != binary:
+ symbolized_line = self.symbolize_address(addr, binary, offset)
+ self.print_symbolized_lines(symbolized_line)
+
+
+if __name__ == '__main__':
+ opts, args = getopt.getopt(sys.argv[1:], "d", ["demangle"])
+ for o, a in opts:
+ if o in ("-d", "--demangle"):
+ demangle = True;
+ loop = SymbolizationLoop()
+ loop.process_stdin()
diff --git a/chromium/tools/valgrind/browser_wrapper_win.py b/chromium/tools/valgrind/browser_wrapper_win.py
new file mode 100644
index 00000000000..b855e80d6d9
--- /dev/null
+++ b/chromium/tools/valgrind/browser_wrapper_win.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import glob
+import os
+import re
+import sys
+import subprocess
+
+# TODO(timurrrr): we may use it on POSIX too to avoid code duplication once we
+# support layout_tests, remove Dr. Memory specific code and verify it works
+# on a "clean" Mac.
+
+testcase_name = None
+for arg in sys.argv:
+ m = re.match("\-\-test\-name=(.*)", arg)
+ if m:
+ assert testcase_name is None
+ testcase_name = m.groups()[0]
+
+# arg #0 is the path to this python script
+cmd_to_run = sys.argv[1:]
+
+# TODO(timurrrr): this is Dr. Memory-specific
+# Usually, we pass "-logdir" "foo\bar\spam path" args to Dr. Memory.
+# To group reports per UI test, we want to put the reports for each test into a
+# separate directory. This code can be simplified when we have
+# http://code.google.com/p/drmemory/issues/detail?id=684 fixed.
+logdir_idx = cmd_to_run.index("-logdir")
+old_logdir = cmd_to_run[logdir_idx + 1]
+
+wrapper_pid = str(os.getpid())
+
+# On Windows, there is a chance of PID collision. We avoid it by appending the
+# number of entries in the logdir at the end of wrapper_pid.
+# This number is monotonic and we can't have two simultaneously running wrappers
+# with the same PID.
+wrapper_pid += "_%d" % len(glob.glob(old_logdir + "\\*"))
+
+cmd_to_run[logdir_idx + 1] += "\\testcase.%s.logs" % wrapper_pid
+os.makedirs(cmd_to_run[logdir_idx + 1])
+
+if testcase_name:
+ f = open(old_logdir + "\\testcase.%s.name" % wrapper_pid, "w")
+ print >>f, testcase_name
+ f.close()
+
+exit(subprocess.call(cmd_to_run))
diff --git a/chromium/tools/valgrind/chrome_tests.bat b/chromium/tools/valgrind/chrome_tests.bat
new file mode 100755
index 00000000000..138bec7e93d
--- /dev/null
+++ b/chromium/tools/valgrind/chrome_tests.bat
@@ -0,0 +1,70 @@
+@echo off
+:: Copyright (c) 2011 The Chromium Authors. All rights reserved.
+:: Use of this source code is governed by a BSD-style license that can be
+:: found in the LICENSE file.
+
+:: TODO(timurrrr): batch files 'export' all the variables to the parent shell
+set THISDIR=%~dp0
+set TOOL_NAME="unknown"
+
+:: Get the tool name and put it into TOOL_NAME {{{1
+:: NB: SHIFT command doesn't modify %*
+:PARSE_ARGS_LOOP
+ if %1 == () GOTO:TOOLNAME_NOT_FOUND
+ if %1 == --tool GOTO:TOOLNAME_FOUND
+ SHIFT
+ goto :PARSE_ARGS_LOOP
+
+:TOOLNAME_NOT_FOUND
+echo "Please specify a tool (tsan or drmemory) by using --tool flag"
+exit /B 1
+
+:TOOLNAME_FOUND
+SHIFT
+set TOOL_NAME=%1
+:: }}}
+if "%TOOL_NAME%" == "drmemory" GOTO :SETUP_DRMEMORY
+if "%TOOL_NAME%" == "drmemory_light" GOTO :SETUP_DRMEMORY
+if "%TOOL_NAME%" == "drmemory_full" GOTO :SETUP_DRMEMORY
+if "%TOOL_NAME%" == "drmemory_pattern" GOTO :SETUP_DRMEMORY
+if "%TOOL_NAME%" == "tsan" GOTO :SETUP_TSAN
+echo "Unknown tool: `%TOOL_NAME%`! Only tsan and drmemory are supported right now"
+exit /B 1
+
+:SETUP_DRMEMORY
+if NOT "%DRMEMORY_COMMAND%"=="" GOTO :RUN_TESTS
+:: Set up DRMEMORY_COMMAND to invoke Dr. Memory {{{1
+set DRMEMORY_PATH=%THISDIR%..\..\third_party\drmemory
+set DRMEMORY_SFX=%DRMEMORY_PATH%\drmemory-windows-sfx.exe
+if EXIST %DRMEMORY_SFX% GOTO DRMEMORY_BINARY_OK
+echo "Can't find Dr. Memory executables."
+echo "See http://www.chromium.org/developers/how-tos/using-valgrind/dr-memory"
+echo "for the instructions on how to get them."
+exit /B 1
+
+:DRMEMORY_BINARY_OK
+%DRMEMORY_SFX% -o%DRMEMORY_PATH%\unpacked -y
+set DRMEMORY_COMMAND=%DRMEMORY_PATH%\unpacked\bin\drmemory.exe
+:: }}}
+goto :RUN_TESTS
+
+:SETUP_TSAN
+:: Set up PIN_COMMAND to invoke TSan {{{1
+set TSAN_PATH=%THISDIR%..\..\third_party\tsan
+set TSAN_SFX=%TSAN_PATH%\tsan-x86-windows-sfx.exe
+if EXIST %TSAN_SFX% GOTO TSAN_BINARY_OK
+echo "Can't find ThreadSanitizer executables."
+echo "See http://www.chromium.org/developers/how-tos/using-valgrind/threadsanitizer/threadsanitizer-on-windows"
+echo "for the instructions on how to get them."
+exit /B 1
+
+:TSAN_BINARY_OK
+%TSAN_SFX% -o%TSAN_PATH%\unpacked -y
+set PIN_COMMAND=%TSAN_PATH%\unpacked\tsan-x86-windows\tsan.bat
+:: }}}
+goto :RUN_TESTS
+
+:RUN_TESTS
+set PYTHONPATH=%THISDIR%../python/google
+set RUNNING_ON_VALGRIND=yes
+python %THISDIR%/chrome_tests.py %*
diff --git a/chromium/tools/valgrind/chrome_tests.py b/chromium/tools/valgrind/chrome_tests.py
new file mode 100755
index 00000000000..07de66b2d61
--- /dev/null
+++ b/chromium/tools/valgrind/chrome_tests.py
@@ -0,0 +1,626 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+''' Runs various chrome tests through valgrind_test.py.'''
+
+import glob
+import logging
+import multiprocessing
+import optparse
+import os
+import stat
+import sys
+
+import logging_utils
+import path_utils
+
+import common
+import valgrind_test
+
+class TestNotFound(Exception): pass
+
+class MultipleGTestFiltersSpecified(Exception): pass
+
+class BuildDirNotFound(Exception): pass
+
+class BuildDirAmbiguous(Exception): pass
+
+class ChromeTests:
+ SLOW_TOOLS = ["memcheck", "tsan", "tsan_rv", "drmemory"]
+ LAYOUT_TESTS_DEFAULT_CHUNK_SIZE = 500
+
+ def __init__(self, options, args, test):
+ if ':' in test:
+ (self._test, self._gtest_filter) = test.split(':', 1)
+ else:
+ self._test = test
+ self._gtest_filter = options.gtest_filter
+
+ if self._test not in self._test_list:
+ raise TestNotFound("Unknown test: %s" % test)
+
+ if options.gtest_filter and options.gtest_filter != self._gtest_filter:
+ raise MultipleGTestFiltersSpecified("Can not specify both --gtest_filter "
+ "and --test %s" % test)
+
+ self._options = options
+ self._args = args
+
+ script_dir = path_utils.ScriptDir()
+ # Compute the top of the tree (the "source dir") from the script dir (where
+ # this script lives). We assume that the script dir is in tools/valgrind/
+ # relative to the top of the tree.
+ self._source_dir = os.path.dirname(os.path.dirname(script_dir))
+ # since this path is used for string matching, make sure it's always
+ # an absolute Unix-style path
+ self._source_dir = os.path.abspath(self._source_dir).replace('\\', '/')
+ valgrind_test_script = os.path.join(script_dir, "valgrind_test.py")
+ self._command_preamble = ["--source_dir=%s" % (self._source_dir)]
+
+ if not self._options.build_dir:
+ dirs = [
+ os.path.join(self._source_dir, "xcodebuild", "Debug"),
+ os.path.join(self._source_dir, "out", "Debug"),
+ os.path.join(self._source_dir, "build", "Debug"),
+ ]
+ build_dir = [d for d in dirs if os.path.isdir(d)]
+ if len(build_dir) > 1:
+ raise BuildDirAmbiguous("Found more than one suitable build dir:\n"
+ "%s\nPlease specify just one "
+ "using --build_dir" % ", ".join(build_dir))
+ elif build_dir:
+ self._options.build_dir = build_dir[0]
+ else:
+ self._options.build_dir = None
+
+ if self._options.build_dir:
+ build_dir = os.path.abspath(self._options.build_dir)
+ self._command_preamble += ["--build_dir=%s" % (self._options.build_dir)]
+
+ def _EnsureBuildDirFound(self):
+ if not self._options.build_dir:
+ raise BuildDirNotFound("Oops, couldn't find a build dir, please "
+ "specify it manually using --build_dir")
+
+ def _DefaultCommand(self, tool, exe=None, valgrind_test_args=None):
+ '''Generates the default command array that most tests will use.'''
+ if exe and common.IsWindows():
+ exe += '.exe'
+
+ cmd = list(self._command_preamble)
+
+ # Find all suppressions matching the following pattern:
+ # tools/valgrind/TOOL/suppressions[_PLATFORM].txt
+ # and list them with --suppressions= prefix.
+ script_dir = path_utils.ScriptDir()
+ tool_name = tool.ToolName();
+ suppression_file = os.path.join(script_dir, tool_name, "suppressions.txt")
+ if os.path.exists(suppression_file):
+ cmd.append("--suppressions=%s" % suppression_file)
+ # Platform-specific suppression
+ for platform in common.PlatformNames():
+ platform_suppression_file = \
+ os.path.join(script_dir, tool_name, 'suppressions_%s.txt' % platform)
+ if os.path.exists(platform_suppression_file):
+ cmd.append("--suppressions=%s" % platform_suppression_file)
+
+ if self._options.valgrind_tool_flags:
+ cmd += self._options.valgrind_tool_flags.split(" ")
+ if self._options.keep_logs:
+ cmd += ["--keep_logs"]
+ if valgrind_test_args != None:
+ for arg in valgrind_test_args:
+ cmd.append(arg)
+ if exe:
+ self._EnsureBuildDirFound()
+ cmd.append(os.path.join(self._options.build_dir, exe))
+ # Valgrind runs tests slowly, so slow tests hurt more; show elapased time
+ # so we can find the slowpokes.
+ cmd.append("--gtest_print_time")
+ if self._options.gtest_repeat:
+ cmd.append("--gtest_repeat=%s" % self._options.gtest_repeat)
+ return cmd
+
+ def Run(self):
+ ''' Runs the test specified by command-line argument --test '''
+ logging.info("running test %s" % (self._test))
+ return self._test_list[self._test](self)
+
+ def _AppendGtestFilter(self, tool, name, cmd):
+ '''Append an appropriate --gtest_filter flag to the googletest binary
+ invocation.
+ If the user passed his own filter mentioning only one test, just use it.
+ Othewise, filter out tests listed in the appropriate gtest_exclude files.
+ '''
+ if (self._gtest_filter and
+ ":" not in self._gtest_filter and
+ "?" not in self._gtest_filter and
+ "*" not in self._gtest_filter):
+ cmd.append("--gtest_filter=%s" % self._gtest_filter)
+ return
+
+ filters = []
+ gtest_files_dir = os.path.join(path_utils.ScriptDir(), "gtest_exclude")
+
+ gtest_filter_files = [
+ os.path.join(gtest_files_dir, name + ".gtest-%s.txt" % tool.ToolName())]
+ # Use ".gtest.txt" files only for slow tools, as they now contain
+ # Valgrind- and Dr.Memory-specific filters.
+ # TODO(glider): rename the files to ".gtest_slow.txt"
+ if tool.ToolName() in ChromeTests.SLOW_TOOLS:
+ gtest_filter_files += [os.path.join(gtest_files_dir, name + ".gtest.txt")]
+ for platform_suffix in common.PlatformNames():
+ gtest_filter_files += [
+ os.path.join(gtest_files_dir, name + ".gtest_%s.txt" % platform_suffix),
+ os.path.join(gtest_files_dir, name + ".gtest-%s_%s.txt" % \
+ (tool.ToolName(), platform_suffix))]
+ logging.info("Reading gtest exclude filter files:")
+ for filename in gtest_filter_files:
+ # strip the leading absolute path (may be very long on the bot)
+ # and the following / or \.
+ readable_filename = filename.replace("\\", "/") # '\' on Windows
+ readable_filename = readable_filename.replace(self._source_dir, "")[1:]
+ if not os.path.exists(filename):
+ logging.info(" \"%s\" - not found" % readable_filename)
+ continue
+ logging.info(" \"%s\" - OK" % readable_filename)
+ f = open(filename, 'r')
+ for line in f.readlines():
+ if line.startswith("#") or line.startswith("//") or line.isspace():
+ continue
+ line = line.rstrip()
+ test_prefixes = ["FLAKY", "FAILS"]
+ for p in test_prefixes:
+ # Strip prefixes from the test names.
+ line = line.replace(".%s_" % p, ".")
+ # Exclude the original test name.
+ filters.append(line)
+ if line[-2:] != ".*":
+ # List all possible prefixes if line doesn't end with ".*".
+ for p in test_prefixes:
+ filters.append(line.replace(".", ".%s_" % p))
+ # Get rid of duplicates.
+ filters = set(filters)
+ gtest_filter = self._gtest_filter
+ if len(filters):
+ if gtest_filter:
+ gtest_filter += ":"
+ if gtest_filter.find("-") < 0:
+ gtest_filter += "-"
+ else:
+ gtest_filter = "-"
+ gtest_filter += ":".join(filters)
+ if gtest_filter:
+ cmd.append("--gtest_filter=%s" % gtest_filter)
+
+ @staticmethod
+ def ShowTests():
+ test_to_names = {}
+ for name, test_function in ChromeTests._test_list.iteritems():
+ test_to_names.setdefault(test_function, []).append(name)
+
+ name_to_aliases = {}
+ for names in test_to_names.itervalues():
+ names.sort(key=lambda name: len(name))
+ name_to_aliases[names[0]] = names[1:]
+
+ print
+ print "Available tests:"
+ print "----------------"
+ for name, aliases in sorted(name_to_aliases.iteritems()):
+ if aliases:
+ print " {} (aka {})".format(name, ', '.join(aliases))
+ else:
+ print " {}".format(name)
+
+ def SetupLdPath(self, requires_build_dir):
+ if requires_build_dir:
+ self._EnsureBuildDirFound()
+ elif not self._options.build_dir:
+ return
+
+ # Append build_dir to LD_LIBRARY_PATH so external libraries can be loaded.
+ if (os.getenv("LD_LIBRARY_PATH")):
+ os.putenv("LD_LIBRARY_PATH", "%s:%s" % (os.getenv("LD_LIBRARY_PATH"),
+ self._options.build_dir))
+ else:
+ os.putenv("LD_LIBRARY_PATH", self._options.build_dir)
+
+ def SimpleTest(self, module, name, valgrind_test_args=None, cmd_args=None):
+ tool = valgrind_test.CreateTool(self._options.valgrind_tool)
+ cmd = self._DefaultCommand(tool, name, valgrind_test_args)
+ self._AppendGtestFilter(tool, name, cmd)
+ cmd.extend(['--test-tiny-timeout=1000'])
+ if cmd_args:
+ cmd.extend(cmd_args)
+
+ self.SetupLdPath(True)
+ return tool.Run(cmd, module)
+
+ def RunCmdLine(self):
+ tool = valgrind_test.CreateTool(self._options.valgrind_tool)
+ cmd = self._DefaultCommand(tool, None, self._args)
+ self.SetupLdPath(False)
+ return tool.Run(cmd, None)
+
+ def TestAppList(self):
+ return self.SimpleTest("app_list", "app_list_unittests")
+
+ def TestAsh(self):
+ return self.SimpleTest("ash", "ash_unittests")
+
+ def TestAura(self):
+ return self.SimpleTest("aura", "aura_unittests")
+
+ def TestBase(self):
+ return self.SimpleTest("base", "base_unittests")
+
+ def TestChromeOS(self):
+ return self.SimpleTest("chromeos", "chromeos_unittests")
+
+ def TestComponents(self):
+ return self.SimpleTest("components", "components_unittests")
+
+ def TestCompositor(self):
+ return self.SimpleTest("compositor", "compositor_unittests")
+
+ def TestContent(self):
+ return self.SimpleTest("content", "content_unittests")
+
+ def TestContentBrowser(self):
+ return self.SimpleTest("content", "content_browsertests")
+
+ def TestCourgette(self):
+ return self.SimpleTest("courgette", "courgette_unittests")
+
+ def TestCrypto(self):
+ return self.SimpleTest("crypto", "crypto_unittests")
+
+ def TestDevice(self):
+ return self.SimpleTest("device", "device_unittests")
+
+ def TestFFmpeg(self):
+ return self.SimpleTest("chrome", "ffmpeg_unittests")
+
+ def TestFFmpegRegressions(self):
+ return self.SimpleTest("chrome", "ffmpeg_regression_tests")
+
+ def TestGPU(self):
+ return self.SimpleTest("gpu", "gpu_unittests")
+
+ def TestIpc(self):
+ return self.SimpleTest("ipc", "ipc_tests",
+ valgrind_test_args=["--trace_children"])
+
+ def TestJingle(self):
+ return self.SimpleTest("chrome", "jingle_unittests")
+
+ def TestMedia(self):
+ return self.SimpleTest("chrome", "media_unittests")
+
+ def TestMessageCenter(self):
+ return self.SimpleTest("message_center", "message_center_unittests")
+
+ def TestNet(self):
+ return self.SimpleTest("net", "net_unittests")
+
+ def TestNetPerf(self):
+ return self.SimpleTest("net", "net_perftests")
+
+ def TestPPAPI(self):
+ return self.SimpleTest("chrome", "ppapi_unittests")
+
+ def TestPrinting(self):
+ return self.SimpleTest("chrome", "printing_unittests")
+
+ def TestRemoting(self):
+ return self.SimpleTest("chrome", "remoting_unittests",
+ cmd_args=[
+ "--ui-test-action-timeout=60000",
+ "--ui-test-action-max-timeout=150000"])
+
+ def TestSql(self):
+ return self.SimpleTest("chrome", "sql_unittests")
+
+ def TestSync(self):
+ return self.SimpleTest("chrome", "sync_unit_tests")
+
+ def TestLinuxSandbox(self):
+ return self.SimpleTest("sandbox", "sandbox_linux_unittests")
+
+ def TestUnit(self):
+ # http://crbug.com/51716
+ # Disabling all unit tests
+ # Problems reappeared after r119922
+ if common.IsMac() and (self._options.valgrind_tool == "memcheck"):
+ logging.warning("unit_tests are disabled for memcheck on MacOS.")
+ return 0;
+ return self.SimpleTest("chrome", "unit_tests")
+
+ def TestUIUnit(self):
+ return self.SimpleTest("chrome", "ui_unittests")
+
+ def TestURL(self):
+ return self.SimpleTest("chrome", "url_unittests")
+
+ def TestViews(self):
+ return self.SimpleTest("views", "views_unittests")
+
+ # Valgrind timeouts are in seconds.
+ UI_VALGRIND_ARGS = ["--timeout=14400", "--trace_children", "--indirect"]
+ # UI test timeouts are in milliseconds.
+ UI_TEST_ARGS = ["--ui-test-action-timeout=60000",
+ "--ui-test-action-max-timeout=150000",
+ "--no-sandbox"]
+
+ # TODO(thestig) fine-tune these values.
+ # Valgrind timeouts are in seconds.
+ BROWSER_VALGRIND_ARGS = ["--timeout=50000", "--trace_children", "--indirect"]
+ # Browser test timeouts are in milliseconds.
+ BROWSER_TEST_ARGS = ["--ui-test-action-timeout=400000",
+ "--ui-test-action-max-timeout=800000",
+ "--no-sandbox"]
+
+ def TestAutomatedUI(self):
+ return self.SimpleTest("chrome", "automated_ui_tests",
+ valgrind_test_args=self.UI_VALGRIND_ARGS,
+ cmd_args=self.UI_TEST_ARGS)
+
+ def TestBrowser(self):
+ return self.SimpleTest("chrome", "browser_tests",
+ valgrind_test_args=self.BROWSER_VALGRIND_ARGS,
+ cmd_args=self.BROWSER_TEST_ARGS)
+
+ def TestInteractiveUI(self):
+ return self.SimpleTest("chrome", "interactive_ui_tests",
+ valgrind_test_args=self.UI_VALGRIND_ARGS,
+ cmd_args=self.UI_TEST_ARGS)
+
+ def TestReliability(self):
+ script_dir = path_utils.ScriptDir()
+ url_list_file = os.path.join(script_dir, "reliability", "url_list.txt")
+ return self.SimpleTest("chrome", "reliability_tests",
+ valgrind_test_args=self.UI_VALGRIND_ARGS,
+ cmd_args=(self.UI_TEST_ARGS +
+ ["--list=%s" % url_list_file]))
+
+ def TestSafeBrowsing(self):
+ return self.SimpleTest("chrome", "safe_browsing_tests",
+ valgrind_test_args=self.UI_VALGRIND_ARGS,
+ cmd_args=(["--ui-test-action-max-timeout=450000"]))
+
+ def TestSyncIntegration(self):
+ return self.SimpleTest("chrome", "sync_integration_tests",
+ valgrind_test_args=self.UI_VALGRIND_ARGS,
+ cmd_args=(["--ui-test-action-max-timeout=450000"]))
+
+ def TestLayoutChunk(self, chunk_num, chunk_size):
+ # Run tests [chunk_num*chunk_size .. (chunk_num+1)*chunk_size) from the
+ # list of tests. Wrap around to beginning of list at end.
+ # If chunk_size is zero, run all tests in the list once.
+ # If a text file is given as argument, it is used as the list of tests.
+ #
+ # Build the ginormous commandline in 'cmd'.
+ # It's going to be roughly
+ # python valgrind_test.py ... python run_webkit_tests.py ...
+ # but we'll use the --indirect flag to valgrind_test.py
+ # to avoid valgrinding python.
+ # Start by building the valgrind_test.py commandline.
+ tool = valgrind_test.CreateTool(self._options.valgrind_tool)
+ cmd = self._DefaultCommand(tool)
+ cmd.append("--trace_children")
+ cmd.append("--indirect_webkit_layout")
+ cmd.append("--ignore_exit_code")
+ # Now build script_cmd, the run_webkits_tests.py commandline
+ # Store each chunk in its own directory so that we can find the data later
+ chunk_dir = os.path.join("layout", "chunk_%05d" % chunk_num)
+ out_dir = os.path.join(path_utils.ScriptDir(), "latest")
+ out_dir = os.path.join(out_dir, chunk_dir)
+ if os.path.exists(out_dir):
+ old_files = glob.glob(os.path.join(out_dir, "*.txt"))
+ for f in old_files:
+ os.remove(f)
+ else:
+ os.makedirs(out_dir)
+ script = os.path.join(self._source_dir, "webkit", "tools", "layout_tests",
+ "run_webkit_tests.py")
+ # http://crbug.com/260627: After the switch to content_shell from DRT, each
+ # test now brings up 3 processes. Under Valgrind, they become memory bound
+ # and can eventually OOM if we don't reduce the total count.
+ jobs = int(multiprocessing.cpu_count() * 0.3)
+ script_cmd = ["python", script, "-v",
+ "--run-singly", # run a separate DumpRenderTree for each test
+ "--fully-parallel",
+ "--child-processes=%d" % jobs,
+ "--time-out-ms=200000",
+ "--no-retry-failures", # retrying takes too much time
+ # http://crbug.com/176908: Don't launch a browser when done.
+ "--no-show-results",
+ "--nocheck-sys-deps"]
+ # Pass build mode to run_webkit_tests.py. We aren't passed it directly,
+ # so parse it out of build_dir. run_webkit_tests.py can only handle
+ # the two values "Release" and "Debug".
+ # TODO(Hercules): unify how all our scripts pass around build mode
+ # (--mode / --target / --build_dir / --debug)
+ if self._options.build_dir.endswith("Debug"):
+ script_cmd.append("--debug");
+ if (chunk_size > 0):
+ script_cmd.append("--run-chunk=%d:%d" % (chunk_num, chunk_size))
+ if len(self._args):
+ # if the arg is a txt file, then treat it as a list of tests
+ if os.path.isfile(self._args[0]) and self._args[0][-4:] == ".txt":
+ script_cmd.append("--test-list=%s" % self._args[0])
+ else:
+ script_cmd.extend(self._args)
+ self._AppendGtestFilter(tool, "layout", script_cmd)
+ # Now run script_cmd with the wrapper in cmd
+ cmd.extend(["--"])
+ cmd.extend(script_cmd)
+
+ # Layout tests often times fail quickly, but the buildbot remains green.
+ # Detect this situation when running with the default chunk size.
+ if chunk_size == self.LAYOUT_TESTS_DEFAULT_CHUNK_SIZE:
+ min_runtime_in_seconds=120
+ else:
+ min_runtime_in_seconds=0
+ ret = tool.Run(cmd, "layout", min_runtime_in_seconds=min_runtime_in_seconds)
+ return ret
+
+
+ def TestLayout(self):
+ # A "chunk file" is maintained in the local directory so that each test
+ # runs a slice of the layout tests of size chunk_size that increments with
+ # each run. Since tests can be added and removed from the layout tests at
+ # any time, this is not going to give exact coverage, but it will allow us
+ # to continuously run small slices of the layout tests under valgrind rather
+ # than having to run all of them in one shot.
+ chunk_size = self._options.num_tests
+ if (chunk_size == 0):
+ return self.TestLayoutChunk(0, 0)
+ chunk_num = 0
+ chunk_file = os.path.join("valgrind_layout_chunk.txt")
+ logging.info("Reading state from " + chunk_file)
+ try:
+ f = open(chunk_file)
+ if f:
+ str = f.read()
+ if len(str):
+ chunk_num = int(str)
+ # This should be enough so that we have a couple of complete runs
+ # of test data stored in the archive (although note that when we loop
+ # that we almost guaranteed won't be at the end of the test list)
+ if chunk_num > 10000:
+ chunk_num = 0
+ f.close()
+ except IOError, (errno, strerror):
+ logging.error("error reading from file %s (%d, %s)" % (chunk_file,
+ errno, strerror))
+ # Save the new chunk size before running the tests. Otherwise if a
+ # particular chunk hangs the bot, the chunk number will never get
+ # incremented and the bot will be wedged.
+ logging.info("Saving state to " + chunk_file)
+ try:
+ f = open(chunk_file, "w")
+ chunk_num += 1
+ f.write("%d" % chunk_num)
+ f.close()
+ except IOError, (errno, strerror):
+ logging.error("error writing to file %s (%d, %s)" % (chunk_file, errno,
+ strerror))
+ # Since we're running small chunks of the layout tests, it's important to
+ # mark the ones that have errors in them. These won't be visible in the
+ # summary list for long, but will be useful for someone reviewing this bot.
+ return self.TestLayoutChunk(chunk_num, chunk_size)
+
+ # The known list of tests.
+ # Recognise the original abbreviations as well as full executable names.
+ _test_list = {
+ "cmdline" : RunCmdLine,
+ "app_list": TestAppList, "app_list_unittests": TestAppList,
+ "ash": TestAsh, "ash_unittests": TestAsh,
+ "aura": TestAura, "aura_unittests": TestAura,
+ "automated_ui" : TestAutomatedUI,
+ "base": TestBase, "base_unittests": TestBase,
+ "browser": TestBrowser, "browser_tests": TestBrowser,
+ "chromeos": TestChromeOS, "chromeos_unittests": TestChromeOS,
+ "components": TestComponents,"components_unittests": TestComponents,
+ "compositor": TestCompositor,"compositor_unittests": TestCompositor,
+ "content": TestContent, "content_unittests": TestContent,
+ "content_browsertests": TestContentBrowser,
+ "courgette": TestCourgette, "courgette_unittests": TestCourgette,
+ "crypto": TestCrypto, "crypto_unittests": TestCrypto,
+ "device": TestDevice, "device_unittests": TestDevice,
+ "ffmpeg": TestFFmpeg, "ffmpeg_unittests": TestFFmpeg,
+ "ffmpeg_regression_tests": TestFFmpegRegressions,
+ "gpu": TestGPU, "gpu_unittests": TestGPU,
+ "ipc": TestIpc, "ipc_tests": TestIpc,
+ "interactive_ui": TestInteractiveUI,
+ "jingle": TestJingle, "jingle_unittests": TestJingle,
+ "layout": TestLayout, "layout_tests": TestLayout,
+ "webkit": TestLayout,
+ "media": TestMedia, "media_unittests": TestMedia,
+ "message_center": TestMessageCenter,
+ "message_center_unittests" : TestMessageCenter,
+ "net": TestNet, "net_unittests": TestNet,
+ "net_perf": TestNetPerf, "net_perftests": TestNetPerf,
+ "ppapi": TestPPAPI, "ppapi_unittests": TestPPAPI,
+ "printing": TestPrinting, "printing_unittests": TestPrinting,
+ "reliability": TestReliability, "reliability_tests": TestReliability,
+ "remoting": TestRemoting, "remoting_unittests": TestRemoting,
+ "safe_browsing": TestSafeBrowsing, "safe_browsing_tests": TestSafeBrowsing,
+ "sandbox": TestLinuxSandbox, "sandbox_linux_unittests": TestLinuxSandbox,
+ "sql": TestSql, "sql_unittests": TestSql,
+ "sync": TestSync, "sync_unit_tests": TestSync,
+ "sync_integration_tests": TestSyncIntegration,
+ "sync_integration": TestSyncIntegration,
+ "ui_unit": TestUIUnit, "ui_unittests": TestUIUnit,
+ "unit": TestUnit, "unit_tests": TestUnit,
+ "url": TestURL, "url_unittests": TestURL,
+ "views": TestViews, "views_unittests": TestViews,
+ }
+
+
+def _main():
+ parser = optparse.OptionParser("usage: %prog -b <dir> -t <test> "
+ "[-t <test> ...]")
+ parser.disable_interspersed_args()
+
+ parser.add_option("", "--help-tests", dest="help_tests", action="store_true",
+ default=False, help="List all available tests")
+ parser.add_option("-b", "--build_dir",
+ help="the location of the compiler output")
+ parser.add_option("-t", "--test", action="append", default=[],
+ help="which test to run, supports test:gtest_filter format "
+ "as well.")
+ parser.add_option("", "--baseline", action="store_true", default=False,
+ help="generate baseline data instead of validating")
+ parser.add_option("", "--gtest_filter",
+ help="additional arguments to --gtest_filter")
+ parser.add_option("", "--gtest_repeat",
+ help="argument for --gtest_repeat")
+ parser.add_option("-v", "--verbose", action="store_true", default=False,
+ help="verbose output - enable debug log messages")
+ parser.add_option("", "--tool", dest="valgrind_tool", default="memcheck",
+ help="specify a valgrind tool to run the tests under")
+ parser.add_option("", "--tool_flags", dest="valgrind_tool_flags", default="",
+ help="specify custom flags for the selected valgrind tool")
+ parser.add_option("", "--keep_logs", action="store_true", default=False,
+ help="store memory tool logs in the <tool>.logs directory "
+ "instead of /tmp.\nThis can be useful for tool "
+ "developers/maintainers.\nPlease note that the <tool>"
+ ".logs directory will be clobbered on tool startup.")
+ parser.add_option("-n", "--num_tests", type="int",
+ default=ChromeTests.LAYOUT_TESTS_DEFAULT_CHUNK_SIZE,
+ help="for layout tests: # of subtests per run. 0 for all.")
+ # TODO(thestig) Remove this if we can.
+ parser.add_option("", "--gtest_color", dest="gtest_color", default="no",
+ help="dummy compatibility flag for sharding_supervisor.")
+
+ options, args = parser.parse_args()
+
+ if options.verbose:
+ logging_utils.config_root(logging.DEBUG)
+ else:
+ logging_utils.config_root()
+
+ if options.help_tests:
+ ChromeTests.ShowTests()
+ return 0
+
+ if not options.test:
+ parser.error("--test not specified")
+
+ if len(options.test) != 1 and options.gtest_filter:
+ parser.error("--gtest_filter and multiple tests don't make sense together")
+
+ for t in options.test:
+ tests = ChromeTests(options, args, t)
+ ret = tests.Run()
+ if ret: return ret
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(_main())
diff --git a/chromium/tools/valgrind/chrome_tests.sh b/chromium/tools/valgrind/chrome_tests.sh
new file mode 100755
index 00000000000..d8cebd4a569
--- /dev/null
+++ b/chromium/tools/valgrind/chrome_tests.sh
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Set up some paths and re-direct the arguments to chrome_tests.py
+
+export THISDIR=`dirname $0`
+ARGV_COPY="$@"
+
+# We need to set CHROME_VALGRIND iff using Memcheck or TSan-Valgrind:
+# tools/valgrind/chrome_tests.sh --tool memcheck
+# or
+# tools/valgrind/chrome_tests.sh --tool=memcheck
+# (same for "--tool=tsan")
+tool="memcheck" # Default to memcheck.
+while (( "$#" ))
+do
+ if [[ "$1" == "--tool" ]]
+ then
+ tool="$2"
+ shift
+ elif [[ "$1" =~ --tool=(.*) ]]
+ then
+ tool="${BASH_REMATCH[1]}"
+ fi
+ shift
+done
+
+NEEDS_VALGRIND=0
+NEEDS_DRMEMORY=0
+
+case "$tool" in
+ "memcheck")
+ NEEDS_VALGRIND=1
+ ;;
+ "tsan" | "tsan_rv")
+ if [ "`uname -s`" == CYGWIN* ]
+ then
+ NEEDS_PIN=1
+ else
+ NEEDS_VALGRIND=1
+ fi
+ ;;
+ "drmemory" | "drmemory_light" | "drmemory_full" | "drmemory_pattern")
+ NEEDS_DRMEMORY=1
+ ;;
+esac
+
+if [ "$NEEDS_VALGRIND" == "1" ]
+then
+ CHROME_VALGRIND=`sh $THISDIR/locate_valgrind.sh`
+ if [ "$CHROME_VALGRIND" = "" ]
+ then
+ # locate_valgrind.sh failed
+ exit 1
+ fi
+ echo "Using valgrind binaries from ${CHROME_VALGRIND}"
+
+ PATH="${CHROME_VALGRIND}/bin:$PATH"
+ # We need to set these variables to override default lib paths hard-coded into
+ # Valgrind binary.
+ export VALGRIND_LIB="$CHROME_VALGRIND/lib/valgrind"
+ export VALGRIND_LIB_INNER="$CHROME_VALGRIND/lib/valgrind"
+
+ # Clean up some /tmp directories that might be stale due to interrupted
+ # chrome_tests.py execution.
+ # FYI:
+ # -mtime +1 <- only print files modified more than 24h ago,
+ # -print0/-0 are needed to handle possible newlines in the filenames.
+ echo "Cleanup /tmp from Valgrind stuff"
+ find /tmp -maxdepth 1 \(\
+ -name "vgdb-pipe-*" -or -name "vg_logs_*" -or -name "valgrind.*" \
+ \) -mtime +1 -print0 | xargs -0 rm -rf
+fi
+
+if [ "$NEEDS_DRMEMORY" == "1" ]
+then
+ if [ -z "$DRMEMORY_COMMAND" ]
+ then
+ DRMEMORY_PATH="$THISDIR/../../third_party/drmemory"
+ DRMEMORY_SFX="$DRMEMORY_PATH/drmemory-windows-sfx.exe"
+ if [ ! -f "$DRMEMORY_SFX" ]
+ then
+ echo "Can't find Dr. Memory executables."
+ echo "See http://www.chromium.org/developers/how-tos/using-valgrind/dr-memory"
+ echo "for the instructions on how to get them."
+ exit 1
+ fi
+
+ chmod +x "$DRMEMORY_SFX" # Cygwin won't run it without +x.
+ "$DRMEMORY_SFX" -o"$DRMEMORY_PATH/unpacked" -y
+ export DRMEMORY_COMMAND="$DRMEMORY_PATH/unpacked/bin/drmemory.exe"
+ fi
+fi
+
+if [ "$NEEDS_PIN" == "1" ]
+then
+ if [ -z "$PIN_COMMAND" ]
+ then
+ # Set up PIN_COMMAND to invoke TSan.
+ TSAN_PATH="$THISDIR/../../third_party/tsan"
+ TSAN_SFX="$TSAN_PATH/tsan-x86-windows-sfx.exe"
+ echo "$TSAN_SFX"
+ if [ ! -f $TSAN_SFX ]
+ then
+ echo "Can't find ThreadSanitizer executables."
+ echo "See http://www.chromium.org/developers/how-tos/using-valgrind/threadsanitizer/threadsanitizer-on-windows"
+ echo "for the instructions on how to get them."
+ exit 1
+ fi
+
+ chmod +x "$TSAN_SFX" # Cygwin won't run it without +x.
+ "$TSAN_SFX" -o"$TSAN_PATH"/unpacked -y
+ export PIN_COMMAND="$TSAN_PATH/unpacked/tsan-x86-windows/tsan.bat"
+ fi
+fi
+
+
+PYTHONPATH=$THISDIR/../python/google python \
+ "$THISDIR/chrome_tests.py" $ARGV_COPY
diff --git a/chromium/tools/valgrind/common.py b/chromium/tools/valgrind/common.py
new file mode 100644
index 00000000000..7e163e3c602
--- /dev/null
+++ b/chromium/tools/valgrind/common.py
@@ -0,0 +1,252 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import platform
+import os
+import signal
+import subprocess
+import sys
+import time
+
+
+class NotImplementedError(Exception):
+ pass
+
+
+class TimeoutError(Exception):
+ pass
+
+
+def RunSubprocessInBackground(proc):
+ """Runs a subprocess in the background. Returns a handle to the process."""
+ logging.info("running %s in the background" % " ".join(proc))
+ return subprocess.Popen(proc)
+
+
+def RunSubprocess(proc, timeout=0):
+ """ Runs a subprocess, until it finishes or |timeout| is exceeded and the
+ process is killed with taskkill. A |timeout| <= 0 means no timeout.
+
+ Args:
+ proc: list of process components (exe + args)
+ timeout: how long to wait before killing, <= 0 means wait forever
+ """
+
+ logging.info("running %s, timeout %d sec" % (" ".join(proc), timeout))
+ sys.stdout.flush()
+ sys.stderr.flush()
+
+ # Manually read and print out stdout and stderr.
+ # By default, the subprocess is supposed to inherit these from its parent,
+ # however when run under buildbot, it seems unable to read data from a
+ # grandchild process, so we have to read the child and print the data as if
+ # it came from us for buildbot to read it. We're not sure why this is
+ # necessary.
+ # TODO(erikkay): should we buffer stderr and stdout separately?
+ p = subprocess.Popen(proc, universal_newlines=True,
+ bufsize=0, # unbuffered
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+ logging.info("started subprocess")
+
+ did_timeout = False
+ if timeout > 0:
+ wait_until = time.time() + timeout
+ while p.poll() is None and not did_timeout:
+ # Have to use readline rather than readlines() or "for line in p.stdout:",
+ # otherwise we get buffered even with bufsize=0.
+ line = p.stdout.readline()
+ while line and not did_timeout:
+ sys.stdout.write(line)
+ sys.stdout.flush()
+ line = p.stdout.readline()
+ if timeout > 0:
+ did_timeout = time.time() > wait_until
+
+ if did_timeout:
+ logging.info("process timed out")
+ else:
+ logging.info("process ended, did not time out")
+
+ if did_timeout:
+ if IsWindows():
+ subprocess.call(["taskkill", "/T", "/F", "/PID", str(p.pid)])
+ else:
+ # Does this kill all children, too?
+ os.kill(p.pid, signal.SIGINT)
+ logging.error("KILLED %d" % p.pid)
+ # Give the process a chance to actually die before continuing
+ # so that cleanup can happen safely.
+ time.sleep(1.0)
+ logging.error("TIMEOUT waiting for %s" % proc[0])
+ raise TimeoutError(proc[0])
+ else:
+ for line in p.stdout:
+ sys.stdout.write(line)
+ if not IsMac(): # stdout flush fails on Mac
+ logging.info("flushing stdout")
+ sys.stdout.flush()
+
+ logging.info("collecting result code")
+ result = p.poll()
+ if result:
+ logging.error("%s exited with non-zero result code %d" % (proc[0], result))
+ return result
+
+
+def IsLinux():
+ return sys.platform.startswith('linux')
+
+
+def IsMac():
+ return sys.platform.startswith('darwin')
+
+
+def IsWindows():
+ return sys.platform == 'cygwin' or sys.platform.startswith('win')
+
+
+def WindowsVersionName():
+ """Returns the name of the Windows version if it is known, or None.
+
+ Possible return values are: xp, vista, 7, 8, or None
+ """
+ if sys.platform == 'cygwin':
+ # Windows version number is hiding in system name. Looks like:
+ # CYGWIN_NT-6.1-WOW64
+ try:
+ version_str = platform.uname()[0].split('-')[1]
+ except:
+ return None
+ elif sys.platform.startswith('win'):
+ # Normal Windows version string. Mine: 6.1.7601
+ version_str = platform.version()
+ else:
+ return None
+
+ parts = version_str.split('.')
+ try:
+ major = int(parts[0])
+ minor = int(parts[1])
+ except:
+ return None # Can't parse, unknown version.
+
+ if major == 5:
+ return 'xp'
+ elif major == 6 and minor == 0:
+ return 'vista'
+ elif major == 6 and minor == 1:
+ return '7'
+ elif major == 6 and minor == 2:
+ return '8' # Future proof. ;)
+ return None
+
+
+def PlatformNames():
+ """Return an array of string to be used in paths for the platform
+ (e.g. suppressions, gtest filters, ignore files etc.)
+ The first element of the array describes the 'main' platform
+ """
+ if IsLinux():
+ return ['linux']
+ if IsMac():
+ return ['mac']
+ if IsWindows():
+ names = ['win32']
+ version_name = WindowsVersionName()
+ if version_name is not None:
+ names.append('win-%s' % version_name)
+ return names
+ raise NotImplementedError('Unknown platform "%s".' % sys.platform)
+
+
+def PutEnvAndLog(env_name, env_value):
+ os.putenv(env_name, env_value)
+ logging.info('export %s=%s', env_name, env_value)
+
+def BoringCallers(mangled, use_re_wildcards):
+ """Return a list of 'boring' function names (optinally mangled)
+ with */? wildcards (optionally .*/.).
+ Boring = we drop off the bottom of stack traces below such functions.
+ """
+
+ need_mangling = [
+ # Don't show our testing framework:
+ ("testing::Test::Run", "_ZN7testing4Test3RunEv"),
+ ("testing::TestInfo::Run", "_ZN7testing8TestInfo3RunEv"),
+ ("testing::internal::Handle*ExceptionsInMethodIfSupported*",
+ "_ZN7testing8internal3?Handle*ExceptionsInMethodIfSupported*"),
+
+ # Depend on scheduling:
+ ("MessageLoop::Run", "_ZN11MessageLoop3RunEv"),
+ ("MessageLoop::RunTask", "_ZN11MessageLoop7RunTask*"),
+ ("RunnableMethod*", "_ZN14RunnableMethod*"),
+ ("DispatchToMethod*", "_Z*16DispatchToMethod*"),
+ ("base::internal::Invoker*::DoInvoke*",
+ "_ZN4base8internal8Invoker*DoInvoke*"), # Invoker{1,2,3}
+ ("base::internal::RunnableAdapter*::Run*",
+ "_ZN4base8internal15RunnableAdapter*Run*"),
+ ]
+
+ ret = []
+ for pair in need_mangling:
+ ret.append(pair[1 if mangled else 0])
+
+ ret += [
+ # Also don't show the internals of libc/pthread.
+ "start_thread",
+ "main",
+ "BaseThreadInitThunk",
+ ]
+
+ if use_re_wildcards:
+ for i in range(0, len(ret)):
+ ret[i] = ret[i].replace('*', '.*').replace('?', '.')
+
+ return ret
+
+def NormalizeWindowsPath(path):
+ """If we're using Cygwin Python, turn the path into a Windows path.
+
+ Don't turn forward slashes into backslashes for easier copy-pasting and
+ escaping.
+
+ TODO(rnk): If we ever want to cut out the subprocess invocation, we can use
+ _winreg to get the root Cygwin directory from the registry key:
+ HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin\setup\rootdir.
+ """
+ if sys.platform.startswith("cygwin"):
+ p = subprocess.Popen(["cygpath", "-m", path],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ (out, err) = p.communicate()
+ if err:
+ logging.warning("WARNING: cygpath error: %s", err)
+ return out.strip()
+ else:
+ return path
+
+############################
+# Common output format code
+
+def PrintUsedSuppressionsList(suppcounts):
+ """ Prints out the list of used suppressions in a format common to all the
+ memory tools. If the list is empty, prints nothing and returns False,
+ otherwise True.
+
+ suppcounts: a dictionary of used suppression counts,
+ Key -> name, Value -> count.
+ """
+ if not suppcounts:
+ return False
+
+ print "-----------------------------------------------------"
+ print "Suppressions used:"
+ print " count name"
+ for (name, count) in sorted(suppcounts.items(), key=lambda (k,v): (v,k)):
+ print "%7d %s" % (count, name)
+ print "-----------------------------------------------------"
+ sys.stdout.flush()
+ return True
diff --git a/chromium/tools/valgrind/drmemory.bat b/chromium/tools/valgrind/drmemory.bat
new file mode 100755
index 00000000000..46d5a4f09bb
--- /dev/null
+++ b/chromium/tools/valgrind/drmemory.bat
@@ -0,0 +1,5 @@
+@echo off
+:: Copyright (c) 2011 The Chromium Authors. All rights reserved.
+:: Use of this source code is governed by a BSD-style license that can be
+:: found in the LICENSE file.
+%~dp0\chrome_tests.bat -t cmdline --tool drmemory %*
diff --git a/chromium/tools/valgrind/drmemory/OWNERS b/chromium/tools/valgrind/drmemory/OWNERS
new file mode 100644
index 00000000000..72e8ffc0db8
--- /dev/null
+++ b/chromium/tools/valgrind/drmemory/OWNERS
@@ -0,0 +1 @@
+*
diff --git a/chromium/tools/valgrind/drmemory/PRESUBMIT.py b/chromium/tools/valgrind/drmemory/PRESUBMIT.py
new file mode 100644
index 00000000000..11c71478b78
--- /dev/null
+++ b/chromium/tools/valgrind/drmemory/PRESUBMIT.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into gcl.
+"""
+
+
+def CheckChange(input_api, output_api):
+ """Checks the DrMemory suppression files for bad suppressions."""
+
+ # TODO(timurrrr): find out how to do relative imports
+ # and remove this ugly hack. Also, the CheckChange function won't be needed.
+ tools_vg_path = input_api.os_path.join(input_api.PresubmitLocalPath(), '..')
+ import sys
+ old_path = sys.path
+ try:
+ sys.path = sys.path + [tools_vg_path]
+ import suppressions
+ return suppressions.PresubmitCheck(input_api, output_api)
+ finally:
+ sys.path = old_path
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+
+def GetPreferredTrySlaves():
+ return ['win_drmemory']
diff --git a/chromium/tools/valgrind/drmemory/suppressions.txt b/chromium/tools/valgrind/drmemory/suppressions.txt
new file mode 100644
index 00000000000..fcab5fce6d6
--- /dev/null
+++ b/chromium/tools/valgrind/drmemory/suppressions.txt
@@ -0,0 +1,456 @@
+# This file contains suppressions for the Dr.Memory tool, see
+# http://dev.chromium.org/developers/how-tos/using-drmemory
+#
+# This file contains suppressions for the DrMemory reports happening
+# in the 'light' mode (a.k.a. drmemory_light) as well as in the 'full' mode.
+# Please use suppressions_full.txt for all the reports that can happen only
+# in the full mode (drmemory_full),
+
+############################
+# Known reports on the third party we have no control over.
+
+# Reports from Sophos antivirus
+UNADDRESSABLE ACCESS
+name=Sophos UNADDR
+...
+sophos*.dll!*
+
+UNINITIALIZED READ
+name=Sophos UNINIT
+...
+sophos*.dll!*
+
+LEAK
+name=Sophos LEAK
+...
+sophos*.dll!*
+
+# Reports from Micorosft RDP ActiveX control (mstscax.dll)
+
+GDI USAGE ERROR
+name=crbug.com/177832: mstscax.dll causes "GDI USAGE ERROR" errors.
+...
+mstscax.dll!*
+
+UNADDRESSABLE ACCESS
+name=crbug.com/177832: mstscax.dll causes "UNADDRESSABLE ACCESS" errors.
+...
+mstscax.dll!*
+
+############################
+# Suppress some false reports due to bugs in Dr.Memory like wrong analysis
+# assumptions or unhandled syscalls
+
+# Please note: the following suppressions were written in the abscense of
+# private symbols so may need to be updated when we switch to auto-loading PDBs
+
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=12 UNADDR
+...
+SHELL32.dll!SHFileOperation*
+
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=40 UNADDR
+...
+WINSPOOL.DRV!*
+
+INVALID HEAP ARGUMENT
+name=http://code.google.com/p/drmemory/issues/detail?id=40 INVALID HEAP
+...
+WINSPOOL.DRV!*
+
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=59
+...
+*!SetEnvironmentVariable*
+
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=68 (UNADDR 1)
+...
+MSWSOCK.dll!WSPStartup
+
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=68 (UNADDR 2)
+...
+ntdll.dll!RtlValidateUnicodeString
+
+############################
+# TODO(timurrrr): investigate these
+UNADDRESSABLE ACCESS
+name=TODO SHParseDisplayName
+...
+*!SHParseDisplayName
+
+UNADDRESSABLE ACCESS
+name=TODO GetCanonicalPathInfo
+...
+*!GetCanonicalPathInfo*
+
+UNADDRESSABLE ACCESS
+name=TODO CreateDC
+...
+GDI32.dll!CreateDC*
+
+# This one looks interesting
+INVALID HEAP ARGUMENT
+name=TODO ExitProcess
+...
+KERNEL32.dll!ExitProcess
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/103365 (a)
+ppapi_tests.dll!*
+...
+ppapi_tests.dll!*
+*!base::internal::RunnableAdapter<*>::Run
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/103365 (b)
+ppapi_tests.dll!*
+...
+ppapi_tests.dll!*
+*!PP_RunCompletionCallback
+...
+*!base::internal::RunnableAdapter<*>::Run
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/107567 intentional mismatch in _DebugHeapDelete, no frame
+*!std::numpunct<*>::_Tidy
+*!std::numpunct<*>::~numpunct<*>
+
+# TODO(rbultje): Investigate if code fix is required instead.
+WARNING
+name=http://crbug.com/223255 - prefetches in vp8
+instruction=prefetch*
+ffmpegsumo.dll!ff_prefetch_mmxext
+ffmpegsumo.dll!vp8_decode_mb_row_no_filter
+
+############################
+# Intentional errors in Chromium tests (ToolsSanityTests)
+LEAK
+name=sanity test 01 (memory leak)
+base_unittests.exe!operator new
+base_unittests.exe!operator new[]
+base_unittests.exe!base::ToolsSanityTest_MemoryLeak_Test::TestBody
+
+# "..." is needed due to http://code.google.com/p/drmemory/issues/detail?id=666
+UNADDRESSABLE ACCESS
+name=sanity test 02 (malloc/read left)
+base_unittests.exe!*ReadValueOutOfArrayBoundsLeft
+...
+base_unittests.exe!base::ToolsSanityTest_AccessesToMallocMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=sanity test 03 (malloc/read right)
+base_unittests.exe!*ReadValueOutOfArrayBoundsRight
+base_unittests.exe!*MakeSomeErrors
+base_unittests.exe!base::ToolsSanityTest_AccessesToMallocMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=sanity test 04 (malloc/write left)
+base_unittests.exe!*WriteValueOutOfArrayBoundsLeft
+base_unittests.exe!*MakeSomeErrors
+base_unittests.exe!base::ToolsSanityTest_AccessesToMallocMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=sanity test 05 (malloc/write right)
+base_unittests.exe!*WriteValueOutOfArrayBoundsRight
+base_unittests.exe!*MakeSomeErrors
+base_unittests.exe!base::ToolsSanityTest_AccessesToMallocMemory_Test::TestBody
+
+# "..." is needed due to http://code.google.com/p/drmemory/issues/detail?id=666
+UNADDRESSABLE ACCESS
+name=sanity test 06 (new/read left)
+base_unittests.exe!*ReadValueOutOfArrayBoundsLeft
+...
+base_unittests.exe!base::ToolsSanityTest_AccessesToNewMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=sanity test 07 (new/read right)
+base_unittests.exe!*ReadValueOutOfArrayBoundsRight
+base_unittests.exe!*MakeSomeErrors
+base_unittests.exe!base::ToolsSanityTest_AccessesToNewMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=sanity test 08 (new/write left)
+base_unittests.exe!*WriteValueOutOfArrayBoundsLeft
+base_unittests.exe!*MakeSomeErrors
+base_unittests.exe!base::ToolsSanityTest_AccessesToNewMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=sanity test 09 (new/write right)
+base_unittests.exe!*WriteValueOutOfArrayBoundsRight
+base_unittests.exe!*MakeSomeErrors
+base_unittests.exe!base::ToolsSanityTest_AccessesToNewMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=sanity test 10 (write after free)
+base_unittests.exe!base::ToolsSanityTest_AccessesToMallocMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=sanity test 11 (write after delete)
+base_unittests.exe!base::ToolsSanityTest_AccessesToNewMemory_Test::TestBody
+
+INVALID HEAP ARGUMENT
+name=sanity test 12 (array deleted without [])
+base_unittests.exe!base::ToolsSanityTest_ArrayDeletedWithoutBraces_Test::TestBody
+
+INVALID HEAP ARGUMENT
+name=sanity test 13 (single element deleted with [])
+base_unittests.exe!base::ToolsSanityTest_SingleElementDeletedWithBraces_Test::TestBody
+
+UNINITIALIZED READ
+name=sanity test 14 (malloc/read uninit)
+base_unittests.exe!*ReadUninitializedValue
+base_unittests.exe!*MakeSomeErrors
+base_unittests.exe!base::ToolsSanityTest_AccessesToMallocMemory_Test::TestBody
+
+UNINITIALIZED READ
+name=sanity test 15 (new/read uninit)
+base_unittests.exe!*ReadUninitializedValue
+base_unittests.exe!*MakeSomeErrors
+base_unittests.exe!base::ToolsSanityTest_AccessesToNewMemory_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=AboutHandler::AboutCrash deliberate crash
+# TODO(bruening): switch to annotation once have support for that
+chrome.dll!AboutHandler::AboutCrash
+
+UNADDRESSABLE ACCESS
+name=RendererCrashTest.Crash deliberate crash
+# function is small, little risk for false negative in rest of it
+# TODO(bruening): switch to annotation once have support for that
+chrome.dll!HandleRendererErrorTestParameters
+
+UNADDRESSABLE ACCESS
+name=NPAPITesterBase.NoHangIfInitCrashes deliberate crash
+# function is small, little risk for false negative in rest of it
+# TODO(bruening): switch to annotation once have support for that
+npapi_test_plugin.dll!NPAPIClient::PluginClient::Initialize
+
+# Deliberate NULL deref to crash the child process
+UNADDRESSABLE ACCESS
+name=CrashingChildProcess deliberate crash
+*!CrashingChildProcess
+
+UNADDRESSABLE ACCESS
+name=::Crasher::Run deliberate crash
+*!base::`anonymous namespace'::Crasher::Run
+
+############################
+# Benign issues in Chromium
+
+WARNING
+name=http://crbug.com/72463 - prefetches in generated MemCopy
+instruction=prefetch*
+<not in a module>
+chrome.dll!v8::internal::CopyChars*
+
+WARNING
+name=prefetches in NVD3DUM.dll
+instruction=prefetch*
+NVD3DUM.dll!*
+
+WARNING
+name=prefetches in igdumd32.dll
+instruction=prefetch*
+igdumd32.dll!*
+
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=582 bizarre cl-generated read-beyond-TOS
+instruction=mov 0xfffffffc(%esp) -> %eax
+chrome.dll!WebCore::RenderStyle::resetBorder*
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/101537
+*!scoped_ptr<_TOKEN_USER>*
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/101717 (1)
+*!scoped_ptr<_TOKEN_DEFAULT_DACL>*
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/101717 (2)
+*!sandbox::PolicyBase::~PolicyBase
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/101717 (3)
+*!scoped_ptr<_UNICODE_STRING>::~scoped_ptr<_UNICODE_STRING>
+*!sandbox::GetHandleName
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/101717 (4)
+*!scoped_ptr<_OBJECT_NAME_INFORMATION>::~scoped_ptr<_OBJECT_NAME_INFORMATION>
+*!sandbox::GetPathFromHandle
+
+GDI USAGE ERROR
+name=http://code.google.com/p/drmemory/issues/detail?id=899 deleting bitmap which is probably safe
+system call NtGdiDeleteObjectApp
+*!skia::`anonymous namespace'::Bitmap::~Bitmap
+*!skia::`anonymous namespace'::Bitmap::`scalar deleting destructor'
+
+############################
+# Real issues in Chromium
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/88213
+*!base::win::ObjectWatcher::StopWatching
+*!base::win::ObjectWatcher::WillDestroyCurrentMessageLoop
+*!MessageLoop::~MessageLoop
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/96010
+*!TestingProfile::FinishInit
+*!TestingProfile::TestingProfile
+*!BrowserAboutHandlerTest_WillHandleBrowserAboutURL_Test::TestBody
+
+UNADDRESSABLE ACCESS
+name=http://crbug.com/106522
+npapi_test_plugin.dll!NPAPIClient::PluginTest::id
+npapi_test_plugin.dll!NPAPIClient::ExecuteGetJavascriptUrlTest::TimerProc
+
+# Bad GDI teardown sequence.
+GDI USAGE ERROR
+name=http://crbug.com/109963 a
+system call NtGdiDeleteObjectApp
+# usually one or two GDI32.dll frames here but sometimes in light mode
+# there are zero. still pretty narrow b/c of frames on either side.
+...
+*!skia::BitmapPlatformDevice::BitmapPlatformDeviceData::~BitmapPlatformDeviceData
+
+GDI USAGE ERROR
+name=http://crbug.com/109963 b
+system call NtGdiDeleteObjectApp
+# usually one or two GDI32.dll frames here but sometimes in light mode
+# there are zero. still pretty narrow b/c of frames on either side.
+...
+*!skia::BitmapPlatformDevice::BitmapPlatformDeviceData::ReleaseBitmapDC
+
+GDI USAGE ERROR
+name=http://crbug.com/109963 c
+system call NtGdiDeleteObjectApp
+GDI32.dll!DeleteDC
+content.dll!*
+
+GDI USAGE ERROR
+name=http://crbug.com/109963 d
+system call NtGdiDeleteObjectApp
+GDI32.dll!DeleteDC
+*!base::internal::RunnableAdapter*
+
+# GDI usage errors in 3rd-party components
+GDI USAGE ERROR
+name=http://crbug.com/119552 a
+system call NtGdiDeleteObjectApp
+...
+*!OmniboxViewWin::*
+
+GDI USAGE ERROR
+name=http://crbug.com/119552 b
+system call Nt*
+...
+*!ATL::*
+
+GDI USAGE ERROR
+name=http://crbug.com/119552 c
+# optional gdi32.dll frame followed by user32.dll
+# TODO(bruening): once have
+# http://code.google.com/p/drmemory/issues/detail?id=846
+# I would do "gdi32.dll!...\nuser32.dll!*"
+*32.dll!*
+...
+shell32.dll!SHGetFileInfoW
+*!IconLoader::ReadIcon
+
+GDI USAGE ERROR
+name=http://crbug.com/119552 d
+system call NtGdiDeleteObjectApp
+gdi32.dll!DeleteObject
+riched20.dll!*
+riched20.dll!*
+riched20.dll!*
+
+GDI USAGE ERROR
+name=http://crbug.com/120157
+# "ReleaseDC called from different thread than GetDC"
+system call NtUserCallOneParam.RELEASEDC
+*!*FontCache::CacheElement::~CacheElement
+
+GDI USAGE ERROR
+name=http://crbug.com/158090
+# "DC created by one thread and used by another"
+...
+content.dll!content::*::FontCache::PreCacheFont
+content.dll!content::FontCacheDispatcher::OnPreCacheFont
+content.dll!DispatchToMethod<content::FontCacheDispatcher*
+
+GDI USAGE ERROR
+name=http://crbug.com/158090 c#4
+# ReleaseDC for DC called from different thread than the thread that called GetDC
+system call NtUserCallOneParam.RELEASEDC
+ui.dll!gfx::ReadColorProfile
+ui.dll!gfx::GetColorProfile
+content.dll!content::RenderMessageFilter::OnGetMonitorColorProfile
+content.dll!DispatchToMethod*
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/158350
+# allocated with operator new[], freed with operator delete
+*!*
+*!*
+*!*
+*!*
+*!*
+content.dll!*
+content.dll!*
+content.dll!*
+content.dll!*
+content.dll!*
+*!*
+*!*
+*!*
+*!*
+*!*
+KERNEL32.dll!*
+ntdll.dll!*
+ntdll.dll!*
+
+WARNING
+name=Security test (new oveflow)
+MSVCR100D.dll!operator new
+*!operator new
+*!operator new[]
+*!`anonymous namespace'::SecurityTest_NewOverflow_Test::TestBody
+*!testing::internal::HandleExceptionsInMethodIfSupported<testing::Test,void>
+
+WARNING
+name=Security test (calloc overflow)
+*!`anonymous namespace'::CallocReturnsNull
+*!`anonymous namespace'::SecurityTest_CallocOverflow_Test::TestBody
+*!testing::internal::HandleExceptionsInMethodIfSupported<testing::Test,void>
+
+GDI USAGE ERROR
+name=http://crbug.com/234484
+# "DC created by one thread and used by another"
+...
+*!chrome::`anonymous namespace'::SetOverlayIcon
+
+INVALID HEAP ARGUMENT
+name=http://crbug.com/262088
+drmemorylib.dll!av_dup_packet
+msvcrt.dll!wcsrchr
+ntdll.dll!RtlIsCurrentThreadAttachExempt
+ntdll.dll!LdrShutdownThread
+ntdll.dll!RtlExitUserThread
+
+GDI USAGE ERROR
+name=http://crbug.com/266484
+skia.dll!HDCOffscreen::draw
+skia.dll!SkScalerContext_GDI::generateImage
+skia.dll!SkScalerContext::getImage
+skia.dll!SkGlyphCache::findImage
+skia.dll!D1G_NoBounder_RectClip
+skia.dll!SkDraw::drawText
+skia.dll!SkDevice::drawText
+skia.dll!SkCanvas::drawText
+media.dll!media::FakeVideoCaptureDevice::OnCaptureTask
diff --git a/chromium/tools/valgrind/drmemory/suppressions_full.txt b/chromium/tools/valgrind/drmemory/suppressions_full.txt
new file mode 100644
index 00000000000..d322d86b7ec
--- /dev/null
+++ b/chromium/tools/valgrind/drmemory/suppressions_full.txt
@@ -0,0 +1,1323 @@
+# This file contains suppressions for the Dr.Memory tool, see
+# http://dev.chromium.org/developers/how-tos/using-drmemory
+#
+# This file should contain suppressions only for the reports happening
+# in the 'full' mode (drmemory_full).
+# For the reports that can happen in the light mode (a.k.a. drmemory_light),
+# please use suppressions.txt instead.
+
+###############################################################
+# Known reports on the third party we have no control over.
+UNINITIALIZED READ
+name=deflate UNINIT
+...
+*!deflate_*
+*!MOZ_Z_deflate
+
+# TODO(timurrrr): check if these frames change when NT_SYMBOLS are present.
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=406
+ADVAPI32.dll!WmiOpenBlock
+ADVAPI32.dll!WmiOpenBlock
+
+# Leaks inside GoogleDesktop - it injects into our processes for some reason
+LEAK
+name=GoogleDesktop LEAK
+...
+GoogleDesktopNetwork3.DLL!DllUnregisterServer
+
+# They deliberately use uninit local var in sqlite random generator
+UNINITIALIZED READ
+name=sqlite3_randomness UNINIT
+*!randomByte
+*!sqlite3_randomness
+
+# Intentional leak in WebKit Template Framework for ThreadData.
+LEAK
+name=intentional WTF ThreadData leak
+...
+*!WTF::wtfThreadData
+
+# Happens when winhttp returns ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT.
+LEAK
+name=http://crbug.com/125558 a
+KERNELBASE.dll!LocalAlloc
+SECHOST.dll!...
+SECHOST.dll!NotifyServiceStatusChange
+WINHTTP.dll!...
+WINHTTP.dll!WinHttpDetectAutoProxyConfigUrl
+*!net::ProxyResolverWinHttp::GetProxyForURL
+
+# Tiny locale-related leaks in ntdll. Probably system bug.
+LEAK
+name=http://crbug.com/125558 b
+ntdll.dll!...
+ntdll.dll!*
+KERNELBASE.dll!...
+KERNELBASE.dll!GetCPInfoExW
+webio.dll!*
+webio.dll!*
+webio.dll!*
+WINHTTP.dll!...
+WINHTTP.dll!WinHttpGetIEProxyConfigForCurrentUser
+*!net::ProxyConfigServiceWin::GetCurrentProxyConfig
+
+###############################################################
+# Suppress some false reports due to bugs in Dr.Memory like wrong analysis
+# assumptions or unhandled syscalls
+
+# Please note: the following suppressions were written in the abscense of
+# private symbols so may need to be updated when we switch to auto-loading PDBs
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (1)
+ntdll.dll!Rtl*
+ntdll.dll!Rtl*
+ntdll.dll!RtlFindActivationContextSectionString
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (2)
+...
+SHELL32.dll!SHFileOperation*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (3)
+...
+SHELL32.dll!SHGetFolderPath*
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (4)
+...
+SHELL32.dll!SHGetFolderPath*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (5)
+...
+SHELL32.dll!SHCreateDirectory*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (6)
+...
+SHELL32.dll!ILLoadFromStream*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (7)
+...
+SHELL32.dll!ILSaveToStream*
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (8)
+...
+SHELL32.dll!SHFileOperation*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (9)
+...
+SHELL32.dll!SHGetItemFromDataObject
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (10)
+...
+SHELL32.dll!SHGetItemFromDataObject
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=12 (11)
+...
+ole32.dll!*
+SHELL32.dll!SHChangeNotifySuspendResume
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=14 (1)
+...
+*!CreateProcess*
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=14 (2)
+...
+*!CreateProcess*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=14 (3)
+...
+*!base::LaunchApp*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=17 (1)
+...
+*!CreateWindow*
+
+POSSIBLE LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=17 (2)
+GDI32.dll!*
+GDI32.dll!CreateFontIndirectExW
+GDI32.dll!CreateFontIndirectW
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=17 (3)
+KERNELBASE.dll!LocalAlloc
+...
+USER32.dll!CreateWindow*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=18 a
+...
+*!CoInitialize*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=18 b
+...
+*!CoCreateInstance*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=18 c
+...
+*!CoUninitialize*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=18 d
+...
+UxTheme.dll!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=40 a
+...
+WINSPOOL.DRV!*
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=40 b
+...
+WINSPOOL.DRV!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=48 a
+system call NtContinue
+...
+*!*SetThreadName
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=48 b
+system call NtContinue
+*!WTF::initializeCurrentThreadInternal
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=52 a
+...
+DBGHELP.dll!SymInitialize
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=52 b
+...
+DBGHELP.dll!SymEnumSourceFiles
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=52 c
+...
+msvcrt.dll!_RTDynamicCast
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=52 bit-level fp in dbghelp
+instruction=test 0x*(%*) $0x??
+DBGHELP.dll!SymUnloadModule64
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=53
+ADVAPI32.dll!WmiMofEnumerateResourcesA
+ADVAPI32.dll!WmiMofEnumerateResourcesA
+ADVAPI32.dll!Sta*TraceW
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=58
+...
+*!_cfltcvt_l
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=60
+USP10.dll!*
+...
+USP10.dll!ScriptStringAnalyse
+
+LEAK
+IMM32.dll!ImmGetIMCCSize
+IMM32.dll!ImmLockClientImc
+IMM32.dll!ImmDisableIME
+IMM32.dll!ImmSetActiveContext
+USER32.dll!IMPSetIMEA
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=65 a
+...
+*!SystemFunction036
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=65 b
+...
+*!talk_base::CreateRandomString
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=68 a
+...
+WS2_32.dll!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=68 b
+...
+ADVAPI32.dll!SetSecurityDescriptorDacl
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=68 c
+...
+MSWSOCK.dll!WSPStartup
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=68 d
+...
+ntdll.dll!RtlValidateUnicodeString
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=256
+*!_mtinit
+*!__tmainCRTStartup
+*!mainCRTStartup
+
+POSSIBLE LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=274 a
+...
+GDI32.dll!CreateDCW
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=274 b
+...
+GDI32.dll!CreateDCW
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=275
+...
+*!_getptd*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=276
+...
+ntdll.dll!RtlConvertUlongToLargeInteger
+ntdll.dll!RtlConvertUlongToLargeInteger
+ntdll.dll!KiUserExceptionDispatcher
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=305
+*!free
+*!free
+*!operator new
+...
+*!MiniDumpWriteDump
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=346 a
+...
+GDI32.dll!CloseEnhMetaFile
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=346 b
+GDI32.dll!SetPolyFillMode
+GDI32.dll!CreateICW
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=362
+USER32.dll!UnregisterClass*
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=382
+...
+ntdll.dll!CsrNewThread
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=397
+system call NtDeviceIoControlFile InputBuffer
+ADVAPI32.dll!ImpersonateAnonymousToken
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=407 a
+system call NtRequestWaitReplyPort
+RPCRT4.dll!I_RpcSendReceive
+RPCRT4.dll!NdrSendReceive
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=407 b
+IMM32.dll!*
+ntdll.dll!LdrInitializeThunk
+ntdll.dll!LdrShutdownThread
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=412 a
+ADVAPI32.dll!RegDeleteValue*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=412 b
+...
+ADVAPI32.dll!Crypt*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=412 c
+...
+RPCRT4.dll!NdrClientCall2
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=412 d
+RSAENH.dll!DllUnregisterServer
+...
+ADVAPI32.dll!CryptAcquireContextA
+CRYPT32.dll!CryptEnumOIDFunction
+...
+CRYPT32.dll!CertFindCertificateInStore
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=412 e
+...
+RSAENH.dll!CPGenRandom
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=412 f
+...
+CRYPT??.dll!Crypt*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=412 g
+*!replace_memcmp
+...
+*!testing::internal::CmpHelperEQ*
+...
+*!SymmetricKeyTest_ImportGeneratedKey_Test::TestBody
+
+# We get these sometimes from AesEncrypt and AesExpandKey. AesEncrypt doesn't
+# have frame pointers, and we have trouble unwinding from it. Therefore, we use
+# this broad suppression, effectively disabling uninit checks in rsaenh.dll.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=412 h
+RSAENH.dll!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=425 a
+CLBCatQ.DLL!DestroyStgDatabase
+CLBCatQ.DLL!PostError
+CLBCatQ.DLL!PostError
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=425 b
+RPCRT4.dll!I_RpcBCacheFree
+RPCRT4.dll!I_RpcBCacheFree
+...
+RPCRT4.dll!NdrClientCall2
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=425 c
+msdmo.dll!*
+msdmo.dll!*
+DEVENUM.DLL!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=435 a
+...
+ntdll.dll!RtlSetSecurityObject
+ntdll.dll!RtlNewSecurityObjectEx
+ADVAPI32.dll!CreatePrivateObjectSecurityEx
+NTMARTA.dll!AccRewriteSetNamedRights
+
+POSSIBLE LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=435 b
+WLDAP32.dll!Ordinal325
+...
+WLDAP32.dll!Ordinal325
+ntdll.dll!LdrInitializeThunk
+ntdll.dll!LdrFindResourceDirectory_U
+ntdll.dll!RtlValidateUnicodeString
+ntdll.dll!LdrLoadDll
+KERNEL32.dll!LoadLibraryExW
+
+# mod+offs suppression because the symbolic makes no sense and changes
+# completely in the presence of WS2_32.dll symbols.
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=438
+<WS2_32.dll+0x260c>
+<WS2_32.dll+0x2b76>
+<WS2_32.dll+0x2c61>
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=454 a
+...
+WINMM.dll!wave*GetNumDevs
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=454 b
+...
+WINMM.dll!wave*GetNumDevs
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=466
+ntdll.dll!RtlRunOnceBeginInitialize
+ntdll.dll!RtlInitializeCriticalSectionAndSpinCount
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=471 a
+*!media::AudioRendererAlgorithmOLA::Crossfade<unsigned char>
+*!media::AudioRendererAlgorithmOLA::FillBuffer
+*!media::AudioRendererAlgorithmOLATest_FillBuffer_*
+
+# Uninit reported in copy ctor. Would be nice if we could specify which ctor
+# overload to suppress.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=471 b
+*!WebCore::FormDataElement::FormDataElement
+
+# Another default copy ctor uninit.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=471 c
+*!WebCore::CachedResourceLoader::InitiatorInfo::InitiatorInfo
+...
+*!WTF::Hash*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=473 a
+system call NtDeviceIoControlFile InputBuffer
+...
+iphlpapi.dll!GetAdaptersAddresses
+
+POSSIBLE LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=473 b
+ESENT.dll!*
+ESENT.dll!*
+ESENT.dll!*
+ntdll.dll!Ldr*Init*
+ntdll.dll!Ldr*
+ntdll.dll!*
+ntdll.dll!LdrLoadDll
+...
+iphlpapi.dll!GetPerAdapterInfo
+...
+iphlpapi.dll!GetAdaptersAddresses
+
+POSSIBLE LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=473 c
+RPCRT4.dll!*
+RPCRT4.dll!*
+...
+IPHLPAPI.DLL!GetAdaptersAddresses
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=475
+...
+ADVAPI32.dll!CryptAcquireContextA
+...
+CRYPT32.dll!CryptMsgOpenToDecode
+...
+CRYPT32.dll!CryptQueryObject
+
+# Lots of leaks from our interactions with the system certificate store. May be
+# worth reviewing our use of their API.
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 a
+KERNEL*.dll!LocalAlloc
+...
+CRYPT32.dll!CertGetCRLContextProperty
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 b
+KERNEL*.dll!LocalAlloc
+...
+CRYPT32.dll!CertAddCRLContextToStore
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 c
+KERNEL*.dll!LocalAlloc
+...
+CRYPT32.dll!CertOpenStore
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 d
+...
+CRYPT32.dll!CertOpenSystemStore?
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 e
+...
+CRYPT32.dll!CertGetCertificateChain
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 f
+...
+CRYPT32.dll!CertCompareIntegerBlob
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 g
+...
+CRYPT32.dll!CryptUnprotectData
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 h
+KERNEL*.dll!LocalAlloc
+...
+CRYPT32.dll!CertEnumCertificatesInStore
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 i
+...
+CRYPT32.dll!CryptProtectData
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=476 j
+...
+CRYPT32.dll!CryptExportPublicKeyInfoEx
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=502 a
+system call NtSecureConnectPort parameter #3
+GDI32.dll!*
+GDI32.dll!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=502 b
+system call NtGdiEnumFonts parameter #6
+GDI32.dll!*
+GDI32.dll!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=511 a
+RPCRT4.dll!...
+ole32.dll!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=511 b
+ole32.dll!*
+ole32.dll!*
+ole32.dll!StringFromGUID2
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=512 a
+...
+*!browser_sync::Cryptographer::PackBootstrapToken
+*!browser_sync::Cryptographer::GetBootstrapToken
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=512 b
+...
+*!Encrypt*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=513 a
+*!v8*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=513 b
+*!*
+*!v8*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=513 c
+<not in a module>
+...
+*!v8*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=546
+...
+mscms.dll!*
+...
+GDI32.dll!*
+*!IconUtil::Create*HICON*
+
+LEAK
+name=http://crbug.com/92152
+...
+USER32.dll!CreateWindowExW
+*!views::TooltipManagerWin::Init
+*!views::TooltipManagerWin::TooltipManagerWin
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=567 a
+dbghelp.dll!*
+...
+dbghelp.dll!StackWalk64
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=567 b
+*!*
+dbghelp.dll!*
+...
+dbghelp.dll!StackWalk64
+
+# Symbols w/o PDB make no sense, first ntdll frame is TpSetTimer w/o syms and
+# TppWorkerThread w/ syms. We used to use mod+offs here, but that was too
+# brittle, so we switched to RPCRT4.dll!*.
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=569
+RPCRT4.dll!...
+ntdll.dll!*
+ntdll.dll!*
+KERNEL*.dll!BaseThreadInitThunk
+
+# TODO(timurrrr): investigate these
+UNINITIALIZED READ
+name=http://crbug.com/TODO a
+...
+*!win_util::GetLogonSessionOnlyDACL
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO b
+...
+ntshrui.dll!IsPathSharedW
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO c
+...
+*!NetApiBufferFree
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO d
+...
+*!ShellExecute*
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO e
+...
+*!SHParseDisplayName
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO f
+...
+*!GetCanonicalPathInfo*
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO g
+...
+SHELL32.dll!Ordinal*
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO h
+...
+GDI32.dll!GetTextExtentPoint32*
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO i
+...
+*!SyncSocketClientListener::OnMsgClassResponse
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO j
+...
+*!*NSPRInitSingleton*
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO k
+*!NdrSimpleStructFree
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO l
+ntdll.dll!RtlpNtOpenKey
+ntdll.dll!RtlMakeSelfRelativeSD
+ntdll.dll!RtlAbsoluteToSelfRelativeSD
+ADVAPI32.dll!MakeSelfRelativeSD
+
+UNINITIALIZED READ
+name=http://crbug.com/TODO m
+...
+CRYPT32.dll!I_CertSyncStore
+
+# This matches the same stack as DrMem i#751, but it's an uninit read instead of
+# a leak. Must be some early thread initialization. Doesn't look like
+# bit-level though.
+UNINITIALIZED READ
+name=http://crbug.com/TODO n
+RPCRT4.dll!*
+RPCRT4.dll!*
+RPCRT4.dll!*
+ntdll.dll!*
+ntdll.dll!*
+KERNEL*.dll!BaseThreadInitThunk
+
+# No idea where this is from, but Chrome isn't even on the stack.
+POSSIBLE LEAK
+name=http://crbug.com/TODO o
+RPCRT4.dll!...
+ole32.dll!OleInitialize
+ole32.dll!...
+KERNEL32.dll!BaseThreadInitThunk
+
+# Matches lots of RPC related leaks. So far RPC handles have been mostly owned
+# by system libraries and are not something we can fix easily.
+POSSIBLE LEAK
+name=http://crbug.com/TODO p
+RPCRT4.dll!*
+RPCRT4.dll!*
+RPCRT4.dll!NDRCContextBinding
+
+# No idea, but all system code, not interesting.
+POSSIBLE LEAK
+name=http://crbug.com/TODO q
+RPCRT4.dll!...
+RPCRT4.dll!*
+RPCRT4.dll!*
+ole32.dll!...
+ole32.dll!*
+ole32.dll!*
+...
+SHELL32.dll!*
+
+LEAK
+name=http://crbug.com/109278 video device COM leaks
+...
+*!media::VideoCaptureDevice::*
+
+LEAK
+name=http://crbug.com/109278 audio device COM leaks
+...
+*!media::GetInputDeviceNamesWin
+
+# False pos uninit in shell32 when resolving links.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=745
+SHELL*.dll!*
+...
+SHELL*.dll!*
+*!file_util::ResolveShortcut
+
+# Probable false pos uninit in ffmpeg. Probably due to running off the end of a
+# buffer with SSE/MMX instructions whose results are then masked out later.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=747 a
+*!ff_pred4x4_vertical_vp8_mmxext
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=747 b
+*!ff_pred4x4_down_left_mmxext
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=747 c
+*!ff_vorbis_floor1_render_list
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=747 d
+*!ff_put_vp8_epel8_h6_ssse3
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=747 e
+*!ff_put_vp8_epel8_h4_ssse3
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=747 f
+*!ff_fft_permute_sse
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=747 g
+*!ff_simple_idct_add_mmx
+
+# ffmpeg seems to leak a pthread condition variable.
+LEAK
+name=http://crbug.com/110042
+*!ptw32_new
+*!pthread_self
+*!sem_wait
+*!pthread_cond_wait
+*!ff_thread_decode_frame
+*!avcodec_decode_video2
+
+# Improperly handled ioctl in bcrypt.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=748
+system call NtDeviceIoControlFile InputBuffer
+bcrypt.dll!BCryptUnregisterConfigChangeNotify
+bcrypt.dll!BCryptGetFipsAlgorithmMode
+ntdll.dll!RtlQueryEnvironmentVariable
+
+# Not sure what this is.
+POSSIBLE LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=749
+...
+fwpuclnt.dll!*
+...
+RPCRT4.dll!*
+...
+fwpuclnt.dll!*
+...
+WS2_32.dll!*
+*!talk_base::SafeGetHostByName
+*!talk_base::SocketAddress::GetLocalIPs
+*!talk_base::SocketAddress::IsLocalIP
+*!cricket::Transport::VerifyCandidate
+*!cricket::Session::OnRemoteCandidates
+*!cricket::Session::OnTransportInfoMessage
+*!cricket::Session::OnIncomingMessage
+*!cricket::SessionManager::OnIncomingMessage
+
+# More uninit false pos in rpcrt4.dll not caught by default suppressions.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=529
+RPCRT4.dll!*
+...
+*!base::LaunchProcess
+
+# System leak from CreateEnvironmentBlock.
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=757
+...
+USERENV.dll!CreateEnvironmentBlock
+
+# Looks like another instance of 753
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=753
+...
+ntdll.dll!RtlLoadString
+
+# More bit manip fps
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=493
+USP10.dll!ScriptPositionSingleGlyph
+
+# Various TLS leaks that we don't understand yet. We should be finding a root
+# for these.
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=778 a
+KERNELBASE.dll!TlsSetValue
+
+# Originally filed as: http://crbug.com/109281
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=778 b
+*!operator new
+*!operator new[]
+*!*::ConstructTlsVector
+*!base::ThreadLocalStorage::StaticSlot::Get
+
+# This is an NSS PRThread object installed in TLS. Why isn't this detected as a
+# root? See also http://crbug.com/32624
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=778 c
+*!PR_Calloc
+*!_PR_AttachThread
+*!_PRI_AttachThread
+
+# Bit-level fps in rich edit layer.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=791
+RICHED20.dll!*
+RICHED20.dll!*
+
+# Already suppressed by drmemory default supp we don't have yet.
+LEAK
+name=i#757: RPC binding leaks in sspicli.dll
+RPCRT4.dll!*
+...
+SspiCli.dll!*
+SspiCli.dll!Cre*
+
+# Async NtReadFile false positives. This was fixed in drmemory r772, remove
+# this supp when we pull that rev.
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=798
+system call NtReadFile parameter #5
+KERNEL32.dll!ReadFile
+
+# Probable syscall false positive.
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=809
+system call NtGdiPolyPolyDraw parameter #1
+*!gfx::Path::CreateNativeRegion
+
+# Very wide suppression for all uninits in rpcrt4.dll. We get bad stack traces
+# coming out of this module (sometimes only one frame), which makes it hard to
+# write precise suppressions. Until we have bit-level tracking (DRMi#113) we
+# should keep this.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=113 rpcrt4.dll wildcard
+RPCRT4.dll!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=841 a
+...
+CRYPTNET.dll!I_CryptNetGetConnectivity
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=841 b
+...
+webio.dll!*
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=841 c
+...
+winhttp.dll!*
+
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=841 d
+...
+CRYPTNET.dll!I_CryptNetGetConnectivity
+
+# Often missing a ntdll.dll!KiUserCallbackDispatcher frame.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=810
+instruction=test %edx %edx
+USER32.dll!GetClassLongW
+...
+*!ui::CenterAndSizeWindow
+
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=815
+KERNEL*.dll!...
+dxgi.dll!*
+USER32.dll!GetMonitorInfoA
+ntdll.dll!KiUserCallbackDispatcher
+dxgi.dll!*
+WinSATAPI.DLL!*
+
+# Suppress anything in cmd.exe. It's safer to suppress these than disable
+# following, since someone might launch a Chrome process via cmd.exe.
+LEAK
+name=cmd.exe
+...
+cmd.exe!*
+
+# Possible true system use after free.
+UNADDRESSABLE ACCESS
+name=http://code.google.com/p/drmemory/issues/detail?id=623
+KERNELBASE.dll!TlsGetValue
+OLEAUT32.dll!SysFreeString
+OLEAUT32.dll!SysAllocStringByteLen
+OLEACC.dll!*
+OLEACC.dll!*
+OLEACC.dll!*
+OLEACC.dll!*
+
+# basic_streambuf seems to leak something in creating a std::_Mutex
+LEAK
+name=http://code.google.com/p/drmemory/issues/detail?id=857
+ntdll.dll!...
+ntdll.dll!RtlInitializeCriticalSection
+*!_Mtxinit
+*!std::_Mutex::_Mutex
+*!std::basic_streambuf<*>
+
+# stdext::hash_map<> seems to swap uninitialized floats.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=931
+*!std::swap<float>
+*!std::_Hash<*
+
+# syscall false positive on handling NtQuerySystemInformation, fix in soon.
+UNINITIALIZED READ
+name=http://code.google.com/p/drmemory/issues/detail?id=932
+KERNEL32.dll!K32GetPerformanceInfo
+
+# Seems to create a DC, sometimes. GetTextMetrics returns no pointers, though.
+LEAK
+name=GDI SetBrushOrgEx leak
+GDI32.dll!...
+GDI32.dll!GetTextMetricsW
+*!gfx::PlatformFontWin::CreateHFontRef
+*!gfx::PlatformFontWin::GetBaseFontRef
+
+###############################################################
+# Benign issues in Chromium
+
+# This test intentionally leaks an object and checks that it's never deleted.
+LEAK
+name=BrowserThreadTest.NotReleasedIfTargetThreadNonExistant leak
+...
+*!BrowserThreadTest_NotReleasedIfTargetThreadNonExistent_Test::TestBody
+
+LEAK
+name=deliberate histogram leak
+...
+*!replace_operator_new
+...
+*!*::*Histogram::FactoryGet
+
+LEAK
+name=deliberate LazyInstance leak
+...
+*!*LeakyLazyInstance*
+...
+*!base::LazyInstance*::Pointer
+
+LEAK
+name=http://crbug.com/79933 (1)
+...
+*!TestURLRequestContext::Init
+
+LEAK
+name=http://crbug.com/79933 (2)
+...
+*!TestURLRequestContext::TestURLRequestContext
+*!TestURLRequestContextGetter::GetURLRequestContext
+*!notifier::SingleLoginAttempt::SingleLoginAttempt
+*!notifier::Login::StartConnection
+*!syncer::InvalidationNotifier::UpdateCredentials
+*!syncer::NonBlockingInvalidationNotifier::Core::UpdateCredentials
+
+LEAK
+name=http://crbug.com/79933 (3)
+...
+*!TestURLRequestContext::TestURLRequestContext
+*!TestURLRequestContextGetter::GetURLRequestContext
+*!URLFetcher::Core::StartURLRequest
+
+LEAK
+name=http://crbug.com/79933 (4)
+*!generic_cpp_alloc
+*!operator new
+*!std::_Allocate<net::SSLConfigService::Observer *>
+*!std::allocator<net::SSLConfigService::Observer *>::allocate
+*!std::vector<net::SSLConfigService::Observer *,std::allocator<net::SSLConfigService::Observer *> >::_Insert_n
+*!std::vector<net::SSLConfigService::Observer *,std::allocator<net::SSLConfigService::Observer *> >::insert
+*!std::vector<net::SSLConfigService::Observer *,std::allocator<net::SSLConfigService::Observer *> >::push_back
+*!ObserverListBase<net::SSLConfigService::Observer>::AddObserver
+...
+*!net::HttpNetworkSession::HttpNetworkSession
+*!notifier::ProxyResolvingClientSocket::ProxyResolvingClientSocket
+*!notifier::XmppClientSocketFactory::CreateTransportClientSocket
+*!notifier::ChromeAsyncSocket::Connect
+*!buzz::XmppClient::ProcessStartXmppLogin
+*!buzz::XmppClient::Process
+*!talk_base::Task::Step
+*!talk_base::TaskRunner::InternalRunTasks
+*!talk_base::TaskRunner::RunTasks
+*!notifier::TaskPump::CheckAndRunTasks
+*!base::internal::RunnableAdapter<void (__thiscall notifier::TaskPump::*)(void)>::Run
+
+# Test intentionally leaks an object.
+LEAK
+name=http://crbug.com/86301
+*!replace_operator_new
+...
+*!*_DeadReplyLoopDoesNotDelete_Test::TestBody
+
+# Leak in a binary copy of Firefox 3's NSS dll. Not much we can do about it.
+LEAK
+name=Firefox 3 NSS dll leak
+nspr4.dll!*
+...
+*!NSSDecryptor::~NSSDecryptor
+
+# We get uninit reports inside GMock when it prints the bytes of references to
+# partially initialized objects passed to unexpected method calls.
+UNINITIALIZED READ
+name=GMock printing uninit data
+...
+*!testing::internal2::PrintBytesInObjectTo
+
+###############################################################
+# Real issues in Chromium
+
+LEAK
+name=http://crbug.com/32085
+...
+chrome.dll!NotificationRegistrar::Add
+
+LEAK
+name=http://crbug.com/32623
+...
+*!ssl3_HandleHandshakeMessage
+*!ssl3_HandleHandshake
+*!ssl3_HandleRecord
+*!ssl3_GatherCompleteHandshake
+...
+*!SSL_ForceHandshake
+*!net::SSLServerSocketNSS::DoHandshake
+*!net::SSLServerSocketNSS::DoHandshakeLoop
+
+UNINITIALIZED READ
+name=http://crbug.com/57266 (1)
+...
+*!remoting::EncoderVp8::Encode
+
+UNINITIALIZED READ
+name=http://crbug.com/57266 (2)
+...
+*!vp8_*
+
+LEAK
+name=http://crbug.com/70062
+*!PR_Calloc
+*!PR_NewLock
+...
+*!InitSessionCacheLocks
+*!initSessionCacheLocksLazily
+*!PR_CallOnce
+*!ssl_InitSessionCacheLocks
+*!lock_cache
+*!ssl_LookupSID
+*!ssl2_BeginClientHandshake
+*!ssl_Do1stHandshake
+*!SSL_ForceHandshake
+*!net::SSL*SocketNSS::DoHandshake
+*!net::SSL*SocketNSS::DoHandshakeLoop
+
+LEAK
+name=http://crbug.com/74417 a
+*!replace_operator_new
+*!disk_cache::BackendImpl::CreateEntryImpl
+
+LEAK
+name=http://crbug.com/74417 b
+*!replace_operator_new
+*!disk_cache::BackendImpl::NewEntry
+
+# One more disk_cache::BackendImpl leak. See also http://crbug.com/87500.
+LEAK
+name=http://crbug.com/74417 c
+*!replace_operator_new
+...
+*!disk_cache::EntryImpl::UserBuffer::UserBuffer
+
+LEAK
+name=http://crbug.com/75247
+...
+*!replace_operator_new
+*!AutofillDownloadTestHelper::AutofillDownloadTestHelper
+
+LEAK
+name=http://crbug.com/78784
+*!generic_cpp_alloc
+*!operator new
+*!TestingProfile::CreateRequestContext
+*!*ProfileSyncService*::SetUp
+
+LEAK
+name=http://crbug.com/80550 (1)
+...
+*!RenderWidgetHost::WasHidden
+
+LEAK
+name=http://crbug.com/80550 (2)
+...
+*!RenderWidgetHost::WasRestored
+
+LEAK
+name=http://crbug.com/87612
+...
+*!SSL_ConfigSecureServer
+*!net::SSLServerSocketNSS::InitializeSSLOptions
+*!net::SSLServerSocketNSS::Handshake
+
+LEAK
+name=http://crbug.com/88640
+*!generic_cpp_alloc
+*!operator new
+*!ProfileImpl::InitRegisteredProtocolHandlers
+*!ProfileImpl::DoFinalInit
+*!ProfileImpl::OnPrefsLoaded
+
+LEAK
+name=http://crbug.com/91465
+*!generic_cpp_alloc
+*!operator new
+*!browser_sync::internal::WeakHandleCore<browser_sync::JsBackend>::*
+*!browser_sync::WeakHandle<browser_sync::JsBackend>::*
+*!syncer::SyncManager::SyncInternal::Init
+
+LEAK
+name=http://crbug.com/91491
+...
+*!CrxUpdateService::ProcessPendingItems
+
+UNINITIALIZED READ
+name=http://crbug.com/92026 (1)
+softokn3.dll!FC_GetFunctionList
+...
+softokn3.dll!NSC_ModuleDBFunc
+
+UNINITIALIZED READ
+name=http://crbug.com/92026 (2)
+freebl3.dll!FREEBL_GetVector
+...
+softokn3.dll!NSC_ModuleDBFunc
+
+LEAK
+name=http://crbug.com/92166
+...
+*!replace_operator_new
+*!views::NativeWidgetWin::OnCreate
+
+# Possible real Chromium issue in DoCrossfade.
+UNINITIALIZED READ
+name=http://crbug.com/110049
+*!media::DoCrossfade<*>
+*!media::Crossfade
+*!media::AudioRendererAlgorithmBase::FillBuffer
+
+# Known sqlite3 leaks.
+LEAK
+name=http://crbug.com/113847 (1)
+...
+*!sqlite3MemMalloc
+*!mallocWithAlarm
+*!sqlite3Malloc
+...
+*!yy_reduce
+
+LEAK
+name=http://crbug.com/113847 (2)
+...
+*!openDatabase
+*!sqlite3_open
+
+LEAK
+name=http://crbug.com/115328
+...
+*!GenericInfoViewTest_GenericInfoView_Test::TestBody
+
+UNINITIALIZED READ
+name=http://crbug.com/116277
+*!MOZ_Z_deflate
+*!zipCloseFileInZipRaw64
+
+LEAK
+name=http://crbug.com/117427 a
+...
+*!net::HostCache::Set
+*!net::HostResolverImpl::CacheResult
+*!net::HostResolverImpl::Job::CompleteRequests
+*!net::HostResolverImpl::Job::OnProcTaskComplete
+*!base::internal::RunnableAdapter<void (__thiscall net::HostResolverImpl::Job::*)(int,net::AddressList const &)>::Run
+
+# Probably related to 117427. Someone is not tearing down DNS resolution during
+# testing.
+LEAK
+name=http://crbug.com/117427 b
+*!generic_cpp_alloc
+*!operator new
+*!base::internal::WeakReferenceOwner::GetRef
+*!base::SupportsWeakPtr<net::HostResolverImpl>::AsWeakPtr
+*!net::HostResolverImpl::Job::Job
+*!net::HostResolverImpl::Resolve
+*!net::SingleRequestHostResolver::Resolve
+*!net::TransportConnectJob::DoResolveHost
+*!net::TransportConnectJob::DoLoop
+*!net::TransportConnectJob::ConnectInternal
+*!net::ConnectJob::Connect
+*!net::internal::ClientSocketPoolBaseHelper::RequestSocketInternal
+*!net::internal::ClientSocketPoolBaseHelper::RequestSocket
+*!net::ClientSocketPoolBase<net::TransportSocketParams>::RequestSocket
+*!net::TransportClientSocketPool::RequestSocket
+*!net::ClientSocketHandle::Init<net::TransportSocketParams,net::TransportClientSocketPool>
+*!net::`anonymous namespace'::InitSocketPoolHelper
+*!net::InitSocketHandleForRawConnect
+*!notifier::ProxyResolvingClientSocket::ProcessProxyResolveDone
+*!base::internal::RunnableAdapter<void (__thiscall notifier::ProxyResolvingClientSocket::*)(int)>::Run
+
+# IE frame possible leak of COM object.
+LEAK
+name=http://crbug.com/122399
+ole32.dll!...
+ole32.dll!CoTaskMemAlloc
+urlmon.dll!...
+urlmon.dll!CreateUri
+IEFRAME.dll!*
+
+# RenderWidgetHelper leak in DelayProfileDestruction test.
+LEAK
+name=http://crbug.com/125565
+*!generic_cpp_alloc
+*!operator new
+*!RenderProcessHostImpl::RenderProcessHostImpl
+*!SiteInstanceImpl::GetProcess
+*!BrowserTestOffTheRecord_DelayProfileDestruction_Test::TestBody
+
+LEAK
+name=http://crbug.com/125807
+*!generic_cpp_alloc
+*!operator new
+*!TransportSecurityPersister::TransportSecurityPersister
+*!TransportSecurityPersisterTest::TransportSecurityPersisterTest
diff --git a/chromium/tools/valgrind/drmemory_analyze.py b/chromium/tools/valgrind/drmemory_analyze.py
new file mode 100755
index 00000000000..97d4635eebf
--- /dev/null
+++ b/chromium/tools/valgrind/drmemory_analyze.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# drmemory_analyze.py
+
+''' Given a Dr. Memory output file, parses errors and uniques them.'''
+
+from collections import defaultdict
+import common
+import hashlib
+import logging
+import optparse
+import os
+import re
+import subprocess
+import sys
+import time
+
+class DrMemoryError:
+ def __init__(self, report, suppression, testcase):
+ self._report = report
+ self._testcase = testcase
+
+ # Chromium-specific transformations of the suppressions:
+ # Replace 'any_test.exe' and 'chrome.dll' with '*', then remove the
+ # Dr.Memory-generated error ids from the name= lines as they don't
+ # make sense in a multiprocess report.
+ supp_lines = suppression.split("\n")
+ for l in xrange(len(supp_lines)):
+ if supp_lines[l].startswith("name="):
+ supp_lines[l] = "name=<insert_a_suppression_name_here>"
+ if supp_lines[l].startswith("chrome.dll!"):
+ supp_lines[l] = supp_lines[l].replace("chrome.dll!", "*!")
+ bang_index = supp_lines[l].find("!")
+ d_exe_index = supp_lines[l].find(".exe!")
+ if bang_index >= 4 and d_exe_index + 4 == bang_index:
+ supp_lines[l] = "*" + supp_lines[l][bang_index:]
+ self._suppression = "\n".join(supp_lines)
+
+ def __str__(self):
+ output = self._report + "\n"
+ if self._testcase:
+ output += "The report came from the `%s` test.\n" % self._testcase
+ output += "Suppression (error hash=#%016X#):\n" % self.ErrorHash()
+ output += (" For more info on using suppressions see "
+ "http://dev.chromium.org/developers/how-tos/using-drmemory#TOC-Suppressing-error-reports-from-the-\n")
+ output += "{\n%s\n}\n" % self._suppression
+ return output
+
+ # This is a device-independent hash identifying the suppression.
+ # By printing out this hash we can find duplicate reports between tests and
+ # different shards running on multiple buildbots
+ def ErrorHash(self):
+ return int(hashlib.md5(self._suppression).hexdigest()[:16], 16)
+
+ def __hash__(self):
+ return hash(self._suppression)
+
+ def __eq__(self, rhs):
+ return self._suppression == rhs
+
+
+class DrMemoryAnalyzer:
+ ''' Given a set of Dr.Memory output files, parse all the errors out of
+ them, unique them and output the results.'''
+
+ def __init__(self):
+ self.known_errors = set()
+ self.error_count = 0;
+
+ def ReadLine(self):
+ self.line_ = self.cur_fd_.readline()
+
+ def ReadSection(self):
+ result = [self.line_]
+ self.ReadLine()
+ while len(self.line_.strip()) > 0:
+ result.append(self.line_)
+ self.ReadLine()
+ return result
+
+ def ParseReportFile(self, filename, testcase):
+ ret = []
+
+ # First, read the generated suppressions file so we can easily lookup a
+ # suppression for a given error.
+ supp_fd = open(filename.replace("results", "suppress"), 'r')
+ generated_suppressions = {} # Key -> Error #, Value -> Suppression text.
+ for line in supp_fd:
+ # NOTE: this regexp looks fragile. Might break if the generated
+ # suppression format slightly changes.
+ m = re.search("# Suppression for Error #([0-9]+)", line.strip())
+ if not m:
+ continue
+ error_id = int(m.groups()[0])
+ assert error_id not in generated_suppressions
+ # OK, now read the next suppression:
+ cur_supp = ""
+ for supp_line in supp_fd:
+ if supp_line.startswith("#") or supp_line.strip() == "":
+ break
+ cur_supp += supp_line
+ generated_suppressions[error_id] = cur_supp.strip()
+ supp_fd.close()
+
+ self.cur_fd_ = open(filename, 'r')
+ while True:
+ self.ReadLine()
+ if (self.line_ == ''): break
+
+ match = re.search("^Error #([0-9]+): (.*)", self.line_)
+ if match:
+ error_id = int(match.groups()[0])
+ self.line_ = match.groups()[1].strip() + "\n"
+ report = "".join(self.ReadSection()).strip()
+ suppression = generated_suppressions[error_id]
+ ret.append(DrMemoryError(report, suppression, testcase))
+
+ if re.search("SUPPRESSIONS USED:", self.line_):
+ self.ReadLine()
+ while self.line_.strip() != "":
+ line = self.line_.strip()
+ (count, name) = re.match(" *([0-9]+)x(?: \(leaked .*\))?: (.*)",
+ line).groups()
+ count = int(count)
+ self.used_suppressions[name] += count
+ self.ReadLine()
+
+ if self.line_.startswith("ASSERT FAILURE"):
+ ret.append(self.line_.strip())
+
+ self.cur_fd_.close()
+ return ret
+
+ def Report(self, filenames, testcase, check_sanity):
+ sys.stdout.flush()
+ # TODO(timurrrr): support positive tests / check_sanity==True
+ self.used_suppressions = defaultdict(int)
+
+ to_report = []
+ reports_for_this_test = set()
+ for f in filenames:
+ cur_reports = self.ParseReportFile(f, testcase)
+
+ # Filter out the reports that were there in previous tests.
+ for r in cur_reports:
+ if r in reports_for_this_test:
+ # A similar report is about to be printed for this test.
+ pass
+ elif r in self.known_errors:
+ # A similar report has already been printed in one of the prev tests.
+ to_report.append("This error was already printed in some "
+ "other test, see 'hash=#%016X#'" % r.ErrorHash())
+ reports_for_this_test.add(r)
+ else:
+ self.known_errors.add(r)
+ reports_for_this_test.add(r)
+ to_report.append(r)
+
+ common.PrintUsedSuppressionsList(self.used_suppressions)
+
+ if not to_report:
+ logging.info("PASS: No error reports found")
+ return 0
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+ logging.info("Found %i error reports" % len(to_report))
+ for report in to_report:
+ self.error_count += 1
+ logging.info("Report #%d\n%s" % (self.error_count, report))
+ logging.info("Total: %i error reports" % len(to_report))
+ sys.stdout.flush()
+ return -1
+
+
+def main():
+ '''For testing only. The DrMemoryAnalyze class should be imported instead.'''
+ parser = optparse.OptionParser("usage: %prog [options] <files to analyze>")
+ parser.add_option("", "--source_dir",
+ help="path to top of source tree for this build"
+ "(used to normalize source paths in baseline)")
+
+ (options, args) = parser.parse_args()
+ if len(args) == 0:
+ parser.error("no filename specified")
+ filenames = args
+
+ logging.getLogger().setLevel(logging.INFO)
+ return DrMemoryAnalyzer().Report(filenames, None, False)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/valgrind/gdb_helper.py b/chromium/tools/valgrind/gdb_helper.py
new file mode 100644
index 00000000000..548ee9474e6
--- /dev/null
+++ b/chromium/tools/valgrind/gdb_helper.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+''' A bunch of helper functions for querying gdb.'''
+
+import logging
+import os
+import re
+import tempfile
+
+GDB_LINE_RE = re.compile(r'Line ([0-9]*) of "([^"]*)".*')
+
+def _GdbOutputToFileLine(output_line):
+ ''' Parse the gdb output line, return a pair (file, line num) '''
+ match = GDB_LINE_RE.match(output_line)
+ if match:
+ return match.groups()[1], match.groups()[0]
+ else:
+ return None
+
+def ResolveAddressesWithinABinary(binary_name, load_address, address_list):
+ ''' For each address, return a pair (file, line num) '''
+ commands = tempfile.NamedTemporaryFile()
+ commands.write('add-symbol-file "%s" %s\n' % (binary_name, load_address))
+ for addr in address_list:
+ commands.write('info line *%s\n' % addr)
+ commands.write('quit\n')
+ commands.flush()
+ gdb_commandline = 'gdb -batch -x %s 2>/dev/null' % commands.name
+ gdb_pipe = os.popen(gdb_commandline)
+ result = gdb_pipe.readlines()
+
+ address_count = 0
+ ret = {}
+ for line in result:
+ if line.startswith('Line'):
+ ret[address_list[address_count]] = _GdbOutputToFileLine(line)
+ address_count += 1
+ if line.startswith('No line'):
+ ret[address_list[address_count]] = (None, None)
+ address_count += 1
+ gdb_pipe.close()
+ commands.close()
+ return ret
+
+class AddressTable(object):
+ ''' Object to do batched line number lookup. '''
+ def __init__(self):
+ self._load_addresses = {}
+ self._binaries = {}
+ self._all_resolved = False
+
+ def AddBinaryAt(self, binary, load_address):
+ ''' Register a new shared library or executable. '''
+ self._load_addresses[binary] = load_address
+
+ def Add(self, binary, address):
+ ''' Register a lookup request. '''
+ if binary == '':
+ logging.warn('adding address %s in empty binary?' % address)
+ if binary in self._binaries:
+ self._binaries[binary].append(address)
+ else:
+ self._binaries[binary] = [address]
+ self._all_resolved = False
+
+ def ResolveAll(self):
+ ''' Carry out all lookup requests. '''
+ self._translation = {}
+ for binary in self._binaries.keys():
+ if binary != '' and binary in self._load_addresses:
+ load_address = self._load_addresses[binary]
+ addr = ResolveAddressesWithinABinary(
+ binary, load_address, self._binaries[binary])
+ self._translation[binary] = addr
+ self._all_resolved = True
+
+ def GetFileLine(self, binary, addr):
+ ''' Get the (filename, linenum) result of a previously-registered lookup
+ request.
+ '''
+ if self._all_resolved:
+ if binary in self._translation:
+ if addr in self._translation[binary]:
+ return self._translation[binary][addr]
+ return (None, None)
diff --git a/chromium/tools/valgrind/gtest_exclude/OWNERS b/chromium/tools/valgrind/gtest_exclude/OWNERS
new file mode 100644
index 00000000000..72e8ffc0db8
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/OWNERS
@@ -0,0 +1 @@
+*
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 00000000000..029dfa9cbd9
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,26 @@
+# TODO(timurrrr) investigate the failures and enable these tests one-by-one.
+RSA*
+GmockTest.*
+EtwTrace*
+StatsTableTest.*
+ProcessUtilTest.EnableLFH
+ScopedNativeLibrary.Basic
+# TODO(zhaoqin) investigate the failures and enable it later, 106043
+ConditionVariableTest.LargeFastTaskTest
+# Next test creates a child that crashes, which naturally generates an
+# unaddressable report as well as a handful of leak reports that we don't need
+# to see.
+ProcessUtilTest.GetTerminationStatusCrash
+# See crbug.com/130668
+ProcessUtilTest.GetTerminationStatusKill
+ProcessUtilTest.KillSlowChild
+ProcessUtilTest.SpawnChild
+ScopedProcessInformationTest.Duplicate
+ScopedProcessInformationTest.Swap
+ScopedProcessInformationTest.TakeBoth
+ScopedProcessInformationTest.TakeProcess
+ScopedProcessInformationTest.TakeWholeStruct
+SharedMemoryProcessTest.Tasks
+
+# crbug/144018
+ScopedStartupInfoExTest.InheritStdOut
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan.txt
new file mode 100644
index 00000000000..1f81beacd4a
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan.txt
@@ -0,0 +1,10 @@
+# Don't run this test under TSan, it takes ~1-2 minutes to pass.
+ProcessUtilTest.GetAppOutputRestrictedNoZombies
+
+# Don't run Memcheck sanity tests under ThreadSanitizer since they can
+# corrupt memory.
+ToolsSanityTest.*Memory*
+ToolsSanityTest.*Delete*
+
+# TSan doesn't understand SharedMemory locks, see http://crbug.com/45083
+StatsTableTest.*MultipleThreads
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan_mac.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan_mac.txt
new file mode 100644
index 00000000000..7ee06a18be3
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan_mac.txt
@@ -0,0 +1,2 @@
+# http://crbug.com/29855.
+StackTrace.OutputToStream
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan_win32.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan_win32.txt
new file mode 100644
index 00000000000..c9d407750d6
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest-tsan_win32.txt
@@ -0,0 +1,23 @@
+# Occasionally fails under TSan, see http://crbug.com/54229
+ProcessUtilTest.CalcFreeMemory
+
+# This file is copied from Valgrind-on-Wine filter
+# TODO(timurrrr): include/investigate the listed tests one-by-one
+EtwTraceControllerTest.EnableDisable
+EtwTraceConsumer*Test.*
+EtwTraceProvider*Test.*
+JSONReaderTest.Reading
+TimeTicks.*
+WMIUtilTest.*
+
+# Too slow under TSan
+ConditionVariableTest.LargeFastTaskTest
+
+# Fails under TSan: http://crbug.com/93843
+MessageLoopTest.RecursiveDenial3
+
+# Crashes under TSan: http://crbug.com/115107
+WorkerPoolTest.PostTask
+
+# Times out on Win7, slow on Vista: http://crbug.com/106531
+TraceEventTestFixture.DataCapturedManyThreads
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
new file mode 100644
index 00000000000..35c209db10f
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
@@ -0,0 +1,26 @@
+# This test currently times out in valgrind, see http://crbug.com/9194
+WatchdogTest.AlarmTest
+
+# These tests occassionally hangs under Valgrind on Mac. valgrind-darwin r9573
+# Revisit with better valgrind.
+# Valgrind bug: https://bugs.kde.org/show_bug.cgi?id=189661
+TimerTest.RepeatingTimer
+TimerTest.RepeatingTimer_Cancel
+
+# Crashes occasionally, see http://crbug.com/7477
+ObserverListThreadSafeTest.CrossThreadObserver
+ObserverListThreadSafeTest.CrossThreadNotifications
+
+# Hangs sometimes on linux, see http://crbug.com/22138
+ClipboardTest.*
+
+# These tests trigger a CHECK so they will leak memory. They don't test
+# anything else, so just disable them on valgrind. Bug 28179.
+OutOfMemoryDeathTest.*
+
+# Flaky under slow tools or just when the VM is under load.
+# See http://crbug.com/43972
+ConditionVariableTest.LargeFastTaskTest
+
+# Flaky under Valgrind, see http://crbug.com/55517
+PlatformFile.TouchGetInfoPlatformFile
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
new file mode 100644
index 00000000000..0d2a4d38b64
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
@@ -0,0 +1,18 @@
+# Fails on Valgrind/Mac, see http://crbug.com/43972
+ConditionVariableTest.LargeFastTaskTest
+
+# Fails on Valgrind/Mac due to missing syscall wrapper
+# for the symlink() syscall. See http://crbug.com/44001
+FileUtilTest.NormalizeFilePathSymlinks
+
+# Fails on Valgrind/Mac, see http://crbug.com/53196
+CancellationFlagTest.SetOnDifferentThreadDeathTest
+
+# Fails on Valgrind/Mac, see http://crbug.com/93722
+ProcessMemoryTest.MacTerminateOnHeapCorruption
+
+# Fails on Valgrind/Mac, see http://crbug.com/122080
+ProcessMemoryTest.MacMallocFailureDoesNotTerminate
+
+# Times out on Valgrind/Mac, see http://crbug.com/172044
+MessageLoopTest.RecursivePosts
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_win-8.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_win-8.txt
new file mode 100644
index 00000000000..1d24cdf8e52
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_win-8.txt
@@ -0,0 +1,2 @@
+# Fails natively as well: http://crbug.com/251517
+PEImageTest.EnumeratesPE
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_win32.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_win32.txt
new file mode 100644
index 00000000000..840a3035070
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest_win32.txt
@@ -0,0 +1,12 @@
+# Too slow under Valgrind/Wine and TSan/Windows
+TimeTicks.WinRollover
+
+# Very sensitive to slowdown
+TimeTicks.Deltas
+TimeTicks.HighResNow
+TimerTest.RepeatingTimer*
+
+# This Windows-native sampling profiler test does not work under our tools
+# because it assumes the original code runs, not the modified version
+# with instrumentation. See http://crbug.com/106829
+SamplingProfilerTest.Sample
diff --git a/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt
new file mode 100644
index 00000000000..c1dcce93fb7
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory_win32.txt
@@ -0,0 +1,50 @@
+# TODO(zhaoqin): File bugs for those failing browser tests.
+
+# Dr.Memory i#1052: http://code.google.com/p/drmemory/issues/detail?id=1052
+#
+# The list is too long for gtest_filter, so we exclude the whole
+# test case if any of its tests failed.
+*FLAKY*
+
+# it takes too long to run all browser_tests with Dr.Memory,
+# and we only select subset to run
+# A*: ~70 tests
+A*
+# DrM-i#1052-c#52
+# AutofillTest.*
+# AcceleratedCompositingBlockedTest.*
+# AppApiTest.*
+# BrowserAccessibilityStateImplTest.*
+B*
+C*
+D*
+E*
+F*
+G*
+# H*: ~35 tests
+H*
+# DrM-i#1052-c#53
+# HistoryWebUITest.*
+# I*: ~10 tests
+# DrM-i#1052-c#53
+InfoBarsTest.*
+# J*: 0 tests
+# K*: 1 tests
+L*
+M*
+N*
+O*
+P*
+Q*
+R*
+S*
+T*
+# U*: ~20 tests
+# DrM-i#1052-c#53
+UnloadTest.*
+# V*: 5 tests
+# W*: ~150 tests
+W*
+# X*: 0 tests
+# Y*: 0 tests
+# Z*: 0 tests
diff --git a/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-memcheck.txt b/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-memcheck.txt
new file mode 100644
index 00000000000..bad2936a0ea
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-memcheck.txt
@@ -0,0 +1,60 @@
+# Don't run FLAKY or FAILS ui tests under Valgrind.
+# They tend to generate way too many flaky Valgrind reports.
+*FLAKY_*
+*FAILS_*
+
+# NaCl tests fail with Data Execution Prevention error http://crbug.com/104517
+NaClGdbTest.Empty
+PPAPINaClGLibcTest.*
+PPAPINaClNewlibTest.*
+PPAPINaClTest*
+
+# http://crbug.com/109336
+OutOfProcessPPAPITest.View_PageHideShow
+
+# TODO(thestig) File bugs for these failing browser tests.
+AllUrlsApiTest.WhitelistedExtension
+AppBackgroundPageApiTest.NoJsManifestBackgroundPage
+BrowserCloseTest.DownloadsCloseCheck_2
+BrowserCloseTest.DownloadsCloseCheck_5
+BrowserEncodingTest.SLOW_TestEncodingAliasMapping
+BrowserNavigatorTest.Disposition_Bookmarks_DoNothingIfIncognitoIsForced
+BrowserNavigatorTest.Disposition_Incognito
+BrowserNavigatorTest.Disposition_SyncPromo_DoNothingIfIncognitoIsForced
+BrowserTest.ForwardDisabledOnForward
+ClickToPlayPluginTest.Basic
+ClickToPlayPluginTest.LoadAllBlockedPlugins
+ClickToPlayPluginTest.NoCallbackAtLoad
+DevToolsExperimentalExtensionTest.TestDevToolsExperimentalExtensionAPI
+DevToolsExtensionTest.TestDevToolsExtensionMessaging
+DownloadExtensionTest.DownloadExtensionTest_FileIcon_Active
+DownloadExtensionTest.DownloadExtensionTest_FileIcon_History
+DownloadExtensionTest.DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito
+DownloadExtensionTestIncognito.DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito
+ErrorPageTest.DNSError_Basic
+ErrorPageTest.DNSError_GoBack1
+ExecuteScriptApiTest.ExecuteScriptPermissions
+ExtensionApiTest.FontSettingsIncognito
+ExtensionApiTest.PopupBlockingExtension
+ExtensionApiTest.PopupBlockingHostedApp
+FastShutdown.SlowTermination
+IndexedDBLayoutTest.IndexTests
+NetInternalsTest.netInternalsPrerenderViewFail
+NewTabUIBrowserTest.LoadNTPInExistingProcess
+OutOfProcessPPAPITest.NetAddressPrivate_GetAnyAddress
+OutOfProcessPPAPITest.NetAddressPrivate_ReplacePort
+PageCyclerCachedBrowserTest.PlaybackMode
+PageCyclerCachedBrowserTest.URLNotInCache
+PPAPITest.ImeInputEvent
+PrerenderBrowserTest.*
+PrerenderBrowserTestWithNaCl.PrerenderNaClPluginEnabled
+PrintPreviewWebUITest.TestPrinterList
+PrintPreviewWebUITest.TestPrinterListCloudEmpty
+PrintPreviewWebUITest.TestSectionsDisabled
+PrintWebViewHelperTest.BlockScriptInitiatedPrinting
+SafeBrowsingBlockingPageTest.MalwareDontProceed
+SafeBrowsingBlockingPageTest.ProceedDisabled
+SocketApiTest.SocketTCPExtension
+SocketApiTest.SocketUDPExtension
+SSLUITest.TestWSSInvalidCertAndGoForward
+WebViewTest.Shim
diff --git a/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-tsan.txt b/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-tsan.txt
new file mode 100644
index 00000000000..c96da5b20b8
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-tsan.txt
@@ -0,0 +1,2 @@
+# http://crbug.com/159234.
+WebContentsVideoCaptureDeviceTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
new file mode 100644
index 00000000000..3d1c13dc370
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
@@ -0,0 +1,3 @@
+# Flaky, see http://crbug.com/227278
+WebContentsVideoCaptureDeviceTest.WebContentsDestroyed
+CompositingIOSurfaceTransformerTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt b/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt
new file mode 100644
index 00000000000..6e109511c92
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest_mac.txt
@@ -0,0 +1,52 @@
+# http://crbug.com/93245
+GeolocationGatewayDataProviderCommonTest.*
+GeolocationWifiDataProviderCommonTest.*
+
+# Flaky, see http://crbug.com/131154
+WebRTCAudioDeviceTest.FullDuplexAudioWithAGC
+
+# Flaky, see http://crbug.com/155284
+WebRTCAudioDeviceTest.StartRecording
+WebRTCAudioDeviceTest.PlayLocalFile
+
+# Fail/crash, see http://crbug.com/151939
+WebDragDestTest.URL
+WebDragDestTest.Data
+WebDragSourceMacTest.DragInvalidlyEscapedBookmarklet
+
+# Fail, see http://crbug.com/153007
+MacSandboxTest.ClipboardAccess
+
+# mach_override assertion, see http://crbug.com/162728
+BlobURLRequestJobTest.*
+
+# Fail, see http://crbug.com/159234
+WebContentsVideoCaptureDeviceTest.GoesThroughAllTheMotions
+WebContentsVideoCaptureDeviceTest.BadFramesGoodFrames
+
+# Hang at arbitrary point, can't tell where exactly, see http://crbug.com/163314
+RenderWidgetHostViewMacTest.*
+WebContentsVideoCaptureDeviceTest.*
+RenderViewHostTest.*
+DeviceMotionEventPumpTest.*
+
+# Speculative disable of hanging tests. http://crbug.com/241919
+VideoCaptureControllerTest.*
+VideoCaptureHostTest.*
+
+# Hangs under Valgrind, see http://crbug.com/244257
+SmoothScrollGestureControllerTest.Tick
+
+# http://crbug.com/247163
+VideoCaptureManagerTest.CloseWithoutStop
+VideoCaptureManagerTest.CreateAndClose
+VideoCaptureManagerTest.StartUsingId
+WebRTCAudioDeviceTest.WebRtcPlayoutSetupTime
+WebRTCAudioDeviceTest.WebRtcRecordingSetupTime
+
+# http://crbug.com/247601
+FontSerializationTest.StyledFonts
+MacSandboxTest.FontLoadingTest
+
+# http://crbug.com/270254
+DeviceOrientationEventPumpTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/crypto_unittests.gtest-tsan_win32.txt b/chromium/tools/valgrind/gtest_exclude/crypto_unittests.gtest-tsan_win32.txt
new file mode 100644
index 00000000000..3ed1f116532
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/crypto_unittests.gtest-tsan_win32.txt
@@ -0,0 +1,2 @@
+# Too slow under TSan
+RSAPrivateKeyUnitTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/interactive_ui_tests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/interactive_ui_tests.gtest.txt
new file mode 100644
index 00000000000..6ae761f0a91
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/interactive_ui_tests.gtest.txt
@@ -0,0 +1,34 @@
+# These test fail due to mmap Valgrind failures, see http://crbug.com/66677
+CollectedCookiesTest.DoubleDisplay
+CollectedCookiesTest.NavigateAway
+InfoBarsUITest.TestInfoBarsCloseOnNewTheme
+FastShutdown.SlowTermination
+MouseLeaveTest.TestOnMouseOut
+NotificationsPermissionTest.TestNoUserGestureInfobar
+NotificationsPermissionTest.TestUserGestureInfobar
+
+# These test fail due to timeout or limited buildslave support;
+# http://crbug.com/67301
+BrowserFocusTest.InterstitialFocus
+BrowserFocusTest.FindFocusTest
+BrowserFocusTest.FocusTraversalOnInterstitial
+
+# Don't run FLAKY or FAILS tests under Valgrind and TSan
+# as they tend to generate too many reports, see http://crbug.com/67959
+# NB: Can't use FAILS_/FLAKY_ as it will be turned into *.* by chrome_tests.py!
+*.FLAKY*
+*.FAILS*
+
+# Fails under Valgrind, see http://crbug.com/68068
+DevToolsSanityTest.TestPauseWhenScriptIsRunning
+
+# These tests time out under Valgrind, see http://crbug.com/163880
+BrowserFocusTest.FocusOnReload
+CommandsApiTest.Basic
+ExtensionApiTest.NotificationsHasPermissionManifest
+ExtensionCrashRecoveryTest.ReloadTabsWithBackgroundPage
+ExtensionCrashRecoveryTest.TwoExtensionsCrashBothAtOnce
+ExtensionCrashRecoveryTest.TwoExtensionsCrashFirst
+ExtensionCrashRecoveryTest.TwoExtensionsOneByOne
+FullscreenControllerInteractiveTest.TestTabExitsMouseLockOnNavigation
+OmniboxViewTest.Escape
diff --git a/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest-drmemory_win32.txt
new file mode 100644
index 00000000000..ac62a9a6e95
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest-drmemory_win32.txt
@@ -0,0 +1,2 @@
+# TODO(timurrrr): investigate
+IPCSyncChannelTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest-tsan_win32.txt b/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest-tsan_win32.txt
new file mode 100644
index 00000000000..f13b4d997c4
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest-tsan_win32.txt
@@ -0,0 +1,2 @@
+# Fails under TSan, see http://crbug.com/62511
+IPCSyncChannelTest.BadMessage
diff --git a/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest.txt
new file mode 100644
index 00000000000..30a1f89323b
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/ipc_tests.gtest.txt
@@ -0,0 +1,6 @@
+# Takes 27-40 seconds to run.
+IPCSyncChannelTest.ChattyServer
+# Hangs on Linux sometimes. See http://crbug.com/22141
+IPCChannelTest.ChannelTest
+# Crashes under Valgrind. See http://crbug.com/46782
+IPCSyncChannelTest.Multiple
diff --git a/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 00000000000..315244542d3
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,4 @@
+# Hangs under Dr. Memory
+# http://code.google.com/p/drmemory/issues/detail?id=978
+WinAudioTest.SyncSocketBasic
+AudioBusTest.CopyTo
diff --git a/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest-tsan_win32.txt b/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest-tsan_win32.txt
new file mode 100644
index 00000000000..ef4835c093f
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest-tsan_win32.txt
@@ -0,0 +1,3 @@
+# Win TSan disturbs ffmpeg's output, causing hash comparison assertion to fail.
+# http://crbug.com/120396
+PipelineIntegrationTest.BasicPlaybackHashed
diff --git a/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest.txt
new file mode 100644
index 00000000000..7e22249b8e4
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/media_unittests.gtest.txt
@@ -0,0 +1,3 @@
+# This test tries to record fake audio in real-time.
+# This appears to be too sensitive to slowdown, see http://crbug.com/49497
+FakeAudioInputTest.BasicCallbacks
diff --git a/chromium/tools/valgrind/gtest_exclude/message_center_unittests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/message_center_unittests.gtest.txt
new file mode 100644
index 00000000000..56bb83c0e39
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/message_center_unittests.gtest.txt
@@ -0,0 +1,3 @@
+# Fails http://crbug.com/256911
+MessageCenterImplTest.PopupTimersControllerResetTimer
+MessageCenterImplTest.PopupTimersControllerStartMultipleTimersPause
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win-xp.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win-xp.txt
new file mode 100644
index 00000000000..46717dc3890
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win-xp.txt
@@ -0,0 +1,3 @@
+# http://code.google.com/p/drmemory/issues/detail?id=842
+# Failing and then crashing.
+HttpNetworkTransationSpdy21Test.HttpsProxySpdy*
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 00000000000..f0d641122c8
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,24 @@
+# See http://crbug.com/82391
+URLRequestTestHTTP.HTTPSToHTTPRedirectNoRefererTest
+
+# Times out. See http://crbug.com/134313
+URLRequestTestHTTP.GetTest_ManyCookies
+
+# Dr. Memory hits an assertion:
+# http://code.google.com/p/drmemory/issues/detail?id=422
+HttpAuthTest.*
+HttpAuthHandlerFactoryTest.*
+X509CertificateTest.*
+
+# Too many uninits and too slow. TODO(timurrrr): investigate uninits
+ProxyResolverV8Test.*
+
+# Slow
+CookieMonsterTest.GarbageCollectionTriggers
+
+# Hangs only when built in release mode.
+# http://crbug.com/105762
+ClientSocketPoolBaseTest.DisableCleanupTimer
+
+# Flaky, see http://crbug.com/108422
+SSLClientSocketTest.ConnectMismatched
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-memcheck.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-memcheck.txt
new file mode 100644
index 00000000000..264a7fa8992
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-memcheck.txt
@@ -0,0 +1,26 @@
+# These tests leak data intentionally, so are inappropriate for Valgrind tests.
+# Similar list in ../purify/net_unittests.exe.gtest.txt
+# TODO(dkegel): either merge the two files or keep them in sync,
+# see http://code.google.com/p/chromium/issues/detail?id=8951
+DiskCacheBackendTest.AppCacheInvalidEntry
+DiskCacheBackendTest.AppCacheInvalidEntryRead
+DiskCacheBackendTest.AppCacheInvalidEntryWithLoad
+DiskCacheBackendTest.InvalidEntry
+DiskCacheBackendTest.InvalidEntryRead
+DiskCacheBackendTest.InvalidEntryWithLoad
+DiskCacheBackendTest.TrimInvalidEntry
+DiskCacheBackendTest.TrimInvalidEntry2
+DiskCacheBackendTest.InvalidEntryEnumeration
+DiskCacheBackendTest.NewEvictionInvalidEntry
+DiskCacheBackendTest.NewEvictionInvalidEntryRead
+DiskCacheBackendTest.NewEvictionInvalidEntryWithLoad
+DiskCacheBackendTest.NewEvictionTrimInvalidEntry
+DiskCacheBackendTest.NewEvictionTrimInvalidEntry2
+DiskCacheBackendTest.NewEvictionInvalidEntryEnumeration
+DiskCacheBackendTest.ShutdownWithPendingCreate_Fast
+DiskCacheBackendTest.ShutdownWithPendingFileIO_Fast
+DiskCacheBackendTest.ShutdownWithPendingIO_Fast
+
+# flaky failure on Linux Tests (valgrind)(2),
+# see http://code.google.com/p/chromium/issues/detail?id=117196
+SSLClientSocketTest.VerifyReturnChainProperlyOrdered
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan.txt
new file mode 100644
index 00000000000..79c5afa8e08
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan.txt
@@ -0,0 +1,27 @@
+# These huge tests are flaky and sometimes crash the following tests.
+# See http://crbug.com/50346
+DiskCacheEntryTest.*HugeSparse*
+
+# SPDY tests tend to crash on both Mac and Windows.
+# See http://crbug.com/51144
+Spdy/SpdyNetworkTransactionTest.SocketWriteReturnsZero*
+# See http://crbug.com/50918
+Spdy/SpdyNetworkTransactionTest.CancelledTransactionSendRst*
+# See http://crbug.com/51087
+Spdy*
+
+# See http://crbug.com/44570
+HttpNetworkTransactionTest.StopsReading204
+# See http://crbug.com/51145
+HttpNetworkTransactionTest.Incomplete100ThenEOF
+HttpNetworkTransactionTest.UseAlternateProtocolForNpnSpdyWithExistingSpdySession
+HttpNetworkTransactionTest.KeepAliveConnectionEOF
+
+# Crashes silently, see http://crbug.com/76911
+URLRequestTest.FileTest
+
+# http://crbug.com/92439
+ServerBoundCertServiceTest.*
+
+# Flaky, see http://crbug.com/259781
+EmbeddedTestServerTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan_mac.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan_mac.txt
new file mode 100644
index 00000000000..2b58bba9c39
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan_mac.txt
@@ -0,0 +1,11 @@
+# WebSocketTest tests are extraordinary slow under ThreadSanitizer,
+# (see http://crbug.com/25392)
+# TODO(glider): investigate this.
+WebSocketTest.*
+
+# Strange reports from __NSThread__main__ appeared with the new TSan binaries
+# See http://crbug.com/38926
+DirectoryLister*
+
+# Looks like http://crbug.com/78536 depends on this test.
+CookieMonsterTest.GarbageCollectionTriggers
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan_win32.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan_win32.txt
new file mode 100644
index 00000000000..e336298a00a
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-tsan_win32.txt
@@ -0,0 +1,40 @@
+# These tests fail due to unknown reasons
+# TODO(timurrrr): investigate
+CookieMonsterTest.TestLastAccess
+SpdyNetwork*Error*
+SpdyNetwork*Get*
+SpdyNetworkTransactionTest.SynReplyHeadersVary
+X509CertificateTest.UnoSoftCertParsing
+URLRequestTest.DoNotSaveCookies
+URLRequestTest.QuitTest
+
+# See http://crbug.com/47836
+ClientSocketPoolBaseTest.CancelPendingSocketAtSocketLimit
+
+# Single-threaded and relatively slow - no reason to test
+# See http://crbug.com/59642
+CookieMonsterTest.GarbageCollectionTriggers
+
+# Time out, see http://crbug.com/68482
+SSLServerSocketTest.*
+
+# See http://crbug.com/102330
+SSLClientSocketTest.*
+
+# See http://crbug.com/104805
+HostResolverImplTest.AbortOnlyExistingRequestsOnIPAddressChange
+
+# Times out occasionally, http://crbug.com/124452
+HostResolverImplTest.StartWithinCallback
+
+# Crash. See crbug.com/234776.
+DiskCacheEntryTest.EvictOldEntries
+DiskCacheEntryTest.NewEvictionEvictOldEntries
+
+# Hang. crbug.com/265647.
+NetworkChangeNotifierWinTest.NetChangeWinBasic
+NetworkChangeNotifierWinTest.NetChangeWinSignal
+NetworkChangeNotifierWinTest.NetChangeWinFailSignal*
+
+
+
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest.txt
new file mode 100644
index 00000000000..6c7d3cadb7a
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest.txt
@@ -0,0 +1,17 @@
+# Very slow under Valgrind.
+KeygenHandlerTest.*SmokeTest
+KeygenHandlerTest.*ConcurrencyTest
+
+# Hangs, see http://crbug.com/61908
+DirectoryListerTest.BigDirRecursiveTest
+
+# http://crbug.com/88228
+SSLClientSocketTest.Connect
+SSLClientSocketTest.ConnectClientAuthSendNullCert
+
+# These tests are broken http://crbug.com/118883
+*SpdyNetworkTransactionSpdy*Test.*
+*SpdyHttpStreamSpdy*Test.*
+
+# Fails flakily. http://crbug.com/255775
+SimpleIndexFileTest.WriteThenLoadIndex
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest_linux.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest_linux.txt
new file mode 100644
index 00000000000..a93d58871b0
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest_linux.txt
@@ -0,0 +1,5 @@
+# Flaky. crbug.com/234776
+DiskCacheEntryTest.SimpleCacheStreamAccess
+DiskCacheEntryTest.SimpleCacheGrowData
+DiskCacheEntryTest.SimpleCacheSizeChanges
+
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest_mac.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest_mac.txt
new file mode 100644
index 00000000000..6986bdfe874
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest_mac.txt
@@ -0,0 +1,6 @@
+# Very slow under Valgrind, (see <http://crbug.com/37289>).
+KeygenHandlerTest.SmokeTest
+
+# These tests fail under Valgrind on Mac, see http://crbug.com/62314
+SSLClientSocketTest.*
+HTTPSRequestTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/printing_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/printing_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 00000000000..58a6a8da51d
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/printing_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,3 @@
+# CreateDC returns NULL, see http://crbug.com/73652
+PrintingContextTest.Base
+PrintingContextTest.PrintAll
diff --git a/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 00000000000..2b1ead484e9
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,9 @@
+# This test fails on an assertion, see http://crbug.com/57266
+EncoderVp8Test.TestEncoder
+DecoderVp8Test.EncodeAndDecode
+
+# These test intentionally generate exceptions to verify if a dump is generated
+# during the crash.
+BreakpadWinDeathTest.TestAccessViolation
+BreakpadWinDeathTest.TestInvalidParameter
+BreakpadWinDeathTest.TestDebugbreak
diff --git a/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-tsan_win32.txt b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-tsan_win32.txt
new file mode 100644
index 00000000000..d446a1df17b
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-tsan_win32.txt
@@ -0,0 +1,2 @@
+# These tests load mstscax.dll, which generates a bunch of race reports, see http://crbug.com/177832
+RdpClientTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest.txt
new file mode 100644
index 00000000000..c322014654a
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest.txt
@@ -0,0 +1,2 @@
+# http://crbug.com/241856
+VideoSchedulerTest.StartAndStop
diff --git a/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest_win-8.txt b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest_win-8.txt
new file mode 100644
index 00000000000..eaf36f8f047
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest_win-8.txt
@@ -0,0 +1,2 @@
+# Fails natively as well: http://crbug.com/251517
+RdpClientTest.Basic
diff --git a/chromium/tools/valgrind/gtest_exclude/safe_browsing_tests.gtest_mac.txt b/chromium/tools/valgrind/gtest_exclude/safe_browsing_tests.gtest_mac.txt
new file mode 100644
index 00000000000..3afb727a320
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/safe_browsing_tests.gtest_mac.txt
@@ -0,0 +1,2 @@
+# Fails on Valgrind/Mac, see http://crbug.com/69280
+SafeBrowsingServiceTest.SafeBrowsingSystemTest
diff --git a/chromium/tools/valgrind/gtest_exclude/suppressions.txt b/chromium/tools/valgrind/gtest_exclude/suppressions.txt
new file mode 100644
index 00000000000..e8cc21038a2
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/suppressions.txt
@@ -0,0 +1,39 @@
+{
+ Test DiskCacheBackendTest.InvalidEntryEnumeration leaks.
+ Memcheck:Leak
+ fun:_Znwj
+ fun:_ZN10disk_cache12StorageBlockINS_12RankingsNodeEE12AllocateDataEv
+ fun:_ZN10disk_cache12StorageBlockINS_12RankingsNodeEE4LoadEv
+ fun:_ZN10disk_cache9EntryImpl15LoadNodeAddressEv
+ fun:_ZN10disk_cache11BackendImpl8NewEntryENS_4AddrEPPNS_9EntryImplEPb
+ fun:_ZN10disk_cache11BackendImpl10MatchEntryERKSsjb
+ fun:_ZN10disk_cache11BackendImpl9OpenEntryERKSsPPNS_5EntryE
+ fun:_ZN49DiskCacheBackendTest_InvalidEntryEnumeration_Test8TestBodyEv
+ fun:_ZN7testing4Test3RunEv
+}
+{
+ Test DiskCacheBackendTest.InvalidEntryRead leaks.
+ Memcheck:Leak
+ fun:_Znwj
+ fun:_ZN10disk_cache11BackendImpl8NewEntryENS_4AddrEPPNS_9EntryImplEPb
+ fun:_ZN10disk_cache11BackendImpl10MatchEntryERKSsjb
+ fun:_ZN10disk_cache11BackendImpl9OpenEntryERKSsPPNS_5EntryE
+ fun:_ZN42DiskCacheBackendTest_InvalidEntryRead_Test8TestBodyEv
+ fun:_ZN7testing4Test3RunEv
+}
+{
+ Test DiskCacheBackendTest.InvalidEntryWithLoad leaks.
+ Memcheck:Leak
+ fun:_Znwj
+ fun:_ZN10disk_cache11BackendImpl11CreateEntryERKSsPPNS_5EntryE
+ fun:_ZN46DiskCacheBackendTest_InvalidEntryWithLoad_Test8TestBodyEv
+ fun:_ZN7testing4Test3RunEv
+}
+{
+ Test FlipNetworkTransactionTest.WriteError Bug 29004
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net26FlipNetworkTransactionTest17TransactionHelperERKNS_15HttpRequestInfoEPNS_17DelayedSocketDataE
+ fun:_ZN3net42FlipNetworkTransactionTest_WriteError_Test8TestBodyEv
+}
diff --git a/chromium/tools/valgrind/gtest_exclude/sync_unit_tests.gtest-asan.txt b/chromium/tools/valgrind/gtest_exclude/sync_unit_tests.gtest-asan.txt
new file mode 100644
index 00000000000..fc2cc8ec845
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/sync_unit_tests.gtest-asan.txt
@@ -0,0 +1,2 @@
+# Flaky, see http://crbug.com/118370
+SyncSchedulerTest.TransientPollFailure
diff --git a/chromium/tools/valgrind/gtest_exclude/sync_unit_tests.gtest-tsan.txt b/chromium/tools/valgrind/gtest_exclude/sync_unit_tests.gtest-tsan.txt
new file mode 100644
index 00000000000..69768478008
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/sync_unit_tests.gtest-tsan.txt
@@ -0,0 +1,5 @@
+# Flaky, see http://crbug.com/118370
+SyncSchedulerTest.TransientPollFailure
+
+# Flaky, http://crbug.com/119467
+InvalidationNotifierTest.Basic
diff --git a/chromium/tools/valgrind/gtest_exclude/ui_unittests.gtest-memcheck.txt b/chromium/tools/valgrind/gtest_exclude/ui_unittests.gtest-memcheck.txt
new file mode 100644
index 00000000000..9474d9faa3e
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/ui_unittests.gtest-memcheck.txt
@@ -0,0 +1,2 @@
+# http://crbug.com/222606
+RenderTextTest.DisplayRectShowsCursorLTR
diff --git a/chromium/tools/valgrind/gtest_exclude/ui_unittests.gtest-tsan.txt b/chromium/tools/valgrind/gtest_exclude/ui_unittests.gtest-tsan.txt
new file mode 100644
index 00000000000..64383b7dcbf
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/ui_unittests.gtest-tsan.txt
@@ -0,0 +1,2 @@
+# Hangs under TSAN, see http://crbug.com/28332
+TextEliderTest.ElideTextLongStrings
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win-xp.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win-xp.txt
new file mode 100644
index 00000000000..2ef9d506eae
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win-xp.txt
@@ -0,0 +1,7 @@
+# Crashing (!) since forever, needs analysis.
+BookmarkNodeDataTest.*
+
+# http://code.google.com/p/drmemory/issues/detail?id=842
+# Fails assertion. App data corrupted by DrMemory?
+JsonSchemaTest.TestType
+JsonSchemaTest.TestNumber
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
new file mode 100644
index 00000000000..ce084e9761a
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
@@ -0,0 +1,69 @@
+##################################################
+# known Dr. Memory bugs:
+
+# http://code.google.com/p/drmemory/issues/detail?id=318
+AudioRendererHostTest.*
+
+##################################################
+# un-analyzed Dr. Memory bugs:
+
+# http://code.google.com/p/drmemory/issues/detail?id=548
+DownloadManagerTest.StartDownload
+
+# http://code.google.com/p/drmemory/issues/detail?id=979
+FirefoxProfileImporterTest.Firefox35Importer
+
+# http://code.google.com/p/drmemory/issues/detail?id=980
+MetricsLogManagerTest.*
+
+# http://code.google.com/p/drmemory/issues/detail?id=983
+ProfileShortcutManagerTest.*
+
+##################################################
+# Chromium bugs:
+
+# times out on the bot
+# http://crbug.com/87887
+VideoCaptureHostTest.*
+
+# crashes due to use-after-free's, http://crbug.com/90980
+FirefoxImporterTest.Firefox*NSS3Decryptor
+
+# fails http://crbug.com/92144
+ServiceProcessStateTest.ForceShutdown
+
+# fails sporadically: http://crbug.com/108205
+MultiProcessLockTest.RecursiveLock
+
+# Poor isolation, DCHECKs when no MessageLoop exists. Breaks when sharded.
+# http://crbug.com/117679
+WebsiteSettingsModelTest.*
+
+# fails to create thread
+# http://crbug.com/144087
+DesktopNotificationServiceTest.SettingsForSchemes
+TemplateURLFetcherTest.*
+
+# times out on the bot.
+# http://crbug.com/148644
+GAIAInfoUpdateServiceTest.*
+ProfileManagerTest.*
+ProfileInfoCacheTest.*
+
+# Failing on the bot. http://crbug.com/167014
+BrowserCommandControllerTest.AvatarMenuDisabledWhenOnlyOneProfile
+
+# Failing on the bot. http://crbug.com/168882
+UserCloudPolicyStoreTest.LoadWithInvalidFile
+UserCloudPolicyStoreTest.LoadWithNoFile
+UserCloudPolicyStoreTest.Store
+UserCloudPolicyStoreTest.StoreThenClear
+UserCloudPolicyStoreTest.StoreThenLoad
+UserCloudPolicyStoreTest.StoreTwoTimes
+UserCloudPolicyStoreTest.StoreValidationError
+
+# Tests are timing out on the bot. crbug.com/248373.
+PnaclTranslationCacheTest.*
+
+# Failing on the bot. crbug.com/266972
+OneClickSigninBubbleViewTest.ShowBubble
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
new file mode 100644
index 00000000000..54d3b03611f
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-memcheck.txt
@@ -0,0 +1,12 @@
+# Takes too long and may cause bots to time out. http://crbug.com/134400
+# This test alone takes 10-15 minutes.
+Convolver.SIMDVerification
+
+# Timing issues. http://crbug.com/241051
+ExtensionAlarmsTest.*
+
+# SEGV_MAPERR. http://crbug.com/245797
+ClientSideDetectionHostTest.NavigationCancelsShouldClassifyUrl
+
+# Test fails on CrOS memcheck only. http://crbug.com/247440
+NotificationAudioControllerTest.MultiProfiles
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-tsan.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-tsan.txt
new file mode 100644
index 00000000000..ec8d751dad6
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-tsan.txt
@@ -0,0 +1,12 @@
+# This test has a possible data race detected by the TSAN bot
+# see http://crbug.com/46840
+ProfileManagerTest.CreateAndUseTwoProfiles
+
+# Crashing - http://crbug.com/84536
+HttpBridgeTest.*
+
+# Takes too long and may cause TSAN bots to time out. http://crbug.com/134400
+Convolver.SIMDVerification
+
+# SEGV_MAPERR. http://crbug.com/245797
+ClientSideDetectionHostTest.NavigationCancelsShouldClassifyUrl
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-tsan_mac.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-tsan_mac.txt
new file mode 100644
index 00000000000..20563c7994e
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-tsan_mac.txt
@@ -0,0 +1,5 @@
+# http://crbug.com/26214
+ExtensionTest.InitFromValueInvalid
+
+# http://crbug.com/38503
+TabRestoreServiceTest.DontPersistPostData
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest.txt
new file mode 100644
index 00000000000..b3c944c4a63
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest.txt
@@ -0,0 +1,36 @@
+# Hangs sometimes; see http://crbug.com/22146
+VisitedLinkEventsTest.Coalescense
+# Hangs sometimes; see http://crbug.com/22160
+VisitedLinkRelayTest.Basics
+# Hangs (or takes forever?) reliably on bots; see http://crbug.com/23580
+RenderViewTest.ImeComposition
+# Hangs sometimes; see http://crbug.com/52844
+PredictorTest.MassiveConcurrentLookupTest
+# Pure virtual method called: see http://crbug.com/50950
+ConnectionTesterTest.RunAllTests
+
+# Following tests fail under valgrind because libjingle has hardcoded
+# timeouts for P2P connections, and it makes these tests fail under valgrind.
+# TODO(sergeyu): Remove hardcoded timeouts from libjingle.
+P2PTransportImplTest.Create
+P2PTransportImplTest.ConnectUdp
+P2PTransportImplTest.ConnectTcp
+P2PTransportImplTest.SendDataUdp
+P2PTransportImplTest.SendDataTcp
+
+# Failing on CrOS, see http://crbug.com/79657
+SignedSettingsTest.StorePolicyNoPolicyData
+
+# Flaky and not very interesting under Valgrind http://crbug.com/93027
+ProcessWatcherTest.ImmediateTermination
+
+# Timing out all over the place. Disabling for now. http://crbug.com/149715
+ExtensionWebRequestTest.*
+# Timing out all over the place. Disabling for now. http://crbug.com/149882
+NativeMessagingTest.*
+
+# Timing out all over the place. Disabling for now. http://crbug.com/164589
+StorageInfoProviderTest.*
+
+# Fails under Valgrind, probably timing-related. http://crbug.com/259679
+WhitelistManagerTest.DownloadWhitelistRetry
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
new file mode 100644
index 00000000000..5bc4480e255
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest_linux.txt
@@ -0,0 +1,37 @@
+# Fails under Valgrind; see http://crbug.com/36770
+URLFetcherBadHTTPSTest.BadHTTPSTest
+# Fails under Valgrind; see http://crbug.com/44552
+RenderViewTest.OnHandleKeyboardEvent
+# http://crbug.com/88221
+ConnectionTesterTest.DeleteWhileInProgress
+# Crash on CrOS, see http://crbug.com/115979
+ClientSideDetectionHostTest.OnPhishingDetectionDoneNotPhishing
+ClientSideDetectionHostTest.OnPhishingDetectionDoneVerdictNotPhishing
+ClientSideDetectionHostTest.OnPhishingDetectionDoneInvalidVerdict
+ClientSideDetectionHostTest.OnPhishingDetectionDoneDisabled
+
+# http://crbug.com/119610
+ProfileSyncServiceSessionTest.WriteFilledSessionToNode
+ProfileSyncServiceSessionTest.ValidTabs
+
+# http://crbug.com/139652
+BackgroundApplicationListModelTest.RandomTest
+
+# http://crbug.com/179427
+ExtensionPrefsDelayedInstallInfo.DelayedInstallInfo
+ExtensionServiceTest.*
+
+# http://crbug.com/180335
+AutocompleteActionPredictorTest.RecommendActionURL
+
+# http://crbug.com/180467
+HttpPipeliningCompatibilityClientTest.*
+
+# http://crbug.com/238964
+CpuInfoProviderTest.*
+
+# Fails flakily. http://crbug.com/255771
+NetworkStatsTestUDP.UDPEcho*
+
+# Fails flakily. http://crbug.com/269965
+DesktopMediaPickerModelTest.UpdateThumbnail \ No newline at end of file
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest_mac.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest_mac.txt
new file mode 100644
index 00000000000..589b6947ad8
--- /dev/null
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest_mac.txt
@@ -0,0 +1,39 @@
+# Times out too often
+# crbug.com/15817
+IPCSyncChannelTest.*
+# Hangs
+# http://crbug.com/21890
+WebDropTargetTest.URL
+WebDropTargetTest.Data
+# http://crbug.com/69037
+FirefoxImporterTest.Firefox3NSS3Decryptor
+# http://crbug.com/69039
+ProcessInfoSnapshotMacTest.EffectiveVsRealUserIDTest
+
+# Following tests do not pass memcheck test.
+# See http://crbug.com/30393.
+NSMenuItemAdditionsTest.TestMOnDifferentLayouts
+
+# Hangs
+# See http://crbug.com/75733
+BookmarkBarControllerTest.DeleteFromOffTheSideWhileItIsOpen
+BookmarkBarControllerTest.HideWhenShowBookmarkBarTrueButDisabled
+BookmarkBarControllerTest.HideWhenShowBookmarkBarFalse
+
+# Crashes, see http://crbug.com/86656
+MacSandboxTest.FileAccess
+
+# http://crbug.com/87769
+BalloonControllerTest.ShowAndCloseTest
+BalloonControllerTest.SizesTest
+
+# http://crbug.com/89030
+ConnectionTesterTest.DeleteWhileInProgress
+
+# http://crbug.com/93245
+GeolocationWifiDataProviderCommonTest.*
+
+# http://crbug.com/96298
+FileSystemDirURLRequestJobTest.*
+FileSystemURLRequestJobTest.*
+FileSystemOperationWriteTest.*
diff --git a/chromium/tools/valgrind/locate_valgrind.sh b/chromium/tools/valgrind/locate_valgrind.sh
new file mode 100755
index 00000000000..5d0a06be467
--- /dev/null
+++ b/chromium/tools/valgrind/locate_valgrind.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Prints a path to Valgrind binaries to be used for Chromium.
+# Select the valgrind from third_party/valgrind by default,
+# but allow users to override this default without editing scripts and
+# without specifying a commandline option
+
+export THISDIR=`dirname $0`
+
+# User may use his own valgrind by giving its path with CHROME_VALGRIND env.
+if [ "$CHROME_VALGRIND" = "" ]
+then
+ # Guess which binaries we should use by uname
+ case "$(uname -a)" in
+ *Linux*x86_64*)
+ PLATFORM="linux_x64"
+ ;;
+ *Linux*86*)
+ PLATFORM="linux_x86"
+ ;;
+ *Darwin*9.[678].[01]*i386*)
+ # Didn't test other kernels.
+ PLATFORM="mac"
+ ;;
+ *Darwin*10.[0-9].[0-9]*i386*)
+ PLATFORM="mac_10.6"
+ ;;
+ *Darwin*10.[0-9].[0-9]*x86_64*)
+ PLATFORM="mac_10.6"
+ ;;
+ *Darwin*11.[0-9].[0-9]*x86_64*)
+ PLATFORM="mac_10.7"
+ ;;
+ *)
+ echo "Unknown platform:" >&2
+ uname -a >&2
+ echo "We'll try to search for valgrind binaries installed in /usr/local" >&2
+ PLATFORM=
+ esac
+
+ if [ "$PLATFORM" != "" ]
+ then
+ # The binaries should be in third_party/valgrind
+ # (checked out from deps/third_party/valgrind/binaries).
+ CHROME_VALGRIND="$THISDIR/../../third_party/valgrind/$PLATFORM"
+
+ # TODO(timurrrr): readlink -f is not present on Mac...
+ if [ "$PLATFORM" != "mac" ] && \
+ [ "$PLATFORM" != "mac_10.6" ] && \
+ [ "$PLATFORM" != "mac_10.7" ]
+ then
+ # Get rid of all "../" dirs
+ CHROME_VALGRIND=`readlink -f $CHROME_VALGRIND`
+ fi
+
+ if ! test -x $CHROME_VALGRIND/bin/valgrind
+ then
+ # We couldn't find the binaries in third_party/valgrind
+ CHROME_VALGRIND=""
+ fi
+ fi
+fi
+
+if ! test -x $CHROME_VALGRIND/bin/valgrind
+then
+ echo "Oops, could not find Valgrind binaries in your checkout." >&2
+ echo "Please see" >&2
+ echo " http://dev.chromium.org/developers/how-tos/using-valgrind/get-valgrind" >&2
+ echo "for the instructions on how to download pre-built binaries." >&2
+ exit 1
+fi
+
+echo $CHROME_VALGRIND
diff --git a/chromium/tools/valgrind/memcheck/OWNERS b/chromium/tools/valgrind/memcheck/OWNERS
new file mode 100644
index 00000000000..72e8ffc0db8
--- /dev/null
+++ b/chromium/tools/valgrind/memcheck/OWNERS
@@ -0,0 +1 @@
+*
diff --git a/chromium/tools/valgrind/memcheck/PRESUBMIT.py b/chromium/tools/valgrind/memcheck/PRESUBMIT.py
new file mode 100644
index 00000000000..512da0b3467
--- /dev/null
+++ b/chromium/tools/valgrind/memcheck/PRESUBMIT.py
@@ -0,0 +1,81 @@
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into gcl.
+"""
+
+import re
+
+def CheckChange(input_api, output_api):
+ """Checks the memcheck suppressions files for bad data."""
+ sup_regex = re.compile('suppressions.*\.txt$')
+ suppressions = {}
+ errors = []
+ check_for_memcheck = False
+ # skip_next_line has 3 possible values:
+ # - False: don't skip the next line.
+ # - 'skip_suppression_name': the next line is a suppression name, skip.
+ # - 'skip_param': the next line is a system call parameter error, skip.
+ skip_next_line = False
+ for f in filter(lambda x: sup_regex.search(x.LocalPath()),
+ input_api.AffectedFiles()):
+ for line, line_num in zip(f.NewContents(),
+ xrange(1, len(f.NewContents()) + 1)):
+ line = line.lstrip()
+ if line.startswith('#') or not line:
+ continue
+
+ if skip_next_line:
+ if skip_next_line == 'skip_suppression_name':
+ if 'insert_a_suppression_name_here' in line:
+ errors.append('"insert_a_suppression_name_here" is not a valid '
+ 'suppression name')
+ if suppressions.has_key(line):
+ if f.LocalPath() == suppressions[line][1]:
+ errors.append('suppression with name "%s" at %s line %s '
+ 'has already been defined at line %s' %
+ (line, f.LocalPath(), line_num,
+ suppressions[line][1]))
+ else:
+ errors.append('suppression with name "%s" at %s line %s '
+ 'has already been defined at %s line %s' %
+ (line, f.LocalPath(), line_num,
+ suppressions[line][0], suppressions[line][1]))
+ else:
+ suppressions[line] = (f, line_num)
+ check_for_memcheck = True;
+ skip_next_line = False
+ continue
+ if check_for_memcheck:
+ if not line.startswith('Memcheck:'):
+ errors.append('"%s" should be "Memcheck:..." in %s line %s' %
+ (line, f.LocalPath(), line_num))
+ check_for_memcheck = False;
+ if line == '{':
+ skip_next_line = 'skip_suppression_name'
+ continue
+ if line == "Memcheck:Param":
+ skip_next_line = 'skip_param'
+ continue
+
+ if (line.startswith('fun:') or line.startswith('obj:') or
+ line.startswith('Memcheck:') or line == '}' or
+ line == '...'):
+ continue
+ errors.append('"%s" is probably wrong: %s line %s' % (line, f.LocalPath(),
+ line_num))
+ if errors:
+ return [output_api.PresubmitError('\n'.join(errors))]
+ return []
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+def GetPreferredTrySlaves():
+ return ['linux_valgrind', 'mac_valgrind']
diff --git a/chromium/tools/valgrind/memcheck/suppressions.txt b/chromium/tools/valgrind/memcheck/suppressions.txt
new file mode 100644
index 00000000000..b68046922e8
--- /dev/null
+++ b/chromium/tools/valgrind/memcheck/suppressions.txt
@@ -0,0 +1,7231 @@
+# There are four kinds of suppressions in this file.
+# 1. third party stuff we have no control over
+#
+# 2. intentional unit test errors, or stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing
+#
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system (but a few aren't yet).
+# Periodically we should sweep this file and the bug tracker clean by
+# running overnight and removing outdated bugs/suppressions.
+#-----------------------------------------------------------------------
+
+# 1. third party stuff we have no control over
+{
+ Uninitialized value in deflate (Third Party)
+ Memcheck:Uninitialized
+ ...
+ fun:MOZ_Z_deflate
+}
+{
+ #gtk developers don't like cleaning up one-time leaks. See http://mail.gnome.org/archives/gtk-devel-list/2004-April/msg00230.html
+ gtk_init_check leak (Third Party)
+ Memcheck:Leak
+ ...
+ fun:gtk_init_check
+}
+{
+ Fontconfig leak?
+ Memcheck:Leak
+ ...
+ fun:XML_ParseBuffer
+ fun:FcConfigParseAndLoad
+}
+{
+ bug_9245_FcConfigAppFontAddFile_leak
+ Memcheck:Leak
+ ...
+ fun:FcConfigAppFontAddFile
+}
+{
+ # See also http://www.gnome.org/~johan/gtk.suppression
+ # (which has a smattering of similar pango suppressions)
+ pango_font_leak_todo
+ Memcheck:Leak
+ ...
+ fun:FcFontRenderPrepare
+ obj:*
+ fun:pango_font_map_load_fontset
+}
+{
+ pango_font_leak_todo_2
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ fun:pango_script_get_sample_language
+ ...
+ fun:pango_font_get_metrics
+}
+{
+ pango_font_leak_todo_3
+ Memcheck:Leak
+ ...
+ fun:FcFontRenderPrepare
+ ...
+ fun:pango_itemize_with_base_dir
+}
+{
+ pango_font_leak_todo_4
+ Memcheck:Leak
+ ...
+ fun:FcFontRenderPrepare
+ ...
+ fun:pango_ot_buffer_output
+}
+{
+ pango_font_leak_todo_5
+ Memcheck:Leak
+ ...
+ fun:FcFontRenderPrepare
+ ...
+ fun:pango_context_get_metrics
+}
+{
+ pango_font_leak_todo_6
+ Memcheck:Leak
+ ...
+ fun:FcDefaultSubstitute
+ ...
+ fun:pango_itemize_with_base_dir
+}
+{
+ # Similar to fontconfig_bug_8428 below. Reported in
+ # https://bugs.freedesktop.org/show_bug.cgi?id=8215
+ fontconfig_bug_8215
+ Memcheck:Leak
+ fun:malloc
+ fun:FcPatternObjectInsertElt
+ fun:FcPatternObjectAddWithBinding
+}
+{
+ # Fontconfig leak, seen in shard 16 of 20 of ui_tests
+ # See https://bugs.freedesktop.org/show_bug.cgi?id=8428
+ # and http://www.gnome.org/~johan/gtk.suppression
+ fontconfig_bug_8428
+ Memcheck:Leak
+ ...
+ fun:realloc
+ fun:FcPatternObjectInsertElt
+ fun:FcPatternObjectAddWithBinding
+}
+{
+ # Another permutation of previous leak.
+ fontconfig_bug_8428_2
+ Memcheck:Leak
+ ...
+ fun:realloc
+ fun:FcPatternObjectInsertElt
+ fun:FcPatternObjectAdd
+}
+{
+ bug_18590 (Third Party)
+ Memcheck:Leak
+ ...
+ fun:malloc
+ fun:FcConfigValues
+ fun:FcConfigValues
+ ...
+ fun:FcConfigValues
+ fun:FcConfigValues
+}
+{
+ bug_18590a (Third Party)
+ Memcheck:Leak
+ fun:malloc
+ fun:FcConfigValues
+ fun:FcConfigSubstituteWithPat
+ fun:*SkFontConfigInterfaceDirect*match*
+}
+{
+ bug_46177_a (Third Party)
+ Memcheck:Leak
+ ...
+ fun:FcCharSetOperate
+ fun:FcFontSetSort
+ fun:FcFontSort
+ ...
+ fun:pango_layout_get_pixel_size
+}
+{
+ bug_46177_b (Third Party)
+ Memcheck:Leak
+ ...
+ fun:FcCharSetFindLeafCreate
+ fun:FcCharSetAddLeaf
+ fun:FcCharSetOperate
+ fun:FcFontSetSort
+ fun:FcFontSort
+ ...
+ fun:pango_layout_get_iter
+}
+{
+ bug_46177_c (Third Party)
+ Memcheck:Leak
+ ...
+ fun:FcCharSetFindLeafCreate
+ fun:FcCharSetAddLeaf
+ fun:FcCharSetOperate
+ fun:FcFontSetSort
+ fun:FcFontSort
+ ...
+ fun:pango_layout_line_get_extents
+}
+{
+ bug_46177_d (Third Party)
+ Memcheck:Leak
+ fun:malloc
+ fun:FcFontSetCreate
+ fun:FcFontSetSort
+ fun:FcFontSort
+}
+{
+ bug_46177_e (Third Party)
+ Memcheck:Leak
+ ...
+ fun:FcCharSetFindLeafCreate
+ fun:FcCharSetAddChar
+}
+{
+ bug_181572 (Skia -- global cache of typefaces)
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN10SkFontHost14CreateTypefaceEPK10SkTypefacePKcNS0_5StyleE
+ fun:_ZN10SkTypeface14CreateFromNameEPKcNS_5StyleE
+}
+{
+ dlopen invalid read, probably a bug in glibc. TODO(dkegel): file glibc bug
+ Memcheck:Uninitialized
+ ...
+ fun:dlopen@@GLIBC_2.1
+ fun:PR_LoadLibraryWithFlags
+}
+{
+ dlopen leak on error. See http://sourceware.org/bugzilla/show_bug.cgi?id=12878.
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ fun:dlopen@@GLIBC_2.1
+}
+{
+ glibc leak. See also http://sources.redhat.com/bugzilla/show_bug.cgi?id=2451
+ Memcheck:Leak
+ fun:malloc
+ fun:_dl_map_object_from_fd
+}
+{
+ Pure NSS leak, does not involve glibc. TODO(dkegel): track down and fix or file bug.
+ Memcheck:Leak
+ ...
+ fun:NSS_NoDB_Init
+}
+{
+ Another pure NSS leak, does not involve glibc. TODO(dkegel): track down and fix or file bug. Shows up under --show-reachable=yes.
+ Memcheck:Leak
+ ...
+ fun:SECMOD_LoadUserModule
+}
+{
+ Pure NSS leak, does not involve glibc.
+ Memcheck:Leak
+ ...
+ fun:SECMOD_AddNewModule
+}
+{
+ bug_12614 (Third Party)
+ Memcheck:Leak
+ fun:?alloc
+ ...
+ fun:PR_LoadLibraryWithFlags
+ ...
+ fun:SECMOD_LoadModule
+}
+{
+ NSS leak - https://bugzilla.mozilla.org/show_bug.cgi?id=762351 - fixed in NSS 3.13.6/3.14
+ Memcheck:Leak
+ ...
+ fun:PKIX_PL_Malloc
+ ...
+ fun:PKIX_PL_OID_Create
+ ...
+ fun:cert_PKIXMakeOIDList
+ fun:cert_pkixSetParam
+ fun:CERT_PKIXVerifyCert
+}
+{
+ libc_dynamiclinker_foo
+ Memcheck:Uninitialized
+ obj:/lib*/ld-2.*.so
+ obj:/lib*/ld-2.*.so
+}
+{
+ libc_dynamiclinker_bar
+ Memcheck:Unaddressable
+ obj:/lib*/ld-2.*.so
+ obj:/lib*/ld-2.*.so
+}
+{
+ libc_dynamiclinker_bar_2
+ Memcheck:Jump
+ obj:*
+ obj:/lib*/ld-2.*.so
+}
+{
+ FIXME epoll uninitialized data 1
+ Memcheck:Param
+ epoll_ctl(epfd)
+ fun:syscall
+ fun:event_add
+}
+{
+ FIXME epoll uninitialized data 2
+ Memcheck:Param
+ epoll_ctl(epfd)
+ fun:syscall
+ fun:event_del
+}
+{
+ FIXME epoll uninitialized data 3
+ Memcheck:Param
+ epoll_wait(epfd)
+ fun:syscall
+ fun:event_base_loop
+}
+{
+ # "The section of the SQLite library identified works exactly as it should."
+ # http://www.sqlite.org/cvstrac/tktview?tn=536,39
+ # http://www.sqlite.org/cvstrac/tktview?tn=694,39
+ # http://www.sqlite.org/cvstrac/tktview?tn=964,39
+ # This looks like a case where an entire page was allocated, the header and
+ # perhaps some data was written, but the entire buffer was not written to.
+ # The SQLite authors aren't very interested in adding code to clear buffers
+ # for no reason other than pleasing valgrind, but a patch might be accepted
+ # under a macro like SQLITE_SECURE_DELETE which could be construed to apply
+ # to cases like this. (Note that we compile with SQLITE_SECURE_DELETE.)
+ bug_20653a (Third Party)
+ Memcheck:Param
+ write(buf)
+ ...
+ fun:sqlite3OsWrite
+ fun:pager_write_pagelist
+}
+{
+ bug_20653b (Third Party)
+ Memcheck:Param
+ write(buf)
+ ...
+ fun:*Write
+ fun:sqlite3OsWrite
+ ...
+ fun:pager_write
+}
+{
+ # array of weak references freed but not processed?
+ bug_16576
+ Memcheck:Leak
+ ...
+ fun:g_object_weak_ref
+ fun:g_object_add_weak_pointer
+}
+{
+ # Totem plugin leaks when we load it.
+ bug_21326 (Third Party)
+ Memcheck:Leak
+ ...
+ fun:_ZN56webkit5npapi9PluginLib17ReadWebPluginInfoE*
+}
+{
+ # NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=518443
+ https://bugzilla.mozilla.org/show_bug.cgi?id=518443
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:PORT_ZAlloc_Util
+ fun:PORT_NewArena_Util
+ fun:PK11_ImportAndReturnPrivateKey
+}
+{
+ bug_23314 (Third Party)
+ Memcheck:Unaddressable
+ fun:sqlite3PcacheClearSyncFlags
+ fun:syncJournal
+ fun:sqlite3PagerCommitPhaseOne
+ fun:sqlite3BtreeCommitPhaseOne
+}
+{
+ bug_23314b (Third Party)
+ Memcheck:Unaddressable
+ fun:sqlite3PcacheClearSyncFlags
+ fun:syncJournal
+ fun:sqlite3PagerCommitPhaseOne
+ fun:sqlite3BtreeCommitPhaseOne
+}
+{
+ http://sources.redhat.com/bugzilla/show_bug.cgi?id=5171
+ Memcheck:Leak
+ fun:calloc
+ fun:allocate_dtv
+ fun:_dl_allocate_tls
+ fun:pthread_create@@GLIBC_2.1
+}
+{
+ bug_33394 (Third Party)
+ Memcheck:Leak
+ fun:calloc
+ fun:PR_Calloc
+ fun:PR_NewLock
+ fun:_PR_UnixInit
+ fun:_PR_ImplicitInitialization
+ ...
+ fun:_ZN4base14EnsureNSPRInitEv
+}
+{
+ bug_33394_b (Third Party)
+ Memcheck:Leak
+ fun:calloc
+ fun:PR_Calloc
+ fun:PR_NewMonitor
+ fun:_PR_UnixInit
+ fun:_PR_ImplicitInitialization
+ ...
+ fun:_ZN4base14EnsureNSPRInitEv
+}
+{
+ # Looks like a leak in gtk's code when loading the im context module.
+ bug_41231 (Third Party)
+ Memcheck:Leak
+ ...
+ fun:malloc
+ fun:g_malloc
+ fun:g_strdup
+ fun:gtk_im_multicontext_get_slave
+ fun:gtk_im_multicontext_set_client_window
+ fun:gtk_im_context_set_client_window
+}
+{
+ bug_51332a (Third Party)
+ Memcheck:Leak
+ ...
+ fun:PORT_NewArena_Util
+ fun:sec_pkcs7_create_content_info
+ fun:SEC_PKCS7CreateData
+ fun:sec_pkcs12_encoder_start_context
+ fun:SEC_PKCS12Encode
+}
+{
+ bug_51332b (Third Party)
+ Memcheck:Leak
+ ...
+ fun:PORT_ArenaZAlloc_Util
+ fun:sec_pkcs7_create_content_info
+ fun:SEC_PKCS7CreateData
+ fun:sec_pkcs12_encoder_start_context
+ fun:SEC_PKCS12Encode
+}
+{
+ bug_51332c (Third Party)
+ Memcheck:Leak
+ fun:calloc
+ fun:PORT_ZAlloc_Util
+ fun:PORT_NewArena_Util
+ fun:sec_pkcs7_create_content_info
+ fun:sec_pkcs12_encoder_start_context
+ fun:SEC_PKCS12Encode
+}
+{
+ bug_51330 (Third Party)
+ Memcheck:Leak
+ ...
+ fun:p12u_DigestOpen
+ ...
+ fun:SEC_PKCS12DecoderUpdate
+}
+{
+ bug_51328a (Third Party)
+ Memcheck:Leak
+ ...
+ fun:SEC_ASN1DecoderUpdate_Util
+ ...
+ fun:SEC_ASN1DecoderUpdate_Util
+ fun:SEC_PKCS7DecoderUpdate
+ ...
+ fun:SEC_ASN1DecoderUpdate_Util
+ fun:SEC_PKCS12DecoderUpdate
+}
+{
+ bug_51328b (Third Party)
+ Memcheck:Leak
+ ...
+ fun:SEC_PKCS7DecoderStart
+ ...
+ fun:SEC_ASN1DecoderUpdate_Util
+ fun:SEC_PKCS12DecoderUpdate
+}
+{
+ # See http://sourceware.org/bugzilla/show_bug.cgi?id=14015.
+ bug_51770 (Third Party)
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ fun:dlsym
+}
+{
+ bug_58730_strlen_addr8 (Third Party)
+ Memcheck:Unaddressable
+ fun:__strlen_sse2
+}
+{
+ bug_58730_strlen_cond (Third Party)
+ Memcheck:Uninitialized
+ fun:__strlen_sse2
+}
+{
+ bug_58730_strcmp_addr8 (Third Party)
+ Memcheck:Unaddressable
+ fun:__strcmp_ssse3
+}
+{
+ bug_58730_strcmp_cond (Third Party)
+ Memcheck:Uninitialized
+ fun:__strcmp_ssse3
+}
+{
+ bug_58730_strcmp_value8 (Third Party)
+ Memcheck:Uninitialized
+ fun:__strcmp_ssse3
+}
+{
+ bug_58730_strncmp_value8 (Third Party)
+ Memcheck:Uninitialized
+ fun:__strncmp_ssse3
+}
+{
+ bug_58730_memmove_value4 (Third Party)
+ Memcheck:Uninitialized
+ fun:__memmove_ssse3
+}
+{
+ bug_58730_memmove_cond (Third Party)
+ Memcheck:Uninitialized
+ fun:__memmove_ssse3
+}
+{
+ bug_58730_memcpy_value4 (Third Party)
+ Memcheck:Uninitialized
+ fun:__memcpy_ssse3
+}
+{
+ bug_58730_memcpy_addr8 (Third Party)
+ Memcheck:Unaddressable
+ fun:__memcpy_ssse3
+}
+{
+ bug_58730_memcpy_cond (Third Party)
+ Memcheck:Uninitialized
+ fun:__memcpy_ssse3
+}
+{
+ bug_58730_memmove_chk_cond (Third Party)
+ Memcheck:Uninitialized
+ fun:__memmove_chk_ssse3
+}
+{
+ bug_58730_libc.so_addr8 (Third Party)
+ Memcheck:Unaddressable
+ obj:/lib/libc-2.*.so
+}
+{
+ bug_58730_libc.so_cond (Third Party)
+ Memcheck:Uninitialized
+ obj:/lib/libc-2.*.so
+}
+{
+ bug_58730_libc.so_value8 (Third Party)
+ Memcheck:Uninitialized
+ obj:/lib/libc-2.11.1.so
+}
+# net::SniffXML() clearly tries to read < 8 bytes, but strncasecmp() reads 8.
+{
+ bug_58730_strncasecmp_uninit (Third Party)
+ Memcheck:Uninitialized
+ ...
+ fun:strncasecmp
+ fun:_ZN4base11strncasecmpEPKcS1_m
+ fun:_ZN3netL8SniffXMLEPKcmPbPSs
+}
+{
+ # I believe it's a bug in gtk+-2.12.x and should already be fixed in recent gtk.
+ bug_61685 (Third Party)
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:gtk_text_buffer_select_range
+ fun:*OmniboxViewGtk16SetSelectedRange*
+}
+{
+ bug_66941 (Third Party)
+ Memcheck:Leak
+ ...
+ fun:STAN_ChangeCertTrust
+ fun:CERT_ChangeCertTrust
+}
+{
+ leaks in bash
+ Memcheck:Leak
+ ...
+ obj:/bin/bash
+}
+{
+ bug_73000_fixed_upstream_in_gtk
+ Memcheck:Uninitialized
+ fun:clipboard_clipboard_buffer_received
+ ...
+ fun:gtk_text_view_key_press_event
+ fun:_ZN14OmniboxViewGtk14HandleKeyPressEP10_GtkWidgetP12_GdkEventKey
+}
+{
+ bug_76386a (Third Party)
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNSs4_Rep9_S_createE*RKSaIcE
+ ...
+ fun:_ZNSsC1*KS*
+}
+{
+ bug_76386b (Third Party)
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNSs4_Rep9_S_createE*RKSaIcE
+ fun:_ZNSs4_Rep8_M_cloneERKSaIcE*
+}
+{
+ bug_76386c (Third Party)
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNSs4_Rep9_S_createE*RKSaIcE
+ fun:_ZNSs9_M_mutateEjjj
+}
+{
+ bug_80378_fixed_upstream_for_next_gtk
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ ...
+ fun:gtk_window_group_list_windows
+ fun:_ZN8gtk_util*AppModal*
+}
+{
+ getpwuid_and_getgrouplist
+ Memcheck:Leak
+ fun:malloc
+ fun:nss_parse_service_list
+ fun:__nss_database_lookup
+ obj:*
+ ...
+ fun:get*
+}
+{
+ dbus_x64_leaks
+ Memcheck:Leak
+ ...
+ obj:/usr/bin/dbus-launch
+}
+{
+ pulseaudio: pa_set_env_and_record
+ Memcheck:Leak
+ fun:malloc
+ fun:realloc
+ fun:pa_xrealloc
+ fun:pa_sprintf_malloc
+ fun:pa_set_env
+ fun:pa_set_env_and_record
+ fun:main
+}
+
+# The following stack suppresses Memcheck false positives on NaCl browser_tests
+# See https://bugs.kde.org/show_bug.cgi?id=270709#c4 for possible reason
+{
+ bug_101755 valgrind_bitfields_false_positive
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN7WebCore13WidthIterator*
+ ...
+ fun:_ZNK7WebCore4Font*
+}
+
+# Invalid frees from exit() and accept().
+{
+ bug_108618 (Third party)
+ Memcheck:Free
+ fun:free
+ fun:__libc_freeres
+ fun:_vgnU_freeres
+}
+
+# XRandRInfo object seems to be leaking inside XRRFindDisplay. This happens the
+# first time it is called, no matter who the caller is. We have observed this
+# problem with both XRRSelectInput and XRRQueryExtension.
+{
+ bug_119677
+ Memcheck:Leak
+ fun:malloc
+ fun:XRRFindDisplay
+}
+{
+ Flash Player Leak
+ Memcheck:Leak
+ ...
+ obj:/usr/lib/flashplugin-installer/libflashplayer.so
+}
+{
+ Flash Player Unaddressable
+ Memcheck:Unaddressable
+ ...
+ obj:/usr/lib/flashplugin-installer/libflashplayer.so
+}
+{
+ Flash Player Uninitialized
+ Memcheck:Uninitialized
+ ...
+ obj:/usr/lib/flashplugin-installer/libflashplayer.so
+}
+{
+ Occasional leak inside setlocale()
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_nl_make_l10nflist
+ fun:_nl_find_locale
+ fun:setlocale
+ fun:_ZN12_GLOBAL__N_121ContentMainRunnerImpl10InitializeEiPPKcPN7content19ContentMainDelegateE
+ fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
+ fun:ChromeMain
+}
+{
+ Occasional leak inside gdk_init()
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_nl_find_domain
+ fun:__dcigettext
+ fun:gdk_screen_class_intern_init
+ fun:g_type_class_ref
+ fun:g_type_class_ref
+ fun:g_object_newv
+ fun:g_object_new
+ fun:_gdk_x11_screen_new
+ fun:gdk_display_open
+ fun:gdk_display_open_default_libgtk_only
+ fun:gdk_init_check
+ fun:gdk_init
+}
+{
+ bug_130770_a
+ Memcheck:Unaddressable
+ ...
+ fun:_mesa_glsl_compile_shader
+}
+{
+ bug_130770_b
+ Memcheck:Unaddressable
+ ...
+ fun:_mesa_glsl_link_shader
+}
+# leak in OSMesa used to run compositor_unittests in bots.
+{
+ bug_148477
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN3gfx9GLApiBase17glCompileShaderFnEj
+ fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl13compileShaderEj
+ fun:_ZN2cc18ProgramBindingBase10LoadShaderEPN6WebKit20WebGraphicsContext3DEjRKSs
+ fun:_ZN2cc18ProgramBindingBase4InitEPN6WebKit20WebGraphicsContext3DERKSsS5_
+}
+{
+ bug_148477_link
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN3gfx9GLApiBase15glLinkProgramFnEj
+ fun:_ZN6webkit3gpu33WebGraphicsContext3DInProcessImpl11linkProgramEj
+ fun:_ZN2cc18ProgramBindingBase4LinkEPN6WebKit20WebGraphicsContext3DE
+ fun:_ZN2cc14ProgramBindingINS_*
+}
+# bug_todo_getdelim, bug_todo_getdelim2 and bug_todo_grep used to happen on
+# Google Lucid workstations only.
+{
+ bug_todo_getdelim
+ Memcheck:Leak
+ fun:malloc
+ fun:getdelim
+ ...
+ fun:call_init
+ fun:_dl_init
+}
+{
+ bug_todo_getdelim2
+ Memcheck:Leak
+ fun:malloc
+ fun:getdelim
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+}
+{
+ bug_todo_grep
+ Memcheck:Leak
+ fun:malloc
+ obj:/bin/grep
+ obj:/bin/grep
+}
+{
+ Ubuntu_Precise_Fontconfig_Optimized_Code
+ Memcheck:Unaddressable
+ fun:FcConfigFileExists
+}
+{
+ Ubuntu_Precise_Itoa_Optimized_Code
+ Memcheck:Uninitialized
+ fun:_itoa_word
+ fun:vfprintf
+ fun:__vsnprintf_chk
+ fun:__snprintf_chk
+}
+{
+ Ubuntu_Precise_Wcscmp_Optimized_Code_In_Tests
+ Memcheck:Uninitialized
+ fun:wcscmp
+ fun:_ZN7testing8internal6String17WideCStringEqualsEPKwS3_
+}
+{
+ # Most plugins return a constant char * string, but this totem plugin
+ # uses printf and allocates one.
+ Ubuntu_Precise_totem_mime_desc_leak
+ Memcheck:Leak
+ fun:g_strdup_printf
+ obj:*/libtotem-cone-plugin.so
+ fun:_ZN6webkit5npapi9PluginLib17ReadWebPluginInfoERKN4base8FilePathEPNS_13WebPluginInfoE
+}
+{
+ glib/gthread malloc leak in component build
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:g_thread_proxy
+}
+{
+ glib/gthread calloc leak in component build
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:g_thread_proxy
+}
+
+#-----------------------------------------------------------------------
+# 2. intentional unit test errors, or stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing
+
+# See tools/valgrind/memcheck_analyze.py before modifying sanity tests.
+{
+ Memcheck sanity test 01 (memory leak).
+ Memcheck:Leak
+ fun:_Zna*
+ fun:_ZN4base31ToolsSanityTest_MemoryLeak_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 02 (malloc/read left).
+ Memcheck:Unaddressable
+ fun:*ReadValueOutOfArrayBoundsLeft*
+ ...
+ fun:_ZN4base43ToolsSanityTest_AccessesToMallocMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 03 (malloc/read right).
+ Memcheck:Unaddressable
+ fun:*ReadValueOutOfArrayBoundsRight*
+ ...
+ fun:_ZN4base43ToolsSanityTest_AccessesToMallocMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 04 (malloc/write left).
+ Memcheck:Unaddressable
+ fun:*WriteValueOutOfArrayBoundsLeft*
+ ...
+ fun:_ZN4base43ToolsSanityTest_AccessesToMallocMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 05 (malloc/write right).
+ Memcheck:Unaddressable
+ fun:*WriteValueOutOfArrayBoundsRight*
+ ...
+ fun:_ZN4base43ToolsSanityTest_AccessesToMallocMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 06 (new/read left).
+ Memcheck:Unaddressable
+ fun:*ReadValueOutOfArrayBoundsLeft*
+ ...
+ fun:_ZN4base40ToolsSanityTest_AccessesToNewMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 07 (new/read right).
+ Memcheck:Unaddressable
+ fun:*ReadValueOutOfArrayBoundsRight*
+ ...
+ fun:_ZN4base40ToolsSanityTest_AccessesToNewMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 08 (new/write left).
+ Memcheck:Unaddressable
+ fun:*WriteValueOutOfArrayBoundsLeft*
+ ...
+ fun:_ZN4base40ToolsSanityTest_AccessesToNewMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 09 (new/write right).
+ Memcheck:Unaddressable
+ fun:*WriteValueOutOfArrayBoundsRight*
+ ...
+ fun:_ZN4base40ToolsSanityTest_AccessesToNewMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 10 (write after free).
+ Memcheck:Unaddressable
+ fun:_ZN4base43ToolsSanityTest_AccessesToMallocMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 11 (write after delete).
+ Memcheck:Unaddressable
+ fun:_ZN4base40ToolsSanityTest_AccessesToNewMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 12 (array deleted without []).
+ Memcheck:Free
+ ...
+ fun:_ZN4base46ToolsSanityTest_ArrayDeletedWithoutBraces_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 13 (single element deleted with []).
+ Memcheck:Free
+ ...
+ fun:_ZN4base51ToolsSanityTest_SingleElementDeletedWithBraces_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 14 (malloc/read uninit).
+ Memcheck:Uninitialized
+ fun:*ReadUninitializedValue*
+ ...
+ fun:_ZN4base43ToolsSanityTest_AccessesToMallocMemory_Test8TestBodyEv
+}
+{
+ Memcheck sanity test 15 (new/read uninit).
+ Memcheck:Uninitialized
+ fun:*ReadUninitializedValue*
+ ...
+ fun:_ZN4base40ToolsSanityTest_AccessesToNewMemory_Test8TestBodyEv
+}
+{
+ bug_86301 This test explicitly verifies PostTaskAndReply leaks the task if the originating MessageLoop has been deleted.
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_
+ fun:_ZN4base12_GLOBAL__N_169MessageLoopProxyTest_PostTaskAndReply_DeadReplyLoopDoesNotDelete_Test8TestBodyEv
+}
+{
+ logging::InitLogging never frees filename. It would be hard to free properly.
+ Memcheck:Leak
+ ...
+ fun:_ZN7logging11InitLoggingEPKcNS_18LoggingDestinationENS_15LogLockingStateENS_20OldFileDeletionStateE
+}
+{
+ Linux tests don't bother to undo net::SpawnedTestServer::LoadTestRootCert().
+ Memcheck:Leak
+ ...
+ fun:_ZN3net10SpawnedTestServer16LoadTestRootCertEv
+}
+{
+ # uitest's ResourceDispatcherTest.CrossSiteAfterCrash crashes on purpose
+ Intentional_crash
+ Memcheck:Unaddressable
+ fun:_ZN12AboutHandler10AboutCrashEv
+}
+{
+ Intentional_browser_test_crash
+ Memcheck:Unaddressable
+ fun:_ZL18CrashIntentionallyv
+ fun:_ZL19MaybeHandleDebugURLRK4GURL
+ fun:_ZN14RenderViewImpl10OnNavigateERK23ViewMsg_Navigate_Params
+}
+{
+ # Non-joinable thread doesn't clean up all state on program exit
+ # very common in ui tests
+ bug_16096 (WontFix)
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNSs4_Rep9_S_createE*RKSaIcE
+ fun:_ZNSs4_Rep8_M_cloneERKSaIcE*
+ fun:_ZNSs7reserveE*
+ fun:_ZNSs6appendEPKc*
+ fun:*StringAppendV*
+ ...
+ fun:_ZN4base12StringPrintfEPKcz
+}
+{
+ # According to dglazkov, these are one-time leaks and intentional.
+ # They may go away if the change to move these off the heap lands.
+ bug_17996 (Intentional)
+ Memcheck:Leak
+ ...
+ fun:_ZN7WebCore8SVGNames4initEv
+}
+{
+ intentional_BrowserThreadTest_NotReleasedIfTargetThreadNonExistent_Test_leak
+ Memcheck:Leak
+ fun:_Znw*
+ fun:*BrowserThreadTest_NotReleasedIfTargetThreadNonExistent_Test8TestBodyEv
+}
+{
+ # This is an on demand initialization which is done and then intentionally
+ # kept around (not freed) while the process is running.
+ intentional_WebCore_XMLNames_init_leak
+ Memcheck:Leak
+ ...
+ fun:_ZN7WebCore8XMLNames4initEv
+}
+{
+ # This is WebKit wide theading initialization which is intentionally kept
+ # around (not freed) while the process is running.
+ intentional_WTF_ThreadIdentifierData_initialize_leak
+ Memcheck:Leak
+ ...
+ fun:_ZN3WTF20ThreadIdentifierData10initializeEj
+}
+{
+ # This is WebKit wide theading initialization which is intentionally kept
+ # around (not freed) while the process is running.
+ intentional_WTF_wtfThreadData_leak
+ Memcheck:Leak
+ ...
+ fun:_ZN3WTF13wtfThreadDataEv
+}
+{
+ # Intentional crash test
+ intentional_RendererCrashTest
+ Memcheck:Unaddressable
+ fun:_Z*33HandleRendererErrorTestParametersRK11CommandLine
+ fun:_Z12RendererMainRKN7content18MainFunctionParams*
+}
+{
+ # PR_GetCurrentThread allocates a PRThread structure and stores it in
+ # thread-specific data. The PRThread structure is freed by the
+ # PR_DetachThread call in CertVerifierWorker::Run or when the thread
+ # terminates. Since we do not shut down worker threads, the PRThread
+ # structure created for a worker thread may be leaked at Chrome shutdown
+ # if the worker thread did not make it to the PR_DetachThread call.
+ bug_32624 (Intentional)
+ Memcheck:Leak
+ fun:calloc
+ fun:PR_Calloc
+ fun:PR_GetCurrentThread
+ ...
+ fun:_ZNK3net15X509Certificate14VerifyInternalERKSsiPNS_16CertVerifyResultE
+ fun:_ZNK3net15X509Certificate6VerifyERKSsiPNS_16CertVerifyResultE
+ fun:_ZN3net18CertVerifierWorker3RunEv
+}
+{
+ # Intentionally leaking NSS to prevent shutdown crashes
+ bug_61585a (Intentional)
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:error_get_my_stack
+}
+{
+ FileStream::Context can leak through WorkerPool by design
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net10FileStreamC1EPNS_6NetLogE
+}
+{
+ Tasks posted to WorkerPool can leak by design
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10WorkerPool16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_b
+}
+{
+ bug_61585b (Intentional)
+ Memcheck:Leak
+ fun:malloc
+ fun:PL_ArenaAllocate
+ fun:PORT_ArenaAlloc*
+}
+{
+ # Histograms are used on un-joined threads, and can't be deleted atexit.
+ Histograms via FactoryGet including Linear Custom Boolean and Basic
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN4base*Histogram10FactoryGet*
+}
+{
+ # Histograms are used on un-joined threads, and can't be deleted atexit.
+ Histograms via FactoryGet including Stats for disk_cache
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN10disk_cache14StatsHistogram10FactoryGet*
+}
+{
+ Intentional leak for Histogram (in StatisticsRecorderTest, NotInitialized).
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base42StatisticsRecorderTest_NotInitialized_Test8TestBodyEv
+}
+{
+ Intentional leak for SampleMap (stores SparseHistogram counts).
+ Memcheck:Leak
+ ...
+ fun:_ZN4base9SampleMap10AccumulateEii
+ fun:_ZN4base15SparseHistogram3AddEi
+}
+{
+ Intentional leak for list<const BucketRanges*>(in StatisticsRecorderTest, RegisterBucketRanges).
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base18StatisticsRecorder31RegisterOrDeleteDuplicateRangesEPKNS_12BucketRangesE
+ fun:_ZN4base48StatisticsRecorderTest_RegisterBucketRanges_Test8TestBodyEv
+}
+{
+ # See http://code.google.com/p/chromium/issues/detail?id=70062#c8
+ bug_70062 (Intentional)
+ Memcheck:Leak
+ ...
+ fun:InitSessionCacheLocks
+ fun:initSessionCacheLocksLazily
+ ...
+ fun:ssl_InitSessionCacheLocks
+}
+{
+ bug_83345 (Needs_Annotation)
+ Memcheck:Leak
+ ...
+ fun:_ZN4base*23LeakyLazyInstanceTraits*NewEPv
+ fun:_ZN4base12LazyInstance*LeakyLazyInstanceTraits*PointerEv
+}
+{
+ bug_87500_a (Intentional)
+ Memcheck:Leak
+ ...
+ fun:_ZN10disk_cache9BackendIO23ExecuteBackendOperationEv
+ fun:_ZN10disk_cache9BackendIO16ExecuteOperationEv
+}
+{
+ bug_87500_b (Intentional)
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4Bind*TaskClosureAdapterEFvvEPS2_EENS_8internal20InvokerStorageHolderINS6_15InvokerStorage1IT_T0_EEEES9_RKSA_
+ fun:_ZN4base11MessageLoop15PostDelayedTaskERKN15tracked_objects8LocationEP4Taskx
+ fun:_ZN4base20MessageLoopProxyImpl14PostTaskHelperERKN15tracked_objects8LocationEP4Taskxb
+ fun:_ZN4base20MessageLoopProxyImpl8PostTaskERKN15tracked_objects8LocationEP4Task
+ fun:_ZN10disk_cache10InFlightIO12OnIOCompleteEPNS_12BackgroundIOE
+}
+{
+ bug_87500_c (Intentional)
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net9HttpCache*EntryERKSsPPNS0_11ActiveEntryEPNS0_11TransactionE
+ fun:_ZN3net9HttpCache11Transaction13Do*EntryEv
+ fun:_ZN3net9HttpCache11Transaction6DoLoopEi
+ fun:_ZN3net9HttpCache11Transaction12OnIOCompleteEi
+}
+{
+ Intentional, see http://codereview.chromium.org/7670025
+ Memcheck:Param
+ msync(start)
+ fun:msync$UNIX2003
+ fun:mach_override_ptr
+ fun:_ZN4base33EnableTerminationOnHeapCorruptionEv
+}
+{
+ # Intentional - data is stored in thread-local storage for an unjoined
+ # worker thread, and so can occasionally leak. See crbug.com/89553 for
+ # additional info
+ bug_89553
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12_GLOBAL__N_111DnsReloader11MaybeReloadEv
+}
+{
+ bug_79322 (Intentional)
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN4base*StatisticsRecorderTest_*_Test8TestBodyEv
+}
+{
+ # This test simulates a ppapi plugin that fails to decrement a reference
+ # count. In that case, the ppapi runtime will clean up its internal data
+ # structures, but intentionally does not delete the plugin object's
+ # desctructor, because we don't want them to have the opportunity to do
+ # anything at that part of shutdown.
+ bug_145710 (Intentional)
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12TestInstance27TestLeakedObjectDestructorsEv
+ fun:_ZN12TestInstance8RunTestsERKSs
+ fun:_ZN15TestingInstance12ExecuteTestsEi
+ fun:_ZN2pp25CompletionCallbackFactoryI15TestingInstanceNS_22ThreadSafeThreadTraitsEE11Dispatcher0IMS1_FviEEclEPS1_i
+ fun:_ZN2pp25CompletionCallbackFactoryI15TestingInstanceNS_22ThreadSafeThreadTraitsEE12CallbackDataINS3_11Dispatcher0IMS1_FviEEEE5ThunkEPvi
+}
+{
+ intentional_see_bug_156466
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3ash5ShellC1EPNS_13ShellDelegateE
+ fun:_ZN3ash5Shell14CreateInstanceEPNS_13ShellDelegateE
+}
+{
+ intentional OOM in layout test: fast/js/string-replacement-outofmemory.html
+ Memcheck:Unaddressable
+ fun:_ZN7WebCoreL28reportFatalErrorInMainThreadEPKcS1_
+ fun:_ZN2v88internal2V823FatalProcessOutOfMemoryEPKcb
+ ...
+ fun:_ZN7WebCore16HTMLScriptRunner36executePendingScriptAndDispatchEventERNS_13PendingScriptE
+}
+
+# http://crbug.com/269278 causes really widespread, flaky leaks in
+# value objects that own some memory. These suppressions will cover
+# all such objects, even though it's possible to get real leaks that
+# look the same way (e.g. by allocating such an object in an arena).
+{
+ bug_269278a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4Bind*Callback*BindState*
+}
+{
+ bug_269278b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocator*allocate*
+ fun:_ZNSt12_Vector_base*_M_allocate*
+}
+
+
+#-----------------------------------------------------------------------
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system (but a few aren't yet).
+
+{
+ # Chromium flakily leaks tasks at shutdown, see
+ # http://crbug.com/6532
+ # http://codereview.chromium.org/20067
+ # http://codereview.chromium.org/42083
+ # To reproduce, run ipc tests
+ # This is the -O0 case
+ # In Purify, they don't even try to free them anymore.
+ # For now, in Valgrind, we'll add suppressions to ignore these leaks.
+ bug_6532
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_Z17NewRunnableMethodIN3IPC12ChannelProxy7ContextEMS2_FvvEEP14CancelableTaskPT_T0_
+}
+{
+ # See http://crbug.com/6532
+ # This is the -O1 case
+ bug_6532b
+ Memcheck:Leak
+ ...
+ fun:_ZN3IPC12ChannelProxy7Context14OnChannelErrorEv
+ fun:_ZN3IPC7Channel11ChannelImpl28OnFileCanReadWithoutBlockingEi
+}
+{
+ # webkit leak? See http://crbug.com/9503
+ bug_9503
+ Memcheck:Leak
+ ...
+ fun:_ZN19TestWebViewDelegate24UpdateSelectionClipboardEb
+}
+{
+ # very common in ui tests
+ bug_16091
+ Memcheck:Leak
+ ...
+ fun:_ZN4base11MessageLoop22AddDestructionObserverEPNS0_19DestructionObserverE
+ ...
+ fun:_ZN3IPC11SyncChannel11SyncContext15OnChannelOpenedEv
+}
+{
+ # very common in ui tests
+ bug_16092
+ Memcheck:Leak
+ fun:*
+ fun:_ZN4base11MessageLoopC1ENS0_4TypeE
+ fun:_ZN4base6Thread10ThreadMainEv
+}
+{
+ # very common in ui tests
+ bug_16092b
+ Memcheck:Leak
+ ...
+ fun:_ZNSt11_Deque_baseIN4base11PendingTaskESaIS1_EE17_M_initialize_mapE*
+ ...
+ fun:_ZN4base11MessageLoopC1ENS0_4TypeE
+}
+{
+ # very common in ui tests
+ bug_16092c
+ Memcheck:Leak
+ ...
+ fun:_ZNSt14priority_queueIN11MessageLoop11PendingTaskESt6vectorIS1_SaIS1_EESt4lessIS1_EEC1ERKS6_RKS4_
+ fun:_ZN4base11MessageLoopC1ENS0_4TypeE
+ fun:_ZN4base6Thread10ThreadMainEv
+}
+{
+ # very common in ui tests, also seen in Linux Reliability
+ bug_16093
+ Memcheck:Leak
+ ...
+ fun:getaddrinfo
+}
+{
+ # very common in ui tests, also seen in Linux Reliability
+ bug_16095
+ Memcheck:Leak
+ ...
+ fun:_ZN4base11MessageLoop21AddToDelayedWorkQueueERKN*PendingTaskE
+ fun:_ZN4base11MessageLoop6DoWorkEv
+}
+{
+ bug_16128
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3IPC11SyncChannelC1E*
+ ...
+ fun:_ZN7content11ChildThread4InitEv
+}
+{
+ bug_16326
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN11webkit_glue16WebURLLoaderImplC1Ev
+ fun:_ZN11webkit_glue16WebKitClientImpl15createURLLoaderEv
+ fun:_ZN7WebCore22ResourceHandleInternal5startEv
+}
+{
+ bug_17291
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocE*
+ ...
+ fun:_ZN2v88internal8JSObject23SetPropertyWithCallbackEPNS0_6ObjectEPNS0_6StringES3_PS1_
+}
+{
+ # also bug 17979. It's a nest of leaks.
+ bug_17385
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3IPC12ChannelProxy7Context13CreateChannelERKSsRKNS_7Channel4ModeE
+ fun:_ZN3IPC12ChannelProxy4InitERKSsNS_7Channel4ModeEP11MessageLoopb
+ fun:_ZN3IPC12ChannelProxyC2ERKSsNS_7Channel4ModeEP11MessageLoopPNS0_7ContextEb
+ ...
+ fun:_ZN3IPC11SyncChannelC1ERKSsNS_7Channel4ModeEPNS3_8ListenerEPNS_12ChannelProxy13MessageFilterEP11MessageLoopbPN4base13WaitableEventE
+}
+{
+ bug_17540
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base19MessagePumpLibevent19WatchFileDescriptorEibNS0_4ModeEPNS0_21FileDescriptorWatcherEPNS0_7WatcherE
+ fun:_ZN4base16MessageLoopForIO19WatchFileDescriptorEibNS_4ModeEPN4base19MessagePumpLibevent21FileDescriptorWatcherEPNS2_7WatcherE
+ fun:_ZN3IPC7Channel11ChannelImpl7ConnectEv
+ fun:_ZN3IPC7Channel7ConnectEv
+ fun:_ZN3IPC12ChannelProxy7Context15OnChannelOpenedEv
+}
+{
+ bug_19196
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2v817RegisterExtensionEPNS_9ExtensionE
+ fun:_ZN7WebCore7V8Proxy23registerExtensionWithV8EPN2v89ExtensionE
+ fun:_ZN7WebCore7V8Proxy17registerExtensionEPN2v89ExtensionEi
+ fun:_ZN6WebKit17registerExtensionEPN2v89ExtensionEi
+ fun:_ZN12RenderThread23EnsureWebKitInitializedEv
+}
+{
+ bug_19371
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN4base13WaitableEvent7EnqueueEPNS0_6WaiterE
+ fun:_ZN4base13WaitableEvent9TimedWaitERKNS_9TimeDeltaE
+ fun:_ZN4base13WaitableEvent4WaitEv
+ fun:_ZN4base18MessagePumpDefault3RunEPNS_11MessagePump8DelegateE
+}
+{
+ # slight variant of the above
+ bug_19371a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN4base13WaitableEvent7EnqueueEPNS0_6WaiterE
+ fun:_ZN4base13WaitableEvent9TimedWaitERKNS_9TimeDeltaE
+ fun:_ZN4base18MessagePumpDefault3RunEPNS_11MessagePump8DelegateE
+}
+{
+ bug_19377
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:event_base_new
+ fun:_ZN4base19MessagePumpLibeventC1Ev
+ fun:_ZN4base11MessageLoopC1ENS0_4TypeE
+ fun:_ZN4base6Thread10ThreadMainEv
+}
+{
+ bug_19463
+ Memcheck:Leak
+ ...
+ fun:_ZN4base19MessagePumpLibevent4InitEv
+ fun:_ZN4base19MessagePumpLibeventC1Ev
+ fun:_ZN4base11MessageLoopC1ENS0_4TypeE
+}
+{
+ bug_19775_a
+ Memcheck:Leak
+ ...
+ fun:malloc
+ fun:sqlite3MemMalloc
+ fun:mallocWithAlarm
+ fun:sqlite3Malloc
+ ...
+ fun:sqlite3VdbeExec
+ fun:sqlite3Step
+ fun:sqlite3_step
+ fun:sqlite3_exec
+ fun:_ZN3sql10Connection7Execute*
+ ...
+ fun:_ZN7history*Database*Create*
+}
+{
+ bug_19775_c
+ Memcheck:Leak
+ ...
+ fun:openDatabase
+ fun:sqlite3_open
+ fun:_ZN3sql10Connection12OpenInternalERKSs
+}
+{
+ bug_19775_g
+ Memcheck:Leak
+ fun:malloc
+ fun:sqlite3MemMalloc
+ fun:mallocWithAlarm
+ fun:sqlite3Malloc
+ fun:sqlite3ParserAlloc
+ fun:sqlite3RunParser
+ fun:sqlite3Prepare
+ fun:sqlite3LockAndPrepare
+ fun:sqlite3_prepare*
+}
+{
+ bug_19775_h
+ Memcheck:Leak
+ ...
+ fun:malloc
+ fun:sqlite3MemMalloc
+ fun:mallocWithAlarm
+ fun:sqlite3Malloc
+ ...
+ fun:yy_reduce
+}
+# IPCing uninitialized data
+{
+ bug_20997_a
+ Memcheck:Param
+ socketcall.sendmsg(msg.msg_iov[i])
+ fun:sendmsg*
+ fun:_ZN3IPC7Channel11ChannelImpl4SendEPNS_7MessageE
+}
+{
+ bug_20997_b
+ Memcheck:Param
+ socketcall.sendmsg(msg.msg_iov[i])
+ fun:sendmsg$UNIX2003
+ ...
+ fun:_ZN4base19MessagePumpLibevent21FileDescriptorWatcher28OnFileCanReadWithoutBlockingEiPS0_
+ ...
+ fun:event_process_active
+ fun:event_base_loop
+}
+{
+ bug_22098
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base19MessagePumpLibevent19WatchFileDescriptorEibNS0_4ModeEPNS0_21FileDescriptorWatcherEPNS0_7WatcherE
+ fun:_ZN4base16MessageLoopForIO19WatchFileDescriptorEibNS_4ModeEPN4base19MessagePumpLibevent21FileDescriptorWatcherEPNS2_7WatcherE
+ fun:_ZN3IPC7Channel11ChannelImpl23ProcessOutgoingMessagesEv
+ fun:_ZN3IPC7Channel11ChannelImpl4SendEPNS_7MessageE
+ fun:_ZN3IPC7Channel4SendEPNS_7MessageE
+ fun:_ZN3IPC12ChannelProxy7Context13OnSendMessageEPNS_7MessageE
+ fun:_ZN3IPC8SendTask3RunEv
+}
+{
+ bug_22923
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN13WorkerService12CreateWorker*
+ fun:_ZN19RenderMessageFilter14OnCreateWorker*
+}
+{
+ bug_27665
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN10SkXfermode6CreateENS_4ModeE
+ fun:_ZN7SkPaint15setXfermodeModeEN10SkXfermode4ModeE
+ fun:_ZNK7WebCore19PlatformContextSkia16setupPaintCommonEP7SkPaint
+ fun:_ZN7WebCore15GraphicsContext8fillRectERKNS_9FloatRectERKNS_5ColorENS_10ColorSpaceE
+ fun:_ZN7WebCore15GraphicsContext8fillRectERKNS_9FloatRectERKNS_5ColorENS_10ColorSpaceENS_17CompositeOperatorE
+}
+# The following three suppressions are related to the workers code.
+{
+ bug_27837
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN19WebSharedWorkerStub9OnConnectEii
+}
+{
+ bug_27838
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEj
+ fun:_ZN3WTF13FastAllocBasenwEj
+ fun:_ZN7WebCore18MessagePortChannel6createEN3WTF10PassRefPtrINS_26PlatformMessagePortChannelEEE
+ fun:_ZN6WebKit19WebSharedWorkerImpl7connectEPNS_21WebMessagePortChannelEPNS_15WebSharedWorker15ConnectListenerE
+ fun:_ZN19WebSharedWorkerStub9OnConnectEii
+}
+{
+ bug_28200
+ Memcheck:Leak
+ fun:malloc
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEj
+ fun:_ZN3WTF13FastAllocBasenwEj
+ fun:_ZN7WebCore18MessagePortChannel6createEN3WTF10PassRefPtrINS_26PlatformMessagePortChannelEEE
+ fun:_ZN6WebKit19WebSharedWorkerImpl7connectEPNS_21WebMessagePortChannelEPNS_15WebSharedWorker15ConnectListenerE
+ fun:_ZN19WebSharedWorkerStub9OnConnectEii
+}
+{
+ # GTK tooltip doesn't always initialize variables.
+ # https://bugzilla.gnome.org/show_bug.cgi?id=554686
+ tooltip_554686
+ Memcheck:Uninitialized
+ fun:child_location_foreach
+ fun:gtk_fixed_forall
+ ...
+ fun:find_widget_under_pointer
+ fun:gtk_tooltip_show_tooltip
+ fun:tooltip_popup_timeout
+ fun:gdk_threads_dispatch
+ fun:g_timeout_dispatch
+}
+{
+ bug_29675
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN27ChromeBrowserMainPartsPosix24PostMainMessageLoopStartEv
+ fun:_ZN7content15BrowserMainLoop20MainMessageLoopStartEv
+ fun:_ZN7content21BrowserMainRunnerImpl10InitializeERKNS_18MainFunctionParamsE
+ fun:_ZN7content11BrowserMainERKNS_18MainFunctionParamsE
+ fun:_ZN7content23RunNamedProcessTypeMainERKSsRKNS_18MainFunctionParamsEPNS_19ContentMainDelegateE
+ fun:_ZN7content21ContentMainRunnerImpl3RunEv
+ fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
+ fun:ChromeMain
+}
+{
+ bug_30346
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN13TCMallocGuardC1Ev
+ fun:_Z41__static_initialization_and_destruction_0ii
+ fun:_GLOBAL__I__ZN61FLAG__namespace_do_not_use_directly_use_DECLARE_int64_instead43FLAGS_tcmalloc_large_alloc_report_thresholdE
+}
+{
+ bug_30346b
+ Memcheck:Unaddressable
+ ...
+ fun:_ZSt22__get_temporary_bufferIPN7WebCore11RenderLayerEESt4pairIPT_iEiS5_
+ fun:_ZNSt17_Temporary_bufferIPPN7WebCore11RenderLayerES2_EC1ES3_S3_
+ fun:_ZN7WebCore11RenderLayer17updateZOrderListsEv
+ fun:_ZN7WebCore11RenderLayer24updateLayerListsIfNeededEv
+ fun:_ZN7WebCore11RenderLayer38updateCompositingAndLayerListsIfNeededEv
+}
+{
+ bug_30703a
+ Memcheck:Param
+ write(buf)
+ ...
+ fun:zipCloseFileInZipRaw
+ fun:zipCloseFileInZip
+ fun:_Z*13AddEntryToZip*
+}
+{
+ bug_30703b
+ Memcheck:Uninitialized
+ fun:deflate
+ ...
+ fun:zipCloseFileInZipRaw
+ fun:zipCloseFileInZip
+ fun:_Z*13AddEntryToZip*
+}
+{
+ bug_30704a
+ Memcheck:Uninitialized
+ fun:crc32
+ ...
+ fun:png_write_row
+}
+{
+ bug_30704b
+ Memcheck:Param
+ write(buf)
+ ...
+ fun:_ZN26SandboxedUnpacker17RewriteImageFilesEv
+}
+{
+ bug_30704c
+ Memcheck:Param
+ write(buf)
+ ...
+ fun:_ZNK16BrowserThemePack11WriteToDiskE*
+}
+{
+ bug_30704d
+ Memcheck:Uninitialized
+ ...
+ fun:png_process_data
+ fun:_ZN7WebCore14PNGImageReader6decodeERKNS_12SharedBufferEb
+ fun:_ZN7WebCore15PNGImageDecoder6decodeEb
+ fun:_ZN7WebCore15PNGImageDecoder18frameBufferAtIndexEm
+}
+{
+ bug_30704e
+ Memcheck:Uninitialized
+ obj:*/libpng*
+ fun:png_write_row
+}
+{
+ bug_30704f
+ Memcheck:Uninitialized
+ ...
+ fun:wk_png_write_find_filter
+ fun:wk_png_write_row
+}
+{
+ bug_30704g
+ Memcheck:Param
+ write(buf)
+ obj:*libpthread*
+ fun:_ZN9file_util19WriteFileDescriptorE*
+ fun:_ZN9file_util9WriteFileE*
+ fun:*SaveScreenshotInternalE*4base8Callback*
+ fun:*SaveScreenshotE*4base8Callback*
+}
+{
+ bug_87232
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore12base64EncodeEPKcjRN3WTF6VectorIcLj0EEEb
+ fun:_ZN7WebCore12base64EncodeERKN3WTF6VectorIcLj0EEERS2_b
+ fun:_ZN7WebCore*14ImageToDataURL*SkBitmapEEN3WTF6StringERT_*
+}
+{
+ bug_31985
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net16HttpNetworkLayer10GetSessionEv
+ fun:_ZN3net16HttpNetworkLayer17CreateTransactionEP10scoped_ptrINS_15HttpTransactionEE
+ fun:_ZN3net9HttpCache11Transaction13DoSendRequestEv
+ fun:_ZN3net9HttpCache11Transaction6DoLoopEi
+}
+{
+ bug_32085
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIN7content21NotificationRegistrar6RecordEE8allocate*
+ fun:_ZNSt12_Vector_baseIN7content21NotificationRegistrar6RecordESaIS*
+ fun:_ZNSt6vectorIN7content21NotificationRegistrar6RecordESaIS2_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS2_S*
+ fun:_ZNSt6vectorIN7content21NotificationRegistrar6RecordESaIS*
+ fun:_ZN7content21NotificationRegistrar3Add*
+}
+{
+ bug_32273_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3IPC12ChannelProxy4SendEPNS_7MessageE
+ fun:_ZN3IPC11SyncChannel15SendWithTimeoutEPNS_7MessageEi
+ fun:_ZN3IPC11SyncChannel4SendEPNS_7MessageE
+ fun:_ZN11ChildThread4SendEPN3IPC7MessageE
+ fun:_ZN12RenderThread4SendEPN3IPC7MessageE
+ fun:_ZN12RenderWidget4SendEPN3IPC7MessageE
+ fun:_ZN12RenderWidget16DoDeferredUpdateEv
+ fun:_ZN12RenderWidget20CallDoDeferredUpdateEv
+}
+{
+ bug_32273_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN24BrowserRenderProcessHost4SendEPN3IPC7MessageE
+ fun:_ZN16RenderWidgetHost4SendEPN3IPC7MessageE
+}
+{
+ bug_32623
+ Memcheck:Leak
+ ...
+ fun:ssl3_HandleHandshakeMessage
+ fun:ssl3_HandleHandshake
+ fun:ssl3_HandleRecord
+ fun:ssl3_GatherCompleteHandshake
+ fun:SSL_ForceHandshake
+ fun:_ZN3net18SSLClientSocketNSS4Core11DoHandshakeEv
+}
+{
+ bug_32624_b
+ Memcheck:Leak
+ fun:malloc
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ fun:secmod_ModuleInit
+}
+{
+ bug_32624_c
+ Memcheck:Leak
+ ...
+ fun:malloc
+ ...
+ fun:PORT_Alloc_Util
+ ...
+ fun:PK11_InitPin
+}
+{
+ bug_32624_f
+ Memcheck:Leak
+ ...
+ fun:CERT_PKIXVerifyCert
+ fun:_ZN3net12_GLOBAL__N_114PKIXVerifyCertE*
+}
+{
+ bug_32624_g
+ Memcheck:Leak
+ ...
+ fun:CERT_VerifySignedData
+ fun:cert_VerifyCertChain
+ fun:CERT_VerifyCertChain
+ fun:CERT_VerifyCert
+}
+{
+ bug_38138
+ Memcheck:Param
+ write(buf)
+ obj:*libpthread*
+ fun:_ZN3IPC7Channel11ChannelImpl23ProcessOutgoingMessagesEv
+ ...
+ fun:_ZN4base19MessagePumpLibevent3RunEPNS_11MessagePump8DelegateE
+ fun:_ZN4base11MessageLoop11RunInternalEv
+ fun:_ZN4base11MessageLoop10RunHandlerEv
+}
+{
+ bug_30633_39325
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN11ProfileImpl17GetRequestContextEv
+ fun:_ZN19SafeBrowsingService5StartEv
+ fun:_ZN19SafeBrowsingService10InitializeEv
+ fun:_ZN22ResourceDispatcherHost10InitializeEv
+ fun:_ZN18BrowserProcessImpl28CreateResourceDispatcherHostEv
+ fun:_ZN18BrowserProcessImpl24resource_dispatcher_hostEv
+ fun:_ZN16ExtensionService4InitEv
+}
+{
+ bug_42842
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN19TestWebViewDelegate12createWorkerEPN6WebKit8WebFrameEPNS0_15WebWorkerClientE
+ fun:_ZN6WebKit19WebWorkerClientImpl24createWorkerContextProxyEPN7WebCore6WorkerE
+ fun:_ZN7WebCore18WorkerContextProxy6createEPNS_6WorkerE
+ fun:_ZN7WebCore6WorkerC1EPNS_22ScriptExecutionContextE
+ fun:_ZN7WebCore6Worker6createERKN3WTF6StringEPNS_22ScriptExecutionContextERi
+ fun:_ZN7WebCore8V8Worker19constructorCallbackERKN2v89ArgumentsE
+}
+{
+ bug_42942_a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3sql10Connection18GetCachedStatementERKNS_11StatementIDEPKc
+ fun:_ZN3sql9MetaTable19PrepareGetStatementEPNS_9StatementEPKc
+ fun:_ZN3sql9MetaTable8GetValueEPKcPi
+ fun:_ZN3sql9MetaTable26GetCompatibleVersionNumberEv
+ ...
+ fun:_ZN3net13CookieMonster9InitStoreEv
+}
+{
+ bug_42942_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3sql10Connection18GetCachedStatementERKNS_11StatementIDEPKc
+ fun:_ZN3sql9MetaTable19PrepareSetStatementEPNS_9StatementEPKc
+ fun:_ZN3sql9MetaTable8SetValueEPKci
+ fun:_ZN3sql9MetaTable16SetVersionNumberEi
+ ...
+ fun:_ZN3net13CookieMonster9InitStoreEv
+}
+{
+ bug_42958_a
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_NPN_RegisterObject
+ fun:_ZN7WebCore16ScriptController20windowScriptNPObjectEv
+ fun:_ZNK6WebKit12WebFrameImpl12windowObjectEv
+ fun:_ZN6webkit5npapi13WebPluginImpl23GetWindowScriptNPObjectEv
+ fun:NPN_GetValue
+}
+{
+ bug_42958_b
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_NPN_RegisterObject
+ fun:_ZN7WebCore25createV8ObjectForNPObjectEP8NPObjectS1_
+ fun:_ZN7WebCore16ScriptController18bindToWindowObjectEPNS_5FrameERKN3WTF6StringEP8NPObject
+ fun:_ZN6WebKit12WebFrameImpl18bindToWindowObjectERKNS_9WebStringEP8NPObject
+ fun:_ZN13CppBoundClass16bindToJavascriptEPN6WebKit8WebFrameERKNS0_9WebStringE
+}
+{
+ bug_42958_c
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_NPN_RegisterObject
+ fun:_ZN7WebCore25createV8ObjectForNPObjectEP8NPObjectS1_
+ fun:_ZN7WebCore16ScriptController29createScriptInstanceForWidgetEPNS_6WidgetE
+ fun:_ZN*7WebCore17HTMLPlugInElement11getInstanceEv
+}
+{
+ bug_43471
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIPN4base11MessageLoop19DestructionObserverEE8allocateE*
+ fun:_ZNSt12_Vector_baseIPN4base11MessageLoop19DestructionObserverESaIS*
+ fun:_ZNSt6vectorIPN4base11MessageLoop19DestructionObserverESaIS*
+ fun:_ZNSt6vectorIPN4base11MessageLoop19DestructionObserverESaIS*
+ fun:_ZN16ObserverListBaseIN4base11MessageLoop19DestructionObserverEE11AddObserverEPS*
+ fun:_ZN4base11MessageLoop22AddDestructionObserverEPNS0_19DestructionObserverE
+}
+{
+ bug_46250
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIPN11MessageLoop12TaskObserverEE8allocateEjPKv
+ fun:_ZNSt12_Vector_baseIPN11MessageLoop12TaskObserverESaIS2_EE11_M_allocateEj
+ fun:_ZNSt6vectorIPN11MessageLoop12TaskObserverESaIS2_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS2_S4_EERKS2_
+ fun:_ZNSt6vectorIPN11MessageLoop12TaskObserverESaIS2_EE9push_backERKS2_
+ fun:_ZN16ObserverListBaseIN11MessageLoop12TaskObserverEE11AddObserverEPS1_
+ fun:_ZN4base11MessageLoop15AddTaskObserverEPNS_12TaskObserverE
+ fun:*IOJankObserver21AttachToCurrentThreadEv
+}
+{
+ bug_47950
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:*CreateSpdyHeadersFromHttpRequestERKN3net15HttpRequestInfoEPSt3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE
+}
+{
+ bug_49279_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:*ChromeCookieMonsterDelegateC1EP7Profile
+ fun:_ZN30ChromeURLRequestContextFactoryC2EP7Profile
+}
+{
+ bug_49279_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN29ChromeURLRequestContextGetter28CreateRequestContextForMediaE*
+ fun:_ZN29ChromeURLRequestContextGetter22CreateOriginalForMediaE*
+ fun:_ZN11ProfileImpl25GetRequestContextForMediaEv
+}
+{
+ bug_49279_c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:*ChromeCookieMonsterDelegateC2EP7Profile
+ fun:*ChromeCookieMonsterDelegateC1EP7Profile
+ fun:_ZN30ChromeURLRequestContextFactoryC2EP7Profile
+}
+{
+ bug_50304
+ Memcheck:Leak
+ ...
+ fun:_ZN7history14HistoryBackend8InitImpl*
+ fun:_ZN7history14HistoryBackend4Init*
+}
+{
+ bug_50936
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN23OffTheRecordProfileImpl4InitEv
+ fun:_ZN7Profile25CreateOffTheRecordProfileEv
+ fun:_ZN11ProfileImpl22GetOffTheRecordProfileEv
+}
+{
+ bug_50968_a
+ Memcheck:Leak
+ ...
+ fun:_ZN14WebDataService29InitializeDatabaseIfNecessaryEv
+}
+{
+ bug_50968_b
+ Memcheck:Unaddressable
+ ...
+ fun:_ZN14WebDataService29InitializeDatabaseIfNecessaryEv
+}
+{
+ bug_50968_d
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN14WebDataService29InitializeDatabaseIfNecessaryEv
+}
+{
+ bug_56359_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net9HttpCache24GetBackendForTransactionEPNS0_11TransactionE
+ fun:_ZN3net9HttpCache11Transaction12DoGetBackendEv
+ fun:_ZN3net9HttpCache11Transaction6DoLoopEi
+ fun:_ZN3net9HttpCache11Transaction5StartEPKNS_15HttpRequestInfoEP14CallbackRunnerI6Tuple1IiEERKNS_11BoundNetLogE
+ fun:_ZN17URLRequestHttpJob16StartTransactionEv
+ fun:_ZN17URLRequestHttpJob24OnCanGetCookiesCompletedEi
+ fun:_ZN17URLRequestHttpJob23AddCookieHeaderAndStartEv
+ fun:_ZN17URLRequestHttpJob5StartEv
+ fun:_ZN10URLRequest8StartJobEP13URLRequestJob
+ fun:_ZN10URLRequest5StartEv
+ fun:_ZN10URLFetcher4Core15StartURLRequestEv
+}
+{
+ bug_51153
+ Memcheck:Leak
+ ...
+ fun:_ZN7history14HistoryBackend16GetFaviconForURLE13scoped_refptrI17CancelableRequestI14CallbackRunnerI6Tuple5IibS1_I16RefCountedMemoryEb4GURLEEEERKS7_
+}
+{
+ bug_51379
+ Memcheck:Leak
+ fun:malloc
+ ...
+ obj:/usr/lib/libpangocairo-1.0.so.0.2002.3
+ ...
+ fun:_ZN3gfx10Canvas13DrawStringIntERKSbIwSt11char_traitsIwESaIwEERKNS_4FontERKjiiiii
+ fun:_ZN3gfx10Canvas13DrawStringIntERKSbIwSt11char_traitsIwESaIwEERKNS_4FontERKjiiii
+}
+{
+ bug_51590a
+ Memcheck:Unaddressable
+ ...
+ fun:_ZN7WebCore13TextRunWalker13nextScriptRunEv
+ fun:_ZN7WebCore13TextRunWalker14widthOfFullRunEv
+}
+{
+ bug_51590b
+ Memcheck:Unaddressable
+ ...
+ fun:_ZN7WebCore13TextRunWalker13nextScriptRunEv
+ fun:_ZN7WebCore13TextRunWalker14widthOfFullRunEv
+}
+{
+ bug_51590c
+ Memcheck:Unaddressable
+ ...
+ fun:_ZN7WebCore13TextRunWalker13nextScriptRunEv
+ fun:_ZN7WebCore13TextRunWalker14widthOfFullRunEv
+}
+{
+ bug_51679
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN23MessageService16AddEventListenerERKSsi
+ fun:_ZN24BrowserRenderProcessHost22OnExtensionAddListenerERKSs
+}
+{
+ bug_52831
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:*InotifyReaderTask3RunEv
+ ...
+ fun:_ZN4base11MessageLoop11RunInternalEv
+ fun:_ZN4base11MessageLoop10RunHandlerEv
+}
+{
+ bug_52837
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZNSt3map*FilePath*insert*
+ fun:_ZNSt3map*FilePath*ix*
+ fun:_ZN16ExtensionService15UnloadExtensionERKSs
+ fun:_ZN16ExtensionService18UninstallExtensionERKSsb
+ fun:_ZN18AutomationProvider18UninstallExtensionEiPb
+}
+{
+ bug_52957
+ Memcheck:Unaddressable
+ fun:glGetString
+ fun:_ZN18gpu_info_collector19CollectGraphicsInfoER7GPUInfo
+ fun:_ZN9GpuThread18OnEstablishChannelEi
+}
+{
+ bug_54308
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZNK8chromeos25CrosSettingsProviderProxy3GetERKSsPP5Value
+ fun:_ZNK8chromeos12CrosSettings3GetERKSsPP5Value
+ fun:_ZN8chromeos26CoreChromeOSOptionsHandler9FetchPrefERKSs
+ fun:_ZN18CoreOptionsHandler16HandleFetchPrefsEPK9ListValue
+}
+{
+ bug_55533
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN5IDMapIN3IPC7Channel8ListenerEL23IDMapOwnershipSemantics*
+ fun:_ZN17RenderProcessHost*Profile
+ fun:_ZN21MockRenderProcessHost*Profile
+}
+{
+ bug_56676
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIN4base15file_util_proxy5EntryEE8allocate*
+ fun:_ZNSt12_Vector_baseIN4base15file_util_proxy5EntryESaIS2_EE11_M_allocate*
+ fun:_ZNSt6vectorIN4base15file_util_proxy5EntryESaIS2_EE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKS2*
+ fun:_ZNSt6vectorIN4base15file_util_proxy5EntryESaIS2_EEaSERKS4_
+ fun:_ZN14MockDispatcher16DidReadDirectoryERKSt6vectorIN4base15file_util_proxy5EntryESaIS3_EEb
+ fun:_ZN7fileapi19FileSystemOperation16DidReadDirectoryEN4base17PlatformFileErrorERKSt6vectorINS1_15file_util_proxy5EntryESaIS5_EE
+}
+{
+ bug_58321
+ Memcheck:Unaddressable
+ fun:_ZNK3WTF6RefPtrIN7WebCore5FrameEE3getEv
+ fun:_ZN7WebCore14ResourceLoader18didReceiveResponseEPNS_14ResourceHandleERKNS_16ResourceResponseE
+ fun:_ZN7WebCore22ResourceHandleInternal18didReceiveResponseEPN6WebKit12WebURLLoaderERKNS1_14WebURLResponseE
+ fun:_ZN11webkit_glue16WebURLLoaderImpl7Context18OnReceivedResponseERKNS_20ResourceLoaderBridge12ResponseInfoEb
+ fun:_ZN85_GLOBAL__N_webkit_tools_test_shell_simple_resource_loader_bridge.cc_00000000_*12RequestProxy22NotifyReceivedResponseERKN11webkit_glue20ResourceLoaderBridge12ResponseInfoEb
+}
+{
+ bug_58340
+ Memcheck:Unaddressable
+ fun:_ZNK3WTF6RefPtrIN7WebCore5FrameEE3getEv
+ fun:_ZN7WebCore14ResourceLoader18didReceiveResponseEPNS_14ResourceHandleERKNS_16ResourceResponseE
+ fun:_ZN7WebCore22ResourceHandleInternal18didReceiveResponseEPN6WebKit12WebURLLoaderERKNS1_14WebURLResponseE
+ fun:_ZN11webkit_glue16WebURLLoaderImpl7Context18OnReceivedResponseERKNS_20ResourceResponseInfoEb
+}
+{
+ bug_58546
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN27SSLConfigServiceManagerPrefC1EP7Profile
+ fun:_ZN23SSLConfigServiceManager20CreateDefaultManagerEP7Profile
+ fun:_ZN11ProfileImplC1E*
+ fun:_ZN7Profile13CreateProfileE*
+ fun:_ZN14ProfileManager13CreateProfileE*
+ fun:_ZN14ProfileManager10GetProfileE*
+ fun:_ZN14ProfileManager17GetDefaultProfileE*
+ fun:_ZN14ProfileManager17GetDefaultProfileEv
+}
+{
+ bug_58561
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net8internal26ClientSocketPoolBaseHelper16GetOrCreateGroupERKSs
+ fun:_ZN3net8internal26ClientSocketPoolBaseHelper13RequestSocketERKSsPKNS1_7RequestE
+ fun:_ZN3net20ClientSocketPoolBaseINS_*
+ fun:_ZN3net*SocketPool13RequestSocketE*
+ fun:_ZN3net18ClientSocketHandle4InitINS_*
+ ...
+ fun:_ZN3net21HttpStreamFactoryImpl3Job16DoInitConnectionEv
+ fun:_ZN3net21HttpStreamFactoryImpl3Job6DoLoopEi
+}
+{
+ bug_58564
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:SSL_ImportFD
+ fun:_ZN3net18SSLClientSocketNSS20InitializeSSLOptionsEv
+ fun:_ZN3net18SSLClientSocketNSS7ConnectEP14CallbackRunnerI6Tuple1IiEE
+ fun:_ZN3net13SSLConnectJob12DoSSLConnectEv
+ fun:_ZN3net13SSLConnectJob6DoLoopEi
+}
+{
+ bug_58574
+ Memcheck:Unaddressable
+ ...
+ fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationERKN4base8CallbackIFvvEEE
+ fun:_ZN3net12CertVerifier7Request8DoVerifyEv
+}
+{
+ bug_60556a
+ Memcheck:Unaddressable
+ ...
+ fun:sqlite3_exec
+ fun:_ZN3sql10Connection7ExecuteEPKc
+ fun:_ZN11WebDatabase*
+}
+{
+ bug_60556b
+ Memcheck:Unaddressable
+ ...
+ fun:sqlite3_exec
+ fun:_ZN3sql10Connection7ExecuteEPKc
+ fun:_ZN11WebDatabase*
+}
+{
+ bug_60556c
+ Memcheck:Unaddressable
+ ...
+ fun:sqlite3_step
+ fun:_ZN3sql9Statement3RunEv
+ fun:_ZN3sql10Connection17CommitTransactionEv
+ fun:_ZN3sql11Transaction6CommitEv
+ fun:_ZN11WebDatabase*
+}
+{
+ bug_60556d
+ Memcheck:Unaddressable
+ ...
+ fun:sqlite3_step
+ fun:_ZN3sql9Statement3RunEv
+ fun:_ZN3sql10Connection17CommitTransactionEv
+ fun:_ZN3sql11Transaction6CommitEv
+ fun:_ZN11WebDatabase*
+}
+{
+ bug_60556e
+ Memcheck:Param
+ read(buf)
+ ...
+ fun:sqlite3_exec
+ fun:_ZN3sql10Connection7ExecuteEPKc
+ fun:_ZN11WebDatabase*
+}
+{
+ bug_60556f
+ Memcheck:Unaddressable
+ ...
+ fun:sqlite3_close
+ fun:_ZN3sql10Connection5CloseEv
+ fun:_ZN3sql10ConnectionD2Ev
+ fun:_ZN3sql10ConnectionD1Ev
+ fun:_ZN11WebDatabase*
+}
+{
+ bug_60556g
+ Memcheck:Unaddressable
+ ...
+ fun:sqlite3_step
+ fun:_ZN3sql9Statement4StepEv
+ fun:_ZN7history11URLDatabase12GetRowForURLERK4GURLPNS_6URLRowE
+ fun:_ZN7history14HistoryBackend12AddPageVisitERK4GURLN4base4TimeExjNS_11VisitSourceE
+}
+{
+ bug_60654
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore25GraphicsContext3DInternal7reshapeEii
+ fun:_ZN7WebCore17GraphicsContext3D7reshapeEii
+ fun:_ZN7WebCore21WebGLRenderingContextC1EPNS_17HTMLCanvasElementEN3WTF10PassRefPtrINS_17GraphicsContext3DEEE
+ fun:_ZN7WebCore21WebGLRenderingContext6createEPNS_17HTMLCanvasElementEPNS_22WebGLContextAttributesE
+ fun:_ZN7WebCore17HTMLCanvasElement10getContextERKN3WTF6StringEPNS_23CanvasContextAttributesE
+ ...
+ fun:_ZN2v88internal6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPPPS4_Pb
+}
+{
+ bug_60667c
+ Memcheck:Leak
+ ...
+ obj:*
+ fun:_ZN3gpu5gles216GLES2DecoderImpl15DoCompileShaderEj
+ fun:_ZN3gpu5gles216GLES2DecoderImpl19HandleCompileShaderEjRKNS0_13CompileShaderE
+ fun:_ZN3gpu5gles216GLES2DecoderImpl9DoCommandEjjPKv
+}
+{
+ bug_60668a
+ Memcheck:Uninitialized
+ ...
+ fun:_swrast_write_rgba_span
+ fun:general_triangle
+ fun:_swrast_validate_triangle
+ fun:_swrast_Triangle
+ fun:triangle_rgba
+ fun:_tnl_render_triangles_verts
+ fun:run_render
+ fun:_tnl_run_pipeline
+ fun:_tnl_draw_prims
+ fun:_tnl_vbo_draw_prims
+ fun:vbo_exec_DrawArrays
+ fun:neutral_DrawArrays
+ fun:glDrawArrays
+}
+{
+ bug_60668b
+ Memcheck:Overlap
+ fun:memcpy
+ fun:clip_span
+ fun:_swrast_write_rgba_span
+ fun:general_triangle
+ fun:_swrast_validate_triangle
+ fun:_swrast_Triangle
+ fun:triangle_rgba
+ fun:_tnl_render_poly_elts
+ fun:_tnl_RenderClippedPolygon
+ fun:clip_tri_4
+ fun:clip_elt_triangles
+ fun:run_render
+ fun:_tnl_run_pipeline
+ fun:_tnl_draw_prims
+ fun:_tnl_vbo_draw_prims
+ fun:vbo_validated_drawrangeelements
+ fun:vbo_exec_DrawElements
+ fun:neutral_DrawElements
+ fun:glDrawElements
+ fun:_ZN3gpu5gles216GLES2DecoderImpl14DoDrawElementsEbjijii
+ fun:_ZN3gpu5gles216GLES2DecoderImpl18HandleDrawElementsEjRKNS0_12DrawElementsE
+ fun:_ZN3gpu5gles216GLES2DecoderImpl9DoCommandEjjPKv
+}
+{
+ bug_60668c
+ Memcheck:Overlap
+ ...
+ fun:_swrast_write_rgba_span
+ fun:general_triangle
+ fun:_swrast_Triangle
+ fun:triangle_rgba
+ fun:_tnl_render_poly_elts
+ fun:_tnl_RenderClippedPolygon
+ fun:clip_tri_4
+ fun:clip_render_tri_fan_verts
+ fun:run_render
+ fun:_tnl_run_pipeline
+ fun:_tnl_draw_prims
+ fun:_tnl_vbo_draw_prims
+ fun:vbo_exec_DrawArrays
+ fun:neutral_DrawArrays
+ fun:glDrawArrays
+}
+{
+ bug_60670a
+ Memcheck:Unaddressable
+ fun:swizzle_copy
+ fun:_mesa_swizzle_ubyte_image
+ fun:_mesa_texstore_rgba8888
+ fun:_mesa_texstore
+ fun:_mesa_store_teximage2d
+ fun:_mesa_TexImage2D
+ fun:glTexImage2D
+ fun:_ZN6WebKit31WebGraphicsContext3DDefaultImpl10texImage2DEjjjjjjjjPKv
+ fun:_ZN7WebCore25GraphicsContext3DInternal10texImage2DEjjjjjjjjPv
+ fun:_ZN7WebCore17GraphicsContext3D10texImage2DEjjjjjjjjPv
+}
+{
+ bug_60670b
+ Memcheck:Unaddressable
+ fun:extract_float_rgba
+ fun:_mesa_unpack_color_span_chan
+ fun:_mesa_make_temp_chan_image
+ fun:_mesa_texstore_rgba8888
+ fun:_mesa_texstore
+ fun:_mesa_store_teximage2d
+ fun:_mesa_TexImage2D
+ fun:glTexImage2D
+ fun:_ZN6WebKit31WebGraphicsContext3DDefaultImpl10texImage2DEjjjjjjjjPKv
+ fun:_ZN7WebCore25GraphicsContext3DInternal10texImage2DEjjjjjjjjPv
+ fun:_ZN7WebCore17GraphicsContext3D10texImage2DEjjjjjjjjPv
+}
+{
+ bug_69073
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:sqlite3*
+ ...
+ fun:find_objects
+ fun:find_objects_by_template
+ fun:nssToken_FindCertificatesBySubject
+ fun:nssTrustDomain_FindCertificatesBySubject
+ fun:nssCertificate_BuildChain
+ fun:NSSCertificate_BuildChain
+}
+{
+ bug_61424
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN13FormStructure18EncodeQueryRequestERK12ScopedVectorIS_EPSt6vectorISsSaISsEEPSs
+ fun:*FormStructureTest_EncodeQueryRequest_Test8TestBodyEv
+}
+{
+ bug_61424_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN13FormStructure18EncodeQueryRequestERK12ScopedVectorIS_EPSt6vectorISsSaISsEEPSs
+ fun:_ZN12_GLOBAL__N_141FormStructureTest_EncodeQueryRequest_Test8TestBodyEv
+}
+{
+ bug_63671
+ Memcheck:Param
+ write(buf)
+ ...
+ fun:_ZN9file_util9WriteFileE*
+ fun:_Z24ConvertWebAppToExtensionRK18WebApplicationInfoRKN4base4TimeE
+ fun:_ZN30ExtensionFromWebApp_Basic_Test8TestBodyEv
+}
+{
+ bug_63671_b
+ Memcheck:Param
+ write(buf)
+ ...
+ fun:_ZN9file_util9WriteFileE*
+ fun:_ZN12_GLOBAL__N_110SaveBitmapEPSt6vectorIhSaIhEE*
+ fun:_ZN4base8internal15RunnableAdapterIPFvPSt6vectorIhSaIhEE*
+}
+{
+ bug_64804
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base16MessageLoopProxy22currentEv
+ ...
+ fun:_ZN10URLFetcher4CoreC1EPS_RK4GURLNS_11RequestTypeEPNS_8DelegateE
+ fun:_ZN10URLFetcherC*ERK4GURLNS_11RequestTypeEPNS_8DelegateE
+}
+{
+ bug_64887_a
+ Memcheck:Uninitialized
+ fun:_itoa_word
+ fun:vfprintf
+ fun:vsnprintf
+ fun:snprintf
+ fun:_ZN7testing*26PrintByteSegmentInObjectToEPKhmmPSo
+ fun:_ZN7testing*24PrintBytesInObjectToImplEPKhmPSo
+ fun:_ZN7testing9internal220PrintBytesInObjectToEPKhmPSo
+ fun:_ZN7testing9internal220TypeWithoutFormatterI*
+ fun:_ZN7testing9internal2lsIcSt11char_traitsIcE*
+ fun:_ZN16testing_internal26DefaultPrintNonContainerToI*
+ fun:_ZN7testing8internal14DefaultPrintToI*
+ fun:_ZN7testing8internal7PrintToI*
+ fun:_ZN7testing8internal16UniversalPrinterI*
+ fun:_ZN7testing8internal14UniversalPrintI*
+}
+{
+ bug_64887_b
+ Memcheck:Uninitialized
+ fun:_itoa_word
+ fun:vfprintf
+ fun:*vsnprintf*
+ fun:*snprintf*
+ fun:_ZN7testing*PrintByteSegmentInObjectTo*
+ fun:_ZN7testing*PrintBytesInObjectToImplEPKhjPSo
+ fun:_ZN7testing9internal220PrintBytesInObjectToEPKhjPSo
+ fun:_ZN7testing9internal220TypeWithoutFormatter*
+ fun:_ZN7testing9internal2lsIcSt11char_traitsIcE*
+ fun:_ZN16testing_internal26DefaultPrintNonContainerTo*
+ fun:_ZN7testing8internal14DefaultPrintToI*
+ fun:_ZN7testing8internal7PrintToI*
+ fun:_ZN7testing8internal16UniversalPrinterI*
+ fun:_ZN7testing8internal14UniversalPrintI*
+}
+{
+ bug_64887_c
+ Memcheck:Uninitialized
+ fun:_itoa_word
+ fun:vfprintf
+ fun:*vsnprintf*
+ fun:*snprintf*
+ fun:_ZN7testing*PrintByteSegmentInObjectTo*
+ fun:_ZN7testing*PrintBytesInObjectToImplEPKhjPSo
+ fun:_ZN7testing9internal220PrintBytesInObjectToEPKhjPSo
+ fun:_ZN7testing9internal220TypeWithoutFormatter*
+ fun:_ZN7testing9internal2lsIcSt11char_traitsIcE*
+ fun:_ZN16testing_internal26DefaultPrintNonContainerTo*
+ fun:_ZN7testing8internal14DefaultPrintToI*
+ fun:_ZN7testing8internal7PrintToI*
+ fun:_ZN7testing8internal16UniversalPrinterI*
+ fun:_ZN7testing8internal14UniversalPrintI*
+}
+{
+ bug_64887_d
+ Memcheck:Uninitialized
+ ...
+ fun:_ZNSolsEx
+ fun:_ZN7testing9internal220TypeWithoutFormatterIN5media7PreloadELNS0_8TypeKindE1EE10PrintValueERKS3_PSo
+ fun:_ZN7testing9internal2lsIcSt11char_traitsIcEN5media7PreloadEEERSt13basic_ostreamIT_T0_ESA_RKT1_
+ fun:_ZN16testing_internal26DefaultPrintNonContainerToIN5media7PreloadEEEvRKT_PSo
+ fun:_ZN7testing8internal14DefaultPrintToIN5media7PreloadEEEvcNS0_13bool_constantILb0EEERKT_PSo
+ fun:_ZN7testing8internal7PrintToIN5media7PreloadEEEvRKT_PSo
+ fun:_ZN7testing8internal16UniversalPrinterIN5media7PreloadEE5PrintERKS3_PSo
+ fun:_ZN7testing8internal18TuplePrefixPrinter*
+ fun:_ZN7testing8internal12PrintTupleToINSt3tr15tupleIN5media7PreloadENS2*
+ fun:_ZN7testing8internal7PrintToIN5media7PreloadEEEvRKNSt3tr15tupleIT*
+ fun:_ZN7testing8internal16UniversalPrinterINSt3tr15tupleIN5media7PreloadENS2*
+ fun:_ZN7testing8internal14UniversalPrintINSt3tr15tupleIN5media7PreloadENS2*
+ fun:_ZNK7testing8internal18FunctionMockerBaseIFvN5media7PreloadEEE32UntypedDescribeUninterestingCallEPKvPSo
+ fun:_ZN7testing8internal25UntypedFunctionMockerBase17UntypedInvokeWithEPKv
+ fun:_ZN7testing8internal18FunctionMockerBaseIFvN5media7PreloadEEE10InvokeWithERKNSt3tr15tupleIS3*
+ fun:_ZN7testing8internal14FunctionMockerIFvN5media7PreloadEEE6InvokeES3_
+ fun:_ZN5media11MockDemuxer10SetPreloadENS_7PreloadE
+}
+{
+ bug_64887_e
+ Memcheck:Uninitialized
+ ...
+ fun:_ZNSolsEx
+ fun:_ZN7testing9internal220TypeWithoutFormatterIN5media7PreloadELNS0_8TypeKindE1EE10PrintValueERKS3_PSo
+ fun:_ZN7testing9internal2lsIcSt11char_traitsIcEN5media7PreloadEEERSt13basic_ostreamIT_T0_ESA_RKT1_
+ fun:_ZN16testing_internal26DefaultPrintNonContainerToIN5media7PreloadEEEvRKT_PSo
+ fun:_ZN7testing8internal14DefaultPrintToIN5media7PreloadEEEvcNS0_13bool_constantILb0EEERKT_PSo
+ fun:_ZN7testing8internal7PrintToIN5media7PreloadEEEvRKT_PSo
+ fun:_ZN7testing8internal16UniversalPrinterIN5media7PreloadEE5PrintERKS3_PSo
+ fun:_ZN7testing8internal18TuplePrefixPrinter*
+ fun:_ZN7testing8internal12PrintTupleToINSt3tr15tupleIN5media7PreloadENS2*
+ fun:_ZN7testing8internal7PrintToIN5media7PreloadEEEvRKNSt3tr15tupleIT*
+ fun:_ZN7testing8internal16UniversalPrinterINSt3tr15tupleIN5media7PreloadENS2*
+ fun:_ZN7testing8internal14UniversalPrintINSt3tr15tupleIN5media7PreloadENS2*
+ fun:_ZNK7testing8internal18FunctionMockerBaseIFvN5media7PreloadEEE32UntypedDescribeUninterestingCallEPKvPSo
+ fun:_ZN7testing8internal25UntypedFunctionMockerBase17UntypedInvokeWithEPKv
+ fun:_ZN7testing8internal18FunctionMockerBaseIFvN5media7PreloadEEE10InvokeWithERKNSt3tr15tupleIS3*
+ fun:_ZN7testing8internal14FunctionMockerIFvN5media7PreloadEEE6InvokeES3_
+ fun:_ZN5media11MockDemuxer10SetPreloadENS_7PreloadE
+}
+{
+ bug_65940_a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3IPC12ChannelProxy7Context13CreateChannelERKNS_13ChannelHandleERKNS_7Channel4ModeE
+ fun:_ZN3IPC12ChannelProxy4InitERKNS_13ChannelHandleENS_7Channel4ModeEP11MessageLoopb
+ fun:_ZN3IPC12ChannelProxyC2ERKNS_13ChannelHandleENS_7Channel4ModeEP11MessageLoopPNS0_7ContextEb
+ fun:_ZN3IPC11SyncChannelC1ERKNS_13ChannelHandleENS_7Channel4ModeEPNS4_8ListenerEP11MessageLoopbPN4base13WaitableEventE
+}
+{
+ bug_65940_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3IPC11SyncChannelC1ERKNS_13ChannelHandleENS_7Channel4ModeEPNS_8ListenerEPN4base22SingleThreadTaskRunnerEbPNS8_13WaitableEventE
+ fun:_ZN7content11ChildThread4InitEv
+ fun:_ZN7content11ChildThreadC2ERKSs
+}
+{
+ bug_65940_c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorI13scoped_refptrIN3IPC12ChannelProxy13MessageFilterEEE8allocateEmPKv
+ fun:_ZNSt12_Vector_baseI13scoped_refptrIN3IPC12ChannelProxy13MessageFilterEESaIS4_EE11_M_allocateEm
+ fun:_ZNSt6vectorI13scoped_refptrIN3IPC12ChannelProxy13MessageFilterEESaIS4_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS4_S6_EERKS4_
+ fun:_ZNSt6vectorI13scoped_refptrIN3IPC12ChannelProxy13MessageFilterEESaIS4_EE9push_backERKS4_
+ fun:_ZN3IPC12ChannelProxy7Context11OnAddFilterEv
+}
+{
+ bug_65940_d
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content11ChildThread4InitEv
+ fun:_ZN7content11ChildThreadC*
+ ...
+ fun:_ZN7content21WebRTCAudioDeviceTest5SetUpEv
+}
+{
+ bug_65940_e
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content16RenderThreadImpl4InitEv
+ fun:_ZN7content16RenderThreadImplC*
+ ...
+ fun:_ZN7content21WebRTCAudioDeviceTest5SetUpEv
+}
+{
+ bug_66853_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11ProfileImpl14GetHostZoomMapEv
+ ...
+ fun:_ZNK17ProfileImplIOData6Handle27GetMainRequestContextGetterEv
+ fun:_ZN11ProfileImpl17GetRequestContextEv
+ fun:_ZN19SafeBrowsingService5StartEv
+ fun:_ZN19SafeBrowsingService10InitializeEv
+ fun:_ZN22ResourceDispatcherHost10InitializeEv
+ fun:_ZN18BrowserProcessImpl28CreateResourceDispatcherHostEv
+ fun:_ZN18BrowserProcessImpl24resource_dispatcher_hostEv
+ fun:_ZN16ExtensionService4InitEv
+ fun:_ZN11ProfileImpl14InitExtensionsE*
+ fun:_ZN14ProfileManager10AddProfileEP7Profileb
+}
+{
+ bug_67142
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN16ChildProcessHost13CreateChannelEv
+ fun:_ZN14GpuProcessHost4InitEv
+}
+{
+ bug_67261
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3sql10Connection18GetUniqueStatementEPKc
+ fun:_ZN3sql10Connection18GetCachedStatementERKNS_11StatementIDEPKc
+ fun:_ZN8appcache16AppCacheDatabase22PrepareCachedStatementERKN3sql11StatementIDEPKcPNS1_9StatementE
+}
+{
+ bug_67553
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZNSt3mapISs13scoped_refptrIK9ExtensionESt4lessISsESaISt4pairIKSsS3_EEEixERS7_
+ fun:_ZN16ExtensionInfoMap12AddExtensionEPK9Extension
+}
+{
+ bug_68069_a
+ Memcheck:Leak
+ fun:malloc
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ fun:_ZN3gfx20GetGLCoreProcAddressEPKc
+ fun:_ZN3gfx22InitializeGLBindingsGLEv
+ fun:_ZN3gfx20InitializeGLBindingsENS_16GLImplementationE
+ fun:_ZN3gfx9GLSurface16InitializeOneOffEv
+}
+{
+ bug_68069_b
+ Memcheck:Leak
+ fun:malloc
+ fun:XextCreateExtension
+ ...
+ fun:_ZN3gfx12GLSurfaceGLX16InitializeOneOffEv
+ fun:_ZN3gfx9GLSurface24InitializeOneOffInternalEv
+ fun:_ZN3gfx9GLSurface16InitializeOneOffEv
+}
+{
+ bug_68553
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net25DiskCacheBasedSSLHostInfoC1ERKSsRKNS_9SSLConfigEPNS_12CertVerifierEPNS_9HttpCacheE
+ fun:_ZN3net9HttpCache25SSLHostInfoFactoryAdaptor10GetForHostERKSsRKNS_9SSLConfigE
+ fun:_ZN3net13SSLConnectJob12DoTCPConnectEv
+ fun:_ZN3net13SSLConnectJob6DoLoopEi
+ fun:_ZN3net13SSLConnectJob15ConnectInternalEv
+ fun:_ZN3net10ConnectJob7ConnectEv
+ fun:_ZN3net8internal26ClientSocketPoolBaseHelper21RequestSocketInternalERKSsPKNS1_7RequestE
+ fun:_ZN3net8internal26ClientSocketPoolBaseHelper13RequestSocketERKSsPKNS1_7RequestE
+ fun:_ZN3net20ClientSocketPoolBaseINS_15SSLSocketParamsEE13RequestSocketERKSsRK13scoped_refptrIS1_ENS_15RequestPriorityEPNS_18ClientSocketHandleEP14CallbackRunnerI6Tuple1IiEERKNS_11BoundNetLogE
+ fun:_ZN3net19SSLClientSocketPool13RequestSocketERKSsPKvNS_15RequestPriorityEPNS_18ClientSocketHandleEP14CallbackRunnerI6Tuple1IiEERKNS_11BoundNetLogE
+ fun:_ZN3net18ClientSocketHandle4InitINS_15SSLSocketParamsENS_19SSLClientSocketPoolEEEiRKSsRK13scoped_refptrIT_ENS_15RequestPriorityEP14CallbackRunnerI6Tuple1IiEEPT0_RKNS_11BoundNetLogE
+}
+{
+ Bug_69919
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN3gfx15OSMesaGLContext10InitializeEjPNS_9GLContextE
+ fun:_ZN3gfx9GLContext24CreateOffscreenGLContextEPS0_
+ fun:*InitializeGLContextEv
+}
+{
+ Bug_69934_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN*NPObjectProxy10NPAllocateEP4_NPPP7NPClass
+ fun:_NPN_CreateObject
+ fun:_ZN6WebKit11WebBindings12createObjectEP4_NPPP7NPClass
+}
+{
+ Bug_69934_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3IPC11SyncMessage13GenerateReplyEPKNS_7MessageE
+ fun:_ZN3IPC17SyncMessageSchema*
+}
+{
+ bug_70327
+ Memcheck:Leak
+ ...
+ fun:shaper_font_cache_insert
+ fun:get_shaper_and_font
+ fun:itemize_state_process_run
+ fun:pango_itemize_with_base_dir
+ fun:pango_layout_check_lines
+ fun:pango_layout_get_extents_internal
+ fun:pango_layout_get_pixel_extents
+ fun:pango_layout_get_pixel_size
+ fun:_ZN3gfx10Canvas13SizeStringIntERKSbItN4base20string16_char_traitsESaItEERKNS_4FontEPiSA_i
+}
+{
+ bug_71152
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN14SessionService20OnGotSessionCommandsEi13scoped_refptrIN18BaseSessionService26InternalGetCommandsRequestEE
+}
+{
+ bug_71728
+ Memcheck:Leak
+ fun:_Znw*
+ fun:*DownloadFileTest5SetUpEv
+}
+{
+ bug_72544
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEj
+ fun:_ZN3WTF10RefCountedIN7WebCore14StyleSheetListEEnwEj
+ fun:_ZN7WebCore14StyleSheetList6createEPNS_8DocumentE
+ fun:_ZN7WebCore8DocumentC2EPNS_5FrameERKNS_4KURLEbbS5_
+ fun:_ZN7WebCore12HTMLDocumentC1EPNS_5FrameERKNS_4KURLES5_
+ fun:_ZN7WebCore12HTMLDocument6createEPNS_5FrameERKNS_4KURLES5_
+ fun:_ZN7WebCore17DOMImplementation14createDocumentERKN3WTF6StringEPNS_5FrameERKNS_4KURLEb
+ fun:_ZN7WebCore14DocumentWriter14createDocumentERKNS_4KURLE
+ fun:_ZN7WebCore14DocumentWriter5beginERKNS_4KURLEbPNS_14SecurityOriginE
+ fun:_ZN7WebCore11FrameLoader4initEv
+ fun:_ZN7WebCore5Frame4initEv
+ fun:_ZN6WebKit12WebFrameImpl21initializeAsMainFrameEPNS_11WebViewImplE
+ fun:_ZN6WebKit11WebViewImpl19initializeMainFrameEPNS_14WebFrameClientE
+ fun:_ZN10RenderViewC1EP16RenderThreadBaseiiRK19RendererPreferencesRK14WebPreferencesPN4base14RefCountedDataIiEEixRKSbItNS8_20string16_char_traitsESaItEE
+ fun:_ZN10RenderView6CreateEP16RenderThreadBaseiiRK19RendererPreferencesRK14WebPreferencesPN4base14RefCountedDataIiEEixRKSbItNS8_20string16_char_traitsESaItEE
+ fun:_ZN12RenderThread15OnCreateNewViewERK18ViewMsg_New_Params
+}
+{
+ bug_72698_a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN13ProfileIOData20InitializeOnUIThreadEP7Profile
+}
+{
+ bug_73299
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN21RenderProcessHostImpl20CreateMessageFiltersEv
+ fun:_ZN21RenderProcessHostImpl4InitEb
+ fun:_ZN7content18RenderViewHostImpl16CreateRenderViewERKSbItN4base20string16_char_traitsESaItEEi
+}
+{
+ bug_73415
+ Memcheck:Unaddressable
+ fun:_ZN23AccessibilityController36shouldDumpAccessibilityNotificationsEv
+ fun:_ZN11WebViewHost29postAccessibilityNotificationERKN6WebKit22WebAccessibilityObjectENS0_28WebAccessibilityNotificationE
+ fun:_ZN6WebKit16ChromeClientImpl29postAccessibilityNotificationEPN7WebCore19AccessibilityObjectENS1_13AXObjectCache14AXNotificationE
+ fun:_ZN7WebCore13AXObjectCache24postPlatformNotificationEPNS_19AccessibilityObjectENS0_14AXNotificationE
+}
+{
+ bug_73675
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN20LayoutTestController13waitUntilDoneERKN3WTF6VectorI10CppVariantLj0EEEPS2_
+ fun:_ZN13CppBoundClass14MemberCallbackI20LayoutTestControllerE3runERKN3WTF6VectorI10CppVariantLj0EEEPS5_
+ fun:_ZN13CppBoundClass6invokeEPvPK10_NPVariantjPS1_
+ fun:_ZN11CppNPObject6invokeEP8NPObjectPvPK10_NPVariantjPS3_
+ fun:_ZN7WebCore18npObjectInvokeImplERKN2v89ArgumentsENS_18InvokeFunctionTypeE
+ fun:_ZN7WebCore21npObjectMethodHandlerERKN2v89ArgumentsE
+ fun:_ZN2v88internal19HandleApiCallHelperILb0EEEPNS0_11MaybeObjectENS0_47_GLOBAL__N_v8_src_builtins.cc_*BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEE
+ obj:*
+}
+{
+ bug_75019
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN14GpuDataManagerC1Ev
+ fun:_ZN22DefaultSingletonTraitsI14GpuDataManagerE3NewEv
+ fun:_ZN9SingletonI14GpuDataManager22DefaultSingletonTraitsIS0_ES0_E3getEv
+ fun:_ZN14GpuDataManager11GetInstanceEv
+ fun:_Z11BrowserMainRK18MainFunctionParams
+ fun:_ZN20InProcessBrowserTest5SetUpEv
+}
+{
+ bug_75051
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net12CertVerifier6VerifyEPNS_15X509CertificateERKSsiPNS_16CertVerifyResultEP14CallbackRunnerI6Tuple1IiEEPPv
+ fun:_ZN3net25SingleRequestCertVerifier6VerifyEPNS_15X509CertificateERKSsiPNS_16CertVerifyResultEP14CallbackRunnerI6Tuple1IiEE
+ fun:_ZN3net18SSLClientSocketNSS12DoVerifyCertEi
+ fun:_ZN3net18SSLClientSocketNSS15DoHandshakeLoopEi
+}
+{
+ bug_75127a
+ Memcheck:Uninitialized
+ ...
+ fun:png_process_data
+ fun:_ZN3gfx8PNGCodec6Decode*
+}
+{
+ bug_75127b
+ Memcheck:Uninitialized
+ ...
+ fun:png_process_data
+ fun:_ZN3gfx8PNGCodec6Decode*
+}
+{
+ bug_75127c
+ Memcheck:Uninitialized
+ ...
+ fun:png_process_data
+ fun:_ZN3gfx8PNGCodec6Decode*
+}
+{
+ bug_76197a
+ Memcheck:Unaddressable
+ fun:sqlite3DbFree
+ fun:releaseMemArray
+ fun:sqlite3VdbeDelete
+ fun:sqlite3VdbeFinalize
+ fun:sqlite3_finalize
+ fun:_ZN3sql10Connection12StatementRef5CloseEv
+ fun:_ZN3sql10Connection12StatementRefD2Ev
+ fun:_ZN3sql10Connection12StatementRefD1Ev
+ fun:_ZNK4base10RefCountedIN3sql10Connection12StatementRefEE7ReleaseEv
+ fun:_ZN13scoped_refptrIN3sql10Connection12StatementRefEED2Ev
+ fun:_ZN13scoped_refptrIN3sql10Connection12StatementRefEED1Ev
+ fun:_ZNSt4pairIKN3sql11StatementIDE13scoped_refptrINS0_10Connection12StatementRefEEED2Ev
+ fun:_ZNSt4pairIKN3sql11StatementIDE13scoped_refptrINS0_10Connection12StatementRefEEED1Ev
+ fun:_ZN9__gnu_cxx13new_allocatorISt4pairIKN3sql11StatementIDE13scoped_refptrINS2_10Connection12StatementRefEEEE7destroyEPS9_
+ fun:_ZNSt8_Rb_treeIN3sql11StatementIDESt4pairIKS1_13scoped_refptrINS0_10Connection12StatementRefEEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE12destroy_nodeEPSt13_Rb_tree_nodeIS8_E
+ fun:_ZNSt8_Rb_treeIN3sql11StatementIDESt4pairIKS1_13scoped_refptrINS0_10Connection12StatementRefEEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE8_M_eraseEPSt13_Rb_tree_nodeIS8_E
+ fun:_ZNSt8_Rb_treeIN3sql11StatementIDESt4pairIKS1_13scoped_refptrINS0_10Connection12StatementRefEEESt10_Select1stIS8_ESt4lessIS1_ESaIS8_EE5clearEv
+ fun:_ZNSt3mapIN3sql11StatementIDE13scoped_refptrINS0_10Connection12StatementRefEESt4lessIS1_ESaISt4pairIKS1_S5_EEE5clearEv
+ fun:_ZN3sql10Connection5CloseEv
+ fun:_ZN3sql10ConnectionD2Ev
+ fun:_ZN3sql10ConnectionD1Ev
+ fun:_ZN7history16InMemoryDatabaseD0Ev
+}
+{
+ bug_76197b
+ Memcheck:Unaddressable
+ ...
+ fun:sqlite3_step
+ fun:sqlite3_exec
+ fun:_ZN3sql10Connection7ExecuteEPKc
+ fun:_ZN7history11URLDatabase31CreateKeywordSearchTermsIndicesEv
+ fun:_ZN7history16InMemoryDatabase12InitFromDiskE*
+ fun:_ZN7history22InMemoryHistoryBackend4InitE*
+}
+{
+ bug_77766
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN7WebCore18PerformTaskContextnwEm
+ fun:_ZN7WebCore8Document8postTaskEN3WTF10PassOwnPtrINS_22ScriptExecutionContext4TaskEEE
+ fun:_ZN7WebCore20WorkerMessagingProxy22workerContextDestroyedEv
+ fun:_ZN6WebKit19WebWorkerClientImpl22workerContextDestroyedEv
+ fun:_ZN7WebCore13WorkerContextD2Ev
+ fun:_ZN7WebCore22DedicatedWorkerContextD0Ev
+ fun:_ZN3WTF10RefCountedIN7WebCore13WorkerContextEE5derefEv
+ fun:_ZN3WTF6RefPtrIN7WebCore13WorkerContextEEaSEPS2_
+ fun:_ZN7WebCore12WorkerThread12workerThreadEv
+ fun:_ZN7WebCore12WorkerThread17workerThreadStartEPv
+ fun:_ZN3WTFL16threadEntryPointEPv
+ fun:_ZN3WTFL19wtfThreadEntryPointEPv
+}
+{
+ bug_78201
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN18BrowserProcessImpl28CreateResourceDispatcherHostEv
+ fun:_ZN18BrowserProcessImpl24resource_dispatcher_hostEv
+ fun:_ZN16ExtensionService4InitEv
+ fun:_ZN11ProfileImpl14InitExtensionsE*
+}
+{
+ bug_78786
+ Memcheck:Leak
+ fun:_Znw*
+ fun:*35NonBlockingInvalidationNotifierTest5SetUpEv
+}
+{
+ bug_79357a
+ Memcheck:Unaddressable
+ ...
+ fun:*FilePathWatcherImpl*Watch*Delegate*
+ fun:*FilePathWatcher*Watch*
+ fun:_ZN21UserStyleSheetWatcher4InitEv
+}
+{
+ bug_79357b
+ Memcheck:Leak
+ ...
+ fun:*FilePathWatcherImpl*Watch*Delegate*
+ fun:*FilePathWatcher*Watch*
+ fun:_ZN21UserStyleSheetWatcher4InitEv
+}
+{
+ bug_79651
+ Memcheck:Leak
+ ...
+ fun:_ZN8notifier14XmppConnectionC1ERKN4buzz18XmppClientSettingsERK13scoped_refptrIN3net23URLRequestContextGetterEEPNS0_8DelegateEPNS1_11PreXmppAuthE
+ fun:_ZN8notifier18SingleLoginAttempt13OnNewSettingsERKNS_18ConnectionSettingsE
+ fun:_ZN8notifier23XmppConnectionGenerator17UseNextConnectionEv
+ fun:_ZN8notifier23XmppConnectionGenerator15StartGeneratingEv
+ fun:_ZN8notifier18SingleLoginAttemptC1EPNS_13LoginSettingsEPNS0_8DelegateE
+ fun:_ZN8notifier5Login15StartConnectionEv
+ fun:_ZN13sync_notifier20InvalidationNotifier17UpdateCredentialsERKSsS2_
+ fun:*35InvalidationNotifierTest_Basic_Test8TestBodyEv
+}
+{
+ bug_79652
+ Memcheck:Leak
+ ...
+ fun:_ZN8chromeos14AudioMixerAlsa15ConnectInternalEv
+ fun:_ZN8chromeos14AudioMixerAlsa7ConnectEv
+}
+{
+ bug_79654_a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZNSt3setIP16RenderWidgetHostSt4lessIS1_ESaIS1_EE6insertERKS1_
+ fun:_ZN*9TabLoader12TabIsLoadingEP24NavigationControllerImpl
+ fun:_ZN*18SessionRestoreImpl21ProcessSessionWindowsEPSt6vectorIP13SessionWindowSaIS3_EE
+ fun:_ZN*18SessionRestoreImpl12OnGotSessionEiPSt6vectorIP13SessionWindowSaIS3_EE
+}
+{
+ bug_79654_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:*RenderWidgetHost*
+ ...
+ fun:_ZNSt3setIP16RenderWidgetHostSt4lessIS1_ESaIS1_EE6insertERKS1_
+ fun:*TabLoader7ObserveEiRKN7content18NotificationSourceERKNS1_19NotificationDetailsE
+ fun:_ZN23NotificationServiceImpl*
+ fun:_ZN15WebContentsImpl12SetIsLoading*
+ fun:_ZN15WebContentsImpl14RenderViewGone*
+}
+{
+ bug_79865a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN33MalwareDetailsTest_HTTPCache_Test8TestBodyEv
+}
+{
+ bug_79865b
+ Memcheck:Leak
+ ...
+ fun:_Znw*
+ fun:_ZN14TestingProfile20CreateRequestContextEv
+ fun:_ZN42MalwareDetailsTest_HTTPCacheNoEntries_Test8TestBodyEv
+}
+{
+ bug_79933a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN21TestURLRequestContext4InitEv
+ ...
+ fun:_ZN21TestURLRequestContextC1Ev
+ fun:_ZN27TestURLRequestContextGetter20GetURLRequestContextEv
+}
+{
+ bug_16089 WorkerPool threads can leak by design
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base22PosixDynamicThreadPool8PostTask*
+}
+{
+ bug_80462_a
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN7WebCoreL15allocV8NPObjectEP4_NPPP7NPClass
+ fun:_NPN_CreateObject
+ fun:_ZN7WebCore22npCreateV8ScriptObjectEP4_NPPN2v86HandleINS2_6ObjectEEEPNS_9DOMWindowE
+ fun:_ZN6WebKitL16makeIntArrayImplERKNS_9WebVectorIiEE
+ fun:_ZN6WebKit11WebBindings12makeIntArrayERKNS_9WebVectorIiEE
+}
+{
+ bug_80462_b
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN7WebCoreL15allocV8NPObjectEP4_NPPP7NPClass
+ fun:_NPN_CreateObject
+ fun:_ZN7WebCore22npCreateV8ScriptObjectEP4_NPPN2v86HandleINS2_6ObjectEEEPNS_9DOMWindowE
+ fun:_ZN6WebKitL19makeStringArrayImplERKNS_9WebVectorINS_9WebStringEEE
+ fun:_ZN6WebKit11WebBindings15makeStringArrayERKNS_9WebVectorINS_9WebStringEEE
+}
+{
+ bug_80537_a
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN3gfx15GLContextOSMesa11MakeCurrentEv
+}
+{
+ bug_80537_b
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:_ZN3gfx15GLContextOSMesa11MakeCurrentEPNS_9GLSurfaceE
+}
+{
+ bug_80551
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_Z11BrowserMainRK18MainFunctionParams
+ fun:_ZN20InProcessBrowserTest5SetUpEv
+}
+{
+ bug_80550_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN16RenderWidgetHost11WasRestoredEv
+}
+{
+ bug_80550_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN16RenderWidgetHost9WasHiddenEv
+}
+{
+ bug_80663
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMN3net17URLRequestHttpJobEFvPSsPSt6vectorINS1_11CookieStore10CookieInfoESaIS6_EEEPS2_EENS_8internal20InvokerStorageHolderINSD_15InvokerStorage1IT_T0_EEEESG_RKSH_
+ fun:_ZN3net17URLRequestHttpJob23AddCookieHeaderAndStartEv
+ fun:_ZN3net17URLRequestHttpJob5StartEv
+ fun:_ZN3net10URLRequest8StartJobEPNS_13URLRequestJobE
+ fun:_ZN3net10URLRequest5StartEv
+ fun:_ZN10URLFetcher4Core15StartURLRequestEv
+ fun:_ZN10URLFetcher4Core30StartURLRequestWhenAppropriateEv
+}
+{
+ bug_82717
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN6chrome26ChromeContentBrowserClient24RenderProcessHostCreatedEPN7content17RenderProcessHostE
+ fun:_ZN21RenderProcessHostImpl4Init*
+ ...
+ fun:_ZN15WebContentsImpl32CreateRenderViewForRenderManagerEP*
+ fun:_ZN21RenderViewHostManager14InitRenderViewEP*
+ ...
+ fun:_ZN21RenderViewHostManager8NavigateERKN7content19NavigationEntryImplE
+ fun:_ZN15WebContentsImpl15NavigateToEntryERKN7content19NavigationEntryImplENS0_20NavigationController10ReloadTypeE
+}
+{
+ bug_83609
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4Bind*TaskClosureAdapterEFvvEPS2_EENS_8internal20InvokerStorageHolderINS6_15InvokerStorage1IT_T0_EEEES9_RKSA_
+ fun:_ZN4base11MessageLoop15PostDelayedTaskERKN15tracked_objects8LocationEP4Taskx
+ fun:_ZN13BrowserThread14PostTaskHelperENS_2IDERKN15tracked_objects8LocationEP4Taskxb
+ fun:_ZN13BrowserThread8PostTaskENS_2IDERKN15tracked_objects8LocationEP4Task
+}
+{
+ bug_83609b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4Bind*TaskClosureAdapterEFvvEPS2_EENS_8internal20InvokerStorageHolderINS6_15InvokerStorage1IT_T0_EEEES9_RKSA_
+ fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationEP4Task
+}
+{
+ bug_84224_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocator*PendingTaskEE8allocate*
+ fun:_ZN*_Deque_baseIN*PendingTaskESaIS1_*_M_allocate_*
+ ...
+ fun:_ZNSt5dequeIN*PendingTaskESaIS1_EE*push_back*
+ fun:_ZNSt5queueIN4*PendingTask*deque*push*
+ fun:_ZN4base11MessageLoop18AddToIncomingQueueEPN*PendingTaskE*
+}
+{
+ bug_84224_b
+ Memcheck:Unaddressable
+ fun:_ZN13scoped_refptrIN4base8internal18InvokerStorageBaseEEC2ERKS3_
+ fun:_ZN13scoped_refptrIN4base8internal18InvokerStorageBaseEEC1ERKS3_
+ fun:_ZN4base8internal12CallbackBaseC2ERKS1_
+ fun:_ZN4base8CallbackIFvvEEC2ERKS2_
+ fun:_ZN4base8CallbackIFvvEEC1ERKS2_
+ fun:_ZN4base11MessageLoop11PendingTaskC2ERKS0_
+ fun:_ZN4base11MessageLoop11PendingTaskC1ERKS0_
+ fun:_ZN9__gnu_cxx13new_allocatorIN11MessageLoop11PendingTaskEE9constructEPS2_RKS2_
+ fun:_ZNSt5dequeIN11MessageLoop11PendingTaskESaIS1_EE9push_backERKS1_
+ fun:_ZNSt5queueIN11MessageLoop11PendingTaskESt5dequeIS1_SaIS1_EEE4pushERKS1_
+ fun:_ZN4base11MessageLoop18AddToIncomingQueueEPNS_11PendingTaskE
+}
+{
+ bug_84265
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12LoginHandler6CreateEPN3net17AuthChallengeInfoEPNS0_10URLRequestE
+ fun:_Z17CreateLoginPromptPN3net17AuthChallengeInfoEPNS_10URLRequestE
+ fun:_ZN22ResourceDispatcherHost14OnAuthRequiredEPN3net10URLRequestEPNS0_17AuthChallengeInfoE
+ fun:_ZN3net13URLRequestJob21NotifyHeadersCompleteEv
+}
+{
+ bug_84770_a
+ Memcheck:Unaddressable
+ fun:_ZN6WebKit21FrameLoaderClientImpl12allowPluginsEb
+ fun:_ZN7WebCore14SubframeLoader12allowPluginsENS_28ReasonForCallingAllowPluginsE
+}
+{
+ bug_84770_b
+ Memcheck:Unaddressable
+ fun:_ZN6WebKit21FrameLoaderClientImpl15allowJavaScriptEb
+ fun:_ZN7WebCore16ScriptController17canExecuteScriptsENS_33ReasonForCallingCanExecuteScriptsE
+}
+{
+ bug_84770_c
+ Memcheck:Unaddressable
+ fun:_ZN6WebKit21FrameLoaderClientImpl20allowScriptExtensionERKN3WTF6StringEi
+ fun:_ZN7WebCore16V8DOMWindowShell16createNewContextEN2v86HandleINS1_6ObjectEEEi
+}
+{
+ bug_86481
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocator*FilePath*allocate*
+ fun:_ZNSt11_Deque_base*FilePath*_M_allocate_map*
+ fun:_ZNSt11_Deque_base*FilePath*_M_initialize_map*
+ fun:_ZNSt11_Deque_baseI*FilePath*
+ fun:_ZNSt5dequeI*FilePath*
+ fun:_ZNSt5stackI*FilePath*deque*
+ fun:_ZN9file_util14FileEnumeratorC1E*
+ fun:_ZN7history20ExpireHistoryBackend25DoExpireHistoryIndexFilesEv
+}
+{
+ bug_87423
+ Memcheck:Uninitialized
+ fun:_ZNK3net15HttpBasicStream23LogNumRttVsBytesMetricsEv
+ fun:_ZN3net22HttpNetworkTransaction18DoReadBodyCompleteEi
+ fun:_ZN3net22HttpNetworkTransaction6DoLoopEi
+ fun:_ZN3net22HttpNetworkTransaction4ReadEPNS_8IOBufferEiP14CallbackRunnerI6Tuple1IiEE
+ fun:_Z15ReadTransactionPN3net15HttpTransactionEPSs
+ fun:_ZN3net73HttpNetworkTransactionTest_ErrorResponseTofHttpsConnectViaHttpsProxy_Test8TestBodyEv
+}
+{
+ bug_88640_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11ProfileImpl30InitRegisteredProtocolHandlersEv
+ fun:_ZN11ProfileImpl11DoFinalInitEv
+ fun:_ZN11ProfileImpl13OnPrefsLoadedEb
+}
+{
+ bug_88640_b
+ Memcheck:Leak
+ ...
+ fun:_ZN11ProfileImpl13OnPrefsLoadedEb
+ ...
+ fun:_ZN11ProfileImplC*E*
+}
+{
+ bug_88640_c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN29ChromeURLRequestContextGetter14CreateOriginalEP7ProfilePK13ProfileIOData
+ fun:_ZN17ProfileImplIOData6Handle4InitE*
+ fun:_ZN11ProfileImpl11DoFinalInitEv
+ fun:_ZN11ProfileImpl13OnPrefsLoadedEb
+}
+{
+ bug_81796
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base16MessageLoopProxy22currentEv
+ fun:_ZN3IPC12ChannelProxy7ContextC1EPNS_7Channel8ListenerEPN4base16MessageLoopProxyE
+ fun:_ZN3IPC12ChannelProxyC1ERKNS_13ChannelHandleENS_7Channel4ModeEPNS4_8ListenerEPN4base16MessageLoopProxyE
+}
+{
+ bug_89304
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net20ClientSocketPoolBaseINS_*SocketParamsEE13RequestSocketERKSsRK13scoped_refptrIS1_ENS_15RequestPriorityEPNS_18ClientSocketHandleEP14CallbackRunnerI6Tuple1IiEERKNS_11BoundNetLogE
+ fun:_ZN3net*SocketPool13RequestSocketERKSsPKvNS_15RequestPriorityEPNS_18ClientSocketHandleEP14CallbackRunnerI6Tuple1IiEERKNS_11BoundNetLogE
+ fun:_ZN3net18ClientSocketHandle4Init*
+ ...
+ fun:_ZN3net23ClientSocketPoolManager30InitSocketHandleForHttpRequestERK4GURLRKNS_18HttpRequestHeadersEiNS_15RequestPriorityEPNS_18HttpNetworkSessionERKNS_9ProxyInfoEbbRKNS_9SSLConfigESF_RKNS_11BoundNetLogEPNS_18ClientSocketHandleEP14CallbackRunnerI6Tuple1IiEE
+ fun:_ZN3net21HttpStreamFactoryImpl3Job16DoInitConnectionEv
+}
+{
+ bug_89311
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net16HttpStreamParser22DoParseResponseHeadersEi
+ fun:_ZN3net16HttpStreamParser20ParseResponseHeadersEv
+ fun:_ZN3net16HttpStreamParser21DoReadHeadersCompleteEi
+}
+{
+ bug_89942_a
+ Memcheck:Leak
+ ...
+ fun:_ZN10ZygoteHost11ForkRequestERKSt6vectorISsSaISsEERKS0_ISt4pairIjiESaIS6_EERKSs
+ fun:_ZN20ChildProcessLauncher7Context14LaunchInternalE13scoped_refptrIS0_EN13BrowserThread2IDEbRKSt6vectorISt4pairISsSsESaIS7_EEiP11CommandLine
+}
+{
+ bug_89942_b
+ Memcheck:Leak
+ ...
+ fun:_ZNSt6vectorISt4pairIjiESaIS1_EE9push_backERKS1_
+ fun:_ZN20ChildProcessLauncher7Context14LaunchInternalE13scoped_refptrIS0_EN13BrowserThread2IDEbRKSt6vectorISt4pairISsSsESaIS7_EEiP11CommandLine
+}
+{
+ bug_90057a
+ Memcheck:Leak
+ ...
+ fun:_ZN3net13CookieMonster9InitStoreEv
+ fun:_ZN3net13CookieMonster15InitIfNecessaryEv
+ fun:_ZN3net13CookieMonster30GetAllCookiesForURLWithOptionsERK4GURLRKNS_13CookieOptionsE
+ fun:_ZN3net13CookieMonster19GetAllCookiesForURLERK4GURL
+ fun:_ZN22ResourceDispatcherHost13CanGetCookiesEPN3net10URLRequestE
+ fun:_ZN3net10URLRequest13CanGetCookiesEv
+ fun:_ZN3net13URLRequestJob13CanGetCookiesEv
+ fun:_ZN3net17URLRequestHttpJob23AddCookieHeaderAndStartEv
+}
+{
+ bug_90057b
+ Memcheck:Leak
+ ...
+ fun:_ZN3net13CookieMonster9InitStoreEv
+ fun:_ZN3net13CookieMonster15InitIfNecessaryEv
+ fun:_ZN3net13CookieMonster21GetCookiesWithOptionsERK4GURLRKNS_13CookieOptionsE
+ fun:_ZN3net13CookieMonster26GetCookiesWithOptionsAsyncERK4GURLRKNS_13CookieOptionsERKN4base8CallbackIFvRKSsEEE
+ fun:_ZN3net11CookieStore15GetCookiesAsyncERK4GURLRKN4base8CallbackIFvRKSsEEE
+ fun:_ZN12_GLOBAL__N_120GetCookiesOnIOThreadERK4GURLRK13scoped_refptrIN3net23URLRequestContextGetterEEPN4base13WaitableEventEPSs
+}
+{
+ bug_90057c
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net17URLRequestHttpJob14SaveNextCookieEv
+ fun:_ZN3net17URLRequestHttpJob35SaveCookiesAndNotifyHeadersCompleteEv
+ fun:_ZN3net17URLRequestHttpJob16OnStartCompletedEi
+}
+{
+ bug_90215_c
+ Memcheck:Leak
+ ...
+ fun:_ZN3net13URLRequestJob21NotifyRestartRequiredEv
+ fun:_ZN8appcache21AppCacheURLRequestJob13BeginDeliveryEv
+}
+{
+ bug_90215_d
+ Memcheck:Leak
+ ...
+ fun:_ZN8appcache19AppCacheStorageImpl23RunOnePendingSimpleTaskEv
+}
+{
+ bug_90215_e
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN8appcache15AppCacheService10InitializeE*
+ fun:_ZN21ChromeAppCacheService20InitializeOnIOThreadE*
+}
+{
+ bug_90215_f
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN26TransportSecurityPersisterC1EPN3net22TransportSecurityStateERKN4base8FilePathEb
+ fun:_ZNK13ProfileIOData4InitEPSt3mapISs10linked_ptrIN3net20URLRequestJobFactory15ProtocolHandlerEESt4lessISsESaISt4pairIKSsS5_EEE
+ fun:_ZN12_GLOBAL__N_114FactoryForMain6CreateEv
+ fun:_ZN29ChromeURLRequestContextGetter20GetURLRequestContextEv
+ fun:_ZN7content21ChromeAppCacheService20InitializeOnIOThreadERKN4base8FilePathEPNS_15ResourceContextEPN3net23URLRequestContextGetterE13scoped_refptrIN5quota20SpecialStoragePolicyEE
+}
+{
+ bug_90240
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN2pp5proxy26PPP_Instance_Private_Proxy22OnMsgGetInstanceObjectEiNS0_24SerializedVarReturnValueE
+}
+{
+ bug_90400
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11ProfileImpl24GetUserStyleSheetWatcherEv
+ fun:_ZN6chrome26ChromeContentBrowserClient14GetWebkitPrefs*
+ fun:_ZN15WebContentsImpl14GetWebkitPrefsEv
+}
+{
+ bug_90487a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt10_List_nodeIPN5quota11QuotaClientEEE8allocateEjPKv
+ fun:_ZNSt10_List_baseIPN5quota11QuotaClientESaIS2_EE11_M_get_nodeEv
+ fun:_ZNSt4listIPN5quota11QuotaClientESaIS2_EE14_M_create_nodeERKS2_
+ fun:_ZNSt4listIPN5quota11QuotaClientESaIS2_EE9_M_insertESt14_List_iteratorIS2_ERKS2_
+ fun:_ZNSt4listIPN5quota11QuotaClientESaIS2_EE9push_backERKS2_
+ fun:_ZN5quota12QuotaManager14RegisterClientEPNS_11QuotaClientE
+ fun:_ZN5quota17QuotaManagerProxy14RegisterClientEPNS_11QuotaClientE
+}
+{
+ bug_90487b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_
+ ...
+ fun:_ZN5quota12QuotaManager*
+}
+{
+ bug_90496a
+ Memcheck:Leak
+ ...
+ fun:_ZN3IPC16MessageWithTupleI6Tuple2Ii23ResourceHostMsg_RequestEE8DispatchI22ResourceDispatcherHostS6_iRKS2_EEbPKNS_7MessageEPT_PT0_MSC_FvRSA_T1_T2_E
+ fun:_ZN22ResourceDispatcherHost17OnMessageReceivedERKN3IPC7MessageEP21ResourceMessageFilterPb
+ fun:_ZN21ResourceMessageFilter17OnMessageReceivedERKN3IPC7MessageEPb
+ fun:_ZN20BrowserMessageFilter15DispatchMessageERKN3IPC7MessageE
+ fun:_ZN20BrowserMessageFilter17OnMessageReceivedERKN3IPC7MessageE
+ fun:_ZN3IPC12ChannelProxy7Context10TryFiltersERKNS_7MessageE
+ fun:_ZN3IPC12ChannelProxy7Context17OnMessageReceivedERKNS_7MessageE
+ fun:_ZN3IPC7Channel11ChannelImpl23ProcessIncomingMessagesEv
+ fun:_ZN3IPC7Channel11ChannelImpl28OnFileCanReadWithoutBlockingEi
+}
+{
+ bug_90496b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN22ResourceDispatcherHost23CompleteResponseStartedEPN3net10URLRequestE
+ fun:_ZN22ResourceDispatcherHost17OnResponseStartedEPN3net10URLRequestE
+ fun:_ZN3net10URLRequest21NotifyResponseStartedEv
+ fun:_ZN3net13URLRequestJob21NotifyHeadersCompleteEv
+}
+{
+ bug_90496c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN20AsyncResourceHandler15OnReadCompletedEiPi
+ fun:_ZN23BufferedResourceHandler15OnReadCompletedEiPi
+ fun:_ZN27SafeBrowsingResourceHandler15OnReadCompletedEiPi
+ fun:_ZN22OfflineResourceHandler15OnReadCompletedEiPi
+ fun:_ZN22ResourceDispatcherHost12CompleteReadEPN3net10URLRequestEPi
+ fun:_ZN22ResourceDispatcherHost15OnReadCompletedEPN3net10URLRequestEi
+ fun:_ZN3net10URLRequest19NotifyReadCompletedEi
+ fun:_ZN3net13URLRequestJob18NotifyReadCompleteEi
+ fun:_ZN19URLRequestChromeJob13DataAvailableEP16RefCountedMemory
+ fun:_ZN27ChromeURLDataManagerBackend13DataAvailableEiP16RefCountedMemory
+ fun:_ZN20ChromeURLDataManager10DataSource22SendResponseOnIOThreadEi13scoped_refptrI16RefCountedMemoryE
+}
+{
+ bug_90496d
+ Memcheck:Leak
+ ...
+ fun:_ZN24CrossSiteResourceHandler14ResumeResponseEv
+ fun:_ZN22ResourceDispatcherHost12OnSwapOutACKERK22ViewMsg_SwapOut_Params
+ fun:_ZN18RenderWidgetHelper21OnCrossSiteSwapOutACKERK22ViewMsg_SwapOut_Params
+}
+{
+ bug_90496e
+ Memcheck:Leak
+ ...
+ fun:_ZN14SharedIOBuffer4InitEv
+ fun:_ZN20AsyncResourceHandler10OnWillReadEiPPN3net8IOBufferEPii
+ fun:_ZN24CrossSiteResourceHandler10OnWillReadEiPPN3net8IOBufferEPii
+ fun:_ZN23BufferedResourceHandler10OnWillReadEiPPN3net8IOBufferEPii
+ fun:_ZN27SafeBrowsingResourceHandler10OnWillReadEiPPN3net8IOBufferEPii
+ fun:_ZN22OfflineResourceHandler10OnWillReadEiPPN3net8IOBufferEPii
+ fun:_ZN22ResourceDispatcherHost4ReadEPN3net10URLRequestEPi
+ fun:_ZN22ResourceDispatcherHost12StartReadingEPN3net10URLRequestE
+}
+{
+ bug_90671
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZNK3sql9Statement*ColumnString*
+ fun:_ZN7history11URLDatabase10FillURLRowERN3sql9StatementEPNS_6URLRowE
+ fun:_ZN7history11URLDatabase13URLEnumerator10GetNextURLEPNS_6URLRowE
+ fun:_ZN7history14HistoryBackend11IterateURLsEPN14HistoryService13URLEnumeratorE
+}
+{
+ bug_91199
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN19URLRequestChromeJob15GetResponseInfoEPN3net16HttpResponseInfoE
+ fun:_ZN3net13URLRequestJob21NotifyHeadersCompleteEv
+ fun:_ZN19URLRequestChromeJob10StartAsyncEv
+}
+{
+ bug_92571
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7history16TopSitesDatabase8CreateDBE*
+ fun:_ZN7history16TopSitesDatabase4InitE*
+ fun:_ZN7history15TopSitesBackend16InitDBOnDBThreadE*
+}
+{
+ bug_92741a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIPFvPNS_13WaitableEventEPSsRKSsES2_S3_EENS_8internal20InvokerStorageHolderINS8_15InvokerStorage2IT_T0_T1_EEEESB_RKSC_RKSD_
+ fun:_ZN12_GLOBAL__N_120GetCookiesOnIOThreadERK4GURLRK13scoped_refptrIN3net23URLRequestContextGetterEEPN4base13WaitableEventEPSs
+ fun:_Z18DispatchToFunctionIPFvRK4GURLRK13scoped_refptrIN3net23URLRequestContextGetterEEPN4base13WaitableEventEPSsES0_S6_SB_SC_EvT_RK6Tuple4IT0_T1_T2_T3_E
+}
+{
+ bug_92741b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMN3net17URLRequestHttpJobEFvPSsPSt6vectorINS1_11CookieStore10CookieInfoESaIS6_EEENS_7WeakPtrIS2_EEEENS_8internal20InvokerStorageHolderINSE_15InvokerStorage1IT_T0_EEEESH_RKSI_
+ fun:_ZN3net17URLRequestHttpJob24CheckCookiePolicyAndLoadERKNS_10CookieListE
+}
+{
+ bug_92741c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMN3net17URLRequestHttpJobEFvRKNS1_10CookieListEENS_7WeakPtrIS2_EEEENS_8internal20InvokerStorageHolderINSA_15InvokerStorage1IT_T0_EEEESD_RKSE_
+ fun:_ZN3net17URLRequestHttpJob23AddCookieHeaderAndStartEv
+ fun:_ZN3net17URLRequestHttpJob5StartEv
+ fun:_ZN3net10URLRequest8StartJobEPNS_13URLRequestJobE
+ fun:_ZN3net10URLRequest5StartEv
+}
+{
+ bug_92876a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net18SSLClientSocketNSS10BufferSendEv
+ fun:_ZN3net18SSLClientSocketNSS13DoTransportIOEv
+ fun:_ZN3net18SSLClientSocketNSS11DoWriteLoopEi
+ fun:_ZN3net18SSLClientSocketNSS5WriteEPNS_8IOBufferEiP14CallbackRunnerI6Tuple1IiEE
+ fun:_ZN3net11SpdySession11WriteSocketEv
+}
+{
+ bug_92876b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net18SSLClientSocketNSS10BufferSendEv
+ fun:_ZN3net18SSLClientSocketNSS13DoTransportIOEv
+ fun:_ZN3net18SSLClientSocketNSS15DoHandshakeLoopEi
+ fun:_ZN3net18SSLClientSocketNSS7ConnectEP14CallbackRunnerI6Tuple1IiEE
+ fun:_ZN3net13SSLConnectJob12DoSSLConnectEv
+ fun:_ZN3net13SSLConnectJob6DoLoopEi
+ fun:_ZN3net13SSLConnectJob12OnIOCompleteEi
+}
+{
+ bug_93250a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:*SHA1Fingerprint*
+ fun:_ZN3net16CertVerifyResultaSERKS0_
+ fun:_ZN3net12CertVerifier12HandleResultEPNS_15X509CertificateERKSsiiRKNS_16CertVerifyResultE
+ fun:_ZN3net18CertVerifierWorker7DoReplyEv
+}
+{
+ bug_93250b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMNS_6subtle18TaskClosureAdapterEFvvEPS2_EENS_8internal20InvokerStorageHolderINS6_15InvokerStorage1IT_T0_EEEES9_RKSA_
+ fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationEP4Task
+ fun:_ZN3net18CertVerifierWorker6FinishEv
+ fun:_ZN3net18CertVerifierWorker3RunEv
+}
+{
+ bug_93730_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN14ServiceProcess10InitializeEP16MessageLoopForUIRK11CommandLineP19ServiceProcessState
+ fun:_Z18ServiceProcessMainRK18MainFunctionParams
+ ...
+ fun:ChromeMain
+ fun:main
+}
+{
+ bug_93730_b
+ Memcheck:Leak
+ fun:_Zna*
+ fun:_ZN4base13LaunchProcessERKSt6vectorISsSaISsEERKNS_13LaunchOptionsEPi
+ fun:_ZN4base13LaunchProcessERK11CommandLineRKNS_13LaunchOptionsEPi
+ fun:_ZN21ServiceProcessControl8Launcher5DoRunEv
+}
+{
+ bug_93730_c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_Z17NewRunnableMethodIN21ServiceProcessControl8LauncherEMS1_FvvEEP14CancelableTaskPT_T0_
+ fun:_ZN21ServiceProcessControl8Launcher5DoRunEv
+}
+{
+ bug_93730_d
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3IPC11SyncChannelC1ERKNS_13ChannelHandleENS_7Channel4ModeEPNS4_8ListenerEPN4base16MessageLoopProxyEbPNS8_13WaitableEventE
+ fun:_ZN16ServiceIPCServer13CreateChannelEv
+ fun:_ZN16ServiceIPCServer4InitEv
+ fun:_ZN14ServiceProcess10InitializeEP16MessageLoopForUIRK11CommandLineP19ServiceProcessState
+ fun:_Z18ServiceProcessMainRK18MainFunctionParams
+ ...
+ fun:ChromeMain
+ fun:main
+}
+{
+ bug_94195
+ Memcheck:Leak
+ ...
+ fun:_ZN12GpuBlacklist16LoadGpuBlacklistERKSsNS_8OsFilterE
+}
+{
+ bug_94345
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNK4base8internal18WeakReferenceOwner6GetRefEv
+ fun:_ZN4base15SupportsWeakPtrI16ObserverListBaseIN11MessageLoop12TaskObserverEEE9AsWeakPtrEv
+ fun:_ZN16ObserverListBaseIN11MessageLoop12TaskObserverEE8IteratorC1ERS2_
+}
+{
+ bug_94764
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN8remoting13ClientSession11UnpressKeysEv
+ fun:_ZN8remoting34ClientSessionTest_UnpressKeys_Test8TestBodyEv
+}
+{
+ bug_95448
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKSsPN4base5ValueEEEE8allocateEjPKv
+ fun:_ZNSt8_Rb_treeISsSt4pairIKSsPN4base5ValueEESt10_Select1stIS5_ESt4lessISsESaIS5_EE11_M_get_nodeEv
+ fun:_ZNSt8_Rb_treeISsSt4pairIKSsPN4base5ValueEESt10_Select1stIS5_ESt4lessISsESaIS5_EE14_M_create_nodeERKS5_
+ fun:_ZNSt8_Rb_treeISsSt4pairIKSsPN4base5ValueEESt10_Select1stIS5_ESt4lessISsESaIS5_EE10_M_insert_EPKSt18_Rb_tree_node_baseSE_RKS5_
+ fun:_ZNSt8_Rb_treeISsSt4pairIKSsPN4base5ValueEESt10_Select1stIS5_ESt4lessISsESaIS5_EE17_M_insert_unique_ESt23_Rb_tree_const_iteratorIS5_ERKS5_
+ fun:_ZNSt3mapISsPN4base5ValueESt4lessISsESaISt4pairIKSsS2_EEE6insertESt17_Rb_tree_iteratorIS7_ERKS7_
+ fun:_ZNSt3mapISsPN4base5ValueESt4lessISsESaISt4pairIKSsS2_EEEixERS6_
+ fun:_ZN4base15DictionaryValue23SetWithoutPathExpansionERKSsPNS_5ValueE
+ fun:_ZN4base15DictionaryValue3SetERKSsPNS_5ValueE
+ fun:_ZN4base15DictionaryValue9SetStringERKSsRKSbItNS_20string16_char_traitsESaItEE
+ fun:_ZN11PluginPrefs23CreatePluginFileSummaryERKN6webkit13WebPluginInfoE
+ fun:_ZN11PluginPrefs19OnUpdatePreferencesESt6vectorIN6webkit13WebPluginInfoESaIS2_EES0_INS1_5npapi11PluginGroupESaIS6_EE
+}
+{
+ bug_95902
+ Memcheck:Leak
+ ...
+ fun:xdg_mime_init
+ fun:xdg_mime_get_mime_type_from_file_name
+ fun:*GetFileMimeTypeE*
+ fun:_ZNK3net16PlatformMimeUtil32GetPlatformMimeTypeFromExtensionERKSsPSs
+ fun:_ZNK3net8MimeUtil30GetMimeTypeFromExtensionHelperERKSsbPSs
+ fun:_ZNK3net8MimeUtil24GetMimeTypeFromExtensionERKSsPSs
+ fun:_ZNK3net8MimeUtil19GetMimeTypeFromFileE*
+ fun:_ZN3net19GetMimeTypeFromFileE*
+}
+{
+ bug_96069
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net9HttpCache13CreateBackendEPPN10disk_cache7BackendEP14CallbackRunnerI6Tuple1IiEE
+ fun:_ZN3net9HttpCache17CreateTransactionEP10scoped_ptrINS_15HttpTransactionEE
+ ...
+ fun:_ZN3net13CookieMonster17CookieMonsterTask14InvokeCallbackEN4base8CallbackIFvvEEE
+}
+{
+ bug_96365
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN27PasswordManagerDelegateImpl33AddSavePasswordInfoBarIfPermittedEP19PasswordFormManager
+ fun:_ZN15PasswordManager23OnPasswordFormsRenderedERKSt6vectorIN6webkit5forms12PasswordFormESaIS3_EE
+}
+{
+ bug_96369
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ fun:g_type_create_instance
+ fun:g_object_constructor
+ fun:g_object_newv
+ fun:g_object_new
+ fun:_gdk_window_impl_new
+ fun:gdk_window_ensure_native
+ fun:gdk_x11_drawable_get_xid
+ fun:_ZN20GtkNativeViewManager14GetIdForWidgetEP10_GtkWidget
+ fun:_ZNK7content23RenderWidgetHostViewGtk15GetNativeViewIdEv
+}
+{
+ bug_96402
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ fun:g_type_create_instance
+ fun:g_object_constructor
+ fun:g_object_newv
+ fun:g_object_new
+ fun:_gdk_window_impl_new
+ fun:gdk_window_ensure_native
+ fun:gdk_x11_drawable_get_xid
+ ...
+ fun:g_closure_invoke
+ fun:signal_emit_unlocked_R
+ fun:g_signal_emit_valist
+ fun:g_signal_emit
+ fun:gtk_widget_realize
+ fun:gtk_widget_set_parent
+}
+{
+ bug_96407
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ fun:g_slice_alloc
+ fun:g_slice_alloc0
+ fun:g_type_create_instance
+ fun:g_object_constructor
+ fun:g_object_newv
+ fun:g_object_new
+ fun:_gdk_window_impl_new
+ fun:gdk_window_ensure_native
+ fun:gdk_x11_drawable_get_xid
+ fun:_ZN19TestWebViewDelegate20CreatePluginDelegateE*
+}
+{
+ bug_96568a
+ Memcheck:Leak
+ fun:*alloc
+ ...
+ fun:HB_OpenType*
+ ...
+ fun:HB_ShapeItem
+ fun:_ZN7WebCore21ComplexTextController11shapeGlyphsEv
+ fun:_ZN7WebCore21ComplexTextController13nextScriptRunEv
+}
+{
+ bug_96568b
+ Memcheck:Leak
+ ...
+ fun:HB_NewFace
+ fun:_ZN7WebCoreL21getCachedHarfbuzzFaceEPNS_16FontPlatformDataE
+ fun:_ZN7WebCore12HarfbuzzFaceC1EPNS_16FontPlatformDataE
+ fun:_ZN7WebCore12HarfbuzzFace6createEPNS_16FontPlatformDataE
+ fun:_ZNK7WebCore16FontPlatformData12harfbuzzFaceEv
+ fun:_ZN7WebCore21ComplexTextController21setupFontForScriptRunEv
+}
+{
+ bug_98568
+ Memcheck:Leak
+ ...
+ fun:_ZN44WebDragDestGtkTest_NoTabContentsWrapper_Test8TestBodyEv
+}
+{
+ bug_98867
+ Memcheck:Jump
+ obj:*
+ obj:*
+ obj:*
+}
+{
+ bug_99304
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN2v88internal10PagedSpace11AllocateRawEi
+ fun:_ZN2v88internal12Deserializer8AllocateEiPNS0_5SpaceEi
+ fun:_ZN2v88internal12Deserializer10ReadObjectEiPNS0_5SpaceEPPNS0_6ObjectE
+ fun:_ZN2v88internal12Deserializer9ReadChunkEPPNS0_6ObjectES4_iPh
+ fun:_ZN2v88internal12Deserializer10ReadObjectEiPNS0_5SpaceEPPNS0_6ObjectE
+ fun:_ZN2v88internal12Deserializer9ReadChunkEPPNS0_6ObjectES4_iPh
+ fun:_ZN2v88internal12Deserializer13VisitPointersEPPNS0_6ObjectES4_
+}
+{
+ bug_99307
+ Memcheck:Uninitialized
+ fun:modp_b64_encode
+ fun:_ZN4base12Base64Encode*
+ fun:_ZN11web_ui_util15GetImageDataUrlERK8SkBitmap
+ fun:_ZN12_GLOBAL__N_121NetworkInfoDictionary8set_iconERK8SkBitmap
+}
+{
+ bug_99308
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZL9toCStringRK9_NPString
+ fun:_ZL15testPostURLFileP12PluginObjectPK10_NPVariantjPS1_
+ fun:_ZL12pluginInvokeP8NPObjectPvPK10_NPVariantjPS2_
+ fun:_ZN7WebCoreL18npObjectInvokeImplERKN2v89ArgumentsENS_18InvokeFunctionTypeE
+}
+{
+ bug_99321
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN6WebKit12CCThreadImpl6createEPNS_9WebThreadE
+ fun:_ZN6WebKit13WebCompositor9setThreadEPNS_9WebThreadE
+ fun:_ZN11WebViewHostC1EP9TestShell
+ fun:_ZN9TestShell15createNewWindowERKN6WebKit6WebURLEP16DRTDevToolsAgent
+}
+{
+ bug_99435
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base19MessagePumpLibevent3RunEPNS_11MessagePump8DelegateE
+ fun:_ZN4base11MessageLoop11RunInternalEv
+ fun:_ZN4base11MessageLoop10RunHandlerEv
+}
+{
+ bug_100043
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIN6webkit13WebPluginInfoEE8allocateEjPKv
+ ...
+ fun:_ZNSt6vectorIN6webkit13WebPluginInfoESaIS1*
+}
+{
+ bug_101125a
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN6SkScan12AntiFillPathERK6SkPathRK8SkRegionP9SkBlitterb
+ fun:_ZN6SkScan12AntiFillPathERK6SkPathRK12SkRasterClipP9SkBlitter
+ fun:_ZNK6SkDraw8drawPathERK6SkPathRK7SkPaintPK8SkMatrixb
+ fun:_ZN8SkDevice8drawPathERK6SkDrawRK6SkPathRK7SkPaintPK8SkMatrixb
+ fun:_ZNK6SkDraw14drawTextOnPathEPKcmRK6SkPathPK8SkMatrixRK7SkPaint
+ fun:_ZN8SkDevice14drawTextOnPathERK6SkDrawPKvmRK6SkPathPK8SkMatrixRK7SkPaint
+ fun:_ZN8SkCanvas14drawTextOnPathEPKvmRK6SkPathPK8SkMatrixRK7SkPaint
+ fun:_ZNK7WebCore4Font10drawGlyphsEPNS_15GraphicsContextEPKNS_14SimpleFontDataERKNS_11GlyphBufferEiiRKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font15drawGlyphBufferEPNS_15GraphicsContextERKNS_7TextRunERKNS_11GlyphBufferERKNS_10FloatPointE
+}
+{
+ bug_101125b
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN6SkScan12AntiFillRectERK6SkRectPK8SkRegionP9SkBlitter
+ fun:_ZN6SkScan12AntiFillRectERK6SkRectRK12SkRasterClipP9SkBlitter
+ fun:_ZNK6SkDraw8drawRectERK6SkRectRK7SkPaint
+ fun:_ZN8SkDevice8drawRectERK6SkDrawRK6SkRectRK7SkPaint
+ fun:_ZN8SkCanvas8drawRectERK6SkRectRK7SkPaint
+ fun:_ZN7WebCore15GraphicsContext8fillRectERKNS_9FloatRectERKNS_5ColorENS_10ColorSpaceE
+ fun:_ZN7WebCore15GraphicsContext20drawHighlightForTextERKNS_4FontERKNS_7TextRunERKNS_10FloatPointEiRKNS_5ColorENS_10ColorSpaceEii
+}
+{
+ bug_101125c
+ Memcheck:Uninitialized
+ ...
+ fun:_ZL11morphpointsP7SkPointPKS_iR13SkPathMeasureRK8SkMatrix
+ fun:_ZL9morphpathP6SkPathRKS_R13SkPathMeasureRK8SkMatrix
+ fun:_ZNK6SkDraw14drawTextOnPathEPKcmRK6SkPathPK8SkMatrixRK7SkPaint
+ fun:_ZN8SkDevice14drawTextOnPathERK6SkDrawPKvmRK6SkPathPK8SkMatrixRK7SkPaint
+ fun:_ZN8SkCanvas14drawTextOnPathEPKvmRK6SkPathPK8SkMatrixRK7SkPaint
+ fun:_ZNK7WebCore4Font10drawGlyphsEPNS_15GraphicsContextEPKNS_14SimpleFontDataERKNS_11GlyphBufferEiiRKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font15drawGlyphBufferEPNS_15GraphicsContextERKNS_7TextRunERKNS_11GlyphBufferERKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font14drawSimpleTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZNK7WebCore4Font8drawTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZN7WebCore15GraphicsContext8drawTextERKNS_4FontERKNS_7TextRunERKNS_10FloatPointEii
+}
+{
+ bug_100133
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_Z22RecoveryRegisterHelperP22ComponentUpdateServiceP11PrefService
+}
+{
+ bug_100330
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN25TestingAutomationProvider42NavigateToURLBlockUntilNavigationsCompleteEiRK4GURLiPN3IPC7MessageE
+}
+{
+ bug_100647
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN18WebResourceService19UpdateResourceCacheERKSs
+ fun:_ZN18WebResourceService18WebResourceFetcher18OnURLFetchCompleteEPK10URLFetcherRK4GURLRKN3net16URLRequestStatusEiRKSt6vectorISsSaISsEERKSs
+ fun:_ZN10URLFetcher8Delegate18OnURLFetchCompleteEPKS_
+ fun:_ZN10URLFetcher4Core29InformDelegateFetchIsCompleteEv
+ fun:_ZN10URLFetcher4Core21OnCompletedURLRequestEN4base9TimeDeltaE
+}
+{
+ bug_100777
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12_GLOBAL__N_119MakeContextDelegateI16CrxUpdateServiceNS1_13UpdateContextEEEPN7content18URLFetcherDelegateEPT_PT0_
+ fun:_ZN16CrxUpdateService19ProcessPendingItemsEv
+}
+{
+ bug_100916
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN6WebKit19WebWorkerClientImpl24createWorkerContextProxyEPN7WebCore6WorkerE
+ ...
+ fun:_ZN7WebCore6WorkerC1EPNS_22ScriptExecutionContextE
+ fun:_ZN7WebCore6Worker6createEPNS_22ScriptExecutionContextERKN3WTF6StringERi
+ fun:_ZN7WebCore8V8Worker19constructorCallbackERKN2v89ArgumentsE
+ fun:_ZN2v88internalL19HandleApiCallHelperILb1EEEPNS0_11MaybeObjectENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+}
+{
+ bug_100982
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore12RenderRegion22setRenderBoxRegionInfoEPKNS_9RenderBoxEiib
+ fun:_ZNK7WebCore9RenderBox19renderBoxRegionInfoEPNS_12RenderRegionEiNS0_24RenderBoxRegionInfoFlagsE
+ ...
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_8IntPointE
+}
+{
+ bug_101145a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2v88internal2OS15CreateSemaphoreEi
+ fun:_ZN2v88internal8ProfilerC1EPNS0_7IsolateE
+ fun:_ZN2v88internal6Logger5SetUpEv
+ fun:_ZN2v88internal7Isolate4InitEPNS0_12DeserializerE
+ ...
+ fun:_ZN7WebCore27WorkerContextExecutionProxy8evaluateERKN3WTF6StringES4_RKNS1_12TextPositionEPNS_27WorkerContextExecutionStateE
+}
+{
+ bug_101145b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF6StringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ fun:_ZN7WebCore16V8StringResourceILNS_20V8StringResourceMode*
+}
+{
+ bug_101145c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore*makeExternalString*
+ ...
+ fun:_ZN7WebCore11StringCache20v8ExternalStringSlow*
+ fun:_ZN7WebCore11StringCache16v8ExternalStringEPN*
+}
+{
+ bug_101146d
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11webkit_glue16WebURLLoaderImplC1EPNS_25WebKitPlatformSupportImplE
+ fun:_ZN11webkit_glue25WebKitPlatformSupportImpl15createURLLoaderEv
+}
+{
+ bug_101151
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF*StringEEET_*
+ fun:_ZN7WebCore15V8ParameterBase8toStringIN3WTF*StringEEET_*
+ fun:_ZN7WebCore15V8ParameterBasecvN3WTF*StringEEv
+ ...
+ fun:_ZN2v88internalL*HandleApiCall*
+ obj:*
+}
+{
+ bug_101159
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore15NPObjectWrapper10NPAllocateEP4_NPPP7NPClass
+ fun:_NPN_CreateObject
+ fun:_ZN7WebCore15NPObjectWrapper6createEP8NPObject
+ fun:_ZN7WebCore16ScriptController20windowScriptNPObjectEv
+ fun:_ZNK6WebKit12WebFrameImpl12windowObjectEv
+ fun:_ZN6webkit5npapi13WebPluginImpl23GetWindowScriptNPObjectEv
+ fun:NPN_GetValue
+}
+{
+ bug_101345
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN22WebPluginDelegateProxy20CreateResourceClientEmRK4GURLi
+ fun:_ZN6webkit5npapi13WebPluginImpl24HandleURLRequestInternalEPKcS3_S3_S3_jibNS1_8ReferrerEbb
+}
+{
+ bug_101347
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2pp25CompletionCallbackFactoryIN5ppapi5proxy20PPB_Graphics2D_ProxyENS2_26ProxyNonThreadSafeRefCountEE17NewCallbackHelperINS5_11Dispatcher1IMS3_FviRKNS1_12HostResourceEES8_EEEENS_18CompletionCallbackERKT_
+ fun:_ZN2pp25CompletionCallbackFactoryIN5ppapi5proxy20PPB_Graphics2D_ProxyENS2_26ProxyNonThreadSafeRefCountEE11NewCallbackIMS3_FviRKNS1_12HostResourceEES7_EENS_18CompletionCallbackET_RKT0_
+ fun:_ZN2pp25CompletionCallbackFactoryIN5ppapi5proxy20PPB_Graphics2D_ProxyENS2_26ProxyNonThreadSafeRefCountEE19NewOptionalCallbackIMS3_FviRKNS1_12HostResourceEES7_EENS_18CompletionCallbackET_RKT0_
+ fun:_ZN5ppapi5proxy38EnterHostFromHostResourceForceCallbackINS_5thunk18PPB_Graphics2D_APIEEC1IN2pp25CompletionCallbackFactoryINS0_20PPB_Graphics2D_ProxyENS0_26ProxyNonThreadSafeRefCountEEEMS8_FviRKNS_12HostResourceEESB_EESD_RT_T0_RKT1_
+ fun:_ZN5ppapi5proxy20PPB_Graphics2D_Proxy10OnMsgFlushERKNS_12HostResourceE
+}
+{
+ bug_101470
+ Memcheck:Param
+ write(buf)
+ obj:/lib/x86_64-linux-gnu/libc-2.15.so
+ ...
+ fun:new_do_write
+ ...
+ fun:_ZNK13safe_browsing9PrefixSet9WriteFileE*
+}
+{
+ bug_101750
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEj
+ fun:_ZN3WTF7HashSetIPN7WebCore16SVGStyledElementENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEEnwEj
+ fun:_ZN7WebCore21SVGDocumentExtensions18addPendingResourceERKN3WTF12AtomicStringEPNS_16SVGStyledElementE
+}
+{
+ bug_101751
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore14SVGFontElement6createERKNS_13QualifiedNameEPNS_8DocumentE
+ fun:_ZN7WebCoreL15fontConstructorERKNS_13QualifiedNameEPNS_8DocumentEb
+ fun:_ZN7WebCore17SVGElementFactory16createSVGElementERKNS_13QualifiedNameEPNS_8DocumentEb
+ fun:_ZN7WebCore8Document13createElementERKNS_13QualifiedNameEb
+}
+{
+ bug_101781
+ Memcheck:Uninitialized
+ fun:encode_one_block
+ fun:encode_mcu_huff
+ fun:compress_data
+ fun:process_data_simple_main
+ fun:chromium_jpeg_write_scanlines
+ fun:_ZN3gfx9JPEGCodec6EncodeEPKhNS0_11ColorFormatEiiiiPSt6vectorIhSaIhEE
+ fun:_ZN3gfx24JPEGEncodedDataFromImageERKNS_5ImageE?PSt6vectorIhSaIhEE
+ fun:_ZN7history8TopSites12EncodeBitmapE*N3gfx5ImageEP13scoped_refptrIN4base15RefCountedBytesEE
+ fun:_ZN7history8TopSites16SetPageThumbnailERK4GURL*N3gfx5ImageERK14ThumbnailScore
+ fun:_ZN7history17ExpireHistoryTest14AddExampleDataEP?PN4base4TimeE
+ fun:_ZN7history*ExpireHistoryTest_*
+}
+{
+ bug_101781_d
+ Memcheck:Uninitialized
+ fun:_ZN7testing8internal11CmpHelperGEIddEENS_15AssertionResultEPKcS4_RKT_RKT0_
+ fun:_ZN3gfx31JPEGCodec_EncodeDecodeRGBA_Test8TestBodyEv
+}
+{
+ bug_102257
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+ fun:_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb
+}
+{
+ bug_102327a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN15tracked_objects10ThreadData10InitializeEv
+ fun:_ZN15tracked_objects10ThreadData30InitializeAndSetTrackingStatusEb
+ fun:_ZN15tracked_objects10ThreadData29ShutdownSingleThreadedCleanupEb
+}
+{
+ bug_102327b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKPKN15tracked_objects6BirthsENS3_9DeathDataEEEE8allocateE*
+ ...
+ fun:_ZNSt3mapIPKN15tracked_objects6BirthsENS0_9DeathDataESt4lessIS3_ESaISt4pairIKS3_S4_EEE6insertESt17_Rb_tree_iteratorIS9_ERKS9_
+ fun:_ZNSt3mapIPKN15tracked_objects6BirthsENS0_9DeathDataESt4lessIS3_ESaISt4pairIKS3_S4_EEEixERS8_
+ fun:_ZN15tracked_objects10ThreadData11TallyADeathERKNS_6Births*
+ fun:_ZN15tracked_objects10ThreadData3?TallyRun*IfTrackingE*
+}
+{
+ bug_102327c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN15tracked_objects10ThreadData11TallyABirthERKNS_8LocationE
+ fun:_ZN15tracked_objects10ThreadData19TallyABirthIfActiveERKNS_8LocationE
+}
+{
+ bug_102327d
+ Memcheck:Uninitialized
+ fun:_ZN15tracked_objects9DeathData11RecordDeathEiii
+ fun:_ZN15tracked_objects10ThreadData11TallyADeathERKNS_6BirthsEii
+ fun:_ZN15tracked_objects10ThreadData31TallyRunOnNamedThreadIfTrackingERKN4base12TrackingInfoERKNS_11TrackedTimeES7_
+}
+{
+ Intentional leak of stl map during thread cleanup in profiler
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNK15tracked_objects10ThreadData26OnThreadTerminationCleanupEv
+}
+{
+ bug_102614
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12*FinishPepperFlashUpdateRegistrationEP22ComponentUpdateServiceRK7Version
+}
+{
+ bug_102831_a
+ Memcheck:Leak
+ ...
+ fun:_ZN17PluginLoaderPosix19LoadPluginsInternalEv
+}
+{
+ bug_104447
+ Memcheck:Leak
+ ...
+ fun:HB_OpenTypeShape
+ fun:arabicSyriacOpenTypeShape
+ fun:HB_ArabicShape
+ fun:HB_ShapeItem
+ fun:_ZN7WebCore21ComplexTextController11shapeGlyphsEv
+ fun:_ZN7WebCore21ComplexTextController13nextScriptRunEv
+ fun:_ZN7WebCore21ComplexTextController14widthOfFullRunEv
+ fun:_ZNK7WebCore4Font24floatWidthForComplexTextERKNS_7TextRunEPN3WTF7HashSetIPKNS_14SimpleFontDataENS4_7PtrHashIS8_EENS4_10HashTraitsIS8_EEEEPNS_13GlyphOverflowE
+ fun:_ZNK7WebCore4Font5widthERKNS_7TextRunERiRN3WTF6StringE
+ fun:_ZN7WebCore14SVGTextMetricsC1EPNS_19RenderSVGInlineTextERKNS_7TextRunE
+ fun:_ZN7WebCore14SVGTextMetrics21measureCharacterRangeEPNS_19RenderSVGInlineTextEjj
+ fun:_ZNK7WebCore30SVGTextLayoutAttributesBuilder25propagateLayoutAttributesEPNS_12RenderObjectERN3WTF6VectorINS_23SVGTextLayoutAttributesELm0EEERjRt
+}
+{
+ # ProcessSingleton::LinuxWatcher is marked DeleteOnIOThread. Sometimes it
+ # leaks on shutdown instead of getting deleted. The destructor doesn't do
+ # anything important, so this shouldn't be a big deal.
+ bug_104578
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN16ProcessSingletonC1E*
+ fun:_ZN22ChromeProcessSingletonC1E*
+}
+{
+ bug_104806_a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN15tracked_objects10ThreadData19TallyABirthIfActiveERKNS_8LocationE
+ fun:_ZN4base12TrackingInfoC?ERKN15tracked_objects8LocationENS_9TimeTicksE
+}
+{
+ bug_104806_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZNSt3mapIPKN15tracked_objects6BirthsENS0_9DeathDataESt4lessIS3_ESaISt4pairIKS3_S4_EEEixERS8_
+ fun:_ZN15tracked_objects10ThreadData11TallyADeathERKNS_6BirthsEii
+ fun:_ZN15tracked_objects10ThreadData32TallyRunOnWorkerThreadIfTrackingEPKNS_6BirthsERKNS_11TrackedTimeES6_S6_
+}
+{
+ bug_105715
+ Memcheck:Uninitialized
+ ...
+ fun:vfprintf
+ fun:__vsnprintf_chk
+ fun:_ZN4base9vsnprintfEPcjPKcS0_
+ fun:_ZN4base12_GLOBAL__N_110vsnprintfTEPcjPKcS1_
+ fun:_ZN4base12_GLOBAL__N_1L14StringAppendVTISsEEvPT_PKNS2_10value_typeEPc
+ fun:_ZN4base13StringAppendVEPSsPKcPc
+ fun:_ZN4base13StringAppendFEPSsPKcz
+ fun:_ZN4base10JSONWriter15BuildJSONStringEPKNS_5ValueEibb
+ fun:_ZN4base10JSONWriter15BuildJSONStringEPKNS_5ValueEibb
+ fun:_ZN4base10JSONWriter15BuildJSONStringEPKNS_5ValueEibb
+ fun:_ZN4base10JSONWriter15BuildJSONStringEPKNS_5ValueEibb
+ fun:_ZN4base10JSONWriter16WriteWithOptionsEPKNS_5ValueEbiPSs
+ fun:_ZN25JSONStringValueSerializer17SerializeInternalERKN4base5ValueEb
+ fun:_ZN25JSONStringValueSerializer9SerializeERKN4base5ValueE
+ fun:_ZN18jstemplate_builder12AppendJsonJSEPKN4base15DictionaryValueEPSs
+ fun:_ZN19OptionsUIHTMLSource16StartDataRequestERKSsbi
+ fun:_ZN4base8internal15RunnableAdapterIMN20ChromeURLDataManager10DataSourceEFvRKSsbiEE3RunEPS3_S5_RKbRKi
+ fun:_ZN4base8internal12InvokeHelperILb0EvNS0_15RunnableAdapterIMN20ChromeURLDataManager10DataSourceEFvRKSsbiEEEFvRKPS4_S6_RKbRKiEE8MakeItSoES9_SC_S6_SE_SG_
+ fun:_ZN4base8internal7InvokerILi4ENS0_9BindStateINS0_15RunnableAdapterIMN20ChromeURLDataManager10DataSourceEFvRKSsbiEEEFvPS5_S7_biEFvSB_SsbiEEESC_E3RunEPNS0_13BindStateBaseE
+ fun:_ZNK4base8CallbackIFvvEE3RunEv
+}
+{
+ bug_105744b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZNSt6vector*9push_back*
+ fun:_ZN4skia19ConvolutionFilter1D9AddFilterEiPKsi
+ fun:_ZN4skia12_GLOBAL__N_112ResizeFilter14ComputeFiltersEiiiffPNS_19ConvolutionFilter1DE
+ fun:_ZN4skia12_GLOBAL__N_112ResizeFilterC1ENS_15ImageOperations12ResizeMethodEiiiiRK7SkIRect
+ fun:_ZN4skia15ImageOperations11ResizeBasicERK8SkBitmapNS0_12ResizeMethodEiiRK7SkIRect
+ fun:_ZN4skia15ImageOperations6ResizeERK8SkBitmapNS0_12ResizeMethodEiiRK7SkIRect
+ fun:_ZN4skia15ImageOperations6ResizeERK8SkBitmapNS0_12ResizeMethodEii
+ fun:_ZN24ChromeRenderViewObserver21CaptureFrameThumbnailEPN6WebKit7WebViewEiiP8SkBitmapP14ThumbnailScore
+ fun:_ZN24ChromeRenderViewObserver16CaptureThumbnailEv
+ fun:_ZN24ChromeRenderViewObserver15CapturePageInfoEib
+}
+{
+ bug_105907
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN4skia14BGRAConvolve2DEPKhibRKNS_19ConvolutionFilter1DES4_iPhb
+ fun:_ZN4skia15ImageOperations11ResizeBasicE*
+ fun:_ZN4skia15ImageOperations6ResizeE*
+}
+{
+ bug_106183a
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore13RenderMarquee18updateMarqueeStyleEv
+ fun:_ZN7WebCore11RenderLayer12styleChangedENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore20RenderBoxModelObject14styleDidChangeENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore9RenderBox14styleDidChangeENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore11RenderBlock14styleDidChangeENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore12RenderObject8setStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE
+}
+{
+ bug_106183b
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore21ComplexTextController*
+ ...
+ fun:_ZNK7WebCore4Font27selectionRectForComplexTextERKNS_7TextRunERKNS_10FloatPointEiii
+ fun:_ZNK7WebCore4Font20selectionRectForTextERKNS_7TextRunERKNS_10FloatPointEiii
+ fun:_ZNK7WebCore13InlineTextBox17positionForOffsetEi
+ fun:_ZN7WebCore10RenderText14localCaretRectEPNS_9InlineBoxEiPi
+ fun:_ZNK7WebCore15VisiblePosition14localCaretRectERPNS_12RenderObjectE
+ fun:_ZN7WebCore9CaretBase15updateCaretRectEPNS_8DocumentERKNS_15VisiblePositionE
+ fun:_ZN7WebCore14FrameSelection14localCaretRectEv
+ fun:_ZN7WebCore14FrameSelection18recomputeCaretRectEv
+ fun:_ZN7WebCore14FrameSelection16updateAppearanceEv
+}
+{
+ bug_106183c
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore21ComplexTextController*
+ ...
+ fun:_ZNK7WebCore4Font15drawComplexTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZNK7WebCore4Font8drawTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZN7WebCore15GraphicsContext8drawTextERKNS_4FontERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZN7WebCoreL20paintTextWithShadowsEPNS_15GraphicsContextERKNS_4FontERKNS_7TextRunERKN3WTF12AtomicStringEiiiiRKNS_10FloatPointERKNS_9FloatRectEPKNS_10ShadowDataEbb
+ ...
+ fun:_ZNK7WebCore17RenderLineBoxList5paintEPNS_20RenderBoxModelObjectERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock13paintContentsERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_8IntPointE
+}
+{
+ bug_106402
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2pp25CompletionCallbackFactoryIN5ppapi5proxy20PPB_Graphics2D_ProxyENS2_26ProxyNonThreadSafeRefCountEE17NewCallbackHelperINS5_11Dispatcher1IMS3_FviRKNS1_12HostResourceEES8_EEEENS_18CompletionCallbackERKT_
+ fun:_ZN2pp25CompletionCallbackFactoryIN5ppapi5proxy20PPB_Graphics2D_ProxyENS2_26ProxyNonThreadSafeRefCountEE11NewCallbackIMS3_FviRKNS1_12HostResourceEES7_EENS_18CompletionCallbackET_RKT0_
+ fun:_ZN2pp25CompletionCallbackFactoryIN5ppapi5proxy20PPB_Graphics2D_ProxyENS2_26ProxyNonThreadSafeRefCountEE19NewOptionalCallbackIMS3_FviRKNS1_12HostResourceEES7_EENS_18CompletionCallbackET_RKT0_
+ fun:_ZN5ppapi5proxy38EnterHostFromHostResourceForceCallbackINS_5thunk18PPB_Graphics2D_APIEEC1IN2pp25CompletionCallbackFactoryINS0_20PPB_Graphics2D_ProxyENS0_26ProxyNonThreadSafeRefCountEEEMS8_FviRKNS_12HostResourceEESB_EESD_RT_T0_RKT1_
+ fun:_ZN5ppapi5proxy20PPB_Graphics2D_Proxy14OnHostMsgFlushERKNS_12HostResourceE
+}
+{
+ bug_106552
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN25JSONStringValueSerializer17SerializeInternalERKN4base5ValueEb
+ fun:_ZN25JSONStringValueSerializer9SerializeERKN4base5ValueE
+ fun:_ZN13JsonPrefStore13SerializeDataEPSs
+ fun:_ZN19ImportantFileWriter16DoScheduledWriteEv
+ fun:_ZN13JsonPrefStore18CommitPendingWriteEv
+ fun:_ZN13JsonPrefStoreD0Ev
+ fun:_ZNK4base10RefCountedI9PrefStoreE7ReleaseEv
+ fun:_ZN13scoped_refptrI19PersistentPrefStoreEaSEPS0_
+ fun:_ZN11PrefServiceD0Ev
+ fun:_ZN10scoped_ptrI11PrefServiceED1Ev
+ fun:_ZN14TestingProfileD2Ev
+ fun:_ZN23ExtensionTestingProfileD0Ev
+}
+{
+ bug_106912
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN15tracked_objects10ThreadData23InitializeThreadContextERKSs
+ fun:_ZN4base14PlatformThread7SetNameEPKc
+}
+{
+ bug_107696
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore11iBeamCursorEv
+ fun:_ZN7WebCore12EventHandler12selectCursorERKNS_28MouseEventWithHitTestResultsEPNS_9ScrollbarE
+ fun:_ZN7WebCore12EventHandler20handleMouseMoveEventERKNS_18PlatformMouseEventEPNS_13HitTestResultEb
+ fun:_ZN7WebCore12EventHandler10mouseMovedERKNS_18PlatformMouseEventEb
+ fun:_ZN6WebKit11WebViewImpl9mouseMoveERKNS_13WebMouseEventE
+ fun:_ZN6WebKit11WebViewImpl16handleInputEventERKNS_13WebInputEventE
+ fun:_ZN12RenderWidget18OnHandleInputEventERKN3IPC7MessageE
+}
+{
+ bug_107699
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ ...
+ fun:_ZN7WebCore13AnimationBase17ensurePropertyMapEv
+ fun:_ZN7WebCore13AnimationBase16getNumPropertiesEv
+ fun:_ZN7WebCore18CompositeAnimation17updateTransitionsEPNS_12RenderObjectEPNS_11RenderStyleES4_
+ fun:_ZN7WebCore18CompositeAnimation7animateEPNS_12RenderObjectEPNS_11RenderStyleES4_
+ fun:_ZN7WebCore19AnimationController16updateAnimationsEPNS_12RenderObjectEPNS_11RenderStyleE
+ fun:_ZN7WebCore12RenderObject18setAnimatableStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE
+ fun:_ZN7WebCore4Node14setRenderStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE
+ ...
+ fun:_ZN7WebCore7Element11recalcStyleENS_4Node11StyleChangeE
+ fun:_ZN7WebCore8Document11recalcStyleENS_4Node11StyleChangeE
+ fun:_ZN7WebCore8Document19updateStyleIfNeededEv
+ fun:_ZN7WebCore8Document12updateLayoutEv
+ fun:_ZN7WebCore8Document36updateLayoutIgnorePendingStylesheetsEv
+}
+{
+ bug_108146a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN5ppapi5proxy26PPP_Instance_Private_Proxy22OnMsgGetInstanceObjectEiNS0_24SerializedVarReturnValueE
+}
+{
+ bug_108146b
+ Memcheck:Param
+ write(buf)
+ obj:/lib/tls/i686/cmov/libpthread-2.11.1.so
+ fun:_ZN3IPC7Channel11ChannelImpl4SendEPNS_7MessageE
+ fun:_ZN3IPC7Channel4SendEPNS_7MessageE
+ fun:_ZN3IPC12ChannelProxy7Context13OnSendMessageEPNS_7MessageE
+ fun:_ZN3IPC18SendCallbackHelper4SendEv
+}
+{
+ bug_108147
+ Memcheck:Uninitialized
+ ...
+ fun:_ZNK6SkDraw11drawPosTextEPKcmPKffiRK7SkPaint
+ fun:_ZN8SkDevice11drawPosTextERK6SkDrawPKvmPKffiRK7SkPaint
+ fun:_ZN8SkCanvas11drawPosTextEPKvmPK7SkPointRK7SkPaint
+ fun:_ZNK7WebCore4Font10drawGlyphsEPNS_15GraphicsContextEPKNS_14SimpleFontDataERKNS_11GlyphBufferEiiRKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font15drawGlyphBufferEPNS_15GraphicsContextERKNS_7TextRunERKNS_11GlyphBufferERKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font14drawSimpleTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZNK7WebCore4Font8drawTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+}
+{
+ bug_108620
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore13PlatformEventC2ENS0_4TypeEbbbbd
+ fun:_ZN7WebCore18PlatformMouseEventC1ERKNS_8IntPointES3_NS_11MouseButtonENS_13PlatformEvent4TypeEibbbbd
+ fun:_ZN7WebCore12EventHandler28fakeMouseMoveEventTimerFiredEPNS_5TimerIS0_EE
+ fun:_ZN7WebCore5TimerINS_12EventHandlerEE5firedEv
+ fun:_ZN7WebCore12ThreadTimers24sharedTimerFiredInternalEv
+ fun:_ZN7WebCore12ThreadTimers16sharedTimerFiredEv
+ fun:_ZN11webkit_glue25WebKitPlatformSupportImpl9DoTimeoutEv
+ fun:_ZN4base9BaseTimerIN11webkit_glue25WebKitPlatformSupportImplELb0EE9TimerTask3RunEv
+}
+{
+ bug_108621
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10RefCountedIN7WebCore5EventEEnwEm
+ fun:_ZN7WebCore12MessageEvent6createEN3WTF10PassOwnPtrINS1_6VectorINS1_6RefPtrINS_11MessagePortEEELm1EEEEENS1_10PassRefPtrINS_21SerializedScriptValueEEERKNS1_6StringESE_NS9_INS_9DOMWindowEEE
+ fun:_ZN7WebCore16PostMessageTimer5eventEPNS_22ScriptExecutionContextE
+ fun:_ZN7WebCore9DOMWindow21postMessageTimerFiredEN3WTF10PassOwnPtrINS_16PostMessageTimerEEE
+ fun:_ZN7WebCore16PostMessageTimer5firedEv
+ fun:_ZN7WebCore12ThreadTimers24sharedTimerFiredInternalEv
+ fun:_ZN7WebCore12ThreadTimers16sharedTimerFiredEv
+ fun:_ZN11webkit_glue25WebKitPlatformSupportImpl9DoTimeoutEv
+ fun:_ZN4base9BaseTimerIN11webkit_glue25WebKitPlatformSupportImplELb0EE9TimerTask3RunEv
+}
+{
+ bug_108622
+ Memcheck:Leak
+ fun:_Zna*
+ fun:_ZN2v88internal8NewArrayIhEEPT*
+ fun:_ZN2v88internal11RegExpStack14EnsureCapacityEm
+ fun:_ZN2v88internal16RegExpStackScopeC1EPNS0_7IsolateE
+ fun:_ZN2v88internal26NativeRegExpMacroAssembler7ExecuteEPNS0_4CodeEPNS0_6String*
+ fun:_ZN2v88internal26NativeRegExpMacroAssembler5MatchENS0_6HandleINS0_4CodeEEENS2_INS0_6StringEEEPiiiPNS0_7IsolateE
+ fun:_ZN2v88internal10RegExpImpl*IrregexpExec*ENS0_6HandleINS0_8JSRegExpEEENS2_INS0_6StringEEEiPii
+}
+{
+ bug_108624
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF6StringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ fun:_ZN7WebCore15V8ParameterBase8toStringIN3WTF6StringEEET_v
+ fun:_ZN7WebCore15V8ParameterBasecvN3WTF6StringEEv
+ ...
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+ fun:_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb
+ fun:_ZN2v88Function4CallENS_6HandleINS_6ObjectEEEiPNS1_INS_5ValueEEE
+ fun:_ZN7WebCore28V8WorkerContextEventListener20callListenerFunctionEPNS_22ScriptExecutionContextEN2v86HandleINS3_5ValueEEEPNS_5EventE
+ fun:_ZN7WebCore23V8AbstractEventListener18invokeEventHandlerEPNS_22ScriptExecutionContextEPNS_5EventEN2v86HandleINS5_5ValueEEE
+ fun:_ZN7WebCore28V8WorkerContextEventListener11handleEventEPNS_22ScriptExecutionContextEPNS_5EventE
+ fun:_ZN7WebCore11EventTarget18fireEventListenersEPNS_5EventEPNS_15EventTargetDataERN3WTF6VectorINS_23RegisteredEventListenerELm1EEE
+}
+{
+ bug_108624a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF6StringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ fun:_ZN7WebCore15V8ParameterBase8toStringIN3WTF6StringEEET_v
+ fun:_ZN7WebCore15V8ParameterBasecvN3WTF6StringEEv
+ fun:_ZN7WebCore25WebKitBlobBuilderInternal*
+}
+{
+ bug_108628
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF12AtomicStringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ fun:_ZN7WebCore16V8StringResourceILNS_20V8StringResourceModeE0EE8toStringIN3WTF12AtomicStringEEET_v
+ fun:_ZN7WebCore16V8StringResourceILNS_20V8StringResourceModeE0EEcvN3WTF12AtomicStringEEv
+ ...
+ fun:_ZN7WebCore24XMLHttpRequestV8Internal*
+ fun:_ZN2v88internalL19HandleApiCallHelperILb0EEEPNS0_11MaybeObjectENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+}
+{
+ bug_109495e
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt10_List_nodeIPN3gpu5gles219VertexAttribManager16VertexAttribInfoEEE8allocateEmPKv
+ fun:_ZNSt10_List_baseIPN3gpu5gles219VertexAttribManager16VertexAttribInfoESaIS4_EE11_M_get_nodeEv
+ fun:_ZNSt4listIPN3gpu5gles219VertexAttribManager16VertexAttribInfoESaIS4_EE14_M_create_nodeERKS4_
+ fun:_ZNSt4listIPN3gpu5gles219VertexAttribManager16VertexAttribInfoESaIS4_EE6insertESt14_List_iteratorIS4_ERKS4_
+ fun:_ZN3gpu5gles219VertexAttribManager16VertexAttribInfo7SetListEPSt4listIPS2_SaIS4_EE
+ fun:_ZN3gpu5gles219VertexAttribManager10InitializeEj
+ fun:_ZN3gpu5gles216GLES2DecoderImpl10Initialize*
+ fun:_ZN6webkit3gpu18GLInProcessContext10InitializeERKN3gfx4SizeEPS1_PKcPKiNS2_13GpuPreferenceE
+ fun:_ZN6webkit3gpu18GLInProcessContext22CreateOffscreenContextEPS1_RKN3gfx4SizeES2_PKcPKiNS3_13GpuPreferenceE
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl10InitializeEN6WebKit20WebGraphicsContext3D10AttributesEPS3_
+}
+{
+ bug_109495f
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN6webkit3gpu18GLInProcessContext22CreateOffscreenContextEPS1_RKN3gfx4SizeES2_PKcPKiNS3_13GpuPreferenceE
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl10InitializeEN6WebKit20WebGraphicsContext3D10AttributesEPS3_
+ fun:_ZN25TestWebKitPlatformSupport32createOffscreenGraphicsContext3DERKN6WebKit20WebGraphicsContext3D10AttributesE
+ fun:_ZN7WebCore17GraphicsContext3D6createENS0_10AttributesEPNS_10HostWindowENS0_11RenderStyleE
+ fun:_ZN7WebCore21WebGLRenderingContext6createEPNS_17HTMLCanvasElementEPNS_22WebGLContextAttributesE
+ fun:_ZN7WebCore17HTMLCanvasElement10getContextERKN3WTF6StringEPNS_23CanvasContextAttributesE
+ fun:_ZN7WebCore19V8HTMLCanvasElement18getContextCallbackERKN2v89ArgumentsE
+}
+{
+ bug_109496
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN7WebCore11ImageBuffer27platformTransformColorSpaceERKN3WTF6VectorIiLm0EEE
+ fun:_ZN7WebCore11ImageBuffer19transformColorSpaceENS_10ColorSpaceES1_
+ fun:_ZN7WebCore23RenderSVGResourceFilter17postApplyResourceEPNS_12RenderObjectERPNS_15GraphicsContextEtPKNS_4PathEPKNS_14RenderSVGShapeE
+ ...
+ fun:_ZN7WebCore14RenderSVGShape5paintERNS_9PaintInfoERKNS_*
+ ...
+ fun:_ZN7WebCore13RenderSVGRoot*paint*PaintInfoERKNS_*
+}
+{
+ bug_109872
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN18BrowserProcessImpl29ResourceDispatcherHostCreatedEv
+ fun:_ZN6chrome26ChromeContentBrowserClient29ResourceDispatcherHostCreatedEv
+ fun:_ZN22ResourceDispatcherHost*
+ ...
+ fun:_ZN7content15BrowserMainLoop21BrowserThreadsStartedEv
+ fun:_ZN7content15BrowserMainLoop*
+ ...
+ fun:_Z11BrowserMainRKN7content18MainFunctionParamsE
+}
+{
+ bug_110734
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN15StartupTimeBomb3ArmERKN4base9TimeDeltaE
+ fun:_ZN22ChromeBrowserMainParts25PreMainMessageLoopRunImplEv
+}
+{
+ bug_111186
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11leveldb_*ChromiumEnv11StartThread*
+ fun:_ZN11leveldb_*ChromiumEnv8Schedule*
+ fun:_ZN7leveldb6DBImpl23MaybeScheduleCompactionEv
+ fun:_ZN7leveldb6DBImpl16MakeRoomForWriteEb
+ fun:_ZN7leveldb6DBImpl5WriteERKNS_12WriteOptionsEPNS_10WriteBatchE
+ fun:_ZN17LeveldbValueStore9WriteToDbEPN7leveldb10WriteBatchE
+ fun:_ZN17LeveldbValueStore3SetEiRKSsRKN4base5ValueE
+ fun:_ZN10extensions28SettingsStorageQuotaEnforcer3SetEiRKSsRKN4base5ValueE
+ fun:_ZN10extensions23SyncableSettingsStorage3SetEiRKSsRKN4base5ValueE
+}
+{
+ bug_111341
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN7WebCore17ClipboardChromiumnwEm
+ fun:_ZN7WebCore17ClipboardChromium6createENS_9Clipboard13ClipboardTypeEN3WTF10PassRefPtrINS_18ChromiumDataObjectEEENS_21ClipboardAccessPolicyEPNS_5FrameE
+}
+{
+ bug_111669
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN8appcache17AppCacheDiskCache10ActiveCall17OnAsyncCompletionEi
+}
+{
+ bug_112278
+ Memcheck:Uninitialized
+ fun:fetch_texel_2d_f_rgba8888
+ fun:sample_2d_linear
+ fun:sample_linear_2d
+ fun:fetch_texel_lod
+ fun:fetch_texel
+ fun:_mesa_execute_program
+ fun:run_program
+ fun:_swrast_exec_fragment_program
+ fun:shade_texture_span
+ fun:_swrast_write_rgba_span
+ fun:general_triangle
+ fun:_swrast_validate_triangle
+ fun:_swrast_Triangle
+ fun:triangle_rgba
+ fun:_tnl_render_triangles_elts
+ fun:run_render
+ fun:_tnl_run_pipeline
+ fun:_tnl_draw_prims
+ fun:_tnl_vbo_draw_prims
+ fun:vbo_validated_drawrangeelements
+ fun:vbo_exec_DrawElements
+ fun:neutral_DrawElements
+}
+{
+ bug_112278b
+ Memcheck:Uninitialized
+ fun:fetch_texel_2d_f_rgba8888
+ fun:sample_2d_nearest
+ fun:sample_nearest_2d
+ fun:fetch_texel_lod
+ fun:fetch_texel
+ fun:_mesa_execute_program
+ fun:run_program
+ fun:_swrast_exec_fragment_program
+ fun:shade_texture_span
+ fun:_swrast_write_rgba_span
+ fun:general_triangle
+ ...
+ fun:_swrast_Triangle
+ fun:triangle_rgba
+ ...
+ fun:run_render
+ fun:_tnl_run_pipeline
+ fun:_tnl_draw_prims
+ fun:_tnl_vbo_draw_prims
+}
+{
+ bug_112315
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2v88internal21NativeObjectsExplorer18FindOrAddGroupInfoEPKc
+ ...
+ fun:_ZN2v88internal21NativeObjectsExplorer27IterateAndExtractReferencesEPNS0_23SnapshotFillerInterfaceE
+ fun:_ZN2v88internal21HeapSnapshotGenerator25CountEntriesAndReferencesEv
+ fun:_ZN2v88internal21HeapSnapshotGenerator16GenerateSnapshotEv
+ fun:_ZN2v88internal12HeapProfiler16TakeSnapshotImplEPKciPNS_15ActivityControlE
+ ...
+ fun:_ZN2v88internal12HeapProfiler12TakeSnapshotEPNS0_6StringEiPNS_15ActivityControlE
+ fun:_ZN2v812HeapProfiler12TakeSnapshotENS_6HandleINS_6StringEEENS_12HeapSnapshot4TypeEPNS_15ActivityControlE
+ fun:_ZL13GetNumObjectsPKc
+}
+{
+ bug_112450_b
+ Memcheck:Unaddressable
+ fun:_ZN7WebCore15PlatformSupport25loadPlatformAudioResourceEPKcd
+ fun:_ZN7WebCore8AudioBus20loadPlatformResourceEPKcf
+ fun:_ZN7WebCore13HRTFElevation35calculateKernelsForAzimuthElevationEiifRKN3WTF6StringERNS1_6RefPtrINS_10HRTFKernelEEES8_
+ fun:_ZN7WebCore13HRTFElevation16createForSubjectERKN3WTF6StringEif
+ fun:_ZN7WebCore12HRTFDatabaseC1Ef
+ fun:_ZN7WebCore12HRTFDatabase6createEf
+ fun:_ZN7WebCore18HRTFDatabaseLoader4loadEv
+ fun:_ZN7WebCoreL19databaseLoaderEntryEPv
+ fun:_ZN3WTFL16threadEntryPointEPv
+}
+{
+ bug_112594_a
+ Memcheck:Leak
+ ...
+ fun:NPP_New
+ fun:_ZN6webkit5npapi14PluginInstance7NPP_NewEtsPPcS3_
+ fun:_ZN6webkit5npapi14PluginInstance5StartERK4GURLPPcS6_ib
+ fun:_ZN6webkit5npapi21WebPluginDelegateImpl10InitializeERK4GURLRKSt6vectorISsSaISsEES9_PNS0_9WebPluginEb
+ fun:_ZN6webkit5npapi13WebPluginImpl10initializeEPN6WebKit18WebPluginContainerE
+ fun:_ZN6WebKit21FrameLoaderClientImpl12createPluginERKN7WebCore7IntSizeEPNS1_17HTMLPlugInElementERKNS1_4KURLERKN3WTF6VectorINSA_6StringELm0EEESF_RKSC_b
+ fun:_ZN7WebCore14SubframeLoader10loadPluginEPNS_22HTMLPlugInImageElementERKNS_4KURLERKN3WTF6StringERKNS6_6VectorIS7_Lm0EEESD_b
+ fun:_ZN7WebCore14SubframeLoader13requestPluginEPNS_22HTMLPlugInImageElementERKNS_4KURLERKN3WTF6StringERKNS6_6VectorIS7_Lm0EEESD_b
+ fun:_ZN7WebCore14SubframeLoader13requestObjectEPNS_22HTMLPlugInImageElementERKN3WTF6StringERKNS3_12AtomicStringES6_RKNS3_6VectorIS4_Lm0EEESD_
+}
+{
+ bug_112594_b
+ Memcheck:Unaddressable
+ fun:_ZN6webkit5npapi13WebPluginImpl24HandleURLRequestInternalEPKcS3_S3_S3_jibNS1_8ReferrerEbb
+ fun:_ZN6webkit5npapi13WebPluginImpl16HandleURLRequestEPKcS3_S3_S3_jibb
+ fun:_ZN6webkit5npapi14PluginInstance10RequestURLEPKcS3_S3_S3_jbPv
+ fun:GetURLNotify
+ fun:NPN_GetURLNotify
+ fun:_ZN10PluginTest16NPN_GetURLNotifyEPKcS1_Pv
+ fun:_ZN34GetURLNotifyWithURLThatFailsToLoad7NPP_NewEPctsPS0_S1_P12_NPSavedData
+ fun:NPP_New
+ fun:_ZN6webkit5npapi14PluginInstance7NPP_NewEtsPPcS3_
+ fun:_ZN6webkit5npapi14PluginInstance5StartERK4GURLPPcS6_ib
+ fun:_ZN6webkit5npapi21WebPluginDelegateImpl10InitializeERK4GURLRKSt6vectorISsSaISsEES9_PNS0_9WebPluginEb
+ fun:_ZN6webkit5npapi13WebPluginImpl10initializeEPN6WebKit18WebPluginContainerE
+ fun:_ZN6WebKit21FrameLoaderClientImpl12createPluginERKN7WebCore7IntSizeEPNS1_17HTMLPlugInElementERKNS1_4KURLERKN3WTF6VectorINSA_6StringELm0EEESF_RKSC_b
+ fun:_ZN7WebCore14SubframeLoader10loadPluginEPNS_22HTMLPlugInImageElementERKNS_4KURLERKN3WTF6StringERKNS6_6VectorIS7_Lm0EEESD_b
+ fun:_ZN7WebCore14SubframeLoader13requestPluginEPNS_22HTMLPlugInImageElementERKNS_4KURLERKN3WTF6StringERKNS6_6VectorIS7_Lm0EEESD_b
+ fun:_ZN7WebCore14SubframeLoader13requestObjectEPNS_22HTMLPlugInImageElementERKN3WTF6StringERKNS3_12AtomicStringES6_RKNS3_6VectorIS4_Lm0EEESD_
+}
+{
+ bug_112594_c
+ Memcheck:Unaddressable
+ fun:_ZN27DocumentOpenInDestroyStream17NPP_DestroyStreamEP9_NPStreams
+ fun:NPP_DestroyStream
+ fun:_ZN6webkit5npapi14PluginInstance17NPP_DestroyStreamEP9_NPStreams
+ fun:_ZN6webkit5npapi12PluginStream5CloseEs
+ fun:_ZN6webkit5npapi15PluginStreamUrl5CloseEs
+ fun:_ZN6webkit5npapi15PluginStreamUrl16DidFinishLoadingEv
+ fun:_ZN6webkit5npapi13WebPluginImpl16didFinishLoadingEPN6WebKit12WebURLLoaderEd
+}
+{
+ bug_112594_d
+ Memcheck:Leak
+ fun:malloc
+ fun:NPN_MemAlloc
+ fun:*Enumerate*ObjectPPPvPj
+ fun:_ZN7WebCore26npObjectPropertyEnumerator*Info*
+ ...
+ fun:_ZN2v88internal28Runtime_GetPropertyNamesFast*IsolateE
+}
+{
+ bug_112573
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2v88internal2OS15CreateSemaphoreEi
+ fun:_ZN2v88internal8ProfilerC1EPNS0_7IsolateE
+ fun:_ZN2v88internal6Logger5SetUpEv
+ fun:_ZN2v88internal7Isolate4InitEPNS0_12DeserializerE
+ fun:_ZN2v88internal2V810InitializeEPNS0_12DeserializerE
+ fun:_ZN2v88internal8Snapshot11DeserializeEPKhi
+ fun:_ZN2v88internal8Snapshot10InitializeEPKc
+ fun:_ZN2v8L16InitializeHelperEv
+ fun:_ZN2v8L27EnsureInitializedForIsolateEPNS_8internal7IsolateEPKc
+ fun:_ZN2v82V818AddMessageListenerEPFvNS_6HandleINS_7MessageEEENS1_INS_5ValueEEEES5_
+ fun:_ZN7WebCore27WorkerContextExecutionProxy19initContextIfNeededEv
+ fun:_ZN7WebCore27WorkerContextExecutionProxy8evaluateERKN3WTF6StringES4_RKNS1_12TextPositionEPNS_27WorkerContextExecutionStateE
+ fun:_ZN7WebCore22WorkerScriptController8evaluateERKNS_16ScriptSourceCodeEPNS_11ScriptValueE
+ fun:_ZN7WebCore22WorkerScriptController8evaluateERKNS_16ScriptSourceCodeE
+ fun:_ZN7WebCore12WorkerThread12workerThreadEv
+ fun:_ZN7WebCore12WorkerThread17workerThreadStartEPv
+ fun:_ZN3WTFL16threadEntryPointEPv
+}
+{
+ bug_112835
+ Memcheck:Unaddressable
+ ...
+ fun:_ZN6WebKit31WorkerFileSystemCallbacksBridge4stopEv
+ fun:_ZN6WebKit31WorkerFileSystemContextObserver10notifyStopEv
+ fun:_ZN7WebCore13WorkerContext21notifyObserversOfStopEv
+ fun:_ZN7WebCore29WorkerThreadShutdownStartTask11performTaskEPNS_22ScriptExecutionContextE
+ fun:_ZN7WebCore13WorkerRunLoop4Task11performTaskERKS0_PNS_22ScriptExecutionContextE
+ fun:_ZN7WebCore13WorkerRunLoop15runCleanupTasksEPNS_13WorkerContextE
+}
+{
+ bug_113076
+ Memcheck:Uninitialized
+ fun:_ZN5mediaL19ConvertYUVToRGB32_CEhhhPh
+ fun:_ZN5media35LinearScaleYUVToRGB32RowWithRange_CEPKhS1_S1_Phiii
+ fun:_ZN5media23ScaleYUVToRGB32WithRectEPKhS1_S1_Phiiiiiiiiiii
+ fun:_ZN8remoting29ConvertAndScaleYUVToRGB32RectEPKhS1_S1_iiRK7SkTSizeIiERK7SkIRectPhiS5_S8_S8_
+}
+{
+ bug_115294
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN17AudioRendererHost14OnCreateStreamEiRK15AudioParameters
+}
+{
+ bug_115419_1
+ Memcheck:Uninitialized
+ fun:fetch_texel_2d_f_rgba8888
+ fun:texture_get_row
+ fun:fast_read_rgba_pixels
+ fun:read_rgba_pixels
+ fun:_swrast_ReadPixels
+ fun:_mesa_ReadPixels
+ fun:glReadPixels
+ fun:_ZN3gpu5gles216GLES2DecoderImpl16HandleReadPixelsEjRKNS0_10ReadPixelsE
+ fun:_ZN3gpu5gles216GLES2DecoderImpl9DoCommandEjjPKv
+ fun:_ZN3gpu13CommandParser14ProcessCommandEv
+ fun:_ZN3gpu12GpuScheduler10PutChangedEv
+ fun:_ZN6webkit3gpu18GLInProcessContext12PumpCommandsEv
+}
+{
+ bug_115419_2
+ Memcheck:Uninitialized
+ fun:get_src_arg_mask
+ fun:_mesa_remove_extra_move_use
+ fun:_mesa_optimize_program
+ fun:_Z16get_mesa_programP14__GLcontextRecP17gl_shader_programP9gl_shader
+ fun:_mesa_ir_link_shader
+ fun:_mesa_glsl_link_shader
+ fun:link_program
+ fun:_mesa_LinkProgramARB
+ fun:glLinkProgram
+ ...
+ fun:_ZN3gpu5gles216GLES2DecoderImpl13DoLinkProgram*
+ fun:_ZN3gpu5gles216GLES2DecoderImpl17HandleLinkProgram*
+ fun:_ZN3gpu5gles216GLES2DecoderImpl9DoCommandEjjPKv
+ fun:_ZN3gpu13CommandParser14ProcessCommandEv
+ fun:_ZN3gpu12GpuScheduler10PutChangedEv
+ fun:_ZN6webkit3gpu18GLInProcessContext12PumpCommandsEv
+}
+{
+ bug_116475
+ Memcheck:Uninitialized
+ ...
+ fun:_ZNK4base9Histogram11BucketIndexEi
+ fun:_ZN4base9Histogram3AddEi
+ fun:_ZN11webkit_glue25WebKitPlatformSupportImpl21histogramCustomCountsEPKciiii
+ fun:_ZN7WebCore15PlatformSupport21histogramCustomCountsEPKciiii
+ fun:_ZN7WebCore19CCLayerTreeHostImpl20optimizeRenderPasses*
+ fun:_ZN7WebCore19CCLayerTreeHostImpl10drawLayersEv
+ fun:_ZN7WebCore19CCSingleThreadProxy11doCompositeEv
+}
+{
+ bug_118890_a
+ Memcheck:Leak
+ ...
+ fun:_ZN8notifier18SingleLoginAttemptC1EPNS_13LoginSettingsEPNS0_8DelegateE
+ fun:_ZN8notifier5Login15StartConnectionEv
+ fun:_ZN13sync_notifier20InvalidationNotifier17UpdateCredentialsERKSsS2_
+}
+{
+ bug_118890_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN13sync_notifier12_GLOBAL__N_124InvalidationNotifierTest5SetUpEv
+}
+{
+ bug_121729
+ Memcheck:Leak
+ ...
+ fun:_ZN7WebCoreL12parseUASheetERKN3WTF6StringE
+ fun:_ZN7WebCoreL12parseUASheetEPKcj
+ ...
+ fun:_ZN7WebCore7Element16styleForRendererE*
+}
+{
+ bug_122177
+ Memcheck:Leak
+ ...
+ fun:_ZN7history16InMemoryURLIndex23PostSaveToCacheFileTaskEv
+ fun:_ZN7history16InMemoryURLIndex8ShutDownEv
+ fun:_ZN14HistoryService13UnloadBackendEv
+ fun:_ZN14HistoryService7CleanupEv
+}
+{
+ bug_122189
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN6WebKit16ChromeClientImpl18createColorChooserEPN7WebCore18ColorChooserClientERKNS1_5ColorE
+ fun:_ZN7WebCore6Chrome18createColorChooserEPNS_18ColorChooserClientERKNS_5ColorE
+ fun:_ZN7WebCore14ColorInputType22handleDOMActivateEventEPNS_5EventE
+ fun:_ZN7WebCore16HTMLInputElement19defaultEventHandlerEPNS_5EventE
+ fun:_ZN7WebCore15EventDispatcher13dispatchEventEN3WTF10PassRefPtrINS_5EventEEE
+ fun:_ZNK7WebCore21EventDispatchMediator13dispatchEventEPNS_15EventDispatcherE
+}
+{
+ bug_122192
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN6webkit3gpu18GLInProcessContext22CreateOffscreenContextEPS1_RKN3gfx4SizeES2_PKcPKiNS3_13GpuPreferenceE
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl10InitializeEN6WebKit20WebGraphicsContext3D10AttributesEPS3_
+ fun:_ZN14webkit_support23CreateGraphicsContext3DERKN6WebKit20WebGraphicsContext3D10AttributesEPNS0_7WebViewEb
+ fun:_ZN11WebViewHost23createGraphicsContext3DERKN6WebKit20WebGraphicsContext3D10AttributesE
+ fun:_ZN6WebKit11WebViewImpl33createCompositorGraphicsContext3DEv
+ fun:_ZN6WebKit11WebViewImpl15createContext3DEv
+}
+{
+ bug_122195
+ Memcheck:Leak
+ ...
+ fun:_ZNSt3*insert*
+ fun:_ZN3gpu5gles219GLES2Implementation15GetStringHelperEj
+ fun:_ZN3gpu5gles219GLES2Implementation9GetStringEj
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl9getStringEj
+ fun:_ZN7WebCore24GraphicsContext3DPrivate9getStringEj
+ fun:_ZN7WebCore24GraphicsContext3DPrivate20initializeExtensionsEv
+ fun:_ZN7WebCore24GraphicsContext3DPrivate17supportsExtensionERKN3WTF6StringE
+ fun:_ZN7WebCore20Extensions3DChromium8supportsERKN3WTF6StringE
+}
+{
+ bug_122201
+ Memcheck:Unaddressable
+ fun:_ZN3WTF17ChromiumThreading16callOnMainThreadEPFvPvES1_
+ fun:_ZN3WTF16callOnMainThreadEPFvPvES0_
+}
+{
+ bug_122245a
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN15SkScalerContext15internalGetPathERK7SkGlyphP6SkPathS4_P8SkMatrix
+ fun:_ZN15SkScalerContext10getMetricsEP7SkGlyph
+ fun:_ZN12SkGlyphCache13lookupMetricsEjNS_11MetricsTypeE
+}
+{
+ bug_122245b
+ Memcheck:Uninitialized
+ ...
+ fun:_ZNK6SkRect8roundOutEP7SkIRect
+ fun:_ZN15SkScalerContext10getMetricsEP7SkGlyph
+ fun:_ZN12SkGlyphCache13lookupMetricsEjNS_11MetricsTypeE
+ fun:_ZN12SkGlyphCache17getGlyphIDMetricsEt
+ fun:_ZL22sk_getMetrics_glyph_00P12SkGlyphCachePPKcii
+ fun:_ZNK6SkDraw11drawPosTextEPKcmPKffiRK7SkPaint
+ fun:_ZN8SkDevice11drawPosTextERK6SkDrawPKvmPKffiRK7SkPaint
+ fun:_ZN11SkGpuDevice11drawPosTextERK6SkDrawPKvmPKffiRK7SkPaint
+ fun:_ZN8SkCanvas11drawPosTextEPKvmPK7SkPointRK7SkPaint
+ fun:_ZNK7WebCore4Font10drawGlyphsEPNS_15GraphicsContextEPKNS_14SimpleFontDataERKNS_11GlyphBufferEiiRKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font15drawGlyphBufferEPNS_15GraphicsContextERKNS_7TextRunERKNS_11GlyphBufferERKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font14drawSimpleTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZNK7WebCore4Font8drawTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZN7WebCore15GraphicsContext12drawBidiTextERKNS_4FontERKNS_7TextRunERKNS_10FloatPointE
+ fun:_ZN7WebCore24CanvasRenderingContext2D16drawTextInternalERKN3WTF6StringEffbfb
+ fun:_ZN7WebCore24CanvasRenderingContext2D10strokeTextERKN3WTF6StringEfff
+ fun:_ZN7WebCore32CanvasRenderingContext2DInternalL18strokeTextCallbackERKN2v89ArgumentsE
+ fun:_ZN2v88internalL19HandleApiCallHelperILb0EEEPNS0_11MaybeObjectENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+ fun:_ZN2v88internalL21Builtin_HandleApiCallENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+}
+{
+ bug_122429
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN6webkit3gpu18GLInProcessContext22CreateOffscreenContextEPS1_RKN3gfx4SizeES2_PKcPKiNS3_13GpuPreferenceE
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl10InitializeEN6WebKit20WebGraphicsContext3D10AttributesEPS3_
+ fun:_ZN25TestWebKitPlatformSupport32createOffscreenGraphicsContext3DERKN6WebKit20WebGraphicsContext3D10AttributesE
+ fun:_ZN13TestWebPlugin10initializeEPN6WebKit18WebPluginContainerE
+ fun:_ZN6WebKit21FrameLoaderClientImpl12createPluginERKN7WebCore7IntSizeEPNS1_17HTMLPlugInElementERKNS1_4KURLERKN3WTF6VectorINSA_6StringELm0EEESF_RKSC_b
+}
+{
+ bug_122431
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11WebViewHost12createPluginEPN6WebKit8WebFrameERKNS0_15WebPluginParamsE
+ fun:_ZN6WebKit21FrameLoaderClientImpl12createPluginERKN7WebCore7IntSizeEPNS1_17HTMLPlugInElementERKNS1_4KURLERKN3WTF6VectorINSA_6StringELm0EEESF_RKSC_b
+ fun:_ZN7WebCore14SubframeLoader10loadPluginEPNS_22HTMLPlugInImageElementERKNS_4KURLERKN3WTF6StringERKNS6_6VectorIS7_Lm0EEESD_b
+ fun:_ZN7WebCore14SubframeLoader13requestPluginEPNS_22HTMLPlugInImageElementERKNS_4KURLERKN3WTF6StringERKNS6_6VectorIS7_Lm0EEESD_b
+ fun:_ZN7WebCore14SubframeLoader13requestObjectEPNS_22HTMLPlugInImageElementERKN3WTF6StringERKNS3_12AtomicStringES6_RKNS3_6VectorIS4_Lm0EEESD_
+ fun:_ZN7WebCore16HTMLEmbedElement12updateWidgetENS_20PluginCreationOptionE
+}
+{
+ bug_122435a
+ Memcheck:Leak
+ fun:_Zna*
+ fun:_ZN3gpu5gles219VertexAttribManager10InitializeEj
+ fun:_ZN3gpu5gles216GLES2DecoderImpl10InitializeERK13scoped_refptrIN3gfx9GLSurfaceEERKS2_INS3_9GLContext*SizeERKNS0_18DisallowedFeaturesEPKcRKSt6vectorIiSaIiEE
+ fun:_ZN6webkit3gpu18GLInProcessContext10InitializeERKN3gfx4SizeEPS1_PKcPKiNS2_13GpuPreferenceE
+ fun:_ZN6webkit3gpu18GLInProcessContext22CreateOffscreenContextEPS1_RKN3gfx4SizeES2_PKcPKiNS3_13GpuPreferenceE
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl10InitializeEN6WebKit20WebGraphicsContext3D10AttributesEPS3_
+}
+{
+ bug_122435b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt10_List_nodeIPN3gpu5gles219VertexAttribManager16VertexAttribInfoEEE8allocateEmPKv
+ fun:_ZNSt10_List_baseIPN3gpu5gles219VertexAttribManager16VertexAttribInfoESaIS4_EE11_M_get_nodeEv
+ fun:_ZNSt4listIPN3gpu5gles219VertexAttribManager16VertexAttribInfoESaIS4_EE14_M_create_nodeERKS4_
+ fun:_ZNSt4listIPN3gpu5gles219VertexAttribManager16VertexAttribInfoESaIS4_EE6insertESt14_List_iteratorIS4_ERKS4_
+ fun:_ZN3gpu5gles219VertexAttribManager16VertexAttribInfo7SetListEPSt4listIPS2_SaIS4_EE
+ fun:_ZN3gpu5gles219VertexAttribManager6EnableEjb
+}
+{
+ bug_122436
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKj10linked_ptrIN3gpu13CommonDecoder6BucketEEEEE8allocateEmPKv
+ fun:_ZNSt8_Rb_treeIjSt4pairIKj10linked_ptrIN3gpu13CommonDecoder6BucketEEESt10_Select1stIS7_ESt4lessIjESaIS7_EE11_M_get_nodeEv
+ fun:_ZNSt8_Rb_treeIjSt4pairIKj10linked_ptrIN3gpu13CommonDecoder6BucketEEESt10_Select1stIS7_ESt4lessIjESaIS7_EE14_M_create_nodeERKS7_
+ fun:_ZNSt8_Rb_treeIjSt4pairIKj10linked_ptrIN3gpu13CommonDecoder6BucketEEESt10_Select1stIS7_ESt4lessIjESaIS7_EE10_M_insert_EPKSt18_Rb_tree_node_baseSG_RKS7_
+ fun:_ZNSt8_Rb_treeIjSt4pairIKj10linked_ptrIN3gpu13CommonDecoder6BucketEEESt10_Select1stIS7_ESt4lessIjESaIS7_EE16_M_insert_uniqueERKS7_
+ fun:_ZNSt8_Rb_treeIjSt4pairIKj10linked_ptrIN3gpu13CommonDecoder6BucketEEESt10_Select1stIS7_ESt4lessIjESaIS7_EE17_M_insert_unique_ESt23_Rb_tree_const_iteratorIS7_ERKS7_
+ fun:_ZNSt3mapIj10linked_ptrIN3gpu13CommonDecoder6BucketEESt4lessIjESaISt4pairIKjS4_EEE6insertESt17_Rb_tree_iteratorIS9_ERKS9_
+ fun:_ZNSt3mapIj10linked_ptrIN3gpu13CommonDecoder6BucketEESt4lessIjESaISt4pairIKjS4_EEEixERS8_
+ fun:_ZN3gpu13CommonDecoder12CreateBucketEj
+}
+{
+ bug_122437
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3gpu19MappedMemoryManager5Alloc*
+ fun:_ZN3gpu5gles219GLES2Implementation24MapTexSubImage2DCHROMIUM*
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl24mapTexSubImage2DCHROMIUM*
+ fun:_ZN7WebCore24GraphicsContext3DPrivate24mapTexSubImage2DCHROMIUM*
+ fun:_ZN7WebCore20Extensions3DChromium24mapTexSubImage2DCHROMIUM*
+ fun:_ZN7WebCore20LayerTextureSubImage24uploadWithMapTexSubImageEPKhRKNS_7IntRectES5_S5_jPNS_17GraphicsContext3DE
+ fun:_ZN7WebCore20LayerTextureSubImage6uploadEPKhRKNS_7IntRectES5_S5_jPNS_17GraphicsContext3DE
+ fun:_ZN7WebCore31BitmapCanvasLayerTextureUpdater17updateTextureRectEPNS_17GraphicsContext3DEPNS_16TextureAllocatorEPNS_14ManagedTextureERKNS_7IntRectES9_
+ fun:_ZN7WebCore31BitmapCanvasLayerTextureUpdater7Texture10updateRectEPNS_17GraphicsContext3DEPNS_16TextureAllocatorERKNS_7IntRectES8_
+}
+{
+ bug_122454
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11GrGLTexture4initEP7GrGpuGLRKNS_4DescEPKN16GrGLRenderTarget4DescE
+ fun:_ZN11GrGLTextureC1EP7GrGpuGLRKNS_4DescE
+ fun:_ZN7GrGpuGL15onCreateTextureERK13GrTextureDescPKvm
+ fun:_ZN5GrGpu13createTextureERK13GrTextureDescPKvm
+ fun:_ZN9GrContext20createAndLockTextureEmPK14GrSamplerStateRK13GrTextureDescPvm
+ fun:_Z27sk_gr_create_bitmap_textureP9GrContextmPK14GrSamplerStateRK8SkBitmap
+ fun:_ZN11SkGpuDevice17lockCachedTextureERK8SkBitmapPK14GrSamplerState
+}
+{
+ bug_122455
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISsEE8allocateEmPKv
+ fun:_ZNSt8_Rb_treeISsSsSt9_IdentityISsESt4lessISsESaISsEE11_M_get_nodeEv
+ fun:_ZNSt8_Rb_treeISsSsSt9_IdentityISsESt4lessISsESaISsEE14_M_create_nodeERKSs
+ fun:_ZNSt8_Rb_treeISsSsSt9_IdentityISsESt4lessISsESaISsEE10_M_insert_EPKSt18_Rb_tree_node_baseS8_RKSs
+ fun:_ZNSt8_Rb_treeISsSsSt9_IdentityISsESt4lessISsESaISsEE16_M_insert_uniqueERKSs
+ fun:_ZNSt3setISsSt4lessISsESaISsEE6insertERKSs
+ fun:_ZN3gpu5gles219GLES2Implementation32GetRequestableExtensionsCHROMIUMEv
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl32getRequestableExtensionsCHROMIUMEv
+ fun:_ZN7WebCore24GraphicsContext3DPrivate20initializeExtensionsEv
+ fun:_ZN7WebCore24GraphicsContext3DPrivate17supportsExtensionERKN3WTF6StringE
+}
+{
+ bug_122457
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10RefCountedIN7WebCore7ArchiveEEnwEm
+ fun:_ZN7WebCore12MHTMLArchive6createEv
+ ...
+ fun:_ZN7WebCore11MHTMLParser22parseArchiveWithHeaderEPNS_10MIMEHeaderE
+ fun:_ZN7WebCore11MHTMLParser12parseArchiveEv
+ fun:_ZN7WebCore12MHTMLArchive6createERKNS_4KURLEPNS_12SharedBufferE
+ fun:_ZN7WebCoreL20archiveFactoryCreateINS_12MHTMLArchiveEEEN3WTF10PassRefPtrINS_7ArchiveEEERKNS_4KURLEPNS_12SharedBufferE
+ fun:_ZN7WebCore14ArchiveFactory6createERKNS_4KURLEPNS_12SharedBufferERKN3WTF6StringE
+ ...
+ fun:_ZN7WebCore14DocumentLoader15finishedLoadingEv
+ fun:_ZN7WebCore18MainResourceLoader16didFinishLoadingEd
+}
+{
+ bug_122670
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3WTF11ListHashSetIPN7WebCore12RenderInlineELm256ENS_7PtrHashIS3_EEEC1Ev
+ fun:_ZNK7WebCore17RenderLineBoxList5paintEPNS_20RenderBoxModelObjectERNS_9PaintInfoERKNS*
+ fun:_ZN7WebCore11RenderBlock13paintContentsERNS_9PaintInfoERKNS*
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS*
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS*
+}
+{
+ bug_122716
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISsE8allocate*
+ fun:_ZNSt12_Vector_baseISsSaISsEE11_M_allocate*
+ fun:_ZNSt6vectorISsSaISsEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPSsS1_EERKSs
+ fun:_ZNSt6vectorISsSaISsEE9push_backERKSs
+ fun:_ZN4baseL12SplitStringTISsEEvRKT_NS1_10value_typeEbPSt6vectorIS1_SaIS1_EE
+}
+{
+ bug_122717_use_after_free
+ Memcheck:Unaddressable
+ fun:__pthread_mutex_unlock_usercnt
+ fun:_ZN4base8internal8LockImpl6UnlockEv
+ fun:_ZN4base4Lock7ReleaseEv
+ fun:_ZN4base8AutoLockD1Ev
+ fun:_ZN5gdata15GDataFileSystem21RunTaskOnIOThreadPoolERKN4base8CallbackIFvvEEE
+}
+{
+ bug_122717_leak
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_
+ fun:_ZN7content13BrowserThread16PostTaskAndReplyENS0_2IDERKN15tracked_objects8LocationERKN4base8CallbackIFvvEEESB_
+ fun:_ZN5gdata15GDataFileSystem37PostBlockingPoolSequencedTaskAndReplyERKSsRKN15tracked_objects8LocationERKN4base8CallbackIFvvEEESC_
+ fun:_ZN5gdata15GDataFileSystem29PostBlockingPoolSequencedTaskERKSsRKN15tracked_objects8LocationERKN4base8CallbackIFvvEEE
+ fun:_ZN5gdata15GDataFileSystem8SaveFeedE10scoped_ptrIN4base5ValueEE*
+ fun:_ZN5gdata15GDataFileSystem14OnGetDocumentsEPNS0_18GetDocumentsParamsENS_14GDataErrorCodeE10scoped_ptrIN4base5ValueEE
+}
+{
+ bug_122733
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorINS_15_Hashtable_nodeISsEEE8allocateEmPKv
+ fun:_ZN9__gnu_cxx9hashtableISsSsNS_4hashISsEESt9_IdentityISsESt8equal_toISsESaISsEE11_M_get_nodeEv
+ fun:_ZN9__gnu_cxx9hashtableISsSsNS_4hashISsEESt9_IdentityISsESt8equal_toISsESaISsEE11_M_new_nodeERKSs
+ fun:_ZN9__gnu_cxx9hashtableISsSsNS_4hashISsEESt9_IdentityISsESt8equal_toISsESaISsEE22insert_unique_noresizeERKSs
+ fun:_ZN9__gnu_cxx9hashtableISsSsNS_4hashISsEESt9_IdentityISsESt8equal_toISsESaISsEE13insert_uniqueERKSs
+ fun:_ZN9__gnu_cxx8hash_setISsNS_4hashISsEESt8equal_toISsESaISsEE6insertERKSs
+ fun:_ZN13safe_browsing6Scorer6CreateERKN4base16BasicStringPieceISsEE
+ fun:_ZN13safe_browsing24PhishingClassifierFilter18OnSetPhishingModelERKSs
+}
+{
+ bug_122733b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN13safe_browsing15ClientSideModel27MergePartialFromCodedStreamEPN6google8protobuf2io16CodedInputStreamE
+ fun:_ZN6google8protobuf11MessageLite14ParseFromArrayEPKvi
+ fun:_ZN13safe_browsing6Scorer6CreateERKN4base16BasicStringPieceISsEE
+ fun:_ZN13safe_browsing24PhishingClassifierFilter18OnSetPhishingModelERKSs
+}
+{
+ bug_122752a
+ Memcheck:Unaddressable
+ fun:_ZN6WebKit12CCThreadImpl8postTaskEN3WTF10PassOwnPtrIN7WebCore8CCThread4TaskEEE
+ fun:_ZN7WebCore13CCThreadProxy18finishAllRenderingEv
+ fun:_ZN7WebCore15CCLayerTreeHost18finishAllRenderingEv
+ fun:_ZN6WebKit16WebLayerTreeView18finishAllRenderingEv
+ fun:_ZN6WebKit11WebViewImpl33setIsAcceleratedCompositingActiveEb
+ fun:_ZN6WebKit11WebViewImpl20setRootGraphicsLayerEPN7WebCore13GraphicsLayerE
+}
+{
+ bug_122752b
+ Memcheck:Unaddressable
+ fun:_ZN6WebKit12CCThreadImpl8postTaskEN3WTF10PassOwnPtrIN7WebCore8CCThread4TaskEEE
+ fun:_ZN7WebCore13CCThreadProxy14setNeedsCommitEv
+ fun:_ZN7WebCore15CCLayerTreeHost14setNeedsCommitEv
+ fun:_ZN7WebCore13LayerChromium14setNeedsCommitEv
+ fun:_ZN7WebCore13LayerChromium11removeChildEPS0_
+ fun:_ZN7WebCore13LayerChromium16removeFromParentEv
+ fun:_ZN7WebCore21GraphicsLayerChromium16removeFromParentEv
+}
+{
+ bug_123307
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF16fastZeroedMallocEm
+ ...
+ fun:_ZN7WebCore12_GLOBAL__N_111V8ObjectMapIN2v86ObjectEjE3setERKNS2_6HandleIS3_EERKj
+ fun:_ZN7WebCore12_GLOBAL__N_110Serializer10greyObjectERKN2v86HandleINS2_6ObjectEEE
+ fun:_ZN7WebCore12_GLOBAL__N_110Serializer11doSerializeEN2v86HandleINS2_5ValueEEEPNS1_9StateBaseE
+ fun:_ZN7WebCore12_GLOBAL__N_110Serializer9serializeEN2v86HandleINS2_5ValueEEE
+ fun:_ZN7WebCore21SerializedScriptValueC1EN2v86HandleINS1_5ValueEEEPN3WTF6VectorINS5_6RefPtrINS_11MessagePortEEELm1EEEPNS6_INS7_INS5_11ArrayBufferEEELm1EEERb
+ fun:_ZN7WebCore21SerializedScriptValue6createEN2v86HandleINS1_5ValueEEEPN3WTF6VectorINS5_6RefPtrINS_11MessagePortEEELm1EEEPNS6_INS7_INS5_11ArrayBufferEEELm1EEERb
+ fun:_ZN7WebCoreL25handlePostMessageCallbackERKN2v89ArgumentsEb
+ fun:_ZN7WebCore11V8DOMWindow19postMessageCallbackERKN2v89ArgumentsE
+ fun:_ZN2v88internalL19HandleApiCallHelperILb0EEEPNS0_11MaybeObjectENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+ fun:_ZN2v88internalL21Builtin_HandleApiCallENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+}
+{
+ bug_124156
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:*WebKitPlatformSupport*20CreateResourceLoaderERKN11webkit_glue20ResourceLoaderBridge11RequestInfoE
+ fun:_ZN11webkit_glue16WebURLLoaderImpl7Context5StartERKN6WebKit13WebURLRequestEPNS_20ResourceLoaderBridge16SyncLoadResponseEPNS_25WebKitPlatformSupportImplE
+ fun:_ZN11webkit_glue16WebURLLoaderImpl18loadAsynchronouslyERKN6WebKit13WebURLRequestEPNS1_18WebURLLoaderClientE
+}
+{
+ bug_124488
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ ...
+ fun:_ZN34CopyTextureCHROMIUMResourceManager10InitializeEv
+ fun:_ZN3gpu5gles216GLES2DecoderImpl10InitializeERK13scoped_refptrIN3gfx9GLSurfaceEERKS2_INS3_9GLContextEERKNS3_4SizeERKNS0_18DisallowedFeaturesEPKcRKSt6vectorIiSaIiEE
+ fun:_ZN6webkit3gpu18GLInProcessContext10InitializeERKN3gfx4SizeEPS1_PKcPKiNS2_13GpuPreferenceE
+ fun:_ZN6webkit3gpu18GLInProcessContext22CreateOffscreenContextEPS1_RKN3gfx4SizeES2_PKcPKiNS3_13GpuPreferenceE
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl10InitializeEN6WebKit20WebGraphicsContext3D10AttributesEPS3_
+}
+{
+ bug_124496
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN8notifier26ProxyResolvingClientSocket23ProcessProxyResolveDoneEi
+}
+{
+ bug_124500
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIN6webkit17WebPluginMimeTypeEE8allocateEmPKv
+ fun:_ZNSt12_Vector_baseIN6webkit17WebPluginMimeTypeESaIS1_EE11_M_allocateEm
+ fun:_ZNSt6vectorIN6webkit17WebPluginMimeTypeESaIS1_EE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPS1_S3_EERKS1_
+ fun:_ZNSt6vectorIN6webkit17WebPluginMimeTypeESaIS1_EE9push_backERKS1_
+ fun:_ZN6webkit5npapi9PluginLib20ParseMIMEDescriptionERKSsPSt6vectorINS_17WebPluginMimeTypeESaIS5_EE
+ fun:_ZN6webkit5npapi9PluginLib17ReadWebPluginInfoE*
+ fun:_ZN6webkit5npapi10PluginList14ReadPluginInfoE*
+ fun:_ZN6webkit5npapi10PluginList10LoadPluginE*
+ fun:_ZN17UtilityThreadImpl13OnLoadPluginsE*
+}
+{
+ bug_127716
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3gfx5ImageC1ERK8SkBitmap
+ fun:_ZN16BrowserThemePack16LoadRawBitmapsToE*
+ fun:_ZN16BrowserThemePack18BuildFromExtensionEPK9Extension
+ fun:_ZN45BrowserThemePackTest_CanBuildAndReadPack_Test8TestBodyEv
+}
+{
+ bug_130362
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12invalidation20NewPermanentCallbackINS_22InvalidationClientImplES1_St4pairINS_6StatusESsEEEPN4base8CallbackIFvT1_EEEPT_MT0_FvS7_E
+ fun:_ZN12invalidation22InvalidationClientImpl34ScheduleStartAfterReadingStateBlobEv
+ fun:_ZN12invalidation22InvalidationClientImpl5StartEv
+ fun:_ZN6syncer24SyncInvalidationListener5StartERKSsS2_S2_RKSt3mapIN8syncable9ModelTypeElSt4lessIS5_ESaISt4pairIKS5_lEEERKN12browser_sync10WeakHandleINS_24InvalidationStateTrackerEEEPNS0_8ListenerEPNS_11StateWriterE
+ fun:_ZN6syncer20InvalidationNotifier17UpdateCredentialsERKSsS2_
+ fun:_ZN6syncer31NonBlockingInvalidationNotifier4Core17UpdateCredentialsERKSsS3_
+}
+{
+ bug_130449
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12invalidation20NewPermanentCallbackINS_22InvalidationClientImplES1_St4pairINS_6StatusESsEEEPN4base8CallbackIFvT1_EEEPT_MT0_FvS7_E
+ fun:_ZN12invalidation22InvalidationClientImpl34ScheduleStartAfterReadingStateBlobEv
+ fun:_ZN12invalidation22InvalidationClientImpl5StartEv
+ fun:_ZN6syncer24SyncInvalidationListener5StartERKSsS2_S2_RKSt3mapIN8syncable9ModelTypeElSt4lessIS5_ESaISt4pairIKS5_lEEERKN12browser_sync10WeakHandleINS_24InvalidationStateTrackerEEEPNS0_8ListenerE
+ fun:_ZN6syncer20InvalidationNotifier17UpdateCredentialsERKSsS2_
+ fun:_ZN6syncer31NonBlockingInvalidationNotifier4Core17UpdateCredentialsERKSsS3_
+}
+{
+ bug_130619
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore9ClipRects6createERKS0_
+ fun:_ZN7WebCore11RenderLayer15updateClipRectsEPKS0_PNS_12RenderRegionENS_13ClipRectsTypeENS_29OverlayScrollbarSizeRelevancyE
+ ...
+ fun:_ZNK7WebCore11RenderLayer15parentClipRectsEPKS0_PNS_12RenderRegionENS_13ClipRectsTypeERNS_9ClipRectsENS_29OverlayScrollbarSizeRelevancyE
+ fun:_ZNK7WebCore11RenderLayer18backgroundClipRectEPKS0_PNS_12RenderRegionENS_13ClipRectsTypeENS_29OverlayScrollbarSizeRelevancyE
+}
+{
+ bug_138058
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN7WebCore12WebVTTParser22constructTreeFromTokenEPNS_8DocumentE
+ fun:_ZN7WebCore12WebVTTParser33createDocumentFragmentFromCueTextERKN3WTF6StringE
+ fun:_ZN7WebCore12TextTrackCue12getCueAsHTMLEv
+ fun:_ZN7WebCore12TextTrackCue17updateDisplayTreeEf
+ fun:_ZN7WebCore16HTMLMediaElement25updateActiveTextTrackCuesEf
+}
+{
+ bug_138060
+ Memcheck:Uninitialized
+ fun:_NPN_EvaluateHelper
+ fun:_NPN_Evaluate
+ fun:_ZN6WebKit11WebBindings8evaluateEP4_NPPP8NPObjectP9_NPStringP10_NPVariant
+ fun:_ZL13executeScriptPK12PluginObjectPKc
+ fun:NPP_Destroy
+ fun:_ZN6webkit5npapi14PluginInstance11NPP_DestroyEv
+ fun:_ZN6webkit5npapi21WebPluginDelegateImpl15DestroyInstanceEv
+ fun:_ZN6webkit5npapi21WebPluginDelegateImplD0Ev
+ fun:_ZN6webkit5npapi21WebPluginDelegateImpl15PluginDestroyedEv
+ fun:_ZN6webkit5npapi13WebPluginImpl22TearDownPluginInstanceEPN6WebKit12WebURLLoaderE
+ fun:_ZN6webkit5npapi13WebPluginImpl12SetContainerEPN6WebKit18WebPluginContainerE
+ fun:_ZN6webkit5npapi13WebPluginImpl7destroyEv
+ fun:_ZN6WebKit22WebPluginContainerImplD0Ev
+ fun:_ZN3WTF10RefCountedIN7WebCore6WidgetEE5derefEv
+ fun:_ZNSt4pairIN3WTF6RefPtrIN7WebCore6WidgetEEEPNS2_9FrameViewEED1Ev
+ fun:_ZN3WTF9HashTableINS_6RefPtrIN7WebCore6WidgetEEESt4pairIS4_PNS2_9FrameViewEENS_18PairFirstExtractorIS8_EENS_7PtrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSE_IS7_EEEESF_E15deallocateTableEPS8_i
+ fun:_ZN3WTF9HashTableINS_6RefPtrIN7WebCore6WidgetEEESt4pairIS4_PNS2_9FrameViewEENS_18PairFirstExtractorIS8_EENS_7PtrHashIS4_EENS_14PairHashTraitsINS_10HashTraitsIS4_EENSE_IS7_EEEESF_ED1Ev
+ fun:_ZN3WTF7HashMapINS_6RefPtrIN7WebCore6WidgetEEEPNS2_9FrameViewENS_7PtrHashIS4_EENS_10HashTraitsIS4_EENS9_IS6_EEED1Ev
+ fun:_ZN7WebCore12RenderWidget28resumeWidgetHierarchyUpdatesEv
+ fun:_ZN7WebCore7Element6detachEv
+ fun:_ZN7WebCore13ContainerNode14detachChildrenEv
+ fun:_ZN7WebCore13ContainerNode6detachEv
+}
+{
+ bug_138220_a
+ Memcheck:Uninitialized
+ fun:_ZNK7WebCore16HTMLInputElement8dataListEv
+ fun:_ZNK7WebCore16HTMLInputElement4listEv
+ fun:_ZN7WebCore21RenderSliderContainer6layoutEv
+ fun:_ZN7WebCore11RenderBlock16layoutBlockChildEPNS_9RenderBoxERNS0_10MarginInfoERNS_20FractionalLayoutUnitES6_
+ fun:_ZN7WebCore11RenderBlock19layoutBlockChildrenEbRNS_20FractionalLayoutUnitE
+ fun:_ZN7WebCore11RenderBlock11layoutBlockEbNS_20FractionalLayoutUnitE
+ fun:_ZN7WebCore11RenderBlock6layoutEv
+ fun:_ZN7WebCore12RenderSlider6layoutEv
+}
+{
+ bug_138220_b
+ Memcheck:Uninitialized
+ fun:_ZNK7WebCore16HTMLInputElement8dataListEv
+ fun:_ZNK7WebCore16HTMLInputElement4listEv
+ fun:_ZN7WebCore11RenderTheme16paintSliderTicksEPNS_12RenderObjectERKNS_9PaintInfoERKNS_7IntRectE
+ fun:_ZN7WebCore24RenderThemeChromiumLinux16paintSliderTrackEPNS_12RenderObjectERKNS_9PaintInfoERKNS_7IntRectE
+ fun:_ZN7WebCore11RenderTheme5paintEPNS_12RenderObjectERKNS_9PaintInfoERKNS_7IntRectE
+ fun:_ZN7WebCore9RenderBox19paintBoxDecorationsERNS_9PaintInfoERKNS_21FractionalLayoutPointE
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_21FractionalLayoutPointE
+}
+{
+ bug_138233_a
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10RefCountedIN7WebCore17ScriptProfileNodeEEnwEm
+ fun:_ZN7WebCore17ScriptProfileNode6createEPKN2v814CpuProfileNodeE
+ fun:_ZNK7WebCore13ScriptProfile4headEv
+ fun:_ZN7WebCore23ScriptProfileV8InternalL14headAttrGetterEN2v85LocalINS1_6StringEEERKNS1_12AccessorInfoE
+ fun:_ZN2v88internal8JSObject23GetPropertyWithCallbackEPNS0_6ObjectES3_PNS0_6StringE
+ fun:_ZN2v88internal6Object11GetPropertyEPS1_PNS0_12LookupResultEPNS0_6StringEP18PropertyAttributes
+ fun:_ZN2v88internal6LoadIC4LoadENS0_16InlineCacheStateENS0_6HandleINS0_6ObjectEEENS3_INS0_6StringEEE
+ fun:_ZN2v88internal11LoadIC_MissENS0_9ArgumentsEPNS0_7IsolateE
+}
+{
+ bug_138233_b
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10RefCountedIN7WebCore17ScriptProfileNodeEEnwEm
+ fun:_ZN7WebCore17ScriptProfileNode6createEPKN2v814CpuProfileNodeE
+ fun:_ZNK7WebCore17ScriptProfileNode8childrenEv
+ fun:_ZN7WebCore27ScriptProfileNodeV8InternalL16childrenCallbackERKN2v89ArgumentsE
+}
+{
+ bug_138522
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF12AtomicStringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ fun:_ZN7WebCore*V8StringResourceILNS_20V8StringResourceMode*
+ ...
+ fun:_ZN7WebCore23WorkerContextV8InternalL22addEventListenerMethodERKN2v89ArgumentsE
+}
+{
+ bug_138712
+ Memcheck:Uninitialized
+ fun:_ZN7testing8internal11CmpHelperGEIddEENS_15AssertionResultEPKcS4_RKT_RKT0_
+ fun:_ZN3gfx30JPEGCodec_EncodeDecodeRGB_Test8TestBodyEv
+}
+{
+ bug_16089 WorkerPool threads and its tasks can leak by design
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base22PosixDynamicThreadPool7AddTaskEPNS_11PendingTaskE
+ fun:_ZN4base22PosixDynamicThreadPool8PostTask*
+}
+{
+ bug_139467
+ Memcheck:Uninitialized
+ fun:_ZNK7WebCore18AccessibilityTable9roleValueEv
+ fun:_ZNK7WebCore25AccessibilityRenderObject20ariaLiveRegionStatusEv
+ fun:_ZNK7WebCore19AccessibilityObject22supportsARIALiveRegionEv
+ fun:_ZNK7WebCore19AccessibilityObject22supportsARIAAttributesEv
+ fun:_ZN7WebCore25AccessibilityRenderObject26determineAccessibilityRoleEv
+ fun:_ZN7WebCore23AccessibilityNodeObject4initEv
+ fun:_ZN7WebCore25AccessibilityRenderObject4initEv
+ fun:_ZN7WebCore18AccessibilityTable4initEv
+}
+{
+ bug_139470
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore22ThreadableBlobRegistry17unregisterBlobURLERKNS_4KURLE
+ ...
+ fun:_ZN7WebCore15WrapperTypeInfo11derefObjectEPv
+ fun:_ZN7WebCore7DOMData11derefObjectEPNS_15WrapperTypeInfoEPv
+ fun:_ZN7WebCore7DOMData23WrapperMapObjectRemoverIvE15visitDOMWrapperEPNS_12DOMDataStoreEPvN2v810PersistentINS6_6ObjectEEE
+ fun:_ZN7WebCore16WeakReferenceMapIvN2v86ObjectEE5visitEPNS_12DOMDataStoreEPNS_24AbstractWeakReferenceMapIvS2_E7VisitorE
+ fun:_ZN7WebCore7DOMData27removeObjectsFromWrapperMapIvEEvPNS_12DOMDataStoreERNS_24AbstractWeakReferenceMapIT_N2v86ObjectEEE
+ fun:_ZN7WebCore19removeAllDOMObjectsEv
+ fun:_ZN7WebCore22WorkerScriptControllerD1Ev
+ fun:_ZN3WTF14deleteOwnedPtrIN7WebCore22WorkerScriptControllerEEEvPT_
+ fun:_ZN3WTF6OwnPtrIN7WebCore22WorkerScriptControllerEE5clearEv
+ fun:_ZN7WebCore13WorkerContext11clearScriptEv
+ fun:_ZN7WebCore30WorkerThreadShutdownFinishTask11performTaskEPNS_22ScriptExecutionContextE
+ fun:_ZN7WebCore13WorkerRunLoop4Task11performTaskERKS0_PNS_22ScriptExecutionContextE
+ fun:_ZN7WebCore13WorkerRunLoop9runInModeEPNS_13WorkerContextERKNS_13ModePredicateENS0_8WaitModeE
+ fun:_ZN7WebCore13WorkerRunLoop3runEPNS_13WorkerContextE
+ fun:_ZN7WebCore12WorkerThread12runEventLoopEv
+ fun:_ZN7WebCore21DedicatedWorkerThread12runEventLoopEv
+}
+{
+ bug_139662
+ Memcheck:Uninitialized
+ fun:qcms_transform_data_rgba_out_lut_sse2
+ fun:qcms_transform_data_type
+ fun:_ZN7WebCore16JPEGImageDecoder15outputScanlinesEv
+ fun:_ZN7WebCore15JPEGImageReader6decodeERKNS_12SharedBufferEb
+}
+{
+ bug_139853
+ Memcheck:Unaddressable
+ fun:_ZN11SkGpuDeviceC1EP9GrContextP9GrTexture
+ fun:_ZN7WebCoreL23createAcceleratedCanvas*
+ fun:_ZN7WebCore45FrameBufferSkPictureCanvasLayerTextureUpdater17*
+ fun:_ZN7WebCore45FrameBufferSkPictureCanvasLayerTextureUpdater7Texture10updateRectEPNS_18CCResourceProviderERKNS_7IntRectES6_
+ fun:_ZN7WebCore12_GLOBAL__N_126UnthrottledTextureUploader13uploadTextureEPNS_19LayerTextureUpdater7TextureEPNS_18CCResourceProviderENS_7IntRectES7_
+ fun:_ZN7WebCore16CCTextureUpdater6updateEPNS_18CCResourceProviderEPNS_13TextureCopierEPNS_15TextureUploaderEm
+ fun:_ZN7WebCore19CCSingleThreadProxy8doCommitERNS_16CCTextureUpdaterE
+ fun:_ZN7WebCore19CCSingleThreadProxy18commitAndCompositeEv
+ fun:_ZN7WebCore19CCSingleThreadProxy20compositeAndReadbackEPvRKNS_7IntRectE
+ fun:_ZN7WebCore15CCLayerTreeHost20compositeAndReadbackEPvRKNS_7IntRectE
+ fun:_ZN6WebKit16WebLayerTreeView20compositeAndReadbackEPvRKNS_7WebRectE
+ fun:_ZN6WebKit11WebViewImpl23doPixelReadbackToCanvasEP8SkCanvasRKN7WebCore7IntRectE
+ fun:_ZN6WebKit11WebViewImpl5paintEP8SkCanvasRKNS_7WebRectE
+ fun:_ZN11WebViewHost9paintRectERKN6WebKit7WebRectE
+ fun:_ZN11WebViewHost22paintInvalidatedRegionEv
+}
+{
+ bug_139996
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF6StringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ fun:_ZN7WebCore15toWebCoreStringEN2v86HandleINS0_5ValueEEE
+ fun:_ZN7WebCore6V8Blob19constructorCallbackERKN2v89ArgumentsE
+ fun:_ZN2v88internalL19HandleApiCallHelperILb1EEEPNS0_11MaybeObjectENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+ fun:_ZN2v88internalL30Builtin_HandleApiCallConstructENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+}
+{
+ bug_139998
+ Memcheck:Leak
+ fun:*alloc
+ ...
+ fun:_ZL23link_intrastage_shadersP14__GLcontextRecP17gl_shader_programPP9gl_shaderj
+ fun:_Z12link_shadersP14__GLcontextRecP17gl_shader_program
+ fun:_mesa_glsl_link_shader
+ fun:link_program
+ fun:_mesa_LinkProgramARB
+ fun:glLinkProgram
+ ...
+ fun:_ZN3gpu5gles216GLES2DecoderImpl13DoLinkProgramEj
+ fun:_ZN3gpu5gles216GLES2DecoderImpl17HandleLinkProgram*
+ fun:_ZN3gpu5gles216GLES2DecoderImpl9DoCommandEjjPKv
+ fun:_ZN3gpu13CommandParser14ProcessCommandEv
+ fun:_ZN3gpu12GpuScheduler10PutChangedEv
+ fun:_ZN6webkit3gpu18GLInProcessContext12PumpCommandsEv
+}
+{
+ bug_140196
+ Memcheck:Uninitialized
+ fun:_ZNK12SkDescriptor6equalsERKS_
+ fun:_ZN12SkGlyphCache10VisitCacheEPK12SkDescriptorPFbPKS_PvES5_
+ ...
+ fun:_ZNK7SkPaint14descriptorProcEPK8SkMatrixPFvPK12SkDescriptorPvES6_b
+}
+{
+ bug_143545
+ Memcheck:Uninitialized
+ fun:_ZN4aura10RootWindow10ShowCursorEb
+ fun:_ZN3ash5Shell10ShowCursorEb
+ fun:_ZN3ash13CursorManager10ShowCursorEb
+ fun:_ZN3ash4test11AshTestBase5SetUpEv
+}
+{
+ bug_144118
+ Memcheck:Unaddressable
+ fun:NPP_SetWindow
+ fun:_ZN6webkit5npapi14PluginInstance13NPP_SetWindowEP9_NPWindow
+ fun:_ZN6webkit5npapi21WebPluginDelegateImpl17WindowedSetWindowEv
+ fun:_ZN6webkit5npapi21WebPluginDelegateImpl22WindowedUpdateGeometryERKN3gfx4RectES5_
+ fun:_ZN6webkit5npapi21WebPluginDelegateImpl14UpdateGeometryERKN3gfx4RectES5_
+ fun:_ZN6webkit5npapi13WebPluginImpl14updateGeometryERKN6WebKit7WebRectES5_RKNS2_9WebVectorIS3_EEb
+ fun:_ZN6WebKit22WebPluginContainerImpl14reportGeometryEv
+ fun:_ZN6WebKit22WebPluginContainerImpl12setFrameRectERKN7WebCore7IntRectE
+ ...
+ fun:_ZN9TestShell4dumpEv
+}
+{
+ bug_144118_b
+ Memcheck:Unaddressable
+ fun:_ZNK3WTF6OwnPtrIN6WebKit14ScrollbarGroupEEcvMS3_PS2_Ev
+ fun:_ZN6WebKit22WebPluginContainerImpl14reportGeometryEv
+ fun:_ZN6WebKit22WebPluginContainerImpl12setFrameRectERKN7WebCore7IntRectE
+ ...
+ fun:_ZN9TestShell4dumpEv
+}
+{
+ bug_144913
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN8chromeos30BluetoothAdapterClientStubImplC1Ev
+ fun:_ZN8chromeos22BluetoothAdapterClient6CreateENS_28DBusClientImplementationTypeEPN4dbus3BusEPNS_22BluetoothManagerClientE
+ fun:_ZN8chromeos21DBusThreadManagerImplC1ENS_28DBusClientImplementationTypeE
+ fun:_ZN8chromeos17DBusThreadManager10InitializeEv
+ fun:_ZN8chromeos23KioskModeIdleLogoutTest5SetUpEv
+}
+{
+ bug_144913_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN8chromeos17DBusThreadManager10InitializeEv
+ fun:_ZN8chromeos23KioskModeIdleLogoutTest5SetUpEv
+}
+{
+ bug_144913_c
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN8chromeos21DBusThreadManagerImplC1ENS_28DBusClientImplementationTypeE
+ fun:_ZN8chromeos17DBusThreadManager10InitializeEv
+ fun:_ZN8chromeos23KioskModeIdleLogoutTest5SetUpEv
+}
+{
+ bug_144930
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZL20cachedPaintLuminancef
+}
+{
+ bug_144930_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZL21cachedDeviceLuminancef
+}
+{
+ bug_145244
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore15StyleRuleImport17requestStyleSheetEPNS_13CSSStyleSheetERKNS_16CSSParserContextE
+ fun:_ZN7WebCore18StyleSheetContents26requestImportedStyleSheetsEPNS_13CSSStyleSheetE
+}
+{
+ bug_145645
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10RefCountedIN7WebCore18InjectedScriptHostEEnwEm
+ fun:_ZN7WebCore18InjectedScriptHost6createEv
+ fun:_ZN7WebCore21InjectedScriptManagerC1EPFbPNS_11ScriptStateEE
+ fun:_ZN7WebCore21InjectedScriptManager15createForWorkerEv
+ fun:_ZN7WebCore25WorkerInspectorControllerC1EPNS_13WorkerContextE
+}
+{
+ bug_145650a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN14WebDataService10AddKeywordERK15TemplateURLData
+ fun:_ZN18TemplateURLService11AddNoNotifyEP11TemplateURLb
+}
+{
+ bug_145650b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN14WebDataService13RemoveKeywordEl
+ fun:_ZN18TemplateURLService14RemoveNoNotifyEP11TemplateURL
+ fun:_ZN18TemplateURLService6RemoveEP11TemplateURL
+ fun:_ZN9protector71DefaultSearchProviderChangeTest_CurrentSearchProviderRemovedByUser_Test19RunTestOnMainThreadEv
+}
+{
+ bug_145650c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN14WebDataService13UpdateKeywordERK15TemplateURLData
+ fun:_ZN18TemplateURLService32SetDefaultSearchProviderNoNotifyEP11TemplateURL
+}
+{
+ bug_125692a
+ Memcheck:Uninitialized
+ fun:_ZN2v88internal11StoreBuffer28IteratePointersInStoreBufferEPFvPPNS0_10HeapObjectES3_E
+ fun:_ZN2v88internal11StoreBuffer25IteratePointersToNewSpaceEPFvPPNS0_10HeapObjectES3_E
+ fun:_ZN2v88internal20MarkCompactCollector29EvacuateNewSpaceAndCandidatesEv
+ fun:_ZN2v88internal20MarkCompactCollector11SweepSpacesEv
+ fun:_ZN2v88internal20MarkCompactCollector14CollectGarbageEv
+ fun:_ZN2v88internal4Heap11MarkCompactEPNS0_8GCTracerE
+}
+{
+ bug_125692b
+ Memcheck:Uninitialized
+ fun:_ZN2v88internal11StoreBuffer7CompactEv
+ fun:_ZN2v88internal11StoreBuffer19PrepareForIterationEv
+ fun:_ZN2v88internal11StoreBuffer25IteratePointersToNewSpaceEPFvPPNS0_10HeapObjectES3_E
+ fun:_ZN2v88internal20MarkCompactCollector29EvacuateNewSpaceAndCandidatesEv
+ fun:_ZN2v88internal20MarkCompactCollector11SweepSpacesEv
+ fun:_ZN2v88internal20MarkCompactCollector14CollectGarbageEv
+ fun:_ZN2v88internal4Heap11MarkCompactEPNS0_8GCTracerE
+ fun:_ZN2v88internal4Heap24PerformGarbageCollectionENS0_16GarbageCollectorEPNS0_8GCTracerE
+ fun:_ZN2v88internal4Heap14CollectGarbageENS0_15AllocationSpaceENS0_16GarbageCollectorEPKcS5_
+ fun:_ZN2v88internal4Heap14CollectGarbageENS0_15AllocationSpaceEPKc
+ fun:_ZN2v88internal4Heap17CollectAllGarbageEiPKc
+ fun:_ZN2v88internal4Heap16IdleNotificationEi
+ fun:_ZN2v88internal2V816IdleNotificationEi
+ fun:_ZN2v82V816IdleNotificationEi
+ fun:_ZN16RenderThreadImpl11IdleHandlerEv
+}
+{
+ bug_145693
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN10extensions18PermissionsUpdater17RecordOAuth2GrantEPKNS_9ExtensionE
+ fun:_ZN10extensions18PermissionsUpdater22GrantActivePermissionsEPKNS_9ExtensionEb
+ fun:_ZN10extensions12CrxInstaller25ReportSuccessFromUIThreadEv
+}
+{
+ bug_145695
+ Memcheck:Leak
+ fun:malloc
+ fun:NaClDescImcBoundDescAcceptConn
+ fun:RevRpcHandlerBase
+ fun:NaClThreadInterfaceStart
+}
+{
+ bug_145696
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN10extensions9TabHelper23OnInlineWebstoreInstallEiiRKSsRK4GURL
+}
+{
+ bug_145697
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN18SecurityFilterPeer40CreateSecurityFilterPeerForDeniedRequestEN12ResourceType4TypeEPN11webkit_glue20ResourceLoaderBridge4PeerEi
+ fun:_ZN12_GLOBAL__N_124RendererResourceDelegate17OnRequestCompleteEPN11webkit_glue20ResourceLoaderBridge4PeerEN12ResourceType4TypeERKN3net16URLRequestStatusE
+ fun:_ZN7content18ResourceDispatcher17OnRequestCompleteEiRKN3net16URLRequestStatusERKSsRKN4base9TimeTicksE
+}
+{
+ bug_145698
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN6chrome24ShowSessionCrashedPromptEP7Browser
+ fun:_ZN25StartupBrowserCreatorImpl22AddInfoBarsIfNecessaryEP7BrowserN6chrome7startup16IsProcessStartupE
+ fun:_ZN25StartupBrowserCreatorImpl17ProcessLaunchURLsEbRKSt6vectorI4GURLSaIS1_EE
+ fun:_ZN25StartupBrowserCreatorImpl6LaunchEP7ProfileRKSt6vectorI4GURLSaIS3_EEb
+}
+{
+ bug_145699
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN17OAuth2ApiCallFlow24CreateAccessTokenFetcherEv
+ fun:_ZN17OAuth2ApiCallFlow20BeginMintAccessTokenEv
+ fun:_ZN17OAuth2ApiCallFlow12BeginApiCallEv
+ fun:_ZN17OAuth2ApiCallFlow5StartEv
+ fun:_ZN19OAuth2MintTokenFlow13FireAndForgetEv
+}
+{
+ bug_145703
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN7content16SiteInstanceImpl10GetProcessEv
+ fun:_ZN7content18RenderViewHostImplC1EPNS_12SiteInstanceEPNS_22RenderViewHostDelegateEPNS_24RenderWidgetHostDelegateEibPNS_23SessionStorageNamespaceE
+ fun:_ZN7content21RenderViewHostFactory6CreateEPNS_12SiteInstanceEPNS_22RenderViewHostDelegateEPNS_24RenderWidgetHostDelegateEibPNS_23SessionStorageNamespaceE
+ fun:_ZN7content21RenderViewHostManager4InitEPNS_14BrowserContextEPNS_12SiteInstanceEi
+ fun:_ZN7content15WebContentsImpl4InitERKNS_11WebContents12CreateParamsE
+ fun:_ZN7content15TestWebContents6CreateEPNS_14BrowserContextEPNS_12SiteInstanceE
+ fun:_ZN7content17WebContentsTester21CreateTestWebContentsEPNS_14BrowserContextEPNS_12SiteInstanceE
+}
+{
+ bug_145704
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2v88internal5Debug17CreateScriptCacheEv
+ fun:_ZN2v88internal5Debug16GetLoadedScriptsEv
+ fun:_ZN2v88internal29Runtime_DebugGetLoadedScriptsENS0_9ArgumentsEPNS0_7IsolateE
+}
+{
+ bug_145705
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN10extensions16SettingsFrontendC1ERK13scoped_refptrINS_22SettingsStorageFactoryEEP7Profile
+ fun:_ZN10extensions16SettingsFrontend6CreateEP7Profile
+ fun:_ZN16ExtensionServiceC1E*
+}
+{
+ bug_145708
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN27ExtensionDevToolsClientHostC1EPN7content11WebContentsERKSsS4_i
+ fun:_ZN22AttachDebuggerFunction7RunImplEv
+ fun:_ZN17ExtensionFunction3RunEv
+ fun:_ZN27ExtensionFunctionDispatcher8DispatchERK31ExtensionHostMsg_Request_ParamsPN7content14RenderViewHostE
+ fun:_ZN10extensions13ExtensionHost9OnRequestERK31ExtensionHostMsg_Request_Params
+}
+{
+ bug_145712
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN6WebKit25NotificationPresenterImpl17requestPermissionEPN7WebCore22Scri ptExecutionContextEN3WTF10PassRefPtrINS1_12VoidCallbackEEE
+ fun:_ZN7WebCore18NotificationCenter17requestPermissionEN3WTF10PassRefPtrINS_1 2VoidCallbackEEE
+ fun:_ZN7WebCore20V8NotificationCenter25requestPermissionCallbackERKN2v89Argum entsE
+}
+{
+ bug_145723
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_Z20NewExtensionFunctionI25TabsExecuteScriptFunctionEP17ExtensionFunctionv
+ fun:_ZN25ExtensionFunctionRegistry11NewFunctionERKSs
+ fun:_ZN27ExtensionFunctionDispatcher23CreateExtensionFunctionERK31ExtensionHostMsg_Request_ParamsPKN10extensions9ExtensionEiRKNS3_10ProcessMapEPNS3_12ExtensionAPIEPvPN3IPC6SenderEPN7content14RenderViewHostEi
+ fun:_ZN27ExtensionFunctionDispatcher8DispatchERK31ExtensionHostMsg_Request_ParamsPN7content14RenderViewHostE
+ fun:_ZN10extensions13ExtensionHost9OnRequestERK31ExtensionHostMsg_Request_Params
+}
+{
+ bug_145733
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN25ExtensionInstallUIDefault35GetNewThemeInstalledInfoBarDelegateEP11TabContentsPKN10extensions9ExtensionERKSsb
+ fun:_ZN25ExtensionInstallUIDefault16ShowThemeInfoBarERKSsbPKN10extensions9ExtensionEP7Profile
+ fun:_ZN25ExtensionInstallUIDefault16OnInstallSuccessEPKN10extensions9ExtensionEP8SkBitmap
+ fun:_ZN22ExtensionInstallPrompt16OnInstallSuccessEPKN10extensions9ExtensionEP8SkBitmap
+ fun:_ZN10extensions12CrxInstaller25ReportSuccessFromUIThreadEv
+}
+{
+ bug_145735
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIcE8allocateEmPKv
+ fun:_ZNSt12_Vector_baseIcSaIcEE11_M_allocateEm
+ fun:_ZNSt12_Vector_baseIcSaIcEEC2EmRKS0_
+ fun:_ZNSt6vectorIcSaIcEEC1EmRKcRKS0_
+ fun:_ZN4base5files12_GLOBAL__N_121InotifyReaderCallbackEPNS1_13InotifyReaderEii
+}
+{
+ bug_145747a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN24TranslateInfoBarDelegate19CreateErrorDelegateEN15TranslateErrors4TypeEP14InfoBarServiceP11PrefServiceRKSsS7_
+ fun:_ZN16TranslateManager14PageTranslatedEPN7content11WebContentsEP21PageTranslatedDetails
+ fun:_ZN16TranslateManager7ObserveEiRKN7content18NotificationSourceERKNS0_19NotificationDetailsE
+ fun:_ZN23NotificationServiceImpl6NotifyEiRKN7content18NotificationSourceERKNS0_19NotificationDetailsE
+ fun:_ZN18TranslateTabHelper16OnPageTranslatedEiRKSsS1_N15TranslateErrors4TypeE
+}
+{
+ bug_145747b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN24TranslateInfoBarDelegate19CreateErrorDelegateEN15TranslateErrors4TypeEP14InfoBarServiceP11PrefServiceRKSsS7_
+ fun:_ZN16TranslateManager18OnURLFetchCompleteEPKN3net10URLFetcherE
+ fun:_ZN20TranslateManagerTest31SimulateTranslateScriptURLFetchEb
+}
+{
+ bug_146464
+ Memcheck:Leak
+ fun:realloc
+ fun:add_codeset.isra.10
+ ...
+ fun:XCreatePixmap
+ fun:XCreateBitmapFromData
+ ...
+ fun:_ZN4aura19RootWindowHostLinuxC1EPNS_22RootWindowHostDelegateERKN3gfx4RectE
+}
+{
+ bug_146950
+ Memcheck:Leak
+ fun:malloc
+ fun:get_peer_sock_name
+ fun:_xcb_get_auth_info
+ fun:xcb_connect_to_display_with_auth_info
+ fun:_XConnectXCB
+ fun:XOpenDisplay
+ fun:_ZN4base18MessagePumpAuraX1118GetDefaultXDisplayEv
+}
+{
+ bug_147755_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12PluginFinder18GetPluginInstallerERKN6webkit13WebPluginInfoE
+ fun:_ZN11PluginPrefs30EnablePluginIfPossibleCallbackE*
+}
+{
+ bug_147755_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12PluginFinder17GetPluginMetadataERKN6webkit13WebPluginInfoE
+ fun:_ZN11PluginPrefs12EnablePluginE*
+ fun:_ZN15PluginPrefsTest25EnablePluginSynchronouslyE*
+ fun:_ZN44PluginPrefsTest_UnifiedPepperFlashState_Test8TestBodyEv
+}
+{
+ bug_148637_a
+ Memcheck:Unaddressable
+ ...
+ fun:_ZN9SkPathRef6EditorC1EP12SkAutoTUnrefIS_Eii
+ fun:_ZN6SkPath10incReserveEj
+ fun:_ZN7WebCoreL23setPathFromConvexPointsEP6SkPathmPKNS_10FloatPointE
+ fun:_ZN7WebCore15GraphicsContext17drawConvexPolygonEmPKNS_10FloatPointEb
+}
+{
+ bug_148637_b
+ Memcheck:Unaddressable
+ fun:_Z13sk_atomic_incPi
+ fun:_ZNK8SkRefCnt3refEv
+ fun:_ZN9SkPathRef11CreateEmptyEv
+ fun:_ZN6SkPathC1Ev
+ fun:_ZN11SkClipStack3RecC1EiRK6SkRectN8SkRegion2OpEb
+ fun:_ZN11SkClipStack11clipDevRectERK6SkRectN8SkRegion2OpEb
+ fun:_ZN8SkCanvas8clipRectERK6SkRectN8SkRegion2OpEb
+ fun:_ZN7WebCore15GraphicsContext4clipERKNS_9FloatRectE
+ fun:_ZN7WebCore15GraphicsContext4clipERKNS_7IntRectE
+}
+{
+ bug_149734a
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF16VectorBufferBaseIN7WebCore9AttributeEE14allocateBufferEm
+ fun:_ZN3WTF12VectorBufferIN7WebCore9AttributeELm4EE14allocateBufferEm
+ fun:_ZN3WTF6VectorIN7WebCore9AttributeELm4EE22reserveInitialCapacityEm
+ fun:_ZN7WebCore20ElementAttributeData13cloneDataFromERKS0_RKNS_7ElementERS3_
+}
+{
+ bug_149734b
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF16VectorBufferBaseIN7WebCore9AttributeEE14allocateBufferEm
+ fun:_ZN3WTF12VectorBufferIN7WebCore9AttributeELm4EE14allocateBufferEm
+ fun:_ZN3WTF6VectorIN7WebCore9AttributeELm4EE15reserveCapacityEm
+ fun:_ZN3WTF6VectorIN7WebCore9AttributeELm4EE14expandCapacityEm
+ fun:_ZN3WTF6VectorIN7WebCore9AttributeELm4EE14expandCapacityEmPKS2_
+ fun:_ZN3WTF6VectorIN7WebCore9AttributeELm4EE14appendSlowCaseIS2_EEvRKT_
+ fun:_ZN7WebCore20ElementAttributeData12addAttributeERKNS_9AttributeEPNS_7ElementENS_30SynchronizationOfLazyAttributeE
+}
+{
+ bug_150995
+ Memcheck:Leak
+ fun:_Zna*
+ fun:_ZN14webkit_support12_GLOBAL__N_113DoLibpngWrite*
+ fun:_ZN14webkit_support26EncodeWithCompressionLevel*
+ fun:_ZN14webkit_support6EncodeEPKhNS_12_GLOBAL__N_111ColorFormat*
+ fun:_ZN14webkit_support25EncodeBGRAPNGWithChecksum*
+ fun:_ZNK9TestShell9dumpImageEP8SkCanvas
+ fun:_ZN9TestShell4dumpEv
+ fun:_ZN9TestShell12testFinishedEP11WebViewHost
+ fun:_ZN11WebViewHost12testFinishedEv
+ fun:_ZN13WebTestRunner10TestRunner9WorkQueue15processWorkSoonEv
+}
+{
+ bug_151006
+ Memcheck:Leak
+ fun:malloc
+ fun:uprv_malloc_46
+ fun:_ZN6icu_467UMemorynwEm
+ fun:_ZN6icu_4610DateFormat6createENS0_6EStyleES1_RKNS_6LocaleE
+ fun:_ZN6icu_4610DateFormat22createDateTimeInstanceENS0_6EStyleES1_RKNS_6LocaleE
+ fun:udat_open_46
+ fun:_ZNK7WebCore9LocaleICU14openDateFormatE16UDateFormatStyleS1_
+ fun:_ZN7WebCore9LocaleICU24initializeDateTimeFormatEv
+ fun:_ZN7WebCore9LocaleICU15shortTimeFormatEv
+ fun:_ZN7WebCore19DateTimeEditElement6layoutERKNS_9StepRangeERKNS_14DateComponentsERNS_9LocalizerE
+ fun:_ZN7WebCore19DateTimeEditElement13setEmptyValueERKNS_9StepRangeERKNS_14DateComponentsERNS_9LocalizerE
+ fun:_ZN7WebCore13TimeInputType20updateInnerTextValueEv
+ fun:_ZN7WebCore13TimeInputType19createShadowSubtreeEv
+ fun:_ZN7WebCore16HTMLInputElement10updateTypeEv
+ fun:_ZN7WebCore16HTMLInputElement14parseAttributeERKNS_9AttributeE
+ fun:_ZN7WebCore7Element16attributeChangedERKNS_9AttributeE
+ fun:_ZN7WebCore13StyledElement16attributeChangedERKNS_9AttributeE
+ fun:_ZN7WebCore7Element19parserSetAttributesERKN3WTF6VectorINS_9AttributeELm0EEENS_27FragmentScriptingPermissionE
+ fun:_ZN7WebCore20HTMLConstructionSite17createHTMLElementEPNS_15AtomicHTMLTokenE
+ fun:_ZN7WebCore20HTMLConstructionSite28insertSelfClosingHTMLElementEPNS_15AtomicHTMLTokenE
+ fun:_ZN7WebCore15HTMLTreeBuilder24processStartTagForInBodyEPNS_15AtomicHTMLTokenE
+ fun:_ZN7WebCore15HTMLTreeBuilder15processStartTagEPNS_15AtomicHTMLTokenE
+}
+{
+ bug_151007
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10RefCountedIN7WebCore15AtomicHTMLTokenEEnwEm
+ fun:_ZN7WebCore15AtomicHTMLToken6createERNS_9HTMLTokenE
+ fun:_ZN7WebCore15HTMLTreeBuilder22constructTreeFromTokenERNS_9HTMLTokenE
+ fun:_ZN7WebCore18HTMLDocumentParser13pumpTokenizerENS0_15SynchronousModeE
+ fun:_ZN7WebCore18HTMLDocumentParser23pumpTokenizerIfPossibleENS0_15SynchronousModeE
+ fun:_ZN7WebCore18HTMLDocumentParser6insertERKNS_15SegmentedStringE
+ fun:_ZN7WebCore18HTMLDocumentParser21parseDocumentFragmentERKN3WTF6StringEPNS_16DocumentFragmentEPNS_7ElementENS_27FragmentScriptingPermissionE
+ fun:_ZN7WebCore16DocumentFragment9parseHTMLERKN3WTF6StringEPNS_7ElementENS_27FragmentScriptingPermissionE
+ fun:_ZN7WebCore31createFragmentForInnerOuterHTMLERKN3WTF6StringEPNS_7ElementENS_27FragmentScriptingPermissionERi
+ fun:_ZN7WebCore11HTMLElement12setInnerHTMLERKN3WTF6StringERi
+ fun:_ZN7WebCore21HTMLElementV8InternalL19innerHTMLAttrSetterEN2v85LocalINS1_6StringEEENS2_INS1_5ValueEEERKNS1_12AccessorInfoE
+ fun:_ZN2v88internal21StoreCallbackPropertyENS0_9ArgumentsEPNS0_7IsolateE
+ ...
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+}
+{
+ bug_151017
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN19GrTextureStripAtlas8GetAtlasERKNS_4DescE
+ fun:_ZN16GrGradientEffectC2EP9GrContextRK20SkGradientShaderBaseN8SkShader8TileModeE
+ ...
+ fun:_ZN12_GLOBAL__N_121skPaint2GrPaintShaderEP11SkGpuDeviceRK7SkPaintbPNS0_19SkAutoCachedTextureEP7GrPaint
+ fun:_ZN11SkGpuDevice8drawRectERK6SkDrawRK6SkRectRK7SkPaint
+ fun:_ZN8SkCanvas8drawRectERK6SkRectRK7SkPaint
+ fun:_ZN7WebCore15GraphicsContext8fillRectERKNS_9FloatRectE
+ fun:_ZN7WebCore24CanvasRenderingContext2D8fillRectEffff
+ fun:_ZN7WebCore34CanvasRenderingContext2DV8InternalL16fillRectCallbackERKN2v89ArgumentsE
+ fun:_ZN2v88internalL19HandleApiCallHelperILb0EEEPNS0_11MaybeObjectENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+ fun:_ZN2v88internalL21Builtin_HandleApiCallENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+ ...
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+ fun:_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb
+ fun:_ZN2v88Function4CallENS_6HandleINS_6ObjectEEEiPNS1_INS_5ValueEEE
+}
+{
+ bug_151908
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN6webkit3gpu18GLInProcessContext22CreateOffscreenContextEPS1_RKN3gfx4SizeES2_PKcPKiNS3_13GpuPreferenceE
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl10InitializeEN6WebKit20WebGraphicsContext3D10AttributesEPS3_
+ fun:_ZN14webkit_support23CreateGraphicsContext3DERKN6WebKit20WebGraphicsContext3D10AttributesEPNS0_7WebViewE
+ fun:_ZN11WebViewHost19createOutputSurfaceEv
+ fun:_ZN6WebKit11WebViewImpl19createOutputSurfaceEv
+ fun:_ZN6WebKit20WebLayerTreeViewImpl19createOutputSurfaceEv
+}
+{
+ bug_155404
+ Memcheck:Uninitialized
+ fun:_ZN2v88internalL21ProfilerSignalHandlerEiP7siginfoPv
+ obj:/lib/libpthread-2.11.1.so
+}
+{
+ bug_156829
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content23AudioInputDeviceManager23EnumerateOnDeviceThread*
+}
+{
+ bug_158510
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore11RenderTable6layoutEv
+ ...
+ fun:_ZN7WebCore11RenderBlock6layoutEv
+}
+{
+ bug_158514
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN2v88internal16ProfileGenerator16RecordTickSampleERKNS0_10TickSampleE
+ fun:_ZN2v88internal23ProfilerEventsProcessor12ProcessTicksEj
+ fun:_ZN2v88internal23ProfilerEventsProcessor3RunEv
+ fun:_ZN2v88internalL11ThreadEntryEPv
+}
+{
+ bug_159005
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore13RenderMarquee18updateMarqueeStyleEv
+ fun:_ZN7WebCore11RenderLayer12styleChangedENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore22RenderLayerModelObject14styleDidChangeENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore9RenderBox14styleDidChangeENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore11RenderBlock14styleDidChangeENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore12RenderObject8setStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE
+}
+{
+ bug_160877
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN7content*DummyListenSocketC1Ev
+ fun:_ZNK7content*DummyListenSocketFactory15CreateAndListenEPN3net18StreamListenSocket8DelegateE
+ ...
+ fun:_ZN3net10HttpServerC1ERKNS_25StreamListenSocketFactoryEPNS0_8DelegateE
+ fun:_ZN7content23DevToolsHttpHandlerImpl4InitEv
+}
+{
+ bug_162825
+ Memcheck:Uninitialized
+ fun:bcmp
+ fun:_ZNK3gpu5gles221ShaderTranslatorCache26ShaderTranslatorInitParamsltERKS2_
+ fun:_ZNKSt4lessIN3gpu5gles221ShaderTranslatorCache26ShaderTranslatorInitParamsEEclERKS3_S6_
+ ...
+ fun:_ZNSt3mapIN3gpu5gles221ShaderTranslatorCache26ShaderTranslatorInitParamsEPNS1_16ShaderTranslatorESt4lessIS3_ESaISt4pairIKS3_S5_EEE4findERS9_
+ fun:_ZN3gpu5gles221ShaderTranslatorCache13GetTranslatorE12ShShaderType12ShShaderSpecPK18ShBuiltInResourcesNS0_25ShaderTranslatorInterface22GlslImplementationTypeENS7_27GlslBuiltInFunctionBehaviorE
+ fun:_ZN3gpu5gles216GLES2DecoderImpl26InitializeShaderTranslatorEv
+}
+{
+ bug_162828
+ Memcheck:Leak
+ fun:malloc
+ fun:_Z15sk_malloc_flagsmj
+ fun:_Z15sk_malloc_throwm
+ fun:_ZN6SkMask10AllocImageEm
+ fun:_ZL17drawRectsIntoMaskPK6SkRectiP6SkMask
+ fun:_ZN20SkBlurMaskFilterImpl17filterRectsToNineEPK6SkRectiRK8SkMatrixRK7SkIRectPN12SkMaskFilter9NinePatchE
+ fun:_ZN12SkMaskFilter10filterPathERK6SkPathRK8SkMatrixRK12SkRasterClipP9SkBounderP9SkBlitterN7SkPaint5StyleE
+ fun:_ZNK6SkDraw8drawPathERK6SkPathRK7SkPaintPK8SkMatrixb
+}
+{
+ bug_163111
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4dbus8Response14FromMethodCallEPNS_10MethodCallE
+ fun:_ZN8chromeos20IBusPanelServiceImpl*
+}
+{
+ bug_163922
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN10extensions16SettingsFrontendC1ERK13scoped_refptrINS_22SettingsStorageFactoryEEP7Profile
+ fun:_ZN10extensions16SettingsFrontend6CreateEP7Profile
+ fun:_ZN16ExtensionServiceC1E*
+ fun:_ZN10extensions19ExtensionSystemImpl6Shared4InitEb
+ fun:_ZN10extensions19ExtensionSystemImpl21InitForRegularProfileEb
+ fun:_ZN14ProfileManager22DoFinalInitForServicesEP7Profileb
+ fun:_ZN14ProfileManager11DoFinalInitEP7Profileb
+ fun:_ZN14ProfileManager10AddProfileEP7Profile
+ fun:_ZN14ProfileManager10GetProfileE*
+}
+{
+ bug_163924
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN28JSONAsynchronousUnpackerImpl22StartProcessOnIOThreadEN7content13BrowserThread2IDERKSs
+}
+{
+ bug_164176
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN18BrowserProcessImpl21PreMainMessageLoopRunEv
+ fun:_ZN22ChromeBrowserMainParts25PreMainMessageLoopRunImplEv
+ fun:_ZN22ChromeBrowserMainParts21PreMainMessageLoopRunEv
+ fun:_ZN7content15BrowserMainLoop13CreateThreadsEv
+ fun:_ZN7content21BrowserMainRunnerImpl10InitializeERKNS_18MainFunctionParamsE
+ fun:_ZN7content11BrowserMainERKNS_18MainFunctionParamsE
+ fun:_ZN7content23RunNamedProcessTypeMainERKSsRKNS_18MainFunctionParamsEPNS_19ContentMainDelegateE
+ fun:_ZN7content21ContentMainRunnerImpl3RunEv
+ fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
+ fun:ChromeMain
+}
+{
+ bug_164178
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net25MultiThreadedCertVerifier6VerifyEPNS_15X509CertificateERKSsiPNS_6CRLSetEPNS_16CertVerifyResultERKN4base8CallbackIFviEEEPPvRKNS_11BoundNetLogE
+ fun:_ZN3net25SingleRequestCertVerifier6VerifyEPNS_15X509CertificateERKSsiPNS_6CRLSetEPNS_16CertVerifyResultERKN4base8CallbackIFviEEERKNS_11BoundNetLogE
+ fun:_ZN3net18SSLClientSocketNSS12DoVerifyCertEi
+ fun:_ZN3net18SSLClientSocketNSS15DoHandshakeLoopEi
+ fun:_ZN3net18SSLClientSocketNSS21OnHandshakeIOCompleteEi
+}
+{
+ bug_164179
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net10URLFetcher6CreateERK4GURLNS0_11RequestTypeEPNS_18URLFetcherDelegateE
+ fun:_ZN18WebResourceService10StartFetchEv
+}
+{
+ bug_164198
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore9RenderBox15paintFillLayersERKNS_9PaintInfoERKNS_5ColorEPKNS_9FillLayerERKNS_10LayoutRectENS_24BackgroundBleedAvoidanceENS_17CompositeOperatorEPNS_12RenderObjectE
+ ...
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_11LayoutPointE
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_11LayoutPointE
+ fun:_ZN7WebCore11RenderLayer18paintLayerContentsEPNS_15GraphicsContextERKNS0_17LayerPaintingInfoEj
+ fun:_ZN7WebCore11RenderLayer31paintLayerContentsAndReflectionEPNS_15GraphicsContextERKNS0_17LayerPaintingInfoEj
+ fun:_ZN7WebCore11RenderLayer10paintLayerEPNS_15GraphicsContextERKNS0_17LayerPaintingInfoEj
+ fun:_ZN7WebCore11RenderLayer9paintListEPN3WTF6VectorIPS0_Lm0EEEPNS_15GraphicsContextERKNS0_17LayerPaintingInfoEj
+ fun:_ZN7WebCore11RenderLayer18paintLayerContentsEPNS_15GraphicsContextERKNS0_17LayerPaintingInfoEj
+ fun:_ZN7WebCore11RenderLayer31paintLayerContentsAndReflectionEPNS_15GraphicsContextERKNS0_17LayerPaintingInfoEj
+ fun:_ZN7WebCore11RenderLayer10paintLayerEPNS_15GraphicsContextERKNS0_17LayerPaintingInfoEj
+}
+{
+ bug_166470
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMN11dom_storage17DomStorageContextEFvRK4GURLE13scoped_refptrIS2_ES3_EENS_8CallbackINS_8internal9BindStateINSB_13FunctorTraitsIT_E12RunnableTypeENSF_7RunTypeEFvNSB_19CallbackParamTraitsIT0_E11StorageTypeENSI_IT1_E11StorageTypeEEE14UnboundRunTypeEEESE_RKSJ_RKSM_
+ fun:_ZN7content21DOMStorageContextImpl18DeleteLocalStorageERK4GURL
+ ...
+ fun:_ZN10extensions11DataDeleter13StartDeletingEP7ProfileRKSsRK4GURL
+ fun:_ZN16ExtensionService18UninstallExtensionESsbPSbItN4base20string16_char_traitsESaItEE
+}
+{
+ bug_166470c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11dom_storage19DomStorageNamespace24DeleteLocalStorageOriginERK4GURL
+ fun:_ZN11dom_storage17DomStorageContext18DeleteLocalStorageERK4GURL
+}
+{
+ bug_166470d
+ Memcheck:Leak
+ ...
+ fun:_ZN7fileapi26GetOriginIdentifierFromURLERK4GURL
+ fun:_ZN11dom_storage14DomStorageArea26DatabaseFileNameFromOriginERK4GURL
+ fun:_ZN11dom_storage14DomStorageAreaC1E*
+ fun:_ZN11dom_storage19DomStorageNamespace24DeleteLocalStorageOriginERK4GURL
+ fun:_ZN11dom_storage17DomStorageContext18DeleteLocalStorageERK4GURL
+}
+{
+ bug_166709
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMNS_12_GLOBAL__N_121PostTaskAndReplyRelayEFvvENS_8internal17UnretainedWrapper*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8Location*
+ ...
+ fun:_ZN16ExtensionService12AddExtensionEPKN10extensions9ExtensionE
+ fun:_ZN52BackgroundApplicationListModelTest_ExplicitTest_Test8TestBodyEv
+}
+{
+ bug_166709b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base12_GLOBAL__N_112CreateThreadEmbPNS_14PlatformThread8DelegateEPmNS_14ThreadPriorityE
+ fun:_ZN4base14PlatformThread6CreateEmPNS0_8DelegateEPm
+ fun:_ZN4base12SimpleThread5StartEv
+ fun:_ZN4base19SequencedWorkerPool6WorkerC1ERK13scoped_refptrIS0_EiRKSs
+ fun:_ZN4base19SequencedWorkerPool5Inner30FinishStartingAdditionalThreadEi
+ fun:_ZN4base19SequencedWorkerPool5Inner10ThreadLoopEPNS0_6WorkerE
+ fun:_ZN4base19SequencedWorkerPool6Worker3RunEv
+ fun:_ZN4base12SimpleThread10ThreadMainEv
+ fun:_ZN4base12_GLOBAL__N_110ThreadFuncEPv
+}
+{
+ bug_166709c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_
+ fun:_ZN7content13BrowserThread28PostBlockingPoolTaskAndReplyERKN15tracked_objects8LocationERKN4base8CallbackIFvvEEESA_
+ fun:_ZN10extensions11ImageLoader15LoadImagesAsyncEPKNS_9ExtensionERKSt6vectorINS0_19ImageRepresentationESaIS5_EERKN4base8CallbackIFvRKN3gfx5ImageEEEE
+}
+{
+ bug_166818
+ Memcheck:Leak
+ fun:malloc
+ fun:g_malloc
+ ...
+ fun:gdk_pixbuf_loader_load_module
+ fun:gdk_pixbuf_loader_close
+ fun:_ZN2ui12_GLOBAL__N_110LoadPixbufEPN4base22RefCountedStaticMemoryEb
+ fun:_ZN2ui14ResourceBundle19GetNativeImageNamedEiNS0_8ImageRTLE
+ fun:_ZN2ui14ResourceBundle19GetNativeImageNamedEi
+}
+{
+ bug_166819
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNK3sql10Connection21GetUntrackedStatementEPKc
+ fun:_ZNK3sql10Connection21DoesTableOrIndexExistEPKcS2_
+ fun:_ZNK3sql10Connection14DoesTableExistEPKc
+ fun:_ZN3sql9MetaTable14DoesTableExistEPNS_10ConnectionE
+ ...
+ fun:_ZN7history16TopSitesDatabase4InitE*
+ fun:_ZN7history15TopSitesBackend16InitDBOnDBThreadE*
+}
+{
+ bug_166819b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNK3sql10Connection21GetUntrackedStatementEPKc
+ fun:_ZNK3sql10Connection21DoesTableOrIndexExistEPKcS2_
+ fun:_ZNK3sql10Connection14DoesTableExistEPKc
+ fun:_ZN7history17ShortcutsDatabase11EnsureTableEv
+ fun:_ZN7history17ShortcutsDatabase4InitEv
+ fun:_ZN7history16ShortcutsBackend12InitInternalEv
+}
+{
+ bug_166976a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base19SequencedWorkerPool5Inner30FinishStartingAdditionalThreadEi
+ fun:_ZN4base19SequencedWorkerPool5Inner10ThreadLoopEPNS0_6WorkerE
+ fun:_ZN4base19SequencedWorkerPool6Worker3RunEv
+ fun:_ZN4base12SimpleThread10ThreadMainEv
+ fun:_ZN4base12_GLOBAL__N_110ThreadFuncEPv
+}
+{
+ bug_166976b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt10_List_nodeIPN4base13WaitableEvent6WaiterEEE8allocateEmPKv
+ fun:_ZNSt10_List_baseIPN4base13WaitableEvent6WaiterESaIS3_EE11_M_get_nodeEv
+ fun:_ZNSt4listIPN4base13WaitableEvent6WaiterESaIS3_EE14_M_create_nodeERKS3_
+ fun:_ZNSt4listIPN4base13WaitableEvent6WaiterESaIS3_EE9_M_insertESt14_List_iteratorIS3_ERKS3_
+ fun:_ZNSt4listIPN4base13WaitableEvent6WaiterESaIS3_EE9push_backERKS3_
+ fun:_ZN4base13WaitableEvent7EnqueueEPNS0_6WaiterE
+ fun:_ZN4base13WaitableEvent9TimedWaitERKNS_9TimeDeltaE
+ fun:_ZN4base13WaitableEvent4WaitEv
+ ...
+ fun:_ZN4base19SequencedWorkerPool6WorkerC1ERK13scoped_refptrIS0_EiRKSs
+ fun:_ZN4base19SequencedWorkerPool5Inner30FinishStartingAdditionalThreadEi
+ fun:_ZN4base19SequencedWorkerPool5Inner10ThreadLoopEPNS0_6WorkerE
+ fun:_ZN4base19SequencedWorkerPool6Worker3RunEv
+}
+{
+ bug_167175a
+ Memcheck:Leak
+ ...
+ fun:g_*
+ ...
+ fun:_ZN16BrowserWindowGtk11InitWidgetsEv
+ fun:_ZN16BrowserWindowGtk4InitEv
+ fun:_ZN13BrowserWindow19CreateBrowserWindowEP7Browser
+}
+{
+ bug_167175b
+ Memcheck:Leak
+ fun:malloc
+ obj:/lib/libpng12.so.0.42.0
+ fun:png_create_read_struct_2
+ ...
+ fun:_ZN15ReloadButtonGtkC1EP18LocationBarViewGtkP7Browser
+ fun:_ZN17BrowserToolbarGtk4InitEP10_GtkWindow
+ fun:_ZN16BrowserWindowGtk11InitWidgetsEv
+ fun:_ZN16BrowserWindowGtk4InitEv
+ fun:_ZN13BrowserWindow19CreateBrowserWindowEP7Browser
+}
+{
+ bug_167175d
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISbItN4base20string16_char_traitsESaItEEE8allocateEmPKv
+ fun:_ZNSt12_Vector_baseISbItN4base20string16_char_traitsESaItEESaIS3_EE11_M_allocateEm
+ ...
+ fun:_ZN15WrenchMenuModel5BuildEbb
+ fun:_ZN15WrenchMenuModelC1EPN2ui19AcceleratorProviderEP7Browserbb
+ fun:_ZN17BrowserToolbarGtkC1EP7BrowserP16BrowserWindowGtk
+ fun:_ZN16BrowserWindowGtk11InitWidgetsEv
+ fun:_ZN16BrowserWindowGtk4InitEv
+ fun:_ZN13BrowserWindow19CreateBrowserWindowEP7Browser
+}
+{
+ bug_164781a
+ Memcheck:Uninitialized
+ ...
+ fun:vp8cx_encode_*_macroblock
+ fun:thread_encoding_proc
+}
+{
+ bug_167481b
+ Memcheck:Uninitialized
+ ...
+ fun:encode_frame_to_data_rate
+ fun:vp8_get_compressed_data
+ fun:vp8e_encode
+ fun:vpx_codec_encode
+}
+{
+ bug_170340
+ Memcheck:Uninitialized
+ fun:_ZN3WTF12AtomicString3addEPKt
+ fun:_ZN3WTF12AtomicStringC1EPKt
+ fun:_ZN7WebCore18HTMLPreloadScanner12processTokenEv
+ fun:_ZN7WebCore18HTMLPreloadScanner4scanEv
+ fun:_ZN7WebCore18HTMLDocumentParser13pumpTokenizerENS0_15SynchronousModeE
+ fun:_ZN7WebCore18HTMLDocumentParser23pumpTokenizerIfPossibleENS0_15SynchronousModeE
+ fun:_ZN7WebCore18HTMLDocumentParser6appendERKNS_15SegmentedStringE
+ fun:_ZN7WebCore25DecodedDataDocumentParser5flushEPNS_14DocumentWriterE
+ fun:_ZN7WebCore14DocumentWriter3endEv
+ fun:_ZN7WebCore14DocumentLoader15finishedLoadingEv
+}
+{
+ bug_171722
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net12_GLOBAL__N_120URLRequestFtpJobTest9AddSocketEPNS_13MockReadWriteILNS_17MockReadWriteTypeE0EEEmPNS2_ILS3_1EEEm
+}
+{
+ bug_172005
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7leveldb10VersionSet11LogAndApplyEPNS_11VersionEditEPNS_4port5MutexE
+ fun:_ZN7leveldb2DB4OpenERKNS_7OptionsERKSsPPS0_
+ fun:_ZN11dom_storage22SessionStorageDatabase9TryToOpenEPPN7leveldb2DBE
+ fun:_ZN11dom_storage22SessionStorageDatabase8LazyOpenEb
+ fun:_ZN11dom_storage22SessionStorageDatabase24ReadNamespacesAndOriginsEPSt3mapISsSt6vectorI4GURLSaIS3_EESt4lessISsESaISt4pairIKSsS5_EEE
+ fun:_ZN11dom_storage17DomStorageContext36FindUnusedNamespacesInCommitSequenceERKSt3setISsSt4lessISsESaISsEES7_
+}
+{
+ bug_172005b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7leveldb6DBImplC1ERKNS_7OptionsERKSs
+ fun:_ZN7leveldb2DB4OpenERKNS_7OptionsERKSsPPS0_
+ fun:_ZN11dom_storage22SessionStorageDatabase9TryToOpenEPPN7leveldb2DBE
+ fun:_ZN11dom_storage22SessionStorageDatabase8LazyOpenEb
+ fun:_ZN11dom_storage22SessionStorageDatabase24ReadNamespacesAndOriginsEPSt3mapISsSt6vectorI4GURLSaIS3_EESt4lessISsESaISt4pairIKSsS5_EEE
+ fun:_ZN11dom_storage17DomStorageContext36FindUnusedNamespacesInCommitSequenceERKSt3setISsSt4lessISsESaISsEES7_
+}
+{
+ bug_172025
+ Memcheck:Uninitialized
+ fun:_ZN11WebViewHost19didCreateDataSourceEPN6WebKit8WebFrameEPNS0_13WebDataSourceE
+ fun:_ZN6WebKit21FrameLoaderClientImpl20createDocumentLoaderERKN7WebCore15ResourceRequestERKNS1_14SubstituteDataE
+ fun:_ZN7WebCore11FrameLoader4initEv
+ fun:_ZN7WebCore5Frame4initEv
+ fun:_ZN6WebKit12WebFrameImpl21initializeAsMainFrameEPN7WebCore4PageE
+ fun:_ZN6WebKit11WebViewImpl19initializeMainFrameEPNS_14WebFrameClientE
+ fun:_ZN9TestShell15createNewWindowERKN6WebKit6WebURLEP16DRTDevToolsAgentPN13WebTestRunner17WebTestInterfacesE
+ fun:_ZN9TestShell16createMainWindowEv
+ fun:_ZN9TestShell10initializeEv
+}
+{
+ bug_172884
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKiSt3setIPN10extensions15DeclarativeRuleINS5_16ContentConditionENS5_13ContentActionEEESt4lessISA_ESaISA_EEEEE8allocateEmPKv
+ ...
+ fun:_ZNSt3mapIiSt3setIPN10extensions15DeclarativeRuleINS1_16ContentConditionENS1_13ContentActionEEESt4lessIS6_ESaIS6_EES7_IiESaISt4pairIKiSA_EEE6insertESt17_Rb_tree_iteratorISE_ERKSE_
+ fun:_ZNSt3mapIiSt3setIPN10extensions15DeclarativeRuleINS1_16ContentConditionENS1_13ContentActionEEESt4lessIS6_ESaIS6_EES7_IiESaISt4pairIKiSA_EEEixERSD_
+ fun:_ZN10extensions20ContentRulesRegistry5ApplyEPN7content11WebContentsERKSt6vectorISsSaISsEE
+ fun:_ZN10extensions20ContentRulesRegistry20DidNavigateMainFrameEPN7content11WebContentsERKNS1_20LoadCommittedDetailsERKNS1_19FrameNavigateParamsE
+ fun:_ZN10extensions9TabHelper20DidNavigateMainFrameERKN7content20LoadCommittedDetailsERKNS1_19FrameNavigateParamsE
+ fun:_ZN7content15WebContentsImpl30DidNavigateMainFramePostCommitERKNS_20LoadCommittedDetailsERK32ViewHostMsg_FrameNavigate_Params
+ fun:_ZN7content15WebContentsImpl11DidNavigateEPNS_14RenderViewHostERK32ViewHostMsg_FrameNavigate_Params
+ fun:_ZN7content18RenderViewHostImpl10OnNavigateERKN3IPC7MessageE
+ fun:_ZN7content18RenderViewHostImpl17OnMessageReceivedERKN3IPC7MessageE
+ fun:_ZN7content21RenderProcessHostImpl17OnMessageReceivedERKN3IPC7MessageE
+ fun:_ZN3IPC12ChannelProxy7Context17OnDispatchMessageERKNS_7MessageE
+}
+{
+ bug_173096
+ Memcheck:Uninitialized
+ fun:bcmp
+ fun:_ZN2cc19LayerTreeDebugState5equalERKS0_S2_
+ fun:_ZN2cc13LayerTreeHost13setDebugStateERKNS_19LayerTreeDebugStateE
+ fun:_ZN6WebKit20WebLayerTreeViewImpl*set*
+ fun:_ZN6WebKit11WebViewImpl33setIsAcceleratedCompositingActiveEb
+ fun:_ZN6WebKit11WebViewImpl20setRootGraphicsLayerEPN7WebCore13GraphicsLayerE
+ fun:_ZN6WebKit16ChromeClientImpl23attachRootGraphicsLayerEPN7WebCore5FrameEPNS1_13GraphicsLayerE
+ fun:_ZN7WebCore21RenderLayerCompositor15attachRootLayerENS0_19RootLayerAttachmentE
+ fun:_ZN7WebCore21RenderLayerCompositor15ensureRootLayerEv
+ fun:_ZN7WebCore21RenderLayerCompositor21enableCompositingModeEb
+ fun:_ZN7WebCore21RenderLayerCompositor13updateBackingEPNS_11RenderLayerENS0_24CompositingChangeRepaintE
+ fun:_ZN7WebCore21RenderLayerCompositor27updateLayerCompositingStateEPNS_11RenderLayerENS0_24CompositingChangeRepaintE
+ fun:_ZN7WebCore11RenderLayer12styleChangedENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore22RenderLayerModelObject14styleDidChangeENS_15StyleDifferenceEPKNS_11RenderStyleE
+ fun:_ZN7WebCore9RenderBox14styleDidChangeENS_15StyleDifferenceEPKNS_11RenderStyleE
+}
+{
+ bug_175100
+ Memcheck:Leak
+ ...
+ fun:_ZN20OneClickSigninHelper14DidStopLoadingEPN7content14RenderViewHostE
+ fun:_ZN*OneClickSigninHelperTest*
+}
+{
+ bug_175815
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base5Value18CreateIntegerValueEi
+ fun:_ZNK4base16FundamentalValue8DeepCopyEv
+ fun:_ZN4base8internal12_GLOBAL__N_125DictionaryHiddenRootValue26RemoveWithoutPathExpansionERKSsPPNS_5ValueE
+ fun:_ZN4base15DictionaryValue6RemoveERKSsPPNS_5ValueE
+ fun:_ZN32PluginFinderTest_JsonSyntax_Test8TestBodyEv
+}
+{
+ bug_175823
+ Memcheck:Leak
+ ...
+ fun:_ZN18ValueStoreFrontend*
+}
+{
+ bug_175985
+ Memcheck:Uninitialized
+ fun:_ZN2cc13LayerTreeHost13setDebugStateERKNS_19LayerTreeDebugStateE
+ ...
+ fun:_ZN6WebKit20WebLayerTreeViewImpl*
+}
+{
+ bug_176270
+ Memcheck:Uninitialized
+ fun:_ZNK2cc19LayerTreeDebugState20recordRenderingStatsEv
+}
+{
+ bug_176616_a
+ Memcheck:Uninitialized
+ fun:_ZN13WebTestRunner16WebTestProxyBase19didCreateDataSourceEPN6WebKit8WebFrameEPNS1_13WebDataSourceE
+ fun:_ZN13WebTestRunner12WebTestProxyI11WebViewHostP9TestShellE19didCreateDataSourceEPN6WebKit8WebFrameEPNS5_13WebDataSourceE
+ fun:_ZN6WebKit21FrameLoaderClientImpl20createDocumentLoaderERKN7WebCore15ResourceRequestERKNS1_14SubstituteDataE
+ fun:_ZN7WebCore11FrameLoader4initEv
+ fun:_ZN7WebCore5Frame4initEv
+ fun:_ZN6WebKit12WebFrameImpl21initializeAsMainFrameEPN7WebCore4PageE
+ fun:_ZN6WebKit11WebViewImpl19initializeMainFrameEPNS_14WebFrameClientE
+ fun:_ZN9TestShell15createNewWindowERKN6WebKit6WebURLEP16DRTDevToolsAgentPN13WebTestRunner17WebTestInterfacesE
+ fun:_ZN9TestShell16createMainWindowEv
+ fun:_ZN9TestShell10initializeEP25MockWebKitPlatformSupport
+}
+{
+ bug_176616_b
+ Memcheck:Uninitialized
+ fun:_ZN13WebTestRunner10TestRunner5resetEv
+ fun:_ZN13WebTestRunner14TestInterfaces8resetAllEv
+ fun:_ZN13WebTestRunner17WebTestInterfaces8resetAllEv
+ fun:_ZN9TestShell19resetTestControllerEv
+ fun:_ZL7runTestR9TestShellR10TestParamsRKSsb
+}
+{
+ bug_176619_a
+ Memcheck:Uninitialized
+ fun:_ZN3WTF6StringC1EPKt
+ fun:_ZN7WebCore12WebVTTParser22constructTreeFromTokenEPNS_8DocumentE
+ fun:_ZN7WebCore12WebVTTParser33createDocumentFragmentFromCueTextERKN3WTF6StringE
+ fun:_ZN7WebCore12TextTrackCue20createWebVTTNodeTreeEv
+ fun:_ZN7WebCore12TextTrackCue22createCueRenderingTreeEv
+ fun:_ZN7WebCore12TextTrackCue17updateDisplayTreeEf
+}
+{
+ bug_176619_b
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore12WebVTTParser13collectDigitsERKN3WTF6StringEPj
+ fun:_ZN7WebCore12WebVTTParser16collectTimeStampERKN3WTF6StringEPj
+ fun:_ZN7WebCore12WebVTTParser22constructTreeFromTokenEPNS_8DocumentE
+ fun:_ZN7WebCore12WebVTTParser33createDocumentFragmentFromCueTextERKN3WTF6StringE
+ fun:_ZN7WebCore12TextTrackCue20createWebVTTNodeTreeEv
+ fun:_ZN7WebCore12TextTrackCue22createCueRenderingTreeEv
+ fun:_ZN7WebCore12TextTrackCue17updateDisplayTreeEf
+}
+{
+ bug_176621
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN13WebTestRunner10TestPlugin6createEPN6WebKit8WebFrameERKNS1_15WebPluginParamsEPNS_15WebTestDelegateE
+ fun:_ZN13WebTestRunner16WebTestProxyBase12createPluginEPN6WebKit8WebFrameERKNS1_15WebPluginParamsE
+ fun:_ZN13WebTestRunner12WebTestProxyI11WebViewHostP9TestShellE12createPluginEPN6WebKit8WebFrameERKNS5_15WebPluginParamsE
+ fun:_ZN6WebKit21FrameLoaderClientImpl12createPluginERKN7WebCore7IntSizeEPNS1_17HTMLPlugInElementERKNS1_4KURLERKN3WTF6VectorINSA_6String*
+ fun:_ZN7WebCore14SubframeLoader10loadPluginEPNS_22HTMLPlugInImageElementERKNS_4KURLERKN3WTF6StringERKNS6_6VectorIS7*
+}
+{
+ bug_176888
+ Memcheck:Leak
+ fun:malloc
+ fun:strdup
+ fun:p11_kit_registered_module_to_name
+ fun:gnutls_pkcs11_init
+ fun:gnutls_global_init
+ fun:_ZN12_GLOBAL__N_117GcryptInitializer4InitEv
+ fun:_ZN12_GLOBAL__N_117GcryptInitializerC1Ev
+ fun:_ZN4base25DefaultLazyInstanceTraitsIN12_GLOBAL__N_117GcryptInitializerEE3NewEPv
+}
+{
+ bug_176889_a
+ Memcheck:Uninitialized
+ fun:inflateReset2
+ fun:inflateInit2_
+ fun:png_create_read_struct_2
+ obj:/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so
+ obj:/usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0.2600.1
+ fun:gdk_pixbuf_loader*
+}
+{
+ bug_176889_b
+ Memcheck:Uninitialized
+ fun:sse2_composite_over_8888_8888
+ ...
+ fun:gdk_pixbuf_loader_close
+}
+{
+ bug_176889_c
+ Memcheck:Uninitialized
+ fun:sse2_combine_over_u
+ ...
+ fun:gdk_pixbuf_loader_close
+}
+{
+ bug_176889_d
+ Memcheck:Uninitialized
+ obj:*/librsvg-2.so*
+ fun:rsvg_handle_get_pixbuf_sub
+ obj:*/libpixbufloader-svg.so
+ fun:gdk_pixbuf_loader_close
+}
+{
+ bug_176889_e
+ Memcheck:Uninitialized
+ fun:gdk_pixbuf_saturate_and_pixelate
+}
+{
+ bug_176891a
+ Memcheck:Leak
+ fun:calloc
+ fun:nss_ZAlloc
+ fun:nssCryptokiObject_Create
+ fun:create_objects_from_handles
+ fun:find_objects
+ fun:find_objects_by_template
+ fun:nssToken_FindCertificateByEncodedCertificate
+ fun:PK11_FindCertFromDERCertItem
+ fun:_ZN24mozilla_security_manager12_GLOBAL__N_125nsPKCS12Blob_ImportHelper*
+}
+{
+ bug_176891b
+ Memcheck:Leak
+ ...
+ fun:nssPKIObject_Create
+ fun:nssTrustDomain_FindTrustForCertificate
+ fun:STAN_DeleteCertTrustMatchingSlot
+ fun:SEC_DeletePermCertificate
+ ...
+ fun:_ZN3net15NSSCertDatabase16DeleteCertAndKeyEPKNS_15X509CertificateE
+}
+{
+ bug_177213
+ Memcheck:Leak
+ ...
+ fun:_ZN10extensionsL9SerializeERKSt6vectorINS_10UserScriptESaIS1_EE
+}
+{
+ bug_178424a
+ Memcheck:Param
+ write(buf)
+ obj:/lib*/libpthread-*.so
+ fun:_ZN3net10FileStream7Context13WriteFileImplE13scoped_refptrINS_8IOBufferEEi
+}
+{
+ bug_178424b
+ Memcheck:Param
+ read(buf)
+ obj:/lib*/libpthread-*.so
+ fun:_ZN3net10FileStream7Context12ReadFileImplE13scoped_refptrINS_8IOBufferEEi
+}
+{
+ bug_179758_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base54WeakPtrTest_NonOwnerThreadCanCopyAndAssignWeakPtr_Test8TestBodyEv
+}
+{
+ bug_179758_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base58WeakPtrTest_NonOwnerThreadCanCopyAndAssignWeakPtrBase_Test8TestBodyEv
+}
+{
+ bug_180381
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN4base8FilePath31StripTrailingSeparatorsInternalEv
+ fun:_ZNK4base8FilePath7DirNameEv
+ fun:_ZN11dom_storage18DomStorageDatabase18GetJournalFilePathERKN4base8FilePathE
+ fun:_ZN11dom_storage27LocalStorageDatabaseAdapter11DeleteFilesEv
+ fun:_ZN11dom_storage14DomStorageArea12DeleteOriginEv
+ fun:_ZN11dom_storage19DomStorageNamespace24DeleteLocalStorageOriginERK4GURL
+ fun:_ZN11dom_storage17DomStorageContext18DeleteLocalStorageERK4GURL
+}
+{
+ bug_181038
+ Memcheck:Leak
+ ...
+ fun:_ZN3gfx9GLApiBase17glCompileShaderFnEj
+ fun:_ZN3gpu5gles214ProgramManager18ForceCompileShaderEPKSsPNS0_6ShaderEPNS0_16ShaderTranslatorEPNS0_11FeatureInfoE
+ fun:_ZN3gpu5gles214ProgramManager15DoCompileShaderEPNS0_6ShaderEPNS0_16ShaderTranslatorEPNS0_11FeatureInfoE
+ fun:_ZN3gpu5gles216GLES2DecoderImpl15DoCompileShaderEj
+}
+{
+ bug_181038_link
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:_ZN3gfx9GLApiBase15glLinkProgramFnEj
+ fun:_ZN3gpu5gles27Program4LinkEPNS0_13ShaderManagerEPNS0_16ShaderTranslatorES5_PNS0_11FeatureInfoE
+ fun:_ZN3gpu5gles216GLES2DecoderImpl13DoLinkProgramEj
+ fun:_ZN3gpu5gles216GLES2DecoderImpl17HandleLinkProgramEjRKNS0_4cmds11LinkProgramE
+ fun:_ZN3gpu5gles216GLES2DecoderImpl9DoCommandEjjPKv
+ fun:_ZN3gpu13CommandParser14ProcessCommandEv
+ fun:_ZN3gpu12GpuScheduler10PutChangedEv
+ fun:_ZN6webkit3gpu18GLInProcessContext12PumpCommandsEv
+}
+{
+ bug_181082
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12_GLOBAL__N_124ResourceLoaderBridgeImpl5StartEPN11webkit_glue20ResourceLoaderBridge4PeerE
+ fun:_ZN11webkit_glue16WebURLLoaderImpl7Context5StartERKN6WebKit13WebURLRequestEPNS_20ResourceLoaderBridge16SyncLoadResponseEPNS_25WebKitPlatformSupportImplE
+ fun:_ZN11webkit_glue16WebURLLoaderImpl18loadAsynchronouslyERKN6WebKit13WebURLRequestEPNS1_18WebURLLoaderClientE
+ fun:_ZN7WebCore22ResourceHandleInternal5start*
+ ...
+ fun:_ZN7WebCore14CachedResource4loadEPNS_20CachedResourceLoaderERKNS_21ResourceLoaderOptionsE
+ fun:_ZN7WebCore20CachedResourceLoader15requestResourceENS_14CachedResource4TypeERNS_21CachedResourceRequestE
+}
+{
+ bug_181680
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore11ScriptState10forContextEN2v85LocalINS1_7ContextEEE
+ fun:_ZN7WebCore17ScriptDebugServer12breakProgramEN2v86HandleINS1_6ObjectEEENS2_INS1_5ValueEEE
+ fun:_ZN7WebCore17ScriptDebugServer18handleV8DebugEventERKN2v85Debug12EventDetailsE
+ fun:_ZN7WebCore17ScriptDebugServer20v8DebugEventCallbackERKN2v85Debug12EventDetailsE
+ fun:_ZN2v88internal8Debugger18CallCEventCallbackENS_10DebugEventENS0_6HandleINS0_6ObjectEEES5_PNS_5Debug10ClientDataE
+}
+{
+ bug_184264
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore24createDragImageFromImageEPNS_5ImageENS_27RespectImageOrientationEnumE
+ fun:_ZN7WebCore5Frame21dragImageForSelectionEv
+ fun:_ZN7WebCore27createDragImageForSelectionEPNS_5FrameE
+ fun:_ZN7WebCore14DragController9startDragEPNS_5FrameERKNS_9DragStateENS_13DragOperationERKNS_18PlatformMouseEventERKNS_8IntPointE
+ fun:_ZN7WebCore12EventHandler10handleDragERKNS_28MouseEventWithHitTestResultsENS_19CheckDragHysteresisE
+ fun:_ZN7WebCore12EventHandler23handleMouseDraggedEventERKNS_28MouseEventWithHitTestResultsE
+ fun:_ZN7WebCore12EventHandler20handleMouseMoveEventERKNS_18PlatformMouseEventEPNS_13HitTestResultEb
+ fun:_ZN7WebCore12EventHandler28passMouseMoveEventToSubframeERNS_28MouseEventWithHitTestResultsEPNS_5FrameEPNS_13HitTestResultE
+ fun:_ZN7WebCore12EventHandler20handleMouseMoveEventERKNS_18PlatformMouseEventEPNS_13HitTestResultEb
+ fun:_ZN7WebCore12EventHandler10mouseMovedERKNS_18PlatformMouseEventE
+}
+{
+ bug_189194
+ Memcheck:Leak
+ ...
+ fun:*ProfileSigninConfirmationDialogTest_*
+}
+{
+ bug_195160_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeIiEE8allocateEmPKv
+ fun:_ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE11_M_get_nodeEv
+ fun:_ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE14_M_create_nodeERKi
+ fun:_ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE10_M_insert_EPKSt18_Rb_tree_node_baseS8_RKi
+ fun:_ZNSt8_Rb_treeIiiSt9_IdentityIiESt4lessIiESaIiEE16_M_insert_uniqueERKi
+ fun:_ZNSt3setIiSt4lessIiESaIiEE6insertERKi
+ fun:_ZN10extensions10URLMatcher14UpdateTriggersEv
+ fun:_ZN10extensions10URLMatcher28UpdateInternalDatastructuresEv
+ fun:_ZN10extensions10URLMatcher16AddConditionSetsERKSt6vectorI13scoped_refptrINS_22URLMatcherConditionSetEESaIS4_EE
+ fun:_ZN12_GLOBAL__N_113FilterBuilder5BuildEv
+ fun:_ZN12_GLOBAL__N_134LoadWhitelistsOnBlockingPoolThreadE12ScopedVectorI19ManagedModeSiteListE
+}
+{
+ bug_195160_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeIPN10extensions13StringPatternEEE8allocateEmPKv
+ fun:_ZNSt8_Rb_treeIPN10extensions13StringPatternES2_St9_IdentityIS2_ENS0_26URLMatcherConditionFactory27StringPatternPointerCompareESaIS2_EE11_M_get_nodeEv
+ fun:_ZNSt8_Rb_treeIPN10extensions13StringPatternES2_St9_IdentityIS2_ENS0_26URLMatcherConditionFactory27StringPatternPointerCompareESaIS2_EE14_M_create_nodeERKS2_
+ fun:_ZNSt8_Rb_treeIPN10extensions13StringPatternES2_St9_IdentityIS2_ENS0_26URLMatcherConditionFactory27StringPatternPointerCompareESaIS2_EE10_M_insert_EPKSt18_Rb_tree_node_baseSB_RKS2_
+ fun:_ZNSt8_Rb_treeIPN10extensions13StringPatternES2_St9_IdentityIS2_ENS0_26URLMatcherConditionFactory27StringPatternPointerCompareESaIS2_EE16_M_insert_uniqueERKS2_
+ fun:_ZNSt3setIPN10extensions13StringPatternENS0_26URLMatcherConditionFactory27StringPatternPointerCompareESaIS2_EE6insertERKS2_
+ fun:_ZN10extensions26URLMatcherConditionFactory15CreateConditionENS_19URLMatcherCondition9CriterionERKSs
+ fun:_ZN10extensions26URLMatcherConditionFactory35CreateHostSuffixPathPrefixConditionERKSsS2_
+ fun:_ZN6policy12URLBlacklist18CreateConditionSetEPN10extensions10URLMatcherEiRKSsS5_btS5_
+ fun:_ZN12_GLOBAL__N_113FilterBuilder10AddPatternERKSsi
+ fun:_ZN12_GLOBAL__N_113FilterBuilder11AddSiteListEP19ManagedModeSiteList
+ fun:_ZN12_GLOBAL__N_134LoadWhitelistsOnBlockingPoolThreadE12ScopedVectorI19ManagedModeSiteListE
+}
+{
+ bug_195160_c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_
+ fun:_ZN4base26PostTaskAndReplyWithResultI10scoped_ptrIN20ManagedModeURLFilter8ContentsENS_14DefaultDeleterIS3_EEES6_EEbPNS_10TaskRunnerERKN15tracked_objects8LocationERKNS_8CallbackIFT_vEEERKNSD_IFvT0_EEE
+ fun:_ZN20ManagedModeURLFilter14LoadWhitelistsE12ScopedVectorI19ManagedModeSiteListE
+}
+{
+ bug_222363
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN18WebDatabaseService12LoadDatabaseERKN4base8CallbackIFvN3sql10InitStatusEEEE
+}
+{
+ bug_222687a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN6chrome12_GLOBAL__N_134CreateMtabWatcherLinuxOnFileThread*
+}
+{
+ bug_222687b
+ Memcheck:Leak
+ ...
+ fun:_ZN4base26PostTaskAndReplyWithResultIPN6chrome16MtabWatcherLinux*
+ fun:_ZN7content13BrowserThread26PostTaskAndReplyWithResultIPN6chrome16MtabWatcherLinux*
+ fun:_ZN6chrome19StorageMonitorLinux4InitEv
+}
+{
+ bug_222687c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMN6chrome19StorageMonitorLinux*
+ fun:_ZN6chrome19StorageMonitorLinux4InitEv
+ fun:_ZN27ChromeBrowserMainPartsLinux15PostProfileInitEv
+ fun:_ZN22ChromeBrowserMainParts25PreMainMessageLoopRunImplEv
+ fun:_ZN22ChromeBrowserMainParts21PreMainMessageLoopRunEv
+ fun:_ZN7content15BrowserMainLoop13CreateThreadsEv
+}
+{
+ bug_222687d
+ Memcheck:Leak
+ ...
+ fun:_ZN21TestingBrowserProcess15storage_monitorEv
+ fun:_ZN6chrome14StorageMonitor11GetInstanceEv
+ fun:_ZN6chrome12_GLOBAL__N_131GetMediaTransferProtocolManagerEv
+ fun:_ZN6chrome40MediaTransferProtocolDeviceObserverLinuxD1Ev
+ fun:_ZN6chrome40MediaTransferProtocolDeviceObserverLinuxD0Ev
+ fun:_ZNK4base14DefaultDeleterIN6chrome40MediaTransferProtocolDeviceObserverLinuxEEclEPS2_
+ fun:_ZN4base8internal15scoped_ptr_implIN6chrome40MediaTransferProtocolDeviceObserverLinuxENS_14DefaultDeleterIS3_EEED1Ev
+ fun:_ZN10scoped_ptrIN6chrome40MediaTransferProtocolDeviceObserverLinuxEN4base14DefaultDeleterIS1_EEED1Ev
+ fun:_ZN6chrome19StorageMonitorLinuxD1Ev
+ ...
+ fun:_ZN6chrome4test18TestStorageMonitor15RemoveSingletonEv
+}
+{
+ bug_222876
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN21WebDataServiceWrapperC1EP7Profile
+ fun:_ZNK21WebDataServiceFactory23BuildServiceInstanceForEPN7content14BrowserContextE
+ fun:_ZN33BrowserContextKeyedServiceFactory27GetServiceForBrowserContextEPN7content14BrowserContextEb
+ fun:_ZN21WebDataServiceFactory13GetForProfileEP7ProfileNS0_17ServiceAccessTypeE
+ ...
+ fun:_ZN12TokenService10InitializeEPKcP7Profile
+}
+{
+ bug_222880
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF16VectorBufferBaseINS_6RefPtrIN7WebCore7ArchiveEEEE14allocateBufferEm
+ ...
+ fun:_ZN7WebCore7Archive18addSubframeArchiveEN3WTF10PassRefPtrIS0_EE
+ fun:_ZN7WebCore11MHTMLParser22parseArchiveWithHeaderEPNS_10MIMEHeaderE
+ fun:_ZN7WebCore11MHTMLParser12parseArchiveEv
+ fun:_ZN7WebCore12MHTMLArchive6createERKNS_4KURLEPNS_12SharedBufferE
+}
+{
+ bug_222883
+ Memcheck:Uninitialized
+ fun:_ZN2v88internal15ScavengeVisitor15ScavengePointerEPPNS0_6ObjectE.isra.327
+ fun:_ZN2v88internal15ScavengeVisitor13VisitPointersEPPNS0_6ObjectES4_
+ fun:_ZNK2v88internal13StandardFrame18IterateExpressionsEPNS0_13ObjectVisitorE
+ ...
+ fun:_ZN2v88internal4Heap8ScavengeEv
+ fun:_ZN2v88internal4Heap24PerformGarbageCollectionENS0_16GarbageCollectorEPNS0_8GCTracerE.constprop.678
+}
+{
+ bug_222887
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN6webkit3gpu18GLInProcessContext10InitializeERKN3gfx4SizeEPS1_PKcPKiNS2_13GpuPreferenceE
+ fun:_ZN6webkit3gpu18GLInProcessContext22CreateOffscreenContextEPS1_RKN3gfx4SizeES2_PKcPKiNS3_13GpuPreferenceE
+ fun:_ZN6webkit3gpu46WebGraphicsContext3DInProcessCommandBufferImpl10InitializeEN6WebKit20WebGraphicsContext3D10AttributesEPS3_
+ fun:_ZN25TestWebKitPlatformSupport32createOffscreenGraphicsContext3DERKN6WebKit20WebGraphicsContext3D10AttributesE
+ fun:_ZN7WebCore17GraphicsContext3D6createENS0_10AttributesEPNS_10HostWindowENS0_11RenderStyleE
+}
+{
+ bug_222898
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF9BitVector13OutOfLineBits6createEm
+ fun:_ZN3WTF9BitVector15resizeOutOfLineEm
+ fun:_ZN3WTF9BitVector10ensureSizeEm
+ fun:_ZN3WTF9BitVectorC1Em
+ fun:_ZN7WebCore10UseCounter10didObserveENS0_7FeatureE
+ fun:_ZN7WebCore10UseCounter7observeEPNS_8DocumentENS0_7FeatureE
+}
+{
+ bug_224747
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ ...
+ fun:_ZN64BackgroundApplicationListModelTest_AddRemovePermissionsTest_Test8TestBodyEv
+}
+{
+ bug_225028
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN31SafeBrowsingDatabaseFactoryImpl26CreateSafeBrowsingDatabaseEbbbb
+ fun:_ZN20SafeBrowsingDatabase6CreateEbbbb
+ fun:_ZN27SafeBrowsingDatabaseManager11GetDatabaseEv
+}
+{
+ bug_225596
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN8chromeos12input_method22InputMethodManagerImpl4InitERK13scoped_refptrIN4base19SequencedTaskRunnerEES7_
+ fun:_ZN8chromeos12input_method10InitializeERK13scoped_refptrIN4base19SequencedTaskRunnerEES6_
+ fun:_ZN8chromeos12input_method48InputMethodConfigurationTest_TestInitialize_Test8TestBodyEv
+}
+{
+ bug_226254
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMN10extensions16UserScriptMaster14ScriptReloader*
+ fun:_ZN10extensions16UserScriptMaster14ScriptReloader9StartLoad*
+ fun:_ZN10extensions16UserScriptMaster9StartLoadEv
+ fun:_ZN10extensions16UserScriptMaster7ObserveEiRKN7content18NotificationSourceERKNS1_19NotificationDetailsE
+}
+{
+ bug_227278a
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN7content35CompositingIOSurfaceTransformerTest13RunResizeTestERK8SkBitmapRKN3gfx4RectERKNS4_4SizeE
+ fun:_ZN7content65CompositingIOSurfaceTransformerTest_ResizesTexturesCorrectly_Test8TestBodyEv
+}
+{
+ bug_227278b
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN7content35CompositingIOSurfaceTransformerTest25RunTransformRGBToYV12TestERK8SkBitmapRKN3gfx4RectERKNS4_4SizeE
+ fun:_ZN7content60CompositingIOSurfaceTransformerTest_TransformsRGBToYV12_Test8TestBodyEv
+}
+{
+ bug_227278c
+ Memcheck:Uninitialized
+ fun:BitSetNextSetBit
+ fun:RegistersReInterfere
+ fun:RegistersMerge
+ fun:glpPPShaderLinearizeStreamMgr
+ fun:glpPPShaderLinearize
+ fun:glePrepareShaderForEmulation
+ fun:gleSetVPTransformFuncAll
+ fun:gleVPRenderQuadsSmooth
+ fun:gleDrawArraysOrElements_ExecCore
+ fun:glDrawArrays_Exec
+ fun:glDrawArrays
+ fun:_ZN7content12_GLOBAL__N_18DrawQuadEffffbff
+ fun:_ZN7content31CompositingIOSurfaceTransformer14ResizeBilinearEjRKN3gfx4RectERKNS1_4SizeEPj
+ fun:_ZN7content35CompositingIOSurfaceTransformerTest13RunResizeTestERK8SkBitmapRKN3gfx4RectERKNS4_4SizeE
+ fun:_ZN7content65CompositingIOSurfaceTransformerTest_ResizesTexturesCorrectly_Test8TestBodyEv
+}
+{
+ bug_227278d
+ Memcheck:Uninitialized
+ fun:glViewport_Exec
+ fun:glViewport
+ fun:_ZN7content12_GLOBAL__N_139SetTransformationsForOffScreenRenderingERKN3gfx4SizeE
+ fun:_ZN7content31CompositingIOSurfaceTransformer18TransformRGBToYV12EjRKN3gfx4RectERKNS1_4SizeEPjS8_S8_PS5_S9_
+ fun:_ZN7content35CompositingIOSurfaceTransformerTest25RunTransformRGBToYV12TestERK8SkBitmapRKN3gfx4RectERKNS4_4SizeE
+ fun:_ZN7content60CompositingIOSurfaceTransformerTest_TransformsRGBToYV12_Test8TestBodyEv
+}
+{
+ bug_227278e
+ Memcheck:Free
+ fun:_ZdlPv
+ fun:_ZN12BindingTableD2Ev
+ fun:_ZN14TGenericLinkerD0Ev
+ fun:ShDestruct
+ fun:gleFreeProgramObject
+ fun:gleUnbindDeleteHashNameAndObject
+ fun:glDeleteObjectARB_Exec
+ fun:glDeleteProgram
+ fun:_ZN7content34CompositingIOSurfaceShaderPrograms5ResetEv
+ fun:_ZN7content35CompositingIOSurfaceTransformerTestD2Ev
+ fun:_ZN7content69CompositingIOSurfaceTransformerTest_ShaderProgramsCompileAndLink_TestD2Ev
+ fun:_ZN7content69CompositingIOSurfaceTransformerTest_ShaderProgramsCompileAndLink_TestD1Ev
+ fun:_ZN7content69CompositingIOSurfaceTransformerTest_ShaderProgramsCompileAndLink_TestD0Ev
+ fun:_ZN7testing4Test11DeleteSelf_Ev
+}
+{
+ bug_233541
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN22DiskCacheTestWithCache13CreateBackendEjPN4base6ThreadE
+ fun:_ZN22DiskCacheTestWithCache13InitDiskCacheEv
+ fun:_ZN22DiskCacheTestWithCache9InitCacheEv
+ fun:*DiskCacheBackendTest_SimpleDoom*
+}
+{
+ bug_234845
+ Memcheck:Leak
+ fun:malloc
+ fun:PORT_Alloc_Util
+ fun:pk11_CreateSymKey
+ fun:PK11_KeyGenWithTemplate
+ fun:pk11_TokenKeyGenWithFlagsAndKeyType
+ fun:pk11_RawPBEKeyGenWithKeyType
+ fun:PK11_PBEKeyGen
+ fun:PK11_ExportEncryptedPrivKeyInfo
+ fun:_ZN6crypto12ECPrivateKey25ExportEncryptedPrivateKeyERKSsiPSt6vectorIhSaIhEE
+}
+{
+ bug_235584
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4Bind*
+ fun:_ZN3net18SSLClientSocketNSS4Core21OnHandshakeIOCompleteEi
+ fun:_ZN3net18SSLClientSocketNSS4Core28OnGetDomainBoundCertCompleteEi
+}
+{
+ bug_236791
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3ash4test53FocusCyclerTest_CycleFocusThroughWindowWithPanes_Test8TestBodyEv
+}
+{
+ bug_238170a
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore20ElementRuleCollector20collectMatchingRulesERKNS_12MatchRequestERNS_13StyleResolver9RuleRangeE
+ fun:_ZN7WebCore20ElementRuleCollector19hasAnyMatchingRulesEPNS_7RuleSetE
+}
+{
+ bug_238170b
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore20ElementRuleCollector20collectMatchingRulesERKNS_12MatchRequestERNS_13StyleResolver9RuleRangeE
+ fun:_ZN7WebCore13StyleResolver16matchAuthorRulesERNS_20ElementRuleCollectorEb
+}
+{
+ bug_238170c
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore23ReplaceSelectionCommand7doApplyEv
+ fun:_ZN7WebCore20CompositeEditCommand5applyEv
+ fun:_ZN7WebCore12applyCommandEN3WTF10PassRefPtrINS_20CompositeEditCommandEEE
+}
+{
+ bug_238547
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIPN4base11PendingTaskEE8allocateEmPKv
+ fun:_ZNSt11_Deque_baseIN4base11PendingTaskESaIS1_EE15_M_allocate_mapEm
+ fun:_ZNSt5dequeIN4base11PendingTaskESaIS1_EE17_M_reallocate_mapEmb
+ fun:_ZNSt5dequeIN4base11PendingTaskESaIS1_EE22_M_reserve_map_at_backEm
+ fun:_ZNSt5dequeIN4base11PendingTaskESaIS1_EE16_M_push_back_auxERKS1_
+ fun:_ZNSt5dequeIN4base11PendingTaskESaIS1_EE9push_backERKS1_
+ fun:_ZNSt5queueIN4base11PendingTaskESt5dequeIS1_SaIS1_EEE4pushERKS1_
+ ...
+ fun:_ZN4base*MessageLoop*15PostDelayedTaskERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEENS_9TimeDeltaE
+}
+{
+ bug_239141
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF9BitVector13OutOfLineBits6createEm
+ fun:_ZN3WTF9BitVector15resizeOutOfLineEm
+ fun:_ZN3WTF9BitVector10ensureSizeEm
+ fun:_ZN3WTF9BitVectorC1Em
+ fun:_ZN7WebCore10UseCounter17recordMeasurementENS0_7FeatureE
+}
+{
+ bug_241044
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore8Settings29setOpenGLMultisamplingEnabledEb
+ fun:_ZN6WebKit15WebSettingsImpl29setOpenGLMultisamplingEnabledEb
+ fun:_ZN11webkit_glue19ApplyWebPreferencesERK14WebPreferencesPN6WebKit7WebViewE
+ fun:_ZN7content14RenderViewImpl10InitializeEPNS_20RenderViewImplParamsE
+ fun:_ZN7content14RenderViewImpl6CreateEiRKNS_19RendererPreferencesERK14WebPreferencesPN4base14RefCountedDataIiEEiilRKSbItNS7_20string16_char_traitsESaItEEbbiRKN6WebKit13WebScreenInfoE17AccessibilityModeb
+ fun:_ZN7content16RenderThreadImpl15OnCreateNewViewERK18ViewMsg_New_Params
+}
+{
+ bug_241892a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore11CSSSelector8RareData6createEN3WTF10PassRefPtrINS2_16AtomicStringImplEEE
+ fun:_ZN7WebCore11CSSSelector14createRareDataEv
+ ...
+ fun:_Z10cssyyparsePN7WebCore9CSSParserE
+ fun:_ZN7WebCore9CSSParser10parseSheetEPNS_18StyleSheetContentsE*
+ fun:_ZN7WebCore18StyleSheetContents17parseStringAtLineERKN3WTF6StringEib
+ fun:_ZN7WebCore12StyleElement11createSheetE*
+ fun:_ZN7WebCore12StyleElement7processEPNS_7ElementE
+}
+{
+ bug_241892b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore11CSSSelector8RareData6createEN3WTF10PassRefPtrINS2_16AtomicStringImplEEE
+ fun:_ZN7WebCore11CSSSelector14createRareDataEv
+ ...
+ fun:_Z10cssyyparsePN7WebCore9CSSParserE
+ fun:_ZN7WebCore9CSSParser13parseSelectorERKN3WTF6StringERNS_15CSSSelectorListE
+}
+{
+ bug_241892c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore11CSSSelector8RareData6createEN3WTF10PassRefPtrINS2_16AtomicStringImplEEE
+ fun:_ZN7WebCore11CSSSelector14createRareDataEv
+ fun:_ZN7WebCore11CSSSelector12setAttributeERKNS_13QualifiedNameE
+ fun:_ZN7WebCore17CSSParserSelector12setAttributeERKNS_13QualifiedNameE
+ fun:_Z10cssyyparsePN7WebCore9CSSParserE
+ fun:_ZN7WebCore9CSSParser10parseSheetEPNS_18StyleSheetContentsERKN3WTF6StringERKNS3_12TextPositionEPNS0_17SourceDataHandlerEb
+ fun:_ZN7WebCore18StyleSheetContents21parseStringAtPositionERKN3WTF6StringERKNS1_12TextPositionEb
+ fun:_ZN7WebCore12StyleElement11createSheetEPNS_7ElementERKN3WTF6StringE
+ fun:_ZN7WebCore12StyleElement7processEPNS_7ElementE
+ fun:_ZN7WebCore12StyleElement17processStyleSheetEPNS_8DocumentEPNS_7ElementE
+ fun:_ZN7WebCore16HTMLStyleElement26didNotifySubtreeInsertionsEPNS_13ContainerNodeE
+ fun:_ZN7WebCore26ChildNodeInsertionNotifier6notifyEPNS_4NodeE
+ fun:_ZN7WebCoreL24updateTreeAfterInsertionEPNS_13ContainerNodeEPNS_4NodeENS_14AttachBehaviorE
+ fun:_ZN7WebCore13ContainerNode11appendChildEN3WTF10PassRefPtrINS_4NodeEEERiNS_14AttachBehaviorE
+ fun:_ZN7WebCore4Node11appendChildEN3WTF10PassRefPtrIS0_EERiNS_14AttachBehaviorE
+ fun:_ZN7WebCore6V8Node23appendChildMethodCustomERKN2v820FunctionCallbackInfoINS1_5ValueEEE
+ fun:_ZN7WebCore14NodeV8InternalL37appendChildMethodCallbackForMainWorldERKN2v820FunctionCallbackInfoINS1_5ValueEEE
+}
+{
+ bug_241892d
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10RefCountedIN7WebCore11CSSSelector8RareDataEEnwEm
+ fun:_ZN7WebCore11CSSSelector8RareData6createEN3WTF10PassRefPtrINS2_10StringImplEEE
+ fun:_ZN7WebCore11CSSSelector14createRareDataEv
+ ...
+ fun:_Z10cssyyparsePN7WebCore9CSSParserE
+}
+{
+ bug_241932
+ Memcheck:Leak
+ fun:calloc
+ fun:_ZN3WTF13tryFastCallocEmm
+ fun:_ZN3WTF9RawBufferC1EjjNS0_20InitializationPolicyE
+ fun:_ZN3WTF19ArrayBufferContentsC1EjjNS_9RawBuffer20InitializationPolicyE
+ fun:_ZN3WTF11ArrayBuffer6createEPKvj
+ fun:_ZN7WebCore12_GLOBAL__N_16Reader17doReadArrayBufferEv
+ fun:_ZN7WebCore12_GLOBAL__N_16Reader15readArrayBufferEPN2v86HandleINS2_5ValueEEE
+ fun:_ZN7WebCore12_GLOBAL__N_16Reader4readEPN2v86HandleINS2_5ValueEEERNS0_16CompositeCreatorE
+ fun:_ZN7WebCore12_GLOBAL__N_112Deserializer13doDeserializeEv
+ fun:_ZN7WebCore12_GLOBAL__N_112Deserializer11deserializeEv
+ fun:_ZN7WebCore21SerializedScriptValue11deserializeEPN2v87IsolateEPN3WTF6VectorINS4_6RefPtrINS_11MessagePortEEELm1EEE
+ fun:_ZN7WebCore14V8MessageEvent20dataAttrGetterCustomEN2v85LocalINS1_6StringEEERKNS1_12AccessorInfoE
+ fun:_ZN7WebCore22MessageEventV8InternalL22dataAttrGetterCallbackEN2v85LocalINS1_6StringEEERKNS1_12AccessorInfoE
+}
+{
+ bug_242672
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF9BitVector13OutOfLineBits6createEm
+ fun:_ZN3WTF9BitVector15resizeOutOfLineEm
+ fun:_ZN3WTF9BitVector10ensureSizeEm
+ fun:_ZN7WebCore10UseCounterC1Ev
+ fun:_ZN7WebCore4PageC1ERNS0_11PageClientsE
+}
+{
+ bug_243132
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10StringImpl19createUninitializedEjRPh
+ fun:_ZN3WTF6String6appendERKS0_
+ fun:_ZN7WebCoreL24valueForGridTrackBreadthERKNS_10GridLengthEPKNS_11RenderStyleEPNS_10RenderViewE
+ fun:_ZN7WebCoreL21valueForGridTrackSizeERKNS_13GridTrackSizeEPKNS_11RenderStyleEPNS_10RenderViewE
+ fun:_ZN7WebCoreL21valueForGridTrackListERKN3WTF6VectorINS_13GridTrackSizeELm0EEERKNS0_7HashMap*
+ fun:_ZNK7WebCore27CSSComputedStyleDeclaration19getPropertyCSSValueENS_13CSSPropertyIDENS_13EUpdateLayoutE
+ fun:_ZNK7WebCore27CSSComputedStyleDeclaration19getPropertyCSSValueENS_13CSSPropertyIDE
+ fun:_ZNK7WebCore27CSSComputedStyleDeclaration16getPropertyValueENS_13CSSPropertyIDE
+ fun:_ZN7WebCore27CSSComputedStyleDeclaration16getPropertyValueERKN3WTF6StringE
+}
+{
+ bug_243137
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore11RenderStyle6createEv
+ fun:_ZN7WebCore13StyleResolver15styleForElementEPNS_7ElementEPNS_11RenderStyle*
+ fun:_ZN7WebCore7Element16styleForRendererEv
+ fun:_ZN7WebCore20NodeRenderingContext32createRendererForElementIfNeededEv
+ fun:_ZN7WebCore7Element22createRendererIfNeededEv
+ fun:_ZN7WebCore7Element6attachEv
+ fun:_ZN7WebCore22HTMLPlugInImageElement6attachEv
+}
+{
+ bug_243753
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7fileapi28SandboxFileSystemBackendTest11GetRootPathERK4GURLNS_14FileSystemTypeEbPN4base8FilePathE
+}
+{
+ bug_245714
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content17WorkerServiceImplC1Ev
+ fun:_ZN22DefaultSingletonTraitsIN7content17WorkerServiceImplEE3NewEv
+ fun:_ZN9SingletonIN7content17WorkerServiceImplE22DefaultSingletonTraitsIS1_ES1_E3getEv
+ fun:_ZN7content17WorkerServiceImpl11GetInstanceEv
+ fun:_ZN7content19WorkerMessageFilter16OnChannelClosingEv
+ fun:_ZN3IPC12ChannelProxy7Context15OnChannelClosedEv
+}
+{
+ bug_245714b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content17WorkerServiceImplC1Ev
+ fun:_ZN22DefaultSingletonTraitsIN7content17WorkerServiceImplEE3NewEv
+ fun:_ZN9SingletonIN7content17WorkerServiceImplE22DefaultSingletonTraitsIS1_ES1_E3getEv
+ fun:_ZN7content17WorkerServiceImpl11GetInstanceEv
+ fun:_ZN7content22ResourceRequestDetailsC1EPKN3net10URLRequestEi
+ fun:_ZN7content26ResourceDispatcherHostImpl18DidReceiveResponseEPNS_14ResourceLoaderE
+ fun:_ZN7content14ResourceLoader23CompleteResponseStartedEv
+ fun:_ZN7content14ResourceLoader17OnResponseStartedEPN3net10URLRequestE
+ fun:_ZN3net10URLRequest21NotifyResponseStartedEv
+}
+{
+ bug_245828
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_
+ fun:_ZN7content13BrowserThread16PostTaskAndReplyENS0_2IDERKN15tracked_objects8LocationERKN4base8CallbackIFvvEEESB_
+ fun:_ZN7content23DevToolsHttpHandlerImpl4StopEv
+ fun:_ZN7content21ShellDevToolsDelegate4StopEv
+ fun:_ZN7content21ShellBrowserMainParts22PostMainMessageLoopRunEv
+ fun:_ZN7content15BrowserMainLoop25ShutdownThreadsAndCleanUpEv
+ fun:_ZN7content21BrowserMainRunnerImpl8ShutdownEv
+ fun:_Z16ShellBrowserMainRKN7content18MainFunctionParams*
+ fun:_ZN7content17ShellMainDelegate10RunProcessERKSsRKNS_18MainFunctionParamsE
+ fun:_ZN7content23RunNamedProcessTypeMainERKSsRKNS_18MainFunctionParamsEPNS_19ContentMainDelegateE
+ fun:_ZN7content21ContentMainRunnerImpl3RunEv
+ fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
+}
+{
+ bug_245866
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base23EnsureProcessTerminatedEi
+ fun:_ZN7content6Zygote17HandleReapRequestEiRK6Pickle14PickleIterator
+ fun:_ZN7content6Zygote24HandleRequestFromBrowserEi
+ fun:_ZN7content6Zygote15ProcessRequestsEv
+ fun:_ZN7content10ZygoteMainERKNS_18MainFunctionParamsEPNS_18ZygoteForkDelegateE
+ fun:_ZN7content9RunZygoteERKNS_18MainFunctionParamsEPNS_19ContentMainDelegateE
+ fun:_ZN7content23RunNamedProcessTypeMainERKSsRKNS_18MainFunctionParamsEPNS_19ContentMainDelegateE
+ fun:_ZN7content21ContentMainRunnerImpl3RunEv
+ fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
+}
+{
+ bug_246148
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN7content16SiteInstanceImpl10GetProcessEv
+ fun:_ZN7content18RenderViewHostImplC1EPNS_12SiteInstanceEPNS_22RenderViewHostDelegateEPNS_24RenderWidgetHostDelegateEiibPNS_23SessionStorageNamespaceE
+ fun:_ZN7content21RenderViewHostFactory6CreateEPNS_12SiteInstanceEPNS_22RenderViewHostDelegateEPNS_24RenderWidgetHostDelegateEiibPNS_23SessionStorageNamespaceE
+ fun:_ZN7content21RenderViewHostManager4InitEPNS_14BrowserContextEPNS_12SiteInstanceEii
+ fun:_ZN7content15WebContentsImpl4InitERKNS_11WebContents12CreateParamsE
+ fun:_ZN7content15TestWebContents6CreateEPNS_14BrowserContextEPNS_12SiteInstanceE
+ fun:_ZN7content17WebContentsTester21CreateTestWebContentsEPNS_14BrowserContextEPNS_12SiteInstanceE
+ fun:_ZN8autofill12_GLOBAL__N_128AutofillDialogControllerTest5SetUpEv
+}
+{
+ bug_246153
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore8Settings29setOpenGLMultisamplingEnabledEb
+ fun:_ZN6WebKit15WebSettingsImpl29setOpenGLMultisamplingEnabledEb
+ fun:_ZN11webkit_glue19ApplyWebPreferencesERK14WebPreferencesPN6WebKit7WebViewE
+ ...
+ fun:_ZN7content14RenderViewImpl10InitializeEPNS_20RenderViewImplParamsE
+ fun:_ZN7content14RenderViewImpl6CreateEiRKNS_19RendererPreferencesERK14WebPreferencesPN4base14RefCountedDataIiEEiiilRKSbItNS7_20string16_char_traitsESaItEEbbiRKN6WebKit13WebScreenInfoE17AccessibilityModeb
+ fun:_ZN7content16RenderThreadImpl15OnCreateNewViewERK18ViewMsg_New_Params
+}
+{
+ bug_247525a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7fileapi24SandboxFileSystemBackendC1EPN5quota17QuotaManagerProxyEPN4base19SequencedTaskRunnerERKNS4_8FilePathERKNS_17FileSystemOptionsEPNS1_20SpecialStoragePolicyE
+ fun:_ZN7fileapi17FileSystemContextC1E10scoped_ptrINS_21FileSystemTaskRunnersEN4base14DefaultDeleterIS2_EEEPNS_19ExternalMountPointsEPN5quota20SpecialStoragePolicyEPNS9_17QuotaManagerProxyE12ScopedVectorINS_17FileSystemBackendEERKNS3_8FilePathERKNS_17FileSystemOptionsE
+ fun:_ZN7content23CreateFileSystemContextERKN4base8FilePathEbPN7fileapi19ExternalMountPointsEPN5quota20SpecialStoragePolicyEPNS7_17QuotaManagerProxyE
+ fun:_ZN7content20StoragePartitionImpl6CreateEPNS_14BrowserContextEbRKN4base8FilePathE
+ fun:_ZN7content23StoragePartitionImplMap3GetERKSsS2_b
+ fun:_ZN7content12_GLOBAL__N_129GetStoragePartitionFromConfigEPNS_14BrowserContextERKSsS4_b
+ fun:_ZN7content14BrowserContext19GetStoragePartitionEPS0_PNS_12SiteInstanceE
+ fun:_ZN7content24NavigationControllerImpl26GetSessionStorageNamespaceEPNS_12SiteInstanceE
+ fun:_ZN7content21RenderViewHostManager4InitEPNS_14BrowserContextEPNS_12SiteInstanceEii
+ fun:_ZN7content15WebContentsImpl4InitERKNS_11WebContents12CreateParamsE
+ fun:_ZN7content15TestWebContents6CreateEPNS_14BrowserContextEPNS_12SiteInstanceE
+ fun:_ZN7content25RenderViewHostTestHarness21CreateTestWebContentsEv
+ fun:_ZN7content25RenderViewHostTestHarness5SetUpEv
+ fun:_ZN31ChromeRenderViewHostTestHarness5SetUpEv
+}
+{
+ bug_247525b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN8appcache19AppCacheStorageImpl10InitializeERKN4base8FilePathEPNS1_16MessageLoopProxyES6_
+ fun:_ZN8appcache15AppCacheService10InitializeERKN4base8FilePathEPNS1_16MessageLoopProxyES6_
+ fun:_ZN7content21ChromeAppCacheService20InitializeOnIOThreadERKN4base8FilePathEPNS_15ResourceContextEPN3net23URLRequestContextGetterE13scoped_refptrIN5quota20SpecialStoragePolicyEE
+}
+{
+ bug_247525c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content20StoragePartitionImpl6CreateEPNS_14BrowserContextEbRKN4base8FilePathE
+ fun:_ZN7content23StoragePartitionImplMap3GetERKSsS2_b
+ fun:_ZN7content12_GLOBAL__N_129GetStoragePartitionFromConfigEPNS_14BrowserContextERKSsS4_b
+ fun:_ZN7content14BrowserContext19GetStoragePartitionEPS0_PNS_12SiteInstanceE
+ fun:_ZN7content24NavigationControllerImpl26GetSessionStorageNamespaceEPNS_12SiteInstanceE
+ fun:_ZN7content21RenderViewHostManager4InitEPNS_14BrowserContextEPNS_12SiteInstanceEii
+ fun:_ZN7content15WebContentsImpl4InitERKNS_11WebContents12CreateParamsE
+ fun:_ZN7content15TestWebContents6CreateEPNS_14BrowserContextEPNS_12SiteInstanceE
+ fun:_ZN7content25RenderViewHostTestHarness21CreateTestWebContentsEv
+ fun:_ZN7content25RenderViewHostTestHarness5SetUpEv
+ fun:_ZN31ChromeRenderViewHostTestHarness5SetUpEv
+}
+{
+ bug_250529_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN14TestingProfile20CreateRequestContextEv
+ fun:_ZN12_GLOBAL__N_130ProfileSyncServiceTypedUrlTest5SetUpEv
+}
+{
+ bug_250529_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN14TestingProfile20CreateRequestContextEv
+ fun:_ZN30ProfileSyncServicePasswordTest5SetUpEv
+}
+{
+ bug_250533
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net21TestURLRequestContext4InitEv
+ fun:_ZN3net21TestURLRequestContextC1Ev
+ fun:_ZN3net27TestURLRequestContextGetter20GetURLRequestContextEv
+ fun:_ZN11jingle_glue26ProxyResolvingClientSocketC1EPN3net19ClientSocketFactoryERK13scoped_refptrINS1_23URLRequestContextGetterEERKNS1_9SSLConfigERKNS1_12HostPortPairE
+ fun:_ZN11jingle_glue23XmppClientSocketFactory27CreateTransportClientSocketERKN3net12HostPortPairE
+ fun:_ZN11jingle_glue17ChromeAsyncSocket7ConnectERKN9talk_base13SocketAddressE
+}
+{
+ bug_250533_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3net18HttpNetworkSessionC1ERKNS0_6ParamsE
+ fun:_ZN11jingle_glue26ProxyResolvingClientSocketC1EPN3net19ClientSocketFactoryERK13scoped_refptrINS1_23URLRequestContextGetterEERKNS1_9SSLConfigERKNS1_12HostPortPairE
+ fun:_ZN11jingle_glue23XmppClientSocketFactory27CreateTransportClientSocketERKN3net12HostPortPairE
+ fun:_ZN11jingle_glue17ChromeAsyncSocket7ConnectERKN9talk_base13SocketAddressE
+}
+{
+ bug_250688
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKN3net9HostCache3KeyES2_INS4_5EntryEN4base9TimeTicksEEEEE8allocateEmPKv
+ fun:_ZNSt8_Rb_treeIN3net9HostCache3KeyESt4pairIKS2_S3_INS1_5EntryEN4base9TimeTicksEEESt10_Select1stIS9_ESt4lessIS2_ESaIS9_EE11_M_get_nodeEv
+ fun:_ZNSt8_Rb_treeIN3net9HostCache3KeyESt4pairIKS2_S3_INS1_5EntryEN4base9TimeTicksEEESt10_Select1stIS9_ESt4lessIS2_ESaIS9_EE14_M_create_nodeERKS9_
+ fun:_ZNSt8_Rb_treeIN3net9HostCache3KeyESt4pairIKS2_S3_INS1_5EntryEN4base9TimeTicksEEESt10_Select1stIS9_ESt4lessIS2_ESaIS9_EE10_M_insert_EPKSt18_Rb_tree_node_baseSI_RKS9_
+ fun:_ZNSt8_Rb_treeIN3net9HostCache3KeyESt4pairIKS2_S3_INS1_5EntryEN4base9TimeTicksEEESt10_Select1stIS9_ESt4lessIS2_ESaIS9_EE16_M_insert_uniqueERKS9_
+ fun:_ZNSt3mapIN3net9HostCache3KeyESt4pairINS1_5EntryEN4base9TimeTicksEESt4lessIS2_ESaIS3_IKS2_S7_EEE6insertERKSB_
+ fun:_ZN3net13ExpiringCacheINS_9HostCache3KeyENS1_5EntryEN4base9TimeTicksESt4lessIS5_ENS1_15EvictionHandlerEE3PutERKS2_RKS3_RKS5_SF_
+ fun:_ZN3net9HostCache3SetERKNS0_3KeyERKNS0_5EntryEN4base9TimeTicksENS7_9TimeDeltaE
+ fun:_ZN3net20MockHostResolverBase11ResolveProcEmRKNS_12HostResolver11RequestInfoEPNS_11AddressListE
+ fun:_ZN3net20MockHostResolverBase10ResolveNowEm
+}
+{
+ bug_251004_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_
+ fun:_ZN3net10FileStream7Context14CloseAndDeleteEv
+}
+{
+ bug_251034
+ Memcheck:Leak
+ ...
+ fun:_ZN3gpu5gles216ShaderTranslator4InitE12ShShaderType12ShShaderSpecPK18ShBuiltInResourcesNS0_25ShaderTranslatorInterface22GlslImplementationTypeENS7_27GlslBuiltInFunctionBehaviorE
+ fun:_ZN3gpu5gles221ShaderTranslatorCache13GetTranslatorE12ShShaderType12ShShaderSpecPK18ShBuiltInResourcesNS0_25ShaderTranslatorInterface22GlslImplementationTypeENS7_27GlslBuiltInFunctionBehaviorE
+ fun:_ZN3gpu5gles216GLES2DecoderImpl26InitializeShaderTranslatorEv
+ fun:_ZN3gpu5gles216GLES2DecoderImpl10InitializeERK13scoped_refptrIN3gfx9GLSurfaceEERKS2_INS3_9GLContextEEbRKNS3_4SizeERKNS0_18DisallowedFeaturesEPKcRKSt6vectorIiSaIiEE
+ fun:_ZN3gpu22InProcessCommandBuffer21InitializeOnGpuThreadEbmRKN3gfx4SizeEPKcRKSt6vectorIiSaIiEENS1_13GpuPreferenceE
+}
+{
+ bug_252054
+ Memcheck:Unaddressable
+ fun:_ZNK7WebCore32PlatformSpeechSynthesisUtterance6clientEv
+ fun:_ZN7WebCore15SpeechSynthesis17didFinishSpeakingEN3WTF10PassRefPtrINS_32PlatformSpeechSynthesisUtteranceEEE
+ fun:_ZN7WebCore29PlatformSpeechSynthesizerMock16speakingFinishedEPNS_5TimerIS0_EE
+ fun:_ZN7WebCore5TimerINS_29PlatformSpeechSynthesizerMockEE5firedEv
+ fun:_ZN7WebCore12ThreadTimers24sharedTimerFiredInternalEv
+ fun:_ZN7WebCore12ThreadTimers16sharedTimerFiredEv
+ fun:_ZN11webkit_glue25WebKitPlatformSupportImpl9DoTimeoutEv
+}
+{
+ bug_252036
+ Memcheck:Uninitialized
+ fun:_ZN2cc9Scheduler27SetupNextBeginFrameIfNeededEv
+ fun:_ZN2cc9Scheduler23ProcessScheduledActionsEv
+}
+{
+ bug_252209
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content18ResourceDispatcher12CreateBridgeERKN11webkit_glue20ResourceLoaderBridge11RequestInfoE
+ fun:_ZN7content11ChildThread12CreateBridgeERKN11webkit_glue20ResourceLoaderBridge11RequestInfoE
+ fun:_ZN7content25WebKitPlatformSupportImpl20CreateResourceLoaderERKN11webkit_glue20ResourceLoaderBridge11RequestInfoE
+ fun:_ZN11webkit_glue16WebURLLoaderImpl7Context5StartERKN6WebKit13WebURLRequestEPNS_20ResourceLoaderBridge16SyncLoadResponseEPNS_25WebKitPlatformSupportImplE
+ fun:_ZN11webkit_glue16WebURLLoaderImpl18loadAsynchronouslyERKN6WebKit13WebURLRequestEPNS1_18WebURLLoaderClientE
+ fun:_ZN7WebCore22ResourceHandleInternal5startENS_17StoredCredentialsE
+ fun:_ZN7WebCore14ResourceHandle5startENS_17StoredCredentialsE
+ fun:_ZN7WebCore14ResourceHandle6createERKNS_15ResourceRequestEPNS_20ResourceHandleClientEbbNS_17StoredCredentialsE
+}
+{
+ bug_252228
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN2v88internal25FunctionCallbackArguments4CallEPFNS_6HandleINS_5ValueEEERKNS_9ArgumentsEE
+ fun:_ZN2v88internalL19HandleApiCallHelperILb0EEEPNS0_11MaybeObjectENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+ fun:_ZN2v88internalL25Builtin_implHandleApiCallENS0_12_GLOBAL__N_116BuiltinArgumentsILNS0_21BuiltinExtraArgumentsE1EEEPNS0_7IsolateE
+ fun:_ZN2v88internalL21Builtin_HandleApiCallEiPPNS0_6ObjectEPNS0_7IsolateE
+ ...
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+ fun:_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb
+}
+{
+ bug_252241_a
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN7content20WebKitTestController20PrepareForLayoutTestERK4GURLRKN4base8FilePathEbRKSs
+ fun:_Z16ShellBrowserMainRKN7content18MainFunctionParams*
+ fun:_ZN7content17ShellMainDelegate10RunProcessERKSsRKNS_18MainFunctionParamsE
+ fun:_ZN7content23RunNamedProcessTypeMainERKSsRKNS_18MainFunctionParamsEPNS_19ContentMainDelegateE
+ fun:_ZN7content21ContentMainRunnerImpl3RunEv
+ fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
+}
+{
+ bug_252241_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content19ContentMainDelegate26CreateContentUtilityClientEv
+ fun:_ZN7content24ContentClientInitializer3SetERKSsPNS_19ContentMainDelegateE
+ fun:_ZN7content21ContentMainRunnerImpl10InitializeEiPPKcPNS_19ContentMainDelegateE
+ fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
+}
+{
+ bug_252641_a
+ Memcheck:Uninitialized
+ fun:pthread_rwlock_init$UNIX2003
+ fun:_ZN3re25MutexC2Ev
+ fun:_ZN3re25MutexC1Ev
+ ...
+ fun:_ZN11leveldb_env19ParseMethodAndErrorEPKcPNS_8MethodIDEPi
+}
+{
+ bug_252641_b
+ Memcheck:Uninitialized
+ fun:pthread_rwlock_init$UNIX2003
+ fun:_ZN3re25MutexC2Ev
+ fun:_ZN3re25MutexC1Ev
+ ...
+ fun:_ZN11leveldb_env19ParseMethodAndErrorEPKcPNS_8MethodIDEPi
+ fun:_ZN7content23RecoveryCouldBeFruitfulEN7leveldb6StatusE
+ fun:_ZN7content21IndexedDBBackingStore4OpenERKSsRKN4base8FilePathES2_PN6WebKit15WebIDBCallbacks8DataLossEPNS_14LevelDBFactoryE
+ fun:_ZN12_GLOBAL__N_137IndexedDBIOErrorTest_CleanUpTest_Test8TestBodyEv
+}
+{
+ bug_253797
+ Memcheck:Uninitialized
+ fun:_ZNSt11char_traitsIcE6lengthEPKc
+ fun:_ZN4base8internal17StringPieceDetail*
+ fun:_ZN4base16BasicStringPieceISsEC1EPKc
+ fun:_ZN8autofill22AutofillQueryXmlParser13CharacterDataEPN4buzz15XmlParseContextEPKci
+ fun:_ZN4buzz9XmlParser18ExpatCharacterDataEPKci
+ fun:_ZN4buzzL21CharacterDataCallbackEPvPKci
+ obj:*libexpat.so*
+ obj:*libexpat.so*
+ obj:*libexpat.so*
+ obj:*libexpat.so*
+ fun:XML_ParseBuffer
+ fun:_ZN4buzz9XmlParser5ParseEPKcmb
+ fun:_ZN8autofill12_GLOBAL__N_126AutofillQueryXmlParserTest13ParseQueryXMLERKSsb
+ fun:_ZN8autofill12_GLOBAL__N_149AutofillQueryXmlParserTest_ParseAutofillFlow_Test8TestBodyEv
+}
+{
+ bug_255718
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base4BindIMNS_12_GLOBAL__N_121PostTaskAndReplyRelayEFvvENS_8internal17UnretainedWrapperIS2_EEEENS_8CallbackINS5_9BindStateINS5_13FunctorTraitsIT_E12RunnableTypeENSC_7RunTypeEFvNS5_19CallbackParamTraitsIT0_E11StorageTypeEEE14UnboundRunTypeEEESB_RKSG_
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_
+ fun:_ZN4base26PostTaskAndReplyWithResultIN5quota15QuotaStatusCodeES2_EEbPNS_10TaskRunnerERKN15tracked_objects8LocationERKNS_8CallbackIFT_vEEERKNS9_IFvT0_EEE
+ fun:_ZN7fileapi21FileSystemQuotaClient16DeleteOriginDataERK4GURLN5quota11StorageTypeERKN4base8CallbackIFvNS4_15QuotaStatusCodeEEEE
+ fun:_ZN5quota12QuotaManager17OriginDataDeleter3RunEv
+ fun:_ZN5quota9QuotaTask5StartEv
+ fun:_ZN5quota12QuotaManager16DeleteOriginDataERK4GURLNS_11StorageTypeEiRKN4base8CallbackIFvNS_15QuotaStatusCodeEEEE
+ fun:_ZN7content12_GLOBAL__N_134ClearQuotaManagedOriginsOnIOThreadERK13scoped_refptrIN5quota12QuotaManagerEERKSt3setI4GURLSt4lessIS8_ESaIS8_EENS2_11StorageTypeE
+ fun:_ZN7content12_GLOBAL__N_121ClearOriginOnIOThreadEjRK4GURLRK13scoped_refptrIN3net23URLRequestContextGetterEERKS4_IN5quota12QuotaManagerEE
+}
+{
+ bug_258466
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN22ChromeBrowserMainParts25PreMainMessageLoopRunImplEv
+ fun:_ZN22ChromeBrowserMainParts21PreMainMessageLoopRunEv
+ fun:_ZN7content15BrowserMainLoop13CreateThreadsEv
+ fun:_ZN7content21BrowserMainRunnerImpl10InitializeERKNS_18MainFunctionParamsE
+ fun:_ZN7content11BrowserMainERKNS_18MainFunctionParamsE
+ fun:_ZN7content23RunNamedProcessTypeMainERKSsRKNS_18MainFunctionParamsEPNS_19ContentMainDelegateE
+ fun:_ZN7content21ContentMainRunnerImpl3RunEv
+ fun:_ZN7content11ContentMainEiPPKcPNS_19ContentMainDelegateE
+ fun:ChromeMain
+}
+{
+ bug_258132a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN5ppapi5proxy15PPP_Class_Proxy19CreateProxiedObjectEPK18PPB_Var_DeprecatedPNS0_10DispatcherEill
+ fun:_ZN5ppapi5proxy24PPB_Var_Deprecated_Proxy27OnMsgCreateObjectDeprecatedEillNS0_24SerializedVarReturnValueE
+}
+{
+ bug_258132b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN5ppapi5proxy26PluginProxyMultiThreadTest7RunTestEv
+ fun:_ZN5ppapi*ThreadAwareCallback*Test_*
+}
+{
+ bug_259188
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore16V8PerIsolateData6createEPN2v87IsolateE
+ fun:_ZN7WebCore16V8PerIsolateData17ensureInitializedEPN2v87IsolateE
+ fun:_ZN6WebKit10initializeEPNS_8PlatformE
+}
+{
+ bug_259303
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3IPC7Message23EnsureFileDescriptorSetEv
+ fun:_ZN3IPC7Message19file_descriptor_setEv
+ fun:_ZN3IPC7Channel11ChannelImpl24WillDispatchInputMessageEPNS_7MessageE
+ fun:_ZN3IPC8internal13ChannelReader17DispatchInputDataEPKci
+ fun:_ZN3IPC8internal13ChannelReader23ProcessIncomingMessagesEv
+ fun:_ZN3IPC7Channel11ChannelImpl28OnFileCanReadWithoutBlockingEi
+ fun:_ZN4base19MessagePumpLibevent21FileDescriptorWatcher28OnFileCanReadWithoutBlockingEiPS0_
+ fun:_ZN4base19MessagePumpLibevent22OnLibeventNotificationEisPv
+}
+{
+ bug_259357d
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN3gpu5gles239ShaderTranslatorTest_OptionsString_Test8TestBodyEv
+}
+{
+ bug_259357f
+ Memcheck:Uninitialized
+ fun:_ZNK3gpu12AsyncAPIMock6IsArgsclEPKv
+ fun:_ZNK7testing8internal12TrulyMatcherIN3gpu12AsyncAPIMock6IsArgsEE15MatchAndExplainIPKvEEbRT_PNS_19MatchResultListenerE
+ fun:_ZNK7testing18PolymorphicMatcherINS_8internal12TrulyMatcherIN3gpu12AsyncAPIMock6IsArgsEEEE15MonomorphicImplIPKvE15MatchAndExplainESA_PNS_19MatchResultListenerE
+ fun:_ZNK7testing8internal11MatcherBaseIPKvE15MatchAndExplainES3_PNS_19MatchResultListenerE
+ fun:_ZNK7testing8internal11MatcherBaseIPKvE7MatchesES3_
+ fun:_ZN7testing8internal11TuplePrefixILm3EE7MatchesINSt3tr15tupleIINS_7MatcherIjEES7_NS6_IPKvEEEEENS5_IIjjS9_EEEEEbRKT_RKT0_
+ fun:_ZN7testing8internal12TupleMatchesINSt3tr15tupleIINS_7MatcherIjEES5_NS4_IPKvEEEEENS3_IIjjS7_EEEEEbRKT_RKT0_
+ fun:_ZNK7testing8internal16TypedExpectationIFN3gpu5error5ErrorEjjPKvEE7MatchesERKNSt3tr15tupleIIjjS6_EEE
+ fun:_ZNK7testing8internal16TypedExpectationIFN3gpu5error5ErrorEjjPKvEE21ShouldHandleArgumentsERKNSt3tr15tupleIIjjS6_EEE
+ fun:_ZNK7testing8internal18FunctionMockerBaseIFN3gpu5error5ErrorEjjPKvEE29FindMatchingExpectationLockedERKNSt3tr15tupleIIjjS6_EEE
+ fun:_ZN7testing8internal18FunctionMockerBaseIFN3gpu5error5ErrorEjjPKvEE30UntypedFindMatchingExpectationES6_PS6_PbPSoSB_
+ fun:_ZN7testing8internal25UntypedFunctionMockerBase17UntypedInvokeWithEPKv
+ fun:_ZN7testing8internal18FunctionMockerBaseIFN3gpu5error5ErrorEjjPKvEE10InvokeWithERKNSt3tr15tupleIIjjS6_EEE
+ fun:_ZN7testing8internal14FunctionMockerIFN3gpu5error5ErrorEjjPKvEE6InvokeEjjS6_
+ fun:_ZN3gpu12AsyncAPIMock9DoCommandEjjPKv
+ fun:_ZN3gpu13CommandParser14ProcessCommandEv
+ fun:_ZN3gpu12GpuScheduler10PutChangedEv
+}
+{
+ bug_259789
+ Memcheck:Uninitialized
+ fun:_ZN7WebCore12_GLOBAL__N_116adjustAttributesERKNS_17GraphicsContext3D10AttributesEPNS_8SettingsE
+ fun:_ZN7WebCore21WebGLRenderingContext19maybeRestoreContextEPNS_5TimerIS0_EE
+ fun:_ZN7WebCore5TimerINS_21WebGLRenderingContextEE5firedEv
+ fun:_ZN7WebCore12ThreadTimers24sharedTimerFiredInternalEv
+ fun:_ZN7WebCore12ThreadTimers16sharedTimerFiredEv
+ fun:_ZN11webkit_glue25WebKitPlatformSupportImpl9DoTimeoutEv
+}
+{
+ bug_259799
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN6WebKit16EditorClientImpl23requestCheckingOfStringEN3WTF10PassRefPtrIN7WebCore19TextCheckingRequestEEE
+ fun:_ZN7WebCore12SpellChecker13invokeRequestEN3WTF10PassRefPtrINS_17SpellCheckRequestEEE
+ fun:_ZN7WebCore12SpellChecker18requestCheckingForEN3WTF10PassRefPtrINS_17SpellCheckRequestEEE
+ fun:_ZN7WebCore6Editor40markAllMisspellingsAndBadGrammarInRangesEjPNS_5RangeES2_
+ fun:_ZN7WebCore6Editor33markMisspellingsAfterTypingToWordERKNS_15VisiblePositionERKNS_16VisibleSelectionE
+ fun:_ZN7WebCore13TypingCommand27markMisspellingsAfterTypingENS0_14ETypingCommandE
+ fun:_ZN7WebCore13TypingCommand24typingAddedToOpenCommandENS0_14ETypingCommandE
+ fun:_ZN7WebCore13TypingCommand28insertTextRunWithoutNewlinesERKN3WTF6StringEb
+ fun:_ZNK7WebCore26TypingCommandLineOperationclEmmb
+}
+{
+ bug_262875
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN3sql10Connection18GetCachedStatementERKNS_11StatementIDEPKc
+ ...
+ fun:_ZN15webkit_database15DatabaseTracker23UpgradeToCurrentVersionEv
+ fun:_ZN15webkit_database15DatabaseTracker8LazyInitEv
+ fun:_ZN15webkit_database15DatabaseTracker23GetAllOriginIdentifiersEPSt6vectorISsSaISsEE
+ fun:_ZN15webkit_database12_GLOBAL__N_120GetOriginsOnDBThreadEPNS_15DatabaseTrackerEPSt3setI4GURLSt4lessIS4_ESaIS4_EE
+}
+{
+ bug_268258
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN3WTF10fastMallocEm
+ fun:_ZN3WTF10StringImpl12createStaticEPKcjj
+ fun:_ZN7WebCore*Names*init*
+}
+{
+ bug_268267
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNK4base8internal18WeakReferenceOwner6GetRefEv
+ fun:_ZN4base14WeakPtrFactoryINS_12_GLOBAL__N_16TargetEE10GetWeakPtrEv
+ fun:_ZN4base45WeakPtrTest_MoveOwnershipAfterInvalidate_Test8TestBodyEv
+}
+{
+ bug_268368
+ Memcheck:Leak
+ fun:calloc
+ fun:_dlerror_run
+ ...
+ fun:_ZN4base17LoadNativeLibraryERKNS_8FilePathEPSs
+ fun:_ZN7content10PluginList17ReadWebPluginInfoERKN4base8FilePathEPNS_13WebPluginInfoE
+ fun:_ZN7content10PluginList14ReadPluginInfoERKN4base8FilePathEPNS_13WebPluginInfoE
+}
+{
+ bug_269201
+ Memcheck:Unaddressable
+ ...
+ fun:_ZN4base8internal17IncomingTaskQueue18AddToIncomingQueueERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEENS_9TimeDeltaEb
+ fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEE
+ fun:_ZN8printing8PrintJob21UpdatePrintedDocumentEPNS_15PrintedDocumentE
+ fun:_ZN8printing8PrintJob4StopEv
+}
+{
+ bug_269844
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorIPN4base11PendingTaskEE8allocateEmPKv
+ fun:_ZNSt11_Deque_baseIN4base11PendingTaskESaIS1_EE15_M_allocate_mapEm
+ fun:_ZNSt5dequeIN4base11PendingTaskESaIS1_EE17_M_reallocate_mapEmb
+ ...
+ fun:_ZN4base8internal17IncomingTaskQueue15PostPendingTaskEPNS_11PendingTaskE
+ fun:_ZN4base8internal17IncomingTaskQueue18AddToIncomingQueueERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEENS_9TimeDeltaEb
+ fun:_ZN4base11MessageLoop8PostTaskERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEE
+}
+{
+ bug_270312
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN14message_center22MessageCenterButtonBarC1EPNS_17MessageCenterViewEPNS_13MessageCenterEPNS_24NotifierSettingsProviderEb
+ fun:_ZN14message_center17MessageCenterViewC1EPNS_13MessageCenterEPNS_17MessageCenterTrayEibb
+ fun:_ZN14message_center21MessageCenterViewTest5SetUpEv
+}
+{
+ bug_272179_a
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN7WebCore14HarfBuzzShaper17shapeHarfBuzzRuns*
+}
+{
+ bug_272179_b
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN7WebCore14HarfBuzzShaper19collectHarfBuzzRunsEv
+}
+{
+ bug_272179_c
+ Memcheck:Param
+ sendmsg(msg.msg_iov[0])
+ obj:/lib/x86_64-linux-gnu/libpthread-2.15.so
+ ...
+ fun:_ZN7WebCore14HarfBuzzShaper19collectHarfBuzzRunsEv
+}
+{
+ bug_272596
+ Memcheck:Leak
+ ...
+ fun:nssPKIObjectCollection_AddInstanceAsObject
+ fun:nssToken_TraverseCertificates
+ fun:NSSTrustDomain_TraverseCertificates
+ fun:PK11_ListCerts
+ fun:_ZN3net15NSSCertDatabase9ListCertsEPSt6vectorI13scoped_refptrINS_15X509CertificateEESaIS4_EE
+ fun:_ZN8chromeos12_GLOBAL__N_119LoadNSSCertificatesEPSt6vectorI13scoped_refptrIN3net15X509CertificateEESaIS5_EE
+}
+{
+ bug_272083
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN12ThemeService19SetManagedUserThemeEv
+ fun:_ZN12ThemeService24OnManagedUserInitializedEv
+}
diff --git a/chromium/tools/valgrind/memcheck/suppressions_linux.txt b/chromium/tools/valgrind/memcheck/suppressions_linux.txt
new file mode 100644
index 00000000000..b37ce32db72
--- /dev/null
+++ b/chromium/tools/valgrind/memcheck/suppressions_linux.txt
@@ -0,0 +1,35 @@
+# There are three kinds of suppressions in this file:
+# 1. Third party stuff we have no control over.
+#
+# 2. Intentional unit test errors, stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing.
+#
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system.
+# Periodically we should sweep this file and the bug tracker clean by
+# running overnight and removing outdated bugs/suppressions.
+#
+# TODO(rnk): Should we move all of the Linux-only system library suppressions
+# over from suppressions.txt? We'd avoid wasting time parsing and matching
+# suppressions on non-Linux, which is basically just Mac.
+#
+#-----------------------------------------------------------------------
+
+# 1. Third party stuff we have no control over.
+{
+ # The InvalidRead error in rc4_wordconv is intentional.
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=341127
+ # TODO(wtc): This invalid read has been fixed in NSS 3.15. Remove this
+ # suppression when the system NSS libraries in Linux distributions are
+ # version 3.15 or later.
+ bug_43113 (Intentional)
+ Memcheck:Unaddressable
+ fun:rc4_wordconv
+ fun:RC4_Encrypt
+}
+
+# 2. Intentional unit test errors, stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing.
+
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+
diff --git a/chromium/tools/valgrind/memcheck/suppressions_mac.txt b/chromium/tools/valgrind/memcheck/suppressions_mac.txt
new file mode 100644
index 00000000000..714321acf59
--- /dev/null
+++ b/chromium/tools/valgrind/memcheck/suppressions_mac.txt
@@ -0,0 +1,2597 @@
+# There are three kinds of suppressions in this file:
+# 1. Third party stuff we have no control over.
+#
+# 2. Intentional unit test errors, stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing.
+#
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system.
+# Periodically we should sweep this file and the bug tracker clean by
+# running overnight and removing outdated bugs/suppressions.
+#-----------------------------------------------------------------------
+
+# 1. Third party stuff we have no control over.
+{
+ FIXME mac kevent libevent probably needs valgrind hooks
+ Memcheck:Param
+ kevent(changelist)
+ fun:kevent
+ fun:event_base_new
+}
+{
+ # CoreAudio leak. See http://crbug.com/9351
+ bug_9351
+ Memcheck:Leak
+ ...
+ fun:_ZN12HALCADClient19AddPropertyListenerEmPK26AudioObjectPropertyAddressPFlmmS2_PvES3_
+ ...
+ fun:_ZN9HALSystem16CheckOutInstanceEv
+ ...
+}
+{
+ # Mac system library bug? See http://crbug.com/11327
+ bug_11327
+ Memcheck:Uninitialized
+ fun:_ZN19AudioConverterChain5ResetEv
+ fun:AudioConverterReset
+ obj:/System/Library/Components/CoreAudio.component/Contents/MacOS/CoreAudio
+}
+{
+ # Mac system library bug? See http://crbug.com/11327
+ bug_11327b
+ Memcheck:Uninitialized
+ fun:AUNetSendEntry
+ fun:AUNetSendEntry
+ obj:/System/Library/Components/CoreAudio.component/Contents/MacOS/CoreAudio
+}
+{
+ # Filed with Apple as rdar://6915060; see http://crbug.com/11270
+ bug_11270
+ Memcheck:Leak
+ fun:calloc
+ fun:CMSSetLabCLUT
+}
+{
+ # Mac leak in CMOpenOrNewAccess in unit_tests PlatformCanvas_SkLayer_Test,
+ # ToolbarControllerTest_FocusLocation_Test. See http://crbug.com/11333.
+ bug_11333
+ Memcheck:Leak
+ fun:malloc
+ fun:stdSmartNewPtr
+ fun:stdSmartNewHandle
+ fun:IOCreateAndOpen
+ fun:ScratchInit
+ fun:CMOpenOrNewAccess
+}
+{
+ # suddenly very common as of 6 aug 2009
+ bug_11333b
+ Memcheck:Leak
+ fun:malloc
+ fun:stdSmartNewPtr
+ fun:stdSmartNewHandle
+ fun:IOCreateAndOpen
+ fun:ScratchInit
+ fun:CMNewAccessFromAnother
+}
+{
+ # Tiny one-time leak, widely seen by valgind users; everyone suppresses this.
+ # See related discussion at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39366
+ plugin_bundle_global_leak
+ Memcheck:Leak
+ fun:malloc
+ fun:__cxa_get_globals
+ fun:__cxa_allocate_exception
+ fun:_ZN4dyld4loadEPKcRKNS_11LoadContextE
+ fun:dlopen
+ fun:dlopen
+ fun:_CFBundleDlfcnCheckLoaded
+}
+{
+ bug_18215
+ Memcheck:Uninitialized
+ fun:_DPSNextEvent
+ fun:-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
+ fun:-[NSApplication run]
+}
+{
+ bug_18223
+ Memcheck:Uninitialized
+ fun:_ZNK8Security12UnixPlusPlus17StaticForkMonitorclEv
+ fun:_ZN12ocspdGlobals10serverPortEv
+}
+{
+ # Filed with Apple as rdar://7255382
+ bug_20459a
+ Memcheck:Leak
+ ...
+ fun:_CFRuntimeCreateInstance
+ fun:CFRunLoopSourceCreate
+ fun:CFMachPortCreateRunLoopSource
+ fun:_ZN8Security12MachPlusPlus10CFAutoPort6enableEv
+ fun:_ZN8Security14SecurityServer14ThreadNotifierC2Ev
+}
+{
+ # Also filed with Apple as rdar://7255382
+ bug_20459b
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:__CFArrayInit
+ fun:CFArrayCreateMutableCopy
+ ...
+ fun:_ZN8Security12KeychainCore5Trust8evaluate*
+}
+# See description of bug_20653a/b in suppressions.txt.
+{
+ bug_20653a_mac
+ Memcheck:Param
+ write(buf)
+ fun:write$UNIX2003
+ fun:pager_write_pagelist
+}
+{
+ bug_20653b_mac
+ Memcheck:Param
+ write(buf)
+ fun:write$UNIX2003
+ ...
+ fun:pager_write
+}
+
+# See http://www.openradar.me/8287193
+{
+ Invalid redzone accesses in DKeyHas8Words
+ Memcheck:Unaddressable
+ fun:DKeyHas8Words
+}
+
+# See https://bugs.kde.org/show_bug.cgi?id=188572
+# This suppression is missing in Valgrind on Mac 10.6
+# TODO(glider): remove it once it arrives in the trunk.
+{
+ Unavoidable leak in setenv()
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:__setenv
+ fun:setenv$UNIX2003
+}
+{
+ # Reported to Apple as rdar://6915429
+ bug_12525
+ Memcheck:Leak
+ ...
+ fun:-[CIContextImpl render:toBitmap:rowBytes:bounds:format:colorSpace:]
+}
+{
+ bug_69436
+ Memcheck:Leak
+ ...
+ fun:-[CIKernel initWithCString:noCopy:]
+ ...
+ fun:-[NSPopUpButtonCell _drawIndicatorWithFrame:inView:]
+}
+{
+ # Capturer on Mac uses OpenGL driver, which triggers several warnings.
+ # The check has to be quite generic, as different hardware graphics cards
+ # will cause different sets of warnings.
+ bug_75037
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN8remoting*CapturerMac*
+}
+{
+ # See also http://openradar.appspot.com/radar?id=1235407
+ bug_77063
+ Memcheck:Free
+ fun:_ZdlPv
+ fun:_ZN15THFSPlusCatalogD2Ev
+ fun:_ZN5TNode10SetCatalogEP15THFSPlusCatalog
+ fun:_ZN15TMountPointList9AddVolumeEsb
+ fun:_ZN15TMountPointList4FindEsPN5TNode12StPopulatingE
+ fun:_ZN15TMountPointList20SupportsInvisibleBitEsPN5TNode12StPopulatingEb
+ fun:_ZNK21THFSPlusPropertyStore4OpenEbb
+ fun:_ZNK21THFSPlusPropertyStore13GetPropertiesEb
+ fun:_ZN16TFSCopyOperation22GetSourcePropertyStoreERK11THFSPlusRef
+ fun:_ZN16TFSCopyOperation13DoMoveToTrashERK11THFSPlusRef
+ fun:_ZN16TFSCopyOperation3RunEv
+ fun:_FSOperation
+ fun:_FSOperateOnObjectSync
+ fun:FSMoveObjectToTrashSync
+ fun:_Z9TrashFunc*FilePath
+}
+{
+ # See also http://openradar.appspot.com/radar?id=1169404
+ bug_79533a
+ Memcheck:Uninitialized
+ ...
+ fun:_Z*19cssm_DataAbortQuery17cssm_dl_db_handlel
+ fun:CSSM_DL_DataAbortQuery
+ fun:_ZN11SSDLSession14DataAbortQueryEll
+ fun:_Z*19cssm_DataAbortQuery17cssm_dl_db_handlel
+ fun:CSSM_DL_DataAbortQuery
+ fun:tpDbFindIssuerCrl
+ fun:tpVerifyCertGroupWithCrls
+}
+{
+ # See also http://openradar.appspot.com/radar?id=1169404
+ bug_79533b
+ Memcheck:Uninitialized
+ ...
+ fun:_Z*19cssm_DataAbortQuery17cssm_dl_db_handlel
+ fun:CSSM_DL_DataAbortQuery
+ fun:_ZN11SSDLSession14DataAbortQueryEll
+ fun:_Z*19cssm_DataAbortQuery17cssm_dl_db_handlel
+ fun:CSSM_DL_DataAbortQuery
+ fun:tpDbFindIssuerCrl
+ fun:tpVerifyCertGroupWithCrls
+}
+{
+ bug_85213_a
+ Memcheck:Leak
+ ...
+ fun:_CFBundleCopyDirectoryContentsAtPath
+}
+{
+ bug_85213_b
+ Memcheck:Leak
+ ...
+ fun:_CFBundleCopyInfoDictionaryInDirectoryWithVersion
+}
+{
+ bug_85213_c
+ Memcheck:Leak
+ ...
+ fun:_CFBundleURLLooksLikeBundleVersion
+}
+{
+ bug_85213_d
+ Memcheck:Leak
+ ...
+ fun:_CFBundleCreate
+ fun:_ZN6webkit5npapi9PluginLib17ReadWebPluginInfoE*
+}
+{
+ bug_85213_e
+ Memcheck:Leak
+ ...
+ fun:CFBundlePreflightExecutable
+ fun:_ZN6webkit5npapi9PluginLib17ReadWebPluginInfoE*
+}
+{
+ bug_85213_f
+ Memcheck:Leak
+ ...
+ fun:CFBundleGetPackageInfo
+ fun:_ZN6webkit5npapi9PluginLib17ReadWebPluginInfoE*
+}
+{
+ bug_86927
+ Memcheck:Leak
+ fun:malloc
+ fun:CGSMapShmem
+ fun:CGSResolveShmemReference
+ fun:CGSScoreboard
+ fun:initCGDisplayState
+ fun:initCGDisplayMappings
+ fun:cgsInit
+ fun:pthread_once
+ fun:CGSInitialize
+ fun:CGSServerOperationState
+ fun:+[NSThemeFrame initialize]
+ fun:_class_initialize
+}
+{
+ # QTKit leak. See http://crbug.com/100772 and rdar://10319535.
+ bug_100772
+ Memcheck:Leak
+ fun:calloc
+ fun:QTMLCreateMutex
+ fun:WarholCreateGlobals
+ fun:INIT_QuickTimeLibInternal
+ fun:pthread_once
+ fun:INIT_QuickTimeLib
+ fun:EnterMovies_priv
+ fun:EnterMovies
+ fun:TundraUnitInputFromTSFileEntry
+ fun:TundraUnitVDIGInputEntry
+ fun:TundraUnitCreateFromDescription
+ fun:+[QTCaptureVDIGDevice _refreshDevices]
+ fun:+[QTCaptureVDIGDevice devicesWithIOType:]
+ fun:+[QTCaptureDevice devicesWithIOType:]
+ fun:+[QTCaptureDevice inputDevices]
+ fun:+[QTCaptureDevice inputDevicesWithMediaType:]
+ ...
+}
+{
+ # See http://crbug.com/141293
+ bug_141293
+ Memcheck:Uninitialized
+ fun:deflateEnd
+ fun:deflateSetDictionary
+ fun:deflate
+ fun:png_write_finish_row
+ ...
+ fun:png_write_find_filter
+ fun:_cg_png_write_row
+ fun:writeOnePng
+ fun:_CGImagePluginWritePNG
+ fun:CGImageDestinationFinalize
+ fun:+[NSBitmapImageRep(NSBitmapImageFileTypeExtensions) representationOfImageRepsInArray:usingType:properties:]
+ fun:-[NSBitmapImageRep(NSBitmapImageFileTypeExtensions) representationUsingType:properties:]
+ fun:_ZN3gfx8internal24Get1xPNGBytesFromNSImageEP7NSImage
+}
+
+# 2. Intentional unit test errors, stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing.
+{
+ # Plugins are deliberately not unloaded (on shutdown) on the Mac, in order to
+ # prevent crashes for those that don't unload cleanly.
+ plugin_unload
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base17LoadNativeLibraryE*
+ fun:_ZN6webkit5npapi9PluginLib4LoadEv
+ fun:_ZN6webkit5npapi9PluginLib13NP_InitializeEv
+ fun:_ZN6webkit5npapi21WebPluginDelegateImpl6CreateE*
+ fun:_ZN19TestWebViewDelegate20CreatePluginDelegateE*
+}
+{
+ # Mac Sandbox test cases are registered in a global map. This code is only
+ # used in the unit test binary.
+ Mac_Sandbox_Intentional_Leak1
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content8internal19RegisterSandboxTestINS_*
+ ...
+ fun:_ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextE
+ fun:_ZN4dyld24initializeMainExecutableEv
+}
+{
+ # The ConfirmQuitPanelController animates out and releases itself. And
+ # CocoaTest::TearDown() still sees this window and deques events for it,
+ # but one of those events creates this TSM Context that gets leaked.
+ # See http://crbug.com/61816 for more details.
+ # ut*AllSelectedIMInDoc = fun:utOpenActivateAllSelectedIMInDoc or
+ # fun:utDeactivateAllSelectedIMInDoc
+ Mac_Animated_Window_Close_ProcessNotification_Event
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:__CFDictionaryInit
+ fun:ut*AllSelectedIMInDoc
+ ...
+ fun:My*ctivateTSMDocument
+}
+{
+ # __cxa_get_globals leaks a structure when called for the first time
+ __cxa_get_globals one-time leak
+ Memcheck:Leak
+ ...
+ fun:__cxa_get_globals
+}
+{
+ bug_93711_a - intentional
+ Memcheck:Param
+ msync(start)
+ fun:msync$UNIX2003
+ fun:mach_override_ptr
+}
+{
+ bug_93711_b - likely induced by an intentional memory error
+ Memcheck:Leak
+ fun:malloc
+ fun:allocateBranchIsland
+ fun:mach_override_ptr
+}
+
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+{
+ bug_17297
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:+[NSColor keyboardFocusIndicatorColor]
+ fun:+[NSColor colorWithCatalogName:colorName:]
+ fun:+[NSCatalogColor newWithCoder:zone:]
+ fun:-[NSColor initWithCoder:]
+}
+{
+ bug_18218
+ Memcheck:Leak
+ fun:malloc
+ fun:__addHandler2
+ fun:__NSFinalizeThreadData
+ fun:_pthread_tsd_cleanup
+ fun:_pthread_exit
+ fun:thread_start
+}
+{
+ bug_20582
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base19MessagePumpLibevent19WatchFileDescriptorEibNS0_4ModeEPNS0_21FileDescriptorWatcherEPNS0_7WatcherE
+ fun:_ZN4base16MessageLoopForIO19WatchFileDescriptorEibNS_4ModeEPN4base19MessagePumpLibevent21FileDescriptorWatcherEPNS2_7WatcherE
+ fun:_ZN3IPC7Channel11ChannelImpl23ProcessOutgoingMessagesEv
+}
+{
+ bug_21479a
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:CFPasteboardCreate
+ fun:CFPasteboardCreateUnique
+ fun:+[NSPasteboard _pasteboardWithName:]
+ fun:+[NSPasteboard pasteboardWithUniqueName]
+}
+{
+ bug_21479b
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:CFPasteboardCreate
+ fun:+[NSPasteboard _pasteboardWithName:]
+ fun:-[FindPasteboard findPboard]
+}
+{
+ bug_27315
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZNSt8_Rb_treeIlSt4pairIKlPN4llvm8PassInfoEESt10_Select1stIS5_ESt4lessIlESaIS5_EE9_M_insertEPSt18_Rb_tree_node_baseSD_RKS5_
+ fun:_ZNSt8_Rb_treeIlSt4pairIKlPN4llvm8PassInfoEESt10_Select1stIS5_ESt4lessIlESaIS5_EE13insert_uniqueERKS5_
+ fun:_ZN4llvm16RegisterPassBase12registerPassEv
+ fun:_Z41__static_initialization_and_destruction_0ii
+ fun:_ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEj
+ fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextE
+}
+{
+ bug_27644
+ Memcheck:Leak
+ ...
+ fun:_ZN19WebSharedWorkerStub9OnConnectEii
+}
+{
+ bug_28847a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN13WorkerService12CreateWorkerERK4GURLbbRKSbItN4base20string16_char_traitsESaItEEiiPN3IPC7Message6SenderEi
+ fun:_ZN21ResourceMessageFilter14OnCreateWorkerERK4GURLbRKSbItN4base20string16_char_traitsESaItEEiPi
+}
+{
+ bug_28847b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN16ChildProcessHost6LaunchERKSt6vectorISt4pairISsSsESaIS2_EEP11CommandLine
+ fun:_ZN17WorkerProcessHost4InitEv
+ fun:_ZN13WorkerService12CreateWorkerERK4GURLbbRKSbItN4base20string16_char_traitsESaItEEiiPN3IPC7Message6SenderEi
+ fun:_ZN21ResourceMessageFilter14OnCreateWorkerERK4GURLbRKSbItN4base20string16_char_traitsESaItEEiPi
+}
+{
+ bug_28072a
+ Memcheck:Leak
+ ...
+ fun:CSBackupSetItemExcluded
+ fun:_ZN8mac_util22SetFileBackupExclusionE*
+ fun:_ZN7history15HistoryDatabase4InitE*
+ fun:_ZN7history14HistoryBackend8InitImplEv
+ fun:_ZN7history14HistoryBackend4InitEb
+}
+{
+ bug_28072b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7history14HistoryBackend8InitImplEv
+ fun:_ZN7history14HistoryBackend4InitEb
+}
+{
+ bug_28072c
+ Memcheck:Unaddressable
+ ...
+ fun:CSBackupSetItemExcluded
+ fun:_ZN8mac_util22SetFileBackupExclusionE*
+ fun:_ZN7history15HistoryDatabase4InitE*
+ fun:_ZN7history14HistoryBackend8InitImplEv
+ fun:_ZN7history14HistoryBackend4InitEb
+}
+{
+ bug_28072d
+ Memcheck:Unaddressable
+ ...
+ fun:CSBackupSetItemExcluded
+ fun:_ZN4base3mac22SetFileBackupExclusionE*
+ fun:_ZN7history15HistoryDatabase4InitE*
+ fun:_ZN7history14HistoryBackend8InitImplERKSs
+ fun:_ZN7history14HistoryBackend4InitERKSsb
+}
+
+# Note: bug 31634 happens very sporatically.
+{
+ bug_31634
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:__CFDictionaryInit
+ fun:CFDictionaryCreate
+ fun:classDescription
+}
+{
+ bug_35164
+ Memcheck:Uninitialized
+ ...
+ fun:gl_context_init_client_state
+ fun:ogl_begin_rendering
+ fun:CARenderOGLRender
+ fun:view_draw
+}
+{
+ bug_35625
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:CGTypeCreateInstanceWithAllocator
+ fun:CGTypeCreateInstance
+ fun:CGFunctionCreate
+ fun:CGGradientGetFunction
+ fun:CGContextDrawLinearGradient
+ ...
+ fun:-[NSView _drawRect:clip:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+}
+{
+ bug_40429
+ Memcheck:Leak
+ fun:calloc
+ fun:_internal_class_createInstanceFromZone
+ fun:_internal_class_createInstance
+ fun:+[NSObject allocWithZone:]
+ ...
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSButtonCell initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSControl initWithCoder:]
+ fun:-[NSButton initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:-[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:]
+ fun:-[NSArray(NSArray) initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSView initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+}
+{
+ bug_40429b
+ Memcheck:Leak
+ fun:calloc
+ fun:_internal_class_createInstanceFromZone
+ ...
+ fun:+[NSObject allocWithZone:]
+ ...
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSNibConnector initWithCoder:]
+ fun:-[NSNibControlConnector initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:-[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:]
+ fun:-[NSArray(NSArray) initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSIBObjectData initWithCoder:]
+ fun:_decodeObjectBinary
+}
+{
+ bug_40429c
+ Memcheck:Leak
+ fun:calloc
+ fun:_internal_class_createInstanceFromZone
+ fun:_internal_class_createInstance
+ fun:+[NSObject allocWithZone:]
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSButtonCell initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSControl initWithCoder:]
+ fun:-[NSButton initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:-[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:]
+ fun:-[NSArray(NSArray) initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSView initWithCoder:]
+ fun:_decodeObjectBinary
+ fun:_decodeObject
+ fun:-[NSResponder initWithCoder:]
+ fun:-[NSView initWithCoder:]
+}
+{
+ bug_40659
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN19extension_file_util13LoadExtensionE*
+ fun:_ZN12CrxInstaller15CompleteInstallEv
+}
+{
+ bug_47949_a
+ Memcheck:Uninitialized
+ ...
+ fun:ripc_DrawRects
+ fun:CGContextFillRects
+ fun:CGContextFillRect
+ fun:NSRectFill
+ fun:_ZN18FocusIndicationFix40currentOSHasSetFocusRingStyleInBitmapBugEv
+}
+{
+ bug_47949_b
+ Memcheck:Uninitialized
+ ...
+ fun:ripc_DrawRects
+ fun:CGContextFillRects
+ fun:CGContextFillRect
+ fun:NSRectFill
+ fun:_ZN18FocusIndicationFix40currentOSHasSetFocusRingStyleInBitmapBugEv
+}
+{
+ bug_47949_c
+ Memcheck:Leak
+ ...
+ fun:ripc_DrawRects
+ fun:CGContextFillRects
+ fun:CGContextFillRect
+ fun:NSRectFill
+ fun:_ZN18FocusIndicationFix40currentOSHasSetFocusRingStyleInBitmapBugEv
+}
+{
+ bug_50286
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN11ProfileImpl14InitExtensionsEv
+ fun:_ZN14ProfileManager10AddProfileEP7Profileb
+ fun:_ZN14ProfileManager10GetProfileE*
+ fun:_ZN14ProfileManager10GetProfileE*
+ fun:_ZN14ProfileManager17GetDefaultProfileE*
+ fun:_ZN12_GLOBAL__N_113CreateProfileE*
+ fun:_Z11BrowserMainRK18MainFunctionParams
+ fun:ChromeMain
+ fun:main
+}
+{
+ bug_50297_a
+ Memcheck:Uninitialized
+ fun:_ZN3IPC7Channel11ChannelImpl23ProcessIncomingMessagesEv
+ fun:_ZN3IPC7Channel11ChannelImpl28OnFileCanReadWithoutBlockingEi
+ fun:_ZN4base19MessagePumpLibevent21FileDescriptorWatcher28OnFileCanReadWithoutBlockingEiPS0_
+ ...
+ fun:event_process_active
+ fun:event_base_loop
+ fun:_ZN4base19MessagePumpLibevent3RunEPNS_11MessagePump8DelegateE
+ fun:_ZN4base11MessageLoop11RunInternalEv
+}
+{
+ bug_50297_b
+ Memcheck:Uninitialized
+ fun:_ZN6Pickle8FindNextEmPKcS1_
+ fun:_ZN3IPC7Message8FindNextEPKcS2_
+ fun:_ZN3IPC7Channel11ChannelImpl23ProcessIncomingMessagesEv
+ fun:_ZN3IPC7Channel11ChannelImpl28OnFileCanReadWithoutBlockingEi
+ fun:_ZN4base19MessagePumpLibevent21FileDescriptorWatcher28OnFileCanReadWithoutBlockingEiPS0_
+ ...
+ fun:event_process_active
+ fun:event_base_loop
+ fun:_ZN4base19MessagePumpLibevent3RunEPNS_11MessagePump8DelegateE
+ fun:_ZN4base11MessageLoop11RunInternalEv
+}
+{
+ bug_50638_a
+ Memcheck:Uninitialized
+ fun:gleUpdateViewScissorData
+ ...
+ fun:cgl_set_surface
+ fun:ogl_attach_surface
+ fun:ogl_render_fade_transition
+ fun:ogl_render_layer_
+ ...
+ fun:ogl_render_layers
+ fun:CARenderOGLRender
+ fun:view_draw
+}
+{
+ bug_50638_b
+ Memcheck:Uninitialized
+ fun:gleUpdateViewScissorData
+ fun:cgl_set_surface
+ fun:ogl_attach_surface
+ fun:ogl_render_layer_contents_bg
+ fun:ogl_render_layer_image_
+ fun:ogl_render_layer_
+ fun:ogl_render_layer_image_
+ fun:ogl_render_layer_
+ fun:ogl_render_layer_image_
+ fun:ogl_render_layer_
+ fun:ogl_render_layers
+ fun:CARenderOGLRender
+ fun:view_draw
+}
+{
+ bug_50968
+ Memcheck:Unaddressable
+ fun:sqlite3PcacheClearSyncFlags
+ fun:syncJournal
+ fun:pagerStress
+ fun:sqlite3PcacheFetch
+ fun:sqlite3PagerAcquire2
+ fun:sqlite3PagerAcquire
+ fun:btreeGetPage
+ fun:allocateBtreePage
+ fun:btreeCreateTable
+ fun:sqlite3BtreeCreateTable
+ fun:sqlite3VdbeExec
+ fun:sqlite3Step
+ fun:sqlite3_step
+ fun:sqlite3_exec
+ fun:_ZN3sql10Connection7ExecuteEPKc
+ fun:_ZN17TokenServiceTable4InitEv
+ fun:_ZN11WebDatabase4InitE*
+ fun:_ZN14WebDataService29InitializeDatabaseIfNecessaryEv
+}
+{
+ bug_52681_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN16ChildProcessHost13CreateChannelEv
+ fun:_ZN18UtilityProcessHost12StartProcessE*
+ fun:_ZN18UtilityProcessHost22StartExtensionUnpackerE*
+}
+{
+ bug_52681_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN16ChildProcessHost13CreateChannelEv
+ fun:_ZN18UtilityProcessHost12StartProcessE*
+ fun:_ZN18UtilityProcessHost22StartExtensionUnpackerE*
+ fun:_ZN26SandboxedUnpacker22StartProcessOnIOThreadE*
+}
+{
+ bug_53742_a
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN16AudioQueueObject12ConvertInputEP9AQCommandRmb
+ fun:_ZN16AudioQueueObject12RunConverterEi
+ fun:_ZN18AQConverterManager17AQConverterThread3RunEv
+ fun:_ZN18AQConverterManager17AQConverterThread20ConverterThreadEntryEPv
+ fun:_ZN9CAPThread5EntryEPS_
+ fun:_pthread_start
+ fun:thread_start
+}
+{
+ bug_53742_b
+ Memcheck:Uninitialized
+ fun:_ZN16AudioQueueObject12ConvertInputEP9AQCommandRmb
+ fun:_ZN16AudioQueueObject5ResetEv
+ fun:_ZN16AudioQueueObject4StopEb
+}
+{
+ bug_53989_a
+ Memcheck:Uninitialized
+ fun:glvm_function_new
+ fun:glvmCreateModularFunction
+ fun:gleGetVertexSubmitFuncObjectAndKey
+ fun:gleSetVertexArrayFunc
+ fun:gleDrawArraysOrElements_ExecCore
+ fun:gleDrawArraysOrElements_IMM_Exec
+ fun:gl_context_draw
+ fun:ogl_array_flush
+ fun:ogl_primitives_end_
+ ...
+ fun:CARenderOGLRender
+ fun:view_draw
+ fun:view_display_link
+ fun:link_callback
+}
+{
+ bug_53989_b
+ Memcheck:Uninitialized
+ fun:glvm_function_hash_value_6
+ fun:glvm_hash_set_*
+ fun:glvm*ModularFunction*Cache
+ fun:gleGetVertexSubmitFuncObjectAndKey
+ fun:gleSetVertexArrayFunc
+ fun:gleDrawArraysOrElements_ExecCore
+ fun:gleDrawArraysOrElements_IMM_Exec
+ fun:gl_context_draw
+ fun:ogl_array_flush
+ fun:ogl_primitives_end_
+ ...
+ fun:CARenderOGLRender
+ fun:view_draw
+ fun:view_display_link
+}
+{
+ bug_53989_c
+ Memcheck:Uninitialized
+ ...
+ fun:gleGetVertexSubmitFuncObjectAndKey
+ fun:gleSetVertexArrayFunc
+ fun:gleDrawArraysOrElements_ExecCore
+ fun:gleDrawArraysOrElements_IMM_Exec
+ fun:gl_context_draw
+ fun:ogl_array_flush
+ fun:ogl_primitives_end_
+ ...
+ fun:CARenderOGLRender
+ fun:view_draw
+ fun:view_display_link
+ fun:link_callback
+}
+{
+ bug_55773
+ Memcheck:Unaddressable
+ fun:sseCGSFill8by1
+ fun:argb32_mark_constshape
+ fun:argb32_mark
+ fun:ripl_BltShape
+ fun:ripc_Render
+ fun:ripc_DrawRects
+ fun:CGContextFillRects
+ fun:CGContextFillRect
+ fun:NSRectFill
+ fun:-[NSView _drawRect:clip:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
+ fun:-[NSView displayIfNeeded]
+ fun:-[NSWindow displayIfNeeded]
+ fun:-[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:]
+ fun:-[NSWindow orderWindow:relativeTo:]
+ fun:-[NSWindow addChildWindow:ordered:]
+ fun:-[GTMWindowSheetController(PrivateMethods) beginSystemSheet:withInfo:modalForView:withParameters:]
+ fun:-[GTMWindowSheetController beginSystemSheet:modalForView:withParameters:]
+ fun:-[GTMWindowSheetController beginSheet:modalForView:modalDelegate:didEndSelector:contextInfo:]
+}
+{
+ bug_58860_a
+ Memcheck:Unaddressable
+ fun:memcpy
+ ...
+ fun:FSFindFolder
+ fun:_ZN12_GLOBAL__N_124GetPluginCommonDirectoryE*
+ fun:_ZN6webkit5npapi10PluginList20GetPluginDirectoriesE*
+ fun:_ZN6webkit5npapi10PluginList11LoadPluginsEb
+ fun:_ZN6webkit5npapi10PluginList10GetPluginsEbPSt6vectorI13WebPluginInfoSaIS2_EE
+ fun:_ZN13PluginUpdater30GetPreferencesDataOnFileThreadEPv
+}
+{
+ bug_58860_b
+ Memcheck:Unaddressable
+ ...
+ fun:FSFindFolder
+ fun:_ZN12_GLOBAL__N_124GetPluginCommonDirectoryE*
+ fun:_ZN6webkit5npapi10PluginList20GetPluginDirectoriesE*
+ fun:_ZN6webkit5npapi10PluginList11LoadPluginsEb
+ fun:_ZN6webkit5npapi10PluginList10GetPluginsEbPSt6vectorI13WebPluginInfoSaIS2_EE
+ fun:_ZN13PluginUpdater30GetPreferencesDataOnFileThreadEPv
+}
+{
+ bug_51682a
+ Memcheck:Leak
+ fun:malloc
+ fun:__cxa_get_globals
+ fun:__cxa_allocate_exception
+ fun:_ZN8Security9CssmError7throwMeEi
+ fun:_ZN9RSASigner6verifyEPKvmS1_m
+ fun:_ZN16SignatureContext5finalERKN8Security8CssmDataE
+ fun:_ZL20cssm_VerifyDataFinallyPK9cssm_data
+ fun:CSSM_VerifyDataFinal
+ fun:_ZN4base17SignatureVerifier11VerifyFinalEv
+ fun:_ZN36SignatureVerifierTest_BasicTest_Test8TestBodyEv
+}
+{
+ bug_51682b
+ Memcheck:Leak
+ fun:malloc
+ fun:__cxa_get_globals
+ fun:__cxa_allocate_exception
+ fun:_ZN8Security9CssmError7throwMeEi
+ ...
+ fun:SecTrustEvaluate
+}
+{
+ bug_51682c
+ Memcheck:Leak
+ fun:realloc
+ fun:_ZN16DefaultAllocator7reallocEPvm
+ fun:_ZN8Security28CssmAllocatorMemoryFunctions12relayReallocEPvmS1_
+ fun:_ZNK8Security19CssmMemoryFunctions7reallocEPvm
+ fun:_ZN8Security28CssmMemoryFunctionsAllocator7reallocEPvm
+ fun:_ZN10Attachment13upcallReallocElPvj
+ fun:_ZN8Security13PluginSession7reallocEPvm
+ fun:_ZN17DecodedExtensions12addExtensionERK9cssm_databPvbPK22SecAsn1Template_structPS1_
+ fun:_ZN17DecodedExtensions13decodeFromNssEPP17NSS_CertExtension
+ fun:_ZN11DecodedCertC2ER18AppleX509CLSessionRKN8Security8CssmDataE
+ fun:_ZN18AppleX509CLSession22CertGetFirstFieldValueERKN8Security8CssmDataES3_RjRP9cssm_data
+ fun:_Z27cssm_CertGetFirstFieldValuelPK9cssm_dataS1_PlPjPPS_
+ fun:CSSM_CL_CertGetFirstFieldValue
+}
+{
+ bug_60873
+ Memcheck:Uninitialized
+ fun:UTF8ToCString
+ fun:_Z16UTF8ToClassicHFSPKcmmmPh
+ fun:_Z14PathMakeFSSpecPKcP6FSSpecPh
+ fun:NativePathNameToFSSpec
+ fun:ConvertProfLocation
+ fun:GetProfileLocationOfSuite
+ fun:_CMGetProfileOfSuite
+ fun:CMGetProfileByAVID
+ fun:CMSCreateDisplayProfile
+ fun:create
+ fun:CMSTransformCreate
+ fun:createBase
+ fun:initialize
+ fun:createColorTransform
+ fun:CGColorTransformCreateMutable
+ fun:CGBitmapColorTransformCreate
+ fun:__CGBitmapContextDelegateCreate
+ fun:__CGBitmapContextDelegateCreate
+ fun:createBitmapContext
+ fun:CGBitmapContextCreate
+ fun:_ZN4skia12_GLOBAL__N_1L16CGContextForDataEPvii
+ fun:_ZN4skia20BitmapPlatformDevice*
+}
+{
+ bug_61737
+ Memcheck:Uninitialized
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE36ParseMemberWithNewPrefixesExpressionEPiPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE14ParseNewPrefixEPiPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE18ParseNewExpressionEPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE27ParseLeftHandSideExpressionEPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE22ParsePostfixExpressionEPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE20ParseUnaryExpressionEPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE21ParseBinaryExpressionEibPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE26ParseConditionalExpressionEbPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE25ParseAssignmentExpressionEbPb
+ ...
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE19ParseSourceElementsEiPb
+ fun:_ZN2v88internal9preparser9PreParserINS0_7ScannerENS0_21PartialParserRecorderEE15PreParseProgramEPS3_PS4_b
+ fun:_ZN2v88internal9ParserApi15PartialPreParseENS0_6HandleINS0_6StringEEEPN7unibrow15CharacterStreamEPNS_9ExtensionE
+ fun:_ZN2v88internal8Compiler7CompileENS0_6HandleINS0_6StringEEENS2_INS0_6ObjectEEEiiPNS_9ExtensionEPNS0_14ScriptDataImplES6_NS0_11NativesFlagE
+}
+{
+ bug_61929
+ Memcheck:Leak
+ fun:calloc
+ fun:IOAlloc
+ fun:CMOpenOrNewAccess
+ fun:CMOpenProfile
+ fun:_CMGetProfileOfSuite
+ fun:CMGetProfileByAVID
+ fun:CMSCreateDisplayProfile
+ fun:create
+ fun:CMSTransformCreate
+ fun:createBase
+ fun:initialize
+ fun:createColorTransform
+ fun:CGColorTransformCreateMutable
+ fun:CGBitmapColorTransformCreate
+ fun:__CGBitmapContextDelegateCreate
+ fun:__CGBitmapContextDelegateCreate
+ fun:createBitmapContext
+ fun:CGBitmapContextCreate
+}
+{
+ bug_63024a
+ Memcheck:Uninitialized
+ fun:memcpy
+ fun:_ZN8Security13NameValuePair9CloneDataERKNS_8CssmDataE
+ fun:_ZN8Security13NameValuePairC2ERKNS_8CssmDataE
+ fun:_ZN8Security19NameValueDictionary12MakeFromDataERKNS_8CssmDataE
+ fun:_ZN8Security19NameValueDictionaryC2ERKNS_8CssmDataE
+ fun:_ZN8Security12KeychainCore12CCallbackMgr7consumeEjjRKNS_8CssmDataE
+ fun:_ZN8Security14SecurityServer16NotificationPort7receiveERKNS_12MachPlusPlus7MessageE
+ fun:_ZN8Security12MachPlusPlus10CFAutoPort10cfCallbackEP12__CFMachPortPvlS4_
+}
+{
+ bug_63024b
+ Memcheck:Uninitialized
+ fun:_ZN8Security19NameValueDictionary12MakeFromDataERKNS_8CssmDataE
+ fun:_ZN8Security19NameValueDictionaryC2ERKNS_8CssmDataE
+ fun:_ZN8Security12KeychainCore12CCallbackMgr7consumeEjjRKNS_8CssmDataE
+ fun:_ZN8Security14SecurityServer16NotificationPort7receiveERKNS_12MachPlusPlus7MessageE
+ fun:_ZN8Security12MachPlusPlus10CFAutoPort10cfCallbackEP12__CFMachPortPvlS4_
+}
+{
+ bug_63024c
+ Memcheck:Free
+ fun:_ZdlPv
+ fun:_ZN8Security19NameValueDictionaryD2Ev
+ fun:_ZN8Security12KeychainCore12CCallbackMgr7consumeEjjRKNS_8CssmDataE
+ fun:_ZN8Security14SecurityServer16NotificationPort7receiveERKNS_12MachPlusPlus7MessageE
+ fun:_ZN8Security12MachPlusPlus10CFAutoPort10cfCallbackEP12__CFMachPortPvlS4_
+}
+{
+ bug_63670
+ Memcheck:Uninitialized
+ fun:NSIntersectionRect
+ fun:-[BrowserWindowController tabContentsViewFrameWillChange:frameRect:]
+ fun:-[TabStripController tabContentsViewFrameWillChange:frameRect:]
+ fun:-[TabContentsController tabContentsViewFrameWillChange:]
+ fun:-[ResizeNotificationView setFrame:]
+ fun:-[TabStripController swapInTabAtIndex:]
+ fun:-[TabStripController selectTabWithContents:previousContents:atIndex:userGesture:]
+ fun:_ZN27TabStripModelObserverBridge13TabSelectedAtEP18TabContentsWrapperS1_ib
+ fun:_ZN13TabStripModel26ChangeSelectedContentsFromEP18TabContentsWrapperib
+ fun:_ZN13TabStripModel19InsertTabContentsAtEiP18TabContentsWrapperi
+ fun:_ZN13TabStripModel14AddTabContentsEP18TabContentsWrapperiji
+ fun:_ZN7browser8NavigateEPNS_14NavigateParamsE
+ fun:_ZN11BrowserInit17LaunchWithProfile17OpenTabsInBrowserEP7BrowserbRKSt6vectorINS0_3TabESaIS4_EE
+ fun:_ZN11BrowserInit17LaunchWithProfile17OpenURLsInBrowserEP7BrowserbRKSt6vectorI4GURLSaIS4_EE
+ fun:_ZN11BrowserInit17LaunchWithProfile17ProcessLaunchURLsEbRKSt6vectorI4GURLSaIS2_EE
+ fun:_ZN11BrowserInit17LaunchWithProfile6LaunchEP7Profileb
+ fun:_ZN11BrowserInit13LaunchBrowserE*
+ fun:_ZN11BrowserInit18ProcessCmdLineImplE*
+ fun:_ZN11BrowserInit5StartE*
+}
+{
+ bug_64463
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base16MessageLoopProxy22currentEv
+ fun:_ZN3net12CertVerifier7RequestC2EPS0_PNS_15X509CertificateERKSsiPNS_16CertVerifyResultEP14CallbackRunnerI6Tuple1IiEE
+}
+{
+ bug_65940
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3IPC11SyncChannelC2ERKNS_13ChannelHandleENS_7Channel4ModeEPNS4_8ListenerEP11MessageLoopbPN4base13WaitableEventE
+ fun:_ZN3IPC11SyncChannelC1ERKNS_13ChannelHandleENS_7Channel4ModeEPNS4_8ListenerEP11MessageLoopbPN4base13WaitableEventE
+ fun:_ZN11ChildThread4InitEv
+ fun:_ZN11ChildThreadC2Ev
+ fun:_ZN13UtilityThreadC2Ev
+ fun:_ZN13UtilityThreadC1Ev
+}
+{
+ bug_67291
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN16ExtensionInfoMap12AddExtensionEPK9Extension
+}
+{
+ bug_68090
+ Memcheck:Uninitialized
+ fun:_ZL10AddEncHashP12EncHashTablePKhij
+ fun:_Z16BuildMacEncTablev
+ fun:_ZN15TParsingContext13GetParseProcsEv
+ fun:_ZN19TSFNTParsingContext13GetParseProcsEv
+ fun:_ZN18TCIDParsingContext13GetParseProcsEv
+ fun:_ZN16TType1OTFCIDFont20ParseCFFCIDFontDictsERK19TType1CFFDescriptorP32Type1ProtectionEvaluationContextRVt
+ fun:_ZN16TType1OTFCIDFont15ParseCFFCIDFontERK19TType1CFFDescriptorP32Type1ProtectionEvaluationContext
+ fun:_ZN16TType1OTFCIDFontC2ERK19TType1CFFDescriptor
+ fun:_ZN10TType1Font7GetFontEPK5TFont
+ fun:_ZN12TType1StrikeC2EPK5TFontmPK13FontVariationRK15StrikeTransform
+ fun:_ZN12TType1Strike9GetStrikeERK18TStrikeDescription
+ fun:_Z19Type1GetStrikeSpecsmPK18TStrikeDescriptionP11StrikeSpecs
+ fun:_ZNK19TConcreteFontScaler14GetFontMetricsEv
+ ...
+ fun:_ZNK9TBaseFont20CalculateFontMetricsEb
+ fun:_ZNK9TBaseFont15InitFontMetricsEv
+ fun:_ZNK9TBaseFont16GetStrikeMetricsEfPK17CGAffineTransformb
+}
+{
+ bug_73036
+ Memcheck:Leak
+ fun:malloc_zone_calloc
+ fun:_internal_class_createInstanceFromZone
+ fun:NSAllocateObject
+ fun:+[NSHashTable alloc]
+ fun:+[NSTrackingArea initialize]
+ fun:_class_initialize
+ fun:_class_lookupMethodAndLoadCache
+ fun:objc_msgSend
+}
+{
+ bug_73299_b
+ Memcheck:Leak
+ fun:_Znw*
+ ...
+ fun:_ZN24BrowserRenderProcessHost4InitEb
+ fun:_ZN14RenderViewHost16CreateRenderViewERKSbItN4base20string16_char_traitsESaItEE
+ fun:_ZN13ExtensionHost19CreateRenderViewNowEv
+ fun:_ZN13ExtensionHost20ProcessCreationQueue14ProcessOneHostEv
+}
+{
+ bug_75136a
+ Memcheck:Unaddressable
+ ...
+ fun:CFBundlePreflightExecutable
+}
+{
+ bug_75136b
+ Memcheck:Unaddressable
+ ...
+ fun:CFBundlePreflightExecutable
+}
+{
+ bug_75142a
+ Memcheck:Unaddressable
+ ...
+ fun:CGContextShowGlyphsWithAdvances
+}
+{
+ bug_75142b
+ Memcheck:Leak
+ ...
+ fun:CGContextShowGlyphsWithAdvances
+}
+{
+ bug_75714_a
+ Memcheck:Unaddressable
+ ...
+ fun:argb32_mark
+ fun:ripl_BltShape
+ ...
+ fun:ripc_Render*
+ ...
+ fun:-[NSView _drawRect:clip:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ ...
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
+ fun:-[NSView displayIfNeeded]
+}
+{
+ bug_75714_b
+ Memcheck:Unaddressable
+ ...
+ fun:argb32_mark
+ fun:ripl_BltShape
+ fun:ripc_Render
+ ...
+ fun:-[NSView _drawRect:clip:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ ...
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
+ fun:-[NSView displayIfNeeded]
+}
+{
+ bug_75714_c
+ Memcheck:Unaddressable
+ ...
+ fun:argb32_image
+ fun:ripd_Mark
+ fun:ripl_BltImage
+ ...
+ fun:ripc_Render*
+ ...
+ fun:-[NSView _drawRect:clip:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ ...
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
+ fun:-[NSView displayIfNeeded]
+}
+{
+ bug_77265_a
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:-[BubbleView drawRect:]
+ fun:-[NSView _drawRect:clip:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
+ fun:-[NSView displayIfNeeded]
+ fun:-[NSWindow _setFrameCommon:display:stashSize:]
+ fun:-[NSWindow setFrame:display:]
+ fun:-[NSWindow setValue:forKey:]
+ fun:-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]
+ fun:-[NSInFlightAnimation advanceToTime:]
+ fun:-[NSAnimationManager animationTimerFired:]
+ fun:__NSFireTimer
+}
+{
+ bug_77265_b
+ Memcheck:Leak
+ fun:calloc
+ fun:CGClipStackCreateMutableCopy
+ fun:maybeCopyClipState
+ fun:CGGStateClipToRect
+ fun:CGContextClipToRect
+ fun:CGContextClipToRects
+ fun:NSRectClipList
+ fun:-[NSView _drawRect:clip:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
+ fun:-[NSView displayIfNeeded]
+ fun:-[NSWindow _setFrameCommon:display:stashSize:]
+ fun:-[NSWindow setFrame:display:]
+ fun:-[NSWindow setValue:forKey:]
+ fun:-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]
+ fun:-[NSInFlightAnimation advanceToTime:]
+ fun:-[NSAnimationManager animationTimerFired:]
+ fun:__NSFireTimer
+}
+{
+ bug_77265_c
+ Memcheck:Leak
+ fun:calloc
+ fun:CGClipStackCreateMutableCopy
+ fun:maybeCopyClipState
+ fun:CGGStateClipToRect
+ fun:CGContextClipToRect
+ fun:NSRectClip
+ fun:-[NSFocusState flush]
+ fun:-[NSView lockFocusIfCanDraw]
+ fun:-[NSView lockFocus]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
+ fun:-[NSView displayIfNeeded]
+ fun:-[NSWindow _setFrameCommon:display:stashSize:]
+ fun:-[NSWindow setFrame:display:]
+ fun:-[NSWindow setValue:forKey:]
+ fun:-[NSObject(NSKeyValueCoding) setValue:forKeyPath:]
+ fun:-[NSInFlightAnimation advanceToTime:]
+ fun:-[NSAnimationManager animationTimerFired:]
+ fun:__NSFireTimer
+}
+{
+ bug_77388_a
+ Memcheck:Uninitialized
+ ...
+ fun:PrivateMPEntryPoint
+ fun:_pthread_start
+ fun:thread_start
+}
+{
+ bug_77388_b
+ Memcheck:Uninitialized
+ ...
+ fun:PrivateMPEntryPoint
+ fun:_pthread_start
+ fun:thread_start
+}
+{
+ bug_77388_c
+ Memcheck:Param
+ access_extended(entries)
+ fun:accessx_np
+ ...
+ fun:PrivateMPEntryPoint
+ fun:_pthread_start
+ fun:thread_start
+}
+{
+ bug_77388_d
+ Memcheck:Uninitialized
+ fun:TestAndSetClear
+ fun:TestAndClear
+ fun:_ZN5TNode28UnregisterChangeNotificationERK11TCountedPtrI21TClientChangeNotifierEmb
+ fun:NodeUnregisterChangeNotification
+ fun:NodeUnRegisterChildChangedNotification
+ fun:-[NSNavFBENode _unregisterForChildChangedNotifications]
+ fun:_commonTearDown_NSNavFBENode
+ fun:-[NSNavFBENode dealloc]
+ fun:CFRelease
+ fun:__CFSetDeallocate
+ fun:_CFRelease
+ fun:-[NSOutlineView dealloc]
+ fun:-[NSTrackableOutlineView dealloc]
+}
+{
+ bug_79655a
+ Memcheck:Unaddressable
+ ...
+ fun:dlopen
+ fun:_ZN20IOSurfaceSupportImplC2Ev
+ fun:_ZN20IOSurfaceSupportImplC1Ev
+ fun:_ZN22DefaultSingletonTraitsI20IOSurfaceSupportImplE3NewEv
+ fun:_ZN9SingletonI20IOSurfaceSupportImpl22DefaultSingletonTraitsIS0_ES0_E3getEv
+ fun:_ZN20IOSurfaceSupportImpl11GetInstanceEv
+ fun:_ZN16IOSurfaceSupport10InitializeEv
+ fun:_ZN15WebContentsImpl14GetWebkitPrefsEv
+}
+{
+ bug_79655b
+ Memcheck:Leak
+ ...
+ fun:dlopen
+ fun:_ZN20IOSurfaceSupportImplC2Ev
+ fun:_ZN20IOSurfaceSupportImplC1Ev
+ fun:_ZN22DefaultSingletonTraitsI20IOSurfaceSupportImplE3NewEv
+ fun:_ZN9SingletonI20IOSurfaceSupportImpl22DefaultSingletonTraitsIS0_ES0_E3getEv
+ fun:_ZN20IOSurfaceSupportImpl11GetInstanceEv
+ fun:_ZN16IOSurfaceSupport10InitializeEv
+ fun:_ZN15WebContentsImpl14GetWebkitPrefsEv
+}
+{
+ bug_79994
+ Memcheck:Uninitialized
+ ...
+ fun:gleUpdateState
+ fun:gleInitializeContext
+ fun:gliCreateContext
+ fun:CGLRestoreDispatchFunction
+ fun:CGLCreateContext
+}
+{
+ bug_80239_a
+ Memcheck:Unaddressable
+ ...
+ fun:CGLCreateContext
+ fun:-[NSOpenGLContext initWithFormat:shareContext:]
+ fun:-[AcceleratedPluginView initWithRenderWidgetHostViewMac:pluginHandle:]
+ fun:_ZN23RenderWidgetHostViewMac30AllocateFakePluginWindowHandleEbb
+ fun:_ZN23RenderWidgetHostViewMac21GetCompositingSurfaceEv
+ fun:_ZN16RenderWidgetHost21GetCompositingSurfaceEv
+ fun:_ZN14RenderViewHost16CreateRenderViewERKSbItN4base20string16_char_traitsESaItEE
+ fun:_ZN15WebContentsImpl32CreateRenderViewForRenderManagerEP14RenderViewHost
+ fun:_ZN21RenderViewHostManager14InitRenderViewEP14RenderViewHostRK15NavigationEntry
+}
+{
+ bug_80239_b
+ Memcheck:Unaddressable
+ ...
+ fun:CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext
+ fun:-[AcceleratedPluginView initWithRenderWidgetHostViewMac:pluginHandle:]
+ fun:_ZN23RenderWidgetHostViewMac30AllocateFakePluginWindowHandleEbb
+ fun:_ZN23RenderWidgetHostViewMac21GetCompositingSurfaceEv
+ fun:_ZN16RenderWidgetHost21GetCompositingSurfaceEv
+ fun:_ZN14RenderViewHost16CreateRenderViewERKSbItN4base20string16_char_traitsESaItEE
+ fun:_ZN15WebContentsImpl32CreateRenderViewForRenderManagerEP14RenderViewHost
+}
+{
+ bug_82328
+ Memcheck:Unaddressable
+ fun:CGSFillDRAM64
+ fun:argb32_mark_pixelshape
+ ...
+ fun:ripc_DrawImages
+ fun:CGContextDrawImages
+ fun:_ZN11CUIRenderer19DrawWindowFrameDarkEPK10CUIContext
+ fun:_ZN11CUIRenderer4DrawE6CGRectP9CGContextPK14__CFDictionaryPS5_
+ fun:_NSDrawThemeBackground
+}
+{
+ bug_82682
+ Memcheck:Leak
+ ...
+ fun:_ZN6webkit5npapi12_GLOBAL__N_119ReadPlistPluginInfoE*
+}
+{
+ bug_84329
+ Memcheck:Unaddressable
+ fun:_ZN3WTF17ChromiumThreading16callOnMainThreadEPFvPvES1_
+ fun:_ZN3WTF16callOnMainThreadEPFvPvES0_
+ fun:_ZN6WebKit13WebWorkerBase24dispatchTaskToMainThreadEN3WTF10PassOwnPtrIN7WebCore22ScriptExecutionContext4TaskEEE
+ fun:_ZN6WebKit13WebWorkerBase21reportPendingActivityEb
+}
+{
+ bug_86303a
+ Memcheck:Unaddressable
+ ...
+ fun:objc_msgSend*
+}
+{
+ bug_86303b
+ Memcheck:Unaddressable
+ ...
+ fun:-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
+ fun:-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
+ fun:-[NSView displayIfNeeded]
+ fun:-[NSWindow displayIfNeeded]
+ fun:_handleWindowNeedsDisplay
+}
+{
+ bug_87461
+ Memcheck:Leak
+ ...
+ fun:_ZN15StatusBubbleMac6CreateEv
+ fun:_ZN15StatusBubbleMacC2EP8NSWindowP11objc_object
+ fun:-[BrowserWindowController initWithBrowser:takeOwnership:]
+ fun:-[BrowserWindowController initWithBrowser:]
+ fun:_ZN13BrowserWindow19CreateBrowserWindowEP7Browser
+ fun:_ZN7Browser19CreateBrowserWindowEv
+ fun:_ZN7Browser17InitBrowserWindowEv
+ fun:_ZN7Browser6CreateEP7Profile
+ fun:_ZN11BrowserInit17LaunchWithProfile17OpenTabsInBrowserEP7BrowserbRKSt6vectorINS0_3TabESaIS4_EE
+ fun:_ZN11BrowserInit17LaunchWithProfile17OpenURLsInBrowserEP7BrowserbRKSt6vectorI4GURLSaIS4_EE
+ fun:_ZN11BrowserInit17LaunchWithProfile17ProcessLaunchURLsEbRKSt6vectorI4GURLSaIS2_EE
+ fun:_ZN11BrowserInit17LaunchWithProfile6LaunchEP7ProfileRKSt6vectorI4GURLSaIS4_EEb
+ fun:_ZN11BrowserInit13LaunchBrowserE*
+ fun:_ZN11BrowserInit18ProcessCmdLineImplE*
+ fun:_ZN11BrowserInit5StartE*
+}
+{
+ bug_87629
+ Memcheck:Leak
+ ...
+ fun:realloc
+ fun:new_sem_from_pool
+}
+{
+ bug_90976
+ Memcheck:Unaddressable
+ ...
+ fun:_CFPropertyListCreateFromXMLData
+ fun:CFPropertyListCreateFromStream
+ fun:+[CFXPreferencesPropertyListSource createPlistFromFile:statInfo:]
+ fun:-[CFXPreferencesPropertyListSource synchronize]
+ fun:CFPreferencesSynchronize
+ fun:_CSBackupSettingsIsPathExcluded
+ fun:CSBackupIsItemExcluded
+ fun:pager_open_journal
+ fun:pager_write
+ fun:sqlite3PagerWrite
+ fun:newDatabase
+ fun:sqlite3BtreeBeginTrans
+ fun:sqlite3VdbeExec
+ fun:sqlite3Step
+ fun:sqlite3_step
+ fun:sqlite3_exec
+ fun:_ZN3sql10Connection7ExecuteEPKc
+}
+{
+ bug_91889_a
+ Memcheck:Unaddressable
+ fun:_ZN4base12_GLOBAL__N_122StackDumpSignalHandlerEiP9__siginfoP17__darwin_ucontext
+ obj:*
+ fun:IOCFUnserialize
+ fun:IORegistryEntrySearchCFProperty
+ fun:_ZN12_GLOBAL__N_121SearchPortForPropertyEjPK10__CFString
+ fun:_ZN12_GLOBAL__N_123CollectPCIVideoCardInfoEP7GPUInfo
+ fun:_ZN18gpu_info_collector30CollectPreliminaryGraphicsInfoEP7GPUInfo
+ fun:_ZN14GpuDataManagerC2Ev
+ fun:_ZN14GpuDataManagerC1Ev
+ fun:_ZN22DefaultSingletonTraitsI14GpuDataManagerE3NewEv
+ fun:_ZN9SingletonI14GpuDataManager22DefaultSingletonTraitsIS0_ES0_E3getEv
+ fun:_ZN14GpuDataManager11GetInstanceEv
+ fun:_ZN19GpuBlacklistUpdater17SetupOnFileThreadEv
+}
+{
+ bug_91889_b
+ Memcheck:Unaddressable
+ fun:IOCFUnserializeparse
+ fun:IOCFUnserialize
+ fun:IORegistryEntrySearchCFProperty
+ fun:_ZN12_GLOBAL__N_121SearchPortForPropertyEjPK10__CFString
+ fun:_ZN12_GLOBAL__N_123CollectPCIVideoCardInfoEP7GPUInfo
+ fun:_ZN18gpu_info_collector30CollectPreliminaryGraphicsInfoEP7GPUInfo
+ fun:_ZN14GpuDataManagerC2Ev
+ fun:_ZN14GpuDataManagerC1Ev
+ fun:_ZN22DefaultSingletonTraitsI14GpuDataManagerE3NewEv
+ fun:_ZN9SingletonI14GpuDataManager22DefaultSingletonTraitsIS0_ES0_E3getEv
+ fun:_ZN14GpuDataManager11GetInstanceEv
+ fun:_ZN19GpuBlacklistUpdater17SetupOnFileThreadEv
+}
+{
+ bug_91889_c
+ Memcheck:Unaddressable
+ fun:_ZN4base12_GLOBAL__N_122StackDumpSignalHandlerEiP9__siginfoP17__darwin_ucontext
+ obj:*
+ obj:*
+ fun:IOCFUnserialize
+ fun:IORegistryEntrySearchCFProperty
+ fun:_ZN12_GLOBAL__N_121SearchPortForPropertyEjPK10__CFString
+ fun:_ZN12_GLOBAL__N_123CollectPCIVideoCardInfoEP7GPUInfo
+ fun:_ZN18gpu_info_collector30CollectPreliminaryGraphicsInfoEP7GPUInfo
+ fun:_ZN14GpuDataManagerC2Ev
+ fun:_ZN14GpuDataManagerC1Ev
+ fun:_ZN22DefaultSingletonTraitsI14GpuDataManagerE3NewEv
+ fun:_ZN9SingletonI14GpuDataManager22DefaultSingletonTraitsIS0_ES0_E3getEv
+ fun:_ZN14GpuDataManager11GetInstanceEv
+ fun:_ZN19GpuBlacklistUpdater17SetupOnFileThreadEv
+}
+{
+ bug_91892
+ Memcheck:Leak
+ fun:_Znw*
+ fun:sendSimpleEventToSelf
+ fun:aeInitializeFromHIToolbox
+ fun:INIT_AppleEvents
+ fun:_FirstEventTime
+ fun:RunCurrentEventLoopInMode
+ fun:ReceiveNextEventCommon
+ fun:BlockUntilNextEventMatchingListInMode
+ fun:_DPSNextEvent
+ fun:-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
+ fun:-[NSApplication run]
+ fun:_ZN4base24MessagePumpNSApplication5DoRunEPNS_11MessagePump8DelegateE
+ fun:_ZN4base24MessagePumpCFRunLoopBase3RunEPNS_11MessagePump8DelegateE
+ fun:_ZN4base11MessageLoop11RunInternalEv
+ fun:_ZN4base11MessageLoop10RunHandlerEv
+ fun:_ZN4base11MessageLoop13RunAllPendingEv
+ fun:_ZN20InProcessBrowserTest23RunTestOnMainThreadLoopEv
+}
+{
+ bug_92579a
+ Memcheck:Unaddressable
+ fun:_ZN15CVCGDisplayLink17setCurrentDisplayEj
+ fun:CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext
+}
+{
+ bug_92579b
+ Memcheck:Unaddressable
+ fun:_ZN15CVCGDisplayLink17setCurrentDisplayEj
+ fun:_ZN15CVCGDisplayLink18initWithCGDisplaysEPjlPi
+ fun:CVDisplayLinkCreateWithCGDisplays
+ fun:CVDisplayLinkCreateWithActiveCGDisplays
+}
+{
+ bug_92579c
+ Memcheck:Unaddressable
+ fun:IOCFUnserializeparse
+ fun:IOCFUnserialize
+ fun:IORegistryEntryCreateCFProperties
+ fun:_ZN15CVCGDisplayLink17setCurrentDisplayEj
+ fun:_ZN15CVCGDisplayLink18initWithCGDisplaysEPjlPi
+ fun:CVDisplayLinkCreateWithCGDisplays
+ fun:CVDisplayLinkCreateWithActiveCGDisplays
+ fun:-[AcceleratedPluginView initWithRenderWidgetHostViewMac:pluginHandle:]
+}
+{
+ bug_93036
+ Memcheck:Unaddressable
+ fun:+[NSPICTImageRep _verifyDataIsPICT:]
+ fun:+[NSImageRep imageRepClassForData:]
+ fun:-[NSImage initWithData:]
+ fun:_ZN2ui14ResourceBundle19GetNativeImageNamedEi
+ fun:-[BookmarkBarController initWithBrowser:initialWidth:delegate:resizeDelegate:]
+}
+{
+ bug_93932_a
+ Memcheck:Overlap
+ fun:memcpy
+ fun:vp8_decode_update_thread_context
+ fun:update_context_from_thread
+ ...
+ fun:ff_thread_decode_frame
+ fun:avcodec_decode_video2
+ fun:_ZN5media23FFmpegVideoDecodeEngine6DecodeERK13scoped_refptrINS_6BufferEEPS1_INS_10VideoFrameEE
+ fun:_ZN5media18FFmpegVideoDecoder14DoDecodeBufferERK13scoped_refptrINS_6BufferEE
+}
+{
+ bug_93932_b
+ Memcheck:Overlap
+ fun:memcpy
+ fun:vp8_decode_update_thread_context
+ fun:update_context_from_thread
+ fun:frame_thread_free
+ fun:avcodec_close
+ ...
+ fun:_ZN5media23FFmpegVideoDecodeEngineD0Ev
+ fun:_ZN10scoped_ptrIN5media23FFmpegVideoDecodeEngineEE5resetEPS1_
+ fun:_ZN5media27FFmpegVideoDecodeEngineTestD2Ev
+ fun:_ZN5media51FFmpegVideoDecodeEngineTest_DecodeFrame_Normal_TestD0Ev
+}
+{
+ bug_96300
+ Memcheck:Leak
+ ...
+ fun:_ZN8Security12KeychainCore5Trust8evaluate*
+ fun:SecTrustEvaluate
+ fun:_ZN3net17CertVerifyProcMac14VerifyInternal*
+ fun:_ZN3net14CertVerifyProc6Verify*CertVerifyResult*
+}
+{
+ bug_96559a
+ Memcheck:Uninitialized
+ fun:PyObject_Realloc
+}
+{
+ bug_96559b
+ Memcheck:Unaddressable
+ fun:PyObject_Realloc
+}
+{
+ bug_96559c
+ Memcheck:Uninitialized
+ fun:PyObject_Realloc
+}
+{
+ bug_96559d
+ Memcheck:Uninitialized
+ fun:PyObject_Free
+}
+{
+ bug_96559e
+ Memcheck:Unaddressable
+ fun:PyObject_Free
+}
+{
+ bug_96559f
+ Memcheck:Uninitialized
+ fun:PyObject_Free
+}
+{
+ bug_96671
+ Memcheck:Uninitialized
+ ...
+ fun:_ZNK12MockKeychain26SearchCreateFromAttributesEPKvmPK24SecKeychainAttributeListPP26OpaqueSecKeychainSearchRef
+ fun:_ZN14KeychainSearch17FindMatchingItemsEPSt6vectorIP24OpaqueSecKeychainItemRefSaIS2_EE
+}
+{
+ bug_96684a
+ Memcheck:Uninitialized
+ fun:_ZN7content20P2PSocketHostTcpBase4SendERKN3net10IPEndPointERKSt6vectorIcSaIcEE
+ fun:*SocketHost*TcpTest_*_Test8TestBodyEv
+}
+{
+ bug_96684b
+ Memcheck:Uninitialized
+ fun:_ZN7content16P2PSocketHostUdp4SendERKN3net10IPEndPointERKSt6vectorIcSaIcEE
+ fun:*SocketHostUdpTest_*_Test8TestBodyEv
+}
+{
+ bug_96689
+ Memcheck:Uninitialized
+ fun:_ZN3net11SSLHostInfo10ParseInnerERKSs
+ fun:_ZN3net11SSLHostInfo5ParseERKSs
+ fun:_ZN3net25DiskCacheBasedSSLHostInfo22DoWaitForDataReadyDoneEv
+ fun:_ZN3net25DiskCacheBasedSSLHostInfo6DoLoopEi
+ fun:_ZN3net25DiskCacheBasedSSLHostInfo12OnIOCompleteEPNS0_22CacheOperationDataShimEi
+}
+{
+ bug_100022
+ Memcheck:Unaddressable
+ ...
+ fun:_ZNK11ImageLoader15containsAddressEPKv
+ fun:_ZN4dyld14bindLazySymbolEPK11mach_headerPm
+ fun:stub_binding_helper_interface2
+ obj:/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libRIP.A.dylib
+ obj:/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libRIP.A.dylib
+ fun:CGContextDrawImage
+ fun:_Z23PlotISImageRefInContextPvP9CGContext6CGRectssPK8RGBColormPK20_ISImageRefCallbacks
+ fun:PlotIconRefInContext
+}
+{
+ bug_100983
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base18StatisticsRecorder31RegisterOrDeleteDuplicateRangesEPNS_9HistogramE
+ fun:_ZN4base18StatisticsRecorder25RegisterOrDeleteDuplicateEPNS_9HistogramE
+ fun:_ZN10disk_cache14StatsHistogram10FactoryGetERKSs
+ fun:_ZN10disk_cache5Stats4InitEPNS_11BackendImplEPj
+ fun:_ZN10disk_cache11BackendImpl8SyncInitEv
+ fun:_ZN10disk_cache9BackendIO23ExecuteBackendOperationEv
+}
+{
+ bug_101359
+ Memcheck:Leak
+ fun:malloc
+ fun:CGFontNameTableCreate
+ fun:get_name_table
+ fun:CGFontCopyPostScriptName
+ fun:CGFontCreateFontsWithURL
+}
+{
+ bug_102327_a
+ Memcheck:Unaddressable
+ fun:_ZNK15tracked_objects10ThreadData26OnThreadTerminationCleanupEv
+ fun:_ZN15tracked_objects10ThreadData19OnThreadTerminationEPv
+ fun:_pthread_tsd_cleanup
+ fun:_pthread_exit
+ fun:thread_start
+}
+{
+ bug_102327_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN15tracked_objects10ThreadData10InitializeEv
+ fun:_ZN15tracked_objects10ThreadData23InitializeThreadContextERKSs
+}
+{
+ bug_102621
+ Memcheck:Uninitialized
+ ...
+ fun:-[NSPasteboard(ChimeraPasteboardURLUtils) getURLs:andTitles:convertingFilenames:]
+ fun:_ZN2ui33PopulateURLAndTitleFromPasteboardEP4GURLPSbItN4base20string16_char_traitsESaItEEP12NSPasteboarda
+ fun:_ZN24WebDragDestTest_URL_Test8TestBodyEv
+}
+{
+ bug_102920
+ Memcheck:Unaddressable
+ fun:MDItemCreate
+ fun:CSBackupSetItemExcluded
+ fun:_ZN4base3mac22SetFileBackupExclusionE*
+ fun:_ZN7history17ThumbnailDatabase4InitE*
+ fun:_ZN7history14HistoryBackend8InitImplERKSs
+ fun:_ZN7history14HistoryBackend4InitERKSsb
+}
+{
+ bug_104756
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3IPC11SyncMessage13GenerateReplyEPKNS_7MessageE
+ fun:_ZN3IPC17SyncMessageSchemaI6Tuple1IbES1_IRSt6vectorIN6webkit13WebPluginInfoESaIS5_EEEE32DispatchDelayReplyWithSendParamsI19RenderMessageFilterMSC_FvbPNS_7MessageEEEEbbRKS2_PKSD_PT_T0_
+ fun:_ZN22ViewHostMsg_GetPlugins18DispatchDelayReplyI19RenderMessageFilterMS1_FvbPN3IPC7MessageEEEEbPKS3_PT_T0_
+ fun:_ZN19RenderMessageFilter17OnMessageReceivedERKN3IPC7MessageEPb
+ fun:_ZN20BrowserMessageFilter15DispatchMessageERKN3IPC7MessageE
+}
+{
+ bug_104786
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKjiEEE8allocateEmPKv
+ fun:_ZNSt8_Rb_treeIjSt4pairIKjiESt10_Select1stIS2_ESt4lessIjESaIS2_EE11_M_get_nodeEv
+ fun:_ZNSt8_Rb_treeIjSt4pairIKjiESt10_Select1stIS2_ESt4lessIjESaIS2_EE14_M_create_nodeERKS2_
+ fun:_ZNSt8_Rb_treeIjSt4pairIKjiESt10_Select1stIS2_ESt4lessIjESaIS2_EE9_M_insertEPSt18_Rb_tree_node_baseSA_RKS2_
+ fun:_ZNSt8_Rb_treeIjSt4pairIKjiESt10_Select1stIS2_ESt4lessIjESaIS2_EE13insert_uniqueERKS2_
+ fun:_ZNSt8_Rb_treeIjSt4pairIKjiESt10_Select1stIS2_ESt4lessIjESaIS2_EE13insert_uniqueESt17_Rb_tree_iteratorIS2_ERKS2_
+ fun:_ZNSt3mapIjiSt4lessIjESaISt4pairIKjiEEE6insertESt17_Rb_tree_iteratorIS4_ERKS4_
+ fun:_ZNSt3mapIjiSt4lessIjESaISt4pairIKjiEEEixERS3_
+ fun:_ZN18RenderWidgetHelper17AllocTransportDIBEmbPN4base14FileDescriptorE
+ fun:_ZN19RenderMessageFilter19OnAllocTransportDIBEmbPN4base14FileDescriptorE
+}
+{
+ bug_105022
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:malloc_set_zone_name
+ fun:init__zone0
+ fun:setenv$UNIX2003
+ fun:_ZN12_GLOBAL__N_115EnvironmentImpl10SetVarImplEPKcRKSs
+ fun:_ZN12_GLOBAL__N_115EnvironmentImpl6SetVarEPKcRKSs
+ fun:_Z18AppendToPythonPath*FilePath
+ fun:_ZN*3net15LocalTestServer13SetPythonPathEv
+ fun:_ZN3net15LocalTestServer5StartEv
+ fun:_ZN12_GLOBAL__N_132MimeTypeTests_MimeTypeTests_Test8TestBodyEv
+}
+{
+ bug_105323
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN15tracked_objects10ThreadData3GetEv
+ fun:_ZN15tracked_objects10ThreadData32TallyRunOnWorkerThreadIfTrackingEPKNS_6BirthsERKNS_11TrackedTimeES6_S6_
+ fun:_ZN4base12_GLOBAL__N_112WorkerThread10ThreadMainEv
+ fun:_ZN4base12_GLOBAL__N_110ThreadFuncEPv
+}
+{
+ bug_105339
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_malloc_internal
+ fun:_cache_addForwardEntry
+ fun:lookUpMethod
+ fun:class_respondsToSelector
+}
+{
+ bug_105341_a
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:allocWorld
+ fun:create
+ fun:aquireColorWorldByAttributes
+ fun:acquireColorWorld
+ fun:CMSTransformConvert*
+ fun:CGCMSInterfaceTransformConvert*
+}
+{
+ bug_105341_b
+ Memcheck:Leak
+ fun:calloc
+ fun:_ZN9CMMMemMgr3NewEm
+ ...
+ fun:create
+ fun:aquireColorWorldByAttributes
+ fun:acquireColorWorld
+ fun:CMSTransformConvert*
+ fun:CGCMSInterfaceTransformConvert*
+}
+{
+ bug_105342
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN15TSessionManager20CreateSessionManagerEv
+ fun:pthread_once
+ fun:_ZN15TSessionManagerC1Ev
+ fun:_ZN13TFontMetadata24CreateMetadataForFontURLEPK7__CFURLb
+ ...
+ fun:XTRegisterFont
+ fun:SendActivateFontsMessage
+}
+{
+ bug_105523
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:allocGeneric
+ fun:create
+ fun:CMSCreateDataProvider
+ fun:create_generic_color_space
+ fun:CGColorSpaceCreateWithIndex
+}
+{
+ bug_105524_a
+ Memcheck:Uninitialized
+ fun:_ZNK7WebCore13InlineTextBox17expansionBehaviorEv
+ fun:_ZNK7WebCore13InlineTextBox16constructTextRunEPNS_11RenderStyleERKNS_4FontEPKtiiPNS_24BufferForAppendingHyphenE
+ fun:_ZNK7WebCore13InlineTextBox16constructTextRunEPNS_11RenderStyleERKNS_4FontEPNS_24BufferForAppendingHyphenE
+ fun:_ZNK7WebCore13InlineTextBox17positionForOffsetEi
+ fun:_ZN7WebCore10RenderText14localCaretRectEPNS_9InlineBoxEiPi
+ fun:_ZNK7WebCore15VisiblePosition14localCaretRectERPNS_12RenderObjectE
+ fun:_ZN7WebCore9CaretBase15updateCaretRectEPNS_8DocumentERKNS_15VisiblePositionE
+ fun:_ZN7WebCore14FrameSelection14localCaretRectEv
+ fun:_ZN7WebCore14FrameSelection18recomputeCaretRectEv
+ fun:_ZN7WebCore14FrameSelection16updateAppearanceEv
+ fun:_ZN7WebCore14FrameSelection12setSelectionERKNS_16VisibleSelectionEjNS0_19CursorAlignOnScrollENS_15TextGranularityE
+ fun:_ZN7WebCore14FrameSelection12setSelectionERKNS_16VisibleSelectionENS_15TextGranularityE
+ fun:_ZN7WebCore14FrameSelection34setNonDirectionalSelectionIfNeededERKNS_16VisibleSelectionENS_15TextGranularityENS0_23EndPointsAdjustmentModeE
+ fun:_ZN7WebCore12EventHandler49updateSelectionForMouseDownDispatchingSelectStartEPNS_4NodeERKNS_16VisibleSelectionENS_15TextGranularityE
+ fun:_ZN7WebCore12EventHandler32handleMousePressEventSingleClickERKNS_28MouseEventWithHitTestResultsE
+ fun:_ZN7WebCore12EventHandler21handleMousePressEventERKNS_28MouseEventWithHitTestResultsE
+ fun:_ZN7WebCore12EventHandler21handleMousePressEventERKNS_18PlatformMouseEventE
+ fun:_ZN7WebCore12EventHandler29passMousePressEventToSubframeERNS_28MouseEventWithHitTestResultsEPNS_5FrameE
+ fun:_ZN7WebCore12EventHandler21handleMousePressEventERKNS_18PlatformMouseEventE
+ fun:_ZN6WebKit11WebViewImpl9mouseDownERKNS_13WebMouseEventE
+ fun:_ZN6WebKit11WebViewImpl16handleInputEventERKNS_13WebInputEventE
+ fun:_ZN46ContextMenuCapturing_ContextMenuCapturing_Test8TestBodyEv
+}
+{
+ bug_105524_b
+ Memcheck:Uninitialized
+ fun:_ZNK7WebCore13InlineTextBox17expansionBehaviorEv
+ fun:_ZNK7WebCore13InlineTextBox16constructTextRunEPNS_11RenderStyleERKNS_4FontEPKtiiPNS_24BufferForAppendingHyphenE
+ fun:_ZN7WebCore13InlineTextBox5paintERNS_9PaintInfoERKNS_8IntPointEii
+ fun:_ZN7WebCore13InlineFlowBox5paintERNS_9PaintInfoERKNS_8IntPointEii
+ fun:_ZN7WebCore13RootInlineBox5paintERNS_9PaintInfoERKNS_8IntPointEii
+ fun:_ZNK7WebCore17RenderLineBoxList5paintEPNS_20RenderBoxModelObjectERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock13paintContentsERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock13paintChildrenERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock13paintContentsERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderLayer10paintLayerEPS0_PNS_15GraphicsContextERKNS_7IntRectEjPNS_12RenderObjectEPNS_12RenderRegionEPN3WTF7HashMapIPNS_24OverlapTestRequestClientES4_NSB_7PtrHashISE_EENSB_10HashTraitsISE_EENSH_IS4_EEEEj
+ fun:_ZN7WebCore11RenderLayer9paintListEPN3WTF6VectorIPS0_Lm0EEES3_PNS_15GraphicsContextERKNS_7IntRectEjPNS_12RenderObjectEPNS_12RenderRegionEPNS1_7HashMapIPNS_24OverlapTestRequestClientES8_NS1_7PtrHashISH_EENS1_10HashTraitsISH_EENSK_IS8_EEEEj
+ fun:_ZN7WebCore11RenderLayer10paintLayerEPS0_PNS_15GraphicsContextERKNS_7IntRectEjPNS_12RenderObjectEPNS_12RenderRegionEPN3WTF7HashMapIPNS_24OverlapTestRequestClientES4_NSB_7PtrHashISE_EENSB_10HashTraitsISE_EENSH_IS4_EEEEj
+ fun:_ZN7WebCore11RenderLayer5paintEPNS_15GraphicsContextERKNS_7IntRectEjPNS_12RenderObjectEPNS_12RenderRegionEj
+ fun:_ZN7WebCore9FrameView13paintContentsEPNS_15GraphicsContextERKNS_7IntRectE
+ fun:_ZN7WebCore10ScrollView5paintEPNS_15GraphicsContextERKNS_7IntRectE
+ fun:_ZN6WebKit12WebFrameImpl16paintWithContextERN7WebCore15GraphicsContextERKNS_7WebRectE
+ fun:_ZN6WebKit12WebFrameImpl5paintEP9CGContextRKNS_7WebRectE
+ fun:_ZN6WebKit11WebViewImpl5paintEP9CGContextRKNS_7WebRectE
+}
+{
+ bug_105525
+ Memcheck:Leak
+ ...
+ fun:CGContextDrawPath
+ fun:CGContextFillPath
+ fun:_NSDrawWindowBackgroundRegion
+ fun:-[NSThemeFrame drawWindowBackgroundRegion:]
+}
+{
+ bug_105526_read_a
+ Memcheck:Unaddressable
+ fun:CGSSetWindowColorSpace
+ fun:_ZN10WindowData16UpdateColorSpaceEh
+ fun:_ZN10WindowData18FinishConstructionEmymPK4RectPhjP15OpaqueWindowPtrP16OpaqueControlRef
+ fun:_ZN10WindowData10InitializeEP14OpaqueEventRef
+ fun:_ZN14AppleWindowDef10InitializeEP14OpaqueEventRef
+ fun:_ZN8HIObject24HandleClassHIObjectEventEP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv
+ fun:_ZN8HIObject9EventHookEP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv
+ fun:_ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec
+ fun:_ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec
+ fun:SendEventToEventTargetWithOptions
+ fun:_ZN8HIObject6CreateEPK10__CFStringP14OpaqueEventRefPPS_
+ fun:HIObjectCreate
+}
+{
+ bug_105526_read_b
+ Memcheck:Unaddressable
+ obj:*
+ fun:_ZN10WindowData16UpdateColorSpaceEh
+ fun:_ZN10WindowData18FinishConstructionEmymPK4RectPhjP15OpaqueWindowPtrP16OpaqueControlRef
+ fun:_ZN10WindowData10InitializeEP14OpaqueEventRef
+ fun:_ZN14AppleWindowDef10InitializeEP14OpaqueEventRef
+ fun:_ZN8HIObject24HandleClassHIObjectEventEP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv
+ fun:_ZN8HIObject9EventHookEP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv
+ fun:_ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec
+ fun:_ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec
+ fun:SendEventToEventTargetWithOptions
+ fun:_ZN8HIObject6CreateEPK10__CFStringP14OpaqueEventRefPPS_
+ fun:HIObjectCreate
+}
+{
+ bug_105526_write
+ Memcheck:Unaddressable
+ fun:CGSColorProfileRelease
+ fun:CGSSetWindowColorSpace
+ fun:_ZN10WindowData16UpdateColorSpaceEh
+ fun:_ZN10WindowData18FinishConstructionEmymPK4RectPhjP15OpaqueWindowPtrP16OpaqueControlRef
+ fun:_ZN10WindowData10InitializeEP14OpaqueEventRef
+ fun:_ZN14AppleWindowDef10InitializeEP14OpaqueEventRef
+ fun:_ZN8HIObject24HandleClassHIObjectEventEP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv
+ fun:_ZN8HIObject9EventHookEP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv
+ fun:_ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec
+ fun:_ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec
+ fun:SendEventToEventTargetWithOptions
+ fun:_ZN8HIObject6CreateEPK10__CFStringP14OpaqueEventRefPPS_
+ fun:HIObjectCreate
+}
+{
+ bug_105527_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN16TCFStringUniquer19CreateStringUniquerEv
+ fun:pthread_once
+ fun:_ZN16TCFStringUniquerC1Ev
+ fun:_ZNK6TCFStr15GetUniqueStringEv
+ fun:_ZNK17TClientFontEntity14CopyFamilyNameEb
+ fun:_ZNK11TFontEntity14CopyPropertiesEPK7__CFSetb
+ fun:_ZNK21TLocalFontRegistryImp37CopyPropertiesForFontsMatchingRequestEPK14__CFDictionaryPK7__CFSetj
+ fun:XTCopyFontsWithProperties
+ fun:_ZL20CopyFaceURLsForFontsPK9__CFArrayj
+ fun:XTRegisterFonts
+ fun:XTRegisterFont
+ fun:SendActivateFontsMessage
+}
+{
+ bug_105527_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN18TLocalFontRegistry14CreateRegistryEv
+ fun:pthread_once
+ fun:_ZN18TLocalFontRegistryC2Ev
+ fun:XTRegisterFonts
+ fun:XTRegisterFont
+ fun:SendActivateFontsMessage
+}
+{
+ bug_105527_c
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:CFBasicHashCreate
+ fun:__CFSetCreateGeneric
+ fun:CFSetCreate
+ fun:_ZN16TBasicFontEntity21CreateBasicPropertiesEv
+ fun:pthread_once
+ fun:_ZN16TBasicFontEntity18GetBasicPropertiesEv
+ fun:XTCopyFontsWithProperties
+}
+{
+ bug_105527_d
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN19TGlobalFontRegistry14CreateRegistryEv
+ fun:pthread_once
+ fun:_ZN19TGlobalFontRegistryC2Ev
+ fun:XTCopyFontWithName
+ fun:_ZNK17TDescriptorSource35CopyFontDescriptorPerPostscriptNameEPK10__CFStringm
+}
+{
+ bug_105527_e
+ Memcheck:Leak
+ fun:calloc
+ fun:CGFontFinderCreate
+ fun:cg_font_library_link_symbol
+ fun:load_vtable
+ fun:pthread_once
+ fun:CGFontGetVTable
+ fun:CGFontCreateFontsWithPath
+ fun:CGFontCreateFontsWithURL
+ fun:_Z18CreateFontsFromURLPK7__CFURL
+ fun:_ZNK21TLocalFontRegistryImp12RegisterFontEPK7__CFURLPK14__CFDictionaryjj
+ fun:_ZNK21TLocalFontRegistryImp13RegisterFontsEPK9__CFArrayPK14__CFDictionaryjjPS2_
+ fun:_ZNK18TLocalFontRegistry13RegisterFontsEPK9__CFArrayPK14__CFDictionaryjjPS2_
+ fun:XTRegisterFonts
+ fun:XTRegisterFont
+ fun:SendActivateFontsMessage
+}
+{
+ bug_105580
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:malloc_set_zone_name
+ fun:malloc_default_purgeable_zone
+ ...
+ fun:_ZN4base30EnableTerminationOnOutOfMemoryEv
+ fun:_ZN7leveldb12_GLOBAL__N_111ChromiumEnvC2Ev
+ ...
+ fun:_ZN4base25DefaultLazyInstanceTraitsIN7leveldb12_GLOBAL__N_111ChromiumEnvEE3NewEPv
+ ...
+ fun:_ZN4base12LazyInstanceIN7leveldb12_GLOBAL__N_111ChromiumEnvENS_*
+ ...
+ fun:_ZN7leveldb7OptionsC2Ev
+ ...
+ fun:_ZN7fileapi27FileSystemDirectoryDatabase4InitEv
+ fun:_ZN7fileapi27FileSystemDirectoryDatabase11GetFileInfoExPNS0_8FileInfoE
+ fun:_ZN7fileapi59FileSystemDirectoryDatabaseTest_TestMissingFileGetInfo_Test8TestBodyEv
+}
+{
+ bug_105938_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF12AtomicStringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ ...
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+ fun:_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb
+ fun:_ZN2v86Script3RunEv
+ fun:_ZN7WebCore7V8Proxy9runScriptEN2v86HandleINS1_6ScriptE*
+ fun:_ZN7WebCore7V8Proxy8evaluateERKNS_16ScriptSourceCodeEPNS_4NodeE
+ fun:_ZN7WebCore16ScriptController8evaluateERKNS_16ScriptSourceCodeE
+}
+{
+ bug_105938_b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF6StringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ ...
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+ fun:_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb
+ fun:_ZN2v86Script3RunEv
+ fun:_ZN7WebCore7V8Proxy9runScriptEN2v86HandleINS1_6ScriptE*
+ fun:_ZN7WebCore7V8Proxy8evaluateERKNS_16ScriptSourceCodeEPNS_4NodeE
+ fun:_ZN7WebCore16ScriptController8evaluateERKNS_16ScriptSourceCodeE
+}
+{
+ bug_105938_c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF12AtomicStringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ ...
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+ fun:_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb
+ fun:_ZN2v88Function4CallENS_6HandleINS_6ObjectEEEiPNS1_INS_5ValueEEE
+ fun:_ZN7WebCore7V8Proxy24instrumentedCallFunctionEPNS_4PageEN2v86HandleINS3_8FunctionEEENS4_INS3_6ObjectEEEiPNS4_INS3_5ValueEEE
+ fun:_ZN7WebCore7V8Proxy12callFunctionEN2v86HandleINS1_8FunctionEEENS2_INS1_6ObjectEEEiPNS2_INS1_5ValueEEE
+ fun:_ZN7WebCore19V8LazyEventListener20callListenerFunctionEPNS_22ScriptExecutionContextEN2v86HandleINS3_5ValueEEEPNS_5EventE
+ fun:_ZN7WebCore23V8AbstractEventListener18invokeEventHandlerEPNS_22ScriptExecutionContextEPNS_5EventEN2v86HandleINS5_5ValueEEE
+ fun:_ZN7WebCore23V8AbstractEventListener11handleEventEPNS_22ScriptExecutionContextEPNS_5EventE
+ fun:_ZN7WebCore11EventTarget18fireEventListenersEPNS_5EventEPNS_15EventTargetDataERN3WTF6VectorINS_23RegisteredEventListenerELm1EEE
+}
+{
+ bug_107179
+ Memcheck:Uninitialized
+ fun:_ZNK7WebCore13InlineTextBox17expansionBehaviorEv
+ fun:_ZNK7WebCore13InlineTextBox16constructTextRunEPNS_11RenderStyleERKNS_4FontEPKtiiPNS_24BufferForAppendingHyphenE
+ fun:_ZN7WebCore13InlineTextBox5paintERNS_9PaintInfoERKNS_8IntPointEii
+ fun:_ZN7WebCore13InlineFlowBox5paintERNS_9PaintInfoERKNS_8IntPointEii
+ fun:_ZN7WebCore13RootInlineBox5paintERNS_9PaintInfoERKNS_8IntPointEii
+ fun:_ZNK7WebCore17RenderLineBoxList5paintEPNS_20RenderBoxModelObjectERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock13paintContentsERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock13paintChildrenERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock13paintContentsERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_8IntPointE
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_8IntPointE
+ ...
+ fun:_ZN7WebCore11RenderLayer5paintEPNS_15GraphicsContextERKNS_7IntRectEjPNS_12RenderObjectEPNS_12RenderRegionEj
+ fun:_ZN7WebCore9FrameView13paintContentsEPNS_15GraphicsContextERKNS_7IntRectE
+ fun:_ZN7WebCore10ScrollView5paintEPNS_15GraphicsContextERKNS_7IntRectE
+ fun:_ZN6WebKit12WebFrameImpl16paintWithContextERN7WebCore15GraphicsContextERKNS_7WebRectE
+}
+{
+ bug_107541_a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZL14NewFromFontRefPK8__CTFontPKc
+ fun:_Z26SkCreateTypefaceFromCTFontPK8__CTFont
+ fun:_ZN7WebCoreL10setupPaintEP7SkPaintPKNS_14SimpleFontDataEPKNS_4FontE*
+ fun:_ZNK7WebCore4Font10drawGlyphsEPNS_15GraphicsContextEPKNS_14SimpleFontDataERKNS_11GlyphBufferEiiRKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font15drawGlyphBufferEPNS_15GraphicsContextERKNS_7TextRunERKNS_11GlyphBufferERKNS_10FloatPointE
+ fun:_ZNK7WebCore4Font14drawSimpleTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPointEii
+ fun:_ZNK7WebCore4Font8drawTextEPNS_15GraphicsContextERKNS_7TextRunERKNS_10FloatPoint*
+ fun:_ZN7WebCore15GraphicsContext8drawTextERKNS_4FontERKNS_7TextRunERKNS_10FloatPoint*
+ fun:_ZN7WebCoreL20paintTextWithShadowsEPNS_15GraphicsContextERKNS_4FontERKNS_7TextRunERKN3WTF12AtomicStringEiiiiRKNS_10FloatPointERKNS_9FloatRectEPKNS_10ShadowDataEbb
+ fun:_ZN7WebCore13InlineTextBox5paintERNS_9PaintInfoERKNS_*
+ fun:_ZN7WebCore13InlineFlowBox5paintERNS_9PaintInfoERKNS_*
+ fun:_ZN7WebCore13RootInlineBox5paintERNS_9PaintInfoERKNS_*
+ fun:_ZNK7WebCore17RenderLineBoxList5paintEPNS_20RenderBoxModelObjectERNS_9PaintInfoERKNS_*
+ fun:_ZN7WebCore11RenderBlock13paintContentsERNS_9PaintInfoERKNS_*
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_*
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_*
+ ...
+ fun:_ZN7WebCore11RenderBlock13paintChildrenERNS_9PaintInfoERKNS_*
+ fun:_ZN7WebCore11RenderBlock13paintContentsERNS_9PaintInfoERKNS_*
+ fun:_ZN7WebCore11RenderBlock11paintObjectERNS_9PaintInfoERKNS_*
+ fun:_ZN7WebCore11RenderBlock5paintERNS_9PaintInfoERKNS_*
+}
+{
+ bug_107541_b
+ Memcheck:Leak
+ fun:calloc
+ fun:CGGlyphBitmapCreate
+ ...
+ fun:CGFontCreateGlyphBitmap*
+ fun:create_missing_bitmaps
+ fun:CGGlyphLockLockGlyphBitmaps
+ ...
+ fun:draw_glyphs
+ fun:CGContextShowGlyphs
+ fun:_ZN9Offscreen5getCGERK19SkScalerContext_MacRK7SkGlyph*
+ fun:_ZN19SkScalerContext_Mac13generateImageERK7SkGlyph
+ fun:_ZN15SkScalerContext8getImageERK7SkGlyph
+ fun:_ZN12SkGlyphCache9findImageERK7SkGlyph
+ fun:_ZL22D1G_NoBounder_RectClipRK12SkDraw1GlyphiiRK7SkGlyph
+ fun:_ZNK6SkDraw*draw*TextE*
+ fun:_ZN8SkDevice*draw*TextE*
+ fun:_ZN8SkCanvas*draw*TextE*
+}
+{
+ bug_107541_c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZL14NewFromFontRefPK8__CTFontPKc
+ fun:_ZL11NewFromNamePKcN10SkTypeface5StyleE
+ fun:_ZL15create_typefacePK10SkTypefacePKcNS_5StyleE
+ fun:_ZN10SkFontHost14CreateTypefaceEPK10SkTypefacePKcNS0_5StyleE
+ fun:_ZN10SkTypeface14CreateFromNameEPKcNS_5StyleE
+ fun:_ZN3gfx8internal16SkiaTextRenderer22SetFontFamilyWithStyleERKSsi
+ fun:_ZN3gfx13RenderTextMac14DrawVisualTextEPNS_6CanvasE
+ fun:_ZN3gfx10RenderText4DrawEPNS_6CanvasE
+ fun:_ZN3gfx43RenderTextTest_SelectionKeepsLigatures_Test8TestBodyEv
+}
+{
+ bug_109994
+ Memcheck:Leak
+ ...
+ fun:_class_lookupMethodAndLoadCache
+ fun:objc_msgSend
+ ...
+ fun:_class_initialize
+ fun:_class_initialize
+ fun:_class_lookupMethodAndLoadCache
+ fun:objc_msgSend
+ fun:_ZN15ChromeTestSuite10InitializeEv
+ fun:_ZN4base9TestSuite3RunEv
+ fun:_ZN17UnitTestTestSuite3RunEv
+}
+{
+ bug_112078
+ Memcheck:Uninitialized
+ fun:glViewport_Exec
+ fun:glViewport
+ fun:-[AcceleratedPluginView globalFrameDidChange:]
+ fun:-[AcceleratedPluginView renewGState]
+ fun:-[NSView _invalidateGStatesForTree]
+ fun:-[NSView(NSInternal) _setHidden:setNeedsDisplay:]
+ fun:-[NSView _setHidden:]
+ fun:_ZN*23RenderWidgetHostViewMac17MovePluginWindows*
+ fun:_ZN*27RenderWidgetHostViewMacTest24AddAcceleratedPluginViewEii
+ fun:_ZN*53RenderWidgetHostViewMacTest_FocusAcceleratedView_Test8TestBodyEv
+}
+{
+ bug_112086
+ Memcheck:Uninitialized
+ fun:x_zone_size
+ fun:find_registered_purgeable_zone
+ fun:malloc_make_purgeable
+}
+{
+ bug_117310
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7WebCore23v8StringToWebCoreStringIN3WTF12AtomicStringEEET_N2v86HandleINS4_6StringEEENS_12ExternalModeE
+ fun:_ZN7WebCore29v8StringToAtomicWebCoreStringEN2v86HandleINS0_6StringEEE
+ fun:_ZN7WebCore11V8DOMWindow19namedPropertyGetterEN2v85LocalINS1_6StringEEERKNS1_12AccessorInfoE
+ fun:_ZN2v88internal8JSObject26GetPropertyWithInterceptorEPNS0_10JSReceiverEPNS0_6StringEP18PropertyAttributes
+ fun:_ZN2v88internal6Object11GetPropertyEPS1_PNS0_12LookupResultEPNS0_6StringEP18PropertyAttributes
+ fun:_ZN2v88internal6Object11GetPropertyENS0_6HandleIS1_EES3_PNS0_12LookupResultENS2_INS0_6StringEEEP18PropertyAttributes
+ fun:_ZN2v88internal6LoadIC4LoadENS0_16InlineCacheStateENS0_6HandleINS0_6ObjectEEENS3_INS0_6StringEEE
+ fun:_ZN2v88internal11LoadIC_MissENS0_9ArgumentsEPNS0_7IsolateE
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ fun:_ZN2v88internalL6InvokeEbNS0_6HandleINS0_10JSFunctionEEENS1_INS0_6ObjectEEEiPS5_Pb
+ fun:_ZN2v88internal9Execution4CallENS0_6HandleINS0_6ObjectEEES4_iPS4_Pbb
+ fun:_ZN2v88Function4CallENS_6HandleINS_6ObjectEEEiPNS1_INS_5ValueEEE
+ fun:_ZN7WebCore7V8Proxy24instrumentedCallFunctionEPNS_5FrameEN2v86HandleINS3_8FunctionEEENS4_INS3_6ObjectEEEiPNS4_INS3_5ValueEEE
+ fun:_ZN7WebCore7V8Proxy12callFunctionEN2v86HandleINS1_8FunctionEEENS2_INS1_6ObjectEEEiPNS2_INS1_5ValueEEE
+ fun:_ZN7WebCore19V8LazyEventListener20callListenerFunctionEPNS_22ScriptExecutionContextEN2v86HandleINS3_5ValueEEEPNS_5EventE
+ fun:_ZN7WebCore23V8AbstractEventListener18invokeEventHandlerEPNS_22ScriptExecutionContextEPNS_5EventEN2v86HandleINS5_5ValueEEE
+ fun:_ZN7WebCore23V8AbstractEventListener11handleEventEPNS_22ScriptExecutionContextEPNS_5EventE
+ fun:_ZN7WebCore11EventTarget18fireEventListenersEPNS_5EventEPNS_15EventTargetDataERN3WTF6VectorINS_23RegisteredEventListenerELm1EEE
+}
+{
+ bug_127499_a
+ Memcheck:Uninitialized
+ ...
+ fun:VDADecoderCreate
+ fun:_ZN3gfx30VideoDecodeAccelerationSupport6CreateEiiiPKvm
+ fun:_ZN3gfx46VideoDecodeAccelerationSupportTest_Create_Test8TestBodyEv
+}
+{
+ bug_127499_b
+ Memcheck:Leak
+ ...
+ fun:VDADecoderCreate
+ fun:_ZN3gfx30VideoDecodeAccelerationSupport6CreateEiiiPKvm
+ fun:_ZN3gfx46VideoDecodeAccelerationSupportTest_Create_Test8TestBodyEv
+}
+{
+ bug_127499_c
+ Memcheck:Free
+ ...
+ fun:VTDecompressionSessionInvalidate
+ fun:VDADecoderDestroy
+ fun:_ZN3gfx30VideoDecodeAccelerationSupport7DestroyEv
+ fun:_ZN3gfx46VideoDecodeAccelerationSupportTest_Create_Test8TestBodyEv
+}
+{
+ bug_127499_d
+ Memcheck:Uninitialized
+ ...
+ fun:VTDecompressionSessionInvalidate
+ fun:VDADecoderDestroy
+ fun:_ZN3gfx30VideoDecodeAccelerationSupport7DestroyEv
+ fun:_ZN3gfx46VideoDecodeAccelerationSupportTest_Create_Test8TestBodyEv
+}
+{
+ bug_127499_e
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN4base17LoadNativeLibraryE*
+ fun:_ZN12_GLOBAL__N_117InitializeVdaApisEv
+ fun:_ZN3gfx30VideoDecodeAccelerationSupport6CreateEiiiPKvm
+ fun:_ZN3gfx46VideoDecodeAccelerationSupportTest_Create_Test8TestBodyEv
+}
+{
+ bug_127499_f
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:CFBasicHashCreate
+ fun:__CFDictionaryCreateGeneric
+ fun:CFDictionaryCreate
+ fun:-[__NSPlaceholderDictionary initWithObjects:forKeys:count:]
+ fun:+[NSDictionary dictionaryWithObjectsAndKeys:]
+ fun:_ZN3gfx30VideoDecodeAccelerationSupport6CreateEiiiPKvm
+ fun:_ZN3gfx46VideoDecodeAccelerationSupportTest_Create_Test8TestBodyEv
+}
+{
+ bug_131361
+ Memcheck:Overlap
+ fun:memcpy
+ ...
+ fun:_ZN2v88internal18GvnBasicBlockState32*
+}
+{
+ bug_139633
+ Memcheck:Uninitialized
+ fun:_ZL19ConvertYUVToRGB32_ChhhPh
+ fun:LinearScaleYUVToRGB32RowWithRange_C
+ fun:_ZN5media23ScaleYUVToRGB32WithRectEPKhS1_S1_Phiiiiiiiiiii
+ fun:_ZN8remoting29ConvertAndScaleYUVToRGB32RectEPKhS1_S1_iiRK7SkTSizeIiERK7SkIRectPhiS5_S8_S8_
+ fun:_ZN8remoting10DecoderVp811RenderFrameERK7SkTSizeIiERK7SkIRectPhiP8SkRegion
+ fun:_ZN8remoting13DecoderTester11RenderFrameEv
+ fun:_ZN8remoting13DecoderTester14ReceivedPacketEPNS_11VideoPacketE
+ fun:_ZN8remoting13DecoderTester20ReceivedScopedPacketE10scoped_ptrINS_11VideoPacketEE
+}
+{
+ bug_148865
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN7content16RenderThreadImpl4InitEv
+ fun:_ZN7content16RenderThreadImplC2ERKSs
+ fun:_ZN7content16RenderThreadImplC1ERKSs
+ fun:_ZN7content21WebRTCAudioDeviceTest5SetUpEv
+}
+{
+ bug_159190
+ Memcheck:Uninitialized
+ ...
+ fun:_ZNK19TConcreteFontScaler15CopyGlyphBitmapEtjP6CGRectPm
+ ...
+ fun:_ZN9Offscreen5getCGERK19SkScalerContext_MacRK7SkGlyphtPmb
+ fun:_ZN19SkScalerContext_Mac13generateImageERK7SkGlyph
+}
+{
+ bug_171722_mac
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN3net12_GLOBAL__N_120URLRequestFtpJobTest9AddSocketEPNS_13MockReadWriteILNS_17MockReadWriteTypeE0EEEmPNS2_ILS3_1EEEm
+ ...
+}
+{
+ bug_173779
+ Memcheck:Uninitialized
+ ...
+ fun:img_data_lock
+ fun:CGSImageDataLock
+ fun:ripc_AcquireImage
+ fun:ripc_DrawImages
+ fun:CGContextDrawImages
+ fun:_ZN11CUIRenderer10Draw9PieceElPK13CUIDescriptorm
+ fun:_ZN11CUIRenderer4DrawE6CGRectP9CGContextPK14__CFDictionaryPS5_
+ fun:-[NSButtonCell drawBezelWithFrame:inView:]
+ ...
+}
+{
+ bug_177540
+ Memcheck:Uninitialized
+ fun:_ZN3WTF20TCMalloc_ThreadCache10DeallocateENS_11HardenedSLLEm
+}
+{
+ bug_178424c
+ Memcheck:Param
+ write(buf)
+ fun:write$UNIX2003
+}
+{
+ bug_178424d
+ Memcheck:Param
+ read(buf)
+ fun:read$UNIX2003
+}
+{
+ bug_231969
+ Memcheck:Uninitialized
+ fun:rangematch
+ fun:fnmatch1
+ fun:fnmatch1
+ fun:fnmatch$UNIX2003
+ fun:_ZN4base14FileEnumerator4NextEv
+ fun:_ZN10disk_cache15SimpleIndexFile15RestoreFromDiskERKN4base8FilePathE
+}
+{
+ bug_244420
+ Memcheck:Uninitialized
+ ...
+ fun:_ZN9talk_baseL8ToStringIyEESsRKT_
+ fun:_ZN7content23VideoDestinationHandler4OpenEPNS_28MediaStreamDependencyFactoryEPNS_28MediaStreamRegistryInterfaceERKSsPPNS_20FrameWriterInterfaceE
+ fun:_ZN7content37VideoDestinationHandlerTest_Open_Test8TestBodyEv
+}
+{
+ bug_244437
+ Memcheck:Uninitialized
+ fun:_ZN5mediaL23FromInterleavedInternalIssLs0EEEvPKviiPNS_8AudioBusEff
+ fun:_ZN5media8AudioBus22FromInterleavedPartialEPKviii
+ fun:_ZN5media8AudioBus15FromInterleavedEPKvii
+ fun:_ZN7content19WebRtcAudioRenderer14SourceCallbackEiPN5media8AudioBusE
+}
+{
+ bug_246567
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2v88internal24PerThreadAssertScopeBase10AssertDataEv
+ fun:_ZN2v88internal20PerThreadAssertScopeILNS0_19PerThreadAssertTypeE1ELb1EE9IsAllowedEv
+ ...
+ fun:_ZN3net15ProxyResolverV87Context6InitV8ERK13scoped_refptrINS_23ProxyResolverScriptDataEE
+ fun:_ZN3net15ProxyResolverV812SetPacScriptERK13scoped_refptrINS_23ProxyResolverScriptDataEERKN4base8CallbackIFviEEE
+ fun:_ZN3net22ProxyResolverV8Tracing3Job20ExecuteProxyResolverEv
+ fun:_ZN3net22ProxyResolverV8Tracing3Job15ExecuteBlockingEv
+}
+{
+ bug_246567b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN2v88internal24PerThreadAssertScopeBase10AssertDataEv
+ fun:_ZN2v88internal20PerThreadAssertScopeILNS0_19PerThreadAssertTypeE1ELb1EE9IsAllowedEv
+ fun:_ZN2v88internal11HandleScope12CreateHandleINS0*
+ fun:_ZN2v88internal6Handle*
+}
+# Maybe related to bug_105527_a?
+{
+ bug_247506a
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN16TCFStringUniquer19CreateStringUniquerEv
+ fun:pthread_once
+ fun:_ZN16TCFStringUniquerC1Ev
+ fun:_ZN19TCFResurrectContext17ResurrectCFStringEv
+ fun:_ZN19TCFResurrectContext9ResurrectEv
+ fun:_ZN19TCFResurrectContext21ResurrectCFDictionaryEv
+ fun:_ZN19TCFResurrectContext9ResurrectEv
+ fun:_ZNK22TGlobalFontRegistryImp20RendezvousWithServerEv
+ fun:_ZN22TGlobalFontRegistryImpC2Ev
+ fun:_ZN19TGlobalFontRegistry14CreateRegistryEv
+}
+# Maybe related to bug_105527_b ?
+{
+ bug_247506b
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN18TLocalFontRegistry14CreateRegistryEv
+ fun:pthread_once
+ fun:_ZN18TLocalFontRegistryC2Ev
+ fun:XTCopyFontWithName
+ fun:_ZNK17TDescriptorSource35CopyFontDescriptorPerPostscriptNameEPK10__CFStringm
+ fun:_ZNK11TDescriptor32CreateMatchingDescriptorInternalEPK7__CFSet
+ fun:_ZN11TDescriptor12InitBaseFontEv
+}
+# Maybe related to bug_105342 ?
+{
+ bug_247506c
+ Memcheck:Leak
+ fun:_Znw*
+ fun:_ZN15TSessionManager20CreateSessionManagerEv
+ fun:pthread_once
+ fun:_ZN15TSessionManagerC1Ev
+ fun:_ZNK22TGlobalFontRegistryImp13GetServerPortEv
+ fun:_ZNK22TGlobalFontRegistryImp20RendezvousWithServerEv
+ fun:_ZN22TGlobalFontRegistryImpC2Ev
+ fun:_ZN19TGlobalFontRegistry14CreateRegistryEv
+ fun:pthread_once
+ fun:_ZN19TGlobalFontRegistryC2Ev
+ fun:XTCopyFontWithName
+}
+{
+ bug_247506d
+ Memcheck:Leak
+ fun:malloc_zone_calloc
+ fun:_calloc_internal
+ fun:_cache_malloc
+ fun:_cache_fill
+ fun:lookUpMethod
+ fun:_class_lookupMethodAndLoadCache
+ fun:objc_msgSend
+ ...
+ fun:_ZL17SetupMenuTrackingR14MenuSelectDatah5PointdP8MenuDatamtPK4RectS6_jS6_PK10__CFString
+ fun:_ZL19PopUpMenuSelectCoreP8MenuData5PointdS1_tjPK4RecttmS4_S4_PK10__CFStringPP13OpaqueMenuRefPt
+ fun:_HandlePopUpMenuSelection7
+}
+{
+ bug_247506e
+ Memcheck:Leak
+ fun:calloc
+ fun:_ZN11TMemoryHeap6CallocEmm
+ fun:_Z14AllocateMemorymP11TMemoryHeapb
+ fun:_Z13CacheAllocatemb
+ fun:_Z16BuildMacEncTablev
+ fun:_ZN15TParsingContext13GetParseProcsEv
+ fun:_ZN19TSFNTParsingContext13GetParseProcsEv
+ fun:_ZN18TCIDParsingContext13GetParseProcsEv
+ fun:_ZN16TType1OTFCIDFont20ParseCFFCIDFontDictsERK19TType1CFFDescriptorP32Type1ProtectionEvaluationContextRVt
+}
+{
+ bug_247506f
+ Memcheck:Leak
+ fun:malloc_zone_calloc
+ fun:_calloc_internal
+ fun:_objc_insertMethods
+ fun:_objc_read_categories_from_image
+ fun:_read_images
+ fun:map_images_nolock
+ fun:map_images
+ fun:_ZN4dyldL18notifyBatchPartialE17dyld_image_statesbPFPKcS0_jPK15dyld_image_infoE
+ fun:_ZN11ImageLoader4linkERKNS_11LinkContextEbbRKNS_10RPathChainE
+ fun:_ZN4dyld4linkEP11ImageLoaderbRKNS0_10RPathChainE
+}
+{
+ bug_247506g
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:malloc_set_zone_name
+ fun:malloc_default_purgeable_zone
+ fun:ImageIO_Malloc
+ fun:copyImageBlockSetPNG
+ fun:ImageProviderCopyImageBlockSetCallback
+ fun:CGImageProviderCopyImageBlockSet
+ fun:img_blocks_create
+ fun:img_blocks_extent
+ fun:img_data_lock
+ fun:CGSImageDataLock
+ fun:ripc_AcquireImage
+ fun:ripc_DrawImage
+ fun:CGContextDrawImage
+ fun:__-[NSImageRep drawInRect:fromRect:operation:fraction:respectFlipped:hints:]_block_invoke_1
+ fun:-[NSImageRep drawInRect:fromRect:operation:fraction:respectFlipped:hints:]
+ fun:_ZN12_GLOBAL__N_129NSImageOrNSImageRepToSkBitmapEP7NSImageP10NSImageRep7_NSSizeb
+ fun:_ZN3gfx20NSImageRepToSkBitmapEP10NSImageRep7_NSSizeb
+ fun:_ZN3gfx27ImageSkiaFromResizedNSImageEP7NSImage7_NSSize
+ fun:_ZN3gfx20ImageSkiaFromNSImageEP7NSImage
+ fun:_ZNK3gfx5Image11ToImageSkiaEv
+ fun:_ZNK3gfx5Image10ToSkBitmapEv
+}
+{
+ bug_247506h
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN11TMemoryHeap6MallocEm
+ fun:_Z14AllocateMemorymP11TMemoryHeapb
+ fun:_Z13GetGrowBufferm
+ fun:_ZN31TFractionalMetricsRenderContextC2EPK10TType1FontPKht
+ fun:_ZNK10TType1Font13GetRawMetricsERK18TType1FontInstancePKhtR10_t_CharSBW
+ fun:_ZNK10TType1Font23RenderFractionalMetricsERK15TType1TransformtPKhtR22GlyphFractionalMetrics
+ fun:_ZNK13TType1CIDFont20GetFractionalMetricsERK15TType1TransformtP22GlyphFractionalMetrics
+ fun:_ZNK12TType1Strike10GetMetricsERK21TRenderingDescriptionmPKtRK19TDestinationMapping
+ fun:_Z20Type1GetGlyphMetricsmPK18TStrikeDescriptionPK21TRenderingDescriptionmPKtPvm
+ fun:_ZNK19TConcreteFontScaler25GetGlyphIdealAdvanceWidthEt
+}
+{
+ bug_247506i
+ Memcheck:Leak
+ fun:malloc_zone_malloc
+ fun:_CFRuntimeCreateInstance
+ fun:CFBasicHashCreate
+ fun:__CFDictionaryCreateGeneric
+ fun:CFDictionaryCreateMutable
+ fun:utDeactivateAllSelectedIMInDoc
+ fun:MyDeactivateTSMDocument
+ fun:_ReactivateTSMDocumentAfterMenuTracking
+}
+{
+ bug_247506j
+ Memcheck:Leak
+ fun:malloc_zone_calloc
+ fun:ripr_Rectangles
+ fun:ripc_DrawRects
+ fun:CGContextFillRects
+ fun:NSRectFillListWithColorsUsingOperation
+ fun:NSDrawColorTiledRects
+}
+{
+ bug_247506k
+ Memcheck:Leak
+ fun:malloc
+ fun:_ZN11TMemoryHeap6MallocEm
+ fun:_Z24Type1InterpretCharStringP11_t_FontInstP10_t_BCProcsP17_t_T1CharDataDescP9_t_CharIOP9_t_RunRecP12_t_PathProcsP6T1Args
+ fun:_ZL14ATMCharOutlineP11_t_FontInstP10_t_BCProcsPvP9_t_CharIOP12_t_PathProcsmS3_
+ fun:_ZN21MPathRenderingContext13RenderOutlineERK11_t_FontInstb
+ fun:_ZN28TPathMetricsRenderingContext11MakeOutlineERK11_t_FontInstbR10FixedPointS4_S4_
+ fun:_ZNK10TType1Font20RenderOutlineMetricsERK15TType1TransformtPKhtR21GlyphRenderingMetrics
+ fun:_ZNK13TType1CIDFont17GetOutlineMetricsERK15TType1TransformtP21GlyphRenderingMetrics
+ fun:_ZNK12TType1Strike10GetMetricsERK21TRenderingDescriptionmPKtRK19TDestinationMapping
+ fun:_Z20Type1GetGlyphMetricsmPK18TStrikeDescriptionPK21TRenderingDescriptionmPKtPvm
+ fun:_ZNK19TConcreteFontScaler19GetGlyphIdealBoundsEt
+ fun:FPFontGetGlyphIdealBounds
+}
+{
+ bug_257276
+ Memcheck:Leak
+ fun:malloc_zone_calloc
+ fun:ripr_Path
+ fun:ripc_DrawPath
+ fun:CGContextDrawPath
+ fun:CGContextStrokePath
+ fun:-[NSLayoutManager(NSTextViewSupport) _drawLineForGlyphRange:inContext:from:to:at:thickness:lineOrigin:breakForDescenders:flipped:]
+ fun:-[NSLayoutManager(NSTextViewSupport) _drawLineForGlyphRange:type:baselineOffset:lineFragmentRect:lineFragmentGlyphRange:containerOrigin:isStrikethrough:]
+ fun:-[NSLayoutManager(NSTextViewSupport) drawUnderlineForGlyphRange:underlineType:baselineOffset:lineFragmentRect:lineFragmentGlyphRange:containerOrigin:]
+ fun:-[NSLayoutManager(NSTextViewSupport) _lineGlyphRange:type:lineFragmentRect:lineFragmentGlyphRange:containerOrigin:isStrikethrough:]
+ fun:-[NSLayoutManager(NSTextViewSupport) underlineGlyphRange:underlineType:lineFragmentRect:lineFragmentGlyphRange:containerOrigin:]
+ fun:-[NSLayoutManager(NSPrivate) _drawGlyphsForGlyphRange:atPoint:parameters:]
+ fun:-[NSLayoutManager(NSTextViewSupport) drawGlyphsForGlyphRange:atPoint:]
+ fun:-[NSStringDrawingTextStorage drawTextContainer:withRect:graphicsContext:baselineMode:scrollable:padding:]
+ fun:_NSStringDrawingCore
+ fun:-[NSString(NSExtendedStringDrawing) drawWithRect:options:attributes:]
+ fun:-[HyperlinkButtonCell drawTitle:withFrame:inView:]
+}
+{
+ bug_257501
+ Memcheck:Uninitialized
+ fun:rangematch
+ fun:fnmatch1
+ fun:fnmatch1
+ fun:fnmatch$UNIX2003
+ fun:_ZN4base14FileEnumerator4NextEv
+ fun:_ZN10disk_cache15SimpleIndexFile19SyncRestoreFromDiskERKN4base8FilePathE
+ fun:_ZN10disk_cache15SimpleIndexFile20SyncLoadIndexEntriesERKN4base8FilePathE13scoped_refptrINS1_22SingleThreadTaskRunnerEERKNS1_8CallbackIFv10scoped_ptrIN9__gnu_cxx8hash_mapIyNS_13EntryMetadataENSA_4hashIyEESt8equal_toIyESaISC_EEENS1_14DefaultDeleterISI_EEEbEEE
+}
diff --git a/chromium/tools/valgrind/memcheck_analyze.py b/chromium/tools/valgrind/memcheck_analyze.py
new file mode 100755
index 00000000000..91795df34e0
--- /dev/null
+++ b/chromium/tools/valgrind/memcheck_analyze.py
@@ -0,0 +1,634 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# memcheck_analyze.py
+
+''' Given a valgrind XML file, parses errors and uniques them.'''
+
+import gdb_helper
+
+from collections import defaultdict
+import hashlib
+import logging
+import optparse
+import os
+import re
+import subprocess
+import sys
+import time
+from xml.dom.minidom import parse
+from xml.parsers.expat import ExpatError
+
+import common
+
+# Global symbol table (yuck)
+TheAddressTable = None
+
+# These are regexps that define functions (using C++ mangled names)
+# we don't want to see in stack traces while pretty printing
+# or generating suppressions.
+# Just stop printing the stack/suppression frames when the current one
+# matches any of these.
+_BORING_CALLERS = common.BoringCallers(mangled=True, use_re_wildcards=True)
+
+def getTextOf(top_node, name):
+ ''' Returns all text in all DOM nodes with a certain |name| that are children
+ of |top_node|.
+ '''
+
+ text = ""
+ for nodes_named in top_node.getElementsByTagName(name):
+ text += "".join([node.data for node in nodes_named.childNodes
+ if node.nodeType == node.TEXT_NODE])
+ return text
+
+def getCDATAOf(top_node, name):
+ ''' Returns all CDATA in all DOM nodes with a certain |name| that are children
+ of |top_node|.
+ '''
+
+ text = ""
+ for nodes_named in top_node.getElementsByTagName(name):
+ text += "".join([node.data for node in nodes_named.childNodes
+ if node.nodeType == node.CDATA_SECTION_NODE])
+ if (text == ""):
+ return None
+ return text
+
+def shortenFilePath(source_dir, directory):
+ '''Returns a string with the string prefix |source_dir| removed from
+ |directory|.'''
+ prefixes_to_cut = ["build/src/", "valgrind/coregrind/", "out/Release/../../"]
+
+ if source_dir:
+ prefixes_to_cut.append(source_dir)
+
+ for p in prefixes_to_cut:
+ index = directory.rfind(p)
+ if index != -1:
+ directory = directory[index + len(p):]
+
+ return directory
+
+# Constants that give real names to the abbreviations in valgrind XML output.
+INSTRUCTION_POINTER = "ip"
+OBJECT_FILE = "obj"
+FUNCTION_NAME = "fn"
+SRC_FILE_DIR = "dir"
+SRC_FILE_NAME = "file"
+SRC_LINE = "line"
+
+def gatherFrames(node, source_dir):
+ frames = []
+ for frame in node.getElementsByTagName("frame"):
+ frame_dict = {
+ INSTRUCTION_POINTER : getTextOf(frame, INSTRUCTION_POINTER),
+ OBJECT_FILE : getTextOf(frame, OBJECT_FILE),
+ FUNCTION_NAME : getTextOf(frame, FUNCTION_NAME),
+ SRC_FILE_DIR : shortenFilePath(
+ source_dir, getTextOf(frame, SRC_FILE_DIR)),
+ SRC_FILE_NAME : getTextOf(frame, SRC_FILE_NAME),
+ SRC_LINE : getTextOf(frame, SRC_LINE)
+ }
+
+ # Ignore this frame and all the following if it's a "boring" function.
+ enough_frames = False
+ for regexp in _BORING_CALLERS:
+ if re.match("^%s$" % regexp, frame_dict[FUNCTION_NAME]):
+ enough_frames = True
+ break
+ if enough_frames:
+ break
+
+ frames += [frame_dict]
+
+ global TheAddressTable
+ if TheAddressTable != None and frame_dict[SRC_LINE] == "":
+ # Try using gdb
+ TheAddressTable.Add(frame_dict[OBJECT_FILE],
+ frame_dict[INSTRUCTION_POINTER])
+ return frames
+
+class ValgrindError:
+ ''' Takes a <DOM Element: error> node and reads all the data from it. A
+ ValgrindError is immutable and is hashed on its pretty printed output.
+ '''
+
+ def __init__(self, source_dir, error_node, commandline, testcase):
+ ''' Copies all the relevant information out of the DOM and into object
+ properties.
+
+ Args:
+ error_node: The <error></error> DOM node we're extracting from.
+ source_dir: Prefix that should be stripped from the <dir> node.
+ commandline: The command that was run under valgrind
+ testcase: The test case name, if known.
+ '''
+
+ # Valgrind errors contain one <what><stack> pair, plus an optional
+ # <auxwhat><stack> pair, plus an optional <origin><what><stack></origin>,
+ # plus (since 3.5.0) a <suppression></suppression> pair.
+ # (Origin is nicely enclosed; too bad the other two aren't.)
+ # The most common way to see all three in one report is
+ # a syscall with a parameter that points to uninitialized memory, e.g.
+ # Format:
+ # <error>
+ # <unique>0x6d</unique>
+ # <tid>1</tid>
+ # <kind>SyscallParam</kind>
+ # <what>Syscall param write(buf) points to uninitialised byte(s)</what>
+ # <stack>
+ # <frame>
+ # ...
+ # </frame>
+ # </stack>
+ # <auxwhat>Address 0x5c9af4f is 7 bytes inside a block of ...</auxwhat>
+ # <stack>
+ # <frame>
+ # ...
+ # </frame>
+ # </stack>
+ # <origin>
+ # <what>Uninitialised value was created by a heap allocation</what>
+ # <stack>
+ # <frame>
+ # ...
+ # </frame>
+ # </stack>
+ # </origin>
+ # <suppression>
+ # <sname>insert_a_suppression_name_here</sname>
+ # <skind>Memcheck:Param</skind>
+ # <skaux>write(buf)</skaux>
+ # <sframe> <fun>__write_nocancel</fun> </sframe>
+ # ...
+ # <sframe> <fun>main</fun> </sframe>
+ # <rawtext>
+ # <![CDATA[
+ # {
+ # <insert_a_suppression_name_here>
+ # Memcheck:Param
+ # write(buf)
+ # fun:__write_nocancel
+ # ...
+ # fun:main
+ # }
+ # ]]>
+ # </rawtext>
+ # </suppression>
+ # </error>
+ #
+ # Each frame looks like this:
+ # <frame>
+ # <ip>0x83751BC</ip>
+ # <obj>/data/dkegel/chrome-build/src/out/Release/base_unittests</obj>
+ # <fn>_ZN7testing8internal12TestInfoImpl7RunTestEPNS_8TestInfoE</fn>
+ # <dir>/data/dkegel/chrome-build/src/testing/gtest/src</dir>
+ # <file>gtest-internal-inl.h</file>
+ # <line>655</line>
+ # </frame>
+ # although the dir, file, and line elements are missing if there is
+ # no debug info.
+
+ self._kind = getTextOf(error_node, "kind")
+ self._backtraces = []
+ self._suppression = None
+ self._commandline = commandline
+ self._testcase = testcase
+ self._additional = []
+
+ # Iterate through the nodes, parsing <what|auxwhat><stack> pairs.
+ description = None
+ for node in error_node.childNodes:
+ if node.localName == "what" or node.localName == "auxwhat":
+ description = "".join([n.data for n in node.childNodes
+ if n.nodeType == n.TEXT_NODE])
+ elif node.localName == "xwhat":
+ description = getTextOf(node, "text")
+ elif node.localName == "stack":
+ assert description
+ self._backtraces.append([description, gatherFrames(node, source_dir)])
+ description = None
+ elif node.localName == "origin":
+ description = getTextOf(node, "what")
+ stack = node.getElementsByTagName("stack")[0]
+ frames = gatherFrames(stack, source_dir)
+ self._backtraces.append([description, frames])
+ description = None
+ stack = None
+ frames = None
+ elif description and node.localName != None:
+ # The lastest description has no stack, e.g. "Address 0x28 is unknown"
+ self._additional.append(description)
+ description = None
+
+ if node.localName == "suppression":
+ self._suppression = getCDATAOf(node, "rawtext");
+
+ def __str__(self):
+ ''' Pretty print the type and backtrace(s) of this specific error,
+ including suppression (which is just a mangled backtrace).'''
+ output = ""
+ if (self._commandline):
+ output += self._commandline + "\n"
+
+ output += self._kind + "\n"
+ for backtrace in self._backtraces:
+ output += backtrace[0] + "\n"
+ filter = subprocess.Popen("c++filt -n", stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ shell=True,
+ close_fds=True)
+ buf = ""
+ for frame in backtrace[1]:
+ buf += (frame[FUNCTION_NAME] or frame[INSTRUCTION_POINTER]) + "\n"
+ (stdoutbuf, stderrbuf) = filter.communicate(buf.encode('latin-1'))
+ demangled_names = stdoutbuf.split("\n")
+
+ i = 0
+ for frame in backtrace[1]:
+ output += (" " + demangled_names[i])
+ i = i + 1
+
+ global TheAddressTable
+ if TheAddressTable != None and frame[SRC_FILE_DIR] == "":
+ # Try using gdb
+ foo = TheAddressTable.GetFileLine(frame[OBJECT_FILE],
+ frame[INSTRUCTION_POINTER])
+ if foo[0] != None:
+ output += (" (" + foo[0] + ":" + foo[1] + ")")
+ elif frame[SRC_FILE_DIR] != "":
+ output += (" (" + frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME] +
+ ":" + frame[SRC_LINE] + ")")
+ else:
+ output += " (" + frame[OBJECT_FILE] + ")"
+ output += "\n"
+
+ for additional in self._additional:
+ output += additional + "\n"
+
+ assert self._suppression != None, "Your Valgrind doesn't generate " \
+ "suppressions - is it too old?"
+
+ if self._testcase:
+ output += "The report came from the `%s` test.\n" % self._testcase
+ output += "Suppression (error hash=#%016X#):\n" % self.ErrorHash()
+ output += (" For more info on using suppressions see "
+ "http://dev.chromium.org/developers/tree-sheriffs/sheriff-details-chromium/memory-sheriff#TOC-Suppressing-memory-reports")
+
+ # Widen suppression slightly to make portable between mac and linux
+ # TODO(timurrrr): Oops, these transformations should happen
+ # BEFORE calculating the hash!
+ supp = self._suppression;
+ supp = supp.replace("fun:_Znwj", "fun:_Znw*")
+ supp = supp.replace("fun:_Znwm", "fun:_Znw*")
+ supp = supp.replace("fun:_Znaj", "fun:_Zna*")
+ supp = supp.replace("fun:_Znam", "fun:_Zna*")
+
+ # Make suppressions even less platform-dependent.
+ for sz in [1, 2, 4, 8]:
+ supp = supp.replace("Memcheck:Addr%d" % sz, "Memcheck:Unaddressable")
+ supp = supp.replace("Memcheck:Value%d" % sz, "Memcheck:Uninitialized")
+ supp = supp.replace("Memcheck:Cond", "Memcheck:Uninitialized")
+
+ # Split into lines so we can enforce length limits
+ supplines = supp.split("\n")
+ supp = None # to avoid re-use
+
+ # Truncate at line 26 (VG_MAX_SUPP_CALLERS plus 2 for name and type)
+ # or at the first 'boring' caller.
+ # (https://bugs.kde.org/show_bug.cgi?id=199468 proposes raising
+ # VG_MAX_SUPP_CALLERS, but we're probably fine with it as is.)
+ newlen = min(26, len(supplines));
+
+ # Drop boring frames and all the following.
+ enough_frames = False
+ for frameno in range(newlen):
+ for boring_caller in _BORING_CALLERS:
+ if re.match("^ +fun:%s$" % boring_caller, supplines[frameno]):
+ newlen = frameno
+ enough_frames = True
+ break
+ if enough_frames:
+ break
+ if (len(supplines) > newlen):
+ supplines = supplines[0:newlen]
+ supplines.append("}")
+
+ for frame in range(len(supplines)):
+ # Replace the always-changing anonymous namespace prefix with "*".
+ m = re.match("( +fun:)_ZN.*_GLOBAL__N_.*\.cc_" +
+ "[0-9a-fA-F]{8}_[0-9a-fA-F]{8}(.*)",
+ supplines[frame])
+ if m:
+ supplines[frame] = "*".join(m.groups())
+
+ output += "\n".join(supplines) + "\n"
+
+ return output
+
+ def UniqueString(self):
+ ''' String to use for object identity. Don't print this, use str(obj)
+ instead.'''
+ rep = self._kind + " "
+ for backtrace in self._backtraces:
+ for frame in backtrace[1]:
+ rep += frame[FUNCTION_NAME]
+
+ if frame[SRC_FILE_DIR] != "":
+ rep += frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME]
+ else:
+ rep += frame[OBJECT_FILE]
+
+ return rep
+
+ # This is a device-independent hash identifying the suppression.
+ # By printing out this hash we can find duplicate reports between tests and
+ # different shards running on multiple buildbots
+ def ErrorHash(self):
+ return int(hashlib.md5(self.UniqueString()).hexdigest()[:16], 16)
+
+ def __hash__(self):
+ return hash(self.UniqueString())
+ def __eq__(self, rhs):
+ return self.UniqueString() == rhs
+
+def log_is_finished(f, force_finish):
+ f.seek(0)
+ prev_line = ""
+ while True:
+ line = f.readline()
+ if line == "":
+ if not force_finish:
+ return False
+ # Okay, the log is not finished but we can make it up to be parseable:
+ if prev_line.strip() in ["</error>", "</errorcounts>", "</status>"]:
+ f.write("</valgrindoutput>\n")
+ return True
+ return False
+ if '</valgrindoutput>' in line:
+ # Valgrind often has garbage after </valgrindoutput> upon crash.
+ f.truncate()
+ return True
+ prev_line = line
+
+class MemcheckAnalyzer:
+ ''' Given a set of Valgrind XML files, parse all the errors out of them,
+ unique them and output the results.'''
+
+ SANITY_TEST_SUPPRESSIONS = {
+ "Memcheck sanity test 01 (memory leak).": 1,
+ "Memcheck sanity test 02 (malloc/read left).": 1,
+ "Memcheck sanity test 03 (malloc/read right).": 1,
+ "Memcheck sanity test 04 (malloc/write left).": 1,
+ "Memcheck sanity test 05 (malloc/write right).": 1,
+ "Memcheck sanity test 06 (new/read left).": 1,
+ "Memcheck sanity test 07 (new/read right).": 1,
+ "Memcheck sanity test 08 (new/write left).": 1,
+ "Memcheck sanity test 09 (new/write right).": 1,
+ "Memcheck sanity test 10 (write after free).": 1,
+ "Memcheck sanity test 11 (write after delete).": 1,
+ "Memcheck sanity test 12 (array deleted without []).": 1,
+ "Memcheck sanity test 13 (single element deleted with []).": 1,
+ "Memcheck sanity test 14 (malloc/read uninit).": 1,
+ "Memcheck sanity test 15 (new/read uninit).": 1,
+ }
+
+ # Max time to wait for memcheck logs to complete.
+ LOG_COMPLETION_TIMEOUT = 180.0
+
+ def __init__(self, source_dir, show_all_leaks=False, use_gdb=False):
+ '''Create a parser for Memcheck logs.
+
+ Args:
+ source_dir: Path to top of source tree for this build
+ show_all_leaks: Whether to show even less important leaks
+ use_gdb: Whether to use gdb to resolve source filenames and line numbers
+ in the report stacktraces
+ '''
+ self._source_dir = source_dir
+ self._show_all_leaks = show_all_leaks
+ self._use_gdb = use_gdb
+
+ # Contains the set of unique errors
+ self._errors = set()
+
+ # Contains the time when the we started analyzing the first log file.
+ # This variable is used to skip incomplete logs after some timeout.
+ self._analyze_start_time = None
+
+
+ def Report(self, files, testcase, check_sanity=False):
+ '''Reads in a set of files and prints Memcheck report.
+
+ Args:
+ files: A list of filenames.
+ check_sanity: if true, search for SANITY_TEST_SUPPRESSIONS
+ '''
+ # Beyond the detailed errors parsed by ValgrindError above,
+ # the xml file contain records describing suppressions that were used:
+ # <suppcounts>
+ # <pair>
+ # <count>28</count>
+ # <name>pango_font_leak_todo</name>
+ # </pair>
+ # <pair>
+ # <count>378</count>
+ # <name>bug_13243</name>
+ # </pair>
+ # </suppcounts
+ # Collect these and print them at the end.
+ #
+ # With our patch for https://bugs.kde.org/show_bug.cgi?id=205000 in,
+ # the file also includes records of the form
+ # <load_obj><obj>/usr/lib/libgcc_s.1.dylib</obj><ip>0x27000</ip></load_obj>
+ # giving the filename and load address of each binary that was mapped
+ # into the process.
+
+ global TheAddressTable
+ if self._use_gdb:
+ TheAddressTable = gdb_helper.AddressTable()
+ else:
+ TheAddressTable = None
+ cur_report_errors = set()
+ suppcounts = defaultdict(int)
+ badfiles = set()
+
+ if self._analyze_start_time == None:
+ self._analyze_start_time = time.time()
+ start_time = self._analyze_start_time
+
+ parse_failed = False
+ for file in files:
+ # Wait up to three minutes for valgrind to finish writing all files,
+ # but after that, just skip incomplete files and warn.
+ f = open(file, "r+")
+ pid = re.match(".*\.([0-9]+)$", file)
+ if pid:
+ pid = pid.groups()[0]
+ found = False
+ running = True
+ firstrun = True
+ skip = False
+ origsize = os.path.getsize(file)
+ while (running and not found and not skip and
+ (firstrun or
+ ((time.time() - start_time) < self.LOG_COMPLETION_TIMEOUT))):
+ firstrun = False
+ f.seek(0)
+ if pid:
+ # Make sure the process is still running so we don't wait for
+ # 3 minutes if it was killed. See http://crbug.com/17453
+ ps_out = subprocess.Popen("ps p %s" % pid, shell=True,
+ stdout=subprocess.PIPE).stdout
+ if len(ps_out.readlines()) < 2:
+ running = False
+ else:
+ skip = True
+ running = False
+ found = log_is_finished(f, False)
+ if not running and not found:
+ logging.warn("Valgrind process PID = %s is not running but its "
+ "XML log has not been finished correctly.\n"
+ "Make it up by adding some closing tags manually." % pid)
+ found = log_is_finished(f, not running)
+ if running and not found:
+ time.sleep(1)
+ f.close()
+ if not found:
+ badfiles.add(file)
+ else:
+ newsize = os.path.getsize(file)
+ if origsize > newsize+1:
+ logging.warn(str(origsize - newsize) +
+ " bytes of junk were after </valgrindoutput> in %s!" %
+ file)
+ try:
+ parsed_file = parse(file);
+ except ExpatError, e:
+ parse_failed = True
+ logging.warn("could not parse %s: %s" % (file, e))
+ lineno = e.lineno - 1
+ context_lines = 5
+ context_start = max(0, lineno - context_lines)
+ context_end = lineno + context_lines + 1
+ context_file = open(file, "r")
+ for i in range(0, context_start):
+ context_file.readline()
+ for i in range(context_start, context_end):
+ context_data = context_file.readline().rstrip()
+ if i != lineno:
+ logging.warn(" %s" % context_data)
+ else:
+ logging.warn("> %s" % context_data)
+ context_file.close()
+ continue
+ if TheAddressTable != None:
+ load_objs = parsed_file.getElementsByTagName("load_obj")
+ for load_obj in load_objs:
+ obj = getTextOf(load_obj, "obj")
+ ip = getTextOf(load_obj, "ip")
+ TheAddressTable.AddBinaryAt(obj, ip)
+
+ commandline = None
+ preamble = parsed_file.getElementsByTagName("preamble")[0];
+ for node in preamble.getElementsByTagName("line"):
+ if node.localName == "line":
+ for x in node.childNodes:
+ if x.nodeType == node.TEXT_NODE and "Command" in x.data:
+ commandline = x.data
+ break
+
+ raw_errors = parsed_file.getElementsByTagName("error")
+ for raw_error in raw_errors:
+ # Ignore "possible" leaks for now by default.
+ if (self._show_all_leaks or
+ getTextOf(raw_error, "kind") != "Leak_PossiblyLost"):
+ error = ValgrindError(self._source_dir,
+ raw_error, commandline, testcase)
+ if error not in cur_report_errors:
+ # We haven't seen such errors doing this report yet...
+ if error in self._errors:
+ # ... but we saw it in earlier reports, e.g. previous UI test
+ cur_report_errors.add("This error was already printed in "
+ "some other test, see 'hash=#%016X#'" % \
+ error.ErrorHash())
+ else:
+ # ... and we haven't seen it in other tests as well
+ self._errors.add(error)
+ cur_report_errors.add(error)
+
+ suppcountlist = parsed_file.getElementsByTagName("suppcounts")
+ if len(suppcountlist) > 0:
+ suppcountlist = suppcountlist[0]
+ for node in suppcountlist.getElementsByTagName("pair"):
+ count = getTextOf(node, "count");
+ name = getTextOf(node, "name");
+ suppcounts[name] += int(count)
+
+ if len(badfiles) > 0:
+ logging.warn("valgrind didn't finish writing %d files?!" % len(badfiles))
+ for file in badfiles:
+ logging.warn("Last 20 lines of %s :" % file)
+ os.system("tail -n 20 '%s' 1>&2" % file)
+
+ if parse_failed:
+ logging.error("FAIL! Couldn't parse Valgrind output file")
+ return -2
+
+ common.PrintUsedSuppressionsList(suppcounts)
+
+ retcode = 0
+ if cur_report_errors:
+ logging.error("FAIL! There were %s errors: " % len(cur_report_errors))
+
+ if TheAddressTable != None:
+ TheAddressTable.ResolveAll()
+
+ for error in cur_report_errors:
+ logging.error(error)
+
+ retcode = -1
+
+ # Report tool's insanity even if there were errors.
+ if check_sanity:
+ remaining_sanity_supp = MemcheckAnalyzer.SANITY_TEST_SUPPRESSIONS
+ for (name, count) in suppcounts.iteritems():
+ if (name in remaining_sanity_supp and
+ remaining_sanity_supp[name] == count):
+ del remaining_sanity_supp[name]
+ if remaining_sanity_supp:
+ logging.error("FAIL! Sanity check failed!")
+ logging.info("The following test errors were not handled: ")
+ for (name, count) in remaining_sanity_supp.iteritems():
+ logging.info(" * %dx %s" % (count, name))
+ retcode = -3
+
+ if retcode != 0:
+ return retcode
+
+ logging.info("PASS! No errors found!")
+ return 0
+
+
+def _main():
+ '''For testing only. The MemcheckAnalyzer class should be imported instead.'''
+ parser = optparse.OptionParser("usage: %prog [options] <files to analyze>")
+ parser.add_option("", "--source_dir",
+ help="path to top of source tree for this build"
+ "(used to normalize source paths in baseline)")
+
+ (options, args) = parser.parse_args()
+ if len(args) == 0:
+ parser.error("no filename specified")
+ filenames = args
+
+ analyzer = MemcheckAnalyzer(options.source_dir, use_gdb=True)
+ return analyzer.Report(filenames, None)
+
+
+if __name__ == "__main__":
+ sys.exit(_main())
diff --git a/chromium/tools/valgrind/regrind.sh b/chromium/tools/valgrind/regrind.sh
new file mode 100755
index 00000000000..0f90ba737f0
--- /dev/null
+++ b/chromium/tools/valgrind/regrind.sh
@@ -0,0 +1,138 @@
+#!/bin/sh
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Scape errors from the valgrind bots, reproduce them locally,
+# save logs as regrind-TESTNAME.log, and display any errors found.
+# Also save files regrind-failed.txt listing failed tests,
+# and regrind-failed-map.txt showing which bot URLs have which failed tests
+# (handy when filing bugs).
+#
+# Only scrapes linux layout bot at the moment.
+# TODO: handle layout tests that don't have obvious path to test file
+# TODO: extend script to handle more kinds of errors and more tests
+
+# where the valgrind layout bot results live
+LAYOUT_URL="http://build.chromium.org/p/chromium.memory.fyi/builders/Webkit%20Linux%20(valgrind%20layout)"
+# how many builds back to check
+LAYOUT_COUNT=250
+
+# regexp to match valgrind errors
+PATTERN="are definitely|uninitialised|Unhandled exception|\
+Invalid read|Invalid write|Invalid free|Source and desti|Mismatched free|\
+unaddressable byte|vex x86|the 'impossible' happened|\
+valgrind:.*: Assertion.*failed|VALGRIND INTERNAL ERROR"
+
+usage() {
+ echo "Usage: regrind.sh [--noscrape][--norepro][--keep]"
+ echo "--noscrape: don't scrape bots, just use old regrind-failed.txt"
+ echo "--norepro: don't reproduce locally"
+ echo "--keep: keep temp files"
+ exit 1
+}
+
+# Given a log on stdin, list all the tests that failed in that log.
+layout_list_failed_tests() {
+ grep "Command:.*LayoutTests" |
+ sed 's/<.*>//' |
+ sed 's/.*LayoutTests/LayoutTests/' |
+ sort -u |
+ tr -d '\015'
+}
+
+# Generate a list of failed tests in regrind-failed.txt by scraping bot.
+# Scrape most recent first, so if user interrupts, he is left with fresh-ish data.
+scrape_layout() {
+ rm -f regrind-*.tmp* regrind-failed.txt regrind-failed-map.txt
+ touch regrind-failed.txt
+
+ # First, grab the number of the latest complete build.
+ wget -q -O regrind-builds.html "$LAYOUT_URL"
+ latest=`grep "<li><font .*" < regrind-builds.html | head -1 | sed 's/.*#//;s/<.*//'`
+
+ echo "Fetching $LAYOUT_COUNT logs from bot"
+ # Scrape the desired number of runs (150 is about one cycle)
+ first=`expr $latest - $LAYOUT_COUNT`
+ i=$latest
+ while test $i -ge $first
+ do
+ url="$LAYOUT_URL/builds/$i/steps/valgrind%20test:%20layout/logs/stdio"
+ wget -q -O regrind-$i.tmp "$url"
+ # Did any tests fail in this file?
+ layout_list_failed_tests < regrind-$i.tmp > regrind-$i.tmp.failed
+ if test -s regrind-$i.tmp.failed
+ then
+ # Yes. Log them to stdout,
+ echo "$url"
+ cat regrind-$i.tmp.failed
+ # to the table regrind-failed-map.txt,
+ cat regrind-$i.tmp.failed | sed "s,^,$url ," >> regrind-failed-map.txt
+ # and, if not already there, to regrind-failed.txt.
+ for test in `cat regrind-$i.tmp.failed`
+ do
+ fgrep "$test" regrind-failed.txt > /dev/null 2>&1 || echo "$test" >> regrind-failed.txt
+ done
+ else
+ rm regrind-$i.tmp.failed
+ fi
+ # Sleep 1/3 sec per fetch
+ case $i in
+ *[036]) sleep 1;;
+ esac
+ i=`expr $i - 1`
+ done
+
+ # Finally, munge the logs to identify tests that probably failed.
+ sh c.sh -l regrind-*.tmp > regrind-errfiles.txt
+ cat `cat regrind-errfiles.txt` | layout_list_failed_tests > regrind-failed.txt
+}
+
+# Run the tests identified in regrind-failed.txt locally under valgrind.
+# Save logs in regrind-$TESTNAME.log.
+repro_layout() {
+ echo Running `wc -l < regrind-failed.txt` layout tests.
+ for test in `cat regrind-failed.txt`
+ do
+ logname="`echo $test | tr / _`"
+ echo "sh tools/valgrind/valgrind_webkit_tests.sh $test"
+ sh tools/valgrind/valgrind_webkit_tests.sh "$test" > regrind-"$logname".log 2>&1
+ egrep "$PATTERN" < regrind-"$logname".log | sed 's/==.*==//'
+ done
+}
+
+do_repro=1
+do_scrape=1
+do_cleanup=1
+while test ! -z "$1"
+do
+ case "$1" in
+ --noscrape) do_scrape=0;;
+ --norepro) do_repro=0;;
+ --keep) do_cleanup=0;;
+ *) usage;;
+ esac
+ shift
+done
+
+echo "WARNING: This script is not supported and may be out of date"
+
+if test $do_scrape = 0 && test $do_repro = 0
+then
+ usage
+fi
+
+if test $do_scrape = 1
+then
+ scrape_layout
+fi
+
+if test $do_repro = 1
+then
+ repro_layout
+fi
+
+if test $do_cleanup = 1
+then
+ rm -f regrind-errfiles.txt regrind-*.tmp*
+fi
diff --git a/chromium/tools/valgrind/reliability/url_list.txt b/chromium/tools/valgrind/reliability/url_list.txt
new file mode 100644
index 00000000000..ac531225602
--- /dev/null
+++ b/chromium/tools/valgrind/reliability/url_list.txt
@@ -0,0 +1,11 @@
+www.google.com
+maps.google.com
+news.google.com
+www.youtube.com
+build.chromium.org/p/chromium/waterfall
+build.chromium.org/p/chromium.memory/console
+build.chromium.org/f/chromium/perf/dashboard/overview.html
+www.slashdot.org
+www.ibanez.co.jp/japan/index.html
+www.bbc.co.uk/arabic/
+www.uni.edu/becker/chinese2.html
diff --git a/chromium/tools/valgrind/scan-build.py b/chromium/tools/valgrind/scan-build.py
new file mode 100755
index 00000000000..b58b6cc447e
--- /dev/null
+++ b/chromium/tools/valgrind/scan-build.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import errno
+import os
+import re
+import sys
+import urllib
+import urllib2
+
+# Where all the data lives.
+ROOT_URL = "http://build.chromium.org/p/chromium.memory.fyi/builders"
+
+# TODO(groby) - support multi-line search from the command line. Useful when
+# scanning for classes of failures, see below.
+SEARCH_STRING = """<p class=\"failure result\">
+Failed memory test: content
+</p>"""
+
+# Location of the log cache.
+CACHE_DIR = "buildlogs.tmp"
+
+# If we don't find anything after searching |CUTOFF| logs, we're probably done.
+CUTOFF = 100
+
+def EnsurePath(path):
+ """Makes sure |path| does exist, tries to create it if it doesn't."""
+ try:
+ os.makedirs(path)
+ except OSError as exception:
+ if exception.errno != errno.EEXIST:
+ raise
+
+
+class Cache(object):
+ def __init__(self, root_dir):
+ self._root_dir = os.path.abspath(root_dir)
+
+ def _LocalName(self, name):
+ """If name is a relative path, treat it as relative to cache root.
+ If it is absolute and under cache root, pass it through.
+ Otherwise, raise error.
+ """
+ if os.path.isabs(name):
+ assert os.path.commonprefix([name, self._root_dir]) == self._root_dir
+ else:
+ name = os.path.join(self._root_dir, name)
+ return name
+
+ def _FetchLocal(self, local_name):
+ local_name = self._LocalName(local_name)
+ EnsurePath(os.path.dirname(local_name))
+ if os.path.exists(local_name):
+ f = open(local_name, 'r')
+ return f.readlines();
+ return None
+
+ def _FetchRemote(self, remote_name):
+ try:
+ response = urllib2.urlopen(remote_name)
+ except:
+ print "Could not fetch", remote_name
+ raise
+ return response.read()
+
+ def Update(self, local_name, remote_name):
+ local_name = self._LocalName(local_name)
+ EnsurePath(os.path.dirname(local_name))
+ blob = self._FetchRemote(remote_name)
+ f = open(local_name, "w")
+ f.write(blob)
+ return blob.splitlines()
+
+ def FetchData(self, local_name, remote_name):
+ result = self._FetchLocal(local_name)
+ if result:
+ return result
+ # If we get here, the local cache does not exist yet. Fetch, and store.
+ return self.Update(local_name, remote_name)
+
+
+class Builder(object):
+ def __init__(self, waterfall, name):
+ self._name = name
+ self._waterfall = waterfall
+
+ def Name(self):
+ return self._name
+
+ def LatestBuild(self):
+ return self._waterfall.GetLatestBuild(self._name)
+
+ def GetBuildPath(self, build_num):
+ return "%s/%s/builds/%d" % (
+ self._waterfall._root_url, urllib.quote(self._name), build_num)
+
+ def _FetchBuildLog(self, build_num):
+ local_build_path = "builds/%s" % self._name
+ local_build_file = os.path.join(local_build_path, "%d.log" % build_num)
+ return self._waterfall._cache.FetchData(local_build_file,
+ self.GetBuildPath(build_num))
+
+ def _CheckLog(self, build_num, tester):
+ log_lines = self._FetchBuildLog(build_num)
+ return any(tester(line) for line in log_lines)
+
+ def ScanLogs(self, tester):
+ occurrences = []
+ build = self.LatestBuild()
+ no_results = 0
+ while build != 0 and no_results < CUTOFF:
+ if self._CheckLog(build, tester):
+ occurrences.append(build)
+ else:
+ no_results = no_results + 1
+ build = build - 1
+ return occurrences
+
+
+class Waterfall(object):
+ def __init__(self, root_url, cache_dir):
+ self._root_url = root_url
+ self._builders = {}
+ self._top_revision = {}
+ self._cache = Cache(cache_dir)
+
+ def Builders(self):
+ return self._builders.values()
+
+ def Update(self):
+ self._cache.Update("builders", self._root_url)
+ self.FetchInfo()
+
+ def FetchInfo(self):
+ if self._top_revision:
+ return
+
+ html = self._cache.FetchData("builders", self._root_url)
+
+ """ Search for both builders and latest build number in HTML
+ <td class="box"><a href="builders/<builder-name>"> identifies a builder
+ <a href="builders/<builder-name>/builds/<build-num>"> is the latest build.
+ """
+ box_matcher = re.compile('.*a href[^>]*>([^<]*)\<')
+ build_matcher = re.compile('.*a href=\"builders/(.*)/builds/([0-9]+)\".*')
+ last_builder = ""
+ for line in html:
+ if 'a href="builders/' in line:
+ if 'td class="box"' in line:
+ last_builder = box_matcher.match(line).group(1)
+ self._builders[last_builder] = Builder(self, last_builder)
+ else:
+ result = build_matcher.match(line)
+ builder = result.group(1)
+ assert builder == urllib.quote(last_builder)
+ self._top_revision[last_builder] = int(result.group(2))
+
+ def GetLatestBuild(self, name):
+ self.FetchInfo()
+ assert self._top_revision
+ return self._top_revision[name]
+
+
+class MultiLineChange(object):
+ def __init__(self, lines):
+ self._tracked_lines = lines
+ self._current = 0
+
+ def __call__(self, line):
+ """ Test a single line against multi-line change.
+
+ If it matches the currently active line, advance one line.
+ If the current line is the last line, report a match.
+ """
+ if self._tracked_lines[self._current] in line:
+ self._current = self._current + 1
+ if self._current == len(self._tracked_lines):
+ self._current = 0
+ return True
+ else:
+ self._current = 0
+ return False
+
+
+def main(argv):
+ # Create argument parser.
+ parser = argparse.ArgumentParser()
+ commands = parser.add_mutually_exclusive_group(required=True)
+ commands.add_argument("--update", action='store_true')
+ commands.add_argument("--find", metavar='search term')
+ args = parser.parse_args()
+
+ path = os.path.abspath(os.path.dirname(argv[0]))
+ cache_path = os.path.join(path, CACHE_DIR)
+
+ fyi = Waterfall(ROOT_URL, cache_path)
+
+ if args.update:
+ fyi.Update()
+ for builder in fyi.Builders():
+ print "Updating", builder.Name()
+ builder.ScanLogs(lambda x:False)
+
+ if args.find:
+ tester = MultiLineChange(args.find.splitlines())
+ fyi.FetchInfo()
+
+ print "SCANNING FOR ", args.find
+ for builder in fyi.Builders():
+ print "Scanning", builder.Name()
+ occurrences = builder.ScanLogs(tester)
+ if occurrences:
+ min_build = min(occurrences)
+ path = builder.GetBuildPath(min_build)
+ print "Earliest occurrence in build %d" % min_build
+ print "Latest occurrence in build %d" % max(occurrences)
+ print "Latest build: %d" % builder.LatestBuild()
+ print path
+ print "%d total" % len(occurrences)
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
+
diff --git a/chromium/tools/valgrind/shard-all-tests.sh b/chromium/tools/valgrind/shard-all-tests.sh
new file mode 100755
index 00000000000..dfcf3d7fa0b
--- /dev/null
+++ b/chromium/tools/valgrind/shard-all-tests.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to run tests under tools/valgrind/chrome_tests.sh
+# in a loop looking for rare/flaky valgrind warnings, and
+# generate suppressions for them, to be later filed as bugs
+# and added to our suppressions file.
+#
+# FIXME: Layout tests are a bit funny - they have their own
+# sharding control, and should probably be tweaked to obey
+# GTEST_SHARD_INDEX/GTEST_TOTAL_SHARDS like the rest,
+# but they take days and days to run, so they are left
+# out of this script.
+
+if test ! -d chrome
+then
+ echo "Please run from parent directory of chrome and build directories"
+ exit 1
+fi
+
+if test "$1" = ""
+then
+ echo "Usage: shard-all-tests.sh [BUILDTYPE=Release] target [target ...]"
+ echo "Example: shard-all-tests.sh ui_tests"
+ exit 1
+fi
+
+set -x
+set -e
+
+# Regexp to match any valgrind error
+PATTERN="ERROR SUMMARY: [^0]|are definitely|uninitialised|Unhandled exception|\
+Invalid read|Invalid write|Invalid free|Source and desti|Mismatched free|\
+unaddressable byte|vex x86|impossible|Assertion|INTERNAL ERROR|finish writing|OUCH"
+
+BUILDTYPE=Debug
+case "$1" in
+ BUILDTYPE=Debug) BUILDTYPE=Debug ; shift ;;
+ BUILDTYPE=Release) BUILDTYPE=Release ; shift ;;
+ BUILDTYPE=*) echo "unknown build type $1"; exit 1;;
+ *) ;;
+esac
+TESTS="$@"
+
+what_to_build() {
+ echo $TESTS | tr ' ' '\012' | grep -v layout_tests || true
+ echo $TESTS | grep -q layout_tests && echo test_shell || true
+ echo $TESTS | grep -q ui_tests && echo chrome || true
+}
+
+# Wrap xcodebuild to take same arguments as our make, more or less
+xcodemake() {
+ for target in $*
+ do
+ case $target in
+ chrome) xcodebuild -configuration $BUILDTYPE -project chrome/chrome.xcodeproj -target chrome ;;
+ ui_tests) xcodebuild -configuration $BUILDTYPE -project chrome/chrome.xcodeproj -target ui_tests ;;
+ base_unittests) xcodebuild -configuration $BUILDTYPE -project base/base.xcodeproj -target base_unittests ;;
+ net_unittests) xcodebuild -configuration $BUILDTYPE -project net/net.xcodeproj -target net_unittests ;;
+ *) echo "dunno how to build $target yet"; exit 1 ;;
+ esac
+ done
+}
+
+build_tests() {
+ buildtype=$1
+ shift
+
+ OS=`uname`
+ case $OS in
+ Linux)
+ # Lame way to autodetect whether 'make' or 'hammer' is in use
+ if test -d out
+ then
+ make -j4 BUILDTYPE=$1 $@
+ else
+ # fixme: obey buildtype
+ hammer $@
+ fi
+ ;;
+ Darwin)
+ xcodemake $@
+ ;;
+ *) echo "don't know how to build on os $OS"
+ ;;
+ esac
+}
+
+TESTS_BUILDABLE=`what_to_build`
+echo building $TESTS_BUILDABLE
+build_tests $BUILDTYPE $TESTS_BUILDABLE
+
+# Divide each test suite up into 100 shards, as first step
+# in tracking down exact source of errors.
+export GTEST_TOTAL_SHARDS=100
+
+rm -rf *.vlog *.vtmp || true
+
+iter=0
+while test $iter -lt 1000
+do
+ for testname in $TESTS
+ do
+ export GTEST_SHARD_INDEX=0
+ while test $GTEST_SHARD_INDEX -lt $GTEST_TOTAL_SHARDS
+ do
+ i=$GTEST_SHARD_INDEX
+ sh tools/valgrind/chrome_tests.sh -b xcodebuild/$BUILDTYPE -t ${testname} --tool_flags="--nocleanup_on_exit" > ${testname}_$i.vlog 2>&1 || true
+ mv valgrind.tmp ${testname}_$i.vtmp
+ GTEST_SHARD_INDEX=`expr $GTEST_SHARD_INDEX + 1`
+ done
+ done
+
+ # Save any interesting log files from this iteration
+ # Also show interesting lines on stdout, to make tail -f more interesting
+ if egrep "$PATTERN" *.vlog
+ then
+ mkdir -p shard-results/$iter
+ mv `egrep -l "$PATTERN" *.vlog` shard-results/$iter
+ # ideally we'd only save the .vtmp's corresponding to the .vlogs we saved
+ mv *.vtmp shard-results/$iter
+ fi
+
+ rm -rf *.vlog *.vtmp || true
+ iter=`expr $iter + 1`
+done
diff --git a/chromium/tools/valgrind/suppressions.py b/chromium/tools/valgrind/suppressions.py
new file mode 100755
index 00000000000..48955984d2c
--- /dev/null
+++ b/chromium/tools/valgrind/suppressions.py
@@ -0,0 +1,1018 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# suppressions.py
+
+"""Post-process Valgrind suppression matcher.
+
+Suppressions are defined as follows:
+
+# optional one-line comments anywhere in the suppressions file.
+{
+ <Short description of the error>
+ Toolname:Errortype
+ fun:function_name
+ obj:object_filename
+ fun:wildcarded_fun*_name
+ # an ellipsis wildcards zero or more functions in a stack.
+ ...
+ fun:some_other_function_name
+}
+
+If ran from the command line, suppressions.py does a self-test
+of the Suppression class.
+"""
+
+import os
+import re
+import sys
+
+sys.path.insert(0, os.path.join(os.path.dirname(__file__),
+ '..', 'python', 'google'))
+import path_utils
+
+
+ELLIPSIS = '...'
+
+
+def GetSuppressions():
+ suppressions_root = path_utils.ScriptDir()
+ JOIN = os.path.join
+
+ result = {}
+
+ supp_filename = JOIN(suppressions_root, "memcheck", "suppressions.txt")
+ vg_common = ReadSuppressionsFromFile(supp_filename)
+ supp_filename = JOIN(suppressions_root, "tsan", "suppressions.txt")
+ tsan_common = ReadSuppressionsFromFile(supp_filename)
+ result['common_suppressions'] = vg_common + tsan_common
+
+ supp_filename = JOIN(suppressions_root, "memcheck", "suppressions_linux.txt")
+ vg_linux = ReadSuppressionsFromFile(supp_filename)
+ supp_filename = JOIN(suppressions_root, "tsan", "suppressions_linux.txt")
+ tsan_linux = ReadSuppressionsFromFile(supp_filename)
+ result['linux_suppressions'] = vg_linux + tsan_linux
+
+ supp_filename = JOIN(suppressions_root, "memcheck", "suppressions_mac.txt")
+ vg_mac = ReadSuppressionsFromFile(supp_filename)
+ supp_filename = JOIN(suppressions_root, "tsan", "suppressions_mac.txt")
+ tsan_mac = ReadSuppressionsFromFile(supp_filename)
+ result['mac_suppressions'] = vg_mac + tsan_mac
+
+ supp_filename = JOIN(suppressions_root, "tsan", "suppressions_win32.txt")
+ tsan_win = ReadSuppressionsFromFile(supp_filename)
+ result['win_suppressions'] = tsan_win
+
+ supp_filename = JOIN(suppressions_root, "..", "heapcheck", "suppressions.txt")
+ result['heapcheck_suppressions'] = ReadSuppressionsFromFile(supp_filename)
+
+ supp_filename = JOIN(suppressions_root, "drmemory", "suppressions.txt")
+ result['drmem_suppressions'] = ReadSuppressionsFromFile(supp_filename)
+ supp_filename = JOIN(suppressions_root, "drmemory", "suppressions_full.txt")
+ result['drmem_full_suppressions'] = ReadSuppressionsFromFile(supp_filename)
+
+ return result
+
+
+def GlobToRegex(glob_pattern, ignore_case=False):
+ """Translate glob wildcards (*?) into regex syntax. Escape the rest."""
+ regex = ''
+ for char in glob_pattern:
+ if char == '*':
+ regex += '.*'
+ elif char == '?':
+ regex += '.'
+ elif ignore_case and char.isalpha():
+ regex += '[%s%s]' % (char.lower(), char.upper())
+ else:
+ regex += re.escape(char)
+ return ''.join(regex)
+
+
+def StripAndSkipCommentsIterator(lines):
+ """Generator of (line_no, line) pairs that strips comments and whitespace."""
+ for (line_no, line) in enumerate(lines):
+ line = line.strip() # Drop \n
+ if line.startswith('#'):
+ continue # Comments
+ # Skip comment lines, but not empty lines, they indicate the end of a
+ # suppression. Add one to the line number as well, since most editors use
+ # 1-based numberings, and enumerate is 0-based.
+ yield (line_no + 1, line)
+
+
+class Suppression(object):
+ """This class represents a single stack trace suppression.
+
+ Attributes:
+ description: A string representing the error description.
+ type: A string representing the error type, e.g. Memcheck:Leak.
+ stack: The lines comprising the stack trace for the suppression.
+ regex: The actual regex used to match against scraped reports.
+ """
+
+ def __init__(self, description, type, stack, defined_at, regex):
+ """Inits Suppression.
+
+ description, type, stack, regex: same as class attributes
+ defined_at: file:line identifying where the suppression was defined
+ """
+ self.description = description
+ self.type = type
+ self.stack = stack
+ self.defined_at = defined_at
+ self.regex = re.compile(regex, re.MULTILINE)
+
+ def Match(self, suppression_from_report):
+ """Returns bool indicating whether this suppression matches
+ the suppression generated from Valgrind error report.
+
+ We match our suppressions against generated suppressions
+ (not against reports) since they have the same format
+ while the reports are taken from XML, contain filenames,
+ they are demangled, and are generally more difficult to
+ parse.
+
+ Args:
+ suppression_from_report: list of strings (function names).
+ Returns:
+ True if the suppression is not empty and matches the report.
+ """
+ if not self.stack:
+ return False
+ lines = [f.strip() for f in suppression_from_report]
+ return self.regex.match('\n'.join(lines) + '\n') is not None
+
+
+def FilenameToTool(filename):
+ """Return the name of the tool that a file is related to, or None.
+
+ Example mappings:
+ tools/heapcheck/suppressions.txt -> heapcheck
+ tools/valgrind/tsan/suppressions.txt -> tsan
+ tools/valgrind/drmemory/suppressions.txt -> drmemory
+ tools/valgrind/drmemory/suppressions_full.txt -> drmemory
+ tools/valgrind/memcheck/suppressions.txt -> memcheck
+ tools/valgrind/memcheck/suppressions_mac.txt -> memcheck
+ """
+ filename = os.path.abspath(filename)
+ parts = filename.split(os.sep)
+ tool = parts[-2]
+ if tool in ('heapcheck', 'drmemory', 'memcheck', 'tsan'):
+ return tool
+ return None
+
+
+def ReadSuppressionsFromFile(filename):
+ """Read suppressions from the given file and return them as a list"""
+ tool_to_parser = {
+ "drmemory": ReadDrMemorySuppressions,
+ "memcheck": ReadValgrindStyleSuppressions,
+ "tsan": ReadValgrindStyleSuppressions,
+ "heapcheck": ReadValgrindStyleSuppressions,
+ }
+ tool = FilenameToTool(filename)
+ assert tool in tool_to_parser, (
+ "unknown tool %s for filename %s" % (tool, filename))
+ parse_func = tool_to_parser[tool]
+
+ # Consider non-existent files to be empty.
+ if not os.path.exists(filename):
+ return []
+
+ input_file = file(filename, 'r')
+ try:
+ return parse_func(input_file, filename)
+ except SuppressionError:
+ input_file.close()
+ raise
+
+
+class ValgrindStyleSuppression(Suppression):
+ """A suppression using the Valgrind syntax.
+
+ Most tools, even ones that are not Valgrind-based, use this syntax, ie
+ Heapcheck, TSan, etc.
+
+ Attributes:
+ Same as Suppression.
+ """
+
+ def __init__(self, description, type, stack, defined_at):
+ """Creates a suppression using the Memcheck, TSan, and Heapcheck syntax."""
+ regex = '{\n.*\n%s\n' % type
+ for line in stack:
+ if line == ELLIPSIS:
+ regex += '(.*\n)*'
+ else:
+ regex += GlobToRegex(line)
+ regex += '\n'
+ regex += '(.*\n)*'
+ regex += '}'
+
+ # In the recent version of valgrind-variant we've switched
+ # from memcheck's default Addr[1248]/Value[1248]/Cond suppression types
+ # to simply Unaddressable/Uninitialized.
+ # The suppression generator no longer gives us "old" types thus
+ # for the "new-type" suppressions:
+ # * Memcheck:Unaddressable should also match Addr* reports,
+ # * Memcheck:Uninitialized should also match Cond and Value reports,
+ #
+ # We also want to support legacy suppressions (e.g. copied from
+ # upstream bugs etc), so:
+ # * Memcheck:Addr[1248] suppressions should match Unaddressable reports,
+ # * Memcheck:Cond and Memcheck:Value[1248] should match Uninitialized.
+ # Please note the latest two rules only apply to the
+ # tools/valgrind/waterfall.sh suppression matcher and the real
+ # valgrind-variant Memcheck will not suppress
+ # e.g. Addr1 printed as Unaddressable with Addr4 suppression.
+ # Be careful to check the access size while copying legacy suppressions!
+ for sz in [1, 2, 4, 8]:
+ regex = regex.replace("\nMemcheck:Addr%d\n" % sz,
+ "\nMemcheck:(Addr%d|Unaddressable)\n" % sz)
+ regex = regex.replace("\nMemcheck:Value%d\n" % sz,
+ "\nMemcheck:(Value%d|Uninitialized)\n" % sz)
+ regex = regex.replace("\nMemcheck:Cond\n",
+ "\nMemcheck:(Cond|Uninitialized)\n")
+ regex = regex.replace("\nMemcheck:Unaddressable\n",
+ "\nMemcheck:(Addr.|Unaddressable)\n")
+ regex = regex.replace("\nMemcheck:Uninitialized\n",
+ "\nMemcheck:(Cond|Value.|Uninitialized)\n")
+
+ return super(ValgrindStyleSuppression, self).__init__(
+ description, type, stack, defined_at, regex)
+
+ def __str__(self):
+ """Stringify."""
+ lines = [self.description, self.type] + self.stack
+ return "{\n %s\n}\n" % "\n ".join(lines)
+
+
+class SuppressionError(Exception):
+ def __init__(self, message, happened_at):
+ self._message = message
+ self._happened_at = happened_at
+
+ def __str__(self):
+ return 'Error reading suppressions at %s!\n%s' % (
+ self._happened_at, self._message)
+
+
+def ReadValgrindStyleSuppressions(lines, supp_descriptor):
+ """Given a list of lines, returns a list of suppressions.
+
+ Args:
+ lines: a list of lines containing suppressions.
+ supp_descriptor: should typically be a filename.
+ Used only when printing errors.
+ """
+ result = []
+ cur_descr = ''
+ cur_type = ''
+ cur_stack = []
+ in_suppression = False
+ nline = 0
+ for line in lines:
+ nline += 1
+ line = line.strip()
+ if line.startswith('#'):
+ continue
+ if not in_suppression:
+ if not line:
+ # empty lines between suppressions
+ pass
+ elif line.startswith('{'):
+ in_suppression = True
+ pass
+ else:
+ raise SuppressionError('Expected: "{"',
+ "%s:%d" % (supp_descriptor, nline))
+ elif line.startswith('}'):
+ result.append(
+ ValgrindStyleSuppression(cur_descr, cur_type, cur_stack,
+ "%s:%d" % (supp_descriptor, nline)))
+ cur_descr = ''
+ cur_type = ''
+ cur_stack = []
+ in_suppression = False
+ elif not cur_descr:
+ cur_descr = line
+ continue
+ elif not cur_type:
+ if (not line.startswith("Memcheck:") and
+ not line.startswith("ThreadSanitizer:") and
+ (line != "Heapcheck:Leak")):
+ raise SuppressionError(
+ 'Expected "Memcheck:TYPE", "ThreadSanitizer:TYPE" '
+ 'or "Heapcheck:Leak", got "%s"' % line,
+ "%s:%d" % (supp_descriptor, nline))
+ supp_type = line.split(':')[1]
+ if not supp_type in ["Addr1", "Addr2", "Addr4", "Addr8",
+ "Cond", "Free", "Jump", "Leak", "Overlap", "Param",
+ "Value1", "Value2", "Value4", "Value8",
+ "Race", "UnlockNonLocked", "InvalidLock",
+ "Unaddressable", "Uninitialized"]:
+ raise SuppressionError('Unknown suppression type "%s"' % supp_type,
+ "%s:%d" % (supp_descriptor, nline))
+ cur_type = line
+ continue
+ elif re.match("^fun:.*|^obj:.*|^\.\.\.$", line):
+ cur_stack.append(line.strip())
+ elif len(cur_stack) == 0 and cur_type == "Memcheck:Param":
+ cur_stack.append(line.strip())
+ else:
+ raise SuppressionError(
+ '"fun:function_name" or "obj:object_file" or "..." expected',
+ "%s:%d" % (supp_descriptor, nline))
+ return result
+
+
+def PresubmitCheckSuppressions(supps):
+ """Check a list of suppressions and return a list of SuppressionErrors.
+
+ Mostly useful for separating the checking logic from the Presubmit API for
+ testing.
+ """
+ known_supp_names = {} # Key: name, Value: suppression.
+ errors = []
+ for s in supps:
+ if re.search("<.*suppression.name.here>", s.description):
+ # Suppression name line is
+ # <insert_a_suppression_name_here> for Memcheck,
+ # <Put your suppression name here> for TSan,
+ # name=<insert_a_suppression_name_here> for DrMemory
+ errors.append(
+ SuppressionError(
+ "You've forgotten to put a suppression name like bug_XXX",
+ s.defined_at))
+ continue
+
+ if s.description in known_supp_names:
+ errors.append(
+ SuppressionError(
+ 'Suppression named "%s" is defined more than once, '
+ 'see %s' % (s.description,
+ known_supp_names[s.description].defined_at),
+ s.defined_at))
+ else:
+ known_supp_names[s.description] = s
+ return errors
+
+
+def PresubmitCheck(input_api, output_api):
+ """A helper function useful in PRESUBMIT.py
+ Returns a list of errors or [].
+ """
+ sup_regex = re.compile('suppressions.*\.txt$')
+ filenames = [f.AbsoluteLocalPath() for f in input_api.AffectedFiles()
+ if sup_regex.search(f.LocalPath())]
+
+ errors = []
+
+ # TODO(timurrrr): warn on putting suppressions into a wrong file,
+ # e.g. TSan suppression in a memcheck file.
+
+ for f in filenames:
+ try:
+ supps = ReadSuppressionsFromFile(f)
+ errors.extend(PresubmitCheckSuppressions(supps))
+ except SuppressionError as e:
+ errors.append(e)
+
+ return [output_api.PresubmitError(str(e)) for e in errors]
+
+
+class DrMemorySuppression(Suppression):
+ """A suppression using the DrMemory syntax.
+
+ Attributes:
+ instr: The instruction to match.
+ Rest inherited from Suppression.
+ """
+
+ def __init__(self, name, report_type, instr, stack, defined_at):
+ """Constructor."""
+ self.instr = instr
+
+ # Construct the regex.
+ regex = '{\n'
+ if report_type == 'LEAK':
+ regex += '(POSSIBLE )?LEAK'
+ else:
+ regex += report_type
+ regex += '\nname=.*\n'
+
+ # TODO(rnk): Implement http://crbug.com/107416#c5 .
+ # drmemory_analyze.py doesn't generate suppressions with an instruction in
+ # them, so these suppressions will always fail to match. We should override
+ # Match to fetch the instruction from the report and try to match against
+ # that.
+ if instr:
+ regex += 'instruction=%s\n' % GlobToRegex(instr)
+
+ for line in stack:
+ if line == ELLIPSIS:
+ regex += '(.*\n)*'
+ elif '!' in line:
+ (mod, func) = line.split('!')
+ if func == ELLIPSIS: # mod!ellipsis frame
+ regex += '(%s\!.*\n)+' % GlobToRegex(mod, ignore_case=True)
+ else: # mod!func frame
+ # Ignore case for the module match, but not the function match.
+ regex += '%s\!%s\n' % (GlobToRegex(mod, ignore_case=True),
+ GlobToRegex(func, ignore_case=False))
+ else:
+ regex += GlobToRegex(line)
+ regex += '\n'
+ regex += '(.*\n)*' # Match anything left in the stack.
+ regex += '}'
+ return super(DrMemorySuppression, self).__init__(name, report_type, stack,
+ defined_at, regex)
+
+ def __str__(self):
+ """Stringify."""
+ text = self.type + "\n"
+ if self.description:
+ text += "name=%s\n" % self.description
+ if self.instr:
+ text += "instruction=%s\n" % self.instr
+ text += "\n".join(self.stack)
+ text += "\n"
+ return text
+
+
+# Possible DrMemory error report types. Keep consistent with suppress_name
+# array in drmemory/drmemory/report.c.
+DRMEMORY_ERROR_TYPES = [
+ 'UNADDRESSABLE ACCESS',
+ 'UNINITIALIZED READ',
+ 'INVALID HEAP ARGUMENT',
+ 'GDI USAGE ERROR',
+ 'HANDLE LEAK',
+ 'LEAK',
+ 'POSSIBLE LEAK',
+ 'WARNING',
+ ]
+
+
+# Regexes to match valid drmemory frames.
+DRMEMORY_FRAME_PATTERNS = [
+ re.compile(r"^.*\!.*$"), # mod!func
+ re.compile(r"^.*!\.\.\.$"), # mod!ellipsis
+ re.compile(r"^\<.*\+0x.*\>$"), # <mod+0xoffs>
+ re.compile(r"^\<not in a module\>$"),
+ re.compile(r"^system call .*$"),
+ re.compile(r"^\*$"), # wildcard
+ re.compile(r"^\.\.\.$"), # ellipsis
+ ]
+
+
+def ReadDrMemorySuppressions(lines, supp_descriptor):
+ """Given a list of lines, returns a list of DrMemory suppressions.
+
+ Args:
+ lines: a list of lines containing suppressions.
+ supp_descriptor: should typically be a filename.
+ Used only when parsing errors happen.
+ """
+ lines = StripAndSkipCommentsIterator(lines)
+ suppressions = []
+ for (line_no, line) in lines:
+ if not line:
+ continue
+ if line not in DRMEMORY_ERROR_TYPES:
+ raise SuppressionError('Expected a DrMemory error type, '
+ 'found %r instead\n Valid error types: %s' %
+ (line, ' '.join(DRMEMORY_ERROR_TYPES)),
+ "%s:%d" % (supp_descriptor, line_no))
+
+ # Suppression starts here.
+ report_type = line
+ name = ''
+ instr = None
+ stack = []
+ defined_at = "%s:%d" % (supp_descriptor, line_no)
+ found_stack = False
+ for (line_no, line) in lines:
+ if not found_stack and line.startswith('name='):
+ name = line.replace('name=', '')
+ elif not found_stack and line.startswith('instruction='):
+ instr = line.replace('instruction=', '')
+ else:
+ # Unrecognized prefix indicates start of stack trace.
+ found_stack = True
+ if not line:
+ # Blank line means end of suppression.
+ break
+ if not any([regex.match(line) for regex in DRMEMORY_FRAME_PATTERNS]):
+ raise SuppressionError(
+ ('Unexpected stack frame pattern at line %d\n' +
+ 'Frames should be one of the following:\n' +
+ ' module!function\n' +
+ ' module!...\n' +
+ ' <module+0xhexoffset>\n' +
+ ' <not in a module>\n' +
+ ' system call Name\n' +
+ ' *\n' +
+ ' ...\n') % line_no, defined_at)
+ stack.append(line)
+
+ if len(stack) == 0: # In case we hit EOF or blank without any stack frames.
+ raise SuppressionError('Suppression "%s" has no stack frames, ends at %d'
+ % (name, line_no), defined_at)
+ if stack[-1] == ELLIPSIS:
+ raise SuppressionError('Suppression "%s" ends in an ellipsis on line %d' %
+ (name, line_no), defined_at)
+
+ suppressions.append(
+ DrMemorySuppression(name, report_type, instr, stack, defined_at))
+
+ return suppressions
+
+
+def ParseSuppressionOfType(lines, supp_descriptor, def_line_no, report_type):
+ """Parse the suppression starting on this line.
+
+ Suppressions start with a type, have an optional name and instruction, and a
+ stack trace that ends in a blank line.
+ """
+
+
+
+def TestStack(stack, positive, negative, suppression_parser=None):
+ """A helper function for SelfTest() that checks a single stack.
+
+ Args:
+ stack: the stack to match the suppressions.
+ positive: the list of suppressions that must match the given stack.
+ negative: the list of suppressions that should not match.
+ suppression_parser: optional arg for the suppression parser, default is
+ ReadValgrindStyleSuppressions.
+ """
+ if not suppression_parser:
+ suppression_parser = ReadValgrindStyleSuppressions
+ for supp in positive:
+ parsed = suppression_parser(supp.split("\n"), "positive_suppression")
+ assert parsed[0].Match(stack.split("\n")), (
+ "Suppression:\n%s\ndidn't match stack:\n%s" % (supp, stack))
+ for supp in negative:
+ parsed = suppression_parser(supp.split("\n"), "negative_suppression")
+ assert not parsed[0].Match(stack.split("\n")), (
+ "Suppression:\n%s\ndid match stack:\n%s" % (supp, stack))
+
+
+def TestFailPresubmit(supp_text, error_text, suppression_parser=None):
+ """A helper function for SelfTest() that verifies a presubmit check fires.
+
+ Args:
+ supp_text: suppression text to parse.
+ error_text: text of the presubmit error we expect to find.
+ suppression_parser: optional arg for the suppression parser, default is
+ ReadValgrindStyleSuppressions.
+ """
+ if not suppression_parser:
+ suppression_parser = ReadValgrindStyleSuppressions
+ try:
+ supps = suppression_parser(supp_text.split("\n"), "<presubmit suppression>")
+ except SuppressionError, e:
+ # If parsing raised an exception, match the error text here.
+ assert error_text in str(e), (
+ "presubmit text %r not in SuppressionError:\n%r" %
+ (error_text, str(e)))
+ else:
+ # Otherwise, run the presubmit checks over the supps. We expect a single
+ # error that has text matching error_text.
+ errors = PresubmitCheckSuppressions(supps)
+ assert len(errors) == 1, (
+ "expected exactly one presubmit error, got:\n%s" % errors)
+ assert error_text in str(errors[0]), (
+ "presubmit text %r not in SuppressionError:\n%r" %
+ (error_text, str(errors[0])))
+
+
+def SelfTest():
+ """Tests the Suppression.Match() capabilities."""
+
+ test_memcheck_stack_1 = """{
+ test
+ Memcheck:Leak
+ fun:absolutly
+ fun:brilliant
+ obj:condition
+ fun:detection
+ fun:expression
+ }"""
+
+ test_memcheck_stack_2 = """{
+ test
+ Memcheck:Uninitialized
+ fun:absolutly
+ fun:brilliant
+ obj:condition
+ fun:detection
+ fun:expression
+ }"""
+
+ test_memcheck_stack_3 = """{
+ test
+ Memcheck:Unaddressable
+ fun:absolutly
+ fun:brilliant
+ obj:condition
+ fun:detection
+ fun:expression
+ }"""
+
+ test_memcheck_stack_4 = """{
+ test
+ Memcheck:Addr4
+ fun:absolutly
+ fun:brilliant
+ obj:condition
+ fun:detection
+ fun:expression
+ }"""
+
+ test_heapcheck_stack = """{
+ test
+ Heapcheck:Leak
+ fun:absolutly
+ fun:brilliant
+ obj:condition
+ fun:detection
+ fun:expression
+ }"""
+
+ test_tsan_stack = """{
+ test
+ ThreadSanitizer:Race
+ fun:absolutly
+ fun:brilliant
+ obj:condition
+ fun:detection
+ fun:expression
+ }"""
+
+
+ positive_memcheck_suppressions_1 = [
+ "{\nzzz\nMemcheck:Leak\nfun:absolutly\n}",
+ "{\nzzz\nMemcheck:Leak\nfun:ab*ly\n}",
+ "{\nzzz\nMemcheck:Leak\nfun:absolutly\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Leak\n...\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Leak\n...\nfun:detection\n}",
+ "{\nzzz\nMemcheck:Leak\nfun:absolutly\n...\nfun:detection\n}",
+ "{\nzzz\nMemcheck:Leak\nfun:ab*ly\n...\nfun:detection\n}",
+ "{\nzzz\nMemcheck:Leak\n...\nobj:condition\n}",
+ "{\nzzz\nMemcheck:Leak\n...\nobj:condition\nfun:detection\n}",
+ "{\nzzz\nMemcheck:Leak\n...\nfun:brilliant\nobj:condition\n}",
+ ]
+
+ positive_memcheck_suppressions_2 = [
+ "{\nzzz\nMemcheck:Uninitialized\nfun:absolutly\n}",
+ "{\nzzz\nMemcheck:Uninitialized\nfun:ab*ly\n}",
+ "{\nzzz\nMemcheck:Uninitialized\nfun:absolutly\nfun:brilliant\n}",
+ # Legacy suppression types
+ "{\nzzz\nMemcheck:Value1\n...\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Cond\n...\nfun:detection\n}",
+ "{\nzzz\nMemcheck:Value8\nfun:absolutly\nfun:brilliant\n}",
+ ]
+
+ positive_memcheck_suppressions_3 = [
+ "{\nzzz\nMemcheck:Unaddressable\nfun:absolutly\n}",
+ "{\nzzz\nMemcheck:Unaddressable\nfun:absolutly\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Unaddressable\nfun:absolutly\nfun:brilliant\n}",
+ # Legacy suppression types
+ "{\nzzz\nMemcheck:Addr1\n...\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Addr8\n...\nfun:detection\n}",
+ ]
+
+ positive_memcheck_suppressions_4 = [
+ "{\nzzz\nMemcheck:Addr4\nfun:absolutly\n}",
+ "{\nzzz\nMemcheck:Unaddressable\nfun:absolutly\n}",
+ "{\nzzz\nMemcheck:Addr4\nfun:absolutly\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Unaddressable\n...\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Addr4\n...\nfun:detection\n}",
+ ]
+
+ positive_heapcheck_suppressions = [
+ "{\nzzz\nHeapcheck:Leak\n...\nobj:condition\n}",
+ "{\nzzz\nHeapcheck:Leak\nfun:absolutly\n}",
+ ]
+
+ positive_tsan_suppressions = [
+ "{\nzzz\nThreadSanitizer:Race\n...\nobj:condition\n}",
+ "{\nzzz\nThreadSanitizer:Race\nfun:absolutly\n}",
+ ]
+
+ negative_memcheck_suppressions_1 = [
+ "{\nzzz\nMemcheck:Leak\nfun:abnormal\n}",
+ "{\nzzz\nMemcheck:Leak\nfun:ab*liant\n}",
+ "{\nzzz\nMemcheck:Leak\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Leak\nobj:condition\n}",
+ "{\nzzz\nMemcheck:Addr8\nfun:brilliant\n}",
+ ]
+
+ negative_memcheck_suppressions_2 = [
+ "{\nzzz\nMemcheck:Cond\nfun:abnormal\n}",
+ "{\nzzz\nMemcheck:Value2\nfun:abnormal\n}",
+ "{\nzzz\nMemcheck:Uninitialized\nfun:ab*liant\n}",
+ "{\nzzz\nMemcheck:Value4\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Leak\nobj:condition\n}",
+ "{\nzzz\nMemcheck:Addr8\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Unaddressable\nfun:brilliant\n}",
+ ]
+
+ negative_memcheck_suppressions_3 = [
+ "{\nzzz\nMemcheck:Addr1\nfun:abnormal\n}",
+ "{\nzzz\nMemcheck:Uninitialized\nfun:absolutly\n}",
+ "{\nzzz\nMemcheck:Addr2\nfun:ab*liant\n}",
+ "{\nzzz\nMemcheck:Value4\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Leak\nobj:condition\n}",
+ "{\nzzz\nMemcheck:Addr8\nfun:brilliant\n}",
+ ]
+
+ negative_memcheck_suppressions_4 = [
+ "{\nzzz\nMemcheck:Addr1\nfun:abnormal\n}",
+ "{\nzzz\nMemcheck:Addr4\nfun:abnormal\n}",
+ "{\nzzz\nMemcheck:Unaddressable\nfun:abnormal\n}",
+ "{\nzzz\nMemcheck:Addr1\nfun:absolutly\n}",
+ "{\nzzz\nMemcheck:Addr2\nfun:ab*liant\n}",
+ "{\nzzz\nMemcheck:Value4\nfun:brilliant\n}",
+ "{\nzzz\nMemcheck:Leak\nobj:condition\n}",
+ "{\nzzz\nMemcheck:Addr8\nfun:brilliant\n}",
+ ]
+
+ negative_heapcheck_suppressions = [
+ "{\nzzz\nMemcheck:Leak\nfun:absolutly\n}",
+ "{\nzzz\nHeapcheck:Leak\nfun:brilliant\n}",
+ ]
+
+ negative_tsan_suppressions = [
+ "{\nzzz\nThreadSanitizer:Leak\nfun:absolutly\n}",
+ "{\nzzz\nThreadSanitizer:Race\nfun:brilliant\n}",
+ ]
+
+ TestStack(test_memcheck_stack_1,
+ positive_memcheck_suppressions_1,
+ negative_memcheck_suppressions_1)
+ TestStack(test_memcheck_stack_2,
+ positive_memcheck_suppressions_2,
+ negative_memcheck_suppressions_2)
+ TestStack(test_memcheck_stack_3,
+ positive_memcheck_suppressions_3,
+ negative_memcheck_suppressions_3)
+ TestStack(test_memcheck_stack_4,
+ positive_memcheck_suppressions_4,
+ negative_memcheck_suppressions_4)
+ TestStack(test_heapcheck_stack, positive_heapcheck_suppressions,
+ negative_heapcheck_suppressions)
+ TestStack(test_tsan_stack, positive_tsan_suppressions,
+ negative_tsan_suppressions)
+
+ # TODO(timurrrr): add TestFailPresubmit tests.
+
+ ### DrMemory self tests.
+
+ # http://crbug.com/96010 suppression.
+ stack_96010 = """{
+ UNADDRESSABLE ACCESS
+ name=<insert_a_suppression_name_here>
+ *!TestingProfile::FinishInit
+ *!TestingProfile::TestingProfile
+ *!BrowserAboutHandlerTest_WillHandleBrowserAboutURL_Test::TestBody
+ *!testing::Test::Run
+ }"""
+
+ suppress_96010 = [
+ "UNADDRESSABLE ACCESS\nname=zzz\n...\n*!testing::Test::Run\n",
+ ("UNADDRESSABLE ACCESS\nname=zzz\n...\n" +
+ "*!BrowserAboutHandlerTest_WillHandleBrowserAboutURL_Test::TestBody\n"),
+ "UNADDRESSABLE ACCESS\nname=zzz\n...\n*!BrowserAboutHandlerTest*\n",
+ "UNADDRESSABLE ACCESS\nname=zzz\n*!TestingProfile::FinishInit\n",
+ # No name should be needed
+ "UNADDRESSABLE ACCESS\n*!TestingProfile::FinishInit\n",
+ # Whole trace
+ ("UNADDRESSABLE ACCESS\n" +
+ "*!TestingProfile::FinishInit\n" +
+ "*!TestingProfile::TestingProfile\n" +
+ "*!BrowserAboutHandlerTest_WillHandleBrowserAboutURL_Test::TestBody\n" +
+ "*!testing::Test::Run\n"),
+ ]
+
+ negative_96010 = [
+ # Wrong type
+ "UNINITIALIZED READ\nname=zzz\n*!TestingProfile::FinishInit\n",
+ # No ellipsis
+ "UNADDRESSABLE ACCESS\nname=zzz\n*!BrowserAboutHandlerTest*\n",
+ ]
+
+ TestStack(stack_96010, suppress_96010, negative_96010,
+ suppression_parser=ReadDrMemorySuppressions)
+
+ # Invalid heap arg
+ stack_invalid = """{
+ INVALID HEAP ARGUMENT
+ name=asdf
+ *!foo
+ }"""
+ suppress_invalid = [
+ "INVALID HEAP ARGUMENT\n*!foo\n",
+ ]
+ negative_invalid = [
+ "UNADDRESSABLE ACCESS\n*!foo\n",
+ ]
+
+ TestStack(stack_invalid, suppress_invalid, negative_invalid,
+ suppression_parser=ReadDrMemorySuppressions)
+
+ # Suppress only ntdll
+ stack_in_ntdll = """{
+ UNADDRESSABLE ACCESS
+ name=<insert_a_suppression_name_here>
+ ntdll.dll!RtlTryEnterCriticalSection
+ }"""
+ stack_not_ntdll = """{
+ UNADDRESSABLE ACCESS
+ name=<insert_a_suppression_name_here>
+ notntdll.dll!RtlTryEnterCriticalSection
+ }"""
+
+ suppress_in_ntdll = [
+ "UNADDRESSABLE ACCESS\nntdll.dll!RtlTryEnterCriticalSection\n",
+ ]
+ suppress_in_any = [
+ "UNADDRESSABLE ACCESS\n*!RtlTryEnterCriticalSection\n",
+ ]
+
+ TestStack(stack_in_ntdll, suppress_in_ntdll + suppress_in_any, [],
+ suppression_parser=ReadDrMemorySuppressions)
+ # Make sure we don't wildcard away the "not" part and match ntdll.dll by
+ # accident.
+ TestStack(stack_not_ntdll, suppress_in_any, suppress_in_ntdll,
+ suppression_parser=ReadDrMemorySuppressions)
+
+ # Suppress a POSSIBLE LEAK with LEAK.
+ stack_foo_possible = """{
+ POSSIBLE LEAK
+ name=foo possible
+ *!foo
+ }"""
+ suppress_foo_possible = [ "POSSIBLE LEAK\n*!foo\n" ]
+ suppress_foo_leak = [ "LEAK\n*!foo\n" ]
+ TestStack(stack_foo_possible, suppress_foo_possible + suppress_foo_leak, [],
+ suppression_parser=ReadDrMemorySuppressions)
+
+ # Don't suppress LEAK with POSSIBLE LEAK.
+ stack_foo_leak = """{
+ LEAK
+ name=foo leak
+ *!foo
+ }"""
+ TestStack(stack_foo_leak, suppress_foo_leak, suppress_foo_possible,
+ suppression_parser=ReadDrMemorySuppressions)
+
+ # Test case insensitivity of module names.
+ stack_user32_mixed_case = """{
+ LEAK
+ name=<insert>
+ USER32.dll!foo
+ user32.DLL!bar
+ user32.dll!baz
+ }"""
+ suppress_user32 = [ # Module name case doesn't matter.
+ "LEAK\nuser32.dll!foo\nuser32.dll!bar\nuser32.dll!baz\n",
+ "LEAK\nUSER32.DLL!foo\nUSER32.DLL!bar\nUSER32.DLL!baz\n",
+ ]
+ no_suppress_user32 = [ # Function name case matters.
+ "LEAK\nuser32.dll!FOO\nuser32.dll!BAR\nuser32.dll!BAZ\n",
+ "LEAK\nUSER32.DLL!FOO\nUSER32.DLL!BAR\nUSER32.DLL!BAZ\n",
+ ]
+ TestStack(stack_user32_mixed_case, suppress_user32, no_suppress_user32,
+ suppression_parser=ReadDrMemorySuppressions)
+
+ # Test mod!... frames.
+ stack_kernel32_through_ntdll = """{
+ LEAK
+ name=<insert>
+ kernel32.dll!foo
+ KERNEL32.dll!bar
+ kernel32.DLL!baz
+ ntdll.dll!quux
+ }"""
+ suppress_mod_ellipsis = [
+ "LEAK\nkernel32.dll!...\nntdll.dll!quux\n",
+ "LEAK\nKERNEL32.DLL!...\nntdll.dll!quux\n",
+ ]
+ no_suppress_mod_ellipsis = [
+ # Need one or more matching frames, not zero, unlike regular ellipsis.
+ "LEAK\nuser32.dll!...\nkernel32.dll!...\nntdll.dll!quux\n",
+ ]
+ TestStack(stack_kernel32_through_ntdll, suppress_mod_ellipsis,
+ no_suppress_mod_ellipsis,
+ suppression_parser=ReadDrMemorySuppressions)
+
+ # Test that the presubmit checks work.
+ forgot_to_name = """
+ UNADDRESSABLE ACCESS
+ name=<insert_a_suppression_name_here>
+ ntdll.dll!RtlTryEnterCriticalSection
+ """
+ TestFailPresubmit(forgot_to_name, 'forgotten to put a suppression',
+ suppression_parser=ReadDrMemorySuppressions)
+
+ named_twice = """
+ UNADDRESSABLE ACCESS
+ name=http://crbug.com/1234
+ *!foo
+
+ UNADDRESSABLE ACCESS
+ name=http://crbug.com/1234
+ *!bar
+ """
+ TestFailPresubmit(named_twice, 'defined more than once',
+ suppression_parser=ReadDrMemorySuppressions)
+
+ forgot_stack = """
+ UNADDRESSABLE ACCESS
+ name=http://crbug.com/1234
+ """
+ TestFailPresubmit(forgot_stack, 'has no stack frames',
+ suppression_parser=ReadDrMemorySuppressions)
+
+ ends_in_ellipsis = """
+ UNADDRESSABLE ACCESS
+ name=http://crbug.com/1234
+ ntdll.dll!RtlTryEnterCriticalSection
+ ...
+ """
+ TestFailPresubmit(ends_in_ellipsis, 'ends in an ellipsis',
+ suppression_parser=ReadDrMemorySuppressions)
+
+ bad_stack_frame = """
+ UNADDRESSABLE ACCESS
+ name=http://crbug.com/1234
+ fun:memcheck_style_frame
+ """
+ TestFailPresubmit(bad_stack_frame, 'Unexpected stack frame pattern',
+ suppression_parser=ReadDrMemorySuppressions)
+
+ # Test FilenameToTool.
+ filenames_to_tools = {
+ "tools/heapcheck/suppressions.txt": "heapcheck",
+ "tools/valgrind/tsan/suppressions.txt": "tsan",
+ "tools/valgrind/drmemory/suppressions.txt": "drmemory",
+ "tools/valgrind/drmemory/suppressions_full.txt": "drmemory",
+ "tools/valgrind/memcheck/suppressions.txt": "memcheck",
+ "tools/valgrind/memcheck/suppressions_mac.txt": "memcheck",
+ "asdf/tools/valgrind/memcheck/suppressions_mac.txt": "memcheck",
+ "foo/bar/baz/tools/valgrind/memcheck/suppressions_mac.txt": "memcheck",
+ "foo/bar/baz/tools/valgrind/suppressions.txt": None,
+ "tools/valgrind/suppressions.txt": None,
+ }
+ for (filename, expected_tool) in filenames_to_tools.items():
+ filename.replace('/', os.sep) # Make the path look native.
+ tool = FilenameToTool(filename)
+ assert tool == expected_tool, (
+ "failed to get expected tool for filename %r, expected %s, got %s" %
+ (filename, expected_tool, tool))
+
+ # Test ValgrindStyleSuppression.__str__.
+ supp = ValgrindStyleSuppression("http://crbug.com/1234", "Memcheck:Leak",
+ ["...", "fun:foo"], "supp.txt:1")
+ # Intentional 3-space indent. =/
+ supp_str = ("{\n"
+ " http://crbug.com/1234\n"
+ " Memcheck:Leak\n"
+ " ...\n"
+ " fun:foo\n"
+ "}\n")
+ assert str(supp) == supp_str, (
+ "str(supp) != supp_str:\nleft: %s\nright: %s" % (str(supp), supp_str))
+
+ # Test DrMemorySuppression.__str__.
+ supp = DrMemorySuppression(
+ "http://crbug.com/1234", "LEAK", None, ["...", "*!foo"], "supp.txt:1")
+ supp_str = ("LEAK\n"
+ "name=http://crbug.com/1234\n"
+ "...\n"
+ "*!foo\n")
+ assert str(supp) == supp_str, (
+ "str(supp) != supp_str:\nleft: %s\nright: %s" % (str(supp), supp_str))
+
+ supp = DrMemorySuppression(
+ "http://crbug.com/1234", "UNINITIALIZED READ", "test 0x08(%eax) $0x01",
+ ["ntdll.dll!*", "*!foo"], "supp.txt:1")
+ supp_str = ("UNINITIALIZED READ\n"
+ "name=http://crbug.com/1234\n"
+ "instruction=test 0x08(%eax) $0x01\n"
+ "ntdll.dll!*\n"
+ "*!foo\n")
+ assert str(supp) == supp_str, (
+ "str(supp) != supp_str:\nleft: %s\nright: %s" % (str(supp), supp_str))
+
+
+if __name__ == '__main__':
+ SelfTest()
+ print 'PASS'
diff --git a/chromium/tools/valgrind/test_suppressions.py b/chromium/tools/valgrind/test_suppressions.py
new file mode 100755
index 00000000000..8c0900d5214
--- /dev/null
+++ b/chromium/tools/valgrind/test_suppressions.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+from collections import defaultdict
+import os
+import re
+import subprocess
+import sys
+
+import suppressions
+
+
+def ReadReportsFromFile(filename):
+ """ Returns a list of (report_hash, report) and the URL of the report on the
+ waterfall.
+ """
+ input_file = file(filename, 'r')
+ # reports is a list of (error hash, report) pairs.
+ reports = []
+ in_suppression = False
+ cur_supp = []
+ # This stores the last error hash found while reading the file.
+ last_hash = ""
+ for line in input_file:
+ line = line.strip()
+ line = line.replace("</span><span class=\"stdout\">", "")
+ line = line.replace("</span><span class=\"stderr\">", "")
+ line = line.replace("&lt;", "<")
+ line = line.replace("&gt;", ">")
+ if in_suppression:
+ if line == "}":
+ cur_supp += ["}"]
+ reports += [[last_hash, "\n".join(cur_supp)]]
+ in_suppression = False
+ cur_supp = []
+ last_hash = ""
+ else:
+ cur_supp += [" "*3 + line]
+ elif line == "{":
+ in_suppression = True
+ cur_supp = ["{"]
+ elif line.find("Suppression (error hash=#") == 0:
+ last_hash = line[25:41]
+ # The line at the end of the file is assumed to store the URL of the report.
+ return reports,line
+
+def Demangle(names):
+ """ Demangle a list of C++ symbols, return a list of human-readable symbols.
+ """
+ args = ['c++filt', '-n']
+ args.extend(names)
+ pipe = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ stdout, _ = pipe.communicate()
+ demangled = stdout.split("\n")
+
+ # Each line ends with a newline, so the final entry of the split output
+ # will always be ''.
+ assert len(demangled) == len(names) + 1
+ return demangled[:-1]
+
+def GetSymbolsFromReport(report):
+ """Extract all symbols from a suppression report."""
+ symbols = []
+ prefix = "fun:"
+ prefix_len = len(prefix)
+ for line in report.splitlines():
+ index = line.find(prefix)
+ if index != -1:
+ symbols.append(line[index + prefix_len:])
+ return symbols
+
+def PrintTopSymbols(symbol_reports, top_count):
+ """Print the |top_count| symbols with the most occurrences."""
+ boring_symbols=['malloc', '_Znw*', 'TestBody']
+ sorted_reports = sorted(filter(lambda x:x[0] not in boring_symbols,
+ symbol_reports.iteritems()),
+ key=lambda x:len(x[1]), reverse=True)
+ symbols = symbol_reports.keys()
+ demangled = Demangle(symbols)
+ assert len(demangled) == len(symbols)
+ symboltable = dict(zip(symbols, demangled))
+
+ print "\n"
+ print "Top %d symbols" % top_count
+ for (symbol, suppressions) in sorted_reports[:top_count]:
+ print "%4d occurrences : %s" % (len(suppressions), symboltable[symbol])
+
+def main(argv):
+ supp = suppressions.GetSuppressions()
+
+ # all_reports is a map {report: list of urls containing this report}
+ all_reports = defaultdict(list)
+ report_hashes = {}
+ symbol_reports = defaultdict(list)
+
+ # Create argument parser.
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--top-symbols', type=int, default=0,
+ help='Print a list of the top <n> symbols')
+ parser.add_argument('--symbol-filter', action='append',
+ help='Filter out all suppressions not containing the specified symbol(s). '
+ 'Matches against the mangled names')
+
+ parser.add_argument('reports', metavar='report file', nargs='+',
+ help='List of report files')
+ args = parser.parse_args(argv)
+
+ for f in args.reports:
+ f_reports, url = ReadReportsFromFile(f)
+ for (hash, report) in f_reports:
+ all_reports[report] += [url]
+ report_hashes[report] = hash
+
+ reports_count = 0
+ for r in all_reports:
+ cur_supp = supp['common_suppressions']
+ if all([re.search("%20Mac%20|mac_valgrind", url)
+ for url in all_reports[r]]):
+ # Include mac suppressions if the report is only present on Mac
+ cur_supp += supp['mac_suppressions']
+ elif all([re.search("Windows%20", url) for url in all_reports[r]]):
+ # Include win32 suppressions if the report is only present on Windows
+ cur_supp += supp['win_suppressions']
+ elif all([re.search("Linux%20", url) for url in all_reports[r]]):
+ cur_supp += supp['linux_suppressions']
+ elif all([re.search("%20Heapcheck", url)
+ for url in all_reports[r]]):
+ cur_supp += supp['heapcheck_suppressions']
+ if all(["DrMemory" in url for url in all_reports[r]]):
+ cur_supp += supp['drmem_suppressions']
+ if all(["DrMemory%20full" in url for url in all_reports[r]]):
+ cur_supp += supp['drmem_full_suppressions']
+
+ # Test if this report is already suppressed
+ skip = False
+ for s in cur_supp:
+ if s.Match(r.split("\n")):
+ skip = True
+ break
+
+ # Skip reports if none of the symbols are in the report.
+ if args.symbol_filter and all(not s in r for s in args.symbol_filter):
+ skip = True
+
+ if not skip:
+ reports_count += 1
+ print "==================================="
+ print "This report observed at"
+ for url in all_reports[r]:
+ print " %s" % url
+ print "didn't match any suppressions:"
+ print "Suppression (error hash=#%s#):" % (report_hashes[r])
+ print r
+ print "==================================="
+
+ if args.top_symbols > 0:
+ symbols = GetSymbolsFromReport(r)
+ for symbol in symbols:
+ symbol_reports[symbol].append(report_hashes[r])
+
+ if reports_count > 0:
+ print ("%d unique reports don't match any of the suppressions" %
+ reports_count)
+ if args.top_symbols > 0:
+ PrintTopSymbols(symbol_reports, args.top_symbols)
+
+ else:
+ print "Congratulations! All reports are suppressed!"
+ # TODO(timurrrr): also make sure none of the old suppressions
+ # were narrowed too much.
+
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
diff --git a/chromium/tools/valgrind/tsan/OWNERS b/chromium/tools/valgrind/tsan/OWNERS
new file mode 100644
index 00000000000..72e8ffc0db8
--- /dev/null
+++ b/chromium/tools/valgrind/tsan/OWNERS
@@ -0,0 +1 @@
+*
diff --git a/chromium/tools/valgrind/tsan/PRESUBMIT.py b/chromium/tools/valgrind/tsan/PRESUBMIT.py
new file mode 100644
index 00000000000..999dc1de7d4
--- /dev/null
+++ b/chromium/tools/valgrind/tsan/PRESUBMIT.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into gcl.
+"""
+
+
+def CheckChange(input_api, output_api):
+ """Checks the TSan suppressions files for bad suppressions."""
+
+ # TODO(timurrrr): find out how to do relative imports
+ # and remove this ugly hack. Also, the CheckChange function won't be needed.
+ tools_vg_path = input_api.os_path.join(input_api.PresubmitLocalPath(), '..')
+ import sys
+ old_path = sys.path
+ try:
+ sys.path = sys.path + [tools_vg_path]
+ import suppressions
+ return suppressions.PresubmitCheck(input_api, output_api)
+ finally:
+ sys.path = old_path
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CheckChange(input_api, output_api)
+
+
+def GetPreferredTrySlaves():
+ return ['linux_tsan']
diff --git a/chromium/tools/valgrind/tsan/ignores.txt b/chromium/tools/valgrind/tsan/ignores.txt
new file mode 100644
index 00000000000..39d43244a32
--- /dev/null
+++ b/chromium/tools/valgrind/tsan/ignores.txt
@@ -0,0 +1,188 @@
+# This file lists the functions, object files and source files
+# which should be ignored (i.e. not instrumented) by ThreadSanitizer.
+# See http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores.
+
+# ignore these libraries
+obj:*/libfreetype*
+obj:*/libdbus*
+
+# we ignore the whole NSS library for now since
+# its instrumentation is very slow.
+# TODO(timurrrr): investigate whether we need to instrument it
+obj:*/libnss*
+obj:*/nss/*
+
+# ignore pulseaudio - We don't have symbols there and it can be slow otherwise
+obj:*/libpulse*.so*
+
+# ignore this standard stuff
+fun:clone
+fun:fork
+fun:pthread_*
+fun_r:_pthread_exit
+fun_r:_pthread_free_pthread_onstack
+fun_r:random_r
+fun_r:random
+fun_r:rand
+fun_r:srand
+fun:__new_exitfn
+fun:_dl_*
+fun:__dl_*
+fun:*_setjmp*
+
+# dark magic with 'errno' here.
+fun:sys_*
+
+# ignore libc's printf functions
+fun_r:_IO_*
+fun:fwrite
+fun:fflush
+
+# False reports on std::string internals, see
+# http://code.google.com/p/data-race-test/issues/detail?id=40
+fun:*_M_mutateE*
+fun_r:*_M_set_length_and_sharable*
+fun:*_M_is_leaked*
+fun:*_M_is_shared*
+fun:*_M_set_leaked*
+fun:*_M_set_sharable*
+
+# Comparison of std::strings sometimes takes a lot of time but we don't really
+# need precise stack traces there.
+fun_hist:_ZStltIcSt11char_traitsIcESaIcEEbRKSbIT_T0_T1_ES8_
+fun_hist:_ZNKSs7compareERKSs
+
+# Don't instrument intercepts
+src:*ts_valgrind_intercepts.c
+
+##################################################################
+# Don't instrument synchronization code
+src:*base/threading/thread_local_storage*
+src:*base/stats_counters*
+src:*base/synchronization/condition_variable*
+src:*base/synchronization/lock*
+src:*base/synchronization/waitable_event*
+
+# Don't instrument code dealing with atomics (base::subtle)
+fun:*base*subtle*Release_Store*
+fun:*base*subtle*NoBarrier_CompareAndSwap*
+fun:*base*subtle*NoBarrier_Load*
+# Keep some mangling so we don't match NoBarrier_AtomicIncrement
+fun:*base*subtle23Barrier_AtomicIncrement*
+
+# MD5 computations are very slow due since sums are computed by
+# repeatedly calling tiny functions and is unlikely to race with
+# anything.
+src:*base/md5*
+
+# Don't instrument tcmalloc
+src:*/tcmalloc/*
+
+# This function is heavy in net_unittests
+fun_r:*disk_cache*BackendImpl*CheckAllEntries*
+
+# V8 is a hot-spot under ThreadSanitizer.
+# Lots of tiny functions there...
+# TODO(timurrrr):
+# Can we miss data races on V8 objects due to non thread-safe API calls
+# if we don't instrument v8::internals?
+fun_r:*v8*internal*
+
+# unibrow namespace contains lots of tiny unicode conversion functions.
+fun_hist:*unibrow*
+
+# Histogram has tiny functions that can be called frequently
+fun_hist:*Histogram*
+# Recursively ignore Histrogram::Add and friends, see http://crbug.com/62694.
+fun_r:*4base*9Histogram*3Add*
+fun_r:*4base*16HistogramSamples*3Add*
+fun_r:*4base*13HistogramBase*7AddTime*
+
+# TODO(timurrrr): SKIA - needs separate testing?
+# SKIA unittest is single-threaded...
+# SKIA uses un-annotated atomic refcount and other sync stuff
+# some functions are HEAVY like png, jpeg decoding
+src:*third_party/skia*
+
+# WebKit hotspot
+fun:*png_write*
+
+# This function generates 25% of memory accesses in net_unittests
+fun:*icu_4_2*UnicodeSet*add*
+
+# SQLite has lots of tiny functions and produce too many segments on some tests.
+# See http://crbug.com/56511
+fun_hist:*sqlite*
+
+# There's some weird failure test going on in this tiny test function in sqlite
+fun_r:threadLockingTest
+
+# Ignore accesses below GetCurrentThreadIdentifier.
+# There is a benign race which is hard to suppress properly,
+# see http://crbug.com/44580
+fun_r:*BrowserThread*GetCurrentThreadIdentifier*
+
+# BrowserThread accesses MessageLoop::current() in ::CurrentlyOn.
+# We can't use suppressions to hide these reports since the concurrent stack
+# is simply "base::Thread::ThreadMain"
+# See http://crbug.com/63678
+fun_r:*BrowserThread*CurrentlyOn*
+
+# zlib is smarter than we are, see http://www.zlib.net/zlib_faq.html#faq36
+fun_r:inflate
+# zlib-related reports, not investigated yet. See http://crbug.com/70932
+fun_r:*remoting*CompressorZlib*Process*
+
+# X11 reads the _XErrorFunction callback in a racey way, see
+# http://crbug.com/65278
+fun:XSetErrorHandler
+
+fun:*IPC*Logging*Enable*
+fun:*IPC*Logging*Disable*
+
+# TSan doesn't support lockf and hence shared memory locks in this function;
+# http://crbug.com/45083
+fun_r:*base*StatsTable*AddCounter*
+
+# TSan doesn't understand internal libc locks, see http://crbug.com/71435
+fun_r:mbsrtowcs
+
+# gethostbyname2_r is thread-safe, however ThreadSanitizer reports races inside it and
+# (sometimes) in __nss_* functions below it.
+# This may be related to
+# https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/59449
+fun_r:gethostbyname2_r*
+
+# TODO(timurrrr): remove this when TSan is updated past r3232
+fun_r:gaih_inet
+
+# Strange reports below _IO_getline, every time in "Concurrent access".
+# Probably the reports are there since we're missing the libc internal locks
+fun_r:_IO_getline*
+
+# A benign race in glib on something called "contention_counter".
+fun:g_slice_alloc
+
+# A benign race in glibc on "random_time_bits".
+fun:__gen_tempname
+
+# A probably-benign race on '__have_o_cloexec' in opendir/__alloc_dir,
+# see http://crbug.com/125928.
+fun_r:__alloc_dir
+fun_r:opendir
+
+# The sqlite cache is racing against a few different stacktraces,
+# so let's ignore it recursively. See http://crbug.com/84094
+fun_r:pcache1Fetch
+
+# "Suppress" a data race in TraceLog::GetCategory which has
+# fun:MessageLoop::RunTask at the top of the "current" stack which we don't want
+# to suppress. See http://crbug.com/98926
+fun:*base*debug*TraceLog*GetCategoryInternal*
+
+# libc threading on GCC 4.6
+fun:arena_thread_freeres
+
+# __strncasecmp_l_ssse3 overreads the buffer causing TSan to report a data race
+# on another object. See http://crbug.com/177074
+fun:*strncasecmp*
diff --git a/chromium/tools/valgrind/tsan/ignores_mac.txt b/chromium/tools/valgrind/tsan/ignores_mac.txt
new file mode 100644
index 00000000000..1c219835788
--- /dev/null
+++ b/chromium/tools/valgrind/tsan/ignores_mac.txt
@@ -0,0 +1,38 @@
+# This file lists the functions, object files and source files
+# which should be ignored (i.e. not instrumented) by ThreadSanitizer on Mac OS.
+# At the moment the Chromium binaries' debug info is not available to
+# ThreadSanitizer, so we have to define fun:* rules for Mac OS complementing
+# the src:* rules defined for Linux.
+
+# we ignore the Security libraries for now since
+# their instrumentation is very slow.
+# TODO(timurrrr): investigate whether we need to instrument them
+obj:*/Security*
+obj:*/libcrypto*
+# SensitiveAllocator::free is a part of the Security framework.
+# It calls bzero (0xffff0633) which can't be resolved and thus should be
+# ignored recursively.
+fun_r:*SensitiveAllocator*free*
+
+# The CFBag and CFDictionary operators should be thread-safe, but they are not
+# annotated properly.
+# TODO(glider): replace all the CoreFoundation suppressions with ignores.
+fun_r:CFBag*
+fun_r:CFDictionary*
+fun_r:CFBasicDictionary*
+#fun_r:CFBasicHash*
+
+# see crbug.com/46138
+fun_r:__CFRunLoopDeallocate
+
+fun_r:__CFRunLoopRemoveAllSources
+fun_r:__CFFinalizeRunLoop
+
+# _cthread_fork_child() is called in the child process after the fork syscall.
+# This function cleans up the cthread data structures created in the parent,
+# so ThreadSanitizer might consider it racey.
+fun_r:_cthread_fork_child
+
+# False reports on Snow Leopard.
+fun_r: _pthread_exit
+fun_r: _dispatch_queue_drain
diff --git a/chromium/tools/valgrind/tsan/ignores_win32.txt b/chromium/tools/valgrind/tsan/ignores_win32.txt
new file mode 100644
index 00000000000..f38b00f4541
--- /dev/null
+++ b/chromium/tools/valgrind/tsan/ignores_win32.txt
@@ -0,0 +1,64 @@
+# This file lists the functions, object files and source files
+# which should be ignored (i.e. not instrumented) by ThreadSanitizer on Windows.
+
+# We ignore security libraries for now since their instrumentation is very slow.
+# TODO(timurrrr): investigate whether we need to instrument them
+obj:*CRYPT32.dll
+obj:*RPCRT4.dll
+fun_r:*SHA256*
+fun_r:*BCryptGenerateSymmetricKey*
+fun_r:*CryptAcquireContext*
+
+obj:*WINHTTP.dll
+obj:*imagehlp.dll
+
+# Instrumenting IP Helper API causes crashes.
+# TODO(szym): investigate http://crbug.com/146119
+obj:*IPHLPAPI.dll
+
+# Use less detailed instrumentation of STL
+fun_hist:*std::*<*
+# Don't instrument some stl internals - they shouldn't be useful
+fun_r:*std::_Debug*
+fun_r:*std::_Lockit*
+
+# Benign race on mutex unlock
+fun:_Mtxunlock
+
+# Benign race during clock initialization
+fun_r:*InitializeClock*
+
+# Some unknown Windows guts
+fun_r:Ordinal_*
+fun:unnamedImageEntryPoint
+fun_r:RtlDestroyQueryDebugBuffer
+fun:_updatetlocinfoEx_nolock
+
+# Strange reports on net_unittests, maybe related to raising
+# a debug exception by PlatformThread
+# TODO(timurrrr): investigate
+fun_r:*PlatformThread*SetName*
+
+# Recursively ignore Histrogram::Add and friends, see http://crbug.com/62694.
+fun_r:base::Histogram::Add
+fun_r:base::HistogramSamples::Add
+fun_r:base::HistogramBase::AddTime
+
+# ffmpegsumo.dll appears to read a few bytes beyond the end of the buffer.
+fun:_ff_prefetch_mmxext
+
+# Shows up as a race in SHELL32.dll when deleting a directory while opening an
+# unrelated file in another thread. Revealed by DiskCacheBackendTest.DeleteOld.
+# See: https://code.google.com/p/data-race-test/issues/detail?id=114
+fun_r:SHFileOperationW
+
+# Ignore internal file I/O synchronization: crbug.com/146724
+fun_r:_lock_file
+fun_r:_lock_file2
+fun_r:_lock
+fun_r:_flsbuf
+fun_r:_unlock_file
+fun_r:_getstream
+
+# http://crbug.com/272065
+obj:*NLAapi.dll
diff --git a/chromium/tools/valgrind/tsan/suppressions.txt b/chromium/tools/valgrind/tsan/suppressions.txt
new file mode 100644
index 00000000000..b0de50b5bd8
--- /dev/null
+++ b/chromium/tools/valgrind/tsan/suppressions.txt
@@ -0,0 +1,1138 @@
+# There are a few kinds of suppressions in this file.
+# 1. third party stuff we have no control over
+#
+# 2. intentional unit test errors, or stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing
+#
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system (but a few aren't yet).
+# Periodically we should sweep this file and the bug tracker clean by
+# running overnight and removing outdated bugs/suppressions.
+#-----------------------------------------------------------------------
+
+# 1. third party stuff we have no control over
+############################
+# 1.1 Benign races in libc
+
+# A benign race inside the implementation of internal libc mutex
+{
+ Benign races in __lll_*lock_*_private
+ ThreadSanitizer:Race
+ fun:__lll_*lock_*_private
+}
+
+# Benign races below thread-safe time-conversion functions
+{
+ fun:__tz*
+ ThreadSanitizer:Race
+ fun:__tz*
+}
+{
+ fun:tzset*
+ ThreadSanitizer:Race
+ ...
+ fun:tzset*
+}
+
+# Benign race in thread-safe function
+{
+ fun:mkstemp*
+ ThreadSanitizer:Race
+ ...
+ fun:mkstemp*
+}
+
+# We already ignore memory accesses inside ld
+# but we also need to ignore accesses below it.
+{
+ fun:_dl_close
+ ThreadSanitizer:Race
+ ...
+ fun:_dl_close
+}
+
+# fprintf is thread-safe. The benign races happen on the internal lock.
+{
+ Benign race below fprintf (1)
+ ThreadSanitizer:Race
+ ...
+ fun:buffered_vfprintf
+ ...
+ fun:fprintf
+}
+{
+ Benign race below fprintf (2)
+ ThreadSanitizer:Race
+ fun:new_do_write
+ fun:vfprintf
+}
+
+{
+ fun:timegm
+ ThreadSanitizer:Race
+ ...
+ fun:timegm
+}
+
+{
+ fun:mktime
+ ThreadSanitizer:Race
+ ...
+ fun:mktime
+}
+
+# See crbug.com/84244 for benign races in nss.
+{
+ Benign race in nss (PR_EnterMonitor)
+ ThreadSanitizer:Race
+ fun:PR_EnterMonitor
+}
+{
+ Benign race in nss (PR_ExitMonitor)
+ ThreadSanitizer:Race
+ fun:PR_ExitMonitor
+}
+
+{
+ False positive on strncasecmp OOB read
+ ThreadSanitizer:Race
+ fun:__strncasecmp_l_ssse3
+ fun:base::strncasecmp
+}
+{
+ False positive on strcasecmp OOB read
+ ThreadSanitizer:Race
+ fun:__strcasecmp_l_ssse3
+ fun:base::strcasecmp
+}
+
+{
+ Benign race in get_nprocs, uses barriers
+ ThreadSanitizer:Race
+ fun:get_nprocs
+}
+
+{
+ False positives, glibc just uses internal atomics
+ ThreadSanitizer:Race
+ ...
+ fun:getaddrinfo
+}
+
+############################
+# 1.2 Benign races in ICU
+{
+ Two writes, same value (ICU gGlobalMutex, gMutexesInUse)
+ ThreadSanitizer:Race
+ ...
+ fun:umtx_init_46
+}
+
+{
+ Two writes, same value (ICU gHeapInUse)
+ ThreadSanitizer:Race
+ fun:uprv_malloc_46
+}
+
+# http://bugs.icu-project.org/trac/ticket/10295
+{
+ Two writes, same value (ICU gLibCleanupFunctions[*])
+ ThreadSanitizer:Race
+ fun:ucln_registerCleanup_46
+}
+
+# Reading a pointer to a mutex being initialized in a concurrent thread.
+{
+ A benign race in umtx_lock_46
+ ThreadSanitizer:Race
+ fun:umtx_lock_46
+}
+
+############################
+# 1.3 Benign races in SQLLite
+# TODO(timurrr|oshima): following four suppressions could be obsolete.
+{
+ Two writes, same value (SQLLite pthreadMutexAlloc)
+ ThreadSanitizer:Race
+ ...
+ fun:pthreadMutexAlloc
+}
+
+{
+ Two writes, same value (under sqlite3Malloc)
+ ThreadSanitizer:Race
+ ...
+ fun:sqlite3Malloc*
+}
+
+{
+ Two writes, same value (sqlite3_initialize)
+ ThreadSanitizer:Race
+ fun:sqlite3_initialize
+ fun:openDatabase
+}
+
+{
+ bug_84094_a (Could be benign. See bug for details)
+ ThreadSanitizer:Race
+ ...
+ fun:pcache1Fetch
+ fun:sqlite3PcacheFetch
+}
+
+{
+ bug_84094_b (Could be benign. See bug for details)
+ ThreadSanitizer:Race
+ fun:sqlite3StatusSet
+ fun:pcache1Alloc
+}
+
+{
+ bug_84094_c (Could be benign. See bug for details)
+ ThreadSanitizer:Race
+ ...
+ fun:pcache1Unpin
+ fun:pcacheUnpin
+ fun:sqlite3PcacheMakeClean
+ fun:sqlite3PcacheCleanAll
+}
+
+############################
+# 1.4 Real races in third_party
+{
+ Nvidia GL driver destroys an invalid lock
+ ThreadSanitizer:InvalidLock
+ fun:pthread_mutex_destroy
+ obj:*nvidia*/libGL.so.*
+}
+
+# http://code.google.com/p/v8/issues/detail?id=361
+{
+ V8: race on Locker::active_
+ ThreadSanitizer:Race
+ fun:v8::Locker::*
+}
+
+{
+ bug_23244 (libevent)
+ ThreadSanitizer:Race
+ fun:event_*
+ fun:event_*
+}
+
+{
+ bug_28396 (libevent) (1)
+ ThreadSanitizer:Race
+ fun:detect_monotonic
+ fun:event_base_new
+}
+
+{
+ bug_28396 (libevent) (2)
+ ThreadSanitizer:Race
+ fun:gettime
+ fun:event_base_loop
+}
+
+{
+ bug_28765 (tcmalloc)
+ ThreadSanitizer:Race
+ ...
+ fun:*tcmalloc*ThreadCache*DeleteCache*
+}
+
+{
+ bug_70938
+ ThreadSanitizer:Race
+ ...
+ obj:*libdbus*
+}
+
+{
+ bug_84467a (Could be benign. See bug for details)
+ ThreadSanitizer:Race
+ fun:unixTempFileDir
+}
+
+{
+ bug_84467b
+ ThreadSanitizer:Race
+ fun:getenv
+ fun:unixTempFileDir
+}
+
+{
+ bug_84467c
+ ThreadSanitizer:Race
+ fun:__add_to_environ
+ fun:::EnvironmentImpl::SetVarImpl
+ fun:::EnvironmentImpl::SetVar
+}
+
+{
+ bug_84726_a
+ ThreadSanitizer:Race
+ fun:qsort_r
+ fun:qsort
+ fun:_xdg_mime_alias_read_from_file
+}
+
+{
+ bug_84726_b
+ ThreadSanitizer:Race
+ fun:qsort_r
+ fun:qsort
+ fun:_cairo_bentley_ottmann_tessellate_polygon
+}
+
+{
+ bug_177061
+ ThreadSanitizer:Race
+ ...
+ fun:*cairo*
+}
+
+# 2. intentional unit test errors, or stuff that is somehow a false positive
+############################
+# 2.1 Data races in tests
+{
+ bug_30582
+ ThreadSanitizer:Race
+ fun:*LongCallbackD*
+ fun:*WorkerThreadTickerTest_LongCallback_Test*TestBody*
+}
+
+{
+ bug_61731
+ ThreadSanitizer:Race
+ fun:*Log*
+ ...
+ fun:*Worker*
+ ...
+ obj:*ipc_tests
+}
+
+{
+ bug_68481 [test-only race on bool]
+ ThreadSanitizer:Race
+ ...
+ fun:tracked_objects::ThreadData::ShutdownSingleThreadedCleanup
+ fun:tracked_objects::TrackedObjectsTest_MinimalStartupShutdown_Test::*
+}
+
+# TODO(timurrrr): bug item
+{
+ Data race on bool in AssertReporter [test-only]
+ ThreadSanitizer:Race
+ ...
+ fun:*AssertReporter*warn*
+}
+
+# TODO(timurrrr): bug item
+{
+ Data race on WatchdogCounter [test-only]
+ ThreadSanitizer:Race
+ ...
+ fun:*WatchdogCounter*larm*
+}
+
+# TODO(timurrrr): bug item
+{
+ Data race on counter in WorkQueue [test-only]
+ ThreadSanitizer:Race
+ ...
+ fun:*WorkQueue*
+}
+
+# TODO(timurrrr): bug item
+{
+ Data race on vfptr in base/watchdog_unittest
+ ThreadSanitizer:Race
+ ...
+ fun:*WatchdogTest_*arm*Test_Test*TestBody*
+}
+
+# TODO(timurrrr): bug item
+{
+ Data race on bool in chrome/browser/net/url_fetcher_unittest (1)
+ ThreadSanitizer:Race
+ fun:*URLFetcherCancelTest*TestContextReleased*
+}
+{
+ Data race on bool in chrome/browser/net/url_fetcher_unittest (2)
+ ThreadSanitizer:Race
+ fun:*CancelTestURLRequestContext*CancelTestURLRequestContext*
+}
+
+{
+ ThreadSanitizer sanity test (ToolsSanityTest.DataRace)
+ ThreadSanitizer:Race
+ fun:*TOOLS_SANITY_TEST_CONCURRENT_THREAD::ThreadMain
+}
+
+{
+ Benign race (or even a false positive) on atomics in ThreadCollisionWarner
+ ThreadSanitizer:Race
+ fun:base::subtle::NoBarrier_Store
+ fun:base::ThreadCollisionWarner::Leave
+}
+
+############################
+# 2.2 Benign races in Chromium
+{
+ bug_61179 [benign race on tracked_objects::Births]
+ ThreadSanitizer:Race
+ fun:tracked_objects::Births::*Birth*
+}
+
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+############################
+# Real races in Chromium
+{
+ bug_24419
+ ThreadSanitizer:Race
+ fun:*BrowserProcessImpl*nspector*iles*
+}
+
+{
+ bug_37496
+ ThreadSanitizer:Race
+ ...
+ fun:*browser_sync*SyncShareIntercept*Observe*
+}
+
+{
+ bug_41314
+ ThreadSanitizer:Race
+ ...
+ fun:base::LaunchApp*
+ fun:ChildProcessLauncher::Context::LaunchInternal*
+}
+
+{
+ bug_57266a
+ ThreadSanitizer:Race
+ ...
+ fun:*vp8*_*
+}
+
+{
+ bug_57266b
+ ThreadSanitizer:Race
+ ...
+ obj:*libffmpegsumo.*
+ fun:ThreadSanitizerStartThread
+}
+
+{
+ bug_57266c
+ ThreadSanitizer:Race
+ fun:thread_encoding_proc
+}
+
+{
+ bug_64075a
+ ThreadSanitizer:Race
+ fun:disk_cache::EntryImpl::GetDataSize*
+ fun:net::HttpCache::Transaction::*
+}
+
+{
+ bug_64075b
+ ThreadSanitizer:Race
+ fun:disk_cache::EntryImpl::UpdateSize*
+ ...
+ fun:disk_cache::EntryImpl::WriteDataImpl*
+}
+{
+ bug_66835a
+ ThreadSanitizer:Race
+ fun:getenv
+ fun:::EnvironmentImpl::GetVarImpl
+ fun:::EnvironmentImpl::GetVar
+ fun:ShellIntegrationLinux::GetDesktopName
+ fun:::GetIsDefaultWebClient
+ fun:ShellIntegration::GetDefaultBrowser
+ fun:::RecordDefaultBrowserUMAStat
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_66835b
+ ThreadSanitizer:Race
+ fun:__add_to_environ
+ fun:g_setenv
+ ...
+ fun:giop_init
+ fun:CORBA_ORB_init
+ fun:gconf_orb_get
+ ...
+ fun:gconf_activate_server
+ ...
+ fun:gconf_engine_get_fuller
+ fun:gconf_engine_get_entry
+ ...
+ fun:GConfTitlebarListener::GConfTitlebarListener
+ fun:DefaultSingletonTraits::New
+ fun:Singleton::get
+ fun:GConfTitlebarListener::GetInstance
+ fun:BrowserTitlebar::Init
+ fun:BrowserWindowGtk::InitWidgets
+ fun:BrowserWindowGtk::Init
+ fun:BrowserWindow::CreateBrowserWindow
+ fun:::CreateBrowserWindow
+ fun:Browser::Browser
+ fun:StartupBrowserCreatorImpl::OpenTabsInBrowser
+ fun:StartupBrowserCreatorImpl::ProcessSpecifiedURLs
+ fun:StartupBrowserCreatorImpl::ProcessStartupURLs
+ fun:StartupBrowserCreatorImpl::ProcessLaunchURLs
+ fun:StartupBrowserCreatorImpl::Launch
+}
+
+{
+ bug_67957
+ ThreadSanitizer:Race
+ fun:Replace_memcpy
+ fun:memcpy
+ fun:extensions::Serialize
+ fun:extensions::UserScriptMaster::ScriptReloader::RunLoad
+}
+
+{
+ bug_72548
+ ThreadSanitizer:Race
+ ...
+ fun:JSC::Yarr::Interpreter::*Disjunction*
+ fun:JSC::Yarr::Interpreter::interpret*
+ fun:JSC::Yarr::interpret*
+}
+
+{
+ bug_86916
+ ThreadSanitizer:Race
+ fun:loopfilter_frame
+ fun:loopfilter_thread
+}
+
+{
+ bug_89141
+ ThreadSanitizer:Race
+ fun:base::Thread::message_loop
+ fun:content::BrowserThread::IsMessageLoopValid
+ fun:ThreadWatcherList::StartWatching
+ fun:ThreadWatcherList::InitializeAndStartWatching
+}
+{
+ bug_93932_a
+ ThreadSanitizer:Race
+ ...
+ fun:avcodec_close
+ ...
+ fun:media::FFmpegVideoDecoder::*
+ ...
+ fun:media::FFmpegVideoDecode*Test::*
+}
+{
+ bug_93932_b
+ ThreadSanitizer:Race
+ ...
+ fun:ff_thread_decode_frame
+ fun:avcodec_decode_video2
+ ...
+ fun:media::FFmpegVideoDecoder::Decode*
+}
+{
+ bug_93932_c
+ ThreadSanitizer:Race
+ fun:Replace_memcpy
+ fun:memcpy
+ fun:media::CopyPlane
+ ...
+ fun:media::FFmpegVideoDecoder::Decode*
+}
+{
+ bug_93932_d
+ ThreadSanitizer:Race
+ fun:frame_worker_thread
+}
+{
+ bug_93932_e
+ ThreadSanitizer:Race
+ fun:Replace_memcpy
+ fun:memcpy
+ fun:ff_thread_decode_frame
+ ...
+ fun:media::FFmpegVideoDecoder::Decode*
+}
+{
+ bug_93932_f
+ ThreadSanitizer:Race
+ ...
+ fun:ff_thread_flush
+ ...
+ fun:media::FFmpegVideoDecoder::Reset
+}
+{
+ bug_93932_g
+ ThreadSanitizer:Race
+ ...
+ fun:frame_thread_free
+ ...
+ fun:avcodec_close
+}
+{
+ bug_93932_h
+ ThreadSanitizer:Race
+ ...
+ fun:render_slice
+ fun:vp3_decode_frame
+ fun:frame_worker_thread
+}
+{
+ bug_93932_i
+ ThreadSanitizer:Race
+ ...
+ fun:ff_thread_flush
+ ...
+ fun:media::FFmpegVideoDecoder::DoReset
+}
+{
+ bug_93932_j
+ ThreadSanitizer:Race
+ ...
+ fun:base::MD5Update
+ fun:media::VideoFrame::HashFrameForTesting
+ fun:media::PipelineIntegrationTestBase::OnVideoRendererPaint
+}
+{
+ bug_93932_k
+ ThreadSanitizer:Race
+ ...
+ fun:media::FFmpegVideoDecoder::Decode
+ fun:media::FFmpegVideoDecoder::DecodeBuffer
+ fun:media::FFmpegVideoDecoder::DoDecryptOrDecodeBuffer
+ fun:media::FFmpegVideoDecoder::DoDecryptOrDecodeBuffer
+}
+{
+ bug_100020
+ ThreadSanitizer:Race
+ fun:linked_ptr_internal::join
+ fun:linked_ptr::copy
+ ...
+ fun:HostContentSettingsMap::GetDefaultContentSetting
+}
+{
+ bug_102327_a
+ ThreadSanitizer:Race
+ fun:tracked_objects::ThreadData::Initialize
+ fun:tracked_objects::ThreadData::InitializeThreadContext
+ fun:base::Thread::ThreadMain
+ fun:base::::ThreadFunc
+}
+{
+ bug_102327_b
+ ThreadSanitizer:Race
+ ...
+ fun:tracked_objects::ThreadData::TallyABirthIfActive
+ fun:base::PosixDynamicThreadPool::PendingTask::PendingTask
+ fun:base::PosixDynamicThreadPool::WaitForTask
+ fun:base::::WorkerThread::ThreadMain
+ fun:base::::ThreadFunc
+}
+{
+ bug_102327_c
+ ThreadSanitizer:Race
+ fun:tracked_objects::ThreadData::TrackingStatus
+}
+{
+ bug_102327_d
+ ThreadSanitizer:Race
+ fun:tracked_objects::ThreadData::SnapshotMaps
+}
+{
+ bug_102327_e
+ ThreadSanitizer:Race
+ fun:tracked_objects::Births::birth_count
+ fun:tracked_objects::ThreadData::SnapshotExecutedTasks
+}
+{
+ bug_102327_f
+ ThreadSanitizer:Race
+ fun:tracked_objects::DeathData::RecordDeath
+}
+{
+ bug_103711a
+ ThreadSanitizer:Race
+ fun:webrtc::Trace::SetLevelFilter
+}
+{
+ bug_103711b
+ ThreadSanitizer:Race
+ fun:webrtc::TraceImpl::TraceCheck
+}
+{
+ bug_103711c
+ ThreadSanitizer:Race
+ fun:webrtc::ThreadPosix::*
+}
+{
+ bug_103711d
+ ThreadSanitizer:Race
+ fun:webrtc::FileWrapper*::*
+ ...
+ fun:webrtc::TraceImpl::StaticInstance
+ fun:webrtc::Trace::ReturnTrace
+ fun:webrtc::voe::SharedData::~SharedData
+ fun:webrtc::VoiceEngineImpl::~VoiceEngineImpl
+ ...
+ fun:webrtc::VoiceEngine::Delete
+ fun:WebRTCAutoDelete::reset
+ ...
+ fun:content::WebRTCAudioDeviceTest_Construct_Test::TestBody
+}
+{
+ bug_103711e
+ ThreadSanitizer:Race
+ ...
+ fun:content::WebRTCAudioDeviceTest::OnMessageReceived
+ ...
+ fun:IPC::*
+ fun:IPC::Channel::ChannelImpl::OnFileCanReadWithoutBlocking
+ ...
+ fun:base::MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking
+ fun:base::MessagePumpLibevent::OnLibeventNotification
+ fun:event_process_active
+ fun:event_base_loop
+}
+{
+ bug_103711f
+ ThreadSanitizer:Race
+ fun:webrtc::TracePosix::AddTime
+ fun:webrtc::TraceImpl::AddImpl
+ fun:webrtc::Trace::Add
+ fun:webrtc::ThreadPosix::Run
+}
+{
+ bug_103711g
+ ThreadSanitizer:Race
+ fun:content::WebRTCAudioDeviceTest::SetUp
+}
+{
+ bug_103711h
+ ThreadSanitizer:Race
+ fun:webrtc::EventWrapper::~EventWrapper
+ fun:webrtc::EventPosix::~EventPosix
+ fun:webrtc::ProcessThreadImpl::~ProcessThreadImpl
+ fun:webrtc::ProcessThread::DestroyProcessThread
+ fun:webrtc::voe::SharedData::~SharedData
+ fun:webrtc::VoiceEngineImpl::~VoiceEngineImpl
+ fun:webrtc::VoiceEngine::Delete
+ fun:WebRTCAutoDelete::reset
+ fun:WebRTCAutoDelete::~WebRTCAutoDelete
+ fun:content::WebRTCAudioDeviceTest_Construct_Test::TestBody
+}
+{
+ bug_103711i
+ ThreadSanitizer:Race
+ fun:webrtc::ProcessThreadImpl::Process
+ fun:webrtc::ProcessThreadImpl::Run
+ fun:webrtc::ThreadPosix::Run
+ fun:StartThread
+}
+{
+ bug_103711j
+ ThreadSanitizer:Race
+ fun:webrtc::ProcessThreadImpl::Stop
+ fun:webrtc::VoEBaseImpl::TerminateInternal
+ fun:webrtc::VoEBaseImpl::Terminate
+ fun:content::WebRTCAudioDeviceTest_PlayLocalFile_Test::TestBody
+}
+{
+ bug_104769
+ ThreadSanitizer:Race
+ fun:timeout_correct
+ fun:event_base_loop
+ fun:base::MessagePumpLibevent::Run
+ fun:base::MessageLoop::RunInternal
+ fun:base::MessageLoop::RunHandler
+}
+{
+ bug_104776_maybe_benign
+ ThreadSanitizer:Race
+ fun:base::StatisticsRecorder::StatisticsRecorder
+ fun:::BrowserMainRunnerImpl::Initialize
+ fun:BrowserMain
+ fun:::RunNamedProcessTypeMain
+ fun:::ContentMainRunnerImpl::Run
+ fun:content::ContentMain
+ fun:ChromeMain
+ fun:main
+}
+{
+ bug_106196
+ ThreadSanitizer:Race
+ fun:tracked_objects::ThreadData::InitializeAndSetTrackingStatus
+ fun:*ChildThread::OnSetProfilerStatus
+ fun:DispatchToMethod
+}
+{
+ bug_107903_a
+ ThreadSanitizer:Race
+ ...
+ fun:TestProfileSyncService::~TestProfileSyncService
+ fun:scoped_ptr::reset
+ fun:ProfileSyncServiceAutofillTest::TearDown
+}
+{
+ bug_107903_b
+ ThreadSanitizer:Race
+ ...
+ fun:syncer::SyncManager::SyncInternal::ShutdownOnSyncThread
+ fun:syncer::SyncManager::ShutdownOnSyncThread
+ fun:browser_sync::SyncBackendHost::Core::DoShutdown
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_107903_c
+ ThreadSanitizer:Race
+ fun:syncable::DirectoryChangeDelegate::~DirectoryChangeDelegate
+ fun:syncer::SyncManager::SyncInternal::~SyncInternal
+ fun:syncer::SyncManager::~SyncManager
+ fun:scoped_ptr::reset
+ fun:browser_sync::SyncBackendHost::Core::DoShutdown
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_108408
+ ThreadSanitizer:Race
+ fun:base::subtle::RefCountedBase::AddRef
+ fun:base::RefCounted::AddRef
+ fun:net::HttpCache::Transaction::DoCacheWriteData
+ fun:net::HttpCache::Transaction::DoLoop
+ fun:net::HttpCache::Transaction::ReadFromNetwork
+ fun:net::HttpCache::Transaction::Read
+ fun:net::URLRequestHttpJob::ReadRawData
+ fun:net::URLRequestJob::ReadRawDataHelper
+ fun:net::URLRequestJob::Read
+ fun:net::URLRequest::Read
+ fun:ResourceDispatcherHost::Read
+ fun:ResourceDispatcherHost::StartReading
+ fun:ResourceDispatcherHost::ResumeRequest
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_108539
+ ThreadSanitizer:Race
+ fun:tracked_objects::ThreadData::InitializeAndSetTrackingStatus
+ fun:tracked_objects::ThreadData::ShutdownSingleThreadedCleanup
+ fun:tracked_objects::TrackedObjectsTest::TrackedObjectsTest
+ fun:tracked_objects::TrackedObjectsTest_MinimalStartupShutdown_Test::TrackedObjectsTest_MinimalStartupShutdown_Test
+}
+{
+ bug_112419
+ ThreadSanitizer:Race
+ ...
+ fun:::OCSPTrySendAndReceive
+ fun:pkix_pl_Pk11CertStore_GetCRL
+ fun:pkix_CrlChecker_CheckExternal
+ fun:PKIX_RevocationChecker_Check
+ fun:pkix_CheckChain
+ fun:pkix_Build_ValidateEntireChain
+ fun:pkix_BuildForwardDepthFirstSearch
+ fun:pkix_Build_InitiateBuildChain
+ fun:PKIX_BuildChain
+ fun:CERT_PKIXVerifyCert
+ fun:net::::PKIXVerifyCert
+ fun:net::X509Certificate::VerifyInternal
+ fun:net::X509Certificate::Verify
+ fun:net::CertVerifierWorker::Run
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_113717
+ ThreadSanitizer:Race
+ fun:std::swap
+ fun:content::RenderThreadImpl::Send
+ fun:content::RenderWidget::Send
+ fun:content::RenderViewImpl::Send
+ fun:content::RenderWidget::DoDeferredUpdate
+ fun:content::RenderWidget::DoDeferredUpdateAndSendInputAck
+ fun:content::RenderWidget::InvalidationCallback
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_115540
+ ThreadSanitizer:Race
+ fun:base::Thread::message_loop
+ fun:content::BrowserThreadImpl::PostTaskHelper
+ fun:content::BrowserThread::PostTask
+ fun:AudioRendererHost::OnCreated
+ fun:media::AudioOutputController::DoCreate
+}
+{
+ bug_116559
+ ThreadSanitizer:Race
+ fun:logging::::LoggingTest_Dcheck_Test::TestBody
+ fun:testing::internal::HandleSehExceptionsInMethodIfSupported
+}
+{
+ bug_118319_a
+ ThreadSanitizer:Race
+ fun:content::BrowserThreadImpl::~BrowserThreadImpl
+ fun:content::BrowserProcessSubThread::~BrowserProcessSubThread
+ fun:scoped_ptr::reset
+ fun:content::BrowserMainLoop::ShutdownThreadsAndCleanUp
+ fun:::BrowserMainRunnerImpl::Shutdown
+ fun:BrowserMain
+ fun:::RunNamedProcessTypeMain
+ fun:::ContentMainRunnerImpl::Run
+ fun:content::ContentMain
+ fun:ChromeMain
+ fun:main
+}
+{
+ bug_118319_b
+ ThreadSanitizer:Race
+ fun:base::Thread::message_loop
+ fun:content::BrowserThreadImpl::PostTaskHelper
+ fun:content::BrowserThread::PostTask
+ fun:PluginLoaderPosix::GetPluginsToLoad
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_118319_c
+ ThreadSanitizer:Race
+ fun:base::Thread::ThreadMain
+ fun:base::::ThreadFunc
+}
+{
+ bug_125928_a
+ ThreadSanitizer:Race
+ fun:__alloc_dir
+ fun:opendir
+ fun:g_dir_open
+ fun:pango_find_map
+ fun:itemize_state_process_run
+ fun:pango_itemize_with_base_dir
+ fun:pango_layout_check_lines
+ fun:pango_layout_get_unknown_glyphs_count
+ fun:find_invisible_char
+ fun:gtk_entry_init
+ fun:g_type_create_instance
+ fun:g_object_constructor
+ fun:g_object_newv
+ fun:g_object_new
+ ...
+ fun:ThemeServiceFactory::BuildServiceInstanceFor
+ fun:BrowserContextKeyedServiceFactory::GetServiceForBrowserContext
+ fun:ThemeServiceFactory::GetForProfile
+ fun:ExtensionService::GarbageCollectExtensions
+ fun:ExtensionService::InitAfterImport
+ fun:ExtensionService::Observe
+ fun:NotificationServiceImpl::Notify
+ fun:ProfileManager::OnImportFinished
+ fun:ChromeBrowserMainParts::PreMainMessageLoopRunImpl
+ fun:ChromeBrowserMainParts::PreMainMessageLoopRun
+ fun:content::BrowserMainLoop::CreateThreads
+ fun:::BrowserMainRunnerImpl::Initialize
+ fun:BrowserMain
+ fun:::RunNamedProcessTypeMain
+ fun:::ContentMainRunnerImpl::Run
+}
+{
+ bug_125928_b
+ ThreadSanitizer:Race
+ fun:__alloc_dir
+ fun:opendir
+ fun:base::FileEnumerator::ReadDirectory
+ fun:base::FileEnumerator::Next
+ fun:::GetPrefsCandidateFilesFromFolder
+ fun:ExternalPrefLoader::ReadStandaloneExtensionPrefFiles
+ fun:ExternalPrefLoader::LoadOnFileThread
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_121574
+ ThreadSanitizer:Race
+ fun:base::Thread::message_loop
+ fun:content::BrowserThreadImpl::PostTaskHelper
+ fun:content::BrowserThread::PostTask
+ fun:ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK
+ fun:ProcessSingleton::LinuxWatcher::HandleMessage
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_131001
+ ThreadSanitizer:Race
+ ...
+ fun:media::AudioOutputMixer::StopStream
+ fun:media::AudioOutputProxy::Stop
+ fun:media::AudioOutputController::DoStopCloseAndClearStream
+ fun:media::AudioOutputController::DoClose
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_137701
+ ThreadSanitizer:Race
+ ...
+ fun:_output_*
+ fun:_vsnprintf_helper
+}
+{
+ bug_137973_a
+ ThreadSanitizer:Race
+ fun:media::Pipeline::OnVideoTimeUpdate
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_137973_b
+ ThreadSanitizer:Race
+ fun:media::Pipeline::SetState
+ fun:media::Pipeline::StopTask
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_137973_c
+ ThreadSanitizer:Race
+ fun:media::Pipeline::SetState
+ fun:media::Pipeline::SeekTask
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_144894
+ ThreadSanitizer:Race
+ fun:av_parser_close
+ fun:avcodec_open2
+ fun:avformat_find_stream_info
+ fun:media::FFmpegConfigHelper::SetupStreamConfigs
+ fun:media::FFmpegConfigHelper::Parse
+ fun:media::WebMStreamParser::ParseInfoAndTracks
+ fun:media::WebMStreamParser::Parse
+ fun:media::ChunkDemuxer::AppendData
+ fun:media::MockMediaSource::AppendAtTime
+ fun:media::PipelineIntegrationTest_MediaSource_ConfigChange_WebM_Test::TestBody
+}
+{
+ bug_172292
+ ThreadSanitizer:Race
+ fun:testing::internal::CmpHelperGE
+ fun:ThreadWatcherTest_MultipleThreadsResponding_Test::TestBody
+ fun:testing::internal::HandleSehExceptionsInMethodIfSupported
+}
+{
+ bug_172297
+ ThreadSanitizer:Race
+ fun:CustomThreadWatcher::UpdateState
+ fun:*
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_172306
+ ThreadSanitizer:Race
+ fun:ThreadWatcher::OnPongMessage
+ fun:CustomThreadWatcher::OnPongMessage
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_175467
+ ThreadSanitizer:Race
+ ...
+ fun:file_util::OpenFile
+ fun:visitedlink::VisitedLinkMaster::InitFromFile
+ fun:visitedlink::VisitedLinkMaster::InitFromFile
+ fun:visitedlink::VisitedLinkMaster::InitFromFile
+ fun:visitedlink::VisitedLinkMaster::Init
+ fun:visitedlink::VisitedLinkEventsTest::CreateBrowserContext
+ fun:content::RenderViewHostTestHarness::SetUp
+}
+{
+ bug_178433a
+ ThreadSanitizer:Race
+ fun:scoped_refptr::operator->
+ fun:base::WaitableEvent::Signal
+ fun:base::debug::TraceSamplingThread::ThreadMain
+ fun:base::::ThreadFunc
+}
+{
+ bug_178433b
+ ThreadSanitizer:Race
+ fun:base::internal::scoped_ptr_impl::get
+ ...
+ fun:base::debug::TraceSamplingThread::ThreadMain
+}
+{
+ bug_222684a
+ ThreadSanitizer:Race
+ ...
+ fun:WebCore::shouldTreatAsUniqueOrigin
+ fun:WebCore::SecurityOrigin::create
+ fun:WebCore::SecurityOrigin::createFromString
+ fun:WebKit::WebSecurityOrigin::createFromString
+}
+{
+ bug_222684b
+ ThreadSanitizer:Race
+ ...
+ fun:WebCore::SecurityOrigin::SecurityOrigin
+ fun:WebCore::SecurityOrigin::create
+ fun:WebCore::SecurityOrigin::createFromString
+ fun:WebKit::WebSecurityOrigin::createFromString
+}
+{
+ bug_225123
+ ThreadSanitizer:Race
+ fun:setlocale
+ ...
+ fun:gfx::GtkInitFromCommandLine
+}
+{
+ bug_239350
+ ThreadSanitizer:Race
+ fun:av_buffer_unref
+ fun:av_frame_unref
+ fun:avcodec_decode_video2
+ ...
+ fun:media::FFmpegVideoDecoder::Decode
+}
+{
+ bug_256792
+ ThreadSanitizer:Race
+ fun:media::AudioManagerLinux::~AudioManagerLinux
+ fun:content::MockAudioManager::~MockAudioManager
+ fun:content::MockAudioManager::~MockAudioManager
+ fun:base::DefaultDeleter*
+ fun:base::internal::scoped_ptr_impl::~scoped_ptr_impl
+ fun:scoped_ptr::~scoped_ptr
+ fun:content::MediaStreamManagerTest::~MediaStreamManagerTest
+ fun:content::MediaStreamManagerTest_MakeAndCancelMediaAccessRequest_Test::~MediaStreamManagerTest_MakeAndCancelMediaAccessRequest_Test
+ fun:content::MediaStreamManagerTest_MakeAndCancelMediaAccessRequest_Test::~MediaStreamManagerTest_MakeAndCancelMediaAccessRequest_Test
+ fun:testing::Test::DeleteSelf_
+ fun:testing::internal::HandleSehExceptionsInMethodIfSupported
+}
+{
+ bug_258935
+ ThreadSanitizer:Race
+ fun:base::Thread::StopSoon
+ fun:base::Thread::Stop
+ fun:content::UtilityMainThread::~UtilityMainThread
+ fun:content::UtilityMainThread::~UtilityMainThread
+ fun:base::DefaultDeleter::operator*
+ fun:base::internal::scoped_ptr_impl::~scoped_ptr_impl
+ fun:scoped_ptr::~scoped_ptr
+ fun:content::UtilityProcessHostImpl::~UtilityProcessHostImpl
+ fun:content::UtilityProcessHostImpl::~UtilityProcessHostImpl
+ fun:content::BrowserChildProcessHostImpl::OnChildDisconnected
+ fun:content::ChildProcessHostImpl::OnChannelError
+ fun:IPC::Channel::ChannelImpl::ClosePipeOnError
+ fun:IPC::Channel::ChannelImpl::OnFileCanReadWithoutBlocking
+ fun:base::MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking
+ fun:base::MessagePumpLibevent::OnLibeventNotification
+}
+{
+ bug_268924
+ ThreadSanitizer:Race
+ fun:base::PowerMonitor::PowerMonitor
+ fun:content::ChildThread::Init
+ fun:content::ChildThread::ChildThread
+ fun:content::UtilityThreadImpl::UtilityThreadImpl
+ fun:content::UtilityMainThread::InitInternal
+}
diff --git a/chromium/tools/valgrind/tsan/suppressions_mac.txt b/chromium/tools/valgrind/tsan/suppressions_mac.txt
new file mode 100644
index 00000000000..224a5ae124b
--- /dev/null
+++ b/chromium/tools/valgrind/tsan/suppressions_mac.txt
@@ -0,0 +1,270 @@
+# There are two kinds of suppressions in this file.
+# 1. third party stuff we have no control over
+#
+# 2. Intentional unit test errors, or stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing
+#
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system (but a few aren't yet).
+# Periodically we should sweep this file and the bug tracker clean by
+# running overnight and removing outdated bugs/suppressions.
+#-----------------------------------------------------------------------
+
+# 1. third party stuff we have no control over
+# Several Cocoa-specific races
+{
+ Some Cocoa-specific race in NSRunLoop class
+ ThreadSanitizer:Race
+ ...
+ fun:*CFRunLoop*
+}
+
+{
+ A race releasing NSObject
+ ThreadSanitizer:Race
+ ...
+ fun:__CFDoExternRefOperation
+ fun:-[NSObject release]
+}
+
+{
+ A race retaining NSObject
+ ThreadSanitizer:Race
+ ...
+ fun:CFBagAddValue
+ fun:__CFDoExternRefOperation
+ fun:-[NSObject retain]
+}
+
+{
+ A race retaining NSBundle
+ ThreadSanitizer:Race
+ ...
+ fun:CFBagAddValue
+ fun:__CFDoExternRefOperation
+ fun:NSIncrementExtraRefCount
+ fun:-[NSBundle retain]
+}
+
+{
+ A race deallocating NSOperationQueue
+ ThreadSanitizer:Race
+ ...
+ fun:_CFRelease
+ fun:-[NSOperationQueue dealloc]
+}
+
+{
+ Another race deallocating NSOperationQueue
+ ThreadSanitizer:Race
+ ...
+ fun:-[NSIndexSet dealloc]
+ fun:-[NSOperationQueue dealloc]
+}
+
+# A related OpenRadar bug is at http://openradar.appspot.com/7396501.
+{
+ A benign race on a debug counter in __NSAutoreleaseObject
+ ThreadSanitizer:Race
+ fun:__NSAutoreleaseObject
+ fun:-[NSObject(NSObject) autorelease]
+}
+
+# media_unittests depend on the Darwin libraries which have many reports in
+# them. A related OpenRadar bug is at http://openradar.appspot.com/7223948
+{
+ Warnings in the CoreAudio component
+ ThreadSanitizer:Race
+ ...
+ obj:/System/Library/Components/CoreAudio.component*
+}
+
+{
+ Warnings in the CoreAudio framework
+ ThreadSanitizer:Race
+ ...
+ obj:/System/Library/Frameworks/CoreAudio.framework*
+}
+
+{
+ A warning in CoreAudio framework
+ ThreadSanitizer:Race
+ ...
+ fun:*HALRunLoop*
+}
+
+{
+ A warning in the AudioToolbox framework
+ ThreadSanitizer:Race
+ ...
+ fun:*CAPThread*
+}
+
+{
+ Warnings inside AQServer_{Stop,EnqueueBuffer}
+ ThreadSanitizer:Race
+ ...
+ fun:*AudioQueueObject*
+ ...
+ fun:AQServer_*
+}
+
+{
+ Warnings inside AudioHardwareGetProperty
+ ThreadSanitizer:Race
+ ...
+ fun:AudioHardwareGetProperty
+}
+
+{
+ Benign data race in CAMutex bug_23579
+ ThreadSanitizer:Race
+ fun:*CAMutex*ock*
+}
+
+{
+ A warning on destruction of third party ClientAudioQueue object (AudioToolbox)
+ ThreadSanitizer:Race
+ ...
+ fun:*AQClient*CheckDisposal*
+ fun:*ClientAudioQueueD*
+ fun:AudioQueueDispose
+}
+
+{
+ Destroying invalid lock in krb5int_getaddrinfo while terminating Kerberos.
+ ThreadSanitizer:InvalidLock
+ fun:pthread_mutex_destroy
+ fun:krb5int_getaddrinfo
+ fun:ImageLoaderMachO::doTermination*
+}
+
+{
+ bug_55946
+ ThreadSanitizer:Race
+ ...
+ fun:OSAtomicAdd32
+ fun:base::subtle::Barrier_AtomicIncrement*
+}
+
+#-----------------------------------------------------------------------
+# 2. Intentional unit test errors, or stuff that is somehow a false positive
+# in our own code, or stuff that is so trivial it's not worth fixing
+
+{
+ Benign data race inside PCMQueueOutAudioOutputStream::Stop bug_24801
+ ThreadSanitizer:Race
+ fun:*PCMQueueOutAudioOutputStream*Stop*
+}
+
+{
+ bug_100313 TSan false positive
+ ThreadSanitizer:Race
+ ...
+ fun:__sfp
+ fun:fopen
+ fun:file_util::OpenFile
+ fun:base::SharedMemory::CreateNamed
+}
+
+{
+ Benign race to access status during TrackedObject unittests
+ ThreadSanitizer:Race
+ ...
+ fun:tracked_objects::ThreadData::ShutdownSingleThreadedCleanup
+}
+
+#-----------------------------------------------------------------------
+# 3. Suppressions for real chromium bugs that are not yet fixed.
+# These should all be in chromium's bug tracking system (but a few aren't yet).
+# Periodically we should sweep this file and the bug tracker clean by
+# running overnight and removing outdated bugs/suppressions.
+
+{
+ bug_93932j
+ ThreadSanitizer:Race
+ fun:release_delayed_buffers
+ fun:frame_thread_free
+ fun:ff_thread_free
+ fun:avcodec_close
+ fun:avcodec_close
+ fun:media::FFmpegVideoDecoder::ReleaseFFmpegResources
+ fun:media::FFmpegVideoDecoder::Stop
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_100772a
+ ThreadSanitizer:Race
+ fun:CAGuard::Wait
+ fun:MIO::DAL::RunLoop::StartOwnThread
+ fun:MIO::DAL::RunLoop::Start
+ fun:MIO::DAL::System::CheckOutInstance
+ fun:TundraObjectGetPropertyDataSize
+ fun:+[QTCaptureDALDevice _refreshDevices]
+ fun:+[QTCaptureDALDevice devicesWithIOType:]
+ fun:+[QTCaptureDevice devicesWithIOType:]
+ fun:+[QTCaptureDevice inputDevices]
+ fun:+[QTCaptureDevice inputDevicesWithMediaType:]
+ fun:+[VideoCaptureDeviceQTKit deviceNames]
+ fun:media::VideoCaptureDevice::GetDeviceNames
+ fun:media::VideoCaptureDeviceMac::Init
+ fun:media::VideoCaptureDevice::Create
+ fun:media::VideoCaptureDeviceTest_OpenInvalidDevice_Test::TestBody
+}
+{
+ bug_100772b
+ ThreadSanitizer:Race
+ fun:DVDeviceTerminate
+}
+{
+ bug_100772c
+ ThreadSanitizer:Race
+ fun:MIO::DAL::RunLoop::StopOwnThread
+ fun:MIO::DAL::RunLoop::Teardown
+ fun:MIO::DAL::System::TeardownShell
+ fun:MIO::DAL::System::AtExitHandler
+ fun:MIO::DAL::AtExit::AtExitHandler
+}
+{
+ bug_100772d
+ ThreadSanitizer:Race
+ fun:DVSignalSync
+ fun:DVDeviceTerminate
+}
+{
+ bug_106197
+ ThreadSanitizer:Race
+ ...
+ fun:__sfp
+ fun:fopen
+ fun:file_util::OpenFile
+ fun:base::SharedMemory::Create
+ fun:base::SharedMemory::CreateNamed
+ fun:base::::MultipleThreadMain::ThreadMain
+ fun:base::::ThreadFunc
+}
+{
+ bug_123112
+ ThreadSanitizer:Race
+ fun:media::AUAudioOutputStream::Stop
+ fun:media::AudioOutputDispatcherImpl::StopStream
+ fun:media::AudioOutputProxy::Stop
+ fun:media::AudioOutputController::DoStopCloseAndClearStream
+ fun:media::AudioOutputController::DoClose
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_133074_a
+ ThreadSanitizer:Race
+ fun:CAMutex::~CAMutex
+ fun:AudioQueueDispose
+ fun:media::PCMQueueOutAudioOutputStream::Close
+}
+{
+ bug_133074_b
+ ThreadSanitizer:Race
+ fun:media::AUAudioOutputStream::Stop
+ fun:media::AudioOutputMixer::ClosePhysicalStream
+ fun:media::AudioOutputMixer::Shutdown
+ fun:media::AudioManagerBase::ShutdownOnAudioThread
+}
diff --git a/chromium/tools/valgrind/tsan/suppressions_win32.txt b/chromium/tools/valgrind/tsan/suppressions_win32.txt
new file mode 100644
index 00000000000..b1e111c41f4
--- /dev/null
+++ b/chromium/tools/valgrind/tsan/suppressions_win32.txt
@@ -0,0 +1,225 @@
+############################
+# Reports on the guts of Windows
+{
+ UuidCreate
+ ThreadSanitizer:Race
+ ...
+ fun:UuidCreate
+}
+
+{
+ ILFindLastID
+ ThreadSanitizer:Race
+ ...
+ fun:ILFindLastID
+}
+
+{
+ RpcServerUnregisterIf
+ ThreadSanitizer:Race
+ ...
+ fun:RpcServerUnregisterIf
+}
+
+# http://code.google.com/p/data-race-test/issues/detail?id=45
+{
+ accessing an invalid lock in unnamedImageEntryPoint
+ ThreadSanitizer:InvalidLock
+ fun:unnamedImageEntryPoint
+}
+
+{
+ accessing an invalid lock in CoFreeAllLibraries
+ ThreadSanitizer:InvalidLock
+ fun:CoFreeAllLibraries
+}
+
+{
+ bug_158099_mmdevice_endpoint_shutdown_too_fast
+ ThreadSanitizer:Race
+ fun:GetLocalIdFromEndpointId
+ ...
+}
+
+############################
+# Chromium
+
+{
+ Benign race durung InitializeClock
+ ThreadSanitizer:Race
+ ...
+ fun:*InitializeClock*
+}
+
+{
+ bug_62560
+ ThreadSanitizer:Race
+ ...
+ fun:_initterm
+ fun:doexit
+}
+
+{
+ accessing an invalid lock under exit/doexit
+ ThreadSanitizer:InvalidLock
+ fun:*~Lock*
+ ...
+ fun:doexit
+ fun:exit
+}
+{
+ bug_81793a
+ ThreadSanitizer:Race
+ ...
+ fun:NetTestSuite::InitializeTestThread
+}
+{
+ bug_81793b
+ ThreadSanitizer:Race
+ ...
+ fun:base::MessageLoop::CalculateDelayedRuntime
+ fun:base::MessageLoop::Post*Task
+}
+{
+ bug_93932a
+ ThreadSanitizer:Race
+ fun:avcodec_default_release_buffer
+ fun:ff_mpeg4video_split
+}
+{
+ bug_93932b
+ ThreadSanitizer:Race
+ ...
+ fun:avcodec_close
+ fun:media::FFmpegVideoDecoder::ReleaseFFmpegResources
+}
+{
+ bug_93932d
+ ThreadSanitizer:Race
+ fun:memcpy
+ fun:media::CopyPlane
+}
+{
+ bug_93932e
+ ThreadSanitizer:Race
+ ...
+ fun:ff_thread_finish_setup
+ fun:ptw32_threadStart@4
+}
+{
+ bug_93932f
+ ThreadSanitizer:Race
+ ...
+ fun:ff_vp3_h_loop_filter_c
+ ...
+ fun:ff_thread_flush
+ fun:media::FFmpegVideoDecoder::Flush
+}
+{
+ bug_93932g
+ ThreadSanitizer:Race
+ ...
+ fun:av_parser_close
+ ...
+ fun:BaseThreadInitThunk
+}
+{
+ bug_93932h
+ ThreadSanitizer:Race
+ ...
+ fun:av_parser_close
+ ...
+ fun:base::internal::RunnableAdapter::Run
+}
+{
+ bug_93932i
+ ThreadSanitizer:Race
+ fun:ff_simple_idct_add_mmx
+ ...
+ fun:BaseThreadInitThunk
+}
+{
+ bug_144928_a
+ ThreadSanitizer:Race
+ fun:google_breakpad::CrashGenerationServer::Handle*
+ fun:google_breakpad::CrashGenerationServer::OnPipeConnected
+ fun:RtlSetTimer
+ fun:RtlSetTimer
+ fun:TpReleaseTimer
+ fun:TpReleaseTimer
+ fun:RtlMultiByteToUnicodeSize
+ fun:TpCallbackMayRunLong
+ fun:TpCallbackMayRunLong
+ fun:BaseThreadInitThunk
+}
+{
+ bug_144928_b
+ ThreadSanitizer:Race
+ fun:google_breakpad::CrashGenerationServer::~CrashGenerationServer
+ fun:google_breakpad::CrashGenerationServer::`scalar deleting destructor'
+ fun:base::DefaultDeleter*
+ fun:base::internal::scoped_ptr_impl::~scoped_ptr_impl
+ fun:remoting::BreakpadWinDeathTest::~BreakpadWinDeathTest
+ fun:remoting::BreakpadWinDeathTest_TestAccessViolation_Test::`scalar deleting destructor'
+ fun:testing::Test::DeleteSelf_
+ fun:testing::internal::HandleExceptionsInMethodIfSupported
+}
+
+{
+ bug_146119
+ ThreadSanitizer:Race
+ ...
+ fun:GetAdaptersAddresses
+ ...
+ fun:base::internal::RunnableAdapter::Run
+}
+
+{
+ bug_157076_a
+ ThreadSanitizer:Race
+ fun:win32thread_worker
+ fun:_callthreadstartex
+ fun:_threadstartex
+ fun:BaseThreadInitThunk
+}
+
+{
+ bug_157076_b
+ ThreadSanitizer:Race
+ fun:memset
+ fun:_free_dbg_nolock
+ fun:_free_dbg
+ fun:_aligned_free_dbg
+ fun:_aligned_free
+}
+
+{
+ bug_157076_c
+ ThreadSanitizer:Race
+ fun:memset
+ fun:_heap_alloc_dbg_impl
+ fun:_nh_malloc_dbg_impl
+ fun:_nh_malloc_dbg
+ fun:_malloc_dbg
+ fun:_aligned_offset_malloc_dbg
+ fun:_aligned_malloc
+ fun:base::AlignedAlloc
+}
+
+{
+ bug_170334
+ ThreadSanitizer:Race
+ ...
+ fun:net::NetworkChangeNotifierWinTest::~NetworkChangeNotifierWinTest
+}
+
+{
+ bug_239350
+ ThreadSanitizer:Race
+ ...
+ fun:av_freep
+ fun:av_buffer_unref
+ fun:av_frame_unref
+ ...
+ fun:media::FFmpegVideoDecoder::Decode
+}
diff --git a/chromium/tools/valgrind/tsan_analyze.py b/chromium/tools/valgrind/tsan_analyze.py
new file mode 100755
index 00000000000..1950f6efcc7
--- /dev/null
+++ b/chromium/tools/valgrind/tsan_analyze.py
@@ -0,0 +1,278 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# tsan_analyze.py
+
+''' Given a ThreadSanitizer output file, parses errors and uniques them.'''
+
+import gdb_helper
+
+from collections import defaultdict
+import hashlib
+import logging
+import optparse
+import os
+import re
+import subprocess
+import sys
+import time
+
+import common
+
+# Global symbol table (ugh)
+TheAddressTable = None
+
+class _StackTraceLine(object):
+ def __init__(self, line, address, binary):
+ self.raw_line_ = line
+ self.address = address
+ self.binary = binary
+ def __str__(self):
+ global TheAddressTable
+ file, line = TheAddressTable.GetFileLine(self.binary, self.address)
+ if (file is None) or (line is None):
+ return self.raw_line_
+ else:
+ return self.raw_line_.replace(self.binary, '%s:%s' % (file, line))
+
+class TsanAnalyzer(object):
+ ''' Given a set of ThreadSanitizer output files, parse all the errors out of
+ them, unique them and output the results.'''
+
+ LOAD_LIB_RE = re.compile('--[0-9]+-- ([^(:]*) \((0x[0-9a-f]+)\)')
+ TSAN_LINE_RE = re.compile('==[0-9]+==\s*[#0-9]+\s*'
+ '([0-9A-Fa-fx]+):'
+ '(?:[^ ]* )*'
+ '([^ :\n]+)'
+ '')
+ THREAD_CREATION_STR = ("INFO: T.* "
+ "(has been created by T.* at this point|is program's main thread)")
+
+ SANITY_TEST_SUPPRESSION = ("ThreadSanitizer sanity test "
+ "(ToolsSanityTest.DataRace)")
+ TSAN_RACE_DESCRIPTION = "Possible data race"
+ TSAN_WARNING_DESCRIPTION = ("Unlocking a non-locked lock"
+ "|accessing an invalid lock"
+ "|which did not acquire this lock")
+ RACE_VERIFIER_LINE = "Confirmed a race|unexpected race"
+ TSAN_ASSERTION = "Assertion failed: "
+
+ def __init__(self, source_dir, use_gdb=False):
+ '''Reads in a set of files.
+
+ Args:
+ source_dir: Path to top of source tree for this build
+ '''
+
+ self._use_gdb = use_gdb
+ self._cur_testcase = None
+
+ def ReadLine(self):
+ self.line_ = self.cur_fd_.readline()
+ self.stack_trace_line_ = None
+ if not self._use_gdb:
+ return
+ global TheAddressTable
+ match = TsanAnalyzer.LOAD_LIB_RE.match(self.line_)
+ if match:
+ binary, ip = match.groups()
+ TheAddressTable.AddBinaryAt(binary, ip)
+ return
+ match = TsanAnalyzer.TSAN_LINE_RE.match(self.line_)
+ if match:
+ address, binary_name = match.groups()
+ stack_trace_line = _StackTraceLine(self.line_, address, binary_name)
+ TheAddressTable.Add(stack_trace_line.binary, stack_trace_line.address)
+ self.stack_trace_line_ = stack_trace_line
+
+ def ReadSection(self):
+ """ Example of a section:
+ ==4528== WARNING: Possible data race: {{{
+ ==4528== T20 (L{}):
+ ==4528== #0 MyTest::Foo1
+ ==4528== #1 MyThread::ThreadBody
+ ==4528== Concurrent write happened at this point:
+ ==4528== T19 (L{}):
+ ==4528== #0 MyTest::Foo2
+ ==4528== #1 MyThread::ThreadBody
+ ==4528== }}}
+ ------- suppression -------
+ {
+ <Put your suppression name here>
+ ThreadSanitizer:Race
+ fun:MyTest::Foo1
+ fun:MyThread::ThreadBody
+ }
+ ------- end suppression -------
+ """
+ result = [self.line_]
+ if re.search("{{{", self.line_):
+ while not re.search('}}}', self.line_):
+ self.ReadLine()
+ if self.stack_trace_line_ is None:
+ result.append(self.line_)
+ else:
+ result.append(self.stack_trace_line_)
+ self.ReadLine()
+ if re.match('-+ suppression -+', self.line_):
+ # We need to calculate the suppression hash and prepend a line like
+ # "Suppression (error hash=#0123456789ABCDEF#):" so the buildbot can
+ # extract the suppression snippet.
+ supp = ""
+ while not re.match('-+ end suppression -+', self.line_):
+ self.ReadLine()
+ supp += self.line_
+ self.ReadLine()
+ if self._cur_testcase:
+ result.append("The report came from the `%s` test.\n" % \
+ self._cur_testcase)
+ result.append("Suppression (error hash=#%016X#):\n" % \
+ (int(hashlib.md5(supp).hexdigest()[:16], 16)))
+ result.append(" For more info on using suppressions see "
+ "http://dev.chromium.org/developers/how-tos/using-valgrind/threadsanitizer#TOC-Suppressing-data-races\n")
+ result.append(supp)
+ else:
+ self.ReadLine()
+
+ return result
+
+ def ReadTillTheEnd(self):
+ result = [self.line_]
+ while self.line_:
+ self.ReadLine()
+ result.append(self.line_)
+ return result
+
+ def ParseReportFile(self, filename):
+ '''Parses a report file and returns a list of ThreadSanitizer reports.
+
+
+ Args:
+ filename: report filename.
+ Returns:
+ list of (list of (str iff self._use_gdb, _StackTraceLine otherwise)).
+ '''
+ ret = []
+ self.cur_fd_ = open(filename, 'r')
+
+ while True:
+ # Read ThreadSanitizer reports.
+ self.ReadLine()
+ if not self.line_:
+ break
+
+ while True:
+ tmp = []
+ while re.search(TsanAnalyzer.RACE_VERIFIER_LINE, self.line_):
+ tmp.append(self.line_)
+ self.ReadLine()
+ while re.search(TsanAnalyzer.THREAD_CREATION_STR, self.line_):
+ tmp.extend(self.ReadSection())
+ if re.search(TsanAnalyzer.TSAN_RACE_DESCRIPTION, self.line_):
+ tmp.extend(self.ReadSection())
+ ret.append(tmp) # includes RaceVerifier and thread creation stacks
+ elif (re.search(TsanAnalyzer.TSAN_WARNING_DESCRIPTION, self.line_) and
+ not common.IsWindows()): # workaround for http://crbug.com/53198
+ tmp.extend(self.ReadSection())
+ ret.append(tmp)
+ else:
+ break
+
+ tmp = []
+ if re.search(TsanAnalyzer.TSAN_ASSERTION, self.line_):
+ tmp.extend(self.ReadTillTheEnd())
+ ret.append(tmp)
+ break
+
+ match = re.search("used_suppression:\s+([0-9]+)\s(.*)", self.line_)
+ if match:
+ count, supp_name = match.groups()
+ count = int(count)
+ self.used_suppressions[supp_name] += count
+ self.cur_fd_.close()
+ return ret
+
+ def GetReports(self, files):
+ '''Extracts reports from a set of files.
+
+ Reads a set of files and returns a list of all discovered
+ ThreadSanitizer race reports. As a side effect, populates
+ self.used_suppressions with appropriate info.
+ '''
+
+ global TheAddressTable
+ if self._use_gdb:
+ TheAddressTable = gdb_helper.AddressTable()
+ else:
+ TheAddressTable = None
+ reports = []
+ self.used_suppressions = defaultdict(int)
+ for file in files:
+ reports.extend(self.ParseReportFile(file))
+ if self._use_gdb:
+ TheAddressTable.ResolveAll()
+ # Make each line of each report a string.
+ reports = map(lambda(x): map(str, x), reports)
+ return [''.join(report_lines) for report_lines in reports]
+
+ def Report(self, files, testcase, check_sanity=False):
+ '''Reads in a set of files and prints ThreadSanitizer report.
+
+ Args:
+ files: A list of filenames.
+ check_sanity: if true, search for SANITY_TEST_SUPPRESSIONS
+ '''
+
+ # We set up _cur_testcase class-wide variable to avoid passing it through
+ # about 5 functions.
+ self._cur_testcase = testcase
+ reports = self.GetReports(files)
+ self._cur_testcase = None # just in case, shouldn't be used anymore
+
+ common.PrintUsedSuppressionsList(self.used_suppressions)
+
+
+ retcode = 0
+ if reports:
+ sys.stdout.flush()
+ sys.stderr.flush()
+ logging.info("FAIL! Found %i report(s)" % len(reports))
+ for report in reports:
+ logging.info('\n' + report)
+ sys.stdout.flush()
+ retcode = -1
+
+ # Report tool's insanity even if there were errors.
+ if (check_sanity and
+ TsanAnalyzer.SANITY_TEST_SUPPRESSION not in self.used_suppressions):
+ logging.error("FAIL! Sanity check failed!")
+ retcode = -3
+
+ if retcode != 0:
+ return retcode
+
+ logging.info("PASS: No reports found")
+ return 0
+
+
+def main():
+ '''For testing only. The TsanAnalyzer class should be imported instead.'''
+ parser = optparse.OptionParser("usage: %prog [options] <files to analyze>")
+ parser.add_option("", "--source_dir",
+ help="path to top of source tree for this build"
+ "(used to normalize source paths in baseline)")
+
+ (options, args) = parser.parse_args()
+ if not args:
+ parser.error("no filename specified")
+ filenames = args
+
+ logging.getLogger().setLevel(logging.INFO)
+ analyzer = TsanAnalyzer(options.source_dir, use_gdb=True)
+ return analyzer.Report(filenames, None)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/valgrind/tsan_v2/ignores.txt b/chromium/tools/valgrind/tsan_v2/ignores.txt
new file mode 100644
index 00000000000..13a6857b42a
--- /dev/null
+++ b/chromium/tools/valgrind/tsan_v2/ignores.txt
@@ -0,0 +1,16 @@
+# The rules in this file are only applied at compile time.
+# Because the Chrome buildsystem does not automatically touch the files
+# mentioned here, changing this file requires clobbering all TSan v2 bots.
+#
+# Please think twice before you add or remove these rules.
+# Data races should typically go to suppressions.txt.
+
+# See http://crbug.com/102327
+fun:*ThreadData*Initialize*
+
+# Known benign races on histograms. See http://crbug.com/62694.
+src:base/metrics/histogram_samples.cc
+src:base/metrics/sample_vector.cc
+
+# See http://crbug.com/172104
+fun:*v8*internal*ThreadEntry*
diff --git a/chromium/tools/valgrind/tsan_v2/suppressions.txt b/chromium/tools/valgrind/tsan_v2/suppressions.txt
new file mode 100644
index 00000000000..fbcaacb295f
--- /dev/null
+++ b/chromium/tools/valgrind/tsan_v2/suppressions.txt
@@ -0,0 +1,121 @@
+# False positives in libflashplayer.so and libglib.so. Since we don't
+# instrument them, we cannot reason about the synchronization in them.
+race:libflashplayer.so
+race:libglib*.so
+
+# Intentional race in ToolsSanityTest.DataRace in base_unittests.
+race:base/tools_sanity_unittest.cc
+
+# Data race on WatchdogCounter [test-only]
+race:base/threading/watchdog_unittest.cc
+
+# Races in libevent, http://crbug.com/23244
+race:libevent/event.c
+
+# http://crbug.com/46840
+race:history::HistoryBackend::DeleteFTSIndexDatabases
+race:history::InMemoryHistoryBackend::Init
+
+# http://crbug.com/84094
+race:sqlite3StatusSet
+race:pcache1EnforceMaxPage
+race:pcache1AllocPage
+
+# http://crbug.com/102327.
+# Test-only race, won't fix.
+race:tracked_objects::ThreadData::ShutdownSingleThreadedCleanup
+
+# http://crbug.com/115540
+race:*GetCurrentThreadIdentifier
+
+# http://crbug.com/120808
+race:base/threading/watchdog.cc
+
+# http://crbug.com/157586
+race:third_party/libvpx/source/libvpx/vp8/decoder/threading.c
+
+# http://crbug.com/158718
+race:third_party/ffmpeg/libavcodec/pthread.c
+race:third_party/ffmpeg/libavcodec/vp8.c
+race:third_party/ffmpeg/libavutil/mem.c
+race:*HashFrameForTesting
+race:third_party/ffmpeg/libavcodec/h264pred.c
+race:media::ReleaseData
+
+# http://crbug.com/158922
+race:third_party/libvpx/source/libvpx/vp8/encoder/*
+
+# See http://crbug.com/181502
+race:_M_rep
+race:_M_is_leaked
+
+# http://crbug.com/189177
+race:thread_manager
+race:v8::Locker::Initialize
+
+# http://crbug.com/223352
+race:uprv_malloc_46
+race:uprv_realloc_46
+
+# http://crbug.com/223955
+race:PassRefPtr
+
+# http://crbug.com/224617
+race:base::debug::TraceEventTestFixture_TraceSampling_Test::TestBody
+
+# http://crbug.com/244368
+race:skia::BeginPlatformPaint
+
+# http://crbug.com/244385
+race:unixTempFileDir
+
+# http://crbug.com/244774
+race:webrtc::RTPReceiver::ProcessBitrate
+race:webrtc::RTPSender::ProcessBitrate
+race:webrtc::VideoCodingModuleImpl::Decode
+race:webrtc::RTPSender::SendOutgoingData
+race:webrtc::VP8EncoderImpl::GetEncodedPartitions
+race:webrtc::VP8EncoderImpl::Encode
+race:webrtc::ViEEncoder::DeliverFrame
+
+# http://crbug.com/246968
+race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback
+
+# http://crbug.com/246970
+race:webrtc::EventPosix::StartTimer
+
+# http://crbug.com/246974
+race:content::GpuWatchdogThread::CheckArmed
+
+# http://crbug.com/248101
+race:sqlite3Config
+race:mem0
+
+# http://crbug.com/257396
+race:base::debug::TraceEventTestFixture_TraceSamplingScope_Test::TestBody
+
+# http://crbug.com/257543
+race:*GetObjectFromEntryAddress
+
+# http://crbug.com/268924
+race:base::g_power_monitor
+race:base::PowerMonitor::PowerMonitor
+race:base::PowerMonitor::AddObserver
+
+# http://crbug.com/268941
+race:tracked_objects::ThreadData::tls_index_
+
+# http://crbug.com/268946
+race:CommandLine::HasSwitch
+
+# http://crbug.com/269965
+race:DesktopMediaPickerModelTest_UpdateThumbnail_Test
+
+# http://crbug.com/270037
+race:gLibCleanupFunctions
+
+# http://crbug.com/270675
+race:net::RuleBasedHostResolverProc::Resolve
+
+# http://crbug.com/272095
+race:base::g_top_manager
diff --git a/chromium/tools/valgrind/unused_suppressions.py b/chromium/tools/valgrind/unused_suppressions.py
new file mode 100755
index 00000000000..0f336f136d0
--- /dev/null
+++ b/chromium/tools/valgrind/unused_suppressions.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+import urllib2
+
+import suppressions
+
+
+def main():
+ supp = suppressions.GetSuppressions()
+
+ all_supps = []
+ for supps in supp.values():
+ all_supps += [s.description for s in supps]
+ sys.stdout.write(urllib2.urlopen(
+ 'http://chromium-build-logs.appspot.com/unused_suppressions',
+ '\n'.join(all_supps)).read())
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/valgrind/valgrind.sh b/chromium/tools/valgrind/valgrind.sh
new file mode 100755
index 00000000000..4034c4bc2c3
--- /dev/null
+++ b/chromium/tools/valgrind/valgrind.sh
@@ -0,0 +1,124 @@
+#!/bin/bash
+
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is a small script for manually launching valgrind, along with passing
+# it the suppression file, and some helpful arguments (automatically attaching
+# the debugger on failures, etc). Run it from your repo root, something like:
+# $ sh ./tools/valgrind/valgrind.sh ./out/Debug/chrome
+#
+# This is mostly intended for running the chrome browser interactively.
+# To run unit tests, you probably want to run chrome_tests.sh instead.
+# That's the script used by the valgrind buildbot.
+
+export THISDIR=`dirname $0`
+
+setup_memcheck() {
+ RUN_COMMAND="valgrind"
+ GDB=gdb
+ EXE_INFO=$(file $1)
+ if [[ $? -eq 0 ]]; then
+ # Prefer a gdb that matches the executable if it's available.
+ if [[ "$EXE_INFO" == *32-bit* && -x /usr/bin/gdb32 ]]; then
+ GDB="/usr/bin/gdb32";
+ elif [[ "$EXE_INFO" == *64-bit* && -x /usr/bin/gdb64 ]]; then
+ GDB="/usr/bin/gdb64";
+ fi
+ fi
+
+ # Prompt to attach gdb when there was an error detected.
+ DEFAULT_TOOL_FLAGS=("--db-command=$GDB -nw %f %p" "--db-attach=yes" \
+ # Keep the registers in gdb in sync with the code.
+ "--vex-iropt-register-updates=allregs-at-mem-access" \
+ # Overwrite newly allocated or freed objects
+ # with 0x41 to catch inproper use.
+ "--malloc-fill=41" "--free-fill=41" \
+ # Increase the size of stacks being tracked.
+ "--num-callers=30")
+}
+
+setup_tsan() {
+ RUN_COMMAND="valgrind-tsan.sh"
+ IGNORE_FILE="$THISDIR/tsan/ignores.txt"
+ DEFAULT_TOOL_FLAGS=("--announce-threads" "--pure-happens-before=yes" \
+ "--ignore=$IGNORE_FILE")
+}
+
+setup_unknown() {
+ echo "Unknown tool \"$TOOL_NAME\" specified, the result is not guaranteed"
+ DEFAULT_TOOL_FLAGS=()
+}
+
+set -e
+
+if [ $# -eq 0 ]; then
+ echo "usage: <command to run> <arguments ...>"
+ exit 1
+fi
+
+TOOL_NAME="memcheck"
+declare -a DEFAULT_TOOL_FLAGS[0]
+
+# Select a tool different from memcheck with --tool=TOOL as a first argument
+TMP_STR=`echo $1 | sed 's/^\-\-tool=//'`
+if [ "$TMP_STR" != "$1" ]; then
+ TOOL_NAME="$TMP_STR"
+ shift
+fi
+
+if echo "$@" | grep "\-\-tool" ; then
+ echo "--tool=TOOL must be the first argument" >&2
+ exit 1
+fi
+
+case $TOOL_NAME in
+ memcheck*) setup_memcheck "$1";;
+ tsan*) setup_tsan;;
+ *) setup_unknown;;
+esac
+
+
+SUPPRESSIONS="$THISDIR/$TOOL_NAME/suppressions.txt"
+
+CHROME_VALGRIND=`sh $THISDIR/locate_valgrind.sh`
+if [ "$CHROME_VALGRIND" = "" ]
+then
+ # locate_valgrind.sh failed
+ exit 1
+fi
+echo "Using valgrind binaries from ${CHROME_VALGRIND}"
+
+set -x
+PATH="${CHROME_VALGRIND}/bin:$PATH"
+# We need to set these variables to override default lib paths hard-coded into
+# Valgrind binary.
+export VALGRIND_LIB="$CHROME_VALGRIND/lib/valgrind"
+export VALGRIND_LIB_INNER="$CHROME_VALGRIND/lib/valgrind"
+
+# G_SLICE=always-malloc: make glib use system malloc
+# NSS_DISABLE_UNLOAD=1: make nss skip dlclosing dynamically loaded modules,
+# which would result in "obj:*" in backtraces.
+# NSS_DISABLE_ARENA_FREE_LIST=1: make nss use system malloc
+# G_DEBUG=fatal_warnings: make GTK abort on any critical or warning assertions.
+# If it crashes on you in the Options menu, you hit bug 19751,
+# comment out the G_DEBUG=fatal_warnings line.
+#
+# GTEST_DEATH_TEST_USE_FORK=1: make gtest death tests valgrind-friendly
+#
+# When everyone has the latest valgrind, we might want to add
+# --show-possibly-lost=no
+# to ignore possible but not definite leaks.
+
+G_SLICE=always-malloc \
+NSS_DISABLE_UNLOAD=1 \
+NSS_DISABLE_ARENA_FREE_LIST=1 \
+G_DEBUG=fatal_warnings \
+GTEST_DEATH_TEST_USE_FORK=1 \
+$RUN_COMMAND \
+ --trace-children=yes \
+ --leak-check=yes \
+ --suppressions="$SUPPRESSIONS" \
+ "${DEFAULT_TOOL_FLAGS[@]}" \
+ "$@"
diff --git a/chromium/tools/valgrind/valgrind_test.py b/chromium/tools/valgrind/valgrind_test.py
new file mode 100644
index 00000000000..cafe7f942fe
--- /dev/null
+++ b/chromium/tools/valgrind/valgrind_test.py
@@ -0,0 +1,1228 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs an exe through Valgrind and puts the intermediate files in a
+directory.
+"""
+
+import datetime
+import glob
+import logging
+import optparse
+import os
+import re
+import shutil
+import stat
+import subprocess
+import sys
+import tempfile
+
+import common
+
+import drmemory_analyze
+import memcheck_analyze
+import tsan_analyze
+
+class BaseTool(object):
+ """Abstract class for running Valgrind-, PIN-based and other dynamic
+ error detector tools.
+
+ Always subclass this and implement ToolCommand with framework- and
+ tool-specific stuff.
+ """
+
+ def __init__(self):
+ temp_parent_dir = None
+ self.log_parent_dir = ""
+ if common.IsWindows():
+ # gpu process on Windows Vista+ runs at Low Integrity and can only
+ # write to certain directories (http://crbug.com/119131)
+ #
+ # TODO(bruening): if scripts die in middle and don't clean up temp
+ # dir, we'll accumulate files in profile dir. should remove
+ # really old files automatically.
+ profile = os.getenv("USERPROFILE")
+ if profile:
+ self.log_parent_dir = profile + "\\AppData\\LocalLow\\"
+ if os.path.exists(self.log_parent_dir):
+ self.log_parent_dir = common.NormalizeWindowsPath(self.log_parent_dir)
+ temp_parent_dir = self.log_parent_dir
+ # Generated every time (even when overridden)
+ self.temp_dir = tempfile.mkdtemp(prefix="vg_logs_", dir=temp_parent_dir)
+ self.log_dir = self.temp_dir # overridable by --keep_logs
+ self.option_parser_hooks = []
+ # TODO(glider): we may not need some of the env vars on some of the
+ # platforms.
+ self._env = {
+ "G_SLICE" : "always-malloc",
+ "NSS_DISABLE_UNLOAD" : "1",
+ "NSS_DISABLE_ARENA_FREE_LIST" : "1",
+ "GTEST_DEATH_TEST_USE_FORK": "1",
+ }
+
+ def ToolName(self):
+ raise NotImplementedError, "This method should be implemented " \
+ "in the tool-specific subclass"
+
+ def Analyze(self, check_sanity=False):
+ raise NotImplementedError, "This method should be implemented " \
+ "in the tool-specific subclass"
+
+ def RegisterOptionParserHook(self, hook):
+ # Frameworks and tools can add their own flags to the parser.
+ self.option_parser_hooks.append(hook)
+
+ def CreateOptionParser(self):
+ # Defines Chromium-specific flags.
+ self._parser = optparse.OptionParser("usage: %prog [options] <program to "
+ "test>")
+ self._parser.disable_interspersed_args()
+ self._parser.add_option("-t", "--timeout",
+ dest="timeout", metavar="TIMEOUT", default=10000,
+ help="timeout in seconds for the run (default 10000)")
+ self._parser.add_option("", "--build_dir",
+ help="the location of the compiler output")
+ self._parser.add_option("", "--source_dir",
+ help="path to top of source tree for this build"
+ "(used to normalize source paths in baseline)")
+ self._parser.add_option("", "--gtest_filter", default="",
+ help="which test case to run")
+ self._parser.add_option("", "--gtest_repeat",
+ help="how many times to run each test")
+ self._parser.add_option("", "--gtest_print_time", action="store_true",
+ default=False,
+ help="show how long each test takes")
+ self._parser.add_option("", "--ignore_exit_code", action="store_true",
+ default=False,
+ help="ignore exit code of the test "
+ "(e.g. test failures)")
+ self._parser.add_option("", "--keep_logs", action="store_true",
+ default=False,
+ help="store memory tool logs in the <tool>.logs "
+ "directory instead of /tmp.\nThis can be "
+ "useful for tool developers/maintainers.\n"
+ "Please note that the <tool>.logs directory "
+ "will be clobbered on tool startup.")
+
+ # To add framework- or tool-specific flags, please add a hook using
+ # RegisterOptionParserHook in the corresponding subclass.
+ # See ValgrindTool and ThreadSanitizerBase for examples.
+ for hook in self.option_parser_hooks:
+ hook(self, self._parser)
+
+ def ParseArgv(self, args):
+ self.CreateOptionParser()
+
+ # self._tool_flags will store those tool flags which we don't parse
+ # manually in this script.
+ self._tool_flags = []
+ known_args = []
+
+ """ We assume that the first argument not starting with "-" is a program
+ name and all the following flags should be passed to the program.
+ TODO(timurrrr): customize optparse instead
+ """
+ while len(args) > 0 and args[0][:1] == "-":
+ arg = args[0]
+ if (arg == "--"):
+ break
+ if self._parser.has_option(arg.split("=")[0]):
+ known_args += [arg]
+ else:
+ self._tool_flags += [arg]
+ args = args[1:]
+
+ if len(args) > 0:
+ known_args += args
+
+ self._options, self._args = self._parser.parse_args(known_args)
+
+ self._timeout = int(self._options.timeout)
+ self._source_dir = self._options.source_dir
+ if self._options.keep_logs:
+ # log_parent_dir has trailing slash if non-empty
+ self.log_dir = self.log_parent_dir + "%s.logs" % self.ToolName()
+ if os.path.exists(self.log_dir):
+ shutil.rmtree(self.log_dir)
+ os.mkdir(self.log_dir)
+ logging.info("Logs are in " + self.log_dir)
+
+ self._ignore_exit_code = self._options.ignore_exit_code
+ if self._options.gtest_filter != "":
+ self._args.append("--gtest_filter=%s" % self._options.gtest_filter)
+ if self._options.gtest_repeat:
+ self._args.append("--gtest_repeat=%s" % self._options.gtest_repeat)
+ if self._options.gtest_print_time:
+ self._args.append("--gtest_print_time")
+
+ return True
+
+ def Setup(self, args):
+ return self.ParseArgv(args)
+
+ def ToolCommand(self):
+ raise NotImplementedError, "This method should be implemented " \
+ "in the tool-specific subclass"
+
+ def Cleanup(self):
+ # You may override it in the tool-specific subclass
+ pass
+
+ def Execute(self):
+ """ Execute the app to be tested after successful instrumentation.
+ Full execution command-line provided by subclassers via proc."""
+ logging.info("starting execution...")
+ proc = self.ToolCommand()
+ for var in self._env:
+ common.PutEnvAndLog(var, self._env[var])
+ return common.RunSubprocess(proc, self._timeout)
+
+ def RunTestsAndAnalyze(self, check_sanity):
+ exec_retcode = self.Execute()
+ analyze_retcode = self.Analyze(check_sanity)
+
+ if analyze_retcode:
+ logging.error("Analyze failed.")
+ logging.info("Search the log for '[ERROR]' to see the error reports.")
+ return analyze_retcode
+
+ if exec_retcode:
+ if self._ignore_exit_code:
+ logging.info("Test execution failed, but the exit code is ignored.")
+ else:
+ logging.error("Test execution failed.")
+ return exec_retcode
+ else:
+ logging.info("Test execution completed successfully.")
+
+ if not analyze_retcode:
+ logging.info("Analysis completed successfully.")
+
+ return 0
+
+ def Main(self, args, check_sanity, min_runtime_in_seconds):
+ """Call this to run through the whole process: Setup, Execute, Analyze"""
+ start_time = datetime.datetime.now()
+ retcode = -1
+ if self.Setup(args):
+ retcode = self.RunTestsAndAnalyze(check_sanity)
+ shutil.rmtree(self.temp_dir, ignore_errors=True)
+ self.Cleanup()
+ else:
+ logging.error("Setup failed")
+ end_time = datetime.datetime.now()
+ runtime_in_seconds = (end_time - start_time).seconds
+ hours = runtime_in_seconds / 3600
+ seconds = runtime_in_seconds % 3600
+ minutes = seconds / 60
+ seconds = seconds % 60
+ logging.info("elapsed time: %02d:%02d:%02d" % (hours, minutes, seconds))
+ if (min_runtime_in_seconds > 0 and
+ runtime_in_seconds < min_runtime_in_seconds):
+ logging.error("Layout tests finished too quickly. "
+ "It should have taken at least %d seconds. "
+ "Something went wrong?" % min_runtime_in_seconds)
+ retcode = -1
+ return retcode
+
+ def Run(self, args, module, min_runtime_in_seconds=0):
+ MODULES_TO_SANITY_CHECK = ["base"]
+
+ # TODO(timurrrr): this is a temporary workaround for http://crbug.com/47844
+ if self.ToolName() == "tsan" and common.IsMac():
+ MODULES_TO_SANITY_CHECK = []
+
+ check_sanity = module in MODULES_TO_SANITY_CHECK
+ return self.Main(args, check_sanity, min_runtime_in_seconds)
+
+
+class ValgrindTool(BaseTool):
+ """Abstract class for running Valgrind tools.
+
+ Always subclass this and implement ToolSpecificFlags() and
+ ExtendOptionParser() for tool-specific stuff.
+ """
+ def __init__(self):
+ super(ValgrindTool, self).__init__()
+ self.RegisterOptionParserHook(ValgrindTool.ExtendOptionParser)
+
+ def UseXML(self):
+ # Override if tool prefers nonxml output
+ return True
+
+ def SelfContained(self):
+ # Returns true iff the tool is distibuted as a self-contained
+ # .sh script (e.g. ThreadSanitizer)
+ return False
+
+ def ExtendOptionParser(self, parser):
+ parser.add_option("", "--suppressions", default=[],
+ action="append",
+ help="path to a valgrind suppression file")
+ parser.add_option("", "--indirect", action="store_true",
+ default=False,
+ help="set BROWSER_WRAPPER rather than "
+ "running valgrind directly")
+ parser.add_option("", "--indirect_webkit_layout", action="store_true",
+ default=False,
+ help="set --wrapper rather than running Dr. Memory "
+ "directly.")
+ parser.add_option("", "--trace_children", action="store_true",
+ default=False,
+ help="also trace child processes")
+ parser.add_option("", "--num-callers",
+ dest="num_callers", default=30,
+ help="number of callers to show in stack traces")
+ parser.add_option("", "--generate_dsym", action="store_true",
+ default=False,
+ help="Generate .dSYM file on Mac if needed. Slow!")
+
+ def Setup(self, args):
+ if not BaseTool.Setup(self, args):
+ return False
+ if common.IsMac():
+ self.PrepareForTestMac()
+ return True
+
+ def PrepareForTestMac(self):
+ """Runs dsymutil if needed.
+
+ Valgrind for Mac OS X requires that debugging information be in a .dSYM
+ bundle generated by dsymutil. It is not currently able to chase DWARF
+ data into .o files like gdb does, so executables without .dSYM bundles or
+ with the Chromium-specific "fake_dsym" bundles generated by
+ build/mac/strip_save_dsym won't give source file and line number
+ information in valgrind.
+
+ This function will run dsymutil if the .dSYM bundle is missing or if
+ it looks like a fake_dsym. A non-fake dsym that already exists is assumed
+ to be up-to-date.
+ """
+ test_command = self._args[0]
+ dsym_bundle = self._args[0] + '.dSYM'
+ dsym_file = os.path.join(dsym_bundle, 'Contents', 'Resources', 'DWARF',
+ os.path.basename(test_command))
+ dsym_info_plist = os.path.join(dsym_bundle, 'Contents', 'Info.plist')
+
+ needs_dsymutil = True
+ saved_test_command = None
+
+ if os.path.exists(dsym_file) and os.path.exists(dsym_info_plist):
+ # Look for the special fake_dsym tag in dsym_info_plist.
+ dsym_info_plist_contents = open(dsym_info_plist).read()
+
+ if not re.search('^\s*<key>fake_dsym</key>$', dsym_info_plist_contents,
+ re.MULTILINE):
+ # fake_dsym is not set, this is a real .dSYM bundle produced by
+ # dsymutil. dsymutil does not need to be run again.
+ needs_dsymutil = False
+ else:
+ # fake_dsym is set. dsym_file is a copy of the original test_command
+ # before it was stripped. Copy it back to test_command so that
+ # dsymutil has unstripped input to work with. Move the stripped
+ # test_command out of the way, it will be restored when this is
+ # done.
+ saved_test_command = test_command + '.stripped'
+ os.rename(test_command, saved_test_command)
+ shutil.copyfile(dsym_file, test_command)
+ shutil.copymode(saved_test_command, test_command)
+
+ if needs_dsymutil:
+ if self._options.generate_dsym:
+ # Remove the .dSYM bundle if it exists.
+ shutil.rmtree(dsym_bundle, True)
+
+ dsymutil_command = ['dsymutil', test_command]
+
+ # dsymutil is crazy slow. Ideally we'd have a timeout here,
+ # but common.RunSubprocess' timeout is only checked
+ # after each line of output; dsymutil is silent
+ # until the end, and is then killed, which is silly.
+ common.RunSubprocess(dsymutil_command)
+
+ if saved_test_command:
+ os.rename(saved_test_command, test_command)
+ else:
+ logging.info("No real .dSYM for test_command. Line numbers will "
+ "not be shown. Either tell xcode to generate .dSYM "
+ "file, or use --generate_dsym option to this tool.")
+
+ def ToolCommand(self):
+ """Get the valgrind command to run."""
+ # Note that self._args begins with the exe to be run.
+ tool_name = self.ToolName()
+
+ # Construct the valgrind command.
+ if self.SelfContained():
+ proc = ["valgrind-%s.sh" % tool_name]
+ else:
+ proc = ["valgrind", "--tool=%s" % tool_name]
+
+ proc += ["--num-callers=%i" % int(self._options.num_callers)]
+
+ if self._options.trace_children:
+ proc += ["--trace-children=yes"]
+ proc += ["--trace-children-skip='*dbus-daemon*'"]
+ proc += ["--trace-children-skip='*dbus-launch*'"]
+ proc += ["--trace-children-skip='*perl*'"]
+ proc += ["--trace-children-skip='*python*'"]
+ # This is really Python, but for some reason Valgrind follows it.
+ proc += ["--trace-children-skip='*lsb_release*'"]
+
+ proc += self.ToolSpecificFlags()
+ proc += self._tool_flags
+
+ suppression_count = 0
+ for suppression_file in self._options.suppressions:
+ if os.path.exists(suppression_file):
+ suppression_count += 1
+ proc += ["--suppressions=%s" % suppression_file]
+
+ if not suppression_count:
+ logging.warning("WARNING: NOT USING SUPPRESSIONS!")
+
+ logfilename = self.log_dir + ("/%s." % tool_name) + "%p"
+ if self.UseXML():
+ proc += ["--xml=yes", "--xml-file=" + logfilename]
+ else:
+ proc += ["--log-file=" + logfilename]
+
+ # The Valgrind command is constructed.
+
+ # Valgrind doesn't play nice with the Chrome sandbox. Empty this env var
+ # set by runtest.py to disable the sandbox.
+ if os.environ.get("CHROME_DEVEL_SANDBOX", None):
+ logging.info("Removing CHROME_DEVEL_SANDBOX fron environment")
+ os.environ["CHROME_DEVEL_SANDBOX"] = ''
+
+ # Handle --indirect_webkit_layout separately.
+ if self._options.indirect_webkit_layout:
+ # Need to create the wrapper before modifying |proc|.
+ wrapper = self.CreateBrowserWrapper(proc, webkit=True)
+ proc = self._args
+ proc.append("--wrapper")
+ proc.append(wrapper)
+ return proc
+
+ if self._options.indirect:
+ wrapper = self.CreateBrowserWrapper(proc)
+ os.environ["BROWSER_WRAPPER"] = wrapper
+ logging.info('export BROWSER_WRAPPER=' + wrapper)
+ proc = []
+ proc += self._args
+ return proc
+
+ def ToolSpecificFlags(self):
+ raise NotImplementedError, "This method should be implemented " \
+ "in the tool-specific subclass"
+
+ def CreateBrowserWrapper(self, proc, webkit=False):
+ """The program being run invokes Python or something else that can't stand
+ to be valgrinded, and also invokes the Chrome browser. In this case, use a
+ magic wrapper to only valgrind the Chrome browser. Build the wrapper here.
+ Returns the path to the wrapper. It's up to the caller to use the wrapper
+ appropriately.
+ """
+ command = " ".join(proc)
+ # Add the PID of the browser wrapper to the logfile names so we can
+ # separate log files for different UI tests at the analyze stage.
+ command = command.replace("%p", "$$.%p")
+
+ (fd, indirect_fname) = tempfile.mkstemp(dir=self.log_dir,
+ prefix="browser_wrapper.",
+ text=True)
+ f = os.fdopen(fd, "w")
+ f.write('#!/bin/bash\n'
+ 'echo "Started Valgrind wrapper for this test, PID=$$" >&2\n')
+
+ f.write('DIR=`dirname $0`\n'
+ 'TESTNAME_FILE=$DIR/testcase.$$.name\n\n')
+
+ if webkit:
+ # Webkit layout_tests pass the URL as the first line of stdin.
+ f.write('tee $TESTNAME_FILE | %s "$@"\n' % command)
+ else:
+ # Try to get the test case name by looking at the program arguments.
+ # i.e. Chromium ui_tests used --test-name arg.
+ # TODO(timurrrr): This doesn't handle "--test-name Test.Name"
+ # TODO(timurrrr): ui_tests are dead. Where do we use the non-webkit
+ # wrapper now? browser_tests? What do they do?
+ f.write('for arg in $@\ndo\n'
+ ' if [[ "$arg" =~ --test-name=(.*) ]]\n then\n'
+ ' echo ${BASH_REMATCH[1]} >$TESTNAME_FILE\n'
+ ' fi\n'
+ 'done\n\n'
+ '%s "$@"\n' % command)
+
+ f.close()
+ os.chmod(indirect_fname, stat.S_IRUSR|stat.S_IXUSR)
+ return indirect_fname
+
+ def CreateAnalyzer(self):
+ raise NotImplementedError, "This method should be implemented " \
+ "in the tool-specific subclass"
+
+ def GetAnalyzeResults(self, check_sanity=False):
+ # Glob all the files in the log directory
+ filenames = glob.glob(self.log_dir + "/" + self.ToolName() + ".*")
+
+ # If we have browser wrapper, the logfiles are named as
+ # "toolname.wrapper_PID.valgrind_PID".
+ # Let's extract the list of wrapper_PIDs and name it ppids
+ ppids = set([int(f.split(".")[-2]) \
+ for f in filenames if re.search("\.[0-9]+\.[0-9]+$", f)])
+
+ analyzer = self.CreateAnalyzer()
+ if len(ppids) == 0:
+ # Fast path - no browser wrapper was set.
+ return analyzer.Report(filenames, None, check_sanity)
+
+ ret = 0
+ for ppid in ppids:
+ testcase_name = None
+ try:
+ f = open(self.log_dir + ("/testcase.%d.name" % ppid))
+ testcase_name = f.read().strip()
+ f.close()
+ wk_layout_prefix="third_party/WebKit/LayoutTests/"
+ wk_prefix_at = testcase_name.rfind(wk_layout_prefix)
+ if wk_prefix_at != -1:
+ testcase_name = testcase_name[wk_prefix_at + len(wk_layout_prefix):]
+ except IOError:
+ pass
+ print "====================================================="
+ print " Below is the report for valgrind wrapper PID=%d." % ppid
+ if testcase_name:
+ print " It was used while running the `%s` test." % testcase_name
+ else:
+ print " You can find the corresponding test"
+ print " by searching the above log for 'PID=%d'" % ppid
+ sys.stdout.flush()
+
+ ppid_filenames = [f for f in filenames \
+ if re.search("\.%d\.[0-9]+$" % ppid, f)]
+ # check_sanity won't work with browser wrappers
+ assert check_sanity == False
+ ret |= analyzer.Report(ppid_filenames, testcase_name)
+ print "====================================================="
+ sys.stdout.flush()
+
+ if ret != 0:
+ print ""
+ print "The Valgrind reports are grouped by test names."
+ print "Each test has its PID printed in the log when the test was run"
+ print "and at the beginning of its Valgrind report."
+ print "Hint: you can search for the reports by Ctrl+F -> `=#`"
+ sys.stdout.flush()
+
+ return ret
+
+
+# TODO(timurrrr): Split into a separate file.
+class Memcheck(ValgrindTool):
+ """Memcheck
+ Dynamic memory error detector for Linux & Mac
+
+ http://valgrind.org/info/tools.html#memcheck
+ """
+
+ def __init__(self):
+ super(Memcheck, self).__init__()
+ self.RegisterOptionParserHook(Memcheck.ExtendOptionParser)
+
+ def ToolName(self):
+ return "memcheck"
+
+ def ExtendOptionParser(self, parser):
+ parser.add_option("--leak-check", "--leak_check", type="string",
+ default="yes", # --leak-check=yes is equivalent of =full
+ help="perform leak checking at the end of the run")
+ parser.add_option("", "--show_all_leaks", action="store_true",
+ default=False,
+ help="also show less blatant leaks")
+ parser.add_option("", "--track_origins", action="store_true",
+ default=False,
+ help="Show whence uninitialized bytes came. 30% slower.")
+
+ def ToolSpecificFlags(self):
+ ret = ["--gen-suppressions=all", "--demangle=no"]
+ ret += ["--leak-check=%s" % self._options.leak_check]
+
+ if self._options.show_all_leaks:
+ ret += ["--show-reachable=yes"]
+ else:
+ ret += ["--show-possibly-lost=no"]
+
+ if self._options.track_origins:
+ ret += ["--track-origins=yes"]
+
+ # TODO(glider): this is a temporary workaround for http://crbug.com/51716
+ # Let's see whether it helps.
+ if common.IsMac():
+ ret += ["--smc-check=all"]
+
+ return ret
+
+ def CreateAnalyzer(self):
+ use_gdb = common.IsMac()
+ return memcheck_analyze.MemcheckAnalyzer(self._source_dir,
+ self._options.show_all_leaks,
+ use_gdb=use_gdb)
+
+ def Analyze(self, check_sanity=False):
+ ret = self.GetAnalyzeResults(check_sanity)
+
+ if ret != 0:
+ logging.info("Please see http://dev.chromium.org/developers/how-tos/"
+ "using-valgrind for the info on Memcheck/Valgrind")
+ return ret
+
+
+class PinTool(BaseTool):
+ """Abstract class for running PIN tools.
+
+ Always subclass this and implement ToolSpecificFlags() and
+ ExtendOptionParser() for tool-specific stuff.
+ """
+ def PrepareForTest(self):
+ pass
+
+ def ToolSpecificFlags(self):
+ raise NotImplementedError, "This method should be implemented " \
+ "in the tool-specific subclass"
+
+ def ToolCommand(self):
+ """Get the PIN command to run."""
+
+ # Construct the PIN command.
+ pin_cmd = os.getenv("PIN_COMMAND")
+ if not pin_cmd:
+ raise RuntimeError, "Please set PIN_COMMAND environment variable " \
+ "with the path to pin.exe"
+ proc = pin_cmd.split(" ")
+
+ proc += self.ToolSpecificFlags()
+
+ # The PIN command is constructed.
+
+ # PIN requires -- to separate PIN flags from the executable name.
+ # self._args begins with the exe to be run.
+ proc += ["--"]
+
+ proc += self._args
+ return proc
+
+
+class ThreadSanitizerBase(object):
+ """ThreadSanitizer
+ Dynamic data race detector for Linux, Mac and Windows.
+
+ http://code.google.com/p/data-race-test/wiki/ThreadSanitizer
+
+ Since TSan works on both Valgrind (Linux, Mac) and PIN (Windows), we need
+ to have multiple inheritance
+ """
+
+ INFO_MESSAGE="Please see http://dev.chromium.org/developers/how-tos/" \
+ "using-valgrind/threadsanitizer for the info on " \
+ "ThreadSanitizer"
+
+ def __init__(self):
+ super(ThreadSanitizerBase, self).__init__()
+ self.RegisterOptionParserHook(ThreadSanitizerBase.ExtendOptionParser)
+
+ def ToolName(self):
+ return "tsan"
+
+ def UseXML(self):
+ return False
+
+ def SelfContained(self):
+ return True
+
+ def ExtendOptionParser(self, parser):
+ parser.add_option("", "--hybrid", default="no",
+ dest="hybrid",
+ help="Finds more data races, may give false positive "
+ "reports unless the code is annotated")
+ parser.add_option("", "--announce-threads", default="yes",
+ dest="announce_threads",
+ help="Show the the stack traces of thread creation")
+ parser.add_option("", "--free-is-write", default="no",
+ dest="free_is_write",
+ help="Treat free()/operator delete as memory write. "
+ "This helps finding more data races, but (currently) "
+ "this may give false positive reports on std::string "
+ "internals, see http://code.google.com/p/data-race-test"
+ "/issues/detail?id=40")
+
+ def EvalBoolFlag(self, flag_value):
+ if (flag_value in ["1", "true", "yes"]):
+ return True
+ elif (flag_value in ["0", "false", "no"]):
+ return False
+ raise RuntimeError, "Can't parse flag value (%s)" % flag_value
+
+ def ToolSpecificFlags(self):
+ ret = []
+
+ ignore_files = ["ignores.txt"]
+ for platform_suffix in common.PlatformNames():
+ ignore_files.append("ignores_%s.txt" % platform_suffix)
+ for ignore_file in ignore_files:
+ fullname = os.path.join(self._source_dir,
+ "tools", "valgrind", "tsan", ignore_file)
+ if os.path.exists(fullname):
+ fullname = common.NormalizeWindowsPath(fullname)
+ ret += ["--ignore=%s" % fullname]
+
+ # This should shorten filepaths for local builds.
+ ret += ["--file-prefix-to-cut=%s/" % self._source_dir]
+
+ # This should shorten filepaths on bots.
+ ret += ["--file-prefix-to-cut=build/src/"]
+ ret += ["--file-prefix-to-cut=out/Release/../../"]
+
+ # This should shorten filepaths for functions intercepted in TSan.
+ ret += ["--file-prefix-to-cut=scripts/tsan/tsan/"]
+ ret += ["--file-prefix-to-cut=src/tsan/tsan/"]
+
+ ret += ["--gen-suppressions=true"]
+
+ if self.EvalBoolFlag(self._options.hybrid):
+ ret += ["--hybrid=yes"] # "no" is the default value for TSAN
+
+ if self.EvalBoolFlag(self._options.announce_threads):
+ ret += ["--announce-threads"]
+
+ if self.EvalBoolFlag(self._options.free_is_write):
+ ret += ["--free-is-write=yes"]
+ else:
+ ret += ["--free-is-write=no"]
+
+
+ # --show-pc flag is needed for parsing the error logs on Darwin.
+ if platform_suffix == 'mac':
+ ret += ["--show-pc=yes"]
+ ret += ["--show-pid=no"]
+
+ boring_callers = common.BoringCallers(mangled=False, use_re_wildcards=False)
+ # TODO(timurrrr): In fact, we want "starting from .." instead of "below .."
+ for bc in boring_callers:
+ ret += ["--cut_stack_below=%s" % bc]
+
+ return ret
+
+
+class ThreadSanitizerPosix(ThreadSanitizerBase, ValgrindTool):
+ def ToolSpecificFlags(self):
+ proc = ThreadSanitizerBase.ToolSpecificFlags(self)
+ # The -v flag is needed for printing the list of used suppressions and
+ # obtaining addresses for loaded shared libraries on Mac.
+ proc += ["-v"]
+ return proc
+
+ def CreateAnalyzer(self):
+ use_gdb = common.IsMac()
+ return tsan_analyze.TsanAnalyzer(self._source_dir, use_gdb)
+
+ def Analyze(self, check_sanity=False):
+ ret = self.GetAnalyzeResults(check_sanity)
+
+ if ret != 0:
+ logging.info(self.INFO_MESSAGE)
+ return ret
+
+
+class ThreadSanitizerWindows(ThreadSanitizerBase, PinTool):
+
+ def __init__(self):
+ super(ThreadSanitizerWindows, self).__init__()
+ self.RegisterOptionParserHook(ThreadSanitizerWindows.ExtendOptionParser)
+
+ def ExtendOptionParser(self, parser):
+ parser.add_option("", "--suppressions", default=[],
+ action="append",
+ help="path to TSan suppression file")
+
+
+ def ToolSpecificFlags(self):
+ add_env = {
+ "CHROME_ALLOCATOR" : "WINHEAP",
+ }
+ for k,v in add_env.iteritems():
+ logging.info("export %s=%s", k, v)
+ os.putenv(k, v)
+
+ proc = ThreadSanitizerBase.ToolSpecificFlags(self)
+ # On PIN, ThreadSanitizer has its own suppression mechanism
+ # and --log-file flag which work exactly on Valgrind.
+ suppression_count = 0
+ for suppression_file in self._options.suppressions:
+ if os.path.exists(suppression_file):
+ suppression_count += 1
+ suppression_file = common.NormalizeWindowsPath(suppression_file)
+ proc += ["--suppressions=%s" % suppression_file]
+
+ if not suppression_count:
+ logging.warning("WARNING: NOT USING SUPPRESSIONS!")
+
+ logfilename = self.log_dir + "/tsan.%p"
+ proc += ["--log-file=" + common.NormalizeWindowsPath(logfilename)]
+
+ # TODO(timurrrr): Add flags for Valgrind trace children analog when we
+ # start running complex tests (e.g. UI) under TSan/Win.
+
+ return proc
+
+ def Analyze(self, check_sanity=False):
+ filenames = glob.glob(self.log_dir + "/tsan.*")
+ analyzer = tsan_analyze.TsanAnalyzer(self._source_dir)
+ ret = analyzer.Report(filenames, None, check_sanity)
+ if ret != 0:
+ logging.info(self.INFO_MESSAGE)
+ return ret
+
+
+class DrMemory(BaseTool):
+ """Dr.Memory
+ Dynamic memory error detector for Windows.
+
+ http://dev.chromium.org/developers/how-tos/using-drmemory
+ It is not very mature at the moment, some things might not work properly.
+ """
+
+ def __init__(self, full_mode, pattern_mode):
+ super(DrMemory, self).__init__()
+ self.full_mode = full_mode
+ self.pattern_mode = pattern_mode
+ self.RegisterOptionParserHook(DrMemory.ExtendOptionParser)
+
+ def ToolName(self):
+ return "drmemory"
+
+ def ExtendOptionParser(self, parser):
+ parser.add_option("", "--suppressions", default=[],
+ action="append",
+ help="path to a drmemory suppression file")
+ parser.add_option("", "--follow_python", action="store_true",
+ default=False, dest="follow_python",
+ help="Monitor python child processes. If off, neither "
+ "python children nor any children of python children "
+ "will be monitored.")
+ parser.add_option("", "--indirect", action="store_true",
+ default=False,
+ help="set BROWSER_WRAPPER rather than "
+ "running Dr. Memory directly on the harness")
+ parser.add_option("", "--indirect_webkit_layout", action="store_true",
+ default=False,
+ help="set --wrapper rather than running valgrind "
+ "directly.")
+ parser.add_option("", "--use_debug", action="store_true",
+ default=False, dest="use_debug",
+ help="Run Dr. Memory debug build")
+ parser.add_option("", "--trace_children", action="store_true",
+ default=True,
+ help="TODO: default value differs from Valgrind")
+
+ def ToolCommand(self):
+ """Get the tool command to run."""
+ # WINHEAP is what Dr. Memory supports as there are issues w/ both
+ # jemalloc (http://code.google.com/p/drmemory/issues/detail?id=320) and
+ # tcmalloc (http://code.google.com/p/drmemory/issues/detail?id=314)
+ add_env = {
+ "CHROME_ALLOCATOR" : "WINHEAP",
+ "JSIMD_FORCEMMX" : "1", # http://code.google.com/p/drmemory/issues/detail?id=540
+ }
+ for k,v in add_env.iteritems():
+ logging.info("export %s=%s", k, v)
+ os.putenv(k, v)
+
+ drmem_cmd = os.getenv("DRMEMORY_COMMAND")
+ if not drmem_cmd:
+ raise RuntimeError, "Please set DRMEMORY_COMMAND environment variable " \
+ "with the path to drmemory.exe"
+ proc = drmem_cmd.split(" ")
+
+ # By default, don't run python (this will exclude python's children as well)
+ # to reduce runtime. We're not really interested in spending time finding
+ # bugs in the python implementation.
+ # With file-based config we must update the file every time, and
+ # it will affect simultaneous drmem uses by this user. While file-based
+ # config has many advantages, here we may want this-instance-only
+ # (http://code.google.com/p/drmemory/issues/detail?id=334).
+ drconfig_cmd = [ proc[0].replace("drmemory.exe", "drconfig.exe") ]
+ drconfig_cmd += ["-quiet"] # suppress errors about no 64-bit libs
+ run_drconfig = True
+ if self._options.follow_python:
+ logging.info("Following python children")
+ # -unreg fails if not already registered so query for that first
+ query_cmd = drconfig_cmd + ["-isreg", "python.exe"]
+ query_proc = subprocess.Popen(query_cmd, stdout=subprocess.PIPE,
+ shell=True)
+ (query_out, query_err) = query_proc.communicate()
+ if re.search("exe not registered", query_out):
+ run_drconfig = False # all set
+ else:
+ drconfig_cmd += ["-unreg", "python.exe"]
+ else:
+ logging.info("Excluding python children")
+ drconfig_cmd += ["-reg", "python.exe", "-norun"]
+ if run_drconfig:
+ drconfig_retcode = common.RunSubprocess(drconfig_cmd, self._timeout)
+ if drconfig_retcode:
+ logging.error("Configuring whether to follow python children failed " \
+ "with %d.", drconfig_retcode)
+ raise RuntimeError, "Configuring python children failed "
+
+ suppression_count = 0
+ supp_files = self._options.suppressions
+ if self.full_mode:
+ supp_files += [s.replace(".txt", "_full.txt") for s in supp_files]
+ for suppression_file in supp_files:
+ if os.path.exists(suppression_file):
+ suppression_count += 1
+ proc += ["-suppress", common.NormalizeWindowsPath(suppression_file)]
+
+ if not suppression_count:
+ logging.warning("WARNING: NOT USING SUPPRESSIONS!")
+
+ # Un-comment to dump Dr.Memory events on error
+ #proc += ["-dr_ops", "-dumpcore_mask", "-dr_ops", "0x8bff"]
+
+ # Un-comment and comment next line to debug Dr.Memory
+ #proc += ["-dr_ops", "-no_hide"]
+ #proc += ["-dr_ops", "-msgbox_mask", "-dr_ops", "15"]
+ #Proc += ["-dr_ops", "-stderr_mask", "-dr_ops", "15"]
+ # Ensure we see messages about Dr. Memory crashing!
+ proc += ["-dr_ops", "-stderr_mask", "-dr_ops", "12"]
+
+ if self._options.use_debug:
+ proc += ["-debug"]
+
+ proc += ["-logdir", common.NormalizeWindowsPath(self.log_dir)]
+
+ if self.log_parent_dir:
+ # gpu process on Windows Vista+ runs at Low Integrity and can only
+ # write to certain directories (http://crbug.com/119131)
+ symcache_dir = os.path.join(self.log_parent_dir, "drmemory.symcache")
+ elif self._options.build_dir:
+ # The other case is only possible with -t cmdline.
+ # Anyways, if we omit -symcache_dir the -logdir's value is used which
+ # should be fine.
+ symcache_dir = os.path.join(self._options.build_dir, "drmemory.symcache")
+ if symcache_dir:
+ if not os.path.exists(symcache_dir):
+ try:
+ os.mkdir(symcache_dir)
+ except OSError:
+ logging.warning("Can't create symcache dir?")
+ if os.path.exists(symcache_dir):
+ proc += ["-symcache_dir", common.NormalizeWindowsPath(symcache_dir)]
+
+ # Use -no_summary to suppress DrMemory's summary and init-time
+ # notifications. We generate our own with drmemory_analyze.py.
+ proc += ["-batch", "-no_summary"]
+
+ # Un-comment to disable interleaved output. Will also suppress error
+ # messages normally printed to stderr.
+ #proc += ["-quiet", "-no_results_to_stderr"]
+
+ proc += ["-callstack_max_frames", "40"]
+
+ # make callstacks easier to read
+ proc += ["-callstack_srcfile_prefix",
+ "build\\src,chromium\\src,crt_build\\self_x86"]
+ proc += ["-callstack_modname_hide",
+ "*drmemory*,chrome.dll"]
+
+ boring_callers = common.BoringCallers(mangled=False, use_re_wildcards=False)
+ # TODO(timurrrr): In fact, we want "starting from .." instead of "below .."
+ proc += ["-callstack_truncate_below", ",".join(boring_callers)]
+
+ if self.pattern_mode:
+ proc += ["-pattern", "0xf1fd", "-no_count_leaks", "-redzone_size", "0x20"]
+ elif not self.full_mode:
+ proc += ["-light"]
+
+ proc += self._tool_flags
+
+ # DrM i#850/851: The new -callstack_use_top_fp_selectively has bugs.
+ proc += ["-no_callstack_use_top_fp_selectively"]
+
+ # Dr.Memory requires -- to separate tool flags from the executable name.
+ proc += ["--"]
+
+ if self._options.indirect or self._options.indirect_webkit_layout:
+ # TODO(timurrrr): reuse for TSan on Windows
+ wrapper_path = os.path.join(self._source_dir,
+ "tools", "valgrind", "browser_wrapper_win.py")
+ wrapper = " ".join(["python", wrapper_path] + proc)
+ self.CreateBrowserWrapper(wrapper)
+ logging.info("browser wrapper = " + " ".join(proc))
+ if self._options.indirect_webkit_layout:
+ proc = self._args
+ # Layout tests want forward slashes.
+ wrapper = wrapper.replace('\\', '/')
+ proc += ["--wrapper", wrapper]
+ return proc
+ else:
+ proc = []
+
+ # Note that self._args begins with the name of the exe to be run.
+ self._args[0] = common.NormalizeWindowsPath(self._args[0])
+ proc += self._args
+ return proc
+
+ def CreateBrowserWrapper(self, command):
+ os.putenv("BROWSER_WRAPPER", command)
+
+ def Analyze(self, check_sanity=False):
+ # Use one analyzer for all the log files to avoid printing duplicate reports
+ #
+ # TODO(timurrrr): unify this with Valgrind and other tools when we have
+ # http://code.google.com/p/drmemory/issues/detail?id=684
+ analyzer = drmemory_analyze.DrMemoryAnalyzer()
+
+ ret = 0
+ if not self._options.indirect and not self._options.indirect_webkit_layout:
+ filenames = glob.glob(self.log_dir + "/*/results.txt")
+
+ ret = analyzer.Report(filenames, None, check_sanity)
+ else:
+ testcases = glob.glob(self.log_dir + "/testcase.*.logs")
+ # If we have browser wrapper, the per-test logdirs are named as
+ # "testcase.wrapper_PID.name".
+ # Let's extract the list of wrapper_PIDs and name it ppids.
+ # NOTE: ppids may contain '_', i.e. they are not ints!
+ ppids = set([f.split(".")[-2] for f in testcases])
+
+ for ppid in ppids:
+ testcase_name = None
+ try:
+ f = open("%s/testcase.%s.name" % (self.log_dir, ppid))
+ testcase_name = f.read().strip()
+ f.close()
+ except IOError:
+ pass
+ print "====================================================="
+ print " Below is the report for drmemory wrapper PID=%s." % ppid
+ if testcase_name:
+ print " It was used while running the `%s` test." % testcase_name
+ else:
+ # TODO(timurrrr): hm, the PID line is suppressed on Windows...
+ print " You can find the corresponding test"
+ print " by searching the above log for 'PID=%s'" % ppid
+ sys.stdout.flush()
+ ppid_filenames = glob.glob("%s/testcase.%s.logs/*/results.txt" %
+ (self.log_dir, ppid))
+ ret |= analyzer.Report(ppid_filenames, testcase_name, False)
+ print "====================================================="
+ sys.stdout.flush()
+
+ logging.info("Please see http://dev.chromium.org/developers/how-tos/"
+ "using-drmemory for the info on Dr. Memory")
+ return ret
+
+
+# RaceVerifier support. See
+# http://code.google.com/p/data-race-test/wiki/RaceVerifier for more details.
+class ThreadSanitizerRV1Analyzer(tsan_analyze.TsanAnalyzer):
+ """ TsanAnalyzer that saves race reports to a file. """
+
+ TMP_FILE = "rvlog.tmp"
+
+ def __init__(self, source_dir, use_gdb):
+ super(ThreadSanitizerRV1Analyzer, self).__init__(source_dir, use_gdb)
+ self.out = open(self.TMP_FILE, "w")
+
+ def Report(self, files, testcase, check_sanity=False):
+ reports = self.GetReports(files)
+ for report in reports:
+ print >>self.out, report
+ if len(reports) > 0:
+ logging.info("RaceVerifier pass 1 of 2, found %i reports" % len(reports))
+ return -1
+ return 0
+
+ def CloseOutputFile(self):
+ self.out.close()
+
+
+class ThreadSanitizerRV1Mixin(object):
+ """RaceVerifier first pass.
+
+ Runs ThreadSanitizer as usual, but hides race reports and collects them in a
+ temporary file"""
+
+ def __init__(self):
+ super(ThreadSanitizerRV1Mixin, self).__init__()
+ self.RegisterOptionParserHook(ThreadSanitizerRV1Mixin.ExtendOptionParser)
+
+ def ExtendOptionParser(self, parser):
+ parser.set_defaults(hybrid="yes")
+
+ def CreateAnalyzer(self):
+ use_gdb = common.IsMac()
+ self.analyzer = ThreadSanitizerRV1Analyzer(self._source_dir, use_gdb)
+ return self.analyzer
+
+ def Cleanup(self):
+ super(ThreadSanitizerRV1Mixin, self).Cleanup()
+ self.analyzer.CloseOutputFile()
+
+
+class ThreadSanitizerRV2Mixin(object):
+ """RaceVerifier second pass."""
+
+ def __init__(self):
+ super(ThreadSanitizerRV2Mixin, self).__init__()
+ self.RegisterOptionParserHook(ThreadSanitizerRV2Mixin.ExtendOptionParser)
+
+ def ExtendOptionParser(self, parser):
+ parser.add_option("", "--race-verifier-sleep-ms",
+ dest="race_verifier_sleep_ms", default=10,
+ help="duration of RaceVerifier delays")
+
+ def ToolSpecificFlags(self):
+ proc = super(ThreadSanitizerRV2Mixin, self).ToolSpecificFlags()
+ proc += ['--race-verifier=%s' % ThreadSanitizerRV1Analyzer.TMP_FILE,
+ '--race-verifier-sleep-ms=%d' %
+ int(self._options.race_verifier_sleep_ms)]
+ return proc
+
+ def Cleanup(self):
+ super(ThreadSanitizerRV2Mixin, self).Cleanup()
+ os.unlink(ThreadSanitizerRV1Analyzer.TMP_FILE)
+
+
+class ThreadSanitizerRV1Posix(ThreadSanitizerRV1Mixin, ThreadSanitizerPosix):
+ pass
+
+
+class ThreadSanitizerRV2Posix(ThreadSanitizerRV2Mixin, ThreadSanitizerPosix):
+ pass
+
+
+class ThreadSanitizerRV1Windows(ThreadSanitizerRV1Mixin,
+ ThreadSanitizerWindows):
+ pass
+
+
+class ThreadSanitizerRV2Windows(ThreadSanitizerRV2Mixin,
+ ThreadSanitizerWindows):
+ pass
+
+
+class RaceVerifier(object):
+ """Runs tests under RaceVerifier/Valgrind."""
+
+ MORE_INFO_URL = "http://code.google.com/p/data-race-test/wiki/RaceVerifier"
+
+ def RV1Factory(self):
+ if common.IsWindows():
+ return ThreadSanitizerRV1Windows()
+ else:
+ return ThreadSanitizerRV1Posix()
+
+ def RV2Factory(self):
+ if common.IsWindows():
+ return ThreadSanitizerRV2Windows()
+ else:
+ return ThreadSanitizerRV2Posix()
+
+ def ToolName(self):
+ return "tsan"
+
+ def Main(self, args, check_sanity, min_runtime_in_seconds):
+ logging.info("Running a TSan + RaceVerifier test. For more information, " +
+ "see " + self.MORE_INFO_URL)
+ cmd1 = self.RV1Factory()
+ ret = cmd1.Main(args, check_sanity, min_runtime_in_seconds)
+ # Verify race reports, if there are any.
+ if ret == -1:
+ logging.info("Starting pass 2 of 2. Running the same binary in " +
+ "RaceVerifier mode to confirm possible race reports.")
+ logging.info("For more information, see " + self.MORE_INFO_URL)
+ cmd2 = self.RV2Factory()
+ ret = cmd2.Main(args, check_sanity, min_runtime_in_seconds)
+ else:
+ logging.info("No reports, skipping RaceVerifier second pass")
+ logging.info("Please see " + self.MORE_INFO_URL + " for more information " +
+ "on RaceVerifier")
+ return ret
+
+ def Run(self, args, module, min_runtime_in_seconds=0):
+ return self.Main(args, False, min_runtime_in_seconds)
+
+
+class EmbeddedTool(BaseTool):
+ """Abstract class for tools embedded directly into the test binary.
+ """
+ # TODO(glider): need to override Execute() and support process chaining here.
+
+ def ToolCommand(self):
+ # In the simplest case just the args of the script.
+ return self._args
+
+
+class Asan(EmbeddedTool):
+ """AddressSanitizer, a memory error detector.
+
+ More information at
+ http://dev.chromium.org/developers/testing/addresssanitizer
+ """
+ def __init__(self):
+ super(Asan, self).__init__()
+ self._timeout = 1200
+ if common.IsMac():
+ self._env["DYLD_NO_PIE"] = "1"
+
+
+ def ToolName(self):
+ return "asan"
+
+ def ToolCommand(self):
+ # TODO(glider): use pipes instead of the ugly wrapper here once they
+ # are supported.
+ procs = [os.path.join(self._source_dir, "tools", "valgrind",
+ "asan", "asan_wrapper.sh")]
+ procs.extend(self._args)
+ return procs
+
+ def Analyze(sels, unused_check_sanity):
+ return 0
+
+
+class ToolFactory:
+ def Create(self, tool_name):
+ if tool_name == "memcheck":
+ return Memcheck()
+ if tool_name == "tsan":
+ if common.IsWindows():
+ return ThreadSanitizerWindows()
+ else:
+ return ThreadSanitizerPosix()
+ if tool_name == "drmemory" or tool_name == "drmemory_light":
+ # TODO(timurrrr): remove support for "drmemory" when buildbots are
+ # switched to drmemory_light OR make drmemory==drmemory_full the default
+ # mode when the tool is mature enough.
+ return DrMemory(False, False)
+ if tool_name == "drmemory_full":
+ return DrMemory(True, False)
+ if tool_name == "drmemory_pattern":
+ return DrMemory(False, True)
+ if tool_name == "tsan_rv":
+ return RaceVerifier()
+ if tool_name == "asan":
+ return Asan()
+ try:
+ platform_name = common.PlatformNames()[0]
+ except common.NotImplementedError:
+ platform_name = sys.platform + "(Unknown)"
+ raise RuntimeError, "Unknown tool (tool=%s, platform=%s)" % (tool_name,
+ platform_name)
+
+def CreateTool(tool):
+ return ToolFactory().Create(tool)
diff --git a/chromium/tools/valgrind/waterfall.sh b/chromium/tools/valgrind/waterfall.sh
new file mode 100755
index 00000000000..bce3e637b0f
--- /dev/null
+++ b/chromium/tools/valgrind/waterfall.sh
@@ -0,0 +1,222 @@
+#!/bin/bash
+
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script can be used by waterfall sheriffs to fetch the status
+# of Valgrind bots on the memory waterfall and test if their local
+# suppressions match the reports on the waterfall.
+
+set -e
+
+THISDIR=$(dirname "${0}")
+LOGS_DIR=$THISDIR/waterfall.tmp
+WATERFALL_PAGE="http://build.chromium.org/p/chromium.memory/builders"
+WATERFALL_FYI_PAGE="http://build.chromium.org/p/chromium.memory.fyi/builders"
+
+download() {
+ # Download a file.
+ # $1 = URL to download
+ # $2 = Path to the output file
+ # {{{1
+ if [ "$(which curl)" != "" ]
+ then
+ if ! curl -s -o "$2" "$1"
+ then
+ echo
+ echo "Failed to download '$1'... aborting"
+ exit 1
+ fi
+ elif [ "$(which wget)" != "" ]
+ then
+ if ! wget "$1" -O "$2" -q
+ then
+ echo
+ echo "Failed to download '$1'... aborting"
+ exit 1
+ fi
+ else
+ echo "Need either curl or wget to download stuff... aborting"
+ exit 1
+ fi
+ # }}}
+}
+
+fetch_logs() {
+ # Fetch Valgrind logs from the waterfall {{{1
+
+ # TODO(timurrrr,maruel): use JSON, see
+ # http://build.chromium.org/p/chromium.memory/json/help
+
+ rm -rf "$LOGS_DIR" # Delete old logs
+ mkdir "$LOGS_DIR"
+
+ echo "Fetching the list of builders..."
+ download $1 "$LOGS_DIR/builders"
+ SLAVES=$(grep "<a href=\"builders\/" "$LOGS_DIR/builders" | \
+ grep 'td class="box"' | \
+ sed "s/.*<a href=\"builders\///" | sed "s/\".*//" | \
+ sort | uniq)
+
+ for S in $SLAVES
+ do
+ SLAVE_URL=$1/$S
+ SLAVE_NAME=$(echo $S | sed -e "s/%20/ /g" -e "s/%28/(/g" -e "s/%29/)/g")
+ echo -n "Fetching builds by slave '${SLAVE_NAME}'"
+ download $SLAVE_URL?numbuilds=${NUMBUILDS} "$LOGS_DIR/slave_${S}"
+
+ # We speed up the 'fetch' step by skipping the builds/tests which succeeded.
+ # TODO(timurrrr): OTOH, we won't be able to check
+ # if some suppression is not used anymore.
+ #
+ # The awk script here joins the lines ending with </td> to make it possible
+ # to find the failed builds.
+ LIST_OF_BUILDS=$(cat "$LOGS_DIR/slave_$S" | \
+ awk 'BEGIN { buf = "" }
+ {
+ if ($0 ~ /<\/td>/) { buf = (buf $0); }
+ else {
+ if (buf) { print buf; buf="" }
+ print $0
+ }
+ }
+ END {if (buf) print buf}' | \
+ grep "success\|failure" | \
+ head -n $NUMBUILDS | \
+ grep "failure" | \
+ grep -v "failed compile" | \
+ sed "s/.*\/builds\///" | sed "s/\".*//")
+
+ for BUILD in $LIST_OF_BUILDS
+ do
+ # We'll fetch a few tiny URLs now, let's use a temp file.
+ TMPFILE=$(mktemp -t memory_waterfall.XXXXXX)
+ download $SLAVE_URL/builds/$BUILD "$TMPFILE"
+
+ REPORT_FILE="$LOGS_DIR/report_${S}_${BUILD}"
+ rm -f $REPORT_FILE 2>/dev/null || true # make sure it doesn't exist
+
+ REPORT_URLS=$(grep -o "[0-9]\+/steps/\(memory\|heapcheck\).*/logs/[0-9A-F]\{16\}" \
+ "$TMPFILE" \
+ || true) # `true` is to succeed on empty output
+ FAILED_TESTS=$(grep -o "[0-9]\+/steps/\(memory\|heapcheck\).*/logs/[A-Za-z0-9_.]\+" \
+ "$TMPFILE" | grep -v "[0-9A-F]\{16\}" \
+ | grep -v "stdio" || true)
+
+ for REPORT in $REPORT_URLS
+ do
+ download "$SLAVE_URL/builds/$REPORT/text" "$TMPFILE"
+ echo "" >> "$TMPFILE" # Add a newline at the end
+ cat "$TMPFILE" | tr -d '\r' >> "$REPORT_FILE"
+ done
+
+ for FAILURE in $FAILED_TESTS
+ do
+ echo -n "FAILED:" >> "$REPORT_FILE"
+ echo "$FAILURE" | sed -e "s/.*\/logs\///" -e "s/\/.*//" \
+ >> "$REPORT_FILE"
+ done
+
+ rm "$TMPFILE"
+ echo $SLAVE_URL/builds/$BUILD >> "$REPORT_FILE"
+ done
+ echo " DONE"
+ done
+ # }}}
+}
+
+match_suppressions() {
+ PYTHONPATH=$THISDIR/../python/google \
+ python "$THISDIR/test_suppressions.py" $@ "$LOGS_DIR/report_"*
+}
+
+match_gtest_excludes() {
+ for PLATFORM in "Linux" "Chromium%20Mac" "Chromium%20OS"
+ do
+ echo
+ echo "Test failures on ${PLATFORM}:" | sed "s/%20/ /"
+ grep -h -o "^FAILED:.*" -R "$LOGS_DIR"/*${PLATFORM}* | \
+ grep -v "FAILS\|FLAKY" | sort | uniq | \
+ sed -e "s/^FAILED://" -e "s/^/ /"
+ # Don't put any operators between "grep | sed" and "RESULT=$PIPESTATUS"
+ RESULT=$PIPESTATUS
+
+ if [ "$RESULT" == 1 ]
+ then
+ echo " None!"
+ else
+ echo
+ echo " Note: we don't check for failures already excluded locally yet"
+ echo " TODO(timurrrr): don't list tests we've already excluded locally"
+ fi
+ done
+ echo
+ echo "Note: we don't print FAILS/FLAKY tests and 1200s-timeout failures"
+}
+
+usage() {
+ cat <<EOF
+usage: $0 fetch|match options
+
+This script can be used by waterfall sheriffs to fetch the status
+of Valgrind bots on the memory waterfall and test if their local
+suppressions match the reports on the waterfall.
+
+OPTIONS:
+ -h Show this message
+ -n N Fetch N builds from each slave.
+
+COMMANDS:
+ fetch Fetch Valgrind logs from the memory waterfall
+ match Test the local suppression files against the downloaded logs
+
+EOF
+}
+
+NUMBUILDS=3
+
+CMD=$1
+if [ $# != 0 ]; then
+ shift
+fi
+
+# Arguments for "match" are handled in match_suppressions
+if [ "$CMD" != "match" ]; then
+ while getopts “hn:†OPTION
+ do
+ case $OPTION in
+ h)
+ usage
+ exit
+ ;;
+ n)
+ NUMBUILDS=$OPTARG
+ ;;
+ ?)
+ usage
+ exit
+ ;;
+ esac
+ done
+ shift $((OPTIND-1))
+ if [ $# != 0 ]; then
+ usage
+ exit 1
+ fi
+fi
+
+if [ "$CMD" = "fetch" ]; then
+ echo "Fetching $NUMBUILDS builds"
+ fetch_logs $WATERFALL_PAGE
+ fetch_logs $WATERFALL_FYI_PAGE
+elif [ "$CMD" = "match" ]; then
+ match_suppressions $@
+ match_gtest_excludes
+elif [ "$CMD" = "blame" ]; then
+ echo The blame command died of bitrot. If you need it, please reimplement it.
+ echo Reimplementation is blocked on http://crbug.com/82688
+else
+ usage
+ exit 1
+fi
diff --git a/chromium/tools/vim/chromium.ycm_extra_conf.py b/chromium/tools/vim/chromium.ycm_extra_conf.py
new file mode 100644
index 00000000000..ac9582d0b1c
--- /dev/null
+++ b/chromium/tools/vim/chromium.ycm_extra_conf.py
@@ -0,0 +1,203 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Autocompletion config for YouCompleteMe in Chromium.
+#
+# USAGE:
+#
+# 1. Install YCM [https://github.com/Valloric/YouCompleteMe]
+# (Googlers should check out [go/ycm])
+#
+# 2. Point to this config file in your .vimrc:
+# let g:ycm_global_ycm_extra_conf =
+# '<chrome_depot>/src/tools/vim/chromium.ycm_extra_conf.py'
+#
+# 3. Profit
+#
+#
+# Usage notes:
+#
+# * You must use ninja & clang to build Chromium.
+#
+# * You must have run gyp_chromium and built Chromium recently.
+#
+#
+# Hacking notes:
+#
+# * The purpose of this script is to construct an accurate enough command line
+# for YCM to pass to clang so it can build and extract the symbols.
+#
+# * Right now, we only pull the -I and -D flags. That seems to be sufficient
+# for everything I've used it for.
+#
+# * That whole ninja & clang thing? We could support other configs if someone
+# were willing to write the correct commands and a parser.
+#
+# * This has only been tested on gPrecise.
+
+
+import os
+import subprocess
+
+
+# Flags from YCM's default config.
+flags = [
+'-DUSE_CLANG_COMPLETER',
+'-std=c++11',
+'-x',
+'c++',
+]
+
+
+def PathExists(*args):
+ return os.path.exists(os.path.join(*args))
+
+
+def FindChromeSrcFromFilename(filename):
+ """Searches for the root of the Chromium checkout.
+
+ Simply checks parent directories until it finds .gclient and src/.
+
+ Args:
+ filename: (String) Path to source file being edited.
+
+ Returns:
+ (String) Path of 'src/', or None if unable to find.
+ """
+ curdir = os.path.normpath(os.path.dirname(filename))
+ while not (PathExists(curdir, 'src') and PathExists(curdir, 'src', 'DEPS')
+ and (PathExists(curdir, '.gclient')
+ or PathExists(curdir, 'src', '.git'))):
+ nextdir = os.path.normpath(os.path.join(curdir, '..'))
+ if nextdir == curdir:
+ return None
+ curdir = nextdir
+ return os.path.join(curdir, 'src')
+
+
+# Largely copied from ninja-build.vim (guess_configuration)
+def GetNinjaOutputDirectory(chrome_root):
+ """Returns either <chrome_root>/out/Release or <chrome_root>/out/Debug.
+
+ The configuration chosen is the one most recently generated/built."""
+ root = os.path.join(chrome_root, 'out')
+ debug_path = os.path.join(root, 'Debug')
+ release_path = os.path.join(root, 'Release')
+
+ def is_release_15s_newer(test_path):
+ try:
+ debug_mtime = os.path.getmtime(os.path.join(debug_path, test_path))
+ except os.error:
+ debug_mtime = 0
+ try:
+ rel_mtime = os.path.getmtime(os.path.join(release_path, test_path))
+ except os.error:
+ rel_mtime = 0
+ return rel_mtime - debug_mtime >= 15
+
+ if is_release_15s_newer('build.ninja') or is_release_15s_newer('protoc'):
+ return release_path
+ return debug_path
+
+
+def GetClangCommandFromNinjaForFilename(chrome_root, filename):
+ """Returns the command line to build |filename|.
+
+ Asks ninja how it would build the source file. If the specified file is a
+ header, tries to find its companion source file first.
+
+ Args:
+ chrome_root: (String) Path to src/.
+ filename: (String) Path to source file being edited.
+
+ Returns:
+ (List of Strings) Command line arguments for clang.
+ """
+ if not chrome_root:
+ return []
+
+ # Generally, everyone benefits from including Chromium's src/, because all of
+ # Chromium's includes are relative to that.
+ chrome_flags = ['-I' + os.path.join(chrome_root)]
+
+ # Header files can't be built. Instead, try to match a header file to its
+ # corresponding source file.
+ if filename.endswith('.h'):
+ alternates = ['.cc', '.cpp']
+ for alt_extension in alternates:
+ alt_name = filename[:-2] + alt_extension
+ if os.path.exists(alt_name):
+ filename = alt_name
+ break
+ else:
+ # If this is a standalone .h file with no source, the best we can do is
+ # try to use the default flags.
+ return chrome_flags
+
+ # Ninja needs the path to the source file from the output build directory.
+ # Cut off the common part and /.
+ subdir_filename = filename[len(chrome_root)+1:]
+ rel_filename = os.path.join('..', '..', subdir_filename)
+
+ out_dir = GetNinjaOutputDirectory(chrome_root)
+
+ # Ask ninja how it would build our source file.
+ p = subprocess.Popen(['ninja', '-v', '-C', out_dir, '-t',
+ 'commands', rel_filename + '^'],
+ stdout=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ if p.returncode:
+ return chrome_flags
+
+ # Ninja might execute several commands to build something. We want the last
+ # clang command.
+ clang_line = None
+ for line in reversed(stdout.split('\n')):
+ if 'clang' in line:
+ clang_line = line
+ break
+ else:
+ return chrome_flags
+
+ # Parse out the -I and -D flags. These seem to be the only ones that are
+ # important for YCM's purposes.
+ for flag in clang_line.split(' '):
+ if flag.startswith('-I'):
+ # Relative paths need to be resolved, because they're relative to the
+ # output dir, not the source.
+ if flag[2] == '/':
+ chrome_flags.append(flag)
+ else:
+ abs_path = os.path.normpath(os.path.join(out_dir, flag[2:]))
+ chrome_flags.append('-I' + abs_path)
+ elif flag.startswith('-') and flag[1] in 'DWFfmO':
+ if flag == '-Wno-deprecated-register' or flag == '-Wno-header-guard':
+ # These flags causes libclang (3.3) to crash. Remove it until things
+ # are fixed.
+ continue
+ chrome_flags.append(flag)
+
+ return chrome_flags
+
+
+def FlagsForFile(filename):
+ """This is the main entry point for YCM. Its interface is fixed.
+
+ Args:
+ filename: (String) Path to source file being edited.
+
+ Returns:
+ (Dictionary)
+ 'flags': (List of Strings) Command line flags.
+ 'do_cache': (Boolean) True if the result should be cached.
+ """
+ chrome_root = FindChromeSrcFromFilename(filename)
+ chrome_flags = GetClangCommandFromNinjaForFilename(chrome_root,
+ filename)
+ final_flags = flags + chrome_flags
+
+ return {
+ 'flags': final_flags,
+ 'do_cache': True
+ }
diff --git a/chromium/tools/vim/filetypes.vim b/chromium/tools/vim/filetypes.vim
new file mode 100644
index 00000000000..3e7c8f9eada
--- /dev/null
+++ b/chromium/tools/vim/filetypes.vim
@@ -0,0 +1,9 @@
+" To get syntax highlighting and tab settings for gyp(i) and DEPS files,
+" add the following to your .vimrc file:
+" so /path/to/src/tools/vim/filetypes.vim
+
+augroup filetype
+ au! BufRead,BufNewFile *.gyp set filetype=python expandtab tabstop=2 shiftwidth=2
+ au! BufRead,BufNewFile *.gypi set filetype=python expandtab tabstop=2 shiftwidth=2
+ au! BufRead,BufNewFile DEPS set filetype=python expandtab tabstop=2 shiftwidth=2
+augroup END
diff --git a/chromium/tools/vim/ninja-build.vim b/chromium/tools/vim/ninja-build.vim
new file mode 100644
index 00000000000..f8b74191d82
--- /dev/null
+++ b/chromium/tools/vim/ninja-build.vim
@@ -0,0 +1,129 @@
+" Copyright (c) 2012 The Chromium Authors. All rights reserved.
+" Use of this source code is governed by a BSD-style license that can be
+" found in the LICENSE file.
+"
+" Adds a "Compile this file" function, using ninja. On Mac, binds Cmd-k to
+" this command. On Windows, Ctrl-F7 (which is the same as the VS default).
+" On Linux, <Leader>o, which is \o by default ("o"=creates .o files)
+"
+" Adds a "Build this target" function, using ninja. This is not bound
+" to any key by default, but can be used via the :CrBuild command.
+" It builds 'chrome' by default, but :CrBuild target1 target2 etc works as well.
+"
+" Requires that gyp has already generated build.ninja files, and that ninja is
+" in your path (which it is automatically if depot_tools is in your path).
+"
+" Add the following to your .vimrc file:
+" so /path/to/src/tools/vim/ninja-build.vim
+
+python << endpython
+import os
+import vim
+
+
+def path_to_current_buffer():
+ """Returns the absolute path of the current buffer."""
+ return vim.current.buffer.name
+
+
+def path_to_source_root():
+ """Returns the absolute path to the chromium source root."""
+ candidate = os.path.dirname(path_to_current_buffer())
+ # This is a list of files that need to identify the src directory. The shorter
+ # it is, the more likely it's wrong (checking for just "build/common.gypi"
+ # would find "src/v8" for files below "src/v8", as "src/v8/build/common.gypi"
+ # exists). The longer it is, the more likely it is to break when we rename
+ # directories.
+ fingerprints = ['chrome', 'net', 'v8', 'build', 'skia']
+ while candidate and not all(
+ [os.path.isdir(os.path.join(candidate, fp)) for fp in fingerprints]):
+ candidate = os.path.dirname(candidate)
+ return candidate
+
+
+def guess_configuration():
+ """Default to the configuration with either a newer build.ninja or a newer
+ protoc."""
+ root = os.path.join(path_to_source_root(), 'out')
+ def is_release_15s_newer(test_path):
+ try:
+ debug_mtime = os.path.getmtime(os.path.join(root, 'Debug', test_path))
+ except os.error:
+ debug_mtime = 0
+ try:
+ rel_mtime = os.path.getmtime(os.path.join(root, 'Release', test_path))
+ except os.error:
+ rel_mtime = 0
+ return rel_mtime - debug_mtime >= 15
+ configuration = 'Debug'
+ if is_release_15s_newer('build.ninja') or is_release_15s_newer('protoc'):
+ configuration = 'Release'
+ return configuration
+
+
+def compute_ninja_command_for_current_buffer(configuration=None):
+ """Returns the shell command to compile the file in the current buffer."""
+ if not configuration: configuration = guess_configuration()
+ build_dir = os.path.join(path_to_source_root(), 'out', configuration)
+
+ # ninja needs filepaths for the ^ syntax to be relative to the
+ # build directory.
+ file_to_build = path_to_current_buffer()
+ file_to_build = os.path.relpath(file_to_build, build_dir)
+
+ build_cmd = ' '.join(['ninja', '-C', build_dir, file_to_build + '^'])
+ if sys.platform == 'win32':
+ # Escape \ for Vim, and ^ for both Vim and shell.
+ build_cmd = build_cmd.replace('\\', '\\\\').replace('^', '^^^^')
+ vim.command('return "%s"' % build_cmd)
+
+
+def compute_ninja_command_for_targets(targets='', configuration=None):
+ if not configuration: configuration = guess_configuration()
+ build_dir = os.path.join(path_to_source_root(), 'out', configuration)
+ build_cmd = ' '.join(['ninja', '-C', build_dir, targets])
+ vim.command('return "%s"' % build_cmd)
+endpython
+
+fun! s:MakeWithCustomCommand(build_cmd)
+ let l:oldmakepgr = &makeprg
+ let &makeprg=a:build_cmd
+ silent make | cwindow
+ if !has('gui_running')
+ redraw!
+ endif
+ let &makeprg = l:oldmakepgr
+endfun
+
+fun! s:NinjaCommandForCurrentBuffer()
+ python compute_ninja_command_for_current_buffer()
+endfun
+
+fun! s:NinjaCommandForTargets(targets)
+ python compute_ninja_command_for_targets(vim.eval('a:targets'))
+endfun
+
+fun! CrCompileFile()
+ call s:MakeWithCustomCommand(s:NinjaCommandForCurrentBuffer())
+endfun
+
+fun! CrBuild(...)
+ let l:targets = a:0 > 0 ? join(a:000, ' ') : ''
+ if (l:targets !~ "\i")
+ let l:targets = 'chrome'
+ endif
+ call s:MakeWithCustomCommand(s:NinjaCommandForTargets(l:targets))
+endfun
+
+command! CrCompileFile call CrCompileFile()
+command! -nargs=* CrBuild call CrBuild(<q-args>)
+
+if has('mac')
+ map <D-k> :CrCompileFile<cr>
+ imap <D-k> <esc>:CrCompileFile<cr>
+elseif has('win32')
+ map <C-F7> :CrCompileFile<cr>
+ imap <C-F7> <esc>:CrCompileFile<cr>
+elseif has('unix')
+ map <Leader>o :CrCompileFile<cr>
+endif
diff --git a/chromium/tools/webrtc_perf_expectations/README b/chromium/tools/webrtc_perf_expectations/README
new file mode 100644
index 00000000000..972aceb6b64
--- /dev/null
+++ b/chromium/tools/webrtc_perf_expectations/README
@@ -0,0 +1,13 @@
+========
+Overview
+========
+
+See http://dev.chromium.org/developers/tree-sheriffs/perf-sheriffs#TOC-Selecting-an-acceptable-range-of-results
+for a general explanation of how performance expectations work.
+
+Instead of the regular make_expectations.py call, run this:
+
+../perf_expectations/make_expectations.py -c webrtc_perf_expectations.cfg
+
+We keep the WebRTC perf expectations aside since the tests are running on an
+internal master for now. \ No newline at end of file
diff --git a/chromium/tools/webrtc_perf_expectations/perf_expectations.json b/chromium/tools/webrtc_perf_expectations/perf_expectations.json
new file mode 100644
index 00000000000..bd31c5654bc
--- /dev/null
+++ b/chromium/tools/webrtc_perf_expectations/perf_expectations.json
@@ -0,0 +1,8 @@
+{"linux-chrome-pure/webrtc_pyauto/cpu/jsep01_call": {"reva": 199965, "revb": 200469, "type": "absolute", "improve": 27.55, "regress": 84.84, "sha1": "a35b38f1"},
+ "linux-chrome-pure/webrtc_pyauto/memory/jsep01_call": {"reva": 199600, "revb": 200178, "type": "absolute", "improve": 39672, "regress": 46402, "sha1": "e5906b10"},
+ "mac-chrome-pure/webrtc_pyauto/cpu/jsep01_call": {"reva": 189929, "revb": 193335, "type": "absolute", "improve": 35.15, "regress": 55.02, "sha1": "3fb872b1"},
+ "mac-chrome-pure/webrtc_pyauto/memory/jsep01_call": {"reva": 199600, "revb": 200178, "type": "absolute", "improve": 55537, "regress": 62769, "sha1": "3301ac33"},
+ "win-chrome-pure/webrtc_pyauto/cpu/jsep01_call": {"reva": 197094, "revb": 198850, "type": "absolute", "improve": 28.88, "regress": 51.45, "sha1": "0ce37cd6"},
+ "win-chrome-pure/webrtc_pyauto/memory/jsep01_call": {"reva": 199600, "revb": 200178, "type": "absolute", "improve": 39649, "regress": 44726, "sha1": "2beba373"},
+ "load": true
+}
diff --git a/chromium/tools/webrtc_perf_expectations/webrtc_perf_expectations.cfg b/chromium/tools/webrtc_perf_expectations/webrtc_perf_expectations.cfg
new file mode 100644
index 00000000000..d6ecf3017b0
--- /dev/null
+++ b/chromium/tools/webrtc_perf_expectations/webrtc_perf_expectations.cfg
@@ -0,0 +1,4 @@
+{
+ "base_url": "http://www.corp.google.com/~webrtc-cb/perf/",
+ "perf_file": "perf_expectations.json"
+} \ No newline at end of file
diff --git a/chromium/tools/win/copy-installer.bat b/chromium/tools/win/copy-installer.bat
new file mode 100755
index 00000000000..2615cba38e1
--- /dev/null
+++ b/chromium/tools/win/copy-installer.bat
@@ -0,0 +1,134 @@
+ECHO OFF
+
+REM Copyright (c) 2012 The Chromium Authors. All rights reserved.
+REM Use of this source code is governed by a BSD-style license that can be
+REM found in the LICENSE file.
+
+REM Copies an installer and symbols from a build directory on a network share
+REM into the directory \[out|build]\[Debug|Release] on the current drive.
+REM
+REM Usage:
+REM \\build.share\<path_to_checkout>\src\tools\win\copy-installer.bat
+REM
+REM By default, the script will copy the Debug build in the tree, falling back
+REM to the Release build if one is not found. Similarly, the ninja output
+REM directory is preferred over the devenv output directory. Specify
+REM "out|build" and/or "Debug|Release" (case matters) on the command line in
+REM any order to influence selection. The defaults for location and build type
+REM can also be overridden in a given build tree by creating a
+REM "copy-installer.cfg" file alongside the .gclient file that sets the OUTPUT
+REM and/or BUILDTYPE variables.
+REM
+REM Install Robocopy for superior performance on Windows XP if desired (it is
+REM present by default on Vista+).
+
+SETLOCAL
+
+REM Get the path to the build tree's src directory.
+CALL :_canonicalize "%~dp0..\.."
+SET FROM=%RET%
+
+REM Read local configuration (set OUTPUT and BUILDTYPE there).
+IF EXIST "%FROM%\..\copy-installer.cfg" CALL "%FROM%\..\copy-installer.cfg"
+
+REM Read OUTPUT and/or BUILDTYPE from command line.
+FOR %%a IN (%1 %2) do (
+IF "%%a"=="out" SET OUTPUT=out
+IF "%%a"=="build" SET OUTPUT=build
+IF "%%a"=="Debug" SET BUILDTYPE=Debug
+IF "%%a"=="Release" SET BUILDTYPE=Release
+)
+
+CALL :_find_build
+IF "%OUTPUT%%BUILDTYPE%"=="" (
+ECHO No build found to copy.
+EXIT 1
+)
+
+SET FROM=%FROM%\%OUTPUT%\%BUILDTYPE%
+SET TO=\%OUTPUT%\%BUILDTYPE%
+
+REM Figure out what files to copy based on the component type (shared/static).
+IF EXIST "%FROM%\base.dll" (
+SET TOCOPY=*.pdb setup.exe setup.exe.manifest chrome.7z *.dll
+SET ARCHIVETODELETE=chrome.packed.7z
+SET INSTALLER=setup.exe
+) ELSE (
+SET TOCOPY=*.pdb mini_installer.exe
+SET INSTALLER=mini_installer.exe
+)
+
+CALL :_copyfiles
+
+REM incremental_chrome_dll=1 puts chrome_dll.pdb into the "initial" dir.
+IF EXIST "%FROM%\initial" (
+SET FROM=%FROM%\initial
+SET TOCOPY=*.pdb
+CALL :_copyfiles
+)
+
+REM Keeping the old chrome.packed.7z around could cause the new setup.exe to
+REM use it instead of the new chrome.7z, delete it to save developers from
+REM debugging nightmares!
+IF NOT "%ARCHIVETODELETE%"=="" (
+IF EXIST "%TO%\%ARCHIVETODELETE%" (
+ECHO Deleting old/deprecated %ARCHIVETODELETE%
+del /Q "%TO%\%ARCHIVETODELETE%"
+)
+)
+
+ECHO Ready to run/debug %TO%\%INSTALLER%.
+GOTO :EOF
+
+REM All labels henceforth are subroutines intended to be invoked by CALL.
+
+REM Canonicalize the first argument, returning it in RET.
+:_canonicalize
+SET RET=%~f1
+GOTO :EOF
+
+REM Search for a mini_installer.exe in the candidate build outputs.
+:_find_build
+IF "%OUTPUT%"=="" (
+SET OUTPUTS=out build
+) ELSE (
+SET OUTPUTS=%OUTPUT%
+SET OUTPUT=
+)
+
+IF "%BUILDTYPE%"=="" (
+SET BUILDTYPES=Debug Release
+) ELSE (
+SET BUILDTYPES=%BUILDTYPE%
+SET BUILDTYPE=
+)
+
+FOR %%o IN (%OUTPUTS%) DO (
+FOR %%f IN (%BUILDTYPES%) DO (
+IF EXIST "%FROM%\%%o\%%f\mini_installer.exe" (
+SET OUTPUT=%%o
+SET BUILDTYPE=%%f
+GOTO :EOF
+)
+)
+)
+GOTO :EOF
+
+REM Branch to handle copying via robocopy (fast) or xcopy (slow).
+:_copyfiles
+robocopy /? 1> nul 2> nul
+IF NOT "%ERRORLEVEL%"=="9009" (
+robocopy "%FROM%" "%TO%" %TOCOPY% /MT /XX
+) ELSE (
+IF NOT EXIST "%TO%" mkdir "%TO%"
+call :_xcopy_hack %TOCOPY%
+)
+GOTO :EOF
+
+REM We can't use a for..in..do loop since we have wildcards, so we make a call
+REM to this with the files to copy.
+:_xcopy_hack
+SHIFT
+IF "%0"=="" GOTO :EOF
+xcopy "%FROM%\%0" "%TO%" /d /y
+GOTO _xcopy_hack
diff --git a/chromium/tools/win/link_limiter/build_link_limiter.py b/chromium/tools/win/link_limiter/build_link_limiter.py
new file mode 100755
index 00000000000..464d30c57b2
--- /dev/null
+++ b/chromium/tools/win/link_limiter/build_link_limiter.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import glob
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+
+BUILD_DIR = 'build'
+
+
+def run_with_vsvars(cmd, tmpdir=None):
+ fd, filename = tempfile.mkstemp('.bat', text=True)
+ with os.fdopen(fd, 'w') as f:
+ print >> f, '@echo off'
+ print >> f, r'call "%VS100COMNTOOLS%\vsvars32.bat"'
+ if tmpdir:
+ print >> f, r'cd %s' % tmpdir
+ print >> f, cmd
+ try:
+ p = subprocess.Popen([filename], shell=True, stdout=subprocess.PIPE,
+ universal_newlines=True)
+ out, _ = p.communicate()
+ return p.returncode, out
+ finally:
+ os.unlink(filename)
+
+
+def get_vc_dir():
+ _, out = run_with_vsvars('echo VCINSTALLDIR=%VCINSTALLDIR%')
+ for line in out.splitlines(): # pylint: disable-msg=E1103
+ if line.startswith('VCINSTALLDIR='):
+ return line[len('VCINSTALLDIR='):]
+ return None
+
+
+def build(infile):
+ if not os.path.exists(BUILD_DIR):
+ os.makedirs(BUILD_DIR)
+ outfile = 'limiter.exe'
+ outpath = os.path.join(BUILD_DIR, outfile)
+ cpptime = os.path.getmtime(infile)
+ if not os.path.exists(outpath) or cpptime > os.path.getmtime(outpath):
+ print 'Building %s...' % outfile
+ rc, out = run_with_vsvars(
+ 'cl /nologo /Ox /Zi /W4 /WX /D_UNICODE /DUNICODE'
+ ' /D_CRT_SECURE_NO_WARNINGS /EHsc %s /link /out:%s'
+ % (os.path.join('..', infile), outfile), BUILD_DIR)
+ if rc:
+ print out
+ print 'Failed to build %s' % outfile
+ sys.exit(1)
+ else:
+ print '%s already built' % outfile
+ return outpath
+
+
+def main():
+ # Switch to our own dir.
+ os.chdir(os.path.dirname(os.path.abspath(__file__)))
+
+ if sys.argv[-1] == 'clean':
+ if os.path.exists(BUILD_DIR):
+ shutil.rmtree(BUILD_DIR)
+ for exe in glob.glob('*.exe'):
+ os.unlink(exe)
+ return 0
+
+ vcdir = os.environ.get('VCINSTALLDIR')
+ if not vcdir:
+ vcdir = get_vc_dir()
+ if not vcdir:
+ print 'Could not get VCINSTALLDIR. Run vsvars32.bat?'
+ return 1
+ os.environ['PATH'] += (';' + os.path.join(vcdir, 'bin') +
+ ';' + os.path.join(vcdir, r'..\Common7\IDE'))
+
+ # Verify that we can find link.exe.
+ link = os.path.join(vcdir, 'bin', 'link.exe')
+ if not os.path.exists(link):
+ print 'link.exe not found at %s' % link
+ return 1
+
+ exe_name = build('limiter.cc')
+ for shim_exe in ('lib.exe', 'link.exe'):
+ newpath = '%s__LIMITER.exe' % shim_exe
+ shutil.copyfile(exe_name, newpath)
+ print '%s shim built. Use with msbuild like: "/p:LinkToolExe=%s"' \
+ % (shim_exe, os.path.abspath(newpath))
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/win/link_limiter/limiter.cc b/chromium/tools/win/link_limiter/limiter.cc
new file mode 100644
index 00000000000..b8a5d1cc802
--- /dev/null
+++ b/chromium/tools/win/link_limiter/limiter.cc
@@ -0,0 +1,337 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define NOMINMAX
+#include <windows.h>
+
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+#include <string>
+#include <vector>
+
+typedef std::basic_string<TCHAR> tstring;
+
+namespace {
+ const bool g_is_debug = (_wgetenv(L"LIMITER_DEBUG") != NULL);
+}
+
+// Don't use stderr for errors because VS has large buffers on them, leading
+// to confusing error output.
+static void Error(const wchar_t* msg, ...) {
+ tstring new_msg = tstring(L"limiter fatal error: ") + msg + L"\n";
+ va_list args;
+ va_start(args, msg);
+ vwprintf(new_msg.c_str(), args);
+ va_end(args);
+}
+
+static void Warn(const wchar_t* msg, ...) {
+ if (!g_is_debug)
+ return;
+ tstring new_msg = tstring(L"limiter warning: ") + msg + L"\n";
+ va_list args;
+ va_start(args, msg);
+ vwprintf(new_msg.c_str(), args);
+ va_end(args);
+}
+
+static tstring ErrorMessageToString(DWORD err) {
+ TCHAR* msg_buf = NULL;
+ DWORD rc = FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, // lpSource
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ reinterpret_cast<LPTSTR>(&msg_buf),
+ 0, // nSize
+ NULL); // Arguments
+ if (!rc)
+ return L"unknown error";
+ tstring ret(msg_buf);
+ LocalFree(msg_buf);
+ return ret;
+}
+
+static DWORD RunExe(const tstring& exe_name) {
+ STARTUPINFO startup_info = { sizeof(STARTUPINFO) };
+ PROCESS_INFORMATION process_info;
+ DWORD exit_code;
+
+ GetStartupInfo(&startup_info);
+ tstring cmdline = tstring(GetCommandLine());
+
+ size_t first_space = cmdline.find(' ');
+ if (first_space == -1) {
+ // I'm not sure why this would ever happen, but just in case...
+ cmdline = exe_name;
+ } else {
+ cmdline = exe_name + cmdline.substr(first_space);
+ }
+
+ if (!CreateProcess(NULL, // lpApplicationName
+ const_cast<TCHAR*>(cmdline.c_str()),
+ NULL, // lpProcessAttributes
+ NULL, // lpThreadAttributes
+ TRUE, // bInheritHandles
+ 0, // dwCreationFlags,
+ NULL, // lpEnvironment,
+ NULL, // lpCurrentDirectory,
+ &startup_info,
+ &process_info)) {
+ Error(L"Error in CreateProcess[%s]: %s",
+ cmdline.c_str(), ErrorMessageToString(GetLastError()).c_str());
+ return MAXDWORD;
+ }
+ CloseHandle(process_info.hThread);
+ WaitForSingleObject(process_info.hProcess, INFINITE);
+ GetExitCodeProcess(process_info.hProcess, &exit_code);
+ CloseHandle(process_info.hProcess);
+ return exit_code;
+}
+
+// Returns 0 if there was an error
+static int CpuConcurrencyMetric(const tstring& envvar_name) {
+ int max_concurrent = 0;
+ std::vector<char> buffer(1);
+ BOOL ok = false;
+ DWORD last_error = 0;
+ do {
+ DWORD bufsize = buffer.size();
+ ok = GetLogicalProcessorInformation(
+ reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>(&buffer[0]),
+ &bufsize);
+ last_error = GetLastError();
+ if (!ok && last_error == ERROR_INSUFFICIENT_BUFFER &&
+ bufsize > buffer.size()) {
+ buffer.resize(bufsize);
+ }
+ } while (!ok && last_error == ERROR_INSUFFICIENT_BUFFER);
+
+ if (!ok) {
+ Warn(L"Error while getting number of cores. Try setting the "
+ L" environment variable '%s' to (num_cores - 1): %s",
+ envvar_name.c_str(), ErrorMessageToString(last_error).c_str());
+ return 0;
+ }
+
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION pproc_info =
+ reinterpret_cast<PSYSTEM_LOGICAL_PROCESSOR_INFORMATION>(&buffer[0]);
+ int num_entries = buffer.size() /
+ sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+
+ for (int i = 0; i < num_entries; ++i) {
+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION& info = pproc_info[i];
+ if (info.Relationship == RelationProcessorCore) {
+ ++max_concurrent;
+ }
+ }
+
+ // Leave one core for other tasks
+ return max_concurrent - 1;
+}
+
+// TODO(defaults): Create a better heuristic than # of CPUs. It seems likely
+// that the right value will, in fact, be based on the memory capacity of the
+// machine, not on the number of CPUs.
+enum ConcurrencyMetricEnum {
+ CONCURRENCY_METRIC_ONE,
+ CONCURRENCY_METRIC_CPU,
+ CONCURRENCY_METRIC_DEFAULT = CONCURRENCY_METRIC_CPU
+};
+
+static int GetMaxConcurrency(const tstring& base_pipename,
+ ConcurrencyMetricEnum metric) {
+ static int max_concurrent = -1;
+
+ if (max_concurrent == -1) {
+ tstring envvar_name = base_pipename + L"_MAXCONCURRENCY";
+
+ const LPTSTR max_concurrent_str = _wgetenv(envvar_name.c_str());
+ max_concurrent = max_concurrent_str ? _wtoi(max_concurrent_str) : 0;
+
+ if (max_concurrent == 0) {
+ switch (metric) {
+ case CONCURRENCY_METRIC_CPU:
+ max_concurrent = CpuConcurrencyMetric(envvar_name);
+ if (max_concurrent)
+ break;
+ // else fall through
+ case CONCURRENCY_METRIC_ONE:
+ max_concurrent = 1;
+ break;
+ }
+ }
+
+ max_concurrent = std::min(std::max(max_concurrent, 1),
+ PIPE_UNLIMITED_INSTANCES);
+ }
+
+ return max_concurrent;
+}
+
+static HANDLE WaitForPipe(const tstring& pipename,
+ HANDLE event,
+ int max_concurrency) {
+ // We're using a named pipe instead of a semaphore so the Kernel can clean up
+ // after us if we crash while holding onto the pipe (A real semaphore will
+ // not release on process termination).
+ HANDLE pipe = INVALID_HANDLE_VALUE;
+ for (;;) {
+ pipe = CreateNamedPipe(
+ pipename.c_str(),
+ PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_BYTE,
+ max_concurrency,
+ 1, // nOutBufferSize
+ 1, // nInBufferSize
+ 0, // nDefaultTimeOut
+ NULL); // Default security attributes (noinherit)
+ if (pipe != INVALID_HANDLE_VALUE)
+ break;
+
+ DWORD error = GetLastError();
+ if (error == ERROR_PIPE_BUSY) {
+ if (event) {
+ WaitForSingleObject(event, 60 * 1000 /* ms */);
+ } else {
+ // TODO(iannucci): Maybe we should error out here instead of falling
+ // back to a sleep-poll
+ Sleep(5 * 1000 /* ms */);
+ }
+ } else {
+ Warn(L"Got error %d while waiting for pipe: %s", error,
+ ErrorMessageToString(error).c_str());
+ return INVALID_HANDLE_VALUE;
+ }
+ }
+
+ return pipe;
+}
+
+static int WaitAndRun(const tstring& shimmed_exe,
+ const tstring& base_pipename) {
+ ULONGLONG start_time = 0, end_time = 0;
+ tstring pipename = L"\\\\.\\pipe\\" + base_pipename;
+ tstring event_name = L"Local\\EVENT_" + base_pipename;
+
+ // This event lets us do better than strict polling, but we don't rely on it
+ // (in case a process crashes before signalling the event).
+ HANDLE event = CreateEvent(
+ NULL, // Default security attributes
+ FALSE, // Manual reset
+ FALSE, // Initial state
+ event_name.c_str());
+
+ if (g_is_debug)
+ start_time = GetTickCount64();
+
+ HANDLE pipe =
+ WaitForPipe(pipename, event,
+ GetMaxConcurrency(base_pipename, CONCURRENCY_METRIC_DEFAULT));
+
+ if (g_is_debug) {
+ end_time = GetTickCount64();
+ wprintf(L" took %.2fs to acquire semaphore.\n",
+ (end_time - start_time) / 1000.0);
+ }
+
+ DWORD ret = RunExe(shimmed_exe);
+
+ if (pipe != INVALID_HANDLE_VALUE)
+ CloseHandle(pipe);
+ if (event != NULL)
+ SetEvent(event);
+
+ return ret;
+}
+
+void Usage(const tstring& msg) {
+ tstring usage(msg);
+ usage += L"\n"
+ L"Usage: SHIMED_NAME__SEMAPHORE_NAME\n"
+ L"\n"
+ L" SHIMMED_NAME - ex. 'link.exe' or 'lib.exe'\n"
+ L" - can be exe, bat, or com\n"
+ L" - must exist in PATH\n"
+ L"\n"
+ L" SEMAPHORE_NAME - ex. 'SOME_NAME' or 'GROOVY_SEMAPHORE'\n"
+ L"\n"
+ L" Example:\n"
+ L" link.exe__LINK_LIMITER.exe\n"
+ L" lib.exe__LINK_LIMITER.exe\n"
+ L" * Both will limit on the same semaphore\n"
+ L"\n"
+ L" link.exe__LINK_LIMITER.exe\n"
+ L" lib.exe__LIB_LIMITER.exe\n"
+ L" * Both will limit on independent semaphores\n"
+ L"\n"
+ L" This program is meant to be run after renaming it into the\n"
+ L" above format. Once you have done so, executing it will block\n"
+ L" on the availability of the semaphore SEMAPHORE_NAME. Once\n"
+ L" the semaphore is obtained, it will execute SHIMMED_NAME, \n"
+ L" passing through all arguments as-is.\n"
+ L"\n"
+ L" The maximum concurrency can be manually set by setting the\n"
+ L" environment variable <SEMAPHORE_NAME>_MAXCONCURRENCY to an\n"
+ L" integer value (1, 254).\n"
+ L" * This value must be set the same for ALL invocations.\n"
+ L" * If the value is not set, it defaults to (num_cores-1).\n"
+ L"\n"
+ L" The semaphore is automatically released when the program\n"
+ L" completes normally, OR if the program crashes (or even if\n"
+ L" limiter itself crashes).\n";
+ Error(usage.c_str());
+ exit(-1);
+}
+
+// Input command line is assumed to be of the form:
+//
+// thing.exe__PIPE_NAME.exe ...
+//
+// Specifically, wait for a semaphore (whose concurrency is specified by
+// LIMITER_MAXCONCURRENT), and then pass through everything once we have
+// acquired the semaphore.
+//
+// argv[0] is parsed for:
+// * exe_to_shim_including_extension.exe
+// * This could also be a bat or com. Anything that CreateProcess will
+// accept.
+// * "__"
+// * We search for this separator from the end of argv[0], so the exe name
+// could contain a double underscore if necessary.
+// * PIPE_NAME
+// * Can only contain single underscores, not a double underscore.
+// * i.e. HELLO_WORLD_PIPE will work, but HELLO__WORLD_PIPE will not.
+// * This would allow the shimmed exe to contain arbitrary numbers of
+// underscores. We control the pipe name, but not necessarily the thing
+// we're shimming.
+//
+int wmain(int, wchar_t** argv) {
+ tstring shimmed_plus_pipename = argv[0];
+ size_t last_slash = shimmed_plus_pipename.find_last_of(L"/\\");
+ if (last_slash != tstring::npos) {
+ shimmed_plus_pipename = shimmed_plus_pipename.substr(last_slash + 1);
+ }
+
+ size_t separator = shimmed_plus_pipename.rfind(L"__");
+ if (separator == tstring::npos) {
+ Usage(L"Cannot parse argv[0]. No '__' found. "
+ L"Should be like '[...(\\|/)]link.exe__PIPE_NAME.exe'");
+ }
+ tstring shimmed_exe = shimmed_plus_pipename.substr(0, separator);
+ tstring base_pipename = shimmed_plus_pipename.substr(separator + 2);
+
+ size_t dot = base_pipename.find(L'.');
+ if (dot == tstring::npos) {
+ Usage(L"Expected an executable extension in argv[0]. No '.' found.");
+ }
+ base_pipename = base_pipename.substr(0, dot);
+
+ return WaitAndRun(shimmed_exe, base_pipename);
+}
+
diff --git a/chromium/tools/win/sizeviewer/README.chromium b/chromium/tools/win/sizeviewer/README.chromium
new file mode 100644
index 00000000000..5d093e3c957
--- /dev/null
+++ b/chromium/tools/win/sizeviewer/README.chromium
@@ -0,0 +1,2 @@
+code_tally.exe binary from
+http://syzygy-archive.commondatastorage.googleapis.com/index.html?path=builds/official/1626/
diff --git a/chromium/tools/win/sizeviewer/code_tally.exe b/chromium/tools/win/sizeviewer/code_tally.exe
new file mode 100755
index 00000000000..7898b67414f
--- /dev/null
+++ b/chromium/tools/win/sizeviewer/code_tally.exe
Binary files differ
diff --git a/chromium/tools/win/sizeviewer/sizeviewer.py b/chromium/tools/win/sizeviewer/sizeviewer.py
new file mode 100644
index 00000000000..defb00a4b85
--- /dev/null
+++ b/chromium/tools/win/sizeviewer/sizeviewer.py
@@ -0,0 +1,95 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import string
+import subprocess
+import sys
+
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def Run(*args):
+ with open(os.devnull, 'w') as null:
+ subprocess.check_call(args, stdout=null, stderr=null)
+
+
+def FindNode(node, component):
+ for child in node['children']:
+ if child['name'] == component:
+ return child
+ return None
+
+
+def InsertIntoTree(tree, source_name, size):
+ components = source_name.replace(':', '').split('\\')
+ node = tree
+ for index, component in enumerate(components):
+ data = FindNode(node, component)
+ if not data:
+ data = { 'name': component }
+ if index == len(components) - 1:
+ data['size'] = size
+ else:
+ data['children'] = []
+ node['children'].append(data)
+ node = data
+
+
+def main():
+ out_dir = os.path.join(BASE_DIR, '..', '..', '..', 'out', 'Release')
+ jsons = []
+ for dll in ('chrome.dll', 'chrome_child.dll'):
+ dll_path = os.path.normpath(os.path.join(out_dir, dll))
+ if os.path.exists(dll_path):
+ print 'Tallying %s...' % dll_path
+ json_path = dll_path + '.json'
+ Run(os.path.join(BASE_DIR, 'code_tally.exe'),
+ '--input-image=' + dll_path,
+ '--input-pdb=' + dll_path + '.pdb',
+ '--output-file=' + json_path)
+ jsons.append(json_path)
+ if not jsons:
+ print 'Couldn\'t find binaries, looking in', out_dir
+ return 1
+
+ for json_name in jsons:
+ with open(json_name, 'r') as jsonf:
+ all_data = json.load(jsonf)
+ html_path = os.path.splitext(json_name)[0] + '.html'
+ print 'Generating %s...' % html_path
+ by_source = {}
+ for obj_name, obj_data in all_data['objects'].iteritems():
+ for symbol, symbol_data in obj_data.iteritems():
+ size = int(symbol_data['size'])
+ # Sometimes there's symbols with no source file, we just ignore those.
+ if 'contribs' in symbol_data:
+ # There may be more than one file in the list, we just assign to the
+ # first source file that contains the symbol, rather than try to
+ # split or duplicate info.
+ src_index = symbol_data['contribs'][0]
+ source = all_data['sources'][int(src_index)]
+ if source not in by_source:
+ by_source[source] = []
+ by_source[source].append(size)
+ binary_name = all_data['executable']['name']
+ data = {}
+ data['name'] = binary_name
+ data['children'] = []
+ for source, sizes in by_source.iteritems():
+ InsertIntoTree(data, source, sum(sizes))
+ with open(html_path, 'w') as f:
+ with open(os.path.join(BASE_DIR, 'template.html'), 'r') as templatef:
+ template = templatef.read()
+ f.write(string.Template(template).substitute(
+ {'data': json.dumps(data, indent=2),
+ 'dllname': binary_name + ' ' + all_data['executable']['version']}))
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/win/sizeviewer/template.html b/chromium/tools/win/sizeviewer/template.html
new file mode 100644
index 00000000000..ffbffbb1f15
--- /dev/null
+++ b/chromium/tools/win/sizeviewer/template.html
@@ -0,0 +1,199 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
+ <link type="text/css" rel="stylesheet" href="style.css"/>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <style type="text/css">
+
+body {
+ overflow: hidden;
+ margin: 0;
+ font-size: 14px;
+ font-family: "Helvetica Neue", Helvetica;
+}
+
+#chart, #header, #footer {
+ position: absolute;
+ top: 0;
+}
+
+#header, #footer {
+ z-index: 1;
+ display: block;
+ font-size: 36px;
+ font-weight: 300;
+ text-shadow: 0 1px 0 #fff;
+}
+
+#header.inverted, #footer.inverted {
+ color: #fff;
+ text-shadow: 0 1px 4px #000;
+}
+
+#header {
+ top: 80px;
+ left: 140px;
+ width: 1000px;
+}
+
+#footer {
+ top: 1080px;
+ right: 140px;
+ text-align: right;
+}
+
+rect {
+ fill: none;
+ pointer-events: all;
+}
+
+pre {
+ font-size: 18px;
+}
+
+line {
+ stroke: #000;
+ stroke-width: 1.5px;
+}
+
+.string, .regexp {
+ color: #f39;
+}
+
+.keyword {
+ color: #00c;
+}
+
+.comment {
+ color: #777;
+ font-style: oblique;
+}
+
+.number {
+ color: #369;
+}
+
+.class, .special {
+ color: #1181B8;
+}
+
+a:link, a:visited {
+ color: #000;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #666;
+}
+
+.hint {
+ position: absolute;
+ right: 0;
+ width: 1280px;
+ font-size: 12px;
+ color: #999;
+}
+.chart {
+ display: block;
+ margin: auto;
+ margin-top: 60px;
+ font-size: 11px;
+}
+
+rect {
+ stroke: #eee;
+ fill: #aaa;
+ fill-opacity: .8;
+}
+
+rect.parent {
+ cursor: pointer;
+ fill: steelblue;
+}
+
+text {
+ pointer-events: none;
+}
+
+ </style>
+ </head>
+ <body>
+ <div id="body">
+ <div id="footer">
+ $dllname
+ </div>
+ </div>
+ <script type="text/javascript">
+
+var w = 1120,
+ h = 1000,
+ x = d3.scale.linear().range([0, w]),
+ y = d3.scale.linear().range([0, h]);
+
+var vis = d3.select("#body").append("div")
+ .attr("class", "chart")
+ .style("width", w + "px")
+ .style("height", h + "px")
+ .append("svg:svg")
+ .attr("width", w)
+ .attr("height", h);
+
+var partition = d3.layout.partition()
+ .value(function(d) { return d.size; });
+
+(function(root) {
+ var g = vis.selectAll("g")
+ .data(partition.nodes(root))
+ .enter().append("svg:g")
+ .attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; })
+ .on("click", click);
+
+ var kx = w / root.dx,
+ ky = h / 1;
+
+ g.append("svg:rect")
+ .attr("width", root.dy * kx)
+ .attr("height", function(d) { return d.dx * ky; })
+ .attr("class", function(d) { return d.children ? "parent" : "child"; });
+
+ g.append("svg:text")
+ .attr("transform", transform)
+ .attr("dy", ".35em")
+ .style("opacity", function(d) { return d.dx * ky > 12 ? 1 : 0; })
+ .text(function(d) { return d.name; })
+
+ d3.select(window)
+ .on("click", function() { click(root); })
+
+ function click(d) {
+ if (!d.children) return;
+
+ kx = (d.y ? w - 40 : w) / (1 - d.y);
+ ky = h / d.dx;
+ x.domain([d.y, 1]).range([d.y ? 40 : 0, w]);
+ y.domain([d.x, d.x + d.dx]);
+
+ var t = g.transition()
+ .duration(d3.event.altKey ? 7500 : 750)
+ .attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; });
+
+ t.select("rect")
+ .attr("width", d.dy * kx)
+ .attr("height", function(d) { return d.dx * ky; });
+
+ t.select("text")
+ .attr("transform", transform)
+ .style("opacity", function(d) { return d.dx * ky > 12 ? 1 : 0; });
+
+ d3.event.stopPropagation();
+ }
+
+ function transform(d) {
+ return "translate(8," + d.dx * ky / 2 + ")";
+ }
+})($data);
+
+ </script>
+ </body>
+</html>
diff --git a/chromium/tools/win/split_link/check_installed.py b/chromium/tools/win/split_link/check_installed.py
new file mode 100644
index 00000000000..31bf60f1217
--- /dev/null
+++ b/chromium/tools/win/split_link/check_installed.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+
+def IsAvailable():
+ _winreg = None
+ if sys.platform == 'win32':
+ import _winreg
+ elif sys.platform == 'cygwin':
+ try:
+ import cygwinreg as _winreg
+ except ImportError:
+ pass # If not available, be safe and write 0.
+
+ if not _winreg:
+ return False
+
+ try:
+ val = _winreg.QueryValue(_winreg.HKEY_CURRENT_USER,
+ 'Software\\Chromium\\split_link_installed')
+ return os.path.exists(val)
+ except WindowsError:
+ pass
+
+ return False
+
+
+def main():
+ # Can be called from gyp to set variable.
+ if IsAvailable():
+ sys.stdout.write('1')
+ else:
+ print >> sys.stderr, "Couldn't find split_link installation."
+ print >> sys.stderr, ('Run python tools\\win\\split_link\\'
+ 'install_split_link.py from an elevated Visual '
+ 'Studio Command Prompt to install.')
+ sys.stdout.write('0')
+ return 1
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/win/split_link/graph_dependencies.py b/chromium/tools/win/split_link/graph_dependencies.py
new file mode 100644
index 00000000000..f95e076d392
--- /dev/null
+++ b/chromium/tools/win/split_link/graph_dependencies.py
@@ -0,0 +1,89 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import shutil
+import subprocess
+import sys
+
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def main():
+ if len(sys.argv) != 2:
+ print 'usage: %s <output.html>' % sys.argv[0]
+ return 1
+ env = os.environ.copy()
+ env['GYP_GENERATORS'] = 'dump_dependency_json'
+ print 'Dumping dependencies...'
+ popen = subprocess.Popen(
+ ['python', 'build/gyp_chromium'],
+ shell=True, env=env)
+ popen.communicate()
+ if popen.returncode != 0:
+ return popen.returncode
+ print 'Finding problems...'
+ popen = subprocess.Popen(
+ ['python', 'tools/gyp-explain.py', '--dot',
+ 'chrome.gyp:browser#', 'core.gyp:webcore#'],
+ stdout=subprocess.PIPE,
+ shell=True)
+ out, _ = popen.communicate()
+ if popen.returncode != 0:
+ return popen.returncode
+
+ # Break into pairs to uniq to make graph less of a mess.
+ print 'Simplifying...'
+ deduplicated = set()
+ lines = out.splitlines()[2:-1]
+ for line in lines:
+ line = line.strip('\r\n ;')
+ pairs = line.split(' -> ')
+ for i in range(len(pairs) - 1):
+ deduplicated.add('%s -> %s;' % (pairs[i], pairs[i + 1]))
+ graph = 'strict digraph {\n' + '\n'.join(sorted(deduplicated)) + '\n}'
+
+ print 'Writing report to %s...' % sys.argv[1]
+ path_count = len(out.splitlines())
+ with open(os.path.join(BASE_DIR, 'viz.js', 'viz.js')) as f:
+ viz_js = f.read()
+ with open(sys.argv[1], 'w') as f:
+ f.write(PREFIX % path_count)
+ f.write(graph)
+ f.write(SUFFIX % viz_js)
+ print 'Done.'
+
+
+PREFIX = r'''<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Undesirable Dependencies</title>
+ </head>
+ <body>
+ <h1>Undesirable Dependencies</h1>
+<h2>browser &rarr; webcore</h2>
+<h3>%d paths</h3>
+ <script type="text/vnd.graphviz" id="graph">
+'''
+
+
+SUFFIX = r'''
+ </script>
+ <script>%s</script>
+ <div id="output">Rendering...</div>
+ <script>
+ setTimeout(function() {
+ document.getElementById("output").innerHTML =
+ Viz(document.getElementById("graph").innerHTML, "svg");
+ }, 1);
+ </script>
+ </body>
+</html>
+'''
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/win/split_link/install_split_link.py b/chromium/tools/win/split_link/install_split_link.py
new file mode 100644
index 00000000000..309b5116a2c
--- /dev/null
+++ b/chromium/tools/win/split_link/install_split_link.py
@@ -0,0 +1,100 @@
+# Copyright (c) 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import _winreg
+import os
+import shutil
+import subprocess
+import sys
+
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def IsExe(fpath):
+ return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
+
+
+def FindInPath(program):
+ fpath, _ = os.path.split(program)
+ if fpath:
+ if IsExe(program):
+ return program
+ else:
+ for path in os.environ['PATH'].split(os.pathsep):
+ path = path.strip('"')
+ exe_file = os.path.join(path, program)
+ if not path or not os.path.isabs(path):
+ continue
+ if IsExe(exe_file):
+ return exe_file
+ return None
+
+
+def EscapeForCommandLineAndCString(path):
+ """Quoted sufficiently to be passed on the compile command line as a define
+ to be turned into a string in the target C program."""
+ path = '"' + path + '"'
+ return path.replace('\\', '\\\\').replace('"', '\\"')
+
+
+def main():
+ # Switch to our own dir.
+ os.chdir(BASE_DIR)
+
+ link = FindInPath('link.exe')
+ mt = FindInPath('mt.exe')
+ if not link or not mt:
+ print("Couldn't find link.exe or mt.exe in PATH. "
+ "Must run from Administrator Visual Studio Command Prompt.")
+ return 1
+
+ link_backup = os.path.join(os.path.split(link)[0], 'link.exe.split_link.exe')
+
+ # Don't re-backup link.exe, so only copy link.exe to backup if it's
+ # not there already.
+ if not os.path.exists(link_backup):
+ try:
+ print 'Saving original link.exe...'
+ shutil.copyfile(link, link_backup)
+ except IOError:
+ print(("Wasn't able to back up %s to %s. "
+ "Not running with Administrator privileges?")
+ % (link, link_backup))
+ return 1
+
+ # Build our linker shim.
+ print 'Building split_link.exe...'
+ split_link_py = os.path.abspath('split_link.py')
+ script_path = EscapeForCommandLineAndCString(split_link_py)
+ python = EscapeForCommandLineAndCString(sys.executable)
+ subprocess.check_call('cl.exe /nologo /Ox /Zi /W4 /WX /D_UNICODE /DUNICODE'
+ ' /D_CRT_SECURE_NO_WARNINGS /EHsc split_link.cc'
+ ' /DPYTHON_PATH="%s"'
+ ' /DSPLIT_LINK_SCRIPT_PATH="%s"'
+ ' /link shell32.lib shlwapi.lib /out:split_link.exe' % (
+ python, script_path))
+
+ # Copy shim into place.
+ print 'Copying split_link.exe over link.exe...'
+ try:
+ shutil.copyfile('split_link.exe', link)
+ _winreg.SetValue(_winreg.HKEY_CURRENT_USER,
+ 'Software\\Chromium\\split_link_installed',
+ _winreg.REG_SZ,
+ link_backup)
+ _winreg.SetValue(_winreg.HKEY_CURRENT_USER,
+ 'Software\\Chromium\\split_link_mt_path',
+ _winreg.REG_SZ,
+ mt)
+ except IOError:
+ print("Wasn't able to copy split_link.exe over %s. "
+ "Not running with Administrator privileges?" % link)
+ return 1
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/win/split_link/split_link.cc b/chromium/tools/win/split_link/split_link.cc
new file mode 100644
index 00000000000..dab06188c30
--- /dev/null
+++ b/chromium/tools/win/split_link/split_link.cc
@@ -0,0 +1,258 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+#include <shlwapi.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+#include <vector>
+
+#ifndef SPLIT_LINK_SCRIPT_PATH
+#error SPLIT_LINK_SCRIPT_PATH must be defined as the path to "split_link.py".
+#endif
+
+#ifndef PYTHON_PATH
+#error PYTHON_PATH must be defined to be the path to the python binary.
+#endif
+
+#define WIDEN2(x) L ## x
+#define WIDEN(x) WIDEN2(x)
+#define WPYTHON_PATH WIDEN(PYTHON_PATH)
+#define WSPLIT_LINK_SCRIPT_PATH WIDEN(SPLIT_LINK_SCRIPT_PATH)
+
+using namespace std;
+
+// Don't use stderr for errors because VS has large buffers on them, leading
+// to confusing error output.
+static void Fatal(const wchar_t* msg) {
+ wprintf(L"split_link fatal error: %s\n", msg);
+ exit(1);
+}
+
+static wstring ErrorMessageToString(DWORD err) {
+ wchar_t* msg_buf = NULL;
+ DWORD rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ reinterpret_cast<LPTSTR>(&msg_buf),
+ 0,
+ NULL);
+ if (!rc)
+ return L"unknown error";
+ wstring ret(msg_buf);
+ LocalFree(msg_buf);
+ return ret;
+}
+
+static void ArgvQuote(const std::wstring& argument,
+ std::wstring* command_line) {
+ // Don't quote unless we actually need to.
+ if (!argument.empty() &&
+ argument.find_first_of(L" \t\n\v\"") == argument.npos) {
+ command_line->append(argument);
+ } else {
+ command_line->push_back(L'"');
+ for (std::wstring::const_iterator it = argument.begin();; ++it) {
+ int num_backslashes = 0;
+ while (it != argument.end() && *it == L'\\') {
+ ++it;
+ ++num_backslashes;
+ }
+ if (it == argument.end()) {
+ // Escape all backslashes, but let the terminating double quotation
+ // mark we add below be interpreted as a metacharacter.
+ command_line->append(num_backslashes * 2, L'\\');
+ break;
+ } else if (*it == L'"') {
+ // Escape all backslashes and the following double quotation mark.
+ command_line->append(num_backslashes * 2 + 1, L'\\');
+ command_line->push_back(*it);
+ } else {
+ // Backslashes aren't special here.
+ command_line->append(num_backslashes, L'\\');
+ command_line->push_back(*it);
+ }
+ }
+ command_line->push_back(L'"');
+ }
+}
+
+// Does the opposite of CommandLineToArgvW. Suitable for CreateProcess, but
+// not for cmd.exe. |args| should include the program name as argv[0].
+// See http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
+static wstring BuildCommandLine(const vector<wstring>& args) {
+ std::wstring result;
+ for (size_t i = 0; i < args.size(); ++i) {
+ ArgvQuote(args[i], &result);
+ if (i < args.size() - 1) {
+ result += L" ";
+ }
+ }
+ return result;
+}
+
+static void RunLinker(const vector<wstring>& prefix, const wchar_t* msg) {
+ if (msg) {
+ wprintf(L"split_link failed (%s), trying to fallback to standard link.\n",
+ msg);
+ wprintf(L"Original command line: %s\n", GetCommandLine());
+ fflush(stdout);
+ }
+
+ STARTUPINFO startup_info = { sizeof(STARTUPINFO) };
+ PROCESS_INFORMATION process_info;
+ DWORD exit_code;
+
+ GetStartupInfo(&startup_info);
+
+ if (getenv("SPLIT_LINK_DEBUG")) {
+ wprintf(L" original command line '%s'\n", GetCommandLine());
+ fflush(stdout);
+ }
+
+ int num_args;
+ LPWSTR* args = CommandLineToArgvW(GetCommandLine(), &num_args);
+ if (!args)
+ Fatal(L"Couldn't parse command line.");
+ vector<wstring> argv;
+ argv.insert(argv.end(), prefix.begin(), prefix.end());
+ for (int i = 1; i < num_args; ++i) // Skip old argv[0].
+ argv.push_back(args[i]);
+ LocalFree(args);
+
+ wstring cmd = BuildCommandLine(argv);
+
+ if (getenv("SPLIT_LINK_DEBUG")) {
+ wprintf(L" running '%s'\n", cmd.c_str());
+ fflush(stdout);
+ }
+ if (!CreateProcess(NULL,
+ reinterpret_cast<LPWSTR>(const_cast<wchar_t *>(
+ cmd.c_str())),
+ NULL,
+ NULL,
+ TRUE,
+ 0,
+ NULL,
+ NULL,
+ &startup_info, &process_info)) {
+ wstring error = ErrorMessageToString(GetLastError());
+ Fatal(error.c_str());
+ }
+ CloseHandle(process_info.hThread);
+ WaitForSingleObject(process_info.hProcess, INFINITE);
+ GetExitCodeProcess(process_info.hProcess, &exit_code);
+ CloseHandle(process_info.hProcess);
+ exit(exit_code);
+}
+
+static void Fallback(const wchar_t* msg) {
+ wchar_t original_link[1024];
+ DWORD type;
+ DWORD size = sizeof(original_link);
+ if (SHGetValue(HKEY_CURRENT_USER,
+ L"Software\\Chromium\\split_link_installed",
+ NULL,
+ &type,
+ original_link,
+ &size) != ERROR_SUCCESS || type != REG_SZ) {
+ Fatal(L"Couldn't retrieve linker location from "
+ L"HKCU\\Software\\Chromium\\split_link_installed.");
+ }
+ if (getenv("SPLIT_LINK_DEBUG")) {
+ wprintf(L" got original linker '%s'\n", original_link);
+ fflush(stdout);
+ }
+ vector<wstring> link_binary;
+ link_binary.push_back(original_link);
+ RunLinker(link_binary, msg);
+}
+
+static void Fallback() {
+ Fallback(NULL);
+}
+
+static unsigned char* SlurpFile(const wchar_t* path, size_t* length) {
+ HANDLE file = CreateFile(
+ path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if (file == INVALID_HANDLE_VALUE)
+ Fallback(L"couldn't open file");
+ LARGE_INTEGER file_size;
+ if (!GetFileSizeEx(file, &file_size))
+ Fallback(L"couldn't get file size");
+ *length = static_cast<size_t>(file_size.QuadPart);
+ unsigned char* buffer = static_cast<unsigned char*>(malloc(*length));
+ DWORD bytes_read = 0;
+ if (!ReadFile(file, buffer, *length, &bytes_read, NULL))
+ Fallback(L"couldn't read file");
+ return buffer;
+}
+
+static bool SplitLinkRequested(const wchar_t* rsp_path) {
+ size_t length;
+ unsigned char* data = SlurpFile(rsp_path, &length);
+ bool flag_found = false;
+ if (data[0] == 0xff && data[1] == 0xfe) {
+ // UTF-16LE
+ wstring wide(reinterpret_cast<wchar_t*>(&data[2]),
+ length / sizeof(wchar_t) - 1);
+ flag_found = wide.find(L"/splitlink") != wide.npos;
+ } else {
+ string narrow(reinterpret_cast<char*>(data), length);
+ flag_found = narrow.find("/splitlink") != narrow.npos;
+ }
+ free(data);
+ return flag_found;
+}
+
+// If /splitlink is on the command line, delegate to split_link.py, otherwise
+// fallback to standard linker.
+int wmain(int argc, wchar_t** argv) {
+ int rsp_file_index = -1;
+
+ if (argc < 2)
+ Fallback();
+
+ for (int i = 1; i < argc; ++i) {
+ if (argv[i][0] == L'@') {
+ rsp_file_index = i;
+ break;
+ }
+ }
+
+ if (rsp_file_index == -1)
+ Fallback(L"couldn't find a response file in argv");
+
+ if (getenv("SPLIT_LINK_DEBUG")) {
+ wstring backup_copy(&argv[rsp_file_index][1]);
+ backup_copy += L".copy";
+ wchar_t buf[1024];
+ swprintf(buf,
+ sizeof(buf),
+ L"copy %s %s",
+ &argv[rsp_file_index][1],
+ backup_copy.c_str());
+ if (_wsystem(buf) == 0)
+ wprintf(L"Saved original rsp as %s\n", backup_copy.c_str());
+ else
+ wprintf(L"'%s' failed.", buf);
+ }
+
+ if (SplitLinkRequested(&argv[rsp_file_index][1])) {
+ vector<wstring> link_binary;
+ link_binary.push_back(WPYTHON_PATH);
+ link_binary.push_back(WSPLIT_LINK_SCRIPT_PATH);
+ RunLinker(link_binary, NULL);
+ }
+
+ // Otherwise, run regular linker silently.
+ Fallback();
+}
diff --git a/chromium/tools/win/split_link/split_link.py b/chromium/tools/win/split_link/split_link.py
new file mode 100644
index 00000000000..791bc90fca5
--- /dev/null
+++ b/chromium/tools/win/split_link/split_link.py
@@ -0,0 +1,420 @@
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Takes the same arguments as Windows link.exe, and a definition of libraries
+to split into subcomponents. Does multiple passes of link.exe invocation to
+determine exports between parts and generates .def and import libraries to
+cause symbols to be available to other parts."""
+
+import _winreg
+import ctypes
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+# This can be set to ignore data exports. The resulting DLLs will probably not
+# run, but at least they can be generated. The log of data exports will still
+# be output.
+IGNORE_DATA = 0
+
+
+def Log(message):
+ print 'split_link:', message
+
+
+def GetFlagsAndInputs(argv):
+ """Parses the command line intended for link.exe and return the flags and
+ input files."""
+ rsp_expanded = []
+ for arg in argv:
+ if arg[0] == '@':
+ with open(arg[1:]) as rsp:
+ rsp_expanded.extend(rsp.read().splitlines())
+ else:
+ rsp_expanded.append(arg)
+
+ # Use CommandLineToArgvW so we match link.exe parsing.
+ try:
+ size = ctypes.c_int()
+ ptr = ctypes.windll.shell32.CommandLineToArgvW(
+ ctypes.create_unicode_buffer(' '.join(rsp_expanded)),
+ ctypes.byref(size))
+ ref = ctypes.c_wchar_p * size.value
+ raw = ref.from_address(ptr)
+ args = [arg for arg in raw]
+ finally:
+ ctypes.windll.kernel32.LocalFree(ptr)
+
+ inputs = []
+ flags = []
+ intermediate_manifest = ''
+ for arg in args:
+ lower_arg = arg.lower()
+ # We'll be replacing these ourselves.
+ if lower_arg.startswith('/out:'):
+ continue
+ if lower_arg.startswith('/manifestfile:'):
+ intermediate_manifest = arg[arg.index(':')+1:]
+ continue
+ if lower_arg.startswith('/pdb:'):
+ continue
+ if (not lower_arg.startswith('/') and
+ lower_arg.endswith(('.obj', '.lib', '.res'))):
+ inputs.append(arg)
+ else:
+ flags.append(arg)
+
+ return flags, inputs, intermediate_manifest
+
+
+def GetRegistryValue(subkey):
+ try:
+ val = _winreg.QueryValue(_winreg.HKEY_CURRENT_USER,
+ 'Software\\Chromium\\' + subkey)
+ if os.path.exists(val):
+ return val
+ except WindowsError:
+ pass
+
+ raise SystemExit("Couldn't read from registry")
+
+
+def GetOriginalLinkerPath():
+ return GetRegistryValue('split_link_installed')
+
+
+def GetMtPath():
+ return GetRegistryValue('split_link_mt_path')
+
+
+def PartFor(input_file, description_parts, description_all):
+ """Determines which part a given link input should be put into (or all)."""
+ # Check if it should go in all parts.
+ input_file = input_file.lower()
+ if any(re.search(spec, input_file) for spec in description_all):
+ return -1
+ # Or pick which particular one it belongs in.
+ for i, spec_list in enumerate(description_parts):
+ if any(re.search(spec, input_file) for spec in spec_list):
+ return i
+ raise ValueError("couldn't find location for %s" % input_file)
+
+
+def ParseOutExternals(output):
+ """Given the stdout of link.exe, parses the error messages to retrieve all
+ symbols that are unresolved."""
+ result = set()
+ # Styles of messages for unresolved externals, and a boolean to indicate
+ # whether the error message emits the symbols with or without a leading
+ # underscore.
+ unresolved_regexes = [
+ (re.compile(r' : error LNK2019: unresolved external symbol ".*" \((.*)\)'
+ r' referenced in function'),
+ False),
+ (re.compile(r' : error LNK2001: unresolved external symbol ".*" \((.*)\)$'),
+ False),
+ (re.compile(r' : error LNK2019: unresolved external symbol (.*)'
+ r' referenced in function '),
+ True),
+ (re.compile(r' : error LNK2001: unresolved external symbol (.*)$'),
+ True),
+ ]
+ for line in output.splitlines():
+ line = line.strip()
+ for regex, strip_leading_underscore in unresolved_regexes:
+ mo = regex.search(line)
+ if mo:
+ if strip_leading_underscore:
+ result.add(mo.group(1)[1:])
+ else:
+ result.add(mo.group(1))
+ break
+
+ mo = re.search(r'fatal error LNK1120: (\d+) unresolved externals', output)
+ # Make sure we have the same number that the linker thinks we have.
+ if mo is None and result:
+ raise SystemExit(output)
+ if len(result) != int(mo.group(1)):
+ print output
+ print 'Expecting %d, got %d' % (int(mo.group(1)), len(result))
+ assert len(result) == int(mo.group(1))
+ return sorted(result)
+
+
+def AsCommandLineArgs(items):
+ """Intended for output to a response file. Quotes all arguments."""
+ return '\n'.join('"' + x + '"' for x in items)
+
+
+def OutputNameForIndex(index):
+ """Gets the final output DLL name, given a zero-based index."""
+ if index == 0:
+ return "chrome.dll"
+ else:
+ return 'chrome%d.dll' % index
+
+
+def ManifestNameForIndex(index):
+ return OutputNameForIndex(index) + '.intermediate.manifest'
+
+
+def PdbNameForIndex(index):
+ return OutputNameForIndex(index) + '.pdb'
+
+
+def RunLinker(flags, index, inputs, phase, intermediate_manifest):
+ """Invokes the linker and returns the stdout, returncode and target name."""
+ rspfile = 'part%d_%s.rsp' % (index, phase)
+ with open(rspfile, 'w') as f:
+ print >> f, AsCommandLineArgs(inputs)
+ print >> f, AsCommandLineArgs(flags)
+ output_name = OutputNameForIndex(index)
+ manifest_name = ManifestNameForIndex(index)
+ print >> f, '/ENTRY:ChromeEmptyEntry@12'
+ print >> f, '/OUT:' + output_name
+ print >> f, '/MANIFESTFILE:' + manifest_name
+ print >> f, '/PDB:' + PdbNameForIndex(index)
+ # Log('[[[\n' + open(rspfile).read() + '\n]]]')
+ link_exe = GetOriginalLinkerPath()
+ popen = subprocess.Popen([link_exe, '@' + rspfile], stdout=subprocess.PIPE)
+ stdout, _ = popen.communicate()
+ if index == 0 and popen.returncode == 0 and intermediate_manifest:
+ # Hack for ninja build. After the linker runs, it does some manifest
+ # things and expects there to be a file in this location. We just put it
+ # there so it's happy. This is a no-op.
+ if os.path.isdir(os.path.dirname(intermediate_manifest)):
+ shutil.copyfile(manifest_name, intermediate_manifest)
+ return stdout, popen.returncode, output_name
+
+
+def GetLibObjList(lib):
+ """Gets the list of object files contained in a .lib."""
+ link_exe = GetOriginalLinkerPath()
+ popen = subprocess.Popen(
+ [link_exe, '/lib', '/nologo', '/list', lib], stdout=subprocess.PIPE)
+ stdout, _ = popen.communicate()
+ return stdout.splitlines()
+
+
+def ExtractObjFromLib(lib, obj):
+ """Extracts a .obj file contained in a .lib file. Returns the absolute path
+ a temp file."""
+ link_exe = GetOriginalLinkerPath()
+ temp = tempfile.NamedTemporaryFile(
+ prefix='split_link_', suffix='.obj', delete=False)
+ temp.close()
+ subprocess.check_call([
+ link_exe, '/lib', '/nologo', '/extract:' + obj, lib, '/out:' + temp.name])
+ return temp.name
+
+
+def Unmangle(export):
+ "Returns the human-presentable name of a mangled symbol."""
+ # Use dbghelp.dll to demangle the name.
+ # TODO(scottmg): Perhaps a simple cache? Seems pretty fast though.
+ UnDecorateSymbolName = ctypes.windll.dbghelp.UnDecorateSymbolName
+ buffer_size = 2048
+ output_string = ctypes.create_string_buffer(buffer_size)
+ if not UnDecorateSymbolName(
+ export, ctypes.byref(output_string), buffer_size, 0):
+ raise ctypes.WinError()
+ return output_string.value
+
+
+def IsDataDefinition(export):
+ """Determines if a given name is data rather than a function. Always returns
+ False for C-style (as opposed to C++-style names)."""
+ if export[0] != '?':
+ return False
+
+ # If it contains a '(' we assume it's a function.
+ return '(' not in Unmangle(export)
+
+
+def GenerateDefFiles(unresolved_by_part):
+ """Given a list of unresolved externals, generates a .def file that will
+ cause all those symbols to be exported."""
+ deffiles = []
+ Log('generating .def files')
+ for i, part in enumerate(unresolved_by_part):
+ deffile = 'part%d.def' % i
+ with open(deffile, 'w') as f:
+ print >> f, 'LIBRARY %s' % OutputNameForIndex(i)
+ print >> f, 'EXPORTS'
+ for j, part in enumerate(unresolved_by_part):
+ if i == j:
+ continue
+ is_data = \
+ [' DATA' if IsDataDefinition(export) and not IGNORE_DATA else ''
+ for export in part]
+ print >> f, '\n'.join(' ' + export + data
+ for export, data in zip(part, is_data))
+ deffiles.append(deffile)
+ return deffiles
+
+
+def BuildImportLibs(flags, inputs_by_part, deffiles):
+ """Runs the linker to generate an import library."""
+ import_libs = []
+ Log('building import libs')
+ for i, (inputs, deffile) in enumerate(zip(inputs_by_part, deffiles)):
+ libfile = 'part%d.lib' % i
+ flags_with_implib_and_deffile = flags + ['/IMPLIB:%s' % libfile,
+ '/DEF:%s' % deffile]
+ RunLinker(flags_with_implib_and_deffile, i, inputs, 'implib', None)
+ import_libs.append(libfile)
+ return import_libs
+
+
+def AttemptLink(flags, inputs_by_part, unresolved_by_part, deffiles,
+ import_libs, intermediate_manifest):
+ """Tries to run the linker for all parts using the current round of
+ generated import libs and .def files. If the link fails, updates the
+ unresolved externals list per part."""
+ dlls = []
+ all_succeeded = True
+ new_externals = []
+ Log('unresolveds now: %r' % [len(part) for part in unresolved_by_part])
+ for i, (inputs, deffile) in enumerate(zip(inputs_by_part, deffiles)):
+ Log('running link, part %d' % i)
+ others_implibs = import_libs[:]
+ others_implibs.pop(i)
+ inputs_with_implib = inputs + filter(lambda x: x, others_implibs)
+ if deffile:
+ flags = flags + ['/DEF:%s' % deffile, '/LTCG']
+ stdout, rc, output = RunLinker(
+ flags, i, inputs_with_implib, 'final', intermediate_manifest)
+ if rc != 0:
+ all_succeeded = False
+ new_externals.append(ParseOutExternals(stdout))
+ else:
+ new_externals.append([])
+ dlls.append(output)
+ combined_externals = [sorted(set(prev) | set(new))
+ for prev, new in zip(unresolved_by_part, new_externals)]
+ return all_succeeded, dlls, combined_externals
+
+
+def ExtractSubObjsTargetedAtAll(
+ inputs,
+ num_parts,
+ description_parts,
+ description_all,
+ description_all_from_libs):
+ """For (lib, obj) tuples in the all_from_libs section, extract the obj out of
+ the lib and added it to inputs. Returns a list of lists for which part the
+ extracted obj belongs in (which is whichever the .lib isn't in)."""
+ by_parts = [[] for _ in range(num_parts)]
+ for lib_spec, obj_spec in description_all_from_libs:
+ for input_file in inputs:
+ if re.search(lib_spec, input_file):
+ objs = GetLibObjList(input_file)
+ match_count = 0
+ for obj in objs:
+ if re.search(obj_spec, obj, re.I):
+ extracted_obj = ExtractObjFromLib(input_file, obj)
+ #Log('extracted %s (%s %s)' % (extracted_obj, input_file, obj))
+ i = PartFor(input_file, description_parts, description_all)
+ if i == -1:
+ raise SystemExit(
+ '%s is already in all parts, but matched '
+ '%s in all_from_libs' % (input_file, obj))
+ # See note in main().
+ assert num_parts == 2, "Can't handle > 2 dlls currently"
+ by_parts[1 - i].append(obj)
+ match_count += 1
+ if match_count == 0:
+ raise SystemExit(
+ '%s, %s matched a lib, but no objs' % (lib_spec, obj_spec))
+ return by_parts
+
+
+def main():
+ flags, inputs, intermediate_manifest = GetFlagsAndInputs(sys.argv[1:])
+ partition_file = os.path.normpath(
+ os.path.join(BASE_DIR, '../../../build/split_link_partition.py'))
+ with open(partition_file) as partition:
+ description = eval(partition.read())
+ inputs_by_part = []
+ description_parts = description['parts']
+ # We currently assume that if a symbol isn't in dll 0, then it's in dll 1
+ # when generating def files. Otherwise, we'd need to do more complex things
+ # to figure out where each symbol actually is to assign it to the correct
+ # .def file.
+ num_parts = len(description_parts)
+ assert num_parts == 2, "Can't handle > 2 dlls currently"
+ description_parts.reverse()
+ objs_from_libs = ExtractSubObjsTargetedAtAll(
+ inputs,
+ num_parts,
+ description_parts,
+ description['all'],
+ description['all_from_libs'])
+ objs_from_libs.reverse()
+ inputs_by_part = [[] for _ in range(num_parts)]
+ for input_file in inputs:
+ i = PartFor(input_file, description_parts, description['all'])
+ if i == -1:
+ for part in inputs_by_part:
+ part.append(input_file)
+ else:
+ inputs_by_part[i].append(input_file)
+ inputs_by_part.reverse()
+
+ # Put the subobjs on to the main list.
+ for i, part in enumerate(objs_from_libs):
+ Log('%d sub .objs added to part %d' % (len(part), i))
+ inputs_by_part[i].extend(part)
+
+ unresolved_by_part = [[] for _ in range(num_parts)]
+ import_libs = [None] * num_parts
+ deffiles = [None] * num_parts
+
+ data_exports = 0
+ for i in range(5):
+ Log('--- starting pass %d' % i)
+ ok, dlls, unresolved_by_part = AttemptLink(
+ flags, inputs_by_part, unresolved_by_part, deffiles, import_libs,
+ intermediate_manifest)
+ if ok:
+ break
+ data_exports = 0
+ for i, part in enumerate(unresolved_by_part):
+ for export in part:
+ if IsDataDefinition(export):
+ print 'part %d contains data export: %s (aka %s)' % (
+ i, Unmangle(export), export)
+ data_exports += 1
+ deffiles = GenerateDefFiles(unresolved_by_part)
+ import_libs = BuildImportLibs(flags, inputs_by_part, deffiles)
+ else:
+ if data_exports and not IGNORE_DATA:
+ print '%d data exports found, see report above.' % data_exports
+ print('These cannot be exported, and must be either duplicated to the '
+ 'target DLL (if constant), or wrapped in a function.')
+ return 1
+
+ mt_exe = GetMtPath()
+ for i, dll in enumerate(dlls):
+ Log('embedding manifest in %s' % dll)
+ args = [mt_exe, '-nologo', '-manifest']
+ args.append(ManifestNameForIndex(i))
+ args.append(description['manifest'])
+ args.append('-outputresource:%s;2' % dll)
+ subprocess.check_call(args)
+
+ Log('built %r' % dlls)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/chromium/tools/win/split_link/viz.js/COPYING b/chromium/tools/win/split_link/viz.js/COPYING
new file mode 100644
index 00000000000..a681d9f0a41
--- /dev/null
+++ b/chromium/tools/win/split_link/viz.js/COPYING
@@ -0,0 +1,129 @@
+* The original parts of this project (including files used in compiling the viz.js file) are made available under the following terms:
+
+Copyright (c) 2012 Michael Daines
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+* Graphviz is distributed under the Eclipse Public License:
+
+AT&T has previously made versions of this software available under the AT&T Source Code Agreement, version 1.2D and earlier. If you received a copy of the software under that license agreement, you may continue to use and distribute the same version of the software subject to the terms and conditions of the license agreement under which the software was received. However, current versions of the software are now licensed on an open source basis only under The Eclipse Public License (EPL).
+
+For more information on the Eclipse Public License, see the FAQ. If you have any concerns about the what the license means, especially if money is involved, you should contact an intellectual property lawyer.
+
+Eclipse Public License - v 1.0
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
+
+b) in the case of each subsequent Contributor:
+
+i) changes to the Program, and
+
+ii) additions to the Program;
+
+where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
+
+b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
+
+c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
+
+a) it complies with the terms and conditions of this Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
+
+ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
+
+iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
+
+iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each copy of the Program.
+
+Contributors may not remove or alter any copyright notices contained within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
+
+
+* This project, including the Makefile, uses work by Satoshi Ueyama, made available under the following terms:
+
+ -> Liviz.js (JSViz) <-
+ Interactive GraphViz on DHTML
+
+-- MIT License
+
+Copyright (c) 2011-2012 Satoshi Ueyama
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/chromium/tools/win/split_link/viz.js/viz.js b/chromium/tools/win/split_link/viz.js/viz.js
new file mode 100644
index 00000000000..4319610bfc2
--- /dev/null
+++ b/chromium/tools/win/split_link/viz.js/viz.js
@@ -0,0 +1,201588 @@
+((typeof exports !== "undefined" && exports !== null) ? exports : this)["Viz"] = function(src, format) {
+ var Module = {};
+ Module["return"] = "";
+ Module["print"] = function(text) {
+ Module["return"] += text + "\n";
+ }
+// Note: Some Emscripten settings will significantly limit the speed of the generated code.
+// Note: Some Emscripten settings may limit the speed of the generated code.
+try {
+ this['Module'] = Module;
+} catch(e) {
+ this['Module'] = Module = {};
+}
+// The environment setup code below is customized to use Module.
+// *** Environment setup code ***
+var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function';
+var ENVIRONMENT_IS_WEB = typeof window === 'object';
+var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
+var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+if (ENVIRONMENT_IS_NODE) {
+ // Expose functionality in the same simple way that the shells work
+ // Note that we pollute the global namespace here, otherwise we break in node
+ Module['print'] = function(x) {
+ process['stdout'].write(x + '\n');
+ };
+ Module['printErr'] = function(x) {
+ process['stderr'].write(x + '\n');
+ };
+ var nodeFS = require('fs');
+ var nodePath = require('path');
+ Module['read'] = function(filename, binary) {
+ filename = nodePath['normalize'](filename);
+ var ret = nodeFS['readFileSync'](filename);
+ // The path is absolute if the normalized version is the same as the resolved.
+ if (!ret && filename != nodePath['resolve'](filename)) {
+ filename = path.join(__dirname, '..', 'src', filename);
+ ret = nodeFS['readFileSync'](filename);
+ }
+ if (ret && !binary) ret = ret.toString();
+ return ret;
+ };
+ Module['readBinary'] = function(filename) { return Module['read'](filename, true) };
+ Module['load'] = function(f) {
+ globalEval(read(f));
+ };
+ if (!Module['arguments']) {
+ Module['arguments'] = process['argv'].slice(2);
+ }
+}
+if (ENVIRONMENT_IS_SHELL) {
+ Module['print'] = print;
+ if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm
+ Module['read'] = read;
+ Module['readBinary'] = function(f) {
+ return read(f, 'binary');
+ };
+ if (!Module['arguments']) {
+ if (typeof scriptArgs != 'undefined') {
+ Module['arguments'] = scriptArgs;
+ } else if (typeof arguments != 'undefined') {
+ Module['arguments'] = arguments;
+ }
+ }
+}
+if (ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_WORKER) {
+ if (!Module['print']) {
+ Module['print'] = function(x) {
+ console.log(x);
+ };
+ }
+ if (!Module['printErr']) {
+ Module['printErr'] = function(x) {
+ console.log(x);
+ };
+ }
+}
+if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ Module['read'] = function(url) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ xhr.send(null);
+ return xhr.responseText;
+ };
+ if (!Module['arguments']) {
+ if (typeof arguments != 'undefined') {
+ Module['arguments'] = arguments;
+ }
+ }
+}
+if (ENVIRONMENT_IS_WORKER) {
+ // We can do very little here...
+ var TRY_USE_DUMP = false;
+ if (!Module['print']) {
+ Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) {
+ dump(x);
+ }) : (function(x) {
+ // self.postMessage(x); // enable this if you want stdout to be sent as messages
+ }));
+ }
+ Module['load'] = importScripts;
+}
+if (!ENVIRONMENT_IS_WORKER && !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_SHELL) {
+ // Unreachable because SHELL is dependant on the others
+ throw 'Unknown runtime environment. Where are we?';
+}
+function globalEval(x) {
+ eval.call(null, x);
+}
+if (!Module['load'] == 'undefined' && Module['read']) {
+ Module['load'] = function(f) {
+ globalEval(Module['read'](f));
+ };
+}
+if (!Module['print']) {
+ Module['print'] = function(){};
+}
+if (!Module['printErr']) {
+ Module['printErr'] = Module['print'];
+}
+if (!Module['arguments']) {
+ Module['arguments'] = [];
+}
+// *** Environment setup code ***
+// Closure helpers
+Module.print = Module['print'];
+Module.printErr = Module['printErr'];
+// Callbacks
+if (!Module['preRun']) Module['preRun'] = [];
+if (!Module['postRun']) Module['postRun'] = [];
+// === Auto-generated preamble library stuff ===
+//========================================
+// Runtime code shared with compiler
+//========================================
+var Runtime = {
+ stackSave: function () {
+ return STACKTOP;
+ },
+ stackRestore: function (stackTop) {
+ STACKTOP = stackTop;
+ },
+ forceAlign: function (target, quantum) {
+ quantum = quantum || 4;
+ if (quantum == 1) return target;
+ if (isNumber(target) && isNumber(quantum)) {
+ return Math.ceil(target/quantum)*quantum;
+ } else if (isNumber(quantum) && isPowerOfTwo(quantum)) {
+ var logg = log2(quantum);
+ return '((((' +target + ')+' + (quantum-1) + ')>>' + logg + ')<<' + logg + ')';
+ }
+ return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum;
+ },
+ isNumberType: function (type) {
+ return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES;
+ },
+ isPointerType: function isPointerType(type) {
+ return type[type.length-1] == '*';
+},
+ isStructType: function isStructType(type) {
+ if (isPointerType(type)) return false;
+ if (/^\[\d+\ x\ (.*)\]/.test(type)) return true; // [15 x ?] blocks. Like structs
+ if (/<?{ ?[^}]* ?}>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types
+ // See comment in isStructPointerType()
+ return type[0] == '%';
+},
+ INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0},
+ FLOAT_TYPES: {"float":0,"double":0},
+ or64: function (x, y) {
+ var l = (x | 0) | (y | 0);
+ var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+ and64: function (x, y) {
+ var l = (x | 0) & (y | 0);
+ var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+ xor64: function (x, y) {
+ var l = (x | 0) ^ (y | 0);
+ var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296;
+ return l + h;
+ },
+ getNativeTypeSize: function (type, quantumSize) {
+ if (Runtime.QUANTUM_SIZE == 1) return 1;
+ var size = {
+ '%i1': 1,
+ '%i8': 1,
+ '%i16': 2,
+ '%i32': 4,
+ '%i64': 8,
+ "%float": 4,
+ "%double": 8
+ }['%'+type]; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc
+ if (!size) {
+ if (type.charAt(type.length-1) == '*') {
+ size = Runtime.QUANTUM_SIZE; // A pointer
+ } else if (type[0] == 'i') {
+ var bits = parseInt(type.substr(1));
+ assert(bits % 8 == 0);
+ size = bits/8;
+ }
+ }
+ return size;
+ },
+ getNativeFieldSize: function (type) {
+ return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
+ },
+ dedup: function dedup(items, ident) {
+ var seen = {};
+ if (ident) {
+ return items.filter(function(item) {
+ if (seen[item[ident]]) return false;
+ seen[item[ident]] = true;
+ return true;
+ });
+ } else {
+ return items.filter(function(item) {
+ if (seen[item]) return false;
+ seen[item] = true;
+ return true;
+ });
+ }
+},
+ set: function set() {
+ var args = typeof arguments[0] === 'object' ? arguments[0] : arguments;
+ var ret = {};
+ for (var i = 0; i < args.length; i++) {
+ ret[args[i]] = 0;
+ }
+ return ret;
+},
+ STACK_ALIGN: 8,
+ getAlignSize: function (type, size, vararg) {
+ // we align i64s and doubles on 64-bit boundaries, unlike x86
+ if (type == 'i64' || type == 'double' || vararg) return 8;
+ if (!type) return Math.min(size, 8); // align structures internally to 64 bits
+ return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE);
+ },
+ calculateStructAlignment: function calculateStructAlignment(type) {
+ type.flatSize = 0;
+ type.alignSize = 0;
+ var diffs = [];
+ var prev = -1;
+ type.flatIndexes = type.fields.map(function(field) {
+ var size, alignSize;
+ if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) {
+ size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s.
+ alignSize = Runtime.getAlignSize(field, size);
+ } else if (Runtime.isStructType(field)) {
+ size = Types.types[field].flatSize;
+ alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize);
+ } else if (field[0] == 'b') {
+ // bN, large number field, like a [N x i8]
+ size = field.substr(1)|0;
+ alignSize = 1;
+ } else {
+ throw 'Unclear type in struct: ' + field + ', in ' + type.name_ + ' :: ' + dump(Types.types[type.name_]);
+ }
+ if (type.packed) alignSize = 1;
+ type.alignSize = Math.max(type.alignSize, alignSize);
+ var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory
+ type.flatSize = curr + size;
+ if (prev >= 0) {
+ diffs.push(curr-prev);
+ }
+ prev = curr;
+ return curr;
+ });
+ type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize);
+ if (diffs.length == 0) {
+ type.flatFactor = type.flatSize;
+ } else if (Runtime.dedup(diffs).length == 1) {
+ type.flatFactor = diffs[0];
+ }
+ type.needsFlattening = (type.flatFactor != 1);
+ return type.flatIndexes;
+ },
+ generateStructInfo: function (struct, typeName, offset) {
+ var type, alignment;
+ if (typeName) {
+ offset = offset || 0;
+ type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName];
+ if (!type) return null;
+ if (type.fields.length != struct.length) {
+ printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo');
+ return null;
+ }
+ alignment = type.flatIndexes;
+ } else {
+ var type = { fields: struct.map(function(item) { return item[0] }) };
+ alignment = Runtime.calculateStructAlignment(type);
+ }
+ var ret = {
+ __size__: type.flatSize
+ };
+ if (typeName) {
+ struct.forEach(function(item, i) {
+ if (typeof item === 'string') {
+ ret[item] = alignment[i] + offset;
+ } else {
+ // embedded struct
+ var key;
+ for (var k in item) key = k;
+ ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]);
+ }
+ });
+ } else {
+ struct.forEach(function(item, i) {
+ ret[item[1]] = alignment[i];
+ });
+ }
+ return ret;
+ },
+ dynCall: function (sig, ptr, args) {
+ if (args && args.length) {
+ if (!args.splice) args = Array.prototype.slice.call(args);
+ args.splice(0, 0, ptr);
+ return Module['dynCall_' + sig].apply(null, args);
+ } else {
+ return Module['dynCall_' + sig].call(null, ptr);
+ }
+ },
+ functionPointers: [],
+ addFunction: function (func) {
+ for (var i = 0; i < Runtime.functionPointers.length; i++) {
+ if (!Runtime.functionPointers[i]) {
+ Runtime.functionPointers[i] = func;
+ return 2 + 2*i;
+ }
+ }
+ throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.';
+ },
+ removeFunction: function (index) {
+ Runtime.functionPointers[(index-2)/2] = null;
+ },
+ warnOnce: function (text) {
+ if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
+ if (!Runtime.warnOnce.shown[text]) {
+ Runtime.warnOnce.shown[text] = 1;
+ Module.printErr(text);
+ }
+ },
+ funcWrappers: {},
+ getFuncWrapper: function (func, sig) {
+ assert(sig);
+ if (!Runtime.funcWrappers[func]) {
+ Runtime.funcWrappers[func] = function() {
+ return Runtime.dynCall(sig, func, arguments);
+ };
+ }
+ return Runtime.funcWrappers[func];
+ },
+ UTF8Processor: function () {
+ var buffer = [];
+ var needed = 0;
+ this.processCChar = function (code) {
+ code = code & 0xff;
+ if (needed) {
+ buffer.push(code);
+ needed--;
+ }
+ if (buffer.length == 0) {
+ if (code < 128) return String.fromCharCode(code);
+ buffer.push(code);
+ if (code > 191 && code < 224) {
+ needed = 1;
+ } else {
+ needed = 2;
+ }
+ return '';
+ }
+ if (needed > 0) return '';
+ var c1 = buffer[0];
+ var c2 = buffer[1];
+ var c3 = buffer[2];
+ var ret;
+ if (c1 > 191 && c1 < 224) {
+ ret = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
+ } else {
+ ret = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+ }
+ buffer.length = 0;
+ return ret;
+ }
+ this.processJSString = function(string) {
+ string = unescape(encodeURIComponent(string));
+ var ret = [];
+ for (var i = 0; i < string.length; i++) {
+ ret.push(string.charCodeAt(i));
+ }
+ return ret;
+ }
+ },
+ stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = ((((STACKTOP)+7)>>3)<<3); return ret; },
+ staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = ((((STATICTOP)+7)>>3)<<3); return ret; },
+ dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = ((((DYNAMICTOP)+7)>>3)<<3); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; },
+ alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; },
+ makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+(((low)>>>(0))))+((+(((high)>>>(0))))*(+(4294967296)))) : ((+(((low)>>>(0))))+((+(((high)|(0))))*(+(4294967296))))); return ret; },
+ GLOBAL_BASE: 8,
+ QUANTUM_SIZE: 4,
+ __dummy__: 0
+}
+//========================================
+// Runtime essentials
+//========================================
+var __THREW__ = 0; // Used in checking for thrown exceptions.
+var ABORT = false;
+var undef = 0;
+// tempInt is used for 32-bit signed values or smaller. tempBigInt is used
+// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt
+var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD;
+var tempI64, tempI64b;
+var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9;
+function abort(text) {
+ Module.print(text + ':\n' + (new Error).stack);
+ ABORT = true;
+ throw "Assertion: " + text;
+}
+function assert(condition, text) {
+ if (!condition) {
+ abort('Assertion failed: ' + text);
+ }
+}
+var globalScope = this;
+// C calling interface. A convenient way to call C functions (in C files, or
+// defined with extern "C").
+//
+// Note: LLVM optimizations can inline and remove functions, after which you will not be
+// able to call them. Closure can also do so. To avoid that, add your function to
+// the exports using something like
+//
+// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]'
+//
+// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C")
+// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and
+// 'array' for JavaScript arrays and typed arrays).
+// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType,
+// except that 'array' is not possible (there is no way for us to know the length of the array)
+// @param args An array of the arguments to the function, as native JS values (as in returnType)
+// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack).
+// @return The return value, as a native JS value (as in returnType)
+function ccall(ident, returnType, argTypes, args) {
+ return ccallFunc(getCFunc(ident), returnType, argTypes, args);
+}
+Module["ccall"] = ccall;
+// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
+function getCFunc(ident) {
+ try {
+ var func = globalScope['Module']['_' + ident]; // closure exported function
+ if (!func) func = eval('_' + ident); // explicit lookup
+ } catch(e) {
+ }
+ assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)');
+ return func;
+}
+// Internal function that does a C call using a function, not an identifier
+function ccallFunc(func, returnType, argTypes, args) {
+ var stack = 0;
+ function toC(value, type) {
+ if (type == 'string') {
+ if (value === null || value === undefined || value === 0) return 0; // null string
+ if (!stack) stack = Runtime.stackSave();
+ var ret = Runtime.stackAlloc(value.length+1);
+ writeStringToMemory(value, ret);
+ return ret;
+ } else if (type == 'array') {
+ if (!stack) stack = Runtime.stackSave();
+ var ret = Runtime.stackAlloc(value.length);
+ writeArrayToMemory(value, ret);
+ return ret;
+ }
+ return value;
+ }
+ function fromC(value, type) {
+ if (type == 'string') {
+ return Pointer_stringify(value);
+ }
+ assert(type != 'array');
+ return value;
+ }
+ var i = 0;
+ var cArgs = args ? args.map(function(arg) {
+ return toC(arg, argTypes[i++]);
+ }) : [];
+ var ret = fromC(func.apply(null, cArgs), returnType);
+ if (stack) Runtime.stackRestore(stack);
+ return ret;
+}
+// Returns a native JS wrapper for a C function. This is similar to ccall, but
+// returns a function you can call repeatedly in a normal way. For example:
+//
+// var my_function = cwrap('my_c_function', 'number', ['number', 'number']);
+// alert(my_function(5, 22));
+// alert(my_function(99, 12));
+//
+function cwrap(ident, returnType, argTypes) {
+ var func = getCFunc(ident);
+ return function() {
+ return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments));
+ }
+}
+Module["cwrap"] = cwrap;
+// Sets a value in memory in a dynamic way at run-time. Uses the
+// type data. This is the same as makeSetValue, except that
+// makeSetValue is done at compile-time and generates the needed
+// code then, whereas this function picks the right code at
+// run-time.
+// Note that setValue and getValue only do *aligned* writes and reads!
+// Note that ccall uses JS types as for defining types, while setValue and
+// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation
+function setValue(ptr, value, type, noSafe) {
+ type = type || 'i8';
+ if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': HEAP8[(ptr)]=value; break;
+ case 'i8': HEAP8[(ptr)]=value; break;
+ case 'i16': HEAP16[((ptr)>>1)]=value; break;
+ case 'i32': HEAP32[((ptr)>>2)]=value; break;
+ case 'i64': (tempI64 = [value>>>0,Math.min(Math.floor((value)/(+(4294967296))), (+(4294967295)))>>>0],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break;
+ case 'float': HEAPF32[((ptr)>>2)]=value; break;
+ case 'double': HEAPF64[((ptr)>>3)]=value; break;
+ default: abort('invalid type for setValue: ' + type);
+ }
+}
+Module['setValue'] = setValue;
+// Parallel to setValue.
+function getValue(ptr, type, noSafe) {
+ type = type || 'i8';
+ if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': return HEAP8[(ptr)];
+ case 'i8': return HEAP8[(ptr)];
+ case 'i16': return HEAP16[((ptr)>>1)];
+ case 'i32': return HEAP32[((ptr)>>2)];
+ case 'i64': return HEAP32[((ptr)>>2)];
+ case 'float': return HEAPF32[((ptr)>>2)];
+ case 'double': return HEAPF64[((ptr)>>3)];
+ default: abort('invalid type for setValue: ' + type);
+ }
+ return null;
+}
+Module['getValue'] = getValue;
+var ALLOC_NORMAL = 0; // Tries to use _malloc()
+var ALLOC_STACK = 1; // Lives for the duration of the current function call
+var ALLOC_STATIC = 2; // Cannot be freed
+var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk
+var ALLOC_NONE = 4; // Do not allocate
+Module['ALLOC_NORMAL'] = ALLOC_NORMAL;
+Module['ALLOC_STACK'] = ALLOC_STACK;
+Module['ALLOC_STATIC'] = ALLOC_STATIC;
+Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC;
+Module['ALLOC_NONE'] = ALLOC_NONE;
+// allocate(): This is for internal use. You can use it yourself as well, but the interface
+// is a little tricky (see docs right below). The reason is that it is optimized
+// for multiple syntaxes to save space in generated code. So you should
+// normally not use allocate(), and instead allocate memory using _malloc(),
+// initialize it with setValue(), and so forth.
+// @slab: An array of data, or a number. If a number, then the size of the block to allocate,
+// in *bytes* (note that this is sometimes confusing: the next parameter does not
+// affect this!)
+// @types: Either an array of types, one for each byte (or 0 if no type at that position),
+// or a single type which is used for the entire block. This only matters if there
+// is initial data - if @slab is a number, then this does not matter at all and is
+// ignored.
+// @allocator: How to allocate memory, see ALLOC_*
+function allocate(slab, types, allocator, ptr) {
+ var zeroinit, size;
+ if (typeof slab === 'number') {
+ zeroinit = true;
+ size = slab;
+ } else {
+ zeroinit = false;
+ size = slab.length;
+ }
+ var singleType = typeof types === 'string' ? types : null;
+ var ret;
+ if (allocator == ALLOC_NONE) {
+ ret = ptr;
+ } else {
+ ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
+ }
+ if (zeroinit) {
+ var ptr = ret, stop;
+ assert((ret & 3) == 0);
+ stop = ret + (size & ~3);
+ for (; ptr < stop; ptr += 4) {
+ HEAP32[((ptr)>>2)]=0;
+ }
+ stop = ret + size;
+ while (ptr < stop) {
+ HEAP8[((ptr++)|0)]=0;
+ }
+ return ret;
+ }
+ if (singleType === 'i8') {
+ HEAPU8.set(new Uint8Array(slab), ret);
+ return ret;
+ }
+ var i = 0, type, typeSize, previousType;
+ while (i < size) {
+ var curr = slab[i];
+ if (typeof curr === 'function') {
+ curr = Runtime.getFunctionIndex(curr);
+ }
+ type = singleType || types[i];
+ if (type === 0) {
+ i++;
+ continue;
+ }
+ if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
+ setValue(ret+i, curr, type);
+ // no need to look up size unless type changes, so cache it
+ if (previousType !== type) {
+ typeSize = Runtime.getNativeTypeSize(type);
+ previousType = type;
+ }
+ i += typeSize;
+ }
+ return ret;
+}
+Module['allocate'] = allocate;
+function Pointer_stringify(ptr, /* optional */ length) {
+ // Find the length, and check for UTF while doing so
+ var hasUtf = false;
+ var t;
+ var i = 0;
+ while (1) {
+ t = HEAPU8[(((ptr)+(i))|0)];
+ if (t >= 128) hasUtf = true;
+ else if (t == 0 && !length) break;
+ i++;
+ if (length && i == length) break;
+ }
+ if (!length) length = i;
+ var ret = '';
+ if (!hasUtf) {
+ var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack
+ var curr;
+ while (length > 0) {
+ curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
+ ret = ret ? ret + curr : curr;
+ ptr += MAX_CHUNK;
+ length -= MAX_CHUNK;
+ }
+ return ret;
+ }
+ var utf8 = new Runtime.UTF8Processor();
+ for (i = 0; i < length; i++) {
+ t = HEAPU8[(((ptr)+(i))|0)];
+ ret += utf8.processCChar(t);
+ }
+ return ret;
+}
+Module['Pointer_stringify'] = Pointer_stringify;
+// Memory management
+var PAGE_SIZE = 4096;
+function alignMemoryPage(x) {
+ return ((x+4095)>>12)<<12;
+}
+var HEAP;
+var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
+var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area
+var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area
+var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk
+function enlargeMemory() {
+ abort('Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs.');
+}
+var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880;
+var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216;
+var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152;
+// Initialize the runtime's memory
+// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
+assert(!!Int32Array && !!Float64Array && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
+ 'Cannot fallback to non-typed array case: Code is too specialized');
+var buffer = new ArrayBuffer(TOTAL_MEMORY);
+HEAP8 = new Int8Array(buffer);
+HEAP16 = new Int16Array(buffer);
+HEAP32 = new Int32Array(buffer);
+HEAPU8 = new Uint8Array(buffer);
+HEAPU16 = new Uint16Array(buffer);
+HEAPU32 = new Uint32Array(buffer);
+HEAPF32 = new Float32Array(buffer);
+HEAPF64 = new Float64Array(buffer);
+// Endianness check (note: assumes compiler arch was little-endian)
+HEAP32[0] = 255;
+assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system');
+Module['HEAP'] = HEAP;
+Module['HEAP8'] = HEAP8;
+Module['HEAP16'] = HEAP16;
+Module['HEAP32'] = HEAP32;
+Module['HEAPU8'] = HEAPU8;
+Module['HEAPU16'] = HEAPU16;
+Module['HEAPU32'] = HEAPU32;
+Module['HEAPF32'] = HEAPF32;
+Module['HEAPF64'] = HEAPF64;
+function callRuntimeCallbacks(callbacks) {
+ while(callbacks.length > 0) {
+ var callback = callbacks.shift();
+ if (typeof callback == 'function') {
+ callback();
+ continue;
+ }
+ var func = callback.func;
+ if (typeof func === 'number') {
+ if (callback.arg === undefined) {
+ Runtime.dynCall('v', func);
+ } else {
+ Runtime.dynCall('vi', func, [callback.arg]);
+ }
+ } else {
+ func(callback.arg === undefined ? null : callback.arg);
+ }
+ }
+}
+var __ATINIT__ = []; // functions called during startup
+var __ATMAIN__ = []; // functions called when main() is to be run
+var __ATEXIT__ = []; // functions called during shutdown
+var runtimeInitialized = false;
+function ensureInitRuntime() {
+ if (runtimeInitialized) return;
+ runtimeInitialized = true;
+ callRuntimeCallbacks(__ATINIT__);
+}
+function preMain() {
+ callRuntimeCallbacks(__ATMAIN__);
+}
+function exitRuntime() {
+ callRuntimeCallbacks(__ATEXIT__);
+}
+// Tools
+// This processes a JS string into a C-line array of numbers, 0-terminated.
+// For LLVM-originating strings, see parser.js:parseLLVMString function
+function intArrayFromString(stringy, dontAddNull, length /* optional */) {
+ var ret = (new Runtime.UTF8Processor()).processJSString(stringy);
+ if (length) {
+ ret.length = length;
+ }
+ if (!dontAddNull) {
+ ret.push(0);
+ }
+ return ret;
+}
+Module['intArrayFromString'] = intArrayFromString;
+function intArrayToString(array) {
+ var ret = [];
+ for (var i = 0; i < array.length; i++) {
+ var chr = array[i];
+ if (chr > 0xFF) {
+ chr &= 0xFF;
+ }
+ ret.push(String.fromCharCode(chr));
+ }
+ return ret.join('');
+}
+Module['intArrayToString'] = intArrayToString;
+// Write a Javascript array to somewhere in the heap
+function writeStringToMemory(string, buffer, dontAddNull) {
+ var array = intArrayFromString(string, dontAddNull);
+ var i = 0;
+ while (i < array.length) {
+ var chr = array[i];
+ HEAP8[(((buffer)+(i))|0)]=chr
+ i = i + 1;
+ }
+}
+Module['writeStringToMemory'] = writeStringToMemory;
+function writeArrayToMemory(array, buffer) {
+ for (var i = 0; i < array.length; i++) {
+ HEAP8[(((buffer)+(i))|0)]=array[i];
+ }
+}
+Module['writeArrayToMemory'] = writeArrayToMemory;
+function unSign(value, bits, ignore, sig) {
+ if (value >= 0) {
+ return value;
+ }
+ return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts
+ : Math.pow(2, bits) + value;
+}
+function reSign(value, bits, ignore, sig) {
+ if (value <= 0) {
+ return value;
+ }
+ var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
+ : Math.pow(2, bits-1);
+ if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that
+ // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors
+ // TODO: In i64 mode 1, resign the two parts separately and safely
+ value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
+ }
+ return value;
+}
+if (!Math.imul) Math.imul = function(a, b) {
+ var ah = a >>> 16;
+ var al = a & 0xffff;
+ var bh = b >>> 16;
+ var bl = b & 0xffff;
+ return (al*bl + ((ah*bl + al*bh) << 16))|0;
+};
+// A counter of dependencies for calling run(). If we need to
+// do asynchronous work before running, increment this and
+// decrement it. Incrementing must happen in a place like
+// PRE_RUN_ADDITIONS (used by emcc to add file preloading).
+// Note that you can add dependencies in preRun, even though
+// it happens right before run - run will be postponed until
+// the dependencies are met.
+var runDependencies = 0;
+var runDependencyTracking = {};
+var calledInit = false, calledRun = false;
+var runDependencyWatcher = null;
+function addRunDependency(id) {
+ runDependencies++;
+ if (Module['monitorRunDependencies']) {
+ Module['monitorRunDependencies'](runDependencies);
+ }
+ if (id) {
+ assert(!runDependencyTracking[id]);
+ runDependencyTracking[id] = 1;
+ if (runDependencyWatcher === null && typeof setInterval !== 'undefined') {
+ // Check for missing dependencies every few seconds
+ runDependencyWatcher = setInterval(function() {
+ var shown = false;
+ for (var dep in runDependencyTracking) {
+ if (!shown) {
+ shown = true;
+ Module.printErr('still waiting on run dependencies:');
+ }
+ Module.printErr('dependency: ' + dep);
+ }
+ if (shown) {
+ Module.printErr('(end of list)');
+ }
+ }, 6000);
+ }
+ } else {
+ Module.printErr('warning: run dependency added without ID');
+ }
+}
+Module['addRunDependency'] = addRunDependency;
+function removeRunDependency(id) {
+ runDependencies--;
+ if (Module['monitorRunDependencies']) {
+ Module['monitorRunDependencies'](runDependencies);
+ }
+ if (id) {
+ assert(runDependencyTracking[id]);
+ delete runDependencyTracking[id];
+ } else {
+ Module.printErr('warning: run dependency removed without ID');
+ }
+ if (runDependencies == 0) {
+ if (runDependencyWatcher !== null) {
+ clearInterval(runDependencyWatcher);
+ runDependencyWatcher = null;
+ }
+ // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
+ if (!calledRun && shouldRunNow) run();
+ }
+}
+Module['removeRunDependency'] = removeRunDependency;
+Module["preloadedImages"] = {}; // maps url to image data
+Module["preloadedAudios"] = {}; // maps url to audio data
+function addPreRun(func) {
+ if (!Module['preRun']) Module['preRun'] = [];
+ else if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
+ Module['preRun'].push(func);
+}
+var awaitingMemoryInitializer = false;
+function loadMemoryInitializer(filename) {
+ function applyData(data) {
+ HEAPU8.set(data, STATIC_BASE);
+ runPostSets();
+ }
+ // always do this asynchronously, to keep shell and web as similar as possible
+ addPreRun(function() {
+ if (ENVIRONMENT_IS_NODE || ENVIRONMENT_IS_SHELL) {
+ applyData(Module['readBinary'](filename));
+ } else {
+ Browser.asyncLoad(filename, function(data) {
+ applyData(data);
+ }, function(data) {
+ throw 'could not load memory initializer ' + filename;
+ });
+ }
+ });
+ awaitingMemoryInitializer = false;
+}
+// === Body ===
+STATIC_BASE = 8;
+STATICTOP = STATIC_BASE + 168584;
+var _stdout;
+var _stderr;
+var _stdout = _stdout=allocate([0,0,0,0,0,0,0,0], "i8", ALLOC_STATIC);
+var _stderr = _stderr=allocate([0,0,0,0,0,0,0,0], "i8", ALLOC_STATIC);
+/* memory initializer */ allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40,1,0,0,50,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,1,0,0,0,0,0,0,36,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,2,0,0,0,0,0,0,134,1,0,0,196,1,0,0,166,1,0,0,250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,216,0,0,0,232,0,0,0,248,0,0,0,8,1,0,0,24,1,0,0,40,1,0,0,56,1,0,0,72,1,0,0,232,0,0,0,232,0,0,0,40,1,0,0,40,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,119,2,0,200,104,2,0,232,91,2,0,136,77,2,0,200,65,2,0,240,54,2,0,32,43,2,0,88,29,2,0,152,18,2,0,40,9,2,0,32,1,2,0,88,250,1,0,56,241,1,0,120,231,1,0,168,223,1,0,40,219,1,0,174,0,0,0,0,0,0,0,188,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152,1,0,0,76,1,0,0,0,0,0,0,0,0,0,0,254,1,0,0,0,0,0,0,202,0,0,0,34,1,0,0,90,0,0,0,204,0,0,0,8,0,0,0,0,0,0,0,100,0,0,0,116,0,0,0,92,0,0,0,146,0,0,0,158,2,0,0,98,2,0,0,204,1,0,0,78,0,0,0,2,2,0,0,28,1,0,0,46,0,0,0,146,1,0,0,210,0,0,0,108,0,0,0,26,0,0,0,94,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,21,10,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,16,12,19,28,30,3,13,31,32,33,34,35,27,26,17,25,25,25,25,25,25,25,25,25,25,22,18,2,14,11,15,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,20,28,4,28,22,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,36,28,28,28,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,0,0,0,0,0,0,0,0,0,1,1,64,0,0,0,250,1,0,0,210,1,0,0,98,1,0,0,178,0,0,0,210,1,0,0,226,0,0,0,228,0,0,0,236,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,112,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,216,1,0,0,0,0,0,0,124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,168,1,0,0,0,0,0,0,62,2,0,0,58,2,0,0,188,1,0,0,230,0,0,0,112,0,0,0,0,0,0,0,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,37,117,2,154,8,27,218,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,44,212,154,230,29,167,234,63,106,222,113,138,142,228,232,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,93,220,70,3,120,11,226,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,208,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,93,220,70,3,120,11,226,63,93,220,70,3,120,11,226,63,93,220,70,3,120,11,226,63,13,113,172,139,219,104,220,63,100,93,220,70,3,120,237,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,16,122,54,171,62,87,229,63,210,111,95,7,206,25,231,63,120,11,36,40,126,140,227,63,181,21,251,203,238,201,225,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,88,168,53,205,59,78,213,63,136,133,90,211,188,227,216,63,210,111,95,7,206,25,231,63,120,11,36,40,126,140,227,63,196,66,173,105,222,113,236,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,181,21,251,203,238,201,225,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,181,21,251,203,238,201,225,63,120,11,36,40,126,140,227,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,134,56,214,197,109,52,238,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,120,11,36,40,126,140,227,63,88,168,53,205,59,78,213,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,166,10,70,37,117,2,222,63,0,0,0,0,0,0,224,63,88,168,53,205,59,78,213,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,224,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,224,63,13,113,172,139,219,104,220,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,106,222,113,138,142,228,232,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,88,168,53,205,59,78,213,63,136,133,90,211,188,227,216,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,210,111,95,7,206,25,231,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,13,113,172,139,219,104,220,63,244,108,86,125,174,182,222,63,17,54,60,189,82,150,201,63,244,108,86,125,174,182,222,63,59,1,77,132,13,79,225,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,62,232,217,172,250,92,197,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,130,115,70,148,246,6,199,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,224,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,7,240,22,72,80,252,220,63,162,180,55,248,194,100,214,63,88,168,53,205,59,78,213,63,13,113,172,139,219,104,220,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,208,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,196,66,173,105,222,113,236,63,0,0,0,0,0,0,208,63,127,217,61,121,88,168,209,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,120,11,36,40,126,140,227,63,210,111,95,7,206,25,231,63,196,66,173,105,222,113,236,63,19,242,65,207,102,213,211,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,16,122,54,171,62,87,229,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,210,111,95,7,206,25,231,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,16,219,1,0,58,0,0,0,96,186,1,0,56,1,0,0,32,184,1,0,126,1,0,0,8,127,1,0,194,0,0,0,64,182,1,0,104,0,0,0,8,180,1,0,150,0,0,0,16,205,1,0,146,2,0,0,208,176,1,0,8,1,0,0,120,175,1,0,160,2,0,0,200,173,1,0,202,1,0,0,40,172,1,0,76,0,0,0,248,170,1,0,150,2,0,0,112,125,1,0,182,1,0,0,184,166,1,0,246,0,0,0,56,165,1,0,6,0,0,0,72,163,1,0,6,0,0,0,240,161,1,0,216,0,0,0,112,160,1,0,90,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,0,0,0,0,192,244,1,0,232,203,1,0,56,183,1,0,0,166,1,0,160,150,1,0,64,134,1,0,48,118,1,0,232,104,1,0,248,122,2,0,248,108,2,0,48,95,2,0,240,81,2,0,40,69,2,0,32,58,2,0,32,46,2,0,64,32,2,0,136,21,2,0,40,12,2,0,56,3,2,0,240,251,1,0,232,243,1,0,240,233,1,0,8,226,1,0,224,219,1,0,184,217,1,0,248,214,1,0,64,212,1,0,48,210,1,0,0,208,1,0,208,205,1,0,168,203,1,0,40,201,1,0,232,198,1,0,232,196,1,0,56,195,1,0,56,193,1,0,48,191,1,0,248,188,1,0,48,187,1,0,32,185,1,0,16,183,1,0,248,180,1,0,40,179,1,0,120,177,1,0,248,175,1,0,72,174,1,0,176,172,1,0,104,171,1,0,8,170,1,0,80,167,1,0,232,165,1,0,248,163,1,0,104,162,1,0,24,161,1,0,136,159,1,0,16,158,1,0,176,156,1,0,72,155,1,0,248,153,1,0,8,152,1,0,144,150,1,0,160,148,1,0,64,147,1,0,200,145,1,0,112,144,1,0,176,142,1,0,16,141,1,0,224,138,1,0,120,137,1,0,104,135,1,0,24,134,1,0,80,132,1,0,240,130,1,0,32,129,1,0,128,127,1,0,16,126,1,0,48,124,1,0,232,122,1,0,16,121,1,0,64,119,1,0,24,118,1,0,136,116,1,0,64,115,1,0,16,114,1,0,216,112,1,0,112,111,1,0,64,110,1,0,192,108,1,0,136,107,1,0,240,105,1,0,184,104,1,0,192,102,1,0,112,101,1,0,64,100,1,0,224,98,1,0,184,97,1,0,144,96,1,0,72,95,1,0,56,125,2,0,216,123,2,0,208,122,2,0,240,120,2,0,136,119,2,0,96,118,2,0,24,117,2,0,224,115,2,0,176,114,2,0,104,113,2,0,224,111,2,0,72,110,2,0,192,108,2,0,8,107,2,0,128,105,2,0,16,104,2,0,120,102,2,0,56,101,2,0,64,100,2,0,8,99,2,0,192,97,2,0,40,96,2,0,248,94,2,0,144,93,2,0,88,92,2,0,8,91,2,0,224,89,2,0,176,88,2,0,64,87,2,0,184,85,2,0,152,84,2,0,8,83,2,0,184,81,2,0,200,79,2,0,80,78,2,0,224,76,2,0,88,75,2,0,104,74,2,0,80,73,2,0,8,72,2,0,240,70,2,0,224,69,2,0,0,69,2,0,88,67,2,0,128,66,2,0,64,65,2,0,56,64,2,0,40,63,2,0,48,62,2,0,0,0,0,0,114,0,0,0,0,0,0,0,232,0,0,0,140,1,0,0,158,1,0,0,118,0,0,0,244,0,0,0,252,0,0,0,50,0,0,0,212,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,196,0,0,0,232,1,0,0,212,0,0,0,238,1,0,0,24,0,0,0,94,2,0,0,0,0,0,0,0,0,0,0,88,0,0,0,0,0,0,0,198,1,0,0,90,2,0,0,154,1,0,0,128,2,0,0,126,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,54,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,1,0,0,226,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,114,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,193,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,176,193,0,0,0,0,0,0,0,0,0,0,0,0,0,88,1,0,0,16,0,0,0,1,0,0,0,0,0,0,0,0,16,0,2,0,0,0,0,0,0,0,0,0,0,16,64,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,176,193,0,0,0,0,0,0,0,0,0,0,0,16,64,16,13,0,0,147,0,0,0,1,0,0,0,0,0,0,0,0,32,3,2,0,0,0,0,0,0,0,0,0,0,16,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,144,195,0,0,0,0,0,0,0,0,0,0,0,16,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,16,0,0,0,0,0,0,0,0,0,0,0,0,16,64,80,64,0,0,8,0,0,0,1,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,66,0,0,0,148,1,0,0,56,2,0,0,70,2,0,0,92,2,0,0,122,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,135,1,0,8,119,1,0,200,105,1,0,176,123,2,0,24,110,2,0,0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,102,1,0,0,142,0,0,0,52,0,0,0,0,0,0,0,136,2,0,0,0,0,0,0,6,1,0,0,36,0,0,0,136,1,0,0,222,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,1,0,0,2,0,0,0,130,1,0,0,4,1,0,0,234,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,1,0,0,0,0,0,0,116,2,0,0,158,0,0,0,172,0,0,0,218,0,0,0,170,2,0,0,42,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,208,108,2,0,48,110,2,0,168,252,1,0,136,206,1,0,136,185,1,0,104,168,1,0,112,152,1,0,248,135,1,0,136,206,1,0,128,119,1,0,56,106,1,0,136,206,1,0,16,124,2,0,184,110,2,0,128,96,2,0,88,83,2,0,32,70,2,0,40,59,2,0,136,47,2,0,104,33,2,0,192,22,2,0,88,13,2,0,0,4,2,0,224,252,1,0,72,245,1,0,16,235,1,0,8,227,1,0,24,220,1,0,8,218,1,0,48,215,1,0,120,212,1,0,96,210,1,0,96,208,1,0,152,206,1,0,136,206,1,0,8,204,1,0,96,201,1,0,48,199,1,0,64,197,1,0,136,206,1,0,120,195,1,0,96,193,1,0,176,190,1,0,192,188,1,0,152,206,1,0,136,206,1,0,0,187,1,0,208,184,1,0,192,182,1,0,152,180,1,0,192,178,1,0,16,177,1,0,208,175,1,0,16,174,1,0,136,172,1,0,64,171,1,0,136,206,1,0,216,169,1,0,24,167,1,0,176,165,1,0,192,163,1,0,48,162,1,0,136,206,1,0,208,160,1,0,96,159,1,0,240,157,1,0,144,156,1,0,32,155,1,0,216,153,1,0,240,151,1,0,104,150,1,0,128,148,1,0,240,146,1,0,168,145,1,0,88,144,1,0,152,206,1,0,136,206,1,0,144,142,1,0,240,140,1,0,184,138,1,0,104,33,2,0,136,206,1,0,56,137,1,0,24,136,1,0,248,133,1,0,40,132,1,0,216,130,1,0,0,129,1,0,96,127,1,0,184,125,1,0,16,124,1,0,200,122,1,0,104,33,2,0,136,206,1,0,208,120,1,0,16,119,1,0,248,117,1,0,104,116,1,0,24,115,1,0,248,113,1,0,192,112,1,0,96,111,1,0,152,206,1,0,136,206,1,0,48,110,1,0,176,108,1,0,120,107,1,0,224,105,1,0,168,104,1,0,168,102,1,0,96,101,1,0,48,100,1,0,208,98,1,0,160,97,1,0,128,96,1,0,152,206,1,0,136,206,1,0,40,95,1,0,32,125,2,0,136,206,1,0,200,123,2,0,160,122,2,0,224,120,2,0,144,119,2,0,104,118,2,0,40,117,2,0,232,115,2,0,192,114,2,0,112,113,2,0,136,206,1,0,240,111,2,0,136,206,1,0,96,110,2,0,32,109,2,0,64,107,2,0,144,105,2,0,32,104,2,0,160,102,2,0,152,206,1,0,136,206,1,0,64,101,2,0,136,206,1,0,72,100,2,0,24,99,2,0,200,97,2,0,56,96,2,0,8,95,2,0,184,93,2,0,112,92,2,0,104,33,2,0,136,206,1,0,16,91,2,0,136,206,1,0,240,89,2,0,248,88,2,0,80,87,2,0,248,85,2,0,160,84,2,0,24,83,2,0,200,81,2,0,136,206,1,0,248,79,2,0,96,78,2,0,232,76,2,0,216,75,2,0,120,74,2,0,88,73,2,0,16,72,2,0,248,70,2,0,136,206,1,0,240,69,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,36,64,0,0,0,0,0,0,89,64,0,0,0,0,0,136,195,64,0,0,0,0,132,215,151,65,0,128,224,55,121,195,65,67,23,110,5,181,181,184,147,70,245,249,63,233,3,79,56,77,50,29,48,249,72,119,130,90,60,191,115,127,221,79,21,117,40,116,1,0,96,102,1,0,152,120,2,0,0,0,0,0,0,0,0,0,4,0,0,0,216,106,2,0,0,0,0,0,0,0,0,0,88,93,2,0,96,102,1,0,152,120,2,0,0,0,0,0,160,79,2,0,5,0,0,0,216,106,2,0,0,0,0,0,40,67,2,0,64,56,2,0,96,102,1,0,96,44,2,0,0,0,0,0,0,0,0,0,6,0,0,0,216,106,2,0,176,30,2,0,0,0,0,0,200,19,2,0,96,102,1,0,96,44,2,0,0,0,0,0,160,79,2,0,7,0,0,0,216,106,2,0,176,30,2,0,40,67,2,0,120,10,2,0,224,1,2,0,96,44,2,0,0,0,0,0,0,0,0,0,10,0,0,0,32,251,1,0,176,30,2,0,0,0,0,0,96,242,1,0,224,1,2,0,96,44,2,0,0,0,0,0,40,67,2,0,11,0,0,0,32,251,1,0,176,30,2,0,40,67,2,0,80,232,1,0,224,1,2,0,152,224,1,0,0,0,0,0,0,0,0,0,8,0,0,0,32,251,1,0,0,0,0,0,0,0,0,0,96,219,1,0,224,1,2,0,152,224,1,0,0,0,0,0,40,67,2,0,9,0,0,0,32,251,1,0,0,0,0,0,40,67,2,0,0,217,1,0,0,217,1,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,80,214,1,0,0,0,0,0,0,0,0,0,200,211,1,0,0,217,1,0,176,30,2,0,0,0,0,0,0,0,0,0,14,0,0,0,80,214,1,0,176,30,2,0,0,0,0,0,168,209,1,0,0,217,1,0,176,30,2,0,0,0,0,0,160,79,2,0,15,0,0,0,80,214,1,0,176,30,2,0,40,67,2,0,152,207,1,0,0,217,1,0,0,0,0,0,0,0,0,0,160,79,2,0,13,0,0,0,80,214,1,0,0,0,0,0,40,67,2,0,72,205,1,0,72,205,1,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,216,106,2,0,0,0,0,0,0,0,0,0,32,203,1,0,72,205,1,0,176,30,2,0,0,0,0,0,0,0,0,0,18,0,0,0,216,106,2,0,176,30,2,0,0,0,0,0,160,200,1,0,72,205,1,0,176,30,2,0,0,0,0,0,160,79,2,0,19,0,0,0,216,106,2,0,176,30,2,0,40,67,2,0,136,198,1,0,72,205,1,0,0,0,0,0,152,196,1,0,0,0,0,0,20,0,0,0,216,106,2,0,0,0,0,0,0,0,0,0,208,194,1,0,72,205,1,0,176,30,2,0,152,196,1,0,0,0,0,0,22,0,0,0,216,106,2,0,176,30,2,0,0,0,0,0,176,192,1,0,72,205,1,0,176,30,2,0,152,196,1,0,160,79,2,0,23,0,0,0,216,106,2,0,176,30,2,0,40,67,2,0,96,190,1,0,72,205,1,0,0,0,0,0,152,196,1,0,160,79,2,0,21,0,0,0,216,106,2,0,0,0,0,0,40,67,2,0,88,188,1,0,72,205,1,0,0,0,0,0,0,0,0,0,160,79,2,0,17,0,0,0,216,106,2,0,0,0,0,0,40,67,2,0,168,186,1,0,80,184,1,0,176,30,2,0,0,0,0,0,0,0,0,0,26,0,0,0,32,251,1,0,176,30,2,0,0,0,0,0,160,182,1,0,80,184,1,0,176,30,2,0,0,0,0,0,40,67,2,0,27,0,0,0,32,251,1,0,176,30,2,0,40,67,2,0,96,180,1,0,80,184,1,0,0,0,0,0,0,0,0,0,40,67,2,0,25,0,0,0,32,251,1,0,0,0,0,0,40,67,2,0,152,178,1,0,80,184,1,0,8,177,1,0,0,0,0,0,0,0,0,0,24,0,0,0,32,251,1,0,0,0,0,0,0,0,0,0,192,175,1,0,248,173,1,0,176,30,2,0,0,0,0,0,0,0,0,0,30,0,0,0,32,251,1,0,176,30,2,0,0,0,0,0,112,172,1,0,248,173,1,0,176,30,2,0,0,0,0,0,40,67,2,0,31,0,0,0,32,251,1,0,176,30,2,0,40,67,2,0,48,171,1,0,248,173,1,0,0,0,0,0,0,0,0,0,40,67,2,0,29,0,0,0,32,251,1,0,0,0,0,0,40,67,2,0,200,169,1,0,248,173,1,0,8,177,1,0,0,0,0,0,0,0,0,0,28,0,0,0,32,251,1,0,0,0,0,0,0,0,0,0,240,166,1,0,240,166,1,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,168,165,1,0,0,0,0,0,0,0,0,0,144,163,1,0,32,162,1,0,176,30,2,0,0,0,0,0,0,0,0,0,2,0,0,0,32,251,1,0,176,30,2,0,0,0,0,0,184,160,1,0,32,162,1,0,176,30,2,0,0,0,0,0,40,67,2,0,3,0,0,0,32,251,1,0,176,30,2,0,40,67,2,0,80,159,1,0,32,162,1,0,0,0,0,0,0,0,0,0,40,67,2,0,1,0,0,0,32,251,1,0,0,0,0,0,40,67,2,0,224,157,1,0,32,162,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,251,1,0,0,0,0,0,0,0,0,0,96,156,1,0,0,155,1,0,192,153,1,0,0,0,0,0,40,67,2,0,33,0,0,0,32,251,1,0,0,0,0,0,40,67,2,0,176,151,1,0,72,150,1,0,0,0,0,0,0,0,0,0,0,0,0,0,34,0,0,0,168,165,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,1,0,0,144,0,0,0,164,1,0,0,208,1,0,0,138,0,0,0,242,1,0,0,152,143,1,0,192,141,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,0,0,0,144,0,0,0,164,1,0,0,130,2,0,0,0,0,0,0,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154,153,153,153,153,153,217,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,51,51,51,51,51,51,227,63,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,128,102,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,128,102,64,154,153,153,153,153,153,217,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,128,102,64,123,20,174,71,225,122,228,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123,20,174,71,225,122,228,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,51,51,51,51,51,51,211,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,128,70,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,128,70,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,104,7,2,0,32,0,2,0,208,248,1,0,88,239,1,0,24,230,1,0,176,222,1,0,216,218,1,0,88,216,1,0,128,213,1,0,56,211,1,0,8,209,1,0,48,207,1,0,184,204,1,0,120,202,1,0,8,200,1,0,40,198,1,0,32,196,1,0,64,194,1,0,8,192,1,0,192,189,1,0,232,187,1,0,0,0,0,0,2,3,4,5,6,7,8,0,0,9,10,11,12,13,14,15,16,17,0,0,0,0,0,0,0,0,0,0,0,0,18,19,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,23,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,4,254,255,255,135,254,255,255,7,0,0,0,0,0,0,0,0,255,255,127,255,255,255,127,255,255,255,255,255,255,255,243,127,254,253,255,255,255,255,255,127,255,255,255,255,255,255,255,255,15,224,255,255,255,255,49,252,255,255,255,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,1,0,248,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,215,255,255,251,255,255,255,255,127,127,84,253,255,15,0,254,223,255,255,255,255,255,255,255,255,254,223,255,255,255,255,3,0,255,255,255,255,255,255,159,25,255,255,255,207,63,3,0,0,0,0,0,0,254,255,255,255,127,2,254,255,255,255,127,0,0,0,0,0,0,0,0,0,255,255,255,7,7,0,0,0,0,0,254,255,255,7,254,7,0,0,0,0,254,255,255,255,255,255,255,255,255,124,255,127,47,0,96,0,0,0,224,255,255,255,255,255,255,35,0,0,0,255,3,0,0,0,224,159,249,255,255,253,197,3,0,0,0,176,3,0,3,0,224,135,249,255,255,253,109,3,0,0,0,94,0,0,28,0,224,175,251,255,255,253,237,35,0,0,0,0,1,0,0,0,224,159,249,255,255,253,205,35,0,0,0,176,3,0,0,0,224,199,61,214,24,199,191,3,0,0,0,0,0,0,0,0,224,223,253,255,255,253,239,3,0,0,0,0,3,0,0,0,224,223,253,255,255,253,239,3,0,0,0,64,3,0,0,0,224,223,253,255,255,253,255,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,255,255,255,255,127,13,0,63,0,0,0,0,0,0,0,150,37,240,254,174,108,13,32,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,254,255,255,255,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,63,0,255,255,255,255,127,0,237,218,7,0,0,0,0,80,1,80,49,130,171,98,44,0,0,0,0,64,0,201,128,245,7,0,0,0,0,8,1,2,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,15,255,255,255,255,255,255,255,255,255,255,255,3,255,255,63,63,255,255,255,255,63,63,255,170,255,255,255,63,255,255,255,255,255,255,223,95,220,31,207,15,255,31,220,31,0,0,0,0,64,76,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,254,3,0,0,254,255,255,255,255,255,255,255,255,255,31,0,254,255,255,255,255,255,255,255,255,255,255,7].concat([224,255,255,255,255,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,63,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,255,7,254,255,255,135,254,255,255,7,0,0,0,0,0,0,128,0,255,255,127,255,255,255,127,255,255,255,255,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,1,0,248,3,0,3,0,0,0,0,0,255,255,255,255,255,255,255,255,63,0,0,0,3,0,0,0,192,215,255,255,251,255,255,255,255,127,127,84,253,255,15,0,254,223,255,255,255,255,255,255,255,255,254,223,255,255,255,255,123,0,255,255,255,255,255,255,159,25,255,255,255,207,63,3,0,0,0,0,0,0,254,255,255,255,127,2,254,255,255,255,127,0,254,255,251,255,255,187,22,0,255,255,255,7,7,0,0,0,0,0,254,255,255,7,255,255,7,0,255,3,255,255,255,255,255,255,255,255,255,124,255,127,239,255,255,61,255,3,238,255,255,255,255,255,255,243,255,63,30,255,207,255,0,0,238,159,249,255,255,253,197,211,159,57,128,176,207,255,3,0,228,135,249,255,255,253,109,211,135,57,0,94,192,255,31,0,238,175,251,255,255,253,237,243,191,59,0,0,193,255,0,0,238,159,249,255,255,253,205,243,143,57,192,176,195,255,0,0,236,199,61,214,24,199,191,195,199,61,128,0,128,255,0,0,238,223,253,255,255,253,239,195,223,61,96,0,195,255,0,0,236,223,253,255,255,253,239,195,223,61,96,64,195,255,0,0,236,223,253,255,255,253,255,195,207,61,128,0,195,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,255,255,255,255,127,255,7,255,127,255,3,0,0,0,0,150,37,240,254,174,108,255,59,95,63,255,3,0,0,0,0,0,0,0,3,255,3,160,194,255,254,255,255,255,3,254,255,223,15,191,254,255,63,254,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,31,2,0,0,0,160,0,0,0,254,255,62,0,254,255,255,255,255,255,255,255,255,255,31,102,254,255,255,255,255,255,255,255,255,255,255,119,25,3,26,27,28,29,30,0,0,31,32,33,34,35,36,37,16,17,0,0,0,0,0,0,0,0,0,0,0,0,18,19,38,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,23,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,46,57,57,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,1,0,0,118,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,108,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,144,2,0,0,0,0,0,0,20,2,0,0,8,2,0,0,184,0,0,0,152,0,0,0,96,1,0,0,106,1,0,0,162,1,0,0,214,0,0,0,32,2,0,0,48,1,0,0,132,1,0,0,54,2,0,0,16,0,0,0,224,0,0,0,240,1,0,0,190,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,10,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,16,12,19,28,30,3,13,31,32,33,34,35,27,26,17,25,25,25,25,25,25,25,25,25,25,22,18,2,14,11,15,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,20,28,4,28,22,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,36,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,22,28,28,28,28,28,28,28,28,28,28,22,28,26,28,28,22,28,28,28,28,28,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,22,22,22,22,22,22,22,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,116,0,0,0,92,0,0,0,146,0,0,0,158,2,0,0,98,2,0,0,204,1,0,0,78,0,0,0,2,2,0,0,28,1,0,0,46,0,0,0,146,1,0,0,210,0,0,0,108,0,0,0,72,0,0,0,214,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,10,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,16,12,19,28,30,3,13,31,32,33,34,35,27,26,17,25,25,25,25,25,25,25,25,25,25,22,18,2,14,11,15,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,20,28,4,28,22,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,36,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,22,28,28,28,28,28,28,28,28,28,28,22,28,26,28,28,22,28,28,28,28,28,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,22,22,22,22,22,22,22,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,252,1,0,8,0,0,0,3,0,0,0,232,244,1,0,160,234,1,0,11,0,0,0,6,0,0,0,144,226,1,0,8,220,1,0,2,0,0,0,1,0,0,0,248,217,1,0,32,215,1,0,4,0,0,0,2,0,0,0,104,212,1,0,80,210,1,0,4,0,0,0,4,0,0,0,80,208,1,0,128,206,1,0,5,0,0,0,5,0,0,0,248,203,1,0,80,201,1,0,4,0,0,0,7,0,0,0,32,199,1,0,8,197,1,0,5,0,0,0,9,0,0,0,104,195,1,0,1,208,209,210,211,212,213,214,215,216,217,0,0,0,0,0,0,0,0,0,0,0,0,0,100,0,0,0,116,0,0,0,92,0,0,0,146,0,0,0,158,2,0,0,98,2,0,0,204,1,0,0,78,0,0,0,2,2,0,0,28,1,0,0,46,0,0,0,146,1,0,0,210,0,0,0,108,0,0,0,26,0,0,0,94,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,21,10,0,0,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,16,12,19,28,30,3,13,31,32,33,34,35,27,26,17,25,25,25,25,25,25,25,25,25,25,22,18,2,14,11,15,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,20,28,4,28,22,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,36,28,28,28,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,0,0,0,0,0,0,0,0,0,1,1,64,0,0,0,250,1,0,0,210,1,0,0,98,1,0,0,178,0,0,0,210,1,0,0,226,0,0,0,228,0,0,0,236,0,0,0,0,0,0,0,8,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,66,1,0,0,168,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,109,108,61,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99,101,0,0,0,0,0,0,0,0,136,249,1,0,222,0,0,0,104,240,1,0,70,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,0,0,23,16,17,18,19,30,36,38,40,42,44,45,1,27,23,23,23,23,2,28,29,36,38,40,42,47,48,30,203,30,4,30,46,30,83,30,30,5,6,77,78,49,4,7,8,9,10,11,12,5,6,46,72,49,52,7,8,9,10,11,12,66,217,55,66,70,58,72,75,4,23,16,17,18,19,4,85,52,37,39,41,43,5,6,88,90,91,92,7,8,9,10,11,12,4,79,57,55,51,54,71,5,6,80,76,84,0,7,8,9,10,11,12,4,60,0,0,58,0,0,5,6,0,0,0,0,7,8,9,10,11,12,4,0,0,0,0,61,0,5,6,0,0,0,0,7,8,9,10,11,12,4,0,0,0,0,0,63,5,6,0,0,0,4,7,8,9,10,11,12,5,6,0,0,0,0,7,8,9,10,11,12,0,0,0,2,3,3,1,1,2,1,1,1,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,0,6,1,3,3,3,3,1,0,1,2,0,4,1,2,0,4,0,4,0,4,0,3,2,1,0,0,0,0,0,0,0,0,31,32,32,32,33,34,34,35,35,35,35,35,35,35,35,36,37,38,39,40,41,42,43,44,45,46,47,48,48,49,49,51,50,52,52,52,52,52,53,53,54,54,56,55,57,57,59,58,60,58,61,58,62,58,63,63,0,0,0,0,0,0,0,245,245,23,246,247,255,61,0,60,1,55,2,71,245,245,245,245,245,254,62,245,31,34,245,33,245,245,32,245,245,245,245,245,0,0,0,0,0,0,0,11,0,245,255,151,0,13,0,245,255,245,255,16,0,245,255,245,255,245,255,245,255,245,255,245,255,12,0,151,0,245,255,151,0,151,0,151,0,151,0,151,0,151,0,245,255,39,0,245,255,17,0,3,0,245,255,245,255,245,255,245,255,151,0,151,0,151,0,151,0,20,0,30,0,42,0,63,0,40,0,82,0,48,0,101,0,50,0,120,0,139,0,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,245,255,59,0,245,255,56,0,245,255,43,0,57,0,245,255,18,0,28,0,245,255,20,0,245,255,245,255,72,0,245,255,245,255,74,0,245,255,245,255,245,255,245,255,75,0,76,0,245,255,77,0,245,255,245,255,245,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,3,13,14,15,31,50,32,53,33,56,34,59,20,62,21,64,22,35,24,65,25,26,67,68,69,73,74,87,86,89,81,82,0,0,0,0,0,0,0,0,4,40,0,30,29,0,16,18,20,22,24,26,0,5,7,40,40,40,40,0,0,9,8,34,0,0,1,28,2,6,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,31,3,32,17,10,35,19,11,36,21,13,38,23,12,37,25,14,27,15,0,43,0,41,0,40,42,40,0,45,39,33,56,0,49,47,0,51,44,46,55,0,0,54,0,50,48,52,0,0,0,2,2,2,2,2,14,16,17,18,19,20,21,1,0,16,17,18,19,7,3,8,31,32,33,34,8,23,36,10,38,12,40,12,42,6,44,45,19,20,21,22,11,12,25,26,27,28,29,30,19,20,12,24,11,14,25,26,27,28,29,30,5,23,15,5,9,16,24,70,12,72,72,72,72,72,12,4,14,16,17,18,19,19,20,10,10,10,10,25,26,27,28,29,30,12,72,41,15,37,39,67,19,20,72,70,73,255,25,26,27,28,29,30,12,43,255,255,16,255,255,19,20,255,255,255,255,25,26,27,28,29,30,12,255,255,255,255,17,255,19,20,255,255,255,255,25,26,27,28,29,30,12,255,255,255,255,255,18,19,20,255,255,255,12,25,26,27,28,29,30,19,20,255,255,255,255,25,26,27,28,29,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152,114,1,0,1,0,0,0,152,1,0,0,32,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,181,1,0,1,0,0,0,224,3,0,0,64,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,253,1,0,1,0,0,0,96,15,0,0,96,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,69,2,0,1,0,0,0,112,18,0,0,128,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,80,135,1,0,1,0,0,0,24,44,0,0,160,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,201,1,0,1,0,0,0,112,64,0,0,192,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,176,201,1,0,1,0,0,0,168,79,0,0,224,17,0,0,4,0,0,0,64,181,1,0,1,0,0,0,40,0,0,0,0,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40,208,1,0,120,89,1,0,16,208,1,0,248,88,1,0,15,0,0,0,56,151,1,0,1,0,0,0,0,79,0,0,0,0,0,0,16,0,0,0,176,46,2,0,1,0,0,0,0,79,0,0,0,0,0,0,17,0,0,0,232,217,1,0,1,0,0,0,0,79,0,0,0,0,0,0,17,0,0,0,80,195,1,0,1,0,0,0,0,79,0,0,0,0,0,0,17,0,0,0,24,176,1,0,1,0,0,0,0,79,0,0,0,0,0,0,19,0,0,0,168,159,1,0,1,0,0,0,32,79,0,0,0,0,0,0,20,0,0,0,152,144,1,0,1,0,0,0,32,79,0,0,0,0,0,0,21,0,0,0,176,127,1,0,1,0,0,0,32,79,0,0,0,0,0,0,21,0,0,0,16,113,1,0,1,0,0,0,32,79,0,0,0,0,0,0,21,0,0,0,32,99,1,0,1,0,0,0,32,79,0,0,0,0,0,0,22,0,0,0,112,117,2,0,1,0,0,0,240,78,0,0,0,0,0,0,23,0,0,0,8,103,2,0,1,0,0,0,240,78,0,0,0,0,0,0,24,0,0,0,56,90,2,0,1,0,0,0,240,78,0,0,0,0,0,0,24,0,0,0,168,75,2,0,1,0,0,0,240,78,0,0,0,0,0,0,24,0,0,0,112,64,2,0,1,0,0,0,240,78,0,0,0,0,0,0,25,0,0,0,128,53,2,0,1,0,0,0,16,79,0,0,0,0,0,0,25,0,0,0,136,41,2,0,1,0,0,0,16,79,0,0,0,0,0,0,25,0,0,0,168,27,2,0,1,0,0,0,16,79,0,0,0,0,0,0,25,0,0,0,120,17,2,0,1,0,0,0,16,79,0,0,0,0,0,0,26,0,0,0,112,7,2,0,1,0,0,0,8,79,0,0,0,0,0,0,10,0,0,0,40,0,2,0,1,0,0,0,24,79,0,0,0,0,0,0,11,0,0,0,224,248,1,0,1,0,0,0,24,79,0,0,0,0,0,0,12,0,0,0,112,239,1,0,1,0,0,0,24,79,0,0,0,0,0,0,12,0,0,0,32,230,1,0,1,0,0,0,24,79,0,0,0,0,0,0,12,0,0,0,184,222,1,0,1,0,0,0,24,79,0,0,0,0,0,0,14,0,0,0,224,218,1,0,1,0,0,0,24,79,0,0,0,0,0,0,14,0,0,0,96,216,1,0,1,0,0,0,24,79,0,0,0,0,0,0,13,0,0,0,136,213,1,0,1,0,0,0,24,79,0,0,0,0,0,0,5,0,0,0,64,211,1,0,1,0,0,0,24,79,0,0,0,0,0,0,6,0,0,0,16,209,1,0,1,0,0,0,24,79,0,0,0,0,0,0,7,0,0,0,56,207,1,0,1,0,0,0,24,79,0,0,0,0,0,0,7,0,0,0,192,204,1,0,1,0,0,0,24,79,0,0,0,0,0,0,7,0,0,0,128,202,1,0,1,0,0,0,24,79,0,0,0,0,0,0,9,0,0,0,16,200,1,0,1,0,0,0,24,79,0,0,0,0,0,0,9,0,0,0,48,198,1,0,1,0,0,0,24,79,0,0,0,0,0,0,8,0,0,0,40,196,1,0,1,0,0,0,24,79,0,0,0,0,0,0,0,0,0,0,72,194,1,0,1,0,0,0,232,78,0,0,0,0,0,0,1,0,0,0,16,192,1,0,1,0,0,0,232,78,0,0,0,0,0,0,2,0,0,0,200,189,1,0,1,0,0,0,232,78,0,0,0,0,0,0,2,0,0,0,240,187,1,0,1,0,0,0,232,78,0,0,0,0,0,0,2,0,0,0,64,186,1,0,1,0,0,0,232,78,0,0,0,0,0,0,4,0,0,0,8,184,1,0,1,0,0,0,232,78,0,0,0,0,0,0,4,0,0,0,32,182,1,0,1,0,0,0,232,78,0,0,0,0,0,0,3,0,0,0,232,179,1,0,1,0,0,0,232,78,0,0,0,0,0,0,18,0,0,0,64,178,1,0,1,0,0,0,0,79,0,0,0,0,0,0,27,0,0,0,184,176,1,0,1,0,0,0,248,78,0,0,0,0,0,0,28,0,0,0,96,175,1,0,1,0,0,0,248,78,0,0,0,0,0,0,29,0,0,0,168,173,1,0,1,0,0,0,248,78,0,0,0,0,0,0,29,0,0,0,16,172,1,0,1,0,0,0,248,78,0,0,0,0,0,0,29,0,0,0,224,170,1,0,1,0,0,0,248,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,84,2,0,0,0,0,0,160,79,0,0,152,79,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,48,193,1,0,200,1,0,0,144,73,2,0,76,2,0,0,152,228,1,0,76,2,0,0,120,199,1,0,162,2,0,0,88,179,1,0,162,2,0,0,144,162,1,0,10,0,0,0,232,146,1,0,10,0,0,0,176,130,1,0,180,0,0,0,232,114,1,0,180,0,0,0,32,101,1,0,40,0,0,0,40,119,2,0,40,0,0,0,8,105,2,0,156,0,0,0,200,91,2,0,156,0,0,0,128,81,2,0,86,1,0,0,0,0,0,0,240,100,1,0,1,0,0,0,0,0,0,0,144,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,208,67,2,0,1,0,0,0,0,0,0,0,200,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,96,2,0,1,0,0,0,0,0,0,0,0,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,67,2,0,1,0,0,0,0,0,0,0,56,81,0,0,1,0,0,0,136,66,2,0,1,0,0,0,0,0,0,0,56,81,0,0,2,0,0,0,72,65,2,0,1,0,0,0,0,0,0,0,24,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,240,29,2,0,1,0,0,0,0,0,0,0,112,81,0,0,2,0,0,0,192,213,1,0,1,0,0,0,0,0,0,0,168,81,0,0,0,0,0,0,32,192,1,0,1,0,0,0,0,0,0,0,168,81,0,0,3,0,0,0,136,173,1,0,1,0,0,0,0,0,0,0,168,81,0,0,0,0,0,0,80,157,1,0,1,0,0,0,0,0,0,0,112,81,0,0,3,0,0,0,128,141,1,0,1,0,0,0,0,0,0,0,112,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,160,75,2,0,1,0,0,0,0,0,0,0,224,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,72,164,1,0,1,0,0,0,0,0,0,0,80,82,0,0,0,0,0,0,232,148,1,0,1,0,0,0,0,0,0,0,80,82,0,0,1,0,0,0,152,132,1,0,1,0,0,0,0,0,0,0,136,82,0,0,2,0,0,0,208,116,1,0,1,0,0,0,0,0,0,0,80,82,0,0,3,0,0,0,32,103,1,0,1,0,0,0,0,0,0,0,80,82,0,0,4,0,0,0,72,121,2,0,1,0,0,0,0,0,0,0,80,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,0,0,0,208,0,0,0,22,2,0,0,166,2,0,0,48,2,0,0,2,1,0,0,114,2,0,0,154,2,0,0,174,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,207,1,0,192,205,1,0,160,203,1,0,0,0,0,0,100,0,0,0,101,0,0,0,102,0,0,0,100,0,0,0,32,201,1,0,224,198,1,0,224,196,1,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,176,139,2,0,72,139,2,0,24,139,2,0,64,139,2,0,48,139,2,0,32,139,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,205,1,0,104,2,0,0,168,202,1,0,140,2,0,0,40,200,1,0,60,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,228,1,0,112,199,1,0,80,179,1,0,136,162,1,0,224,146,1,0,168,130,1,0,224,114,1,0,24,101,1,0,0,0,0,0,0,0,0,0,14,2,0,0,144,1,0,0,0,0,0,0,0,0,0,0,84,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,74,2,0,0,148,2,0,0,82,1,0,0,18,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,1,0,0,82,2,0,0,224,1,0,0,156,2,0,0,32,0,0,0,30,2,0,0,108,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,2,0,0,126,0,0,0,164,1,0,0,60,0,0,0,0,0,0,0,38,0,0,0,80,191,1,0,198,0,0,0,24,189,1,0,193,0,0,0,80,187,1,0,194,0,0,0,152,185,1,0,192,0,0,0,64,183,1,0,145,3,0,0,32,181,1,0,197,0,0,0,72,179,1,0,195,0,0,0,152,177,1,0,196,0,0,0,48,176,1,0,146,3,0,0,128,174,1,0,199,0,0,0,224,172,1,0,167,3,0,0,144,171,1,0,33,32,0,0,40,170,1,0,148,3,0,0,112,168,1,0,208,0,0,0,32,166,1,0,201,0,0,0,32,164,1,0,202,0,0,0,168,162,1,0,200,0,0,0,88,161,1,0,149,3,0,0,192,159,1,0,151,3,0,0,56,158,1,0,203,0,0,0,216,156,1,0,147,3,0,0,120,155,1,0,205,0,0,0,56,154,1,0,206,0,0,0,144,152,1,0,204,0,0,0,184,150,1,0,153,3,0,0,192,148,1,0,207,0,0,0,104,147,1,0,154,3,0,0,240,145,1,0,155,3,0,0,176,144,1,0,156,3,0,0,248,142,1,0,209,0,0,0,64,141,1,0,157,3,0,0,8,139,1,0,82,1,0,0,168,137,1,0,211,0,0,0,16,136,1,0,212,0,0,0,88,134,1,0,210,0,0,0,120,132,1,0,169,3,0,0,32,131,1,0,159,3,0,0,88,129,1,0,216,0,0,0,208,127,1,0,213,0,0,0,64,126,1,0,214,0,0,0,112,124,1,0,166,3,0,0,16,123,1,0,160,3,0,0,56,121,1,0,51,32,0,0,192,119,1,0,168,3,0,0,72,118,1,0,161,3,0,0,176,116,1,0,96,1,0,0,104,115,1,0,163,3,0,0,72,114,1,0,222,0,0,0,40,113,1,0,164,3,0,0,152,111,1,0,152,3,0,0,104,110,1,0,218,0,0,0,248,108,1,0,219,0,0,0,184,107,1,0,217,0,0,0,88,106,1,0,165,3,0,0,240,104,1,0,220,0,0,0,240,102,1,0,158,3,0,0,160,101,1,0,221,0,0,0,136,100,1,0,120,1,0,0,40,99,1,0,150,3,0,0,232,97,1,0,225,0,0,0,200,96,1,0,226,0,0,0,120,95,1,0,180,0,0,0,104,125,2,0,230,0,0,0,56,124,2,0,224,0,0,0,8,123,2,0,53,33,0,0,24,121,2,0,177,3,0,0,184,119,2,0,38,0,0,0,168,118,2,0,39,34,0,0,144,117,2,0,32,34,0,0,16,116,2,0,229,0,0,0,232,114,2,0,72,34,0,0,152,113,2,0,227,0,0,0,56,112,2,0,228,0,0,0,200,110,2,0,30,32,0,0,8,109,2,0,178,3,0,0,120,107,2,0,166,0,0,0,72,106,2,0,34,32,0,0,160,104,2,0,41,34,0,0,80,103,2,0,231,0,0,0,240,101,2,0,184,0,0,0,176,100,2,0,162,0,0,0,160,99,2,0,199,3,0,0,80,98,2,0,198,2,0,0,176,96,2,0,99,38,0,0,128,95,2,0,69,34,0,0,40,94,2,0,169,0,0,0,248,92,2,0,181,33,0,0,112,91,2,0,42,34,0,0,128,90,2,0,164,0,0,0,56,89,2,0,211,33,0,0,224,87,2,0,32,32,0,0,104,86,2,0,147,33,0,0,40,85,2,0,176,0,0,0,224,83,2,0,180,3,0,0,96,82,2,0,102,38,0,0,184,80,2,0,247,0,0,0,32,79,2,0,233,0,0,0,120,76,2,0,234,0,0,0,48,76,2,0,232,0,0,0,216,74,2,0,5,34,0,0,216,73,2,0,3,32,0,0,120,72,2,0,2,32,0,0,64,71,2,0,181,3,0,0,112,70,2,0,97,34,0,0,104,69,2,0,183,3,0,0,232,67,2,0,240,0,0,0,208,66,2,0,235,0,0,0,176,65,2,0,172,32,0,0,192,64,2,0,3,34,0,0,192,63,2,0,146,1,0,0,176,62,2,0,0,34,0,0,80,61,2,0,189,0,0,0,96,60,2,0,188,0,0,0,144,59,2,0,190,0,0,0,112,58,2,0,68,32,0,0,8,57,2,0,179,3,0,0,232,55,2,0,101,34,0,0,216,54,2,0,62,0,0,0,216,53,2,0,212,33,0,0,200,52,2,0,148,33,0,0,232,51,2,0,101,38,0,0,248,50,2,0,38,32,0,0,72,49,2,0,237,0,0,0,72,48,2,0,238,0,0,0,128,46,2,0,161,0,0,0,72,45,2,0,236,0,0,0,0,44,2,0,17,33,0,0,8,43,2,0,30,34,0,0,248,41,2,0,43,34,0,0,232,40,2,0,185,3,0,0,224,39,2,0,191,0,0,0,248,38,2,0,8,34,0,0,160,34,2,0,239,0,0,0,200,33,2,0,186,3,0,0,144,32,2,0,208,33,0,0,128,31,2,0,187,3,0,0,80,30,2,0,41,35,0,0,64,29,2,0,171,0,0,0,88,28,2,0,144,33,0,0,32,27,2,0,8,35,0,0,64,26,2,0,28,32,0,0,88,25,2,0,100,34,0,0,24,24,2,0,10,35,0,0,32,23,2,0,23,34,0,0,16,22,2,0,202,37,0,0,184,20,2,0,14,32,0,0,120,19,2,0,57,32,0,0,128,18,2,0,24,32,0,0,200,17,2,0,60,0,0,0,8,17,2,0,175,0,0,0,56,16,2,0,20,32,0,0,72,15,2,0,181,0,0,0,112,14,2,0,183,0,0,0,184,13,2,0,18,34,0,0,168,12,2,0,188,3,0,0,136,11,2,0,7,34,0,0,32,10,2,0,160,0,0,0,32,9,2,0,19,32,0,0,224,7,2,0,96,34,0,0,240,6,2,0,11,34,0,0,40,6,2,0,172,0,0,0,128,5,2,0,9,34,0,0,224,4,2,0,132,34,0,0,80,4,2,0,241,0,0,0,136,3,2,0,189,3,0,0,192,2,2,0,243,0,0,0,192,1,2,0,244,0,0,0,24,1,2,0,83,1,0,0,112,0,2,0,242,0,0,0,208,255,1,0,62,32,0,0,72,255,1,0,201,3,0,0,136,254,1,0,191,3,0,0,224,253,1,0,149,34,0,0,64,253,1,0,40,34,0,0,72,252,1,0,170,0,0,0,168,251,1,0,186,0,0,0,0,251,1,0,248,0,0,0,80,250,1,0,245,0,0,0,80,249,1,0,151,34,0,0,160,248,1,0,246,0,0,0,248,247,1,0,182,0,0,0,72,247,1,0,2,34,0,0,136,246,1,0,48,32,0,0,200,245,1,0,165,34,0,0,96,244,1,0,198,3,0,0,104,243,1,0,192,3,0,0,40,242,1,0,214,3,0,0,48,241,1,0,177,0,0,0,216,239,1,0,163,0,0,0,248,238,1,0,50,32,0,0,0,238,1,0,15,34,0,0,96,237,1,0,29,34,0,0,120,236,1,0,200,3,0,0,144,235,1,0,34,0,0,0,72,234,1,0,210,33,0,0,24,233,1,0,26,34,0,0,24,232,1,0,42,35,0,0,112,231,1,0,187,0,0,0,144,230,1,0,146,33,0,0,208,229,1,0,9,35,0,0,88,229,1,0,29,32,0,0,224,228,1,0,28,33,0,0,8,228,1,0,174,0,0,0,120,227,1,0,11,35,0,0,80,226,1,0,193,3,0,0,104,225,1,0,15,32,0,0,112,224,1,0,58,32,0,0,192,223,1,0,25,32,0,0,144,222,1,0,26,32,0,0,104,222,1,0,97,1,0,0,160,221,1,0,197,34,0,0,32,221,1,0,167,0,0,0,120,220,1,0,173,0,0,0,96,220,1,0,195,3,0,0,0,220,1,0,194,3,0,0,192,219,1,0,60,34,0,0,88,219,1,0,96,38,0,0,48,219,1,0,130,34,0,0,8,219,1,0,134,34,0,0,208,218,1,0,17,34,0,0,176,218,1,0,131,34,0,0,136,218,1,0,185,0,0,0,104,218,1,0,178,0,0,0,80,218,1,0,179,0,0,0,224,217,1,0,135,34,0,0,88,217,1,0,223,0,0,0,248,216,1,0,196,3,0,0,208,216,1,0,52,34,0,0,160,216,1,0,184,3,0,0,64,216,1,0,209,3,0,0,8,216,1,0,9,32,0,0,224,215,1,0,254,0,0,0,144,215,1,0,220,2,0,0,120,215,1,0,215,0,0,0,24,215,1,0,34,33,0,0,168,214,1,0,209,33,0,0,72,214,1,0,250,0,0,0,232,213,1,0,145,33,0,0,176,213,1,0,251,0,0,0,120,213,1,0,249,0,0,0,80,213,1,0,168,0,0,0,40,213,1,0,210,3,0,0,8,213,1,0,197,3,0,0,176,212,1,0,252,0,0,0,96,212,1,0,24,33,0,0,16,212,1,0,190,3,0,0,192,211,1,0,253,0,0,0,160,211,1,0,165,0,0,0,88,211,1,0,255,0,0,0,32,211,1,0,182,3,0,0,0,211,1,0,13,32,0,0,216,210,1,0,12,32,0,0,186,0,0,0,0,0,0,0,10,1,0,0,0,0,0,0,164,0,0,0,0,0,0,0,44,2,0,0,0,0,0,0,118,1,0,0,0,0,0,0,44,1,0,0,0,0,0,0,160,1,0,0,0,0,0,0,140,0,0,0,0,0,0,0,64,46,0,0,136,79,1,0,16,2,0,0,176,77,1,0,176,77,1,0,200,44,0,0,16,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,78,2,0,0,28,0,0,0,0,0,0,0,0,0,0,0,40,1,0,0,50,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
+.concat([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,79,84,65,84,73,79,78,40,0,0,0,0,0,0,0,40,0,0,0,0,0,0,0,124,0,0,0,0,0,0,0,78,77,84,79,75,69,78,83,0,0,0,0,0,0,0,0,78,77,84,79,75,69,78,0,73,68,82,69,70,83,0,0,73,68,82,69,70,0,0,0,73,68,0,0,0,0,0,0,69,78,84,73,84,89,0,0,69,78,84,73,84,73,69,83,0,0,0,0,0,0,0,0,67,68,65,84,65,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,64,0,0,0,0,0,0,88,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,64,0,0,0,0,0,0,88,64,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64,96,0,0,0,0,0,0,0,0,0,0,0,0,0,66,64,0,0,0,0,0,0,66,64,0,0,0,0,0,32,131,64,0,0,0,0,0,192,136,64,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,64,0,0,0,0,0,0,88,64,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,64,0,0,0,0,0,0,88,64,2,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,150,64,0,0,0,0,0,128,150,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,64,0,0,0,0,0,0,66,64,0,0,0,0,0,32,131,64,0,0,0,0,0,192,136,64,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64,0,153,1,0,224,150,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,184,212,1,0,85,93,201,127,201,127,255,0,104,191,1,0,187,45,212,190,174,212,255,0,232,172,1,0,20,119,253,253,192,134,255,0,224,156,1,0,85,93,201,127,201,127,255,0,72,141,1,0,187,45,212,190,174,212,255,0,120,124,1,0,20,119,253,253,192,134,255,0,128,110,1,0,42,102,255,255,255,153,255,0,224,96,1,0,85,93,201,127,201,127,255,0,0,115,2,0,187,45,212,190,174,212,255,0,128,100,2,0,20,119,253,253,192,134,255,0,176,87,2,0,42,102,255,255,255,153,255,0,168,73,2,0,151,173,176,56,108,176,255,0,112,62,2,0,85,93,201,127,201,127,255,0,168,51,2,0,187,45,212,190,174,212,255,0,160,39,2,0,20,119,253,253,192,134,255,0,0,26,2,0,42,102,255,255,255,153,255,0,248,15,2,0,151,173,176,56,108,176,255,0,216,5,2,0,232,252,240,240,2,127,255,0,16,255,1,0,85,93,201,127,201,127,255,0,192,247,1,0,187,45,212,190,174,212,255,0,192,237,1,0,20,119,253,253,192,134,255,0,32,229,1,0,42,102,255,255,255,153,255,0,96,221,1,0,151,173,176,56,108,176,255,0,144,218,1,0,232,252,240,240,2,127,255,0,232,215,1,0,17,224,191,191,91,23,255,0,48,213,1,0,85,93,201,127,201,127,255,0,224,210,1,0,187,45,212,190,174,212,255,0,192,208,1,0,20,119,253,253,192,134,255,0,240,206,1,0,42,102,255,255,255,153,255,0,120,204,1,0,151,173,176,56,108,176,255,0,8,202,1,0,232,252,240,240,2,127,255,0,200,199,1,0,17,224,191,191,91,23,255,0,224,197,1,0,0,0,102,102,102,102,255,0,232,195,1,0,147,25,247,222,235,247,255,0,248,193,1,0,142,75,225,158,202,225,255,0,168,191,1,0,145,188,189,49,130,189,255,0,128,189,1,0,159,16,255,239,243,255,255,0,168,187,1,0,143,46,231,189,215,231,255,0,248,185,1,0,143,127,214,107,174,214,255,0,144,183,1,0,147,208,181,33,113,181,255,0,136,181,1,0,159,16,255,239,243,255,255,0,176,179,1,0,143,46,231,189,215,231,255,0,0,178,1,0,143,127,214,107,174,214,255,0,128,176,1,0,145,188,189,49,130,189,255,0,0,175,1,0,149,241,156,8,81,156,255,0,56,173,1,0,159,16,255,239,243,255,255,0,216,171,1,0,148,43,239,198,219,239,255,0,112,170,1,0,142,75,225,158,202,225,255,0,216,168,1,0,143,127,214,107,174,214,255,0,96,166,1,0,145,188,189,49,130,189,255,0,136,164,1,0,149,241,156,8,81,156,255,0,232,162,1,0,159,16,255,239,243,255,255,0,152,161,1,0,148,43,239,198,219,239,255,0,24,160,1,0,142,75,225,158,202,225,255,0,176,158,1,0,143,127,214,107,174,214,255,0,64,157,1,0,144,169,198,66,146,198,255,0,192,155,1,0,147,208,181,33,113,181,255,0,136,154,1,0,151,241,148,8,69,148,255,0,24,153,1,0,148,8,255,247,251,255,255,0,16,151,1,0,147,25,247,222,235,247,255,0,56,149,1,0,148,43,239,198,219,239,255,0,176,147,1,0,142,75,225,158,202,225,255,0,64,146,1,0,143,127,214,107,174,214,255,0,240,144,1,0,144,169,198,66,146,198,255,0,112,143,1,0,147,208,181,33,113,181,255,0,160,141,1,0,151,241,148,8,69,148,255,0,32,140,1,0,148,8,255,247,251,255,255,0,240,137,1,0,147,25,247,222,235,247,255,0,144,136,1,0,148,43,239,198,219,239,255,0,160,134,1,0,142,75,225,158,202,225,255,0,224,132,1,0,143,127,214,107,174,214,255,0,96,131,1,0,144,169,198,66,146,198,255,0,152,129,1,0,147,208,181,33,113,181,255,0,24,128,1,0,149,241,156,8,81,156,255,0,184,126,1,0,152,235,107,8,48,107,255,0,192,124,1,0,23,239,84,84,48,5,255,0,104,123,1,0,119,255,60,0,60,48,255,0,168,121,1,0,23,236,140,140,81,10,255,0,56,120,1,0,24,194,191,191,129,45,255,0,136,118,1,0,29,112,223,223,194,125,255,0,56,117,1,0,30,52,246,246,232,195,255,0,216,115,1,0,121,38,234,199,234,229,255,0,136,114,1,0,120,95,205,128,205,193,255,0,112,113,1,0,124,165,151,53,151,143,255,0,32,112,1,0,124,252,102,1,102,94,255,0,208,110,1,0,23,239,84,84,48,5,255,0,104,109,1,0,124,252,102,1,102,94,255,0,24,108,1,0,119,255,60,0,60,48,255,0,176,106,1,0,23,236,140,140,81,10,255,0,64,105,1,0,24,194,191,191,129,45,255,0,176,103,1,0,29,112,223,223,194,125,255,0,0,102,1,0,30,52,246,246,232,195,255,0,208,100,1,0,0,0,245,245,245,245,255,0,112,99,1,0,121,38,234,199,234,229,255,0,88,98,1,0,120,95,205,128,205,193,255,0,32,97,1,0,124,165,151,53,151,143,255,0,240,95,1,0,28,135,216,216,179,101,255,0,144,94,1,0,0,0,245,245,245,245,255,0,144,124,2,0,123,127,180,90,180,172,255,0,72,123,2,0,21,215,166,166,97,26,255,0,184,121,2,0,29,112,223,223,194,125,255,0,24,120,2,0,120,95,205,128,205,193,255,0,232,118,2,0,121,253,133,1,133,113,255,0,208,117,2,0,21,215,166,166,97,26,255,0,120,116,2,0,29,112,223,223,194,125,255,0,56,115,2,0,0,0,245,245,245,245,255,0,232,113,2,0,120,95,205,128,205,193,255,0,168,112,2,0,121,253,133,1,133,113,255,0,96,111,2,0,23,236,140,140,81,10,255,0,128,109,2,0,28,135,216,216,179,101,255,0,216,107,2,0,30,52,246,246,232,195,255,0,80,106,2,0,121,38,234,199,234,229,255,0,168,104,2,0,123,127,180,90,180,172,255,0,88,103,2,0,124,252,102,1,102,94,255,0,248,101,2,0,23,236,140,140,81,10,255,0,184,100,2,0,28,135,216,216,179,101,255,0,168,99,2,0,30,52,246,246,232,195,255,0,96,98,2,0,0,0,245,245,245,245,255,0,32,97,2,0,121,38,234,199,234,229,255,0,136,95,2,0,123,127,180,90,180,172,255,0,72,94,2,0,124,252,102,1,102,94,255,0,0,93,2,0,23,236,140,140,81,10,255,0,184,91,2,0,24,194,191,191,129,45,255,0,136,90,2,0,29,112,223,223,194,125,255,0,64,89,2,0,30,52,246,246,232,195,255,0,232,87,2,0,121,38,234,199,234,229,255,0,112,86,2,0,120,95,205,128,205,193,255,0,56,85,2,0,124,165,151,53,151,143,255,0,232,83,2,0,124,252,102,1,102,94,255,0,104,82,2,0,23,236,140,140,81,10,255,0,192,80,2,0,24,194,191,191,129,45,255,0,40,79,2,0,29,112,223,223,194,125,255,0,104,77,2,0,30,52,246,246,232,195,255,0,56,76,2,0,0,0,245,245,245,245,255,0,224,74,2,0,121,38,234,199,234,229,255,0,224,73,2,0,120,95,205,128,205,193,255,0,128,72,2,0,124,165,151,53,151,143,255,0,80,71,2,0,124,252,102,1,102,94,255,0,120,70,2,0,135,20,249,229,245,249,255,0,112,69,2,0,117,74,216,153,216,201,255,0,248,67,2,0,103,185,162,44,162,95,255,0,216,66,2,0,136,14,251,237,248,251,255,0,184,65,2,0,127,54,226,178,226,226,255,0,200,64,2,0,113,120,194,102,194,164,255,0,200,63,2,0,98,190,139,35,139,69,255,0,184,62,2,0,136,14,251,237,248,251,255,0,88,61,2,0,127,54,226,178,226,226,255,0,112,60,2,0,113,120,194,102,194,164,255,0,152,59,2,0,103,185,162,44,162,95,255,0,120,58,2,0,102,255,109,0,109,44,255,0,16,57,2,0,136,14,251,237,248,251,255,0,240,55,2,0,119,34,236,204,236,230,255,0,224,54,2,0,117,74,216,153,216,201,255,0,224,53,2,0,113,120,194,102,194,164,255,0,208,52,2,0,103,185,162,44,162,95,255,0,240,51,2,0,102,255,109,0,109,44,255,0,0,51,2,0,136,14,251,237,248,251,255,0,96,49,2,0,119,34,236,204,236,230,255,0,80,48,2,0,117,74,216,153,216,201,255,0,136,46,2,0,113,120,194,102,194,164,255,0,80,45,2,0,105,159,174,65,174,118,255,0,8,44,2,0,98,190,139,35,139,69,255,0,16,43,2,0,102,255,88,0,88,36,255,0,0,42,2,0,134,6,253,247,252,253,255,0,240,40,2,0,135,20,249,229,245,249,255,0,232,39,2,0,119,34,236,204,236,230,255,0,0,39,2,0,117,74,216,153,216,201,255,0,176,34,2,0,113,120,194,102,194,164,255,0,208,33,2,0,105,159,174,65,174,118,255,0,152,32,2,0,98,190,139,35,139,69,255,0,136,31,2,0,102,255,88,0,88,36,255,0,88,30,2,0,134,6,253,247,252,253,255,0,72,29,2,0,135,20,249,229,245,249,255,0,96,28,2,0,119,34,236,204,236,230,255,0,40,27,2,0,117,74,216,153,216,201,255,0,72,26,2,0,113,120,194,102,194,164,255,0,96,25,2,0,105,159,174,65,174,118,255,0,40,24,2,0,98,190,139,35,139,69,255,0,40,23,2,0,102,255,109,0,109,44,255,0,24,22,2,0,101,255,68,0,68,27,255,0,192,20,2,0,144,20,244,224,236,244,255,0,128,19,2,0,148,70,218,158,188,218,255,0,136,18,2,0,196,123,167,136,86,167,255,0,208,17,2,0,136,14,251,237,248,251,255,0,16,17,2,0,146,53,227,179,205,227,255,0,64,16,2,0,162,74,198,140,150,198,255,0,80,15,2,0,202,149,157,136,65,157,255,0,128,14,2,0,136,14,251,237,248,251,255,0,192,13,2,0,146,53,227,179,205,227,255,0,176,12,2,0,162,74,198,140,150,198,255,0,144,11,2,0,196,123,167,136,86,167,255,0,40,10,2,0,214,225,129,129,15,124,255,0,240,9,2,0,136,14,251,237,248,251,255,0,240,8,2,0,148,43,230,191,211,230,255,0,176,7,2,0,148,70,218,158,188,218,255,0,192,6,2,0,162,74,198,140,150,198,255,0,248,5,2,0,196,123,167,136,86,167,255,0,96,5,2,0,214,225,129,129,15,124,255,0,192,4,2,0,136,14,251,237,248,251,255,0,48,4,2,0,148,43,230,191,211,230,255,0,104,3,2,0,148,70,218,158,188,218,255,0,152,2,2,0,162,74,198,140,150,198,255,0,152,1,2,0,190,100,177,140,107,177,255,0,248,0,2,0,202,149,157,136,65,157,255,0,80,0,2,0,213,252,110,110,1,107,255,0,176,255,1,0,134,6,253,247,252,253,255,0,40,255,1,0,144,20,244,224,236,244,255,0,96,254,1,0,148,43,230,191,211,230,255,0,184,253,1,0,148,70,218,158,188,218,255,0,32,253,1,0,162,74,198,140,150,198,255,0,40,252,1,0,190,100,177,140,107,177,255,0,128,251,1,0,202,149,157,136,65,157,255,0,224,250,1,0,213,252,110,110,1,107,255,0,48,250,1,0,134,6,253,247,252,253,255,0,48,249,1,0,144,20,244,224,236,244,255,0,128,248,1,0,148,43,230,191,211,230,255,0,216,247,1,0,148,70,218,158,188,218,255,0,40,247,1,0,162,74,198,140,150,198,255,0,88,246,1,0,190,100,177,140,107,177,255,0,168,245,1,0,202,149,157,136,65,157,255,0,120,244,1,0,214,225,129,129,15,124,255,0,48,243,1,0,213,255,77,77,0,75,255,0,248,241,1,0,114,211,158,27,158,119,255,0,192,240,1,0,18,252,217,217,95,2,255,0,168,239,1,0,173,95,179,117,112,179,255,0,200,238,1,0,114,211,158,27,158,119,255,0,216,237,1,0,18,252,217,217,95,2,255,0,64,237,1,0,173,95,179,117,112,179,255,0,72,236,1,0,233,209,231,231,41,138,255,0,96,235,1,0,114,211,158,27,158,119,255,0,24,234,1,0,18,252,217,217,95,2,255,0,232,232,1,0,173,95,179,117,112,179,255,0,240,231,1,0,233,209,231,231,41,138,255,0,64,231,1,0,62,208,166,102,166,30,255,0,88,230,1,0,114,211,158,27,158,119,255,0,176,229,1,0,18,252,217,217,95,2,255,0,56,229,1,0,173,95,179,117,112,179,255,0,176,228,1,0,233,209,231,231,41,138,255,0,224,227,1,0,62,208,166,102,166,30,255,0,72,227,1,0,31,252,230,230,171,2,255,0,48,226,1,0,114,211,158,27,158,119,255,0,48,225,1,0,18,252,217,217,95,2,255,0,80,224,1,0,173,95,179,117,112,179,255,0,136,223,1,0,233,209,231,231,41,138,255,0,248,222,1,0,62,208,166,102,166,30,255,0,56,222,1,0,31,252,230,230,171,2,255,0,128,221,1,0,27,210,166,166,118,29,255,0,0,221,1,0,114,211,158,27,158,119,255,0,104,220,1,0,18,252,217,217,95,2,255,0,64,220,1,0,173,95,179,117,112,179,255,0,240,219,1,0,233,209,231,231,41,138,255,0,160,219,1,0,62,208,166,102,166,30,255,0,72,219,1,0,31,252,230,230,171,2,255,0,24,219,1,0,27,210,166,166,118,29,255,0,248,218,1,0,0,0,102,102,102,102,255,0,192,218,1,0,76,25,243,224,243,219,255,0,160,218,1,0,95,61,221,168,221,181,255,0,120,218,1,0,140,170,202,67,162,202,255,0,88,218,1,0,65,17,249,240,249,232,255,0,48,218,1,0,87,46,228,186,228,188,255,0,200,217,1,0,123,101,204,123,204,196,255,0,64,217,1,0,141,197,190,43,140,190,255,0,232,216,1,0,65,17,249,240,249,232,255,0,176,216,1,0,87,46,228,186,228,188,255,0,144,216,1,0,123,101,204,123,204,196,255,0,48,216,1,0,140,170,202,67,162,202,255,0,248,215,1,0,145,243,172,8,104,172,255,0,184,215,1,0,65,17,249,240,249,232,255,0,128,215,1,0,77,41,235,204,235,197,255,0,80,215,1,0,95,61,221,168,221,181,255,0,8,215,1,0,123,101,204,123,204,196,255,0,144,214,1,0,140,170,202,67,162,202,255,0,56,214,1,0,145,243,172,8,104,172,255,0,208,213,1,0,65,17,249,240,249,232,255,0,160,213,1,0,77,41,235,204,235,197,255,0,104,213,1,0,95,61,221,168,221,181,255,0,64,213,1,0,123,101,204,123,204,196,255,0,24,213,1,0,137,160,211,78,179,211,255,0,224,212,1,0,141,197,190,43,140,190,255,0,152,212,1,0,147,242,158,8,88,158,255,0,80,212,1,0,60,12,252,247,252,240,255,0,248,211,1,0,76,25,243,224,243,219,255,0,176,211,1,0,77,41,235,204,235,197,255,0,104,211,1,0,95,61,221,168,221,181,255,0,72,211,1,0,123,101,204,123,204,196,255,0,16,211,1,0,137,160,211,78,179,211,255,0,240,210,1,0,141,197,190,43,140,190,255,0,200,210,1,0,147,242,158,8,88,158,255,0,160,210,1,0,60,12,252,247,252,240,255,0,136,210,1,0,76,25,243,224,243,219,255,0,64,210,1,0,77,41,235,204,235,197,255,0,224,209,1,0,95,61,221,168,221,181,255,0,152,209,1,0,123,101,204,123,204,196,255,0,80,209,1,0,137,160,211,78,179,211,255,0,24,209,1,0,141,197,190,43,140,190,255,0,232,208,1,0,145,243,172,8,104,172,255,0,208,208,1,0,150,239,129,8,64,129,255,0,176,208,1,0,74,21,245,229,245,224,255,0,136,208,1,0,80,72,217,161,217,155,255,0,112,208,1,0,98,178,163,49,163,84,255,0,24,208,1,0,73,15,248,237,248,233,255,0,224,207,1,0,78,54,228,186,228,179,255,0,136,207,1,0,86,104,196,116,196,118,255,0,112,207,1,0,98,190,139,35,139,69,255,0,72,207,1,0,73,15,248,237,248,233,255,0,24,207,1,0,78,54,228,186,228,179,255,0,0,207,1,0,86,104,196,116,196,118,255,0,224,206,1,0,98,178,163,49,163,84,255,0,200,206,1,0,102,255,109,0,109,44,255,0,176,206,1,0,73,15,248,237,248,233,255,0,232,205,1,0,77,44,233,199,233,192,255,0,152,205,1,0,80,72,217,161,217,155,255,0,56,205,1,0,86,104,196,116,196,118,255,0,32,205,1,0,98,178,163,49,163,84,255,0,0,205,1,0,102,255,109,0,109,44,255,0,160,204,1,0,73,15,248,237,248,233,255,0,136,204,1,0,77,44,233,199,233,192,255,0,104,204,1,0,80,72,217,161,217,155,255,0,80,204,1,0,86,104,196,116,196,118,255,0,64,204,1,0,96,158,171,65,171,93,255,0,216,203,1,0,98,190,139,35,139,69,255,0,88,203,1,0,108,255,90,0,90,50,255,0,16,203,1,0,72,7,252,247,252,245,255,0,240,202,1,0,74,21,245,229,245,224,255,0,152,202,1,0,77,44,233,199,233,192,255,0,88,202,1,0,80,72,217,161,217,155,255,0,24,202,1,0,86,104,196,116,196,118,255,0,248,201,1,0,96,158,171,65,171,93,255,0,184,201,1,0,98,190,139,35,139,69,255,0,152,201,1,0,108,255,90,0,90,50,255,0,64,201,1,0,72,7,252,247,252,245,255,0,240,200,1,0,74,21,245,229,245,224,255,0,144,200,1,0,77,44,233,199,233,192,255,0,64,200,1,0,80,72,217,161,217,155,255,0,24,200,1,0,86,104,196,116,196,118,255,0,248,199,1,0,96,158,171,65,171,93,255,0,216,199,1,0,98,190,139,35,139,69,255,0,184,199,1,0,102,255,109,0,109,44,255,0,128,199,1,0,101,255,68,0,68,27,255,0,96,199,1,0,0,0,240,240,240,240,255,0,240,198,1,0,0,0,189,189,189,189,255,0,200,198,1,0,0,0,99,99,99,99,255,0,120,198,1,0,0,0,247,247,247,247,255,0,96,198,1,0,0,0,204,204,204,204,255,0,56,198,1,0,0,0,150,150,150,150,255,0,24,198,1,0,0,0,82,82,82,82,255,0,240,197,1,0,0,0,247,247,247,247,255,0,208,197,1,0,0,0,204,204,204,204,255,0,160,197,1,0,0,0,150,150,150,150,255,0,136,197,1,0,0,0,99,99,99,99,255,0,248,196,1,0,0,0,37,37,37,37,255,0,200,196,1,0,0,0,247,247,247,247,255,0,136,196,1,0,0,0,217,217,217,217,255,0,104,196,1,0,0,0,189,189,189,189,255,0,48,196,1,0,0,0,150,150,150,150,255,0,16,196,1,0,0,0,99,99,99,99,255,0,248,195,1,0,0,0,37,37,37,37,255,0,216,195,1,0,0,0,247,247,247,247,255,0,176,195,1,0,0,0,217,217,217,217,255,0,160,195,1,0,0,0,189,189,189,189,255,0,88,195,1,0,0,0,150,150,150,150,255,0,24,195,1,0,0,0,115,115,115,115,255,0,192,194,1,0,0,0,82,82,82,82,255,0,160,194,1,0,0,0,37,37,37,37,255,0,88,194,1,0,0,0,255,255,255,255,255,0,48,194,1,0,0,0,240,240,240,240,255,0,8,194,1,0,0,0,217,217,217,217,255,0,232,193,1,0,0,0,189,189,189,189,255,0,136,193,1,0,0,0,150,150,150,150,255,0,120,193,1,0,0,0,115,115,115,115,255,0,72,193,1,0,0,0,82,82,82,82,255,0,240,192,1,0,0,0,37,37,37,37,255,0,160,192,1,0,0,0,255,255,255,255,255,0,128,192,1,0,0,0,240,240,240,240,255,0,48,192,1,0,0,0,217,217,217,217,255,0,248,191,1,0,0,0,189,189,189,189,255,0,216,191,1,0,0,0,150,150,150,150,255,0,152,191,1,0,0,0,115,115,115,115,255,0,120,191,1,0,0,0,82,82,82,82,255,0,88,191,1,0,0,0,37,37,37,37,255,0,64,191,1,0,0,0,0,0,0,0,255,0,224,190,1,0,21,48,254,254,230,206,255,0,80,190,1,0,19,147,253,253,174,107,255,0,8,190,1,0,14,240,230,230,85,13,255,0,216,189,1,0,19,32,254,254,237,222,255,0,176,189,1,0,20,120,253,253,190,133,255,0,144,189,1,0,17,194,253,253,141,60,255,0,112,189,1,0,13,253,217,217,71,1,255,0,48,189,1,0,19,32,254,254,237,222,255,0,32,189,1,0,20,120,253,253,190,133,255,0,8,189,1,0,17,194,253,253,141,60,255,0,208,188,1,0,14,240,230,230,85,13,255,0,72,188,1,0,13,250,166,166,54,3,255,0,48,188,1,0,19,32,254,254,237,222,255,0,0,188,1,0,21,91,253,253,208,162,255,0,216,187,1,0,19,147,253,253,174,107,255,0,184,187,1,0,17,194,253,253,141,60,255,0,152,187,1,0,14,240,230,230,85,13,255,0,104,187,1,0,13,250,166,166,54,3,255,0,88,187,1,0,19,32,254,254,237,222,255,0,64,187,1,0,21,91,253,253,208,162,255,0,16,187,1,0,19,147,253,253,174,107,255,0,152,186,1,0,17,194,253,253,141,60,255,0,128,186,1,0,16,234,241,241,105,19,255,0,80,186,1,0,13,253,217,217,72,1,255,0,40,186,1,0,12,247,140,140,45,4,255,0,8,186,1,0,21,20,255,255,245,235,255,0,232,185,1,0,21,48,254,254,230,206,255,0,184,185,1,0,21,91,253,253,208,162,255,0,160,185,1,0,19,147,253,253,174,107,255,0,72,185,1,0,17,194,253,253,141,60,255,0,248,184,1,0,16,234,241,241,105,19,255,0,64,184,1,0,13,253,217,217,72,1,255,0,48,184,1,0,12,247,140,140,45,4,255,0,16,184,1,0,21,20,255,255,245,235,255,0,248,183,1,0,21,48,254,254,230,206,255,0,160,183,1,0,21,91,253,253,208,162,255,0,128,183,1,0,19,147,253,253,174,107,255,0,88,183,1,0,17,194,253,253,141,60,255,0,72,183,1,0,16,234,241,241,105,19,255,0,40,183,1,0,13,253,217,217,72,1,255,0,0,183,1,0,13,250,166,166,54,3,255,0,120,182,1,0,12,246,127,127,39,4,255,0,104,182,1,0,25,54,254,254,232,200,255,0,48,182,1,0,19,121,253,253,187,132,255,0,8,182,1,0,5,197,227,227,74,51,255,0,152,181,1,0,26,37,254,254,240,217,255,0,120,181,1,0,24,115,253,253,204,138,255,0,72,181,1,0,13,164,252,252,141,89,255,0,40,181,1,0,3,218,215,215,48,31,255,0,16,181,1,0,26,37,254,254,240,217,255,0,232,180,1,0,24,115,253,253,204,138,255,0,80,180,1,0,13,164,252,252,141,89,255,0,56,180,1,0,5,197,227,227,74,51,255,0,248,179,1,0,0,255,179,179,0,0,255,0,216,179,1,0,26,37,254,254,240,217,255,0,192,179,1,0,24,95,253,253,212,158,255,0,160,179,1,0,19,121,253,253,187,132,255,0,120,179,1,0,13,164,252,252,141,89,255,0,104,179,1,0,5,197,227,227,74,51,255,0,56,179,1,0,0,255,179,179,0,0,255,0,24,179,1,0,26,37,254,254,240,217,255,0,136,178,1,0,24,95,253,253,212,158,255,0,120,178,1,0,19,121,253,253,187,132,255,0,72,178,1,0,13,164,252,252,141,89,255,0,48,178,1,0,7,178,239,239,101,72,255,0,16,178,1,0,3,218,215,215,48,31,255,0,240,177,1,0,0,255,153,153,0,0,255,0,200,177,1,0,24,18,255,255,247,236,255,0,184,177,1,0,25,54,254,254,232,200,255,0,136,177,1,0,24,95,253,253,212,158,255,0,104,177,1,0,19,121,253,253,187,132,255,0,248,176,1,0,13,164,252,252,141,89,255,0,232,176,1,0,7,178,239,239,101,72,255,0,192,176,1,0,3,218,215,215,48,31,255,0,168,176,1,0,0,255,153,153,0,0,255,0,144,176,1,0,24,18,255,255,247,236,255,0,112,176,1,0,25,54,254,254,232,200,255,0,72,176,1,0,24,95,253,253,212,158,255,0,56,176,1,0,19,121,253,253,187,132,255,0,32,176,1,0,13,164,252,252,141,89,255,0,232,175,1,0,7,178,239,239,101,72,255,0,176,175,1,0,3,218,215,215,48,31,255,0,152,175,1,0,0,255,179,179,0,0,255,0,104,175,1,0,0,255,127,127,0,0,255,0,80,175,1,0,142,68,227,166,206,227,255,0,16,175,1,0,190,153,154,106,61,154,255,0,240,174,1,0,144,211,180,31,120,180,255,0,160,174,1,0,65,97,223,178,223,138,255,0,144,174,1,0,82,184,160,51,160,44,255,0,112,174,1,0,0,99,251,251,154,153,255,0,40,174,1,0,254,225,227,227,26,28,255,0,232,173,1,0,23,143,253,253,191,111,255,0,216,173,1,0,21,255,255,255,127,0,255,0,184,173,1,0,198,42,214,202,178,214,255,0,152,173,1,0,142,68,227,166,206,227,255,0,72,173,1,0,190,153,154,106,61,154,255,0,40,173,1,0,42,102,255,255,255,153,255,0,8,173,1,0,144,211,180,31,120,180,255,0,248,172,1,0,65,97,223,178,223,138,255,0,208,172,1,0,82,184,160,51,160,44,255,0,160,172,1,0,0,99,251,251,154,153,255,0,96,172,1,0,254,225,227,227,26,28,255,0,80,172,1,0,23,143,253,253,191,111,255,0,24,172,1,0,21,255,255,255,127,0,255,0,0,172,1,0,198,42,214,202,178,214,255,0,232,171,1,0,142,68,227,166,206,227,255,0,200,171,1,0,190,153,154,106,61,154,255,0,168,171,1,0,42,102,255,255,255,153,255,0,152,171,1,0,15,197,177,177,89,40,255,0,128,171,1,0,144,211,180,31,120,180,255,0,88,171,1,0,65,97,223,178,223,138,255,0,32,171,1,0,82,184,160,51,160,44,255,0,16,171,1,0,0,99,251,251,154,153,255,0,232,170,1,0,254,225,227,227,26,28,255,0,208,170,1,0,23,143,253,253,191,111,255,0,128,170,1,0,21,255,255,255,127,0,255,0,96,170,1,0,198,42,214,202,178,214,255,0,64,170,1,0,142,68,227,166,206,227,255,0,48,170,1,0,144,211,180,31,120,180,255,0,24,170,1,0,65,97,223,178,223,138,255,0,248,169,1,0,142,68,227,166,206,227,255,0,184,169,1,0,144,211,180,31,120,180,255,0,168,169,1,0,65,97,223,178,223,138,255,0,136,169,1,0,82,184,160,51,160,44,255,0,24,169,1,0,142,68,227,166,206,227,255,0,232,168,1,0,144,211,180,31,120,180,255,0,200,168,1,0,65,97,223,178,223,138,255,0,168,168,1,0,82,184,160,51,160,44,255,0,144,168,1,0,0,99,251,251,154,153,255,0,184,167,1,0,142,68,227,166,206,227,255,0,64,167,1,0,144,211,180,31,120,180,255,0,224,166,1,0,65,97,223,178,223,138,255,0,208,166,1,0,82,184,160,51,160,44,255,0,168,166,1,0,0,99,251,251,154,153,255,0,144,166,1,0,254,225,227,227,26,28,255,0,120,166,1,0,142,68,227,166,206,227,255,0,80,166,1,0,144,211,180,31,120,180,255,0,56,166,1,0,65,97,223,178,223,138,255,0,40,166,1,0,82,184,160,51,160,44,255,0,16,166,1,0,0,99,251,251,154,153,255,0,216,165,1,0,254,225,227,227,26,28,255,0,152,165,1,0,23,143,253,253,191,111,255,0,72,165,1,0,142,68,227,166,206,227,255,0,24,165,1,0,144,211,180,31,120,180,255,0,232,164,1,0,65,97,223,178,223,138,255,0,168,164,1,0,82,184,160,51,160,44,255,0,120,164,1,0,0,99,251,251,154,153,255,0,80,164,1,0,254,225,227,227,26,28,255,0,40,164,1,0,23,143,253,253,191,111,255,0,16,164,1,0,21,255,255,255,127,0,255,0,232,163,1,0,142,68,227,166,206,227,255,0,128,163,1,0,144,211,180,31,120,180,255,0,88,163,1,0,65,97,223,178,223,138,255,0,56,163,1,0,82,184,160,51,160,44,255,0,24,163,1,0,0,99,251,251,154,153,255,0,248,162,1,0,254,225,227,227,26,28,255,0,216,162,1,0,23,143,253,253,191,111,255,0,192,162,1,0,21,255,255,255,127,0,255,0,176,162,1,0,198,42,214,202,178,214,255,0,152,162,1,0,3,78,251,251,180,174,255,0,88,162,1,0,146,53,227,179,205,227,255,0,16,162,1,0,77,41,235,204,235,197,255,0,0,162,1,0,3,78,251,251,180,174,255,0,224,161,1,0,146,53,227,179,205,227,255,0,200,161,1,0,77,41,235,204,235,197,255,0,168,161,1,0,202,27,228,222,203,228,255,0,136,161,1,0,3,78,251,251,180,174,255,0,112,161,1,0,146,53,227,179,205,227,255,0,96,161,1,0,77,41,235,204,235,197,255,0,72,161,1,0,202,27,228,222,203,228,255,0,8,161,1,0,24,88,254,254,217,166,255,0,168,160,1,0,3,78,251,251,180,174,255,0,152,160,1,0,146,53,227,179,205,227,255,0,96,160,1,0,77,41,235,204,235,197,255,0,64,160,1,0,202,27,228,222,203,228,255,0,40,160,1,0,24,88,254,254,217,166,255,0,8,160,1,0,42,50,255,255,255,204,255,0,240,159,1,0,3,78,251,251,180,174,255,0,224,159,1,0,146,53,227,179,205,227,255,0,176,159,1,0,77,41,235,204,235,197,255,0,120,159,1,0,202,27,228,222,203,228,255,0,64,159,1,0,24,88,254,254,217,166,255,0,48,159,1,0,42,50,255,255,255,204,255,0,16,159,1,0,28,44,229,229,216,189,255,0,248,158,1,0,3,78,251,251,180,174,255,0,192,158,1,0,146,53,227,179,205,227,255,0,160,158,1,0,77,41,235,204,235,197,255,0,88,158,1,0,202,27,228,222,203,228,255,0,72,158,1,0,24,88,254,254,217,166,255,0,40,158,1,0,42,50,255,255,255,204,255,0,0,158,1,0,28,44,229,229,216,189,255,0,208,157,1,0,233,35,253,253,218,236,255,0,192,157,1,0,3,78,251,251,180,174,255,0,144,157,1,0,146,53,227,179,205,227,255,0,120,157,1,0,77,41,235,204,235,197,255,0,96,157,1,0,202,27,228,222,203,228,255,0,48,157,1,0,24,88,254,254,217,166,255,0,16,157,1,0,42,50,255,255,255,204,255,0,240,156,1,0,28,44,229,229,216,189,255,0,200,156,1,0,233,35,253,253,218,236,255,0,160,156,1,0,0,0,242,242,242,242,255,0,128,156,1,0,108,53,226,179,226,205,255,0,80,156,1,0,17,81,253,253,205,172,255,0,40,156,1,0,155,31,232,203,213,232,255,0,232,155,1,0,108,53,226,179,226,205,255,0,208,155,1,0,17,81,253,253,205,172,255,0,176,155,1,0,155,31,232,203,213,232,255,0,144,155,1,0,228,43,244,244,202,228,255,0,128,155,1,0,108,53,226,179,226,205,255,0,104,155,1,0,17,81,253,253,205,172,255,0,56,155,1,0,155,31,232,203,213,232,255,0,16,155,1,0,228,43,244,244,202,228,255,0,240,154,1,0,56,45,245,230,245,201,255,0,208,154,1,0,108,53,226,179,226,205,255,0,176,154,1,0,17,81,253,253,205,172,255,0,152,154,1,0,155,31,232,203,213,232,255,0,120,154,1,0,228,43,244,244,202,228,255,0,80,154,1,0,56,45,245,230,245,201,255,0,64,154,1,0,35,81,255,255,242,174,255,0,40,154,1,0,108,53,226,179,226,205,255,0,232,153,1,0,17,81,253,253,205,172,255,0,200,153,1,0,155,31,232,203,213,232,255,0,176,153,1,0,228,43,244,244,202,228,255,0,112,153,1,0,56,45,245,230,245,201,255,0,64,153,1,0,35,81,255,255,242,174,255,0,40,153,1,0,25,39,241,241,226,204,255,0,8,153,1,0,108,53,226,179,226,205,255,0,184,152,1,0,17,81,253,253,205,172,255,0,152,152,1,0,155,31,232,203,213,232,255,0,88,152,1,0,228,43,244,244,202,228,255,0,248,151,1,0,56,45,245,230,245,201,255,0,192,151,1,0,35,81,255,255,242,174,255,0,160,151,1,0,25,39,241,241,226,204,255,0,96,151,1,0,0,0,204,204,204,204,255,0,64,151,1,0,230,253,142,142,1,82,255,0,32,151,1,0,77,191,100,39,100,25,255,0,240,150,1,0,230,220,197,197,27,125,255,0,208,150,1,0,232,118,222,222,119,174,255,0,192,150,1,0])
+.concat([229,62,241,241,182,218,255,0,168,150,1,0,233,29,253,253,224,239,255,0,128,150,1,0,59,38,245,230,245,208,255,0,88,150,1,0,61,103,225,184,225,134,255,0,56,150,1,0,63,166,188,127,188,65,255,0,176,149,1,0,68,197,146,77,146,33,255,0,128,149,1,0,230,253,142,142,1,82,255,0,72,149,1,0,68,197,146,77,146,33,255,0,40,149,1,0,77,191,100,39,100,25,255,0,240,148,1,0,230,220,197,197,27,125,255,0,200,148,1,0,232,118,222,222,119,174,255,0,176,148,1,0,229,62,241,241,182,218,255,0,144,148,1,0,233,29,253,253,224,239,255,0,96,148,1,0,0,0,247,247,247,247,255,0,56,148,1,0,59,38,245,230,245,208,255,0,248,147,1,0,61,103,225,184,225,134,255,0,224,147,1,0,63,166,188,127,188,65,255,0,192,147,1,0,231,76,233,233,163,201,255,0,160,147,1,0,0,0,247,247,247,247,255,0,128,147,1,0,63,129,215,161,215,106,255,0,112,147,1,0,228,220,208,208,28,139,255,0,88,147,1,0,229,62,241,241,182,218,255,0,48,147,1,0,61,103,225,184,225,134,255,0,192,146,1,0,72,198,172,77,172,38,255,0,176,146,1,0,228,220,208,208,28,139,255,0,136,146,1,0,229,62,241,241,182,218,255,0,112,146,1,0,0,0,247,247,247,247,255,0,80,146,1,0,61,103,225,184,225,134,255,0,48,146,1,0,72,198,172,77,172,38,255,0,8,146,1,0,230,220,197,197,27,125,255,0,248,145,1,0,231,76,233,233,163,201,255,0,224,145,1,0,233,29,253,253,224,239,255,0,184,145,1,0,59,38,245,230,245,208,255,0,136,145,1,0,63,129,215,161,215,106,255,0,120,145,1,0,68,197,146,77,146,33,255,0,56,145,1,0,230,220,197,197,27,125,255,0,24,145,1,0,231,76,233,233,163,201,255,0,0,145,1,0,233,29,253,253,224,239,255,0,224,144,1,0,0,0,247,247,247,247,255,0,200,144,1,0,59,38,245,230,245,208,255,0,184,144,1,0,63,129,215,161,215,106,255,0,160,144,1,0,68,197,146,77,146,33,255,0,96,144,1,0,230,220,197,197,27,125,255,0,72,144,1,0,232,118,222,222,119,174,255,0,56,144,1,0,229,62,241,241,182,218,255,0,208,143,1,0,233,29,253,253,224,239,255,0,160,143,1,0,59,38,245,230,245,208,255,0,128,143,1,0,61,103,225,184,225,134,255,0,96,143,1,0,63,166,188,127,188,65,255,0,72,143,1,0,68,197,146,77,146,33,255,0,8,143,1,0,230,220,197,197,27,125,255,0,208,142,1,0,232,118,222,222,119,174,255,0,160,142,1,0,229,62,241,241,182,218,255,0,128,142,1,0,233,29,253,253,224,239,255,0,112,142,1,0,0,0,247,247,247,247,255,0,248,141,1,0,59,38,245,230,245,208,255,0,200,141,1,0,61,103,225,184,225,134,255,0,176,141,1,0,63,166,188,127,188,65,255,0,144,141,1,0,68,197,146,77,146,33,255,0,104,141,1,0,206,255,75,64,0,75,255,0,88,141,1,0,101,255,68,0,68,27,255,0,48,141,1,0,206,173,131,118,42,131,255,0,0,141,1,0,199,87,171,153,112,171,255,0,224,140,1,0,199,51,207,194,165,207,255,0,208,140,1,0,210,21,232,231,212,232,255,0,128,140,1,0,76,30,240,217,240,211,255,0,80,140,1,0,80,68,219,166,219,160,255,0,48,140,1,0,88,123,174,90,174,97,255,0,56,139,1,0,97,197,120,27,120,55,255,0,32,139,1,0,206,255,75,64,0,75,255,0,16,139,1,0,97,197,120,27,120,55,255,0,248,138,1,0,101,255,68,0,68,27,255,0,208,138,1,0,206,173,131,118,42,131,255,0,144,138,1,0,199,87,171,153,112,171,255,0,128,138,1,0,199,51,207,194,165,207,255,0,72,138,1,0,210,21,232,231,212,232,255,0,24,138,1,0,0,0,247,247,247,247,255,0,0,138,1,0,76,30,240,217,240,211,255,0,224,137,1,0,80,68,219,166,219,160,255,0,192,137,1,0,88,123,174,90,174,97,255,0,176,137,1,0,196,70,195,175,141,195,255,0,152,137,1,0,0,0,247,247,247,247,255,0,104,137,1,0,82,90,191,127,191,123,255,0,40,137,1,0,201,168,148,123,50,148,255,0,24,137,1,0,199,51,207,194,165,207,255,0,224,136,1,0,80,68,219,166,219,160,255,0,200,136,1,0,102,255,136,0,136,55,255,0,160,136,1,0,201,168,148,123,50,148,255,0,112,136,1,0,199,51,207,194,165,207,255,0,80,136,1,0,0,0,247,247,247,247,255,0,56,136,1,0,80,68,219,166,219,160,255,0,232,135,1,0,102,255,136,0,136,55,255,0,88,135,1,0,206,173,131,118,42,131,255,0,56,135,1,0,196,70,195,175,141,195,255,0,40,135,1,0,210,21,232,231,212,232,255,0,0,135,1,0,76,30,240,217,240,211,255,0,200,134,1,0,82,90,191,127,191,123,255,0,176,134,1,0,97,197,120,27,120,55,255,0,144,134,1,0,206,173,131,118,42,131,255,0,112,134,1,0,196,70,195,175,141,195,255,0,96,134,1,0,210,21,232,231,212,232,255,0,72,134,1,0,0,0,247,247,247,247,255,0,8,134,1,0,76,30,240,217,240,211,255,0,232,133,1,0,82,90,191,127,191,123,255,0,216,133,1,0,97,197,120,27,120,55,255,0,96,133,1,0,206,173,131,118,42,131,255,0,40,133,1,0,199,87,171,153,112,171,255,0,240,132,1,0,199,51,207,194,165,207,255,0,208,132,1,0,210,21,232,231,212,232,255,0,168,132,1,0,76,30,240,217,240,211,255,0,128,132,1,0,80,68,219,166,219,160,255,0,104,132,1,0,88,123,174,90,174,97,255,0,64,132,1,0,97,197,120,27,120,55,255,0,0,132,1,0,206,173,131,118,42,131,255,0,216,131,1,0,199,87,171,153,112,171,255,0,176,131,1,0,199,51,207,194,165,207,255,0,144,131,1,0,210,21,232,231,212,232,255,0,120,131,1,0,0,0,247,247,247,247,255,0,80,131,1,0,76,30,240,217,240,211,255,0,56,131,1,0,80,68,219,166,219,160,255,0,40,131,1,0,88,123,174,90,174,97,255,0,16,131,1,0,97,197,120,27,120,55,255,0,224,130,1,0,189,11,242,236,231,242,255,0,184,130,1,0,151,61,219,166,189,219,255,0,152,130,1,0,141,197,190,43,140,190,255,0,112,130,1,0,185,8,246,241,238,246,255,0,240,129,1,0,155,40,225,189,201,225,255,0,168,129,1,0,145,112,207,116,169,207,255,0,136,129,1,0,143,247,176,5,112,176,255,0,112,129,1,0,185,8,246,241,238,246,255,0,96,129,1,0,155,40,225,189,201,225,255,0,72,129,1,0,145,112,207,116,169,207,255,0,16,129,1,0,141,197,190,43,140,190,255,0,232,128,1,0,143,247,141,4,90,141,255,0,192,128,1,0,185,8,246,241,238,246,255,0,160,128,1,0,168,24,230,208,209,230,255,0,104,128,1,0,151,61,219,166,189,219,255,0,40,128,1,0,145,112,207,116,169,207,255,0,8,128,1,0,141,197,190,43,140,190,255,0,232,127,1,0,143,247,141,4,90,141,255,0,216,127,1,0,185,8,246,241,238,246,255,0,192,127,1,0,168,24,230,208,209,230,255,0,112,127,1,0,151,61,219,166,189,219,255,0,80,127,1,0,145,112,207,116,169,207,255,0,64,127,1,0,142,183,192,54,144,192,255,0,24,127,1,0,143,247,176,5,112,176,255,0,224,126,1,0,143,248,123,3,78,123,255,0,200,126,1,0,233,8,255,255,247,251,255,0,168,126,1,0,189,11,242,236,231,242,255,0,144,126,1,0,168,24,230,208,209,230,255,0,80,126,1,0,151,61,219,166,189,219,255,0,48,126,1,0,145,112,207,116,169,207,255,0,0,126,1,0,142,183,192,54,144,192,255,0,168,125,1,0,143,247,176,5,112,176,255,0,152,125,1,0,143,248,123,3,78,123,255,0,120,125,1,0,233,8,255,255,247,251,255,0,16,125,1,0,189,11,242,236,231,242,255,0,208,124,1,0,168,24,230,208,209,230,255,0,176,124,1,0,151,61,219,166,189,219,255,0,152,124,1,0,145,112,207,116,169,207,255,0,136,124,1,0,142,183,192,54,144,192,255,0,96,124,1,0,143,247,176,5,112,176,255,0,24,124,1,0,143,247,141,4,90,141,255,0,0,124,1,0,143,249,88,2,56,88,255,0,240,123,1,0,200,14,240,236,226,240,255,0,216,123,1,0,151,61,219,166,189,219,255,0,160,123,1,0,130,208,153,28,144,153,255,0,128,123,1,0,207,8,247,246,239,247,255,0,88,123,1,0,155,40,225,189,201,225,255,0,40,123,1,0,143,128,207,103,169,207,255,0,24,123,1,0,130,251,138,2,129,138,255,0,0,123,1,0,207,8,247,246,239,247,255,0,216,122,1,0,155,40,225,189,201,225,255,0,184,122,1,0,143,128,207,103,169,207,255,0,168,122,1,0,130,208,153,28,144,153,255,0,144,122,1,0,119,252,108,1,108,89,255,0,8,122,1,0,207,8,247,246,239,247,255,0,184,121,1,0,168,24,230,208,209,230,255,0,152,121,1,0,151,61,219,166,189,219,255,0,80,121,1,0,143,128,207,103,169,207,255,0,64,121,1,0,130,208,153,28,144,153,255,0,40,121,1,0,119,252,108,1,108,89,255,0,0,121,1,0,207,8,247,246,239,247,255,0,192,120,1,0,168,24,230,208,209,230,255,0,176,120,1,0,151,61,219,166,189,219,255,0,112,120,1,0,143,128,207,103,169,207,255,0,88,120,1,0,142,183,192,54,144,192,255,0,72,120,1,0,130,251,138,2,129,138,255,0,40,120,1,0,118,252,100,1,100,80,255,0,232,119,1,0,233,8,255,255,247,251,255,0,200,119,1,0,200,14,240,236,226,240,255,0,176,119,1,0,168,24,230,208,209,230,255,0,32,119,1,0,151,61,219,166,189,219,255,0,248,118,1,0,143,128,207,103,169,207,255,0,232,118,1,0,142,183,192,54,144,192,255,0,200,118,1,0,130,251,138,2,129,138,255,0,168,118,1,0,118,252,100,1,100,80,255,0,152,118,1,0,233,8,255,255,247,251,255,0,120,118,1,0,200,14,240,236,226,240,255,0,96,118,1,0,168,24,230,208,209,230,255,0,80,118,1,0,151,61,219,166,189,219,255,0,56,118,1,0,143,128,207,103,169,207,255,0,8,118,1,0,142,183,192,54,144,192,255,0,232,117,1,0,130,251,138,2,129,138,255,0,216,117,1,0,119,252,108,1,108,89,255,0,176,117,1,0,117,251,70,1,70,54,255,0,152,117,1,0,18,238,127,127,59,8,255,0,72,117,1,0,195,255,75,45,0,75,255,0,40,117,1,0,20,246,179,179,88,6,255,0,224,116,1,0,22,232,224,224,130,20,255,0,192,116,1,0,23,155,253,253,184,99,255,0,160,116,1,0,24,72,254,254,224,182,255,0,120,116,1,0,165,20,235,216,218,235,255,0,72,116,1,0,177,47,210,178,171,210,255,0,56,116,1,0,179,84,172,128,115,172,255,0,16,116,1,0,189,181,136,84,39,136,255,0,0,116,1,0,18,238,127,127,59,8,255,0,232,115,1,0,189,181,136,84,39,136,255,0,200,115,1,0,195,255,75,45,0,75,255,0,128,115,1,0,20,246,179,179,88,6,255,0,112,115,1,0,22,232,224,224,130,20,255,0,88,115,1,0,23,155,253,253,184,99,255,0,48,115,1,0,24,72,254,254,224,182,255,0,0,115,1,0,0,0,247,247,247,247,255,0,240,114,1,0,165,20,235,216,218,235,255,0,192,114,1,0,177,47,210,178,171,210,255,0,176,114,1,0,179,84,172,128,115,172,255,0,160,114,1,0,23,187,241,241,163,64,255,0,120,114,1,0,0,0,247,247,247,247,255,0,96,114,1,0,178,69,195,153,142,195,255,0,80,114,1,0,17,253,230,230,97,1,255,0,56,114,1,0,23,155,253,253,184,99,255,0,32,114,1,0,177,47,210,178,171,210,255,0,224,113,1,0,185,155,153,94,60,153,255,0,208,113,1,0,17,253,230,230,97,1,255,0,160,113,1,0,23,155,253,253,184,99,255,0,144,113,1,0,0,0,247,247,247,247,255,0,128,113,1,0,177,47,210,178,171,210,255,0,96,113,1,0,185,155,153,94,60,153,255,0,64,113,1,0,20,246,179,179,88,6,255,0,48,113,1,0,23,187,241,241,163,64,255,0,24,113,1,0,24,72,254,254,224,182,255,0,224,112,1,0,165,20,235,216,218,235,255,0,176,112,1,0,178,69,195,153,142,195,255,0,160,112,1,0,189,181,136,84,39,136,255,0,80,112,1,0,20,246,179,179,88,6,255,0,64,112,1,0,23,187,241,241,163,64,255,0,48,112,1,0,24,72,254,254,224,182,255,0,16,112,1,0,0,0,247,247,247,247,255,0,240,111,1,0,165,20,235,216,218,235,255,0,184,111,1,0,178,69,195,153,142,195,255,0,160,111,1,0,189,181,136,84,39,136,255,0,120,111,1,0,20,246,179,179,88,6,255,0,80,111,1,0,22,232,224,224,130,20,255,0,64,111,1,0,23,155,253,253,184,99,255,0,0,111,1,0,24,72,254,254,224,182,255,0,240,110,1,0,165,20,235,216,218,235,255,0,224,110,1,0,177,47,210,178,171,210,255,0,192,110,1,0,179,84,172,128,115,172,255,0,160,110,1,0,189,181,136,84,39,136,255,0,144,110,1,0,20,246,179,179,88,6,255,0,112,110,1,0,22,232,224,224,130,20,255,0,72,110,1,0,23,155,253,253,184,99,255,0,240,109,1,0,24,72,254,254,224,182,255,0,224,109,1,0,0,0,247,247,247,247,255,0,152,109,1,0,165,20,235,216,218,235,255,0,136,109,1,0,177,47,210,178,171,210,255,0,120,109,1,0,179,84,172,128,115,172,255,0,88,109,1,0,189,181,136,84,39,136,255,0,32,109,1,0,188,14,239,231,225,239,255,0,16,109,1,0,214,67,201,201,148,199,255,0,0,109,1,0,234,222,221,221,28,119,255,0,216,108,1,0,185,8,246,241,238,246,255,0,160,108,1,0,211,41,216,215,181,216,255,0,144,108,1,0,228,139,223,223,101,176,255,0,72,108,1,0,239,232,206,206,18,86,255,0,56,108,1,0,185,8,246,241,238,246,255,0,40,108,1,0,211,41,216,215,181,216,255,0,8,108,1,0,228,139,223,223,101,176,255,0,224,107,1,0,234,222,221,221,28,119,255,0,208,107,1,0,236,255,152,152,0,67,255,0,192,107,1,0,185,8,246,241,238,246,255,0,152,107,1,0,204,38,218,212,185,218,255,0,104,107,1,0,214,67,201,201,148,199,255,0,88,107,1,0,228,139,223,223,101,176,255,0,224,106,1,0,234,222,221,221,28,119,255,0,208,106,1,0,236,255,152,152,0,67,255,0,192,106,1,0,185,8,246,241,238,246,255,0,160,106,1,0,204,38,218,212,185,218,255,0,136,106,1,0,214,67,201,201,148,199,255,0,112,106,1,0,228,139,223,223,101,176,255,0,96,106,1,0,233,209,231,231,41,138,255,0,8,106,1,0,239,232,206,206,18,86,255,0,208,105,1,0,236,255,145,145,0,63,255,0,184,105,1,0,195,5,249,247,244,249,255,0,112,105,1,0,188,14,239,231,225,239,255,0,96,105,1,0,204,38,218,212,185,218,255,0,80,105,1,0,214,67,201,201,148,199,255,0,48,105,1,0,228,139,223,223,101,176,255,0,24,105,1,0,233,209,231,231,41,138,255,0,8,105,1,0,239,232,206,206,18,86,255,0,248,104,1,0,236,255,145,145,0,63,255,0,200,104,1,0,195,5,249,247,244,249,255,0,152,104,1,0,188,14,239,231,225,239,255,0,136,104,1,0,204,38,218,212,185,218,255,0,40,104,1,0,214,67,201,201,148,199,255,0,16,104,1,0,228,139,223,223,101,176,255,0,224,103,1,0,233,209,231,231,41,138,255,0,128,103,1,0,239,232,206,206,18,86,255,0,48,103,1,0,236,255,152,152,0,67,255,0,16,103,1,0,242,255,103,103,0,31,255,0,248,102,1,0,180,8,245,239,237,245,255,0,208,102,1,0,168,37,220,188,189,220,255,0,128,102,1,0,176,100,177,117,107,177,255,0,112,102,1,0,182,7,247,242,240,247,255,0,56,102,1,0,173,28,226,203,201,226,255,0,40,102,1,0,173,58,200,158,154,200,255,0,24,102,1,0,182,128,163,106,81,163,255,0,240,101,1,0,182,7,247,242,240,247,255,0,208,101,1,0,173,28,226,203,201,226,255,0,184,101,1,0,173,58,200,158,154,200,255,0,168,101,1,0,176,100,177,117,107,177,255,0,128,101,1,0,188,185,143,84,39,143,255,0,80,101,1,0,182,7,247,242,240,247,255,0,64,101,1,0,170,18,235,218,218,235,255,0,40,101,1,0,168,37,220,188,189,220,255,0,8,101,1,0,173,58,200,158,154,200,255,0,248,100,1,0,176,100,177,117,107,177,255,0,224,100,1,0,188,185,143,84,39,143,255,0,176,100,1,0,182,7,247,242,240,247,255,0,160,100,1,0,170,18,235,218,218,235,255,0,144,100,1,0,168,37,220,188,189,220,255,0,88,100,1,0,173,58,200,158,154,200,255,0,24,100,1,0,172,83,186,128,125,186,255,0,8,100,1,0,182,128,163,106,81,163,255,0,176,99,1,0,190,216,134,74,20,134,255,0,160,99,1,0,191,2,253,252,251,253,255,0,144,99,1,0,180,8,245,239,237,245,255,0,128,99,1,0,170,18,235,218,218,235,255,0,80,99,1,0,168,37,220,188,189,220,255,0,64,99,1,0,173,58,200,158,154,200,255,0,48,99,1,0,172,83,186,128,125,186,255,0,240,98,1,0,182,128,163,106,81,163,255,0,192,98,1,0,190,216,134,74,20,134,255,0,176,98,1,0,191,2,253,252,251,253,255,0,152,98,1,0,180,8,245,239,237,245,255,0,136,98,1,0,170,18,235,218,218,235,255,0,120,98,1,0,168,37,220,188,189,220,255,0,104,98,1,0,173,58,200,158,154,200,255,0,64,98,1,0,172,83,186,128,125,186,255,0,32,98,1,0,182,128,163,106,81,163,255,0,240,97,1,0,188,185,143,84,39,143,255,0,200,97,1,0,191,255,125,63,0,125,255,0,144,97,1,0,242,255,103,103,0,31,255,0,128,97,1,0,150,241,97,5,48,97,255,0,96,97,1,0,249,220,178,178,24,43,255,0,80,97,1,0,5,163,214,214,96,77,255,0,64,97,1,0,13,119,244,244,165,130,255,0,48,97,1,0,15,54,253,253,219,199,255,0,0,97,1,0,142,32,240,209,229,240,255,0,240,96,1,0,141,87,222,146,197,222,255,0,208,96,1,0,143,167,195,67,147,195,255,0,160,96,1,0,148,206,172,33,102,172,255,0,112,96,1,0,242,255,103,103,0,31,255,0,88,96,1,0,148,206,172,33,102,172,255,0,48,96,1,0,150,241,97,5,48,97,255,0,32,96,1,0,249,220,178,178,24,43,255,0,16,96,1,0,5,163,214,214,96,77,255,0,0,96,1,0,13,119,244,244,165,130,255,0,208,95,1,0,15,54,253,253,219,199,255,0,144,95,1,0,0,0,247,247,247,247,255,0,128,95,1,0,142,32,240,209,229,240,255,0,88,95,1,0,141,87,222,146,197,222,255,0,24,95,1,0,143,167,195,67,147,195,255,0,8,95,1,0,12,150,239,239,138,98,255,0,208,94,1,0,0,0,247,247,247,247,255,0,192,94,1,0,143,128,207,103,169,207,255,0,176,94,1,0,248,255,202,202,0,32,255,0,160,94,1,0,13,119,244,244,165,130,255,0,144,125,2,0,141,87,222,146,197,222,255,0,128,125,2,0,143,247,176,5,113,176,255,0,112,125,2,0,248,255,202,202,0,32,255,0,72,125,2,0,13,119,244,244,165,130,255,0,16,125,2,0,0,0,247,247,247,247,255,0,0,125,2,0,141,87,222,146,197,222,255,0,208,124,2,0,143,247,176,5,113,176,255,0,192,124,2,0,249,220,178,178,24,43,255,0,176,124,2,0,12,150,239,239,138,98,255,0,160,124,2,0,15,54,253,253,219,199,255,0,112,124,2,0,142,32,240,209,229,240,255,0,80,124,2,0,143,128,207,103,169,207,255,0,64,124,2,0,148,206,172,33,102,172,255,0,240,123,2,0,249,220,178,178,24,43,255,0,184,123,2,0,12,150,239,239,138,98,255,0,160,123,2,0,15,54,253,253,219,199,255,0,136,123,2,0,0,0,247,247,247,247,255,0,120,123,2,0,142,32,240,209,229,240,255,0,104,123,2,0,143,128,207,103,169,207,255,0,88,123,2,0,148,206,172,33,102,172,255,0,48,123,2,0,249,220,178,178,24,43,255,0,32,123,2,0,5,163,214,214,96,77,255,0,16,123,2,0,13,119,244,244,165,130,255,0,224,122,2,0,15,54,253,253,219,199,255,0,144,122,2,0,142,32,240,209,229,240,255,0,128,122,2,0,141,87,222,146,197,222,255,0,32,122,2,0,143,167,195,67,147,195,255,0,8,122,2,0,148,206,172,33,102,172,255,0,216,121,2,0,249,220,178,178,24,43,255,0,200,121,2,0,5,163,214,214,96,77,255,0,88,121,2,0,13,119,244,244,165,130,255,0,56,121,2,0,15,54,253,253,219,199,255,0,32,121,2,0,0,0,247,247,247,247,255,0,248,120,2,0,142,32,240,209,229,240,255,0,176,120,2,0,141,87,222,146,197,222,255,0,160,120,2,0,143,167,195,67,147,195,255,0,88,120,2,0,148,206,172,33,102,172,255,0,72,120,2,0,242,255,103,103,0,31,255,0,56,120,2,0,0,0,26,26,26,26,255,0,40,120,2,0,249,220,178,178,24,43,255,0,240,119,2,0,5,163,214,214,96,77,255,0,224,119,2,0,13,119,244,244,165,130,255,0,192,119,2,0,15,54,253,253,219,199,255,0,160,119,2,0,0,0,224,224,224,224,255,0,120,119,2,0,0,0,186,186,186,186,255,0,104,119,2,0,0,0,135,135,135,135,255,0,64,119,2,0,0,0,77,77,77,77,255,0,48,119,2,0,242,255,103,103,0,31,255,0,16,119,2,0,0,0,77,77,77,77,255,0,248,118,2,0,0,0,26,26,26,26,255,0,208,118,2,0,249,220,178,178,24,43,255,0,192,118,2,0,5,163,214,214,96,77,255,0,176,118,2,0,13,119,244,244,165,130,255,0,120,118,2,0,15,54,253,253,219,199,255,0,72,118,2,0,0,0,255,255,255,255,255,0,56,118,2,0,0,0,224,224,224,224,255,0,16,118,2,0,0,0,186,186,186,186,255,0,0,118,2,0,0,0,135,135,135,135,255,0,240,117,2,0,12,150,239,239,138,98,255,0,224,117,2,0,0,0,255,255,255,255,255,0,184,117,2,0,0,0,153,153,153,153,255,0,168,117,2,0,248,255,202,202,0,32,255,0,152,117,2,0,13,119,244,244,165,130,255,0,56,117,2,0,0,0,186,186,186,186,255,0,8,117,2,0,0,0,64,64,64,64,255,0,248,116,2,0,248,255,202,202,0,32,255,0,184,116,2,0,13,119,244,244,165,130,255,0,168,116,2,0,0,0,255,255,255,255,255,0,152,116,2,0,0,0,186,186,186,186,255,0,136,116,2,0,0,0,64,64,64,64,255,0,96,116,2,0,249,220,178,178,24,43,255,0,48,116,2,0,12,150,239,239,138,98,255,0,24,116,2,0,15,54,253,253,219,199,255,0,248,115,2,0,0,0,224,224,224,224,255,0,208,115,2,0,0,0,153,153,153,153,255,0,192,115,2,0,0,0,77,77,77,77,255,0,120,115,2,0,249,220,178,178,24,43,255,0,104,115,2,0,12,150,239,239,138,98,255,0,88,115,2,0,15,54,253,253,219,199,255,0,72,115,2,0,0,0,255,255,255,255,255,0,32,115,2,0,0,0,224,224,224,224,255,0,16,115,2,0,0,0,153,153,153,153,255,0,240,114,2,0,0,0,77,77,77,77,255,0,200,114,2,0,249,220,178,178,24,43,255,0,160,114,2,0,5,163,214,214,96,77,255,0,144,114,2,0,13,119,244,244,165,130,255,0,40,114,2,0,15,54,253,253,219,199,255,0,24,114,2,0,0,0,224,224,224,224,255,0,8,114,2,0,0,0,186,186,186,186,255,0,248,113,2,0,0,0,135,135,135,135,255,0,200,113,2,0,0,0,77,77,77,77,255,0,184,113,2,0,249,220,178,178,24,43,255,0,160,113,2,0,5,163,214,214,96,77,255,0,120,113,2,0,13,119,244,244,165,130,255,0,88,113,2,0,15,54,253,253,219,199,255,0,72,113,2,0,0,0,255,255,255,255,255,0,232,112,2,0,0,0,224,224,224,224,255,0,216,112,2,0,0,0,186,186,186,186,255,0,200,112,2,0,0,0,135,135,135,135,255,0,184,112,2,0,0,0,77,77,77,77,255,0,96,112,2,0,3,32,253,253,224,221,255,0,80,112,2,0,244,92,250,250,159,181,255,0,64,112,2,0,227,220,197,197,27,138,255,0,24,112,2,0,13,28,254,254,235,226,255,0,208,111,2,0,252,72,251,251,180,185,255,0,192,111,2,0,238,147,247,247,104,161,255,0,160,111,2,0,224,253,174,174,1,126,255,0,144,111,2,0,13,28,254,254,235,226,255,0,128,111,2,0,252,72,251,251,180,185,255,0,112,111,2,0,238,147,247,247,104,161,255,0,40,111,2,0,227,220,197,197,27,138,255,0,224,110,2,0,213,252,122,122,1,119,255,0,208,110,2,0,13,28,254,254,235,226,255,0,152,110,2,0,3,60,252,252,197,192,255,0,32,110,2,0,244,92,250,250,159,181,255,0,8,110,2,0,238,147,247,247,104,161,255,0,224,109,2,0,227,220,197,197,27,138,255,0,176,109,2,0,213,252,122,122,1,119,255,0,160,109,2,0,13,28,254,254,235,226,255,0,144,109,2,0,3,60,252,252,197,192,255,0,96,109,2,0,244,92,250,250,159,181,255,0,80,109,2,0,238,147,247,247,104,161,255,0,16,109,2,0,230,195,221,221,52,151,255,0,224,108,2,0,224,253,174,174,1,126,255,0,176,108,2,0,213,252,122,122,1,119,255,0,160,108,2,0,14,12,255,255,247,243,255,0,72,108,2,0,3,32,253,253,224,221,255,0,48,108,2,0,3,60,252,252,197,192,255,0,248,107,2,0,244,92,250,250,159,181,255,0,232,107,2,0,238,147,247,247,104,161,255,0,184,107,2,0,230,195,221,221,52,151,255,0,152,107,2,0,224,253,174,174,1,126,255,0,128,107,2,0,213,252,122,122,1,119,255,0,88,107,2,0,14,12,255,255,247,243,255,0,248,106,2,0,3,32,253,253,224,221,255,0,232,106,2,0,3,60,252,252,197,192,255,0,144,106,2,0,244,92,250,250,159,181,255,0,128,106,2,0,238,147,247,247,104,161,255,0,112,106,2,0,230,195,221,221,52,151,255,0,96,106,2,0,224,253,174,174,1,126,255,0,56,106,2,0,213,252,122,122,1,119,255,0,24,106,2,0,199,255,106,73,0,106,255,0,8,106,2,0,245,255,165,165,0,38,255,0,176,105,2,0,167,171,149,49,54,149,255,0,112,105,2,0,2,208,215,215,48,39,255,0,88,105,2,0,10,184,244,244,109,67,255,0,48,105,2,0,20,157,253,253,174,97,255,0,32,105,2,0,30,110,254,254,224,144,255,0,16,105,2,0,136,24,248,224,243,248,255,0,184,104,2,0,138,67,233,171,217,233,255,0,144,104,2,0,143,113,209,116,173,209,255,0,128,104,2,0,151,157,180,69,117,180,255,0,112,104,2,0,245,255,165,165,0,38,255,0,80,104,2,0,151,157,180,69,117,180,255,0,232,103,2,0,167,171,149,49,54,149,255,0,216,103,2,0,2,208,215,215,48,39,255,0,152,103,2,0,10,184,244,244,109,67,255,0,136,103,2,0,20,157,253,253,174,97,255,0,120,103,2,0,30,110,254,254,224,144,255,0,104,103,2,0,42,64,255,255,255,191,255,0,64,103,2,0,136,24,248,224,243,248,255,0,48,103,2,0,138,67,233,171,217,233,255,0,32,103,2,0,143,113,209,116,173,209,255,0,248,102,2,0,13,164,252,252,141,89,255,0,104,102,2,0,42,64,255,255,255,191,255,0,88,102,2,0,143,86,219,145,191,219,255,0,56,102,2,0,254,225,215,215,25,28,255,0,40,102,2,0,20,157,253,253,174,97,255,0,24,102,2,0,138,67,233,171,217,233,255,0,8,102,2,0,145,193,182,44,123,182,255,0,224,101,2,0,254,225,215,215,25,28,255,0,152,101,2,0,20,157,253,253,174,97,255,0,136,101,2,0,42,64,255,255,255,191,255,0,104,101,2,0,138,67,233,171,217,233,255,0,40,101,2,0,145,193,182,44,123,182,255,0,24,101,2,0,2,208,215,215,48,39,255,0,248,100,2,0,13,164,252,252,141,89,255,0,232,100,2,0,30,110,254,254,224,144,255,0,216,100,2,0,136,24,248,224,243,248,255,0,200,100,2,0,143,86,219,145,191,219,255,0,160,100,2,0,151,157,180,69,117,180,255,0,144,100,2,0,2,208,215,215,48,39,255,0,112,100,2,0,13,164,252,252,141,89,255,0,88,100,2,0,30,110,254,254,224,144,255,0,48,100,2,0,42,64,255,255,255,191,255,0,32,100,2,0,136,24,248,224,243,248,255,0,240,99,2,0,143,86,219,145,191,219,255,0,216,99,2,0,151,157,180,69,117,180,255,0,200,99,2,0,2,208,215,215,48,39,255,0,184,99,2,0,10,184,244,244,109,67,255,0,144,99,2,0,20,157,253,253,174,97,255,0,128,99,2,0,30,110,254,254,224,144,255,0,112,99,2,0,136,24,248,224,243,248,255,0,48,99,2,0,138,67,233,171,217,233,255,0,248,98,2,0,143,113,209,116,173,209,255,0,232,98,2,0,151,157,180,69,117,180,255,0,160,98,2,0,2,208,215,215,48,39,255,0,144,98,2,0,10,184,244,244,109,67,255,0,128,98,2,0,20,157,253,253,174,97,255,0,112,98,2,0,30,110,254,254,224,144,255,0,64,98,2,0,42,64,255,255,255,191,255,0,48,98,2,0,136,24,248,224,243,248,255,0,32,98,2,0,138,67,233,171,217,233,255,0,224,97,2,0,143,113,209,116,173,209,255,0,176,97,2,0,151,157,180,69,117,180,255,0,160,97,2,0,245,255,165,165,0,38,255,0,96,97,2,0,107,255,104,0,104,55,255,0,80,97,2,0,2,208,215,215,48,39,255,0,64,97,2,0,10,184,244,244,109,67,255,0,48,97,2,0,20,157,253,253,174,97,255,0,224,96,2,0,31,115,254,254,224,139,255,0,208,96,2,0,51,106,239,217,239,139,255,0,184,96,2,0,62,130,217,166,217,106,255,0,80,96,2,0,83,121,189,102,189,99,255,0,24,96,2,0,103,211,152,26,152,80,255,0,248,95,2,0,245,255,165,165,0,38,255,0,216,95,2,0,103,211,152,26,152,80,255,0,200,95,2,0,107,255,104,0,104,55,255,0,184,95,2,0,2,208,215,215,48,39,255,0,152,95,2,0,10,184,244,244,109,67,255,0,112,95,2,0,20,157,253,253,174,97,255,0,96,95,2,0,31,115,254,254,224,139,255,0,80,95,2,0,42,64,255,255,255,191,255,0,32,95,2,0,51,106,239,217,239,139,255,0,232,94,2,0,62,130,217,166,217,106,255,0,216,94,2,0,83,121,189,102,189,99,255,0,176,94,2,0,13,164,252,252,141,89,255,0,152,94,2,0,42,64,255,255,255,191,255,0,104,94,2,0,66,136,207,145,207,96,255,0,88,94,2,0,254,225,215,215,25,28,255,0,24,94,2,0,20,157,253,253,174,97,255,0,0,94,2,0,62,130,217,166,217,106,255,0,224,93,2,0,98,210,150,26,150,65,255,0,192,93,2,0,254,225,215,215,25,28,255,0,128,93,2,0,20,157,253,253,174,97,255,0,112,93,2,0,42,64,255,255,255,191,255,0,64,93,2,0,62,130,217,166,217,106,255,0,48,93,2,0,98,210,150,26,150,65,255,0,32,93,2,0,2,208,215,215,48,39,255,0,16,93,2,0,13,164,252,252,141,89,255,0,232,92,2,0,31,115,254,254,224,139,255,0,216,92,2,0,51,106,239,217,239,139,255,0,184,92,2,0,66,136,207,145,207,96,255,0,128,92,2,0,103,211,152,26,152,80,255,0,72,92,2,0,2,208,215,215,48,39,255,0,48,92,2,0,13,164,252,252,141,89,255,0,32,92,2,0,31,115,254,254,224,139,255,0,0,92,2,0,42,64,255,255,255,191,255,0,240,91,2,0,51,106,239,217,239,139,255,0,216,91,2,0,66,136,207,145,207,96,255,0,96,91,2,0,103,211,152,26,152,80,255,0,72,91,2,0,2,208,215,215,48,39,255,0,56,91,2,0,10,184,244,244,109,67,255,0,32,91,2,0,20,157,253,253,174,97,255,0,240,90,2,0,31,115,254,254,224,139,255,0,224,90,2,0,51,106,239,217,239,139,255,0,208,90,2,0,62,130,217,166,217,106,255,0,184,90,2,0,83,121,189,102,189,99,255,0,168,90,2,0,103,211,152,26,152,80,255,0,152,90,2,0,2,208,215,215,48,39,255,0,112,90,2,0,10,184,244,244,109,67,255,0,96,90,2,0,20,157,253,253,174,97,255,0,80,90,2,0,31,115,254,254,224,139,255,0,40,90,2,0,42,64,255,255,255,191,255,0,208,89,2,0,51,106,239,217,239,139,255,0,192,89,2,0,62,130,217,166,217,106,255,0,176,89,2,0,83,121,189,102,189,99,255,0,112,89,2,0,103,211,152,26,152,80,255,0,96,89,2,0,13,44,254,254,224,210,255,0,80,89,2,0,9,139,252,252,146,114,255,0,40,89,2,0,1,211,222,222,45,38,255,0,8,89,2,0,13,37,254,254,229,217,255,0,232,88,2,0,11,108,252,252,174,145,255,0,200,88,2,0,7,179,251,251,106,74,255,0,160,88,2,0,253,224,203,203,24,29,255,0,144,88,2,0,13,37,254,254,229,217,255,0,120,88,2,0,11,108,252,252,174,145,255,0,24,88,2,0,7,179,251,251,106,74,255,0,8,88,2,0,1,211,222,222,45,38,255,0,248,87,2,0,253,231,165,165,15,21,255,0,208,87,2,0,13,37,254,254,229,217,255,0,192,87,2,0,12,92,252,252,187,161,255,0,160,87,2,0,9,139,252,252,146,114,255,0,96,87,2,0,7,179,251,251,106,74,255,0,48,87,2,0,1,211,222,222,45,38,255,0,32,87,2,0,253,231,165,165,15,21,255,0,16,87,2,0,13,37,254,254,229,217,255,0,224,86,2,0,12,92,252,252,187,161,255,0,144,86,2,0,9,139,252,252,146,114,255,0,128,86,2,0,7,179,251,251,106,74,255,0,88,86,2,0,3,208,239,239,59,44,255,0,72,86,2,0,253,224,203,203,24,29,255,0,56,86,2,0,251,255,153,153,0,13,255,0,24,86,2,0,14,15,255,255,245,240,255,0,168,85,2,0,13,44,254,254,224,210,255,0,152,85,2,0,12,92,252,252,187,161,255,0,136,85,2,0,9,139,252,252,146,114,255,0,104,85,2,0,7,179,251,251,106,74,255,0,88,85,2,0,3,208,239,239,59,44,255,0,72,85,2,0,253,224,203,203,24,29,255,0,24,85,2,0,251,255,153,153,0,13,255,0,8,85,2,0,14,15,255,255,245,240,255,0,248,84,2,0,13,44,254,254,224,210,255,0,176,84,2,0,12,92,252,252,187,161,255,0,136,84,2,0,9,139,252,252,146,114,255,0,120,84,2,0,7,179,251,251,106,74,255,0,104,84,2,0,3,208,239,239,59,44,255,0,24,84,2,0,253,224,203,203,24,29,255,0,8,84,2,0,253,231,165,165,15,21,255,0,248,83,2,0,249,255,103,103,0,13,255,0,208,83,2,0,254,225,228,228,26,28,255,0,192,83,2,0,146,178,184,55,126,184,255,0,168,83,2,0,83,147,175,77,175,74,255,0,64,83,2,0,254,225,228,228,26,28,255,0,248,82,2,0,146,178,184,55,126,184,255,0,232,82,2,0,83,147,175,77,175,74,255,0,216,82,2,0,207,132,163,152,78,163,255,0,184,82,2,0,254,225,228,228,26,28,255,0,168,82,2,0,146,178,184,55,126,184,255,0,152,82,2,0,83,147,175,77,175,74,255,0,80,82,2,0,207,132,163,152,78,163,255,0,64,82,2,0,21,255,255,255,127,0,255,0,48,82,2,0,254,225,228,228,26,28,255,0,224,81,2,0,146,178,184,55,126,184,255,0,168,81,2,0,83,147,175,77,175,74,255,0,152,81,2,0,207,132,163,152,78,163,255,0,112,81,2,0,21,255,255,255,127,0,255,0,16,81,2,0,42,204,255,255,255,51,255,0,232,80,2,0,254,225,228,228,26,28,255,0,216,80,2,0,146,178,184,55,126,184,255,0,168,80,2,0,83,147,175,77,175,74,255,0,120,80,2,0,207,132,163,152,78,163,255,0,96,80,2,0,21,255,255,255,127,0,255,0,72,80,2,0,42,204,255,255,255,51,255,0,184,79,2,0,15,193,166,166,86,40,255,0,168,79,2,0,254,225,228,228,26,28,255,0,144,79,2,0,146,178,184,55,126,184,255,0,88,79,2,0,83,147,175,77,175,74,255,0,72,79,2,0,207,132,163,152,78,163,255,0,56,79,2,0,21,255,255,255,127,0,255,0,16,79,2,0,42,204,255,255,255,51,255,0,0,79,2,0,15,193,166,166,86,40,255,0,240,78,2,0,232,121,247,247,129,191,255,0,168,78,2,0,254,225,228,228,26,28,255,0,64,78,2,0,146,178,184,55,126,184,255,0,224,77,2,0,83,147,175,77,175,74,255,0,208,77,2,0,207,132,163,152,78,163,255,0,160,77,2,0,21,255,255,255,127,0,255,0,144,77,2,0,42,204,255,255,255,51,255,0,120,77,2,0,15,193,166,166,86,40,255,0,80,77,2,0,232,121,247,247,129,191,255,0,56,77,2,0,0,0,153,153,153,153,255,0,40,77,2,0,114,120,194,102,194,165,255,0,24,77,2,0,11,155,252,252,141,98,255,0,200,76,2,0,156,77,203,141,160,203,255,0,184,76,2,0,114,120,194,102,194,165,255,0,168,76,2,0,11,155,252,252,141,98,255,0,104,76,2,0,156,77,203,141,160,203,255,0,88,76,2,0,228,102,231,231,138,195,255,0,72,76,2,0,114,120,194,102,194,165,255,0,32,76,2,0,11,155,252,252,141,98,255,0,16,76,2,0,156,77,203,141,160,203,255,0,200,75,2,0,228,102,231,231,138,195,255,0,184,75,2,0,58,155,216,166,216,84,255,0,72,75,2,0,114,120,194,102,194,165,255,0,56,75,2,0,11,155,252,252,141,98,255,0,40,75,2,0,156,77,203,141,160,203,255,0,16,75,2,0,228,102,231,231,138,195,255,0,0,75,2,0,58,155,216,166,216,84,255,0,240,74,2,0,34,208,255,255,217,47,255,0,200,74,2,0,114,120,194,102,194,165,255,0,168,74,2,0,11,155,252,252,141,98,255,0,152,74,2,0,156,77,203,141,160,203,255,0,128,74,2,0,228,102,231,231,138,195,255,0,88,74,2,0,58,155,216,166,216,84,255,0,72,74,2,0,34,208,255,255,217,47,255,0,56,74,2,0,25,90,229,229,196,148,255,0,16,74,2,0,114,120,194,102,194,165,255,0,0,74,2,0,11,155,252,252,141,98,255,0,240,73,2,0,156,77,203,141,160,203,255,0,200,73,2,0,228,102,231,231,138,195,255,0,184,73,2,0,58,155,216,166,216,84,255,0,152,73,2,0,34,208,255,255,217,47,255,0,128,73,2,0,25,90,229,229,196,148,255,0,64,73,2,0,0,0,179,179,179,179,255,0,48,73,2,0,120,84,211,141,211,199,255,0,32,73,2,0,211,82,189,188,128,189,255,0,0,73,2,0,42,76,255,255,255,179,255,0,240,72,2,0,175,37,218,190,186,218,255,0,144,72,2,0,4,139,251,251,128,114,255,0,104,72,2,0,144,100,211,128,177,211,255,0,88,72,2,0,22,156,253,253,180,98,255,0,72,72,2,0,58,134,222,179,222,105,255,0,56,72,2,0,233,47,252,252,205,229,255,0,248,71,2,0,0,0,217,217,217,217,255,0,168,71,2,0,120,84,211,141,211,199,255,0,152,71,2,0,211,82,189,188,128,189,255,0,128,71,2,0,77,41,235,204,235,197,255,0,112,71,2,0,42,76,255,255,255,179,255,0,96,71,2,0,175,37,218,190,186,218,255,0,48,71,2,0,4,139,251,251,128,114,255,0,32,71,2,0,144,100,211,128,177,211,255,0,16,71,2,0,22,156,253,253,180,98,255,0,0,71,2,0,58,134,222,179,222,105,255,0,224,70,2,0,233,47,252,252,205,229,255,0,208,70,2,0,0,0,217,217,217,217,255,0,192,70,2,0,120,84,211,141,211,199,255,0,168,70,2,0,211,82,189,188,128,189,255,0,152,70,2,0,77,41,235,204,235,197,255,0,136,70,2,0,37,144,255,255,237,111,255,0,96,70,2,0,42,76,255,255,255,179,255,0,80,70,2,0,175,37,218,190,186,218,255,0,56,70,2,0,4,139,251,251,128,114,255,0,0,70,2,0,144,100,211,128,177,211,255,0,208,69,2,0,22,156,253,253,180,98,255,0,192,69,2,0,58,134,222,179,222,105,255,0,176,69,2,0,233,47,252,252,205,229,255,0,160,69,2,0,0,0,217,217,217,217,255,0,144,69,2,0,120,84,211,141,211,199,255,0,128,69,2,0,42,76,255,255,255,179,255,0,88,69,2,0,175,37,218,190,186,218,255,0,72,69,2,0,120,84,211,141,211,199,255,0,56,69,2,0,42,76,255,255,255,179,255,0,24,69,2,0,175,37,218,190,186,218,255,0,240,68,2,0,4,139,251,251,128,114,255,0,224,68,2,0,120,84,211,141,211,199,255,0,96,68,2,0,42,76,255,255,255,179,255,0,72,68,2,0,175,37,218,190,186,218,255,0,24,68,2,0,4,139,251,251,128,114,255,0,8,68,2,0,144,100,211,128,177,211,255,0,216,67,2,0,120,84,211,141,211,199,255,0,168,67,2,0,42,76,255,255,255,179,255,0,144,67,2,0,175,37,218,190,186,218,255,0,128,67,2,0,4,139,251,251,128,114,255,0,64,67,2,0,144,100,211,128,177,211,255,0,48,67,2,0,22,156,253,253,180,98,255,0,24,67,2,0,120,84,211,141,211,199,255,0,8,67,2,0,42,76,255,255,255,179,255,0,248,66,2,0,175,37,218,190,186,218,255,0,232,66,2,0,4,139,251,251,128,114,255,0,192,66,2,0,144,100,211,128,177,211,255,0,176,66,2,0,22,156,253,253,180,98,255,0,160,66,2,0,58,134,222,179,222,105,255,0,144,66,2,0,120,84,211,141,211,199,255,0,112,66,2,0,42,76,255,255,255,179,255,0,72,66,2,0,175,37,218,190,186,218,255,0,0,66,2,0,4,139,251,251,128,114,255,0,240,65,2,0,144,100,211,128,177,211,255,0,224,65,2,0,22,156,253,253,180,98,255,0,208,65,2,0,58,134,222,179,222,105,255,0,160,65,2,0,233,47,252,252,205,229,255,0,136,65,2,0,120,84,211,141,211,199,255,0,96,65,2,0,42,76,255,255,255,179,255,0,80,65,2,0,175,37,218,190,186,218,255,0,48,65,2,0,4,139,251,251,128,114,255,0,24,65,2,0,144,100,211,128,177,211,255,0,8,65,2,0,22,156,253,253,180,98,255,0,248,64,2,0,58,134,222,179,222,105,255,0,232,64,2,0,233,47,252,252,205,229,255,0,216,64,2,0,0,0,217,217,217,217,255,0,176,64,2,0,237,253,158,158,1,66,255,0,160,64,2,0,177,130,162,94,79,162,255,0,144,64,2,0,250,180,213,213,62,79,255,0,128,64,2,0,10,184,244,244,109,67,255,0,40,64,2,0,20,157,253,253,174,97,255,0,24,64,2,0,31,115,254,254,224,139,255,0,8,64,2,0,49,96,245,230,245,152,255,0,248,63,2,0,79,65,221,171,221,164,255,0,232,63,2,0,114,120,194,102,194,165,255,0,216,63,2,0,143,187,189,50,136,189,255,0,176,63,2,0,237,253,158,158,1,66,255,0,104,63,2,0,143,187,189,50,136,189,255,0,88,63,2,0,177,130,162,94,79,162,255,0,64,63,2,0,250,180,213,213,62,79,255,0,24,63,2,0,10,184,244,244])
+.concat([109,67,255,0,8,63,2,0,20,157,253,253,174,97,255,0,248,62,2,0,31,115,254,254,224,139,255,0,232,62,2,0,42,64,255,255,255,191,255,0,216,62,2,0,49,96,245,230,245,152,255,0,200,62,2,0,79,65,221,171,221,164,255,0,160,62,2,0,114,120,194,102,194,165,255,0,144,62,2,0,13,164,252,252,141,89,255,0,128,62,2,0,42,64,255,255,255,191,255,0,80,62,2,0,81,77,213,153,213,148,255,0,32,62,2,0,254,225,215,215,25,28,255,0,16,62,2,0,20,157,253,253,174,97,255,0,0,62,2,0,79,65,221,171,221,164,255,0,240,61,2,0,143,196,186,43,131,186,255,0,224,61,2,0,254,225,215,215,25,28,255,0,208,61,2,0,20,157,253,253,174,97,255,0,64,61,2,0,42,64,255,255,255,191,255,0,48,61,2,0,79,65,221,171,221,164,255,0,32,61,2,0,143,196,186,43,131,186,255,0,16,61,2,0,250,180,213,213,62,79,255,0,224,60,2,0,13,164,252,252,141,89,255,0,208,60,2,0,31,115,254,254,224,139,255,0,176,60,2,0,49,96,245,230,245,152,255,0,160,60,2,0,81,77,213,153,213,148,255,0,144,60,2,0,143,187,189,50,136,189,255,0,128,60,2,0,250,180,213,213,62,79,255,0,80,60,2,0,13,164,252,252,141,89,255,0,64,60,2,0,31,115,254,254,224,139,255,0,48,60,2,0,42,64,255,255,255,191,255,0,32,60,2,0,49,96,245,230,245,152,255,0,248,59,2,0,81,77,213,153,213,148,255,0,232,59,2,0,143,187,189,50,136,189,255,0,216,59,2,0,250,180,213,213,62,79,255,0,200,59,2,0,10,184,244,244,109,67,255,0,184,59,2,0,20,157,253,253,174,97,255,0,168,59,2,0,31,115,254,254,224,139,255,0,128,59,2,0,49,96,245,230,245,152,255,0,112,59,2,0,79,65,221,171,221,164,255,0,80,59,2,0,114,120,194,102,194,165,255,0,16,59,2,0,143,187,189,50,136,189,255,0,216,58,2,0,250,180,213,213,62,79,255,0,200,58,2,0,10,184,244,244,109,67,255,0,184,58,2,0,20,157,253,253,174,97,255,0,168,58,2,0,31,115,254,254,224,139,255,0,152,58,2,0,42,64,255,255,255,191,255,0,136,58,2,0,49,96,245,230,245,152,255,0,96,58,2,0,79,65,221,171,221,164,255,0,80,58,2,0,114,120,194,102,194,165,255,0,64,58,2,0,143,187,189,50,136,189,255,0,48,58,2,0,147,15,255,240,248,255,255,0,224,57,2,0,24,35,250,250,235,215,255,0,208,57,2,0,127,255,255,0,255,255,255,0,152,57,2,0,113,128,255,127,255,212,255,0,120,57,2,0,127,15,255,240,255,255,255,0,72,57,2,0,42,26,245,245,245,220,255,0,56,57,2,0,23,58,255,255,228,196,255,0,248,56,2,0,0,0,0,0,0,0,255,0,216,56,2,0,25,49,255,255,235,205,255,0,192,56,2,0,170,255,255,0,0,255,255,0,176,56,2,0,192,206,226,138,43,226,255,0,104,56,2,0,0,190,165,165,42,42,255,0,80,56,2,0,23,99,222,222,184,135,255,0,48,56,2,0,128,103,160,95,158,160,255,0,32,56,2,0,63,255,255,127,255,0,255,0,16,56,2,0,17,218,210,210,105,30,255,0,0,56,2,0,11,175,255,255,127,80,255,0,208,55,2,0,154,147,237,100,149,237,255,0,192,55,2,0,33,34,255,255,248,220,255,0,176,55,2,0,246,231,220,220,20,60,255,0,160,55,2,0,127,255,255,0,255,255,255,0,128,55,2,0,170,255,139,0,0,139,255,0,104,55,2,0,127,255,139,0,139,139,255,0,80,55,2,0,30,239,184,184,134,11,255,0,24,55,2,0,0,0,169,169,169,169,255,0,8,55,2,0,85,255,100,0,100,0,255,0,248,54,2,0,0,0,169,169,169,169,255,0,200,54,2,0,39,110,189,189,183,107,255,0,176,54,2,0,212,255,139,139,0,139,255,0,152,54,2,0,58,142,107,85,107,47,255,0,128,54,2,0,23,255,255,255,140,0,255,0,96,54,2,0,198,192,204,153,50,204,255,0,72,54,2,0,0,255,139,139,0,0,255,0,56,54,2,0,10,121,233,233,150,122,255,0,32,54,2,0,85,61,188,143,188,143,255,0,8,54,2,0,175,143,139,72,61,139,255,0,240,53,2,0,127,103,79,47,79,79,255,0,192,53,2,0,127,103,79,47,79,79,255,0,168,53,2,0,128,255,209,0,206,209,255,0,152,53,2,0,199,255,211,148,0,211,255,0,136,53,2,0,232,235,255,255,20,147,255,0,56,53,2,0,138,255,255,0,191,255,255,0,40,53,2,0,0,0,105,105,105,105,255,0,24,53,2,0,0,0,105,105,105,105,255,0,8,53,2,0,148,225,255,30,144,255,255,0,248,52,2,0,0,206,178,178,34,34,255,0,224,52,2,0,28,15,255,255,250,240,255,0,176,52,2,0,85,192,139,34,139,34,255,0,160,52,2,0,212,255,255,255,0,255,255,0,144,52,2,0,0,0,220,220,220,220,255,0,120,52,2,0,170,7,255,248,248,255,255,0,88,52,2,0,35,255,255,255,215,0,255,0,72,52,2,0,30,217,218,218,165,32,255,0,56,52,2,0,0,0,128,128,128,128,255,0,40,52,2,0,85,255,128,0,128,0,255,0,16,52,2,0,59,208,255,173,255,47,255,0,0,52,2,0,0,0,128,128,128,128,255,0,216,51,2,0,85,15,255,240,255,240,255,0,200,51,2,0,233,150,255,255,105,180,255,0,184,51,2,0,0,140,205,205,92,92,255,0,152,51,2,0,194,255,130,75,0,130,255,0,112,51,2,0,42,15,255,255,255,240,255,0,96,51,2,0,38,106,240,240,230,140,255,0,80,51,2,0,170,20,250,230,230,250,255,0,56,51,2,0,240,15,255,255,240,245,255,0,40,51,2,0,64,255,252,124,252,0,255,0,16,51,2,0,38,49,255,255,250,205,255,0,232,50,2,0,137,63,230,173,216,230,255,0,96,50,2,0,0,119,240,240,128,128,255,0,80,50,2,0,127,31,255,224,255,255,255,0,48,50,2,0,42,40,250,250,250,210,255,0,240,49,2,0,0,0,211,211,211,211,255,0,224,49,2,0,85,100,238,144,238,144,255,0,208,49,2,0,0,0,211,211,211,211,255,0,160,49,2,0,248,73,255,255,182,193,255,0,136,49,2,0,12,132,255,255,160,122,255,0,112,49,2,0,125,209,178,32,178,170,255,0,48,49,2,0,143,117,250,135,206,250,255,0,24,49,2,0,148,56,153,119,136,153,255,0,0,49,2,0,148,56,153,119,136,153,255,0,232,48,2,0,151,52,222,176,196,222,255,0,176,48,2,0,42,31,255,255,255,224,255,0,160,48,2,0,85,255,255,0,255,0,255,0,144,48,2,0,85,192,205,50,205,50,255,0,128,48,2,0,21,20,250,250,240,230,255,0,112,48,2,0,212,255,255,255,0,255,255,0,96,48,2,0,0,255,128,128,0,0,255,0,48,48,2,0,113,128,205,102,205,170,255,0,232,47,2,0,170,255,205,0,0,205,255,0,176,47,2,0,204,152,211,186,85,211,255,0,96,47,2,0,183,124,219,147,112,219,255,0,24,47,2,0,103,169,179,60,179,113,255,0,0,47,2,0,176,143,238,123,104,238,255,0,232,46,2,0,111,255,250,0,250,154,255,0,208,46,2,0,125,167,209,72,209,204,255,0,184,46,2,0,228,228,199,199,21,133,255,0,152,46,2,0,170,198,112,25,25,112,255,0,104,46,2,0,106,9,255,245,255,250,255,0,88,46,2,0,4,30,255,255,228,225,255,0,72,46,2,0,26,73,255,255,228,181,255,0,48,46,2,0,25,81,255,255,222,173,255,0,248,45,2,0,170,255,128,0,0,128,255,0,232,45,2,0,27,23,253,253,245,230,255,0,176,45,2,0,42,255,128,128,128,0,255,0,152,45,2,0,56,192,142,107,142,35,255,0,112,45,2,0,27,255,255,255,165,0,255,0,96,45,2,0,11,255,255,255,69,0,255,0,56,45,2,0,214,123,218,218,112,214,255,0,248,44,2,0,38,72,238,238,232,170,255,0,224,44,2,0,85,100,251,152,251,152,255,0,200,44,2,0,127,67,238,175,238,238,255,0,120,44,2,0,241,124,219,219,112,147,255,0,104,44,2,0,26,41,255,255,239,213,255,0,72,44,2,0,20,70,255,255,218,185,255,0,56,44,2,0,20,176,205,205,133,63,255,0,40,44,2,0,247,63,255,255,192,203,255,0,24,44,2,0,212,70,221,221,160,221,255,0,240,43,2,0,132,59,230,176,224,230,255,0,224,43,2,0,212,255,128,128,0,128,255,0,208,43,2,0,0,255,255,255,0,0,255,0,192,43,2,0,0,61,188,188,143,143,255,0,152,43,2,0,159,181,225,65,105,225,255,0,112,43,2,0,17,220,139,139,69,19,255,0,96,43,2,0,4,138,250,250,128,114,255,0,80,43,2,0,19,154,244,244,164,96,255,0,56,43,2,0,103,170,139,46,139,87,255,0,40,43,2,0,17,16,255,255,245,238,255,0,248,42,2,0,13,183,160,160,82,45,255,0,232,42,2,0,0,0,192,192,192,192,255,0,216,42,2,0,139,108,235,135,206,235,255,0,200,42,2,0,175,143,205,106,90,205,255,0,112,42,2,0,148,56,144,112,128,144,255,0,88,42,2,0,148,56,144,112,128,144,255,0,72,42,2,0,0,5,255,255,250,250,255,0,48,42,2,0,106,255,255,0,255,127,255,0,32,42,2,0,146,155,180,70,130,180,255,0,16,42,2,0,24,84,210,210,180,140,255,0,232,41,2,0,127,255,128,0,128,128,255,0,216,41,2,0,212,29,216,216,191,216,255,0,200,41,2,0,6,184,255,255,99,71,255,0,168,41,2,0,123,182,224,64,224,208,255,0,88,41,2,0,212,115,238,238,130,238,255,0,72,41,2,0,27,68,245,245,222,179,255,0,56,41,2,0,0,0,255,255,255,255,255,0,40,41,2,0,0,0,245,245,245,245,255,0,24,41,2,0,42,255,255,255,255,0,255,0,0,41,2,0,56,192,205,154,205,50,255,0,216,40,2,0,45,67,252,247,252,185,255,0,200,40,2,0,68,91,221,173,221,142,255,0,184,40,2,0,98,178,163,49,163,84,255,0,112,40,2,0,42,50,255,255,255,204,255,0,72,40,2,0,62,85,230,194,230,153,255,0,56,40,2,0,85,100,198,120,198,121,255,0,40,40,2,0,99,187,132,35,132,67,255,0,24,40,2,0,42,50,255,255,255,204,255,0,8,40,2,0,62,85,230,194,230,153,255,0,248,39,2,0,85,100,198,120,198,121,255,0,208,39,2,0,98,178,163,49,163,84,255,0,192,39,2,0,107,255,104,0,104,55,255,0,176,39,2,0,42,50,255,255,255,204,255,0,144,39,2,0,55,81,240,217,240,163,255,0,96,39,2,0,68,91,221,173,221,142,255,0,80,39,2,0,85,100,198,120,198,121,255,0,64,39,2,0,98,178,163,49,163,84,255,0,48,39,2,0,107,255,104,0,104,55,255,0,32,39,2,0,42,50,255,255,255,204,255,0,16,39,2,0,55,81,240,217,240,163,255,0,200,35,2,0,68,91,221,173,221,142,255,0,184,35,2,0,85,100,198,120,198,121,255,0,128,35,2,0,96,158,171,65,171,93,255,0,112,35,2,0,99,187,132,35,132,67,255,0,64,35,2,0,108,255,90,0,90,50,255,0,0,35,2,0,42,25,255,255,255,229,255,0,240,34,2,0,45,67,252,247,252,185,255,0,224,34,2,0,55,81,240,217,240,163,255,0,208,34,2,0,68,91,221,173,221,142,255,0,192,34,2,0,85,100,198,120,198,121,255,0,144,34,2,0,96,158,171,65,171,93,255,0,128,34,2,0,99,187,132,35,132,67,255,0,112,34,2,0,108,255,90,0,90,50,255,0,96,34,2,0,42,25,255,255,255,229,255,0,48,34,2,0,45,67,252,247,252,185,255,0,32,34,2,0,55,81,240,217,240,163,255,0,16,34,2,0,68,91,221,173,221,142,255,0,0,34,2,0,85,100,198,120,198,121,255,0,240,33,2,0,96,158,171,65,171,93,255,0,224,33,2,0,99,187,132,35,132,67,255,0,168,33,2,0,107,255,104,0,104,55,255,0,152,33,2,0,110,255,69,0,69,41,255,0,112,33,2,0,49,73,248,237,248,177,255,0,88,33,2,0,117,97,205,127,205,187,255,0,248,32,2,0,144,194,184,44,127,184,255,0,232,32,2,0,42,50,255,255,255,204,255,0,216,32,2,0,99,66,218,161,218,180,255,0,200,32,2,0,132,170,196,65,182,196,255,0,184,32,2,0,150,203,168,34,94,168,255,0,168,32,2,0,42,50,255,255,255,204,255,0,128,32,2,0,99,66,218,161,218,180,255,0,112,32,2,0,132,170,196,65,182,196,255,0,96,32,2,0,144,194,184,44,127,184,255,0,80,32,2,0,164,191,148,37,52,148,255,0,24,32,2,0,42,50,255,255,255,204,255,0,8,32,2,0,69,58,233,199,233,180,255,0,232,31,2,0,117,97,205,127,205,187,255,0,208,31,2,0,132,170,196,65,182,196,255,0,168,31,2,0,144,194,184,44,127,184,255,0,152,31,2,0,164,191,148,37,52,148,255,0,112,31,2,0,42,50,255,255,255,204,255,0,88,31,2,0,69,58,233,199,233,180,255,0,64,31,2,0,117,97,205,127,205,187,255,0,48,31,2,0,132,170,196,65,182,196,255,0,200,30,2,0,139,216,192,29,145,192,255,0,184,30,2,0,150,203,168,34,94,168,255,0,160,30,2,0,158,231,132,12,44,132,255,0,136,30,2,0,42,38,255,255,255,217,255,0,120,30,2,0,49,73,248,237,248,177,255,0,104,30,2,0,69,58,233,199,233,180,255,0,64,30,2,0,117,97,205,127,205,187,255,0,48,30,2,0,132,170,196,65,182,196,255,0,16,30,2,0,139,216,192,29,145,192,255,0,0,30,2,0,150,203,168,34,94,168,255,0,200,29,2,0,158,231,132,12,44,132,255,0,176,29,2,0,42,38,255,255,255,217,255,0,160,29,2,0,49,73,248,237,248,177,255,0,144,29,2,0,69,58,233,199,233,180,255,0,128,29,2,0,117,97,205,127,205,187,255,0,96,29,2,0,132,170,196,65,182,196,255,0,48,29,2,0,139,216,192,29,145,192,255,0,32,29,2,0,150,203,168,34,94,168,255,0,16,29,2,0,164,191,148,37,52,148,255,0,0,29,2,0,158,231,88,8,29,88,255,0,208,28,2,0,37,66,255,255,247,188,255,0,176,28,2,0,28,175,254,254,196,79,255,0,160,28,2,0,16,238,217,217,95,14,255,0,144,28,2,0,42,42,255,255,255,212,255,0,128,28,2,0,28,112,254,254,217,142,255,0,112,28,2,0,22,213,254,254,153,41,255,0,72,28,2,0,15,252,204,204,76,2,255,0,56,28,2,0,42,42,255,255,255,212,255,0,40,28,2,0,28,112,254,254,217,142,255,0,16,28,2,0,22,213,254,254,153,41,255,0,136,27,2,0,16,238,217,217,95,14,255,0,120,27,2,0,13,248,153,153,52,4,255,0,104,27,2,0,42,42,255,255,255,212,255,0,88,27,2,0,31,109,254,254,227,145,255,0,72,27,2,0,28,175,254,254,196,79,255,0,56,27,2,0,22,213,254,254,153,41,255,0,16,27,2,0,16,238,217,217,95,14,255,0,0,27,2,0,13,248,153,153,52,4,255,0,240,26,2,0,42,42,255,255,255,212,255,0,208,26,2,0,31,109,254,254,227,145,255,0,168,26,2,0,28,175,254,254,196,79,255,0,152,26,2,0,22,213,254,254,153,41,255,0,136,26,2,0,18,233,236,236,112,20,255,0,120,26,2,0,15,252,204,204,76,2,255,0,104,26,2,0,12,247,140,140,45,4,255,0,88,26,2,0,42,25,255,255,255,229,255,0,48,26,2,0,37,66,255,255,247,188,255,0,32,26,2,0,31,109,254,254,227,145,255,0,16,26,2,0,28,175,254,254,196,79,255,0,240,25,2,0,22,213,254,254,153,41,255,0,192,25,2,0,18,233,236,236,112,20,255,0,176,25,2,0,15,252,204,204,76,2,255,0,160,25,2,0,12,247,140,140,45,4,255,0,144,25,2,0,42,25,255,255,255,229,255,0,128,25,2,0,37,66,255,255,247,188,255,0,112,25,2,0,31,109,254,254,227,145,255,0,72,25,2,0,28,175,254,254,196,79,255,0,56,25,2,0,22,213,254,254,153,41,255,0,40,25,2,0,18,233,236,236,112,20,255,0,192,24,2,0,15,252,204,204,76,2,255,0,144,24,2,0,13,248,153,153,52,4,255,0,128,24,2,0,13,240,102,102,37,6,255,0,112,24,2,0,34,95,255,255,237,160,255,0,96,24,2,0,24,178,254,254,178,76,255,0,80,24,2,0,5,221,240,240,59,32,255,0,56,24,2,0,42,77,255,255,255,178,255,0,8,24,2,0,29,162,254,254,204,92,255,0,248,23,2,0,17,194,253,253,141,60,255,0,232,23,2,0,254,225,227,227,26,28,255,0,216,23,2,0,42,77,255,255,255,178,255,0,152,23,2,0,29,162,254,254,204,92,255,0,136,23,2,0,17,194,253,253,141,60,255,0,120,23,2,0,5,221,240,240,59,32,255,0,88,23,2,0,246,255,189,189,0,38,255,0,72,23,2,0,42,77,255,255,255,178,255,0,56,23,2,0,30,136,254,254,217,118,255,0,16,23,2,0,24,178,254,254,178,76,255,0,0,23,2,0,17,194,253,253,141,60,255,0,240,22,2,0,5,221,240,240,59,32,255,0,224,22,2,0,246,255,189,189,0,38,255,0,120,22,2,0,42,77,255,255,255,178,255,0,104,22,2,0,30,136,254,254,217,118,255,0,88,22,2,0,24,178,254,254,178,76,255,0,72,22,2,0,17,194,253,253,141,60,255,0,56,22,2,0,7,212,252,252,78,42,255,0,40,22,2,0,254,225,227,227,26,28,255,0,0,22,2,0,245,255,177,177,0,38,255,0,240,21,2,0,42,50,255,255,255,204,255,0,224,21,2,0,34,95,255,255,237,160,255,0,160,21,2,0,30,136,254,254,217,118,255,0,96,21,2,0,24,178,254,254,178,76,255,0,80,21,2,0,17,194,253,253,141,60,255,0,16,21,2,0,7,212,252,252,78,42,255,0,248,20,2,0,254,225,227,227,26,28,255,0,232,20,2,0,245,255,177,177,0,38,255,0,208,20,2,0,42,50,255,255,255,204,255,0,168,20,2,0,34,95,255,255,237,160,255,0,136,20,2,0,30,136,254,254,217,118,255,0,120,20,2,0,24,178,254,254,178,76,255,0,96,20,2,0,17,194,253,253,141,60,255,0,0,20,2,0,7,212,252,252,78,42,255,0,240,19,2,0,254,225,227,227,26,28,255,0,224,19,2,0,246,255,189,189,0,38,255,0,184,19,2,0,242,255,128,128,0,38,255,0,160,19,2,0,147,15,255,240,248,255,255,0,144,19,2,0,24,35,250,250,235,215,255,0,104,19,2,0,23,36,255,255,239,219,255,0,88,19,2,0,23,36,238,238,223,204,255,0,72,19,2,0,23,36,205,205,192,176,255,0,56,19,2,0,24,34,139,139,131,120,255,0,248,18,2,0,113,128,255,127,255,212,255,0,216,18,2,0,113,128,255,127,255,212,255,0,200,18,2,0,113,128,238,118,238,198,255,0,184,18,2,0,113,128,205,102,205,170,255,0,168,18,2,0,113,128,139,69,139,116,255,0,160,18,2,0,127,15,255,240,255,255,255,0,120,18,2,0,127,15,255,240,255,255,255,0,112,18,2,0,127,15,238,224,238,238,255,0,104,18,2,0,127,14,205,193,205,205,255,0,96,18,2,0,127,14,139,131,139,139,255,0,48,18,2,0,42,26,245,245,245,220,255,0,8,18,2,0,23,58,255,255,228,196,255,0,248,17,2,0,23,58,255,255,228,196,255,0,240,17,2,0,23,58,238,238,213,183,255,0,232,17,2,0,22,58,205,205,183,158,255,0,224,17,2,0,23,58,139,139,125,107,255,0,192,17,2,0,0,0,0,0,0,0,255,0,176,17,2,0,25,49,255,255,235,205,255,0,168,17,2,0,170,255,255,0,0,255,255,0,160,17,2,0,170,255,255,0,0,255,255,0,104,17,2,0,170,255,238,0,0,238,255,0,72,17,2,0,170,255,205,0,0,205,255,0,64,17,2,0,170,255,139,0,0,139,255,0,48,17,2,0,192,206,226,138,43,226,255,0,40,17,2,0,0,190,165,165,42,42,255,0,32,17,2,0,0,191,255,255,64,64,255,0,0,17,2,0,0,191,238,238,59,59,255,0,248,16,2,0,0,191,205,205,51,51,255,0,240,16,2,0,0,190,139,139,35,35,255,0,216,16,2,0,23,99,222,222,184,135,255,0,184,16,2,0,23,100,255,255,211,155,255,0,144,16,2,0,23,99,238,238,197,145,255,0,128,16,2,0,23,99,205,205,170,125,255,0,112,16,2,0,23,99,139,139,115,85,255,0,96,16,2,0,128,103,160,95,158,160,255,0,80,16,2,0,131,103,255,152,245,255,255,0,40,16,2,0,131,102,238,142,229,238,255,0,24,16,2,0,131,103,205,122,197,205,255,0,8,16,2,0,131,102,139,83,134,139,255,0,232,15,2,0,63,255,255,127,255,0,255,0,200,15,2,0,63,255,255,127,255,0,255,0,160,15,2,0,63,255,238,118,238,0,255,0,144,15,2,0,63,255,205,102,205,0,255,0,128,15,2,0,63,255,139,69,139,0,255,0,112,15,2,0,17,218,210,210,105,30,255,0,96,15,2,0,17,219,255,255,127,36,255,0,56,15,2,0,17,219,238,238,118,33,255,0,40,15,2,0,17,218,205,205,102,29,255,0,24,15,2,0,17,220,139,139,69,19,255,0,16,15,2,0,11,175,255,255,127,80,255,0,216,14,2,0,7,169,255,255,114,86,255,0,192,14,2,0,6,169,238,238,106,80,255,0,184,14,2,0,6,169,205,205,91,69,255,0,176,14,2,0,6,168,139,139,62,47,255,0,160,14,2,0,154,147,237,100,149,237,255,0,144,14,2,0,33,34,255,255,248,220,255,0,96,14,2,0,33,34,255,255,248,220,255,0,80,14,2,0,34,35,238,238,232,205,255,0,64,14,2,0,34,34,205,205,200,177,255,0,48,14,2,0,35,34,139,139,136,120,255,0,16,14,2,0,246,231,220,220,20,60,255,0,240,13,2,0,127,255,255,0,255,255,255,0,232,13,2,0,127,255,255,0,255,255,255,0,224,13,2,0,127,255,238,0,238,238,255,0,216,13,2,0,127,255,205,0,205,205,255,0,208,13,2,0,127,255,139,0,139,139,255,0,168,13,2,0,30,239,184,184,134,11,255,0,152,13,2,0,30,240,255,255,185,15,255,0,136,13,2,0,30,240,238,238,173,14,255,0,120,13,2,0,30,240,205,205,149,12,255,0,32,13,2,0,30,240,139,139,101,8,255,0,0,13,2,0,85,255,100,0,100,0,255,0,240,12,2,0,39,110,189,189,183,107,255,0,224,12,2,0,58,142,107,85,107,47,255,0,208,12,2,0,58,143,255,202,255,112,255,0,192,12,2,0,58,143,238,188,238,104,255,0,152,12,2,0,58,143,205,162,205,90,255,0,136,12,2,0,58,143,139,110,139,61,255,0,120,12,2,0,23,255,255,255,140,0,255,0,104,12,2,0,21,255,255,255,127,0,255,0,24,12,2,0,21,255,238,238,118,0,255,0,248,11,2,0,21,255,205,205,102,0,255,0,224,11,2,0,21,255,139,139,69,0,255,0,192,11,2,0,198,192,204,153,50,204,255,0,176,11,2,0,198,193,255,191,62,255,255,0,160,11,2,0,198,192,238,178,58,238,255,0,120,11,2,0,198,192,205,154,50,205,255,0,96,11,2,0,198,192,139,104,34,139,255,0,80,11,2,0,10,121,233,233,150,122,255,0,56,11,2,0,85,61,188,143,188,143,255,0,176,10,2,0,85,62,255,193,255,193,255,0,152,10,2,0,85,62,238,180,238,180,255,0,136,10,2,0,85,62,205,155,205,155,255,0,104,10,2,0,85,62,139,105,139,105,255,0,88,10,2,0,175,143,139,72,61,139,255,0,56,10,2,0,127,103,79,47,79,79,255,0,16,10,2,0,127,104,255,151,255,255,255,0,0,10,2,0,127,103,238,141,238,238,255,0,224,9,2,0,127,104,205,121,205,205,255,0,208,9,2,0,127,104,139,82,139,139,255,0,144,9,2,0,127,103,79,47,79,79,255,0,120,9,2,0,128,255,209,0,206,209,255,0,96,9,2,0,199,255,211,148,0,211,255,0,80,9,2,0,232,235,255,255,20,147,255,0,64,9,2,0,232,235,255,255,20,147,255,0,48,9,2,0,232,235,238,238,18,137,255,0,16,9,2,0,232,235,205,205,16,118,255,0,0,9,2,0,231,236,139,139,10,80,255,0,216,8,2,0,138,255,255,0,191,255,255,0,200,8,2,0,138,255,255,0,191,255,255,0,168,8,2,0,138,255,238,0,178,238,255,0,96,8,2,0,138,255,205,0,154,205,255,0,80,8,2,0,138,255,139,0,104,139,255,0,0,8,2,0,0,0,105,105,105,105,255,0,248,7,2,0,0,0,105,105,105,105,255,0,232,7,2,0,148,225,255,30,144,255,255,0,208,7,2,0,148,225,255,30,144,255,255,0,192,7,2,0,148,225,238,28,134,238,255,0,160,7,2,0,148,225,205,24,116,205,255,0,144,7,2,0,148,225,139,16,78,139,255,0,88,7,2,0,0,206,178,178,34,34,255,0,56,7,2,0,0,207,255,255,48,48,255,0,40,7,2,0,0,207,238,238,44,44,255,0,24,7,2,0,0,207,205,205,38,38,255,0,8,7,2,0,0,207,139,139,26,26,255,0,248,6,2,0,28,15,255,255,250,240,255,0,224,6,2,0,85,192,139,34,139,34,255,0,208,6,2,0,0,0,220,220,220,220,255,0,176,6,2,0,170,7,255,248,248,255,255,0,152,6,2,0,35,255,255,255,215,0,255,0,120,6,2,0,35,255,255,255,215,0,255,0,96,6,2,0,35,255,238,238,201,0,255,0,88,6,2,0,35,255,205,205,173,0,255,0,80,6,2,0,35,255,139,139,117,0,255,0,64,6,2,0,30,217,218,218,165,32,255,0,48,6,2,0,30,218,255,255,193,37,255,0,24,6,2,0,30,218,238,238,180,34,255,0,8,6,2,0,30,218,205,205,155,29,255,0,232,5,2,0,30,218,139,139,105,20,255,0,208,5,2,0,0,0,192,192,192,192,255,0,184,5,2,0,0,0,0,0,0,0,255,0,168,5,2,0,0,0,3,3,3,3,255,0,160,5,2,0,0,0,26,26,26,26,255,0,152,5,2,0,0,0,255,255,255,255,255,0,144,5,2,0,0,0,28,28,28,28,255,0,136,5,2,0,0,0,31,31,31,31,255,0,120,5,2,0,0,0,33,33,33,33,255,0,112,5,2,0,0,0,36,36,36,36,255,0,88,5,2,0,0,0,38,38,38,38,255,0,80,5,2,0,0,0,41,41,41,41,255,0,48,5,2,0,0,0,43,43,43,43,255,0,24,5,2,0,0,0,46,46,46,46,255,0,16,5,2,0,0,0,48,48,48,48,255,0,8,5,2,0,0,0,5,5,5,5,255,0,0,5,2,0,0,0,51,51,51,51,255,0,248,4,2,0,0,0,54,54,54,54,255,0,216,4,2,0,0,0,56,56,56,56,255,0,208,4,2,0,0,0,59,59,59,59,255,0,184,4,2,0,0,0,61,61,61,61,255,0,176,4,2,0,0,0,64,64,64,64,255,0,136,4,2,0,0,0,66,66,66,66,255,0,120,4,2,0,0,0,69,69,69,69,255,0,112,4,2,0,0,0,71,71,71,71,255,0,104,4,2,0,0,0,74,74,74,74,255,0,96,4,2,0,0,0,8,8,8,8,255,0,88,4,2,0,0,0,77,77,77,77,255,0,72,4,2,0,0,0,79,79,79,79,255,0,64,4,2,0,0,0,82,82,82,82,255,0,40,4,2,0,0,0,84,84,84,84,255,0,32,4,2,0,0,0,87,87,87,87,255,0,208,3,2,0,0,0,89,89,89,89,255,0,176,3,2,0,0,0,92,92,92,92,255,0,168,3,2,0,0,0,94,94,94,94,255,0,160,3,2,0,0,0,97,97,97,97,255,0,152,3,2,0,0,0,99,99,99,99,255,0,144,3,2,0,0,0,10,10,10,10,255,0,128,3,2,0,0,0,102,102,102,102,255,0,120,3,2,0,0,0,105,105,105,105,255,0,96,3,2,0,0,0,107,107,107,107,255,0,88,3,2,0,0,0,110,110,110,110,255,0,48,3,2,0,0,0,112,112,112,112,255,0,32,3,2,0,0,0,115,115,115,115,255,0,16,3,2,0,0,0,117,117,117,117,255,0,0,3,2,0,0,0,120,120,120,120,255,0,248,2,2,0,0,0,122,122,122,122,255,0,240,2,2,0,0,0,125,125,125,125,255,0,184,2,2,0,0,0,13,13,13,13,255,0,168,2,2,0,0,0,127,127,127,127,255,0,144,2,2,0,0,0,130,130,130,130,255,0,128,2,2,0,0,0,133,133,133,133,255,0,8,2,2,0,0,0,135,135,135,135,255,0,248,1,2,0,0,0,138,138,138,138,255,0,240,1,2,0,0,0,140,140,140,140,255,0,216,1,2,0,0,0,143,143,143,143,255,0,208,1,2,0,0,0,145,145,145,145,255,0,200,1,2,0,0,0,148,148,148,148,255,0,176,1,2,0,0,0,150,150,150,150,255,0,168,1,2,0,0,0,15,15,15,15,255,0,144,1,2,0,0,0,153,153,153,153,255,0,136,1,2,0,0,0,156,156,156,156,255,0,112,1,2,0,0,0,158,158,158,158,255,0,88,1,2,0,0,0,161,161,161,161,255,0,64,1,2,0,0,0,163,163,163,163,255,0,56,1,2,0,0,0,166,166,166,166,255,0,48,1,2,0,0,0,168,168,168,168,255,0,40,1,2,0,0,0,171,171,171,171,255,0,16,1,2,0,0,0,173,173,173,173,255,0,8,1,2,0,0,0,176,176,176,176,255,0,240,0,2,0,0,0,18,18,18,18,255,0,232,0,2,0,0,0,179,179,179,179,255,0,208,0,2,0,0,0,181,181,181,181,255,0,176,0,2,0,0,0,184,184,184,184,255,0,168,0,2,0,0,0,186,186,186,186,255,0,160,0,2,0,0,0,189,189,189,189,255,0,128,0,2,0,0,0,191,191,191,191,255,0,120,0,2,0,0,0,194,194,194,194,255,0,104,0,2,0,0,0,196,196,196,196,255,0,96,0,2,0,0,0,199,199,199,199,255,0,72,0,2,0,0,0,201,201,201,201,255,0,64,0,2,0,0,0,20,20,20,20,255,0,24,0,2,0,0,0,204,204,204,204,255,0,248,255,1,0,0,0,207,207,207,207,255,0,240,255,1,0,0,0,209,209,209,209,255,0,232,255,1,0,0,0,212,212,212,212,255,0,224,255,1,0,0,0,214,214,214,214,255,0,216,255,1,0,0,0,217,217,217,217,255,0,200,255,1,0,0,0,219,219,219,219,255,0,192,255,1,0,0,0,222,222,222,222,255,0,168,255,1,0,0,0,224,224,224,224,255,0,152,255,1,0,0,0,227,227,227,227,255,0,136,255,1,0,0,0,23,23,23,23,255,0,112,255,1,0,0,0,229,229,229,229,255,0,104,255,1,0,0,0,232,232,232,232,255,0,96,255,1,0,0,0,235,235,235,235,255,0,88,255,1,0,0,0,237,237,237,237,255,0,80,255,1,0,0,0,240,240,240,240,255,0,64,255,1,0,0,0,242,242,242,242,255,0,56,255,1,0,0,0,245,245,245,245,255,0,32,255,1,0,0,0,247,247,247,247,255,0,8,255,1,0,0,0,250,250,250,250,255,0,240,254,1,0,0,0,252,252,252,252,255,0,176,254,1,0,85,255,255,0,255,0,255,0,168,254,1,0,85,255,255,0,255,0,255,0,160,254,1,0,85,255,238,0,238,0,255,0,152,254,1,0,85,255,205,0,205,0,255,0,144,254,1,0,85,255,139,0,139,0,255,0,120,254,1,0,59,208,255,173,255,47,255,0,112,254,1,0,0,0,192,192,192,192,255,0,88,254,1,0,0,0,0,0,0,0,255,0,80,254,1,0,0,0,3,3,3,3,255,0,56,254,1,0,0,0,26,26,26,26,255,0,24,254,1,0,0,0,255,255,255,255,255,0,8,254,1,0,0,0,28,28,28,28,255,0,0,254,1,0,0,0,31,31,31,31,255,0,248,253,1,0,0,0,33,33,33,33,255,0,240,253,1,0,0,0,36,36,36,36,255,0,216,253,1,0,0,0,38,38,38,38,255,0,200,253,1,0,0,0,41,41,41,41,255,0,176,253,1,0,0,0,43,43,43,43,255,0,168,253,1,0,0,0,46,46,46,46,255,0,120,253,1,0,0,0,48,48,48,48,255,0,104,253,1,0,0,0,5,5,5,5,255,0,96,253,1,0,0,0,51,51,51,51,255,0,88,253,1,0,0,0,54,54,54,54,255,0,80,253,1,0,0,0,56,56,56,56,255,0,72,253,1,0,0,0,59,59,59,59,255,0,56,253,1,0,0,0,61,61,61,61,255,0,48,253,1,0,0,0,64,64,64,64,255,0,24,253,1,0,0,0,66,66,66,66,255,0,16,253,1,0,0,0,69,69,69,69,255,0,208,252,1,0,0,0,71,71,71,71,255,0,144,252,1,0,0,0,74,74,74,74,255,0,136,252,1,0,0,0,8,8,8,8,255,0,128,252,1,0,0,0,77,77,77,77,255,0,88,252,1,0,0,0,79,79,79,79,255,0,80,252,1,0,0,0,82,82,82,82,255,0,64,252,1,0,0,0,84,84,84,84,255,0,56,252,1,0,0,0,87,87,87,87,255,0,32,252,1,0,0,0,89,89,89,89,255,0,24,252,1,0,0,0,92,92,92,92,255,0,232,251,1,0,0,0,94,94,94,94,255,0,224,251,1,0,0,0,97,97,97,97,255,0,208,251,1,0,0,0,99,99,99,99,255,0,192,251,1,0,0,0,10,10,10,10,255,0,184,251,1,0,0,0,102,102,102,102,255,0,176,251,1,0,0,0,105,105,105,105,255,0,160,251,1,0,0,0,107,107,107,107,255,0,144,251,1,0,0,0,110,110,110,110,255,0,120,251,1,0,0,0,112,112,112,112,255,0,112,251,1,0,0,0,115,115,115,115,255,0,56,251,1,0,0,0,117,117,117,117,255,0,48,251,1,0,0,0,120,120,120,120,255,0,40,251,1,0,0,0,122,122,122,122,255,0,24,251,1,0,0,0,125,125,125,125,255,0,16,251,1,0,0,0,13,13,13,13,255,0,8,251,1,0,0,0,127,127,127,127,255,0,248,250,1,0,0,0,130,130,130,130,255,0,240,250,1,0,0,0,133,133,133,133,255,0,216,250,1,0,0,0,135,135,135,135,255,0,208,250,1,0,0,0,138,138,138,138,255,0,160,250,1,0,0,0,140,140,140,140,255,0,152,250,1,0,0,0,143,143,143,143,255,0,120,250,1,0,0,0,145,145,145,145,255,0,112,250,1,0,0,0,148,148,148,148,255,0,104,250,1,0,0,0,150,150,150,150,255,0,96,250,1,0,0,0,15,15,15,15,255,0,72,250,1,0,0,0,153,153,153,153,255,0,64,250,1,0,0,0,156,156,156,156,255,0,40,250,1,0,0,0,158,158,158,158,255,0,232,249,1,0,0,0,161,161,161,161,255,0,192,249,1,0,0,0,163,163,163,163,255,0,128,249,1,0,0,0,166,166,166,166,255,0,120,249,1,0,0,0,168,168,168,168,255,0,112,249,1,0,0,0,171,171,171,171,255,0,104,249,1,0,0,0,173,173,173,173,255,0,88,249,1,0,0,0,176,176,176,176,255,0,72,249,1,0,0,0,18,18,18,18,255,0,64,249,1,0,0,0,179,179,179,179,255,0,40,249,1,0,0,0,181,181,181,181,255,0,16,249,1,0,0,0,184,184,184,184,255,0,216,248,1,0,0,0,186,186,186,186,255,0,200,248,1,0,0,0,189,189,189,189,255,0,192,248,1,0,0,0,191,191,191,191,255,0,184,248,1,0,0,0,194,194,194,194,255,0,176,248,1,0,0,0,196,196,196,196,255,0,168,248,1,0,0,0,199,199,199,199,255,0,152,248,1,0,0,0,201,201,201,201,255,0,144,248,1,0,0,0,20,20,20,20,255,0,120,248,1,0,0,0,204,204,204,204,255,0,112,248,1,0,0,0,207,207,207,207,255,0,40,248,1,0,0,0,209,209,209,209,255,0,32,248,1,0,0,0,212,212,212,212,255,0,24,248,1,0,0,0,214,214,214,214,255,0,16,248,1,0,0,0,217,217,217,217,255,0,8,248,1,0,0,0,219,219,219,219,255,0,0,248,1,0,0,0,222,222,222,222,255,0,240,247,1,0,0,0,224,224,224,224,255,0,232,247,1,0,0,0,227,227,227,227,255,0,208,247,1,0,0,0,23,23,23,23,255,0,184,247,1,0,0,0,229,229,229,229,255,0,120,247,1,0,0,0,232,232,232,232,255,0,112,247,1,0,0,0,235,235,235,235,255,0,104,247,1,0,0,0,237,237,237,237,255,0,96,247,1,0,0,0,240,240,240,240,255,0,88,247,1,0,0,0,242,242,242,242,255,0,80,247,1,0,0,0,245,245,245,245,255,0,64,247,1,0,0,0,247,247,247,247,255,0,56,247,1,0,0,0,250,250,250,250,255,0,32,247,1,0,0,0,252,252,252,252,255,0,16,247,1,0,85,15,255,240,255,240,255,0,240,246,1,0,85,15,255,240,255,240,255,0,224,246,1,0,85,15,238,224,238,224,255,0,208,246,1,0,85,14,205,193,205,193,255,0,176,246,1,0,85,14,139,131,139,131,255,0,168,246,1,0,233,150,255,255,105,180,255,0,152,246,1,0,234,145,255,255,110,180,255,0,120,246,1,0,235,141,238,238,106,167,255,0,104,246,1,0,236,135,205,205,96,144,255,0,72,246,1,0,234,148,139,139,58,98,255,0,56,246,1,0,0,140,205,205,92,92,255,0,16,246,1,0,0,148,255,255,106,106,255,0,0,246,1,0,0,148,238,238,99,99,255,0,240,245,1,0,0,149,205,205,85,85,255,0,224,245,1,0,0,148,139,139,58,58,255,0,216,245,1,0,194,255,130,75,0,130,255,0,208,245,1,0,42,0,255,255,255,254,0,0,192,245,1,0,42,15,255,255,255,240,255,0,184,245,1,0,42,15,255,255,255,240,255,0,160,245,1,0,42,15,238,238,238,224,255,0,128,245,1,0,42,14,205,205,205,193,255,0,240,244,1,0,42,14,139,139,139,131,255,0,224,244,1,0,38,106,240,240,230,140,255,0,216,244,1,0,39,112,255,255,246,143,255,0,208,244,1,0,39,112,238,238,230,133,255,0,184,244,1,0,39,111,205,205,198,115,255,0,176,244,1,0,39,111,139,139,134,78,255,0,152,244,1,0,170,20,250,230,230,250,255,0,136,244,1,0,240,15,255,255,240,245,255,0,104,244,1,0,240,15,255,255,240,245,255,0,32,244,1,0,239,15,238,238,224,229,255,0,216,243,1,0,240,14,205,205,193,197,255,0,200,243,1,0,239,14,139,139,131,134,255,0,176,243,1,0,64,255,252,124,252,0,255,0,144,243,1,0,38,49,255,255,250,205,255,0,128,243,1,0,38,49,255,255,250,205,255,0,112,243,1,0,37,50,238,238,233,191,255,0,88,243,1,0,38,49,205,205,201,165,255,0,64,243,1,0,39,49,139,139,137,112,255,0,32,243,1,0,137,63,230,173,216,230,255,0,16,243,1,0,138,64,255,191,239,255,255,0,152,242,1,0,138,64,238,178,223,238,255,0,136,242,1,0,138,63,205,154,192,205,255,0,120,242,1,0,137,64,139,104,131,139,255,0,80,242,1,0,0,119,240,240,128,128,255,0,64,242,1,0,127,31,255,224,255,255,255,0,48,242,1,0,127,31,255,224,255,255,255,0,24,242,1,0,127,31,238,209,238,238,255,0,8,242,1,0,127,31,205,180,205,205,255,0,232,241,1,0,127,31,139,122,139,139,255,0,216,241,1,0,35,115,238,238,221,130,255,0,176,241,1,0,35,116,255,255,236,139,255,0,160,241,1,0,35,115,238,238,220,130,255,0,120,241,1,0,35,115,205,205,190,112,255,0,104,241,1,0,35,115,139,139,129,76,255,0,80,241,1,0,42,40,250,250,250,210,255,0,64,241,1,0,0,0,211,211,211,211,255,0,32,241,1,0,0,0,211,211,211,211,255,0,208,240,1,0,248,73,255,255,182,193,255,0,176,240,1,0,249,81,255,255,174,185,255,0,144,240,1,0,248,81,238,238,162,173,255,0,112,240,1,0,249,80,205,205,140,149,255,0,88,240,1,0,249,80,139,139,95,101,255,0,72,240,1,0,12,132,255,255,160,122,255,0,56,240,1,0,12,132,255,255,160,122,255,0,40,240,1,0,11,132,238,238,149,114,255,0,24,240,1,0,12,133,205,205,129,98,255,0,200,239,1,0,12,133,139,139,87,66,255,0,184,239,1,0,125,209,178,32,178,170,255,0,152,239,1,0,143,117,250,135,206,250,255,0,136,239,1,0,143,79,255,176,226,255,255,0,96,239,1,0,143,79,238,164,211,238,255,0,72,239,1,0,142,79,205,141,182,205,255,0,56,239,1,0,143,78,139,96,123,139,255,0,32,239,1,0,175,143,255,132,112,255,255,0,16,239,1,0,148,56,153,119,136,153,255,0,0,239,1,0,148,56,153,119,136,153,255,0,232,238,1,0,151,52,222,176,196,222,255,0,216,238,1,0,151,53,255,202,225,255,255,0,184,238,1,0,151,53,238,188,210,238,255,0,144,238,1,0,151,53,205,162,181,205,255,0,104,238,1,0,150,53,139,110,123,139,255,0,88,238,1,0,42,31,255,255,255,224,255,0,56,238,1,0,42,31,255,255,255,224,255,0,40,238,1,0,42,31,238,238,238,209,255,0,24,238,1,0,42,31,205,205,205,180,255,0,8,238,1,0,42,31,139,139,139,122,255,0,240,237,1,0,85,192,205,50,205,50,255,0,232,237,1,0,21,20,250,250,240,230,255,0,208,237,1,0,212,255,255,255,0,255,255,0,176,237,1,0,212,255,255,255,0,255,255,0,160,237,1,0,212,255,238,238,0,238,255,0,144,237,1,0,212,255,205,205,0,205,255,0,128,237,1,0,212,255,139,139,0,139,255,0,120,237,1,0,239,185,176,176,48,96,255,0,112,237,1,0,228,203,255,255,52,179,255,0,104,237,1,0,228,203,238,238,48,167,255,0,88,237,1,0,228,204,205,205,41,144,255,0,80,237,1,0,228,203,139,139,28,98,255,0,40,237,1,0,113,128,205,102,205,170,255,0,24,237,1,0,170,255,205,0,0,205,255,0,232,236,1,0,204,152,211,186,85,211,255,0,216,236,1,0,203,153,255,224,102,255,255,0,200,236,1,0,203,153,238,209,95,238,255,0,184,236,1,0,203,153,205,180,82,205,255,0,152,236,1,0,203,154,139,122,55,139,255,0,136,236,1,0,183,124,219,147,112,219,255,0,104,236,1,0,183,125,255,171,130,255,255,0,88,236,1,0,183,125,238,159,121,238,255,0,56,236,1,0,183,125,205,137,104,205,255,0,40,236,1,0,183,124,139,93,71,139,255,0,240,235,1,0,103,169,179,60,179,113,255,0,224,235,1,0,176,143,238,123,104,238,255,0,200,235,1,0,111,255,250,0,250,154,255,0,184,235,1,0,125,167,209,72,209,204,255,0,168,235,1,0,228,228,199,199,21,133,255,0,152,235,1,0,170,198,112,25,25,112,255,0,128,235,1,0,106,9,255,245,255,250,255,0,112,235,1,0,4,30,255,255,228,225,255,0,80,235,1,0,4,30,255,255,228,225,255,0,56,235,1,0,4,30,238,238,213,210,255,0,176,234,1,0,3,29,205,205,183,181,255,0,144,234,1,0,5,29,139,139,125,123,255,0,128,234,1,0,26,73,255,255,228,181,255,0,112,234,1,0,25,81,255,255,222,173,255,0,96,234,1,0,25,81,255,255,222,173,255,0,80,234,1,0,25,82,238,238,207,161,255,0,56,234,1,0,25,82,205,205,179,139,255,0,40,234,1,0,25,82,139,139,121,94,255,0,16,234,1,0,170,255,128,0,0,128,255,0,0,234,1,0,170,255,128,0,0,128,255,0,232,233,1,0,42,0,255,255,255,254,0,0,224,233,1,0,27,23,253,253,245,230,255,0,192,233,1,0,56,192,142,107,142,35,255,0,168,233,1,0,56,193,255,192,255,62,255,0])
+.concat([144,233,1,0,56,192,238,179,238,58,255,0,128,233,1,0,56,192,205,154,205,50,255,0,8,233,1,0,56,192,139,105,139,34,255,0,248,232,1,0,27,255,255,255,165,0,255,0,208,232,1,0,27,255,255,255,165,0,255,0,160,232,1,0,27,255,238,238,154,0,255,0,120,232,1,0,27,255,205,205,133,0,255,0,112,232,1,0,27,255,139,139,90,0,255,0,96,232,1,0,11,255,255,255,69,0,255,0,64,232,1,0,11,255,255,255,69,0,255,0,48,232,1,0,11,255,238,238,64,0,255,0,32,232,1,0,11,255,205,205,55,0,255,0,8,232,1,0,11,255,139,139,37,0,255,0,0,232,1,0,214,123,218,218,112,214,255,0,232,231,1,0,214,124,255,255,131,250,255,0,224,231,1,0,214,124,238,238,122,233,255,0,208,231,1,0,214,124,205,205,105,201,255,0,200,231,1,0,213,124,139,139,71,137,255,0,176,231,1,0,38,72,238,238,232,170,255,0,160,231,1,0,85,100,251,152,251,152,255,0,144,231,1,0,85,101,255,154,255,154,255,0,128,231,1,0,85,100,238,144,238,144,255,0,96,231,1,0,85,100,205,124,205,124,255,0,80,231,1,0,85,100,139,84,139,84,255,0,48,231,1,0,127,67,238,175,238,238,255,0,32,231,1,0,127,68,255,187,255,255,255,0,16,231,1,0,127,68,238,174,238,238,255,0,216,230,1,0,127,68,205,150,205,205,255,0,200,230,1,0,127,67,139,102,139,139,255,0,184,230,1,0,241,124,219,219,112,147,255,0,168,230,1,0,241,125,255,255,130,171,255,0,152,230,1,0,241,125,238,238,121,159,255,0,128,230,1,0,241,125,205,205,104,137,255,0,104,230,1,0,241,124,139,139,71,93,255,0,72,230,1,0,26,41,255,255,239,213,255,0,56,230,1,0,20,70,255,255,218,185,255,0,40,230,1,0,20,70,255,255,218,185,255,0,8,230,1,0,19,69,238,238,203,173,255,0,248,229,1,0,19,69,205,205,175,149,255,0,232,229,1,0,20,69,139,139,119,101,255,0,224,229,1,0,20,176,205,205,133,63,255,0,216,229,1,0,247,63,255,255,192,203,255,0,200,229,1,0,245,73,255,255,181,197,255,0,192,229,1,0,245,73,238,238,169,184,255,0,168,229,1,0,245,74,205,205,145,158,255,0,160,229,1,0,245,73,139,139,99,108,255,0,144,229,1,0,212,70,221,221,160,221,255,0,136,229,1,0,212,68,255,255,187,255,255,0,128,229,1,0,212,68,238,238,174,238,255,0,120,229,1,0,212,68,205,205,150,205,255,0,112,229,1,0,212,67,139,139,102,139,255,0,96,229,1,0,132,59,230,176,224,230,255,0,80,229,1,0,196,221,240,160,32,240,255,0,72,229,1,0,191,207,255,155,48,255,255,0,48,229,1,0,192,207,238,145,44,238,255,0,24,229,1,0,192,207,205,125,38,205,255,0,16,229,1,0,192,207,139,85,26,139,255,0,8,229,1,0,0,255,255,255,0,0,255,0,0,229,1,0,0,255,255,255,0,0,255,0,248,228,1,0,0,255,238,238,0,0,255,0,240,228,1,0,0,255,205,205,0,0,255,0,232,228,1,0,0,255,139,139,0,0,255,0,208,228,1,0,0,61,188,188,143,143,255,0,192,228,1,0,0,62,255,255,193,193,255,0,160,228,1,0,0,62,238,238,180,180,255,0,136,228,1,0,0,62,205,205,155,155,255,0,112,228,1,0,0,62,139,139,105,105,255,0,96,228,1,0,159,181,225,65,105,225,255,0,80,228,1,0,159,183,255,72,118,255,255,0,64,228,1,0,159,183,238,67,110,238,255,0,48,228,1,0,159,182,205,58,95,205,255,0,24,228,1,0,159,183,139,39,64,139,255,0,248,227,1,0,17,220,139,139,69,19,255,0,240,227,1,0,4,138,250,250,128,114,255,0,216,227,1,0,9,150,255,255,140,105,255,0,208,227,1,0,9,150,238,238,130,98,255,0,200,227,1,0,9,150,205,205,112,84,255,0,192,227,1,0,9,150,139,139,76,57,255,0,176,227,1,0,19,154,244,244,164,96,255,0,160,227,1,0,103,170,139,46,139,87,255,0,144,227,1,0,103,171,255,84,255,159,255,0,128,227,1,0,103,171,238,78,238,148,255,0,104,227,1,0,103,171,205,67,205,128,255,0,88,227,1,0,103,170,139,46,139,87,255,0,56,227,1,0,17,16,255,255,245,238,255,0,40,227,1,0,17,16,255,255,245,238,255,0,152,226,1,0,18,17,238,238,229,222,255,0,128,226,1,0,18,17,205,205,197,191,255,0,112,226,1,0,18,16,139,139,134,130,255,0,104,226,1,0,13,183,160,160,82,45,255,0,96,226,1,0,13,184,255,255,130,71,255,0,88,226,1,0,13,184,238,238,121,66,255,0,72,226,1,0,13,184,205,205,104,57,255,0,64,226,1,0,13,185,139,139,71,38,255,0,40,226,1,0,139,108,235,135,206,235,255,0,24,226,1,0,144,120,255,135,206,255,255,0,248,225,1,0,144,120,238,126,192,238,255,0,232,225,1,0,144,120,205,108,166,205,255,0,192,225,1,0,145,119,139,74,112,139,255,0,168,225,1,0,175,143,205,106,90,205,255,0,128,225,1,0,175,144,255,131,111,255,255,0,112,225,1,0,175,144,238,122,103,238,255,0,88,225,1,0,175,144,205,105,89,205,255,0,64,225,1,0,175,144,139,71,60,139,255,0,32,225,1,0,148,56,144,112,128,144,255,0,16,225,1,0,149,56,255,198,226,255,255,0,192,224,1,0,149,56,238,185,211,238,255,0,176,224,1,0,148,57,205,159,182,205,255,0,160,224,1,0,149,56,139,108,123,139,255,0,136,224,1,0,148,56,144,112,128,144,255,0,128,224,1,0,0,5,255,255,250,250,255,0,120,224,1,0,0,5,255,255,250,250,255,0,104,224,1,0,0,5,238,238,233,233,255,0,96,224,1,0,0,4,205,205,201,201,255,0,72,224,1,0,0,3,139,139,137,137,255,0,56,224,1,0,106,255,255,0,255,127,255,0,40,224,1,0,106,255,255,0,255,127,255,0,24,224,1,0,106,255,238,0,238,118,255,0,248,223,1,0,106,255,205,0,205,102,255,0,232,223,1,0,106,255,139,0,139,69,255,0,216,223,1,0,146,155,180,70,130,180,255,0,200,223,1,0,146,156,255,99,184,255,255,0,176,223,1,0,146,156,238,92,172,238,255,0,152,223,1,0,146,156,205,79,148,205,255,0,120,223,1,0,147,155,139,54,100,139,255,0,112,223,1,0,24,84,210,210,180,140,255,0,104,223,1,0,20,176,255,255,165,79,255,0,96,223,1,0,20,176,238,238,154,73,255,0,80,223,1,0,20,176,205,205,133,63,255,0,72,223,1,0,20,176,139,139,90,43,255,0,64,223,1,0,212,29,216,216,191,216,255,0,48,223,1,0,212,30,255,255,225,255,255,0,24,223,1,0,212,30,238,238,210,238,255,0,8,223,1,0,212,29,205,205,181,205,255,0,208,222,1,0,212,29,139,139,123,139,255,0,200,222,1,0,6,184,255,255,99,71,255,0,192,222,1,0,6,184,255,255,99,71,255,0,168,222,1,0,6,184,238,238,92,66,255,0,160,222,1,0,6,184,205,205,79,57,255,0,152,222,1,0,6,185,139,139,54,38,255,0,128,222,1,0,42,0,255,255,255,254,0,0,112,222,1,0,123,182,224,64,224,208,255,0,88,222,1,0,129,255,255,0,245,255,255,0,72,222,1,0,129,255,238,0,229,238,255,0,40,222,1,0,129,255,205,0,197,205,255,0,24,222,1,0,129,255,139,0,134,139,255,0,0,222,1,0,212,115,238,238,130,238,255,0,232,221,1,0,227,215,208,208,32,144,255,0,216,221,1,0,235,193,255,255,62,150,255,0,200,221,1,0,235,192,238,238,58,140,255,0,184,221,1,0,235,192,205,205,50,120,255,0,168,221,1,0,235,192,139,139,34,82,255,0,152,221,1,0,27,68,245,245,222,179,255,0,144,221,1,0,27,69,255,255,231,186,255,0,120,221,1,0,27,68,238,238,216,174,255,0,112,221,1,0,27,68,205,205,186,150,255,0,88,221,1,0,27,67,139,139,126,102,255,0,80,221,1,0,0,0,255,255,255,255,255,0,64,221,1,0,0,0,245,245,245,245,255,0,56,221,1,0,42,255,255,255,255,0,255,0,48,221,1,0,42,255,255,255,255,0,255,0,40,221,1,0,42,255,238,238,238,0,255,0,24,221,1,0,42,255,205,205,205,0,255,0,16,221,1,0,42,255,139,139,139,0,255,0,240,220,1,0,56,192,205,154,205,50,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,219,1,0,30,0,0,0,16,188,1,0,252,1,0,0,96,186,1,0,56,1,0,0,32,184,1,0,126,1,0,0,64,182,1,0,104,0,0,0,8,180,1,0,150,0,0,0,16,205,1,0,146,2,0,0,88,178,1,0,206,1,0,0,208,176,1,0,8,1,0,0,120,175,1,0,160,2,0,0,200,173,1,0,202,1,0,0,40,172,1,0,76,0,0,0,248,170,1,0,150,2,0,0,152,169,1,0,4,2,0,0,184,166,1,0,246,0,0,0,56,165,1,0,6,0,0,0,72,163,1,0,6,0,0,0,240,161,1,0,216,0,0,0,112,160,1,0,90,1,0,0,8,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,219,1,0,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
+.concat([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
+.concat([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
+.concat([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,132,2,0,0,30,1,0,0,20,0,0,0,24,2,0,0,240,0,0,0,170,1,0,0,110,0,0,0,134,2,0,0,100,2,0,0,36,1,0,0,152,2,0,0,20,1,0,0,106,2,0,0,64,1,0,0,198,0,0,0,102,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,10,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,16,12,19,28,30,3,13,31,32,33,34,35,27,26,17,25,25,25,25,25,25,25,25,25,25,22,18,2,14,11,15,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,20,28,4,28,22,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,36,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,22,28,28,28,28,28,28,28,28,28,28,22,28,26,28,28,22,28,28,28,28,28,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,22,22,22,22,22,22,22,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,140,2,0,216,139,2,0,208,139,2,0,200,139,2,0,232,139,2,0,240,139,2,0,160,139,2,0,144,139,2,0,100,0,0,0,116,0,0,0,92,0,0,0,146,0,0,0,158,2,0,0,98,2,0,0,204,1,0,0,78,0,0,0,2,2,0,0,28,1,0,0,46,0,0,0,146,1,0,0,210,0,0,0,108,0,0,0,96,0,0,0,214,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,21,10,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,16,12,19,28,30,3,13,31,32,33,34,35,27,26,17,25,25,25,25,25,25,25,25,25,25,22,18,2,14,11,15,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,20,28,4,28,22,28,24,24,24,24,24,24,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,28,36,28,28,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,244,108,86,125,174,182,214,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,196,66,173,105,222,113,236,63,16,122,54,171,62,87,229,63,245,219,215,129,115,70,204,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,136,133,90,211,188,227,216,63,1,77,132,13,79,175,226,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,1,77,132,13,79,175,226,63,1,77,132,13,79,175,226,63,1,77,132,13,79,175,226,63,181,21,251,203,238,201,225,63,204,93,75,200,7,61,240,63,16,122,54,171,62,87,229,63,16,122,54,171,62,87,229,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,120,11,36,40,126,140,227,63,106,222,113,138,142,228,232,63,210,111,95,7,206,25,231,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,16,122,54,171,62,87,229,63,181,21,251,203,238,201,225,63,44,212,154,230,29,167,234,63,210,111,95,7,206,25,231,63,106,222,113,138,142,228,232,63,16,122,54,171,62,87,229,63,106,222,113,138,142,228,232,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,120,11,36,40,126,140,227,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,134,56,214,197,109,52,238,63,16,122,54,171,62,87,229,63,16,122,54,171,62,87,229,63,120,11,36,40,126,140,227,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,166,10,70,37,117,2,222,63,181,21,251,203,238,201,225,63,72,191,125,29,56,103,204,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,0,0,0,0,0,0,224,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,72,191,125,29,56,103,204,63,72,191,125,29,56,103,204,63,0,0,0,0,0,0,224,63,72,191,125,29,56,103,204,63,44,212,154,230,29,167,234,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,0,0,0,0,0,0,224,63,210,111,95,7,206,25,231,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,2,154,8,27,158,94,213,63,224,190,14,156,51,162,208,63,2,154,8,27,158,94,213,63,1,77,132,13,79,175,226,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,62,232,217,172,250,92,197,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,29,56,103,68,105,111,200,63,88,168,53,205,59,78,213,63,181,21,251,203,238,201,225,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,231,29,167,232,72,46,225,63,162,180,55,248,194,100,214,63,72,191,125,29,56,103,204,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,181,21,251,203,238,201,225,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,211,188,227,20,29,201,209,63,120,11,36,40,126,140,227,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,240,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,240,63,211,188,227,20,29,201,209,63,234,149,178,12,113,172,215,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,106,222,113,138,142,228,232,63,0,0,0,0,0,0,240,63,152,221,147,135,133,90,215,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,196,66,173,105,222,113,236,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,72,191,125,29,56,103,204,63,120,11,36,40,126,140,227,63,134,56,214,197,109,52,238,63,120,11,36,40,126,140,227,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,3,0,0,0,104,62,0,0,3,0,0,0,64,62,0,0,3,0,0,0,176,61,0,0,3,0,0,0,96,61,0,0,3,0,0,0,56,61,0,0,3,0,0,0,16,61,0,0,3,0,0,0,232,60,0,0,0,0,0,0,200,55,0,0,0,0,0,0,160,55,0,0,0,0,0,0,120,55,0,0,0,0,0,0,80,55,0,0,0,0,0,0,40,55,0,0,0,0,0,0,0,55,0,0,0,0,0,0,216,54,0,0,4,0,0,0,72,56,0,0,0,0,0,0,0,0,0,0,1,0,0,0,72,60,0,0,0,0,0,0,0,0,0,0,144,191,1,0,24,191,1,0,224,188,1,0,32,187,1,0,8,185,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,20,14,2,2,2,2,2,2,2,2,2,2,2,2,2,19,18,2,17,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,15,2,16,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,12,2,13,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,3,4,5,6,7,8,9,10,11,0,0,0,0,0,13,65,57,55,251,1,9,2,3,4,85,16,87,19,66,20,68,40,21,22,17,10,11,23,24,229,10,11,23,24,7,8,57,88,89,18,59,42,10,11,19,39,20,64,44,21,22,67,10,11,23,24,230,10,11,46,76,210,207,49,52,62,53,70,69,78,59,203,71,80,81,200,86,82,73,74,0,75,0,0,45,0,0,0,0,0,0,0,0,2,0,6,1,0,1,0,1,2,1,2,1,1,1,3,0,0,1,3,2,0,1,3,1,1,1,0,1,2,1,2,1,1,1,1,1,2,1,2,1,0,2,4,0,3,0,0,5,0,0,5,2,0,4,2,0,4,4,0,5,0,4,1,2,1,1,1,3,0,0,0,0,21,23,22,22,22,24,24,25,25,25,25,26,26,26,27,27,28,28,29,30,30,31,32,33,33,34,34,35,35,36,36,36,37,37,37,37,38,38,39,40,41,41,41,43,42,45,46,44,47,48,44,49,50,49,49,51,49,52,53,52,54,52,52,55,56,56,57,57,0,0,0,188,188,188,188,188,188,1,188,14,188,189,216,188,218,188,52,188,188,13,188,188,188,188,188,188,188,188,188,206,188,188,15,188,188,188,250,188,0,0,0,4,188,188,188,27,6,44,188,188,188,188,188,188,188,247,8,25,12,188,188,188,188,188,29,188,22,188,31,39,188,37,188,49,40,188,188,50,48,45,188,188,12,44,188,188,188,188,188,53,44,188,53,12,44,12,51,47,188,54,45,22,188,17,188,46,188,56,188,57,188,188,188,44,188,59,63,188,188,44,188,188,188,188,53,53,188,188,188,188,188,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,239,187,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,5,15,12,6,25,56,72,43,60,61,26,58,27,28,29,30,31,32,33,50,34,47,35,48,77,51,79,63,83,84,36,54,41,37,38,14,0,0,0,0,4,8,10,0,0,7,9,11,1,65,67,2,6,66,0,0,0,68,32,12,13,14,0,61,0,38,0,0,28,30,35,44,41,33,34,36,63,40,59,64,0,16,37,3,29,31,21,0,0,39,0,0,0,0,0,0,24,17,25,22,45,0,47,42,50,0,23,0,62,19,18,16,20,52,55,40,21,0,21,58,60,15,0,0,48,43,51,54,57,0,0,0,0,0,0,6,51,42,41,0,1,0,3,4,5,77,20,79,1,52,3,54,23,6,7,12,9,10,11,12,13,9,10,11,12,3,4,72,83,84,10,42,15,9,10,1,12,3,49,13,6,7,53,9,10,11,12,13,9,10,18,62,8,8,19,12,8,17,16,13,19,72,8,14,13,13,8,78,72,60,62,255,62,255,255,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,72,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,4,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,176,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,244,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,4,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,176,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,48,47,120,109,108,110,115,47,0,0,0,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,88,77,76,47,49,57,57,56,47,110,97,109,101,115,112,97,99,101,0,0,0,0,47,98,114,98,103,51,47,50,0,0,0,0,0,0,0,0,47,114,100,98,117,52,47,50,0,0,0,0,0,0,0,0,47,114,100,98,117,52,47,49,0,0,0,0,0,0,0,0,47,114,100,98,117,51,47,51,0,0,0,0,0,0,0,0,47,114,100,98,117,51,47,50,0,0,0,0,0,0,0,0,32,32,32,60,83,67,82,73,80,84,32,76,65,78,71,85,65,71,69,61,39,74,97,118,97,115,99,114,105,112,116,39,62,10,0,0,0,0,0,0,47,114,100,98,117,51,47,49,0,0,0,0,0,0,0,0,47,114,100,98,117,49,49,47,57,0,0,0,0,0,0,0,47,101,110,100,112,97,103,101,32,123,32,115,104,111,119,112,97,103,101,32,125,32,98,105,110,100,32,100,101,102,0,0,109,105,110,116,99,114,101,97,109,0,0,0,0,0,0,0,47,114,100,98,117,49,49,47,56,0,0,0,0,0,0,0,116,97,105,108,99,108,105,112,0,0,0,0,0,0,0,0,97,99,117,116,101,0,0,0,47,114,100,98,117,49,49,47,55,0,0,0,0,0,0,0,47,114,100,98,117,49,49,47,54,0,0,0,0,0,0,0,111,114,100,101,114,105,110,103,32,39,37,115,39,32,110,111,116,32,114,101,99,111,103,110,105,122,101,100,32,102,111,114,32,110,111,100,101,32,39,37,115,39,46,10,0,0,0,0,47,114,100,98,117,49,49,47,53,0,0,0,0,0,0,0,108,97,98,101,108,116,111,111,108,116,105,112,0,0,0,0,47,98,114,98,103,51,47,49,0,0,0,0,0,0,0,0,47,114,100,98,117,49,49,47,52,0,0,0,0,0,0,0,47,114,100,98,117,49,49,47,51,0,0,0,0,0,0,0,47,114,100,98,117,49,49,47,50,0,0,0,0,0,0,0,47,114,100,98,117,49,49,47,49,49,0,0,0,0,0,0,60,33,45,45,32,80,97,103,101,115,58,32,37,100,32,45,45,62,10,0,0,0,0,0,47,114,100,98,117,49,49,47,49,48,0,0,0,0,0,0,112,111,108,121,32,37,115,0,47,114,100,98,117,49,49,47,49,0,0,0,0,0,0,0,9,115,101,116,109,97,116,114,105,120,0,0,0,0,0,0,109,105,100,110,105,103,104,116,98,108,117,101,0,0,0,0,47,114,100,98,117,49,48,47,57,0,0,0,0,0,0,0,99,111,110,115,116,114,97,105,110,116,0,0,0,0,0,0,98,103,99,111,108,111,114,0,97,99,105,114,99,0,0,0,47,114,100,98,117,49,48,47,56,0,0,0,0,0,0,0,47,97,99,99,101,110,116,53,47,49,0,0,0,0,0,0,47,114,100,98,117,49,48,47,55,0,0,0,0,0,0,0,47,114,100,98,117,49,48,47,54,0,0,0,0,0,0,0,101,100,103,101,116,111,111,108,116,105,112,0,0,0,0,0,47,98,114,98,103,49,49,47,57,0,0,0,0,0,0,0,47,114,100,98,117,49,48,47,53,0,0,0,0,0,0,0,47,114,100,98,117,49,48,47,52,0,0,0,0,0,0,0,47,114,100,98,117,49,48,47,51,0,0,0,0,0,0,0,47,114,100,98,117,49,48,47,50,0,0,0,0,0,0,0,60,47,84,73,84,76,69,62,0,0,0,0,0,0,0,0,47,114,100,98,117,49,48,47,49,48,0,0,0,0,0,0,47,114,100,98,117,49,48,47,49,0,0,0,0,0,0,0,9,48,32,48,32,49,32,48,32,51,54,48,32,97,114,99,0,0,0,0,0,0,0,0,109,101,100,105,117,109,118,105,111,108,101,116,114,101,100,0,47,112,117,114,112,108,101,115,57,47,57,0,0,0,0,0,97,114,114,111,119,115,105,122,101,0,0,0,0,0,0,0,97,97,99,117,116,101,0,0,47,112,117,114,112,108,101,115,57,47,56,0,0,0,0,0,117,115,105,110,103,32,37,115,32,102,111,114,32,117,110,107,110,111,119,110,32,115,104,97,112,101,32,37,115,10,0,0,47,112,117,114,112,108,101,115,57,47,55,0,0,0,0,0,37,100,32,98,111,120,101,115,58,10,0,0,0,0,0,0,47,112,117,114,112,108,101,115,57,47,54,0,0,0,0,0,116,111,111,108,116,105,112,0,47,98,114,98,103,49,49,47,56,0,0,0,0,0,0,0,47,112,117,114,112,108,101,115,57,47,53,0,0,0,0,0,47,112,117,114,112,108,101,115,57,47,52,0,0,0,0,0,47,112,117,114,112,108,101,115,57,47,51,0,0,0,0,0,47,112,117,114,112,108,101,115,57,47,50,0,0,0,0,0,60,84,73,84,76,69,62,0,47,112,117,114,112,108,101,115,57,47,49,0,0,0,0,0,47,112,117,114,112,108,101,115,56,47,56,0,0,0,0,0,9,114,120,32,114,121,32,115,99,97,108,101,0,0,0,0,109,101,100,105,117,109,116,117,114,113,117,111,105,115,101,0,47,112,117,114,112,108,101,115,56,47,55,0,0,0,0,0,100,101,108,121,32,62,61,32,48,0,0,0,0,0,0,0,100,101,99,111,114,97,116,101,0,0,0,0,0,0,0,0,106,112,103,58,102,105,103,0,90,101,116,97,0,0,0,0,47,112,117,114,112,108,101,115,56,47,54,0,0,0,0,0,47,112,117,114,112,108,101,115,56,47,53,0,0,0,0,0,47,112,117,114,112,108,101,115,56,47,52,0,0,0,0,0,104,101,97,100,116,97,114,103,101,116,0,0,0,0,0,0,47,98,114,98,103,49,49,47,55,0,0,0,0,0,0,0,47,112,117,114,112,108,101,115,56,47,51,0,0,0,0,0,47,112,117,114,112,108,101,115,56,47,50,0,0,0,0,0,47,112,117,114,112,108,101,115,56,47,49,0,0,0,0,0,47,112,117,114,112,108,101,115,55,47,55,0,0,0,0,0,60,77,69,84,65,32,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,116,101,110,116,45,84,121,112,101,34,32,99,111,110,116,101,110,116,61,34,116,101,120,116,47,104,116,109,108,59,32,99,104,97,114,115,101,116,61,85,84,70,45,56,34,62,10,0,0,0,0,47,112,117,114,112,108,101,115,55,47,54,0,0,0,0,0,47,112,117,114,112,108,101,115,55,47,53,0,0,0,0,0,84,68,0,0,0,0,0,0,9,120,32,121,32,116,114,97,110,115,108,97,116,101,0,0,109,101,100,105,117,109,115,112,114,105,110,103,103,114,101,101,110,0,0,0,0,0,0,0,47,112,117,114,112,108,101,115,55,47,52,0,0,0,0,0,97,103,115,116,114,102,114,101,101,32,108,111,115,116,32,37,115,10,0,0,0,0,0,0,109,105,110,108,101,110,0,0,89,117,109,108,0,0,0,0,47,112,117,114,112,108,101,115,55,47,51,0,0,0,0,0,47,112,117,114,112,108,101,115,55,47,50,0,0,0,0,0,47,112,117,114,112,108,101,115,55,47,49,0,0,0,0,0,116,97,105,108,116,97,114,103,101,116,0,0,0,0,0,0,47,98,114,98,103,49,49,47,54,0,0,0,0,0,0,0,47,112,117,114,112,108,101,115,54,47,54,0,0,0,0,0,118,109,108,58,118,109,108,0,47,112,117,114,112,108,101,115,54,47,53,0,0,0,0,0,47,112,117,114,112,108,101,115,54,47,52,0,0,0,0,0,121,101,108,108,111,119,0,0,112,108,117,115,0,0,0,0,47,112,117,114,112,108,101,115,54,47,51,0,0,0,0,0,60,72,69,65,68,62,0,0,47,112,117,114,112,108,101,115,54,47,50,0,0,0,0,0,47,112,117,114,112,108,101,115,54,47,49,0,0,0,0,0,9,110,101,119,112,97,116,104,0,0,0,0,0,0,0,0,109,101,100,105,117,109,115,108,97,116,101,98,108,117,101,0,47,112,117,114,112,108,101,115,53,47,53,0,0,0,0,0,108,97,98,101,108,97,110,103,108,101,0,0,0,0,0,0,89,97,99,117,116,101,0,0,47,112,117,114,112,108,101,115,53,47,52,0,0,0,0,0,47,112,117,114,112,108,101,115,53,47,51,0,0,0,0,0,58,32,0,0,0,0,0,0,47,112,117,114,112,108,101,115,53,47,50,0,0,0,0,0,108,97,98,101,108,116,97,114,103,101,116,0,0,0,0,0,47,112,117,114,112,108,101,115,53,47,49,0,0,0,0,0,47,98,114,98,103,49,49,47,53,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,112,117,114,112,108,101,115,52,47,52,0,0,0,0,0,47,112,117,114,112,108,101,115,52,47,51,0,0,0,0,0,47,112,117,114,112,108,101,115,52,47,50,0,0,0,0,0,60,47,66,79,68,89,62,10,60,47,72,84,77,76,62,10,0,0,0,0,0,0,0,0,85,82,87,32,71,111,116,104,105,99,32,76,0,0,0,0,47,112,117,114,112,108,101,115,52,47,49,0,0,0,0,0,47,112,117,114,112,108,101,115,51,47,51,0,0,0,0,0,100,117,112,108,105,99,97,116,101,32,97,116,116,114,105,98,117,116,101,0,0,0,0,0,9,109,97,116,114,105,120,32,99,117,114,114,101,110,116,109,97,116,114,105,120,0,0,0,109,101,100,105,117,109,115,101,97,103,114,101,101,110,0,0,47,112,117,114,112,108,101,115,51,47,50,0,0,0,0,0,108,97,98,101,108,100,105,115,116,97,110,99,101,0,0,0,88,105,0,0,0,0,0,0,47,112,117,114,112,108,101,115,51,47,49,0,0,0,0,0,38,103,116,59,0,0,0,0,47,112,117,114,100,57,47,57,0,0,0,0,0,0,0,0,112,108,97,105,110,45,101,120,116,58,100,111,116,0,0,0,47,112,117,114,100,57,47,56,0,0,0,0,0,0,0,0,101,100,103,101,116,97,114,103,101,116,0,0,0,0,0,0,37,115,32,45,62,32,37,115,58,32,104,101,97,100,32,105,115,32,105,110,115,105,100,101,32,116,97,105,108,32,99,108,117,115,116,101,114,32,37,115,10,0,0,0,0,0,0,0,47,112,117,114,100,57,47,55,0,0,0,0,0,0,0,0,110,111,32,109,101,109,111,114,121,32,102,114,111,109,32,122,109,97,108,108,111,99,40,41,10,0,0,0,0,0,0,0,47,98,114,98,103,49,49,47,52,0,0,0,0,0,0,0,109,101,109,111,114,121,32,97,108,108,111,99,97,116,105,111,110,32,102,97,105,108,117,114,101,10,0,0,0,0,0,0,47,112,117,114,100,57,47,54,0,0,0,0,0,0,0,0,32,123,10,0,0,0,0,0,99,97,110,110,111,116,32,109,97,108,108,111,99,32,112,110])
+.concat([108,115,0,0,0,0,0,0,47,112,117,114,100,57,47,53,0,0,0,0,0,0,0,0,112,111,115,0,0,0,0,0,47,112,117,114,100,57,47,52,0,0,0,0,0,0,0,0,60,33,45,45,32,105,110,115,101,114,116,32,97,110,121,32,111,116,104,101,114,32,78,79,78,45,73,69,32,104,116,109,108,32,99,111,110,116,101,110,116,32,104,101,114,101,32,45,45,62,10,0,0,0,0,0,95,76,84,88,95,108,105,98,114,97,114,121,0,0,0,0,84,82,65,73,76,69,82,0,47,112,117,114,100,57,47,51,0,0,0,0,0,0,0,0,47,112,117,114,100,57,47,50,0,0,0,0,0,0,0,0,9,47,120,32,101,120,99,104,32,100,101,102,0,0,0,0,109,101,100,105,117,109,112,117,114,112,108,101,0,0,0,0,47,112,117,114,100,57,47,49,0,0,0,0,0,0,0,0,108,97,98,101,108,102,111,110,116,99,111,108,111,114,0,0,98,108,97,99,107,0,0,0,85,117,109,108,0,0,0,0,47,112,117,114,100,56,47,56,0,0,0,0,0,0,0,0,47,112,117,114,100,56,47,55,0,0,0,0,0,0,0,0,47,112,117,114,100,56,47,54,0,0,0,0,0,0,0,0,116,97,114,103,101,116,0,0,47,112,117,114,100,56,47,53,0,0,0,0,0,0,0,0,47,98,114,98,103,49,49,47,51,0,0,0,0,0,0,0,47,112,117,114,100,56,47,52,0,0,0,0,0,0,0,0,47,112,117,114,100,56,47,51,0,0,0,0,0,0,0,0,47,112,117,114,100,56,47,50,0,0,0,0,0,0,0,0,60,68,73,86,32,105,100,61,39,95,110,111,116,86,77,76,50,95,39,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,34,62,10,0,0,0,0,0,0,0,0,47,112,117,114,100,56,47,49,0,0,0,0,0,0,0,0,115,111,117,114,99,101,0,0,47,112,117,114,100,55,47,55,0,0,0,0,0,0,0,0,9,47,121,32,101,120,99,104,32,100,101,102,0,0,0,0,109,101,100,105,117,109,111,114,99,104,105,100,0,0,0,0,105,110,0,0,0,0,0,0,47,112,117,114,100,55,47,54,0,0,0,0,0,0,0,0,108,97,98,101,108,102,111,110,116,110,97,109,101,0,0,0,104,112,0,0,0,0,0,0,110,111,0,0,0,0,0,0,69,110,99,111,100,105,110,103,86,101,99,116,111,114,32,52,53,32,47,104,121,112,104,101,110,32,112,117,116,0,0,0,85,112,115,105,108,111,110,0,47,112,117,114,100,55,47,53,0,0,0,0,0,0,0,0,47,112,117,114,100,55,47,52,0,0,0,0,0,0,0,0,102,105,108,108,101,100,0,0,47,112,117,114,100,55,47,51,0,0,0,0,0,0,0,0,104,101,97,100,85,82,76,0,47,112,117,114,100,55,47,50,0,0,0,0,0,0,0,0,47,98,114,98,103,49,49,47,50,0,0,0,0,0,0,0,47,112,117,114,100,55,47,49,0,0,0,0,0,0,0,0,47,112,117,114,100,54,47,54,0,0,0,0,0,0,0,0,47,112,117,114,100,54,47,53,0,0,0,0,0,0,0,0,60,72,50,62,83,111,114,114,121,44,32,116,104,105,115,32,100,105,97,103,114,97,109,32,119,105,108,108,32,111,110,108,121,32,100,105,115,112,108,97,121,32,99,111,114,114,101,99,116,108,121,32,111,110,32,73,110,116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,32,53,32,40,97,110,100,32,117,112,41,32,98,114,111,119,115,101,114,115,46,60,47,72,50,62,10,0,0,0,0,0,47,112,117,114,100,54,47,52,0,0,0,0,0,0,0,0,47,112,117,114,100,54,47,51,0,0,0,0,0,0,0,0,9,47,114,120,32,101,120,99,104,32,100,101,102,0,0,0,109,101,100,105,117,109,98,108,117,101,0,0,0,0,0,0,47,112,117,114,100,54,47,50,0,0,0,0,0,0,0,0,108,97,98,101,108,102,111,110,116,115,105,122,101,0,0,0,85,103,114,97,118,101,0,0,47,112,117,114,100,54,47,49,0,0,0,0,0,0,0,0,47,112,117,114,100,53,47,53,0,0,0,0,0,0,0,0,47,112,117,114,100,53,47,52,0,0,0,0,0,0,0,0,104,101,97,100,104,114,101,102,0,0,0,0,0,0,0,0,112,101,110,0,0,0,0,0,47,112,117,114,100,53,47,51,0,0,0,0,0,0,0,0,47,98,114,98,103,49,49,47,49,49,0,0,0,0,0,0,47,112,117,114,100,53,47,50,0,0,0,0,0,0,0,0,47,112,117,114,100,53,47,49,0,0,0,0,0,0,0,0,47,112,117,114,100,52,47,52,0,0,0,0,0,0,0,0,60,33,45,45,32,116,104,105,115,32,115,104,111,117,108,100,32,111,110,108,121,32,100,105,115,112,108,97,121,32,111,110,32,78,79,78,45,73,69,32,98,114,111,119,115,101,114,115,32,45,45,62,10,0,0,0,47,112,117,114,100,52,47,51,0,0,0,0,0,0,0,0,47,112,117,114,100,52,47,50,0,0,0,0,0,0,0,0,9,47,114,121,32,101,120,99,104,32,100,101,102,0,0,0,109,101,100,105,117,109,97,113,117,97,109,97,114,105,110,101,0,0,0,0,0,0,0,0,47,112,117,114,100,52,47,49,0,0,0,0,0,0,0,0,116,97,105,108,108,97,98,101,108,0,0,0,0,0,0,0,85,99,105,114,99,0,0,0,47,112,117,114,100,51,47,51,0,0,0,0,0,0,0,0,47,112,117,114,100,51,47,50,0,0,0,0,0,0,0,0,47,112,117,114,100,51,47,49,0,0,0,0,0,0,0,0,116,97,105,108,85,82,76,0,111,114,100,101,114,105,110,103,32,39,37,115,39,32,110,111,116,32,114,101,99,111,103,110,105,122,101,100,46,10,0,0,47,112,117,111,114,57,47,57,0,0,0,0,0,0,0,0,47,98,114,98,103,49,49,47,49,48,0,0,0,0,0,0,47,112,117,111,114,57,47,56,0,0,0,0,0,0,0,0,47,112,117,111,114,57,47,55,0,0,0,0,0,0,0,0,47,112,117,111,114,57,47,54,0,0,0,0,0,0,0,0,60,68,73,86,32,105,100,61,39,95,110,111,116,86,77,76,49,95,39,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,34,62,10,0,0,0,0,0,0,0,0,47,112,117,111,114,57,47,53,0,0,0,0,0,0,0,0,47,112,117,111,114,57,47,52,0,0,0,0,0,0,0,0,99,105,114,99,108,101,32,37,115,32,37,100,44,37,100,44,37,100,10,0,0,0,0,0,109,101,109,111,114,121,32,101,120,104,97,117,115,116,101,100,0,0,0,0,0,0,0,0,47,101,108,108,105,112,115,101,95,112,97,116,104,32,123,0,109,97,114,111,111,110,0,0,47,112,117,111,114,57,47,51,0,0,0,0,0,0,0,0,104,101,97,100,108,97,98,101,108,0,0,0,0,0,0,0,85,97,99,117,116,101,0,0,47,112,117,111,114,57,47,50,0,0,0,0,0,0,0,0,47,97,99,99,101,110,116,52,47,52,0,0,0,0,0,0,47,112,117,111,114,57,47,49,0,0,0,0,0,0,0,0,47,112,117,111,114,56,47,56,0,0,0,0,0,0,0,0,116,97,105,108,104,114,101,102,0,0,0,0,0,0,0,0,47,112,117,111,114,56,47,55,0,0,0,0,0,0,0,0,47,98,114,98,103,49,49,47,49,0,0,0,0,0,0,0,47,112,117,111,114,56,47,54,0,0,0,0,0,0,0,0,47,112,117,111,114,56,47,53,0,0,0,0,0,0,0,0,47,112,117,111,114,56,47,52,0,0,0,0,0,0,0,0,60,33,45,45,32,105,110,115,101,114,116,32,97,110,121,32,111,116,104,101,114,32,104,116,109,108,32,99,111,110,116,101,110,116,32,104,101,114,101,32,45,45,62,10,0,0,0,0,47,112,117,111,114,56,47,51,0,0,0,0,0,0,0,0,47,112,117,111,114,56,47,50,0,0,0,0,0,0,0,0,9,9,99,108,111,115,101,112,97,116,104,0,0,0,0,0,109,97,103,101,110,116,97,0,47,112,117,111,114,56,47,49,0,0,0,0,0,0,0,0,97,114,114,111,119,116,97,105,108,0,0,0,0,0,0,0,84,104,101,116,97,0,0,0,47,112,117,111,114,55,47,55,0,0,0,0,0,0,0,0,119,0,0,0,0,0,0,0,47,112,117,111,114,55,47,54,0,0,0,0,0,0,0,0,105,110,32,99,104,101,99,107,112,97,116,104,44,32,101,110,100,32,112,111,114,116,32,110,111,116,32,105,110,32,108,97,115,116,32,98,111,120,10,0,47,112,117,111,114,55,47,53,0,0,0,0,0,0,0,0,108,97,98,101,108,85,82,76,0,0,0,0,0,0,0,0,47,112,117,111,114,55,47,52,0,0,0,0,0,0,0,0,47,98,114,98,103,49,48,47,57,0,0,0,0,0,0,0,47,112,117,111,114,55,47,51,0,0,0,0,0,0,0,0,47,112,117,111,114,55,47,50,0,0,0,0,0,0,0,0,47,112,117,111,114,55,47,49,0,0,0,0,0,0,0,0,60,68,73,86,32,105,100,61,39,95,86,77,76,50,95,39,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,118,105,115,105,98,105,108,105,116,121,58,104,105,100,100,101,110,34,62,10,0,0,47,112,117,111,114,54,47,54,0,0,0,0,0,0,0,0,47,112,117,111,114,54,47,53,0,0,0,0,0,0,0,0,9,9,112,111,112,32,110,101,103,32,48,32,114,108,105,110,101,116,111,0,0,0,0,0,108,105,110,101,110,0,0,0,47,112,117,111,114,54,47,52,0,0,0,0,0,0,0,0,100,101,108,120,32,62,61,32,48,0,0,0,0,0,0,0,97,114,114,111,119,104,101,97,100,0,0,0,0,0,0,0,106,112,101,58,102,105,103,0,47,112,117,111,114,54,47,51,0,0,0,0,0,0,0,0,84,97,117,0,0,0,0,0,47,112,117,111,114,54,47,50,0,0,0,0,0,0,0,0,47,112,117,111,114,54,47,49,0,0,0,0,0,0,0,0,108,97,98,101,108,104,114,101,102,0,0,0,0,0,0,0,47,112,117,111,114,53,47,53,0,0,0,0,0,0,0,0,47,98,114,98,103,49,48,47,56,0,0,0,0,0,0,0,47,112,117,111,114,53,47,52,0,0,0,0,0,0,0,0,47,112,117,111,114,53,47,51,0,0,0,0,0,0,0,0,47,112,117,111,114,53,47,50,0,0,0,0,0,0,0,0,60,47,68,73,86,62,10,0,69,68,95,116,111,95,118,105,114,116,40,101,41,32,61,61,32,78,85,76,76,0,0,0,47,112,117,111,114,53,47,49,0,0,0,0,0,0,0,0,47,112,117,111,114,52,47,52,0,0,0,0,0,0,0,0,84,72,0,0,0,0,0,0,9,9,48,32,101,120,99,104,32,114,108,105,110,101,116,111,0,0,0,0,0,0,0,0,108,105,109,101,103,114,101,101,110,0,0,0,0,0,0,0,47,112,117,111,114,52,47,51,0,0,0,0,0,0,0,0,100,105,114,0,0,0,0,0,47,112,117,111,114,52,47,50,0,0,0,0,0,0,0,0,84,72,79,82,78,0,0,0,47,112,117,111,114,52,47,49,0,0,0,0,0,0,0,0,47,112,117,111,114,51,47,51,0,0,0,0,0,0,0,0,101,100,103,101,85,82,76,0,47,112,117,111,114,51,47,50,0,0,0,0,0,0,0,0,47,98,114,98,103,49,48,47,55,0,0,0,0,0,0,0,118,109,108,0,0,0,0,0,47,112,117,111,114,51,47,49,0,0,0,0,0,0,0,0,47,112,117,111,114,49,49,47,57,0,0,0,0,0,0,0,47,112,117,111,114,49,49,47,56,0,0,0,0,0,0,0,60,47,118,58,103,114,111,117,112,62,10,0,0,0,0,0,119,104,105,116,101,0,0,0,75,80,95,68,111,119,110,0,47,112,117,111,114,49,49,47,55,0,0,0,0,0,0,0,47,112,117,111,114,49,49,47,54,0,0,0,0,0,0,0,110,111,100,101,0,0,0,0,9,9,101,120,99,104,32,48,32,114,108,105,110,101,116,111,0,0,0,0,0,0,0,0,47,112,117,111,114,49,49,47,53,0,0,0,0,0,0,0,108,105,109,101,0,0,0,0,108,97,98,101,108,102,108,111,97,116,0,0,0,0,0,0,47,112,117,111,114,49,49,47,52,0,0,0,0,0,0,0,83,105,103,109,97,0,0,0,47,112,117,111,114,49,49,47,51,0,0,0,0,0,0,0,47,112,117,111,114,49,49,47,50,0,0,0,0,0,0,0,101,100,103,101,104,114,101,102,0,0,0,0,0,0,0,0,117,115,101,114,111,117,116,58,32,99,111,117,108,100,32,110,111,116,32,97,108,108,111,99,97,116,101,32,109,101,109,111,114,121,10,0,0,0,0,0,47,112,117,111,114,49,49,47,49,49,0,0,0,0,0,0,47,98,114,98,103,49,48,47,54,0,0,0,0,0,0,0,47,112,117,111,114,49,49,47,49,48,0,0,0,0,0,0,97,117,120,103,0,0,0,0,47,112,117,111,114,49,49,47,49,0,0,0,0,0,0,0,47,112,117,111,114,49,48,47,57,0,0,0,0,0,0,0,62,10,0,0,0,0,0,0,65,118,97,110,116,71,97,114,100,101,45,66,111,111,107,0,47,112,117,111,114,49,48,47,56,0,0,0,0,0,0,0,47,112,117,111,114,49,48,47,55,0,0,0,0,0,0,0,109,105,115,109,97,116,99,104,101,100,32,116,97,103,0,0,9,9,50,32,99,111,112,121,0,0,0,0,0,0,0,0,47,112,117,111,114,49,48,47,54,0,0,0,0,0,0,0,108,105,103,104,116,121,101,108,108,111,119,0,0,0,0,0,119,101,105,103,104,116,0,0,47,112,117,111,114,49,48,47,53,0,0,0,0,0,0,0,83,99,97,114,111,110,0,0,38,108,116,59,0,0,0,0,47,112,117,111,114,49,48,47,52,0,0,0,0,0,0,0,112,108,97,105,110,58,100,111,116,0,0,0,0,0,0,0,47,112,117,111,114,49,48,47,51,0,0,0,0,0,0,0,85,82,76,0,0,0,0,0,37,115,32,45,62,32,37,115,58,32,116,97,105,108,32,110,111,116,32,105,110,115,105,100,101,32,116,97,105,108,32,99,108,117,115,116,101,114,32,37,115,10,0,0,0,0,0,0,47,112,117,111,114,49,48,47,50,0,0,0,0,0,0,0,47,98,114,98,103,49,48,47,53,0,0,0,0,0,0,0,47,112,117,111,114,49,48,47,49,48,0,0,0,0,0,0,37,100,32,116,101,120,116,115,10,0,0,0,0,0,0,0,95,97,110,111,110,121,109,111,117,115,0,0,0,0,0,0,99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,100,113,46,112,110,108,115,0,0,48,0,0,0,0,0,0,0,47,112,117,111,114,49,48,47,49,0,0,0,0,0,0,0,115,116,111,112,10,0,0,0,47,112,117,98,117,103,110,57,47,57,0,0,0,0,0,0,32,116,97,114,103,101,116,61,34,37,115,34,0,0,0,0,69,78,68,0,0,0,0,0,47,112,117,98,117,103,110,57,47,56,0,0,0,0,0,0,47,112,117,98,117,103,110,57,47,55,0,0,0,0,0,0,9,9,109,111,118,101,116,111,0,0,0,0,0,0,0,0,47,112,117,98,117,103,110,57,47,54,0,0,0,0,0,0,108,105,103,104,116,115,116,101,101,108,98,108,117,101,0,0,122,0,0,0,0,0,0,0,98,105,115,113,117,101,0,0,47,112,117,98,117,103,110,57,47,53,0,0,0,0,0,0,82,104,111,0,0,0,0,0,47,112,117,98,117,103,110,57,47,52,0,0,0,0,0,0,47,112,117,98,117,103,110,57,47,51,0,0,0,0,0,0,104,114,101,102,0,0,0,0,47,112,117,98,117,103,110,57,47,50,0,0,0,0,0,0,47,98,114,98,103,49,48,47,52,0,0,0,0,0,0,0,47,112,117,98,117,103,110,57,47,49,0,0,0,0,0,0,47,112,117,98,117,103,110,56,47,56,0,0,0,0,0,0,46,46,46,32,37,115,32,46,46,46,10,0,0,0,0,0,47,112,117,98,117,103,110,56,47,55,0,0,0,0,0,0,32,116,105,116,108,101,61,34,37,115,34,0,0,0,0,0,47,112,117,98,117,103,110,56,47,54,0,0,0,0,0,0,47,112,117,98,117,103,110,56,47,53,0,0,0,0,0,0,109,105,110,0,0,0,0,0,9,9,52,32,50,32,114,111,108,108,0,0,0,0,0,0,47,112,117,98,117,103,110,56,47,52,0,0,0,0,0,0,114,101,109,105,110,99,114,111,115,115,0,0,0,0,0,0,108,105,103,104,116,115,108,97,116,101,103,114,101,121,0,0,104,101,105,103,104,116,61,34,37,108,102,37,50,115,34,0,118,101,114,116,105,99,101,115,0,0,0,0,0,0,0,0,110,115,108,105,109,105,116,0,102,97,108,115,101,0,0,0,73,83,79,76,97,116,105,110,49,69,110,99,111,100,105,110,103,32,48,32,50,53,53,32,103,101,116,105,110,116,101,114,118,97,108,32,112,117,116,105,110,116,101,114,118,97,108,0,47,112,117,98,117,103,110,56,47,51,0,0,0,0,0,0,80,115,105,0,0,0,0,0,47,112,117,98,117,103,110,56,47,50,0,0,0,0,0,0,115,101,116,108,105,110,101,119,105,100,116,104,0,0,0,0,47,112,117,98,117,103,110,56,47,49,0,0,0,0,0,0,78,111,32,99,111,109,109,97,32,105,110,32,99,111,108,111,114,32,115,112,101,99,32,34,37,115,34,32,105,110,32,99,111,108,111,114,32,97,116,116,114,105,98,117,116,101,32,0,47,112,117,98,117,103,110,55,47,55,0,0,0,0,0,0,47,98,114,98,103,49,48,47,51,0,0,0,0,0,0,0,47,112,117,98,117,103,110,55,47,54,0,0,0,0,0,0,47,112,117,98,117,103,110,55,47,53,0,0,0,0,0,0,47,62,10,0,0,0,0,0,47,112,117,98,117,103,110,55,47,52,0,0,0,0,0,0,67,69,76,76,83,66,79,82,68,69,82,0,0,0,0,0,35,37,50,120,37,50,120,37,50,120,37,50,120,0,0,0,32,104,114,101,102,61,34,37,115,34,0,0,0,0,0,0,47,112,117,98,117,103,110,55,47,51,0,0,0,0,0,0,47,112,117,98,117,103,110,55,47,50,0,0,0,0,0,0,47,98,111,120,112,114,105,109,32,123,9,9,9,9,37,32,120,99,111,114,110,101,114,32,121,99,111,114,110,101,114,32,120,115,105,122,101,32,121,115,105,122,101,0,0,0,0,0,47,112,117,98,117,103,110,55,47,49,0,0,0,0,0,0,108,105,103,104,116,115,108,97,116,101,103,114,97,121,0,0,99,111,109,109,101,110,116,0,47,112,117,98,117,103,110,54,47,54,0,0,0,0,0,0,80,114,105,109,101,0,0,0,47,112,117,98,117,103,110,54,47,53,0,0,0,0,0,0,47,112,117,98,117,103,110,54,47,52,0,0,0,0,0,0,73,108,108,101,103,97,108,32,108,101,110,103,116,104,32,118,97,108,117,101,32,105,110,32,34,37,115,34,32,99,111,108,111,114,32,97,116,116,114,105,98,117,116,101,32,0,0,0,118,101,101,0,0,0,0,0,47,112,117,98,117,103,110,54,47,51,0,0,0,0,0,0,47,98,114,98,103,49,48,47,50,0,0,0,0,0,0,0,47,112,117,98,117,103,110,54,47,50,0,0,0,0,0,0,115,112,108,105,110,101,115,46,99,0,0,0,0,0,0,0,110,111,100,101,32,39,37,115,39,44,32,103,114,97,112,104,32,39,37,115,39,32,115,105,122,101,32,116,111,111,32,115,109,97,108,108,32,102,111,114,32,108,97,98,101,108,10,0,47,112,117,98,117,103,110,54,47,49,0,0,0,0,0,0,34,32,119,105,100,116,104,61,34,37,103,112,120,34,32,104,101,105,103,104,116,61,34,37,103,112,120,34,32,112,114,101,115,101,114,118,101,65,115,112,101,99,116,82,97,116,105,111,61,34,120,77,105,110,89,77,105,110,32,109,101,101,116,34,32,120,61,34,37,103,34,32,121,61,34,37,103,34,0,0,73,108,108,101,103,97,108,32,118,97,108,117,101,32,37,115,32,102,111,114,32,83,84,89,76,69,32,45,32,105,103,110,111,114,101,100,10,0,0,0,47,112,117,98,117,103,110,53,47,53,0,0,0,0,0,0,60,97,0,0,0,0,0,0,47,112,117,98,117,103,110,53,47,52,0,0,0,0,0,0,47,112,117,98,117,103,110,53,47,51,0,0,0,0,0,0,9,103,114,101,115,116,111,114,101,0,0,0,0,0,0,0,47,112,117,98,117,103,110,53,47,50,0,0,0,0,0,0,108,105,103,104,116,115,107,121,98,108,117,101,0,0,0,0,103,114,111,117,112,0,0,0,47,112,117,98,117,103,110,53,47,49,0,0,0,0,0,0,80,105,0,0,0,0,0,0,47,112,117,98,117,103,110,52,47,52,0,0,0,0,0,0,47,112,117,98,117,103,110,52,47,51,0,0,0,0,0,0,48,45,108,101,110,103,116,104,32,105,110,32,99,111,108,111,114,32,115,112,101,99,32,34,37,115,34,10,0,0,0,0,47,112,117,98,117,103,110,52,47,50,0,0,0,0,0,0,47,98,114,98,103,49,48,47,49,48,0,0,0,0,0,0,105,110,0,0,0,0,0,0,47,112,117,98,117,103,110,52,47,49,0,0,0,0,0,0,108,97,98,101,108,108,111,99,0,0,0,0,0,0,0,0,47,112,117,98,117,103,110,51,47,51,0,0,0,0,0,0,32,116,114,97,110,115,102,111,114,109,61,34,114,111,116,97,116,101,40,37,100,32,37,103,32,37,103,41,34,0,0,0,79,85,78,68,69,68,0,0,47,112,117,98,117,103,110,51,47,50,0,0,0,0,0,0,60,47,97,62,10,0,0,0,47,112,117,98,117,103,110,51,47,49,0,0,0,0,0,0,47,112,117,98,117,57,47,57,0,0,0,0,0,0,0,0,9,9,125,32,105,102,0,0,47,112,117,98,117,57,47,56,0,0,0,0,0,0,0,0,102,108,97,116,46,99,0,0,108,105,103,104,116,115,101,97,103,114,101,101,110,0,0,0,108,97,121,101,114,0,0,0,114,101,99,116,32,37,115,32,37,100,44,37,100,32,37,100,44,37,100,10,0,0,0,0,47,112,117,98,117,57,47,55,0,0,0,0,0,0,0,0,80,104,105,0,0,0,0,0,47,97,99,99,101,110,116,52,47,51,0,0,0,0,0,0,47,112,117,98,117,57,47,54,0,0,0,0,0,0,0,0,47,112,117,98,117,57,47,53,0,0,0,0,0,0,0,0,32,45,45,32,0,0,0,0,47,112,117,98,117,57,47,52,0,0,0,0,0,0,0,0,47,98,114,98,103,49,48,47,49,0,0,0,0,0,0,0,47,112,117,98,117,57,47,51,0,0,0,0,0,0,0,0,78,111,32,111,114,32,105,109,112,114,111,112,101,114,32,105,109,97,103,101,61,34,37,115,34,32,102,111,114,32,110,111,100,101,32,34,37,115,34,10,0,0,0,0,0,0,0,0,47,112,117,98,117,57,47,50,0,0,0,0,0,0,0,0,34,32,119,105,100,116,104,61,34,37,103,112,120,34,32,104,101,105,103,104,116,61,34,37,103,112,120,34,32,112,114,101,115,101,114,118,101,65,115,112,101,99,116,82,97,116,105,111,61,34,120,77,105,100,89,77,105,100,32,109,101,101,116,34,32,120,61,34,37,103,34,32,121,61,34,37,103,34,0,0,115,116,121,108,101,0,0,0,47,112,117,98,117,57,47,49,0,0,0,0,0,0,0,0,60,47,118,58,114,101,99,116,62,10,0,0,0,0,0,0,47,112,117,98,117,56,47,56,0,0,0,0,0,0,0,0,47,112,117,98,117,56,47,55,0,0,0,0,0,0,0,0,9,9,9,116,101,120,116,32,115,116,114,105,110,103,119,105,100,116,104,32,112,111,112,32,119,105,100,116,104,32,101,120,99,104,32,115,117,98,32,116,101,120,116,32,108,101,110,103,116,104,32,100,105,118,32,48,32,116,101,120,116,32,97,115,104,111,119,0,0,0,0,0,47,112,117,98,117,56,47,54,0,0,0,0,0,0,0,0,108,105,103,104,116,115,97,108,109,111,110,0,0,0,0,0,110,111,106,117,115,116,105,102,121,0,0,0,0,0,0,0,47,112,117,98,117,56,47,53,0,0,0,0,0,0,0,0,79,117,109,108,0,0,0,0,110,0,0,0,0,0,0,0,47,112,117,98,117,56,47,52,0,0,0,0,0,0,0,0,105,110,32,99,104,101,99,107,112,97,116,104,44,32,115,116,97,114,116,32,112,111,114,116,32,110,111,116,32,105,110,32,102,105,114,115,116,32,98,111,120,10,0,0,0,0,0,0,47,112,117,98,117,56,47,51,0,0,0,0,0,0,0,0,32,45,62,32,0,0,0,0,47,112,117,98,117,56,47,50,0,0,0,0,0,0,0,0,47,98,108,117,101,115,57,47,57,0,0,0,0,0,0,0,47,112,117,98,117,56,47,49,0,0,0,0,0,0,0,0,60,110,105,108,62,0,0,0,47,112,117,98,117,55,47,55,0,0,0,0,0,0,0,0,60,105,109,97,103,101,32,120,108,105,110,107,58,104,114,101,102,61,34,0,0,0,0,0,99,101,108,108,98,111,114,100,101,114,0,0,0,0,0,0,47,112,117,98,117,55,47,54,0,0,0,0,0,0,0,0,60,47,99,101,110,116,101,114,62,60,47,118,58,116,101,120,116,98,111,120,62,10,0,0,47,112,117,98,117,55,47,53,0,0,0,0,0,0,0,0,47,112,117,98,117,55,47,52,0,0,0,0,0,0,0,0,9,9,9,91,93,32,48,32,115,101,116,100,97,115,104,0,47,112,117,98,117,55,47,51,0,0,0,0,0,0,0,0,108,105,103,104,116,112,105,110,107,0,0,0,0,0,0,0,104,116,109,108,116,97,98,108,101,46,99,0,0,0,0,0,105,109,97,103,101,115,99,97,108,101,0,0,0,0,0,0,106,112,101,103,58,102,105,103,0,0,0,0,0,0,0,0,47,112,117,98,117,55,47,50,0,0,0,0,0,0,0,0,79,116,105,108,100,101,0,0,47,112,117,98,117,55,47,49,0,0,0,0,0,0,0,0,47,112,117,98,117,54,47,54,0,0,0,0,0,0,0,0,105,110,32,101,100,103,101,32,37,115,37,115,37,115,10,0,47,112,117,98,117,54,47,53,0,0,0,0,0,0,0,0,47,98,108,117,101,115,57,47,56,0,0,0,0,0,0,0,47,112,117,98,117,54,47,52,0,0,0,0,0,0,0,0,78,111,32,111,114,32,105,109,112,114,111,112,101,114,32,115,104,97,112,101,102,105,108,101,61,34,37,115,34,32,102,111,114,32,110,111,100,101,32,34,37,115,34,10,0,0,0,0,47,112,117,98,117,54,47,51,0,0,0,0,0,0,0,0,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,10,0,60,84,65,66,76,69,62,0,47,112,117,98,117,54,47,50,0,0,0,0,0,0,0,0,34,62,60,99,101,110,116,101,114,62,0,0,0,0,0,0,47,112,117,98,117,54,47,49,0,0,0,0,0,0,0,0,109,101,114,103,101,95,111,110,101,119,97,121,32,103,108,105,116,99,104,10,0,0,0,0,47,112,117,98,117,53,47,53,0,0,0,0,0,0,0,0,84,82,0,0,0,0,0,0,9,9,119,105,100,116,104,32,48,32,103,116,32,123,0,0,47,112,117,98,117,53,47,52,0,0,0,0,0,0,0,0,108,105,103,104,116,103,114,101,121,0,0,0,0,0,0,0,45,45,0,0,0,0,0,0,102,105,120,101,100,115,105,122,101,0,0,0,0,0,0,0,47,112,117,98,117,53,47,51,0,0,0,0,0,0,0,0,79,115,108,97,115,104,0,0,47,112,117,98,117,53,47,50,0,0,0,0,0,0,0,0,47,112,117,98,117,53,47,49,0,0,0,0,0,0,0,0,58,0,0,0,0,0,0,0,47,112,117,98,117,52,47,52,0,0,0,0,0,0,0,0,47,98,108,117,101,115,57,47,55,0,0,0,0,0,0,0,47,112,117,98,117,52,47,51,0,0,0,0,0,0,0,0,69,114,114,111,114,32,100,117,114,105,110,103,32,99,111,110,118,101,114,115,105,111,110,32,116,111,32,34,85,84,70,45,56,34,46,32,32,81,117,105,116,105,110,103,46,10,0,0,114,101,103,117,108,97,114,0,47,112,117,98,117,52,47,50,0,0,0,0,0,0,0,0,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,49,102,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,10,32,37,100,32,37,115,10,0,0,0,0,0,0,0,73,108,108,101,103,97,108,32,118,97,108,117,101,32,37,115,32,102,111,114,32,65,76,73,71,78,32,105,110,32,84,68,32,45,32,105,103,110,111,114,101,100,10,0,0,0,0,0,47,112,117,98,117,52,47,49,0,0,0,0,0,0,0,0,99,111,108,111,114,58,35,37,48,50,120,37,48,50,120,37,48,50,120,59,0,0,0,0,47,112,117,98,117,51,47,51,0,0,0,0,0,0,0,0,114,101,100,0,0,0,0,0,68,111,119,110,0,0,0,0,47,112,117,98,117,51,47,50,0,0,0,0,0,0,0,0,32,45,100,97,115,104,32,50,0,0,0,0,0,0,0,0,9,103,115,97,118,101,0,0,47,112,117,98,117,51,47,49,0,0,0,0,0,0,0,0,108,105,103,104,116,103,114,101,101,110,0,0,0,0,0,0,100,105,115,116,111,114,116,105,111,110,0,0,0,0,0,0,47,112,114,103,110,57,47,57,0,0,0,0,0,0,0,0,79,109,105,99,114,111,110,0,47,112,114,103,110,57,47,56,0,0,0,0,0,0,0,0,47,112,114,103,110,57,47,55,0,0,0,0,0,0,0,0,37,115,45,37,115,0,0,0,47,112,114,103,110,57,47,54,0,0,0,0,0,0,0,0,47,98,108,117,101,115,57,47,54,0,0,0,0,0,0,0,87,97,114,110,105,110,103,0,47,112,114,103,110,57,47,53,0,0,0,0,0,0,0,0,37,108,102,44,37,108,102,0,47,112,114,103,110,57,47,52,0,0,0,0,0,0,0,0,125,10,0,0,0,0,0,0,108,97,98,101,108,0,0,0,47,112,114,103,110,57,47,51,0,0,0,0,0,0,0,0,69,88,84,0,0,0,0,0,99,111,108,111,114,58,37,115,59,0,0,0,0,0,0,0,47,112,114,103,110,57,47,50,0,0,0,0,0,0,0,0,91,105,110,116,101,114,110,97,108,32,116,105,109,101,115,93,0,0,0,0,0,0,0,0,47,112,114,103,110,57,47,49,0,0,0,0,0,0,0,0,112,97,114,116,105,97,108,32,99,104,97,114,97,99,116,101,114,0,0,0,0,0,0,0,9,47,119,105,100,116,104,32,101,120,99,104,32,100,101,102,0,0,0,0,0,0,0,0,47,112,114,103,110,56,47,56,0,0,0,0,0,0,0,0,108,105,103,104,116,103,114,97,121,0,0,0,0,0,0,0,115,107,101,119,0,0,0,0,47,112,114,103,110,56,47,55,0,0,0,0,0,0,0,0,79,109,101,103,97,0,0,0,47,112,114,103,110,56,47,54,0,0,0,0,0,0,0,0,38,97,109,112,59,0,0,0,99,97,110,111,110,58,100,111,116,0,0,0,0,0,0,0,47,112,114,103,110,56,47,53,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,98,101,122,45,62,101,102,108,97,103,0,0,0,0,0,0,47,112,114,103,110,56,47,52,0,0,0,0,0,0,0,0,47,98,108,117,101,115,57,47,53,0,0,0,0,0,0,0,47,112,114,103,110,56,47,51,0,0,0,0,0,0,0,0,109,97,114,103,105,110,0,0,103,114,97,112,104,0,0,0,99,97,110,110,111,116,32,109,97,108,108,111,99,32,100,113,46,112,110,108,115,0,0,0,47,112,114,103,110,56,47,50,0,0,0,0,0,0,0,0,37,100,32,101,108,108,105,112,115,101,115,10,0,0,0,0,32,32,125,10,0,0,0,0,101,100,103,101,0,0,0,0,32,0,0,0,0,0,0,0,47,112,114,103,110,56,47,49,0,0,0,0,0,0,0,0,73,108,108,101,103,97,108,32,118,97,108,117,101,32,37,115,32,102,111,114,32,66,65,76,73,71,78,32,105,110,32,84,68,32,45,32,105,103,110,111,114,101,100,10,0,0,0,0,32,102,111,110,116,45,115,105,122,101,58,32,37,46,50,102,112,116,59,0,0,0,0,0,76,97,121,111,117,116,32,119,97,115,32,110,111,116,32,100,111,110,101,10,0,0,0,0,66,69,71,73,78,0,0,0,47,112,114,103,110,55,47,55,0,0,0,0,0,0,0,0,47,112,114,103,110,55,47,54,0,0,0,0,0,0,0,0,9,47,116,101,120,116,32,101,120,99,104,32,100,101,102,0,47,112,114,103,110,55,47,53,0,0,0,0,0,0,0,0,108,105,103,104,116,103,111,108,100,101,110,114,111,100,121,101,108,108,111,119,0,0,0,0,112,101,114,105,112,104,101,114,105,101,115,0,0,0,0,0,98,101,105,103,101,0,0,0,47,112,114,103,110,55,47,52,0,0,0,0,0,0,0,0,79,103,114,97,118,101,0,0,47,112,114,103,110,55,47,51,0,0,0,0,0,0,0,0,47,112,114,103,110,55,47,50,0,0,0,0,0,0,0,0,116,97,105,108,108,97,98,101,108,0,0,0,0,0,0,0,47,112,114,103,110,55,47,49,0,0,0,0,0,0,0,0,47,98,108,117,101,115,57,47,52,0,0,0,0,0,0,0,47,112,114,103,110,54,47,54,0,0,0,0,0,0,0,0,92,78,0,0,0,0,0,0,47,112,114,103,110,54,47,53,0,0,0,0,0,0,0,0,32,32,32,32,116,101,120,116,117,114,101,32,73,109,97,103,101,84,101,120,116,117,114,101,32,123,32,117,114,108,32,34,37,115,34,32,125,10,0,0,47,112,114,103,110,54,47,52,0,0,0,0,0,0,0,0,66,79,82,68,69,82,0,0,102,111,110,116,45,115,116,121,108,101,58,32,37,115,59,0,47,112,114,103,110,54,47,51,0,0,0,0,0,0,0,0,47,112,114,103,110,54,47,50,0,0,0,0,0,0,0,0,115,97,109,101,0,0,0,0,109,97,112,0,0,0,0,0,47,112,114,103,110,54,47,49,0,0,0,0,0,0,0,0,108,105,103,104,116,99,121,97,110,0,0,0,0,0,0,0,119,105,100,116,104,61,34,37,108,102,37,50,115,34,0,0,115,105,100,101,115,0,0,0,69,100,103,101,32,108,101,110,103,116,104,32,37,102,32,108,97,114,103,101,114,32,116,104,97,110,32,109,97,120,105,109,117,109,32,37,117,32,97,108,108,111,119,101,100,46,10,67,104,101,99,107,32,102,111,114,32,111,118,101,114,119,105,100,101,32,110,111,100,101,40,115,41,46,10,0,0,0,0,0,47,0,0,0,0,0,0,0,47,112,114,103,110,53,47,53,0,0,0,0,0,0,0,0,32,69,110,99,111,100,105,110,103,86,101,99,116,111,114,32,48,0,0,0,0,0,0,0,79,99,105,114,99,0,0,0,47,97,108,105,103,110,101,100,116,101,120,116,32,123,9,9,9,37,32,119,105,100,116,104,32,116,101,120,116,0,0,0,47,112,114,103,110,53,47,52,0,0,0,0,0,0,0,0,98,111,108,100,0,0,0,0,47,112,114,103,110,53,47,51,0,0,0,0,0,0,0,0,104,101,97,100,108,97,98,101,108,0,0,0,0,0,0,0,47,112,114,103,110,53,47,50,0,0,0,0,0,0,0,0,115,104,97,112,101,115,46,99,0,0,0,0,0,0,0,0,47,98,108,117,101,115,57,47,51,0,0,0,0,0,0,0,47,112,114,103,110,53,47,49,0,0,0,0,0,0,0,0,98,97,100,32,108,97,98,101,108,32,102,111,114,109,97,116,32,37,115,10,0,0,0,0,47,112,114,103,110,52,47,52,0,0,0,0,0,0,0,0,32,32,32,32,125,10,0,0,47,112,114,103,110,52,47,51,0,0,0,0,0,0,0,0,67,69,76,76,80,65,68,68,73,78,71,0,0,0,0,0,102,111,110,116,45,115,116,114,101,116,99,104,58,32,37,115,59,0,0,0,0,0,0,0,47,112,114,103,110,52,47,50,0,0,0,0,0,0,0,0,47,112,114,103,110,52,47,49,0,0,0,0,0,0,0,0,37,32,100,114,97,119,32,116,101,120,116,32,102,105,116,116,101,100,32,116,111,32,105,116,115,32,101,120,112,101,99,116,101,100,32,119,105,100,116,104,0,0,0,0,0,0,0,0,47,112,114,103,110,51,47,51,0,0,0,0,0,0,0,0,108,105,103,104,116,99,111,114,97,108,0,0,0,0,0,0,112,101,110,119,105,100,116,104,0,0,0,0,0,0,0,0,47,112,114,103,110,51,47,50,0,0,0,0,0,0,0,0,79,97,99,117,116,101,0,0,47,112,114,103,110,51,47,49,0,0,0,0,0,0,0,0,47,112,114,103,110,49,49,47,57,0,0,0,0,0,0,0,108,97,98,101,108,0,0,0,105,110,118,0,0,0,0,0,47,112,114,103,110,49,49,47,56,0,0,0,0,0,0,0,47,98,108,117,101,115,57,47,50,0,0,0,0,0,0,0,47,112,114,103,110,49,49,47,55,0,0,0,0,0,0,0,102,97,108,115,101,0,0,0,47,112,114,103,110,49,49,47,54,0,0,0,0,0,0,0,32,32,32,32,32,32,32,32,100,105,102,102,117,115,101,67,111,108,111,114,32,49,32,49,32,49,10,0,0,0,0,0,47,112,114,103,110,49,49,47,53,0,0,0,0,0,0,0,67,69,76,76,83,80,65,67,73,78,71,0,0,0,0,0,102,111,110,116,45,119,101,105,103,104,116,58,32,37,115,59,0,0,0,0,0,0,0,0,47,112,114,103,110,49,49,47,52,0,0,0,0,0,0,0,47,112,114,103,110,49,49,47,51,0,0,0,0,0,0,0,99,97,110,110,111,116,32,97,108,108,111,99,97,116,101,32,112,115,10,0,0,0,0,0,9,115,99,97,108,101,102,111,110,116,32,115,101,116,102,111,110,116,0,0,0,0,0,0,47,112,114,103,110,49,49,47,50,0,0,0,0,0,0,0,108,105,103,104,116,98,108,117,101,0,0,0,0,0,0,0,120,108,97,98,101,108,0,0,47,112,114,103,110,49,49,47,49,49,0,0,0,0,0,0,79,69,108,105,103,0,0,0,47,112,114,103,110,49,49,47,49,48,0,0,0,0,0,0,47,112,114,103,110,49,49,47,49,0,0,0,0,0,0,0,102,97,108,115,101,0,0,0,47,112,114,103,110,49,48,47,57,0,0,0,0,0,0,0,47,112,97,116,104,98,111,120,32,123,10,32,32,32,32,47,88,32,101,120,99,104,32,110,101,103,32,37,46,53,103,32,115,117,98,32,100,101,102,10,32,32,32,32,47,89,32,101,120,99,104,32,37,46,53,103,32,115,117,98,32,100,101,102,10,32,32,32,32,47,120,32,101,120,99,104,32,110,101,103,32,37,46,53,103,32,115,117,98,32,100,101,102,10,32,32,32,32,47,121,32,101,120,99,104,32,37,46,53,103,32,115,117,98,32,100,101,102,10,32,32,32,32,110,101,119,112,97,116,104,32,120,32,121,32,109,111,118,101,116,111,10,32,32,32,32,88,32,121,32,108,105,110,101,116,111,10,32,32,32,32,88,32,89,32,108,105,110,101,116,111,10,32,32,32,32,120,32,89,32,108,105,110,101,116,111,10,32,32,32,32,99,108,111,115,101,112,97,116,104,32,115,116,114,111,107,101,10,125,32,100,101,102,10,0,0,47,98,108,117,101,115,57,47,49,0,0,0,0,0,0,0,47,112,114,103,110,49,48,47,56,0,0,0,0,0,0,0,105,109,97,103,101,0,0,0,111,117,116,0,0,0,0,0,47,112,114,103,110,49,48,47,55,0,0,0,0,0,0,0,32,32,32,32,32,32,97,109,98,105,101,110,116,73,110,116,101,110,115,105,116,121,32,48,46,51,51,10,0,0,0,0,47,112,114,103,110,49,48,47,54,0,0,0,0,0,0,0,67,79,76,83,80,65,78,32,118,97,108,117,101,32,99,97,110,110,111,116,32,98,101,32,48,32,45,32,105,103,110,111,114,101,100,10,0,0,0,0,102,111,110,116,45,102,97,109,105,108,121,58,32,39,37,115,39,59,0,0,0,0,0,0,47,112,114,103,110,49,48,47,53,0,0,0,0,0,0,0,47,112,114,103,110,49,48,47,52,0,0,0,0,0,0,0,9,102,105,110,100,102,111,110,116,32,101,120,99,104,0,0,47,112,114,103,110,49,48,47,51,0,0,0,0,0,0,0,108,101,109,111,110,99,104,105,102,102,111,110,0,0,0,0,102,111,110,116,99,111,108,111,114,0,0,0,0,0,0,0,47,112,114,103,110,49,48,47,50,0,0,0,0,0,0,0,78,117,0,0,0,0,0,0,47,97,99,99,101,110,116,52,47,50,0,0,0,0,0,0,47,112,114,103,110,49,48,47,49,48,0,0,0,0,0,0,47,112,114,103,110,49,48,47,49,0,0,0,0,0,0,0,105,110,118,105,115,0,0,0,99,109,97,112,120,95,110,112,58,109,97,112,0,0,0,0,47,112,105,121,103,57,47,57,0,0,0,0,0,0,0,0,47,98,108,117,101,115,56,47,56,0,0,0,0,0,0,0,47,112,105,121,103,57,47,56,0,0,0,0,0,0,0,0,102,105,108,108,101,100,0,0,47,112,105,121,103,57,47,55,0,0,0,0,0,0,0,0,32,32,32,32,109,97,116,101,114,105,97,108,32,77,97,116,101,114,105,97,108,32,123,10,0,0,0,0,0,0,0,0,47,112,105,121,103,57,47,54,0,0,0,0,0,0,0,0,67,79,76,83,80,65,78,0,60,118,58,116,101,120,116,98,111,120,32,105,110,115,101,116,61,34,48,44,48,44,48,44,48,34,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,32,118,45,116,101,120,116,45,119,114,97,112,112,105,110,103,58,39,102,97,108,115,101,39,59,112,97,100,100,105,110,103,58,39,48,39,59,0,0,0,0,0,0,0,47,112,105,121,103,57,47,53,0,0,0,0,0,0,0,0,47,112,105,121,103,57,47,52,0,0,0,0,0,0,0,0,47,115,101,116,95,102,111,110,116,32,123,0,0,0,0,0,47,112,105,121,103,57,47,51,0,0,0,0,0,0,0,0,108,97,119,110,103,114,101,101,110,0,0,0,0,0,0,0,102,111,110,116,110,97,109,101,0,0,0,0,0,0,0,0,47,112,105,121,103,57,47,50,0,0,0,0,0,0,0,0,110,101,116,119,111,114,107,32,115,105,109,112,108,101,120,58,32,0,0,0,0,0,0,0,78,116,105,108,100,101,0,0,101,0,0,0,0,0,0,0,47,112,105,121,103,57,47,49,0,0,0,0,0,0,0,0,105,110,32,99,104,101,99,107,112,97,116,104,44,32,98,111,120,101,115,32,37,100,32,97,110,100,32,37,100,32,100,111,110,39,116,32,116,111,117,99,104,10,0,0,0,0,0,0,47,112,105,121,103,56,47,56,0,0,0,0,0,0,0,0,45,45,0,0,0,0,0,0,47,112,105,121,103,56,47,55,0,0,0,0,0,0,0,0,47,98,108,117,101,115,56,47,55,0,0,0,0,0,0,0,47,112,105,121,103,56,47,54,0,0,0,0,0,0,0,0,9,37,115,32,37,100,10,0,105,110,118,105,115,0,0,0,47,112,105,121,103,56,47,53,0,0,0,0,0,0,0,0,32,32,97,112,112,101,97,114,97,110,99,101,32,65,112,112,101,97,114,97,110,99,101,32,123,10,0,0,0,0,0,0,47,112,105,121,103,56,47,52,0,0,0,0,0,0,0,0,73,108,108,101,103,97,108,32,118,97,108,117,101,32,37,115,32,102,111,114,32,70,73,88,69,68,83,73,90,69,32,45,32,105,103,110,111,114,101,100])
+.concat([10,0,0,0,0,0,0,0,32,115,116,114,111,107,101,100,61,34,102,97,108,115,101,34,32,102,105,108,108,101,100,61,34,102,97,108,115,101,34,62,10,0,0,0,0,0,0,0,47,112,105,121,103,56,47,51,0,0,0,0,0,0,0,0,47,112,105,121,103,56,47,50,0,0,0,0,0,0,0,0,9,125,32,105,102,0,0,0,47,112,105,121,103,56,47,49,0,0,0,0,0,0,0,0,108,97,118,101,110,100,101,114,98,108,117,115,104,0,0,0,102,111,110,116,115,105,122,101,0,0,0,0,0,0,0,0,60,84,65,66,76,69,62,0,103,105,102,58,102,105,103,0,47,112,105,121,103,55,47,55,0,0,0,0,0,0,0,0,77,117,0,0,0,0,0,0,47,112,105,121,103,55,47,54,0,0,0,0,0,0,0,0,47,112,105,121,103,55,47,53,0,0,0,0,0,0,0,0,45,62,0,0,0,0,0,0,47,112,105,121,103,55,47,52,0,0,0,0,0,0,0,0,47,98,108,117,101,115,56,47,54,0,0,0,0,0,0,0,47,112,105,121,103,55,47,51,0,0,0,0,0,0,0,0,35,102,56,102,56,102,56,0,47,112,105,121,103,55,47,50,0,0,0,0,0,0,0,0,83,104,97,112,101,32,123,10,0,0,0,0,0,0,0,0,47,112,105,121,103,55,47,49,0,0,0,0,0,0,0,0,65,76,83,69,0,0,0,0,60,118,58,114,101,99,116,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,32,0,0,0,0,0,0,47,112,105,121,103,54,47,54,0,0,0,0,0,0,0,0,47,112,105,121,103,54,47,53,0,0,0,0,0,0,0,0,118,105,114,116,117,97,108,0,84,65,66,76,69,0,0,0,9,9,103,114,101,115,116,111,114,101,0,0,0,0,0,0,47,112,105,121,103,54,47,52,0,0,0,0,0,0,0,0,108,97,118,101,110,100,101,114,0,0,0,0,0,0,0,0,115,116,121,108,101,0,0,0,47,112,105,121,103,54,47,51,0,0,0,0,0,0,0,0,76,97,109,98,100,97,0,0,47,112,105,121,103,54,47,50,0,0,0,0,0,0,0,0,47,112,105,121,103,54,47,49,0,0,0,0,0,0,0,0,98,122,46,115,105,122,101,32,37,32,51,32,61,61,32,49,0,0,0,0,0,0,0,0,47,112,105,121,103,53,47,53,0,0,0,0,0,0,0,0,47,98,108,117,101,115,56,47,53,0,0,0,0,0,0,0,47,112,105,121,103,53,47,52,0,0,0,0,0,0,0,0,38,35,51,57,59,0,0,0,35,49,48,49,48,49,48,0,47,112,105,121,103,53,47,51,0,0,0,0,0,0,0,0,110,0,0,0,0,0,0,0,47,112,105,121,103,53,47,50,0,0,0,0,0,0,0,0,82,85,69,0,0,0,0,0,60,47,118,58,111,118,97,108,62,10,0,0,0,0,0,0,47,112,105,121,103,53,47,49,0,0,0,0,0,0,0,0,47,112,105,121,103,52,47,52,0,0,0,0,0,0,0,0,32,45,100,97,115,104,32,53,0,0,0,0,0,0,0,0,109,97,103,101,110,116,97,0,75,80,95,85,112,0,0,0,9,9,9,40,92,40,41,32,115,104,111,119,32,105,32,115,116,114,32,99,118,115,32,115,104,111,119,32,40,44,41,32,115,104,111,119,32,106,32,115,116,114,32,99,118,115,32,115,104,111,119,32,40,92,41,41,32,115,104,111,119,0,0,0,47,112,105,121,103,52,47,51,0,0,0,0,0,0,0,0,107,104,97,107,105,0,0,0,102,105,108,108,99,111,108,111,114,0,0,0,0,0,0,0,47,112,105,121,103,52,47,50,0,0,0,0,0,0,0,0,75,97,112,112,97,0,0,0,47,112,105,121,103,52,47,49,0,0,0,0,0,0,0,0,47,112,105,121,103,51,47,51,0,0,0,0,0,0,0,0,98,122,46,115,105,122,101,32,62,32,48,0,0,0,0,0,47,112,105,121,103,51,47,50,0,0,0,0,0,0,0,0,47,98,108,117,101,115,56,47,52,0,0,0,0,0,0,0,47,112,105,121,103,51,47,49,0,0,0,0,0,0,0,0,35,102,48,102,48,102,48,0,69,114,114,111,114,0,0,0,47,112,105,121,103,49,49,47,57,0,0,0,0,0,0,0,111,98,106,0,0,0,0,0,47,112,105,121,103,49,49,47,56,0,0,0,0,0,0,0,72,69,73,71,72,84,0,0,32,119,105,100,116,104,58,32,37,46,50,102,59,32,104,101,105,103,104,116,58,32,37,46,50,102,34,0,0,0,0,0,123,37,115,125,0,0,0,0,47,112,105,121,103,49,49,47,55,0,0,0,0,0,0,0,91,105,110,116,101,114,110,97,108,32,97,114,105,97,108,93,0,0,0,0,0,0,0,0,47,112,105,121,103,49,49,47,54,0,0,0,0,0,0,0,117,110,99,108,111,115,101,100,32,116,111,107,101,110,0,0,9,9,9,48,32,48,32,109,111,118,101,116,111,0,0,0,47,112,105,121,103,49,49,47,53,0,0,0,0,0,0,0,105,118,111,114,121,0,0,0,99,111,108,111,114,0,0,0,47,112,105,121,103,49,49,47,52,0,0,0,0,0,0,0,73,117,109,108,0,0,0,0,47,112,105,121,103,49,49,47,51,0,0,0,0,0,0,0,107,105,110,100,32,61,61,32,76,84,95,78,79,78,69,0,103,118,58,100,111,116,0,0,47,112,105,121,103,49,49,47,50,0,0,0,0,0,0,0,115,112,108,45,62,115,105,122,101,32,62,32,48,0,0,0,98,101,122,45,62,115,102,108,97,103,0,0,0,0,0,0,100,105,103,114,97,112,104,0,47,112,105,121,103,49,49,47,49,49,0,0,0,0,0,0,47,98,108,117,101,115,56,47,51,0,0,0,0,0,0,0,47,112,105,121,103,49,49,47,49,48,0,0,0,0,0,0,35,101,48,101,48,101,48,0,37,100,0,0,0,0,0,0,99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,111,112,115,0,0,0,0,0,0,47,112,105,121,103,49,49,47,49,0,0,0,0,0,0,0,103,114,101,115,116,111,114,101,10,0,0,0,0,0,0,0,108,105,103,104,116,103,114,101,121,0,0,0,0,0,0,0,47,112,105,121,103,49,48,47,57,0,0,0,0,0,0,0,37,100,32,98,101,122,105,101,114,115,32,37,100,32,112,111,105,110,116,115,10,0,0,0,82,79,87,83,80,65,78,32,118,97,108,117,101,32,99,97,110,110,111,116,32,98,101,32,48,32,45,32,105,103,110,111,114,101,100,10,0,0,0,0,32,108,101,102,116,58,32,37,46,50,102,59,32,116,111,112,58,32,37,46,50,102,59,0,78,111,32,108,105,98,122,32,115,117,112,112,111,114,116,10,0,0,0,0,0,0,0,0,69,79,70,0,0,0,0,0,47,112,105,121,103,49,48,47,56,0,0,0,0,0,0,0,68,105,110,103,98,97,116,115,0,0,0,0,0,0,0,0,47,112,105,121,103,49,48,47,55,0,0,0,0,0,0,0,9,9,9,99,111,111,114,100,102,111,110,116,32,115,101,116,102,111,110,116,0,0,0,0,47,112,105,121,103,49,48,47,54,0,0,0,0,0,0,0,105,110,100,105,103,111,0,0,115,104,97,112,101,0,0,0,97,122,117,114,101,0,0,0,47,112,105,121,103,49,48,47,53,0,0,0,0,0,0,0,73,111,116,97,0,0,0,0,47,112,105,121,103,49,48,47,52,0,0,0,0,0,0,0,47,112,105,121,103,49,48,47,51,0,0,0,0,0,0,0,115,101,116,108,105,110,101,119,105,100,116,104,0,49,0,0,47,112,105,121,103,49,48,47,50,0,0,0,0,0,0,0,105,109,97,103,101,115,99,97,108,101,0,0,0,0,0,0,47,98,108,117,101,115,56,47,50,0,0,0,0,0,0,0,47,112,105,121,103,49,48,47,49,48,0,0,0,0,0,0,35,101,56,101,56,101,56,0,112,110,103,58,115,118,103,0,47,112,105,121,103,49,48,47,49,0,0,0,0,0,0,0,117,115,101,114,95,115,104,97,112,101,95,37,100,10,0,0,47,112,97,115,116,101,108,50,56,47,56,0,0,0,0,0,82,79,87,83,80,65,78,0,32,32,60,118,58,111,118,97,108,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,0,0,0,0,0,47,112,97,115,116,101,108,50,56,47,55,0,0,0,0,0,90,97,112,102,68,105,110,103,98,97,116,115,0,0,0,0,47,112,97,115,116,101,108,50,56,47,54,0,0,0,0,0,97,103,116,97,105,108,40,101,41,32,61,61,32,85,70,95,102,105,110,100,40,97,103,116,97,105,108,40,101,41,41,0,9,9,103,115,97,118,101,0,47,112,97,115,116,101,108,50,56,47,53,0,0,0,0,0,105,110,100,105,97,110,114,101,100,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,119,105,100,116,104,0,0,0,99,111,110,116,97,105,110,95,110,111,100,101,115,32,99,108,117,115,116,32,37,115,32,114,97,110,107,32,37,100,32,109,105,115,115,105,110,103,32,110,111,100,101,10,0,0,0,0,47,112,97,115,116,101,108,50,56,47,52,0,0,0,0,0,37,115,37,115,37,115,0,0,47,69,110,99,111,100,105,110,103,86,101,99,116,111,114,32,50,53,54,32,97,114,114,97,121,32,100,101,102,0,0,0,73,103,114,97,118,101,0,0,47,112,97,115,116,101,108,50,56,47,51,0,0,0,0,0,105,110,118,105,115,105,98,108,101,0,0,0,0,0,0,0,47,112,97,115,116,101,108,50,56,47,50,0,0,0,0,0,83,121,110,116,97,120,32,101,114,114,111,114,58,32,110,111,110,45,115,112,97,99,101,32,115,116,114,105,110,103,32,117,115,101,100,32,98,101,102,111,114,101,32,60,84,65,66,76,69,62,0,0,0,0,0,0,115,111,108,105,100,0,0,0,47,112,97,115,116,101,108,50,56,47,49,0,0,0,0,0,47,98,108,117,101,115,56,47,49,0,0,0,0,0,0,0,47,112,97,115,116,101,108,50,55,47,55,0,0,0,0,0,35,51,48,51,48,51,48,0,47,112,97,115,116,101,108,50,55,47,54,0,0,0,0,0,103,115,97,118,101,32,37,103,32,37,103,32,116,114,97,110,115,108,97,116,101,32,110,101,119,112,97,116,104,10,0,0,47,112,97,115,116,101,108,50,55,47,53,0,0,0,0,0,73,108,108,101,103,97,108,32,118,97,108,117,101,32,37,115,32,102,111,114,32,86,65,76,73,71,78,32,45,32,105,103,110,111,114,101,100,10,0,0,120,32,101,32,34,47,62,0,47,112,97,115,116,101,108,50,55,47,52,0,0,0,0,0,109,101,100,105,117,109,0,0,47,112,97,115,116,101,108,50,55,47,51,0,0,0,0,0,9,110,112,97,103,101,115,32,49,32,103,116,32,123,0,0,47,112,97,115,116,101,108,50,55,47,50,0,0,0,0,0,104,111,116,112,105,110,107,0,104,101,105,103,104,116,0,0,100,121,110,97,109,105,99,32,108,111,97,100,105,110,103,32,110,111,116,32,97,118,97,105,108,97,98,108,101,10,0,0,47,112,97,115,116,101,108,50,55,47,49,0,0,0,0,0,73,99,105,114,99,0,0,0,47,112,97,115,116,101,108,50,54,47,54,0,0,0,0,0,47,112,97,115,116,101,108,50,54,47,53,0,0,0,0,0,84,105,109,101,115,45,82,111,109,97,110,0,0,0,0,0,110,111,110,101,0,0,0,0,47,112,97,115,116,101,108,50,54,47,52,0,0,0,0,0,47,98,108,117,101,115,55,47,55,0,0,0,0,0,0,0,47,112,97,115,116,101,108,50,54,47,51,0,0,0,0,0,35,102,99,102,99,102,99,0,47,112,97,115,116,101,108,50,54,47,50,0,0,0,0,0,93,32,32,37,100,32,102,97,108,115,101,32,37,115,10,0,47,112,97,115,116,101,108,50,54,47,49,0,0,0,0,0,73,68,68,76,69,0,0,0,108,32,0,0,0,0,0,0,47,112,97,115,116,101,108,50,53,47,53,0,0,0,0,0,85,82,87,32,67,104,97,110,99,101,114,121,32,76,0,0,47,112,97,115,116,101,108,50,53,47,52,0,0,0,0,0,9,47,115,116,114,32,49,48,32,115,116,114,105,110,103,32,100,101,102,0,0,0,0,0,47,112,97,115,116,101,108,50,53,47,51,0,0,0,0,0,104,111,110,101,121,100,101,119,0,0,0,0,0,0,0,0,111,114,100,101,114,105,110,103,0,0,0,0,0,0,0,0,47,112,97,115,116,101,108,50,53,47,50,0,0,0,0,0,73,97,99,117,116,101,0,0,47,112,97,115,116,101,108,50,53,47,49,0,0,0,0,0,47,112,97,115,116,101,108,50,52,47,52,0,0,0,0,0,112,101,110,119,105,100,116,104,0,0,0,0,0,0,0,0,47,112,97,115,116,101,108,50,52,47,51,0,0,0,0,0,47,98,108,117,101,115,55,47,54,0,0,0,0,0,0,0,47,112,97,115,116,101,108,50,52,47,50,0,0,0,0,0,35,56,48,56,48,56,48,0,47,112,97,115,116,101,108,50,52,47,49,0,0,0,0,0,93,32,32,37,100,32,116,114,117,101,32,37,115,10,0,0,78,68,95,111,114,100,101,114,40,118,41,32,60,32,78,68,95,111,114,100,101,114,40,119,41,0,0,0,0,0,0,0,47,112,97,115,116,101,108,50,51,47,51,0,0,0,0,0,79,80,0,0,0,0,0,0,37,46,48,102,32,37,46,48,102,32,0,0,0,0,0,0,47,112,97,115,116,101,108,50,51,47,50,0,0,0,0,0,90,97,112,102,67,104,97,110,99,101,114,121,45,77,101,100,105,117,109,73,116,97,108,105,99,0,0,0,0,0,0,0,47,112,97,115,116,101,108,50,51,47,49,0,0,0,0,0,9,47,105,32,101,120,99,104,32,100,101,102,0,0,0,0,47,112,97,115,116,101,108,49,57,47,57,0,0,0,0,0,103,114,101,121,0,0,0,0,114,101,115,111,108,117,116,105,111,110,0,0,0,0,0,0,47,112,97,115,116,101,108,49,57,47,56,0,0,0,0,0,71,97,109,109,97,0,0,0,47,97,99,99,101,110,116,52,47,49,0,0,0,0,0,0,47,112,97,115,116,101,108,49,57,47,55,0,0,0,0,0,115,121,110,116,97,120,32,101,114,114,111,114,0,0,0,0,47,112,97,115,116,101,108,49,57,47,54,0,0,0,0,0,112,101,114,105,112,104,101,114,105,101,115,0,0,0,0,0,47,112,97,115,116,101,108,49,57,47,53,0,0,0,0,0,47,98,108,117,101,115,55,47,53,0,0,0,0,0,0,0,105,109,97,112,95,110,112,58,109,97,112,0,0,0,0,0,47,112,97,115,116,101,108,49,57,47,52,0,0,0,0,0,105,110,118,105,115,0,0,0,47,112,97,115,116,101,108,49,57,47,51,0,0,0,0,0,37,103,32,37,103,32,0,0,47,112,97,115,116,101,108,49,57,47,50,0,0,0,0,0,79,84,84,79,77,0,0,0,32,102,105,108,108,101,100,61,34,102,97,108,115,101,34,32,0,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,57,47,49,0,0,0,0,0,47,112,97,115,116,101,108,49,56,47,56,0,0,0,0,0,84,105,109,101,115,45,82,111,109,97,110,0,0,0,0,0,9,47,106,32,101,120,99,104,32,100,101,102,0,0,0,0,47,112,97,115,116,101,108,49,56,47,55,0,0,0,0,0,103,114,101,101,110,121,101,108,108,111,119,0,0,0,0,0,100,112,105,0,0,0,0,0,47,112,97,115,116,101,108,49,56,47,54,0,0,0,0,0,69,117,109,108,0,0,0,0,115,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,56,47,53,0,0,0,0,0,47,112,97,115,116,101,108,49,56,47,52,0,0,0,0,0,112,97,103,101,100,105,114,0,105,110,32,99,104,101,99,107,112,97,116,104,44,32,98,111,120,32,37,100,32,104,97,115,32,76,76,32,99,111,111,114,100,32,62,32,85,82,32,99,111,111,114,100,10,0,0,0,47,112,97,115,116,101,108,49,56,47,51,0,0,0,0,0,47,98,108,117,101,115,55,47,52,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,56,47,50,0,0,0,0,0,116,114,111,117,98,108,101,32,105,110,32,105,110,105,116,95,114,97,110,107,10,0,0,0,100,105,97,103,111,110,97,108,115,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,56,47,49,0,0,0,0,0,91,32,0,0,0,0,0,0,47,112,97,115,116,101,108,49,55,47,55,0,0,0,0,0,87,73,68,84,72,0,0,0,34,32,0,0,0,0,0,0,47,112,97,115,116,101,108,49,55,47,54,0,0,0,0,0,47,112,97,115,116,101,108,49,55,47,53,0,0,0,0,0,84,105,109,101,115,45,73,116,97,108,105,99,0,0,0,0,9,47,110,112,97,103,101,115,32,101,120,99,104,32,100,101,102,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,55,47,52,0,0,0,0,0,103,114,101,101,110,0,0,0,99,111,110,99,101,110,116,114,97,116,101,0,0,0,0,0,99,111,108,103,0,0,0,0,112,110,103,58,102,105,103,0,47,112,97,115,116,101,108,49,55,47,51,0,0,0,0,0,69,116,97,0,0,0,0,0,109,101,109,111,114,121,32,101,120,104,97,117,115,116,101,100,0,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,55,47,50,0,0,0,0,0,47,112,97,115,116,101,108,49,55,47,49,0,0,0,0,0,66,76,0,0,0,0,0,0,47,112,97,115,116,101,108,49,54,47,54,0,0,0,0,0,47,98,108,117,101,115,55,47,51,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,54,47,53,0,0,0,0,0,114,111,117,110,100,101,100,0,47,112,97,115,116,101,108,49,54,47,52,0,0,0,0,0,117,115,45,62,110,97,109,101,0,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,54,47,51,0,0,0,0,0,119,105,100,116,104,0,0,0,32,102,105,108,108,101,100,61,34,116,114,117,101,34,32,102,105,108,108,99,111,108,111,114,61,34,0,0,0,0,0,0,47,112,97,115,116,101,108,49,54,47,50,0,0,0,0,0,47,112,97,115,116,101,108,49,54,47,49,0,0,0,0,0,84,105,109,101,115,45,66,111,108,100,73,116,97,108,105,99,0,0,0,0,0,0,0,0,47,98,101,103,105,110,112,97,103,101,32,123,9,37,32,105,32,106,32,110,112,97,103,101,115,0,0,0,0,0,0,0,85,110,99,108,111,115,101,100,32,99,111,109,109,101,110,116,10,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,53,47,53,0,0,0,0,0,103,114,97,121,0,0,0,0,99,108,117,115,116,101,114,114,97,110,107,0,0,0,0,0,102,105,110,100,95,102,97,115,116,95,110,111,100,101,40,103,44,32,110,41,0,0,0,0,47,112,97,115,116,101,108,49,53,47,52,0,0,0,0,0,69,112,115,105,108,111,110,0,47,112,97,115,116,101,108,49,53,47,51,0,0,0,0,0,47,112,97,115,116,101,108,49,53,47,50,0,0,0,0,0,112,97,100,0,0,0,0,0,47,112,97,115,116,101,108,49,53,47,49,0,0,0,0,0,47,98,108,117,101,115,55,47,50,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,52,47,52,0,0,0,0,0,38,113,117,111,116,59,0,0,102,105,108,108,101,100,0,0,47,112,97,115,116,101,108,49,52,47,51,0,0,0,0,0,117,115,0,0,0,0,0,0,47,112,97,115,116,101,108,49,52,47,50,0,0,0,0,0,118,97,108,105,103,110,0,0,34,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,52,47,49,0,0,0,0,0,47,112,97,115,116,101,108,49,51,47,51,0,0,0,0,0,84,105,109,101,115,0,0,0,32,45,102,105,108,108,32,0,47,110,111,112,99,111,108,111,114,32,123,112,111,112,32,112,111,112,32,112,111,112,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,0,0,0,47,112,97,115,116,101,108,49,51,47,50,0,0,0,0,0,103,111,108,100,101,110,114,111,100,0,0,0,0,0,0,0,108,97,110,100,115,99,97,112,101,0,0,0,0,0,0,0,103,114,101,101,110,0,0,0,85,112,0,0,0,0,0,0,47,112,97,115,116,101,108,49,51,47,49,0,0,0,0,0,69,103,114,97,118,101,0,0,47,112,97,105,114,101,100,57,47,57,0,0,0,0,0,0,47,112,97,105,114,101,100,57,47,56,0,0,0,0,0,0,37,108,102,44,37,108,102,0,47,112,97,105,114,101,100,57,47,55,0,0,0,0,0,0,47,98,108,117,101,115,55,47,49,0,0,0,0,0,0,0,47,112,97,105,114,101,100,57,47,54,0,0,0,0,0,0,108,105,103,104,116,103,114,101,121,0,0,0,0,0,0,0,47,112,97,105,114,101,100,57,47,53,0,0,0,0,0,0,106,111,98,0,0,0,0,0,37,115,58,32,0,0,0,0,47,112,97,105,114,101,100,57,47,52,0,0,0,0,0,0,116,111,111,108,116,105,112,0,0,0,0,0,0,0,0,0,47,112,97,105,114,101,100,57,47,51,0,0,0,0,0,0,104,101,108,118,101,116,105,99,97,0,0,0,0,0,0,0,49,48,48,48,48,0,0,0,47,112,97,105,114,101,100,57,47,50,0,0,0,0,0,0,84,105,109,101,115,45,66,111,108,100,0,0,0,0,0,0,110,111,116,32,119,101,108,108,45,102,111,114,109,101,100,32,40,105,110,118,97,108,105,100,32,116,111,107,101,110,41,0,47,103,114,97,112,104,99,111,108,111,114,32,123,32,115,101,116,104,115,98,99,111,108,111,114,32,125,32,98,105,110,100,32,100,101,102,0,0,0,0,47,112,97,105,114,101,100,57,47,49,0,0,0,0,0,0,103,111,108,100,0,0,0,0,111,114,105,101,110,116,97,116,105,111,110,0,0,0,0,0,47,112,97,105,114,101,100,56,47,56,0,0,0,0,0,0,69,99,105,114,99,0,0,0,47,112,97,105,114,101,100,56,47,55,0,0,0,0,0,0,108,97,98,101,108,115,46,99,0,0,0,0,0,0,0,0,100,111,116,58,100,111,116,0,47,112,97,105,114,101,100,56,47,54,0,0,0,0,0,0,109,97,114,103,105,110,0,0,99,111,109,112,111,117,110,100,46,99,0,0,0,0,0,0,47,112,97,105,114,101,100,56,47,53,0,0,0,0,0,0,47,98,108,117,101,115,54,47,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,116,114,105,99,116,32,0,47,112,97,105,114,101,100,56,47,52,0,0,0,0,0,0,98,108,97,99,107,0,0,0,104,101,97,100,112,111,114,116,0,0,0,0,0,0,0,0,108,105,98,112,97,116,104,47,37,115,58,37,100,58,32,37,115,10,0,0,0,0,0,0,47,112,97,105,114,101,100,56,47,51,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,118,108,111,97,100,105,109,97,103,101,95,99,111,114,101,46,99,0,0,0,0,0,0,47,112,97,105,114,101,100,56,47,50,0,0,0,0,0,0,37,115,32,105,110,32,108,105,110,101,32,37,100,32,10,0,116,105,116,108,101,0,0,0,99,32,0,0,0,0,0,0,47,112,97,105,114,101,100,56,47,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,97,110,39,116,32,111,112,101,110,32,108,105,98,114,97,114,121,32,102,105,108,101,32,37,115,10,0,0,0,0,0,37,100,32,112,111,108,121,108,105,110,101,115,32,37,100,32,112,111,105,110,116,115,10,0,47,112,97,105,114,101,100,55,47,55,0,0,0,0,0,0,102,97,110,116,97,115,121,0,47,101,100,103,101,99,111,108,111,114,32,123,32,115,101,116,104,115,98,99,111,108,111,114,32,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,47,112,97,105,114,101,100,55,47,54,0,0,0,0,0,0,103,104,111,115,116,119,104,105,116,101,0,0,0,0,0,0,114,111,116,97,116,101,0,0,97,113,117,97,109,97,114,105,110,101,0,0,0,0,0,0,47,112,97,105,114,101,100,55,47,53,0,0,0,0,0,0,69,97,99,117,116,101,0,0,47,112,97,105,114,101,100,55,47,52,0,0,0,0,0,0,47,112,97,105,114,101,100,55,47,51,0,0,0,0,0,0,58,9,32,0,0,0,0,0,47,112,97,105,114,101,100,55,47,50,0,0,0,0,0,0,47,98,108,117,101,115,54,47,53,0,0,0,0,0,0,0,1,112,114,111,116,111,0,0,47,112,97,105,114,101,100,55,47,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,112,97,105,114,101,100,54,47,54,0,0,0,0,0,0,32,47,62,10,0,0,0,0,47,112,97,105,114,101,100,54,47,53,0,0,0,0,0,0,116,97,114,103,101,116,0,0,37,115,37,46,48,102,44,37,46,48,102,32,0,0,0,0,47,112,97,105,114,101,100,54,47,52,0,0,0,0,0,0,47,112,97,105,114,101,100,54,47,51,0,0,0,0,0,0,83,121,109,98,111,108,0,0,97,103,104,101,97,100,40,101,41,32,61,61,32,85,70,95,102,105,110,100,40,97,103,104,101,97,100,40,101,41,41,0,47,110,111,100,101,99,111,108,111,114,32,123,32,115,101,116,104,115,98,99,111,108,111,114,32,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,47,112,97,105,114,101,100,54,47,50,0,0,0,0,0,0,103,97,105,110,115,98,111,114,111,0,0,0,0,0,0,0,34,37,115,34,32,119,97,115,32,110,111,116,32,102,111,117,110,100,32,97,115,32,97,32,102,105,108,101,32,111,114,32,97,115,32,97,32,115,104,97,112,101,32,108,105,98,114,97,114,121,32,109,101,109,98,101,114,10,0,0,0,0,0,0,99,101,110,116,101,114,0,0,110,101,120,116,35,105,116,101,114,61,37,100,10,0,0,0,47,112,97,105,114,101,100,54,47,49,0,0,0,0,0,0,80,97,116,104,32,112,114,111,118,105,100,101,100,32,116,111,32,102,105,108,101,58,32,34,37,115,34,32,104,97,115,32,98,101,101,110,32,105,103,110,111,114,101,100,32,98,101,99,97,117,115,101,32,102,105,108,101,115,32,97,114,101,32,111,110,108,121,32,112,101,114,109,105,116,116,101,100,32,116,111,32,98,101,32,108,111,97,100,101,100,32,102,114,111,109,32,116,104,101,32,100,105,114,101,99,116,111,114,105,101,115,32,105,110,32,34,37,115,34,32,119,104,101,110,32,114,117,110,110,105,110,103,32,105,110,32,97,110,32,104,116,116,112,32,115,101,114,118,101,114,46,10,0,0,0,0,0,0,0,0,109,97,114,107,0,0,0,0,69,84,72,0,0,0,0,0,99,97,110,110,111,116,32,109,97,108,108,111,99,32,111,112,115,0,0,0,0,0,0,0,47,112,97,105,114,101,100,53,47,53,0,0,0,0,0,0,105,110,118,105,115,0,0,0,47,112,97,105,114,101,100,53,47,52,0,0,0,0,0,0,108,97,121,101,114,115,101,112,0,0,0,0,0,0,0,0,47,112,97,105,114,101,100,53,47,51,0,0,0,0,0,0,47,98,108,117,101,115,54,47,52,0,0,0,0,0,0,0,47,112,97,105,114,101,100,53,47,50,0,0,0,0,0,0,110,111,100,101,32,37,115,44,32,112,111,114,116,32,37,115,32,117,110,114,101,99,111,103,110,105,122,101,100,10,0,0,47,112,97,105,114,101,100,53,47,49,0,0,0,0,0,0,60,118,58,105,109,97,103,101,32,115,114,99,61,34,37,115,34,32,115,116,121,108,101,61,34,32,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,32,119,105,100,116,104,58,37,46,50,102,59,32,104,101,105,103,104,116,58,37,46,50,102,59,32,108,101,102,116,58,37,46,50,102,32,59,32,116,111,112,58,37,46,50,102,34,0,0,0,0,0,47,112,97,105,114,101,100,52,47,52,0,0,0,0,0,0,114,111,119,115,112,97,110,0,109,32,0,0,0,0,0,0,47,112,97,105,114,101,100,52,47,51,0,0,0,0,0,0,47,112,97,105,114,101,100,52,47,50,0,0,0,0,0,0,80,97,108,97,116,105,110,111,45,82,111,109,97,110,0,0,37,32,104,111,111,107,115,32,102,111,114,32,115,101,116,116,105,110,103,32,99,111,108,111,114,32,0,0,0,0,0,0,47,112,97,105,114,101,100,52,47,49,0,0,0,0,0,0,102,117,99,104,115,105,97,0,112,97,103,101,0,0,0,0,47,112,97,105,114,101,100,51,47,51,0,0,0,0,0,0,68,101,108,116,97,0,0,0,47,112,97,105,114,101,100,51,47,50,0,0,0,0,0,0,47,112,97,105,114,101,100,51,47,49,0,0,0,0,0,0,108,97,121,101,114,115,0,0,100,111,116,0,0,0,0,0,47,112,97,105,114,101,100,49,50,47,57,0,0,0,0,0,47,98,108,117,101,115,54,47,51,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,50,47,56,0,0,0,0,0,110,111,100,101,32,37,115,44,32,112,111,114,116,32,37,115,44,32,117,110,114,101,99,111,103,110,105,122,101,100,32,99,111,109,112,97,115,115,32,112,111,105,110,116,32,39,37,115,39,32,45,32,105,103,110,111,114,101,100,10,0,0,0,0,47,112,97,105,114,101,100,49,50,47,55,0,0,0,0,0,106,112,103,58,118,109,108,0,47,112,97,105,114,101,100,49,50,47,54,0,0,0,0,0,112,111,114,116,0,0,0,0,47,62,60,47,118,58,115,104,97,112,101,62,10,0,0,0,47,112,97,105,114,101,100,49,50,47,53,0,0,0,0,0,47,112,97,105,114,101,100,49,50,47,52,0,0,0,0,0,80,97,108,97,116,105,110,111,45,73,116,97,108,105,99,0,47,100,105,97,103,111,110,97,108,115,32,123,32,125,32,98,105,110,100,32,100,101,102,0,47,112,97,105,114,101,100,49,50,47,51,0,0,0,0,0,102,111,114,101,115,116,103,114,101,101,110,0,0,0,0,0,115,105,122,101,0,0,0,0,47,112,97,105,114,101,100,49,50,47,50,0,0,0,0,0,68,97,103,103,101,114,0,0,47,112,97,105,114,101,100,49,50,47,49,50,0,0,0,0,47,112,97,105,114,101,100,49,50,47,49,49,0,0,0,0,100,103,101,115,102,105,114,115,116,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,50,47,49,48,0,0,0,0,47,98,108,117,101,115,54,47,50,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,50,47,49,0,0,0,0,0,95,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,49,47,57,0,0,0,0,0,106,112,101,58,118,109,108,0,47,112,97,105,114,101,100,49,49,47,56,0,0,0,0,0,105,100,0,0,0,0,0,0,115,117,114,112,114,105,115,101,10,0,0,0,0,0,0,0,60,118,58,112,97,116,104,32,32,118,61,34,0,0,0,0,47,112,97,105,114,101,100,49,49,47,55,0,0,0,0,0,47,112,97,105,114,101,100,49,49,47,54,0,0,0,0,0,80,97,108,97,116,105,110,111,45,66,111,108,100,73,116,97,108,105,99,0,0,0,0,0,47,114,111,117,110,100,101,100,32,123,32,125,32,98,105,110,100,32,100,101,102,0,0,0,47,112,97,105,114,101,100,49,49,47,53,0,0,0,0,0,102,108,111,114,97,108,119,104,105,116,101,0,0,0,0,0,102,111,110,116,110,97,109,101,115,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,49,47,52,0,0,0,0,0,67,104,105,0,0,0,0,0,47,97,99,99,101,110,116,51,47,51,0,0,0,0,0,0,47,112,97,105,114,101,100,49,49,47,51,0,0,0,0,0,47,112,97,105,114,101,100,49,49,47,50,0,0,0,0,0,111,100,101,115,102,105,114,115,116,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,49,47,49,49,0,0,0,0,47,98,108,117,101,115,54,47,49,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,49,47,49,48,0,0,0,0,37,46,53,103,32,37,46,53,103,32,116,114,97,110,115,108,97,116,101,32,110,101,119,112,97,116,104,32,117,115,101,114,95,115,104,97,112,101,95,37,100,10,0,0,0,0,0,0,99,109,97,112,120,58,109,97,112,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,49,47,49,0,0,0,0,0,106,112,101,103,58,118,109,108,0,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,48,47,57,0,0,0,0,0,104,114,101,102,0,0,0,0,32,62,0,0,0,0,0,0,47,112,97,105,114,101,100,49,48,47,56,0,0,0,0,0,47,112,97,105,114,101,100,49,48,47,55,0,0,0,0,0,80,97,108,97,116,105,110,111,32,76,105,110,111,116,121,112,101,0,0,0,0,0,0,0,47,117,110,102,105,108,108,101,100,32,123,32,125,32,98,105,110,100,32,100,101,102,0,0,47,112,97,105,114,101,100,49,48,47,54,0,0,0,0,0,102,97,115,116,103,114,46,99,0,0,0,0,0,0,0,0,102,105,114,101,98,114,105,99,107,0,0,0,0,0,0,0,115,104,111,119,98,111,120,101,115,0,0,0,0,0,0,0,38,97,109,112,59,0,0,0,47,112,97,105,114,101,100,49,48,47,53,0,0,0,0,0,67,99,101,100,105,108,0,0,99,117,115,116,111,109,0,0,47,112,97,105,114,101,100,49,48,47,52,0,0,0,0,0,47,112,97,105,114,101,100,49,48,47,51,0,0,0,0,0,111,117,116,112,117,116,111,114,100,101,114,0,0,0,0,0,105,110,32,99,104,101,99,107,112,97,116,104,44,32,98,111,120,32,48,32,104,97,115,32,76,76,32,99,111,111,114,100,32,62,32,85,82,32,99,111,111,114,100,10,0,0,0,0,47,112,97,105,114,101,100,49,48,47,50,0,0,0,0,0,47,98,108,117,101,115,53,47,53,0,0,0,0,0,0,0,47,112,97,105,114,101,100,49,48,47,49,48,0,0,0,0,37,115,37,100,32,110,111,100,101,115,32,37,100,32,101,100,103,101,115,32,37,100,32,105,116,101,114,32,37,46,50,102,32,115,101,99,10,0,0,0,77,114,101,99,111,114,100,0,47,112,97,105,114,101,100,49,48,47,49,0,0,0,0,0,103,105,102,58,118,109,108,0,47,111,114,114,100,57,47,57,0,0,0,0,0,0,0,0,104,101,105,103,104,116,0,0,32,119,105,100,116,104,58,32,37,100,59,32,104,101,105,103,104,116,58,32,37,100,34,0,47,111,114,114,100,57,47,56,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,111,114,114,100,57,47,55,0,0,0,0,0,0,0,0,80,97,108,97,116,105,110,111,45,66,111,108,100,0,0,0,47,102,105,108,108,101,100,32,123,32,125,32,98,105,110,100,32,100,101,102,0,0,0,0,47,111,114,114,100,57,47,54,0,0,0,0,0,0,0,0,100,111,100,103,101,114,98,108,117,101,0,0,0,0,0,0,101,113,117,97,108,108,121,0,114,111,119,103,0,0,0,0,106,112,103,58,115,118,103,0,47,111,114,114,100,57,47,53,0,0,0,0,0,0,0,0,66,101,116,97,0,0,0,0,47,111,114,114,100,57,47,52,0,0,0,0,0,0,0,0,47,111,114,114,100,57,47,51,0,0,0,0,0,0,0,0,37,108,102,44,37,108,102,44,37,108,102,44,37,108,102,44,37,108,102,0,0,0,0,0,47,111,114,114,100,57,47,50,0,0,0,0,0,0,0,0,47,98,108,117,101,115,53,47,52,0,0,0,0,0,0,0,47,111,114,114,100,57,47,49,0,0,0,0,0,0,0,0,114,101,99,111,114,100,0,0,47,111,114,114,100,56,47,56,0,0,0,0,0,0,0,0,112,110,103,58,118,109,108,0,47,111,114,114,100,56,47,55,0,0,0,0,0,0,0,0,102,105,120,101,100,115,105,122,101,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,47,111,114,114,100,56,47,54,0,0,0,0,0,0,0,0,47,111,114,114,100,56,47,53,0,0,0,0,0,0,0,0,114,111,109,97,110,0,0,0,47,98,111,108,100,32,123,32,50,32,115,101,116,108,105,110,101,119,105,100,116,104,32,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,0,0,76,97,98,101,108,32,99,108,111,115,101,100,32,98,101,102,111,114,101,32,101,110,100,32,111,102,32,72,84,77,76,32,101,108,101,109,101,110,116,10,0,0,0,0,0,0,0,0,47,111,114,114,100,56,47,52,0,0,0,0,0,0,0,0,100,105,109,103,114,101,121,0,114,97,110,107,115,101,112,0,47,111,114,114,100,56,47,51,0,0,0,0,0,0,0,0,65,117,109,108,0,0,0,0,78,68,95,110,101,120,116,40,118,41,32,61,61,32,78,85,76,76,0,0,0,0,0,0,47,111,114,114,100,56,47,50,0,0,0,0,0,0,0,0,47,111,114,114,100,56,47,49,0,0,0,0,0,0,0,0,37,108,102,44,37,108,102,44,37,108,102,44,37,91,94,44,93,37,115,0,0,0,0,0,47,111,114,114,100,55,47,55,0,0,0,0,0,0,0,0,47,98,108,117,101,115,53,47,51,0,0,0,0,0,0,0,47,111,114,114,100,55,47,54,0,0,0,0,0,0,0,0,38,35,49,54,48,59,0,0,77,99,105,114,99,108,101,0,47,111,114,114,100,55,47,53,0,0,0,0,0,0,0,0,115,118,103,58,115,118,103,0,47,111,114,114,100,55,47,52,0,0,0,0,0,0,0,0,99,111,108,115,112,97,110,0,103,118,114,101,110,100,101,114,95,99,111,114,101,95,118,109,108,46,99,0,0,0,0,0,47,111,114,114,100,55,47,51,0,0,0,0,0,0,0,0,47,111,114,114,100,55,47,50,0,0,0,0,0,0,0,0,78,101,119,67,101,110,116,117,114,121,83,99,104,108,98,107,45,82,111,109,97,110,0,0,32,99,114,101,97,116,101,32,108,105,110,101,32,0,0,0,47,105,110,118,105,115,32,123,47,102,105,108,108,32,123,110,101,119,112,97,116,104,125,32,100,101,102,32,47,115,116,114,111,107,101,32,123,110,101,119,112,97,116,104,125,32,100,101,102,32,47,115,104,111,119,32,123,112,111,112,32,110,101,119,112,97,116,104,125,32,100,101,102,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,47,111,114,114,100,55,47,49,0,0,0,0,0,0,0,0,100,105,109,103,114,97,121,0,110,111,100,101,115,101,112,0,47,111,114,114,100,54,47,54,0,0,0,0,0,0,0,0,65,116,105,108,100,101,0,0,99,121,97,110,0,0,0,0,75,80,95,82,105,103,104,116,0,0,0,0,0,0,0,0,47,111,114,114,100,54,47,53,0,0,0,0,0,0,0,0,47,111,114,114,100,54,47,52,0,0,0,0,0,0,0,0,37,108,102,44,37,108,102,44,37,108,102,44,39,37,91,94,39,93,39,0,0,0,0,0,47,111,114,114,100,54,47,51,0,0,0,0,0,0,0,0,47,98,108,117,101,115,53,47,50,0,0,0,0,0,0,0,47,111,114,114,100,54,47,50,0,0,0,0,0,0,0,0,77,115,113,117,97,114,101,0,47,111,114,114,100,54,47,49,0,0,0,0,0,0,0,0,115,118,103,58,120,100,111,116,0,0,0,0,0,0,0,0,47,111,114,114,100,53,47,53,0,0,0,0,0,0,0,0,99,101,108,108,115,112,97,99,105,110,103,0,0,0,0,0,60,117,110,107,110,111,119,110,62,0,0,0,0,0,0,0,35,37,48,50,120,37,48,50,120,37,48,50,120,0,0,0,47,111,114,114,100,53,47,52,0,0,0,0,0,0,0,0,97,114,105,97,108,0,0,0,47,111,114,114,100,53,47,51,0,0,0,0,0,0,0,0,78,101,119,67,101,110,116,117,114,121,83,99,104,108,98,107,45,73,116,97,108,105,99,0,115,111,117,114,99,101,0,0,110,111,32,101,108,101,109,101,110,116,32,102,111,117,110,100,0,0,0,0,0,0,0,0,47,100,111,116,116,101,100,32,123,32,91,49,32,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,109,117,108,32,54,32,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,109,117,108,93,32,48,32,115,101,116,100,97,115,104,32,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,0,47,111,114,114,100,53,47,50,0,0,0,0,0,0,0,0,100,101,101,112,115,107,121,98,108,117,101,0,0,0,0,0,82,76,0,0,0,0,0,0,47,111,114,114,100,53,47,49,0,0,0,0,0,0,0,0,65,114,105,110,103,0,0,0,47,111,114,114,100,52,47,52,0,0,0,0,0,0,0,0,45,45,0,0,0,0,0,0,120,100,111,116,0,0,0,0,47,111,114,114,100,52,47,51,0,0,0,0,0,0,0,0,118,105,101,119,112,111,114,116,0,0,0,0,0,0,0,0,99,108,117,115,116,101,114,46,99,0,0,0,0,0,0,0,47,111,114,114,100,52,47,50,0,0,0,0,0,0,0,0,47,98,108,117,101,115,53,47,49,0,0,0,0,0,0,0,47,111,114,114,100,52,47,49,0,0,0,0,0,0,0,0,116,97,105,108,112,111,114,116,0,0,0,0,0,0,0,0,77,100,105,97,109,111,110,100,0,0,0,0,0,0,0,0,116,107,0,0,0,0,0,0,84,97,114,103,101,116,32,65,82,32,61,32,37,103,10,0,99,97,110,110,111,116,32,102,105,110,100,32,116,114,105,97,110,103,108,101,32,112,97,116,104,0,0,0,0,0,0,0,32,45,45,32,0,0,0,0,47,111,114,114,100,51,47,51,0,0,0,0,0,0,0,0,98,108,97,99,107,0,0,0,101,112,115,58,120,100,111,116,0,0,0,0,0,0,0,0,47,111,114,114,100,51,47,50,0,0,0,0,0,0,0,0,99,101,108,108,112,97,100,100,105,110,103,0,0,0,0,0,110,111,110,101,0,0,0,0,98,98,0,0,0,0,0,0,114,0,0,0,0,0,0,0,47,111,114,114,100,51,47,49,0,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,57,47,57,0,0,0,0,0,37,100,32,112,111,108,121,103,111,110,115,32,37,100,32,112,111,105,110,116,115,10,0,0,78,101,119,67,101,110,116,117,114,121,83,99,104,108,98,107,45,66,111,108,100,73,116,97,108,105,99,0,0,0,0,0,47,100,97,115,104,101,100,32,123,32,91,57,32,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,109,117,108,32,100,117,112,32,93,32,48,32,115,101,116,100,97,115,104,32,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,0,47,111,114,97,110,103,101,115,57,47,56,0,0,0,0,0,100,101,101,112,112,105,110,107,0,0,0,0,0,0,0,0,66,84,0,0,0,0,0,0,47,111,114,97,110,103,101,115,57,47,55,0,0,0,0,0,97,113,117,97,0,0,0,0,65,108,112,104,97,0,0,0,47,111,114,97,110,103,101,115,57,47,54,0,0,0,0,0,47,111,114,97,110,103,101,115,57,47,53,0,0,0,0,0,112,97,103,101,100,105,114,61,37,115,32,105,103,110,111,114,101,100,10,0,0,0,0,0,47,111,114,97,110,103,101,115,57,47,52,0,0,0,0,0,47,98,108,117,101,115,52,47,52,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,57,47,51,0,0,0,0,0,105,110,118,104,111,117,115,101,0,0,0,0,0,0,0,0,37,115,32,45,62,32,37,115,58,32,116,97,105,108,32,105,115,32,105,110,115,105,100,101,32,104,101,97,100,32,99,108,117,115,116,101,114,32,37,115,10,0,0,0,0,0,0,0,101,100,103,101,0,0,0,0,47,111,114,97,110,103,101,115,57,47,50,0,0,0,0,0])
+.concat([112,115,58,120,100,111,116,0,47,111,114,97,110,103,101,115,57,47,49,0,0,0,0,0,98,111,114,100,101,114,0,0,34,32,47,62,0,0,0,0,47,111,114,97,110,103,101,115,56,47,56,0,0,0,0,0,47,111,114,97,110,103,101,115,56,47,55,0,0,0,0,0,67,101,110,116,117,114,121,32,83,99,104,111,111,108,98,111,111,107,32,76,0,0,0,0,40,78,68,95,85,70,95,115,105,122,101,40,110,41,32,60,61,32,49,41,32,124,124,32,40,110,32,61,61,32,108,101,97,100,101,114,41,0,0,0,112,114,101,102,105,120,32,109,117,115,116,32,110,111,116,32,98,101,32,98,111,117,110,100,32,116,111,32,111,110,101,32,111,102,32,116,104,101,32,114,101,115,101,114,118,101,100,32,110,97,109,101,115,112,97,99,101,32,110,97,109,101,115,0,47,115,111,108,105,100,32,123,32,91,93,32,48,32,115,101,116,100,97,115,104,32,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,56,47,54,0,0,0,0,0,108,111,97,100,105,109,97,103,101,0,0,0,0,0,0,0,76,82,0,0,0,0,0,0,100,97,114,107,118,105,111,108,101,116,0,0,0,0,0,0,37,115,32,119,104,105,108,101,32,111,112,101,110,105,110,103,32,37,115,10,0,0,0,0,47,111,114,97,110,103,101,115,56,47,53,0,0,0,0,0,71,111,105,110,103,32,116,111,32,97,112,112,108,121,32,97,110,111,116,104,101,114,32,101,120,112,97,110,115,105,111,110,46,10,0,0,0,0,0,0,58,0,0,0,0,0,0,0,47,115,101,116,117,112,76,97,116,105,110,49,32,123,0,0,65,103,114,97,118,101,0,0,47,111,114,97,110,103,101,115,56,47,52,0,0,0,0,0,100,111,116,116,101,100,0,0,47,111,114,97,110,103,101,115,56,47,51,0,0,0,0,0,114,101,110,100,101,114,101,114,32,102,111,114,32,37,115,32,105,115,32,117,110,97,118,97,105,108,97,98,108,101,10,0,47,111,114,97,110,103,101,115,56,47,50,0,0,0,0,0,47,98,108,117,101,115,52,47,51,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,56,47,49,0,0,0,0,0,105,110,118,116,114,97,112,101,122,105,117,109,0,0,0,0,47,111,114,97,110,103,101,115,55,47,55,0,0,0,0,0,95,37,100,0,0,0,0,0,106,112,103,58,120,100,111,116,0,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,55,47,54,0,0,0,0,0,98,103,99,111,108,111,114,0,34,32,100,97,115,104,115,116,121,108,101,61,34,100,111,116,0,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,55,47,53,0,0,0,0,0,41,10,0,0,0,0,0,0,47,111,114,97,110,103,101,115,55,47,52,0,0,0,0,0,78,101,119,67,101,110,116,117,114,121,83,99,104,108,98,107,45,66,111,108,100,0,0,0,114,101,115,101,114,118,101,100,32,112,114,101,102,105,120,32,40,120,109,108,110,115,41,32,109,117,115,116,32,110,111,116,32,98,101,32,100,101,99,108,97,114,101,100,32,111,114,32,117,110,100,101,99,108,97,114,101,100,0,0,0,0,0,0,37,32,115,116,121,108,101,115,0,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,55,47,51,0,0,0,0,0,100,101,118,105,99,101,0,0,114,97,110,107,100,105,114,0,100,97,114,107,116,117,114,113,117,111,105,115,101,0,0,0,47,111,114,97,110,103,101,115,55,47,50,0,0,0,0,0,65,99,105,114,99,0,0,0,47,111,114,97,110,103,101,115,55,47,49,0,0,0,0,0,47,111,114,97,110,103,101,115,54,47,54,0,0,0,0,0,108,97,121,111,117,116,32,119,97,115,32,110,111,116,32,100,111,110,101,10,0,0,0,0,100,105,97,109,111,110,100,0,47,111,114,97,110,103,101,115,54,47,53,0,0,0,0,0,47,98,108,117,101,115,52,47,50,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,54,47,52,0,0,0,0,0,105,110,118,116,114,105,97,110,103,108,101,0,0,0,0,0,47,111,114,97,110,103,101,115,54,47,51,0,0,0,0,0,50,48,0,0,0,0,0,0,106,112,101,58,120,100,111,116,0,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,54,47,50,0,0,0,0,0,98,97,108,105,103,110,0,0,34,32,100,97,115,104,115,116,121,108,101,61,34,100,97,115,104,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,54,47,49,0,0,0,0,0,32,40,0,0,0,0,0,0,47,111,114,97,110,103,101,115,53,47,53,0,0,0,0,0,72,101,108,118,101,116,105,99,97,45,79,98,108,105,113,117,101,0,0,0,0,0,0,0,114,101,115,101,114,118,101,100,32,112,114,101,102,105,120,32,40,120,109,108,41,32,109,117,115,116,32,110,111,116,32,98,101,32,117,110,100,101,99,108,97,114,101,100,32,111,114,32,98,111,117,110,100,32,116,111,32,97,110,111,116,104,101,114,32,110,97,109,101,115,112,97,99,101,32,110,97,109,101,0,32,32,32,32,32,32,32,115,99,97,108,101,0,0,0,0,47,111,114,97,110,103,101,115,53,47,52,0,0,0,0,0,116,101,120,116,108,97,121,111,117,116,0,0,0,0,0,0,113,117,97,110,116,117,109,0,100,97,114,107,115,108,97,116,101,103,114,101,121,0,0,0,47,111,114,97,110,103,101,115,53,47,51,0,0,0,0,0,65,97,99,117,116,101,0,0,47,111,114,97,110,103,101,115,53,47,50,0,0,0,0,0,47,111,114,97,110,103,101,115,53,47,49,0,0,0,0,0,76,97,121,111,117,116,32,119,97,115,32,110,111,116,32,100,111,110,101,46,32,32,77,105,115,115,105,110,103,32,108,97,121,111,117,116,32,112,108,117,103,105,110,115,63,32,10,0,47,111,114,97,110,103,101,115,52,47,52,0,0,0,0,0,47,98,108,117,101,115,52,47,49,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,52,47,51,0,0,0,0,0,116,114,105,112,108,101,111,99,116,97,103,111,110,0,0,0,47,111,114,97,110,103,101,115,52,47,50,0,0,0,0,0,49,57,0,0,0,0,0,0,106,112,101,103,58,120,100,111,116,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,52,47,49,0,0,0,0,0,60,84,68,62,0,0,0,0,34,32,119,101,105,103,104,116,61,34,37,46,48,102,112,116,0,0,0,0,0,0,0,0,47,111,114,97,110,103,101,115,51,47,51,0,0,0,0,0,32,118,101,114,115,105,111,110,32,0,0,0,0,0,0,0,71,68,95,114,97,110,107,40,103,41,91,114,93,46,110,32,60,61,32,71,68,95,114,97,110,107,40,103,41,91,114,93,46,97,110,0,0,0,0,0,47,111,114,97,110,103,101,115,51,47,50,0,0,0,0,0,72,101,108,118,101,116,105,99,97,45,78,97,114,114,111,119,45,79,98,108,105,113,117,101,0,0,0,0,0,0,0,0,99,97,110,110,111,116,32,115,117,115,112,101,110,100,32,105,110,32,101,120,116,101,114,110,97,108,32,112,97,114,97,109,101,116,101,114,32,101,110,116,105,116,121,0,0,0,0,0,32,32,32,32,32,32,32,100,117,112,32,49,32,101,120,99,104,32,100,105,118,32,47,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,101,120,99,104,32,100,101,102,0,0,47,111,114,97,110,103,101,115,51,47,49,0,0,0,0,0,100,101,115,116,105,110,97,116,105,111,110,32,112,111,105,110,116,32,110,111,116,32,105,110,32,97,110,121,32,116,114,105,97,110,103,108,101,0,0,0,108,97,121,111,117,116,0,0,71,68,70,79,78,84,80,65,84,72,61,0,0,0,0,0,100,97,114,107,115,108,97,116,101,103,114,97,121,0,0,0,47,103,114,101,121,115,57,47,57,0,0,0,0,0,0,0,65,69,108,105,103,0,0,0,47,103,114,101,121,115,57,47,56,0,0,0,0,0,0,0,47,97,99,99,101,110,116,51,47,50,0,0,0,0,0,0,47,103,114,101,121,115,57,47,55,0,0,0,0,0,0,0,67,0,0,0,0,0,0,0,114,101,110,100,101,114,0,0,47,103,114,101,121,115,57,47,54,0,0,0,0,0,0,0,47,98,108,117,101,115,51,47,51,0,0,0,0,0,0,0,115,121,110,116,97,120,32,101,114,114,111,114,44,32,115,116,97,116,101,109,101,110,116,32,115,107,105,112,112,101,100,0,47,103,114,101,121,115,57,47,53,0,0,0,0,0,0,0,100,111,117,98,108,101,111,99,116,97,103,111,110,0,0,0,47,103,114,101,121,115,57,47,52,0,0,0,0,0,0,0,49,56,0,0,0,0,0,0,103,105,102,58,120,100,111,116,0,0,0,0,0,0,0,0,105,109,97,112,58,109,97,112,0,0,0,0,0,0,0,0,47,103,114,101,121,115,57,47,51,0,0,0,0,0,0,0,37,115,32,118,97,108,117,101,32,37,115,32,60,32,37,100,32,45,32,116,111,111,32,115,109,97,108,108,32,45,32,105,103,110,111,114,101,100,0,0,60,118,58,115,116,114,111,107,101,32,99,111,108,111,114,61,34,0,0,0,0,0,0,0,47,103,114,101,121,115,57,47,50,0,0,0,0,0,0,0,35,32,71,101,110,101,114,97,116,101,100,32,98,121,32,0,47,103,114,101,121,115,57,47,49,0,0,0,0,0,0,0,72,101,108,118,101,116,105,99,97,45,78,97,114,114,111,119,45,66,111,108,100,79,98,108,105,113,117,101,0,0,0,0,112,97,114,115,105,110,103,32,102,105,110,105,115,104,101,100,0,0,0,0,0,0,0,0,32,50,10,0,0,0,0,0,47,103,114,101,121,115,56,47,56,0,0,0,0,0,0,0,78,68,95,114,97,110,107,40,102,114,111,109,41,32,60,32,78,68,95,114,97,110,107,40,116,111,41,0,0,0,0,0,68,79,84,70,79,78,84,80,65,84,72,0,0,0,0,0,81,0,0,0,0,0,0,0,100,97,114,107,115,108,97,116,101,98,108,117,101,0,0,0,47,103,114,101,121,115,56,47,55,0,0,0,0,0,0,0,98,122,46,115,105,122,101,0,47,115,101,116,95,115,99,97,108,101,32,123,0,0,0,0,101,112,115,102,0,0,0,0,47,103,114,101,121,115,56,47,54,0,0,0,0,0,0,0,47,103,114,101,121,115,56,47,53,0,0,0,0,0,0,0,117,110,109,97,116,99,104,101,100,32,39,40,39,32,105,110,32,115,116,121,108,101,58,32,37,115,10,0,0,0,0,0,105,110,32,114,111,117,116,101,115,112,108,105,110,101,115,44,32,99,97,110,110,111,116,32,102,105,110,100,32,78,79,82,77,65,76,32,101,100,103,101,10,0,0,0,0,0,0,0,47,103,114,101,121,115,56,47,52,0,0,0,0,0,0,0,47,98,108,117,101,115,51,47,50,0,0,0,0,0,0,0,47,103,114,101,121,115,56,47,51,0,0,0,0,0,0,0,37,100,32,0,0,0,0,0,100,111,117,98,108,101,99,105,114,99,108,101,0,0,0,0,47,103,114,101,121,115,56,47,50,0,0,0,0,0,0,0,49,55,0,0,0,0,0,0,112,110,103,58,120,100,111,116,0,0,0,0,0,0,0,0,47,103,114,101,121,115,56,47,49,0,0,0,0,0,0,0,37,115,32,118,97,108,117,101,32,37,115,32,62,32,37,100,32,45,32,116,111,111,32,108,97,114,103,101,32,45,32,105,103,110,111,114,101,100,0,0,60,47,118,58,115,104,97,112,101,62,10,0,0,0,0,0,47,103,114,101,121,115,55,47,55,0,0,0,0,0,0,0,32,80,97,103,101,115,58,32,37,100,10,0,0,0,0,0,47,103,114,101,121,115,55,47,54,0,0,0,0,0,0,0,72,101,108,118,101,116,105,99,97,45,78,97,114,114,111,119,45,66,111,108,100,0,0,0,112,97,114,115,105,110,103,32,97,98,111,114,116,101,100,0,85,115,105,110,103,32,37,115,58,32,37,115,58,37,115,10,0,0,0,0,0,0,0,0,49,50,48,48,0,0,0,0,47,103,114,101,121,115,55,47,53,0,0,0,0,0,0,0,102,111,110,116,112,97,116,104,0,0,0,0,0,0,0,0,100,97,114,107,115,101,97,103,114,101,101,110,0,0,0,0,37,100,0,0,0,0,0,0,106,112,101,58,115,118,103,0,47,103,114,101,121,115,55,47,52,0,0,0,0,0,0,0,120,109,108,0,0,0,0,0,115,112,108,105,110,101,115,0,47,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,49,46,48,32,100,101,102,0,34,32,110,97,109,101,61,34,0,0,0,0,0,0,0,0,47,103,114,101,121,115,55,47,51,0,0,0,0,0,0,0,47,103,114,101,121,115,55,47,50,0,0,0,0,0,0,0,116,114,117,110,99,97,116,105,110,103,32,115,116,121,108,101,32,39,37,115,39,10,0,0,47,103,114,101,121,115,55,47,49,0,0,0,0,0,0,0,47,98,108,117,101,115,51,47,49,0,0,0,0,0,0,0,47,103,114,101,121,115,54,47,54,0,0,0,0,0,0,0,115,113,117,97,114,101,0,0,47,103,114,101,121,115,54,47,53,0,0,0,0,0,0,0,49,54,0,0,0,0,0,0,115,118,103,58,100,111,116,0,47,103,114,101,121,115,54,47,52,0,0,0,0,0,0,0,73,109,112,114,111,112,101,114,32,37,115,32,118,97,108,117,101,32,37,115,32,45,32,105,103,110,111,114,101,100,0,0,34,47,62,0,0,0,0,0,47,103,114,101,121,115,54,47,51,0,0,0,0,0,0,0,32,84,105,116,108,101,58,32,0,0,0,0,0,0,0,0,47,103,114,101,121,115,54,47,50,0,0,0,0,0,0,0,99,111,110,100,101,110,115,101,100,0,0,0,0,0,0,0,112,97,114,115,101,114,32,110,111,116,32,115,117,115,112,101,110,100,101,100,0,0,0,0,45,50,10,0,0,0,0,0,47,103,114,101,121,115,54,47,49,0,0,0,0,0,0,0,45,45,0,0,0,0,0,0,115,118,103,0,0,0,0,0,100,97,114,107,115,97,108,109,111,110,0,0,0,0,0,0,47,103,114,101,121,115,53,47,53,0,0,0,0,0,0,0,60,63,120,109,108,0,0,0,85,110,107,110,111,119,110,32,34,115,112,108,105,110,101,115,34,32,118,97,108,117,101,58,32,34,37,115,34,32,45,32,105,103,110,111,114,101,100,10,0,0,0,0,0,0,0,0,47,99,111,111,114,100,102,111,110,116,32,99,111,111,114,100,45,102,111,110,116,45,102,97,109,105,108,121,32,102,105,110,100,102,111,110,116,32,56,32,115,99,97,108,101,102,111,110,116,32,100,101,102,0,0,0,60,109,97,112,32,105,100,61,34,0,0,0,0,0,0,0,47,103,114,101,121,115,53,47,52,0,0,0,0,0,0,0,117,32,33,61,32,118,0,0,47,103,114,101,121,115,53,47,51,0,0,0,0,0,0,0,117,110,109,97,116,99,104,101,100,32,39,41,39,32,105,110,32,115,116,121,108,101,58,32,37,115,10,0,0,0,0,0,47,103,114,101,121,115,53,47,50,0,0,0,0,0,0,0,47,97,99,99,101,110,116,56,47,56,0,0,0,0,0,0,47,103,114,101,121,115,53,47,49,0,0,0,0,0,0,0,38,35,52,53,59,0,0,0,114,101,99,116,97,110,103,108,101,0,0,0,0,0,0,0,47,103,114,101,121,115,52,47,52,0,0,0,0,0,0,0,49,53,0,0,0,0,0,0,101,112,115,58,100,111,116,0,47,103,114,101,121,115,52,47,51,0,0,0,0,0,0,0,80,79,73,78,84,45,83,73,90,69,0,0,0,0,0,0,32,101,32,0,0,0,0,0,47,103,114,101,121,115,52,47,50,0,0,0,0,0,0,0,35,0,0,0,0,0,0,0,47,103,114,101,121,115,52,47,49,0,0,0,0,0,0,0,72,101,108,118,101,116,105,99,97,45,78,97,114,114,111,119,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,112,97,114,115,101,114,32,115,117,115,112,101,110,100,101,100,0,0,0,0,0,0,0,0,83,105,110,103,108,101,10,0,47,103,114,101,121,115,51,47,51,0,0,0,0,0,0,0,58,0,0,0,0,0,0,0,112,115,0,0,0,0,0,0,100,97,114,107,114,101,100,0,47,103,114,101,121,115,51,47,50,0,0,0,0,0,0,0,102,111,110,116,110,97,109,101,58,32,34,37,115,34,32,114,101,115,111,108,118,101,100,32,116,111,58,32,37,115,10,0,101,112,115,0,0,0,0,0,101,115,0,0,0,0,0,0,47,100,101,102,97,117,108,116,45,102,111,110,116,45,102,97,109,105,108,121,32,47,84,105,109,101,115,45,82,111,109,97,110,32,100,101,102,0,0,0,32,0,0,0,0,0,0,0,47,103,114,101,121,115,51,47,49,0,0,0,0,0,0,0,98,108,117,101,0,0,0,0,82,105,103,104,116,0,0,0,47,103,114,101,101,110,115,57,47,57,0,0,0,0,0,0,110,101,115,116,105,110,103,32,110,111,116,32,97,108,108,111,119,101,100,32,105,110,32,115,116,121,108,101,58,32,37,115,10,0,0,0,0,0,0,0,47,103,114,101,101,110,115,57,47,56,0,0,0,0,0,0,47,97,99,99,101,110,116,56,47,55,0,0,0,0,0,0,47,103,114,101,101,110,115,57,47,55,0,0,0,0,0,0,114,101,99,116,0,0,0,0,49,48,48,46,48,48,10,0,47,103,114,101,101,110,115,57,47,54,0,0,0,0,0,0,49,52,0,0,0,0,0,0,112,115,58,100,111,116,0,0,47,103,114,101,101,110,115,57,47,53,0,0,0,0,0,0,112,111,105,110,116,45,115,105,122,101,0,0,0,0,0,0,32,108,32,0,0,0,0,0,47,103,114,101,101,110,115,57,47,52,0,0,0,0,0,0,32,45,97,110,99,104,111,114,32,101,0,0,0,0,0,0,91,105,110,116,101,114,110,97,108,32,99,111,117,114,105,101,114,93,0,0,0,0,0,0,37,115,58,37,100,58,32,37,115,32,110,101,97,114,32,108,105,110,101,32,37,100,10,0,47,103,114,101,101,110,115,57,47,51,0,0,0,0,0,0,72,101,108,118,101,116,105,99,97,45,66,111,108,100,79,98,108,105,113,117,101,0,0,0,105,108,108,101,103,97,108,32,99,104,97,114,97,99,116,101,114,40,115,41,32,105,110,32,112,117,98,108,105,99,32,105,100,0,0,0,0,0,0,0,115,121,110,116,97,120,32,101,114,114,111,114,0,0,0,0,47,103,114,101,101,110,115,57,47,50,0,0,0,0,0,0,102,105,103,0,0,0,0,0,111,117,116,32,111,102,32,109,101,109,111,114,121,10,0,0,37,100,0,0,0,0,0,0,103,100,0,0,0,0,0,0,100,97,114,107,111,114,99,104,105,100,0,0,0,0,0,0,114,97,110,107,0,0,0,0,47,103,114,101,101,110,115,57,47,49,0,0,0,0,0,0,197,208,211,198,0,0,0,0,114,117,101,0,0,0,0,0,47,99,111,111,114,100,45,102,111,110,116,45,102,97,109,105,108,121,32,47,84,105,109,101,115,45,82,111,109,97,110,32,100,101,102,0,0,0,0,0,100,101,102,97,117,108,116,32,0,0,0,0,0,0,0,0,47,103,114,101,101,110,115,56,47,56,0,0,0,0,0,0,45,62,0,0,0,0,0,0,100,111,116,0,0,0,0,0,47,103,114,101,101,110,115,56,47,55,0,0,0,0,0,0,108,105,103,104,116,103,114,101,121,0,0,0,0,0,0,0,69,68,95,116,111,95,118,105,114,116,40,111,114,105,103,41,32,33,61,32,78,85,76,76,0,0,0,0,0,0,0,0,47,103,114,101,101,110,115,56,47,54,0,0,0,0,0,0,47,97,99,99,101,110,116,56,47,54,0,0,0,0,0,0,47,103,114,101,101,110,115,56,47,53,0,0,0,0,0,0,107,101,121,0,0,0,0,0,99,111,109,112,111,110,101,110,116,0,0,0,0,0,0,0,99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,111,112,115,0,0,0,0,0,0,47,103,114,101,101,110,115,56,47,52,0,0,0,0,0,0,76,101,116,116,101,114,10,0,115,111,108,105,100,0,0,0,49,51,0,0,0,0,0,0,106,112,103,58,100,111,116,0,37,108,102,44,37,100,0,0,32,45,62,32,0,0,0,0,47,103,114,101,101,110,115,56,47,51,0,0,0,0,0,0,102,97,99,101,0,0,0,0,37,46,48,102,44,37,46,48,102,32,0,0,0,0,0,0,37,100,32,37,100,32,37,100,32,37,100,0,0,0,0,0,99,97,110,39,116,32,102,105,110,100,32,108,105,98,114,97,114,121,32,102,105,108,101,32,37,115,10,0,0,0,0,0,47,103,114,101,101,110,115,56,47,50,0,0,0,0,0,0,32,45,97,110,99,104,111,114,32,119,0,0,0,0,0,0,47,103,114,101,101,110,115,56,47,49,0,0,0,0,0,0,72,101,108,118,101,116,105,99,97,45,66,111,108,100,0,0,116,101,120,116,32,100,101,99,108,97,114,97,116,105,111,110,32,110,111,116,32,119,101,108,108,45,102,111,114,109,101,100,0,0,0,0,0,0,0,0,47,103,114,101,101,110,115,55,47,55,0,0,0,0,0,0,37,115,37,100,32,45,0,0,37,100,32,111,112,115,32,37,46,50,102,32,115,101,99,10,0,0,0,0,0,0,0,0,37,46,53,103,44,37,46,53,103,44,37,46,53,103,44,37,46,53,103,32,0,0,0,0,110,111,110,101,0,0,0,0,100,97,114,107,111,114,97,110,103,101,0,0,0,0,0,0,103,118,119,114,105,116,101,95,110,111,95,122,32,112,114,111,98,108,101,109,32,37,100,10,0,0,0,0,0,0,0,0,47,103,114,101,101,110,115,55,47,54,0,0,0,0,0,0,97,110,116,105,113,117,101,119,104,105,116,101,0,0,0,0,112,100,102,0,0,0,0,0,112,108,105,110,101,0,0,0,37,37,66,101,103,105,110,82,101,115,111,117,114,99,101,58,32,112,114,111,99,115,101,116,32,103,114,97,112,104,118,105,122,32,48,32,48,0,0,0,98,97,115,101,32,114,101,102,101,114,101,114,10,0,0,0,47,103,114,101,101,110,115,55,47,53,0,0,0,0,0,0,47,103,114,101,101,110,115,55,47,52,0,0,0,0,0,0,98,108,97,99,107,0,0,0,47,103,114,101,101,110,115,55,47,51,0,0,0,0,0,0,47,97,99,99,101,110,116,56,47,53,0,0,0,0,0,0,47,103,114,101,101,110,115,55,47,50,0,0,0,0,0,0,98,111,120,51,100,0,0,0,47,103,114,101,101,110,115,55,47,49,0,0,0,0,0,0,73,110,99,104,101,115,10,0,49,50,0,0,0,0,0,0,106,112,101,58,100,111,116,0,37,115,32,45,62,32,37,115,58,32,104,101,97,100,32,110,111,116,32,105,110,115,105,100,101,32,104,101,97,100,32,99,108,117,115,116,101,114,32,37,115,10,0,0,0,0,0,0,110,111,100,101,0,0,0,0,47,103,114,101,101,110,115,54,47,54,0,0,0,0,0,0,99,111,108,111,114,0,0,0,32,109,32,0,0,0,0,0,47,103,114,101,101,110,115,54,47,53,0,0,0,0,0,0,32,37,100,125,0,0,0,0,47,103,114,101,101,110,115,54,47,52,0,0,0,0,0,0,72,101,108,118,101,116,105,99,97,0,0,0,0,0,0,0,108,101,97,100,101,114,32,33,61,32,78,85,76,76,0,0,88,77,76,32,100,101,99,108,97,114,97,116,105,111,110,32,110,111,116,32,119,101,108,108,45,102,111,114,109,101,100,0,95,116,108,100,114,97,119,95,0,0,0,0,0,0,0,0,47,103,114,101,101,110,115,54,47,51,0,0,0,0,0,0,37,46,53,103,44,37,46,53,103,44,37,46,53,103,44,37,46,53,103,0,0,0,0,0,103,108,111,98,97,108,0,0,108,97,121,111,117,116,0,0,100,97,114,107,111,108,105,118,101,103,114,101,101,110,0,0,114,0,0,0,0,0,0,0,47,103,114,101,101,110,115,54,47,50,0,0,0,0,0,0,68,117,109,109,121,61,37,100,10,0,0,0,0,0,0,0,102,105,108,101,32,108,111,97,100,105,110,103,32,105,115,32,100,105,115,97,98,108,101,100,32,98,101,99,97,117,115,101,32,116,104,101,32,101,110,118,105,114,111,110,109,101,110,116,32,99,111,110,116,97,105,110,115,32,83,69,82,86,69,82,95,78,65,77,69,61,34,37,115,34,110,97,110,100,32,116,104,101,114,101,32,105,115,32,110,111,32,71,86,95,70,73,76,69,95,80,65,84,72,32,118,97,114,105,97,98,108,101,32,115,101,116,46,10,0,0,37,80,68,70,45,0,0,0,0,0,0,0,0,0,0,0,111,108,121,108,105,110,101,0,125,32,98,105,110,100,32,100,101,102,0,0,0,0,0,0,60,47,109,97,112,62,10,0,47,103,114,101,101,110,115,54,47,49,0,0,0,0,0,0,100,97,115,104,101,100,0,0,47,103,114,101,101,110,115,53,47,53,0,0,0,0,0,0,98,103,99,111,108,111,114,0,47,103,114,101,101,110,115,53,47,52,0,0,0,0,0,0,47,97,99,99,101,110,116,56,47,52,0,0,0,0,0,0,47,103,114,101,101,110,115,53,47,51,0,0,0,0,0,0,102,111,108,100,101,114,0,0,47,103,114,101,101,110,115,53,47,50,0,0,0,0,0,0,67,101,110,116,101,114,10,0,49,49,0,0,0,0,0,0,106,112,101,103,58,100,111,116,0,0,0,0,0,0,0,0,47,103,114,101,101,110,115,53,47,49,0,0,0,0,0,0,60,70,79,78,84,62,0,0,60,118,58,112,97,116,104,32,118,61,34,0,0,0,0,0,47,103,114,101,101,110,115,52,47,52,0,0,0,0,0,0,34,0,0,0,0,0,0,0,47,103,114,101,101,110,115,52,47,51,0,0,0,0,0,0,67,111,117,114,105,101,114,45,79,98,108,105,113,117,101,0,105,110,99,111,109,112,108,101,116,101,32,109,97,114,107,117,112,32,105,110,32,112,97,114,97,109,101,116,101,114,32,101,110,116,105,116,121,0,0,0,95,104,108,100,114,97,119,95,0,0,0,0,0,0,0,0,47,103,114,101,101,110,115,52,47,50,0,0,0,0,0,0,37,100,32,37,100,32,0,0,108,111,99,97,108,0,0,0,100,97,114,107,109,97,103,101,110,116,97,0,0,0,0,0,99,111,114,101,0,0,0,0,47,103,114,101,101,110,115,52,47,49,0,0,0,0,0,0,100,111,116,95,108,97,121,111,117,116,0,0,0,0,0,0,105,110,32,108,97,98,101,108,32,111,102,32,103,114,97,112,104,32,37,115,10,0,0,0,106,112,101,103,0,0,0,0,114,116,104,111,0,0,0,0,99,108,101,97,114,116,111,109,97,114,107,0,0,0,0,0,47,103,114,101,101,110,115,51,47,51,0,0,0,0,0,0,34,62,10,0,0,0,0,0,47,103,114,101,101,110,115,51,47,50,0,0,0,0,0,0,102,105,108,108,99,111,108,111,114,0,0,0,0,0,0,0,98,111,120,0,0,0,0,0,47,103,114,101,101,110,115,51,47,49,0,0,0,0,0,0,47,97,99,99,101,110,116,56,47,51,0,0,0,0,0,0,47,103,110,98,117,57,47,57,0,0,0,0,0,0,0,0,116,97,98,0,0,0,0,0,47,103,110,98,117,57,47,56,0,0,0,0,0,0,0,0,80,111,114,116,114,97,105,116,10,0,0,0,0,0,0,0,49,48,0,0,0,0,0,0,103,105,102,58,100,111,116,0,47,103,110,98,117,57,47,55,0,0,0,0,0,0,0,0,73,108,108,101,103,97,108,32,118,97,108,117,101,32,37,115,32,102,111,114,32,65,76,73,71,78,32,45,32,105,103,110,111,114,101,100,10,0,0,0,47,103,110,98,117,57,47,54,0,0,0,0,0,0,0,0,32,119,105,100,116,104,58,32,37,100,59,32,104,101,105,103,104,116,58,32,37,100,34,32,102,105,108,108,101,100,61,34,102,97,108,115,101,34,62,0,32,45,102,111,110,116,32,123,0,0,0,0,0,0,0,0,47,103,110,98,117,57,47,53,0,0,0,0,0,0,0,0,67,111,117,114,105,101,114,45,66,111,108,100,79,98,108,105,113,117,101,0,0,0,0,0,109,117,115,116,32,110,111,116,32,117,110,100,101,99,108,97,114,101,32,112,114,101,102,105,120,0,0,0,0,0,0,0,47,103,110,98,117,57,47,52,0,0,0,0,0,0,0,0,95,116,100,114,97,119,95,0,100,111,116,115,112,108,105,110,101,115,46,99,0,0,0,0,99,111,109,98,105,65,82,32,61,32,37,108,102,10,0,0,101,44,37,46,53,103,44,37,46,53,103,32,0,0,0,0,100,105,103,114,97,112,104,0,100,97,114,107,107,104,97,107,105,0,0,0,0,0,0,0,47,103,110,98,117,57,47,51,0,0,0,0,0,0,0,0,255,216,255,224,0,0,0,0,111,0,0,0,0,0,0,0,47,67,111,117,114,105,101,114,45,66,111,108,100,79,98,108,105,113,117,101,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,0,0,47,103,110,98,117,57,47,50,0,0,0,0,0,0,0,0,34,47,62,10,0,0,0,0,47,103,110,98,117,57,47,49,0,0,0,0,0,0,0,0,110,97,109,101,0,0,0,0,112,101,110,99,111,108,111,114,0,0,0,0,0,0,0,0,47,103,110,98,117,56,47,56,0,0,0,0,0,0,0,0,122,119,110,106,0,0,0,0,47,97,99,99,101,110,116,56,47,50,0,0,0,0,0,0,47,103,110,98,117,56,47,55,0,0,0,0,0,0,0,0,122,119,106,0,0,0,0,0,110,111,116,101,0,0,0,0,47,103,110,98,117,56,47,54,0,0,0,0,0,0,0,0,122,101,116,97,0,0,0,0,35,32,80,97,103,101,115,58,32,37,100,10,0,0,0,0,57,0,0,0,0,0,0,0,112,110,103,58,100,111,116,0,47,103,110,98,117,56,47,53,0,0,0,0,0,0,0,0,121,117,109,108,0,0,0,0,69,78,84,69,82,0,0,0,47,103,110,98,117,56,47,52,0,0,0,0,0,0,0,0,32,60,118,58,115,104,97,112,101,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,32,0,0,0,0,121,101,110,0,0,0,0,0,125,0,0,0,0,0,0,0,47,103,110,98,117,56,47,51,0,0,0,0,0,0,0,0,121,97,99,117,116,101,0,0,67,111,117,114,105,101,114,45,66,111,108,100,0,0,0,0,117,110,98,111,117,110,100,32,112,114,101,102,105,120,0,0,109,105,110,99,114,111,115,115,46,99,0,0,0,0,0,0,47,103,110,98,117,56,47,50,0,0,0,0,0,0,0,0,95,104,100,114,97,119,95,0,120,105,0,0,0,0,0,0,9,37,112,32,37,115,44,37,115,10,0,0,0,0,0,0,115,44,37,46,53,103,44,37,46,53,103,32,0,0,0,0,103,114,97,112,104,0,0,0,100,97,114,107,103,114,101,121,0,0,0,0,0,0,0,0,47,103,110,98,117,56,47,49,0,0,0,0,0,0,0,0,119,101,105,101,114,112,0,0,103,105,102,0,0,0,0,0,111,110,101,0,0,0,0,0,47,67,111,117,114,105,101,114,45,66,111,108,100,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,0,47,103,110,98,117,55,47,55,0,0,0,0,0,0,0,0,44,37,100,44,37,100,0,0,117,117,109,108,0,0,0,0,47,97,99,99,101,110,116,51,47,49,0,0,0,0,0,0,71,68,95,109,105,110,114,97,110,107,40,103,41,32,61,61,32,48,0,0,0,0,0,0,47,103,110,98,117,55,47,54,0,0,0,0,0,0,0,0,80,45,62,101,110,100,46,116,104,101,116,97,32,60,32,50,32,42,32,77,95,80,73,0,117,112,115,105,108,111,110,0,99,111,108,111,114,0,0,0,47,103,110,98,117,55,47,53,0,0,0,0,0,0,0,0,117,112,115,105,104,0,0,0,47,97,99,99,101,110,116,56,47,49,0,0,0,0,0,0,47,103,110,98,117,55,47,52,0,0,0,0,0,0,0,0,117,109,108,0,0,0,0,0,111,99,116,97,103,111,110,0,116,114,117,101,0,0,0,0,47,103,110,98,117,55,47,51,0,0,0,0,0,0,0,0,117,103,114,97,118,101,0,0,56,0,0,0,0,0,0,0,115,118,103,58,109,97,112,0,35,32,84,105,116,108,101,58,32,37,115,10,0,0,0,0,47,103,110,98,117,55,47,50,0,0,0,0,0,0,0,0,117,99,105,114,99,0,0,0,69,70,84,0,0,0,0,0,99,109,97,112,58,109,97,112,0,0,0,0,0,0,0,0,47,103,110,98,117,55,47,49,0,0,0,0,0,0,0,0,32,45,45,62,10,0,0,0,117,97,114,114,0,0,0,0,97,103,105,110,105,116,40,41,32,99,97,108,108,101,100,32,109,117,108,116,105,112,108,121,32,119,105,116,104,32,105,110,99,111,110,115,105,115,116,101,110,116,32,97,114,103,115,10,0,0,0,0,0,0,0,0,32,45,116,101,120,116,32,123,0,0,0,0,0,0,0,0,47,103,110,98,117,54,47,54,0,0,0,0,0,0,0,0,117,97,99,117,116,101,0,0,109,111,110,111,115,112,97,99,101,0,0,0,0,0,0,0,99,97,110,110,111,116,32,99,104,97,110,103,101,32,115,101,116,116,105,110,103,32,111,110,99,101,32,112,97,114,115,105,110,103,32,104,97,115,32,98,101,103,117,110,0,0,0,0,47,103,110,98,117,54,47,53,0,0,0,0,0,0,0,0,95,108,100,114,97,119,95,0,117,65,114,114,0,0,0,0,115,111,117,114,99,101,32,112,111,105,110,116,32,110,111,116,32,105,110,32,97,110,121,32,116,114,105,97,110,103,108,101,0,0,0,0,0,0,0,0,37,46,53,103,32,37,46,53,103,0,0,0,0,0,0,0,115,117,98,103,114,97,112,104,0,0,0,0,0,0,0,0,100,97,114,107,103,114,101,101,110,0,0,0,0,0,0,0,47,103,110,98,117,54,47,52,0,0,0,0,0,0,0,0,116,114,97,100,101,0,0,0,71,73,70,56,0,0,0,0,105,110,101,0,0,0,0,0,47,67,111,117,114,105,101,114,45,79,98,108,105,113,117,101,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,47,103,110,98,117,54,47,51,0,0,0,0,0,0,0,0,115,104,97,112,101,102,105,108,101,0,0,0,0,0,0,0,37,100,44,37,100,0,0,0,116,105,109,101,115,0,0,0,47,103,110,98,117,54,47,50,0,0,0,0,0,0,0,0,116,105,108,100,101,0,0,0,35,102,56,102,56,102,56,0,99,97,110,110,111,116,32,114,101,45,97,108,108,111,99,97,116,101,32,112,115,10,0,0,47,103,110,98,117,54,47,49,0,0,0,0,0,0,0,0,108,111,115,116,32,37,115,32,37,115,32,101,100,103,101,10,0,0,0,0,0,0,0,0,116,104,111,114,110,0,0,0,47,97,99,99,101,110,116,55,47,55,0,0,0,0,0,0,47,103,110,98,117,53,47,53,0,0,0,0,0,0,0,0,116,104,105,110,115,112,0,0,115,101,97,114,99,104,115,105,122,101,0,0,0,0,0,0,115,101,112,116,97,103,111,110,0,0,0,0,0,0,0,0,47,103,110,98,117,53,47,52,0,0,0,0,0,0,0,0,116,104,101,116,97,115,121,109,0,0,0,0,0,0,0,0,103,114,97,112,104,32,0,0,55,0,0,0,0,0,0,0,101,112,115,58,109,97,112,0,35,32,71,101,110,101,114,97,116,101,100,32,98,121,32,37,115,32,118,101,114,115,105,111,110,32,37,115,32,40,37,115,41,10,0,0,0,0,0,0,47,103,110,98,117,53,47,51,0,0,0,0,0,0,0,0,116,104,101,116,97,0,0,0,73,71,72,84,0,0,0,0,47,103,110,98,117,53,47,50,0,0,0,0,0,0,0,0,32,32,32,32,32,32,60,33,45,45,32,0,0,0,0,0,116,104,101,114,101,52,0,0,32,99,114,101,97,116,101,32,116,101,120,116,32,0,0,0,47,103,110,98,117,53,47,49,0,0,0,0,0,0,0,0,116,97,117,0,0,0,0,0,67,111,117,114,105,101,114,0,114,101,113,117,101,115,116,101,100,32,102,101,97,116,117,114,101,32,114,101,113,117,105,114,101,115,32,88,77,76,95,68,84,68,32,115,117,112,112,111,114,116,32,105,110,32,69,120,112,97,116,0,0,0,0,0,47,103,110,98,117,52,47,52,0,0,0,0,0,0,0,0,49,46,50,0,0,0,0,0,115,122,108,105,103,0,0,0,37,115,32,119,97,115,32,97,108,114,101,97,100,121,32,105,110,32,97,32,114,97,110,107,115,101,116,44,32,100,101,108,101,116,101,100,32,102,114,111,109,32,99,108,117,115,116,101,114,32,37,115,10,0,0,0,115,97,109,112,108,101,112,111,105,110,116,115,0,0,0,0,110,111,100,101,0,0,0,0,37,108,102,0,0,0,0,0,100,97,114,107,103,114,97,121,0,0,0,0,0,0,0,0,47,103,110,98,117,52,47,51,0,0,0,0,0,0,0,0,98,108,97,99,107,0,0,0,115,117,112,101,0,0,0,0,106,112,101,103,58,115,118,103,0,0,0,0,0,0,0,0,98,109,112,0,0,0,0,0,97,108,115,101,0,0,0,0,47,67,111,117,114,105,101,114,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,115,121,110,116,97,120,32,101,114,114,111,114,0,0,0,0,47,103,110,98,117,52,47,50,0,0,0,0,0,0,0,0,37,100,44,37,100,44,37,100,44,37,100,0,0,0,0,0,115,117,112,51,0,0,0,0,47,103,110,98,117,52,47,49,0,0,0,0,0,0,0,0,115,117,112,50,0,0,0,0,35,49,48,49,48,49,48,0,47,103,110,98,117,51,47,51,0,0,0,0,0,0,0,0,115,117,112,49,0,0,0,0,47,97,99,99,101,110,116,55,47,54,0,0,0,0,0,0,47,103,110,98,117,51,47,50,0,0,0,0,0,0,0,0,115,117,112,0,0,0,0,0,104,101,120,97,103,111,110,0,47,103,110,98,117,51,47,49,0,0,0,0,0,0,0,0,115,117,109,0,0,0,0,0,54,0,0,0,0,0,0,0,112,115,58,109,97,112,0,0,35,70,73,71,32,51,46,50,10,0,0,0,0,0,0,0,47,100,97,114,107,50,56,47,56,0,0,0,0,0,0,0,115,117,98,101,0,0,0,0,97,108,105,103,110,0,0,0,47,100,97,114,107,50,56,47,55,0,0,0,0,0,0,0,121,101,108,108,111,119,0,0,115,117,98,0,0,0,0,0,32,99,114,101,97,116,101,32,111,118,97,108,32,0,0,0,47,100,97,114,107,50,56,47,54,0,0,0,0,0,0,0,115,112,97,100,101,115,0,0,66,111,111,107,109,97,110,45,76,105,103,104,116,73,116,97,108,105,99,0,0,0,0,0,101,110,116,105,116,121,32,100,101,99,108,97,114,101,100,32,105,110,32,112,97,114,97,109,101,116,101,114,32,101,110,116,105,116,121,0,0,0,0,0,47,100,97,114,107,50,56,47,53,0,0,0,0,0,0,0,120,100,111,116,118,101,114,115,105,111,110,0,0,0,0,0,115,105,109,0,0,0,0,0,60,47,72,84,77,76,62,0,114,101,99,111,114,100,0,0,101,100,103,101,0,0,0,0,100,97,114,107,103,111,108,100,101,110,114,111,100,0,0,0,47,100,97,114,107,50,56,47,52,0,0,0,0,0,0,0,115,105,103,109,97,102,0,0,66,77,0,0,0,0,0,0,111,109,112,111,117,110,100,0,47,72,101,108,118,101,116,105,99,97,45,66,111,108,100,79,98,108,105,113,117,101,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,47,100,97,114,107,50,56,47,51,0,0,0,0,0,0,0,37,100,44,37,100,44,37,100,0,0,0,0,0,0,0,0,115,105,103,109,97,0,0,0,47,100,97,114,107,50,56,47,50,0,0,0,0,0,0,0,115,104,121,0,0,0,0,0,35,102,48,102,48,102,48,0,32,99,111,111,114,100,115,61,34,0,0,0,0,0,0,0,108,97,98,101,108,0,0,0,115,104,97,112,101,102,105,108,101,0,0,0,0,0,0,0,47,37,115,47,37,115,0,0,88,49,49,47,0,0,0,0,105,103,104,116,103,114,101,121,0,0,0,0,0,0,0,0,104,105,116,101,0,0,0,0,108,97,99,107,0,0,0,0,110,32,33,61,32,78,68,95,110,101,120,116,40,110,41,0,121,101,108,108,111,119,103,114,101,101,110,0,0,0,0,0,47,100,97,114,107,50,56,47,49,0,0,0,0,0,0,0,121,101,108,108,111,119,52,0,121,101,108,108,111,119,51,0,115,101,99,116,0,0,0,0,121,101,108,108,111,119,50,0,121,101,108,108,111,119,49,0,121,101,108,108,111,119,0,0,119,104,105,116,101,115,109,111,107,101,0,0,0,0,0,0,119,104,105,116,101,0,0,0,119,104,101,97,116,52,0,0,47,97,99,99,101,110,116,55,47,53,0,0,0,0,0,0,119,104,101,97,116,51,0,0,119,104,101,97,116,50,0,0,47,100,97,114,107,50,55,47,55,0,0,0,0,0,0,0,119,104,101,97,116,49,0,0,119,104,101,97,116,0,0,0,115,100,111,116,0,0,0,0,118,105,111,108,101,116,114,101,100,52,0,0,0,0,0,0,118,105,111,108,101,116,114,101,100,51,0,0,0,0,0,0,118,105,111,108,101,116,114,101,100,50,0,0,0,0,0,0,118,105,111,108,101,116,114,101,100,49,0,0,0,0,0,0,118,105,111,108,101,116,114,101,100,0,0,0,0,0,0,0,38,103,116,59,0,0,0,0,118,105,111,108,101,116,0,0,112,101,110,116,97,103,111,110,0,0,0,0,0,0,0,0,116,117,114,113,117,111,105,115,101,52,0,0,0,0,0,0,116,117,114,113,117,111,105,115,101,51,0,0,0,0,0,0,47,100,97,114,107,50,55,47,54,0,0,0,0,0,0,0,116,117,114,113,117,111,105,115,101,50,0,0,0,0,0,0,116,117,114,113,117,111,105,115,101,49,0,0,0,0,0,0,115,99,97,114,111,110,0,0,116,117,114,113,117,111,105,115,101,0,0,0,0,0,0,0,116,114,97,110,115,112,97,114,101,110,116,0,0,0,0,0,115,98,113,117,111,0,0,0,116,111,109,97,116,111,52,0,116,111,109,97,116,111,51,0,116,111,109,97,116,111,50,0,53,0,0,0,0,0,0,0,106,112,103,58,109,97,112,0,116,111,109,97,116,111,49,0,116,111,109,97,116,111,0,0,116,104,105,115,116,108,101,52,0,0,0,0,0,0,0,0,35,32,101,110,100,32,111,102,32,70,73,71,32,102,105,108,101,10,0,0,0,0,0,0,47,100,97,114,107,50,55,47,53,0,0,0,0,0,0,0,116,104,105,115,116,108,101,51,0,0,0,0,0,0,0,0,116,104,105,115,116,108,101,50,0,0,0,0,0,0,0,0,35,101,48,101,48,101,48,0,116,104,105,115,116,108,101,49,0,0,0,0,0,0,0,0,116,104,105,115,116,108,101,0,116,97,110,52,0,0,0,0,116,97,110,51,0,0,0,0,60,66,82,62,0,0,0,0,116,97,110,50,0,0,0,0,116,97,110,49,0,0,0,0,116,97,110,0,0,0,0,0,115,116,101,101,108,98,108,117,101,52,0,0,0,0,0,0,47,100,97,114,107,50,55,47,52,0,0,0,0,0,0,0,115,116,101,101,108,98,108,117,101,51,0,0,0,0,0,0,119,104,105,116,101,0,0,0,115,116,101,101,108,98,108,117,101,50,0,0,0,0,0,0,114,115,113,117,111,0,0,0,115,116,101,101,108,98,108,117,101,49,0,0,0,0,0,0,115,116,101,101,108,98,108,117,101,0,0,0,0,0,0,0,115,112,114,105,110,103,103,114,101,101,110,52,0,0,0,0,115,112,114,105,110,103,103,114,101,101,110,51,0,0,0,0])
+.concat([32,45,111,117,116,108,105,110,101,32,0,0,0,0,0,0,115,112,114,105,110,103,103,114,101,101,110,50,0,0,0,0,115,112,114,105,110,103,103,114,101,101,110,49,0,0,0,0,115,112,114,105,110,103,103,114,101,101,110,0,0,0,0,0,115,110,111,119,52,0,0,0,47,100,97,114,107,50,55,47,51,0,0,0,0,0,0,0,115,110,111,119,51,0,0,0,115,110,111,119,50,0,0,0,114,115,97,113,117,111,0,0,115,110,111,119,49,0,0,0,115,110,111,119,0,0,0,0,115,108,97,116,101,103,114,101,121,0,0,0,0,0,0,0,108,105,103,104,116,0,0,0,115,108,97,116,101,103,114,97,121,52,0,0,0,0,0,0,115,108,97,116,101,103,114,97,121,51,0,0,0,0,0,0,115,108,97,116,101,103,114,97,121,50,0,0,0,0,0,0,117,110,101,120,112,101,99,116,101,100,32,112,97,114,115,101,114,32,115,116,97,116,101,32,45,32,112,108,101,97,115,101,32,115,101,110,100,32,97,32,98,117,103,32,114,101,112,111,114,116,0,0,0,0,0,0,35,32,0,0,0,0,0,0,115,108,97,116,101,103,114,97,121,49,0,0,0,0,0,0,115,108,97,116,101,103,114,97,121,0,0,0,0,0,0,0,47,100,97,114,107,50,55,47,50,0,0,0,0,0,0,0,115,108,97,116,101,98,108,117,101,52,0,0,0,0,0,0,95,100,114,97,119,95,0,0,115,108,97,116,101,98,108,117,101,51,0,0,0,0,0,0,114,108,109,0,0,0,0,0,115,108,97,116,101,98,108,117,101,50,0,0,0,0,0,0,115,108,97,116,101,98,108,117,101,49,0,0,0,0,0,0,99,97,110,110,111,116,32,109,97,108,108,111,99,32,111,112,115,0,0,0,0,0,0,0,115,108,97,116,101,98,108,117,101,0,0,0,0,0,0,0,37,46,53,103,0,0,0,0,115,107,121,98,108,117,101,52,0,0,0,0,0,0,0,0,116,97,105,108,112,111,114,116,0,0,0,0,0,0,0,0,108,97,98,101,108,0,0,0,115,107,121,98,108,117,101,51,0,0,0,0,0,0,0,0,115,107,121,98,108,117,101,50,0,0,0,0,0,0,0,0,100,97,114,107,99,121,97,110,0,0,0,0,0,0,0,0,115,107,121,98,108,117,101,49,0,0,0,0,0,0,0,0,115,107,121,98,108,117,101,0,47,100,97,114,107,50,55,47,49,0,0,0,0,0,0,0,115,105,101,110,110,97,52,0,115,105,101,110,110,97,51,0,114,104,111,0,0,0,0,0,115,105,101,110,110,97,50,0,115,105,101,110,110,97,49,0,115,105,101,110,110,97,0,0,115,101,97,115,104,101,108,108,52,0,0,0,0,0,0,0,115,101,97,115,104,101,108,108,51,0,0,0,0,0,0,0,112,115,0,0,0,0,0,0,115,101,97,115,104,101,108,108,50,0,0,0,0,0,0,0,85,84,70,56,32,99,111,100,101,115,32,62,32,51,32,98,121,116,101,115,32,97,114,101,32,110,111,116,32,99,117,114,114,101,110,116,108,121,32,115,117,112,112,111,114,116,101,100,46,32,79,114,32,112,101,114,104,97,112,115,32,34,45,71,99,104,97,114,115,101,116,61,108,97,116,105,110,49,34,32,105,115,32,110,101,101,100,101,100,63,10,0,0,0,0,0,47,72,101,108,118,101,116,105,99,97,45,66,111,108,100,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,115,101,97,115,104,101,108,108,49,0,0,0,0,0,0,0,115,101,97,115,104,101,108,108,0,0,0,0,0,0,0,0,47,100,97,114,107,50,54,47,54,0,0,0,0,0,0,0,115,101,97,103,114,101,101,110,52,0,0,0,0,0,0,0,115,101,97,103,114,101,101,110,51,0,0,0,0,0,0,0,114,102,108,111,111,114,0,0,115,101,97,103,114,101,101,110,50,0,0,0,0,0,0,0,115,101,97,103,114,101,101,110,49,0,0,0,0,0,0,0,115,101,97,103,114,101,101,110,0,0,0,0,0,0,0,0,115,97,110,100,121,98,114,111,119,110,0,0,0,0,0,0,115,97,108,109,111,110,52,0,115,97,108,109,111,110,51,0,115,97,108,109,111,110,50,0,115,97,108,109,111,110,49,0,47,100,97,114,107,50,54,47,53,0,0,0,0,0,0,0,115,97,108,109,111,110,0,0,115,97,100,100,108,101,98,114,111,119,110,0,0,0,0,0,114,101,103,0,0,0,0,0,116,101,101,0,0,0,0,0,114,111,121,97,108,98,108,117,101,52,0,0,0,0,0,0,32,97,108,116,61,34,34,0,114,111,121,97,108,98,108,117,101,51,0,0,0,0,0,0,114,111,121,97,108,98,108,117,101,50,0,0,0,0,0,0,114,111,121,97,108,98,108,117,101,49,0,0,0,0,0,0,114,111,121,97,108,98,108,117,101,0,0,0,0,0,0,0,114,111,115,121,98,114,111,119,110,52,0,0,0,0,0,0,98,108,97,99,107,0,0,0,114,111,115,121,98,114,111,119,110,51,0,0,0,0,0,0,75,80,95,76,101,102,116,0,114,111,115,121,98,114,111,119,110,50,0,0,0,0,0,0,47,100,97,114,107,50,54,47,52,0,0,0,0,0,0,0,114,111,115,121,98,114,111,119,110,49,0,0,0,0,0,0,114,111,115,121,98,114,111,119,110,0,0,0,0,0,0,0,114,101,97,108,0,0,0,0,114,101,100,52,0,0,0,0,114,101,100,51,0,0,0,0,114,101,100,50,0,0,0,0,114,101,100,49,0,0,0,0,114,101,100,0,0,0,0,0,112,117,114,112,108,101,52,0,112,117,114,112,108,101,51,0,47,97,99,99,101,110,116,55,47,52,0,0,0,0,0,0,112,117,114,112,108,101,50,0,47,100,97,114,107,50,54,47,51,0,0,0,0,0,0,0,112,117,114,112,108,101,49,0,112,117,114,112,108,101,0,0,114,100,113,117,111,0,0,0,112,111,119,100,101,114,98,108,117,101,0,0,0,0,0,0,112,108,117,109,52,0,0,0,112,108,117,109,51,0,0,0,112,108,117,109,50,0,0,0,112,108,117,109,49,0,0,0,112,108,117,109,0,0,0,0,104,111,117,115,101,0,0,0,112,105,110,107,52,0,0,0,112,105,110,107,51,0,0,0,47,100,97,114,107,50,54,47,50,0,0,0,0,0,0,0,112,105,110,107,50,0,0,0,112,105,110,107,49,0,0,0,114,99,101,105,108,0,0,0,112,105,110,107,0,0,0,0,112,101,114,117,0,0,0,0,112,101,97,99,104,112,117,102,102,52,0,0,0,0,0,0,112,101,97,99,104,112,117,102,102,51,0,0,0,0,0,0,112,101,97,99,104,112,117,102,102,50,0,0,0,0,0,0,52,0,0,0,0,0,0,0,106,112,101,58,109,97,112,0,112,101,97,99,104,112,117,102,102,49,0,0,0,0,0,0,112,101,97,99,104,112,117,102,102,0,0,0,0,0,0,0,112,97,112,97,121,97,119,104,105,112,0,0,0,0,0,0,47,100,97,114,107,50,54,47,49,0,0,0,0,0,0,0,112,97,108,101,118,105,111,108,101,116,114,101,100,52,0,0,37,48,51,111,0,0,0,0,112,97,108,101,118,105,111,108,101,116,114,101,100,51,0,0,114,97,114,114,0,0,0,0,112,97,108,101,118,105,111,108,101,116,114,101,100,50,0,0,112,97,108,101,118,105,111,108,101,116,114,101,100,49,0,0,112,97,108,101,118,105,111,108,101,116,114,101,100,0,0,0,112,97,108,101,116,117,114,113,117,111,105,115,101,52,0,0,112,97,108,101,116,117,114,113,117,111,105,115,101,51,0,0,73,108,108,101,103,97,108,32,97,116,116,114,105,98,117,116,101,32,37,115,32,105,110,32,37,115,32,45,32,105,103,110,111,114,101,100,10,0,0,0,112,97,108,101,116,117,114,113,117,111,105,115,101,50,0,0,112,97,108,101,116,117,114,113,117,111,105,115,101,49,0,0,112,97,108,101,116,117,114,113,117,111,105,115,101,0,0,0,47,100,97,114,107,50,53,47,53,0,0,0,0,0,0,0,112,97,108,101,103,114,101,101,110,52,0,0,0,0,0,0,112,97,108,101,103,114,101,101,110,51,0,0,0,0,0,0,114,97,113,117,111,0,0,0,116,101,97,108,0,0,0,0,112,97,108,101,103,114,101,101,110,50,0,0,0,0,0,0,112,97,108,101,103,114,101,101,110,49,0,0,0,0,0,0,112,97,108,101,103,114,101,101,110,0,0,0,0,0,0,0,112,97,108,101,103,111,108,100,101,110,114,111,100,0,0,0,119,104,105,116,101,0,0,0,111,114,99,104,105,100,52,0,111,114,99,104,105,100,51,0,99,111,117,114,0,0,0,0,111,114,99,104,105,100,50,0,111,114,99,104,105,100,49,0,47,100,97,114,107,50,53,47,52,0,0,0,0,0,0,0,111,114,99,104,105,100,0,0,111,114,97,110,103,101,114,101,100,52,0,0,0,0,0,0,114,97,110,103,0,0,0,0,111,114,97,110,103,101,114,101,100,51,0,0,0,0,0,0,111,114,97,110,103,101,114,101,100,50,0,0,0,0,0,0,111,114,97,110,103,101,114,101,100,49,0,0,0,0,0,0,66,111,111,107,109,97,110,45,76,105,103,104,116,0,0,0,111,114,97,110,103,101,114,101,100,0,0,0,0,0,0,0,111,114,97,110,103,101,52,0,111,114,97,110,103,101,51,0,100,111,99,117,109,101,110,116,32,105,115,32,110,111,116,32,115,116,97,110,100,97,108,111,110,101,0,0,0,0,0,0,111,114,97,110,103,101,50,0,110,111,110,116,101,114,109,105,110,97,116,101,100,32,99,111,109,109,101,110,116,32,105,110,32,108,105,110,101,32,37,100,10,0,0,0,0,0,0,0,111,114,97,110,103,101,49,0,111,117,116,32,111,102,32,109,101,109,111,114,121,0,0,0,47,100,97,114,107,50,53,47,51,0,0,0,0,0,0,0,111,114,97,110,103,101,0,0,84,32,0,0,0,0,0,0,111,108,105,118,101,100,114,97,98,52,0,0,0,0,0,0,114,97,100,105,99,0,0,0,100,111,116,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,101,32,97,115,112,101,99,116,32,97,116,116,114,105,98,117,116,101,32,102,111,114,32,100,105,115,99,111,110,110,101,99,116,101,100,32,103,114,97,112,104,115,32,111,114,32,103,114,97,112,104,115,32,119,105,116,104,32,99,108,117,115,116,101,114,115,10,0,0,0,0,0,0,111,108,105,118,101,100,114,97,98,51,0,0,0,0,0,0,111,108,105,118,101,100,114,97,98,50,0,0,0,0,0,0,93,59,10,0,0,0,0,0,111,108,105,118,101,100,114,97,98,49,0,0,0,0,0,0,44,37,46,53,103,0,0,0,111,108,105,118,101,100,114,97,98,0,0,0,0,0,0,0,104,101,97,100,112,111,114,116,0,0,0,0,0,0,0,0,111,108,100,108,97,99,101,0,110,111,110,101,0,0,0,0,100,97,114,107,98,108,117,101,0,0,0,0,0,0,0,0,110,97,118,121,98,108,117,101,0,0,0,0,0,0,0,0,110,97,118,121,0,0,0,0,47,100,97,114,107,50,53,47,50,0,0,0,0,0,0,0,110,97,118,97,106,111,119,104,105,116,101,52,0,0,0,0,110,97,118,97,106,111,119,104,105,116,101,51,0,0,0,0,114,65,114,114,0,0,0,0,110,97,118,97,106,111,119,104,105,116,101,50,0,0,0,0,110,97,118,97,106,111,119,104,105,116,101,49,0,0,0,0,110,97,118,97,106,111,119,104,105,116,101,0,0,0,0,0,109,111,99,99,97,115,105,110,0,0,0,0,0,0,0,0,109,105,115,116,121,114,111,115,101,52,0,0,0,0,0,0,37,33,80,83,45,65,100,111,98,101,45,0,0,0,0,0,109,105,115,116,121,114,111,115,101,51,0,0,0,0,0,0,73,110,118,97,108,105,100,32,51,45,98,121,116,101,32,85,84,70,56,32,102,111,117,110,100,32,105,110,32,105,110,112,117,116,46,32,80,101,114,104,97,112,115,32,34,45,71,99,104,97,114,115,101,116,61,108,97,116,105,110,49,34,32,105,115,32,110,101,101,100,101,100,63,10,0,0,0,0,0,0,47,72,101,108,118,101,116,105,99,97,45,79,98,108,105,113,117,101,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,0,0,0,0,109,105,115,116,121,114,111,115,101,50,0,0,0,0,0,0,120,120,120,0,0,0,0,0,109,105,115,116,121,114,111,115,101,49,0,0,0,0,0,0,47,100,97,114,107,50,53,47,49,0,0,0,0,0,0,0,109,105,115,116,121,114,111,115,101,0,0,0,0,0,0,0,109,105,110,116,99,114,101,97,109,0,0,0,0,0,0,0,113,117,111,116,0,0,0,0,109,105,100,110,105,103,104,116,98,108,117,101,0,0,0,0,109,101,100,105,117,109,118,105,111,108,101,116,114,101,100,0,109,101,100,105,117,109,116,117,114,113,117,111,105,115,101,0,109,101,100,105,117,109,115,112,114,105,110,103,103,114,101,101,110,0,0,0,0,0,0,0,109,101,100,105,117,109,115,108,97,116,101,98,108,117,101,0,109,101,100,105,117,109,115,101,97,103,114,101,101,110,0,0,105,110,32,108,97,98,101,108,32,111,102,32,101,100,103,101,32,37,115,32,37,115,32,37,115,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,101,100,105,117,109,112,117,114,112,108,101,52,0,0,0,109,101,100,105,117,109,112,117,114,112,108,101,51,0,0,0,47,100,97,114,107,50,52,47,52,0,0,0,0,0,0,0,109,101,100,105,117,109,112,117,114,112,108,101,50,0,0,0,109,101,100,105,117,109,112,117,114,112,108,101,49,0,0,0,112,115,105,0,0,0,0,0,35,101,56,101,56,101,56,0,109,101,100,105,117,109,112,117,114,112,108,101,0,0,0,0,109,101,100,105,117,109,111,114,99,104,105,100,52,0,0,0,32,116,105,116,108,101,61,34,0,0,0,0,0,0,0,0,109,101,100,105,117,109,111,114,99,104,105,100,51,0,0,0,109,101,100,105,117,109,111,114,99,104,105,100,50,0,0,0,109,101,100,105,117,109,111,114,99,104,105,100,49,0,0,0,109,101,100,105,117,109,111,114,99,104,105,100,0,0,0,0,69,68,95,116,111,95,118,105,114,116,40,111,114,105,103,41,32,61,61,32,78,85,76,76,0,0,0,0,0,0,0,0,109,101,100,105,117,109,98,108,117,101,0,0,0,0,0,0,109,101,100,105,117,109,97,113,117,97,109,97,114,105,110,101,0,0,0,0,0,0,0,0,47,100,97,114,107,50,52,47,51,0,0,0,0,0,0,0,109,97,114,111,111,110,52,0,109,97,114,111,111,110,51,0,112,114,111,112,0,0,0,0,109,97,114,111,111,110,50,0,109,97,114,111,111,110,49,0,109,97,114,111,111,110,0,0,109,97,103,101,110,116,97,52,0,0,0,0,0,0,0,0,109,97,103,101,110,116,97,51,0,0,0,0,0,0,0,0,109,97,103,101,110,116,97,50,0,0,0,0,0,0,0,0,109,97,103,101,110,116,97,49,0,0,0,0,0,0,0,0,47,97,99,99,101,110,116,55,47,51,0,0,0,0,0,0,109,97,103,101,110,116,97,0,47,100,97,114,107,50,52,47,50,0,0,0,0,0,0,0,108,105,110,101,110,0,0,0,108,105,109,101,103,114,101,101,110,0,0,0,0,0,0,0,112,114,111,100,0,0,0,0,108,105,103,104,116,121,101,108,108,111,119,52,0,0,0,0,108,105,103,104,116,121,101,108,108,111,119,51,0,0,0,0,108,105,103,104,116,121,101,108,108,111,119,50,0,0,0,0,108,105,103,104,116,121,101,108,108,111,119,49,0,0,0,0,80,114,111,116,111,71,114,97,112,104,0,0,0,0,0,0,108,105,103,104,116,121,101,108,108,111,119,0,0,0,0,0,108,105,103,104,116,115,116,101,101,108,98,108,117,101,52,0,41,10,0,0,0,0,0,0,112,97,114,97,108,108,101,108,111,103,114,97,109,0,0,0,108,105,103,104,116,115,116,101,101,108,98,108,117,101,51,0,108,105,98,112,97,116,104,47,37,115,58,37,100,58,32,37,115,10,0,0,0,0,0,0,108,105,103,104,116,115,116,101,101,108,98,108,117,101,50,0,47,100,97,114,107,50,52,47,49,0,0,0,0,0,0,0,108,105,103,104,116,115,116,101,101,108,98,108,117,101,49,0,108,105,103,104,116,115,116,101,101,108,98,108,117,101,0,0,112,114,105,109,101,0,0,0,108,105,103,104,116,115,108,97,116,101,103,114,101,121,0,0,108,105,103,104,116,115,108,97,116,101,103,114,97,121,0,0,108,105,103,104,116,115,108,97,116,101,98,108,117,101,0,0,110,111,100,101,32,0,0,0,108,105,103,104,116,115,107,121,98,108,117,101,52,0,0,0,108,105,103,104,116,115,107,121,98,108,117,101,51,0,0,0,51,0,0,0,0,0,0,0,108,105,103,104,116,115,107,121,98,108,117,101,50,0,0,0,106,112,101,103,58,109,97,112,0,0,0,0,0,0,0,0,32,40,0,0,0,0,0,0,108,105,103,104,116,115,107,121,98,108,117,101,49,0,0,0,108,105,103,104,116,115,107,121,98,108,117,101,0,0,0,0,47,100,97,114,107,50,51,47,51,0,0,0,0,0,0,0,108,105,103,104,116,115,101,97,103,114,101,101,110,0,0,0,108,105,103,104,116,115,97,108,109,111,110,52,0,0,0,0,112,111,117,110,100,0,0,0,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,49,102,32,37,46,52,102,32,37,100,32,37,46,49,102,32,37,46,49,102,32,37,100,32,37,100,32,37,115,92,48,48,49,10,0,0,108,105,103,104,116,115,97,108,109,111,110,51,0,0,0,0,108,105,103,104,116,115,97,108,109,111,110,50,0,0,0,0,108,105,103,104,116,115,97,108,109,111,110,49,0,0,0,0,108,105,103,104,116,115,97,108,109,111,110,0,0,0,0,0,108,105,103,104,116,112,105,110,107,52,0,0,0,0,0,0,115,114,99,0,0,0,0,0,108,105,103,104,116,112,105,110,107,51,0,0,0,0,0,0,32,118,101,114,115,105,111,110,32,0,0,0,0,0,0,0,108,105,103,104,116,112,105,110,107,50,0,0,0,0,0,0,97,115,112,101,99,116,0,0,0,0,0,0,0,0,0,0,108,105,103,104,116,112,105,110,107,49,0,0,0,0,0,0,47,100,97,114,107,50,51,47,50,0,0,0,0,0,0,0,108,105,103,104,116,112,105,110,107,0,0,0,0,0,0,0,76,97,121,111,117,116,32,116,121,112,101,58,32,34,37,115,34,32,110,111,116,32,114,101,99,111,103,110,105,122,101,100,46,32,85,115,101,32,111,110,101,32,111,102,58,37,115,10,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,108,105,103,104,116,103,114,101,121,0,0,0,0,0,0,0,112,108,117,115,109,110,0,0,115,105,108,118,101,114,0,0,108,105,103,104,116,103,114,97,121,0,0,0,0,0,0,0,108,105,103,104,116,103,111,108,100,101,110,114,111,100,121,101,108,108,111,119,0,0,0,0,108,105,103,104,116,103,111,108,100,101,110,114,111,100,52,0,108,105,103,104,116,103,111,108,100,101,110,114,111,100,51,0,32,99,114,101,97,116,101,32,112,111,108,121,103,111,110,32,0,0,0,0,0,0,0,0,108,105,103,104,116,103,111,108,100,101,110,114,111,100,50,0,108,105,103,104,116,103,111,108,100,101,110,114,111,100,49,0,60,33,45,45,32,71,101,110,101,114,97,116,101,100,32,98,121,32,0,0,0,0,0,0,108,105,103,104,116,103,111,108,100,101,110,114,111,100,0,0,108,105,103,104,116,99,121,97,110,52,0,0,0,0,0,0,47,100,97,114,107,50,51,47,49,0,0,0,0,0,0,0,108,105,103,104,116,99,121,97,110,51,0,0,0,0,0,0,108,105,103,104,116,99,121,97,110,50,0,0,0,0,0,0,112,105,118,0,0,0,0,0,108,105,103,104,116,99,121,97,110,49,0,0,0,0,0,0,108,105,103,104,116,99,121,97,110,0,0,0,0,0,0,0,108,105,103,104,116,99,111,114,97,108,0,0,0,0,0,0,66,111,111,107,109,97,110,45,68,101,109,105,73,116,97,108,105,99,0,0,0,0,0,0,108,105,103,104,116,98,108,117,101,52,0,0,0,0,0,0,108,105,103,104,116,98,108,117,101,51,0,0,0,0,0,0,108,105,103,104,116,98,108,117,101,50,0,0,0,0,0,0,101,114,114,111,114,32,105,110,32,112,114,111,99,101,115,115,105,110,103,32,101,120,116,101,114,110,97,108,32,101,110,116,105,116,121,32,114,101,102,101,114,101,110,99,101,0,0,0,32,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,71,114,97,112,104,105,99,115,47,83,86,71,47,49,46,49,47,68,84,68,47,115,118,103,49,49,46,100,116,100,34,62,10,0,0,0,108,105,103,104,116,98,108,117,101,49,0,0,0,0,0,0,108,105,103,104,116,98,108,117,101,0,0,0,0,0,0,0,47,98,117,112,117,57,47,57,0,0,0,0,0,0,0,0,108,101,109,111,110,99,104,105,102,102,111,110,52,0,0,0,70,32,37,102,32,0,0,0,108,101,109,111,110,99,104,105,102,102,111,110,51,0,0,0,112,105,0,0,0,0,0,0,108,101,109,111,110,99,104,105,102,102,111,110,50,0,0,0,108,101,109,111,110,99,104,105,102,102,111,110,49,0,0,0,108,101,109,111,110,99,104,105,102,102,111,110,0,0,0,0,37,46,53,103,44,37,46,53,103,44,37,46,53,103,0,0,108,97,119,110,103,114,101,101,110,0,0,0,0,0,0,0,107,101,121,0,0,0,0,0,108,97,118,101,110,100,101,114,98,108,117,115,104,52,0,0,108,97,118,101,110,100,101,114,98,108,117,115,104,51,0,0,99,121,97,110,0,0,0,0,60,33,68,79,67,84,89,80,69,32,115,118,103,32,80,85,66,76,73,67,32,34,45,47,47,87,51,67,47,47,68,84,68,32,83,86,71,32,49,46,49,47,47,69,78,34,10,0,108,97,118,101,110,100,101,114,98,108,117,115,104,50,0,0,78,68,95,105,110,40,114,105,103,104,116,41,46,115,105,122,101,32,43,32,78,68,95,111,117,116,40,114,105,103,104,116,41,46,115,105,122,101,32,61,61,32,48,0,0,0,0,0,112,104,105,0,0,0,0,0,108,97,118,101,110,100,101,114,98,108,117,115,104,49,0,0,47,98,117,112,117,57,47,56,0,0,0,0,0,0,0,0,108,97,118,101,110,100,101,114,98,108,117,115,104,0,0,0,108,97,118,101,110,100,101,114,0,0,0,0,0,0,0,0,32,32,34,37,115,34,10,0,107,104,97,107,105,52,0,0,107,104,97,107,105,51,0,0,97,108,105,99,101,98,108,117,101,0,0,0,0,0,0,0,107,104,97,107,105,50,0,0,107,104,97,107,105,49,0,0,107,104,97,107,105,0,0,0,112,110,103,0,0,0,0,0,105,118,111,114,121,52,0,0,73,110,118,97,108,105,100,32,50,45,98,121,116,101,32,85,84,70,56,32,102,111,117,110,100,32,105,110,32,105,110,112,117,116,46,32,80,101,114,104,97,112,115,32,34,45,71,99,104,97,114,115,101,116,61,108,97,116,105,110,49,34,32,105,115,32,110,101,101,100,101,100,63,10,0,0,0,0,0,0,47,72,101,108,118,101,116,105,99,97,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,0,0,0,0,34,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,63,62,10,0,0,0,0,105,118,111,114,121,51,0,0,78,111,32,108,105,98,122,32,115,117,112,112,111,114,116,46,10,0,0,0,0,0,0,0,105,118,111,114,121,50,0,0,47,98,117,112,117,57,47,55,0,0,0,0,0,0,0,0,105,118,111,114,121,49,0,0,105,118,111,114,121,0,0,0,112,101,114,112,0,0,0,0,105,110,118,105,115,0,0,0,105,110,100,105,103,111,0,0,105,110,100,105,97,110,114,101,100,52,0,0,0,0,0,0,105,110,100,105,97,110,114,101,100,51,0,0,0,0,0,0,105,110,100,105,97,110,114,101,100,50,0,0,0,0,0,0,105,110,100,105,97,110,114,101,100,49,0,0,0,0,0,0,60,63,120,109,108,45,115,116,121,108,101,115,104,101,101,116,32,104,114,101,102,61,34,0,105,110,100,105,97,110,114,101,100,0,0,0,0,0,0,0,104,111,116,112,105,110,107,52,0,0,0,0,0,0,0,0,47,98,117,112,117,57,47,54,0,0,0,0,0,0,0,0,104,111,116,112,105,110,107,51,0,0,0,0,0,0,0,0,104,111,116,112,105,110,107,50,0,0,0,0,0,0,0,0,112,101,114,109,105,108,0,0,35,51,48,51,48,51,48,0,104,111,116,112,105,110,107,49,0,0,0,0,0,0,0,0,104,111,116,112,105,110,107,0,104,111,110,101,121,100,101,119,52,0,0,0,0,0,0,0,32,116,97,114,103,101,116,61,34,0,0,0,0,0,0,0,104,111,110,101,121,100,101,119,51,0,0,0,0,0,0,0,104,111,110,101,121,100,101,119,50,0,0,0,0,0,0,0,104,111,110,101,121,100,101,119,49,0,0,0,0,0,0,0,115,116,121,108,101,115,104,101,101,116,0,0,0,0,0,0,104,111,110,101,121,100,101,119,0,0,0,0,0,0,0,0,103,114,101,121,57,57,0,0,47,98,117,112,117,57,47,53,0,0,0,0,0,0,0,0,103,114,101,121,57,56,0,0,103,114,101,121,57,55,0,0,112,97,114,116,0,0,0,0,103,114,101,121,57,54,0,0,103,114,101,121,57,53,0,0,103,114,101,121,57,52,0,0,103,114,101,121,57,51,0,0,103,114,101,121,57,50,0,0,103,114,101,121,57,49,0,0,60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101,110,99,111,100,105,110,103,61,34,85,84,70,45,56,34,32,115,116,97,110,100,97,108,111,110,101,61,34,110,111,34,63,62,10,0,103,114,101,121,57,48,0,0,47,97,99,99,101,110,116,55,47,50,0,0,0,0,0,0,103,114,101,121,57,0,0,0,47,98,117,112,117,57,47,52,0,0,0,0,0,0,0,0,103,114,101,121,56,57,0,0,103,114,101,121,56,56,0,0,112,97,114,97,0,0,0,0,103,114,101,121,56,55,0,0,103,114,101,121,56,54,0,0,103,114,101,121,56,53,0,0,103,114,101,121,56,52,0,0,103,114,101,121,56,51,0,0,103,114,101,121,56,50,0,0,32,120,109,108,110,115,58,120,108,105,110,107,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,108,105,110,107,34,0,0,0,0,0,116,114,97,112,101,122,105,117,109,0,0,0,0,0,0,0,103,114,101,121,56,49,0,0,103,114,101,121,56,48,0,0,47,98,117,112,117,57,47,51,0,0,0,0,0,0,0,0,103,114,101,121,56,0,0,0,103,114,101,121,55,57,0,0,111,117,109,108,0,0,0,0,103,114,101,121,55,56,0,0,103,114,101,121,55,55,0,0,103,114,101,121,55,54,0,0,103,114,101,121,55,53,0,0,103,114,101,121,55,52,0,0,50,0,0,0,0,0,0,0,103,114,101,121,55,51,0,0,103,105,102,58,109,97,112,0,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,48,47,115,118,103,34,0,0,0,0,0,103,114,101,121,55,50,0,0,50,48,49,49,48,53,48,55,46,48,51,50,55,0,0,0,103,114,101,121,55,49,0,0,47,98,117,112,117,57,47,50,0,0,0,0,0,0,0,0,103,114,101,121,55,48,0,0,103,114,101,121,55,0,0,0,111,116,105,109,101,115,0,0,103,114,101,121,54,57,0,0,48,0,0,0,0,0,0,0,103,114,101,121,54,56,0,0,103,114,101,121,54,55,0,0,103,114,101,121,54,54,0,0,103,114,101,121,54,53,0,0,115,99,97,108,101,0,0,0,116,111,111,32,109,97,110,121,32,115,97,109,101,123,104,101,97,100,44,116,97,105,108,125,32,103,114,111,117,112,115,32,102,111,114,32,110,111,100,101,32,37,115,10,0,0,0,0,103,114,101,121,54,52,0,0,32,118,105,101,119,66,111,120,61,34,37,46,50,102,32,37,46,50,102,32,37,46,50,102,32,37,46,50,102,34,0,0,103,114,101,121,54,51,0,0,37,115,32,45,62,32,37,115,58,32,115,112,108,105,110,101,32,115,105,122,101,32,62,32,49,32,110,111,116,32,115,117,112,112,111,114,116,101,100,10,0,0,0,0,0,0,0,0,103,114,97,112,104,0,0,0,103,114,101,121,54,50,0,0,47,98,117,112,117,57,47,49,0,0,0,0,0,0,0,0,103,114,101,121,54,49,0,0,103,114,101,121,54,48,0,0,111,116,105,108,100,101,0,0,114,101,100,0,0,0,0,0,103,114,101,121,54,0,0,0,103,114,101,121,53,57,0,0,103,114,101,121,53,56,0,0,103,114,101,121,53,55,0,0,32,45,115,109,111,111,116,104,32,98,101,122,105,101,114,32,0,0,0,0,0,0,0,0,103,114,101,121,53,54,0,0,103,114,101,121,53,53,0,0,60,115,118,103,32,119,105,100,116,104,61,34,37,100,112,116,34,32,104,101,105,103,104,116,61,34,37,100,112,116,34,10,0,0,0,0,0,0,0,0,103,114,101,121,53,52,0,0,103,114,101,121,53,51,0,0,47,98,117,112,117,56,47,56,0,0,0,0,0,0,0,0,103,114,101,121,53,50,0,0,103,114,101,121,53,49,0,0,111,115,108,97,115,104,0,0,103,114,101,121,53,48,0,0,103,114,101,121,53,0,0,0,103,114,101,121,52,57,0,0,115,101,114,105,102,0,0,0,103,114,101,121,52,56,0,0,103,114,101,121,52,55,0,0,103,114,101,121,52,54,0,0,117,110,99,108,111,115,101,100,32,67,68,65,84,65,32,115,101,99,116,105,111,110,0,0,114,97,110,107,46,99,0,0,32,80,97,103,101,115,58,32,37,100,32,45,45,62,10,0,103,114,101,121,52,53,0,0,103,114,101,121,52,52,0,0,47,98,117,112,117,56,47,55,0,0,0,0,0,0,0,0,103,114,101,121,52,51,0,0,101,32,0,0,0,0,0,0,103,114,101,121,52,50,0,0,111,114,100,109,0,0,0,0,103,114,101,121,52,49,0,0,103,114,101,121,52,48,0,0,103,114,101,121,52,0,0,0,98,98,0,0,0,0,0,0,103,114,101,121,51,57,0,0,104,114,101,102,0,0,0,0,103,114,101,121,51,56,0,0,103,114,101,121,51,55,0,0,99,114,105,109,115,111,110,0,32,84,105,116,108,101,58,32,0,0,0,0,0,0,0,0,117,115,45,62,110,97,109,101,0,0,0,0,0,0,0,0,103,114,101,121,51,54,0,0,103,114,101,121,51,53,0,0,47,98,117,112,117,56,47,54,0,0,0,0,0,0,0,0,103,114,101,121,51,52,0,0,103,114,101,121,51,51,0,0,111,114,100,102,0,0,0,0,103,114,101,121,51,50,0,0,103,114,101,121,51,49,0,0,65,82,61,37,48,46,52,108,102,9,32,65,114,101,97,61,32,37,48,46,52,108,102,9,0,0,0,0,0,0,0,0,103,114,101,121,51,48,0,0,103,114,101,121,51,0,0,0,103,114,101,121,50,57,0,0,117,32,61,61,32,85,70,95,102,105,110,100,40,117,41,0,68,111,116,68,105,99,116,32,98,101,103,105,110,0,0,0,60,33,45,45,0,0,0,0,137,80,78,71,13,10,26,10,0,0,0,0,0,0,0,0,103,114,101,121,50,56,0,0,37,100,0,0,0,0,0,0,47,84,105,109,101,115,45,66,111,108,100,73,116,97,108,105,99,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,0,0,0,0,0,115,118,103,0,0,0,0,0,103,114,101,121,50,55,0,0,103,114,101,121,50,54,0,0,47,98,117,112,117,56,47,53,0,0,0,0,0,0,0,0,103,114,101,121,50,53,0,0,103,114,101,121,50,52,0,0,111,114,0,0,0,0,0,0,103,114,101,121,50,51,0,0,103,114,101,121,50,50,0,0,103,114,101,121,50,49,0,0,103,114,101,121,50,48,0,0,103,114,101,121,50,0,0,0,60,47,115,118,103,62,10,0,103,114,101,121,49,57,0,0,37,37,37,37,67,114,101,97,116,111,114,58,32,37,115,32,118,101,114,115,105,111,110,32,37,115,32,40,37,115,41,10,0,0,0,0,0,0,0,0,103,114,101,121,49,56,0,0,103,114,101,121,49,55,0,0,47,98,117,112,117,56,47,52,0,0,0,0,0,0,0,0,103,114,101,121,49,54,0,0,115,111,108,105,100,0,0,0,103,114,101,121,49,53,0,0,111,112,108,117,115,0,0,0,35,102,99,102,99,102,99,0,103,114,101,121,49,52,0,0,103,114,101,121,49,51,0,0,103,114,101,121,49,50,0,0,103,114,101,121,49,49,0,0,32,104,114,101,102,61,34,0,103,114,101,121,49,48,48,0,34,32,99,108,97,115,115,61,34,108,97,121,101,114,34,62,10,0,0,0,0,0,0,0,103,114,101,121,49,48,0,0,32,69,80,83,70,45,51,46,48,10,0,0,0,0,0,0,103,114,101,121,49,0,0,0,103,114,101,121,48,0,0,0,47,98,117,112,117,56,47,51,0,0,0,0,0,0,0,0,103,114,101,121,0,0,0,0,103,114,101,101,110,121,101,108,108,111,119,0,0,0,0,0,111,109,105,99,114,111,110,0,103,114,101,101,110,52,0,0,103,114,101,101,110,51,0,0,103,114,101,101,110,50,0,0,103,114,101,101,110,49,0,0,103,114,101,101,110,0,0,0,32,116,114,97,110,115,102,111,114,109,61,34,115,99,97,108,101,40,37,103,32,37,103,41,32,114,111,116,97,116,101,40,37,100,41,32,116,114,97,110,115,108,97,116,101,40,37,103,32,37,103,41,34,62,10,0,103,114,97,121,57,57,0,0,37,33,80,83,45,65,100,111,98,101,45,51,46,48,0,0,103,114,97,121,57,56,0,0,47,97,99,99,101,110,116,55,47,49,0,0,0,0,0,0,103,114,97,121,57,55,0,0,47,98,117,112,117,56,47,50,0,0,0,0,0,0,0,0,103,114,97,121,57,54,0,0,103,114,97,121,57,53,0,0,111,109,101,103,97,0,0,0,103,114,97,121,57,52,0,0,103,114,97,121,57,51,0,0,103,114,97,121,57,50,0,0,103,114,97,121,57,49,0,0,103,114,97,121,57,48,0,0,34,32,99,108,97,115,115,61,34,103,114,97,112,104,34,0,103,114,97,121,57,0,0,0,37,37,69,79,70,10,0,0,103,114,97,121,56,57,0,0,100,105,97,109,111,110,100,0,103,114,97,121,56,56,0,0,47,98,117,112,117,56,47,49,0,0,0,0,0,0,0,0,103,114,97,121,56,55,0,0,103,114,97,121,56,54,0,0,111,108,105,110,101,0,0,0,103,114,97,121,56,53,0,0,103,114,97,121,56,52,0,0,103,114,97,121,56,51,0,0,103,114,97,121,56,50,0,0,103,114,97,121,56,49,0,0,34,32,99,108,97,115,115,61,34,99,108,117,115,116,101,114,34,62,0,0,0,0,0,0,103,114,97,121,56,48,0,0,49,0,0,0,0,0,0,0,112,110,103,58,109,97,112,0,101,110,100,10,114,101,115,116,111,114,101,10,0,0,0,0,103,114,97,121,56,0,0,0,103,114,97,121,55,57,0,0,47,98,117,112,117,55,47,55,0,0,0,0,0,0,0,0,103,114,97,121,55,56,0,0,103,114,97,121,55,55,0,0,111,103,114,97,118,101,0,0,103,114,97,121,55,54,0,0,103,114,97,121,55,53,0,0,37,100,32,37,100,32,35,37,48,50,120,37,48,50,120,37,48,50,120,10,0,0,0,0,103,114,97,121,55,52,0,0,103,114,97,121,55,51,0,0,103,114,97,121,55,50,0,0,60,73,77,71,62,0,0,0,34,32,99,108,97,115,115,61,34,110,111,100,101,34,62,0,103,114,97,121,55,49,0,0,37,37,37,37,80,97,103,101,115,58,32,37,100,10,0,0,103,114,97,121,55,48,0,0,103,114,97,121,55,0,0,0,47,98,117,112,117,55,47,54,0,0,0,0,0,0,0,0,103,114,97,121,54,57,0,0,103,114,97,121,54,56,0,0,111,101,108,105,103,0,0,0,112,117,114,112,108,101,0,0,103,114,97,121,54,55,0,0,103,114,97,121,54,54,0,0,103,114,97,121,54,53,0,0,103,114,97,121,54,52,0,0,32,45,119,105,100,116,104,32,0,0,0,0,0,0,0,0,103,114,97,121,54,51,0,0,60,47,116,105,116,108,101,62,10,0,0,0,0,0,0,0,103,114,97,121,54,50,0,0,37,37,84,114,97,105,108,101,114,10,0,0,0,0,0,0,103,114,97,121,54,49,0,0,103,114,97,121,54,48,0,0,47,98,117,112,117,55,47,53,0,0,0,0,0,0,0,0,103,114,97,121,54,0,0,0,103,114,97,121,53,57,0,0,35,56,48,56,48,56,48,0,111,99,105,114,99,0,0,0,103,114,97,121,53,56,0,0,103,114,97,121,53,55,0,0,103,114,97,121,53,54,0,0,85,82,87,32,66,111,111,107,109,97,110,32,76,0,0,0,103,114,97,121,53,53,0,0,103,114,97,121,53,52,0,0,92,69,0,0,0,0,0,0,103,114,97,121,53,51,0,0,101,110,99,111,100,105,110,103,32,115,112,101,99,105,102,105,101,100,32,105,110,32,88,77,76,32,100,101,99,108,97,114,97,116,105,111,110,32,105,115,32,105,110,99,111,114,114,101,99,116,0,0,0,0,0,0,91,32,123,67,97,116,97,108,111,103,125,32,60,60,32,47,85,82,73,32,60,60,32,47,66,97,115,101,32,40,37,115,41,32,62,62,32,62,62,10,47,80,85,84,32,112,100,102,109,97,114,107,10,0,0,0,103,114,97,121,53,50,0,0,92,76,0,0,0,0,0,0,103,114,97,121,53,49,0,0,47,98,117,112,117,55,47,52,0,0,0,0,0,0,0,0,103,114,97,121,53,48,0,0,69,32,0,0,0,0,0,0,103,114,97,121,53,0,0,0,111,97,99,117,116,101,0,0,100,101,103,101,110,101,114,97,116,101,32,99,111,110,99,101,110,116,114,97,116,101,100,32,114,97,110,107,32,37,115,44,37,100,10,0,0,0,0,0,103,114,97,121,52,57,0,0,103,114,97,121,52,56,0,0,103,114,97,121,52,55,0,0,37,46,50,102,0,0,0,0,103,114,97,121,52,54,0,0,85,82,76,0,0,0,0,0,103,114,97,121,52,53,0,0,60,116,105,116,108,101,62,0,103,114,97,121,52,52,0,0,99,111,114,110,115,105,108,107,0,0,0,0,0,0,0,0,115,101,116,117,112,76,97,116,105,110,49,10,0,0,0,0,103,114,97,121,52,51,0,0,103,114,97,121,52,50,0,0,47,98,117,112,117,55,47,51,0,0,0,0,0,0,0,0,103,114,97,121,52,49,0,0,103,114,97,121,52,48,0,0,110,117,0,0,0,0,0,0,103,114,97,121,52,0,0,0,103,114,97,121,51,57,0,0,103,114,97,121,51,56,0,0,103,114,97,121,51,55,0,0,103,114,97,121,51,54,0,0,34,32,99,108,97,115,115,61,34,101,100,103,101,34,62,0,40,108,105,98,41,0,0,0,103,114,97,121,51,53,0,0,95,95,99,108,117,115,116,101,114,110,111,100,101,115,0,0,37,37,69,110,100,67,111,109,109,101,110,116,115,10,115,97,118,101,10,0,0,0,0,0,47,84,105,109,101,115,45,66,111,108,100,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,0,0,0,103,114,97,121,51,52,0,0,103,114,97,121,51,51,0,0,47,98,117,112,117,55,47,50,0,0,0,0,0,0,0,0,103,114,97,121,51,50,0,0,103,114,97,121,51,49,0,0,110,116,105,108,100,101,0,0,103,114,97,121,51,48,0,0,103,114,97,121,51,0,0,0,103,114,97,121,50,57,0,0,103,114,97,121,50,56,0,0,103,114,97,121,50,55,0,0,60,103,32,105,100,61,34,0,103,114,97,121,50,54,0,0,37,37,37,37,66,111,117,110,100,105,110,103,66,111,120,58,32,37,100,32,37,100,32,37,100,32,37,100,10,0,0,0,103,114,97,121,50,53,0,0,103,114,97,121,50,52,0,0,47,98,117,112,117,55,47,49,0,0,0,0,0,0,0,0,103,114,97,121,50,51,0,0,103,114,97,121,50,50,0,0,110,115,117,98,0,0,0,0,95,100,114,97,119,95,0,0,110,111,114,109,97,108,0,0,103,114,97,121,50,49,0,0,103,114,97,121,50,48,0,0,103,114,97,121,50,0,0,0,103,114,97,121,49,57,0,0,103,114,97,121,49,56,0,0,34,0,0,0,0,0,0,0,60,47,103,62,10,0,0,0,103,114,97,121,49,55,0,0,37,37,66,111,117,110,100,105,110,103,66,111,120,58,32,40,97,116,101,110,100,41,10,0,103,114,97,121,49,54,0,0,103,114,97,121,49,53,0,0,47,98,117,112,117,54,47,54,0,0,0,0,0,0,0,0,103,114,97,121,49,52,0,0,103,114,97,121,49,51,0,0,110,111,116,105,110,0,0,0,103,114,97,121,49,50,0,0,103,114,97,121,49,49,0,0,103,114,97,121,49,48,48,0,103,114,97,121,49,48,0,0,103,114,97,121,49,0,0,0,62,10,0,0,0,0,0,0,103,114,97,121,48,0,0,0,37,37,80,97,103,101,115,58,32,49,10,0,0,0,0,0,103,114,97,121,0,0,0,0,47,97,99,99,101,110,116,54,47,54,0,0,0,0,0,0,103,111,108,100,101,110,114,111,100,52,0,0,0,0,0,0,47,98,117,112,117,54,47,53,0,0,0,0,0,0,0,0,103,111,108,100,101,110,114,111,100,51,0,0,0,0,0,0,103,111,108,100,101,110,114,111,100,50,0,0,0,0,0,0,110,111,116,0,0,0,0,0,103,111,108,100,101,110,114,111,100,49,0,0,0,0,0,0,103,111,108,100,101,110,114,111,100,0,0,0,0,0,0,0,103,111,108,100,52,0,0,0,103,111,108,100,51,0,0,0,103,111,108,100,50,0,0,0,32,116,97,114,103,101,116,61,34,0,0,0,0,0,0,0,103,111,108,100,49,0,0,0,37,37,80,97,103,101,115,58,32,40,97,116,101,110,100,41,10,0,0,0,0,0,0,0,103,111,108,100,0,0,0,0,112,108,97,105,110,116,101,120,116,0,0,0,0,0,0,0,103,104,111,115,116,119,104,105,116,101,0,0,0,0,0,0,47,98,117,112,117,54,47,52,0,0,0,0,0,0,0,0,103,97,105,110,115,98,111,114,111,0,0,0,0,0,0,0,102,111,114,101,115,116,103,114,101,101,110,0,0,0,0,0,110,105,0,0,0,0,0,0,102,108,111,114,97,108,119,104,105,116,101,0,0,0,0,0,102,105,114,101,98,114,105,99,107,52,0,0,0,0,0,0,102,105,114,101,98,114,105,99,107,51,0,0,0,0,0,0,102,105,114,101,98,114,105,99,107,50,0,0,0,0,0,0,102,105,114,101,98,114,105,99,107,49,0,0,0,0,0,0,32,120,108,105,110,107,58,116,105,116,108,101,61,34,0,0,102,105,114,101,98,114,105,99,107,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,40,108,105,98,41,58,112,115,0,0,0,0,0,0,0,0,37,37,37,37,84,105,116,108,101,58,32,37,115,10,0,0,100,111,100,103,101,114,98,108,117,101,52,0,0,0,0,0,100,111,100,103,101,114,98,108,117,101,51,0,0,0,0,0,47,98,117,112,117,54,47,51,0,0,0,0,0,0,0,0,100,111,100,103,101,114,98,108,117,101,50,0,0,0,0,0,100,111,100,103,101,114,98,108,117,101,49,0,0,0,0,0,110,101,0,0,0,0,0,0,100,111,100,103,101,114,98,108,117,101,0,0,0,0,0,0,100,105,109,103,114,101,121,0,100,105,109,103,114,97,121,0])
+.concat([37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,51,102,32,37,100,32,37,46,52,102,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,10,0,0,0,0,0,0,0,0,100,101,101,112,115,107,121,98,108,117,101,52,0,0,0,0,100,101,101,112,115,107,121,98,108,117,101,51,0,0,0,0,85,110,107,110,111,119,110,32,72,84,77,76,32,101,108,101,109,101,110,116,32,60,37,115,62,32,111,110,32,108,105,110,101,32,37,100,32,10,0,0,32,120,108,105,110,107,58,104,114,101,102,61,34,0,0,0,100,101,101,112,115,107,121,98,108,117,101,50,0,0,0,0,37,100,32,37,100,32,115,101,116,108,97,121,101,114,10,0,100,101,101,112,115,107,121,98,108,117,101,49,0,0,0,0,100,101,101,112,115,107,121,98,108,117,101,0,0,0,0,0,45,45,0,0,0,0,0,0,47,98,117,112,117,54,47,50,0,0,0,0,0,0,0,0,100,101,101,112,112,105,110,107,52,0,0,0,0,0,0,0,100,101,101,112,112,105,110,107,51,0,0,0,0,0,0,0,110,100,97,115,104,0,0,0,111,108,105,118,101,0,0,0,100,101,101,112,112,105,110,107,50,0,0,0,0,0,0,0,100,101,101,112,112,105,110,107,49,0,0,0,0,0,0,0,100,101,101,112,112,105,110,107,0,0,0,0,0,0,0,0,100,97,114,107,118,105,111,108,101,116,0,0,0,0,0,0,36,99,0,0,0,0,0,0,100,97,114,107,116,117,114,113,117,111,105,115,101,0,0,0,60,97,0,0,0,0,0,0,100,97,114,107,115,108,97,116,101,103,114,101,121,0,0,0,91,32,47,67,114,111,112,66,111,120,32,91,37,100,32,37,100,32,37,100,32,37,100,93,32,47,80,65,71,69,83,32,112,100,102,109,97,114,107,10,0,0,0,0,0,0,0,0,100,97,114,107,115,108,97,116,101,103,114,97,121,52,0,0,100,97,114,107,115,108,97,116,101,103,114,97,121,51,0,0,47,98,117,112,117,54,47,49,0,0,0,0,0,0,0,0,100,97,114,107,115,108,97,116,101,103,114,97,121,50,0,0,100,97,114,107,115,108,97,116,101,103,114,97,121,49,0,0,110,98,115,112,0,0,0,0,47,98,117,112,117,53,47,53,0,0,0,0,0,0,0,0,100,97,114,107,115,108,97,116,101,103,114,97,121,0,0,0,99,111,108,111,114,115,99,104,101,109,101,0,0,0,0,0,100,97,114,107,115,108,97,116,101,98,108,117,101,0,0,0,100,97,114,107,115,101,97,103,114,101,101,110,52,0,0,0,66,111,111,107,109,97,110,45,68,101,109,105,0,0,0,0,100,97,114,107,115,101,97,103,114,101,101,110,51,0,0,0,100,97,114,107,115,101,97,103,114,101,101,110,50,0,0,0,60,47,97,62,10,0,0,0,100,97,114,107,115,101,97,103,114,101,101,110,49,0,0,0,117,110,107,110,111,119,110,32,101,110,99,111,100,105,110,103,0,0,0,0,0,0,0,0,99,97,110,118,97,115,32,115,105,122,101,32,40,37,100,44,37,100,41,32,101,120,99,101,101,100,115,32,80,68,70,32,108,105,109,105,116,32,40,37,100,41,10,9,40,115,117,103,103,101,115,116,32,115,101,116,116,105,110,103,32,97,32,98,111,117,110,100,105,110,103,32,98,111,120,32,115,105,122,101,44,32,115,101,101,32,100,111,116,40,49,41,41,10,0,0,100,97,114,107,115,101,97,103,114,101,101,110,0,0,0,0,92,84,0,0,0,0,0,0,100,97,114,107,115,97,108,109,111,110,0,0,0,0,0,0,100,97,114,107,111,114,99,104,105,100,52,0,0,0,0,0,67,32,0,0,0,0,0,0,100,97,114,107,111,114,99,104,105,100,51,0,0,0,0,0,110,97,98,108,97,0,0,0,47,98,117,112,117,53,47,52,0,0,0,0,0,0,0,0,100,97,114,107,111,114,99,104,105,100,50,0,0,0,0,0,100,97,114,107,111,114,99,104,105,100,49,0,0,0,0,0,100,97,114,107,111,114,99,104,105,100,0,0,0,0,0,0,37,46,53,103,44,37,46,53,103,0,0,0,0,0,0,0,100,97,114,107,111,114,97,110,103,101,52,0,0,0,0,0,119,0,0,0,0,0,0,0,100,97,114,107,111,114,97,110,103,101,51,0,0,0,0,0,60,47,116,101,120,116,62,10,0,0,0,0,0,0,0,0,100,97,114,107,111,114,97,110,103,101,50,0,0,0,0,0,99,111,114,110,102,108,111,119,101,114,98,108,117,101,0,0,37,103,32,37,103,32,115,101,116,95,115,99,97,108,101,32,37,100,32,114,111,116,97,116,101,32,37,103,32,37,103,32,116,114,97,110,115,108,97,116,101,10,0,0,0,0,0,0,100,97,114,107,111,114,97,110,103,101,49,0,0,0,0,0,100,97,114,107,111,114,97,110,103,101,0,0,0,0,0,0,100,97,114,107,111,108,105,118,101,103,114,101,101,110,52,0,100,97,114,107,111,108,105,118,101,103,114,101,101,110,51,0,109,117,0,0,0,0,0,0,47,98,117,112,117,53,47,51,0,0,0,0,0,0,0,0,100,97,114,107,111,108,105,118,101,103,114,101,101,110,50,0,100,97,114,107,111,108,105,118,101,103,114,101,101,110,49,0,100,97,114,107,111,108,105,118,101,103,114,101,101,110,0,0,100,97,114,107,107,104,97,107,105,0,0,0,0,0,0,0,100,97,114,107,103,114,101,101,110,0,0,0,0,0,0,0,62,0,0,0,0,0,0,0,115,118,103,0,0,0,0,0,100,97,114,107,103,111,108,100,101,110,114,111,100,52,0,0,103,115,97,118,101,10,37,100,32,37,100,32,37,100,32,37,100,32,98,111,120,112,114,105,109,32,99,108,105,112,32,110,101,119,112,97,116,104,10,0,47,84,105,109,101,115,45,73,116,97,108,105,99,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,0,100,97,114,107,103,111,108,100,101,110,114,111,100,51,0,0,100,97,114,107,103,111,108,100,101,110,114,111,100,50,0,0,100,97,114,107,103,111,108,100,101,110,114,111,100,49,0,0,100,97,114,107,103,111,108,100,101,110,114,111,100,0,0,0,109,105,110,117,115,0,0,0,47,98,117,112,117,53,47,50,0,0,0,0,0,0,0,0,99,121,97,110,52,0,0,0,99,121,97,110,51,0,0,0,99,121,97,110,50,0,0,0,99,121,97,110,49,0,0,0,99,121,97,110,0,0,0,0,32,102,105,108,108,61,34,35,37,48,50,120,37,48,50,120,37,48,50,120,34,0,0,0,99,114,105,109,115,111,110,0,37,100,32,37,100,32,37,100,32,98,101,103,105,110,112,97,103,101,10,0,0,0,0,0,99,111,114,110,115,105,108,107,52,0,0,0,0,0,0,0,99,111,114,110,115,105,108,107,51,0,0,0,0,0,0,0,99,111,114,110,115,105,108,107,50,0,0,0,0,0,0,0,99,111,114,110,115,105,108,107,49,0,0,0,0,0,0,0,109,105,100,100,111,116,0,0,98,111,116,104,0,0,0,0,47,98,117,112,117,53,47,49,0,0,0,0,0,0,0,0,99,111,114,110,115,105,108,107,0,0,0,0,0,0,0,0,99,111,114,110,102,108,111,119,101,114,98,108,117,101,0,0,99,111,114,97,108,52,0,0,99,111,114,97,108,51,0,0,99,111,114,97,108,50,0,0,32,102,105,108,108,61,34,37,115,34,0,0,0,0,0,0,99,111,114,97,108,49,0,0,32,105,100,61,34,0,0,0,60,60,32,47,80,97,103,101,83,105,122,101,32,91,37,100,32,37,100,93,32,62,62,32,115,101,116,112,97,103,101,100,101,118,105,99,101,10,0,0,99,111,114,97,108,0,0,0,99,104,111,99,111,108,97,116,101,52,0,0,0,0,0,0,99,104,111,99,111,108,97,116,101,51,0,0,0,0,0,0,99,104,111,99,111,108,97,116,101,50,0,0,0,0,0,0,109,105,99,114,111,0,0,0,47,98,117,112,117,52,47,52,0,0,0,0,0,0,0,0,99,104,111,99,111,108,97,116,101,49,0,0,0,0,0,0,99,104,111,99,111,108,97,116,101,0,0,0,0,0,0,0,99,104,97,114,116,114,101,117,115,101,52,0,0,0,0,0,99,104,97,114,116,114,101,117,115,101,51,0,0,0,0,0,99,104,97,114,116,114,101,117,115,101,50,0,0,0,0,0,32,102,111,110,116,45,115,105,122,101,61,34,37,46,50,102,34,0,0,0,0,0,0,0,99,104,97,114,116,114,101,117,115,101,49,0,0,0,0,0,80,111,114,116,114,97,105,116,0,0,0,0,0,0,0,0,99,104,97,114,116,114,101,117,115,101,0,0,0,0,0,0,47,97,99,99,101,110,116,54,47,53,0,0,0,0,0,0,99,97,100,101,116,98,108,117,101,52,0,0,0,0,0,0,99,97,100,101,116,98,108,117,101,51,0,0,0,0,0,0,99,97,100,101,116,98,108,117,101,50,0,0,0,0,0,0,109,100,97,115,104,0,0,0,47,98,117,112,117,52,47,51,0,0,0,0,0,0,0,0,99,97,100,101,116,98,108,117,101,49,0,0,0,0,0,0,99,97,100,101,116,98,108,117,101,0,0,0,0,0,0,0,98,117,114,108,121,119,111,111,100,52,0,0,0,0,0,0,98,117,114,108,121,119,111,111,100,51,0,0,0,0,0,0,98,117,114,108,121,119,111,111,100,50,0,0,0,0,0,0,32,102,111,110,116,45,102,97,109,105,108,121,61,34,37,115,34,0,0,0,0,0,0,0,98,117,114,108,121,119,111,111,100,49,0,0,0,0,0,0,76,97,110,100,115,99,97,112,101,0,0,0,0,0,0,0,98,117,114,108,121,119,111,111,100,0,0,0,0,0,0,0,110,111,110,101,0,0,0,0,98,114,111,119,110,52,0,0,98,114,111,119,110,51,0,0,98,114,111,119,110,50,0,0,109,97,99,114,0,0,0,0,47,98,117,112,117,52,47,50,0,0,0,0,0,0,0,0,98,114,111,119,110,49,0,0,98,114,111,119,110,0,0,0,98,108,117,101,118,105,111,108,101,116,0,0,0,0,0,0,98,108,117,101,52,0,0,0,98,108,117,101,51,0,0,0,32,102,111,110,116,45,115,116,121,108,101,61,34,37,115,34,0,0,0,0,0,0,0,0,98,108,117,101,50,0,0,0,45,45,0,0,0,0,0,0,112,115,58,108,97,115,105,0,37,37,37,37,80,97,103,101,79,114,105,101,110,116,97,116,105,111,110,58,32,37,115,10,0,0,0,0,0,0,0,0,98,108,117,101,49,0,0,0,98,108,117,101,0,0,0,0,98,108,97,110,99,104,101,100,97,108,109,111,110,100,0,0,98,108,97,99,107,0,0,0,108,116,0,0,0,0,0,0,47,98,117,112,117,52,47,49,0,0,0,0,0,0,0,0,98,105,115,113,117,101,52,0,98,105,115,113,117,101,51,0,98,105,115,113,117,101,50,0,98,105,115,113,117,101,49,0,32,37,100,0,0,0,0,0,98,105,115,113,117,101,0,0,73,77,71,0,0,0,0,0,32,102,111,110,116,45,115,116,114,101,116,99,104,61,34,37,115,34,0,0,0,0,0,0,98,101,105,103,101,0,0,0,37,37,37,37,80,97,103,101,66,111,117,110,100,105,110,103,66,111,120,58,32,37,100,32,37,100,32,37,100,32,37,100,10,0,0,0,0,0,0,0,97,122,117,114,101,52,0,0,97,122,117,114,101,51,0,0,97,122,117,114,101,50,0,0,97,122,117,114,101,49,0,0,108,115,113,117,111,0,0,0,47,98,117,112,117,51,47,51,0,0,0,0,0,0,0,0,110,97,118,121,0,0,0,0,97,122,117,114,101,0,0,0,97,113,117,97,109,97,114,105,110,101,52,0,0,0,0,0,97,113,117,97,109,97,114,105,110,101,51,0,0,0,0,0,97,113,117,97,109,97,114,105,110,101,50,0,0,0,0,0,97,113,117,97,109,97,114,105,110,101,49,0,0,0,0,0,35,37,48,50,120,37,48,50,120,37,48,50,120,0,0,0,97,113,117,97,109,97,114,105,110,101,0,0,0,0,0,0,32,102,111,110,116,45,119,101,105,103,104,116,61,34,37,115,34,0,0,0,0,0,0,0,37,37,37,37,80,97,103,101,58,32,37,100,32,37,100,10,0,0,0,0,0,0,0,0,97,110,116,105,113,117,101,119,104,105,116,101,52,0,0,0,97,110,116,105,113,117,101,119,104,105,116,101,51,0,0,0,97,110,116,105,113,117,101,119,104,105,116,101,50,0,0,0,97,110,116,105,113,117,101,119,104,105,116,101,49,0,0,0,108,115,97,113,117,111,0,0,47,98,117,112,117,51,47,50,0,0,0,0,0,0,0,0,97,110,116,105,113,117,101,119,104,105,116,101,0,0,0,0,97,108,105,99,101,98,108,117,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,121,108,111,114,114,100,57,47,57,0,0,0,0,0,0,65,118,97,110,116,71,97,114,100,101,45,68,101,109,105,79,98,108,105,113,117,101,0,0,47,121,108,111,114,114,100,57,47,56,0,0,0,0,0,0,47,121,108,111,114,114,100,57,47,55,0,0,0,0,0,0,47,121,108,111,114,114,100,57,47,54,0,0,0,0,0,0,44,37,115,0,0,0,0,0,88,77,76,32,111,114,32,116,101,120,116,32,100,101,99,108,97,114,97,116,105,111,110,32,110,111,116,32,97,116,32,115,116,97,114,116,32,111,102,32,101,110,116,105,116,121,0,0,37,37,37,37,69,110,100,80,97,103,101,58,32,37,100,10,0,0,0,0,0,0,0,0,47,121,108,111,114,114,100,57,47,53,0,0,0,0,0,0,92,72,0,0,0,0,0,0,47,121,108,111,114,114,100,57,47,52,0,0,0,0,0,0,47,121,108,111,114,114,100,57,47,51,0,0,0,0,0,0,115,101,116,108,105,110,101,119,105,100,116,104,0,0,0,0,47,121,108,111,114,114,100,57,47,50,0,0,0,0,0,0,108,114,109,0,0,0,0,0,47,98,117,112,117,51,47,49,0,0,0,0,0,0,0,0,47,121,108,111,114,114,100,57,47,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,121,108,111,114,114,100,56,47,56,0,0,0,0,0,0,47,121,108,111,114,114,100,56,47,55,0,0,0,0,0,0,108,104,101,105,103,104,116,0,47,121,108,111,114,114,100,56,47,54,0,0,0,0,0,0,45,62,0,0,0,0,0,0,66,111,117,110,100,105,110,103,66,111,120,32,110,111,116,32,102,111,117,110,100,32,105,110,32,101,112,115,102,32,102,105,108,101,32,37,115,10,0,0,47,121,108,111,114,114,100,56,47,53,0,0,0,0,0,0,47,121,108,111,114,114,100,56,47,52,0,0,0,0,0,0,32,102,111,110,116,45,102,97,109,105,108,121,61,34,37,115,0,0,0,0,0,0,0,0,99,111,114,97,108,0,0,0,37,37,80,97,103,101,84,114,97,105,108,101,114,10,0,0,47,121,108,111,114,114,100,56,47,51,0,0,0,0,0,0,105,110,115,116,97,108,108,95,105,110,95,114,97,110,107,32,37,115,32,37,115,32,114,97,110,107,32,37,100,32,105,32,61,32,37,100,32,97,110,32,61,32,48,10,0,0,0,0,47,121,108,111,114,114,100,56,47,50,0,0,0,0,0,0,47,121,108,111,114,114,100,56,47,49,0,0,0,0,0,0,47,121,108,111,114,114,100,55,47,55,0,0,0,0,0,0,108,111,122,0,0,0,0,0,47,98,117,103,110,57,47,57,0,0,0,0,0,0,0,0,47,121,108,111,114,114,100,55,47,54,0,0,0,0,0,0,47,121,108,111,114,114,100,55,47,53,0,0,0,0,0,0,47,121,108,111,114,114,100,55,47,52,0,0,0,0,0,0,47,121,108,111,114,114,100,55,47,51,0,0,0,0,0,0,47,121,108,111,114,114,100,55,47,50,0,0,0,0,0,0,47,121,108,111,114,114,100,55,47,49,0,0,0,0,0,0,32,120,61,34,37,103,34,32,121,61,34,37,103,34,0,0,60,115,118,103,0,0,0,0,101,110,100,112,97,103,101,10,115,104,111,119,112,97,103,101,10,103,114,101,115,116,111,114,101,10,0,0,0,0,0,0,47,84,105,109,101,115,45,82,111,109,97,110,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0,0,0,0,0,47,121,108,111,114,114,100,54,47,54,0,0,0,0,0,0,47,121,108,111,114,114,100,54,47,53,0,0,0,0,0,0,47,121,108,111,114,114,100,54,47,52,0,0,0,0,0,0,47,121,108,111,114,114,100,54,47,51,0,0,0,0,0,0,108,111,119,97,115,116,0,0,47,98,117,103,110,57,47,56,0,0,0,0,0,0,0,0,47,121,108,111,114,114,100,54,47,50,0,0,0,0,0,0,47,121,108,111,114,114,100,54,47,49,0,0,0,0,0,0,47,121,108,111,114,114,100,53,47,53,0,0,0,0,0,0,37,108,102,37,108,102,37,108,102,0,0,0,0,0,0,0,47,121,108,111,114,114,100,53,47,52,0,0,0,0,0,0,47,121,108,111,114,114,100,53,47,51,0,0,0,0,0,0,47,121,108,111,114,114,100,53,47,50,0,0,0,0,0,0,32,116,101,120,116,45,97,110,99,104,111,114,61,34,109,105,100,100,108,101,34,0,0,0,48,32,48,32,48,32,101,100,103,101,99,111,108,111,114,10,0,0,0,0,0,0,0,0,47,121,108,111,114,114,100,53,47,49,0,0,0,0,0,0,47,121,108,111,114,114,100,52,47,52,0,0,0,0,0,0,47,121,108,111,114,114,100,52,47,51,0,0,0,0,0,0,47,121,108,111,114,114,100,52,47,50,0,0,0,0,0,0,108,102,108,111,111,114,0,0,98,97,99,107,0,0,0,0,47,98,117,103,110,57,47,55,0,0,0,0,0,0,0,0,47,121,108,111,114,114,100,52,47,49,0,0,0,0,0,0,48,0,0,0,0,0,0,0,47,121,108,111,114,114,100,51,47,51,0,0,0,0,0,0,47,121,108,111,114,114,100,51,47,50,0,0,0,0,0,0,47,121,108,111,114,114,100,51,47,49,0,0,0,0,0,0,47,121,108,111,114,98,114,57,47,57,0,0,0,0,0,0,47,121,108,111,114,98,114,57,47,56,0,0,0,0,0,0,32,116,101,120,116,45,97,110,99,104,111,114,61,34,101,110,100,34,0,0,0,0,0,0,37,37,32,37,115,10,0,0,47,121,108,111,114,98,114,57,47,55,0,0,0,0,0,0,78,68,95,111,117,116,40,118,41,46,115,105,122,101,32,61,61,32,50,0,0,0,0,0,60,97,114,101,97,32,115,104,97,112,101,61,34,112,111,108,121,34,0,0,0,0,0,0,71,115,116,97,99,107,32,117,110,100,101,114,102,108,111,119,32,105,110,32,103,114,97,112,104,32,112,97,114,115,101,114,10,0,0,0,0,0,0,0,47,121,108,111,114,98,114,57,47,54,0,0,0,0,0,0,47,121,108,111,114,98,114,57,47,53,0,0,0,0,0,0,47,121,108,111,114,98,114,57,47,52,0,0,0,0,0,0,108,101,0,0,0,0,0,0,47,98,117,103,110,57,47,54,0,0,0,0,0,0,0,0,47,121,108,111,114,98,114,57,47,51,0,0,0,0,0,0,47,121,108,111,114,98,114,57,47,50,0,0,0,0,0,0,47,121,108,111,114,98,114,57,47,49,0,0,0,0,0,0,47,121,108,111,114,98,114,56,47,56,0,0,0,0,0,0,47,121,108,111,114,98,114,56,47,55,0,0,0,0,0,0,47,121,108,111,114,98,114,56,47,54,0,0,0,0,0,0,32,116,101,120,116,45,97,110,99,104,111,114,61,34,115,116,97,114,116,34,0,0,0,0,103,115,97,118,101,10,0,0,47,121,108,111,114,98,114,56,47,53,0,0,0,0,0,0,47,97,99,99,101,110,116,54,47,52,0,0,0,0,0,0,47,121,108,111,114,98,114,56,47,52,0,0,0,0,0,0,47,121,108,111,114,98,114,56,47,51,0,0,0,0,0,0,47,121,108,111,114,98,114,56,47,50,0,0,0,0,0,0,108,100,113,117,111,0,0,0,47,98,117,103,110,57,47,53,0,0,0,0,0,0,0,0,47,121,108,111,114,98,114,56,47,49,0,0,0,0,0,0,47,121,108,111,114,98,114,55,47,55,0,0,0,0,0,0,47,121,108,111,114,98,114,55,47,54,0,0,0,0,0,0,47,121,108,111,114,98,114,55,47,53,0,0,0,0,0,0,47,121,108,111,114,98,114,55,47,52,0,0,0,0,0,0,47,121,108,111,114,98,114,55,47,51,0,0,0,0,0,0,60,116,101,120,116,0,0,0,103,114,101,115,116,111,114,101,10,0,0,0,0,0,0,0,47,121,108,111,114,98,114,55,47,50,0,0,0,0,0,0,116,114,105,97,110,103,108,101,0,0,0,0,0,0,0,0,47,121,108,111,114,98,114,55,47,49,0,0,0,0,0,0,47,121,108,111,114,98,114,54,47,54,0,0,0,0,0,0,47,121,108,111,114,98,114,54,47,53,0,0,0,0,0,0,108,99,101,105,108,0,0,0,47,98,117,103,110,57,47,52,0,0,0,0,0,0,0,0,47,121,108,111,114,98,114,54,47,52,0,0,0,0,0,0,47,121,108,111,114,98,114,54,47,51,0,0,0,0,0,0,47,121,108,111,114,98,114,54,47,50,0,0,0,0,0,0,47,121,108,111,114,98,114,54,47,49,0,0,0,0,0,0,47,121,108,111,114,98,114,53,47,53,0,0,0,0,0,0,47,121,108,111,114,98,114,53,47,52,0,0,0,0,0,0,47,62,10,0,0,0,0,0,45,62,0,0,0,0,0,0,112,115,58,112,115,0,0,0,32,32,47,66,111,114,100,101,114,32,91,32,48,32,48,32,48,32,93,10,32,32,47,65,99,116,105,111,110,32,60,60,32,47,83,117,98,116,121,112,101,32,47,85,82,73,32,47,85,82,73,32,37,115,32,62,62,10,32,32,47,83,117,98,116,121,112,101,32,47,76,105,110,107,10,47,65,78,78,32,112,100,102,109,97,114,107,10,0,0,0,0,0,0,0,0,47,121,108,111,114,98,114,53,47,51,0,0,0,0,0,0,45,62,0,0,0,0,0,0,47,121,108,111,114,98,114,53,47,50,0,0,0,0,0,0,47,121,108,111,114,98,114,53,47,49,0,0,0,0,0,0,47,121,108,111,114,98,114,52,47,52,0,0,0,0,0,0,108,97,114,114,0,0,0,0,47,98,117,103,110,57,47,51,0,0,0,0,0,0,0,0,47,121,108,111,114,98,114,52,47,51,0,0,0,0,0,0,47,121,108,111,114,98,114,52,47,50,0,0,0,0,0,0,47,121,108,111,114,98,114,52,47,49,0,0,0,0,0,0,47,121,108,111,114,98,114,51,47,51,0,0,0,0,0,0,47,121,108,111,114,98,114,51,47,50,0,0,0,0,0,0,32,37,115,10,0,0,0,0,66,82,0,0,0,0,0,0,47,121,108,111,114,98,114,51,47,49,0,0,0,0,0,0,32,114,120,61,34,37,103,34,32,114,121,61,34,37,103,34,0,0,0,0,0,0,0,0,32,93,10,0,0,0,0,0,47,121,108,103,110,98,117,57,47,57,0,0,0,0,0,0,47,121,108,103,110,98,117,57,47,56,0,0,0,0,0,0,47,121,108,103,110,98,117,57,47,55,0,0,0,0,0,0,47,121,108,103,110,98,117,57,47,54,0,0,0,0,0,0,108,97,113,117,111,0,0,0,47,98,117,103,110,57,47,50,0,0,0,0,0,0,0,0,109,97,114,111,111,110,0,0,47,121,108,103,110,98,117,57,47,53,0,0,0,0,0,0,37,100,32,37,49,91,34,93,37,110,0,0,0,0,0,0,47,121,108,103,110,98,117,57,47,52,0,0,0,0,0,0,47,121,108,103,110,98,117,57,47,51,0,0,0,0,0,0,47,121,108,103,110,98,117,57,47,50,0,0,0,0,0,0,47,121,108,103,110,98,117,57,47,49,0,0,0,0,0,0,34,34,0,0,0,0,0,0,47,121,108,103,110,98,117,56,47,56,0,0,0,0,0,0,32,99,120,61,34,37,103,34,32,99,121,61,34,37,103,34,0,0,0,0,0,0,0,0,105,115,109,97,112,58,109,97,112,0,0,0,0,0,0,0,47,121,108,103,110,98,117,56,47,55,0,0,0,0,0,0,47,121,108,103,110,98,117,56,47,54,0,0,0,0,0,0,91,32,47,82,101,99,116,32,91,32,0,0,0,0,0,0,47,121,108,103,110,98,117,56,47,53,0,0,0,0,0,0,47,121,108,103,110,98,117,56,47,52,0,0,0,0,0,0,108,97,110,103,0,0,0,0,47,98,117,103,110,57,47,49,0,0,0,0,0,0,0,0,47,121,108,103,110,98,117,56,47,51,0,0,0,0,0,0,47,121,108,103,110,98,117,56,47,50,0,0,0,0,0,0,47,121,108,103,110,98,117,56,47,49,0,0,0,0,0,0,99,111,109,109,101,110,116,0,47,121,108,103,110,98,117,55,47,55,0,0,0,0,0,0,98,111,108,100,0,0,0,0,47,121,108,103,110,98,117,55,47,54,0,0,0,0,0,0,47,121,108,103,110,98,117,55,47,53,0,0,0,0,0,0,60,101,108,108,105,112,115,101,0,0,0,0,0,0,0,0,114,101,102,101,114,101,110,99,101,32,116,111,32,101,120,116,101,114,110,97,108,32,101,110,116,105,116,121,32,105,110,32,97,116,116,114,105,98,117,116,101,0,0,0,0,0,0,0,32,37,115,32,97,108,105,103,110,101,100,116,101,120,116,10,0,0,0,0,0,0,0,0,47,121,108,103,110,98,117,55,47,52,0,0,0,0,0,0,47,121,108,103,110,98,117,55,47,51,0,0,0,0,0,0,92,69,0,0,0,0,0,0,47,121,108,103,110,98,117,55,47,50,0,0,0,0,0,0,98,111,108,100,0,0,0,0,47,121,108,103,110,98,117,55,47,49,0,0,0,0,0,0,108,97,109,98,100,97,0,0,47,98,117,103,110,56,47,56,0,0,0,0,0,0,0,0,47,121,108,103,110,98,117,54,47,54,0,0,0,0,0,0,47,121,108,103,110,98,117,54,47,53,0,0,0,0,0,0,69,100,103,101,32,37,112,32,119,97,115,32,110,111,116,32,102,111,117,110,100,10,0,0,47,121,108,103,110,98,117,54,47,52,0,0,0,0,0,0,108,119,105,100,116,104,0,0,47,121,108,103,110,98,117,54,47,51,0,0,0,0,0,0,116,111,111,108,116,105,112,0,114,101,97,100,0,0,0,0,47,121,108,103,110,98,117,54,47,50,0,0,0,0,0,0,47,121,108,103,110,98,117,54,47,49,0,0,0,0,0,0,37,103,44,37,103,0,0,0,32,109,111,118,101,116,111,32,0,0,0,0,0,0,0,0,99,104,111,99,111,108,97,116,101,0,0,0,0,0,0,0,47,121,108,103,110,98,117,53,47,53,0,0,0,0,0,0,47,121,108,103,110,98,117,53,47,52,0,0,0,0,0,0,47,121,108,103,110,98,117,53,47,51,0,0,0,0,0,0,47,121,108,103,110,98,117,53,47,50,0,0,0,0,0,0,108,65,114,114,0,0,0,0,47,98,117,103,110,56,47,55,0,0,0,0,0,0,0,0,47,121,108,103,110,98,117,53,47,49,0,0,0,0,0,0,47,121,108,103,110,98,117,52,47,52,0,0,0,0,0,0,47,121,108,103,110,98,117,52,47,51,0,0,0,0,0,0,47,121,108,103,110,98,117,52,47,50,0,0,0,0,0,0,47,121,108,103,110,98,117,52,47,49,0,0,0,0,0,0,47,121,108,103,110,98,117,51,47,51,0,0,0,0,0,0,60,112,111,108,121,103,111,110,0,0,0,0,0,0,0,0,37,37,37,37,66,111,117,110,100,105,110,103,66,111,120,58,32,37,100,32,37,100,32,37,100,32,37,100,0,0,0,0,32,47,37,115,32,115,101,116,95,102,111,110,116,10,0,0,104,101,97,100,112,111,114,116,0,0,0,0,0,0,0,0,47,121,108,103,110,98,117,51,47,50,0,0,0,0,0,0,125,32,100,101,102,0,0,0,47,121,108,103,110,98,117,51,47,49,0,0,0,0,0,0,101,114,114,111,114,32,105,110,32,99,111,108,120,108,97,116,101,40,41,10,0,0,0,0,47,121,108,103,110,57,47,57,0,0,0,0,0,0,0,0,47,121,108,103,110,57,47,56,0,0,0,0,0,0,0,0,115,105,100,101,115,32,61,61,32,52,0,0,0,0,0,0,107,97,112,112,97,0,0,0,47,98,117,103,110,56,47,54,0,0,0,0,0,0,0,0,47,121,108,103,110,57,47,55,0,0,0,0,0,0,0,0,47,121,108,103,110,57,47,54,0,0,0,0,0,0,0,0,47,121,108,103,110,57,47,53,0,0,0,0,0,0,0,0,47,121,108,103,110,57,47,52,0,0,0,0,0,0,0,0,47,121,108,103,110,57,47,51,0,0,0,0,0,0,0,0,47,121,108,103,110,57,47,50,0,0,0,0,0,0,0,0,37,99,37,103,44,37,103,0,32,101,108,108,105,112,115,101,95,112,97,116,104,32,115,116,114,111,107,101,10,0,0,0,47,121,108,103,110,57,47,49,0,0,0,0,0,0,0,0,47,121,108,103,110,56,47,56,0,0,0,0,0,0,0,0,47,121,108,103,110,56,47,55,0,0,0,0,0,0,0,0,47,121,108,103,110,56,47,54,0,0,0,0,0,0,0,0,105,117,109,108,0,0,0,0,102,111,114,119,97,114,100,0,47,98,117,103,110,56,47,53,0,0,0,0,0,0,0,0,47,121,108,103,110,56,47,53,0,0,0,0,0,0,0,0,47,121,108,103,110,56,47,52,0,0,0,0,0,0,0,0,47,121,108,103,110,56,47,51,0,0,0,0,0,0,0,0,47,121,108,103,110,56,47,50,0,0,0,0,0,0,0,0,47,121,108,103,110,56,47,49,0,0,0,0,0,0,0,0,114,111,117,116,101,115,112,108,105,110,101,115,58,32,37,100,32,101,100,103,101,115,44,32,37,100,32,98,111,120,101,115,32,37,46,50,102,32,115,101,99,10,0,0,0,0,0,0,47,121,108,103,110,55,47,55,0,0,0,0,0,0,0,0,32,100,61,34,0,0,0,0,32,101,108,108,105,112,115,101,95,112,97,116,104,32,102,105,108,108,10,0,0,0,0,0,47,121,108,103,110,55,47,54,0,0,0,0,0,0,0,0,47,121,108,103,110,55,47,53,0,0,0,0,0,0,0,0,60,97,114,101,97,32,115,104,97,112,101,61,34,114,101,99,116,34,0,0,0,0,0,0,95,97,110,111,110,121,109,111,117,115,95,37,100,0,0,0,47,121,108,103,110,55,47,52,0,0,0,0,0,0,0,0,47,121,108,103,110,55,47,51,0,0,0,0,0,0,0,0,47,112,97,116,104,98,111,120,32,123,10,32,32,32,32,47,89,32,101,120,99,104,32,37,46,53,103,32,115,117,98,32,100,101,102,10,32,32,32,32,47,88,32,101,120,99,104,32,37,46,53,103,32,115,117,98,32,100,101,102,10,32,32,32,32,47,121,32,101,120,99,104,32,37,46,53,103,32,115,117,98,32,100,101,102,10,32,32,32,32,47,120,32,101,120,99,104,32,37,46,53,103,32,115,117,98,32,100,101,102,10,32,32,32,32,110,101,119,112,97,116,104,32,120,32,121,32,109,111,118,101,116,111,10,32,32,32,32,88,32,121,32,108,105,110,101,116,111,10,32,32,32,32,88,32,89,32,108,105,110,101,116,111,10,32,32,32,32,120,32,89,32,108,105,110,101,116,111,10,32,32,32,32,99,108,111,115,101,112,97,116,104,32,115,116,114,111,107,101,10,32,125,32,100,101,102,10,47,100,98,103,115,116,97,114,116,32,123,32,103,115,97,118,101,32,37,46,53,103,32,37,46,53,103,32,116,114,97,110,115,108,97,116,101,32,125,32,100,101,102,10,47,97,114,114,111,119,108,101,110,103,116,104,32,49,48,32,100,101,102,10,47,97,114,114,111,119,119,105,100,116,104,32,97,114,114,111,119,108,101,110,103,116,104,32,50,32,100,105,118,32,100,101,102,10,47,97,114,114,111,119,104,101,97,100,32,123,10,32,32,32,32,103,115,97,118,101,10,32,32,32,32,114,111,116,97,116,101,10,32,32,32,32,99,117,114,114,101,110,116,112,111,105,110,116,10,32,32,32,32,110,101,119,112,97,116,104,10,32,32,32,32,109,111,118,101,116,111,10,32,32,32,32,97,114,114,111,119,108,101,110,103,116,104,32,97,114,114,111,119,119,105,100,116,104,32,50,32,100,105,118,32,114,108,105,110,101,116,111,10,32,32,32,32,48,32,97,114,114,111,119,119,105,100,116,104,32,110,101,103,32,114,108,105,110,101,116,111,10,32,32,32,32,99,108,111,115,101,112,97,116,104,32,102,105,108,108,10,32,32,32,32,103,114,101,115,116,111,114,101,10,125,32,98,105,110,100,32,100,101,102,10,47,109,97,107,101,97,114,114,111,119,32,123,10,32,32,32,32,99,117,114,114,101,110,116,112,111,105,110,116,32,101,120,99,104,32,112,111,112,32,115,117,98,32,101,120,99,104,32,99,117,114,114,101,110,116,112,111,105,110,116,32,112,111,112,32,115,117,98,32,97,116,97,110,10,32,32,32,32,97,114,114,111,119,104,101,97,100,10,125,32,98,105,110,100,32,100,101,102,10,47,112,111,105,110,116,32,123,32,32,32,32,110,101,119,112,97,116,104,32,32,32,32,50,32,48,32,51,54,48,32,97,114,99,32,102,105,108,108,125,32,100,101,102,47,109,97,107,101,118,101,99,32,123,10,32,32,32,32,47,89,32,101,120,99,104,32,100,101,102,10,32,32,32,32,47,88,32,101,120,99,104,32,100,101,102,10,32,32,32,32,47,121,32,101,120,99,104,32,100,101,102,10,32,32,32,32,47,120,32,101,120,99,104,32,100,101,102,10,32,32,32,32,110,101,119,112,97,116,104,32,120,32,121,32,109,111,118,101,116,111,10,32,32,32,32,88,32,89,32,108,105,110,101,116,111,32,115,116,114,111,107,101,10,32,32,32,32,88,32,89,32,109,111,118,101,116,111,10,32,32,32,32,120,32,121,32,109,97,107,101,97,114,114,111,119,10,125,32,100,101,102,10,0,0,0,0,0,0,105,115,105,110,0,0,0,0,47,98,117,103,110,56,47,52,0,0,0,0,0,0,0,0,47,121,108,103,110,55,47,50,0,0,0,0,0,0,0,0,47,121,108,103,110,55,47,49,0,0,0,0,0,0,0,0,47,121,108,103,110,54,47,54,0,0,0,0,0,0,0,0,47,121,108,103,110,54,47,53,0,0,0,0,0,0,0,0,47,121,108,103,110,54,47,52,0,0,0,0,0,0,0,0,47,121,108,103,110,54,47,51,0,0,0,0,0,0,0,0,60,112,97,116,104,0,0,0,99,108,111,115,101,112,97,116,104,32,115,116,114,111,107,101,10,0,0,0,0,0,0,0,47,121,108,103,110,54,47,50,0,0,0,0,0,0,0,0,47,97,99,99,101,110,116,54,47,51,0,0,0,0,0,0,47,121,108,103,110,54,47,49,0,0,0,0,0,0,0,0,47,121,108,103,110,53,47,53,0,0,0,0,0,0,0,0,47,121,108,103,110,53,47,52,0,0,0,0,0,0,0,0,105,113,117,101,115,116,0,0,47,98,117,103,110,56,47,51,0,0,0,0,0,0,0,0,47,121,108,103,110,53,47,51,0,0,0,0,0,0,0,0,47,121,108,103,110,53,47,50,0,0,0,0,0,0,0,0,47,121,108,103,110,53,47,49,0,0,0,0,0,0,0,0,47,121,108,103,110,52,47,52,0,0,0,0,0,0,0,0,47,121,108,103,110,52,47,51,0,0,0,0,0,0,0,0,47,121,108,103,110,52,47,50,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,99,108,111,115,101,112,97,116,104,32,102,105,108,108,10,0,47,121,108,103,110,52,47,49,0,0,0,0,0,0,0,0,37,115,32,37,100,32,110,111,100,101,115,32,37,100,32,101,100,103,101,115,32,109,97,120,105,116,101,114,61,37,100,32,98,97,108,97,110,99,101,61,37,100,10,0,0,0,0,0,101,103,103,0,0,0,0,0,47,121,108,103,110,51,47,51,0,0,0,0,0,0,0,0,47,121,108,103,110,51,47,50,0,0,0,0,0,0,0,0,47,121,108,103,110,51,47,49,0,0,0,0,0,0,0,0,105,111,116,97,0,0,0,0,47,98,117,103,110,56,47,50,0,0,0,0,0,0,0,0,47,115,118,103,47,121,101,108,108,111,119,103,114,101,101,110,0,0,0,0,0,0,0,0,47,115,118,103,47,121,101,108,108,111,119,0,0,0,0,0,47,115,118,103,47,119,104,105,116,101,115,109,111,107,101,0,47,115,118,103,47,119,104,105,116,101,0,0,0,0,0,0,47,115,118,103,47,119,104,101,97,116,0,0,0,0,0,0,47,115,118,103,47,118,105,111,108,101,116,0,0,0,0,0,103,118,114,101,110,100,101,114,95,99,111,114,101,95,115,118,103,46,99,0,0,0,0,0,99,111,108,111,114,0,0,0,101,112,115,58,108,97,115,105,0,0,0,0,0,0,0,0,32,99,117,114,118,101,116,111,10,0,0,0,0,0,0,0,47,115,118,103,47,116,117,114,113,117,111,105,115,101,0,0,116,101,120,116,108,97,121,111,117,116,0,0,0,0,0,0,47,115,118,103,47,116,111,109,97,116,111,0,0,0,0,0,47,115,118,103,47,116,104,105,115,116,108,101,0,0,0,0,47,115,118,103,47,116,101,97,108,0,0,0,0,0,0,0,105,110,116,0,0,0,0,0,47,98,117,103,110,56,47,49,0,0,0,0,0,0,0,0,47,115,118,103,47,116,97,110,0,0,0,0,0,0,0,0,47,115,118,103,47,115,116,101,101,108,98,108,117,101,0,0,47,115,118,103,47,115,112,114,105,110,103,103,114,101,101,110,0,0,0,0,0,0,0,0,47,115,118,103,47,115,110,111,119,0,0,0,0,0,0,0,47,115,118,103,47,115,108,97,116,101,103,114,101,121,0,0,83,85,66,0,0,0,0,0,47,115,118,103,47,115,108,97,116,101,103,114,97,121,0,0,35,37,48,50,120,37,48,50,120,37,48,50,120,0,0,0,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,49,102,32,37,100,32,37,100,32,37,100,32,37,100,10,0,0,0,0,115,116,114,111,107,101,10,0,47,115,118,103,47,115,108,97,116,101,98,108,117,101,0,0,47,115,118,103,47,115,107,121,98,108,117,101,0,0,0,0,47,115,118,103,47,115,105,108,118,101,114,0,0,0,0,0,47,115,118,103,47,115,105,101,110,110,97,0,0,0,0,0,105,110,102,105,110,0,0,0,47,98,117,103,110,55,47,55,0,0,0,0,0,0,0,0,108,105,109,101,0,0,0,0,47,115,118,103,47,115,101,97,115,104,101,108,108,0,0,0,47,115,118,103,47,115,101,97,103,114,101,101,110,0,0,0,108,105,110,101,0,0,0,0,47,115,118,103,47,115,97,110,100,121,98,114,111,119,110,0,47,115,118,103,47,115,97,108,109,111,110,0,0,0,0,0,47,115,118,103,47,115,97,100,100,108,101,98,114,111,119,110,0,0,0,0,0,0,0,0,32,45,116,97,103,115,32,123,37,100,37,115,37,100,125,0,47,115,118,103,47,114,111,121,97,108,98,108,117,101,0,0,53,44,50,0,0,0,0,0,32,108,105,110,101,116,111,10,0,0,0,0,0,0,0,0,47,115,118,103,47,114,111,115,121,98,114,111,119,110,0,0,47,115,118,103,47,114,101,100,0,0,0,0,0,0,0,0,47,115,118,103,47,112,117,114,112,108,101,0,0,0,0,0,47,115,118,103,47,112,111,119,100,101,114,98,108,117,101,0,105,109,97,103,101,0,0,0,47,98,117,103,110,55,47,54,0,0,0,0,0,0,0,0,47,115,118,103,47,112,108,117,109,0,0,0,0,0,0,0,47,115,118,103,47,112,105,110,107,0,0,0,0,0,0,0,47,115,118,103,47,112,101,114,117,0,0,0,0,0,0,0,47,115,118,103,47,112,101,97,99,104,112,117,102,102,0,0,37,108,100,0,0,0,0,0,100,101,109,105,0,0,0,0,47,115,118,103,47,112,97,112,97,121,97,119,104,105,112,0,47,115,118,103,47,112,97,108,101,118,105,111,108,101,116,114,101,100,0,0,0,0,0,0,49,44,53,0,0,0,0,0,114,101,102,101,114,101,110,99,101,32,116,111,32,98,105,110,97,114,121,32,101,110,116,105,116,121,0,0,0,0,0,0,32,109,111,118,101,116,111,10,0,0,0,0,0,0,0,0,47,115,118,103,47,112,97,108,101,116,117,114,113,117,111,105,115,101,0,0,0,0,0,0,47,115,118,103,47,112,97,108,101,103,114,101,101,110,0,0,92,78,0,0,0,0,0,0,47,115,118,103,47,112,97,108,101,103,111,108,100,101,110,114,111,100,0,0,0,0,0,0,102,105,108,108,101,100,0,0,102,108,97,116,105,110,100,101,120,40,97,103,116,97,105,108,40,101,41,41,32,60,32,77,45,62,110,99,111,108,115,0,47,115,118,103,47,111,114,99,104,105,100,0,0,0,0,0,105,103,114,97,118,101,0,0,47,98,117,103,110,55,47,53,0,0,0,0,0,0,0,0,47,115,118,103,47,111,114,97,110,103,101,114,101,100,0,0,47,115,118,103,47,111,114,97,110,103,101,0,0,0,0,0,34,34,0,0,0,0,0,0,115,104,111,114,116,101,115,116,46,99,0,0,0,0,0,0,47,115,118,103,47,111,108,105,118,101,100,114,97,98,0,0,116,97,105,108,95,108,112,0,47,115,118,103,47,111,108,105,118,101,0,0,0,0,0,0,114,0,0,0,0,0,0,0,37,37,37,37,66,111,117,110,100,105,110,103,66,111,120,58,32,37,100,32,37,100,32,37,100,32,37,100,0,0,0,0,47,115,118,103,47,111,108,100,108,97,99,101,0,0,0,0,47,115,118,103,47,110,97,118,121,0,0,0,0,0,0,0,34,0,0,0,0,0,0,0,110,101,119,112,97,116,104,32,0,0,0,0,0,0,0,0,99,104,97,114,116,114,101,117,115,101,0,0,0,0,0,0,47,115,118,103,47,110,97,118,97,106,111,119,104,105,116,101,0,0,0,0,0,0,0,0,47,115,118,103,47,109,111,99,99,97,115,105,110,0,0,0,47,115,118,103,47,109,105,115,116,121,114,111,115,101,0,0,47,115,118,103,47,109,105,110,116,99,114,101,97,109,0,0,102,97,108,115,101,0,0,0,105,101,120,99,108,0,0,0,47,98,117,103,110,55,47,52,0,0,0,0,0,0,0,0,47,115,118,103,47,109,105,100,110,105,103,104,116,98,108,117,101,0,0,0,0,0,0,0,103,105,102,58,115,118,103,0,47,115,118,103,47,109,101,100,105,117,109,118,105,111,108,101,116,114,101,100,0,0,0,0,47,115,118,103,47,109,101,100,105,117,109,116,117,114,113,117,111,105,115,101,0,0,0,0,47,115,118,103,47,109,101,100,105,117,109,115,112,114,105,110,103,103,114,101,101,110,0,0,47,115,118,103,47,109,101,100,105,117,109,115,108,97,116,101,98,108,117,101,0,0,0,0,47,115,118,103,47,109,101,100,105,117,109,115,101,97,103,114,101,101,110,0,0,0,0,0,34,32,115,116,114,111,107,101,45,111,112,97,99,105,116,121,61,34,37,102,0,0,0,0,37,37,66,111,117,110,100,105,110,103,66,111,120,58,0,0,10,0,0,0,0,0,0,0,47,115,118,103,47,109,101,100,105,117,109,112,117,114,112,108,101,0,0,0,0,0,0,0,116,97,105,108,112,111,114,116,0,0,0,0,0,0,0,0,32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,100,105,99,116,32,101,110,100,32,100,101,102,105,110,101,102,111,110,116,0,0,0,0,0,0,47,115,118,103,47,109,101,100,105,117,109,111,114,99,104,105,100,0,0,0,0,0,0,0,37,115,32,105,115,32,110,111,116,32,97,32,107,110,111,119,110,32,99,111,108,111,114,46,10,0,0,0,0,0,0,0,47,115,118,103,47,109,101,100,105,117,109,98,108,117,101,0,83,121,110,116,97,120,32,101,114,114,111,114,58,32,110,111])
+.concat([110,45,115,112,97,99,101,32,115,116,114,105,110,103,32,117,115,101,100,32,97,102,116,101,114,32,60,47,84,65,66,76,69,62,0,0,0,0,0,0,47,115,118,103,47,109,101,100,105,117,109,97,113,117,97,109,97,114,105,110,101,0,0,0,105,99,105,114,99,0,0,0,47,98,117,103,110,55,47,51,0,0,0,0,0,0,0,0,47,115,118,103,47,109,97,114,111,111,110,0,0,0,0,0,47,115,118,103,47,109,97,103,101,110,116,97,0,0,0,0,47,115,118,103,47,108,105,110,101,110,0,0,0,0,0,0,47,115,118,103,47,108,105,109,101,103,114,101,101,110,0,0,47,115,118,103,47,108,105,109,101,0,0,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,121,101,108,108,111,119,0,0,0,0,0,0,0,0,34,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,61,34,37,115,0,0,37,32,0,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,115,116,101,101,108,98,108,117,101,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,115,108,97,116,101,103,114,101,121,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,115,108,97,116,101,103,114,97,121,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,115,107,121,98,108,117,101,0,0,0,0,0,0,0,105,97,99,117,116,101,0,0,105,110,118,101,109,112,116,121,0,0,0,0,0,0,0,0,47,98,117,103,110,55,47,50,0,0,0,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,115,101,97,103,114,101,101,110,0,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,115,97,108,109,111,110,0,0,0,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,112,105,110,107,0,0,102,108,97,116,105,110,100,101,120,40,97,103,104,101,97,100,40,101,41,41,32,60,32,77,45,62,110,114,111,119,115,0,47,115,118,103,47,108,105,103,104,116,103,114,101,121,0,0,47,115,118,103,47,108,105,103,104,116,103,114,101,101,110,0,47,115,118,103,47,108,105,103,104,116,103,114,97,121,0,0,34,32,115,116,114,111,107,101,45,119,105,100,116,104,61,34,37,103,0,0,0,0,0,0,37,46,53,103,32,37,46,53,103,32,37,46,53,103,32,37,115,99,111,108,111,114,10,0,47,115,118,103,47,108,105,103,104,116,103,111,108,100,101,110,114,111,100,121,101,108,108,111,119,0,0,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,99,121,97,110,0,0,47,115,118,103,47,108,105,103,104,116,99,111,114,97,108,0,60,97,114,101,97,32,115,104,97,112,101,61,34,99,105,114,99,108,101,34,0,0,0,0,80,108,101,97,115,101,32,117,115,101,32,97,32,115,105,110,103,108,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,116,104,101,32,115,117,98,103,114,97,112,104,32,119,105,116,104,105,110,32,116,104,101,32,99,111,110,116,101,120,116,32,111,102,32,105,116,115,32,112,97,114,101,110,116,32,103,114,97,112,104,32,34,37,115,34,10,0,0,0,0,0,47,115,118,103,47,108,105,103,104,116,98,108,117,101,0,0,104,101,108,108,105,112,0,0,47,98,117,103,110,55,47,49,0,0,0,0,0,0,0,0,47,115,118,103,47,108,101,109,111,110,99,104,105,102,102,111,110,0,0,0,0,0,0,0,47,115,118,103,47,108,97,119,110,103,114,101,101,110,0,0,47,115,118,103,47,108,97,118,101,110,100,101,114,98,108,117,115,104,0,0,0,0,0,0,47,115,118,103,47,108,97,118,101,110,100,101,114,0,0,0,47,115,118,103,47,107,104,97,107,105,0,0,0,0,0,0,47,115,118,103,47,105,118,111,114,121,0,0,0,0,0,0,34,32,115,116,114,111,107,101,61,34,0,0,0,0,0,0,115,101,116,104,115,98,0,0,47,115,118,103,47,105,110,100,105,103,111,0,0,0,0,0,47,97,99,99,101,110,116,54,47,50,0,0,0,0,0,0,47,115,118,103,47,105,110,100,105,97,110,114,101,100,0,0,47,115,118,103,47,104,111,116,112,105,110,107,0,0,0,0,47,115,118,103,47,104,111,110,101,121,100,101,119,0,0,0,104,101,97,114,116,115,0,0,47,98,117,103,110,54,47,54,0,0,0,0,0,0,0,0,47,115,118,103,47,103,114,101,121,0,0,0,0,0,0,0,47,115,118,103,47,103,114,101,101,110,121,101,108,108,111,119,0,0,0,0,0,0,0,0,47,115,118,103,47,103,114,101,101,110,0,0,0,0,0,0,47,115,118,103,47,103,114,97,121,0,0,0,0,0,0,0,47,115,118,103,47,103,111,108,100,101,110,114,111,100,0,0,47,115,118,103,47,103,111,108,100,0,0,0,0,0,0,0,110,111,110,101,0,0,0,0,101,100,103,101,0,0,0,0,47,115,118,103,47,103,104,111,115,116,119,104,105,116,101,0,112,111,105,110,116,0,0,0,47,115,118,103,47,103,97,105,110,115,98,111,114,111,0,0,47,115,118,103,47,102,117,99,104,115,105,97,0,0,0,0,47,115,118,103,47,102,111,114,101,115,116,103,114,101,101,110,0,0,0,0,0,0,0,0,104,97,114,114,0,0,0,0,47,98,117,103,110,54,47,53,0,0,0,0,0,0,0,0,47,115,118,103,47,102,108,111,114,97,108,119,104,105,116,101,0,0,0,0,0,0,0,0,47,115,118,103,47,102,105,114,101,98,114,105,99,107,0,0,47,115,118,103,47,100,111,100,103,101,114,98,108,117,101,0,47,115,118,103,47,100,105,109,103,114,101,121,0,0,0,0,47,115,118,103,47,100,105,109,103,114,97,121,0,0,0,0,47,115,118,103,47,100,101,101,112,115,107,121,98,108,117,101,0,0,0,0,0,0,0,0,34,32,102,105,108,108,45,111,112,97,99,105,116,121,61,34,37,102,0,0,0,0,0,0,112,101,110,99,111,108,111,114,0,0,0,0,0,0,0,0,110,111,100,101,0,0,0,0,101,112,115,58,112,115,0,0,47,115,118,103,47,100,101,101,112,112,105,110,107,0,0,0,47,115,118,103,47,100,97,114,107,118,105,111,108,101,116,0,47,115,118,103,47,100,97,114,107,116,117,114,113,117,111,105,115,101,0,0,0,0,0,0,47,115,118,103,47,100,97,114,107,115,108,97,116,101,103,114,101,121,0,0,0,0,0,0,104,65,114,114,0,0,0,0,47,98,117,103,110,54,47,52,0,0,0,0,0,0,0,0,47,115,118,103,47,100,97,114,107,115,108,97,116,101,103,114,97,121,0,0,0,0,0,0,47,115,118,103,47,100,97,114,107,115,108,97,116,101,98,108,117,101,0,0,0,0,0,0,47,115,118,103,47,100,97,114,107,115,101,97,103,114,101,101,110,0,0,0,0,0,0,0,47,115,118,103,47,100,97,114,107,115,97,108,109,111,110,0,47,115,118,103,47,100,97,114,107,114,101,100,0,0,0,0,83,85,80,0,0,0,0,0,47,115,118,103,47,100,97,114,107,111,114,99,104,105,100,0,32,102,105,108,108,61,34,0,103,114,97,112,104,0,0,0,47,115,118,103,47,100,97,114,107,111,114,97,110,103,101,0,110,32,62,61,32,52,0,0,47,115,118,103,47,100,97,114,107,111,108,105,118,101,103,114,101,101,110,0,0,0,0,0,47,115,118,103,47,100,97,114,107,109,97,103,101,110,116,97,0,0,0,0,0,0,0,0,47,115,118,103,47,100,97,114,107,107,104,97,107,105,0,0,103,116,0,0,0,0,0,0,47,98,117,103,110,54,47,51,0,0,0,0,0,0,0,0,103,114,101,101,110,0,0,0,47,115,118,103,47,100,97,114,107,103,114,101,121,0,0,0,47,115,118,103,47,100,97,114,107,103,114,101,101,110,0,0,47,115,118,103,47,100,97,114,107,103,114,97,121,0,0,0,37,115,58,37,100,58,32,115,116,114,105,110,103,32,114,97,110,32,112,97,115,116,32,101,110,100,32,111,102,32,108,105,110,101,10,0,0,0,0,0,47,115,118,103,47,100,97,114,107,103,111,108,100,101,110,114,111,100,0,0,0,0,0,0,47,115,118,103,47,100,97,114,107,99,121,97,110,0,0,0,48,0,0,0,0,0,0,0,47,115,118,103,47,100,97,114,107,98,108,117,101,0,0,0,34,47,62,10,0,0,0,0,37,115,10,0,0,0,0,0,47,115,118,103,47,99,121,97,110,0,0,0,0,0,0,0,47,115,118,103,47,99,114,105,109,115,111,110,0,0,0,0,47,115,118,103,47,99,111,114,110,115,105,108,107,0,0,0,47,115,118,103,47,99,111,114,110,102,108,111,119,101,114,98,108,117,101,0,0,0,0,0,103,101,0,0,0,0,0,0,47,98,117,103,110,54,47,50,0,0,0,0,0,0,0,0,47,115,118,103,47,99,111,114,97,108,0,0,0,0,0,0,47,115,118,103,47,99,104,111,99,111,108,97,116,101,0,0,47,115,118,103,47,99,104,97,114,116,114,101,117,115,101,0,47,115,118,103,47,99,97,100,101,116,98,108,117,101,0,0,65,118,97,110,116,71,97,114,100,101,45,68,101,109,105,0,47,115,118,103,47,98,117,114,108,121,119,111,111,100,0,0,101,100,103,101,0,0,0,0,47,115,118,103,47,98,114,111,119,110,0,0,0,0,0,0,37,103,44,37,103,32,0,0,114,101,102,101,114,101,110,99,101,32,116,111,32,105,110,118,97,108,105,100,32,99,104,97,114,97,99,116,101,114,32,110,117,109,98,101,114,0,0,0,105,110,118,105,115,0,0,0,47,115,118,103,47,98,108,117,101,118,105,111,108,101,116,0,47,115,118,103,47,98,108,117,101,0,0,0,0,0,0,0,92,71,0,0,0,0,0,0,47,115,118,103,47,98,108,97,110,99,104,101,100,97,108,109,111,110,100,0,0,0,0,0,83,32,0,0,0,0,0,0,47,115,118,103,47,98,108,97,99,107,0,0,0,0,0,0,103,97,109,109,97,0,0,0,47,98,117,103,110,54,47,49,0,0,0,0,0,0,0,0,69,68,95,116,111,95,118,105,114,116,40,101,41,32,33,61,32,78,85,76,76,0,0,0,47,115,118,103,47,98,105,115,113,117,101,0,0,0,0,0,47,115,118,103,47,98,101,105,103,101,0,0,0,0,0,0,44,32,0,0,0,0,0,0,99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,116,114,105,115,0,0,0,0,0,47,115,118,103,47,97,122,117,114,101,0,0,0,0,0,0,60,72,84,77,76,62,0,0,104,101,97,100,95,108,112,0,47,115,118,103,47,97,113,117,97,109,97,114,105,110,101,0,110,101,119,46,103,118,0,0,99,111,117,108,100,110,39,116,32,111,112,101,110,32,101,112,115,102,32,102,105,108,101,32,37,115,10,0,0,0,0,0,47,115,118,103,47,97,113,117,97,0,0,0,0,0,0,0,47,115,118,103,47,97,110,116,105,113,117,101,119,104,105,116,101,0,0,0,0,0,0,0,32,112,111,105,110,116,115,61,34,0,0,0,0,0,0,0,37,115,32,0,0,0,0,0,115,97,109,101,104,101,97,100,0,0,0,0,0,0,0,0,99,97,100,101,116,98,108,117,101,0,0,0,0,0,0,0,47,115,118,103,47,97,108,105,99,101,98,108,117,101,0,0,47,115,112,101,99,116,114,97,108,57,47,57,0,0,0,0,47,115,112,101,99,116,114,97,108,57,47,56,0,0,0,0,47,115,112,101,99,116,114,97,108,57,47,55,0,0,0,0,102,114,97,115,108,0,0,0,47,98,117,103,110,53,47,53,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,57,47,54,0,0,0,0,47,115,112,101,99,116,114,97,108,57,47,53,0,0,0,0,47,115,112,101,99,116,114,97,108,57,47,52,0,0,0,0,47,115,112,101,99,116,114,97,108,57,47,51,0,0,0,0,47,115,112,101,99,116,114,97,108,57,47,50,0,0,0,0,47,115,112,101,99,116,114,97,108,57,47,49,0,0,0,0,60,112,111,108,121,108,105,110,101,0,0,0,0,0,0,0,109,109,0,0,0,0,0,0,115,101,116,108,105,110,101,119,105,100,116,104,0,0,0,0,47,115,112,101,99,116,114,97,108,56,47,56,0,0,0,0,98,108,97,99,107,0,0,0,32,32,32,32,32,32,32,32,47,69,110,99,111,100,105,110,103,32,69,110,99,111,100,105,110,103,86,101,99,116,111,114,32,100,101,102,0,0,0,0,47,115,112,101,99,116,114,97,108,56,47,55,0,0,0,0,99,111,108,111,114,32,37,115,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,56,47,54,0,0,0,0,47,115,112,101,99,116,114,97,108,56,47,53,0,0,0,0,102,114,97,99,51,52,0,0,47,98,117,103,110,53,47,52,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,56,47,52,0,0,0,0,47,115,112,101,99,116,114,97,108,56,47,51,0,0,0,0,47,115,112,101,99,116,114,97,108,56,47,50,0,0,0,0,47,115,112,101,99,116,114,97,108,56,47,49,0,0,0,0,47,115,112,101,99,116,114,97,108,55,47,55,0,0,0,0,47,115,112,101,99,116,114,97,108,55,47,54,0,0,0,0,32,45,45,62,10,0,0,0,32,115,101,116,108,105,110,101,119,105,100,116,104,10,0,0,47,115,112,101,99,116,114,97,108,55,47,53,0,0,0,0,47,115,112,101,99,116,114,97,108,55,47,52,0,0,0,0,47,115,112,101,99,116,114,97,108,55,47,51,0,0,0,0,47,115,112,101,99,116,114,97,108,55,47,50,0,0,0,0,102,114,97,99,49,52,0,0,104,97,108,102,0,0,0,0,47,98,117,103,110,53,47,51,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,55,47,49,0,0,0,0,47,115,112,101,99,116,114,97,108,54,47,54,0,0,0,0,47,115,112,101,99,116,114,97,108,54,47,53,0,0,0,0,47,115,112,101,99,116,114,97,108,54,47,52,0,0,0,0,78,68,95,114,97,110,107,40,118,41,32,61,61,32,114,0,47,115,112,101,99,116,114,97,108,54,47,51,0,0,0,0,47,115,112,101,99,116,114,97,108,54,47,50,0,0,0,0,60,33,45,45,32,0,0,0,32,93,32,32,37,100,32,102,97,108,115,101,32,37,115,10,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,54,47,49,0,0,0,0,47,115,112,101,99,116,114,97,108,53,47,53,0,0,0,0,47,115,112,101,99,116,114,97,108,53,47,52,0,0,0,0,47,115,112,101,99,116,114,97,108,53,47,51,0,0,0,0,102,114,97,99,49,50,0,0,47,98,117,103,110,53,47,50,0,0,0,0,0,0,0,0,114,101,99,116,97,110,103,108,101,32,40,37,100,44,37,100,41,32,40,37,100,44,37,100,41,32,37,115,32,37,115,10,0,0,0,0,0,0,0,0,84,104,105,115,32,109,97,121,32,99,97,117,115,101,32,117,110,101,120,112,101,99,116,101,100,32,98,101,104,97,118,105,111,114,32,111,114,32,99,114,97,115,104,32,116,104,101,32,112,114,111,103,114,97,109,46,10,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,53,47,50,0,0,0,0,47,115,112,101,99,116,114,97,108,53,47,49,0,0,0,0,47,115,112,101,99,116,114,97,108,52,47,52,0,0,0,0,47,115,112,101,99,116,114,97,108,52,47,51,0,0,0,0,47,115,112,101,99,116,114,97,108,52,47,50,0,0,0,0,47,115,112,101,99,116,114,97,108,52,47,49,0,0,0,0,121,101,108,108,111,119,103,114,101,101,110,0,0,0,0,0,32,93,32,32,37,100,32,116,114,117,101,32,37,115,10,0,47,115,112,101,99,116,114,97,108,51,47,51,0,0,0,0,101,32,33,61,32,78,85,76,76,0,0,0,0,0,0,0,47,97,99,99,101,110,116,54,47,49,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,51,47,50,0,0,0,0,47,115,112,101,99,116,114,97,108,51,47,49,0,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,57,0,0,0,102,111,114,97,108,108,0,0,47,98,117,103,110,53,47,49,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,56,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,55,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,54,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,53,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,52,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,51,0,0,0,121,101,108,108,111,119,0,0,38,108,116,59,0,0,0,0,32,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,50,0,0,0,99,105,114,99,108,101,0,0,47,115,112,101,99,116,114,97,108,49,49,47,49,49,0,0,47,115,112,101,99,116,114,97,108,49,49,47,49,48,0,0,101,110,100,32,112,111,114,116,58,32,40,37,46,53,103,44,32,37,46,53,103,41,44,32,116,97,110,103,101,110,116,32,97,110,103,108,101,58,32,37,46,53,103,44,32,37,115,10,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,49,49,47,49,0,0,0,102,110,111,102,0,0,0,0,47,98,117,103,110,52,47,52,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,57,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,56,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,55,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,54,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,53,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,52,0,0,0,119,104,105,116,101,115,109,111,107,101,0,0,0,0,0,0,78,111,32,111,114,32,105,109,112,114,111,112,101,114,32,105,109,97,103,101,32,102,105,108,101,61,34,37,115,34,10,0,91,32,0,0,0,0,0,0,106,112,103,58,118,114,109,108,0,0,0,0,0,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,51,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,50,0,0,0,47,115,112,101,99,116,114,97,108,49,48,47,49,48,0,0,47,115,112,101,99,116,114,97,108,49,48,47,49,0,0,0,101,120,105,115,116,0,0,0,47,98,117,103,110,52,47,51,0,0,0,0,0,0,0,0,47,115,101,116,51,57,47,57,0,0,0,0,0,0,0,0,47,115,101,116,51,57,47,56,0,0,0,0,0,0,0,0,47,115,101,116,51,57,47,55,0,0,0,0,0,0,0,0,47,115,101,116,51,57,47,54,0,0,0,0,0,0,0,0,47,115,101,116,51,57,47,53,0,0,0,0,0,0,0,0,73,0,0,0,0,0,0,0,47,115,101,116,51,57,47,52,0,0,0,0,0,0,0,0,119,104,105,116,101,0,0,0,101,112,115,58,112,115,0,0,47,115,101,116,51,57,47,51,0,0,0,0,0,0,0,0,47,115,101,116,51,57,47,50,0,0,0,0,0,0,0,0,103,118,114,101,110,100,101,114,95,99,111,114,101,95,102,105,103,46,99,0,0,0,0,0,47,115,101,116,51,57,47,49,0,0,0,0,0,0,0,0,71,0,0,0,0,0,0,0,47,115,101,116,51,56,47,56,0,0,0,0,0,0,0,0,101,117,114,111,0,0,0,0,47,98,117,103,110,52,47,50,0,0,0,0,0,0,0,0,103,114,97,121,0,0,0,0,47,115,101,116,51,56,47,55,0,0,0,0,0,0,0,0,47,115,101,116,51,56,47,54,0,0,0,0,0,0,0,0,47,115,101,116,51,56,47,53,0,0,0,0,0,0,0,0,47,115,101,116,51,56,47,52,0,0,0,0,0,0,0,0,110,111,110,45,116,101,114,109,105,110,97,116,101,100,32,72,84,77,76,32,115,116,114,105,110,103,32,115,116,97,114,116,105,110,103,32,108,105,110,101,32,37,100,44,32,102,105,108,101,32,37,115,10,0,0,0,47,115,101,116,51,56,47,51,0,0,0,0,0,0,0,0,103,118,114,101,110,100,101,114,95,99,111,114,101,95,116,107,46,99,0,0,0,0,0,0,47,115,101,116,51,56,47,50,0,0,0,0,0,0,0,0,119,104,101,97,116,0,0,0,112,115,50,58,112,115,0,0,47,115,101,116,51,56,47,49,0,0,0,0,0,0,0,0,47,115,101,116,51,55,47,55,0,0,0,0,0,0,0,0,47,115,101,116,51,55,47,54,0,0,0,0,0,0,0,0,47,115,101,116,51,55,47,53,0,0,0,0,0,0,0,0,101,117,109,108,0,0,0,0,47,98,117,103,110,52,47,49,0,0,0,0,0,0,0,0,47,115,101,116,51,55,47,52,0,0,0,0,0,0,0,0,47,115,101,116,51,55,47,51,0,0,0,0,0,0,0,0,47,115,101,116,51,55,47,50,0,0,0,0,0,0,0,0,47,115,101,116,51,55,47,49,0,0,0,0,0,0,0,0,105,116,97,108,105,99,0,0,47,115,101,116,51,54,47,54,0,0,0,0,0,0,0,0,47,115,101,116,51,54,47,53,0,0,0,0,0,0,0,0,110,111,100,101,0,0,0,0,118,105,111,108,101,116,0,0,97,115,121,110,99,104,114,111,110,111,117,115,32,101,110,116,105,116,121,0,0,0,0,0,112,115,58,112,115,0,0,0,47,115,101,116,51,54,47,52,0,0,0,0,0,0,0,0,47,115,101,116,51,54,47,51,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,115,101,116,51,54,47,50,0,0,0,0,0,0,0,0,115,101,116,108,105,110,101,119,105,100,116,104,40,37,46,51,102,41,0,0,0,0,0,0,116,107,58,116,107,0,0,0,47,115,101,116,51,54,47,49,0,0,0,0,0,0,0,0,101,116,104,0,0,0,0,0,119,101,105,103,104,116,0,0,47,98,117,103,110,51,47,51,0,0,0,0,0,0,0,0,47,115,101,116,51,53,47,53,0,0,0,0,0,0,0,0,47,115,101,116,51,53,47,52,0,0,0,0,0,0,0,0,44,10,0,0,0,0,0,0,99,97,110,110,111,116,32,109,97,108,108,111,99,32,116,114,105,115,0,0,0,0,0,0,47,115,101,116,51,53,47,51,0,0,0,0,0,0,0,0,108,112,0,0,0,0,0,0,47,115,101,116,51,53,47,50,0,0,0,0,0,0,0,0,85,84,70,45,56,32,105,110,112,117,116,32,117,115,101,115,32,110,111,110,45,76,97,116,105,110,49,32,99,104,97,114,97,99,116,101,114,115,32,119,104,105,99,104,32,99,97,110,110,111,116,32,98,101,32,104,97,110,100,108,101,100,32,98,121,32,116,104,105,115,32,80,111,115,116,83,99,114,105,112,116,32,100,114,105,118,101,114,10,0,0,0,0,0,0,0,103,114,97,112,104,118,105,122,0,0,0,0,0,0,0,0,47,115,101,116,51,53,47,49,0,0,0,0,0,0,0,0,47,115,101,116,51,52,47,52,0,0,0,0,0,0,0,0,116,117,114,113,117,111,105,115,101,0,0,0,0,0,0,0,112,115,0,0,0,0,0,0,47,115,101,116,51,52,47,51,0,0,0,0,0,0,0,0,98,117,114,108,121,119,111,111,100,0,0,0,0,0,0,0,47,115,101,116,51,52,47,50,0,0,0,0,0,0,0,0,47,115,101,116,51,52,47,49,0,0,0,0,0,0,0,0,47,115,101,116,51,51,47,51,0,0,0,0,0,0,0,0,101,116,97,0,0,0,0,0,47,98,117,103,110,51,47,50,0,0,0,0,0,0,0,0,47,115,101,116,51,51,47,50,0,0,0,0,0,0,0,0,47,115,101,116,51,51,47,49,0,0,0,0,0,0,0,0,47,115,101,116,51,49,50,47,57,0,0,0,0,0,0,0,47,115,101,116,51,49,50,47,56,0,0,0,0,0,0,0,47,115,101,116,51,49,50,47,55,0,0,0,0,0,0,0,47,115,101,116,51,49,50,47,54,0,0,0,0,0,0,0,116,111,109,97,116,111,0,0,99,109,0,0,0,0,0,0,37,37,69,110,100,83,101,116,117,112,0,0,0,0,0,0,47,115,101,116,51,49,50,47,53,0,0,0,0,0,0,0,84,105,109,101,115,45,82,111,109,97,110,0,0,0,0,0,32,32,32,32,32,32,32,32,125,32,102,111,114,97,108,108,0,0,0,0,0,0,0,0,47,115,101,116,51,49,50,47,52,0,0,0,0,0,0,0,98,111,116,104,0,0,0,0,47,115,101,116,51,49,50,47,51,0,0,0,0,0,0,0,47,115,101,116,51,49,50,47,50,0,0,0,0,0,0,0,101,113,117,105,118,0,0,0,47,98,117,103,110,51,47,49,0,0,0,0,0,0,0,0,47,115,101,116,51,49,50,47,49,50,0,0,0,0,0,0,47,115,101,116,51,49,50,47,49,49,0,0,0,0,0,0,47,115,101,116,51,49,50,47,49,48,0,0,0,0,0,0,41,10,45,45,62,10,0,0,47,115,101,116,51,49,50,47,49,0,0,0,0,0,0,0,47,115,101,116,51,49,49,47,57,0,0,0,0,0,0,0,47,115,101,116,51,49,49,47,56,0,0,0,0,0,0,0,116,104,105,115,116,108,101,0,125,32,105,102,0,0,0,0,47,115,101,116,51,49,49,47,55,0,0,0,0,0,0,0,47,115,101,116,51,49,49,47,54,0,0,0,0,0,0,0,47,115,101,116,51,49,49,47,53,0,0,0,0,0,0,0,47,115,101,116,51,49,49,47,52,0,0,0,0,0,0,0,101,112,115,105,108,111,110,0,101,0,0,0,0,0,0,0,47,98,114,98,103,57,47,57,0,0,0,0,0,0,0,0,47,115,101,116,51,49,49,47,51,0,0,0,0,0,0,0,47,115,101,116,51,49,49,47,50,0,0,0,0,0,0,0,47,115,101,116,51,49,49,47,49,49,0,0,0,0,0,0,32,40,0,0,0,0,0,0,47,115,101,116,51,49,49,47,49,48,0,0,0,0,0,0,47,115,101,116,51,49,49,47,49,0,0,0,0,0,0,0,109,105,110,99,114,111,115,115,58,32,112,97,115,115,32,37,100,32,105,116,101,114,32,37,100,32,116,114,121,105,110,103,32,37,100,32,99,117,114,95,99,114,111,115,115,32,37,100,32,98,101,115,116,95,99,114,111,115,115,32,37,100,10,0,47,115,101,116,51,49,48,47,57,0,0,0,0,0,0,0,116,101,97,108,0,0,0,0,32,32,32,32,117,115,101,114,100,105,99,116,32,40,62,62,41,32,99,118,110,32,40,91,41,32,99,118,110,32,108,111,97,100,32,112,117,116,0,0,47,115,101,116,51,49,48,47,56,0,0,0,0,0,0,0,47,115,101,116,51,49,48,47,55,0,0,0,0,0,0,0,47,115,101,116,51,49,48,47,54,0,0,0,0,0,0,0,47,115,101,116,51,49,48,47,53,0,0,0,0,0,0,0,101,110,115,112,0,0,0,0,47,98,114,98,103,57,47,56,0,0,0,0,0,0,0,0,47,115,101,116,51,49,48,47,52,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,84,104,101,32,117,115,101,32,111,102,32,34,115,117,98,103,114,97,112,104,32,37,115,34,44,32,108,105,110,101,32,37,100,44,32,119,105,116,104,111,117,116,32,97,32,98,111,100,121,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,10,0,0,0,0,0,0,0,47,115,101,116,51,49,48,47,51,0,0,0,0,0,0,0,47,115,101,116,51,49,48,47,50,0,0,0,0,0,0,0,32,118,101,114,115,105,111,110,32,0,0,0,0,0,0,0,47,115,101,116,51,49,48,47,49,48,0,0,0,0,0,0,47,115,101,116,51,49,48,47,49,0,0,0,0,0,0,0,47,115,101,116,50,56,47,56,0,0,0,0,0,0,0,0,116,97,110,0,0,0,0,0,32,32,32,32,117,115,101,114,100,105,99,116,32,40,60,60,41,32,99,118,110,32,40,91,41,32,99,118,110,32,108,111,97,100,32,112,117,116,0,0,47,115,101,116,50,56,47,55,0,0,0,0,0,0,0,0,76,101,102,116,0,0,0,0,47,115,101,116,50,56,47,54,0,0,0,0,0,0,0,0,47,97,99,99,101,110,116,53,47,53,0,0,0,0,0,0,47,115,101,116,50,56,47,53,0,0,0,0,0,0,0,0,47,115,101,116,50,56,47,52,0,0,0,0,0,0,0,0,101,109,115,112,0,0,0,0,47,98,114,98,103,57,47,55,0,0,0,0,0,0,0,0,47,115,101,116,50,56,47,51,0,0,0,0,0,0,0,0,47,115,101,116,50,56,47,50,0,0,0,0,0,0,0,0,47,115,101,116,50,56,47,49,0,0,0,0,0,0,0,0,10,60,33,45,45,32,71,101,110,101,114,97,116,101,100,32,98,121,32,0,0,0,0,0,47,115,101,116,50,55,47,55,0,0,0,0,0,0,0,0,47,115,101,116,50,55,47,54,0,0,0,0,0,0,0,0,47,115,101,116,50,55,47,53,0,0,0,0,0,0,0,0,115,116,101,101,108,98,108,117,101,0,0,0,0,0,0,0,50,32,108,116,32,123,0,0,47,115,101,116,50,55,47,52,0,0,0,0,0,0,0,0,111,118,97,108,0,0,0,0,47,115,101,116,50,55,47,51,0,0,0,0,0,0,0,0,47,115,101,116,50,55,47,50,0,0,0,0,0,0,0,0,110,111,116,32,99,111,110,115,116,114,97,105,110,101,100,0,47,115,101,116,50,55,47,49,0,0,0,0,0,0,0,0,101,109,112,116,121,0,0,0,47,98,114,98,103,57,47,54,0,0,0,0,0,0,0,0,47,115,101,116,50,54,47,54,0,0,0,0,0,0,0,0,47,115,101,116,50,54,47,53,0,0,0,0,0,0,0,0,47,115,101,116,50,54,47,52,0,0,0,0,0,0,0,0,60,72,84,77,76,62,10,0,47,115,101,116,50,54,47,51,0,0,0,0,0,0,0,0,47,115,101,116,50,54,47,50,0,0,0,0,0,0,0,0,47,115,101,116,50,54,47,49,0,0,0,0,0,0,0,0,115,112,114,105,110,103,103,114,101,101,110,0,0,0,0,0,102,105,120,101,100,32,99,101,108,108,32,115,105,122,101,32,119,105,116,104,32,117,110,115,112,101,99,105,102,105,101,100,32,119,105,100,116,104,32,111,114,32,104,101,105,103,104,116,10,0,0,0,0,0,0,0,102,105,103,58,102,105,103,0,106,112,101,58,118,114,109,108,0,0,0,0,0,0,0,0,47,115,101,116,50,53,47,53,0,0,0,0,0,0,0,0,47,115,101,116,50,53,47,52,0,0,0,0,0,0,0,0,47,108,97,110,103,117,97,103,101,108,101,118,101,108,32,119,104,101,114,101,32,123,112,111,112,32,108,97,110,103,117,97,103,101,108,101,118,101,108,125,123,49,125,32,105,102,101,108,115,101,0,0,0,0,0,0,47,115,101,116,50,53,47,51,0,0,0,0,0,0,0,0,47,115,101,116,50,53,47,50,0,0,0,0,0,0,0,0,101,103,114,97,118,101,0,0,47,98,114,98,103,57,47,53,0,0,0,0,0,0,0,0,47,115,101,116,50,53,47,49,0,0,0,0,0,0,0,0,47,115,101,116,50,52,47,52,0,0,0,0,0,0,0,0,47,115,101,116,50,52,47,51,0,0,0,0,0,0,0,0,101,99,105,114,99,0,0,0,32,99,111,111,114,100,111,114,105,103,105,110,61,34,48,44,48,34,32,99,111,111,114,100,115,105,122,101,61,34,37,100,44,37,100,34,32,62,0,0,47,115,101,116,50,52,47,50,0,0,0,0,0,0,0,0,47,115,101,116,50,52,47,49,0,0,0,0,0,0,0,0,47,115,101,116,50,51,47,51,0,0,0,0,0,0,0,0,85,0,0,0,0,0,0,0,115,110,111,119,0,0,0,0,37,32,109,97,107,101,32,39,60,60,39,32,97,110,100,32,39,62,62,39,32,115,97,102,101,32,111,110,32,80,83,32,76,101,118,101,108,32,49,32,100,101,118,105,99,101,115,0,47,115,101,116,50,51,47,50,0,0,0,0,0,0,0,0,47,115,101,116,50,51,47,49,0,0,0,0,0,0,0,0,47,115,101,116,49,57,47,57,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,47,115,101,116,49,57,47,56,0,0,0,0,0,0,0,0,108,0,0,0,0,0,0,0,47,98,114,98,103,57,47,52,0,0,0,0,0,0,0,0,47,115,101,116,49,57,47,55,0,0,0,0,0,0,0,0,102,117,99,104,115,105,97,0,47,115,101,116,49,57,47,54,0,0,0,0,0,0,0,0,47,115,101,116,49,57,47,53,0,0,0,0,0,0,0,0,32,119,105,100,116,104,58,32,37,100,112,116,59,32,104,101,105,103,104,116,58,32,37,100,112,116,34,0,0,0,0,0,47,115,101,116,49,57,47,52,0,0,0,0,0,0,0,0,47,115,101,116,49,57,47,51,0,0,0,0,0,0,0,0,103,114,97,112,104,32,108,97,98,101,108,0,0,0,0,0,37,115,58,37,100,58,32,97,109,98,105,103,117,111,117,115,32,34,37,115,34,32,115,112,108,105,116,115,32,105,110,116,111,32,116,119,111,32,110,97,109,101,115,58,32,34,37,115,34,32,97,110,100,32,34,37,115,34,10,0,0,0,0,0,47,115,101,116,49,57,47,50,0,0,0,0,0,0,0,0,115,108,97,116,101,103,114,101,121,0,0,0,0,0,0,0,47,112,100,102,109,97,114,107,32,119,104,101,114,101,32,123,112,111,112,125,32,123,117,115,101,114,100,105,99,116,32,47,112,100,102,109,97,114,107,32,47,99,108,101,97,114,116,111,109,97,114,107,32,108,111,97,100,32,112,117,116,125,32,105,102,101,108,115,101,0,0,0,47,115,101,116,49,57,47,49,0,0,0,0,0,0,0,0,102,111,110,116,110,97,109,101,58,32,117,110,97,98,108,101,32,116,111,32,114,101,115,111,108,118,101,32,34,37,115,34,10,0,0,0,0,0,0,0,115,97,109,101,116,97,105,108,0,0,0,0,0,0,0,0,47,115,101,116,49,56,47,56,0,0,0,0,0,0,0,0,47,115,101,116,49,56,47,55,0,0,0,0,0,0,0,0,47,115,101,116,49,56,47,54,0,0,0,0,0,0,0,0,101,97,99,117,116,101,0,0,47,98,114,98,103,57,47,51,0,0,0,0,0,0,0,0,47,115,101,116,49,56,47,53,0,0,0,0,0,0,0,0,47,115,101,116,49,56,47,52,0,0,0,0,0,0,0,0,47,115,101,116,49,56,47,51,0,0,0,0,0,0,0,0,32,60,118,58,103,114,111,117,112,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,32,0,0,0,0,47,115,101,116,49,56,47,50,0,0,0,0,0,0,0,0,111,98,108,105,113,117,101,0,47,115,101,116,49,56,47,49,0,0,0,0,0,0,0,0,47,115,101,116,49,55,47,55,0,0,0,0,0,0,0,0,115,108,97,116,101,103,114,97,121,0,0,0,0,0,0,0,114,101,99,117,114,115,105,118,101,32,101,110,116,105,116,121,32,114,101,102,101,114,101,110,99,101,0,0,0,0,0,0,37,32,109,97,107,101,32,115,117,114,101,32,112,100,102,109,97,114,107,32,105,115,32,104,97,114,109,108,101,115,115,32,102,111,114,32,80,83,45,105,110,116,101,114,112,114,101,116,101,114,115,32,111,116,104,101,114,32,116,104,97,110,32,68,105,115,116,105,108,108,101,114,0,0,0,0,0,0,0,0,47,115,101,116,49,55,47,54,0,0,0,0,0,0,0,0,103,114,97,112,104,0,0,0,47,115,101,116,49,55,47,53,0,0,0,0,0,0,0,0,38,35,51,57,59,0,0,0,47,115,101,116,49,55,47,52,0,0,0,0,0,0,0,0,35,37,48,50,120,37,48,50,120,37,48,50,120,37,48,50,120,0,0,0,0,0,0,0,32,91,0,0,0,0,0,0,47,115,101,116,49,55,47,51,0,0,0,0,0,0,0,0,100,105,118,105,100,101,0,0,47,98,114,98,103,57,47,50,0,0,0,0,0,0,0,0,108,104,101,97,100,0,0,0,47,115,101,116,49,55,47,50,0,0,0,0,0,0,0,0,47,115,101,116,49,55,47,49,0,0,0,0,0,0,0,0,97,103,117,115,101,114,103,114,97,112,104,0,0,0,0,0,114,111,117,116,101,46,99,0,47,115,101,116,49,54,47,54,0,0,0,0,0,0,0,0,120,108,112,0,0,0,0,0,60,120,109,108,58,110,97,109,101,115,112,97,99,101,32,110,115,61,34,117,114,110,58,115,99,104,101,109,97,115,45,109,105,99,114,111,115,111,102,116,45,99,111,109,58,118,109,108,34,32,112,114,101,102,105,120,61,34,118,34,32,47,62,10,0,0,0,0,0,0,0,0,47,115,101,116,49,54,47,53,0,0,0,0,0,0,0,0,70,0,0,0,0,0,0,0,125,32,98,105,110,100,32,100,101,102,10,0,0,0,0,0,47,115,101,116,49,54,47,52,0,0,0,0,0,0,0,0,47,115,101,116,49,54,47,51,0,0,0,0,0,0,0,0,115,108,97,116,101,98,108,117,101,0,0,0,0,0,0,0,37,32,47,97,114,114,111,119,119,105,100,116,104,32,53,32,100,101,102,0,0,0,0,0,47,115,101,116,49,54,47,50,0,0,0,0,0,0,0,0,98,114,111,119,110,0,0,0,76,97,121,111,117,116,32,116,121,112,101,58,32,34,37,115,34,32,110,111,116,32,114,101,99,111,103,110,105,122,101,100,46,32,85,115,101,32,111,110,101,32,111,102,58,37,115,10,0,0,0,0,0,0,0,0,47,115,101,116,49,54,47,49,0,0,0,0,0,0,0,0,47,115,101,116,49,53,47,53,0,0,0,0,0,0,0,0,47,115,101,116,49,53,47,52,0,0,0,0,0,0,0,0,100,105,97,109,115,0,0,0,47,98,114,98,103,57,47,49,0,0,0,0,0,0,0,0,99,108,117,115,116,101,114,32,110,97,109,101,100,32,37,115,32,110,111,116,32,102,111,117,110,100,10,0,0,0,0,0,47,115,101,116,49,53,47,51,0,0,0,0,0,0,0,0,47,115,101,116,49,53,47,50,0,0,0,0,0,0,0,0,47,115,101,116,49,53,47,49,0,0,0,0,0,0,0,0,60,47,83,84,89,76,69,62,10,0,0,0,0,0,0,0,47,115,101,116,49,52,47,52,0,0,0,0,0,0,0,0,47,115,101,116,49,52,47,51,0,0,0,0,0,0,0,0,47,115,101,116,49,52,47,50,0,0,0,0,0,0,0,0,115,107,121,98,108,117,101,0,34,0,0,0,0,0,0,0,37,32,47,97,114,114,111,119,108,101,110,103,116,104,32,49,48,32,100,101,102,0,0,0,110,115,108,105,109,105,116,49,0,0,0,0,0,0,0,0,47,115,101,116,49,52,47,49,0,0,0,0,0,0,0,0,101,108,108,105,112,115,101,0,32,32,32,32,32,32,32,32,123,32,49,32,105,110,100,101,120,32,47,70,73,68,32,110,101,32,123,32,100,101,102,32,125,123,32,112,111,112,32,112,111,112,32,125,32,105,102,101,108,115,101,0,0,0,0,0,116,114,105,97,110,103,117,108,97,116,105,111,110,32,102,97,105,108,101,100,0,0,0,0,47,115,101,116,49,51,47,51,0,0,0,0,0,0,0,0,104,101,105,103,104,116,0,0,47,115,101,116,49,51,47,50,0,0,0,0,0,0,0,0,47,115,101,116,49,51,47,49,0,0,0,0,0,0,0,0,100,101,108,116,97,0,0,0,47,98,114,98,103,56,47,56,0,0,0,0,0,0,0,0,47,114,101,100,115,57,47,57,0,0,0,0,0,0,0,0,47,114,101,100,115,57,47,56,0,0,0,0,0,0,0,0,47,114,101,100,115,57,47,55,0,0,0,0,0,0,0,0,118,92,58,42,32,123,32,98,101,104,97,118,105,111,114,58,32,117,114,108,40,35,100,101,102,97,117,108,116,35,86,77,76,41,59,100,105,115,112,108,97,121,58,105,110,108,105,110,101,45,98,108,111,99,107,125,10,0,0,0,0,0,0,0,47,114,101,100,115,57,47,54,0,0,0,0,0,0,0,0,47,114,101,100,115,57,47,53,0,0,0,0,0,0,0,0,47,114,101,100,115,57,47,52,0,0,0,0,0,0,0,0,115,105,108,118,101,114,0,0,49,32,115,101,116,109,105,116,101,114,108,105,109,105,116,0,47,114,101,100,115,57,47,51,0,0,0,0,0,0,0,0,105,110,32,108,97,98,101,108,32,111,102,32,110,111,100,101,32,37,115,10,0,0,0,0,69,68,95,108,97,98,101,108,40,102,101,41,0,0,0,0,73,32,0,0,0,0,0,0,100,111,116,0,0,0,0,0,47,114,101,100,115,57,47,50,0,0,0,0,0,0,0,0,47,114,101,100,115,57,47,49,0,0,0,0,0,0,0,0,47,114,101,100,115,56,47,56,0,0,0,0,0,0,0,0,100,101,103,0,0,0,0,0,99,114,111,119,0,0,0,0,47,98,114,98,103,56,47,55,0,0,0,0,0,0,0,0,47,114,101,100,115,56,47,55,0,0,0,0,0,0,0,0,47,114,101,100,115,56,47,54,0,0,0,0,0,0,0,0,47,114,101,100,115,56,47,53,0,0,0,0,0,0,0,0,60,83,84,89,76,69,62,10,0,0,0,0,0,0,0,0,47,114,101,100,115,56,47,52,0,0,0,0,0,0,0,0,47,114,101,100,115,56,47,51,0,0,0,0,0,0,0,0,47,114,101,100,115,56,47,50,0,0,0,0,0,0,0,0,115,105,101,110,110,97,0,0,109,101,114,103,101,50,58,32,103,114,97,112,104,32,37,115,44,32,114,97,110,107,32,37,100,32,104,97,115,32,111,110,108,121,32,37,100,32,60,32,37,100,32,110,111,100,101,115,10,0,0,0,0,0,0,0,49,52,32,100,101,102,97,117,108,116,45,102,111,110,116,45,102,97,109,105,108,121,32,115,101,116,95,102,111,110,116,0,47,114,101,100,115,56,47,49,0,0,0,0,0,0,0,0,99,108,97,115,115,50,46,99,0,0,0,0,0,0,0,0,47,114,101,100,115,55,47,55,0,0,0,0,0,0,0,0,47,114,101,100,115,55,47,54,0,0,0,0,0,0,0,0,47,114,101,100,115,55,47,53,0,0,0,0,0,0,0,0,100,97,114,114,0,0,0,0,47,98,114,98,103,56,47,54,0,0,0,0,0,0,0,0,47,114,101,100,115,55,47,52,0,0,0,0,0,0,0,0,47,114,101,100,115,55,47,51,0,0,0,0,0,0,0,0,103,118,114,101,110,100,101,114,95,99,111,114,101,95,109,97,112,46,99,0,0,0,0,0,71,115,116,97,99,107,32,111,118,101,114,102,108,111,119,32,105,110,32,103,114,97,112,104,32,112,97,114,115,101,114,10,0,0,0,0,0,0,0,0,47,114,101,100,115,55,47,50,0,0,0,0,0,0,0,0,32,119,105,100,116,104,58,32,37,100,112,116,59,32,104,101,105,103,104,116,58,32,37,100,112,116,34,62,10,0,0,0,47,114,101,100,115,55,47,49,0,0,0,0,0,0,0,0,47,114,101,100,115,54,47,54,0,0,0,0,0,0,0,0,47,114,101,100,115,54,47,53,0,0,0,0,0,0,0,0,115,101,97,115,104,101,108,108,0,0,0,0,0,0,0,0,37,37,66,101,103,105,110,83,101,116,117,112,0,0,0,0,47,114,101,100,115,54,47,52,0,0,0,0,0,0,0,0,85,110,115,117,112,112,111,114,116,101,100,32,99,104,97,114,115,101,116,32,34,37,115,34,32,45,32,97,115,115,117,109,105,110,103,32,117,116,102,45,56,10,0,0,0,0,0,0,47,114,101,100,115,54,47,51,0,0,0,0,0,0,0,0,47,97,99,99,101,110,116,53,47,52,0,0,0,0,0,0,47,114,101,100,115,54,47,50,0,0,0,0,0,0,0,0,47,114,101,100,115,54,47,49,0,0,0,0,0,0,0,0,100,97,103,103,101,114,0,0,47,98,114,98,103,56,47,53,0,0,0,0,0,0,0,0,47,114,101,100,115,53,47,53,0,0,0,0,0,0,0,0])
+.concat([47,114,101,100,115,53,47,52,0,0,0,0,0,0,0,0,47,114,101,100,115,53,47,51,0,0,0,0,0,0,0,0,60,68,73,86,32,105,100,61,39,95,86,77,76,49,95,39,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,32,100,105,115,112,108,97,121,58,105,110,108,105,110,101,59,32,118,105,115,105,98,105,108,105,116,121,58,104,105,100,100,101,110,0,0,0,0,47,114,101,100,115,53,47,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,114,101,100,115,53,47,49,0,0,0,0,0,0,0,0,47,114,101,100,115,52,47,52,0,0,0,0,0,0,0,0,115,101,97,103,114,101,101,110,0,0,0,0,0,0,0,0,99,32,0,0,0,0,0,0,47,114,101,100,115,52,47,51,0,0,0,0,0,0,0,0,117,116,102,56,0,0,0,0,101,108,108,105,112,115,101,0,47,114,101,100,115,52,47,50,0,0,0,0,0,0,0,0,37,37,69,110,100,80,114,111,108,111,103,0,0,0,0,0,47,114,101,100,115,52,47,49,0,0,0,0,0,0,0,0,99,111,110,115,116,114,97,105,110,101,100,0,0,0,0,0,47,114,101,100,115,51,47,51,0,0,0,0,0,0,0,0,100,65,114,114,0,0,0,0,47,98,114,98,103,56,47,52,0,0,0,0,0,0,0,0,47,114,101,100,115,51,47,50,0,0,0,0,0,0,0,0,47,114,101,100,115,51,47,49,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,57,47,57,0,0,0,0,0,0,32,0,0,0,0,0,0,0,60,66,79,68,89,32,111,110,108,111,97,100,61,39,98,114,111,119,115,101,114,99,104,101,99,107,40,41,59,39,62,10,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,57,47,56,0,0,0,0,0,0,47,114,100,121,108,103,110,57,47,55,0,0,0,0,0,0,47,114,100,121,108,103,110,57,47,54,0,0,0,0,0,0,115,97,110,100,121,98,114,111,119,110,0,0,0,0,0,0,37,37,69,110,100,82,101,115,111,117,114,99,101,0,0,0,99,101,108,108,32,115,105,122,101,32,116,111,111,32,115,109,97,108,108,32,102,111,114,32,99,111,110,116,101,110,116,10,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,57,47,53,0,0,0,0,0,0,106,112,101,103,58,118,114,109,108,0,0,0,0,0,0,0,98,105,103,53,0,0,0,0,47,114,100,121,108,103,110,57,47,52,0,0,0,0,0,0,47,114,100,121,108,103,110,57,47,51,0,0,0,0,0,0,47,114,100,121,108,103,110,57,47,50,0,0,0,0,0,0,99,117,114,114,101,110,0,0,47,98,114,98,103,56,47,51,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,57,47,49,0,0,0,0,0,0,47,114,100,121,108,103,110,56,47,56,0,0,0,0,0,0,47,114,100,121,108,103,110,56,47,55,0,0,0,0,0,0,60,47,72,69,65,68,62,0,47,114,100,121,108,103,110,56,47,54,0,0,0,0,0,0,47,114,100,121,108,103,110,56,47,53,0,0,0,0,0,0,47,114,100,121,108,103,110,56,47,52,0,0,0,0,0,0,66,0,0,0,0,0,0,0,115,97,108,109,111,110,0,0,47,99,117,114,108,97,121,101,114,32,48,32,100,101,102,0,47,114,100,121,108,103,110,56,47,51,0,0,0,0,0,0,98,105,103,45,53,0,0,0,47,114,100,121,108,103,110,56,47,50,0,0,0,0,0,0,47,114,100,121,108,103,110,56,47,49,0,0,0,0,0,0,92,78,0,0,0,0,0,0,47,114,100,121,108,103,110,55,47,55,0,0,0,0,0,0,99,117,112,0,0,0,0,0,115,104,97,112,101,102,105,108,101,32,110,111,116,32,115,101,116,32,111,114,32,110,111,116,32,102,111,117,110,100,32,102,111,114,32,101,112,115,102,32,110,111,100,101,32,37,115,10,0,0,0,0,0,0,0,0,32,37,100,32,37,100,0,0,47,98,114,98,103,56,47,50,0,0,0,0,0,0,0,0,75,80,95,83,117,98,116,114,97,99,116,0,0,0,0,0,47,114,100,121,108,103,110,55,47,54,0,0,0,0,0,0,98,108,117,101,0,0,0,0,47,114,100,121,108,103,110,55,47,53,0,0,0,0,0,0,47,114,100,121,108,103,110,55,47,52,0,0,0,0,0,0,32,32,32,60,47,83,67,82,73,80,84,62,10,0,0,0,47,114,100,121,108,103,110,55,47,51,0,0,0,0,0,0,47,114,100,121,108,103,110,55,47,50,0,0,0,0,0,0,103,114,97,112,104,0,0,0,47,114,100,121,108,103,110,55,47,49,0,0,0,0,0,0,115,97,100,100,108,101,98,114,111,119,110,0,0,0,0,0,32,60,60,60,32,0,0,0,9,123,105,110,118,105,115,125,32,105,102,0,0,0,0,0,47,114,100,121,108,103,110,54,47,54,0,0,0,0,0,0,99,111,109,112,111,117,110,100,0,0,0,0,0,0,0,0,59,10,0,0,0,0,0,0,73,83,79,45,73,82,45,49,48,48,0,0,0,0,0,0,47,114,100,121,108,103,110,54,47,53,0,0,0,0,0,0,115,97,109,101,104,101,97,100,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,54,47,52,0,0,0,0,0,0,47,114,100,121,108,103,110,54,47,51,0,0,0,0,0,0,99,114,97,114,114,0,0,0,47,98,114,98,103,56,47,49,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,54,47,50,0,0,0,0,0,0,47,114,100,121,108,103,110,54,47,49,0,0,0,0,0,0,47,114,100,121,108,103,110,53,47,53,0,0,0,0,0,0,47,114,100,121,108,103,110,53,47,52,0,0,0,0,0,0,32,32,32,125,10,0,0,0,65,118,97,110,116,71,97,114,100,101,45,66,111,111,107,79,98,108,105,113,117,101,0,0,47,114,100,121,108,103,110,53,47,51,0,0,0,0,0,0,47,114,100,121,108,103,110,53,47,50,0,0,0,0,0,0,114,111,121,97,108,98,108,117,101,0,0,0,0,0,0,0,117,110,100,101,102,105,110,101,100,32,101,110,116,105,116,121,0,0,0,0,0,0,0,0,9,111,114,0,0,0,0,0,47,114,100,121,108,103,110,53,47,49,0,0,0,0,0,0,73,83,79,56,56,53,57,45,49,0,0,0,0,0,0,0,47,114,100,121,108,103,110,52,47,52,0,0,0,0,0,0,105,100,0,0,0,0,0,0,38,113,117,111,116,59,0,0,47,114,100,121,108,103,110,52,47,51,0,0,0,0,0,0,37,100,32,37,100,32,0,0,47,114,100,121,108,103,110,52,47,50,0,0,0,0,0,0,99,111,112,121,0,0,0,0,69,68,95,116,111,95,118,105,114,116,40,101,41,32,61,61,32,78,85,76,76,0,0,0,47,98,114,98,103,55,47,55,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,52,47,49,0,0,0,0,0,0,47,114,100,121,108,103,110,51,47,51,0,0,0,0,0,0,123,10,0,0,0,0,0,0,99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,112,110,108,112,115,0,0,0,0,47,114,100,121,108,103,110,51,47,50,0,0,0,0,0,0,104,101,105,103,104,116,0,0,47,114,100,121,108,103,110,51,47,49,0,0,0,0,0,0,32,32,32,32,32,125,10,0,37,37,69,110,100,68,111,99,117,109,101,110,116,10,0,0,47,114,100,121,108,103,110,49,49,47,57,0,0,0,0,0,47,114,100,121,108,103,110,49,49,47,56,0,0,0,0,0,114,111,115,121,98,114,111,119,110,0,0,0,0,0,0,0,9,99,117,114,108,97,121,101,114,32,109,121,117,112,112,101,114,32,103,116,0,0,0,0,47,114,100,121,108,103,110,49,49,47,55,0,0,0,0,0,98,108,117,101,118,105,111,108,101,116,0,0,0,0,0,0,73,83,79,95,56,56,53,57,45,49,0,0,0,0,0,0,47,114,100,121,108,103,110,49,49,47,54,0,0,0,0,0,47,114,100,121,108,103,110,49,49,47,53,0,0,0,0,0,47,114,100,121,108,103,110,49,49,47,52,0,0,0,0,0,99,111,110,103,0,0,0,0,47,98,114,98,103,55,47,54,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,49,49,47,51,0,0,0,0,0,40,37,46,53,103,44,37,46,53,103,41,0,0,0,0,0,47,114,100,121,108,103,110,49,49,47,50,0,0,0,0,0,47,114,100,121,108,103,110,49,49,47,49,49,0,0,0,0,47,114,100,121,108,103,110,49,49,47,49,48,0,0,0,0,32,32,32,32,32,125,101,108,115,101,123,10,0,0,0,0,47,114,100,121,108,103,110,49,49,47,49,0,0,0,0,0,115,118,103,58,115,118,103,0,114,97,110,107,0,0,0,0,47,114,100,121,108,103,110,49,48,47,57,0,0,0,0,0,114,101,100,0,0,0,0,0,112,116,0,0,0,0,0,0,9,99,117,114,108,97,121,101,114,32,109,121,108,111,119,101,114,32,108,116,0,0,0,0,47,114,100,121,108,103,110,49,48,47,56,0,0,0,0,0,99,111,110,99,46,99,0,0,108,49,0,0,0,0,0,0,103,118,117,115,101,114,115,104,97,112,101,46,99,0,0,0,32,32,32,32,32,32,32,32,100,117,112,32,100,117,112,32,102,105,110,100,102,111,110,116,32,100,117,112,32,108,101,110,103,116,104,32,100,105,99,116,32,98,101,103,105,110,0,0,99,108,117,98,115,0,0,0,47,114,100,121,108,103,110,49,48,47,55,0,0,0,0,0,119,105,100,116,104,0,0,0,47,114,100,121,108,103,110,49,48,47,54,0,0,0,0,0,47,114,100,121,108,103,110,49,48,47,53,0,0,0,0,0,67,111,117,108,100,32,110,111,116,32,112,97,114,115,101,32,34,95,100,114,97,119,95,34,32,97,116,116,114,105,98,117,116,101,32,105,110,32,103,114,97,112,104,32,37,115,10,0,47,98,114,98,103,55,47,53,0,0,0,0,0,0,0,0,47,114,100,121,108,103,110,49,48,47,52,0,0,0,0,0,47,114,100,121,108,103,110,49,48,47,51,0,0,0,0,0,47,114,100,121,108,103,110,49,48,47,50,0,0,0,0,0,47,114,100,121,108,103,110,49,48,47,49,48,0,0,0,0,32,32,32,32,32,32,32,32,32,32,32,105,116,101,109,46,115,116,121,108,101,46,118,105,115,105,98,105,108,105,116,121,61,39,104,105,100,100,101,110,39,59,10,0,0,0,0,0,47,114,100,121,108,103,110,49,48,47,49,0,0,0,0,0,47,114,100,121,108,98,117,57,47,57,0,0,0,0,0,0,112,117,114,112,108,101,0,0,9,47,109,121,108,111,119,101,114,32,101,120,99,104,32,100,101,102,0,0,0,0,0,0,47,114,100,121,108,98,117,57,47,56,0,0,0,0,0,0,108,97,116,105,110,49,0,0,67,111,117,108,100,32,110,111,116,32,111,112,101,110,32,34,37,115,34,32,102,111,114,32,119,114,105,116,105,110,103,32,58,32,37,115,10,0,0,0,47,114,100,121,108,98,117,57,47,55,0,0,0,0,0,0,47,114,100,121,108,98,117,57,47,54,0,0,0,0,0,0,47,114,100,121,108,98,117,57,47,53,0,0,0,0,0,0,99,105,114,99,0,0,0,0,114,0,0,0,0,0,0,0,47,98,114,98,103,55,47,52,0,0,0,0,0,0,0,0,47,114,100,121,108,98,117,57,47,52,0,0,0,0,0,0,47,114,100,121,108,98,117,57,47,51,0,0,0,0,0,0,47,114,100,121,108,98,117,57,47,50,0,0,0,0,0,0,47,114,100,121,108,98,117,57,47,49,0,0,0,0,0,0,32,32,32,32,32,32,32,32,32,105,116,101,109,32,61,32,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,86,77,76,110,111,91,120,93,41,59,10,0,0,0,0,0,47,114,100,121,108,98,117,56,47,56,0,0,0,0,0,0,47,114,100,121,108,98,117,56,47,55,0,0,0,0,0,0,112,111,119,100,101,114,98,108,117,101,0,0,0,0,0,0,9,47,109,121,117,112,112,101,114,32,101,120,99,104,32,100,101,102,0,0,0,0,0,0,47,114,100,121,108,98,117,56,47,54,0,0,0,0,0,0,108,97,116,105,110,45,49,0,109,105,110,99,114,111,115,115,32,37,115,58,32,37,100,32,99,114,111,115,115,105,110,103,115,44,32,37,46,50,102,32,115,101,99,115,46,10,0,0,47,114,100,121,108,98,117,56,47,53,0,0,0,0,0,0,47,114,100,121,108,98,117,56,47,52,0,0,0,0,0,0,47,114,100,121,108,98,117,56,47,51,0,0,0,0,0,0,99,104,105,0,0,0,0,0,47,98,114,98,103,55,47,51,0,0,0,0,0,0,0,0,47,114,100,121,108,98,117,56,47,50,0,0,0,0,0,0,47,114,100,121,108,98,117,56,47,49,0,0,0,0,0,0,47,114,100,121,108,98,117,55,47,55,0,0,0,0,0,0,10,0,0,0,0,0,0,0,47,114,100,121,108,98,117,55,47,54,0,0,0,0,0,0,32,32,32,32,32,32,32,102,111,114,32,40,120,32,105,110,32,86,77,76,110,111,41,123,10,0,0,0,0,0,0,0,47,114,100,121,108,98,117,55,47,53,0,0,0,0,0,0,47,114,100,121,108,98,117,55,47,52,0,0,0,0,0,0,112,108,117,109,0,0,0,0,47,111,110,108,97,121,101,114,115,32,123,0,0,0,0,0,47,114,100,121,108,98,117,55,47,51,0,0,0,0,0,0,117,116,102,45,56,0,0,0,47,114,100,121,108,98,117,55,47,50,0,0,0,0,0,0,47,97,99,99,101,110,116,53,47,51,0,0,0,0,0,0,47,114,100,121,108,98,117,55,47,49,0,0,0,0,0,0,47,114,100,121,108,98,117,54,47,54,0,0,0,0,0,0,99,101,110,116,0,0,0,0,47,98,114,98,103,55,47,50,0,0,0,0,0,0,0,0,47,114,100,121,108,98,117,54,47,53,0,0,0,0,0,0,47,114,100,121,108,98,117,54,47,52,0,0,0,0,0,0,47,114,100,121,108,98,117,54,47,51,0,0,0,0,0,0,47,114,100,121,108,98,117,54,47,50,0,0,0,0,0,0,32,32,32,32,32,32,32,125,10,0,0,0,0,0,0,0,47,114,100,121,108,98,117,54,47,49,0,0,0,0,0,0,47,114,100,121,108,98,117,53,47,53,0,0,0,0,0,0,112,105,110,107,0,0,0,0,47,111,110,108,97,121,101,114,32,123,32,99,117,114,108,97,121,101,114,32,110,101,32,123,105,110,118,105,115,125,32,105,102,32,125,32,100,101,102,0,47,114,100,121,108,98,117,53,47,52,0,0,0,0,0,0,99,104,97,114,115,101,116,0,112,111,108,121,103,111,110,0,47,114,100,121,108,98,117,53,47,51,0,0,0,0,0,0,47,114,100,121,108,98,117,53,47,50,0,0,0,0,0,0,115,116,97,114,116,32,112,111,114,116,58,32,40,37,46,53,103,44,32,37,46,53,103,41,44,32,116,97,110,103,101,110,116,32,97,110,103,108,101,58,32,37,46,53,103,44,32,37,115,10,0,0,0,0,0,0,47,114,100,121,108,98,117,53,47,49,0,0,0,0,0,0,99,101,100,105,108,0,0,0,47,98,114,98,103,55,47,49,0,0,0,0,0,0,0,0,47,114,100,121,108,98,117,52,47,52,0,0,0,0,0,0,47,114,100,121,108,98,117,52,47,51,0,0,0,0,0,0,47,114,100,121,108,98,117,52,47,50,0,0,0,0,0,0,47,114,100,121,108,98,117,52,47,49,0,0,0,0,0,0,32,32,32,32,32,32,32,32,32,125,10,0,0,0,0,0,47,114,100,121,108,98,117,51,47,51,0,0,0,0,0,0,47,114,100,121,108,98,117,51,47,50,0,0,0,0,0,0,112,101,114,117,0,0,0,0,78,111,32,108,111,97,100,105,109,97,103,101,32,112,108,117,103,105,110,32,102,111,114,32,34,37,115,34,10,0,0,0,9,47,103,114,97,112,104,99,111,108,111,114,32,123,110,111,112,99,111,108,111,114,125,32,100,101,102,0,0,0,0,0,102,105,120,101,100,32,116,97,98,108,101,32,115,105,122,101,32,119,105,116,104,32,117,110,115,112,101,99,105,102,105,101,100,32,119,105,100,116,104,32,111,114,32,104,101,105,103,104,116,10,0,0,0,0,0,0,47,114,100,121,108,98,117,51,47,49,0,0,0,0,0,0,103,105,102,58,118,114,109,108,0,0,0,0,0,0,0,0,102,105,108,108,0,0,0,0,47,114,100,121,108,98,117,49,49,47,57,0,0,0,0,0,47,114,100,121,108,98,117,49,49,47,56,0,0,0,0,0,47,114,100,121,108,98,117,49,49,47,55,0,0,0,0,0,99,99,101,100,105,108,0,0,47,98,114,98,103,54,47,54,0,0,0,0,0,0,0,0,47,114,100,121,108,98,117,49,49,47,54,0,0,0,0,0,47,114,100,121,108,98,117,49,49,47,53,0,0,0,0,0,47,114,100,121,108,98,117,49,49,47,52,0,0,0,0,0,47,114,100,121,108,98,117,49,49,47,51,0,0,0,0,0,32,32,32,32,32,32,32,32,32,32,32,105,116,101,109,46,115,116,121,108,101,46,118,105,115,105,98,105,108,105,116,121,61,39,118,105,115,105,98,108,101,39,59,10,0,0,0,0,47,114,100,121,108,98,117,49,49,47,50,0,0,0,0,0,47,114,100,121,108,98,117,49,49,47,49,49,0,0,0,0,70,79,78,84,0,0,0,0,115,97,109,101,116,97,105,108,0,0,0,0,0,0,0,0,112,101,97,99,104,112,117,102,102,0,0,0,0,0,0,0,9,47,101,100,103,101,99,111,108,111,114,32,123,110,111,112,99,111,108,111,114,125,32,100,101,102,0,0,0,0,0,0,112,111,115,105,116,105,111,110,46,99,0,0,0,0,0,0,47,114,100,121,108,98,117,49,49,47,49,48,0,0,0,0,101,120,112,97,110,100,0,0,50,46,50,56,46,48,0,0,47,114,100,121,108,98,117,49,49,47,49,0,0,0,0,0,47,114,100,121,108,98,117,49,48,47,57,0,0,0,0,0,47,114,100,121,108,98,117,49,48,47,56,0,0,0,0,0,99,97,112,0,0,0,0,0,47,98,114,98,103,54,47,53,0,0,0,0,0,0,0,0,47,114,100,121,108,98,117,49,48,47,55,0,0,0,0,0,98,108,97,99,107,0,0,0,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,49,102,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,10,0,0,0,0,0,0,109,105,110,117,115,0,0,0,47,114,100,121,108,98,117,49,48,47,54,0,0,0,0,0,47,114,100,121,108,98,117,49,48,47,53,0,0,0,0,0,47,114,100,121,108,98,117,49,48,47,52,0,0,0,0,0,32,32,32,32,32,32,32,32,32,105,102,32,40,105,116,101,109,41,32,123,10,0,0,0,47,114,100,121,108,98,117,49,48,47,51,0,0,0,0,0,101,100,103,101,0,0,0,0,47,114,100,121,108,98,117,49,48,47,50,0,0,0,0,0,112,97,112,97,121,97,119,104,105,112,0,0,0,0,0,0,9,47,110,111,100,101,99,111,108,111,114,32,123,110,111,112,99,111,108,111,114,125,32,100,101,102,0,0,0,0,0,0,47,114,100,121,108,98,117,49,48,47,49,48,0,0,0,0,108,116,97,105,108,0,0,0,108,105,98,97,103,32,101,114,114,111,114,32,45,45,32,97,103,105,110,105,116,40,41,32,119,97,115,32,110,111,116,32,99,97,108,108,101,100,10,0,99,111,109,112,114,101,115,115,0,0,0,0,0,0,0,0,32,62,62,62,32,0,0,0,47,114,100,121,108,98,117,49,48,47,49,0,0,0,0,0,47,114,100,112,117,57,47,57,0,0,0,0,0,0,0,0,116,97,105,108,112,111,114,116,0,0,0,0,0,0,0,0,47,114,100,112,117,57,47,56,0,0,0,0,0,0,0,0,98,117,108,108,0,0,0,0,47,98,114,98,103,54,47,52,0,0,0,0,0,0,0,0,47,114,100,112,117,57,47,55,0,0,0,0,0,0,0,0,47,114,100,112,117,57,47,54,0,0,0,0,0,0,0,0,47,114,100,112,117,57,47,53,0,0,0,0,0,0,0,0,47,114,100,112,117,57,47,52,0,0,0,0,0,0,0,0,32,32,32,32,32,32,32,32,32,105,116,101,109,32,61,32,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,86,77,76,121,101,115,91,120,93,41,59,10,0,0,0,0,115,97,110,115,45,83,101,114,105,102,0,0,0,0,0,0,47,114,100,112,117,57,47,51,0,0,0,0,0,0,0,0,47,114,100,112,117,57,47,50,0,0,0,0,0,0,0,0,112,97,108,101,118,105,111,108,101,116,114,101,100,0,0,0,105,108,108,101,103,97,108,32,112,97,114,97,109,101,116,101,114,32,101,110,116,105,116,121,32,114,101,102,101,114,101,110,99,101,0,0,0,0,0,0,9,97,108,111,97,100,32,112,111,112,32,115,101,116,104,115,98,99,111,108,111,114,0,0,47,114,100,112,117,57,47,49,0,0,0,0,0,0,0,0,97,117,116,111,0,0,0,0,99,108,117,115,116,101,114,0,98,114,118,98,97,114,0,0,47,114,100,112,117,56,47,56,0,0,0,0,0,0,0,0,38,35,49,54,48,59,0,0,47,114,100,112,117,56,47,55,0,0,0,0,0,0,0,0,111,98,106,0,0,0,0,0,32,37,100,32,0,0,0,0,47,114,100,112,117,56,47,54,0,0,0,0,0,0,0,0,117,116,105,108,115,46,99,0,48,0,0,0,0,0,0,0,47,98,114,98,103,54,47,51,0,0,0,0,0,0,0,0,47,114,100,112,117,56,47,53,0,0,0,0,0,0,0,0,47,114,100,112,117,56,47,52,0,0,0,0,0,0,0,0,115,117,98,103,114,97,112,104,32,0,0,0,0,0,0,0,99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,112,110,108,115,0,0,0,0,0,47,114,100,112,117,56,47,51,0,0,0,0,0,0,0,0,119,105,100,116,104,0,0,0,47,114,100,112,117,56,47,50,0,0,0,0,0,0,0,0,32,32,32,32,32,32,32,102,111,114,32,40,120,32,105,110,32,86,77,76,121,101,115,41,123,10,0,0,0,0,0,0,110,111,110,97,109,101,46,103,118,0,0,0,0,0,0,0,37,37,66,101,103,105,110,68,111,99,117,109,101,110,116,58,10,0,0,0,0,0,0,0,47,114,100,112,117,56,47,49,0,0,0,0,0,0,0,0,47,114,100,112,117,55,47,55,0,0,0,0,0,0,0,0,112,97,108,101,116,117,114,113,117,111,105,115,101,0,0,0,37,37,66,101,103,105,110,80,114,111,108,111,103,0,0,0,47,114,100,112,117,55,47,54,0,0,0,0,0,0,0,0,114,97,116,105,111,0,0,0,98,108,117,101,0,0,0,0,117,115,0,0,0,0,0,0,98,101,116,97,0,0,0,0,47,114,100,112,117,55,47,53,0,0,0,0,0,0,0,0,9,108,97,121,101,114,99,111,108,111,114,115,101,113,32,99,117,114,108,97,121,101,114,32,49,32,115,117,98,32,108,97,121,101,114,108,101,110,32,109,111,100,32,103,101,116,0,0,47,114,100,112,117,55,47,52,0,0,0,0,0,0,0,0,47,114,100,112,117,55,47,51,0,0,0,0,0,0,0,0,102,111,110,116,99,111,108,111,114,0,0,0,0,0,0,0,47,98,114,98,103,54,47,50,0,0,0,0,0,0,0,0,47,114,100,112,117,55,47,50,0,0,0,0,0,0,0,0,47,114,100,112,117,55,47,49,0,0,0,0,0,0,0,0,47,114,100,112,117,54,47,54,0,0,0,0,0,0,0,0,114,97,110,107,40,103,44,32,50,44,32,110,115,105,116,101,114,50,40,103,41,41,32,61,61,32,48,0,0,0,0,0,47,114,100,112,117,54,47,53,0,0,0,0,0,0,0,0,32,32,32,32,32,32,105,102,32,40,105,101,118,101,114,115,62,61,53,41,123,10,0,0,47,114,100,112,117,54,47,52,0,0,0,0,0,0,0,0,115,105,110,107,0,0,0,0,47,114,100,112,117,54,47,51,0,0,0,0,0,0,0,0,47,68,111,116,68,105,99,116,32,50,48,48,32,100,105,99,116,32,100,101,102,0,0,0,112,97,108,101,103,114,101,101,110,0,0,0,0,0,0,0,112,99,0,0,0,0,0,0,47,115,101,116,108,97,121,101,114,32,123,47,109,97,120,108,97,121,101,114,32,101,120,99,104,32,100,101,102,32,47,99,117,114,108,97,121,101,114,32,101,120,99,104,32,100,101,102,0,0,0,0,0,0,0,0,47,114,100,112,117,54,47,50,0,0,0,0,0,0,0,0,37,108,102,37,99,0,0,0,121,101,115,0,0,0,0,0,47,115,116,97,114,110,101,116,73,83,79,32,123,0,0,0,98,100,113,117,111,0,0,0,47,114,100,112,117,54,47,49,0,0,0,0,0,0,0,0,47,114,100,112,117,53,47,53,0,0,0,0,0,0,0,0,103,118,114,101,110,100,101,114,95,115,101,116,95,115,116,121,108,101,58,32,117,110,115,117,112,112,111,114,116,101,100,32,115,116,121,108,101,32,37,115,32,45,32,105,103,110,111,114,105,110,103,10,0,0,0,0,47,114,100,112,117,53,47,52,0,0,0,0,0,0,0,0,108,97,121,101,114,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,105,110,32,37,115,32,111,117,116,112,117,116,10,0,0,0,0,0,0,47,98,114,98,103,54,47,49,0,0,0,0,0,0,0,0,47,114,100,112,117,53,47,51,0,0,0,0,0,0,0,0,47,114,100,112,117,53,47,50,0,0,0,0,0,0,0,0,47,114,100,112,117,53,47,49,0,0,0,0,0,0,0,0,47,114,100,112,117,52,47,52,0,0,0,0,0,0,0,0,32,32,32,32,32,32,125,10,0,0,0,0,0,0,0,0,47,114,100,112,117,52,47,51,0,0,0,0,0,0,0,0,47,114,100,112,117,52,47,50,0,0,0,0,0,0,0,0,112,97,108,101,103,111,108,100,101,110,114,111,100,0,0,0,47,108,97,121,101,114,108,101,110,32,108,97,121,101,114,99,111,108,111,114,115,101,113,32,108,101,110,103,116,104,32,100,101,102,0,0,0,0,0,0,47,114,100,112,117,52,47,49,0,0,0,0,0,0,0,0,37,108,102,44,37,108,102,37,99,0,0,0,0,0,0,0,97,117,109,108,0,0,0,0,47,114,100,112,117,51,47,51,0,0,0,0,0,0,0,0,47,114,100,112,117,51,47,50,0,0,0,0,0,0,0,0,47,114,100,112,117,51,47,49,0,0,0,0,0,0,0,0,73,109,97,103,101,115,32,117,110,115,117,112,112,111,114,116,101,100,32,105,110,32,34,98,97,99,107,103,114,111,117,110,100,34,32,97,116,116,114,105,98,117,116,101,10,0,0,0,111,0,0,0,0,0,0,0,47,98,114,98,103,53,47,53,0,0,0,0,0,0,0,0,47,114,100,103,121,57,47,57,0,0,0,0,0,0,0,0,47,114,100,103,121,57,47,56,0,0,0,0,0,0,0,0,47,114,100,103,121,57,47,55,0,0,0,0,0,0,0,0,47,114,100,103,121,57,47,54,0,0,0,0,0,0,0,0,32,32,32,32,32,32,32,32,32,105,101,118,101,114,115,61,32,112,97,114,115,101,73,110,116,32,40,117,97,46,115,117,98,115,116,114,105,110,103,32,40,109,115,105,101,43,53,44,32,117,97,46,105,110,100,101,120,79,102,32,40,39,46,39,44,32,109,115,105,101,32,41,41,41,10,0,0,0,0,0,47,114,100,103,121,57,47,53,0,0,0,0,0,0,0,0,47,114,100,103,121,57,47,52,0,0,0,0,0,0,0,0,111,114,99,104,105,100,0,0,100,101,102,0,0,0,0,0,47,114,100,103,121,57,47,51,0,0,0,0,0,0,0,0,108,97,98,101,108,106,117,115,116,0,0,0,0,0,0,0,97,116,105,108,100,101,0,0,47,114,100,103,121,57,47,50,0,0,0,0,0,0,0,0,109,99,108,105,109,105,116,0,47,114,100,103,121,57,47,49,0,0,0,0,0,0,0,0,47,114,100,103,121,56,47,56,0,0,0,0,0,0,0,0,116,114,97,110,115,112,97,114,101,110,116,0,0,0,0,0,47,98,114,98,103,53,47,52,0,0,0,0,0,0,0,0,47,114,100,103,121,56,47,55,0,0,0,0,0,0,0,0,47,114,100,103,121,56,47,54,0,0,0,0,0,0,0,0,47,114,100,103,121,56,47,53,0,0,0,0,0,0,0,0,47,114,100,103,121,56,47,52,0,0,0,0,0,0,0,0,32,32,32,32,32,32,105,102,32,40,32,109,115,105,101,32,62,32,48,32,41,123,32,32,32,32,32,32,47,47,32,73,102,32,73,110,116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,44,32,114,101,116,117,114,110,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,10,0,0,0,0,0,32,37,100,44,37,100,0,0,47,114,100,103,121,56,47,51,0,0,0,0,0,0,0,0,47,114,100,103,121,56,47,50,0,0,0,0,0,0,0,0,111,114,97,110,103,101,114,101,100,0,0,0,0,0,0,0,9,93,0,0,0,0,0,0,47,114,100,103,121,56,47,49,0,0,0,0,0,0,0,0,108,97,98,101,108,108,111,99,0,0,0,0,0,0,0,0,97,115,121,109,112,0,0,0,47,114,100,103,121,55,47,55,0,0,0,0,0,0,0,0,47,97,99,99,101,110,116,53,47,50,0,0,0,0,0,0,47,114,100,103,121,55,47,54,0,0,0,0,0,0,0,0,47,114,100,103,121,55,47,53,0,0,0,0,0,0,0,0,119,104,105,116,101,0,0,0,47,98,114,98,103,53,47,51,0,0,0,0,0,0,0,0,47,114,100,103,121,55,47,52,0,0,0,0,0,0,0,0,47,114,100,103,121,55,47,51,0,0,0,0,0,0,0,0,47,114,100,103,121,55,47,50,0,0,0,0,0,0,0,0,47,114,100,103,121,55,47,49,0,0,0,0,0,0,0,0,32,32,32,32,32,32,118,97,114,32,86,77,76,110,111,61,110,101,119,32,65,114,114,97,121,40,39,95,110,111,116,86,77,76,49,95,39,44,39,95,110,111,116,86,77,76,50,95,39,41,59,10,0,0,0,0,47,114,100,103,121,54,47,54,0,0,0,0,0,0,0,0,47,114,100,103,121,54,47,53,0,0,0,0,0,0,0,0,111,114,97,110,103,101,0,0,9,9,91,46,56,32,46,56,32,46,56,93,0,0,0,0,47,114,100,103,121,54,47,52,0,0,0,0,0,0,0,0,98,108,97,99,107,0,0,0,97,114,105,110,103,0,0,0,47,114,100,103,121,54,47,51,0,0,0,0,0,0,0,0,98,111,120,0,0,0,0,0,47,114,100,103,121,54,47,50,0,0,0,0,0,0,0,0,37,100,32,40,37,46,53,103,44,32,37,46,53,103,41,44,32,40,37,46,53,103,44,32,37,46,53,103,41,10,0,0,47,114,100,103,121,54,47,49,0,0,0,0,0,0,0,0,108,97,121,101,114,0,0,0,47,98,114,98,103,53,47,50,0,0,0,0,0,0,0,0,47,114,100,103,121,53,47,53,0,0,0,0,0,0,0,0,47,114,100,103,121,53,47,52,0,0,0,0,0,0,0,0,47,114,100,103,121,53,47,51,0,0,0,0,0,0,0,0,47,114,100,103,121,53,47,50,0,0,0,0,0,0,0,0,32,32,32,32,32,32,118,97,114,32,86,77,76,121,101,115,61,110,101,119,32,65,114,114,97,121,40,39,95,86,77,76,49,95,39,44,39,95,86,77,76,50,95,39,41,59,10,0,47,114,100,103,121,53,47,49,0,0,0,0,0,0,0,0,47,114,100,103,121,52,47,52,0,0,0,0,0,0,0,0,111,108,105,118,101,100,114,97,98,0,0,0,0,0,0,0,9,9,91,46,54,32,46,56,32,46,56,93,0,0,0,0,47,114,100,103,121,52,47,51,0,0,0,0,0,0,0,0,116,97,98,108,101,32,115,105,122,101,32,116,111,111,32,115,109,97,108,108,32,102,111,114,32,99,111,110,116,101,110,116,10,0,0,0,0,0,0,0,112,110,103,58,118,114,109,108,0,0,0,0,0,0,0,0,84,105,109,101,115,45,82,111,109,97,110,0,0,0,0,0,97,110,103,0,0,0,0,0,47,114,100,103,121,52,47,50,0,0,0,0,0,0,0,0,47,114,100,103,121,52,47,49,0,0,0,0,0,0,0,0,47,114,100,103,121,51,47,51,0,0,0,0,0,0,0,0,114,111,117,110,100,101,100,0,47,98,114,98,103,53,47,49,0,0,0,0,0,0,0,0,47,114,100,103,121,51,47,50,0,0,0,0,0,0,0,0,47,114,100,103,121,51,47,49,0,0,0,0,0,0,0,0,47,114,100,103,121,49,49,47,57,0,0,0,0,0,0,0,47,114,100,103,121,49,49,47,56,0,0,0,0,0,0,0,32,32,32,32,32,32,118,97,114,32,105,116,101,109,59,10,0,0,0,0,0,0,0,0,47,114,100,103,121,49,49,47,55,0,0,0,0,0,0,0,47,114,100,103,121,49,49,47,54,0,0,0,0,0,0,0,72,84,77,76,0,0,0,0,111,108,105,118,101,0,0,0,9,9,91,46,52,32,46,56,32,46,56,93,0,0,0,0,47,114,100,103,121,49,49,47,53,0,0,0,0,0,0,0,85,110,115,117,112,112,111,114,116,101,100,32,99,104,97,114,115,101,116,32,118,97,108,117,101,32,37,100,10,0,0,0,97,110,100,0,0,0,0,0,47,114,100,103,121,49,49,47,52,0,0,0,0,0,0,0,47,114,100,103,121,49,49,47,51,0,0,0,0,0,0,0,47,114,100,103,121,49,49,47,50,0,0,0,0,0,0,0,115,116,121,108,101,0,0,0,47,98,114,98,103,52,47,52,0,0,0,0,0,0,0,0,47,114,100,103,121,49,49,47,49,49,0,0,0,0,0,0,97,113,117,97,0,0,0,0,47,114,100,103,121,49,49,47,49,48,0,0,0,0,0,0,35,32,37,115,10,0,0,0,75,80,95,65,100,100,0,0,47,114,100,103,121,49,49,47,49,0,0,0,0,0,0,0,47,114,100,103,121,49,48,47,57,0,0,0,0,0,0,0,32,32,32,32,32,32,118,97,114,32,105,101,118,101,114,115,59,10,0,0,0,0,0,0,47,114,100,103,121,49,48,47,56,0,0,0,0,0,0,0,47,114,100,103,121,49,48,47,55,0,0,0,0,0,0,0,111,108,100,108,97,99,101,0,9,9,91,46,50,32,46,56,32,46,56,93,0,0,0,0,47,114,100,103,121,49,48,47,54,0,0,0,0,0,0,0,66,73,71,45,53,0,0,0,97,109,112,0,0,0,0,0,47,114,100,103,121,49,48,47,53,0,0,0,0,0,0,0,99,111,110,116,101,120,116,58,32,0,0,0,0,0,0,0,47,114,100,103,121,49,48,47,52,0,0,0,0,0,0,0,47,114,100,103,121,49,48,47,51,0,0,0,0,0,0,0,102,105,108,108,101,100,0,0,104,101,97,100,112,111,114,116,0,0,0,0,0,0,0,0,47,98,114,98,103,52,47,51,0,0,0,0,0,0,0,0,47,114,100,103,121,49,48,47,50,0,0,0,0,0,0,0,47,114,100,103,121,49,48,47,49,48,0,0,0,0,0,0,47,114,100,103,121,49,48,47,49,0,0,0,0,0,0,0,47,114,100,98,117,57,47,57,0,0,0,0,0,0,0,0,32,32,32,32,32,32,118,97,114,32,109,115,105,101,32,61,32,117,97,46,105,110,100,101,120,79,102,32,40,32,39,77,83,73,69,32,39,32,41,10,0,0,0,0,0,0,0,0,98,111,111,107,0,0,0,0,47,114,100,98,117,57,47,56,0,0,0,0,0,0,0,0,47,114,100,98,117,57,47,55,0,0,0,0,0,0,0,0,106,117,110,107,32,97,102,116,101,114,32,100,111,99,117,109,101,110,116,32,101,108,101,109,101,110,116,0,0,0,0,0,9,9,91,48,32,48,32,48,93,0,0,0,0,0,0,0,110,97,118,121,0,0,0,0,47,114,100,98,117,57,47,54,0,0,0,0,0,0,0,0,73,83,79,45,56,56,53,57,45,49,0,0,0,0,0,0,97,108,112,104,97,0,0,0,47,114,100,98,117,57,47,53,0,0,0,0,0,0,0,0,38,35,52,53,59,0,0,0,47,114,100,98,117,57,47,52,0,0,0,0,0,0,0,0,120,100,111,116,58,120,100,111,116,0,0,0,0,0,0,0,47,114,100,98,117,57,47,51,0,0,0,0,0,0,0,0,101,109,105,116,46,99,0,0,115,97,109,112,108,101,112,111,105,110,116,115,0,0,0,0,115,101,103,109,101,110,116,32,91,37,115,44,37,115,93,32,100,111,101,115,32,110,111,116,32,105,110,116,101,114,115,101,99,116,32,98,111,120,32,108,108,61,37,115,44,117,114,61,37,115,10,0,0,0,0,0,47,98,114,98,103,52,47,50,0,0,0,0,0,0,0,0,47,114,100,98,117,57,47,50,0,0,0,0,0,0,0,0,47,114,100,98,117,57,47,49,0,0,0,0,0,0,0,0,125,10,0,0,0,0,0,0,99,97,110,110,111,116,32,109,97,108,108,111,99,32,112,110,108,112,115,0,0,0,0,0,47,114,100,98,117,56,47,56,0,0,0,0,0,0,0,0,114,101,99,116,115,0,0,0,47,114,100,98,117,56,47,55,0,0,0,0,0,0,0,0,32,32,32,32,32,32,118,97,114,32,117,97,32,61,32,119,105,110,100,111,119,46,110,97,118,105,103,97,116,111,114,46,117,115,101,114,65,103,101,110,116,10,0,0,0,0,0,0,46,37,100,0,0,0,0,0,47,117,115,101,114,95,115,104,97,112,101,95,37,100,32,123,10,0,0,0,0,0,0,0,47,114,100,98,117,56,47,54,0,0,0,0,0,0,0,0,47,114,100,98,117,56,47,53,0,0,0,0,0,0,0,0,9,91,9,37,32,108,97,121,101,114,32,99,111,108,111,114,32,115,101,113,117,101,110,99,101,32,45,32,100,97,114,107,101,115,116,32,116,111,32,108,105,103,104,116,101,115,116,0,110,97,118,97,106,111,119,104,105,116,101,0,0,0,0,0,47,114,100,98,117,56,47,52,0,0,0,0,0,0,0,0,85,84,70,45,56,0,0,0,98,108,97,110,99,104,101,100,97,108,109,111,110,100,0,0,97,108,101,102,115,121,109,0,47,114,100,98,117,56,47,51,0,0,0,0,0,0,0,0,47,114,100,98,117,56,47,50,0,0,0,0,0,0,0,0,47,114,100,98,117,56,47,49,0,0,0,0,0,0,0,0,97,108,108,0,0,0,0,0,47,98,114,98,103,52,47,49,0,0,0,0,0,0,0,0,47,114,100,98,117,55,47,55,0,0,0,0,0,0,0,0,47,114,100,98,117,55,47,54,0,0,0,0,0,0,0,0,47,114,100,98,117,55,47,53,0,0,0,0,0,0,0,0,47,114,100,98,117,55,47,52,0,0,0,0,0,0,0,0,32,32,32,123,10,0,0,0,47,114,100,98,117,55,47,51,0,0,0,0,0,0,0,0,109,97,120,0,0,0,0,0,47,114,100,98,117,55,47,50,0,0,0,0,0,0,0,0,47,108,97,121,101,114,99,111,108,111,114,115,101,113,0,0,109,111,99,99,97,115,105,110,0,0,0,0,0,0,0,0,112,120,0,0,0,0,0,0,47,114,100,98,117,55,47,49,0,0,0,0,0,0,0,0,105,100,0,0,0,0,0,0,116,114,117,101,0,0,0,0,37,32,83,101,116,32,117,112,32,73,83,79,32,76,97,116,105,110,32,49,32,99,104,97,114,97,99,116,101,114,32,101,110,99,111,100,105,110,103,0,97,103,114,97,118,101,0,0,47,114,100,98,117,54,47,54,0,0,0,0,0,0,0,0,47,114,100,98,117,54,47,53,0,0,0,0,0,0,0,0,117,110,102,105,108,108,101,100,0,0,0,0,0,0,0,0,47,114,100,98,117,54,47,52,0,0,0,0,0,0,0,0,104,101,97,100,116,111,111,108,116,105,112,0,0,0,0,0,47,98,114,98,103,51,47,51,0,0,0,0,0,0,0,0,47,114,100,98,117,54,47,51,0,0,0,0,0,0,0,0,47,114,100,98,117,54,47,50,0,0,0,0,0,0,0,0,47,114,100,98,117,54,47,49,0,0,0,0,0,0,0,0,47,114,100,98,117,53,47,53,0,0,0,0,0,0,0,0,32,32,32,102,117,110,99,116,105,111,110,32,98,114,111,119,115,101,114,99,104,101,99,107,40,41,10,0,0,0,0,0,47,114,100,98,117,53,47,52,0,0,0,0,0,0,0,0,47,114,100,98,117,53,47,51,0,0,0,0,0,0,0,0,47,115,104,111,119,112,97,103,101,32,123,32,125,32,100,101,102,0,0,0,0,0,0,0,109,105,115,116,121,114,111,115,101,0,0,0,0,0,0,0,47,114,100,98,117,53,47,50,0,0,0,0,0,0,0,0,104,101,97,100,99,108,105,112,0,0,0,0,0,0,0,0,97,101,108,105,103,0,0,0,47,114,100,98,117,53,47,49,0,0,0,0,0,0,0,0,47,114,100,98,117,52,47,52,0,0,0,0,0,0,0,0,47,114,100,98,117,52,47,51,0,0,0,0,0,0,0,0,116,97,105,108,116,111,111,108,116,105,112,0,0,0,0,0,109,112,116,121,0,0,0,0,100,111,116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,118,109,108,95,116,101,120,116,112,97,114,97,0,0,0,0,118,109,108,95,112,114,105,110,116,95,99,111,108,111,114,0,116,114,97,110,115,112,111,115,101,95,115,116,101,112,0,0,116,107,103,101,110,95,112,114,105,110,116,95,116,97,103,115,0,0,0,0,0,0,0,0,116,107,103,101,110,95,112,114,105,110,116,95,99,111,108,111,114,0,0,0,0,0,0,0,115,118,103,95,116,101,120,116,112,97,114,97,0,0,0,0])
+.concat([115,118,103,95,112,114,105,110,116,95,99,111,108,111,114,0,115,101,116,98,111,117,110,100,115,0,0,0,0,0,0,0,115,97,102,101,95,100,101,108,101,116,101,95,102,97,115,116,95,101,100,103,101,0,0,0,114,111,117,110,100,95,99,111,114,110,101,114,115,0,0,0,112,111,115,116,111,114,100,101,114,0,0,0,0,0,0,0,112,111,115,95,104,116,109,108,95,116,98,108,0,0,0,0,112,111,112,95,111,98,106,95,115,116,97,116,101,0,0,0,111,118,101,114,108,97,112,95,98,101,122,105,101,114,0,0,109,105,110,109,97,120,95,101,100,103,101,115,0,0,0,0,109,101,114,103,101,118,105,114,116,117,97,108,0,0,0,0,109,101,114,103,101,95,111,110,101,119,97,121,0,0,0,0,109,101,114,103,101,95,99,104,97,105,110,0,0,0,0,0,109,97,112,95,112,97,116,104,0,0,0,0,0,0,0,0,109,97,112,95,111,117,116,112,117,116,95,115,104,97,112,101,0,0,0,0,0,0,0,0,109,97,112,78,0,0,0,0,109,97,107,101,95,108,97,98,101,108,0,0,0,0,0,0,109,97,107,101,95,99,104,97,105,110,0,0,0,0,0,0,109,97,107,101,83,101,108,102,69,100,103,101,0,0,0,0,109,97,107,101,67,111,109,112,111,117,110,100,69,100,103,101,0,0,0,0,0,0,0,0,105,110,116,101,114,99,108,101,120,112,0,0,0,0,0,0,105,110,115,116,97,108,108,95,105,110,95,114,97,110,107,0,105,110,105,116,95,115,112,108,105,110,101,115,95,98,98,0,103,118,117,115,101,114,115,104,97,112,101,95,102,105,108,101,95,97,99,99,101,115,115,0,102,108,97,116,95,115,101,97,114,99,104,0,0,0,0,0,102,105,103,95,114,101,115,111,108,118,101,95,99,111,108,111,114,0,0,0,0,0,0,0,102,105,103,95,98,101,122,105,101,114,0,0,0,0,0,0,102,97,115,116,95,110,111,100,101,97,112,112,0,0,0,0,102,97,115,116,95,110,111,100,101,0,0,0,0,0,0,0,101,110,100,112,97,116,104,0,101,109,105,116,95,101,100,103,101,95,108,97,98,101,108,0,100,111,116,95,112,111,115,105,116,105,111,110,0,0,0,0,100,101,108,101,116,101,95,102,108,97,116,95,101,100,103,101,0,0,0,0,0,0,0,0,100,101,108,101,116,101,95,102,97,115,116,95,110,111,100,101,0,0,0,0,0,0,0,0,100,101,108,101,116,101,95,102,97,115,116,95,101,100,103,101,0,0,0,0,0,0,0,0,99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,118,114,109,108,0,0,0,0,0,99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,115,118,103,0,0,0,0,0,0,99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,112,115,108,105,98,0,0,0,0,99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,112,115,0,0,0,0,0,0,0,99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,102,105,103,0,0,0,0,0,0,99,111,110,110,101,99,116,71,114,97,112,104,0,0,0,0,99,108,117,115,116,101,114,95,108,101,97,100,101,114,0,0,98,111,120,73,110,116,101,114,115,101,99,116,102,0,0,0,98,101,122,105,101,114,95,98,98,0,0,0,0,0,0,0,98,101,103,105,110,112,97,116,104,0,0,0,0,0,0,0,98,97,108,97,110,99,101,0,97,98,111,109,105,110,97,116,105,111,110,0,0,0,0,0,95,100,111,116,95,115,112,108,105,110,101,115,0,0,0,0,85,70,95,115,101,116,110,97,109,101,0,0,0,0,0,0,124,2,0,0,4,0,0,0,132,0,0,0,64,0,0,0,124,2,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,216,232,1,0,224,200,1,0,128,180,1,0,160,163,1,0,112,148,1,0,16,132,1,0,88,116,1,0,144,102,1,0,192,120,2,0,24,107,2,0,160,93,2,0,216,79,2,0,96,67,2,0,128,56,2,0,152,44,2,0,232,30,2,0,24,20,2,0,192,10,2,0,16,2,2,0,64,251,1,0,168,242,1,0,128,232,1,0,208,224,1,0,120,219,1,0,8,217,1,0,96,214,1,0,216,211,1,0,192,209,1,0,168,207,1,0,104,205,1,0,48,203,1,0,184,200,1,0,168,198,1,0,168,196,1,0,232,194,1,0,208,192,1,0,128,190,1,0,112,188,1,0,192,186,1,0,144,184,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,115,0,21,0,101,0,8,0,103,0,12,0,110,0,17,0,100,0,1,0,105,0,2,0,103,0,3,0,114,0,4,0,97,0,5,0,112,0,6,0,104,0,7,0,100,0,9,0,103,0,10,0,101,0,11,0,114,0,13,0,97,0,14,0,112,0,15,0,104,0,16,0,111,0,18,0,100,0,19,0,101,0,20,0,116,0,22,0,117,0,27,0,114,0,23,0,105,0,24,0,99,0,25,0,116,0,26,0,98,0,28,0,103,0,29,0,114,0,30,0,97,0,31,0,112,0,32,0,104,0,33,0,0,0,0,0,255,255,0,0,88,32,4,0,255,255,5,0,0,1,0,0,255,255,6,0,64,0,0,0,255,255,7,0,0,0,2,0,255,255,8,0,1,0,0,0,255,255,9,0,0,128,0,0,255,255,10,0,128,0,0,0,3,1,11,0,0,0,0,0,255,255,11,0,8,0,0,0,255,255,12,0,64,0,0,0,255,255,13,0,16,0,0,0,6,1,14,0,0,0,0,0,255,255,14,0,0,0,2,0,255,255,15,0,1,0,0,0,255,255,16,0,0,128,0,0,255,255,17,0,128,0,0,0,2,1,18,0,0,0,0,0,255,255,18,0,0,64,0,0,255,255,19,0,8,0,0,0,255,255,20,0,16,0,0,0,5,1,21,0,0,0,0,0,255,255,21,0,0,0,24,0,255,255,23,0,0,0,2,0,255,255,24,0,0,1,0,0,255,255,25,0,4,0,0,0,255,255,26,0,0,0,8,0,4,1,27,0,0,0,0,0,255,255,27,0,2,0,0,0,255,255,28,0,64,0,0,0,255,255,29,0,0,0,2,0,255,255,30,0,1,0,0,0,255,255,31,0,0,128,0,0,255,255,32,0,128,0,0,0,10,1,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40,116,2,0,144,27,0,0,96,34,0,0,0,0,0,0,128,101,2,0,144,27,0,0,160,30,0,0,0,0,0,0,224,88,2,0,144,27,0,0,224,32,0,0,0,0,0,0,144,74,2,0,144,27,0,0,224,32,0,0,0,0,0,0,80,63,2,0,144,27,0,0,0,34,0,0,0,0,0,0,136,52,2,0,216,27,0,0,0,34,0,0,0,0,0,0,176,40,2,0,144,27,0,0,16,33,0,0,0,0,0,0,224,26,2,0,144,27,0,0,176,29,0,0,0,0,0,0,232,16,2,0,144,27,0,0,208,30,0,0,0,0,0,0,160,6,2,0,144,27,0,0,208,30,0,0,0,0,0,0,160,255,1,0,144,27,0,0,160,33,0,0,0,0,0,0,96,248,1,0,144,27,0,0,224,29,0,0,0,0,0,0,128,238,1,0,144,27,0,0,48,31,0,0,0,0,0,0,152,229,1,0,144,27,0,0,80,32,0,0,0,0,0,0,8,222,1,0,144,27,0,0,0,31,0,0,0,0,0,0,184,218,1,0,144,27,0,0,128,32,0,0,0,0,0,0,32,216,1,0,144,27,0,0,112,30,0,0,0,0,0,0,88,213,1,0,144,27,0,0,96,31,0,0,0,0,0,0,8,211,1,0,144,27,0,0,144,31,0,0,0,0,0,0,224,208,1,0,144,27,0,0,16,30,0,0,0,0,0,0,16,207,1,0,144,27,0,0,176,32,0,0,0,0,0,0,152,204,1,0,144,27,0,0,48,34,0,0,0,0,0,0,48,202,1,0,144,27,0,0,208,33,0,0,0,0,0,0,232,199,1,0,144,27,0,0,96,34,0,0,0,0,0,0,8,198,1,0,144,27,0,0,96,34,0,0,0,0,0,0,8,196,1,0,144,27,0,0,64,30,0,0,0,0,0,0,32,194,1,0,144,27,0,0,112,33,0,0,0,0,0,0,232,191,1,0,144,27,0,0,64,33,0,0,0,0,0,0,160,189,1,0,144,27,0,0,128,29,0,0,0,0,0,0,200,187,1,0,144,27,0,0,192,31,0,0,0,0,0,0,24,186,1,0,144,27,0,0,240,31,0,0,0,0,0,0,176,183,1,0,144,27,0,0,32,32,0,0,0,0,0,0,184,181,1,0,144,27,0,0,192,34,0,0,0,0,0,0,208,179,1,0,144,27,0,0,144,34,0,0,0,0,0,0,40,178,1,0,144,27,0,0,240,34,0,0,0,0,0,0,160,176,1,0,0,18,0,0,0,0,0,0,0,0,0,0,72,175,1,0,0,18,0,0,0,0,0,0,0,0,0,0,112,193,1,0,240,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,208,68,2,0,104,104,2,0,24,249,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,121,101,115,0,0,0,0,0,118,101,114,115,105,111,110,0,115,116,97,110,100,97,108,111,110,101,0,0,0,0,0,0,110,111,0,0,0,0,0,0,101,110,99,111,100,105,110,103,0,0,0,0,0,0,0,0,85,84,70,45,56,0,0,0,85,84,70,45,49,54,76,69,0,0,0,0,0,0,0,0,85,84,70,45,49,54,66,69,0,0,0,0,0,0,0,0,85,84,70,45,49,54,0,0,85,83,45,65,83,67,73,73,0,0,0,0,0,0,0,0,83,89,83,84,69,77,0,0,82,69,81,85,73,82,69,68,0,0,0,0,0,0,0,0,80,85,66,76,73,67,0,0,80,67,68,65,84,65,0,0,78,79,84,65,84,73,79,78,0,0,0,0,0,0,0,0,78,77,84,79,75,69,78,83,0,0,0,0,0,0,0,0,78,77,84,79,75,69,78,0,78,68,65,84,65,0,0,0,73,83,79,45,56,56,53,57,45,49,0,0,0,0,0,0,73,77,80,76,73,69,68,0,73,68,82,69,70,83,0,0,73,68,82,69,70,0,0,0,73,68,0,0,0,0,0,0,70,73,88,69,68,0,0,0,69,78,84,73,84,89,0,0,69,78,84,73,84,73,69,83,0,0,0,0,0,0,0,0,69,77,80,84,89,0,0,0,69,76,69,77,69,78,84,0,68,79,67,84,89,80,69,0,67,68,65,84,65,0,0,0,65,84,84,76,73,83,84,0,65,78,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,190,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,180,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,131,2,0,0,0,0,0,96,131,2,0,0,0,0,0,104,131,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,8,0,0,0,16,0,0,0,32,0,0,0,64,0,0,0,128,0,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,8,0,0,0,16,0,0,0,32,0,0,0,64,0,0,0,128,0,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,8,0,0,0,16,0,0,0,32,0,0,0,64,0,0,0,128,0,0,0,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,191,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,240,63,172,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,240,63,42,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,224,63,242,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,240,63,12,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,51,51,51,51,51,51,243,63,130,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,154,153,153,153,153,153,233,63,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,80,49,2,0,25,0,0,0,0,0,0,0,0,0,0,0,240,4,2,0,1,0,0,0,48,85,2,0,2,0,0,0,16,228,1,0,3,0,0,0,168,208,1,0,4,0,0,0,144,187,1,0,5,0,0,0,88,170,1,0,6,0,0,0,112,154,1,0,0,0,0,0,216,137,1,0,17,0,0,0,144,121,1,0,18,0,0,0,0,108,1,0,18,0,0,0,176,125,2,0,1,0,0,0,0,0,0,0,0,0,0,0,160,112,2,0,8,0,0,0,88,98,2,0,64,0,0,0,96,77,2,0,32,0,0,0,72,71,2,0,8,0,0,0,104,60,2,0,32,0,0,0,0,0,0,0,0,0,0,0,168,34,2,0,0,0,0,0,1,0,0,0,32,24,2,0,1,0,0,0,0,0,0,0,120,14,2,0,1,0,0,0,1,0,0,0,112,154,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
+, "i8", ALLOC_NONE, Runtime.GLOBAL_BASE)
+function runPostSets() {
+}
+if (!awaitingMemoryInitializer) runPostSets();
+var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);
+assert(tempDoublePtr % 8 == 0);
+function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+ HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
+ HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
+ HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
+}
+function copyTempDouble(ptr) {
+ HEAP8[tempDoublePtr] = HEAP8[ptr];
+ HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
+ HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
+ HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
+ HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];
+ HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];
+ HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];
+ HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];
+}
+ function _strncmp(px, py, n) {
+ var i = 0;
+ while (i < n) {
+ var x = HEAPU8[(((px)+(i))|0)];
+ var y = HEAPU8[(((py)+(i))|0)];
+ if (x == y && x == 0) return 0;
+ if (x == 0) return -1;
+ if (y == 0) return 1;
+ if (x == y) {
+ i ++;
+ continue;
+ } else {
+ return x > y ? 1 : -1;
+ }
+ }
+ return 0;
+ }function _strcmp(px, py) {
+ return _strncmp(px, py, TOTAL_MEMORY);
+ }
+ Module["_memcmp"] = _memcmp;
+ Module["_memcpy"] = _memcpy;var _llvm_memcpy_p0i8_p0i8_i32=_memcpy;
+ var _sqrt=Math.sqrt;
+ Module["_strlen"] = _strlen;
+ function _parseXDotF() {
+ Module['printErr']('missing function: parseXDotF'); abort(-1);
+ }
+ function _statXDot() {
+ Module['printErr']('missing function: statXDot'); abort(-1);
+ }
+ var ERRNO_CODES={E2BIG:7,EACCES:13,EADDRINUSE:98,EADDRNOTAVAIL:99,EAFNOSUPPORT:97,EAGAIN:11,EALREADY:114,EBADF:9,EBADMSG:74,EBUSY:16,ECANCELED:125,ECHILD:10,ECONNABORTED:103,ECONNREFUSED:111,ECONNRESET:104,EDEADLK:35,EDESTADDRREQ:89,EDOM:33,EDQUOT:122,EEXIST:17,EFAULT:14,EFBIG:27,EHOSTUNREACH:113,EIDRM:43,EILSEQ:84,EINPROGRESS:115,EINTR:4,EINVAL:22,EIO:5,EISCONN:106,EISDIR:21,ELOOP:40,EMFILE:24,EMLINK:31,EMSGSIZE:90,EMULTIHOP:72,ENAMETOOLONG:36,ENETDOWN:100,ENETRESET:102,ENETUNREACH:101,ENFILE:23,ENOBUFS:105,ENODATA:61,ENODEV:19,ENOENT:2,ENOEXEC:8,ENOLCK:37,ENOLINK:67,ENOMEM:12,ENOMSG:42,ENOPROTOOPT:92,ENOSPC:28,ENOSR:63,ENOSTR:60,ENOSYS:38,ENOTCONN:107,ENOTDIR:20,ENOTEMPTY:39,ENOTRECOVERABLE:131,ENOTSOCK:88,ENOTSUP:95,ENOTTY:25,ENXIO:6,EOPNOTSUPP:45,EOVERFLOW:75,EOWNERDEAD:130,EPERM:1,EPIPE:32,EPROTO:71,EPROTONOSUPPORT:93,EPROTOTYPE:91,ERANGE:34,EROFS:30,ESPIPE:29,ESRCH:3,ESTALE:116,ETIME:62,ETIMEDOUT:110,ETXTBSY:26,EWOULDBLOCK:11,EXDEV:18};
+ function ___setErrNo(value) {
+ // For convenient setting and returning of errno.
+ if (!___setErrNo.ret) ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL);
+ HEAP32[((___setErrNo.ret)>>2)]=value
+ return value;
+ }
+ var _stdin=allocate(1, "i32*", ALLOC_STATIC);
+ var _stdout=allocate(1, "i32*", ALLOC_STATIC);
+ var _stderr=allocate(1, "i32*", ALLOC_STATIC);
+ var __impure_ptr=allocate(1, "i32*", ALLOC_STATIC);var FS={currentPath:"/",nextInode:2,streams:[null],ignorePermissions:true,joinPath:function (parts, forceRelative) {
+ var ret = parts[0];
+ for (var i = 1; i < parts.length; i++) {
+ if (ret[ret.length-1] != '/') ret += '/';
+ ret += parts[i];
+ }
+ if (forceRelative && ret[0] == '/') ret = ret.substr(1);
+ return ret;
+ },absolutePath:function (relative, base) {
+ if (typeof relative !== 'string') return null;
+ if (base === undefined) base = FS.currentPath;
+ if (relative && relative[0] == '/') base = '';
+ var full = base + '/' + relative;
+ var parts = full.split('/').reverse();
+ var absolute = [''];
+ while (parts.length) {
+ var part = parts.pop();
+ if (part == '' || part == '.') {
+ // Nothing.
+ } else if (part == '..') {
+ if (absolute.length > 1) absolute.pop();
+ } else {
+ absolute.push(part);
+ }
+ }
+ return absolute.length == 1 ? '/' : absolute.join('/');
+ },analyzePath:function (path, dontResolveLastLink, linksVisited) {
+ var ret = {
+ isRoot: false,
+ exists: false,
+ error: 0,
+ name: null,
+ path: null,
+ object: null,
+ parentExists: false,
+ parentPath: null,
+ parentObject: null
+ };
+ path = FS.absolutePath(path);
+ if (path == '/') {
+ ret.isRoot = true;
+ ret.exists = ret.parentExists = true;
+ ret.name = '/';
+ ret.path = ret.parentPath = '/';
+ ret.object = ret.parentObject = FS.root;
+ } else if (path !== null) {
+ linksVisited = linksVisited || 0;
+ path = path.slice(1).split('/');
+ var current = FS.root;
+ var traversed = [''];
+ while (path.length) {
+ if (path.length == 1 && current.isFolder) {
+ ret.parentExists = true;
+ ret.parentPath = traversed.length == 1 ? '/' : traversed.join('/');
+ ret.parentObject = current;
+ ret.name = path[0];
+ }
+ var target = path.shift();
+ if (!current.isFolder) {
+ ret.error = ERRNO_CODES.ENOTDIR;
+ break;
+ } else if (!current.read) {
+ ret.error = ERRNO_CODES.EACCES;
+ break;
+ } else if (!current.contents.hasOwnProperty(target)) {
+ ret.error = ERRNO_CODES.ENOENT;
+ break;
+ }
+ current = current.contents[target];
+ if (current.link && !(dontResolveLastLink && path.length == 0)) {
+ if (linksVisited > 40) { // Usual Linux SYMLOOP_MAX.
+ ret.error = ERRNO_CODES.ELOOP;
+ break;
+ }
+ var link = FS.absolutePath(current.link, traversed.join('/'));
+ ret = FS.analyzePath([link].concat(path).join('/'),
+ dontResolveLastLink, linksVisited + 1);
+ return ret;
+ }
+ traversed.push(target);
+ if (path.length == 0) {
+ ret.exists = true;
+ ret.path = traversed.join('/');
+ ret.object = current;
+ }
+ }
+ }
+ return ret;
+ },findObject:function (path, dontResolveLastLink) {
+ FS.ensureRoot();
+ var ret = FS.analyzePath(path, dontResolveLastLink);
+ if (ret.exists) {
+ return ret.object;
+ } else {
+ ___setErrNo(ret.error);
+ return null;
+ }
+ },createObject:function (parent, name, properties, canRead, canWrite) {
+ if (!parent) parent = '/';
+ if (typeof parent === 'string') parent = FS.findObject(parent);
+ if (!parent) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ throw new Error('Parent path must exist.');
+ }
+ if (!parent.isFolder) {
+ ___setErrNo(ERRNO_CODES.ENOTDIR);
+ throw new Error('Parent must be a folder.');
+ }
+ if (!parent.write && !FS.ignorePermissions) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ throw new Error('Parent folder must be writeable.');
+ }
+ if (!name || name == '.' || name == '..') {
+ ___setErrNo(ERRNO_CODES.ENOENT);
+ throw new Error('Name must not be empty.');
+ }
+ if (parent.contents.hasOwnProperty(name)) {
+ ___setErrNo(ERRNO_CODES.EEXIST);
+ throw new Error("Can't overwrite object.");
+ }
+ parent.contents[name] = {
+ read: canRead === undefined ? true : canRead,
+ write: canWrite === undefined ? false : canWrite,
+ timestamp: Date.now(),
+ inodeNumber: FS.nextInode++
+ };
+ for (var key in properties) {
+ if (properties.hasOwnProperty(key)) {
+ parent.contents[name][key] = properties[key];
+ }
+ }
+ return parent.contents[name];
+ },createFolder:function (parent, name, canRead, canWrite) {
+ var properties = {isFolder: true, isDevice: false, contents: {}};
+ return FS.createObject(parent, name, properties, canRead, canWrite);
+ },createPath:function (parent, path, canRead, canWrite) {
+ var current = FS.findObject(parent);
+ if (current === null) throw new Error('Invalid parent.');
+ path = path.split('/').reverse();
+ while (path.length) {
+ var part = path.pop();
+ if (!part) continue;
+ if (!current.contents.hasOwnProperty(part)) {
+ FS.createFolder(current, part, canRead, canWrite);
+ }
+ current = current.contents[part];
+ }
+ return current;
+ },createFile:function (parent, name, properties, canRead, canWrite) {
+ properties.isFolder = false;
+ return FS.createObject(parent, name, properties, canRead, canWrite);
+ },createDataFile:function (parent, name, data, canRead, canWrite) {
+ if (typeof data === 'string') {
+ var dataArray = new Array(data.length);
+ for (var i = 0, len = data.length; i < len; ++i) dataArray[i] = data.charCodeAt(i);
+ data = dataArray;
+ }
+ var properties = {
+ isDevice: false,
+ contents: data.subarray ? data.subarray(0) : data // as an optimization, create a new array wrapper (not buffer) here, to help JS engines understand this object
+ };
+ return FS.createFile(parent, name, properties, canRead, canWrite);
+ },createLazyFile:function (parent, name, url, canRead, canWrite) {
+ if (typeof XMLHttpRequest !== 'undefined') {
+ if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
+ // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
+ var LazyUint8Array = function(chunkSize, length) {
+ this.length = length;
+ this.chunkSize = chunkSize;
+ this.chunks = []; // Loaded chunks. Index is the chunk number
+ }
+ LazyUint8Array.prototype.get = function(idx) {
+ if (idx > this.length-1 || idx < 0) {
+ return undefined;
+ }
+ var chunkOffset = idx % chunkSize;
+ var chunkNum = Math.floor(idx / chunkSize);
+ return this.getter(chunkNum)[chunkOffset];
+ }
+ LazyUint8Array.prototype.setDataGetter = function(getter) {
+ this.getter = getter;
+ }
+ // Find length
+ var xhr = new XMLHttpRequest();
+ xhr.open('HEAD', url, false);
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
+ var datalength = Number(xhr.getResponseHeader("Content-length"));
+ var header;
+ var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
+ var chunkSize = 1024*1024; // Chunk size in bytes
+ if (!hasByteServing) chunkSize = datalength;
+ // Function to get a range from the remote URL.
+ var doXHR = (function(from, to) {
+ if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
+ if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
+ // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
+ // Some hints to the browser that we want binary data.
+ if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
+ if (xhr.overrideMimeType) {
+ xhr.overrideMimeType('text/plain; charset=x-user-defined');
+ }
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
+ if (xhr.response !== undefined) {
+ return new Uint8Array(xhr.response || []);
+ } else {
+ return intArrayFromString(xhr.responseText || '', true);
+ }
+ });
+ var lazyArray = new LazyUint8Array(chunkSize, datalength);
+ lazyArray.setDataGetter(function(chunkNum) {
+ var start = chunkNum * lazyArray.chunkSize;
+ var end = (chunkNum+1) * lazyArray.chunkSize - 1; // including this byte
+ end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") {
+ lazyArray.chunks[chunkNum] = doXHR(start, end);
+ }
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!");
+ return lazyArray.chunks[chunkNum];
+ });
+ var properties = { isDevice: false, contents: lazyArray };
+ } else {
+ var properties = { isDevice: false, url: url };
+ }
+ return FS.createFile(parent, name, properties, canRead, canWrite);
+ },createPreloadedFile:function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) {
+ Browser.init();
+ var fullname = FS.joinPath([parent, name], true);
+ function processData(byteArray) {
+ function finish(byteArray) {
+ if (!dontCreateFile) {
+ FS.createDataFile(parent, name, byteArray, canRead, canWrite);
+ }
+ if (onload) onload();
+ removeRunDependency('cp ' + fullname);
+ }
+ var handled = false;
+ Module['preloadPlugins'].forEach(function(plugin) {
+ if (handled) return;
+ if (plugin['canHandle'](fullname)) {
+ plugin['handle'](byteArray, fullname, finish, function() {
+ if (onerror) onerror();
+ removeRunDependency('cp ' + fullname);
+ });
+ handled = true;
+ }
+ });
+ if (!handled) finish(byteArray);
+ }
+ addRunDependency('cp ' + fullname);
+ if (typeof url == 'string') {
+ Browser.asyncLoad(url, function(byteArray) {
+ processData(byteArray);
+ }, onerror);
+ } else {
+ processData(url);
+ }
+ },createLink:function (parent, name, target, canRead, canWrite) {
+ var properties = {isDevice: false, link: target};
+ return FS.createFile(parent, name, properties, canRead, canWrite);
+ },createDevice:function (parent, name, input, output) {
+ if (!(input || output)) {
+ throw new Error('A device must have at least one callback defined.');
+ }
+ var ops = {isDevice: true, input: input, output: output};
+ return FS.createFile(parent, name, ops, Boolean(input), Boolean(output));
+ },forceLoadFile:function (obj) {
+ if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
+ var success = true;
+ if (typeof XMLHttpRequest !== 'undefined') {
+ throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
+ } else if (Module['read']) {
+ // Command-line.
+ try {
+ // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as
+ // read() will try to parse UTF8.
+ obj.contents = intArrayFromString(Module['read'](obj.url), true);
+ } catch (e) {
+ success = false;
+ }
+ } else {
+ throw new Error('Cannot load without read() or XMLHttpRequest.');
+ }
+ if (!success) ___setErrNo(ERRNO_CODES.EIO);
+ return success;
+ },ensureRoot:function () {
+ if (FS.root) return;
+ // The main file system tree. All the contents are inside this.
+ FS.root = {
+ read: true,
+ write: true,
+ isFolder: true,
+ isDevice: false,
+ timestamp: Date.now(),
+ inodeNumber: 1,
+ contents: {}
+ };
+ },init:function (input, output, error) {
+ // Make sure we initialize only once.
+ assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
+ FS.init.initialized = true;
+ FS.ensureRoot();
+ // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
+ input = input || Module['stdin'];
+ output = output || Module['stdout'];
+ error = error || Module['stderr'];
+ // Default handlers.
+ var stdinOverridden = true, stdoutOverridden = true, stderrOverridden = true;
+ if (!input) {
+ stdinOverridden = false;
+ input = function() {
+ if (!input.cache || !input.cache.length) {
+ var result;
+ if (typeof window != 'undefined' &&
+ typeof window.prompt == 'function') {
+ // Browser.
+ result = window.prompt('Input: ');
+ if (result === null) result = String.fromCharCode(0); // cancel ==> EOF
+ } else if (typeof readline == 'function') {
+ // Command line.
+ result = readline();
+ }
+ if (!result) result = '';
+ input.cache = intArrayFromString(result + '\n', true);
+ }
+ return input.cache.shift();
+ };
+ }
+ var utf8 = new Runtime.UTF8Processor();
+ function simpleOutput(val) {
+ if (val === null || val === 10) {
+ output.printer(output.buffer.join(''));
+ output.buffer = [];
+ } else {
+ output.buffer.push(utf8.processCChar(val));
+ }
+ }
+ if (!output) {
+ stdoutOverridden = false;
+ output = simpleOutput;
+ }
+ if (!output.printer) output.printer = Module['print'];
+ if (!output.buffer) output.buffer = [];
+ if (!error) {
+ stderrOverridden = false;
+ error = simpleOutput;
+ }
+ if (!error.printer) error.printer = Module['print'];
+ if (!error.buffer) error.buffer = [];
+ // Create the temporary folder, if not already created
+ try {
+ FS.createFolder('/', 'tmp', true, true);
+ } catch(e) {}
+ // Create the I/O devices.
+ var devFolder = FS.createFolder('/', 'dev', true, true);
+ var stdin = FS.createDevice(devFolder, 'stdin', input);
+ var stdout = FS.createDevice(devFolder, 'stdout', null, output);
+ var stderr = FS.createDevice(devFolder, 'stderr', null, error);
+ FS.createDevice(devFolder, 'tty', input, output);
+ // Create default streams.
+ FS.streams[1] = {
+ path: '/dev/stdin',
+ object: stdin,
+ position: 0,
+ isRead: true,
+ isWrite: false,
+ isAppend: false,
+ isTerminal: !stdinOverridden,
+ error: false,
+ eof: false,
+ ungotten: []
+ };
+ FS.streams[2] = {
+ path: '/dev/stdout',
+ object: stdout,
+ position: 0,
+ isRead: false,
+ isWrite: true,
+ isAppend: false,
+ isTerminal: !stdoutOverridden,
+ error: false,
+ eof: false,
+ ungotten: []
+ };
+ FS.streams[3] = {
+ path: '/dev/stderr',
+ object: stderr,
+ position: 0,
+ isRead: false,
+ isWrite: true,
+ isAppend: false,
+ isTerminal: !stderrOverridden,
+ error: false,
+ eof: false,
+ ungotten: []
+ };
+ // TODO: put these low in memory like we used to assert on: assert(Math.max(_stdin, _stdout, _stderr) < 15000); // make sure these are low, we flatten arrays with these
+ HEAP32[((_stdin)>>2)]=1;
+ HEAP32[((_stdout)>>2)]=2;
+ HEAP32[((_stderr)>>2)]=3;
+ // Other system paths
+ FS.createPath('/', 'dev/shm/tmp', true, true); // temp files
+ // Newlib initialization
+ for (var i = FS.streams.length; i < Math.max(_stdin, _stdout, _stderr) + 4; i++) {
+ FS.streams[i] = null; // Make sure to keep FS.streams dense
+ }
+ FS.streams[_stdin] = FS.streams[1];
+ FS.streams[_stdout] = FS.streams[2];
+ FS.streams[_stderr] = FS.streams[3];
+ allocate([ allocate(
+ [0, 0, 0, 0, _stdin, 0, 0, 0, _stdout, 0, 0, 0, _stderr, 0, 0, 0],
+ 'void*', ALLOC_DYNAMIC) ], 'void*', ALLOC_NONE, __impure_ptr);
+ },quit:function () {
+ if (!FS.init.initialized) return;
+ // Flush any partially-printed lines in stdout and stderr. Careful, they may have been closed
+ if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output(10);
+ if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output(10);
+ },standardizePath:function (path) {
+ if (path.substr(0, 2) == './') path = path.substr(2);
+ return path;
+ },deleteFile:function (path) {
+ path = FS.analyzePath(path);
+ if (!path.parentExists || !path.exists) {
+ throw 'Invalid path ' + path;
+ }
+ delete path.parentObject.contents[path.name];
+ }};
+ function _pwrite(fildes, buf, nbyte, offset) {
+ // ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html
+ var stream = FS.streams[fildes];
+ if (!stream || stream.object.isDevice) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ } else if (!stream.isWrite) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ } else if (stream.object.isFolder) {
+ ___setErrNo(ERRNO_CODES.EISDIR);
+ return -1;
+ } else if (nbyte < 0 || offset < 0) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ } else {
+ var contents = stream.object.contents;
+ while (contents.length < offset) contents.push(0);
+ for (var i = 0; i < nbyte; i++) {
+ contents[offset + i] = HEAPU8[(((buf)+(i))|0)];
+ }
+ stream.object.timestamp = Date.now();
+ return i;
+ }
+ }function _write(fildes, buf, nbyte) {
+ // ssize_t write(int fildes, const void *buf, size_t nbyte);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/write.html
+ var stream = FS.streams[fildes];
+ if (!stream) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ } else if (!stream.isWrite) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ } else if (nbyte < 0) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ } else {
+ if (stream.object.isDevice) {
+ if (stream.object.output) {
+ for (var i = 0; i < nbyte; i++) {
+ try {
+ stream.object.output(HEAP8[(((buf)+(i))|0)]);
+ } catch (e) {
+ ___setErrNo(ERRNO_CODES.EIO);
+ return -1;
+ }
+ }
+ stream.object.timestamp = Date.now();
+ return i;
+ } else {
+ ___setErrNo(ERRNO_CODES.ENXIO);
+ return -1;
+ }
+ } else {
+ var bytesWritten = _pwrite(fildes, buf, nbyte, stream.position);
+ if (bytesWritten != -1) stream.position += bytesWritten;
+ return bytesWritten;
+ }
+ }
+ }function _fwrite(ptr, size, nitems, stream) {
+ // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fwrite.html
+ var bytesToWrite = nitems * size;
+ if (bytesToWrite == 0) return 0;
+ var bytesWritten = _write(stream, ptr, bytesToWrite);
+ if (bytesWritten == -1) {
+ if (FS.streams[stream]) FS.streams[stream].error = true;
+ return 0;
+ } else {
+ return Math.floor(bytesWritten / size);
+ }
+ }
+ function __reallyNegative(x) {
+ return x < 0 || (x === 0 && (1/x) === -Infinity);
+ }function __formatString(format, varargs) {
+ var textIndex = format;
+ var argIndex = 0;
+ function getNextArg(type) {
+ // NOTE: Explicitly ignoring type safety. Otherwise this fails:
+ // int x = 4; printf("%c\n", (char)x);
+ var ret;
+ if (type === 'double') {
+ ret = HEAPF64[(((varargs)+(argIndex))>>3)];
+ } else if (type == 'i64') {
+ ret = [HEAP32[(((varargs)+(argIndex))>>2)],
+ HEAP32[(((varargs)+(argIndex+8))>>2)]];
+ argIndex += 8; // each 32-bit chunk is in a 64-bit block
+ } else {
+ type = 'i32'; // varargs are always i32, i64, or double
+ ret = HEAP32[(((varargs)+(argIndex))>>2)];
+ }
+ argIndex += Math.max(Runtime.getNativeFieldSize(type), Runtime.getAlignSize(type, null, true));
+ return ret;
+ }
+ var ret = [];
+ var curr, next, currArg;
+ while(1) {
+ var startTextIndex = textIndex;
+ curr = HEAP8[(textIndex)];
+ if (curr === 0) break;
+ next = HEAP8[((textIndex+1)|0)];
+ if (curr == 37) {
+ // Handle flags.
+ var flagAlwaysSigned = false;
+ var flagLeftAlign = false;
+ var flagAlternative = false;
+ var flagZeroPad = false;
+ flagsLoop: while (1) {
+ switch (next) {
+ case 43:
+ flagAlwaysSigned = true;
+ break;
+ case 45:
+ flagLeftAlign = true;
+ break;
+ case 35:
+ flagAlternative = true;
+ break;
+ case 48:
+ if (flagZeroPad) {
+ break flagsLoop;
+ } else {
+ flagZeroPad = true;
+ break;
+ }
+ default:
+ break flagsLoop;
+ }
+ textIndex++;
+ next = HEAP8[((textIndex+1)|0)];
+ }
+ // Handle width.
+ var width = 0;
+ if (next == 42) {
+ width = getNextArg('i32');
+ textIndex++;
+ next = HEAP8[((textIndex+1)|0)];
+ } else {
+ while (next >= 48 && next <= 57) {
+ width = width * 10 + (next - 48);
+ textIndex++;
+ next = HEAP8[((textIndex+1)|0)];
+ }
+ }
+ // Handle precision.
+ var precisionSet = false;
+ if (next == 46) {
+ var precision = 0;
+ precisionSet = true;
+ textIndex++;
+ next = HEAP8[((textIndex+1)|0)];
+ if (next == 42) {
+ precision = getNextArg('i32');
+ textIndex++;
+ } else {
+ while(1) {
+ var precisionChr = HEAP8[((textIndex+1)|0)];
+ if (precisionChr < 48 ||
+ precisionChr > 57) break;
+ precision = precision * 10 + (precisionChr - 48);
+ textIndex++;
+ }
+ }
+ next = HEAP8[((textIndex+1)|0)];
+ } else {
+ var precision = 6; // Standard default.
+ }
+ // Handle integer sizes. WARNING: These assume a 32-bit architecture!
+ var argSize;
+ switch (String.fromCharCode(next)) {
+ case 'h':
+ var nextNext = HEAP8[((textIndex+2)|0)];
+ if (nextNext == 104) {
+ textIndex++;
+ argSize = 1; // char (actually i32 in varargs)
+ } else {
+ argSize = 2; // short (actually i32 in varargs)
+ }
+ break;
+ case 'l':
+ var nextNext = HEAP8[((textIndex+2)|0)];
+ if (nextNext == 108) {
+ textIndex++;
+ argSize = 8; // long long
+ } else {
+ argSize = 4; // long
+ }
+ break;
+ case 'L': // long long
+ case 'q': // int64_t
+ case 'j': // intmax_t
+ argSize = 8;
+ break;
+ case 'z': // size_t
+ case 't': // ptrdiff_t
+ case 'I': // signed ptrdiff_t or unsigned size_t
+ argSize = 4;
+ break;
+ default:
+ argSize = null;
+ }
+ if (argSize) textIndex++;
+ next = HEAP8[((textIndex+1)|0)];
+ // Handle type specifier.
+ switch (String.fromCharCode(next)) {
+ case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': {
+ // Integer.
+ var signed = next == 100 || next == 105;
+ argSize = argSize || 4;
+ var currArg = getNextArg('i' + (argSize * 8));
+ var origArg = currArg;
+ var argText;
+ // Flatten i64-1 [low, high] into a (slightly rounded) double
+ if (argSize == 8) {
+ currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 117);
+ }
+ // Truncate to requested size.
+ if (argSize <= 4) {
+ var limit = Math.pow(256, argSize) - 1;
+ currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8);
+ }
+ // Format the number.
+ var currAbsArg = Math.abs(currArg);
+ var prefix = '';
+ if (next == 100 || next == 105) {
+ if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else
+ argText = reSign(currArg, 8 * argSize, 1).toString(10);
+ } else if (next == 117) {
+ if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else
+ argText = unSign(currArg, 8 * argSize, 1).toString(10);
+ currArg = Math.abs(currArg);
+ } else if (next == 111) {
+ argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8);
+ } else if (next == 120 || next == 88) {
+ prefix = flagAlternative ? '0x' : '';
+ if (argSize == 8 && i64Math) {
+ if (origArg[1]) {
+ argText = (origArg[1]>>>0).toString(16);
+ var lower = (origArg[0]>>>0).toString(16);
+ while (lower.length < 8) lower = '0' + lower;
+ argText += lower;
+ } else {
+ argText = (origArg[0]>>>0).toString(16);
+ }
+ } else
+ if (currArg < 0) {
+ // Represent negative numbers in hex as 2's complement.
+ currArg = -currArg;
+ argText = (currAbsArg - 1).toString(16);
+ var buffer = [];
+ for (var i = 0; i < argText.length; i++) {
+ buffer.push((0xF - parseInt(argText[i], 16)).toString(16));
+ }
+ argText = buffer.join('');
+ while (argText.length < argSize * 2) argText = 'f' + argText;
+ } else {
+ argText = currAbsArg.toString(16);
+ }
+ if (next == 88) {
+ prefix = prefix.toUpperCase();
+ argText = argText.toUpperCase();
+ }
+ } else if (next == 112) {
+ if (currAbsArg === 0) {
+ argText = '(nil)';
+ } else {
+ prefix = '0x';
+ argText = currAbsArg.toString(16);
+ }
+ }
+ if (precisionSet) {
+ while (argText.length < precision) {
+ argText = '0' + argText;
+ }
+ }
+ // Add sign if needed
+ if (flagAlwaysSigned) {
+ if (currArg < 0) {
+ prefix = '-' + prefix;
+ } else {
+ prefix = '+' + prefix;
+ }
+ }
+ // Add padding.
+ while (prefix.length + argText.length < width) {
+ if (flagLeftAlign) {
+ argText += ' ';
+ } else {
+ if (flagZeroPad) {
+ argText = '0' + argText;
+ } else {
+ prefix = ' ' + prefix;
+ }
+ }
+ }
+ // Insert the result into the buffer.
+ argText = prefix + argText;
+ argText.split('').forEach(function(chr) {
+ ret.push(chr.charCodeAt(0));
+ });
+ break;
+ }
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': {
+ // Float.
+ var currArg = getNextArg('double');
+ var argText;
+ if (isNaN(currArg)) {
+ argText = 'nan';
+ flagZeroPad = false;
+ } else if (!isFinite(currArg)) {
+ argText = (currArg < 0 ? '-' : '') + 'inf';
+ flagZeroPad = false;
+ } else {
+ var isGeneral = false;
+ var effectivePrecision = Math.min(precision, 20);
+ // Convert g/G to f/F or e/E, as per:
+ // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
+ if (next == 103 || next == 71) {
+ isGeneral = true;
+ precision = precision || 1;
+ var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10);
+ if (precision > exponent && exponent >= -4) {
+ next = ((next == 103) ? 'f' : 'F').charCodeAt(0);
+ precision -= exponent + 1;
+ } else {
+ next = ((next == 103) ? 'e' : 'E').charCodeAt(0);
+ precision--;
+ }
+ effectivePrecision = Math.min(precision, 20);
+ }
+ if (next == 101 || next == 69) {
+ argText = currArg.toExponential(effectivePrecision);
+ // Make sure the exponent has at least 2 digits.
+ if (/[eE][-+]\d$/.test(argText)) {
+ argText = argText.slice(0, -1) + '0' + argText.slice(-1);
+ }
+ } else if (next == 102 || next == 70) {
+ argText = currArg.toFixed(effectivePrecision);
+ if (currArg === 0 && __reallyNegative(currArg)) {
+ argText = '-' + argText;
+ }
+ }
+ var parts = argText.split('e');
+ if (isGeneral && !flagAlternative) {
+ // Discard trailing zeros and periods.
+ while (parts[0].length > 1 && parts[0].indexOf('.') != -1 &&
+ (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) {
+ parts[0] = parts[0].slice(0, -1);
+ }
+ } else {
+ // Make sure we have a period in alternative mode.
+ if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.';
+ // Zero pad until required precision.
+ while (precision > effectivePrecision++) parts[0] += '0';
+ }
+ argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : '');
+ // Capitalize 'E' if needed.
+ if (next == 69) argText = argText.toUpperCase();
+ // Add sign.
+ if (flagAlwaysSigned && currArg >= 0) {
+ argText = '+' + argText;
+ }
+ }
+ // Add padding.
+ while (argText.length < width) {
+ if (flagLeftAlign) {
+ argText += ' ';
+ } else {
+ if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) {
+ argText = argText[0] + '0' + argText.slice(1);
+ } else {
+ argText = (flagZeroPad ? '0' : ' ') + argText;
+ }
+ }
+ }
+ // Adjust case.
+ if (next < 97) argText = argText.toUpperCase();
+ // Insert the result into the buffer.
+ argText.split('').forEach(function(chr) {
+ ret.push(chr.charCodeAt(0));
+ });
+ break;
+ }
+ case 's': {
+ // String.
+ var arg = getNextArg('i8*');
+ var argLength = arg ? _strlen(arg) : '(null)'.length;
+ if (precisionSet) argLength = Math.min(argLength, precision);
+ if (!flagLeftAlign) {
+ while (argLength < width--) {
+ ret.push(32);
+ }
+ }
+ if (arg) {
+ for (var i = 0; i < argLength; i++) {
+ ret.push(HEAPU8[((arg++)|0)]);
+ }
+ } else {
+ ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true));
+ }
+ if (flagLeftAlign) {
+ while (argLength < width--) {
+ ret.push(32);
+ }
+ }
+ break;
+ }
+ case 'c': {
+ // Character.
+ if (flagLeftAlign) ret.push(getNextArg('i8'));
+ while (--width > 0) {
+ ret.push(32);
+ }
+ if (!flagLeftAlign) ret.push(getNextArg('i8'));
+ break;
+ }
+ case 'n': {
+ // Write the length written so far to the next parameter.
+ var ptr = getNextArg('i32*');
+ HEAP32[((ptr)>>2)]=ret.length
+ break;
+ }
+ case '%': {
+ // Literal percent sign.
+ ret.push(curr);
+ break;
+ }
+ default: {
+ // Unknown specifiers remain untouched.
+ for (var i = startTextIndex; i < textIndex + 2; i++) {
+ ret.push(HEAP8[(i)]);
+ }
+ }
+ }
+ textIndex += 2;
+ // TODO: Support a/A (hex float) and m (last error) specifiers.
+ // TODO: Support %1${specifier} for arg selection.
+ } else {
+ ret.push(curr);
+ textIndex += 1;
+ }
+ }
+ return ret;
+ }function _fprintf(stream, format, varargs) {
+ // int fprintf(FILE *restrict stream, const char *restrict format, ...);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
+ var result = __formatString(format, varargs);
+ var stack = Runtime.stackSave();
+ var ret = _fwrite(allocate(result, 'i8', ALLOC_STACK), 1, result.length, stream);
+ Runtime.stackRestore(stack);
+ return ret;
+ }
+ function ___assert_func(filename, line, func, condition) {
+ throw 'Assertion failed: ' + (condition ? Pointer_stringify(condition) : 'unknown condition') + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function'] + ' at ' + new Error().stack;
+ }
+ function _strdup(ptr) {
+ var len = _strlen(ptr);
+ var newStr = _malloc(len + 1);
+ _memcpy(newStr, ptr, len);
+ HEAP8[(((newStr)+(len))|0)]=0;
+ return newStr;
+ }
+ function _snprintf(s, n, format, varargs) {
+ // int snprintf(char *restrict s, size_t n, const char *restrict format, ...);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
+ var result = __formatString(format, varargs);
+ var limit = (n === undefined) ? result.length
+ : Math.min(result.length, Math.max(n - 1, 0));
+ if (s < 0) {
+ s = -s;
+ var buf = _malloc(limit+1);
+ HEAP32[((s)>>2)]=buf;
+ s = buf;
+ }
+ for (var i = 0; i < limit; i++) {
+ HEAP8[(((s)+(i))|0)]=result[i];
+ }
+ if (limit < n || (n === undefined)) HEAP8[(((s)+(i))|0)]=0;
+ return result.length;
+ }function _sprintf(s, format, varargs) {
+ // int sprintf(char *restrict s, const char *restrict format, ...);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/printf.html
+ return _snprintf(s, undefined, format, varargs);
+ }
+ function _setlocale(category, locale) {
+ if (!_setlocale.ret) _setlocale.ret = allocate([0], 'i8', ALLOC_NORMAL);
+ return _setlocale.ret;
+ }
+ Module["_memset"] = _memset;var _llvm_memset_p0i8_i32=_memset;
+ function __isFloat(text) {
+ return !!(/^[+-]?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)?$/.exec(text));
+ }function __scanString(format, get, unget, varargs) {
+ if (!__scanString.whiteSpace) {
+ __scanString.whiteSpace = {};
+ __scanString.whiteSpace[32] = 1;
+ __scanString.whiteSpace[9] = 1;
+ __scanString.whiteSpace[10] = 1;
+ __scanString.whiteSpace[' '] = 1;
+ __scanString.whiteSpace['\t'] = 1;
+ __scanString.whiteSpace['\n'] = 1;
+ }
+ // Supports %x, %4x, %d.%d, %lld, %s, %f, %lf.
+ // TODO: Support all format specifiers.
+ format = Pointer_stringify(format);
+ var soFar = 0;
+ if (format.indexOf('%n') >= 0) {
+ // need to track soFar
+ var _get = get;
+ get = function() {
+ soFar++;
+ return _get();
+ }
+ var _unget = unget;
+ unget = function() {
+ soFar--;
+ return _unget();
+ }
+ }
+ var formatIndex = 0;
+ var argsi = 0;
+ var fields = 0;
+ var argIndex = 0;
+ var next;
+ mainLoop:
+ for (var formatIndex = 0; formatIndex < format.length;) {
+ if (format[formatIndex] === '%' && format[formatIndex+1] == 'n') {
+ var argPtr = HEAP32[(((varargs)+(argIndex))>>2)];
+ argIndex += Runtime.getAlignSize('void*', null, true);
+ HEAP32[((argPtr)>>2)]=soFar;
+ formatIndex += 2;
+ continue;
+ }
+ // TODO: Support strings like "%5c" etc.
+ if (format[formatIndex] === '%' && format[formatIndex+1] == 'c') {
+ var argPtr = HEAP32[(((varargs)+(argIndex))>>2)];
+ argIndex += Runtime.getAlignSize('void*', null, true);
+ fields++;
+ next = get();
+ HEAP8[(argPtr)]=next
+ formatIndex += 2;
+ continue;
+ }
+ // remove whitespace
+ while (1) {
+ next = get();
+ if (next == 0) return fields;
+ if (!(next in __scanString.whiteSpace)) break;
+ }
+ unget();
+ if (format[formatIndex] === '%') {
+ formatIndex++;
+ var suppressAssignment = false;
+ if (format[formatIndex] == '*') {
+ suppressAssignment = true;
+ formatIndex++;
+ }
+ var maxSpecifierStart = formatIndex;
+ while (format[formatIndex].charCodeAt(0) >= 48 &&
+ format[formatIndex].charCodeAt(0) <= 57) {
+ formatIndex++;
+ }
+ var max_;
+ if (formatIndex != maxSpecifierStart) {
+ max_ = parseInt(format.slice(maxSpecifierStart, formatIndex), 10);
+ }
+ var long_ = false;
+ var half = false;
+ var longLong = false;
+ if (format[formatIndex] == 'l') {
+ long_ = true;
+ formatIndex++;
+ if(format[formatIndex] == 'l') {
+ longLong = true;
+ formatIndex++;
+ }
+ } else if (format[formatIndex] == 'h') {
+ half = true;
+ formatIndex++;
+ }
+ var type = format[formatIndex];
+ formatIndex++;
+ var curr = 0;
+ var buffer = [];
+ // Read characters according to the format. floats are trickier, they may be in an unfloat state in the middle, then be a valid float later
+ if (type == 'f' || type == 'e' || type == 'g' || type == 'E') {
+ var last = 0;
+ next = get();
+ while (next > 0) {
+ buffer.push(String.fromCharCode(next));
+ if (__isFloat(buffer.join(''))) {
+ last = buffer.length;
+ }
+ next = get();
+ }
+ for (var i = 0; i < buffer.length - last + 1; i++) {
+ unget();
+ }
+ buffer.length = last;
+ } else {
+ next = get();
+ var first = true;
+ while ((curr < max_ || isNaN(max_)) && next > 0) {
+ if (!(next in __scanString.whiteSpace) && // stop on whitespace
+ (type == 's' ||
+ ((type === 'd' || type == 'u' || type == 'i') && ((next >= 48 && next <= 57) ||
+ (first && next == 45))) ||
+ (type === 'x' && (next >= 48 && next <= 57 ||
+ next >= 97 && next <= 102 ||
+ next >= 65 && next <= 70))) &&
+ (formatIndex >= format.length || next !== format[formatIndex].charCodeAt(0))) { // Stop when we read something that is coming up
+ buffer.push(String.fromCharCode(next));
+ next = get();
+ curr++;
+ first = false;
+ } else {
+ break;
+ }
+ }
+ unget();
+ }
+ if (buffer.length === 0) return 0; // Failure.
+ if (suppressAssignment) continue;
+ var text = buffer.join('');
+ var argPtr = HEAP32[(((varargs)+(argIndex))>>2)];
+ argIndex += Runtime.getAlignSize('void*', null, true);
+ switch (type) {
+ case 'd': case 'u': case 'i':
+ if (half) {
+ HEAP16[((argPtr)>>1)]=parseInt(text, 10);
+ } else if(longLong) {
+ (tempI64 = [parseInt(text, 10)>>>0,Math.min(Math.floor((parseInt(text, 10))/(+(4294967296))), (+(4294967295)))>>>0],HEAP32[((argPtr)>>2)]=tempI64[0],HEAP32[(((argPtr)+(4))>>2)]=tempI64[1]);
+ } else {
+ HEAP32[((argPtr)>>2)]=parseInt(text, 10);
+ }
+ break;
+ case 'x':
+ HEAP32[((argPtr)>>2)]=parseInt(text, 16)
+ break;
+ case 'f':
+ case 'e':
+ case 'g':
+ case 'E':
+ // fallthrough intended
+ if (long_) {
+ HEAPF64[((argPtr)>>3)]=parseFloat(text)
+ } else {
+ HEAPF32[((argPtr)>>2)]=parseFloat(text)
+ }
+ break;
+ case 's':
+ var array = intArrayFromString(text);
+ for (var j = 0; j < array.length; j++) {
+ HEAP8[(((argPtr)+(j))|0)]=array[j]
+ }
+ break;
+ }
+ fields++;
+ } else if (format[formatIndex] in __scanString.whiteSpace) {
+ next = get();
+ while (next in __scanString.whiteSpace) {
+ if (next <= 0) break mainLoop; // End of input.
+ next = get();
+ }
+ unget(next);
+ formatIndex++;
+ } else {
+ // Not a specifier.
+ next = get();
+ if (format[formatIndex].charCodeAt(0) !== next) {
+ unget(next);
+ break mainLoop;
+ }
+ formatIndex++;
+ }
+ }
+ return fields;
+ }function _sscanf(s, format, varargs) {
+ // int sscanf(const char *restrict s, const char *restrict format, ... );
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
+ var index = 0;
+ var get = function() { return HEAP8[(((s)+(index++))|0)]; };
+ var unget = function() { index--; };
+ return __scanString(format, get, unget, varargs);
+ }
+ var ___strtok_state=0;
+ function _strtok_r(s, delim, lasts) {
+ var skip_leading_delim = 1;
+ var spanp;
+ var c, sc;
+ var tok;
+ if (s == 0 && (s = getValue(lasts, 'i8*')) == 0) {
+ return 0;
+ }
+ cont: while (1) {
+ c = getValue(s++, 'i8');
+ for (spanp = delim; (sc = getValue(spanp++, 'i8')) != 0;) {
+ if (c == sc) {
+ if (skip_leading_delim) {
+ continue cont;
+ } else {
+ setValue(lasts, s, 'i8*');
+ setValue(s - 1, 0, 'i8');
+ return s - 1;
+ }
+ }
+ }
+ break;
+ }
+ if (c == 0) {
+ setValue(lasts, 0, 'i8*');
+ return 0;
+ }
+ tok = s - 1;
+ for (;;) {
+ c = getValue(s++, 'i8');
+ spanp = delim;
+ do {
+ if ((sc = getValue(spanp++, 'i8')) == c) {
+ if (c == 0) {
+ s = 0;
+ } else {
+ setValue(s - 1, 0, 'i8');
+ }
+ setValue(lasts, s, 'i8*');
+ return tok;
+ }
+ } while (sc != 0);
+ }
+ abort('strtok_r error!');
+ }function _strtok(s, delim) {
+ return _strtok_r(s, delim, ___strtok_state);
+ }
+ function _isspace(chr) {
+ return chr in { 32: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0 };
+ }
+ Module["_strcpy"] = _strcpy;
+ Module["_strcat"] = _strcat;
+ function _strchr(ptr, chr) {
+ ptr--;
+ do {
+ ptr++;
+ var val = HEAP8[(ptr)];
+ if (val == chr) return ptr;
+ } while (val);
+ return 0;
+ }
+ var _cos=Math.cos;
+ var _sin=Math.sin;
+ var _atan2=Math.atan2;
+ function __parseInt(str, endptr, base, min, max, bits, unsign) {
+ // Skip space.
+ while (_isspace(HEAP8[(str)])) str++;
+ // Check for a plus/minus sign.
+ var multiplier = 1;
+ if (HEAP8[(str)] == 45) {
+ multiplier = -1;
+ str++;
+ } else if (HEAP8[(str)] == 43) {
+ str++;
+ }
+ // Find base.
+ var finalBase = base;
+ if (!finalBase) {
+ if (HEAP8[(str)] == 48) {
+ if (HEAP8[((str+1)|0)] == 120 ||
+ HEAP8[((str+1)|0)] == 88) {
+ finalBase = 16;
+ str += 2;
+ } else {
+ finalBase = 8;
+ str++;
+ }
+ }
+ }
+ if (!finalBase) finalBase = 10;
+ // Get digits.
+ var chr;
+ var ret = 0;
+ while ((chr = HEAP8[(str)]) != 0) {
+ var digit = parseInt(String.fromCharCode(chr), finalBase);
+ if (isNaN(digit)) {
+ break;
+ } else {
+ ret = ret * finalBase + digit;
+ str++;
+ }
+ }
+ // Apply sign.
+ ret *= multiplier;
+ // Set end pointer.
+ if (endptr) {
+ HEAP32[((endptr)>>2)]=str
+ }
+ // Unsign if needed.
+ if (unsign) {
+ if (Math.abs(ret) > max) {
+ ret = max;
+ ___setErrNo(ERRNO_CODES.ERANGE);
+ } else {
+ ret = unSign(ret, bits);
+ }
+ }
+ // Validate range.
+ if (ret > max || ret < min) {
+ ret = ret > max ? max : min;
+ ___setErrNo(ERRNO_CODES.ERANGE);
+ }
+ if (bits == 64) {
+ return ((asm.setTempRet0(Math.min(Math.floor((ret)/(+(4294967296))), (+(4294967295)))>>>0),ret>>>0)|0);
+ }
+ return ret;
+ }function _strtol(str, endptr, base) {
+ return __parseInt(str, endptr, base, -2147483648, 2147483647, 32); // LONG_MIN, LONG_MAX.
+ }function _atoi(ptr) {
+ return _strtol(ptr, null, 10);
+ }
+ function _pread(fildes, buf, nbyte, offset) {
+ // ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html
+ var stream = FS.streams[fildes];
+ if (!stream || stream.object.isDevice) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ } else if (!stream.isRead) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ } else if (stream.object.isFolder) {
+ ___setErrNo(ERRNO_CODES.EISDIR);
+ return -1;
+ } else if (nbyte < 0 || offset < 0) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ } else {
+ var bytesRead = 0;
+ while (stream.ungotten.length && nbyte > 0) {
+ HEAP8[((buf++)|0)]=stream.ungotten.pop()
+ nbyte--;
+ bytesRead++;
+ }
+ var contents = stream.object.contents;
+ var size = Math.min(contents.length - offset, nbyte);
+ if (contents.subarray) { // typed array
+ HEAPU8.set(contents.subarray(offset, offset+size), buf);
+ } else
+ if (contents.slice) { // normal array
+ for (var i = 0; i < size; i++) {
+ HEAP8[(((buf)+(i))|0)]=contents[offset + i]
+ }
+ } else {
+ for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR
+ HEAP8[(((buf)+(i))|0)]=contents.get(offset + i)
+ }
+ }
+ bytesRead += size;
+ return bytesRead;
+ }
+ }function _read(fildes, buf, nbyte) {
+ // ssize_t read(int fildes, void *buf, size_t nbyte);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/read.html
+ var stream = FS.streams[fildes];
+ if (!stream) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ } else if (!stream.isRead) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ } else if (nbyte < 0) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ } else {
+ var bytesRead;
+ if (stream.object.isDevice) {
+ if (stream.object.input) {
+ bytesRead = 0;
+ while (stream.ungotten.length && nbyte > 0) {
+ HEAP8[((buf++)|0)]=stream.ungotten.pop()
+ nbyte--;
+ bytesRead++;
+ }
+ for (var i = 0; i < nbyte; i++) {
+ try {
+ var result = stream.object.input();
+ } catch (e) {
+ ___setErrNo(ERRNO_CODES.EIO);
+ return -1;
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ HEAP8[(((buf)+(i))|0)]=result
+ }
+ return bytesRead;
+ } else {
+ ___setErrNo(ERRNO_CODES.ENXIO);
+ return -1;
+ }
+ } else {
+ var ungotSize = stream.ungotten.length;
+ bytesRead = _pread(fildes, buf, nbyte, stream.position);
+ if (bytesRead != -1) {
+ stream.position += (stream.ungotten.length - ungotSize) + bytesRead;
+ }
+ return bytesRead;
+ }
+ }
+ }function _fgetc(stream) {
+ // int fgetc(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgetc.html
+ if (!FS.streams[stream]) return -1;
+ var streamObj = FS.streams[stream];
+ if (streamObj.eof || streamObj.error) return -1;
+ var ret = _read(stream, _fgetc.ret, 1);
+ if (ret == 0) {
+ streamObj.eof = true;
+ return -1;
+ } else if (ret == -1) {
+ streamObj.error = true;
+ return -1;
+ } else {
+ return HEAPU8[((_fgetc.ret)|0)];
+ }
+ }function _fgets(s, n, stream) {
+ // char *fgets(char *restrict s, int n, FILE *restrict stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fgets.html
+ if (!FS.streams[stream]) return 0;
+ var streamObj = FS.streams[stream];
+ if (streamObj.error || streamObj.eof) return 0;
+ var byte_;
+ for (var i = 0; i < n - 1 && byte_ != 10; i++) {
+ byte_ = _fgetc(stream);
+ if (byte_ == -1) {
+ if (streamObj.error || (streamObj.eof && i == 0)) return 0;
+ else if (streamObj.eof) break;
+ }
+ HEAP8[(((s)+(i))|0)]=byte_
+ }
+ HEAP8[(((s)+(i))|0)]=0
+ return s;
+ }
+ function _strrchr(ptr, chr) {
+ var ptr2 = ptr + _strlen(ptr);
+ do {
+ if (HEAP8[(ptr2)] == chr) return ptr2;
+ ptr2--;
+ } while (ptr2 >= ptr);
+ return 0;
+ }
+ function _access(path, amode) {
+ // int access(const char *path, int amode);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/access.html
+ path = Pointer_stringify(path);
+ var target = FS.findObject(path);
+ if (target === null) return -1;
+ if ((amode & 2 && !target.write) || // W_OK.
+ ((amode & 1 || amode & 4) && !target.read)) { // X_OK, R_OK.
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ var _fabs=Math.abs;
+ Module["_strncpy"] = _strncpy;
+ function _bsearch(key, base, num, size, compar) {
+ var cmp = function(x, y) {
+ return Runtime.dynCall('iii', compar, [x, y])
+ };
+ var left = 0;
+ var right = num;
+ var mid, test, addr;
+ while (left < right) {
+ mid = (left + right) >>> 1;
+ addr = base + (mid * size);
+ test = cmp(key, addr);
+ if (test < 0) {
+ right = mid;
+ } else if (test > 0) {
+ left = mid + 1;
+ } else {
+ return addr;
+ }
+ }
+ return 0;
+ }
+ function __exit(status) {
+ // void _exit(int status);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html
+ function ExitStatus() {
+ this.name = "ExitStatus";
+ this.message = "Program terminated with exit(" + status + ")";
+ this.status = status;
+ Module.print('Exit Status: ' + status);
+ };
+ ExitStatus.prototype = new Error();
+ ExitStatus.prototype.constructor = ExitStatus;
+ exitRuntime();
+ ABORT = true;
+ throw new ExitStatus();
+ }function _exit(status) {
+ __exit(status);
+ }
+ Module["_tolower"] = _tolower;
+ function _rand() {
+ return Math.floor(Math.random()*0x80000000);
+ }
+ function _abort() {
+ ABORT = true;
+ throw 'abort() at ' + (new Error().stack);
+ }
+ function _toupper(chr) {
+ if (chr >= 97 && chr <= 122) {
+ return chr - 97 + 65;
+ } else {
+ return chr;
+ }
+ }
+ function _fputc(c, stream) {
+ // int fputc(int c, FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fputc.html
+ var chr = unSign(c & 0xFF);
+ HEAP8[((_fputc.ret)|0)]=chr
+ var ret = _write(stream, _fputc.ret, 1);
+ if (ret == -1) {
+ if (FS.streams[stream]) FS.streams[stream].error = true;
+ return -1;
+ } else {
+ return chr;
+ }
+ }
+ function _hypot(a, b) {
+ return Math.sqrt(a*a + b*b);
+ }
+ function _isupper(chr) {
+ return chr >= 65 && chr <= 90;
+ }
+ var ___dirent_struct_layout={__size__:1040,d_ino:0,d_name:4,d_off:1028,d_reclen:1032,d_type:1036};function _open(path, oflag, varargs) {
+ // int open(const char *path, int oflag, ...);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html
+ // NOTE: This implementation tries to mimic glibc rather than strictly
+ // following the POSIX standard.
+ var mode = HEAP32[((varargs)>>2)];
+ // Simplify flags.
+ var accessMode = oflag & 3;
+ var isWrite = accessMode != 0;
+ var isRead = accessMode != 1;
+ var isCreate = Boolean(oflag & 512);
+ var isExistCheck = Boolean(oflag & 2048);
+ var isTruncate = Boolean(oflag & 1024);
+ var isAppend = Boolean(oflag & 8);
+ // Verify path.
+ var origPath = path;
+ path = FS.analyzePath(Pointer_stringify(path));
+ if (!path.parentExists) {
+ ___setErrNo(path.error);
+ return -1;
+ }
+ var target = path.object || null;
+ var finalPath;
+ // Verify the file exists, create if needed and allowed.
+ if (target) {
+ if (isCreate && isExistCheck) {
+ ___setErrNo(ERRNO_CODES.EEXIST);
+ return -1;
+ }
+ if ((isWrite || isCreate || isTruncate) && target.isFolder) {
+ ___setErrNo(ERRNO_CODES.EISDIR);
+ return -1;
+ }
+ if (isRead && !target.read || isWrite && !target.write) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ }
+ if (isTruncate && !target.isDevice) {
+ target.contents = [];
+ } else {
+ if (!FS.forceLoadFile(target)) {
+ ___setErrNo(ERRNO_CODES.EIO);
+ return -1;
+ }
+ }
+ finalPath = path.path;
+ } else {
+ if (!isCreate) {
+ ___setErrNo(ERRNO_CODES.ENOENT);
+ return -1;
+ }
+ if (!path.parentObject.write) {
+ ___setErrNo(ERRNO_CODES.EACCES);
+ return -1;
+ }
+ target = FS.createDataFile(path.parentObject, path.name, [],
+ mode & 0x100, mode & 0x80); // S_IRUSR, S_IWUSR.
+ finalPath = path.parentPath + '/' + path.name;
+ }
+ // Actually create an open stream.
+ var id = FS.streams.length; // Keep dense
+ if (target.isFolder) {
+ var entryBuffer = 0;
+ if (___dirent_struct_layout) {
+ entryBuffer = _malloc(___dirent_struct_layout.__size__);
+ }
+ var contents = [];
+ for (var key in target.contents) contents.push(key);
+ FS.streams[id] = {
+ path: finalPath,
+ object: target,
+ // An index into contents. Special values: -2 is ".", -1 is "..".
+ position: -2,
+ isRead: true,
+ isWrite: false,
+ isAppend: false,
+ error: false,
+ eof: false,
+ ungotten: [],
+ // Folder-specific properties:
+ // Remember the contents at the time of opening in an array, so we can
+ // seek between them relying on a single order.
+ contents: contents,
+ // Each stream has its own area for readdir() returns.
+ currentEntry: entryBuffer
+ };
+ } else {
+ FS.streams[id] = {
+ path: finalPath,
+ object: target,
+ position: 0,
+ isRead: isRead,
+ isWrite: isWrite,
+ isAppend: isAppend,
+ error: false,
+ eof: false,
+ ungotten: []
+ };
+ }
+ return id;
+ }function _fopen(filename, mode) {
+ // FILE *fopen(const char *restrict filename, const char *restrict mode);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fopen.html
+ var flags;
+ mode = Pointer_stringify(mode);
+ if (mode[0] == 'r') {
+ if (mode.indexOf('+') != -1) {
+ flags = 2;
+ } else {
+ flags = 0;
+ }
+ } else if (mode[0] == 'w') {
+ if (mode.indexOf('+') != -1) {
+ flags = 2;
+ } else {
+ flags = 1;
+ }
+ flags |= 512;
+ flags |= 1024;
+ } else if (mode[0] == 'a') {
+ if (mode.indexOf('+') != -1) {
+ flags = 2;
+ } else {
+ flags = 1;
+ }
+ flags |= 512;
+ flags |= 8;
+ } else {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return 0;
+ }
+ var ret = _open(filename, flags, allocate([0x1FF, 0, 0, 0], 'i32', ALLOC_STACK)); // All creation permissions.
+ return (ret == -1) ? 0 : ret;
+ }
+ function _close(fildes) {
+ // int close(int fildes);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/close.html
+ if (FS.streams[fildes]) {
+ if (FS.streams[fildes].currentEntry) {
+ _free(FS.streams[fildes].currentEntry);
+ }
+ FS.streams[fildes] = null;
+ return 0;
+ } else {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ }
+ function _fsync(fildes) {
+ // int fsync(int fildes);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fsync.html
+ if (FS.streams[fildes]) {
+ // We write directly to the file system, so there's nothing to do here.
+ return 0;
+ } else {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ }function _fclose(stream) {
+ // int fclose(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fclose.html
+ _fsync(stream);
+ return _close(stream);
+ }
+ function _strstr(ptr1, ptr2) {
+ var check = 0, start;
+ do {
+ if (!check) {
+ start = ptr1;
+ check = ptr2;
+ }
+ var curr1 = HEAP8[((ptr1++)|0)];
+ var curr2 = HEAP8[((check++)|0)];
+ if (curr2 == 0) return start;
+ if (curr2 != curr1) {
+ // rewind to one character after start, to find ez in eeez
+ ptr1 = start + 1;
+ check = 0;
+ }
+ } while (curr1);
+ return 0;
+ }
+ var ___stat_struct_layout={__size__:68,st_dev:0,st_ino:4,st_mode:8,st_nlink:12,st_uid:16,st_gid:20,st_rdev:24,st_size:28,st_atime:32,st_spare1:36,st_mtime:40,st_spare2:44,st_ctime:48,st_spare3:52,st_blksize:56,st_blocks:60,st_spare4:64};function _stat(path, buf, dontResolveLastLink) {
+ // http://pubs.opengroup.org/onlinepubs/7908799/xsh/stat.html
+ // int stat(const char *path, struct stat *buf);
+ // NOTE: dontResolveLastLink is a shortcut for lstat(). It should never be
+ // used in client code.
+ var obj = FS.findObject(Pointer_stringify(path), dontResolveLastLink);
+ if (obj === null || !FS.forceLoadFile(obj)) return -1;
+ var offsets = ___stat_struct_layout;
+ // Constants.
+ HEAP32[(((buf)+(offsets.st_nlink))>>2)]=1
+ HEAP32[(((buf)+(offsets.st_uid))>>2)]=0
+ HEAP32[(((buf)+(offsets.st_gid))>>2)]=0
+ HEAP32[(((buf)+(offsets.st_blksize))>>2)]=4096
+ // Variables.
+ HEAP32[(((buf)+(offsets.st_ino))>>2)]=obj.inodeNumber
+ var time = Math.floor(obj.timestamp / 1000);
+ if (offsets.st_atime === undefined) {
+ offsets.st_atime = offsets.st_atim.tv_sec;
+ offsets.st_mtime = offsets.st_mtim.tv_sec;
+ offsets.st_ctime = offsets.st_ctim.tv_sec;
+ var nanosec = (obj.timestamp % 1000) * 1000;
+ HEAP32[(((buf)+(offsets.st_atim.tv_nsec))>>2)]=nanosec
+ HEAP32[(((buf)+(offsets.st_mtim.tv_nsec))>>2)]=nanosec
+ HEAP32[(((buf)+(offsets.st_ctim.tv_nsec))>>2)]=nanosec
+ }
+ HEAP32[(((buf)+(offsets.st_atime))>>2)]=time
+ HEAP32[(((buf)+(offsets.st_mtime))>>2)]=time
+ HEAP32[(((buf)+(offsets.st_ctime))>>2)]=time
+ var mode = 0;
+ var size = 0;
+ var blocks = 0;
+ var dev = 0;
+ var rdev = 0;
+ if (obj.isDevice) {
+ // Device numbers reuse inode numbers.
+ dev = rdev = obj.inodeNumber;
+ size = blocks = 0;
+ mode = 0x2000; // S_IFCHR.
+ } else {
+ dev = 1;
+ rdev = 0;
+ // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
+ // but this is not required by the standard.
+ if (obj.isFolder) {
+ size = 4096;
+ blocks = 1;
+ mode = 0x4000; // S_IFDIR.
+ } else {
+ var data = obj.contents || obj.link;
+ size = data.length;
+ blocks = Math.ceil(data.length / 4096);
+ mode = obj.link === undefined ? 0x8000 : 0xA000; // S_IFREG, S_IFLNK.
+ }
+ }
+ HEAP32[(((buf)+(offsets.st_dev))>>2)]=dev;
+ HEAP32[(((buf)+(offsets.st_rdev))>>2)]=rdev;
+ HEAP32[(((buf)+(offsets.st_size))>>2)]=size
+ HEAP32[(((buf)+(offsets.st_blocks))>>2)]=blocks
+ if (obj.read) mode |= 0x16D; // S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH.
+ if (obj.write) mode |= 0x92; // S_IWUSR | S_IWGRP | S_IWOTH.
+ HEAP32[(((buf)+(offsets.st_mode))>>2)]=mode
+ return 0;
+ }function _fstat(fildes, buf) {
+ // int fstat(int fildes, struct stat *buf);
+ // http://pubs.opengroup.org/onlinepubs/7908799/xsh/fstat.html
+ if (!FS.streams[fildes]) {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ } else {
+ var pathArray = intArrayFromString(FS.streams[fildes].path);
+ return _stat(allocate(pathArray, 'i8', ALLOC_STACK), buf);
+ }
+ }
+ function _fileno(stream) {
+ // int fileno(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fileno.html
+ // We use file descriptor numbers and FILE* streams interchangeably.
+ return stream;
+ }
+ function _lseek(fildes, offset, whence) {
+ // off_t lseek(int fildes, off_t offset, int whence);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/lseek.html
+ if (FS.streams[fildes] && !FS.streams[fildes].object.isDevice) {
+ var stream = FS.streams[fildes];
+ var position = offset;
+ if (whence === 1) { // SEEK_CUR.
+ position += stream.position;
+ } else if (whence === 2) { // SEEK_END.
+ position += stream.object.contents.length;
+ }
+ if (position < 0) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ } else {
+ stream.ungotten = [];
+ stream.position = position;
+ return position;
+ }
+ } else {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ }function _fseek(stream, offset, whence) {
+ // int fseek(FILE *stream, long offset, int whence);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fseek.html
+ var ret = _lseek(stream, offset, whence);
+ if (ret == -1) {
+ return -1;
+ } else {
+ FS.streams[stream].eof = false;
+ return 0;
+ }
+ }
+ function _fread(ptr, size, nitems, stream) {
+ // size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fread.html
+ var bytesToRead = nitems * size;
+ if (bytesToRead == 0) return 0;
+ var bytesRead = _read(stream, ptr, bytesToRead);
+ var streamObj = FS.streams[stream];
+ if (bytesRead == -1) {
+ if (streamObj) streamObj.error = true;
+ return 0;
+ } else {
+ if (bytesRead < bytesToRead) streamObj.eof = true;
+ return Math.floor(bytesRead / size);
+ }
+ }
+ var _environ=allocate(1, "i32*", ALLOC_STATIC);var ___environ=_environ;function ___buildEnvironment(env) {
+ // WARNING: Arbitrary limit!
+ var MAX_ENV_VALUES = 64;
+ var TOTAL_ENV_SIZE = 1024;
+ // Statically allocate memory for the environment.
+ var poolPtr;
+ var envPtr;
+ if (!___buildEnvironment.called) {
+ ___buildEnvironment.called = true;
+ // Set default values. Use string keys for Closure Compiler compatibility.
+ ENV['USER'] = 'root';
+ ENV['PATH'] = '/';
+ ENV['PWD'] = '/';
+ ENV['HOME'] = '/home/emscripten';
+ ENV['LANG'] = 'en_US.UTF-8';
+ ENV['_'] = './this.program';
+ // Allocate memory.
+ poolPtr = allocate(TOTAL_ENV_SIZE, 'i8', ALLOC_STATIC);
+ envPtr = allocate(MAX_ENV_VALUES * 4,
+ 'i8*', ALLOC_STATIC);
+ HEAP32[((envPtr)>>2)]=poolPtr
+ HEAP32[((_environ)>>2)]=envPtr;
+ } else {
+ envPtr = HEAP32[((_environ)>>2)];
+ poolPtr = HEAP32[((envPtr)>>2)];
+ }
+ // Collect key=value lines.
+ var strings = [];
+ var totalSize = 0;
+ for (var key in env) {
+ if (typeof env[key] === 'string') {
+ var line = key + '=' + env[key];
+ strings.push(line);
+ totalSize += line.length;
+ }
+ }
+ if (totalSize > TOTAL_ENV_SIZE) {
+ throw new Error('Environment size exceeded TOTAL_ENV_SIZE!');
+ }
+ // Make new.
+ var ptrSize = 4;
+ for (var i = 0; i < strings.length; i++) {
+ var line = strings[i];
+ for (var j = 0; j < line.length; j++) {
+ HEAP8[(((poolPtr)+(j))|0)]=line.charCodeAt(j);
+ }
+ HEAP8[(((poolPtr)+(j))|0)]=0;
+ HEAP32[(((envPtr)+(i * ptrSize))>>2)]=poolPtr;
+ poolPtr += line.length + 1;
+ }
+ HEAP32[(((envPtr)+(strings.length * ptrSize))>>2)]=0;
+ }var ENV={};function _getenv(name) {
+ // char *getenv(const char *name);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html
+ if (name === 0) return 0;
+ name = Pointer_stringify(name);
+ if (!ENV.hasOwnProperty(name)) return 0;
+ if (_getenv.ret) _free(_getenv.ret);
+ _getenv.ret = allocate(intArrayFromString(ENV[name]), 'i8', ALLOC_NORMAL);
+ return _getenv.ret;
+ }
+ function _putenv(string) {
+ // int putenv(char *string);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/putenv.html
+ // WARNING: According to the standard (and the glibc implementation), the
+ // string is taken by reference so future changes are reflected.
+ // We copy it instead, possibly breaking some uses.
+ if (string === 0) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ }
+ string = Pointer_stringify(string);
+ var splitPoint = string.indexOf('=')
+ if (string === '' || string.indexOf('=') === -1) {
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ }
+ var name = string.slice(0, splitPoint);
+ var value = string.slice(splitPoint + 1);
+ if (!(name in ENV) || ENV[name] !== value) {
+ ENV[name] = value;
+ ___buildEnvironment(ENV);
+ }
+ return 0;
+ }
+ function _freeXDot() {
+ Module['printErr']('missing function: freeXDot'); abort(-1);
+ }
+ var ___tms_struct_layout={__size__:16,tms_utime:0,tms_stime:4,tms_cutime:8,tms_cstime:12};function _times(buffer) {
+ // clock_t times(struct tms *buffer);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/times.html
+ // NOTE: This is fake, since we can't calculate real CPU time usage in JS.
+ if (buffer !== 0) {
+ _memset(buffer, 0, ___tms_struct_layout.__size__);
+ }
+ return 0;
+ }
+ var ERRNO_MESSAGES={1:"Operation not permitted",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"Input/output error",6:"No such device or address",8:"Exec format error",9:"Bad file descriptor",10:"No child processes",11:"Resource temporarily unavailable",12:"Cannot allocate memory",13:"Permission denied",14:"Bad address",16:"Device or resource busy",17:"File exists",18:"Invalid cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Inappropriate ioctl for device",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read-only file system",31:"Too many links",32:"Broken pipe",33:"Numerical argument out of domain",34:"Numerical result out of range",35:"Resource deadlock avoided",36:"File name too long",37:"No locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many levels of symbolic links",42:"No message of desired type",43:"Identifier removed",45:"Op not supported on transport endpoint",60:"Device not a stream",61:"No data available",62:"Timer expired",63:"Out of streams resources",67:"Link has been severed",71:"Protocol error",72:"Multihop attempted",74:"Bad message",75:"Value too large for defined data type",84:"Invalid or incomplete multibyte or wide character",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Protocol not supported",95:"Operation not supported",97:"Address family not supported by protocol",98:"Address already in use",99:"Cannot assign requested address",100:"Network is down",101:"Network is unreachable",102:"Network dropped connection on reset",103:"Software caused connection abort",104:"Connection reset by peer",105:"No buffer space available",106:"Transport endpoint is already connected",107:"Transport endpoint is not connected",110:"Connection timed out",111:"Connection refused",113:"No route to host",114:"Operation already in progress",115:"Operation now in progress",116:"Stale NFS file handle",122:"Disk quota exceeded",125:"Operation canceled",130:"Owner died",131:"State not recoverable"};function _strerror_r(errnum, strerrbuf, buflen) {
+ if (errnum in ERRNO_MESSAGES) {
+ if (ERRNO_MESSAGES[errnum].length > buflen - 1) {
+ return ___setErrNo(ERRNO_CODES.ERANGE);
+ } else {
+ var msg = ERRNO_MESSAGES[errnum];
+ for (var i = 0; i < msg.length; i++) {
+ HEAP8[(((strerrbuf)+(i))|0)]=msg.charCodeAt(i)
+ }
+ HEAP8[(((strerrbuf)+(i))|0)]=0
+ return 0;
+ }
+ } else {
+ return ___setErrNo(ERRNO_CODES.EINVAL);
+ }
+ }function _strerror(errnum) {
+ if (!_strerror.buffer) _strerror.buffer = _malloc(256);
+ _strerror_r(errnum, _strerror.buffer, 256);
+ return _strerror.buffer;
+ }
+ function ___errno_location() {
+ if (!___setErrNo.ret) {
+ ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL);
+ HEAP32[((___setErrNo.ret)>>2)]=0
+ }
+ return ___setErrNo.ret;
+ }var ___errno=___errno_location;
+ function _ferror(stream) {
+ // int ferror(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/ferror.html
+ return Number(FS.streams[stream] && FS.streams[stream].error);
+ }
+ function _fflush(stream) {
+ // int fflush(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html
+ var flush = function(filedes) {
+ // Right now we write all data directly, except for output devices.
+ if (FS.streams[filedes] && FS.streams[filedes].object.output) {
+ if (!FS.streams[filedes].isTerminal) { // don't flush terminals, it would cause a \n to also appear
+ FS.streams[filedes].object.output(null);
+ }
+ }
+ };
+ try {
+ if (stream === 0) {
+ for (var i = 0; i < FS.streams.length; i++) if (FS.streams[i]) flush(i);
+ } else {
+ flush(stream);
+ }
+ return 0;
+ } catch (e) {
+ ___setErrNo(ERRNO_CODES.EIO);
+ return -1;
+ }
+ }
+ var _llvm_va_start=undefined;
+ function _vsprintf(s, format, va_arg) {
+ return _sprintf(s, format, HEAP32[((va_arg)>>2)]);
+ }
+ function _llvm_va_end() {}
+ function _feof(stream) {
+ // int feof(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/feof.html
+ return Number(FS.streams[stream] && FS.streams[stream].eof);
+ }
+ var _llvm_pow_f64=Math.pow;
+ function _isalnum(chr) {
+ return (chr >= 48 && chr <= 57) ||
+ (chr >= 97 && chr <= 122) ||
+ (chr >= 65 && chr <= 90);
+ }
+ function _isalpha(chr) {
+ return (chr >= 97 && chr <= 122) ||
+ (chr >= 65 && chr <= 90);
+ }
+ function _islower(chr) {
+ return chr >= 97 && chr <= 122;
+ }
+ function _ispunct(chr) {
+ return (chr >= 33 && chr <= 47) ||
+ (chr >= 58 && chr <= 64) ||
+ (chr >= 91 && chr <= 96) ||
+ (chr >= 123 && chr <= 126);
+ }
+ function _ftell(stream) {
+ // long ftell(FILE *stream);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/ftell.html
+ if (FS.streams[stream]) {
+ stream = FS.streams[stream];
+ if (stream.object.isDevice) {
+ ___setErrNo(ERRNO_CODES.ESPIPE);
+ return -1;
+ } else {
+ return stream.position;
+ }
+ } else {
+ ___setErrNo(ERRNO_CODES.EBADF);
+ return -1;
+ }
+ }
+ function _vfprintf(s, f, va_arg) {
+ return _fprintf(s, f, HEAP32[((va_arg)>>2)]);
+ }
+ function _tmpnam(s, dir, prefix) {
+ // char *tmpnam(char *s);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/tmpnam.html
+ // NOTE: The dir and prefix arguments are for internal use only.
+ var folder = FS.findObject(dir || '/tmp');
+ if (!folder || !folder.isFolder) {
+ dir = '/tmp';
+ folder = FS.findObject(dir);
+ if (!folder || !folder.isFolder) return 0;
+ }
+ var name = prefix || 'file';
+ do {
+ name += String.fromCharCode(65 + Math.floor(Math.random() * 25));
+ } while (name in folder.contents);
+ var result = dir + '/' + name;
+ if (!_tmpnam.buffer) _tmpnam.buffer = _malloc(256);
+ if (!s) s = _tmpnam.buffer;
+ for (var i = 0; i < result.length; i++) {
+ HEAP8[(((s)+(i))|0)]=result.charCodeAt(i);
+ }
+ HEAP8[(((s)+(i))|0)]=0;
+ return s;
+ }function _tmpfile() {
+ // FILE *tmpfile(void);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/tmpfile.html
+ // TODO: Delete the created file on closing.
+ if (_tmpfile.mode) {
+ _tmpfile.mode = allocate(intArrayFromString('w+'), 'i8', ALLOC_NORMAL);
+ }
+ return _fopen(_tmpnam(0), _tmpfile.mode);
+ }
+ function _vsnprintf(s, n, format, va_arg) {
+ return _snprintf(s, n, format, HEAP32[((va_arg)>>2)]);
+ }
+ function _iscntrl(chr) {
+ return (0 <= chr && chr <= 0x1F) || chr === 0x7F;
+ }
+ function _qsort(base, num, size, cmp) {
+ if (num == 0 || size == 0) return;
+ // forward calls to the JavaScript sort method
+ // first, sort the items logically
+ var comparator = function(x, y) {
+ return Runtime.dynCall('iii', cmp, [x, y]);
+ }
+ var keys = [];
+ for (var i = 0; i < num; i++) keys.push(i);
+ keys.sort(function(a, b) {
+ return comparator(base+a*size, base+b*size);
+ });
+ // apply the sort
+ var temp = _malloc(num*size);
+ _memcpy(temp, base, num*size);
+ for (var i = 0; i < num; i++) {
+ if (keys[i] == i) continue; // already in place
+ _memcpy(base+i*size, temp+keys[i]*size, size);
+ }
+ _free(temp);
+ }
+ var _ceil=Math.ceil;
+ function _bcopy() {
+ Module['printErr']('missing function: bcopy'); abort(-1);
+ }
+ function _time(ptr) {
+ var ret = Math.floor(Date.now()/1000);
+ if (ptr) {
+ HEAP32[((ptr)>>2)]=ret
+ }
+ return ret;
+ }
+ function _srand(seed) {}
+ function _sysconf(name) {
+ // long sysconf(int name);
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html
+ switch(name) {
+ case 8: return PAGE_SIZE;
+ case 54:
+ case 56:
+ case 21:
+ case 61:
+ case 63:
+ case 22:
+ case 67:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 69:
+ case 28:
+ case 101:
+ case 70:
+ case 71:
+ case 29:
+ case 30:
+ case 199:
+ case 75:
+ case 76:
+ case 32:
+ case 43:
+ case 44:
+ case 80:
+ case 46:
+ case 47:
+ case 45:
+ case 48:
+ case 49:
+ case 42:
+ case 82:
+ case 33:
+ case 7:
+ case 108:
+ case 109:
+ case 107:
+ case 112:
+ case 119:
+ case 121:
+ return 200809;
+ case 13:
+ case 104:
+ case 94:
+ case 95:
+ case 34:
+ case 35:
+ case 77:
+ case 81:
+ case 83:
+ case 84:
+ case 85:
+ case 86:
+ case 87:
+ case 88:
+ case 89:
+ case 90:
+ case 91:
+ case 94:
+ case 95:
+ case 110:
+ case 111:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 120:
+ case 40:
+ case 16:
+ case 79:
+ case 19:
+ return -1;
+ case 92:
+ case 93:
+ case 5:
+ case 72:
+ case 6:
+ case 74:
+ case 92:
+ case 93:
+ case 96:
+ case 97:
+ case 98:
+ case 99:
+ case 102:
+ case 103:
+ case 105:
+ return 1;
+ case 38:
+ case 66:
+ case 50:
+ case 51:
+ case 4:
+ return 1024;
+ case 15:
+ case 64:
+ case 41:
+ return 32;
+ case 55:
+ case 37:
+ case 17:
+ return 2147483647;
+ case 18:
+ case 1:
+ return 47839;
+ case 59:
+ case 57:
+ return 99;
+ case 68:
+ case 58:
+ return 2048;
+ case 0: return 2097152;
+ case 3: return 65536;
+ case 14: return 32768;
+ case 73: return 32767;
+ case 39: return 16384;
+ case 60: return 1000;
+ case 106: return 700;
+ case 52: return 256;
+ case 62: return 255;
+ case 2: return 100;
+ case 65: return 64;
+ case 36: return 20;
+ case 100: return 16;
+ case 20: return 6;
+ case 53: return 4;
+ case 10: return 1;
+ }
+ ___setErrNo(ERRNO_CODES.EINVAL);
+ return -1;
+ }
+ function _sbrk(bytes) {
+ // Implement a Linux-like 'memory area' for our 'process'.
+ // Changes the size of the memory area by |bytes|; returns the
+ // address of the previous top ('break') of the memory area
+ // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP
+ var self = _sbrk;
+ if (!self.called) {
+ DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned
+ self.called = true;
+ assert(Runtime.dynamicAlloc);
+ self.alloc = Runtime.dynamicAlloc;
+ Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') };
+ }
+ var ret = DYNAMICTOP;
+ if (bytes != 0) self.alloc(bytes);
+ return ret; // Previous break location.
+ }
+ var _llvm_memset_p0i8_i64=_memset;
+ Module["_memmove"] = _memmove;var _llvm_memmove_p0i8_p0i8_i32=_memmove;
+ var Browser={mainLoop:{scheduler:null,shouldPause:false,paused:false,queue:[],pause:function () {
+ Browser.mainLoop.shouldPause = true;
+ },resume:function () {
+ if (Browser.mainLoop.paused) {
+ Browser.mainLoop.paused = false;
+ Browser.mainLoop.scheduler();
+ }
+ Browser.mainLoop.shouldPause = false;
+ },updateStatus:function () {
+ if (Module['setStatus']) {
+ var message = Module['statusMessage'] || 'Please wait...';
+ var remaining = Browser.mainLoop.remainingBlockers;
+ var expected = Browser.mainLoop.expectedBlockers;
+ if (remaining) {
+ if (remaining < expected) {
+ Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')');
+ } else {
+ Module['setStatus'](message);
+ }
+ } else {
+ Module['setStatus']('');
+ }
+ }
+ }},isFullScreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function () {
+ if (Browser.initted) return;
+ Browser.initted = true;
+ try {
+ new Blob();
+ Browser.hasBlobConstructor = true;
+ } catch(e) {
+ Browser.hasBlobConstructor = false;
+ console.log("warning: no blob constructor, cannot create blobs with mimetypes");
+ }
+ Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null));
+ Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : console.log("warning: cannot create object URLs");
+ // Support for plugins that can process preloaded files. You can add more of these to
+ // your app by creating and appending to Module.preloadPlugins.
+ //
+ // Each plugin is asked if it can handle a file based on the file's name. If it can,
+ // it is given the file's raw data. When it is done, it calls a callback with the file's
+ // (possibly modified) data. For example, a plugin might decompress a file, or it
+ // might create some side data structure for use later (like an Image element, etc.).
+ function getMimetype(name) {
+ return {
+ 'jpg': 'image/jpeg',
+ 'jpeg': 'image/jpeg',
+ 'png': 'image/png',
+ 'bmp': 'image/bmp',
+ 'ogg': 'audio/ogg',
+ 'wav': 'audio/wav',
+ 'mp3': 'audio/mpeg'
+ }[name.substr(name.lastIndexOf('.')+1)];
+ }
+ if (!Module["preloadPlugins"]) Module["preloadPlugins"] = [];
+ var imagePlugin = {};
+ imagePlugin['canHandle'] = function(name) {
+ return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/.exec(name);
+ };
+ imagePlugin['handle'] = function(byteArray, name, onload, onerror) {
+ var b = null;
+ if (Browser.hasBlobConstructor) {
+ try {
+ b = new Blob([byteArray], { type: getMimetype(name) });
+ } catch(e) {
+ Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder');
+ }
+ }
+ if (!b) {
+ var bb = new Browser.BlobBuilder();
+ bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range
+ b = bb.getBlob();
+ }
+ var url = Browser.URLObject.createObjectURL(b);
+ var img = new Image();
+ img.onload = function() {
+ assert(img.complete, 'Image ' + name + ' could not be decoded');
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0);
+ Module["preloadedImages"][name] = canvas;
+ Browser.URLObject.revokeObjectURL(url);
+ if (onload) onload(byteArray);
+ };
+ img.onerror = function(event) {
+ console.log('Image ' + url + ' could not be decoded');
+ if (onerror) onerror();
+ };
+ img.src = url;
+ };
+ Module['preloadPlugins'].push(imagePlugin);
+ var audioPlugin = {};
+ audioPlugin['canHandle'] = function(name) {
+ return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 };
+ };
+ audioPlugin['handle'] = function(byteArray, name, onload, onerror) {
+ var done = false;
+ function finish(audio) {
+ if (done) return;
+ done = true;
+ Module["preloadedAudios"][name] = audio;
+ if (onload) onload(byteArray);
+ }
+ function fail() {
+ if (done) return;
+ done = true;
+ Module["preloadedAudios"][name] = new Audio(); // empty shim
+ if (onerror) onerror();
+ }
+ if (Browser.hasBlobConstructor) {
+ try {
+ var b = new Blob([byteArray], { type: getMimetype(name) });
+ } catch(e) {
+ return fail();
+ }
+ var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this!
+ var audio = new Audio();
+ audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926
+ audio.onerror = function(event) {
+ if (done) return;
+ console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach');
+ function encode64(data) {
+ var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+ var PAD = '=';
+ var ret = '';
+ var leftchar = 0;
+ var leftbits = 0;
+ for (var i = 0; i < data.length; i++) {
+ leftchar = (leftchar << 8) | data[i];
+ leftbits += 8;
+ while (leftbits >= 6) {
+ var curr = (leftchar >> (leftbits-6)) & 0x3f;
+ leftbits -= 6;
+ ret += BASE[curr];
+ }
+ }
+ if (leftbits == 2) {
+ ret += BASE[(leftchar&3) << 4];
+ ret += PAD + PAD;
+ } else if (leftbits == 4) {
+ ret += BASE[(leftchar&0xf) << 2];
+ ret += PAD;
+ }
+ return ret;
+ }
+ audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray);
+ finish(audio); // we don't wait for confirmation this worked - but it's worth trying
+ };
+ audio.src = url;
+ // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
+ setTimeout(function() {
+ finish(audio); // try to use it even though it is not necessarily ready to play
+ }, 10000);
+ } else {
+ return fail();
+ }
+ };
+ Module['preloadPlugins'].push(audioPlugin);
+ // Canvas event setup
+ var canvas = Module['canvas'];
+ canvas.requestPointerLock = canvas['requestPointerLock'] ||
+ canvas['mozRequestPointerLock'] ||
+ canvas['webkitRequestPointerLock'];
+ canvas.exitPointerLock = document['exitPointerLock'] ||
+ document['mozExitPointerLock'] ||
+ document['webkitExitPointerLock'];
+ canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
+ function pointerLockChange() {
+ Browser.pointerLock = document['pointerLockElement'] === canvas ||
+ document['mozPointerLockElement'] === canvas ||
+ document['webkitPointerLockElement'] === canvas;
+ }
+ document.addEventListener('pointerlockchange', pointerLockChange, false);
+ document.addEventListener('mozpointerlockchange', pointerLockChange, false);
+ document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
+ if (Module['elementPointerLock']) {
+ canvas.addEventListener("click", function(ev) {
+ if (!Browser.pointerLock && canvas.requestPointerLock) {
+ canvas.requestPointerLock();
+ ev.preventDefault();
+ }
+ }, false);
+ }
+ },createContext:function (canvas, useWebGL, setInModule) {
+ var ctx;
+ try {
+ if (useWebGL) {
+ ctx = canvas.getContext('experimental-webgl', {
+ alpha: false
+ });
+ } else {
+ ctx = canvas.getContext('2d');
+ }
+ if (!ctx) throw ':(';
+ } catch (e) {
+ Module.print('Could not create canvas - ' + e);
+ return null;
+ }
+ if (useWebGL) {
+ // Set the background of the WebGL canvas to black
+ canvas.style.backgroundColor = "black";
+ // Warn on context loss
+ canvas.addEventListener('webglcontextlost', function(event) {
+ alert('WebGL context lost. You will need to reload the page.');
+ }, false);
+ }
+ if (setInModule) {
+ Module.ctx = ctx;
+ Module.useWebGL = useWebGL;
+ Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
+ Browser.init();
+ }
+ return ctx;
+ },destroyContext:function (canvas, useWebGL, setInModule) {},fullScreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullScreen:function (lockPointer, resizeCanvas) {
+ this.lockPointer = lockPointer;
+ this.resizeCanvas = resizeCanvas;
+ if (typeof this.lockPointer === 'undefined') this.lockPointer = true;
+ if (typeof this.resizeCanvas === 'undefined') this.resizeCanvas = false;
+ var canvas = Module['canvas'];
+ function fullScreenChange() {
+ Browser.isFullScreen = false;
+ if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] ||
+ document['mozFullScreenElement'] || document['mozFullscreenElement'] ||
+ document['fullScreenElement'] || document['fullscreenElement']) === canvas) {
+ canvas.cancelFullScreen = document['cancelFullScreen'] ||
+ document['mozCancelFullScreen'] ||
+ document['webkitCancelFullScreen'];
+ canvas.cancelFullScreen = canvas.cancelFullScreen.bind(document);
+ if (Browser.lockPointer) canvas.requestPointerLock();
+ Browser.isFullScreen = true;
+ if (Browser.resizeCanvas) Browser.setFullScreenCanvasSize();
+ } else if (Browser.resizeCanvas){
+ Browser.setWindowedCanvasSize();
+ }
+ if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen);
+ }
+ if (!this.fullScreenHandlersInstalled) {
+ this.fullScreenHandlersInstalled = true;
+ document.addEventListener('fullscreenchange', fullScreenChange, false);
+ document.addEventListener('mozfullscreenchange', fullScreenChange, false);
+ document.addEventListener('webkitfullscreenchange', fullScreenChange, false);
+ }
+ canvas.requestFullScreen = canvas['requestFullScreen'] ||
+ canvas['mozRequestFullScreen'] ||
+ (canvas['webkitRequestFullScreen'] ? function() { canvas['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null);
+ canvas.requestFullScreen();
+ },requestAnimationFrame:function (func) {
+ if (!window.requestAnimationFrame) {
+ window.requestAnimationFrame = window['requestAnimationFrame'] ||
+ window['mozRequestAnimationFrame'] ||
+ window['webkitRequestAnimationFrame'] ||
+ window['msRequestAnimationFrame'] ||
+ window['oRequestAnimationFrame'] ||
+ window['setTimeout'];
+ }
+ window.requestAnimationFrame(func);
+ },getMovementX:function (event) {
+ return event['movementX'] ||
+ event['mozMovementX'] ||
+ event['webkitMovementX'] ||
+ 0;
+ },getMovementY:function (event) {
+ return event['movementY'] ||
+ event['mozMovementY'] ||
+ event['webkitMovementY'] ||
+ 0;
+ },xhrLoad:function (url, onload, onerror) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.onload = function() {
+ if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
+ onload(xhr.response);
+ } else {
+ onerror();
+ }
+ };
+ xhr.onerror = onerror;
+ xhr.send(null);
+ },asyncLoad:function (url, onload, onerror, noRunDep) {
+ Browser.xhrLoad(url, function(arrayBuffer) {
+ assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
+ onload(new Uint8Array(arrayBuffer));
+ if (!noRunDep) removeRunDependency('al ' + url);
+ }, function(event) {
+ if (onerror) {
+ onerror();
+ } else {
+ throw 'Loading data file "' + url + '" failed.';
+ }
+ });
+ if (!noRunDep) addRunDependency('al ' + url);
+ },resizeListeners:[],updateResizeListeners:function () {
+ var canvas = Module['canvas'];
+ Browser.resizeListeners.forEach(function(listener) {
+ listener(canvas.width, canvas.height);
+ });
+ },setCanvasSize:function (width, height, noUpdates) {
+ var canvas = Module['canvas'];
+ canvas.width = width;
+ canvas.height = height;
+ if (!noUpdates) Browser.updateResizeListeners();
+ },windowedWidth:0,windowedHeight:0,setFullScreenCanvasSize:function () {
+ var canvas = Module['canvas'];
+ this.windowedWidth = canvas.width;
+ this.windowedHeight = canvas.height;
+ canvas.width = screen.width;
+ canvas.height = screen.height;
+ var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)];
+ flags = flags | 0x00800000; // set SDL_FULLSCREEN flag
+ HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags
+ Browser.updateResizeListeners();
+ },setWindowedCanvasSize:function () {
+ var canvas = Module['canvas'];
+ canvas.width = this.windowedWidth;
+ canvas.height = this.windowedHeight;
+ var flags = HEAPU32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)];
+ flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag
+ HEAP32[((SDL.screen+Runtime.QUANTUM_SIZE*0)>>2)]=flags
+ Browser.updateResizeListeners();
+ }};
+__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });__ATEXIT__.push({ func: function() { FS.quit() } });Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice;
+___strtok_state = Runtime.staticAlloc(4);
+_fgetc.ret = allocate([0], "i8", ALLOC_STATIC);
+_fputc.ret = allocate([0], "i8", ALLOC_STATIC);
+___buildEnvironment(ENV);
+Module["requestFullScreen"] = function(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) };
+ Module["requestAnimationFrame"] = function(func) { Browser.requestAnimationFrame(func) };
+ Module["pauseMainLoop"] = function() { Browser.mainLoop.pause() };
+ Module["resumeMainLoop"] = function() { Browser.mainLoop.resume() };
+STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);
+staticSealed = true; // seal the static portion of memory
+STACK_MAX = STACK_BASE + 5242880;
+DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX);
+assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY
+var Math_min = Math.min;
+function invoke_iiiii(index,a1,a2,a3,a4) {
+ try {
+ return Module.dynCall_iiiii(index,a1,a2,a3,a4);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_viiiffi(index,a1,a2,a3,a4,a5,a6) {
+ try {
+ Module.dynCall_viiiffi(index,a1,a2,a3,a4,a5,a6);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_viiiii(index,a1,a2,a3,a4,a5) {
+ try {
+ Module.dynCall_viiiii(index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_vi(index,a1) {
+ try {
+ Module.dynCall_vi(index,a1);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_vii(index,a1,a2) {
+ try {
+ Module.dynCall_vii(index,a1,a2);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_ii(index,a1) {
+ try {
+ return Module.dynCall_ii(index,a1);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_iiii(index,a1,a2,a3) {
+ try {
+ return Module.dynCall_iiii(index,a1,a2,a3);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_viii(index,a1,a2,a3) {
+ try {
+ Module.dynCall_viii(index,a1,a2,a3);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_v(index) {
+ try {
+ Module.dynCall_v(index);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9) {
+ try {
+ Module.dynCall_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) {
+ try {
+ Module.dynCall_viiiiii(index,a1,a2,a3,a4,a5,a6);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_iii(index,a1,a2) {
+ try {
+ return Module.dynCall_iii(index,a1,a2);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_iiiiii(index,a1,a2,a3,a4,a5) {
+ try {
+ return Module.dynCall_iiiiii(index,a1,a2,a3,a4,a5);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function invoke_viiii(index,a1,a2,a3,a4) {
+ try {
+ Module.dynCall_viiii(index,a1,a2,a3,a4);
+ } catch(e) {
+ if (typeof e !== 'number' && e !== 'longjmp') throw e;
+ asm.setThrew(1, 0);
+ }
+}
+function asmPrintInt(x, y) {
+ Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack);
+}
+function asmPrintFloat(x, y) {
+ Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack);
+}
+// EMSCRIPTEN_START_ASM
+var asm = (function(global, env, buffer) {
+ 'use asm';
+ var HEAP8 = new global.Int8Array(buffer);
+ var HEAP16 = new global.Int16Array(buffer);
+ var HEAP32 = new global.Int32Array(buffer);
+ var HEAPU8 = new global.Uint8Array(buffer);
+ var HEAPU16 = new global.Uint16Array(buffer);
+ var HEAPU32 = new global.Uint32Array(buffer);
+ var HEAPF32 = new global.Float32Array(buffer);
+ var HEAPF64 = new global.Float64Array(buffer);
+ var STACKTOP=env.STACKTOP|0;
+ var STACK_MAX=env.STACK_MAX|0;
+ var tempDoublePtr=env.tempDoublePtr|0;
+ var ABORT=env.ABORT|0;
+ var _stdout=env._stdout|0;
+ var _stderr=env._stderr|0;
+ var NaN=+env.NaN;
+ var Infinity=+env.Infinity;
+ var __THREW__ = 0;
+ var threwValue = 0;
+ var setjmpId = 0;
+ var undef = 0;
+ var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0;
+ var tempRet0 = 0;
+ var tempRet1 = 0;
+ var tempRet2 = 0;
+ var tempRet3 = 0;
+ var tempRet4 = 0;
+ var tempRet5 = 0;
+ var tempRet6 = 0;
+ var tempRet7 = 0;
+ var tempRet8 = 0;
+ var tempRet9 = 0;
+ var Math_floor=global.Math.floor;
+ var Math_abs=global.Math.abs;
+ var Math_sqrt=global.Math.sqrt;
+ var Math_pow=global.Math.pow;
+ var Math_cos=global.Math.cos;
+ var Math_sin=global.Math.sin;
+ var Math_tan=global.Math.tan;
+ var Math_acos=global.Math.acos;
+ var Math_asin=global.Math.asin;
+ var Math_atan=global.Math.atan;
+ var Math_atan2=global.Math.atan2;
+ var Math_exp=global.Math.exp;
+ var Math_log=global.Math.log;
+ var Math_ceil=global.Math.ceil;
+ var Math_imul=global.Math.imul;
+ var abort=env.abort;
+ var assert=env.assert;
+ var asmPrintInt=env.asmPrintInt;
+ var asmPrintFloat=env.asmPrintFloat;
+ var copyTempDouble=env.copyTempDouble;
+ var copyTempFloat=env.copyTempFloat;
+ var Math_min=env.min;
+ var invoke_iiiii=env.invoke_iiiii;
+ var invoke_viiiffi=env.invoke_viiiffi;
+ var invoke_viiiii=env.invoke_viiiii;
+ var invoke_vi=env.invoke_vi;
+ var invoke_vii=env.invoke_vii;
+ var invoke_ii=env.invoke_ii;
+ var invoke_iiii=env.invoke_iiii;
+ var invoke_viii=env.invoke_viii;
+ var invoke_v=env.invoke_v;
+ var invoke_viiiiiiiii=env.invoke_viiiiiiiii;
+ var invoke_viiiiii=env.invoke_viiiiii;
+ var invoke_iii=env.invoke_iii;
+ var invoke_iiiiii=env.invoke_iiiiii;
+ var invoke_viiii=env.invoke_viiii;
+ var _lseek=env._lseek;
+ var __scanString=env.__scanString;
+ var _fclose=env._fclose;
+ var __isFloat=env.__isFloat;
+ var _fflush=env._fflush;
+ var _strtol=env._strtol;
+ var _fputc=env._fputc;
+ var _strtok=env._strtok;
+ var _fwrite=env._fwrite;
+ var _tmpnam=env._tmpnam;
+ var _isspace=env._isspace;
+ var _read=env._read;
+ var _ceil=env._ceil;
+ var _fileno=env._fileno;
+ var _strstr=env._strstr;
+ var _fsync=env._fsync;
+ var _strcmp=env._strcmp;
+ var _strncmp=env._strncmp;
+ var _tmpfile=env._tmpfile;
+ var _snprintf=env._snprintf;
+ var _fgetc=env._fgetc;
+ var _hypot=env._hypot;
+ var _fgets=env._fgets;
+ var _close=env._close;
+ var _strchr=env._strchr;
+ var ___setErrNo=env.___setErrNo;
+ var _access=env._access;
+ var _ftell=env._ftell;
+ var _exit=env._exit;
+ var _sprintf=env._sprintf;
+ var _strrchr=env._strrchr;
+ var _ferror=env._ferror;
+ var _cos=env._cos;
+ var _putenv=env._putenv;
+ var _times=env._times;
+ var _bsearch=env._bsearch;
+ var _islower=env._islower;
+ var __exit=env.__exit;
+ var _isupper=env._isupper;
+ var _rand=env._rand;
+ var _setlocale=env._setlocale;
+ var _bcopy=env._bcopy;
+ var _toupper=env._toupper;
+ var _pread=env._pread;
+ var _fopen=env._fopen;
+ var _open=env._open;
+ var _isalnum=env._isalnum;
+ var _qsort=env._qsort;
+ var _isalpha=env._isalpha;
+ var _strdup=env._strdup;
+ var _srand=env._srand;
+ var __formatString=env.__formatString;
+ var _getenv=env._getenv;
+ var _atoi=env._atoi;
+ var _vfprintf=env._vfprintf;
+ var _llvm_pow_f64=env._llvm_pow_f64;
+ var _sbrk=env._sbrk;
+ var ___errno_location=env.___errno_location;
+ var _strerror=env._strerror;
+ var _fstat=env._fstat;
+ var __parseInt=env.__parseInt;
+ var _freeXDot=env._freeXDot;
+ var _vsprintf=env._vsprintf;
+ var _vsnprintf=env._vsnprintf;
+ var _sscanf=env._sscanf;
+ var _sysconf=env._sysconf;
+ var _fread=env._fread;
+ var _strtok_r=env._strtok_r;
+ var _abort=env._abort;
+ var _fprintf=env._fprintf;
+ var ___buildEnvironment=env.___buildEnvironment;
+ var _feof=env._feof;
+ var _statXDot=env._statXDot;
+ var _ispunct=env._ispunct;
+ var _fabs=env._fabs;
+ var __reallyNegative=env.__reallyNegative;
+ var _fseek=env._fseek;
+ var _sqrt=env._sqrt;
+ var _write=env._write;
+ var _sin=env._sin;
+ var _stat=env._stat;
+ var _parseXDotF=env._parseXDotF;
+ var _llvm_va_end=env._llvm_va_end;
+ var ___assert_func=env.___assert_func;
+ var _pwrite=env._pwrite;
+ var _strerror_r=env._strerror_r;
+ var _iscntrl=env._iscntrl;
+ var _atan2=env._atan2;
+ var _time=env._time;
+// EMSCRIPTEN_START_FUNCS
+function stackAlloc(size) {
+ size = size | 0;
+ var ret = 0;
+ ret = STACKTOP;
+ STACKTOP = STACKTOP + size | 0;
+ STACKTOP = STACKTOP + 7 >> 3 << 3;
+ return ret | 0;
+}
+function stackSave() {
+ return STACKTOP | 0;
+}
+function stackRestore(top) {
+ top = top | 0;
+ STACKTOP = top;
+}
+function setThrew(threw, value) {
+ threw = threw | 0;
+ value = value | 0;
+ if ((__THREW__ | 0) == 0) {
+ __THREW__ = threw;
+ threwValue = value;
+ }
+}
+function setTempRet0(value) {
+ value = value | 0;
+ tempRet0 = value;
+}
+function setTempRet1(value) {
+ value = value | 0;
+ tempRet1 = value;
+}
+function setTempRet2(value) {
+ value = value | 0;
+ tempRet2 = value;
+}
+function setTempRet3(value) {
+ value = value | 0;
+ tempRet3 = value;
+}
+function setTempRet4(value) {
+ value = value | 0;
+ tempRet4 = value;
+}
+function setTempRet5(value) {
+ value = value | 0;
+ tempRet5 = value;
+}
+function setTempRet6(value) {
+ value = value | 0;
+ tempRet6 = value;
+}
+function setTempRet7(value) {
+ value = value | 0;
+ tempRet7 = value;
+}
+function setTempRet8(value) {
+ value = value | 0;
+ tempRet8 = value;
+}
+function setTempRet9(value) {
+ value = value | 0;
+ tempRet9 = value;
+}
+function _dtflatten($dt) {
+ $dt = $dt | 0;
+ var $data = 0, $0 = 0, $type = 0, $1 = 0, $and = 0, $tobool = 0, $here = 0, $2 = 0, $and4 = 0, $tobool5 = 0, $_htab = 0, $3 = 0, $ntab = 0, $4 = 0, $add_ptr = 0, $cmp46 = 0, $s_049 = 0, $last_048 = 0, $list_047 = 0, $5 = 0, $tobool9 = 0, $tobool11 = 0, $right = 0, $list_1_ph = 0, $last_1_ph = 0, $last_1 = 0, $right14 = 0, $6 = 0, $tobool15 = 0, $list_2 = 0, $last_2 = 0, $incdec_ptr = 0, $cmp = 0, $and21 = 0, $tobool22 = 0, $hh25 = 0, $_head = 0, $7 = 0, $here28 = 0, $8 = 0, $tobool29 = 0, $hl40 = 0, $_left41 = 0, $9 = 0, $tobool3242 = 0, $r_0_lcssa = 0, $r_1_in35 = 0, $r_136 = 0, $tobool4137 = 0, $10 = 0, $hl44 = 0, $r_043 = 0, $right34 = 0, $11 = 0, $12 = 0, $_c34 = 0, $hl = 0, $_left = 0, $13 = 0, $tobool32 = 0, $r_139 = 0, $r_1_in38 = 0, $hl43 = 0, $_left44 = 0, $14 = 0, $tobool45 = 0, $r_0_pn_be = 0, $r_1_in = 0, $r_1 = 0, $tobool41 = 0, $t_0 = 0, $r_2 = 0, $right47 = 0, $15 = 0, $16 = 0, $_c = 0, $hl51 = 0, $_left52 = 0, $17 = 0, $tobool53 = 0, $list_3 = 0, $18 = 0, $here63 = 0, $19 = 0, $type65 = 0, $20 = 0, $or = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $data = $dt + 8 | 0;
+ $0 = HEAP32[$data >> 2] | 0;
+ $type = $0 | 0;
+ $1 = HEAP32[$type >> 2] | 0;
+ $and = $1 & 4096;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $here = $0 + 4 | 0;
+ $2 = HEAP32[$here >> 2] | 0;
+ $retval_0 = $2;
+ label = 24;
+ break;
+ case 4:
+ $and4 = $1 & 3;
+ $tobool5 = ($and4 | 0) == 0;
+ if ($tobool5) {
+ label = 13;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $_htab = $0 + 8 | 0;
+ $3 = HEAP32[$_htab >> 2] | 0;
+ $ntab = $0 + 12 | 0;
+ $4 = HEAP32[$ntab >> 2] | 0;
+ $add_ptr = $3 + ($4 << 2) | 0;
+ $cmp46 = ($4 | 0) > 0;
+ if ($cmp46) {
+ $list_047 = 0;
+ $last_048 = 0;
+ $s_049 = $3;
+ label = 6;
+ break;
+ } else {
+ $list_3 = 0;
+ label = 23;
+ break;
+ }
+ case 6:
+ $5 = HEAP32[$s_049 >> 2] | 0;
+ $tobool9 = ($5 | 0) == 0;
+ if ($tobool9) {
+ $last_2 = $last_048;
+ $list_2 = $list_047;
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $tobool11 = ($last_048 | 0) == 0;
+ if ($tobool11) {
+ $last_1_ph = $5;
+ $list_1_ph = $5;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $right = $last_048 | 0;
+ HEAP32[$right >> 2] = $5;
+ $last_1_ph = $last_048;
+ $list_1_ph = $list_047;
+ label = 9;
+ break;
+ case 9:
+ $last_1 = $last_1_ph;
+ label = 10;
+ break;
+ case 10:
+ $right14 = $last_1 | 0;
+ $6 = HEAP32[$right14 >> 2] | 0;
+ $tobool15 = ($6 | 0) == 0;
+ if ($tobool15) {
+ label = 11;
+ break;
+ } else {
+ $last_1 = $6;
+ label = 10;
+ break;
+ }
+ case 11:
+ HEAP32[$s_049 >> 2] = $last_1;
+ $last_2 = $last_1;
+ $list_2 = $list_1_ph;
+ label = 12;
+ break;
+ case 12:
+ $incdec_ptr = $s_049 + 4 | 0;
+ $cmp = $incdec_ptr >>> 0 < $add_ptr >>> 0;
+ if ($cmp) {
+ $list_047 = $list_2;
+ $last_048 = $last_2;
+ $s_049 = $incdec_ptr;
+ label = 6;
+ break;
+ } else {
+ $list_3 = $list_2;
+ label = 23;
+ break;
+ }
+ case 13:
+ $and21 = $1 & 112;
+ $tobool22 = ($and21 | 0) == 0;
+ if ($tobool22) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $hh25 = $0 + 8 | 0;
+ $_head = $hh25;
+ $7 = HEAP32[$_head >> 2] | 0;
+ $list_3 = $7;
+ label = 23;
+ break;
+ case 15:
+ $here28 = $0 + 4 | 0;
+ $8 = HEAP32[$here28 >> 2] | 0;
+ $tobool29 = ($8 | 0) == 0;
+ if ($tobool29) {
+ $list_3 = 0;
+ label = 23;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $hl40 = $8 + 4 | 0;
+ $_left41 = $hl40;
+ $9 = HEAP32[$_left41 >> 2] | 0;
+ $tobool3242 = ($9 | 0) == 0;
+ if ($tobool3242) {
+ $r_0_lcssa = $8;
+ label = 17;
+ break;
+ } else {
+ $r_043 = $8;
+ $hl44 = $hl40;
+ $10 = $9;
+ label = 18;
+ break;
+ }
+ case 17:
+ $r_1_in35 = $r_0_lcssa | 0;
+ $r_136 = HEAP32[$r_1_in35 >> 2] | 0;
+ $tobool4137 = ($r_136 | 0) == 0;
+ if ($tobool4137) {
+ $list_3 = $r_0_lcssa;
+ label = 23;
+ break;
+ } else {
+ $r_1_in38 = $r_1_in35;
+ $r_139 = $r_136;
+ label = 19;
+ break;
+ }
+ case 18:
+ $right34 = $10 | 0;
+ $11 = HEAP32[$right34 >> 2] | 0;
+ $12 = $hl44 | 0;
+ $_c34 = $11;
+ HEAP32[$12 >> 2] = $_c34;
+ HEAP32[$right34 >> 2] = $r_043;
+ $hl = $10 + 4 | 0;
+ $_left = $hl;
+ $13 = HEAP32[$_left >> 2] | 0;
+ $tobool32 = ($13 | 0) == 0;
+ if ($tobool32) {
+ $r_0_lcssa = $10;
+ label = 17;
+ break;
+ } else {
+ $r_043 = $10;
+ $hl44 = $hl;
+ $10 = $13;
+ label = 18;
+ break;
+ }
+ case 19:
+ $hl43 = $r_139 + 4 | 0;
+ $_left44 = $hl43;
+ $14 = HEAP32[$_left44 >> 2] | 0;
+ $tobool45 = ($14 | 0) == 0;
+ if ($tobool45) {
+ $r_0_pn_be = $r_139;
+ label = 20;
+ break;
+ } else {
+ $r_2 = $r_139;
+ $t_0 = $14;
+ label = 21;
+ break;
+ }
+ case 20:
+ $r_1_in = $r_0_pn_be | 0;
+ $r_1 = HEAP32[$r_1_in >> 2] | 0;
+ $tobool41 = ($r_1 | 0) == 0;
+ if ($tobool41) {
+ $list_3 = $r_0_lcssa;
+ label = 23;
+ break;
+ } else {
+ $r_1_in38 = $r_1_in;
+ $r_139 = $r_1;
+ label = 19;
+ break;
+ }
+ case 21:
+ $right47 = $t_0 | 0;
+ $15 = HEAP32[$right47 >> 2] | 0;
+ $16 = $r_2 + 4 | 0;
+ $_c = $15;
+ HEAP32[$16 >> 2] = $_c;
+ HEAP32[$right47 >> 2] = $r_2;
+ $hl51 = $t_0 + 4 | 0;
+ $_left52 = $hl51;
+ $17 = HEAP32[$_left52 >> 2] | 0;
+ $tobool53 = ($17 | 0) == 0;
+ if ($tobool53) {
+ label = 22;
+ break;
+ } else {
+ $r_2 = $t_0;
+ $t_0 = $17;
+ label = 21;
+ break;
+ }
+ case 22:
+ HEAP32[$r_1_in38 >> 2] = $t_0;
+ $r_0_pn_be = $t_0;
+ label = 20;
+ break;
+ case 23:
+ $18 = HEAP32[$data >> 2] | 0;
+ $here63 = $18 + 4 | 0;
+ HEAP32[$here63 >> 2] = $list_3;
+ $19 = HEAP32[$data >> 2] | 0;
+ $type65 = $19 | 0;
+ $20 = HEAP32[$type65 >> 2] | 0;
+ $or = $20 | 4096;
+ HEAP32[$type65 >> 2] = $or;
+ $retval_0 = $list_3;
+ label = 24;
+ break;
+ case 24:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _vizRenderFromString($string, $format) {
+ $string = $string | 0;
+ $format = $format | 0;
+ var $call = 0, $call1 = 0, $0 = 0;
+ $call = _gvContext() | 0;
+ _gvAddLibrary($call, 14400);
+ _gvAddLibrary($call, 14392);
+ $call1 = _agmemread($string) | 0;
+ $0 = $call1;
+ _gvLayout($call, $0, 163256);
+ _gvRender($call, $0, $format, HEAP32[_stdout >> 2] | 0);
+ _gvFreeLayout(0, $0);
+ _agclose($call1);
+ _gvFreeContext($call);
+ return;
+}
+function _dtclose($dt) {
+ $dt = $dt | 0;
+ var $tobool = 0, $nview = 0, $0 = 0, $cmp = 0, $disc1 = 0, $1 = 0, $eventf = 0, $2 = 0, $tobool2 = 0, $call = 0, $cmp4 = 0, $ev_0 = 0, $view = 0, $3 = 0, $tobool7 = 0, $call9 = 0, $cmp11 = 0, $meth = 0, $4 = 0, $searchf = 0, $5 = 0, $call13 = 0, $call14 = 0, $cmp15 = 0, $data = 0, $6 = 0, $ntab = 0, $7 = 0, $cmp18 = 0, $memoryf = 0, $8 = 0, $_htab = 0, $9 = 0, $10 = 0, $call21 = 0, $memoryf23 = 0, $11 = 0, $12 = 0, $13 = 0, $call25 = 0, $type = 0, $14 = 0, $cmp27 = 0, $15 = 0, $cmp32 = 0, $or_cond = 0, $memoryf34 = 0, $16 = 0, $17 = 0, $call35 = 0, $18 = 0, $tobool39 = 0, $call42 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($dt | 0) == 0;
+ if ($tobool) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $nview = $dt + 24 | 0;
+ $0 = HEAP32[$nview >> 2] | 0;
+ $cmp = ($0 | 0) > 0;
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $disc1 = $dt + 4 | 0;
+ $1 = HEAP32[$disc1 >> 2] | 0;
+ $eventf = $1 + 32 | 0;
+ $2 = HEAP32[$eventf >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ $ev_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call = FUNCTION_TABLE_iiiii[$2 & 1023]($dt, 2, 0, $1) | 0;
+ $cmp4 = ($call | 0) < 0;
+ if ($cmp4) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ $ev_0 = $call;
+ label = 6;
+ break;
+ }
+ case 6:
+ $view = $dt + 28 | 0;
+ $3 = HEAP32[$view >> 2] | 0;
+ $tobool7 = ($3 | 0) == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call9 = _dtview($dt, 0) | 0;
+ label = 8;
+ break;
+ case 8:
+ $cmp11 = ($ev_0 | 0) == 0;
+ if ($cmp11) {
+ label = 9;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 9:
+ $meth = $dt + 16 | 0;
+ $4 = HEAP32[$meth >> 2] | 0;
+ $searchf = $4 | 0;
+ $5 = HEAP32[$searchf >> 2] | 0;
+ $call13 = FUNCTION_TABLE_iiii[$5 & 1023]($dt, 0, 64) | 0;
+ $call14 = _dtsize($dt) | 0;
+ $cmp15 = ($call14 | 0) > 0;
+ if ($cmp15) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $data = $dt + 8 | 0;
+ $6 = HEAP32[$data >> 2] | 0;
+ $ntab = $6 + 12 | 0;
+ $7 = HEAP32[$ntab >> 2] | 0;
+ $cmp18 = ($7 | 0) > 0;
+ if ($cmp18) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $memoryf = $dt + 12 | 0;
+ $8 = HEAP32[$memoryf >> 2] | 0;
+ $_htab = $6 + 8 | 0;
+ $9 = HEAP32[$_htab >> 2] | 0;
+ $10 = $9;
+ $call21 = FUNCTION_TABLE_iiiii[$8 & 1023]($dt, $10, 0, $1) | 0;
+ label = 12;
+ break;
+ case 12:
+ $memoryf23 = $dt + 12 | 0;
+ $11 = HEAP32[$memoryf23 >> 2] | 0;
+ $12 = HEAP32[$data >> 2] | 0;
+ $13 = $12;
+ $call25 = FUNCTION_TABLE_iiiii[$11 & 1023]($dt, $13, 0, $1) | 0;
+ label = 13;
+ break;
+ case 13:
+ $type = $dt + 20 | 0;
+ $14 = HEAP32[$type >> 2] | 0;
+ $cmp27 = ($14 | 0) == 0;
+ if ($cmp27) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $15 = $dt;
+ _free($15);
+ label = 17;
+ break;
+ case 15:
+ $cmp32 = ($14 | 0) == 1;
+ $or_cond = $cmp11 & $cmp32;
+ if ($or_cond) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $memoryf34 = $dt + 12 | 0;
+ $16 = HEAP32[$memoryf34 >> 2] | 0;
+ $17 = $dt;
+ $call35 = FUNCTION_TABLE_iiiii[$16 & 1023]($dt, $17, 0, $1) | 0;
+ label = 17;
+ break;
+ case 17:
+ $18 = HEAP32[$eventf >> 2] | 0;
+ $tobool39 = ($18 | 0) == 0;
+ if ($tobool39) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $call42 = FUNCTION_TABLE_iiiii[$18 & 1023]($dt, 6, 0, $1) | 0;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dtdisc($dt, $disc, $type) {
+ $dt = $dt | 0;
+ $disc = $disc | 0;
+ $type = $type | 0;
+ var $disc1 = 0, $0 = 0, $tobool = 0, $memoryf = 0, $1 = 0, $memoryf3 = 0, $tobool4 = 0, $dtmemory_ = 0, $tobool8 = 0, $meth = 0, $2 = 0, $searchf11 = 0, $3 = 0, $data = 0, $4 = 0, $type12 = 0, $5 = 0, $and = 0, $tobool13 = 0, $call = 0, $eventf = 0, $6 = 0, $tobool14 = 0, $7 = 0, $call16 = 0, $cmp = 0, $memoryf20 = 0, $8 = 0, $memoryf21 = 0, $tobool22 = 0, $dtmemory_51 = 0, $9 = 0, $type27 = 0, $10 = 0, $and28 = 0, $tobool29 = 0, $and33 = 0, $tobool34 = 0, $and36 = 0, $tobool37 = 0, $and43 = 0, $tobool44 = 0, $11 = 0, $12 = 0, $and54 = 0, $tobool55 = 0, $call58 = 0, $13 = 0, $type60 = 0, $14 = 0, $and61 = 0, $15 = 0, $here = 0, $16 = 0, $size = 0, $17 = 0, $type65 = 0, $18 = 0, $and66 = 0, $tobool67 = 0, $tobool7452 = 0, $and76 = 0, $tobool77 = 0, $link = 0, $size86 = 0, $key = 0, $hashf = 0, $_htab = 0, $19 = 0, $ntab = 0, $20 = 0, $add_ptr = 0, $cmp7155 = 0, $s_056 = 0, $incdec_ptr = 0, $cmp71 = 0, $r_053 = 0, $right = 0, $21 = 0, $22 = 0, $cmp79 = 0, $obj = 0, $23 = 0, $24 = 0, $25 = 0, $idx_neg = 0, $add_ptr83 = 0, $cond85 = 0, $26 = 0, $cmp87 = 0, $27 = 0, $add_ptr89 = 0, $28 = 0, $29 = 0, $cond94 = 0, $30 = 0, $tobool95 = 0, $call98 = 0, $31 = 0, $call101 = 0, $cond103 = 0, $_hash = 0, $32 = 0, $call105 = 0, $tobool74 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $disc1 = $dt + 4 | 0;
+ $0 = HEAP32[$disc1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[$disc1 >> 2] = $disc;
+ $memoryf = $disc + 28 | 0;
+ $1 = HEAP32[$memoryf >> 2] | 0;
+ $memoryf3 = $dt + 12 | 0;
+ $tobool4 = ($1 | 0) == 0;
+ $dtmemory_ = $tobool4 ? 238 : $1;
+ HEAP32[$memoryf3 >> 2] = $dtmemory_;
+ $retval_0 = $disc;
+ label = 31;
+ break;
+ case 4:
+ $tobool8 = ($disc | 0) == 0;
+ if ($tobool8) {
+ $retval_0 = $0;
+ label = 31;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $meth = $dt + 16 | 0;
+ $2 = HEAP32[$meth >> 2] | 0;
+ $searchf11 = $2 | 0;
+ $3 = HEAP32[$searchf11 >> 2] | 0;
+ $data = $dt + 8 | 0;
+ $4 = HEAP32[$data >> 2] | 0;
+ $type12 = $4 | 0;
+ $5 = HEAP32[$type12 >> 2] | 0;
+ $and = $5 & 4096;
+ $tobool13 = ($and | 0) == 0;
+ if ($tobool13) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call = _dtrestore($dt, 0) | 0;
+ label = 7;
+ break;
+ case 7:
+ $eventf = $0 + 32 | 0;
+ $6 = HEAP32[$eventf >> 2] | 0;
+ $tobool14 = ($6 | 0) == 0;
+ if ($tobool14) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $7 = $disc;
+ $call16 = FUNCTION_TABLE_iiiii[$6 & 1023]($dt, 3, $7, $0) | 0;
+ $cmp = ($call16 | 0) < 0;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 31;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ HEAP32[$disc1 >> 2] = $disc;
+ $memoryf20 = $disc + 28 | 0;
+ $8 = HEAP32[$memoryf20 >> 2] | 0;
+ $memoryf21 = $dt + 12 | 0;
+ $tobool22 = ($8 | 0) == 0;
+ $dtmemory_51 = $tobool22 ? 238 : $8;
+ HEAP32[$memoryf21 >> 2] = $dtmemory_51;
+ $9 = HEAP32[$data >> 2] | 0;
+ $type27 = $9 | 0;
+ $10 = HEAP32[$type27 >> 2] | 0;
+ $and28 = $10 & 112;
+ $tobool29 = ($and28 | 0) == 0;
+ if ($tobool29) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = $0;
+ label = 31;
+ break;
+ }
+ case 10:
+ $and33 = $10 & 2;
+ $tobool34 = ($and33 | 0) == 0;
+ if ($tobool34) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $and36 = $type & 2;
+ $tobool37 = ($and36 | 0) == 0;
+ if ($tobool37) {
+ label = 15;
+ break;
+ } else {
+ $retval_0 = $0;
+ label = 31;
+ break;
+ }
+ case 12:
+ $and43 = $10 & 3;
+ $tobool44 = ($and43 | 0) == 0;
+ if ($tobool44) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $11 = $type & 3;
+ $12 = ($11 | 0) == 3;
+ if ($12) {
+ $retval_0 = $0;
+ label = 31;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $and54 = $type & 1;
+ $tobool55 = ($and54 | 0) == 0;
+ if ($tobool55) {
+ label = 15;
+ break;
+ } else {
+ $retval_0 = $0;
+ label = 31;
+ break;
+ }
+ case 15:
+ $call58 = _dtflatten($dt) | 0;
+ $13 = HEAP32[$data >> 2] | 0;
+ $type60 = $13 | 0;
+ $14 = HEAP32[$type60 >> 2] | 0;
+ $and61 = $14 & -4097;
+ HEAP32[$type60 >> 2] = $and61;
+ $15 = HEAP32[$data >> 2] | 0;
+ $here = $15 + 4 | 0;
+ HEAP32[$here >> 2] = 0;
+ $16 = HEAP32[$data >> 2] | 0;
+ $size = $16 + 16 | 0;
+ HEAP32[$size >> 2] = 0;
+ $17 = HEAP32[$data >> 2] | 0;
+ $type65 = $17 | 0;
+ $18 = HEAP32[$type65 >> 2] | 0;
+ $and66 = $18 & 3;
+ $tobool67 = ($and66 | 0) == 0;
+ if ($tobool67) {
+ label = 16;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 16:
+ $tobool7452 = ($call58 | 0) == 0;
+ if ($tobool7452) {
+ $retval_0 = $0;
+ label = 31;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $and76 = $type & 2;
+ $tobool77 = ($and76 | 0) == 0;
+ $link = $disc + 8 | 0;
+ $size86 = $disc + 4 | 0;
+ $key = $disc | 0;
+ $hashf = $disc + 24 | 0;
+ $r_053 = $call58;
+ label = 20;
+ break;
+ case 18:
+ $_htab = $17 + 8 | 0;
+ $19 = HEAP32[$_htab >> 2] | 0;
+ $ntab = $17 + 12 | 0;
+ $20 = HEAP32[$ntab >> 2] | 0;
+ $add_ptr = $19 + ($20 << 2) | 0;
+ $cmp7155 = ($20 | 0) > 0;
+ if ($cmp7155) {
+ $s_056 = $19;
+ label = 19;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 19:
+ $incdec_ptr = $s_056 + 4 | 0;
+ HEAP32[$s_056 >> 2] = 0;
+ $cmp71 = $incdec_ptr >>> 0 < $add_ptr >>> 0;
+ if ($cmp71) {
+ $s_056 = $incdec_ptr;
+ label = 19;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 20:
+ $right = $r_053 | 0;
+ $21 = HEAP32[$right >> 2] | 0;
+ if ($tobool77) {
+ label = 21;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 21:
+ $22 = HEAP32[$link >> 2] | 0;
+ $cmp79 = ($22 | 0) < 0;
+ if ($cmp79) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $obj = $r_053 + 8 | 0;
+ $23 = $obj;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $cond85 = $24;
+ label = 24;
+ break;
+ case 23:
+ $25 = $r_053;
+ $idx_neg = -$22 | 0;
+ $add_ptr83 = $25 + $idx_neg | 0;
+ $cond85 = $add_ptr83;
+ label = 24;
+ break;
+ case 24:
+ $26 = HEAP32[$size86 >> 2] | 0;
+ $cmp87 = ($26 | 0) < 0;
+ $27 = HEAP32[$key >> 2] | 0;
+ $add_ptr89 = $cond85 + $27 | 0;
+ if ($cmp87) {
+ label = 25;
+ break;
+ } else {
+ $cond94 = $add_ptr89;
+ label = 26;
+ break;
+ }
+ case 25:
+ $28 = $add_ptr89;
+ $29 = HEAP32[$28 >> 2] | 0;
+ $cond94 = $29;
+ label = 26;
+ break;
+ case 26:
+ $30 = HEAP32[$hashf >> 2] | 0;
+ $tobool95 = ($30 | 0) == 0;
+ if ($tobool95) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $call98 = FUNCTION_TABLE_iiii[$30 & 1023]($dt, $cond94, $disc) | 0;
+ $cond103 = $call98;
+ label = 29;
+ break;
+ case 28:
+ $31 = HEAP32[$size86 >> 2] | 0;
+ $call101 = _dtstrhash(0, $cond94, $31) | 0;
+ $cond103 = $call101;
+ label = 29;
+ break;
+ case 29:
+ $_hash = $r_053 + 4 | 0;
+ HEAP32[$_hash >> 2] = $cond103;
+ label = 30;
+ break;
+ case 30:
+ $32 = $r_053;
+ $call105 = FUNCTION_TABLE_iiii[$3 & 1023]($dt, $32, 32) | 0;
+ $tobool74 = ($21 | 0) == 0;
+ if ($tobool74) {
+ $retval_0 = $0;
+ label = 31;
+ break;
+ } else {
+ $r_053 = $21;
+ label = 20;
+ break;
+ }
+ case 31:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dtmemory($dt, $addr, $size, $disc) {
+ $dt = $dt | 0;
+ $addr = $addr | 0;
+ $size = $size | 0;
+ $disc = $disc | 0;
+ var $tobool = 0, $cmp3 = 0, $call = 0, $call4 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($addr | 0) == 0;
+ $cmp3 = ($size | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ if ($cmp3) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ _free($addr);
+ $retval_0 = 0;
+ label = 8;
+ break;
+ case 5:
+ $call = _realloc($addr, $size) | 0;
+ $retval_0 = $call;
+ label = 8;
+ break;
+ case 6:
+ if ($cmp3) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call4 = _malloc($size) | 0;
+ $retval_0 = $call4;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dtlist($dt, $obj, $type) {
+ $dt = $dt | 0;
+ $obj = $obj | 0;
+ $type = $type | 0;
+ var $data = 0, $0 = 0, $type1 = 0, $1 = 0, $and = 0, $tobool = 0, $2 = 0, $call = 0, $disc2 = 0, $3 = 0, $key3 = 0, $4 = 0, $size = 0, $5 = 0, $link = 0, $6 = 0, $comparf = 0, $7 = 0, $type4 = 0, $8 = 0, $and5 = 0, $tobool6 = 0, $and7 = 0, $tobool8 = 0, $9 = 0, $hh = 0, $_head = 0, $10 = 0, $tobool11 = 0, $and13 = 0, $tobool14 = 0, $11 = 0, $here199 = 0, $hl = 0, $_left = 0, $12 = 0, $13 = 0, $here = 0, $tobool18 = 0, $r_0201 = 0, $cmp = 0, $obj21 = 0, $14 = 0, $15 = 0, $16 = 0, $idx_neg = 0, $add_ptr = 0, $and28 = 0, $tobool29 = 0, $17 = 0, $type32 = 0, $18 = 0, $and33 = 0, $tobool34 = 0, $hh36 = 0, $_head37 = 0, $19 = 0, $tobool38 = 0, $and42 = 0, $tobool43 = 0, $freef = 0, $20 = 0, $tobool45 = 0, $21 = 0, $cmp48 = 0, $22 = 0, $hh51 = 0, $_head52 = 0, $23 = 0, $tobool53205 = 0, $memoryf = 0, $cmp58 = 0, $idx_neg62 = 0, $r_2206 = 0, $right = 0, $24 = 0, $25 = 0, $tobool55 = 0, $obj60 = 0, $26 = 0, $27 = 0, $28 = 0, $add_ptr63 = 0, $cond65 = 0, $29 = 0, $cmp68 = 0, $tobool53 = 0, $30 = 0, $31 = 0, $call70 = 0, $32 = 0, $here74 = 0, $33 = 0, $34 = 0, $35 = 0, $size79 = 0, $and82 = 0, $tobool83 = 0, $makef = 0, $36 = 0, $tobool85 = 0, $and86 = 0, $tobool87 = 0, $call90 = 0, $tobool91 = 0, $obj_addr_0 = 0, $cmp94 = 0, $add_ptr96 = 0, $memoryf98 = 0, $37 = 0, $call99 = 0, $tobool100 = 0, $obj102 = 0, $38 = 0, $39 = 0, $tobool105 = 0, $freef107 = 0, $40 = 0, $tobool108 = 0, $and110 = 0, $tobool111 = 0, $r_3_in = 0, $r_3 = 0, $41 = 0, $type118 = 0, $42 = 0, $and119 = 0, $tobool120 = 0, $and122 = 0, $tobool123 = 0, $and129 = 0, $tobool130 = 0, $and132 = 0, $tobool133 = 0, $here136 = 0, $43 = 0, $tobool137 = 0, $right139 = 0, $44 = 0, $tobool140 = 0, $right144 = 0, $45 = 0, $r_3_c196 = 0, $hl148 = 0, $_left149 = 0, $hh159 = 0, $_head160 = 0, $46 = 0, $cmp161 = 0, $hl164 = 0, $_left165 = 0, $47 = 0, $hl166 = 0, $_left167 = 0, $right170 = 0, $right171 = 0, $48 = 0, $r_3_c195 = 0, $and179 = 0, $tobool180 = 0, $49 = 0, $hh183 = 0, $_head184 = 0, $50 = 0, $right185 = 0, $tobool186 = 0, $hl188 = 0, $_left189 = 0, $51 = 0, $hl190 = 0, $_left191 = 0, $52 = 0, $r_3_c194 = 0, $hl195 = 0, $_left196 = 0, $53 = 0, $54 = 0, $55 = 0, $hh203 = 0, $_head204 = 0, $56 = 0, $tobool205 = 0, $hl207 = 0, $_left208 = 0, $57 = 0, $right209 = 0, $58 = 0, $hl212 = 0, $_left213 = 0, $59 = 0, $r_3_c192 = 0, $60 = 0, $r_3_c = 0, $hl220 = 0, $_left221 = 0, $right223 = 0, $61 = 0, $size228 = 0, $62 = 0, $cmp229 = 0, $add = 0, $63 = 0, $here235 = 0, $cmp236 = 0, $obj238 = 0, $64 = 0, $65 = 0, $idx_neg240 = 0, $add_ptr241 = 0, $and245 = 0, $tobool246 = 0, $66 = 0, $here249 = 0, $67 = 0, $tobool250 = 0, $cmp252 = 0, $obj254 = 0, $68 = 0, $69 = 0, $70 = 0, $idx_neg256 = 0, $add_ptr257 = 0, $cond259 = 0, $cmp260 = 0, $cmp266 = 0, $add_ptr268 = 0, $71 = 0, $72 = 0, $cond274 = 0, $73 = 0, $hh276 = 0, $_head277 = 0, $cmp281 = 0, $cmp289 = 0, $tobool296 = 0, $cmp300 = 0, $idx_neg285 = 0, $r_4_in = 0, $r_4 = 0, $tobool279 = 0, $obj283 = 0, $74 = 0, $75 = 0, $76 = 0, $add_ptr286 = 0, $cond288 = 0, $add_ptr291 = 0, $77 = 0, $78 = 0, $cond295 = 0, $call298 = 0, $call302 = 0, $call304 = 0, $cond308 = 0, $cmp309 = 0, $right313 = 0, $r_5 = 0, $tobool316 = 0, $79 = 0, $or = 0, $and320 = 0, $tobool321 = 0, $r_6 = 0, $right323 = 0, $80 = 0, $tobool324 = 0, $hl326 = 0, $_left327 = 0, $81 = 0, $82 = 0, $_c191 = 0, $83 = 0, $hh333 = 0, $_head334 = 0, $84 = 0, $cmp335 = 0, $85 = 0, $86 = 0, $_c189 = 0, $87 = 0, $hh342 = 0, $_head343 = 0, $88 = 0, $tobool344 = 0, $hl346 = 0, $_left347 = 0, $89 = 0, $90 = 0, $_c190 = 0, $hl356 = 0, $_left357 = 0, $91 = 0, $right358 = 0, $hl359 = 0, $_left360 = 0, $92 = 0, $cmp361 = 0, $93 = 0, $94 = 0, $_c = 0, $95 = 0, $here370 = 0, $96 = 0, $cmp371 = 0, $97 = 0, $cond376 = 0, $98 = 0, $here378 = 0, $99 = 0, $size380 = 0, $100 = 0, $sub = 0, $cmp381 = 0, $obj383 = 0, $101 = 0, $102 = 0, $103 = 0, $idx_neg385 = 0, $add_ptr386 = 0, $cond388 = 0, $freef389 = 0, $104 = 0, $tobool390 = 0, $and392 = 0, $tobool393 = 0, $105 = 0, $cmp398 = 0, $memoryf400 = 0, $106 = 0, $107 = 0, $call401 = 0, $and404 = 0, $tobool405 = 0, $right407 = 0, $108 = 0, $and409 = 0, $tobool410 = 0, $109 = 0, $hh413 = 0, $_head414 = 0, $110 = 0, $cmp415 = 0, $111 = 0, $here426203 = 0, $hl418 = 0, $_left419 = 0, $112 = 0, $r_7 = 0, $113 = 0, $here426 = 0, $tobool427 = 0, $cmp429 = 0, $obj431 = 0, $114 = 0, $115 = 0, $116 = 0, $idx_neg433 = 0, $add_ptr434 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $data = $dt + 8 | 0;
+ $0 = HEAP32[$data >> 2] | 0;
+ $type1 = $0 | 0;
+ $1 = HEAP32[$type1 >> 2] | 0;
+ $and = $1 & 4096;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $dt;
+ $call = _dtrestore($2, 0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $disc2 = $dt + 4 | 0;
+ $3 = HEAP32[$disc2 >> 2] | 0;
+ $key3 = $3 | 0;
+ $4 = HEAP32[$key3 >> 2] | 0;
+ $size = $3 + 4 | 0;
+ $5 = HEAP32[$size >> 2] | 0;
+ $link = $3 + 8 | 0;
+ $6 = HEAP32[$link >> 2] | 0;
+ $comparf = $3 + 20 | 0;
+ $7 = HEAP32[$comparf >> 2] | 0;
+ $type4 = $dt + 20 | 0;
+ $8 = HEAP32[$type4 >> 2] | 0;
+ $and5 = $8 & -32769;
+ HEAP32[$type4 >> 2] = $and5;
+ $tobool6 = ($obj | 0) == 0;
+ if ($tobool6) {
+ label = 5;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 5:
+ $and7 = $type & 384;
+ $tobool8 = ($and7 | 0) == 0;
+ if ($tobool8) {
+ label = 13;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $9 = HEAP32[$data >> 2] | 0;
+ $hh = $9 + 8 | 0;
+ $_head = $hh;
+ $10 = HEAP32[$_head >> 2] | 0;
+ $tobool11 = ($10 | 0) == 0;
+ if ($tobool11) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $and13 = $type & 256;
+ $tobool14 = ($and13 | 0) == 0;
+ if ($tobool14) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $11 = HEAP32[$data >> 2] | 0;
+ $here199 = $11 + 4 | 0;
+ HEAP32[$here199 >> 2] = $10;
+ $r_0201 = $10;
+ label = 10;
+ break;
+ case 9:
+ $hl = $10 + 4 | 0;
+ $_left = $hl;
+ $12 = HEAP32[$_left >> 2] | 0;
+ $13 = HEAP32[$data >> 2] | 0;
+ $here = $13 + 4 | 0;
+ HEAP32[$here >> 2] = $12;
+ $tobool18 = ($12 | 0) == 0;
+ if ($tobool18) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ $r_0201 = $12;
+ label = 10;
+ break;
+ }
+ case 10:
+ $cmp = ($6 | 0) < 0;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $obj21 = $r_0201 + 8 | 0;
+ $14 = $obj21;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $retval_0 = $15;
+ label = 117;
+ break;
+ case 12:
+ $16 = $r_0201;
+ $idx_neg = -$6 | 0;
+ $add_ptr = $16 + $idx_neg | 0;
+ $retval_0 = $add_ptr;
+ label = 117;
+ break;
+ case 13:
+ $and28 = $type & 4098;
+ $tobool29 = ($and28 | 0) == 0;
+ if ($tobool29) {
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $17 = HEAP32[$data >> 2] | 0;
+ $type32 = $17 | 0;
+ $18 = HEAP32[$type32 >> 2] | 0;
+ $and33 = $18 & 144;
+ $tobool34 = ($and33 | 0) == 0;
+ if ($tobool34) {
+ label = 15;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ }
+ case 15:
+ $hh36 = $17 + 8 | 0;
+ $_head37 = $hh36;
+ $19 = HEAP32[$_head37 >> 2] | 0;
+ $tobool38 = ($19 | 0) == 0;
+ if ($tobool38) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ $r_6 = $19;
+ label = 90;
+ break;
+ }
+ case 16:
+ $and42 = $type & 64;
+ $tobool43 = ($and42 | 0) == 0;
+ if ($tobool43) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $freef = $3 + 16 | 0;
+ $20 = HEAP32[$freef >> 2] | 0;
+ $tobool45 = ($20 | 0) == 0;
+ if ($tobool45) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $21 = HEAP32[$link >> 2] | 0;
+ $cmp48 = ($21 | 0) < 0;
+ if ($cmp48) {
+ label = 19;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 19:
+ $22 = HEAP32[$data >> 2] | 0;
+ $hh51 = $22 + 8 | 0;
+ $_head52 = $hh51;
+ $23 = HEAP32[$_head52 >> 2] | 0;
+ $tobool53205 = ($23 | 0) == 0;
+ if ($tobool53205) {
+ label = 29;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $memoryf = $dt + 12 | 0;
+ $cmp58 = ($6 | 0) < 0;
+ $idx_neg62 = -$6 | 0;
+ $r_2206 = $23;
+ label = 21;
+ break;
+ case 21:
+ $right = $r_2206 | 0;
+ $24 = HEAP32[$right >> 2] | 0;
+ $25 = HEAP32[$freef >> 2] | 0;
+ $tobool55 = ($25 | 0) == 0;
+ if ($tobool55) {
+ label = 26;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ if ($cmp58) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ $obj60 = $r_2206 + 8 | 0;
+ $26 = $obj60;
+ $27 = HEAP32[$26 >> 2] | 0;
+ $cond65 = $27;
+ label = 25;
+ break;
+ case 24:
+ $28 = $r_2206;
+ $add_ptr63 = $28 + $idx_neg62 | 0;
+ $cond65 = $add_ptr63;
+ label = 25;
+ break;
+ case 25:
+ FUNCTION_TABLE_viii[$25 & 1023]($dt, $cond65, $3);
+ label = 26;
+ break;
+ case 26:
+ $29 = HEAP32[$link >> 2] | 0;
+ $cmp68 = ($29 | 0) < 0;
+ if ($cmp68) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $tobool53 = ($24 | 0) == 0;
+ if ($tobool53) {
+ label = 29;
+ break;
+ } else {
+ $r_2206 = $24;
+ label = 21;
+ break;
+ }
+ case 28:
+ $30 = HEAP32[$memoryf >> 2] | 0;
+ $31 = $r_2206;
+ $call70 = FUNCTION_TABLE_iiiii[$30 & 1023]($dt, $31, 0, $3) | 0;
+ label = 27;
+ break;
+ case 29:
+ $32 = HEAP32[$data >> 2] | 0;
+ $here74 = $32 + 4 | 0;
+ HEAP32[$here74 >> 2] = 0;
+ $33 = HEAP32[$data >> 2] | 0;
+ $34 = $33 + 8 | 0;
+ HEAP32[$34 >> 2] = 0;
+ $35 = HEAP32[$data >> 2] | 0;
+ $size79 = $35 + 16 | 0;
+ HEAP32[$size79 >> 2] = 0;
+ $retval_0 = 0;
+ label = 117;
+ break;
+ case 30:
+ $and82 = $type & 2049;
+ $tobool83 = ($and82 | 0) == 0;
+ if ($tobool83) {
+ label = 66;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $makef = $3 + 12 | 0;
+ $36 = HEAP32[$makef >> 2] | 0;
+ $tobool85 = ($36 | 0) == 0;
+ if ($tobool85) {
+ $obj_addr_0 = $obj;
+ label = 34;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $and86 = $type & 1;
+ $tobool87 = ($and86 | 0) == 0;
+ if ($tobool87) {
+ $obj_addr_0 = $obj;
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $call90 = FUNCTION_TABLE_iiii[$36 & 1023]($dt, $obj, $3) | 0;
+ $tobool91 = ($call90 | 0) == 0;
+ if ($tobool91) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ $obj_addr_0 = $call90;
+ label = 34;
+ break;
+ }
+ case 34:
+ $cmp94 = ($6 | 0) > -1;
+ if ($cmp94) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ $add_ptr96 = $obj_addr_0 + $6 | 0;
+ $r_3_in = $add_ptr96;
+ label = 42;
+ break;
+ case 36:
+ $memoryf98 = $dt + 12 | 0;
+ $37 = HEAP32[$memoryf98 >> 2] | 0;
+ $call99 = FUNCTION_TABLE_iiiii[$37 & 1023]($dt, 0, 12, $3) | 0;
+ $tobool100 = ($call99 | 0) == 0;
+ if ($tobool100) {
+ label = 38;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $obj102 = $call99 + 8 | 0;
+ $38 = $obj102;
+ HEAP32[$38 >> 2] = $obj_addr_0;
+ $r_3_in = $call99;
+ label = 42;
+ break;
+ case 38:
+ $39 = HEAP32[$makef >> 2] | 0;
+ $tobool105 = ($39 | 0) == 0;
+ if ($tobool105) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $freef107 = $3 + 16 | 0;
+ $40 = HEAP32[$freef107 >> 2] | 0;
+ $tobool108 = ($40 | 0) == 0;
+ if ($tobool108) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $and110 = $type & 1;
+ $tobool111 = ($and110 | 0) == 0;
+ if ($tobool111) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ FUNCTION_TABLE_viii[$40 & 1023]($dt, $obj_addr_0, $3);
+ $retval_0 = 0;
+ label = 117;
+ break;
+ case 42:
+ $r_3 = $r_3_in;
+ $41 = HEAP32[$data >> 2] | 0;
+ $type118 = $41 | 0;
+ $42 = HEAP32[$type118 >> 2] | 0;
+ $and119 = $42 & 128;
+ $tobool120 = ($and119 | 0) == 0;
+ if ($tobool120) {
+ label = 44;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $and122 = $type & 8192;
+ $tobool123 = ($and122 | 0) == 0;
+ if ($tobool123) {
+ label = 53;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 44:
+ $and129 = $42 & 16;
+ $tobool130 = ($and129 | 0) == 0;
+ if ($tobool130) {
+ label = 52;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $and132 = $type & 8192;
+ $tobool133 = ($and132 | 0) == 0;
+ $here136 = $41 + 4 | 0;
+ $43 = HEAP32[$here136 >> 2] | 0;
+ $tobool137 = ($43 | 0) != 0;
+ if ($tobool133) {
+ label = 49;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ if ($tobool137) {
+ label = 47;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 47:
+ $right139 = $43 | 0;
+ $44 = HEAP32[$right139 >> 2] | 0;
+ $tobool140 = ($44 | 0) == 0;
+ if ($tobool140) {
+ label = 57;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $right144 = $r_3_in;
+ HEAP32[$right144 >> 2] = $44;
+ $45 = $44 + 4 | 0;
+ $r_3_c196 = $r_3_in;
+ HEAP32[$45 >> 2] = $r_3_c196;
+ $hl148 = $r_3_in + 4 | 0;
+ $_left149 = $hl148;
+ HEAP32[$_left149 >> 2] = $43;
+ HEAP32[$right139 >> 2] = $r_3;
+ label = 61;
+ break;
+ case 49:
+ if ($tobool137) {
+ label = 50;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 50:
+ $hh159 = $41 + 8 | 0;
+ $_head160 = $hh159;
+ $46 = HEAP32[$_head160 >> 2] | 0;
+ $cmp161 = ($43 | 0) == ($46 | 0);
+ if ($cmp161) {
+ label = 53;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $hl164 = $43 + 4 | 0;
+ $_left165 = $hl164;
+ $47 = HEAP32[$_left165 >> 2] | 0;
+ $hl166 = $r_3_in + 4 | 0;
+ $_left167 = $hl166;
+ HEAP32[$_left167 >> 2] = $47;
+ $right170 = $47 | 0;
+ HEAP32[$right170 >> 2] = $r_3;
+ $right171 = $r_3_in;
+ HEAP32[$right171 >> 2] = $43;
+ $48 = $hl164 | 0;
+ $r_3_c195 = $r_3_in;
+ HEAP32[$48 >> 2] = $r_3_c195;
+ label = 61;
+ break;
+ case 52:
+ $and179 = $42 & 32;
+ $tobool180 = ($and179 | 0) == 0;
+ if ($tobool180) {
+ label = 57;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $49 = HEAP32[$data >> 2] | 0;
+ $hh183 = $49 + 8 | 0;
+ $_head184 = $hh183;
+ $50 = HEAP32[$_head184 >> 2] | 0;
+ $right185 = $r_3_in;
+ HEAP32[$right185 >> 2] = $50;
+ $tobool186 = ($50 | 0) == 0;
+ if ($tobool186) {
+ label = 55;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 54:
+ $hl188 = $50 + 4 | 0;
+ $_left189 = $hl188;
+ $51 = HEAP32[$_left189 >> 2] | 0;
+ $hl190 = $r_3_in + 4 | 0;
+ $_left191 = $hl190;
+ HEAP32[$_left191 >> 2] = $51;
+ $52 = $hl188 | 0;
+ $r_3_c194 = $r_3_in;
+ HEAP32[$52 >> 2] = $r_3_c194;
+ label = 56;
+ break;
+ case 55:
+ $hl195 = $r_3_in + 4 | 0;
+ $_left196 = $hl195;
+ HEAP32[$_left196 >> 2] = $r_3;
+ label = 56;
+ break;
+ case 56:
+ $53 = HEAP32[$data >> 2] | 0;
+ $54 = $53 + 8 | 0;
+ HEAP32[$54 >> 2] = $right185;
+ label = 61;
+ break;
+ case 57:
+ $55 = HEAP32[$data >> 2] | 0;
+ $hh203 = $55 + 8 | 0;
+ $_head204 = $hh203;
+ $56 = HEAP32[$_head204 >> 2] | 0;
+ $tobool205 = ($56 | 0) == 0;
+ if ($tobool205) {
+ label = 59;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $hl207 = $56 + 4 | 0;
+ $_left208 = $hl207;
+ $57 = HEAP32[$_left208 >> 2] | 0;
+ $right209 = $57 | 0;
+ HEAP32[$right209 >> 2] = $r_3;
+ $58 = HEAP32[$_left208 >> 2] | 0;
+ $hl212 = $r_3_in + 4 | 0;
+ $_left213 = $hl212;
+ HEAP32[$_left213 >> 2] = $58;
+ $59 = $hl207 | 0;
+ $r_3_c192 = $r_3_in;
+ HEAP32[$59 >> 2] = $r_3_c192;
+ label = 60;
+ break;
+ case 59:
+ $60 = $hh203 | 0;
+ $r_3_c = $r_3_in;
+ HEAP32[$60 >> 2] = $r_3_c;
+ $hl220 = $r_3_in + 4 | 0;
+ $_left221 = $hl220;
+ HEAP32[$_left221 >> 2] = $r_3;
+ label = 60;
+ break;
+ case 60:
+ $right223 = $r_3_in;
+ HEAP32[$right223 >> 2] = 0;
+ label = 61;
+ break;
+ case 61:
+ $61 = HEAP32[$data >> 2] | 0;
+ $size228 = $61 + 16 | 0;
+ $62 = HEAP32[$size228 >> 2] | 0;
+ $cmp229 = ($62 | 0) > -1;
+ if ($cmp229) {
+ label = 62;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 62:
+ $add = $62 + 1 | 0;
+ HEAP32[$size228 >> 2] = $add;
+ label = 63;
+ break;
+ case 63:
+ $63 = HEAP32[$data >> 2] | 0;
+ $here235 = $63 + 4 | 0;
+ HEAP32[$here235 >> 2] = $r_3;
+ $cmp236 = ($6 | 0) < 0;
+ if ($cmp236) {
+ label = 64;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 64:
+ $obj238 = $r_3_in + 8 | 0;
+ $64 = $obj238;
+ $65 = HEAP32[$64 >> 2] | 0;
+ $retval_0 = $65;
+ label = 117;
+ break;
+ case 65:
+ $idx_neg240 = -$6 | 0;
+ $add_ptr241 = $r_3_in + $idx_neg240 | 0;
+ $retval_0 = $add_ptr241;
+ label = 117;
+ break;
+ case 66:
+ $and245 = $type & 512;
+ $tobool246 = ($and245 | 0) != 0;
+ if ($tobool246) {
+ $cond274 = $obj;
+ label = 75;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 67:
+ $66 = HEAP32[$data >> 2] | 0;
+ $here249 = $66 + 4 | 0;
+ $67 = HEAP32[$here249 >> 2] | 0;
+ $tobool250 = ($67 | 0) == 0;
+ if ($tobool250) {
+ label = 73;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $cmp252 = ($6 | 0) < 0;
+ if ($cmp252) {
+ label = 69;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 69:
+ $obj254 = $67 + 8 | 0;
+ $68 = $obj254;
+ $69 = HEAP32[$68 >> 2] | 0;
+ $cond259 = $69;
+ label = 71;
+ break;
+ case 70:
+ $70 = $67;
+ $idx_neg256 = -$6 | 0;
+ $add_ptr257 = $70 + $idx_neg256 | 0;
+ $cond259 = $add_ptr257;
+ label = 71;
+ break;
+ case 71:
+ $cmp260 = ($cond259 | 0) == ($obj | 0);
+ if ($cmp260) {
+ $r_5 = $67;
+ label = 88;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 72:
+ if ($tobool246) {
+ $cond274 = $obj;
+ label = 75;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $cmp266 = ($5 | 0) < 0;
+ $add_ptr268 = $obj + $4 | 0;
+ if ($cmp266) {
+ label = 74;
+ break;
+ } else {
+ $cond274 = $add_ptr268;
+ label = 75;
+ break;
+ }
+ case 74:
+ $71 = $add_ptr268;
+ $72 = HEAP32[$71 >> 2] | 0;
+ $cond274 = $72;
+ label = 75;
+ break;
+ case 75:
+ $73 = HEAP32[$data >> 2] | 0;
+ $hh276 = $73 + 8 | 0;
+ $_head277 = $hh276;
+ $cmp281 = ($6 | 0) < 0;
+ $cmp289 = ($5 | 0) < 0;
+ $tobool296 = ($7 | 0) == 0;
+ $cmp300 = ($5 | 0) < 1;
+ $idx_neg285 = -$6 | 0;
+ $r_4_in = $_head277;
+ label = 76;
+ break;
+ case 76:
+ $r_4 = HEAP32[$r_4_in >> 2] | 0;
+ $tobool279 = ($r_4 | 0) == 0;
+ if ($tobool279) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 77:
+ if ($cmp281) {
+ label = 78;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 78:
+ $obj283 = $r_4 + 8 | 0;
+ $74 = $obj283;
+ $75 = HEAP32[$74 >> 2] | 0;
+ $cond288 = $75;
+ label = 80;
+ break;
+ case 79:
+ $76 = $r_4;
+ $add_ptr286 = $76 + $idx_neg285 | 0;
+ $cond288 = $add_ptr286;
+ label = 80;
+ break;
+ case 80:
+ $add_ptr291 = $cond288 + $4 | 0;
+ if ($cmp289) {
+ label = 81;
+ break;
+ } else {
+ $cond295 = $add_ptr291;
+ label = 82;
+ break;
+ }
+ case 81:
+ $77 = $add_ptr291;
+ $78 = HEAP32[$77 >> 2] | 0;
+ $cond295 = $78;
+ label = 82;
+ break;
+ case 82:
+ if ($tobool296) {
+ label = 84;
+ break;
+ } else {
+ label = 83;
+ break;
+ }
+ case 83:
+ $call298 = FUNCTION_TABLE_iiiii[$7 & 1023]($dt, $cond274, $cond295, $3) | 0;
+ $cond308 = $call298;
+ label = 87;
+ break;
+ case 84:
+ if ($cmp300) {
+ label = 85;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 85:
+ $call302 = _strcmp($cond274 | 0, $cond295 | 0) | 0;
+ $cond308 = $call302;
+ label = 87;
+ break;
+ case 86:
+ $call304 = _memcmp($cond274 | 0, $cond295 | 0, $5 | 0) | 0;
+ $cond308 = $call304;
+ label = 87;
+ break;
+ case 87:
+ $cmp309 = ($cond308 | 0) == 0;
+ $right313 = $r_4 | 0;
+ if ($cmp309) {
+ $r_5 = $r_4;
+ label = 88;
+ break;
+ } else {
+ $r_4_in = $right313;
+ label = 76;
+ break;
+ }
+ case 88:
+ $tobool316 = ($r_5 | 0) == 0;
+ if ($tobool316) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 89:
+ $79 = HEAP32[$type4 >> 2] | 0;
+ $or = $79 | 32768;
+ HEAP32[$type4 >> 2] = $or;
+ $and320 = $type & 4098;
+ $tobool321 = ($and320 | 0) == 0;
+ if ($tobool321) {
+ label = 107;
+ break;
+ } else {
+ $r_6 = $r_5;
+ label = 90;
+ break;
+ }
+ case 90:
+ $right323 = $r_6 | 0;
+ $80 = HEAP32[$right323 >> 2] | 0;
+ $tobool324 = ($80 | 0) == 0;
+ if ($tobool324) {
+ label = 92;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 91:
+ $hl326 = $r_6 + 4 | 0;
+ $_left327 = $hl326;
+ $81 = HEAP32[$_left327 >> 2] | 0;
+ $82 = $80 + 4 | 0;
+ $_c191 = $81;
+ HEAP32[$82 >> 2] = $_c191;
+ label = 92;
+ break;
+ case 92:
+ $83 = HEAP32[$data >> 2] | 0;
+ $hh333 = $83 + 8 | 0;
+ $_head334 = $hh333;
+ $84 = HEAP32[$_head334 >> 2] | 0;
+ $cmp335 = ($r_6 | 0) == ($84 | 0);
+ $85 = HEAP32[$right323 >> 2] | 0;
+ if ($cmp335) {
+ label = 93;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 93:
+ $86 = $hh333 | 0;
+ $_c189 = $85 | 0;
+ HEAP32[$86 >> 2] = $_c189;
+ $87 = HEAP32[$data >> 2] | 0;
+ $hh342 = $87 + 8 | 0;
+ $_head343 = $hh342;
+ $88 = HEAP32[$_head343 >> 2] | 0;
+ $tobool344 = ($88 | 0) == 0;
+ if ($tobool344) {
+ label = 97;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 94:
+ $hl346 = $84 + 4 | 0;
+ $_left347 = $hl346;
+ $89 = HEAP32[$_left347 >> 2] | 0;
+ $90 = $88 + 4 | 0;
+ $_c190 = $89;
+ HEAP32[$90 >> 2] = $_c190;
+ label = 97;
+ break;
+ case 95:
+ $hl356 = $r_6 + 4 | 0;
+ $_left357 = $hl356;
+ $91 = HEAP32[$_left357 >> 2] | 0;
+ $right358 = $91 | 0;
+ HEAP32[$right358 >> 2] = $85;
+ $hl359 = $84 + 4 | 0;
+ $_left360 = $hl359;
+ $92 = HEAP32[$_left360 >> 2] | 0;
+ $cmp361 = ($r_6 | 0) == ($92 | 0);
+ if ($cmp361) {
+ label = 96;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 96:
+ $93 = HEAP32[$_left357 >> 2] | 0;
+ $94 = $hl359 | 0;
+ $_c = $93;
+ HEAP32[$94 >> 2] = $_c;
+ label = 97;
+ break;
+ case 97:
+ $95 = HEAP32[$data >> 2] | 0;
+ $here370 = $95 + 4 | 0;
+ $96 = HEAP32[$here370 >> 2] | 0;
+ $cmp371 = ($r_6 | 0) == ($96 | 0);
+ if ($cmp371) {
+ label = 98;
+ break;
+ } else {
+ $cond376 = 0;
+ label = 99;
+ break;
+ }
+ case 98:
+ $97 = HEAP32[$right323 >> 2] | 0;
+ $cond376 = $97;
+ label = 99;
+ break;
+ case 99:
+ $98 = HEAP32[$data >> 2] | 0;
+ $here378 = $98 + 4 | 0;
+ HEAP32[$here378 >> 2] = $cond376;
+ $99 = HEAP32[$data >> 2] | 0;
+ $size380 = $99 + 16 | 0;
+ $100 = HEAP32[$size380 >> 2] | 0;
+ $sub = $100 - 1 | 0;
+ HEAP32[$size380 >> 2] = $sub;
+ $cmp381 = ($6 | 0) < 0;
+ if ($cmp381) {
+ label = 100;
+ break;
+ } else {
+ label = 101;
+ break;
+ }
+ case 100:
+ $obj383 = $r_6 + 8 | 0;
+ $101 = $obj383;
+ $102 = HEAP32[$101 >> 2] | 0;
+ $cond388 = $102;
+ label = 102;
+ break;
+ case 101:
+ $103 = $r_6;
+ $idx_neg385 = -$6 | 0;
+ $add_ptr386 = $103 + $idx_neg385 | 0;
+ $cond388 = $add_ptr386;
+ label = 102;
+ break;
+ case 102:
+ $freef389 = $3 + 16 | 0;
+ $104 = HEAP32[$freef389 >> 2] | 0;
+ $tobool390 = ($104 | 0) == 0;
+ if ($tobool390) {
+ label = 105;
+ break;
+ } else {
+ label = 103;
+ break;
+ }
+ case 103:
+ $and392 = $type & 2;
+ $tobool393 = ($and392 | 0) == 0;
+ if ($tobool393) {
+ label = 105;
+ break;
+ } else {
+ label = 104;
+ break;
+ }
+ case 104:
+ FUNCTION_TABLE_viii[$104 & 1023]($dt, $cond388, $3);
+ label = 105;
+ break;
+ case 105:
+ $105 = HEAP32[$link >> 2] | 0;
+ $cmp398 = ($105 | 0) < 0;
+ if ($cmp398) {
+ label = 106;
+ break;
+ } else {
+ $retval_0 = $cond388;
+ label = 117;
+ break;
+ }
+ case 106:
+ $memoryf400 = $dt + 12 | 0;
+ $106 = HEAP32[$memoryf400 >> 2] | 0;
+ $107 = $r_6;
+ $call401 = FUNCTION_TABLE_iiiii[$106 & 1023]($dt, $107, 0, $3) | 0;
+ $retval_0 = $cond388;
+ label = 117;
+ break;
+ case 107:
+ $and404 = $type & 8;
+ $tobool405 = ($and404 | 0) == 0;
+ if ($tobool405) {
+ label = 109;
+ break;
+ } else {
+ label = 108;
+ break;
+ }
+ case 108:
+ $right407 = $r_5 | 0;
+ $108 = HEAP32[$right407 >> 2] | 0;
+ $r_7 = $108;
+ label = 113;
+ break;
+ case 109:
+ $and409 = $type & 16;
+ $tobool410 = ($and409 | 0) == 0;
+ if ($tobool410) {
+ $r_7 = $r_5;
+ label = 113;
+ break;
+ } else {
+ label = 110;
+ break;
+ }
+ case 110:
+ $109 = HEAP32[$data >> 2] | 0;
+ $hh413 = $109 + 8 | 0;
+ $_head414 = $hh413;
+ $110 = HEAP32[$_head414 >> 2] | 0;
+ $cmp415 = ($r_5 | 0) == ($110 | 0);
+ if ($cmp415) {
+ label = 111;
+ break;
+ } else {
+ label = 112;
+ break;
+ }
+ case 111:
+ $111 = HEAP32[$data >> 2] | 0;
+ $here426203 = $111 + 4 | 0;
+ HEAP32[$here426203 >> 2] = 0;
+ $retval_0 = 0;
+ label = 117;
+ break;
+ case 112:
+ $hl418 = $r_5 + 4 | 0;
+ $_left419 = $hl418;
+ $112 = HEAP32[$_left419 >> 2] | 0;
+ $r_7 = $112;
+ label = 113;
+ break;
+ case 113:
+ $113 = HEAP32[$data >> 2] | 0;
+ $here426 = $113 + 4 | 0;
+ HEAP32[$here426 >> 2] = $r_7;
+ $tobool427 = ($r_7 | 0) == 0;
+ if ($tobool427) {
+ $retval_0 = 0;
+ label = 117;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 114:
+ $cmp429 = ($6 | 0) < 0;
+ if ($cmp429) {
+ label = 115;
+ break;
+ } else {
+ label = 116;
+ break;
+ }
+ case 115:
+ $obj431 = $r_7 + 8 | 0;
+ $114 = $obj431;
+ $115 = HEAP32[$114 >> 2] | 0;
+ $retval_0 = $115;
+ label = 117;
+ break;
+ case 116:
+ $116 = $r_7;
+ $idx_neg433 = -$6 | 0;
+ $add_ptr434 = $116 + $idx_neg433 | 0;
+ $retval_0 = $add_ptr434;
+ label = 117;
+ break;
+ case 117:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dtopen($disc, $meth) {
+ $disc = $disc | 0;
+ $meth = $meth | 0;
+ var $data = 0, $tobool = 0, $tobool1 = 0, $or_cond = 0, $call = 0, $0 = 0, $tobool2 = 0, $searchf = 0, $meth5 = 0, $1 = 0, $disc6 = 0, $2 = 0, $call7 = 0, $type = 0, $eventf = 0, $3 = 0, $tobool8 = 0, $4 = 0, $5 = 0, $call11 = 0, $cmp = 0, $cmp13 = 0, $6 = 0, $tobool15 = 0, $type17 = 0, $7 = 0, $type18 = 0, $8 = 0, $and = 0, $tobool19 = 0, $memoryf = 0, $9 = 0, $tobool23 = 0, $10 = 0, $call27 = 0, $11 = 0, $tobool28 = 0, $searchf31 = 0, $meth32 = 0, $12 = 0, $disc33 = 0, $13 = 0, $call34 = 0, $type35 = 0, $14 = 0, $nview36 = 0, $15 = 0, $walk37 = 0, $16 = 0, $view38 = 0, $17 = 0, $dt_0 = 0, $memoryf42 = 0, $18 = 0, $call43 = 0, $19 = 0, $tobool44 = 0, $dt_1 = 0, $20 = 0, $type47 = 0, $21 = 0, $type48 = 0, $22 = 0, $here = 0, $23 = 0, $_htab = 0, $24 = 0, $loop = 0, $25 = 0, $size = 0, $26 = 0, $ntab = 0, $27 = 0, $minp = 0, $dt_2 = 0, $28 = 0, $data49 = 0, $searchf50 = 0, $29 = 0, $searchf51 = 0, $meth52 = 0, $30 = 0, $tobool54 = 0, $31 = 0, $call57 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $data = __stackBase__ | 0;
+ $tobool = ($disc | 0) == 0;
+ $tobool1 = ($meth | 0) == 0;
+ $or_cond = $tobool | $tobool1;
+ if ($or_cond) {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _malloc(40) | 0;
+ $0 = $call;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $searchf = $call;
+ HEAP32[$searchf >> 2] = 0;
+ $meth5 = $call + 16 | 0;
+ $1 = $meth5;
+ HEAP32[$1 >> 2] = 0;
+ $disc6 = $call + 4 | 0;
+ $2 = $disc6;
+ HEAP32[$2 >> 2] = 0;
+ $call7 = _dtdisc($0, $disc, 0) | 0;
+ $type = $call + 20 | 0;
+ $eventf = $disc + 32 | 0;
+ _memset($type | 0, 0, 20);
+ $3 = HEAP32[$eventf >> 2] | 0;
+ $tobool8 = ($3 | 0) == 0;
+ if ($tobool8) {
+ $dt_0 = $0;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[$data >> 2] = 0;
+ $4 = HEAP32[$eventf >> 2] | 0;
+ $5 = $data;
+ $call11 = FUNCTION_TABLE_iiiii[$4 & 1023]($0, 1, $5, $disc) | 0;
+ $cmp = ($call11 | 0) < 0;
+ if ($cmp) {
+ $dt_1 = $0;
+ label = 13;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp13 = ($call11 | 0) > 0;
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ $dt_0 = $0;
+ label = 12;
+ break;
+ }
+ case 7:
+ $6 = HEAP32[$data >> 2] | 0;
+ $tobool15 = ($6 | 0) == 0;
+ if ($tobool15) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type17 = $6 | 0;
+ $7 = HEAP32[$type17 >> 2] | 0;
+ $type18 = $meth + 4 | 0;
+ $8 = HEAP32[$type18 >> 2] | 0;
+ $and = $8 & $7;
+ $tobool19 = ($and | 0) == 0;
+ if ($tobool19) {
+ $dt_1 = $0;
+ label = 13;
+ break;
+ } else {
+ $dt_2 = $0;
+ label = 15;
+ break;
+ }
+ case 9:
+ $memoryf = $disc + 28 | 0;
+ $9 = HEAP32[$memoryf >> 2] | 0;
+ $tobool23 = ($9 | 0) == 0;
+ if ($tobool23) {
+ $dt_1 = $0;
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ _free($call);
+ $10 = HEAP32[$memoryf >> 2] | 0;
+ $call27 = FUNCTION_TABLE_iiiii[$10 & 1023](0, 0, 40, $disc) | 0;
+ $11 = $call27;
+ $tobool28 = ($call27 | 0) == 0;
+ if ($tobool28) {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $searchf31 = $call27;
+ HEAP32[$searchf31 >> 2] = 0;
+ $meth32 = $call27 + 16 | 0;
+ $12 = $meth32;
+ HEAP32[$12 >> 2] = 0;
+ $disc33 = $call27 + 4 | 0;
+ $13 = $disc33;
+ HEAP32[$13 >> 2] = 0;
+ $call34 = _dtdisc($11, $disc, 0) | 0;
+ $type35 = $call27 + 20 | 0;
+ $14 = $type35;
+ HEAP32[$14 >> 2] = 1;
+ $nview36 = $call27 + 24 | 0;
+ $15 = $nview36;
+ HEAP32[$15 >> 2] = 0;
+ $walk37 = $call27 + 32 | 0;
+ $16 = $walk37;
+ HEAP32[$16 >> 2] = 0;
+ $view38 = $call27 + 28 | 0;
+ $17 = $view38;
+ HEAP32[$17 >> 2] = 0;
+ $dt_0 = $11;
+ label = 12;
+ break;
+ case 12:
+ $memoryf42 = $dt_0 + 12 | 0;
+ $18 = HEAP32[$memoryf42 >> 2] | 0;
+ $call43 = FUNCTION_TABLE_iiiii[$18 & 1023]($dt_0, 0, 28, $disc) | 0;
+ $19 = $call43;
+ HEAP32[$data >> 2] = $19;
+ $tobool44 = ($call43 | 0) == 0;
+ if ($tobool44) {
+ $dt_1 = $dt_0;
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $20 = $dt_1;
+ _free($20);
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 14:
+ $type47 = $meth + 4 | 0;
+ $21 = HEAP32[$type47 >> 2] | 0;
+ $type48 = $call43;
+ HEAP32[$type48 >> 2] = $21;
+ $22 = HEAP32[$data >> 2] | 0;
+ $here = $22 + 4 | 0;
+ HEAP32[$here >> 2] = 0;
+ $23 = HEAP32[$data >> 2] | 0;
+ $_htab = $23 + 8 | 0;
+ HEAP32[$_htab >> 2] = 0;
+ $24 = HEAP32[$data >> 2] | 0;
+ $loop = $24 + 20 | 0;
+ HEAP32[$loop >> 2] = 0;
+ $25 = HEAP32[$data >> 2] | 0;
+ $size = $25 + 16 | 0;
+ HEAP32[$size >> 2] = 0;
+ $26 = HEAP32[$data >> 2] | 0;
+ $ntab = $26 + 12 | 0;
+ HEAP32[$ntab >> 2] = 0;
+ $27 = HEAP32[$data >> 2] | 0;
+ $minp = $27 + 24 | 0;
+ HEAP32[$minp >> 2] = 0;
+ $dt_2 = $dt_0;
+ label = 15;
+ break;
+ case 15:
+ $28 = HEAP32[$data >> 2] | 0;
+ $data49 = $dt_2 + 8 | 0;
+ HEAP32[$data49 >> 2] = $28;
+ $searchf50 = $meth | 0;
+ $29 = HEAP32[$searchf50 >> 2] | 0;
+ $searchf51 = $dt_2 | 0;
+ HEAP32[$searchf51 >> 2] = $29;
+ $meth52 = $dt_2 + 16 | 0;
+ HEAP32[$meth52 >> 2] = $meth;
+ $30 = HEAP32[$eventf >> 2] | 0;
+ $tobool54 = ($30 | 0) == 0;
+ if ($tobool54) {
+ $retval_0 = $dt_2;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $31 = $dt_2;
+ $call57 = FUNCTION_TABLE_iiiii[$30 & 1023]($dt_2, 5, $31, $disc) | 0;
+ $retval_0 = $dt_2;
+ label = 17;
+ break;
+ case 17:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dtsize($dt) {
+ $dt = $dt | 0;
+ var $data = 0, $0 = 0, $type = 0, $1 = 0, $and = 0, $tobool = 0, $call = 0, $2 = 0, $size2 = 0, $3 = 0, $cmp = 0, $type4 = 0, $4 = 0, $and5 = 0, $tobool6 = 0, $here = 0, $5 = 0, $call9 = 0, $and14 = 0, $tobool15 = 0, $hh = 0, $_head = 0, $t_010 = 0, $tobool1811 = 0, $t_013 = 0, $size_012 = 0, $add = 0, $right = 0, $t_0 = 0, $tobool18 = 0, $size_0_lcssa = 0, $6 = 0, $size20 = 0, $7 = 0, $size24 = 0, $8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $data = $dt + 8 | 0;
+ $0 = HEAP32[$data >> 2] | 0;
+ $type = $0 | 0;
+ $1 = HEAP32[$type >> 2] | 0;
+ $and = $1 & 4096;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _dtrestore($dt, 0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$data >> 2] | 0;
+ $size2 = $2 + 16 | 0;
+ $3 = HEAP32[$size2 >> 2] | 0;
+ $cmp = ($3 | 0) < 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 5:
+ $type4 = $2 | 0;
+ $4 = HEAP32[$type4 >> 2] | 0;
+ $and5 = $4 & 12;
+ $tobool6 = ($and5 | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $here = $2 + 4 | 0;
+ $5 = HEAP32[$here >> 2] | 0;
+ $call9 = _treecount($5) | 0;
+ HEAP32[$size2 >> 2] = $call9;
+ label = 11;
+ break;
+ case 7:
+ $and14 = $4 & 112;
+ $tobool15 = ($and14 | 0) == 0;
+ if ($tobool15) {
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $hh = $2 + 8 | 0;
+ $_head = $hh;
+ $t_010 = HEAP32[$_head >> 2] | 0;
+ $tobool1811 = ($t_010 | 0) == 0;
+ if ($tobool1811) {
+ $size_0_lcssa = 0;
+ label = 10;
+ break;
+ } else {
+ $size_012 = 0;
+ $t_013 = $t_010;
+ label = 9;
+ break;
+ }
+ case 9:
+ $add = $size_012 + 1 | 0;
+ $right = $t_013 | 0;
+ $t_0 = HEAP32[$right >> 2] | 0;
+ $tobool18 = ($t_0 | 0) == 0;
+ if ($tobool18) {
+ $size_0_lcssa = $add;
+ label = 10;
+ break;
+ } else {
+ $size_012 = $add;
+ $t_013 = $t_0;
+ label = 9;
+ break;
+ }
+ case 10:
+ $6 = HEAP32[$data >> 2] | 0;
+ $size20 = $6 + 16 | 0;
+ HEAP32[$size20 >> 2] = $size_0_lcssa;
+ label = 11;
+ break;
+ case 11:
+ $7 = HEAP32[$data >> 2] | 0;
+ $size24 = $7 + 16 | 0;
+ $8 = HEAP32[$size24 >> 2] | 0;
+ return $8 | 0;
+ }
+ return 0;
+}
+function _treecount($e) {
+ $e = $e | 0;
+ var $tobool = 0, $hl = 0, $_left = 0, $0 = 0, $call = 0, $right = 0, $1 = 0, $call1 = 0, $add = 0, $add2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($e | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $hl = $e + 4 | 0;
+ $_left = $hl;
+ $0 = HEAP32[$_left >> 2] | 0;
+ $call = _treecount($0) | 0;
+ $right = $e | 0;
+ $1 = HEAP32[$right >> 2] | 0;
+ $call1 = _treecount($1) | 0;
+ $add = $call + 1 | 0;
+ $add2 = $add + $call1 | 0;
+ return $add2 | 0;
+ case 4:
+ return 0;
+ }
+ return 0;
+}
+function _dtstrhash($h, $args, $n) {
+ $h = $h | 0;
+ $args = $args | 0;
+ $n = $n | 0;
+ var $cmp = 0, $0 = 0, $cmp120 = 0, $1 = 0, $h_addr_022 = 0, $s_021 = 0, $conv = 0, $shl = 0, $add = 0, $arrayidx4 = 0, $2 = 0, $conv5 = 0, $add6 = 0, $mul = 0, $tobool = 0, $cond = 0, $add_ptr = 0, $3 = 0, $cmp1 = 0, $h_addr_0_lcssa = 0, $s_0_lcssa = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $add_ptr9_sum = 0, $add_ptr10 = 0, $cmp1224 = 0, $h_addr_126 = 0, $s_125 = 0, $4 = 0, $conv16 = 0, $shl17 = 0, $add18 = 0, $arrayidx19 = 0, $5 = 0, $conv20 = 0, $add21 = 0, $mul22 = 0, $add_ptr24 = 0, $cmp12 = 0, $h_addr_1_lcssa = 0, $s_1_lcssa = 0, $cmp26 = 0, $6 = 0, $conv30 = 0, $shl31 = 0, $add32 = 0, $mul33 = 0, $n_addr_0 = 0, $h_addr_2 = 0, $add35 = 0, $mul36 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($n | 0) < 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$args] | 0;
+ $cmp120 = $0 << 24 >> 24 == 0;
+ if ($cmp120) {
+ $s_0_lcssa = $args;
+ $h_addr_0_lcssa = $h;
+ label = 5;
+ break;
+ } else {
+ $s_021 = $args;
+ $h_addr_022 = $h;
+ $1 = $0;
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = $1 & 255;
+ $shl = $conv << 8;
+ $add = $shl + $h_addr_022 | 0;
+ $arrayidx4 = $s_021 + 1 | 0;
+ $2 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $2 & 255;
+ $add6 = $add + $conv5 | 0;
+ $mul = Math_imul($add6, 17109811);
+ $tobool = $2 << 24 >> 24 != 0;
+ $cond = $tobool ? 2 : 1;
+ $add_ptr = $s_021 + $cond | 0;
+ $3 = HEAP8[$add_ptr] | 0;
+ $cmp1 = $3 << 24 >> 24 == 0;
+ if ($cmp1) {
+ $s_0_lcssa = $add_ptr;
+ $h_addr_0_lcssa = $mul;
+ label = 5;
+ break;
+ } else {
+ $s_021 = $add_ptr;
+ $h_addr_022 = $mul;
+ $1 = $3;
+ label = 4;
+ break;
+ }
+ case 5:
+ $sub_ptr_lhs_cast = $s_0_lcssa;
+ $sub_ptr_rhs_cast = $args;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $h_addr_2 = $h_addr_0_lcssa;
+ $n_addr_0 = $sub_ptr_sub;
+ label = 10;
+ break;
+ case 6:
+ $add_ptr9_sum = $n - 1 | 0;
+ $add_ptr10 = $args + $add_ptr9_sum | 0;
+ $cmp1224 = ($add_ptr9_sum | 0) > 0;
+ if ($cmp1224) {
+ $s_125 = $args;
+ $h_addr_126 = $h;
+ label = 7;
+ break;
+ } else {
+ $s_1_lcssa = $args;
+ $h_addr_1_lcssa = $h;
+ label = 8;
+ break;
+ }
+ case 7:
+ $4 = HEAP8[$s_125] | 0;
+ $conv16 = $4 & 255;
+ $shl17 = $conv16 << 8;
+ $add18 = $shl17 + $h_addr_126 | 0;
+ $arrayidx19 = $s_125 + 1 | 0;
+ $5 = HEAP8[$arrayidx19] | 0;
+ $conv20 = $5 & 255;
+ $add21 = $add18 + $conv20 | 0;
+ $mul22 = Math_imul($add21, 17109811);
+ $add_ptr24 = $s_125 + 2 | 0;
+ $cmp12 = $add_ptr24 >>> 0 < $add_ptr10 >>> 0;
+ if ($cmp12) {
+ $s_125 = $add_ptr24;
+ $h_addr_126 = $mul22;
+ label = 7;
+ break;
+ } else {
+ $s_1_lcssa = $add_ptr24;
+ $h_addr_1_lcssa = $mul22;
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp26 = $s_1_lcssa >>> 0 > $add_ptr10 >>> 0;
+ if ($cmp26) {
+ $h_addr_2 = $h_addr_1_lcssa;
+ $n_addr_0 = $n;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $6 = HEAP8[$s_1_lcssa] | 0;
+ $conv30 = $6 & 255;
+ $shl31 = $conv30 << 8;
+ $add32 = $shl31 + $h_addr_1_lcssa | 0;
+ $mul33 = Math_imul($add32, 17109811);
+ $h_addr_2 = $mul33;
+ $n_addr_0 = $n;
+ label = 10;
+ break;
+ case 10:
+ $add35 = $h_addr_2 + $n_addr_0 | 0;
+ $mul36 = Math_imul($add35, 17109811);
+ return $mul36 | 0;
+ }
+ return 0;
+}
+function _dttree($dt, $obj, $type) {
+ $dt = $dt | 0;
+ $obj = $obj | 0;
+ $type = $type | 0;
+ var $link = 0, $turn = 0, $data = 0, $0 = 0, $type1 = 0, $1 = 0, $and = 0, $tobool = 0, $2 = 0, $call = 0, $disc2 = 0, $3 = 0, $key3 = 0, $4 = 0, $size = 0, $5 = 0, $link4 = 0, $6 = 0, $comparf = 0, $7 = 0, $type5 = 0, $8 = 0, $and6 = 0, $9 = 0, $here = 0, $10 = 0, $tobool8 = 0, $tobool9 = 0, $and10 = 0, $tobool11 = 0, $and13 = 0, $tobool14 = 0, $freef = 0, $11 = 0, $tobool16 = 0, $12 = 0, $cmp19 = 0, $memoryf = 0, $cmp30 = 0, $idx_neg = 0, $root_0 = 0, $hl = 0, $_left = 0, $13 = 0, $tobool21 = 0, $right = 0, $14 = 0, $15 = 0, $_c389 = 0, $right25 = 0, $16 = 0, $17 = 0, $tobool27 = 0, $obj32 = 0, $18 = 0, $19 = 0, $20 = 0, $add_ptr = 0, $cond35 = 0, $21 = 0, $cmp38 = 0, $22 = 0, $23 = 0, $call40 = 0, $tobool42 = 0, $24 = 0, $size45 = 0, $25 = 0, $here47 = 0, $and48 = 0, $tobool49 = 0, $right52431 = 0, $26 = 0, $tobool53432 = 0, $hl63425 = 0, $_left64426 = 0, $27 = 0, $tobool65427 = 0, $28 = 0, $right52434 = 0, $root_1433 = 0, $hl55 = 0, $_left56 = 0, $29 = 0, $30 = 0, $root_1_c = 0, $right52 = 0, $31 = 0, $tobool53 = 0, $32 = 0, $hl63429 = 0, $root_2428 = 0, $right67 = 0, $33 = 0, $34 = 0, $_c = 0, $hl63 = 0, $_left64 = 0, $35 = 0, $tobool65 = 0, $root_3 = 0, $36 = 0, $here74 = 0, $cmp75 = 0, $obj77 = 0, $37 = 0, $38 = 0, $39 = 0, $idx_neg79 = 0, $add_ptr80 = 0, $meth = 0, $40 = 0, $type84 = 0, $41 = 0, $cmp85 = 0, $and86 = 0, $tobool87 = 0, $cmp89 = 0, $add_ptr91 = 0, $42 = 0, $43 = 0, $cond95 = 0, $searchf96 = 0, $44 = 0, $call97 = 0, $tobool98496 = 0, $tobool106 = 0, $cmp110 = 0, $o_0497 = 0, $add_ptr101 = 0, $45 = 0, $46 = 0, $cond105 = 0, $call108 = 0, $call112 = 0, $call114 = 0, $cond118 = 0, $cmp119 = 0, $cmp122 = 0, $47 = 0, $here125 = 0, $48 = 0, $hl126 = 0, $_left127 = 0, $49 = 0, $right128 = 0, $right129 = 0, $50 = 0, $51 = 0, $_c411 = 0, $52 = 0, $call135 = 0, $tobool98 = 0, $and137 = 0, $tobool138 = 0, $and140 = 0, $tobool141 = 0, $cmp144 = 0, $add_ptr146 = 0, $53 = 0, $54 = 0, $cond152 = 0, $tobool153 = 0, $and157 = 0, $tobool158 = 0, $55 = 0, $cmp160 = 0, $obj162 = 0, $56 = 0, $57 = 0, $idx_neg164 = 0, $add_ptr165 = 0, $cond167 = 0, $cmp168 = 0, $add_ptr170 = 0, $58 = 0, $59 = 0, $cond174 = 0, $tobool175 = 0, $tobool179 = 0, $cmp181 = 0, $obj183 = 0, $60 = 0, $61 = 0, $62 = 0, $idx_neg185 = 0, $add_ptr186 = 0, $cond188 = 0, $cmp189 = 0, $cmp191 = 0, $add_ptr193 = 0, $63 = 0, $64 = 0, $key_0 = 0, $me_0 = 0, $obj_addr_0 = 0, $65 = 0, $type199 = 0, $66 = 0, $cmp200 = 0, $67 = 0, $minp203 = 0, $68 = 0, $cmp204 = 0, $and206 = 0, $tobool207 = 0, $cmp212 = 0, $cmp220 = 0, $tobool227 = 0, $cmp231 = 0, $idx_neg216 = 0, $l_2_ph = 0, $r_2_ph = 0, $root_6_ph = 0, $cmp317 = 0, $cmp325 = 0, $tobool332 = 0, $cmp373 = 0, $idx_neg358 = 0, $cmp336 = 0, $idx_neg321 = 0, $cmp437 = 0, $idx_neg422 = 0, $t_0 = 0, $n_0 = 0, $cmp210 = 0, $cmp266485 = 0, $obj214 = 0, $69 = 0, $70 = 0, $71 = 0, $add_ptr217 = 0, $cond219 = 0, $add_ptr222 = 0, $72 = 0, $73 = 0, $cond226 = 0, $call229 = 0, $call233 = 0, $call235 = 0, $cond239 = 0, $cmp240 = 0, $obj244 = 0, $74 = 0, $75 = 0, $76 = 0, $idx_neg246 = 0, $add_ptr247 = 0, $arrayidx = 0, $cmp251 = 0, $hl253 = 0, $_left254 = 0, $right256 = 0, $cond258_in = 0, $cond258 = 0, $tobool259 = 0, $inc = 0, $root_4489 = 0, $n_1488 = 0, $r_0487 = 0, $l_0486 = 0, $arrayidx268 = 0, $77 = 0, $cmp269 = 0, $hl271 = 0, $_left272 = 0, $78 = 0, $add407 = 0, $arrayidx273 = 0, $79 = 0, $cmp274 = 0, $right276 = 0, $80 = 0, $81 = 0, $_c409 = 0, $82 = 0, $_c410 = 0, $hl282 = 0, $_left283 = 0, $right285 = 0, $83 = 0, $root_4_c408 = 0, $right288 = 0, $right291 = 0, $84 = 0, $add292405 = 0, $arrayidx293 = 0, $85 = 0, $cmp294 = 0, $hl296 = 0, $_left297 = 0, $86 = 0, $87 = 0, $root_4_c = 0, $right301 = 0, $right302 = 0, $88 = 0, $_c406 = 0, $right306 = 0, $hl307 = 0, $_left308 = 0, $l_1 = 0, $r_1 = 0, $root_5_in = 0, $root_5 = 0, $add312 = 0, $cmp266 = 0, $r_2 = 0, $root_6 = 0, $obj319 = 0, $89 = 0, $90 = 0, $91 = 0, $add_ptr322 = 0, $cond324 = 0, $add_ptr327 = 0, $92 = 0, $93 = 0, $cond331 = 0, $call334 = 0, $call338 = 0, $call340 = 0, $cond344 = 0, $cmp345 = 0, $cmp348 = 0, $hl350 = 0, $_left351 = 0, $94 = 0, $tobool352 = 0, $obj356 = 0, $95 = 0, $96 = 0, $97 = 0, $add_ptr359 = 0, $cond361 = 0, $add_ptr364 = 0, $98 = 0, $99 = 0, $cond368 = 0, $call371 = 0, $call375 = 0, $call377 = 0, $cond381 = 0, $cmp382 = 0, $right384 = 0, $100 = 0, $101 = 0, $_c403 = 0, $102 = 0, $_c404 = 0, $hl390 = 0, $_left391 = 0, $103 = 0, $tobool392 = 0, $cmp396 = 0, $104 = 0, $root_6_c402 = 0, $right401 = 0, $105 = 0, $root_6_c401 = 0, $right404 = 0, $106 = 0, $tobool405 = 0, $107 = 0, $root_6_c400 = 0, $right415 = 0, $108 = 0, $tobool416 = 0, $obj420 = 0, $109 = 0, $110 = 0, $111 = 0, $add_ptr423 = 0, $cond425 = 0, $add_ptr428 = 0, $112 = 0, $113 = 0, $cond432 = 0, $call435 = 0, $call439 = 0, $call441 = 0, $cond445 = 0, $cmp446 = 0, $hl448 = 0, $_left449 = 0, $114 = 0, $115 = 0, $root_6_c = 0, $right453 = 0, $right454 = 0, $116 = 0, $tobool455 = 0, $l_2_ph459 = 0, $r_2_ph460 = 0, $root_6_ph461 = 0, $cmp459 = 0, $right461 = 0, $117 = 0, $_c399 = 0, $right465 = 0, $hl466 = 0, $_left467 = 0, $118 = 0, $tobool468 = 0, $right474 = 0, $l_3 = 0, $r_3 = 0, $me_1 = 0, $root_7 = 0, $obj_addr_1 = 0, $tobool482 = 0, $119 = 0, $or = 0, $hl485 = 0, $_left486 = 0, $120 = 0, $right487 = 0, $right488 = 0, $121 = 0, $122 = 0, $_c396 = 0, $and491 = 0, $tobool492 = 0, $root_8 = 0, $right494 = 0, $123 = 0, $124 = 0, $_c391 = 0, $hl497 = 0, $_left498 = 0, $125 = 0, $right499 = 0, $126 = 0, $type501 = 0, $127 = 0, $and502 = 0, $tobool503 = 0, $and505 = 0, $tobool506 = 0, $cmp508 = 0, $obj510 = 0, $128 = 0, $129 = 0, $130 = 0, $idx_neg512 = 0, $add_ptr513 = 0, $cond515 = 0, $cmp516 = 0, $add_ptr518 = 0, $131 = 0, $132 = 0, $cond522 = 0, $hl524442 = 0, $_left525443 = 0, $133 = 0, $tobool526444 = 0, $tobool555 = 0, $cmp559 = 0, $idx_neg544 = 0, $134 = 0, $hl524446 = 0, $root_9445 = 0, $right529436 = 0, $135 = 0, $tobool530437 = 0, $136 = 0, $right529439 = 0, $t_1438 = 0, $hl532 = 0, $_left533 = 0, $137 = 0, $138 = 0, $t_1_c393 = 0, $right529 = 0, $139 = 0, $tobool530 = 0, $right529_lcssa = 0, $t_1_lcssa = 0, $140 = 0, $t_1_c = 0, $obj542 = 0, $141 = 0, $142 = 0, $143 = 0, $add_ptr545 = 0, $cond547 = 0, $add_ptr550 = 0, $144 = 0, $145 = 0, $cond554 = 0, $call557 = 0, $call561 = 0, $call563 = 0, $cond567 = 0, $cmp568 = 0, $146 = 0, $_c392 = 0, $hl524 = 0, $_left525 = 0, $147 = 0, $tobool526 = 0, $root_10 = 0, $148 = 0, $here578 = 0, $cmp579 = 0, $obj581 = 0, $149 = 0, $150 = 0, $151 = 0, $idx_neg583 = 0, $add_ptr584 = 0, $and588 = 0, $tobool589 = 0, $right591 = 0, $152 = 0, $153 = 0, $_c398 = 0, $obj_addr_1421 = 0, $r_3414 = 0, $hl596 = 0, $_left597 = 0, $154 = 0, $tobool598 = 0, $hl601453 = 0, $_left602454 = 0, $155 = 0, $tobool603455 = 0, $156 = 0, $hl601457 = 0, $root_11456 = 0, $right605 = 0, $157 = 0, $158 = 0, $_c395 = 0, $hl601 = 0, $_left602 = 0, $159 = 0, $tobool603 = 0, $root_11_lcssa = 0, $right610 = 0, $160 = 0, $161 = 0, $_c394 = 0, $and615 = 0, $tobool616 = 0, $hl618 = 0, $_left619 = 0, $162 = 0, $163 = 0, $164 = 0, $root_7_c397 = 0, $obj_addr_1424 = 0, $r_3416 = 0, $right625 = 0, $165 = 0, $tobool626 = 0, $right629448 = 0, $166 = 0, $tobool630449 = 0, $167 = 0, $right629451 = 0, $root_12450 = 0, $hl632 = 0, $_left633 = 0, $168 = 0, $169 = 0, $root_12_c = 0, $right629 = 0, $170 = 0, $tobool630 = 0, $root_12_lcssa = 0, $hl638 = 0, $_left639 = 0, $171 = 0, $and643 = 0, $tobool644 = 0, $r_4 = 0, $root_13 = 0, $cmp646 = 0, $obj648 = 0, $172 = 0, $173 = 0, $174 = 0, $idx_neg650 = 0, $add_ptr651 = 0, $cond653 = 0, $freef654 = 0, $175 = 0, $tobool655 = 0, $and657 = 0, $tobool658 = 0, $176 = 0, $cmp663 = 0, $memoryf665 = 0, $177 = 0, $178 = 0, $call666 = 0, $179 = 0, $size669 = 0, $180 = 0, $sub = 0, $cmp670 = 0, $181 = 0, $size673 = 0, $and676 = 0, $tobool677 = 0, $182 = 0, $type680 = 0, $183 = 0, $and681 = 0, $tobool682 = 0, $184 = 0, $hl687 = 0, $_left688 = 0, $185 = 0, $186 = 0, $root_7_c = 0, $and693 = 0, $tobool694 = 0, $187 = 0, $type697 = 0, $188 = 0, $and698 = 0, $tobool699 = 0, $freef701 = 0, $189 = 0, $tobool702 = 0, $190 = 0, $cmp707 = 0, $memoryf709 = 0, $191 = 0, $192 = 0, $call710 = 0, $193 = 0, $hl715 = 0, $_left716 = 0, $194 = 0, $right717 = 0, $195 = 0, $me_1_c = 0, $196 = 0, $size721 = 0, $197 = 0, $add722 = 0, $obj_addr_1422 = 0, $me_1418 = 0, $r_3415 = 0, $l_3413 = 0, $198 = 0, $right733 = 0, $and734 = 0, $tobool735 = 0, $and738 = 0, $tobool739 = 0, $and742 = 0, $tobool743 = 0, $r_5_ph = 0, $obj_addr_2_ph = 0, $r_5 = 0, $hl746 = 0, $_left747 = 0, $199 = 0, $tobool748 = 0, $right751 = 0, $200 = 0, $201 = 0, $_c390 = 0, $hl754 = 0, $_left755 = 0, $202 = 0, $203 = 0, $here757 = 0, $and758 = 0, $tobool759 = 0, $cond763 = 0, $and765 = 0, $tobool766 = 0, $obj_addr_1423 = 0, $root_7419 = 0, $r_3417 = 0, $makef = 0, $204 = 0, $tobool768 = 0, $and770 = 0, $tobool771 = 0, $call774 = 0, $obj_addr_3 = 0, $tobool776 = 0, $cmp778 = 0, $add_ptr780 = 0, $205 = 0, $memoryf782 = 0, $206 = 0, $call783 = 0, $207 = 0, $tobool784 = 0, $obj786 = 0, $208 = 0, $209 = 0, $tobool789 = 0, $freef791 = 0, $210 = 0, $tobool792 = 0, $and794 = 0, $tobool795 = 0, $root_14 = 0, $tobool802 = 0, $211 = 0, $size805 = 0, $212 = 0, $cmp806 = 0, $add810 = 0, $and814 = 0, $tobool815 = 0, $213 = 0, $size818 = 0, $214 = 0, $add819 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $link = __stackBase__ | 0;
+ $turn = __stackBase__ + 8 | 0;
+ $data = $dt + 8 | 0;
+ $0 = HEAP32[$data >> 2] | 0;
+ $type1 = $0 | 0;
+ $1 = HEAP32[$type1 >> 2] | 0;
+ $and = $1 & 4096;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $dt;
+ $call = _dtrestore($2, 0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $disc2 = $dt + 4 | 0;
+ $3 = HEAP32[$disc2 >> 2] | 0;
+ $key3 = $3 | 0;
+ $4 = HEAP32[$key3 >> 2] | 0;
+ $size = $3 + 4 | 0;
+ $5 = HEAP32[$size >> 2] | 0;
+ $link4 = $3 + 8 | 0;
+ $6 = HEAP32[$link4 >> 2] | 0;
+ $comparf = $3 + 20 | 0;
+ $7 = HEAP32[$comparf >> 2] | 0;
+ $type5 = $dt + 20 | 0;
+ $8 = HEAP32[$type5 >> 2] | 0;
+ $and6 = $8 & -32769;
+ HEAP32[$type5 >> 2] = $and6;
+ $9 = HEAP32[$data >> 2] | 0;
+ $here = $9 + 4 | 0;
+ $10 = HEAP32[$here >> 2] | 0;
+ $tobool8 = ($obj | 0) == 0;
+ if ($tobool8) {
+ label = 5;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 5:
+ $tobool9 = ($10 | 0) == 0;
+ if ($tobool9) {
+ $retval_0 = 0;
+ label = 231;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $and10 = $type & 448;
+ $tobool11 = ($and10 | 0) == 0;
+ if ($tobool11) {
+ $retval_0 = 0;
+ label = 231;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $and13 = $type & 64;
+ $tobool14 = ($and13 | 0) == 0;
+ if ($tobool14) {
+ label = 22;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $freef = $3 + 16 | 0;
+ $11 = HEAP32[$freef >> 2] | 0;
+ $tobool16 = ($11 | 0) == 0;
+ if ($tobool16) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $12 = HEAP32[$link4 >> 2] | 0;
+ $cmp19 = ($12 | 0) < 0;
+ if ($cmp19) {
+ label = 10;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 10:
+ $memoryf = $dt + 12 | 0;
+ $cmp30 = ($6 | 0) < 0;
+ $idx_neg = -$6 | 0;
+ $root_0 = $10;
+ label = 11;
+ break;
+ case 11:
+ $hl = $root_0 + 4 | 0;
+ $_left = $hl;
+ $13 = HEAP32[$_left >> 2] | 0;
+ $tobool21 = ($13 | 0) == 0;
+ if ($tobool21) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $right = $13 | 0;
+ $14 = HEAP32[$right >> 2] | 0;
+ $15 = $hl | 0;
+ $_c389 = $14;
+ HEAP32[$15 >> 2] = $_c389;
+ HEAP32[$right >> 2] = $root_0;
+ $root_0 = $13;
+ label = 11;
+ break;
+ case 13:
+ $right25 = $root_0 | 0;
+ $16 = HEAP32[$right25 >> 2] | 0;
+ $17 = HEAP32[$freef >> 2] | 0;
+ $tobool27 = ($17 | 0) == 0;
+ if ($tobool27) {
+ label = 18;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ if ($cmp30) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $obj32 = $root_0 + 8 | 0;
+ $18 = $obj32;
+ $19 = HEAP32[$18 >> 2] | 0;
+ $cond35 = $19;
+ label = 17;
+ break;
+ case 16:
+ $20 = $root_0;
+ $add_ptr = $20 + $idx_neg | 0;
+ $cond35 = $add_ptr;
+ label = 17;
+ break;
+ case 17:
+ FUNCTION_TABLE_viii[$17 & 1023]($dt, $cond35, $3);
+ label = 18;
+ break;
+ case 18:
+ $21 = HEAP32[$link4 >> 2] | 0;
+ $cmp38 = ($21 | 0) < 0;
+ if ($cmp38) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $22 = HEAP32[$memoryf >> 2] | 0;
+ $23 = $root_0;
+ $call40 = FUNCTION_TABLE_iiiii[$22 & 1023]($dt, $23, 0, $3) | 0;
+ label = 20;
+ break;
+ case 20:
+ $tobool42 = ($16 | 0) == 0;
+ if ($tobool42) {
+ label = 21;
+ break;
+ } else {
+ $root_0 = $16;
+ label = 11;
+ break;
+ }
+ case 21:
+ $24 = HEAP32[$data >> 2] | 0;
+ $size45 = $24 + 16 | 0;
+ HEAP32[$size45 >> 2] = 0;
+ $25 = HEAP32[$data >> 2] | 0;
+ $here47 = $25 + 4 | 0;
+ HEAP32[$here47 >> 2] = 0;
+ $retval_0 = 0;
+ label = 231;
+ break;
+ case 22:
+ $and48 = $type & 256;
+ $tobool49 = ($and48 | 0) == 0;
+ if ($tobool49) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $right52431 = $10 | 0;
+ $26 = HEAP32[$right52431 >> 2] | 0;
+ $tobool53432 = ($26 | 0) == 0;
+ if ($tobool53432) {
+ $root_3 = $10;
+ label = 27;
+ break;
+ } else {
+ $root_1433 = $10;
+ $right52434 = $right52431;
+ $28 = $26;
+ label = 25;
+ break;
+ }
+ case 24:
+ $hl63425 = $10 + 4 | 0;
+ $_left64426 = $hl63425;
+ $27 = HEAP32[$_left64426 >> 2] | 0;
+ $tobool65427 = ($27 | 0) == 0;
+ if ($tobool65427) {
+ $root_3 = $10;
+ label = 27;
+ break;
+ } else {
+ $root_2428 = $10;
+ $hl63429 = $hl63425;
+ $32 = $27;
+ label = 26;
+ break;
+ }
+ case 25:
+ $hl55 = $28 + 4 | 0;
+ $_left56 = $hl55;
+ $29 = HEAP32[$_left56 >> 2] | 0;
+ HEAP32[$right52434 >> 2] = $29;
+ $30 = $hl55 | 0;
+ $root_1_c = $root_1433;
+ HEAP32[$30 >> 2] = $root_1_c;
+ $right52 = $28 | 0;
+ $31 = HEAP32[$right52 >> 2] | 0;
+ $tobool53 = ($31 | 0) == 0;
+ if ($tobool53) {
+ $root_3 = $28;
+ label = 27;
+ break;
+ } else {
+ $root_1433 = $28;
+ $right52434 = $right52;
+ $28 = $31;
+ label = 25;
+ break;
+ }
+ case 26:
+ $right67 = $32 | 0;
+ $33 = HEAP32[$right67 >> 2] | 0;
+ $34 = $hl63429 | 0;
+ $_c = $33;
+ HEAP32[$34 >> 2] = $_c;
+ HEAP32[$right67 >> 2] = $root_2428;
+ $hl63 = $32 + 4 | 0;
+ $_left64 = $hl63;
+ $35 = HEAP32[$_left64 >> 2] | 0;
+ $tobool65 = ($35 | 0) == 0;
+ if ($tobool65) {
+ $root_3 = $32;
+ label = 27;
+ break;
+ } else {
+ $root_2428 = $32;
+ $hl63429 = $hl63;
+ $32 = $35;
+ label = 26;
+ break;
+ }
+ case 27:
+ $36 = HEAP32[$data >> 2] | 0;
+ $here74 = $36 + 4 | 0;
+ HEAP32[$here74 >> 2] = $root_3;
+ $cmp75 = ($6 | 0) < 0;
+ if ($cmp75) {
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ $obj77 = $root_3 + 8 | 0;
+ $37 = $obj77;
+ $38 = HEAP32[$37 >> 2] | 0;
+ $retval_0 = $38;
+ label = 231;
+ break;
+ case 29:
+ $39 = $root_3;
+ $idx_neg79 = -$6 | 0;
+ $add_ptr80 = $39 + $idx_neg79 | 0;
+ $retval_0 = $add_ptr80;
+ label = 231;
+ break;
+ case 30:
+ $meth = $dt + 16 | 0;
+ $40 = HEAP32[$meth >> 2] | 0;
+ $type84 = $40 + 4 | 0;
+ $41 = HEAP32[$type84 >> 2] | 0;
+ $cmp85 = ($41 | 0) == 8;
+ if ($cmp85) {
+ label = 31;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 31:
+ $and86 = $type & 4098;
+ $tobool87 = ($and86 | 0) == 0;
+ if ($tobool87) {
+ label = 47;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $cmp89 = ($5 | 0) < 0;
+ $add_ptr91 = $obj + $4 | 0;
+ if ($cmp89) {
+ label = 33;
+ break;
+ } else {
+ $cond95 = $add_ptr91;
+ label = 34;
+ break;
+ }
+ case 33:
+ $42 = $add_ptr91;
+ $43 = HEAP32[$42 >> 2] | 0;
+ $cond95 = $43;
+ label = 34;
+ break;
+ case 34:
+ $searchf96 = $dt;
+ $44 = HEAP32[$searchf96 >> 2] | 0;
+ $call97 = FUNCTION_TABLE_iiii[$44 & 1023]($dt, $obj, 4) | 0;
+ $tobool98496 = ($call97 | 0) == 0;
+ if ($tobool98496) {
+ label = 47;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $tobool106 = ($7 | 0) == 0;
+ $cmp110 = ($5 | 0) < 1;
+ $o_0497 = $call97;
+ label = 36;
+ break;
+ case 36:
+ $add_ptr101 = $o_0497 + $4 | 0;
+ if ($cmp89) {
+ label = 37;
+ break;
+ } else {
+ $cond105 = $add_ptr101;
+ label = 38;
+ break;
+ }
+ case 37:
+ $45 = $add_ptr101;
+ $46 = HEAP32[$45 >> 2] | 0;
+ $cond105 = $46;
+ label = 38;
+ break;
+ case 38:
+ if ($tobool106) {
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $call108 = FUNCTION_TABLE_iiiii[$7 & 1023]($dt, $cond95, $cond105, $3) | 0;
+ $cond118 = $call108;
+ label = 43;
+ break;
+ case 40:
+ if ($cmp110) {
+ label = 41;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 41:
+ $call112 = _strcmp($cond95 | 0, $cond105 | 0) | 0;
+ $cond118 = $call112;
+ label = 43;
+ break;
+ case 42:
+ $call114 = _memcmp($cond95 | 0, $cond105 | 0, $5 | 0) | 0;
+ $cond118 = $call114;
+ label = 43;
+ break;
+ case 43:
+ $cmp119 = ($cond118 | 0) == 0;
+ if ($cmp119) {
+ label = 44;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 44:
+ $cmp122 = ($o_0497 | 0) == ($obj | 0);
+ if ($cmp122) {
+ label = 45;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 45:
+ $47 = HEAP32[$data >> 2] | 0;
+ $here125 = $47 + 4 | 0;
+ $48 = HEAP32[$here125 >> 2] | 0;
+ $hl126 = $48 + 4 | 0;
+ $_left127 = $hl126;
+ $49 = HEAP32[$_left127 >> 2] | 0;
+ $right128 = $link | 0;
+ HEAP32[$right128 >> 2] = $49;
+ $right129 = $48 | 0;
+ $50 = HEAP32[$right129 >> 2] | 0;
+ $51 = $link + 4 | 0;
+ $_c411 = $50;
+ HEAP32[$51 >> 2] = $_c411;
+ $root_13 = $48;
+ $r_4 = $link;
+ label = 187;
+ break;
+ case 46:
+ $52 = HEAP32[$searchf96 >> 2] | 0;
+ $call135 = FUNCTION_TABLE_iiii[$52 & 1023]($dt, $o_0497, 8) | 0;
+ $tobool98 = ($call135 | 0) == 0;
+ if ($tobool98) {
+ label = 47;
+ break;
+ } else {
+ $o_0497 = $call135;
+ label = 36;
+ break;
+ }
+ case 47:
+ $and137 = $type & 2565;
+ $tobool138 = ($and137 | 0) == 0;
+ if ($tobool138) {
+ label = 52;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $and140 = $type & 512;
+ $tobool141 = ($and140 | 0) == 0;
+ if ($tobool141) {
+ label = 49;
+ break;
+ } else {
+ $cond152 = $obj;
+ label = 51;
+ break;
+ }
+ case 49:
+ $cmp144 = ($5 | 0) < 0;
+ $add_ptr146 = $obj + $4 | 0;
+ if ($cmp144) {
+ label = 50;
+ break;
+ } else {
+ $cond152 = $add_ptr146;
+ label = 51;
+ break;
+ }
+ case 50:
+ $53 = $add_ptr146;
+ $54 = HEAP32[$53 >> 2] | 0;
+ $cond152 = $54;
+ label = 51;
+ break;
+ case 51:
+ $tobool153 = ($10 | 0) == 0;
+ if ($tobool153) {
+ $l_3413 = $link;
+ $r_3415 = $link;
+ $me_1418 = 0;
+ $obj_addr_1422 = $obj;
+ label = 207;
+ break;
+ } else {
+ $obj_addr_0 = $obj;
+ $me_0 = 0;
+ $key_0 = $cond152;
+ label = 66;
+ break;
+ }
+ case 52:
+ $and157 = $type & 32;
+ $tobool158 = ($and157 | 0) == 0;
+ if ($tobool158) {
+ label = 59;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $55 = $obj;
+ $cmp160 = ($6 | 0) < 0;
+ if ($cmp160) {
+ label = 54;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 54:
+ $obj162 = $obj + 8 | 0;
+ $56 = $obj162;
+ $57 = HEAP32[$56 >> 2] | 0;
+ $cond167 = $57;
+ label = 56;
+ break;
+ case 55:
+ $idx_neg164 = -$6 | 0;
+ $add_ptr165 = $obj + $idx_neg164 | 0;
+ $cond167 = $add_ptr165;
+ label = 56;
+ break;
+ case 56:
+ $cmp168 = ($5 | 0) < 0;
+ $add_ptr170 = $cond167 + $4 | 0;
+ if ($cmp168) {
+ label = 57;
+ break;
+ } else {
+ $cond174 = $add_ptr170;
+ label = 58;
+ break;
+ }
+ case 57:
+ $58 = $add_ptr170;
+ $59 = HEAP32[$58 >> 2] | 0;
+ $cond174 = $59;
+ label = 58;
+ break;
+ case 58:
+ $tobool175 = ($10 | 0) == 0;
+ if ($tobool175) {
+ $l_3413 = $link;
+ $r_3415 = $link;
+ $me_1418 = $55;
+ $obj_addr_1422 = $cond167;
+ label = 207;
+ break;
+ } else {
+ $obj_addr_0 = $cond167;
+ $me_0 = $55;
+ $key_0 = $cond174;
+ label = 66;
+ break;
+ }
+ case 59:
+ $tobool179 = ($10 | 0) == 0;
+ if ($tobool179) {
+ $l_3413 = $link;
+ $r_3415 = $link;
+ $me_1418 = 0;
+ $obj_addr_1422 = $obj;
+ label = 207;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $cmp181 = ($6 | 0) < 0;
+ if ($cmp181) {
+ label = 61;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 61:
+ $obj183 = $10 + 8 | 0;
+ $60 = $obj183;
+ $61 = HEAP32[$60 >> 2] | 0;
+ $cond188 = $61;
+ label = 63;
+ break;
+ case 62:
+ $62 = $10;
+ $idx_neg185 = -$6 | 0;
+ $add_ptr186 = $62 + $idx_neg185 | 0;
+ $cond188 = $add_ptr186;
+ label = 63;
+ break;
+ case 63:
+ $cmp189 = ($cond188 | 0) == ($obj | 0);
+ if ($cmp189) {
+ $obj_addr_1 = $obj;
+ $root_7 = $10;
+ $me_1 = 0;
+ $r_3 = $link;
+ $l_3 = $link;
+ label = 146;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 64:
+ $cmp191 = ($5 | 0) < 0;
+ $add_ptr193 = $obj + $4 | 0;
+ if ($cmp191) {
+ label = 65;
+ break;
+ } else {
+ $obj_addr_0 = $obj;
+ $me_0 = 0;
+ $key_0 = $add_ptr193;
+ label = 66;
+ break;
+ }
+ case 65:
+ $63 = $add_ptr193;
+ $64 = HEAP32[$63 >> 2] | 0;
+ $obj_addr_0 = $obj;
+ $me_0 = 0;
+ $key_0 = $64;
+ label = 66;
+ break;
+ case 66:
+ $65 = HEAP32[$meth >> 2] | 0;
+ $type199 = $65 + 4 | 0;
+ $66 = HEAP32[$type199 >> 2] | 0;
+ $cmp200 = ($66 | 0) == 4;
+ if ($cmp200) {
+ label = 67;
+ break;
+ } else {
+ $root_6_ph = $10;
+ $r_2_ph = $link;
+ $l_2_ph = $link;
+ label = 70;
+ break;
+ }
+ case 67:
+ $67 = HEAP32[$data >> 2] | 0;
+ $minp203 = $67 + 24 | 0;
+ $68 = HEAP32[$minp203 >> 2] | 0;
+ $cmp204 = ($68 | 0) == 0;
+ if ($cmp204) {
+ $root_6_ph = $10;
+ $r_2_ph = $link;
+ $l_2_ph = $link;
+ label = 70;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $and206 = $type & 516;
+ $tobool207 = ($and206 | 0) == 0;
+ if ($tobool207) {
+ $root_6_ph = $10;
+ $r_2_ph = $link;
+ $l_2_ph = $link;
+ label = 70;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 69:
+ $cmp212 = ($6 | 0) < 0;
+ $cmp220 = ($5 | 0) < 0;
+ $tobool227 = ($7 | 0) == 0;
+ $cmp231 = ($5 | 0) < 1;
+ $idx_neg216 = -$6 | 0;
+ $n_0 = 0;
+ $t_0 = $10;
+ label = 71;
+ break;
+ case 70:
+ $cmp317 = ($6 | 0) < 0;
+ $cmp325 = ($5 | 0) < 0;
+ $tobool332 = ($7 | 0) != 0;
+ $cmp373 = ($5 | 0) < 1;
+ $idx_neg358 = -$6 | 0;
+ $cmp336 = ($5 | 0) < 1;
+ $idx_neg321 = -$6 | 0;
+ $cmp437 = ($5 | 0) < 1;
+ $idx_neg422 = -$6 | 0;
+ $root_6_ph461 = $root_6_ph;
+ $r_2_ph460 = $r_2_ph;
+ $l_2_ph459 = $l_2_ph;
+ label = 141;
+ break;
+ case 71:
+ $cmp210 = ($n_0 | 0) < ($68 | 0);
+ if ($cmp210) {
+ label = 73;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 72:
+ $cmp266485 = ($68 | 0) > 0;
+ if ($cmp266485) {
+ $l_0486 = $link;
+ $r_0487 = $link;
+ $n_1488 = 0;
+ $root_4489 = $10;
+ label = 91;
+ break;
+ } else {
+ $root_6_ph = $10;
+ $r_2_ph = $link;
+ $l_2_ph = $link;
+ label = 70;
+ break;
+ }
+ case 73:
+ if ($cmp212) {
+ label = 74;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 74:
+ $obj214 = $t_0 + 8 | 0;
+ $69 = $obj214;
+ $70 = HEAP32[$69 >> 2] | 0;
+ $cond219 = $70;
+ label = 76;
+ break;
+ case 75:
+ $71 = $t_0;
+ $add_ptr217 = $71 + $idx_neg216 | 0;
+ $cond219 = $add_ptr217;
+ label = 76;
+ break;
+ case 76:
+ $add_ptr222 = $cond219 + $4 | 0;
+ if ($cmp220) {
+ label = 77;
+ break;
+ } else {
+ $cond226 = $add_ptr222;
+ label = 78;
+ break;
+ }
+ case 77:
+ $72 = $add_ptr222;
+ $73 = HEAP32[$72 >> 2] | 0;
+ $cond226 = $73;
+ label = 78;
+ break;
+ case 78:
+ if ($tobool227) {
+ label = 80;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 79:
+ $call229 = FUNCTION_TABLE_iiiii[$7 & 1023]($dt, $key_0, $cond226, $3) | 0;
+ $cond239 = $call229;
+ label = 83;
+ break;
+ case 80:
+ if ($cmp231) {
+ label = 81;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 81:
+ $call233 = _strcmp($key_0 | 0, $cond226 | 0) | 0;
+ $cond239 = $call233;
+ label = 83;
+ break;
+ case 82:
+ $call235 = _memcmp($key_0 | 0, $cond226 | 0, $5 | 0) | 0;
+ $cond239 = $call235;
+ label = 83;
+ break;
+ case 83:
+ $cmp240 = ($cond239 | 0) == 0;
+ if ($cmp240) {
+ label = 84;
+ break;
+ } else {
+ label = 87;
+ break;
+ }
+ case 84:
+ if ($cmp212) {
+ label = 85;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 85:
+ $obj244 = $t_0 + 8 | 0;
+ $74 = $obj244;
+ $75 = HEAP32[$74 >> 2] | 0;
+ $retval_0 = $75;
+ label = 231;
+ break;
+ case 86:
+ $76 = $t_0;
+ $idx_neg246 = -$6 | 0;
+ $add_ptr247 = $76 + $idx_neg246 | 0;
+ $retval_0 = $add_ptr247;
+ label = 231;
+ break;
+ case 87:
+ $arrayidx = $turn + ($n_0 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $cond239;
+ $cmp251 = ($cond239 | 0) < 0;
+ if ($cmp251) {
+ label = 88;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 88:
+ $hl253 = $t_0 + 4 | 0;
+ $_left254 = $hl253;
+ $cond258_in = $_left254;
+ label = 90;
+ break;
+ case 89:
+ $right256 = $t_0 | 0;
+ $cond258_in = $right256;
+ label = 90;
+ break;
+ case 90:
+ $cond258 = HEAP32[$cond258_in >> 2] | 0;
+ $tobool259 = ($cond258 | 0) == 0;
+ $inc = $n_0 + 1 | 0;
+ if ($tobool259) {
+ $retval_0 = 0;
+ label = 231;
+ break;
+ } else {
+ $n_0 = $inc;
+ $t_0 = $cond258;
+ label = 71;
+ break;
+ }
+ case 91:
+ $arrayidx268 = $turn + ($n_1488 << 2) | 0;
+ $77 = HEAP32[$arrayidx268 >> 2] | 0;
+ $cmp269 = ($77 | 0) < 0;
+ if ($cmp269) {
+ label = 92;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 92:
+ $hl271 = $root_4489 + 4 | 0;
+ $_left272 = $hl271;
+ $78 = HEAP32[$_left272 >> 2] | 0;
+ $add407 = $n_1488 | 1;
+ $arrayidx273 = $turn + ($add407 << 2) | 0;
+ $79 = HEAP32[$arrayidx273 >> 2] | 0;
+ $cmp274 = ($79 | 0) < 0;
+ if ($cmp274) {
+ label = 93;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 93:
+ $right276 = $78 | 0;
+ $80 = HEAP32[$right276 >> 2] | 0;
+ $81 = $hl271 | 0;
+ $_c409 = $80;
+ HEAP32[$81 >> 2] = $_c409;
+ HEAP32[$right276 >> 2] = $root_4489;
+ $82 = $r_0487 + 4 | 0;
+ $_c410 = $78;
+ HEAP32[$82 >> 2] = $_c410;
+ $hl282 = $78 + 4 | 0;
+ $_left283 = $hl282;
+ $root_5_in = $_left283;
+ $r_1 = $78;
+ $l_1 = $l_0486;
+ label = 98;
+ break;
+ case 94:
+ $right285 = $l_0486 | 0;
+ HEAP32[$right285 >> 2] = $78;
+ $83 = $r_0487 + 4 | 0;
+ $root_4_c408 = $root_4489;
+ HEAP32[$83 >> 2] = $root_4_c408;
+ $right288 = $78 | 0;
+ $root_5_in = $right288;
+ $r_1 = $root_4489;
+ $l_1 = $78;
+ label = 98;
+ break;
+ case 95:
+ $right291 = $root_4489 | 0;
+ $84 = HEAP32[$right291 >> 2] | 0;
+ $add292405 = $n_1488 | 1;
+ $arrayidx293 = $turn + ($add292405 << 2) | 0;
+ $85 = HEAP32[$arrayidx293 >> 2] | 0;
+ $cmp294 = ($85 | 0) > 0;
+ if ($cmp294) {
+ label = 96;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 96:
+ $hl296 = $84 + 4 | 0;
+ $_left297 = $hl296;
+ $86 = HEAP32[$_left297 >> 2] | 0;
+ HEAP32[$right291 >> 2] = $86;
+ $87 = $hl296 | 0;
+ $root_4_c = $root_4489;
+ HEAP32[$87 >> 2] = $root_4_c;
+ $right301 = $l_0486 | 0;
+ HEAP32[$right301 >> 2] = $84;
+ $right302 = $84 | 0;
+ $root_5_in = $right302;
+ $r_1 = $r_0487;
+ $l_1 = $84;
+ label = 98;
+ break;
+ case 97:
+ $88 = $r_0487 + 4 | 0;
+ $_c406 = $84;
+ HEAP32[$88 >> 2] = $_c406;
+ $right306 = $l_0486 | 0;
+ HEAP32[$right306 >> 2] = $root_4489;
+ $hl307 = $84 + 4 | 0;
+ $_left308 = $hl307;
+ $root_5_in = $_left308;
+ $r_1 = $84;
+ $l_1 = $root_4489;
+ label = 98;
+ break;
+ case 98:
+ $root_5 = HEAP32[$root_5_in >> 2] | 0;
+ $add312 = $n_1488 + 2 | 0;
+ $cmp266 = ($add312 | 0) < ($68 | 0);
+ if ($cmp266) {
+ $l_0486 = $l_1;
+ $r_0487 = $r_1;
+ $n_1488 = $add312;
+ $root_4489 = $root_5;
+ label = 91;
+ break;
+ } else {
+ $root_6_ph = $root_5;
+ $r_2_ph = $r_1;
+ $l_2_ph = $l_1;
+ label = 70;
+ break;
+ }
+ case 99:
+ if ($cmp317) {
+ label = 100;
+ break;
+ } else {
+ label = 101;
+ break;
+ }
+ case 100:
+ $obj319 = $root_6 + 8 | 0;
+ $89 = $obj319;
+ $90 = HEAP32[$89 >> 2] | 0;
+ $cond324 = $90;
+ label = 102;
+ break;
+ case 101:
+ $91 = $root_6;
+ $add_ptr322 = $91 + $idx_neg321 | 0;
+ $cond324 = $add_ptr322;
+ label = 102;
+ break;
+ case 102:
+ $add_ptr327 = $cond324 + $4 | 0;
+ if ($cmp325) {
+ label = 103;
+ break;
+ } else {
+ $cond331 = $add_ptr327;
+ label = 104;
+ break;
+ }
+ case 103:
+ $92 = $add_ptr327;
+ $93 = HEAP32[$92 >> 2] | 0;
+ $cond331 = $93;
+ label = 104;
+ break;
+ case 104:
+ if ($tobool332) {
+ label = 105;
+ break;
+ } else {
+ label = 106;
+ break;
+ }
+ case 105:
+ $call334 = FUNCTION_TABLE_iiiii[$7 & 1023]($dt, $key_0, $cond331, $3) | 0;
+ $cond344 = $call334;
+ label = 109;
+ break;
+ case 106:
+ if ($cmp336) {
+ label = 107;
+ break;
+ } else {
+ label = 108;
+ break;
+ }
+ case 107:
+ $call338 = _strcmp($key_0 | 0, $cond331 | 0) | 0;
+ $cond344 = $call338;
+ label = 109;
+ break;
+ case 108:
+ $call340 = _memcmp($key_0 | 0, $cond331 | 0, $5 | 0) | 0;
+ $cond344 = $call340;
+ label = 109;
+ break;
+ case 109:
+ $cmp345 = ($cond344 | 0) == 0;
+ if ($cmp345) {
+ $obj_addr_1 = $obj_addr_0;
+ $root_7 = $root_6;
+ $me_1 = $me_0;
+ $r_3 = $r_2;
+ $l_3 = $l_2_ph459;
+ label = 146;
+ break;
+ } else {
+ label = 110;
+ break;
+ }
+ case 110:
+ $cmp348 = ($cond344 | 0) < 0;
+ if ($cmp348) {
+ label = 111;
+ break;
+ } else {
+ label = 128;
+ break;
+ }
+ case 111:
+ $hl350 = $root_6 + 4 | 0;
+ $_left351 = $hl350;
+ $94 = HEAP32[$_left351 >> 2] | 0;
+ $tobool352 = ($94 | 0) == 0;
+ if ($tobool352) {
+ label = 127;
+ break;
+ } else {
+ label = 112;
+ break;
+ }
+ case 112:
+ if ($cmp317) {
+ label = 113;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 113:
+ $obj356 = $94 + 8 | 0;
+ $95 = $obj356;
+ $96 = HEAP32[$95 >> 2] | 0;
+ $cond361 = $96;
+ label = 115;
+ break;
+ case 114:
+ $97 = $94;
+ $add_ptr359 = $97 + $idx_neg358 | 0;
+ $cond361 = $add_ptr359;
+ label = 115;
+ break;
+ case 115:
+ $add_ptr364 = $cond361 + $4 | 0;
+ if ($cmp325) {
+ label = 116;
+ break;
+ } else {
+ $cond368 = $add_ptr364;
+ label = 117;
+ break;
+ }
+ case 116:
+ $98 = $add_ptr364;
+ $99 = HEAP32[$98 >> 2] | 0;
+ $cond368 = $99;
+ label = 117;
+ break;
+ case 117:
+ if ($tobool332) {
+ label = 118;
+ break;
+ } else {
+ label = 119;
+ break;
+ }
+ case 118:
+ $call371 = FUNCTION_TABLE_iiiii[$7 & 1023]($dt, $key_0, $cond368, $3) | 0;
+ $cond381 = $call371;
+ label = 122;
+ break;
+ case 119:
+ if ($cmp373) {
+ label = 120;
+ break;
+ } else {
+ label = 121;
+ break;
+ }
+ case 120:
+ $call375 = _strcmp($key_0 | 0, $cond368 | 0) | 0;
+ $cond381 = $call375;
+ label = 122;
+ break;
+ case 121:
+ $call377 = _memcmp($key_0 | 0, $cond368 | 0, $5 | 0) | 0;
+ $cond381 = $call377;
+ label = 122;
+ break;
+ case 122:
+ $cmp382 = ($cond381 | 0) < 0;
+ if ($cmp382) {
+ label = 123;
+ break;
+ } else {
+ label = 124;
+ break;
+ }
+ case 123:
+ $right384 = $94 | 0;
+ $100 = HEAP32[$right384 >> 2] | 0;
+ $101 = $hl350 | 0;
+ $_c403 = $100;
+ HEAP32[$101 >> 2] = $_c403;
+ HEAP32[$right384 >> 2] = $root_6;
+ $102 = $r_2 + 4 | 0;
+ $_c404 = $94;
+ HEAP32[$102 >> 2] = $_c404;
+ $hl390 = $94 + 4 | 0;
+ $_left391 = $hl390;
+ $103 = HEAP32[$_left391 >> 2] | 0;
+ $tobool392 = ($103 | 0) == 0;
+ if ($tobool392) {
+ $l_3413 = $l_2_ph459;
+ $r_3415 = $94;
+ $me_1418 = $me_0;
+ $obj_addr_1422 = $obj_addr_0;
+ label = 207;
+ break;
+ } else {
+ $root_6 = $103;
+ $r_2 = $94;
+ label = 99;
+ break;
+ }
+ case 124:
+ $cmp396 = ($cond381 | 0) == 0;
+ if ($cmp396) {
+ label = 125;
+ break;
+ } else {
+ label = 126;
+ break;
+ }
+ case 125:
+ $104 = $r_2 + 4 | 0;
+ $root_6_c402 = $root_6;
+ HEAP32[$104 >> 2] = $root_6_c402;
+ $obj_addr_1 = $obj_addr_0;
+ $root_7 = $94;
+ $me_1 = $me_0;
+ $r_3 = $root_6;
+ $l_3 = $l_2_ph459;
+ label = 146;
+ break;
+ case 126:
+ $right401 = $l_2_ph459 | 0;
+ HEAP32[$right401 >> 2] = $94;
+ $105 = $r_2 + 4 | 0;
+ $root_6_c401 = $root_6;
+ HEAP32[$105 >> 2] = $root_6_c401;
+ $right404 = $94 | 0;
+ $106 = HEAP32[$right404 >> 2] | 0;
+ $tobool405 = ($106 | 0) == 0;
+ if ($tobool405) {
+ $l_3413 = $94;
+ $r_3415 = $root_6;
+ $me_1418 = $me_0;
+ $obj_addr_1422 = $obj_addr_0;
+ label = 207;
+ break;
+ } else {
+ $root_6_ph461 = $106;
+ $r_2_ph460 = $root_6;
+ $l_2_ph459 = $94;
+ label = 141;
+ break;
+ }
+ case 127:
+ $107 = $r_2 + 4 | 0;
+ $root_6_c400 = $root_6;
+ HEAP32[$107 >> 2] = $root_6_c400;
+ $l_3413 = $l_2_ph459;
+ $r_3415 = $root_6;
+ $me_1418 = $me_0;
+ $obj_addr_1422 = $obj_addr_0;
+ label = 207;
+ break;
+ case 128:
+ $right415 = $root_6 | 0;
+ $108 = HEAP32[$right415 >> 2] | 0;
+ $tobool416 = ($108 | 0) == 0;
+ if ($tobool416) {
+ label = 145;
+ break;
+ } else {
+ label = 129;
+ break;
+ }
+ case 129:
+ if ($cmp317) {
+ label = 130;
+ break;
+ } else {
+ label = 131;
+ break;
+ }
+ case 130:
+ $obj420 = $108 + 8 | 0;
+ $109 = $obj420;
+ $110 = HEAP32[$109 >> 2] | 0;
+ $cond425 = $110;
+ label = 132;
+ break;
+ case 131:
+ $111 = $108;
+ $add_ptr423 = $111 + $idx_neg422 | 0;
+ $cond425 = $add_ptr423;
+ label = 132;
+ break;
+ case 132:
+ $add_ptr428 = $cond425 + $4 | 0;
+ if ($cmp325) {
+ label = 133;
+ break;
+ } else {
+ $cond432 = $add_ptr428;
+ label = 134;
+ break;
+ }
+ case 133:
+ $112 = $add_ptr428;
+ $113 = HEAP32[$112 >> 2] | 0;
+ $cond432 = $113;
+ label = 134;
+ break;
+ case 134:
+ if ($tobool332) {
+ label = 135;
+ break;
+ } else {
+ label = 136;
+ break;
+ }
+ case 135:
+ $call435 = FUNCTION_TABLE_iiiii[$7 & 1023]($dt, $key_0, $cond432, $3) | 0;
+ $cond445 = $call435;
+ label = 139;
+ break;
+ case 136:
+ if ($cmp437) {
+ label = 137;
+ break;
+ } else {
+ label = 138;
+ break;
+ }
+ case 137:
+ $call439 = _strcmp($key_0 | 0, $cond432 | 0) | 0;
+ $cond445 = $call439;
+ label = 139;
+ break;
+ case 138:
+ $call441 = _memcmp($key_0 | 0, $cond432 | 0, $5 | 0) | 0;
+ $cond445 = $call441;
+ label = 139;
+ break;
+ case 139:
+ $cmp446 = ($cond445 | 0) > 0;
+ if ($cmp446) {
+ label = 140;
+ break;
+ } else {
+ label = 142;
+ break;
+ }
+ case 140:
+ $hl448 = $108 + 4 | 0;
+ $_left449 = $hl448;
+ $114 = HEAP32[$_left449 >> 2] | 0;
+ HEAP32[$right415 >> 2] = $114;
+ $115 = $hl448 | 0;
+ $root_6_c = $root_6;
+ HEAP32[$115 >> 2] = $root_6_c;
+ $right453 = $l_2_ph459 | 0;
+ HEAP32[$right453 >> 2] = $108;
+ $right454 = $108 | 0;
+ $116 = HEAP32[$right454 >> 2] | 0;
+ $tobool455 = ($116 | 0) == 0;
+ if ($tobool455) {
+ $l_3413 = $108;
+ $r_3415 = $r_2;
+ $me_1418 = $me_0;
+ $obj_addr_1422 = $obj_addr_0;
+ label = 207;
+ break;
+ } else {
+ $root_6_ph461 = $116;
+ $r_2_ph460 = $r_2;
+ $l_2_ph459 = $108;
+ label = 141;
+ break;
+ }
+ case 141:
+ $root_6 = $root_6_ph461;
+ $r_2 = $r_2_ph460;
+ label = 99;
+ break;
+ case 142:
+ $cmp459 = ($cond445 | 0) == 0;
+ if ($cmp459) {
+ label = 143;
+ break;
+ } else {
+ label = 144;
+ break;
+ }
+ case 143:
+ $right461 = $l_2_ph459 | 0;
+ HEAP32[$right461 >> 2] = $root_6;
+ $obj_addr_1 = $obj_addr_0;
+ $root_7 = $108;
+ $me_1 = $me_0;
+ $r_3 = $r_2;
+ $l_3 = $root_6;
+ label = 146;
+ break;
+ case 144:
+ $117 = $r_2 + 4 | 0;
+ $_c399 = $108;
+ HEAP32[$117 >> 2] = $_c399;
+ $right465 = $l_2_ph459 | 0;
+ HEAP32[$right465 >> 2] = $root_6;
+ $hl466 = $108 + 4 | 0;
+ $_left467 = $hl466;
+ $118 = HEAP32[$_left467 >> 2] | 0;
+ $tobool468 = ($118 | 0) == 0;
+ if ($tobool468) {
+ $l_3413 = $root_6;
+ $r_3415 = $108;
+ $me_1418 = $me_0;
+ $obj_addr_1422 = $obj_addr_0;
+ label = 207;
+ break;
+ } else {
+ $root_6_ph461 = $118;
+ $r_2_ph460 = $108;
+ $l_2_ph459 = $root_6;
+ label = 141;
+ break;
+ }
+ case 145:
+ $right474 = $l_2_ph459 | 0;
+ HEAP32[$right474 >> 2] = $root_6;
+ $l_3413 = $root_6;
+ $r_3415 = $r_2;
+ $me_1418 = $me_0;
+ $obj_addr_1422 = $obj_addr_0;
+ label = 207;
+ break;
+ case 146:
+ $tobool482 = ($root_7 | 0) == 0;
+ if ($tobool482) {
+ $l_3413 = $l_3;
+ $r_3415 = $r_3;
+ $me_1418 = $me_1;
+ $obj_addr_1422 = $obj_addr_1;
+ label = 207;
+ break;
+ } else {
+ label = 147;
+ break;
+ }
+ case 147:
+ $119 = HEAP32[$type5 >> 2] | 0;
+ $or = $119 | 32768;
+ HEAP32[$type5 >> 2] = $or;
+ $hl485 = $root_7 + 4 | 0;
+ $_left486 = $hl485;
+ $120 = HEAP32[$_left486 >> 2] | 0;
+ $right487 = $l_3 | 0;
+ HEAP32[$right487 >> 2] = $120;
+ $right488 = $root_7 | 0;
+ $121 = HEAP32[$right488 >> 2] | 0;
+ $122 = $r_3 + 4 | 0;
+ $_c396 = $121;
+ HEAP32[$122 >> 2] = $_c396;
+ $and491 = $type & 516;
+ $tobool492 = ($and491 | 0) == 0;
+ if ($tobool492) {
+ label = 174;
+ break;
+ } else {
+ $root_8 = $root_7;
+ label = 148;
+ break;
+ }
+ case 148:
+ $right494 = $link | 0;
+ $123 = HEAP32[$right494 >> 2] | 0;
+ $124 = $root_8 + 4 | 0;
+ $_c391 = $123;
+ HEAP32[$124 >> 2] = $_c391;
+ $hl497 = $link + 4 | 0;
+ $_left498 = $hl497;
+ $125 = HEAP32[$_left498 >> 2] | 0;
+ $right499 = $root_8 | 0;
+ HEAP32[$right499 >> 2] = $125;
+ $126 = HEAP32[$meth >> 2] | 0;
+ $type501 = $126 + 4 | 0;
+ $127 = HEAP32[$type501 >> 2] | 0;
+ $and502 = $127 & 8;
+ $tobool503 = ($and502 | 0) == 0;
+ if ($tobool503) {
+ $root_10 = $root_8;
+ label = 171;
+ break;
+ } else {
+ label = 149;
+ break;
+ }
+ case 149:
+ $and505 = $type & 516;
+ $tobool506 = ($and505 | 0) == 0;
+ if ($tobool506) {
+ $root_10 = $root_8;
+ label = 171;
+ break;
+ } else {
+ label = 150;
+ break;
+ }
+ case 150:
+ $cmp508 = ($6 | 0) < 0;
+ if ($cmp508) {
+ label = 151;
+ break;
+ } else {
+ label = 152;
+ break;
+ }
+ case 151:
+ $obj510 = $root_8 + 8 | 0;
+ $128 = $obj510;
+ $129 = HEAP32[$128 >> 2] | 0;
+ $cond515 = $129;
+ label = 153;
+ break;
+ case 152:
+ $130 = $root_8;
+ $idx_neg512 = -$6 | 0;
+ $add_ptr513 = $130 + $idx_neg512 | 0;
+ $cond515 = $add_ptr513;
+ label = 153;
+ break;
+ case 153:
+ $cmp516 = ($5 | 0) < 0;
+ $add_ptr518 = $cond515 + $4 | 0;
+ if ($cmp516) {
+ label = 154;
+ break;
+ } else {
+ $cond522 = $add_ptr518;
+ label = 155;
+ break;
+ }
+ case 154:
+ $131 = $add_ptr518;
+ $132 = HEAP32[$131 >> 2] | 0;
+ $cond522 = $132;
+ label = 155;
+ break;
+ case 155:
+ $hl524442 = $root_8 + 4 | 0;
+ $_left525443 = $hl524442;
+ $133 = HEAP32[$_left525443 >> 2] | 0;
+ $tobool526444 = ($133 | 0) == 0;
+ if ($tobool526444) {
+ $root_10 = $root_8;
+ label = 171;
+ break;
+ } else {
+ label = 156;
+ break;
+ }
+ case 156:
+ $tobool555 = ($7 | 0) == 0;
+ $cmp559 = ($5 | 0) < 1;
+ $idx_neg544 = -$6 | 0;
+ $root_9445 = $root_8;
+ $hl524446 = $hl524442;
+ $134 = $133;
+ label = 157;
+ break;
+ case 157:
+ $right529436 = $134 | 0;
+ $135 = HEAP32[$right529436 >> 2] | 0;
+ $tobool530437 = ($135 | 0) == 0;
+ if ($tobool530437) {
+ $t_1_lcssa = $134;
+ $right529_lcssa = $right529436;
+ label = 159;
+ break;
+ } else {
+ $t_1438 = $134;
+ $right529439 = $right529436;
+ $136 = $135;
+ label = 158;
+ break;
+ }
+ case 158:
+ $hl532 = $136 + 4 | 0;
+ $_left533 = $hl532;
+ $137 = HEAP32[$_left533 >> 2] | 0;
+ HEAP32[$right529439 >> 2] = $137;
+ $138 = $hl532 | 0;
+ $t_1_c393 = $t_1438;
+ HEAP32[$138 >> 2] = $t_1_c393;
+ $right529 = $136 | 0;
+ $139 = HEAP32[$right529 >> 2] | 0;
+ $tobool530 = ($139 | 0) == 0;
+ if ($tobool530) {
+ $t_1_lcssa = $136;
+ $right529_lcssa = $right529;
+ label = 159;
+ break;
+ } else {
+ $t_1438 = $136;
+ $right529439 = $right529;
+ $136 = $139;
+ label = 158;
+ break;
+ }
+ case 159:
+ $140 = $hl524446 | 0;
+ $t_1_c = $t_1_lcssa;
+ HEAP32[$140 >> 2] = $t_1_c;
+ if ($cmp508) {
+ label = 160;
+ break;
+ } else {
+ label = 161;
+ break;
+ }
+ case 160:
+ $obj542 = $t_1_lcssa + 8 | 0;
+ $141 = $obj542;
+ $142 = HEAP32[$141 >> 2] | 0;
+ $cond547 = $142;
+ label = 162;
+ break;
+ case 161:
+ $143 = $t_1_lcssa;
+ $add_ptr545 = $143 + $idx_neg544 | 0;
+ $cond547 = $add_ptr545;
+ label = 162;
+ break;
+ case 162:
+ $add_ptr550 = $cond547 + $4 | 0;
+ if ($cmp516) {
+ label = 163;
+ break;
+ } else {
+ $cond554 = $add_ptr550;
+ label = 164;
+ break;
+ }
+ case 163:
+ $144 = $add_ptr550;
+ $145 = HEAP32[$144 >> 2] | 0;
+ $cond554 = $145;
+ label = 164;
+ break;
+ case 164:
+ if ($tobool555) {
+ label = 166;
+ break;
+ } else {
+ label = 165;
+ break;
+ }
+ case 165:
+ $call557 = FUNCTION_TABLE_iiiii[$7 & 1023]($dt, $cond522, $cond554, $3) | 0;
+ $cond567 = $call557;
+ label = 169;
+ break;
+ case 166:
+ if ($cmp559) {
+ label = 167;
+ break;
+ } else {
+ label = 168;
+ break;
+ }
+ case 167:
+ $call561 = _strcmp($cond522 | 0, $cond554 | 0) | 0;
+ $cond567 = $call561;
+ label = 169;
+ break;
+ case 168:
+ $call563 = _memcmp($cond522 | 0, $cond554 | 0, $5 | 0) | 0;
+ $cond567 = $call563;
+ label = 169;
+ break;
+ case 169:
+ $cmp568 = ($cond567 | 0) == 0;
+ if ($cmp568) {
+ label = 170;
+ break;
+ } else {
+ $root_10 = $root_9445;
+ label = 171;
+ break;
+ }
+ case 170:
+ $146 = HEAP32[$right529_lcssa >> 2] | 0;
+ $_c392 = $146;
+ HEAP32[$140 >> 2] = $_c392;
+ HEAP32[$right529_lcssa >> 2] = $root_9445;
+ $hl524 = $t_1_lcssa + 4 | 0;
+ $_left525 = $hl524;
+ $147 = HEAP32[$_left525 >> 2] | 0;
+ $tobool526 = ($147 | 0) == 0;
+ if ($tobool526) {
+ $root_10 = $t_1_lcssa;
+ label = 171;
+ break;
+ } else {
+ $root_9445 = $t_1_lcssa;
+ $hl524446 = $hl524;
+ $134 = $147;
+ label = 157;
+ break;
+ }
+ case 171:
+ $148 = HEAP32[$data >> 2] | 0;
+ $here578 = $148 + 4 | 0;
+ HEAP32[$here578 >> 2] = $root_10;
+ $cmp579 = ($6 | 0) < 0;
+ if ($cmp579) {
+ label = 172;
+ break;
+ } else {
+ label = 173;
+ break;
+ }
+ case 172:
+ $obj581 = $root_10 + 8 | 0;
+ $149 = $obj581;
+ $150 = HEAP32[$149 >> 2] | 0;
+ $retval_0 = $150;
+ label = 231;
+ break;
+ case 173:
+ $151 = $root_10;
+ $idx_neg583 = -$6 | 0;
+ $add_ptr584 = $151 + $idx_neg583 | 0;
+ $retval_0 = $add_ptr584;
+ label = 231;
+ break;
+ case 174:
+ $and588 = $type & 8;
+ $tobool589 = ($and588 | 0) == 0;
+ if ($tobool589) {
+ label = 180;
+ break;
+ } else {
+ label = 175;
+ break;
+ }
+ case 175:
+ $right591 = $link | 0;
+ $152 = HEAP32[$right591 >> 2] | 0;
+ $153 = $hl485 | 0;
+ $_c398 = $152;
+ HEAP32[$153 >> 2] = $_c398;
+ HEAP32[$right488 >> 2] = 0;
+ HEAP32[$right591 >> 2] = $root_7;
+ $r_3414 = $r_3;
+ $obj_addr_1421 = $obj_addr_1;
+ label = 176;
+ break;
+ case 176:
+ $hl596 = $link + 4 | 0;
+ $_left597 = $hl596;
+ $154 = HEAP32[$_left597 >> 2] | 0;
+ $tobool598 = ($154 | 0) == 0;
+ if ($tobool598) {
+ $obj_addr_2_ph = $obj_addr_1421;
+ $r_5_ph = $r_3414;
+ label = 210;
+ break;
+ } else {
+ label = 177;
+ break;
+ }
+ case 177:
+ $hl601453 = $154 + 4 | 0;
+ $_left602454 = $hl601453;
+ $155 = HEAP32[$_left602454 >> 2] | 0;
+ $tobool603455 = ($155 | 0) == 0;
+ if ($tobool603455) {
+ $root_11_lcssa = $154;
+ label = 179;
+ break;
+ } else {
+ $root_11456 = $154;
+ $hl601457 = $hl601453;
+ $156 = $155;
+ label = 178;
+ break;
+ }
+ case 178:
+ $right605 = $156 | 0;
+ $157 = HEAP32[$right605 >> 2] | 0;
+ $158 = $hl601457 | 0;
+ $_c395 = $157;
+ HEAP32[$158 >> 2] = $_c395;
+ HEAP32[$right605 >> 2] = $root_11456;
+ $hl601 = $156 + 4 | 0;
+ $_left602 = $hl601;
+ $159 = HEAP32[$_left602 >> 2] | 0;
+ $tobool603 = ($159 | 0) == 0;
+ if ($tobool603) {
+ $root_11_lcssa = $156;
+ label = 179;
+ break;
+ } else {
+ $root_11456 = $156;
+ $hl601457 = $hl601;
+ $156 = $159;
+ label = 178;
+ break;
+ }
+ case 179:
+ $right610 = $root_11_lcssa | 0;
+ $160 = HEAP32[$right610 >> 2] | 0;
+ $161 = $hl596 | 0;
+ $_c394 = $160;
+ HEAP32[$161 >> 2] = $_c394;
+ $root_8 = $root_11_lcssa;
+ label = 148;
+ break;
+ case 180:
+ $and615 = $type & 16;
+ $tobool616 = ($and615 | 0) == 0;
+ if ($tobool616) {
+ label = 186;
+ break;
+ } else {
+ label = 181;
+ break;
+ }
+ case 181:
+ $hl618 = $link + 4 | 0;
+ $_left619 = $hl618;
+ $162 = HEAP32[$_left619 >> 2] | 0;
+ HEAP32[$right488 >> 2] = $162;
+ $163 = $hl485 | 0;
+ HEAP32[$163 >> 2] = 0;
+ $164 = $hl618 | 0;
+ $root_7_c397 = $root_7;
+ HEAP32[$164 >> 2] = $root_7_c397;
+ $r_3416 = $r_3;
+ $obj_addr_1424 = $obj_addr_1;
+ label = 182;
+ break;
+ case 182:
+ $right625 = $link | 0;
+ $165 = HEAP32[$right625 >> 2] | 0;
+ $tobool626 = ($165 | 0) == 0;
+ if ($tobool626) {
+ $obj_addr_2_ph = $obj_addr_1424;
+ $r_5_ph = $r_3416;
+ label = 210;
+ break;
+ } else {
+ label = 183;
+ break;
+ }
+ case 183:
+ $right629448 = $165 | 0;
+ $166 = HEAP32[$right629448 >> 2] | 0;
+ $tobool630449 = ($166 | 0) == 0;
+ if ($tobool630449) {
+ $root_12_lcssa = $165;
+ label = 185;
+ break;
+ } else {
+ $root_12450 = $165;
+ $right629451 = $right629448;
+ $167 = $166;
+ label = 184;
+ break;
+ }
+ case 184:
+ $hl632 = $167 + 4 | 0;
+ $_left633 = $hl632;
+ $168 = HEAP32[$_left633 >> 2] | 0;
+ HEAP32[$right629451 >> 2] = $168;
+ $169 = $hl632 | 0;
+ $root_12_c = $root_12450;
+ HEAP32[$169 >> 2] = $root_12_c;
+ $right629 = $167 | 0;
+ $170 = HEAP32[$right629 >> 2] | 0;
+ $tobool630 = ($170 | 0) == 0;
+ if ($tobool630) {
+ $root_12_lcssa = $167;
+ label = 185;
+ break;
+ } else {
+ $root_12450 = $167;
+ $right629451 = $right629;
+ $167 = $170;
+ label = 184;
+ break;
+ }
+ case 185:
+ $hl638 = $root_12_lcssa + 4 | 0;
+ $_left639 = $hl638;
+ $171 = HEAP32[$_left639 >> 2] | 0;
+ HEAP32[$right625 >> 2] = $171;
+ $root_8 = $root_12_lcssa;
+ label = 148;
+ break;
+ case 186:
+ $and643 = $type & 4098;
+ $tobool644 = ($and643 | 0) == 0;
+ if ($tobool644) {
+ label = 197;
+ break;
+ } else {
+ $root_13 = $root_7;
+ $r_4 = $r_3;
+ label = 187;
+ break;
+ }
+ case 187:
+ $cmp646 = ($6 | 0) < 0;
+ if ($cmp646) {
+ label = 188;
+ break;
+ } else {
+ label = 189;
+ break;
+ }
+ case 188:
+ $obj648 = $root_13 + 8 | 0;
+ $172 = $obj648;
+ $173 = HEAP32[$172 >> 2] | 0;
+ $cond653 = $173;
+ label = 190;
+ break;
+ case 189:
+ $174 = $root_13;
+ $idx_neg650 = -$6 | 0;
+ $add_ptr651 = $174 + $idx_neg650 | 0;
+ $cond653 = $add_ptr651;
+ label = 190;
+ break;
+ case 190:
+ $freef654 = $3 + 16 | 0;
+ $175 = HEAP32[$freef654 >> 2] | 0;
+ $tobool655 = ($175 | 0) == 0;
+ if ($tobool655) {
+ label = 193;
+ break;
+ } else {
+ label = 191;
+ break;
+ }
+ case 191:
+ $and657 = $type & 2;
+ $tobool658 = ($and657 | 0) == 0;
+ if ($tobool658) {
+ label = 193;
+ break;
+ } else {
+ label = 192;
+ break;
+ }
+ case 192:
+ FUNCTION_TABLE_viii[$175 & 1023]($dt, $cond653, $3);
+ label = 193;
+ break;
+ case 193:
+ $176 = HEAP32[$link4 >> 2] | 0;
+ $cmp663 = ($176 | 0) < 0;
+ if ($cmp663) {
+ label = 194;
+ break;
+ } else {
+ label = 195;
+ break;
+ }
+ case 194:
+ $memoryf665 = $dt + 12 | 0;
+ $177 = HEAP32[$memoryf665 >> 2] | 0;
+ $178 = $root_13;
+ $call666 = FUNCTION_TABLE_iiiii[$177 & 1023]($dt, $178, 0, $3) | 0;
+ label = 195;
+ break;
+ case 195:
+ $179 = HEAP32[$data >> 2] | 0;
+ $size669 = $179 + 16 | 0;
+ $180 = HEAP32[$size669 >> 2] | 0;
+ $sub = $180 - 1 | 0;
+ HEAP32[$size669 >> 2] = $sub;
+ $cmp670 = ($sub | 0) < 0;
+ if ($cmp670) {
+ label = 196;
+ break;
+ } else {
+ $obj_addr_2_ph = $cond653;
+ $r_5_ph = $r_4;
+ label = 210;
+ break;
+ }
+ case 196:
+ $181 = HEAP32[$data >> 2] | 0;
+ $size673 = $181 + 16 | 0;
+ HEAP32[$size673 >> 2] = -1;
+ $obj_addr_2_ph = $cond653;
+ $r_5_ph = $r_4;
+ label = 210;
+ break;
+ case 197:
+ $and676 = $type & 2049;
+ $tobool677 = ($and676 | 0) == 0;
+ if ($tobool677) {
+ label = 200;
+ break;
+ } else {
+ label = 198;
+ break;
+ }
+ case 198:
+ $182 = HEAP32[$meth >> 2] | 0;
+ $type680 = $182 + 4 | 0;
+ $183 = HEAP32[$type680 >> 2] | 0;
+ $and681 = $183 & 4;
+ $tobool682 = ($and681 | 0) == 0;
+ if ($tobool682) {
+ label = 199;
+ break;
+ } else {
+ $root_8 = $root_7;
+ label = 148;
+ break;
+ }
+ case 199:
+ $184 = $hl485 | 0;
+ HEAP32[$184 >> 2] = 0;
+ $hl687 = $link + 4 | 0;
+ $_left688 = $hl687;
+ $185 = HEAP32[$_left688 >> 2] | 0;
+ HEAP32[$right488 >> 2] = $185;
+ $186 = $hl687 | 0;
+ $root_7_c = $root_7;
+ HEAP32[$186 >> 2] = $root_7_c;
+ $r_3417 = $r_3;
+ $root_7419 = $root_7;
+ $obj_addr_1423 = $obj_addr_1;
+ label = 214;
+ break;
+ case 200:
+ $and693 = $type & 32;
+ $tobool694 = ($and693 | 0) == 0;
+ if ($tobool694) {
+ $retval_0 = 0;
+ label = 231;
+ break;
+ } else {
+ label = 201;
+ break;
+ }
+ case 201:
+ $187 = HEAP32[$meth >> 2] | 0;
+ $type697 = $187 + 4 | 0;
+ $188 = HEAP32[$type697 >> 2] | 0;
+ $and698 = $188 & 4;
+ $tobool699 = ($and698 | 0) == 0;
+ if ($tobool699) {
+ label = 206;
+ break;
+ } else {
+ label = 202;
+ break;
+ }
+ case 202:
+ $freef701 = $3 + 16 | 0;
+ $189 = HEAP32[$freef701 >> 2] | 0;
+ $tobool702 = ($189 | 0) == 0;
+ if ($tobool702) {
+ label = 204;
+ break;
+ } else {
+ label = 203;
+ break;
+ }
+ case 203:
+ FUNCTION_TABLE_viii[$189 & 1023]($dt, $obj_addr_1, $3);
+ label = 204;
+ break;
+ case 204:
+ $190 = HEAP32[$link4 >> 2] | 0;
+ $cmp707 = ($190 | 0) < 0;
+ if ($cmp707) {
+ label = 205;
+ break;
+ } else {
+ $root_8 = $root_7;
+ label = 148;
+ break;
+ }
+ case 205:
+ $memoryf709 = $dt + 12 | 0;
+ $191 = HEAP32[$memoryf709 >> 2] | 0;
+ $192 = $me_1;
+ $call710 = FUNCTION_TABLE_iiiii[$191 & 1023]($dt, $192, 0, $3) | 0;
+ $root_8 = $root_7;
+ label = 148;
+ break;
+ case 206:
+ $193 = $me_1 + 4 | 0;
+ HEAP32[$193 >> 2] = 0;
+ $hl715 = $link + 4 | 0;
+ $_left716 = $hl715;
+ $194 = HEAP32[$_left716 >> 2] | 0;
+ $right717 = $me_1 | 0;
+ HEAP32[$right717 >> 2] = $194;
+ $195 = $hl715 | 0;
+ $me_1_c = $me_1;
+ HEAP32[$195 >> 2] = $me_1_c;
+ $196 = HEAP32[$data >> 2] | 0;
+ $size721 = $196 + 16 | 0;
+ $197 = HEAP32[$size721 >> 2] | 0;
+ $add722 = $197 + 1 | 0;
+ HEAP32[$size721 >> 2] = $add722;
+ $root_8 = $root_7;
+ label = 148;
+ break;
+ case 207:
+ $198 = $r_3415 + 4 | 0;
+ HEAP32[$198 >> 2] = 0;
+ $right733 = $l_3413 | 0;
+ HEAP32[$right733 >> 2] = 0;
+ $and734 = $type & 8;
+ $tobool735 = ($and734 | 0) == 0;
+ if ($tobool735) {
+ label = 208;
+ break;
+ } else {
+ $r_3414 = $r_3415;
+ $obj_addr_1421 = $obj_addr_1422;
+ label = 176;
+ break;
+ }
+ case 208:
+ $and738 = $type & 16;
+ $tobool739 = ($and738 | 0) == 0;
+ if ($tobool739) {
+ label = 209;
+ break;
+ } else {
+ $r_3416 = $r_3415;
+ $obj_addr_1424 = $obj_addr_1422;
+ label = 182;
+ break;
+ }
+ case 209:
+ $and742 = $type & 516;
+ $tobool743 = ($and742 | 0) == 0;
+ if ($tobool743) {
+ label = 213;
+ break;
+ } else {
+ $obj_addr_2_ph = $obj_addr_1422;
+ $r_5_ph = $r_3415;
+ label = 210;
+ break;
+ }
+ case 210:
+ $r_5 = $r_5_ph;
+ label = 211;
+ break;
+ case 211:
+ $hl746 = $r_5 + 4 | 0;
+ $_left747 = $hl746;
+ $199 = HEAP32[$_left747 >> 2] | 0;
+ $tobool748 = ($199 | 0) == 0;
+ if ($tobool748) {
+ label = 212;
+ break;
+ } else {
+ $r_5 = $199;
+ label = 211;
+ break;
+ }
+ case 212:
+ $right751 = $link | 0;
+ $200 = HEAP32[$right751 >> 2] | 0;
+ $201 = $hl746 | 0;
+ $_c390 = $200;
+ HEAP32[$201 >> 2] = $_c390;
+ $hl754 = $link + 4 | 0;
+ $_left755 = $hl754;
+ $202 = HEAP32[$_left755 >> 2] | 0;
+ $203 = HEAP32[$data >> 2] | 0;
+ $here757 = $203 + 4 | 0;
+ HEAP32[$here757 >> 2] = $202;
+ $and758 = $type & 2;
+ $tobool759 = ($and758 | 0) != 0;
+ $cond763 = $tobool759 ? $obj_addr_2_ph : 0;
+ $retval_0 = $cond763;
+ label = 231;
+ break;
+ case 213:
+ $and765 = $type & 2049;
+ $tobool766 = ($and765 | 0) == 0;
+ if ($tobool766) {
+ label = 229;
+ break;
+ } else {
+ $r_3417 = $r_3415;
+ $root_7419 = 0;
+ $obj_addr_1423 = $obj_addr_1422;
+ label = 214;
+ break;
+ }
+ case 214:
+ $makef = $3 + 12 | 0;
+ $204 = HEAP32[$makef >> 2] | 0;
+ $tobool768 = ($204 | 0) == 0;
+ if ($tobool768) {
+ $obj_addr_3 = $obj_addr_1423;
+ label = 217;
+ break;
+ } else {
+ label = 215;
+ break;
+ }
+ case 215:
+ $and770 = $type & 1;
+ $tobool771 = ($and770 | 0) == 0;
+ if ($tobool771) {
+ $obj_addr_3 = $obj_addr_1423;
+ label = 217;
+ break;
+ } else {
+ label = 216;
+ break;
+ }
+ case 216:
+ $call774 = FUNCTION_TABLE_iiii[$204 & 1023]($dt, $obj_addr_1423, $3) | 0;
+ $obj_addr_3 = $call774;
+ label = 217;
+ break;
+ case 217:
+ $tobool776 = ($obj_addr_3 | 0) == 0;
+ if ($tobool776) {
+ $root_14 = $root_7419;
+ label = 226;
+ break;
+ } else {
+ label = 218;
+ break;
+ }
+ case 218:
+ $cmp778 = ($6 | 0) > -1;
+ if ($cmp778) {
+ label = 219;
+ break;
+ } else {
+ label = 220;
+ break;
+ }
+ case 219:
+ $add_ptr780 = $obj_addr_3 + $6 | 0;
+ $205 = $add_ptr780;
+ $root_14 = $205;
+ label = 226;
+ break;
+ case 220:
+ $memoryf782 = $dt + 12 | 0;
+ $206 = HEAP32[$memoryf782 >> 2] | 0;
+ $call783 = FUNCTION_TABLE_iiiii[$206 & 1023]($dt, 0, 12, $3) | 0;
+ $207 = $call783;
+ $tobool784 = ($call783 | 0) == 0;
+ if ($tobool784) {
+ label = 222;
+ break;
+ } else {
+ label = 221;
+ break;
+ }
+ case 221:
+ $obj786 = $call783 + 8 | 0;
+ $208 = $obj786;
+ HEAP32[$208 >> 2] = $obj_addr_3;
+ $root_14 = $207;
+ label = 226;
+ break;
+ case 222:
+ $209 = HEAP32[$makef >> 2] | 0;
+ $tobool789 = ($209 | 0) == 0;
+ if ($tobool789) {
+ $root_14 = $207;
+ label = 226;
+ break;
+ } else {
+ label = 223;
+ break;
+ }
+ case 223:
+ $freef791 = $3 + 16 | 0;
+ $210 = HEAP32[$freef791 >> 2] | 0;
+ $tobool792 = ($210 | 0) == 0;
+ if ($tobool792) {
+ $root_14 = $207;
+ label = 226;
+ break;
+ } else {
+ label = 224;
+ break;
+ }
+ case 224:
+ $and794 = $type & 1;
+ $tobool795 = ($and794 | 0) == 0;
+ if ($tobool795) {
+ $root_14 = $207;
+ label = 226;
+ break;
+ } else {
+ label = 225;
+ break;
+ }
+ case 225:
+ FUNCTION_TABLE_viii[$210 & 1023]($dt, $obj_addr_3, $3);
+ $root_14 = $207;
+ label = 226;
+ break;
+ case 226:
+ $tobool802 = ($root_14 | 0) == 0;
+ if ($tobool802) {
+ $obj_addr_2_ph = $obj_addr_3;
+ $r_5_ph = $r_3417;
+ label = 210;
+ break;
+ } else {
+ label = 227;
+ break;
+ }
+ case 227:
+ $211 = HEAP32[$data >> 2] | 0;
+ $size805 = $211 + 16 | 0;
+ $212 = HEAP32[$size805 >> 2] | 0;
+ $cmp806 = ($212 | 0) > -1;
+ if ($cmp806) {
+ label = 228;
+ break;
+ } else {
+ $root_8 = $root_14;
+ label = 148;
+ break;
+ }
+ case 228:
+ $add810 = $212 + 1 | 0;
+ HEAP32[$size805 >> 2] = $add810;
+ $root_8 = $root_14;
+ label = 148;
+ break;
+ case 229:
+ $and814 = $type & 32;
+ $tobool815 = ($and814 | 0) == 0;
+ if ($tobool815) {
+ $obj_addr_2_ph = 0;
+ $r_5_ph = $r_3415;
+ label = 210;
+ break;
+ } else {
+ label = 230;
+ break;
+ }
+ case 230:
+ $213 = HEAP32[$data >> 2] | 0;
+ $size818 = $213 + 16 | 0;
+ $214 = HEAP32[$size818 >> 2] | 0;
+ $add819 = $214 + 1 | 0;
+ HEAP32[$size818 >> 2] = $add819;
+ $root_8 = $me_1418;
+ label = 148;
+ break;
+ case 231:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _inside($inside_context, $p) {
+ $inside_context = $inside_context | 0;
+ $p = $p | 0;
+ var $1 = 0, $sub = 0.0, $sub13 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $1 = HEAP32[$inside_context >> 2] | 0;
+ $sub = +HEAPF64[$p >> 3] - +HEAPF64[$1 >> 3];
+ $sub13 = +HEAPF64[$p + 8 >> 3] - +HEAPF64[$1 + 8 >> 3];
+ STACKTOP = __stackBase__;
+ return $sub * $sub + $sub13 * $sub13 <= +HEAPF64[HEAP32[$inside_context + 4 >> 2] >> 3] & 1 | 0;
+}
+function _dtrestore($dt, $list) {
+ $dt = $dt | 0;
+ $list = $list | 0;
+ var $meth = 0, $0 = 0, $searchf1 = 0, $1 = 0, $data = 0, $2 = 0, $type2 = 0, $3 = 0, $and = 0, $tobool = 0, $tobool3 = 0, $here = 0, $4 = 0, $size = 0, $5 = 0, $cmp = 0, $list_addr_0 = 0, $type_0 = 0, $6 = 0, $type11 = 0, $7 = 0, $and12 = 0, $8 = 0, $type14 = 0, $9 = 0, $and15 = 0, $tobool16 = 0, $here19 = 0, $tobool20 = 0, $10 = 0, $_htab = 0, $11 = 0, $ntab = 0, $12 = 0, $add_ptr = 0, $cmp2430 = 0, $list_addr_132 = 0, $s_031 = 0, $13 = 0, $tobool25 = 0, $right = 0, $14 = 0, $list_addr_2 = 0, $incdec_ptr = 0, $cmp24 = 0, $size31 = 0, $tobool3227 = 0, $list_addr_328 = 0, $right33 = 0, $15 = 0, $16 = 0, $call = 0, $tobool32 = 0, $and38 = 0, $tobool39 = 0, $here45 = 0, $17 = 0, $18 = 0, $list_addr_0_c = 0, $tobool49 = 0, $19 = 0, $size52 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $meth = $dt + 16 | 0;
+ $0 = HEAP32[$meth >> 2] | 0;
+ $searchf1 = $0 | 0;
+ $1 = HEAP32[$searchf1 >> 2] | 0;
+ $data = $dt + 8 | 0;
+ $2 = HEAP32[$data >> 2] | 0;
+ $type2 = $2 | 0;
+ $3 = HEAP32[$type2 >> 2] | 0;
+ $and = $3 & 4096;
+ $tobool = ($list | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $tobool3 = ($and | 0) == 0;
+ if ($tobool3) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $here = $2 + 4 | 0;
+ $4 = HEAP32[$here >> 2] | 0;
+ $type_0 = $and;
+ $list_addr_0 = $4;
+ label = 6;
+ break;
+ case 5:
+ $size = $2 + 16 | 0;
+ $5 = HEAP32[$size >> 2] | 0;
+ $cmp = ($5 | 0) == 0;
+ if ($cmp) {
+ $type_0 = 0;
+ $list_addr_0 = $list;
+ label = 6;
+ break;
+ } else {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ }
+ case 6:
+ $6 = HEAP32[$data >> 2] | 0;
+ $type11 = $6 | 0;
+ $7 = HEAP32[$type11 >> 2] | 0;
+ $and12 = $7 & -4097;
+ HEAP32[$type11 >> 2] = $and12;
+ $8 = HEAP32[$data >> 2] | 0;
+ $type14 = $8 | 0;
+ $9 = HEAP32[$type14 >> 2] | 0;
+ $and15 = $9 & 3;
+ $tobool16 = ($and15 | 0) == 0;
+ if ($tobool16) {
+ label = 14;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $here19 = $8 + 4 | 0;
+ HEAP32[$here19 >> 2] = 0;
+ $tobool20 = ($type_0 | 0) == 0;
+ $10 = HEAP32[$data >> 2] | 0;
+ if ($tobool20) {
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $_htab = $10 + 8 | 0;
+ $11 = HEAP32[$_htab >> 2] | 0;
+ $ntab = $10 + 12 | 0;
+ $12 = HEAP32[$ntab >> 2] | 0;
+ $add_ptr = $11 + ($12 << 2) | 0;
+ $cmp2430 = ($12 | 0) > 0;
+ if ($cmp2430) {
+ $s_031 = $11;
+ $list_addr_132 = $list_addr_0;
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 9:
+ $13 = HEAP32[$s_031 >> 2] | 0;
+ $tobool25 = ($13 | 0) == 0;
+ if ($tobool25) {
+ $list_addr_2 = $list_addr_132;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ HEAP32[$s_031 >> 2] = $list_addr_132;
+ $right = $13 | 0;
+ $14 = HEAP32[$right >> 2] | 0;
+ HEAP32[$right >> 2] = 0;
+ $list_addr_2 = $14;
+ label = 11;
+ break;
+ case 11:
+ $incdec_ptr = $s_031 + 4 | 0;
+ $cmp24 = $incdec_ptr >>> 0 < $add_ptr >>> 0;
+ if ($cmp24) {
+ $s_031 = $incdec_ptr;
+ $list_addr_132 = $list_addr_2;
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 12:
+ $size31 = $10 + 16 | 0;
+ HEAP32[$size31 >> 2] = 0;
+ $tobool3227 = ($list_addr_0 | 0) == 0;
+ if ($tobool3227) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ $list_addr_328 = $list_addr_0;
+ label = 13;
+ break;
+ }
+ case 13:
+ $right33 = $list_addr_328 | 0;
+ $15 = HEAP32[$right33 >> 2] | 0;
+ $16 = $list_addr_328;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($dt, $16, 32) | 0;
+ $tobool32 = ($15 | 0) == 0;
+ if ($tobool32) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ $list_addr_328 = $15;
+ label = 13;
+ break;
+ }
+ case 14:
+ $and38 = $9 & 12;
+ $tobool39 = ($and38 | 0) == 0;
+ $here45 = $8 + 4 | 0;
+ if ($tobool39) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ HEAP32[$here45 >> 2] = $list_addr_0;
+ label = 17;
+ break;
+ case 16:
+ HEAP32[$here45 >> 2] = 0;
+ $17 = HEAP32[$data >> 2] | 0;
+ $18 = $17 + 8 | 0;
+ $list_addr_0_c = $list_addr_0 | 0;
+ HEAP32[$18 >> 2] = $list_addr_0_c;
+ label = 17;
+ break;
+ case 17:
+ $tobool49 = ($type_0 | 0) == 0;
+ if ($tobool49) {
+ label = 18;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 18:
+ $19 = HEAP32[$data >> 2] | 0;
+ $size52 = $19 + 16 | 0;
+ HEAP32[$size52 >> 2] = -1;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dtview($dt, $view) {
+ $dt = $dt | 0;
+ $view = $view | 0;
+ var $data = 0, $0 = 0, $type = 0, $1 = 0, $and = 0, $tobool = 0, $call = 0, $tobool1 = 0, $data2 = 0, $2 = 0, $type3 = 0, $3 = 0, $and4 = 0, $tobool5 = 0, $call7 = 0, $meth = 0, $4 = 0, $meth11 = 0, $5 = 0, $cmp = 0, $tobool1423 = 0, $d_024 = 0, $cmp15 = 0, $view18 = 0, $6 = 0, $tobool14 = 0, $view19 = 0, $7 = 0, $tobool20 = 0, $nview = 0, $8 = 0, $sub = 0, $walk = 0, $meth26 = 0, $9 = 0, $searchf = 0, $10 = 0, $searchf27 = 0, $searchf30 = 0, $nview31 = 0, $11 = 0, $add = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $data = $dt + 8 | 0;
+ $0 = HEAP32[$data >> 2] | 0;
+ $type = $0 | 0;
+ $1 = HEAP32[$type >> 2] | 0;
+ $and = $1 & 4096;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _dtrestore($dt, 0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $tobool1 = ($view | 0) != 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 5:
+ $data2 = $view + 8 | 0;
+ $2 = HEAP32[$data2 >> 2] | 0;
+ $type3 = $2 | 0;
+ $3 = HEAP32[$type3 >> 2] | 0;
+ $and4 = $3 & 4096;
+ $tobool5 = ($and4 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call7 = _dtrestore($view, 0) | 0;
+ label = 7;
+ break;
+ case 7:
+ $meth = $view + 16 | 0;
+ $4 = HEAP32[$meth >> 2] | 0;
+ $meth11 = $dt + 16 | 0;
+ $5 = HEAP32[$meth11 >> 2] | 0;
+ $cmp = ($4 | 0) == ($5 | 0);
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 16;
+ break;
+ }
+ case 8:
+ $tobool1423 = ($view | 0) == 0;
+ if ($tobool1423) {
+ label = 11;
+ break;
+ } else {
+ $d_024 = $view;
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp15 = ($d_024 | 0) == ($dt | 0);
+ if ($cmp15) {
+ $retval_0 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $view18 = $d_024 + 28 | 0;
+ $6 = HEAP32[$view18 >> 2] | 0;
+ $tobool14 = ($6 | 0) == 0;
+ if ($tobool14) {
+ label = 11;
+ break;
+ } else {
+ $d_024 = $6;
+ label = 9;
+ break;
+ }
+ case 11:
+ $view19 = $dt + 28 | 0;
+ $7 = HEAP32[$view19 >> 2] | 0;
+ $tobool20 = ($7 | 0) == 0;
+ if ($tobool20) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $nview = $7 + 24 | 0;
+ $8 = HEAP32[$nview >> 2] | 0;
+ $sub = $8 - 1 | 0;
+ HEAP32[$nview >> 2] = $sub;
+ label = 13;
+ break;
+ case 13:
+ $walk = $dt + 32 | 0;
+ HEAP32[$walk >> 2] = 0;
+ HEAP32[$view19 >> 2] = 0;
+ if ($tobool1) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $meth26 = $dt + 16 | 0;
+ $9 = HEAP32[$meth26 >> 2] | 0;
+ $searchf = $9 | 0;
+ $10 = HEAP32[$searchf >> 2] | 0;
+ $searchf27 = $dt | 0;
+ HEAP32[$searchf27 >> 2] = $10;
+ $retval_0 = $7;
+ label = 16;
+ break;
+ case 15:
+ HEAP32[$view19 >> 2] = $view;
+ $searchf30 = $dt | 0;
+ HEAP32[$searchf30 >> 2] = 650;
+ $nview31 = $view + 24 | 0;
+ $11 = HEAP32[$nview31 >> 2] | 0;
+ $add = $11 + 1 | 0;
+ HEAP32[$nview31 >> 2] = $add;
+ $retval_0 = $view;
+ label = 16;
+ break;
+ case 16:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dtvsearch($dt, $obj, $type) {
+ $dt = $dt | 0;
+ $obj = $obj | 0;
+ $type = $type | 0;
+ var $and = 0, $tobool = 0, $meth = 0, $0 = 0, $searchf = 0, $1 = 0, $call = 0, $and1 = 0, $tobool2 = 0, $and3 = 0, $tobool4 = 0, $meth5 = 0, $2 = 0, $type6 = 0, $3 = 0, $and7 = 0, $tobool8 = 0, $tobool10100 = 0, $d_0101 = 0, $meth11 = 0, $4 = 0, $searchf12 = 0, $5 = 0, $call13 = 0, $tobool14 = 0, $view = 0, $6 = 0, $tobool10 = 0, $d_0_lcssa = 0, $o_1 = 0, $walk = 0, $meth18 = 0, $7 = 0, $type19 = 0, $8 = 0, $and20 = 0, $tobool21 = 0, $and23 = 0, $tobool24 = 0, $tobool2893 = 0, $and57 = 0, $tobool58 = 0, $and62 = 0, $tobool63 = 0, $d_197 = 0, $p_096 = 0, $nk_095 = 0, $n_094 = 0, $meth30 = 0, $9 = 0, $searchf31 = 0, $10 = 0, $call32 = 0, $tobool33 = 0, $disc = 0, $11 = 0, $key = 0, $12 = 0, $size = 0, $13 = 0, $comparf = 0, $14 = 0, $cmp39 = 0, $add_ptr = 0, $15 = 0, $16 = 0, $cond = 0, $tobool41 = 0, $tobool43 = 0, $17 = 0, $call46 = 0, $cmp48 = 0, $call50 = 0, $call52 = 0, $cond56 = 0, $cmp60 = 0, $or_cond = 0, $cmp65 = 0, $or_cond80 = 0, $or_cond112 = 0, $n_1 = 0, $nk_1 = 0, $p_1 = 0, $view70 = 0, $18 = 0, $tobool28 = 0, $p_0_lcssa = 0, $n_0_lcssa = 0, $walk72 = 0, $and74 = 0, $tobool75 = 0, $walk78 = 0, $19 = 0, $tobool79 = 0, $disc82 = 0, $20 = 0, $link83 = 0, $21 = 0, $cmp84 = 0, $data = 0, $22 = 0, $here = 0, $23 = 0, $obj87 = 0, $24 = 0, $25 = 0, $26 = 0, $idx_neg = 0, $add_ptr95 = 0, $cond97 = 0, $cmp98 = 0, $tobool10191 = 0, $d_292 = 0, $meth103 = 0, $27 = 0, $searchf104 = 0, $28 = 0, $call105 = 0, $tobool106 = 0, $view110 = 0, $29 = 0, $tobool101 = 0, $obj_addr_0 = 0, $30 = 0, $meth118 = 0, $31 = 0, $searchf119 = 0, $32 = 0, $call120 = 0, $and144 = 0, $tobool145 = 0, $d_3_ph = 0, $obj_addr_1_ph = 0, $tobool12288 = 0, $cmp12482 = 0, $meth136 = 0, $obj_addr_189 = 0, $p_283 = 0, $meth127 = 0, $33 = 0, $searchf128 = 0, $34 = 0, $call129 = 0, $tobool130 = 0, $view134 = 0, $35 = 0, $cmp124 = 0, $36 = 0, $searchf137 = 0, $37 = 0, $call138 = 0, $tobool122 = 0, $view139 = 0, $38 = 0, $tobool141 = 0, $meth147 = 0, $39 = 0, $searchf148 = 0, $40 = 0, $call149 = 0, $call153 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $and = $type & 99;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $meth = $dt + 16 | 0;
+ $0 = HEAP32[$meth >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($dt, $obj, $type) | 0;
+ $retval_0 = $call;
+ label = 50;
+ break;
+ case 4:
+ $and1 = $type & 516;
+ $tobool2 = ($and1 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $and3 = $type & 384;
+ $tobool4 = ($and3 | 0) == 0;
+ if ($tobool4) {
+ label = 11;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $meth5 = $dt + 16 | 0;
+ $2 = HEAP32[$meth5 >> 2] | 0;
+ $type6 = $2 + 4 | 0;
+ $3 = HEAP32[$type6 >> 2] | 0;
+ $and7 = $3 & 12;
+ $tobool8 = ($and7 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $tobool10100 = ($dt | 0) == 0;
+ if ($tobool10100) {
+ $o_1 = 0;
+ $d_0_lcssa = 0;
+ label = 10;
+ break;
+ } else {
+ $d_0101 = $dt;
+ label = 8;
+ break;
+ }
+ case 8:
+ $meth11 = $d_0101 + 16 | 0;
+ $4 = HEAP32[$meth11 >> 2] | 0;
+ $searchf12 = $4 | 0;
+ $5 = HEAP32[$searchf12 >> 2] | 0;
+ $call13 = FUNCTION_TABLE_iiii[$5 & 1023]($d_0101, $obj, $type) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ label = 9;
+ break;
+ } else {
+ $o_1 = $call13;
+ $d_0_lcssa = $d_0101;
+ label = 10;
+ break;
+ }
+ case 9:
+ $view = $d_0101 + 28 | 0;
+ $6 = HEAP32[$view >> 2] | 0;
+ $tobool10 = ($6 | 0) == 0;
+ if ($tobool10) {
+ $o_1 = 0;
+ $d_0_lcssa = 0;
+ label = 10;
+ break;
+ } else {
+ $d_0101 = $6;
+ label = 8;
+ break;
+ }
+ case 10:
+ $walk = $dt + 32 | 0;
+ HEAP32[$walk >> 2] = $d_0_lcssa;
+ $retval_0 = $o_1;
+ label = 50;
+ break;
+ case 11:
+ $meth18 = $dt + 16 | 0;
+ $7 = HEAP32[$meth18 >> 2] | 0;
+ $type19 = $7 + 4 | 0;
+ $8 = HEAP32[$type19 >> 2] | 0;
+ $and20 = $8 & 12;
+ $tobool21 = ($and20 | 0) == 0;
+ if ($tobool21) {
+ label = 28;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $and23 = $type & 408;
+ $tobool24 = ($and23 | 0) == 0;
+ if ($tobool24) {
+ $retval_0 = 0;
+ label = 50;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $tobool2893 = ($dt | 0) == 0;
+ if ($tobool2893) {
+ $n_0_lcssa = 0;
+ $p_0_lcssa = 0;
+ label = 27;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $and57 = $type & 136;
+ $tobool58 = ($and57 | 0) != 0;
+ $and62 = $type & 272;
+ $tobool63 = ($and62 | 0) != 0;
+ $n_094 = 0;
+ $nk_095 = 0;
+ $p_096 = 0;
+ $d_197 = $dt;
+ label = 15;
+ break;
+ case 15:
+ $meth30 = $d_197 + 16 | 0;
+ $9 = HEAP32[$meth30 >> 2] | 0;
+ $searchf31 = $9 | 0;
+ $10 = HEAP32[$searchf31 >> 2] | 0;
+ $call32 = FUNCTION_TABLE_iiii[$10 & 1023]($d_197, $obj, $type) | 0;
+ $tobool33 = ($call32 | 0) == 0;
+ if ($tobool33) {
+ $p_1 = $p_096;
+ $nk_1 = $nk_095;
+ $n_1 = $n_094;
+ label = 26;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $disc = $d_197 + 4 | 0;
+ $11 = HEAP32[$disc >> 2] | 0;
+ $key = $11 | 0;
+ $12 = HEAP32[$key >> 2] | 0;
+ $size = $11 + 4 | 0;
+ $13 = HEAP32[$size >> 2] | 0;
+ $comparf = $11 + 20 | 0;
+ $14 = HEAP32[$comparf >> 2] | 0;
+ $cmp39 = ($13 | 0) < 0;
+ $add_ptr = $call32 + $12 | 0;
+ if ($cmp39) {
+ label = 17;
+ break;
+ } else {
+ $cond = $add_ptr;
+ label = 18;
+ break;
+ }
+ case 17:
+ $15 = $add_ptr;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $cond = $16;
+ label = 18;
+ break;
+ case 18:
+ $tobool41 = ($n_094 | 0) == 0;
+ if ($tobool41) {
+ label = 25;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $tobool43 = ($14 | 0) == 0;
+ if ($tobool43) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $17 = HEAP32[$disc >> 2] | 0;
+ $call46 = FUNCTION_TABLE_iiiii[$14 & 1023]($d_197, $cond, $nk_095, $17) | 0;
+ $cond56 = $call46;
+ label = 24;
+ break;
+ case 21:
+ $cmp48 = ($13 | 0) < 1;
+ if ($cmp48) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $call50 = _strcmp($cond | 0, $nk_095 | 0) | 0;
+ $cond56 = $call50;
+ label = 24;
+ break;
+ case 23:
+ $call52 = _memcmp($cond | 0, $nk_095 | 0, $13 | 0) | 0;
+ $cond56 = $call52;
+ label = 24;
+ break;
+ case 24:
+ $cmp60 = ($cond56 | 0) < 0;
+ $or_cond = $tobool58 & $cmp60;
+ $cmp65 = ($cond56 | 0) > 0;
+ $or_cond80 = $tobool63 & $cmp65;
+ $or_cond112 = $or_cond | $or_cond80;
+ if ($or_cond112) {
+ label = 25;
+ break;
+ } else {
+ $p_1 = $p_096;
+ $nk_1 = $nk_095;
+ $n_1 = $n_094;
+ label = 26;
+ break;
+ }
+ case 25:
+ $p_1 = $d_197;
+ $nk_1 = $cond;
+ $n_1 = $call32;
+ label = 26;
+ break;
+ case 26:
+ $view70 = $d_197 + 28 | 0;
+ $18 = HEAP32[$view70 >> 2] | 0;
+ $tobool28 = ($18 | 0) == 0;
+ if ($tobool28) {
+ $n_0_lcssa = $n_1;
+ $p_0_lcssa = $p_1;
+ label = 27;
+ break;
+ } else {
+ $n_094 = $n_1;
+ $nk_095 = $nk_1;
+ $p_096 = $p_1;
+ $d_197 = $18;
+ label = 15;
+ break;
+ }
+ case 27:
+ $walk72 = $dt + 32 | 0;
+ HEAP32[$walk72 >> 2] = $p_0_lcssa;
+ $retval_0 = $n_0_lcssa;
+ label = 50;
+ break;
+ case 28:
+ $and74 = $type & 24;
+ $tobool75 = ($and74 | 0) == 0;
+ if ($tobool75) {
+ $retval_0 = 0;
+ label = 50;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $walk78 = $dt + 32 | 0;
+ $19 = HEAP32[$walk78 >> 2] | 0;
+ $tobool79 = ($19 | 0) == 0;
+ if ($tobool79) {
+ label = 34;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $disc82 = $19 + 4 | 0;
+ $20 = HEAP32[$disc82 >> 2] | 0;
+ $link83 = $20 + 8 | 0;
+ $21 = HEAP32[$link83 >> 2] | 0;
+ $cmp84 = ($21 | 0) < 0;
+ $data = $19 + 8 | 0;
+ $22 = HEAP32[$data >> 2] | 0;
+ $here = $22 + 4 | 0;
+ $23 = HEAP32[$here >> 2] | 0;
+ if ($cmp84) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ $obj87 = $23 + 8 | 0;
+ $24 = $obj87;
+ $25 = HEAP32[$24 >> 2] | 0;
+ $cond97 = $25;
+ label = 33;
+ break;
+ case 32:
+ $26 = $23;
+ $idx_neg = -$21 | 0;
+ $add_ptr95 = $26 + $idx_neg | 0;
+ $cond97 = $add_ptr95;
+ label = 33;
+ break;
+ case 33:
+ $cmp98 = ($cond97 | 0) == ($obj | 0);
+ if ($cmp98) {
+ $obj_addr_0 = $obj;
+ label = 39;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $tobool10191 = ($dt | 0) == 0;
+ if ($tobool10191) {
+ label = 38;
+ break;
+ } else {
+ $d_292 = $dt;
+ label = 35;
+ break;
+ }
+ case 35:
+ $meth103 = $d_292 + 16 | 0;
+ $27 = HEAP32[$meth103 >> 2] | 0;
+ $searchf104 = $27 | 0;
+ $28 = HEAP32[$searchf104 >> 2] | 0;
+ $call105 = FUNCTION_TABLE_iiii[$28 & 1023]($d_292, $obj, 4) | 0;
+ $tobool106 = ($call105 | 0) == 0;
+ if ($tobool106) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ HEAP32[$walk78 >> 2] = $d_292;
+ $obj_addr_0 = $call105;
+ label = 39;
+ break;
+ case 37:
+ $view110 = $d_292 + 28 | 0;
+ $29 = HEAP32[$view110 >> 2] | 0;
+ $tobool101 = ($29 | 0) == 0;
+ if ($tobool101) {
+ label = 38;
+ break;
+ } else {
+ $d_292 = $29;
+ label = 35;
+ break;
+ }
+ case 38:
+ HEAP32[$walk78 >> 2] = 0;
+ $retval_0 = 0;
+ label = 50;
+ break;
+ case 39:
+ $30 = HEAP32[$walk78 >> 2] | 0;
+ $meth118 = $30 + 16 | 0;
+ $31 = HEAP32[$meth118 >> 2] | 0;
+ $searchf119 = $31 | 0;
+ $32 = HEAP32[$searchf119 >> 2] | 0;
+ $call120 = FUNCTION_TABLE_iiii[$32 & 1023]($30, $obj_addr_0, $type) | 0;
+ $and144 = $type & 8;
+ $tobool145 = ($and144 | 0) == 0;
+ $obj_addr_1_ph = $call120;
+ $d_3_ph = $30;
+ label = 40;
+ break;
+ case 40:
+ $tobool12288 = ($obj_addr_1_ph | 0) == 0;
+ if ($tobool12288) {
+ label = 46;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $cmp12482 = ($d_3_ph | 0) == ($dt | 0);
+ $meth136 = $d_3_ph + 16 | 0;
+ $obj_addr_189 = $obj_addr_1_ph;
+ label = 42;
+ break;
+ case 42:
+ if ($cmp12482) {
+ $retval_0 = $obj_addr_189;
+ label = 50;
+ break;
+ } else {
+ $p_283 = $dt;
+ label = 43;
+ break;
+ }
+ case 43:
+ $meth127 = $p_283 + 16 | 0;
+ $33 = HEAP32[$meth127 >> 2] | 0;
+ $searchf128 = $33 | 0;
+ $34 = HEAP32[$searchf128 >> 2] | 0;
+ $call129 = FUNCTION_TABLE_iiii[$34 & 1023]($p_283, $obj_addr_189, 4) | 0;
+ $tobool130 = ($call129 | 0) == 0;
+ if ($tobool130) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 44:
+ $view134 = $p_283 + 28 | 0;
+ $35 = HEAP32[$view134 >> 2] | 0;
+ $cmp124 = ($35 | 0) == ($d_3_ph | 0);
+ if ($cmp124) {
+ $retval_0 = $obj_addr_189;
+ label = 50;
+ break;
+ } else {
+ $p_283 = $35;
+ label = 43;
+ break;
+ }
+ case 45:
+ $36 = HEAP32[$meth136 >> 2] | 0;
+ $searchf137 = $36 | 0;
+ $37 = HEAP32[$searchf137 >> 2] | 0;
+ $call138 = FUNCTION_TABLE_iiii[$37 & 1023]($d_3_ph, $obj_addr_189, $type) | 0;
+ $tobool122 = ($call138 | 0) == 0;
+ if ($tobool122) {
+ label = 46;
+ break;
+ } else {
+ $obj_addr_189 = $call138;
+ label = 42;
+ break;
+ }
+ case 46:
+ $view139 = $d_3_ph + 28 | 0;
+ $38 = HEAP32[$view139 >> 2] | 0;
+ HEAP32[$walk78 >> 2] = $38;
+ $tobool141 = ($38 | 0) == 0;
+ if ($tobool141) {
+ $retval_0 = 0;
+ label = 50;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $meth147 = $38 + 16 | 0;
+ $39 = HEAP32[$meth147 >> 2] | 0;
+ $searchf148 = $39 | 0;
+ $40 = HEAP32[$searchf148 >> 2] | 0;
+ if ($tobool145) {
+ label = 49;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $call149 = FUNCTION_TABLE_iiii[$40 & 1023]($38, 0, 128) | 0;
+ $obj_addr_1_ph = $call149;
+ $d_3_ph = $38;
+ label = 40;
+ break;
+ case 49:
+ $call153 = FUNCTION_TABLE_iiii[$40 & 1023]($38, 0, 256) | 0;
+ $obj_addr_1_ph = $call153;
+ $d_3_ph = $38;
+ label = 40;
+ break;
+ case 50:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dtwalk($dt, $userf, $data) {
+ $dt = $dt | 0;
+ $userf = $userf | 0;
+ $data = $data | 0;
+ var $searchf = 0, $0 = 0, $call = 0, $walk1 = 0, $callee_knr_cast = 0, $obj_0 = 0, $tobool = 0, $1 = 0, $tobool2 = 0, $dt_ = 0, $2 = 0, $call4 = 0, $call5 = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $searchf = $dt | 0;
+ $0 = HEAP32[$searchf >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$0 & 1023]($dt, 0, 128) | 0;
+ $walk1 = $dt + 32 | 0;
+ $callee_knr_cast = $userf;
+ $obj_0 = $call;
+ label = 3;
+ break;
+ case 3:
+ $tobool = ($obj_0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[$walk1 >> 2] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ $dt_ = $tobool2 ? $dt : $1;
+ $2 = HEAP32[$searchf >> 2] | 0;
+ $call4 = FUNCTION_TABLE_iiii[$2 & 1023]($dt, $obj_0, 8) | 0;
+ $call5 = FUNCTION_TABLE_iiii[$callee_knr_cast & 1023]($dt_, $obj_0, $data) | 0;
+ $cmp = ($call5 | 0) < 0;
+ if ($cmp) {
+ $retval_0 = $call5;
+ label = 5;
+ break;
+ } else {
+ $obj_0 = $call4;
+ label = 3;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _arrow_flags($e, $sflag, $eflag) {
+ $e = $e | 0;
+ $sflag = $sflag | 0;
+ $eflag = $eflag | 0;
+ var $s0 = 0, $e0 = 0, $tail = 0, $0 = 0, $graph = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $and = 0, $5 = 0, $tobool1 = 0, $6 = 0, $index = 0, $7 = 0, $call = 0, $8 = 0, $tobool2 = 0, $9 = 0, $call10 = 0, $tobool11 = 0, $arrowdir_028_lcssa = 0, $sflag13 = 0, $10 = 0, $eflag14 = 0, $11 = 0, $12 = 0, $tobool16 = 0, $13 = 0, $cmp18 = 0, $14 = 0, $index21 = 0, $15 = 0, $call22 = 0, $16 = 0, $tobool25 = 0, $17 = 0, $tobool28 = 0, $18 = 0, $cmp30 = 0, $19 = 0, $index33 = 0, $20 = 0, $call34 = 0, $21 = 0, $tobool37 = 0, $conc_opp_flag = 0, $22 = 0, $tobool40 = 0, $head = 0, $23 = 0, $graph42 = 0, $24 = 0, $25 = 0, $26 = 0, $27 = 0, $28 = 0, $call45 = 0, $29 = 0, $30 = 0, $31 = 0, $or = 0, $32 = 0, $33 = 0, $or46 = 0, $call10_1 = 0, $tobool11_1 = 0, $call10_2 = 0, $tobool11_2 = 0, $cmp_3 = 0, $call10_3 = 0, $tobool11_3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s0 = __stackBase__ | 0;
+ $e0 = __stackBase__ + 8 | 0;
+ HEAP32[$sflag >> 2] = 0;
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $2 = $1;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $4 = $3 >>> 4;
+ $and = $4 & 1;
+ HEAP32[$eflag >> 2] = $and;
+ $5 = HEAP32[41946] | 0;
+ $tobool1 = ($5 | 0) == 0;
+ if ($tobool1) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $6 = $e | 0;
+ $index = $5 + 8 | 0;
+ $7 = HEAP32[$index >> 2] | 0;
+ $call = _agxget($6, $7) | 0;
+ $8 = HEAP8[$call] | 0;
+ $tobool2 = $8 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $9 = HEAP8[$call] | 0;
+ if (($9 << 24 >> 24 | 0) == 102) {
+ label = 5;
+ break;
+ } else if (($9 << 24 >> 24 | 0) == 98) {
+ label = 18;
+ break;
+ } else if (($9 << 24 >> 24 | 0) == 110) {
+ label = 21;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $call10 = _strcmp($call | 0, 139944) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ if ($tobool11) {
+ $arrowdir_028_lcssa = 168464;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $sflag13 = $arrowdir_028_lcssa + 4 | 0;
+ $10 = HEAP32[$sflag13 >> 2] | 0;
+ HEAP32[$sflag >> 2] = $10;
+ $eflag14 = $arrowdir_028_lcssa + 8 | 0;
+ $11 = HEAP32[$eflag14 >> 2] | 0;
+ HEAP32[$eflag >> 2] = $11;
+ label = 7;
+ break;
+ case 7:
+ $12 = HEAP32[41964] | 0;
+ $tobool16 = ($12 | 0) == 0;
+ if ($tobool16) {
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $13 = HEAP32[$eflag >> 2] | 0;
+ $cmp18 = ($13 | 0) == 1;
+ if ($cmp18) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $14 = $e | 0;
+ $index21 = $12 + 8 | 0;
+ $15 = HEAP32[$index21 >> 2] | 0;
+ $call22 = _agxget($14, $15) | 0;
+ $16 = HEAP8[$call22] | 0;
+ $tobool25 = $16 << 24 >> 24 == 0;
+ if ($tobool25) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ _arrow_match_name($call22, $eflag);
+ label = 11;
+ break;
+ case 11:
+ $17 = HEAP32[41960] | 0;
+ $tobool28 = ($17 | 0) == 0;
+ if ($tobool28) {
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $18 = HEAP32[$sflag >> 2] | 0;
+ $cmp30 = ($18 | 0) == 1;
+ if ($cmp30) {
+ label = 13;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $19 = $e | 0;
+ $index33 = $17 + 8 | 0;
+ $20 = HEAP32[$index33 >> 2] | 0;
+ $call34 = _agxget($19, $20) | 0;
+ $21 = HEAP8[$call34] | 0;
+ $tobool37 = $21 << 24 >> 24 == 0;
+ if ($tobool37) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ _arrow_match_name($call34, $sflag);
+ label = 15;
+ break;
+ case 15:
+ $conc_opp_flag = $e + 169 | 0;
+ $22 = HEAP8[$conc_opp_flag] | 0;
+ $tobool40 = $22 << 24 >> 24 == 0;
+ if ($tobool40) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $head = $e + 12 | 0;
+ $23 = HEAP32[$head >> 2] | 0;
+ $graph42 = $23 + 20 | 0;
+ $24 = HEAP32[$graph42 >> 2] | 0;
+ $25 = HEAP32[$tail >> 2] | 0;
+ $26 = $24;
+ $27 = $23;
+ $28 = $25;
+ $call45 = _agfindedge($26, $27, $28) | 0;
+ $29 = $call45;
+ _arrow_flags($29, $s0, $e0);
+ $30 = HEAP32[$eflag >> 2] | 0;
+ $31 = HEAP32[$s0 >> 2] | 0;
+ $or = $31 | $30;
+ HEAP32[$eflag >> 2] = $or;
+ $32 = HEAP32[$sflag >> 2] | 0;
+ $33 = HEAP32[$e0 >> 2] | 0;
+ $or46 = $33 | $32;
+ HEAP32[$sflag >> 2] = $or46;
+ label = 17;
+ break;
+ case 17:
+ STACKTOP = __stackBase__;
+ return;
+ case 18:
+ $call10_1 = _strcmp($call | 0, 137248) | 0;
+ $tobool11_1 = ($call10_1 | 0) == 0;
+ if ($tobool11_1) {
+ $arrowdir_028_lcssa = 168476;
+ label = 6;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $call10_2 = _strcmp($call | 0, 134776) | 0;
+ $tobool11_2 = ($call10_2 | 0) == 0;
+ if ($tobool11_2) {
+ $arrowdir_028_lcssa = 168488;
+ label = 6;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $cmp_3 = $9 << 24 >> 24 == 110;
+ if ($cmp_3) {
+ label = 21;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 21:
+ $call10_3 = _strcmp($call | 0, 105072) | 0;
+ $tobool11_3 = ($call10_3 | 0) == 0;
+ if ($tobool11_3) {
+ $arrowdir_028_lcssa = 168500;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ }
+}
+function _arrow_match_name($name, $flag) {
+ $name = $name | 0;
+ $flag = $flag | 0;
+ var $f = 0, $0 = 0, $cmp5 = 0, $i_07 = 0, $rest_06 = 0, $call = 0, $1 = 0, $mul = 0, $shl = 0, $2 = 0, $or = 0, $inc = 0, $3 = 0, $cmp = 0, $cmp2 = 0, $or_cond = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $f = __stackBase__ | 0;
+ HEAP32[$flag >> 2] = 0;
+ $0 = HEAP8[$name] | 0;
+ $cmp5 = $0 << 24 >> 24 == 0;
+ if ($cmp5) {
+ label = 4;
+ break;
+ } else {
+ $rest_06 = $name;
+ $i_07 = 0;
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAP32[$f >> 2] = 0;
+ $call = _arrow_match_shape($rest_06, $f) | 0;
+ $1 = HEAP32[$f >> 2] | 0;
+ $mul = $i_07 << 3;
+ $shl = $1 << $mul;
+ $2 = HEAP32[$flag >> 2] | 0;
+ $or = $2 | $shl;
+ HEAP32[$flag >> 2] = $or;
+ $inc = $i_07 + 1 | 0;
+ $3 = HEAP8[$call] | 0;
+ $cmp = $3 << 24 >> 24 != 0;
+ $cmp2 = ($inc | 0) < 4;
+ $or_cond = $cmp & $cmp2;
+ if ($or_cond) {
+ $rest_06 = $call;
+ $i_07 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_length($e, $flag) {
+ $e = $e | 0;
+ $flag = $flag | 0;
+ var $and = 0, $arrowtype_0 = 0, $gen = 0, $0 = 0, $tobool = 0, $type = 0, $1 = 0, $cmp3 = 0, $incdec_ptr = 0, $lenfact4 = 0, $2 = 0.0, $add = 0.0, $lenfact_1 = 0.0, $shr_110 = 0, $and_1 = 0, $arrowtype_0_1 = 0, $gen_1 = 0, $3 = 0, $tobool_1 = 0, $type_1 = 0, $4 = 0, $cmp3_1 = 0, $incdec_ptr_1 = 0, $lenfact4_1 = 0, $5 = 0.0, $add_1 = 0.0, $lenfact_1_1 = 0.0, $shr_211 = 0, $and_2 = 0, $arrowtype_0_2 = 0, $gen_2 = 0, $6 = 0, $tobool_2 = 0, $type_2 = 0, $7 = 0, $cmp3_2 = 0, $incdec_ptr_2 = 0, $lenfact4_2 = 0, $8 = 0.0, $add_2 = 0.0, $lenfact_1_2 = 0.0, $shr_312 = 0, $and_3 = 0, $arrowtype_0_3 = 0, $gen_3 = 0, $9 = 0, $tobool_3 = 0, $type_3 = 0, $10 = 0, $cmp3_3 = 0, $incdec_ptr_3 = 0, $lenfact4_3 = 0, $11 = 0.0, $add_3 = 0.0, $lenfact_1_3 = 0.0, $mul7 = 0.0, $12 = 0, $13 = 0, $call = 0.0, $mul8 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $and = $flag & 7;
+ $arrowtype_0 = 168136;
+ label = 3;
+ break;
+ case 3:
+ $gen = $arrowtype_0 + 16 | 0;
+ $0 = HEAP32[$gen >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $lenfact_1 = 0.0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $type = $arrowtype_0 | 0;
+ $1 = HEAP32[$type >> 2] | 0;
+ $cmp3 = ($and | 0) == ($1 | 0);
+ $incdec_ptr = $arrowtype_0 + 24 | 0;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ $arrowtype_0 = $incdec_ptr;
+ label = 3;
+ break;
+ }
+ case 5:
+ $lenfact4 = $arrowtype_0 + 8 | 0;
+ $2 = +HEAPF64[$lenfact4 >> 3];
+ $add = $2 + 0.0;
+ $lenfact_1 = $add;
+ label = 6;
+ break;
+ case 6:
+ $shr_110 = $flag >>> 8;
+ $and_1 = $shr_110 & 7;
+ $arrowtype_0_1 = 168136;
+ label = 7;
+ break;
+ case 7:
+ $gen_1 = $arrowtype_0_1 + 16 | 0;
+ $3 = HEAP32[$gen_1 >> 2] | 0;
+ $tobool_1 = ($3 | 0) == 0;
+ if ($tobool_1) {
+ $lenfact_1_1 = $lenfact_1;
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type_1 = $arrowtype_0_1 | 0;
+ $4 = HEAP32[$type_1 >> 2] | 0;
+ $cmp3_1 = ($and_1 | 0) == ($4 | 0);
+ $incdec_ptr_1 = $arrowtype_0_1 + 24 | 0;
+ if ($cmp3_1) {
+ label = 9;
+ break;
+ } else {
+ $arrowtype_0_1 = $incdec_ptr_1;
+ label = 7;
+ break;
+ }
+ case 9:
+ $lenfact4_1 = $arrowtype_0_1 + 8 | 0;
+ $5 = +HEAPF64[$lenfact4_1 >> 3];
+ $add_1 = $lenfact_1 + $5;
+ $lenfact_1_1 = $add_1;
+ label = 10;
+ break;
+ case 10:
+ $shr_211 = $flag >>> 16;
+ $and_2 = $shr_211 & 7;
+ $arrowtype_0_2 = 168136;
+ label = 11;
+ break;
+ case 11:
+ $gen_2 = $arrowtype_0_2 + 16 | 0;
+ $6 = HEAP32[$gen_2 >> 2] | 0;
+ $tobool_2 = ($6 | 0) == 0;
+ if ($tobool_2) {
+ $lenfact_1_2 = $lenfact_1_1;
+ label = 14;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $type_2 = $arrowtype_0_2 | 0;
+ $7 = HEAP32[$type_2 >> 2] | 0;
+ $cmp3_2 = ($and_2 | 0) == ($7 | 0);
+ $incdec_ptr_2 = $arrowtype_0_2 + 24 | 0;
+ if ($cmp3_2) {
+ label = 13;
+ break;
+ } else {
+ $arrowtype_0_2 = $incdec_ptr_2;
+ label = 11;
+ break;
+ }
+ case 13:
+ $lenfact4_2 = $arrowtype_0_2 + 8 | 0;
+ $8 = +HEAPF64[$lenfact4_2 >> 3];
+ $add_2 = $lenfact_1_1 + $8;
+ $lenfact_1_2 = $add_2;
+ label = 14;
+ break;
+ case 14:
+ $shr_312 = $flag >>> 24;
+ $and_3 = $shr_312 & 7;
+ $arrowtype_0_3 = 168136;
+ label = 15;
+ break;
+ case 15:
+ $gen_3 = $arrowtype_0_3 + 16 | 0;
+ $9 = HEAP32[$gen_3 >> 2] | 0;
+ $tobool_3 = ($9 | 0) == 0;
+ if ($tobool_3) {
+ $lenfact_1_3 = $lenfact_1_2;
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $type_3 = $arrowtype_0_3 | 0;
+ $10 = HEAP32[$type_3 >> 2] | 0;
+ $cmp3_3 = ($and_3 | 0) == ($10 | 0);
+ $incdec_ptr_3 = $arrowtype_0_3 + 24 | 0;
+ if ($cmp3_3) {
+ label = 17;
+ break;
+ } else {
+ $arrowtype_0_3 = $incdec_ptr_3;
+ label = 15;
+ break;
+ }
+ case 17:
+ $lenfact4_3 = $arrowtype_0_3 + 8 | 0;
+ $11 = +HEAPF64[$lenfact4_3 >> 3];
+ $add_3 = $lenfact_1_2 + $11;
+ $lenfact_1_3 = $add_3;
+ label = 18;
+ break;
+ case 18:
+ $mul7 = $lenfact_1_3 * 10.0;
+ $12 = $e | 0;
+ $13 = HEAP32[41962] | 0;
+ $call = +_late_double($12, $13, 1.0, 0.0);
+ $mul8 = $mul7 * $call;
+ return +$mul8;
+ }
+ return 0.0;
+}
+function _arrowEndClip($e, $ps, $startp, $endp, $spl, $eflag) {
+ $e = $e | 0;
+ $ps = $ps | 0;
+ $startp = $startp | 0;
+ $endp = $endp | 0;
+ $spl = $spl | 0;
+ $eflag = $eflag | 0;
+ var $inside_context = 0, $sp = 0, $elen2 = 0, $call = 0.0, $mul = 0.0, $eflag1 = 0, $ep = 0, $add = 0, $arrayidx = 0, $0 = 0, $1 = 0, $cmp = 0, $x = 0, $2 = 0.0, $x5 = 0, $3 = 0.0, $sub = 0.0, $mul12 = 0.0, $y = 0, $4 = 0.0, $y16 = 0, $5 = 0.0, $sub17 = 0.0, $mul24 = 0.0, $add25 = 0.0, $6 = 0.0, $cmp26 = 0, $sub27 = 0, $endp_addr_0 = 0, $arrayidx28 = 0, $arrayidx29 = 0, $7 = 0, $8 = 0, $arrayidx30 = 0, $add31 = 0, $arrayidx32 = 0, $9 = 0, $10 = 0, $arrayidx33 = 0, $add34 = 0, $arrayidx35 = 0, $11 = 0, $12 = 0, $arrayidx36 = 0, $13 = 0, $p = 0, $r = 0, $add48 = 0, $arrayidx49 = 0, $14 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 80 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $inside_context = __stackBase__ | 0;
+ $sp = __stackBase__ + 8 | 0;
+ $elen2 = __stackBase__ + 72 | 0;
+ $call = +_arrow_length($e, $eflag);
+ $mul = $call * $call;
+ HEAPF64[$elen2 >> 3] = $mul;
+ $eflag1 = $spl + 12 | 0;
+ HEAP32[$eflag1 >> 2] = $eflag;
+ $ep = $spl + 32 | 0;
+ $add = $endp + 3 | 0;
+ $arrayidx = $ps + ($add << 4) | 0;
+ $0 = $ep;
+ $1 = $arrayidx;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $cmp = ($endp | 0) > ($startp | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $endp_addr_0 = $endp;
+ label = 5;
+ break;
+ }
+ case 3:
+ $x = $ps + ($endp << 4) | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x5 = $arrayidx | 0;
+ $3 = +HEAPF64[$x5 >> 3];
+ $sub = $2 - $3;
+ $mul12 = $sub * $sub;
+ $y = $ps + ($endp << 4) + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y16 = $ps + ($add << 4) + 8 | 0;
+ $5 = +HEAPF64[$y16 >> 3];
+ $sub17 = $4 - $5;
+ $mul24 = $sub17 * $sub17;
+ $add25 = $mul12 + $mul24;
+ $6 = +HEAPF64[$elen2 >> 3];
+ $cmp26 = $add25 < $6;
+ if ($cmp26) {
+ label = 4;
+ break;
+ } else {
+ $endp_addr_0 = $endp;
+ label = 5;
+ break;
+ }
+ case 4:
+ $sub27 = $endp - 3 | 0;
+ $endp_addr_0 = $sub27;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx28 = $sp + 48 | 0;
+ $arrayidx29 = $ps + ($endp_addr_0 << 4) | 0;
+ $7 = $arrayidx28;
+ $8 = $arrayidx29;
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $arrayidx30 = $sp + 32 | 0;
+ $add31 = $endp_addr_0 + 1 | 0;
+ $arrayidx32 = $ps + ($add31 << 4) | 0;
+ $9 = $arrayidx30;
+ $10 = $arrayidx32;
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $arrayidx33 = $sp + 16 | 0;
+ $add34 = $endp_addr_0 + 2 | 0;
+ $arrayidx35 = $ps + ($add34 << 4) | 0;
+ $11 = $arrayidx33;
+ $12 = $arrayidx35;
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ $arrayidx36 = $sp | 0;
+ $13 = $sp;
+ HEAP32[$13 >> 2] = HEAP32[$0 >> 2] | 0;
+ HEAP32[$13 + 4 >> 2] = HEAP32[$0 + 4 >> 2] | 0;
+ HEAP32[$13 + 8 >> 2] = HEAP32[$0 + 8 >> 2] | 0;
+ HEAP32[$13 + 12 >> 2] = HEAP32[$0 + 12 >> 2] | 0;
+ $p = $inside_context | 0;
+ HEAP32[$p >> 2] = $arrayidx36;
+ $r = $inside_context + 4 | 0;
+ HEAP32[$r >> 2] = $elen2;
+ _bezier_clip($inside_context, 600, $arrayidx36, 1);
+ HEAP32[$8 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ HEAP32[$10 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ HEAP32[$12 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ $add48 = $endp_addr_0 + 3 | 0;
+ $arrayidx49 = $ps + ($add48 << 4) | 0;
+ $14 = $arrayidx49;
+ HEAP32[$14 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return $endp_addr_0 | 0;
+ }
+ return 0;
+}
+function _arrowStartClip($e, $ps, $startp, $endp, $spl, $sflag) {
+ $e = $e | 0;
+ $ps = $ps | 0;
+ $startp = $startp | 0;
+ $endp = $endp | 0;
+ $spl = $spl | 0;
+ $sflag = $sflag | 0;
+ var $inside_context = 0, $sp = 0, $slen2 = 0, $call = 0.0, $mul = 0.0, $sflag1 = 0, $sp2 = 0, $arrayidx = 0, $0 = 0, $1 = 0, $cmp = 0, $x = 0, $2 = 0.0, $add = 0, $x5 = 0, $3 = 0.0, $sub = 0.0, $mul12 = 0.0, $y = 0, $4 = 0.0, $y16 = 0, $5 = 0.0, $sub17 = 0.0, $mul24 = 0.0, $add25 = 0.0, $6 = 0.0, $cmp26 = 0, $startp_addr_0 = 0, $arrayidx28 = 0, $add29 = 0, $arrayidx30 = 0, $7 = 0, $8 = 0, $arrayidx31 = 0, $add32 = 0, $arrayidx33 = 0, $9 = 0, $10 = 0, $arrayidx34 = 0, $add35 = 0, $arrayidx36 = 0, $11 = 0, $12 = 0, $arrayidx37 = 0, $13 = 0, $p = 0, $r = 0, $arrayidx41 = 0, $14 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 80 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $inside_context = __stackBase__ | 0;
+ $sp = __stackBase__ + 8 | 0;
+ $slen2 = __stackBase__ + 72 | 0;
+ $call = +_arrow_length($e, $sflag);
+ $mul = $call * $call;
+ HEAPF64[$slen2 >> 3] = $mul;
+ $sflag1 = $spl + 8 | 0;
+ HEAP32[$sflag1 >> 2] = $sflag;
+ $sp2 = $spl + 16 | 0;
+ $arrayidx = $ps + ($startp << 4) | 0;
+ $0 = $sp2;
+ $1 = $arrayidx;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $cmp = ($endp | 0) > ($startp | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $startp_addr_0 = $startp;
+ label = 5;
+ break;
+ }
+ case 3:
+ $x = $arrayidx | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $add = $startp + 3 | 0;
+ $x5 = $ps + ($add << 4) | 0;
+ $3 = +HEAPF64[$x5 >> 3];
+ $sub = $2 - $3;
+ $mul12 = $sub * $sub;
+ $y = $ps + ($startp << 4) + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y16 = $ps + ($add << 4) + 8 | 0;
+ $5 = +HEAPF64[$y16 >> 3];
+ $sub17 = $4 - $5;
+ $mul24 = $sub17 * $sub17;
+ $add25 = $mul12 + $mul24;
+ $6 = +HEAPF64[$slen2 >> 3];
+ $cmp26 = $add25 < $6;
+ if ($cmp26) {
+ label = 4;
+ break;
+ } else {
+ $startp_addr_0 = $startp;
+ label = 5;
+ break;
+ }
+ case 4:
+ $startp_addr_0 = $add;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx28 = $sp | 0;
+ $add29 = $startp_addr_0 + 3 | 0;
+ $arrayidx30 = $ps + ($add29 << 4) | 0;
+ $7 = $sp;
+ $8 = $arrayidx30;
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $arrayidx31 = $sp + 16 | 0;
+ $add32 = $startp_addr_0 + 2 | 0;
+ $arrayidx33 = $ps + ($add32 << 4) | 0;
+ $9 = $arrayidx31;
+ $10 = $arrayidx33;
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $arrayidx34 = $sp + 32 | 0;
+ $add35 = $startp_addr_0 + 1 | 0;
+ $arrayidx36 = $ps + ($add35 << 4) | 0;
+ $11 = $arrayidx34;
+ $12 = $arrayidx36;
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ $arrayidx37 = $sp + 48 | 0;
+ $13 = $arrayidx37;
+ HEAP32[$13 >> 2] = HEAP32[$0 >> 2] | 0;
+ HEAP32[$13 + 4 >> 2] = HEAP32[$0 + 4 >> 2] | 0;
+ HEAP32[$13 + 8 >> 2] = HEAP32[$0 + 8 >> 2] | 0;
+ HEAP32[$13 + 12 >> 2] = HEAP32[$0 + 12 >> 2] | 0;
+ $p = $inside_context | 0;
+ HEAP32[$p >> 2] = $arrayidx37;
+ $r = $inside_context + 4 | 0;
+ HEAP32[$r >> 2] = $slen2;
+ _bezier_clip($inside_context, 600, $arrayidx28, 0);
+ $arrayidx41 = $ps + ($startp_addr_0 << 4) | 0;
+ $14 = $arrayidx41;
+ HEAP32[$14 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ HEAP32[$12 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ HEAP32[$10 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ HEAP32[$8 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return $startp_addr_0 | 0;
+ }
+ return 0;
+}
+function _arrowOrthoClip($e, $ps, $startp, $endp, $spl, $sflag, $eflag) {
+ $e = $e | 0;
+ $ps = $ps | 0;
+ $startp = $startp | 0;
+ $endp = $endp | 0;
+ $spl = $spl | 0;
+ $sflag = $sflag | 0;
+ $eflag = $eflag | 0;
+ var $tobool = 0, $tobool1 = 0, $tobool1_not = 0, $or_cond_not = 0, $cmp = 0, $or_cond174 = 0, $arrayidx = 0, $p_sroa_0_0__idx93 = 0, $p_sroa_0_0_copyload94 = 0.0, $p_sroa_1_8__idx121 = 0, $p_sroa_1_8_copyload122 = 0.0, $add = 0, $arrayidx3 = 0, $q_sroa_0_0__idx45 = 0, $q_sroa_0_0_copyload46 = 0.0, $q_sroa_1_8__idx69 = 0, $q_sroa_1_8_copyload70 = 0.0, $call = 0.0, $call4 = 0.0, $sub = 0.0, $mul = 0.0, $sub10 = 0.0, $mul14 = 0.0, $add15 = 0.0, $call16 = 0.0, $add17 = 0.0, $cmp18 = 0, $div = 0.0, $tlen_0 = 0.0, $hlen_0 = 0.0, $cmp22 = 0, $cmp29 = 0, $sub32 = 0.0, $add35 = 0.0, $add38 = 0.0, $sub41 = 0.0, $cmp50 = 0, $sub53 = 0.0, $add56 = 0.0, $add60 = 0.0, $sub63 = 0.0, $s_sroa_1_0 = 0.0, $s_sroa_0_0 = 0.0, $t_sroa_1_0 = 0.0, $t_sroa_0_0 = 0.0, $add68 = 0, $arrayidx69 = 0, $s_sroa_0_0__idx = 0, $s_sroa_1_8__idx21 = 0, $0 = 0, $1 = 0, $add70 = 0, $arrayidx71 = 0, $2 = 0, $3 = 0, $eflag74 = 0, $p_sroa_0_0__idx85 = 0, $p_sroa_1_8__idx112 = 0, $sflag75 = 0, $call80 = 0.0, $p_sroa_0_0__idx83 = 0, $p_sroa_0_0_copyload84 = 0.0, $p_sroa_1_8__idx110 = 0, $p_sroa_1_8_copyload111 = 0.0, $add82 = 0, $arrayidx83 = 0, $q_sroa_0_0__idx37 = 0, $q_sroa_0_0_copyload38 = 0.0, $q_sroa_1_8__idx60 = 0, $q_sroa_1_8_copyload61 = 0.0, $sub86 = 0.0, $mul90 = 0.0, $sub93 = 0.0, $mul97 = 0.0, $add98 = 0.0, $call99 = 0.0, $mul100 = 0.0, $cmp101 = 0, $hlen_1 = 0.0, $cmp106 = 0, $cmp112 = 0, $sub115 = 0.0, $add119 = 0.0, $cmp127 = 0, $sub130 = 0.0, $add134 = 0.0, $r_sroa_1_0 = 0.0, $r_sroa_0_0 = 0.0, $add138 = 0, $p_sroa_0_0__idx77 = 0, $p_sroa_1_8__idx103 = 0, $add140 = 0, $arrayidx141 = 0, $4 = 0, $5 = 0, $eflag144 = 0, $q_sroa_0_0__idx31 = 0, $q_sroa_1_8__idx53 = 0, $hlen_2 = 0.0, $call149 = 0.0, $arrayidx150 = 0, $p_sroa_0_0__idx75 = 0, $p_sroa_0_0_copyload76 = 0.0, $p_sroa_1_8__idx101 = 0, $p_sroa_1_8_copyload102 = 0.0, $add151 = 0, $q_sroa_0_0__idx29 = 0, $q_sroa_0_0_copyload30 = 0.0, $q_sroa_1_8__idx51 = 0, $q_sroa_1_8_copyload52 = 0.0, $sub155 = 0.0, $mul159 = 0.0, $sub162 = 0.0, $mul166 = 0.0, $add167 = 0.0, $call168 = 0.0, $mul169 = 0.0, $cmp170 = 0, $tlen_1 = 0.0, $cmp175 = 0, $cmp181 = 0, $add184 = 0.0, $sub188 = 0.0, $cmp196 = 0, $add199 = 0.0, $sub203 = 0.0, $r_sroa_1_1 = 0.0, $r_sroa_0_1 = 0.0, $add208 = 0, $arrayidx209 = 0, $r_sroa_0_0__idx = 0, $r_sroa_1_8__idx24 = 0, $6 = 0, $7 = 0, $add210 = 0, $q_sroa_0_0__idx = 0, $q_sroa_1_8__idx47 = 0, $sflag212 = 0, $p_sroa_0_0__idx = 0, $p_sroa_1_8__idx95 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($sflag | 0) != 0;
+ $tobool1 = ($eflag | 0) == 0;
+ $tobool1_not = $tobool1 ^ 1;
+ $or_cond_not = $tobool & $tobool1_not;
+ $cmp = ($endp | 0) == ($startp | 0);
+ $or_cond174 = $or_cond_not & $cmp;
+ if ($or_cond174) {
+ label = 3;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 3:
+ $arrayidx = $ps + ($endp << 4) | 0;
+ $p_sroa_0_0__idx93 = $arrayidx | 0;
+ $p_sroa_0_0_copyload94 = +HEAPF64[$p_sroa_0_0__idx93 >> 3];
+ $p_sroa_1_8__idx121 = $ps + ($endp << 4) + 8 | 0;
+ $p_sroa_1_8_copyload122 = +HEAPF64[$p_sroa_1_8__idx121 >> 3];
+ $add = $endp + 3 | 0;
+ $arrayidx3 = $ps + ($add << 4) | 0;
+ $q_sroa_0_0__idx45 = $arrayidx3 | 0;
+ $q_sroa_0_0_copyload46 = +HEAPF64[$q_sroa_0_0__idx45 >> 3];
+ $q_sroa_1_8__idx69 = $ps + ($add << 4) + 8 | 0;
+ $q_sroa_1_8_copyload70 = +HEAPF64[$q_sroa_1_8__idx69 >> 3];
+ $call = +_arrow_length($e, $sflag);
+ $call4 = +_arrow_length($e, $eflag);
+ $sub = $p_sroa_0_0_copyload94 - $q_sroa_0_0_copyload46;
+ $mul = $sub * $sub;
+ $sub10 = $p_sroa_1_8_copyload122 - $q_sroa_1_8_copyload70;
+ $mul14 = $sub10 * $sub10;
+ $add15 = $mul + $mul14;
+ $call16 = +Math_sqrt(+$add15);
+ $add17 = $call + $call4;
+ $cmp18 = $add17 < $call16;
+ if ($cmp18) {
+ $hlen_0 = $call4;
+ $tlen_0 = $call;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $div = $call16 / 3.0;
+ $hlen_0 = $div;
+ $tlen_0 = $div;
+ label = 5;
+ break;
+ case 5:
+ $cmp22 = $p_sroa_1_8_copyload122 == $q_sroa_1_8_copyload70;
+ if ($cmp22) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 6:
+ $cmp29 = $p_sroa_0_0_copyload94 < $q_sroa_0_0_copyload46;
+ if ($cmp29) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $sub32 = $q_sroa_0_0_copyload46 - $hlen_0;
+ $add35 = $p_sroa_0_0_copyload94 + $tlen_0;
+ $t_sroa_0_0 = $sub32;
+ $t_sroa_1_0 = $p_sroa_1_8_copyload122;
+ $s_sroa_0_0 = $add35;
+ $s_sroa_1_0 = $p_sroa_1_8_copyload122;
+ label = 12;
+ break;
+ case 8:
+ $add38 = $q_sroa_0_0_copyload46 + $hlen_0;
+ $sub41 = $p_sroa_0_0_copyload94 - $tlen_0;
+ $t_sroa_0_0 = $add38;
+ $t_sroa_1_0 = $p_sroa_1_8_copyload122;
+ $s_sroa_0_0 = $sub41;
+ $s_sroa_1_0 = $p_sroa_1_8_copyload122;
+ label = 12;
+ break;
+ case 9:
+ $cmp50 = $p_sroa_1_8_copyload122 < $q_sroa_1_8_copyload70;
+ if ($cmp50) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $sub53 = $q_sroa_1_8_copyload70 - $hlen_0;
+ $add56 = $p_sroa_1_8_copyload122 + $tlen_0;
+ $t_sroa_0_0 = $p_sroa_0_0_copyload94;
+ $t_sroa_1_0 = $sub53;
+ $s_sroa_0_0 = $p_sroa_0_0_copyload94;
+ $s_sroa_1_0 = $add56;
+ label = 12;
+ break;
+ case 11:
+ $add60 = $q_sroa_1_8_copyload70 + $hlen_0;
+ $sub63 = $p_sroa_1_8_copyload122 - $tlen_0;
+ $t_sroa_0_0 = $p_sroa_0_0_copyload94;
+ $t_sroa_1_0 = $add60;
+ $s_sroa_0_0 = $p_sroa_0_0_copyload94;
+ $s_sroa_1_0 = $sub63;
+ label = 12;
+ break;
+ case 12:
+ $add68 = $endp + 1 | 0;
+ $arrayidx69 = $ps + ($add68 << 4) | 0;
+ $s_sroa_0_0__idx = $arrayidx69 | 0;
+ HEAPF64[$s_sroa_0_0__idx >> 3] = $s_sroa_0_0;
+ $s_sroa_1_8__idx21 = $ps + ($add68 << 4) + 8 | 0;
+ HEAPF64[$s_sroa_1_8__idx21 >> 3] = $s_sroa_1_0;
+ $0 = $arrayidx;
+ $1 = $arrayidx69;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $add70 = $endp + 2 | 0;
+ $arrayidx71 = $ps + ($add70 << 4) | 0;
+ HEAPF64[$q_sroa_0_0__idx45 >> 3] = $t_sroa_0_0;
+ HEAPF64[$q_sroa_1_8__idx69 >> 3] = $t_sroa_1_0;
+ $2 = $arrayidx71;
+ $3 = $arrayidx3;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $eflag74 = $spl + 12 | 0;
+ HEAP32[$eflag74 >> 2] = $eflag;
+ $p_sroa_0_0__idx85 = $spl + 32 | 0;
+ $p_sroa_1_8__idx112 = $spl + 40 | 0;
+ $sflag75 = $spl + 8 | 0;
+ HEAP32[$sflag75 >> 2] = $sflag;
+ HEAPF64[$p_sroa_0_0__idx85 >> 3] = $q_sroa_0_0_copyload46;
+ HEAPF64[$p_sroa_1_8__idx112 >> 3] = $q_sroa_1_8_copyload70;
+ label = 31;
+ break;
+ case 13:
+ if ($tobool1) {
+ $hlen_2 = 0.0;
+ label = 22;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $call80 = +_arrow_length($e, $eflag);
+ $p_sroa_0_0__idx83 = $ps + ($endp << 4) | 0;
+ $p_sroa_0_0_copyload84 = +HEAPF64[$p_sroa_0_0__idx83 >> 3];
+ $p_sroa_1_8__idx110 = $ps + ($endp << 4) + 8 | 0;
+ $p_sroa_1_8_copyload111 = +HEAPF64[$p_sroa_1_8__idx110 >> 3];
+ $add82 = $endp + 3 | 0;
+ $arrayidx83 = $ps + ($add82 << 4) | 0;
+ $q_sroa_0_0__idx37 = $arrayidx83 | 0;
+ $q_sroa_0_0_copyload38 = +HEAPF64[$q_sroa_0_0__idx37 >> 3];
+ $q_sroa_1_8__idx60 = $ps + ($add82 << 4) + 8 | 0;
+ $q_sroa_1_8_copyload61 = +HEAPF64[$q_sroa_1_8__idx60 >> 3];
+ $sub86 = $p_sroa_0_0_copyload84 - $q_sroa_0_0_copyload38;
+ $mul90 = $sub86 * $sub86;
+ $sub93 = $p_sroa_1_8_copyload111 - $q_sroa_1_8_copyload61;
+ $mul97 = $sub93 * $sub93;
+ $add98 = $mul90 + $mul97;
+ $call99 = +Math_sqrt(+$add98);
+ $mul100 = $call99 * .9;
+ $cmp101 = $call80 < $mul100;
+ $hlen_1 = $cmp101 ? $call80 : $mul100;
+ $cmp106 = $p_sroa_1_8_copyload111 == $q_sroa_1_8_copyload61;
+ if ($cmp106) {
+ label = 15;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 15:
+ $cmp112 = $p_sroa_0_0_copyload84 < $q_sroa_0_0_copyload38;
+ if ($cmp112) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $sub115 = $q_sroa_0_0_copyload38 - $hlen_1;
+ $r_sroa_0_0 = $sub115;
+ $r_sroa_1_0 = $p_sroa_1_8_copyload111;
+ label = 21;
+ break;
+ case 17:
+ $add119 = $q_sroa_0_0_copyload38 + $hlen_1;
+ $r_sroa_0_0 = $add119;
+ $r_sroa_1_0 = $p_sroa_1_8_copyload111;
+ label = 21;
+ break;
+ case 18:
+ $cmp127 = $p_sroa_1_8_copyload111 < $q_sroa_1_8_copyload61;
+ if ($cmp127) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $sub130 = $q_sroa_1_8_copyload61 - $hlen_1;
+ $r_sroa_0_0 = $p_sroa_0_0_copyload84;
+ $r_sroa_1_0 = $sub130;
+ label = 21;
+ break;
+ case 20:
+ $add134 = $q_sroa_1_8_copyload61 + $hlen_1;
+ $r_sroa_0_0 = $p_sroa_0_0_copyload84;
+ $r_sroa_1_0 = $add134;
+ label = 21;
+ break;
+ case 21:
+ $add138 = $endp + 1 | 0;
+ $p_sroa_0_0__idx77 = $ps + ($add138 << 4) | 0;
+ HEAPF64[$p_sroa_0_0__idx77 >> 3] = $p_sroa_0_0_copyload84;
+ $p_sroa_1_8__idx103 = $ps + ($add138 << 4) + 8 | 0;
+ HEAPF64[$p_sroa_1_8__idx103 >> 3] = $p_sroa_1_8_copyload111;
+ $add140 = $endp + 2 | 0;
+ $arrayidx141 = $ps + ($add140 << 4) | 0;
+ HEAPF64[$q_sroa_0_0__idx37 >> 3] = $r_sroa_0_0;
+ HEAPF64[$q_sroa_1_8__idx60 >> 3] = $r_sroa_1_0;
+ $4 = $arrayidx141;
+ $5 = $arrayidx83;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $eflag144 = $spl + 12 | 0;
+ HEAP32[$eflag144 >> 2] = $eflag;
+ $q_sroa_0_0__idx31 = $spl + 32 | 0;
+ HEAPF64[$q_sroa_0_0__idx31 >> 3] = $q_sroa_0_0_copyload38;
+ $q_sroa_1_8__idx53 = $spl + 40 | 0;
+ HEAPF64[$q_sroa_1_8__idx53 >> 3] = $q_sroa_1_8_copyload61;
+ $hlen_2 = $hlen_1;
+ label = 22;
+ break;
+ case 22:
+ if ($tobool) {
+ label = 23;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 23:
+ $call149 = +_arrow_length($e, $sflag);
+ $arrayidx150 = $ps + ($startp << 4) | 0;
+ $p_sroa_0_0__idx75 = $arrayidx150 | 0;
+ $p_sroa_0_0_copyload76 = +HEAPF64[$p_sroa_0_0__idx75 >> 3];
+ $p_sroa_1_8__idx101 = $ps + ($startp << 4) + 8 | 0;
+ $p_sroa_1_8_copyload102 = +HEAPF64[$p_sroa_1_8__idx101 >> 3];
+ $add151 = $startp + 3 | 0;
+ $q_sroa_0_0__idx29 = $ps + ($add151 << 4) | 0;
+ $q_sroa_0_0_copyload30 = +HEAPF64[$q_sroa_0_0__idx29 >> 3];
+ $q_sroa_1_8__idx51 = $ps + ($add151 << 4) + 8 | 0;
+ $q_sroa_1_8_copyload52 = +HEAPF64[$q_sroa_1_8__idx51 >> 3];
+ $sub155 = $p_sroa_0_0_copyload76 - $q_sroa_0_0_copyload30;
+ $mul159 = $sub155 * $sub155;
+ $sub162 = $p_sroa_1_8_copyload102 - $q_sroa_1_8_copyload52;
+ $mul166 = $sub162 * $sub162;
+ $add167 = $mul159 + $mul166;
+ $call168 = +Math_sqrt(+$add167);
+ $mul169 = $call168 * .9;
+ $cmp170 = $call149 < $mul169;
+ $tlen_1 = $cmp170 ? $call149 : $mul169;
+ $cmp175 = $p_sroa_1_8_copyload102 == $q_sroa_1_8_copyload52;
+ if ($cmp175) {
+ label = 24;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 24:
+ $cmp181 = $p_sroa_0_0_copyload76 < $q_sroa_0_0_copyload30;
+ if ($cmp181) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $add184 = $p_sroa_0_0_copyload76 + $tlen_1;
+ $r_sroa_0_1 = $add184;
+ $r_sroa_1_1 = $p_sroa_1_8_copyload102;
+ label = 30;
+ break;
+ case 26:
+ $sub188 = $p_sroa_0_0_copyload76 - $hlen_2;
+ $r_sroa_0_1 = $sub188;
+ $r_sroa_1_1 = $p_sroa_1_8_copyload102;
+ label = 30;
+ break;
+ case 27:
+ $cmp196 = $p_sroa_1_8_copyload102 < $q_sroa_1_8_copyload52;
+ if ($cmp196) {
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ $add199 = $hlen_2 + $p_sroa_1_8_copyload102;
+ $r_sroa_0_1 = $p_sroa_0_0_copyload76;
+ $r_sroa_1_1 = $add199;
+ label = 30;
+ break;
+ case 29:
+ $sub203 = $p_sroa_1_8_copyload102 - $hlen_2;
+ $r_sroa_0_1 = $p_sroa_0_0_copyload76;
+ $r_sroa_1_1 = $sub203;
+ label = 30;
+ break;
+ case 30:
+ $add208 = $startp + 1 | 0;
+ $arrayidx209 = $ps + ($add208 << 4) | 0;
+ $r_sroa_0_0__idx = $arrayidx209 | 0;
+ HEAPF64[$r_sroa_0_0__idx >> 3] = $r_sroa_0_1;
+ $r_sroa_1_8__idx24 = $ps + ($add208 << 4) + 8 | 0;
+ HEAPF64[$r_sroa_1_8__idx24 >> 3] = $r_sroa_1_1;
+ $6 = $arrayidx150;
+ $7 = $arrayidx209;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $add210 = $startp + 2 | 0;
+ $q_sroa_0_0__idx = $ps + ($add210 << 4) | 0;
+ HEAPF64[$q_sroa_0_0__idx >> 3] = $q_sroa_0_0_copyload30;
+ $q_sroa_1_8__idx47 = $ps + ($add210 << 4) + 8 | 0;
+ HEAPF64[$q_sroa_1_8__idx47 >> 3] = $q_sroa_1_8_copyload52;
+ $sflag212 = $spl + 8 | 0;
+ HEAP32[$sflag212 >> 2] = $sflag;
+ $p_sroa_0_0__idx = $spl + 16 | 0;
+ HEAPF64[$p_sroa_0_0__idx >> 3] = $p_sroa_0_0_copyload76;
+ $p_sroa_1_8__idx95 = $spl + 24 | 0;
+ HEAPF64[$p_sroa_1_8__idx95 >> 3] = $p_sroa_1_8_copyload102;
+ label = 31;
+ break;
+ case 31:
+ return;
+ }
+}
+function _arrow_bb($agg_result, $p, $u, $arrowsize, $flag) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $flag = $flag | 0;
+ var $x = 0, $x1 = 0, $y = 0, $y2 = 0, $sub3 = 0.0, $4 = 0.0, $div = 0.0, $5 = 0.0, $mul22 = 0.0, $8 = 0.0, $div24 = 0.0, $div26 = 0.0, $9 = 0.0, $sub28 = 0.0, $10 = 0.0, $sub30 = 0.0, $add32 = 0.0, $add34 = 0.0, $add36 = 0.0, $add38 = 0.0, $add40 = 0.0, $add42 = 0.0, $cond44 = 0.0, $add32_cond44 = 0.0, $cond80 = 0.0, $add34_cond80 = 0.0, $cond117 = 0.0, $add32_cond117 = 0.0, $cond153 = 0.0, $add34_cond153 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $x = $p | 0;
+ $x1 = $u | 0;
+ HEAPF64[$x1 >> 3] = +HEAPF64[$x1 >> 3] - +HEAPF64[$x >> 3];
+ $y = $p + 8 | 0;
+ $y2 = $u + 8 | 0;
+ $sub3 = +HEAPF64[$y2 >> 3] - +HEAPF64[$y >> 3];
+ HEAPF64[$y2 >> 3] = $sub3;
+ $4 = +HEAPF64[$x1 >> 3];
+ $div = $arrowsize * 10.0 / (+Math_sqrt(+($4 * $4 + $sub3 * $sub3)) + 1.0e-4);
+ HEAPF64[$x1 >> 3] = $4 + ($4 >= 0.0 ? 1.0e-4 : -1.0e-4);
+ $5 = +HEAPF64[$y2 >> 3];
+ HEAPF64[$y2 >> 3] = $5 + ($5 >= 0.0 ? 1.0e-4 : -1.0e-4);
+ HEAPF64[$x1 >> 3] = $div * +HEAPF64[$x1 >> 3];
+ $mul22 = $div * +HEAPF64[$y2 >> 3];
+ HEAPF64[$y2 >> 3] = $mul22;
+ $8 = +HEAPF64[$x1 >> 3];
+ $div24 = $8 * .5;
+ $div26 = $mul22 * .5;
+ $9 = +HEAPF64[$x >> 3];
+ $sub28 = $9 - $div26;
+ $10 = +HEAPF64[$y >> 3];
+ $sub30 = $10 - $div24;
+ $add32 = $9 + $div26;
+ $add34 = $div24 + $10;
+ $add36 = $8 + $sub28;
+ $add38 = $mul22 + $sub30;
+ $add40 = $8 + $add32;
+ $add42 = $mul22 + $add34;
+ $cond44 = $add36 > $add40 ? $add36 : $add40;
+ $add32_cond44 = $add32 > $cond44 ? $add32 : $cond44;
+ $cond80 = $add38 > $add42 ? $add38 : $add42;
+ $add34_cond80 = $add34 > $cond80 ? $add34 : $cond80;
+ $cond117 = $add36 < $add40 ? $add36 : $add40;
+ $add32_cond117 = $add32 < $cond117 ? $add32 : $cond117;
+ $cond153 = $add38 < $add42 ? $add38 : $add42;
+ $add34_cond153 = $add34 < $cond153 ? $add34 : $cond153;
+ HEAPF64[$agg_result >> 3] = $sub28 < $add32_cond117 ? $sub28 : $add32_cond117;
+ HEAPF64[$agg_result + 8 >> 3] = $sub30 < $add34_cond153 ? $sub30 : $add34_cond153;
+ HEAPF64[$agg_result + 16 >> 3] = $sub28 > $add32_cond44 ? $sub28 : $add32_cond44;
+ HEAPF64[$agg_result + 24 >> 3] = $sub30 > $add34_cond80 ? $sub30 : $add34_cond80;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _arrow_gen($job, $emit_state, $p, $u, $arrowsize, $penwidth, $flag) {
+ $job = $job | 0;
+ $emit_state = $emit_state | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ $flag = $flag | 0;
+ var $tmp = 0, $obj1 = 0, $0 = 0, $emit_state2 = 0, $1 = 0, $gvc = 0, $2 = 0, $defaultlinestyle = 0, $3 = 0, $x = 0, $4 = 0.0, $x4 = 0, $5 = 0.0, $sub = 0.0, $y = 0, $6 = 0.0, $y5 = 0, $7 = 0.0, $sub6 = 0.0, $8 = 0.0, $mul = 0.0, $mul11 = 0.0, $add = 0.0, $call = 0.0, $add12 = 0.0, $div = 0.0, $cmp = 0, $cond = 0.0, $add15 = 0.0, $9 = 0.0, $cmp17 = 0, $cond18 = 0.0, $add20 = 0.0, $10 = 0.0, $mul22 = 0.0, $11 = 0.0, $mul24 = 0.0, $12 = 0, $13 = 0, $i_010 = 0, $mul26 = 0, $shr = 0, $and = 0, $cmp27 = 0, $inc = 0, $cmp25 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $emit_state2 = $0 + 12 | 0;
+ $1 = HEAP32[$emit_state2 >> 2] | 0;
+ HEAP32[$emit_state2 >> 2] = $emit_state;
+ $gvc = $job | 0;
+ $2 = HEAP32[$gvc >> 2] | 0;
+ $defaultlinestyle = $2 + 304 | 0;
+ $3 = HEAP32[$defaultlinestyle >> 2] | 0;
+ _gvrender_set_style($job, $3);
+ $x = $p | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $x4 = $u | 0;
+ $5 = +HEAPF64[$x4 >> 3];
+ $sub = $5 - $4;
+ HEAPF64[$x4 >> 3] = $sub;
+ $y = $p + 8 | 0;
+ $6 = +HEAPF64[$y >> 3];
+ $y5 = $u + 8 | 0;
+ $7 = +HEAPF64[$y5 >> 3];
+ $sub6 = $7 - $6;
+ HEAPF64[$y5 >> 3] = $sub6;
+ $8 = +HEAPF64[$x4 >> 3];
+ $mul = $8 * $8;
+ $mul11 = $sub6 * $sub6;
+ $add = $mul + $mul11;
+ $call = +Math_sqrt(+$add);
+ $add12 = $call + 1.0e-4;
+ $div = 10.0 / $add12;
+ $cmp = $8 >= 0.0;
+ $cond = $cmp ? 1.0e-4 : -1.0e-4;
+ $add15 = $8 + $cond;
+ HEAPF64[$x4 >> 3] = $add15;
+ $9 = +HEAPF64[$y5 >> 3];
+ $cmp17 = $9 >= 0.0;
+ $cond18 = $cmp17 ? 1.0e-4 : -1.0e-4;
+ $add20 = $9 + $cond18;
+ HEAPF64[$y5 >> 3] = $add20;
+ $10 = +HEAPF64[$x4 >> 3];
+ $mul22 = $div * $10;
+ HEAPF64[$x4 >> 3] = $mul22;
+ $11 = +HEAPF64[$y5 >> 3];
+ $mul24 = $div * $11;
+ HEAPF64[$y5 >> 3] = $mul24;
+ $12 = $p;
+ $13 = $tmp;
+ $i_010 = 0;
+ label = 3;
+ break;
+ case 3:
+ $mul26 = $i_010 << 3;
+ $shr = $flag >> $mul26;
+ $and = $shr & 255;
+ $cmp27 = ($and | 0) == 0;
+ if ($cmp27) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _arrow_gen_type($tmp, $job, $p, $u, $arrowsize, $penwidth, $and);
+ HEAP32[$12 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ $inc = $i_010 + 1 | 0;
+ $cmp25 = ($inc | 0) < 4;
+ if ($cmp25) {
+ $i_010 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[$emit_state2 >> 2] = $1;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_gen_type($agg_result, $job, $p, $u, $arrowsize, $penwidth, $flag) {
+ $agg_result = $agg_result | 0;
+ $job = $job | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ $flag = $flag | 0;
+ var $and = 0, $arrowtype_0 = 0, $type = 0, $0 = 0, $tobool = 0, $cmp = 0, $incdec_ptr = 0, $lenfact = 0, $1 = 0.0, $mul = 0.0, $x = 0, $2 = 0.0, $mul2 = 0.0, $3 = 0.0, $mul4 = 0.0, $y = 0, $4 = 0.0, $mul5 = 0.0, $gen = 0, $5 = 0, $x6 = 0, $6 = 0.0, $7 = 0.0, $add = 0.0, $y9 = 0, $8 = 0.0, $9 = 0.0, $add11 = 0.0, $10 = 0, $11 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $and = $flag & 7;
+ $arrowtype_0 = 168136;
+ label = 3;
+ break;
+ case 3:
+ $type = $arrowtype_0 | 0;
+ $0 = HEAP32[$type >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $cmp = ($and | 0) == ($0 | 0);
+ $incdec_ptr = $arrowtype_0 + 24 | 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $arrowtype_0 = $incdec_ptr;
+ label = 3;
+ break;
+ }
+ case 5:
+ $lenfact = $arrowtype_0 + 8 | 0;
+ $1 = +HEAPF64[$lenfact >> 3];
+ $mul = $1 * $arrowsize;
+ $x = $u | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $mul2 = $2 * $mul;
+ HEAPF64[$x >> 3] = $mul2;
+ $3 = +HEAPF64[$lenfact >> 3];
+ $mul4 = $3 * $arrowsize;
+ $y = $u + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $mul5 = $4 * $mul4;
+ HEAPF64[$y >> 3] = $mul5;
+ $gen = $arrowtype_0 + 16 | 0;
+ $5 = HEAP32[$gen >> 2] | 0;
+ FUNCTION_TABLE_viiiffi[$5 & 1023]($job, $p, $u, $arrowsize, $penwidth, $flag);
+ $x6 = $p | 0;
+ $6 = +HEAPF64[$x6 >> 3];
+ $7 = +HEAPF64[$x >> 3];
+ $add = $6 + $7;
+ HEAPF64[$x6 >> 3] = $add;
+ $y9 = $p + 8 | 0;
+ $8 = +HEAPF64[$y9 >> 3];
+ $9 = +HEAPF64[$y >> 3];
+ $add11 = $8 + $9;
+ HEAPF64[$y9 >> 3] = $add11;
+ label = 6;
+ break;
+ case 6:
+ $10 = $agg_result;
+ $11 = $p;
+ HEAP32[$10 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_type_normal($job, $p, $u, $arrowsize, $penwidth, $flag) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ $flag = $flag | 0;
+ var $a = 0, $cmp = 0, $div = 0.0, $mul = 0.0, $arrowwidth_0 = 0.0, $y = 0, $0 = 0.0, $sub = 0.0, $mul1 = 0.0, $x2 = 0, $1 = 0.0, $mul3 = 0.0, $x5 = 0, $2 = 0.0, $add = 0.0, $y8 = 0, $3 = 0.0, $add10 = 0.0, $and = 0, $tobool = 0, $arrayidx = 0, $arrayidx13 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0.0, $sub16 = 0.0, $x18 = 0, $8 = 0.0, $sub21 = 0.0, $y23 = 0, $q_sroa_0_0__idx10 = 0, $q_sroa_1_8__idx14 = 0, $9 = 0.0, $add27 = 0.0, $x29 = 0, $10 = 0.0, $add32 = 0.0, $y34 = 0, $q_sroa_0_0__idx = 0, $q_sroa_1_8__idx13 = 0, $11 = 0, $sub39 = 0.0, $x41 = 0, $sub44 = 0.0, $y46 = 0, $arrayidx47 = 0, $12 = 0, $13 = 0, $add50 = 0.0, $x52 = 0, $add55 = 0.0, $y57 = 0, $and59 = 0, $tobool60 = 0, $and62 = 0, $and62_lobit = 0, $14 = 0, $conv = 0, $and65 = 0, $tobool66 = 0, $arrayidx68 = 0, $and69 = 0, $and69_lobit = 0, $15 = 0, $conv73 = 0, $arrayidx75 = 0, $and76 = 0, $and76_lobit = 0, $16 = 0, $conv80 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 80 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $a = __stackBase__ | 0;
+ $cmp = $penwidth > 4.0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $arrowwidth_0 = .35;
+ label = 4;
+ break;
+ }
+ case 3:
+ $div = $penwidth * .25;
+ $mul = $div * .35;
+ $arrowwidth_0 = $mul;
+ label = 4;
+ break;
+ case 4:
+ $y = $u + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $sub = -0.0 - $0;
+ $mul1 = $arrowwidth_0 * $sub;
+ $x2 = $u | 0;
+ $1 = +HEAPF64[$x2 >> 3];
+ $mul3 = $arrowwidth_0 * $1;
+ $x5 = $p | 0;
+ $2 = +HEAPF64[$x5 >> 3];
+ $add = $1 + $2;
+ $y8 = $p + 8 | 0;
+ $3 = +HEAPF64[$y8 >> 3];
+ $add10 = $0 + $3;
+ $and = $flag & 16;
+ $tobool = ($and | 0) == 0;
+ $arrayidx = $a | 0;
+ $arrayidx13 = $a + 64 | 0;
+ $4 = $arrayidx13;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = $p;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $6 = $a;
+ HEAP32[$6 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $7 = +HEAPF64[$x5 >> 3];
+ $sub16 = $7 - $mul1;
+ $x18 = $a + 16 | 0;
+ HEAPF64[$x18 >> 3] = $sub16;
+ $8 = +HEAPF64[$y8 >> 3];
+ $sub21 = $8 - $mul3;
+ $y23 = $a + 24 | 0;
+ HEAPF64[$y23 >> 3] = $sub21;
+ $q_sroa_0_0__idx10 = $a + 32 | 0;
+ HEAPF64[$q_sroa_0_0__idx10 >> 3] = $add;
+ $q_sroa_1_8__idx14 = $a + 40 | 0;
+ HEAPF64[$q_sroa_1_8__idx14 >> 3] = $add10;
+ $9 = +HEAPF64[$x5 >> 3];
+ $add27 = $mul1 + $9;
+ $x29 = $a + 48 | 0;
+ HEAPF64[$x29 >> 3] = $add27;
+ $10 = +HEAPF64[$y8 >> 3];
+ $add32 = $mul3 + $10;
+ $y34 = $a + 56 | 0;
+ HEAPF64[$y34 >> 3] = $add32;
+ label = 7;
+ break;
+ case 6:
+ $q_sroa_0_0__idx = $a + 64 | 0;
+ HEAPF64[$q_sroa_0_0__idx >> 3] = $add;
+ $q_sroa_1_8__idx13 = $a + 72 | 0;
+ HEAPF64[$q_sroa_1_8__idx13 >> 3] = $add10;
+ $11 = $a;
+ HEAP32[$11 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $sub39 = $add - $mul1;
+ $x41 = $a + 16 | 0;
+ HEAPF64[$x41 >> 3] = $sub39;
+ $sub44 = $add10 - $mul3;
+ $y46 = $a + 24 | 0;
+ HEAPF64[$y46 >> 3] = $sub44;
+ $arrayidx47 = $a + 32 | 0;
+ $12 = $arrayidx47;
+ $13 = $p;
+ HEAP32[$12 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ $add50 = $mul1 + $add;
+ $x52 = $a + 48 | 0;
+ HEAPF64[$x52 >> 3] = $add50;
+ $add55 = $mul3 + $add10;
+ $y57 = $a + 56 | 0;
+ HEAPF64[$y57 >> 3] = $add55;
+ label = 7;
+ break;
+ case 7:
+ $and59 = $flag & 32;
+ $tobool60 = ($and59 | 0) == 0;
+ if ($tobool60) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $and62 = $flag >>> 3;
+ $and62_lobit = $and62 & 1;
+ $14 = $and62_lobit ^ 1;
+ $conv = $14 & 255;
+ _gvrender_polygon($job, $arrayidx, 3, $conv);
+ label = 12;
+ break;
+ case 9:
+ $and65 = $flag & 64;
+ $tobool66 = ($and65 | 0) == 0;
+ if ($tobool66) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $arrayidx68 = $a + 32 | 0;
+ $and69 = $flag >>> 3;
+ $and69_lobit = $and69 & 1;
+ $15 = $and69_lobit ^ 1;
+ $conv73 = $15 & 255;
+ _gvrender_polygon($job, $arrayidx68, 3, $conv73);
+ label = 12;
+ break;
+ case 11:
+ $arrayidx75 = $a + 16 | 0;
+ $and76 = $flag >>> 3;
+ $and76_lobit = $and76 & 1;
+ $16 = $and76_lobit ^ 1;
+ $conv80 = $16 & 255;
+ _gvrender_polygon($job, $arrayidx75, 3, $conv80);
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_type_crow($job, $p, $u, $arrowsize, $penwidth, $flag) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ $flag = $flag | 0;
+ var $a = 0, $mul = 0.0, $cmp = 0, $and = 0, $tobool = 0, $div = 0.0, $mul2 = 0.0, $arrowwidth_0 = 0.0, $cmp3 = 0, $and5 = 0, $tobool6 = 0, $sub = 0.0, $mul8 = 0.0, $div9 = 0.0, $shaftwidth_0 = 0.0, $y = 0, $0 = 0.0, $sub11 = 0.0, $mul12 = 0.0, $x13 = 0, $1 = 0.0, $mul14 = 0.0, $mul18 = 0.0, $mul21 = 0.0, $x23 = 0, $2 = 0.0, $add = 0.0, $y26 = 0, $3 = 0.0, $add28 = 0.0, $mul32 = 0.0, $add33 = 0.0, $mul37 = 0.0, $add38 = 0.0, $and40 = 0, $tobool41 = 0, $arrayidx = 0, $arrayidx43 = 0, $4 = 0, $5 = 0, $6 = 0, $sub46 = 0.0, $x48 = 0, $sub51 = 0.0, $y53 = 0, $sub56 = 0.0, $x58 = 0, $sub61 = 0.0, $y63 = 0, $sub66 = 0.0, $x68 = 0, $sub71 = 0.0, $y73 = 0, $q_sroa_0_0__idx21 = 0, $q_sroa_1_8__idx27 = 0, $add77 = 0.0, $x79 = 0, $add82 = 0.0, $y84 = 0, $add87 = 0.0, $x89 = 0, $add92 = 0.0, $y94 = 0, $add97 = 0.0, $x99 = 0, $add102 = 0.0, $y104 = 0, $q_sroa_0_0__idx = 0, $q_sroa_1_8__idx25 = 0, $7 = 0, $8 = 0.0, $sub109 = 0.0, $x111 = 0, $9 = 0.0, $sub114 = 0.0, $y116 = 0, $sub119 = 0.0, $x121 = 0, $sub124 = 0.0, $y126 = 0, $10 = 0.0, $x129 = 0, $11 = 0.0, $y132 = 0, $arrayidx133 = 0, $12 = 0, $13 = 0, $14 = 0.0, $x136 = 0, $15 = 0.0, $y139 = 0, $add142 = 0.0, $x144 = 0, $add147 = 0.0, $y149 = 0, $16 = 0.0, $add152 = 0.0, $x154 = 0, $17 = 0.0, $add157 = 0.0, $y159 = 0, $and161 = 0, $tobool162 = 0, $and165 = 0, $tobool166 = 0, $arrayidx168 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $a = __stackBase__ | 0;
+ $mul = $arrowsize * 4.0;
+ $cmp = $mul < $penwidth;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $arrowwidth_0 = .45;
+ label = 5;
+ break;
+ }
+ case 3:
+ $and = $flag & 16;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ $arrowwidth_0 = .45;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $div = $penwidth / $mul;
+ $mul2 = $div * .45;
+ $arrowwidth_0 = $mul2;
+ label = 5;
+ break;
+ case 5:
+ $cmp3 = $penwidth > 1.0;
+ if ($cmp3) {
+ label = 6;
+ break;
+ } else {
+ $shaftwidth_0 = 0.0;
+ label = 8;
+ break;
+ }
+ case 6:
+ $and5 = $flag & 16;
+ $tobool6 = ($and5 | 0) == 0;
+ if ($tobool6) {
+ $shaftwidth_0 = 0.0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub = $penwidth + -1.0;
+ $mul8 = $sub * .05;
+ $div9 = $mul8 / $arrowsize;
+ $shaftwidth_0 = $div9;
+ label = 8;
+ break;
+ case 8:
+ $y = $u + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $sub11 = -0.0 - $0;
+ $mul12 = $arrowwidth_0 * $sub11;
+ $x13 = $u | 0;
+ $1 = +HEAPF64[$x13 >> 3];
+ $mul14 = $arrowwidth_0 * $1;
+ $mul18 = $shaftwidth_0 * $sub11;
+ $mul21 = $shaftwidth_0 * $1;
+ $x23 = $p | 0;
+ $2 = +HEAPF64[$x23 >> 3];
+ $add = $1 + $2;
+ $y26 = $p + 8 | 0;
+ $3 = +HEAPF64[$y26 >> 3];
+ $add28 = $0 + $3;
+ $mul32 = $1 * .5;
+ $add33 = $2 + $mul32;
+ $mul37 = $0 * .5;
+ $add38 = $mul37 + $3;
+ $and40 = $flag & 16;
+ $tobool41 = ($and40 | 0) == 0;
+ $arrayidx = $a | 0;
+ $arrayidx43 = $a + 128 | 0;
+ $4 = $arrayidx43;
+ if ($tobool41) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $5 = $p;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $6 = $a;
+ HEAP32[$6 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $sub46 = $add - $mul12;
+ $x48 = $a + 16 | 0;
+ HEAPF64[$x48 >> 3] = $sub46;
+ $sub51 = $add28 - $mul14;
+ $y53 = $a + 24 | 0;
+ HEAPF64[$y53 >> 3] = $sub51;
+ $sub56 = $add33 - $mul18;
+ $x58 = $a + 32 | 0;
+ HEAPF64[$x58 >> 3] = $sub56;
+ $sub61 = $add38 - $mul21;
+ $y63 = $a + 40 | 0;
+ HEAPF64[$y63 >> 3] = $sub61;
+ $sub66 = $add - $mul18;
+ $x68 = $a + 48 | 0;
+ HEAPF64[$x68 >> 3] = $sub66;
+ $sub71 = $add28 - $mul21;
+ $y73 = $a + 56 | 0;
+ HEAPF64[$y73 >> 3] = $sub71;
+ $q_sroa_0_0__idx21 = $a + 64 | 0;
+ HEAPF64[$q_sroa_0_0__idx21 >> 3] = $add;
+ $q_sroa_1_8__idx27 = $a + 72 | 0;
+ HEAPF64[$q_sroa_1_8__idx27 >> 3] = $add28;
+ $add77 = $mul18 + $add;
+ $x79 = $a + 80 | 0;
+ HEAPF64[$x79 >> 3] = $add77;
+ $add82 = $mul21 + $add28;
+ $y84 = $a + 88 | 0;
+ HEAPF64[$y84 >> 3] = $add82;
+ $add87 = $mul18 + $add33;
+ $x89 = $a + 96 | 0;
+ HEAPF64[$x89 >> 3] = $add87;
+ $add92 = $mul21 + $add38;
+ $y94 = $a + 104 | 0;
+ HEAPF64[$y94 >> 3] = $add92;
+ $add97 = $mul12 + $add;
+ $x99 = $a + 112 | 0;
+ HEAPF64[$x99 >> 3] = $add97;
+ $add102 = $mul14 + $add28;
+ $y104 = $a + 120 | 0;
+ HEAPF64[$y104 >> 3] = $add102;
+ label = 11;
+ break;
+ case 10:
+ $q_sroa_0_0__idx = $a + 128 | 0;
+ HEAPF64[$q_sroa_0_0__idx >> 3] = $add;
+ $q_sroa_1_8__idx25 = $a + 136 | 0;
+ HEAPF64[$q_sroa_1_8__idx25 >> 3] = $add28;
+ $7 = $a;
+ HEAP32[$7 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $8 = +HEAPF64[$x23 >> 3];
+ $sub109 = $8 - $mul12;
+ $x111 = $a + 16 | 0;
+ HEAPF64[$x111 >> 3] = $sub109;
+ $9 = +HEAPF64[$y26 >> 3];
+ $sub114 = $9 - $mul14;
+ $y116 = $a + 24 | 0;
+ HEAPF64[$y116 >> 3] = $sub114;
+ $sub119 = $add33 - $mul18;
+ $x121 = $a + 32 | 0;
+ HEAPF64[$x121 >> 3] = $sub119;
+ $sub124 = $add38 - $mul21;
+ $y126 = $a + 40 | 0;
+ HEAPF64[$y126 >> 3] = $sub124;
+ $10 = +HEAPF64[$x23 >> 3];
+ $x129 = $a + 48 | 0;
+ HEAPF64[$x129 >> 3] = $10;
+ $11 = +HEAPF64[$y26 >> 3];
+ $y132 = $a + 56 | 0;
+ HEAPF64[$y132 >> 3] = $11;
+ $arrayidx133 = $a + 64 | 0;
+ $12 = $arrayidx133;
+ $13 = $p;
+ HEAP32[$12 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ $14 = +HEAPF64[$x23 >> 3];
+ $x136 = $a + 80 | 0;
+ HEAPF64[$x136 >> 3] = $14;
+ $15 = +HEAPF64[$y26 >> 3];
+ $y139 = $a + 88 | 0;
+ HEAPF64[$y139 >> 3] = $15;
+ $add142 = $mul18 + $add33;
+ $x144 = $a + 96 | 0;
+ HEAPF64[$x144 >> 3] = $add142;
+ $add147 = $mul21 + $add38;
+ $y149 = $a + 104 | 0;
+ HEAPF64[$y149 >> 3] = $add147;
+ $16 = +HEAPF64[$x23 >> 3];
+ $add152 = $mul12 + $16;
+ $x154 = $a + 112 | 0;
+ HEAPF64[$x154 >> 3] = $add152;
+ $17 = +HEAPF64[$y26 >> 3];
+ $add157 = $mul14 + $17;
+ $y159 = $a + 120 | 0;
+ HEAPF64[$y159 >> 3] = $add157;
+ label = 11;
+ break;
+ case 11:
+ $and161 = $flag & 32;
+ $tobool162 = ($and161 | 0) == 0;
+ if ($tobool162) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _gvrender_polygon($job, $arrayidx, 6, 1);
+ label = 16;
+ break;
+ case 13:
+ $and165 = $flag & 64;
+ $tobool166 = ($and165 | 0) == 0;
+ if ($tobool166) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $arrayidx168 = $a + 48 | 0;
+ _gvrender_polygon($job, $arrayidx168, 6, 1);
+ label = 16;
+ break;
+ case 15:
+ _gvrender_polygon($job, $arrayidx, 9, 1);
+ label = 16;
+ break;
+ case 16:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_type_tee($job, $p, $u, $arrowsize, $penwidth, $flag) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ $flag = $flag | 0;
+ var $a = 0, $y = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $x3 = 0, $2 = 0.0, $add = 0.0, $y6 = 0, $3 = 0.0, $add8 = 0.0, $mul = 0.0, $add12 = 0.0, $mul16 = 0.0, $add17 = 0.0, $mul21 = 0.0, $add22 = 0.0, $mul26 = 0.0, $add27 = 0.0, $add31 = 0.0, $arrayidx = 0, $x32 = 0, $add35 = 0.0, $y37 = 0, $sub40 = 0.0, $x42 = 0, $sub45 = 0.0, $y47 = 0, $sub50 = 0.0, $x52 = 0, $sub55 = 0.0, $y57 = 0, $add60 = 0.0, $x62 = 0, $add65 = 0.0, $y67 = 0, $and = 0, $tobool = 0, $and70 = 0, $tobool71 = 0, $4 = 0, $5 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $a = __stackBase__ | 0;
+ $y = $u + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $x1 = $u | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $x3 = $p | 0;
+ $2 = +HEAPF64[$x3 >> 3];
+ $add = $1 + $2;
+ $y6 = $p + 8 | 0;
+ $3 = +HEAPF64[$y6 >> 3];
+ $add8 = $0 + $3;
+ $mul = $1 * .2;
+ $add12 = $2 + $mul;
+ $mul16 = $0 * .2;
+ $add17 = $mul16 + $3;
+ $mul21 = $1 * .6;
+ $add22 = $2 + $mul21;
+ $mul26 = $0 * .6;
+ $add27 = $mul26 + $3;
+ $add31 = $add12 - $0;
+ $arrayidx = $a | 0;
+ $x32 = $a | 0;
+ HEAPF64[$x32 >> 3] = $add31;
+ $add35 = $1 + $add17;
+ $y37 = $a + 8 | 0;
+ HEAPF64[$y37 >> 3] = $add35;
+ $sub40 = $0 + $add12;
+ $x42 = $a + 16 | 0;
+ HEAPF64[$x42 >> 3] = $sub40;
+ $sub45 = $add17 - $1;
+ $y47 = $a + 24 | 0;
+ HEAPF64[$y47 >> 3] = $sub45;
+ $sub50 = $0 + $add22;
+ $x52 = $a + 32 | 0;
+ HEAPF64[$x52 >> 3] = $sub50;
+ $sub55 = $add27 - $1;
+ $y57 = $a + 40 | 0;
+ HEAPF64[$y57 >> 3] = $sub55;
+ $add60 = $add22 - $0;
+ $x62 = $a + 48 | 0;
+ HEAPF64[$x62 >> 3] = $add60;
+ $add65 = $1 + $add27;
+ $y67 = $a + 56 | 0;
+ HEAPF64[$y67 >> 3] = $add65;
+ $and = $flag & 32;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAPF64[$x32 >> 3] = $add12;
+ HEAPF64[$y37 >> 3] = $add17;
+ HEAPF64[$x62 >> 3] = $add22;
+ HEAPF64[$y67 >> 3] = $add27;
+ label = 6;
+ break;
+ case 4:
+ $and70 = $flag & 64;
+ $tobool71 = ($and70 | 0) == 0;
+ if ($tobool71) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAPF64[$x42 >> 3] = $add12;
+ HEAPF64[$y47 >> 3] = $add17;
+ HEAPF64[$x52 >> 3] = $add22;
+ HEAPF64[$y57 >> 3] = $add27;
+ label = 6;
+ break;
+ case 6:
+ _gvrender_polygon($job, $arrayidx, 4, 1);
+ $4 = $a;
+ $5 = $p;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ HEAPF64[$x42 >> 3] = $add;
+ HEAPF64[$y47 >> 3] = $add8;
+ _gvrender_polyline($job, $arrayidx, 2);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_type_box($job, $p, $u, $arrowsize, $penwidth, $flag) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ $flag = $flag | 0;
+ var $a = 0, $y = 0, $0 = 0.0, $mul = 0.0, $x1 = 0, $1 = 0.0, $mul2 = 0.0, $x4 = 0, $2 = 0.0, $mul6 = 0.0, $add = 0.0, $y8 = 0, $3 = 0.0, $mul10 = 0.0, $add11 = 0.0, $add15 = 0.0, $add19 = 0.0, $add23 = 0.0, $arrayidx = 0, $x24 = 0, $4 = 0.0, $add27 = 0.0, $y29 = 0, $5 = 0.0, $sub32 = 0.0, $arrayidx33 = 0, $x34 = 0, $6 = 0.0, $sub37 = 0.0, $y39 = 0, $sub42 = 0.0, $x44 = 0, $sub47 = 0.0, $y49 = 0, $add52 = 0.0, $x54 = 0, $add57 = 0.0, $y59 = 0, $and = 0, $tobool = 0, $7 = 0, $8 = 0, $and62 = 0, $tobool63 = 0, $9 = 0, $10 = 0, $and68 = 0, $and68_lobit = 0, $11 = 0, $conv = 0, $q_sroa_0_0__idx = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $a = __stackBase__ | 0;
+ $y = $u + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $mul = $0 * -.4;
+ $x1 = $u | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $mul2 = $1 * .4;
+ $x4 = $p | 0;
+ $2 = +HEAPF64[$x4 >> 3];
+ $mul6 = $1 * .8;
+ $add = $2 + $mul6;
+ $y8 = $p + 8 | 0;
+ $3 = +HEAPF64[$y8 >> 3];
+ $mul10 = $0 * .8;
+ $add11 = $mul10 + $3;
+ $add15 = $1 + $2;
+ $add19 = $0 + $3;
+ $add23 = $mul + $2;
+ $arrayidx = $a | 0;
+ $x24 = $a | 0;
+ HEAPF64[$x24 >> 3] = $add23;
+ $4 = +HEAPF64[$y8 >> 3];
+ $add27 = $mul2 + $4;
+ $y29 = $a + 8 | 0;
+ HEAPF64[$y29 >> 3] = $add27;
+ $5 = +HEAPF64[$x4 >> 3];
+ $sub32 = $5 - $mul;
+ $arrayidx33 = $a + 16 | 0;
+ $x34 = $arrayidx33 | 0;
+ HEAPF64[$x34 >> 3] = $sub32;
+ $6 = +HEAPF64[$y8 >> 3];
+ $sub37 = $6 - $mul2;
+ $y39 = $a + 24 | 0;
+ HEAPF64[$y39 >> 3] = $sub37;
+ $sub42 = $add - $mul;
+ $x44 = $a + 32 | 0;
+ HEAPF64[$x44 >> 3] = $sub42;
+ $sub47 = $add11 - $mul2;
+ $y49 = $a + 40 | 0;
+ HEAPF64[$y49 >> 3] = $sub47;
+ $add52 = $mul + $add;
+ $x54 = $a + 48 | 0;
+ HEAPF64[$x54 >> 3] = $add52;
+ $add57 = $mul2 + $add11;
+ $y59 = $a + 56 | 0;
+ HEAPF64[$y59 >> 3] = $add57;
+ $and = $flag & 32;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $7 = $a;
+ $8 = $p;
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ HEAPF64[$x54 >> 3] = $add;
+ HEAPF64[$y59 >> 3] = $add11;
+ label = 6;
+ break;
+ case 4:
+ $and62 = $flag & 64;
+ $tobool63 = ($and62 | 0) == 0;
+ if ($tobool63) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $9 = $arrayidx33;
+ $10 = $p;
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ HEAPF64[$x44 >> 3] = $add;
+ HEAPF64[$y49 >> 3] = $add11;
+ label = 6;
+ break;
+ case 6:
+ $and68 = $flag >>> 3;
+ $and68_lobit = $and68 & 1;
+ $11 = $and68_lobit ^ 1;
+ $conv = $11 & 255;
+ _gvrender_polygon($job, $arrayidx, 4, $conv);
+ HEAPF64[$x24 >> 3] = $add;
+ HEAPF64[$y29 >> 3] = $add11;
+ $q_sroa_0_0__idx = $a + 16 | 0;
+ HEAPF64[$q_sroa_0_0__idx >> 3] = $add15;
+ HEAPF64[$y39 >> 3] = $add19;
+ _gvrender_polyline($job, $arrayidx, 2);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_type_diamond($job, $p, $u, $arrowsize, $penwidth, $flag) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ $flag = $flag | 0;
+ var $a = 0, $y = 0, $0 = 0.0, $sub = 0.0, $div = 0.0, $x1 = 0, $1 = 0.0, $div2 = 0.0, $x4 = 0, $2 = 0.0, $div6 = 0.0, $add = 0.0, $y8 = 0, $3 = 0.0, $div10 = 0.0, $add11 = 0.0, $add15 = 0.0, $add19 = 0.0, $arrayidx = 0, $arrayidx21 = 0, $q_sroa_0_0__idx = 0, $q_sroa_1_8__idx5 = 0, $4 = 0, $5 = 0, $add24 = 0.0, $x26 = 0, $add29 = 0.0, $y31 = 0, $arrayidx32 = 0, $6 = 0, $7 = 0, $sub35 = 0.0, $x37 = 0, $sub40 = 0.0, $y42 = 0, $and = 0, $tobool = 0, $and44 = 0, $and44_lobit = 0, $8 = 0, $conv = 0, $and46 = 0, $tobool47 = 0, $and49 = 0, $and49_lobit = 0, $9 = 0, $conv53 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 80 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $a = __stackBase__ | 0;
+ $y = $u + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $sub = -0.0 - $0;
+ $div = $sub / 3.0;
+ $x1 = $u | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $div2 = $1 / 3.0;
+ $x4 = $p | 0;
+ $2 = +HEAPF64[$x4 >> 3];
+ $div6 = $1 * .5;
+ $add = $div6 + $2;
+ $y8 = $p + 8 | 0;
+ $3 = +HEAPF64[$y8 >> 3];
+ $div10 = $0 * .5;
+ $add11 = $div10 + $3;
+ $add15 = $1 + $2;
+ $add19 = $0 + $3;
+ $arrayidx = $a | 0;
+ $arrayidx21 = $a + 64 | 0;
+ $q_sroa_0_0__idx = $a + 64 | 0;
+ HEAPF64[$q_sroa_0_0__idx >> 3] = $add15;
+ $q_sroa_1_8__idx5 = $a + 72 | 0;
+ HEAPF64[$q_sroa_1_8__idx5 >> 3] = $add19;
+ $4 = $a;
+ $5 = $arrayidx21;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $add24 = $div + $add;
+ $x26 = $a + 16 | 0;
+ HEAPF64[$x26 >> 3] = $add24;
+ $add29 = $div2 + $add11;
+ $y31 = $a + 24 | 0;
+ HEAPF64[$y31 >> 3] = $add29;
+ $arrayidx32 = $a + 32 | 0;
+ $6 = $arrayidx32;
+ $7 = $p;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $sub35 = $add - $div;
+ $x37 = $a + 48 | 0;
+ HEAPF64[$x37 >> 3] = $sub35;
+ $sub40 = $add11 - $div2;
+ $y42 = $a + 56 | 0;
+ HEAPF64[$y42 >> 3] = $sub40;
+ $and = $flag & 32;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $and44 = $flag >>> 3;
+ $and44_lobit = $and44 & 1;
+ $8 = $and44_lobit ^ 1;
+ $conv = $8 & 255;
+ _gvrender_polygon($job, $arrayidx32, 3, $conv);
+ label = 7;
+ break;
+ case 4:
+ $and46 = $flag & 64;
+ $tobool47 = ($and46 | 0) == 0;
+ $and49 = $flag >>> 3;
+ $and49_lobit = $and49 & 1;
+ $9 = $and49_lobit ^ 1;
+ $conv53 = $9 & 255;
+ if ($tobool47) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _gvrender_polygon($job, $arrayidx, 3, $conv53);
+ label = 7;
+ break;
+ case 6:
+ _gvrender_polygon($job, $arrayidx, 4, $conv53);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_type_dot($job, $p, $u, $arrowsize, $penwidth, $flag) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $u = $u | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ $flag = $flag | 0;
+ var $AF = 0, $x = 0, $0 = 0.0, $y = 0, $1 = 0.0, $div = 0.0, $x4 = 0, $y9 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $AF = __stackBase__ | 0;
+ $x = $u | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $y = $u + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $div = +Math_sqrt(+($0 * $0 + $1 * $1)) * .5;
+ $x4 = $p | 0;
+ HEAPF64[$AF >> 3] = $0 * .5 + +HEAPF64[$x4 >> 3] - $div;
+ $y9 = $p + 8 | 0;
+ HEAPF64[$AF + 8 >> 3] = +HEAPF64[$y9 >> 3] + +HEAPF64[$y >> 3] * .5 - $div;
+ HEAPF64[$AF + 16 >> 3] = $div + (+HEAPF64[$x4 >> 3] + +HEAPF64[$x >> 3] * .5);
+ HEAPF64[$AF + 24 >> 3] = $div + (+HEAPF64[$y9 >> 3] + +HEAPF64[$y >> 3] * .5);
+ _gvrender_ellipse($job, $AF | 0, 0, ($flag >>> 3 & 1 ^ 1) & 255);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _arrow_match_shape($name, $flag) {
+ $name = $name | 0;
+ $flag = $flag | 0;
+ var $f = 0, $call = 0, $cmp = 0, $rest_0 = 0, $call1 = 0, $cmp2 = 0, $call3 = 0, $rest_1 = 0, $0 = 0, $tobool = 0, $and = 0, $tobool4 = 0, $or_cond = 0, $or = 0, $1 = 0, $2 = 0, $or7 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $f = __stackBase__ | 0;
+ HEAP32[$f >> 2] = 0;
+ $call = _arrow_match_name_frag($name, 168304, $f) | 0;
+ $cmp = ($call | 0) == ($name | 0);
+ if ($cmp) {
+ $rest_0 = $call;
+ label = 3;
+ break;
+ } else {
+ $rest_1 = $call;
+ label = 5;
+ break;
+ }
+ case 3:
+ $call1 = _arrow_match_name_frag($rest_0, 168416, $f) | 0;
+ $cmp2 = ($rest_0 | 0) == ($call1 | 0);
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ $rest_0 = $call1;
+ label = 3;
+ break;
+ }
+ case 4:
+ $call3 = _arrow_match_name_frag($call1, 168320, $f) | 0;
+ $rest_1 = $call3;
+ label = 5;
+ break;
+ case 5:
+ $0 = HEAP32[$f >> 2] | 0;
+ $tobool = ($0 | 0) != 0;
+ $and = $0 & 7;
+ $tobool4 = ($and | 0) == 0;
+ $or_cond = $tobool & $tobool4;
+ if ($or_cond) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $or = $0 | 1;
+ HEAP32[$f >> 2] = $or;
+ label = 7;
+ break;
+ case 7:
+ $1 = HEAP32[$f >> 2] | 0;
+ $2 = HEAP32[$flag >> 2] | 0;
+ $or7 = $2 | $1;
+ HEAP32[$flag >> 2] = $or7;
+ STACKTOP = __stackBase__;
+ return $rest_1 | 0;
+ }
+ return 0;
+}
+function _arrow_match_name_frag($name, $arrownames, $flag) {
+ $name = $name | 0;
+ $arrownames = $arrownames | 0;
+ $flag = $flag | 0;
+ var $arrowname_0 = 0, $name1 = 0, $0 = 0, $tobool = 0, $call = 0, $call4 = 0, $cmp = 0, $incdec_ptr = 0, $type = 0, $1 = 0, $2 = 0, $or = 0, $add_ptr = 0, $rest_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $arrowname_0 = $arrownames;
+ label = 3;
+ break;
+ case 3:
+ $name1 = $arrowname_0 | 0;
+ $0 = HEAP32[$name1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $rest_0 = $name;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _strlen($0 | 0) | 0;
+ $call4 = _strncmp($name | 0, $0 | 0, $call | 0) | 0;
+ $cmp = ($call4 | 0) == 0;
+ $incdec_ptr = $arrowname_0 + 8 | 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $arrowname_0 = $incdec_ptr;
+ label = 3;
+ break;
+ }
+ case 5:
+ $type = $arrowname_0 + 4 | 0;
+ $1 = HEAP32[$type >> 2] | 0;
+ $2 = HEAP32[$flag >> 2] | 0;
+ $or = $2 | $1;
+ HEAP32[$flag >> 2] = $or;
+ $add_ptr = $name + $call | 0;
+ $rest_0 = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ return $rest_0 | 0;
+ }
+ return 0;
+}
+function _init_xdot($g) {
+ $g = $g | 0;
+ var $stats = 0, $0 = 0, $call = 0, $tobool = 0, $1 = 0, $tobool1 = 0, $2 = 0, $tobool2 = 0, $call4 = 0, $tobool5 = 0, $name = 0, $3 = 0, $call7 = 0, $call8 = 0, $4 = 0, $tobool10 = 0, $call12 = 0.0, $call13 = 0, $5 = 0, $cnt = 0, $6 = 0, $call14 = 0, $7 = 0, $n_polygon = 0, $8 = 0, $n_polygon_pts = 0, $9 = 0, $call15 = 0, $10 = 0, $n_polyline = 0, $11 = 0, $n_polyline_pts = 0, $12 = 0, $call16 = 0, $13 = 0, $n_bezier = 0, $14 = 0, $n_bezier_pts = 0, $15 = 0, $call17 = 0, $16 = 0, $n_ellipse = 0, $17 = 0, $call18 = 0, $18 = 0, $n_text = 0, $19 = 0, $call19 = 0, $xd_0 = 0, $20 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 56 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $stats = __stackBase__ | 0;
+ $0 = $g | 0;
+ $call = _agget($0, 132328) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $xd_0 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$call] | 0;
+ $tobool1 = $1 << 24 >> 24 == 0;
+ if ($tobool1) {
+ $xd_0 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP8[164912] | 0;
+ $tobool2 = $2 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _start_timer();
+ label = 6;
+ break;
+ case 6:
+ $call4 = _parseXDotF($call | 0, 0, 96) | 0;
+ $tobool5 = ($call4 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $name = $g + 12 | 0;
+ $3 = HEAP32[$name >> 2] | 0;
+ $call7 = _agerr(0, 155888, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $3, tempInt) | 0) | 0;
+ $call8 = _agerr(3, 128168, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call, tempInt) | 0) | 0;
+ label = 8;
+ break;
+ case 8:
+ $4 = HEAP8[164912] | 0;
+ $tobool10 = $4 << 24 >> 24 == 0;
+ if ($tobool10) {
+ $xd_0 = $call4;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call12 = +_elapsed_sec();
+ $call13 = _statXDot($call4 | 0, $stats | 0) | 0;
+ $5 = HEAP32[_stderr >> 2] | 0;
+ $cnt = $stats | 0;
+ $6 = HEAP32[$cnt >> 2] | 0;
+ $call14 = _fprintf($5 | 0, 117616, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $6, HEAPF64[tempInt + 8 >> 3] = $call12, tempInt) | 0) | 0;
+ $7 = HEAP32[_stderr >> 2] | 0;
+ $n_polygon = $stats + 8 | 0;
+ $8 = HEAP32[$n_polygon >> 2] | 0;
+ $n_polygon_pts = $stats + 12 | 0;
+ $9 = HEAP32[$n_polygon_pts >> 2] | 0;
+ $call15 = _fprintf($7 | 0, 112264, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $8, HEAP32[tempInt + 8 >> 2] = $9, tempInt) | 0) | 0;
+ $10 = HEAP32[_stderr >> 2] | 0;
+ $n_polyline = $stats + 16 | 0;
+ $11 = HEAP32[$n_polyline >> 2] | 0;
+ $n_polyline_pts = $stats + 20 | 0;
+ $12 = HEAP32[$n_polyline_pts >> 2] | 0;
+ $call16 = _fprintf($10 | 0, 107904, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $11, HEAP32[tempInt + 8 >> 2] = $12, tempInt) | 0) | 0;
+ $13 = HEAP32[_stderr >> 2] | 0;
+ $n_bezier = $stats + 24 | 0;
+ $14 = HEAP32[$n_bezier >> 2] | 0;
+ $n_bezier_pts = $stats + 28 | 0;
+ $15 = HEAP32[$n_bezier_pts >> 2] | 0;
+ $call17 = _fprintf($13 | 0, 103872, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $14, HEAP32[tempInt + 8 >> 2] = $15, tempInt) | 0) | 0;
+ $16 = HEAP32[_stderr >> 2] | 0;
+ $n_ellipse = $stats + 4 | 0;
+ $17 = HEAP32[$n_ellipse >> 2] | 0;
+ $call18 = _fprintf($16 | 0, 99640, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $17, tempInt) | 0) | 0;
+ $18 = HEAP32[_stderr >> 2] | 0;
+ $n_text = $stats + 32 | 0;
+ $19 = HEAP32[$n_text >> 2] | 0;
+ $call19 = _fprintf($18 | 0, 95576, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $19, tempInt) | 0) | 0;
+ $xd_0 = $call4;
+ label = 10;
+ break;
+ case 10:
+ $20 = $xd_0;
+ STACKTOP = __stackBase__;
+ return $20 | 0;
+ }
+ return 0;
+}
+function _push_obj_state($job) {
+ $job = $job | 0;
+ var $call = 0, $0 = 0, $tobool = 0, $call1 = 0, $obj2 = 0, $1 = 0, $parent3 = 0, $tobool5 = 0, $pencolor = 0, $pencolor7 = 0, $2 = 0, $fillcolor = 0, $fillcolor8 = 0, $3 = 0, $pen = 0, $4 = 0, $pen9 = 0, $5 = 0, $fill = 0, $6 = 0, $fill10 = 0, $7 = 0, $penwidth = 0, $8 = 0.0, $penwidth11 = 0, $9 = 0, $pen12 = 0, $10 = 0, $fill13 = 0, $11 = 0, $penwidth14 = 0, $12 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(256) | 0;
+ $0 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call1 = _agerr(1, 92048, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $obj2 = $job + 16 | 0;
+ $1 = HEAP32[$obj2 >> 2] | 0;
+ $parent3 = $call;
+ HEAP32[$parent3 >> 2] = $1;
+ HEAP32[$obj2 >> 2] = $0;
+ $tobool5 = ($1 | 0) == 0;
+ if ($tobool5) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $pencolor = $call + 16 | 0;
+ $pencolor7 = $1 + 16 | 0;
+ $2 = $pencolor7;
+ HEAP32[$pencolor >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$pencolor + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$pencolor + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$pencolor + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ HEAP32[$pencolor + 16 >> 2] = HEAP32[$2 + 16 >> 2] | 0;
+ HEAP32[$pencolor + 20 >> 2] = HEAP32[$2 + 20 >> 2] | 0;
+ HEAP32[$pencolor + 24 >> 2] = HEAP32[$2 + 24 >> 2] | 0;
+ HEAP32[$pencolor + 28 >> 2] = HEAP32[$2 + 28 >> 2] | 0;
+ HEAP32[$pencolor + 32 >> 2] = HEAP32[$2 + 32 >> 2] | 0;
+ HEAP32[$pencolor + 36 >> 2] = HEAP32[$2 + 36 >> 2] | 0;
+ $fillcolor = $call + 56 | 0;
+ $fillcolor8 = $1 + 56 | 0;
+ $3 = $fillcolor8;
+ HEAP32[$fillcolor >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$fillcolor + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$fillcolor + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$fillcolor + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ HEAP32[$fillcolor + 16 >> 2] = HEAP32[$3 + 16 >> 2] | 0;
+ HEAP32[$fillcolor + 20 >> 2] = HEAP32[$3 + 20 >> 2] | 0;
+ HEAP32[$fillcolor + 24 >> 2] = HEAP32[$3 + 24 >> 2] | 0;
+ HEAP32[$fillcolor + 28 >> 2] = HEAP32[$3 + 28 >> 2] | 0;
+ HEAP32[$fillcolor + 32 >> 2] = HEAP32[$3 + 32 >> 2] | 0;
+ HEAP32[$fillcolor + 36 >> 2] = HEAP32[$3 + 36 >> 2] | 0;
+ $pen = $1 + 96 | 0;
+ $4 = HEAP32[$pen >> 2] | 0;
+ $pen9 = $call + 96 | 0;
+ $5 = $pen9;
+ HEAP32[$5 >> 2] = $4;
+ $fill = $1 + 100 | 0;
+ $6 = HEAP32[$fill >> 2] | 0;
+ $fill10 = $call + 100 | 0;
+ $7 = $fill10;
+ HEAP32[$7 >> 2] = $6;
+ $penwidth = $1 + 104 | 0;
+ $8 = +HEAPF64[$penwidth >> 3];
+ $penwidth11 = $call + 104 | 0;
+ $9 = $penwidth11;
+ HEAPF64[$9 >> 3] = $8;
+ label = 7;
+ break;
+ case 6:
+ $pen12 = $call + 96 | 0;
+ $10 = $pen12;
+ HEAP32[$10 >> 2] = 3;
+ $fill13 = $call + 100 | 0;
+ $11 = $fill13;
+ HEAP32[$11 >> 2] = 0;
+ $penwidth14 = $call + 104 | 0;
+ $12 = $penwidth14;
+ HEAPF64[$12 >> 3] = 1.0;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $0 | 0;
+ }
+ return 0;
+}
+function _initMapData($job, $lbl, $url, $tooltip, $target, $id, $gobj) {
+ $job = $job | 0;
+ $lbl = $lbl | 0;
+ $url = $url | 0;
+ $tooltip = $tooltip | 0;
+ $target = $target | 0;
+ $id = $id | 0;
+ $gobj = $gobj | 0;
+ var $obj1 = 0, $0 = 0, $flags2 = 0, $1 = 0, $and = 0, $tobool = 0, $tobool3 = 0, $or_cond = 0, $label = 0, $and4 = 0, $tobool5 = 0, $call = 0, $id7 = 0, $tobool8 = 0, $2 = 0, $tobool10 = 0, $call12 = 0, $url13 = 0, $assigned_0 = 0, $and16 = 0, $tobool17 = 0, $tobool19 = 0, $3 = 0, $tobool23 = 0, $call25 = 0, $tooltip26 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, $label27 = 0, $8 = 0, $tobool28 = 0, $call31 = 0, $tooltip32 = 0, $assigned_1 = 0, $and36 = 0, $tobool37 = 0, $tobool39 = 0, $or_cond23 = 0, $9 = 0, $tobool43 = 0, $call45 = 0, $target46 = 0, $assigned_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $flags2 = $job + 152 | 0;
+ $1 = HEAP32[$flags2 >> 2] | 0;
+ $and = $1 & 32768;
+ $tobool = ($and | 0) == 0;
+ $tobool3 = ($lbl | 0) == 0;
+ $or_cond = $tobool | $tobool3;
+ if ($or_cond) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $label = $0 + 144 | 0;
+ HEAP32[$label >> 2] = $lbl;
+ label = 4;
+ break;
+ case 4:
+ $and4 = $1 & 65536;
+ $tobool5 = ($and4 | 0) == 0;
+ if ($tobool5) {
+ $assigned_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call = _strdup_and_subst_obj($id, $gobj) | 0;
+ $id7 = $0 + 164 | 0;
+ HEAP32[$id7 >> 2] = $call;
+ $tobool8 = ($url | 0) == 0;
+ if ($tobool8) {
+ $assigned_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $2 = HEAP8[$url] | 0;
+ $tobool10 = $2 << 24 >> 24 == 0;
+ if ($tobool10) {
+ $assigned_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call12 = _strdup_and_subst_obj($url, $gobj) | 0;
+ $url13 = $0 + 160 | 0;
+ HEAP32[$url13 >> 2] = $call12;
+ $assigned_0 = 1;
+ label = 8;
+ break;
+ case 8:
+ $and16 = $1 & 4194304;
+ $tobool17 = ($and16 | 0) == 0;
+ if ($tobool17) {
+ $assigned_1 = $assigned_0;
+ label = 14;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $tobool19 = ($tooltip | 0) == 0;
+ if ($tobool19) {
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $3 = HEAP8[$tooltip] | 0;
+ $tobool23 = $3 << 24 >> 24 == 0;
+ if ($tobool23) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call25 = _strdup_and_subst_obj($tooltip, $gobj) | 0;
+ $tooltip26 = $0 + 180 | 0;
+ HEAP32[$tooltip26 >> 2] = $call25;
+ $4 = $0 + 212 | 0;
+ $5 = $4;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $7 = $6 | 1;
+ HEAP32[$5 >> 2] = $7;
+ $assigned_1 = 1;
+ label = 14;
+ break;
+ case 12:
+ $label27 = $0 + 144 | 0;
+ $8 = HEAP32[$label27 >> 2] | 0;
+ $tobool28 = ($8 | 0) == 0;
+ if ($tobool28) {
+ $assigned_1 = $assigned_0;
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $call31 = _strdup($8 | 0) | 0;
+ $tooltip32 = $0 + 180 | 0;
+ HEAP32[$tooltip32 >> 2] = $call31;
+ $assigned_1 = 1;
+ label = 14;
+ break;
+ case 14:
+ $and36 = $1 & 8388608;
+ $tobool37 = ($and36 | 0) == 0;
+ $tobool39 = ($target | 0) == 0;
+ $or_cond23 = $tobool37 | $tobool39;
+ if ($or_cond23) {
+ $assigned_2 = $assigned_1;
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $9 = HEAP8[$target] | 0;
+ $tobool43 = $9 << 24 >> 24 == 0;
+ if ($tobool43) {
+ $assigned_2 = $assigned_1;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $call45 = _strdup_and_subst_obj($target, $gobj) | 0;
+ $target46 = $0 + 196 | 0;
+ HEAP32[$target46 >> 2] = $call45;
+ $assigned_2 = 1;
+ label = 17;
+ break;
+ case 17:
+ return $assigned_2 | 0;
+ }
+ return 0;
+}
+function _getObjId($job, $obj, $xb) {
+ $job = $job | 0;
+ $obj = $obj | 0;
+ $xb = $xb | 0;
+ var $buf = 0, $gvc = 0, $0 = 0, $g = 0, $1 = 0, $drawing = 0, $2 = 0, $id1 = 0, $3 = 0, $call = 0, $tobool = 0, $4 = 0, $tobool2 = 0, $5 = 0, $6 = 0, $7 = 0, $bf_val_sext = 0, $meta_node = 0, $8 = 0, $9 = 0, $id3 = 0, $10 = 0, $id5 = 0, $11 = 0, $12 = 0, $id7 = 0, $13 = 0, $14 = 0, $idnum_0 = 0, $pfx_0 = 0, $tobool8 = 0, $call10 = 0, $ptr = 0, $15 = 0, $eptr = 0, $16 = 0, $cmp = 0, $call12 = 0, $17 = 0, $incdec_ptr = 0, $call15 = 0, $arraydecay = 0, $call16 = 0, $call18 = 0, $ptr19 = 0, $18 = 0, $eptr20 = 0, $19 = 0, $cmp21 = 0, $call24 = 0, $20 = 0, $buf30 = 0, $21 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $gvc = $job | 0;
+ $0 = HEAP32[$gvc >> 2] | 0;
+ $g = $0 + 128 | 0;
+ $1 = HEAP32[$g >> 2] | 0;
+ $drawing = $1 + 48 | 0;
+ $2 = HEAP32[$drawing >> 2] | 0;
+ $id1 = $2 + 92 | 0;
+ $3 = HEAP32[$id1 >> 2] | 0;
+ $call = _agget($obj, 155120) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $4 = HEAP8[$call] | 0;
+ $tobool2 = $4 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = $call;
+ label = 15;
+ break;
+ }
+ case 4:
+ $5 = $obj;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $7 = $6 << 28;
+ $bf_val_sext = $7 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 5;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 6;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 7;
+ break;
+ } else {
+ $pfx_0 = 0;
+ $idnum_0 = 0;
+ label = 8;
+ break;
+ }
+ case 5:
+ $meta_node = $obj + 36 | 0;
+ $8 = $meta_node;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $id3 = $9 + 16 | 0;
+ $10 = HEAP32[$id3 >> 2] | 0;
+ $pfx_0 = 151640;
+ $idnum_0 = $10;
+ label = 8;
+ break;
+ case 6:
+ $id5 = $obj + 16 | 0;
+ $11 = $id5;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $pfx_0 = 148304;
+ $idnum_0 = $12;
+ label = 8;
+ break;
+ case 7:
+ $id7 = $obj + 20 | 0;
+ $13 = $id7;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $pfx_0 = 145504;
+ $idnum_0 = $14;
+ label = 8;
+ break;
+ case 8:
+ $tobool8 = ($3 | 0) == 0;
+ if ($tobool8) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call10 = _agxbput($xb, $3) | 0;
+ $ptr = $xb + 4 | 0;
+ $15 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $xb + 8 | 0;
+ $16 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $15 >>> 0 < $16 >>> 0;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call12 = _agxbmore($xb, 1) | 0;
+ label = 11;
+ break;
+ case 11:
+ $17 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $17 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$17] = 95;
+ label = 12;
+ break;
+ case 12:
+ $call15 = _agxbput($xb, $pfx_0) | 0;
+ $arraydecay = $buf | 0;
+ $call16 = _sprintf($arraydecay | 0, 142424, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $idnum_0, tempInt) | 0) | 0;
+ $call18 = _agxbput($xb, $arraydecay) | 0;
+ $ptr19 = $xb + 4 | 0;
+ $18 = HEAP32[$ptr19 >> 2] | 0;
+ $eptr20 = $xb + 8 | 0;
+ $19 = HEAP32[$eptr20 >> 2] | 0;
+ $cmp21 = $18 >>> 0 < $19 >>> 0;
+ if ($cmp21) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $call24 = _agxbmore($xb, 1) | 0;
+ label = 14;
+ break;
+ case 14:
+ $20 = HEAP32[$ptr19 >> 2] | 0;
+ HEAP8[$20] = 0;
+ $buf30 = $xb | 0;
+ $21 = HEAP32[$buf30 >> 2] | 0;
+ HEAP32[$ptr19 >> 2] = $21;
+ $retval_0 = $21;
+ label = 15;
+ break;
+ case 15:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _emit_map_rect($job, $b) {
+ $job = $job | 0;
+ $b = $b | 0;
+ var $obj1 = 0, $0 = 0, $flags2 = 0, $1 = 0, $and = 0, $tobool = 0, $and3 = 0, $tobool4 = 0, $url_map_shape = 0, $url_map_n = 0, $url_map_n7 = 0, $url_map_p = 0, $2 = 0, $3 = 0, $url_map_n8 = 0, $4 = 0, $mul = 0, $call = 0, $5 = 0, $6 = 0, $arrayidx10 = 0, $UR = 0, $7 = 0, $and11 = 0, $tobool12 = 0, $call14 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $flags2 = $job + 152 | 0;
+ $1 = HEAP32[$flags2 >> 2] | 0;
+ $and = $1 & 4259840;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $and3 = $1 & 131072;
+ $tobool4 = ($and3 | 0) != 0;
+ $url_map_shape = $0 + 216 | 0;
+ if ($tobool4) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP32[$url_map_shape >> 2] = 0;
+ $url_map_n = $0 + 220 | 0;
+ HEAP32[$url_map_n >> 2] = 2;
+ label = 6;
+ break;
+ case 5:
+ HEAP32[$url_map_shape >> 2] = 2;
+ $url_map_n7 = $0 + 220 | 0;
+ HEAP32[$url_map_n7 >> 2] = 4;
+ label = 6;
+ break;
+ case 6:
+ $url_map_p = $0 + 224 | 0;
+ $2 = HEAP32[$url_map_p >> 2] | 0;
+ $3 = $2;
+ _free($3);
+ $url_map_n8 = $0 + 220 | 0;
+ $4 = HEAP32[$url_map_n8 >> 2] | 0;
+ $mul = $4 << 4;
+ $call = _zmalloc($mul) | 0;
+ $5 = $call;
+ HEAP32[$url_map_p >> 2] = $5;
+ $6 = $b;
+ HEAP32[$call >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$call + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$call + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$call + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ $arrayidx10 = $call + 16 | 0;
+ $UR = $b + 16 | 0;
+ $7 = $UR;
+ HEAP32[$arrayidx10 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$arrayidx10 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$arrayidx10 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$arrayidx10 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $and11 = $1 & 8192;
+ $tobool12 = ($and11 | 0) == 0;
+ if ($tobool12) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call14 = _gvrender_ptf_A($job, $5, $5, 2) | 0;
+ label = 8;
+ break;
+ case 8:
+ if ($tobool4) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ _rect2poly($5);
+ label = 10;
+ break;
+ case 10:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pop_obj_state($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $tobool = 0, $id = 0, $1 = 0, $url = 0, $2 = 0, $labelurl = 0, $3 = 0, $tailurl = 0, $4 = 0, $headurl = 0, $5 = 0, $tooltip = 0, $6 = 0, $labeltooltip = 0, $7 = 0, $tailtooltip = 0, $8 = 0, $headtooltip = 0, $9 = 0, $target = 0, $10 = 0, $labeltarget = 0, $11 = 0, $tailtarget = 0, $12 = 0, $headtarget = 0, $13 = 0, $url_map_p = 0, $14 = 0, $15 = 0, $url_bsplinemap_p = 0, $16 = 0, $17 = 0, $url_bsplinemap_n = 0, $18 = 0, $19 = 0, $parent = 0, $20 = 0, $21 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(162152, 110, 163952, 158632);
+ case 4:
+ $id = $0 + 164 | 0;
+ $1 = HEAP32[$id >> 2] | 0;
+ _free($1);
+ $url = $0 + 160 | 0;
+ $2 = HEAP32[$url >> 2] | 0;
+ _free($2);
+ $labelurl = $0 + 168 | 0;
+ $3 = HEAP32[$labelurl >> 2] | 0;
+ _free($3);
+ $tailurl = $0 + 172 | 0;
+ $4 = HEAP32[$tailurl >> 2] | 0;
+ _free($4);
+ $headurl = $0 + 176 | 0;
+ $5 = HEAP32[$headurl >> 2] | 0;
+ _free($5);
+ $tooltip = $0 + 180 | 0;
+ $6 = HEAP32[$tooltip >> 2] | 0;
+ _free($6);
+ $labeltooltip = $0 + 184 | 0;
+ $7 = HEAP32[$labeltooltip >> 2] | 0;
+ _free($7);
+ $tailtooltip = $0 + 188 | 0;
+ $8 = HEAP32[$tailtooltip >> 2] | 0;
+ _free($8);
+ $headtooltip = $0 + 192 | 0;
+ $9 = HEAP32[$headtooltip >> 2] | 0;
+ _free($9);
+ $target = $0 + 196 | 0;
+ $10 = HEAP32[$target >> 2] | 0;
+ _free($10);
+ $labeltarget = $0 + 200 | 0;
+ $11 = HEAP32[$labeltarget >> 2] | 0;
+ _free($11);
+ $tailtarget = $0 + 204 | 0;
+ $12 = HEAP32[$tailtarget >> 2] | 0;
+ _free($12);
+ $headtarget = $0 + 208 | 0;
+ $13 = HEAP32[$headtarget >> 2] | 0;
+ _free($13);
+ $url_map_p = $0 + 224 | 0;
+ $14 = HEAP32[$url_map_p >> 2] | 0;
+ $15 = $14;
+ _free($15);
+ $url_bsplinemap_p = $0 + 236 | 0;
+ $16 = HEAP32[$url_bsplinemap_p >> 2] | 0;
+ $17 = $16;
+ _free($17);
+ $url_bsplinemap_n = $0 + 232 | 0;
+ $18 = HEAP32[$url_bsplinemap_n >> 2] | 0;
+ $19 = $18;
+ _free($19);
+ $parent = $0 | 0;
+ $20 = HEAP32[$parent >> 2] | 0;
+ HEAP32[$obj1 >> 2] = $20;
+ $21 = $0;
+ _free($21);
+ return;
+ }
+}
+function _validlayer($job) {
+ $job = $job | 0;
+ return (HEAP32[$job + 160 >> 2] | 0) <= (HEAP32[$job + 156 >> 2] | 0) & 1 | 0;
+}
+function _firstpage($job) {
+ $job = $job | 0;
+ var $0 = 0, $1 = 0, $2$1 = 0;
+ $0 = $job + 172 | 0;
+ $1 = $job + 196 | 0;
+ $2$1 = HEAP32[$0 + 4 >> 2] | 0;
+ HEAP32[$1 >> 2] = HEAP32[$0 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = $2$1;
+ return;
+}
+function _validpage($job) {
+ $job = $job | 0;
+ var $x = 0, $0 = 0, $cmp = 0, $x3 = 0, $1 = 0, $cmp4 = 0, $y = 0, $2 = 0, $cmp7 = 0, $y11 = 0, $3 = 0, $cmp12 = 0, $phitmp = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $job + 196 | 0;
+ $0 = HEAP32[$x >> 2] | 0;
+ $cmp = ($0 | 0) > -1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 3:
+ $x3 = $job + 164 | 0;
+ $1 = HEAP32[$x3 >> 2] | 0;
+ $cmp4 = ($0 | 0) < ($1 | 0);
+ if ($cmp4) {
+ label = 4;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 4:
+ $y = $job + 200 | 0;
+ $2 = HEAP32[$y >> 2] | 0;
+ $cmp7 = ($2 | 0) > -1;
+ if ($cmp7) {
+ label = 5;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $y11 = $job + 168 | 0;
+ $3 = HEAP32[$y11 >> 2] | 0;
+ $cmp12 = ($2 | 0) < ($3 | 0);
+ $phitmp = $cmp12 & 1;
+ $4 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ return $4 | 0;
+ }
+ return 0;
+}
+function _nextlayer($job) {
+ $job = $job | 0;
+ var $layerNum = 0;
+ $layerNum = $job + 160 | 0;
+ HEAP32[$layerNum >> 2] = (HEAP32[$layerNum >> 2] | 0) + 1 | 0;
+ return;
+}
+function _update_bb_bz($bb, $cp) {
+ $bb = $bb | 0;
+ $cp = $cp | 0;
+ var $left = 0, $right = 0, $tmp = 0, $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $cmp = 0, $x4 = 0, $2 = 0.0, $cmp5 = 0, $y = 0, $3 = 0.0, $y9 = 0, $4 = 0.0, $cmp10 = 0, $y15 = 0, $5 = 0.0, $cmp16 = 0, $x19 = 0, $6 = 0.0, $cmp22 = 0, $cmp28 = 0, $or_cond = 0, $y31 = 0, $7 = 0.0, $cmp34 = 0, $cmp40 = 0, $or_cond54 = 0, $x43 = 0, $8 = 0.0, $cmp46 = 0, $cmp52 = 0, $or_cond55 = 0, $y55 = 0, $9 = 0.0, $cmp58 = 0, $cmp64 = 0, $or_cond56 = 0, $x67 = 0, $10 = 0.0, $cmp70 = 0, $cmp76 = 0, $or_cond57 = 0, $y79 = 0, $11 = 0.0, $cmp82 = 0, $cmp88 = 0, $or_cond58 = 0, $call = 0, $tobool = 0, $y115 = 0, $y126 = 0, $x104 = 0, $x92 = 0, $12 = 0.0, $13 = 0.0, $cmp95 = 0, $14 = 0.0, $cmp105 = 0, $y113 = 0, $15 = 0.0, $16 = 0.0, $cmp116 = 0, $17 = 0.0, $cmp127 = 0, $x92_1 = 0, $18 = 0.0, $19 = 0.0, $cmp95_1 = 0, $arraydecay = 0, $arraydecay136 = 0, $20 = 0.0, $cmp105_1 = 0, $y113_1 = 0, $21 = 0.0, $22 = 0.0, $cmp116_1 = 0, $23 = 0.0, $cmp127_1 = 0, $x92_2 = 0, $24 = 0.0, $25 = 0.0, $cmp95_2 = 0, $26 = 0.0, $cmp105_2 = 0, $y113_2 = 0, $27 = 0.0, $28 = 0.0, $cmp116_2 = 0, $29 = 0.0, $cmp127_2 = 0, $x92_3 = 0, $30 = 0.0, $31 = 0.0, $cmp95_3 = 0, $32 = 0.0, $cmp105_3 = 0, $y113_3 = 0, $33 = 0.0, $34 = 0.0, $cmp116_3 = 0, $35 = 0.0, $cmp127_3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $left = __stackBase__ | 0;
+ $right = __stackBase__ + 64 | 0;
+ $tmp = __stackBase__ + 128 | 0;
+ $x = $cp | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $bb + 16 | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $cmp = $0 > $1;
+ if ($cmp) {
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x4 = $bb | 0;
+ $2 = +HEAPF64[$x4 >> 3];
+ $cmp5 = $0 < $2;
+ if ($cmp5) {
+ label = 12;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $cp + 8 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $y9 = $bb + 24 | 0;
+ $4 = +HEAPF64[$y9 >> 3];
+ $cmp10 = $3 > $4;
+ if ($cmp10) {
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y15 = $bb + 8 | 0;
+ $5 = +HEAPF64[$y15 >> 3];
+ $cmp16 = $3 < $5;
+ if ($cmp16) {
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $x19 = $cp + 16 | 0;
+ $6 = +HEAPF64[$x19 >> 3];
+ $cmp22 = $6 > $1;
+ $cmp28 = $6 < $2;
+ $or_cond = $cmp22 | $cmp28;
+ if ($or_cond) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $y31 = $cp + 24 | 0;
+ $7 = +HEAPF64[$y31 >> 3];
+ $cmp34 = $7 > $4;
+ $cmp40 = $7 < $5;
+ $or_cond54 = $cmp34 | $cmp40;
+ if ($or_cond54) {
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $x43 = $cp + 32 | 0;
+ $8 = +HEAPF64[$x43 >> 3];
+ $cmp46 = $8 > $1;
+ $cmp52 = $8 < $2;
+ $or_cond55 = $cmp46 | $cmp52;
+ if ($or_cond55) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $y55 = $cp + 40 | 0;
+ $9 = +HEAPF64[$y55 >> 3];
+ $cmp58 = $9 > $4;
+ $cmp64 = $9 < $5;
+ $or_cond56 = $cmp58 | $cmp64;
+ if ($or_cond56) {
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $x67 = $cp + 48 | 0;
+ $10 = +HEAPF64[$x67 >> 3];
+ $cmp70 = $10 > $1;
+ $cmp76 = $10 < $2;
+ $or_cond57 = $cmp70 | $cmp76;
+ if ($or_cond57) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $y79 = $cp + 56 | 0;
+ $11 = +HEAPF64[$y79 >> 3];
+ $cmp82 = $11 > $4;
+ $cmp88 = $11 < $5;
+ $or_cond58 = $cmp82 | $cmp88;
+ if ($or_cond58) {
+ label = 12;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 12:
+ $call = _check_control_points($cp) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 22;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $y115 = $bb + 24 | 0;
+ $y126 = $bb + 8 | 0;
+ $x104 = $bb | 0;
+ $x92 = $cp | 0;
+ $12 = +HEAPF64[$x92 >> 3];
+ $13 = +HEAPF64[$x1 >> 3];
+ $cmp95 = $12 > $13;
+ if ($cmp95) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAPF64[$x1 >> 3] = $12;
+ label = 17;
+ break;
+ case 15:
+ $14 = +HEAPF64[$x104 >> 3];
+ $cmp105 = $12 < $14;
+ if ($cmp105) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ HEAPF64[$x104 >> 3] = $12;
+ label = 17;
+ break;
+ case 17:
+ $y113 = $cp + 8 | 0;
+ $15 = +HEAPF64[$y113 >> 3];
+ $16 = +HEAPF64[$y115 >> 3];
+ $cmp116 = $15 > $16;
+ if ($cmp116) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAPF64[$y115 >> 3] = $15;
+ label = 21;
+ break;
+ case 19:
+ $17 = +HEAPF64[$y126 >> 3];
+ $cmp127 = $15 < $17;
+ if ($cmp127) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ HEAPF64[$y126 >> 3] = $15;
+ label = 21;
+ break;
+ case 21:
+ $x92_1 = $cp + 16 | 0;
+ $18 = +HEAPF64[$x92_1 >> 3];
+ $19 = +HEAPF64[$x1 >> 3];
+ $cmp95_1 = $18 > $19;
+ if ($cmp95_1) {
+ label = 26;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 22:
+ $arraydecay = $left | 0;
+ $arraydecay136 = $right | 0;
+ _Bezier($tmp, $cp, 3, .5, $arraydecay, $arraydecay136);
+ _update_bb_bz($bb, $arraydecay);
+ _update_bb_bz($bb, $arraydecay136);
+ label = 23;
+ break;
+ case 23:
+ STACKTOP = __stackBase__;
+ return;
+ case 24:
+ $20 = +HEAPF64[$x104 >> 3];
+ $cmp105_1 = $18 < $20;
+ if ($cmp105_1) {
+ label = 25;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 25:
+ HEAPF64[$x104 >> 3] = $18;
+ label = 27;
+ break;
+ case 26:
+ HEAPF64[$x1 >> 3] = $18;
+ label = 27;
+ break;
+ case 27:
+ $y113_1 = $cp + 24 | 0;
+ $21 = +HEAPF64[$y113_1 >> 3];
+ $22 = +HEAPF64[$y115 >> 3];
+ $cmp116_1 = $21 > $22;
+ if ($cmp116_1) {
+ label = 30;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $23 = +HEAPF64[$y126 >> 3];
+ $cmp127_1 = $21 < $23;
+ if ($cmp127_1) {
+ label = 29;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 29:
+ HEAPF64[$y126 >> 3] = $21;
+ label = 31;
+ break;
+ case 30:
+ HEAPF64[$y115 >> 3] = $21;
+ label = 31;
+ break;
+ case 31:
+ $x92_2 = $cp + 32 | 0;
+ $24 = +HEAPF64[$x92_2 >> 3];
+ $25 = +HEAPF64[$x1 >> 3];
+ $cmp95_2 = $24 > $25;
+ if ($cmp95_2) {
+ label = 34;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $26 = +HEAPF64[$x104 >> 3];
+ $cmp105_2 = $24 < $26;
+ if ($cmp105_2) {
+ label = 33;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 33:
+ HEAPF64[$x104 >> 3] = $24;
+ label = 35;
+ break;
+ case 34:
+ HEAPF64[$x1 >> 3] = $24;
+ label = 35;
+ break;
+ case 35:
+ $y113_2 = $cp + 40 | 0;
+ $27 = +HEAPF64[$y113_2 >> 3];
+ $28 = +HEAPF64[$y115 >> 3];
+ $cmp116_2 = $27 > $28;
+ if ($cmp116_2) {
+ label = 38;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $29 = +HEAPF64[$y126 >> 3];
+ $cmp127_2 = $27 < $29;
+ if ($cmp127_2) {
+ label = 37;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 37:
+ HEAPF64[$y126 >> 3] = $27;
+ label = 39;
+ break;
+ case 38:
+ HEAPF64[$y115 >> 3] = $27;
+ label = 39;
+ break;
+ case 39:
+ $x92_3 = $cp + 48 | 0;
+ $30 = +HEAPF64[$x92_3 >> 3];
+ $31 = +HEAPF64[$x1 >> 3];
+ $cmp95_3 = $30 > $31;
+ if ($cmp95_3) {
+ label = 42;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $32 = +HEAPF64[$x104 >> 3];
+ $cmp105_3 = $30 < $32;
+ if ($cmp105_3) {
+ label = 41;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 41:
+ HEAPF64[$x104 >> 3] = $30;
+ label = 43;
+ break;
+ case 42:
+ HEAPF64[$x1 >> 3] = $30;
+ label = 43;
+ break;
+ case 43:
+ $y113_3 = $cp + 56 | 0;
+ $33 = +HEAPF64[$y113_3 >> 3];
+ $34 = +HEAPF64[$y115 >> 3];
+ $cmp116_3 = $33 > $34;
+ if ($cmp116_3) {
+ label = 46;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $35 = +HEAPF64[$y126 >> 3];
+ $cmp127_3 = $33 < $35;
+ if ($cmp127_3) {
+ label = 45;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 45:
+ HEAPF64[$y126 >> 3] = $33;
+ label = 23;
+ break;
+ case 46:
+ HEAPF64[$y115 >> 3] = $33;
+ label = 23;
+ break;
+ }
+}
+function _check_control_points($cp) {
+ $cp = $cp | 0;
+ var $arrayidx1 = 0, $call = 0.0;
+ $arrayidx1 = $cp + 48 | 0;
+ $call = +_ptToLine2($cp, $arrayidx1, $cp + 16 | 0);
+ return $call < 4.0 & +_ptToLine2($cp, $arrayidx1, $cp + 32 | 0) < 4.0 & 1 | 0;
+}
+function _emit_graph($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $flags1 = 0, $0 = 0, $zoom = 0, $1 = 0.0, $x = 0, $2 = 0.0, $mul = 0.0, $div = 0.0, $x2 = 0, $3 = 0.0, $y = 0, $4 = 0.0, $mul5 = 0.0, $div6 = 0.0, $y8 = 0, $5 = 0.0, $div11 = 0.0, $x12 = 0, $6 = 0.0, $div15 = 0.0, $y17 = 0, $7 = 0, $and = 0, $8 = 0, $9 = 0, $10 = 0, $mul22 = 0.0, $rotation = 0, $11 = 0, $tobool23 = 0, $width = 0, $12 = 0, $conv = 0.0, $13 = 0.0, $div27 = 0.0, $y28 = 0, $height = 0, $14 = 0, $conv29 = 0.0, $15 = 0.0, $div32 = 0.0, $x34 = 0, $16 = 0.0, $div39 = 0.0, $x41 = 0, $height42 = 0, $17 = 0, $conv43 = 0.0, $18 = 0.0, $div46 = 0.0, $y48 = 0, $19 = 0, $call = 0, $call50 = 0, $and51 = 0, $tobool52 = 0, $20 = 0, $call55 = 0, $tobool5650 = 0, $n_0_in51 = 0, $state = 0, $21 = 0, $call57 = 0, $tobool56 = 0, $call5948 = 0, $tobool6049 = 0, $numLayers = 0, $22 = 0, $cmp = 0, $call6646 = 0, $tobool6747 = 0, $call66 = 0, $tobool67 = 0, $23 = 0, $cmp72 = 0, $call59 = 0, $tobool60 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $flags1 = $job + 152 | 0;
+ $0 = HEAP32[$flags1 >> 2] | 0;
+ $zoom = $job + 352 | 0;
+ $1 = +HEAPF64[$zoom >> 3];
+ $x = $job + 432 | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $mul = $1 * $2;
+ $div = $mul / 72.0;
+ $x2 = $job + 488 | 0;
+ HEAPF64[$x2 >> 3] = $div;
+ $3 = +HEAPF64[$zoom >> 3];
+ $y = $job + 440 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $mul5 = $3 * $4;
+ $div6 = $mul5 / 72.0;
+ $y8 = $job + 496 | 0;
+ HEAPF64[$y8 >> 3] = $div6;
+ $5 = +HEAPF64[$x >> 3];
+ $div11 = $5 / 72.0;
+ $x12 = $job + 520 | 0;
+ HEAPF64[$x12 >> 3] = $div11;
+ $6 = +HEAPF64[$y >> 3];
+ $div15 = $6 / 72.0;
+ $y17 = $job + 528 | 0;
+ HEAPF64[$y17 >> 3] = $div15;
+ $7 = HEAP32[$flags1 >> 2] | 0;
+ $and = $7 & 4096;
+ $8 = HEAP32[41182] | 0;
+ $9 = $and | $8;
+ $10 = ($9 | 0) == 0;
+ if ($10) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $mul22 = $div15 * -1.0;
+ HEAPF64[$y17 >> 3] = $mul22;
+ label = 4;
+ break;
+ case 4:
+ $rotation = $job + 360 | 0;
+ $11 = HEAP32[$rotation >> 2] | 0;
+ $tobool23 = ($11 | 0) == 0;
+ $width = $job + 448 | 0;
+ $12 = HEAP32[$width >> 2] | 0;
+ $conv = +($12 >>> 0 >>> 0);
+ if ($tobool23) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $13 = +HEAPF64[$y8 >> 3];
+ $div27 = $conv / $13;
+ $y28 = $job + 376 | 0;
+ HEAPF64[$y28 >> 3] = $div27;
+ $height = $job + 452 | 0;
+ $14 = HEAP32[$height >> 2] | 0;
+ $conv29 = +($14 >>> 0 >>> 0);
+ $15 = +HEAPF64[$x2 >> 3];
+ $div32 = $conv29 / $15;
+ $x34 = $job + 368 | 0;
+ HEAPF64[$x34 >> 3] = $div32;
+ label = 7;
+ break;
+ case 6:
+ $16 = +HEAPF64[$x2 >> 3];
+ $div39 = $conv / $16;
+ $x41 = $job + 368 | 0;
+ HEAPF64[$x41 >> 3] = $div39;
+ $height42 = $job + 452 | 0;
+ $17 = HEAP32[$height42 >> 2] | 0;
+ $conv43 = +($17 >>> 0 >>> 0);
+ $18 = +HEAPF64[$y8 >> 3];
+ $div46 = $conv43 / $18;
+ $y48 = $job + 376 | 0;
+ HEAPF64[$y48 >> 3] = $div46;
+ label = 7;
+ break;
+ case 7:
+ $19 = $g | 0;
+ $call = _agfindattr($19, 138904) | 0;
+ $call50 = _late_string($19, $call, 136112) | 0;
+ _gvrender_comment($job, $call50);
+ _emit_begin_graph($job, $g);
+ $and51 = $0 & 2;
+ $tobool52 = ($and51 | 0) == 0;
+ if ($tobool52) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _emit_colors($job, $g);
+ label = 9;
+ break;
+ case 9:
+ $20 = $g;
+ $call55 = _agfstnode($20) | 0;
+ $tobool5650 = ($call55 | 0) == 0;
+ if ($tobool5650) {
+ label = 11;
+ break;
+ } else {
+ $n_0_in51 = $call55;
+ label = 10;
+ break;
+ }
+ case 10:
+ $state = $n_0_in51 + 132 | 0;
+ $21 = $state;
+ HEAP8[$21] = 0;
+ $call57 = _agnxtnode($20, $n_0_in51) | 0;
+ $tobool56 = ($call57 | 0) == 0;
+ if ($tobool56) {
+ label = 11;
+ break;
+ } else {
+ $n_0_in51 = $call57;
+ label = 10;
+ break;
+ }
+ case 11:
+ _firstlayer($job);
+ $call5948 = _validlayer($job) | 0;
+ $tobool6049 = $call5948 << 24 >> 24 == 0;
+ if ($tobool6049) {
+ label = 20;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $numLayers = $job + 156 | 0;
+ label = 13;
+ break;
+ case 13:
+ $22 = HEAP32[$numLayers >> 2] | 0;
+ $cmp = ($22 | 0) > 1;
+ if ($cmp) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ _gvrender_begin_layer($job);
+ label = 15;
+ break;
+ case 15:
+ _firstpage($job);
+ $call6646 = _validpage($job) | 0;
+ $tobool6747 = $call6646 << 24 >> 24 == 0;
+ if ($tobool6747) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ _emit_page($job, $g);
+ _nextpage($job);
+ $call66 = _validpage($job) | 0;
+ $tobool67 = $call66 << 24 >> 24 == 0;
+ if ($tobool67) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 17:
+ $23 = HEAP32[$numLayers >> 2] | 0;
+ $cmp72 = ($23 | 0) > 1;
+ if ($cmp72) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ _gvrender_end_layer($job);
+ label = 19;
+ break;
+ case 19:
+ _nextlayer($job);
+ $call59 = _validlayer($job) | 0;
+ $tobool60 = $call59 << 24 >> 24 == 0;
+ if ($tobool60) {
+ label = 20;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 20:
+ _emit_end_graph($job);
+ return;
+ }
+}
+function _emit_begin_graph($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $call = 0;
+ $call = _push_obj_state($job) | 0;
+ HEAP32[$call + 4 >> 2] = 0;
+ HEAP32[$call + 8 >> 2] = $g;
+ HEAP32[$call + 12 >> 2] = 0;
+ _initObjMapData($job, HEAP32[$g + 52 >> 2] | 0, $g | 0);
+ _gvrender_begin_graph($job, $g);
+ return;
+}
+function _emit_colors($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $cmp = 0, $1 = 0, $tobool = 0, $call1 = 0, $cmp2 = 0, $2 = 0, $tobool7 = 0, $3 = 0, $call10 = 0, $tobool1147 = 0, $n_0_in48 = 0, $4 = 0, $call12 = 0, $cmp13 = 0, $5 = 0, $tobool18 = 0, $call21 = 0, $cmp22 = 0, $6 = 0, $tobool27 = 0, $call30 = 0, $cmp31 = 0, $7 = 0, $tobool36 = 0, $call39 = 0, $tobool4145 = 0, $e_0_in46 = 0, $8 = 0, $call43 = 0, $cmp44 = 0, $9 = 0, $tobool49 = 0, $call51 = 0, $tobool52 = 0, $call54 = 0, $call55 = 0, $tobool5743 = 0, $str_044 = 0, $10 = 0, $tobool60 = 0, $call63 = 0, $tobool57 = 0, $call66 = 0, $cmp67 = 0, $11 = 0, $tobool72 = 0, $call76 = 0, $tobool41 = 0, $call79 = 0, $tobool11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _gvrender_set_fillcolor($job, 117192);
+ $0 = $g | 0;
+ $call = _agget($0, 118488) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$call] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _gvrender_set_fillcolor($job, $call);
+ label = 5;
+ break;
+ case 5:
+ $call1 = _agget($0, 159088) | 0;
+ $cmp2 = ($call1 | 0) == 0;
+ if ($cmp2) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $2 = HEAP8[$call1] | 0;
+ $tobool7 = $2 << 24 >> 24 == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _gvrender_set_pencolor($job, $call1);
+ label = 8;
+ break;
+ case 8:
+ _emit_cluster_colors($job, $g);
+ $3 = $g;
+ $call10 = _agfstnode($3) | 0;
+ $tobool1147 = ($call10 | 0) == 0;
+ if ($tobool1147) {
+ label = 33;
+ break;
+ } else {
+ $n_0_in48 = $call10;
+ label = 9;
+ break;
+ }
+ case 9:
+ $4 = $n_0_in48 | 0;
+ $call12 = _agget($4, 120080) | 0;
+ $cmp13 = ($call12 | 0) == 0;
+ if ($cmp13) {
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $5 = HEAP8[$call12] | 0;
+ $tobool18 = $5 << 24 >> 24 == 0;
+ if ($tobool18) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ _gvrender_set_pencolor($job, $call12);
+ label = 12;
+ break;
+ case 12:
+ $call21 = _agget($4, 118936) | 0;
+ $cmp22 = ($call21 | 0) == 0;
+ if ($cmp22) {
+ label = 15;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $6 = HEAP8[$call21] | 0;
+ $tobool27 = $6 << 24 >> 24 == 0;
+ if ($tobool27) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ _gvrender_set_fillcolor($job, $call21);
+ label = 15;
+ break;
+ case 15:
+ $call30 = _agget($4, 159088) | 0;
+ $cmp31 = ($call30 | 0) == 0;
+ if ($cmp31) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $7 = HEAP8[$call30] | 0;
+ $tobool36 = $7 << 24 >> 24 == 0;
+ if ($tobool36) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ _gvrender_set_pencolor($job, $call30);
+ label = 18;
+ break;
+ case 18:
+ $call39 = _agfstout($3, $n_0_in48) | 0;
+ $tobool4145 = ($call39 | 0) == 0;
+ if ($tobool4145) {
+ label = 32;
+ break;
+ } else {
+ $e_0_in46 = $call39;
+ label = 19;
+ break;
+ }
+ case 19:
+ $8 = $e_0_in46 | 0;
+ $call43 = _agget($8, 120080) | 0;
+ $cmp44 = ($call43 | 0) == 0;
+ if ($cmp44) {
+ label = 28;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $9 = HEAP8[$call43] | 0;
+ $tobool49 = $9 << 24 >> 24 == 0;
+ if ($tobool49) {
+ label = 28;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $call51 = _strchr($call43 | 0, 58) | 0;
+ $tobool52 = ($call51 | 0) == 0;
+ if ($tobool52) {
+ label = 27;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $call54 = _strdup($call43 | 0) | 0;
+ $call55 = _strtok($call54 | 0, 98688) | 0;
+ $tobool5743 = ($call55 | 0) == 0;
+ if ($tobool5743) {
+ label = 26;
+ break;
+ } else {
+ $str_044 = $call55;
+ label = 23;
+ break;
+ }
+ case 23:
+ $10 = HEAP8[$str_044] | 0;
+ $tobool60 = $10 << 24 >> 24 == 0;
+ if ($tobool60) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ _gvrender_set_pencolor($job, $str_044);
+ label = 25;
+ break;
+ case 25:
+ $call63 = _strtok(0, 98688) | 0;
+ $tobool57 = ($call63 | 0) == 0;
+ if ($tobool57) {
+ label = 26;
+ break;
+ } else {
+ $str_044 = $call63;
+ label = 23;
+ break;
+ }
+ case 26:
+ _free($call54);
+ label = 28;
+ break;
+ case 27:
+ _gvrender_set_pencolor($job, $call43);
+ label = 28;
+ break;
+ case 28:
+ $call66 = _agget($8, 159088) | 0;
+ $cmp67 = ($call66 | 0) == 0;
+ if ($cmp67) {
+ label = 31;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $11 = HEAP8[$call66] | 0;
+ $tobool72 = $11 << 24 >> 24 == 0;
+ if ($tobool72) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ _gvrender_set_pencolor($job, $call66);
+ label = 31;
+ break;
+ case 31:
+ $call76 = _agnxtout($3, $e_0_in46) | 0;
+ $tobool41 = ($call76 | 0) == 0;
+ if ($tobool41) {
+ label = 32;
+ break;
+ } else {
+ $e_0_in46 = $call76;
+ label = 19;
+ break;
+ }
+ case 32:
+ $call79 = _agnxtnode($3, $n_0_in48) | 0;
+ $tobool11 = ($call79 | 0) == 0;
+ if ($tobool11) {
+ label = 33;
+ break;
+ } else {
+ $n_0_in48 = $call79;
+ label = 9;
+ break;
+ }
+ case 33:
+ return;
+ }
+}
+function _firstlayer($job) {
+ $job = $job | 0;
+ var $gvc = 0, $0 = 0, $numLayers = 0, $1 = 0, $numLayers1 = 0, $cmp = 0, $flags = 0, $2 = 0, $and = 0, $tobool = 0, $output_langname = 0, $3 = 0, $call = 0, $layerNum = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc = $job | 0;
+ $0 = HEAP32[$gvc >> 2] | 0;
+ $numLayers = $0 + 284 | 0;
+ $1 = HEAP32[$numLayers >> 2] | 0;
+ $numLayers1 = $job + 156 | 0;
+ HEAP32[$numLayers1 >> 2] = $1;
+ $cmp = ($1 | 0) > 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $flags = $job + 152 | 0;
+ $2 = HEAP32[$flags >> 2] | 0;
+ $and = $2 & 64;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $output_langname = $job + 52 | 0;
+ $3 = HEAP32[$output_langname >> 2] | 0;
+ $call = _agerr(0, 159544, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $3, tempInt) | 0) | 0;
+ HEAP32[$numLayers1 >> 2] = 1;
+ label = 5;
+ break;
+ case 5:
+ $layerNum = $job + 160 | 0;
+ HEAP32[$layerNum >> 2] = 1;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_page($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $obj1 = 0, $0 = 0, $flags2 = 0, $1 = 0, $2 = 0, $call = 0, $and = 0, $tobool = 0, $url = 0, $3 = 0, $tobool3 = 0, $4 = 0, $5 = 0, $6 = 0, $_mask53 = 0, $tobool4 = 0, $and5 = 0, $tobool6 = 0, $and8 = 0, $tobool9 = 0, $url_map_shape = 0, $7 = 0, $8 = 0, $9 = 0, $10 = 0, $11 = 0, $mul = 0, $call12 = 0, $12 = 0, $pageBox = 0, $13 = 0, $arrayidx13 = 0, $UR = 0, $14 = 0, $nump_1 = 0, $p_0 = 0, $and20 = 0, $tobool21 = 0, $call23 = 0, $url_map_p = 0, $url_map_n = 0, $and26 = 0, $tobool27 = 0, $label = 0, $15 = 0, $tobool29 = 0, $text = 0, $16 = 0, $label31 = 0, $and33 = 0, $tobool34 = 0, $url36 = 0, $17 = 0, $tobool37 = 0, $18 = 0, $19 = 0, $20 = 0, $_mask = 0, $tobool42 = 0, $clip = 0, $21 = 0, $tooltip = 0, $22 = 0, $target = 0, $23 = 0, $id = 0, $24 = 0, $numLayers = 0, $25 = 0, $cmp = 0, $label49 = 0, $26 = 0, $tobool50 = 0, $url58 = 0, $27 = 0, $tobool59 = 0, $28 = 0, $29 = 0, $30 = 0, $_mask52 = 0, $tobool64 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $flags2 = $job + 152 | 0;
+ $1 = HEAP32[$flags2 >> 2] | 0;
+ $2 = $g | 0;
+ $call = _agget($2, 133704) | 0;
+ _setColorScheme($call);
+ _setup_page($job);
+ _gvrender_begin_page($job);
+ _gvrender_set_pencolor($job, 117856);
+ _gvrender_set_fillcolor($job, 117192);
+ $and = $1 & 4259840;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $url = $0 + 160 | 0;
+ $3 = HEAP32[$url >> 2] | 0;
+ $tobool3 = ($3 | 0) == 0;
+ if ($tobool3) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $4 = $0 + 212 | 0;
+ $5 = $4;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $_mask53 = $6 & 1;
+ $tobool4 = ($_mask53 | 0) == 0;
+ if ($tobool4) {
+ label = 11;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $and5 = $1 & 655360;
+ $tobool6 = ($and5 | 0) == 0;
+ if ($tobool6) {
+ $p_0 = 0;
+ $nump_1 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $and8 = $1 & 131072;
+ $tobool9 = ($and8 | 0) == 0;
+ $url_map_shape = $0 + 216 | 0;
+ $7 = $and8 >>> 16;
+ $8 = $7 ^ 2;
+ $9 = $and8 >>> 16;
+ $10 = $9 ^ 2;
+ $11 = $10 + 2 | 0;
+ HEAP32[$url_map_shape >> 2] = $8;
+ $mul = $11 << 4;
+ $call12 = _zmalloc($mul) | 0;
+ $12 = $call12;
+ $pageBox = $job + 288 | 0;
+ $13 = $pageBox;
+ HEAP32[$call12 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$call12 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$call12 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$call12 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ $arrayidx13 = $call12 + 16 | 0;
+ $UR = $job + 304 | 0;
+ $14 = $UR;
+ HEAP32[$arrayidx13 >> 2] = HEAP32[$14 >> 2] | 0;
+ HEAP32[$arrayidx13 + 4 >> 2] = HEAP32[$14 + 4 >> 2] | 0;
+ HEAP32[$arrayidx13 + 8 >> 2] = HEAP32[$14 + 8 >> 2] | 0;
+ HEAP32[$arrayidx13 + 12 >> 2] = HEAP32[$14 + 12 >> 2] | 0;
+ if ($tobool9) {
+ label = 7;
+ break;
+ } else {
+ $p_0 = $12;
+ $nump_1 = $11;
+ label = 8;
+ break;
+ }
+ case 7:
+ _rect2poly($12);
+ $p_0 = $12;
+ $nump_1 = $11;
+ label = 8;
+ break;
+ case 8:
+ $and20 = $1 & 8192;
+ $tobool21 = ($and20 | 0) == 0;
+ if ($tobool21) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $call23 = _gvrender_ptf_A($job, $p_0, $p_0, $nump_1) | 0;
+ label = 10;
+ break;
+ case 10:
+ $url_map_p = $0 + 224 | 0;
+ HEAP32[$url_map_p >> 2] = $p_0;
+ $url_map_n = $0 + 220 | 0;
+ HEAP32[$url_map_n >> 2] = $nump_1;
+ label = 11;
+ break;
+ case 11:
+ $and26 = $1 & 32768;
+ $tobool27 = ($and26 | 0) == 0;
+ if ($tobool27) {
+ label = 14;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $label = $g + 52 | 0;
+ $15 = HEAP32[$label >> 2] | 0;
+ $tobool29 = ($15 | 0) == 0;
+ if ($tobool29) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $text = $15 | 0;
+ $16 = HEAP32[$text >> 2] | 0;
+ $label31 = $0 + 144 | 0;
+ HEAP32[$label31 >> 2] = $16;
+ label = 14;
+ break;
+ case 14:
+ $and33 = $1 & 4;
+ $tobool34 = ($and33 | 0) != 0;
+ if ($tobool34) {
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $url36 = $0 + 160 | 0;
+ $17 = HEAP32[$url36 >> 2] | 0;
+ $tobool37 = ($17 | 0) == 0;
+ if ($tobool37) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $18 = $0 + 212 | 0;
+ $19 = $18;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $_mask = $20 & 1;
+ $tobool42 = ($_mask | 0) == 0;
+ if ($tobool42) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $clip = $job + 256 | 0;
+ _emit_map_rect($job, $clip);
+ $21 = HEAP32[$url36 >> 2] | 0;
+ $tooltip = $0 + 180 | 0;
+ $22 = HEAP32[$tooltip >> 2] | 0;
+ $target = $0 + 196 | 0;
+ $23 = HEAP32[$target >> 2] | 0;
+ $id = $0 + 164 | 0;
+ $24 = HEAP32[$id >> 2] | 0;
+ _gvrender_begin_anchor($job, $21, $22, $23, $24);
+ label = 18;
+ break;
+ case 18:
+ $numLayers = $job + 156 | 0;
+ $25 = HEAP32[$numLayers >> 2] | 0;
+ $cmp = ($25 | 0) == 1;
+ if ($cmp) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ _emit_background($job, $g);
+ label = 20;
+ break;
+ case 20:
+ $label49 = $g + 52 | 0;
+ $26 = HEAP32[$label49 >> 2] | 0;
+ $tobool50 = ($26 | 0) == 0;
+ if ($tobool50) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ _emit_label($job, 4, $26);
+ label = 22;
+ break;
+ case 22:
+ if ($tobool34) {
+ label = 26;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $url58 = $0 + 160 | 0;
+ $27 = HEAP32[$url58 >> 2] | 0;
+ $tobool59 = ($27 | 0) == 0;
+ if ($tobool59) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $28 = $0 + 212 | 0;
+ $29 = $28;
+ $30 = HEAP32[$29 >> 2] | 0;
+ $_mask52 = $30 & 1;
+ $tobool64 = ($_mask52 | 0) == 0;
+ if ($tobool64) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ _gvrender_end_anchor($job);
+ label = 26;
+ break;
+ case 26:
+ _emit_view($job, $g, $1);
+ _gvrender_end_page($job);
+ return;
+ }
+}
+function _nextpage($job) {
+ $job = $job | 0;
+ var $tmp = 0, $tmpcast = 0, $tmp13 = 0, $tmpcast11 = 0, $pagesArrayElem = 0, $pagesArrayMinor = 0, $0 = 0, $ld$0$0 = 0, $1$0 = 0, $ld$1$1 = 0, $1$1 = 0, $st$2$0 = 0, $st$3$1 = 0, $call = 0, $cmp = 0, $pagesArrayMajor = 0, $y = 0, $2 = 0, $tobool = 0, $x = 0, $3 = 0, $x5 = 0, $y7 = 0, $4 = 0, $y9 = 0, $ld$4$0 = 0, $5$0 = 0, $ld$5$1 = 0, $5$1 = 0, $st$6$0 = 0, $st$7$1 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmpcast = $tmp;
+ $tmp13 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast11 = $tmp13;
+ $pagesArrayElem = $job + 196 | 0;
+ $pagesArrayMinor = $job + 188 | 0;
+ _add_point($tmpcast, $pagesArrayElem, $pagesArrayMinor);
+ $0 = $pagesArrayElem;
+ $ld$0$0 = $tmp | 0;
+ $1$0 = HEAP32[$ld$0$0 >> 2] | 0;
+ $ld$1$1 = $tmp + 4 | 0;
+ $1$1 = HEAP32[$ld$1$1 >> 2] | 0;
+ $st$2$0 = $0 | 0;
+ HEAP32[$st$2$0 >> 2] = $1$0;
+ $st$3$1 = $0 + 4 | 0;
+ HEAP32[$st$3$1 >> 2] = $1$1;
+ $call = _validpage($job) | 0;
+ $cmp = $call << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $pagesArrayMajor = $job + 180 | 0;
+ $y = $job + 184 | 0;
+ $2 = HEAP32[$y >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $x = $job + 172 | 0;
+ $3 = HEAP32[$x >> 2] | 0;
+ $x5 = $pagesArrayElem | 0;
+ HEAP32[$x5 >> 2] = $3;
+ label = 6;
+ break;
+ case 5:
+ $y7 = $job + 176 | 0;
+ $4 = HEAP32[$y7 >> 2] | 0;
+ $y9 = $job + 200 | 0;
+ HEAP32[$y9 >> 2] = $4;
+ label = 6;
+ break;
+ case 6:
+ _add_point($tmpcast11, $pagesArrayElem, $pagesArrayMajor);
+ $ld$4$0 = $tmp13 | 0;
+ $5$0 = HEAP32[$ld$4$0 >> 2] | 0;
+ $ld$5$1 = $tmp13 + 4 | 0;
+ $5$1 = HEAP32[$ld$5$1 >> 2] | 0;
+ $st$6$0 = $0 | 0;
+ HEAP32[$st$6$0 >> 2] = $5$0;
+ $st$7$1 = $0 + 4 | 0;
+ HEAP32[$st$7$1 >> 2] = $5$1;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_end_graph($job) {
+ $job = $job | 0;
+ _gvrender_end_graph($job);
+ _pop_obj_state($job);
+ return;
+}
+function _emit_once($str) {
+ $str = $str | 0;
+ var $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $searchf = 0, $4 = 0, $call1 = 0, $tobool = 0, $5 = 0, $searchf3 = 0, $6 = 0, $call4 = 0, $call5 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[1014] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[41978] | 0;
+ $2 = $1;
+ $call = _dtopen(4064, $2) | 0;
+ HEAP32[1014] = $call;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[1014] | 0;
+ $searchf = $3 | 0;
+ $4 = HEAP32[$searchf >> 2] | 0;
+ $call1 = FUNCTION_TABLE_iiii[$4 & 1023]($3, $str, 4) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[1014] | 0;
+ $searchf3 = $5 | 0;
+ $6 = HEAP32[$searchf3 >> 2] | 0;
+ $call4 = _agstrdup($str) | 0;
+ $call5 = FUNCTION_TABLE_iiii[$6 & 1023]($5, $call4, 1) | 0;
+ $retval_0 = 1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _emit_once_reset() {
+ var $0 = 0, $tobool = 0, $call = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[1014] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _dtclose($0) | 0;
+ HEAP32[1014] = 0;
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _emit_clusters($job, $g, $flags) {
+ $job = $job | 0;
+ $g = $g | 0;
+ $flags = $flags | 0;
+ var $istyle = 0, $AF = 0, $n_cluster = 0, $0 = 0, $cmp103 = 0, $clust = 0, $and = 0, $tobool = 0, $obj6 = 0, $and186 = 0, $tobool187 = 0, $arrayidx125 = 0, $1 = 0, $arrayidx128 = 0, $2 = 0, $x = 0, $x133 = 0, $y = 0, $y136 = 0, $x138 = 0, $x140 = 0, $y142 = 0, $y144 = 0, $c_0104 = 0, $3 = 0, $arrayidx = 0, $4 = 0, $call = 0, $cmp2 = 0, $5 = 0, $url = 0, $6 = 0, $tobool7 = 0, $7 = 0, $8 = 0, $9 = 0, $_mask = 0, $tobool8 = 0, $10 = 0, $11 = 0, $call9 = 0, $_not = 0, $brmerge = 0, $bb = 0, $12 = 0, $tooltip = 0, $13 = 0, $target = 0, $14 = 0, $id = 0, $15 = 0, $call17 = 0, $tobool18 = 0, $16 = 0, $and20 = 0, $filled_0 = 0, $gui_state = 0, $17 = 0, $conv26 = 0, $and27 = 0, $tobool28 = 0, $18 = 0, $call30 = 0, $19 = 0, $call31 = 0, $and35 = 0, $tobool36 = 0, $20 = 0, $call38 = 0, $21 = 0, $call39 = 0, $and44 = 0, $tobool45 = 0, $22 = 0, $call47 = 0, $23 = 0, $call48 = 0, $and53 = 0, $tobool54 = 0, $24 = 0, $call56 = 0, $25 = 0, $call57 = 0, $call59 = 0, $cmp60 = 0, $26 = 0, $tobool65 = 0, $_call59 = 0, $pencolor_0 = 0, $call68 = 0, $cmp69 = 0, $27 = 0, $tobool74 = 0, $pencolor_0_call68 = 0, $pencolor_1 = 0, $call77 = 0, $cmp78 = 0, $28 = 0, $tobool83 = 0, $pencolor_0_call77 = 0, $fillcolor_1 = 0, $tobool86 = 0, $call88 = 0, $cmp89 = 0, $29 = 0, $tobool94 = 0, $fillcolor_1_call88 = 0, $filled_0_ = 0, $pencolor_2 = 0, $fillcolor_2 = 0, $filled_1 = 0, $tobool101 = 0, $_pencolor_2 = 0, $tobool104 = 0, $fillcolor_3 = 0, $30 = 0, $tobool107 = 0, $index = 0, $31 = 0, $call109 = 0, $tobool110 = 0, $32 = 0, $tobool114 = 0, $call116 = 0.0, $33 = 0, $and118 = 0, $tobool119 = 0, $34 = 0, $call121 = 0, $35 = 0, $36 = 0, $bb127 = 0, $37 = 0, $UR = 0, $38 = 0, $39 = 0.0, $40 = 0.0, $41 = 0.0, $42 = 0.0, $43 = 0, $and145 = 0, $44 = 0, $call148 = 0, $tobool149 = 0, $bb152 = 0, $conv153 = 0, $tobool155 = 0, $cmp159 = 0, $bb164 = 0, $conv165 = 0, $label = 0, $45 = 0, $tobool170 = 0, $bb179 = 0, $46 = 0, $tooltip181 = 0, $47 = 0, $target182 = 0, $48 = 0, $id183 = 0, $49 = 0, $50 = 0, $call189 = 0, $tobool191101 = 0, $n_0_in102 = 0, $n_0 = 0, $call193 = 0, $tobool19599 = 0, $e_0_in100 = 0, $e_0 = 0, $call197 = 0, $tobool195 = 0, $call199 = 0, $tobool191 = 0, $inc = 0, $51 = 0, $cmp = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 72 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $istyle = __stackBase__ | 0;
+ $AF = __stackBase__ + 8 | 0;
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp103 = ($0 | 0) < 1;
+ if ($cmp103) {
+ label = 57;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $and = $flags & 4;
+ $tobool = ($and | 0) != 0;
+ $obj6 = $job + 16 | 0;
+ $and186 = $flags & 8;
+ $tobool187 = ($and186 | 0) == 0;
+ $arrayidx125 = $AF | 0;
+ $1 = $AF;
+ $arrayidx128 = $AF + 32 | 0;
+ $2 = $arrayidx128;
+ $x = $arrayidx128 | 0;
+ $x133 = $AF + 16 | 0;
+ $y = $AF + 8 | 0;
+ $y136 = $AF + 24 | 0;
+ $x138 = $AF | 0;
+ $x140 = $AF + 48 | 0;
+ $y142 = $AF + 40 | 0;
+ $y144 = $AF + 56 | 0;
+ $c_0104 = 1;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $3 + ($c_0104 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $call = _clust_in_layer($job, $4) | 0;
+ $cmp2 = $call << 24 >> 24 == 0;
+ if ($cmp2) {
+ label = 56;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ _emit_clusters($job, $4, $flags);
+ label = 7;
+ break;
+ case 7:
+ _emit_begin_cluster($job, $4);
+ $5 = HEAP32[$obj6 >> 2] | 0;
+ $url = $5 + 160 | 0;
+ $6 = HEAP32[$url >> 2] | 0;
+ $tobool7 = ($6 | 0) == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ $10 = 1;
+ label = 9;
+ break;
+ }
+ case 8:
+ $7 = $5 + 212 | 0;
+ $8 = $7;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $_mask = $9 & 1;
+ $tobool8 = ($_mask | 0) != 0;
+ $10 = $tobool8;
+ label = 9;
+ break;
+ case 9:
+ $11 = $4 | 0;
+ $call9 = _agget($11, 133704) | 0;
+ _setColorScheme($call9);
+ $_not = $10 ^ 1;
+ $brmerge = $tobool | $_not;
+ if ($brmerge) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $bb = $4 + 56 | 0;
+ _emit_map_rect($job, $bb);
+ $12 = HEAP32[$url >> 2] | 0;
+ $tooltip = $5 + 180 | 0;
+ $13 = HEAP32[$tooltip >> 2] | 0;
+ $target = $5 + 196 | 0;
+ $14 = HEAP32[$target >> 2] | 0;
+ $id = $5 + 164 | 0;
+ $15 = HEAP32[$id >> 2] | 0;
+ _gvrender_begin_anchor($job, $12, $13, $14, $15);
+ label = 11;
+ break;
+ case 11:
+ HEAP32[$istyle >> 2] = 0;
+ $call17 = _checkClusterStyle($4, $istyle) | 0;
+ $tobool18 = ($call17 | 0) == 0;
+ if ($tobool18) {
+ $filled_0 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _gvrender_set_style($job, $call17);
+ $16 = HEAP32[$istyle >> 2] | 0;
+ $and20 = $16 & 1;
+ $filled_0 = $and20;
+ label = 13;
+ break;
+ case 13:
+ $gui_state = $4 + 152 | 0;
+ $17 = HEAP8[$gui_state] | 0;
+ $conv26 = $17 & 255;
+ $and27 = $conv26 & 1;
+ $tobool28 = ($and27 | 0) == 0;
+ if ($tobool28) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $18 = HEAP32[41872] | 0;
+ $call30 = _late_nnstring($11, $18, 131512) | 0;
+ $19 = HEAP32[41874] | 0;
+ $call31 = _late_nnstring($11, $19, 130536) | 0;
+ $filled_1 = 1;
+ $fillcolor_2 = $call31;
+ $pencolor_2 = $call30;
+ label = 30;
+ break;
+ case 15:
+ $and35 = $conv26 & 2;
+ $tobool36 = ($and35 | 0) == 0;
+ if ($tobool36) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $20 = HEAP32[41872] | 0;
+ $call38 = _late_nnstring($11, $20, 128656) | 0;
+ $21 = HEAP32[41874] | 0;
+ $call39 = _late_nnstring($11, $21, 126080) | 0;
+ $filled_1 = 1;
+ $fillcolor_2 = $call39;
+ $pencolor_2 = $call38;
+ label = 30;
+ break;
+ case 17:
+ $and44 = $conv26 & 8;
+ $tobool45 = ($and44 | 0) == 0;
+ if ($tobool45) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $22 = HEAP32[41868] | 0;
+ $call47 = _late_nnstring($11, $22, 122664) | 0;
+ $23 = HEAP32[41870] | 0;
+ $call48 = _late_nnstring($11, $23, 121984) | 0;
+ $filled_1 = 1;
+ $fillcolor_2 = $call48;
+ $pencolor_2 = $call47;
+ label = 30;
+ break;
+ case 19:
+ $and53 = $conv26 & 4;
+ $tobool54 = ($and53 | 0) == 0;
+ if ($tobool54) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $24 = HEAP32[41858] | 0;
+ $call56 = _late_nnstring($11, $24, 121456) | 0;
+ $25 = HEAP32[41860] | 0;
+ $call57 = _late_nnstring($11, $25, 120728) | 0;
+ $filled_1 = 1;
+ $fillcolor_2 = $call57;
+ $pencolor_2 = $call56;
+ label = 30;
+ break;
+ case 21:
+ $call59 = _agget($11, 120080) | 0;
+ $cmp60 = ($call59 | 0) == 0;
+ if ($cmp60) {
+ $pencolor_0 = 0;
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $26 = HEAP8[$call59] | 0;
+ $tobool65 = $26 << 24 >> 24 == 0;
+ $_call59 = $tobool65 ? 0 : $call59;
+ $pencolor_0 = $_call59;
+ label = 23;
+ break;
+ case 23:
+ $call68 = _agget($11, 119480) | 0;
+ $cmp69 = ($call68 | 0) == 0;
+ if ($cmp69) {
+ $pencolor_1 = $pencolor_0;
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $27 = HEAP8[$call68] | 0;
+ $tobool74 = $27 << 24 >> 24 == 0;
+ $pencolor_0_call68 = $tobool74 ? $pencolor_0 : $call68;
+ $pencolor_1 = $pencolor_0_call68;
+ label = 25;
+ break;
+ case 25:
+ $call77 = _agget($11, 118936) | 0;
+ $cmp78 = ($call77 | 0) == 0;
+ if ($cmp78) {
+ $fillcolor_1 = $pencolor_0;
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $28 = HEAP8[$call77] | 0;
+ $tobool83 = $28 << 24 >> 24 == 0;
+ $pencolor_0_call77 = $tobool83 ? $pencolor_0 : $call77;
+ $fillcolor_1 = $pencolor_0_call77;
+ label = 27;
+ break;
+ case 27:
+ $tobool86 = ($filled_0 | 0) == 0;
+ if ($tobool86) {
+ label = 28;
+ break;
+ } else {
+ $filled_1 = $filled_0;
+ $fillcolor_2 = $fillcolor_1;
+ $pencolor_2 = $pencolor_1;
+ label = 30;
+ break;
+ }
+ case 28:
+ $call88 = _agget($11, 118488) | 0;
+ $cmp89 = ($call88 | 0) == 0;
+ if ($cmp89) {
+ $filled_1 = 0;
+ $fillcolor_2 = $fillcolor_1;
+ $pencolor_2 = $pencolor_1;
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $29 = HEAP8[$call88] | 0;
+ $tobool94 = $29 << 24 >> 24 == 0;
+ $fillcolor_1_call88 = $tobool94 ? $fillcolor_1 : $call88;
+ $filled_0_ = $tobool94 ? $filled_0 : 1;
+ $filled_1 = $filled_0_;
+ $fillcolor_2 = $fillcolor_1_call88;
+ $pencolor_2 = $pencolor_1;
+ label = 30;
+ break;
+ case 30:
+ $tobool101 = ($pencolor_2 | 0) == 0;
+ $_pencolor_2 = $tobool101 ? 117856 : $pencolor_2;
+ $tobool104 = ($fillcolor_2 | 0) == 0;
+ $fillcolor_3 = $tobool104 ? 117192 : $fillcolor_2;
+ $30 = HEAP32[41864] | 0;
+ $tobool107 = ($30 | 0) == 0;
+ if ($tobool107) {
+ label = 34;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $index = $30 + 8 | 0;
+ $31 = HEAP32[$index >> 2] | 0;
+ $call109 = _agxget($11, $31) | 0;
+ $tobool110 = ($call109 | 0) == 0;
+ if ($tobool110) {
+ label = 34;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $32 = HEAP8[$call109] | 0;
+ $tobool114 = $32 << 24 >> 24 == 0;
+ if ($tobool114) {
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $call116 = +_late_double($11, $30, 1.0, 0.0);
+ _gvrender_set_penwidth($job, $call116);
+ label = 34;
+ break;
+ case 34:
+ $33 = HEAP32[$istyle >> 2] | 0;
+ $and118 = $33 & 2;
+ $tobool119 = ($and118 | 0) == 0;
+ if ($tobool119) {
+ label = 37;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $34 = HEAP32[41862] | 0;
+ $call121 = _late_int($11, $34, 1, 0) | 0;
+ $35 = $call121 | $filled_1;
+ $36 = ($35 | 0) == 0;
+ if ($36) {
+ label = 43;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $bb127 = $4 + 56 | 0;
+ $37 = $bb127;
+ HEAP32[$1 >> 2] = HEAP32[$37 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$37 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$37 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$37 + 12 >> 2] | 0;
+ $UR = $4 + 72 | 0;
+ $38 = $UR;
+ HEAP32[$2 >> 2] = HEAP32[$38 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$38 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$38 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$38 + 12 >> 2] | 0;
+ $39 = +HEAPF64[$x >> 3];
+ HEAPF64[$x133 >> 3] = $39;
+ $40 = +HEAPF64[$y >> 3];
+ HEAPF64[$y136 >> 3] = $40;
+ $41 = +HEAPF64[$x138 >> 3];
+ HEAPF64[$x140 >> 3] = $41;
+ $42 = +HEAPF64[$y142 >> 3];
+ HEAPF64[$y144 >> 3] = $42;
+ $43 = HEAP32[$istyle >> 2] | 0;
+ $and145 = $43 & 1;
+ _round_corners($job, $fillcolor_3, $_pencolor_2, $arrayidx125, 4, $43, $and145);
+ label = 43;
+ break;
+ case 37:
+ _gvrender_set_pencolor($job, $_pencolor_2);
+ _gvrender_set_fillcolor($job, $fillcolor_3);
+ $44 = HEAP32[41862] | 0;
+ $call148 = _late_int($11, $44, 1, 0) | 0;
+ $tobool149 = ($call148 | 0) == 0;
+ if ($tobool149) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $bb152 = $4 + 56 | 0;
+ $conv153 = $filled_1 & 255;
+ _gvrender_box($job, $bb152, $conv153);
+ label = 43;
+ break;
+ case 39:
+ $tobool155 = ($filled_1 | 0) == 0;
+ if ($tobool155) {
+ label = 43;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $cmp159 = ($fillcolor_3 | 0) == ($_pencolor_2 | 0);
+ if ($cmp159) {
+ label = 42;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ _gvrender_set_pencolor($job, $fillcolor_3);
+ label = 42;
+ break;
+ case 42:
+ $bb164 = $4 + 56 | 0;
+ $conv165 = $filled_1 & 255;
+ _gvrender_box($job, $bb164, $conv165);
+ label = 43;
+ break;
+ case 43:
+ $label = $4 + 52 | 0;
+ $45 = HEAP32[$label >> 2] | 0;
+ $tobool170 = ($45 | 0) == 0;
+ if ($tobool170) {
+ label = 45;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ _emit_label($job, 5, $45);
+ label = 45;
+ break;
+ case 45:
+ if ($10) {
+ label = 46;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 46:
+ if ($tobool) {
+ label = 47;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 47:
+ $bb179 = $4 + 56 | 0;
+ _emit_map_rect($job, $bb179);
+ $46 = HEAP32[$url >> 2] | 0;
+ $tooltip181 = $5 + 180 | 0;
+ $47 = HEAP32[$tooltip181 >> 2] | 0;
+ $target182 = $5 + 196 | 0;
+ $48 = HEAP32[$target182 >> 2] | 0;
+ $id183 = $5 + 164 | 0;
+ $49 = HEAP32[$id183 >> 2] | 0;
+ _gvrender_begin_anchor($job, $46, $47, $48, $49);
+ label = 48;
+ break;
+ case 48:
+ _gvrender_end_anchor($job);
+ label = 49;
+ break;
+ case 49:
+ if ($tobool187) {
+ label = 54;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $50 = $4;
+ $call189 = _agfstnode($50) | 0;
+ $tobool191101 = ($call189 | 0) == 0;
+ if ($tobool191101) {
+ label = 54;
+ break;
+ } else {
+ $n_0_in102 = $call189;
+ label = 51;
+ break;
+ }
+ case 51:
+ $n_0 = $n_0_in102;
+ _emit_node($job, $n_0);
+ $call193 = _agfstout($50, $n_0_in102) | 0;
+ $tobool19599 = ($call193 | 0) == 0;
+ if ($tobool19599) {
+ label = 53;
+ break;
+ } else {
+ $e_0_in100 = $call193;
+ label = 52;
+ break;
+ }
+ case 52:
+ $e_0 = $e_0_in100;
+ _emit_edge($job, $e_0);
+ $call197 = _agnxtout($50, $e_0_in100) | 0;
+ $tobool195 = ($call197 | 0) == 0;
+ if ($tobool195) {
+ label = 53;
+ break;
+ } else {
+ $e_0_in100 = $call197;
+ label = 52;
+ break;
+ }
+ case 53:
+ $call199 = _agnxtnode($50, $n_0_in102) | 0;
+ $tobool191 = ($call199 | 0) == 0;
+ if ($tobool191) {
+ label = 54;
+ break;
+ } else {
+ $n_0_in102 = $call199;
+ label = 51;
+ break;
+ }
+ case 54:
+ _emit_end_cluster($job, $g);
+ if ($tobool) {
+ label = 56;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ _emit_clusters($job, $4, $flags);
+ label = 56;
+ break;
+ case 56:
+ $inc = $c_0104 + 1 | 0;
+ $51 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($51 | 0);
+ if ($cmp) {
+ label = 57;
+ break;
+ } else {
+ $c_0104 = $inc;
+ label = 4;
+ break;
+ }
+ case 57:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _clust_in_layer($job, $sg) {
+ $job = $job | 0;
+ $sg = $sg | 0;
+ var $numLayers = 0, $0 = 0, $cmp = 0, $1 = 0, $call = 0, $call1 = 0, $call2 = 0, $tobool = 0, $2 = 0, $tobool5 = 0, $3 = 0, $call8 = 0, $tobool910 = 0, $n_0_in11 = 0, $n_0 = 0, $call10 = 0, $tobool11 = 0, $call14 = 0, $tobool9 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $numLayers = $job + 156 | 0;
+ $0 = HEAP32[$numLayers >> 2] | 0;
+ $cmp = ($0 | 0) < 2;
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $sg | 0;
+ $call = _agfindattr($1, 160880) | 0;
+ $call1 = _late_string($1, $call, 136112) | 0;
+ $call2 = _selectedlayer($job, $call1) | 0;
+ $tobool = $call2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 8;
+ break;
+ }
+ case 4:
+ $2 = HEAP8[$call1] | 0;
+ $tobool5 = $2 << 24 >> 24 == 0;
+ if ($tobool5) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ }
+ case 5:
+ $3 = $sg;
+ $call8 = _agfstnode($3) | 0;
+ $tobool910 = ($call8 | 0) == 0;
+ if ($tobool910) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ $n_0_in11 = $call8;
+ label = 6;
+ break;
+ }
+ case 6:
+ $n_0 = $n_0_in11;
+ $call10 = _node_in_layer($job, $sg, $n_0) | 0;
+ $tobool11 = $call10 << 24 >> 24 == 0;
+ if ($tobool11) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 8;
+ break;
+ }
+ case 7:
+ $call14 = _agnxtnode($3, $n_0_in11) | 0;
+ $tobool9 = ($call14 | 0) == 0;
+ if ($tobool9) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ $n_0_in11 = $call14;
+ label = 6;
+ break;
+ }
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _emit_begin_cluster($job, $sg) {
+ $job = $job | 0;
+ $sg = $sg | 0;
+ var $call = 0;
+ $call = _push_obj_state($job) | 0;
+ HEAP32[$call + 4 >> 2] = 1;
+ HEAP32[$call + 8 >> 2] = $sg;
+ HEAP32[$call + 12 >> 2] = 1;
+ _initObjMapData($job, HEAP32[$sg + 52 >> 2] | 0, $sg | 0);
+ _gvrender_begin_cluster($job, 0);
+ return;
+}
+function _checkClusterStyle($sg, $flagp) {
+ $sg = $sg | 0;
+ $flagp = $flagp | 0;
+ var $0 = 0, $call = 0, $cmp = 0, $1 = 0, $tobool = 0, $call1 = 0, $or11 = 0, $istyle_0_ph = 0, $pp_0_ph = 0, $pp_0 = 0, $2 = 0, $tobool2 = 0, $call3 = 0, $cmp4 = 0, $or = 0, $incdec_ptr = 0, $call7 = 0, $cmp8 = 0, $incdec_ptr15 = 0, $qp_0 = 0, $incdec_ptr12 = 0, $3 = 0, $4 = 0, $tobool13 = 0, $istyle_1 = 0, $pstyle_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $sg | 0;
+ $call = _agget($0, 161504) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ $pstyle_0 = 0;
+ $istyle_1 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$call] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ $pstyle_0 = 0;
+ $istyle_1 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call1 = _parse_style($call) | 0;
+ $pp_0_ph = 7280;
+ $istyle_0_ph = 0;
+ label = 6;
+ break;
+ case 5:
+ $or11 = $istyle_0_ph | 2;
+ $pp_0_ph = $pp_0;
+ $istyle_0_ph = $or11;
+ label = 6;
+ break;
+ case 6:
+ $pp_0 = $pp_0_ph;
+ label = 7;
+ break;
+ case 7:
+ $2 = HEAP32[$pp_0 >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ $pstyle_0 = 7280;
+ $istyle_1 = $istyle_0_ph;
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call3 = _strcmp($2 | 0, 161792) | 0;
+ $cmp4 = ($call3 | 0) == 0;
+ if ($cmp4) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $or = $istyle_0_ph | 1;
+ $incdec_ptr = $pp_0 + 4 | 0;
+ $pp_0_ph = $incdec_ptr;
+ $istyle_0_ph = $or;
+ label = 6;
+ break;
+ case 10:
+ $call7 = _strcmp($2 | 0, 161224) | 0;
+ $cmp8 = ($call7 | 0) == 0;
+ $incdec_ptr15 = $pp_0 + 4 | 0;
+ if ($cmp8) {
+ $qp_0 = $pp_0;
+ label = 11;
+ break;
+ } else {
+ $pp_0 = $incdec_ptr15;
+ label = 7;
+ break;
+ }
+ case 11:
+ $incdec_ptr12 = $qp_0 + 4 | 0;
+ $3 = HEAP32[$incdec_ptr12 >> 2] | 0;
+ HEAP32[$qp_0 >> 2] = $3;
+ $4 = HEAP32[$incdec_ptr12 >> 2] | 0;
+ $tobool13 = ($4 | 0) == 0;
+ if ($tobool13) {
+ label = 5;
+ break;
+ } else {
+ $qp_0 = $incdec_ptr12;
+ label = 11;
+ break;
+ }
+ case 12:
+ HEAP32[$flagp >> 2] = $istyle_1;
+ return $pstyle_0 | 0;
+ }
+ return 0;
+}
+function _emit_node($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $gvc1 = 0, $0 = 0, $shape = 0, $1 = 0, $tobool = 0, $graph = 0, $2 = 0, $call = 0, $tobool2 = 0, $clip = 0, $call4 = 0, $tobool6 = 0, $state = 0, $3 = 0, $conv9 = 0, $viewNum = 0, $4 = 0, $cmp = 0, $conv13 = 0, $name = 0, $5 = 0, $6 = 0, $7 = 0, $call16 = 0, $8 = 0, $tobool17 = 0, $9 = 0, $call19 = 0, $10 = 0, $tobool21 = 0, $call23 = 0, $11 = 0, $tobool2426 = 0, $12 = 0, $incdec_ptr27 = 0, $13 = 0, $cmp27 = 0, $incdec_ptr = 0, $14 = 0, $tobool24 = 0, $call30 = 0, $tobool31 = 0, $15 = 0, $fns = 0, $16 = 0, $codefn = 0, $17 = 0, $xlabel = 0, $18 = 0, $tobool38 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $shape = $n + 24 | 0;
+ $1 = HEAP32[$shape >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 16;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $graph = $n + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $call = _node_in_layer($job, $2, $n) | 0;
+ $tobool2 = $call << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 16;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $clip = $job + 256 | 0;
+ $call4 = _node_in_box($n, $clip) | 0;
+ $tobool6 = $call4 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 16;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $state = $n + 132 | 0;
+ $3 = HEAP8[$state] | 0;
+ $conv9 = $3 << 24 >> 24;
+ $viewNum = $0 + 28 | 0;
+ $4 = HEAP32[$viewNum >> 2] | 0;
+ $cmp = ($conv9 | 0) == ($4 | 0);
+ if ($cmp) {
+ label = 16;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $conv13 = $4 & 255;
+ HEAP8[$state] = $conv13;
+ $name = $n + 12 | 0;
+ $5 = HEAP32[$name >> 2] | 0;
+ _gvrender_comment($job, $5);
+ $6 = $n | 0;
+ $7 = HEAP32[41614] | 0;
+ $call16 = _late_string($6, $7, 136112) | 0;
+ $8 = HEAP8[$call16] | 0;
+ $tobool17 = $8 << 24 >> 24 == 0;
+ if ($tobool17) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _gvrender_comment($job, $call16);
+ label = 8;
+ break;
+ case 8:
+ $9 = HEAP32[41560] | 0;
+ $call19 = _late_string($6, $9, 136112) | 0;
+ $10 = HEAP8[$call19] | 0;
+ $tobool21 = $10 << 24 >> 24 == 0;
+ if ($tobool21) {
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call23 = _parse_style($call19) | 0;
+ $11 = HEAP32[1820] | 0;
+ $tobool2426 = ($11 | 0) == 0;
+ if ($tobool2426) {
+ label = 13;
+ break;
+ } else {
+ $incdec_ptr27 = 7284;
+ $12 = $11;
+ label = 10;
+ break;
+ }
+ case 10:
+ $13 = HEAP8[$12] | 0;
+ $cmp27 = $13 << 24 >> 24 == 105;
+ if ($cmp27) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $incdec_ptr = $incdec_ptr27 + 4 | 0;
+ $14 = HEAP32[$incdec_ptr27 >> 2] | 0;
+ $tobool24 = ($14 | 0) == 0;
+ if ($tobool24) {
+ label = 13;
+ break;
+ } else {
+ $incdec_ptr27 = $incdec_ptr;
+ $12 = $14;
+ label = 10;
+ break;
+ }
+ case 12:
+ $call30 = _strcmp($12 | 0, 101752) | 0;
+ $tobool31 = ($call30 | 0) == 0;
+ if ($tobool31) {
+ label = 16;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 13:
+ _emit_begin_node($job, $n);
+ $15 = HEAP32[$shape >> 2] | 0;
+ $fns = $15 + 4 | 0;
+ $16 = HEAP32[$fns >> 2] | 0;
+ $codefn = $16 + 20 | 0;
+ $17 = HEAP32[$codefn >> 2] | 0;
+ FUNCTION_TABLE_vii[$17 & 1023]($job, $n);
+ $xlabel = $n + 124 | 0;
+ $18 = HEAP32[$xlabel >> 2] | 0;
+ $tobool38 = ($18 | 0) == 0;
+ if ($tobool38) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ _emit_label($job, 10, $18);
+ label = 15;
+ break;
+ case 15:
+ _emit_end_node($job);
+ label = 16;
+ break;
+ case 16:
+ return;
+ }
+}
+function _emit_edge($job, $e) {
+ $job = $job | 0;
+ $e = $e | 0;
+ var $clip = 0, $call = 0, $tobool = 0, $head = 0, $call1 = 0, $tobool3 = 0, $tail = 0, $0 = 0, $name = 0, $1 = 0, $call4 = 0, $2 = 0, $name6 = 0, $3 = 0, $call7 = 0, $add8 = 0, $add9 = 0, $call10 = 0, $4 = 0, $name12 = 0, $5 = 0, $call13 = 0, $6 = 0, $graph15 = 0, $7 = 0, $8 = 0, $9 = 0, $and = 0, $tobool16 = 0, $strlen = 0, $endptr = 0, $10 = 0, $name21 = 0, $11 = 0, $call22 = 0, $12 = 0, $13 = 0, $call23 = 0, $14 = 0, $tobool24 = 0, $15 = 0, $call27 = 0, $16 = 0, $tobool29 = 0, $call31 = 0, $17 = 0, $tobool3231 = 0, $18 = 0, $incdec_ptr32 = 0, $19 = 0, $cmp = 0, $incdec_ptr = 0, $20 = 0, $tobool32 = 0, $call37 = 0, $tobool38 = 0, $styles_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $clip = $job + 256 | 0;
+ $call = _edge_in_box($e, $clip) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $e + 12 | 0;
+ $call1 = _edge_in_layer($job, $e) | 0;
+ $tobool3 = $call1 << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 15;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $name = $0 + 12 | 0;
+ $1 = HEAP32[$name >> 2] | 0;
+ $call4 = _strlen($1 | 0) | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $name6 = $2 + 12 | 0;
+ $3 = HEAP32[$name6 >> 2] | 0;
+ $call7 = _strlen($3 | 0) | 0;
+ $add8 = $call4 + 3 | 0;
+ $add9 = $add8 + $call7 | 0;
+ $call10 = _malloc($add9) | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $name12 = $4 + 12 | 0;
+ $5 = HEAP32[$name12 >> 2] | 0;
+ $call13 = _strcpy($call10 | 0, $5 | 0) | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ $graph15 = $6 + 20 | 0;
+ $7 = HEAP32[$graph15 >> 2] | 0;
+ $8 = $7;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $and = $9 & 16;
+ $tobool16 = ($and | 0) == 0;
+ $strlen = _strlen($call10 | 0) | 0;
+ $endptr = $call10 + $strlen | 0;
+ if ($tobool16) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP8[$endptr] = HEAP8[102616] | 0;
+ HEAP8[$endptr + 1 | 0] = HEAP8[102617 | 0] | 0;
+ HEAP8[$endptr + 2 | 0] = HEAP8[102618 | 0] | 0;
+ label = 7;
+ break;
+ case 6:
+ HEAP8[$endptr] = HEAP8[102232] | 0;
+ HEAP8[$endptr + 1 | 0] = HEAP8[102233 | 0] | 0;
+ HEAP8[$endptr + 2 | 0] = HEAP8[102234 | 0] | 0;
+ label = 7;
+ break;
+ case 7:
+ $10 = HEAP32[$head >> 2] | 0;
+ $name21 = $10 + 12 | 0;
+ $11 = HEAP32[$name21 >> 2] | 0;
+ $call22 = _strcat($call10 | 0, $11 | 0) | 0;
+ _gvrender_comment($job, $call10);
+ _free($call10);
+ $12 = $e | 0;
+ $13 = HEAP32[41956] | 0;
+ $call23 = _late_string($12, $13, 136112) | 0;
+ $14 = HEAP8[$call23] | 0;
+ $tobool24 = $14 << 24 >> 24 == 0;
+ if ($tobool24) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _gvrender_comment($job, $call23);
+ label = 9;
+ break;
+ case 9:
+ $15 = HEAP32[41904] | 0;
+ $call27 = _late_string($12, $15, 136112) | 0;
+ $16 = HEAP8[$call27] | 0;
+ $tobool29 = $16 << 24 >> 24 == 0;
+ if ($tobool29) {
+ $styles_0 = 0;
+ label = 14;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call31 = _parse_style($call27) | 0;
+ $17 = HEAP32[1820] | 0;
+ $tobool3231 = ($17 | 0) == 0;
+ if ($tobool3231) {
+ $styles_0 = 7280;
+ label = 14;
+ break;
+ } else {
+ $incdec_ptr32 = 7284;
+ $18 = $17;
+ label = 11;
+ break;
+ }
+ case 11:
+ $19 = HEAP8[$18] | 0;
+ $cmp = $19 << 24 >> 24 == 105;
+ if ($cmp) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $incdec_ptr = $incdec_ptr32 + 4 | 0;
+ $20 = HEAP32[$incdec_ptr32 >> 2] | 0;
+ $tobool32 = ($20 | 0) == 0;
+ if ($tobool32) {
+ $styles_0 = 7280;
+ label = 14;
+ break;
+ } else {
+ $incdec_ptr32 = $incdec_ptr;
+ $18 = $20;
+ label = 11;
+ break;
+ }
+ case 13:
+ $call37 = _strcmp($18 | 0, 101752) | 0;
+ $tobool38 = ($call37 | 0) == 0;
+ if ($tobool38) {
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 14:
+ _emit_begin_edge($job, $e, $styles_0);
+ _emit_edge_graphics($job, $e, $styles_0);
+ _emit_end_edge($job);
+ label = 15;
+ break;
+ case 15:
+ return;
+ }
+}
+function _emit_end_cluster($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ _gvrender_end_cluster($job, 0);
+ _pop_obj_state($job);
+ return;
+}
+function _parse_style($s) {
+ $s = $s | 0;
+ var $buf = 0, $p = 0, $xb = 0, $_b = 0, $arraydecay = 0, $ptr = 0, $eptr = 0, $buf34 = 0, $fun_0_ph = 0, $in_parens_0_ph = 0, $in_parens_0 = 0, $call = 0, $tobool1 = 0, $call3 = 0, $cmp6 = 0, $call9 = 0, $cmp12 = 0, $cmp15 = 0, $call18 = 0, $arrayidx = 0, $0 = 0, $1 = 0, $cmp20 = 0, $call22 = 0, $2 = 0, $incdec_ptr = 0, $3 = 0, $inc = 0, $arrayidx23 = 0, $fun_1 = 0, $4 = 0, $5 = 0, $cmp25 = 0, $call28 = 0, $6 = 0, $7 = 0, $call36 = 0, $8 = 0, $9 = 0, $cmp37 = 0, $call40 = 0, $10 = 0, $incdec_ptr44 = 0, $tobool45 = 0, $call47 = 0, $arrayidx49 = 0, $11 = 0, $12 = 0, $cmp50 = 0, $call53 = 0, $13 = 0, $14 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 152 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $p = __stackBase__ + 128 | 0;
+ $xb = __stackBase__ + 136 | 0;
+ $_b = HEAP8[7536] | 0;
+ if ($_b) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _agxbinit(4840, 128, 9008);
+ HEAP8[7536] = 1;
+ label = 4;
+ break;
+ case 4:
+ $arraydecay = $buf | 0;
+ _agxbinit($xb, 128, $arraydecay);
+ HEAP32[$p >> 2] = $s;
+ $ptr = $xb + 4 | 0;
+ $eptr = $xb + 8 | 0;
+ $buf34 = $xb | 0;
+ $in_parens_0_ph = 0;
+ $fun_0_ph = 0;
+ label = 5;
+ break;
+ case 5:
+ $in_parens_0 = $in_parens_0_ph;
+ label = 6;
+ break;
+ case 6:
+ $call = _style_token($p, $xb) | 0;
+ if (($call | 0) == 40) {
+ label = 7;
+ break;
+ } else if (($call | 0) == 41) {
+ label = 9;
+ break;
+ } else if (($call | 0) == 0) {
+ label = 22;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $tobool1 = $in_parens_0 << 24 >> 24 == 0;
+ if ($tobool1) {
+ $in_parens_0 = 1;
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call3 = _agerr(1, 116624, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $s, tempInt) | 0) | 0;
+ HEAP32[1820] = 0;
+ _agxbfree($xb);
+ label = 27;
+ break;
+ case 9:
+ $cmp6 = $in_parens_0 << 24 >> 24 == 0;
+ if ($cmp6) {
+ label = 10;
+ break;
+ } else {
+ $in_parens_0 = 0;
+ label = 6;
+ break;
+ }
+ case 10:
+ $call9 = _agerr(1, 116144, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $s, tempInt) | 0) | 0;
+ HEAP32[1820] = 0;
+ _agxbfree($xb);
+ label = 27;
+ break;
+ case 11:
+ $cmp12 = $in_parens_0 << 24 >> 24 == 0;
+ if ($cmp12) {
+ label = 12;
+ break;
+ } else {
+ $fun_1 = $fun_0_ph;
+ label = 17;
+ break;
+ }
+ case 12:
+ $cmp15 = ($fun_0_ph | 0) == 63;
+ if ($cmp15) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $call18 = _agerr(0, 115648, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $s, tempInt) | 0) | 0;
+ $arrayidx = 7280 + ($fun_0_ph << 2) | 0;
+ HEAP32[$arrayidx >> 2] = 0;
+ _agxbfree($xb);
+ label = 27;
+ break;
+ case 14:
+ $0 = HEAP32[1211] | 0;
+ $1 = HEAP32[1212] | 0;
+ $cmp20 = $0 >>> 0 < $1 >>> 0;
+ if ($cmp20) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $call22 = _agxbmore(4840, 1) | 0;
+ label = 16;
+ break;
+ case 16:
+ $2 = HEAP32[1211] | 0;
+ $incdec_ptr = $2 + 1 | 0;
+ HEAP32[1211] = $incdec_ptr;
+ HEAP8[$2] = 0;
+ $3 = HEAP32[1211] | 0;
+ $inc = $fun_0_ph + 1 | 0;
+ $arrayidx23 = 7280 + ($fun_0_ph << 2) | 0;
+ HEAP32[$arrayidx23 >> 2] = $3;
+ $fun_1 = $inc;
+ label = 17;
+ break;
+ case 17:
+ $4 = HEAP32[$ptr >> 2] | 0;
+ $5 = HEAP32[$eptr >> 2] | 0;
+ $cmp25 = $4 >>> 0 < $5 >>> 0;
+ if ($cmp25) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $call28 = _agxbmore($xb, 1) | 0;
+ label = 19;
+ break;
+ case 19:
+ $6 = HEAP32[$ptr >> 2] | 0;
+ HEAP8[$6] = 0;
+ $7 = HEAP32[$buf34 >> 2] | 0;
+ HEAP32[$ptr >> 2] = $7;
+ $call36 = _agxbput(4840, $7) | 0;
+ $8 = HEAP32[1211] | 0;
+ $9 = HEAP32[1212] | 0;
+ $cmp37 = $8 >>> 0 < $9 >>> 0;
+ if ($cmp37) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $call40 = _agxbmore(4840, 1) | 0;
+ label = 21;
+ break;
+ case 21:
+ $10 = HEAP32[1211] | 0;
+ $incdec_ptr44 = $10 + 1 | 0;
+ HEAP32[1211] = $incdec_ptr44;
+ HEAP8[$10] = 0;
+ $in_parens_0_ph = $in_parens_0;
+ $fun_0_ph = $fun_1;
+ label = 5;
+ break;
+ case 22:
+ $tobool45 = $in_parens_0 << 24 >> 24 == 0;
+ if ($tobool45) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $call47 = _agerr(1, 115096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $s, tempInt) | 0) | 0;
+ HEAP32[1820] = 0;
+ _agxbfree($xb);
+ label = 27;
+ break;
+ case 24:
+ $arrayidx49 = 7280 + ($fun_0_ph << 2) | 0;
+ HEAP32[$arrayidx49 >> 2] = 0;
+ _agxbfree($xb);
+ $11 = HEAP32[1211] | 0;
+ $12 = HEAP32[1212] | 0;
+ $cmp50 = $11 >>> 0 < $12 >>> 0;
+ if ($cmp50) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $call53 = _agxbmore(4840, 1) | 0;
+ label = 26;
+ break;
+ case 26:
+ $13 = HEAP32[1211] | 0;
+ HEAP8[$13] = 0;
+ $14 = HEAP32[1210] | 0;
+ HEAP32[1211] = $14;
+ label = 27;
+ break;
+ case 27:
+ STACKTOP = __stackBase__;
+ return 7280;
+ }
+ return 0;
+}
+function _style_token($s, $xb) {
+ $s = $s | 0;
+ $xb = $xb | 0;
+ var $0 = 0, $1 = 0, $tobool16 = 0, $2 = 0, $p_017 = 0, $conv = 0, $call = 0, $tobool2 = 0, $3 = 0, $cmp = 0, $incdec_ptr = 0, $4 = 0, $tobool = 0, $p_0_lcssa = 0, $5 = 0, $conv5 = 0, $6 = 0, $conv1012 = 0, $call1113 = 0, $lnot14 = 0, $ptr = 0, $eptr = 0, $incdec_ptr7 = 0, $7 = 0, $conv8 = 0, $8 = 0, $p_115 = 0, $9 = 0, $10 = 0, $cmp14 = 0, $call16 = 0, $11 = 0, $incdec_ptr18 = 0, $incdec_ptr20 = 0, $12 = 0, $conv10 = 0, $call11 = 0, $lnot = 0, $token_0 = 0, $p_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$s >> 2] | 0;
+ $1 = HEAP8[$0] | 0;
+ $tobool16 = $1 << 24 >> 24 == 0;
+ if ($tobool16) {
+ $p_0_lcssa = $0;
+ label = 6;
+ break;
+ } else {
+ $p_017 = $0;
+ $2 = $1;
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $2 << 24 >> 24;
+ $call = _isspace($conv | 0) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $3 = HEAP8[$p_017] | 0;
+ $cmp = $3 << 24 >> 24 == 44;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $p_0_lcssa = $p_017;
+ label = 6;
+ break;
+ }
+ case 5:
+ $incdec_ptr = $p_017 + 1 | 0;
+ $4 = HEAP8[$incdec_ptr] | 0;
+ $tobool = $4 << 24 >> 24 == 0;
+ if ($tobool) {
+ $p_0_lcssa = $incdec_ptr;
+ label = 6;
+ break;
+ } else {
+ $p_017 = $incdec_ptr;
+ $2 = $4;
+ label = 3;
+ break;
+ }
+ case 6:
+ $5 = HEAP8[$p_0_lcssa] | 0;
+ $conv5 = $5 << 24 >> 24;
+ if (($conv5 | 0) == 40 | ($conv5 | 0) == 41) {
+ label = 9;
+ break;
+ } else if (($conv5 | 0) == 0) {
+ $p_2 = $p_0_lcssa;
+ $token_0 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $6 = HEAP8[$p_0_lcssa] | 0;
+ $conv1012 = $6 << 24 >> 24;
+ $call1113 = _is_style_delim($conv1012) | 0;
+ $lnot14 = $call1113 << 24 >> 24 == 0;
+ if ($lnot14) {
+ label = 8;
+ break;
+ } else {
+ $p_2 = $p_0_lcssa;
+ $token_0 = 1;
+ label = 13;
+ break;
+ }
+ case 8:
+ $ptr = $xb + 4 | 0;
+ $eptr = $xb + 8 | 0;
+ $p_115 = $p_0_lcssa;
+ $8 = $6;
+ label = 10;
+ break;
+ case 9:
+ $incdec_ptr7 = $p_0_lcssa + 1 | 0;
+ $7 = HEAP8[$p_0_lcssa] | 0;
+ $conv8 = $7 << 24 >> 24;
+ $p_2 = $incdec_ptr7;
+ $token_0 = $conv8;
+ label = 13;
+ break;
+ case 10:
+ $9 = HEAP32[$ptr >> 2] | 0;
+ $10 = HEAP32[$eptr >> 2] | 0;
+ $cmp14 = $9 >>> 0 < $10 >>> 0;
+ if ($cmp14) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call16 = _agxbmore($xb, 1) | 0;
+ label = 12;
+ break;
+ case 12:
+ $11 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr18 = $11 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr18;
+ HEAP8[$11] = $8;
+ $incdec_ptr20 = $p_115 + 1 | 0;
+ $12 = HEAP8[$incdec_ptr20] | 0;
+ $conv10 = $12 << 24 >> 24;
+ $call11 = _is_style_delim($conv10) | 0;
+ $lnot = $call11 << 24 >> 24 == 0;
+ if ($lnot) {
+ $p_115 = $incdec_ptr20;
+ $8 = $12;
+ label = 10;
+ break;
+ } else {
+ $p_2 = $incdec_ptr20;
+ $token_0 = 1;
+ label = 13;
+ break;
+ }
+ case 13:
+ HEAP32[$s >> 2] = $p_2;
+ return $token_0 | 0;
+ }
+ return 0;
+}
+function _gv_fixLocale($set) {
+ $set = $set | 0;
+ var $tobool = 0, $0 = 0, $inc = 0, $cmp = 0, $call = 0, $call2 = 0, $call3 = 0, $cmp4 = 0, $dec = 0, $cmp6 = 0, $1 = 0, $call8 = 0, $2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($set | 0) == 0;
+ $0 = HEAP32[4042] | 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $inc = $0 + 1 | 0;
+ HEAP32[4042] = $inc;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $call = _setlocale(4, 0) | 0;
+ $call2 = _strdup($call | 0) | 0;
+ HEAP32[4040] = $call2;
+ $call3 = _setlocale(4, 114568) | 0;
+ label = 8;
+ break;
+ case 5:
+ $cmp4 = ($0 | 0) > 0;
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $dec = $0 - 1 | 0;
+ HEAP32[4042] = $dec;
+ $cmp6 = ($dec | 0) == 0;
+ if ($cmp6) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $1 = HEAP32[4040] | 0;
+ $call8 = _setlocale(4, $1 | 0) | 0;
+ $2 = HEAP32[4040] | 0;
+ _free($2);
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _gvRenderJobs($gvc, $g) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ var $drawing = 0, $0 = 0, $tobool = 0, $call = 0, $keybindings = 0, $1 = 0, $numkeys = 0, $call1 = 0, $tobool257 = 0, $gvg = 0, $common = 0, $type = 0, $active_jobs = 0, $viewNum = 0, $job_058 = 0, $2 = 0, $tobool3 = 0, $input_filename = 0, $3 = 0, $input_filename6 = 0, $4 = 0, $graph_index = 0, $5 = 0, $graph_index8 = 0, $input_filename9 = 0, $graph_index10 = 0, $common12 = 0, $6 = 0, $layout_type = 0, $7 = 0, $tobool15 = 0, $call17 = 0, $output_langname = 0, $8 = 0, $call19 = 0, $output_lang = 0, $9 = 0, $call23 = 0, $flags = 0, $10 = 0, $or = 0, $flags27 = 0, $11 = 0, $or28 = 0, $call29 = 0, $flags30 = 0, $12 = 0, $or31 = 0, $13 = 0, $tobool32 = 0, $flags34 = 0, $14 = 0, $and = 0, $tobool35 = 0, $15 = 0, $output_langname37 = 0, $16 = 0, $call38 = 0, $tobool39 = 0, $_pr = 0, $tobool46 = 0, $next_active = 0, $17 = 0, $output_file = 0, $18 = 0, $output_file48 = 0, $call50 = 0, $tobool51 = 0, $next_active56 = 0, $callbacks = 0, $flags57 = 0, $19 = 0, $and58 = 0, $tobool59 = 0, $20 = 0, $21 = 0, $show_boxes = 0, $call63 = 0, $tobool2 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $drawing = $g + 48 | 0;
+ $0 = HEAP32[$drawing >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _agerr(1, 113984, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $retval_0 = -1;
+ label = 30;
+ break;
+ case 4:
+ _init_bb($g);
+ _init_gvc($gvc, $g);
+ _init_layering($gvc, $g);
+ $keybindings = $gvc + 104 | 0;
+ HEAP32[$keybindings >> 2] = 15480;
+ $1 = HEAP32[3868] | 0;
+ $numkeys = $gvc + 108 | 0;
+ HEAP32[$numkeys >> 2] = $1;
+ _gv_fixLocale(1);
+ $call1 = _gvjobs_first($gvc) | 0;
+ $tobool257 = ($call1 | 0) == 0;
+ if ($tobool257) {
+ label = 29;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $gvg = $gvc + 56 | 0;
+ $common = $gvc | 0;
+ $type = $gvc + 156 | 0;
+ $active_jobs = $gvc + 164 | 0;
+ $viewNum = $gvc + 28 | 0;
+ $job_058 = $call1;
+ label = 6;
+ break;
+ case 6:
+ $2 = HEAP32[$gvg >> 2] | 0;
+ $tobool3 = ($2 | 0) == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $input_filename = $2 + 8 | 0;
+ $3 = HEAP32[$input_filename >> 2] | 0;
+ $input_filename6 = $job_058 + 20 | 0;
+ HEAP32[$input_filename6 >> 2] = $3;
+ $4 = HEAP32[$gvg >> 2] | 0;
+ $graph_index = $4 + 12 | 0;
+ $5 = HEAP32[$graph_index >> 2] | 0;
+ $graph_index8 = $job_058 + 24 | 0;
+ HEAP32[$graph_index8 >> 2] = $5;
+ label = 9;
+ break;
+ case 8:
+ $input_filename9 = $job_058 + 20 | 0;
+ HEAP32[$input_filename9 >> 2] = 0;
+ $graph_index10 = $job_058 + 24 | 0;
+ HEAP32[$graph_index10 >> 2] = 0;
+ label = 9;
+ break;
+ case 9:
+ $common12 = $job_058 + 12 | 0;
+ HEAP32[$common12 >> 2] = $common;
+ $6 = HEAP32[$type >> 2] | 0;
+ $layout_type = $job_058 + 28 | 0;
+ HEAP32[$layout_type >> 2] = $6;
+ $7 = HEAP32[$drawing >> 2] | 0;
+ $tobool15 = ($7 | 0) == 0;
+ if ($tobool15) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $call17 = _agerr(1, 113528, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _gv_fixLocale(0);
+ $retval_0 = -1;
+ label = 30;
+ break;
+ case 11:
+ $output_langname = $job_058 + 52 | 0;
+ $8 = HEAP32[$output_langname >> 2] | 0;
+ $call19 = _gvrender_select($job_058, $8) | 0;
+ $output_lang = $job_058 + 56 | 0;
+ HEAP32[$output_lang >> 2] = $call19;
+ if (($call19 | 0) == 999) {
+ label = 12;
+ break;
+ } else if (($call19 | 0) == 21) {
+ label = 13;
+ break;
+ } else if (($call19 | 0) == 24) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 12:
+ $9 = HEAP32[$output_langname >> 2] | 0;
+ $call23 = _agerr(1, 113096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $9, tempInt) | 0) | 0;
+ _gv_fixLocale(0);
+ $retval_0 = -1;
+ label = 30;
+ break;
+ case 13:
+ $flags = $job_058 + 152 | 0;
+ $10 = HEAP32[$flags >> 2] | 0;
+ $or = $10 | 1;
+ HEAP32[$flags >> 2] = $or;
+ label = 16;
+ break;
+ case 14:
+ $flags27 = $job_058 + 152 | 0;
+ $11 = HEAP32[$flags27 >> 2] | 0;
+ $or28 = $11 | 520;
+ HEAP32[$flags27 >> 2] = $or28;
+ label = 16;
+ break;
+ case 15:
+ $call29 = _chkOrder($g) | 0;
+ $flags30 = $job_058 + 152 | 0;
+ $12 = HEAP32[$flags30 >> 2] | 0;
+ $or31 = $12 | $call29;
+ HEAP32[$flags30 >> 2] = $or31;
+ label = 16;
+ break;
+ case 16:
+ $13 = HEAP32[$active_jobs >> 2] | 0;
+ $tobool32 = ($13 | 0) == 0;
+ if ($tobool32) {
+ label = 20;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $flags34 = $13 + 152 | 0;
+ $14 = HEAP32[$flags34 >> 2] | 0;
+ $and = $14 & 32;
+ $tobool35 = ($and | 0) == 0;
+ if ($tobool35) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $15 = HEAP32[$output_langname >> 2] | 0;
+ $output_langname37 = $13 + 52 | 0;
+ $16 = HEAP32[$output_langname37 >> 2] | 0;
+ $call38 = _strcmp($15 | 0, $16 | 0) | 0;
+ $tobool39 = ($call38 | 0) == 0;
+ if ($tobool39) {
+ label = 21;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ _gvrender_end_job($13);
+ HEAP32[$active_jobs >> 2] = 0;
+ HEAP32[$viewNum >> 2] = 0;
+ HEAP32[4044] = 0;
+ label = 23;
+ break;
+ case 20:
+ HEAP32[4044] = 0;
+ label = 23;
+ break;
+ case 21:
+ $_pr = HEAP32[4044] | 0;
+ $tobool46 = ($_pr | 0) == 0;
+ if ($tobool46) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $next_active = $_pr + 8 | 0;
+ HEAP32[$next_active >> 2] = $job_058;
+ $17 = HEAP32[4044] | 0;
+ $output_file = $17 + 36 | 0;
+ $18 = HEAP32[$output_file >> 2] | 0;
+ $output_file48 = $job_058 + 36 | 0;
+ HEAP32[$output_file48 >> 2] = $18;
+ label = 25;
+ break;
+ case 23:
+ $call50 = _gvrender_begin_job($job_058) | 0;
+ $tobool51 = ($call50 | 0) == 0;
+ if ($tobool51) {
+ label = 24;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 24:
+ HEAP32[$active_jobs >> 2] = $job_058;
+ label = 25;
+ break;
+ case 25:
+ $next_active56 = $job_058 + 8 | 0;
+ HEAP32[$next_active56 >> 2] = 0;
+ $callbacks = $job_058 + 104 | 0;
+ HEAP32[$callbacks >> 2] = 16120;
+ _init_job_pad($job_058);
+ _init_job_margin($job_058);
+ _init_job_dpi($job_058, $g);
+ _init_job_viewport($job_058, $g);
+ _init_job_pagination($job_058, $g);
+ $flags57 = $job_058 + 152 | 0;
+ $19 = HEAP32[$flags57 >> 2] | 0;
+ $and58 = $19 & 128;
+ $tobool59 = ($and58 | 0) == 0;
+ if ($tobool59) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $20 = HEAP32[41362] | 0;
+ $21 = HEAP32[$common12 >> 2] | 0;
+ $show_boxes = $21 + 20 | 0;
+ HEAP32[$show_boxes >> 2] = $20;
+ _emit_graph($job_058, $g);
+ label = 27;
+ break;
+ case 27:
+ HEAP32[4044] = $job_058;
+ label = 28;
+ break;
+ case 28:
+ $call63 = _gvjobs_next($gvc) | 0;
+ $tobool2 = ($call63 | 0) == 0;
+ if ($tobool2) {
+ label = 29;
+ break;
+ } else {
+ $job_058 = $call63;
+ label = 6;
+ break;
+ }
+ case 29:
+ _gv_fixLocale(0);
+ $retval_0 = 0;
+ label = 30;
+ break;
+ case 30:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _init_bb($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool5 = 0, $n_0_in6 = 0, $n_0 = 0, $call1 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool5 = ($call | 0) == 0;
+ if ($tobool5) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in6 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $n_0 = $n_0_in6;
+ _init_bb_node($g, $n_0);
+ $call1 = _agnxtnode($0, $n_0_in6) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in6 = $call1;
+ label = 3;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _init_gvc($gvc, $g) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ var $xf = 0, $yf = 0, $g1 = 0, $graph_sets_margin = 0, $0 = 0, $call = 0, $tobool = 0, $call2 = 0, $cmp = 0, $1 = 0.0, $mul = 0.0, $y = 0, $x = 0, $cmp5 = 0, $2 = 0.0, $mul7 = 0.0, $graph_sets_pad = 0, $call13 = 0, $tobool14 = 0, $call16 = 0, $cmp17 = 0, $3 = 0.0, $mul19 = 0.0, $y20 = 0, $x22 = 0, $cmp23 = 0, $4 = 0.0, $mul25 = 0.0, $graph_sets_pageSize = 0, $pageSize = 0, $drawing = 0, $5 = 0, $page = 0, $6 = 0, $7 = 0, $8 = 0, $x35 = 0, $9 = 0.0, $cmp36 = 0, $y40 = 0, $10 = 0.0, $cmp41 = 0, $11 = 0, $landscape = 0, $12 = 0, $tobool47 = 0, $rotation = 0, $_ = 0, $pagedir = 0, $call51 = 0, $tobool52 = 0, $13 = 0, $tobool54 = 0, $bb = 0, $bb59 = 0, $14 = 0, $15 = 0, $root = 0, $16 = 0, $17 = 0, $call60 = 0, $18 = 0, $19 = 0, $call62 = 0, $proto = 0, $20 = 0, $n = 0, $21 = 0, $22 = 0, $23 = 0, $call63 = 0, $defaultfontname = 0, $24 = 0, $n65 = 0, $25 = 0, $26 = 0, $27 = 0, $call66 = 0.0, $defaultfontsize = 0, $defaultlinestyle = 0, $name = 0, $28 = 0, $graphname = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $xf = __stackBase__ | 0;
+ $yf = __stackBase__ + 8 | 0;
+ $g1 = $gvc + 128 | 0;
+ HEAP32[$g1 >> 2] = $g;
+ $graph_sets_margin = $gvc + 269 | 0;
+ HEAP8[$graph_sets_margin] = 0;
+ $0 = $g | 0;
+ $call = _agget($0, 107616) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call2 = _sscanf($call | 0, 107216, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $xf, HEAP32[tempInt + 8 >> 2] = $yf, tempInt) | 0) | 0;
+ $cmp = ($call2 | 0) > 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $1 = +HEAPF64[$xf >> 3];
+ $mul = $1 * 72.0;
+ $y = $gvc + 184 | 0;
+ HEAPF64[$y >> 3] = $mul;
+ $x = $gvc + 176 | 0;
+ HEAPF64[$x >> 3] = $mul;
+ $cmp5 = ($call2 | 0) > 1;
+ if ($cmp5) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $2 = +HEAPF64[$yf >> 3];
+ $mul7 = $2 * 72.0;
+ HEAPF64[$y >> 3] = $mul7;
+ label = 6;
+ break;
+ case 6:
+ HEAP8[$graph_sets_margin] = 1;
+ label = 7;
+ break;
+ case 7:
+ $graph_sets_pad = $gvc + 268 | 0;
+ HEAP8[$graph_sets_pad] = 0;
+ $call13 = _agget($0, 106880) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call16 = _sscanf($call13 | 0, 107216, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $xf, HEAP32[tempInt + 8 >> 2] = $yf, tempInt) | 0) | 0;
+ $cmp17 = ($call16 | 0) > 0;
+ if ($cmp17) {
+ label = 9;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 9:
+ $3 = +HEAPF64[$xf >> 3];
+ $mul19 = $3 * 72.0;
+ $y20 = $gvc + 200 | 0;
+ HEAPF64[$y20 >> 3] = $mul19;
+ $x22 = $gvc + 192 | 0;
+ HEAPF64[$x22 >> 3] = $mul19;
+ $cmp23 = ($call16 | 0) > 1;
+ if ($cmp23) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $4 = +HEAPF64[$yf >> 3];
+ $mul25 = $4 * 72.0;
+ HEAPF64[$y20 >> 3] = $mul25;
+ label = 11;
+ break;
+ case 11:
+ HEAP8[$graph_sets_pad] = 1;
+ label = 12;
+ break;
+ case 12:
+ $graph_sets_pageSize = $gvc + 270 | 0;
+ HEAP8[$graph_sets_pageSize] = 0;
+ $pageSize = $gvc + 208 | 0;
+ $drawing = $g + 48 | 0;
+ $5 = HEAP32[$drawing >> 2] | 0;
+ $page = $5 + 48 | 0;
+ $6 = $pageSize;
+ $7 = $page;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $8 = HEAP32[$drawing >> 2] | 0;
+ $x35 = $8 + 48 | 0;
+ $9 = +HEAPF64[$x35 >> 3];
+ $cmp36 = $9 > .001;
+ if ($cmp36) {
+ label = 13;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $y40 = $8 + 56 | 0;
+ $10 = +HEAPF64[$y40 >> 3];
+ $cmp41 = $10 > .001;
+ if ($cmp41) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP8[$graph_sets_pageSize] = 1;
+ label = 15;
+ break;
+ case 15:
+ $11 = HEAP32[$drawing >> 2] | 0;
+ $landscape = $11 + 81 | 0;
+ $12 = HEAP8[$landscape] | 0;
+ $tobool47 = $12 << 24 >> 24 == 0;
+ $rotation = $gvc + 264 | 0;
+ $_ = $tobool47 ? 0 : 90;
+ HEAP32[$rotation >> 2] = $_;
+ $pagedir = $gvc + 168 | 0;
+ HEAP32[$pagedir >> 2] = 106496;
+ $call51 = _agget($0, 106088) | 0;
+ $tobool52 = ($call51 | 0) == 0;
+ if ($tobool52) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $13 = HEAP8[$call51] | 0;
+ $tobool54 = $13 << 24 >> 24 == 0;
+ if ($tobool54) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ HEAP32[$pagedir >> 2] = $call51;
+ label = 18;
+ break;
+ case 18:
+ $bb = $gvc + 232 | 0;
+ $bb59 = $g + 56 | 0;
+ $14 = $bb;
+ $15 = $bb59;
+ HEAP32[$14 >> 2] = HEAP32[$15 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$15 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$15 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$15 + 12 >> 2] | 0;
+ HEAP32[$14 + 16 >> 2] = HEAP32[$15 + 16 >> 2] | 0;
+ HEAP32[$14 + 20 >> 2] = HEAP32[$15 + 20 >> 2] | 0;
+ HEAP32[$14 + 24 >> 2] = HEAP32[$15 + 24 >> 2] | 0;
+ HEAP32[$14 + 28 >> 2] = HEAP32[$15 + 28 >> 2] | 0;
+ $root = $g + 32 | 0;
+ $16 = HEAP32[$root >> 2] | 0;
+ $17 = $16 | 0;
+ $call60 = _agfindattr($17, 105760) | 0;
+ HEAP32[41862] = $call60;
+ $18 = HEAP32[$root >> 2] | 0;
+ $19 = $18 | 0;
+ $call62 = _agfindattr($19, 105376) | 0;
+ HEAP32[41864] = $call62;
+ $proto = $g + 40 | 0;
+ $20 = HEAP32[$proto >> 2] | 0;
+ $n = $20 | 0;
+ $21 = HEAP32[$n >> 2] | 0;
+ $22 = $21 | 0;
+ $23 = HEAP32[41598] | 0;
+ $call63 = _late_nnstring($22, $23, 105056) | 0;
+ $defaultfontname = $gvc + 288 | 0;
+ HEAP32[$defaultfontname >> 2] = $call63;
+ $24 = HEAP32[$proto >> 2] | 0;
+ $n65 = $24 | 0;
+ $25 = HEAP32[$n65 >> 2] | 0;
+ $26 = $25 | 0;
+ $27 = HEAP32[41596] | 0;
+ $call66 = +_late_double($26, $27, 14.0, 1.0);
+ $defaultfontsize = $gvc + 296 | 0;
+ HEAPF64[$defaultfontsize >> 3] = $call66;
+ $defaultlinestyle = $gvc + 304 | 0;
+ HEAP32[$defaultlinestyle >> 2] = 21184;
+ $name = $g + 12 | 0;
+ $28 = HEAP32[$name >> 2] | 0;
+ $graphname = $gvc + 160 | 0;
+ HEAP32[$graphname >> 2] = $28;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _init_layering($gvc, $g) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ var $layers = 0, $0 = 0, $tobool = 0, $layerIDs = 0, $1 = 0, $tobool3 = 0, $2 = 0, $3 = 0, $call = 0, $cmp = 0, $call9 = 0, $numLayers = 0, $numLayers11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $layers = $gvc + 276 | 0;
+ $0 = HEAP32[$layers >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _free($0);
+ HEAP32[$layers >> 2] = 0;
+ label = 4;
+ break;
+ case 4:
+ $layerIDs = $gvc + 280 | 0;
+ $1 = HEAP32[$layerIDs >> 2] | 0;
+ $tobool3 = ($1 | 0) == 0;
+ if ($tobool3) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = $1;
+ _free($2);
+ HEAP32[$layerIDs >> 2] = 0;
+ label = 6;
+ break;
+ case 6:
+ $3 = $g | 0;
+ $call = _agget($3, 109136) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call9 = _parse_layers($gvc, $g, $call) | 0;
+ $numLayers = $gvc + 284 | 0;
+ HEAP32[$numLayers >> 2] = $call9;
+ label = 9;
+ break;
+ case 8:
+ HEAP32[$layerIDs >> 2] = 0;
+ $numLayers11 = $gvc + 284 | 0;
+ HEAP32[$numLayers11 >> 2] = 1;
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _chkOrder($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $1 = 0, $add_ptr = 0, $call2 = 0, $tobool3 = 0, $add_ptr9 = 0, $call10 = 0, $tobool11 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g | 0;
+ $call = _agget($0, 110256) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$call] | 0;
+ if (($1 << 24 >> 24 | 0) == 110) {
+ label = 4;
+ break;
+ } else if (($1 << 24 >> 24 | 0) == 101) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $add_ptr = $call + 1 | 0;
+ $call2 = _strcmp($add_ptr | 0, 109848) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $add_ptr9 = $call + 1 | 0;
+ $call10 = _strcmp($add_ptr9 | 0, 109496) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ if ($tobool11) {
+ $retval_0 = 16;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $retval_0 = 0;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _init_job_pad($job) {
+ $job = $job | 0;
+ var $gvc1 = 0, $0 = 0, $graph_sets_pad = 0, $1 = 0, $tobool = 0, $pad = 0, $pad2 = 0, $2 = 0, $3 = 0, $output_lang = 0, $4 = 0, $cond = 0, $features = 0, $5 = 0, $default_pad = 0, $6 = 0.0, $y = 0, $x = 0, $y6 = 0, $x8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $graph_sets_pad = $0 + 268 | 0;
+ $1 = HEAP8[$graph_sets_pad] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $pad = $job + 240 | 0;
+ $pad2 = $0 + 192 | 0;
+ $2 = $pad;
+ $3 = $pad2;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ label = 7;
+ break;
+ case 4:
+ $output_lang = $job + 56 | 0;
+ $4 = HEAP32[$output_lang >> 2] | 0;
+ $cond = ($4 | 0) == 300;
+ if ($cond) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $features = $job + 68 | 0;
+ $5 = HEAP32[$features >> 2] | 0;
+ $default_pad = $5 + 8 | 0;
+ $6 = +HEAPF64[$default_pad >> 3];
+ $y = $job + 248 | 0;
+ HEAPF64[$y >> 3] = $6;
+ $x = $job + 240 | 0;
+ HEAPF64[$x >> 3] = $6;
+ label = 7;
+ break;
+ case 6:
+ $y6 = $job + 248 | 0;
+ HEAPF64[$y6 >> 3] = 4.0;
+ $x8 = $job + 240 | 0;
+ HEAPF64[$x8 >> 3] = 4.0;
+ label = 7;
+ break;
+ case 7:
+ return;
+ }
+}
+function _init_job_margin($job) {
+ $job = $job | 0;
+ var $gvc1 = 0, $0 = 0, $graph_sets_margin = 0, $1 = 0, $tobool = 0, $margin = 0, $margin2 = 0, $2 = 0, $3 = 0, $output_lang = 0, $4 = 0, $margin3 = 0, $features = 0, $5 = 0, $default_margin = 0, $6 = 0, $7 = 0, $y = 0, $x = 0, $x10 = 0, $8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $graph_sets_margin = $0 + 269 | 0;
+ $1 = HEAP8[$graph_sets_margin] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $margin = $job + 416 | 0;
+ $margin2 = $0 + 176 | 0;
+ $2 = $margin;
+ $3 = $margin2;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ label = 8;
+ break;
+ case 4:
+ $output_lang = $job + 56 | 0;
+ $4 = HEAP32[$output_lang >> 2] | 0;
+ if (($4 | 0) == 300) {
+ label = 5;
+ break;
+ } else if (($4 | 0) == 2 | ($4 | 0) == 3 | ($4 | 0) == 4 | ($4 | 0) == 22 | ($4 | 0) == 21 | ($4 | 0) == 30) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $margin3 = $job + 416 | 0;
+ $features = $job + 84 | 0;
+ $5 = HEAP32[$features >> 2] | 0;
+ $default_margin = $5 + 8 | 0;
+ $6 = $margin3;
+ $7 = $default_margin;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ label = 8;
+ break;
+ case 6:
+ $y = $job + 424 | 0;
+ HEAPF64[$y >> 3] = 36.0;
+ $x = $job + 416 | 0;
+ HEAPF64[$x >> 3] = 36.0;
+ label = 8;
+ break;
+ case 7:
+ $x10 = $job + 416 | 0;
+ $8 = $x10;
+ _memset($8 | 0, 0, 16);
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _init_job_dpi($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $gvc = 0, $0 = 0, $active_jobs = 0, $1 = 0, $drawing = 0, $2 = 0, $dpi = 0, $3 = 0.0, $cmp = 0, $y = 0, $x = 0, $tobool = 0, $device_sets_dpi = 0, $4 = 0, $tobool6 = 0, $dpi8 = 0, $device_dpi = 0, $5 = 0, $6 = 0, $output_lang = 0, $7 = 0, $cond = 0, $dpi10 = 0, $features = 0, $8 = 0, $default_dpi = 0, $9 = 0, $10 = 0, $y12 = 0, $x14 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc = $job | 0;
+ $0 = HEAP32[$gvc >> 2] | 0;
+ $active_jobs = $0 + 164 | 0;
+ $1 = HEAP32[$active_jobs >> 2] | 0;
+ $drawing = $g + 48 | 0;
+ $2 = HEAP32[$drawing >> 2] | 0;
+ $dpi = $2 + 24 | 0;
+ $3 = +HEAPF64[$dpi >> 3];
+ $cmp = $3 != 0.0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $y = $job + 440 | 0;
+ HEAPF64[$y >> 3] = $3;
+ $x = $job + 432 | 0;
+ HEAPF64[$x >> 3] = $3;
+ label = 10;
+ break;
+ case 4:
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $device_sets_dpi = $1 + 128 | 0;
+ $4 = HEAP8[$device_sets_dpi] | 0;
+ $tobool6 = $4 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $dpi8 = $job + 432 | 0;
+ $device_dpi = $1 + 112 | 0;
+ $5 = $dpi8;
+ $6 = $device_dpi;
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ label = 10;
+ break;
+ case 7:
+ $output_lang = $job + 56 | 0;
+ $7 = HEAP32[$output_lang >> 2] | 0;
+ $cond = ($7 | 0) == 300;
+ $dpi10 = $job + 432 | 0;
+ if ($cond) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $features = $job + 84 | 0;
+ $8 = HEAP32[$features >> 2] | 0;
+ $default_dpi = $8 + 40 | 0;
+ $9 = $dpi10;
+ $10 = $default_dpi;
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ label = 10;
+ break;
+ case 9:
+ $y12 = $job + 440 | 0;
+ HEAPF64[$y12 >> 3] = 96.0;
+ $x14 = $dpi10 | 0;
+ HEAPF64[$x14 >> 3] = 96.0;
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _init_job_viewport($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $X = 0, $Y = 0, $Z = 0, $x = 0, $y = 0, $gvc1 = 0, $0 = 0, $UR_sroa_0_0__idx = 0, $UR_sroa_0_0_copyload = 0.0, $UR_sroa_1_8__idx33 = 0, $UR_sroa_1_8_copyload = 0.0, $LL_sroa_0_0__idx = 0, $LL_sroa_0_0_copyload = 0.0, $LL_sroa_1_8__idx36 = 0, $LL_sroa_1_8_copyload = 0.0, $x6 = 0, $1 = 0.0, $sub = 0.0, $x9 = 0, $y12 = 0, $2 = 0.0, $sub13 = 0.0, $y16 = 0, $3 = 0.0, $add = 0.0, $x22 = 0, $4 = 0.0, $add26 = 0.0, $y29 = 0, $5 = 0.0, $6 = 0.0, $sub36 = 0.0, $7 = 0.0, $sub44 = 0.0, $drawing = 0, $8 = 0, $x47 = 0, $9 = 0.0, $cmp = 0, $y51 = 0, $10 = 0.0, $cmp52 = 0, $cmp58 = 0, $cmp61 = 0, $or_cond = 0, $filled = 0, $11 = 0, $tobool = 0, $cmp68 = 0, $or_cond63 = 0, $cmp73 = 0, $or_cond64 = 0, $div = 0.0, $div80 = 0.0, $cmp81 = 0, $div_div80 = 0.0, $add92 = 0.0, $div93 = 0.0, $add96 = 0.0, $div97 = 0.0, $12 = 0, $rotation = 0, $13 = 0, $rotation99 = 0, $14 = 0.0, $mul = 0.0, $mul102 = 0.0, $15 = 0, $call = 0, $tobool103 = 0, $call105 = 0, $add106 = 0, $call107 = 0, $call108 = 0, $add109 = 0, $call110 = 0, $call111 = 0, $cmp112 = 0, $root = 0, $16 = 0, $17 = 0, $call115 = 0, $tobool116 = 0, $u118 = 0, $coord = 0, $x119 = 0, $18 = 0.0, $y122 = 0, $19 = 0, $20 = 0.0, $call124 = 0, $cmp125 = 0, $root128 = 0, $21 = 0, $22 = 0, $call129 = 0, $tobool130 = 0, $u132 = 0, $coord133 = 0, $x134 = 0, $23 = 0.0, $y137 = 0, $24 = 0, $25 = 0.0, $call140 = 0, $26 = 0.0, $x144 = 0, $27 = 0.0, $y146 = 0, $28 = 0.0, $zoom = 0, $29 = 0.0, $x147 = 0, $30 = 0.0, $y149 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $X = __stackBase__ | 0;
+ $Y = __stackBase__ + 8 | 0;
+ $Z = __stackBase__ + 16 | 0;
+ $x = __stackBase__ + 24 | 0;
+ $y = __stackBase__ + 32 | 0;
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $UR_sroa_0_0__idx = $0 + 248 | 0;
+ $UR_sroa_0_0_copyload = +HEAPF64[$UR_sroa_0_0__idx >> 3];
+ $UR_sroa_1_8__idx33 = $0 + 256 | 0;
+ $UR_sroa_1_8_copyload = +HEAPF64[$UR_sroa_1_8__idx33 >> 3];
+ $LL_sroa_0_0__idx = $0 + 232 | 0;
+ $LL_sroa_0_0_copyload = +HEAPF64[$LL_sroa_0_0__idx >> 3];
+ $LL_sroa_1_8__idx36 = $0 + 240 | 0;
+ $LL_sroa_1_8_copyload = +HEAPF64[$LL_sroa_1_8__idx36 >> 3];
+ $x6 = $job + 240 | 0;
+ $1 = +HEAPF64[$x6 >> 3];
+ $sub = $LL_sroa_0_0_copyload - $1;
+ $x9 = $job + 208 | 0;
+ HEAPF64[$x9 >> 3] = $sub;
+ $y12 = $job + 248 | 0;
+ $2 = +HEAPF64[$y12 >> 3];
+ $sub13 = $LL_sroa_1_8_copyload - $2;
+ $y16 = $job + 216 | 0;
+ HEAPF64[$y16 >> 3] = $sub13;
+ $3 = +HEAPF64[$x6 >> 3];
+ $add = $UR_sroa_0_0_copyload + $3;
+ $x22 = $job + 224 | 0;
+ HEAPF64[$x22 >> 3] = $add;
+ $4 = +HEAPF64[$y12 >> 3];
+ $add26 = $UR_sroa_1_8_copyload + $4;
+ $y29 = $job + 232 | 0;
+ HEAPF64[$y29 >> 3] = $add26;
+ $5 = +HEAPF64[$x22 >> 3];
+ $6 = +HEAPF64[$x9 >> 3];
+ $sub36 = $5 - $6;
+ $7 = +HEAPF64[$y16 >> 3];
+ $sub44 = $add26 - $7;
+ HEAPF64[$Z >> 3] = 1.0;
+ $drawing = $g + 48 | 0;
+ $8 = HEAP32[$drawing >> 2] | 0;
+ $x47 = $8 + 64 | 0;
+ $9 = +HEAPF64[$x47 >> 3];
+ $cmp = $9 > .001;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $y51 = $8 + 72 | 0;
+ $10 = +HEAPF64[$y51 >> 3];
+ $cmp52 = $10 > .001;
+ if ($cmp52) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $cmp58 = $9 < $sub36;
+ $cmp61 = $10 < $sub44;
+ $or_cond = $cmp58 | $cmp61;
+ if ($or_cond) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $filled = $8 + 80 | 0;
+ $11 = HEAP8[$filled] | 0;
+ $tobool = $11 << 24 >> 24 != 0;
+ $cmp68 = $9 > $sub36;
+ $or_cond63 = $tobool & $cmp68;
+ $cmp73 = $10 > $sub44;
+ $or_cond64 = $or_cond63 & $cmp73;
+ if ($or_cond64) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $div = $9 / $sub36;
+ $div80 = $10 / $sub44;
+ $cmp81 = $div < $div80;
+ $div_div80 = $cmp81 ? $div : $div80;
+ HEAPF64[$Z >> 3] = $div_div80;
+ label = 7;
+ break;
+ case 7:
+ $add92 = $UR_sroa_0_0_copyload + $LL_sroa_0_0_copyload;
+ $div93 = $add92 * .5;
+ HEAPF64[$x >> 3] = $div93;
+ $add96 = $UR_sroa_1_8_copyload + $LL_sroa_1_8_copyload;
+ $div97 = $add96 * .5;
+ HEAPF64[$y >> 3] = $div97;
+ $12 = HEAP32[$gvc1 >> 2] | 0;
+ $rotation = $12 + 264 | 0;
+ $13 = HEAP32[$rotation >> 2] | 0;
+ $rotation99 = $job + 360 | 0;
+ HEAP32[$rotation99 >> 2] = $13;
+ $14 = +HEAPF64[$Z >> 3];
+ $mul = $sub36 * $14;
+ HEAPF64[$X >> 3] = $mul;
+ $mul102 = $sub44 * $14;
+ HEAPF64[$Y >> 3] = $mul102;
+ $15 = $g | 0;
+ $call = _agget($15, 111960) | 0;
+ $tobool103 = ($call | 0) == 0;
+ if ($tobool103) {
+ label = 16;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call105 = _strlen($call | 0) | 0;
+ $add106 = $call105 + 1 | 0;
+ $call107 = _malloc($add106) | 0;
+ $call108 = _strlen($call | 0) | 0;
+ $add109 = $call108 + 1 | 0;
+ $call110 = _malloc($add109) | 0;
+ $call111 = _sscanf($call | 0, 111496, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $X, HEAP32[tempInt + 8 >> 2] = $Y, HEAP32[tempInt + 16 >> 2] = $Z, HEAP32[tempInt + 24 >> 2] = $call107, tempInt) | 0) | 0;
+ $cmp112 = ($call111 | 0) == 4;
+ if ($cmp112) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $root = $g + 32 | 0;
+ $16 = HEAP32[$root >> 2] | 0;
+ $17 = $16;
+ $call115 = _agfindnode($17, $call107) | 0;
+ $tobool116 = ($call115 | 0) == 0;
+ if ($tobool116) {
+ label = 15;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $u118 = $call115 + 24 | 0;
+ $coord = $u118 + 8 | 0;
+ $x119 = $coord;
+ $18 = +HEAPF64[$x119 >> 3];
+ HEAPF64[$x >> 3] = $18;
+ $y122 = $u118 + 16 | 0;
+ $19 = $y122;
+ $20 = +HEAPF64[$19 >> 3];
+ HEAPF64[$y >> 3] = $20;
+ label = 15;
+ break;
+ case 11:
+ $call124 = _sscanf($call | 0, 111064, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = $X, HEAP32[tempInt + 8 >> 2] = $Y, HEAP32[tempInt + 16 >> 2] = $Z, HEAP32[tempInt + 24 >> 2] = $call107, HEAP32[tempInt + 32 >> 2] = $call110, tempInt) | 0) | 0;
+ $cmp125 = ($call124 | 0) == 4;
+ if ($cmp125) {
+ label = 12;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ $root128 = $g + 32 | 0;
+ $21 = HEAP32[$root128 >> 2] | 0;
+ $22 = $21;
+ $call129 = _agfindnode($22, $call107) | 0;
+ $tobool130 = ($call129 | 0) == 0;
+ if ($tobool130) {
+ label = 15;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $u132 = $call129 + 24 | 0;
+ $coord133 = $u132 + 8 | 0;
+ $x134 = $coord133;
+ $23 = +HEAPF64[$x134 >> 3];
+ HEAPF64[$x >> 3] = $23;
+ $y137 = $u132 + 16 | 0;
+ $24 = $y137;
+ $25 = +HEAPF64[$24 >> 3];
+ HEAPF64[$y >> 3] = $25;
+ label = 15;
+ break;
+ case 14:
+ $call140 = _sscanf($call | 0, 110680, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = $X, HEAP32[tempInt + 8 >> 2] = $Y, HEAP32[tempInt + 16 >> 2] = $Z, HEAP32[tempInt + 24 >> 2] = $x, HEAP32[tempInt + 32 >> 2] = $y, tempInt) | 0) | 0;
+ label = 15;
+ break;
+ case 15:
+ _free($call107);
+ _free($call110);
+ label = 16;
+ break;
+ case 16:
+ $26 = +HEAPF64[$X >> 3];
+ $x144 = $job + 368 | 0;
+ HEAPF64[$x144 >> 3] = $26;
+ $27 = +HEAPF64[$Y >> 3];
+ $y146 = $job + 376 | 0;
+ HEAPF64[$y146 >> 3] = $27;
+ $28 = +HEAPF64[$Z >> 3];
+ $zoom = $job + 352 | 0;
+ HEAPF64[$zoom >> 3] = $28;
+ $29 = +HEAPF64[$x >> 3];
+ $x147 = $job + 336 | 0;
+ HEAPF64[$x147 >> 3] = $29;
+ $30 = +HEAPF64[$y >> 3];
+ $y149 = $job + 344 | 0;
+ HEAPF64[$y149 >> 3] = $30;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _exch_xyf($agg_result, $p) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ var $1 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $1 = +HEAPF64[$p >> 3];
+ HEAPF64[$agg_result >> 3] = +HEAPF64[$p + 8 >> 3];
+ HEAPF64[$agg_result + 8 >> 3] = $1;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _pagecode($agg_result, $job, $c) {
+ $agg_result = $agg_result | 0;
+ $job = $job | 0;
+ $c = $c | 0;
+ var $conv = 0, $y1 = 0, $0 = 0, $sub = 0, $y2 = 0, $x10 = 0, $1 = 0, $sub11 = 0, $x13 = 0, $rv_sroa_1_0 = 0, $rv_sroa_0_0 = 0, $rv_sroa_0_0__idx = 0, $rv_sroa_1_4__idx1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $conv = $c << 24 >> 24;
+ if (($conv | 0) == 84) {
+ label = 3;
+ break;
+ } else if (($conv | 0) == 66) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 76) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 82) {
+ label = 6;
+ break;
+ } else {
+ $rv_sroa_0_0 = 0;
+ $rv_sroa_1_0 = 0;
+ label = 7;
+ break;
+ }
+ case 3:
+ $y1 = $job + 168 | 0;
+ $0 = HEAP32[$y1 >> 2] | 0;
+ $sub = $0 - 1 | 0;
+ $y2 = $job + 176 | 0;
+ HEAP32[$y2 >> 2] = $sub;
+ $rv_sroa_0_0 = 0;
+ $rv_sroa_1_0 = -1;
+ label = 7;
+ break;
+ case 4:
+ $rv_sroa_0_0 = 0;
+ $rv_sroa_1_0 = 1;
+ label = 7;
+ break;
+ case 5:
+ $rv_sroa_0_0 = 1;
+ $rv_sroa_1_0 = 0;
+ label = 7;
+ break;
+ case 6:
+ $x10 = $job + 164 | 0;
+ $1 = HEAP32[$x10 >> 2] | 0;
+ $sub11 = $1 - 1 | 0;
+ $x13 = $job + 172 | 0;
+ HEAP32[$x13 >> 2] = $sub11;
+ $rv_sroa_0_0 = -1;
+ $rv_sroa_1_0 = 0;
+ label = 7;
+ break;
+ case 7:
+ $rv_sroa_0_0__idx = $agg_result | 0;
+ HEAP32[$rv_sroa_0_0__idx >> 2] = $rv_sroa_0_0;
+ $rv_sroa_1_4__idx1 = $agg_result + 4 | 0;
+ HEAP32[$rv_sroa_1_4__idx1 >> 2] = $rv_sroa_1_0;
+ return;
+ }
+}
+function _exch_xy($agg_result, $p) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ var $1 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ $1 = HEAP32[$p >> 2] | 0;
+ HEAP32[$agg_result >> 2] = HEAP32[$p + 4 >> 2] | 0;
+ HEAP32[$agg_result + 4 >> 2] = $1;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _init_job_pagination($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $pageSize = 0, $imageSize = 0, $margin = 0, $centering = 0, $tmp = 0, $tmp219 = 0, $tmpcast = 0, $tmp223 = 0, $tmpcast85 = 0, $tmp241 = 0, $tmpcast88 = 0, $tmp243 = 0, $tmpcast89 = 0, $tmp275 = 0, $tmp276 = 0, $tmp277 = 0, $tmp278 = 0, $tmp456 = 0, $tmpcast86 = 0, $tmp461 = 0, $tmpcast87 = 0, $gvc1 = 0, $0 = 0, $1 = 0, $view = 0, $2 = 0, $3 = 0, $rotation = 0, $4 = 0, $tobool = 0, $5 = 0, $margin2 = 0, $6 = 0, $7 = 0, $graph_sets_pageSize = 0, $8 = 0, $tobool3 = 0, $flags = 0, $9 = 0, $and = 0, $tobool4 = 0, $x = 0, $10 = 0.0, $x7 = 0, $11 = 0.0, $mul = 0.0, $sub = 0.0, $x8 = 0, $y = 0, $12 = 0.0, $y10 = 0, $13 = 0.0, $mul11 = 0.0, $sub12 = 0.0, $y13 = 0, $14 = 0.0, $cmp = 0, $x17 = 0, $x18 = 0, $15 = 0.0, $div = 0.0, $conv20 = 0, $x22 = 0, $16 = 0.0, $conv26 = 0.0, $17 = 0.0, $mul28 = 0.0, $sub29 = 0.0, $cmp30 = 0, $inc = 0, $18 = 0.0, $cmp38 = 0, $y42 = 0, $y44 = 0, $19 = 0.0, $div46 = 0.0, $conv47 = 0, $y49 = 0, $20 = 0.0, $conv53 = 0.0, $21 = 0.0, $mul55 = 0.0, $sub56 = 0.0, $cmp57 = 0, $inc62 = 0, $x66 = 0, $22 = 0, $y68 = 0, $23 = 0, $mul69 = 0, $numPages = 0, $x70 = 0, $24 = 0.0, $25 = 0.0, $cmp72 = 0, $_ = 0.0, $y77 = 0, $26 = 0.0, $27 = 0.0, $cmp79 = 0, $cond86 = 0.0, $features = 0, $28 = 0, $tobool89 = 0, $features91 = 0, $29 = 0, $x92 = 0, $30 = 0.0, $x93 = 0, $31 = 0.0, $mul94 = 0.0, $sub95 = 0.0, $x96 = 0, $cmp98 = 0, $storemerge = 0.0, $32 = 0, $y106 = 0, $33 = 0.0, $y107 = 0, $34 = 0.0, $mul108 = 0.0, $sub109 = 0.0, $y110 = 0, $cmp112 = 0, $35 = 0, $numPages121 = 0, $y123 = 0, $x125 = 0, $x126 = 0, $36 = 0.0, $x127 = 0, $37 = 0.0, $cmp128 = 0, $y134 = 0, $38 = 0.0, $y135 = 0, $39 = 0.0, $cmp136 = 0, $x143 = 0, $40 = 0.0, $x144 = 0, $41 = 0.0, $mul145 = 0.0, $add = 0.0, $x146 = 0, $42 = 0.0, $mul147 = 0.0, $div148 = 0.0, $cmp149 = 0, $add160 = 0.0, $sub171 = 0.0, $add160_sink = 0.0, $conv161 = 0, $width = 0, $y175 = 0, $43 = 0.0, $y176 = 0, $44 = 0.0, $mul177 = 0.0, $add178 = 0.0, $y180 = 0, $45 = 0.0, $mul181 = 0.0, $div182 = 0.0, $cmp183 = 0, $add194 = 0.0, $sub205 = 0.0, $add194_sink = 0.0, $conv195 = 0, $height = 0, $pagesArrayMinor = 0, $x211 = 0, $pagesArrayMajor = 0, $x214 = 0, $x217 = 0, $pagedir = 0, $46 = 0, $47 = 0, $48 = 0, $49 = 0, $ld$0$0 = 0, $50$0 = 0, $ld$1$1 = 0, $50$1 = 0, $st$2$0 = 0, $st$3$1 = 0, $51 = 0, $arrayidx222 = 0, $52 = 0, $53 = 0, $ld$4$0 = 0, $54$0 = 0, $ld$5$1 = 0, $54$1 = 0, $st$6$0 = 0, $st$7$1 = 0, $55 = 0, $56 = 0, $add228 = 0, $ispos = 0, $neg = 0, $call = 0, $cmp229 = 0, $y212 = 0, $y209 = 0, $57 = 0, $58 = 0, $add235 = 0, $ispos90 = 0, $neg91 = 0, $call236 = 0, $cmp237 = 0, $ld$8$0 = 0, $59$0 = 0, $ld$9$1 = 0, $59$1 = 0, $st$10$0 = 0, $st$11$1 = 0, $ld$12$0 = 0, $60$0 = 0, $ld$13$1 = 0, $60$1 = 0, $st$14$0 = 0, $st$15$1 = 0, $61 = 0, $call245 = 0, $drawing = 0, $62 = 0, $centered = 0, $63 = 0, $tobool247 = 0, $64 = 0.0, $x250 = 0, $65 = 0.0, $cmp251 = 0, $sub256 = 0.0, $div257 = 0.0, $x258 = 0, $66 = 0.0, $y261 = 0, $67 = 0.0, $cmp262 = 0, $sub267 = 0.0, $div268 = 0.0, $y269 = 0, $68 = 0, $tobool273 = 0, $69 = 0, $70 = 0, $71 = 0, $72 = 0, $73 = 0, $74 = 0.0, $x281 = 0, $75 = 0.0, $add282 = 0.0, $x283 = 0, $76 = 0.0, $y285 = 0, $77 = 0.0, $add286 = 0.0, $y289 = 0, $78 = 0.0, $79 = 0.0, $add292 = 0.0, $x293 = 0, $80 = 0.0, $add294 = 0.0, $x296 = 0, $81 = 0.0, $82 = 0.0, $add299 = 0.0, $y300 = 0, $83 = 0.0, $add301 = 0.0, $y304 = 0, $84 = 0.0, $zoom = 0, $85 = 0.0, $div306 = 0.0, $x308 = 0, $86 = 0.0, $87 = 0.0, $div311 = 0.0, $y313 = 0, $88 = 0.0, $89 = 0.0, $mul319 = 0.0, $div320 = 0.0, $cmp321 = 0, $add331 = 0.0, $sub341 = 0.0, $add331_sink = 0.0, $conv332 = 0, $pageBoundingBox = 0, $LL345 = 0, $x346 = 0, $90 = 0.0, $91 = 0.0, $mul352 = 0.0, $div353 = 0.0, $cmp354 = 0, $add364 = 0.0, $sub374 = 0.0, $add364_sink = 0.0, $conv365 = 0, $y380 = 0, $92 = 0.0, $93 = 0.0, $mul386 = 0.0, $div387 = 0.0, $cmp388 = 0, $add398 = 0.0, $sub408 = 0.0, $add398_sink = 0.0, $conv399 = 0, $UR413 = 0, $x414 = 0, $94 = 0.0, $95 = 0.0, $mul420 = 0.0, $div421 = 0.0, $cmp422 = 0, $add432 = 0.0, $sub442 = 0.0, $add432_sink = 0.0, $conv433 = 0, $y448 = 0, $96 = 0, $tobool450 = 0, $97 = 0, $ld$16$0 = 0, $98$0 = 0, $ld$17$1 = 0, $98$1 = 0, $st$18$0 = 0, $st$19$1 = 0, $99 = 0, $ld$20$0 = 0, $100$0 = 0, $ld$21$1 = 0, $100$1 = 0, $st$22$0 = 0, $st$23$1 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 88 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pageSize = __stackBase__ | 0;
+ $imageSize = __stackBase__ + 16 | 0;
+ $margin = __stackBase__ + 32 | 0;
+ $centering = __stackBase__ + 48 | 0;
+ $tmp = __stackBase__ + 64 | 0;
+ $tmp219 = __stackBase__ + 80 | 0;
+ $tmpcast = $tmp219;
+ $tmp223 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast85 = $tmp223;
+ $tmp241 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast88 = $tmp241;
+ $tmp243 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast89 = $tmp243;
+ $tmp275 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $tmp276 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $tmp277 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $tmp278 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $tmp456 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast86 = $tmp456;
+ $tmp461 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast87 = $tmp461;
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $1 = $centering;
+ _memset($1 | 0, 0, 16);
+ $view = $job + 368 | 0;
+ $2 = $imageSize;
+ $3 = $view;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $rotation = $job + 360 | 0;
+ $4 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _exch_xyf($tmp, $imageSize);
+ $5 = $tmp;
+ HEAP32[$2 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ label = 4;
+ break;
+ case 4:
+ $margin2 = $job + 416 | 0;
+ $6 = $margin;
+ $7 = $margin2;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $graph_sets_pageSize = $0 + 270 | 0;
+ $8 = HEAP8[$graph_sets_pageSize] | 0;
+ $tobool3 = $8 << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 15;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $flags = $job + 152 | 0;
+ $9 = HEAP32[$flags >> 2] | 0;
+ $and = $9 & 32;
+ $tobool4 = ($and | 0) == 0;
+ if ($tobool4) {
+ label = 15;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $x = $0 + 208 | 0;
+ $10 = +HEAPF64[$x >> 3];
+ $x7 = $margin | 0;
+ $11 = +HEAPF64[$x7 >> 3];
+ $mul = $11 * 2.0;
+ $sub = $10 - $mul;
+ $x8 = $pageSize | 0;
+ HEAPF64[$x8 >> 3] = $sub;
+ $y = $0 + 216 | 0;
+ $12 = +HEAPF64[$y >> 3];
+ $y10 = $margin + 8 | 0;
+ $13 = +HEAPF64[$y10 >> 3];
+ $mul11 = $13 * 2.0;
+ $sub12 = $12 - $mul11;
+ $y13 = $pageSize + 8 | 0;
+ HEAPF64[$y13 >> 3] = $sub12;
+ $14 = +HEAPF64[$x8 >> 3];
+ $cmp = $14 < 1.0e-4;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $x17 = $job + 164 | 0;
+ HEAP32[$x17 >> 2] = 1;
+ label = 10;
+ break;
+ case 8:
+ $x18 = $imageSize | 0;
+ $15 = +HEAPF64[$x18 >> 3];
+ $div = $15 / $14;
+ $conv20 = ~~$div;
+ $x22 = $job + 164 | 0;
+ HEAP32[$x22 >> 2] = $conv20;
+ $16 = +HEAPF64[$x18 >> 3];
+ $conv26 = +($conv20 | 0);
+ $17 = +HEAPF64[$x8 >> 3];
+ $mul28 = $conv26 * $17;
+ $sub29 = $16 - $mul28;
+ $cmp30 = $sub29 > 1.0e-4;
+ if ($cmp30) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $inc = $conv20 + 1 | 0;
+ HEAP32[$x22 >> 2] = $inc;
+ label = 10;
+ break;
+ case 10:
+ $18 = +HEAPF64[$y13 >> 3];
+ $cmp38 = $18 < 1.0e-4;
+ if ($cmp38) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $y42 = $job + 168 | 0;
+ HEAP32[$y42 >> 2] = 1;
+ label = 14;
+ break;
+ case 12:
+ $y44 = $imageSize + 8 | 0;
+ $19 = +HEAPF64[$y44 >> 3];
+ $div46 = $19 / $18;
+ $conv47 = ~~$div46;
+ $y49 = $job + 168 | 0;
+ HEAP32[$y49 >> 2] = $conv47;
+ $20 = +HEAPF64[$y44 >> 3];
+ $conv53 = +($conv47 | 0);
+ $21 = +HEAPF64[$y13 >> 3];
+ $mul55 = $conv53 * $21;
+ $sub56 = $20 - $mul55;
+ $cmp57 = $sub56 > 1.0e-4;
+ if ($cmp57) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $inc62 = $conv47 + 1 | 0;
+ HEAP32[$y49 >> 2] = $inc62;
+ label = 14;
+ break;
+ case 14:
+ $x66 = $job + 164 | 0;
+ $22 = HEAP32[$x66 >> 2] | 0;
+ $y68 = $job + 168 | 0;
+ $23 = HEAP32[$y68 >> 2] | 0;
+ $mul69 = Math_imul($23, $22);
+ $numPages = $job + 204 | 0;
+ HEAP32[$numPages >> 2] = $mul69;
+ $x70 = $imageSize | 0;
+ $24 = +HEAPF64[$x70 >> 3];
+ $25 = +HEAPF64[$x8 >> 3];
+ $cmp72 = $24 < $25;
+ $_ = $cmp72 ? $24 : $25;
+ HEAPF64[$x70 >> 3] = $_;
+ $y77 = $imageSize + 8 | 0;
+ $26 = +HEAPF64[$y77 >> 3];
+ $27 = +HEAPF64[$y13 >> 3];
+ $cmp79 = $26 < $27;
+ $cond86 = $cmp79 ? $26 : $27;
+ HEAPF64[$y77 >> 3] = $cond86;
+ label = 23;
+ break;
+ case 15:
+ $features = $job + 68 | 0;
+ $28 = HEAP32[$features >> 2] | 0;
+ $tobool89 = ($28 | 0) == 0;
+ if ($tobool89) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $features91 = $job + 84 | 0;
+ $29 = HEAP32[$features91 >> 2] | 0;
+ $x92 = $29 + 24 | 0;
+ $30 = +HEAPF64[$x92 >> 3];
+ $x93 = $margin | 0;
+ $31 = +HEAPF64[$x93 >> 3];
+ $mul94 = $31 * 2.0;
+ $sub95 = $30 - $mul94;
+ $x96 = $pageSize | 0;
+ $cmp98 = $sub95 < 0.0;
+ $storemerge = $cmp98 ? 0.0 : $sub95;
+ HEAPF64[$x96 >> 3] = $storemerge;
+ $32 = HEAP32[$features91 >> 2] | 0;
+ $y106 = $32 + 32 | 0;
+ $33 = +HEAPF64[$y106 >> 3];
+ $y107 = $margin + 8 | 0;
+ $34 = +HEAPF64[$y107 >> 3];
+ $mul108 = $34 * 2.0;
+ $sub109 = $33 - $mul108;
+ $y110 = $pageSize + 8 | 0;
+ HEAPF64[$y110 >> 3] = $sub109;
+ $cmp112 = $sub109 < 0.0;
+ if ($cmp112) {
+ label = 17;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 17:
+ HEAPF64[$y110 >> 3] = 0.0;
+ label = 19;
+ break;
+ case 18:
+ $35 = $pageSize;
+ _memset($35 | 0, 0, 16);
+ label = 19;
+ break;
+ case 19:
+ $numPages121 = $job + 204 | 0;
+ HEAP32[$numPages121 >> 2] = 1;
+ $y123 = $job + 168 | 0;
+ HEAP32[$y123 >> 2] = 1;
+ $x125 = $job + 164 | 0;
+ HEAP32[$x125 >> 2] = 1;
+ $x126 = $pageSize | 0;
+ $36 = +HEAPF64[$x126 >> 3];
+ $x127 = $imageSize | 0;
+ $37 = +HEAPF64[$x127 >> 3];
+ $cmp128 = $36 < $37;
+ if ($cmp128) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ HEAPF64[$x126 >> 3] = $37;
+ label = 21;
+ break;
+ case 21:
+ $y134 = $pageSize + 8 | 0;
+ $38 = +HEAPF64[$y134 >> 3];
+ $y135 = $imageSize + 8 | 0;
+ $39 = +HEAPF64[$y135 >> 3];
+ $cmp136 = $38 < $39;
+ if ($cmp136) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ HEAPF64[$y134 >> 3] = $39;
+ label = 23;
+ break;
+ case 23:
+ $x143 = $pageSize | 0;
+ $40 = +HEAPF64[$x143 >> 3];
+ $x144 = $margin | 0;
+ $41 = +HEAPF64[$x144 >> 3];
+ $mul145 = $41 * 2.0;
+ $add = $40 + $mul145;
+ $x146 = $job + 432 | 0;
+ $42 = +HEAPF64[$x146 >> 3];
+ $mul147 = $42 * $add;
+ $div148 = $mul147 / 72.0;
+ $cmp149 = $div148 < 0.0;
+ if ($cmp149) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $add160 = $div148 + .5;
+ $add160_sink = $add160;
+ label = 26;
+ break;
+ case 25:
+ $sub171 = $div148 + -.5;
+ $add160_sink = $sub171;
+ label = 26;
+ break;
+ case 26:
+ $conv161 = ~~$add160_sink;
+ $width = $job + 448 | 0;
+ HEAP32[$width >> 2] = $conv161;
+ $y175 = $pageSize + 8 | 0;
+ $43 = +HEAPF64[$y175 >> 3];
+ $y176 = $margin + 8 | 0;
+ $44 = +HEAPF64[$y176 >> 3];
+ $mul177 = $44 * 2.0;
+ $add178 = $43 + $mul177;
+ $y180 = $job + 440 | 0;
+ $45 = +HEAPF64[$y180 >> 3];
+ $mul181 = $45 * $add178;
+ $div182 = $mul181 / 72.0;
+ $cmp183 = $div182 < 0.0;
+ if ($cmp183) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $add194 = $div182 + .5;
+ $add194_sink = $add194;
+ label = 29;
+ break;
+ case 28:
+ $sub205 = $div182 + -.5;
+ $add194_sink = $sub205;
+ label = 29;
+ break;
+ case 29:
+ $conv195 = ~~$add194_sink;
+ $height = $job + 452 | 0;
+ HEAP32[$height >> 2] = $conv195;
+ $pagesArrayMinor = $job + 188 | 0;
+ $x211 = $pagesArrayMinor | 0;
+ $pagesArrayMajor = $job + 180 | 0;
+ $x214 = $pagesArrayMajor | 0;
+ $x217 = $job + 172 | 0;
+ $pagedir = $0 + 168 | 0;
+ $46 = $x217;
+ _memset($46 | 0, 0, 24);
+ $47 = HEAP32[$pagedir >> 2] | 0;
+ $48 = HEAP8[$47] | 0;
+ _pagecode($tmpcast, $job, $48);
+ $49 = $pagesArrayMajor;
+ $ld$0$0 = $tmp219 | 0;
+ $50$0 = HEAP32[$ld$0$0 >> 2] | 0;
+ $ld$1$1 = $tmp219 + 4 | 0;
+ $50$1 = HEAP32[$ld$1$1 >> 2] | 0;
+ $st$2$0 = $49 | 0;
+ HEAP32[$st$2$0 >> 2] = $50$0;
+ $st$3$1 = $49 + 4 | 0;
+ HEAP32[$st$3$1 >> 2] = $50$1;
+ $51 = HEAP32[$pagedir >> 2] | 0;
+ $arrayidx222 = $51 + 1 | 0;
+ $52 = HEAP8[$arrayidx222] | 0;
+ _pagecode($tmpcast85, $job, $52);
+ $53 = $pagesArrayMinor;
+ $ld$4$0 = $tmp223 | 0;
+ $54$0 = HEAP32[$ld$4$0 >> 2] | 0;
+ $ld$5$1 = $tmp223 + 4 | 0;
+ $54$1 = HEAP32[$ld$5$1 >> 2] | 0;
+ $st$6$0 = $53 | 0;
+ HEAP32[$st$6$0 >> 2] = $54$0;
+ $st$7$1 = $53 + 4 | 0;
+ HEAP32[$st$7$1 >> 2] = $54$1;
+ $55 = HEAP32[$x214 >> 2] | 0;
+ $56 = HEAP32[$x211 >> 2] | 0;
+ $add228 = $56 + $55 | 0;
+ $ispos = ($add228 | 0) > -1;
+ $neg = -$add228 | 0;
+ $call = $ispos ? $add228 : $neg;
+ $cmp229 = ($call | 0) == 1;
+ if ($cmp229) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $y212 = $job + 184 | 0;
+ $y209 = $job + 192 | 0;
+ $57 = HEAP32[$y212 >> 2] | 0;
+ $58 = HEAP32[$y209 >> 2] | 0;
+ $add235 = $58 + $57 | 0;
+ $ispos90 = ($add235 | 0) > -1;
+ $neg91 = -$add235 | 0;
+ $call236 = $ispos90 ? $add235 : $neg91;
+ $cmp237 = ($call236 | 0) == 1;
+ if ($cmp237) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ _pagecode($tmpcast88, $job, 66);
+ $ld$8$0 = $tmp241 | 0;
+ $59$0 = HEAP32[$ld$8$0 >> 2] | 0;
+ $ld$9$1 = $tmp241 + 4 | 0;
+ $59$1 = HEAP32[$ld$9$1 >> 2] | 0;
+ $st$10$0 = $49 | 0;
+ HEAP32[$st$10$0 >> 2] = $59$0;
+ $st$11$1 = $49 + 4 | 0;
+ HEAP32[$st$11$1 >> 2] = $59$1;
+ _pagecode($tmpcast89, $job, 76);
+ $ld$12$0 = $tmp243 | 0;
+ $60$0 = HEAP32[$ld$12$0 >> 2] | 0;
+ $ld$13$1 = $tmp243 + 4 | 0;
+ $60$1 = HEAP32[$ld$13$1 >> 2] | 0;
+ $st$14$0 = $53 | 0;
+ HEAP32[$st$14$0 >> 2] = $60$0;
+ $st$15$1 = $53 + 4 | 0;
+ HEAP32[$st$15$1 >> 2] = $60$1;
+ $61 = HEAP32[$pagedir >> 2] | 0;
+ $call245 = _agerr(0, 112488, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $61, tempInt) | 0) | 0;
+ label = 32;
+ break;
+ case 32:
+ $drawing = $g + 48 | 0;
+ $62 = HEAP32[$drawing >> 2] | 0;
+ $centered = $62 + 82 | 0;
+ $63 = HEAP8[$centered] | 0;
+ $tobool247 = $63 << 24 >> 24 == 0;
+ if ($tobool247) {
+ label = 37;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $64 = +HEAPF64[$x143 >> 3];
+ $x250 = $imageSize | 0;
+ $65 = +HEAPF64[$x250 >> 3];
+ $cmp251 = $64 > $65;
+ if ($cmp251) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ $sub256 = $64 - $65;
+ $div257 = $sub256 * .5;
+ $x258 = $centering | 0;
+ HEAPF64[$x258 >> 3] = $div257;
+ label = 35;
+ break;
+ case 35:
+ $66 = +HEAPF64[$y175 >> 3];
+ $y261 = $imageSize + 8 | 0;
+ $67 = +HEAPF64[$y261 >> 3];
+ $cmp262 = $66 > $67;
+ if ($cmp262) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ $sub267 = $66 - $67;
+ $div268 = $sub267 * .5;
+ $y269 = $centering + 8 | 0;
+ HEAPF64[$y269 >> 3] = $div268;
+ label = 37;
+ break;
+ case 37:
+ $68 = HEAP32[$rotation >> 2] | 0;
+ $tobool273 = ($68 | 0) == 0;
+ if ($tobool273) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ _exch_xyf($tmp275, $imageSize);
+ $69 = $tmp275;
+ HEAP32[$2 >> 2] = HEAP32[$69 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$69 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$69 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$69 + 12 >> 2] | 0;
+ _exch_xyf($tmp276, $pageSize);
+ $70 = $pageSize;
+ $71 = $tmp276;
+ HEAP32[$70 >> 2] = HEAP32[$71 >> 2] | 0;
+ HEAP32[$70 + 4 >> 2] = HEAP32[$71 + 4 >> 2] | 0;
+ HEAP32[$70 + 8 >> 2] = HEAP32[$71 + 8 >> 2] | 0;
+ HEAP32[$70 + 12 >> 2] = HEAP32[$71 + 12 >> 2] | 0;
+ _exch_xyf($tmp277, $margin);
+ $72 = $tmp277;
+ HEAP32[$6 >> 2] = HEAP32[$72 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$72 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$72 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$72 + 12 >> 2] | 0;
+ _exch_xyf($tmp278, $centering);
+ $73 = $tmp278;
+ HEAP32[$1 >> 2] = HEAP32[$73 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$73 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$73 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$73 + 12 >> 2] | 0;
+ label = 39;
+ break;
+ case 39:
+ $74 = +HEAPF64[$x144 >> 3];
+ $x281 = $centering | 0;
+ $75 = +HEAPF64[$x281 >> 3];
+ $add282 = $74 + $75;
+ $x283 = $job + 384 | 0;
+ HEAPF64[$x283 >> 3] = $add282;
+ $76 = +HEAPF64[$y176 >> 3];
+ $y285 = $centering + 8 | 0;
+ $77 = +HEAPF64[$y285 >> 3];
+ $add286 = $76 + $77;
+ $y289 = $job + 392 | 0;
+ HEAPF64[$y289 >> 3] = $add286;
+ $78 = +HEAPF64[$x144 >> 3];
+ $79 = +HEAPF64[$x281 >> 3];
+ $add292 = $78 + $79;
+ $x293 = $imageSize | 0;
+ $80 = +HEAPF64[$x293 >> 3];
+ $add294 = $add292 + $80;
+ $x296 = $job + 400 | 0;
+ HEAPF64[$x296 >> 3] = $add294;
+ $81 = +HEAPF64[$y176 >> 3];
+ $82 = +HEAPF64[$y285 >> 3];
+ $add299 = $81 + $82;
+ $y300 = $imageSize + 8 | 0;
+ $83 = +HEAPF64[$y300 >> 3];
+ $add301 = $add299 + $83;
+ $y304 = $job + 408 | 0;
+ HEAPF64[$y304 >> 3] = $add301;
+ $84 = +HEAPF64[$x293 >> 3];
+ $zoom = $job + 352 | 0;
+ $85 = +HEAPF64[$zoom >> 3];
+ $div306 = $84 / $85;
+ $x308 = $job + 320 | 0;
+ HEAPF64[$x308 >> 3] = $div306;
+ $86 = +HEAPF64[$y300 >> 3];
+ $87 = +HEAPF64[$zoom >> 3];
+ $div311 = $86 / $87;
+ $y313 = $job + 328 | 0;
+ HEAPF64[$y313 >> 3] = $div311;
+ $88 = +HEAPF64[$x283 >> 3];
+ $89 = +HEAPF64[$x146 >> 3];
+ $mul319 = $88 * $89;
+ $div320 = $mul319 / 72.0;
+ $cmp321 = $div320 < 0.0;
+ if ($cmp321) {
+ label = 41;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $add331 = $div320 + .5;
+ $add331_sink = $add331;
+ label = 42;
+ break;
+ case 41:
+ $sub341 = $div320 + -.5;
+ $add331_sink = $sub341;
+ label = 42;
+ break;
+ case 42:
+ $conv332 = ~~$add331_sink;
+ $pageBoundingBox = $job + 456 | 0;
+ $LL345 = $pageBoundingBox | 0;
+ $x346 = $pageBoundingBox | 0;
+ HEAP32[$x346 >> 2] = $conv332;
+ $90 = +HEAPF64[$y289 >> 3];
+ $91 = +HEAPF64[$y180 >> 3];
+ $mul352 = $90 * $91;
+ $div353 = $mul352 / 72.0;
+ $cmp354 = $div353 < 0.0;
+ if ($cmp354) {
+ label = 44;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $add364 = $div353 + .5;
+ $add364_sink = $add364;
+ label = 45;
+ break;
+ case 44:
+ $sub374 = $div353 + -.5;
+ $add364_sink = $sub374;
+ label = 45;
+ break;
+ case 45:
+ $conv365 = ~~$add364_sink;
+ $y380 = $job + 460 | 0;
+ HEAP32[$y380 >> 2] = $conv365;
+ $92 = +HEAPF64[$x296 >> 3];
+ $93 = +HEAPF64[$x146 >> 3];
+ $mul386 = $92 * $93;
+ $div387 = $mul386 / 72.0;
+ $cmp388 = $div387 < 0.0;
+ if ($cmp388) {
+ label = 47;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $add398 = $div387 + .5;
+ $add398_sink = $add398;
+ label = 48;
+ break;
+ case 47:
+ $sub408 = $div387 + -.5;
+ $add398_sink = $sub408;
+ label = 48;
+ break;
+ case 48:
+ $conv399 = ~~$add398_sink;
+ $UR413 = $job + 464 | 0;
+ $x414 = $UR413 | 0;
+ HEAP32[$x414 >> 2] = $conv399;
+ $94 = +HEAPF64[$y304 >> 3];
+ $95 = +HEAPF64[$y180 >> 3];
+ $mul420 = $94 * $95;
+ $div421 = $mul420 / 72.0;
+ $cmp422 = $div421 < 0.0;
+ if ($cmp422) {
+ label = 50;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $add432 = $div421 + .5;
+ $add432_sink = $add432;
+ label = 51;
+ break;
+ case 50:
+ $sub442 = $div421 + -.5;
+ $add432_sink = $sub442;
+ label = 51;
+ break;
+ case 51:
+ $conv433 = ~~$add432_sink;
+ $y448 = $job + 468 | 0;
+ HEAP32[$y448 >> 2] = $conv433;
+ $96 = HEAP32[$rotation >> 2] | 0;
+ $tobool450 = ($96 | 0) == 0;
+ if ($tobool450) {
+ label = 53;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ _exch_xy($tmpcast86, $LL345);
+ $97 = $pageBoundingBox;
+ $ld$16$0 = $tmp456 | 0;
+ $98$0 = HEAP32[$ld$16$0 >> 2] | 0;
+ $ld$17$1 = $tmp456 + 4 | 0;
+ $98$1 = HEAP32[$ld$17$1 >> 2] | 0;
+ $st$18$0 = $97 | 0;
+ HEAP32[$st$18$0 >> 2] = $98$0;
+ $st$19$1 = $97 + 4 | 0;
+ HEAP32[$st$19$1 >> 2] = $98$1;
+ _exch_xy($tmpcast87, $UR413);
+ $99 = $UR413;
+ $ld$20$0 = $tmp461 | 0;
+ $100$0 = HEAP32[$ld$20$0 >> 2] | 0;
+ $ld$21$1 = $tmp461 + 4 | 0;
+ $100$1 = HEAP32[$ld$21$1 >> 2] | 0;
+ $st$22$0 = $99 | 0;
+ HEAP32[$st$22$0 >> 2] = $100$0;
+ $st$23$1 = $99 + 4 | 0;
+ HEAP32[$st$23$1 >> 2] = $100$1;
+ label = 53;
+ break;
+ case 53:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _parse_layers($gvc, $g, $p) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ $p = $p | 0;
+ var $0 = 0, $call = 0, $layerDelims = 0, $tobool = 0, $_call = 0, $call3 = 0, $layers = 0, $1 = 0, $call6 = 0, $tobool724 = 0, $layerIDs = 0, $layerIDs16 = 0, $sz_027 = 0, $tok_026 = 0, $ntok_025 = 0, $inc = 0, $cmp = 0, $add = 0, $2 = 0, $tobool9 = 0, $3 = 0, $mul = 0, $call11 = 0, $mul12 = 0, $call13 = 0, $call11_sink = 0, $4 = 0, $sz_1 = 0, $5 = 0, $arrayidx = 0, $6 = 0, $call18 = 0, $tobool7 = 0, $tobool19 = 0, $layerIDs21 = 0, $7 = 0, $8 = 0, $add22 = 0, $mul23 = 0, $call24 = 0, $9 = 0, $add28 = 0, $10 = 0, $arrayidx30 = 0, $ntok_0_lcssa29 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g | 0;
+ $call = _agget($0, 108728) | 0;
+ $layerDelims = $gvc + 272 | 0;
+ $tobool = ($call | 0) == 0;
+ $_call = $tobool ? 108104 : $call;
+ HEAP32[$layerDelims >> 2] = $_call;
+ $call3 = _strdup($p | 0) | 0;
+ $layers = $gvc + 276 | 0;
+ HEAP32[$layers >> 2] = $call3;
+ $1 = HEAP32[$layerDelims >> 2] | 0;
+ $call6 = _strtok($call3 | 0, $1 | 0) | 0;
+ $tobool724 = ($call6 | 0) == 0;
+ if ($tobool724) {
+ $ntok_0_lcssa29 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $layerIDs = $gvc + 280 | 0;
+ $layerIDs16 = $gvc + 280 | 0;
+ $ntok_025 = 0;
+ $tok_026 = $call6;
+ $sz_027 = 0;
+ label = 4;
+ break;
+ case 4:
+ $inc = $ntok_025 + 1 | 0;
+ $cmp = ($inc | 0) > ($sz_027 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $sz_1 = $sz_027;
+ label = 9;
+ break;
+ }
+ case 5:
+ $add = $sz_027 + 128 | 0;
+ $2 = HEAP32[$layerIDs >> 2] | 0;
+ $tobool9 = ($2 | 0) == 0;
+ if ($tobool9) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = $2;
+ $mul = $add << 2;
+ $call11 = _grealloc($3, $mul) | 0;
+ $call11_sink = $call11;
+ label = 8;
+ break;
+ case 7:
+ $mul12 = $add << 2;
+ $call13 = _gmalloc($mul12) | 0;
+ $call11_sink = $call13;
+ label = 8;
+ break;
+ case 8:
+ $4 = $call11_sink;
+ HEAP32[$layerIDs >> 2] = $4;
+ $sz_1 = $add;
+ label = 9;
+ break;
+ case 9:
+ $5 = HEAP32[$layerIDs16 >> 2] | 0;
+ $arrayidx = $5 + ($inc << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $tok_026;
+ $6 = HEAP32[$layerDelims >> 2] | 0;
+ $call18 = _strtok(0, $6 | 0) | 0;
+ $tobool7 = ($call18 | 0) == 0;
+ if ($tobool7) {
+ label = 10;
+ break;
+ } else {
+ $ntok_025 = $inc;
+ $tok_026 = $call18;
+ $sz_027 = $sz_1;
+ label = 4;
+ break;
+ }
+ case 10:
+ $tobool19 = ($inc | 0) == 0;
+ if ($tobool19) {
+ $ntok_0_lcssa29 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $layerIDs21 = $gvc + 280 | 0;
+ $7 = HEAP32[$layerIDs21 >> 2] | 0;
+ $8 = $7;
+ $add22 = $inc << 2;
+ $mul23 = $add22 + 8 | 0;
+ $call24 = _grealloc($8, $mul23) | 0;
+ $9 = $call24;
+ HEAP32[$layerIDs21 >> 2] = $9;
+ HEAP32[$9 >> 2] = 0;
+ $add28 = $ntok_025 + 2 | 0;
+ $10 = HEAP32[$layerIDs21 >> 2] | 0;
+ $arrayidx30 = $10 + ($add28 << 2) | 0;
+ HEAP32[$arrayidx30 >> 2] = 0;
+ $ntok_0_lcssa29 = $inc;
+ label = 12;
+ break;
+ case 12:
+ return $ntok_0_lcssa29 | 0;
+ }
+ return 0;
+}
+function _init_bb_node($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $x = 0, $0 = 0.0, $lw = 0, $1 = 0.0, $sub = 0.0, $x3 = 0, $y = 0, $2 = 0.0, $ht = 0, $3 = 0.0, $div = 0.0, $sub7 = 0.0, $y11 = 0, $4 = 0.0, $rw = 0, $5 = 0.0, $add = 0.0, $x18 = 0, $6 = 0.0, $7 = 0.0, $div24 = 0.0, $add25 = 0.0, $y29 = 0, $8 = 0, $9 = 0, $call = 0, $tobool16 = 0, $e_0_in17 = 0, $e_0 = 0, $call30 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $n + 32 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $lw = $n + 104 | 0;
+ $1 = +HEAPF64[$lw >> 3];
+ $sub = $0 - $1;
+ $x3 = $n + 64 | 0;
+ HEAPF64[$x3 >> 3] = $sub;
+ $y = $n + 40 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $ht = $n + 96 | 0;
+ $3 = +HEAPF64[$ht >> 3];
+ $div = $3 * .5;
+ $sub7 = $2 - $div;
+ $y11 = $n + 72 | 0;
+ HEAPF64[$y11 >> 3] = $sub7;
+ $4 = +HEAPF64[$x >> 3];
+ $rw = $n + 112 | 0;
+ $5 = +HEAPF64[$rw >> 3];
+ $add = $4 + $5;
+ $x18 = $n + 80 | 0;
+ HEAPF64[$x18 >> 3] = $add;
+ $6 = +HEAPF64[$y >> 3];
+ $7 = +HEAPF64[$ht >> 3];
+ $div24 = $7 * .5;
+ $add25 = $6 + $div24;
+ $y29 = $n + 88 | 0;
+ HEAPF64[$y29 >> 3] = $add25;
+ $8 = $g;
+ $9 = $n;
+ $call = _agfstout($8, $9) | 0;
+ $tobool16 = ($call | 0) == 0;
+ if ($tobool16) {
+ label = 4;
+ break;
+ } else {
+ $e_0_in17 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $e_0 = $e_0_in17;
+ _init_bb_edge($e_0);
+ $call30 = _agnxtout($8, $e_0_in17) | 0;
+ $tobool = ($call30 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $e_0_in17 = $call30;
+ label = 3;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _init_bb_edge($e) {
+ $e = $e | 0;
+ var $spl1 = 0, $0 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $spl1 = $e + 24 | 0;
+ $0 = HEAP32[$spl1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _init_splines_bb($0);
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _init_splines_bb($spl) {
+ $spl = $spl | 0;
+ var $bz = 0, $tmp = 0, $tmp6 = 0, $tmp66 = 0, $tmp134 = 0, $size = 0, $0 = 0, $cmp = 0, $list = 0, $1 = 0, $2 = 0, $3 = 0, $bb_sroa_0_0__idx40 = 0, $bb_sroa_0_0_copyload41 = 0.0, $bb_sroa_1_8__idx48 = 0, $bb_sroa_1_8_copyload49 = 0.0, $bb_sroa_2_16__idx56 = 0, $bb_sroa_2_16_copyload57 = 0.0, $bb_sroa_3_24__idx64 = 0, $bb_sroa_3_24_copyload65 = 0.0, $4 = 0, $cmp278 = 0, $b_sroa_0_0__idx3 = 0, $b_sroa_1_8__idx13 = 0, $b_sroa_2_16__idx23 = 0, $b_sroa_3_24__idx33 = 0, $sflag = 0, $eflag = 0, $ep = 0, $size130 = 0, $list131 = 0, $b_sroa_0_0__idx = 0, $b_sroa_1_8__idx10 = 0, $b_sroa_2_16__idx20 = 0, $b_sroa_3_24__idx30 = 0, $sp = 0, $list63 = 0, $b_sroa_0_0__idx1 = 0, $b_sroa_1_8__idx11 = 0, $b_sroa_2_16__idx21 = 0, $b_sroa_3_24__idx31 = 0, $bb_sroa_0_083 = 0.0, $bb_sroa_1_082 = 0.0, $bb_sroa_2_081 = 0.0, $bb_sroa_3_080 = 0.0, $i_079 = 0, $cmp3 = 0, $5 = 0, $arrayidx5 = 0, $6 = 0, $b_sroa_0_0_copyload4 = 0.0, $b_sroa_1_8_copyload14 = 0.0, $b_sroa_2_16_copyload24 = 0.0, $b_sroa_3_24_copyload34 = 0.0, $cmp9 = 0, $bb_sroa_0_0_b_sroa_0_0_copyload4 = 0.0, $cmp22 = 0, $cond30 = 0.0, $cmp36 = 0, $bb_sroa_2_0_b_sroa_2_16_copyload24 = 0.0, $cmp51 = 0, $cond59 = 0.0, $bb_sroa_3_1 = 0.0, $bb_sroa_2_1 = 0.0, $bb_sroa_1_1 = 0.0, $bb_sroa_0_1 = 0.0, $7 = 0, $tobool = 0, $8 = 0, $b_sroa_0_0_copyload2 = 0.0, $b_sroa_1_8_copyload12 = 0.0, $b_sroa_2_16_copyload22 = 0.0, $b_sroa_3_24_copyload32 = 0.0, $cmp71 = 0, $bb_sroa_0_1_b_sroa_0_0_copyload2 = 0.0, $cmp86 = 0, $cond94 = 0.0, $cmp101 = 0, $bb_sroa_2_1_b_sroa_2_16_copyload22 = 0.0, $cmp116 = 0, $cond124 = 0.0, $bb_sroa_3_2 = 0.0, $bb_sroa_2_2 = 0.0, $bb_sroa_1_2 = 0.0, $bb_sroa_0_2 = 0.0, $9 = 0, $tobool128 = 0, $10 = 0, $sub = 0, $11 = 0, $arrayidx132 = 0, $b_sroa_0_0_copyload = 0.0, $b_sroa_1_8_copyload = 0.0, $b_sroa_2_16_copyload = 0.0, $b_sroa_3_24_copyload = 0.0, $cmp139 = 0, $bb_sroa_0_2_b_sroa_0_0_copyload = 0.0, $cmp154 = 0, $cond162 = 0.0, $cmp169 = 0, $bb_sroa_2_2_b_sroa_2_16_copyload = 0.0, $cmp184 = 0, $cond192 = 0.0, $bb_sroa_3_3 = 0.0, $bb_sroa_2_3 = 0.0, $bb_sroa_1_3 = 0.0, $bb_sroa_0_3 = 0.0, $inc = 0, $12 = 0, $cmp2 = 0, $bb_sroa_0_0_lcssa = 0.0, $bb_sroa_1_0_lcssa = 0.0, $bb_sroa_2_0_lcssa = 0.0, $bb_sroa_3_0_lcssa = 0.0, $bb_sroa_0_0__idx = 0, $bb_sroa_1_8__idx47 = 0, $bb_sroa_2_16__idx55 = 0, $bb_sroa_3_24__idx63 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 176 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $bz = __stackBase__ | 0;
+ $tmp = __stackBase__ + 48 | 0;
+ $tmp6 = __stackBase__ + 80 | 0;
+ $tmp66 = __stackBase__ + 112 | 0;
+ $tmp134 = __stackBase__ + 144 | 0;
+ $size = $spl + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp = ($0 | 0) > 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ ___assert_func(162152, 3408, 164200, 103680);
+ case 4:
+ $list = $spl | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = $bz;
+ $3 = $1;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ HEAP32[$2 + 16 >> 2] = HEAP32[$3 + 16 >> 2] | 0;
+ HEAP32[$2 + 20 >> 2] = HEAP32[$3 + 20 >> 2] | 0;
+ HEAP32[$2 + 24 >> 2] = HEAP32[$3 + 24 >> 2] | 0;
+ HEAP32[$2 + 28 >> 2] = HEAP32[$3 + 28 >> 2] | 0;
+ HEAP32[$2 + 32 >> 2] = HEAP32[$3 + 32 >> 2] | 0;
+ HEAP32[$2 + 36 >> 2] = HEAP32[$3 + 36 >> 2] | 0;
+ HEAP32[$2 + 40 >> 2] = HEAP32[$3 + 40 >> 2] | 0;
+ HEAP32[$2 + 44 >> 2] = HEAP32[$3 + 44 >> 2] | 0;
+ _bezier_bb($tmp, $bz);
+ $bb_sroa_0_0__idx40 = $tmp | 0;
+ $bb_sroa_0_0_copyload41 = +HEAPF64[$bb_sroa_0_0__idx40 >> 3];
+ $bb_sroa_1_8__idx48 = $tmp + 8 | 0;
+ $bb_sroa_1_8_copyload49 = +HEAPF64[$bb_sroa_1_8__idx48 >> 3];
+ $bb_sroa_2_16__idx56 = $tmp + 16 | 0;
+ $bb_sroa_2_16_copyload57 = +HEAPF64[$bb_sroa_2_16__idx56 >> 3];
+ $bb_sroa_3_24__idx64 = $tmp + 24 | 0;
+ $bb_sroa_3_24_copyload65 = +HEAPF64[$bb_sroa_3_24__idx64 >> 3];
+ $4 = HEAP32[$size >> 2] | 0;
+ $cmp278 = ($4 | 0) > 0;
+ if ($cmp278) {
+ label = 5;
+ break;
+ } else {
+ $bb_sroa_3_0_lcssa = $bb_sroa_3_24_copyload65;
+ $bb_sroa_2_0_lcssa = $bb_sroa_2_16_copyload57;
+ $bb_sroa_1_0_lcssa = $bb_sroa_1_8_copyload49;
+ $bb_sroa_0_0_lcssa = $bb_sroa_0_0_copyload41;
+ label = 13;
+ break;
+ }
+ case 5:
+ $b_sroa_0_0__idx3 = $tmp6 | 0;
+ $b_sroa_1_8__idx13 = $tmp6 + 8 | 0;
+ $b_sroa_2_16__idx23 = $tmp6 + 16 | 0;
+ $b_sroa_3_24__idx33 = $tmp6 + 24 | 0;
+ $sflag = $bz + 8 | 0;
+ $eflag = $bz + 12 | 0;
+ $ep = $bz + 32 | 0;
+ $size130 = $bz + 4 | 0;
+ $list131 = $bz | 0;
+ $b_sroa_0_0__idx = $tmp134 | 0;
+ $b_sroa_1_8__idx10 = $tmp134 + 8 | 0;
+ $b_sroa_2_16__idx20 = $tmp134 + 16 | 0;
+ $b_sroa_3_24__idx30 = $tmp134 + 24 | 0;
+ $sp = $bz + 16 | 0;
+ $list63 = $bz | 0;
+ $b_sroa_0_0__idx1 = $tmp66 | 0;
+ $b_sroa_1_8__idx11 = $tmp66 + 8 | 0;
+ $b_sroa_2_16__idx21 = $tmp66 + 16 | 0;
+ $b_sroa_3_24__idx31 = $tmp66 + 24 | 0;
+ $i_079 = 0;
+ $bb_sroa_3_080 = $bb_sroa_3_24_copyload65;
+ $bb_sroa_2_081 = $bb_sroa_2_16_copyload57;
+ $bb_sroa_1_082 = $bb_sroa_1_8_copyload49;
+ $bb_sroa_0_083 = $bb_sroa_0_0_copyload41;
+ label = 6;
+ break;
+ case 6:
+ $cmp3 = ($i_079 | 0) > 0;
+ if ($cmp3) {
+ label = 7;
+ break;
+ } else {
+ $bb_sroa_0_1 = $bb_sroa_0_083;
+ $bb_sroa_1_1 = $bb_sroa_1_082;
+ $bb_sroa_2_1 = $bb_sroa_2_081;
+ $bb_sroa_3_1 = $bb_sroa_3_080;
+ label = 8;
+ break;
+ }
+ case 7:
+ $5 = HEAP32[$list >> 2] | 0;
+ $arrayidx5 = $5 + ($i_079 * 48 & -1) | 0;
+ $6 = $arrayidx5;
+ HEAP32[$2 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ HEAP32[$2 + 16 >> 2] = HEAP32[$6 + 16 >> 2] | 0;
+ HEAP32[$2 + 20 >> 2] = HEAP32[$6 + 20 >> 2] | 0;
+ HEAP32[$2 + 24 >> 2] = HEAP32[$6 + 24 >> 2] | 0;
+ HEAP32[$2 + 28 >> 2] = HEAP32[$6 + 28 >> 2] | 0;
+ HEAP32[$2 + 32 >> 2] = HEAP32[$6 + 32 >> 2] | 0;
+ HEAP32[$2 + 36 >> 2] = HEAP32[$6 + 36 >> 2] | 0;
+ HEAP32[$2 + 40 >> 2] = HEAP32[$6 + 40 >> 2] | 0;
+ HEAP32[$2 + 44 >> 2] = HEAP32[$6 + 44 >> 2] | 0;
+ _bezier_bb($tmp6, $bz);
+ $b_sroa_0_0_copyload4 = +HEAPF64[$b_sroa_0_0__idx3 >> 3];
+ $b_sroa_1_8_copyload14 = +HEAPF64[$b_sroa_1_8__idx13 >> 3];
+ $b_sroa_2_16_copyload24 = +HEAPF64[$b_sroa_2_16__idx23 >> 3];
+ $b_sroa_3_24_copyload34 = +HEAPF64[$b_sroa_3_24__idx33 >> 3];
+ $cmp9 = $bb_sroa_0_083 < $b_sroa_0_0_copyload4;
+ $bb_sroa_0_0_b_sroa_0_0_copyload4 = $cmp9 ? $bb_sroa_0_083 : $b_sroa_0_0_copyload4;
+ $cmp22 = $bb_sroa_1_082 < $b_sroa_1_8_copyload14;
+ $cond30 = $cmp22 ? $bb_sroa_1_082 : $b_sroa_1_8_copyload14;
+ $cmp36 = $bb_sroa_2_081 > $b_sroa_2_16_copyload24;
+ $bb_sroa_2_0_b_sroa_2_16_copyload24 = $cmp36 ? $bb_sroa_2_081 : $b_sroa_2_16_copyload24;
+ $cmp51 = $bb_sroa_3_080 > $b_sroa_3_24_copyload34;
+ $cond59 = $cmp51 ? $bb_sroa_3_080 : $b_sroa_3_24_copyload34;
+ $bb_sroa_0_1 = $bb_sroa_0_0_b_sroa_0_0_copyload4;
+ $bb_sroa_1_1 = $cond30;
+ $bb_sroa_2_1 = $bb_sroa_2_0_b_sroa_2_16_copyload24;
+ $bb_sroa_3_1 = $cond59;
+ label = 8;
+ break;
+ case 8:
+ $7 = HEAP32[$sflag >> 2] | 0;
+ $tobool = ($7 | 0) == 0;
+ if ($tobool) {
+ $bb_sroa_0_2 = $bb_sroa_0_1;
+ $bb_sroa_1_2 = $bb_sroa_1_1;
+ $bb_sroa_2_2 = $bb_sroa_2_1;
+ $bb_sroa_3_2 = $bb_sroa_3_1;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $8 = HEAP32[$list63 >> 2] | 0;
+ _arrow_bb($tmp66, $sp, $8, 1.0, 0);
+ $b_sroa_0_0_copyload2 = +HEAPF64[$b_sroa_0_0__idx1 >> 3];
+ $b_sroa_1_8_copyload12 = +HEAPF64[$b_sroa_1_8__idx11 >> 3];
+ $b_sroa_2_16_copyload22 = +HEAPF64[$b_sroa_2_16__idx21 >> 3];
+ $b_sroa_3_24_copyload32 = +HEAPF64[$b_sroa_3_24__idx31 >> 3];
+ $cmp71 = $bb_sroa_0_1 < $b_sroa_0_0_copyload2;
+ $bb_sroa_0_1_b_sroa_0_0_copyload2 = $cmp71 ? $bb_sroa_0_1 : $b_sroa_0_0_copyload2;
+ $cmp86 = $bb_sroa_1_1 < $b_sroa_1_8_copyload12;
+ $cond94 = $cmp86 ? $bb_sroa_1_1 : $b_sroa_1_8_copyload12;
+ $cmp101 = $bb_sroa_2_1 > $b_sroa_2_16_copyload22;
+ $bb_sroa_2_1_b_sroa_2_16_copyload22 = $cmp101 ? $bb_sroa_2_1 : $b_sroa_2_16_copyload22;
+ $cmp116 = $bb_sroa_3_1 > $b_sroa_3_24_copyload32;
+ $cond124 = $cmp116 ? $bb_sroa_3_1 : $b_sroa_3_24_copyload32;
+ $bb_sroa_0_2 = $bb_sroa_0_1_b_sroa_0_0_copyload2;
+ $bb_sroa_1_2 = $cond94;
+ $bb_sroa_2_2 = $bb_sroa_2_1_b_sroa_2_16_copyload22;
+ $bb_sroa_3_2 = $cond124;
+ label = 10;
+ break;
+ case 10:
+ $9 = HEAP32[$eflag >> 2] | 0;
+ $tobool128 = ($9 | 0) == 0;
+ if ($tobool128) {
+ $bb_sroa_0_3 = $bb_sroa_0_2;
+ $bb_sroa_1_3 = $bb_sroa_1_2;
+ $bb_sroa_2_3 = $bb_sroa_2_2;
+ $bb_sroa_3_3 = $bb_sroa_3_2;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $10 = HEAP32[$size130 >> 2] | 0;
+ $sub = $10 - 1 | 0;
+ $11 = HEAP32[$list131 >> 2] | 0;
+ $arrayidx132 = $11 + ($sub << 4) | 0;
+ _arrow_bb($tmp134, $ep, $arrayidx132, 1.0, 0);
+ $b_sroa_0_0_copyload = +HEAPF64[$b_sroa_0_0__idx >> 3];
+ $b_sroa_1_8_copyload = +HEAPF64[$b_sroa_1_8__idx10 >> 3];
+ $b_sroa_2_16_copyload = +HEAPF64[$b_sroa_2_16__idx20 >> 3];
+ $b_sroa_3_24_copyload = +HEAPF64[$b_sroa_3_24__idx30 >> 3];
+ $cmp139 = $bb_sroa_0_2 < $b_sroa_0_0_copyload;
+ $bb_sroa_0_2_b_sroa_0_0_copyload = $cmp139 ? $bb_sroa_0_2 : $b_sroa_0_0_copyload;
+ $cmp154 = $bb_sroa_1_2 < $b_sroa_1_8_copyload;
+ $cond162 = $cmp154 ? $bb_sroa_1_2 : $b_sroa_1_8_copyload;
+ $cmp169 = $bb_sroa_2_2 > $b_sroa_2_16_copyload;
+ $bb_sroa_2_2_b_sroa_2_16_copyload = $cmp169 ? $bb_sroa_2_2 : $b_sroa_2_16_copyload;
+ $cmp184 = $bb_sroa_3_2 > $b_sroa_3_24_copyload;
+ $cond192 = $cmp184 ? $bb_sroa_3_2 : $b_sroa_3_24_copyload;
+ $bb_sroa_0_3 = $bb_sroa_0_2_b_sroa_0_0_copyload;
+ $bb_sroa_1_3 = $cond162;
+ $bb_sroa_2_3 = $bb_sroa_2_2_b_sroa_2_16_copyload;
+ $bb_sroa_3_3 = $cond192;
+ label = 12;
+ break;
+ case 12:
+ $inc = $i_079 + 1 | 0;
+ $12 = HEAP32[$size >> 2] | 0;
+ $cmp2 = ($inc | 0) < ($12 | 0);
+ if ($cmp2) {
+ $i_079 = $inc;
+ $bb_sroa_3_080 = $bb_sroa_3_3;
+ $bb_sroa_2_081 = $bb_sroa_2_3;
+ $bb_sroa_1_082 = $bb_sroa_1_3;
+ $bb_sroa_0_083 = $bb_sroa_0_3;
+ label = 6;
+ break;
+ } else {
+ $bb_sroa_3_0_lcssa = $bb_sroa_3_3;
+ $bb_sroa_2_0_lcssa = $bb_sroa_2_3;
+ $bb_sroa_1_0_lcssa = $bb_sroa_1_3;
+ $bb_sroa_0_0_lcssa = $bb_sroa_0_3;
+ label = 13;
+ break;
+ }
+ case 13:
+ $bb_sroa_0_0__idx = $spl + 8 | 0;
+ HEAPF64[$bb_sroa_0_0__idx >> 3] = $bb_sroa_0_0_lcssa;
+ $bb_sroa_1_8__idx47 = $spl + 16 | 0;
+ HEAPF64[$bb_sroa_1_8__idx47 >> 3] = $bb_sroa_1_0_lcssa;
+ $bb_sroa_2_16__idx55 = $spl + 24 | 0;
+ HEAPF64[$bb_sroa_2_16__idx55 >> 3] = $bb_sroa_2_0_lcssa;
+ $bb_sroa_3_24__idx63 = $spl + 32 | 0;
+ HEAPF64[$bb_sroa_3_24__idx63 >> 3] = $bb_sroa_3_0_lcssa;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _is_style_delim($c) {
+ $c = $c | 0;
+ var $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($c | 0) == 40 | ($c | 0) == 41 | ($c | 0) == 44 | ($c | 0) == 0) {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _edge_in_box($e, $b) {
+ $e = $e | 0;
+ $b = $b | 0;
+ var $spl1 = 0, $0 = 0, $tobool = 0, $bb = 0, $call = 0, $tobool2 = 0, $label = 0, $1 = 0, $tobool4 = 0, $call6 = 0, $tobool7 = 0, $xlabel = 0, $2 = 0, $tobool11 = 0, $call13 = 0, $tobool15 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $spl1 = $e + 24 | 0;
+ $0 = HEAP32[$spl1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $bb = $0 + 8 | 0;
+ $call = _boxf_overlap($bb, $b) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ }
+ case 4:
+ $label = $e + 112 | 0;
+ $1 = HEAP32[$label >> 2] | 0;
+ $tobool4 = ($1 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call6 = _overlap_label($1, $b) | 0;
+ $tobool7 = $call6 << 24 >> 24 == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ }
+ case 6:
+ $xlabel = $e + 124 | 0;
+ $2 = HEAP32[$xlabel >> 2] | 0;
+ $tobool11 = ($2 | 0) == 0;
+ if ($tobool11) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call13 = _overlap_label($2, $b) | 0;
+ $tobool15 = $call13 << 24 >> 24 == 0;
+ if ($tobool15) {
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ }
+ case 8:
+ $retval_0 = 0;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _edge_in_layer($job, $e) {
+ $job = $job | 0;
+ $e = $e | 0;
+ var $numLayers = 0, $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $call = 0, $call1 = 0, $tobool = 0, $3 = 0, $tobool4 = 0, $tail = 0, $head = 0, $cnt_0 = 0, $cmp7 = 0, $cmp8 = 0, $cond_in = 0, $cond = 0, $4 = 0, $5 = 0, $call9 = 0, $6 = 0, $cmp11 = 0, $call13 = 0, $tobool15 = 0, $inc = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $numLayers = $job + 156 | 0;
+ $0 = HEAP32[$numLayers >> 2] | 0;
+ $cmp = ($0 | 0) < 2;
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $e | 0;
+ $2 = HEAP32[41920] | 0;
+ $call = _late_string($1, $2, 136112) | 0;
+ $call1 = _selectedlayer($job, $call) | 0;
+ $tobool = $call1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ }
+ case 4:
+ $3 = HEAP8[$call] | 0;
+ $tobool4 = $3 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ }
+ case 5:
+ $tail = $e + 16 | 0;
+ $head = $e + 12 | 0;
+ $cnt_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ $cmp7 = ($cnt_0 | 0) < 2;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ }
+ case 7:
+ $cmp8 = ($cnt_0 | 0) < 1;
+ $cond_in = $cmp8 ? $tail : $head;
+ $cond = HEAP32[$cond_in >> 2] | 0;
+ $4 = $cond | 0;
+ $5 = HEAP32[41586] | 0;
+ $call9 = _late_string($4, $5, 136112) | 0;
+ $6 = HEAP8[$call9] | 0;
+ $cmp11 = $6 << 24 >> 24 == 0;
+ if ($cmp11) {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call13 = _selectedlayer($job, $call9) | 0;
+ $tobool15 = $call13 << 24 >> 24 == 0;
+ $inc = $cnt_0 + 1 | 0;
+ if ($tobool15) {
+ $cnt_0 = $inc;
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ }
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _bezier_bb($agg_result, $bz) {
+ $agg_result = $agg_result | 0;
+ $bz = $bz | 0;
+ var $size = 0, $0 = 0, $cmp = 0, $rem = 0, $cmp2 = 0, $list = 0, $1 = 0, $bb_sroa_1_sroa_0_0_bb_sroa_1_16__cast35_idx = 0, $bb_sroa_1_sroa_0_0_copyload = 0.0, $bb_sroa_1_sroa_1_8_bb_sroa_1_16__cast35_idx42 = 0, $bb_sroa_1_sroa_1_8_copyload = 0.0, $2 = 0, $cmp780 = 0, $3 = 0, $4 = 0, $bb_sroa_1_sroa_0_085 = 0.0, $bb_sroa_1_sroa_1_084 = 0.0, $bb_sroa_0_sroa_0_083 = 0.0, $bb_sroa_0_sroa_1_082 = 0.0, $i_081 = 0, $p1_sroa_0_0__idx = 0, $p1_sroa_0_0_copyload = 0.0, $p1_sroa_1_8__idx58 = 0, $p1_sroa_1_8_copyload = 0.0, $inc = 0, $p2_sroa_0_0__idx = 0, $p2_sroa_0_0_copyload = 0.0, $p2_sroa_1_8__idx57 = 0, $p2_sroa_1_8_copyload = 0.0, $inc12 = 0, $add = 0.0, $div = 0.0, $add16 = 0.0, $div17 = 0.0, $cmp22 = 0, $bb_sroa_0_sroa_0_0_div = 0.0, $cmp34 = 0, $cond41 = 0.0, $cmp47 = 0, $bb_sroa_1_sroa_0_0_div = 0.0, $cmp60 = 0, $cond67 = 0.0, $p_sroa_0_0__idx = 0, $p_sroa_0_0_copyload = 0.0, $p_sroa_1_8__idx69 = 0, $p_sroa_1_8_copyload = 0.0, $cmp75 = 0, $bb_sroa_0_sroa_0_0_div_p_sroa_0_0_copyload = 0.0, $cmp88 = 0, $cond95 = 0.0, $cmp101 = 0, $bb_sroa_1_sroa_0_0_div_p_sroa_0_0_copyload = 0.0, $cmp114 = 0, $cond121 = 0.0, $inc124 = 0, $cmp7 = 0, $bb_sroa_1_sroa_0_0_lcssa = 0.0, $bb_sroa_1_sroa_1_0_lcssa = 0.0, $bb_sroa_0_sroa_0_0_lcssa = 0.0, $bb_sroa_0_sroa_1_0_lcssa = 0.0, $bb_sroa_0_sroa_0_0_bb_sroa_0_0__cast_idx = 0, $bb_sroa_0_sroa_1_8_bb_sroa_0_0__cast_idx56 = 0, $bb_sroa_1_sroa_0_0_bb_sroa_1_16__cast_idx = 0, $bb_sroa_1_sroa_1_8_bb_sroa_1_16__cast_idx48 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $bz;
+ $bz = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ _memcpy($bz, tempParam, 48);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $bz + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp = ($0 | 0) > 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ ___assert_func(162152, 3382, 164608, 103312);
+ case 4:
+ $rem = ($0 | 0) % 3;
+ $cmp2 = ($rem | 0) == 1;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ ___assert_func(162152, 3383, 164608, 102936);
+ case 6:
+ $list = $bz | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $bb_sroa_1_sroa_0_0_bb_sroa_1_16__cast35_idx = $1 | 0;
+ $bb_sroa_1_sroa_0_0_copyload = +HEAPF64[$bb_sroa_1_sroa_0_0_bb_sroa_1_16__cast35_idx >> 3];
+ $bb_sroa_1_sroa_1_8_bb_sroa_1_16__cast35_idx42 = $1 + 8 | 0;
+ $bb_sroa_1_sroa_1_8_copyload = +HEAPF64[$bb_sroa_1_sroa_1_8_bb_sroa_1_16__cast35_idx42 >> 3];
+ $2 = HEAP32[$size >> 2] | 0;
+ $cmp780 = ($2 | 0) > 1;
+ if ($cmp780) {
+ label = 7;
+ break;
+ } else {
+ $bb_sroa_0_sroa_1_0_lcssa = $bb_sroa_1_sroa_1_8_copyload;
+ $bb_sroa_0_sroa_0_0_lcssa = $bb_sroa_1_sroa_0_0_copyload;
+ $bb_sroa_1_sroa_1_0_lcssa = $bb_sroa_1_sroa_1_8_copyload;
+ $bb_sroa_1_sroa_0_0_lcssa = $bb_sroa_1_sroa_0_0_copyload;
+ label = 9;
+ break;
+ }
+ case 7:
+ $3 = HEAP32[$list >> 2] | 0;
+ $4 = HEAP32[$size >> 2] | 0;
+ $i_081 = 1;
+ $bb_sroa_0_sroa_1_082 = $bb_sroa_1_sroa_1_8_copyload;
+ $bb_sroa_0_sroa_0_083 = $bb_sroa_1_sroa_0_0_copyload;
+ $bb_sroa_1_sroa_1_084 = $bb_sroa_1_sroa_1_8_copyload;
+ $bb_sroa_1_sroa_0_085 = $bb_sroa_1_sroa_0_0_copyload;
+ label = 8;
+ break;
+ case 8:
+ $p1_sroa_0_0__idx = $3 + ($i_081 << 4) | 0;
+ $p1_sroa_0_0_copyload = +HEAPF64[$p1_sroa_0_0__idx >> 3];
+ $p1_sroa_1_8__idx58 = $3 + ($i_081 << 4) + 8 | 0;
+ $p1_sroa_1_8_copyload = +HEAPF64[$p1_sroa_1_8__idx58 >> 3];
+ $inc = $i_081 + 1 | 0;
+ $p2_sroa_0_0__idx = $3 + ($inc << 4) | 0;
+ $p2_sroa_0_0_copyload = +HEAPF64[$p2_sroa_0_0__idx >> 3];
+ $p2_sroa_1_8__idx57 = $3 + ($inc << 4) + 8 | 0;
+ $p2_sroa_1_8_copyload = +HEAPF64[$p2_sroa_1_8__idx57 >> 3];
+ $inc12 = $i_081 + 2 | 0;
+ $add = $p1_sroa_0_0_copyload + $p2_sroa_0_0_copyload;
+ $div = $add * .5;
+ $add16 = $p1_sroa_1_8_copyload + $p2_sroa_1_8_copyload;
+ $div17 = $add16 * .5;
+ $cmp22 = $bb_sroa_0_sroa_0_083 < $div;
+ $bb_sroa_0_sroa_0_0_div = $cmp22 ? $bb_sroa_0_sroa_0_083 : $div;
+ $cmp34 = $bb_sroa_0_sroa_1_082 < $div17;
+ $cond41 = $cmp34 ? $bb_sroa_0_sroa_1_082 : $div17;
+ $cmp47 = $bb_sroa_1_sroa_0_085 > $div;
+ $bb_sroa_1_sroa_0_0_div = $cmp47 ? $bb_sroa_1_sroa_0_085 : $div;
+ $cmp60 = $bb_sroa_1_sroa_1_084 > $div17;
+ $cond67 = $cmp60 ? $bb_sroa_1_sroa_1_084 : $div17;
+ $p_sroa_0_0__idx = $3 + ($inc12 << 4) | 0;
+ $p_sroa_0_0_copyload = +HEAPF64[$p_sroa_0_0__idx >> 3];
+ $p_sroa_1_8__idx69 = $3 + ($inc12 << 4) + 8 | 0;
+ $p_sroa_1_8_copyload = +HEAPF64[$p_sroa_1_8__idx69 >> 3];
+ $cmp75 = $bb_sroa_0_sroa_0_0_div < $p_sroa_0_0_copyload;
+ $bb_sroa_0_sroa_0_0_div_p_sroa_0_0_copyload = $cmp75 ? $bb_sroa_0_sroa_0_0_div : $p_sroa_0_0_copyload;
+ $cmp88 = $cond41 < $p_sroa_1_8_copyload;
+ $cond95 = $cmp88 ? $cond41 : $p_sroa_1_8_copyload;
+ $cmp101 = $bb_sroa_1_sroa_0_0_div > $p_sroa_0_0_copyload;
+ $bb_sroa_1_sroa_0_0_div_p_sroa_0_0_copyload = $cmp101 ? $bb_sroa_1_sroa_0_0_div : $p_sroa_0_0_copyload;
+ $cmp114 = $cond67 > $p_sroa_1_8_copyload;
+ $cond121 = $cmp114 ? $cond67 : $p_sroa_1_8_copyload;
+ $inc124 = $i_081 + 3 | 0;
+ $cmp7 = ($inc124 | 0) < ($4 | 0);
+ if ($cmp7) {
+ $i_081 = $inc124;
+ $bb_sroa_0_sroa_1_082 = $cond95;
+ $bb_sroa_0_sroa_0_083 = $bb_sroa_0_sroa_0_0_div_p_sroa_0_0_copyload;
+ $bb_sroa_1_sroa_1_084 = $cond121;
+ $bb_sroa_1_sroa_0_085 = $bb_sroa_1_sroa_0_0_div_p_sroa_0_0_copyload;
+ label = 8;
+ break;
+ } else {
+ $bb_sroa_0_sroa_1_0_lcssa = $cond95;
+ $bb_sroa_0_sroa_0_0_lcssa = $bb_sroa_0_sroa_0_0_div_p_sroa_0_0_copyload;
+ $bb_sroa_1_sroa_1_0_lcssa = $cond121;
+ $bb_sroa_1_sroa_0_0_lcssa = $bb_sroa_1_sroa_0_0_div_p_sroa_0_0_copyload;
+ label = 9;
+ break;
+ }
+ case 9:
+ $bb_sroa_0_sroa_0_0_bb_sroa_0_0__cast_idx = $agg_result | 0;
+ HEAPF64[$bb_sroa_0_sroa_0_0_bb_sroa_0_0__cast_idx >> 3] = $bb_sroa_0_sroa_0_0_lcssa;
+ $bb_sroa_0_sroa_1_8_bb_sroa_0_0__cast_idx56 = $agg_result + 8 | 0;
+ HEAPF64[$bb_sroa_0_sroa_1_8_bb_sroa_0_0__cast_idx56 >> 3] = $bb_sroa_0_sroa_1_0_lcssa;
+ $bb_sroa_1_sroa_0_0_bb_sroa_1_16__cast_idx = $agg_result + 16 | 0;
+ HEAPF64[$bb_sroa_1_sroa_0_0_bb_sroa_1_16__cast_idx >> 3] = $bb_sroa_1_sroa_0_0_lcssa;
+ $bb_sroa_1_sroa_1_8_bb_sroa_1_16__cast_idx48 = $agg_result + 24 | 0;
+ HEAPF64[$bb_sroa_1_sroa_1_8_bb_sroa_1_16__cast_idx48 >> 3] = $bb_sroa_1_sroa_1_0_lcssa;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_begin_edge($job, $e, $styles) {
+ $job = $job | 0;
+ $e = $e | 0;
+ $styles = $styles | 0;
+ var $pbs = 0, $pbs_n = 0, $pbs_poly_n = 0, $xb = 0, $xbuf = 0, $flags1 = 0, $0 = 0, $call = 0, $type = 0, $1 = 0, $e_c = 0, $emit_state = 0, $tobool = 0, $spl = 0, $2 = 0, $tobool4 = 0, $3 = 0, $tobool5 = 0, $4 = 0, $index = 0, $5 = 0, $call7 = 0, $tobool8 = 0, $6 = 0, $tobool10 = 0, $call12 = 0.0, $and = 0, $tobool14 = 0, $tail = 0, $7 = 0, $graph = 0, $8 = 0, $odim = 0, $9 = 0, $cmp = 0, $pos = 0, $10 = 0, $arrayidx22 = 0, $11 = 0.0, $mul = 0.0, $cmp23 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv30 = 0, $conv37 = 0.0, $tail_z = 0, $head = 0, $12 = 0, $pos39 = 0, $13 = 0, $arrayidx40 = 0, $14 = 0.0, $mul41 = 0.0, $cmp42 = 0, $add50 = 0.0, $sub58 = 0.0, $add50_sink = 0.0, $conv51 = 0, $conv62 = 0.0, $head_z = 0, $tail_z64 = 0, $15 = 0, $and67 = 0, $tobool68 = 0, $label = 0, $16 = 0, $tobool71 = 0, $text = 0, $17 = 0, $label73 = 0, $label75 = 0, $18 = 0, $xlabel = 0, $headlabel = 0, $taillabel = 0, $xlabel77 = 0, $19 = 0, $tobool78 = 0, $text80 = 0, $20 = 0, $tail_label = 0, $21 = 0, $tobool84 = 0, $text86 = 0, $22 = 0, $head_label = 0, $23 = 0, $tobool90 = 0, $text92 = 0, $24 = 0, $and96 = 0, $tobool97 = 0, $arraydecay = 0, $25 = 0, $call99 = 0, $call100 = 0, $id = 0, $call101 = 0, $tobool102 = 0, $26 = 0, $tobool106 = 0, $call107 = 0, $tobool108 = 0, $27 = 0, $tobool112 = 0, $s_0 = 0, $call114 = 0, $dflt_url_0 = 0, $call116 = 0, $tobool117 = 0, $28 = 0, $tobool121 = 0, $call123 = 0, $tobool124 = 0, $29 = 0, $tobool128 = 0, $s_1 = 0, $call130 = 0, $url = 0, $tobool132 = 0, $call134 = 0, $url135 = 0, $call138 = 0, $tobool139 = 0, $30 = 0, $tobool143 = 0, $call145 = 0, $tobool146 = 0, $31 = 0, $tobool150 = 0, $s_2 = 0, $call152 = 0, $labelurl = 0, $tobool154 = 0, $call156 = 0, $labelurl157 = 0, $call160 = 0, $tobool161 = 0, $32 = 0, $tobool165 = 0, $call167 = 0, $tobool168 = 0, $33 = 0, $tobool172 = 0, $s_3 = 0, $call174 = 0, $tailurl = 0, $34 = 0, $35 = 0, $36 = 0, $37 = 0, $tobool176 = 0, $call178 = 0, $tailurl179 = 0, $call182 = 0, $tobool183 = 0, $38 = 0, $tobool187 = 0, $call189 = 0, $tobool190 = 0, $39 = 0, $tobool194 = 0, $s_4 = 0, $call196 = 0, $headurl = 0, $40 = 0, $41 = 0, $42 = 0, $43 = 0, $tobool199 = 0, $call201 = 0, $headurl202 = 0, $dflt_url_1 = 0, $and206 = 0, $tobool207 = 0, $44 = 0, $call209 = 0, $tobool210 = 0, $45 = 0, $tobool214 = 0, $call216 = 0, $dflt_target_0 = 0, $call218 = 0, $tobool219 = 0, $46 = 0, $tobool223 = 0, $47 = 0, $48 = 0, $49 = 0, $50 = 0, $call226 = 0, $target = 0, $tobool228 = 0, $call230 = 0, $target231 = 0, $call234 = 0, $tobool235 = 0, $51 = 0, $tobool239 = 0, $call241 = 0, $labeltarget = 0, $tobool243 = 0, $call245 = 0, $labeltarget246 = 0, $call249 = 0, $tobool250 = 0, $52 = 0, $tobool254 = 0, $call256 = 0, $tailtarget = 0, $53 = 0, $54 = 0, $55 = 0, $56 = 0, $tobool259 = 0, $call261 = 0, $tailtarget262 = 0, $call265 = 0, $tobool266 = 0, $57 = 0, $tobool270 = 0, $58 = 0, $59 = 0, $60 = 0, $61 = 0, $call273 = 0, $headtarget = 0, $tobool275 = 0, $call277 = 0, $headtarget278 = 0, $dflt_target_1 = 0, $and282 = 0, $tobool283 = 0, $62 = 0, $call285 = 0, $tobool286 = 0, $63 = 0, $tobool290 = 0, $call292 = 0, $tobool293 = 0, $64 = 0, $tobool297 = 0, $s_5 = 0, $call299 = 0, $tooltip = 0, $65 = 0, $66 = 0, $67 = 0, $68 = 0, $label302 = 0, $69 = 0, $tobool303 = 0, $call306 = 0, $tooltip307 = 0, $call310 = 0, $tobool311 = 0, $70 = 0, $tobool315 = 0, $call317 = 0, $labeltooltip = 0, $71 = 0, $72 = 0, $73 = 0, $74 = 0, $label320 = 0, $75 = 0, $tobool321 = 0, $call324 = 0, $labeltooltip325 = 0, $call328 = 0, $tobool329 = 0, $76 = 0, $tobool333 = 0, $call335 = 0, $tailtooltip = 0, $77 = 0, $78 = 0, $79 = 0, $80 = 0, $taillabel338 = 0, $81 = 0, $tobool339 = 0, $call342 = 0, $tailtooltip343 = 0, $call346 = 0, $tobool347 = 0, $82 = 0, $tobool351 = 0, $call353 = 0, $headtooltip = 0, $83 = 0, $84 = 0, $85 = 0, $86 = 0, $headlabel356 = 0, $87 = 0, $tobool357 = 0, $call360 = 0, $headtooltip361 = 0, $and365 = 0, $tobool366 = 0, $spl369 = 0, $88 = 0, $tobool370 = 0, $url372 = 0, $89 = 0, $tobool373 = 0, $tooltip375 = 0, $90 = 0, $tobool376 = 0, $and378 = 0, $tobool379 = 0, $obj382 = 0, $91 = 0, $penwidth383 = 0, $92 = 0.0, $div = 0.0, $cmp384 = 0, $cond392 = 0.0, $93 = 0, $size = 0, $94 = 0, $cmp395201 = 0, $list = 0, $i_0202 = 0, $95 = 0, $add_ptr = 0, $inc = 0, $cmp395 = 0, $96 = 0, $url_bsplinemap_poly_n = 0, $97 = 0, $url_bsplinemap_n = 0, $and397 = 0, $tobool398 = 0, $98 = 0, $cmp401198 = 0, $99 = 0, $100 = 0, $nump_0200 = 0, $i_1199 = 0, $arrayidx404 = 0, $101 = 0, $add405 = 0, $inc407 = 0, $cmp401 = 0, $nump_0_lcssa = 0, $102 = 0, $call409 = 0, $103 = 0, $url_bsplinemap_p = 0, $url_map_shape = 0, $104 = 0, $url_map_p = 0, $105 = 0, $106 = 0, $url_map_n = 0, $url414 = 0, $107 = 0, $tobool415 = 0, $108 = 0, $109 = 0, $110 = 0, $_mask = 0, $tobool418 = 0, $111 = 0, $tooltip421 = 0, $112 = 0, $target422 = 0, $113 = 0, $id423 = 0, $114 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 168 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pbs = __stackBase__ | 0;
+ $pbs_n = __stackBase__ + 8 | 0;
+ $pbs_poly_n = __stackBase__ + 16 | 0;
+ $xb = __stackBase__ + 24 | 0;
+ $xbuf = __stackBase__ + 40 | 0;
+ $flags1 = $job + 152 | 0;
+ $0 = HEAP32[$flags1 >> 2] | 0;
+ HEAP32[$pbs >> 2] = 0;
+ HEAP32[$pbs_n >> 2] = 0;
+ HEAP32[$pbs_poly_n >> 2] = 0;
+ $call = _push_obj_state($job) | 0;
+ $type = $call + 4 | 0;
+ HEAP32[$type >> 2] = 3;
+ $1 = $call + 8 | 0;
+ $e_c = $e;
+ HEAP32[$1 >> 2] = $e_c;
+ $emit_state = $call + 12 | 0;
+ HEAP32[$emit_state >> 2] = 9;
+ $tobool = ($styles | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $spl = $e + 24 | 0;
+ $2 = HEAP32[$spl >> 2] | 0;
+ $tobool4 = ($2 | 0) == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _gvrender_set_style($job, $styles);
+ label = 5;
+ break;
+ case 5:
+ $3 = HEAP32[41916] | 0;
+ $tobool5 = ($3 | 0) == 0;
+ if ($tobool5) {
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $4 = $e | 0;
+ $index = $3 + 8 | 0;
+ $5 = HEAP32[$index >> 2] | 0;
+ $call7 = _agxget($4, $5) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $6 = HEAP8[$call7] | 0;
+ $tobool10 = $6 << 24 >> 24 == 0;
+ if ($tobool10) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call12 = +_late_double($4, $3, 1.0, 0.0);
+ _gvrender_set_penwidth($job, $call12);
+ label = 9;
+ break;
+ case 9:
+ $and = $0 & 16777216;
+ $tobool14 = ($and | 0) == 0;
+ if ($tobool14) {
+ label = 19;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $tail = $e + 16 | 0;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $graph = $7 + 20 | 0;
+ $8 = HEAP32[$graph >> 2] | 0;
+ $odim = $8 + 210 | 0;
+ $9 = HEAP16[$odim >> 1] | 0;
+ $cmp = ($9 & 65535) > 2;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 11:
+ $pos = $7 + 148 | 0;
+ $10 = HEAP32[$pos >> 2] | 0;
+ $arrayidx22 = $10 + 16 | 0;
+ $11 = +HEAPF64[$arrayidx22 >> 3];
+ $mul = $11 * 72.0;
+ $cmp23 = $mul < 0.0;
+ if ($cmp23) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $add = $mul + .5;
+ $add_sink = $add;
+ label = 14;
+ break;
+ case 13:
+ $sub = $mul + -.5;
+ $add_sink = $sub;
+ label = 14;
+ break;
+ case 14:
+ $conv30 = ~~$add_sink;
+ $conv37 = +($conv30 | 0);
+ $tail_z = $call + 128 | 0;
+ HEAPF64[$tail_z >> 3] = $conv37;
+ $head = $e + 12 | 0;
+ $12 = HEAP32[$head >> 2] | 0;
+ $pos39 = $12 + 148 | 0;
+ $13 = HEAP32[$pos39 >> 2] | 0;
+ $arrayidx40 = $13 + 16 | 0;
+ $14 = +HEAPF64[$arrayidx40 >> 3];
+ $mul41 = $14 * 72.0;
+ $cmp42 = $mul41 < 0.0;
+ if ($cmp42) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $add50 = $mul41 + .5;
+ $add50_sink = $add50;
+ label = 17;
+ break;
+ case 16:
+ $sub58 = $mul41 + -.5;
+ $add50_sink = $sub58;
+ label = 17;
+ break;
+ case 17:
+ $conv51 = ~~$add50_sink;
+ $conv62 = +($conv51 | 0);
+ $head_z = $call + 136 | 0;
+ HEAPF64[$head_z >> 3] = $conv62;
+ label = 19;
+ break;
+ case 18:
+ $tail_z64 = $call + 128 | 0;
+ $15 = $tail_z64;
+ _memset($15 | 0, 0, 16);
+ label = 19;
+ break;
+ case 19:
+ $and67 = $0 & 32768;
+ $tobool68 = ($and67 | 0) == 0;
+ if ($tobool68) {
+ label = 28;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $label = $e + 112 | 0;
+ $16 = HEAP32[$label >> 2] | 0;
+ $tobool71 = ($16 | 0) == 0;
+ if ($tobool71) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $text = $16 | 0;
+ $17 = HEAP32[$text >> 2] | 0;
+ $label73 = $call + 144 | 0;
+ HEAP32[$label73 >> 2] = $17;
+ label = 22;
+ break;
+ case 22:
+ $label75 = $call + 144 | 0;
+ $18 = HEAP32[$label75 >> 2] | 0;
+ $xlabel = $call + 148 | 0;
+ HEAP32[$xlabel >> 2] = $18;
+ $headlabel = $call + 156 | 0;
+ HEAP32[$headlabel >> 2] = $18;
+ $taillabel = $call + 152 | 0;
+ HEAP32[$taillabel >> 2] = $18;
+ $xlabel77 = $e + 124 | 0;
+ $19 = HEAP32[$xlabel77 >> 2] | 0;
+ $tobool78 = ($19 | 0) == 0;
+ if ($tobool78) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $text80 = $19 | 0;
+ $20 = HEAP32[$text80 >> 2] | 0;
+ HEAP32[$xlabel >> 2] = $20;
+ label = 24;
+ break;
+ case 24:
+ $tail_label = $e + 120 | 0;
+ $21 = HEAP32[$tail_label >> 2] | 0;
+ $tobool84 = ($21 | 0) == 0;
+ if ($tobool84) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $text86 = $21 | 0;
+ $22 = HEAP32[$text86 >> 2] | 0;
+ HEAP32[$taillabel >> 2] = $22;
+ label = 26;
+ break;
+ case 26:
+ $head_label = $e + 116 | 0;
+ $23 = HEAP32[$head_label >> 2] | 0;
+ $tobool90 = ($23 | 0) == 0;
+ if ($tobool90) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $text92 = $23 | 0;
+ $24 = HEAP32[$text92 >> 2] | 0;
+ HEAP32[$headlabel >> 2] = $24;
+ label = 28;
+ break;
+ case 28:
+ $and96 = $0 & 65536;
+ $tobool97 = ($and96 | 0) == 0;
+ if ($tobool97) {
+ $dflt_url_1 = 0;
+ label = 62;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $arraydecay = $xbuf | 0;
+ _agxbinit($xb, 128, $arraydecay);
+ $25 = $e | 0;
+ $call99 = _getObjId($job, $25, $xb) | 0;
+ $call100 = _strdup_and_subst_obj($call99, $25) | 0;
+ $id = $call + 164 | 0;
+ HEAP32[$id >> 2] = $call100;
+ _agxbfree($xb);
+ $call101 = _agget($25, 95856) | 0;
+ $tobool102 = ($call101 | 0) == 0;
+ if ($tobool102) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $26 = HEAP8[$call101] | 0;
+ $tobool106 = $26 << 24 >> 24 == 0;
+ if ($tobool106) {
+ label = 31;
+ break;
+ } else {
+ $s_0 = $call101;
+ label = 33;
+ break;
+ }
+ case 31:
+ $call107 = _agget($25, 95472) | 0;
+ $tobool108 = ($call107 | 0) == 0;
+ if ($tobool108) {
+ $dflt_url_0 = 0;
+ label = 34;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $27 = HEAP8[$call107] | 0;
+ $tobool112 = $27 << 24 >> 24 == 0;
+ if ($tobool112) {
+ $dflt_url_0 = 0;
+ label = 34;
+ break;
+ } else {
+ $s_0 = $call107;
+ label = 33;
+ break;
+ }
+ case 33:
+ $call114 = _strdup_and_subst_obj($s_0, $25) | 0;
+ $dflt_url_0 = $call114;
+ label = 34;
+ break;
+ case 34:
+ $call116 = _agget($25, 95120) | 0;
+ $tobool117 = ($call116 | 0) == 0;
+ if ($tobool117) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $28 = HEAP8[$call116] | 0;
+ $tobool121 = $28 << 24 >> 24 == 0;
+ if ($tobool121) {
+ label = 36;
+ break;
+ } else {
+ $s_1 = $call116;
+ label = 38;
+ break;
+ }
+ case 36:
+ $call123 = _agget($25, 94832) | 0;
+ $tobool124 = ($call123 | 0) == 0;
+ if ($tobool124) {
+ label = 39;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $29 = HEAP8[$call123] | 0;
+ $tobool128 = $29 << 24 >> 24 == 0;
+ if ($tobool128) {
+ label = 39;
+ break;
+ } else {
+ $s_1 = $call123;
+ label = 38;
+ break;
+ }
+ case 38:
+ $call130 = _strdup_and_subst_obj($s_1, $25) | 0;
+ $url = $call + 160 | 0;
+ HEAP32[$url >> 2] = $call130;
+ label = 41;
+ break;
+ case 39:
+ $tobool132 = ($dflt_url_0 | 0) == 0;
+ if ($tobool132) {
+ label = 41;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $call134 = _strdup($dflt_url_0 | 0) | 0;
+ $url135 = $call + 160 | 0;
+ HEAP32[$url135 >> 2] = $call134;
+ label = 41;
+ break;
+ case 41:
+ $call138 = _agget($25, 94544) | 0;
+ $tobool139 = ($call138 | 0) == 0;
+ if ($tobool139) {
+ label = 43;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $30 = HEAP8[$call138] | 0;
+ $tobool143 = $30 << 24 >> 24 == 0;
+ if ($tobool143) {
+ label = 43;
+ break;
+ } else {
+ $s_2 = $call138;
+ label = 45;
+ break;
+ }
+ case 43:
+ $call145 = _agget($25, 94208) | 0;
+ $tobool146 = ($call145 | 0) == 0;
+ if ($tobool146) {
+ label = 46;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $31 = HEAP8[$call145] | 0;
+ $tobool150 = $31 << 24 >> 24 == 0;
+ if ($tobool150) {
+ label = 46;
+ break;
+ } else {
+ $s_2 = $call145;
+ label = 45;
+ break;
+ }
+ case 45:
+ $call152 = _strdup_and_subst_obj($s_2, $25) | 0;
+ $labelurl = $call + 168 | 0;
+ HEAP32[$labelurl >> 2] = $call152;
+ label = 48;
+ break;
+ case 46:
+ $tobool154 = ($dflt_url_0 | 0) == 0;
+ if ($tobool154) {
+ label = 48;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $call156 = _strdup($dflt_url_0 | 0) | 0;
+ $labelurl157 = $call + 168 | 0;
+ HEAP32[$labelurl157 >> 2] = $call156;
+ label = 48;
+ break;
+ case 48:
+ $call160 = _agget($25, 93872) | 0;
+ $tobool161 = ($call160 | 0) == 0;
+ if ($tobool161) {
+ label = 50;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $32 = HEAP8[$call160] | 0;
+ $tobool165 = $32 << 24 >> 24 == 0;
+ if ($tobool165) {
+ label = 50;
+ break;
+ } else {
+ $s_3 = $call160;
+ label = 52;
+ break;
+ }
+ case 50:
+ $call167 = _agget($25, 93488) | 0;
+ $tobool168 = ($call167 | 0) == 0;
+ if ($tobool168) {
+ label = 53;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $33 = HEAP8[$call167] | 0;
+ $tobool172 = $33 << 24 >> 24 == 0;
+ if ($tobool172) {
+ label = 53;
+ break;
+ } else {
+ $s_3 = $call167;
+ label = 52;
+ break;
+ }
+ case 52:
+ $call174 = _strdup_and_subst_obj($s_3, $25) | 0;
+ $tailurl = $call + 172 | 0;
+ HEAP32[$tailurl >> 2] = $call174;
+ $34 = $call + 212 | 0;
+ $35 = $34;
+ $36 = HEAP32[$35 >> 2] | 0;
+ $37 = $36 | 128;
+ HEAP32[$35 >> 2] = $37;
+ label = 55;
+ break;
+ case 53:
+ $tobool176 = ($dflt_url_0 | 0) == 0;
+ if ($tobool176) {
+ label = 55;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 54:
+ $call178 = _strdup($dflt_url_0 | 0) | 0;
+ $tailurl179 = $call + 172 | 0;
+ HEAP32[$tailurl179 >> 2] = $call178;
+ label = 55;
+ break;
+ case 55:
+ $call182 = _agget($25, 93168) | 0;
+ $tobool183 = ($call182 | 0) == 0;
+ if ($tobool183) {
+ label = 57;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 56:
+ $38 = HEAP8[$call182] | 0;
+ $tobool187 = $38 << 24 >> 24 == 0;
+ if ($tobool187) {
+ label = 57;
+ break;
+ } else {
+ $s_4 = $call182;
+ label = 59;
+ break;
+ }
+ case 57:
+ $call189 = _agget($25, 92824) | 0;
+ $tobool190 = ($call189 | 0) == 0;
+ if ($tobool190) {
+ label = 60;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $39 = HEAP8[$call189] | 0;
+ $tobool194 = $39 << 24 >> 24 == 0;
+ if ($tobool194) {
+ label = 60;
+ break;
+ } else {
+ $s_4 = $call189;
+ label = 59;
+ break;
+ }
+ case 59:
+ $call196 = _strdup_and_subst_obj($s_4, $25) | 0;
+ $headurl = $call + 176 | 0;
+ HEAP32[$headurl >> 2] = $call196;
+ $40 = $call + 212 | 0;
+ $41 = $40;
+ $42 = HEAP32[$41 >> 2] | 0;
+ $43 = $42 | 256;
+ HEAP32[$41 >> 2] = $43;
+ $dflt_url_1 = $dflt_url_0;
+ label = 62;
+ break;
+ case 60:
+ $tobool199 = ($dflt_url_0 | 0) == 0;
+ if ($tobool199) {
+ $dflt_url_1 = 0;
+ label = 62;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 61:
+ $call201 = _strdup($dflt_url_0 | 0) | 0;
+ $headurl202 = $call + 176 | 0;
+ HEAP32[$headurl202 >> 2] = $call201;
+ $dflt_url_1 = $dflt_url_0;
+ label = 62;
+ break;
+ case 62:
+ $and206 = $0 & 8388608;
+ $tobool207 = ($and206 | 0) == 0;
+ if ($tobool207) {
+ $dflt_target_1 = 0;
+ label = 86;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ $44 = $e | 0;
+ $call209 = _agget($44, 92456) | 0;
+ $tobool210 = ($call209 | 0) == 0;
+ if ($tobool210) {
+ $dflt_target_0 = 0;
+ label = 66;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 64:
+ $45 = HEAP8[$call209] | 0;
+ $tobool214 = $45 << 24 >> 24 == 0;
+ if ($tobool214) {
+ $dflt_target_0 = 0;
+ label = 66;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $call216 = _strdup_and_subst_obj($call209, $44) | 0;
+ $dflt_target_0 = $call216;
+ label = 66;
+ break;
+ case 66:
+ $call218 = _agget($44, 91968) | 0;
+ $tobool219 = ($call218 | 0) == 0;
+ if ($tobool219) {
+ label = 69;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 67:
+ $46 = HEAP8[$call218] | 0;
+ $tobool223 = $46 << 24 >> 24 == 0;
+ if ($tobool223) {
+ label = 69;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $47 = $call + 212 | 0;
+ $48 = $47;
+ $49 = HEAP32[$48 >> 2] | 0;
+ $50 = $49 | 64;
+ HEAP32[$48 >> 2] = $50;
+ $call226 = _strdup_and_subst_obj($call218, $44) | 0;
+ $target = $call + 196 | 0;
+ HEAP32[$target >> 2] = $call226;
+ label = 71;
+ break;
+ case 69:
+ $tobool228 = ($dflt_target_0 | 0) == 0;
+ if ($tobool228) {
+ label = 71;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $call230 = _strdup($dflt_target_0 | 0) | 0;
+ $target231 = $call + 196 | 0;
+ HEAP32[$target231 >> 2] = $call230;
+ label = 71;
+ break;
+ case 71:
+ $call234 = _agget($44, 91616) | 0;
+ $tobool235 = ($call234 | 0) == 0;
+ if ($tobool235) {
+ label = 74;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 72:
+ $51 = HEAP8[$call234] | 0;
+ $tobool239 = $51 << 24 >> 24 == 0;
+ if ($tobool239) {
+ label = 74;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $call241 = _strdup_and_subst_obj($call234, $44) | 0;
+ $labeltarget = $call + 200 | 0;
+ HEAP32[$labeltarget >> 2] = $call241;
+ label = 76;
+ break;
+ case 74:
+ $tobool243 = ($dflt_target_0 | 0) == 0;
+ if ($tobool243) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $call245 = _strdup($dflt_target_0 | 0) | 0;
+ $labeltarget246 = $call + 200 | 0;
+ HEAP32[$labeltarget246 >> 2] = $call245;
+ label = 76;
+ break;
+ case 76:
+ $call249 = _agget($44, 91328) | 0;
+ $tobool250 = ($call249 | 0) == 0;
+ if ($tobool250) {
+ label = 79;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 77:
+ $52 = HEAP8[$call249] | 0;
+ $tobool254 = $52 << 24 >> 24 == 0;
+ if ($tobool254) {
+ label = 79;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $call256 = _strdup_and_subst_obj($call249, $44) | 0;
+ $tailtarget = $call + 204 | 0;
+ HEAP32[$tailtarget >> 2] = $call256;
+ $53 = $call + 212 | 0;
+ $54 = $53;
+ $55 = HEAP32[$54 >> 2] | 0;
+ $56 = $55 | 16;
+ HEAP32[$54 >> 2] = $56;
+ label = 81;
+ break;
+ case 79:
+ $tobool259 = ($dflt_target_0 | 0) == 0;
+ if ($tobool259) {
+ label = 81;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 80:
+ $call261 = _strdup($dflt_target_0 | 0) | 0;
+ $tailtarget262 = $call + 204 | 0;
+ HEAP32[$tailtarget262 >> 2] = $call261;
+ label = 81;
+ break;
+ case 81:
+ $call265 = _agget($44, 90976) | 0;
+ $tobool266 = ($call265 | 0) == 0;
+ if ($tobool266) {
+ label = 84;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 82:
+ $57 = HEAP8[$call265] | 0;
+ $tobool270 = $57 << 24 >> 24 == 0;
+ if ($tobool270) {
+ label = 84;
+ break;
+ } else {
+ label = 83;
+ break;
+ }
+ case 83:
+ $58 = $call + 212 | 0;
+ $59 = $58;
+ $60 = HEAP32[$59 >> 2] | 0;
+ $61 = $60 | 32;
+ HEAP32[$59 >> 2] = $61;
+ $call273 = _strdup_and_subst_obj($call265, $44) | 0;
+ $headtarget = $call + 208 | 0;
+ HEAP32[$headtarget >> 2] = $call273;
+ $dflt_target_1 = $dflt_target_0;
+ label = 86;
+ break;
+ case 84:
+ $tobool275 = ($dflt_target_0 | 0) == 0;
+ if ($tobool275) {
+ $dflt_target_1 = 0;
+ label = 86;
+ break;
+ } else {
+ label = 85;
+ break;
+ }
+ case 85:
+ $call277 = _strdup($dflt_target_0 | 0) | 0;
+ $headtarget278 = $call + 208 | 0;
+ HEAP32[$headtarget278 >> 2] = $call277;
+ $dflt_target_1 = $dflt_target_0;
+ label = 86;
+ break;
+ case 86:
+ $and282 = $0 & 4194304;
+ $tobool283 = ($and282 | 0) == 0;
+ if ($tobool283) {
+ label = 109;
+ break;
+ } else {
+ label = 87;
+ break;
+ }
+ case 87:
+ $62 = $e | 0;
+ $call285 = _agget($62, 90704) | 0;
+ $tobool286 = ($call285 | 0) == 0;
+ if ($tobool286) {
+ label = 89;
+ break;
+ } else {
+ label = 88;
+ break;
+ }
+ case 88:
+ $63 = HEAP8[$call285] | 0;
+ $tobool290 = $63 << 24 >> 24 == 0;
+ if ($tobool290) {
+ label = 89;
+ break;
+ } else {
+ $s_5 = $call285;
+ label = 91;
+ break;
+ }
+ case 89:
+ $call292 = _agget($62, 90384) | 0;
+ $tobool293 = ($call292 | 0) == 0;
+ if ($tobool293) {
+ label = 92;
+ break;
+ } else {
+ label = 90;
+ break;
+ }
+ case 90:
+ $64 = HEAP8[$call292] | 0;
+ $tobool297 = $64 << 24 >> 24 == 0;
+ if ($tobool297) {
+ label = 92;
+ break;
+ } else {
+ $s_5 = $call292;
+ label = 91;
+ break;
+ }
+ case 91:
+ $call299 = _strdup_and_subst_obj($s_5, $62) | 0;
+ $tooltip = $call + 180 | 0;
+ HEAP32[$tooltip >> 2] = $call299;
+ $65 = $call + 212 | 0;
+ $66 = $65;
+ $67 = HEAP32[$66 >> 2] | 0;
+ $68 = $67 | 1;
+ HEAP32[$66 >> 2] = $68;
+ label = 94;
+ break;
+ case 92:
+ $label302 = $call + 144 | 0;
+ $69 = HEAP32[$label302 >> 2] | 0;
+ $tobool303 = ($69 | 0) == 0;
+ if ($tobool303) {
+ label = 94;
+ break;
+ } else {
+ label = 93;
+ break;
+ }
+ case 93:
+ $call306 = _strdup($69 | 0) | 0;
+ $tooltip307 = $call + 180 | 0;
+ HEAP32[$tooltip307 >> 2] = $call306;
+ label = 94;
+ break;
+ case 94:
+ $call310 = _agget($62, 90080) | 0;
+ $tobool311 = ($call310 | 0) == 0;
+ if ($tobool311) {
+ label = 97;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 95:
+ $70 = HEAP8[$call310] | 0;
+ $tobool315 = $70 << 24 >> 24 == 0;
+ if ($tobool315) {
+ label = 97;
+ break;
+ } else {
+ label = 96;
+ break;
+ }
+ case 96:
+ $call317 = _strdup_and_subst_obj($call310, $62) | 0;
+ $labeltooltip = $call + 184 | 0;
+ HEAP32[$labeltooltip >> 2] = $call317;
+ $71 = $call + 212 | 0;
+ $72 = $71;
+ $73 = HEAP32[$72 >> 2] | 0;
+ $74 = $73 | 8;
+ HEAP32[$72 >> 2] = $74;
+ label = 99;
+ break;
+ case 97:
+ $label320 = $call + 144 | 0;
+ $75 = HEAP32[$label320 >> 2] | 0;
+ $tobool321 = ($75 | 0) == 0;
+ if ($tobool321) {
+ label = 99;
+ break;
+ } else {
+ label = 98;
+ break;
+ }
+ case 98:
+ $call324 = _strdup($75 | 0) | 0;
+ $labeltooltip325 = $call + 184 | 0;
+ HEAP32[$labeltooltip325 >> 2] = $call324;
+ label = 99;
+ break;
+ case 99:
+ $call328 = _agget($62, 163232) | 0;
+ $tobool329 = ($call328 | 0) == 0;
+ if ($tobool329) {
+ label = 102;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 100:
+ $76 = HEAP8[$call328] | 0;
+ $tobool333 = $76 << 24 >> 24 == 0;
+ if ($tobool333) {
+ label = 102;
+ break;
+ } else {
+ label = 101;
+ break;
+ }
+ case 101:
+ $call335 = _strdup_and_subst_obj($call328, $62) | 0;
+ $tailtooltip = $call + 188 | 0;
+ HEAP32[$tailtooltip >> 2] = $call335;
+ $77 = $call + 212 | 0;
+ $78 = $77;
+ $79 = HEAP32[$78 >> 2] | 0;
+ $80 = $79 | 2;
+ HEAP32[$78 >> 2] = $80;
+ label = 104;
+ break;
+ case 102:
+ $taillabel338 = $call + 152 | 0;
+ $81 = HEAP32[$taillabel338 >> 2] | 0;
+ $tobool339 = ($81 | 0) == 0;
+ if ($tobool339) {
+ label = 104;
+ break;
+ } else {
+ label = 103;
+ break;
+ }
+ case 103:
+ $call342 = _strdup($81 | 0) | 0;
+ $tailtooltip343 = $call + 188 | 0;
+ HEAP32[$tailtooltip343 >> 2] = $call342;
+ label = 104;
+ break;
+ case 104:
+ $call346 = _agget($62, 162944) | 0;
+ $tobool347 = ($call346 | 0) == 0;
+ if ($tobool347) {
+ label = 107;
+ break;
+ } else {
+ label = 105;
+ break;
+ }
+ case 105:
+ $82 = HEAP8[$call346] | 0;
+ $tobool351 = $82 << 24 >> 24 == 0;
+ if ($tobool351) {
+ label = 107;
+ break;
+ } else {
+ label = 106;
+ break;
+ }
+ case 106:
+ $call353 = _strdup_and_subst_obj($call346, $62) | 0;
+ $headtooltip = $call + 192 | 0;
+ HEAP32[$headtooltip >> 2] = $call353;
+ $83 = $call + 212 | 0;
+ $84 = $83;
+ $85 = HEAP32[$84 >> 2] | 0;
+ $86 = $85 | 4;
+ HEAP32[$84 >> 2] = $86;
+ label = 109;
+ break;
+ case 107:
+ $headlabel356 = $call + 156 | 0;
+ $87 = HEAP32[$headlabel356 >> 2] | 0;
+ $tobool357 = ($87 | 0) == 0;
+ if ($tobool357) {
+ label = 109;
+ break;
+ } else {
+ label = 108;
+ break;
+ }
+ case 108:
+ $call360 = _strdup($87 | 0) | 0;
+ $headtooltip361 = $call + 192 | 0;
+ HEAP32[$headtooltip361 >> 2] = $call360;
+ label = 109;
+ break;
+ case 109:
+ _free($dflt_url_1);
+ _free($dflt_target_1);
+ $and365 = $0 & 4259840;
+ $tobool366 = ($and365 | 0) == 0;
+ if ($tobool366) {
+ label = 123;
+ break;
+ } else {
+ label = 110;
+ break;
+ }
+ case 110:
+ $spl369 = $e + 24 | 0;
+ $88 = HEAP32[$spl369 >> 2] | 0;
+ $tobool370 = ($88 | 0) == 0;
+ if ($tobool370) {
+ label = 123;
+ break;
+ } else {
+ label = 111;
+ break;
+ }
+ case 111:
+ $url372 = $call + 160 | 0;
+ $89 = HEAP32[$url372 >> 2] | 0;
+ $tobool373 = ($89 | 0) == 0;
+ if ($tobool373) {
+ label = 112;
+ break;
+ } else {
+ label = 113;
+ break;
+ }
+ case 112:
+ $tooltip375 = $call + 180 | 0;
+ $90 = HEAP32[$tooltip375 >> 2] | 0;
+ $tobool376 = ($90 | 0) == 0;
+ if ($tobool376) {
+ label = 123;
+ break;
+ } else {
+ label = 113;
+ break;
+ }
+ case 113:
+ $and378 = $0 & 524288;
+ $tobool379 = ($and378 | 0) == 0;
+ if ($tobool379) {
+ label = 123;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 114:
+ $obj382 = $job + 16 | 0;
+ $91 = HEAP32[$obj382 >> 2] | 0;
+ $penwidth383 = $91 + 104 | 0;
+ $92 = +HEAPF64[$penwidth383 >> 3];
+ $div = $92 * .5;
+ $cmp384 = $div > 2.0;
+ $cond392 = $cmp384 ? $div : 2.0;
+ $93 = HEAP32[$spl369 >> 2] | 0;
+ $size = $93 + 4 | 0;
+ $94 = HEAP32[$size >> 2] | 0;
+ $cmp395201 = ($94 | 0) > 0;
+ if ($cmp395201) {
+ label = 115;
+ break;
+ } else {
+ label = 117;
+ break;
+ }
+ case 115:
+ $list = $93 | 0;
+ $i_0202 = 0;
+ label = 116;
+ break;
+ case 116:
+ $95 = HEAP32[$list >> 2] | 0;
+ $add_ptr = $95 + ($i_0202 * 48 & -1) | 0;
+ _map_output_bspline($pbs, $pbs_n, $pbs_poly_n, $add_ptr, $cond392);
+ $inc = $i_0202 + 1 | 0;
+ $cmp395 = ($inc | 0) < ($94 | 0);
+ if ($cmp395) {
+ $i_0202 = $inc;
+ label = 116;
+ break;
+ } else {
+ label = 117;
+ break;
+ }
+ case 117:
+ $96 = HEAP32[$pbs_poly_n >> 2] | 0;
+ $url_bsplinemap_poly_n = $call + 228 | 0;
+ HEAP32[$url_bsplinemap_poly_n >> 2] = $96;
+ $97 = HEAP32[$pbs_n >> 2] | 0;
+ $url_bsplinemap_n = $call + 232 | 0;
+ HEAP32[$url_bsplinemap_n >> 2] = $97;
+ $and397 = $0 & 8192;
+ $tobool398 = ($and397 | 0) == 0;
+ if ($tobool398) {
+ label = 118;
+ break;
+ } else {
+ label = 122;
+ break;
+ }
+ case 118:
+ $98 = HEAP32[$pbs_poly_n >> 2] | 0;
+ $cmp401198 = ($98 | 0) > 0;
+ if ($cmp401198) {
+ label = 119;
+ break;
+ } else {
+ $nump_0_lcssa = 0;
+ label = 121;
+ break;
+ }
+ case 119:
+ $99 = HEAP32[$pbs_n >> 2] | 0;
+ $100 = HEAP32[$pbs_poly_n >> 2] | 0;
+ $i_1199 = 0;
+ $nump_0200 = 0;
+ label = 120;
+ break;
+ case 120:
+ $arrayidx404 = $99 + ($i_1199 << 2) | 0;
+ $101 = HEAP32[$arrayidx404 >> 2] | 0;
+ $add405 = $101 + $nump_0200 | 0;
+ $inc407 = $i_1199 + 1 | 0;
+ $cmp401 = ($inc407 | 0) < ($100 | 0);
+ if ($cmp401) {
+ $i_1199 = $inc407;
+ $nump_0200 = $add405;
+ label = 120;
+ break;
+ } else {
+ $nump_0_lcssa = $add405;
+ label = 121;
+ break;
+ }
+ case 121:
+ $102 = HEAP32[$pbs >> 2] | 0;
+ $call409 = _gvrender_ptf_A($job, $102, $102, $nump_0_lcssa) | 0;
+ label = 122;
+ break;
+ case 122:
+ $103 = HEAP32[$pbs >> 2] | 0;
+ $url_bsplinemap_p = $call + 236 | 0;
+ HEAP32[$url_bsplinemap_p >> 2] = $103;
+ $url_map_shape = $call + 216 | 0;
+ HEAP32[$url_map_shape >> 2] = 2;
+ $104 = HEAP32[$pbs >> 2] | 0;
+ $url_map_p = $call + 224 | 0;
+ HEAP32[$url_map_p >> 2] = $104;
+ $105 = HEAP32[$pbs_n >> 2] | 0;
+ $106 = HEAP32[$105 >> 2] | 0;
+ $url_map_n = $call + 220 | 0;
+ HEAP32[$url_map_n >> 2] = $106;
+ label = 123;
+ break;
+ case 123:
+ _gvrender_begin_edge($job, 0);
+ $url414 = $call + 160 | 0;
+ $107 = HEAP32[$url414 >> 2] | 0;
+ $tobool415 = ($107 | 0) == 0;
+ if ($tobool415) {
+ label = 124;
+ break;
+ } else {
+ label = 125;
+ break;
+ }
+ case 124:
+ $108 = $call + 212 | 0;
+ $109 = $108;
+ $110 = HEAP32[$109 >> 2] | 0;
+ $_mask = $110 & 1;
+ $tobool418 = ($_mask | 0) == 0;
+ if ($tobool418) {
+ label = 126;
+ break;
+ } else {
+ label = 125;
+ break;
+ }
+ case 125:
+ $111 = HEAP32[$url414 >> 2] | 0;
+ $tooltip421 = $call + 180 | 0;
+ $112 = HEAP32[$tooltip421 >> 2] | 0;
+ $target422 = $call + 196 | 0;
+ $113 = HEAP32[$target422 >> 2] | 0;
+ $id423 = $call + 164 | 0;
+ $114 = HEAP32[$id423 >> 2] | 0;
+ _gvrender_begin_anchor($job, $111, $112, $113, $114);
+ label = 126;
+ break;
+ case 126:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_edge_graphics($job, $e, $styles) {
+ $job = $job | 0;
+ $e = $e | 0;
+ $styles = $styles | 0;
+ var $bz = 0, $pf0 = 0, $pf1 = 0, $pf2 = 0, $pf3 = 0, $tmp = 0, $tmp128 = 0, $tmp140 = 0, $tmp193 = 0, $0 = 0, $obj = 0, $1 = 0, $penwidth1 = 0, $2 = 0.0, $3 = 0, $call = 0, $spl = 0, $4 = 0, $tobool = 0, $5 = 0, $call2 = 0.0, $6 = 0, $call3 = 0, $numcomma_0 = 0, $numc_0 = 0, $p_0 = 0, $7 = 0, $inc = 0, $inc11 = 0, $numcomma_1 = 0, $numc_1 = 0, $incdec_ptr = 0, $tobool13 = 0, $tobool14 = 0, $or_cond = 0, $add = 0, $call16 = 0, $tobool17 = 0, $color_0 = 0, $gui_state = 0, $8 = 0, $conv23 = 0, $and = 0, $tobool24 = 0, $9 = 0, $call26 = 0, $call27 = 0, $10 = 0, $call28 = 0, $and33 = 0, $tobool34 = 0, $11 = 0, $call36 = 0, $call37 = 0, $12 = 0, $call38 = 0, $and43 = 0, $tobool44 = 0, $13 = 0, $call46 = 0, $call47 = 0, $14 = 0, $call48 = 0, $and53 = 0, $tobool54 = 0, $15 = 0, $call56 = 0, $call57 = 0, $16 = 0, $call58 = 0, $fillcolor_0 = 0, $pencolor_0 = 0, $cmp63 = 0, $cmp67 = 0, $pencolor_0191193 = 0, $17 = 0, $size = 0, $18 = 0, $mul = 0, $call78 = 0, $19 = 0, $call81 = 0, $20 = 0, $add83 = 0, $conv84 = 0.0, $div = 0.0, $cmp87216 = 0, $21 = 0, $size93 = 0, $list112 = 0, $22 = 0, $23 = 0, $x194 = 0, $y201 = 0, $24 = 0, $25 = 0, $26 = 0, $27 = 0, $x = 0, $y = 0, $x153 = 0, $y162 = 0, $x171 = 0, $y180 = 0, $28 = 0, $i_0217 = 0, $29 = 0, $list92 = 0, $30 = 0, $arrayidx = 0, $31 = 0, $32 = 0, $size96 = 0, $size99 = 0, $33 = 0, $mul101 = 0, $call102 = 0, $34 = 0, $list105 = 0, $35 = 0, $mul107 = 0, $call108 = 0, $36 = 0, $list111 = 0, $37 = 0, $38 = 0, $39 = 0, $sub212 = 0, $cmp116213 = 0, $j_0214 = 0, $add119 = 0, $40 = 0, $arrayidx121 = 0, $41 = 0, $cmp122 = 0, $arrayidx125 = 0, $42 = 0, $43 = 0, $add130 = 0, $44 = 0, $arrayidx132 = 0, $45 = 0, $add133 = 0, $46 = 0, $arrayidx135 = 0, $47 = 0, $arrayidx137 = 0, $arrayidx139 = 0, $48 = 0, $49 = 0, $50 = 0.0, $x142 = 0, $51 = 0.0, $mul143 = 0.0, $sub144 = 0.0, $x146 = 0, $52 = 0.0, $y148 = 0, $53 = 0.0, $mul149 = 0.0, $sub150 = 0.0, $y152 = 0, $54 = 0.0, $x156 = 0, $55 = 0.0, $mul157 = 0.0, $sub158 = 0.0, $x161 = 0, $56 = 0.0, $y165 = 0, $57 = 0.0, $mul166 = 0.0, $sub167 = 0.0, $y170 = 0, $58 = 0.0, $x174 = 0, $59 = 0.0, $mul175 = 0.0, $sub176 = 0.0, $x179 = 0, $60 = 0.0, $y183 = 0, $61 = 0.0, $mul184 = 0.0, $sub185 = 0.0, $y188 = 0, $62 = 0, $sub = 0, $cmp116 = 0, $j_0_lcssa = 0, $arrayidx192 = 0, $63 = 0, $64 = 0.0, $x196 = 0, $65 = 0.0, $mul197 = 0.0, $sub198 = 0.0, $x200 = 0, $66 = 0.0, $y203 = 0, $67 = 0.0, $mul204 = 0.0, $sub205 = 0.0, $y207 = 0, $inc209 = 0, $cmp87 = 0, $call211 = 0, $call212 = 0, $tobool214203 = 0, $cmp241201 = 0, $cnum_0208 = 0, $color_1207 = 0, $lastcolor_0206 = 0, $tailcolor_0205 = 0, $headcolor_0204 = 0, $68 = 0, $tobool217 = 0, $_color_1 = 0, $cmp220 = 0, $69 = 0, $and226 = 0, $tobool227 = 0, $lastcolor_1 = 0, $cmp231 = 0, $_color_1_headcolor_0 = 0, $_color_1_tailcolor_0 = 0, $cmp235 = 0, $tailcolor_2 = 0, $i_1202 = 0, $list246 = 0, $70 = 0, $list249 = 0, $71 = 0, $size253 = 0, $72 = 0, $cmp254199 = 0, $j_1200 = 0, $x258 = 0, $73 = 0.0, $x260 = 0, $74 = 0.0, $add261 = 0.0, $y263 = 0, $75 = 0.0, $y265 = 0, $76 = 0.0, $add266 = 0.0, $inc268 = 0, $77 = 0, $cmp254 = 0, $_lcssa = 0, $inc274 = 0, $cmp241 = 0, $inc277 = 0, $call278 = 0, $tobool214 = 0, $tailcolor_0_lcssa = 0, $headcolor_0_lcssa = 0, $sflag = 0, $78 = 0, $tobool280 = 0, $cmp282 = 0, $79 = 0, $and288 = 0, $tobool289 = 0, $color_3 = 0, $sp = 0, $list293 = 0, $80 = 0, $81 = 0, $color_4 = 0, $eflag = 0, $82 = 0, $tobool297 = 0, $cmp299 = 0, $83 = 0, $and305 = 0, $tobool306 = 0, $ep = 0, $size310 = 0, $84 = 0, $sub311 = 0, $list312 = 0, $85 = 0, $arrayidx313 = 0, $86 = 0, $cmp318197 = 0, $i_2198 = 0, $list323 = 0, $87 = 0, $88 = 0, $list326 = 0, $89 = 0, $90 = 0, $inc328 = 0, $cmp318 = 0, $91 = 0, $and336 = 0, $tobool337 = 0, $92 = 0, $tobool340 = 0, $93 = 0, $size348194 = 0, $94 = 0, $cmp349195 = 0, $95 = 0, $flags = 0, $list359 = 0, $size360 = 0, $sflag366 = 0, $eflag374 = 0, $tobool395 = 0, $tobool395_old = 0, $ep377 = 0, $sp369 = 0, $sflag361 = 0, $eflag362 = 0, $96 = 0, $i_3196 = 0, $list354 = 0, $97 = 0, $arrayidx355 = 0, $98 = 0, $99 = 0, $and356 = 0, $tobool357 = 0, $100 = 0, $101 = 0, $102 = 0, $103 = 0, $104 = 0, $tobool367 = 0, $105 = 0, $106 = 0, $tobool375 = 0, $107 = 0, $sub379 = 0, $108 = 0, $arrayidx381 = 0, $109 = 0, $size386 = 0, $110 = 0, $cmp387 = 0, $111 = 0, $tobool391 = 0, $112 = 0, $tobool393 = 0, $or_cond188 = 0, $inc400 = 0, $113 = 0, $size348 = 0, $114 = 0, $cmp349 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 176 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $bz = __stackBase__ | 0;
+ $pf0 = __stackBase__ + 48 | 0;
+ $pf1 = __stackBase__ + 64 | 0;
+ $pf2 = __stackBase__ + 80 | 0;
+ $pf3 = __stackBase__ + 96 | 0;
+ $tmp = __stackBase__ + 112 | 0;
+ $tmp128 = __stackBase__ + 128 | 0;
+ $tmp140 = __stackBase__ + 144 | 0;
+ $tmp193 = __stackBase__ + 160 | 0;
+ $0 = $pf2;
+ _memset($0 | 0, 0, 16);
+ $obj = $job + 16 | 0;
+ $1 = HEAP32[$obj >> 2] | 0;
+ $penwidth1 = $1 + 104 | 0;
+ $2 = +HEAPF64[$penwidth1 >> 3];
+ $3 = $e | 0;
+ $call = _agget($3, 133704) | 0;
+ _setColorScheme($call);
+ $spl = $e + 24 | 0;
+ $4 = HEAP32[$spl >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ label = 72;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $5 = HEAP32[41962] | 0;
+ $call2 = +_late_double($3, $5, 1.0, 0.0);
+ $6 = HEAP32[41958] | 0;
+ $call3 = _late_string($3, $6, 136112) | 0;
+ $p_0 = $call3;
+ $numc_0 = 0;
+ $numcomma_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ $7 = HEAP8[$p_0] | 0;
+ if (($7 << 24 >> 24 | 0) == 58) {
+ label = 5;
+ break;
+ } else if (($7 << 24 >> 24 | 0) == 44) {
+ label = 6;
+ break;
+ } else if (($7 << 24 >> 24 | 0) == 0) {
+ label = 8;
+ break;
+ } else {
+ $numc_1 = $numc_0;
+ $numcomma_1 = $numcomma_0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $inc = $numc_0 + 1 | 0;
+ $numc_1 = $inc;
+ $numcomma_1 = $numcomma_0;
+ label = 7;
+ break;
+ case 6:
+ $inc11 = $numcomma_0 + 1 | 0;
+ $numc_1 = $numc_0;
+ $numcomma_1 = $inc11;
+ label = 7;
+ break;
+ case 7:
+ $incdec_ptr = $p_0 + 1 | 0;
+ $p_0 = $incdec_ptr;
+ $numc_0 = $numc_1;
+ $numcomma_0 = $numcomma_1;
+ label = 4;
+ break;
+ case 8:
+ $tobool13 = ($numcomma_0 | 0) == 0;
+ $tobool14 = ($numc_0 | 0) == 0;
+ $or_cond = $tobool13 | $tobool14;
+ if ($or_cond) {
+ $color_0 = $call3;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add = $numc_0 + 1 | 0;
+ $call16 = _multicolor($job, $e, $styles, $call3, $add, $call2, $2) | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ if ($tobool17) {
+ label = 72;
+ break;
+ } else {
+ $color_0 = 117856;
+ label = 10;
+ break;
+ }
+ case 10:
+ $gui_state = $e + 131 | 0;
+ $8 = HEAP8[$gui_state] | 0;
+ $conv23 = $8 & 255;
+ $and = $conv23 & 1;
+ $tobool24 = ($and | 0) == 0;
+ if ($tobool24) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $9 = HEAP32[41966] | 0;
+ $call26 = _default_pencolor($color_0, 131512) | 0;
+ $call27 = _late_nnstring($3, $9, $call26) | 0;
+ $10 = HEAP32[41968] | 0;
+ $call28 = _late_nnstring($3, $10, 130536) | 0;
+ $pencolor_0 = $call27;
+ $fillcolor_0 = $call28;
+ label = 18;
+ break;
+ case 12:
+ $and33 = $conv23 & 2;
+ $tobool34 = ($and33 | 0) == 0;
+ if ($tobool34) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $11 = HEAP32[41908] | 0;
+ $call36 = _default_pencolor($color_0, 128656) | 0;
+ $call37 = _late_nnstring($3, $11, $call36) | 0;
+ $12 = HEAP32[41910] | 0;
+ $call38 = _late_nnstring($3, $12, 126080) | 0;
+ $pencolor_0 = $call37;
+ $fillcolor_0 = $call38;
+ label = 18;
+ break;
+ case 14:
+ $and43 = $conv23 & 8;
+ $tobool44 = ($and43 | 0) == 0;
+ if ($tobool44) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $13 = HEAP32[41948] | 0;
+ $call46 = _default_pencolor($color_0, 122664) | 0;
+ $call47 = _late_nnstring($3, $13, $call46) | 0;
+ $14 = HEAP32[41950] | 0;
+ $call48 = _late_nnstring($3, $14, 121984) | 0;
+ $pencolor_0 = $call47;
+ $fillcolor_0 = $call48;
+ label = 18;
+ break;
+ case 16:
+ $and53 = $conv23 & 4;
+ $tobool54 = ($and53 | 0) == 0;
+ if ($tobool54) {
+ $pencolor_0191193 = $color_0;
+ label = 22;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $15 = HEAP32[41896] | 0;
+ $call56 = _default_pencolor($color_0, 121456) | 0;
+ $call57 = _late_nnstring($3, $15, $call56) | 0;
+ $16 = HEAP32[41898] | 0;
+ $call58 = _late_nnstring($3, $16, 120728) | 0;
+ $pencolor_0 = $call57;
+ $fillcolor_0 = $call58;
+ label = 18;
+ break;
+ case 18:
+ $cmp63 = ($pencolor_0 | 0) == ($color_0 | 0);
+ if ($cmp63) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ _gvrender_set_pencolor($job, $pencolor_0);
+ label = 20;
+ break;
+ case 20:
+ $cmp67 = ($fillcolor_0 | 0) == ($color_0 | 0);
+ if ($cmp67) {
+ $pencolor_0191193 = $pencolor_0;
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ _gvrender_set_fillcolor($job, $fillcolor_0);
+ $pencolor_0191193 = $pencolor_0;
+ label = 22;
+ break;
+ case 22:
+ if ($tobool14) {
+ label = 54;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $17 = HEAP32[$spl >> 2] | 0;
+ $size = $17 + 4 | 0;
+ $18 = HEAP32[$size >> 2] | 0;
+ $mul = $18 * 48 & -1;
+ $call78 = _malloc($mul) | 0;
+ $19 = $call78;
+ $call81 = _malloc($mul) | 0;
+ $20 = $call81;
+ $add83 = $numc_0 + 2 | 0;
+ $conv84 = +($add83 | 0);
+ $div = $conv84 * .5;
+ $cmp87216 = ($18 | 0) > 0;
+ if ($cmp87216) {
+ label = 24;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 24:
+ $21 = $bz;
+ $size93 = $bz + 4 | 0;
+ $list112 = $bz | 0;
+ $22 = $pf3;
+ $23 = $tmp193;
+ $x194 = $pf3 | 0;
+ $y201 = $pf3 + 8 | 0;
+ $24 = $pf0;
+ $25 = $pf1;
+ $26 = $tmp;
+ $27 = $tmp140;
+ $x = $pf0 | 0;
+ $y = $pf0 + 8 | 0;
+ $x153 = $pf1 | 0;
+ $y162 = $pf1 + 8 | 0;
+ $x171 = $pf2 | 0;
+ $y180 = $pf2 + 8 | 0;
+ $28 = $tmp128;
+ $i_0217 = 0;
+ label = 25;
+ break;
+ case 25:
+ $29 = HEAP32[$spl >> 2] | 0;
+ $list92 = $29 | 0;
+ $30 = HEAP32[$list92 >> 2] | 0;
+ $arrayidx = $30 + ($i_0217 * 48 & -1) | 0;
+ $31 = $arrayidx;
+ HEAP32[$21 >> 2] = HEAP32[$31 >> 2] | 0;
+ HEAP32[$21 + 4 >> 2] = HEAP32[$31 + 4 >> 2] | 0;
+ HEAP32[$21 + 8 >> 2] = HEAP32[$31 + 8 >> 2] | 0;
+ HEAP32[$21 + 12 >> 2] = HEAP32[$31 + 12 >> 2] | 0;
+ HEAP32[$21 + 16 >> 2] = HEAP32[$31 + 16 >> 2] | 0;
+ HEAP32[$21 + 20 >> 2] = HEAP32[$31 + 20 >> 2] | 0;
+ HEAP32[$21 + 24 >> 2] = HEAP32[$31 + 24 >> 2] | 0;
+ HEAP32[$21 + 28 >> 2] = HEAP32[$31 + 28 >> 2] | 0;
+ HEAP32[$21 + 32 >> 2] = HEAP32[$31 + 32 >> 2] | 0;
+ HEAP32[$21 + 36 >> 2] = HEAP32[$31 + 36 >> 2] | 0;
+ HEAP32[$21 + 40 >> 2] = HEAP32[$31 + 40 >> 2] | 0;
+ HEAP32[$21 + 44 >> 2] = HEAP32[$31 + 44 >> 2] | 0;
+ $32 = HEAP32[$size93 >> 2] | 0;
+ $size96 = $19 + ($i_0217 * 48 & -1) + 4 | 0;
+ HEAP32[$size96 >> 2] = $32;
+ $size99 = $20 + ($i_0217 * 48 & -1) + 4 | 0;
+ HEAP32[$size99 >> 2] = $32;
+ $33 = HEAP32[$size93 >> 2] | 0;
+ $mul101 = $33 << 4;
+ $call102 = _malloc($mul101) | 0;
+ $34 = $call102;
+ $list105 = $19 + ($i_0217 * 48 & -1) | 0;
+ HEAP32[$list105 >> 2] = $34;
+ $35 = HEAP32[$size93 >> 2] | 0;
+ $mul107 = $35 << 4;
+ $call108 = _malloc($mul107) | 0;
+ $36 = $call108;
+ $list111 = $20 + ($i_0217 * 48 & -1) | 0;
+ HEAP32[$list111 >> 2] = $36;
+ $37 = HEAP32[$list112 >> 2] | 0;
+ $38 = $37;
+ HEAP32[$22 >> 2] = HEAP32[$38 >> 2] | 0;
+ HEAP32[$22 + 4 >> 2] = HEAP32[$38 + 4 >> 2] | 0;
+ HEAP32[$22 + 8 >> 2] = HEAP32[$38 + 8 >> 2] | 0;
+ HEAP32[$22 + 12 >> 2] = HEAP32[$38 + 12 >> 2] | 0;
+ $39 = HEAP32[$size93 >> 2] | 0;
+ $sub212 = $39 - 1 | 0;
+ $cmp116213 = ($sub212 | 0) > 0;
+ if ($cmp116213) {
+ $j_0214 = 0;
+ label = 26;
+ break;
+ } else {
+ $j_0_lcssa = 0;
+ label = 30;
+ break;
+ }
+ case 26:
+ HEAP32[$24 >> 2] = HEAP32[$22 >> 2] | 0;
+ HEAP32[$24 + 4 >> 2] = HEAP32[$22 + 4 >> 2] | 0;
+ HEAP32[$24 + 8 >> 2] = HEAP32[$22 + 8 >> 2] | 0;
+ HEAP32[$24 + 12 >> 2] = HEAP32[$22 + 12 >> 2] | 0;
+ $add119 = $j_0214 + 1 | 0;
+ $40 = HEAP32[$list112 >> 2] | 0;
+ $arrayidx121 = $40 + ($add119 << 4) | 0;
+ $41 = $arrayidx121;
+ HEAP32[$25 >> 2] = HEAP32[$41 >> 2] | 0;
+ HEAP32[$25 + 4 >> 2] = HEAP32[$41 + 4 >> 2] | 0;
+ HEAP32[$25 + 8 >> 2] = HEAP32[$41 + 8 >> 2] | 0;
+ HEAP32[$25 + 12 >> 2] = HEAP32[$41 + 12 >> 2] | 0;
+ $cmp122 = ($j_0214 | 0) == 0;
+ $arrayidx125 = $34 + ($j_0214 << 4) | 0;
+ if ($cmp122) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ _computeoffset_p($tmp, $pf0, $pf1);
+ $42 = $arrayidx125;
+ HEAP32[$42 >> 2] = HEAP32[$26 >> 2] | 0;
+ HEAP32[$42 + 4 >> 2] = HEAP32[$26 + 4 >> 2] | 0;
+ HEAP32[$42 + 8 >> 2] = HEAP32[$26 + 8 >> 2] | 0;
+ HEAP32[$42 + 12 >> 2] = HEAP32[$26 + 12 >> 2] | 0;
+ label = 29;
+ break;
+ case 28:
+ _computeoffset_p($tmp128, $pf2, $pf1);
+ $43 = $arrayidx125;
+ HEAP32[$43 >> 2] = HEAP32[$28 >> 2] | 0;
+ HEAP32[$43 + 4 >> 2] = HEAP32[$28 + 4 >> 2] | 0;
+ HEAP32[$43 + 8 >> 2] = HEAP32[$28 + 8 >> 2] | 0;
+ HEAP32[$43 + 12 >> 2] = HEAP32[$28 + 12 >> 2] | 0;
+ label = 29;
+ break;
+ case 29:
+ $add130 = $j_0214 + 2 | 0;
+ $44 = HEAP32[$list112 >> 2] | 0;
+ $arrayidx132 = $44 + ($add130 << 4) | 0;
+ $45 = $arrayidx132;
+ HEAP32[$0 >> 2] = HEAP32[$45 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$45 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$45 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$45 + 12 >> 2] | 0;
+ $add133 = $j_0214 + 3 | 0;
+ $46 = HEAP32[$list112 >> 2] | 0;
+ $arrayidx135 = $46 + ($add133 << 4) | 0;
+ $47 = $arrayidx135;
+ HEAP32[$22 >> 2] = HEAP32[$47 >> 2] | 0;
+ HEAP32[$22 + 4 >> 2] = HEAP32[$47 + 4 >> 2] | 0;
+ HEAP32[$22 + 8 >> 2] = HEAP32[$47 + 8 >> 2] | 0;
+ HEAP32[$22 + 12 >> 2] = HEAP32[$47 + 12 >> 2] | 0;
+ $arrayidx137 = $34 + ($add119 << 4) | 0;
+ $arrayidx139 = $34 + ($add130 << 4) | 0;
+ _computeoffset_qr($tmp140, $pf0, $pf1, $pf2, $pf3);
+ $48 = $arrayidx139;
+ HEAP32[$48 >> 2] = HEAP32[$27 >> 2] | 0;
+ HEAP32[$48 + 4 >> 2] = HEAP32[$27 + 4 >> 2] | 0;
+ HEAP32[$48 + 8 >> 2] = HEAP32[$27 + 8 >> 2] | 0;
+ HEAP32[$48 + 12 >> 2] = HEAP32[$27 + 12 >> 2] | 0;
+ $49 = $arrayidx137;
+ HEAP32[$49 >> 2] = HEAP32[$27 >> 2] | 0;
+ HEAP32[$49 + 4 >> 2] = HEAP32[$27 + 4 >> 2] | 0;
+ HEAP32[$49 + 8 >> 2] = HEAP32[$27 + 8 >> 2] | 0;
+ HEAP32[$49 + 12 >> 2] = HEAP32[$27 + 12 >> 2] | 0;
+ $50 = +HEAPF64[$x >> 3];
+ $x142 = $arrayidx125 | 0;
+ $51 = +HEAPF64[$x142 >> 3];
+ $mul143 = $div * $51;
+ $sub144 = $50 - $mul143;
+ $x146 = $36 + ($j_0214 << 4) | 0;
+ HEAPF64[$x146 >> 3] = $sub144;
+ $52 = +HEAPF64[$y >> 3];
+ $y148 = $34 + ($j_0214 << 4) + 8 | 0;
+ $53 = +HEAPF64[$y148 >> 3];
+ $mul149 = $div * $53;
+ $sub150 = $52 - $mul149;
+ $y152 = $36 + ($j_0214 << 4) + 8 | 0;
+ HEAPF64[$y152 >> 3] = $sub150;
+ $54 = +HEAPF64[$x153 >> 3];
+ $x156 = $arrayidx137 | 0;
+ $55 = +HEAPF64[$x156 >> 3];
+ $mul157 = $div * $55;
+ $sub158 = $54 - $mul157;
+ $x161 = $36 + ($add119 << 4) | 0;
+ HEAPF64[$x161 >> 3] = $sub158;
+ $56 = +HEAPF64[$y162 >> 3];
+ $y165 = $34 + ($add119 << 4) + 8 | 0;
+ $57 = +HEAPF64[$y165 >> 3];
+ $mul166 = $div * $57;
+ $sub167 = $56 - $mul166;
+ $y170 = $36 + ($add119 << 4) + 8 | 0;
+ HEAPF64[$y170 >> 3] = $sub167;
+ $58 = +HEAPF64[$x171 >> 3];
+ $x174 = $arrayidx139 | 0;
+ $59 = +HEAPF64[$x174 >> 3];
+ $mul175 = $div * $59;
+ $sub176 = $58 - $mul175;
+ $x179 = $36 + ($add130 << 4) | 0;
+ HEAPF64[$x179 >> 3] = $sub176;
+ $60 = +HEAPF64[$y180 >> 3];
+ $y183 = $34 + ($add130 << 4) + 8 | 0;
+ $61 = +HEAPF64[$y183 >> 3];
+ $mul184 = $div * $61;
+ $sub185 = $60 - $mul184;
+ $y188 = $36 + ($add130 << 4) + 8 | 0;
+ HEAPF64[$y188 >> 3] = $sub185;
+ $62 = HEAP32[$size93 >> 2] | 0;
+ $sub = $62 - 1 | 0;
+ $cmp116 = ($add133 | 0) < ($sub | 0);
+ if ($cmp116) {
+ $j_0214 = $add133;
+ label = 26;
+ break;
+ } else {
+ $j_0_lcssa = $add133;
+ label = 30;
+ break;
+ }
+ case 30:
+ $arrayidx192 = $34 + ($j_0_lcssa << 4) | 0;
+ _computeoffset_p($tmp193, $pf2, $pf3);
+ $63 = $arrayidx192;
+ HEAP32[$63 >> 2] = HEAP32[$23 >> 2] | 0;
+ HEAP32[$63 + 4 >> 2] = HEAP32[$23 + 4 >> 2] | 0;
+ HEAP32[$63 + 8 >> 2] = HEAP32[$23 + 8 >> 2] | 0;
+ HEAP32[$63 + 12 >> 2] = HEAP32[$23 + 12 >> 2] | 0;
+ $64 = +HEAPF64[$x194 >> 3];
+ $x196 = $arrayidx192 | 0;
+ $65 = +HEAPF64[$x196 >> 3];
+ $mul197 = $div * $65;
+ $sub198 = $64 - $mul197;
+ $x200 = $36 + ($j_0_lcssa << 4) | 0;
+ HEAPF64[$x200 >> 3] = $sub198;
+ $66 = +HEAPF64[$y201 >> 3];
+ $y203 = $34 + ($j_0_lcssa << 4) + 8 | 0;
+ $67 = +HEAPF64[$y203 >> 3];
+ $mul204 = $div * $67;
+ $sub205 = $66 - $mul204;
+ $y207 = $36 + ($j_0_lcssa << 4) + 8 | 0;
+ HEAPF64[$y207 >> 3] = $sub205;
+ $inc209 = $i_0217 + 1 | 0;
+ $cmp87 = ($inc209 | 0) < ($18 | 0);
+ if ($cmp87) {
+ $i_0217 = $inc209;
+ label = 25;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $call211 = _strdup($pencolor_0191193 | 0) | 0;
+ $call212 = _strtok($call211 | 0, 98688) | 0;
+ $tobool214203 = ($call212 | 0) == 0;
+ if ($tobool214203) {
+ $headcolor_0_lcssa = $pencolor_0191193;
+ $tailcolor_0_lcssa = $pencolor_0191193;
+ label = 41;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $cmp241201 = ($18 | 0) > 0;
+ $headcolor_0204 = $pencolor_0191193;
+ $tailcolor_0205 = $pencolor_0191193;
+ $lastcolor_0206 = $pencolor_0191193;
+ $color_1207 = $call212;
+ $cnum_0208 = 0;
+ label = 33;
+ break;
+ case 33:
+ $68 = HEAP8[$color_1207] | 0;
+ $tobool217 = $68 << 24 >> 24 == 0;
+ $_color_1 = $tobool217 ? 117856 : $color_1207;
+ $cmp220 = ($_color_1 | 0) == ($lastcolor_0206 | 0);
+ if ($cmp220) {
+ $lastcolor_1 = $lastcolor_0206;
+ label = 36;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $69 = HEAP8[$gui_state] | 0;
+ $and226 = $69 & 3;
+ $tobool227 = $and226 << 24 >> 24 == 0;
+ if ($tobool227) {
+ label = 35;
+ break;
+ } else {
+ $lastcolor_1 = $_color_1;
+ label = 36;
+ break;
+ }
+ case 35:
+ _gvrender_set_pencolor($job, $_color_1);
+ _gvrender_set_fillcolor($job, $_color_1);
+ $lastcolor_1 = $_color_1;
+ label = 36;
+ break;
+ case 36:
+ $cmp231 = ($cnum_0208 | 0) == 0;
+ $_color_1_headcolor_0 = $cmp231 ? $_color_1 : $headcolor_0204;
+ $_color_1_tailcolor_0 = $cmp231 ? $_color_1 : $tailcolor_0205;
+ $cmp235 = ($cnum_0208 | 0) == 1;
+ $tailcolor_2 = $cmp235 ? $_color_1 : $_color_1_tailcolor_0;
+ if ($cmp241201) {
+ $i_1202 = 0;
+ label = 37;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 37:
+ $list246 = $20 + ($i_1202 * 48 & -1) | 0;
+ $70 = HEAP32[$list246 >> 2] | 0;
+ $list249 = $19 + ($i_1202 * 48 & -1) | 0;
+ $71 = HEAP32[$list249 >> 2] | 0;
+ $size253 = $20 + ($i_1202 * 48 & -1) + 4 | 0;
+ $72 = HEAP32[$size253 >> 2] | 0;
+ $cmp254199 = ($72 | 0) > 0;
+ if ($cmp254199) {
+ $j_1200 = 0;
+ label = 38;
+ break;
+ } else {
+ $_lcssa = $72;
+ label = 39;
+ break;
+ }
+ case 38:
+ $x258 = $71 + ($j_1200 << 4) | 0;
+ $73 = +HEAPF64[$x258 >> 3];
+ $x260 = $70 + ($j_1200 << 4) | 0;
+ $74 = +HEAPF64[$x260 >> 3];
+ $add261 = $73 + $74;
+ HEAPF64[$x260 >> 3] = $add261;
+ $y263 = $71 + ($j_1200 << 4) + 8 | 0;
+ $75 = +HEAPF64[$y263 >> 3];
+ $y265 = $70 + ($j_1200 << 4) + 8 | 0;
+ $76 = +HEAPF64[$y265 >> 3];
+ $add266 = $75 + $76;
+ HEAPF64[$y265 >> 3] = $add266;
+ $inc268 = $j_1200 + 1 | 0;
+ $77 = HEAP32[$size253 >> 2] | 0;
+ $cmp254 = ($inc268 | 0) < ($77 | 0);
+ if ($cmp254) {
+ $j_1200 = $inc268;
+ label = 38;
+ break;
+ } else {
+ $_lcssa = $77;
+ label = 39;
+ break;
+ }
+ case 39:
+ _gvrender_beziercurve($job, $70, $_lcssa, 0, 0, 0);
+ $inc274 = $i_1202 + 1 | 0;
+ $cmp241 = ($inc274 | 0) < ($18 | 0);
+ if ($cmp241) {
+ $i_1202 = $inc274;
+ label = 37;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $inc277 = $cnum_0208 + 1 | 0;
+ $call278 = _strtok(0, 98688) | 0;
+ $tobool214 = ($call278 | 0) == 0;
+ if ($tobool214) {
+ $headcolor_0_lcssa = $_color_1_headcolor_0;
+ $tailcolor_0_lcssa = $tailcolor_2;
+ label = 41;
+ break;
+ } else {
+ $headcolor_0204 = $_color_1_headcolor_0;
+ $tailcolor_0205 = $tailcolor_2;
+ $lastcolor_0206 = $lastcolor_1;
+ $color_1207 = $call278;
+ $cnum_0208 = $inc277;
+ label = 33;
+ break;
+ }
+ case 41:
+ $sflag = $bz + 8 | 0;
+ $78 = HEAP32[$sflag >> 2] | 0;
+ $tobool280 = ($78 | 0) == 0;
+ if ($tobool280) {
+ $color_4 = 0;
+ label = 46;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $cmp282 = ($tailcolor_0_lcssa | 0) == 0;
+ if ($cmp282) {
+ $color_3 = 0;
+ label = 45;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $79 = HEAP8[$gui_state] | 0;
+ $and288 = $79 & 3;
+ $tobool289 = $and288 << 24 >> 24 == 0;
+ if ($tobool289) {
+ label = 44;
+ break;
+ } else {
+ $color_3 = $tailcolor_0_lcssa;
+ label = 45;
+ break;
+ }
+ case 44:
+ _gvrender_set_pencolor($job, $tailcolor_0_lcssa);
+ _gvrender_set_fillcolor($job, $tailcolor_0_lcssa);
+ $color_3 = $tailcolor_0_lcssa;
+ label = 45;
+ break;
+ case 45:
+ $sp = $bz + 16 | 0;
+ $list293 = $bz | 0;
+ $80 = HEAP32[$list293 >> 2] | 0;
+ $81 = HEAP32[$sflag >> 2] | 0;
+ _arrow_gen($job, 2, $sp, $80, $call2, $2, $81);
+ $color_4 = $color_3;
+ label = 46;
+ break;
+ case 46:
+ $eflag = $bz + 12 | 0;
+ $82 = HEAP32[$eflag >> 2] | 0;
+ $tobool297 = ($82 | 0) == 0;
+ if ($tobool297) {
+ label = 51;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $cmp299 = ($color_4 | 0) == ($headcolor_0_lcssa | 0);
+ if ($cmp299) {
+ label = 50;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $83 = HEAP8[$gui_state] | 0;
+ $and305 = $83 & 3;
+ $tobool306 = $and305 << 24 >> 24 == 0;
+ if ($tobool306) {
+ label = 49;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 49:
+ _gvrender_set_pencolor($job, $headcolor_0_lcssa);
+ _gvrender_set_fillcolor($job, $headcolor_0_lcssa);
+ label = 50;
+ break;
+ case 50:
+ $ep = $bz + 32 | 0;
+ $size310 = $bz + 4 | 0;
+ $84 = HEAP32[$size310 >> 2] | 0;
+ $sub311 = $84 - 1 | 0;
+ $list312 = $bz | 0;
+ $85 = HEAP32[$list312 >> 2] | 0;
+ $arrayidx313 = $85 + ($sub311 << 4) | 0;
+ $86 = HEAP32[$eflag >> 2] | 0;
+ _arrow_gen($job, 3, $ep, $arrayidx313, $call2, $2, $86);
+ label = 51;
+ break;
+ case 51:
+ _free($call211);
+ $cmp318197 = ($18 | 0) > 0;
+ if ($cmp318197) {
+ $i_2198 = 0;
+ label = 52;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 52:
+ $list323 = $19 + ($i_2198 * 48 & -1) | 0;
+ $87 = HEAP32[$list323 >> 2] | 0;
+ $88 = $87;
+ _free($88);
+ $list326 = $20 + ($i_2198 * 48 & -1) | 0;
+ $89 = HEAP32[$list326 >> 2] | 0;
+ $90 = $89;
+ _free($90);
+ $inc328 = $i_2198 + 1 | 0;
+ $cmp318 = ($inc328 | 0) < ($18 | 0);
+ if ($cmp318) {
+ $i_2198 = $inc328;
+ label = 52;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ _free($call78);
+ _free($call81);
+ label = 72;
+ break;
+ case 54:
+ $91 = HEAP8[$gui_state] | 0;
+ $and336 = $91 & 3;
+ $tobool337 = $and336 << 24 >> 24 == 0;
+ if ($tobool337) {
+ label = 55;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 55:
+ $92 = HEAP8[$pencolor_0191193] | 0;
+ $tobool340 = $92 << 24 >> 24 == 0;
+ if ($tobool340) {
+ label = 57;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 56:
+ _gvrender_set_pencolor($job, $pencolor_0191193);
+ _gvrender_set_fillcolor($job, $pencolor_0191193);
+ label = 58;
+ break;
+ case 57:
+ _gvrender_set_pencolor($job, 117856);
+ _gvrender_set_fillcolor($job, 117856);
+ label = 58;
+ break;
+ case 58:
+ $93 = HEAP32[$spl >> 2] | 0;
+ $size348194 = $93 + 4 | 0;
+ $94 = HEAP32[$size348194 >> 2] | 0;
+ $cmp349195 = ($94 | 0) > 0;
+ if ($cmp349195) {
+ label = 59;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 59:
+ $95 = $bz;
+ $flags = $job + 152 | 0;
+ $list359 = $bz | 0;
+ $size360 = $bz + 4 | 0;
+ $sflag366 = $bz + 8 | 0;
+ $eflag374 = $bz + 12 | 0;
+ $tobool395 = ($styles | 0) == 0;
+ $tobool395_old = ($styles | 0) == 0;
+ $ep377 = $bz + 32 | 0;
+ $sp369 = $bz + 16 | 0;
+ $sflag361 = $bz + 8 | 0;
+ $eflag362 = $bz + 12 | 0;
+ $i_3196 = 0;
+ $96 = $93;
+ label = 60;
+ break;
+ case 60:
+ $list354 = $96 | 0;
+ $97 = HEAP32[$list354 >> 2] | 0;
+ $arrayidx355 = $97 + ($i_3196 * 48 & -1) | 0;
+ $98 = $arrayidx355;
+ HEAP32[$95 >> 2] = HEAP32[$98 >> 2] | 0;
+ HEAP32[$95 + 4 >> 2] = HEAP32[$98 + 4 >> 2] | 0;
+ HEAP32[$95 + 8 >> 2] = HEAP32[$98 + 8 >> 2] | 0;
+ HEAP32[$95 + 12 >> 2] = HEAP32[$98 + 12 >> 2] | 0;
+ HEAP32[$95 + 16 >> 2] = HEAP32[$98 + 16 >> 2] | 0;
+ HEAP32[$95 + 20 >> 2] = HEAP32[$98 + 20 >> 2] | 0;
+ HEAP32[$95 + 24 >> 2] = HEAP32[$98 + 24 >> 2] | 0;
+ HEAP32[$95 + 28 >> 2] = HEAP32[$98 + 28 >> 2] | 0;
+ HEAP32[$95 + 32 >> 2] = HEAP32[$98 + 32 >> 2] | 0;
+ HEAP32[$95 + 36 >> 2] = HEAP32[$98 + 36 >> 2] | 0;
+ HEAP32[$95 + 40 >> 2] = HEAP32[$98 + 40 >> 2] | 0;
+ HEAP32[$95 + 44 >> 2] = HEAP32[$98 + 44 >> 2] | 0;
+ $99 = HEAP32[$flags >> 2] | 0;
+ $and356 = $99 & 16384;
+ $tobool357 = ($and356 | 0) == 0;
+ $100 = HEAP32[$list359 >> 2] | 0;
+ $101 = HEAP32[$size360 >> 2] | 0;
+ if ($tobool357) {
+ label = 62;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 61:
+ $102 = HEAP32[$sflag361 >> 2] | 0;
+ $103 = HEAP32[$eflag362 >> 2] | 0;
+ _gvrender_beziercurve($job, $100, $101, $102, $103, 0);
+ label = 71;
+ break;
+ case 62:
+ _gvrender_beziercurve($job, $100, $101, 0, 0, 0);
+ $104 = HEAP32[$sflag366 >> 2] | 0;
+ $tobool367 = ($104 | 0) == 0;
+ if ($tobool367) {
+ label = 64;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ $105 = HEAP32[$list359 >> 2] | 0;
+ _arrow_gen($job, 2, $sp369, $105, $call2, $2, $104);
+ label = 64;
+ break;
+ case 64:
+ $106 = HEAP32[$eflag374 >> 2] | 0;
+ $tobool375 = ($106 | 0) == 0;
+ if ($tobool375) {
+ label = 66;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $107 = HEAP32[$size360 >> 2] | 0;
+ $sub379 = $107 - 1 | 0;
+ $108 = HEAP32[$list359 >> 2] | 0;
+ $arrayidx381 = $108 + ($sub379 << 4) | 0;
+ _arrow_gen($job, 3, $ep377, $arrayidx381, $call2, $2, $106);
+ label = 66;
+ break;
+ case 66:
+ $109 = HEAP32[$spl >> 2] | 0;
+ $size386 = $109 + 4 | 0;
+ $110 = HEAP32[$size386 >> 2] | 0;
+ $cmp387 = ($110 | 0) > 1;
+ if ($cmp387) {
+ label = 67;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 67:
+ $111 = HEAP32[$sflag366 >> 2] | 0;
+ $tobool391 = ($111 | 0) == 0;
+ if ($tobool391) {
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 68:
+ $112 = HEAP32[$eflag374 >> 2] | 0;
+ $tobool393 = ($112 | 0) == 0;
+ $or_cond188 = $tobool393 | $tobool395;
+ if ($or_cond188) {
+ label = 71;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 69:
+ if ($tobool395_old) {
+ label = 71;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ _gvrender_set_style($job, $styles);
+ label = 71;
+ break;
+ case 71:
+ $inc400 = $i_3196 + 1 | 0;
+ $113 = HEAP32[$spl >> 2] | 0;
+ $size348 = $113 + 4 | 0;
+ $114 = HEAP32[$size348 >> 2] | 0;
+ $cmp349 = ($inc400 | 0) < ($114 | 0);
+ if ($cmp349) {
+ $i_3196 = $inc400;
+ $96 = $113;
+ label = 60;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 72:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_end_edge($job) {
+ $job = $job | 0;
+ var $p = 0, $bz_sroa_4 = 0, $obj1 = 0, $0 = 0, $u = 0, $e2 = 0, $1 = 0, $url = 0, $2 = 0, $tobool = 0, $3 = 0, $4 = 0, $5 = 0, $_mask = 0, $tobool3 = 0, $url_bsplinemap_poly_n = 0, $6 = 0, $tobool4 = 0, $url_bsplinemap_n = 0, $7 = 0, $cmp95 = 0, $8 = 0, $9 = 0, $url_map_n = 0, $url_bsplinemap_p = 0, $url_map_p = 0, $tooltip = 0, $target = 0, $id = 0, $nump_097 = 0, $i_096 = 0, $10 = 0, $arrayidx8 = 0, $11 = 0, $12 = 0, $arrayidx9 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $arrayidx12 = 0, $18 = 0, $add = 0, $inc = 0, $19 = 0, $cmp = 0, $url_map_n14 = 0, $url_map_p15 = 0, $spl = 0, $20 = 0, $tobool17 = 0, $list = 0, $21 = 0, $bz_sroa_0_0__idx2 = 0, $bz_sroa_0_0_copyload3 = 0, $bz_sroa_2_8__idx8 = 0, $bz_sroa_2_8_copyload9 = 0, $bz_sroa_4_16__idx13 = 0, $bz_sroa_4_16__cast14 = 0, $bz_sroa_4_16_cast15 = 0, $tobool22 = 0, $22 = 0, $23 = 0, $24 = 0, $25 = 0, $26 = 0, $27 = 0, $28 = 0, $bf_val_sext29 = 0, $conv = 0, $tailurl = 0, $29 = 0, $30 = 0, $31 = 0, $bf_val_sext32 = 0, $conv33 = 0, $32 = 0, $33 = 0, $bf_val_sext36 = 0, $conv37 = 0, $34 = 0, $size = 0, $35 = 0, $sub = 0, $list42 = 0, $36 = 0, $bz_sroa_0_0__idx = 0, $bz_sroa_0_0_copyload = 0, $bz_sroa_1_4__idx4 = 0, $bz_sroa_1_4_copyload = 0, $bz_sroa_3_12__idx10 = 0, $bz_sroa_3_12_copyload = 0, $bz_sroa_4_16__idx = 0, $bz_sroa_4_16__cast = 0, $tobool44 = 0, $bz_sroa_4_32_idx = 0, $bz_sroa_4_32_cast = 0, $sub48 = 0, $arrayidx50 = 0, $37 = 0, $38 = 0, $39 = 0, $40 = 0, $bf_val_sext54 = 0, $conv55 = 0, $headurl = 0, $41 = 0, $42 = 0, $43 = 0, $bf_val_sext58 = 0, $conv59 = 0, $44 = 0, $45 = 0, $bf_val_sext62 = 0, $conv63 = 0, $label = 0, $46 = 0, $47 = 0, $48 = 0, $49 = 0, $50 = 0, $51 = 0, $bf_val_sext68 = 0, $labelurl = 0, $52 = 0, $labeltooltip = 0, $53 = 0, $labeltarget = 0, $54 = 0, $id69 = 0, $55 = 0, $56 = 0, $57 = 0, $call = 0, $call70 = 0, $tobool72 = 0, $58 = 0, $cond = 0, $xlabel = 0, $59 = 0, $60 = 0, $61 = 0, $62 = 0, $bf_val_sext81 = 0, $63 = 0, $64 = 0, $65 = 0, $66 = 0, $67 = 0, $call86 = 0, $call87 = 0, $tobool89 = 0, $68 = 0, $cond99 = 0, $head_label = 0, $69 = 0, $70 = 0, $71 = 0, $72 = 0, $bf_val_sext103 = 0, $headurl104 = 0, $73 = 0, $headtooltip105 = 0, $74 = 0, $headtarget106 = 0, $75 = 0, $76 = 0, $tail_label = 0, $77 = 0, $78 = 0, $79 = 0, $80 = 0, $bf_val_sext111 = 0, $tailurl112 = 0, $81 = 0, $tailtooltip113 = 0, $82 = 0, $tailtarget114 = 0, $83 = 0, $84 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p = __stackBase__ | 0;
+ $bz_sroa_4 = __stackBase__ + 16 | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $u = $0 + 8 | 0;
+ $e2 = $u;
+ $1 = HEAP32[$e2 >> 2] | 0;
+ $url = $0 + 160 | 0;
+ $2 = HEAP32[$url >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $3 = $0 + 212 | 0;
+ $4 = $3;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $_mask = $5 & 1;
+ $tobool3 = ($_mask | 0) == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _gvrender_end_anchor($job);
+ $url_bsplinemap_poly_n = $0 + 228 | 0;
+ $6 = HEAP32[$url_bsplinemap_poly_n >> 2] | 0;
+ $tobool4 = ($6 | 0) == 0;
+ if ($tobool4) {
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $url_bsplinemap_n = $0 + 232 | 0;
+ $7 = HEAP32[$url_bsplinemap_poly_n >> 2] | 0;
+ $cmp95 = ($7 | 0) > 1;
+ if ($cmp95) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $8 = HEAP32[$url_bsplinemap_n >> 2] | 0;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $url_map_n = $0 + 220 | 0;
+ $url_bsplinemap_p = $0 + 236 | 0;
+ $url_map_p = $0 + 224 | 0;
+ $tooltip = $0 + 180 | 0;
+ $target = $0 + 196 | 0;
+ $id = $0 + 164 | 0;
+ $i_096 = 1;
+ $nump_097 = $9;
+ label = 7;
+ break;
+ case 7:
+ $10 = HEAP32[$url_bsplinemap_n >> 2] | 0;
+ $arrayidx8 = $10 + ($i_096 << 2) | 0;
+ $11 = HEAP32[$arrayidx8 >> 2] | 0;
+ HEAP32[$url_map_n >> 2] = $11;
+ $12 = HEAP32[$url_bsplinemap_p >> 2] | 0;
+ $arrayidx9 = $12 + ($nump_097 << 4) | 0;
+ HEAP32[$url_map_p >> 2] = $arrayidx9;
+ $13 = HEAP32[$url >> 2] | 0;
+ $14 = HEAP32[$tooltip >> 2] | 0;
+ $15 = HEAP32[$target >> 2] | 0;
+ $16 = HEAP32[$id >> 2] | 0;
+ _gvrender_begin_anchor($job, $13, $14, $15, $16);
+ _gvrender_end_anchor($job);
+ $17 = HEAP32[$url_bsplinemap_n >> 2] | 0;
+ $arrayidx12 = $17 + ($i_096 << 2) | 0;
+ $18 = HEAP32[$arrayidx12 >> 2] | 0;
+ $add = $18 + $nump_097 | 0;
+ $inc = $i_096 + 1 | 0;
+ $19 = HEAP32[$url_bsplinemap_poly_n >> 2] | 0;
+ $cmp = ($inc | 0) < ($19 | 0);
+ if ($cmp) {
+ $i_096 = $inc;
+ $nump_097 = $add;
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $url_map_n14 = $0 + 220 | 0;
+ HEAP32[$url_map_n14 >> 2] = 0;
+ $url_map_p15 = $0 + 224 | 0;
+ HEAP32[$url_map_p15 >> 2] = 0;
+ $spl = $1 + 24 | 0;
+ $20 = HEAP32[$spl >> 2] | 0;
+ $tobool17 = ($20 | 0) == 0;
+ if ($tobool17) {
+ label = 16;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $list = $20 | 0;
+ $21 = HEAP32[$list >> 2] | 0;
+ $bz_sroa_0_0__idx2 = $21 | 0;
+ $bz_sroa_0_0_copyload3 = HEAP32[$bz_sroa_0_0__idx2 >> 2] | 0;
+ $bz_sroa_2_8__idx8 = $21 + 8 | 0;
+ $bz_sroa_2_8_copyload9 = HEAP32[$bz_sroa_2_8__idx8 >> 2] | 0;
+ $bz_sroa_4_16__idx13 = $21 + 16 | 0;
+ $bz_sroa_4_16__cast14 = $bz_sroa_4_16__idx13;
+ $bz_sroa_4_16_cast15 = $bz_sroa_4;
+ HEAP32[$bz_sroa_4_16_cast15 >> 2] = HEAP32[$bz_sroa_4_16__cast14 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 4 >> 2] = HEAP32[$bz_sroa_4_16__cast14 + 4 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 8 >> 2] = HEAP32[$bz_sroa_4_16__cast14 + 8 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 12 >> 2] = HEAP32[$bz_sroa_4_16__cast14 + 12 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 16 >> 2] = HEAP32[$bz_sroa_4_16__cast14 + 16 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 20 >> 2] = HEAP32[$bz_sroa_4_16__cast14 + 20 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 24 >> 2] = HEAP32[$bz_sroa_4_16__cast14 + 24 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 28 >> 2] = HEAP32[$bz_sroa_4_16__cast14 + 28 >> 2] | 0;
+ $tobool22 = ($bz_sroa_2_8_copyload9 | 0) == 0;
+ $22 = $p;
+ if ($tobool22) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ HEAP32[$22 >> 2] = HEAP32[$bz_sroa_4_16_cast15 >> 2] | 0;
+ HEAP32[$22 + 4 >> 2] = HEAP32[$bz_sroa_4_16_cast15 + 4 >> 2] | 0;
+ HEAP32[$22 + 8 >> 2] = HEAP32[$bz_sroa_4_16_cast15 + 8 >> 2] | 0;
+ HEAP32[$22 + 12 >> 2] = HEAP32[$bz_sroa_4_16_cast15 + 12 >> 2] | 0;
+ label = 12;
+ break;
+ case 11:
+ $23 = $bz_sroa_0_0_copyload3;
+ HEAP32[$22 >> 2] = HEAP32[$23 >> 2] | 0;
+ HEAP32[$22 + 4 >> 2] = HEAP32[$23 + 4 >> 2] | 0;
+ HEAP32[$22 + 8 >> 2] = HEAP32[$23 + 8 >> 2] | 0;
+ HEAP32[$22 + 12 >> 2] = HEAP32[$23 + 12 >> 2] | 0;
+ label = 12;
+ break;
+ case 12:
+ $24 = $0 + 212 | 0;
+ $25 = $24;
+ $26 = HEAP32[$25 >> 2] | 0;
+ $27 = $26 >>> 7;
+ $28 = $27 << 31;
+ $bf_val_sext29 = $28 >> 31;
+ $conv = $bf_val_sext29 & 255;
+ $tailurl = $0 + 172 | 0;
+ $29 = HEAP32[$tailurl >> 2] | 0;
+ $30 = $26 >>> 1;
+ $31 = $30 << 31;
+ $bf_val_sext32 = $31 >> 31;
+ $conv33 = $bf_val_sext32 & 255;
+ $32 = $26 >>> 4;
+ $33 = $32 << 31;
+ $bf_val_sext36 = $33 >> 31;
+ $conv37 = $bf_val_sext36 & 255;
+ _nodeIntersect($job, $p, $conv, $29, $conv33, $conv37);
+ $34 = HEAP32[$spl >> 2] | 0;
+ $size = $34 + 4 | 0;
+ $35 = HEAP32[$size >> 2] | 0;
+ $sub = $35 - 1 | 0;
+ $list42 = $34 | 0;
+ $36 = HEAP32[$list42 >> 2] | 0;
+ $bz_sroa_0_0__idx = $36 + ($sub * 48 & -1) | 0;
+ $bz_sroa_0_0_copyload = HEAP32[$bz_sroa_0_0__idx >> 2] | 0;
+ $bz_sroa_1_4__idx4 = $36 + ($sub * 48 & -1) + 4 | 0;
+ $bz_sroa_1_4_copyload = HEAP32[$bz_sroa_1_4__idx4 >> 2] | 0;
+ $bz_sroa_3_12__idx10 = $36 + ($sub * 48 & -1) + 12 | 0;
+ $bz_sroa_3_12_copyload = HEAP32[$bz_sroa_3_12__idx10 >> 2] | 0;
+ $bz_sroa_4_16__idx = $36 + ($sub * 48 & -1) + 16 | 0;
+ $bz_sroa_4_16__cast = $bz_sroa_4_16__idx;
+ HEAP32[$bz_sroa_4_16_cast15 >> 2] = HEAP32[$bz_sroa_4_16__cast >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 4 >> 2] = HEAP32[$bz_sroa_4_16__cast + 4 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 8 >> 2] = HEAP32[$bz_sroa_4_16__cast + 8 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 12 >> 2] = HEAP32[$bz_sroa_4_16__cast + 12 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 16 >> 2] = HEAP32[$bz_sroa_4_16__cast + 16 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 20 >> 2] = HEAP32[$bz_sroa_4_16__cast + 20 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 24 >> 2] = HEAP32[$bz_sroa_4_16__cast + 24 >> 2] | 0;
+ HEAP32[$bz_sroa_4_16_cast15 + 28 >> 2] = HEAP32[$bz_sroa_4_16__cast + 28 >> 2] | 0;
+ $tobool44 = ($bz_sroa_3_12_copyload | 0) == 0;
+ if ($tobool44) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $bz_sroa_4_32_idx = $bz_sroa_4 + 16 | 0;
+ $bz_sroa_4_32_cast = $bz_sroa_4_32_idx;
+ HEAP32[$22 >> 2] = HEAP32[$bz_sroa_4_32_cast >> 2] | 0;
+ HEAP32[$22 + 4 >> 2] = HEAP32[$bz_sroa_4_32_cast + 4 >> 2] | 0;
+ HEAP32[$22 + 8 >> 2] = HEAP32[$bz_sroa_4_32_cast + 8 >> 2] | 0;
+ HEAP32[$22 + 12 >> 2] = HEAP32[$bz_sroa_4_32_cast + 12 >> 2] | 0;
+ label = 15;
+ break;
+ case 14:
+ $sub48 = $bz_sroa_1_4_copyload - 1 | 0;
+ $arrayidx50 = $bz_sroa_0_0_copyload + ($sub48 << 4) | 0;
+ $37 = $arrayidx50;
+ HEAP32[$22 >> 2] = HEAP32[$37 >> 2] | 0;
+ HEAP32[$22 + 4 >> 2] = HEAP32[$37 + 4 >> 2] | 0;
+ HEAP32[$22 + 8 >> 2] = HEAP32[$37 + 8 >> 2] | 0;
+ HEAP32[$22 + 12 >> 2] = HEAP32[$37 + 12 >> 2] | 0;
+ label = 15;
+ break;
+ case 15:
+ $38 = HEAP32[$25 >> 2] | 0;
+ $39 = $38 >>> 8;
+ $40 = $39 << 31;
+ $bf_val_sext54 = $40 >> 31;
+ $conv55 = $bf_val_sext54 & 255;
+ $headurl = $0 + 176 | 0;
+ $41 = HEAP32[$headurl >> 2] | 0;
+ $42 = $38 >>> 2;
+ $43 = $42 << 31;
+ $bf_val_sext58 = $43 >> 31;
+ $conv59 = $bf_val_sext58 & 255;
+ $44 = $38 >>> 5;
+ $45 = $44 << 31;
+ $bf_val_sext62 = $45 >> 31;
+ $conv63 = $bf_val_sext62 & 255;
+ _nodeIntersect($job, $p, $conv55, $41, $conv59, $conv63);
+ label = 16;
+ break;
+ case 16:
+ $label = $1 + 112 | 0;
+ $46 = HEAP32[$label >> 2] | 0;
+ $47 = $0 + 212 | 0;
+ $48 = $47;
+ $49 = HEAP32[$48 >> 2] | 0;
+ $50 = $49 >>> 3;
+ $51 = $50 << 31;
+ $bf_val_sext68 = $51 >> 31;
+ $labelurl = $0 + 168 | 0;
+ $52 = HEAP32[$labelurl >> 2] | 0;
+ $labeltooltip = $0 + 184 | 0;
+ $53 = HEAP32[$labeltooltip >> 2] | 0;
+ $labeltarget = $0 + 200 | 0;
+ $54 = HEAP32[$labeltarget >> 2] | 0;
+ $id69 = $0 + 164 | 0;
+ $55 = HEAP32[$id69 >> 2] | 0;
+ $56 = $1 | 0;
+ $57 = HEAP32[41952] | 0;
+ $call = _late_string($56, $57, 101168) | 0;
+ $call70 = _mapbool($call) | 0;
+ $tobool72 = $call70 << 24 >> 24 == 0;
+ if ($tobool72) {
+ $cond = 0;
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $58 = HEAP32[$spl >> 2] | 0;
+ $cond = $58;
+ label = 18;
+ break;
+ case 18:
+ _emit_edge_label($job, $46, 11, $bf_val_sext68, $52, $53, $54, $55, $cond);
+ $xlabel = $1 + 124 | 0;
+ $59 = HEAP32[$xlabel >> 2] | 0;
+ $60 = HEAP32[$48 >> 2] | 0;
+ $61 = $60 >>> 3;
+ $62 = $61 << 31;
+ $bf_val_sext81 = $62 >> 31;
+ $63 = HEAP32[$labelurl >> 2] | 0;
+ $64 = HEAP32[$labeltooltip >> 2] | 0;
+ $65 = HEAP32[$labeltarget >> 2] | 0;
+ $66 = HEAP32[$id69 >> 2] | 0;
+ $67 = HEAP32[41952] | 0;
+ $call86 = _late_string($56, $67, 101168) | 0;
+ $call87 = _mapbool($call86) | 0;
+ $tobool89 = $call87 << 24 >> 24 == 0;
+ if ($tobool89) {
+ $cond99 = 0;
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $68 = HEAP32[$spl >> 2] | 0;
+ $cond99 = $68;
+ label = 20;
+ break;
+ case 20:
+ _emit_edge_label($job, $59, 11, $bf_val_sext81, $63, $64, $65, $66, $cond99);
+ $head_label = $1 + 116 | 0;
+ $69 = HEAP32[$head_label >> 2] | 0;
+ $70 = HEAP32[$48 >> 2] | 0;
+ $71 = $70 >>> 2;
+ $72 = $71 << 31;
+ $bf_val_sext103 = $72 >> 31;
+ $headurl104 = $0 + 176 | 0;
+ $73 = HEAP32[$headurl104 >> 2] | 0;
+ $headtooltip105 = $0 + 192 | 0;
+ $74 = HEAP32[$headtooltip105 >> 2] | 0;
+ $headtarget106 = $0 + 208 | 0;
+ $75 = HEAP32[$headtarget106 >> 2] | 0;
+ $76 = HEAP32[$id69 >> 2] | 0;
+ _emit_edge_label($job, $69, 7, $bf_val_sext103, $73, $74, $75, $76, 0);
+ $tail_label = $1 + 120 | 0;
+ $77 = HEAP32[$tail_label >> 2] | 0;
+ $78 = HEAP32[$48 >> 2] | 0;
+ $79 = $78 >>> 1;
+ $80 = $79 << 31;
+ $bf_val_sext111 = $80 >> 31;
+ $tailurl112 = $0 + 172 | 0;
+ $81 = HEAP32[$tailurl112 >> 2] | 0;
+ $tailtooltip113 = $0 + 188 | 0;
+ $82 = HEAP32[$tailtooltip113 >> 2] | 0;
+ $tailtarget114 = $0 + 204 | 0;
+ $83 = HEAP32[$tailtarget114 >> 2] | 0;
+ $84 = HEAP32[$id69 >> 2] | 0;
+ _emit_edge_label($job, $77, 6, $bf_val_sext111, $81, $82, $83, $84, 0);
+ _gvrender_end_edge($job);
+ _pop_obj_state($job);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _nodeIntersect($job, $p, $explicit_iurl, $iurl, $explicit_itooltip, $explicit_itarget) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $explicit_iurl = $explicit_iurl | 0;
+ $iurl = $iurl | 0;
+ $explicit_itooltip = $explicit_itooltip | 0;
+ $explicit_itarget = $explicit_itarget | 0;
+ var $obj1 = 0, $0 = 0, $tobool = 0, $url2 = 0, $1 = 0, $url_0 = 0, $tobool3 = 0, $2 = 0, $3 = 0, $4 = 0, $_mask = 0, $tobool24 = 0, $tobool25 = 0, $or_cond = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $tobool = $explicit_iurl << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $url_0 = $iurl;
+ label = 4;
+ break;
+ }
+ case 3:
+ $url2 = $0 + 160 | 0;
+ $1 = HEAP32[$url2 >> 2] | 0;
+ $url_0 = $1;
+ label = 4;
+ break;
+ case 4:
+ $tobool3 = $explicit_itooltip << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $2 = $0 + 212 | 0;
+ $3 = $2;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $_mask = $4 & 1;
+ $tobool24 = ($url_0 | 0) == 0;
+ $tobool25 = ($_mask | 0) == 0;
+ $or_cond = $tobool24 & $tobool25;
+ if ($or_cond) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _map_point($job, $p);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pointfof($agg_result, $x, $y) {
+ $agg_result = $agg_result | 0;
+ $x = +$x;
+ $y = +$y;
+ HEAPF64[$agg_result >> 3] = $x;
+ HEAPF64[$agg_result + 8 >> 3] = $y;
+ return;
+}
+function _map_label($job, $lab) {
+ $job = $job | 0;
+ $lab = $lab | 0;
+ var $obj1 = 0, $0 = 0, $flags2 = 0, $1 = 0, $and = 0, $tobool = 0, $and3 = 0, $tobool4 = 0, $url_map_shape = 0, $url_map_n = 0, $url_map_n7 = 0, $url_map_p = 0, $2 = 0, $3 = 0, $url_map_n8 = 0, $4 = 0, $mul = 0, $call = 0, $5 = 0, $x = 0, $6 = 0.0, $x10 = 0, $7 = 0.0, $div = 0.0, $sub = 0.0, $x11 = 0, $y = 0, $8 = 0.0, $y14 = 0, $9 = 0.0, $div15 = 0.0, $sub16 = 0.0, $y18 = 0, $10 = 0, $11 = 0.0, $12 = 0.0, $div23 = 0.0, $add = 0.0, $arrayidx24 = 0, $x25 = 0, $13 = 0.0, $14 = 0.0, $div30 = 0.0, $add31 = 0.0, $y33 = 0, $15 = 0, $and34 = 0, $tobool35 = 0, $call37 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $flags2 = $job + 152 | 0;
+ $1 = HEAP32[$flags2 >> 2] | 0;
+ $and = $1 & 4259840;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $and3 = $1 & 131072;
+ $tobool4 = ($and3 | 0) != 0;
+ $url_map_shape = $0 + 216 | 0;
+ if ($tobool4) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP32[$url_map_shape >> 2] = 0;
+ $url_map_n = $0 + 220 | 0;
+ HEAP32[$url_map_n >> 2] = 2;
+ label = 6;
+ break;
+ case 5:
+ HEAP32[$url_map_shape >> 2] = 2;
+ $url_map_n7 = $0 + 220 | 0;
+ HEAP32[$url_map_n7 >> 2] = 4;
+ label = 6;
+ break;
+ case 6:
+ $url_map_p = $0 + 224 | 0;
+ $2 = HEAP32[$url_map_p >> 2] | 0;
+ $3 = $2;
+ _free($3);
+ $url_map_n8 = $0 + 220 | 0;
+ $4 = HEAP32[$url_map_n8 >> 2] | 0;
+ $mul = $4 << 4;
+ $call = _zmalloc($mul) | 0;
+ $5 = $call;
+ HEAP32[$url_map_p >> 2] = $5;
+ $x = $lab + 56 | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $x10 = $lab + 24 | 0;
+ $7 = +HEAPF64[$x10 >> 3];
+ $div = $7 * .5;
+ $sub = $6 - $div;
+ $x11 = $call;
+ HEAPF64[$x11 >> 3] = $sub;
+ $y = $lab + 64 | 0;
+ $8 = +HEAPF64[$y >> 3];
+ $y14 = $lab + 32 | 0;
+ $9 = +HEAPF64[$y14 >> 3];
+ $div15 = $9 * .5;
+ $sub16 = $8 - $div15;
+ $y18 = $call + 8 | 0;
+ $10 = $y18;
+ HEAPF64[$10 >> 3] = $sub16;
+ $11 = +HEAPF64[$x >> 3];
+ $12 = +HEAPF64[$x10 >> 3];
+ $div23 = $12 * .5;
+ $add = $11 + $div23;
+ $arrayidx24 = $call + 16 | 0;
+ $x25 = $arrayidx24;
+ HEAPF64[$x25 >> 3] = $add;
+ $13 = +HEAPF64[$y >> 3];
+ $14 = +HEAPF64[$y14 >> 3];
+ $div30 = $14 * .5;
+ $add31 = $13 + $div30;
+ $y33 = $call + 24 | 0;
+ $15 = $y33;
+ HEAPF64[$15 >> 3] = $add31;
+ $and34 = $1 & 8192;
+ $tobool35 = ($and34 | 0) == 0;
+ if ($tobool35) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call37 = _gvrender_ptf_A($job, $5, $5, 2) | 0;
+ label = 8;
+ break;
+ case 8:
+ if ($tobool4) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ _rect2poly($5);
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _emit_attachment($job, $lp, $spl) {
+ $job = $job | 0;
+ $lp = $lp | 0;
+ $spl = $spl | 0;
+ var $AF = 0, $tmp18 = 0, $tmp21 = 0, $text = 0, $0 = 0, $s_0 = 0, $1 = 0, $tobool = 0, $conv = 0, $call = 0, $cmp = 0, $incdec_ptr = 0, $_pr = 0, $cmp3 = 0, $sz_sroa_0_0__idx = 0, $sz_sroa_0_0_copyload = 0.0, $sz_sroa_1_8__idx5 = 0, $sz_sroa_1_8_copyload = 0.0, $arrayidx = 0, $pos = 0, $x = 0, $2 = 0.0, $div = 0.0, $add = 0.0, $y = 0, $3 = 0.0, $div10 = 0.0, $sub = 0.0, $AF17 = 0, $arrayidx11 = 0, $x13 = 0, $4 = 0.0, $sub15 = 0.0, $y17 = 0, $5 = 0.0, $6 = 0, $7 = 0, $arrayidx19 = 0, $8 = 0, $9 = 0, $gvc = 0, $10 = 0, $defaultlinestyle = 0, $11 = 0, $fontcolor = 0, $12 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 80 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $AF = __stackBase__ | 0;
+ $tmp18 = __stackBase__ + 48 | 0;
+ $tmp21 = __stackBase__ + 64 | 0;
+ $text = $lp | 0;
+ $0 = HEAP32[$text >> 2] | 0;
+ $s_0 = $0;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP8[$s_0] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = $1 & 255;
+ $call = _isspace($conv | 0) | 0;
+ $cmp = ($call | 0) == 0;
+ $incdec_ptr = $s_0 + 1 | 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $s_0 = $incdec_ptr;
+ label = 3;
+ break;
+ }
+ case 5:
+ $_pr = HEAP8[$s_0] | 0;
+ $cmp3 = $_pr << 24 >> 24 == 0;
+ if ($cmp3) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $sz_sroa_0_0__idx = $lp + 24 | 0;
+ $sz_sroa_0_0_copyload = +HEAPF64[$sz_sroa_0_0__idx >> 3];
+ $sz_sroa_1_8__idx5 = $lp + 32 | 0;
+ $sz_sroa_1_8_copyload = +HEAPF64[$sz_sroa_1_8__idx5 >> 3];
+ $arrayidx = $AF | 0;
+ $pos = $lp + 56 | 0;
+ $x = $pos | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $div = $sz_sroa_0_0_copyload * .5;
+ $add = $div + $2;
+ $y = $lp + 64 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $div10 = $sz_sroa_1_8_copyload * .5;
+ $sub = $3 - $div10;
+ $AF17 = $AF | 0;
+ _pointfof($AF17, $add, $sub);
+ $arrayidx11 = $AF + 16 | 0;
+ $x13 = $AF | 0;
+ $4 = +HEAPF64[$x13 >> 3];
+ $sub15 = $4 - $sz_sroa_0_0_copyload;
+ $y17 = $AF + 8 | 0;
+ $5 = +HEAPF64[$y17 >> 3];
+ _pointfof($tmp18, $sub15, $5);
+ $6 = $arrayidx11;
+ $7 = $tmp18;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $arrayidx19 = $AF + 32 | 0;
+ _dotneato_closest($tmp21, $spl, $pos);
+ $8 = $arrayidx19;
+ $9 = $tmp21;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $gvc = $job | 0;
+ $10 = HEAP32[$gvc >> 2] | 0;
+ $defaultlinestyle = $10 + 304 | 0;
+ $11 = HEAP32[$defaultlinestyle >> 2] | 0;
+ _gvrender_set_style($job, $11);
+ $fontcolor = $lp + 8 | 0;
+ $12 = HEAP32[$fontcolor >> 2] | 0;
+ _gvrender_set_pencolor($job, $12);
+ _gvrender_polyline($job, $arrayidx, 3);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _map_point($job, $pf) {
+ $job = $job | 0;
+ $pf = $pf | 0;
+ var $obj1 = 0, $0 = 0, $flags2 = 0, $1 = 0, $and = 0, $tobool = 0, $and3 = 0, $tobool4 = 0, $url_map_shape = 0, $url_map_n = 0, $url_map_n7 = 0, $url_map_p = 0, $2 = 0, $3 = 0, $url_map_n8 = 0, $4 = 0, $mul = 0, $call = 0, $5 = 0, $x = 0, $6 = 0.0, $sub = 0.0, $x10 = 0, $y = 0, $7 = 0.0, $sub11 = 0.0, $y13 = 0, $8 = 0, $9 = 0.0, $add = 0.0, $arrayidx15 = 0, $x16 = 0, $10 = 0.0, $add18 = 0.0, $y20 = 0, $11 = 0, $and21 = 0, $tobool22 = 0, $call24 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $pf;
+ $pf = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pf >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pf + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pf + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pf + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $flags2 = $job + 152 | 0;
+ $1 = HEAP32[$flags2 >> 2] | 0;
+ $and = $1 & 4259840;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $and3 = $1 & 131072;
+ $tobool4 = ($and3 | 0) != 0;
+ $url_map_shape = $0 + 216 | 0;
+ if ($tobool4) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP32[$url_map_shape >> 2] = 0;
+ $url_map_n = $0 + 220 | 0;
+ HEAP32[$url_map_n >> 2] = 2;
+ label = 6;
+ break;
+ case 5:
+ HEAP32[$url_map_shape >> 2] = 2;
+ $url_map_n7 = $0 + 220 | 0;
+ HEAP32[$url_map_n7 >> 2] = 4;
+ label = 6;
+ break;
+ case 6:
+ $url_map_p = $0 + 224 | 0;
+ $2 = HEAP32[$url_map_p >> 2] | 0;
+ $3 = $2;
+ _free($3);
+ $url_map_n8 = $0 + 220 | 0;
+ $4 = HEAP32[$url_map_n8 >> 2] | 0;
+ $mul = $4 << 4;
+ $call = _zmalloc($mul) | 0;
+ $5 = $call;
+ HEAP32[$url_map_p >> 2] = $5;
+ $x = $pf | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $sub = $6 + -3.0;
+ $x10 = $call;
+ HEAPF64[$x10 >> 3] = $sub;
+ $y = $pf + 8 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $sub11 = $7 + -3.0;
+ $y13 = $call + 8 | 0;
+ $8 = $y13;
+ HEAPF64[$8 >> 3] = $sub11;
+ $9 = +HEAPF64[$x >> 3];
+ $add = $9 + 3.0;
+ $arrayidx15 = $call + 16 | 0;
+ $x16 = $arrayidx15;
+ HEAPF64[$x16 >> 3] = $add;
+ $10 = +HEAPF64[$y >> 3];
+ $add18 = $10 + 3.0;
+ $y20 = $call + 24 | 0;
+ $11 = $y20;
+ HEAPF64[$11 >> 3] = $add18;
+ $and21 = $1 & 8192;
+ $tobool22 = ($and21 | 0) == 0;
+ if ($tobool22) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call24 = _gvrender_ptf_A($job, $5, $5, 2) | 0;
+ label = 8;
+ break;
+ case 8:
+ if ($tobool4) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ _rect2poly($5);
+ label = 10;
+ break;
+ case 10:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _multicolor($job, $e, $styles, $colors, $num, $arrowsize, $penwidth) {
+ $job = $job | 0;
+ $e = $e | 0;
+ $styles = $styles | 0;
+ $colors = $colors | 0;
+ $num = $num | 0;
+ $arrowsize = +$arrowsize;
+ $penwidth = +$penwidth;
+ var $bz = 0, $bz0 = 0, $bz_l = 0, $bz_r = 0, $segs = 0, $call = 0, $cmp = 0, $tail = 0, $0 = 0, $graph = 0, $1 = 0, $name = 0, $2 = 0, $3 = 0, $4 = 0, $and = 0, $tobool = 0, $cond = 0, $head = 0, $5 = 0, $name2 = 0, $6 = 0, $call3 = 0, $cmp4 = 0, $cmp6 = 0, $spl = 0, $7 = 0, $size36 = 0, $8 = 0, $cmp1037 = 0, $9 = 0, $sflag = 0, $eflag = 0, $tobool68 = 0, $tobool68_old = 0, $ep = 0, $size53 = 0, $list54 = 0, $sp = 0, $list47 = 0, $list21 = 0, $size22 = 0, $10 = 0, $11 = 0, $list30 = 0, $list31 = 0, $size32 = 0, $list36 = 0, $size37 = 0, $12 = 0, $endcolor_039 = 0, $i_038 = 0, $list = 0, $13 = 0, $arrayidx = 0, $14 = 0, $15 = 0, $segs13 = 0, $16 = 0, $color31 = 0, $17 = 0, $tobool1532 = 0, $18 = 0, $color35 = 0, $endcolor_134 = 0, $indvars = 0, $19 = 0, $segs18 = 0, $20 = 0, $cmp19 = 0, $t = 0, $21 = 0, $22 = 0.0, $23 = 0, $24 = 0, $25 = 0, $26 = 0, $cmp26 = 0, $27 = 0.0, $28 = 0, $29 = 0, $30 = 0, $31 = 0, $32 = 0, $33 = 0, $34 = 0, $35 = 0, $36 = 0, $37 = 0, $38 = 0, $endcolor_2 = 0, $incdec_ptr = 0, $39 = 0, $tobool15 = 0, $endcolor_1_lcssa = 0, $40 = 0, $tobool41 = 0, $41 = 0, $segs43 = 0, $42 = 0, $color44 = 0, $43 = 0, $44 = 0, $segs45 = 0, $45 = 0, $color46 = 0, $46 = 0, $47 = 0, $48 = 0, $49 = 0, $tobool51 = 0, $50 = 0, $sub = 0, $51 = 0, $arrayidx55 = 0, $52 = 0, $53 = 0, $size60 = 0, $54 = 0, $cmp61 = 0, $55 = 0, $tobool64 = 0, $56 = 0, $tobool66 = 0, $or_cond = 0, $inc = 0, $57 = 0, $size = 0, $58 = 0, $cmp10 = 0, $59 = 0, $60 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 200 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $bz = __stackBase__ | 0;
+ $bz0 = __stackBase__ + 48 | 0;
+ $bz_l = __stackBase__ + 96 | 0;
+ $bz_r = __stackBase__ + 144 | 0;
+ $segs = __stackBase__ + 192 | 0;
+ $call = _parseSegs($colors, $num, $segs) | 0;
+ $cmp = ($call | 0) > 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $name = $0 + 12 | 0;
+ $2 = HEAP32[$name >> 2] | 0;
+ $3 = $1;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $and = $4 & 16;
+ $tobool = ($and | 0) != 0;
+ $cond = $tobool ? 97952 : 97448;
+ $head = $e + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $name2 = $5 + 12 | 0;
+ $6 = HEAP32[$name2 >> 2] | 0;
+ $call3 = _agerr(3, 98296, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $2, HEAP32[tempInt + 8 >> 2] = $cond, HEAP32[tempInt + 16 >> 2] = $6, tempInt) | 0) | 0;
+ $cmp4 = ($call | 0) == 2;
+ if ($cmp4) {
+ $retval_0 = 1;
+ label = 25;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $cmp6 = ($call | 0) == 1;
+ if ($cmp6) {
+ $retval_0 = 1;
+ label = 25;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $spl = $e + 24 | 0;
+ $7 = HEAP32[$spl >> 2] | 0;
+ $size36 = $7 + 4 | 0;
+ $8 = HEAP32[$size36 >> 2] | 0;
+ $cmp1037 = ($8 | 0) > 0;
+ if ($cmp1037) {
+ label = 6;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 6:
+ $9 = $bz;
+ $sflag = $bz + 8 | 0;
+ $eflag = $bz + 12 | 0;
+ $tobool68 = ($styles | 0) == 0;
+ $tobool68_old = ($styles | 0) == 0;
+ $ep = $bz + 32 | 0;
+ $size53 = $bz + 4 | 0;
+ $list54 = $bz | 0;
+ $sp = $bz + 16 | 0;
+ $list47 = $bz | 0;
+ $list21 = $bz_l | 0;
+ $size22 = $bz_l + 4 | 0;
+ $10 = $bz0;
+ $11 = $bz_r;
+ $list30 = $bz0 | 0;
+ $list31 = $bz_l | 0;
+ $size32 = $bz_l + 4 | 0;
+ $list36 = $bz_r | 0;
+ $size37 = $bz_r + 4 | 0;
+ $i_038 = 0;
+ $endcolor_039 = 0;
+ $12 = $7;
+ label = 7;
+ break;
+ case 7:
+ $list = $12 | 0;
+ $13 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $13 + ($i_038 * 48 & -1) | 0;
+ $14 = $arrayidx;
+ HEAP32[$9 >> 2] = HEAP32[$14 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$14 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$14 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$14 + 12 >> 2] | 0;
+ HEAP32[$9 + 16 >> 2] = HEAP32[$14 + 16 >> 2] | 0;
+ HEAP32[$9 + 20 >> 2] = HEAP32[$14 + 20 >> 2] | 0;
+ HEAP32[$9 + 24 >> 2] = HEAP32[$14 + 24 >> 2] | 0;
+ HEAP32[$9 + 28 >> 2] = HEAP32[$14 + 28 >> 2] | 0;
+ HEAP32[$9 + 32 >> 2] = HEAP32[$14 + 32 >> 2] | 0;
+ HEAP32[$9 + 36 >> 2] = HEAP32[$14 + 36 >> 2] | 0;
+ HEAP32[$9 + 40 >> 2] = HEAP32[$14 + 40 >> 2] | 0;
+ HEAP32[$9 + 44 >> 2] = HEAP32[$14 + 44 >> 2] | 0;
+ $15 = HEAP32[$segs >> 2] | 0;
+ $segs13 = $15 + 4 | 0;
+ $16 = HEAP32[$segs13 >> 2] | 0;
+ $color31 = $16 | 0;
+ $17 = HEAP32[$color31 >> 2] | 0;
+ $tobool1532 = ($17 | 0) == 0;
+ if ($tobool1532) {
+ $endcolor_1_lcssa = $endcolor_039;
+ label = 14;
+ break;
+ } else {
+ $endcolor_134 = $endcolor_039;
+ $color35 = $color31;
+ $18 = $17;
+ label = 8;
+ break;
+ }
+ case 8:
+ $indvars = $color35;
+ _gvrender_set_pencolor($job, $18);
+ $19 = HEAP32[$segs >> 2] | 0;
+ $segs18 = $19 + 4 | 0;
+ $20 = HEAP32[$segs18 >> 2] | 0;
+ $cmp19 = ($indvars | 0) == ($20 | 0);
+ $t = $color35 + 4 | 0;
+ $21 = $t;
+ $22 = +HEAPF32[$21 >> 2];
+ if ($cmp19) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ _splitBSpline($bz, $22, $bz_l, $bz_r);
+ $23 = HEAP32[$list21 >> 2] | 0;
+ $24 = HEAP32[$size22 >> 2] | 0;
+ _gvrender_beziercurve($job, $23, $24, 0, 0, 0);
+ $25 = HEAP32[$list21 >> 2] | 0;
+ $26 = $25;
+ _free($26);
+ $endcolor_2 = $endcolor_134;
+ label = 13;
+ break;
+ case 10:
+ $cmp26 = $22 < 1.0;
+ if ($cmp26) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ HEAP32[$10 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ HEAP32[$10 + 16 >> 2] = HEAP32[$11 + 16 >> 2] | 0;
+ HEAP32[$10 + 20 >> 2] = HEAP32[$11 + 20 >> 2] | 0;
+ HEAP32[$10 + 24 >> 2] = HEAP32[$11 + 24 >> 2] | 0;
+ HEAP32[$10 + 28 >> 2] = HEAP32[$11 + 28 >> 2] | 0;
+ HEAP32[$10 + 32 >> 2] = HEAP32[$11 + 32 >> 2] | 0;
+ HEAP32[$10 + 36 >> 2] = HEAP32[$11 + 36 >> 2] | 0;
+ HEAP32[$10 + 40 >> 2] = HEAP32[$11 + 40 >> 2] | 0;
+ HEAP32[$10 + 44 >> 2] = HEAP32[$11 + 44 >> 2] | 0;
+ $27 = +HEAPF32[$21 >> 2];
+ _splitBSpline($bz0, $27, $bz_l, $bz_r);
+ $28 = HEAP32[$list30 >> 2] | 0;
+ $29 = $28;
+ _free($29);
+ $30 = HEAP32[$list31 >> 2] | 0;
+ $31 = HEAP32[$size32 >> 2] | 0;
+ _gvrender_beziercurve($job, $30, $31, 0, 0, 0);
+ $32 = HEAP32[$list31 >> 2] | 0;
+ $33 = $32;
+ _free($33);
+ $endcolor_2 = $endcolor_134;
+ label = 13;
+ break;
+ case 12:
+ $34 = HEAP32[$color35 >> 2] | 0;
+ $35 = HEAP32[$list36 >> 2] | 0;
+ $36 = HEAP32[$size37 >> 2] | 0;
+ _gvrender_beziercurve($job, $35, $36, 0, 0, 0);
+ $37 = HEAP32[$list36 >> 2] | 0;
+ $38 = $37;
+ _free($38);
+ $endcolor_2 = $34;
+ label = 13;
+ break;
+ case 13:
+ $incdec_ptr = $color35 + 8 | 0;
+ $39 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool15 = ($39 | 0) == 0;
+ if ($tobool15) {
+ $endcolor_1_lcssa = $endcolor_2;
+ label = 14;
+ break;
+ } else {
+ $endcolor_134 = $endcolor_2;
+ $color35 = $incdec_ptr;
+ $18 = $39;
+ label = 8;
+ break;
+ }
+ case 14:
+ $40 = HEAP32[$sflag >> 2] | 0;
+ $tobool41 = ($40 | 0) == 0;
+ if ($tobool41) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $41 = HEAP32[$segs >> 2] | 0;
+ $segs43 = $41 + 4 | 0;
+ $42 = HEAP32[$segs43 >> 2] | 0;
+ $color44 = $42 | 0;
+ $43 = HEAP32[$color44 >> 2] | 0;
+ _gvrender_set_pencolor($job, $43);
+ $44 = HEAP32[$segs >> 2] | 0;
+ $segs45 = $44 + 4 | 0;
+ $45 = HEAP32[$segs45 >> 2] | 0;
+ $color46 = $45 | 0;
+ $46 = HEAP32[$color46 >> 2] | 0;
+ _gvrender_set_fillcolor($job, $46);
+ $47 = HEAP32[$list47 >> 2] | 0;
+ $48 = HEAP32[$sflag >> 2] | 0;
+ _arrow_gen($job, 2, $sp, $47, $arrowsize, $penwidth, $48);
+ label = 16;
+ break;
+ case 16:
+ $49 = HEAP32[$eflag >> 2] | 0;
+ $tobool51 = ($49 | 0) == 0;
+ if ($tobool51) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ _gvrender_set_pencolor($job, $endcolor_1_lcssa);
+ _gvrender_set_fillcolor($job, $endcolor_1_lcssa);
+ $50 = HEAP32[$size53 >> 2] | 0;
+ $sub = $50 - 1 | 0;
+ $51 = HEAP32[$list54 >> 2] | 0;
+ $arrayidx55 = $51 + ($sub << 4) | 0;
+ $52 = HEAP32[$eflag >> 2] | 0;
+ _arrow_gen($job, 3, $ep, $arrayidx55, $arrowsize, $penwidth, $52);
+ label = 18;
+ break;
+ case 18:
+ $53 = HEAP32[$spl >> 2] | 0;
+ $size60 = $53 + 4 | 0;
+ $54 = HEAP32[$size60 >> 2] | 0;
+ $cmp61 = ($54 | 0) > 1;
+ if ($cmp61) {
+ label = 19;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 19:
+ $55 = HEAP32[$sflag >> 2] | 0;
+ $tobool64 = ($55 | 0) == 0;
+ if ($tobool64) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $56 = HEAP32[$eflag >> 2] | 0;
+ $tobool66 = ($56 | 0) == 0;
+ $or_cond = $tobool66 | $tobool68;
+ if ($or_cond) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ if ($tobool68_old) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ _gvrender_set_style($job, $styles);
+ label = 23;
+ break;
+ case 23:
+ $inc = $i_038 + 1 | 0;
+ $57 = HEAP32[$spl >> 2] | 0;
+ $size = $57 + 4 | 0;
+ $58 = HEAP32[$size >> 2] | 0;
+ $cmp10 = ($inc | 0) < ($58 | 0);
+ if ($cmp10) {
+ $i_038 = $inc;
+ $endcolor_039 = $endcolor_1_lcssa;
+ $12 = $57;
+ label = 7;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $59 = HEAP32[$segs >> 2] | 0;
+ $60 = $59;
+ _free($60);
+ $retval_0 = 0;
+ label = 25;
+ break;
+ case 25:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _default_pencolor($pencolor, $deflt) {
+ $pencolor = $pencolor | 0;
+ $deflt = $deflt | 0;
+ var $p_0 = 0, $ncol_0 = 0, $0 = 0, $inc = 0, $ncol_1 = 0, $incdec_ptr = 0, $call = 0, $add = 0, $mul = 0, $1 = 0, $cmp2 = 0, $add5 = 0, $2 = 0, $call6 = 0, $3 = 0, $call8 = 0, $dec8 = 0, $tobool99 = 0, $4 = 0, $5 = 0, $dec10 = 0, $strlen = 0, $endptr = 0, $6 = 0, $7 = 0, $call11 = 0, $dec = 0, $tobool9 = 0, $8 = 0, $_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ncol_0 = 1;
+ $p_0 = $pencolor;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[$p_0] | 0;
+ if (($0 << 24 >> 24 | 0) == 58) {
+ label = 4;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 0) {
+ label = 6;
+ break;
+ } else {
+ $ncol_1 = $ncol_0;
+ label = 5;
+ break;
+ }
+ case 4:
+ $inc = $ncol_0 + 1 | 0;
+ $ncol_1 = $inc;
+ label = 5;
+ break;
+ case 5:
+ $incdec_ptr = $p_0 + 1 | 0;
+ $ncol_0 = $ncol_1;
+ $p_0 = $incdec_ptr;
+ label = 3;
+ break;
+ case 6:
+ $call = _strlen($deflt | 0) | 0;
+ $add = $call + 1 | 0;
+ $mul = Math_imul($add, $ncol_0);
+ $1 = HEAP32[5300] | 0;
+ $cmp2 = ($1 | 0) < ($mul | 0);
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $add5 = $mul + 10 | 0;
+ HEAP32[5300] = $add5;
+ $2 = HEAP32[5302] | 0;
+ $call6 = _realloc($2, $add5) | 0;
+ HEAP32[5302] = $call6;
+ label = 8;
+ break;
+ case 8:
+ $3 = HEAP32[5302] | 0;
+ $call8 = _strcpy($3 | 0, $deflt | 0) | 0;
+ $dec8 = $ncol_0 - 1 | 0;
+ $tobool99 = ($dec8 | 0) == 0;
+ $4 = HEAP32[5302] | 0;
+ if ($tobool99) {
+ $_lcssa = $4;
+ label = 10;
+ break;
+ } else {
+ $dec10 = $dec8;
+ $5 = $4;
+ label = 9;
+ break;
+ }
+ case 9:
+ $strlen = _strlen($5 | 0) | 0;
+ $endptr = $5 + $strlen | 0;
+ $6 = $endptr;
+ tempBigInt = 58;
+ HEAP8[$6] = tempBigInt & 255;
+ tempBigInt = tempBigInt >> 8;
+ HEAP8[$6 + 1 | 0] = tempBigInt & 255;
+ $7 = HEAP32[5302] | 0;
+ $call11 = _strcat($7 | 0, $deflt | 0) | 0;
+ $dec = $dec10 - 1 | 0;
+ $tobool9 = ($dec | 0) == 0;
+ $8 = HEAP32[5302] | 0;
+ if ($tobool9) {
+ $_lcssa = $8;
+ label = 10;
+ break;
+ } else {
+ $dec10 = $dec;
+ $5 = $8;
+ label = 9;
+ break;
+ }
+ case 10:
+ return $_lcssa | 0;
+ }
+ return 0;
+}
+function _computeoffset_p($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $sub = 0.0, $sub5 = 0.0, $div = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $sub = +HEAPF64[$p >> 3] - +HEAPF64[$q >> 3];
+ $sub5 = +HEAPF64[$p + 8 >> 3] - +HEAPF64[$q + 8 >> 3];
+ $div = 2.0 / +Math_sqrt(+($sub * $sub + $sub5 * $sub5 + 1.0e-4));
+ HEAPF64[$agg_result >> 3] = $sub5 * $div;
+ HEAPF64[$agg_result + 8 >> 3] = $div * (-0.0 - $sub);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _computeoffset_qr($agg_result, $p, $q, $r, $s) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ $r = $r | 0;
+ $s = $s | 0;
+ var $x1 = 0, $0 = 0.0, $x2 = 0, $1 = 0.0, $sub = 0.0, $y3 = 0, $2 = 0.0, $y4 = 0, $3 = 0.0, $sub5 = 0.0, $mul = 0.0, $mul6 = 0.0, $add = 0.0, $call = 0.0, $cmp = 0, $x7 = 0, $4 = 0.0, $x8 = 0, $5 = 0.0, $sub9 = 0.0, $y10 = 0, $6 = 0.0, $y11 = 0, $7 = 0.0, $sub12 = 0.0, $mul13 = 0.0, $mul14 = 0.0, $add15 = 0.0, $add16 = 0.0, $call17 = 0.0, $len_0 = 0.0, $x_0 = 0.0, $y_0 = 0.0, $div = 0.0, $mul18 = 0.0, $sub20 = 0.0, $mul21 = 0.0, $res_sroa_0_0__idx = 0, $res_sroa_1_8__idx10 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $r;
+ $r = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$r >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$r + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$r + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$r + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $s;
+ $s = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$s >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$s + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$s + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$s + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x1 = $q | 0;
+ $0 = +HEAPF64[$x1 >> 3];
+ $x2 = $r | 0;
+ $1 = +HEAPF64[$x2 >> 3];
+ $sub = $0 - $1;
+ $y3 = $q + 8 | 0;
+ $2 = +HEAPF64[$y3 >> 3];
+ $y4 = $r + 8 | 0;
+ $3 = +HEAPF64[$y4 >> 3];
+ $sub5 = $2 - $3;
+ $mul = $sub * $sub;
+ $mul6 = $sub5 * $sub5;
+ $add = $mul + $mul6;
+ $call = +Math_sqrt(+$add);
+ $cmp = $call < 1.0e-4;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $y_0 = $sub5;
+ $x_0 = $sub;
+ $len_0 = $call;
+ label = 4;
+ break;
+ }
+ case 3:
+ $x7 = $p | 0;
+ $4 = +HEAPF64[$x7 >> 3];
+ $x8 = $s | 0;
+ $5 = +HEAPF64[$x8 >> 3];
+ $sub9 = $4 - $5;
+ $y10 = $p + 8 | 0;
+ $6 = +HEAPF64[$y10 >> 3];
+ $y11 = $s + 8 | 0;
+ $7 = +HEAPF64[$y11 >> 3];
+ $sub12 = $6 - $7;
+ $mul13 = $sub9 * $sub9;
+ $mul14 = $sub12 * $sub12;
+ $add15 = $mul13 + $mul14;
+ $add16 = $add15 + 1.0e-4;
+ $call17 = +Math_sqrt(+$add16);
+ $y_0 = $sub12;
+ $x_0 = $sub9;
+ $len_0 = $call17;
+ label = 4;
+ break;
+ case 4:
+ $div = 2.0 / $len_0;
+ $mul18 = $y_0 * $div;
+ $sub20 = -0.0 - $x_0;
+ $mul21 = $div * $sub20;
+ $res_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$res_sroa_0_0__idx >> 3] = $mul18;
+ $res_sroa_1_8__idx10 = $agg_result + 8 | 0;
+ HEAPF64[$res_sroa_1_8__idx10 >> 3] = $mul21;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _parseSegs($clrs, $nseg, $psegs) {
+ $clrs = $clrs | 0;
+ $nseg = $nseg | 0;
+ $psegs = $psegs | 0;
+ var $call = 0, $0 = 0, $add = 0, $mul = 0, $call1 = 0, $call2 = 0, $base = 0, $call5 = 0, $1 = 0, $segs6 = 0, $2 = 0, $call7 = 0, $tobool32 = 0, $rval_037 = 0, $prev_v_036 = 0.0, $nseg_addr_035 = 0, $cnum_034 = 0, $color_033 = 0, $sub = 0, $cmp = 0, $cmp8 = 0, $call10 = 0, $tobool11 = 0, $color13 = 0, $inc = 0, $t = 0, $call16 = 0.0, $cmp17 = 0, $cmp19 = 0, $color22 = 0, $sub23 = 0.0, $sub24 = 0.0, $div = 0.0, $conv = 0.0, $inc25 = 0, $t27 = 0, $_b29 = 0, $call31 = 0, $_b = 0, $call37 = 0, $rval_1 = 0, $cnum_1 = 0, $nseg_addr_1 = 0, $prev_v_1 = 0.0, $rval_2 = 0, $call42 = 0, $tobool = 0, $cmp43 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(8) | 0;
+ $0 = $call;
+ $add = $nseg << 3;
+ $mul = $add + 8 | 0;
+ $call1 = _zmalloc($mul) | 0;
+ $call2 = _strdup($clrs | 0) | 0;
+ $base = $call;
+ HEAP32[$base >> 2] = $call2;
+ $call5 = _zmalloc($mul) | 0;
+ $1 = $call5;
+ $segs6 = $call + 4 | 0;
+ $2 = $segs6;
+ HEAP32[$2 >> 2] = $1;
+ $call7 = _strtok($call2 | 0, 98688) | 0;
+ $tobool32 = ($call7 | 0) == 0;
+ if ($tobool32) {
+ label = 18;
+ break;
+ } else {
+ $color_033 = $call7;
+ $cnum_034 = 0;
+ $nseg_addr_035 = $nseg;
+ $prev_v_036 = 0.0;
+ $rval_037 = 0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub = $nseg_addr_035 - 1 | 0;
+ $cmp = ($cnum_034 | 0) == ($sub | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $cmp8 = $prev_v_036 < 1.0;
+ if ($cmp8) {
+ label = 5;
+ break;
+ } else {
+ $rval_2 = $rval_037;
+ $prev_v_1 = $prev_v_036;
+ $nseg_addr_1 = $nseg_addr_035;
+ $cnum_1 = $cnum_034;
+ label = 16;
+ break;
+ }
+ case 5:
+ $call10 = _strchr($color_033 | 0, 44) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ if ($tobool11) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ HEAP8[$call10] = 0;
+ label = 7;
+ break;
+ case 7:
+ $color13 = $1 + ($cnum_034 << 3) | 0;
+ HEAP32[$color13 >> 2] = $color_033;
+ $inc = $cnum_034 + 1 | 0;
+ $t = $1 + ($cnum_034 << 3) + 4 | 0;
+ HEAPF32[$t >> 2] = 1.0;
+ $rval_2 = $rval_037;
+ $prev_v_1 = $prev_v_036;
+ $nseg_addr_1 = $nseg_addr_035;
+ $cnum_1 = $inc;
+ label = 16;
+ break;
+ case 8:
+ $call16 = +_getSegLen($color_033, $prev_v_036);
+ $cmp17 = $call16 < 0.0;
+ if ($cmp17) {
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp19 = $prev_v_036 < $call16;
+ if ($cmp19) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $color22 = $1 + ($cnum_034 << 3) | 0;
+ HEAP32[$color22 >> 2] = $color_033;
+ $sub23 = $call16 - $prev_v_036;
+ $sub24 = 1.0 - $prev_v_036;
+ $div = $sub23 / $sub24;
+ $conv = $div;
+ $inc25 = $cnum_034 + 1 | 0;
+ $t27 = $1 + ($cnum_034 << 3) + 4 | 0;
+ HEAPF32[$t27 >> 2] = $conv;
+ $rval_2 = $rval_037;
+ $prev_v_1 = $call16;
+ $nseg_addr_1 = $nseg_addr_035;
+ $cnum_1 = $inc25;
+ label = 16;
+ break;
+ case 11:
+ $_b29 = HEAP8[7544] | 0;
+ if ($_b29) {
+ $rval_2 = $rval_037;
+ $prev_v_1 = $prev_v_036;
+ $nseg_addr_1 = $sub;
+ $cnum_1 = $cnum_034;
+ label = 16;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call31 = _agerr(0, 97080, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $clrs, tempInt) | 0) | 0;
+ HEAP8[7544] = 1;
+ $rval_2 = 3;
+ $prev_v_1 = $prev_v_036;
+ $nseg_addr_1 = $sub;
+ $cnum_1 = $cnum_034;
+ label = 16;
+ break;
+ case 13:
+ $_b = HEAP8[7544] | 0;
+ if ($_b) {
+ $rval_1 = 1;
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $call37 = _agerr(1, 96608, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $clrs, tempInt) | 0) | 0;
+ HEAP8[7544] = 1;
+ $rval_1 = 2;
+ label = 15;
+ break;
+ case 15:
+ _freeSegs($0);
+ $retval_0 = $rval_1;
+ label = 20;
+ break;
+ case 16:
+ $call42 = _strtok(0, 98688) | 0;
+ $tobool = ($call42 | 0) == 0;
+ if ($tobool) {
+ label = 17;
+ break;
+ } else {
+ $color_033 = $call42;
+ $cnum_034 = $cnum_1;
+ $nseg_addr_035 = $nseg_addr_1;
+ $prev_v_036 = $prev_v_1;
+ $rval_037 = $rval_2;
+ label = 3;
+ break;
+ }
+ case 17:
+ $cmp43 = ($cnum_1 | 0) == 0;
+ if ($cmp43) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ _freeSegs($0);
+ $retval_0 = 1;
+ label = 20;
+ break;
+ case 19:
+ HEAP32[$psegs >> 2] = $0;
+ $retval_0 = $rval_2;
+ label = 20;
+ break;
+ case 20:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _splitBSpline($bz, $t, $left, $right) {
+ $bz = $bz | 0;
+ $t = +$t;
+ $left = $left | 0;
+ $right = $right | 0;
+ var $tmp = 0, $tmp84 = 0, $size = 0, $0 = 0, $sub = 0, $div = 0, $sub_off = 0, $1 = 0, $size1 = 0, $call = 0, $2 = 0, $list = 0, $size2 = 0, $call3 = 0, $3 = 0, $list4 = 0, $list5 = 0, $4 = 0, $conv = 0.0, $5 = 0, $mul = 0, $call8 = 0, $6 = 0, $list9 = 0, $cmp1060 = 0, $7 = 0, $i_063 = 0, $pts_062 = 0, $sum_061 = 0.0, $call12 = 0.0, $arrayidx = 0, $add = 0.0, $add_ptr = 0, $inc = 0, $cmp10 = 0, $sum_0_lcssa = 0.0, $conv14 = 0.0, $mul15 = 0.0, $sum_1 = 0.0, $i_1 = 0, $cmp17 = 0, $arrayidx20 = 0, $8 = 0.0, $add21 = 0.0, $cmp22 = 0, $inc27 = 0, $sum_2 = 0.0, $9 = 0, $add31 = 0, $size32 = 0, $mul34 = 0, $call35 = 0, $10 = 0, $list36 = 0, $sub37 = 0, $mul38 = 0, $add39 = 0, $size40 = 0, $mul42 = 0, $call43 = 0, $11 = 0, $list44 = 0, $12 = 0, $cmp4758 = 0, $j_059 = 0, $13 = 0, $arrayidx51 = 0, $14 = 0, $arrayidx53 = 0, $15 = 0, $16 = 0, $inc55 = 0, $17 = 0, $cmp47 = 0, $phitmp = 0, $j_0_lcssa = 0, $18 = 0, $cmp6055 = 0, $j_157 = 0, $k_056 = 0, $19 = 0, $arrayidx64 = 0, $inc65 = 0, $20 = 0, $arrayidx67 = 0, $21 = 0, $22 = 0, $inc69 = 0, $23 = 0, $cmp60 = 0, $arrayidx71 = 0, $24 = 0.0, $sub72 = 0.0, $sub73 = 0.0, $div74 = 0.0, $conv75 = 0.0, $25 = 0, $mul77 = 0, $add_ptr78 = 0, $conv79 = 0.0, $26 = 0, $add_ptr82 = 0, $27 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmp84 = __stackBase__ + 16 | 0;
+ $size = $bz + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $sub = $0 - 1 | 0;
+ $div = ($sub | 0) / 3 & -1;
+ $sub_off = $0 - 4 | 0;
+ $1 = $sub_off >>> 0 < 3;
+ if ($1) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $size1 = $left + 4 | 0;
+ HEAP32[$size1 >> 2] = 4;
+ $call = _zmalloc(64) | 0;
+ $2 = $call;
+ $list = $left | 0;
+ HEAP32[$list >> 2] = $2;
+ $size2 = $right + 4 | 0;
+ HEAP32[$size2 >> 2] = 4;
+ $call3 = _zmalloc(64) | 0;
+ $3 = $call3;
+ $list4 = $right | 0;
+ HEAP32[$list4 >> 2] = $3;
+ $list5 = $bz | 0;
+ $4 = HEAP32[$list5 >> 2] | 0;
+ $conv = $t;
+ $5 = HEAP32[$list >> 2] | 0;
+ _Bezier($tmp, $4, 3, $conv, $5, $3);
+ label = 16;
+ break;
+ case 4:
+ $mul = $div << 3;
+ $call8 = _zmalloc($mul) | 0;
+ $6 = $call8;
+ $list9 = $bz | 0;
+ $cmp1060 = ($sub | 0) > 2;
+ if ($cmp1060) {
+ label = 5;
+ break;
+ } else {
+ $sum_0_lcssa = 0.0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $7 = HEAP32[$list9 >> 2] | 0;
+ $sum_061 = 0.0;
+ $pts_062 = $7;
+ $i_063 = 0;
+ label = 6;
+ break;
+ case 6:
+ $call12 = +_approxLen($pts_062);
+ $arrayidx = $6 + ($i_063 << 3) | 0;
+ HEAPF64[$arrayidx >> 3] = $call12;
+ $add = $sum_061 + $call12;
+ $add_ptr = $pts_062 + 48 | 0;
+ $inc = $i_063 + 1 | 0;
+ $cmp10 = ($inc | 0) < ($div | 0);
+ if ($cmp10) {
+ $sum_061 = $add;
+ $pts_062 = $add_ptr;
+ $i_063 = $inc;
+ label = 6;
+ break;
+ } else {
+ $sum_0_lcssa = $add;
+ label = 7;
+ break;
+ }
+ case 7:
+ $conv14 = $t;
+ $mul15 = $conv14 * $sum_0_lcssa;
+ $i_1 = 0;
+ $sum_1 = 0.0;
+ label = 8;
+ break;
+ case 8:
+ $cmp17 = ($i_1 | 0) < ($div | 0);
+ if ($cmp17) {
+ label = 9;
+ break;
+ } else {
+ $sum_2 = $sum_1;
+ label = 10;
+ break;
+ }
+ case 9:
+ $arrayidx20 = $6 + ($i_1 << 3) | 0;
+ $8 = +HEAPF64[$arrayidx20 >> 3];
+ $add21 = $sum_1 + $8;
+ $cmp22 = $add21 < $mul15;
+ $inc27 = $i_1 + 1 | 0;
+ if ($cmp22) {
+ $i_1 = $inc27;
+ $sum_1 = $add21;
+ label = 8;
+ break;
+ } else {
+ $sum_2 = $add21;
+ label = 10;
+ break;
+ }
+ case 10:
+ $9 = $i_1 * 3 & -1;
+ $add31 = $9 + 4 | 0;
+ $size32 = $left + 4 | 0;
+ HEAP32[$size32 >> 2] = $add31;
+ $mul34 = $add31 << 4;
+ $call35 = _zmalloc($mul34) | 0;
+ $10 = $call35;
+ $list36 = $left | 0;
+ HEAP32[$list36 >> 2] = $10;
+ $sub37 = $div - $i_1 | 0;
+ $mul38 = $sub37 * 3 & -1;
+ $add39 = $mul38 + 1 | 0;
+ $size40 = $right + 4 | 0;
+ HEAP32[$size40 >> 2] = $add39;
+ $mul42 = $add39 << 4;
+ $call43 = _zmalloc($mul42) | 0;
+ $11 = $call43;
+ $list44 = $right | 0;
+ HEAP32[$list44 >> 2] = $11;
+ $12 = HEAP32[$size32 >> 2] | 0;
+ $cmp4758 = ($12 | 0) > 0;
+ if ($cmp4758) {
+ $j_059 = 0;
+ label = 11;
+ break;
+ } else {
+ $j_0_lcssa = -4;
+ label = 13;
+ break;
+ }
+ case 11:
+ $13 = HEAP32[$list36 >> 2] | 0;
+ $arrayidx51 = $13 + ($j_059 << 4) | 0;
+ $14 = HEAP32[$list9 >> 2] | 0;
+ $arrayidx53 = $14 + ($j_059 << 4) | 0;
+ $15 = $arrayidx51;
+ $16 = $arrayidx53;
+ HEAP32[$15 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ $inc55 = $j_059 + 1 | 0;
+ $17 = HEAP32[$size32 >> 2] | 0;
+ $cmp47 = ($inc55 | 0) < ($17 | 0);
+ if ($cmp47) {
+ $j_059 = $inc55;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $phitmp = $j_059 - 3 | 0;
+ $j_0_lcssa = $phitmp;
+ label = 13;
+ break;
+ case 13:
+ $18 = HEAP32[$size40 >> 2] | 0;
+ $cmp6055 = ($18 | 0) > 0;
+ if ($cmp6055) {
+ $k_056 = $j_0_lcssa;
+ $j_157 = 0;
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $19 = HEAP32[$list44 >> 2] | 0;
+ $arrayidx64 = $19 + ($j_157 << 4) | 0;
+ $inc65 = $k_056 + 1 | 0;
+ $20 = HEAP32[$list9 >> 2] | 0;
+ $arrayidx67 = $20 + ($k_056 << 4) | 0;
+ $21 = $arrayidx64;
+ $22 = $arrayidx67;
+ HEAP32[$21 >> 2] = HEAP32[$22 >> 2] | 0;
+ HEAP32[$21 + 4 >> 2] = HEAP32[$22 + 4 >> 2] | 0;
+ HEAP32[$21 + 8 >> 2] = HEAP32[$22 + 8 >> 2] | 0;
+ HEAP32[$21 + 12 >> 2] = HEAP32[$22 + 12 >> 2] | 0;
+ $inc69 = $j_157 + 1 | 0;
+ $23 = HEAP32[$size40 >> 2] | 0;
+ $cmp60 = ($inc69 | 0) < ($23 | 0);
+ if ($cmp60) {
+ $k_056 = $inc65;
+ $j_157 = $inc69;
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $arrayidx71 = $6 + ($i_1 << 3) | 0;
+ $24 = +HEAPF64[$arrayidx71 >> 3];
+ $sub72 = $sum_2 - $24;
+ $sub73 = $mul15 - $sub72;
+ $div74 = $sub73 / $24;
+ $conv75 = $div74;
+ $25 = HEAP32[$list9 >> 2] | 0;
+ $mul77 = $i_1 * 3 & -1;
+ $add_ptr78 = $25 + ($mul77 << 4) | 0;
+ $conv79 = $conv75;
+ $26 = HEAP32[$list36 >> 2] | 0;
+ $add_ptr82 = $26 + ($mul77 << 4) | 0;
+ $27 = HEAP32[$list44 >> 2] | 0;
+ _Bezier($tmp84, $add_ptr78, 3, $conv79, $add_ptr82, $27);
+ _free($call8);
+ label = 16;
+ break;
+ case 16:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_edge_label($job, $lbl, $lkind, $explicit, $url, $tooltip, $target, $id, $spl) {
+ $job = $job | 0;
+ $lbl = $lbl | 0;
+ $lkind = $lkind | 0;
+ $explicit = $explicit | 0;
+ $url = $url | 0;
+ $tooltip = $tooltip | 0;
+ $target = $target | 0;
+ $id = $id | 0;
+ $spl = $spl | 0;
+ var $flags1 = 0, $0 = 0, $cmp = 0, $tobool = 0, $call = 0, $add = 0, $call3 = 0, $type_0 = 0, $call6 = 0, $newid_0 = 0, $obj = 0, $1 = 0, $emit_state = 0, $2 = 0, $tobool10_not = 0, $tobool11 = 0, $or_cond = 0, $and = 0, $tobool12 = 0, $tobool15 = 0, $and22 = 0, $tobool23 = 0, $tobool27 = 0, $3 = 0, $emit_state31 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $flags1 = $job + 152 | 0;
+ $0 = HEAP32[$flags1 >> 2] | 0;
+ $cmp = ($lbl | 0) == 0;
+ if ($cmp) {
+ label = 21;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tobool = ($id | 0) == 0;
+ if ($tobool) {
+ $newid_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _strlen($id | 0) | 0;
+ $add = $call + 11 | 0;
+ $call3 = _zmalloc($add) | 0;
+ if (($lkind | 0) == 7) {
+ label = 5;
+ break;
+ } else if (($lkind | 0) == 6) {
+ label = 6;
+ break;
+ } else if (($lkind | 0) == 11) {
+ $type_0 = 100816;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $type_0 = 100448;
+ label = 8;
+ break;
+ case 6:
+ $type_0 = 99968;
+ label = 8;
+ break;
+ case 7:
+ ___assert_func(162152, 2201, 164336, 99512);
+ case 8:
+ $call6 = _sprintf($call3 | 0, 99144, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $id, HEAP32[tempInt + 8 >> 2] = $type_0, tempInt) | 0) | 0;
+ $newid_0 = $call3;
+ label = 9;
+ break;
+ case 9:
+ $obj = $job + 16 | 0;
+ $1 = HEAP32[$obj >> 2] | 0;
+ $emit_state = $1 + 12 | 0;
+ $2 = HEAP32[$emit_state >> 2] | 0;
+ HEAP32[$emit_state >> 2] = $lkind;
+ $tobool10_not = ($url | 0) == 0;
+ $tobool11 = ($explicit | 0) == 0;
+ $or_cond = $tobool10_not & $tobool11;
+ if ($or_cond) {
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $and = $0 & 4;
+ $tobool12 = ($and | 0) == 0;
+ if ($tobool12) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ _map_label($job, $lbl);
+ _gvrender_begin_anchor($job, $url, $tooltip, $target, $newid_0);
+ label = 12;
+ break;
+ case 12:
+ _emit_label($job, $lkind, $lbl);
+ $tobool15 = ($spl | 0) == 0;
+ if ($tobool15) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _emit_attachment($job, $lbl, $spl);
+ label = 14;
+ break;
+ case 14:
+ if ($or_cond) {
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $and22 = $0 & 4;
+ $tobool23 = ($and22 | 0) == 0;
+ if ($tobool23) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ _map_label($job, $lbl);
+ _gvrender_begin_anchor($job, $url, $tooltip, $target, $newid_0);
+ label = 17;
+ break;
+ case 17:
+ _gvrender_end_anchor($job);
+ label = 18;
+ break;
+ case 18:
+ $tobool27 = ($newid_0 | 0) == 0;
+ if ($tobool27) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ _free($newid_0);
+ label = 20;
+ break;
+ case 20:
+ $3 = HEAP32[$obj >> 2] | 0;
+ $emit_state31 = $3 + 12 | 0;
+ HEAP32[$emit_state31 >> 2] = $2;
+ label = 21;
+ break;
+ case 21:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _is_natural_number($sstr) {
+ $sstr = $sstr | 0;
+ var $str_0 = 0, $0 = 0, $tobool = 0, $incdec_ptr = 0, $conv = 0, $isdigittmp = 0, $isdigit = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $str_0 = $sstr;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[$str_0] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $str_0 + 1 | 0;
+ $conv = $0 & 255;
+ $isdigittmp = $conv - 48 | 0;
+ $isdigit = $isdigittmp >>> 0 < 10;
+ if ($isdigit) {
+ $str_0 = $incdec_ptr;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _boxf_overlap($b0, $b1) {
+ $b0 = $b0 | 0;
+ $b1 = $b1 | 0;
+ var $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $cmp = 0, $x3 = 0, $2 = 0.0, $x5 = 0, $3 = 0.0, $cmp6 = 0, $y = 0, $4 = 0.0, $y10 = 0, $5 = 0.0, $cmp11 = 0, $y13 = 0, $6 = 0.0, $y15 = 0, $7 = 0.0, $cmp16 = 0, $phitmp = 0, $8 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b0;
+ $b0 = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b0, tempParam, 32);
+ tempParam = $b1;
+ $b1 = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b1, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $b0 + 16 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $b1 | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $cmp = $0 < $1;
+ if ($cmp) {
+ $8 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x3 = $b1 + 16 | 0;
+ $2 = +HEAPF64[$x3 >> 3];
+ $x5 = $b0 | 0;
+ $3 = +HEAPF64[$x5 >> 3];
+ $cmp6 = $2 < $3;
+ if ($cmp6) {
+ $8 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $b0 + 24 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y10 = $b1 + 8 | 0;
+ $5 = +HEAPF64[$y10 >> 3];
+ $cmp11 = $4 < $5;
+ if ($cmp11) {
+ $8 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y13 = $b1 + 24 | 0;
+ $6 = +HEAPF64[$y13 >> 3];
+ $y15 = $b0 + 8 | 0;
+ $7 = +HEAPF64[$y15 >> 3];
+ $cmp16 = $6 >= $7;
+ $phitmp = $cmp16 & 1;
+ $8 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $8 | 0;
+ }
+ return 0;
+}
+function _approxLen($pts) {
+ $pts = $pts | 0;
+ var $1 = 0.0, $sub = 0.0, $3 = 0.0, $sub11 = 0.0, $call = 0.0, $4 = 0.0, $sub22 = 0.0, $5 = 0.0, $sub33 = 0.0, $add42 = 0.0, $sub47 = 0.0, $sub58 = 0.0;
+ $1 = +HEAPF64[$pts + 16 >> 3];
+ $sub = +HEAPF64[$pts >> 3] - $1;
+ $3 = +HEAPF64[$pts + 24 >> 3];
+ $sub11 = +HEAPF64[$pts + 8 >> 3] - $3;
+ $call = +Math_sqrt(+($sub * $sub + $sub11 * $sub11));
+ $4 = +HEAPF64[$pts + 32 >> 3];
+ $sub22 = $1 - $4;
+ $5 = +HEAPF64[$pts + 40 >> 3];
+ $sub33 = $3 - $5;
+ $add42 = $call + +Math_sqrt(+($sub22 * $sub22 + $sub33 * $sub33));
+ $sub47 = $4 - +HEAPF64[$pts + 48 >> 3];
+ $sub58 = $5 - +HEAPF64[$pts + 56 >> 3];
+ return +($add42 + +Math_sqrt(+($sub47 * $sub47 + $sub58 * $sub58)));
+}
+function _getSegLen($s, $prev_v) {
+ $s = $s | 0;
+ $prev_v = +$prev_v;
+ var $endp = 0, $call = 0, $tobool = 0, $call1 = 0, $incdec_ptr = 0, $call2 = 0.0, $0 = 0, $cmp = 0, $cmp4 = 0, $cmp5 = 0, $or_cond = 0, $retval_0 = 0.0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $endp = __stackBase__ | 0;
+ $call = _strchr($s | 0, 44) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call1 = _agerr(1, 96248, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $s, tempInt) | 0) | 0;
+ $retval_0 = -1.0;
+ label = 7;
+ break;
+ case 4:
+ $incdec_ptr = $call + 1 | 0;
+ HEAP8[$call] = 0;
+ $call2 = +_strtod($incdec_ptr, $endp);
+ $0 = HEAP32[$endp >> 2] | 0;
+ $cmp = ($0 | 0) == ($incdec_ptr | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp4 = $call2 >= $prev_v;
+ $cmp5 = $call2 <= 1.0;
+ $or_cond = $cmp4 & $cmp5;
+ if ($or_cond) {
+ $retval_0 = $call2;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $retval_0 = -1.0;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return +$retval_0;
+ }
+ return 0.0;
+}
+function _freeSegs($segs) {
+ $segs = $segs | 0;
+ _free(HEAP32[$segs >> 2] | 0);
+ _free(HEAP32[$segs + 4 >> 2] | 0);
+ _free($segs);
+ return;
+}
+function _map_output_bspline($pbs, $pbs_n, $pbs_poly_n, $bp, $w2) {
+ $pbs = $pbs | 0;
+ $pbs_n = $pbs_n | 0;
+ $pbs_poly_n = $pbs_poly_n | 0;
+ $bp = $bp | 0;
+ $w2 = +$w2;
+ var $pts = 0, $pt1 = 0, $pt2 = 0, $call = 0, $0 = 0, $next = 0, $1 = 0, $size = 0, $2 = 0, $sub = 0, $div = 0, $cmp32 = 0, $list = 0, $arraydecay = 0, $tobool27 = 0, $arraydecay11 = 0, $arraydecay10 = 0, $3 = 0, $4 = 0, $j_034 = 0, $segp_033 = 0, $mul = 0, $5 = 0, $arrayidx4 = 0, $6 = 0, $7 = 0, $arrayidx_1 = 0, $add_1 = 0, $8 = 0, $arrayidx4_1 = 0, $9 = 0, $10 = 0, $arrayidx_2 = 0, $add_2 = 0, $11 = 0, $arrayidx4_2 = 0, $12 = 0, $13 = 0, $arrayidx_3 = 0, $add_3 = 0, $14 = 0, $arrayidx4_3 = 0, $15 = 0, $16 = 0, $call5 = 0, $inc7 = 0, $cmp = 0, $tobool2525 = 0, $cnt_030 = 0, $segp_129 = 0, $segprev_028 = 0, $next9 = 0, $17 = 0, $add_ptr = 0, $add_ptr12 = 0, $inc13 = 0, $cmp14 = 0, $cmp15 = 0, $or_cond = 0, $cnt_0_be = 0, $tobool = 0, $18 = 0, $19 = 0, $segl_026 = 0, $next27 = 0, $20 = 0, $21 = 0, $tobool25 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1664 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pts = __stackBase__ | 0;
+ $pt1 = __stackBase__ + 64 | 0;
+ $pt2 = __stackBase__ + 864 | 0;
+ $call = _gmalloc(24) | 0;
+ $0 = $call;
+ $next = $call + 16 | 0;
+ $1 = $next;
+ HEAP32[$1 >> 2] = 1;
+ $size = $bp + 4 | 0;
+ $2 = HEAP32[$size >> 2] | 0;
+ $sub = $2 - 1 | 0;
+ $div = ($sub | 0) / 3 & -1;
+ $cmp32 = ($sub | 0) > 2;
+ if ($cmp32) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $list = $bp | 0;
+ $arraydecay = $pts | 0;
+ $segp_033 = $0;
+ $j_034 = 0;
+ label = 6;
+ break;
+ case 4:
+ $tobool27 = ($call | 0) == 0;
+ if ($tobool27) {
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $arraydecay11 = $pt2 | 0;
+ $arraydecay10 = $pt1 | 0;
+ $3 = $pt1;
+ $4 = $pt2;
+ $segprev_028 = 0;
+ $segp_129 = $0;
+ $cnt_030 = 0;
+ label = 8;
+ break;
+ case 6:
+ $mul = $j_034 * 3 & -1;
+ $5 = HEAP32[$list >> 2] | 0;
+ $arrayidx4 = $5 + ($mul << 4) | 0;
+ $6 = $pts;
+ $7 = $arrayidx4;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $arrayidx_1 = $pts + 16 | 0;
+ $add_1 = $mul + 1 | 0;
+ $8 = HEAP32[$list >> 2] | 0;
+ $arrayidx4_1 = $8 + ($add_1 << 4) | 0;
+ $9 = $arrayidx_1;
+ $10 = $arrayidx4_1;
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $arrayidx_2 = $pts + 32 | 0;
+ $add_2 = $mul + 2 | 0;
+ $11 = HEAP32[$list >> 2] | 0;
+ $arrayidx4_2 = $11 + ($add_2 << 4) | 0;
+ $12 = $arrayidx_2;
+ $13 = $arrayidx4_2;
+ HEAP32[$12 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ $arrayidx_3 = $pts + 48 | 0;
+ $add_3 = $mul + 3 | 0;
+ $14 = HEAP32[$list >> 2] | 0;
+ $arrayidx4_3 = $14 + ($add_3 << 4) | 0;
+ $15 = $arrayidx_3;
+ $16 = $arrayidx4_3;
+ HEAP32[$15 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ $call5 = _approx_bezier($arraydecay, $segp_033) | 0;
+ $inc7 = $j_034 + 1 | 0;
+ $cmp = ($inc7 | 0) < ($div | 0);
+ if ($cmp) {
+ $segp_033 = $call5;
+ $j_034 = $inc7;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 7:
+ $tobool2525 = ($call | 0) == 0;
+ if ($tobool2525) {
+ label = 12;
+ break;
+ } else {
+ $segl_026 = $0;
+ label = 11;
+ break;
+ }
+ case 8:
+ $next9 = $segp_129 + 16 | 0;
+ $17 = HEAP32[$next9 >> 2] | 0;
+ $add_ptr = $pt1 + ($cnt_030 << 4) | 0;
+ $add_ptr12 = $pt2 + ($cnt_030 << 4) | 0;
+ _mkSegPts($segprev_028, $segp_129, $17, $add_ptr, $add_ptr12, $w2);
+ $inc13 = $cnt_030 + 1 | 0;
+ $cmp14 = ($17 | 0) == 0;
+ $cmp15 = ($inc13 | 0) == 50;
+ $or_cond = $cmp14 | $cmp15;
+ if ($or_cond) {
+ label = 10;
+ break;
+ } else {
+ $cnt_0_be = $inc13;
+ label = 9;
+ break;
+ }
+ case 9:
+ $tobool = ($17 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $segprev_028 = $segp_129;
+ $segp_129 = $17;
+ $cnt_030 = $cnt_0_be;
+ label = 8;
+ break;
+ }
+ case 10:
+ _map_bspline_poly($pbs, $pbs_n, $pbs_poly_n, $inc13, $arraydecay10, $arraydecay11);
+ $18 = $add_ptr;
+ HEAP32[$3 >> 2] = HEAP32[$18 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$18 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$18 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$18 + 12 >> 2] | 0;
+ $19 = $add_ptr12;
+ HEAP32[$4 >> 2] = HEAP32[$19 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$19 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$19 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$19 + 12 >> 2] | 0;
+ $cnt_0_be = 1;
+ label = 9;
+ break;
+ case 11:
+ $next27 = $segl_026 + 16 | 0;
+ $20 = HEAP32[$next27 >> 2] | 0;
+ $21 = $segl_026;
+ _free($21);
+ $tobool25 = ($20 | 0) == 0;
+ if ($tobool25) {
+ label = 12;
+ break;
+ } else {
+ $segl_026 = $20;
+ label = 11;
+ break;
+ }
+ case 12:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _approx_bezier($cp, $lp) {
+ $cp = $cp | 0;
+ $lp = $lp | 0;
+ var $left = 0, $right = 0, $tmp = 0, $call = 0, $tobool = 0, $next = 0, $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $arrayidx3 = 0, $call4 = 0, $arraydecay = 0, $arraydecay5 = 0, $call7 = 0, $call9 = 0, $lp_addr_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $left = __stackBase__ | 0;
+ $right = __stackBase__ + 64 | 0;
+ $tmp = __stackBase__ + 128 | 0;
+ $call = _check_control_points($cp) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $next = $lp + 16 | 0;
+ $0 = HEAP32[$next >> 2] | 0;
+ $cmp = ($0 | 0) == 1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP32[$next >> 2] = 0;
+ $1 = $lp;
+ $2 = $cp;
+ HEAP32[$1 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx3 = $cp + 48 | 0;
+ $call4 = _appendSeg($arrayidx3, $lp) | 0;
+ $lp_addr_0 = $call4;
+ label = 7;
+ break;
+ case 6:
+ $arraydecay = $left | 0;
+ $arraydecay5 = $right | 0;
+ _Bezier($tmp, $cp, 3, .5, $arraydecay, $arraydecay5);
+ $call7 = _approx_bezier($arraydecay, $lp) | 0;
+ $call9 = _approx_bezier($arraydecay5, $call7) | 0;
+ $lp_addr_0 = $call9;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $lp_addr_0 | 0;
+ }
+ return 0;
+}
+function _mkSegPts($prv, $cur, $nxt, $p1, $p2, $w2) {
+ $prv = $prv | 0;
+ $cur = $cur | 0;
+ $nxt = $nxt | 0;
+ $p1 = $p1 | 0;
+ $p2 = $p2 | 0;
+ $w2 = +$w2;
+ var $cp = 0, $pp = 0, $np = 0, $0 = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $tobool5 = 0, $4 = 0, $5 = 0, $x = 0, $6 = 0.0, $mul = 0.0, $x8 = 0, $7 = 0.0, $sub = 0.0, $x9 = 0, $y = 0, $8 = 0.0, $mul10 = 0.0, $y11 = 0, $9 = 0.0, $sub12 = 0.0, $y13 = 0, $10 = 0, $11 = 0, $x16 = 0, $12 = 0.0, $mul17 = 0.0, $x18 = 0, $13 = 0.0, $sub19 = 0.0, $x20 = 0, $y21 = 0, $14 = 0.0, $mul22 = 0.0, $y23 = 0, $15 = 0.0, $sub24 = 0.0, $y25 = 0, $call = 0.0, $call27 = 0.0, $mul28 = 0.0, $call29 = 0.0, $mul30 = 0.0, $x31 = 0, $16 = 0.0, $add = 0.0, $y33 = 0, $17 = 0.0, $add34 = 0.0, $p_sroa_0_0__idx1 = 0, $p_sroa_1_8__idx4 = 0, $18 = 0.0, $sub37 = 0.0, $19 = 0.0, $sub40 = 0.0, $p_sroa_0_0__idx = 0, $p_sroa_1_8__idx3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cp = __stackBase__ | 0;
+ $pp = __stackBase__ + 16 | 0;
+ $np = __stackBase__ + 32 | 0;
+ $0 = $cp;
+ $1 = $cur;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $tobool = ($prv | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $pp;
+ $3 = $prv;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $tobool5 = ($nxt | 0) == 0;
+ if ($tobool5) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $4 = $np;
+ $5 = $nxt;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ label = 7;
+ break;
+ case 5:
+ $x = $cp | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $mul = $6 * 2.0;
+ $x8 = $pp | 0;
+ $7 = +HEAPF64[$x8 >> 3];
+ $sub = $mul - $7;
+ $x9 = $np | 0;
+ HEAPF64[$x9 >> 3] = $sub;
+ $y = $cp + 8 | 0;
+ $8 = +HEAPF64[$y >> 3];
+ $mul10 = $8 * 2.0;
+ $y11 = $pp + 8 | 0;
+ $9 = +HEAPF64[$y11 >> 3];
+ $sub12 = $mul10 - $9;
+ $y13 = $np + 8 | 0;
+ HEAPF64[$y13 >> 3] = $sub12;
+ label = 7;
+ break;
+ case 6:
+ $10 = $np;
+ $11 = $nxt;
+ HEAP32[$10 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ $x16 = $cp | 0;
+ $12 = +HEAPF64[$x16 >> 3];
+ $mul17 = $12 * 2.0;
+ $x18 = $np | 0;
+ $13 = +HEAPF64[$x18 >> 3];
+ $sub19 = $mul17 - $13;
+ $x20 = $pp | 0;
+ HEAPF64[$x20 >> 3] = $sub19;
+ $y21 = $cp + 8 | 0;
+ $14 = +HEAPF64[$y21 >> 3];
+ $mul22 = $14 * 2.0;
+ $y23 = $np + 8 | 0;
+ $15 = +HEAPF64[$y23 >> 3];
+ $sub24 = $mul22 - $15;
+ $y25 = $pp + 8 | 0;
+ HEAPF64[$y25 >> 3] = $sub24;
+ label = 7;
+ break;
+ case 7:
+ $call = +_bisect($pp, $cp, $np);
+ $call27 = +Math_cos(+$call);
+ $mul28 = $call27 * $w2;
+ $call29 = +Math_sin(+$call);
+ $mul30 = $call29 * $w2;
+ $x31 = $cp | 0;
+ $16 = +HEAPF64[$x31 >> 3];
+ $add = $mul28 + $16;
+ $y33 = $cp + 8 | 0;
+ $17 = +HEAPF64[$y33 >> 3];
+ $add34 = $mul30 + $17;
+ $p_sroa_0_0__idx1 = $p1 | 0;
+ HEAPF64[$p_sroa_0_0__idx1 >> 3] = $add;
+ $p_sroa_1_8__idx4 = $p1 + 8 | 0;
+ HEAPF64[$p_sroa_1_8__idx4 >> 3] = $add34;
+ $18 = +HEAPF64[$x31 >> 3];
+ $sub37 = $18 - $mul28;
+ $19 = +HEAPF64[$y33 >> 3];
+ $sub40 = $19 - $mul30;
+ $p_sroa_0_0__idx = $p2 | 0;
+ HEAPF64[$p_sroa_0_0__idx >> 3] = $sub37;
+ $p_sroa_1_8__idx3 = $p2 + 8 | 0;
+ HEAPF64[$p_sroa_1_8__idx3 >> 3] = $sub40;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _map_bspline_poly($pbs_p, $pbs_n, $pbs_poly_n, $n, $p1, $p2) {
+ $pbs_p = $pbs_p | 0;
+ $pbs_n = $pbs_n | 0;
+ $pbs_poly_n = $pbs_poly_n | 0;
+ $n = $n | 0;
+ $p1 = $p1 | 0;
+ $p2 = $p2 | 0;
+ var $mul = 0, $sub = 0, $0 = 0, $cmp26 = 0, $1 = 0, $2 = 0, $3 = 0, $i_028 = 0, $nump_027 = 0, $arrayidx = 0, $4 = 0, $add = 0, $inc = 0, $cmp = 0, $smax = 0, $_lcssa = 0, $i_0_lcssa = 0, $nump_0_lcssa = 0, $inc1 = 0, $5 = 0, $6 = 0, $mul2 = 0, $call = 0, $7 = 0, $arrayidx4 = 0, $8 = 0, $9 = 0, $add6 = 0, $mul7 = 0, $call8 = 0, $10 = 0, $cmp1024 = 0, $add15 = 0, $i_125 = 0, $add12 = 0, $11 = 0, $arrayidx13 = 0, $arrayidx14 = 0, $12 = 0, $13 = 0, $sub16 = 0, $14 = 0, $arrayidx17 = 0, $arrayidx18 = 0, $15 = 0, $16 = 0, $inc20 = 0, $cmp10 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $mul = $n << 1;
+ $sub = $mul - 1 | 0;
+ $0 = HEAP32[$pbs_poly_n >> 2] | 0;
+ $cmp26 = ($0 | 0) > 0;
+ if ($cmp26) {
+ label = 3;
+ break;
+ } else {
+ $nump_0_lcssa = 0;
+ $i_0_lcssa = 0;
+ $_lcssa = $0;
+ label = 6;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[$pbs_n >> 2] | 0;
+ $2 = HEAP32[$pbs_poly_n >> 2] | 0;
+ $3 = ($2 | 0) > 1;
+ $nump_027 = 0;
+ $i_028 = 0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $1 + ($i_028 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $add = $4 + $nump_027 | 0;
+ $inc = $i_028 + 1 | 0;
+ $cmp = ($inc | 0) < ($2 | 0);
+ if ($cmp) {
+ $nump_027 = $add;
+ $i_028 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $smax = $3 ? $2 : 1;
+ $nump_0_lcssa = $add;
+ $i_0_lcssa = $smax;
+ $_lcssa = $2;
+ label = 6;
+ break;
+ case 6:
+ $inc1 = $_lcssa + 1 | 0;
+ HEAP32[$pbs_poly_n >> 2] = $inc1;
+ $5 = HEAP32[$pbs_n >> 2] | 0;
+ $6 = $5;
+ $mul2 = $inc1 << 2;
+ $call = _grealloc($6, $mul2) | 0;
+ $7 = $call;
+ HEAP32[$pbs_n >> 2] = $7;
+ $arrayidx4 = $7 + ($i_0_lcssa << 2) | 0;
+ HEAP32[$arrayidx4 >> 2] = $mul;
+ $8 = HEAP32[$pbs_p >> 2] | 0;
+ $9 = $8;
+ $add6 = $nump_0_lcssa + $mul | 0;
+ $mul7 = $add6 << 4;
+ $call8 = _grealloc($9, $mul7) | 0;
+ $10 = $call8;
+ HEAP32[$pbs_p >> 2] = $10;
+ $cmp1024 = ($n | 0) > 0;
+ if ($cmp1024) {
+ label = 7;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 7:
+ $add15 = $sub + $nump_0_lcssa | 0;
+ $i_125 = 0;
+ label = 8;
+ break;
+ case 8:
+ $add12 = $i_125 + $nump_0_lcssa | 0;
+ $11 = HEAP32[$pbs_p >> 2] | 0;
+ $arrayidx13 = $11 + ($add12 << 4) | 0;
+ $arrayidx14 = $p1 + ($i_125 << 4) | 0;
+ $12 = $arrayidx13;
+ $13 = $arrayidx14;
+ HEAP32[$12 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ $sub16 = $add15 - $i_125 | 0;
+ $14 = HEAP32[$pbs_p >> 2] | 0;
+ $arrayidx17 = $14 + ($sub16 << 4) | 0;
+ $arrayidx18 = $p2 + ($i_125 << 4) | 0;
+ $15 = $arrayidx17;
+ $16 = $arrayidx18;
+ HEAP32[$15 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ $inc20 = $i_125 + 1 | 0;
+ $cmp10 = ($inc20 | 0) < ($n | 0);
+ if ($cmp10) {
+ $i_125 = $inc20;
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _bisect($pp, $cp, $np) {
+ $pp = $pp | 0;
+ $cp = $cp | 0;
+ $np = $np | 0;
+ var $y = 0, $0 = 0.0, $y1 = 0, $1 = 0.0, $sub = 0.0, $x = 0, $2 = 0.0, $x2 = 0, $3 = 0.0, $sub3 = 0.0, $call = 0.0, $y4 = 0, $4 = 0.0, $sub6 = 0.0, $x7 = 0, $5 = 0.0, $sub9 = 0.0, $call10 = 0.0, $sub11 = 0.0, $cmp = 0, $sub12 = 0.0, $ang_0 = 0.0, $div = 0.0, $add = 0.0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $pp;
+ $pp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pp >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pp + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pp + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pp + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $cp;
+ $cp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$cp >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$cp + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$cp + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$cp + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $np;
+ $np = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$np >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$np + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$np + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$np + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $y = $np + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $y1 = $cp + 8 | 0;
+ $1 = +HEAPF64[$y1 >> 3];
+ $sub = $0 - $1;
+ $x = $np | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x2 = $cp | 0;
+ $3 = +HEAPF64[$x2 >> 3];
+ $sub3 = $2 - $3;
+ $call = +Math_atan2(+$sub, +$sub3);
+ $y4 = $pp + 8 | 0;
+ $4 = +HEAPF64[$y4 >> 3];
+ $sub6 = $4 - $1;
+ $x7 = $pp | 0;
+ $5 = +HEAPF64[$x7 >> 3];
+ $sub9 = $5 - $3;
+ $call10 = +Math_atan2(+$sub6, +$sub9);
+ $sub11 = $call - $call10;
+ $cmp = $sub11 > 0.0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $ang_0 = $sub11;
+ label = 4;
+ break;
+ }
+ case 3:
+ $sub12 = $sub11 - 6.283185307179586;
+ $ang_0 = $sub12;
+ label = 4;
+ break;
+ case 4:
+ $div = $ang_0 * .5;
+ $add = $call10 + $div;
+ STACKTOP = __stackBase__;
+ return +$add;
+ }
+ return 0.0;
+}
+function _appendSeg($p, $lp) {
+ $p = $p | 0;
+ $lp = $lp | 0;
+ var $call = 0, $0 = 0, $2 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $call = _gmalloc(24) | 0;
+ $0 = $call;
+ HEAP32[$call + 16 >> 2] = 0;
+ $2 = $p;
+ HEAP32[$call >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$call + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$call + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$call + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ HEAP32[$lp + 16 >> 2] = $0;
+ STACKTOP = __stackBase__;
+ return $0 | 0;
+}
+function _selectedlayer($job, $spec) {
+ $job = $job | 0;
+ $spec = $spec | 0;
+ var $buf = 0, $xb = 0, $gvc1 = 0, $0 = 0, $arraydecay = 0, $call = 0, $ptr = 0, $1 = 0, $eptr = 0, $2 = 0, $cmp = 0, $call2 = 0, $3 = 0, $buf4 = 0, $4 = 0, $layerDelims = 0, $5 = 0, $call6 = 0, $tobool = 0, $6 = 0, $call8 = 0, $w1_0 = 0, $conv = 0, $cmp10 = 0, $conv11 = 0, $add = 0, $layerNum = 0, $7 = 0, $call13 = 0, $8 = 0, $cmp15 = 0, $conv17 = 0, $call19 = 0, $numLayers = 0, $9 = 0, $call20 = 0, $10 = 0, $or_cond_not = 0, $cmp26 = 0, $or_cond21 = 0, $n0_0 = 0, $layerNum31 = 0, $11 = 0, $cmp32 = 0, $n1_0 = 0, $cmp35 = 0, $phitmp = 0, $rval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $xb = __stackBase__ + 128 | 0;
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $arraydecay = $buf | 0;
+ _agxbinit($xb, 128, $arraydecay);
+ $call = _agxbput($xb, $spec) | 0;
+ $ptr = $xb + 4 | 0;
+ $1 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $xb + 8 | 0;
+ $2 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $1 >>> 0 < $2 >>> 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call2 = _agxbmore($xb, 1) | 0;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[$ptr >> 2] | 0;
+ HEAP8[$3] = 0;
+ $buf4 = $xb | 0;
+ $4 = HEAP32[$buf4 >> 2] | 0;
+ HEAP32[$ptr >> 2] = $4;
+ $layerDelims = $0 + 272 | 0;
+ $5 = HEAP32[$layerDelims >> 2] | 0;
+ $call6 = _strtok($4 | 0, $5 | 0) | 0;
+ $tobool = ($call6 | 0) != 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $w1_0 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $6 = HEAP32[$layerDelims >> 2] | 0;
+ $call8 = _strtok(0, $6 | 0) | 0;
+ $w1_0 = $call8;
+ label = 6;
+ break;
+ case 6:
+ $conv = $tobool & 1;
+ $cmp10 = ($w1_0 | 0) != 0;
+ $conv11 = $cmp10 & 1;
+ $add = $conv11 + $conv | 0;
+ if (($add | 0) == 1) {
+ label = 7;
+ break;
+ } else if (($add | 0) == 2) {
+ label = 8;
+ break;
+ } else {
+ $rval_0 = 0;
+ label = 10;
+ break;
+ }
+ case 7:
+ $layerNum = $job + 160 | 0;
+ $7 = HEAP32[$layerNum >> 2] | 0;
+ $call13 = _layer_index($0, $call6, $7) | 0;
+ $8 = HEAP32[$layerNum >> 2] | 0;
+ $cmp15 = ($call13 | 0) == ($8 | 0);
+ $conv17 = $cmp15 & 1;
+ $rval_0 = $conv17;
+ label = 10;
+ break;
+ case 8:
+ $call19 = _layer_index($0, $call6, 0) | 0;
+ $numLayers = $job + 156 | 0;
+ $9 = HEAP32[$numLayers >> 2] | 0;
+ $call20 = _layer_index($0, $w1_0, $9) | 0;
+ $10 = $call20 | $call19;
+ $or_cond_not = ($10 | 0) > -1;
+ $cmp26 = ($call19 | 0) > ($call20 | 0);
+ $or_cond21 = $or_cond_not & $cmp26;
+ $n0_0 = $or_cond21 ? $call20 : $call19;
+ $layerNum31 = $job + 160 | 0;
+ $11 = HEAP32[$layerNum31 >> 2] | 0;
+ $cmp32 = ($n0_0 | 0) > ($11 | 0);
+ if ($cmp32) {
+ $rval_0 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $n1_0 = $or_cond21 ? $call19 : $call20;
+ $cmp35 = ($11 | 0) <= ($n1_0 | 0);
+ $phitmp = $cmp35 & 1;
+ $rval_0 = $phitmp;
+ label = 10;
+ break;
+ case 10:
+ _agxbfree($xb);
+ STACKTOP = __stackBase__;
+ return $rval_0 | 0;
+ }
+ return 0;
+}
+function _layer_index($gvc, $str, $all) {
+ $gvc = $gvc | 0;
+ $str = $str | 0;
+ $all = $all | 0;
+ var $job1 = 0, $0 = 0, $1 = 0, $cmp = 0, $call = 0, $tobool = 0, $call4 = 0, $tobool5 = 0, $call7 = 0, $layerIDs = 0, $2 = 0, $tobool9 = 0, $numLayers = 0, $3 = 0, $cmp1113 = 0, $4 = 0, $5 = 0, $i_014 = 0, $arrayidx = 0, $6 = 0, $7 = 0, $cmp16 = 0, $call21 = 0, $tobool22 = 0, $inc = 0, $8 = 0, $cmp11 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $job1 = $gvc + 124 | 0;
+ $0 = HEAP32[$job1 >> 2] | 0;
+ $1 = HEAP8[$str] | 0;
+ $cmp = $1 << 24 >> 24 == 97;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _strcmp($str | 0, 162624) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = $all;
+ label = 12;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call4 = _is_natural_number($str) | 0;
+ $tobool5 = $call4 << 24 >> 24 == 0;
+ if ($tobool5) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call7 = _atoi($str | 0) | 0;
+ $retval_0 = $call7;
+ label = 12;
+ break;
+ case 6:
+ $layerIDs = $gvc + 280 | 0;
+ $2 = HEAP32[$layerIDs >> 2] | 0;
+ $tobool9 = ($2 | 0) == 0;
+ if ($tobool9) {
+ $retval_0 = -1;
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $numLayers = $0 + 156 | 0;
+ $3 = HEAP32[$numLayers >> 2] | 0;
+ $cmp1113 = ($3 | 0) < 1;
+ if ($cmp1113) {
+ $retval_0 = -1;
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $4 = HEAP8[$str] | 0;
+ $5 = HEAP32[$layerIDs >> 2] | 0;
+ $i_014 = 1;
+ label = 9;
+ break;
+ case 9:
+ $arrayidx = $5 + ($i_014 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ $7 = HEAP8[$6] | 0;
+ $cmp16 = $4 << 24 >> 24 == $7 << 24 >> 24;
+ if ($cmp16) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $call21 = _strcmp($str | 0, $6 | 0) | 0;
+ $tobool22 = ($call21 | 0) == 0;
+ if ($tobool22) {
+ $retval_0 = $i_014;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $inc = $i_014 + 1 | 0;
+ $8 = HEAP32[$numLayers >> 2] | 0;
+ $cmp11 = ($inc | 0) > ($8 | 0);
+ if ($cmp11) {
+ $retval_0 = -1;
+ label = 12;
+ break;
+ } else {
+ $i_014 = $inc;
+ label = 9;
+ break;
+ }
+ case 12:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _node_in_layer($job, $g, $n) {
+ $job = $job | 0;
+ $g = $g | 0;
+ $n = $n | 0;
+ var $numLayers = 0, $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $call = 0, $call1 = 0, $tobool = 0, $3 = 0, $tobool4 = 0, $4 = 0, $5 = 0, $call7 = 0, $cmp8 = 0, $call11 = 0, $tobool1212 = 0, $e_0_in13 = 0, $6 = 0, $7 = 0, $call13 = 0, $8 = 0, $cmp15 = 0, $call17 = 0, $tobool19 = 0, $call22 = 0, $tobool12 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $numLayers = $job + 156 | 0;
+ $0 = HEAP32[$numLayers >> 2] | 0;
+ $cmp = ($0 | 0) < 2;
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $n | 0;
+ $2 = HEAP32[41586] | 0;
+ $call = _late_string($1, $2, 136112) | 0;
+ $call1 = _selectedlayer($job, $call) | 0;
+ $tobool = $call1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ }
+ case 4:
+ $3 = HEAP8[$call] | 0;
+ $tobool4 = $3 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ }
+ case 5:
+ $4 = $g;
+ $5 = $n;
+ $call7 = _agfstedge($4, $5) | 0;
+ $cmp8 = ($call7 | 0) == 0;
+ if ($cmp8) {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call11 = _agfstedge($4, $5) | 0;
+ $tobool1212 = ($call11 | 0) == 0;
+ if ($tobool1212) {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ } else {
+ $e_0_in13 = $call11;
+ label = 7;
+ break;
+ }
+ case 7:
+ $6 = $e_0_in13 | 0;
+ $7 = HEAP32[41920] | 0;
+ $call13 = _late_string($6, $7, 136112) | 0;
+ $8 = HEAP8[$call13] | 0;
+ $cmp15 = $8 << 24 >> 24 == 0;
+ if ($cmp15) {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call17 = _selectedlayer($job, $call13) | 0;
+ $tobool19 = $call17 << 24 >> 24 == 0;
+ if ($tobool19) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ }
+ case 9:
+ $call22 = _agnxtedge($4, $e_0_in13, $5) | 0;
+ $tobool12 = ($call22 | 0) == 0;
+ if ($tobool12) {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ } else {
+ $e_0_in13 = $call22;
+ label = 7;
+ break;
+ }
+ case 10:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _node_in_box($n, $b) {
+ $n = $n | 0;
+ $b = $b | 0;
+ var $conv = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ $conv = _boxf_overlap($n + 64 | 0, $b) & 255;
+ STACKTOP = __stackBase__;
+ return $conv | 0;
+}
+function _isRect($p) {
+ $p = $p | 0;
+ var $sides = 0, $0 = 0, $cmp = 0, $orientation = 0, $1 = 0.0, $cmp1 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $rem = 0, $cmp5 = 0, $distortion = 0, $2 = 0.0, $cmp8 = 0, $skew = 0, $3 = 0.0, $cmp10 = 0, $phitmp = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sides = $p + 8 | 0;
+ $0 = HEAP32[$sides >> 2] | 0;
+ $cmp = ($0 | 0) == 4;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $4 = 0;
+ label = 9;
+ break;
+ }
+ case 3:
+ $orientation = $p + 16 | 0;
+ $1 = +HEAPF64[$orientation >> 3];
+ $cmp1 = $1 < 0.0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $add = $1 + .5;
+ $add_sink = $add;
+ label = 6;
+ break;
+ case 5:
+ $sub = $1 + -.5;
+ $add_sink = $sub;
+ label = 6;
+ break;
+ case 6:
+ $conv = ~~$add_sink;
+ $rem = ($conv | 0) % 90;
+ $cmp5 = ($rem | 0) == 0;
+ if ($cmp5) {
+ label = 7;
+ break;
+ } else {
+ $4 = 0;
+ label = 9;
+ break;
+ }
+ case 7:
+ $distortion = $p + 24 | 0;
+ $2 = +HEAPF64[$distortion >> 3];
+ $cmp8 = $2 == 0.0;
+ if ($cmp8) {
+ label = 8;
+ break;
+ } else {
+ $4 = 0;
+ label = 9;
+ break;
+ }
+ case 8:
+ $skew = $p + 32 | 0;
+ $3 = +HEAPF64[$skew >> 3];
+ $cmp10 = $3 == 0.0;
+ $phitmp = $cmp10 & 1;
+ $4 = $phitmp;
+ label = 9;
+ break;
+ case 9:
+ return $4 | 0;
+ }
+ return 0;
+}
+function _add_point($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $add4 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ $add4 = (HEAP32[$q + 4 >> 2] | 0) + (HEAP32[$p + 4 >> 2] | 0) | 0;
+ HEAP32[$agg_result >> 2] = (HEAP32[$q >> 2] | 0) + (HEAP32[$p >> 2] | 0) | 0;
+ HEAP32[$agg_result + 4 >> 2] = $add4;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _emit_begin_node($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $flags1 = 0, $0 = 0, $call = 0, $type = 0, $1 = 0, $n_c = 0, $emit_state = 0, $and = 0, $tobool = 0, $graph = 0, $2 = 0, $odim = 0, $3 = 0, $cmp = 0, $pos = 0, $4 = 0, $arrayidx = 0, $5 = 0.0, $mul = 0.0, $cmp7 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv13 = 0, $conv19 = 0.0, $z = 0, $z20 = 0, $label = 0, $6 = 0, $7 = 0, $and23 = 0, $tobool24 = 0, $url = 0, $8 = 0, $tobool25 = 0, $9 = 0, $10 = 0, $11 = 0, $_mask = 0, $tobool26 = 0, $call28 = 0, $coord_sroa_0_0__idx = 0, $coord_sroa_0_0_copyload = 0.0, $coord_sroa_1_8__idx21 = 0, $coord_sroa_1_8_copyload = 0.0, $call31 = 0, $shape_info = 0, $12 = 0, $13 = 0, $call39 = 0, $tobool41 = 0, $peripheries43 = 0, $14 = 0, $15 = 0, $16 = 0, $phitmp = 0, $rect_0 = 0, $tobool50 = 0, $or_cond138 = 0, $and54 = 0, $tobool55 = 0, $sides57 = 0, $17 = 0, $18 = 0, $cmp58 = 0, $_ = 0, $peripheries64 = 0, $19 = 0, $20 = 0, $cmp65 = 0, $peripheries_0 = 0, $vertices71 = 0, $21 = 0, $22 = 0, $call72 = 0, $tobool73 = 0, $call75 = 0, $nump_0 = 0, $nump_0_off = 0, $23 = 0, $_nump_0 = 0, $24 = 0, $25 = 0, $26 = 0, $url_map_shape = 0, $call91 = 0, $27 = 0, $lw = 0, $28 = 0.0, $sub93 = 0.0, $x95 = 0, $ht = 0, $29 = 0.0, $div = 0.0, $sub97 = 0.0, $y99 = 0, $30 = 0, $31 = 0.0, $add103 = 0.0, $arrayidx104 = 0, $x105 = 0, $32 = 0.0, $div109 = 0.0, $add110 = 0.0, $y112 = 0, $33 = 0, $34 = 0, $cmp115 = 0, $skew = 0, $35 = 0, $36 = 0.0, $cmp118 = 0, $distortion = 0, $37 = 0, $38 = 0.0, $cmp121 = 0, $regular = 0, $39 = 0, $tobool124 = 0, $url_map_shape126 = 0, $call128 = 0, $40 = 0, $x131 = 0, $y134 = 0, $41 = 0, $mul136 = 0, $sub137 = 0, $x139 = 0, $42 = 0.0, $add140 = 0.0, $arrayidx141 = 0, $x142 = 0, $y147 = 0, $43 = 0.0, $add148 = 0.0, $y150 = 0, $44 = 0, $mul153 = 0, $sub154 = 0, $x156 = 0, $45 = 0.0, $y160 = 0, $46 = 0.0, $call161 = 0, $cmp162144 = 0, $i_0145 = 0, $x166 = 0, $47 = 0.0, $add167 = 0.0, $y170 = 0, $48 = 0.0, $add171 = 0.0, $inc = 0, $cmp162 = 0, $sub174 = 0, $49 = 0, $mul176 = 0, $url_map_shape177 = 0, $50 = 0, $cmp179 = 0, $div183 = 0, $mul184 = 0, $call185 = 0, $51 = 0, $cmp187150 = 0, $i_1152 = 0, $j_0151 = 0, $add191 = 0, $x193 = 0, $52 = 0.0, $add194 = 0.0, $x196 = 0, $y200 = 0, $53 = 0.0, $add201 = 0.0, $y203 = 0, $add205 = 0, $inc206 = 0, $cmp187 = 0, $mul209 = 0, $call210 = 0, $54 = 0, $cmp212147 = 0, $i_2148 = 0, $add216 = 0, $x218 = 0, $55 = 0.0, $add219 = 0.0, $x221 = 0, $y225 = 0, $56 = 0.0, $add226 = 0.0, $y228 = 0, $inc230 = 0, $cmp212 = 0, $url_map_shape236 = 0, $call238 = 0, $57 = 0, $lw241 = 0, $58 = 0.0, $sub242 = 0.0, $x244 = 0, $ht247 = 0, $59 = 0.0, $div248 = 0.0, $sub249 = 0.0, $y251 = 0, $60 = 0, $rw = 0, $61 = 0.0, $add254 = 0.0, $arrayidx255 = 0, $x256 = 0, $62 = 0.0, $div260 = 0.0, $add261 = 0.0, $y263 = 0, $63 = 0, $nump_2 = 0, $p_0 = 0, $and265 = 0, $tobool266 = 0, $call268 = 0, $url_map_p = 0, $url_map_n = 0, $call271 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $flags1 = $job + 152 | 0;
+ $0 = HEAP32[$flags1 >> 2] | 0;
+ $call = _push_obj_state($job) | 0;
+ $type = $call + 4 | 0;
+ HEAP32[$type >> 2] = 2;
+ $1 = $call + 8 | 0;
+ $n_c = $n;
+ HEAP32[$1 >> 2] = $n_c;
+ $emit_state = $call + 12 | 0;
+ HEAP32[$emit_state >> 2] = 8;
+ $and = $0 & 16777216;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $graph = $n + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $odim = $2 + 210 | 0;
+ $3 = HEAP16[$odim >> 1] | 0;
+ $cmp = ($3 & 65535) > 2;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $pos = $n + 148 | 0;
+ $4 = HEAP32[$pos >> 2] | 0;
+ $arrayidx = $4 + 16 | 0;
+ $5 = +HEAPF64[$arrayidx >> 3];
+ $mul = $5 * 72.0;
+ $cmp7 = $mul < 0.0;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add = $mul + .5;
+ $add_sink = $add;
+ label = 7;
+ break;
+ case 6:
+ $sub = $mul + -.5;
+ $add_sink = $sub;
+ label = 7;
+ break;
+ case 7:
+ $conv13 = ~~$add_sink;
+ $conv19 = +($conv13 | 0);
+ $z = $call + 120 | 0;
+ HEAPF64[$z >> 3] = $conv19;
+ label = 9;
+ break;
+ case 8:
+ $z20 = $call + 120 | 0;
+ HEAPF64[$z20 >> 3] = 0.0;
+ label = 9;
+ break;
+ case 9:
+ $label = $n + 120 | 0;
+ $6 = HEAP32[$label >> 2] | 0;
+ $7 = $n | 0;
+ _initObjMapData($job, $6, $7);
+ $and23 = $0 & 4259840;
+ $tobool24 = ($and23 | 0) == 0;
+ if ($tobool24) {
+ label = 37;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $url = $call + 160 | 0;
+ $8 = HEAP32[$url >> 2] | 0;
+ $tobool25 = ($8 | 0) == 0;
+ if ($tobool25) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $9 = $call + 212 | 0;
+ $10 = $9;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $_mask = $11 & 1;
+ $tobool26 = ($_mask | 0) == 0;
+ if ($tobool26) {
+ label = 37;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call28 = _shapeOf($n) | 0;
+ $coord_sroa_0_0__idx = $n + 32 | 0;
+ $coord_sroa_0_0_copyload = +HEAPF64[$coord_sroa_0_0__idx >> 3];
+ $coord_sroa_1_8__idx21 = $n + 40 | 0;
+ $coord_sroa_1_8_copyload = +HEAPF64[$coord_sroa_1_8__idx21 >> 3];
+ $call31 = _ifFilled($n) | 0;
+ if (($call28 | 0) == 3 | ($call28 | 0) == 1) {
+ label = 13;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 13:
+ $shape_info = $n + 28 | 0;
+ $12 = HEAP32[$shape_info >> 2] | 0;
+ $13 = $12;
+ $call39 = _isRect($13) | 0;
+ $tobool41 = $call39 << 24 >> 24 == 0;
+ if ($tobool41) {
+ $rect_0 = 1;
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $peripheries43 = $12 + 4 | 0;
+ $14 = $peripheries43;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $16 = $15 | $call31;
+ $phitmp = ($16 | 0) == 0;
+ $rect_0 = $phitmp;
+ label = 15;
+ break;
+ case 15:
+ $tobool50 = ($12 | 0) != 0;
+ $or_cond138 = $tobool50 & $rect_0;
+ if ($or_cond138) {
+ label = 16;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 16:
+ $and54 = $0 & 524288;
+ $tobool55 = ($and54 | 0) == 0;
+ if ($tobool55) {
+ label = 33;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $sides57 = $12 + 8 | 0;
+ $17 = $sides57;
+ $18 = HEAP32[$17 >> 2] | 0;
+ $cmp58 = ($18 | 0) < 3;
+ $_ = $cmp58 ? 1 : $18;
+ $peripheries64 = $12 + 4 | 0;
+ $19 = $peripheries64;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $cmp65 = ($20 | 0) > 1;
+ $peripheries_0 = $cmp65 ? $20 : 1;
+ $vertices71 = $12 + 44 | 0;
+ $21 = $vertices71;
+ $22 = HEAP32[$21 >> 2] | 0;
+ $call72 = _agget($7, 162160) | 0;
+ $tobool73 = ($call72 | 0) == 0;
+ if ($tobool73) {
+ $nump_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $call75 = _atoi($call72 | 0) | 0;
+ $nump_0 = $call75;
+ label = 19;
+ break;
+ case 19:
+ $nump_0_off = $nump_0 - 4 | 0;
+ $23 = $nump_0_off >>> 0 > 56;
+ $_nump_0 = $23 ? 20 : $nump_0;
+ $24 = HEAP32[$19 >> 2] | 0;
+ $25 = $24 | $call31;
+ $26 = ($25 | 0) == 0;
+ if ($26) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $url_map_shape = $call + 216 | 0;
+ HEAP32[$url_map_shape >> 2] = 0;
+ $call91 = _zmalloc(32) | 0;
+ $27 = $call91;
+ $lw = $n + 104 | 0;
+ $28 = +HEAPF64[$lw >> 3];
+ $sub93 = $coord_sroa_0_0_copyload - $28;
+ $x95 = $call91;
+ HEAPF64[$x95 >> 3] = $sub93;
+ $ht = $n + 96 | 0;
+ $29 = +HEAPF64[$ht >> 3];
+ $div = $29 * .5;
+ $sub97 = $coord_sroa_1_8_copyload - $div;
+ $y99 = $call91 + 8 | 0;
+ $30 = $y99;
+ HEAPF64[$30 >> 3] = $sub97;
+ $31 = +HEAPF64[$lw >> 3];
+ $add103 = $coord_sroa_0_0_copyload + $31;
+ $arrayidx104 = $call91 + 16 | 0;
+ $x105 = $arrayidx104;
+ HEAPF64[$x105 >> 3] = $add103;
+ $32 = +HEAPF64[$ht >> 3];
+ $div109 = $32 * .5;
+ $add110 = $coord_sroa_1_8_copyload + $div109;
+ $y112 = $call91 + 24 | 0;
+ $33 = $y112;
+ HEAPF64[$33 >> 3] = $add110;
+ $p_0 = $27;
+ $nump_2 = 2;
+ label = 34;
+ break;
+ case 21:
+ $34 = HEAP32[$17 >> 2] | 0;
+ $cmp115 = ($34 | 0) < 3;
+ if ($cmp115) {
+ label = 22;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 22:
+ $skew = $12 + 32 | 0;
+ $35 = $skew;
+ $36 = +HEAPF64[$35 >> 3];
+ $cmp118 = $36 == 0.0;
+ if ($cmp118) {
+ label = 23;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 23:
+ $distortion = $12 + 24 | 0;
+ $37 = $distortion;
+ $38 = +HEAPF64[$37 >> 3];
+ $cmp121 = $38 == 0.0;
+ if ($cmp121) {
+ label = 24;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 24:
+ $regular = $12;
+ $39 = HEAP32[$regular >> 2] | 0;
+ $tobool124 = ($39 | 0) == 0;
+ $url_map_shape126 = $call + 216 | 0;
+ if ($tobool124) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ HEAP32[$url_map_shape126 >> 2] = 1;
+ $call128 = _zmalloc(32) | 0;
+ $40 = $call128;
+ $x131 = $call128;
+ HEAPF64[$x131 >> 3] = $coord_sroa_0_0_copyload;
+ $y134 = $call128 + 8 | 0;
+ $41 = $y134;
+ HEAPF64[$41 >> 3] = $coord_sroa_1_8_copyload;
+ $mul136 = $peripheries_0 << 1;
+ $sub137 = $mul136 - 1 | 0;
+ $x139 = $22 + ($sub137 << 4) | 0;
+ $42 = +HEAPF64[$x139 >> 3];
+ $add140 = $coord_sroa_0_0_copyload + $42;
+ $arrayidx141 = $call128 + 16 | 0;
+ $x142 = $arrayidx141;
+ HEAPF64[$x142 >> 3] = $add140;
+ $y147 = $22 + ($sub137 << 4) + 8 | 0;
+ $43 = +HEAPF64[$y147 >> 3];
+ $add148 = $coord_sroa_1_8_copyload + $43;
+ $y150 = $call128 + 24 | 0;
+ $44 = $y150;
+ HEAPF64[$44 >> 3] = $add148;
+ $p_0 = $40;
+ $nump_2 = 2;
+ label = 34;
+ break;
+ case 26:
+ HEAP32[$url_map_shape126 >> 2] = 2;
+ $mul153 = $peripheries_0 << 1;
+ $sub154 = $mul153 - 1 | 0;
+ $x156 = $22 + ($sub154 << 4) | 0;
+ $45 = +HEAPF64[$x156 >> 3];
+ $y160 = $22 + ($sub154 << 4) + 8 | 0;
+ $46 = +HEAPF64[$y160 >> 3];
+ $call161 = _pEllipse($45, $46, $_nump_0) | 0;
+ $cmp162144 = ($_nump_0 | 0) > 0;
+ if ($cmp162144) {
+ $i_0145 = 0;
+ label = 27;
+ break;
+ } else {
+ $p_0 = $call161;
+ $nump_2 = $_nump_0;
+ label = 34;
+ break;
+ }
+ case 27:
+ $x166 = $call161 + ($i_0145 << 4) | 0;
+ $47 = +HEAPF64[$x166 >> 3];
+ $add167 = $coord_sroa_0_0_copyload + $47;
+ HEAPF64[$x166 >> 3] = $add167;
+ $y170 = $call161 + ($i_0145 << 4) + 8 | 0;
+ $48 = +HEAPF64[$y170 >> 3];
+ $add171 = $coord_sroa_1_8_copyload + $48;
+ HEAPF64[$y170 >> 3] = $add171;
+ $inc = $i_0145 + 1 | 0;
+ $cmp162 = ($inc | 0) < ($_nump_0 | 0);
+ if ($cmp162) {
+ $i_0145 = $inc;
+ label = 27;
+ break;
+ } else {
+ $p_0 = $call161;
+ $nump_2 = $_nump_0;
+ label = 34;
+ break;
+ }
+ case 28:
+ $sub174 = $peripheries_0 - 1 | 0;
+ $49 = HEAP32[$17 >> 2] | 0;
+ $mul176 = Math_imul($49, $sub174);
+ $url_map_shape177 = $call + 216 | 0;
+ HEAP32[$url_map_shape177 >> 2] = 2;
+ $50 = HEAP32[$17 >> 2] | 0;
+ $cmp179 = ($50 | 0) < ($_nump_0 | 0);
+ if ($cmp179) {
+ label = 31;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $div183 = ($50 | 0) / ($_nump_0 | 0) & -1;
+ $mul184 = $_nump_0 << 4;
+ $call185 = _zmalloc($mul184) | 0;
+ $51 = $call185;
+ $cmp187150 = ($_nump_0 | 0) > 0;
+ if ($cmp187150) {
+ $j_0151 = 0;
+ $i_1152 = 0;
+ label = 30;
+ break;
+ } else {
+ $p_0 = $51;
+ $nump_2 = $_nump_0;
+ label = 34;
+ break;
+ }
+ case 30:
+ $add191 = $i_1152 + $mul176 | 0;
+ $x193 = $22 + ($add191 << 4) | 0;
+ $52 = +HEAPF64[$x193 >> 3];
+ $add194 = $coord_sroa_0_0_copyload + $52;
+ $x196 = $51 + ($j_0151 << 4) | 0;
+ HEAPF64[$x196 >> 3] = $add194;
+ $y200 = $22 + ($add191 << 4) + 8 | 0;
+ $53 = +HEAPF64[$y200 >> 3];
+ $add201 = $coord_sroa_1_8_copyload + $53;
+ $y203 = $51 + ($j_0151 << 4) + 8 | 0;
+ HEAPF64[$y203 >> 3] = $add201;
+ $add205 = $i_1152 + $div183 | 0;
+ $inc206 = $j_0151 + 1 | 0;
+ $cmp187 = ($inc206 | 0) < ($_nump_0 | 0);
+ if ($cmp187) {
+ $j_0151 = $inc206;
+ $i_1152 = $add205;
+ label = 30;
+ break;
+ } else {
+ $p_0 = $51;
+ $nump_2 = $_nump_0;
+ label = 34;
+ break;
+ }
+ case 31:
+ $mul209 = $_ << 4;
+ $call210 = _zmalloc($mul209) | 0;
+ $54 = $call210;
+ $cmp212147 = ($_ | 0) > 0;
+ if ($cmp212147) {
+ $i_2148 = 0;
+ label = 32;
+ break;
+ } else {
+ $p_0 = $54;
+ $nump_2 = $_;
+ label = 34;
+ break;
+ }
+ case 32:
+ $add216 = $i_2148 + $mul176 | 0;
+ $x218 = $22 + ($add216 << 4) | 0;
+ $55 = +HEAPF64[$x218 >> 3];
+ $add219 = $coord_sroa_0_0_copyload + $55;
+ $x221 = $54 + ($i_2148 << 4) | 0;
+ HEAPF64[$x221 >> 3] = $add219;
+ $y225 = $22 + ($add216 << 4) + 8 | 0;
+ $56 = +HEAPF64[$y225 >> 3];
+ $add226 = $coord_sroa_1_8_copyload + $56;
+ $y228 = $54 + ($i_2148 << 4) + 8 | 0;
+ HEAPF64[$y228 >> 3] = $add226;
+ $inc230 = $i_2148 + 1 | 0;
+ $cmp212 = ($inc230 | 0) < ($_ | 0);
+ if ($cmp212) {
+ $i_2148 = $inc230;
+ label = 32;
+ break;
+ } else {
+ $p_0 = $54;
+ $nump_2 = $_;
+ label = 34;
+ break;
+ }
+ case 33:
+ $url_map_shape236 = $call + 216 | 0;
+ HEAP32[$url_map_shape236 >> 2] = 0;
+ $call238 = _zmalloc(32) | 0;
+ $57 = $call238;
+ $lw241 = $n + 104 | 0;
+ $58 = +HEAPF64[$lw241 >> 3];
+ $sub242 = $coord_sroa_0_0_copyload - $58;
+ $x244 = $call238;
+ HEAPF64[$x244 >> 3] = $sub242;
+ $ht247 = $n + 96 | 0;
+ $59 = +HEAPF64[$ht247 >> 3];
+ $div248 = $59 * .5;
+ $sub249 = $coord_sroa_1_8_copyload - $div248;
+ $y251 = $call238 + 8 | 0;
+ $60 = $y251;
+ HEAPF64[$60 >> 3] = $sub249;
+ $rw = $n + 112 | 0;
+ $61 = +HEAPF64[$rw >> 3];
+ $add254 = $coord_sroa_0_0_copyload + $61;
+ $arrayidx255 = $call238 + 16 | 0;
+ $x256 = $arrayidx255;
+ HEAPF64[$x256 >> 3] = $add254;
+ $62 = +HEAPF64[$ht247 >> 3];
+ $div260 = $62 * .5;
+ $add261 = $coord_sroa_1_8_copyload + $div260;
+ $y263 = $call238 + 24 | 0;
+ $63 = $y263;
+ HEAPF64[$63 >> 3] = $add261;
+ $p_0 = $57;
+ $nump_2 = 2;
+ label = 34;
+ break;
+ case 34:
+ $and265 = $0 & 8192;
+ $tobool266 = ($and265 | 0) == 0;
+ if ($tobool266) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ $call268 = _gvrender_ptf_A($job, $p_0, $p_0, $nump_2) | 0;
+ label = 36;
+ break;
+ case 36:
+ $url_map_p = $call + 224 | 0;
+ HEAP32[$url_map_p >> 2] = $p_0;
+ $url_map_n = $call + 220 | 0;
+ HEAP32[$url_map_n >> 2] = $nump_2;
+ label = 37;
+ break;
+ case 37:
+ $call271 = _agget($7, 133704) | 0;
+ _setColorScheme($call271);
+ _gvrender_begin_node($job, 0);
+ return;
+ }
+}
+function _emit_end_node($job) {
+ $job = $job | 0;
+ _gvrender_end_node($job);
+ _pop_obj_state($job);
+ return;
+}
+function _initObjMapData($job, $lab, $gobj) {
+ $job = $job | 0;
+ $lab = $lab | 0;
+ $gobj = $gobj | 0;
+ var $buf = 0, $xb = 0, $call = 0, $call1 = 0, $call2 = 0, $arraydecay = 0, $tobool = 0, $text = 0, $0 = 0, $lbl_0 = 0, $tobool3 = 0, $1 = 0, $tobool4 = 0, $call6 = 0, $url_0 = 0, $call8 = 0, $call9 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $xb = __stackBase__ + 128 | 0;
+ $call = _agget($gobj, 95856) | 0;
+ $call1 = _agget($gobj, 90704) | 0;
+ $call2 = _agget($gobj, 92456) | 0;
+ $arraydecay = $buf | 0;
+ _agxbinit($xb, 128, $arraydecay);
+ $tobool = ($lab | 0) == 0;
+ if ($tobool) {
+ $lbl_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $text = $lab | 0;
+ $0 = HEAP32[$text >> 2] | 0;
+ $lbl_0 = $0;
+ label = 4;
+ break;
+ case 4:
+ $tobool3 = ($call | 0) == 0;
+ if ($tobool3) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $1 = HEAP8[$call] | 0;
+ $tobool4 = $1 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ $url_0 = $call;
+ label = 7;
+ break;
+ }
+ case 6:
+ $call6 = _agget($gobj, 95472) | 0;
+ $url_0 = $call6;
+ label = 7;
+ break;
+ case 7:
+ $call8 = _getObjId($job, $gobj, $xb) | 0;
+ $call9 = _initMapData($job, $lbl_0, $url_0, $call1, $call2, $call8, $gobj) | 0;
+ _agxbfree($xb);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _ifFilled($n) {
+ $n = $n | 0;
+ var $0 = 0, $1 = 0, $call = 0, $2 = 0, $tobool = 0, $call1 = 0, $3 = 0, $tobool23 = 0, $4 = 0, $r_05 = 0, $pp_04 = 0, $call3 = 0, $cmp = 0, $_r_0 = 0, $incdec_ptr = 0, $5 = 0, $tobool2 = 0, $r_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $n | 0;
+ $1 = HEAP32[41560] | 0;
+ $call = _late_nnstring($0, $1, 136112) | 0;
+ $2 = HEAP8[$call] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ $r_2 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _parse_style($call) | 0;
+ $3 = HEAP32[1820] | 0;
+ $tobool23 = ($3 | 0) == 0;
+ if ($tobool23) {
+ $r_2 = 0;
+ label = 5;
+ break;
+ } else {
+ $pp_04 = 7280;
+ $r_05 = 0;
+ $4 = $3;
+ label = 4;
+ break;
+ }
+ case 4:
+ $call3 = _strcmp($4 | 0, 161792) | 0;
+ $cmp = ($call3 | 0) == 0;
+ $_r_0 = $cmp ? 1 : $r_05;
+ $incdec_ptr = $pp_04 + 4 | 0;
+ $5 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool2 = ($5 | 0) == 0;
+ if ($tobool2) {
+ $r_2 = $_r_0;
+ label = 5;
+ break;
+ } else {
+ $pp_04 = $incdec_ptr;
+ $r_05 = $_r_0;
+ $4 = $5;
+ label = 4;
+ break;
+ }
+ case 5:
+ return $r_2 | 0;
+ }
+ return 0;
+}
+function _pEllipse($a, $b, $np) {
+ $a = +$a;
+ $b = +$b;
+ $np = $np | 0;
+ var $conv = 0.0, $div = 0.0, $mul = 0, $call = 0, $0 = 0, $cmp10 = 0, $theta_012 = 0.0, $i_011 = 0, $call2 = 0.0, $mul3 = 0.0, $x = 0, $call4 = 0.0, $mul5 = 0.0, $y = 0, $add = 0.0, $inc = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $conv = +($np | 0);
+ $div = 6.283185307179586 / $conv;
+ $mul = $np << 4;
+ $call = _zmalloc($mul) | 0;
+ $0 = $call;
+ $cmp10 = ($np | 0) > 0;
+ if ($cmp10) {
+ $i_011 = 0;
+ $theta_012 = 0.0;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call2 = +Math_cos(+$theta_012);
+ $mul3 = $call2 * $a;
+ $x = $0 + ($i_011 << 4) | 0;
+ HEAPF64[$x >> 3] = $mul3;
+ $call4 = +Math_sin(+$theta_012);
+ $mul5 = $call4 * $b;
+ $y = $0 + ($i_011 << 4) + 8 | 0;
+ HEAPF64[$y >> 3] = $mul5;
+ $add = $div + $theta_012;
+ $inc = $i_011 + 1 | 0;
+ $cmp = ($inc | 0) < ($np | 0);
+ if ($cmp) {
+ $i_011 = $inc;
+ $theta_012 = $add;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ return $0 | 0;
+ }
+ return 0;
+}
+function _free_string_entry($dict, $key, $disc) {
+ $dict = $dict | 0;
+ $key = $key | 0;
+ $disc = $disc | 0;
+ _agstrfree($key);
+ return;
+}
+function _setup_page($job) {
+ $job = $job | 0;
+ var $pagesArrayElem = 0, $tmpcast = 0, $pagesArraySize = 0, $tmpcast1 = 0, $tmp = 0, $tmp3 = 0, $pagesArrayElem1 = 0, $0 = 0, $ld$0$0 = 0, $1$0 = 0, $ld$1$1 = 0, $1$1 = 0, $st$2$0 = 0, $st$3$1 = 0, $pagesArraySize2 = 0, $2 = 0, $ld$4$0 = 0, $3$0 = 0, $ld$5$1 = 0, $3$1 = 0, $st$6$0 = 0, $st$7$1 = 0, $rotation = 0, $4 = 0, $tobool = 0, $tmpcast3 = 0, $tmpcast2 = 0, $ld$8$0 = 0, $5$0 = 0, $ld$9$1 = 0, $5$1 = 0, $st$10$0 = 0, $st$11$1 = 0, $ld$12$0 = 0, $6$0 = 0, $ld$13$1 = 0, $6$1 = 0, $st$14$0 = 0, $st$15$1 = 0, $x = 0, $7 = 0, $conv = 0.0, $x4 = 0, $8 = 0.0, $mul = 0.0, $x5 = 0, $9 = 0.0, $sub = 0.0, $x6 = 0, $y = 0, $10 = 0, $conv7 = 0.0, $y9 = 0, $11 = 0.0, $mul10 = 0.0, $y12 = 0, $12 = 0.0, $sub13 = 0.0, $y16 = 0, $13 = 0.0, $14 = 0.0, $add = 0.0, $x23 = 0, $15 = 0.0, $16 = 0.0, $add29 = 0.0, $y32 = 0, $common = 0, $17 = 0, $viewNum = 0, $18 = 0, $cmp = 0, $boundingBox = 0, $pageBoundingBox = 0, $19 = 0, $20 = 0, $x37 = 0, $21 = 0, $x40 = 0, $22 = 0, $cmp41 = 0, $_ = 0, $y54 = 0, $23 = 0, $y57 = 0, $24 = 0, $cmp58 = 0, $cond69 = 0, $x75 = 0, $25 = 0, $x78 = 0, $26 = 0, $cmp79 = 0, $_4 = 0, $y96 = 0, $27 = 0, $y99 = 0, $28 = 0, $cmp100 = 0, $cond111 = 0, $flags = 0, $29 = 0, $and = 0, $tobool116 = 0, $x118 = 0, $30 = 0.0, $x119 = 0, $31 = 0.0, $div = 0.0, $sub120 = 0.0, $x122 = 0, $y124 = 0, $32 = 0.0, $y126 = 0, $33 = 0.0, $div127 = 0.0, $sub128 = 0.0, $y131 = 0, $34 = 0.0, $35 = 0.0, $div136 = 0.0, $add137 = 0.0, $x140 = 0, $36 = 0.0, $37 = 0.0, $div145 = 0.0, $add146 = 0.0, $y149 = 0, $38 = 0.0, $39 = 0, $conv156 = 0.0, $x157 = 0, $40 = 0, $conv158 = 0.0, $div159 = 0.0, $sub160 = 0.0, $mul161 = 0.0, $add162 = 0.0, $x165 = 0, $y167 = 0, $41 = 0.0, $42 = 0.0, $43 = 0, $conv171 = 0.0, $y172 = 0, $44 = 0, $conv173 = 0.0, $div174 = 0.0, $sub175 = 0.0, $mul176 = 0.0, $add177 = 0.0, $sub178 = 0.0, $y181 = 0, $45 = 0.0, $46 = 0.0, $add187 = 0.0, $add188 = 0.0, $x191 = 0, $47 = 0.0, $48 = 0.0, $add197 = 0.0, $add198 = 0.0, $y201 = 0, $49 = 0, $tobool204 = 0, $clip206 = 0, $y208 = 0, $50 = 0.0, $sub209 = 0.0, $LL210 = 0, $y211 = 0, $51 = 0.0, $zoom = 0, $52 = 0.0, $div212 = 0.0, $sub213 = 0.0, $translation = 0, $y214 = 0, $53 = 0, $and216 = 0, $54 = 0, $55 = 0, $56 = 0, $x222 = 0, $57 = 0.0, $sub223 = 0.0, $x226 = 0, $58 = 0.0, $59 = 0.0, $div228 = 0.0, $sub229 = 0.0, $x231 = 0, $x235 = 0, $60 = 0.0, $x239 = 0, $61 = 0.0, $62 = 0.0, $div241 = 0.0, $add242 = 0.0, $x244 = 0, $x249 = 0, $63 = 0.0, $x253 = 0, $64 = 0.0, $zoom254 = 0, $65 = 0.0, $div255 = 0.0, $add256 = 0.0, $x258 = 0, $66 = 0, $and260 = 0, $67 = 0, $68 = 0, $69 = 0, $y267 = 0, $70 = 0.0, $sub268 = 0.0, $y271 = 0, $71 = 0.0, $72 = 0.0, $div273 = 0.0, $sub274 = 0.0, $y276 = 0, $y280 = 0, $73 = 0.0, $y284 = 0, $74 = 0.0, $75 = 0.0, $div286 = 0.0, $add287 = 0.0, $y289 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pagesArrayElem = __stackBase__ | 0;
+ $tmpcast = $pagesArrayElem;
+ $pagesArraySize = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast1 = $pagesArraySize;
+ $tmp = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmp3 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $pagesArrayElem1 = $job + 196 | 0;
+ $0 = $pagesArrayElem1;
+ $ld$0$0 = $0 | 0;
+ $1$0 = HEAP32[$ld$0$0 >> 2] | 0;
+ $ld$1$1 = $0 + 4 | 0;
+ $1$1 = HEAP32[$ld$1$1 >> 2] | 0;
+ $st$2$0 = $pagesArrayElem | 0;
+ HEAP32[$st$2$0 >> 2] = $1$0;
+ $st$3$1 = $pagesArrayElem + 4 | 0;
+ HEAP32[$st$3$1 >> 2] = $1$1;
+ $pagesArraySize2 = $job + 164 | 0;
+ $2 = $pagesArraySize2;
+ $ld$4$0 = $2 | 0;
+ $3$0 = HEAP32[$ld$4$0 >> 2] | 0;
+ $ld$5$1 = $2 + 4 | 0;
+ $3$1 = HEAP32[$ld$5$1 >> 2] | 0;
+ $st$6$0 = $pagesArraySize | 0;
+ HEAP32[$st$6$0 >> 2] = $3$0;
+ $st$7$1 = $pagesArraySize + 4 | 0;
+ HEAP32[$st$7$1 >> 2] = $3$1;
+ $rotation = $job + 360 | 0;
+ $4 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tmpcast3 = $tmp3;
+ $tmpcast2 = $tmp;
+ _exch_xy($tmpcast2, $tmpcast);
+ $ld$8$0 = $tmp | 0;
+ $5$0 = HEAP32[$ld$8$0 >> 2] | 0;
+ $ld$9$1 = $tmp + 4 | 0;
+ $5$1 = HEAP32[$ld$9$1 >> 2] | 0;
+ $st$10$0 = $pagesArrayElem | 0;
+ HEAP32[$st$10$0 >> 2] = $5$0;
+ $st$11$1 = $pagesArrayElem + 4 | 0;
+ HEAP32[$st$11$1 >> 2] = $5$1;
+ _exch_xy($tmpcast3, $tmpcast1);
+ $ld$12$0 = $tmp3 | 0;
+ $6$0 = HEAP32[$ld$12$0 >> 2] | 0;
+ $ld$13$1 = $tmp3 + 4 | 0;
+ $6$1 = HEAP32[$ld$13$1 >> 2] | 0;
+ $st$14$0 = $pagesArraySize | 0;
+ HEAP32[$st$14$0 >> 2] = $6$0;
+ $st$15$1 = $pagesArraySize + 4 | 0;
+ HEAP32[$st$15$1 >> 2] = $6$1;
+ label = 4;
+ break;
+ case 4:
+ $x = $pagesArrayElem;
+ $7 = HEAP32[$x >> 2] | 0;
+ $conv = +($7 | 0);
+ $x4 = $job + 320 | 0;
+ $8 = +HEAPF64[$x4 >> 3];
+ $mul = $conv * $8;
+ $x5 = $job + 240 | 0;
+ $9 = +HEAPF64[$x5 >> 3];
+ $sub = $mul - $9;
+ $x6 = $job + 288 | 0;
+ HEAPF64[$x6 >> 3] = $sub;
+ $y = $tmpcast + 4 | 0;
+ $10 = HEAP32[$y >> 2] | 0;
+ $conv7 = +($10 | 0);
+ $y9 = $job + 328 | 0;
+ $11 = +HEAPF64[$y9 >> 3];
+ $mul10 = $conv7 * $11;
+ $y12 = $job + 248 | 0;
+ $12 = +HEAPF64[$y12 >> 3];
+ $sub13 = $mul10 - $12;
+ $y16 = $job + 296 | 0;
+ HEAPF64[$y16 >> 3] = $sub13;
+ $13 = +HEAPF64[$x6 >> 3];
+ $14 = +HEAPF64[$x4 >> 3];
+ $add = $13 + $14;
+ $x23 = $job + 304 | 0;
+ HEAPF64[$x23 >> 3] = $add;
+ $15 = +HEAPF64[$y16 >> 3];
+ $16 = +HEAPF64[$y9 >> 3];
+ $add29 = $15 + $16;
+ $y32 = $job + 312 | 0;
+ HEAPF64[$y32 >> 3] = $add29;
+ $common = $job + 12 | 0;
+ $17 = HEAP32[$common >> 2] | 0;
+ $viewNum = $17 + 28 | 0;
+ $18 = HEAP32[$viewNum >> 2] | 0;
+ $cmp = ($18 | 0) == 0;
+ $boundingBox = $job + 472 | 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $pageBoundingBox = $job + 456 | 0;
+ $19 = $boundingBox;
+ $20 = $pageBoundingBox;
+ HEAP32[$19 >> 2] = HEAP32[$20 >> 2] | 0;
+ HEAP32[$19 + 4 >> 2] = HEAP32[$20 + 4 >> 2] | 0;
+ HEAP32[$19 + 8 >> 2] = HEAP32[$20 + 8 >> 2] | 0;
+ HEAP32[$19 + 12 >> 2] = HEAP32[$20 + 12 >> 2] | 0;
+ label = 7;
+ break;
+ case 6:
+ $x37 = $boundingBox | 0;
+ $21 = HEAP32[$x37 >> 2] | 0;
+ $x40 = $job + 456 | 0;
+ $22 = HEAP32[$x40 >> 2] | 0;
+ $cmp41 = ($21 | 0) < ($22 | 0);
+ $_ = $cmp41 ? $21 : $22;
+ HEAP32[$x37 >> 2] = $_;
+ $y54 = $job + 476 | 0;
+ $23 = HEAP32[$y54 >> 2] | 0;
+ $y57 = $job + 460 | 0;
+ $24 = HEAP32[$y57 >> 2] | 0;
+ $cmp58 = ($23 | 0) < ($24 | 0);
+ $cond69 = $cmp58 ? $23 : $24;
+ HEAP32[$y54 >> 2] = $cond69;
+ $x75 = $job + 480 | 0;
+ $25 = HEAP32[$x75 >> 2] | 0;
+ $x78 = $job + 464 | 0;
+ $26 = HEAP32[$x78 >> 2] | 0;
+ $cmp79 = ($25 | 0) > ($26 | 0);
+ $_4 = $cmp79 ? $25 : $26;
+ HEAP32[$x75 >> 2] = $_4;
+ $y96 = $job + 484 | 0;
+ $27 = HEAP32[$y96 >> 2] | 0;
+ $y99 = $job + 468 | 0;
+ $28 = HEAP32[$y99 >> 2] | 0;
+ $cmp100 = ($27 | 0) > ($28 | 0);
+ $cond111 = $cmp100 ? $27 : $28;
+ HEAP32[$y96 >> 2] = $cond111;
+ label = 7;
+ break;
+ case 7:
+ $flags = $job + 152 | 0;
+ $29 = HEAP32[$flags >> 2] | 0;
+ $and = $29 & 128;
+ $tobool116 = ($and | 0) == 0;
+ $x118 = $job + 336 | 0;
+ $30 = +HEAPF64[$x118 >> 3];
+ if ($tobool116) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $x119 = $job + 368 | 0;
+ $31 = +HEAPF64[$x119 >> 3];
+ $div = $31 * .5;
+ $sub120 = $30 - $div;
+ $x122 = $job + 256 | 0;
+ HEAPF64[$x122 >> 3] = $sub120;
+ $y124 = $job + 344 | 0;
+ $32 = +HEAPF64[$y124 >> 3];
+ $y126 = $job + 376 | 0;
+ $33 = +HEAPF64[$y126 >> 3];
+ $div127 = $33 * .5;
+ $sub128 = $32 - $div127;
+ $y131 = $job + 264 | 0;
+ HEAPF64[$y131 >> 3] = $sub128;
+ $34 = +HEAPF64[$x118 >> 3];
+ $35 = +HEAPF64[$x119 >> 3];
+ $div136 = $35 * .5;
+ $add137 = $34 + $div136;
+ $x140 = $job + 272 | 0;
+ HEAPF64[$x140 >> 3] = $add137;
+ $36 = +HEAPF64[$y124 >> 3];
+ $37 = +HEAPF64[$y126 >> 3];
+ $div145 = $37 * .5;
+ $add146 = $36 + $div145;
+ $y149 = $job + 280 | 0;
+ HEAPF64[$y149 >> 3] = $add146;
+ label = 10;
+ break;
+ case 9:
+ $38 = +HEAPF64[$x4 >> 3];
+ $39 = HEAP32[$x >> 2] | 0;
+ $conv156 = +($39 | 0);
+ $x157 = $pagesArraySize;
+ $40 = HEAP32[$x157 >> 2] | 0;
+ $conv158 = +($40 | 0);
+ $div159 = $conv158 * .5;
+ $sub160 = $conv156 - $div159;
+ $mul161 = $38 * $sub160;
+ $add162 = $30 + $mul161;
+ $x165 = $job + 256 | 0;
+ HEAPF64[$x165 >> 3] = $add162;
+ $y167 = $job + 344 | 0;
+ $41 = +HEAPF64[$y167 >> 3];
+ $42 = +HEAPF64[$y9 >> 3];
+ $43 = HEAP32[$y >> 2] | 0;
+ $conv171 = +($43 | 0);
+ $y172 = $tmpcast1 + 4 | 0;
+ $44 = HEAP32[$y172 >> 2] | 0;
+ $conv173 = +($44 | 0);
+ $div174 = $conv173 * .5;
+ $sub175 = $conv171 - $div174;
+ $mul176 = $42 * $sub175;
+ $add177 = $41 + $mul176;
+ $sub178 = $add177 + -1.0;
+ $y181 = $job + 264 | 0;
+ HEAPF64[$y181 >> 3] = $sub178;
+ $45 = +HEAPF64[$x165 >> 3];
+ $46 = +HEAPF64[$x4 >> 3];
+ $add187 = $45 + $46;
+ $add188 = $add187 + 1.0;
+ $x191 = $job + 272 | 0;
+ HEAPF64[$x191 >> 3] = $add188;
+ $47 = +HEAPF64[$y181 >> 3];
+ $48 = +HEAPF64[$y9 >> 3];
+ $add197 = $47 + $48;
+ $add198 = $add197 + 1.0;
+ $y201 = $job + 280 | 0;
+ HEAPF64[$y201 >> 3] = $add198;
+ label = 10;
+ break;
+ case 10:
+ $49 = HEAP32[$rotation >> 2] | 0;
+ $tobool204 = ($49 | 0) == 0;
+ $clip206 = $job + 256 | 0;
+ if ($tobool204) {
+ label = 14;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $y208 = $job + 280 | 0;
+ $50 = +HEAPF64[$y208 >> 3];
+ $sub209 = -0.0 - $50;
+ $LL210 = $job + 384 | 0;
+ $y211 = $job + 392 | 0;
+ $51 = +HEAPF64[$y211 >> 3];
+ $zoom = $job + 352 | 0;
+ $52 = +HEAPF64[$zoom >> 3];
+ $div212 = $51 / $52;
+ $sub213 = $sub209 - $div212;
+ $translation = $job + 504 | 0;
+ $y214 = $job + 512 | 0;
+ HEAPF64[$y214 >> 3] = $sub213;
+ $53 = HEAP32[$flags >> 2] | 0;
+ $and216 = $53 & 4096;
+ $54 = HEAP32[41182] | 0;
+ $55 = $and216 | $54;
+ $56 = ($55 | 0) == 0;
+ if ($56) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $x222 = $job + 272 | 0;
+ $57 = +HEAPF64[$x222 >> 3];
+ $sub223 = -0.0 - $57;
+ $x226 = $LL210 | 0;
+ $58 = +HEAPF64[$x226 >> 3];
+ $59 = +HEAPF64[$zoom >> 3];
+ $div228 = $58 / $59;
+ $sub229 = $sub223 - $div228;
+ $x231 = $translation | 0;
+ HEAPF64[$x231 >> 3] = $sub229;
+ label = 17;
+ break;
+ case 13:
+ $x235 = $clip206 | 0;
+ $60 = +HEAPF64[$x235 >> 3];
+ $x239 = $LL210 | 0;
+ $61 = +HEAPF64[$x239 >> 3];
+ $62 = +HEAPF64[$zoom >> 3];
+ $div241 = $61 / $62;
+ $add242 = $div241 - $60;
+ $x244 = $translation | 0;
+ HEAPF64[$x244 >> 3] = $add242;
+ label = 17;
+ break;
+ case 14:
+ $x249 = $clip206 | 0;
+ $63 = +HEAPF64[$x249 >> 3];
+ $x253 = $job + 384 | 0;
+ $64 = +HEAPF64[$x253 >> 3];
+ $zoom254 = $job + 352 | 0;
+ $65 = +HEAPF64[$zoom254 >> 3];
+ $div255 = $64 / $65;
+ $add256 = $div255 - $63;
+ $x258 = $job + 504 | 0;
+ HEAPF64[$x258 >> 3] = $add256;
+ $66 = HEAP32[$flags >> 2] | 0;
+ $and260 = $66 & 4096;
+ $67 = HEAP32[41182] | 0;
+ $68 = $and260 | $67;
+ $69 = ($68 | 0) == 0;
+ if ($69) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $y267 = $job + 280 | 0;
+ $70 = +HEAPF64[$y267 >> 3];
+ $sub268 = -0.0 - $70;
+ $y271 = $job + 392 | 0;
+ $71 = +HEAPF64[$y271 >> 3];
+ $72 = +HEAPF64[$zoom254 >> 3];
+ $div273 = $71 / $72;
+ $sub274 = $sub268 - $div273;
+ $y276 = $job + 512 | 0;
+ HEAPF64[$y276 >> 3] = $sub274;
+ label = 17;
+ break;
+ case 16:
+ $y280 = $job + 264 | 0;
+ $73 = +HEAPF64[$y280 >> 3];
+ $y284 = $job + 392 | 0;
+ $74 = +HEAPF64[$y284 >> 3];
+ $75 = +HEAPF64[$zoom254 >> 3];
+ $div286 = $74 / $75;
+ $add287 = $div286 - $73;
+ $y289 = $job + 512 | 0;
+ HEAPF64[$y289 >> 3] = $add287;
+ label = 17;
+ break;
+ case 17:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_background($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $1 = 0, $tobool1 = 0, $_call = 0, $_ = 0, $str_0 = 0, $dfltColor_0 = 0, $flags = 0, $2 = 0, $and = 0, $tobool2 = 0, $3 = 0, $cmp = 0, $call8 = 0, $tobool9 = 0, $_str_0 = 0, $str_1 = 0, $4 = 0, $and13 = 0, $tobool14 = 0, $5 = 0, $cmp18 = 0, $call21 = 0, $tobool22 = 0, $6 = 0, $and24 = 0, $tobool25 = 0, $tobool27 = 0, $or_cond = 0, $clip = 0, $drawing = 0, $7 = 0, $xdots = 0, $8 = 0, $tobool30 = 0, $9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g | 0;
+ $call = _agget($0, 118488) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $dfltColor_0 = 1;
+ $str_0 = 160560;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$call] | 0;
+ $tobool1 = $1 << 24 >> 24 == 0;
+ $_call = $tobool1 ? 160560 : $call;
+ $_ = $tobool1 & 1;
+ $dfltColor_0 = $_;
+ $str_0 = $_call;
+ label = 4;
+ break;
+ case 4:
+ $flags = $job + 152 | 0;
+ $2 = HEAP32[$flags >> 2] | 0;
+ $and = $2 & 256;
+ $tobool2 = ($and | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ $str_1 = $str_0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $3 = HEAP8[$str_0] | 0;
+ $cmp = $3 << 24 >> 24 == 116;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ $str_1 = $str_0;
+ label = 7;
+ break;
+ }
+ case 6:
+ $call8 = _strcmp($str_0 | 0, 160216) | 0;
+ $tobool9 = ($call8 | 0) == 0;
+ $_str_0 = $tobool9 ? 160560 : $str_0;
+ $str_1 = $_str_0;
+ label = 7;
+ break;
+ case 7:
+ $4 = HEAP32[$flags >> 2] | 0;
+ $and13 = $4 & 256;
+ $tobool14 = ($and13 | 0) == 0;
+ if ($tobool14) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $5 = HEAP8[$str_1] | 0;
+ $cmp18 = $5 << 24 >> 24 == 116;
+ if ($cmp18) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $call21 = _strcmp($str_1 | 0, 160216) | 0;
+ $tobool22 = ($call21 | 0) == 0;
+ if ($tobool22) {
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $6 = HEAP32[$flags >> 2] | 0;
+ $and24 = $6 & 33554432;
+ $tobool25 = ($and24 | 0) == 0;
+ $tobool27 = ($dfltColor_0 | 0) == 0;
+ $or_cond = $tobool25 | $tobool27;
+ if ($or_cond) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ _gvrender_set_fillcolor($job, $str_1);
+ _gvrender_set_pencolor($job, $str_1);
+ $clip = $job + 256 | 0;
+ _gvrender_box($job, $clip, 1);
+ label = 12;
+ break;
+ case 12:
+ $drawing = $g + 48 | 0;
+ $7 = HEAP32[$drawing >> 2] | 0;
+ $xdots = $7 + 88 | 0;
+ $8 = HEAP32[$xdots >> 2] | 0;
+ $tobool30 = ($8 | 0) == 0;
+ if ($tobool30) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $9 = $8;
+ _emit_xdot($job, $9);
+ label = 14;
+ break;
+ case 14:
+ return;
+ }
+}
+function _enqueue($q, $n) {
+ $q = $q | 0;
+ $n = $n | 0;
+ var $tail = 0, $0 = 0, $incdec_ptr = 0, $1 = 0, $limit = 0, $2 = 0, $cmp = 0, $store = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $q + 12 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $incdec_ptr = $0 + 4 | 0;
+ HEAP32[$tail >> 2] = $incdec_ptr;
+ HEAP32[$0 >> 2] = $n;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $limit = $q + 4 | 0;
+ $2 = HEAP32[$limit >> 2] | 0;
+ $cmp = $1 >>> 0 < $2 >>> 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $store = $q | 0;
+ $3 = HEAP32[$store >> 2] | 0;
+ HEAP32[$tail >> 2] = $3;
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _dequeue($q) {
+ $q = $q | 0;
+ var $head = 0, $0 = 0, $tail = 0, $1 = 0, $cmp = 0, $incdec_ptr = 0, $2 = 0, $limit = 0, $3 = 0, $cmp3 = 0, $store = 0, $4 = 0, $n_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $head = $q + 8 | 0;
+ $0 = HEAP32[$head >> 2] | 0;
+ $tail = $q + 12 | 0;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $cmp = ($0 | 0) == ($1 | 0);
+ if ($cmp) {
+ $n_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $incdec_ptr = $0 + 4 | 0;
+ HEAP32[$head >> 2] = $incdec_ptr;
+ $2 = HEAP32[$0 >> 2] | 0;
+ $limit = $q + 4 | 0;
+ $3 = HEAP32[$limit >> 2] | 0;
+ $cmp3 = $incdec_ptr >>> 0 < $3 >>> 0;
+ if ($cmp3) {
+ $n_0 = $2;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $store = $q | 0;
+ $4 = HEAP32[$store >> 2] | 0;
+ HEAP32[$head >> 2] = $4;
+ $n_0 = $2;
+ label = 5;
+ break;
+ case 5:
+ return $n_0 | 0;
+ }
+ return 0;
+}
+function _UF_find($n) {
+ $n = $n | 0;
+ var $UF_parent7 = 0, $0 = 0, $cmp8 = 0, $not_tobool9 = 0, $_cmp10 = 0, $1 = 0, $UF_parent11 = 0, $UF_parent6 = 0, $2 = 0, $tobool7 = 0, $3 = 0, $UF_parent = 0, $4 = 0, $cmp = 0, $not_tobool = 0, $_cmp = 0, $n_addr_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $UF_parent7 = $n + 224 | 0;
+ $0 = HEAP32[$UF_parent7 >> 2] | 0;
+ $cmp8 = ($0 | 0) != ($n | 0);
+ $not_tobool9 = ($0 | 0) != 0;
+ $_cmp10 = $cmp8 & $not_tobool9;
+ if ($_cmp10) {
+ $UF_parent11 = $UF_parent7;
+ $1 = $0;
+ label = 3;
+ break;
+ } else {
+ $n_addr_0_lcssa = $n;
+ label = 6;
+ break;
+ }
+ case 3:
+ $UF_parent6 = $1 + 224 | 0;
+ $2 = HEAP32[$UF_parent6 >> 2] | 0;
+ $tobool7 = ($2 | 0) == 0;
+ if ($tobool7) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAP32[$UF_parent11 >> 2] = $2;
+ label = 5;
+ break;
+ case 5:
+ $3 = HEAP32[$UF_parent11 >> 2] | 0;
+ $UF_parent = $3 + 224 | 0;
+ $4 = HEAP32[$UF_parent >> 2] | 0;
+ $cmp = ($4 | 0) != ($3 | 0);
+ $not_tobool = ($4 | 0) != 0;
+ $_cmp = $cmp & $not_tobool;
+ if ($_cmp) {
+ $UF_parent11 = $UF_parent;
+ $1 = $4;
+ label = 3;
+ break;
+ } else {
+ $n_addr_0_lcssa = $3;
+ label = 6;
+ break;
+ }
+ case 6:
+ return $n_addr_0_lcssa | 0;
+ }
+ return 0;
+}
+function _UF_singleton($u) {
+ $u = $u | 0;
+ HEAP32[$u + 220 >> 2] = 1;
+ HEAP32[$u + 224 >> 2] = 0;
+ HEAP8[$u + 165 | 0] = 0;
+ return;
+}
+function _emit_view($job, $g, $flags) {
+ $job = $job | 0;
+ $g = $g | 0;
+ $flags = $flags | 0;
+ var $gvc1 = 0, $0 = 0, $viewNum = 0, $1 = 0, $inc = 0, $and = 0, $tobool = 0, $and2 = 0, $tobool3 = 0, $2 = 0, $call = 0, $tobool5111 = 0, $n_0_in112 = 0, $n_0 = 0, $call6 = 0, $tobool5 = 0, $call7 = 0, $tobool9109 = 0, $n_1_in110 = 0, $call11 = 0, $tobool13107 = 0, $e_0_in108 = 0, $e_0 = 0, $call16 = 0, $tobool13 = 0, $call19 = 0, $tobool9 = 0, $and21 = 0, $tobool22 = 0, $3 = 0, $call24 = 0, $tobool26105 = 0, $n_2_in106 = 0, $call28 = 0, $tobool30103 = 0, $e_1_in104 = 0, $e_1 = 0, $call33 = 0, $tobool30 = 0, $call36 = 0, $tobool26 = 0, $call38 = 0, $tobool40101 = 0, $n_3_in102 = 0, $n_3 = 0, $call43 = 0, $tobool40 = 0, $and46 = 0, $tobool47 = 0, $4 = 0, $call49 = 0, $tobool5198 = 0, $n_4100_in = 0, $n_4100 = 0, $call53 = 0, $tobool54 = 0, $call58 = 0, $tobool51 = 0, $call60 = 0, $tobool6295 = 0, $n_5_in96 = 0, $call64 = 0, $tobool6692 = 0, $e_294_in = 0, $e_294 = 0, $call68 = 0, $tobool69 = 0, $call73 = 0, $tobool66 = 0, $call76 = 0, $tobool62 = 0, $5 = 0, $call79 = 0, $tobool8189 = 0, $n_6_in90 = 0, $n_6 = 0, $call83 = 0, $tobool8587 = 0, $e_3_in88 = 0, $e_3 = 0, $head = 0, $6 = 0, $7 = 0, $call88 = 0, $tobool85 = 0, $call91 = 0, $tobool81 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $viewNum = $0 + 28 | 0;
+ $1 = HEAP32[$viewNum >> 2] | 0;
+ $inc = $1 + 1 | 0;
+ HEAP32[$viewNum >> 2] = $inc;
+ $and = $flags & 4;
+ $tobool = ($and | 0) != 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _emit_clusters($job, $g, $flags);
+ label = 4;
+ break;
+ case 4:
+ $and2 = $flags & 1;
+ $tobool3 = ($and2 | 0) == 0;
+ if ($tobool3) {
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _gvrender_begin_nodes($job);
+ $2 = $g;
+ $call = _agfstnode($2) | 0;
+ $tobool5111 = ($call | 0) == 0;
+ if ($tobool5111) {
+ label = 7;
+ break;
+ } else {
+ $n_0_in112 = $call;
+ label = 6;
+ break;
+ }
+ case 6:
+ $n_0 = $n_0_in112;
+ _emit_node($job, $n_0);
+ $call6 = _agnxtnode($2, $n_0_in112) | 0;
+ $tobool5 = ($call6 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ $n_0_in112 = $call6;
+ label = 6;
+ break;
+ }
+ case 7:
+ _gvrender_end_nodes($job);
+ _gvrender_begin_edges($job);
+ $call7 = _agfstnode($2) | 0;
+ $tobool9109 = ($call7 | 0) == 0;
+ if ($tobool9109) {
+ label = 11;
+ break;
+ } else {
+ $n_1_in110 = $call7;
+ label = 8;
+ break;
+ }
+ case 8:
+ $call11 = _agfstout($2, $n_1_in110) | 0;
+ $tobool13107 = ($call11 | 0) == 0;
+ if ($tobool13107) {
+ label = 10;
+ break;
+ } else {
+ $e_0_in108 = $call11;
+ label = 9;
+ break;
+ }
+ case 9:
+ $e_0 = $e_0_in108;
+ _emit_edge($job, $e_0);
+ $call16 = _agnxtout($2, $e_0_in108) | 0;
+ $tobool13 = ($call16 | 0) == 0;
+ if ($tobool13) {
+ label = 10;
+ break;
+ } else {
+ $e_0_in108 = $call16;
+ label = 9;
+ break;
+ }
+ case 10:
+ $call19 = _agnxtnode($2, $n_1_in110) | 0;
+ $tobool9 = ($call19 | 0) == 0;
+ if ($tobool9) {
+ label = 11;
+ break;
+ } else {
+ $n_1_in110 = $call19;
+ label = 8;
+ break;
+ }
+ case 11:
+ _gvrender_end_edges($job);
+ label = 36;
+ break;
+ case 12:
+ $and21 = $flags & 16;
+ $tobool22 = ($and21 | 0) == 0;
+ if ($tobool22) {
+ label = 20;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _gvrender_begin_edges($job);
+ $3 = $g;
+ $call24 = _agfstnode($3) | 0;
+ $tobool26105 = ($call24 | 0) == 0;
+ if ($tobool26105) {
+ label = 17;
+ break;
+ } else {
+ $n_2_in106 = $call24;
+ label = 14;
+ break;
+ }
+ case 14:
+ $call28 = _agfstout($3, $n_2_in106) | 0;
+ $tobool30103 = ($call28 | 0) == 0;
+ if ($tobool30103) {
+ label = 16;
+ break;
+ } else {
+ $e_1_in104 = $call28;
+ label = 15;
+ break;
+ }
+ case 15:
+ $e_1 = $e_1_in104;
+ _emit_edge($job, $e_1);
+ $call33 = _agnxtout($3, $e_1_in104) | 0;
+ $tobool30 = ($call33 | 0) == 0;
+ if ($tobool30) {
+ label = 16;
+ break;
+ } else {
+ $e_1_in104 = $call33;
+ label = 15;
+ break;
+ }
+ case 16:
+ $call36 = _agnxtnode($3, $n_2_in106) | 0;
+ $tobool26 = ($call36 | 0) == 0;
+ if ($tobool26) {
+ label = 17;
+ break;
+ } else {
+ $n_2_in106 = $call36;
+ label = 14;
+ break;
+ }
+ case 17:
+ _gvrender_end_edges($job);
+ _gvrender_begin_nodes($job);
+ $call38 = _agfstnode($3) | 0;
+ $tobool40101 = ($call38 | 0) == 0;
+ if ($tobool40101) {
+ label = 19;
+ break;
+ } else {
+ $n_3_in102 = $call38;
+ label = 18;
+ break;
+ }
+ case 18:
+ $n_3 = $n_3_in102;
+ _emit_node($job, $n_3);
+ $call43 = _agnxtnode($3, $n_3_in102) | 0;
+ $tobool40 = ($call43 | 0) == 0;
+ if ($tobool40) {
+ label = 19;
+ break;
+ } else {
+ $n_3_in102 = $call43;
+ label = 18;
+ break;
+ }
+ case 19:
+ _gvrender_end_nodes($job);
+ label = 36;
+ break;
+ case 20:
+ $and46 = $flags & 8;
+ $tobool47 = ($and46 | 0) == 0;
+ if ($tobool47) {
+ label = 32;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ _gvrender_begin_nodes($job);
+ $4 = $g;
+ $call49 = _agfstnode($4) | 0;
+ $tobool5198 = ($call49 | 0) == 0;
+ if ($tobool5198) {
+ label = 25;
+ break;
+ } else {
+ $n_4100_in = $call49;
+ label = 22;
+ break;
+ }
+ case 22:
+ $n_4100 = $n_4100_in;
+ $call53 = _write_node_test($g, $n_4100) | 0;
+ $tobool54 = $call53 << 24 >> 24 == 0;
+ if ($tobool54) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ _emit_node($job, $n_4100);
+ label = 24;
+ break;
+ case 24:
+ $call58 = _agnxtnode($4, $n_4100_in) | 0;
+ $tobool51 = ($call58 | 0) == 0;
+ if ($tobool51) {
+ label = 25;
+ break;
+ } else {
+ $n_4100_in = $call58;
+ label = 22;
+ break;
+ }
+ case 25:
+ _gvrender_end_nodes($job);
+ _gvrender_begin_edges($job);
+ $call60 = _agfstnode($4) | 0;
+ $tobool6295 = ($call60 | 0) == 0;
+ if ($tobool6295) {
+ label = 31;
+ break;
+ } else {
+ $n_5_in96 = $call60;
+ label = 26;
+ break;
+ }
+ case 26:
+ $call64 = _agfstout($4, $n_5_in96) | 0;
+ $tobool6692 = ($call64 | 0) == 0;
+ if ($tobool6692) {
+ label = 30;
+ break;
+ } else {
+ $e_294_in = $call64;
+ label = 27;
+ break;
+ }
+ case 27:
+ $e_294 = $e_294_in;
+ $call68 = _write_edge_test($g, $e_294) | 0;
+ $tobool69 = $call68 << 24 >> 24 == 0;
+ if ($tobool69) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ _emit_edge($job, $e_294);
+ label = 29;
+ break;
+ case 29:
+ $call73 = _agnxtout($4, $e_294_in) | 0;
+ $tobool66 = ($call73 | 0) == 0;
+ if ($tobool66) {
+ label = 30;
+ break;
+ } else {
+ $e_294_in = $call73;
+ label = 27;
+ break;
+ }
+ case 30:
+ $call76 = _agnxtnode($4, $n_5_in96) | 0;
+ $tobool62 = ($call76 | 0) == 0;
+ if ($tobool62) {
+ label = 31;
+ break;
+ } else {
+ $n_5_in96 = $call76;
+ label = 26;
+ break;
+ }
+ case 31:
+ _gvrender_end_edges($job);
+ label = 36;
+ break;
+ case 32:
+ $5 = $g;
+ $call79 = _agfstnode($5) | 0;
+ $tobool8189 = ($call79 | 0) == 0;
+ if ($tobool8189) {
+ label = 36;
+ break;
+ } else {
+ $n_6_in90 = $call79;
+ label = 33;
+ break;
+ }
+ case 33:
+ $n_6 = $n_6_in90;
+ _emit_node($job, $n_6);
+ $call83 = _agfstout($5, $n_6_in90) | 0;
+ $tobool8587 = ($call83 | 0) == 0;
+ if ($tobool8587) {
+ label = 35;
+ break;
+ } else {
+ $e_3_in88 = $call83;
+ label = 34;
+ break;
+ }
+ case 34:
+ $e_3 = $e_3_in88;
+ $head = $e_3_in88 + 12 | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ $7 = $6;
+ _emit_node($job, $7);
+ _emit_edge($job, $e_3);
+ $call88 = _agnxtout($5, $e_3_in88) | 0;
+ $tobool85 = ($call88 | 0) == 0;
+ if ($tobool85) {
+ label = 35;
+ break;
+ } else {
+ $e_3_in88 = $call88;
+ label = 34;
+ break;
+ }
+ case 35:
+ $call91 = _agnxtnode($5, $n_6_in90) | 0;
+ $tobool81 = ($call91 | 0) == 0;
+ if ($tobool81) {
+ label = 36;
+ break;
+ } else {
+ $n_6_in90 = $call91;
+ label = 33;
+ break;
+ }
+ case 36:
+ if ($tobool) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ _emit_clusters($job, $g, $flags);
+ label = 38;
+ break;
+ case 38:
+ return;
+ }
+}
+function _write_node_test($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $clust = 0, $n_cluster = 0, $0 = 0, $c_0 = 0, $1 = 0, $cmp = 0, $2 = 0, $arrayidx = 0, $3 = 0, $4 = 0, $call = 0, $tobool = 0, $inc = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $clust = $g + 216 | 0;
+ $n_cluster = $g + 212 | 0;
+ $0 = $n | 0;
+ $c_0 = 1;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($c_0 | 0) > ($1 | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $2 + ($c_0 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $4 = $3;
+ $call = _agcontains($4, $0) | 0;
+ $tobool = ($call | 0) == 0;
+ $inc = $c_0 + 1 | 0;
+ if ($tobool) {
+ $c_0 = $inc;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _write_edge_test($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $clust = 0, $n_cluster = 0, $0 = 0, $c_0 = 0, $1 = 0, $cmp = 0, $2 = 0, $arrayidx = 0, $3 = 0, $4 = 0, $call = 0, $tobool = 0, $inc = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $clust = $g + 216 | 0;
+ $n_cluster = $g + 212 | 0;
+ $0 = $e | 0;
+ $c_0 = 1;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($c_0 | 0) > ($1 | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $2 + ($c_0 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $4 = $3;
+ $call = _agcontains($4, $0) | 0;
+ $tobool = ($call | 0) == 0;
+ $inc = $c_0 + 1 | 0;
+ if ($tobool) {
+ $c_0 = $inc;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _emit_xdot($job, $xd) {
+ $job = $job | 0;
+ $xd = $xd | 0;
+ var $ptsize = 0, $call = 0, $0 = 0, $cnt = 0, $1 = 0, $cmp64 = 0, $ops = 0, $2 = 0, $3 = 0, $clip = 0, $clip35 = 0, $clip59 = 0, $clip83 = 0, $clip102 = 0, $styles_070 = 0, $i_069 = 0, $op_067 = 0, $image_warn_066 = 0, $pts_065 = 0, $kind = 0, $4 = 0, $bb = 0, $call2 = 0, $tobool = 0, $x = 0, $5 = 0.0, $w = 0, $6 = 0, $7 = 0.0, $sub = 0.0, $x7 = 0, $8 = 0, $9 = 0.0, $10 = 0, $11 = 0.0, $sub14 = 0.0, $y16 = 0, $12 = 0.0, $x22 = 0, $13 = 0.0, $y28 = 0, $14 = 0, $cmp31 = 0, $conv32 = 0, $bb34 = 0, $call36 = 0, $tobool37 = 0, $u40 = 0, $polygon = 0, $pts41 = 0, $15 = 0, $cnt45 = 0, $16 = 0, $call46 = 0, $17 = 0, $18 = 0, $cmp53 = 0, $conv55 = 0, $bb58 = 0, $call60 = 0, $tobool61 = 0, $u64 = 0, $bezier = 0, $pts65 = 0, $19 = 0, $cnt69 = 0, $20 = 0, $call70 = 0, $21 = 0, $22 = 0, $cmp77 = 0, $conv79 = 0, $bb82 = 0, $call84 = 0, $tobool85 = 0, $u88 = 0, $polyline = 0, $pts89 = 0, $23 = 0, $cnt93 = 0, $24 = 0, $call94 = 0, $25 = 0, $bb101 = 0, $call103 = 0, $tobool104 = 0, $x108 = 0, $26 = 0.0, $x110 = 0, $y114 = 0, $27 = 0.0, $y116 = 0, $para = 0, $28 = 0, $u121 = 0, $color = 0, $29 = 0, $u124 = 0, $color125 = 0, $30 = 0, $u134 = 0, $style = 0, $31 = 0, $call135 = 0, $tobool137 = 0, $call139 = 0, $pts_1 = 0, $image_warn_1 = 0, $styles_1 = 0, $incdec_ptr = 0, $inc = 0, $32 = 0, $cmp = 0, $tobool141 = 0, $gvc = 0, $33 = 0, $defaultlinestyle = 0, $34 = 0, $pts_0_lcssa73 = 0, $35 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptsize = __stackBase__ | 0;
+ HEAP32[$ptsize >> 2] = 1e3;
+ $call = _gmalloc(16e3) | 0;
+ $0 = $call;
+ $cnt = $xd | 0;
+ $1 = HEAP32[$cnt >> 2] | 0;
+ $cmp64 = ($1 | 0) > 0;
+ if ($cmp64) {
+ label = 3;
+ break;
+ } else {
+ $pts_0_lcssa73 = $0;
+ label = 23;
+ break;
+ }
+ case 3:
+ $ops = $xd + 8 | 0;
+ $2 = HEAP32[$ops >> 2] | 0;
+ $3 = $2;
+ $clip = $job + 256 | 0;
+ $clip35 = $job + 256 | 0;
+ $clip59 = $job + 256 | 0;
+ $clip83 = $job + 256 | 0;
+ $clip102 = $job + 256 | 0;
+ $pts_065 = $0;
+ $image_warn_066 = 1;
+ $op_067 = $3;
+ $i_069 = 0;
+ $styles_070 = 0;
+ label = 4;
+ break;
+ case 4:
+ $kind = $op_067 | 0;
+ $4 = HEAP32[$kind >> 2] | 0;
+ if (($4 | 0) == 0 | ($4 | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($4 | 0) == 2 | ($4 | 0) == 3) {
+ label = 7;
+ break;
+ } else if (($4 | 0) == 4 | ($4 | 0) == 5) {
+ label = 9;
+ break;
+ } else if (($4 | 0) == 6) {
+ label = 11;
+ break;
+ } else if (($4 | 0) == 7) {
+ label = 13;
+ break;
+ } else if (($4 | 0) == 8) {
+ label = 15;
+ break;
+ } else if (($4 | 0) == 9) {
+ label = 16;
+ break;
+ } else if (($4 | 0) == 11) {
+ label = 17;
+ break;
+ } else if (($4 | 0) == 12) {
+ label = 18;
+ break;
+ } else {
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ }
+ case 5:
+ $bb = $op_067 + 56 | 0;
+ $call2 = _boxf_overlap($bb, $clip) | 0;
+ $tobool = ($call2 | 0) == 0;
+ if ($tobool) {
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $x = $op_067 + 8 | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $w = $op_067 + 24 | 0;
+ $6 = $w;
+ $7 = +HEAPF64[$6 >> 3];
+ $sub = $5 - $7;
+ $x7 = $pts_065 | 0;
+ HEAPF64[$x7 >> 3] = $sub;
+ $8 = $op_067 + 16 | 0;
+ $9 = +HEAPF64[$8 >> 3];
+ $10 = $op_067 + 32 | 0;
+ $11 = +HEAPF64[$10 >> 3];
+ $sub14 = $9 - $11;
+ $y16 = $pts_065 + 8 | 0;
+ HEAPF64[$y16 >> 3] = $sub14;
+ $12 = +HEAPF64[$6 >> 3];
+ $x22 = $pts_065 + 16 | 0;
+ HEAPF64[$x22 >> 3] = $12;
+ $13 = +HEAPF64[$10 >> 3];
+ $y28 = $pts_065 + 24 | 0;
+ HEAPF64[$y28 >> 3] = $13;
+ $14 = HEAP32[$kind >> 2] | 0;
+ $cmp31 = ($14 | 0) == 0;
+ $conv32 = $cmp31 & 1;
+ _gvrender_ellipse($job, $pts_065, 0, $conv32);
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ case 7:
+ $bb34 = $op_067 + 56 | 0;
+ $call36 = _boxf_overlap($bb34, $clip35) | 0;
+ $tobool37 = ($call36 | 0) == 0;
+ if ($tobool37) {
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $u40 = $op_067 + 8 | 0;
+ $polygon = $u40;
+ $pts41 = $polygon + 4 | 0;
+ $15 = HEAP32[$pts41 >> 2] | 0;
+ $cnt45 = $u40;
+ $16 = HEAP32[$cnt45 >> 2] | 0;
+ $call46 = _copyPts($pts_065, $ptsize, $15, $16) | 0;
+ $17 = HEAP32[$cnt45 >> 2] | 0;
+ $18 = HEAP32[$kind >> 2] | 0;
+ $cmp53 = ($18 | 0) == 2;
+ $conv55 = $cmp53 & 1;
+ _gvrender_polygon($job, $call46, $17, $conv55);
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $call46;
+ label = 20;
+ break;
+ case 9:
+ $bb58 = $op_067 + 56 | 0;
+ $call60 = _boxf_overlap($bb58, $clip59) | 0;
+ $tobool61 = ($call60 | 0) == 0;
+ if ($tobool61) {
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $u64 = $op_067 + 8 | 0;
+ $bezier = $u64;
+ $pts65 = $bezier + 4 | 0;
+ $19 = HEAP32[$pts65 >> 2] | 0;
+ $cnt69 = $u64;
+ $20 = HEAP32[$cnt69 >> 2] | 0;
+ $call70 = _copyPts($pts_065, $ptsize, $19, $20) | 0;
+ $21 = HEAP32[$cnt69 >> 2] | 0;
+ $22 = HEAP32[$kind >> 2] | 0;
+ $cmp77 = ($22 | 0) == 4;
+ $conv79 = $cmp77 & 1;
+ _gvrender_beziercurve($job, $call70, $21, 0, 0, $conv79);
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $call70;
+ label = 20;
+ break;
+ case 11:
+ $bb82 = $op_067 + 56 | 0;
+ $call84 = _boxf_overlap($bb82, $clip83) | 0;
+ $tobool85 = ($call84 | 0) == 0;
+ if ($tobool85) {
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $u88 = $op_067 + 8 | 0;
+ $polyline = $u88;
+ $pts89 = $polyline + 4 | 0;
+ $23 = HEAP32[$pts89 >> 2] | 0;
+ $cnt93 = $u88;
+ $24 = HEAP32[$cnt93 >> 2] | 0;
+ $call94 = _copyPts($pts_065, $ptsize, $23, $24) | 0;
+ $25 = HEAP32[$cnt93 >> 2] | 0;
+ _gvrender_polyline($job, $call94, $25);
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $call94;
+ label = 20;
+ break;
+ case 13:
+ $bb101 = $op_067 + 56 | 0;
+ $call103 = _boxf_overlap($bb101, $clip102) | 0;
+ $tobool104 = ($call103 | 0) == 0;
+ if ($tobool104) {
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $x108 = $op_067 + 8 | 0;
+ $26 = +HEAPF64[$x108 >> 3];
+ $x110 = $pts_065 | 0;
+ HEAPF64[$x110 >> 3] = $26;
+ $y114 = $op_067 + 16 | 0;
+ $27 = +HEAPF64[$y114 >> 3];
+ $y116 = $pts_065 + 8 | 0;
+ HEAPF64[$y116 >> 3] = $27;
+ $para = $op_067 + 88 | 0;
+ $28 = HEAP32[$para >> 2] | 0;
+ _gvrender_textpara($job, $pts_065, $28);
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ case 15:
+ $u121 = $op_067 + 8 | 0;
+ $color = $u121;
+ $29 = HEAP32[$color >> 2] | 0;
+ _gvrender_set_fillcolor($job, $29);
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ case 16:
+ $u124 = $op_067 + 8 | 0;
+ $color125 = $u124;
+ $30 = HEAP32[$color125 >> 2] | 0;
+ _gvrender_set_pencolor($job, $30);
+ $styles_1 = $styles_070;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ case 17:
+ $u134 = $op_067 + 8 | 0;
+ $style = $u134;
+ $31 = HEAP32[$style >> 2] | 0;
+ $call135 = _parse_style($31) | 0;
+ _gvrender_set_style($job, 7280);
+ $styles_1 = 7280;
+ $image_warn_1 = $image_warn_066;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ case 18:
+ $tobool137 = ($image_warn_066 | 0) == 0;
+ if ($tobool137) {
+ $styles_1 = $styles_070;
+ $image_warn_1 = 0;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $call139 = _agerr(0, 159856, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $styles_1 = $styles_070;
+ $image_warn_1 = 0;
+ $pts_1 = $pts_065;
+ label = 20;
+ break;
+ case 20:
+ $incdec_ptr = $op_067 + 96 | 0;
+ $inc = $i_069 + 1 | 0;
+ $32 = HEAP32[$cnt >> 2] | 0;
+ $cmp = ($inc | 0) < ($32 | 0);
+ if ($cmp) {
+ $pts_065 = $pts_1;
+ $image_warn_066 = $image_warn_1;
+ $op_067 = $incdec_ptr;
+ $i_069 = $inc;
+ $styles_070 = $styles_1;
+ label = 4;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $tobool141 = ($styles_1 | 0) == 0;
+ if ($tobool141) {
+ $pts_0_lcssa73 = $pts_1;
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $gvc = $job | 0;
+ $33 = HEAP32[$gvc >> 2] | 0;
+ $defaultlinestyle = $33 + 304 | 0;
+ $34 = HEAP32[$defaultlinestyle >> 2] | 0;
+ _gvrender_set_style($job, $34);
+ $pts_0_lcssa73 = $pts_1;
+ label = 23;
+ break;
+ case 23:
+ $35 = $pts_0_lcssa73;
+ _free($35);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _copyPts($pts, $ptsize, $inpts, $numpts) {
+ $pts = $pts | 0;
+ $ptsize = $ptsize | 0;
+ $inpts = $inpts | 0;
+ $numpts = $numpts | 0;
+ var $0 = 0, $cmp = 0, $mul = 0, $cmp1 = 0, $mul_numpts = 0, $1 = 0, $mul3 = 0, $call = 0, $2 = 0, $pts_addr_0 = 0, $cmp418 = 0, $i_019 = 0, $x = 0, $3 = 0.0, $x6 = 0, $y = 0, $4 = 0.0, $y9 = 0, $inc = 0, $cmp4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$ptsize >> 2] | 0;
+ $cmp = ($0 | 0) < ($numpts | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $pts_addr_0 = $pts;
+ label = 4;
+ break;
+ }
+ case 3:
+ $mul = $0 << 1;
+ $cmp1 = ($mul | 0) > ($numpts | 0);
+ $mul_numpts = $cmp1 ? $mul : $numpts;
+ $1 = $pts;
+ $mul3 = $mul_numpts << 4;
+ $call = _grealloc($1, $mul3) | 0;
+ $2 = $call;
+ HEAP32[$ptsize >> 2] = $mul_numpts;
+ $pts_addr_0 = $2;
+ label = 4;
+ break;
+ case 4:
+ $cmp418 = ($numpts | 0) > 0;
+ if ($cmp418) {
+ $i_019 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $x = $inpts + ($i_019 * 24 & -1) | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $x6 = $pts_addr_0 + ($i_019 << 4) | 0;
+ HEAPF64[$x6 >> 3] = $3;
+ $y = $inpts + ($i_019 * 24 & -1) + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y9 = $pts_addr_0 + ($i_019 << 4) + 8 | 0;
+ HEAPF64[$y9 >> 3] = $4;
+ $inc = $i_019 + 1 | 0;
+ $cmp4 = ($inc | 0) < ($numpts | 0);
+ if ($cmp4) {
+ $i_019 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ return $pts_addr_0 | 0;
+ }
+ return 0;
+}
+function _emit_cluster_colors($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $n_cluster = 0, $0 = 0, $cmp15 = 0, $clust = 0, $c_016 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $3 = 0, $call = 0, $cmp2 = 0, $4 = 0, $tobool = 0, $call4 = 0, $cmp5 = 0, $5 = 0, $tobool10 = 0, $call13 = 0, $cmp14 = 0, $6 = 0, $tobool19 = 0, $inc = 0, $7 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp15 = ($0 | 0) < 1;
+ if ($cmp15) {
+ label = 14;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $c_016 = 1;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $1 + ($c_016 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _emit_cluster_colors($job, $2);
+ $3 = $2 | 0;
+ $call = _agget($3, 120080) | 0;
+ $cmp2 = ($call | 0) == 0;
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $4 = HEAP8[$call] | 0;
+ $tobool = $4 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _gvrender_set_pencolor($job, $call);
+ label = 7;
+ break;
+ case 7:
+ $call4 = _agget($3, 118936) | 0;
+ $cmp5 = ($call4 | 0) == 0;
+ if ($cmp5) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $5 = HEAP8[$call4] | 0;
+ $tobool10 = $5 << 24 >> 24 == 0;
+ if ($tobool10) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ _gvrender_set_fillcolor($job, $call4);
+ label = 10;
+ break;
+ case 10:
+ $call13 = _agget($3, 159088) | 0;
+ $cmp14 = ($call13 | 0) == 0;
+ if ($cmp14) {
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $6 = HEAP8[$call13] | 0;
+ $tobool19 = $6 << 24 >> 24 == 0;
+ if ($tobool19) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _gvrender_set_pencolor($job, $call13);
+ label = 13;
+ break;
+ case 13:
+ $inc = $c_016 + 1 | 0;
+ $7 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($7 | 0);
+ if ($cmp) {
+ label = 14;
+ break;
+ } else {
+ $c_016 = $inc;
+ label = 4;
+ break;
+ }
+ case 14:
+ return;
+ }
+}
+function _new_queue($sz) {
+ $sz = $sz | 0;
+ var $call = 0, $_sz = 0, $1 = 0, $store = 0;
+ $call = _zmalloc(16) | 0;
+ $_sz = ($sz | 0) < 2 ? 2 : $sz;
+ $1 = _zmalloc($_sz << 2) | 0;
+ $store = $call;
+ HEAP32[$store >> 2] = $1;
+ HEAP32[$call + 12 >> 2] = $1;
+ HEAP32[$call + 8 >> 2] = $1;
+ HEAP32[$call + 4 >> 2] = (HEAP32[$store >> 2] | 0) + ($_sz << 2) | 0;
+ return $call | 0;
+}
+function _free_queue($q) {
+ $q = $q | 0;
+ _free(HEAP32[$q >> 2] | 0);
+ _free($q);
+ return;
+}
+function _late_int($obj, $attr, $def, $low) {
+ $obj = $obj | 0;
+ $attr = $attr | 0;
+ $def = $def | 0;
+ $low = $low | 0;
+ var $cmp = 0, $index = 0, $0 = 0, $call = 0, $tobool = 0, $1 = 0, $cmp1 = 0, $call5 = 0, $cmp6 = 0, $low_call5 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($attr | 0) == 0;
+ if ($cmp) {
+ $retval_0 = $def;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $index = $attr + 8 | 0;
+ $0 = HEAP32[$index >> 2] | 0;
+ $call = _agxget($obj, $0) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = $def;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$call] | 0;
+ $cmp1 = $1 << 24 >> 24 == 0;
+ if ($cmp1) {
+ $retval_0 = $def;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call5 = _atoi($call | 0) | 0;
+ $cmp6 = ($call5 | 0) < ($low | 0);
+ $low_call5 = $cmp6 ? $low : $call5;
+ $retval_0 = $low_call5;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _late_double($obj, $attr, $def, $low) {
+ $obj = $obj | 0;
+ $attr = $attr | 0;
+ $def = +$def;
+ $low = +$low;
+ var $tobool = 0, $tobool1 = 0, $or_cond = 0, $index = 0, $0 = 0, $call = 0, $tobool2 = 0, $1 = 0, $cmp = 0, $call7 = 0.0, $cmp8 = 0, $rv_0 = 0.0, $retval_0 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($attr | 0) == 0;
+ $tobool1 = ($obj | 0) == 0;
+ $or_cond = $tobool | $tobool1;
+ if ($or_cond) {
+ $retval_0 = $def;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $index = $attr + 8 | 0;
+ $0 = HEAP32[$index >> 2] | 0;
+ $call = _agxget($obj, $0) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ $retval_0 = $def;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$call] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ if ($cmp) {
+ $retval_0 = $def;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call7 = +_atof($call);
+ $cmp8 = $call7 < $low;
+ $rv_0 = $cmp8 ? $low : $call7;
+ $retval_0 = $rv_0;
+ label = 6;
+ break;
+ case 6:
+ return +$retval_0;
+ }
+ return 0.0;
+}
+function _late_string($obj, $attr, $def) {
+ $obj = $obj | 0;
+ $attr = $attr | 0;
+ $def = $def | 0;
+ var $tobool = 0, $tobool1 = 0, $or_cond = 0, $index = 0, $0 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($attr | 0) == 0;
+ $tobool1 = ($obj | 0) == 0;
+ $or_cond = $tobool | $tobool1;
+ if ($or_cond) {
+ $retval_0 = $def;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $index = $attr + 8 | 0;
+ $0 = HEAP32[$index >> 2] | 0;
+ $call = _agxget($obj, $0) | 0;
+ $retval_0 = $call;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _late_nnstring($obj, $attr, $def) {
+ $obj = $obj | 0;
+ $attr = $attr | 0;
+ $def = $def | 0;
+ var $call = 0, $tobool = 0, $0 = 0, $cmp = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _late_string($obj, $attr, $def) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$call] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $rv_0 = $call;
+ label = 5;
+ break;
+ }
+ case 4:
+ $rv_0 = $def;
+ label = 5;
+ break;
+ case 5:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _mapbool($p) {
+ $p = $p | 0;
+ return _mapBool($p, 0) | 0;
+}
+function _UF_union($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ var $cmp = 0, $UF_parent = 0, $0 = 0, $cmp2 = 0, $UF_size = 0, $call = 0, $u_addr_0 = 0, $UF_parent9 = 0, $1 = 0, $cmp10 = 0, $UF_size15 = 0, $call17 = 0, $v_addr_0 = 0, $id = 0, $2 = 0, $id19 = 0, $3 = 0, $cmp20 = 0, $UF_parent23 = 0, $UF_size25 = 0, $4 = 0, $UF_size27 = 0, $5 = 0, $add = 0, $UF_parent30 = 0, $UF_size32 = 0, $6 = 0, $UF_size34 = 0, $7 = 0, $add35 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($u | 0) == ($v | 0);
+ if ($cmp) {
+ $retval_0 = $u;
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $UF_parent = $u + 224 | 0;
+ $0 = HEAP32[$UF_parent >> 2] | 0;
+ $cmp2 = ($0 | 0) == 0;
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP32[$UF_parent >> 2] = $u;
+ $UF_size = $u + 220 | 0;
+ HEAP32[$UF_size >> 2] = 1;
+ $u_addr_0 = $u;
+ label = 6;
+ break;
+ case 5:
+ $call = _UF_find($u) | 0;
+ $u_addr_0 = $call;
+ label = 6;
+ break;
+ case 6:
+ $UF_parent9 = $v + 224 | 0;
+ $1 = HEAP32[$UF_parent9 >> 2] | 0;
+ $cmp10 = ($1 | 0) == 0;
+ if ($cmp10) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$UF_parent9 >> 2] = $v;
+ $UF_size15 = $v + 220 | 0;
+ HEAP32[$UF_size15 >> 2] = 1;
+ $v_addr_0 = $v;
+ label = 9;
+ break;
+ case 8:
+ $call17 = _UF_find($v) | 0;
+ $v_addr_0 = $call17;
+ label = 9;
+ break;
+ case 9:
+ $id = $u_addr_0 + 16 | 0;
+ $2 = HEAP32[$id >> 2] | 0;
+ $id19 = $v_addr_0 + 16 | 0;
+ $3 = HEAP32[$id19 >> 2] | 0;
+ $cmp20 = ($2 | 0) > ($3 | 0);
+ if ($cmp20) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $UF_parent23 = $u_addr_0 + 224 | 0;
+ HEAP32[$UF_parent23 >> 2] = $v_addr_0;
+ $UF_size25 = $u_addr_0 + 220 | 0;
+ $4 = HEAP32[$UF_size25 >> 2] | 0;
+ $UF_size27 = $v_addr_0 + 220 | 0;
+ $5 = HEAP32[$UF_size27 >> 2] | 0;
+ $add = $5 + $4 | 0;
+ HEAP32[$UF_size27 >> 2] = $add;
+ $retval_0 = $v_addr_0;
+ label = 12;
+ break;
+ case 11:
+ $UF_parent30 = $v_addr_0 + 224 | 0;
+ HEAP32[$UF_parent30 >> 2] = $u_addr_0;
+ $UF_size32 = $v_addr_0 + 220 | 0;
+ $6 = HEAP32[$UF_size32 >> 2] | 0;
+ $UF_size34 = $u_addr_0 + 220 | 0;
+ $7 = HEAP32[$UF_size34 >> 2] | 0;
+ $add35 = $7 + $6 | 0;
+ HEAP32[$UF_size34 >> 2] = $add35;
+ $retval_0 = $u_addr_0;
+ label = 12;
+ break;
+ case 12:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _UF_setname($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ var $call = 0, $cmp = 0, $UF_parent = 0, $UF_size = 0, $0 = 0, $UF_size4 = 0, $1 = 0, $add = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _UF_find($u) | 0;
+ $cmp = ($call | 0) == ($u | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ ___assert_func(158664, 198, 164680, 130200);
+ case 4:
+ $UF_parent = $u + 224 | 0;
+ HEAP32[$UF_parent >> 2] = $v;
+ $UF_size = $u + 220 | 0;
+ $0 = HEAP32[$UF_size >> 2] | 0;
+ $UF_size4 = $v + 220 | 0;
+ $1 = HEAP32[$UF_size4 >> 2] | 0;
+ $add = $1 + $0 | 0;
+ HEAP32[$UF_size4 >> 2] = $add;
+ return;
+ }
+}
+function _Bezier($agg_result, $V, $degree, $t, $Left, $Right) {
+ $agg_result = $agg_result | 0;
+ $V = $V | 0;
+ $degree = $degree | 0;
+ $t = +$t;
+ $Left = $Left | 0;
+ $Right = $Right | 0;
+ var $Vtemp = 0, $cmp49 = 0, $cmp446 = 0, $sub9 = 0.0, $j_050 = 0, $arrayidx1 = 0, $arrayidx2 = 0, $0 = 0, $1 = 0, $inc = 0, $cmp = 0, $i_047 = 0, $sub = 0, $cmp744 = 0, $sub10 = 0, $j_145 = 0, $x = 0, $2 = 0.0, $mul = 0.0, $add = 0, $x16 = 0, $3 = 0.0, $mul17 = 0.0, $add18 = 0.0, $x21 = 0, $y = 0, $4 = 0.0, $mul26 = 0.0, $y31 = 0, $5 = 0.0, $mul32 = 0.0, $add33 = 0.0, $y36 = 0, $cmp7 = 0, $inc41 = 0, $cmp4 = 0, $cmp43 = 0, $cmp4542 = 0, $or_cond = 0, $j_243 = 0, $arrayidx47 = 0, $arrayidx49 = 0, $6 = 0, $7 = 0, $inc51 = 0, $cmp45 = 0, $cmp53 = 0, $cmp5640 = 0, $or_cond52 = 0, $j_341 = 0, $arrayidx58 = 0, $sub59 = 0, $arrayidx61 = 0, $8 = 0, $9 = 0, $inc63 = 0, $cmp56 = 0, $arrayidx67 = 0, $10 = 0, $11 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 576 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $Vtemp = __stackBase__ | 0;
+ $cmp49 = ($degree | 0) < 0;
+ if ($cmp49) {
+ label = 10;
+ break;
+ } else {
+ $j_050 = 0;
+ label = 5;
+ break;
+ }
+ case 3:
+ $cmp446 = ($degree | 0) < 1;
+ if ($cmp446) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $sub9 = 1.0 - $t;
+ $i_047 = 1;
+ label = 6;
+ break;
+ case 5:
+ $arrayidx1 = $Vtemp + ($j_050 << 4) | 0;
+ $arrayidx2 = $V + ($j_050 << 4) | 0;
+ $0 = $arrayidx1;
+ $1 = $arrayidx2;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $inc = $j_050 + 1 | 0;
+ $cmp = ($inc | 0) > ($degree | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $j_050 = $inc;
+ label = 5;
+ break;
+ }
+ case 6:
+ $sub = $degree - $i_047 | 0;
+ $cmp744 = ($sub | 0) < 0;
+ if ($cmp744) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub10 = $i_047 - 1 | 0;
+ $j_145 = 0;
+ label = 8;
+ break;
+ case 8:
+ $x = $Vtemp + ($sub10 * 96 & -1) + ($j_145 << 4) | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $mul = $sub9 * $2;
+ $add = $j_145 + 1 | 0;
+ $x16 = $Vtemp + ($sub10 * 96 & -1) + ($add << 4) | 0;
+ $3 = +HEAPF64[$x16 >> 3];
+ $mul17 = $3 * $t;
+ $add18 = $mul + $mul17;
+ $x21 = $Vtemp + ($i_047 * 96 & -1) + ($j_145 << 4) | 0;
+ HEAPF64[$x21 >> 3] = $add18;
+ $y = $Vtemp + ($sub10 * 96 & -1) + ($j_145 << 4) + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $mul26 = $sub9 * $4;
+ $y31 = $Vtemp + ($sub10 * 96 & -1) + ($add << 4) + 8 | 0;
+ $5 = +HEAPF64[$y31 >> 3];
+ $mul32 = $5 * $t;
+ $add33 = $mul26 + $mul32;
+ $y36 = $Vtemp + ($i_047 * 96 & -1) + ($j_145 << 4) + 8 | 0;
+ HEAPF64[$y36 >> 3] = $add33;
+ $cmp7 = ($add | 0) > ($sub | 0);
+ if ($cmp7) {
+ label = 9;
+ break;
+ } else {
+ $j_145 = $add;
+ label = 8;
+ break;
+ }
+ case 9:
+ $inc41 = $i_047 + 1 | 0;
+ $cmp4 = ($inc41 | 0) > ($degree | 0);
+ if ($cmp4) {
+ label = 10;
+ break;
+ } else {
+ $i_047 = $inc41;
+ label = 6;
+ break;
+ }
+ case 10:
+ $cmp43 = ($Left | 0) == 0;
+ $cmp4542 = ($degree | 0) < 0;
+ $or_cond = $cmp43 | $cmp4542;
+ if ($or_cond) {
+ label = 12;
+ break;
+ } else {
+ $j_243 = 0;
+ label = 11;
+ break;
+ }
+ case 11:
+ $arrayidx47 = $Left + ($j_243 << 4) | 0;
+ $arrayidx49 = $Vtemp + ($j_243 * 96 & -1) | 0;
+ $6 = $arrayidx47;
+ $7 = $arrayidx49;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $inc51 = $j_243 + 1 | 0;
+ $cmp45 = ($inc51 | 0) > ($degree | 0);
+ if ($cmp45) {
+ label = 12;
+ break;
+ } else {
+ $j_243 = $inc51;
+ label = 11;
+ break;
+ }
+ case 12:
+ $cmp53 = ($Right | 0) == 0;
+ $cmp5640 = ($degree | 0) < 0;
+ $or_cond52 = $cmp53 | $cmp5640;
+ if ($or_cond52) {
+ label = 14;
+ break;
+ } else {
+ $j_341 = 0;
+ label = 13;
+ break;
+ }
+ case 13:
+ $arrayidx58 = $Right + ($j_341 << 4) | 0;
+ $sub59 = $degree - $j_341 | 0;
+ $arrayidx61 = $Vtemp + ($sub59 * 96 & -1) + ($j_341 << 4) | 0;
+ $8 = $arrayidx58;
+ $9 = $arrayidx61;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $inc63 = $j_341 + 1 | 0;
+ $cmp56 = ($inc63 | 0) > ($degree | 0);
+ if ($cmp56) {
+ label = 14;
+ break;
+ } else {
+ $j_341 = $inc63;
+ label = 13;
+ break;
+ }
+ case 14:
+ $arrayidx67 = $Vtemp + ($degree * 96 & -1) | 0;
+ $10 = $agg_result;
+ $11 = $arrayidx67;
+ HEAP32[$10 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _Fgets($fp) {
+ $fp = $fp | 0;
+ var $len_0 = 0, $0 = 0, $sub = 0, $cmp = 0, $add = 0, $1 = 0, $call = 0, $2 = 0, $add_ptr = 0, $3 = 0, $sub1 = 0, $call2 = 0, $cmp3 = 0, $call6 = 0, $add7 = 0, $sub8 = 0, $4 = 0, $arrayidx = 0, $5 = 0, $cmp9 = 0, $len_1 = 0, $cmp11 = 0, $6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $len_0 = 0;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP32[41888] | 0;
+ $sub = $0 - $len_0 | 0;
+ $cmp = ($sub | 0) < 1024;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $add = $0 + 1024 | 0;
+ HEAP32[41888] = $add;
+ $1 = HEAP32[41886] | 0;
+ $call = _grealloc($1, $add) | 0;
+ HEAP32[41886] = $call;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP32[41886] | 0;
+ $add_ptr = $2 + $len_0 | 0;
+ $3 = HEAP32[41888] | 0;
+ $sub1 = $3 - $len_0 | 0;
+ $call2 = _fgets($add_ptr | 0, $sub1 | 0, $fp | 0) | 0;
+ $cmp3 = ($call2 | 0) == 0;
+ if ($cmp3) {
+ $len_1 = $len_0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call6 = _strlen($call2 | 0) | 0;
+ $add7 = $call6 + $len_0 | 0;
+ $sub8 = $add7 - 1 | 0;
+ $4 = HEAP32[41886] | 0;
+ $arrayidx = $4 + $sub8 | 0;
+ $5 = HEAP8[$arrayidx] | 0;
+ $cmp9 = $5 << 24 >> 24 == 10;
+ if ($cmp9) {
+ $len_1 = $add7;
+ label = 7;
+ break;
+ } else {
+ $len_0 = $add7;
+ label = 3;
+ break;
+ }
+ case 7:
+ $cmp11 = ($len_1 | 0) > 0;
+ $6 = HEAP32[41886] | 0;
+ $retval_0 = $cmp11 ? $6 : 0;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _safefile($filename) {
+ $filename = $filename | 0;
+ var $tobool = 0, $0 = 0, $tobool1 = 0, $1 = 0, $tobool2 = 0, $2 = 0, $tobool4 = 0, $_b21 = 0, $call = 0, $_b22 = 0, $call12 = 0, $call13 = 0, $tobool1423 = 0, $3 = 0, $4 = 0, $dir_025 = 0, $cnt_024 = 0, $tobool15 = 0, $5 = 0, $add = 0, $mul = 0, $call16 = 0, $add17 = 0, $mul18 = 0, $call19 = 0, $call16_sink = 0, $6 = 0, $inc = 0, $arrayidx20 = 0, $7 = 0, $call21 = 0, $cmp = 0, $_call21 = 0, $call27 = 0, $tobool14 = 0, $8 = 0, $_lcssa = 0, $cnt_0_lcssa = 0, $arrayidx28 = 0, $call30 = 0, $tobool31 = 0, $incdec_ptr = 0, $filename_incdec_ptr = 0, $call34 = 0, $tobool35 = 0, $incdec_ptr37 = 0, $str_1 = 0, $call39 = 0, $tobool40 = 0, $incdec_ptr42 = 0, $str_1_incdec_ptr42 = 0, $_b = 0, $cmp45 = 0, $or_cond = 0, $9 = 0, $call48 = 0, $10 = 0, $11 = 0, $call50 = 0, $add51 = 0, $add52 = 0, $call53 = 0, $12 = 0, $dp_0 = 0, $13 = 0, $tobool55 = 0, $14 = 0, $call57 = 0, $15 = 0, $call58 = 0, $cmp59 = 0, $incdec_ptr64 = 0, $16 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($filename | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 21;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$filename] | 0;
+ $tobool1 = $0 << 24 >> 24 == 0;
+ if ($tobool1) {
+ $retval_0 = 0;
+ label = 21;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[41772] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ if ($tobool2) {
+ $retval_0 = $filename;
+ label = 21;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP32[41788] | 0;
+ $tobool4 = ($2 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $_b21 = HEAP8[4248] | 0;
+ if ($_b21) {
+ $retval_0 = 0;
+ label = 21;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call = _agerr(0, 118280, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $1, tempInt) | 0) | 0;
+ HEAP8[4248] = 1;
+ $retval_0 = 0;
+ label = 21;
+ break;
+ case 8:
+ $_b22 = HEAP8[4264] | 0;
+ if ($_b22) {
+ label = 15;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call12 = _strdup($2 | 0) | 0;
+ $call13 = _strtok($call12 | 0, 113024) | 0;
+ $tobool1423 = ($call13 | 0) == 0;
+ $3 = HEAP32[1068] | 0;
+ if ($tobool1423) {
+ $cnt_0_lcssa = 0;
+ $_lcssa = $3;
+ label = 14;
+ break;
+ } else {
+ $cnt_024 = 0;
+ $dir_025 = $call13;
+ $4 = $3;
+ label = 10;
+ break;
+ }
+ case 10:
+ $tobool15 = ($4 | 0) == 0;
+ if ($tobool15) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $5 = $4;
+ $add = $cnt_024 << 2;
+ $mul = $add + 8 | 0;
+ $call16 = _grealloc($5, $mul) | 0;
+ $call16_sink = $call16;
+ label = 13;
+ break;
+ case 12:
+ $add17 = $cnt_024 << 2;
+ $mul18 = $add17 + 8 | 0;
+ $call19 = _gmalloc($mul18) | 0;
+ $call16_sink = $call19;
+ label = 13;
+ break;
+ case 13:
+ $6 = $call16_sink;
+ HEAP32[1068] = $6;
+ $inc = $cnt_024 + 1 | 0;
+ $arrayidx20 = $6 + ($cnt_024 << 2) | 0;
+ HEAP32[$arrayidx20 >> 2] = $dir_025;
+ $7 = HEAP32[1064] | 0;
+ $call21 = _strlen($dir_025 | 0) | 0;
+ $cmp = $7 >>> 0 > $call21 >>> 0;
+ $_call21 = $cmp ? $7 : $call21;
+ HEAP32[1064] = $_call21;
+ $call27 = _strtok(0, 113024) | 0;
+ $tobool14 = ($call27 | 0) == 0;
+ $8 = HEAP32[1068] | 0;
+ if ($tobool14) {
+ $cnt_0_lcssa = $inc;
+ $_lcssa = $8;
+ label = 14;
+ break;
+ } else {
+ $cnt_024 = $inc;
+ $dir_025 = $call27;
+ $4 = $8;
+ label = 10;
+ break;
+ }
+ case 14:
+ $arrayidx28 = $_lcssa + ($cnt_0_lcssa << 2) | 0;
+ HEAP32[$arrayidx28 >> 2] = 0;
+ HEAP8[4264] = 1;
+ label = 15;
+ break;
+ case 15:
+ $call30 = _strrchr($filename | 0, 47) | 0;
+ $tobool31 = ($call30 | 0) == 0;
+ $incdec_ptr = $call30 + 1 | 0;
+ $filename_incdec_ptr = $tobool31 ? $filename : $incdec_ptr;
+ $call34 = _strrchr($filename_incdec_ptr | 0, 92) | 0;
+ $tobool35 = ($call34 | 0) == 0;
+ $incdec_ptr37 = $call34 + 1 | 0;
+ $str_1 = $tobool35 ? $filename_incdec_ptr : $incdec_ptr37;
+ $call39 = _strrchr($str_1 | 0, 58) | 0;
+ $tobool40 = ($call39 | 0) == 0;
+ $incdec_ptr42 = $call39 + 1 | 0;
+ $str_1_incdec_ptr42 = $tobool40 ? $str_1 : $incdec_ptr42;
+ $_b = HEAP8[4248] | 0;
+ $cmp45 = ($str_1_incdec_ptr42 | 0) == ($filename | 0);
+ $or_cond = $_b | $cmp45;
+ if ($or_cond) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $9 = HEAP32[41788] | 0;
+ $call48 = _agerr(0, 108488, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $filename, HEAP32[tempInt + 8 >> 2] = $9, tempInt) | 0) | 0;
+ HEAP8[4248] = 1;
+ label = 17;
+ break;
+ case 17:
+ $10 = HEAP32[1060] | 0;
+ $11 = HEAP32[1064] | 0;
+ $call50 = _strlen($str_1_incdec_ptr42 | 0) | 0;
+ $add51 = $11 + 2 | 0;
+ $add52 = $add51 + $call50 | 0;
+ $call53 = _realloc($10, $add52) | 0;
+ HEAP32[1060] = $call53;
+ $12 = HEAP32[1068] | 0;
+ $dp_0 = $12;
+ label = 18;
+ break;
+ case 18:
+ $13 = HEAP32[$dp_0 >> 2] | 0;
+ $tobool55 = ($13 | 0) == 0;
+ if ($tobool55) {
+ $retval_0 = 0;
+ label = 21;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $14 = HEAP32[1060] | 0;
+ $call57 = _sprintf($14 | 0, 104552, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $13, HEAP32[tempInt + 8 >> 2] = 100320, HEAP32[tempInt + 16 >> 2] = $str_1_incdec_ptr42, tempInt) | 0) | 0;
+ $15 = HEAP32[1060] | 0;
+ $call58 = _access($15 | 0, 4) | 0;
+ $cmp59 = ($call58 | 0) == 0;
+ $incdec_ptr64 = $dp_0 + 4 | 0;
+ if ($cmp59) {
+ label = 20;
+ break;
+ } else {
+ $dp_0 = $incdec_ptr64;
+ label = 18;
+ break;
+ }
+ case 20:
+ $16 = HEAP32[1060] | 0;
+ $retval_0 = $16;
+ label = 21;
+ break;
+ case 21:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _maptoken($p, $name, $val) {
+ $p = $p | 0;
+ $name = $name | 0;
+ $val = $val | 0;
+ var $0 = 0, $cmp6 = 0, $tobool = 0, $1 = 0, $i_07 = 0, $2 = 0, $3 = 0, $cmp2 = 0, $call = 0, $tobool5 = 0, $inc = 0, $arrayidx = 0, $4 = 0, $cmp = 0, $i_0_lcssa = 0, $arrayidx6 = 0, $5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$name >> 2] | 0;
+ $cmp6 = ($0 | 0) == 0;
+ if ($cmp6) {
+ $i_0_lcssa = 0;
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tobool = ($p | 0) == 0;
+ $i_07 = 0;
+ $1 = $0;
+ label = 4;
+ break;
+ case 4:
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP8[$p] | 0;
+ $3 = HEAP8[$1] | 0;
+ $cmp2 = $2 << 24 >> 24 == $3 << 24 >> 24;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call = _strcmp($p | 0, $1 | 0) | 0;
+ $tobool5 = ($call | 0) == 0;
+ if ($tobool5) {
+ $i_0_lcssa = $i_07;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $inc = $i_07 + 1 | 0;
+ $arrayidx = $name + ($inc << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp = ($4 | 0) == 0;
+ if ($cmp) {
+ $i_0_lcssa = $inc;
+ label = 8;
+ break;
+ } else {
+ $i_07 = $inc;
+ $1 = $4;
+ label = 4;
+ break;
+ }
+ case 8:
+ $arrayidx6 = $val + ($i_0_lcssa << 2) | 0;
+ $5 = HEAP32[$arrayidx6 >> 2] | 0;
+ return $5 | 0;
+ }
+ return 0;
+}
+function _mapBool($p, $dflt) {
+ $p = $p | 0;
+ $dflt = $dflt | 0;
+ var $tobool = 0, $0 = 0, $cmp = 0, $call = 0, $tobool2 = 0, $call5 = 0, $tobool6 = 0, $call9 = 0, $tobool10 = 0, $call13 = 0, $tobool14 = 0, $1 = 0, $conv17 = 0, $isdigittmp = 0, $isdigit = 0, $call21 = 0, $conv22 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($p | 0) == 0;
+ if ($tobool) {
+ $retval_0 = $dflt;
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$p] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ $retval_0 = $dflt;
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _strcasecmp($p, 96120) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call5 = _strcasecmp($p, 92720) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call9 = _strcasecmp($p, 162824) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call13 = _strcasecmp($p, 159408) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $1 = HEAP8[$p] | 0;
+ $conv17 = $1 << 24 >> 24;
+ $isdigittmp = $conv17 - 48 | 0;
+ $isdigit = $isdigittmp >>> 0 < 10;
+ if ($isdigit) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = $dflt;
+ label = 10;
+ break;
+ }
+ case 9:
+ $call21 = _atoi($p | 0) | 0;
+ $conv22 = $call21 & 255;
+ $retval_0 = $conv22;
+ label = 10;
+ break;
+ case 10:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _strcasecmp($s1, $s2) {
+ $s1 = $s1 | 0;
+ $s2 = $s2 | 0;
+ var $0 = 0, $cmp6 = 0, $1 = 0, $s2_addr_08 = 0, $s1_addr_07 = 0, $conv2 = 0, $call = 0, $2 = 0, $conv3 = 0, $call4 = 0, $cmp5 = 0, $incdec_ptr = 0, $incdec_ptr7 = 0, $3 = 0, $cmp = 0, $s2_addr_0_lcssa = 0, $s1_addr_0_lcssa = 0, $4 = 0, $conv8 = 0, $call9 = 0, $5 = 0, $conv10 = 0, $call11 = 0, $sub = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$s1] | 0;
+ $cmp6 = $0 << 24 >> 24 == 0;
+ if ($cmp6) {
+ $s1_addr_0_lcssa = $s1;
+ $s2_addr_0_lcssa = $s2;
+ label = 5;
+ break;
+ } else {
+ $s1_addr_07 = $s1;
+ $s2_addr_08 = $s2;
+ $1 = $0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv2 = $1 & 255;
+ $call = _tolower($conv2 | 0) | 0;
+ $2 = HEAP8[$s2_addr_08] | 0;
+ $conv3 = $2 & 255;
+ $call4 = _tolower($conv3 | 0) | 0;
+ $cmp5 = ($call | 0) == ($call4 | 0);
+ if ($cmp5) {
+ label = 4;
+ break;
+ } else {
+ $s1_addr_0_lcssa = $s1_addr_07;
+ $s2_addr_0_lcssa = $s2_addr_08;
+ label = 5;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $s1_addr_07 + 1 | 0;
+ $incdec_ptr7 = $s2_addr_08 + 1 | 0;
+ $3 = HEAP8[$incdec_ptr] | 0;
+ $cmp = $3 << 24 >> 24 == 0;
+ if ($cmp) {
+ $s1_addr_0_lcssa = $incdec_ptr;
+ $s2_addr_0_lcssa = $incdec_ptr7;
+ label = 5;
+ break;
+ } else {
+ $s1_addr_07 = $incdec_ptr;
+ $s2_addr_08 = $incdec_ptr7;
+ $1 = $3;
+ label = 3;
+ break;
+ }
+ case 5:
+ $4 = HEAP8[$s1_addr_0_lcssa] | 0;
+ $conv8 = $4 & 255;
+ $call9 = _tolower($conv8 | 0) | 0;
+ $5 = HEAP8[$s2_addr_0_lcssa] | 0;
+ $conv10 = $5 & 255;
+ $call11 = _tolower($conv10 | 0) | 0;
+ $sub = $call9 - $call11 | 0;
+ return $sub | 0;
+ }
+ return 0;
+}
+function _dotneato_closest($agg_result, $spl, $pt) {
+ $agg_result = $agg_result | 0;
+ $spl = $spl | 0;
+ $pt = $pt | 0;
+ var $c = 0, $tmp = 0, $size = 0, $0 = 0, $cmp74 = 0, $list = 0, $1 = 0, $2 = 0, $3 = 0, $x12 = 0, $4 = 0.0, $y17 = 0, $5 = 0.0, $6 = 0, $i_078 = 0, $besti_077 = 0, $bestj_076 = 0, $bestdist2_075 = 0.0, $bz_sroa_0_0__idx6 = 0, $bz_sroa_0_0_copyload7 = 0, $bz_sroa_1_4__idx9 = 0, $bz_sroa_1_4_copyload10 = 0, $cmp365 = 0, $j_069 = 0, $besti_168 = 0, $bestj_167 = 0, $bestdist2_166 = 0.0, $x = 0, $7 = 0.0, $y = 0, $8 = 0.0, $sub = 0.0, $mul = 0.0, $sub18 = 0.0, $mul22 = 0.0, $add = 0.0, $cmp23 = 0, $cmp24 = 0, $or_cond = 0, $bestdist2_2 = 0.0, $bestj_2 = 0, $besti_2 = 0, $inc = 0, $cmp3 = 0, $besti_1_lcssa = 0, $bestj_1_lcssa = 0, $bestdist2_1_lcssa = 0.0, $inc26 = 0, $cmp = 0, $_lcssa73 = 0, $_lcssa = 0, $besti_0_lcssa = 0, $bestj_0_lcssa = 0, $bz_sroa_0_0__idx = 0, $bz_sroa_0_0_copyload = 0, $div = 0, $not_cmp31 = 0, $dec = 0, $j_1 = 0, $x40 = 0, $9 = 0.0, $x42 = 0, $y46 = 0, $10 = 0.0, $y48 = 0, $add37_1 = 0, $x40_1 = 0, $11 = 0.0, $x42_1 = 0, $y46_1 = 0, $12 = 0.0, $y48_1 = 0, $add37_2 = 0, $x40_2 = 0, $13 = 0.0, $x42_2 = 0, $y46_2 = 0, $14 = 0.0, $y48_2 = 0, $add37_3 = 0, $x40_3 = 0, $15 = 0.0, $x42_3 = 0, $y46_3 = 0, $16 = 0.0, $y48_3 = 0, $arrayidx52 = 0, $x53 = 0, $17 = 0.0, $x54 = 0, $18 = 0.0, $sub55 = 0.0, $mul60 = 0.0, $y62 = 0, $19 = 0.0, $y63 = 0, $20 = 0.0, $sub64 = 0.0, $mul69 = 0.0, $add70 = 0.0, $x72 = 0, $21 = 0.0, $sub74 = 0.0, $mul79 = 0.0, $y81 = 0, $22 = 0.0, $sub83 = 0.0, $mul88 = 0.0, $add89 = 0.0, $pt2_sroa_0_0__idx17 = 0, $pt2_sroa_0_0_copyload1851 = 0.0, $pt2_sroa_1_8__idx23 = 0, $pt2_sroa_1_8_copyload2452 = 0.0, $sub9253 = 0.0, $call54 = 0.0, $cmp9355 = 0, $23 = 0.0, $24 = 0.0, $pt2_sroa_1_8_copyload2462 = 0.0, $pt2_sroa_0_0_copyload1861 = 0.0, $div9160 = 0.0, $high_059 = 0.0, $low_058 = 0.0, $dhigh2_057 = 0.0, $dlow2_056 = 0.0, $sub96 = 0.0, $call97 = 0.0, $cmp98 = 0, $cmp101 = 0, $sub105 = 0.0, $mul109 = 0.0, $sub112 = 0.0, $mul116 = 0.0, $add117 = 0.0, $dlow2_0_add117 = 0.0, $add117_dhigh2_0 = 0.0, $low_0_div91 = 0.0, $div91_high_0 = 0.0, $add90 = 0.0, $div91 = 0.0, $pt2_sroa_0_0_copyload18 = 0.0, $pt2_sroa_1_8_copyload24 = 0.0, $sub92 = 0.0, $call = 0.0, $cmp93 = 0, $pt2_sroa_1_8_copyload24_lcssa = 0.0, $pt2_sroa_0_0_copyload18_lcssa = 0.0, $pt2_sroa_0_0__idx = 0, $pt2_sroa_1_8__idx19 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 80 | 0;
+ tempParam = $pt;
+ $pt = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pt >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pt + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pt + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pt + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $c = __stackBase__ | 0;
+ $tmp = __stackBase__ + 64 | 0;
+ $size = $spl + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp74 = ($0 | 0) > 0;
+ $list = $spl | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ if ($cmp74) {
+ label = 3;
+ break;
+ } else {
+ $bestj_0_lcssa = -1;
+ $besti_0_lcssa = -1;
+ $_lcssa = $0;
+ $_lcssa73 = $1;
+ label = 7;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$size >> 2] | 0;
+ $3 = HEAP32[$list >> 2] | 0;
+ $x12 = $pt | 0;
+ $4 = +HEAPF64[$x12 >> 3];
+ $y17 = $pt + 8 | 0;
+ $5 = +HEAPF64[$y17 >> 3];
+ $bestdist2_075 = 1.0e+38;
+ $bestj_076 = -1;
+ $besti_077 = -1;
+ $i_078 = 0;
+ $6 = $1;
+ label = 4;
+ break;
+ case 4:
+ $bz_sroa_0_0__idx6 = $6 + ($i_078 * 48 & -1) | 0;
+ $bz_sroa_0_0_copyload7 = HEAP32[$bz_sroa_0_0__idx6 >> 2] | 0;
+ $bz_sroa_1_4__idx9 = $6 + ($i_078 * 48 & -1) + 4 | 0;
+ $bz_sroa_1_4_copyload10 = HEAP32[$bz_sroa_1_4__idx9 >> 2] | 0;
+ $cmp365 = ($bz_sroa_1_4_copyload10 | 0) > 0;
+ if ($cmp365) {
+ $bestdist2_166 = $bestdist2_075;
+ $bestj_167 = $bestj_076;
+ $besti_168 = $besti_077;
+ $j_069 = 0;
+ label = 5;
+ break;
+ } else {
+ $bestdist2_1_lcssa = $bestdist2_075;
+ $bestj_1_lcssa = $bestj_076;
+ $besti_1_lcssa = $besti_077;
+ label = 6;
+ break;
+ }
+ case 5:
+ $x = $bz_sroa_0_0_copyload7 + ($j_069 << 4) | 0;
+ $7 = +HEAPF64[$x >> 3];
+ $y = $bz_sroa_0_0_copyload7 + ($j_069 << 4) + 8 | 0;
+ $8 = +HEAPF64[$y >> 3];
+ $sub = $7 - $4;
+ $mul = $sub * $sub;
+ $sub18 = $8 - $5;
+ $mul22 = $sub18 * $sub18;
+ $add = $mul + $mul22;
+ $cmp23 = ($bestj_167 | 0) == -1;
+ $cmp24 = $add < $bestdist2_166;
+ $or_cond = $cmp23 | $cmp24;
+ $bestdist2_2 = $or_cond ? $add : $bestdist2_166;
+ $bestj_2 = $or_cond ? $j_069 : $bestj_167;
+ $besti_2 = $or_cond ? $i_078 : $besti_168;
+ $inc = $j_069 + 1 | 0;
+ $cmp3 = ($inc | 0) < ($bz_sroa_1_4_copyload10 | 0);
+ if ($cmp3) {
+ $bestdist2_166 = $bestdist2_2;
+ $bestj_167 = $bestj_2;
+ $besti_168 = $besti_2;
+ $j_069 = $inc;
+ label = 5;
+ break;
+ } else {
+ $bestdist2_1_lcssa = $bestdist2_2;
+ $bestj_1_lcssa = $bestj_2;
+ $besti_1_lcssa = $besti_2;
+ label = 6;
+ break;
+ }
+ case 6:
+ $inc26 = $i_078 + 1 | 0;
+ $cmp = ($inc26 | 0) < ($2 | 0);
+ if ($cmp) {
+ $bestdist2_075 = $bestdist2_1_lcssa;
+ $bestj_076 = $bestj_1_lcssa;
+ $besti_077 = $besti_1_lcssa;
+ $i_078 = $inc26;
+ $6 = $3;
+ label = 4;
+ break;
+ } else {
+ $bestj_0_lcssa = $bestj_1_lcssa;
+ $besti_0_lcssa = $besti_1_lcssa;
+ $_lcssa = $2;
+ $_lcssa73 = $3;
+ label = 7;
+ break;
+ }
+ case 7:
+ $bz_sroa_0_0__idx = $_lcssa73 + ($besti_0_lcssa * 48 & -1) | 0;
+ $bz_sroa_0_0_copyload = HEAP32[$bz_sroa_0_0__idx >> 2] | 0;
+ $div = ($bestj_0_lcssa | 0) / 3 & -1;
+ $not_cmp31 = ($div | 0) >= ($_lcssa | 0);
+ $dec = $not_cmp31 << 31 >> 31;
+ $j_1 = $dec + $div | 0;
+ $x40 = $bz_sroa_0_0_copyload + ($j_1 << 4) | 0;
+ $9 = +HEAPF64[$x40 >> 3];
+ $x42 = $c | 0;
+ HEAPF64[$x42 >> 3] = $9;
+ $y46 = $bz_sroa_0_0_copyload + ($j_1 << 4) + 8 | 0;
+ $10 = +HEAPF64[$y46 >> 3];
+ $y48 = $c + 8 | 0;
+ HEAPF64[$y48 >> 3] = $10;
+ $add37_1 = $j_1 + 1 | 0;
+ $x40_1 = $bz_sroa_0_0_copyload + ($add37_1 << 4) | 0;
+ $11 = +HEAPF64[$x40_1 >> 3];
+ $x42_1 = $c + 16 | 0;
+ HEAPF64[$x42_1 >> 3] = $11;
+ $y46_1 = $bz_sroa_0_0_copyload + ($add37_1 << 4) + 8 | 0;
+ $12 = +HEAPF64[$y46_1 >> 3];
+ $y48_1 = $c + 24 | 0;
+ HEAPF64[$y48_1 >> 3] = $12;
+ $add37_2 = $j_1 + 2 | 0;
+ $x40_2 = $bz_sroa_0_0_copyload + ($add37_2 << 4) | 0;
+ $13 = +HEAPF64[$x40_2 >> 3];
+ $x42_2 = $c + 32 | 0;
+ HEAPF64[$x42_2 >> 3] = $13;
+ $y46_2 = $bz_sroa_0_0_copyload + ($add37_2 << 4) + 8 | 0;
+ $14 = +HEAPF64[$y46_2 >> 3];
+ $y48_2 = $c + 40 | 0;
+ HEAPF64[$y48_2 >> 3] = $14;
+ $add37_3 = $j_1 + 3 | 0;
+ $x40_3 = $bz_sroa_0_0_copyload + ($add37_3 << 4) | 0;
+ $15 = +HEAPF64[$x40_3 >> 3];
+ $x42_3 = $c + 48 | 0;
+ HEAPF64[$x42_3 >> 3] = $15;
+ $y46_3 = $bz_sroa_0_0_copyload + ($add37_3 << 4) + 8 | 0;
+ $16 = +HEAPF64[$y46_3 >> 3];
+ $y48_3 = $c + 56 | 0;
+ HEAPF64[$y48_3 >> 3] = $16;
+ $arrayidx52 = $c | 0;
+ $x53 = $c | 0;
+ $17 = +HEAPF64[$x53 >> 3];
+ $x54 = $pt | 0;
+ $18 = +HEAPF64[$x54 >> 3];
+ $sub55 = $17 - $18;
+ $mul60 = $sub55 * $sub55;
+ $y62 = $c + 8 | 0;
+ $19 = +HEAPF64[$y62 >> 3];
+ $y63 = $pt + 8 | 0;
+ $20 = +HEAPF64[$y63 >> 3];
+ $sub64 = $19 - $20;
+ $mul69 = $sub64 * $sub64;
+ $add70 = $mul60 + $mul69;
+ $x72 = $c + 48 | 0;
+ $21 = +HEAPF64[$x72 >> 3];
+ $sub74 = $21 - $18;
+ $mul79 = $sub74 * $sub74;
+ $y81 = $c + 56 | 0;
+ $22 = +HEAPF64[$y81 >> 3];
+ $sub83 = $22 - $20;
+ $mul88 = $sub83 * $sub83;
+ $add89 = $mul79 + $mul88;
+ _Bezier($tmp, $arrayidx52, 3, .5, 0, 0);
+ $pt2_sroa_0_0__idx17 = $tmp | 0;
+ $pt2_sroa_0_0_copyload1851 = +HEAPF64[$pt2_sroa_0_0__idx17 >> 3];
+ $pt2_sroa_1_8__idx23 = $tmp + 8 | 0;
+ $pt2_sroa_1_8_copyload2452 = +HEAPF64[$pt2_sroa_1_8__idx23 >> 3];
+ $sub9253 = $add70 - $add89;
+ $call54 = +Math_abs(+$sub9253);
+ $cmp9355 = $call54 < 1.0;
+ if ($cmp9355) {
+ $pt2_sroa_0_0_copyload18_lcssa = $pt2_sroa_0_0_copyload1851;
+ $pt2_sroa_1_8_copyload24_lcssa = $pt2_sroa_1_8_copyload2452;
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $23 = +HEAPF64[$x54 >> 3];
+ $24 = +HEAPF64[$y63 >> 3];
+ $dlow2_056 = $add70;
+ $dhigh2_057 = $add89;
+ $low_058 = 0.0;
+ $high_059 = 1.0;
+ $div9160 = .5;
+ $pt2_sroa_0_0_copyload1861 = $pt2_sroa_0_0_copyload1851;
+ $pt2_sroa_1_8_copyload2462 = $pt2_sroa_1_8_copyload2452;
+ label = 9;
+ break;
+ case 9:
+ $sub96 = $high_059 - $low_058;
+ $call97 = +Math_abs(+$sub96);
+ $cmp98 = $call97 < 1.0e-5;
+ if ($cmp98) {
+ $pt2_sroa_0_0_copyload18_lcssa = $pt2_sroa_0_0_copyload1861;
+ $pt2_sroa_1_8_copyload24_lcssa = $pt2_sroa_1_8_copyload2462;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $cmp101 = $dlow2_056 < $dhigh2_057;
+ $sub105 = $pt2_sroa_0_0_copyload1861 - $23;
+ $mul109 = $sub105 * $sub105;
+ $sub112 = $pt2_sroa_1_8_copyload2462 - $24;
+ $mul116 = $sub112 * $sub112;
+ $add117 = $mul109 + $mul116;
+ $dlow2_0_add117 = $cmp101 ? $dlow2_056 : $add117;
+ $add117_dhigh2_0 = $cmp101 ? $add117 : $dhigh2_057;
+ $low_0_div91 = $cmp101 ? $low_058 : $div9160;
+ $div91_high_0 = $cmp101 ? $div9160 : $high_059;
+ $add90 = $low_0_div91 + $div91_high_0;
+ $div91 = $add90 * .5;
+ _Bezier($tmp, $arrayidx52, 3, $div91, 0, 0);
+ $pt2_sroa_0_0_copyload18 = +HEAPF64[$pt2_sroa_0_0__idx17 >> 3];
+ $pt2_sroa_1_8_copyload24 = +HEAPF64[$pt2_sroa_1_8__idx23 >> 3];
+ $sub92 = $dlow2_0_add117 - $add117_dhigh2_0;
+ $call = +Math_abs(+$sub92);
+ $cmp93 = $call < 1.0;
+ if ($cmp93) {
+ $pt2_sroa_0_0_copyload18_lcssa = $pt2_sroa_0_0_copyload18;
+ $pt2_sroa_1_8_copyload24_lcssa = $pt2_sroa_1_8_copyload24;
+ label = 11;
+ break;
+ } else {
+ $dlow2_056 = $dlow2_0_add117;
+ $dhigh2_057 = $add117_dhigh2_0;
+ $low_058 = $low_0_div91;
+ $high_059 = $div91_high_0;
+ $div9160 = $div91;
+ $pt2_sroa_0_0_copyload1861 = $pt2_sroa_0_0_copyload18;
+ $pt2_sroa_1_8_copyload2462 = $pt2_sroa_1_8_copyload24;
+ label = 9;
+ break;
+ }
+ case 11:
+ $pt2_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$pt2_sroa_0_0__idx >> 3] = $pt2_sroa_0_0_copyload18_lcssa;
+ $pt2_sroa_1_8__idx19 = $agg_result + 8 | 0;
+ HEAPF64[$pt2_sroa_1_8__idx19 >> 3] = $pt2_sroa_1_8_copyload24_lcssa;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _common_init_node($n) {
+ $n = $n | 0;
+ var $0 = 0, $1 = 0, $call = 0.0, $width = 0, $2 = 0, $call1 = 0.0, $height = 0, $3 = 0, $call3 = 0, $call4 = 0, $shape = 0, $4 = 0, $index = 0, $5 = 0, $call6 = 0, $6 = 0, $call7 = 0.0, $7 = 0, $call8 = 0, $8 = 0, $call9 = 0, $call10 = 0, $tobool = 0, $cond = 0, $call11 = 0, $cmp = 0, $cond12 = 0, $or = 0, $call16 = 0, $label = 0, $9 = 0, $tobool18 = 0, $index19 = 0, $10 = 0, $call20 = 0, $tobool21 = 0, $11 = 0, $tobool23 = 0, $call24 = 0, $tobool25 = 0, $cond26 = 0, $call30 = 0, $xlabel = 0, $graph = 0, $12 = 0, $has_labels = 0, $13 = 0, $or34 = 0, $14 = 0, $call36 = 0, $conv37 = 0, $showboxes = 0, $15 = 0, $fns = 0, $16 = 0, $initfn = 0, $17 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $n | 0;
+ $1 = HEAP32[41552] | 0;
+ $call = +_late_double($0, $1, .75, .01);
+ $width = $n + 48 | 0;
+ HEAPF64[$width >> 3] = $call;
+ $2 = HEAP32[41592] | 0;
+ $call1 = +_late_double($0, $2, .5, .02);
+ $height = $n + 56 | 0;
+ HEAPF64[$height >> 3] = $call1;
+ $3 = HEAP32[41568] | 0;
+ $call3 = _late_nnstring($0, $3, 152400) | 0;
+ $call4 = _bind_shape($call3, $n) | 0;
+ $shape = $n + 24 | 0;
+ HEAP32[$shape >> 2] = $call4;
+ $4 = HEAP32[41588] | 0;
+ $index = $4 + 8 | 0;
+ $5 = HEAP32[$index >> 2] | 0;
+ $call6 = _agxget($0, $5) | 0;
+ $6 = HEAP32[41596] | 0;
+ $call7 = +_late_double($0, $6, 14.0, 1.0);
+ $7 = HEAP32[41598] | 0;
+ $call8 = _late_nnstring($0, $7, 149008) | 0;
+ $8 = HEAP32[41600] | 0;
+ $call9 = _late_nnstring($0, $8, 146208) | 0;
+ $call10 = _aghtmlstr($call6) | 0;
+ $tobool = ($call10 | 0) != 0;
+ $cond = $tobool ? 2 : 0;
+ $call11 = _shapeOf($n) | 0;
+ $cmp = ($call11 | 0) == 2;
+ $cond12 = $cmp ? 4 : 0;
+ $or = $cond12 | $cond;
+ $call16 = _make_label($0, $call6, $or, $call7, $call8, $call9) | 0;
+ $label = $n + 120 | 0;
+ HEAP32[$label >> 2] = $call16;
+ $9 = HEAP32[41550] | 0;
+ $tobool18 = ($9 | 0) == 0;
+ if ($tobool18) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $index19 = $9 + 8 | 0;
+ $10 = HEAP32[$index19 >> 2] | 0;
+ $call20 = _agxget($0, $10) | 0;
+ $tobool21 = ($call20 | 0) == 0;
+ if ($tobool21) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $11 = HEAP8[$call20] | 0;
+ $tobool23 = $11 << 24 >> 24 == 0;
+ if ($tobool23) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call24 = _aghtmlstr($call20) | 0;
+ $tobool25 = ($call24 | 0) != 0;
+ $cond26 = $tobool25 ? 2 : 0;
+ $call30 = _make_label($0, $call20, $cond26, $call7, $call8, $call9) | 0;
+ $xlabel = $n + 124 | 0;
+ HEAP32[$xlabel >> 2] = $call30;
+ $graph = $n + 20 | 0;
+ $12 = HEAP32[$graph >> 2] | 0;
+ $has_labels = $12 + 153 | 0;
+ $13 = HEAP8[$has_labels] | 0;
+ $or34 = $13 | 16;
+ HEAP8[$has_labels] = $or34;
+ label = 6;
+ break;
+ case 6:
+ $14 = HEAP32[41566] | 0;
+ $call36 = _late_int($0, $14, 0, 0) | 0;
+ $conv37 = $call36 & 255;
+ $showboxes = $n + 160 | 0;
+ HEAP8[$showboxes] = $conv37;
+ $15 = HEAP32[$shape >> 2] | 0;
+ $fns = $15 + 4 | 0;
+ $16 = HEAP32[$fns >> 2] | 0;
+ $initfn = $16 | 0;
+ $17 = HEAP32[$initfn >> 2] | 0;
+ FUNCTION_TABLE_vi[$17 & 1023]($n);
+ return;
+ }
+}
+function _common_init_edge($e) {
+ $e = $e | 0;
+ var $fi = 0, $lfi = 0, $tmp = 0, $tmp132 = 0, $tail = 0, $0 = 0, $graph = 0, $1 = 0, $fontname = 0, $fontname1 = 0, $2 = 0, $tobool = 0, $3 = 0, $index = 0, $4 = 0, $call = 0, $tobool2 = 0, $5 = 0, $tobool4 = 0, $call5 = 0, $tobool6 = 0, $cond = 0, $fontsize = 0, $6 = 0.0, $7 = 0, $fontcolor = 0, $8 = 0, $call8 = 0, $label = 0, $has_labels = 0, $9 = 0, $or = 0, $10 = 0, $call12 = 0, $call13 = 0, $label_ontop = 0, $r_0 = 0, $11 = 0, $tobool15 = 0, $12 = 0, $index17 = 0, $13 = 0, $call18 = 0, $tobool19 = 0, $14 = 0, $tobool23 = 0, $15 = 0, $tobool26 = 0, $call29 = 0, $tobool30 = 0, $cond31 = 0, $fontsize32 = 0, $16 = 0.0, $17 = 0, $fontcolor34 = 0, $18 = 0, $call35 = 0, $xlabel = 0, $has_labels38 = 0, $19 = 0, $or40 = 0, $20 = 0, $tobool43 = 0, $21 = 0, $index45 = 0, $22 = 0, $call46 = 0, $tobool47 = 0, $23 = 0, $tobool51 = 0, $call53 = 0, $tobool54 = 0, $cond55 = 0, $fontsize56 = 0, $24 = 0.0, $25 = 0, $fontcolor58 = 0, $26 = 0, $call59 = 0, $head_label = 0, $has_labels62 = 0, $27 = 0, $or64 = 0, $28 = 0, $tobool67 = 0, $29 = 0, $index69 = 0, $30 = 0, $call70 = 0, $tobool71 = 0, $31 = 0, $tobool75 = 0, $32 = 0, $tobool78 = 0, $call81 = 0, $tobool82 = 0, $cond83 = 0, $fontsize84 = 0, $33 = 0.0, $34 = 0, $fontcolor86 = 0, $35 = 0, $call87 = 0, $tail_label = 0, $has_labels90 = 0, $36 = 0, $or92 = 0, $37 = 0, $call95 = 0, $tobool96 = 0, $38 = 0, $tobool100 = 0, $39 = 0, $has_port = 0, $tail_port = 0, $40 = 0, $shape = 0, $41 = 0, $fns = 0, $42 = 0, $portfn = 0, $43 = 0, $44 = 0, $45 = 0, $46 = 0, $call109 = 0, $tobool110 = 0, $clip = 0, $call115 = 0, $tobool116 = 0, $47 = 0, $tobool120 = 0, $head = 0, $48 = 0, $has_port123 = 0, $head_port = 0, $head126 = 0, $49 = 0, $shape128 = 0, $50 = 0, $fns129 = 0, $51 = 0, $portfn130 = 0, $52 = 0, $53 = 0, $54 = 0, $55 = 0, $call133 = 0, $tobool134 = 0, $clip138 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 112 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $fi = __stackBase__ | 0;
+ $lfi = __stackBase__ + 16 | 0;
+ $tmp = __stackBase__ + 32 | 0;
+ $tmp132 = __stackBase__ + 72 | 0;
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $fontname = $fi + 8 | 0;
+ HEAP32[$fontname >> 2] = 0;
+ $fontname1 = $lfi + 8 | 0;
+ HEAP32[$fontname1 >> 2] = 0;
+ $2 = HEAP32[41934] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ $r_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $3 = $e | 0;
+ $index = $2 + 8 | 0;
+ $4 = HEAP32[$index >> 2] | 0;
+ $call = _agxget($3, $4) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ $r_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $5 = HEAP8[$call] | 0;
+ $tobool4 = $5 << 24 >> 24 == 0;
+ if ($tobool4) {
+ $r_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _initFontEdgeAttr($e, $fi);
+ $call5 = _aghtmlstr($call) | 0;
+ $tobool6 = ($call5 | 0) != 0;
+ $cond = $tobool6 ? 2 : 0;
+ $fontsize = $fi | 0;
+ $6 = +HEAPF64[$fontsize >> 3];
+ $7 = HEAP32[$fontname >> 2] | 0;
+ $fontcolor = $fi + 12 | 0;
+ $8 = HEAP32[$fontcolor >> 2] | 0;
+ $call8 = _make_label($3, $call, $cond, $6, $7, $8) | 0;
+ $label = $e + 112 | 0;
+ HEAP32[$label >> 2] = $call8;
+ $has_labels = $1 + 153 | 0;
+ $9 = HEAP8[$has_labels] | 0;
+ $or = $9 | 1;
+ HEAP8[$has_labels] = $or;
+ $10 = HEAP32[41932] | 0;
+ $call12 = _late_string($3, $10, 96120) | 0;
+ $call13 = _mapbool($call12) | 0;
+ $label_ontop = $e + 130 | 0;
+ HEAP8[$label_ontop] = $call13;
+ $r_0 = 1;
+ label = 6;
+ break;
+ case 6:
+ $11 = HEAP32[41892] | 0;
+ $tobool15 = ($11 | 0) == 0;
+ if ($tobool15) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $12 = $e | 0;
+ $index17 = $11 + 8 | 0;
+ $13 = HEAP32[$index17 >> 2] | 0;
+ $call18 = _agxget($12, $13) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $14 = HEAP8[$call18] | 0;
+ $tobool23 = $14 << 24 >> 24 == 0;
+ if ($tobool23) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $15 = HEAP32[$fontname >> 2] | 0;
+ $tobool26 = ($15 | 0) == 0;
+ if ($tobool26) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _initFontEdgeAttr($e, $fi);
+ label = 11;
+ break;
+ case 11:
+ $call29 = _aghtmlstr($call18) | 0;
+ $tobool30 = ($call29 | 0) != 0;
+ $cond31 = $tobool30 ? 2 : 0;
+ $fontsize32 = $fi | 0;
+ $16 = +HEAPF64[$fontsize32 >> 3];
+ $17 = HEAP32[$fontname >> 2] | 0;
+ $fontcolor34 = $fi + 12 | 0;
+ $18 = HEAP32[$fontcolor34 >> 2] | 0;
+ $call35 = _make_label($12, $call18, $cond31, $16, $17, $18) | 0;
+ $xlabel = $e + 124 | 0;
+ HEAP32[$xlabel >> 2] = $call35;
+ $has_labels38 = $1 + 153 | 0;
+ $19 = HEAP8[$has_labels38] | 0;
+ $or40 = $19 | 32;
+ HEAP8[$has_labels38] = $or40;
+ label = 12;
+ break;
+ case 12:
+ $20 = HEAP32[41936] | 0;
+ $tobool43 = ($20 | 0) == 0;
+ if ($tobool43) {
+ label = 16;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $21 = $e | 0;
+ $index45 = $20 + 8 | 0;
+ $22 = HEAP32[$index45 >> 2] | 0;
+ $call46 = _agxget($21, $22) | 0;
+ $tobool47 = ($call46 | 0) == 0;
+ if ($tobool47) {
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $23 = HEAP8[$call46] | 0;
+ $tobool51 = $23 << 24 >> 24 == 0;
+ if ($tobool51) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ _initFontLabelEdgeAttr($e, $fi, $lfi);
+ $call53 = _aghtmlstr($call46) | 0;
+ $tobool54 = ($call53 | 0) != 0;
+ $cond55 = $tobool54 ? 2 : 0;
+ $fontsize56 = $lfi | 0;
+ $24 = +HEAPF64[$fontsize56 >> 3];
+ $25 = HEAP32[$fontname1 >> 2] | 0;
+ $fontcolor58 = $lfi + 12 | 0;
+ $26 = HEAP32[$fontcolor58 >> 2] | 0;
+ $call59 = _make_label($21, $call46, $cond55, $24, $25, $26) | 0;
+ $head_label = $e + 116 | 0;
+ HEAP32[$head_label >> 2] = $call59;
+ $has_labels62 = $1 + 153 | 0;
+ $27 = HEAP8[$has_labels62] | 0;
+ $or64 = $27 | 2;
+ HEAP8[$has_labels62] = $or64;
+ label = 16;
+ break;
+ case 16:
+ $28 = HEAP32[41900] | 0;
+ $tobool67 = ($28 | 0) == 0;
+ if ($tobool67) {
+ label = 22;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $29 = $e | 0;
+ $index69 = $28 + 8 | 0;
+ $30 = HEAP32[$index69 >> 2] | 0;
+ $call70 = _agxget($29, $30) | 0;
+ $tobool71 = ($call70 | 0) == 0;
+ if ($tobool71) {
+ label = 22;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $31 = HEAP8[$call70] | 0;
+ $tobool75 = $31 << 24 >> 24 == 0;
+ if ($tobool75) {
+ label = 22;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $32 = HEAP32[$fontname1 >> 2] | 0;
+ $tobool78 = ($32 | 0) == 0;
+ if ($tobool78) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ _initFontLabelEdgeAttr($e, $fi, $lfi);
+ label = 21;
+ break;
+ case 21:
+ $call81 = _aghtmlstr($call70) | 0;
+ $tobool82 = ($call81 | 0) != 0;
+ $cond83 = $tobool82 ? 2 : 0;
+ $fontsize84 = $lfi | 0;
+ $33 = +HEAPF64[$fontsize84 >> 3];
+ $34 = HEAP32[$fontname1 >> 2] | 0;
+ $fontcolor86 = $lfi + 12 | 0;
+ $35 = HEAP32[$fontcolor86 >> 2] | 0;
+ $call87 = _make_label($29, $call70, $cond83, $33, $34, $35) | 0;
+ $tail_label = $e + 120 | 0;
+ HEAP32[$tail_label >> 2] = $call87;
+ $has_labels90 = $1 + 153 | 0;
+ $36 = HEAP8[$has_labels90] | 0;
+ $or92 = $36 | 4;
+ HEAP8[$has_labels90] = $or92;
+ label = 22;
+ break;
+ case 22:
+ $37 = $e | 0;
+ $call95 = _agget($37, 143224) | 0;
+ $tobool96 = ($call95 | 0) == 0;
+ if ($tobool96) {
+ label = 25;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $38 = HEAP8[$call95] | 0;
+ $tobool100 = $38 << 24 >> 24 == 0;
+ if ($tobool100) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $39 = HEAP32[$tail >> 2] | 0;
+ $has_port = $39 + 161 | 0;
+ HEAP8[$has_port] = 1;
+ label = 25;
+ break;
+ case 25:
+ $tail_port = $e + 32 | 0;
+ $40 = HEAP32[$tail >> 2] | 0;
+ $shape = $40 + 24 | 0;
+ $41 = HEAP32[$shape >> 2] | 0;
+ $fns = $41 + 4 | 0;
+ $42 = HEAP32[$fns >> 2] | 0;
+ $portfn = $42 + 8 | 0;
+ $43 = HEAP32[$portfn >> 2] | 0;
+ _chkPort($tmp, $43, $40, $call95);
+ $44 = $tail_port;
+ $45 = $tmp;
+ HEAP32[$44 >> 2] = HEAP32[$45 >> 2] | 0;
+ HEAP32[$44 + 4 >> 2] = HEAP32[$45 + 4 >> 2] | 0;
+ HEAP32[$44 + 8 >> 2] = HEAP32[$45 + 8 >> 2] | 0;
+ HEAP32[$44 + 12 >> 2] = HEAP32[$45 + 12 >> 2] | 0;
+ HEAP32[$44 + 16 >> 2] = HEAP32[$45 + 16 >> 2] | 0;
+ HEAP32[$44 + 20 >> 2] = HEAP32[$45 + 20 >> 2] | 0;
+ HEAP32[$44 + 24 >> 2] = HEAP32[$45 + 24 >> 2] | 0;
+ HEAP32[$44 + 28 >> 2] = HEAP32[$45 + 28 >> 2] | 0;
+ HEAP32[$44 + 32 >> 2] = HEAP32[$45 + 32 >> 2] | 0;
+ HEAP32[$44 + 36 >> 2] = HEAP32[$45 + 36 >> 2] | 0;
+ $46 = HEAP32[41902] | 0;
+ $call109 = _noClip($e, $46) | 0;
+ $tobool110 = $call109 << 24 >> 24 == 0;
+ if ($tobool110) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $clip = $e + 62 | 0;
+ HEAP8[$clip] = 0;
+ label = 27;
+ break;
+ case 27:
+ $call115 = _agget($37, 139592) | 0;
+ $tobool116 = ($call115 | 0) == 0;
+ if ($tobool116) {
+ label = 30;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $47 = HEAP8[$call115] | 0;
+ $tobool120 = $47 << 24 >> 24 == 0;
+ if ($tobool120) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $head = $e + 12 | 0;
+ $48 = HEAP32[$head >> 2] | 0;
+ $has_port123 = $48 + 161 | 0;
+ HEAP8[$has_port123] = 1;
+ label = 30;
+ break;
+ case 30:
+ $head_port = $e + 72 | 0;
+ $head126 = $e + 12 | 0;
+ $49 = HEAP32[$head126 >> 2] | 0;
+ $shape128 = $49 + 24 | 0;
+ $50 = HEAP32[$shape128 >> 2] | 0;
+ $fns129 = $50 + 4 | 0;
+ $51 = HEAP32[$fns129 >> 2] | 0;
+ $portfn130 = $51 + 8 | 0;
+ $52 = HEAP32[$portfn130 >> 2] | 0;
+ _chkPort($tmp132, $52, $49, $call115);
+ $53 = $head_port;
+ $54 = $tmp132;
+ HEAP32[$53 >> 2] = HEAP32[$54 >> 2] | 0;
+ HEAP32[$53 + 4 >> 2] = HEAP32[$54 + 4 >> 2] | 0;
+ HEAP32[$53 + 8 >> 2] = HEAP32[$54 + 8 >> 2] | 0;
+ HEAP32[$53 + 12 >> 2] = HEAP32[$54 + 12 >> 2] | 0;
+ HEAP32[$53 + 16 >> 2] = HEAP32[$54 + 16 >> 2] | 0;
+ HEAP32[$53 + 20 >> 2] = HEAP32[$54 + 20 >> 2] | 0;
+ HEAP32[$53 + 24 >> 2] = HEAP32[$54 + 24 >> 2] | 0;
+ HEAP32[$53 + 28 >> 2] = HEAP32[$54 + 28 >> 2] | 0;
+ HEAP32[$53 + 32 >> 2] = HEAP32[$54 + 32 >> 2] | 0;
+ HEAP32[$53 + 36 >> 2] = HEAP32[$54 + 36 >> 2] | 0;
+ $55 = HEAP32[41938] | 0;
+ $call133 = _noClip($e, $55) | 0;
+ $tobool134 = $call133 << 24 >> 24 == 0;
+ if ($tobool134) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $clip138 = $e + 102 | 0;
+ HEAP8[$clip138] = 0;
+ label = 32;
+ break;
+ case 32:
+ STACKTOP = __stackBase__;
+ return $r_0 | 0;
+ }
+ return 0;
+}
+function _initFontEdgeAttr($e, $fi) {
+ $e = $e | 0;
+ $fi = $fi | 0;
+ var $0 = 0;
+ $0 = $e | 0;
+ HEAPF64[$fi >> 3] = +_late_double($0, HEAP32[41940] | 0, 14.0, 1.0);
+ HEAP32[$fi + 8 >> 2] = _late_nnstring($0, HEAP32[41942] | 0, 149008) | 0;
+ HEAP32[$fi + 12 >> 2] = _late_nnstring($0, HEAP32[41944] | 0, 146208) | 0;
+ return;
+}
+function _sub_pointf($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $sub4 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $sub4 = +HEAPF64[$p + 8 >> 3] - +HEAPF64[$q + 8 >> 3];
+ HEAPF64[$agg_result >> 3] = +HEAPF64[$p >> 3] - +HEAPF64[$q >> 3];
+ HEAPF64[$agg_result + 8 >> 3] = $sub4;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _add_pointf($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $add4 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $add4 = +HEAPF64[$p + 8 >> 3] + +HEAPF64[$q + 8 >> 3];
+ HEAPF64[$agg_result >> 3] = +HEAPF64[$p >> 3] + +HEAPF64[$q >> 3];
+ HEAPF64[$agg_result + 8 >> 3] = $add4;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _initFontLabelEdgeAttr($e, $fi, $lfi) {
+ $e = $e | 0;
+ $fi = $fi | 0;
+ $lfi = $lfi | 0;
+ var $fontname = 0, $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $fontsize = 0, $3 = 0.0, $call = 0.0, $fontsize1 = 0, $4 = 0, $5 = 0, $call3 = 0, $fontname4 = 0, $6 = 0, $fontcolor = 0, $7 = 0, $call5 = 0, $fontcolor6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $fontname = $fi + 8 | 0;
+ $0 = HEAP32[$fontname >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _initFontEdgeAttr($e, $fi);
+ label = 4;
+ break;
+ case 4:
+ $1 = $e | 0;
+ $2 = HEAP32[41922] | 0;
+ $fontsize = $fi | 0;
+ $3 = +HEAPF64[$fontsize >> 3];
+ $call = +_late_double($1, $2, $3, 1.0);
+ $fontsize1 = $lfi | 0;
+ HEAPF64[$fontsize1 >> 3] = $call;
+ $4 = HEAP32[41924] | 0;
+ $5 = HEAP32[$fontname >> 2] | 0;
+ $call3 = _late_nnstring($1, $4, $5) | 0;
+ $fontname4 = $lfi + 8 | 0;
+ HEAP32[$fontname4 >> 2] = $call3;
+ $6 = HEAP32[41926] | 0;
+ $fontcolor = $fi + 12 | 0;
+ $7 = HEAP32[$fontcolor >> 2] | 0;
+ $call5 = _late_nnstring($1, $6, $7) | 0;
+ $fontcolor6 = $lfi + 12 | 0;
+ HEAP32[$fontcolor6 >> 2] = $call5;
+ return;
+ }
+}
+function _chkPort($agg_result, $pf, $n, $s) {
+ $agg_result = $agg_result | 0;
+ $pf = $pf | 0;
+ $n = $n | 0;
+ $s = $s | 0;
+ var $pt_sroa_0 = 0, $tmp = 0, $tmp2 = 0, $call = 0, $tobool = 0, $add_ptr = 0, $pt_sroa_0_0__cast7 = 0, $pt_sroa_0_0_idx8 = 0, $pt_sroa_0_0__cast5 = 0, $pt_sroa_0_0_idx6 = 0, $pt_sroa_0_0__cast = 0, $pt_sroa_0_0_idx = 0, $pt_sroa_1_36__idx9 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 120 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pt_sroa_0 = __stackBase__ | 0;
+ $tmp = __stackBase__ + 40 | 0;
+ $tmp2 = __stackBase__ + 80 | 0;
+ $call = _strchr($s | 0, 58) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAP8[$call] = 0;
+ $add_ptr = $call + 1 | 0;
+ FUNCTION_TABLE_viiii[$pf & 1023]($tmp, $n, $s, $add_ptr);
+ $pt_sroa_0_0__cast7 = $tmp;
+ $pt_sroa_0_0_idx8 = $pt_sroa_0 | 0;
+ HEAP32[$pt_sroa_0_0_idx8 >> 2] = HEAP32[$pt_sroa_0_0__cast7 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx8 + 4 >> 2] = HEAP32[$pt_sroa_0_0__cast7 + 4 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx8 + 8 >> 2] = HEAP32[$pt_sroa_0_0__cast7 + 8 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx8 + 12 >> 2] = HEAP32[$pt_sroa_0_0__cast7 + 12 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx8 + 16 >> 2] = HEAP32[$pt_sroa_0_0__cast7 + 16 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx8 + 20 >> 2] = HEAP32[$pt_sroa_0_0__cast7 + 20 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx8 + 24 >> 2] = HEAP32[$pt_sroa_0_0__cast7 + 24 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx8 + 28 >> 2] = HEAP32[$pt_sroa_0_0__cast7 + 28 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx8 + 32 >> 2] = HEAP32[$pt_sroa_0_0__cast7 + 32 >> 2] | 0;
+ HEAP8[$call] = 58;
+ label = 5;
+ break;
+ case 4:
+ FUNCTION_TABLE_viiii[$pf & 1023]($tmp2, $n, $s, 0);
+ $pt_sroa_0_0__cast5 = $tmp2;
+ $pt_sroa_0_0_idx6 = $pt_sroa_0 | 0;
+ HEAP32[$pt_sroa_0_0_idx6 >> 2] = HEAP32[$pt_sroa_0_0__cast5 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx6 + 4 >> 2] = HEAP32[$pt_sroa_0_0__cast5 + 4 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx6 + 8 >> 2] = HEAP32[$pt_sroa_0_0__cast5 + 8 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx6 + 12 >> 2] = HEAP32[$pt_sroa_0_0__cast5 + 12 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx6 + 16 >> 2] = HEAP32[$pt_sroa_0_0__cast5 + 16 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx6 + 20 >> 2] = HEAP32[$pt_sroa_0_0__cast5 + 20 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx6 + 24 >> 2] = HEAP32[$pt_sroa_0_0__cast5 + 24 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx6 + 28 >> 2] = HEAP32[$pt_sroa_0_0__cast5 + 28 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0_idx6 + 32 >> 2] = HEAP32[$pt_sroa_0_0__cast5 + 32 >> 2] | 0;
+ label = 5;
+ break;
+ case 5:
+ $pt_sroa_0_0__cast = $agg_result;
+ $pt_sroa_0_0_idx = $pt_sroa_0 | 0;
+ HEAP32[$pt_sroa_0_0__cast >> 2] = HEAP32[$pt_sroa_0_0_idx >> 2] | 0;
+ HEAP32[$pt_sroa_0_0__cast + 4 >> 2] = HEAP32[$pt_sroa_0_0_idx + 4 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0__cast + 8 >> 2] = HEAP32[$pt_sroa_0_0_idx + 8 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0__cast + 12 >> 2] = HEAP32[$pt_sroa_0_0_idx + 12 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0__cast + 16 >> 2] = HEAP32[$pt_sroa_0_0_idx + 16 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0__cast + 20 >> 2] = HEAP32[$pt_sroa_0_0_idx + 20 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0__cast + 24 >> 2] = HEAP32[$pt_sroa_0_0_idx + 24 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0__cast + 28 >> 2] = HEAP32[$pt_sroa_0_0_idx + 28 >> 2] | 0;
+ HEAP32[$pt_sroa_0_0__cast + 32 >> 2] = HEAP32[$pt_sroa_0_0_idx + 32 >> 2] | 0;
+ $pt_sroa_1_36__idx9 = $agg_result + 36 | 0;
+ HEAP32[$pt_sroa_1_36__idx9 >> 2] = $s;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _noClip($e, $sym) {
+ $e = $e | 0;
+ $sym = $sym | 0;
+ var $tobool = 0, $0 = 0, $index = 0, $1 = 0, $call = 0, $tobool1 = 0, $2 = 0, $tobool2 = 0, $call4 = 0, $lnot = 0, $conv6 = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($sym | 0) == 0;
+ if ($tobool) {
+ $rv_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = $e | 0;
+ $index = $sym + 8 | 0;
+ $1 = HEAP32[$index >> 2] | 0;
+ $call = _agxget($0, $1) | 0;
+ $tobool1 = ($call | 0) == 0;
+ if ($tobool1) {
+ $rv_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP8[$call] | 0;
+ $tobool2 = $2 << 24 >> 24 == 0;
+ if ($tobool2) {
+ $rv_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call4 = _mapbool($call) | 0;
+ $lnot = $call4 << 24 >> 24 == 0;
+ $conv6 = $lnot & 1;
+ $rv_0 = $conv6;
+ label = 6;
+ break;
+ case 6:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _updateBB($g, $lp) {
+ $g = $g | 0;
+ $lp = $lp | 0;
+ var $tmp = 0, $bb = 0, $1 = 0, $2 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ $tmp = __stackBase__ | 0;
+ $bb = $g + 56 | 0;
+ _addLabelBB($tmp, $bb, $lp, HEAP32[$g + 156 >> 2] & 1);
+ $1 = $bb;
+ $2 = $tmp;
+ HEAP32[$1 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ HEAP32[$1 + 16 >> 2] = HEAP32[$2 + 16 >> 2] | 0;
+ HEAP32[$1 + 20 >> 2] = HEAP32[$2 + 20 >> 2] | 0;
+ HEAP32[$1 + 24 >> 2] = HEAP32[$2 + 24 >> 2] | 0;
+ HEAP32[$1 + 28 >> 2] = HEAP32[$2 + 28 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _addLabelBB($agg_result, $bb, $lp, $flipxy) {
+ $agg_result = $agg_result | 0;
+ $bb = $bb | 0;
+ $lp = $lp | 0;
+ $flipxy = $flipxy | 0;
+ var $p_sroa_0_0__idx = 0, $p_sroa_0_0_copyload = 0.0, $p_sroa_1_8__idx9 = 0, $p_sroa_1_8_copyload = 0.0, $tobool = 0, $x = 0, $0 = 0.0, $y5 = 0, $1 = 0.0, $_ = 0.0, $_15 = 0.0, $div = 0.0, $sub = 0.0, $add = 0.0, $x9 = 0, $2 = 0.0, $cmp = 0, $x14 = 0, $3 = 0.0, $cmp15 = 0, $div21 = 0.0, $sub22 = 0.0, $add25 = 0.0, $y27 = 0, $4 = 0.0, $cmp28 = 0, $y34 = 0, $5 = 0.0, $cmp35 = 0, $6 = 0, $7 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $bb;
+ $bb = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($bb, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p_sroa_0_0__idx = $lp + 56 | 0;
+ $p_sroa_0_0_copyload = +HEAPF64[$p_sroa_0_0__idx >> 3];
+ $p_sroa_1_8__idx9 = $lp + 64 | 0;
+ $p_sroa_1_8_copyload = +HEAPF64[$p_sroa_1_8__idx9 >> 3];
+ $tobool = $flipxy << 24 >> 24 == 0;
+ $x = $lp + 24 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $y5 = $lp + 32 | 0;
+ $1 = +HEAPF64[$y5 >> 3];
+ $_ = $tobool ? $1 : $0;
+ $_15 = $tobool ? $0 : $1;
+ $div = $_15 * .5;
+ $sub = $p_sroa_0_0_copyload - $div;
+ $add = $p_sroa_0_0_copyload + $div;
+ $x9 = $bb | 0;
+ $2 = +HEAPF64[$x9 >> 3];
+ $cmp = $sub < $2;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAPF64[$x9 >> 3] = $sub;
+ label = 4;
+ break;
+ case 4:
+ $x14 = $bb + 16 | 0;
+ $3 = +HEAPF64[$x14 >> 3];
+ $cmp15 = $add > $3;
+ if ($cmp15) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAPF64[$x14 >> 3] = $add;
+ label = 6;
+ break;
+ case 6:
+ $div21 = $_ * .5;
+ $sub22 = $p_sroa_1_8_copyload - $div21;
+ $add25 = $p_sroa_1_8_copyload + $div21;
+ $y27 = $bb + 8 | 0;
+ $4 = +HEAPF64[$y27 >> 3];
+ $cmp28 = $sub22 < $4;
+ if ($cmp28) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAPF64[$y27 >> 3] = $sub22;
+ label = 8;
+ break;
+ case 8:
+ $y34 = $bb + 24 | 0;
+ $5 = +HEAPF64[$y34 >> 3];
+ $cmp35 = $add25 > $5;
+ if ($cmp35) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ HEAPF64[$y34 >> 3] = $add25;
+ label = 10;
+ break;
+ case 10:
+ $6 = $agg_result;
+ $7 = $bb;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ HEAP32[$6 + 16 >> 2] = HEAP32[$7 + 16 >> 2] | 0;
+ HEAP32[$6 + 20 >> 2] = HEAP32[$7 + 20 >> 2] | 0;
+ HEAP32[$6 + 24 >> 2] = HEAP32[$7 + 24 >> 2] | 0;
+ HEAP32[$6 + 28 >> 2] = HEAP32[$7 + 28 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _strncasecmp($s1, $s2, $n) {
+ $s1 = $s1 | 0;
+ $s2 = $s2 | 0;
+ $n = $n | 0;
+ var $cmp = 0, $dec15_in = 0, $s2_addr_014 = 0, $s1_addr_013 = 0, $dec15 = 0, $0 = 0, $conv = 0, $call = 0, $1 = 0, $conv2 = 0, $call3 = 0, $cmp4 = 0, $cmp6 = 0, $2 = 0, $cmp9 = 0, $3 = 0, $cmp13 = 0, $incdec_ptr = 0, $incdec_ptr17 = 0, $cmp1 = 0, $s2_addr_0_lcssa = 0, $s1_addr_0_lcssa = 0, $4 = 0, $conv18 = 0, $call19 = 0, $5 = 0, $conv20 = 0, $call21 = 0, $sub = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($n | 0) == 0;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ $s1_addr_013 = $s1;
+ $s2_addr_014 = $s2;
+ $dec15_in = $n;
+ label = 3;
+ break;
+ }
+ case 3:
+ $dec15 = $dec15_in - 1 | 0;
+ $0 = HEAP8[$s1_addr_013] | 0;
+ $conv = $0 & 255;
+ $call = _tolower($conv | 0) | 0;
+ $1 = HEAP8[$s2_addr_014] | 0;
+ $conv2 = $1 & 255;
+ $call3 = _tolower($conv2 | 0) | 0;
+ $cmp4 = ($call | 0) == ($call3 | 0);
+ if ($cmp4) {
+ label = 4;
+ break;
+ } else {
+ $s1_addr_0_lcssa = $s1_addr_013;
+ $s2_addr_0_lcssa = $s2_addr_014;
+ label = 8;
+ break;
+ }
+ case 4:
+ $cmp6 = ($dec15 | 0) == 0;
+ if ($cmp6) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP8[$s1_addr_013] | 0;
+ $cmp9 = $2 << 24 >> 24 == 0;
+ if ($cmp9) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = HEAP8[$s2_addr_014] | 0;
+ $cmp13 = $3 << 24 >> 24 == 0;
+ if ($cmp13) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $incdec_ptr = $s1_addr_013 + 1 | 0;
+ $incdec_ptr17 = $s2_addr_014 + 1 | 0;
+ $cmp1 = ($dec15 | 0) == 0;
+ if ($cmp1) {
+ $s1_addr_0_lcssa = $incdec_ptr;
+ $s2_addr_0_lcssa = $incdec_ptr17;
+ label = 8;
+ break;
+ } else {
+ $s1_addr_013 = $incdec_ptr;
+ $s2_addr_014 = $incdec_ptr17;
+ $dec15_in = $dec15;
+ label = 3;
+ break;
+ }
+ case 8:
+ $4 = HEAP8[$s1_addr_0_lcssa] | 0;
+ $conv18 = $4 & 255;
+ $call19 = _tolower($conv18 | 0) | 0;
+ $5 = HEAP8[$s2_addr_0_lcssa] | 0;
+ $conv20 = $5 & 255;
+ $call21 = _tolower($conv20 | 0) | 0;
+ $sub = $call19 - $call21 | 0;
+ $retval_0 = $sub;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _undoClusterEdges($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $1 = 0, $2 = 0, $call1 = 0, $tobool20 = 0, $n_0_in21 = 0, $call2 = 0, $tobool418 = 0, $e_0_in19 = 0, $e_0 = 0, $call6 = 0, $tobool4 = 0, $call8 = 0, $tobool = 0, $3 = 0, $call10 = 0, $tobool1216 = 0, $n_1_in17 = 0, $4 = 0, $call15 = 0, $tobool12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agsubg($0, 132056) | 0;
+ $1 = $call;
+ $2 = $g;
+ $call1 = _agfstnode($2) | 0;
+ $tobool20 = ($call1 | 0) == 0;
+ if ($tobool20) {
+ label = 6;
+ break;
+ } else {
+ $n_0_in21 = $call1;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call2 = _agfstout($2, $n_0_in21) | 0;
+ $tobool418 = ($call2 | 0) == 0;
+ if ($tobool418) {
+ label = 5;
+ break;
+ } else {
+ $e_0_in19 = $call2;
+ label = 4;
+ break;
+ }
+ case 4:
+ $e_0 = $e_0_in19;
+ _undoCompound($e_0, $1);
+ $call6 = _agnxtout($2, $e_0_in19) | 0;
+ $tobool4 = ($call6 | 0) == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ $e_0_in19 = $call6;
+ label = 4;
+ break;
+ }
+ case 5:
+ $call8 = _agnxtnode($2, $n_0_in21) | 0;
+ $tobool = ($call8 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_0_in21 = $call8;
+ label = 3;
+ break;
+ }
+ case 6:
+ $3 = $call;
+ $call10 = _agfstnode($3) | 0;
+ $tobool1216 = ($call10 | 0) == 0;
+ if ($tobool1216) {
+ label = 8;
+ break;
+ } else {
+ $n_1_in17 = $call10;
+ label = 7;
+ break;
+ }
+ case 7:
+ $4 = $n_1_in17 | 0;
+ _agdelete($0, $4);
+ $call15 = _agnxtnode($3, $n_1_in17) | 0;
+ $tobool12 = ($call15 | 0) == 0;
+ if ($tobool12) {
+ label = 8;
+ break;
+ } else {
+ $n_1_in17 = $call15;
+ label = 7;
+ break;
+ }
+ case 8:
+ _agclose($call);
+ return;
+ }
+}
+function _undoCompound($e, $clg) {
+ $e = $e | 0;
+ $clg = $clg | 0;
+ var $tail = 0, $0 = 0, $head = 0, $1 = 0, $clustnode = 0, $2 = 0, $tobool = 0, $clustnode2 = 0, $3 = 0, $tobool4 = 0, $call = 0, $call5 = 0, $call6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $head = $e + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $clustnode = $0 + 134 | 0;
+ $2 = HEAP8[$clustnode] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $clustnode2 = $1 + 134 | 0;
+ $3 = HEAP8[$clustnode2] | 0;
+ $tobool4 = $3 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _mapN($0, $clg) | 0;
+ $call5 = _mapN($1, $clg) | 0;
+ $call6 = _cloneEdge($e, $call, $call5) | 0;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _safe_dcl($g, $obj, $name, $def, $fun) {
+ $g = $g | 0;
+ $obj = $obj | 0;
+ $name = $name | 0;
+ $def = $def | 0;
+ $fun = $fun | 0;
+ var $call = 0, $cmp = 0, $call1 = 0, $a_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agfindattr($obj, $name) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $a_0 = $call;
+ label = 4;
+ break;
+ }
+ case 3:
+ $call1 = FUNCTION_TABLE_iiii[$fun & 1023]($g, $name, $def) | 0;
+ $a_0 = $call1;
+ label = 4;
+ break;
+ case 4:
+ return $a_0 | 0;
+ }
+ return 0;
+}
+function _scanEntity($t, $xb) {
+ $t = $t | 0;
+ $xb = $xb | 0;
+ var $key = 0, $buf = 0, $call = 0, $ptr = 0, $0 = 0, $eptr = 0, $1 = 0, $cmp = 0, $call1 = 0, $2 = 0, $incdec_ptr = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $sub_ptr_sub_off = 0, $3 = 0, $arraydecay = 0, $call7 = 0, $arrayidx = 0, $name = 0, $4 = 0, $call9 = 0, $tobool10 = 0, $value = 0, $5 = 0, $6 = 0, $call14 = 0, $7 = 0, $8 = 0, $cmp17 = 0, $call19 = 0, $9 = 0, $incdec_ptr24 = 0, $call26 = 0, $10 = 0, $11 = 0, $cmp29 = 0, $call31 = 0, $12 = 0, $incdec_ptr36 = 0, $add_ptr = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 24 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $key = __stackBase__ | 0;
+ $buf = __stackBase__ + 8 | 0;
+ $call = _strchr($t | 0, 59) | 0;
+ $ptr = $xb + 4 | 0;
+ $0 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $xb + 8 | 0;
+ $1 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $0 >>> 0 < $1 >>> 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agxbmore($xb, 1) | 0;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $2 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$2] = 38;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = $t;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $sub_ptr_lhs_cast = $call;
+ $sub_ptr_rhs_cast = $t;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $sub_ptr_sub_off = $sub_ptr_sub - 2 | 0;
+ $3 = $sub_ptr_sub_off >>> 0 > 6;
+ if ($3) {
+ $retval_0 = $t;
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $arraydecay = $buf | 0;
+ $call7 = _strncpy($arraydecay | 0, $t | 0, $sub_ptr_sub | 0) | 0;
+ $arrayidx = $buf + $sub_ptr_sub | 0;
+ HEAP8[$arrayidx] = 0;
+ $name = $key | 0;
+ HEAP32[$name >> 2] = $arraydecay;
+ $4 = $key;
+ $call9 = _bsearch($4 | 0, 18184, 252, 8, 176) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ $retval_0 = $t;
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $value = $call9 + 4 | 0;
+ $5 = $value;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $call14 = _sprintf($arraydecay | 0, 130264, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $6, tempInt) | 0) | 0;
+ $7 = HEAP32[$ptr >> 2] | 0;
+ $8 = HEAP32[$eptr >> 2] | 0;
+ $cmp17 = $7 >>> 0 < $8 >>> 0;
+ if ($cmp17) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call19 = _agxbmore($xb, 1) | 0;
+ label = 9;
+ break;
+ case 9:
+ $9 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr24 = $9 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr24;
+ HEAP8[$9] = 35;
+ $call26 = _agxbput($xb, $arraydecay) | 0;
+ $10 = HEAP32[$ptr >> 2] | 0;
+ $11 = HEAP32[$eptr >> 2] | 0;
+ $cmp29 = $10 >>> 0 < $11 >>> 0;
+ if ($cmp29) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call31 = _agxbmore($xb, 1) | 0;
+ label = 11;
+ break;
+ case 11:
+ $12 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr36 = $12 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr36;
+ HEAP8[$12] = 59;
+ $add_ptr = $call + 1 | 0;
+ $retval_0 = $add_ptr;
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _comp_entities($e1, $e2) {
+ $e1 = $e1 | 0;
+ $e2 = $e2 | 0;
+ return _strcmp(HEAP32[$e1 >> 2] | 0, HEAP32[$e2 >> 2] | 0) | 0;
+}
+function _htmlEntityUTF8($s) {
+ $s = $s | 0;
+ var $s_addr = 0, $xb = 0, $buf = 0, $arraydecay = 0, $0 = 0, $incdec_ptr17 = 0, $1 = 0, $tobool18 = 0, $ptr = 0, $eptr = 0, $ptr142 = 0, $eptr143 = 0, $ptr78 = 0, $eptr79 = 0, $ptr108 = 0, $eptr109 = 0, $2 = 0, $incdec_ptr19 = 0, $3 = 0, $cmp = 0, $cmp3 = 0, $call = 0, $tobool6 = 0, $cmp8 = 0, $conv11 = 0, $cmp12 = 0, $4 = 0, $5 = 0, $cmp15 = 0, $call17 = 0, $shr = 0, $or = 0, $conv20 = 0, $6 = 0, $incdec_ptr22 = 0, $and = 0, $or24 = 0, $conv25 = 0, $call32 = 0, $shr36 = 0, $or39 = 0, $conv40 = 0, $7 = 0, $incdec_ptr42 = 0, $8 = 0, $9 = 0, $cmp46 = 0, $call49 = 0, $shr53 = 0, $conv56 = 0, $or57 = 0, $conv58 = 0, $10 = 0, $incdec_ptr60 = 0, $and62 = 0, $or63 = 0, $conv64 = 0, $cmp70 = 0, $11 = 0, $and74 = 0, $cmp75 = 0, $12 = 0, $13 = 0, $cmp80 = 0, $call83 = 0, $14 = 0, $incdec_ptr88 = 0, $15 = 0, $incdec_ptr90 = 0, $16 = 0, $call92 = 0, $cmp96 = 0, $17 = 0, $and100 = 0, $cmp101 = 0, $arrayidx = 0, $18 = 0, $and104 = 0, $cmp105 = 0, $19 = 0, $20 = 0, $cmp110 = 0, $call113 = 0, $21 = 0, $incdec_ptr118 = 0, $22 = 0, $incdec_ptr120 = 0, $23 = 0, $24 = 0, $25 = 0, $cmp123 = 0, $call126 = 0, $26 = 0, $incdec_ptr131 = 0, $27 = 0, $incdec_ptr133 = 0, $28 = 0, $call135 = 0, $call138 = 0, $c_0 = 0, $29 = 0, $30 = 0, $cmp144 = 0, $call147 = 0, $31 = 0, $incdec_ptr152 = 0, $32 = 0, $incdec_ptr = 0, $33 = 0, $tobool = 0, $ptr154 = 0, $34 = 0, $eptr155 = 0, $35 = 0, $cmp156 = 0, $call159 = 0, $36 = 0, $buf165 = 0, $37 = 0, $call167 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1048 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s_addr = __stackBase__ | 0;
+ $xb = __stackBase__ + 8 | 0;
+ $buf = __stackBase__ + 24 | 0;
+ HEAP32[$s_addr >> 2] = $s;
+ $arraydecay = $buf | 0;
+ _agxbinit($xb, 1024, $arraydecay);
+ $0 = HEAP32[$s_addr >> 2] | 0;
+ $incdec_ptr17 = $0 + 1 | 0;
+ HEAP32[$s_addr >> 2] = $incdec_ptr17;
+ $1 = HEAP8[$0] | 0;
+ $tobool18 = $1 << 24 >> 24 == 0;
+ if ($tobool18) {
+ label = 37;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $ptr = $xb + 4 | 0;
+ $eptr = $xb + 8 | 0;
+ $ptr142 = $xb + 4 | 0;
+ $eptr143 = $xb + 8 | 0;
+ $ptr78 = $xb + 4 | 0;
+ $eptr79 = $xb + 8 | 0;
+ $ptr108 = $xb + 4 | 0;
+ $eptr109 = $xb + 8 | 0;
+ $3 = $0;
+ $incdec_ptr19 = $incdec_ptr17;
+ $2 = $1;
+ label = 4;
+ break;
+ case 4:
+ $cmp = ($2 & 255) < 192;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 5:
+ $cmp3 = $2 << 24 >> 24 == 38;
+ if ($cmp3) {
+ label = 6;
+ break;
+ } else {
+ $c_0 = $2;
+ label = 34;
+ break;
+ }
+ case 6:
+ $call = _htmlEntity($s_addr) | 0;
+ $tobool6 = ($call | 0) == 0;
+ if ($tobool6) {
+ $c_0 = 38;
+ label = 34;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp8 = $call >>> 0 < 127;
+ if ($cmp8) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $conv11 = $call & 255;
+ $c_0 = $conv11;
+ label = 34;
+ break;
+ case 9:
+ $cmp12 = $call >>> 0 < 2047;
+ $4 = HEAP32[$ptr >> 2] | 0;
+ $5 = HEAP32[$eptr >> 2] | 0;
+ $cmp15 = $4 >>> 0 >= $5 >>> 0;
+ if ($cmp12) {
+ label = 10;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 10:
+ if ($cmp15) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $call17 = _agxbmore($xb, 1) | 0;
+ label = 12;
+ break;
+ case 12:
+ $shr = $call >>> 6;
+ $or = $shr | 192;
+ $conv20 = $or & 255;
+ $6 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr22 = $6 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr22;
+ HEAP8[$6] = $conv20;
+ $and = $call & 63;
+ $or24 = $and | 128;
+ $conv25 = $or24 & 255;
+ $c_0 = $conv25;
+ label = 34;
+ break;
+ case 13:
+ if ($cmp15) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $call32 = _agxbmore($xb, 1) | 0;
+ label = 15;
+ break;
+ case 15:
+ $shr36 = $call >>> 12;
+ $or39 = $shr36 | 224;
+ $conv40 = $or39 & 255;
+ $7 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr42 = $7 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr42;
+ HEAP8[$7] = $conv40;
+ $8 = HEAP32[$ptr >> 2] | 0;
+ $9 = HEAP32[$eptr >> 2] | 0;
+ $cmp46 = $8 >>> 0 < $9 >>> 0;
+ if ($cmp46) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $call49 = _agxbmore($xb, 1) | 0;
+ label = 17;
+ break;
+ case 17:
+ $shr53 = $call >>> 6;
+ $conv56 = $shr53 & 63;
+ $or57 = $conv56 | 128;
+ $conv58 = $or57 & 255;
+ $10 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr60 = $10 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr60;
+ HEAP8[$10] = $conv58;
+ $and62 = $call & 63;
+ $or63 = $and62 | 128;
+ $conv64 = $or63 & 255;
+ $c_0 = $conv64;
+ label = 34;
+ break;
+ case 18:
+ $cmp70 = ($2 & 255) < 224;
+ if ($cmp70) {
+ label = 19;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 19:
+ $11 = HEAP8[$incdec_ptr19] | 0;
+ $and74 = $11 & -64;
+ $cmp75 = $and74 << 24 >> 24 == -128;
+ if ($cmp75) {
+ label = 20;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 20:
+ $12 = HEAP32[$ptr78 >> 2] | 0;
+ $13 = HEAP32[$eptr79 >> 2] | 0;
+ $cmp80 = $12 >>> 0 < $13 >>> 0;
+ if ($cmp80) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $call83 = _agxbmore($xb, 1) | 0;
+ label = 22;
+ break;
+ case 22:
+ $14 = HEAP32[$ptr78 >> 2] | 0;
+ $incdec_ptr88 = $14 + 1 | 0;
+ HEAP32[$ptr78 >> 2] = $incdec_ptr88;
+ HEAP8[$14] = $2;
+ $15 = HEAP32[$s_addr >> 2] | 0;
+ $incdec_ptr90 = $15 + 1 | 0;
+ HEAP32[$s_addr >> 2] = $incdec_ptr90;
+ $16 = HEAP8[$15] | 0;
+ $c_0 = $16;
+ label = 34;
+ break;
+ case 23:
+ $call92 = _agerr(1, 128248, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _exit(1);
+ return 0;
+ case 24:
+ $cmp96 = ($2 & 255) < 240;
+ if ($cmp96) {
+ label = 25;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 25:
+ $17 = HEAP8[$incdec_ptr19] | 0;
+ $and100 = $17 & -64;
+ $cmp101 = $and100 << 24 >> 24 == -128;
+ if ($cmp101) {
+ label = 26;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 26:
+ $arrayidx = $3 + 2 | 0;
+ $18 = HEAP8[$arrayidx] | 0;
+ $and104 = $18 & -64;
+ $cmp105 = $and104 << 24 >> 24 == -128;
+ if ($cmp105) {
+ label = 27;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 27:
+ $19 = HEAP32[$ptr108 >> 2] | 0;
+ $20 = HEAP32[$eptr109 >> 2] | 0;
+ $cmp110 = $19 >>> 0 < $20 >>> 0;
+ if ($cmp110) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $call113 = _agxbmore($xb, 1) | 0;
+ label = 29;
+ break;
+ case 29:
+ $21 = HEAP32[$ptr108 >> 2] | 0;
+ $incdec_ptr118 = $21 + 1 | 0;
+ HEAP32[$ptr108 >> 2] = $incdec_ptr118;
+ HEAP8[$21] = $2;
+ $22 = HEAP32[$s_addr >> 2] | 0;
+ $incdec_ptr120 = $22 + 1 | 0;
+ HEAP32[$s_addr >> 2] = $incdec_ptr120;
+ $23 = HEAP8[$22] | 0;
+ $24 = HEAP32[$ptr108 >> 2] | 0;
+ $25 = HEAP32[$eptr109 >> 2] | 0;
+ $cmp123 = $24 >>> 0 < $25 >>> 0;
+ if ($cmp123) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $call126 = _agxbmore($xb, 1) | 0;
+ label = 31;
+ break;
+ case 31:
+ $26 = HEAP32[$ptr108 >> 2] | 0;
+ $incdec_ptr131 = $26 + 1 | 0;
+ HEAP32[$ptr108 >> 2] = $incdec_ptr131;
+ HEAP8[$26] = $23;
+ $27 = HEAP32[$s_addr >> 2] | 0;
+ $incdec_ptr133 = $27 + 1 | 0;
+ HEAP32[$s_addr >> 2] = $incdec_ptr133;
+ $28 = HEAP8[$27] | 0;
+ $c_0 = $28;
+ label = 34;
+ break;
+ case 32:
+ $call135 = _agerr(1, 125632, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _exit(1);
+ return 0;
+ case 33:
+ $call138 = _agerr(1, 123560, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _exit(1);
+ return 0;
+ case 34:
+ $29 = HEAP32[$ptr142 >> 2] | 0;
+ $30 = HEAP32[$eptr143 >> 2] | 0;
+ $cmp144 = $29 >>> 0 < $30 >>> 0;
+ if ($cmp144) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $call147 = _agxbmore($xb, 1) | 0;
+ label = 36;
+ break;
+ case 36:
+ $31 = HEAP32[$ptr142 >> 2] | 0;
+ $incdec_ptr152 = $31 + 1 | 0;
+ HEAP32[$ptr142 >> 2] = $incdec_ptr152;
+ HEAP8[$31] = $c_0;
+ $32 = HEAP32[$s_addr >> 2] | 0;
+ $incdec_ptr = $32 + 1 | 0;
+ HEAP32[$s_addr >> 2] = $incdec_ptr;
+ $33 = HEAP8[$32] | 0;
+ $tobool = $33 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 37;
+ break;
+ } else {
+ $3 = $32;
+ $incdec_ptr19 = $incdec_ptr;
+ $2 = $33;
+ label = 4;
+ break;
+ }
+ case 37:
+ $ptr154 = $xb + 4 | 0;
+ $34 = HEAP32[$ptr154 >> 2] | 0;
+ $eptr155 = $xb + 8 | 0;
+ $35 = HEAP32[$eptr155 >> 2] | 0;
+ $cmp156 = $34 >>> 0 < $35 >>> 0;
+ if ($cmp156) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $call159 = _agxbmore($xb, 1) | 0;
+ label = 39;
+ break;
+ case 39:
+ $36 = HEAP32[$ptr154 >> 2] | 0;
+ HEAP8[$36] = 0;
+ $buf165 = $xb | 0;
+ $37 = HEAP32[$buf165 >> 2] | 0;
+ HEAP32[$ptr154 >> 2] = $37;
+ $call167 = _strdup($37 | 0) | 0;
+ _agxbfree($xb);
+ STACKTOP = __stackBase__;
+ return $call167 | 0;
+ }
+ return 0;
+}
+function _mid_pointf($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $div5 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $div5 = (+HEAPF64[$p + 8 >> 3] + +HEAPF64[$q + 8 >> 3]) * .5;
+ HEAPF64[$agg_result >> 3] = (+HEAPF64[$p >> 3] + +HEAPF64[$q >> 3]) * .5;
+ HEAPF64[$agg_result + 8 >> 3] = $div5;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _boxf_overlap246($b0, $b1) {
+ $b0 = $b0 | 0;
+ $b1 = $b1 | 0;
+ var $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $cmp = 0, $x3 = 0, $2 = 0.0, $x5 = 0, $3 = 0.0, $cmp6 = 0, $y = 0, $4 = 0.0, $y10 = 0, $5 = 0.0, $cmp11 = 0, $y13 = 0, $6 = 0.0, $y15 = 0, $7 = 0.0, $cmp16 = 0, $phitmp = 0, $8 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b0;
+ $b0 = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b0, tempParam, 32);
+ tempParam = $b1;
+ $b1 = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b1, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $b0 + 16 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $b1 | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $cmp = $0 < $1;
+ if ($cmp) {
+ $8 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x3 = $b1 + 16 | 0;
+ $2 = +HEAPF64[$x3 >> 3];
+ $x5 = $b0 | 0;
+ $3 = +HEAPF64[$x5 >> 3];
+ $cmp6 = $2 < $3;
+ if ($cmp6) {
+ $8 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $b0 + 24 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y10 = $b1 + 8 | 0;
+ $5 = +HEAPF64[$y10 >> 3];
+ $cmp11 = $4 < $5;
+ if ($cmp11) {
+ $8 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y13 = $b1 + 24 | 0;
+ $6 = +HEAPF64[$y13 >> 3];
+ $y15 = $b0 + 8 | 0;
+ $7 = +HEAPF64[$y15 >> 3];
+ $cmp16 = $6 >= $7;
+ $phitmp = $cmp16 & 1;
+ $8 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $8 | 0;
+ }
+ return 0;
+}
+function _htmlEntity($s) {
+ $s = $s | 0;
+ var $key = 0, $entity_name_buf = 0, $0 = 0, $1 = 0, $cmp = 0, $add_ptr = 0, $2 = 0, $add_ptr10 = 0, $3 = 0, $conv11 = 0, $_off44 = 0, $4 = 0, $add = 0, $_off45 = 0, $5 = 0, $add24 = 0, $_off46 = 0, $6 = 0, $sub32 = 0, $byte_1 = 0, $add_ptr10_1 = 0, $7 = 0, $conv11_1 = 0, $_off44_1 = 0, $8 = 0, $add_ptr42 = 0, $9 = 0, $conv43 = 0, $_off = 0, $10 = 0, $add52 = 0, $add_ptr42_1 = 0, $11 = 0, $conv43_1 = 0, $_off_1 = 0, $12 = 0, $byte_3 = 0, $i_2 = 0, $n_2 = 0, $cmp59 = 0, $add_ptr63 = 0, $arraydecay = 0, $name = 0, $13 = 0, $p_055_lcssa58 = 0, $i_356_lcssa57 = 0, $14 = 0, $call = 0, $tobool = 0, $value = 0, $15 = 0, $16 = 0, $add_ptr82 = 0, $incdec_ptr86 = 0, $add_ptr71_1 = 0, $17 = 0, $str_0 = 0, $n_3 = 0, $mul50_1 = 0, $sub51_1 = 0, $add52_1 = 0, $add_ptr42_2 = 0, $18 = 0, $conv43_2 = 0, $_off_2 = 0, $19 = 0, $mul50_2 = 0, $sub51_2 = 0, $add52_2 = 0, $add_ptr42_3 = 0, $20 = 0, $conv43_3 = 0, $_off_3 = 0, $21 = 0, $mul50_3 = 0, $sub51_3 = 0, $add52_3 = 0, $add_ptr42_4 = 0, $22 = 0, $conv43_4 = 0, $_off_4 = 0, $23 = 0, $mul50_4 = 0, $sub51_4 = 0, $add52_4 = 0, $add_ptr42_5 = 0, $24 = 0, $conv43_5 = 0, $_off_5 = 0, $25 = 0, $mul50_5 = 0, $sub51_5 = 0, $add52_5 = 0, $add_ptr42_6 = 0, $26 = 0, $conv43_6 = 0, $_off_6 = 0, $27 = 0, $mul50_6 = 0, $sub51_6 = 0, $add52_6 = 0, $_off45_1 = 0, $28 = 0, $_off46_1 = 0, $29 = 0, $sub32_1 = 0, $add24_1 = 0, $add_1 = 0, $byte_1_1 = 0, $mul_1 = 0, $add36_1 = 0, $add_ptr10_2 = 0, $30 = 0, $conv11_2 = 0, $_off44_2 = 0, $31 = 0, $_off45_2 = 0, $32 = 0, $_off46_2 = 0, $33 = 0, $sub32_2 = 0, $add24_2 = 0, $add_2 = 0, $byte_1_2 = 0, $mul_2 = 0, $add36_2 = 0, $add_ptr10_3 = 0, $34 = 0, $conv11_3 = 0, $_off44_3 = 0, $35 = 0, $_off45_3 = 0, $36 = 0, $_off46_3 = 0, $37 = 0, $sub32_3 = 0, $add24_3 = 0, $add_3 = 0, $byte_1_3 = 0, $mul_3 = 0, $add36_3 = 0, $add_ptr10_4 = 0, $38 = 0, $conv11_4 = 0, $_off44_4 = 0, $39 = 0, $_off45_4 = 0, $40 = 0, $_off46_4 = 0, $41 = 0, $sub32_4 = 0, $add24_4 = 0, $add_4 = 0, $byte_1_4 = 0, $mul_4 = 0, $add36_4 = 0, $add_ptr10_5 = 0, $42 = 0, $conv11_5 = 0, $_off44_5 = 0, $43 = 0, $_off45_5 = 0, $44 = 0, $_off46_5 = 0, $45 = 0, $sub32_5 = 0, $add24_5 = 0, $add_5 = 0, $byte_1_5 = 0, $mul_5 = 0, $add36_5 = 0, $incdec_ptr86_1 = 0, $add_ptr71_2 = 0, $46 = 0, $incdec_ptr86_2 = 0, $add_ptr71_3 = 0, $47 = 0, $incdec_ptr86_3 = 0, $add_ptr71_4 = 0, $48 = 0, $incdec_ptr86_4 = 0, $add_ptr71_5 = 0, $49 = 0, $incdec_ptr86_5 = 0, $add_ptr71_6 = 0, $50 = 0, $incdec_ptr86_6 = 0, $add_ptr71_7 = 0, $51 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 24 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $key = __stackBase__ | 0;
+ $entity_name_buf = __stackBase__ + 8 | 0;
+ $0 = HEAP32[$s >> 2] | 0;
+ $1 = HEAP8[$0] | 0;
+ $cmp = $1 << 24 >> 24 == 35;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 3:
+ $add_ptr = $0 + 1 | 0;
+ $2 = HEAP8[$add_ptr] | 0;
+ if (($2 << 24 >> 24 | 0) == 120 | ($2 << 24 >> 24 | 0) == 88) {
+ label = 4;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 4:
+ $add_ptr10 = $0 + 2 | 0;
+ $3 = HEAP8[$add_ptr10] | 0;
+ $conv11 = $3 & 255;
+ $_off44 = $3 - 65 & 255;
+ $4 = ($_off44 & 255) < 6;
+ if ($4) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $add = $conv11 - 55 | 0;
+ $byte_1 = $add;
+ label = 10;
+ break;
+ case 6:
+ $_off45 = $3 - 97 & 255;
+ $5 = ($_off45 & 255) < 6;
+ if ($5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $add24 = $conv11 - 87 | 0;
+ $byte_1 = $add24;
+ label = 10;
+ break;
+ case 8:
+ $_off46 = $3 - 48 & 255;
+ $6 = ($_off46 & 255) < 10;
+ if ($6) {
+ label = 9;
+ break;
+ } else {
+ $n_2 = 0;
+ $i_2 = 3;
+ $byte_3 = $conv11;
+ label = 13;
+ break;
+ }
+ case 9:
+ $sub32 = $conv11 - 48 | 0;
+ $byte_1 = $sub32;
+ label = 10;
+ break;
+ case 10:
+ $add_ptr10_1 = $0 + 3 | 0;
+ $7 = HEAP8[$add_ptr10_1] | 0;
+ $conv11_1 = $7 & 255;
+ $_off44_1 = $7 - 65 & 255;
+ $8 = ($_off44_1 & 255) < 6;
+ if ($8) {
+ label = 30;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 11:
+ $add_ptr42 = $0 + 1 | 0;
+ $9 = HEAP8[$add_ptr42] | 0;
+ $conv43 = $9 & 255;
+ $_off = $9 - 48 & 255;
+ $10 = ($_off & 255) < 10;
+ if ($10) {
+ label = 12;
+ break;
+ } else {
+ $n_2 = 0;
+ $i_2 = 2;
+ $byte_3 = $conv43;
+ label = 13;
+ break;
+ }
+ case 12:
+ $add52 = $conv43 - 48 | 0;
+ $add_ptr42_1 = $0 + 2 | 0;
+ $11 = HEAP8[$add_ptr42_1] | 0;
+ $conv43_1 = $11 & 255;
+ $_off_1 = $11 - 48 & 255;
+ $12 = ($_off_1 & 255) < 10;
+ if ($12) {
+ label = 20;
+ break;
+ } else {
+ $n_2 = $add52;
+ $i_2 = 3;
+ $byte_3 = $conv43_1;
+ label = 13;
+ break;
+ }
+ case 13:
+ $cmp59 = ($byte_3 | 0) == 59;
+ if ($cmp59) {
+ label = 14;
+ break;
+ } else {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ }
+ case 14:
+ $add_ptr63 = $0 + $i_2 | 0;
+ $n_3 = $n_2;
+ $str_0 = $add_ptr63;
+ label = 19;
+ break;
+ case 15:
+ $arraydecay = $entity_name_buf | 0;
+ $name = $key | 0;
+ HEAP32[$name >> 2] = $arraydecay;
+ $13 = HEAP8[$0] | 0;
+ if (($13 << 24 >> 24 | 0) == 59) {
+ $i_356_lcssa57 = 1;
+ $p_055_lcssa58 = $arraydecay;
+ label = 16;
+ break;
+ } else if (($13 << 24 >> 24 | 0) == 0) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 16:
+ HEAP8[$p_055_lcssa58] = 0;
+ $14 = $key;
+ $call = _bsearch($14 | 0, 18184, 252, 8, 176) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $value = $call + 4 | 0;
+ $15 = $value;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $add_ptr82 = $0 + $i_356_lcssa57 | 0;
+ $n_3 = $16;
+ $str_0 = $add_ptr82;
+ label = 19;
+ break;
+ case 18:
+ $incdec_ptr86 = $entity_name_buf + 1 | 0;
+ HEAP8[$arraydecay] = $13;
+ $add_ptr71_1 = $0 + 1 | 0;
+ $17 = HEAP8[$add_ptr71_1] | 0;
+ if (($17 << 24 >> 24 | 0) == 59) {
+ $i_356_lcssa57 = 2;
+ $p_055_lcssa58 = $incdec_ptr86;
+ label = 16;
+ break;
+ } else if (($17 << 24 >> 24 | 0) == 0) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 19:
+ HEAP32[$s >> 2] = $str_0;
+ STACKTOP = __stackBase__;
+ return $n_3 | 0;
+ case 20:
+ $mul50_1 = $add52 * 10 & -1;
+ $sub51_1 = $mul50_1 - 48 | 0;
+ $add52_1 = $sub51_1 + $conv43_1 | 0;
+ $add_ptr42_2 = $0 + 3 | 0;
+ $18 = HEAP8[$add_ptr42_2] | 0;
+ $conv43_2 = $18 & 255;
+ $_off_2 = $18 - 48 & 255;
+ $19 = ($_off_2 & 255) < 10;
+ if ($19) {
+ label = 21;
+ break;
+ } else {
+ $n_2 = $add52_1;
+ $i_2 = 4;
+ $byte_3 = $conv43_2;
+ label = 13;
+ break;
+ }
+ case 21:
+ $mul50_2 = $add52_1 * 10 & -1;
+ $sub51_2 = $mul50_2 - 48 | 0;
+ $add52_2 = $sub51_2 + $conv43_2 | 0;
+ $add_ptr42_3 = $0 + 4 | 0;
+ $20 = HEAP8[$add_ptr42_3] | 0;
+ $conv43_3 = $20 & 255;
+ $_off_3 = $20 - 48 & 255;
+ $21 = ($_off_3 & 255) < 10;
+ if ($21) {
+ label = 22;
+ break;
+ } else {
+ $n_2 = $add52_2;
+ $i_2 = 5;
+ $byte_3 = $conv43_3;
+ label = 13;
+ break;
+ }
+ case 22:
+ $mul50_3 = $add52_2 * 10 & -1;
+ $sub51_3 = $mul50_3 - 48 | 0;
+ $add52_3 = $sub51_3 + $conv43_3 | 0;
+ $add_ptr42_4 = $0 + 5 | 0;
+ $22 = HEAP8[$add_ptr42_4] | 0;
+ $conv43_4 = $22 & 255;
+ $_off_4 = $22 - 48 & 255;
+ $23 = ($_off_4 & 255) < 10;
+ if ($23) {
+ label = 23;
+ break;
+ } else {
+ $n_2 = $add52_3;
+ $i_2 = 6;
+ $byte_3 = $conv43_4;
+ label = 13;
+ break;
+ }
+ case 23:
+ $mul50_4 = $add52_3 * 10 & -1;
+ $sub51_4 = $mul50_4 - 48 | 0;
+ $add52_4 = $sub51_4 + $conv43_4 | 0;
+ $add_ptr42_5 = $0 + 6 | 0;
+ $24 = HEAP8[$add_ptr42_5] | 0;
+ $conv43_5 = $24 & 255;
+ $_off_5 = $24 - 48 & 255;
+ $25 = ($_off_5 & 255) < 10;
+ if ($25) {
+ label = 24;
+ break;
+ } else {
+ $n_2 = $add52_4;
+ $i_2 = 7;
+ $byte_3 = $conv43_5;
+ label = 13;
+ break;
+ }
+ case 24:
+ $mul50_5 = $add52_4 * 10 & -1;
+ $sub51_5 = $mul50_5 - 48 | 0;
+ $add52_5 = $sub51_5 + $conv43_5 | 0;
+ $add_ptr42_6 = $0 + 7 | 0;
+ $26 = HEAP8[$add_ptr42_6] | 0;
+ $conv43_6 = $26 & 255;
+ $_off_6 = $26 - 48 & 255;
+ $27 = ($_off_6 & 255) < 10;
+ if ($27) {
+ label = 25;
+ break;
+ } else {
+ $n_2 = $add52_5;
+ $i_2 = 8;
+ $byte_3 = $conv43_6;
+ label = 13;
+ break;
+ }
+ case 25:
+ $mul50_6 = $add52_5 * 10 & -1;
+ $sub51_6 = $mul50_6 - 48 | 0;
+ $add52_6 = $sub51_6 + $conv43_6 | 0;
+ $n_2 = $add52_6;
+ $i_2 = 9;
+ $byte_3 = $conv43_6;
+ label = 13;
+ break;
+ case 26:
+ $_off45_1 = $7 - 97 & 255;
+ $28 = ($_off45_1 & 255) < 6;
+ if ($28) {
+ label = 29;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $_off46_1 = $7 - 48 & 255;
+ $29 = ($_off46_1 & 255) < 10;
+ if ($29) {
+ label = 28;
+ break;
+ } else {
+ $n_2 = $byte_1;
+ $i_2 = 4;
+ $byte_3 = $conv11_1;
+ label = 13;
+ break;
+ }
+ case 28:
+ $sub32_1 = $conv11_1 - 48 | 0;
+ $byte_1_1 = $sub32_1;
+ label = 31;
+ break;
+ case 29:
+ $add24_1 = $conv11_1 - 87 | 0;
+ $byte_1_1 = $add24_1;
+ label = 31;
+ break;
+ case 30:
+ $add_1 = $conv11_1 - 55 | 0;
+ $byte_1_1 = $add_1;
+ label = 31;
+ break;
+ case 31:
+ $mul_1 = $byte_1 << 4;
+ $add36_1 = $byte_1_1 + $mul_1 | 0;
+ $add_ptr10_2 = $0 + 4 | 0;
+ $30 = HEAP8[$add_ptr10_2] | 0;
+ $conv11_2 = $30 & 255;
+ $_off44_2 = $30 - 65 & 255;
+ $31 = ($_off44_2 & 255) < 6;
+ if ($31) {
+ label = 36;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $_off45_2 = $30 - 97 & 255;
+ $32 = ($_off45_2 & 255) < 6;
+ if ($32) {
+ label = 35;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $_off46_2 = $30 - 48 & 255;
+ $33 = ($_off46_2 & 255) < 10;
+ if ($33) {
+ label = 34;
+ break;
+ } else {
+ $n_2 = $add36_1;
+ $i_2 = 5;
+ $byte_3 = $conv11_2;
+ label = 13;
+ break;
+ }
+ case 34:
+ $sub32_2 = $conv11_2 - 48 | 0;
+ $byte_1_2 = $sub32_2;
+ label = 37;
+ break;
+ case 35:
+ $add24_2 = $conv11_2 - 87 | 0;
+ $byte_1_2 = $add24_2;
+ label = 37;
+ break;
+ case 36:
+ $add_2 = $conv11_2 - 55 | 0;
+ $byte_1_2 = $add_2;
+ label = 37;
+ break;
+ case 37:
+ $mul_2 = $add36_1 << 4;
+ $add36_2 = $byte_1_2 + $mul_2 | 0;
+ $add_ptr10_3 = $0 + 5 | 0;
+ $34 = HEAP8[$add_ptr10_3] | 0;
+ $conv11_3 = $34 & 255;
+ $_off44_3 = $34 - 65 & 255;
+ $35 = ($_off44_3 & 255) < 6;
+ if ($35) {
+ label = 42;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $_off45_3 = $34 - 97 & 255;
+ $36 = ($_off45_3 & 255) < 6;
+ if ($36) {
+ label = 41;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $_off46_3 = $34 - 48 & 255;
+ $37 = ($_off46_3 & 255) < 10;
+ if ($37) {
+ label = 40;
+ break;
+ } else {
+ $n_2 = $add36_2;
+ $i_2 = 6;
+ $byte_3 = $conv11_3;
+ label = 13;
+ break;
+ }
+ case 40:
+ $sub32_3 = $conv11_3 - 48 | 0;
+ $byte_1_3 = $sub32_3;
+ label = 43;
+ break;
+ case 41:
+ $add24_3 = $conv11_3 - 87 | 0;
+ $byte_1_3 = $add24_3;
+ label = 43;
+ break;
+ case 42:
+ $add_3 = $conv11_3 - 55 | 0;
+ $byte_1_3 = $add_3;
+ label = 43;
+ break;
+ case 43:
+ $mul_3 = $add36_2 << 4;
+ $add36_3 = $byte_1_3 + $mul_3 | 0;
+ $add_ptr10_4 = $0 + 6 | 0;
+ $38 = HEAP8[$add_ptr10_4] | 0;
+ $conv11_4 = $38 & 255;
+ $_off44_4 = $38 - 65 & 255;
+ $39 = ($_off44_4 & 255) < 6;
+ if ($39) {
+ label = 48;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $_off45_4 = $38 - 97 & 255;
+ $40 = ($_off45_4 & 255) < 6;
+ if ($40) {
+ label = 47;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $_off46_4 = $38 - 48 & 255;
+ $41 = ($_off46_4 & 255) < 10;
+ if ($41) {
+ label = 46;
+ break;
+ } else {
+ $n_2 = $add36_3;
+ $i_2 = 7;
+ $byte_3 = $conv11_4;
+ label = 13;
+ break;
+ }
+ case 46:
+ $sub32_4 = $conv11_4 - 48 | 0;
+ $byte_1_4 = $sub32_4;
+ label = 49;
+ break;
+ case 47:
+ $add24_4 = $conv11_4 - 87 | 0;
+ $byte_1_4 = $add24_4;
+ label = 49;
+ break;
+ case 48:
+ $add_4 = $conv11_4 - 55 | 0;
+ $byte_1_4 = $add_4;
+ label = 49;
+ break;
+ case 49:
+ $mul_4 = $add36_3 << 4;
+ $add36_4 = $byte_1_4 + $mul_4 | 0;
+ $add_ptr10_5 = $0 + 7 | 0;
+ $42 = HEAP8[$add_ptr10_5] | 0;
+ $conv11_5 = $42 & 255;
+ $_off44_5 = $42 - 65 & 255;
+ $43 = ($_off44_5 & 255) < 6;
+ if ($43) {
+ label = 54;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $_off45_5 = $42 - 97 & 255;
+ $44 = ($_off45_5 & 255) < 6;
+ if ($44) {
+ label = 53;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $_off46_5 = $42 - 48 & 255;
+ $45 = ($_off46_5 & 255) < 10;
+ if ($45) {
+ label = 52;
+ break;
+ } else {
+ $n_2 = $add36_4;
+ $i_2 = 8;
+ $byte_3 = $conv11_5;
+ label = 13;
+ break;
+ }
+ case 52:
+ $sub32_5 = $conv11_5 - 48 | 0;
+ $byte_1_5 = $sub32_5;
+ label = 55;
+ break;
+ case 53:
+ $add24_5 = $conv11_5 - 87 | 0;
+ $byte_1_5 = $add24_5;
+ label = 55;
+ break;
+ case 54:
+ $add_5 = $conv11_5 - 55 | 0;
+ $byte_1_5 = $add_5;
+ label = 55;
+ break;
+ case 55:
+ $mul_5 = $add36_4 << 4;
+ $add36_5 = $byte_1_5 + $mul_5 | 0;
+ $n_2 = $add36_5;
+ $i_2 = 9;
+ $byte_3 = $byte_1_5;
+ label = 13;
+ break;
+ case 56:
+ $incdec_ptr86_1 = $entity_name_buf + 2 | 0;
+ HEAP8[$incdec_ptr86] = $17;
+ $add_ptr71_2 = $0 + 2 | 0;
+ $46 = HEAP8[$add_ptr71_2] | 0;
+ if (($46 << 24 >> 24 | 0) == 59) {
+ $i_356_lcssa57 = 3;
+ $p_055_lcssa58 = $incdec_ptr86_1;
+ label = 16;
+ break;
+ } else if (($46 << 24 >> 24 | 0) == 0) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $incdec_ptr86_2 = $entity_name_buf + 3 | 0;
+ HEAP8[$incdec_ptr86_1] = $46;
+ $add_ptr71_3 = $0 + 3 | 0;
+ $47 = HEAP8[$add_ptr71_3] | 0;
+ if (($47 << 24 >> 24 | 0) == 59) {
+ $i_356_lcssa57 = 4;
+ $p_055_lcssa58 = $incdec_ptr86_2;
+ label = 16;
+ break;
+ } else if (($47 << 24 >> 24 | 0) == 0) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $incdec_ptr86_3 = $entity_name_buf + 4 | 0;
+ HEAP8[$incdec_ptr86_2] = $47;
+ $add_ptr71_4 = $0 + 4 | 0;
+ $48 = HEAP8[$add_ptr71_4] | 0;
+ if (($48 << 24 >> 24 | 0) == 59) {
+ $i_356_lcssa57 = 5;
+ $p_055_lcssa58 = $incdec_ptr86_3;
+ label = 16;
+ break;
+ } else if (($48 << 24 >> 24 | 0) == 0) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ $incdec_ptr86_4 = $entity_name_buf + 5 | 0;
+ HEAP8[$incdec_ptr86_3] = $48;
+ $add_ptr71_5 = $0 + 5 | 0;
+ $49 = HEAP8[$add_ptr71_5] | 0;
+ if (($49 << 24 >> 24 | 0) == 59) {
+ $i_356_lcssa57 = 6;
+ $p_055_lcssa58 = $incdec_ptr86_4;
+ label = 16;
+ break;
+ } else if (($49 << 24 >> 24 | 0) == 0) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $incdec_ptr86_5 = $entity_name_buf + 6 | 0;
+ HEAP8[$incdec_ptr86_4] = $49;
+ $add_ptr71_6 = $0 + 6 | 0;
+ $50 = HEAP8[$add_ptr71_6] | 0;
+ if (($50 << 24 >> 24 | 0) == 59) {
+ $i_356_lcssa57 = 7;
+ $p_055_lcssa58 = $incdec_ptr86_5;
+ label = 16;
+ break;
+ } else if (($50 << 24 >> 24 | 0) == 0) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 61:
+ $incdec_ptr86_6 = $entity_name_buf + 7 | 0;
+ HEAP8[$incdec_ptr86_5] = $50;
+ $add_ptr71_7 = $0 + 7 | 0;
+ $51 = HEAP8[$add_ptr71_7] | 0;
+ if (($51 << 24 >> 24 | 0) == 59) {
+ $i_356_lcssa57 = 8;
+ $p_055_lcssa58 = $incdec_ptr86_6;
+ label = 16;
+ break;
+ } else if (($51 << 24 >> 24 | 0) == 0) {
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 62:
+ HEAP8[$incdec_ptr86_6] = $51;
+ $n_3 = 0;
+ $str_0 = $0;
+ label = 19;
+ break;
+ }
+ return 0;
+}
+function _latin1ToUTF8($s) {
+ $s = $s | 0;
+ var $s_addr = 0, $xb = 0, $buf = 0, $arraydecay = 0, $0 = 0, $incdec_ptr10 = 0, $1 = 0, $tobool11 = 0, $ptr = 0, $eptr = 0, $ptr18 = 0, $eptr19 = 0, $2 = 0, $conv = 0, $cmp = 0, $call = 0, $tobool2 = 0, $_call = 0, $v_0 = 0, $cmp5 = 0, $3 = 0, $4 = 0, $cmp8 = 0, $call10 = 0, $conv11 = 0, $5 = 0, $incdec_ptr13 = 0, $cmp15 = 0, $6 = 0, $7 = 0, $cmp20 = 0, $call23 = 0, $shr = 0, $or = 0, $conv29 = 0, $8 = 0, $incdec_ptr31 = 0, $9 = 0, $10 = 0, $cmp35 = 0, $call38 = 0, $conv43 = 0, $or44 = 0, $conv45 = 0, $11 = 0, $incdec_ptr47 = 0, $12 = 0, $incdec_ptr = 0, $13 = 0, $tobool = 0, $call55 = 0, $shr59 = 0, $or62 = 0, $conv63 = 0, $14 = 0, $incdec_ptr65 = 0, $15 = 0, $16 = 0, $cmp69 = 0, $call72 = 0, $shr76 = 0, $conv79 = 0, $or80 = 0, $conv81 = 0, $17 = 0, $incdec_ptr83 = 0, $18 = 0, $19 = 0, $cmp87 = 0, $call90 = 0, $conv96 = 0, $or97 = 0, $conv98 = 0, $20 = 0, $incdec_ptr100 = 0, $ptr104 = 0, $21 = 0, $eptr105 = 0, $22 = 0, $cmp106 = 0, $call109 = 0, $23 = 0, $buf115 = 0, $24 = 0, $call117 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1048 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s_addr = __stackBase__ | 0;
+ $xb = __stackBase__ + 8 | 0;
+ $buf = __stackBase__ + 24 | 0;
+ HEAP32[$s_addr >> 2] = $s;
+ $arraydecay = $buf | 0;
+ _agxbinit($xb, 1024, $arraydecay);
+ $0 = HEAP32[$s_addr >> 2] | 0;
+ $incdec_ptr10 = $0 + 1 | 0;
+ HEAP32[$s_addr >> 2] = $incdec_ptr10;
+ $1 = HEAP8[$0] | 0;
+ $tobool11 = $1 << 24 >> 24 == 0;
+ if ($tobool11) {
+ label = 24;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $ptr = $xb + 4 | 0;
+ $eptr = $xb + 8 | 0;
+ $ptr18 = $xb + 4 | 0;
+ $eptr19 = $xb + 8 | 0;
+ $2 = $1;
+ label = 4;
+ break;
+ case 4:
+ $conv = $2 & 255;
+ $cmp = $2 << 24 >> 24 == 38;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $v_0 = $conv;
+ label = 6;
+ break;
+ }
+ case 5:
+ $call = _htmlEntity($s_addr) | 0;
+ $tobool2 = ($call | 0) == 0;
+ $_call = $tobool2 ? 38 : $call;
+ $v_0 = $_call;
+ label = 6;
+ break;
+ case 6:
+ $cmp5 = $v_0 >>> 0 < 127;
+ if ($cmp5) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $3 = HEAP32[$ptr >> 2] | 0;
+ $4 = HEAP32[$eptr >> 2] | 0;
+ $cmp8 = $3 >>> 0 < $4 >>> 0;
+ if ($cmp8) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call10 = _agxbmore($xb, 1) | 0;
+ label = 9;
+ break;
+ case 9:
+ $conv11 = $v_0 & 255;
+ $5 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr13 = $5 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr13;
+ HEAP8[$5] = $conv11;
+ label = 16;
+ break;
+ case 10:
+ $cmp15 = $v_0 >>> 0 < 2047;
+ $6 = HEAP32[$ptr18 >> 2] | 0;
+ $7 = HEAP32[$eptr19 >> 2] | 0;
+ $cmp20 = $6 >>> 0 >= $7 >>> 0;
+ if ($cmp15) {
+ label = 11;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 11:
+ if ($cmp20) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $call23 = _agxbmore($xb, 1) | 0;
+ label = 13;
+ break;
+ case 13:
+ $shr = $v_0 >>> 6;
+ $or = $shr | 192;
+ $conv29 = $or & 255;
+ $8 = HEAP32[$ptr18 >> 2] | 0;
+ $incdec_ptr31 = $8 + 1 | 0;
+ HEAP32[$ptr18 >> 2] = $incdec_ptr31;
+ HEAP8[$8] = $conv29;
+ $9 = HEAP32[$ptr18 >> 2] | 0;
+ $10 = HEAP32[$eptr19 >> 2] | 0;
+ $cmp35 = $9 >>> 0 < $10 >>> 0;
+ if ($cmp35) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $call38 = _agxbmore($xb, 1) | 0;
+ label = 15;
+ break;
+ case 15:
+ $conv43 = $v_0 & 63;
+ $or44 = $conv43 | 128;
+ $conv45 = $or44 & 255;
+ $11 = HEAP32[$ptr18 >> 2] | 0;
+ $incdec_ptr47 = $11 + 1 | 0;
+ HEAP32[$ptr18 >> 2] = $incdec_ptr47;
+ HEAP8[$11] = $conv45;
+ label = 16;
+ break;
+ case 16:
+ $12 = HEAP32[$s_addr >> 2] | 0;
+ $incdec_ptr = $12 + 1 | 0;
+ HEAP32[$s_addr >> 2] = $incdec_ptr;
+ $13 = HEAP8[$12] | 0;
+ $tobool = $13 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 24;
+ break;
+ } else {
+ $2 = $13;
+ label = 4;
+ break;
+ }
+ case 17:
+ if ($cmp20) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $call55 = _agxbmore($xb, 1) | 0;
+ label = 19;
+ break;
+ case 19:
+ $shr59 = $v_0 >>> 12;
+ $or62 = $shr59 | 224;
+ $conv63 = $or62 & 255;
+ $14 = HEAP32[$ptr18 >> 2] | 0;
+ $incdec_ptr65 = $14 + 1 | 0;
+ HEAP32[$ptr18 >> 2] = $incdec_ptr65;
+ HEAP8[$14] = $conv63;
+ $15 = HEAP32[$ptr18 >> 2] | 0;
+ $16 = HEAP32[$eptr19 >> 2] | 0;
+ $cmp69 = $15 >>> 0 < $16 >>> 0;
+ if ($cmp69) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $call72 = _agxbmore($xb, 1) | 0;
+ label = 21;
+ break;
+ case 21:
+ $shr76 = $v_0 >>> 6;
+ $conv79 = $shr76 & 63;
+ $or80 = $conv79 | 128;
+ $conv81 = $or80 & 255;
+ $17 = HEAP32[$ptr18 >> 2] | 0;
+ $incdec_ptr83 = $17 + 1 | 0;
+ HEAP32[$ptr18 >> 2] = $incdec_ptr83;
+ HEAP8[$17] = $conv81;
+ $18 = HEAP32[$ptr18 >> 2] | 0;
+ $19 = HEAP32[$eptr19 >> 2] | 0;
+ $cmp87 = $18 >>> 0 < $19 >>> 0;
+ if ($cmp87) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $call90 = _agxbmore($xb, 1) | 0;
+ label = 23;
+ break;
+ case 23:
+ $conv96 = $v_0 & 63;
+ $or97 = $conv96 | 128;
+ $conv98 = $or97 & 255;
+ $20 = HEAP32[$ptr18 >> 2] | 0;
+ $incdec_ptr100 = $20 + 1 | 0;
+ HEAP32[$ptr18 >> 2] = $incdec_ptr100;
+ HEAP8[$20] = $conv98;
+ label = 16;
+ break;
+ case 24:
+ $ptr104 = $xb + 4 | 0;
+ $21 = HEAP32[$ptr104 >> 2] | 0;
+ $eptr105 = $xb + 8 | 0;
+ $22 = HEAP32[$eptr105 >> 2] | 0;
+ $cmp106 = $21 >>> 0 < $22 >>> 0;
+ if ($cmp106) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $call109 = _agxbmore($xb, 1) | 0;
+ label = 26;
+ break;
+ case 26:
+ $23 = HEAP32[$ptr104 >> 2] | 0;
+ HEAP8[$23] = 0;
+ $buf115 = $xb | 0;
+ $24 = HEAP32[$buf115 >> 2] | 0;
+ HEAP32[$ptr104 >> 2] = $24;
+ $call117 = _strdup($24 | 0) | 0;
+ _agxbfree($xb);
+ STACKTOP = __stackBase__;
+ return $call117 | 0;
+ }
+ return 0;
+}
+function _utf8ToLatin1($s) {
+ $s = $s | 0;
+ var $xb = 0, $buf = 0, $arraydecay = 0, $0 = 0, $tobool7 = 0, $ptr = 0, $eptr = 0, $ptr14 = 0, $eptr15 = 0, $1 = 0, $s_pn = 0, $incdec_ptr10 = 0, $cmp = 0, $2 = 0, $3 = 0, $cmp2 = 0, $call = 0, $4 = 0, $incdec_ptr5 = 0, $and = 0, $incdec_ptr9 = 0, $5 = 0, $and12 = 0, $or = 0, $6 = 0, $7 = 0, $cmp16 = 0, $call19 = 0, $8 = 0, $incdec_ptr24 = 0, $s_addr_0_be = 0, $9 = 0, $tobool = 0, $ptr26 = 0, $10 = 0, $eptr27 = 0, $11 = 0, $cmp28 = 0, $call31 = 0, $12 = 0, $buf37 = 0, $13 = 0, $call39 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1040 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $xb = __stackBase__ | 0;
+ $buf = __stackBase__ + 16 | 0;
+ $arraydecay = $buf | 0;
+ _agxbinit($xb, 1024, $arraydecay);
+ $0 = HEAP8[$s] | 0;
+ $tobool7 = $0 << 24 >> 24 == 0;
+ if ($tobool7) {
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $ptr = $xb + 4 | 0;
+ $eptr = $xb + 8 | 0;
+ $ptr14 = $xb + 4 | 0;
+ $eptr15 = $xb + 8 | 0;
+ $s_pn = $s;
+ $1 = $0;
+ label = 4;
+ break;
+ case 4:
+ $incdec_ptr10 = $s_pn + 1 | 0;
+ $cmp = ($1 & 255) < 127;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $2 = HEAP32[$ptr >> 2] | 0;
+ $3 = HEAP32[$eptr >> 2] | 0;
+ $cmp2 = $2 >>> 0 < $3 >>> 0;
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call = _agxbmore($xb, 1) | 0;
+ label = 7;
+ break;
+ case 7:
+ $4 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr5 = $4 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr5;
+ HEAP8[$4] = $1;
+ $s_addr_0_be = $incdec_ptr10;
+ label = 11;
+ break;
+ case 8:
+ $and = $1 << 6;
+ $incdec_ptr9 = $s_pn + 2 | 0;
+ $5 = HEAP8[$incdec_ptr10] | 0;
+ $and12 = $5 & 63;
+ $or = $and12 | $and;
+ $6 = HEAP32[$ptr14 >> 2] | 0;
+ $7 = HEAP32[$eptr15 >> 2] | 0;
+ $cmp16 = $6 >>> 0 < $7 >>> 0;
+ if ($cmp16) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call19 = _agxbmore($xb, 1) | 0;
+ label = 10;
+ break;
+ case 10:
+ $8 = HEAP32[$ptr14 >> 2] | 0;
+ $incdec_ptr24 = $8 + 1 | 0;
+ HEAP32[$ptr14 >> 2] = $incdec_ptr24;
+ HEAP8[$8] = $or;
+ $s_addr_0_be = $incdec_ptr9;
+ label = 11;
+ break;
+ case 11:
+ $9 = HEAP8[$s_addr_0_be] | 0;
+ $tobool = $9 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ $s_pn = $s_addr_0_be;
+ $1 = $9;
+ label = 4;
+ break;
+ }
+ case 12:
+ $ptr26 = $xb + 4 | 0;
+ $10 = HEAP32[$ptr26 >> 2] | 0;
+ $eptr27 = $xb + 8 | 0;
+ $11 = HEAP32[$eptr27 >> 2] | 0;
+ $cmp28 = $10 >>> 0 < $11 >>> 0;
+ if ($cmp28) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $call31 = _agxbmore($xb, 1) | 0;
+ label = 14;
+ break;
+ case 14:
+ $12 = HEAP32[$ptr26 >> 2] | 0;
+ HEAP8[$12] = 0;
+ $buf37 = $xb | 0;
+ $13 = HEAP32[$buf37 >> 2] | 0;
+ HEAP32[$ptr26 >> 2] = $13;
+ $call39 = _strdup($13 | 0) | 0;
+ _agxbfree($xb);
+ STACKTOP = __stackBase__;
+ return $call39 | 0;
+ }
+ return 0;
+}
+function _overlap_node($n, $b) {
+ $n = $n | 0;
+ $b = $b | 0;
+ var $ictxt = 0, $p = 0, $agg_tmp = 0, $UR = 0, $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $cmp = 0, $x5 = 0, $2 = 0.0, $LL6 = 0, $x7 = 0, $3 = 0.0, $cmp8 = 0, $y = 0, $4 = 0.0, $y14 = 0, $5 = 0.0, $cmp15 = 0, $y20 = 0, $6 = 0.0, $y22 = 0, $7 = 0.0, $cmp23 = 0, $coord = 0, $8 = 0, $n_c = 0, $bp = 0, $shape = 0, $9 = 0, $fns = 0, $10 = 0, $insidefn = 0, $11 = 0, $call = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ictxt = __stackBase__ | 0;
+ $p = __stackBase__ + 8 | 0;
+ $agg_tmp = __stackBase__ + 24 | 0;
+ $UR = $b + 16 | 0;
+ $x = $UR | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $n + 64 | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $cmp = $0 < $1;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x5 = $n + 80 | 0;
+ $2 = +HEAPF64[$x5 >> 3];
+ $LL6 = $b | 0;
+ $x7 = $b | 0;
+ $3 = +HEAPF64[$x7 >> 3];
+ $cmp8 = $2 < $3;
+ if ($cmp8) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $b + 24 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y14 = $n + 72 | 0;
+ $5 = +HEAPF64[$y14 >> 3];
+ $cmp15 = $4 < $5;
+ if ($cmp15) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y20 = $n + 88 | 0;
+ $6 = +HEAPF64[$y20 >> 3];
+ $y22 = $b + 8 | 0;
+ $7 = +HEAPF64[$y22 >> 3];
+ $cmp23 = $6 < $7;
+ if ($cmp23) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $coord = $n + 32 | 0;
+ _mid_pointf($agg_tmp, $UR, $LL6);
+ _sub_pointf($p, $coord, $agg_tmp);
+ $8 = $ictxt | 0;
+ $n_c = $n;
+ HEAP32[$8 >> 2] = $n_c;
+ $bp = $ictxt + 4 | 0;
+ HEAP32[$bp >> 2] = 0;
+ $shape = $n + 24 | 0;
+ $9 = HEAP32[$shape >> 2] | 0;
+ $fns = $9 + 4 | 0;
+ $10 = HEAP32[$fns >> 2] | 0;
+ $insidefn = $10 + 12 | 0;
+ $11 = HEAP32[$insidefn >> 2] | 0;
+ $call = FUNCTION_TABLE_iii[$11 & 1023]($ictxt, $p) | 0;
+ $retval_0 = $call;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _overlap_label($lp, $b) {
+ $lp = $lp | 0;
+ $b = $b | 0;
+ var $s = 0, $tmp = 0, $tmp6 = 0, $x = 0, $0 = 0.0, $div = 0.0, $x1 = 0, $y = 0, $1 = 0.0, $div3 = 0.0, $y4 = 0, $pos = 0, $bb_sroa_0_0__idx = 0, $bb_sroa_0_0_copyload = 0.0, $bb_sroa_1_8__idx1 = 0, $bb_sroa_1_8_copyload = 0.0, $bb_sroa_3_24__idx2 = 0, $bb_sroa_3_24_copyload = 0.0, $x8 = 0, $2 = 0.0, $cmp = 0, $bb_sroa_2_16__idx = 0, $bb_sroa_2_16_copyload = 0.0, $x14 = 0, $3 = 0.0, $cmp15 = 0, $y18 = 0, $4 = 0.0, $cmp21 = 0, $y25 = 0, $5 = 0.0, $cmp26 = 0, $phitmp = 0, $6 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s = __stackBase__ | 0;
+ $tmp = __stackBase__ + 16 | 0;
+ $tmp6 = __stackBase__ + 32 | 0;
+ $x = $lp + 24 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $div = $0 * .5;
+ $x1 = $s | 0;
+ HEAPF64[$x1 >> 3] = $div;
+ $y = $lp + 32 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $div3 = $1 * .5;
+ $y4 = $s + 8 | 0;
+ HEAPF64[$y4 >> 3] = $div3;
+ $pos = $lp + 56 | 0;
+ _sub_pointf($tmp, $pos, $s);
+ $bb_sroa_0_0__idx = $tmp | 0;
+ $bb_sroa_0_0_copyload = +HEAPF64[$bb_sroa_0_0__idx >> 3];
+ $bb_sroa_1_8__idx1 = $tmp + 8 | 0;
+ $bb_sroa_1_8_copyload = +HEAPF64[$bb_sroa_1_8__idx1 >> 3];
+ _add_pointf($tmp6, $pos, $s);
+ $bb_sroa_3_24__idx2 = $tmp6 + 8 | 0;
+ $bb_sroa_3_24_copyload = +HEAPF64[$bb_sroa_3_24__idx2 >> 3];
+ $x8 = $b + 16 | 0;
+ $2 = +HEAPF64[$x8 >> 3];
+ $cmp = $2 < $bb_sroa_0_0_copyload;
+ if ($cmp) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $bb_sroa_2_16__idx = $tmp6 | 0;
+ $bb_sroa_2_16_copyload = +HEAPF64[$bb_sroa_2_16__idx >> 3];
+ $x14 = $b | 0;
+ $3 = +HEAPF64[$x14 >> 3];
+ $cmp15 = $bb_sroa_2_16_copyload < $3;
+ if ($cmp15) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y18 = $b + 24 | 0;
+ $4 = +HEAPF64[$y18 >> 3];
+ $cmp21 = $4 < $bb_sroa_1_8_copyload;
+ if ($cmp21) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y25 = $b + 8 | 0;
+ $5 = +HEAPF64[$y25 >> 3];
+ $cmp26 = $bb_sroa_3_24_copyload >= $5;
+ $phitmp = $cmp26 & 1;
+ $6 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $6 | 0;
+ }
+ return 0;
+}
+function _overlap_edge($e, $b) {
+ $e = $e | 0;
+ $b = $b | 0;
+ var $spl1 = 0, $0 = 0, $tobool = 0, $bb = 0, $call = 0, $tobool2 = 0, $size = 0, $list = 0, $i_0 = 0, $1 = 0, $cmp = 0, $2 = 0, $arrayidx = 0, $call3 = 0, $tobool4 = 0, $inc = 0, $label = 0, $3 = 0, $tobool8 = 0, $call10 = 0, $tobool11 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $spl1 = $e + 24 | 0;
+ $0 = HEAP32[$spl1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $bb = $0 + 8 | 0;
+ $call = _boxf_overlap246($bb, $b) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $size = $0 + 4 | 0;
+ $list = $0 | 0;
+ $i_0 = 0;
+ label = 5;
+ break;
+ case 5:
+ $1 = HEAP32[$size >> 2] | 0;
+ $cmp = ($i_0 | 0) < ($1 | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $2 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $2 + ($i_0 * 48 & -1) | 0;
+ $call3 = _overlap_bezier($arrayidx, $b) | 0;
+ $tobool4 = $call3 << 24 >> 24 == 0;
+ $inc = $i_0 + 1 | 0;
+ if ($tobool4) {
+ $i_0 = $inc;
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ }
+ case 7:
+ $label = $e + 112 | 0;
+ $3 = HEAP32[$label >> 2] | 0;
+ $tobool8 = ($3 | 0) == 0;
+ if ($tobool8) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call10 = _overlap_label($3, $b) | 0;
+ $tobool11 = $call10 << 24 >> 24 == 0;
+ if ($tobool11) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ }
+ case 9:
+ $retval_0 = 0;
+ label = 10;
+ break;
+ case 10:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _overlap_bezier($bz, $b) {
+ $bz = $bz | 0;
+ $b = $b | 0;
+ var $p = 0, $u = 0, $size = 0, $0 = 0, $tobool = 0, $list = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $cmp3 = 0, $5 = 0, $6 = 0, $7 = 0, $i_04 = 0, $arrayidx3 = 0, $8 = 0, $call = 0, $cmp4 = 0, $inc = 0, $cmp = 0, $sflag = 0, $9 = 0, $tobool5 = 0, $sp = 0, $10 = 0, $call10 = 0, $tobool11 = 0, $eflag = 0, $11 = 0, $tobool15 = 0, $ep = 0, $12 = 0, $sub = 0, $13 = 0, $arrayidx19 = 0, $call21 = 0, $tobool22 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $bz;
+ $bz = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ _memcpy($bz, tempParam, 48);
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p = __stackBase__ | 0;
+ $u = __stackBase__ + 16 | 0;
+ $size = $bz + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(158664, 1634, 163968, 115032);
+ return 0;
+ case 4:
+ $list = $bz | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = $u;
+ $3 = $1;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $4 = HEAP32[$size >> 2] | 0;
+ $cmp3 = ($4 | 0) > 1;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[$list >> 2] | 0;
+ $6 = $p;
+ $7 = HEAP32[$size >> 2] | 0;
+ $i_04 = 1;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx3 = $5 + ($i_04 << 4) | 0;
+ $8 = $arrayidx3;
+ HEAP32[$6 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $call = _lineToBox($p, $u, $b) | 0;
+ $cmp4 = ($call | 0) == -1;
+ if ($cmp4) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 13;
+ break;
+ }
+ case 7:
+ HEAP32[$2 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ $inc = $i_04 + 1 | 0;
+ $cmp = ($inc | 0) < ($7 | 0);
+ if ($cmp) {
+ $i_04 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $sflag = $bz + 8 | 0;
+ $9 = HEAP32[$sflag >> 2] | 0;
+ $tobool5 = ($9 | 0) == 0;
+ if ($tobool5) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $sp = $bz + 16 | 0;
+ $10 = HEAP32[$list >> 2] | 0;
+ $call10 = _overlap_arrow($sp, $10, $9, $b) | 0;
+ $tobool11 = $call10 << 24 >> 24 == 0;
+ if ($tobool11) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 13;
+ break;
+ }
+ case 10:
+ $eflag = $bz + 12 | 0;
+ $11 = HEAP32[$eflag >> 2] | 0;
+ $tobool15 = ($11 | 0) == 0;
+ if ($tobool15) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $ep = $bz + 32 | 0;
+ $12 = HEAP32[$size >> 2] | 0;
+ $sub = $12 - 1 | 0;
+ $13 = HEAP32[$list >> 2] | 0;
+ $arrayidx19 = $13 + ($sub << 4) | 0;
+ $call21 = _overlap_arrow($ep, $arrayidx19, $11, $b) | 0;
+ $tobool22 = $call21 << 24 >> 24 == 0;
+ if ($tobool22) {
+ label = 12;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 13;
+ break;
+ }
+ case 12:
+ $retval_0 = 0;
+ label = 13;
+ break;
+ case 13:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gv_nodesize($n, $flip) {
+ $n = $n | 0;
+ $flip = $flip | 0;
+ var $tobool = 0, $height = 0, $0 = 0.0, $mul = 0.0, $div = 0.0, $rw = 0, $lw = 0, $width = 0, $1 = 0.0, $mul4 = 0.0, $ht = 0, $width7 = 0, $2 = 0.0, $mul8 = 0.0, $div9 = 0.0, $rw11 = 0, $lw13 = 0, $height15 = 0, $3 = 0.0, $mul16 = 0.0, $ht18 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = $flip << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $height = $n + 56 | 0;
+ $0 = +HEAPF64[$height >> 3];
+ $mul = $0 * 72.0;
+ $div = $mul * .5;
+ $rw = $n + 112 | 0;
+ HEAPF64[$rw >> 3] = $div;
+ $lw = $n + 104 | 0;
+ HEAPF64[$lw >> 3] = $div;
+ $width = $n + 48 | 0;
+ $1 = +HEAPF64[$width >> 3];
+ $mul4 = $1 * 72.0;
+ $ht = $n + 96 | 0;
+ HEAPF64[$ht >> 3] = $mul4;
+ label = 5;
+ break;
+ case 4:
+ $width7 = $n + 48 | 0;
+ $2 = +HEAPF64[$width7 >> 3];
+ $mul8 = $2 * 72.0;
+ $div9 = $mul8 * .5;
+ $rw11 = $n + 112 | 0;
+ HEAPF64[$rw11 >> 3] = $div9;
+ $lw13 = $n + 104 | 0;
+ HEAPF64[$lw13 >> 3] = $div9;
+ $height15 = $n + 56 | 0;
+ $3 = +HEAPF64[$height15 >> 3];
+ $mul16 = $3 * 72.0;
+ $ht18 = $n + 96 | 0;
+ HEAPF64[$ht18 >> 3] = $mul16;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _edgeType($s, $dflt) {
+ $s = $s | 0;
+ $dflt = $dflt | 0;
+ var $tobool = 0, $0 = 0, $cmp = 0, $conv = 0, $add_ptr = 0, $call = 0, $tobool5 = 0, $_ = 0, $add_ptr9 = 0, $call10 = 0, $tobool11 = 0, $_17 = 0, $add_ptr15 = 0, $call16 = 0, $tobool17 = 0, $_18 = 0, $add_ptr21 = 0, $call22 = 0, $tobool23 = 0, $call27 = 0, $tobool28 = 0, $add_ptr32 = 0, $call33 = 0, $tobool34 = 0, $_19 = 0, $add_ptr38 = 0, $call39 = 0, $tobool40 = 0, $_20 = 0, $add_ptr44 = 0, $call45 = 0, $tobool46 = 0, $_21 = 0, $add_ptr50 = 0, $call51 = 0, $tobool52 = 0, $_22 = 0, $add_ptr56 = 0, $call57 = 0, $tobool58 = 0, $_23 = 0, $et_0 = 0, $tobool61 = 0, $call63 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($s | 0) == 0;
+ if ($tobool) {
+ $retval_0 = $dflt;
+ label = 18;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$s] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ $retval_0 = $dflt;
+ label = 18;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = $0 << 24 >> 24;
+ if (($conv | 0) == 49 | ($conv | 0) == 50 | ($conv | 0) == 51 | ($conv | 0) == 52 | ($conv | 0) == 53 | ($conv | 0) == 54 | ($conv | 0) == 55 | ($conv | 0) == 56 | ($conv | 0) == 57) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 99 | ($conv | 0) == 67) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 102 | ($conv | 0) == 70) {
+ label = 7;
+ break;
+ } else if (($conv | 0) == 108 | ($conv | 0) == 76) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 110 | ($conv | 0) == 78) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 111 | ($conv | 0) == 79) {
+ label = 11;
+ break;
+ } else if (($conv | 0) == 112 | ($conv | 0) == 80) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 115 | ($conv | 0) == 83) {
+ label = 13;
+ break;
+ } else if (($conv | 0) == 116 | ($conv | 0) == 84) {
+ label = 14;
+ break;
+ } else if (($conv | 0) == 121 | ($conv | 0) == 89) {
+ label = 15;
+ break;
+ } else if (($conv | 0) == 48) {
+ $retval_0 = 2;
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 5:
+ $retval_0 = 8;
+ label = 18;
+ break;
+ case 6:
+ $add_ptr = $s + 1 | 0;
+ $call = _strcasecmp($add_ptr, 121872) | 0;
+ $tobool5 = ($call | 0) == 0;
+ $_ = $tobool5 ? 10 : 0;
+ $et_0 = $_;
+ label = 16;
+ break;
+ case 7:
+ $add_ptr9 = $s + 1 | 0;
+ $call10 = _strcasecmp($add_ptr9, 121344) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ $_17 = $tobool11 ? 2 : 0;
+ $et_0 = $_17;
+ label = 16;
+ break;
+ case 8:
+ $add_ptr15 = $s + 1 | 0;
+ $call16 = _strcasecmp($add_ptr15, 120616) | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ $_18 = $tobool17 ? 2 : 0;
+ $et_0 = $_18;
+ label = 16;
+ break;
+ case 9:
+ $add_ptr21 = $s + 1 | 0;
+ $call22 = _strcasecmp($add_ptr21, 119920) | 0;
+ $tobool23 = ($call22 | 0) == 0;
+ if ($tobool23) {
+ $retval_0 = 0;
+ label = 18;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call27 = _strcasecmp($add_ptr21, 119384) | 0;
+ $tobool28 = ($call27 | 0) == 0;
+ if ($tobool28) {
+ $retval_0 = 2;
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 11:
+ $add_ptr32 = $s + 1 | 0;
+ $call33 = _strcasecmp($add_ptr32, 118872) | 0;
+ $tobool34 = ($call33 | 0) == 0;
+ $_19 = $tobool34 ? 6 : 0;
+ $et_0 = $_19;
+ label = 16;
+ break;
+ case 12:
+ $add_ptr38 = $s + 1 | 0;
+ $call39 = _strcasecmp($add_ptr38, 118416) | 0;
+ $tobool40 = ($call39 | 0) == 0;
+ $_20 = $tobool40 ? 4 : 0;
+ $et_0 = $_20;
+ label = 16;
+ break;
+ case 13:
+ $add_ptr44 = $s + 1 | 0;
+ $call45 = _strcasecmp($add_ptr44, 117760) | 0;
+ $tobool46 = ($call45 | 0) == 0;
+ $_21 = $tobool46 ? 8 : 0;
+ $et_0 = $_21;
+ label = 16;
+ break;
+ case 14:
+ $add_ptr50 = $s + 1 | 0;
+ $call51 = _strcasecmp($add_ptr50, 117080) | 0;
+ $tobool52 = ($call51 | 0) == 0;
+ $_22 = $tobool52 ? 8 : 0;
+ $et_0 = $_22;
+ label = 16;
+ break;
+ case 15:
+ $add_ptr56 = $s + 1 | 0;
+ $call57 = _strcasecmp($add_ptr56, 116520) | 0;
+ $tobool58 = ($call57 | 0) == 0;
+ $_23 = $tobool58 ? 8 : 0;
+ $et_0 = $_23;
+ label = 16;
+ break;
+ case 16:
+ $tobool61 = ($et_0 | 0) == 0;
+ if ($tobool61) {
+ label = 17;
+ break;
+ } else {
+ $retval_0 = $et_0;
+ label = 18;
+ break;
+ }
+ case 17:
+ $call63 = _agerr(0, 115984, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $s, tempInt) | 0) | 0;
+ $retval_0 = $dflt;
+ label = 18;
+ break;
+ case 18:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _setEdgeType($g, $dflt) {
+ $g = $g | 0;
+ $dflt = $dflt | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $1 = 0, $cmp = 0, $call4 = 0, $et_0 = 0, $flags = 0, $2 = 0, $conv6 = 0, $or = 0, $conv7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g | 0;
+ $call = _agget($0, 115568) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $et_0 = $dflt;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$call] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ if ($cmp) {
+ $et_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call4 = _edgeType($call, $dflt) | 0;
+ $et_0 = $call4;
+ label = 5;
+ break;
+ case 5:
+ $flags = $g + 168 | 0;
+ $2 = HEAP16[$flags >> 1] | 0;
+ $conv6 = $2 & 65535;
+ $or = $conv6 | $et_0;
+ $conv7 = $or & 65535;
+ HEAP16[$flags >> 1] = $conv7;
+ return;
+ }
+}
+function _gv_free_splines($e) {
+ $e = $e | 0;
+ var $spl = 0, $0 = 0, $tobool = 0, $1 = 0, $size8 = 0, $2 = 0, $cmp9 = 0, $list10 = 0, $3 = 0, $4 = 0, $i_011 = 0, $list5 = 0, $5 = 0, $6 = 0, $inc = 0, $7 = 0, $size = 0, $8 = 0, $cmp = 0, $list = 0, $9 = 0, $_lcssa = 0, $10 = 0, $11 = 0, $12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $spl = $e + 24 | 0;
+ $0 = HEAP32[$spl >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[$spl >> 2] | 0;
+ $size8 = $1 + 4 | 0;
+ $2 = HEAP32[$size8 >> 2] | 0;
+ $cmp9 = ($2 | 0) > 0;
+ $list10 = $1 | 0;
+ $3 = HEAP32[$list10 >> 2] | 0;
+ if ($cmp9) {
+ $i_011 = 0;
+ $4 = $3;
+ label = 4;
+ break;
+ } else {
+ $_lcssa = $3;
+ label = 5;
+ break;
+ }
+ case 4:
+ $list5 = $4 + ($i_011 * 48 & -1) | 0;
+ $5 = HEAP32[$list5 >> 2] | 0;
+ $6 = $5;
+ _free($6);
+ $inc = $i_011 + 1 | 0;
+ $7 = HEAP32[$spl >> 2] | 0;
+ $size = $7 + 4 | 0;
+ $8 = HEAP32[$size >> 2] | 0;
+ $cmp = ($inc | 0) < ($8 | 0);
+ $list = $7 | 0;
+ $9 = HEAP32[$list >> 2] | 0;
+ if ($cmp) {
+ $i_011 = $inc;
+ $4 = $9;
+ label = 4;
+ break;
+ } else {
+ $_lcssa = $9;
+ label = 5;
+ break;
+ }
+ case 5:
+ $10 = $_lcssa;
+ _free($10);
+ $11 = HEAP32[$spl >> 2] | 0;
+ $12 = $11;
+ _free($12);
+ label = 6;
+ break;
+ case 6:
+ HEAP32[$spl >> 2] = 0;
+ return;
+ }
+}
+function _gv_cleanup_edge($e) {
+ $e = $e | 0;
+ _gv_free_splines($e);
+ _free_label(HEAP32[$e + 112 >> 2] | 0);
+ _free_label(HEAP32[$e + 124 >> 2] | 0);
+ _free_label(HEAP32[$e + 116 >> 2] | 0);
+ _free_label(HEAP32[$e + 120 >> 2] | 0);
+ _memset($e + 24 | 0, 0, 168);
+ return;
+}
+function _overlap_arrow($p, $u, $flag, $b) {
+ $p = $p | 0;
+ $u = $u | 0;
+ $flag = $flag | 0;
+ $b = $b | 0;
+ var $tmp = 0, $tmp2 = 0, $tmp10 = 0, $tmp15 = 0, $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $cmp = 0, $x4 = 0, $2 = 0.0, $x6 = 0, $3 = 0.0, $cmp7 = 0, $y = 0, $4 = 0.0, $y12 = 0, $5 = 0.0, $cmp13 = 0, $y17 = 0, $6 = 0.0, $y19 = 0, $7 = 0.0, $cmp20 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $u;
+ $u = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$u >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$u + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$u + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$u + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmp2 = __stackBase__ + 32 | 0;
+ $tmp10 = __stackBase__ + 64 | 0;
+ $tmp15 = __stackBase__ + 96 | 0;
+ $x = $b + 16 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ _arrow_bb($tmp, $p, $u, 1.0, 0);
+ $x1 = $tmp | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $cmp = $0 < $1;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _arrow_bb($tmp2, $p, $u, 1.0, 0);
+ $x4 = $tmp2 + 16 | 0;
+ $2 = +HEAPF64[$x4 >> 3];
+ $x6 = $b | 0;
+ $3 = +HEAPF64[$x6 >> 3];
+ $cmp7 = $2 < $3;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $b + 24 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ _arrow_bb($tmp10, $p, $u, 1.0, 0);
+ $y12 = $tmp10 + 8 | 0;
+ $5 = +HEAPF64[$y12 >> 3];
+ $cmp13 = $4 < $5;
+ if ($cmp13) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _arrow_bb($tmp15, $p, $u, 1.0, 0);
+ $y17 = $tmp15 + 24 | 0;
+ $6 = +HEAPF64[$y17 >> 3];
+ $y19 = $b + 8 | 0;
+ $7 = +HEAPF64[$y19 >> 3];
+ $cmp20 = $6 < $7;
+ if ($cmp20) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ }
+ case 6:
+ $retval_0 = 0;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _cloneEdge($e, $ct, $ch) {
+ $e = $e | 0;
+ $ct = $ct | 0;
+ $ch = $ch | 0;
+ var $call = 0;
+ $call = _agedge(HEAP32[$ct + 20 >> 2] | 0, $ct, $ch) | 0;
+ _agcopyattr($e | 0, $call | 0);
+ return $call | 0;
+}
+function _make_simple_label($g, $lp) {
+ $g = $g | 0;
+ $lp = $lp | 0;
+ var $text = 0, $0 = 0, $dimen = 0, $1 = 0, $2 = 0, $cmp = 0, $call = 0, $add = 0, $call3 = 0, $3 = 0, $tobool4757 = 0, $charset = 0, $4 = 0, $_pn = 0, $lineptr_0_ph60 = 0, $line_0_ph59 = 0, $5 = 0, $_pn_pn = 0, $lineptr_049 = 0, $incdec_ptr50 = 0, $6 = 0, $notlhs = 0, $notrhs = 0, $or_cond_not = 0, $cmp13 = 0, $or_cond39 = 0, $incdec_ptr16 = 0, $incdec_ptr17 = 0, $7 = 0, $incdec_ptr18 = 0, $tobool19 = 0, $8 = 0, $conv26 = 0, $incdec_ptr27 = 0, $9 = 0, $incdec_ptr28 = 0, $line_1 = 0, $lineptr_1 = 0, $10 = 0, $tobool29 = 0, $incdec_ptr31 = 0, $incdec_ptr_incdec_ptr31 = 0, $incdec_ptr38 = 0, $p_0_ph_be = 0, $line_0_ph_be = 0, $lineptr_0_ph_be = 0, $11 = 0, $tobool47 = 0, $incdec_ptr40 = 0, $p_0_be = 0, $lineptr_0_be = 0, $12 = 0, $tobool = 0, $line_0_ph53 = 0, $lineptr_2 = 0, $cmp44 = 0, $space = 0, $13 = 0, $14 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $text = $lp | 0;
+ $0 = HEAP32[$text >> 2] | 0;
+ $dimen = $lp + 24 | 0;
+ $1 = $dimen;
+ _memset($1 | 0, 0, 16);
+ $2 = HEAP8[$0] | 0;
+ $cmp = $2 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 20;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _strlen($0 | 0) | 0;
+ $add = $call + 1 | 0;
+ $call3 = _gmalloc($add) | 0;
+ HEAP8[$call3] = 0;
+ $3 = HEAP8[$0] | 0;
+ $tobool4757 = $3 << 24 >> 24 == 0;
+ if ($tobool4757) {
+ label = 19;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $charset = $lp + 12 | 0;
+ $line_0_ph59 = $call3;
+ $lineptr_0_ph60 = $call3;
+ $_pn = $0;
+ $4 = $3;
+ label = 5;
+ break;
+ case 5:
+ $lineptr_049 = $lineptr_0_ph60;
+ $_pn_pn = $_pn;
+ $5 = $4;
+ label = 6;
+ break;
+ case 6:
+ $incdec_ptr50 = $_pn_pn + 1 | 0;
+ $6 = HEAP32[$charset >> 2] | 0;
+ $notlhs = ($6 | 0) != 2;
+ $notrhs = ($5 & 255) < 161;
+ $or_cond_not = $notrhs | $notlhs;
+ $cmp13 = $5 << 24 >> 24 == -1;
+ $or_cond39 = $or_cond_not | $cmp13;
+ if ($or_cond39) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $incdec_ptr16 = $lineptr_049 + 1 | 0;
+ HEAP8[$lineptr_049] = $5;
+ $incdec_ptr17 = $_pn_pn + 2 | 0;
+ $7 = HEAP8[$incdec_ptr50] | 0;
+ $incdec_ptr18 = $lineptr_049 + 2 | 0;
+ HEAP8[$incdec_ptr16] = $7;
+ $tobool19 = $7 << 24 >> 24 == 0;
+ if ($tobool19) {
+ $lineptr_2 = $incdec_ptr18;
+ $line_0_ph53 = $line_0_ph59;
+ label = 17;
+ break;
+ } else {
+ $lineptr_0_be = $incdec_ptr18;
+ $p_0_be = $incdec_ptr17;
+ label = 16;
+ break;
+ }
+ case 8:
+ if (($5 << 24 >> 24 | 0) == 92) {
+ label = 9;
+ break;
+ } else if (($5 << 24 >> 24 | 0) == 10) {
+ label = 13;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 9:
+ $8 = HEAP8[$incdec_ptr50] | 0;
+ $conv26 = $8 << 24 >> 24;
+ if (($conv26 | 0) == 110 | ($conv26 | 0) == 108 | ($conv26 | 0) == 114) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $incdec_ptr27 = $lineptr_049 + 1 | 0;
+ HEAP8[$lineptr_049] = 0;
+ $9 = HEAP8[$incdec_ptr50] | 0;
+ _storeline($g, $lp, $line_0_ph59, $9);
+ $lineptr_1 = $incdec_ptr27;
+ $line_1 = $incdec_ptr27;
+ label = 12;
+ break;
+ case 11:
+ $incdec_ptr28 = $lineptr_049 + 1 | 0;
+ HEAP8[$lineptr_049] = $8;
+ $lineptr_1 = $incdec_ptr28;
+ $line_1 = $line_0_ph59;
+ label = 12;
+ break;
+ case 12:
+ $10 = HEAP8[$incdec_ptr50] | 0;
+ $tobool29 = $10 << 24 >> 24 == 0;
+ $incdec_ptr31 = $_pn_pn + 2 | 0;
+ $incdec_ptr_incdec_ptr31 = $tobool29 ? $incdec_ptr50 : $incdec_ptr31;
+ $lineptr_0_ph_be = $lineptr_1;
+ $line_0_ph_be = $line_1;
+ $p_0_ph_be = $incdec_ptr_incdec_ptr31;
+ label = 14;
+ break;
+ case 13:
+ $incdec_ptr38 = $lineptr_049 + 1 | 0;
+ HEAP8[$lineptr_049] = 0;
+ _storeline($g, $lp, $line_0_ph59, 110);
+ $lineptr_0_ph_be = $incdec_ptr38;
+ $line_0_ph_be = $incdec_ptr38;
+ $p_0_ph_be = $incdec_ptr50;
+ label = 14;
+ break;
+ case 14:
+ $11 = HEAP8[$p_0_ph_be] | 0;
+ $tobool47 = $11 << 24 >> 24 == 0;
+ if ($tobool47) {
+ $lineptr_2 = $lineptr_0_ph_be;
+ $line_0_ph53 = $line_0_ph_be;
+ label = 17;
+ break;
+ } else {
+ $line_0_ph59 = $line_0_ph_be;
+ $lineptr_0_ph60 = $lineptr_0_ph_be;
+ $_pn = $p_0_ph_be;
+ $4 = $11;
+ label = 5;
+ break;
+ }
+ case 15:
+ $incdec_ptr40 = $lineptr_049 + 1 | 0;
+ HEAP8[$lineptr_049] = $5;
+ $lineptr_0_be = $incdec_ptr40;
+ $p_0_be = $incdec_ptr50;
+ label = 16;
+ break;
+ case 16:
+ $12 = HEAP8[$p_0_be] | 0;
+ $tobool = $12 << 24 >> 24 == 0;
+ if ($tobool) {
+ $lineptr_2 = $lineptr_0_be;
+ $line_0_ph53 = $line_0_ph59;
+ label = 17;
+ break;
+ } else {
+ $lineptr_049 = $lineptr_0_be;
+ $_pn_pn = $p_0_be;
+ $5 = $12;
+ label = 6;
+ break;
+ }
+ case 17:
+ $cmp44 = ($line_0_ph53 | 0) == ($lineptr_2 | 0);
+ if ($cmp44) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ HEAP8[$lineptr_2] = 0;
+ _storeline($g, $lp, $line_0_ph53, 110);
+ label = 19;
+ break;
+ case 19:
+ $space = $lp + 40 | 0;
+ $13 = $space;
+ $14 = $dimen;
+ HEAP32[$13 >> 2] = HEAP32[$14 >> 2] | 0;
+ HEAP32[$13 + 4 >> 2] = HEAP32[$14 + 4 >> 2] | 0;
+ HEAP32[$13 + 8 >> 2] = HEAP32[$14 + 8 >> 2] | 0;
+ HEAP32[$13 + 12 >> 2] = HEAP32[$14 + 12 >> 2] | 0;
+ label = 20;
+ break;
+ case 20:
+ return;
+ }
+}
+function _storeline($g, $lp, $line, $terminator) {
+ $g = $g | 0;
+ $lp = $lp | 0;
+ $line = $line | 0;
+ $terminator = $terminator | 0;
+ var $tmp = 0, $nparas = 0, $0 = 0, $conv = 0, $para3 = 0, $1 = 0, $tobool = 0, $add = 0, $2 = 0, $add7 = 0, $call = 0, $3 = 0, $mul = 0, $call9 = 0, $call_sink = 0, $4 = 0, $5 = 0, $idxprom = 0, $arrayidx = 0, $str = 0, $just = 0, $tobool19 = 0, $6 = 0, $tobool22 = 0, $fontname = 0, $7 = 0, $fontsize = 0, $8 = 0.0, $size_sroa_0_0__idx = 0, $size_sroa_0_0_copyload = 0.0, $size_sroa_1_8__idx7 = 0, $size_sroa_1_8_copyload = 0.0, $fontsize23 = 0, $9 = 0.0, $mul24 = 0.0, $conv25 = 0, $conv26 = 0.0, $height = 0, $size_sroa_0_0 = 0.0, $size_sroa_1_0 = 0.0, $10 = 0, $inc = 0, $x30 = 0, $11 = 0.0, $cmp = 0, $_size_sroa_0_0 = 0.0, $y44 = 0, $12 = 0.0, $add45 = 0.0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $nparas = $lp + 76 | 0;
+ $0 = HEAP16[$nparas >> 1] | 0;
+ $conv = $0 << 16 >> 16;
+ $para3 = $lp + 72 | 0;
+ $1 = HEAP32[$para3 >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $conv + 1 | 0;
+ $2 = $1;
+ $add7 = $conv + 2 | 0;
+ $call = _zrealloc($2, $add7, 80, $add) | 0;
+ $call_sink = $call;
+ label = 5;
+ break;
+ case 4:
+ $3 = $conv * 80 & -1;
+ $mul = $3 + 160 | 0;
+ $call9 = _zmalloc($mul) | 0;
+ $call_sink = $call9;
+ label = 5;
+ break;
+ case 5:
+ $4 = $call_sink;
+ HEAP32[$para3 >> 2] = $4;
+ $5 = HEAP16[$nparas >> 1] | 0;
+ $idxprom = $5 << 16 >> 16;
+ $arrayidx = $4 + ($idxprom * 80 & -1) | 0;
+ $str = $arrayidx | 0;
+ HEAP32[$str >> 2] = $line;
+ $just = $4 + ($idxprom * 80 & -1) + 72 | 0;
+ HEAP8[$just] = $terminator;
+ $tobool19 = ($line | 0) == 0;
+ if ($tobool19) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $6 = HEAP8[$line] | 0;
+ $tobool22 = $6 << 24 >> 24 == 0;
+ if ($tobool22) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $fontname = $lp + 4 | 0;
+ $7 = HEAP32[$fontname >> 2] | 0;
+ $fontsize = $lp + 16 | 0;
+ $8 = +HEAPF64[$fontsize >> 3];
+ _textsize($tmp, $g, $arrayidx, $7, $8);
+ $size_sroa_0_0__idx = $tmp | 0;
+ $size_sroa_0_0_copyload = +HEAPF64[$size_sroa_0_0__idx >> 3];
+ $size_sroa_1_8__idx7 = $tmp + 8 | 0;
+ $size_sroa_1_8_copyload = +HEAPF64[$size_sroa_1_8__idx7 >> 3];
+ $size_sroa_1_0 = $size_sroa_1_8_copyload;
+ $size_sroa_0_0 = $size_sroa_0_0_copyload;
+ label = 9;
+ break;
+ case 8:
+ $fontsize23 = $lp + 16 | 0;
+ $9 = +HEAPF64[$fontsize23 >> 3];
+ $mul24 = $9 * 1.2;
+ $conv25 = ~~$mul24;
+ $conv26 = +($conv25 | 0);
+ $height = $4 + ($idxprom * 80 & -1) + 64 | 0;
+ HEAPF64[$height >> 3] = $conv26;
+ $size_sroa_1_0 = $conv26;
+ $size_sroa_0_0 = 0.0;
+ label = 9;
+ break;
+ case 9:
+ $10 = HEAP16[$nparas >> 1] | 0;
+ $inc = $10 + 1 & 65535;
+ HEAP16[$nparas >> 1] = $inc;
+ $x30 = $lp + 24 | 0;
+ $11 = +HEAPF64[$x30 >> 3];
+ $cmp = $11 > $size_sroa_0_0;
+ $_size_sroa_0_0 = $cmp ? $11 : $size_sroa_0_0;
+ HEAPF64[$x30 >> 3] = $_size_sroa_0_0;
+ $y44 = $lp + 32 | 0;
+ $12 = +HEAPF64[$y44 >> 3];
+ $add45 = $size_sroa_1_0 + $12;
+ HEAPF64[$y44 >> 3] = $add45;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _mapN($n, $clg) {
+ $n = $n | 0;
+ $clg = $clg | 0;
+ var $graph = 0, $0 = 0, $clustnode = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $name1 = 0, $4 = 0, $call = 0, $tobool2 = 0, $incdec_ptr = 0, $5 = 0, $call3 = 0, $tobool4 = 0, $6 = 0, $call7 = 0, $7 = 0, $call8 = 0, $list9 = 0, $8 = 0, $9 = 0, $tobool1116 = 0, $10 = 0, $11 = 0, $_pn = 0, $incdec_ptr1017 = 0, $index = 0, $12 = 0, $call12 = 0, $value = 0, $13 = 0, $cmp = 0, $call16 = 0, $14 = 0, $tobool11 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $graph = $n + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ $clustnode = $n + 134 | 0;
+ $1 = HEAP8[$clustnode] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = $n;
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $n | 0;
+ $3 = $clg;
+ _aginsert($3, $2);
+ $name1 = $n + 12 | 0;
+ $4 = HEAP32[$name1 >> 2] | 0;
+ $call = _strchr($4 | 0, 58) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ ___assert_func(158664, 1243, 164088, 119472);
+ return 0;
+ case 5:
+ $incdec_ptr = $call + 1 | 0;
+ $5 = $0;
+ $call3 = _agfindnode($5, $incdec_ptr) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $6 = $call3;
+ $retval_0 = $6;
+ label = 12;
+ break;
+ case 7:
+ $call7 = _agnode($5, $incdec_ptr) | 0;
+ $7 = $call7;
+ $call8 = _agdictof($2) | 0;
+ $list9 = $call8 + 8 | 0;
+ $8 = HEAP32[$list9 >> 2] | 0;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $tobool1116 = ($9 | 0) == 0;
+ if ($tobool1116) {
+ $retval_0 = $7;
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $10 = $call7 | 0;
+ $_pn = $8;
+ $11 = $9;
+ label = 9;
+ break;
+ case 9:
+ $incdec_ptr1017 = $_pn + 4 | 0;
+ $index = $11 + 8 | 0;
+ $12 = HEAP32[$index >> 2] | 0;
+ $call12 = _agxget($10, $12) | 0;
+ $value = $11 + 4 | 0;
+ $13 = HEAP32[$value >> 2] | 0;
+ $cmp = ($call12 | 0) == ($13 | 0);
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call16 = _agxset($10, $12, $13) | 0;
+ label = 11;
+ break;
+ case 11:
+ $14 = HEAP32[$incdec_ptr1017 >> 2] | 0;
+ $tobool11 = ($14 | 0) == 0;
+ if ($tobool11) {
+ $retval_0 = $7;
+ label = 12;
+ break;
+ } else {
+ $_pn = $incdec_ptr1017;
+ $11 = $14;
+ label = 9;
+ break;
+ }
+ case 12:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _make_label($obj, $str, $kind, $fontsize, $fontname, $fontcolor) {
+ $obj = $obj | 0;
+ $str = $str | 0;
+ $kind = $kind | 0;
+ $fontsize = +$fontsize;
+ $fontname = $fontname | 0;
+ $fontcolor = $fontcolor | 0;
+ var $call = 0, $0 = 0, $1 = 0, $2 = 0, $3 = 0, $bf_val_sext = 0, $4 = 0, $root = 0, $5 = 0, $6 = 0, $7 = 0, $graph = 0, $8 = 0, $9 = 0, $root2 = 0, $10 = 0, $11 = 0, $head = 0, $12 = 0, $13 = 0, $graph4 = 0, $14 = 0, $root5 = 0, $15 = 0, $g_0 = 0, $sg_0 = 0, $n_0 = 0, $e_0 = 0, $fontname6 = 0, $16 = 0, $fontcolor7 = 0, $17 = 0, $fontsize8 = 0, $18 = 0, $charset = 0, $19 = 0, $conv = 0, $charset9 = 0, $20 = 0, $and = 0, $tobool = 0, $call10 = 0, $text = 0, $and11 = 0, $tobool12 = 0, $21 = 0, $call16 = 0, $text17 = 0, $22 = 0, $call19 = 0, $tobool20 = 0, $23 = 0, $24 = 0, $bf_val_sext23 = 0, $name = 0, $25 = 0, $call25 = 0, $name27 = 0, $26 = 0, $call28 = 0, $tail = 0, $27 = 0, $name30 = 0, $28 = 0, $29 = 0, $30 = 0, $and33 = 0, $tobool34 = 0, $cond = 0, $head35 = 0, $31 = 0, $name36 = 0, $32 = 0, $call37 = 0, $call43 = 0, $text44 = 0, $33 = 0, $cond1 = 0, $call48 = 0, $call50 = 0, $s_0 = 0, $34 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(88) | 0;
+ $0 = $call;
+ $1 = $obj;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $3 = $2 << 28;
+ $bf_val_sext = $3 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 3;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 5;
+ break;
+ } else {
+ $e_0 = 0;
+ $n_0 = 0;
+ $sg_0 = 0;
+ $g_0 = 0;
+ label = 6;
+ break;
+ }
+ case 3:
+ $4 = $obj;
+ $root = $obj + 32 | 0;
+ $5 = $root;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $e_0 = 0;
+ $n_0 = 0;
+ $sg_0 = $4;
+ $g_0 = $6;
+ label = 6;
+ break;
+ case 4:
+ $7 = $obj;
+ $graph = $obj + 20 | 0;
+ $8 = $graph;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $root2 = $9 + 32 | 0;
+ $10 = HEAP32[$root2 >> 2] | 0;
+ $e_0 = 0;
+ $n_0 = $7;
+ $sg_0 = 0;
+ $g_0 = $10;
+ label = 6;
+ break;
+ case 5:
+ $11 = $obj;
+ $head = $obj + 12 | 0;
+ $12 = $head;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $graph4 = $13 + 20 | 0;
+ $14 = HEAP32[$graph4 >> 2] | 0;
+ $root5 = $14 + 32 | 0;
+ $15 = HEAP32[$root5 >> 2] | 0;
+ $e_0 = $11;
+ $n_0 = 0;
+ $sg_0 = 0;
+ $g_0 = $15;
+ label = 6;
+ break;
+ case 6:
+ $fontname6 = $call + 4 | 0;
+ $16 = $fontname6;
+ HEAP32[$16 >> 2] = $fontname;
+ $fontcolor7 = $call + 8 | 0;
+ $17 = $fontcolor7;
+ HEAP32[$17 >> 2] = $fontcolor;
+ $fontsize8 = $call + 16 | 0;
+ $18 = $fontsize8;
+ HEAPF64[$18 >> 3] = $fontsize;
+ $charset = $g_0 + 155 | 0;
+ $19 = HEAP8[$charset] | 0;
+ $conv = $19 & 255;
+ $charset9 = $call + 12 | 0;
+ $20 = $charset9;
+ HEAP32[$20 >> 2] = $conv;
+ $and = $kind & 4;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call10 = _strdup($str | 0) | 0;
+ $text = $call;
+ HEAP32[$text >> 2] = $call10;
+ $and11 = $kind & 2;
+ $tobool12 = ($and11 | 0) == 0;
+ if ($tobool12) {
+ label = 20;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $21 = $call + 82 | 0;
+ HEAP8[$21] = 1;
+ label = 20;
+ break;
+ case 9:
+ if (($kind | 0) == 2) {
+ label = 10;
+ break;
+ } else if (($kind | 0) == 0) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 10:
+ $call16 = _strdup($str | 0) | 0;
+ $text17 = $call;
+ HEAP32[$text17 >> 2] = $call16;
+ $22 = $call + 82 | 0;
+ HEAP8[$22] = 1;
+ $call19 = _make_html_label($obj, $0) | 0;
+ $tobool20 = ($call19 | 0) == 0;
+ if ($tobool20) {
+ label = 20;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $23 = HEAP32[$1 >> 2] | 0;
+ $24 = $23 << 28;
+ $bf_val_sext23 = $24 >> 28;
+ if (($bf_val_sext23 | 0) == 3) {
+ label = 12;
+ break;
+ } else if (($bf_val_sext23 | 0) == 1) {
+ label = 13;
+ break;
+ } else if (($bf_val_sext23 | 0) == 2) {
+ label = 14;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 12:
+ $name = $sg_0 + 12 | 0;
+ $25 = HEAP32[$name >> 2] | 0;
+ $call25 = _agerr(3, 118840, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $25, tempInt) | 0) | 0;
+ label = 20;
+ break;
+ case 13:
+ $name27 = $n_0 + 12 | 0;
+ $26 = HEAP32[$name27 >> 2] | 0;
+ $call28 = _agerr(3, 152768, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $26, tempInt) | 0) | 0;
+ label = 20;
+ break;
+ case 14:
+ $tail = $e_0 + 16 | 0;
+ $27 = HEAP32[$tail >> 2] | 0;
+ $name30 = $27 + 12 | 0;
+ $28 = HEAP32[$name30 >> 2] | 0;
+ $29 = $g_0;
+ $30 = HEAP32[$29 >> 2] | 0;
+ $and33 = $30 & 16;
+ $tobool34 = ($and33 | 0) != 0;
+ $cond = $tobool34 ? 117160 : 111928;
+ $head35 = $e_0 + 12 | 0;
+ $31 = HEAP32[$head35 >> 2] | 0;
+ $name36 = $31 + 12 | 0;
+ $32 = HEAP32[$name36 >> 2] | 0;
+ $call37 = _agerr(3, 125952, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $28, HEAP32[tempInt + 8 >> 2] = $cond, HEAP32[tempInt + 16 >> 2] = $32, tempInt) | 0) | 0;
+ label = 20;
+ break;
+ case 15:
+ ___assert_func(107576, 169, 164096, 103640);
+ return 0;
+ case 16:
+ $call43 = _strdup_and_subst_obj0($str, $obj, 0) | 0;
+ $text44 = $call;
+ HEAP32[$text44 >> 2] = $call43;
+ $33 = HEAP32[$20 >> 2] | 0;
+ $cond1 = ($33 | 0) == 1;
+ if ($cond1) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $call48 = _latin1ToUTF8($call43) | 0;
+ $s_0 = $call48;
+ label = 19;
+ break;
+ case 18:
+ $call50 = _htmlEntityUTF8($call43) | 0;
+ $s_0 = $call50;
+ label = 19;
+ break;
+ case 19:
+ $34 = HEAP32[$text44 >> 2] | 0;
+ _free($34);
+ HEAP32[$text44 >> 2] = $s_0;
+ _make_simple_label($g_0, $0);
+ label = 20;
+ break;
+ case 20:
+ STACKTOP = __stackBase__;
+ return $0 | 0;
+ }
+ return 0;
+}
+function _xml_isentity($s) {
+ $s = $s | 0;
+ var $incdec_ptr = 0, $0 = 0, $cmp = 0, $incdec_ptr2 = 0, $1 = 0, $incdec_ptr10 = 0, $s_addr_0 = 0, $2 = 0, $_off29 = 0, $3 = 0, $_off30 = 0, $4 = 0, $or_cond = 0, $_off31 = 0, $5 = 0, $or_cond35 = 0, $incdec_ptr31 = 0, $s_addr_1 = 0, $6 = 0, $_off32 = 0, $7 = 0, $incdec_ptr42 = 0, $s_addr_2 = 0, $8 = 0, $_off = 0, $9 = 0, $_off28 = 0, $10 = 0, $or_cond37 = 0, $incdec_ptr64 = 0, $s_addr_3 = 0, $11 = 0, $cmp68 = 0, $_ = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $incdec_ptr = $s + 1 | 0;
+ $0 = HEAP8[$incdec_ptr] | 0;
+ $cmp = $0 << 24 >> 24 == 35;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $s_addr_2 = $incdec_ptr;
+ label = 7;
+ break;
+ }
+ case 3:
+ $incdec_ptr2 = $s + 2 | 0;
+ $1 = HEAP8[$incdec_ptr2] | 0;
+ if (($1 << 24 >> 24 | 0) == 120 | ($1 << 24 >> 24 | 0) == 88) {
+ label = 4;
+ break;
+ } else {
+ $s_addr_1 = $incdec_ptr2;
+ label = 6;
+ break;
+ }
+ case 4:
+ $incdec_ptr10 = $s + 3 | 0;
+ $s_addr_0 = $incdec_ptr10;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP8[$s_addr_0] | 0;
+ $_off29 = $2 - 48 & 255;
+ $3 = ($_off29 & 255) < 10;
+ $_off30 = $2 - 97 & 255;
+ $4 = ($_off30 & 255) < 6;
+ $or_cond = $3 | $4;
+ $_off31 = $2 - 65 & 255;
+ $5 = ($_off31 & 255) < 6;
+ $or_cond35 = $or_cond | $5;
+ $incdec_ptr31 = $s_addr_0 + 1 | 0;
+ if ($or_cond35) {
+ $s_addr_0 = $incdec_ptr31;
+ label = 5;
+ break;
+ } else {
+ $s_addr_3 = $s_addr_0;
+ label = 8;
+ break;
+ }
+ case 6:
+ $6 = HEAP8[$s_addr_1] | 0;
+ $_off32 = $6 - 48 & 255;
+ $7 = ($_off32 & 255) < 10;
+ $incdec_ptr42 = $s_addr_1 + 1 | 0;
+ if ($7) {
+ $s_addr_1 = $incdec_ptr42;
+ label = 6;
+ break;
+ } else {
+ $s_addr_3 = $s_addr_1;
+ label = 8;
+ break;
+ }
+ case 7:
+ $8 = HEAP8[$s_addr_2] | 0;
+ $_off = $8 - 97 & 255;
+ $9 = ($_off & 255) < 26;
+ $_off28 = $8 - 65 & 255;
+ $10 = ($_off28 & 255) < 26;
+ $or_cond37 = $9 | $10;
+ $incdec_ptr64 = $s_addr_2 + 1 | 0;
+ if ($or_cond37) {
+ $s_addr_2 = $incdec_ptr64;
+ label = 7;
+ break;
+ } else {
+ $s_addr_3 = $s_addr_2;
+ label = 8;
+ break;
+ }
+ case 8:
+ $11 = HEAP8[$s_addr_3] | 0;
+ $cmp68 = $11 << 24 >> 24 == 59;
+ $_ = $cmp68 & 1;
+ return $_ | 0;
+ }
+ return 0;
+}
+function _strdup_and_subst_obj0($str, $obj, $escBackslash) {
+ $str = $str | 0;
+ $obj = $obj | 0;
+ $escBackslash = $escBackslash | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $name = 0, $3 = 0, $4 = 0, $call = 0, $label = 0, $5 = 0, $6 = 0, $tobool = 0, $text = 0, $7 = 0, $tobool1 = 0, $call3 = 0, $graph = 0, $8 = 0, $9 = 0, $name6 = 0, $10 = 0, $call7 = 0, $name8 = 0, $11 = 0, $12 = 0, $call9 = 0, $label11 = 0, $13 = 0, $14 = 0, $tobool12 = 0, $text14 = 0, $15 = 0, $tobool15 = 0, $call17 = 0, $tail = 0, $16 = 0, $17 = 0, $graph21 = 0, $18 = 0, $root = 0, $19 = 0, $name22 = 0, $20 = 0, $call23 = 0, $name25 = 0, $21 = 0, $call26 = 0, $pt_sroa_1_36__idx6 = 0, $22 = 0, $pt_sroa_1_36_copyload7 = 0, $tobool29 = 0, $call31 = 0, $tp_len_0 = 0, $head = 0, $23 = 0, $24 = 0, $name33 = 0, $25 = 0, $pt_sroa_1_36__idx4 = 0, $26 = 0, $pt_sroa_1_36_copyload = 0, $tobool37 = 0, $call39 = 0, $hp_len_0 = 0, $call41 = 0, $label43 = 0, $27 = 0, $28 = 0, $tobool44 = 0, $text46 = 0, $29 = 0, $tobool47 = 0, $call49 = 0, $l_str_0 = 0, $l_len_0 = 0, $30 = 0, $graph53 = 0, $31 = 0, $root54 = 0, $32 = 0, $33 = 0, $34 = 0, $and = 0, $tobool57 = 0, $_ = 0, $tobool60 = 0, $add = 0, $cond = 0, $tobool64 = 0, $add66 = 0, $_add66 = 0, $add61 = 0, $add62 = 0, $add63 = 0, $add70 = 0, $tp_str_0 = 0, $hp_str_0 = 0, $g_str_0 = 0, $n_str_0 = 0, $e_str_1 = 0, $h_str_0 = 0, $t_str_0 = 0, $l_str_1 = 0, $g_len_0 = 0, $n_len_0 = 0, $e_len_0 = 0, $h_len_0 = 0, $t_len_0 = 0, $l_len_1 = 0, $tp_len_1 = 0, $hp_len_1 = 0, $isEdge_0 = 0, $tobool89 = 0, $s_0 = 0, $newlen_0 = 0, $incdec_ptr = 0, $35 = 0, $incdec_ptr74 = 0, $36 = 0, $conv75 = 0, $add77 = 0, $add79 = 0, $add81 = 0, $add83 = 0, $add85 = 0, $add87 = 0, $add91 = 0, $add93 = 0, $inc = 0, $add97 = 0, $call98 = 0, $tobool125 = 0, $tobool134 = 0, $tobool159 = 0, $tobool196 = 0, $s_1 = 0, $p_0 = 0, $incdec_ptr100 = 0, $37 = 0, $incdec_ptr107 = 0, $38 = 0, $conv108 = 0, $39 = 0, $tobool112134 = 0, $40 = 0, $tobool119129 = 0, $41 = 0, $tobool174111 = 0, $42 = 0, $tobool182106 = 0, $43 = 0, $tobool190102 = 0, $t_0136 = 0, $p_1135 = 0, $incdec_ptr111 = 0, $incdec_ptr114 = 0, $44 = 0, $tobool112 = 0, $t_1131 = 0, $p_2130 = 0, $incdec_ptr118 = 0, $incdec_ptr122 = 0, $45 = 0, $tobool119 = 0, $46 = 0, $tobool129115 = 0, $t_2117 = 0, $p_3116 = 0, $incdec_ptr128 = 0, $incdec_ptr132 = 0, $47 = 0, $tobool129 = 0, $p_3_lcssa = 0, $p_3_pn = 0, $t_3 = 0, $p_4 = 0, $48 = 0, $tobool139 = 0, $incdec_ptr138 = 0, $p_6_ph = 0, $49 = 0, $tobool147119 = 0, $t_4121 = 0, $p_6120 = 0, $incdec_ptr146 = 0, $incdec_ptr150 = 0, $50 = 0, $tobool147 = 0, $p_6_lcssa = 0, $51 = 0, $tobool154123 = 0, $t_5125 = 0, $p_7124 = 0, $incdec_ptr153 = 0, $incdec_ptr157 = 0, $52 = 0, $tobool154 = 0, $p_7_lcssa = 0, $p_7_pn = 0, $t_6 = 0, $p_8 = 0, $53 = 0, $tobool164 = 0, $incdec_ptr163 = 0, $t_7113 = 0, $p_9112 = 0, $incdec_ptr173 = 0, $incdec_ptr177 = 0, $54 = 0, $tobool174 = 0, $t_8108 = 0, $p_10107 = 0, $incdec_ptr181 = 0, $incdec_ptr185 = 0, $55 = 0, $tobool182 = 0, $t_9104 = 0, $p_11103 = 0, $incdec_ptr189 = 0, $incdec_ptr193 = 0, $56 = 0, $tobool190 = 0, $incdec_ptr198 = 0, $incdec_ptr201 = 0, $incdec_ptr202 = 0, $incdec_ptr205 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $obj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 3;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 6;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 9;
+ break;
+ } else {
+ $isEdge_0 = 0;
+ $hp_len_1 = 0;
+ $tp_len_1 = 0;
+ $l_len_1 = 2;
+ $t_len_0 = 2;
+ $h_len_0 = 2;
+ $e_len_0 = 2;
+ $n_len_0 = 2;
+ $g_len_0 = 2;
+ $l_str_1 = 131720;
+ $t_str_0 = 133960;
+ $h_str_0 = 136304;
+ $e_str_1 = 139088;
+ $n_str_0 = 142576;
+ $g_str_0 = 145616;
+ $hp_str_0 = 148384;
+ $tp_str_0 = 148384;
+ label = 17;
+ break;
+ }
+ case 3:
+ $name = $obj + 12 | 0;
+ $3 = $name;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $call = _strlen($4 | 0) | 0;
+ $label = $obj + 52 | 0;
+ $5 = $label;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ $isEdge_0 = 0;
+ $hp_len_1 = 0;
+ $tp_len_1 = 0;
+ $l_len_1 = 2;
+ $t_len_0 = 2;
+ $h_len_0 = 2;
+ $e_len_0 = 2;
+ $n_len_0 = 2;
+ $g_len_0 = $call;
+ $l_str_1 = 131720;
+ $t_str_0 = 133960;
+ $h_str_0 = 136304;
+ $e_str_1 = 139088;
+ $n_str_0 = 142576;
+ $g_str_0 = $4;
+ $hp_str_0 = 148384;
+ $tp_str_0 = 148384;
+ label = 17;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $text = $6 | 0;
+ $7 = HEAP32[$text >> 2] | 0;
+ $tobool1 = ($str | 0) == 0;
+ if ($tobool1) {
+ $isEdge_0 = 0;
+ $hp_len_1 = 0;
+ $tp_len_1 = 0;
+ $l_len_1 = 2;
+ $t_len_0 = 2;
+ $h_len_0 = 2;
+ $e_len_0 = 2;
+ $n_len_0 = 2;
+ $g_len_0 = $call;
+ $l_str_1 = $7;
+ $t_str_0 = 133960;
+ $h_str_0 = 136304;
+ $e_str_1 = 139088;
+ $n_str_0 = 142576;
+ $g_str_0 = $4;
+ $hp_str_0 = 148384;
+ $tp_str_0 = 148384;
+ label = 17;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call3 = _strlen($7 | 0) | 0;
+ $isEdge_0 = 0;
+ $hp_len_1 = 0;
+ $tp_len_1 = 0;
+ $l_len_1 = $call3;
+ $t_len_0 = 2;
+ $h_len_0 = 2;
+ $e_len_0 = 2;
+ $n_len_0 = 2;
+ $g_len_0 = $call;
+ $l_str_1 = $7;
+ $t_str_0 = 133960;
+ $h_str_0 = 136304;
+ $e_str_1 = 139088;
+ $n_str_0 = 142576;
+ $g_str_0 = $4;
+ $hp_str_0 = 148384;
+ $tp_str_0 = 148384;
+ label = 17;
+ break;
+ case 6:
+ $graph = $obj + 20 | 0;
+ $8 = $graph;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $name6 = $9 + 12 | 0;
+ $10 = HEAP32[$name6 >> 2] | 0;
+ $call7 = _strlen($10 | 0) | 0;
+ $name8 = $obj + 12 | 0;
+ $11 = $name8;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $call9 = _strlen($12 | 0) | 0;
+ $label11 = $obj + 120 | 0;
+ $13 = $label11;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $tobool12 = ($14 | 0) == 0;
+ if ($tobool12) {
+ $isEdge_0 = 0;
+ $hp_len_1 = 0;
+ $tp_len_1 = 0;
+ $l_len_1 = 2;
+ $t_len_0 = 2;
+ $h_len_0 = 2;
+ $e_len_0 = 2;
+ $n_len_0 = $call9;
+ $g_len_0 = $call7;
+ $l_str_1 = 131720;
+ $t_str_0 = 133960;
+ $h_str_0 = 136304;
+ $e_str_1 = 139088;
+ $n_str_0 = $12;
+ $g_str_0 = $10;
+ $hp_str_0 = 148384;
+ $tp_str_0 = 148384;
+ label = 17;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $text14 = $14 | 0;
+ $15 = HEAP32[$text14 >> 2] | 0;
+ $tobool15 = ($str | 0) == 0;
+ if ($tobool15) {
+ $isEdge_0 = 0;
+ $hp_len_1 = 0;
+ $tp_len_1 = 0;
+ $l_len_1 = 2;
+ $t_len_0 = 2;
+ $h_len_0 = 2;
+ $e_len_0 = 2;
+ $n_len_0 = $call9;
+ $g_len_0 = $call7;
+ $l_str_1 = $15;
+ $t_str_0 = 133960;
+ $h_str_0 = 136304;
+ $e_str_1 = 139088;
+ $n_str_0 = $12;
+ $g_str_0 = $10;
+ $hp_str_0 = 148384;
+ $tp_str_0 = 148384;
+ label = 17;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call17 = _strlen($15 | 0) | 0;
+ $isEdge_0 = 0;
+ $hp_len_1 = 0;
+ $tp_len_1 = 0;
+ $l_len_1 = $call17;
+ $t_len_0 = 2;
+ $h_len_0 = 2;
+ $e_len_0 = 2;
+ $n_len_0 = $call9;
+ $g_len_0 = $call7;
+ $l_str_1 = $15;
+ $t_str_0 = 133960;
+ $h_str_0 = 136304;
+ $e_str_1 = 139088;
+ $n_str_0 = $12;
+ $g_str_0 = $10;
+ $hp_str_0 = 148384;
+ $tp_str_0 = 148384;
+ label = 17;
+ break;
+ case 9:
+ $tail = $obj + 16 | 0;
+ $16 = $tail;
+ $17 = HEAP32[$16 >> 2] | 0;
+ $graph21 = $17 + 20 | 0;
+ $18 = HEAP32[$graph21 >> 2] | 0;
+ $root = $18 + 32 | 0;
+ $19 = HEAP32[$root >> 2] | 0;
+ $name22 = $19 + 12 | 0;
+ $20 = HEAP32[$name22 >> 2] | 0;
+ $call23 = _strlen($20 | 0) | 0;
+ $name25 = $17 + 12 | 0;
+ $21 = HEAP32[$name25 >> 2] | 0;
+ $call26 = _strlen($21 | 0) | 0;
+ $pt_sroa_1_36__idx6 = $obj + 68 | 0;
+ $22 = $pt_sroa_1_36__idx6;
+ $pt_sroa_1_36_copyload7 = HEAP32[$22 >> 2] | 0;
+ $tobool29 = ($pt_sroa_1_36_copyload7 | 0) == 0;
+ if ($tobool29) {
+ $tp_len_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call31 = _strlen($pt_sroa_1_36_copyload7 | 0) | 0;
+ $tp_len_0 = $call31;
+ label = 11;
+ break;
+ case 11:
+ $head = $obj + 12 | 0;
+ $23 = $head;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $name33 = $24 + 12 | 0;
+ $25 = HEAP32[$name33 >> 2] | 0;
+ $pt_sroa_1_36__idx4 = $obj + 108 | 0;
+ $26 = $pt_sroa_1_36__idx4;
+ $pt_sroa_1_36_copyload = HEAP32[$26 >> 2] | 0;
+ $tobool37 = ($pt_sroa_1_36_copyload | 0) == 0;
+ if ($tobool37) {
+ $hp_len_0 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call39 = _strlen($pt_sroa_1_36_copyload | 0) | 0;
+ $hp_len_0 = $call39;
+ label = 13;
+ break;
+ case 13:
+ $call41 = _strlen($25 | 0) | 0;
+ $label43 = $obj + 112 | 0;
+ $27 = $label43;
+ $28 = HEAP32[$27 >> 2] | 0;
+ $tobool44 = ($28 | 0) == 0;
+ if ($tobool44) {
+ $l_len_0 = 2;
+ $l_str_0 = 131720;
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $text46 = $28 | 0;
+ $29 = HEAP32[$text46 >> 2] | 0;
+ $tobool47 = ($str | 0) == 0;
+ if ($tobool47) {
+ $l_len_0 = 2;
+ $l_str_0 = $29;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $call49 = _strlen($29 | 0) | 0;
+ $l_len_0 = $call49;
+ $l_str_0 = $29;
+ label = 16;
+ break;
+ case 16:
+ $30 = HEAP32[$16 >> 2] | 0;
+ $graph53 = $30 + 20 | 0;
+ $31 = HEAP32[$graph53 >> 2] | 0;
+ $root54 = $31 + 32 | 0;
+ $32 = HEAP32[$root54 >> 2] | 0;
+ $33 = $32;
+ $34 = HEAP32[$33 >> 2] | 0;
+ $and = $34 & 16;
+ $tobool57 = ($and | 0) == 0;
+ $_ = $tobool57 ? 111928 : 117160;
+ $tobool60 = ($tp_len_0 | 0) == 0;
+ $add = $tp_len_0 + 1 | 0;
+ $cond = $tobool60 ? 0 : $add;
+ $tobool64 = ($hp_len_0 | 0) == 0;
+ $add66 = $hp_len_0 + 1 | 0;
+ $_add66 = $tobool64 ? 0 : $add66;
+ $add61 = $call26 + 2 | 0;
+ $add62 = $add61 + $cond | 0;
+ $add63 = $add62 + $call41 | 0;
+ $add70 = $add63 + $_add66 | 0;
+ $isEdge_0 = 1;
+ $hp_len_1 = $hp_len_0;
+ $tp_len_1 = $tp_len_0;
+ $l_len_1 = $l_len_0;
+ $t_len_0 = $call26;
+ $h_len_0 = $call41;
+ $e_len_0 = $add70;
+ $n_len_0 = 2;
+ $g_len_0 = $call23;
+ $l_str_1 = $l_str_0;
+ $t_str_0 = $21;
+ $h_str_0 = $25;
+ $e_str_1 = $_;
+ $n_str_0 = 142576;
+ $g_str_0 = $20;
+ $hp_str_0 = $pt_sroa_1_36_copyload;
+ $tp_str_0 = $pt_sroa_1_36_copyload7;
+ label = 17;
+ break;
+ case 17:
+ $tobool89 = ($escBackslash | 0) == 0;
+ $newlen_0 = 0;
+ $s_0 = $str;
+ label = 18;
+ break;
+ case 18:
+ $incdec_ptr = $s_0 + 1 | 0;
+ $35 = HEAP8[$s_0] | 0;
+ if (($35 << 24 >> 24 | 0) == 92) {
+ label = 19;
+ break;
+ } else if (($35 << 24 >> 24 | 0) == 0) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 19:
+ $incdec_ptr74 = $s_0 + 2 | 0;
+ $36 = HEAP8[$incdec_ptr] | 0;
+ $conv75 = $36 << 24 >> 24;
+ if (($conv75 | 0) == 71) {
+ label = 20;
+ break;
+ } else if (($conv75 | 0) == 78) {
+ label = 21;
+ break;
+ } else if (($conv75 | 0) == 69) {
+ label = 22;
+ break;
+ } else if (($conv75 | 0) == 72) {
+ label = 23;
+ break;
+ } else if (($conv75 | 0) == 84) {
+ label = 24;
+ break;
+ } else if (($conv75 | 0) == 76) {
+ label = 25;
+ break;
+ } else if (($conv75 | 0) == 92) {
+ label = 26;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 20:
+ $add77 = $newlen_0 + $g_len_0 | 0;
+ $newlen_0 = $add77;
+ $s_0 = $incdec_ptr74;
+ label = 18;
+ break;
+ case 21:
+ $add79 = $newlen_0 + $n_len_0 | 0;
+ $newlen_0 = $add79;
+ $s_0 = $incdec_ptr74;
+ label = 18;
+ break;
+ case 22:
+ $add81 = $newlen_0 + $e_len_0 | 0;
+ $newlen_0 = $add81;
+ $s_0 = $incdec_ptr74;
+ label = 18;
+ break;
+ case 23:
+ $add83 = $newlen_0 + $h_len_0 | 0;
+ $newlen_0 = $add83;
+ $s_0 = $incdec_ptr74;
+ label = 18;
+ break;
+ case 24:
+ $add85 = $newlen_0 + $t_len_0 | 0;
+ $newlen_0 = $add85;
+ $s_0 = $incdec_ptr74;
+ label = 18;
+ break;
+ case 25:
+ $add87 = $newlen_0 + $l_len_1 | 0;
+ $newlen_0 = $add87;
+ $s_0 = $incdec_ptr74;
+ label = 18;
+ break;
+ case 26:
+ if ($tobool89) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $add91 = $newlen_0 + 1 | 0;
+ $newlen_0 = $add91;
+ $s_0 = $incdec_ptr74;
+ label = 18;
+ break;
+ case 28:
+ $add93 = $newlen_0 + 2 | 0;
+ $newlen_0 = $add93;
+ $s_0 = $incdec_ptr74;
+ label = 18;
+ break;
+ case 29:
+ $inc = $newlen_0 + 1 | 0;
+ $newlen_0 = $inc;
+ $s_0 = $incdec_ptr;
+ label = 18;
+ break;
+ case 30:
+ $add97 = $newlen_0 + 1 | 0;
+ $call98 = _gmalloc($add97) | 0;
+ $tobool125 = ($isEdge_0 | 0) == 0;
+ $tobool134 = ($tp_len_1 | 0) == 0;
+ $tobool159 = ($hp_len_1 | 0) == 0;
+ $tobool196 = ($escBackslash | 0) == 0;
+ $p_0 = $call98;
+ $s_1 = $str;
+ label = 31;
+ break;
+ case 31:
+ $incdec_ptr100 = $s_1 + 1 | 0;
+ $37 = HEAP8[$s_1] | 0;
+ if (($37 << 24 >> 24 | 0) == 92) {
+ label = 32;
+ break;
+ } else if (($37 << 24 >> 24 | 0) == 0) {
+ label = 60;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 32:
+ $incdec_ptr107 = $s_1 + 2 | 0;
+ $38 = HEAP8[$incdec_ptr100] | 0;
+ $conv108 = $38 << 24 >> 24;
+ if (($conv108 | 0) == 71) {
+ label = 33;
+ break;
+ } else if (($conv108 | 0) == 78) {
+ label = 34;
+ break;
+ } else if (($conv108 | 0) == 84) {
+ label = 35;
+ break;
+ } else if (($conv108 | 0) == 72) {
+ label = 36;
+ break;
+ } else if (($conv108 | 0) == 76) {
+ label = 37;
+ break;
+ } else if (($conv108 | 0) == 69) {
+ label = 40;
+ break;
+ } else if (($conv108 | 0) == 92) {
+ label = 56;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 33:
+ $39 = HEAP8[$g_str_0] | 0;
+ HEAP8[$p_0] = $39;
+ $tobool112134 = $39 << 24 >> 24 == 0;
+ if ($tobool112134) {
+ $p_0 = $p_0;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_1135 = $p_0;
+ $t_0136 = $g_str_0;
+ label = 38;
+ break;
+ }
+ case 34:
+ $40 = HEAP8[$n_str_0] | 0;
+ HEAP8[$p_0] = $40;
+ $tobool119129 = $40 << 24 >> 24 == 0;
+ if ($tobool119129) {
+ $p_0 = $p_0;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_2130 = $p_0;
+ $t_1131 = $n_str_0;
+ label = 39;
+ break;
+ }
+ case 35:
+ $41 = HEAP8[$t_str_0] | 0;
+ HEAP8[$p_0] = $41;
+ $tobool174111 = $41 << 24 >> 24 == 0;
+ if ($tobool174111) {
+ $p_0 = $p_0;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_9112 = $p_0;
+ $t_7113 = $t_str_0;
+ label = 53;
+ break;
+ }
+ case 36:
+ $42 = HEAP8[$h_str_0] | 0;
+ HEAP8[$p_0] = $42;
+ $tobool182106 = $42 << 24 >> 24 == 0;
+ if ($tobool182106) {
+ $p_0 = $p_0;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_10107 = $p_0;
+ $t_8108 = $h_str_0;
+ label = 54;
+ break;
+ }
+ case 37:
+ $43 = HEAP8[$l_str_1] | 0;
+ HEAP8[$p_0] = $43;
+ $tobool190102 = $43 << 24 >> 24 == 0;
+ if ($tobool190102) {
+ $p_0 = $p_0;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_11103 = $p_0;
+ $t_9104 = $l_str_1;
+ label = 55;
+ break;
+ }
+ case 38:
+ $incdec_ptr111 = $t_0136 + 1 | 0;
+ $incdec_ptr114 = $p_1135 + 1 | 0;
+ $44 = HEAP8[$incdec_ptr111] | 0;
+ HEAP8[$incdec_ptr114] = $44;
+ $tobool112 = $44 << 24 >> 24 == 0;
+ if ($tobool112) {
+ $p_0 = $incdec_ptr114;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_1135 = $incdec_ptr114;
+ $t_0136 = $incdec_ptr111;
+ label = 38;
+ break;
+ }
+ case 39:
+ $incdec_ptr118 = $t_1131 + 1 | 0;
+ $incdec_ptr122 = $p_2130 + 1 | 0;
+ $45 = HEAP8[$incdec_ptr118] | 0;
+ HEAP8[$incdec_ptr122] = $45;
+ $tobool119 = $45 << 24 >> 24 == 0;
+ if ($tobool119) {
+ $p_0 = $incdec_ptr122;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_2130 = $incdec_ptr122;
+ $t_1131 = $incdec_ptr118;
+ label = 39;
+ break;
+ }
+ case 40:
+ if ($tobool125) {
+ $p_0 = $p_0;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $46 = HEAP8[$t_str_0] | 0;
+ HEAP8[$p_0] = $46;
+ $tobool129115 = $46 << 24 >> 24 == 0;
+ if ($tobool129115) {
+ $p_3_lcssa = $p_0;
+ label = 43;
+ break;
+ } else {
+ $p_3116 = $p_0;
+ $t_2117 = $t_str_0;
+ label = 42;
+ break;
+ }
+ case 42:
+ $incdec_ptr128 = $t_2117 + 1 | 0;
+ $incdec_ptr132 = $p_3116 + 1 | 0;
+ $47 = HEAP8[$incdec_ptr128] | 0;
+ HEAP8[$incdec_ptr132] = $47;
+ $tobool129 = $47 << 24 >> 24 == 0;
+ if ($tobool129) {
+ $p_3_lcssa = $incdec_ptr132;
+ label = 43;
+ break;
+ } else {
+ $p_3116 = $incdec_ptr132;
+ $t_2117 = $incdec_ptr128;
+ label = 42;
+ break;
+ }
+ case 43:
+ if ($tobool134) {
+ $p_6_ph = $p_3_lcssa;
+ label = 46;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ HEAP8[$p_3_lcssa] = 58;
+ $t_3 = $tp_str_0;
+ $p_3_pn = $p_3_lcssa;
+ label = 45;
+ break;
+ case 45:
+ $p_4 = $p_3_pn + 1 | 0;
+ $48 = HEAP8[$t_3] | 0;
+ HEAP8[$p_4] = $48;
+ $tobool139 = $48 << 24 >> 24 == 0;
+ $incdec_ptr138 = $t_3 + 1 | 0;
+ if ($tobool139) {
+ $p_6_ph = $p_4;
+ label = 46;
+ break;
+ } else {
+ $t_3 = $incdec_ptr138;
+ $p_3_pn = $p_4;
+ label = 45;
+ break;
+ }
+ case 46:
+ $49 = HEAP8[$e_str_1] | 0;
+ HEAP8[$p_6_ph] = $49;
+ $tobool147119 = $49 << 24 >> 24 == 0;
+ if ($tobool147119) {
+ $p_6_lcssa = $p_6_ph;
+ label = 48;
+ break;
+ } else {
+ $p_6120 = $p_6_ph;
+ $t_4121 = $e_str_1;
+ label = 47;
+ break;
+ }
+ case 47:
+ $incdec_ptr146 = $t_4121 + 1 | 0;
+ $incdec_ptr150 = $p_6120 + 1 | 0;
+ $50 = HEAP8[$incdec_ptr146] | 0;
+ HEAP8[$incdec_ptr150] = $50;
+ $tobool147 = $50 << 24 >> 24 == 0;
+ if ($tobool147) {
+ $p_6_lcssa = $incdec_ptr150;
+ label = 48;
+ break;
+ } else {
+ $p_6120 = $incdec_ptr150;
+ $t_4121 = $incdec_ptr146;
+ label = 47;
+ break;
+ }
+ case 48:
+ $51 = HEAP8[$h_str_0] | 0;
+ HEAP8[$p_6_lcssa] = $51;
+ $tobool154123 = $51 << 24 >> 24 == 0;
+ if ($tobool154123) {
+ $p_7_lcssa = $p_6_lcssa;
+ label = 50;
+ break;
+ } else {
+ $p_7124 = $p_6_lcssa;
+ $t_5125 = $h_str_0;
+ label = 49;
+ break;
+ }
+ case 49:
+ $incdec_ptr153 = $t_5125 + 1 | 0;
+ $incdec_ptr157 = $p_7124 + 1 | 0;
+ $52 = HEAP8[$incdec_ptr153] | 0;
+ HEAP8[$incdec_ptr157] = $52;
+ $tobool154 = $52 << 24 >> 24 == 0;
+ if ($tobool154) {
+ $p_7_lcssa = $incdec_ptr157;
+ label = 50;
+ break;
+ } else {
+ $p_7124 = $incdec_ptr157;
+ $t_5125 = $incdec_ptr153;
+ label = 49;
+ break;
+ }
+ case 50:
+ if ($tobool159) {
+ $p_0 = $p_7_lcssa;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ HEAP8[$p_7_lcssa] = 58;
+ $t_6 = $hp_str_0;
+ $p_7_pn = $p_7_lcssa;
+ label = 52;
+ break;
+ case 52:
+ $p_8 = $p_7_pn + 1 | 0;
+ $53 = HEAP8[$t_6] | 0;
+ HEAP8[$p_8] = $53;
+ $tobool164 = $53 << 24 >> 24 == 0;
+ $incdec_ptr163 = $t_6 + 1 | 0;
+ if ($tobool164) {
+ $p_0 = $p_8;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $t_6 = $incdec_ptr163;
+ $p_7_pn = $p_8;
+ label = 52;
+ break;
+ }
+ case 53:
+ $incdec_ptr173 = $t_7113 + 1 | 0;
+ $incdec_ptr177 = $p_9112 + 1 | 0;
+ $54 = HEAP8[$incdec_ptr173] | 0;
+ HEAP8[$incdec_ptr177] = $54;
+ $tobool174 = $54 << 24 >> 24 == 0;
+ if ($tobool174) {
+ $p_0 = $incdec_ptr177;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_9112 = $incdec_ptr177;
+ $t_7113 = $incdec_ptr173;
+ label = 53;
+ break;
+ }
+ case 54:
+ $incdec_ptr181 = $t_8108 + 1 | 0;
+ $incdec_ptr185 = $p_10107 + 1 | 0;
+ $55 = HEAP8[$incdec_ptr181] | 0;
+ HEAP8[$incdec_ptr185] = $55;
+ $tobool182 = $55 << 24 >> 24 == 0;
+ if ($tobool182) {
+ $p_0 = $incdec_ptr185;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_10107 = $incdec_ptr185;
+ $t_8108 = $incdec_ptr181;
+ label = 54;
+ break;
+ }
+ case 55:
+ $incdec_ptr189 = $t_9104 + 1 | 0;
+ $incdec_ptr193 = $p_11103 + 1 | 0;
+ $56 = HEAP8[$incdec_ptr189] | 0;
+ HEAP8[$incdec_ptr193] = $56;
+ $tobool190 = $56 << 24 >> 24 == 0;
+ if ($tobool190) {
+ $p_0 = $incdec_ptr193;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ } else {
+ $p_11103 = $incdec_ptr193;
+ $t_9104 = $incdec_ptr189;
+ label = 55;
+ break;
+ }
+ case 56:
+ if ($tobool196) {
+ label = 58;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $incdec_ptr198 = $p_0 + 1 | 0;
+ HEAP8[$p_0] = 92;
+ $p_0 = $incdec_ptr198;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ case 58:
+ $incdec_ptr201 = $p_0 + 1 | 0;
+ HEAP8[$p_0] = 92;
+ $incdec_ptr202 = $p_0 + 2 | 0;
+ HEAP8[$incdec_ptr201] = $38;
+ $p_0 = $incdec_ptr202;
+ $s_1 = $incdec_ptr107;
+ label = 31;
+ break;
+ case 59:
+ $incdec_ptr205 = $p_0 + 1 | 0;
+ HEAP8[$p_0] = $37;
+ $p_0 = $incdec_ptr205;
+ $s_1 = $incdec_ptr100;
+ label = 31;
+ break;
+ case 60:
+ HEAP8[$p_0] = 0;
+ return $call98 | 0;
+ }
+ return 0;
+}
+function _free_textpara($tl, $cnt) {
+ $tl = $tl | 0;
+ $cnt = $cnt | 0;
+ var $tobool = 0, $cmp11 = 0, $tlp_013 = 0, $i_012 = 0, $cmp1 = 0, $str = 0, $0 = 0, $tobool2 = 0, $layout = 0, $1 = 0, $tobool6 = 0, $free_layout = 0, $2 = 0, $tobool8 = 0, $incdec_ptr = 0, $inc = 0, $cmp = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($tl | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp11 = ($cnt | 0) > 0;
+ if ($cmp11) {
+ $i_012 = 0;
+ $tlp_013 = $tl;
+ label = 4;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 4:
+ $cmp1 = ($i_012 | 0) == 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $str = $tlp_013 | 0;
+ $0 = HEAP32[$str >> 2] | 0;
+ $tobool2 = ($0 | 0) == 0;
+ if ($tobool2) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _free($0);
+ label = 7;
+ break;
+ case 7:
+ $layout = $tlp_013 + 8 | 0;
+ $1 = HEAP32[$layout >> 2] | 0;
+ $tobool6 = ($1 | 0) == 0;
+ if ($tobool6) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $free_layout = $tlp_013 + 12 | 0;
+ $2 = HEAP32[$free_layout >> 2] | 0;
+ $tobool8 = ($2 | 0) == 0;
+ if ($tobool8) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ FUNCTION_TABLE_vi[$2 & 1023]($1);
+ label = 10;
+ break;
+ case 10:
+ $incdec_ptr = $tlp_013 + 80 | 0;
+ $inc = $i_012 + 1 | 0;
+ $cmp = ($inc | 0) < ($cnt | 0);
+ if ($cmp) {
+ $i_012 = $inc;
+ $tlp_013 = $incdec_ptr;
+ label = 4;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $3 = $tl;
+ _free($3);
+ label = 12;
+ break;
+ case 12:
+ return;
+ }
+}
+function _free_label($p) {
+ $p = $p | 0;
+ var $tobool = 0, $text = 0, $0 = 0, $html = 0, $1 = 0, $tobool1 = 0, $u = 0, $html3 = 0, $2 = 0, $para = 0, $3 = 0, $nparas = 0, $4 = 0, $conv = 0, $5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($p | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $text = $p | 0;
+ $0 = HEAP32[$text >> 2] | 0;
+ _free($0);
+ $html = $p + 82 | 0;
+ $1 = HEAP8[$html] | 0;
+ $tobool1 = $1 << 24 >> 24 == 0;
+ $u = $p + 72 | 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $html3 = $u;
+ $2 = HEAP32[$html3 >> 2] | 0;
+ _free_html_label($2, 1);
+ label = 6;
+ break;
+ case 5:
+ $para = $u | 0;
+ $3 = HEAP32[$para >> 2] | 0;
+ $nparas = $p + 76 | 0;
+ $4 = HEAP16[$nparas >> 1] | 0;
+ $conv = $4 << 16 >> 16;
+ _free_textpara($3, $conv);
+ label = 6;
+ break;
+ case 6:
+ $5 = $p;
+ _free($5);
+ label = 7;
+ break;
+ case 7:
+ return;
+ }
+}
+function _emit_label($job, $emit_state, $lp) {
+ $job = $job | 0;
+ $emit_state = $emit_state | 0;
+ $lp = $lp | 0;
+ var $p = 0, $obj1 = 0, $0 = 0, $emit_state2 = 0, $1 = 0, $html = 0, $2 = 0, $tobool = 0, $u = 0, $html4 = 0, $3 = 0, $nparas = 0, $4 = 0, $cmp = 0, $fontcolor = 0, $5 = 0, $valign = 0, $6 = 0, $conv10 = 0, $y = 0, $7 = 0.0, $y11 = 0, $8 = 0.0, $div = 0.0, $add = 0.0, $fontsize = 0, $9 = 0.0, $sub = 0.0, $y12 = 0, $y15 = 0, $10 = 0.0, $y17 = 0, $11 = 0.0, $div18 = 0.0, $sub19 = 0.0, $y20 = 0, $12 = 0.0, $add21 = 0.0, $fontsize22 = 0, $13 = 0.0, $sub23 = 0.0, $y24 = 0, $y27 = 0, $14 = 0.0, $y29 = 0, $15 = 0.0, $div30 = 0.0, $add31 = 0.0, $fontsize32 = 0, $16 = 0.0, $sub33 = 0.0, $y34 = 0, $17 = 0, $cmp3939 = 0, $para = 0, $x62 = 0, $x63 = 0, $y73 = 0, $x = 0, $x47 = 0, $x50 = 0, $x53 = 0, $x55 = 0, $x58 = 0, $i_040 = 0, $18 = 0, $just = 0, $19 = 0, $conv43 = 0, $20 = 0.0, $21 = 0.0, $div48 = 0.0, $sub49 = 0.0, $22 = 0.0, $23 = 0.0, $div56 = 0.0, $add57 = 0.0, $24 = 0.0, $25 = 0, $arrayidx68 = 0, $26 = 0, $height = 0, $27 = 0.0, $28 = 0.0, $sub74 = 0.0, $inc = 0, $29 = 0, $conv38 = 0, $cmp39 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p = __stackBase__ | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $emit_state2 = $0 + 12 | 0;
+ $1 = HEAP32[$emit_state2 >> 2] | 0;
+ HEAP32[$emit_state2 >> 2] = $emit_state;
+ $html = $lp + 82 | 0;
+ $2 = HEAP8[$html] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $u = $lp + 72 | 0;
+ $html4 = $u;
+ $3 = HEAP32[$html4 >> 2] | 0;
+ _emit_html_label($job, $3, $lp);
+ HEAP32[$emit_state2 >> 2] = $1;
+ label = 17;
+ break;
+ case 4:
+ $nparas = $lp + 76 | 0;
+ $4 = HEAP16[$nparas >> 1] | 0;
+ $cmp = $4 << 16 >> 16 < 1;
+ if ($cmp) {
+ label = 17;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _gvrender_begin_label($job, 0);
+ $fontcolor = $lp + 8 | 0;
+ $5 = HEAP32[$fontcolor >> 2] | 0;
+ _gvrender_set_pencolor($job, $5);
+ $valign = $lp + 80 | 0;
+ $6 = HEAP8[$valign] | 0;
+ $conv10 = $6 << 24 >> 24;
+ if (($conv10 | 0) == 116) {
+ label = 6;
+ break;
+ } else if (($conv10 | 0) == 98) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $y = $lp + 64 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $y11 = $lp + 48 | 0;
+ $8 = +HEAPF64[$y11 >> 3];
+ $div = $8 * .5;
+ $add = $7 + $div;
+ $fontsize = $lp + 16 | 0;
+ $9 = +HEAPF64[$fontsize >> 3];
+ $sub = $add - $9;
+ $y12 = $p + 8 | 0;
+ HEAPF64[$y12 >> 3] = $sub;
+ label = 9;
+ break;
+ case 7:
+ $y15 = $lp + 64 | 0;
+ $10 = +HEAPF64[$y15 >> 3];
+ $y17 = $lp + 48 | 0;
+ $11 = +HEAPF64[$y17 >> 3];
+ $div18 = $11 * .5;
+ $sub19 = $10 - $div18;
+ $y20 = $lp + 32 | 0;
+ $12 = +HEAPF64[$y20 >> 3];
+ $add21 = $12 + $sub19;
+ $fontsize22 = $lp + 16 | 0;
+ $13 = +HEAPF64[$fontsize22 >> 3];
+ $sub23 = $add21 - $13;
+ $y24 = $p + 8 | 0;
+ HEAPF64[$y24 >> 3] = $sub23;
+ label = 9;
+ break;
+ case 8:
+ $y27 = $lp + 64 | 0;
+ $14 = +HEAPF64[$y27 >> 3];
+ $y29 = $lp + 32 | 0;
+ $15 = +HEAPF64[$y29 >> 3];
+ $div30 = $15 * .5;
+ $add31 = $14 + $div30;
+ $fontsize32 = $lp + 16 | 0;
+ $16 = +HEAPF64[$fontsize32 >> 3];
+ $sub33 = $add31 - $16;
+ $y34 = $p + 8 | 0;
+ HEAPF64[$y34 >> 3] = $sub33;
+ label = 9;
+ break;
+ case 9:
+ $17 = HEAP16[$nparas >> 1] | 0;
+ $cmp3939 = $17 << 16 >> 16 > 0;
+ if ($cmp3939) {
+ label = 10;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 10:
+ $para = $lp + 72 | 0;
+ $x62 = $lp + 56 | 0;
+ $x63 = $p | 0;
+ $y73 = $p + 8 | 0;
+ $x = $lp + 56 | 0;
+ $x47 = $lp + 40 | 0;
+ $x50 = $p | 0;
+ $x53 = $lp + 56 | 0;
+ $x55 = $lp + 40 | 0;
+ $x58 = $p | 0;
+ $i_040 = 0;
+ label = 11;
+ break;
+ case 11:
+ $18 = HEAP32[$para >> 2] | 0;
+ $just = $18 + ($i_040 * 80 & -1) + 72 | 0;
+ $19 = HEAP8[$just] | 0;
+ $conv43 = $19 << 24 >> 24;
+ if (($conv43 | 0) == 108) {
+ label = 12;
+ break;
+ } else if (($conv43 | 0) == 114) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ $20 = +HEAPF64[$x >> 3];
+ $21 = +HEAPF64[$x47 >> 3];
+ $div48 = $21 * .5;
+ $sub49 = $20 - $div48;
+ HEAPF64[$x50 >> 3] = $sub49;
+ label = 15;
+ break;
+ case 13:
+ $22 = +HEAPF64[$x53 >> 3];
+ $23 = +HEAPF64[$x55 >> 3];
+ $div56 = $23 * .5;
+ $add57 = $22 + $div56;
+ HEAPF64[$x58 >> 3] = $add57;
+ label = 15;
+ break;
+ case 14:
+ $24 = +HEAPF64[$x62 >> 3];
+ HEAPF64[$x63 >> 3] = $24;
+ label = 15;
+ break;
+ case 15:
+ $25 = HEAP32[$para >> 2] | 0;
+ $arrayidx68 = $25 + ($i_040 * 80 & -1) | 0;
+ _gvrender_textpara($job, $p, $arrayidx68);
+ $26 = HEAP32[$para >> 2] | 0;
+ $height = $26 + ($i_040 * 80 & -1) + 64 | 0;
+ $27 = +HEAPF64[$height >> 3];
+ $28 = +HEAPF64[$y73 >> 3];
+ $sub74 = $28 - $27;
+ HEAPF64[$y73 >> 3] = $sub74;
+ $inc = $i_040 + 1 | 0;
+ $29 = HEAP16[$nparas >> 1] | 0;
+ $conv38 = $29 << 16 >> 16;
+ $cmp39 = ($inc | 0) < ($conv38 | 0);
+ if ($cmp39) {
+ $i_040 = $inc;
+ label = 11;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ _gvrender_end_label($job);
+ HEAP32[$emit_state2 >> 2] = $1;
+ label = 17;
+ break;
+ case 17:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _strdup_and_subst_obj($str, $obj) {
+ $str = $str | 0;
+ $obj = $obj | 0;
+ return _strdup_and_subst_obj0($str, $obj, 1) | 0;
+}
+function _xml_string($s) {
+ $s = $s | 0;
+ var $0 = 0, $tobool = 0, $call = 0, $1 = 0, $tobool121 = 0, $pos_025 = 0, $prev_024 = 0, $p_023 = 0, $s_addr_022 = 0, $2 = 0, $tobool2 = 0, $3 = 0, $sub3 = 0, $cmp = 0, $mul = 0, $4 = 0, $call6 = 0, $add_ptr = 0, $p_1 = 0, $5 = 0, $cmp9 = 0, $call11 = 0, $tobool12 = 0, $_pr = 0, $6 = 0, $tobool33 = 0, $7 = 0, $cmp36 = 0, $8 = 0, $sub_0_ph = 0, $len_0_ph = 0, $9 = 0, $len_019 = 0, $sub_018 = 0, $p_217 = 0, $dec = 0, $incdec_ptr = 0, $10 = 0, $incdec_ptr60 = 0, $tobool58 = 0, $scevgep = 0, $incdec_ptr61 = 0, $tobool1 = 0, $p_0_lcssa = 0, $11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[8] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[6] = 64;
+ $call = _gmalloc(64) | 0;
+ HEAP32[8] = $call;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[8] | 0;
+ $tobool121 = ($s | 0) == 0;
+ if ($tobool121) {
+ $p_0_lcssa = $1;
+ label = 22;
+ break;
+ } else {
+ $s_addr_022 = $s;
+ $p_023 = $1;
+ $prev_024 = 0;
+ $pos_025 = 0;
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP8[$s_addr_022] | 0;
+ $tobool2 = $2 << 24 >> 24 == 0;
+ if ($tobool2) {
+ $p_0_lcssa = $p_023;
+ label = 22;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = HEAP32[6] | 0;
+ $sub3 = $3 - 8 | 0;
+ $cmp = ($pos_025 | 0) > ($sub3 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ $p_1 = $p_023;
+ label = 8;
+ break;
+ }
+ case 7:
+ $mul = $3 << 1;
+ HEAP32[6] = $mul;
+ $4 = HEAP32[8] | 0;
+ $call6 = _grealloc($4, $mul) | 0;
+ HEAP32[8] = $call6;
+ $add_ptr = $call6 + $pos_025 | 0;
+ $p_1 = $add_ptr;
+ label = 8;
+ break;
+ case 8:
+ $5 = HEAP8[$s_addr_022] | 0;
+ $cmp9 = $5 << 24 >> 24 == 38;
+ if ($cmp9) {
+ label = 9;
+ break;
+ } else {
+ $6 = $5;
+ label = 11;
+ break;
+ }
+ case 9:
+ $call11 = _xml_isentity($s_addr_022) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ $len_0_ph = 5;
+ $sub_0_ph = 99472;
+ label = 19;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $_pr = HEAP8[$s_addr_022] | 0;
+ $6 = $_pr;
+ label = 11;
+ break;
+ case 11:
+ if (($6 << 24 >> 24 | 0) == 62) {
+ label = 12;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 45) {
+ label = 13;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 32) {
+ label = 14;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 60) {
+ $len_0_ph = 4;
+ $sub_0_ph = 95416;
+ label = 19;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 12:
+ $len_0_ph = 4;
+ $sub_0_ph = 91912;
+ label = 19;
+ break;
+ case 13:
+ $len_0_ph = 5;
+ $sub_0_ph = 162096;
+ label = 19;
+ break;
+ case 14:
+ $tobool33 = ($prev_024 | 0) == 0;
+ if ($tobool33) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $7 = HEAP8[$prev_024] | 0;
+ $cmp36 = $7 << 24 >> 24 == 32;
+ if ($cmp36) {
+ $len_0_ph = 6;
+ $sub_0_ph = 158608;
+ label = 19;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $8 = HEAP8[$s_addr_022] | 0;
+ if (($8 << 24 >> 24 | 0) == 39) {
+ label = 17;
+ break;
+ } else if (($8 << 24 >> 24 | 0) == 34) {
+ $len_0_ph = 6;
+ $sub_0_ph = 155128;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $len_0_ph = 5;
+ $sub_0_ph = 151664;
+ label = 19;
+ break;
+ case 18:
+ $len_0_ph = 1;
+ $sub_0_ph = $s_addr_022;
+ label = 19;
+ break;
+ case 19:
+ $9 = $len_0_ph + $pos_025 | 0;
+ $p_217 = $p_1;
+ $sub_018 = $sub_0_ph;
+ $len_019 = $len_0_ph;
+ label = 20;
+ break;
+ case 20:
+ $dec = $len_019 - 1 | 0;
+ $incdec_ptr = $sub_018 + 1 | 0;
+ $10 = HEAP8[$sub_018] | 0;
+ $incdec_ptr60 = $p_217 + 1 | 0;
+ HEAP8[$p_217] = $10;
+ $tobool58 = ($dec | 0) == 0;
+ if ($tobool58) {
+ label = 21;
+ break;
+ } else {
+ $p_217 = $incdec_ptr60;
+ $sub_018 = $incdec_ptr;
+ $len_019 = $dec;
+ label = 20;
+ break;
+ }
+ case 21:
+ $scevgep = $p_1 + $len_0_ph | 0;
+ $incdec_ptr61 = $s_addr_022 + 1 | 0;
+ $tobool1 = ($incdec_ptr61 | 0) == 0;
+ if ($tobool1) {
+ $p_0_lcssa = $scevgep;
+ label = 22;
+ break;
+ } else {
+ $prev_024 = $s_addr_022;
+ $s_addr_022 = $incdec_ptr61;
+ $p_023 = $scevgep;
+ $pos_025 = $9;
+ label = 5;
+ break;
+ }
+ case 22:
+ HEAP8[$p_0_lcssa] = 0;
+ $11 = HEAP32[8] | 0;
+ return $11 | 0;
+ }
+ return 0;
+}
+function _xml_url_string($s) {
+ $s = $s | 0;
+ var $0 = 0, $tobool = 0, $call = 0, $1 = 0, $tobool118 = 0, $pos_022 = 0, $p_021 = 0, $s_addr_019 = 0, $2 = 0, $tobool2 = 0, $3 = 0, $sub3 = 0, $cmp = 0, $mul = 0, $4 = 0, $call6 = 0, $add_ptr = 0, $p_1 = 0, $5 = 0, $cmp9 = 0, $call11 = 0, $tobool12 = 0, $_pr = 0, $6 = 0, $sub_0_ph = 0, $len_0_ph = 0, $7 = 0, $len_016 = 0, $sub_015 = 0, $p_214 = 0, $dec = 0, $incdec_ptr = 0, $8 = 0, $incdec_ptr42 = 0, $tobool40 = 0, $scevgep = 0, $incdec_ptr43 = 0, $tobool1 = 0, $p_0_lcssa = 0, $9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[4] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[2] = 64;
+ $call = _gmalloc(64) | 0;
+ HEAP32[4] = $call;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[4] | 0;
+ $tobool118 = ($s | 0) == 0;
+ if ($tobool118) {
+ $p_0_lcssa = $1;
+ label = 19;
+ break;
+ } else {
+ $s_addr_019 = $s;
+ $p_021 = $1;
+ $pos_022 = 0;
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP8[$s_addr_019] | 0;
+ $tobool2 = $2 << 24 >> 24 == 0;
+ if ($tobool2) {
+ $p_0_lcssa = $p_021;
+ label = 19;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = HEAP32[2] | 0;
+ $sub3 = $3 - 8 | 0;
+ $cmp = ($pos_022 | 0) > ($sub3 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ $p_1 = $p_021;
+ label = 8;
+ break;
+ }
+ case 7:
+ $mul = $3 << 1;
+ HEAP32[2] = $mul;
+ $4 = HEAP32[4] | 0;
+ $call6 = _grealloc($4, $mul) | 0;
+ HEAP32[4] = $call6;
+ $add_ptr = $call6 + $pos_022 | 0;
+ $p_1 = $add_ptr;
+ label = 8;
+ break;
+ case 8:
+ $5 = HEAP8[$s_addr_019] | 0;
+ $cmp9 = $5 << 24 >> 24 == 38;
+ if ($cmp9) {
+ label = 9;
+ break;
+ } else {
+ $6 = $5;
+ label = 11;
+ break;
+ }
+ case 9:
+ $call11 = _xml_isentity($s_addr_019) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ $len_0_ph = 5;
+ $sub_0_ph = 99472;
+ label = 16;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $_pr = HEAP8[$s_addr_019] | 0;
+ $6 = $_pr;
+ label = 11;
+ break;
+ case 11:
+ if (($6 << 24 >> 24 | 0) == 62) {
+ label = 12;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 34) {
+ label = 13;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 39) {
+ label = 14;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 60) {
+ $len_0_ph = 4;
+ $sub_0_ph = 95416;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 12:
+ $len_0_ph = 4;
+ $sub_0_ph = 91912;
+ label = 16;
+ break;
+ case 13:
+ $len_0_ph = 6;
+ $sub_0_ph = 155128;
+ label = 16;
+ break;
+ case 14:
+ $len_0_ph = 5;
+ $sub_0_ph = 151664;
+ label = 16;
+ break;
+ case 15:
+ $len_0_ph = 1;
+ $sub_0_ph = $s_addr_019;
+ label = 16;
+ break;
+ case 16:
+ $7 = $len_0_ph + $pos_022 | 0;
+ $p_214 = $p_1;
+ $sub_015 = $sub_0_ph;
+ $len_016 = $len_0_ph;
+ label = 17;
+ break;
+ case 17:
+ $dec = $len_016 - 1 | 0;
+ $incdec_ptr = $sub_015 + 1 | 0;
+ $8 = HEAP8[$sub_015] | 0;
+ $incdec_ptr42 = $p_214 + 1 | 0;
+ HEAP8[$p_214] = $8;
+ $tobool40 = ($dec | 0) == 0;
+ if ($tobool40) {
+ label = 18;
+ break;
+ } else {
+ $p_214 = $incdec_ptr42;
+ $sub_015 = $incdec_ptr;
+ $len_016 = $dec;
+ label = 17;
+ break;
+ }
+ case 18:
+ $scevgep = $p_1 + $len_0_ph | 0;
+ $incdec_ptr43 = $s_addr_019 + 1 | 0;
+ $tobool1 = ($incdec_ptr43 | 0) == 0;
+ if ($tobool1) {
+ $p_0_lcssa = $scevgep;
+ label = 19;
+ break;
+ } else {
+ $s_addr_019 = $incdec_ptr43;
+ $p_021 = $scevgep;
+ $pos_022 = $7;
+ label = 5;
+ break;
+ }
+ case 19:
+ HEAP8[$p_0_lcssa] = 0;
+ $9 = HEAP32[4] | 0;
+ return $9 | 0;
+ }
+ return 0;
+}
+function _lineToBox($p, $q, $b) {
+ $p = $p | 0;
+ $q = $q | 0;
+ $b = $b | 0;
+ var $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $cmp = 0, $x3 = 0, $2 = 0.0, $cmp4 = 0, $y = 0, $3 = 0.0, $y7 = 0, $4 = 0.0, $cmp8 = 0, $y11 = 0, $5 = 0.0, $cmp12 = 0, $phitmp = 0, $6 = 0, $x13 = 0, $7 = 0.0, $8 = 0.0, $cmp16 = 0, $x20 = 0, $9 = 0.0, $cmp21 = 0, $y23 = 0, $10 = 0.0, $y25 = 0, $11 = 0.0, $cmp26 = 0, $y30 = 0, $12 = 0.0, $cmp31 = 0, $phitmp20 = 0, $13 = 0, $cmp34 = 0, $and = 0, $tobool = 0, $14 = 0.0, $15 = 0.0, $cmp39 = 0, $y41 = 0, $16 = 0.0, $y43 = 0, $17 = 0.0, $cmp44 = 0, $y45 = 0, $18 = 0.0, $cmp48 = 0, $xor22 = 0, $19 = 0.0, $cmp55 = 0, $x60 = 0, $20 = 0.0, $cmp61 = 0, $y66 = 0, $21 = 0.0, $cmp67 = 0, $22 = 0.0, $cmp73 = 0, $cmp78 = 0, $xor8021 = 0, $y85 = 0, $23 = 0.0, $cmp86 = 0, $y91 = 0, $24 = 0.0, $cmp92 = 0, $sub = 0.0, $sub103 = 0.0, $div = 0.0, $cmp106 = 0, $_ = 0.0, $_23 = 0.0, $25 = 0.0, $sub119 = 0.0, $mul = 0.0, $add = 0.0, $cmp122 = 0, $cmp127 = 0, $or_cond = 0, $y131 = 0, $26 = 0.0, $cmp132 = 0, $y136 = 0, $27 = 0.0, $cmp137 = 0, $x142 = 0, $28 = 0.0, $29 = 0.0, $sub145 = 0.0, $mul146 = 0.0, $add147 = 0.0, $y149 = 0, $30 = 0.0, $cmp150 = 0, $y154 = 0, $31 = 0.0, $cmp155 = 0, $cmp160 = 0, $or_cond24 = 0, $cmp165 = 0, $or_cond25 = 0, $32 = 0.0, $33 = 0.0, $cmp171 = 0, $_26 = 0.0, $_27 = 0.0, $34 = 0.0, $35 = 0.0, $sub184 = 0.0, $div185 = 0.0, $add186 = 0.0, $36 = 0.0, $cmp189 = 0, $37 = 0.0, $cmp194 = 0, $cmp199 = 0, $or_cond28 = 0, $cmp204 = 0, $or_cond29 = 0, $y209 = 0, $38 = 0.0, $39 = 0.0, $sub212 = 0.0, $div213 = 0.0, $add214 = 0.0, $40 = 0.0, $cmp217 = 0, $41 = 0.0, $cmp222 = 0, $cmp227 = 0, $or_cond30 = 0, $cmp232 = 0, $or_cond31 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $p | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $b | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $cmp = $0 < $1;
+ if ($cmp) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x3 = $b + 16 | 0;
+ $2 = +HEAPF64[$x3 >> 3];
+ $cmp4 = $0 > $2;
+ if ($cmp4) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $p + 8 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $y7 = $b + 8 | 0;
+ $4 = +HEAPF64[$y7 >> 3];
+ $cmp8 = $3 < $4;
+ if ($cmp8) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y11 = $b + 24 | 0;
+ $5 = +HEAPF64[$y11 >> 3];
+ $cmp12 = $3 <= $5;
+ $phitmp = $cmp12 & 1;
+ $6 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ $x13 = $q | 0;
+ $7 = +HEAPF64[$x13 >> 3];
+ $8 = +HEAPF64[$x1 >> 3];
+ $cmp16 = $7 < $8;
+ if ($cmp16) {
+ $13 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $x20 = $b + 16 | 0;
+ $9 = +HEAPF64[$x20 >> 3];
+ $cmp21 = $7 > $9;
+ if ($cmp21) {
+ $13 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $y23 = $q + 8 | 0;
+ $10 = +HEAPF64[$y23 >> 3];
+ $y25 = $b + 8 | 0;
+ $11 = +HEAPF64[$y25 >> 3];
+ $cmp26 = $10 < $11;
+ if ($cmp26) {
+ $13 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $y30 = $b + 24 | 0;
+ $12 = +HEAPF64[$y30 >> 3];
+ $cmp31 = $10 <= $12;
+ $phitmp20 = $cmp31 & 1;
+ $13 = $phitmp20;
+ label = 10;
+ break;
+ case 10:
+ $cmp34 = ($6 | 0) == ($13 | 0);
+ if ($cmp34) {
+ label = 11;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 11:
+ $and = $13 & $6;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 30;
+ break;
+ }
+ case 12:
+ $14 = +HEAPF64[$x >> 3];
+ $15 = +HEAPF64[$x13 >> 3];
+ $cmp39 = $14 == $15;
+ $y41 = $p + 8 | 0;
+ $16 = +HEAPF64[$y41 >> 3];
+ if ($cmp39) {
+ label = 13;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 13:
+ $y43 = $b + 8 | 0;
+ $17 = +HEAPF64[$y43 >> 3];
+ $cmp44 = $16 >= $17;
+ $y45 = $q + 8 | 0;
+ $18 = +HEAPF64[$y45 >> 3];
+ $cmp48 = $18 >= $17;
+ $xor22 = $cmp44 ^ $cmp48;
+ if ($xor22) {
+ label = 14;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 14:
+ $19 = +HEAPF64[$x1 >> 3];
+ $cmp55 = $14 < $19;
+ if ($cmp55) {
+ label = 29;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $x60 = $b + 16 | 0;
+ $20 = +HEAPF64[$x60 >> 3];
+ $cmp61 = $14 > $20;
+ if ($cmp61) {
+ label = 29;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 16:
+ $y66 = $q + 8 | 0;
+ $21 = +HEAPF64[$y66 >> 3];
+ $cmp67 = $16 == $21;
+ if ($cmp67) {
+ label = 17;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 17:
+ $22 = +HEAPF64[$x1 >> 3];
+ $cmp73 = $14 >= $22;
+ $cmp78 = $15 >= $22;
+ $xor8021 = $cmp73 ^ $cmp78;
+ if ($xor8021) {
+ label = 18;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 18:
+ $y85 = $b + 8 | 0;
+ $23 = +HEAPF64[$y85 >> 3];
+ $cmp86 = $16 < $23;
+ if ($cmp86) {
+ label = 29;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $y91 = $b + 24 | 0;
+ $24 = +HEAPF64[$y91 >> 3];
+ $cmp92 = $16 > $24;
+ if ($cmp92) {
+ label = 29;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 20:
+ $sub = $21 - $16;
+ $sub103 = $15 - $14;
+ $div = $sub / $sub103;
+ $cmp106 = $14 < $15;
+ $_ = $cmp106 ? $14 : $15;
+ $_23 = $cmp106 ? $15 : $14;
+ $25 = +HEAPF64[$x1 >> 3];
+ $sub119 = $25 - $14;
+ $mul = $div * $sub119;
+ $add = $16 + $mul;
+ $cmp122 = $25 < $_;
+ $cmp127 = $25 > $_23;
+ $or_cond = $cmp122 | $cmp127;
+ if ($or_cond) {
+ label = 23;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $y131 = $b + 8 | 0;
+ $26 = +HEAPF64[$y131 >> 3];
+ $cmp132 = $add < $26;
+ if ($cmp132) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $y136 = $b + 24 | 0;
+ $27 = +HEAPF64[$y136 >> 3];
+ $cmp137 = $add > $27;
+ if ($cmp137) {
+ label = 23;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 23:
+ $x142 = $b + 16 | 0;
+ $28 = +HEAPF64[$x142 >> 3];
+ $29 = +HEAPF64[$x1 >> 3];
+ $sub145 = $28 - $29;
+ $mul146 = $div * $sub145;
+ $add147 = $add + $mul146;
+ $y149 = $b + 8 | 0;
+ $30 = +HEAPF64[$y149 >> 3];
+ $cmp150 = $add147 < $30;
+ if ($cmp150) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $y154 = $b + 24 | 0;
+ $31 = +HEAPF64[$y154 >> 3];
+ $cmp155 = $add147 > $31;
+ $cmp160 = $28 < $_;
+ $or_cond24 = $cmp155 | $cmp160;
+ $cmp165 = $28 > $_23;
+ $or_cond25 = $or_cond24 | $cmp165;
+ if ($or_cond25) {
+ label = 25;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 25:
+ $32 = +HEAPF64[$y41 >> 3];
+ $33 = +HEAPF64[$y66 >> 3];
+ $cmp171 = $32 < $33;
+ $_26 = $cmp171 ? $32 : $33;
+ $_27 = $cmp171 ? $33 : $32;
+ $34 = +HEAPF64[$x >> 3];
+ $35 = +HEAPF64[$y149 >> 3];
+ $sub184 = $35 - $32;
+ $div185 = $sub184 / $div;
+ $add186 = $34 + $div185;
+ $36 = +HEAPF64[$x1 >> 3];
+ $cmp189 = $add186 < $36;
+ if ($cmp189) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $37 = +HEAPF64[$x142 >> 3];
+ $cmp194 = $add186 > $37;
+ $cmp199 = $35 < $_26;
+ $or_cond28 = $cmp194 | $cmp199;
+ $cmp204 = $35 > $_27;
+ $or_cond29 = $or_cond28 | $cmp204;
+ if ($or_cond29) {
+ label = 27;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 27:
+ $y209 = $b + 24 | 0;
+ $38 = +HEAPF64[$y209 >> 3];
+ $39 = +HEAPF64[$y149 >> 3];
+ $sub212 = $38 - $39;
+ $div213 = $sub212 / $div;
+ $add214 = $add186 + $div213;
+ $40 = +HEAPF64[$x1 >> 3];
+ $cmp217 = $add214 < $40;
+ if ($cmp217) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $41 = +HEAPF64[$x142 >> 3];
+ $cmp222 = $add214 > $41;
+ $cmp227 = $38 < $_26;
+ $or_cond30 = $cmp222 | $cmp227;
+ $cmp232 = $38 > $_27;
+ $or_cond31 = $or_cond30 | $cmp232;
+ if ($or_cond31) {
+ label = 29;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 29:
+ $retval_0 = -1;
+ label = 30;
+ break;
+ case 30:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _rect2poly($p) {
+ $p = $p | 0;
+ var $x = 0, $0 = 0.0;
+ $x = $p + 16 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ HEAPF64[$p + 32 >> 3] = $0;
+ HEAPF64[$p + 48 >> 3] = $0;
+ HEAPF64[$p + 40 >> 3] = +HEAPF64[$p + 24 >> 3];
+ HEAPF64[$p + 56 >> 3] = +HEAPF64[$p + 8 >> 3];
+ HEAPF64[$x >> 3] = +HEAPF64[$p >> 3];
+ return;
+}
+function _flip_rec_boxf($agg_result, $b, $p) {
+ $agg_result = $agg_result | 0;
+ $b = $b | 0;
+ $p = $p | 0;
+ var $4 = 0.0, $5 = 0.0, $add19 = 0.0, $add23 = 0.0, $add27 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $4 = +HEAPF64[$p >> 3];
+ $5 = +HEAPF64[$p + 8 >> 3];
+ $add19 = +HEAPF64[$b >> 3] + $5;
+ $add23 = +HEAPF64[$b + 24 >> 3] + $4;
+ $add27 = +HEAPF64[$b + 16 >> 3] + $5;
+ HEAPF64[$agg_result >> 3] = +HEAPF64[$b + 8 >> 3] + $4;
+ HEAPF64[$agg_result + 8 >> 3] = $add19;
+ HEAPF64[$agg_result + 16 >> 3] = $add23;
+ HEAPF64[$agg_result + 24 >> 3] = $add27;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _ptToLine2($a, $b, $p) {
+ $a = $a | 0;
+ $b = $b | 0;
+ $p = $p | 0;
+ var $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $sub = 0.0, $y = 0, $2 = 0.0, $y2 = 0, $3 = 0.0, $sub3 = 0.0, $y4 = 0, $4 = 0.0, $sub6 = 0.0, $mul = 0.0, $x7 = 0, $5 = 0.0, $sub9 = 0.0, $mul10 = 0.0, $sub11 = 0.0, $mul12 = 0.0, $cmp = 0, $mul13 = 0.0, $mul14 = 0.0, $add = 0.0, $div = 0.0, $retval_0 = 0.0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $a;
+ $a = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$a >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$a + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$a + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$a + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$b >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$b + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$b + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$b + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $b | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $a | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $sub = $0 - $1;
+ $y = $b + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $y2 = $a + 8 | 0;
+ $3 = +HEAPF64[$y2 >> 3];
+ $sub3 = $2 - $3;
+ $y4 = $p + 8 | 0;
+ $4 = +HEAPF64[$y4 >> 3];
+ $sub6 = $4 - $3;
+ $mul = $sub * $sub6;
+ $x7 = $p | 0;
+ $5 = +HEAPF64[$x7 >> 3];
+ $sub9 = $5 - $1;
+ $mul10 = $sub3 * $sub9;
+ $sub11 = $mul - $mul10;
+ $mul12 = $sub11 * $sub11;
+ $cmp = $mul12 < 1.0e-10;
+ if ($cmp) {
+ $retval_0 = 0.0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $mul13 = $sub * $sub;
+ $mul14 = $sub3 * $sub3;
+ $add = $mul13 + $mul14;
+ $div = $mul12 / $add;
+ $retval_0 = $div;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return +$retval_0;
+ }
+ return 0.0;
+}
+function _zmalloc($nbytes) {
+ $nbytes = $nbytes | 0;
+ var $cmp = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($nbytes | 0) == 0;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _gmalloc($nbytes) | 0;
+ _memset($call | 0, 0, $nbytes | 0);
+ $retval_0 = $call;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _textsize($agg_result, $g, $para, $fontname, $fontsize) {
+ $agg_result = $agg_result | 0;
+ $g = $g | 0;
+ $para = $para | 0;
+ $fontname = $fontname | 0;
+ $fontsize = +$fontsize;
+ var $fontpath = 0, $fontname1 = 0, $fontsize2 = 0, $call = 0, $postscript_alias = 0, $0 = 0, $tobool = 0, $1 = 0, $call4 = 0, $tobool5 = 0, $_fontpath = 0, $fp_0 = 0, $gvc = 0, $2 = 0, $call6 = 0, $tobool7 = 0, $tobool10 = 0, $3 = 0, $tobool12 = 0, $4 = 0, $5 = 0, $call15 = 0, $call17 = 0, $width = 0, $6 = 0.0, $height = 0, $7 = 0.0, $size_sroa_0_0__idx = 0, $size_sroa_1_8__idx1 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $fontpath = __stackBase__ | 0;
+ HEAP32[$fontpath >> 2] = 0;
+ $fontname1 = $para + 20 | 0;
+ HEAP32[$fontname1 >> 2] = $fontname;
+ $fontsize2 = $para + 24 | 0;
+ HEAPF64[$fontsize2 >> 3] = $fontsize;
+ $call = _translate_postscript_fontname($fontname) | 0;
+ $postscript_alias = $para + 4 | 0;
+ HEAP32[$postscript_alias >> 2] = $call;
+ $0 = HEAP8[164912] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ $fp_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[$fontname1 >> 2] | 0;
+ $call4 = _emit_once($1) | 0;
+ $tobool5 = ($call4 | 0) == 0;
+ $_fontpath = $tobool5 ? 0 : $fontpath;
+ $fp_0 = $_fontpath;
+ label = 4;
+ break;
+ case 4:
+ $gvc = $g + 176 | 0;
+ $2 = HEAP32[$gvc >> 2] | 0;
+ $call6 = _gvtextlayout($2, $para, $fp_0) | 0;
+ $tobool7 = $call6 << 24 >> 24 == 0;
+ if ($tobool7) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ _estimate_textlayout($para, $fp_0);
+ label = 6;
+ break;
+ case 6:
+ $tobool10 = ($fp_0 | 0) == 0;
+ if ($tobool10) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $3 = HEAP32[$fontpath >> 2] | 0;
+ $tobool12 = ($3 | 0) == 0;
+ $4 = HEAP32[_stderr >> 2] | 0;
+ $5 = HEAP32[$fontname1 >> 2] | 0;
+ if ($tobool12) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call15 = _fprintf($4 | 0, 116480, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $5, HEAP32[tempInt + 8 >> 2] = $3, tempInt) | 0) | 0;
+ label = 10;
+ break;
+ case 9:
+ $call17 = _fprintf($4 | 0, 151224, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $5, tempInt) | 0) | 0;
+ label = 10;
+ break;
+ case 10:
+ $width = $para + 56 | 0;
+ $6 = +HEAPF64[$width >> 3];
+ $height = $para + 64 | 0;
+ $7 = +HEAPF64[$height >> 3];
+ $size_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$size_sroa_0_0__idx >> 3] = $6;
+ $size_sroa_1_8__idx1 = $agg_result + 8 | 0;
+ HEAPF64[$size_sroa_1_8__idx1 >> 3] = $7;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _translate_postscript_fontname($fontname) {
+ $fontname = $fontname | 0;
+ var $0 = 0, $cmp = 0, $call = 0, $tobool = 0, $call1 = 0, $1 = 0, $2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[238] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _strcasecmp($0, $fontname) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAP32[238] = $fontname;
+ $call1 = _bsearch(952, 5648, 35, 36, 558) | 0;
+ $1 = $call1;
+ HEAP32[236] = $1;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP32[236] | 0;
+ return $2 | 0;
+ }
+ return 0;
+}
+function _estimate_textlayout($para, $fontpath) {
+ $para = $para | 0;
+ $fontpath = $fontpath | 0;
+ var $width = 0, $fontsize = 0, $0 = 0.0, $mul = 0.0, $height = 0, $yoffset_layout = 0, $1 = 0.0, $mul2 = 0.0, $yoffset_centerline = 0, $fontname = 0, $2 = 0, $layout = 0, $free_layout = 0, $3 = 0, $call = 0, $tobool = 0, $4 = 0, $call5 = 0, $tobool6 = 0, $5 = 0, $call8 = 0, $tobool9 = 0, $_ = 0, $_1 = 0, $Fontwidth_0 = 0, $fp_0 = 0, $tobool13 = 0, $str = 0, $6 = 0, $tobool16 = 0, $7 = 0, $tobool182 = 0, $8 = 0, $p_03 = 0, $incdec_ptr = 0, $idxprom = 0, $arrayidx = 0, $9 = 0.0, $10 = 0.0, $add = 0.0, $11 = 0, $tobool18 = 0, $12 = 0.0, $13 = 0.0, $mul22 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $width = $para + 56 | 0;
+ HEAPF64[$width >> 3] = 0.0;
+ $fontsize = $para + 24 | 0;
+ $0 = +HEAPF64[$fontsize >> 3];
+ $mul = $0 * 1.2;
+ $height = $para + 64 | 0;
+ HEAPF64[$height >> 3] = $mul;
+ $yoffset_layout = $para + 40 | 0;
+ HEAPF64[$yoffset_layout >> 3] = 0.0;
+ $1 = +HEAPF64[$fontsize >> 3];
+ $mul2 = $1 * .1;
+ $yoffset_centerline = $para + 48 | 0;
+ HEAPF64[$yoffset_centerline >> 3] = $mul2;
+ $fontname = $para + 20 | 0;
+ $2 = HEAP32[$fontname >> 2] | 0;
+ $layout = $para + 8 | 0;
+ HEAP32[$layout >> 2] = $2;
+ $free_layout = $para + 12 | 0;
+ HEAP32[$free_layout >> 2] = 0;
+ $3 = HEAP32[$fontname >> 2] | 0;
+ $call = _strncasecmp($3, 124888, 4) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $fp_0 = 116832;
+ $Fontwidth_0 = 21216;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $4 = HEAP32[$fontname >> 2] | 0;
+ $call5 = _strncasecmp($4, 111688, 5) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ $fp_0 = 103496;
+ $Fontwidth_0 = 86264;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $5 = HEAP32[$fontname >> 2] | 0;
+ $call8 = _strncasecmp($5, 107368, 9) | 0;
+ $tobool9 = ($call8 | 0) == 0;
+ $_ = $tobool9 ? 86264 : 1112;
+ $_1 = $tobool9 ? 103496 : 99304;
+ $fp_0 = $_1;
+ $Fontwidth_0 = $_;
+ label = 5;
+ break;
+ case 5:
+ $tobool13 = ($fontpath | 0) == 0;
+ if ($tobool13) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ HEAP32[$fontpath >> 2] = $fp_0;
+ label = 7;
+ break;
+ case 7:
+ $str = $para | 0;
+ $6 = HEAP32[$str >> 2] | 0;
+ $tobool16 = ($6 | 0) == 0;
+ if ($tobool16) {
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $7 = HEAP8[$6] | 0;
+ $tobool182 = $7 << 24 >> 24 == 0;
+ if ($tobool182) {
+ label = 10;
+ break;
+ } else {
+ $p_03 = $6;
+ $8 = $7;
+ label = 9;
+ break;
+ }
+ case 9:
+ $incdec_ptr = $p_03 + 1 | 0;
+ $idxprom = $8 & 255;
+ $arrayidx = $Fontwidth_0 + ($idxprom << 3) | 0;
+ $9 = +HEAPF64[$arrayidx >> 3];
+ $10 = +HEAPF64[$width >> 3];
+ $add = $9 + $10;
+ HEAPF64[$width >> 3] = $add;
+ $11 = HEAP8[$incdec_ptr] | 0;
+ $tobool18 = $11 << 24 >> 24 == 0;
+ if ($tobool18) {
+ label = 10;
+ break;
+ } else {
+ $p_03 = $incdec_ptr;
+ $8 = $11;
+ label = 9;
+ break;
+ }
+ case 10:
+ $12 = +HEAPF64[$fontsize >> 3];
+ $13 = +HEAPF64[$width >> 3];
+ $mul22 = $12 * $13;
+ HEAPF64[$width >> 3] = $mul22;
+ label = 11;
+ break;
+ case 11:
+ return;
+ }
+}
+function _fontcmpf($a, $b) {
+ $a = $a | 0;
+ $b = $b | 0;
+ return _strcasecmp(HEAP32[$a >> 2] | 0, HEAP32[$b >> 2] | 0) | 0;
+}
+function _cwrotatepf($agg_result, $p, $cwrot) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $cwrot = $cwrot | 0;
+ var $x1 = 0, $0 = 0.0, $y2 = 0, $1 = 0.0, $cwrot_tr = 0, $sub = 0.0, $sub8 = 0.0, $cmp = 0, $sub13 = 0, $cmp14 = 0, $rem = 0, $2 = 0, $3 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x1 = $p | 0;
+ $0 = +HEAPF64[$x1 >> 3];
+ $y2 = $p + 8 | 0;
+ $1 = +HEAPF64[$y2 >> 3];
+ $cwrot_tr = $cwrot;
+ label = 3;
+ break;
+ case 3:
+ if (($cwrot_tr | 0) == 90) {
+ label = 4;
+ break;
+ } else if (($cwrot_tr | 0) == 180) {
+ label = 5;
+ break;
+ } else if (($cwrot_tr | 0) == 270) {
+ label = 6;
+ break;
+ } else if (($cwrot_tr | 0) == 0) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ HEAPF64[$x1 >> 3] = $1;
+ $sub = -0.0 - $0;
+ HEAPF64[$y2 >> 3] = $sub;
+ label = 12;
+ break;
+ case 5:
+ HEAPF64[$x1 >> 3] = $0;
+ $sub8 = -0.0 - $1;
+ HEAPF64[$y2 >> 3] = $sub8;
+ label = 12;
+ break;
+ case 6:
+ HEAPF64[$x1 >> 3] = $1;
+ HEAPF64[$y2 >> 3] = $0;
+ label = 12;
+ break;
+ case 7:
+ $cmp = ($cwrot_tr | 0) < 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $sub13 = -$cwrot_tr | 0;
+ _ccwrotatepf($agg_result, $p, $sub13);
+ label = 13;
+ break;
+ case 9:
+ $cmp14 = ($cwrot_tr | 0) > 360;
+ if ($cmp14) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $rem = ($cwrot_tr | 0) % 360;
+ $cwrot_tr = $rem;
+ label = 3;
+ break;
+ case 11:
+ _rotatepf($agg_result, $p, $cwrot_tr);
+ label = 13;
+ break;
+ case 12:
+ $2 = $agg_result;
+ $3 = $p;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ label = 13;
+ break;
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _ccwrotatepf($agg_result, $p, $ccwrot) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $ccwrot = $ccwrot | 0;
+ var $x1 = 0, $0 = 0.0, $y2 = 0, $1 = 0.0, $ccwrot_tr = 0, $sub = 0.0, $sub8 = 0.0, $cmp = 0, $sub13 = 0, $cmp14 = 0, $rem = 0, $sub17 = 0, $2 = 0, $3 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x1 = $p | 0;
+ $0 = +HEAPF64[$x1 >> 3];
+ $y2 = $p + 8 | 0;
+ $1 = +HEAPF64[$y2 >> 3];
+ $ccwrot_tr = $ccwrot;
+ label = 3;
+ break;
+ case 3:
+ if (($ccwrot_tr | 0) == 90) {
+ label = 4;
+ break;
+ } else if (($ccwrot_tr | 0) == 180) {
+ label = 5;
+ break;
+ } else if (($ccwrot_tr | 0) == 270) {
+ label = 6;
+ break;
+ } else if (($ccwrot_tr | 0) == 0) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $sub = -0.0 - $1;
+ HEAPF64[$x1 >> 3] = $sub;
+ HEAPF64[$y2 >> 3] = $0;
+ label = 12;
+ break;
+ case 5:
+ HEAPF64[$x1 >> 3] = $0;
+ $sub8 = -0.0 - $1;
+ HEAPF64[$y2 >> 3] = $sub8;
+ label = 12;
+ break;
+ case 6:
+ HEAPF64[$x1 >> 3] = $1;
+ HEAPF64[$y2 >> 3] = $0;
+ label = 12;
+ break;
+ case 7:
+ $cmp = ($ccwrot_tr | 0) < 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $sub13 = -$ccwrot_tr | 0;
+ _cwrotatepf($agg_result, $p, $sub13);
+ label = 13;
+ break;
+ case 9:
+ $cmp14 = ($ccwrot_tr | 0) > 360;
+ if ($cmp14) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $rem = ($ccwrot_tr | 0) % 360;
+ $ccwrot_tr = $rem;
+ label = 3;
+ break;
+ case 11:
+ $sub17 = 360 - $ccwrot_tr | 0;
+ _rotatepf($agg_result, $p, $sub17);
+ label = 13;
+ break;
+ case 12:
+ $2 = $agg_result;
+ $3 = $p;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ label = 13;
+ break;
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _rotatepf($agg_result, $p, $cwrot) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $cwrot = $cwrot | 0;
+ var $0 = 0, $cmp = 0, $conv = 0.0, $div = 0.0, $call = 0.0, $call3 = 0.0, $x = 0, $1 = 0.0, $2 = 0.0, $mul = 0.0, $y = 0, $3 = 0.0, $4 = 0.0, $mul4 = 0.0, $sub = 0.0, $mul7 = 0.0, $mul9 = 0.0, $add = 0.0, $P_sroa_0_0__idx = 0, $P_sroa_1_8__idx1 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[1084] | 0;
+ $cmp = ($0 | 0) == ($cwrot | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = +($cwrot | 0);
+ $div = $conv / 6.283185307179586;
+ $call = +Math_sin(+$div);
+ HEAPF64[541] = $call;
+ $call3 = +Math_cos(+$div);
+ HEAPF64[543] = $call3;
+ HEAP32[1084] = $cwrot;
+ label = 4;
+ break;
+ case 4:
+ $x = $p | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $2 = +HEAPF64[543];
+ $mul = $1 * $2;
+ $y = $p + 8 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $4 = +HEAPF64[541];
+ $mul4 = $3 * $4;
+ $sub = $mul - $mul4;
+ $mul7 = $2 * $3;
+ $mul9 = $1 * $4;
+ $add = $mul7 + $mul9;
+ $P_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$P_sroa_0_0__idx >> 3] = $sub;
+ $P_sroa_1_8__idx1 = $agg_result + 8 | 0;
+ HEAPF64[$P_sroa_1_8__idx1 >> 3] = $add;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _htmlerror($msg) {
+ $msg = $msg | 0;
+ var $0 = 0, $tobool = 0, $call = 0, $call1 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[4153] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP8[4153] = 1;
+ $call = _htmllineno() | 0;
+ $call1 = _agerr(1, 107816, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $msg, HEAP32[tempInt + 8 >> 2] = $call, tempInt) | 0) | 0;
+ _error_context();
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _htmllineno() {
+ return _XML_GetCurrentLineNumber(HEAP32[1030] | 0) | 0;
+}
+function _error_context() {
+ var $0 = 0, $buf = 0, $1 = 0, $ptr = 0, $2 = 0, $cmp = 0, $3 = 0, $4 = 0, $call = 0, $5 = 0, $6 = 0, $7 = 0, $call1 = 0, $8 = 0, $ptr2 = 0, $9 = 0, $eptr = 0, $10 = 0, $cmp3 = 0, $call4 = 0, $11 = 0, $ptr5 = 0, $12 = 0, $incdec_ptr = 0, $13 = 0, $buf6 = 0, $14 = 0, $ptr7 = 0, $call8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[1033] | 0;
+ $buf = $0 | 0;
+ $1 = HEAP32[$buf >> 2] | 0;
+ $ptr = $0 + 4 | 0;
+ HEAP32[$ptr >> 2] = $1;
+ $2 = HEAP32[1042] | 0;
+ $cmp = ($2 | 0) > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $3 = HEAP32[1033] | 0;
+ $4 = HEAP32[1040] | 0;
+ $call = _agxbput_n($3, $4, $2) | 0;
+ label = 4;
+ break;
+ case 4:
+ $5 = HEAP32[1033] | 0;
+ $6 = HEAP32[1039] | 0;
+ $7 = HEAP32[1041] | 0;
+ $call1 = _agxbput_n($5, $6, $7) | 0;
+ $8 = HEAP32[1033] | 0;
+ $ptr2 = $8 + 4 | 0;
+ $9 = HEAP32[$ptr2 >> 2] | 0;
+ $eptr = $8 + 8 | 0;
+ $10 = HEAP32[$eptr >> 2] | 0;
+ $cmp3 = $9 >>> 0 < $10 >>> 0;
+ if ($cmp3) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call4 = _agxbmore($8, 1) | 0;
+ label = 6;
+ break;
+ case 6:
+ $11 = HEAP32[1033] | 0;
+ $ptr5 = $11 + 4 | 0;
+ $12 = HEAP32[$ptr5 >> 2] | 0;
+ $incdec_ptr = $12 + 1 | 0;
+ HEAP32[$ptr5 >> 2] = $incdec_ptr;
+ HEAP8[$12] = 0;
+ $13 = HEAP32[1033] | 0;
+ $buf6 = $13 | 0;
+ $14 = HEAP32[$buf6 >> 2] | 0;
+ $ptr7 = $13 + 4 | 0;
+ HEAP32[$ptr7 >> 2] = $14;
+ $call8 = _agerr(3, 95928, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $14, tempInt) | 0) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _initHTMLlexer($src, $xb, $charset) {
+ $src = $src | 0;
+ $xb = $xb | 0;
+ $charset = $charset | 0;
+ var $call1 = 0;
+ HEAP32[1033] = $xb;
+ _agxbinit(4136, 128, 0);
+ HEAP32[1031] = $src;
+ HEAP8[4155] = 0;
+ HEAP8[4152] = 0;
+ HEAP8[4153] = 0;
+ HEAP32[1041] = 0;
+ HEAP32[1042] = 0;
+ HEAP8[4154] = 1;
+ $call1 = _XML_ParserCreate(_charsetToStr($charset) | 0) | 0;
+ HEAP32[1030] = $call1;
+ _XML_SetElementHandler($call1, 598, 384);
+ _XML_SetCharacterDataHandler(HEAP32[1030] | 0, 234);
+ return 0;
+}
+function _startElement($user, $name, $atts) {
+ $user = $user | 0;
+ $name = $name | 0;
+ $atts = $atts | 0;
+ var $call = 0, $cmp = 0, $call1 = 0, $call1_c = 0, $call2 = 0, $cmp3 = 0, $call4 = 0, $cmp5 = 0, $call8 = 0, $cmp9 = 0, $call11 = 0, $call11_c = 0, $call13 = 0, $cmp14 = 0, $call16 = 0, $call16_c = 0, $call18 = 0, $cmp19 = 0, $call21 = 0, $call21_c = 0, $call23 = 0, $cmp24 = 0, $call26 = 0, $call26_c = 0, $call28 = 0, $cmp29 = 0, $call31 = 0, $call31_c = 0, $call33 = 0, $cmp34 = 0, $call36 = 0, $call36_c = 0, $call38 = 0, $cmp39 = 0, $call41 = 0, $call41_c = 0, $call43 = 0, $cmp44 = 0, $call47 = 0, $cmp48 = 0, $call50 = 0, $call50_c = 0, $call52 = 0, $cmp53 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _strcasecmp($name, 102816) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call1 = _mkTbl($atts) | 0;
+ $call1_c = $call1;
+ HEAP32[3420] = $call1_c;
+ HEAP8[4154] = 0;
+ HEAP32[1032] = 278;
+ label = 28;
+ break;
+ case 4:
+ $call2 = _strcasecmp($name, 98552) | 0;
+ $cmp3 = ($call2 | 0) == 0;
+ if ($cmp3) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call4 = _strcasecmp($name, 94704) | 0;
+ $cmp5 = ($call4 | 0) == 0;
+ if ($cmp5) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ HEAP8[4154] = 0;
+ HEAP32[1032] = 260;
+ label = 28;
+ break;
+ case 7:
+ $call8 = _strcasecmp($name, 91176) | 0;
+ $cmp9 = ($call8 | 0) == 0;
+ if ($cmp9) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ HEAP8[4154] = 1;
+ $call11 = _mkCell($atts) | 0;
+ $call11_c = $call11;
+ HEAP32[3420] = $call11_c;
+ HEAP32[1032] = 279;
+ label = 28;
+ break;
+ case 9:
+ $call13 = _strcasecmp($name, 157688) | 0;
+ $cmp14 = ($call13 | 0) == 0;
+ if ($cmp14) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $call16 = _mkFont($atts, 0) | 0;
+ $call16_c = $call16;
+ HEAP32[3420] = $call16_c;
+ HEAP32[1032] = 280;
+ label = 28;
+ break;
+ case 11:
+ $call18 = _strcasecmp($name, 154368) | 0;
+ $cmp19 = ($call18 | 0) == 0;
+ if ($cmp19) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $call21 = _mkFont(0, 1) | 0;
+ $call21_c = $call21;
+ HEAP32[3420] = $call21_c;
+ HEAP32[1032] = 282;
+ label = 28;
+ break;
+ case 13:
+ $call23 = _strcasecmp($name, 150744) | 0;
+ $cmp24 = ($call23 | 0) == 0;
+ if ($cmp24) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $call26 = _mkFont(0, 4) | 0;
+ $call26_c = $call26;
+ HEAP32[3420] = $call26_c;
+ HEAP32[1032] = 283;
+ label = 28;
+ break;
+ case 15:
+ $call28 = _strcasecmp($name, 147752) | 0;
+ $cmp29 = ($call28 | 0) == 0;
+ if ($cmp29) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $call31 = _mkFont(0, 2) | 0;
+ $call31_c = $call31;
+ HEAP32[3420] = $call31_c;
+ HEAP32[1032] = 281;
+ label = 28;
+ break;
+ case 17:
+ $call33 = _strcasecmp($name, 144984) | 0;
+ $cmp34 = ($call33 | 0) == 0;
+ if ($cmp34) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $call36 = _mkFont(0, 8) | 0;
+ $call36_c = $call36;
+ HEAP32[3420] = $call36_c;
+ HEAP32[1032] = 284;
+ label = 28;
+ break;
+ case 19:
+ $call38 = _strcasecmp($name, 141928) | 0;
+ $cmp39 = ($call38 | 0) == 0;
+ if ($cmp39) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $call41 = _mkFont(0, 16) | 0;
+ $call41_c = $call41;
+ HEAP32[3420] = $call41_c;
+ HEAP32[1032] = 285;
+ label = 28;
+ break;
+ case 21:
+ $call43 = _strcasecmp($name, 138440) | 0;
+ $cmp44 = ($call43 | 0) == 0;
+ if ($cmp44) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ _mkBR($atts);
+ HEAP32[1032] = 275;
+ label = 28;
+ break;
+ case 23:
+ $call47 = _strcasecmp($name, 135696) | 0;
+ $cmp48 = ($call47 | 0) == 0;
+ if ($cmp48) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $call50 = _mkImg($atts) | 0;
+ $call50_c = $call50;
+ HEAP32[3420] = $call50_c;
+ HEAP32[1032] = 277;
+ label = 28;
+ break;
+ case 25:
+ $call52 = _strcasecmp($name, 161368) | 0;
+ $cmp53 = ($call52 | 0) == 0;
+ if ($cmp53) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ HEAP32[1032] = 262;
+ label = 28;
+ break;
+ case 27:
+ _lexerror($name);
+ label = 28;
+ break;
+ case 28:
+ return;
+ }
+}
+function _gmalloc($nbytes) {
+ $nbytes = $nbytes | 0;
+ var $cmp = 0, $call = 0, $cmp1 = 0, $0 = 0, $1 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($nbytes | 0) == 0;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _malloc($nbytes) | 0;
+ $cmp1 = ($call | 0) == 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = $call;
+ label = 5;
+ break;
+ }
+ case 4:
+ $0 = HEAP32[_stderr >> 2] | 0;
+ $1 = _fwrite(117e3, 14, 1, $0 | 0) | 0;
+ _abort();
+ return 0;
+ return 0;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _zrealloc($ptr, $size, $elt, $osize) {
+ $ptr = $ptr | 0;
+ $size = $size | 0;
+ $elt = $elt | 0;
+ $osize = $osize | 0;
+ var $mul = 0, $call = 0, $cmp = 0, $tobool = 0, $or_cond = 0, $0 = 0, $1 = 0, $cmp2 = 0, $mul4 = 0, $add_ptr = 0, $sub = 0, $mul5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $mul = Math_imul($elt, $size);
+ $call = _realloc($ptr, $mul) | 0;
+ $cmp = ($call | 0) != 0;
+ $tobool = ($size | 0) == 0;
+ $or_cond = $cmp | $tobool;
+ if ($or_cond) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[_stderr >> 2] | 0;
+ $1 = _fwrite(117e3, 14, 1, $0 | 0) | 0;
+ _abort();
+ return 0;
+ return 0;
+ case 4:
+ $cmp2 = $osize >>> 0 < $size >>> 0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $mul4 = Math_imul($osize, $elt);
+ $add_ptr = $call + $mul4 | 0;
+ $sub = $size - $osize | 0;
+ $mul5 = Math_imul($sub, $elt);
+ _memset($add_ptr | 0, 0, $mul5 | 0);
+ label = 6;
+ break;
+ case 6:
+ return $call | 0;
+ }
+ return 0;
+}
+function _grealloc($ptr, $size) {
+ $ptr = $ptr | 0;
+ $size = $size | 0;
+ var $call = 0, $cmp = 0, $tobool = 0, $or_cond = 0, $0 = 0, $1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _realloc($ptr, $size) | 0;
+ $cmp = ($call | 0) != 0;
+ $tobool = ($size | 0) == 0;
+ $or_cond = $cmp | $tobool;
+ if ($or_cond) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[_stderr >> 2] | 0;
+ $1 = _fwrite(117e3, 14, 1, $0 | 0) | 0;
+ _abort();
+ return 0;
+ return 0;
+ case 4:
+ return $call | 0;
+ }
+ return 0;
+}
+function _endElement($user, $name) {
+ $user = $user | 0;
+ $name = $name | 0;
+ var $call = 0, $cmp = 0, $call1 = 0, $cmp2 = 0, $call3 = 0, $cmp4 = 0, $call7 = 0, $cmp8 = 0, $call11 = 0, $cmp12 = 0, $call15 = 0, $cmp16 = 0, $call19 = 0, $cmp20 = 0, $call23 = 0, $cmp24 = 0, $call27 = 0, $cmp28 = 0, $call31 = 0, $cmp32 = 0, $call35 = 0, $cmp36 = 0, $call39 = 0, $cmp40 = 0, $0 = 0, $cmp42 = 0, $call46 = 0, $cmp47 = 0, $1 = 0, $cmp49 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _strcasecmp($name, 102816) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[1032] = 264;
+ HEAP8[4154] = 1;
+ label = 32;
+ break;
+ case 4:
+ $call1 = _strcasecmp($name, 98552) | 0;
+ $cmp2 = ($call1 | 0) == 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call3 = _strcasecmp($name, 94704) | 0;
+ $cmp4 = ($call3 | 0) == 0;
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ HEAP32[1032] = 261;
+ label = 32;
+ break;
+ case 7:
+ $call7 = _strcasecmp($name, 91176) | 0;
+ $cmp8 = ($call7 | 0) == 0;
+ if ($cmp8) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ HEAP32[1032] = 265;
+ HEAP8[4154] = 0;
+ label = 32;
+ break;
+ case 9:
+ $call11 = _strcasecmp($name, 161368) | 0;
+ $cmp12 = ($call11 | 0) == 0;
+ if ($cmp12) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[1032] = 263;
+ label = 32;
+ break;
+ case 11:
+ $call15 = _strcasecmp($name, 157688) | 0;
+ $cmp16 = ($call15 | 0) == 0;
+ if ($cmp16) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ HEAP32[1032] = 266;
+ label = 32;
+ break;
+ case 13:
+ $call19 = _strcasecmp($name, 154368) | 0;
+ $cmp20 = ($call19 | 0) == 0;
+ if ($cmp20) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[1032] = 270;
+ label = 32;
+ break;
+ case 15:
+ $call23 = _strcasecmp($name, 150744) | 0;
+ $cmp24 = ($call23 | 0) == 0;
+ if ($cmp24) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ HEAP32[1032] = 271;
+ label = 32;
+ break;
+ case 17:
+ $call27 = _strcasecmp($name, 147752) | 0;
+ $cmp28 = ($call27 | 0) == 0;
+ if ($cmp28) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP32[1032] = 269;
+ label = 32;
+ break;
+ case 19:
+ $call31 = _strcasecmp($name, 144984) | 0;
+ $cmp32 = ($call31 | 0) == 0;
+ if ($cmp32) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ HEAP32[1032] = 272;
+ label = 32;
+ break;
+ case 21:
+ $call35 = _strcasecmp($name, 141928) | 0;
+ $cmp36 = ($call35 | 0) == 0;
+ if ($cmp36) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ HEAP32[1032] = 273;
+ label = 32;
+ break;
+ case 23:
+ $call39 = _strcasecmp($name, 138440) | 0;
+ $cmp40 = ($call39 | 0) == 0;
+ if ($cmp40) {
+ label = 24;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 24:
+ $0 = HEAP32[1032] | 0;
+ $cmp42 = ($0 | 0) == 275;
+ if ($cmp42) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ HEAP32[1032] = 274;
+ label = 32;
+ break;
+ case 26:
+ HEAP32[1032] = 258;
+ label = 32;
+ break;
+ case 27:
+ $call46 = _strcasecmp($name, 135696) | 0;
+ $cmp47 = ($call46 | 0) == 0;
+ if ($cmp47) {
+ label = 28;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 28:
+ $1 = HEAP32[1032] | 0;
+ $cmp49 = ($1 | 0) == 277;
+ if ($cmp49) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ HEAP32[1032] = 276;
+ label = 32;
+ break;
+ case 30:
+ HEAP32[1032] = 259;
+ label = 32;
+ break;
+ case 31:
+ _lexerror($name);
+ label = 32;
+ break;
+ case 32:
+ return;
+ }
+}
+function _characterData($user, $s, $length) {
+ $user = $user | 0;
+ $s = $s | 0;
+ $length = $length | 0;
+ var $0 = 0, $tobool = 0, $tobool14 = 0, $or_cond = 0, $s_addr_07 = 0, $cnt_06 = 0, $i_05 = 0, $incdec_ptr = 0, $1 = 0, $cmp = 0, $inc = 0, $2 = 0, $ptr = 0, $3 = 0, $eptr = 0, $4 = 0, $cmp4 = 0, $call = 0, $5 = 0, $ptr6 = 0, $6 = 0, $incdec_ptr7 = 0, $cnt_1 = 0, $dec = 0, $tobool1 = 0, $tobool9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[4154] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ $tobool14 = ($length | 0) == 0;
+ $or_cond = $tobool | $tobool14;
+ if ($or_cond) {
+ label = 10;
+ break;
+ } else {
+ $i_05 = $length;
+ $cnt_06 = 0;
+ $s_addr_07 = $s;
+ label = 3;
+ break;
+ }
+ case 3:
+ $incdec_ptr = $s_addr_07 + 1 | 0;
+ $1 = HEAP8[$s_addr_07] | 0;
+ $cmp = ($1 & 255) > 31;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $cnt_1 = $cnt_06;
+ label = 7;
+ break;
+ }
+ case 4:
+ $inc = $cnt_06 + 1 | 0;
+ $2 = HEAP32[1033] | 0;
+ $ptr = $2 + 4 | 0;
+ $3 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $2 + 8 | 0;
+ $4 = HEAP32[$eptr >> 2] | 0;
+ $cmp4 = $3 >>> 0 < $4 >>> 0;
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call = _agxbmore($2, 1) | 0;
+ label = 6;
+ break;
+ case 6:
+ $5 = HEAP32[1033] | 0;
+ $ptr6 = $5 + 4 | 0;
+ $6 = HEAP32[$ptr6 >> 2] | 0;
+ $incdec_ptr7 = $6 + 1 | 0;
+ HEAP32[$ptr6 >> 2] = $incdec_ptr7;
+ HEAP8[$6] = $1;
+ $cnt_1 = $inc;
+ label = 7;
+ break;
+ case 7:
+ $dec = $i_05 - 1 | 0;
+ $tobool1 = ($dec | 0) == 0;
+ if ($tobool1) {
+ label = 8;
+ break;
+ } else {
+ $i_05 = $dec;
+ $cnt_06 = $cnt_1;
+ $s_addr_07 = $incdec_ptr;
+ label = 3;
+ break;
+ }
+ case 8:
+ $tobool9 = ($cnt_1 | 0) == 0;
+ if ($tobool9) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ HEAP32[1032] = 267;
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _clearHTMLlexer() {
+ var $or = 0;
+ $or = (HEAP8[4153] | HEAP8[4152]) << 24 >> 24;
+ _XML_ParserFree(HEAP32[1030] | 0);
+ _agxbfree(4136);
+ return $or | 0;
+}
+function _htmllex() {
+ var $endp_0 = 0, $0 = 0, $1 = 0, $2 = 0, $cmp7 = 0, $call12 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $s_0 = 0, $endp_1 = 0, $len_0 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $sub_ptr_lhs_cast15 = 0, $sub_ptr_rhs_cast16 = 0, $sub_ptr_sub17 = 0, $tobool = 0, $7 = 0, $8 = 0, $cmp19 = 0, $call21 = 0, $9 = 0, $10 = 0, $call22 = 0, $not_tobool24 = 0, $cond25 = 0, $call26 = 0, $rv_0 = 0, $cmp28 = 0, $11 = 0, $tobool31 = 0, $or_cond = 0, $12 = 0, $call33 = 0, $call34 = 0, $call35 = 0, $call36 = 0, $tobool39 = 0, $13 = 0, $cmp42 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[1032] = 0;
+ $endp_0 = 0;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[4155] | 0;
+ if (($0 << 24 >> 24 | 0) == 0) {
+ label = 4;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 2) {
+ $retval_0 = -1;
+ label = 18;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP8[4155] = 1;
+ $len_0 = 6;
+ $endp_1 = 0;
+ $s_0 = 145800;
+ label = 8;
+ break;
+ case 5:
+ $1 = HEAP32[1031] | 0;
+ $2 = HEAP8[$1] | 0;
+ $cmp7 = $2 << 24 >> 24 == 0;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ HEAP8[4155] = 2;
+ $len_0 = 7;
+ $endp_1 = $endp_0;
+ $s_0 = 121800;
+ label = 8;
+ break;
+ case 7:
+ $call12 = _findNext($1) | 0;
+ $sub_ptr_lhs_cast = $call12;
+ $sub_ptr_rhs_cast = $1;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $len_0 = $sub_ptr_sub;
+ $endp_1 = $call12;
+ $s_0 = $1;
+ label = 8;
+ break;
+ case 8:
+ $3 = HEAP32[1039] | 0;
+ HEAP32[1040] = $3;
+ $4 = HEAP32[1041] | 0;
+ HEAP32[1042] = $4;
+ HEAP32[1039] = $s_0;
+ HEAP32[1041] = $len_0;
+ $5 = HEAP32[1035] | 0;
+ $6 = HEAP32[1034] | 0;
+ $sub_ptr_lhs_cast15 = $5;
+ $sub_ptr_rhs_cast16 = $6;
+ $sub_ptr_sub17 = $sub_ptr_lhs_cast15 - $sub_ptr_rhs_cast16 | 0;
+ $tobool = ($5 | 0) == ($6 | 0);
+ $7 = HEAP32[1030] | 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $8 = HEAP32[1036] | 0;
+ $cmp19 = $5 >>> 0 < $8 >>> 0;
+ if ($cmp19) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call21 = _agxbmore(4136, 1) | 0;
+ label = 11;
+ break;
+ case 11:
+ $9 = HEAP32[1035] | 0;
+ HEAP8[$9] = 0;
+ $10 = HEAP32[1034] | 0;
+ HEAP32[1035] = $10;
+ $call22 = _XML_Parse($7, $10, $sub_ptr_sub17, 0) | 0;
+ $rv_0 = $call22;
+ label = 13;
+ break;
+ case 12:
+ $not_tobool24 = ($len_0 | 0) == 0;
+ $cond25 = $not_tobool24 & 1;
+ $call26 = _XML_Parse($7, $s_0, $len_0, $cond25) | 0;
+ $rv_0 = $call26;
+ label = 13;
+ break;
+ case 13:
+ $cmp28 = ($rv_0 | 0) != 0;
+ $11 = HEAP8[4153] | 0;
+ $tobool31 = $11 << 24 >> 24 != 0;
+ $or_cond = $cmp28 | $tobool31;
+ if ($or_cond) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $12 = HEAP32[1030] | 0;
+ $call33 = _XML_GetErrorCode($12) | 0;
+ $call34 = _XML_ErrorString($call33) | 0;
+ $call35 = _htmllineno() | 0;
+ $call36 = _agerr(1, 107816, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $call34, HEAP32[tempInt + 8 >> 2] = $call35, tempInt) | 0) | 0;
+ _error_context();
+ HEAP8[4153] = 1;
+ HEAP32[1032] = 268;
+ label = 15;
+ break;
+ case 15:
+ $tobool39 = ($endp_1 | 0) == 0;
+ if ($tobool39) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[1031] = $endp_1;
+ label = 17;
+ break;
+ case 17:
+ $13 = HEAP32[1032] | 0;
+ $cmp42 = ($13 | 0) == 0;
+ if ($cmp42) {
+ $endp_0 = $endp_1;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = $13;
+ label = 18;
+ break;
+ }
+ case 18:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _findNext($s) {
+ $s = $s | 0;
+ var $add_ptr = 0, $0 = 0, $cmp = 0, $1 = 0, $cmp3 = 0, $add_ptr5 = 0, $call = 0, $tobool = 0, $add_ptr7 = 0, $call8 = 0, $t_0 = 0, $2 = 0, $incdec_ptr = 0, $t_1 = 0, $3 = 0, $cmp15 = 0, $call18 = 0, $incdec_ptr20 = 0, $t_2 = 0, $4 = 0, $add_ptr36 = 0, $5 = 0, $cmp38 = 0, $call42 = 0, $6 = 0, $7 = 0, $cmp44 = 0, $call46 = 0, $8 = 0, $incdec_ptr48 = 0, $incdec_ptr50 = 0, $t_3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add_ptr = $s + 1 | 0;
+ $0 = HEAP8[$s] | 0;
+ $cmp = $0 << 24 >> 24 == 60;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $t_2 = $s;
+ label = 11;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$add_ptr] | 0;
+ $cmp3 = $1 << 24 >> 24 == 33;
+ if ($cmp3) {
+ label = 4;
+ break;
+ } else {
+ $t_0 = $add_ptr;
+ label = 6;
+ break;
+ }
+ case 4:
+ $add_ptr5 = $s + 2 | 0;
+ $call = _strncmp($add_ptr5 | 0, 115928, 2) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $t_0 = $add_ptr;
+ label = 6;
+ break;
+ }
+ case 5:
+ $add_ptr7 = $s + 4 | 0;
+ $call8 = _eatComment($add_ptr7) | 0;
+ $t_1 = $call8;
+ label = 8;
+ break;
+ case 6:
+ $2 = HEAP8[$t_0] | 0;
+ if (($2 << 24 >> 24 | 0) == 0 | ($2 << 24 >> 24 | 0) == 62) {
+ $t_1 = $t_0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $incdec_ptr = $t_0 + 1 | 0;
+ $t_0 = $incdec_ptr;
+ label = 6;
+ break;
+ case 8:
+ $3 = HEAP8[$t_1] | 0;
+ $cmp15 = $3 << 24 >> 24 == 62;
+ if ($cmp15) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call18 = _agerr(0, 110904, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ HEAP8[4152] = 1;
+ $t_3 = $t_1;
+ label = 17;
+ break;
+ case 10:
+ $incdec_ptr20 = $t_1 + 1 | 0;
+ $t_3 = $incdec_ptr20;
+ label = 17;
+ break;
+ case 11:
+ $4 = HEAP8[$t_2] | 0;
+ if (($4 << 24 >> 24 | 0) == 38) {
+ label = 12;
+ break;
+ } else if (($4 << 24 >> 24 | 0) == 0 | ($4 << 24 >> 24 | 0) == 60) {
+ $t_3 = $t_2;
+ label = 17;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ $add_ptr36 = $t_2 + 1 | 0;
+ $5 = HEAP8[$add_ptr36] | 0;
+ $cmp38 = $5 << 24 >> 24 == 35;
+ if ($cmp38) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $call42 = _scanEntity($add_ptr36, 4136) | 0;
+ $t_2 = $call42;
+ label = 11;
+ break;
+ case 14:
+ $6 = HEAP32[1035] | 0;
+ $7 = HEAP32[1036] | 0;
+ $cmp44 = $6 >>> 0 < $7 >>> 0;
+ if ($cmp44) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $call46 = _agxbmore(4136, 1) | 0;
+ label = 16;
+ break;
+ case 16:
+ $8 = HEAP32[1035] | 0;
+ $incdec_ptr48 = $8 + 1 | 0;
+ HEAP32[1035] = $incdec_ptr48;
+ HEAP8[$8] = $4;
+ $incdec_ptr50 = $t_2 + 1 | 0;
+ $t_2 = $incdec_ptr50;
+ label = 11;
+ break;
+ case 17:
+ STACKTOP = __stackBase__;
+ return $t_3 | 0;
+ }
+ return 0;
+}
+function _eatComment($p) {
+ $p = $p | 0;
+ var $s_0_ph = 0, $depth_0_ph = 0, $tobool = 0, $s_0 = 0, $incdec_ptr = 0, $0 = 0, $inc = 0, $dec = 0, $s_1 = 0, $incdec_ptr9 = 0, $1 = 0, $tobool10 = 0, $add_ptr = 0, $cmp12 = 0, $call = 0, $tobool14 = 0, $call16 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $depth_0_ph = 1;
+ $s_0_ph = $p;
+ label = 3;
+ break;
+ case 3:
+ $tobool = ($depth_0_ph | 0) == 0;
+ $s_0 = $s_0_ph;
+ label = 4;
+ break;
+ case 4:
+ if ($tobool) {
+ $s_1 = $s_0;
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $incdec_ptr = $s_0 + 1 | 0;
+ $0 = HEAP8[$s_0] | 0;
+ if (($0 << 24 >> 24 | 0) == 60) {
+ label = 6;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 62) {
+ label = 7;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 0) {
+ $s_1 = $incdec_ptr;
+ label = 8;
+ break;
+ } else {
+ $s_0 = $incdec_ptr;
+ label = 4;
+ break;
+ }
+ case 6:
+ $inc = $depth_0_ph + 1 | 0;
+ $depth_0_ph = $inc;
+ $s_0_ph = $incdec_ptr;
+ label = 3;
+ break;
+ case 7:
+ $dec = $depth_0_ph - 1 | 0;
+ $depth_0_ph = $dec;
+ $s_0_ph = $incdec_ptr;
+ label = 3;
+ break;
+ case 8:
+ $incdec_ptr9 = $s_1 - 1 | 0;
+ $1 = HEAP8[$incdec_ptr9] | 0;
+ $tobool10 = $1 << 24 >> 24 == 0;
+ if ($tobool10) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add_ptr = $s_1 - 3 | 0;
+ $cmp12 = $add_ptr >>> 0 < $p >>> 0;
+ if ($cmp12) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call = _strncmp($add_ptr | 0, 115928, 2) | 0;
+ $tobool14 = ($call | 0) == 0;
+ if ($tobool14) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call16 = _agerr(0, 106736, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ HEAP8[4152] = 1;
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return $incdec_ptr9 | 0;
+ }
+ return 0;
+}
+function _lexerror($name) {
+ $name = $name | 0;
+ var $call = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ HEAP32[1032] = 268;
+ HEAP8[4153] = 1;
+ $call = _htmllineno() | 0;
+ _agerr(1, 133232, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $name, HEAP32[tempInt + 8 >> 2] = $call, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _mkTbl($atts) {
+ $atts = $atts | 0;
+ var $call = 0;
+ $call = _zmalloc(112) | 0;
+ HEAP32[$call + 92 >> 2] = -1;
+ HEAP8[$call + 80 | 0] = -1;
+ _doAttrs($call, 3160, 18, $atts, 98456);
+ return $call | 0;
+}
+function _mkCell($atts) {
+ $atts = $atts | 0;
+ var $call = 0;
+ $call = _zmalloc(96) | 0;
+ HEAP16[$call + 72 >> 1] = 1;
+ HEAP16[$call + 74 >> 1] = 1;
+ _doAttrs($call, 53208, 19, $atts, 114152);
+ return $call | 0;
+}
+function _mkFont($atts, $flags) {
+ $atts = $atts | 0;
+ $flags = $flags | 0;
+ var $call = 0, $0 = 0, $size = 0, $1 = 0, $bf_value = 0, $bf_field_offs = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(24) | 0;
+ $0 = $call;
+ $size = $call + 16 | 0;
+ $1 = $size;
+ HEAPF64[$1 >> 3] = -1.0;
+ $bf_value = $flags & 127;
+ $bf_field_offs = $call + 8 | 0;
+ $2 = $bf_field_offs;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $4 = $3 & -128;
+ $5 = $4 | $bf_value;
+ HEAP32[$2 >> 2] = $5;
+ $tobool = ($atts | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _doAttrs($call, 16416, 3, $atts, 118616);
+ label = 4;
+ break;
+ case 4:
+ return $0 | 0;
+ }
+ return 0;
+}
+function _mkBR($atts) {
+ $atts = $atts | 0;
+ HEAP32[3420] = 0;
+ _doAttrs(13680, 53416, 1, $atts, 122712);
+ return;
+}
+function _mkImg($atts) {
+ $atts = $atts | 0;
+ var $call = 0;
+ $call = _zmalloc(40) | 0;
+ _doAttrs($call, 12824, 2, $atts, 131256);
+ return $call | 0;
+}
+function _doAttrs($tp, $items, $nel, $atts, $s) {
+ $tp = $tp | 0;
+ $items = $items | 0;
+ $nel = $nel | 0;
+ $atts = $atts | 0;
+ $s = $s | 0;
+ var $key = 0, $0 = 0, $cmp6 = 0, $name2 = 0, $1 = 0, $2 = 0, $3 = 0, $atts_addr_07 = 0, $incdec_ptr = 0, $incdec_ptr1 = 0, $4 = 0, $call = 0, $tobool = 0, $action = 0, $5 = 0, $6 = 0, $call3 = 0, $7 = 0, $conv5 = 0, $or = 0, $conv4 = 0, $call5 = 0, $storemerge = 0, $8 = 0, $cmp = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $key = __stackBase__ | 0;
+ $0 = HEAP32[$atts >> 2] | 0;
+ $cmp6 = ($0 | 0) == 0;
+ if ($cmp6) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $name2 = $key | 0;
+ $1 = $key;
+ $2 = $items;
+ $atts_addr_07 = $atts;
+ $3 = $0;
+ label = 4;
+ break;
+ case 4:
+ $incdec_ptr = $atts_addr_07 + 4 | 0;
+ $incdec_ptr1 = $atts_addr_07 + 8 | 0;
+ $4 = HEAP32[$incdec_ptr >> 2] | 0;
+ HEAP32[$name2 >> 2] = $3;
+ $call = _bsearch($1 | 0, $2 | 0, $nel | 0, 8, 4) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $action = $call + 4 | 0;
+ $5 = $action;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $call3 = FUNCTION_TABLE_iii[$6 & 1023]($tp, $4) | 0;
+ $7 = HEAP8[4152] | 0;
+ $conv5 = $7 & 255;
+ $or = $conv5 | $call3;
+ $conv4 = $or & 255;
+ $storemerge = $conv4;
+ label = 7;
+ break;
+ case 6:
+ $call5 = _agerr(0, 124648, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $3, HEAP32[tempInt + 8 >> 2] = $s, tempInt) | 0) | 0;
+ $storemerge = 1;
+ label = 7;
+ break;
+ case 7:
+ HEAP8[4152] = $storemerge;
+ $8 = HEAP32[$incdec_ptr1 >> 2] | 0;
+ $cmp = ($8 | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ $atts_addr_07 = $incdec_ptr1;
+ $3 = $8;
+ label = 4;
+ break;
+ }
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _scalefn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 36 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _srcfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 32 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _icmp($i, $j) {
+ $i = $i | 0;
+ $j = $j | 0;
+ return _strcasecmp(HEAP32[$i >> 2] | 0, HEAP32[$j >> 2] | 0) | 0;
+}
+function _alignfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $0 = 0, $conv = 0, $call = 0, $sext = 0, $conv2 = 0, $add_ptr = 0, $call4 = 0, $tobool = 0, $add_ptr8 = 0, $call9 = 0, $tobool10 = 0, $cmp14 = 0, $call18 = 0, $tobool19 = 0, $call22 = 0, $rv_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$v] | 0;
+ $conv = $0 << 24 >> 24;
+ $call = _toupper($conv | 0) | 0;
+ $sext = $call << 24;
+ $conv2 = $sext >> 24;
+ if (($conv2 | 0) == 82) {
+ label = 3;
+ break;
+ } else if (($conv2 | 0) == 76) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $add_ptr = $v + 1 | 0;
+ $call4 = _strcasecmp($add_ptr, 121e3) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP32[$p >> 2] = 114;
+ $rv_0 = 0;
+ label = 11;
+ break;
+ case 5:
+ $add_ptr8 = $v + 1 | 0;
+ $call9 = _strcasecmp($add_ptr8, 120248) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ HEAP32[$p >> 2] = 108;
+ $rv_0 = 0;
+ label = 11;
+ break;
+ case 7:
+ $cmp14 = ($conv2 | 0) == 67;
+ if ($cmp14) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call18 = _strcasecmp($add_ptr8, 119648) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ HEAP32[$p >> 2] = 110;
+ $rv_0 = 0;
+ label = 11;
+ break;
+ case 10:
+ $call22 = _agerr(0, 119080, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $v, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _fontcolorfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 4 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _facefn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _ptsizefn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $conv = 0.0, $size = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 116296, 0, 255, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $conv = +($0 | 0);
+ $size = $p + 16 | 0;
+ HEAPF64[$size >> 3] = $conv;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doInt($v, $s, $min, $max, $ul) {
+ $v = $v | 0;
+ $s = $s | 0;
+ $min = $min | 0;
+ $max = $max | 0;
+ $ul = $ul | 0;
+ var $ep = 0, $call = 0, $0 = 0, $cmp = 0, $call1 = 0, $cmp2 = 0, $call4 = 0, $cmp6 = 0, $call8 = 0, $rv_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ep = __stackBase__ | 0;
+ $call = _strtol($v | 0, $ep | 0, 10) | 0;
+ $0 = HEAP32[$ep >> 2] | 0;
+ $cmp = ($0 | 0) == ($v | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call1 = _agerr(0, 115776, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $s, HEAP32[tempInt + 8 >> 2] = $v, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ label = 9;
+ break;
+ case 4:
+ $cmp2 = ($call | 0) > ($max | 0);
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call4 = _agerr(0, 115304, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $s, HEAP32[tempInt + 8 >> 2] = $v, HEAP32[tempInt + 16 >> 2] = $max, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ label = 9;
+ break;
+ case 6:
+ $cmp6 = ($call | 0) < ($min | 0);
+ if ($cmp6) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call8 = _agerr(0, 114752, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $s, HEAP32[tempInt + 8 >> 2] = $v, HEAP32[tempInt + 16 >> 2] = $min, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ label = 9;
+ break;
+ case 8:
+ HEAP32[$ul >> 2] = $call;
+ $rv_0 = 0;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _cell_halignfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $0 = 0, $conv = 0, $call = 0, $sext = 0, $conv2 = 0, $add_ptr = 0, $call4 = 0, $tobool = 0, $flags = 0, $1 = 0, $or = 0, $add_ptr11 = 0, $call12 = 0, $tobool13 = 0, $flags15 = 0, $2 = 0, $or17 = 0, $add_ptr24 = 0, $call25 = 0, $tobool26 = 0, $flags28 = 0, $3 = 0, $or30 = 0, $add_ptr36 = 0, $call37 = 0, $tobool38 = 0, $call45 = 0, $rv_013 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$v] | 0;
+ $conv = $0 << 24 >> 24;
+ $call = _toupper($conv | 0) | 0;
+ $sext = $call << 24;
+ $conv2 = $sext >> 24;
+ if (($conv2 | 0) == 76) {
+ label = 3;
+ break;
+ } else if (($conv2 | 0) == 82) {
+ label = 5;
+ break;
+ } else if (($conv2 | 0) == 84) {
+ label = 7;
+ break;
+ } else if (($conv2 | 0) == 67) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $add_ptr = $v + 1 | 0;
+ $call4 = _strcasecmp($add_ptr, 120248) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 4:
+ $flags = $p + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $or = $1 | 4;
+ HEAP16[$flags >> 1] = $or;
+ $rv_013 = 0;
+ label = 11;
+ break;
+ case 5:
+ $add_ptr11 = $v + 1 | 0;
+ $call12 = _strcasecmp($add_ptr11, 121e3) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 6:
+ $flags15 = $p + 32 | 0;
+ $2 = HEAP16[$flags15 >> 1] | 0;
+ $or17 = $2 | 2;
+ HEAP16[$flags15 >> 1] = $or17;
+ $rv_013 = 0;
+ label = 11;
+ break;
+ case 7:
+ $add_ptr24 = $v + 1 | 0;
+ $call25 = _strcasecmp($add_ptr24, 99264) | 0;
+ $tobool26 = ($call25 | 0) == 0;
+ if ($tobool26) {
+ label = 8;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 8:
+ $flags28 = $p + 32 | 0;
+ $3 = HEAP16[$flags28 >> 1] | 0;
+ $or30 = $3 | 6;
+ HEAP16[$flags28 >> 1] = $or30;
+ $rv_013 = 0;
+ label = 11;
+ break;
+ case 9:
+ $add_ptr36 = $v + 1 | 0;
+ $call37 = _strcasecmp($add_ptr36, 119648) | 0;
+ $tobool38 = ($call37 | 0) == 0;
+ if ($tobool38) {
+ $rv_013 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call45 = _agerr(0, 98880, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $v, tempInt) | 0) | 0;
+ $rv_013 = 1;
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return $rv_013 | 0;
+ }
+ return 0;
+}
+function _balignfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $0 = 0, $conv = 0, $call = 0, $sext = 0, $conv2 = 0, $add_ptr = 0, $call4 = 0, $tobool = 0, $flags = 0, $1 = 0, $or = 0, $add_ptr11 = 0, $call12 = 0, $tobool13 = 0, $flags15 = 0, $2 = 0, $or17 = 0, $add_ptr23 = 0, $call24 = 0, $tobool25 = 0, $call31 = 0, $rv_010 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$v] | 0;
+ $conv = $0 << 24 >> 24;
+ $call = _toupper($conv | 0) | 0;
+ $sext = $call << 24;
+ $conv2 = $sext >> 24;
+ if (($conv2 | 0) == 76) {
+ label = 3;
+ break;
+ } else if (($conv2 | 0) == 82) {
+ label = 5;
+ break;
+ } else if (($conv2 | 0) == 67) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $add_ptr = $v + 1 | 0;
+ $call4 = _strcasecmp($add_ptr, 120248) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $flags = $p + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $or = $1 | 512;
+ HEAP16[$flags >> 1] = $or;
+ $rv_010 = 0;
+ label = 9;
+ break;
+ case 5:
+ $add_ptr11 = $v + 1 | 0;
+ $call12 = _strcasecmp($add_ptr11, 121e3) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $flags15 = $p + 32 | 0;
+ $2 = HEAP16[$flags15 >> 1] | 0;
+ $or17 = $2 | 256;
+ HEAP16[$flags15 >> 1] = $or17;
+ $rv_010 = 0;
+ label = 9;
+ break;
+ case 7:
+ $add_ptr23 = $v + 1 | 0;
+ $call24 = _strcasecmp($add_ptr23, 119648) | 0;
+ $tobool25 = ($call24 | 0) == 0;
+ if ($tobool25) {
+ $rv_010 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call31 = _agerr(0, 99696, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $v, tempInt) | 0) | 0;
+ $rv_010 = 1;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return $rv_010 | 0;
+ }
+ return 0;
+}
+function _bgcolorfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 20 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _borderfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $conv = 0, $border = 0, $flags = 0, $1 = 0, $or = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 100112, 0, 255, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $conv = $0 & 255;
+ $border = $p + 29 | 0;
+ HEAP8[$border] = $conv;
+ $flags = $p + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $or = $1 | 32;
+ HEAP16[$flags >> 1] = $or;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _cellpaddingfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $conv = 0, $pad = 0, $flags = 0, $1 = 0, $or = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 100592, 0, 255, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $conv = $0 & 255;
+ $pad = $p + 30 | 0;
+ HEAP8[$pad] = $conv;
+ $flags = $p + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $or = $1 | 64;
+ HEAP16[$flags >> 1] = $or;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _cellspacingfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $conv = 0, $space = 0, $flags = 0, $1 = 0, $or = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 100952, -128, 127, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $conv = $0 & 255;
+ $space = $p + 28 | 0;
+ HEAP8[$space] = $conv;
+ $flags = $p + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $or = $1 | 128;
+ HEAP16[$flags >> 1] = $or;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _pencolorfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 24 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _colspanfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $cmp = 0, $call2 = 0, $conv = 0, $cspan = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 101896, 0, 65535, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 6;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call2 = _agerr(0, 101520, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $retval_0 = 1;
+ label = 6;
+ break;
+ case 5:
+ $conv = $0 & 65535;
+ $cspan = $p + 72 | 0;
+ HEAP16[$cspan >> 1] = $conv;
+ $retval_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _fixedsizefn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $0 = 0, $conv = 0, $call = 0, $sext = 0, $conv2 = 0, $add_ptr = 0, $call4 = 0, $tobool = 0, $flags = 0, $1 = 0, $or = 0, $add_ptr10 = 0, $call11 = 0, $tobool12 = 0, $call14 = 0, $rv_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$v] | 0;
+ $conv = $0 & 255;
+ $call = _toupper($conv | 0) | 0;
+ $sext = $call << 24;
+ $conv2 = $sext >> 24;
+ if (($conv2 | 0) == 84) {
+ label = 3;
+ break;
+ } else if (($conv2 | 0) == 70) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $add_ptr = $v + 1 | 0;
+ $call4 = _strcasecmp($add_ptr, 103064) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $flags = $p + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $or = $1 | 1;
+ HEAP16[$flags >> 1] = $or;
+ $rv_0 = 0;
+ label = 7;
+ break;
+ case 5:
+ $add_ptr10 = $v + 1 | 0;
+ $call11 = _strcasecmp($add_ptr10, 102728) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ $rv_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call14 = _agerr(0, 102368, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $v, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _heightfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $conv = 0, $height = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 103432, 0, 65535, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $conv = $0 & 65535;
+ $height = $p + 36 | 0;
+ HEAP16[$height >> 1] = $conv;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _hreffn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _idfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 16 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _portfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 4 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _rowspanfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $cmp = 0, $call2 = 0, $conv = 0, $rspan = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 104304, 0, 65535, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 6;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call2 = _agerr(0, 103896, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $retval_0 = 1;
+ label = 6;
+ break;
+ case 5:
+ $conv = $0 & 65535;
+ $rspan = $p + 74 | 0;
+ HEAP16[$rspan >> 1] = $conv;
+ $retval_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _targetfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 8 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _titlefn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ HEAP32[$p + 12 >> 2] = _strdup($v | 0) | 0;
+ return 0;
+}
+function _valignfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $0 = 0, $conv = 0, $call = 0, $sext = 0, $conv2 = 0, $add_ptr = 0, $call4 = 0, $tobool = 0, $flags = 0, $1 = 0, $or = 0, $add_ptr11 = 0, $call12 = 0, $tobool13 = 0, $flags15 = 0, $2 = 0, $or17 = 0, $add_ptr23 = 0, $call24 = 0, $tobool25 = 0, $call27 = 0, $rv_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$v] | 0;
+ $conv = $0 << 24 >> 24;
+ $call = _toupper($conv | 0) | 0;
+ $sext = $call << 24;
+ $conv2 = $sext >> 24;
+ if (($conv2 | 0) == 66) {
+ label = 3;
+ break;
+ } else if (($conv2 | 0) == 84) {
+ label = 5;
+ break;
+ } else if (($conv2 | 0) == 77) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $add_ptr = $v + 1 | 0;
+ $call4 = _strcasecmp($add_ptr, 105888) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $flags = $p + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $or = $1 | 16;
+ HEAP16[$flags >> 1] = $or;
+ $rv_0 = 0;
+ label = 9;
+ break;
+ case 5:
+ $add_ptr11 = $v + 1 | 0;
+ $call12 = _strcasecmp($add_ptr11, 105528) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $flags15 = $p + 32 | 0;
+ $2 = HEAP16[$flags15 >> 1] | 0;
+ $or17 = $2 | 8;
+ HEAP16[$flags15 >> 1] = $or17;
+ $rv_0 = 0;
+ label = 9;
+ break;
+ case 7:
+ $add_ptr23 = $v + 1 | 0;
+ $call24 = _strcasecmp($add_ptr23, 105184) | 0;
+ $tobool25 = ($call24 | 0) == 0;
+ if ($tobool25) {
+ $rv_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call27 = _agerr(0, 104832, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $v, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _widthfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $conv = 0, $width = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 106272, 0, 65535, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $conv = $0 & 65535;
+ $width = $p + 34 | 0;
+ HEAP16[$width >> 1] = $conv;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _halignfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $0 = 0, $conv = 0, $call = 0, $sext = 0, $conv2 = 0, $add_ptr = 0, $call4 = 0, $tobool = 0, $flags = 0, $1 = 0, $or = 0, $add_ptr11 = 0, $call12 = 0, $tobool13 = 0, $flags15 = 0, $2 = 0, $or17 = 0, $add_ptr23 = 0, $call24 = 0, $tobool25 = 0, $call27 = 0, $rv_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$v] | 0;
+ $conv = $0 << 24 >> 24;
+ $call = _toupper($conv | 0) | 0;
+ $sext = $call << 24;
+ $conv2 = $sext >> 24;
+ if (($conv2 | 0) == 76) {
+ label = 3;
+ break;
+ } else if (($conv2 | 0) == 82) {
+ label = 5;
+ break;
+ } else if (($conv2 | 0) == 67) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $add_ptr = $v + 1 | 0;
+ $call4 = _strcasecmp($add_ptr, 120248) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $flags = $p + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $or = $1 | 4;
+ HEAP16[$flags >> 1] = $or;
+ $rv_0 = 0;
+ label = 9;
+ break;
+ case 5:
+ $add_ptr11 = $v + 1 | 0;
+ $call12 = _strcasecmp($add_ptr11, 121e3) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $flags15 = $p + 32 | 0;
+ $2 = HEAP16[$flags15 >> 1] | 0;
+ $or17 = $2 | 2;
+ HEAP16[$flags15 >> 1] = $or17;
+ $rv_0 = 0;
+ label = 9;
+ break;
+ case 7:
+ $add_ptr23 = $v + 1 | 0;
+ $call24 = _strcasecmp($add_ptr23, 119648) | 0;
+ $tobool25 = ($call24 | 0) == 0;
+ if ($tobool25) {
+ $rv_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call27 = _agerr(0, 119080, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $v, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _cellborderfn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $u = 0, $call = 0, $tobool = 0, $0 = 0, $conv = 0, $cb = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = __stackBase__ | 0;
+ $call = _doInt($v, 96384, 0, 127, $u) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$u >> 2] | 0;
+ $conv = $0 & 255;
+ $cb = $p + 80 | 0;
+ HEAP8[$cb] = $conv;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _stylefn($p, $v) {
+ $p = $p | 0;
+ $v = $v | 0;
+ var $0 = 0, $conv = 0, $call = 0, $sext_mask = 0, $cmp = 0, $add_ptr = 0, $call4 = 0, $tobool = 0, $style = 0, $call5 = 0, $rv_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$v] | 0;
+ $conv = $0 << 24 >> 24;
+ $call = _toupper($conv | 0) | 0;
+ $sext_mask = $call & 255;
+ $cmp = ($sext_mask | 0) == 82;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $add_ptr = $v + 1 | 0;
+ $call4 = _strcasecmp($add_ptr, 97232) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $style = $p + 104 | 0;
+ HEAP8[$style] = 2;
+ $rv_0 = 0;
+ label = 6;
+ break;
+ case 5:
+ $call5 = _agerr(0, 96872, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $v, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _htmlparse() {
+ var $htmlssa = 0, $htmlvsa = 0, $arraydecay = 0, $arraydecay1 = 0, $htmlvsp_0 = 0, $htmlssp_0 = 0, $htmlerrstatus_0 = 0, $htmlstate_0 = 0, $incdec_ptr = 0, $htmlvs_0 = 0, $htmlvsp_1 = 0, $htmlstacksize_0 = 0, $htmlssp_1 = 0, $htmlss_0 = 0, $htmlerrstatus_1 = 0, $htmlstate_1 = 0, $conv = 0, $add_ptr_sum = 0, $add_ptr2 = 0, $cmp = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $sub_ptr_div = 0, $add = 0, $cmp4 = 0, $mul = 0, $cmp7 = 0, $_mul = 0, $mul11 = 0, $add12132 = 0, $call = 0, $tobool = 0, $0 = 0, $htmlss_alloc = 0, $1 = 0, $mul15 = 0, $2 = 0, $div = 0, $htmlvs_alloc = 0, $3 = 0, $4 = 0, $mul22 = 0, $cmp30 = 0, $add_ptr35 = 0, $add_ptr37 = 0, $add_ptr38_sum = 0, $cmp40 = 0, $htmlvs_1 = 0, $htmlvsp_2 = 0, $htmlstacksize_2 = 0, $htmlssp_2 = 0, $htmlss_1 = 0, $cmp45 = 0, $arrayidx = 0, $5 = 0, $conv49 = 0, $cmp50 = 0, $6 = 0, $cmp54 = 0, $call57 = 0, $7 = 0, $cmp59 = 0, $cmp62 = 0, $arrayidx64 = 0, $8 = 0, $conv65 = 0, $htmltoken_2 = 0, $add67 = 0, $9 = 0, $arrayidx73 = 0, $10 = 0, $conv74 = 0, $cmp75 = 0, $arrayidx79 = 0, $11 = 0, $conv80 = 0, $cmp81 = 0, $cmp84 = 0, $sub = 0, $tobool92 = 0, $dec = 0, $htmlerrstatus_1_dec = 0, $incdec_ptr95 = 0, $12 = 0, $13 = 0, $arrayidx96 = 0, $14 = 0, $conv97 = 0, $cmp98 = 0, $htmln_0 = 0, $arrayidx102 = 0, $15 = 0, $conv103 = 0, $sub104 = 0, $htmlval_sroa_0_0__idx18 = 0, $htmlval_sroa_0_0_copyload19 = 0, $arrayidx106 = 0, $txt = 0, $16 = 0, $17 = 0, $call107 = 0, $arrayidx109 = 0, $tbl = 0, $18 = 0, $19 = 0, $call110 = 0, $call113 = 0, $20 = 0, $21 = 0, $i = 0, $22 = 0, $font = 0, $23 = 0, $font123 = 0, $24 = 0, $font127 = 0, $25 = 0, $font131 = 0, $26 = 0, $font135 = 0, $27 = 0, $font139 = 0, $28 = 0, $i143 = 0, $29 = 0, $i147 = 0, $30 = 0, $31 = 0, $ptr = 0, $32 = 0, $eptr = 0, $33 = 0, $cmp150 = 0, $call153 = 0, $34 = 0, $ptr157 = 0, $35 = 0, $incdec_ptr158 = 0, $36 = 0, $buf = 0, $37 = 0, $ptr159 = 0, $call160 = 0, $tobool161 = 0, $38 = 0, $tbl165 = 0, $39 = 0, $40 = 0, $_c = 0, $41 = 0, $42 = 0, $call166 = 0, $43 = 0, $rows = 0, $call166_c = 0, $44 = 0, $45 = 0, $cfont = 0, $46 = 0, $call173 = 0, $47 = 0, $font176 = 0, $48 = 0, $49 = 0, $50 = 0, $ptr181 = 0, $51 = 0, $eptr182 = 0, $52 = 0, $cmp183 = 0, $call186 = 0, $53 = 0, $ptr190 = 0, $54 = 0, $incdec_ptr191 = 0, $55 = 0, $buf192 = 0, $56 = 0, $ptr193 = 0, $call194 = 0, $tobool195 = 0, $57 = 0, $58 = 0, $u199 = 0, $prev201 = 0, $59 = 0, $tbl204 = 0, $60 = 0, $61 = 0, $arrayidx207 = 0, $tbl208 = 0, $62 = 0, $63 = 0, $arrayidx211 = 0, $tbl212 = 0, $64 = 0, $65 = 0, $arrayidx215 = 0, $tbl216 = 0, $66 = 0, $67 = 0, $arrayidx219 = 0, $tbl220 = 0, $68 = 0, $69 = 0, $arrayidx224 = 0, $cell = 0, $70 = 0, $tbl226 = 0, $71 = 0, $72 = 0, $arrayidx228 = 0, $cell229 = 0, $73 = 0, $txt231 = 0, $74 = 0, $75 = 0, $arrayidx233 = 0, $cell234 = 0, $76 = 0, $img = 0, $77 = 0, $78 = 0, $cell238 = 0, $79 = 0, $call239 = 0, $80 = 0, $arrayidx241 = 0, $img242 = 0, $81 = 0, $82 = 0, $img246 = 0, $83 = 0, $84 = 0, $htmlval_sroa_0_0 = 0, $idx_neg = 0, $add_ptr250 = 0, $add_ptr248_sum = 0, $incdec_ptr251 = 0, $htmlval_sroa_0_0__idx = 0, $arrayidx252 = 0, $85 = 0, $conv253 = 0, $sub254 = 0, $arrayidx255 = 0, $86 = 0, $conv256 = 0, $87 = 0, $conv257 = 0, $add258 = 0, $88 = 0, $arrayidx264 = 0, $89 = 0, $conv265 = 0, $cmp267 = 0, $arrayidx270 = 0, $90 = 0, $conv271 = 0, $arrayidx274 = 0, $91 = 0, $conv275 = 0, $92 = 0, $inc = 0, $93 = 0, $cmp283 = 0, $cmp286 = 0, $htmlvsp_3 = 0, $htmlssp_3 = 0, $htmlstate_2 = 0, $arrayidx298 = 0, $94 = 0, $cmp300 = 0, $conv299 = 0, $add303 = 0, $cmp312 = 0, $arrayidx315 = 0, $95 = 0, $cmp317 = 0, $cmp323 = 0, $add_ptr329 = 0, $add_ptr330 = 0, $96 = 0, $conv331 = 0, $conv316 = 0, $incdec_ptr332 = 0, $97 = 0, $98 = 0, $htmlresult_0 = 0, $htmlss_3 = 0, $cmp348 = 0, $99 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1200 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $htmlssa = __stackBase__ | 0;
+ $htmlvsa = __stackBase__ + 400 | 0;
+ $arraydecay = $htmlssa | 0;
+ $arraydecay1 = $htmlvsa | 0;
+ HEAP32[3418] = 0;
+ HEAP32[3502] = -2;
+ $htmlstate_1 = 0;
+ $htmlerrstatus_1 = 0;
+ $htmlss_0 = $arraydecay;
+ $htmlssp_1 = $arraydecay;
+ $htmlstacksize_0 = 200;
+ $htmlvsp_1 = $arraydecay1;
+ $htmlvs_0 = $arraydecay1;
+ label = 4;
+ break;
+ case 3:
+ $incdec_ptr = $htmlssp_0 + 2 | 0;
+ $htmlstate_1 = $htmlstate_0;
+ $htmlerrstatus_1 = $htmlerrstatus_0;
+ $htmlss_0 = $htmlss_1;
+ $htmlssp_1 = $incdec_ptr;
+ $htmlstacksize_0 = $htmlstacksize_2;
+ $htmlvsp_1 = $htmlvsp_0;
+ $htmlvs_0 = $htmlvs_1;
+ label = 4;
+ break;
+ case 4:
+ $conv = $htmlstate_1 & 65535;
+ HEAP16[$htmlssp_1 >> 1] = $conv;
+ $add_ptr_sum = $htmlstacksize_0 - 1 | 0;
+ $add_ptr2 = $htmlss_0 + ($add_ptr_sum << 1) | 0;
+ $cmp = $add_ptr2 >>> 0 > $htmlssp_1 >>> 0;
+ if ($cmp) {
+ $htmlss_1 = $htmlss_0;
+ $htmlssp_2 = $htmlssp_1;
+ $htmlstacksize_2 = $htmlstacksize_0;
+ $htmlvsp_2 = $htmlvsp_1;
+ $htmlvs_1 = $htmlvs_0;
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $sub_ptr_lhs_cast = $htmlssp_1;
+ $sub_ptr_rhs_cast = $htmlss_0;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $sub_ptr_div = $sub_ptr_sub >> 1;
+ $add = $sub_ptr_div + 1 | 0;
+ $cmp4 = $htmlstacksize_0 >>> 0 > 9999;
+ if ($cmp4) {
+ label = 83;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $mul = $htmlstacksize_0 << 1;
+ $cmp7 = $mul >>> 0 > 1e4;
+ $_mul = $cmp7 ? 1e4 : $mul;
+ $mul11 = $_mul * 6 & -1;
+ $add12132 = $mul11 | 3;
+ $call = _malloc($add12132) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 83;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $0 = $call;
+ $htmlss_alloc = $call;
+ $1 = $htmlss_0;
+ $mul15 = $add << 1;
+ _memcpy($call | 0, $1 | 0, $mul15);
+ $2 = $_mul >>> 1;
+ $div = $2 & 1073741823;
+ $htmlvs_alloc = $0 + ($div << 2) | 0;
+ $3 = $htmlvs_alloc;
+ $4 = $htmlvs_0;
+ $mul22 = $add << 2;
+ _memcpy($3 | 0, $4 | 0, $mul22);
+ $cmp30 = ($htmlss_0 | 0) == ($arraydecay | 0);
+ if ($cmp30) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _free($1);
+ label = 9;
+ break;
+ case 9:
+ $add_ptr35 = $htmlss_alloc + ($sub_ptr_div << 1) | 0;
+ $add_ptr37 = $htmlvs_alloc + ($sub_ptr_div << 2) | 0;
+ $add_ptr38_sum = $_mul - 1 | 0;
+ $cmp40 = ($add_ptr38_sum | 0) > ($sub_ptr_div | 0);
+ if ($cmp40) {
+ $htmlss_1 = $htmlss_alloc;
+ $htmlssp_2 = $add_ptr35;
+ $htmlstacksize_2 = $_mul;
+ $htmlvsp_2 = $add_ptr37;
+ $htmlvs_1 = $htmlvs_alloc;
+ label = 10;
+ break;
+ } else {
+ $htmlss_3 = $htmlss_alloc;
+ $htmlresult_0 = 1;
+ label = 84;
+ break;
+ }
+ case 10:
+ $cmp45 = ($htmlstate_1 | 0) == 27;
+ if ($cmp45) {
+ $htmlss_3 = $htmlss_1;
+ $htmlresult_0 = 0;
+ label = 84;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $arrayidx = 13480 + ($htmlstate_1 << 1) | 0;
+ $5 = HEAP16[$arrayidx >> 1] | 0;
+ $conv49 = $5 << 16 >> 16;
+ $cmp50 = $5 << 16 >> 16 == -11;
+ if ($cmp50) {
+ label = 24;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $6 = HEAP32[3502] | 0;
+ $cmp54 = ($6 | 0) == -2;
+ if ($cmp54) {
+ label = 13;
+ break;
+ } else {
+ $7 = $6;
+ label = 14;
+ break;
+ }
+ case 13:
+ $call57 = _htmllex() | 0;
+ HEAP32[3502] = $call57;
+ $7 = $call57;
+ label = 14;
+ break;
+ case 14:
+ $cmp59 = ($7 | 0) < 1;
+ if ($cmp59) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ HEAP32[3502] = 0;
+ $htmltoken_2 = 0;
+ label = 18;
+ break;
+ case 16:
+ $cmp62 = $7 >>> 0 < 286;
+ if ($cmp62) {
+ label = 17;
+ break;
+ } else {
+ $htmltoken_2 = 2;
+ label = 18;
+ break;
+ }
+ case 17:
+ $arrayidx64 = $7 + 12840 | 0;
+ $8 = HEAP8[$arrayidx64] | 0;
+ $conv65 = $8 & 255;
+ $htmltoken_2 = $conv65;
+ label = 18;
+ break;
+ case 18:
+ $add67 = $htmltoken_2 + $conv49 | 0;
+ $9 = $add67 >>> 0 > 181;
+ if ($9) {
+ label = 24;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $arrayidx73 = $add67 + 13824 | 0;
+ $10 = HEAP8[$arrayidx73] | 0;
+ $conv74 = $10 << 24 >> 24;
+ $cmp75 = ($conv74 | 0) == ($htmltoken_2 | 0);
+ if ($cmp75) {
+ label = 20;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 20:
+ $arrayidx79 = $add67 + 13128 | 0;
+ $11 = HEAP8[$arrayidx79] | 0;
+ $conv80 = $11 << 24 >> 24;
+ $cmp81 = $11 << 24 >> 24 < 1;
+ if ($cmp81) {
+ label = 21;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 21:
+ $cmp84 = $11 << 24 >> 24 == 0;
+ if ($cmp84) {
+ label = 72;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $sub = -$conv80 | 0;
+ $htmln_0 = $sub;
+ label = 25;
+ break;
+ case 23:
+ $tobool92 = ($htmlerrstatus_1 | 0) == 0;
+ $dec = $htmlerrstatus_1 - 1 | 0;
+ $htmlerrstatus_1_dec = $tobool92 ? 0 : $dec;
+ HEAP32[3502] = -2;
+ $incdec_ptr95 = $htmlvsp_2 + 4 | 0;
+ $12 = HEAP32[3420] | 0;
+ $13 = $incdec_ptr95 | 0;
+ HEAP32[$13 >> 2] = $12;
+ $htmlstate_0 = $conv80;
+ $htmlerrstatus_0 = $htmlerrstatus_1_dec;
+ $htmlssp_0 = $htmlssp_2;
+ $htmlvsp_0 = $incdec_ptr95;
+ label = 3;
+ break;
+ case 24:
+ $arrayidx96 = $htmlstate_1 + 13728 | 0;
+ $14 = HEAP8[$arrayidx96] | 0;
+ $conv97 = $14 & 255;
+ $cmp98 = $14 << 24 >> 24 == 0;
+ if ($cmp98) {
+ label = 72;
+ break;
+ } else {
+ $htmln_0 = $conv97;
+ label = 25;
+ break;
+ }
+ case 25:
+ $arrayidx102 = $htmln_0 + 13312 | 0;
+ $15 = HEAP8[$arrayidx102] | 0;
+ $conv103 = $15 & 255;
+ $sub104 = 1 - $conv103 | 0;
+ $htmlval_sroa_0_0__idx18 = $htmlvsp_2 + ($sub104 << 2) | 0;
+ $htmlval_sroa_0_0_copyload19 = HEAP32[$htmlval_sroa_0_0__idx18 >> 2] | 0;
+ if (($htmln_0 | 0) == 2) {
+ label = 26;
+ break;
+ } else if (($htmln_0 | 0) == 3) {
+ label = 27;
+ break;
+ } else if (($htmln_0 | 0) == 4) {
+ label = 28;
+ break;
+ } else if (($htmln_0 | 0) == 5) {
+ label = 29;
+ break;
+ } else if (($htmln_0 | 0) == 8) {
+ label = 30;
+ break;
+ } else if (($htmln_0 | 0) == 9) {
+ label = 31;
+ break;
+ } else if (($htmln_0 | 0) == 16) {
+ label = 32;
+ break;
+ } else if (($htmln_0 | 0) == 17) {
+ label = 33;
+ break;
+ } else if (($htmln_0 | 0) == 18) {
+ label = 34;
+ break;
+ } else if (($htmln_0 | 0) == 19) {
+ label = 35;
+ break;
+ } else if (($htmln_0 | 0) == 20) {
+ label = 36;
+ break;
+ } else if (($htmln_0 | 0) == 21) {
+ label = 37;
+ break;
+ } else if (($htmln_0 | 0) == 22) {
+ label = 38;
+ break;
+ } else if (($htmln_0 | 0) == 23) {
+ label = 39;
+ break;
+ } else if (($htmln_0 | 0) == 24) {
+ label = 40;
+ break;
+ } else if (($htmln_0 | 0) == 25) {
+ label = 41;
+ break;
+ } else if (($htmln_0 | 0) == 26) {
+ label = 42;
+ break;
+ } else if (($htmln_0 | 0) == 27) {
+ label = 43;
+ break;
+ } else if (($htmln_0 | 0) == 28) {
+ label = 44;
+ break;
+ } else if (($htmln_0 | 0) == 29) {
+ label = 45;
+ break;
+ } else if (($htmln_0 | 0) == 32) {
+ label = 46;
+ break;
+ } else if (($htmln_0 | 0) == 33) {
+ label = 51;
+ break;
+ } else if (($htmln_0 | 0) == 34) {
+ label = 56;
+ break;
+ } else if (($htmln_0 | 0) == 35) {
+ label = 57;
+ break;
+ } else if (($htmln_0 | 0) == 36) {
+ label = 58;
+ break;
+ } else if (($htmln_0 | 0) == 37) {
+ label = 59;
+ break;
+ } else if (($htmln_0 | 0) == 38) {
+ label = 60;
+ break;
+ } else if (($htmln_0 | 0) == 43) {
+ label = 61;
+ break;
+ } else if (($htmln_0 | 0) == 47) {
+ label = 62;
+ break;
+ } else if (($htmln_0 | 0) == 49) {
+ label = 63;
+ break;
+ } else if (($htmln_0 | 0) == 51) {
+ label = 64;
+ break;
+ } else if (($htmln_0 | 0) == 53) {
+ label = 65;
+ break;
+ } else if (($htmln_0 | 0) == 55) {
+ label = 66;
+ break;
+ } else if (($htmln_0 | 0) == 56) {
+ label = 67;
+ break;
+ } else {
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ }
+ case 26:
+ $arrayidx106 = $htmlvsp_2 - 4 | 0;
+ $txt = $arrayidx106;
+ $16 = HEAP32[$txt >> 2] | 0;
+ $17 = $16;
+ $call107 = _mkLabel($17, 2) | 0;
+ HEAP32[41784] = $call107;
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 27:
+ $arrayidx109 = $htmlvsp_2 - 4 | 0;
+ $tbl = $arrayidx109;
+ $18 = HEAP32[$tbl >> 2] | 0;
+ $19 = $18;
+ $call110 = _mkLabel($19, 1) | 0;
+ HEAP32[41784] = $call110;
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 28:
+ _cleanup();
+ $htmlss_3 = $htmlss_1;
+ $htmlresult_0 = 1;
+ label = 84;
+ break;
+ case 29:
+ $call113 = _mkText() | 0;
+ $20 = $call113;
+ $htmlval_sroa_0_0 = $20;
+ label = 68;
+ break;
+ case 30:
+ $21 = HEAP32[41776] | 0;
+ _appendFItemList($21);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 31:
+ $i = $htmlvsp_2 | 0;
+ $22 = HEAP32[$i >> 2] | 0;
+ _appendFLineList($22);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 32:
+ $font = $htmlvsp_2;
+ $23 = HEAP32[$font >> 2] | 0;
+ _pushFont($23);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 33:
+ _popFont();
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 34:
+ $font123 = $htmlvsp_2;
+ $24 = HEAP32[$font123 >> 2] | 0;
+ _pushFont($24);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 35:
+ _popFont();
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 36:
+ $font127 = $htmlvsp_2;
+ $25 = HEAP32[$font127 >> 2] | 0;
+ _pushFont($25);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 37:
+ _popFont();
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 38:
+ $font131 = $htmlvsp_2;
+ $26 = HEAP32[$font131 >> 2] | 0;
+ _pushFont($26);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 39:
+ _popFont();
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 40:
+ $font135 = $htmlvsp_2;
+ $27 = HEAP32[$font135 >> 2] | 0;
+ _pushFont($27);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 41:
+ _popFont();
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 42:
+ $font139 = $htmlvsp_2;
+ $28 = HEAP32[$font139 >> 2] | 0;
+ _pushFont($28);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 43:
+ _popFont();
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 44:
+ $i143 = $htmlvsp_2 - 4 | 0;
+ $29 = HEAP32[$i143 >> 2] | 0;
+ $htmlval_sroa_0_0 = $29;
+ label = 68;
+ break;
+ case 45:
+ $i147 = $htmlvsp_2 | 0;
+ $30 = HEAP32[$i147 >> 2] | 0;
+ $htmlval_sroa_0_0 = $30;
+ label = 68;
+ break;
+ case 46:
+ $31 = HEAP32[41776] | 0;
+ $ptr = $31 + 4 | 0;
+ $32 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $31 + 8 | 0;
+ $33 = HEAP32[$eptr >> 2] | 0;
+ $cmp150 = $32 >>> 0 < $33 >>> 0;
+ if ($cmp150) {
+ label = 48;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $call153 = _agxbmore($31, 1) | 0;
+ label = 48;
+ break;
+ case 48:
+ $34 = HEAP32[41776] | 0;
+ $ptr157 = $34 + 4 | 0;
+ $35 = HEAP32[$ptr157 >> 2] | 0;
+ $incdec_ptr158 = $35 + 1 | 0;
+ HEAP32[$ptr157 >> 2] = $incdec_ptr158;
+ HEAP8[$35] = 0;
+ $36 = HEAP32[41776] | 0;
+ $buf = $36 | 0;
+ $37 = HEAP32[$buf >> 2] | 0;
+ $ptr159 = $36 + 4 | 0;
+ HEAP32[$ptr159 >> 2] = $37;
+ $call160 = _nonSpace($37) | 0;
+ $tobool161 = ($call160 | 0) == 0;
+ if ($tobool161) {
+ label = 50;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ _htmlerror(104648);
+ _cleanup();
+ $htmlss_3 = $htmlss_1;
+ $htmlresult_0 = 1;
+ label = 84;
+ break;
+ case 50:
+ $38 = HEAP32[41782] | 0;
+ $tbl165 = $htmlvsp_2;
+ $39 = HEAP32[$tbl165 >> 2] | 0;
+ $40 = $39 + 72 | 0;
+ $_c = $38;
+ HEAP32[$40 >> 2] = $_c;
+ $41 = HEAP32[41976] | 0;
+ $42 = $41;
+ $call166 = _dtopen(4280, $42) | 0;
+ $43 = HEAP32[$tbl165 >> 2] | 0;
+ $rows = $43 + 76 | 0;
+ $call166_c = $call166;
+ HEAP32[$rows >> 2] = $call166_c;
+ $44 = HEAP32[$tbl165 >> 2] | 0;
+ HEAP32[41782] = $44;
+ $45 = HEAP32[41774] | 0;
+ $cfont = $45 | 0;
+ $46 = HEAP32[$cfont >> 2] | 0;
+ $call173 = _dupFont($46) | 0;
+ $47 = HEAP32[$tbl165 >> 2] | 0;
+ $font176 = $47 + 100 | 0;
+ HEAP32[$font176 >> 2] = $call173;
+ $48 = HEAP32[$tbl165 >> 2] | 0;
+ $49 = $48;
+ $htmlval_sroa_0_0 = $49;
+ label = 68;
+ break;
+ case 51:
+ $50 = HEAP32[41776] | 0;
+ $ptr181 = $50 + 4 | 0;
+ $51 = HEAP32[$ptr181 >> 2] | 0;
+ $eptr182 = $50 + 8 | 0;
+ $52 = HEAP32[$eptr182 >> 2] | 0;
+ $cmp183 = $51 >>> 0 < $52 >>> 0;
+ if ($cmp183) {
+ label = 53;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $call186 = _agxbmore($50, 1) | 0;
+ label = 53;
+ break;
+ case 53:
+ $53 = HEAP32[41776] | 0;
+ $ptr190 = $53 + 4 | 0;
+ $54 = HEAP32[$ptr190 >> 2] | 0;
+ $incdec_ptr191 = $54 + 1 | 0;
+ HEAP32[$ptr190 >> 2] = $incdec_ptr191;
+ HEAP8[$54] = 0;
+ $55 = HEAP32[41776] | 0;
+ $buf192 = $55 | 0;
+ $56 = HEAP32[$buf192 >> 2] | 0;
+ $ptr193 = $55 + 4 | 0;
+ HEAP32[$ptr193 >> 2] = $56;
+ $call194 = _nonSpace($56) | 0;
+ $tobool195 = ($call194 | 0) == 0;
+ if ($tobool195) {
+ label = 55;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 54:
+ _htmlerror(143352);
+ _cleanup();
+ $htmlss_3 = $htmlss_1;
+ $htmlresult_0 = 1;
+ label = 84;
+ break;
+ case 55:
+ $57 = HEAP32[41782] | 0;
+ $58 = $57;
+ $u199 = $57 + 72 | 0;
+ $prev201 = $u199;
+ $59 = HEAP32[$prev201 >> 2] | 0;
+ HEAP32[41782] = $59;
+ $htmlval_sroa_0_0 = $58;
+ label = 68;
+ break;
+ case 56:
+ $tbl204 = $htmlvsp_2;
+ $60 = HEAP32[$tbl204 >> 2] | 0;
+ $61 = $60;
+ $htmlval_sroa_0_0 = $61;
+ label = 68;
+ break;
+ case 57:
+ $arrayidx207 = $htmlvsp_2 - 4 | 0;
+ $tbl208 = $arrayidx207;
+ $62 = HEAP32[$tbl208 >> 2] | 0;
+ $63 = $62;
+ $htmlval_sroa_0_0 = $63;
+ label = 68;
+ break;
+ case 58:
+ $arrayidx211 = $htmlvsp_2 - 4 | 0;
+ $tbl212 = $arrayidx211;
+ $64 = HEAP32[$tbl212 >> 2] | 0;
+ $65 = $64;
+ $htmlval_sroa_0_0 = $65;
+ label = 68;
+ break;
+ case 59:
+ $arrayidx215 = $htmlvsp_2 - 4 | 0;
+ $tbl216 = $arrayidx215;
+ $66 = HEAP32[$tbl216 >> 2] | 0;
+ $67 = $66;
+ $htmlval_sroa_0_0 = $67;
+ label = 68;
+ break;
+ case 60:
+ $arrayidx219 = $htmlvsp_2 - 4 | 0;
+ $tbl220 = $arrayidx219;
+ $68 = HEAP32[$tbl220 >> 2] | 0;
+ $69 = $68;
+ $htmlval_sroa_0_0 = $69;
+ label = 68;
+ break;
+ case 61:
+ _addRow();
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 62:
+ $arrayidx224 = $htmlvsp_2 - 4 | 0;
+ $cell = $arrayidx224;
+ $70 = HEAP32[$cell >> 2] | 0;
+ $tbl226 = $htmlvsp_2;
+ $71 = HEAP32[$tbl226 >> 2] | 0;
+ $72 = $71;
+ _setCell($70, $72, 1);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 63:
+ $arrayidx228 = $htmlvsp_2 - 4 | 0;
+ $cell229 = $arrayidx228;
+ $73 = HEAP32[$cell229 >> 2] | 0;
+ $txt231 = $htmlvsp_2;
+ $74 = HEAP32[$txt231 >> 2] | 0;
+ $75 = $74;
+ _setCell($73, $75, 2);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 64:
+ $arrayidx233 = $htmlvsp_2 - 4 | 0;
+ $cell234 = $arrayidx233;
+ $76 = HEAP32[$cell234 >> 2] | 0;
+ $img = $htmlvsp_2;
+ $77 = HEAP32[$img >> 2] | 0;
+ $78 = $77;
+ _setCell($76, $78, 3);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 65:
+ $cell238 = $htmlvsp_2;
+ $79 = HEAP32[$cell238 >> 2] | 0;
+ $call239 = _mkText() | 0;
+ $80 = $call239;
+ _setCell($79, $80, 2);
+ $htmlval_sroa_0_0 = $htmlval_sroa_0_0_copyload19;
+ label = 68;
+ break;
+ case 66:
+ $arrayidx241 = $htmlvsp_2 - 4 | 0;
+ $img242 = $arrayidx241;
+ $81 = HEAP32[$img242 >> 2] | 0;
+ $82 = $81;
+ $htmlval_sroa_0_0 = $82;
+ label = 68;
+ break;
+ case 67:
+ $img246 = $htmlvsp_2;
+ $83 = HEAP32[$img246 >> 2] | 0;
+ $84 = $83;
+ $htmlval_sroa_0_0 = $84;
+ label = 68;
+ break;
+ case 68:
+ $idx_neg = -$conv103 | 0;
+ $add_ptr250 = $htmlssp_2 + ($idx_neg << 1) | 0;
+ $add_ptr248_sum = 1 - $conv103 | 0;
+ $incdec_ptr251 = $htmlvsp_2 + ($add_ptr248_sum << 2) | 0;
+ $htmlval_sroa_0_0__idx = $htmlvsp_2 + ($add_ptr248_sum << 2) | 0;
+ HEAP32[$htmlval_sroa_0_0__idx >> 2] = $htmlval_sroa_0_0;
+ $arrayidx252 = $htmln_0 + 13376 | 0;
+ $85 = HEAP8[$arrayidx252] | 0;
+ $conv253 = $85 & 255;
+ $sub254 = $conv253 - 31 | 0;
+ $arrayidx255 = $sub254 + 13440 | 0;
+ $86 = HEAP8[$arrayidx255] | 0;
+ $conv256 = $86 << 24 >> 24;
+ $87 = HEAP16[$add_ptr250 >> 1] | 0;
+ $conv257 = $87 << 16 >> 16;
+ $add258 = $conv257 + $conv256 | 0;
+ $88 = $add258 >>> 0 < 182;
+ if ($88) {
+ label = 69;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 69:
+ $arrayidx264 = $add258 + 13824 | 0;
+ $89 = HEAP8[$arrayidx264] | 0;
+ $conv265 = $89 << 24 >> 24;
+ $cmp267 = ($conv265 | 0) == ($conv257 | 0);
+ if ($cmp267) {
+ label = 70;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 70:
+ $arrayidx270 = $add258 + 13128 | 0;
+ $90 = HEAP8[$arrayidx270] | 0;
+ $conv271 = $90 << 24 >> 24;
+ $htmlstate_0 = $conv271;
+ $htmlerrstatus_0 = $htmlerrstatus_1;
+ $htmlssp_0 = $add_ptr250;
+ $htmlvsp_0 = $incdec_ptr251;
+ label = 3;
+ break;
+ case 71:
+ $arrayidx274 = $sub254 + 13688 | 0;
+ $91 = HEAP8[$arrayidx274] | 0;
+ $conv275 = $91 << 24 >> 24;
+ $htmlstate_0 = $conv275;
+ $htmlerrstatus_0 = $htmlerrstatus_1;
+ $htmlssp_0 = $add_ptr250;
+ $htmlvsp_0 = $incdec_ptr251;
+ label = 3;
+ break;
+ case 72:
+ if (($htmlerrstatus_1 | 0) == 0) {
+ label = 73;
+ break;
+ } else if (($htmlerrstatus_1 | 0) == 3) {
+ label = 74;
+ break;
+ } else {
+ $htmlstate_2 = $htmlstate_1;
+ $htmlssp_3 = $htmlssp_2;
+ $htmlvsp_3 = $htmlvsp_2;
+ label = 77;
+ break;
+ }
+ case 73:
+ $92 = HEAP32[3418] | 0;
+ $inc = $92 + 1 | 0;
+ HEAP32[3418] = $inc;
+ _htmlerror(121376);
+ $htmlstate_2 = $htmlstate_1;
+ $htmlssp_3 = $htmlssp_2;
+ $htmlvsp_3 = $htmlvsp_2;
+ label = 77;
+ break;
+ case 74:
+ $93 = HEAP32[3502] | 0;
+ $cmp283 = ($93 | 0) < 1;
+ if ($cmp283) {
+ label = 75;
+ break;
+ } else {
+ label = 76;
+ break;
+ }
+ case 75:
+ $cmp286 = ($93 | 0) == 0;
+ if ($cmp286) {
+ $htmlss_3 = $htmlss_1;
+ $htmlresult_0 = 1;
+ label = 84;
+ break;
+ } else {
+ $htmlstate_2 = $htmlstate_1;
+ $htmlssp_3 = $htmlssp_2;
+ $htmlvsp_3 = $htmlvsp_2;
+ label = 77;
+ break;
+ }
+ case 76:
+ HEAP32[3502] = -2;
+ $htmlstate_2 = $htmlstate_1;
+ $htmlssp_3 = $htmlssp_2;
+ $htmlvsp_3 = $htmlvsp_2;
+ label = 77;
+ break;
+ case 77:
+ $arrayidx298 = 13480 + ($htmlstate_2 << 1) | 0;
+ $94 = HEAP16[$arrayidx298 >> 1] | 0;
+ $cmp300 = $94 << 16 >> 16 == -11;
+ if ($cmp300) {
+ label = 80;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $conv299 = $94 << 16 >> 16;
+ $add303 = $conv299 + 1 | 0;
+ $cmp312 = ($add303 | 0) == 12;
+ if ($cmp312) {
+ label = 79;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 79:
+ $arrayidx315 = $add303 + 13128 | 0;
+ $95 = HEAP8[$arrayidx315] | 0;
+ $cmp317 = $95 << 24 >> 24 > 0;
+ if ($cmp317) {
+ label = 82;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 80:
+ $cmp323 = ($htmlssp_3 | 0) == ($htmlss_1 | 0);
+ if ($cmp323) {
+ $htmlss_3 = $htmlss_1;
+ $htmlresult_0 = 1;
+ label = 84;
+ break;
+ } else {
+ label = 81;
+ break;
+ }
+ case 81:
+ $add_ptr329 = $htmlvsp_3 - 4 | 0;
+ $add_ptr330 = $htmlssp_3 - 2 | 0;
+ $96 = HEAP16[$add_ptr330 >> 1] | 0;
+ $conv331 = $96 << 16 >> 16;
+ $htmlstate_2 = $conv331;
+ $htmlssp_3 = $add_ptr330;
+ $htmlvsp_3 = $add_ptr329;
+ label = 77;
+ break;
+ case 82:
+ $conv316 = $95 << 24 >> 24;
+ $incdec_ptr332 = $htmlvsp_3 + 4 | 0;
+ $97 = HEAP32[3420] | 0;
+ $98 = $incdec_ptr332 | 0;
+ HEAP32[$98 >> 2] = $97;
+ $htmlstate_0 = $conv316;
+ $htmlerrstatus_0 = 3;
+ $htmlssp_0 = $htmlssp_3;
+ $htmlvsp_0 = $incdec_ptr332;
+ label = 3;
+ break;
+ case 83:
+ _htmlerror(106440);
+ $htmlss_3 = $htmlss_0;
+ $htmlresult_0 = 2;
+ label = 84;
+ break;
+ case 84:
+ $cmp348 = ($htmlss_3 | 0) == ($arraydecay | 0);
+ if ($cmp348) {
+ label = 86;
+ break;
+ } else {
+ label = 85;
+ break;
+ }
+ case 85:
+ $99 = $htmlss_3;
+ _free($99);
+ label = 86;
+ break;
+ case 86:
+ STACKTOP = __stackBase__;
+ return $htmlresult_0 | 0;
+ }
+ return 0;
+}
+function _mkLabel($obj, $kind) {
+ $obj = $obj | 0;
+ $kind = $kind | 0;
+ var $call = 0, $0 = 0, $conv = 0, $1 = 0, $cmp = 0, $2 = 0, $txt = 0, $3 = 0, $tbl = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(8) | 0;
+ $0 = $call;
+ $conv = $kind & 255;
+ $1 = $call + 4 | 0;
+ HEAP8[$1] = $conv;
+ $cmp = ($kind | 0) == 2;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $obj;
+ $txt = $call;
+ HEAP32[$txt >> 2] = $2;
+ label = 5;
+ break;
+ case 4:
+ $3 = $obj;
+ $tbl = $call;
+ HEAP32[$tbl >> 2] = $3;
+ label = 5;
+ break;
+ case 5:
+ return $0 | 0;
+ }
+ return 0;
+}
+function _cleanup() {
+ var $0 = 0, $1 = 0, $tobool = 0, $tobool13 = 0, $tp_04 = 0, $u = 0, $prev = 0, $2 = 0, $tobool1 = 0, $3 = 0, $searchf = 0, $4 = 0, $call = 0, $5 = 0, $searchf2 = 0, $6 = 0, $call3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41782] | 0;
+ $1 = HEAP32[41784] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _free_html_label($1, 1);
+ HEAP32[41784] = 0;
+ label = 4;
+ break;
+ case 4:
+ HEAP32[13344] = 450;
+ $tobool13 = ($0 | 0) == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ $tp_04 = $0;
+ label = 5;
+ break;
+ }
+ case 5:
+ $u = $tp_04 + 72 | 0;
+ $prev = $u;
+ $2 = HEAP32[$prev >> 2] | 0;
+ _cleanTbl($tp_04);
+ $tobool1 = ($2 | 0) == 0;
+ if ($tobool1) {
+ label = 6;
+ break;
+ } else {
+ $tp_04 = $2;
+ label = 5;
+ break;
+ }
+ case 6:
+ HEAP32[13344] = 102;
+ HEAP32[4088] = 68;
+ $3 = HEAP32[41780] | 0;
+ $searchf = $3 | 0;
+ $4 = HEAP32[$searchf >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$4 & 1023]($3, 0, 64) | 0;
+ HEAP32[4088] = 102;
+ HEAP32[4098] = 474;
+ $5 = HEAP32[41778] | 0;
+ $searchf2 = $5 | 0;
+ $6 = HEAP32[$searchf2 >> 2] | 0;
+ $call3 = FUNCTION_TABLE_iiii[$6 & 1023]($5, 0, 64) | 0;
+ HEAP32[4098] = 102;
+ _freeFontstack();
+ return;
+ }
+}
+function _nonSpace($s) {
+ $s = $s | 0;
+ var $s_addr_0 = 0, $0 = 0, $tobool = 0, $incdec_ptr = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s_addr_0 = $s;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[$s_addr_0] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $s_addr_0 + 1 | 0;
+ $cmp = $0 << 24 >> 24 == 32;
+ if ($cmp) {
+ $s_addr_0 = $incdec_ptr;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dupFont($f) {
+ $f = $f | 0;
+ var $tobool = 0, $cnt = 0, $0 = 0, $inc = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($f | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cnt = $f + 12 | 0;
+ $0 = HEAP32[$cnt >> 2] | 0;
+ $inc = $0 + 1 | 0;
+ HEAP32[$cnt >> 2] = $inc;
+ label = 4;
+ break;
+ case 4:
+ return $f | 0;
+ }
+ return 0;
+}
+function _mkText() {
+ var $0 = 0, $call = 0, $1 = 0, $2 = 0, $call1 = 0, $tobool = 0, $call2 = 0, $conv = 0, $nparas = 0, $3 = 0, $tobool3 = 0, $mul = 0, $call5 = 0, $4 = 0, $paras = 0, $searchf = 0, $5 = 0, $call6 = 0, $tobool715 = 0, $i_017 = 0, $fl_0_in16 = 0, $6 = 0, $arrayidx = 0, $lp = 0, $7 = 0, $inc = 0, $8 = 0, $call10 = 0, $tobool7 = 0, $searchf12 = 0, $9 = 0, $call13 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41778] | 0;
+ $call = _zmalloc(40) | 0;
+ $1 = $call;
+ $2 = HEAP32[41780] | 0;
+ $call1 = _dtsize($2) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _appendFLineList(0);
+ label = 4;
+ break;
+ case 4:
+ $call2 = _dtsize($0) | 0;
+ $conv = $call2 & 65535;
+ $nparas = $call + 4 | 0;
+ $3 = $nparas;
+ HEAP16[$3 >> 1] = $conv;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $mul = $call2 * 24 & -1;
+ $call5 = _zmalloc($mul) | 0;
+ $4 = $call5;
+ $paras = $call;
+ HEAP32[$paras >> 2] = $4;
+ $searchf = $0 | 0;
+ $5 = HEAP32[$searchf >> 2] | 0;
+ $call6 = FUNCTION_TABLE_iiii[$5 & 1023]($0, 0, 128) | 0;
+ $tobool715 = ($call6 | 0) == 0;
+ if ($tobool715) {
+ label = 7;
+ break;
+ } else {
+ $fl_0_in16 = $call6;
+ $i_017 = 0;
+ label = 6;
+ break;
+ }
+ case 6:
+ $6 = HEAP32[$paras >> 2] | 0;
+ $arrayidx = $6 + ($i_017 * 24 & -1) | 0;
+ $lp = $fl_0_in16 + 8 | 0;
+ $7 = $arrayidx;
+ HEAP32[$7 >> 2] = HEAP32[$lp >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$lp + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$lp + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$lp + 12 >> 2] | 0;
+ HEAP32[$7 + 16 >> 2] = HEAP32[$lp + 16 >> 2] | 0;
+ HEAP32[$7 + 20 >> 2] = HEAP32[$lp + 20 >> 2] | 0;
+ $inc = $i_017 + 1 | 0;
+ $8 = HEAP32[$searchf >> 2] | 0;
+ $call10 = FUNCTION_TABLE_iiii[$8 & 1023]($0, $fl_0_in16, 8) | 0;
+ $tobool7 = ($call10 | 0) == 0;
+ if ($tobool7) {
+ label = 7;
+ break;
+ } else {
+ $fl_0_in16 = $call10;
+ $i_017 = $inc;
+ label = 6;
+ break;
+ }
+ case 7:
+ $searchf12 = $0 | 0;
+ $9 = HEAP32[$searchf12 >> 2] | 0;
+ $call13 = FUNCTION_TABLE_iiii[$9 & 1023]($0, 0, 64) | 0;
+ return $1 | 0;
+ }
+ return 0;
+}
+function _appendFItemList($ag) {
+ $ag = $ag | 0;
+ var $call = 0, $ptr = 0, $0 = 0, $eptr = 0, $1 = 0, $cmp = 0, $call1 = 0, $2 = 0, $buf = 0, $3 = 0, $call4 = 0, $ti = 0, $str = 0, $4 = 0, $cfont = 0, $5 = 0, $call5 = 0, $font = 0, $6 = 0, $7 = 0, $searchf = 0, $8 = 0, $call7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(88) | 0;
+ $ptr = $ag + 4 | 0;
+ $0 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $ag + 8 | 0;
+ $1 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $0 >>> 0 < $1 >>> 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agxbmore($ag, 1) | 0;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$ptr >> 2] | 0;
+ HEAP8[$2] = 0;
+ $buf = $ag | 0;
+ $3 = HEAP32[$buf >> 2] | 0;
+ HEAP32[$ptr >> 2] = $3;
+ $call4 = _strdup($3 | 0) | 0;
+ $ti = $call + 8 | 0;
+ $str = $ti;
+ HEAP32[$str >> 2] = $call4;
+ $4 = HEAP32[41774] | 0;
+ $cfont = $4 | 0;
+ $5 = HEAP32[$cfont >> 2] | 0;
+ $call5 = _dupFont($5) | 0;
+ $font = $call + 24 | 0;
+ $6 = $font;
+ HEAP32[$6 >> 2] = $call5;
+ $7 = HEAP32[41780] | 0;
+ $searchf = $7 | 0;
+ $8 = HEAP32[$searchf >> 2] | 0;
+ $call7 = FUNCTION_TABLE_iiii[$8 & 1023]($7, $call, 1) | 0;
+ return;
+ }
+}
+function _appendFLineList($v) {
+ $v = $v | 0;
+ var $call = 0, $0 = 0, $call1 = 0, $conv = 0, $nitems = 0, $1 = 0, $conv2 = 0, $2 = 0, $tobool = 0, $lp = 0, $mul = 0, $call4 = 0, $3 = 0, $items = 0, $call6 = 0, $tobool713 = 0, $i_015 = 0, $fi_0_in14 = 0, $4 = 0, $arrayidx = 0, $ti = 0, $5 = 0, $6 = 0, $inc = 0, $right = 0, $7 = 0, $tobool7 = 0, $searchf = 0, $8 = 0, $call10 = 0, $9 = 0, $searchf11 = 0, $10 = 0, $call12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(32) | 0;
+ $0 = HEAP32[41780] | 0;
+ $call1 = _dtsize($0) | 0;
+ $conv = $call1 & 65535;
+ $nitems = $call + 12 | 0;
+ $1 = $nitems;
+ HEAP16[$1 >> 1] = $conv;
+ $conv2 = $v & 255;
+ $2 = $call + 14 | 0;
+ HEAP8[$2] = $conv2;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $lp = $call + 8 | 0;
+ $mul = $call1 * 80 & -1;
+ $call4 = _zmalloc($mul) | 0;
+ $3 = $call4;
+ $items = $lp;
+ HEAP32[$items >> 2] = $3;
+ $call6 = _dtflatten($0) | 0;
+ $tobool713 = ($call6 | 0) == 0;
+ if ($tobool713) {
+ label = 5;
+ break;
+ } else {
+ $fi_0_in14 = $call6;
+ $i_015 = 0;
+ label = 4;
+ break;
+ }
+ case 4:
+ $4 = HEAP32[$items >> 2] | 0;
+ $arrayidx = $4 + ($i_015 * 80 & -1) | 0;
+ $ti = $fi_0_in14 + 8 | 0;
+ $5 = $arrayidx;
+ $6 = $ti;
+ _memcpy($5 | 0, $6 | 0, 80);
+ $inc = $i_015 + 1 | 0;
+ $right = $fi_0_in14 | 0;
+ $7 = HEAP32[$right >> 2] | 0;
+ $tobool7 = ($7 | 0) == 0;
+ if ($tobool7) {
+ label = 5;
+ break;
+ } else {
+ $fi_0_in14 = $7;
+ $i_015 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ $searchf = $0 | 0;
+ $8 = HEAP32[$searchf >> 2] | 0;
+ $call10 = FUNCTION_TABLE_iiii[$8 & 1023]($0, 0, 64) | 0;
+ $9 = HEAP32[41778] | 0;
+ $searchf11 = $9 | 0;
+ $10 = HEAP32[$searchf11 >> 2] | 0;
+ $call12 = FUNCTION_TABLE_iiii[$10 & 1023]($9, $call, 1) | 0;
+ return;
+ }
+}
+function _pushFont($f) {
+ $f = $f | 0;
+ var $call = 0, $0 = 0, $1 = 0, $cfont = 0, $2 = 0, $tobool = 0, $color = 0, $3 = 0, $tobool1 = 0, $color2 = 0, $4 = 0, $tobool3 = 0, $call6 = 0, $size = 0, $5 = 0.0, $cmp = 0, $size9 = 0, $6 = 0.0, $cmp10 = 0, $name = 0, $7 = 0, $tobool15 = 0, $name17 = 0, $8 = 0, $tobool18 = 0, $call21 = 0, $9 = 0, $10 = 0, $11 = 0, $_mask = 0, $tobool24 = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $call35 = 0, $cfont36 = 0, $16 = 0, $pfont = 0, $17 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(8) | 0;
+ $0 = $call;
+ $1 = HEAP32[41774] | 0;
+ $cfont = $1 | 0;
+ $2 = HEAP32[$cfont >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $color = $f + 4 | 0;
+ $3 = HEAP32[$color >> 2] | 0;
+ $tobool1 = ($3 | 0) == 0;
+ if ($tobool1) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $color2 = $2 + 4 | 0;
+ $4 = HEAP32[$color2 >> 2] | 0;
+ $tobool3 = ($4 | 0) == 0;
+ if ($tobool3) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call6 = _strdup($4 | 0) | 0;
+ HEAP32[$color >> 2] = $call6;
+ label = 6;
+ break;
+ case 6:
+ $size = $f + 16 | 0;
+ $5 = +HEAPF64[$size >> 3];
+ $cmp = $5 < 0.0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 7:
+ $size9 = $2 + 16 | 0;
+ $6 = +HEAPF64[$size9 >> 3];
+ $cmp10 = $6 < 0.0;
+ if ($cmp10) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ HEAPF64[$size >> 3] = $6;
+ label = 9;
+ break;
+ case 9:
+ $name = $f | 0;
+ $7 = HEAP32[$name >> 2] | 0;
+ $tobool15 = ($7 | 0) == 0;
+ if ($tobool15) {
+ label = 10;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 10:
+ $name17 = $2 | 0;
+ $8 = HEAP32[$name17 >> 2] | 0;
+ $tobool18 = ($8 | 0) == 0;
+ if ($tobool18) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call21 = _strdup($8 | 0) | 0;
+ HEAP32[$name >> 2] = $call21;
+ label = 12;
+ break;
+ case 12:
+ $9 = $2 + 8 | 0;
+ $10 = $9;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $_mask = $11 & 127;
+ $tobool24 = ($_mask | 0) == 0;
+ if ($tobool24) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $12 = $f + 8 | 0;
+ $13 = $12;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $15 = $14 | $_mask;
+ HEAP32[$13 >> 2] = $15;
+ label = 14;
+ break;
+ case 14:
+ $call35 = _dupFont($f) | 0;
+ $cfont36 = $call;
+ HEAP32[$cfont36 >> 2] = $call35;
+ $16 = HEAP32[41774] | 0;
+ $pfont = $call + 4 | 0;
+ $17 = $pfont;
+ HEAP32[$17 >> 2] = $16;
+ HEAP32[41774] = $0;
+ return;
+ }
+}
+function _popFont() {
+ var $0 = 0, $1 = 0;
+ $0 = HEAP32[41774] | 0;
+ $1 = HEAP32[$0 + 4 >> 2] | 0;
+ _free_html_font(HEAP32[$0 >> 2] | 0);
+ _free($0);
+ HEAP32[41774] = $1;
+ return;
+}
+function _addRow() {
+ var $call = 0, $2 = 0, $call1 = 0, $3 = 0;
+ $call = _dtopen(53360, HEAP32[41976] | 0) | 0;
+ $2 = HEAP32[41782] | 0;
+ $call1 = _zmalloc(12) | 0;
+ HEAP32[$call1 + 8 >> 2] = $call;
+ $3 = HEAP32[$2 + 76 >> 2] | 0;
+ FUNCTION_TABLE_iiii[HEAP32[$3 >> 2] & 1023]($3, $call1, 1);
+ return;
+}
+function _setCell($cp, $obj, $kind) {
+ $cp = $cp | 0;
+ $obj = $obj | 0;
+ $kind = $kind | 0;
+ var $call = 0, $0 = 0, $rows = 0, $1 = 0, $2 = 0, $searchf11 = 0, $3 = 0, $call4 = 0, $u5 = 0, $rp6 = 0, $4 = 0, $u7 = 0, $cp8 = 0, $searchf9 = 0, $5 = 0, $call10 = 0, $conv = 0, $child = 0, $kind11 = 0, $6 = 0, $_c12 = 0, $7 = 0, $_c = 0, $8 = 0, $tbl23 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(12) | 0;
+ $0 = HEAP32[41782] | 0;
+ $rows = $0 + 76 | 0;
+ $1 = HEAP32[$rows >> 2] | 0;
+ $2 = $1;
+ $searchf11 = HEAP32[$1 >> 2] | 0;
+ $3 = $searchf11;
+ $call4 = FUNCTION_TABLE_iiii[$3 & 1023]($2, 0, 256) | 0;
+ $u5 = $call4 + 8 | 0;
+ $rp6 = $u5;
+ $4 = HEAP32[$rp6 >> 2] | 0;
+ $u7 = $call + 8 | 0;
+ $cp8 = $u7;
+ HEAP32[$cp8 >> 2] = $cp;
+ $searchf9 = $4 | 0;
+ $5 = HEAP32[$searchf9 >> 2] | 0;
+ $call10 = FUNCTION_TABLE_iiii[$5 & 1023]($4, $call, 1) | 0;
+ $conv = $kind & 255;
+ $child = $cp + 80 | 0;
+ $kind11 = $cp + 84 | 0;
+ HEAP8[$kind11] = $conv;
+ if (($kind | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($kind | 0) == 3) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $6 = $child | 0;
+ $_c12 = $obj;
+ HEAP32[$6 >> 2] = $_c12;
+ label = 6;
+ break;
+ case 4:
+ $7 = $child | 0;
+ $_c = $obj;
+ HEAP32[$7 >> 2] = $_c;
+ label = 6;
+ break;
+ case 5:
+ $8 = $obj;
+ $tbl23 = $child | 0;
+ HEAP32[$tbl23 >> 2] = $8;
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _parseHTML($txt, $warn, $charset) {
+ $txt = $txt | 0;
+ $warn = $warn | 0;
+ $charset = $charset | 0;
+ var $str = 0, $dfltf = 0, $4 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 152 | 0;
+ $str = __stackBase__ + 128 | 0;
+ $dfltf = __stackBase__ + 144 | 0;
+ HEAP32[$dfltf >> 2] = 0;
+ HEAP32[$dfltf + 4 >> 2] = 0;
+ HEAP32[41774] = $dfltf;
+ HEAP32[41782] = 0;
+ HEAP32[41784] = 0;
+ HEAP32[41780] = _dtopen(16336, HEAP32[41976] | 0) | 0;
+ HEAP32[41778] = _dtopen(16376, HEAP32[41976] | 0) | 0;
+ _agxbinit($str, 128, __stackBase__ | 0);
+ HEAP32[41776] = $str;
+ _initHTMLlexer($txt, $str, $charset);
+ _htmlparse();
+ HEAP32[$warn >> 2] = _clearHTMLlexer() | 0;
+ $4 = HEAP32[41784] | 0;
+ _dtclose(HEAP32[41780] | 0);
+ _dtclose(HEAP32[41778] | 0);
+ HEAP32[41780] = 0;
+ HEAP32[41778] = 0;
+ HEAP32[41774] = 0;
+ _agxbfree($str);
+ STACKTOP = __stackBase__;
+ return $4 | 0;
+}
+function _free_item($d, $p, $ds) {
+ $d = $d | 0;
+ $p = $p | 0;
+ $ds = $ds | 0;
+ _free($p);
+ return;
+}
+function _free_ritem($d, $p, $ds) {
+ $d = $d | 0;
+ $p = $p | 0;
+ $ds = $ds | 0;
+ _dtclose(HEAP32[$p + 8 >> 2] | 0);
+ _free($p);
+ return;
+}
+function _free_citem($d, $p, $ds) {
+ $d = $d | 0;
+ $p = $p | 0;
+ $ds = $ds | 0;
+ _cleanCell(HEAP32[$p + 8 >> 2] | 0);
+ _free($p);
+ return;
+}
+function _cleanTbl($tp) {
+ $tp = $tp | 0;
+ _dtclose(HEAP32[$tp + 76 >> 2] | 0);
+ _free_html_data($tp | 0);
+ _free($tp);
+ return;
+}
+function _free_fitem($d, $p, $ds) {
+ $d = $d | 0;
+ $p = $p | 0;
+ $ds = $ds | 0;
+ var $str = 0, $0 = 0, $tobool = 0, $font = 0, $1 = 0, $tobool4 = 0, $2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $str = $p + 8 | 0;
+ $0 = HEAP32[$str >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _free($0);
+ label = 4;
+ break;
+ case 4:
+ $font = $p + 24 | 0;
+ $1 = HEAP32[$font >> 2] | 0;
+ $tobool4 = ($1 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _free_html_font($1);
+ label = 6;
+ break;
+ case 6:
+ $2 = $p;
+ _free($2);
+ return;
+ }
+}
+function _free_fpara($d, $p, $ds) {
+ $d = $d | 0;
+ $p = $p | 0;
+ $ds = $ds | 0;
+ var $nitems = 0, $0 = 0, $tobool = 0, $items = 0, $1 = 0, $cmp11 = 0, $2 = 0, $i_013 = 0, $ti_012 = 0, $str = 0, $3 = 0, $tobool5 = 0, $font = 0, $4 = 0, $tobool8 = 0, $incdec_ptr = 0, $inc = 0, $5 = 0, $conv = 0, $cmp = 0, $6 = 0, $7 = 0, $8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nitems = $p + 12 | 0;
+ $0 = HEAP16[$nitems >> 1] | 0;
+ $tobool = $0 << 16 >> 16 == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $items = $p + 8 | 0;
+ $1 = HEAP16[$nitems >> 1] | 0;
+ $cmp11 = $1 << 16 >> 16 > 0;
+ if ($cmp11) {
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[$items >> 2] | 0;
+ $ti_012 = $2;
+ $i_013 = 0;
+ label = 5;
+ break;
+ case 5:
+ $str = $ti_012 | 0;
+ $3 = HEAP32[$str >> 2] | 0;
+ $tobool5 = ($3 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _free($3);
+ label = 7;
+ break;
+ case 7:
+ $font = $ti_012 + 16 | 0;
+ $4 = HEAP32[$font >> 2] | 0;
+ $tobool8 = ($4 | 0) == 0;
+ if ($tobool8) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _free_html_font($4);
+ label = 9;
+ break;
+ case 9:
+ $incdec_ptr = $ti_012 + 80 | 0;
+ $inc = $i_013 + 1 | 0;
+ $5 = HEAP16[$nitems >> 1] | 0;
+ $conv = $5 << 16 >> 16;
+ $cmp = ($inc | 0) < ($conv | 0);
+ if ($cmp) {
+ $ti_012 = $incdec_ptr;
+ $i_013 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $6 = HEAP32[$items >> 2] | 0;
+ $7 = $6;
+ _free($7);
+ label = 11;
+ break;
+ case 11:
+ $8 = $p;
+ _free($8);
+ return;
+ }
+}
+function _freeFontstack() {
+ var $0 = 0, $pfont3 = 0, $1 = 0, $tobool4 = 0, $2 = 0, $s_05 = 0, $cfont = 0, $3 = 0, $4 = 0, $pfont = 0, $5 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41774] | 0;
+ $pfont3 = $0 + 4 | 0;
+ $1 = HEAP32[$pfont3 >> 2] | 0;
+ $tobool4 = ($1 | 0) == 0;
+ if ($tobool4) {
+ label = 4;
+ break;
+ } else {
+ $s_05 = $0;
+ $2 = $1;
+ label = 3;
+ break;
+ }
+ case 3:
+ $cfont = $s_05 | 0;
+ $3 = HEAP32[$cfont >> 2] | 0;
+ _free_html_font($3);
+ $4 = $s_05;
+ _free($4);
+ $pfont = $2 + 4 | 0;
+ $5 = HEAP32[$pfont >> 2] | 0;
+ $tobool = ($5 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $s_05 = $2;
+ $2 = $5;
+ label = 3;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _cleanCell($cp) {
+ $cp = $cp | 0;
+ var $child = 0, $kind = 0, $0 = 0, $tbl = 0, $1 = 0, $txt = 0, $2 = 0, $data = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $child = $cp + 80 | 0;
+ $kind = $cp + 84 | 0;
+ $0 = HEAP8[$kind] | 0;
+ if (($0 << 24 >> 24 | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 2) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $tbl = $child | 0;
+ $1 = HEAP32[$tbl >> 2] | 0;
+ _cleanTbl($1);
+ label = 5;
+ break;
+ case 4:
+ $txt = $child;
+ $2 = HEAP32[$txt >> 2] | 0;
+ _free_html_text($2);
+ label = 5;
+ break;
+ case 5:
+ $data = $cp | 0;
+ _free_html_data($data);
+ $3 = $cp;
+ _free($3);
+ return;
+ }
+}
+function _emit_html_label($job, $lp, $tp) {
+ $job = $job | 0;
+ $lp = $lp | 0;
+ $tp = $tp | 0;
+ var $env = 0, $pos1 = 0, $0 = 0, $1 = 0, $fontcolor = 0, $2 = 0, $color = 0, $fontname = 0, $3 = 0, $name = 0, $fontsize = 0, $size = 0, $4 = 0.0, $obj = 0, $5 = 0, $u = 0, $n = 0, $6 = 0, $7 = 0, $call = 0, $imgscale = 0, $8 = 0, $id = 0, $9 = 0, $objid = 0, $objid_set = 0, $10 = 0, $cmp = 0, $11 = 0, $cmp10 = 0, $kind = 0, $12 = 0, $cmp14 = 0, $tbl18 = 0, $13 = 0, $gvc = 0, $14 = 0, $defaultlinestyle = 0, $15 = 0, $pencolor = 0, $16 = 0, $tobool = 0, $txt = 0, $17 = 0, $18 = 0, $tobool27 = 0, $19 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $env = __stackBase__ | 0;
+ _allocObj($job);
+ $pos1 = $tp + 56 | 0;
+ $0 = $env;
+ $1 = $pos1;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $fontcolor = $tp + 8 | 0;
+ $2 = HEAP32[$fontcolor >> 2] | 0;
+ $color = $env + 20 | 0;
+ HEAP32[$color >> 2] = $2;
+ $fontname = $tp + 4 | 0;
+ $3 = HEAP32[$fontname >> 2] | 0;
+ $name = $env + 16 | 0;
+ HEAP32[$name >> 2] = $3;
+ $fontsize = $tp + 16 | 0;
+ $size = $env + 32 | 0;
+ $4 = +HEAPF64[$fontsize >> 3];
+ HEAPF64[$size >> 3] = $4;
+ $obj = $job + 16 | 0;
+ $5 = HEAP32[$obj >> 2] | 0;
+ $u = $5 + 8 | 0;
+ $n = $u;
+ $6 = HEAP32[$n >> 2] | 0;
+ $7 = $6 | 0;
+ $call = _agget($7, 104192) | 0;
+ $imgscale = $env + 48 | 0;
+ HEAP32[$imgscale >> 2] = $call;
+ $8 = HEAP32[$obj >> 2] | 0;
+ $id = $8 + 164 | 0;
+ $9 = HEAP32[$id >> 2] | 0;
+ $objid = $env + 52 | 0;
+ HEAP32[$objid >> 2] = $9;
+ $objid_set = $env + 56 | 0;
+ HEAP8[$objid_set] = 0;
+ $10 = HEAP32[$imgscale >> 2] | 0;
+ $cmp = ($10 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $11 = HEAP8[$10] | 0;
+ $cmp10 = $11 << 24 >> 24 == 0;
+ if ($cmp10) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP32[$imgscale >> 2] = 142968;
+ label = 5;
+ break;
+ case 5:
+ $kind = $lp + 4 | 0;
+ $12 = HEAP8[$kind] | 0;
+ $cmp14 = $12 << 24 >> 24 == 1;
+ if ($cmp14) {
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 6:
+ $tbl18 = $lp | 0;
+ $13 = HEAP32[$tbl18 >> 2] | 0;
+ $gvc = $job | 0;
+ $14 = HEAP32[$gvc >> 2] | 0;
+ $defaultlinestyle = $14 + 304 | 0;
+ $15 = HEAP32[$defaultlinestyle >> 2] | 0;
+ _gvrender_set_style($job, $15);
+ $pencolor = $13 + 24 | 0;
+ $16 = HEAP32[$pencolor >> 2] | 0;
+ $tobool = ($16 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _gvrender_set_pencolor($job, $16);
+ label = 9;
+ break;
+ case 8:
+ _gvrender_set_pencolor($job, 121304);
+ label = 9;
+ break;
+ case 9:
+ _emit_html_tbl($job, $13, $env);
+ label = 11;
+ break;
+ case 10:
+ $txt = $lp;
+ $17 = HEAP32[$txt >> 2] | 0;
+ _emit_html_txt($job, $17, $env);
+ label = 11;
+ break;
+ case 11:
+ $18 = HEAP8[$objid_set] | 0;
+ $tobool27 = $18 << 24 >> 24 == 0;
+ if ($tobool27) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $19 = HEAP32[$objid >> 2] | 0;
+ _free($19);
+ label = 13;
+ break;
+ case 13:
+ _freeObj($job);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _allocObj($job) {
+ $job = $job | 0;
+ var $call = 0, $parent1 = 0, $0 = 0, $type = 0, $1 = 0, $type2 = 0, $emit_state = 0, $2 = 0, $emit_state3 = 0, $3 = 0, $u = 0, $n = 0, $4 = 0, $5 = 0, $_c22 = 0, $g = 0, $6 = 0, $g10 = 0, $sg = 0, $7 = 0, $sg14 = 0, $u16 = 0, $e = 0, $8 = 0, $9 = 0, $_c = 0, $url = 0, $10 = 0, $url19 = 0, $tooltip = 0, $11 = 0, $tooltip20 = 0, $target = 0, $12 = 0, $target21 = 0, $13 = 0, $14 = 0, $15 = 0, $bf_val_sext21 = 0, $16 = 0, $17 = 0, $18 = 0, $19 = 0, $20 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _push_obj_state($job) | 0;
+ $parent1 = $call | 0;
+ $0 = HEAP32[$parent1 >> 2] | 0;
+ $type = $0 + 4 | 0;
+ $1 = HEAP32[$type >> 2] | 0;
+ $type2 = $call + 4 | 0;
+ HEAP32[$type2 >> 2] = $1;
+ $emit_state = $0 + 12 | 0;
+ $2 = HEAP32[$emit_state >> 2] | 0;
+ $emit_state3 = $call + 12 | 0;
+ HEAP32[$emit_state3 >> 2] = $2;
+ $3 = HEAP32[$type2 >> 2] | 0;
+ if (($3 | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($3 | 0) == 0) {
+ label = 4;
+ break;
+ } else if (($3 | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($3 | 0) == 3) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $u = $0 + 8 | 0;
+ $n = $u;
+ $4 = HEAP32[$n >> 2] | 0;
+ $5 = $call + 8 | 0;
+ $_c22 = $4;
+ HEAP32[$5 >> 2] = $_c22;
+ label = 7;
+ break;
+ case 4:
+ $g = $0 + 8 | 0;
+ $6 = HEAP32[$g >> 2] | 0;
+ $g10 = $call + 8 | 0;
+ HEAP32[$g10 >> 2] = $6;
+ label = 7;
+ break;
+ case 5:
+ $sg = $0 + 8 | 0;
+ $7 = HEAP32[$sg >> 2] | 0;
+ $sg14 = $call + 8 | 0;
+ HEAP32[$sg14 >> 2] = $7;
+ label = 7;
+ break;
+ case 6:
+ $u16 = $0 + 8 | 0;
+ $e = $u16;
+ $8 = HEAP32[$e >> 2] | 0;
+ $9 = $call + 8 | 0;
+ $_c = $8;
+ HEAP32[$9 >> 2] = $_c;
+ label = 7;
+ break;
+ case 7:
+ $url = $0 + 160 | 0;
+ $10 = HEAP32[$url >> 2] | 0;
+ $url19 = $call + 160 | 0;
+ HEAP32[$url19 >> 2] = $10;
+ $tooltip = $0 + 180 | 0;
+ $11 = HEAP32[$tooltip >> 2] | 0;
+ $tooltip20 = $call + 180 | 0;
+ HEAP32[$tooltip20 >> 2] = $11;
+ $target = $0 + 196 | 0;
+ $12 = HEAP32[$target >> 2] | 0;
+ $target21 = $call + 196 | 0;
+ HEAP32[$target21 >> 2] = $12;
+ $13 = $0 + 212 | 0;
+ $14 = $13;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $bf_val_sext21 = $15 & 1;
+ $16 = $call + 212 | 0;
+ $17 = $16;
+ $18 = HEAP32[$17 >> 2] | 0;
+ $19 = $18 & -2;
+ $20 = $19 | $bf_val_sext21;
+ HEAP32[$17 >> 2] = $20;
+ return;
+ }
+}
+function _emit_html_tbl($job, $tbl, $env) {
+ $job = $job | 0;
+ $tbl = $tbl | 0;
+ $env = $env | 0;
+ var $pts = 0, $saved = 0, $AF = 0, $data = 0, $box = 0, $0 = 0, $1 = 0, $pos_sroa_0_0__idx = 0, $pos_sroa_0_0_copyload = 0.0, $pos_sroa_1_8__idx6 = 0, $pos_sroa_1_8_copyload = 0.0, $cells2 = 0, $2 = 0, $href = 0, $3 = 0, $tobool = 0, $target = 0, $4 = 0, $tobool5 = 0, $5 = 0, $font = 0, $6 = 0, $tobool6 = 0, $x8 = 0, $7 = 0.0, $add = 0.0, $UR = 0, $x10 = 0, $8 = 0.0, $add11 = 0.0, $y13 = 0, $9 = 0.0, $add14 = 0.0, $y17 = 0, $10 = 0.0, $add18 = 0.0, $flags = 0, $11 = 0, $and = 0, $tobool20 = 0, $call = 0, $anchor_0 = 0, $style = 0, $12 = 0, $and24 = 0, $tobool25 = 0, $pencolor = 0, $13 = 0, $tobool28 = 0, $_ = 0, $arrayidx = 0, $14 = 0, $arrayidx32 = 0, $15 = 0, $16 = 0, $x35 = 0, $17 = 0.0, $x37 = 0, $y39 = 0, $18 = 0.0, $y41 = 0, $x43 = 0, $19 = 0.0, $x45 = 0, $y47 = 0, $20 = 0.0, $y49 = 0, $bgcolor = 0, $21 = 0, $22 = 0, $conv52 = 0, $cmp = 0, $conv55 = 0, $bgcolor58 = 0, $23 = 0, $tobool59 = 0, $border = 0, $24 = 0, $tobool65 = 0, $pencolor68 = 0, $25 = 0, $conv71 = 0, $26 = 0, $tobool7439 = 0, $27 = 0, $cells_040 = 0, $incdec_ptr = 0, $28 = 0, $tobool74 = 0, $tobool75 = 0, $flags80 = 0, $29 = 0, $and81 = 0, $tobool82 = 0, $call85 = 0, $tobool86 = 0, $30 = 0, $tobool91 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 136 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pts = __stackBase__ | 0;
+ $saved = __stackBase__ + 32 | 0;
+ $AF = __stackBase__ + 72 | 0;
+ $data = $tbl | 0;
+ $box = $tbl + 40 | 0;
+ $0 = $pts;
+ $1 = $box;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ HEAP32[$0 + 16 >> 2] = HEAP32[$1 + 16 >> 2] | 0;
+ HEAP32[$0 + 20 >> 2] = HEAP32[$1 + 20 >> 2] | 0;
+ HEAP32[$0 + 24 >> 2] = HEAP32[$1 + 24 >> 2] | 0;
+ HEAP32[$0 + 28 >> 2] = HEAP32[$1 + 28 >> 2] | 0;
+ $pos_sroa_0_0__idx = $env | 0;
+ $pos_sroa_0_0_copyload = +HEAPF64[$pos_sroa_0_0__idx >> 3];
+ $pos_sroa_1_8__idx6 = $env + 8 | 0;
+ $pos_sroa_1_8_copyload = +HEAPF64[$pos_sroa_1_8__idx6 >> 3];
+ $cells2 = $tbl + 76 | 0;
+ $2 = HEAP32[$cells2 >> 2] | 0;
+ $href = $tbl | 0;
+ $3 = HEAP32[$href >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $5 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $target = $tbl + 8 | 0;
+ $4 = HEAP32[$target >> 2] | 0;
+ $tobool5 = ($4 | 0) != 0;
+ $5 = $tobool5;
+ label = 4;
+ break;
+ case 4:
+ $font = $tbl + 100 | 0;
+ $6 = HEAP32[$font >> 2] | 0;
+ $tobool6 = ($6 | 0) == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _pushFontInfo($env, $6, 20296);
+ label = 6;
+ break;
+ case 6:
+ $x8 = $pts | 0;
+ $7 = +HEAPF64[$x8 >> 3];
+ $add = $pos_sroa_0_0_copyload + $7;
+ HEAPF64[$x8 >> 3] = $add;
+ $UR = $pts + 16 | 0;
+ $x10 = $UR | 0;
+ $8 = +HEAPF64[$x10 >> 3];
+ $add11 = $pos_sroa_0_0_copyload + $8;
+ HEAPF64[$x10 >> 3] = $add11;
+ $y13 = $pts + 8 | 0;
+ $9 = +HEAPF64[$y13 >> 3];
+ $add14 = $pos_sroa_1_8_copyload + $9;
+ HEAPF64[$y13 >> 3] = $add14;
+ $y17 = $pts + 24 | 0;
+ $10 = +HEAPF64[$y17 >> 3];
+ $add18 = $pos_sroa_1_8_copyload + $10;
+ HEAPF64[$y17 >> 3] = $add18;
+ if ($5) {
+ label = 7;
+ break;
+ } else {
+ $anchor_0 = 0;
+ label = 9;
+ break;
+ }
+ case 7:
+ $flags = $job + 152 | 0;
+ $11 = HEAP32[$flags >> 2] | 0;
+ $and = $11 & 4;
+ $tobool20 = ($and | 0) == 0;
+ if ($tobool20) {
+ label = 8;
+ break;
+ } else {
+ $anchor_0 = 0;
+ label = 9;
+ break;
+ }
+ case 8:
+ $call = _initAnchor($job, $env, $data, $pts, $saved, 1) | 0;
+ $anchor_0 = $call;
+ label = 9;
+ break;
+ case 9:
+ $style = $tbl + 104 | 0;
+ $12 = HEAP8[$style] | 0;
+ $and24 = $12 & 2;
+ $tobool25 = $and24 << 24 >> 24 == 0;
+ if ($tobool25) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $pencolor = $tbl + 24 | 0;
+ $13 = HEAP32[$pencolor >> 2] | 0;
+ $tobool28 = ($13 | 0) == 0;
+ $_ = $tobool28 ? 121304 : $13;
+ $arrayidx = $AF | 0;
+ $14 = $AF;
+ HEAP32[$14 >> 2] = HEAP32[$0 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$0 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$0 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$0 + 12 >> 2] | 0;
+ $arrayidx32 = $AF + 32 | 0;
+ $15 = $arrayidx32;
+ $16 = $UR;
+ HEAP32[$15 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ $x35 = $arrayidx32 | 0;
+ $17 = +HEAPF64[$x35 >> 3];
+ $x37 = $AF + 16 | 0;
+ HEAPF64[$x37 >> 3] = $17;
+ $y39 = $AF + 8 | 0;
+ $18 = +HEAPF64[$y39 >> 3];
+ $y41 = $AF + 24 | 0;
+ HEAPF64[$y41 >> 3] = $18;
+ $x43 = $AF | 0;
+ $19 = +HEAPF64[$x43 >> 3];
+ $x45 = $AF + 48 | 0;
+ HEAPF64[$x45 >> 3] = $19;
+ $y47 = $AF + 40 | 0;
+ $20 = +HEAPF64[$y47 >> 3];
+ $y49 = $AF + 56 | 0;
+ HEAPF64[$y49 >> 3] = $20;
+ $bgcolor = $tbl + 20 | 0;
+ $21 = HEAP32[$bgcolor >> 2] | 0;
+ $22 = HEAP8[$style] | 0;
+ $conv52 = $22 & 255;
+ $cmp = ($21 | 0) != 0;
+ $conv55 = $cmp & 1;
+ _round_corners($job, $21, $_, $arrayidx, 4, $conv52, $conv55);
+ label = 15;
+ break;
+ case 11:
+ $bgcolor58 = $tbl + 20 | 0;
+ $23 = HEAP32[$bgcolor58 >> 2] | 0;
+ $tobool59 = ($23 | 0) == 0;
+ if ($tobool59) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _doFill($job, $23, $pts);
+ label = 13;
+ break;
+ case 13:
+ $border = $tbl + 29 | 0;
+ $24 = HEAP8[$border] | 0;
+ $tobool65 = $24 << 24 >> 24 == 0;
+ if ($tobool65) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $pencolor68 = $tbl + 24 | 0;
+ $25 = HEAP32[$pencolor68 >> 2] | 0;
+ $conv71 = $24 & 255;
+ _doBorder($job, $25, $conv71, $pts);
+ label = 15;
+ break;
+ case 15:
+ $26 = HEAP32[$2 >> 2] | 0;
+ $tobool7439 = ($26 | 0) == 0;
+ if ($tobool7439) {
+ label = 17;
+ break;
+ } else {
+ $cells_040 = $2;
+ $27 = $26;
+ label = 16;
+ break;
+ }
+ case 16:
+ _emit_html_cell($job, $27, $env);
+ $incdec_ptr = $cells_040 + 4 | 0;
+ $28 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool74 = ($28 | 0) == 0;
+ if ($tobool74) {
+ label = 17;
+ break;
+ } else {
+ $cells_040 = $incdec_ptr;
+ $27 = $28;
+ label = 16;
+ break;
+ }
+ case 17:
+ $tobool75 = ($anchor_0 | 0) == 0;
+ if ($tobool75) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ _endAnchor($job, $saved, 1);
+ label = 19;
+ break;
+ case 19:
+ if ($5) {
+ label = 20;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 20:
+ $flags80 = $job + 152 | 0;
+ $29 = HEAP32[$flags80 >> 2] | 0;
+ $and81 = $29 & 4;
+ $tobool82 = ($and81 | 0) == 0;
+ if ($tobool82) {
+ label = 23;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $call85 = _initAnchor($job, $env, $data, $pts, $saved, 0) | 0;
+ $tobool86 = ($call85 | 0) == 0;
+ if ($tobool86) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ _endAnchor($job, $saved, 0);
+ label = 23;
+ break;
+ case 23:
+ $30 = HEAP32[$font >> 2] | 0;
+ $tobool91 = ($30 | 0) == 0;
+ if ($tobool91) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ _popFontInfo($env, 20296);
+ label = 25;
+ break;
+ case 25:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_html_txt($job, $tp, $env) {
+ $job = $job | 0;
+ $tp = $tp | 0;
+ $env = $env | 0;
+ var $p = 0, $nparas = 0, $0 = 0, $cmp = 0, $box = 0, $x = 0, $1 = 0.0, $x3 = 0, $2 = 0.0, $sub = 0.0, $div = 0.0, $x4 = 0, $3 = 0.0, $add = 0.0, $div11 = 0.0, $add12 = 0.0, $x13 = 0, $y = 0, $4 = 0.0, $y17 = 0, $5 = 0.0, $y20 = 0, $6 = 0.0, $add21 = 0.0, $div22 = 0.0, $add23 = 0.0, $y24 = 0, $7 = 0, $conv26 = 0, $paras = 0, $8 = 0, $finfo = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p = __stackBase__ | 0;
+ $nparas = $tp + 4 | 0;
+ $0 = HEAP16[$nparas >> 1] | 0;
+ $cmp = $0 << 16 >> 16 < 1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $box = $tp + 8 | 0;
+ $x = $tp + 24 | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $x3 = $box | 0;
+ $2 = +HEAPF64[$x3 >> 3];
+ $sub = $1 - $2;
+ $div = $sub * .5;
+ $x4 = $env | 0;
+ $3 = +HEAPF64[$x4 >> 3];
+ $add = $1 + $2;
+ $div11 = $add * .5;
+ $add12 = $3 + $div11;
+ $x13 = $p | 0;
+ HEAPF64[$x13 >> 3] = $add12;
+ $y = $env + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y17 = $tp + 32 | 0;
+ $5 = +HEAPF64[$y17 >> 3];
+ $y20 = $tp + 16 | 0;
+ $6 = +HEAPF64[$y20 >> 3];
+ $add21 = $5 + $6;
+ $div22 = $add21 * .5;
+ $add23 = $4 + $div22;
+ $y24 = $p + 8 | 0;
+ HEAPF64[$y24 >> 3] = $add23;
+ $7 = HEAP16[$nparas >> 1] | 0;
+ $conv26 = $7 << 16 >> 16;
+ $paras = $tp | 0;
+ $8 = HEAP32[$paras >> 2] | 0;
+ $finfo = $env + 16 | 0;
+ _emit_htextparas($job, $conv26, $8, $p, $div, $finfo, $box);
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _freeObj($job) {
+ $job = $job | 0;
+ var $0 = 0;
+ $0 = HEAP32[$job + 16 >> 2] | 0;
+ HEAP32[$0 + 160 >> 2] = 0;
+ HEAP32[$0 + 180 >> 2] = 0;
+ HEAP32[$0 + 196 >> 2] = 0;
+ HEAP32[$0 + 164 >> 2] = 0;
+ _pop_obj_state($job);
+ return;
+}
+function _free_html_font($fp) {
+ $fp = $fp | 0;
+ var $cnt = 0, $0 = 0, $dec = 0, $cmp = 0, $name = 0, $1 = 0, $tobool = 0, $color = 0, $2 = 0, $tobool4 = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cnt = $fp + 12 | 0;
+ $0 = HEAP32[$cnt >> 2] | 0;
+ $dec = $0 - 1 | 0;
+ HEAP32[$cnt >> 2] = $dec;
+ $cmp = ($dec | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $name = $fp | 0;
+ $1 = HEAP32[$name >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _free($1);
+ label = 5;
+ break;
+ case 5:
+ $color = $fp + 4 | 0;
+ $2 = HEAP32[$color >> 2] | 0;
+ $tobool4 = ($2 | 0) == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _free($2);
+ label = 7;
+ break;
+ case 7:
+ $3 = $fp;
+ _free($3);
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _free_html_data($dp) {
+ $dp = $dp | 0;
+ _free(HEAP32[$dp >> 2] | 0);
+ _free(HEAP32[$dp + 4 >> 2] | 0);
+ _free(HEAP32[$dp + 8 >> 2] | 0);
+ _free(HEAP32[$dp + 16 >> 2] | 0);
+ _free(HEAP32[$dp + 12 >> 2] | 0);
+ _free(HEAP32[$dp + 20 >> 2] | 0);
+ _free(HEAP32[$dp + 24 >> 2] | 0);
+ return;
+}
+function _free_html_text($t) {
+ $t = $t | 0;
+ var $tobool = 0, $paras = 0, $nparas = 0, $0 = 0, $cmp23 = 0, $1 = 0, $i_025 = 0, $tl_024 = 0, $nitems = 0, $2 = 0, $cmp419 = 0, $items = 0, $3 = 0, $j_021 = 0, $ti_020 = 0, $str = 0, $4 = 0, $tobool7 = 0, $font = 0, $5 = 0, $tobool11 = 0, $layout = 0, $6 = 0, $tobool15 = 0, $free_layout = 0, $7 = 0, $tobool16 = 0, $incdec_ptr = 0, $inc = 0, $8 = 0, $conv3 = 0, $cmp4 = 0, $incdec_ptr21 = 0, $inc23 = 0, $9 = 0, $conv = 0, $cmp = 0, $10 = 0, $tobool26 = 0, $11 = 0, $12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($t | 0) == 0;
+ if ($tobool) {
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $paras = $t | 0;
+ $nparas = $t + 4 | 0;
+ $0 = HEAP16[$nparas >> 1] | 0;
+ $cmp23 = $0 << 16 >> 16 > 0;
+ if ($cmp23) {
+ label = 4;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[$paras >> 2] | 0;
+ $tl_024 = $1;
+ $i_025 = 0;
+ label = 5;
+ break;
+ case 5:
+ $nitems = $tl_024 + 4 | 0;
+ $2 = HEAP16[$nitems >> 1] | 0;
+ $cmp419 = $2 << 16 >> 16 > 0;
+ if ($cmp419) {
+ label = 6;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 6:
+ $items = $tl_024 | 0;
+ $3 = HEAP32[$items >> 2] | 0;
+ $ti_020 = $3;
+ $j_021 = 0;
+ label = 7;
+ break;
+ case 7:
+ $str = $ti_020 | 0;
+ $4 = HEAP32[$str >> 2] | 0;
+ $tobool7 = ($4 | 0) == 0;
+ if ($tobool7) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _free($4);
+ label = 9;
+ break;
+ case 9:
+ $font = $ti_020 + 16 | 0;
+ $5 = HEAP32[$font >> 2] | 0;
+ $tobool11 = ($5 | 0) == 0;
+ if ($tobool11) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ _free_html_font($5);
+ label = 11;
+ break;
+ case 11:
+ $layout = $ti_020 + 8 | 0;
+ $6 = HEAP32[$layout >> 2] | 0;
+ $tobool15 = ($6 | 0) == 0;
+ if ($tobool15) {
+ label = 14;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $free_layout = $ti_020 + 12 | 0;
+ $7 = HEAP32[$free_layout >> 2] | 0;
+ $tobool16 = ($7 | 0) == 0;
+ if ($tobool16) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ FUNCTION_TABLE_vi[$7 & 1023]($6);
+ label = 14;
+ break;
+ case 14:
+ $incdec_ptr = $ti_020 + 80 | 0;
+ $inc = $j_021 + 1 | 0;
+ $8 = HEAP16[$nitems >> 1] | 0;
+ $conv3 = $8 << 16 >> 16;
+ $cmp4 = ($inc | 0) < ($conv3 | 0);
+ if ($cmp4) {
+ $ti_020 = $incdec_ptr;
+ $j_021 = $inc;
+ label = 7;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $incdec_ptr21 = $tl_024 + 24 | 0;
+ $inc23 = $i_025 + 1 | 0;
+ $9 = HEAP16[$nparas >> 1] | 0;
+ $conv = $9 << 16 >> 16;
+ $cmp = ($inc23 | 0) < ($conv | 0);
+ if ($cmp) {
+ $tl_024 = $incdec_ptr21;
+ $i_025 = $inc23;
+ label = 5;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $10 = HEAP32[$paras >> 2] | 0;
+ $tobool26 = ($10 | 0) == 0;
+ if ($tobool26) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $11 = $10;
+ _free($11);
+ label = 18;
+ break;
+ case 18:
+ $12 = $t;
+ _free($12);
+ label = 19;
+ break;
+ case 19:
+ return;
+ }
+}
+function _free_html_img($ip) {
+ $ip = $ip | 0;
+ _free(HEAP32[$ip + 32 >> 2] | 0);
+ _free($ip);
+ return;
+}
+function _free_html_label($lp, $root) {
+ $lp = $lp | 0;
+ $root = $root | 0;
+ var $kind = 0, $0 = 0, $tbl = 0, $1 = 0, $img = 0, $2 = 0, $txt = 0, $3 = 0, $tobool = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $kind = $lp + 4 | 0;
+ $0 = HEAP8[$kind] | 0;
+ if (($0 << 24 >> 24 | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 3) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $tbl = $lp | 0;
+ $1 = HEAP32[$tbl >> 2] | 0;
+ _free_html_tbl($1);
+ label = 6;
+ break;
+ case 4:
+ $img = $lp;
+ $2 = HEAP32[$img >> 2] | 0;
+ _free_html_img($2);
+ label = 6;
+ break;
+ case 5:
+ $txt = $lp;
+ $3 = HEAP32[$txt >> 2] | 0;
+ _free_html_text($3);
+ label = 6;
+ break;
+ case 6:
+ $tobool = ($root | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $4 = $lp;
+ _free($4);
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _free_html_tbl($tbl) {
+ $tbl = $tbl | 0;
+ var $rc = 0, $0 = 0, $cmp = 0, $rows = 0, $1 = 0, $2 = 0, $call = 0, $heights = 0, $3 = 0, $4 = 0, $widths = 0, $5 = 0, $6 = 0, $7 = 0, $tobool11 = 0, $8 = 0, $cells_012 = 0, $incdec_ptr = 0, $9 = 0, $tobool = 0, $10 = 0, $11 = 0, $font = 0, $12 = 0, $tobool6 = 0, $data = 0, $13 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rc = $tbl + 92 | 0;
+ $0 = HEAP32[$rc >> 2] | 0;
+ $cmp = ($0 | 0) == -1;
+ $rows = $tbl + 76 | 0;
+ $1 = HEAP32[$rows >> 2] | 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $1;
+ $call = _dtclose($2) | 0;
+ label = 7;
+ break;
+ case 4:
+ $heights = $tbl + 84 | 0;
+ $3 = HEAP32[$heights >> 2] | 0;
+ $4 = $3;
+ _free($4);
+ $widths = $tbl + 88 | 0;
+ $5 = HEAP32[$widths >> 2] | 0;
+ $6 = $5;
+ _free($6);
+ $7 = HEAP32[$1 >> 2] | 0;
+ $tobool11 = ($7 | 0) == 0;
+ if ($tobool11) {
+ label = 6;
+ break;
+ } else {
+ $cells_012 = $1;
+ $8 = $7;
+ label = 5;
+ break;
+ }
+ case 5:
+ _free_html_cell($8);
+ $incdec_ptr = $cells_012 + 4 | 0;
+ $9 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool = ($9 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $cells_012 = $incdec_ptr;
+ $8 = $9;
+ label = 5;
+ break;
+ }
+ case 6:
+ $10 = HEAP32[$rows >> 2] | 0;
+ $11 = $10;
+ _free($11);
+ label = 7;
+ break;
+ case 7:
+ $font = $tbl + 100 | 0;
+ $12 = HEAP32[$font >> 2] | 0;
+ $tobool6 = ($12 | 0) == 0;
+ if ($tobool6) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _free_html_font($12);
+ label = 9;
+ break;
+ case 9:
+ $data = $tbl | 0;
+ _free_html_data($data);
+ $13 = $tbl;
+ _free($13);
+ return;
+ }
+}
+function _html_port($n, $pname, $sides) {
+ $n = $n | 0;
+ $pname = $pname | 0;
+ $sides = $sides | 0;
+ var $label = 0, $0 = 0, $u1 = 0, $html = 0, $1 = 0, $kind = 0, $2 = 0, $cmp = 0, $tbl = 0, $3 = 0, $call = 0, $tobool = 0, $box = 0, $sides5 = 0, $4 = 0, $conv6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $label = $n + 120 | 0;
+ $0 = HEAP32[$label >> 2] | 0;
+ $u1 = $0 + 72 | 0;
+ $html = $u1;
+ $1 = HEAP32[$html >> 2] | 0;
+ $kind = $1 + 4 | 0;
+ $2 = HEAP8[$kind] | 0;
+ $cmp = $2 << 24 >> 24 == 2;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tbl = $1 | 0;
+ $3 = HEAP32[$tbl >> 2] | 0;
+ $call = _portToTbl($3, $pname) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $box = $call + 40 | 0;
+ $sides5 = $call + 31 | 0;
+ $4 = HEAP8[$sides5] | 0;
+ $conv6 = $4 & 255;
+ HEAP32[$sides >> 2] = $conv6;
+ $retval_0 = $box;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _portToTbl($tp, $id) {
+ $tp = $tp | 0;
+ $id = $id | 0;
+ var $port = 0, $0 = 0, $tobool = 0, $data = 0, $call = 0, $cmp = 0, $cells4 = 0, $1 = 0, $cells_0 = 0, $2 = 0, $tobool5 = 0, $incdec_ptr = 0, $call6 = 0, $tobool7 = 0, $rv_1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $port = $tp + 4 | 0;
+ $0 = HEAP32[$port >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $data = $tp | 0;
+ $call = _strcasecmp($0, $id) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ $rv_1 = $data;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $cells4 = $tp + 76 | 0;
+ $1 = HEAP32[$cells4 >> 2] | 0;
+ $cells_0 = $1;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP32[$cells_0 >> 2] | 0;
+ $tobool5 = ($2 | 0) == 0;
+ if ($tobool5) {
+ $rv_1 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $incdec_ptr = $cells_0 + 4 | 0;
+ $call6 = _portToCell($2, $id) | 0;
+ $tobool7 = ($call6 | 0) == 0;
+ if ($tobool7) {
+ $cells_0 = $incdec_ptr;
+ label = 5;
+ break;
+ } else {
+ $rv_1 = $call6;
+ label = 7;
+ break;
+ }
+ case 7:
+ return $rv_1 | 0;
+ }
+ return 0;
+}
+function _sizeLinearArray($tbl) {
+ $tbl = $tbl | 0;
+ var $rc = 0, $0 = 0, $add = 0, $mul = 0, $call = 0, $1 = 0, $heights = 0, $cc = 0, $2 = 0, $add1 = 0, $mul2 = 0, $call3 = 0, $3 = 0, $widths = 0, $cells4 = 0, $4 = 0, $5 = 0, $tobool51 = 0, $space41 = 0, $space = 0, $6 = 0, $cells_052 = 0, $rspan = 0, $7 = 0, $conv = 0, $cmp = 0, $y6 = 0, $8 = 0.0, $conv7 = 0, $9 = 0, $conv13 = 0, $sub = 0, $sub16 = 0, $mul17 = 0, $conv18 = 0.0, $sub19 = 0.0, $conv22 = 0.0, $div = 0.0, $conv23 = 0, $cmp24 = 0, $cond = 0, $ht_0 = 0, $cspan = 0, $10 = 0, $conv26 = 0, $cmp27 = 0, $x33 = 0, $11 = 0.0, $conv34 = 0, $12 = 0, $conv42 = 0, $sub43 = 0, $sub46 = 0, $mul47 = 0, $conv48 = 0.0, $sub49 = 0.0, $conv52 = 0.0, $div53 = 0.0, $conv54 = 0, $cmp55 = 0, $cond60 = 0, $wd_0 = 0, $row = 0, $13 = 0, $conv62 = 0, $conv6541 = 0, $14 = 0, $conv6742 = 0, $add6843 = 0, $cmp6944 = 0, $i_045 = 0, $15 = 0, $arrayidx = 0, $16 = 0, $cmp73 = 0, $cond78 = 0, $inc = 0, $17 = 0, $conv65 = 0, $18 = 0, $conv67 = 0, $add68 = 0, $cmp69 = 0, $col = 0, $19 = 0, $conv81 = 0, $conv8446 = 0, $20 = 0, $conv8647 = 0, $add8748 = 0, $cmp8849 = 0, $i_150 = 0, $21 = 0, $arrayidx92 = 0, $22 = 0, $cmp93 = 0, $cond98 = 0, $inc102 = 0, $23 = 0, $conv84 = 0, $24 = 0, $conv86 = 0, $add87 = 0, $cmp88 = 0, $incdec_ptr = 0, $25 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rc = $tbl + 92 | 0;
+ $0 = HEAP32[$rc >> 2] | 0;
+ $add = $0 << 2;
+ $mul = $add + 4 | 0;
+ $call = _zmalloc($mul) | 0;
+ $1 = $call;
+ $heights = $tbl + 84 | 0;
+ HEAP32[$heights >> 2] = $1;
+ $cc = $tbl + 96 | 0;
+ $2 = HEAP32[$cc >> 2] | 0;
+ $add1 = $2 << 2;
+ $mul2 = $add1 + 4 | 0;
+ $call3 = _zmalloc($mul2) | 0;
+ $3 = $call3;
+ $widths = $tbl + 88 | 0;
+ HEAP32[$widths >> 2] = $3;
+ $cells4 = $tbl + 76 | 0;
+ $4 = HEAP32[$cells4 >> 2] | 0;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $tobool51 = ($5 | 0) == 0;
+ if ($tobool51) {
+ label = 15;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $space41 = $tbl + 28 | 0;
+ $space = $tbl + 28 | 0;
+ $cells_052 = $4;
+ $6 = $5;
+ label = 4;
+ break;
+ case 4:
+ $rspan = $6 + 74 | 0;
+ $7 = HEAP16[$rspan >> 1] | 0;
+ $conv = $7 & 65535;
+ $cmp = $7 << 16 >> 16 == 1;
+ $y6 = $6 + 64 | 0;
+ $8 = +HEAPF64[$y6 >> 3];
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $conv7 = ~~$8;
+ $ht_0 = $conv7;
+ label = 7;
+ break;
+ case 6:
+ $9 = HEAP8[$space] | 0;
+ $conv13 = $9 << 24 >> 24;
+ $sub = $conv13 - 1 | 0;
+ $sub16 = $conv - 1 | 0;
+ $mul17 = Math_imul($sub, $sub16);
+ $conv18 = +($mul17 | 0);
+ $sub19 = $8 - $conv18;
+ $conv22 = +($conv | 0);
+ $div = $sub19 / $conv22;
+ $conv23 = ~~$div;
+ $cmp24 = ($conv23 | 0) > 1;
+ $cond = $cmp24 ? $conv23 : 1;
+ $ht_0 = $cond;
+ label = 7;
+ break;
+ case 7:
+ $cspan = $6 + 72 | 0;
+ $10 = HEAP16[$cspan >> 1] | 0;
+ $conv26 = $10 & 65535;
+ $cmp27 = $10 << 16 >> 16 == 1;
+ $x33 = $6 + 56 | 0;
+ $11 = +HEAPF64[$x33 >> 3];
+ if ($cmp27) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $conv34 = ~~$11;
+ $wd_0 = $conv34;
+ label = 10;
+ break;
+ case 9:
+ $12 = HEAP8[$space41] | 0;
+ $conv42 = $12 << 24 >> 24;
+ $sub43 = $conv42 - 1 | 0;
+ $sub46 = $conv26 - 1 | 0;
+ $mul47 = Math_imul($sub43, $sub46);
+ $conv48 = +($mul47 | 0);
+ $sub49 = $11 - $conv48;
+ $conv52 = +($conv26 | 0);
+ $div53 = $sub49 / $conv52;
+ $conv54 = ~~$div53;
+ $cmp55 = ($conv54 | 0) > 1;
+ $cond60 = $cmp55 ? $conv54 : 1;
+ $wd_0 = $cond60;
+ label = 10;
+ break;
+ case 10:
+ $row = $6 + 78 | 0;
+ $13 = HEAP16[$row >> 1] | 0;
+ $conv62 = $13 & 65535;
+ $conv6541 = $13 & 65535;
+ $14 = HEAP16[$rspan >> 1] | 0;
+ $conv6742 = $14 & 65535;
+ $add6843 = $conv6742 + $conv6541 | 0;
+ $cmp6944 = ($conv62 | 0) < ($add6843 | 0);
+ if ($cmp6944) {
+ $i_045 = $conv62;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $15 = HEAP32[$heights >> 2] | 0;
+ $arrayidx = $15 + ($i_045 << 2) | 0;
+ $16 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp73 = ($16 | 0) > ($ht_0 | 0);
+ $cond78 = $cmp73 ? $16 : $ht_0;
+ HEAP32[$arrayidx >> 2] = $cond78;
+ $inc = $i_045 + 1 | 0;
+ $17 = HEAP16[$row >> 1] | 0;
+ $conv65 = $17 & 65535;
+ $18 = HEAP16[$rspan >> 1] | 0;
+ $conv67 = $18 & 65535;
+ $add68 = $conv67 + $conv65 | 0;
+ $cmp69 = ($inc | 0) < ($add68 | 0);
+ if ($cmp69) {
+ $i_045 = $inc;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $col = $6 + 76 | 0;
+ $19 = HEAP16[$col >> 1] | 0;
+ $conv81 = $19 & 65535;
+ $conv8446 = $19 & 65535;
+ $20 = HEAP16[$cspan >> 1] | 0;
+ $conv8647 = $20 & 65535;
+ $add8748 = $conv8647 + $conv8446 | 0;
+ $cmp8849 = ($conv81 | 0) < ($add8748 | 0);
+ if ($cmp8849) {
+ $i_150 = $conv81;
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $21 = HEAP32[$widths >> 2] | 0;
+ $arrayidx92 = $21 + ($i_150 << 2) | 0;
+ $22 = HEAP32[$arrayidx92 >> 2] | 0;
+ $cmp93 = ($22 | 0) > ($wd_0 | 0);
+ $cond98 = $cmp93 ? $22 : $wd_0;
+ HEAP32[$arrayidx92 >> 2] = $cond98;
+ $inc102 = $i_150 + 1 | 0;
+ $23 = HEAP16[$col >> 1] | 0;
+ $conv84 = $23 & 65535;
+ $24 = HEAP16[$cspan >> 1] | 0;
+ $conv86 = $24 & 65535;
+ $add87 = $conv86 + $conv84 | 0;
+ $cmp88 = ($inc102 | 0) < ($add87 | 0);
+ if ($cmp88) {
+ $i_150 = $inc102;
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $incdec_ptr = $cells_052 + 4 | 0;
+ $25 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool = ($25 | 0) == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ $cells_052 = $incdec_ptr;
+ $6 = $25;
+ label = 4;
+ break;
+ }
+ case 15:
+ return;
+ }
+}
+function _nToName($c) {
+ $c = $c | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $call = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = $c >>> 0 < 21;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $arrayidx = 9184 + ($c << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $retval_0 = $0;
+ label = 5;
+ break;
+ case 4:
+ $call = _sprintf(11088, 115528, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $c, tempInt) | 0) | 0;
+ $retval_0 = 11088;
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _setSizes($tbl, $rowg, $colg) {
+ $tbl = $tbl | 0;
+ $rowg = $rowg | 0;
+ $colg = $colg | 0;
+ var $nlist = 0, $0 = 0, $n_0_in22 = 0, $n_023 = 0, $tobool24 = 0, $heights = 0, $n_027 = 0, $prev_026 = 0, $i_025 = 0, $rank = 0, $1 = 0, $sub = 0, $2 = 0, $arrayidx = 0, $3 = 0, $inc = 0, $n_0_in = 0, $n_0 = 0, $tobool = 0, $nlist8 = 0, $4 = 0, $n_1_in16 = 0, $n_117 = 0, $tobool1218 = 0, $widths = 0, $n_121 = 0, $prev_120 = 0, $i_119 = 0, $rank15 = 0, $5 = 0, $sub16 = 0, $6 = 0, $arrayidx17 = 0, $7 = 0, $inc21 = 0, $n_1_in = 0, $n_1 = 0, $tobool12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $rowg + 220 | 0;
+ $0 = HEAP32[$nlist >> 2] | 0;
+ $n_0_in22 = $0 + 168 | 0;
+ $n_023 = HEAP32[$n_0_in22 >> 2] | 0;
+ $tobool24 = ($n_023 | 0) == 0;
+ if ($tobool24) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $heights = $tbl + 84 | 0;
+ $i_025 = 0;
+ $prev_026 = 0;
+ $n_027 = $n_023;
+ label = 4;
+ break;
+ case 4:
+ $rank = $n_027 + 236 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $sub = $1 - $prev_026 | 0;
+ $2 = HEAP32[$heights >> 2] | 0;
+ $arrayidx = $2 + ($i_025 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $sub;
+ $3 = HEAP32[$rank >> 2] | 0;
+ $inc = $i_025 + 1 | 0;
+ $n_0_in = $n_027 + 168 | 0;
+ $n_0 = HEAP32[$n_0_in >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $i_025 = $inc;
+ $prev_026 = $3;
+ $n_027 = $n_0;
+ label = 4;
+ break;
+ }
+ case 5:
+ $nlist8 = $colg + 220 | 0;
+ $4 = HEAP32[$nlist8 >> 2] | 0;
+ $n_1_in16 = $4 + 168 | 0;
+ $n_117 = HEAP32[$n_1_in16 >> 2] | 0;
+ $tobool1218 = ($n_117 | 0) == 0;
+ if ($tobool1218) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $widths = $tbl + 88 | 0;
+ $i_119 = 0;
+ $prev_120 = 0;
+ $n_121 = $n_117;
+ label = 7;
+ break;
+ case 7:
+ $rank15 = $n_121 + 236 | 0;
+ $5 = HEAP32[$rank15 >> 2] | 0;
+ $sub16 = $5 - $prev_120 | 0;
+ $6 = HEAP32[$widths >> 2] | 0;
+ $arrayidx17 = $6 + ($i_119 << 2) | 0;
+ HEAP32[$arrayidx17 >> 2] = $sub16;
+ $7 = HEAP32[$rank15 >> 2] | 0;
+ $inc21 = $i_119 + 1 | 0;
+ $n_1_in = $n_121 + 168 | 0;
+ $n_1 = HEAP32[$n_1_in >> 2] | 0;
+ $tobool12 = ($n_1 | 0) == 0;
+ if ($tobool12) {
+ label = 8;
+ break;
+ } else {
+ $i_119 = $inc21;
+ $prev_120 = $7;
+ $n_121 = $n_1;
+ label = 7;
+ break;
+ }
+ case 8:
+ return;
+ }
+}
+function _makeGraphs($tbl, $rowg, $colg) {
+ $tbl = $tbl | 0;
+ $rowg = $rowg | 0;
+ $colg = $colg | 0;
+ var $cc = 0, $0 = 0, $cmp153 = 0, $1 = 0, $rc = 0, $nlist = 0, $rc19 = 0, $2 = 0, $cmp20149 = 0, $3 = 0, $nlist54 = 0, $lastn_0155 = 0, $i_0154 = 0, $call = 0, $call1 = 0, $4 = 0, $u = 0, $in = 0, $size = 0, $5 = 0, $6 = 0, $add = 0, $mul = 0, $call2 = 0, $7 = 0, $list = 0, $out = 0, $size7 = 0, $8 = 0, $9 = 0, $add9 = 0, $mul10 = 0, $call11 = 0, $10 = 0, $list14 = 0, $tobool = 0, $next = 0, $inc = 0, $11 = 0, $cmp = 0, $lastn_2151 = 0, $i_1150 = 0, $call22 = 0, $call23 = 0, $12 = 0, $u25 = 0, $in26 = 0, $size27 = 0, $13 = 0, $14 = 0, $add29 = 0, $mul30 = 0, $call31 = 0, $15 = 0, $list34 = 0, $out38 = 0, $size39 = 0, $16 = 0, $17 = 0, $add41 = 0, $mul42 = 0, $call43 = 0, $18 = 0, $list46 = 0, $tobool48 = 0, $next51 = 0, $inc57 = 0, $19 = 0, $cmp20 = 0, $_lcssa = 0, $mul60 = 0, $call61 = 0, $20 = 0, $21 = 0, $mul63 = 0, $call64 = 0, $22 = 0, $cells66 = 0, $23 = 0, $24 = 0, $tobool68147 = 0, $25 = 0, $cells_0148 = 0, $x70 = 0, $26 = 0.0, $cspan = 0, $27 = 0, $conv = 0, $sub = 0, $conv71 = 0.0, $add72 = 0.0, $conv75 = 0.0, $div = 0.0, $conv76 = 0, $28 = 0, $cmp80142 = 0, $col = 0, $c_0143 = 0, $29 = 0, $conv83 = 0, $add84 = 0, $arrayidx = 0, $30 = 0, $cmp85 = 0, $_conv76 = 0, $inc96 = 0, $31 = 0, $conv79 = 0, $cmp80 = 0, $y101 = 0, $32 = 0.0, $rspan = 0, $33 = 0, $conv102 = 0, $sub103 = 0, $conv104 = 0.0, $add105 = 0.0, $conv108 = 0.0, $div109 = 0.0, $conv110 = 0, $34 = 0, $cmp114145 = 0, $row = 0, $r_0146 = 0, $35 = 0, $conv117 = 0, $add118 = 0, $arrayidx119 = 0, $36 = 0, $cmp120 = 0, $_conv110 = 0, $inc135 = 0, $37 = 0, $conv113 = 0, $cmp114 = 0, $incdec_ptr = 0, $38 = 0, $tobool68 = 0, $39 = 0, $40 = 0, $tobool143139 = 0, $41 = 0, $42 = 0, $43 = 0, $cells_1140 = 0, $col149 = 0, $44 = 0, $conv150 = 0, $call151 = 0, $call152 = 0, $45 = 0, $conv154 = 0, $cspan155 = 0, $46 = 0, $conv156 = 0, $add157 = 0, $call158 = 0, $call159 = 0, $call160 = 0, $47 = 0, $48 = 0, $cmp164131 = 0, $49 = 0, $conv168 = 0, $50 = 0, $conv163 = 0, $c147_0133 = 0, $x145_0132 = 0, $add169 = 0, $arrayidx170 = 0, $51 = 0, $add171 = 0, $inc173 = 0, $cmp164 = 0, $extract_t = 0, $x145_0_lcssa_off0 = 0, $u176 = 0, $minlen = 0, $52 = 0, $u178 = 0, $out179 = 0, $list180 = 0, $53 = 0, $tobool181 = 0, $54 = 0, $size188 = 0, $55 = 0, $56 = 0, $add189 = 0, $mul190 = 0, $call191 = 0, $size195 = 0, $57 = 0, $58 = 0, $add196 = 0, $mul197 = 0, $call198 = 0, $call191_sink = 0, $59 = 0, $size206 = 0, $60 = 0, $61 = 0, $inc207 = 0, $62 = 0, $arrayidx211 = 0, $63 = 0, $64 = 0, $arrayidx218 = 0, $u221 = 0, $in222 = 0, $list223 = 0, $65 = 0, $tobool224 = 0, $66 = 0, $size231 = 0, $67 = 0, $68 = 0, $add232 = 0, $mul233 = 0, $call234 = 0, $size238 = 0, $69 = 0, $70 = 0, $add239 = 0, $mul240 = 0, $call241 = 0, $call234_sink = 0, $71 = 0, $size249 = 0, $72 = 0, $73 = 0, $inc250 = 0, $74 = 0, $arrayidx254 = 0, $75 = 0, $76 = 0, $arrayidx261 = 0, $row263 = 0, $77 = 0, $conv264 = 0, $call265 = 0, $call266 = 0, $78 = 0, $conv268 = 0, $rspan269 = 0, $79 = 0, $conv270 = 0, $add271 = 0, $call272 = 0, $call273 = 0, $call274 = 0, $80 = 0, $81 = 0, $cmp278135 = 0, $82 = 0, $conv282 = 0, $83 = 0, $conv277 = 0, $r148_0137 = 0, $y146_0136 = 0, $add283 = 0, $arrayidx284 = 0, $84 = 0, $add285 = 0, $inc287 = 0, $cmp278 = 0, $extract_t157 = 0, $y146_0_lcssa_off0 = 0, $u290 = 0, $minlen291 = 0, $85 = 0, $u293 = 0, $out294 = 0, $list295 = 0, $86 = 0, $tobool296 = 0, $87 = 0, $size303 = 0, $88 = 0, $89 = 0, $add304 = 0, $mul305 = 0, $call306 = 0, $size310 = 0, $90 = 0, $91 = 0, $add311 = 0, $mul312 = 0, $call313 = 0, $call306_sink = 0, $92 = 0, $size321 = 0, $93 = 0, $94 = 0, $inc322 = 0, $95 = 0, $arrayidx326 = 0, $96 = 0, $97 = 0, $arrayidx333 = 0, $u336 = 0, $in337 = 0, $list338 = 0, $98 = 0, $tobool339 = 0, $99 = 0, $size346 = 0, $100 = 0, $101 = 0, $add347 = 0, $mul348 = 0, $call349 = 0, $size353 = 0, $102 = 0, $103 = 0, $add354 = 0, $mul355 = 0, $call356 = 0, $call349_sink = 0, $104 = 0, $size364 = 0, $105 = 0, $106 = 0, $inc365 = 0, $107 = 0, $arrayidx369 = 0, $108 = 0, $109 = 0, $arrayidx376 = 0, $incdec_ptr379 = 0, $110 = 0, $tobool143 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cc = $tbl + 96 | 0;
+ $0 = HEAP32[$cc >> 2] | 0;
+ $cmp153 = ($0 | 0) < 0;
+ if ($cmp153) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $colg;
+ $rc = $tbl + 92 | 0;
+ $nlist = $colg + 220 | 0;
+ $i_0154 = 0;
+ $lastn_0155 = 0;
+ label = 6;
+ break;
+ case 4:
+ $rc19 = $tbl + 92 | 0;
+ $2 = HEAP32[$rc19 >> 2] | 0;
+ $cmp20149 = ($2 | 0) < 0;
+ if ($cmp20149) {
+ $_lcssa = $2;
+ label = 14;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = $rowg;
+ $nlist54 = $rowg + 220 | 0;
+ $i_1150 = 0;
+ $lastn_2151 = 0;
+ label = 10;
+ break;
+ case 6:
+ $call = _nToName($i_0154) | 0;
+ $call1 = _agnode($1, $call) | 0;
+ $4 = $call1;
+ $u = $call1 + 24 | 0;
+ $in = $u + 152 | 0;
+ $size = $u + 156 | 0;
+ $5 = $size;
+ HEAP32[$5 >> 2] = 0;
+ $6 = HEAP32[$rc >> 2] | 0;
+ $add = $6 << 2;
+ $mul = $add + 4 | 0;
+ $call2 = _zmalloc($mul) | 0;
+ $7 = $call2;
+ $list = $in;
+ HEAP32[$list >> 2] = $7;
+ $out = $u + 160 | 0;
+ $size7 = $u + 164 | 0;
+ $8 = $size7;
+ HEAP32[$8 >> 2] = 0;
+ $9 = HEAP32[$rc >> 2] | 0;
+ $add9 = $9 << 2;
+ $mul10 = $add9 + 4 | 0;
+ $call11 = _zmalloc($mul10) | 0;
+ $10 = $call11;
+ $list14 = $out;
+ HEAP32[$list14 >> 2] = $10;
+ $tobool = ($lastn_0155 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $next = $lastn_0155 + 168 | 0;
+ HEAP32[$next >> 2] = $4;
+ label = 9;
+ break;
+ case 8:
+ HEAP32[$nlist >> 2] = $4;
+ label = 9;
+ break;
+ case 9:
+ $inc = $i_0154 + 1 | 0;
+ $11 = HEAP32[$cc >> 2] | 0;
+ $cmp = ($inc | 0) > ($11 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $i_0154 = $inc;
+ $lastn_0155 = $4;
+ label = 6;
+ break;
+ }
+ case 10:
+ $call22 = _nToName($i_1150) | 0;
+ $call23 = _agnode($3, $call22) | 0;
+ $12 = $call23;
+ $u25 = $call23 + 24 | 0;
+ $in26 = $u25 + 152 | 0;
+ $size27 = $u25 + 156 | 0;
+ $13 = $size27;
+ HEAP32[$13 >> 2] = 0;
+ $14 = HEAP32[$cc >> 2] | 0;
+ $add29 = $14 << 2;
+ $mul30 = $add29 + 4 | 0;
+ $call31 = _zmalloc($mul30) | 0;
+ $15 = $call31;
+ $list34 = $in26;
+ HEAP32[$list34 >> 2] = $15;
+ $out38 = $u25 + 160 | 0;
+ $size39 = $u25 + 164 | 0;
+ $16 = $size39;
+ HEAP32[$16 >> 2] = 0;
+ $17 = HEAP32[$cc >> 2] | 0;
+ $add41 = $17 << 2;
+ $mul42 = $add41 + 4 | 0;
+ $call43 = _zmalloc($mul42) | 0;
+ $18 = $call43;
+ $list46 = $out38;
+ HEAP32[$list46 >> 2] = $18;
+ $tobool48 = ($lastn_2151 | 0) == 0;
+ if ($tobool48) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $next51 = $lastn_2151 + 168 | 0;
+ HEAP32[$next51 >> 2] = $12;
+ label = 13;
+ break;
+ case 12:
+ HEAP32[$nlist54 >> 2] = $12;
+ label = 13;
+ break;
+ case 13:
+ $inc57 = $i_1150 + 1 | 0;
+ $19 = HEAP32[$rc19 >> 2] | 0;
+ $cmp20 = ($inc57 | 0) > ($19 | 0);
+ if ($cmp20) {
+ $_lcssa = $19;
+ label = 14;
+ break;
+ } else {
+ $i_1150 = $inc57;
+ $lastn_2151 = $12;
+ label = 10;
+ break;
+ }
+ case 14:
+ $mul60 = $_lcssa << 2;
+ $call61 = _zmalloc($mul60) | 0;
+ $20 = $call61;
+ $21 = HEAP32[$cc >> 2] | 0;
+ $mul63 = $21 << 2;
+ $call64 = _zmalloc($mul63) | 0;
+ $22 = $call64;
+ $cells66 = $tbl + 76 | 0;
+ $23 = HEAP32[$cells66 >> 2] | 0;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $tobool68147 = ($24 | 0) == 0;
+ if ($tobool68147) {
+ label = 22;
+ break;
+ } else {
+ $cells_0148 = $23;
+ $25 = $24;
+ label = 15;
+ break;
+ }
+ case 15:
+ $x70 = $25 + 56 | 0;
+ $26 = +HEAPF64[$x70 >> 3];
+ $cspan = $25 + 72 | 0;
+ $27 = HEAP16[$cspan >> 1] | 0;
+ $conv = $27 & 65535;
+ $sub = $conv - 1 | 0;
+ $conv71 = +($sub | 0);
+ $add72 = $26 + $conv71;
+ $conv75 = +($conv | 0);
+ $div = $add72 / $conv75;
+ $conv76 = ~~$div;
+ $28 = HEAP16[$cspan >> 1] | 0;
+ $cmp80142 = $28 << 16 >> 16 == 0;
+ if ($cmp80142) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $col = $25 + 76 | 0;
+ $c_0143 = 0;
+ label = 17;
+ break;
+ case 17:
+ $29 = HEAP16[$col >> 1] | 0;
+ $conv83 = $29 & 65535;
+ $add84 = $conv83 + $c_0143 | 0;
+ $arrayidx = $22 + ($add84 << 2) | 0;
+ $30 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp85 = ($30 | 0) > ($conv76 | 0);
+ $_conv76 = $cmp85 ? $30 : $conv76;
+ HEAP32[$arrayidx >> 2] = $_conv76;
+ $inc96 = $c_0143 + 1 | 0;
+ $31 = HEAP16[$cspan >> 1] | 0;
+ $conv79 = $31 & 65535;
+ $cmp80 = ($inc96 | 0) < ($conv79 | 0);
+ if ($cmp80) {
+ $c_0143 = $inc96;
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $y101 = $25 + 64 | 0;
+ $32 = +HEAPF64[$y101 >> 3];
+ $rspan = $25 + 74 | 0;
+ $33 = HEAP16[$rspan >> 1] | 0;
+ $conv102 = $33 & 65535;
+ $sub103 = $conv102 - 1 | 0;
+ $conv104 = +($sub103 | 0);
+ $add105 = $32 + $conv104;
+ $conv108 = +($conv102 | 0);
+ $div109 = $add105 / $conv108;
+ $conv110 = ~~$div109;
+ $34 = HEAP16[$rspan >> 1] | 0;
+ $cmp114145 = $34 << 16 >> 16 == 0;
+ if ($cmp114145) {
+ label = 21;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $row = $25 + 78 | 0;
+ $r_0146 = 0;
+ label = 20;
+ break;
+ case 20:
+ $35 = HEAP16[$row >> 1] | 0;
+ $conv117 = $35 & 65535;
+ $add118 = $conv117 + $r_0146 | 0;
+ $arrayidx119 = $20 + ($add118 << 2) | 0;
+ $36 = HEAP32[$arrayidx119 >> 2] | 0;
+ $cmp120 = ($36 | 0) > ($conv110 | 0);
+ $_conv110 = $cmp120 ? $36 : $conv110;
+ HEAP32[$arrayidx119 >> 2] = $_conv110;
+ $inc135 = $r_0146 + 1 | 0;
+ $37 = HEAP16[$rspan >> 1] | 0;
+ $conv113 = $37 & 65535;
+ $cmp114 = ($inc135 | 0) < ($conv113 | 0);
+ if ($cmp114) {
+ $r_0146 = $inc135;
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $incdec_ptr = $cells_0148 + 4 | 0;
+ $38 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool68 = ($38 | 0) == 0;
+ if ($tobool68) {
+ label = 22;
+ break;
+ } else {
+ $cells_0148 = $incdec_ptr;
+ $25 = $38;
+ label = 15;
+ break;
+ }
+ case 22:
+ $39 = HEAP32[$cells66 >> 2] | 0;
+ $40 = HEAP32[$39 >> 2] | 0;
+ $tobool143139 = ($40 | 0) == 0;
+ if ($tobool143139) {
+ label = 45;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $41 = $colg;
+ $42 = $rowg;
+ $cells_1140 = $39;
+ $43 = $40;
+ label = 24;
+ break;
+ case 24:
+ $col149 = $43 + 76 | 0;
+ $44 = HEAP16[$col149 >> 1] | 0;
+ $conv150 = $44 & 65535;
+ $call151 = _nToName($conv150) | 0;
+ $call152 = _agfindnode($41, $call151) | 0;
+ $45 = HEAP16[$col149 >> 1] | 0;
+ $conv154 = $45 & 65535;
+ $cspan155 = $43 + 72 | 0;
+ $46 = HEAP16[$cspan155 >> 1] | 0;
+ $conv156 = $46 & 65535;
+ $add157 = $conv156 + $conv154 | 0;
+ $call158 = _nToName($add157) | 0;
+ $call159 = _agfindnode($41, $call158) | 0;
+ $call160 = _agedge($41, $call152, $call159) | 0;
+ $47 = $call160;
+ $48 = HEAP16[$cspan155 >> 1] | 0;
+ $cmp164131 = $48 << 16 >> 16 == 0;
+ if ($cmp164131) {
+ $x145_0_lcssa_off0 = 0;
+ label = 28;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $49 = HEAP16[$col149 >> 1] | 0;
+ $conv168 = $49 & 65535;
+ $50 = HEAP16[$cspan155 >> 1] | 0;
+ $conv163 = $50 & 65535;
+ $x145_0132 = 0;
+ $c147_0133 = 0;
+ label = 26;
+ break;
+ case 26:
+ $add169 = $conv168 + $c147_0133 | 0;
+ $arrayidx170 = $22 + ($add169 << 2) | 0;
+ $51 = HEAP32[$arrayidx170 >> 2] | 0;
+ $add171 = $51 + $x145_0132 | 0;
+ $inc173 = $c147_0133 + 1 | 0;
+ $cmp164 = ($inc173 | 0) < ($conv163 | 0);
+ if ($cmp164) {
+ $x145_0132 = $add171;
+ $c147_0133 = $inc173;
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $extract_t = $add171 & 65535;
+ $x145_0_lcssa_off0 = $extract_t;
+ label = 28;
+ break;
+ case 28:
+ $u176 = $call160 + 24 | 0;
+ $minlen = $u176 + 162 | 0;
+ $52 = $minlen;
+ HEAP16[$52 >> 1] = $x145_0_lcssa_off0;
+ $u178 = $call152 + 24 | 0;
+ $out179 = $u178 + 160 | 0;
+ $list180 = $out179;
+ $53 = HEAP32[$list180 >> 2] | 0;
+ $tobool181 = ($53 | 0) == 0;
+ if ($tobool181) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $54 = $53;
+ $size188 = $u178 + 164 | 0;
+ $55 = $size188;
+ $56 = HEAP32[$55 >> 2] | 0;
+ $add189 = $56 << 2;
+ $mul190 = $add189 + 8 | 0;
+ $call191 = _grealloc($54, $mul190) | 0;
+ $call191_sink = $call191;
+ label = 31;
+ break;
+ case 30:
+ $size195 = $u178 + 164 | 0;
+ $57 = $size195;
+ $58 = HEAP32[$57 >> 2] | 0;
+ $add196 = $58 << 2;
+ $mul197 = $add196 + 8 | 0;
+ $call198 = _gmalloc($mul197) | 0;
+ $call191_sink = $call198;
+ label = 31;
+ break;
+ case 31:
+ $59 = $call191_sink;
+ HEAP32[$list180 >> 2] = $59;
+ $size206 = $u178 + 164 | 0;
+ $60 = $size206;
+ $61 = HEAP32[$60 >> 2] | 0;
+ $inc207 = $61 + 1 | 0;
+ HEAP32[$60 >> 2] = $inc207;
+ $62 = HEAP32[$list180 >> 2] | 0;
+ $arrayidx211 = $62 + ($61 << 2) | 0;
+ HEAP32[$arrayidx211 >> 2] = $47;
+ $63 = HEAP32[$60 >> 2] | 0;
+ $64 = HEAP32[$list180 >> 2] | 0;
+ $arrayidx218 = $64 + ($63 << 2) | 0;
+ HEAP32[$arrayidx218 >> 2] = 0;
+ $u221 = $call159 + 24 | 0;
+ $in222 = $u221 + 152 | 0;
+ $list223 = $in222;
+ $65 = HEAP32[$list223 >> 2] | 0;
+ $tobool224 = ($65 | 0) == 0;
+ if ($tobool224) {
+ label = 33;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $66 = $65;
+ $size231 = $u221 + 156 | 0;
+ $67 = $size231;
+ $68 = HEAP32[$67 >> 2] | 0;
+ $add232 = $68 << 2;
+ $mul233 = $add232 + 8 | 0;
+ $call234 = _grealloc($66, $mul233) | 0;
+ $call234_sink = $call234;
+ label = 34;
+ break;
+ case 33:
+ $size238 = $u221 + 156 | 0;
+ $69 = $size238;
+ $70 = HEAP32[$69 >> 2] | 0;
+ $add239 = $70 << 2;
+ $mul240 = $add239 + 8 | 0;
+ $call241 = _gmalloc($mul240) | 0;
+ $call234_sink = $call241;
+ label = 34;
+ break;
+ case 34:
+ $71 = $call234_sink;
+ HEAP32[$list223 >> 2] = $71;
+ $size249 = $u221 + 156 | 0;
+ $72 = $size249;
+ $73 = HEAP32[$72 >> 2] | 0;
+ $inc250 = $73 + 1 | 0;
+ HEAP32[$72 >> 2] = $inc250;
+ $74 = HEAP32[$list223 >> 2] | 0;
+ $arrayidx254 = $74 + ($73 << 2) | 0;
+ HEAP32[$arrayidx254 >> 2] = $47;
+ $75 = HEAP32[$72 >> 2] | 0;
+ $76 = HEAP32[$list223 >> 2] | 0;
+ $arrayidx261 = $76 + ($75 << 2) | 0;
+ HEAP32[$arrayidx261 >> 2] = 0;
+ $row263 = $43 + 78 | 0;
+ $77 = HEAP16[$row263 >> 1] | 0;
+ $conv264 = $77 & 65535;
+ $call265 = _nToName($conv264) | 0;
+ $call266 = _agfindnode($42, $call265) | 0;
+ $78 = HEAP16[$row263 >> 1] | 0;
+ $conv268 = $78 & 65535;
+ $rspan269 = $43 + 74 | 0;
+ $79 = HEAP16[$rspan269 >> 1] | 0;
+ $conv270 = $79 & 65535;
+ $add271 = $conv270 + $conv268 | 0;
+ $call272 = _nToName($add271) | 0;
+ $call273 = _agfindnode($42, $call272) | 0;
+ $call274 = _agedge($42, $call266, $call273) | 0;
+ $80 = $call274;
+ $81 = HEAP16[$rspan269 >> 1] | 0;
+ $cmp278135 = $81 << 16 >> 16 == 0;
+ if ($cmp278135) {
+ $y146_0_lcssa_off0 = 0;
+ label = 38;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $82 = HEAP16[$row263 >> 1] | 0;
+ $conv282 = $82 & 65535;
+ $83 = HEAP16[$rspan269 >> 1] | 0;
+ $conv277 = $83 & 65535;
+ $y146_0136 = 0;
+ $r148_0137 = 0;
+ label = 36;
+ break;
+ case 36:
+ $add283 = $conv282 + $r148_0137 | 0;
+ $arrayidx284 = $20 + ($add283 << 2) | 0;
+ $84 = HEAP32[$arrayidx284 >> 2] | 0;
+ $add285 = $84 + $y146_0136 | 0;
+ $inc287 = $r148_0137 + 1 | 0;
+ $cmp278 = ($inc287 | 0) < ($conv277 | 0);
+ if ($cmp278) {
+ $y146_0136 = $add285;
+ $r148_0137 = $inc287;
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $extract_t157 = $add285 & 65535;
+ $y146_0_lcssa_off0 = $extract_t157;
+ label = 38;
+ break;
+ case 38:
+ $u290 = $call274 + 24 | 0;
+ $minlen291 = $u290 + 162 | 0;
+ $85 = $minlen291;
+ HEAP16[$85 >> 1] = $y146_0_lcssa_off0;
+ $u293 = $call266 + 24 | 0;
+ $out294 = $u293 + 160 | 0;
+ $list295 = $out294;
+ $86 = HEAP32[$list295 >> 2] | 0;
+ $tobool296 = ($86 | 0) == 0;
+ if ($tobool296) {
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $87 = $86;
+ $size303 = $u293 + 164 | 0;
+ $88 = $size303;
+ $89 = HEAP32[$88 >> 2] | 0;
+ $add304 = $89 << 2;
+ $mul305 = $add304 + 8 | 0;
+ $call306 = _grealloc($87, $mul305) | 0;
+ $call306_sink = $call306;
+ label = 41;
+ break;
+ case 40:
+ $size310 = $u293 + 164 | 0;
+ $90 = $size310;
+ $91 = HEAP32[$90 >> 2] | 0;
+ $add311 = $91 << 2;
+ $mul312 = $add311 + 8 | 0;
+ $call313 = _gmalloc($mul312) | 0;
+ $call306_sink = $call313;
+ label = 41;
+ break;
+ case 41:
+ $92 = $call306_sink;
+ HEAP32[$list295 >> 2] = $92;
+ $size321 = $u293 + 164 | 0;
+ $93 = $size321;
+ $94 = HEAP32[$93 >> 2] | 0;
+ $inc322 = $94 + 1 | 0;
+ HEAP32[$93 >> 2] = $inc322;
+ $95 = HEAP32[$list295 >> 2] | 0;
+ $arrayidx326 = $95 + ($94 << 2) | 0;
+ HEAP32[$arrayidx326 >> 2] = $80;
+ $96 = HEAP32[$93 >> 2] | 0;
+ $97 = HEAP32[$list295 >> 2] | 0;
+ $arrayidx333 = $97 + ($96 << 2) | 0;
+ HEAP32[$arrayidx333 >> 2] = 0;
+ $u336 = $call273 + 24 | 0;
+ $in337 = $u336 + 152 | 0;
+ $list338 = $in337;
+ $98 = HEAP32[$list338 >> 2] | 0;
+ $tobool339 = ($98 | 0) == 0;
+ if ($tobool339) {
+ label = 43;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $99 = $98;
+ $size346 = $u336 + 156 | 0;
+ $100 = $size346;
+ $101 = HEAP32[$100 >> 2] | 0;
+ $add347 = $101 << 2;
+ $mul348 = $add347 + 8 | 0;
+ $call349 = _grealloc($99, $mul348) | 0;
+ $call349_sink = $call349;
+ label = 44;
+ break;
+ case 43:
+ $size353 = $u336 + 156 | 0;
+ $102 = $size353;
+ $103 = HEAP32[$102 >> 2] | 0;
+ $add354 = $103 << 2;
+ $mul355 = $add354 + 8 | 0;
+ $call356 = _gmalloc($mul355) | 0;
+ $call349_sink = $call356;
+ label = 44;
+ break;
+ case 44:
+ $104 = $call349_sink;
+ HEAP32[$list338 >> 2] = $104;
+ $size364 = $u336 + 156 | 0;
+ $105 = $size364;
+ $106 = HEAP32[$105 >> 2] | 0;
+ $inc365 = $106 + 1 | 0;
+ HEAP32[$105 >> 2] = $inc365;
+ $107 = HEAP32[$list338 >> 2] | 0;
+ $arrayidx369 = $107 + ($106 << 2) | 0;
+ HEAP32[$arrayidx369 >> 2] = $80;
+ $108 = HEAP32[$105 >> 2] | 0;
+ $109 = HEAP32[$list338 >> 2] | 0;
+ $arrayidx376 = $109 + ($108 << 2) | 0;
+ HEAP32[$arrayidx376 >> 2] = 0;
+ $incdec_ptr379 = $cells_1140 + 4 | 0;
+ $110 = HEAP32[$incdec_ptr379 >> 2] | 0;
+ $tobool143 = ($110 | 0) == 0;
+ if ($tobool143) {
+ label = 45;
+ break;
+ } else {
+ $cells_1140 = $incdec_ptr379;
+ $43 = $110;
+ label = 24;
+ break;
+ }
+ case 45:
+ _checkChain($colg);
+ _checkChain($rowg);
+ _free($call64);
+ _free($call61);
+ return;
+ }
+}
+function _checkChain($g) {
+ $g = $g | 0;
+ var $nlist = 0, $0 = 0, $h_0_in27 = 0, $h_028 = 0, $tobool29 = 0, $1 = 0, $h_031 = 0, $_pn30 = 0, $2 = 0, $3 = 0, $call = 0, $tobool2 = 0, $h_0_in = 0, $h_0 = 0, $tobool = 0, $call3 = 0, $4 = 0, $u4 = 0, $minlen = 0, $5 = 0, $list = 0, $6 = 0, $tobool6 = 0, $7 = 0, $size = 0, $8 = 0, $add = 0, $mul = 0, $call12 = 0, $size15 = 0, $9 = 0, $add16 = 0, $mul17 = 0, $call18 = 0, $call12_sink = 0, $10 = 0, $size24 = 0, $11 = 0, $inc = 0, $12 = 0, $arrayidx = 0, $13 = 0, $14 = 0, $arrayidx34 = 0, $list37 = 0, $15 = 0, $tobool38 = 0, $16 = 0, $size45 = 0, $17 = 0, $add46 = 0, $mul47 = 0, $call48 = 0, $size52 = 0, $18 = 0, $add53 = 0, $mul54 = 0, $call55 = 0, $call48_sink = 0, $19 = 0, $size63 = 0, $20 = 0, $inc64 = 0, $21 = 0, $arrayidx68 = 0, $22 = 0, $23 = 0, $arrayidx75 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $0 = HEAP32[$nlist >> 2] | 0;
+ $h_0_in27 = $0 + 168 | 0;
+ $h_028 = HEAP32[$h_0_in27 >> 2] | 0;
+ $tobool29 = ($h_028 | 0) == 0;
+ if ($tobool29) {
+ label = 13;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $g;
+ $_pn30 = $0;
+ $h_031 = $h_028;
+ label = 4;
+ break;
+ case 4:
+ $2 = $_pn30;
+ $3 = $h_031;
+ $call = _agfindedge($1, $2, $3) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $h_0_in = $h_031 + 168 | 0;
+ $h_0 = HEAP32[$h_0_in >> 2] | 0;
+ $tobool = ($h_0 | 0) == 0;
+ if ($tobool) {
+ label = 13;
+ break;
+ } else {
+ $_pn30 = $h_031;
+ $h_031 = $h_0;
+ label = 4;
+ break;
+ }
+ case 6:
+ $call3 = _agedge($1, $2, $3) | 0;
+ $4 = $call3;
+ $u4 = $call3 + 24 | 0;
+ $minlen = $u4 + 162 | 0;
+ $5 = $minlen;
+ HEAP16[$5 >> 1] = 0;
+ $list = $_pn30 + 184 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $tobool6 = ($6 | 0) == 0;
+ if ($tobool6) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $7 = $6;
+ $size = $_pn30 + 188 | 0;
+ $8 = HEAP32[$size >> 2] | 0;
+ $add = $8 << 2;
+ $mul = $add + 8 | 0;
+ $call12 = _grealloc($7, $mul) | 0;
+ $call12_sink = $call12;
+ label = 9;
+ break;
+ case 8:
+ $size15 = $_pn30 + 188 | 0;
+ $9 = HEAP32[$size15 >> 2] | 0;
+ $add16 = $9 << 2;
+ $mul17 = $add16 + 8 | 0;
+ $call18 = _gmalloc($mul17) | 0;
+ $call12_sink = $call18;
+ label = 9;
+ break;
+ case 9:
+ $10 = $call12_sink;
+ HEAP32[$list >> 2] = $10;
+ $size24 = $_pn30 + 188 | 0;
+ $11 = HEAP32[$size24 >> 2] | 0;
+ $inc = $11 + 1 | 0;
+ HEAP32[$size24 >> 2] = $inc;
+ $12 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $12 + ($11 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $4;
+ $13 = HEAP32[$size24 >> 2] | 0;
+ $14 = HEAP32[$list >> 2] | 0;
+ $arrayidx34 = $14 + ($13 << 2) | 0;
+ HEAP32[$arrayidx34 >> 2] = 0;
+ $list37 = $h_031 + 176 | 0;
+ $15 = HEAP32[$list37 >> 2] | 0;
+ $tobool38 = ($15 | 0) == 0;
+ if ($tobool38) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $16 = $15;
+ $size45 = $h_031 + 180 | 0;
+ $17 = HEAP32[$size45 >> 2] | 0;
+ $add46 = $17 << 2;
+ $mul47 = $add46 + 8 | 0;
+ $call48 = _grealloc($16, $mul47) | 0;
+ $call48_sink = $call48;
+ label = 12;
+ break;
+ case 11:
+ $size52 = $h_031 + 180 | 0;
+ $18 = HEAP32[$size52 >> 2] | 0;
+ $add53 = $18 << 2;
+ $mul54 = $add53 + 8 | 0;
+ $call55 = _gmalloc($mul54) | 0;
+ $call48_sink = $call55;
+ label = 12;
+ break;
+ case 12:
+ $19 = $call48_sink;
+ HEAP32[$list37 >> 2] = $19;
+ $size63 = $h_031 + 180 | 0;
+ $20 = HEAP32[$size63 >> 2] | 0;
+ $inc64 = $20 + 1 | 0;
+ HEAP32[$size63 >> 2] = $inc64;
+ $21 = HEAP32[$list37 >> 2] | 0;
+ $arrayidx68 = $21 + ($20 << 2) | 0;
+ HEAP32[$arrayidx68 >> 2] = $4;
+ $22 = HEAP32[$size63 >> 2] | 0;
+ $23 = HEAP32[$list37 >> 2] | 0;
+ $arrayidx75 = $23 + ($22 << 2) | 0;
+ HEAP32[$arrayidx75 >> 2] = 0;
+ label = 5;
+ break;
+ case 13:
+ return;
+ }
+}
+function _sizeArray($tbl) {
+ $tbl = $tbl | 0;
+ var $rc = 0, $0 = 0, $cmp = 0, $cc = 0, $1 = 0, $cmp1 = 0, $add = 0, $mul = 0, $call = 0, $2 = 0, $heights = 0, $3 = 0, $add4 = 0, $mul5 = 0, $call6 = 0, $4 = 0, $widths = 0, $call7 = 0, $5 = 0, $call8 = 0, $6 = 0, $call9 = 0, $call10 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rc = $tbl + 92 | 0;
+ $0 = HEAP32[$rc >> 2] | 0;
+ $cmp = ($0 | 0) == 1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cc = $tbl + 96 | 0;
+ $1 = HEAP32[$cc >> 2] | 0;
+ $cmp1 = ($1 | 0) == 1;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ _sizeLinearArray($tbl);
+ label = 6;
+ break;
+ case 5:
+ $add = $0 << 2;
+ $mul = $add + 4 | 0;
+ $call = _zmalloc($mul) | 0;
+ $2 = $call;
+ $heights = $tbl + 84 | 0;
+ HEAP32[$heights >> 2] = $2;
+ $3 = HEAP32[$cc >> 2] | 0;
+ $add4 = $3 << 2;
+ $mul5 = $add4 + 4 | 0;
+ $call6 = _zmalloc($mul5) | 0;
+ $4 = $call6;
+ $widths = $tbl + 88 | 0;
+ HEAP32[$widths >> 2] = $4;
+ $call7 = _agopen(110608, 1) | 0;
+ $5 = $call7;
+ $call8 = _agopen(106400, 1) | 0;
+ $6 = $call8;
+ _makeGraphs($tbl, $5, $6);
+ $call9 = _rank($5, 2, 2147483647) | 0;
+ $call10 = _rank($6, 2, 2147483647) | 0;
+ _setSizes($tbl, $5, $6);
+ _closeGraphs($5, $6);
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _closeGraphs($rowg, $colg) {
+ $rowg = $rowg | 0;
+ $colg = $colg | 0;
+ var $nlist = 0, $n_07 = 0, $tobool8 = 0, $n_09 = 0, $list = 0, $0 = 0, $tobool2 = 0, $1 = 0, $list8 = 0, $2 = 0, $tobool9 = 0, $3 = 0, $next = 0, $n_0 = 0, $tobool = 0, $4 = 0, $5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $colg + 220 | 0;
+ $n_07 = HEAP32[$nlist >> 2] | 0;
+ $tobool8 = ($n_07 | 0) == 0;
+ if ($tobool8) {
+ label = 8;
+ break;
+ } else {
+ $n_09 = $n_07;
+ label = 3;
+ break;
+ }
+ case 3:
+ $list = $n_09 + 176 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $tobool2 = ($0 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = $0;
+ _free($1);
+ label = 5;
+ break;
+ case 5:
+ $list8 = $n_09 + 184 | 0;
+ $2 = HEAP32[$list8 >> 2] | 0;
+ $tobool9 = ($2 | 0) == 0;
+ if ($tobool9) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = $2;
+ _free($3);
+ label = 7;
+ break;
+ case 7:
+ $next = $n_09 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $n_09 = $n_0;
+ label = 3;
+ break;
+ }
+ case 8:
+ $4 = $rowg;
+ _agclose($4);
+ $5 = $colg;
+ _agclose($5);
+ return;
+ }
+}
+function _make_html_label($obj, $lp) {
+ $obj = $obj | 0;
+ $lp = $lp | 0;
+ var $rv = 0, $box = 0, $env = 0, $xb = 0, $buf = 0, $obj1 = 0, $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $root = 0, $3 = 0, $4 = 0, $g2 = 0, $graph = 0, $5 = 0, $6 = 0, $g4 = 0, $head = 0, $7 = 0, $8 = 0, $graph6 = 0, $9 = 0, $g7 = 0, $g8 = 0, $10 = 0, $root9 = 0, $11 = 0, $fontsize = 0, $12 = 0.0, $size = 0, $fontname = 0, $13 = 0, $name = 0, $fontcolor = 0, $14 = 0, $color = 0, $text = 0, $15 = 0, $16 = 0, $charset = 0, $17 = 0, $conv = 0, $call = 0, $tobool = 0, $arraydecay = 0, $html = 0, $call13 = 0, $call14 = 0, $charset16 = 0, $18 = 0, $cond = 0, $call19 = 0, $call21 = 0, $s_0 = 0, $19 = 0, $kind = 0, $20 = 0, $cmp = 0, $tbl = 0, $21 = 0, $pencolor = 0, $22 = 0, $tobool29 = 0, $call30 = 0, $tobool31 = 0, $call33 = 0, $call34 = 0, $23 = 0, $pencolor38 = 0, $24 = 0, $call42 = 0, $25 = 0, $or = 0, $26 = 0, $x = 0, $27 = 0.0, $add = 0.0, $div = 0.0, $y = 0, $28 = 0.0, $add52 = 0.0, $div53 = 0.0, $sub = 0.0, $sub54 = 0.0, $29 = 0, $x58 = 0, $30 = 0.0, $x59 = 0, $31 = 0.0, $sub60 = 0.0, $x61 = 0, $y63 = 0, $32 = 0.0, $y65 = 0, $33 = 0.0, $sub66 = 0.0, $y68 = 0, $txt = 0, $34 = 0, $35 = 0, $x76 = 0, $36 = 0.0, $add77 = 0.0, $div78 = 0.0, $y83 = 0, $37 = 0.0, $add84 = 0.0, $div85 = 0.0, $sub86 = 0.0, $sub87 = 0.0, $38 = 0, $39 = 0, $box91 = 0, $40 = 0, $x93 = 0, $41 = 0.0, $x95 = 0, $42 = 0.0, $sub96 = 0.0, $x98 = 0, $y100 = 0, $43 = 0.0, $y102 = 0, $44 = 0.0, $sub103 = 0.0, $y105 = 0, $45 = 0, $call_c = 0, $46 = 0, $cmp111 = 0, $47 = 0, $call115 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 248 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rv = __stackBase__ | 0;
+ $box = __stackBase__ + 8 | 0;
+ $env = __stackBase__ + 40 | 0;
+ $xb = __stackBase__ + 104 | 0;
+ $buf = __stackBase__ + 120 | 0;
+ $obj1 = $env + 40 | 0;
+ HEAP32[$obj1 >> 2] = $obj;
+ $0 = $obj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 3;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $root = $obj + 32 | 0;
+ $3 = $root;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $g2 = $env + 44 | 0;
+ HEAP32[$g2 >> 2] = $4;
+ label = 6;
+ break;
+ case 4:
+ $graph = $obj + 20 | 0;
+ $5 = $graph;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $g4 = $env + 44 | 0;
+ HEAP32[$g4 >> 2] = $6;
+ label = 6;
+ break;
+ case 5:
+ $head = $obj + 12 | 0;
+ $7 = $head;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $graph6 = $8 + 20 | 0;
+ $9 = HEAP32[$graph6 >> 2] | 0;
+ $g7 = $env + 44 | 0;
+ HEAP32[$g7 >> 2] = $9;
+ label = 6;
+ break;
+ case 6:
+ $g8 = $env + 44 | 0;
+ $10 = HEAP32[$g8 >> 2] | 0;
+ $root9 = $10 + 32 | 0;
+ $11 = HEAP32[$root9 >> 2] | 0;
+ $fontsize = $lp + 16 | 0;
+ $12 = +HEAPF64[$fontsize >> 3];
+ $size = $env + 32 | 0;
+ HEAPF64[$size >> 3] = $12;
+ $fontname = $lp + 4 | 0;
+ $13 = HEAP32[$fontname >> 2] | 0;
+ $name = $env + 16 | 0;
+ HEAP32[$name >> 2] = $13;
+ $fontcolor = $lp + 8 | 0;
+ $14 = HEAP32[$fontcolor >> 2] | 0;
+ $color = $env + 20 | 0;
+ HEAP32[$color >> 2] = $14;
+ $text = $lp | 0;
+ $15 = HEAP32[$text >> 2] | 0;
+ $16 = HEAP32[$g8 >> 2] | 0;
+ $charset = $16 + 155 | 0;
+ $17 = HEAP8[$charset] | 0;
+ $conv = $17 & 255;
+ $call = _parseHTML($15, $rv, $conv) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $arraydecay = $buf | 0;
+ _agxbinit($xb, 128, $arraydecay);
+ $html = $lp + 82 | 0;
+ HEAP8[$html] = 0;
+ $call13 = _nameOf($obj, $xb) | 0;
+ $call14 = _strdup($call13 | 0) | 0;
+ HEAP32[$text >> 2] = $call14;
+ $charset16 = $lp + 12 | 0;
+ $18 = HEAP32[$charset16 >> 2] | 0;
+ $cond = ($18 | 0) == 1;
+ if ($cond) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $call19 = _latin1ToUTF8($call14) | 0;
+ $s_0 = $call19;
+ label = 10;
+ break;
+ case 9:
+ $call21 = _htmlEntityUTF8($call14) | 0;
+ $s_0 = $call21;
+ label = 10;
+ break;
+ case 10:
+ $19 = HEAP32[$text >> 2] | 0;
+ _free($19);
+ HEAP32[$text >> 2] = $s_0;
+ _make_simple_label($11, $lp);
+ _agxbfree($xb);
+ label = 19;
+ break;
+ case 11:
+ $kind = $call + 4 | 0;
+ $20 = HEAP8[$kind] | 0;
+ $cmp = $20 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 12;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 12:
+ $tbl = $call | 0;
+ $21 = HEAP32[$tbl >> 2] | 0;
+ $pencolor = $21 + 24 | 0;
+ $22 = HEAP32[$pencolor >> 2] | 0;
+ $tobool29 = ($22 | 0) == 0;
+ if ($tobool29) {
+ label = 13;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $call30 = _getPenColor($obj) | 0;
+ $tobool31 = ($call30 | 0) == 0;
+ if ($tobool31) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $call33 = _getPenColor($obj) | 0;
+ $call34 = _strdup($call33 | 0) | 0;
+ $23 = HEAP32[$tbl >> 2] | 0;
+ $pencolor38 = $23 + 24 | 0;
+ HEAP32[$pencolor38 >> 2] = $call34;
+ label = 15;
+ break;
+ case 15:
+ $24 = HEAP32[$tbl >> 2] | 0;
+ $call42 = _size_html_tbl($11, $24, 0, $env) | 0;
+ $25 = HEAP32[$rv >> 2] | 0;
+ $or = $25 | $call42;
+ HEAP32[$rv >> 2] = $or;
+ $26 = HEAP32[$tbl >> 2] | 0;
+ $x = $26 + 56 | 0;
+ $27 = +HEAPF64[$x >> 3];
+ $add = $27 + 1.0;
+ $div = $add * .5;
+ $y = $26 + 64 | 0;
+ $28 = +HEAPF64[$y >> 3];
+ $add52 = $28 + 1.0;
+ $div53 = $add52 * .5;
+ $sub = -0.0 - $div;
+ $sub54 = -0.0 - $div53;
+ _boxfof($box, $sub, $sub54, $div, $div53);
+ $29 = HEAP32[$tbl >> 2] | 0;
+ _pos_html_tbl($29, $box, 15);
+ $x58 = $box + 16 | 0;
+ $30 = +HEAPF64[$x58 >> 3];
+ $x59 = $box | 0;
+ $31 = +HEAPF64[$x59 >> 3];
+ $sub60 = $30 - $31;
+ $x61 = $lp + 24 | 0;
+ HEAPF64[$x61 >> 3] = $sub60;
+ $y63 = $box + 24 | 0;
+ $32 = +HEAPF64[$y63 >> 3];
+ $y65 = $box + 8 | 0;
+ $33 = +HEAPF64[$y65 >> 3];
+ $sub66 = $32 - $33;
+ $y68 = $lp + 32 | 0;
+ HEAPF64[$y68 >> 3] = $sub66;
+ label = 17;
+ break;
+ case 16:
+ $txt = $call;
+ $34 = HEAP32[$txt >> 2] | 0;
+ _size_html_txt($11, $34, $env);
+ $35 = HEAP32[$txt >> 2] | 0;
+ $x76 = $35 + 24 | 0;
+ $36 = +HEAPF64[$x76 >> 3];
+ $add77 = $36 + 1.0;
+ $div78 = $add77 * .5;
+ $y83 = $35 + 32 | 0;
+ $37 = +HEAPF64[$y83 >> 3];
+ $add84 = $37 + 1.0;
+ $div85 = $add84 * .5;
+ $sub86 = -0.0 - $div78;
+ $sub87 = -0.0 - $div85;
+ _boxfof($box, $sub86, $sub87, $div78, $div85);
+ $38 = $box;
+ $39 = HEAP32[$txt >> 2] | 0;
+ $box91 = $39 + 8 | 0;
+ $40 = $box91;
+ HEAP32[$40 >> 2] = HEAP32[$38 >> 2] | 0;
+ HEAP32[$40 + 4 >> 2] = HEAP32[$38 + 4 >> 2] | 0;
+ HEAP32[$40 + 8 >> 2] = HEAP32[$38 + 8 >> 2] | 0;
+ HEAP32[$40 + 12 >> 2] = HEAP32[$38 + 12 >> 2] | 0;
+ HEAP32[$40 + 16 >> 2] = HEAP32[$38 + 16 >> 2] | 0;
+ HEAP32[$40 + 20 >> 2] = HEAP32[$38 + 20 >> 2] | 0;
+ HEAP32[$40 + 24 >> 2] = HEAP32[$38 + 24 >> 2] | 0;
+ HEAP32[$40 + 28 >> 2] = HEAP32[$38 + 28 >> 2] | 0;
+ $x93 = $box + 16 | 0;
+ $41 = +HEAPF64[$x93 >> 3];
+ $x95 = $box | 0;
+ $42 = +HEAPF64[$x95 >> 3];
+ $sub96 = $41 - $42;
+ $x98 = $lp + 24 | 0;
+ HEAPF64[$x98 >> 3] = $sub96;
+ $y100 = $box + 24 | 0;
+ $43 = +HEAPF64[$y100 >> 3];
+ $y102 = $box + 8 | 0;
+ $44 = +HEAPF64[$y102 >> 3];
+ $sub103 = $43 - $44;
+ $y105 = $lp + 32 | 0;
+ HEAPF64[$y105 >> 3] = $sub103;
+ label = 17;
+ break;
+ case 17:
+ $45 = $lp + 72 | 0;
+ $call_c = $call;
+ HEAP32[$45 >> 2] = $call_c;
+ $46 = HEAP8[$kind] | 0;
+ $cmp111 = $46 << 24 >> 24 == 1;
+ if ($cmp111) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $47 = HEAP32[$text >> 2] | 0;
+ _free($47);
+ $call115 = _strdup(102544) | 0;
+ HEAP32[$text >> 2] = $call115;
+ label = 19;
+ break;
+ case 19:
+ $retval_0 = HEAP32[$rv >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _boxfof($agg_result, $llx, $lly, $urx, $ury) {
+ $agg_result = $agg_result | 0;
+ $llx = +$llx;
+ $lly = +$lly;
+ $urx = +$urx;
+ $ury = +$ury;
+ HEAPF64[$agg_result >> 3] = $llx;
+ HEAPF64[$agg_result + 8 >> 3] = $lly;
+ HEAPF64[$agg_result + 16 >> 3] = $urx;
+ HEAPF64[$agg_result + 24 >> 3] = $ury;
+ return;
+}
+function _nameOf($obj, $xb) {
+ $obj = $obj | 0;
+ $xb = $xb | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $name = 0, $3 = 0, $4 = 0, $call = 0, $name2 = 0, $5 = 0, $6 = 0, $call3 = 0, $tail = 0, $7 = 0, $8 = 0, $name5 = 0, $9 = 0, $call6 = 0, $head = 0, $10 = 0, $11 = 0, $name7 = 0, $12 = 0, $call8 = 0, $13 = 0, $graph = 0, $14 = 0, $15 = 0, $16 = 0, $and = 0, $tobool = 0, $call12 = 0, $call13 = 0, $ptr = 0, $17 = 0, $eptr = 0, $18 = 0, $cmp = 0, $call14 = 0, $19 = 0, $buf = 0, $20 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $obj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 3;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $name = $obj + 12 | 0;
+ $3 = $name;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $call = _agxbput($xb, $4) | 0;
+ label = 8;
+ break;
+ case 4:
+ $name2 = $obj + 12 | 0;
+ $5 = $name2;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $call3 = _agxbput($xb, $6) | 0;
+ label = 8;
+ break;
+ case 5:
+ $tail = $obj + 16 | 0;
+ $7 = $tail;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $name5 = $8 + 12 | 0;
+ $9 = HEAP32[$name5 >> 2] | 0;
+ $call6 = _agxbput($xb, $9) | 0;
+ $head = $obj + 12 | 0;
+ $10 = $head;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $name7 = $11 + 12 | 0;
+ $12 = HEAP32[$name7 >> 2] | 0;
+ $call8 = _agxbput($xb, $12) | 0;
+ $13 = HEAP32[$10 >> 2] | 0;
+ $graph = $13 + 20 | 0;
+ $14 = HEAP32[$graph >> 2] | 0;
+ $15 = $14;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $and = $16 & 16;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call12 = _agxbput($xb, 138144) | 0;
+ label = 8;
+ break;
+ case 7:
+ $call13 = _agxbput($xb, 135536) | 0;
+ label = 8;
+ break;
+ case 8:
+ $ptr = $xb + 4 | 0;
+ $17 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $xb + 8 | 0;
+ $18 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $17 >>> 0 < $18 >>> 0;
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call14 = _agxbmore($xb, 1) | 0;
+ label = 10;
+ break;
+ case 10:
+ $19 = HEAP32[$ptr >> 2] | 0;
+ HEAP8[$19] = 0;
+ $buf = $xb | 0;
+ $20 = HEAP32[$buf >> 2] | 0;
+ HEAP32[$ptr >> 2] = $20;
+ return $20 | 0;
+ }
+ return 0;
+}
+function _getPenColor($obj) {
+ $obj = $obj | 0;
+ var $call = 0, $cmp = 0, $0 = 0, $tobool = 0, $call1 = 0, $cmp2 = 0, $1 = 0, $tobool7 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agget($obj, 144744) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$call] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = $call;
+ label = 7;
+ break;
+ }
+ case 4:
+ $call1 = _agget($obj, 141696) | 0;
+ $cmp2 = ($call1 | 0) == 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $1 = HEAP8[$call1] | 0;
+ $tobool7 = $1 << 24 >> 24 == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = $call1;
+ label = 7;
+ break;
+ }
+ case 6:
+ $retval_0 = 0;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _size_html_tbl($g, $tbl, $parent, $env) {
+ $g = $g | 0;
+ $tbl = $tbl | 0;
+ $parent = $parent | 0;
+ $env = $env | 0;
+ var $font = 0, $0 = 0, $tobool = 0, $parent2 = 0, $call = 0, $flags = 0, $1 = 0, $and = 0, $tobool3 = 0, $space = 0, $2 = 0, $and10 = 0, $tobool11 = 0, $border = 0, $cc = 0, $3 = 0, $add = 0, $space16 = 0, $4 = 0, $conv17 = 0, $mul = 0, $border19 = 0, $5 = 0, $conv20 = 0, $mul21 = 0, $add22 = 0, $rc = 0, $6 = 0, $add23 = 0, $mul27 = 0, $add32 = 0, $7 = 0, $cmp47 = 0, $widths = 0, $8 = 0, $9 = 0, $wd_0_lcssa = 0, $10 = 0, $cmp3844 = 0, $heights = 0, $11 = 0, $12 = 0, $wd_049 = 0, $i_048 = 0, $arrayidx = 0, $13 = 0, $add35 = 0, $inc = 0, $cmp = 0, $ht_046 = 0, $i_145 = 0, $arrayidx41 = 0, $14 = 0, $add42 = 0, $inc44 = 0, $cmp38 = 0, $ht_0_lcssa = 0, $15 = 0, $and49 = 0, $tobool50 = 0, $width = 0, $16 = 0, $conv53 = 0, $tobool54 = 0, $height = 0, $17 = 0, $tobool57 = 0, $conv56 = 0, $cmp62 = 0, $cmp67 = 0, $or_cond = 0, $call70 = 0, $call72 = 0, $wd_1 = 0, $ht_1 = 0, $rv_1 = 0, $width76 = 0, $18 = 0, $conv77 = 0, $cmp78 = 0, $wd_1_conv77 = 0, $conv83 = 0.0, $x = 0, $height86 = 0, $19 = 0, $conv87 = 0, $cmp88 = 0, $cond96 = 0, $conv97 = 0.0, $y = 0, $20 = 0, $tobool102 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $font = $tbl + 100 | 0;
+ $0 = HEAP32[$font >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _pushFontInfo($env, $0, 4184);
+ label = 4;
+ break;
+ case 4:
+ $parent2 = $tbl + 72 | 0;
+ HEAP32[$parent2 >> 2] = $parent;
+ $call = _processTbl($g, $tbl, $env) | 0;
+ $flags = $tbl + 32 | 0;
+ $1 = HEAP16[$flags >> 1] | 0;
+ $and = $1 & 128;
+ $tobool3 = $and << 16 >> 16 == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $space = $tbl + 28 | 0;
+ HEAP8[$space] = 2;
+ label = 6;
+ break;
+ case 6:
+ $2 = HEAP16[$flags >> 1] | 0;
+ $and10 = $2 & 32;
+ $tobool11 = $and10 << 16 >> 16 == 0;
+ if ($tobool11) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $border = $tbl + 29 | 0;
+ HEAP8[$border] = 1;
+ label = 8;
+ break;
+ case 8:
+ _sizeArray($tbl);
+ $cc = $tbl + 96 | 0;
+ $3 = HEAP32[$cc >> 2] | 0;
+ $add = $3 + 1 | 0;
+ $space16 = $tbl + 28 | 0;
+ $4 = HEAP8[$space16] | 0;
+ $conv17 = $4 << 24 >> 24;
+ $mul = Math_imul($conv17, $add);
+ $border19 = $tbl + 29 | 0;
+ $5 = HEAP8[$border19] | 0;
+ $conv20 = $5 & 255;
+ $mul21 = $conv20 << 1;
+ $add22 = $mul21 + $mul | 0;
+ $rc = $tbl + 92 | 0;
+ $6 = HEAP32[$rc >> 2] | 0;
+ $add23 = $6 + 1 | 0;
+ $mul27 = Math_imul($add23, $conv17);
+ $add32 = $mul27 + $mul21 | 0;
+ $7 = HEAP32[$cc >> 2] | 0;
+ $cmp47 = ($7 | 0) > 0;
+ if ($cmp47) {
+ label = 9;
+ break;
+ } else {
+ $wd_0_lcssa = $add22;
+ label = 10;
+ break;
+ }
+ case 9:
+ $widths = $tbl + 88 | 0;
+ $8 = HEAP32[$widths >> 2] | 0;
+ $9 = HEAP32[$cc >> 2] | 0;
+ $i_048 = 0;
+ $wd_049 = $add22;
+ label = 12;
+ break;
+ case 10:
+ $10 = HEAP32[$rc >> 2] | 0;
+ $cmp3844 = ($10 | 0) > 0;
+ if ($cmp3844) {
+ label = 11;
+ break;
+ } else {
+ $ht_0_lcssa = $add32;
+ label = 14;
+ break;
+ }
+ case 11:
+ $heights = $tbl + 84 | 0;
+ $11 = HEAP32[$heights >> 2] | 0;
+ $12 = HEAP32[$rc >> 2] | 0;
+ $i_145 = 0;
+ $ht_046 = $add32;
+ label = 13;
+ break;
+ case 12:
+ $arrayidx = $8 + ($i_048 << 2) | 0;
+ $13 = HEAP32[$arrayidx >> 2] | 0;
+ $add35 = $13 + $wd_049 | 0;
+ $inc = $i_048 + 1 | 0;
+ $cmp = ($inc | 0) < ($9 | 0);
+ if ($cmp) {
+ $i_048 = $inc;
+ $wd_049 = $add35;
+ label = 12;
+ break;
+ } else {
+ $wd_0_lcssa = $add35;
+ label = 10;
+ break;
+ }
+ case 13:
+ $arrayidx41 = $11 + ($i_145 << 2) | 0;
+ $14 = HEAP32[$arrayidx41 >> 2] | 0;
+ $add42 = $14 + $ht_046 | 0;
+ $inc44 = $i_145 + 1 | 0;
+ $cmp38 = ($inc44 | 0) < ($12 | 0);
+ if ($cmp38) {
+ $i_145 = $inc44;
+ $ht_046 = $add42;
+ label = 13;
+ break;
+ } else {
+ $ht_0_lcssa = $add42;
+ label = 14;
+ break;
+ }
+ case 14:
+ $15 = HEAP16[$flags >> 1] | 0;
+ $and49 = $15 & 1;
+ $tobool50 = $and49 << 16 >> 16 == 0;
+ if ($tobool50) {
+ $rv_1 = $call;
+ $ht_1 = $ht_0_lcssa;
+ $wd_1 = $wd_0_lcssa;
+ label = 20;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $width = $tbl + 34 | 0;
+ $16 = HEAP16[$width >> 1] | 0;
+ $conv53 = $16 & 65535;
+ $tobool54 = $16 << 16 >> 16 == 0;
+ if ($tobool54) {
+ label = 19;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $height = $tbl + 36 | 0;
+ $17 = HEAP16[$height >> 1] | 0;
+ $tobool57 = $17 << 16 >> 16 == 0;
+ if ($tobool57) {
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $conv56 = $17 & 65535;
+ $cmp62 = ($conv53 | 0) < ($wd_0_lcssa | 0);
+ $cmp67 = ($conv56 | 0) < ($ht_0_lcssa | 0);
+ $or_cond = $cmp62 | $cmp67;
+ if ($or_cond) {
+ label = 18;
+ break;
+ } else {
+ $rv_1 = $call;
+ $ht_1 = 0;
+ $wd_1 = 0;
+ label = 20;
+ break;
+ }
+ case 18:
+ $call70 = _agerr(0, 161096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $rv_1 = 1;
+ $ht_1 = 0;
+ $wd_1 = 0;
+ label = 20;
+ break;
+ case 19:
+ $call72 = _agerr(0, 157376, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $rv_1 = 1;
+ $ht_1 = $ht_0_lcssa;
+ $wd_1 = $wd_0_lcssa;
+ label = 20;
+ break;
+ case 20:
+ $width76 = $tbl + 34 | 0;
+ $18 = HEAP16[$width76 >> 1] | 0;
+ $conv77 = $18 & 65535;
+ $cmp78 = ($wd_1 | 0) > ($conv77 | 0);
+ $wd_1_conv77 = $cmp78 ? $wd_1 : $conv77;
+ $conv83 = +($wd_1_conv77 | 0);
+ $x = $tbl + 56 | 0;
+ HEAPF64[$x >> 3] = $conv83;
+ $height86 = $tbl + 36 | 0;
+ $19 = HEAP16[$height86 >> 1] | 0;
+ $conv87 = $19 & 65535;
+ $cmp88 = ($ht_1 | 0) > ($conv87 | 0);
+ $cond96 = $cmp88 ? $ht_1 : $conv87;
+ $conv97 = +($cond96 | 0);
+ $y = $tbl + 64 | 0;
+ HEAPF64[$y >> 3] = $conv97;
+ $20 = HEAP32[$font >> 2] | 0;
+ $tobool102 = ($20 | 0) == 0;
+ if ($tobool102) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ _popFontInfo($env, 4184);
+ label = 22;
+ break;
+ case 22:
+ STACKTOP = __stackBase__;
+ return $rv_1 | 0;
+ }
+ return 0;
+}
+function _size_html_txt($g, $ftxt, $env) {
+ $g = $g | 0;
+ $ftxt = $ftxt | 0;
+ $env = $env | 0;
+ var $lp = 0, $lhf = 0, $tmp = 0, $font = 0, $nparas = 0, $0 = 0, $cmp15 = 0, $paras = 0, $obj = 0, $str10 = 0, $size88 = 0, $name90 = 0, $sz_sroa_0_0__idx = 0, $yoffset_layout = 0, $yoffset_centerline = 0, $postscript_alias = 0, $layout = 0, $free_layout = 0, $1 = 0, $2 = 0, $name84 = 0, $size67 = 0, $xsize_020 = 0.0, $i_018 = 0, $ysize_017 = 0.0, $curbline_016 = 0.0, $3 = 0, $nitems2 = 0, $4 = 0, $cmp44 = 0, $5 = 0, $maxoffset_09 = 0.0, $width_08 = 0.0, $j_06 = 0, $mxfsize_15 = 0.0, $items = 0, $6 = 0, $str = 0, $7 = 0, $8 = 0, $call = 0, $9 = 0, $items13 = 0, $10 = 0, $font15 = 0, $11 = 0, $tobool = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $bf_val_sext = 0, $tobool21 = 0, $16 = 0, $bf_value = 0, $17 = 0, $18 = 0, $19 = 0, $20 = 0, $21 = 0, $22 = 0, $23 = 0, $cmp36 = 0, $bf_val_sext351 = 0, $24 = 0, $25 = 0, $26 = 0, $27 = 0, $28 = 0, $29 = 0, $30 = 0, $31 = 0, $32 = 0, $33 = 0, $34 = 0, $35 = 0, $items53 = 0, $36 = 0, $font55 = 0, $37 = 0, $size = 0, $38 = 0.0, $cmp56 = 0, $39 = 0.0, $fsize_0 = 0.0, $40 = 0, $items71 = 0, $41 = 0, $font73 = 0, $42 = 0, $name = 0, $43 = 0, $tobool74 = 0, $44 = 0, $45 = 0.0, $46 = 0, $47 = 0, $48 = 0, $49 = 0, $50 = 0, $51 = 0, $fsize_1 = 0.0, $fname_0 = 0, $sz_sroa_0_0_copyload = 0.0, $52 = 0, $items96 = 0, $53 = 0, $str98 = 0, $54 = 0, $55 = 0, $56 = 0, $items102 = 0, $57 = 0, $str104 = 0, $58 = 0, $items107 = 0, $59 = 0, $size109 = 0, $60 = 0.0, $61 = 0, $items112 = 0, $62 = 0, $yoffset_layout114 = 0, $63 = 0.0, $64 = 0, $items117 = 0, $65 = 0, $yoffset_centerline119 = 0, $66 = 0, $67 = 0, $items122 = 0, $68 = 0, $postscript_alias124 = 0, $69 = 0, $70 = 0, $items127 = 0, $71 = 0, $layout129 = 0, $72 = 0, $73 = 0, $items132 = 0, $74 = 0, $free_layout134 = 0, $add = 0.0, $conv137 = 0, $cmp138 = 0, $cond = 0.0, $75 = 0.0, $cmp141 = 0, $_maxoffset_0 = 0.0, $inc = 0, $phitmp = 0.0, $76 = 0, $nitems = 0, $77 = 0, $conv3 = 0, $cmp4 = 0, $_lcssa = 0, $maxoffset_0_lcssa = 0.0, $width_0_lcssa = 0.0, $mxfsize_1_lcssa = 0.0, $size151 = 0, $add152 = 0.0, $sub = 0.0, $sub153 = 0.0, $78 = 0, $lfsize = 0, $79 = 0, $lfsize158 = 0, $80 = 0.0, $add159 = 0.0, $cmp161 = 0, $width_0_xsize_0 = 0.0, $inc170 = 0, $81 = 0, $conv = 0, $cmp = 0, $phitmp25 = 0, $phitmp26 = 0.0, $xsize_0_lcssa = 0.0, $ysize_0_lcssa = 0.0, $mxfsize_0_lcssa = 0.0, $x172 = 0, $82 = 0, $cmp175 = 0, $conv178 = 0, $conv179 = 0.0, $y = 0, $y187 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 120 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $lp = __stackBase__ | 0;
+ $lhf = __stackBase__ + 80 | 0;
+ $tmp = __stackBase__ + 104 | 0;
+ $font = $lp + 16 | 0;
+ HEAP32[$font >> 2] = $lhf;
+ $nparas = $ftxt + 4 | 0;
+ $0 = HEAP16[$nparas >> 1] | 0;
+ $cmp15 = $0 << 16 >> 16 > 0;
+ if ($cmp15) {
+ label = 3;
+ break;
+ } else {
+ $mxfsize_0_lcssa = 0.0;
+ $ysize_0_lcssa = 0.0;
+ $xsize_0_lcssa = 0.0;
+ label = 19;
+ break;
+ }
+ case 3:
+ $paras = $ftxt | 0;
+ $obj = $env + 40 | 0;
+ $str10 = $lp | 0;
+ $size88 = $env + 32 | 0;
+ $name90 = $env + 16 | 0;
+ $sz_sroa_0_0__idx = $tmp | 0;
+ $yoffset_layout = $lp + 40 | 0;
+ $yoffset_centerline = $lp + 48 | 0;
+ $postscript_alias = $lp + 4 | 0;
+ $layout = $lp + 8 | 0;
+ $free_layout = $lp + 12 | 0;
+ $1 = $env + 24 | 0;
+ $2 = $1;
+ $name84 = $env + 16 | 0;
+ $size67 = $env + 32 | 0;
+ $curbline_016 = 0.0;
+ $ysize_017 = 0.0;
+ $i_018 = 0;
+ $xsize_020 = 0.0;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[$paras >> 2] | 0;
+ $nitems2 = $3 + ($i_018 * 24 & -1) + 4 | 0;
+ $4 = HEAP16[$nitems2 >> 1] | 0;
+ $cmp44 = $4 << 16 >> 16 > 0;
+ if ($cmp44) {
+ $mxfsize_15 = 0.0;
+ $j_06 = 0;
+ $width_08 = 0.0;
+ $maxoffset_09 = 0.0;
+ $5 = $3;
+ label = 5;
+ break;
+ } else {
+ $mxfsize_1_lcssa = 0.0;
+ $width_0_lcssa = 0.0;
+ $maxoffset_0_lcssa = 0.0;
+ $_lcssa = $3;
+ label = 17;
+ break;
+ }
+ case 5:
+ $items = $5 + ($i_018 * 24 & -1) | 0;
+ $6 = HEAP32[$items >> 2] | 0;
+ $str = $6 + ($j_06 * 80 & -1) | 0;
+ $7 = HEAP32[$str >> 2] | 0;
+ $8 = HEAP32[$obj >> 2] | 0;
+ $call = _strdup_and_subst_obj($7, $8) | 0;
+ HEAP32[$str10 >> 2] = $call;
+ $9 = HEAP32[$paras >> 2] | 0;
+ $items13 = $9 + ($i_018 * 24 & -1) | 0;
+ $10 = HEAP32[$items13 >> 2] | 0;
+ $font15 = $10 + ($j_06 * 80 & -1) + 16 | 0;
+ $11 = HEAP32[$font15 >> 2] | 0;
+ $tobool = ($11 | 0) == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $12 = $11 + 8 | 0;
+ $13 = $12;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $15 = $14 << 25;
+ $bf_val_sext = $15 >> 25;
+ $tobool21 = ($bf_val_sext | 0) == 0;
+ if ($tobool21) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $16 = HEAP32[$font >> 2] | 0;
+ $bf_value = $bf_val_sext & 127;
+ $17 = $16 + 8 | 0;
+ $18 = $17;
+ $19 = HEAP32[$18 >> 2] | 0;
+ $20 = $19 & -128;
+ $21 = $20 | $bf_value;
+ HEAP32[$18 >> 2] = $21;
+ label = 11;
+ break;
+ case 8:
+ $22 = HEAP32[$2 >> 2] | 0;
+ $23 = $22 << 25;
+ $cmp36 = ($23 | 0) > 0;
+ if ($cmp36) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $bf_val_sext351 = $22 & 127;
+ $24 = HEAP32[$font >> 2] | 0;
+ $25 = $24 + 8 | 0;
+ $26 = $25;
+ $27 = HEAP32[$26 >> 2] | 0;
+ $28 = $27 & -128;
+ $29 = $28 | $bf_val_sext351;
+ HEAP32[$26 >> 2] = $29;
+ label = 11;
+ break;
+ case 10:
+ $30 = HEAP32[$font >> 2] | 0;
+ $31 = $30 + 8 | 0;
+ $32 = $31;
+ $33 = HEAP32[$32 >> 2] | 0;
+ $34 = $33 & -128;
+ HEAP32[$32 >> 2] = $34;
+ label = 11;
+ break;
+ case 11:
+ $35 = HEAP32[$paras >> 2] | 0;
+ $items53 = $35 + ($i_018 * 24 & -1) | 0;
+ $36 = HEAP32[$items53 >> 2] | 0;
+ $font55 = $36 + ($j_06 * 80 & -1) + 16 | 0;
+ $37 = HEAP32[$font55 >> 2] | 0;
+ $size = $37 + 16 | 0;
+ $38 = +HEAPF64[$size >> 3];
+ $cmp56 = $38 > 0.0;
+ if ($cmp56) {
+ $fsize_0 = $38;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $39 = +HEAPF64[$size67 >> 3];
+ $fsize_0 = $39;
+ label = 13;
+ break;
+ case 13:
+ $40 = HEAP32[$paras >> 2] | 0;
+ $items71 = $40 + ($i_018 * 24 & -1) | 0;
+ $41 = HEAP32[$items71 >> 2] | 0;
+ $font73 = $41 + ($j_06 * 80 & -1) + 16 | 0;
+ $42 = HEAP32[$font73 >> 2] | 0;
+ $name = $42 | 0;
+ $43 = HEAP32[$name >> 2] | 0;
+ $tobool74 = ($43 | 0) == 0;
+ if ($tobool74) {
+ label = 14;
+ break;
+ } else {
+ $fname_0 = $43;
+ $fsize_1 = $fsize_0;
+ label = 16;
+ break;
+ }
+ case 14:
+ $44 = HEAP32[$name84 >> 2] | 0;
+ $fname_0 = $44;
+ $fsize_1 = $fsize_0;
+ label = 16;
+ break;
+ case 15:
+ $45 = +HEAPF64[$size88 >> 3];
+ $46 = HEAP32[$name90 >> 2] | 0;
+ $47 = HEAP32[$font >> 2] | 0;
+ $48 = $47 + 8 | 0;
+ $49 = $48;
+ $50 = HEAP32[$49 >> 2] | 0;
+ $51 = $50 & -128;
+ HEAP32[$49 >> 2] = $51;
+ $fname_0 = $46;
+ $fsize_1 = $45;
+ label = 16;
+ break;
+ case 16:
+ _textsize($tmp, $g, $lp, $fname_0, $fsize_1);
+ $sz_sroa_0_0_copyload = +HEAPF64[$sz_sroa_0_0__idx >> 3];
+ $52 = HEAP32[$paras >> 2] | 0;
+ $items96 = $52 + ($i_018 * 24 & -1) | 0;
+ $53 = HEAP32[$items96 >> 2] | 0;
+ $str98 = $53 + ($j_06 * 80 & -1) | 0;
+ $54 = HEAP32[$str98 >> 2] | 0;
+ _free($54);
+ $55 = HEAP32[$str10 >> 2] | 0;
+ $56 = HEAP32[$paras >> 2] | 0;
+ $items102 = $56 + ($i_018 * 24 & -1) | 0;
+ $57 = HEAP32[$items102 >> 2] | 0;
+ $str104 = $57 + ($j_06 * 80 & -1) | 0;
+ HEAP32[$str104 >> 2] = $55;
+ $58 = HEAP32[$paras >> 2] | 0;
+ $items107 = $58 + ($i_018 * 24 & -1) | 0;
+ $59 = HEAP32[$items107 >> 2] | 0;
+ $size109 = $59 + ($j_06 * 80 & -1) + 32 | 0;
+ HEAPF64[$size109 >> 3] = $sz_sroa_0_0_copyload;
+ $60 = +HEAPF64[$yoffset_layout >> 3];
+ $61 = HEAP32[$paras >> 2] | 0;
+ $items112 = $61 + ($i_018 * 24 & -1) | 0;
+ $62 = HEAP32[$items112 >> 2] | 0;
+ $yoffset_layout114 = $62 + ($j_06 * 80 & -1) + 40 | 0;
+ HEAPF64[$yoffset_layout114 >> 3] = $60;
+ $63 = +HEAPF64[$yoffset_centerline >> 3];
+ $64 = HEAP32[$paras >> 2] | 0;
+ $items117 = $64 + ($i_018 * 24 & -1) | 0;
+ $65 = HEAP32[$items117 >> 2] | 0;
+ $yoffset_centerline119 = $65 + ($j_06 * 80 & -1) + 48 | 0;
+ HEAPF64[$yoffset_centerline119 >> 3] = $63;
+ $66 = HEAP32[$postscript_alias >> 2] | 0;
+ $67 = HEAP32[$paras >> 2] | 0;
+ $items122 = $67 + ($i_018 * 24 & -1) | 0;
+ $68 = HEAP32[$items122 >> 2] | 0;
+ $postscript_alias124 = $68 + ($j_06 * 80 & -1) + 4 | 0;
+ HEAP32[$postscript_alias124 >> 2] = $66;
+ $69 = HEAP32[$layout >> 2] | 0;
+ $70 = HEAP32[$paras >> 2] | 0;
+ $items127 = $70 + ($i_018 * 24 & -1) | 0;
+ $71 = HEAP32[$items127 >> 2] | 0;
+ $layout129 = $71 + ($j_06 * 80 & -1) + 8 | 0;
+ HEAP32[$layout129 >> 2] = $69;
+ $72 = HEAP32[$free_layout >> 2] | 0;
+ $73 = HEAP32[$paras >> 2] | 0;
+ $items132 = $73 + ($i_018 * 24 & -1) | 0;
+ $74 = HEAP32[$items132 >> 2] | 0;
+ $free_layout134 = $74 + ($j_06 * 80 & -1) + 12 | 0;
+ HEAP32[$free_layout134 >> 2] = $72;
+ $add = $width_08 + $sz_sroa_0_0_copyload;
+ $conv137 = ~~$add;
+ $cmp138 = $fsize_1 > $mxfsize_15;
+ $cond = $cmp138 ? $fsize_1 : $mxfsize_15;
+ $75 = +HEAPF64[$yoffset_centerline >> 3];
+ $cmp141 = $75 > $maxoffset_09;
+ $_maxoffset_0 = $cmp141 ? $75 : $maxoffset_09;
+ $inc = $j_06 + 1 | 0;
+ $phitmp = +($conv137 | 0);
+ $76 = HEAP32[$paras >> 2] | 0;
+ $nitems = $76 + ($i_018 * 24 & -1) + 4 | 0;
+ $77 = HEAP16[$nitems >> 1] | 0;
+ $conv3 = $77 << 16 >> 16;
+ $cmp4 = ($inc | 0) < ($conv3 | 0);
+ if ($cmp4) {
+ $mxfsize_15 = $cond;
+ $j_06 = $inc;
+ $width_08 = $phitmp;
+ $maxoffset_09 = $_maxoffset_0;
+ $5 = $76;
+ label = 5;
+ break;
+ } else {
+ $mxfsize_1_lcssa = $cond;
+ $width_0_lcssa = $phitmp;
+ $maxoffset_0_lcssa = $_maxoffset_0;
+ $_lcssa = $76;
+ label = 17;
+ break;
+ }
+ case 17:
+ $size151 = $_lcssa + ($i_018 * 24 & -1) + 8 | 0;
+ HEAPF64[$size151 >> 3] = $width_0_lcssa;
+ $add152 = $ysize_017 + $mxfsize_1_lcssa;
+ $sub = $add152 - $curbline_016;
+ $sub153 = $sub - $maxoffset_0_lcssa;
+ $78 = HEAP32[$paras >> 2] | 0;
+ $lfsize = $78 + ($i_018 * 24 & -1) + 16 | 0;
+ HEAPF64[$lfsize >> 3] = $sub153;
+ $79 = HEAP32[$paras >> 2] | 0;
+ $lfsize158 = $79 + ($i_018 * 24 & -1) + 16 | 0;
+ $80 = +HEAPF64[$lfsize158 >> 3];
+ $add159 = $curbline_016 + $80;
+ $cmp161 = $width_0_lcssa > $xsize_020;
+ $width_0_xsize_0 = $cmp161 ? $width_0_lcssa : $xsize_020;
+ $inc170 = $i_018 + 1 | 0;
+ $81 = HEAP16[$nparas >> 1] | 0;
+ $conv = $81 << 16 >> 16;
+ $cmp = ($inc170 | 0) < ($conv | 0);
+ if ($cmp) {
+ $curbline_016 = $add159;
+ $ysize_017 = $add152;
+ $i_018 = $inc170;
+ $xsize_020 = $width_0_xsize_0;
+ label = 4;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $phitmp25 = ~~$add152;
+ $phitmp26 = +($phitmp25 | 0);
+ $mxfsize_0_lcssa = $mxfsize_1_lcssa;
+ $ysize_0_lcssa = $phitmp26;
+ $xsize_0_lcssa = $width_0_xsize_0;
+ label = 19;
+ break;
+ case 19:
+ $x172 = $ftxt + 24 | 0;
+ HEAPF64[$x172 >> 3] = $xsize_0_lcssa;
+ $82 = HEAP16[$nparas >> 1] | 0;
+ $cmp175 = $82 << 16 >> 16 == 1;
+ if ($cmp175) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $conv178 = ~~$mxfsize_0_lcssa;
+ $conv179 = +($conv178 | 0);
+ $y = $ftxt + 32 | 0;
+ HEAPF64[$y >> 3] = $conv179;
+ label = 22;
+ break;
+ case 21:
+ $y187 = $ftxt + 32 | 0;
+ HEAPF64[$y187 >> 3] = $ysize_0_lcssa;
+ label = 22;
+ break;
+ case 22:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pos_html_tbl($tbl, $pos, $sides) {
+ $tbl = $tbl | 0;
+ $pos = $pos | 0;
+ $sides = $sides | 0;
+ var $cbox = 0, $cells1 = 0, $0 = 0, $parent = 0, $1 = 0, $tobool = 0, $pencolor = 0, $2 = 0, $tobool7 = 0, $pencolor10 = 0, $3 = 0, $tobool11 = 0, $call = 0, $box = 0, $x20 = 0, $4 = 0.0, $conv = 0, $x22 = 0, $5 = 0.0, $x23 = 0, $6 = 0.0, $sub = 0.0, $conv24 = 0.0, $sub25 = 0.0, $conv26 = 0, $cmp = 0, $y31 = 0, $7 = 0.0, $conv32 = 0, $y34 = 0, $8 = 0.0, $y36 = 0, $9 = 0.0, $sub37 = 0.0, $conv38 = 0.0, $sub39 = 0.0, $conv40 = 0, $cmp41 = 0, $flags = 0, $10 = 0, $conv47 = 0, $and = 0, $tobool48 = 0, $cmp50 = 0, $and56 = 0, $add = 0.0, $conv63 = 0.0, $add66 = 0.0, $11 = 0.0, $add70 = 0.0, $div = 0, $conv71 = 0.0, $add74 = 0.0, $12 = 0.0, $sub79 = 0.0, $delx_0 = 0, $cmp81 = 0, $13 = 0, $conv86 = 0, $and87 = 0, $14 = 0.0, $add92 = 0.0, $conv96 = 0.0, $15 = 0.0, $add99 = 0.0, $16 = 0.0, $add103 = 0.0, $div105 = 0, $conv106 = 0.0, $17 = 0.0, $add109 = 0.0, $18 = 0.0, $sub114 = 0.0, $delx_1 = 0, $dely_0 = 0, $19 = 0.0, $border = 0, $20 = 0, $conv121 = 0, $conv122 = 0.0, $add123 = 0.0, $space = 0, $21 = 0, $conv126 = 0.0, $add127 = 0.0, $conv128 = 0, $cc = 0, $22 = 0, $div129 = 0, $mul = 0, $sub131 = 0, $cmp132 = 0, $conv138 = 0.0, $add139 = 0.0, $sub146 = 0.0, $add139_sink = 0.0, $conv140 = 0, $23 = 0, $cmp150101 = 0, $widths = 0, $x_0103 = 0, $i_0102 = 0, $24 = 0, $arrayidx = 0, $25 = 0, $cmp153 = 0, $cond155 = 0, $26 = 0, $conv161 = 0, $add152 = 0, $add156 = 0, $add162 = 0, $add163 = 0, $inc = 0, $27 = 0, $cmp150 = 0, $28 = 0.0, $29 = 0, $conv168 = 0, $conv169 = 0.0, $sub170 = 0.0, $30 = 0, $conv174 = 0.0, $sub175 = 0.0, $conv176 = 0, $rc = 0, $31 = 0, $div177 = 0, $mul179 = 0, $sub180 = 0, $cmp181 = 0, $conv187 = 0.0, $add188 = 0.0, $sub195 = 0.0, $add188_sink = 0.0, $conv189 = 0, $32 = 0, $cmp20198 = 0, $heights = 0, $33 = 0, $tobool22096 = 0, $tobool221 = 0, $widths256 = 0, $x260 = 0, $x274 = 0, $heights277 = 0, $y281 = 0, $y295 = 0, $i_1100 = 0, $y_099 = 0, $34 = 0, $arrayidx204 = 0, $35 = 0, $cmp206 = 0, $cond208 = 0, $36 = 0, $conv214 = 0, $add205_neg = 0, $add209_neg = 0, $add215_neg = 0, $sub216 = 0, $inc218 = 0, $37 = 0, $cmp201 = 0, $38 = 0, $_pn = 0, $incdec_ptr97 = 0, $col = 0, $39 = 0, $cmp224 = 0, $_ = 0, $row = 0, $40 = 0, $cmp229 = 0, $or232 = 0, $mask_1 = 0, $conv235 = 0, $cspan = 0, $41 = 0, $conv236 = 0, $add237 = 0, $42 = 0, $cmp239 = 0, $or242 = 0, $or242_mask_1 = 0, $conv245 = 0, $rspan = 0, $43 = 0, $conv246 = 0, $add247 = 0, $44 = 0, $cmp249 = 0, $or252 = 0, $mask_3 = 0, $col255 = 0, $45 = 0, $idxprom = 0, $46 = 0, $arrayidx257 = 0, $47 = 0, $conv258 = 0.0, $48 = 0, $conv262 = 0, $cspan263 = 0, $49 = 0, $conv264 = 0, $add265 = 0, $50 = 0, $arrayidx267 = 0, $51 = 0, $52 = 0, $conv270 = 0, $sub271 = 0, $conv272 = 0.0, $row275 = 0, $53 = 0, $idxprom276 = 0, $54 = 0, $arrayidx278 = 0, $55 = 0, $conv279 = 0.0, $56 = 0, $conv283 = 0, $rspan284 = 0, $57 = 0, $conv285 = 0, $add286 = 0, $58 = 0, $arrayidx288 = 0, $59 = 0, $60 = 0, $conv291 = 0, $add292 = 0, $conv293 = 0.0, $and296 = 0, $61 = 0, $tobool220 = 0, $conv297 = 0, $sides299 = 0, $62 = 0, $63 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $pos;
+ $pos = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($pos, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cbox = __stackBase__ | 0;
+ $cells1 = $tbl + 76 | 0;
+ $0 = HEAP32[$cells1 >> 2] | 0;
+ $parent = $tbl + 72 | 0;
+ $1 = HEAP32[$parent >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $pencolor = $1 + 24 | 0;
+ $2 = HEAP32[$pencolor >> 2] | 0;
+ $tobool7 = ($2 | 0) == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $pencolor10 = $tbl + 24 | 0;
+ $3 = HEAP32[$pencolor10 >> 2] | 0;
+ $tobool11 = ($3 | 0) == 0;
+ if ($tobool11) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call = _strdup($2 | 0) | 0;
+ HEAP32[$pencolor10 >> 2] = $call;
+ label = 6;
+ break;
+ case 6:
+ $box = $tbl + 40 | 0;
+ $x20 = $tbl + 56 | 0;
+ $4 = +HEAPF64[$x20 >> 3];
+ $conv = ~~$4;
+ $x22 = $pos + 16 | 0;
+ $5 = +HEAPF64[$x22 >> 3];
+ $x23 = $pos | 0;
+ $6 = +HEAPF64[$x23 >> 3];
+ $sub = $5 - $6;
+ $conv24 = +($conv | 0);
+ $sub25 = $sub - $conv24;
+ $conv26 = ~~$sub25;
+ $cmp = ($conv26 | 0) > -1;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ ___assert_func(98192, 1509, 163936, 94448);
+ case 8:
+ $y31 = $tbl + 64 | 0;
+ $7 = +HEAPF64[$y31 >> 3];
+ $conv32 = ~~$7;
+ $y34 = $pos + 24 | 0;
+ $8 = +HEAPF64[$y34 >> 3];
+ $y36 = $pos + 8 | 0;
+ $9 = +HEAPF64[$y36 >> 3];
+ $sub37 = $8 - $9;
+ $conv38 = +($conv32 | 0);
+ $sub39 = $sub37 - $conv38;
+ $conv40 = ~~$sub39;
+ $cmp41 = ($conv40 | 0) > -1;
+ if ($cmp41) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ ___assert_func(98192, 1512, 163936, 90880);
+ case 10:
+ $flags = $tbl + 32 | 0;
+ $10 = HEAP16[$flags >> 1] | 0;
+ $conv47 = $10 & 65535;
+ $and = $conv47 & 1;
+ $tobool48 = ($and | 0) == 0;
+ if ($tobool48) {
+ $dely_0 = $conv40;
+ $delx_1 = $conv26;
+ label = 21;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $cmp50 = ($conv26 | 0) > 0;
+ if ($cmp50) {
+ label = 12;
+ break;
+ } else {
+ $delx_0 = $conv26;
+ label = 16;
+ break;
+ }
+ case 12:
+ $and56 = $conv47 & 6;
+ if (($and56 | 0) == 4) {
+ label = 13;
+ break;
+ } else if (($and56 | 0) == 2) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $add = $6 + $conv38;
+ HEAPF64[$x22 >> 3] = $add;
+ $delx_0 = 0;
+ label = 16;
+ break;
+ case 14:
+ $conv63 = +($conv26 | 0);
+ $add66 = $5 + $conv63;
+ HEAPF64[$x22 >> 3] = $add66;
+ $11 = +HEAPF64[$x23 >> 3];
+ $add70 = $conv63 + $11;
+ HEAPF64[$x23 >> 3] = $add70;
+ $delx_0 = 0;
+ label = 16;
+ break;
+ case 15:
+ $div = ($conv26 | 0) / 2 & -1;
+ $conv71 = +($div | 0);
+ $add74 = $6 + $conv71;
+ HEAPF64[$x23 >> 3] = $add74;
+ $12 = +HEAPF64[$x22 >> 3];
+ $sub79 = $12 - $conv71;
+ HEAPF64[$x22 >> 3] = $sub79;
+ $delx_0 = 0;
+ label = 16;
+ break;
+ case 16:
+ $cmp81 = ($conv40 | 0) > 0;
+ if ($cmp81) {
+ label = 17;
+ break;
+ } else {
+ $dely_0 = $conv40;
+ $delx_1 = $delx_0;
+ label = 21;
+ break;
+ }
+ case 17:
+ $13 = HEAP16[$flags >> 1] | 0;
+ $conv86 = $13 & 65535;
+ $and87 = $conv86 & 24;
+ if (($and87 | 0) == 16) {
+ label = 18;
+ break;
+ } else if (($and87 | 0) == 8) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 18:
+ $14 = +HEAPF64[$y36 >> 3];
+ $add92 = $conv38 + $14;
+ HEAPF64[$y34 >> 3] = $add92;
+ $dely_0 = 0;
+ $delx_1 = $delx_0;
+ label = 21;
+ break;
+ case 19:
+ $conv96 = +($conv40 | 0);
+ $15 = +HEAPF64[$y34 >> 3];
+ $add99 = $conv96 + $15;
+ HEAPF64[$y34 >> 3] = $add99;
+ $16 = +HEAPF64[$y36 >> 3];
+ $add103 = $conv96 + $16;
+ HEAPF64[$y36 >> 3] = $add103;
+ $dely_0 = 0;
+ $delx_1 = $delx_0;
+ label = 21;
+ break;
+ case 20:
+ $div105 = ($conv40 | 0) / 2 & -1;
+ $conv106 = +($div105 | 0);
+ $17 = +HEAPF64[$y36 >> 3];
+ $add109 = $17 + $conv106;
+ HEAPF64[$y36 >> 3] = $add109;
+ $18 = +HEAPF64[$y34 >> 3];
+ $sub114 = $18 - $conv106;
+ HEAPF64[$y34 >> 3] = $sub114;
+ $dely_0 = 0;
+ $delx_1 = $delx_0;
+ label = 21;
+ break;
+ case 21:
+ $19 = +HEAPF64[$x23 >> 3];
+ $border = $tbl + 29 | 0;
+ $20 = HEAP8[$border] | 0;
+ $conv121 = $20 & 255;
+ $conv122 = +($conv121 | 0);
+ $add123 = $19 + $conv122;
+ $space = $tbl + 28 | 0;
+ $21 = HEAP8[$space] | 0;
+ $conv126 = +($21 << 24 >> 24 | 0);
+ $add127 = $conv126 + $add123;
+ $conv128 = ~~$add127;
+ $cc = $tbl + 96 | 0;
+ $22 = HEAP32[$cc >> 2] | 0;
+ $div129 = ($delx_1 | 0) / ($22 | 0) & -1;
+ $mul = Math_imul($div129, $22);
+ $sub131 = $delx_1 - $mul | 0;
+ $cmp132 = ($sub131 | 0) > -1;
+ $conv138 = +($sub131 | 0);
+ if ($cmp132) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $add139 = $conv138 + .5;
+ $add139_sink = $add139;
+ label = 24;
+ break;
+ case 23:
+ $sub146 = $conv138 + -.5;
+ $add139_sink = $sub146;
+ label = 24;
+ break;
+ case 24:
+ $conv140 = ~~$add139_sink;
+ $23 = HEAP32[$cc >> 2] | 0;
+ $cmp150101 = ($23 | 0) < 0;
+ if ($cmp150101) {
+ label = 27;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $widths = $tbl + 88 | 0;
+ $i_0102 = 0;
+ $x_0103 = $conv128;
+ label = 26;
+ break;
+ case 26:
+ $24 = HEAP32[$widths >> 2] | 0;
+ $arrayidx = $24 + ($i_0102 << 2) | 0;
+ $25 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp153 = ($i_0102 | 0) < ($conv140 | 0);
+ $cond155 = $cmp153 & 1;
+ HEAP32[$arrayidx >> 2] = $x_0103;
+ $26 = HEAP8[$space] | 0;
+ $conv161 = $26 << 24 >> 24;
+ $add152 = $x_0103 + $div129 | 0;
+ $add156 = $add152 + $cond155 | 0;
+ $add162 = $add156 + $25 | 0;
+ $add163 = $add162 + $conv161 | 0;
+ $inc = $i_0102 + 1 | 0;
+ $27 = HEAP32[$cc >> 2] | 0;
+ $cmp150 = ($inc | 0) > ($27 | 0);
+ if ($cmp150) {
+ label = 27;
+ break;
+ } else {
+ $i_0102 = $inc;
+ $x_0103 = $add163;
+ label = 26;
+ break;
+ }
+ case 27:
+ $28 = +HEAPF64[$y34 >> 3];
+ $29 = HEAP8[$border] | 0;
+ $conv168 = $29 & 255;
+ $conv169 = +($conv168 | 0);
+ $sub170 = $28 - $conv169;
+ $30 = HEAP8[$space] | 0;
+ $conv174 = +($30 << 24 >> 24 | 0);
+ $sub175 = $sub170 - $conv174;
+ $conv176 = ~~$sub175;
+ $rc = $tbl + 92 | 0;
+ $31 = HEAP32[$rc >> 2] | 0;
+ $div177 = ($dely_0 | 0) / ($31 | 0) & -1;
+ $mul179 = Math_imul($div177, $31);
+ $sub180 = $dely_0 - $mul179 | 0;
+ $cmp181 = ($sub180 | 0) > -1;
+ $conv187 = +($sub180 | 0);
+ if ($cmp181) {
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ $add188 = $conv187 + .5;
+ $add188_sink = $add188;
+ label = 30;
+ break;
+ case 29:
+ $sub195 = $conv187 + -.5;
+ $add188_sink = $sub195;
+ label = 30;
+ break;
+ case 30:
+ $conv189 = ~~$add188_sink;
+ $32 = HEAP32[$rc >> 2] | 0;
+ $cmp20198 = ($32 | 0) < 0;
+ if ($cmp20198) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $heights = $tbl + 84 | 0;
+ $y_099 = $conv176;
+ $i_1100 = 0;
+ label = 34;
+ break;
+ case 32:
+ $33 = HEAP32[$0 >> 2] | 0;
+ $tobool22096 = ($33 | 0) == 0;
+ if ($tobool22096) {
+ label = 39;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $tobool221 = ($sides | 0) == 0;
+ $widths256 = $tbl + 88 | 0;
+ $x260 = $cbox | 0;
+ $x274 = $cbox + 16 | 0;
+ $heights277 = $tbl + 84 | 0;
+ $y281 = $cbox + 24 | 0;
+ $y295 = $cbox + 8 | 0;
+ $_pn = $0;
+ $38 = $33;
+ label = 35;
+ break;
+ case 34:
+ $34 = HEAP32[$heights >> 2] | 0;
+ $arrayidx204 = $34 + ($i_1100 << 2) | 0;
+ $35 = HEAP32[$arrayidx204 >> 2] | 0;
+ $cmp206 = ($i_1100 | 0) < ($conv189 | 0);
+ $cond208 = $cmp206 & 1;
+ HEAP32[$arrayidx204 >> 2] = $y_099;
+ $36 = HEAP8[$space] | 0;
+ $conv214 = $36 << 24 >> 24;
+ $add205_neg = $y_099 - $div177 | 0;
+ $add209_neg = $add205_neg - $cond208 | 0;
+ $add215_neg = $add209_neg - $35 | 0;
+ $sub216 = $add215_neg - $conv214 | 0;
+ $inc218 = $i_1100 + 1 | 0;
+ $37 = HEAP32[$rc >> 2] | 0;
+ $cmp201 = ($inc218 | 0) > ($37 | 0);
+ if ($cmp201) {
+ label = 32;
+ break;
+ } else {
+ $y_099 = $sub216;
+ $i_1100 = $inc218;
+ label = 34;
+ break;
+ }
+ case 35:
+ $incdec_ptr97 = $_pn + 4 | 0;
+ if ($tobool221) {
+ $mask_3 = 0;
+ label = 38;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $col = $38 + 76 | 0;
+ $39 = HEAP16[$col >> 1] | 0;
+ $cmp224 = $39 << 16 >> 16 == 0;
+ $_ = $cmp224 ? 8 : 0;
+ $row = $38 + 78 | 0;
+ $40 = HEAP16[$row >> 1] | 0;
+ $cmp229 = $40 << 16 >> 16 == 0;
+ $or232 = $_ | 4;
+ $mask_1 = $cmp229 ? $or232 : $_;
+ $conv235 = $39 & 65535;
+ $cspan = $38 + 72 | 0;
+ $41 = HEAP16[$cspan >> 1] | 0;
+ $conv236 = $41 & 65535;
+ $add237 = $conv236 + $conv235 | 0;
+ $42 = HEAP32[$cc >> 2] | 0;
+ $cmp239 = ($add237 | 0) == ($42 | 0);
+ $or242 = $mask_1 | 2;
+ $or242_mask_1 = $cmp239 ? $or242 : $mask_1;
+ $conv245 = $40 & 65535;
+ $rspan = $38 + 74 | 0;
+ $43 = HEAP16[$rspan >> 1] | 0;
+ $conv246 = $43 & 65535;
+ $add247 = $conv246 + $conv245 | 0;
+ $44 = HEAP32[$rc >> 2] | 0;
+ $cmp249 = ($add247 | 0) == ($44 | 0);
+ if ($cmp249) {
+ label = 37;
+ break;
+ } else {
+ $mask_3 = $or242_mask_1;
+ label = 38;
+ break;
+ }
+ case 37:
+ $or252 = $or242_mask_1 | 1;
+ $mask_3 = $or252;
+ label = 38;
+ break;
+ case 38:
+ $col255 = $38 + 76 | 0;
+ $45 = HEAP16[$col255 >> 1] | 0;
+ $idxprom = $45 & 65535;
+ $46 = HEAP32[$widths256 >> 2] | 0;
+ $arrayidx257 = $46 + ($idxprom << 2) | 0;
+ $47 = HEAP32[$arrayidx257 >> 2] | 0;
+ $conv258 = +($47 | 0);
+ HEAPF64[$x260 >> 3] = $conv258;
+ $48 = HEAP16[$col255 >> 1] | 0;
+ $conv262 = $48 & 65535;
+ $cspan263 = $38 + 72 | 0;
+ $49 = HEAP16[$cspan263 >> 1] | 0;
+ $conv264 = $49 & 65535;
+ $add265 = $conv264 + $conv262 | 0;
+ $50 = HEAP32[$widths256 >> 2] | 0;
+ $arrayidx267 = $50 + ($add265 << 2) | 0;
+ $51 = HEAP32[$arrayidx267 >> 2] | 0;
+ $52 = HEAP8[$space] | 0;
+ $conv270 = $52 << 24 >> 24;
+ $sub271 = $51 - $conv270 | 0;
+ $conv272 = +($sub271 | 0);
+ HEAPF64[$x274 >> 3] = $conv272;
+ $row275 = $38 + 78 | 0;
+ $53 = HEAP16[$row275 >> 1] | 0;
+ $idxprom276 = $53 & 65535;
+ $54 = HEAP32[$heights277 >> 2] | 0;
+ $arrayidx278 = $54 + ($idxprom276 << 2) | 0;
+ $55 = HEAP32[$arrayidx278 >> 2] | 0;
+ $conv279 = +($55 | 0);
+ HEAPF64[$y281 >> 3] = $conv279;
+ $56 = HEAP16[$row275 >> 1] | 0;
+ $conv283 = $56 & 65535;
+ $rspan284 = $38 + 74 | 0;
+ $57 = HEAP16[$rspan284 >> 1] | 0;
+ $conv285 = $57 & 65535;
+ $add286 = $conv285 + $conv283 | 0;
+ $58 = HEAP32[$heights277 >> 2] | 0;
+ $arrayidx288 = $58 + ($add286 << 2) | 0;
+ $59 = HEAP32[$arrayidx288 >> 2] | 0;
+ $60 = HEAP8[$space] | 0;
+ $conv291 = $60 << 24 >> 24;
+ $add292 = $conv291 + $59 | 0;
+ $conv293 = +($add292 | 0);
+ HEAPF64[$y295 >> 3] = $conv293;
+ $and296 = $mask_3 & $sides;
+ _pos_html_cell($38, $cbox, $and296);
+ $61 = HEAP32[$incdec_ptr97 >> 2] | 0;
+ $tobool220 = ($61 | 0) == 0;
+ if ($tobool220) {
+ label = 39;
+ break;
+ } else {
+ $_pn = $incdec_ptr97;
+ $38 = $61;
+ label = 35;
+ break;
+ }
+ case 39:
+ $conv297 = $sides & 255;
+ $sides299 = $tbl + 31 | 0;
+ HEAP8[$sides299] = $conv297;
+ $62 = $box;
+ $63 = $pos;
+ HEAP32[$62 >> 2] = HEAP32[$63 >> 2] | 0;
+ HEAP32[$62 + 4 >> 2] = HEAP32[$63 + 4 >> 2] | 0;
+ HEAP32[$62 + 8 >> 2] = HEAP32[$63 + 8 >> 2] | 0;
+ HEAP32[$62 + 12 >> 2] = HEAP32[$63 + 12 >> 2] | 0;
+ HEAP32[$62 + 16 >> 2] = HEAP32[$63 + 16 >> 2] | 0;
+ HEAP32[$62 + 20 >> 2] = HEAP32[$63 + 20 >> 2] | 0;
+ HEAP32[$62 + 24 >> 2] = HEAP32[$63 + 24 >> 2] | 0;
+ HEAP32[$62 + 28 >> 2] = HEAP32[$63 + 28 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pos_html_txt($ftxt, $c) {
+ $ftxt = $ftxt | 0;
+ $c = $c | 0;
+ var $nparas = 0, $0 = 0, $cmp7 = 0, $paras = 0, $i_08 = 0, $1 = 0, $just = 0, $2 = 0, $cmp3 = 0, $inc = 0, $3 = 0, $conv = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nparas = $ftxt + 4 | 0;
+ $0 = HEAP16[$nparas >> 1] | 0;
+ $cmp7 = $0 << 16 >> 16 > 0;
+ if ($cmp7) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $paras = $ftxt | 0;
+ $i_08 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$paras >> 2] | 0;
+ $just = $1 + ($i_08 * 24 & -1) + 6 | 0;
+ $2 = HEAP8[$just] | 0;
+ $cmp3 = $2 << 24 >> 24 == 0;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAP8[$just] = $c;
+ label = 6;
+ break;
+ case 6:
+ $inc = $i_08 + 1 | 0;
+ $3 = HEAP16[$nparas >> 1] | 0;
+ $conv = $3 << 16 >> 16;
+ $cmp = ($inc | 0) < ($conv | 0);
+ if ($cmp) {
+ $i_08 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ return;
+ }
+}
+function _pushFontInfo($env, $fp, $savp) {
+ $env = $env | 0;
+ $fp = $fp | 0;
+ $savp = $savp | 0;
+ var $name = 0, $0 = 0, $tobool = 0, $name1 = 0, $1 = 0, $tobool2 = 0, $name10 = 0, $2 = 0, $color = 0, $3 = 0, $tobool13 = 0, $color15 = 0, $4 = 0, $tobool16 = 0, $color25 = 0, $5 = 0, $size = 0, $6 = 0.0, $cmp = 0, $size30 = 0, $7 = 0.0, $cmp31 = 0, $size40 = 0, $8 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $name = $env + 16 | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $name1 = $fp | 0;
+ $1 = HEAP32[$name1 >> 2] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ $name10 = $savp | 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAP32[$name10 >> 2] = $0;
+ $2 = HEAP32[$name1 >> 2] | 0;
+ HEAP32[$name >> 2] = $2;
+ label = 6;
+ break;
+ case 5:
+ HEAP32[$name10 >> 2] = 0;
+ label = 6;
+ break;
+ case 6:
+ $color = $env + 20 | 0;
+ $3 = HEAP32[$color >> 2] | 0;
+ $tobool13 = ($3 | 0) == 0;
+ if ($tobool13) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $color15 = $fp + 4 | 0;
+ $4 = HEAP32[$color15 >> 2] | 0;
+ $tobool16 = ($4 | 0) == 0;
+ $color25 = $savp + 4 | 0;
+ if ($tobool16) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ HEAP32[$color25 >> 2] = $3;
+ $5 = HEAP32[$color15 >> 2] | 0;
+ HEAP32[$color >> 2] = $5;
+ label = 10;
+ break;
+ case 9:
+ HEAP32[$color25 >> 2] = 0;
+ label = 10;
+ break;
+ case 10:
+ $size = $env + 32 | 0;
+ $6 = +HEAPF64[$size >> 3];
+ $cmp = $6 < 0.0;
+ if ($cmp) {
+ label = 14;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $size30 = $fp + 16 | 0;
+ $7 = +HEAPF64[$size30 >> 3];
+ $cmp31 = $7 < 0.0;
+ $size40 = $savp + 16 | 0;
+ if ($cmp31) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAPF64[$size40 >> 3] = $6;
+ $8 = +HEAPF64[$size30 >> 3];
+ HEAPF64[$size >> 3] = $8;
+ label = 14;
+ break;
+ case 13:
+ HEAPF64[$size40 >> 3] = -1.0;
+ label = 14;
+ break;
+ case 14:
+ return;
+ }
+}
+function _popFontInfo($env, $savp) {
+ $env = $env | 0;
+ $savp = $savp | 0;
+ var $name = 0, $0 = 0, $tobool = 0, $name2 = 0, $color = 0, $1 = 0, $tobool3 = 0, $color7 = 0, $size = 0, $2 = 0.0, $cmp = 0, $size12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $name = $savp | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $name2 = $env + 16 | 0;
+ HEAP32[$name2 >> 2] = $0;
+ label = 4;
+ break;
+ case 4:
+ $color = $savp + 4 | 0;
+ $1 = HEAP32[$color >> 2] | 0;
+ $tobool3 = ($1 | 0) == 0;
+ if ($tobool3) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $color7 = $env + 20 | 0;
+ HEAP32[$color7 >> 2] = $1;
+ label = 6;
+ break;
+ case 6:
+ $size = $savp + 16 | 0;
+ $2 = +HEAPF64[$size >> 3];
+ $cmp = $2 < 0.0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $size12 = $env + 32 | 0;
+ HEAPF64[$size12 >> 3] = $2;
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _pos_html_cell($cp, $pos, $sides) {
+ $cp = $cp | 0;
+ $pos = $pos | 0;
+ $sides = $sides | 0;
+ var $cbox = 0, $pencolor = 0, $0 = 0, $tobool = 0, $parent = 0, $1 = 0, $pencolor2 = 0, $2 = 0, $tobool3 = 0, $call = 0, $flags = 0, $3 = 0, $conv = 0, $and = 0, $tobool10 = 0, $oldsz_sroa_0_0__idx6 = 0, $oldsz_sroa_0_0_copyload7 = 0.0, $oldsz_sroa_1_8__idx14 = 0, $oldsz_sroa_1_8_copyload15 = 0.0, $x = 0, $4 = 0.0, $x14 = 0, $5 = 0.0, $sub = 0.0, $sub16 = 0.0, $cmp = 0, $and22 = 0, $add = 0.0, $add31 = 0.0, $6 = 0.0, $add34 = 0.0, $div = 0.0, $add37 = 0.0, $7 = 0.0, $sub41 = 0.0, $y = 0, $8 = 0.0, $y45 = 0, $9 = 0.0, $sub46 = 0.0, $sub48 = 0.0, $cmp49 = 0, $10 = 0, $conv54 = 0, $and55 = 0, $add60 = 0.0, $add66 = 0.0, $11 = 0.0, $add69 = 0.0, $div71 = 0.0, $add74 = 0.0, $12 = 0.0, $sub78 = 0.0, $box83 = 0, $13 = 0, $14 = 0, $conv84 = 0, $sides86 = 0, $x88 = 0, $15 = 0.0, $border = 0, $16 = 0, $conv90 = 0, $conv91 = 0.0, $add92 = 0.0, $pad = 0, $17 = 0, $conv94 = 0, $conv95 = 0.0, $add96 = 0.0, $x98 = 0, $y100 = 0, $18 = 0.0, $19 = 0, $conv103 = 0, $conv104 = 0.0, $add105 = 0.0, $20 = 0, $conv108 = 0, $conv109 = 0.0, $add110 = 0.0, $y112 = 0, $x114 = 0, $21 = 0.0, $22 = 0, $conv117 = 0, $conv118 = 0.0, $sub119 = 0.0, $23 = 0, $conv122 = 0, $conv123 = 0.0, $sub124 = 0.0, $x126 = 0, $y128 = 0, $24 = 0.0, $25 = 0, $conv131 = 0, $conv132 = 0.0, $sub133 = 0.0, $26 = 0, $conv136 = 0, $conv137 = 0.0, $sub138 = 0.0, $y140 = 0, $child = 0, $kind = 0, $27 = 0, $tbl = 0, $28 = 0, $img = 0, $29 = 0, $oldsz_sroa_0_0__idx2 = 0, $oldsz_sroa_0_0_copyload3 = 0.0, $oldsz_sroa_1_8__idx10 = 0, $oldsz_sroa_1_8_copyload11 = 0.0, $30 = 0.0, $31 = 0.0, $sub160 = 0.0, $sub162 = 0.0, $cmp163 = 0, $32 = 0, $conv168 = 0, $and169 = 0, $sub173 = 0.0, $add177 = 0.0, $33 = 0.0, $34 = 0.0, $sub184 = 0.0, $sub186 = 0.0, $cmp187 = 0, $35 = 0, $conv192 = 0, $and193 = 0, $sub197 = 0.0, $add201 = 0.0, $36 = 0, $txt = 0, $37 = 0, $oldsz_sroa_0_0__idx = 0, $oldsz_sroa_0_0_copyload = 0.0, $oldsz_sroa_1_8__idx8 = 0, $oldsz_sroa_1_8_copyload = 0.0, $38 = 0.0, $39 = 0.0, $sub216 = 0.0, $sub218 = 0.0, $cmp219 = 0, $40 = 0, $conv224 = 0, $and225 = 0, $sub232 = 0.0, $add236 = 0.0, $div238 = 0.0, $add241 = 0.0, $41 = 0.0, $sub245 = 0.0, $42 = 0.0, $43 = 0.0, $sub252 = 0.0, $sub254 = 0.0, $cmp255 = 0, $44 = 0, $conv260 = 0, $and261 = 0, $sub265 = 0.0, $add269 = 0.0, $div271 = 0.0, $add274 = 0.0, $45 = 0.0, $sub278 = 0.0, $46 = 0, $box284 = 0, $47 = 0, $48 = 0, $49 = 0, $conv287 = 0, $and288 = 0, $dfltalign_0 = 0, $50 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $pos;
+ $pos = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($pos, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cbox = __stackBase__ | 0;
+ $pencolor = $cp + 24 | 0;
+ $0 = HEAP32[$pencolor >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $parent = $cp + 88 | 0;
+ $1 = HEAP32[$parent >> 2] | 0;
+ $pencolor2 = $1 + 24 | 0;
+ $2 = HEAP32[$pencolor2 >> 2] | 0;
+ $tobool3 = ($2 | 0) == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _strdup($2 | 0) | 0;
+ HEAP32[$pencolor >> 2] = $call;
+ label = 5;
+ break;
+ case 5:
+ $flags = $cp + 32 | 0;
+ $3 = HEAP16[$flags >> 1] | 0;
+ $conv = $3 & 65535;
+ $and = $conv & 1;
+ $tobool10 = ($and | 0) == 0;
+ if ($tobool10) {
+ label = 16;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $oldsz_sroa_0_0__idx6 = $cp + 56 | 0;
+ $oldsz_sroa_0_0_copyload7 = +HEAPF64[$oldsz_sroa_0_0__idx6 >> 3];
+ $oldsz_sroa_1_8__idx14 = $cp + 64 | 0;
+ $oldsz_sroa_1_8_copyload15 = +HEAPF64[$oldsz_sroa_1_8__idx14 >> 3];
+ $x = $pos + 16 | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $x14 = $pos | 0;
+ $5 = +HEAPF64[$x14 >> 3];
+ $sub = $4 - $5;
+ $sub16 = $sub - $oldsz_sroa_0_0_copyload7;
+ $cmp = $sub16 > 0.0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $and22 = $conv & 6;
+ if (($and22 | 0) == 4) {
+ label = 8;
+ break;
+ } else if (($and22 | 0) == 2) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 8:
+ $add = $oldsz_sroa_0_0_copyload7 + $5;
+ HEAPF64[$x >> 3] = $add;
+ label = 11;
+ break;
+ case 9:
+ $add31 = $4 + $sub16;
+ HEAPF64[$x >> 3] = $add31;
+ $6 = +HEAPF64[$x14 >> 3];
+ $add34 = $sub16 + $6;
+ HEAPF64[$x14 >> 3] = $add34;
+ label = 11;
+ break;
+ case 10:
+ $div = $sub16 * .5;
+ $add37 = $5 + $div;
+ HEAPF64[$x14 >> 3] = $add37;
+ $7 = +HEAPF64[$x >> 3];
+ $sub41 = $7 - $div;
+ HEAPF64[$x >> 3] = $sub41;
+ label = 11;
+ break;
+ case 11:
+ $y = $pos + 24 | 0;
+ $8 = +HEAPF64[$y >> 3];
+ $y45 = $pos + 8 | 0;
+ $9 = +HEAPF64[$y45 >> 3];
+ $sub46 = $8 - $9;
+ $sub48 = $sub46 - $oldsz_sroa_1_8_copyload15;
+ $cmp49 = $sub48 > 0.0;
+ if ($cmp49) {
+ label = 12;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 12:
+ $10 = HEAP16[$flags >> 1] | 0;
+ $conv54 = $10 & 65535;
+ $and55 = $conv54 & 24;
+ if (($and55 | 0) == 16) {
+ label = 13;
+ break;
+ } else if (($and55 | 0) == 8) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $add60 = $oldsz_sroa_1_8_copyload15 + $9;
+ HEAPF64[$y >> 3] = $add60;
+ label = 16;
+ break;
+ case 14:
+ $add66 = $8 + $sub48;
+ HEAPF64[$y >> 3] = $add66;
+ $11 = +HEAPF64[$y45 >> 3];
+ $add69 = $sub48 + $11;
+ HEAPF64[$y45 >> 3] = $add69;
+ label = 16;
+ break;
+ case 15:
+ $div71 = $sub48 * .5;
+ $add74 = $9 + $div71;
+ HEAPF64[$y45 >> 3] = $add74;
+ $12 = +HEAPF64[$y >> 3];
+ $sub78 = $12 - $div71;
+ HEAPF64[$y >> 3] = $sub78;
+ label = 16;
+ break;
+ case 16:
+ $box83 = $cp + 40 | 0;
+ $13 = $box83;
+ $14 = $pos;
+ HEAP32[$13 >> 2] = HEAP32[$14 >> 2] | 0;
+ HEAP32[$13 + 4 >> 2] = HEAP32[$14 + 4 >> 2] | 0;
+ HEAP32[$13 + 8 >> 2] = HEAP32[$14 + 8 >> 2] | 0;
+ HEAP32[$13 + 12 >> 2] = HEAP32[$14 + 12 >> 2] | 0;
+ HEAP32[$13 + 16 >> 2] = HEAP32[$14 + 16 >> 2] | 0;
+ HEAP32[$13 + 20 >> 2] = HEAP32[$14 + 20 >> 2] | 0;
+ HEAP32[$13 + 24 >> 2] = HEAP32[$14 + 24 >> 2] | 0;
+ HEAP32[$13 + 28 >> 2] = HEAP32[$14 + 28 >> 2] | 0;
+ $conv84 = $sides & 255;
+ $sides86 = $cp + 31 | 0;
+ HEAP8[$sides86] = $conv84;
+ $x88 = $pos | 0;
+ $15 = +HEAPF64[$x88 >> 3];
+ $border = $cp + 29 | 0;
+ $16 = HEAP8[$border] | 0;
+ $conv90 = $16 & 255;
+ $conv91 = +($conv90 | 0);
+ $add92 = $15 + $conv91;
+ $pad = $cp + 30 | 0;
+ $17 = HEAP8[$pad] | 0;
+ $conv94 = $17 & 255;
+ $conv95 = +($conv94 | 0);
+ $add96 = $add92 + $conv95;
+ $x98 = $cbox | 0;
+ HEAPF64[$x98 >> 3] = $add96;
+ $y100 = $pos + 8 | 0;
+ $18 = +HEAPF64[$y100 >> 3];
+ $19 = HEAP8[$border] | 0;
+ $conv103 = $19 & 255;
+ $conv104 = +($conv103 | 0);
+ $add105 = $18 + $conv104;
+ $20 = HEAP8[$pad] | 0;
+ $conv108 = $20 & 255;
+ $conv109 = +($conv108 | 0);
+ $add110 = $add105 + $conv109;
+ $y112 = $cbox + 8 | 0;
+ HEAPF64[$y112 >> 3] = $add110;
+ $x114 = $pos + 16 | 0;
+ $21 = +HEAPF64[$x114 >> 3];
+ $22 = HEAP8[$border] | 0;
+ $conv117 = $22 & 255;
+ $conv118 = +($conv117 | 0);
+ $sub119 = $21 - $conv118;
+ $23 = HEAP8[$pad] | 0;
+ $conv122 = $23 & 255;
+ $conv123 = +($conv122 | 0);
+ $sub124 = $sub119 - $conv123;
+ $x126 = $cbox + 16 | 0;
+ HEAPF64[$x126 >> 3] = $sub124;
+ $y128 = $pos + 24 | 0;
+ $24 = +HEAPF64[$y128 >> 3];
+ $25 = HEAP8[$border] | 0;
+ $conv131 = $25 & 255;
+ $conv132 = +($conv131 | 0);
+ $sub133 = $24 - $conv132;
+ $26 = HEAP8[$pad] | 0;
+ $conv136 = $26 & 255;
+ $conv137 = +($conv136 | 0);
+ $sub138 = $sub133 - $conv137;
+ $y140 = $cbox + 24 | 0;
+ HEAPF64[$y140 >> 3] = $sub138;
+ $child = $cp + 80 | 0;
+ $kind = $cp + 84 | 0;
+ $27 = HEAP8[$kind] | 0;
+ if (($27 << 24 >> 24 | 0) == 1) {
+ label = 17;
+ break;
+ } else if (($27 << 24 >> 24 | 0) == 3) {
+ label = 18;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 17:
+ $tbl = $child | 0;
+ $28 = HEAP32[$tbl >> 2] | 0;
+ _pos_html_tbl($28, $cbox, $sides);
+ label = 41;
+ break;
+ case 18:
+ $img = $child;
+ $29 = HEAP32[$img >> 2] | 0;
+ $oldsz_sroa_0_0__idx2 = $29 + 16 | 0;
+ $oldsz_sroa_0_0_copyload3 = +HEAPF64[$oldsz_sroa_0_0__idx2 >> 3];
+ $oldsz_sroa_1_8__idx10 = $29 + 24 | 0;
+ $oldsz_sroa_1_8_copyload11 = +HEAPF64[$oldsz_sroa_1_8__idx10 >> 3];
+ $30 = +HEAPF64[$x126 >> 3];
+ $31 = +HEAPF64[$x98 >> 3];
+ $sub160 = $30 - $31;
+ $sub162 = $sub160 - $oldsz_sroa_0_0_copyload3;
+ $cmp163 = $sub162 > 0.0;
+ if ($cmp163) {
+ label = 19;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 19:
+ $32 = HEAP16[$flags >> 1] | 0;
+ $conv168 = $32 & 65535;
+ $and169 = $conv168 & 6;
+ if (($and169 | 0) == 4) {
+ label = 20;
+ break;
+ } else if (($and169 | 0) == 2) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 20:
+ $sub173 = $30 - $sub162;
+ HEAPF64[$x126 >> 3] = $sub173;
+ label = 22;
+ break;
+ case 21:
+ $add177 = $31 + $sub162;
+ HEAPF64[$x98 >> 3] = $add177;
+ label = 22;
+ break;
+ case 22:
+ $33 = +HEAPF64[$y140 >> 3];
+ $34 = +HEAPF64[$y112 >> 3];
+ $sub184 = $33 - $34;
+ $sub186 = $sub184 - $oldsz_sroa_1_8_copyload11;
+ $cmp187 = $sub186 > 0.0;
+ if ($cmp187) {
+ label = 23;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 23:
+ $35 = HEAP16[$flags >> 1] | 0;
+ $conv192 = $35 & 65535;
+ $and193 = $conv192 & 24;
+ if (($and193 | 0) == 16) {
+ label = 24;
+ break;
+ } else if (($and193 | 0) == 8) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 24:
+ $sub197 = $33 - $sub186;
+ HEAPF64[$y140 >> 3] = $sub197;
+ label = 26;
+ break;
+ case 25:
+ $add201 = $34 + $sub186;
+ HEAPF64[$y112 >> 3] = $add201;
+ label = 26;
+ break;
+ case 26:
+ $36 = HEAP32[$img >> 2] | 0;
+ _pos_html_img($36, $cbox);
+ label = 41;
+ break;
+ case 27:
+ $txt = $child;
+ $37 = HEAP32[$txt >> 2] | 0;
+ $oldsz_sroa_0_0__idx = $37 + 24 | 0;
+ $oldsz_sroa_0_0_copyload = +HEAPF64[$oldsz_sroa_0_0__idx >> 3];
+ $oldsz_sroa_1_8__idx8 = $37 + 32 | 0;
+ $oldsz_sroa_1_8_copyload = +HEAPF64[$oldsz_sroa_1_8__idx8 >> 3];
+ $38 = +HEAPF64[$x126 >> 3];
+ $39 = +HEAPF64[$x98 >> 3];
+ $sub216 = $38 - $39;
+ $sub218 = $sub216 - $oldsz_sroa_0_0_copyload;
+ $cmp219 = $sub218 > 0.0;
+ if ($cmp219) {
+ label = 28;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 28:
+ $40 = HEAP16[$flags >> 1] | 0;
+ $conv224 = $40 & 65535;
+ $and225 = $conv224 & 6;
+ if (($and225 | 0) == 4) {
+ label = 29;
+ break;
+ } else if (($and225 | 0) == 2) {
+ label = 30;
+ break;
+ } else if (($and225 | 0) == 6) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 29:
+ $sub232 = $38 - $sub218;
+ HEAPF64[$x126 >> 3] = $sub232;
+ label = 32;
+ break;
+ case 30:
+ $add236 = $39 + $sub218;
+ HEAPF64[$x98 >> 3] = $add236;
+ label = 32;
+ break;
+ case 31:
+ $div238 = $sub218 * .5;
+ $add241 = $39 + $div238;
+ HEAPF64[$x98 >> 3] = $add241;
+ $41 = +HEAPF64[$x126 >> 3];
+ $sub245 = $41 - $div238;
+ HEAPF64[$x126 >> 3] = $sub245;
+ label = 32;
+ break;
+ case 32:
+ $42 = +HEAPF64[$y140 >> 3];
+ $43 = +HEAPF64[$y112 >> 3];
+ $sub252 = $42 - $43;
+ $sub254 = $sub252 - $oldsz_sroa_1_8_copyload;
+ $cmp255 = $sub254 > 0.0;
+ if ($cmp255) {
+ label = 33;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 33:
+ $44 = HEAP16[$flags >> 1] | 0;
+ $conv260 = $44 & 65535;
+ $and261 = $conv260 & 24;
+ if (($and261 | 0) == 16) {
+ label = 34;
+ break;
+ } else if (($and261 | 0) == 8) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 34:
+ $sub265 = $42 - $sub254;
+ HEAPF64[$y140 >> 3] = $sub265;
+ label = 37;
+ break;
+ case 35:
+ $add269 = $43 + $sub254;
+ HEAPF64[$y112 >> 3] = $add269;
+ label = 37;
+ break;
+ case 36:
+ $div271 = $sub254 * .5;
+ $add274 = $43 + $div271;
+ HEAPF64[$y112 >> 3] = $add274;
+ $45 = +HEAPF64[$y140 >> 3];
+ $sub278 = $45 - $div271;
+ HEAPF64[$y140 >> 3] = $sub278;
+ label = 37;
+ break;
+ case 37:
+ $46 = HEAP32[$txt >> 2] | 0;
+ $box284 = $46 + 8 | 0;
+ $47 = $box284;
+ $48 = $cbox;
+ HEAP32[$47 >> 2] = HEAP32[$48 >> 2] | 0;
+ HEAP32[$47 + 4 >> 2] = HEAP32[$48 + 4 >> 2] | 0;
+ HEAP32[$47 + 8 >> 2] = HEAP32[$48 + 8 >> 2] | 0;
+ HEAP32[$47 + 12 >> 2] = HEAP32[$48 + 12 >> 2] | 0;
+ HEAP32[$47 + 16 >> 2] = HEAP32[$48 + 16 >> 2] | 0;
+ HEAP32[$47 + 20 >> 2] = HEAP32[$48 + 20 >> 2] | 0;
+ HEAP32[$47 + 24 >> 2] = HEAP32[$48 + 24 >> 2] | 0;
+ HEAP32[$47 + 28 >> 2] = HEAP32[$48 + 28 >> 2] | 0;
+ $49 = HEAP16[$flags >> 1] | 0;
+ $conv287 = $49 & 65535;
+ $and288 = $conv287 & 768;
+ if (($and288 | 0) == 256) {
+ label = 38;
+ break;
+ } else if (($and288 | 0) == 512) {
+ $dfltalign_0 = 108;
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ $dfltalign_0 = 114;
+ label = 40;
+ break;
+ case 39:
+ $dfltalign_0 = 110;
+ label = 40;
+ break;
+ case 40:
+ $50 = HEAP32[$txt >> 2] | 0;
+ _pos_html_txt($50, $dfltalign_0);
+ label = 41;
+ break;
+ case 41:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pos_html_img($cp, $pos) {
+ $cp = $cp | 0;
+ $pos = $pos | 0;
+ var $0 = 0, $1 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $pos;
+ $pos = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($pos, tempParam, 32);
+ $0 = $cp;
+ $1 = $pos;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ HEAP32[$0 + 16 >> 2] = HEAP32[$1 + 16 >> 2] | 0;
+ HEAP32[$0 + 20 >> 2] = HEAP32[$1 + 20 >> 2] | 0;
+ HEAP32[$0 + 24 >> 2] = HEAP32[$1 + 24 >> 2] | 0;
+ HEAP32[$0 + 28 >> 2] = HEAP32[$1 + 28 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _processTbl($g, $tbl, $env) {
+ $g = $g | 0;
+ $tbl = $tbl | 0;
+ $env = $env | 0;
+ var $rows1 = 0, $0 = 0, $1 = 0, $call = 0, $call2 = 0, $tobool65 = 0, $rp_0_in67 = 0, $cnt_066 = 0, $u3 = 0, $rp4 = 0, $2 = 0, $call5 = 0, $tobool761 = 0, $cp_0_in63 = 0, $cnt_162 = 0, $inc = 0, $right = 0, $3 = 0, $tobool7 = 0, $cnt_1_lcssa = 0, $right11 = 0, $4 = 0, $tobool = 0, $cnt_0_lcssa = 0, $add = 0, $mul = 0, $call13 = 0, $5 = 0, $call16 = 0, $tobool1850 = 0, $rp_1_in57 = 0, $n_cols_056 = 0, $n_rows_055 = 0, $rv_054 = 0, $cells_053 = 0, $r_051 = 0, $u20 = 0, $rp21 = 0, $6 = 0, $call22 = 0, $tobool2440 = 0, $conv = 0, $n_cols_146 = 0, $n_rows_145 = 0, $rv_144 = 0, $cp_1_in43 = 0, $cells_142 = 0, $c_041 = 0, $u26 = 0, $cp27 = 0, $7 = 0, $incdec_ptr = 0, $call28 = 0, $or = 0, $call29 = 0, $row = 0, $conv30 = 0, $col = 0, $cspan = 0, $8 = 0, $conv31 = 0, $add32 = 0, $cmp = 0, $cond = 0, $rspan = 0, $9 = 0, $conv34 = 0, $add35 = 0, $cmp36 = 0, $add35_n_rows_1 = 0, $right45 = 0, $10 = 0, $tobool24 = 0, $n_cols_1_lcssa = 0, $n_rows_1_lcssa = 0, $rv_1_lcssa = 0, $cells_1_lcssa = 0, $right47 = 0, $11 = 0, $inc48 = 0, $tobool18 = 0, $n_cols_0_lcssa = 0, $n_rows_0_lcssa = 0, $rv_0_lcssa = 0, $rc = 0, $cc = 0, $call50 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rows1 = $tbl + 76 | 0;
+ $0 = HEAP32[$rows1 >> 2] | 0;
+ $1 = $0;
+ $call = _newPS() | 0;
+ $call2 = _dtflatten($1) | 0;
+ $tobool65 = ($call2 | 0) == 0;
+ if ($tobool65) {
+ $cnt_0_lcssa = 0;
+ label = 6;
+ break;
+ } else {
+ $cnt_066 = 0;
+ $rp_0_in67 = $call2;
+ label = 3;
+ break;
+ }
+ case 3:
+ $u3 = $rp_0_in67 + 8 | 0;
+ $rp4 = $u3;
+ $2 = HEAP32[$rp4 >> 2] | 0;
+ $call5 = _dtflatten($2) | 0;
+ $tobool761 = ($call5 | 0) == 0;
+ if ($tobool761) {
+ $cnt_1_lcssa = $cnt_066;
+ label = 5;
+ break;
+ } else {
+ $cnt_162 = $cnt_066;
+ $cp_0_in63 = $call5;
+ label = 4;
+ break;
+ }
+ case 4:
+ $inc = $cnt_162 + 1 | 0;
+ $right = $cp_0_in63 | 0;
+ $3 = HEAP32[$right >> 2] | 0;
+ $tobool7 = ($3 | 0) == 0;
+ if ($tobool7) {
+ $cnt_1_lcssa = $inc;
+ label = 5;
+ break;
+ } else {
+ $cnt_162 = $inc;
+ $cp_0_in63 = $3;
+ label = 4;
+ break;
+ }
+ case 5:
+ $right11 = $rp_0_in67 | 0;
+ $4 = HEAP32[$right11 >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ $cnt_0_lcssa = $cnt_1_lcssa;
+ label = 6;
+ break;
+ } else {
+ $cnt_066 = $cnt_1_lcssa;
+ $rp_0_in67 = $4;
+ label = 3;
+ break;
+ }
+ case 6:
+ $add = $cnt_0_lcssa << 2;
+ $mul = $add + 4 | 0;
+ $call13 = _zmalloc($mul) | 0;
+ $5 = $call13;
+ HEAP32[$rows1 >> 2] = $5;
+ $call16 = _dtflatten($1) | 0;
+ $tobool1850 = ($call16 | 0) == 0;
+ if ($tobool1850) {
+ $rv_0_lcssa = 0;
+ $n_rows_0_lcssa = 0;
+ $n_cols_0_lcssa = 0;
+ label = 11;
+ break;
+ } else {
+ $r_051 = 0;
+ $cells_053 = $5;
+ $rv_054 = 0;
+ $n_rows_055 = 0;
+ $n_cols_056 = 0;
+ $rp_1_in57 = $call16;
+ label = 7;
+ break;
+ }
+ case 7:
+ $u20 = $rp_1_in57 + 8 | 0;
+ $rp21 = $u20;
+ $6 = HEAP32[$rp21 >> 2] | 0;
+ $call22 = _dtflatten($6) | 0;
+ $tobool2440 = ($call22 | 0) == 0;
+ if ($tobool2440) {
+ $cells_1_lcssa = $cells_053;
+ $rv_1_lcssa = $rv_054;
+ $n_rows_1_lcssa = $n_rows_055;
+ $n_cols_1_lcssa = $n_cols_056;
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $conv = $r_051 & 65535;
+ $c_041 = 0;
+ $cells_142 = $cells_053;
+ $cp_1_in43 = $call22;
+ $rv_144 = $rv_054;
+ $n_rows_145 = $n_rows_055;
+ $n_cols_146 = $n_cols_056;
+ label = 9;
+ break;
+ case 9:
+ $u26 = $cp_1_in43 + 8 | 0;
+ $cp27 = $u26;
+ $7 = HEAP32[$cp27 >> 2] | 0;
+ $incdec_ptr = $cells_142 + 4 | 0;
+ HEAP32[$cells_142 >> 2] = $7;
+ $call28 = _size_html_cell($g, $7, $tbl, $env) | 0;
+ $or = $call28 | $rv_144;
+ $call29 = _findCol($call, $r_051, $c_041, $7) | 0;
+ $row = $7 + 78 | 0;
+ HEAP16[$row >> 1] = $conv;
+ $conv30 = $call29 & 65535;
+ $col = $7 + 76 | 0;
+ HEAP16[$col >> 1] = $conv30;
+ $cspan = $7 + 72 | 0;
+ $8 = HEAP16[$cspan >> 1] | 0;
+ $conv31 = $8 & 65535;
+ $add32 = $conv31 + $call29 | 0;
+ $cmp = ($add32 | 0) > ($n_cols_146 | 0);
+ $cond = $cmp ? $add32 : $n_cols_146;
+ $rspan = $7 + 74 | 0;
+ $9 = HEAP16[$rspan >> 1] | 0;
+ $conv34 = $9 & 65535;
+ $add35 = $conv34 + $r_051 | 0;
+ $cmp36 = ($add35 | 0) > ($n_rows_145 | 0);
+ $add35_n_rows_1 = $cmp36 ? $add35 : $n_rows_145;
+ $right45 = $cp_1_in43 | 0;
+ $10 = HEAP32[$right45 >> 2] | 0;
+ $tobool24 = ($10 | 0) == 0;
+ if ($tobool24) {
+ $cells_1_lcssa = $incdec_ptr;
+ $rv_1_lcssa = $or;
+ $n_rows_1_lcssa = $add35_n_rows_1;
+ $n_cols_1_lcssa = $cond;
+ label = 10;
+ break;
+ } else {
+ $c_041 = $add32;
+ $cells_142 = $incdec_ptr;
+ $cp_1_in43 = $10;
+ $rv_144 = $or;
+ $n_rows_145 = $add35_n_rows_1;
+ $n_cols_146 = $cond;
+ label = 9;
+ break;
+ }
+ case 10:
+ $right47 = $rp_1_in57 | 0;
+ $11 = HEAP32[$right47 >> 2] | 0;
+ $inc48 = $r_051 + 1 | 0;
+ $tobool18 = ($11 | 0) == 0;
+ if ($tobool18) {
+ $rv_0_lcssa = $rv_1_lcssa;
+ $n_rows_0_lcssa = $n_rows_1_lcssa;
+ $n_cols_0_lcssa = $n_cols_1_lcssa;
+ label = 11;
+ break;
+ } else {
+ $r_051 = $inc48;
+ $cells_053 = $cells_1_lcssa;
+ $rv_054 = $rv_1_lcssa;
+ $n_rows_055 = $n_rows_1_lcssa;
+ $n_cols_056 = $n_cols_1_lcssa;
+ $rp_1_in57 = $11;
+ label = 7;
+ break;
+ }
+ case 11:
+ $rc = $tbl + 92 | 0;
+ HEAP32[$rc >> 2] = $n_rows_0_lcssa;
+ $cc = $tbl + 96 | 0;
+ HEAP32[$cc >> 2] = $n_cols_0_lcssa;
+ $call50 = _dtclose($1) | 0;
+ _freePS($call);
+ return $rv_0_lcssa | 0;
+ }
+ return 0;
+}
+function _size_html_cell($g, $cp, $parent, $env) {
+ $g = $g | 0;
+ $cp = $cp | 0;
+ $parent = $parent | 0;
+ $env = $env | 0;
+ var $parent1 = 0, $flags = 0, $0 = 0, $and = 0, $tobool = 0, $flags3 = 0, $1 = 0, $and5 = 0, $tobool6 = 0, $pad = 0, $2 = 0, $pad10 = 0, $pad12 = 0, $3 = 0, $and17 = 0, $tobool18 = 0, $cb = 0, $4 = 0, $cmp = 0, $border = 0, $flags27 = 0, $5 = 0, $and29 = 0, $tobool30 = 0, $border33 = 0, $6 = 0, $border35 = 0, $border38 = 0, $child = 0, $kind = 0, $7 = 0, $tbl = 0, $8 = 0, $call = 0, $9 = 0, $child_sz_sroa_0_0__idx4 = 0, $child_sz_sroa_1_8__idx9 = 0, $img = 0, $10 = 0, $call60 = 0, $11 = 0, $child_sz_sroa_0_0__idx2 = 0, $child_sz_sroa_1_8__idx7 = 0, $txt = 0, $12 = 0, $13 = 0, $child_sz_sroa_0_0__idx = 0, $child_sz_sroa_1_8__idx6 = 0, $child_sz_sroa_1_0_in = 0, $child_sz_sroa_0_0_in = 0, $rv_0 = 0, $child_sz_sroa_0_0 = 0.0, $child_sz_sroa_1_0 = 0.0, $pad78 = 0, $14 = 0, $conv79 = 0, $border81 = 0, $15 = 0, $conv82 = 0, $add = 0, $mul = 0, $conv83 = 0.0, $add84 = 0.0, $add87 = 0.0, $16 = 0, $and92 = 0, $tobool93 = 0, $width = 0, $17 = 0, $conv96 = 0, $tobool97 = 0, $height = 0, $18 = 0, $conv99 = 0, $tobool100 = 0, $conv105 = 0.0, $cmp107 = 0, $conv112 = 0.0, $cmp114 = 0, $call117 = 0, $call122 = 0, $sz_sroa_1_0 = 0.0, $sz_sroa_0_0 = 0.0, $rv_2 = 0, $width127 = 0, $19 = 0, $conv128 = 0, $conv129 = 0.0, $cmp130 = 0, $sz_sroa_0_0_conv129 = 0.0, $x140 = 0, $height143 = 0, $20 = 0, $conv144 = 0, $conv145 = 0.0, $cmp146 = 0, $cond156 = 0.0, $y160 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $parent1 = $cp + 88 | 0;
+ HEAP32[$parent1 >> 2] = $parent;
+ $flags = $cp + 32 | 0;
+ $0 = HEAP16[$flags >> 1] | 0;
+ $and = $0 & 64;
+ $tobool = $and << 16 >> 16 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $flags3 = $parent + 32 | 0;
+ $1 = HEAP16[$flags3 >> 1] | 0;
+ $and5 = $1 & 64;
+ $tobool6 = $and5 << 16 >> 16 == 0;
+ if ($tobool6) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $pad = $parent + 30 | 0;
+ $2 = HEAP8[$pad] | 0;
+ $pad10 = $cp + 30 | 0;
+ HEAP8[$pad10] = $2;
+ label = 6;
+ break;
+ case 5:
+ $pad12 = $cp + 30 | 0;
+ HEAP8[$pad12] = 2;
+ label = 6;
+ break;
+ case 6:
+ $3 = HEAP16[$flags >> 1] | 0;
+ $and17 = $3 & 32;
+ $tobool18 = $and17 << 16 >> 16 == 0;
+ if ($tobool18) {
+ label = 7;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 7:
+ $cb = $parent + 80 | 0;
+ $4 = HEAP8[$cb] | 0;
+ $cmp = $4 << 24 >> 24 > -1;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $border = $cp + 29 | 0;
+ HEAP8[$border] = $4;
+ label = 12;
+ break;
+ case 9:
+ $flags27 = $parent + 32 | 0;
+ $5 = HEAP16[$flags27 >> 1] | 0;
+ $and29 = $5 & 32;
+ $tobool30 = $and29 << 16 >> 16 == 0;
+ if ($tobool30) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $border33 = $parent + 29 | 0;
+ $6 = HEAP8[$border33] | 0;
+ $border35 = $cp + 29 | 0;
+ HEAP8[$border35] = $6;
+ label = 12;
+ break;
+ case 11:
+ $border38 = $cp + 29 | 0;
+ HEAP8[$border38] = 1;
+ label = 12;
+ break;
+ case 12:
+ $child = $cp + 80 | 0;
+ $kind = $cp + 84 | 0;
+ $7 = HEAP8[$kind] | 0;
+ if (($7 << 24 >> 24 | 0) == 1) {
+ label = 13;
+ break;
+ } else if (($7 << 24 >> 24 | 0) == 3) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $tbl = $child | 0;
+ $8 = HEAP32[$tbl >> 2] | 0;
+ $call = _size_html_tbl($g, $8, $cp, $env) | 0;
+ $9 = HEAP32[$tbl >> 2] | 0;
+ $child_sz_sroa_0_0__idx4 = $9 + 56 | 0;
+ $child_sz_sroa_1_8__idx9 = $9 + 64 | 0;
+ $rv_0 = $call;
+ $child_sz_sroa_0_0_in = $child_sz_sroa_0_0__idx4;
+ $child_sz_sroa_1_0_in = $child_sz_sroa_1_8__idx9;
+ label = 16;
+ break;
+ case 14:
+ $img = $child;
+ $10 = HEAP32[$img >> 2] | 0;
+ $call60 = _size_html_img($10, $env) | 0;
+ $11 = HEAP32[$img >> 2] | 0;
+ $child_sz_sroa_0_0__idx2 = $11 + 16 | 0;
+ $child_sz_sroa_1_8__idx7 = $11 + 24 | 0;
+ $rv_0 = $call60;
+ $child_sz_sroa_0_0_in = $child_sz_sroa_0_0__idx2;
+ $child_sz_sroa_1_0_in = $child_sz_sroa_1_8__idx7;
+ label = 16;
+ break;
+ case 15:
+ $txt = $child;
+ $12 = HEAP32[$txt >> 2] | 0;
+ _size_html_txt($g, $12, $env);
+ $13 = HEAP32[$txt >> 2] | 0;
+ $child_sz_sroa_0_0__idx = $13 + 24 | 0;
+ $child_sz_sroa_1_8__idx6 = $13 + 32 | 0;
+ $rv_0 = 0;
+ $child_sz_sroa_0_0_in = $child_sz_sroa_0_0__idx;
+ $child_sz_sroa_1_0_in = $child_sz_sroa_1_8__idx6;
+ label = 16;
+ break;
+ case 16:
+ $child_sz_sroa_0_0 = +HEAPF64[$child_sz_sroa_0_0_in >> 3];
+ $child_sz_sroa_1_0 = +HEAPF64[$child_sz_sroa_1_0_in >> 3];
+ $pad78 = $cp + 30 | 0;
+ $14 = HEAP8[$pad78] | 0;
+ $conv79 = $14 & 255;
+ $border81 = $cp + 29 | 0;
+ $15 = HEAP8[$border81] | 0;
+ $conv82 = $15 & 255;
+ $add = $conv82 + $conv79 | 0;
+ $mul = $add << 1;
+ $conv83 = +($mul | 0);
+ $add84 = $child_sz_sroa_0_0 + $conv83;
+ $add87 = $child_sz_sroa_1_0 + $conv83;
+ $16 = HEAP16[$flags >> 1] | 0;
+ $and92 = $16 & 1;
+ $tobool93 = $and92 << 16 >> 16 == 0;
+ if ($tobool93) {
+ $rv_2 = $rv_0;
+ $sz_sroa_0_0 = $add84;
+ $sz_sroa_1_0 = $add87;
+ label = 23;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $width = $cp + 34 | 0;
+ $17 = HEAP16[$width >> 1] | 0;
+ $conv96 = $17 & 65535;
+ $tobool97 = $17 << 16 >> 16 == 0;
+ if ($tobool97) {
+ label = 22;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $height = $cp + 36 | 0;
+ $18 = HEAP16[$height >> 1] | 0;
+ $conv99 = $18 & 65535;
+ $tobool100 = $18 << 16 >> 16 == 0;
+ if ($tobool100) {
+ label = 22;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $conv105 = +($conv96 | 0);
+ $cmp107 = $conv105 < $add84;
+ if ($cmp107) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $conv112 = +($conv99 | 0);
+ $cmp114 = $conv112 < $add87;
+ if ($cmp114) {
+ label = 21;
+ break;
+ } else {
+ $rv_2 = $rv_0;
+ $sz_sroa_0_0 = 0.0;
+ $sz_sroa_1_0 = 0.0;
+ label = 23;
+ break;
+ }
+ case 21:
+ $call117 = _agerr(0, 154112, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $rv_2 = 1;
+ $sz_sroa_0_0 = 0.0;
+ $sz_sroa_1_0 = 0.0;
+ label = 23;
+ break;
+ case 22:
+ $call122 = _agerr(0, 150376, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $rv_2 = 1;
+ $sz_sroa_0_0 = $add84;
+ $sz_sroa_1_0 = $add87;
+ label = 23;
+ break;
+ case 23:
+ $width127 = $cp + 34 | 0;
+ $19 = HEAP16[$width127 >> 1] | 0;
+ $conv128 = $19 & 65535;
+ $conv129 = +($conv128 | 0);
+ $cmp130 = $sz_sroa_0_0 > $conv129;
+ $sz_sroa_0_0_conv129 = $cmp130 ? $sz_sroa_0_0 : $conv129;
+ $x140 = $cp + 56 | 0;
+ HEAPF64[$x140 >> 3] = $sz_sroa_0_0_conv129;
+ $height143 = $cp + 36 | 0;
+ $20 = HEAP16[$height143 >> 1] | 0;
+ $conv144 = $20 & 65535;
+ $conv145 = +($conv144 | 0);
+ $cmp146 = $sz_sroa_1_0 > $conv145;
+ $cond156 = $cmp146 ? $sz_sroa_1_0 : $conv145;
+ $y160 = $cp + 64 | 0;
+ HEAPF64[$y160 >> 3] = $cond156;
+ STACKTOP = __stackBase__;
+ return $rv_2 | 0;
+ }
+ return 0;
+}
+function _findCol($ps, $row, $col, $cellp) {
+ $ps = $ps | 0;
+ $row = $row | 0;
+ $col = $col | 0;
+ $cellp = $cellp | 0;
+ var $cspan = 0, $0 = 0, $conv = 0, $sub = 0, $col_addr_0_ph32 = 0, $1 = 0, $cmp1224 = 0, $rspan = 0, $col_addr_0_ph34 = 0, $add = 0, $c_0 = 0, $cmp = 0, $call = 0, $tobool2 = 0, $dec = 0, $add6 = 0, $j_025 = 0, $2 = 0, $cmp1820 = 0, $i_021 = 0, $inc = 0, $3 = 0, $conv16 = 0, $add17 = 0, $cmp18 = 0, $inc24 = 0, $4 = 0, $conv10 = 0, $add11 = 0, $cmp12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cspan = $cellp + 72 | 0;
+ $0 = HEAP16[$cspan >> 1] | 0;
+ $conv = $0 & 65535;
+ $sub = $conv - 1 | 0;
+ $col_addr_0_ph34 = $col;
+ label = 5;
+ break;
+ case 3:
+ $1 = HEAP16[$cspan >> 1] | 0;
+ $cmp1224 = $1 << 16 >> 16 == 0;
+ if ($cmp1224) {
+ label = 12;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $rspan = $cellp + 74 | 0;
+ $j_025 = $col_addr_0_ph32;
+ label = 9;
+ break;
+ case 5:
+ $add = $sub + $col_addr_0_ph34 | 0;
+ $c_0 = $add;
+ label = 6;
+ break;
+ case 6:
+ $cmp = ($c_0 | 0) < ($col_addr_0_ph34 | 0);
+ if ($cmp) {
+ $col_addr_0_ph32 = $col_addr_0_ph34;
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call = _isInPS($ps, $c_0, $row) | 0;
+ $tobool2 = ($call | 0) == 0;
+ $dec = $c_0 - 1 | 0;
+ if ($tobool2) {
+ $c_0 = $dec;
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $add6 = $c_0 + 1 | 0;
+ if (0) {
+ $col_addr_0_ph32 = $add6;
+ label = 3;
+ break;
+ } else {
+ $col_addr_0_ph34 = $add6;
+ label = 5;
+ break;
+ }
+ case 9:
+ $2 = HEAP16[$rspan >> 1] | 0;
+ $cmp1820 = $2 << 16 >> 16 == 0;
+ if ($cmp1820) {
+ label = 11;
+ break;
+ } else {
+ $i_021 = $row;
+ label = 10;
+ break;
+ }
+ case 10:
+ _addPS($ps, $j_025, $i_021);
+ $inc = $i_021 + 1 | 0;
+ $3 = HEAP16[$rspan >> 1] | 0;
+ $conv16 = $3 & 65535;
+ $add17 = $conv16 + $row | 0;
+ $cmp18 = ($inc | 0) < ($add17 | 0);
+ if ($cmp18) {
+ $i_021 = $inc;
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $inc24 = $j_025 + 1 | 0;
+ $4 = HEAP16[$cspan >> 1] | 0;
+ $conv10 = $4 & 65535;
+ $add11 = $conv10 + $col_addr_0_ph32 | 0;
+ $cmp12 = ($inc24 | 0) < ($add11 | 0);
+ if ($cmp12) {
+ $j_025 = $inc24;
+ label = 9;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ return $col_addr_0_ph32 | 0;
+ }
+ return 0;
+}
+function _size_html_img($img, $env) {
+ $img = $img | 0;
+ $env = $env | 0;
+ var $tmp = 0, $g = 0, $0 = 0, $src = 0, $1 = 0, $b_sroa_2_8__idx = 0, $b_sroa_2_8_copyload = 0, $b_sroa_3_12__idx3 = 0, $b_sroa_3_12_copyload = 0, $cmp = 0, $cmp6 = 0, $or_cond = 0, $2 = 0, $call = 0, $3 = 0, $has_images = 0, $phitmp = 0.0, $phitmp10 = 0.0, $b_sroa_2_0 = 0.0, $b_sroa_3_0 = 0.0, $rv_0 = 0, $x28 = 0, $4 = 0, $y34 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $g = $env + 44 | 0;
+ $0 = HEAP32[$g >> 2] | 0;
+ $src = $img + 32 | 0;
+ $1 = HEAP32[$src >> 2] | 0;
+ _gvusershape_size($tmp, $0, $1);
+ $b_sroa_2_8__idx = $tmp | 0;
+ $b_sroa_2_8_copyload = HEAP32[$b_sroa_2_8__idx >> 2] | 0;
+ $b_sroa_3_12__idx3 = $tmp + 4 | 0;
+ $b_sroa_3_12_copyload = HEAP32[$b_sroa_3_12__idx3 >> 2] | 0;
+ $cmp = ($b_sroa_2_8_copyload | 0) == -1;
+ $cmp6 = ($b_sroa_3_12_copyload | 0) == -1;
+ $or_cond = $cmp & $cmp6;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$src >> 2] | 0;
+ $call = _agerr(1, 147528, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $2, tempInt) | 0) | 0;
+ $rv_0 = 1;
+ $b_sroa_3_0 = 0.0;
+ $b_sroa_2_0 = 0.0;
+ label = 5;
+ break;
+ case 4:
+ $3 = HEAP32[$g >> 2] | 0;
+ $has_images = $3 + 154 | 0;
+ HEAP8[$has_images] = 1;
+ $phitmp = +($b_sroa_2_8_copyload | 0);
+ $phitmp10 = +($b_sroa_3_12_copyload | 0);
+ $rv_0 = 0;
+ $b_sroa_3_0 = $phitmp10;
+ $b_sroa_2_0 = $phitmp;
+ label = 5;
+ break;
+ case 5:
+ $x28 = $img + 16 | 0;
+ $4 = $img;
+ _memset($4 | 0, 0, 16);
+ HEAPF64[$x28 >> 3] = $b_sroa_2_0;
+ $y34 = $img + 24 | 0;
+ HEAPF64[$y34 >> 3] = $b_sroa_3_0;
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _portToCell($cp, $id) {
+ $cp = $cp | 0;
+ $id = $id | 0;
+ var $port = 0, $0 = 0, $tobool = 0, $data = 0, $call = 0, $cmp = 0, $kind = 0, $1 = 0, $cmp4 = 0, $tbl = 0, $2 = 0, $call8 = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $port = $cp + 4 | 0;
+ $0 = HEAP32[$port >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $data = $cp | 0;
+ $call = _strcasecmp($0, $id) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ $rv_0 = $data;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $kind = $cp + 84 | 0;
+ $1 = HEAP8[$kind] | 0;
+ $cmp4 = $1 << 24 >> 24 == 1;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ $rv_0 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $tbl = $cp + 80 | 0;
+ $2 = HEAP32[$tbl >> 2] | 0;
+ $call8 = _portToTbl($2, $id) | 0;
+ $rv_0 = $call8;
+ label = 6;
+ break;
+ case 6:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _free_html_cell($cp) {
+ $cp = $cp | 0;
+ _free_html_label($cp + 80 | 0, 0);
+ _free_html_data($cp | 0);
+ _free($cp);
+ return;
+}
+function _graphSize($g, $nn, $ne) {
+ $g = $g | 0;
+ $nn = $nn | 0;
+ $ne = $ne | 0;
+ var $nlist = 0, $n_09 = 0, $tobool10 = 0, $n_013 = 0, $nedges_012 = 0, $nnodes_011 = 0, $inc = 0, $list = 0, $0 = 0, $1 = 0, $tobool36 = 0, $2 = 0, $i_08 = 0, $nedges_17 = 0, $inc5 = 0, $inc6 = 0, $arrayidx = 0, $3 = 0, $tobool3 = 0, $nedges_1_lcssa = 0, $next = 0, $n_0 = 0, $tobool = 0, $nedges_0_lcssa = 0, $nnodes_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $n_09 = HEAP32[$nlist >> 2] | 0;
+ $tobool10 = ($n_09 | 0) == 0;
+ if ($tobool10) {
+ $nnodes_0_lcssa = 0;
+ $nedges_0_lcssa = 0;
+ label = 7;
+ break;
+ } else {
+ $nnodes_011 = 0;
+ $nedges_012 = 0;
+ $n_013 = $n_09;
+ label = 3;
+ break;
+ }
+ case 3:
+ $inc = $nnodes_011 + 1 | 0;
+ $list = $n_013 + 184 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool36 = ($1 | 0) == 0;
+ if ($tobool36) {
+ $nedges_1_lcssa = $nedges_012;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[$list >> 2] | 0;
+ $nedges_17 = $nedges_012;
+ $i_08 = 0;
+ label = 5;
+ break;
+ case 5:
+ $inc5 = $nedges_17 + 1 | 0;
+ $inc6 = $i_08 + 1 | 0;
+ $arrayidx = $2 + ($inc6 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool3 = ($3 | 0) == 0;
+ if ($tobool3) {
+ $nedges_1_lcssa = $inc5;
+ label = 6;
+ break;
+ } else {
+ $nedges_17 = $inc5;
+ $i_08 = $inc6;
+ label = 5;
+ break;
+ }
+ case 6:
+ $next = $n_013 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ $nnodes_0_lcssa = $inc;
+ $nedges_0_lcssa = $nedges_1_lcssa;
+ label = 7;
+ break;
+ } else {
+ $nnodes_011 = $inc;
+ $nedges_012 = $nedges_1_lcssa;
+ $n_013 = $n_0;
+ label = 3;
+ break;
+ }
+ case 7:
+ HEAP32[$nn >> 2] = $nnodes_0_lcssa;
+ HEAP32[$ne >> 2] = $nedges_0_lcssa;
+ return;
+ }
+}
+function _emit_htextparas($job, $nparas, $paras, $p, $halfwidth_x, $finfo, $b) {
+ $job = $job | 0;
+ $nparas = $nparas | 0;
+ $paras = $paras | 0;
+ $p = $p | 0;
+ $halfwidth_x = +$halfwidth_x;
+ $finfo = $finfo | 0;
+ $b = $b | 0;
+ var $tl = 0, $p_ = 0, $0 = 0, $$etemp$0$0 = 0, $$etemp$0$1 = 0, $st$1$0 = 0, $st$2$1 = 0, $x = 0, $1 = 0.0, $sub = 0.0, $add = 0.0, $y = 0, $2 = 0.0, $y1 = 0, $3 = 0.0, $y2 = 0, $4 = 0.0, $sub3 = 0.0, $div = 0.0, $add4 = 0.0, $y5 = 0, $cmp41 = 0, $size33 = 0, $name43 = 0, $color54 = 0, $str56 = 0, $fontname = 0, $fontsize = 0, $yoffset_layout57 = 0, $yoffset_centerline = 0, $postscript_alias58 = 0, $layout59 = 0, $width = 0, $height = 0, $just63 = 0, $x65 = 0, $i_042 = 0, $just = 0, $5 = 0, $conv = 0, $size = 0, $6 = 0.0, $sub9 = 0.0, $size13 = 0, $7 = 0.0, $div14 = 0.0, $sub15 = 0.0, $lfsize = 0, $8 = 0.0, $9 = 0.0, $sub19 = 0.0, $nitems = 0, $10 = 0, $cmp2438 = 0, $items = 0, $11 = 0, $ti_040 = 0, $j_039 = 0, $font = 0, $12 = 0, $tobool = 0, $size28 = 0, $13 = 0.0, $cmp29 = 0, $14 = 0.0, $fsize__0 = 0.0, $15 = 0, $tobool35 = 0, $name = 0, $16 = 0, $tobool38 = 0, $17 = 0, $fname__0 = 0, $18 = 0, $tobool46 = 0, $color = 0, $19 = 0, $tobool49 = 0, $20 = 0, $fcolor__0 = 0, $str = 0, $21 = 0, $yoffset_layout = 0, $22 = 0.0, $postscript_alias = 0, $23 = 0, $layout = 0, $24 = 0, $size60 = 0, $25 = 0.0, $26 = 0.0, $27 = 0.0, $28 = 0.0, $29 = 0.0, $add68 = 0.0, $incdec_ptr = 0, $inc = 0, $30 = 0, $conv23 = 0, $cmp24 = 0, $inc70 = 0, $cmp = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 96 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $finfo;
+ $finfo = STACKTOP;
+ STACKTOP = STACKTOP + 24 | 0;
+ HEAP32[$finfo >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$finfo + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$finfo + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$finfo + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ HEAP32[$finfo + 16 >> 2] = HEAP32[tempParam + 16 >> 2] | 0;
+ HEAP32[$finfo + 20 >> 2] = HEAP32[tempParam + 20 >> 2] | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tl = __stackBase__ | 0;
+ $p_ = __stackBase__ + 80 | 0;
+ $0 = $p_;
+ $$etemp$0$0 = 0;
+ $$etemp$0$1 = 0;
+ $st$1$0 = $0 | 0;
+ HEAP32[$st$1$0 >> 2] = $$etemp$0$0;
+ $st$2$1 = $0 + 4 | 0;
+ HEAP32[$st$2$1 >> 2] = $$etemp$0$1;
+ $x = $p | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $sub = $1 - $halfwidth_x;
+ $add = $1 + $halfwidth_x;
+ $y = $p + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $y1 = $b + 24 | 0;
+ $3 = +HEAPF64[$y1 >> 3];
+ $y2 = $b + 8 | 0;
+ $4 = +HEAPF64[$y2 >> 3];
+ $sub3 = $3 - $4;
+ $div = $sub3 * .5;
+ $add4 = $2 + $div;
+ $y5 = $p_ + 8 | 0;
+ HEAPF64[$y5 >> 3] = $add4;
+ _gvrender_begin_label($job, 1);
+ $cmp41 = ($nparas | 0) > 0;
+ if ($cmp41) {
+ label = 3;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 3:
+ $size33 = $finfo + 16 | 0;
+ $name43 = $finfo | 0;
+ $color54 = $finfo + 4 | 0;
+ $str56 = $tl | 0;
+ $fontname = $tl + 20 | 0;
+ $fontsize = $tl + 24 | 0;
+ $yoffset_layout57 = $tl + 40 | 0;
+ $yoffset_centerline = $tl + 48 | 0;
+ $postscript_alias58 = $tl + 4 | 0;
+ $layout59 = $tl + 8 | 0;
+ $width = $tl + 56 | 0;
+ $height = $tl + 64 | 0;
+ $just63 = $tl + 72 | 0;
+ $x65 = $p_ | 0;
+ $i_042 = 0;
+ label = 4;
+ break;
+ case 4:
+ $just = $paras + ($i_042 * 24 & -1) + 6 | 0;
+ $5 = HEAP8[$just] | 0;
+ $conv = $5 << 24 >> 24;
+ if (($conv | 0) == 108) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 114) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ HEAPF64[$x >> 3] = $sub;
+ label = 8;
+ break;
+ case 6:
+ $size = $paras + ($i_042 * 24 & -1) + 8 | 0;
+ $6 = +HEAPF64[$size >> 3];
+ $sub9 = $add - $6;
+ HEAPF64[$x >> 3] = $sub9;
+ label = 8;
+ break;
+ case 7:
+ $size13 = $paras + ($i_042 * 24 & -1) + 8 | 0;
+ $7 = +HEAPF64[$size13 >> 3];
+ $div14 = $7 * .5;
+ $sub15 = $1 - $div14;
+ HEAPF64[$x >> 3] = $sub15;
+ label = 8;
+ break;
+ case 8:
+ $lfsize = $paras + ($i_042 * 24 & -1) + 16 | 0;
+ $8 = +HEAPF64[$lfsize >> 3];
+ $9 = +HEAPF64[$y5 >> 3];
+ $sub19 = $9 - $8;
+ HEAPF64[$y5 >> 3] = $sub19;
+ $nitems = $paras + ($i_042 * 24 & -1) + 4 | 0;
+ $10 = HEAP16[$nitems >> 1] | 0;
+ $cmp2438 = $10 << 16 >> 16 > 0;
+ if ($cmp2438) {
+ label = 9;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 9:
+ $items = $paras + ($i_042 * 24 & -1) | 0;
+ $11 = HEAP32[$items >> 2] | 0;
+ $j_039 = 0;
+ $ti_040 = $11;
+ label = 10;
+ break;
+ case 10:
+ $font = $ti_040 + 16 | 0;
+ $12 = HEAP32[$font >> 2] | 0;
+ $tobool = ($12 | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $size28 = $12 + 16 | 0;
+ $13 = +HEAPF64[$size28 >> 3];
+ $cmp29 = $13 > 0.0;
+ if ($cmp29) {
+ $fsize__0 = $13;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $14 = +HEAPF64[$size33 >> 3];
+ $fsize__0 = $14;
+ label = 13;
+ break;
+ case 13:
+ $15 = HEAP32[$font >> 2] | 0;
+ $tobool35 = ($15 | 0) == 0;
+ if ($tobool35) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $name = $15 | 0;
+ $16 = HEAP32[$name >> 2] | 0;
+ $tobool38 = ($16 | 0) == 0;
+ if ($tobool38) {
+ label = 15;
+ break;
+ } else {
+ $fname__0 = $16;
+ label = 16;
+ break;
+ }
+ case 15:
+ $17 = HEAP32[$name43 >> 2] | 0;
+ $fname__0 = $17;
+ label = 16;
+ break;
+ case 16:
+ $18 = HEAP32[$font >> 2] | 0;
+ $tobool46 = ($18 | 0) == 0;
+ if ($tobool46) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $color = $18 + 4 | 0;
+ $19 = HEAP32[$color >> 2] | 0;
+ $tobool49 = ($19 | 0) == 0;
+ if ($tobool49) {
+ label = 18;
+ break;
+ } else {
+ $fcolor__0 = $19;
+ label = 19;
+ break;
+ }
+ case 18:
+ $20 = HEAP32[$color54 >> 2] | 0;
+ $fcolor__0 = $20;
+ label = 19;
+ break;
+ case 19:
+ _gvrender_set_pencolor($job, $fcolor__0);
+ $str = $ti_040 | 0;
+ $21 = HEAP32[$str >> 2] | 0;
+ HEAP32[$str56 >> 2] = $21;
+ HEAP32[$fontname >> 2] = $fname__0;
+ HEAPF64[$fontsize >> 3] = $fsize__0;
+ $yoffset_layout = $ti_040 + 40 | 0;
+ $22 = +HEAPF64[$yoffset_layout >> 3];
+ HEAPF64[$yoffset_layout57 >> 3] = $22;
+ HEAPF64[$yoffset_centerline >> 3] = 1.0;
+ $postscript_alias = $ti_040 + 4 | 0;
+ $23 = HEAP32[$postscript_alias >> 2] | 0;
+ HEAP32[$postscript_alias58 >> 2] = $23;
+ $layout = $ti_040 + 8 | 0;
+ $24 = HEAP32[$layout >> 2] | 0;
+ HEAP32[$layout59 >> 2] = $24;
+ $size60 = $ti_040 + 32 | 0;
+ $25 = +HEAPF64[$size60 >> 3];
+ HEAPF64[$width >> 3] = $25;
+ $26 = +HEAPF64[$lfsize >> 3];
+ HEAPF64[$height >> 3] = $26;
+ HEAP8[$just63] = 108;
+ $27 = +HEAPF64[$x >> 3];
+ HEAPF64[$x65 >> 3] = $27;
+ _gvrender_textpara($job, $p_, $tl);
+ $28 = +HEAPF64[$size60 >> 3];
+ $29 = +HEAPF64[$x >> 3];
+ $add68 = $28 + $29;
+ HEAPF64[$x >> 3] = $add68;
+ $incdec_ptr = $ti_040 + 80 | 0;
+ $inc = $j_039 + 1 | 0;
+ $30 = HEAP16[$nitems >> 1] | 0;
+ $conv23 = $30 << 16 >> 16;
+ $cmp24 = ($inc | 0) < ($conv23 | 0);
+ if ($cmp24) {
+ $j_039 = $inc;
+ $ti_040 = $incdec_ptr;
+ label = 10;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $inc70 = $i_042 + 1 | 0;
+ $cmp = ($inc70 | 0) < ($nparas | 0);
+ if ($cmp) {
+ $i_042 = $inc70;
+ label = 4;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ _gvrender_end_label($job);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _initAnchor($job, $env, $data, $b, $save, $closePrev) {
+ $job = $job | 0;
+ $env = $env | 0;
+ $data = $data | 0;
+ $b = $b | 0;
+ $save = $save | 0;
+ $closePrev = $closePrev | 0;
+ var $xb = 0, $intbuf = 0, $buf = 0, $obj1 = 0, $0 = 0, $url = 0, $1 = 0, $url2 = 0, $tooltip = 0, $2 = 0, $tooltip3 = 0, $target = 0, $3 = 0, $target4 = 0, $id5 = 0, $4 = 0, $id6 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $bf_val_sext = 0, $conv = 0, $explicit_tooltip = 0, $id7 = 0, $9 = 0, $tobool = 0, $10 = 0, $tobool8 = 0, $arraydecay = 0, $objid = 0, $11 = 0, $tobool9 = 0, $u = 0, $n = 0, $12 = 0, $13 = 0, $call = 0, $call11 = 0, $objid_set = 0, $14 = 0, $call14 = 0, $arraydecay15 = 0, $15 = 0, $inc = 0, $call16 = 0, $call18 = 0, $ptr = 0, $16 = 0, $eptr = 0, $17 = 0, $cmp = 0, $call20 = 0, $18 = 0, $buf22 = 0, $19 = 0, $id_0 = 0, $internalId_0 = 0, $href = 0, $20 = 0, $title = 0, $21 = 0, $target25 = 0, $22 = 0, $g = 0, $23 = 0, $24 = 0, $call27 = 0, $tobool31 = 0, $tobool33 = 0, $25 = 0, $tobool35 = 0, $26 = 0, $tobool39 = 0, $27 = 0, $tobool43 = 0, $28 = 0, $_mask = 0, $tobool48 = 0, $29 = 0, $30 = 0, $31 = 0, $32 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 176 | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $xb = __stackBase__ | 0;
+ $intbuf = __stackBase__ + 16 | 0;
+ $buf = __stackBase__ + 48 | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $url = $0 + 160 | 0;
+ $1 = HEAP32[$url >> 2] | 0;
+ $url2 = $save | 0;
+ HEAP32[$url2 >> 2] = $1;
+ $tooltip = $0 + 180 | 0;
+ $2 = HEAP32[$tooltip >> 2] | 0;
+ $tooltip3 = $save + 4 | 0;
+ HEAP32[$tooltip3 >> 2] = $2;
+ $target = $0 + 196 | 0;
+ $3 = HEAP32[$target >> 2] | 0;
+ $target4 = $save + 8 | 0;
+ HEAP32[$target4 >> 2] = $3;
+ $id5 = $0 + 164 | 0;
+ $4 = HEAP32[$id5 >> 2] | 0;
+ $id6 = $save + 12 | 0;
+ HEAP32[$id6 >> 2] = $4;
+ $5 = $0 + 212 | 0;
+ $6 = $5;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $8 = $7 << 31;
+ $bf_val_sext = $8 >> 31;
+ $conv = $bf_val_sext & 255;
+ $explicit_tooltip = $save + 16 | 0;
+ HEAP8[$explicit_tooltip] = $conv;
+ $id7 = $data + 16 | 0;
+ $9 = HEAP32[$id7 >> 2] | 0;
+ $tobool = ($9 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $10 = HEAP8[$9] | 0;
+ $tobool8 = $10 << 24 >> 24 == 0;
+ if ($tobool8) {
+ label = 4;
+ break;
+ } else {
+ $internalId_0 = 0;
+ $id_0 = $9;
+ label = 9;
+ break;
+ }
+ case 4:
+ $arraydecay = $buf | 0;
+ _agxbinit($xb, 128, $arraydecay);
+ $objid = $env + 52 | 0;
+ $11 = HEAP32[$objid >> 2] | 0;
+ $tobool9 = ($11 | 0) == 0;
+ if ($tobool9) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $u = $0 + 8 | 0;
+ $n = $u;
+ $12 = HEAP32[$n >> 2] | 0;
+ $13 = $12 | 0;
+ $call = _getObjId($job, $13, $xb) | 0;
+ $call11 = _strdup($call | 0) | 0;
+ HEAP32[$objid >> 2] = $call11;
+ $objid_set = $env + 56 | 0;
+ HEAP8[$objid_set] = 1;
+ label = 6;
+ break;
+ case 6:
+ $14 = HEAP32[$objid >> 2] | 0;
+ $call14 = _agxbput($xb, $14) | 0;
+ $arraydecay15 = $intbuf | 0;
+ $15 = HEAP32[3192] | 0;
+ $inc = $15 + 1 | 0;
+ HEAP32[3192] = $inc;
+ $call16 = _sprintf($arraydecay15 | 0, 113208, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $15, tempInt) | 0) | 0;
+ $call18 = _agxbput($xb, $arraydecay15) | 0;
+ $ptr = $xb + 4 | 0;
+ $16 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $xb + 8 | 0;
+ $17 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $16 >>> 0 < $17 >>> 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call20 = _agxbmore($xb, 1) | 0;
+ label = 8;
+ break;
+ case 8:
+ $18 = HEAP32[$ptr >> 2] | 0;
+ HEAP8[$18] = 0;
+ $buf22 = $xb | 0;
+ $19 = HEAP32[$buf22 >> 2] | 0;
+ HEAP32[$ptr >> 2] = $19;
+ $internalId_0 = 1;
+ $id_0 = $19;
+ label = 9;
+ break;
+ case 9:
+ $href = $data | 0;
+ $20 = HEAP32[$href >> 2] | 0;
+ $title = $data + 12 | 0;
+ $21 = HEAP32[$title >> 2] | 0;
+ $target25 = $data + 8 | 0;
+ $22 = HEAP32[$target25 >> 2] | 0;
+ $g = $0 + 8 | 0;
+ $23 = HEAP32[$g >> 2] | 0;
+ $24 = $23 | 0;
+ $call27 = _initMapData($job, 0, $20, $21, $22, $id_0, $24) | 0;
+ if ($internalId_0) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _agxbfree($xb);
+ label = 11;
+ break;
+ case 11:
+ $tobool31 = ($call27 | 0) == 0;
+ if ($tobool31) {
+ label = 19;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $tobool33 = ($closePrev | 0) == 0;
+ if ($tobool33) {
+ label = 16;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $25 = HEAP32[$url2 >> 2] | 0;
+ $tobool35 = ($25 | 0) == 0;
+ if ($tobool35) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $26 = HEAP8[$explicit_tooltip] | 0;
+ $tobool39 = $26 << 24 >> 24 == 0;
+ if ($tobool39) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ _gvrender_end_anchor($job);
+ label = 16;
+ break;
+ case 16:
+ $27 = HEAP32[$url >> 2] | 0;
+ $tobool43 = ($27 | 0) == 0;
+ if ($tobool43) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $28 = HEAP32[$6 >> 2] | 0;
+ $_mask = $28 & 1;
+ $tobool48 = ($_mask | 0) == 0;
+ if ($tobool48) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ _emit_map_rect($job, $b);
+ $29 = HEAP32[$url >> 2] | 0;
+ $30 = HEAP32[$tooltip >> 2] | 0;
+ $31 = HEAP32[$target >> 2] | 0;
+ $32 = HEAP32[$id5 >> 2] | 0;
+ _gvrender_begin_anchor($job, $29, $30, $31, $32);
+ label = 19;
+ break;
+ case 19:
+ STACKTOP = __stackBase__;
+ return $call27 | 0;
+ }
+ return 0;
+}
+function _doFill($job, $color, $BF) {
+ $job = $job | 0;
+ $color = $color | 0;
+ $BF = $BF | 0;
+ var tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $BF;
+ $BF = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($BF, tempParam, 32);
+ _gvrender_set_fillcolor($job, $color);
+ _gvrender_set_pencolor($job, $color);
+ _gvrender_box($job, $BF, 1);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _doBorder($job, $color, $border, $BF) {
+ $job = $job | 0;
+ $color = $color | 0;
+ $border = $border | 0;
+ $BF = $BF | 0;
+ var $pt = 0, $tobool = 0, $_color = 0, $cmp = 0, $dec = 0, $UR = 0, $y = 0, $0 = 0.0, $LL = 0, $y2 = 0, $1 = 0.0, $sub = 0.0, $x = 0, $2 = 0.0, $x5 = 0, $3 = 0.0, $sub6 = 0.0, $conv = 0.0, $4 = 0.0, $x10 = 0, $5 = 0.0, $y13 = 0, $sub14 = 0, $conv15 = 0.0, $sub19 = 0.0, $6 = 0.0, $7 = 0.0, $sub26 = 0.0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ tempParam = $BF;
+ $BF = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($BF, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pt = __stackBase__ | 0;
+ $tobool = ($color | 0) == 0;
+ $_color = $tobool ? 121304 : $color;
+ _gvrender_set_fillcolor($job, $_color);
+ _gvrender_set_pencolor($job, $_color);
+ $cmp = ($border | 0) == 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _gvrender_box($job, $BF, 0);
+ label = 5;
+ break;
+ case 4:
+ $dec = $border - 1 | 0;
+ $UR = $BF + 16 | 0;
+ $y = $BF + 24 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $LL = $BF | 0;
+ $y2 = $BF + 8 | 0;
+ $1 = +HEAPF64[$y2 >> 3];
+ $sub = $0 - $1;
+ $x = $UR | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x5 = $BF | 0;
+ $3 = +HEAPF64[$x5 >> 3];
+ $sub6 = $2 - $3;
+ $conv = +($dec | 0);
+ _doSide($job, $LL, $conv, $sub);
+ $4 = +HEAPF64[$x5 >> 3];
+ $x10 = $pt | 0;
+ HEAPF64[$x10 >> 3] = $4;
+ $5 = +HEAPF64[$y >> 3];
+ $y13 = $pt + 8 | 0;
+ HEAPF64[$y13 >> 3] = $5;
+ $sub14 = 1 - $border | 0;
+ $conv15 = +($sub14 | 0);
+ _doSide($job, $pt, $sub6, $conv15);
+ $sub19 = -0.0 - $sub;
+ _doSide($job, $UR, $conv15, $sub19);
+ $6 = +HEAPF64[$x >> 3];
+ HEAPF64[$x10 >> 3] = $6;
+ $7 = +HEAPF64[$y2 >> 3];
+ HEAPF64[$y13 >> 3] = $7;
+ $sub26 = -0.0 - $sub6;
+ _doSide($job, $pt, $sub26, $conv);
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _emit_html_cell($job, $cp, $env) {
+ $job = $job | 0;
+ $cp = $cp | 0;
+ $env = $env | 0;
+ var $saved = 0, $pts = 0, $data = 0, $box = 0, $0 = 0, $1 = 0, $pos_sroa_0_0__idx = 0, $pos_sroa_0_0_copyload = 0.0, $pos_sroa_1_8__idx4 = 0, $pos_sroa_1_8_copyload = 0.0, $href = 0, $2 = 0, $tobool = 0, $target = 0, $3 = 0, $tobool4 = 0, $4 = 0, $x5 = 0, $5 = 0.0, $add = 0.0, $x7 = 0, $6 = 0.0, $add8 = 0.0, $y10 = 0, $7 = 0.0, $add11 = 0.0, $y14 = 0, $8 = 0.0, $add15 = 0.0, $flags = 0, $9 = 0, $and = 0, $tobool17 = 0, $call = 0, $inAnchor_0 = 0, $bgcolor = 0, $10 = 0, $tobool20 = 0, $border = 0, $11 = 0, $tobool26 = 0, $pencolor = 0, $12 = 0, $conv = 0, $child = 0, $kind = 0, $13 = 0, $tbl = 0, $14 = 0, $img = 0, $15 = 0, $txt = 0, $16 = 0, $tobool50 = 0, $flags55 = 0, $17 = 0, $and56 = 0, $tobool57 = 0, $call60 = 0, $tobool61 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 72 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $saved = __stackBase__ | 0;
+ $pts = __stackBase__ + 40 | 0;
+ $data = $cp | 0;
+ $box = $cp + 40 | 0;
+ $0 = $pts;
+ $1 = $box;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ HEAP32[$0 + 16 >> 2] = HEAP32[$1 + 16 >> 2] | 0;
+ HEAP32[$0 + 20 >> 2] = HEAP32[$1 + 20 >> 2] | 0;
+ HEAP32[$0 + 24 >> 2] = HEAP32[$1 + 24 >> 2] | 0;
+ HEAP32[$0 + 28 >> 2] = HEAP32[$1 + 28 >> 2] | 0;
+ $pos_sroa_0_0__idx = $env | 0;
+ $pos_sroa_0_0_copyload = +HEAPF64[$pos_sroa_0_0__idx >> 3];
+ $pos_sroa_1_8__idx4 = $env + 8 | 0;
+ $pos_sroa_1_8_copyload = +HEAPF64[$pos_sroa_1_8__idx4 >> 3];
+ $href = $cp | 0;
+ $2 = HEAP32[$href >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $4 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $target = $cp + 8 | 0;
+ $3 = HEAP32[$target >> 2] | 0;
+ $tobool4 = ($3 | 0) != 0;
+ $4 = $tobool4;
+ label = 4;
+ break;
+ case 4:
+ $x5 = $pts | 0;
+ $5 = +HEAPF64[$x5 >> 3];
+ $add = $pos_sroa_0_0_copyload + $5;
+ HEAPF64[$x5 >> 3] = $add;
+ $x7 = $pts + 16 | 0;
+ $6 = +HEAPF64[$x7 >> 3];
+ $add8 = $pos_sroa_0_0_copyload + $6;
+ HEAPF64[$x7 >> 3] = $add8;
+ $y10 = $pts + 8 | 0;
+ $7 = +HEAPF64[$y10 >> 3];
+ $add11 = $pos_sroa_1_8_copyload + $7;
+ HEAPF64[$y10 >> 3] = $add11;
+ $y14 = $pts + 24 | 0;
+ $8 = +HEAPF64[$y14 >> 3];
+ $add15 = $pos_sroa_1_8_copyload + $8;
+ HEAPF64[$y14 >> 3] = $add15;
+ if ($4) {
+ label = 5;
+ break;
+ } else {
+ $inAnchor_0 = 0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $flags = $job + 152 | 0;
+ $9 = HEAP32[$flags >> 2] | 0;
+ $and = $9 & 4;
+ $tobool17 = ($and | 0) == 0;
+ if ($tobool17) {
+ label = 6;
+ break;
+ } else {
+ $inAnchor_0 = 0;
+ label = 7;
+ break;
+ }
+ case 6:
+ $call = _initAnchor($job, $env, $data, $pts, $saved, 1) | 0;
+ $inAnchor_0 = $call;
+ label = 7;
+ break;
+ case 7:
+ $bgcolor = $cp + 20 | 0;
+ $10 = HEAP32[$bgcolor >> 2] | 0;
+ $tobool20 = ($10 | 0) == 0;
+ if ($tobool20) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _doFill($job, $10, $pts);
+ label = 9;
+ break;
+ case 9:
+ $border = $cp + 29 | 0;
+ $11 = HEAP8[$border] | 0;
+ $tobool26 = $11 << 24 >> 24 == 0;
+ if ($tobool26) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $pencolor = $cp + 24 | 0;
+ $12 = HEAP32[$pencolor >> 2] | 0;
+ $conv = $11 & 255;
+ _doBorder($job, $12, $conv, $pts);
+ label = 11;
+ break;
+ case 11:
+ $child = $cp + 80 | 0;
+ $kind = $cp + 84 | 0;
+ $13 = HEAP8[$kind] | 0;
+ if (($13 << 24 >> 24 | 0) == 1) {
+ label = 12;
+ break;
+ } else if (($13 << 24 >> 24 | 0) == 3) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ $tbl = $child | 0;
+ $14 = HEAP32[$tbl >> 2] | 0;
+ _emit_html_tbl($job, $14, $env);
+ label = 15;
+ break;
+ case 13:
+ $img = $child;
+ $15 = HEAP32[$img >> 2] | 0;
+ _emit_html_img($job, $15, $env);
+ label = 15;
+ break;
+ case 14:
+ $txt = $child;
+ $16 = HEAP32[$txt >> 2] | 0;
+ _emit_html_txt($job, $16, $env);
+ label = 15;
+ break;
+ case 15:
+ $tobool50 = ($inAnchor_0 | 0) == 0;
+ if ($tobool50) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ _endAnchor($job, $saved, 1);
+ label = 17;
+ break;
+ case 17:
+ if ($4) {
+ label = 18;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 18:
+ $flags55 = $job + 152 | 0;
+ $17 = HEAP32[$flags55 >> 2] | 0;
+ $and56 = $17 & 4;
+ $tobool57 = ($and56 | 0) == 0;
+ if ($tobool57) {
+ label = 21;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $call60 = _initAnchor($job, $env, $data, $pts, $saved, 0) | 0;
+ $tobool61 = ($call60 | 0) == 0;
+ if ($tobool61) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ _endAnchor($job, $saved, 0);
+ label = 21;
+ break;
+ case 21:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _endAnchor($job, $save, $openPrev) {
+ $job = $job | 0;
+ $save = $save | 0;
+ $openPrev = $openPrev | 0;
+ var $obj1 = 0, $0 = 0, $url = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $4 = 0, $_mask = 0, $tobool2 = 0, $5 = 0, $url4 = 0, $6 = 0, $cmp = 0, $7 = 0, $tooltip = 0, $8 = 0, $tooltip10 = 0, $9 = 0, $cmp11 = 0, $10 = 0, $target = 0, $11 = 0, $target17 = 0, $12 = 0, $cmp18 = 0, $13 = 0, $id = 0, $14 = 0, $id24 = 0, $15 = 0, $cmp25 = 0, $16 = 0, $explicit_tooltip = 0, $17 = 0, $conv = 0, $bf_value = 0, $18 = 0, $19 = 0, $20 = 0, $21 = 0, $22 = 0, $tobool32 = 0, $23 = 0, $tobool34 = 0, $tobool39 = 0, $or_cond = 0, $24 = 0, $25 = 0, $26 = 0, $27 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $url = $0 + 160 | 0;
+ $1 = HEAP32[$url >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $0 + 212 | 0;
+ $3 = $2;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $_mask = $4 & 1;
+ $tobool2 = ($_mask | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _gvrender_end_anchor($job);
+ label = 5;
+ break;
+ case 5:
+ $5 = HEAP32[$url >> 2] | 0;
+ $url4 = $save | 0;
+ $6 = HEAP32[$url4 >> 2] | 0;
+ $cmp = ($5 | 0) == ($6 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _free($5);
+ $7 = HEAP32[$url4 >> 2] | 0;
+ HEAP32[$url >> 2] = $7;
+ label = 7;
+ break;
+ case 7:
+ $tooltip = $0 + 180 | 0;
+ $8 = HEAP32[$tooltip >> 2] | 0;
+ $tooltip10 = $save + 4 | 0;
+ $9 = HEAP32[$tooltip10 >> 2] | 0;
+ $cmp11 = ($8 | 0) == ($9 | 0);
+ if ($cmp11) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _free($8);
+ $10 = HEAP32[$tooltip10 >> 2] | 0;
+ HEAP32[$tooltip >> 2] = $10;
+ label = 9;
+ break;
+ case 9:
+ $target = $0 + 196 | 0;
+ $11 = HEAP32[$target >> 2] | 0;
+ $target17 = $save + 8 | 0;
+ $12 = HEAP32[$target17 >> 2] | 0;
+ $cmp18 = ($11 | 0) == ($12 | 0);
+ if ($cmp18) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ _free($11);
+ $13 = HEAP32[$target17 >> 2] | 0;
+ HEAP32[$target >> 2] = $13;
+ label = 11;
+ break;
+ case 11:
+ $id = $0 + 164 | 0;
+ $14 = HEAP32[$id >> 2] | 0;
+ $id24 = $save + 12 | 0;
+ $15 = HEAP32[$id24 >> 2] | 0;
+ $cmp25 = ($14 | 0) == ($15 | 0);
+ if ($cmp25) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _free($14);
+ $16 = HEAP32[$id24 >> 2] | 0;
+ HEAP32[$id >> 2] = $16;
+ label = 13;
+ break;
+ case 13:
+ $explicit_tooltip = $save + 16 | 0;
+ $17 = HEAP8[$explicit_tooltip] | 0;
+ $conv = $17 & 255;
+ $bf_value = $conv & 1;
+ $18 = $0 + 212 | 0;
+ $19 = $18;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $21 = $20 & -2;
+ $22 = $21 | $bf_value;
+ HEAP32[$19 >> 2] = $22;
+ $tobool32 = ($openPrev | 0) == 0;
+ if ($tobool32) {
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $23 = HEAP32[$url >> 2] | 0;
+ $tobool34 = ($23 | 0) == 0;
+ $tobool39 = ($bf_value | 0) == 0;
+ $or_cond = $tobool34 & $tobool39;
+ if ($or_cond) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $24 = HEAP32[$url >> 2] | 0;
+ $25 = HEAP32[$tooltip >> 2] | 0;
+ $26 = HEAP32[$target >> 2] | 0;
+ $27 = HEAP32[$id >> 2] | 0;
+ _gvrender_begin_anchor($job, $24, $25, $26, $27);
+ label = 16;
+ break;
+ case 16:
+ return;
+ }
+}
+function _emit_html_img($job, $cp, $env) {
+ $job = $job | 0;
+ $cp = $cp | 0;
+ $env = $env | 0;
+ var $A = 0, $bb_sroa_0_0__idx = 0, $bb_sroa_0_0_copyload = 0.0, $bb_sroa_1_8__idx3 = 0, $bb_sroa_1_8_copyload = 0.0, $bb_sroa_2_16__idx6 = 0, $bb_sroa_2_16_copyload = 0.0, $bb_sroa_3_24__idx8 = 0, $bb_sroa_3_24_copyload = 0.0, $x = 0, $0 = 0.0, $add = 0.0, $y = 0, $1 = 0.0, $add5 = 0.0, $add9 = 0.0, $add14 = 0.0, $bb_sroa_2_16__idx = 0, $bb_sroa_3_24__idx9 = 0, $bb_sroa_0_0__idx1 = 0, $bb_sroa_1_8__idx4 = 0, $2 = 0.0, $x21 = 0, $arrayidx22 = 0, $3 = 0.0, $y25 = 0, $4 = 0.0, $x29 = 0, $5 = 0.0, $y33 = 0, $scale34 = 0, $6 = 0, $tobool = 0, $imgscale = 0, $7 = 0, $scale_0 = 0, $src = 0, $8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $A = __stackBase__ | 0;
+ $bb_sroa_0_0__idx = $cp | 0;
+ $bb_sroa_0_0_copyload = +HEAPF64[$bb_sroa_0_0__idx >> 3];
+ $bb_sroa_1_8__idx3 = $cp + 8 | 0;
+ $bb_sroa_1_8_copyload = +HEAPF64[$bb_sroa_1_8__idx3 >> 3];
+ $bb_sroa_2_16__idx6 = $cp + 16 | 0;
+ $bb_sroa_2_16_copyload = +HEAPF64[$bb_sroa_2_16__idx6 >> 3];
+ $bb_sroa_3_24__idx8 = $cp + 24 | 0;
+ $bb_sroa_3_24_copyload = +HEAPF64[$bb_sroa_3_24__idx8 >> 3];
+ $x = $env | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $add = $bb_sroa_0_0_copyload + $0;
+ $y = $env + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $add5 = $bb_sroa_1_8_copyload + $1;
+ $add9 = $bb_sroa_2_16_copyload + $0;
+ $add14 = $bb_sroa_3_24_copyload + $1;
+ $bb_sroa_2_16__idx = $A | 0;
+ HEAPF64[$bb_sroa_2_16__idx >> 3] = $add9;
+ $bb_sroa_3_24__idx9 = $A + 8 | 0;
+ HEAPF64[$bb_sroa_3_24__idx9 >> 3] = $add14;
+ $bb_sroa_0_0__idx1 = $A + 32 | 0;
+ HEAPF64[$bb_sroa_0_0__idx1 >> 3] = $add;
+ $bb_sroa_1_8__idx4 = $A + 40 | 0;
+ HEAPF64[$bb_sroa_1_8__idx4 >> 3] = $add5;
+ $2 = +HEAPF64[$bb_sroa_0_0__idx1 >> 3];
+ $x21 = $A + 16 | 0;
+ HEAPF64[$x21 >> 3] = $2;
+ $arrayidx22 = $A | 0;
+ $3 = +HEAPF64[$bb_sroa_3_24__idx9 >> 3];
+ $y25 = $A + 24 | 0;
+ HEAPF64[$y25 >> 3] = $3;
+ $4 = +HEAPF64[$bb_sroa_2_16__idx >> 3];
+ $x29 = $A + 48 | 0;
+ HEAPF64[$x29 >> 3] = $4;
+ $5 = +HEAPF64[$bb_sroa_1_8__idx4 >> 3];
+ $y33 = $A + 56 | 0;
+ HEAPF64[$y33 >> 3] = $5;
+ $scale34 = $cp + 36 | 0;
+ $6 = HEAP32[$scale34 >> 2] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $scale_0 = $6;
+ label = 4;
+ break;
+ }
+ case 3:
+ $imgscale = $env + 48 | 0;
+ $7 = HEAP32[$imgscale >> 2] | 0;
+ $scale_0 = $7;
+ label = 4;
+ break;
+ case 4:
+ $src = $cp + 32 | 0;
+ $8 = HEAP32[$src >> 2] | 0;
+ _gvrender_usershape($job, $8, $arrayidx22, 4, 1, $scale_0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _doSide($job, $p, $wd, $ht) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $wd = +$wd;
+ $ht = +$ht;
+ var $BF = 0, $0 = 0, $1 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $BF = __stackBase__ | 0;
+ $0 = $BF;
+ $1 = $p;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ HEAPF64[$BF + 16 >> 3] = +HEAPF64[$p >> 3] + $wd;
+ HEAPF64[$BF + 24 >> 3] = +HEAPF64[$p + 8 >> 3] + $ht;
+ _gvrender_box($job, $BF, 1);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _rank($g, $balance, $maxiter) {
+ $g = $g | 0;
+ $balance = $balance | 0;
+ $maxiter = $maxiter | 0;
+ var $nn = 0, $ne = 0, $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $3 = 0, $call = 0, $call1 = 0, $tobool2 = 0, $cmp = 0, $4 = 0, $call7 = 0, $tobool8 = 0, $call10 = 0, $storemerge = 0, $call12 = 0, $tobool13 = 0, $iter_0 = 0, $call16 = 0, $tobool17 = 0, $call18 = 0, $inc = 0, $5 = 0, $tobool19 = 0, $rem = 0, $cmp20 = 0, $rem23 = 0, $cmp24 = 0, $6 = 0, $7 = 0, $8 = 0, $call2917 = 0, $call29 = 0, $cmp31 = 0, $9 = 0, $call34 = 0, $cmp37 = 0, $iter_1 = 0, $10 = 0, $tobool42 = 0, $cmp44 = 0, $11 = 0, $call47 = 0, $12 = 0, $13 = 0, $14 = 0, $call49 = 0.0, $call50 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nn = __stackBase__ | 0;
+ $ne = __stackBase__ + 8 | 0;
+ $0 = HEAP8[164912] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _graphSize($g, $nn, $ne);
+ $1 = HEAP32[_stderr >> 2] | 0;
+ $2 = HEAP32[$nn >> 2] | 0;
+ $3 = HEAP32[$ne >> 2] | 0;
+ $call = _fprintf($1 | 0, 141440, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = 102112, HEAP32[tempInt + 8 >> 2] = $2, HEAP32[tempInt + 16 >> 2] = $3, HEAP32[tempInt + 24 >> 2] = $maxiter, HEAP32[tempInt + 32 >> 2] = $balance, tempInt) | 0) | 0;
+ _start_timer();
+ label = 4;
+ break;
+ case 4:
+ $call1 = _init_graph($g) | 0;
+ $tobool2 = ($call1 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ _init_rank();
+ label = 6;
+ break;
+ case 6:
+ $cmp = ($maxiter | 0) < 1;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ _freeTreeList();
+ $retval_0 = 0;
+ label = 28;
+ break;
+ case 8:
+ $4 = $g | 0;
+ $call7 = _agget($4, 120848) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ $storemerge = 30;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call10 = _atoi($call7 | 0) | 0;
+ $storemerge = $call10;
+ label = 10;
+ break;
+ case 10:
+ HEAP32[41520] = $storemerge;
+ $call12 = _feasible_tree() | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ $iter_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ _freeTreeList();
+ $retval_0 = 1;
+ label = 28;
+ break;
+ case 12:
+ $call16 = _leave_edge() | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ if ($tobool17) {
+ $iter_1 = $iter_0;
+ label = 20;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $call18 = _enter_edge($call16) | 0;
+ _update($call16, $call18);
+ $inc = $iter_0 + 1 | 0;
+ $5 = HEAP8[164912] | 0;
+ $tobool19 = $5 << 24 >> 24 == 0;
+ if ($tobool19) {
+ label = 19;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $rem = ($inc | 0) % 100;
+ $cmp20 = ($rem | 0) == 0;
+ if ($cmp20) {
+ label = 15;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 15:
+ $rem23 = ($inc | 0) % 1e3;
+ $cmp24 = ($rem23 | 0) == 100;
+ $6 = HEAP32[_stderr >> 2] | 0;
+ if ($cmp24) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $7 = _fwrite(102112, 17, 1, $6 | 0) | 0;
+ $8 = HEAP32[_stderr >> 2] | 0;
+ $call2917 = _fprintf($8 | 0, 115224, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $inc, tempInt) | 0) | 0;
+ label = 19;
+ break;
+ case 17:
+ $call29 = _fprintf($6 | 0, 115224, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $inc, tempInt) | 0) | 0;
+ $cmp31 = ($rem23 | 0) == 0;
+ if ($cmp31) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $9 = HEAP32[_stderr >> 2] | 0;
+ $call34 = _fputc(10, $9 | 0) | 0;
+ label = 19;
+ break;
+ case 19:
+ $cmp37 = ($inc | 0) < ($maxiter | 0);
+ if ($cmp37) {
+ $iter_0 = $inc;
+ label = 12;
+ break;
+ } else {
+ $iter_1 = $inc;
+ label = 20;
+ break;
+ }
+ case 20:
+ if (($balance | 0) == 1) {
+ label = 21;
+ break;
+ } else if (($balance | 0) == 2) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 21:
+ _TB_balance();
+ label = 24;
+ break;
+ case 22:
+ _LR_balance();
+ label = 24;
+ break;
+ case 23:
+ _scan_and_normalize();
+ label = 24;
+ break;
+ case 24:
+ $10 = HEAP8[164912] | 0;
+ $tobool42 = $10 << 24 >> 24 == 0;
+ if ($tobool42) {
+ $retval_0 = 0;
+ label = 28;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $cmp44 = ($iter_1 | 0) > 99;
+ if ($cmp44) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $11 = HEAP32[_stderr >> 2] | 0;
+ $call47 = _fputc(10, $11 | 0) | 0;
+ label = 27;
+ break;
+ case 27:
+ $12 = HEAP32[_stderr >> 2] | 0;
+ $13 = HEAP32[41584] | 0;
+ $14 = HEAP32[41606] | 0;
+ $call49 = +_elapsed_sec();
+ $call50 = _fprintf($12 | 0, 110368, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = 102112, HEAP32[tempInt + 8 >> 2] = $13, HEAP32[tempInt + 16 >> 2] = $14, HEAP32[tempInt + 24 >> 2] = $iter_1, HEAPF64[tempInt + 32 >> 3] = $call49, tempInt) | 0) | 0;
+ $retval_0 = 0;
+ label = 28;
+ break;
+ case 28:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _leave_edge() {
+ var $0 = 0, $1 = 0, $cmp20 = 0, $2 = 0, $cnt_022 = 0, $rv_021 = 0, $3 = 0, $arrayidx = 0, $4 = 0, $cutvalue = 0, $5 = 0, $cmp1 = 0, $tobool = 0, $cutvalue4 = 0, $6 = 0, $cmp7 = 0, $_rv_0 = 0, $rv_1 = 0, $inc = 0, $7 = 0, $cmp11 = 0, $rv_2 = 0, $cnt_1 = 0, $8 = 0, $inc15 = 0, $9 = 0, $cmp = 0, $cnt_0_lcssa = 0, $rv_0_lcssa = 0, $cmp16 = 0, $cnt_215 = 0, $rv_314 = 0, $storemerge13 = 0, $10 = 0, $arrayidx21 = 0, $11 = 0, $cutvalue23 = 0, $12 = 0, $cmp24 = 0, $tobool26 = 0, $cutvalue29 = 0, $13 = 0, $cmp32 = 0, $_rv_3 = 0, $rv_4 = 0, $inc38 = 0, $14 = 0, $cmp39 = 0, $rv_5 = 0, $cnt_3 = 0, $15 = 0, $inc43 = 0, $cmp19 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41522] | 0;
+ $1 = HEAP32[41338] | 0;
+ $cmp20 = ($0 | 0) < ($1 | 0);
+ if ($cmp20) {
+ $rv_021 = 0;
+ $cnt_022 = 0;
+ $2 = $0;
+ label = 3;
+ break;
+ } else {
+ $rv_0_lcssa = 0;
+ $cnt_0_lcssa = 0;
+ label = 8;
+ break;
+ }
+ case 3:
+ $3 = HEAP32[41340] | 0;
+ $arrayidx = $3 + ($2 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $cutvalue = $4 + 176 | 0;
+ $5 = HEAP32[$cutvalue >> 2] | 0;
+ $cmp1 = ($5 | 0) < 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ $cnt_1 = $cnt_022;
+ $rv_2 = $rv_021;
+ label = 7;
+ break;
+ }
+ case 4:
+ $tobool = ($rv_021 | 0) == 0;
+ if ($tobool) {
+ $rv_1 = $4;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cutvalue4 = $rv_021 + 176 | 0;
+ $6 = HEAP32[$cutvalue4 >> 2] | 0;
+ $cmp7 = ($6 | 0) > ($5 | 0);
+ $_rv_0 = $cmp7 ? $4 : $rv_021;
+ $rv_1 = $_rv_0;
+ label = 6;
+ break;
+ case 6:
+ $inc = $cnt_022 + 1 | 0;
+ $7 = HEAP32[41520] | 0;
+ $cmp11 = ($inc | 0) < ($7 | 0);
+ if ($cmp11) {
+ $cnt_1 = $inc;
+ $rv_2 = $rv_1;
+ label = 7;
+ break;
+ } else {
+ $retval_0 = $rv_1;
+ label = 15;
+ break;
+ }
+ case 7:
+ $8 = HEAP32[41522] | 0;
+ $inc15 = $8 + 1 | 0;
+ HEAP32[41522] = $inc15;
+ $9 = HEAP32[41338] | 0;
+ $cmp = ($inc15 | 0) < ($9 | 0);
+ if ($cmp) {
+ $rv_021 = $rv_2;
+ $cnt_022 = $cnt_1;
+ $2 = $inc15;
+ label = 3;
+ break;
+ } else {
+ $rv_0_lcssa = $rv_2;
+ $cnt_0_lcssa = $cnt_1;
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp16 = ($0 | 0) > 0;
+ if ($cmp16) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = $rv_0_lcssa;
+ label = 15;
+ break;
+ }
+ case 9:
+ HEAP32[41522] = 0;
+ $storemerge13 = 0;
+ $rv_314 = $rv_0_lcssa;
+ $cnt_215 = $cnt_0_lcssa;
+ label = 10;
+ break;
+ case 10:
+ $10 = HEAP32[41340] | 0;
+ $arrayidx21 = $10 + ($storemerge13 << 2) | 0;
+ $11 = HEAP32[$arrayidx21 >> 2] | 0;
+ $cutvalue23 = $11 + 176 | 0;
+ $12 = HEAP32[$cutvalue23 >> 2] | 0;
+ $cmp24 = ($12 | 0) < 0;
+ if ($cmp24) {
+ label = 11;
+ break;
+ } else {
+ $cnt_3 = $cnt_215;
+ $rv_5 = $rv_314;
+ label = 14;
+ break;
+ }
+ case 11:
+ $tobool26 = ($rv_314 | 0) == 0;
+ if ($tobool26) {
+ $rv_4 = $11;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $cutvalue29 = $rv_314 + 176 | 0;
+ $13 = HEAP32[$cutvalue29 >> 2] | 0;
+ $cmp32 = ($13 | 0) > ($12 | 0);
+ $_rv_3 = $cmp32 ? $11 : $rv_314;
+ $rv_4 = $_rv_3;
+ label = 13;
+ break;
+ case 13:
+ $inc38 = $cnt_215 + 1 | 0;
+ $14 = HEAP32[41520] | 0;
+ $cmp39 = ($inc38 | 0) < ($14 | 0);
+ if ($cmp39) {
+ $cnt_3 = $inc38;
+ $rv_5 = $rv_4;
+ label = 14;
+ break;
+ } else {
+ $retval_0 = $rv_4;
+ label = 15;
+ break;
+ }
+ case 14:
+ $15 = HEAP32[41522] | 0;
+ $inc43 = $15 + 1 | 0;
+ HEAP32[41522] = $inc43;
+ $cmp19 = ($inc43 | 0) < ($0 | 0);
+ if ($cmp19) {
+ $storemerge13 = $inc43;
+ $rv_314 = $rv_5;
+ $cnt_215 = $cnt_3;
+ label = 10;
+ break;
+ } else {
+ $retval_0 = $rv_5;
+ label = 15;
+ break;
+ }
+ case 15:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _init_graph($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_040 = 0, $tobool41 = 0, $n_042 = 0, $mark = 0, $0 = 0, $inc = 0, $list = 0, $1 = 0, $2 = 0, $tobool438 = 0, $i_039 = 0, $3 = 0, $inc6 = 0, $inc7 = 0, $4 = 0, $arrayidx = 0, $5 = 0, $tobool4 = 0, $next = 0, $n_0 = 0, $tobool = 0, $6 = 0, $tobool11 = 0, $7 = 0, $8 = 0, $mul = 0, $call = 0, $9 = 0, $mul12 = 0, $call13 = 0, $call_sink = 0, $10 = 0, $11 = 0, $tobool14 = 0, $12 = 0, $13 = 0, $mul16 = 0, $call17 = 0, $14 = 0, $mul19 = 0, $call20 = 0, $call17_sink = 0, $15 = 0, $n_132 = 0, $tobool2633 = 0, $n_135 = 0, $feasible_034 = 0, $priority = 0, $list31 = 0, $16 = 0, $17 = 0, $tobool3328 = 0, $18 = 0, $feasible_130 = 0, $i_129 = 0, $19 = 0, $inc37 = 0, $cutvalue = 0, $tree_index = 0, $tobool40 = 0, $head = 0, $20 = 0, $rank = 0, $21 = 0, $tail = 0, $22 = 0, $rank43 = 0, $23 = 0, $sub = 0, $minlen = 0, $24 = 0, $conv = 0, $cmp = 0, $_feasible_1 = 0, $feasible_2 = 0, $inc47 = 0, $25 = 0, $arrayidx32 = 0, $26 = 0, $tobool33 = 0, $phitmp = 0, $phitmp43 = 0, $feasible_1_lcssa = 0, $i_1_lcssa = 0, $call50 = 0, $27 = 0, $list52 = 0, $size = 0, $list58 = 0, $28 = 0, $i_2 = 0, $arrayidx59 = 0, $29 = 0, $tobool60 = 0, $inc63 = 0, $mul66 = 0, $call67 = 0, $30 = 0, $list69 = 0, $size72 = 0, $next75 = 0, $n_1 = 0, $tobool26 = 0, $feasible_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[41882] = $g;
+ HEAP32[41522] = 0;
+ HEAP32[41606] = 0;
+ HEAP32[41584] = 0;
+ $nlist = $g + 220 | 0;
+ $n_040 = HEAP32[$nlist >> 2] | 0;
+ $tobool41 = ($n_040 | 0) == 0;
+ if ($tobool41) {
+ label = 6;
+ break;
+ } else {
+ $n_042 = $n_040;
+ label = 3;
+ break;
+ }
+ case 3:
+ $mark = $n_042 + 163 | 0;
+ HEAP8[$mark] = 0;
+ $0 = HEAP32[41584] | 0;
+ $inc = $0 + 1 | 0;
+ HEAP32[41584] = $inc;
+ $list = $n_042 + 184 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool438 = ($2 | 0) == 0;
+ if ($tobool438) {
+ label = 5;
+ break;
+ } else {
+ $i_039 = 0;
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP32[41606] | 0;
+ $inc6 = $3 + 1 | 0;
+ HEAP32[41606] = $inc6;
+ $inc7 = $i_039 + 1 | 0;
+ $4 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $4 + ($inc7 << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool4 = ($5 | 0) == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ $i_039 = $inc7;
+ label = 4;
+ break;
+ }
+ case 5:
+ $next = $n_042 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_042 = $n_0;
+ label = 3;
+ break;
+ }
+ case 6:
+ $6 = HEAP32[41336] | 0;
+ $tobool11 = ($6 | 0) == 0;
+ if ($tobool11) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $7 = $6;
+ $8 = HEAP32[41584] | 0;
+ $mul = $8 << 2;
+ $call = _grealloc($7, $mul) | 0;
+ $call_sink = $call;
+ label = 9;
+ break;
+ case 8:
+ $9 = HEAP32[41584] | 0;
+ $mul12 = $9 << 2;
+ $call13 = _gmalloc($mul12) | 0;
+ $call_sink = $call13;
+ label = 9;
+ break;
+ case 9:
+ $10 = $call_sink;
+ HEAP32[41336] = $10;
+ HEAP32[41334] = 0;
+ $11 = HEAP32[41340] | 0;
+ $tobool14 = ($11 | 0) == 0;
+ if ($tobool14) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $12 = $11;
+ $13 = HEAP32[41584] | 0;
+ $mul16 = $13 << 2;
+ $call17 = _grealloc($12, $mul16) | 0;
+ $call17_sink = $call17;
+ label = 12;
+ break;
+ case 11:
+ $14 = HEAP32[41584] | 0;
+ $mul19 = $14 << 2;
+ $call20 = _gmalloc($mul19) | 0;
+ $call17_sink = $call20;
+ label = 12;
+ break;
+ case 12:
+ $15 = $call17_sink;
+ HEAP32[41340] = $15;
+ HEAP32[41338] = 0;
+ $n_132 = HEAP32[$nlist >> 2] | 0;
+ $tobool2633 = ($n_132 | 0) == 0;
+ if ($tobool2633) {
+ $feasible_0_lcssa = 1;
+ label = 21;
+ break;
+ } else {
+ $feasible_034 = 1;
+ $n_135 = $n_132;
+ label = 13;
+ break;
+ }
+ case 13:
+ $priority = $n_135 + 292 | 0;
+ HEAP32[$priority >> 2] = 0;
+ $list31 = $n_135 + 176 | 0;
+ $16 = HEAP32[$list31 >> 2] | 0;
+ $17 = HEAP32[$16 >> 2] | 0;
+ $tobool3328 = ($17 | 0) == 0;
+ if ($tobool3328) {
+ $i_1_lcssa = 4;
+ $feasible_1_lcssa = $feasible_034;
+ label = 18;
+ break;
+ } else {
+ $i_129 = 0;
+ $feasible_130 = $feasible_034;
+ $18 = $17;
+ label = 14;
+ break;
+ }
+ case 14:
+ $19 = HEAP32[$priority >> 2] | 0;
+ $inc37 = $19 + 1 | 0;
+ HEAP32[$priority >> 2] = $inc37;
+ $cutvalue = $18 + 176 | 0;
+ HEAP32[$cutvalue >> 2] = 0;
+ $tree_index = $18 + 180 | 0;
+ HEAP32[$tree_index >> 2] = -1;
+ $tobool40 = ($feasible_130 | 0) == 0;
+ if ($tobool40) {
+ $feasible_2 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $head = $18 + 12 | 0;
+ $20 = HEAP32[$head >> 2] | 0;
+ $rank = $20 + 236 | 0;
+ $21 = HEAP32[$rank >> 2] | 0;
+ $tail = $18 + 16 | 0;
+ $22 = HEAP32[$tail >> 2] | 0;
+ $rank43 = $22 + 236 | 0;
+ $23 = HEAP32[$rank43 >> 2] | 0;
+ $sub = $21 - $23 | 0;
+ $minlen = $18 + 186 | 0;
+ $24 = HEAP16[$minlen >> 1] | 0;
+ $conv = $24 & 65535;
+ $cmp = ($sub | 0) < ($conv | 0);
+ $_feasible_1 = $cmp ? 0 : $feasible_130;
+ $feasible_2 = $_feasible_1;
+ label = 16;
+ break;
+ case 16:
+ $inc47 = $i_129 + 1 | 0;
+ $25 = HEAP32[$list31 >> 2] | 0;
+ $arrayidx32 = $25 + ($inc47 << 2) | 0;
+ $26 = HEAP32[$arrayidx32 >> 2] | 0;
+ $tobool33 = ($26 | 0) == 0;
+ if ($tobool33) {
+ label = 17;
+ break;
+ } else {
+ $i_129 = $inc47;
+ $feasible_130 = $feasible_2;
+ $18 = $26;
+ label = 14;
+ break;
+ }
+ case 17:
+ $phitmp = $inc47 << 2;
+ $phitmp43 = $phitmp + 4 | 0;
+ $i_1_lcssa = $phitmp43;
+ $feasible_1_lcssa = $feasible_2;
+ label = 18;
+ break;
+ case 18:
+ $call50 = _zmalloc($i_1_lcssa) | 0;
+ $27 = $call50;
+ $list52 = $n_135 + 264 | 0;
+ HEAP32[$list52 >> 2] = $27;
+ $size = $n_135 + 268 | 0;
+ HEAP32[$size >> 2] = 0;
+ $list58 = $n_135 + 184 | 0;
+ $28 = HEAP32[$list58 >> 2] | 0;
+ $i_2 = 0;
+ label = 19;
+ break;
+ case 19:
+ $arrayidx59 = $28 + ($i_2 << 2) | 0;
+ $29 = HEAP32[$arrayidx59 >> 2] | 0;
+ $tobool60 = ($29 | 0) == 0;
+ $inc63 = $i_2 + 1 | 0;
+ if ($tobool60) {
+ label = 20;
+ break;
+ } else {
+ $i_2 = $inc63;
+ label = 19;
+ break;
+ }
+ case 20:
+ $mul66 = $inc63 << 2;
+ $call67 = _zmalloc($mul66) | 0;
+ $30 = $call67;
+ $list69 = $n_135 + 272 | 0;
+ HEAP32[$list69 >> 2] = $30;
+ $size72 = $n_135 + 276 | 0;
+ HEAP32[$size72 >> 2] = 0;
+ $next75 = $n_135 + 168 | 0;
+ $n_1 = HEAP32[$next75 >> 2] | 0;
+ $tobool26 = ($n_1 | 0) == 0;
+ if ($tobool26) {
+ $feasible_0_lcssa = $feasible_1_lcssa;
+ label = 21;
+ break;
+ } else {
+ $feasible_034 = $feasible_1_lcssa;
+ $n_135 = $n_1;
+ label = 13;
+ break;
+ }
+ case 21:
+ return $feasible_0_lcssa | 0;
+ }
+ return 0;
+}
+function _init_rank() {
+ var $0 = 0, $call = 0, $1 = 0, $nlist = 0, $v_040 = 0, $tobool41 = 0, $call336 = 0, $tobool437 = 0, $v_042 = 0, $priority = 0, $2 = 0, $cmp = 0, $next = 0, $v_0 = 0, $tobool = 0, $call3 = 0, $tobool4 = 0, $call339 = 0, $ctr_038 = 0, $rank = 0, $inc = 0, $list = 0, $3 = 0, $4 = 0, $tobool831 = 0, $5 = 0, $i_032 = 0, $6 = 0, $tail = 0, $7 = 0, $rank13 = 0, $8 = 0, $minlen = 0, $9 = 0, $conv = 0, $add = 0, $cmp15 = 0, $_add = 0, $inc29 = 0, $10 = 0, $arrayidx = 0, $11 = 0, $tobool8 = 0, $list33 = 0, $12 = 0, $13 = 0, $tobool3534 = 0, $14 = 0, $i_135 = 0, $head = 0, $15 = 0, $priority38 = 0, $16 = 0, $dec = 0, $cmp39 = 0, $17 = 0, $inc45 = 0, $18 = 0, $arrayidx34 = 0, $19 = 0, $tobool35 = 0, $ctr_0_lcssa = 0, $20 = 0, $cmp47 = 0, $call50 = 0, $21 = 0, $nlist52 = 0, $v_127 = 0, $tobool5428 = 0, $v_129 = 0, $priority57 = 0, $22 = 0, $tobool58 = 0, $name = 0, $23 = 0, $call62 = 0, $next66 = 0, $v_1 = 0, $tobool54 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41584] | 0;
+ $call = _new_queue($0) | 0;
+ $1 = HEAP32[41882] | 0;
+ $nlist = $1 + 220 | 0;
+ $v_040 = HEAP32[$nlist >> 2] | 0;
+ $tobool41 = ($v_040 | 0) == 0;
+ if ($tobool41) {
+ label = 3;
+ break;
+ } else {
+ $v_042 = $v_040;
+ label = 4;
+ break;
+ }
+ case 3:
+ $call336 = _dequeue($call) | 0;
+ $tobool437 = ($call336 | 0) == 0;
+ if ($tobool437) {
+ $ctr_0_lcssa = 0;
+ label = 14;
+ break;
+ } else {
+ $ctr_038 = 0;
+ $call339 = $call336;
+ label = 8;
+ break;
+ }
+ case 4:
+ $priority = $v_042 + 292 | 0;
+ $2 = HEAP32[$priority >> 2] | 0;
+ $cmp = ($2 | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ _enqueue($call, $v_042);
+ label = 6;
+ break;
+ case 6:
+ $next = $v_042 + 168 | 0;
+ $v_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($v_0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $v_042 = $v_0;
+ label = 4;
+ break;
+ }
+ case 7:
+ $call3 = _dequeue($call) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ $ctr_0_lcssa = $inc;
+ label = 14;
+ break;
+ } else {
+ $ctr_038 = $inc;
+ $call339 = $call3;
+ label = 8;
+ break;
+ }
+ case 8:
+ $rank = $call339 + 236 | 0;
+ HEAP32[$rank >> 2] = 0;
+ $inc = $ctr_038 + 1 | 0;
+ $list = $call339 + 176 | 0;
+ $3 = HEAP32[$list >> 2] | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $tobool831 = ($4 | 0) == 0;
+ if ($tobool831) {
+ label = 10;
+ break;
+ } else {
+ $i_032 = 0;
+ $5 = $4;
+ label = 9;
+ break;
+ }
+ case 9:
+ $6 = HEAP32[$rank >> 2] | 0;
+ $tail = $5 + 16 | 0;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $rank13 = $7 + 236 | 0;
+ $8 = HEAP32[$rank13 >> 2] | 0;
+ $minlen = $5 + 186 | 0;
+ $9 = HEAP16[$minlen >> 1] | 0;
+ $conv = $9 & 65535;
+ $add = $conv + $8 | 0;
+ $cmp15 = ($6 | 0) > ($add | 0);
+ $_add = $cmp15 ? $6 : $add;
+ HEAP32[$rank >> 2] = $_add;
+ $inc29 = $i_032 + 1 | 0;
+ $10 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $10 + ($inc29 << 2) | 0;
+ $11 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool8 = ($11 | 0) == 0;
+ if ($tobool8) {
+ label = 10;
+ break;
+ } else {
+ $i_032 = $inc29;
+ $5 = $11;
+ label = 9;
+ break;
+ }
+ case 10:
+ $list33 = $call339 + 184 | 0;
+ $12 = HEAP32[$list33 >> 2] | 0;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $tobool3534 = ($13 | 0) == 0;
+ if ($tobool3534) {
+ label = 7;
+ break;
+ } else {
+ $i_135 = 0;
+ $14 = $13;
+ label = 11;
+ break;
+ }
+ case 11:
+ $head = $14 + 12 | 0;
+ $15 = HEAP32[$head >> 2] | 0;
+ $priority38 = $15 + 292 | 0;
+ $16 = HEAP32[$priority38 >> 2] | 0;
+ $dec = $16 - 1 | 0;
+ HEAP32[$priority38 >> 2] = $dec;
+ $cmp39 = ($dec | 0) < 1;
+ if ($cmp39) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $17 = HEAP32[$head >> 2] | 0;
+ _enqueue($call, $17);
+ label = 13;
+ break;
+ case 13:
+ $inc45 = $i_135 + 1 | 0;
+ $18 = HEAP32[$list33 >> 2] | 0;
+ $arrayidx34 = $18 + ($inc45 << 2) | 0;
+ $19 = HEAP32[$arrayidx34 >> 2] | 0;
+ $tobool35 = ($19 | 0) == 0;
+ if ($tobool35) {
+ label = 7;
+ break;
+ } else {
+ $i_135 = $inc45;
+ $14 = $19;
+ label = 11;
+ break;
+ }
+ case 14:
+ $20 = HEAP32[41584] | 0;
+ $cmp47 = ($ctr_0_lcssa | 0) == ($20 | 0);
+ if ($cmp47) {
+ label = 19;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $call50 = _agerr(1, 106192, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $21 = HEAP32[41882] | 0;
+ $nlist52 = $21 + 220 | 0;
+ $v_127 = HEAP32[$nlist52 >> 2] | 0;
+ $tobool5428 = ($v_127 | 0) == 0;
+ if ($tobool5428) {
+ label = 19;
+ break;
+ } else {
+ $v_129 = $v_127;
+ label = 16;
+ break;
+ }
+ case 16:
+ $priority57 = $v_129 + 292 | 0;
+ $22 = HEAP32[$priority57 >> 2] | 0;
+ $tobool58 = ($22 | 0) == 0;
+ if ($tobool58) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $name = $v_129 + 12 | 0;
+ $23 = HEAP32[$name >> 2] | 0;
+ $call62 = _agerr(3, 102288, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $23, HEAP32[tempInt + 8 >> 2] = $22, tempInt) | 0) | 0;
+ label = 18;
+ break;
+ case 18:
+ $next66 = $v_129 + 168 | 0;
+ $v_1 = HEAP32[$next66 >> 2] | 0;
+ $tobool54 = ($v_1 | 0) == 0;
+ if ($tobool54) {
+ label = 19;
+ break;
+ } else {
+ $v_129 = $v_1;
+ label = 16;
+ break;
+ }
+ case 19:
+ _free_queue($call);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _freeTreeList() {
+ var $0 = 0, $nlist = 0, $n_01 = 0, $tobool3 = 0, $n_04 = 0, $list = 0, $1 = 0, $tobool2 = 0, $2 = 0, $list8 = 0, $3 = 0, $tobool9 = 0, $4 = 0, $mark = 0, $next = 0, $n_0 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41882] | 0;
+ $nlist = $0 + 220 | 0;
+ $n_01 = HEAP32[$nlist >> 2] | 0;
+ $tobool3 = ($n_01 | 0) == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ $n_04 = $n_01;
+ label = 3;
+ break;
+ }
+ case 3:
+ $list = $n_04 + 264 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = $1;
+ _free($2);
+ label = 5;
+ break;
+ case 5:
+ $list8 = $n_04 + 272 | 0;
+ $3 = HEAP32[$list8 >> 2] | 0;
+ $tobool9 = ($3 | 0) == 0;
+ if ($tobool9) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $4 = $3;
+ _free($4);
+ label = 7;
+ break;
+ case 7:
+ $mark = $n_04 + 163 | 0;
+ HEAP8[$mark] = 0;
+ $next = $n_04 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $n_04 = $n_0;
+ label = 3;
+ break;
+ }
+ case 8:
+ return;
+ }
+}
+function _feasible_tree() {
+ var $0 = 0, $cmp = 0, $call35 = 0, $1 = 0, $cmp136 = 0, $2 = 0, $nlist = 0, $n_028 = 0, $tobool29 = 0, $n_031 = 0, $e_030 = 0, $list = 0, $3 = 0, $4 = 0, $tobool425 = 0, $5 = 0, $6 = 0, $e_127 = 0, $i_026 = 0, $tree_index = 0, $7 = 0, $cmp8 = 0, $call10 = 0, $tobool11 = 0, $cmp13 = 0, $head = 0, $8 = 0, $rank = 0, $9 = 0, $tail = 0, $10 = 0, $rank17 = 0, $11 = 0, $sub = 0, $minlen = 0, $12 = 0, $conv19 = 0, $sub20 = 0, $head21 = 0, $13 = 0, $rank23 = 0, $14 = 0, $tail24 = 0, $15 = 0, $rank26 = 0, $16 = 0, $sub27 = 0, $minlen29 = 0, $17 = 0, $conv30 = 0, $sub31 = 0, $cmp32 = 0, $e_2 = 0, $inc = 0, $arrayidx = 0, $18 = 0, $tobool4 = 0, $e_1_lcssa = 0, $next = 0, $n_0 = 0, $tobool = 0, $tobool39 = 0, $head41 = 0, $19 = 0, $rank43 = 0, $20 = 0, $tail44 = 0, $21 = 0, $rank46 = 0, $22 = 0, $sub47 = 0, $minlen49 = 0, $23 = 0, $conv50 = 0, $sub51 = 0, $tobool52 = 0, $call = 0, $24 = 0, $cmp1 = 0, $call54 = 0, $cmp56 = 0, $sub59 = 0, $sub59_sub51 = 0, $25 = 0, $cmp6233 = 0, $i_134 = 0, $26 = 0, $arrayidx65 = 0, $27 = 0, $rank67 = 0, $28 = 0, $add = 0, $inc69 = 0, $29 = 0, $cmp62 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41584] | 0;
+ $cmp = ($0 | 0) < 2;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 20;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call35 = _tight_tree() | 0;
+ $1 = HEAP32[41584] | 0;
+ $cmp136 = ($call35 | 0) < ($1 | 0);
+ if ($cmp136) {
+ label = 4;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[41882] | 0;
+ $nlist = $2 + 220 | 0;
+ $n_028 = HEAP32[$nlist >> 2] | 0;
+ $tobool29 = ($n_028 | 0) == 0;
+ if ($tobool29) {
+ $retval_0 = 1;
+ label = 20;
+ break;
+ } else {
+ $e_030 = 0;
+ $n_031 = $n_028;
+ label = 5;
+ break;
+ }
+ case 5:
+ $list = $n_031 + 184 | 0;
+ $3 = HEAP32[$list >> 2] | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $tobool425 = ($4 | 0) == 0;
+ if ($tobool425) {
+ $e_1_lcssa = $e_030;
+ label = 13;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $5 = HEAP32[$list >> 2] | 0;
+ $i_026 = 0;
+ $e_127 = $e_030;
+ $6 = $4;
+ label = 7;
+ break;
+ case 7:
+ $tree_index = $6 + 180 | 0;
+ $7 = HEAP32[$tree_index >> 2] | 0;
+ $cmp8 = ($7 | 0) < 0;
+ if ($cmp8) {
+ label = 8;
+ break;
+ } else {
+ $e_2 = $e_127;
+ label = 12;
+ break;
+ }
+ case 8:
+ $call10 = _incident($6) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ if ($tobool11) {
+ $e_2 = $e_127;
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp13 = ($e_127 | 0) == 0;
+ if ($cmp13) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $head = $6 + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $rank = $8 + 236 | 0;
+ $9 = HEAP32[$rank >> 2] | 0;
+ $tail = $6 + 16 | 0;
+ $10 = HEAP32[$tail >> 2] | 0;
+ $rank17 = $10 + 236 | 0;
+ $11 = HEAP32[$rank17 >> 2] | 0;
+ $sub = $9 - $11 | 0;
+ $minlen = $6 + 186 | 0;
+ $12 = HEAP16[$minlen >> 1] | 0;
+ $conv19 = $12 & 65535;
+ $sub20 = $sub - $conv19 | 0;
+ $head21 = $e_127 + 12 | 0;
+ $13 = HEAP32[$head21 >> 2] | 0;
+ $rank23 = $13 + 236 | 0;
+ $14 = HEAP32[$rank23 >> 2] | 0;
+ $tail24 = $e_127 + 16 | 0;
+ $15 = HEAP32[$tail24 >> 2] | 0;
+ $rank26 = $15 + 236 | 0;
+ $16 = HEAP32[$rank26 >> 2] | 0;
+ $sub27 = $14 - $16 | 0;
+ $minlen29 = $e_127 + 186 | 0;
+ $17 = HEAP16[$minlen29 >> 1] | 0;
+ $conv30 = $17 & 65535;
+ $sub31 = $sub27 - $conv30 | 0;
+ $cmp32 = ($sub20 | 0) < ($sub31 | 0);
+ if ($cmp32) {
+ label = 11;
+ break;
+ } else {
+ $e_2 = $e_127;
+ label = 12;
+ break;
+ }
+ case 11:
+ $e_2 = $6;
+ label = 12;
+ break;
+ case 12:
+ $inc = $i_026 + 1 | 0;
+ $arrayidx = $5 + ($inc << 2) | 0;
+ $18 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool4 = ($18 | 0) == 0;
+ if ($tobool4) {
+ $e_1_lcssa = $e_2;
+ label = 13;
+ break;
+ } else {
+ $i_026 = $inc;
+ $e_127 = $e_2;
+ $6 = $18;
+ label = 7;
+ break;
+ }
+ case 13:
+ $next = $n_031 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ $e_030 = $e_1_lcssa;
+ $n_031 = $n_0;
+ label = 5;
+ break;
+ }
+ case 14:
+ $tobool39 = ($e_1_lcssa | 0) == 0;
+ if ($tobool39) {
+ $retval_0 = 1;
+ label = 20;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $head41 = $e_1_lcssa + 12 | 0;
+ $19 = HEAP32[$head41 >> 2] | 0;
+ $rank43 = $19 + 236 | 0;
+ $20 = HEAP32[$rank43 >> 2] | 0;
+ $tail44 = $e_1_lcssa + 16 | 0;
+ $21 = HEAP32[$tail44 >> 2] | 0;
+ $rank46 = $21 + 236 | 0;
+ $22 = HEAP32[$rank46 >> 2] | 0;
+ $sub47 = $20 - $22 | 0;
+ $minlen49 = $e_1_lcssa + 186 | 0;
+ $23 = HEAP16[$minlen49 >> 1] | 0;
+ $conv50 = $23 & 65535;
+ $sub51 = $sub47 - $conv50 | 0;
+ $tobool52 = ($sub47 | 0) == ($conv50 | 0);
+ if ($tobool52) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $call = _tight_tree() | 0;
+ $24 = HEAP32[41584] | 0;
+ $cmp1 = ($call | 0) < ($24 | 0);
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 17:
+ $call54 = _incident($e_1_lcssa) | 0;
+ $cmp56 = ($call54 | 0) == ($19 | 0);
+ $sub59 = -$sub51 | 0;
+ $sub59_sub51 = $cmp56 ? $sub59 : $sub51;
+ $25 = HEAP32[41334] | 0;
+ $cmp6233 = ($25 | 0) > 0;
+ if ($cmp6233) {
+ $i_134 = 0;
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 18:
+ $26 = HEAP32[41336] | 0;
+ $arrayidx65 = $26 + ($i_134 << 2) | 0;
+ $27 = HEAP32[$arrayidx65 >> 2] | 0;
+ $rank67 = $27 + 236 | 0;
+ $28 = HEAP32[$rank67 >> 2] | 0;
+ $add = $28 + $sub59_sub51 | 0;
+ HEAP32[$rank67 >> 2] = $add;
+ $inc69 = $i_134 + 1 | 0;
+ $29 = HEAP32[41334] | 0;
+ $cmp62 = ($inc69 | 0) < ($29 | 0);
+ if ($cmp62) {
+ $i_134 = $inc69;
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 19:
+ _init_cutvalues();
+ $retval_0 = 0;
+ label = 20;
+ break;
+ case 20:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _enter_edge($e) {
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $lim = 0, $1 = 0, $head = 0, $2 = 0, $lim2 = 0, $3 = 0, $cmp = 0, $_ = 0, $low = 0, $4 = 0, $lim7 = 0, $5 = 0, $6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $lim = $0 + 288 | 0;
+ $1 = HEAP32[$lim >> 2] | 0;
+ $head = $e + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $lim2 = $2 + 288 | 0;
+ $3 = HEAP32[$lim2 >> 2] | 0;
+ $cmp = ($1 | 0) < ($3 | 0);
+ $_ = $cmp ? $0 : $2;
+ HEAP32[41890] = 0;
+ HEAP32[41360] = 2147483647;
+ $low = $_ + 284 | 0;
+ $4 = HEAP32[$low >> 2] | 0;
+ HEAP32[41636] = $4;
+ $lim7 = $_ + 288 | 0;
+ $5 = HEAP32[$lim7 >> 2] | 0;
+ HEAP32[41642] = $5;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _dfs_enter_outedge($_);
+ label = 5;
+ break;
+ case 4:
+ _dfs_enter_inedge($_);
+ label = 5;
+ break;
+ case 5:
+ $6 = HEAP32[41890] | 0;
+ return $6 | 0;
+ }
+ return 0;
+}
+function _TB_balance() {
+ var $0 = 0, $add = 0, $mul = 0, $call = 0, $1 = 0, $2 = 0, $cmp77 = 0, $i_078 = 0, $arrayidx = 0, $inc = 0, $3 = 0, $cmp = 0, $4 = 0, $nlist = 0, $n_074 = 0, $tobool75 = 0, $n_076 = 0, $node_type = 0, $5 = 0, $cmp4 = 0, $rank = 0, $6 = 0, $arrayidx7 = 0, $7 = 0, $inc8 = 0, $next = 0, $n_0 = 0, $tobool = 0, $8 = 0, $nlist13 = 0, $n_169 = 0, $tobool1570 = 0, $n_171 = 0, $node_type18 = 0, $9 = 0, $cmp20 = 0, $10 = 0, $list = 0, $11 = 0, $12 = 0, $tobool2752 = 0, $13 = 0, $14 = 0, $inweight_055 = 0, $low_054 = 0, $i_153 = 0, $weight = 0, $15 = 0.0, $conv30 = 0.0, $add31 = 0.0, $conv32 = 0, $tail = 0, $16 = 0, $rank34 = 0, $17 = 0, $minlen = 0, $18 = 0, $conv36 = 0, $add37 = 0, $cmp38 = 0, $low_0_add37 = 0, $inc48 = 0, $arrayidx26 = 0, $19 = 0, $tobool27 = 0, $inweight_0_lcssa = 0, $low_0_lcssa = 0, $list52 = 0, $20 = 0, $21 = 0, $tobool5458 = 0, $22 = 0, $23 = 0, $outweight_061 = 0, $high_060 = 0, $i_259 = 0, $weight57 = 0, $24 = 0.0, $conv58 = 0.0, $add59 = 0.0, $conv60 = 0, $head = 0, $25 = 0, $rank62 = 0, $26 = 0, $minlen64 = 0, $27 = 0, $conv65 = 0, $sub = 0, $cmp66 = 0, $high_0_sub = 0, $inc80 = 0, $arrayidx53 = 0, $28 = 0, $tobool54 = 0, $outweight_0_lcssa = 0, $high_0_lcssa = 0, $cmp82 = 0, $_low_0 = 0, $cmp86 = 0, $i_364 = 0, $cmp9165 = 0, $i_367 = 0, $choice_066 = 0, $arrayidx94 = 0, $29 = 0, $arrayidx95 = 0, $30 = 0, $cmp96 = 0, $i_3_choice_0 = 0, $i_3 = 0, $cmp91 = 0, $choice_0_lcssa = 0, $rank104 = 0, $31 = 0, $arrayidx105 = 0, $32 = 0, $dec = 0, $arrayidx106 = 0, $33 = 0, $inc107 = 0, $list112 = 0, $34 = 0, $tobool113 = 0, $35 = 0, $list121 = 0, $36 = 0, $tobool122 = 0, $37 = 0, $mark = 0, $next132 = 0, $n_1 = 0, $tobool15 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _scan_and_normalize();
+ $0 = HEAP32[41632] | 0;
+ $add = $0 << 2;
+ $mul = $add + 4 | 0;
+ $call = _zmalloc($mul) | 0;
+ $1 = $call;
+ $2 = HEAP32[41632] | 0;
+ $cmp77 = ($2 | 0) < 0;
+ if ($cmp77) {
+ label = 4;
+ break;
+ } else {
+ $i_078 = 0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $1 + ($i_078 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = 0;
+ $inc = $i_078 + 1 | 0;
+ $3 = HEAP32[41632] | 0;
+ $cmp = ($inc | 0) > ($3 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $i_078 = $inc;
+ label = 3;
+ break;
+ }
+ case 4:
+ $4 = HEAP32[41882] | 0;
+ $nlist = $4 + 220 | 0;
+ $n_074 = HEAP32[$nlist >> 2] | 0;
+ $tobool75 = ($n_074 | 0) == 0;
+ if ($tobool75) {
+ label = 8;
+ break;
+ } else {
+ $n_076 = $n_074;
+ label = 5;
+ break;
+ }
+ case 5:
+ $node_type = $n_076 + 162 | 0;
+ $5 = HEAP8[$node_type] | 0;
+ $cmp4 = $5 << 24 >> 24 == 0;
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $rank = $n_076 + 236 | 0;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $arrayidx7 = $1 + ($6 << 2) | 0;
+ $7 = HEAP32[$arrayidx7 >> 2] | 0;
+ $inc8 = $7 + 1 | 0;
+ HEAP32[$arrayidx7 >> 2] = $inc8;
+ label = 7;
+ break;
+ case 7:
+ $next = $n_076 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $n_076 = $n_0;
+ label = 5;
+ break;
+ }
+ case 8:
+ $8 = HEAP32[41882] | 0;
+ $nlist13 = $8 + 220 | 0;
+ $n_169 = HEAP32[$nlist13 >> 2] | 0;
+ $tobool1570 = ($n_169 | 0) == 0;
+ if ($tobool1570) {
+ label = 26;
+ break;
+ } else {
+ $n_171 = $n_169;
+ label = 9;
+ break;
+ }
+ case 9:
+ $node_type18 = $n_171 + 162 | 0;
+ $9 = HEAP8[$node_type18] | 0;
+ $cmp20 = $9 << 24 >> 24 == 0;
+ if ($cmp20) {
+ label = 10;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 10:
+ $10 = HEAP32[41632] | 0;
+ $list = $n_171 + 176 | 0;
+ $11 = HEAP32[$list >> 2] | 0;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $tobool2752 = ($12 | 0) == 0;
+ if ($tobool2752) {
+ $low_0_lcssa = 0;
+ $inweight_0_lcssa = 0;
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $13 = HEAP32[$list >> 2] | 0;
+ $i_153 = 0;
+ $low_054 = 0;
+ $inweight_055 = 0;
+ $14 = $12;
+ label = 12;
+ break;
+ case 12:
+ $weight = $14 + 172 | 0;
+ $15 = +HEAPF32[$weight >> 2];
+ $conv30 = +($inweight_055 | 0);
+ $add31 = $conv30 + $15;
+ $conv32 = ~~$add31;
+ $tail = $14 + 16 | 0;
+ $16 = HEAP32[$tail >> 2] | 0;
+ $rank34 = $16 + 236 | 0;
+ $17 = HEAP32[$rank34 >> 2] | 0;
+ $minlen = $14 + 186 | 0;
+ $18 = HEAP16[$minlen >> 1] | 0;
+ $conv36 = $18 & 65535;
+ $add37 = $conv36 + $17 | 0;
+ $cmp38 = ($low_054 | 0) > ($add37 | 0);
+ $low_0_add37 = $cmp38 ? $low_054 : $add37;
+ $inc48 = $i_153 + 1 | 0;
+ $arrayidx26 = $13 + ($inc48 << 2) | 0;
+ $19 = HEAP32[$arrayidx26 >> 2] | 0;
+ $tobool27 = ($19 | 0) == 0;
+ if ($tobool27) {
+ $low_0_lcssa = $low_0_add37;
+ $inweight_0_lcssa = $conv32;
+ label = 13;
+ break;
+ } else {
+ $i_153 = $inc48;
+ $low_054 = $low_0_add37;
+ $inweight_055 = $conv32;
+ $14 = $19;
+ label = 12;
+ break;
+ }
+ case 13:
+ $list52 = $n_171 + 184 | 0;
+ $20 = HEAP32[$list52 >> 2] | 0;
+ $21 = HEAP32[$20 >> 2] | 0;
+ $tobool5458 = ($21 | 0) == 0;
+ if ($tobool5458) {
+ $high_0_lcssa = $10;
+ $outweight_0_lcssa = 0;
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $22 = HEAP32[$list52 >> 2] | 0;
+ $i_259 = 0;
+ $high_060 = $10;
+ $outweight_061 = 0;
+ $23 = $21;
+ label = 15;
+ break;
+ case 15:
+ $weight57 = $23 + 172 | 0;
+ $24 = +HEAPF32[$weight57 >> 2];
+ $conv58 = +($outweight_061 | 0);
+ $add59 = $conv58 + $24;
+ $conv60 = ~~$add59;
+ $head = $23 + 12 | 0;
+ $25 = HEAP32[$head >> 2] | 0;
+ $rank62 = $25 + 236 | 0;
+ $26 = HEAP32[$rank62 >> 2] | 0;
+ $minlen64 = $23 + 186 | 0;
+ $27 = HEAP16[$minlen64 >> 1] | 0;
+ $conv65 = $27 & 65535;
+ $sub = $26 - $conv65 | 0;
+ $cmp66 = ($high_060 | 0) < ($sub | 0);
+ $high_0_sub = $cmp66 ? $high_060 : $sub;
+ $inc80 = $i_259 + 1 | 0;
+ $arrayidx53 = $22 + ($inc80 << 2) | 0;
+ $28 = HEAP32[$arrayidx53 >> 2] | 0;
+ $tobool54 = ($28 | 0) == 0;
+ if ($tobool54) {
+ $high_0_lcssa = $high_0_sub;
+ $outweight_0_lcssa = $conv60;
+ label = 16;
+ break;
+ } else {
+ $i_259 = $inc80;
+ $high_060 = $high_0_sub;
+ $outweight_061 = $conv60;
+ $23 = $28;
+ label = 15;
+ break;
+ }
+ case 16:
+ $cmp82 = ($low_0_lcssa | 0) < 0;
+ $_low_0 = $cmp82 ? 0 : $low_0_lcssa;
+ $cmp86 = ($inweight_0_lcssa | 0) == ($outweight_0_lcssa | 0);
+ if ($cmp86) {
+ label = 17;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 17:
+ $i_364 = $_low_0 + 1 | 0;
+ $cmp9165 = ($i_364 | 0) > ($high_0_lcssa | 0);
+ if ($cmp9165) {
+ $choice_0_lcssa = $_low_0;
+ label = 19;
+ break;
+ } else {
+ $choice_066 = $_low_0;
+ $i_367 = $i_364;
+ label = 18;
+ break;
+ }
+ case 18:
+ $arrayidx94 = $1 + ($i_367 << 2) | 0;
+ $29 = HEAP32[$arrayidx94 >> 2] | 0;
+ $arrayidx95 = $1 + ($choice_066 << 2) | 0;
+ $30 = HEAP32[$arrayidx95 >> 2] | 0;
+ $cmp96 = ($29 | 0) < ($30 | 0);
+ $i_3_choice_0 = $cmp96 ? $i_367 : $choice_066;
+ $i_3 = $i_367 + 1 | 0;
+ $cmp91 = ($i_3 | 0) > ($high_0_lcssa | 0);
+ if ($cmp91) {
+ $choice_0_lcssa = $i_3_choice_0;
+ label = 19;
+ break;
+ } else {
+ $choice_066 = $i_3_choice_0;
+ $i_367 = $i_3;
+ label = 18;
+ break;
+ }
+ case 19:
+ $rank104 = $n_171 + 236 | 0;
+ $31 = HEAP32[$rank104 >> 2] | 0;
+ $arrayidx105 = $1 + ($31 << 2) | 0;
+ $32 = HEAP32[$arrayidx105 >> 2] | 0;
+ $dec = $32 - 1 | 0;
+ HEAP32[$arrayidx105 >> 2] = $dec;
+ $arrayidx106 = $1 + ($choice_0_lcssa << 2) | 0;
+ $33 = HEAP32[$arrayidx106 >> 2] | 0;
+ $inc107 = $33 + 1 | 0;
+ HEAP32[$arrayidx106 >> 2] = $inc107;
+ HEAP32[$rank104 >> 2] = $choice_0_lcssa;
+ label = 20;
+ break;
+ case 20:
+ $list112 = $n_171 + 264 | 0;
+ $34 = HEAP32[$list112 >> 2] | 0;
+ $tobool113 = ($34 | 0) == 0;
+ if ($tobool113) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $35 = $34;
+ _free($35);
+ label = 22;
+ break;
+ case 22:
+ $list121 = $n_171 + 272 | 0;
+ $36 = HEAP32[$list121 >> 2] | 0;
+ $tobool122 = ($36 | 0) == 0;
+ if ($tobool122) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $37 = $36;
+ _free($37);
+ label = 24;
+ break;
+ case 24:
+ $mark = $n_171 + 163 | 0;
+ HEAP8[$mark] = 0;
+ label = 25;
+ break;
+ case 25:
+ $next132 = $n_171 + 168 | 0;
+ $n_1 = HEAP32[$next132 >> 2] | 0;
+ $tobool15 = ($n_1 | 0) == 0;
+ if ($tobool15) {
+ label = 26;
+ break;
+ } else {
+ $n_171 = $n_1;
+ label = 9;
+ break;
+ }
+ case 26:
+ _free($call);
+ return;
+ }
+}
+function _update($e, $f) {
+ $e = $e | 0;
+ $f = $f | 0;
+ var $head = 0, $0 = 0, $rank = 0, $1 = 0, $tail = 0, $2 = 0, $rank2 = 0, $3 = 0, $sub = 0, $minlen = 0, $4 = 0, $conv = 0, $sub4 = 0, $cmp = 0, $tail6 = 0, $5 = 0, $size = 0, $6 = 0, $size10 = 0, $7 = 0, $add = 0, $cmp11 = 0, $head15 = 0, $8 = 0, $size18 = 0, $9 = 0, $size22 = 0, $10 = 0, $add23 = 0, $cmp24 = 0, $sub28 = 0, $lim = 0, $11 = 0, $lim34 = 0, $12 = 0, $cmp35 = 0, $sub41 = 0, $cutvalue46 = 0, $13 = 0, $14 = 0, $15 = 0, $call = 0, $16 = 0, $17 = 0, $call51 = 0, $cmp52 = 0, $sub56 = 0, $cutvalue58 = 0, $par = 0, $18 = 0, $low = 0, $19 = 0, $call63 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $head = $f + 12 | 0;
+ $0 = HEAP32[$head >> 2] | 0;
+ $rank = $0 + 236 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $tail = $f + 16 | 0;
+ $2 = HEAP32[$tail >> 2] | 0;
+ $rank2 = $2 + 236 | 0;
+ $3 = HEAP32[$rank2 >> 2] | 0;
+ $sub = $1 - $3 | 0;
+ $minlen = $f + 186 | 0;
+ $4 = HEAP16[$minlen >> 1] | 0;
+ $conv = $4 & 65535;
+ $sub4 = $sub - $conv | 0;
+ $cmp = ($sub4 | 0) > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $tail6 = $e + 16 | 0;
+ $5 = HEAP32[$tail6 >> 2] | 0;
+ $size = $5 + 268 | 0;
+ $6 = HEAP32[$size >> 2] | 0;
+ $size10 = $5 + 276 | 0;
+ $7 = HEAP32[$size10 >> 2] | 0;
+ $add = $7 + $6 | 0;
+ $cmp11 = ($add | 0) == 1;
+ if ($cmp11) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ _rerank($5, $sub4);
+ label = 10;
+ break;
+ case 5:
+ $head15 = $e + 12 | 0;
+ $8 = HEAP32[$head15 >> 2] | 0;
+ $size18 = $8 + 268 | 0;
+ $9 = HEAP32[$size18 >> 2] | 0;
+ $size22 = $8 + 276 | 0;
+ $10 = HEAP32[$size22 >> 2] | 0;
+ $add23 = $10 + $9 | 0;
+ $cmp24 = ($add23 | 0) == 1;
+ if ($cmp24) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $sub28 = -$sub4 | 0;
+ _rerank($8, $sub28);
+ label = 10;
+ break;
+ case 7:
+ $lim = $5 + 288 | 0;
+ $11 = HEAP32[$lim >> 2] | 0;
+ $lim34 = $8 + 288 | 0;
+ $12 = HEAP32[$lim34 >> 2] | 0;
+ $cmp35 = ($11 | 0) < ($12 | 0);
+ if ($cmp35) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ _rerank($5, $sub4);
+ label = 10;
+ break;
+ case 9:
+ $sub41 = -$sub4 | 0;
+ _rerank($8, $sub41);
+ label = 10;
+ break;
+ case 10:
+ $cutvalue46 = $e + 176 | 0;
+ $13 = HEAP32[$cutvalue46 >> 2] | 0;
+ $14 = HEAP32[$tail >> 2] | 0;
+ $15 = HEAP32[$head >> 2] | 0;
+ $call = _treeupdate($14, $15, $13, 1) | 0;
+ $16 = HEAP32[$head >> 2] | 0;
+ $17 = HEAP32[$tail >> 2] | 0;
+ $call51 = _treeupdate($16, $17, $13, 0) | 0;
+ $cmp52 = ($call51 | 0) == ($call | 0);
+ if ($cmp52) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ _abort();
+ case 12:
+ $sub56 = -$13 | 0;
+ $cutvalue58 = $f + 176 | 0;
+ HEAP32[$cutvalue58 >> 2] = $sub56;
+ HEAP32[$cutvalue46 >> 2] = 0;
+ _exchange_tree_edges($e, $f);
+ $par = $call + 280 | 0;
+ $18 = HEAP32[$par >> 2] | 0;
+ $low = $call + 284 | 0;
+ $19 = HEAP32[$low >> 2] | 0;
+ $call63 = _dfs_range($call, $18, $19) | 0;
+ return;
+ }
+}
+function _scan_and_normalize() {
+ var $0 = 0, $nlist = 0, $n_013 = 0, $tobool14 = 0, $n_015 = 0, $node_type = 0, $1 = 0, $cmp = 0, $2 = 0, $rank = 0, $3 = 0, $cmp4 = 0, $_ = 0, $4 = 0, $5 = 0, $cmp10 = 0, $cond17 = 0, $next = 0, $n_0 = 0, $tobool = 0, $6 = 0, $cmp19 = 0, $7 = 0, $nlist23 = 0, $n_110 = 0, $tobool2511 = 0, $8 = 0, $9 = 0, $n_112 = 0, $rank28 = 0, $10 = 0, $sub = 0, $next31 = 0, $n_1 = 0, $tobool25 = 0, $11 = 0, $_lcssa = 0, $12 = 0, $sub33 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[41628] = 2147483647;
+ HEAP32[41632] = -2147483647;
+ $0 = HEAP32[41882] | 0;
+ $nlist = $0 + 220 | 0;
+ $n_013 = HEAP32[$nlist >> 2] | 0;
+ $tobool14 = ($n_013 | 0) == 0;
+ if ($tobool14) {
+ label = 6;
+ break;
+ } else {
+ $n_015 = $n_013;
+ label = 3;
+ break;
+ }
+ case 3:
+ $node_type = $n_015 + 162 | 0;
+ $1 = HEAP8[$node_type] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[41628] | 0;
+ $rank = $n_015 + 236 | 0;
+ $3 = HEAP32[$rank >> 2] | 0;
+ $cmp4 = ($2 | 0) < ($3 | 0);
+ $_ = $cmp4 ? $2 : $3;
+ HEAP32[41628] = $_;
+ $4 = HEAP32[41632] | 0;
+ $5 = HEAP32[$rank >> 2] | 0;
+ $cmp10 = ($4 | 0) > ($5 | 0);
+ $cond17 = $cmp10 ? $4 : $5;
+ HEAP32[41632] = $cond17;
+ label = 5;
+ break;
+ case 5:
+ $next = $n_015 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_015 = $n_0;
+ label = 3;
+ break;
+ }
+ case 6:
+ $6 = HEAP32[41628] | 0;
+ $cmp19 = ($6 | 0) == 0;
+ if ($cmp19) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $7 = HEAP32[41882] | 0;
+ $nlist23 = $7 + 220 | 0;
+ $n_110 = HEAP32[$nlist23 >> 2] | 0;
+ $tobool2511 = ($n_110 | 0) == 0;
+ $8 = HEAP32[41628] | 0;
+ if ($tobool2511) {
+ $_lcssa = $8;
+ label = 9;
+ break;
+ } else {
+ $n_112 = $n_110;
+ $9 = $8;
+ label = 8;
+ break;
+ }
+ case 8:
+ $rank28 = $n_112 + 236 | 0;
+ $10 = HEAP32[$rank28 >> 2] | 0;
+ $sub = $10 - $9 | 0;
+ HEAP32[$rank28 >> 2] = $sub;
+ $next31 = $n_112 + 168 | 0;
+ $n_1 = HEAP32[$next31 >> 2] | 0;
+ $tobool25 = ($n_1 | 0) == 0;
+ $11 = HEAP32[41628] | 0;
+ if ($tobool25) {
+ $_lcssa = $11;
+ label = 9;
+ break;
+ } else {
+ $n_112 = $n_1;
+ $9 = $11;
+ label = 8;
+ break;
+ }
+ case 9:
+ $12 = HEAP32[41632] | 0;
+ $sub33 = $12 - $_lcssa | 0;
+ HEAP32[41632] = $sub33;
+ HEAP32[41628] = 0;
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _treeupdate($v, $w, $cutvalue, $dir) {
+ $v = $v | 0;
+ $w = $w | 0;
+ $cutvalue = $cutvalue | 0;
+ $dir = $dir | 0;
+ var $lim = 0, $0 = 0, $lnot9 = 0, $lnot_ext = 0, $v_addr_0 = 0, $low = 0, $1 = 0, $2 = 0, $cmp = 0, $lim5 = 0, $3 = 0, $phitmp = 0, $par = 0, $4 = 0, $tail = 0, $5 = 0, $cmp8 = 0, $dir_lnot_ext = 0, $tobool10 = 0, $cutvalue13 = 0, $6 = 0, $storemerge_p = 0, $storemerge = 0, $7 = 0, $lim20 = 0, $8 = 0, $head = 0, $9 = 0, $lim22 = 0, $10 = 0, $cmp23 = 0, $_ = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $lim = $w + 288 | 0;
+ $0 = -$cutvalue | 0;
+ $lnot9 = ($dir | 0) == 0;
+ $lnot_ext = $lnot9 & 1;
+ $v_addr_0 = $v;
+ label = 3;
+ break;
+ case 3:
+ $low = $v_addr_0 + 284 | 0;
+ $1 = HEAP32[$low >> 2] | 0;
+ $2 = HEAP32[$lim >> 2] | 0;
+ $cmp = ($1 | 0) > ($2 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $lim5 = $v_addr_0 + 288 | 0;
+ $3 = HEAP32[$lim5 >> 2] | 0;
+ $phitmp = ($2 | 0) > ($3 | 0);
+ if ($phitmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $par = $v_addr_0 + 280 | 0;
+ $4 = HEAP32[$par >> 2] | 0;
+ $tail = $4 + 16 | 0;
+ $5 = HEAP32[$tail >> 2] | 0;
+ $cmp8 = ($v_addr_0 | 0) == ($5 | 0);
+ $dir_lnot_ext = $cmp8 ? $dir : $lnot_ext;
+ $tobool10 = ($dir_lnot_ext | 0) == 0;
+ $cutvalue13 = $4 + 176 | 0;
+ $6 = HEAP32[$cutvalue13 >> 2] | 0;
+ $storemerge_p = $tobool10 ? $0 : $cutvalue;
+ $storemerge = $storemerge_p + $6 | 0;
+ HEAP32[$cutvalue13 >> 2] = $storemerge;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $lim20 = $7 + 288 | 0;
+ $8 = HEAP32[$lim20 >> 2] | 0;
+ $head = $4 + 12 | 0;
+ $9 = HEAP32[$head >> 2] | 0;
+ $lim22 = $9 + 288 | 0;
+ $10 = HEAP32[$lim22 >> 2] | 0;
+ $cmp23 = ($8 | 0) > ($10 | 0);
+ $_ = $cmp23 ? $7 : $9;
+ $v_addr_0 = $_;
+ label = 3;
+ break;
+ case 6:
+ return $v_addr_0 | 0;
+ }
+ return 0;
+}
+function _exchange_tree_edges($e, $f) {
+ $e = $e | 0;
+ $f = $f | 0;
+ var $tree_index = 0, $0 = 0, $tree_index2 = 0, $1 = 0, $2 = 0, $arrayidx = 0, $tail = 0, $3 = 0, $tree_out = 0, $size = 0, $4 = 0, $dec = 0, $list = 0, $j_0 = 0, $cmp = 0, $5 = 0, $arrayidx10 = 0, $6 = 0, $cmp11 = 0, $inc = 0, $list14 = 0, $7 = 0, $arrayidx15 = 0, $8 = 0, $arrayidx19 = 0, $9 = 0, $arrayidx23 = 0, $head = 0, $10 = 0, $tree_in = 0, $size25 = 0, $11 = 0, $dec26 = 0, $list32 = 0, $j_1 = 0, $cmp28 = 0, $12 = 0, $arrayidx33 = 0, $13 = 0, $cmp34 = 0, $inc38 = 0, $list42 = 0, $14 = 0, $arrayidx43 = 0, $15 = 0, $arrayidx47 = 0, $16 = 0, $arrayidx51 = 0, $tail52 = 0, $17 = 0, $size55 = 0, $18 = 0, $inc56 = 0, $list59 = 0, $19 = 0, $arrayidx60 = 0, $20 = 0, $21 = 0, $arrayidx67 = 0, $head68 = 0, $22 = 0, $size71 = 0, $23 = 0, $inc72 = 0, $list75 = 0, $24 = 0, $arrayidx76 = 0, $25 = 0, $26 = 0, $arrayidx83 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tree_index = $e + 180 | 0;
+ $0 = HEAP32[$tree_index >> 2] | 0;
+ $tree_index2 = $f + 180 | 0;
+ HEAP32[$tree_index2 >> 2] = $0;
+ $1 = HEAP32[$tree_index >> 2] | 0;
+ $2 = HEAP32[41340] | 0;
+ $arrayidx = $2 + ($1 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $f;
+ HEAP32[$tree_index >> 2] = -1;
+ $tail = $e + 16 | 0;
+ $3 = HEAP32[$tail >> 2] | 0;
+ $tree_out = $3 + 272 | 0;
+ $size = $3 + 276 | 0;
+ $4 = HEAP32[$size >> 2] | 0;
+ $dec = $4 - 1 | 0;
+ HEAP32[$size >> 2] = $dec;
+ $list = $tree_out | 0;
+ $j_0 = 0;
+ label = 3;
+ break;
+ case 3:
+ $cmp = ($j_0 | 0) > ($dec | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $5 = HEAP32[$list >> 2] | 0;
+ $arrayidx10 = $5 + ($j_0 << 2) | 0;
+ $6 = HEAP32[$arrayidx10 >> 2] | 0;
+ $cmp11 = ($6 | 0) == ($e | 0);
+ $inc = $j_0 + 1 | 0;
+ if ($cmp11) {
+ label = 5;
+ break;
+ } else {
+ $j_0 = $inc;
+ label = 3;
+ break;
+ }
+ case 5:
+ $list14 = $tree_out | 0;
+ $7 = HEAP32[$list14 >> 2] | 0;
+ $arrayidx15 = $7 + ($dec << 2) | 0;
+ $8 = HEAP32[$arrayidx15 >> 2] | 0;
+ $arrayidx19 = $7 + ($j_0 << 2) | 0;
+ HEAP32[$arrayidx19 >> 2] = $8;
+ $9 = HEAP32[$list14 >> 2] | 0;
+ $arrayidx23 = $9 + ($dec << 2) | 0;
+ HEAP32[$arrayidx23 >> 2] = 0;
+ $head = $e + 12 | 0;
+ $10 = HEAP32[$head >> 2] | 0;
+ $tree_in = $10 + 264 | 0;
+ $size25 = $10 + 268 | 0;
+ $11 = HEAP32[$size25 >> 2] | 0;
+ $dec26 = $11 - 1 | 0;
+ HEAP32[$size25 >> 2] = $dec26;
+ $list32 = $tree_in | 0;
+ $j_1 = 0;
+ label = 6;
+ break;
+ case 6:
+ $cmp28 = ($j_1 | 0) > ($dec26 | 0);
+ if ($cmp28) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $12 = HEAP32[$list32 >> 2] | 0;
+ $arrayidx33 = $12 + ($j_1 << 2) | 0;
+ $13 = HEAP32[$arrayidx33 >> 2] | 0;
+ $cmp34 = ($13 | 0) == ($e | 0);
+ $inc38 = $j_1 + 1 | 0;
+ if ($cmp34) {
+ label = 8;
+ break;
+ } else {
+ $j_1 = $inc38;
+ label = 6;
+ break;
+ }
+ case 8:
+ $list42 = $tree_in | 0;
+ $14 = HEAP32[$list42 >> 2] | 0;
+ $arrayidx43 = $14 + ($dec26 << 2) | 0;
+ $15 = HEAP32[$arrayidx43 >> 2] | 0;
+ $arrayidx47 = $14 + ($j_1 << 2) | 0;
+ HEAP32[$arrayidx47 >> 2] = $15;
+ $16 = HEAP32[$list42 >> 2] | 0;
+ $arrayidx51 = $16 + ($dec26 << 2) | 0;
+ HEAP32[$arrayidx51 >> 2] = 0;
+ $tail52 = $f + 16 | 0;
+ $17 = HEAP32[$tail52 >> 2] | 0;
+ $size55 = $17 + 276 | 0;
+ $18 = HEAP32[$size55 >> 2] | 0;
+ $inc56 = $18 + 1 | 0;
+ HEAP32[$size55 >> 2] = $inc56;
+ $list59 = $17 + 272 | 0;
+ $19 = HEAP32[$list59 >> 2] | 0;
+ $arrayidx60 = $19 + ($18 << 2) | 0;
+ HEAP32[$arrayidx60 >> 2] = $f;
+ $20 = HEAP32[$size55 >> 2] | 0;
+ $21 = HEAP32[$list59 >> 2] | 0;
+ $arrayidx67 = $21 + ($20 << 2) | 0;
+ HEAP32[$arrayidx67 >> 2] = 0;
+ $head68 = $f + 12 | 0;
+ $22 = HEAP32[$head68 >> 2] | 0;
+ $size71 = $22 + 268 | 0;
+ $23 = HEAP32[$size71 >> 2] | 0;
+ $inc72 = $23 + 1 | 0;
+ HEAP32[$size71 >> 2] = $inc72;
+ $list75 = $22 + 264 | 0;
+ $24 = HEAP32[$list75 >> 2] | 0;
+ $arrayidx76 = $24 + ($23 << 2) | 0;
+ HEAP32[$arrayidx76 >> 2] = $f;
+ $25 = HEAP32[$size71 >> 2] | 0;
+ $26 = HEAP32[$list75 >> 2] | 0;
+ $arrayidx83 = $26 + ($25 << 2) | 0;
+ HEAP32[$arrayidx83 >> 2] = 0;
+ return;
+ }
+}
+function _incident($e) {
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $mark = 0, $1 = 0, $tobool = 0, $head = 0, $2 = 0, $mark2 = 0, $3 = 0, $tobool9 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $mark = $0 + 163 | 0;
+ $1 = HEAP8[$mark] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ $head = $e + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $mark2 = $2 + 163 | 0;
+ $3 = HEAP8[$mark2] | 0;
+ $tobool9 = $3 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ if ($tobool9) {
+ $retval_0 = $0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ if ($tobool9) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = $2;
+ label = 6;
+ break;
+ }
+ case 5:
+ $retval_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _x_val($e, $v, $dir) {
+ $e = $e | 0;
+ $v = $v | 0;
+ $dir = $dir | 0;
+ var $tail = 0, $0 = 0, $cmp = 0, $head = 0, $1 = 0, $other_0 = 0, $low = 0, $2 = 0, $lim = 0, $3 = 0, $cmp3 = 0, $lim7 = 0, $4 = 0, $cmp8 = 0, $weight = 0, $5 = 0.0, $tree_index = 0, $6 = 0, $cmp13 = 0, $cutvalue = 0, $7 = 0, $phitmp = 0.0, $rv_0 = 0.0, $weight20 = 0, $8 = 0.0, $sub = 0.0, $rv_1_in = 0.0, $f_0 = 0, $rv_1 = 0, $cmp24 = 0, $head27 = 0, $_sink_in = 0, $_sink = 0, $cmp28 = 0, $_ = 0, $sub42 = 0, $d_1 = 0, $cmp44 = 0, $sub47 = 0, $sub47_rv_1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $cmp = ($0 | 0) == ($v | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $other_0 = $0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $head = $e + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $other_0 = $1;
+ label = 4;
+ break;
+ case 4:
+ $low = $v + 284 | 0;
+ $2 = HEAP32[$low >> 2] | 0;
+ $lim = $other_0 + 288 | 0;
+ $3 = HEAP32[$lim >> 2] | 0;
+ $cmp3 = ($2 | 0) > ($3 | 0);
+ if ($cmp3) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $lim7 = $v + 288 | 0;
+ $4 = HEAP32[$lim7 >> 2] | 0;
+ $cmp8 = ($3 | 0) > ($4 | 0);
+ if ($cmp8) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $weight = $e + 172 | 0;
+ $5 = +HEAPF32[$weight >> 2];
+ $f_0 = 0;
+ $rv_1_in = $5;
+ label = 10;
+ break;
+ case 7:
+ $tree_index = $e + 180 | 0;
+ $6 = HEAP32[$tree_index >> 2] | 0;
+ $cmp13 = ($6 | 0) > -1;
+ if ($cmp13) {
+ label = 8;
+ break;
+ } else {
+ $rv_0 = 0.0;
+ label = 9;
+ break;
+ }
+ case 8:
+ $cutvalue = $e + 176 | 0;
+ $7 = HEAP32[$cutvalue >> 2] | 0;
+ $phitmp = +($7 | 0);
+ $rv_0 = $phitmp;
+ label = 9;
+ break;
+ case 9:
+ $weight20 = $e + 172 | 0;
+ $8 = +HEAPF32[$weight20 >> 2];
+ $sub = $rv_0 - $8;
+ $f_0 = 1;
+ $rv_1_in = $sub;
+ label = 10;
+ break;
+ case 10:
+ $rv_1 = ~~$rv_1_in;
+ $cmp24 = ($dir | 0) > 0;
+ $head27 = $e + 12 | 0;
+ $_sink_in = $cmp24 ? $head27 : $tail;
+ $_sink = HEAP32[$_sink_in >> 2] | 0;
+ $cmp28 = ($_sink | 0) == ($v | 0);
+ $_ = $cmp28 ? 1 : -1;
+ $sub42 = -$_ | 0;
+ $d_1 = $f_0 ? $_ : $sub42;
+ $cmp44 = ($d_1 | 0) < 0;
+ $sub47 = -$rv_1 | 0;
+ $sub47_rv_1 = $cmp44 ? $sub47 : $rv_1;
+ return $sub47_rv_1 | 0;
+ }
+ return 0;
+}
+function _LR_balance() {
+ var $0 = 0, $cmp12 = 0, $i_013 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $cutvalue = 0, $3 = 0, $cmp1 = 0, $call = 0, $cmp2 = 0, $head = 0, $4 = 0, $rank = 0, $5 = 0, $tail = 0, $6 = 0, $rank6 = 0, $7 = 0, $sub = 0, $minlen = 0, $8 = 0, $conv = 0, $sub8 = 0, $cmp9 = 0, $tail13 = 0, $9 = 0, $lim = 0, $10 = 0, $head15 = 0, $11 = 0, $lim17 = 0, $12 = 0, $cmp18 = 0, $div = 0, $div24 = 0, $inc = 0, $13 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41338] | 0;
+ $cmp12 = ($0 | 0) > 0;
+ if ($cmp12) {
+ $i_013 = 0;
+ label = 3;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[41340] | 0;
+ $arrayidx = $1 + ($i_013 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $cutvalue = $2 + 176 | 0;
+ $3 = HEAP32[$cutvalue >> 2] | 0;
+ $cmp1 = ($3 | 0) == 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 4:
+ $call = _enter_edge($2) | 0;
+ $cmp2 = ($call | 0) == 0;
+ if ($cmp2) {
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $head = $call + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ $rank = $4 + 236 | 0;
+ $5 = HEAP32[$rank >> 2] | 0;
+ $tail = $call + 16 | 0;
+ $6 = HEAP32[$tail >> 2] | 0;
+ $rank6 = $6 + 236 | 0;
+ $7 = HEAP32[$rank6 >> 2] | 0;
+ $sub = $5 - $7 | 0;
+ $minlen = $call + 186 | 0;
+ $8 = HEAP16[$minlen >> 1] | 0;
+ $conv = $8 & 65535;
+ $sub8 = $sub - $conv | 0;
+ $cmp9 = ($sub8 | 0) < 2;
+ if ($cmp9) {
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $tail13 = $2 + 16 | 0;
+ $9 = HEAP32[$tail13 >> 2] | 0;
+ $lim = $9 + 288 | 0;
+ $10 = HEAP32[$lim >> 2] | 0;
+ $head15 = $2 + 12 | 0;
+ $11 = HEAP32[$head15 >> 2] | 0;
+ $lim17 = $11 + 288 | 0;
+ $12 = HEAP32[$lim17 >> 2] | 0;
+ $cmp18 = ($10 | 0) < ($12 | 0);
+ if ($cmp18) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $div = ($sub8 | 0) / 2 & -1;
+ _rerank($9, $div);
+ label = 9;
+ break;
+ case 8:
+ $div24 = ($sub8 | 0) / -2 & -1;
+ _rerank($11, $div24);
+ label = 9;
+ break;
+ case 9:
+ $inc = $i_013 + 1 | 0;
+ $13 = HEAP32[41338] | 0;
+ $cmp = ($inc | 0) < ($13 | 0);
+ if ($cmp) {
+ $i_013 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ _freeTreeList();
+ return;
+ }
+}
+function _rerank($v, $delta) {
+ $v = $v | 0;
+ $delta = $delta | 0;
+ var $rank = 0, $0 = 0, $sub = 0, $list = 0, $1 = 0, $2 = 0, $tobool15 = 0, $par = 0, $list5 = 0, $3 = 0, $4 = 0, $tobool713 = 0, $par10 = 0, $5 = 0, $i_016 = 0, $6 = 0, $cmp = 0, $head = 0, $7 = 0, $inc = 0, $8 = 0, $arrayidx = 0, $9 = 0, $tobool = 0, $10 = 0, $i_114 = 0, $11 = 0, $cmp11 = 0, $tail = 0, $12 = 0, $inc15 = 0, $13 = 0, $arrayidx6 = 0, $14 = 0, $tobool7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $v + 236 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $sub = $0 - $delta | 0;
+ HEAP32[$rank >> 2] = $sub;
+ $list = $v + 272 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool15 = ($2 | 0) == 0;
+ if ($tobool15) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $par = $v + 280 | 0;
+ $i_016 = 0;
+ $5 = $2;
+ label = 6;
+ break;
+ case 4:
+ $list5 = $v + 264 | 0;
+ $3 = HEAP32[$list5 >> 2] | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $tobool713 = ($4 | 0) == 0;
+ if ($tobool713) {
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $par10 = $v + 280 | 0;
+ $i_114 = 0;
+ $10 = $4;
+ label = 9;
+ break;
+ case 6:
+ $6 = HEAP32[$par >> 2] | 0;
+ $cmp = ($5 | 0) == ($6 | 0);
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $head = $5 + 12 | 0;
+ $7 = HEAP32[$head >> 2] | 0;
+ _rerank($7, $delta);
+ label = 8;
+ break;
+ case 8:
+ $inc = $i_016 + 1 | 0;
+ $8 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $8 + ($inc << 2) | 0;
+ $9 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($9 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $i_016 = $inc;
+ $5 = $9;
+ label = 6;
+ break;
+ }
+ case 9:
+ $11 = HEAP32[$par10 >> 2] | 0;
+ $cmp11 = ($10 | 0) == ($11 | 0);
+ if ($cmp11) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $tail = $10 + 16 | 0;
+ $12 = HEAP32[$tail >> 2] | 0;
+ _rerank($12, $delta);
+ label = 11;
+ break;
+ case 11:
+ $inc15 = $i_114 + 1 | 0;
+ $13 = HEAP32[$list5 >> 2] | 0;
+ $arrayidx6 = $13 + ($inc15 << 2) | 0;
+ $14 = HEAP32[$arrayidx6 >> 2] | 0;
+ $tobool7 = ($14 | 0) == 0;
+ if ($tobool7) {
+ label = 12;
+ break;
+ } else {
+ $i_114 = $inc15;
+ $10 = $14;
+ label = 9;
+ break;
+ }
+ case 12:
+ return;
+ }
+}
+function _dfs_range($v, $par, $low) {
+ $v = $v | 0;
+ $par = $par | 0;
+ $low = $low | 0;
+ var $par1 = 0, $low3 = 0, $list = 0, $0 = 0, $1 = 0, $tobool22 = 0, $lim_0_lcssa = 0, $list7 = 0, $2 = 0, $3 = 0, $tobool919 = 0, $4 = 0, $lim_024 = 0, $i_023 = 0, $cmp = 0, $head = 0, $5 = 0, $call = 0, $lim_1 = 0, $inc = 0, $6 = 0, $arrayidx = 0, $7 = 0, $tobool = 0, $8 = 0, $lim_221 = 0, $i_120 = 0, $cmp11 = 0, $tail = 0, $9 = 0, $call13 = 0, $lim_3 = 0, $inc16 = 0, $10 = 0, $arrayidx8 = 0, $11 = 0, $tobool9 = 0, $lim_2_lcssa = 0, $lim19 = 0, $add = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $par1 = $v + 280 | 0;
+ HEAP32[$par1 >> 2] = $par;
+ $low3 = $v + 284 | 0;
+ HEAP32[$low3 >> 2] = $low;
+ $list = $v + 272 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool22 = ($1 | 0) == 0;
+ if ($tobool22) {
+ $lim_0_lcssa = $low;
+ label = 3;
+ break;
+ } else {
+ $i_023 = 0;
+ $lim_024 = $low;
+ $4 = $1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $list7 = $v + 264 | 0;
+ $2 = HEAP32[$list7 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool919 = ($3 | 0) == 0;
+ if ($tobool919) {
+ $lim_2_lcssa = $lim_0_lcssa;
+ label = 10;
+ break;
+ } else {
+ $i_120 = 0;
+ $lim_221 = $lim_0_lcssa;
+ $8 = $3;
+ label = 7;
+ break;
+ }
+ case 4:
+ $cmp = ($4 | 0) == ($par | 0);
+ if ($cmp) {
+ $lim_1 = $lim_024;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $head = $4 + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $call = _dfs_range($5, $4, $lim_024) | 0;
+ $lim_1 = $call;
+ label = 6;
+ break;
+ case 6:
+ $inc = $i_023 + 1 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $6 + ($inc << 2) | 0;
+ $7 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($7 | 0) == 0;
+ if ($tobool) {
+ $lim_0_lcssa = $lim_1;
+ label = 3;
+ break;
+ } else {
+ $i_023 = $inc;
+ $lim_024 = $lim_1;
+ $4 = $7;
+ label = 4;
+ break;
+ }
+ case 7:
+ $cmp11 = ($8 | 0) == ($par | 0);
+ if ($cmp11) {
+ $lim_3 = $lim_221;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $tail = $8 + 16 | 0;
+ $9 = HEAP32[$tail >> 2] | 0;
+ $call13 = _dfs_range($9, $8, $lim_221) | 0;
+ $lim_3 = $call13;
+ label = 9;
+ break;
+ case 9:
+ $inc16 = $i_120 + 1 | 0;
+ $10 = HEAP32[$list7 >> 2] | 0;
+ $arrayidx8 = $10 + ($inc16 << 2) | 0;
+ $11 = HEAP32[$arrayidx8 >> 2] | 0;
+ $tobool9 = ($11 | 0) == 0;
+ if ($tobool9) {
+ $lim_2_lcssa = $lim_3;
+ label = 10;
+ break;
+ } else {
+ $i_120 = $inc16;
+ $lim_221 = $lim_3;
+ $8 = $11;
+ label = 7;
+ break;
+ }
+ case 10:
+ $lim19 = $v + 288 | 0;
+ HEAP32[$lim19 >> 2] = $lim_2_lcssa;
+ $add = $lim_2_lcssa + 1 | 0;
+ return $add | 0;
+ }
+ return 0;
+}
+function _dfs_enter_outedge($v) {
+ $v = $v | 0;
+ var $list = 0, $0 = 0, $1 = 0, $tobool24 = 0, $lim30 = 0, $list39 = 0, $2 = 0, $3 = 0, $tobool4120 = 0, $4 = 0, $cmp4221 = 0, $or_cond122 = 0, $lim49 = 0, $5 = 0, $i_025 = 0, $tree_index = 0, $6 = 0, $cmp2 = 0, $7 = 0, $head = 0, $8 = 0, $lim = 0, $9 = 0, $cmp5 = 0, $10 = 0, $cmp10 = 0, $or_cond19 = 0, $rank = 0, $11 = 0, $tail = 0, $12 = 0, $rank16 = 0, $13 = 0, $sub = 0, $minlen = 0, $14 = 0, $conv18 = 0, $sub19 = 0, $15 = 0, $cmp20 = 0, $16 = 0, $cmp22 = 0, $or_cond = 0, $head26 = 0, $17 = 0, $lim28 = 0, $18 = 0, $19 = 0, $cmp31 = 0, $inc = 0, $20 = 0, $arrayidx = 0, $21 = 0, $tobool = 0, $22 = 0, $i_123 = 0, $tail45 = 0, $23 = 0, $lim47 = 0, $24 = 0, $25 = 0, $cmp50 = 0, $inc56 = 0, $26 = 0, $arrayidx40 = 0, $27 = 0, $tobool41 = 0, $28 = 0, $cmp42 = 0, $or_cond1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $v + 184 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool24 = ($1 | 0) == 0;
+ if ($tobool24) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $lim30 = $v + 288 | 0;
+ $i_025 = 0;
+ $5 = $1;
+ label = 6;
+ break;
+ case 4:
+ $list39 = $v + 264 | 0;
+ $2 = HEAP32[$list39 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool4120 = ($3 | 0) != 0;
+ $4 = HEAP32[41360] | 0;
+ $cmp4221 = ($4 | 0) > 0;
+ $or_cond122 = $tobool4120 & $cmp4221;
+ if ($or_cond122) {
+ label = 5;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 5:
+ $lim49 = $v + 288 | 0;
+ $i_123 = 0;
+ $22 = $3;
+ label = 13;
+ break;
+ case 6:
+ $tree_index = $5 + 180 | 0;
+ $6 = HEAP32[$tree_index >> 2] | 0;
+ $cmp2 = ($6 | 0) < 0;
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $7 = HEAP32[41636] | 0;
+ $head = $5 + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $lim = $8 + 288 | 0;
+ $9 = HEAP32[$lim >> 2] | 0;
+ $cmp5 = ($7 | 0) > ($9 | 0);
+ $10 = HEAP32[41642] | 0;
+ $cmp10 = ($9 | 0) > ($10 | 0);
+ $or_cond19 = $cmp5 | $cmp10;
+ if ($or_cond19) {
+ label = 8;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 8:
+ $rank = $8 + 236 | 0;
+ $11 = HEAP32[$rank >> 2] | 0;
+ $tail = $5 + 16 | 0;
+ $12 = HEAP32[$tail >> 2] | 0;
+ $rank16 = $12 + 236 | 0;
+ $13 = HEAP32[$rank16 >> 2] | 0;
+ $sub = $11 - $13 | 0;
+ $minlen = $5 + 186 | 0;
+ $14 = HEAP16[$minlen >> 1] | 0;
+ $conv18 = $14 & 65535;
+ $sub19 = $sub - $conv18 | 0;
+ $15 = HEAP32[41360] | 0;
+ $cmp20 = ($sub19 | 0) < ($15 | 0);
+ $16 = HEAP32[41890] | 0;
+ $cmp22 = ($16 | 0) == 0;
+ $or_cond = $cmp20 | $cmp22;
+ if ($or_cond) {
+ label = 9;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 9:
+ HEAP32[41890] = $5;
+ HEAP32[41360] = $sub19;
+ label = 12;
+ break;
+ case 10:
+ $head26 = $5 + 12 | 0;
+ $17 = HEAP32[$head26 >> 2] | 0;
+ $lim28 = $17 + 288 | 0;
+ $18 = HEAP32[$lim28 >> 2] | 0;
+ $19 = HEAP32[$lim30 >> 2] | 0;
+ $cmp31 = ($18 | 0) < ($19 | 0);
+ if ($cmp31) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ _dfs_enter_outedge($17);
+ label = 12;
+ break;
+ case 12:
+ $inc = $i_025 + 1 | 0;
+ $20 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $20 + ($inc << 2) | 0;
+ $21 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($21 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $i_025 = $inc;
+ $5 = $21;
+ label = 6;
+ break;
+ }
+ case 13:
+ $tail45 = $22 + 16 | 0;
+ $23 = HEAP32[$tail45 >> 2] | 0;
+ $lim47 = $23 + 288 | 0;
+ $24 = HEAP32[$lim47 >> 2] | 0;
+ $25 = HEAP32[$lim49 >> 2] | 0;
+ $cmp50 = ($24 | 0) < ($25 | 0);
+ if ($cmp50) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ _dfs_enter_outedge($23);
+ label = 15;
+ break;
+ case 15:
+ $inc56 = $i_123 + 1 | 0;
+ $26 = HEAP32[$list39 >> 2] | 0;
+ $arrayidx40 = $26 + ($inc56 << 2) | 0;
+ $27 = HEAP32[$arrayidx40 >> 2] | 0;
+ $tobool41 = ($27 | 0) != 0;
+ $28 = HEAP32[41360] | 0;
+ $cmp42 = ($28 | 0) > 0;
+ $or_cond1 = $tobool41 & $cmp42;
+ if ($or_cond1) {
+ $i_123 = $inc56;
+ $22 = $27;
+ label = 13;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ return;
+ }
+}
+function _dfs_enter_inedge($v) {
+ $v = $v | 0;
+ var $list = 0, $0 = 0, $1 = 0, $tobool24 = 0, $lim30 = 0, $list39 = 0, $2 = 0, $3 = 0, $tobool4120 = 0, $4 = 0, $cmp4221 = 0, $or_cond122 = 0, $lim49 = 0, $5 = 0, $i_025 = 0, $tree_index = 0, $6 = 0, $cmp2 = 0, $7 = 0, $tail = 0, $8 = 0, $lim = 0, $9 = 0, $cmp5 = 0, $10 = 0, $cmp10 = 0, $or_cond19 = 0, $head = 0, $11 = 0, $rank = 0, $12 = 0, $rank16 = 0, $13 = 0, $sub = 0, $minlen = 0, $14 = 0, $conv18 = 0, $sub19 = 0, $15 = 0, $cmp20 = 0, $16 = 0, $cmp22 = 0, $or_cond = 0, $tail26 = 0, $17 = 0, $lim28 = 0, $18 = 0, $19 = 0, $cmp31 = 0, $inc = 0, $20 = 0, $arrayidx = 0, $21 = 0, $tobool = 0, $22 = 0, $i_123 = 0, $head45 = 0, $23 = 0, $lim47 = 0, $24 = 0, $25 = 0, $cmp50 = 0, $inc56 = 0, $26 = 0, $arrayidx40 = 0, $27 = 0, $tobool41 = 0, $28 = 0, $cmp42 = 0, $or_cond1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $v + 176 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool24 = ($1 | 0) == 0;
+ if ($tobool24) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $lim30 = $v + 288 | 0;
+ $i_025 = 0;
+ $5 = $1;
+ label = 6;
+ break;
+ case 4:
+ $list39 = $v + 272 | 0;
+ $2 = HEAP32[$list39 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool4120 = ($3 | 0) != 0;
+ $4 = HEAP32[41360] | 0;
+ $cmp4221 = ($4 | 0) > 0;
+ $or_cond122 = $tobool4120 & $cmp4221;
+ if ($or_cond122) {
+ label = 5;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 5:
+ $lim49 = $v + 288 | 0;
+ $i_123 = 0;
+ $22 = $3;
+ label = 13;
+ break;
+ case 6:
+ $tree_index = $5 + 180 | 0;
+ $6 = HEAP32[$tree_index >> 2] | 0;
+ $cmp2 = ($6 | 0) < 0;
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $7 = HEAP32[41636] | 0;
+ $tail = $5 + 16 | 0;
+ $8 = HEAP32[$tail >> 2] | 0;
+ $lim = $8 + 288 | 0;
+ $9 = HEAP32[$lim >> 2] | 0;
+ $cmp5 = ($7 | 0) > ($9 | 0);
+ $10 = HEAP32[41642] | 0;
+ $cmp10 = ($9 | 0) > ($10 | 0);
+ $or_cond19 = $cmp5 | $cmp10;
+ if ($or_cond19) {
+ label = 8;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 8:
+ $head = $5 + 12 | 0;
+ $11 = HEAP32[$head >> 2] | 0;
+ $rank = $11 + 236 | 0;
+ $12 = HEAP32[$rank >> 2] | 0;
+ $rank16 = $8 + 236 | 0;
+ $13 = HEAP32[$rank16 >> 2] | 0;
+ $sub = $12 - $13 | 0;
+ $minlen = $5 + 186 | 0;
+ $14 = HEAP16[$minlen >> 1] | 0;
+ $conv18 = $14 & 65535;
+ $sub19 = $sub - $conv18 | 0;
+ $15 = HEAP32[41360] | 0;
+ $cmp20 = ($sub19 | 0) < ($15 | 0);
+ $16 = HEAP32[41890] | 0;
+ $cmp22 = ($16 | 0) == 0;
+ $or_cond = $cmp20 | $cmp22;
+ if ($or_cond) {
+ label = 9;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 9:
+ HEAP32[41890] = $5;
+ HEAP32[41360] = $sub19;
+ label = 12;
+ break;
+ case 10:
+ $tail26 = $5 + 16 | 0;
+ $17 = HEAP32[$tail26 >> 2] | 0;
+ $lim28 = $17 + 288 | 0;
+ $18 = HEAP32[$lim28 >> 2] | 0;
+ $19 = HEAP32[$lim30 >> 2] | 0;
+ $cmp31 = ($18 | 0) < ($19 | 0);
+ if ($cmp31) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ _dfs_enter_inedge($17);
+ label = 12;
+ break;
+ case 12:
+ $inc = $i_025 + 1 | 0;
+ $20 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $20 + ($inc << 2) | 0;
+ $21 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($21 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $i_025 = $inc;
+ $5 = $21;
+ label = 6;
+ break;
+ }
+ case 13:
+ $head45 = $22 + 12 | 0;
+ $23 = HEAP32[$head45 >> 2] | 0;
+ $lim47 = $23 + 288 | 0;
+ $24 = HEAP32[$lim47 >> 2] | 0;
+ $25 = HEAP32[$lim49 >> 2] | 0;
+ $cmp50 = ($24 | 0) < ($25 | 0);
+ if ($cmp50) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ _dfs_enter_inedge($23);
+ label = 15;
+ break;
+ case 15:
+ $inc56 = $i_123 + 1 | 0;
+ $26 = HEAP32[$list39 >> 2] | 0;
+ $arrayidx40 = $26 + ($inc56 << 2) | 0;
+ $27 = HEAP32[$arrayidx40 >> 2] | 0;
+ $tobool41 = ($27 | 0) != 0;
+ $28 = HEAP32[41360] | 0;
+ $cmp42 = ($28 | 0) > 0;
+ $or_cond1 = $tobool41 & $cmp42;
+ if ($or_cond1) {
+ $i_123 = $inc56;
+ $22 = $27;
+ label = 13;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ return;
+ }
+}
+function _tight_tree() {
+ var $0 = 0, $nlist = 0, $n_019 = 0, $tobool20 = 0, $1 = 0, $cmp17 = 0, $n_021 = 0, $mark = 0, $list = 0, $2 = 0, $list4 = 0, $3 = 0, $size = 0, $size10 = 0, $next = 0, $n_0 = 0, $tobool = 0, $i_018 = 0, $4 = 0, $arrayidx14 = 0, $5 = 0, $tree_index = 0, $inc = 0, $6 = 0, $cmp = 0, $7 = 0, $nlist19 = 0, $n_112 = 0, $tobool2113 = 0, $n_116 = 0, $call = 0, $next26 = 0, $n_1 = 0, $tobool21 = 0, $8 = 0, $cmp22 = 0, $or_cond = 0, $9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41882] | 0;
+ $nlist = $0 + 220 | 0;
+ $n_019 = HEAP32[$nlist >> 2] | 0;
+ $tobool20 = ($n_019 | 0) == 0;
+ if ($tobool20) {
+ label = 3;
+ break;
+ } else {
+ $n_021 = $n_019;
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[41338] | 0;
+ $cmp17 = ($1 | 0) > 0;
+ if ($cmp17) {
+ $i_018 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $mark = $n_021 + 163 | 0;
+ HEAP8[$mark] = 0;
+ $list = $n_021 + 272 | 0;
+ $2 = HEAP32[$list >> 2] | 0;
+ HEAP32[$2 >> 2] = 0;
+ $list4 = $n_021 + 264 | 0;
+ $3 = HEAP32[$list4 >> 2] | 0;
+ HEAP32[$3 >> 2] = 0;
+ $size = $n_021 + 276 | 0;
+ HEAP32[$size >> 2] = 0;
+ $size10 = $n_021 + 268 | 0;
+ HEAP32[$size10 >> 2] = 0;
+ $next = $n_021 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $n_021 = $n_0;
+ label = 4;
+ break;
+ }
+ case 5:
+ $4 = HEAP32[41340] | 0;
+ $arrayidx14 = $4 + ($i_018 << 2) | 0;
+ $5 = HEAP32[$arrayidx14 >> 2] | 0;
+ $tree_index = $5 + 180 | 0;
+ HEAP32[$tree_index >> 2] = -1;
+ $inc = $i_018 + 1 | 0;
+ $6 = HEAP32[41338] | 0;
+ $cmp = ($inc | 0) < ($6 | 0);
+ if ($cmp) {
+ $i_018 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ HEAP32[41338] = 0;
+ HEAP32[41334] = 0;
+ $7 = HEAP32[41882] | 0;
+ $nlist19 = $7 + 220 | 0;
+ $n_112 = HEAP32[$nlist19 >> 2] | 0;
+ $tobool2113 = ($n_112 | 0) == 0;
+ if ($tobool2113) {
+ label = 8;
+ break;
+ } else {
+ $n_116 = $n_112;
+ label = 7;
+ break;
+ }
+ case 7:
+ $call = _treesearch($n_116) | 0;
+ $next26 = $n_116 + 168 | 0;
+ $n_1 = HEAP32[$next26 >> 2] | 0;
+ $tobool21 = ($n_1 | 0) != 0;
+ $8 = HEAP32[41338] | 0;
+ $cmp22 = ($8 | 0) == 0;
+ $or_cond = $tobool21 & $cmp22;
+ if ($or_cond) {
+ $n_116 = $n_1;
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $9 = HEAP32[41334] | 0;
+ return $9 | 0;
+ }
+ return 0;
+}
+function _init_cutvalues() {
+ _dfs_range(HEAP32[(HEAP32[41882] | 0) + 220 >> 2] | 0, 0, 1);
+ _dfs_cutval(HEAP32[(HEAP32[41882] | 0) + 220 >> 2] | 0, 0);
+ return;
+}
+function _dfs_cutval($v, $par) {
+ $v = $v | 0;
+ $par = $par | 0;
+ var $list = 0, $0 = 0, $1 = 0, $tobool15 = 0, $list3 = 0, $2 = 0, $3 = 0, $tobool513 = 0, $4 = 0, $i_016 = 0, $cmp = 0, $head = 0, $5 = 0, $inc = 0, $6 = 0, $arrayidx = 0, $7 = 0, $tobool = 0, $8 = 0, $i_114 = 0, $cmp7 = 0, $tail = 0, $9 = 0, $inc11 = 0, $10 = 0, $arrayidx4 = 0, $11 = 0, $tobool5 = 0, $tobool13 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $v + 272 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool15 = ($1 | 0) == 0;
+ if ($tobool15) {
+ label = 3;
+ break;
+ } else {
+ $i_016 = 0;
+ $4 = $1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $list3 = $v + 264 | 0;
+ $2 = HEAP32[$list3 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool513 = ($3 | 0) == 0;
+ if ($tobool513) {
+ label = 10;
+ break;
+ } else {
+ $i_114 = 0;
+ $8 = $3;
+ label = 7;
+ break;
+ }
+ case 4:
+ $cmp = ($4 | 0) == ($par | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $head = $4 + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ _dfs_cutval($5, $4);
+ label = 6;
+ break;
+ case 6:
+ $inc = $i_016 + 1 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $6 + ($inc << 2) | 0;
+ $7 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($7 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $i_016 = $inc;
+ $4 = $7;
+ label = 4;
+ break;
+ }
+ case 7:
+ $cmp7 = ($8 | 0) == ($par | 0);
+ if ($cmp7) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $tail = $8 + 16 | 0;
+ $9 = HEAP32[$tail >> 2] | 0;
+ _dfs_cutval($9, $8);
+ label = 9;
+ break;
+ case 9:
+ $inc11 = $i_114 + 1 | 0;
+ $10 = HEAP32[$list3 >> 2] | 0;
+ $arrayidx4 = $10 + ($inc11 << 2) | 0;
+ $11 = HEAP32[$arrayidx4 >> 2] | 0;
+ $tobool5 = ($11 | 0) == 0;
+ if ($tobool5) {
+ label = 10;
+ break;
+ } else {
+ $i_114 = $inc11;
+ $8 = $11;
+ label = 7;
+ break;
+ }
+ case 10:
+ $tobool13 = ($par | 0) == 0;
+ if ($tobool13) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ _x_cutval($par);
+ label = 12;
+ break;
+ case 12:
+ return;
+ }
+}
+function _x_cutval($f) {
+ $f = $f | 0;
+ var $tail = 0, $0 = 0, $par = 0, $1 = 0, $cmp = 0, $head = 0, $2 = 0, $v_0 = 0, $dir_0 = 0, $list = 0, $3 = 0, $4 = 0, $tobool17 = 0, $5 = 0, $sum_0_lcssa = 0, $list5 = 0, $6 = 0, $7 = 0, $tobool714 = 0, $8 = 0, $9 = 0, $sum_019 = 0, $i_018 = 0, $call = 0, $add = 0, $inc = 0, $arrayidx = 0, $10 = 0, $tobool = 0, $11 = 0, $sum_116 = 0, $i_115 = 0, $call9 = 0, $add10 = 0, $inc12 = 0, $arrayidx6 = 0, $12 = 0, $tobool7 = 0, $sum_1_lcssa = 0, $cutvalue = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $f + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $par = $0 + 280 | 0;
+ $1 = HEAP32[$par >> 2] | 0;
+ $cmp = ($1 | 0) == ($f | 0);
+ if ($cmp) {
+ $dir_0 = 1;
+ $v_0 = $0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $f + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $dir_0 = -1;
+ $v_0 = $2;
+ label = 4;
+ break;
+ case 4:
+ $list = $v_0 + 184 | 0;
+ $3 = HEAP32[$list >> 2] | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $tobool17 = ($4 | 0) == 0;
+ if ($tobool17) {
+ $sum_0_lcssa = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[$list >> 2] | 0;
+ $i_018 = 0;
+ $sum_019 = 0;
+ $9 = $4;
+ label = 8;
+ break;
+ case 6:
+ $list5 = $v_0 + 176 | 0;
+ $6 = HEAP32[$list5 >> 2] | 0;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $tobool714 = ($7 | 0) == 0;
+ if ($tobool714) {
+ $sum_1_lcssa = $sum_0_lcssa;
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $8 = HEAP32[$list5 >> 2] | 0;
+ $i_115 = 0;
+ $sum_116 = $sum_0_lcssa;
+ $11 = $7;
+ label = 9;
+ break;
+ case 8:
+ $call = _x_val($9, $v_0, $dir_0) | 0;
+ $add = $call + $sum_019 | 0;
+ $inc = $i_018 + 1 | 0;
+ $arrayidx = $5 + ($inc << 2) | 0;
+ $10 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($10 | 0) == 0;
+ if ($tobool) {
+ $sum_0_lcssa = $add;
+ label = 6;
+ break;
+ } else {
+ $i_018 = $inc;
+ $sum_019 = $add;
+ $9 = $10;
+ label = 8;
+ break;
+ }
+ case 9:
+ $call9 = _x_val($11, $v_0, $dir_0) | 0;
+ $add10 = $call9 + $sum_116 | 0;
+ $inc12 = $i_115 + 1 | 0;
+ $arrayidx6 = $8 + ($inc12 << 2) | 0;
+ $12 = HEAP32[$arrayidx6 >> 2] | 0;
+ $tobool7 = ($12 | 0) == 0;
+ if ($tobool7) {
+ $sum_1_lcssa = $add10;
+ label = 10;
+ break;
+ } else {
+ $i_115 = $inc12;
+ $sum_116 = $add10;
+ $11 = $12;
+ label = 9;
+ break;
+ }
+ case 10:
+ $cutvalue = $f + 176 | 0;
+ HEAP32[$cutvalue >> 2] = $sum_1_lcssa;
+ return;
+ }
+}
+function _cmppair($d, $key1, $key2, $disc) {
+ $d = $d | 0;
+ $key1 = $key1 | 0;
+ $key2 = $key2 | 0;
+ $disc = $disc | 0;
+ var $x = 0, $0 = 0, $x1 = 0, $1 = 0, $cmp = 0, $cmp4 = 0, $y = 0, $2 = 0, $y7 = 0, $3 = 0, $cmp8 = 0, $cmp13 = 0, $_ = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $key1 | 0;
+ $0 = HEAP32[$x >> 2] | 0;
+ $x1 = $key2 | 0;
+ $1 = HEAP32[$x1 >> 2] | 0;
+ $cmp = ($0 | 0) > ($1 | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp4 = ($0 | 0) < ($1 | 0);
+ if ($cmp4) {
+ $retval_0 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $key1 + 4 | 0;
+ $2 = HEAP32[$y >> 2] | 0;
+ $y7 = $key2 + 4 | 0;
+ $3 = HEAP32[$y7 >> 2] | 0;
+ $cmp8 = ($2 | 0) > ($3 | 0);
+ if ($cmp8) {
+ $retval_0 = 1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp13 = ($2 | 0) < ($3 | 0);
+ $_ = $cmp13 << 31 >> 31;
+ $retval_0 = $_;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _pointfof693($agg_result, $x, $y) {
+ $agg_result = $agg_result | 0;
+ $x = +$x;
+ $y = +$y;
+ HEAPF64[$agg_result >> 3] = $x;
+ HEAPF64[$agg_result + 8 >> 3] = $y;
+ return;
+}
+function _treesearch($v) {
+ $v = $v | 0;
+ var $list = 0, $0 = 0, $1 = 0, $tobool19 = 0, $list21 = 0, $2 = 0, $3 = 0, $tobool2316 = 0, $4 = 0, $i_020 = 0, $head = 0, $5 = 0, $mark = 0, $6 = 0, $cmp = 0, $rank = 0, $7 = 0, $tail = 0, $8 = 0, $rank6 = 0, $9 = 0, $sub = 0, $minlen = 0, $10 = 0, $conv8 = 0, $cmp10 = 0, $11 = 0, $12 = 0, $sub12 = 0, $cmp13 = 0, $13 = 0, $call = 0, $tobool16 = 0, $inc = 0, $14 = 0, $arrayidx = 0, $15 = 0, $tobool = 0, $16 = 0, $i_117 = 0, $tail25 = 0, $17 = 0, $mark27 = 0, $18 = 0, $cmp29 = 0, $head32 = 0, $19 = 0, $rank34 = 0, $20 = 0, $rank37 = 0, $21 = 0, $sub38 = 0, $minlen40 = 0, $22 = 0, $conv41 = 0, $cmp43 = 0, $23 = 0, $24 = 0, $sub46 = 0, $cmp47 = 0, $25 = 0, $call51 = 0, $tobool52 = 0, $inc57 = 0, $26 = 0, $arrayidx22 = 0, $27 = 0, $tobool23 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $v + 184 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool19 = ($1 | 0) == 0;
+ if ($tobool19) {
+ label = 3;
+ break;
+ } else {
+ $i_020 = 0;
+ $4 = $1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $list21 = $v + 176 | 0;
+ $2 = HEAP32[$list21 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool2316 = ($3 | 0) == 0;
+ if ($tobool2316) {
+ $retval_0 = 0;
+ label = 14;
+ break;
+ } else {
+ $i_117 = 0;
+ $16 = $3;
+ label = 9;
+ break;
+ }
+ case 4:
+ $head = $4 + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $mark = $5 + 163 | 0;
+ $6 = HEAP8[$mark] | 0;
+ $cmp = $6 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $rank = $5 + 236 | 0;
+ $7 = HEAP32[$rank >> 2] | 0;
+ $tail = $4 + 16 | 0;
+ $8 = HEAP32[$tail >> 2] | 0;
+ $rank6 = $8 + 236 | 0;
+ $9 = HEAP32[$rank6 >> 2] | 0;
+ $sub = $7 - $9 | 0;
+ $minlen = $4 + 186 | 0;
+ $10 = HEAP16[$minlen >> 1] | 0;
+ $conv8 = $10 & 65535;
+ $cmp10 = ($sub | 0) == ($conv8 | 0);
+ if ($cmp10) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ _add_tree_edge($4);
+ $11 = HEAP32[41338] | 0;
+ $12 = HEAP32[41584] | 0;
+ $sub12 = $12 - 1 | 0;
+ $cmp13 = ($11 | 0) == ($sub12 | 0);
+ if ($cmp13) {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $13 = HEAP32[$head >> 2] | 0;
+ $call = _treesearch($13) | 0;
+ $tobool16 = ($call | 0) == 0;
+ if ($tobool16) {
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 8:
+ $inc = $i_020 + 1 | 0;
+ $14 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $14 + ($inc << 2) | 0;
+ $15 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($15 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $i_020 = $inc;
+ $4 = $15;
+ label = 4;
+ break;
+ }
+ case 9:
+ $tail25 = $16 + 16 | 0;
+ $17 = HEAP32[$tail25 >> 2] | 0;
+ $mark27 = $17 + 163 | 0;
+ $18 = HEAP8[$mark27] | 0;
+ $cmp29 = $18 << 24 >> 24 == 0;
+ if ($cmp29) {
+ label = 10;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 10:
+ $head32 = $16 + 12 | 0;
+ $19 = HEAP32[$head32 >> 2] | 0;
+ $rank34 = $19 + 236 | 0;
+ $20 = HEAP32[$rank34 >> 2] | 0;
+ $rank37 = $17 + 236 | 0;
+ $21 = HEAP32[$rank37 >> 2] | 0;
+ $sub38 = $20 - $21 | 0;
+ $minlen40 = $16 + 186 | 0;
+ $22 = HEAP16[$minlen40 >> 1] | 0;
+ $conv41 = $22 & 65535;
+ $cmp43 = ($sub38 | 0) == ($conv41 | 0);
+ if ($cmp43) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ _add_tree_edge($16);
+ $23 = HEAP32[41338] | 0;
+ $24 = HEAP32[41584] | 0;
+ $sub46 = $24 - 1 | 0;
+ $cmp47 = ($23 | 0) == ($sub46 | 0);
+ if ($cmp47) {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $25 = HEAP32[$tail25 >> 2] | 0;
+ $call51 = _treesearch($25) | 0;
+ $tobool52 = ($call51 | 0) == 0;
+ if ($tobool52) {
+ label = 13;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 13:
+ $inc57 = $i_117 + 1 | 0;
+ $26 = HEAP32[$list21 >> 2] | 0;
+ $arrayidx22 = $26 + ($inc57 << 2) | 0;
+ $27 = HEAP32[$arrayidx22 >> 2] | 0;
+ $tobool23 = ($27 | 0) == 0;
+ if ($tobool23) {
+ $retval_0 = 0;
+ label = 14;
+ break;
+ } else {
+ $i_117 = $inc57;
+ $16 = $27;
+ label = 9;
+ break;
+ }
+ case 14:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _newPS() {
+ return _dtopen(12728, HEAP32[41978] | 0) | 0;
+}
+function _freePS($ps) {
+ $ps = $ps | 0;
+ _dtclose($ps);
+ return;
+}
+function _mkPair($p) {
+ $p = $p | 0;
+ var $call = 0, $1 = 0, $2 = 0, $3$1 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ $call = _zmalloc(16) | 0;
+ $1 = $p;
+ $2 = $call + 8 | 0;
+ $3$1 = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$2 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = $3$1;
+ STACKTOP = __stackBase__;
+ return $call | 0;
+}
+function _addPS($ps, $x, $y) {
+ $ps = $ps | 0;
+ $x = $x | 0;
+ $y = $y | 0;
+ var $pt = 0, $0 = 0, $1 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $pt = __stackBase__ | 0;
+ HEAP32[$pt >> 2] = $x;
+ HEAP32[$pt + 4 >> 2] = $y;
+ $0 = HEAP32[$ps >> 2] | 0;
+ $1 = _mkPair($pt) | 0;
+ FUNCTION_TABLE_iiii[$0 & 1023]($ps, $1, 1);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _isInPS($ps, $x, $y) {
+ $ps = $ps | 0;
+ $x = $x | 0;
+ $y = $y | 0;
+ var $p = 0, $cond = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $p = __stackBase__ | 0;
+ HEAP32[$p + 8 >> 2] = $x;
+ HEAP32[$p + 12 >> 2] = $y;
+ $cond = (FUNCTION_TABLE_iiii[HEAP32[$ps >> 2] & 1023]($ps, $p, 4) | 0) != 0 & 1;
+ STACKTOP = __stackBase__;
+ return $cond | 0;
+}
+function _freePair($d, $pp, $disc) {
+ $d = $d | 0;
+ $pp = $pp | 0;
+ $disc = $disc | 0;
+ _free($pp);
+ return;
+}
+function _translate_bb($g, $rankdir) {
+ $g = $g | 0;
+ $rankdir = $rankdir | 0;
+ var $new_bb = 0, $agg_tmp = 0, $agg_tmp5 = 0, $tmp10 = 0, $agg_tmp12 = 0, $agg_tmp19 = 0, $tmp24 = 0, $tmp34 = 0, $bb_sroa_0_0__idx = 0, $bb_sroa_0_0_copyload = 0.0, $bb_sroa_1_8__idx1 = 0, $bb_sroa_1_8_copyload = 0.0, $bb_sroa_2_16__idx3 = 0, $bb_sroa_2_16_copyload = 0.0, $bb_sroa_3_24__idx5 = 0, $bb_sroa_3_24_copyload = 0.0, $rankdir_off = 0, $0 = 0, $new_bb19 = 0, $UR4 = 0, $1 = 0, $2 = 0, $new_bb20 = 0, $UR18 = 0, $3 = 0, $4 = 0, $bb26 = 0, $5 = 0, $6 = 0, $label = 0, $7 = 0, $tobool = 0, $pos = 0, $8 = 0, $9 = 0, $n_cluster = 0, $10 = 0, $cmp3717 = 0, $clust = 0, $c_018 = 0, $11 = 0, $arrayidx = 0, $12 = 0, $inc = 0, $13 = 0, $cmp37 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $new_bb = __stackBase__ | 0;
+ $agg_tmp = __stackBase__ + 32 | 0;
+ $agg_tmp5 = __stackBase__ + 48 | 0;
+ $tmp10 = __stackBase__ + 64 | 0;
+ $agg_tmp12 = __stackBase__ + 80 | 0;
+ $agg_tmp19 = __stackBase__ + 96 | 0;
+ $tmp24 = __stackBase__ + 112 | 0;
+ $tmp34 = __stackBase__ + 128 | 0;
+ $bb_sroa_0_0__idx = $g + 56 | 0;
+ $bb_sroa_0_0_copyload = +HEAPF64[$bb_sroa_0_0__idx >> 3];
+ $bb_sroa_1_8__idx1 = $g + 64 | 0;
+ $bb_sroa_1_8_copyload = +HEAPF64[$bb_sroa_1_8__idx1 >> 3];
+ $bb_sroa_2_16__idx3 = $g + 72 | 0;
+ $bb_sroa_2_16_copyload = +HEAPF64[$bb_sroa_2_16__idx3 >> 3];
+ $bb_sroa_3_24__idx5 = $g + 80 | 0;
+ $bb_sroa_3_24_copyload = +HEAPF64[$bb_sroa_3_24__idx5 >> 3];
+ $rankdir_off = $rankdir - 1 | 0;
+ $0 = $rankdir_off >>> 0 < 2;
+ if ($0) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _pointfof693($agg_tmp, $bb_sroa_0_0_copyload, $bb_sroa_3_24_copyload);
+ $new_bb19 = $new_bb | 0;
+ _map_point692($new_bb19, $agg_tmp);
+ $UR4 = $new_bb + 16 | 0;
+ _pointfof693($agg_tmp5, $bb_sroa_2_16_copyload, $bb_sroa_1_8_copyload);
+ _map_point692($tmp10, $agg_tmp5);
+ $1 = $UR4;
+ $2 = $tmp10;
+ HEAP32[$1 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ label = 5;
+ break;
+ case 4:
+ _pointfof693($agg_tmp12, $bb_sroa_0_0_copyload, $bb_sroa_1_8_copyload);
+ $new_bb20 = $new_bb | 0;
+ _map_point692($new_bb20, $agg_tmp12);
+ $UR18 = $new_bb + 16 | 0;
+ _pointfof693($agg_tmp19, $bb_sroa_2_16_copyload, $bb_sroa_3_24_copyload);
+ _map_point692($tmp24, $agg_tmp19);
+ $3 = $UR18;
+ $4 = $tmp24;
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ label = 5;
+ break;
+ case 5:
+ $bb26 = $g + 56 | 0;
+ $5 = $bb26;
+ $6 = $new_bb;
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ HEAP32[$5 + 16 >> 2] = HEAP32[$6 + 16 >> 2] | 0;
+ HEAP32[$5 + 20 >> 2] = HEAP32[$6 + 20 >> 2] | 0;
+ HEAP32[$5 + 24 >> 2] = HEAP32[$6 + 24 >> 2] | 0;
+ HEAP32[$5 + 28 >> 2] = HEAP32[$6 + 28 >> 2] | 0;
+ $label = $g + 52 | 0;
+ $7 = HEAP32[$label >> 2] | 0;
+ $tobool = ($7 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $pos = $7 + 56 | 0;
+ _map_point692($tmp34, $pos);
+ $8 = $pos;
+ $9 = $tmp34;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ label = 7;
+ break;
+ case 7:
+ $n_cluster = $g + 212 | 0;
+ $10 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp3717 = ($10 | 0) < 1;
+ if ($cmp3717) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $clust = $g + 216 | 0;
+ $c_018 = 1;
+ label = 9;
+ break;
+ case 9:
+ $11 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $11 + ($c_018 << 2) | 0;
+ $12 = HEAP32[$arrayidx >> 2] | 0;
+ _translate_bb($12, $rankdir);
+ $inc = $c_018 + 1 | 0;
+ $13 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp37 = ($inc | 0) > ($13 | 0);
+ if ($cmp37) {
+ label = 10;
+ break;
+ } else {
+ $c_018 = $inc;
+ label = 9;
+ break;
+ }
+ case 10:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _map_point692($agg_result, $p) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ var $tmp = 0, $1 = 0, $2 = 0, $x = 0, $y = 0, $7 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $tmp = __stackBase__ | 0;
+ _ccwrotatepf($tmp, $p, (HEAP32[41540] | 0) * 90 & -1);
+ $1 = $p;
+ $2 = $tmp;
+ HEAP32[$1 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ $x = $p | 0;
+ HEAPF64[$x >> 3] = +HEAPF64[$x >> 3] - +HEAPF64[20772];
+ $y = $p + 8 | 0;
+ HEAPF64[$y >> 3] = +HEAPF64[$y >> 3] - +HEAPF64[20773];
+ $7 = $agg_result;
+ HEAP32[$7 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _gv_postprocess($g, $allowTranslation) {
+ $g = $g | 0;
+ $allowTranslation = $allowTranslation | 0;
+ var $dimen = 0, $tmp = 0, $tmp172 = 0, $tmp182 = 0, $buf = 0, $0 = 0, $rankdir = 0, $1 = 0, $and = 0, $2 = 0, $_tr = 0, $conv = 0, $tobool = 0, $label = 0, $3 = 0, $tobool6 = 0, $set = 0, $4 = 0, $tobool9 = 0, $dimen13 = 0, $5 = 0, $x = 0, $6 = 0.0, $add = 0.0, $y = 0, $7 = 0.0, $add14 = 0.0, $8 = 0, $tobool15 = 0, $label_pos = 0, $9 = 0, $and19 = 0, $tobool20 = 0, $x24 = 0, $10 = 0.0, $add25 = 0.0, $x30 = 0, $11 = 0.0, $sub = 0.0, $12 = 0.0, $y36 = 0, $13 = 0.0, $y40 = 0, $14 = 0.0, $sub41 = 0.0, $cmp = 0, $sub54 = 0.0, $div = 0.0, $sub59 = 0.0, $15 = 0.0, $add64 = 0.0, $16 = 0, $cmp73 = 0, $y80 = 0, $17 = 0.0, $add81 = 0.0, $y87 = 0, $18 = 0.0, $sub88 = 0.0, $y98 = 0, $19 = 0.0, $sub99 = 0.0, $y105 = 0, $20 = 0.0, $add106 = 0.0, $21 = 0.0, $x113 = 0, $22 = 0.0, $x117 = 0, $23 = 0.0, $sub118 = 0.0, $cmp119 = 0, $sub132 = 0.0, $div133 = 0.0, $sub138 = 0.0, $24 = 0.0, $add143 = 0.0, $tobool147 = 0, $25 = 0, $LL151 = 0, $26 = 0, $y156 = 0, $27 = 0.0, $sub157 = 0.0, $x161 = 0, $28 = 0.0, $29 = 0, $x166 = 0, $30 = 0.0, $y170 = 0, $31 = 0.0, $sub171 = 0.0, $32 = 0, $y177 = 0, $33 = 0.0, $x181 = 0, $34 = 0.0, $35 = 0, $36 = 0, $tobool186 = 0, $set190 = 0, $37 = 0, $tobool191 = 0, $38 = 0, $tobool194 = 0, $39 = 0, $tobool197 = 0, $arraydecay = 0, $40 = 0.0, $41 = 0.0, $call = 0, $42 = 0.0, $43 = 0.0, $sub201 = 0.0, $sub202 = 0.0, $call203 = 0, $call206 = 0, $44 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1088 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $dimen = __stackBase__ | 0;
+ $tmp = __stackBase__ + 16 | 0;
+ $tmp172 = __stackBase__ + 32 | 0;
+ $tmp182 = __stackBase__ + 48 | 0;
+ $buf = __stackBase__ + 64 | 0;
+ $0 = $dimen;
+ _memset($0 | 0, 0, 16);
+ _addXLabels($g);
+ $rankdir = $g + 156 | 0;
+ $1 = HEAP32[$rankdir >> 2] | 0;
+ $and = $1 & 3;
+ HEAP32[41540] = $and;
+ $2 = HEAP32[$rankdir >> 2] | 0;
+ $_tr = $2 & 255;
+ $conv = $_tr & 1;
+ HEAP8[167536] = $conv;
+ $tobool = $conv << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _place_flip_graph_label($g);
+ label = 5;
+ break;
+ case 4:
+ _place_graph_label($g);
+ label = 5;
+ break;
+ case 5:
+ $label = $g + 52 | 0;
+ $3 = HEAP32[$label >> 2] | 0;
+ $tobool6 = ($3 | 0) == 0;
+ if ($tobool6) {
+ label = 22;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $set = $3 + 81 | 0;
+ $4 = HEAP8[$set] | 0;
+ $tobool9 = $4 << 24 >> 24 == 0;
+ if ($tobool9) {
+ label = 7;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 7:
+ $dimen13 = $3 + 24 | 0;
+ $5 = $dimen13;
+ HEAP32[$0 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $x = $dimen | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $add = $6 + 16.0;
+ HEAPF64[$x >> 3] = $add;
+ $y = $dimen + 8 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $add14 = $7 + 8.0;
+ HEAPF64[$y >> 3] = $add14;
+ $8 = HEAP8[167536] | 0;
+ $tobool15 = $8 << 24 >> 24 == 0;
+ $label_pos = $g + 287 | 0;
+ $9 = HEAP8[$label_pos] | 0;
+ $and19 = $9 & 1;
+ $tobool20 = $and19 << 24 >> 24 != 0;
+ if ($tobool15) {
+ label = 13;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ if ($tobool20) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $x24 = $g + 72 | 0;
+ $10 = +HEAPF64[$x24 >> 3];
+ $add25 = $add14 + $10;
+ HEAPF64[$x24 >> 3] = $add25;
+ label = 11;
+ break;
+ case 10:
+ $x30 = $g + 56 | 0;
+ $11 = +HEAPF64[$x30 >> 3];
+ $sub = $11 - $add14;
+ HEAPF64[$x30 >> 3] = $sub;
+ label = 11;
+ break;
+ case 11:
+ $12 = +HEAPF64[$x >> 3];
+ $y36 = $g + 80 | 0;
+ $13 = +HEAPF64[$y36 >> 3];
+ $y40 = $g + 64 | 0;
+ $14 = +HEAPF64[$y40 >> 3];
+ $sub41 = $13 - $14;
+ $cmp = $12 > $sub41;
+ if ($cmp) {
+ label = 12;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 12:
+ $sub54 = $12 - $sub41;
+ $div = $sub54 * .5;
+ $sub59 = $14 - $div;
+ HEAPF64[$y40 >> 3] = $sub59;
+ $15 = +HEAPF64[$y36 >> 3];
+ $add64 = $div + $15;
+ HEAPF64[$y36 >> 3] = $add64;
+ label = 22;
+ break;
+ case 13:
+ $16 = HEAP32[41540] | 0;
+ $cmp73 = ($16 | 0) == 0;
+ if ($tobool20) {
+ label = 14;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 14:
+ if ($cmp73) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $y80 = $g + 80 | 0;
+ $17 = +HEAPF64[$y80 >> 3];
+ $add81 = $add14 + $17;
+ HEAPF64[$y80 >> 3] = $add81;
+ label = 20;
+ break;
+ case 16:
+ $y87 = $g + 64 | 0;
+ $18 = +HEAPF64[$y87 >> 3];
+ $sub88 = $18 - $add14;
+ HEAPF64[$y87 >> 3] = $sub88;
+ label = 20;
+ break;
+ case 17:
+ if ($cmp73) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $y98 = $g + 64 | 0;
+ $19 = +HEAPF64[$y98 >> 3];
+ $sub99 = $19 - $add14;
+ HEAPF64[$y98 >> 3] = $sub99;
+ label = 20;
+ break;
+ case 19:
+ $y105 = $g + 80 | 0;
+ $20 = +HEAPF64[$y105 >> 3];
+ $add106 = $add14 + $20;
+ HEAPF64[$y105 >> 3] = $add106;
+ label = 20;
+ break;
+ case 20:
+ $21 = +HEAPF64[$x >> 3];
+ $x113 = $g + 72 | 0;
+ $22 = +HEAPF64[$x113 >> 3];
+ $x117 = $g + 56 | 0;
+ $23 = +HEAPF64[$x117 >> 3];
+ $sub118 = $22 - $23;
+ $cmp119 = $21 > $sub118;
+ if ($cmp119) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $sub132 = $21 - $sub118;
+ $div133 = $sub132 * .5;
+ $sub138 = $23 - $div133;
+ HEAPF64[$x117 >> 3] = $sub138;
+ $24 = +HEAPF64[$x113 >> 3];
+ $add143 = $div133 + $24;
+ HEAPF64[$x113 >> 3] = $add143;
+ label = 22;
+ break;
+ case 22:
+ $tobool147 = ($allowTranslation | 0) == 0;
+ if ($tobool147) {
+ label = 29;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $25 = HEAP32[41540] | 0;
+ if (($25 | 0) == 0) {
+ label = 24;
+ break;
+ } else if (($25 | 0) == 1) {
+ label = 25;
+ break;
+ } else if (($25 | 0) == 2) {
+ label = 26;
+ break;
+ } else if (($25 | 0) == 3) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 24:
+ $LL151 = $g + 56 | 0;
+ $26 = $LL151;
+ HEAP32[41544] = HEAP32[$26 >> 2] | 0;
+ HEAP32[41545] = HEAP32[$26 + 4 >> 2] | 0;
+ HEAP32[41546] = HEAP32[$26 + 8 >> 2] | 0;
+ HEAP32[41547] = HEAP32[$26 + 12 >> 2] | 0;
+ label = 28;
+ break;
+ case 25:
+ $y156 = $g + 80 | 0;
+ $27 = +HEAPF64[$y156 >> 3];
+ $sub157 = -0.0 - $27;
+ $x161 = $g + 56 | 0;
+ $28 = +HEAPF64[$x161 >> 3];
+ _pointfof693($tmp, $sub157, $28);
+ $29 = $tmp;
+ HEAP32[41544] = HEAP32[$29 >> 2] | 0;
+ HEAP32[41545] = HEAP32[$29 + 4 >> 2] | 0;
+ HEAP32[41546] = HEAP32[$29 + 8 >> 2] | 0;
+ HEAP32[41547] = HEAP32[$29 + 12 >> 2] | 0;
+ label = 28;
+ break;
+ case 26:
+ $x166 = $g + 56 | 0;
+ $30 = +HEAPF64[$x166 >> 3];
+ $y170 = $g + 80 | 0;
+ $31 = +HEAPF64[$y170 >> 3];
+ $sub171 = -0.0 - $31;
+ _pointfof693($tmp172, $30, $sub171);
+ $32 = $tmp172;
+ HEAP32[41544] = HEAP32[$32 >> 2] | 0;
+ HEAP32[41545] = HEAP32[$32 + 4 >> 2] | 0;
+ HEAP32[41546] = HEAP32[$32 + 8 >> 2] | 0;
+ HEAP32[41547] = HEAP32[$32 + 12 >> 2] | 0;
+ label = 28;
+ break;
+ case 27:
+ $y177 = $g + 64 | 0;
+ $33 = +HEAPF64[$y177 >> 3];
+ $x181 = $g + 56 | 0;
+ $34 = +HEAPF64[$x181 >> 3];
+ _pointfof693($tmp182, $33, $34);
+ $35 = $tmp182;
+ HEAP32[41544] = HEAP32[$35 >> 2] | 0;
+ HEAP32[41545] = HEAP32[$35 + 4 >> 2] | 0;
+ HEAP32[41546] = HEAP32[$35 + 8 >> 2] | 0;
+ HEAP32[41547] = HEAP32[$35 + 12 >> 2] | 0;
+ label = 28;
+ break;
+ case 28:
+ _translate_drawing($g);
+ label = 29;
+ break;
+ case 29:
+ $36 = HEAP32[$label >> 2] | 0;
+ $tobool186 = ($36 | 0) == 0;
+ if ($tobool186) {
+ label = 32;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $set190 = $36 + 81 | 0;
+ $37 = HEAP8[$set190] | 0;
+ $tobool191 = $37 << 24 >> 24 == 0;
+ if ($tobool191) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ _place_root_label($g, $dimen);
+ label = 32;
+ break;
+ case 32:
+ $38 = HEAP32[41362] | 0;
+ $tobool194 = ($38 | 0) == 0;
+ if ($tobool194) {
+ label = 37;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $39 = HEAP8[167536] | 0;
+ $tobool197 = $39 << 24 >> 24 == 0;
+ $arraydecay = $buf | 0;
+ if ($tobool197) {
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $40 = +HEAPF64[20772];
+ $41 = +HEAPF64[20773];
+ $call = _sprintf($arraydecay | 0, 101192, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $40, HEAPF64[tempInt + 8 >> 3] = $41, HEAPF64[tempInt + 16 >> 3] = $40, HEAPF64[tempInt + 24 >> 3] = $41, tempInt) | 0) | 0;
+ label = 36;
+ break;
+ case 35:
+ $42 = +HEAPF64[20773];
+ $43 = +HEAPF64[20772];
+ $sub201 = -0.0 - $43;
+ $sub202 = -0.0 - $42;
+ $call203 = _sprintf($arraydecay | 0, 140248, (tempInt = STACKTOP, STACKTOP = STACKTOP + 48 | 0, HEAPF64[tempInt >> 3] = $42, HEAPF64[tempInt + 8 >> 3] = $43, HEAPF64[tempInt + 16 >> 3] = $42, HEAPF64[tempInt + 24 >> 3] = $43, HEAPF64[tempInt + 32 >> 3] = $sub201, HEAPF64[tempInt + 40 >> 3] = $sub202, tempInt) | 0) | 0;
+ label = 36;
+ break;
+ case 36:
+ $call206 = _strdup($arraydecay | 0) | 0;
+ $44 = HEAP32[41362] | 0;
+ HEAP32[$44 >> 2] = $call206;
+ label = 37;
+ break;
+ case 37:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _addXLabels($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool11 = 0, $n_0_in13 = 0, $pp_sroa_0_012 = 0.0, $xlabel = 0, $1 = 0, $tobool1 = 0, $u = 0, $p_sroa_0_0__idx = 0, $2 = 0, $p_sroa_0_0_copyload = 0.0, $p_sroa_1_8__idx6 = 0, $3 = 0, $p_sroa_1_8_copyload = 0.0, $rw = 0, $4 = 0, $5 = 0.0, $add = 0.0, $dimen = 0, $x5 = 0, $6 = 0.0, $div = 0.0, $add6 = 0.0, $add8 = 0.0, $pp_sroa_0_0__idx = 0, $7 = 0, $pp_sroa_1_8__idx5 = 0, $8 = 0, $9 = 0, $pp_sroa_0_1 = 0.0, $call9 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool11 = ($call | 0) == 0;
+ if ($tobool11) {
+ label = 6;
+ break;
+ } else {
+ $pp_sroa_0_012 = 0.0;
+ $n_0_in13 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $xlabel = $n_0_in13 + 124 | 0;
+ $1 = HEAP32[$xlabel >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ $pp_sroa_0_1 = $pp_sroa_0_012;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $u = $n_0_in13 + 24 | 0;
+ $p_sroa_0_0__idx = $n_0_in13 + 32 | 0;
+ $2 = $p_sroa_0_0__idx;
+ $p_sroa_0_0_copyload = +HEAPF64[$2 >> 3];
+ $p_sroa_1_8__idx6 = $n_0_in13 + 40 | 0;
+ $3 = $p_sroa_1_8__idx6;
+ $p_sroa_1_8_copyload = +HEAPF64[$3 >> 3];
+ $rw = $u + 88 | 0;
+ $4 = $rw;
+ $5 = +HEAPF64[$4 >> 3];
+ $add = $p_sroa_0_0_copyload + $5;
+ $dimen = $1 + 24 | 0;
+ $x5 = $dimen;
+ $6 = +HEAPF64[$x5 >> 3];
+ $div = $6 * .5;
+ $add6 = $add + $div;
+ $add8 = $pp_sroa_0_012 + $add6;
+ $pp_sroa_0_0__idx = $1 + 56 | 0;
+ $7 = $pp_sroa_0_0__idx;
+ HEAPF64[$7 >> 3] = $add8;
+ $pp_sroa_1_8__idx5 = $1 + 64 | 0;
+ $8 = $pp_sroa_1_8__idx5;
+ HEAPF64[$8 >> 3] = $p_sroa_1_8_copyload;
+ $9 = $1 + 81 | 0;
+ HEAP8[$9] = 1;
+ $pp_sroa_0_1 = $add8;
+ label = 5;
+ break;
+ case 5:
+ $call9 = _agnxtnode($0, $n_0_in13) | 0;
+ $tobool = ($call9 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $pp_sroa_0_012 = $pp_sroa_0_1;
+ $n_0_in13 = $call9;
+ label = 3;
+ break;
+ }
+ case 6:
+ return;
+ }
+}
+function _place_flip_graph_label($g) {
+ $g = $g | 0;
+ var $root = 0, $0 = 0, $cmp = 0, $label = 0, $1 = 0, $tobool = 0, $set = 0, $2 = 0, $tobool4 = 0, $label_pos = 0, $3 = 0, $and = 0, $tobool6 = 0, $d_sroa_0_0__idx2 = 0, $d_sroa_0_0_copyload3 = 0.0, $d_sroa_1_8__idx6 = 0, $x = 0, $4 = 0.0, $div = 0.0, $sub = 0.0, $d_sroa_0_0__idx = 0, $d_sroa_0_0_copyload = 0.0, $d_sroa_1_8__idx5 = 0, $x17 = 0, $5 = 0.0, $div19 = 0.0, $add = 0.0, $p_sroa_0_0 = 0.0, $d_sroa_1_0_in = 0, $d_sroa_1_0 = 0.0, $6 = 0, $conv23 = 0, $and24 = 0, $tobool25 = 0, $y = 0, $7 = 0.0, $div31 = 0.0, $add32 = 0.0, $and38 = 0, $tobool39 = 0, $y44 = 0, $8 = 0.0, $div46 = 0.0, $sub47 = 0.0, $y53 = 0, $9 = 0.0, $y57 = 0, $10 = 0.0, $add58 = 0.0, $div59 = 0.0, $p_sroa_1_0 = 0.0, $11 = 0, $p_sroa_0_0__idx = 0, $p_sroa_1_8__idx8 = 0, $12 = 0, $set67 = 0, $n_cluster = 0, $13 = 0, $cmp7027 = 0, $clust = 0, $c_028 = 0, $14 = 0, $arrayidx73 = 0, $15 = 0, $inc = 0, $16 = 0, $cmp70 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $cmp = ($0 | 0) == ($g | 0);
+ if ($cmp) {
+ label = 14;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $label = $g + 52 | 0;
+ $1 = HEAP32[$label >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $set = $1 + 81 | 0;
+ $2 = HEAP8[$set] | 0;
+ $tobool4 = $2 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 5:
+ $label_pos = $g + 287 | 0;
+ $3 = HEAP8[$label_pos] | 0;
+ $and = $3 & 1;
+ $tobool6 = $and << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $d_sroa_0_0__idx2 = $g + 104 | 0;
+ $d_sroa_0_0_copyload3 = +HEAPF64[$d_sroa_0_0__idx2 >> 3];
+ $d_sroa_1_8__idx6 = $g + 112 | 0;
+ $x = $g + 72 | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $div = $d_sroa_0_0_copyload3 * .5;
+ $sub = $4 - $div;
+ $d_sroa_1_0_in = $d_sroa_1_8__idx6;
+ $p_sroa_0_0 = $sub;
+ label = 8;
+ break;
+ case 7:
+ $d_sroa_0_0__idx = $g + 136 | 0;
+ $d_sroa_0_0_copyload = +HEAPF64[$d_sroa_0_0__idx >> 3];
+ $d_sroa_1_8__idx5 = $g + 144 | 0;
+ $x17 = $g + 56 | 0;
+ $5 = +HEAPF64[$x17 >> 3];
+ $div19 = $d_sroa_0_0_copyload * .5;
+ $add = $5 + $div19;
+ $d_sroa_1_0_in = $d_sroa_1_8__idx5;
+ $p_sroa_0_0 = $add;
+ label = 8;
+ break;
+ case 8:
+ $d_sroa_1_0 = +HEAPF64[$d_sroa_1_0_in >> 3];
+ $6 = HEAP8[$label_pos] | 0;
+ $conv23 = $6 << 24 >> 24;
+ $and24 = $conv23 & 4;
+ $tobool25 = ($and24 | 0) == 0;
+ if ($tobool25) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $y = $g + 64 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $div31 = $d_sroa_1_0 * .5;
+ $add32 = $div31 + $7;
+ $p_sroa_1_0 = $add32;
+ label = 13;
+ break;
+ case 10:
+ $and38 = $conv23 & 2;
+ $tobool39 = ($and38 | 0) == 0;
+ if ($tobool39) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $y44 = $g + 80 | 0;
+ $8 = +HEAPF64[$y44 >> 3];
+ $div46 = $d_sroa_1_0 * .5;
+ $sub47 = $8 - $div46;
+ $p_sroa_1_0 = $sub47;
+ label = 13;
+ break;
+ case 12:
+ $y53 = $g + 64 | 0;
+ $9 = +HEAPF64[$y53 >> 3];
+ $y57 = $g + 80 | 0;
+ $10 = +HEAPF64[$y57 >> 3];
+ $add58 = $9 + $10;
+ $div59 = $add58 * .5;
+ $p_sroa_1_0 = $div59;
+ label = 13;
+ break;
+ case 13:
+ $11 = HEAP32[$label >> 2] | 0;
+ $p_sroa_0_0__idx = $11 + 56 | 0;
+ HEAPF64[$p_sroa_0_0__idx >> 3] = $p_sroa_0_0;
+ $p_sroa_1_8__idx8 = $11 + 64 | 0;
+ HEAPF64[$p_sroa_1_8__idx8 >> 3] = $p_sroa_1_0;
+ $12 = HEAP32[$label >> 2] | 0;
+ $set67 = $12 + 81 | 0;
+ HEAP8[$set67] = 1;
+ label = 14;
+ break;
+ case 14:
+ $n_cluster = $g + 212 | 0;
+ $13 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp7027 = ($13 | 0) < 1;
+ if ($cmp7027) {
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $clust = $g + 216 | 0;
+ $c_028 = 1;
+ label = 16;
+ break;
+ case 16:
+ $14 = HEAP32[$clust >> 2] | 0;
+ $arrayidx73 = $14 + ($c_028 << 2) | 0;
+ $15 = HEAP32[$arrayidx73 >> 2] | 0;
+ _place_flip_graph_label($15);
+ $inc = $c_028 + 1 | 0;
+ $16 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp70 = ($inc | 0) > ($16 | 0);
+ if ($cmp70) {
+ label = 17;
+ break;
+ } else {
+ $c_028 = $inc;
+ label = 16;
+ break;
+ }
+ case 17:
+ return;
+ }
+}
+function _place_graph_label($g) {
+ $g = $g | 0;
+ var $root = 0, $0 = 0, $cmp = 0, $label = 0, $1 = 0, $tobool = 0, $set = 0, $2 = 0, $tobool4 = 0, $label_pos = 0, $3 = 0, $and = 0, $tobool6 = 0, $d_sroa_0_0__idx2 = 0, $d_sroa_1_8__idx6 = 0, $d_sroa_1_8_copyload7 = 0.0, $y = 0, $4 = 0.0, $div = 0.0, $sub = 0.0, $d_sroa_0_0__idx = 0, $d_sroa_1_8__idx4 = 0, $d_sroa_1_8_copyload = 0.0, $y17 = 0, $5 = 0.0, $div19 = 0.0, $add = 0.0, $p_sroa_1_0 = 0.0, $d_sroa_0_0_in = 0, $d_sroa_0_0 = 0.0, $6 = 0, $conv23 = 0, $and24 = 0, $tobool25 = 0, $x = 0, $7 = 0.0, $div31 = 0.0, $sub32 = 0.0, $and38 = 0, $tobool39 = 0, $x44 = 0, $8 = 0.0, $div46 = 0.0, $add47 = 0.0, $x57 = 0, $9 = 0.0, $add58 = 0.0, $div59 = 0.0, $p_sroa_0_0 = 0.0, $10 = 0, $p_sroa_0_0__idx = 0, $p_sroa_1_8__idx8 = 0, $11 = 0, $set67 = 0, $n_cluster = 0, $12 = 0, $cmp7027 = 0, $clust = 0, $c_028 = 0, $13 = 0, $arrayidx73 = 0, $14 = 0, $inc = 0, $15 = 0, $cmp70 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $cmp = ($0 | 0) == ($g | 0);
+ if ($cmp) {
+ label = 14;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $label = $g + 52 | 0;
+ $1 = HEAP32[$label >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $set = $1 + 81 | 0;
+ $2 = HEAP8[$set] | 0;
+ $tobool4 = $2 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 5:
+ $label_pos = $g + 287 | 0;
+ $3 = HEAP8[$label_pos] | 0;
+ $and = $3 & 1;
+ $tobool6 = $and << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $d_sroa_0_0__idx2 = $g + 120 | 0;
+ $d_sroa_1_8__idx6 = $g + 128 | 0;
+ $d_sroa_1_8_copyload7 = +HEAPF64[$d_sroa_1_8__idx6 >> 3];
+ $y = $g + 80 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $div = $d_sroa_1_8_copyload7 * .5;
+ $sub = $4 - $div;
+ $d_sroa_0_0_in = $d_sroa_0_0__idx2;
+ $p_sroa_1_0 = $sub;
+ label = 8;
+ break;
+ case 7:
+ $d_sroa_0_0__idx = $g + 88 | 0;
+ $d_sroa_1_8__idx4 = $g + 96 | 0;
+ $d_sroa_1_8_copyload = +HEAPF64[$d_sroa_1_8__idx4 >> 3];
+ $y17 = $g + 64 | 0;
+ $5 = +HEAPF64[$y17 >> 3];
+ $div19 = $d_sroa_1_8_copyload * .5;
+ $add = $5 + $div19;
+ $d_sroa_0_0_in = $d_sroa_0_0__idx;
+ $p_sroa_1_0 = $add;
+ label = 8;
+ break;
+ case 8:
+ $d_sroa_0_0 = +HEAPF64[$d_sroa_0_0_in >> 3];
+ $6 = HEAP8[$label_pos] | 0;
+ $conv23 = $6 << 24 >> 24;
+ $and24 = $conv23 & 4;
+ $tobool25 = ($and24 | 0) == 0;
+ if ($tobool25) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $x = $g + 72 | 0;
+ $7 = +HEAPF64[$x >> 3];
+ $div31 = $d_sroa_0_0 * .5;
+ $sub32 = $7 - $div31;
+ $p_sroa_0_0 = $sub32;
+ label = 13;
+ break;
+ case 10:
+ $and38 = $conv23 & 2;
+ $tobool39 = ($and38 | 0) == 0;
+ $x44 = $g + 56 | 0;
+ $8 = +HEAPF64[$x44 >> 3];
+ if ($tobool39) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $div46 = $d_sroa_0_0 * .5;
+ $add47 = $div46 + $8;
+ $p_sroa_0_0 = $add47;
+ label = 13;
+ break;
+ case 12:
+ $x57 = $g + 72 | 0;
+ $9 = +HEAPF64[$x57 >> 3];
+ $add58 = $8 + $9;
+ $div59 = $add58 * .5;
+ $p_sroa_0_0 = $div59;
+ label = 13;
+ break;
+ case 13:
+ $10 = HEAP32[$label >> 2] | 0;
+ $p_sroa_0_0__idx = $10 + 56 | 0;
+ HEAPF64[$p_sroa_0_0__idx >> 3] = $p_sroa_0_0;
+ $p_sroa_1_8__idx8 = $10 + 64 | 0;
+ HEAPF64[$p_sroa_1_8__idx8 >> 3] = $p_sroa_1_0;
+ $11 = HEAP32[$label >> 2] | 0;
+ $set67 = $11 + 81 | 0;
+ HEAP8[$set67] = 1;
+ label = 14;
+ break;
+ case 14:
+ $n_cluster = $g + 212 | 0;
+ $12 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp7027 = ($12 | 0) < 1;
+ if ($cmp7027) {
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $clust = $g + 216 | 0;
+ $c_028 = 1;
+ label = 16;
+ break;
+ case 16:
+ $13 = HEAP32[$clust >> 2] | 0;
+ $arrayidx73 = $13 + ($c_028 << 2) | 0;
+ $14 = HEAP32[$arrayidx73 >> 2] | 0;
+ _place_graph_label($14);
+ $inc = $c_028 + 1 | 0;
+ $15 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp70 = ($inc | 0) > ($15 | 0);
+ if ($cmp70) {
+ label = 17;
+ break;
+ } else {
+ $c_028 = $inc;
+ label = 16;
+ break;
+ }
+ case 17:
+ return;
+ }
+}
+function _add_tree_edge($e) {
+ $e = $e | 0;
+ var $tree_index = 0, $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $inc = 0, $3 = 0, $arrayidx = 0, $tail = 0, $4 = 0, $mark = 0, $5 = 0, $cmp4 = 0, $6 = 0, $inc8 = 0, $7 = 0, $arrayidx9 = 0, $head = 0, $8 = 0, $mark12 = 0, $9 = 0, $cmp14 = 0, $10 = 0, $inc18 = 0, $11 = 0, $arrayidx19 = 0, $12 = 0, $mark23 = 0, $size = 0, $13 = 0, $inc25 = 0, $list = 0, $14 = 0, $arrayidx28 = 0, $15 = 0, $16 = 0, $arrayidx35 = 0, $17 = 0, $sub = 0, $list40 = 0, $18 = 0, $arrayidx41 = 0, $19 = 0, $cmp42 = 0, $20 = 0, $mark48 = 0, $size50 = 0, $21 = 0, $inc51 = 0, $list54 = 0, $22 = 0, $arrayidx55 = 0, $23 = 0, $24 = 0, $arrayidx62 = 0, $25 = 0, $sub66 = 0, $list68 = 0, $26 = 0, $arrayidx69 = 0, $27 = 0, $cmp70 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tree_index = $e + 180 | 0;
+ $0 = HEAP32[$tree_index >> 2] | 0;
+ $cmp = ($0 | 0) > -1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _abort();
+ case 4:
+ $1 = HEAP32[41338] | 0;
+ HEAP32[$tree_index >> 2] = $1;
+ $2 = HEAP32[41338] | 0;
+ $inc = $2 + 1 | 0;
+ HEAP32[41338] = $inc;
+ $3 = HEAP32[41340] | 0;
+ $arrayidx = $3 + ($2 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $e;
+ $tail = $e + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $mark = $4 + 163 | 0;
+ $5 = HEAP8[$mark] | 0;
+ $cmp4 = $5 << 24 >> 24 == 0;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $6 = HEAP32[41334] | 0;
+ $inc8 = $6 + 1 | 0;
+ HEAP32[41334] = $inc8;
+ $7 = HEAP32[41336] | 0;
+ $arrayidx9 = $7 + ($6 << 2) | 0;
+ HEAP32[$arrayidx9 >> 2] = $4;
+ label = 6;
+ break;
+ case 6:
+ $head = $e + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $mark12 = $8 + 163 | 0;
+ $9 = HEAP8[$mark12] | 0;
+ $cmp14 = $9 << 24 >> 24 == 0;
+ if ($cmp14) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $10 = HEAP32[41334] | 0;
+ $inc18 = $10 + 1 | 0;
+ HEAP32[41334] = $inc18;
+ $11 = HEAP32[41336] | 0;
+ $arrayidx19 = $11 + ($10 << 2) | 0;
+ HEAP32[$arrayidx19 >> 2] = $8;
+ label = 8;
+ break;
+ case 8:
+ $12 = HEAP32[$tail >> 2] | 0;
+ $mark23 = $12 + 163 | 0;
+ HEAP8[$mark23] = 1;
+ $size = $12 + 276 | 0;
+ $13 = HEAP32[$size >> 2] | 0;
+ $inc25 = $13 + 1 | 0;
+ HEAP32[$size >> 2] = $inc25;
+ $list = $12 + 272 | 0;
+ $14 = HEAP32[$list >> 2] | 0;
+ $arrayidx28 = $14 + ($13 << 2) | 0;
+ HEAP32[$arrayidx28 >> 2] = $e;
+ $15 = HEAP32[$size >> 2] | 0;
+ $16 = HEAP32[$list >> 2] | 0;
+ $arrayidx35 = $16 + ($15 << 2) | 0;
+ HEAP32[$arrayidx35 >> 2] = 0;
+ $17 = HEAP32[$size >> 2] | 0;
+ $sub = $17 - 1 | 0;
+ $list40 = $12 + 184 | 0;
+ $18 = HEAP32[$list40 >> 2] | 0;
+ $arrayidx41 = $18 + ($sub << 2) | 0;
+ $19 = HEAP32[$arrayidx41 >> 2] | 0;
+ $cmp42 = ($19 | 0) == 0;
+ if ($cmp42) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ _abort();
+ case 10:
+ $20 = HEAP32[$head >> 2] | 0;
+ $mark48 = $20 + 163 | 0;
+ HEAP8[$mark48] = 1;
+ $size50 = $20 + 268 | 0;
+ $21 = HEAP32[$size50 >> 2] | 0;
+ $inc51 = $21 + 1 | 0;
+ HEAP32[$size50 >> 2] = $inc51;
+ $list54 = $20 + 264 | 0;
+ $22 = HEAP32[$list54 >> 2] | 0;
+ $arrayidx55 = $22 + ($21 << 2) | 0;
+ HEAP32[$arrayidx55 >> 2] = $e;
+ $23 = HEAP32[$size50 >> 2] | 0;
+ $24 = HEAP32[$list54 >> 2] | 0;
+ $arrayidx62 = $24 + ($23 << 2) | 0;
+ HEAP32[$arrayidx62 >> 2] = 0;
+ $25 = HEAP32[$size50 >> 2] | 0;
+ $sub66 = $25 - 1 | 0;
+ $list68 = $20 + 176 | 0;
+ $26 = HEAP32[$list68 >> 2] | 0;
+ $arrayidx69 = $26 + ($sub66 << 2) | 0;
+ $27 = HEAP32[$arrayidx69 >> 2] | 0;
+ $cmp70 = ($27 | 0) == 0;
+ if ($cmp70) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ _abort();
+ case 12:
+ return;
+ }
+}
+function _place_root_label($g, $d) {
+ $g = $g | 0;
+ $d = $d | 0;
+ var $label_pos = 0, $0 = 0, $conv = 0, $and = 0, $tobool = 0, $x = 0, $1 = 0.0, $x2 = 0, $2 = 0.0, $div = 0.0, $sub = 0.0, $and7 = 0, $tobool8 = 0, $x12 = 0, $3 = 0.0, $x13 = 0, $4 = 0.0, $div14 = 0.0, $add = 0.0, $x24 = 0, $5 = 0.0, $add25 = 0.0, $div26 = 0.0, $p_sroa_0_0 = 0.0, $6 = 0, $and32 = 0, $tobool33 = 0, $y = 0, $7 = 0.0, $y38 = 0, $8 = 0.0, $div39 = 0.0, $sub40 = 0.0, $y46 = 0, $9 = 0.0, $y47 = 0, $10 = 0.0, $div48 = 0.0, $add49 = 0.0, $p_sroa_1_0 = 0.0, $label = 0, $11 = 0, $p_sroa_0_0__idx = 0, $p_sroa_1_8__idx1 = 0, $12 = 0, $set = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $d;
+ $d = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$d >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$d + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$d + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$d + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $label_pos = $g + 287 | 0;
+ $0 = HEAP8[$label_pos] | 0;
+ $conv = $0 << 24 >> 24;
+ $and = $conv & 4;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x = $g + 72 | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $x2 = $d | 0;
+ $2 = +HEAPF64[$x2 >> 3];
+ $div = $2 * .5;
+ $sub = $1 - $div;
+ $p_sroa_0_0 = $sub;
+ label = 7;
+ break;
+ case 4:
+ $and7 = $conv & 2;
+ $tobool8 = ($and7 | 0) == 0;
+ $x12 = $g + 56 | 0;
+ $3 = +HEAPF64[$x12 >> 3];
+ if ($tobool8) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $x13 = $d | 0;
+ $4 = +HEAPF64[$x13 >> 3];
+ $div14 = $4 * .5;
+ $add = $3 + $div14;
+ $p_sroa_0_0 = $add;
+ label = 7;
+ break;
+ case 6:
+ $x24 = $g + 72 | 0;
+ $5 = +HEAPF64[$x24 >> 3];
+ $add25 = $3 + $5;
+ $div26 = $add25 * .5;
+ $p_sroa_0_0 = $div26;
+ label = 7;
+ break;
+ case 7:
+ $6 = HEAP8[$label_pos] | 0;
+ $and32 = $6 & 1;
+ $tobool33 = $and32 << 24 >> 24 == 0;
+ if ($tobool33) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $y = $g + 80 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $y38 = $d + 8 | 0;
+ $8 = +HEAPF64[$y38 >> 3];
+ $div39 = $8 * .5;
+ $sub40 = $7 - $div39;
+ $p_sroa_1_0 = $sub40;
+ label = 10;
+ break;
+ case 9:
+ $y46 = $g + 64 | 0;
+ $9 = +HEAPF64[$y46 >> 3];
+ $y47 = $d + 8 | 0;
+ $10 = +HEAPF64[$y47 >> 3];
+ $div48 = $10 * .5;
+ $add49 = $9 + $div48;
+ $p_sroa_1_0 = $add49;
+ label = 10;
+ break;
+ case 10:
+ $label = $g + 52 | 0;
+ $11 = HEAP32[$label >> 2] | 0;
+ $p_sroa_0_0__idx = $11 + 56 | 0;
+ HEAPF64[$p_sroa_0_0__idx >> 3] = $p_sroa_0_0;
+ $p_sroa_1_8__idx1 = $11 + 64 | 0;
+ HEAPF64[$p_sroa_1_8__idx1 >> 3] = $p_sroa_1_0;
+ $12 = HEAP32[$label >> 2] | 0;
+ $set = $12 + 81 | 0;
+ HEAP8[$set] = 1;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _translate_drawing($g) {
+ $g = $g | 0;
+ var $tmp = 0, $tmp18 = 0, $0 = 0.0, $tobool = 0, $1 = 0.0, $tobool1 = 0, $2 = 0, $tobool3 = 0, $or_cond = 0, $3 = 0, $call = 0, $tobool421 = 0, $4 = 0, $5 = 0, $v_023_in = 0, $6 = 0, $tobool5 = 0, $v_023 = 0, $coord = 0, $7 = 0, $8 = 0, $xlabel = 0, $9 = 0, $tobool11 = 0, $pos = 0, $10 = 0, $11 = 0, $cmp = 0, $call21 = 0, $tobool2318 = 0, $e_0_in19 = 0, $e_0 = 0, $call25 = 0, $tobool23 = 0, $call28 = 0, $tobool4 = 0, $rankdir = 0, $12 = 0, $and = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmp18 = __stackBase__ + 16 | 0;
+ $0 = +HEAPF64[20772];
+ $tobool = $0 != 0.0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = +HEAPF64[20773];
+ $tobool1 = $1 != 0.0;
+ $2 = HEAP32[41540] | 0;
+ $tobool3 = ($2 | 0) != 0;
+ $or_cond = $tobool1 | $tobool3;
+ if ($or_cond) {
+ label = 4;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 4:
+ $3 = $g;
+ $call = _agfstnode($3) | 0;
+ $tobool421 = ($call | 0) == 0;
+ if ($tobool421) {
+ label = 14;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $4 = $tmp;
+ $5 = $tmp18;
+ $v_023_in = $call;
+ label = 6;
+ break;
+ case 6:
+ $6 = HEAP32[41540] | 0;
+ $tobool5 = ($6 | 0) == 0;
+ if ($tobool5) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $v_023 = $v_023_in;
+ _gv_nodesize($v_023, 0);
+ label = 8;
+ break;
+ case 8:
+ $coord = $v_023_in + 32 | 0;
+ $7 = $coord;
+ _map_point692($tmp, $7);
+ $8 = $coord;
+ HEAP32[$8 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $xlabel = $v_023_in + 124 | 0;
+ $9 = HEAP32[$xlabel >> 2] | 0;
+ $tobool11 = ($9 | 0) == 0;
+ if ($tobool11) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $pos = $9 + 56 | 0;
+ $10 = $pos;
+ _map_point692($tmp18, $10);
+ HEAP32[$pos >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$pos + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$pos + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$pos + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ label = 10;
+ break;
+ case 10:
+ $11 = HEAP32[41356] | 0;
+ $cmp = ($11 | 0) == 1;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $call21 = _agfstout($3, $v_023_in) | 0;
+ $tobool2318 = ($call21 | 0) == 0;
+ if ($tobool2318) {
+ label = 13;
+ break;
+ } else {
+ $e_0_in19 = $call21;
+ label = 12;
+ break;
+ }
+ case 12:
+ $e_0 = $e_0_in19;
+ _map_edge($e_0);
+ $call25 = _agnxtout($3, $e_0_in19) | 0;
+ $tobool23 = ($call25 | 0) == 0;
+ if ($tobool23) {
+ label = 13;
+ break;
+ } else {
+ $e_0_in19 = $call25;
+ label = 12;
+ break;
+ }
+ case 13:
+ $call28 = _agnxtnode($3, $v_023_in) | 0;
+ $tobool4 = ($call28 | 0) == 0;
+ if ($tobool4) {
+ label = 14;
+ break;
+ } else {
+ $v_023_in = $call28;
+ label = 6;
+ break;
+ }
+ case 14:
+ $rankdir = $g + 156 | 0;
+ $12 = HEAP32[$rankdir >> 2] | 0;
+ $and = $12 & 3;
+ _translate_bb($g, $and);
+ label = 15;
+ break;
+ case 15:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _dotneato_postprocess($g) {
+ $g = $g | 0;
+ _gv_postprocess($g, 1);
+ return;
+}
+function _map_edge($e) {
+ $e = $e | 0;
+ var $tmp = 0, $tmp35 = 0, $tmp48 = 0, $tmp61 = 0, $tmp72 = 0, $tmp83 = 0, $tmp94 = 0, $spl = 0, $0 = 0, $cmp = 0, $1 = 0, $size37 = 0, $2 = 0, $cmp1238 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $cmp1 = 0, $edge_type = 0, $7 = 0, $cmp5 = 0, $tail = 0, $8 = 0, $name = 0, $9 = 0, $head = 0, $10 = 0, $name8 = 0, $11 = 0, $call = 0, $12 = 0, $j_039 = 0, $list = 0, $13 = 0, $bz_sroa_0_0__idx = 0, $bz_sroa_0_0_copyload = 0, $bz_sroa_1_4__idx2 = 0, $bz_sroa_1_4_copyload = 0, $bz_sroa_2_8__idx3 = 0, $bz_sroa_2_8_copyload = 0, $bz_sroa_3_12__idx4 = 0, $bz_sroa_3_12_copyload = 0, $cmp1835 = 0, $k_036 = 0, $arrayidx22 = 0, $14 = 0, $inc = 0, $cmp18 = 0, $tobool = 0, $15 = 0, $list28 = 0, $16 = 0, $sp = 0, $17 = 0, $tobool37 = 0, $18 = 0, $list41 = 0, $19 = 0, $ep = 0, $20 = 0, $inc51 = 0, $21 = 0, $size = 0, $22 = 0, $cmp12 = 0, $label = 0, $23 = 0, $tobool54 = 0, $pos = 0, $24 = 0, $25 = 0, $xlabel = 0, $26 = 0, $tobool64 = 0, $pos68 = 0, $27 = 0, $28 = 0, $head_label = 0, $29 = 0, $tobool75 = 0, $pos79 = 0, $30 = 0, $31 = 0, $tail_label = 0, $32 = 0, $tobool86 = 0, $pos90 = 0, $33 = 0, $34 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 112 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmp35 = __stackBase__ + 16 | 0;
+ $tmp48 = __stackBase__ + 32 | 0;
+ $tmp61 = __stackBase__ + 48 | 0;
+ $tmp72 = __stackBase__ + 64 | 0;
+ $tmp83 = __stackBase__ + 80 | 0;
+ $tmp94 = __stackBase__ + 96 | 0;
+ $spl = $e + 24 | 0;
+ $0 = HEAP32[$spl >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[$spl >> 2] | 0;
+ $size37 = $1 + 4 | 0;
+ $2 = HEAP32[$size37 >> 2] | 0;
+ $cmp1238 = ($2 | 0) > 0;
+ if ($cmp1238) {
+ label = 4;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 4:
+ $3 = $tmp48;
+ $4 = $tmp35;
+ $5 = $tmp;
+ $j_039 = 0;
+ $12 = $1;
+ label = 8;
+ break;
+ case 5:
+ $6 = HEAP8[167952] | 0;
+ $cmp1 = $6 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $edge_type = $e + 128 | 0;
+ $7 = HEAP8[$edge_type] | 0;
+ $cmp5 = $7 << 24 >> 24 == 6;
+ if ($cmp5) {
+ label = 23;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $tail = $e + 16 | 0;
+ $8 = HEAP32[$tail >> 2] | 0;
+ $name = $8 + 12 | 0;
+ $9 = HEAP32[$name >> 2] | 0;
+ $head = $e + 12 | 0;
+ $10 = HEAP32[$head >> 2] | 0;
+ $name8 = $10 + 12 | 0;
+ $11 = HEAP32[$name8 >> 2] | 0;
+ $call = _agerr(1, 120776, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $9, HEAP32[tempInt + 8 >> 2] = $11, tempInt) | 0) | 0;
+ label = 23;
+ break;
+ case 8:
+ $list = $12 | 0;
+ $13 = HEAP32[$list >> 2] | 0;
+ $bz_sroa_0_0__idx = $13 + ($j_039 * 48 & -1) | 0;
+ $bz_sroa_0_0_copyload = HEAP32[$bz_sroa_0_0__idx >> 2] | 0;
+ $bz_sroa_1_4__idx2 = $13 + ($j_039 * 48 & -1) + 4 | 0;
+ $bz_sroa_1_4_copyload = HEAP32[$bz_sroa_1_4__idx2 >> 2] | 0;
+ $bz_sroa_2_8__idx3 = $13 + ($j_039 * 48 & -1) + 8 | 0;
+ $bz_sroa_2_8_copyload = HEAP32[$bz_sroa_2_8__idx3 >> 2] | 0;
+ $bz_sroa_3_12__idx4 = $13 + ($j_039 * 48 & -1) + 12 | 0;
+ $bz_sroa_3_12_copyload = HEAP32[$bz_sroa_3_12__idx4 >> 2] | 0;
+ $cmp1835 = ($bz_sroa_1_4_copyload | 0) > 0;
+ if ($cmp1835) {
+ $k_036 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $arrayidx22 = $bz_sroa_0_0_copyload + ($k_036 << 4) | 0;
+ _map_point692($tmp, $arrayidx22);
+ $14 = $arrayidx22;
+ HEAP32[$14 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $inc = $k_036 + 1 | 0;
+ $cmp18 = ($inc | 0) < ($bz_sroa_1_4_copyload | 0);
+ if ($cmp18) {
+ $k_036 = $inc;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $tobool = ($bz_sroa_2_8_copyload | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $15 = HEAP32[$spl >> 2] | 0;
+ $list28 = $15 | 0;
+ $16 = HEAP32[$list28 >> 2] | 0;
+ $sp = $16 + ($j_039 * 48 & -1) + 16 | 0;
+ _map_point692($tmp35, $sp);
+ $17 = $sp;
+ HEAP32[$17 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$17 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$17 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$17 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ label = 12;
+ break;
+ case 12:
+ $tobool37 = ($bz_sroa_3_12_copyload | 0) == 0;
+ if ($tobool37) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $18 = HEAP32[$spl >> 2] | 0;
+ $list41 = $18 | 0;
+ $19 = HEAP32[$list41 >> 2] | 0;
+ $ep = $19 + ($j_039 * 48 & -1) + 32 | 0;
+ _map_point692($tmp48, $ep);
+ $20 = $ep;
+ HEAP32[$20 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$20 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$20 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$20 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ label = 14;
+ break;
+ case 14:
+ $inc51 = $j_039 + 1 | 0;
+ $21 = HEAP32[$spl >> 2] | 0;
+ $size = $21 + 4 | 0;
+ $22 = HEAP32[$size >> 2] | 0;
+ $cmp12 = ($inc51 | 0) < ($22 | 0);
+ if ($cmp12) {
+ $j_039 = $inc51;
+ $12 = $21;
+ label = 8;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $label = $e + 112 | 0;
+ $23 = HEAP32[$label >> 2] | 0;
+ $tobool54 = ($23 | 0) == 0;
+ if ($tobool54) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $pos = $23 + 56 | 0;
+ _map_point692($tmp61, $pos);
+ $24 = $pos;
+ $25 = $tmp61;
+ HEAP32[$24 >> 2] = HEAP32[$25 >> 2] | 0;
+ HEAP32[$24 + 4 >> 2] = HEAP32[$25 + 4 >> 2] | 0;
+ HEAP32[$24 + 8 >> 2] = HEAP32[$25 + 8 >> 2] | 0;
+ HEAP32[$24 + 12 >> 2] = HEAP32[$25 + 12 >> 2] | 0;
+ label = 17;
+ break;
+ case 17:
+ $xlabel = $e + 124 | 0;
+ $26 = HEAP32[$xlabel >> 2] | 0;
+ $tobool64 = ($26 | 0) == 0;
+ if ($tobool64) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $pos68 = $26 + 56 | 0;
+ _map_point692($tmp72, $pos68);
+ $27 = $pos68;
+ $28 = $tmp72;
+ HEAP32[$27 >> 2] = HEAP32[$28 >> 2] | 0;
+ HEAP32[$27 + 4 >> 2] = HEAP32[$28 + 4 >> 2] | 0;
+ HEAP32[$27 + 8 >> 2] = HEAP32[$28 + 8 >> 2] | 0;
+ HEAP32[$27 + 12 >> 2] = HEAP32[$28 + 12 >> 2] | 0;
+ label = 19;
+ break;
+ case 19:
+ $head_label = $e + 116 | 0;
+ $29 = HEAP32[$head_label >> 2] | 0;
+ $tobool75 = ($29 | 0) == 0;
+ if ($tobool75) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $pos79 = $29 + 56 | 0;
+ _map_point692($tmp83, $pos79);
+ $30 = $pos79;
+ $31 = $tmp83;
+ HEAP32[$30 >> 2] = HEAP32[$31 >> 2] | 0;
+ HEAP32[$30 + 4 >> 2] = HEAP32[$31 + 4 >> 2] | 0;
+ HEAP32[$30 + 8 >> 2] = HEAP32[$31 + 8 >> 2] | 0;
+ HEAP32[$30 + 12 >> 2] = HEAP32[$31 + 12 >> 2] | 0;
+ label = 21;
+ break;
+ case 21:
+ $tail_label = $e + 120 | 0;
+ $32 = HEAP32[$tail_label >> 2] | 0;
+ $tobool86 = ($32 | 0) == 0;
+ if ($tobool86) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $pos90 = $32 + 56 | 0;
+ _map_point692($tmp94, $pos90);
+ $33 = $pos90;
+ $34 = $tmp94;
+ HEAP32[$33 >> 2] = HEAP32[$34 >> 2] | 0;
+ HEAP32[$33 + 4 >> 2] = HEAP32[$34 + 4 >> 2] | 0;
+ HEAP32[$33 + 8 >> 2] = HEAP32[$34 + 8 >> 2] | 0;
+ HEAP32[$33 + 12 >> 2] = HEAP32[$34 + 12 >> 2] | 0;
+ label = 23;
+ break;
+ case 23:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _simpleSplineRoute($tp, $hp, $poly, $n_spl_pts, $polyline) {
+ $tp = $tp | 0;
+ $hp = $hp | 0;
+ $poly = $poly | 0;
+ $n_spl_pts = $n_spl_pts | 0;
+ $polyline = $polyline | 0;
+ var $pl = 0, $spl = 0, $eps = 0, $evs = 0, $x = 0, $0 = 0.0, $arrayidx = 0, $x1 = 0, $y = 0, $1 = 0.0, $y3 = 0, $x4 = 0, $2 = 0.0, $x6 = 0, $y7 = 0, $3 = 0.0, $y9 = 0, $call = 0, $cmp = 0, $tobool = 0, $pn = 0, $4 = 0, $5 = 0, $cmp11 = 0, $6 = 0, $tobool13 = 0, $7 = 0, $mul = 0, $call15 = 0, $mul17 = 0, $call18 = 0, $call15_sink = 0, $8 = 0, $9 = 0, $_pr = 0, $10 = 0, $cmp2212 = 0, $11 = 0, $ps = 0, $12 = 0, $13 = 0, $i_013 = 0, $a = 0, $arrayidx24 = 0, $14 = 0, $15 = 0, $b = 0, $add = 0, $rem = 0, $arrayidx28 = 0, $16 = 0, $17 = 0, $cmp22 = 0, $arrayidx29 = 0, $18 = 0, $19 = 0, $20 = 0, $call39 = 0, $cmp40 = 0, $pn44 = 0, $21 = 0, $22 = 0, $cmp4710 = 0, $23 = 0, $ps50 = 0, $24 = 0, $25 = 0, $i_111 = 0, $arrayidx49 = 0, $arrayidx51 = 0, $26 = 0, $27 = 0, $inc53 = 0, $cmp47 = 0, $_lcssa = 0, $28 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 80 | 0;
+ tempParam = $tp;
+ $tp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$tp >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$tp + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$tp + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$tp + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $hp;
+ $hp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$hp >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$hp + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$hp + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$hp + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $poly;
+ $poly = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$poly >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$poly + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pl = __stackBase__ | 0;
+ $spl = __stackBase__ + 8 | 0;
+ $eps = __stackBase__ + 16 | 0;
+ $evs = __stackBase__ + 48 | 0;
+ $x = $tp | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $arrayidx = $eps | 0;
+ $x1 = $eps | 0;
+ HEAPF64[$x1 >> 3] = $0;
+ $y = $tp + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $y3 = $eps + 8 | 0;
+ HEAPF64[$y3 >> 3] = $1;
+ $x4 = $hp | 0;
+ $2 = +HEAPF64[$x4 >> 3];
+ $x6 = $eps + 16 | 0;
+ HEAPF64[$x6 >> 3] = $2;
+ $y7 = $hp + 8 | 0;
+ $3 = +HEAPF64[$y7 >> 3];
+ $y9 = $eps + 24 | 0;
+ HEAPF64[$y9 >> 3] = $3;
+ $call = _Pshortestpath($poly, $arrayidx, $pl) | 0;
+ $cmp = ($call | 0) == -1;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 18;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tobool = ($polyline | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _make_polyline($pl, $spl);
+ label = 14;
+ break;
+ case 5:
+ $pn = $poly + 4 | 0;
+ $4 = HEAP32[$pn >> 2] | 0;
+ $5 = HEAP32[5082] | 0;
+ $cmp11 = ($4 | 0) > ($5 | 0);
+ if ($cmp11) {
+ label = 6;
+ break;
+ } else {
+ $10 = $4;
+ label = 10;
+ break;
+ }
+ case 6:
+ $6 = HEAP32[5080] | 0;
+ $tobool13 = ($6 | 0) == 0;
+ if ($tobool13) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $7 = $6;
+ $mul = $4 << 5;
+ $call15 = _grealloc($7, $mul) | 0;
+ $call15_sink = $call15;
+ label = 9;
+ break;
+ case 8:
+ $mul17 = $4 << 5;
+ $call18 = _gmalloc($mul17) | 0;
+ $call15_sink = $call18;
+ label = 9;
+ break;
+ case 9:
+ $8 = $call15_sink;
+ HEAP32[5080] = $8;
+ $9 = HEAP32[$pn >> 2] | 0;
+ HEAP32[5082] = $9;
+ $_pr = HEAP32[$pn >> 2] | 0;
+ $10 = $_pr;
+ label = 10;
+ break;
+ case 10:
+ $cmp2212 = ($10 | 0) > 0;
+ if ($cmp2212) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $11 = HEAP32[5080] | 0;
+ $ps = $poly | 0;
+ $12 = HEAP32[$ps >> 2] | 0;
+ $13 = HEAP32[$pn >> 2] | 0;
+ $i_013 = 0;
+ label = 12;
+ break;
+ case 12:
+ $a = $11 + ($i_013 << 5) | 0;
+ $arrayidx24 = $12 + ($i_013 << 4) | 0;
+ $14 = $a;
+ $15 = $arrayidx24;
+ HEAP32[$14 >> 2] = HEAP32[$15 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$15 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$15 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$15 + 12 >> 2] | 0;
+ $b = $11 + ($i_013 << 5) + 16 | 0;
+ $add = $i_013 + 1 | 0;
+ $rem = ($add | 0) % ($13 | 0);
+ $arrayidx28 = $12 + ($rem << 4) | 0;
+ $16 = $b;
+ $17 = $arrayidx28;
+ HEAP32[$16 >> 2] = HEAP32[$17 >> 2] | 0;
+ HEAP32[$16 + 4 >> 2] = HEAP32[$17 + 4 >> 2] | 0;
+ HEAP32[$16 + 8 >> 2] = HEAP32[$17 + 8 >> 2] | 0;
+ HEAP32[$16 + 12 >> 2] = HEAP32[$17 + 12 >> 2] | 0;
+ $cmp22 = ($add | 0) < ($13 | 0);
+ if ($cmp22) {
+ $i_013 = $add;
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $arrayidx29 = $evs | 0;
+ $18 = $evs;
+ _memset($18 | 0, 0, 32);
+ $19 = HEAP32[5080] | 0;
+ $20 = HEAP32[$pn >> 2] | 0;
+ $call39 = _Proutespline($19, $20, $pl, $arrayidx29, $spl) | 0;
+ $cmp40 = ($call39 | 0) == -1;
+ if ($cmp40) {
+ $retval_0 = 0;
+ label = 18;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $pn44 = $spl + 4 | 0;
+ $21 = HEAP32[$pn44 >> 2] | 0;
+ _mkspacep($21);
+ $22 = HEAP32[$pn44 >> 2] | 0;
+ $cmp4710 = ($22 | 0) > 0;
+ if ($cmp4710) {
+ label = 15;
+ break;
+ } else {
+ $_lcssa = $22;
+ label = 17;
+ break;
+ }
+ case 15:
+ $23 = HEAP32[1392] | 0;
+ $ps50 = $spl | 0;
+ $24 = HEAP32[$ps50 >> 2] | 0;
+ $25 = HEAP32[$pn44 >> 2] | 0;
+ $i_111 = 0;
+ label = 16;
+ break;
+ case 16:
+ $arrayidx49 = $23 + ($i_111 << 4) | 0;
+ $arrayidx51 = $24 + ($i_111 << 4) | 0;
+ $26 = $arrayidx49;
+ $27 = $arrayidx51;
+ HEAP32[$26 >> 2] = HEAP32[$27 >> 2] | 0;
+ HEAP32[$26 + 4 >> 2] = HEAP32[$27 + 4 >> 2] | 0;
+ HEAP32[$26 + 8 >> 2] = HEAP32[$27 + 8 >> 2] | 0;
+ HEAP32[$26 + 12 >> 2] = HEAP32[$27 + 12 >> 2] | 0;
+ $inc53 = $i_111 + 1 | 0;
+ $cmp47 = ($inc53 | 0) < ($25 | 0);
+ if ($cmp47) {
+ $i_111 = $inc53;
+ label = 16;
+ break;
+ } else {
+ $_lcssa = $25;
+ label = 17;
+ break;
+ }
+ case 17:
+ HEAP32[$n_spl_pts >> 2] = $_lcssa;
+ $28 = HEAP32[1392] | 0;
+ $retval_0 = $28;
+ label = 18;
+ break;
+ case 18:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _routesplinesterm() {
+ var $0 = 0, $dec = 0, $cmp = 0, $1 = 0, $2 = 0, $3 = 0, $tobool = 0, $4 = 0, $5 = 0, $6 = 0, $call = 0.0, $call2 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[1080] | 0;
+ $dec = $0 - 1 | 0;
+ HEAP32[1080] = $dec;
+ $cmp = ($dec | 0) > 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[1392] | 0;
+ $2 = $1;
+ _free($2);
+ $3 = HEAP8[164912] | 0;
+ $tobool = $3 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $4 = HEAP32[_stderr >> 2] | 0;
+ $5 = HEAP32[2382] | 0;
+ $6 = HEAP32[2384] | 0;
+ $call = +_elapsed_sec();
+ $call2 = _fprintf($4 | 0, 140048, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $5, HEAP32[tempInt + 8 >> 2] = $6, HEAPF64[tempInt + 16 >> 3] = $call, tempInt) | 0) | 0;
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _routesplines($pp, $npoints) {
+ $pp = $pp | 0;
+ $npoints = $npoints | 0;
+ return __routesplines($pp, $npoints, 0) | 0;
+}
+function _mkspacep($size) {
+ $size = $size | 0;
+ var $0 = 0, $cmp = 0, $div = 0, $1 = 0, $mul = 0, $add1 = 0, $2 = 0, $3 = 0, $mul2 = 0, $call = 0, $4 = 0, $tobool = 0, $call4 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[2810] | 0;
+ $cmp = ($0 | 0) < ($size | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $div = ($size | 0) % 300;
+ $1 = $size + 300 | 0;
+ $mul = $1 + $0 | 0;
+ $add1 = $mul - $div | 0;
+ $2 = HEAP32[1392] | 0;
+ $3 = $2;
+ $mul2 = $add1 << 4;
+ $call = _grealloc($3, $mul2) | 0;
+ $4 = $call;
+ HEAP32[1392] = $4;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call4 = _agerr(1, 120736, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _abort();
+ case 5:
+ HEAP32[2810] = $add1;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _routesplinesinit() {
+ var $0 = 0, $inc = 0, $cmp = 0, $call = 0, $1 = 0, $tobool = 0, $call2 = 0, $2 = 0, $tobool4 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[1080] | 0;
+ $inc = $0 + 1 | 0;
+ HEAP32[1080] = $inc;
+ $cmp = ($0 | 0) > 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _gmalloc(4800) | 0;
+ $1 = $call;
+ HEAP32[1392] = $1;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call2 = _agerr(1, 101024, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _abort();
+ case 5:
+ HEAP32[2810] = 300;
+ HEAP32[2382] = 0;
+ HEAP32[2384] = 0;
+ $2 = HEAP8[164912] | 0;
+ $tobool4 = $2 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _start_timer();
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _routepolylines($pp, $npoints) {
+ $pp = $pp | 0;
+ $npoints = $npoints | 0;
+ return __routesplines($pp, $npoints, 1) | 0;
+}
+function __routesplines($pp, $npoints, $polyline) {
+ $pp = $pp | 0;
+ $npoints = $npoints | 0;
+ $polyline = $polyline | 0;
+ var $poly = 0, $pl = 0, $spl = 0, $eps = 0, $evs = 0, $0 = 0, $inc = 0, $nbox = 0, $1 = 0, $2 = 0, $add = 0, $data = 0, $3 = 0, $tobool326 = 0, $4 = 0, $realedge_0327 = 0, $edge_type = 0, $5 = 0, $cmp = 0, $to_orig = 0, $6 = 0, $tobool = 0, $call = 0, $boxes4 = 0, $7 = 0, $8 = 0, $mul = 0, $9 = 0, $cmp6 = 0, $10 = 0, $tobool9 = 0, $11 = 0, $mul11 = 0, $call12 = 0, $mul14 = 0, $call15 = 0, $call12_sink = 0, $12 = 0, $cmp18 = 0, $y = 0, $13 = 0.0, $y22 = 0, $14 = 0.0, $cmp23 = 0, $cmp27323 = 0, $bi_0324 = 0, $y31 = 0, $15 = 0.0, $y34 = 0, $16 = 0.0, $mul35 = 0.0, $sub = 0.0, $inc43 = 0, $cmp27 = 0, $flip_0 = 0, $tail = 0, $17 = 0, $head = 0, $18 = 0, $cmp46 = 0, $cmp50319 = 0, $sub67 = 0, $19 = 0, $bi_1321 = 0, $pi_0320 = 0, $cmp53 = 0, $y58 = 0, $20 = 0.0, $sub59 = 0, $y62 = 0, $21 = 0.0, $cmp63 = 0, $cond65 = 0, $prev_0 = 0, $cmp68 = 0, $add71 = 0, $y74 = 0, $22 = 0.0, $y77 = 0, $23 = 0.0, $cmp78 = 0, $cond80 = 0, $next_0 = 0, $cmp82 = 0, $cmp85 = 0, $cmp87 = 0, $or_cond = 0, $x = 0, $24 = 0.0, $x93 = 0, $y96 = 0, $25 = 0.0, $inc97 = 0, $y99 = 0, $26 = 0.0, $x104 = 0, $y107 = 0, $27 = 0.0, $inc108 = 0, $y110 = 0, $x114 = 0, $28 = 0.0, $x116 = 0, $y119 = 0, $29 = 0.0, $inc120 = 0, $y122 = 0, $30 = 0.0, $x127 = 0, $y130 = 0, $31 = 0.0, $inc131 = 0, $y133 = 0, $x141 = 0, $32 = 0.0, $x143 = 0, $y146 = 0, $33 = 0.0, $inc147 = 0, $y149 = 0, $34 = 0.0, $x154 = 0, $y157 = 0, $35 = 0.0, $inc158 = 0, $y160 = 0, $cmp165 = 0, $pi_1 = 0, $inc172 = 0, $cmp50 = 0, $sub174 = 0, $cmp176315 = 0, $36 = 0, $bi_2317 = 0, $pi_2316 = 0, $cmp180 = 0, $y185 = 0, $37 = 0.0, $add186 = 0, $y189 = 0, $38 = 0.0, $cmp190 = 0, $cond192 = 0, $prev_1 = 0, $cmp194 = 0, $sub197 = 0, $y200 = 0, $39 = 0.0, $y203 = 0, $40 = 0.0, $cmp204 = 0, $cond206 = 0, $next_1 = 0, $cmp208 = 0, $cmp211 = 0, $cmp214 = 0, $or_cond292 = 0, $x219 = 0, $41 = 0.0, $x221 = 0, $y224 = 0, $42 = 0.0, $inc225 = 0, $y227 = 0, $43 = 0.0, $x232 = 0, $y235 = 0, $44 = 0.0, $inc236 = 0, $y238 = 0, $x242 = 0, $45 = 0.0, $x244 = 0, $y247 = 0, $46 = 0.0, $inc248 = 0, $y250 = 0, $47 = 0.0, $x255 = 0, $y258 = 0, $48 = 0.0, $inc259 = 0, $y261 = 0, $x269 = 0, $49 = 0.0, $x271 = 0, $y274 = 0, $50 = 0.0, $inc275 = 0, $y277 = 0, $51 = 0.0, $x282 = 0, $y285 = 0, $52 = 0.0, $inc286 = 0, $y288 = 0, $cmp293 = 0, $x299 = 0, $53 = 0.0, $x301 = 0, $y304 = 0, $54 = 0.0, $inc305 = 0, $y307 = 0, $55 = 0.0, $x312 = 0, $y315 = 0, $56 = 0.0, $inc316 = 0, $y318 = 0, $x321 = 0, $57 = 0.0, $x323 = 0, $58 = 0.0, $inc327 = 0, $y329 = 0, $59 = 0.0, $x334 = 0, $60 = 0.0, $inc338 = 0, $y340 = 0, $pi_3 = 0, $dec = 0, $cmp176 = 0, $pi_2_lcssa = 0, $tobool347 = 0, $cmp350311 = 0, $cmp374309 = 0, $61 = 0, $bi_3312 = 0, $y356 = 0, $62 = 0.0, $conv357 = 0, $y360 = 0, $63 = 0.0, $mul361 = 0.0, $sub365 = 0, $conv366 = 0.0, $inc371 = 0, $cmp350 = 0, $cmp385307 = 0, $i_0310 = 0, $y378 = 0, $64 = 0.0, $mul379 = 0.0, $inc381 = 0, $cmp374 = 0, $bi_4308 = 0, $x390 = 0, $x393 = 0, $inc395 = 0, $cmp385 = 0, $65 = 0, $ps = 0, $pn = 0, $x397 = 0, $66 = 0.0, $arrayidx398 = 0, $x399 = 0, $y402 = 0, $67 = 0.0, $y404 = 0, $x406 = 0, $68 = 0.0, $x408 = 0, $y411 = 0, $69 = 0.0, $y413 = 0, $call414 = 0, $cmp415 = 0, $tobool419 = 0, $70 = 0, $71 = 0, $cmp423 = 0, $72 = 0, $tobool426 = 0, $73 = 0, $mul429 = 0, $call430 = 0, $mul433 = 0, $call434 = 0, $call430_sink = 0, $74 = 0, $75 = 0, $_pr = 0, $76 = 0, $cmp441305 = 0, $77 = 0, $78 = 0, $79 = 0, $edgei_0306 = 0, $a = 0, $arrayidx445 = 0, $80 = 0, $81 = 0, $b = 0, $add447 = 0, $rem = 0, $arrayidx449 = 0, $82 = 0, $83 = 0, $cmp441 = 0, $constrained = 0, $84 = 0, $tobool454 = 0, $theta = 0, $85 = 0.0, $call457 = 0.0, $x459 = 0, $86 = 0.0, $call462 = 0.0, $y464 = 0, $87 = 0, $constrained472 = 0, $88 = 0, $tobool473 = 0, $theta476 = 0, $89 = 0.0, $call477 = 0.0, $sub478 = 0.0, $x480 = 0, $90 = 0.0, $call483 = 0.0, $sub484 = 0.0, $y486 = 0, $x491 = 0, $91 = 0, $92 = 0, $93 = 0, $arraydecay494 = 0, $call495 = 0, $cmp496 = 0, $pn501 = 0, $94 = 0, $cmp503303 = 0, $95 = 0, $cmp517301 = 0, $96 = 0, $ps521 = 0, $97 = 0, $98 = 0, $bi_5304 = 0, $x508 = 0, $x511 = 0, $inc513 = 0, $cmp503 = 0, $_pr331 = 0, $99 = 0, $cmp529298 = 0, $100 = 0, $cmp683293 = 0, $splinepi_0302 = 0, $arrayidx520 = 0, $arrayidx522 = 0, $101 = 0, $102 = 0, $inc524 = 0, $cmp517 = 0, $delta_0 = 0, $mul532 = 0, $cmp534296 = 0, $conv538 = 0.0, $add527 = 0, $cmp529 = 0, $add527300 = 0, $splinepi_1299 = 0, $sp_sroa_0_0__idx = 0, $sp_sroa_1_8__idx229 = 0, $add542 = 0, $sp_sroa_2_16__idx = 0, $sp_sroa_3_24__idx242 = 0, $add545 = 0, $sp_sroa_4_32__idx = 0, $sp_sroa_5_40__idx249 = 0, $sp_sroa_6_48__idx = 0, $sp_sroa_7_56__idx250 = 0, $si_0297 = 0, $conv537 = 0.0, $div = 0.0, $sp_sroa_0_0_copyload = 0.0, $sp_sroa_1_8_copyload = 0.0, $sp_sroa_2_16_copyload = 0.0, $sp_sroa_3_24_copyload = 0.0, $sp_sroa_4_32_copyload = 0.0, $sp_sroa_5_40_copyload = 0.0, $sp_sroa_6_48_copyload = 0.0, $sp_sroa_7_56_copyload = 0.0, $sub556 = 0.0, $mul557 = 0.0, $add558 = 0.0, $sub567 = 0.0, $mul568 = 0.0, $add569 = 0.0, $sub578 = 0.0, $mul579 = 0.0, $add580 = 0.0, $sub589 = 0.0, $mul590 = 0.0, $add591 = 0.0, $sub600 = 0.0, $mul601 = 0.0, $add602 = 0.0, $sub611 = 0.0, $mul612 = 0.0, $add613 = 0.0, $sub622 = 0.0, $mul623 = 0.0, $add624 = 0.0, $sub633 = 0.0, $mul634 = 0.0, $add635 = 0.0, $sub644 = 0.0, $mul645 = 0.0, $add646 = 0.0, $sub655 = 0.0, $mul656 = 0.0, $add657 = 0.0, $sub666 = 0.0, $mul667 = 0.0, $add668 = 0.0, $sub677 = 0.0, $mul678 = 0.0, $add679 = 0.0, $bi_6294 = 0, $y690 = 0, $103 = 0.0, $add691 = 0.0, $cmp692 = 0, $y699 = 0, $104 = 0.0, $sub700 = 0.0, $cmp701 = 0, $x706 = 0, $105 = 0.0, $cmp709 = 0, $x720 = 0, $106 = 0.0, $cmp723 = 0, $inc734 = 0, $cmp683 = 0, $inc737 = 0, $cmp534 = 0, $bi_7 = 0, $cmp743 = 0, $x748 = 0, $107 = 0.0, $cmp749 = 0, $x754 = 0, $108 = 0.0, $cmp755 = 0, $inc761 = 0, $mul758 = 0, $109 = 0, $110 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 88 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $poly = __stackBase__ | 0;
+ $pl = __stackBase__ + 8 | 0;
+ $spl = __stackBase__ + 16 | 0;
+ $eps = __stackBase__ + 24 | 0;
+ $evs = __stackBase__ + 56 | 0;
+ $0 = HEAP32[2382] | 0;
+ $inc = $0 + 1 | 0;
+ HEAP32[2382] = $inc;
+ $nbox = $pp + 80 | 0;
+ $1 = HEAP32[$nbox >> 2] | 0;
+ $2 = HEAP32[2384] | 0;
+ $add = $2 + $1 | 0;
+ HEAP32[2384] = $add;
+ $data = $pp + 88 | 0;
+ $3 = HEAP32[$data >> 2] | 0;
+ $tobool326 = ($3 | 0) == 0;
+ if ($tobool326) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $4 = $3;
+ $realedge_0327 = $4;
+ label = 4;
+ break;
+ case 4:
+ $edge_type = $realedge_0327 + 128 | 0;
+ $5 = HEAP8[$edge_type] | 0;
+ $cmp = $5 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $to_orig = $realedge_0327 + 132 | 0;
+ $6 = HEAP32[$to_orig >> 2] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $realedge_0327 = $6;
+ label = 4;
+ break;
+ }
+ case 6:
+ $call = _agerr(1, 115128, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _abort();
+ return 0;
+ return 0;
+ case 7:
+ $boxes4 = $pp + 84 | 0;
+ $7 = HEAP32[$boxes4 >> 2] | 0;
+ $8 = HEAP32[$nbox >> 2] | 0;
+ _checkpath($8, $7, $pp);
+ $mul = $8 << 3;
+ $9 = HEAP32[1730] | 0;
+ $cmp6 = ($mul | 0) > ($9 | 0);
+ if ($cmp6) {
+ label = 8;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 8:
+ $10 = HEAP32[1728] | 0;
+ $tobool9 = ($10 | 0) == 0;
+ if ($tobool9) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $11 = $10;
+ $mul11 = $8 << 7;
+ $call12 = _grealloc($11, $mul11) | 0;
+ $call12_sink = $call12;
+ label = 11;
+ break;
+ case 10:
+ $mul14 = $8 << 7;
+ $call15 = _gmalloc($mul14) | 0;
+ $call12_sink = $call15;
+ label = 11;
+ break;
+ case 11:
+ $12 = $call12_sink;
+ HEAP32[1728] = $12;
+ HEAP32[1730] = $mul;
+ label = 12;
+ break;
+ case 12:
+ $cmp18 = ($8 | 0) > 1;
+ if ($cmp18) {
+ label = 13;
+ break;
+ } else {
+ $flip_0 = 0;
+ label = 16;
+ break;
+ }
+ case 13:
+ $y = $7 + 8 | 0;
+ $13 = +HEAPF64[$y >> 3];
+ $y22 = $7 + 40 | 0;
+ $14 = +HEAPF64[$y22 >> 3];
+ $cmp23 = $13 > $14;
+ if ($cmp23) {
+ label = 14;
+ break;
+ } else {
+ $flip_0 = 0;
+ label = 16;
+ break;
+ }
+ case 14:
+ $cmp27323 = ($8 | 0) > 0;
+ if ($cmp27323) {
+ $bi_0324 = 0;
+ label = 15;
+ break;
+ } else {
+ $flip_0 = 1;
+ label = 16;
+ break;
+ }
+ case 15:
+ $y31 = $7 + ($bi_0324 << 5) + 24 | 0;
+ $15 = +HEAPF64[$y31 >> 3];
+ $y34 = $7 + ($bi_0324 << 5) + 8 | 0;
+ $16 = +HEAPF64[$y34 >> 3];
+ $mul35 = $16 * -1.0;
+ HEAPF64[$y31 >> 3] = $mul35;
+ $sub = -0.0 - $15;
+ HEAPF64[$y34 >> 3] = $sub;
+ $inc43 = $bi_0324 + 1 | 0;
+ $cmp27 = ($inc43 | 0) < ($8 | 0);
+ if ($cmp27) {
+ $bi_0324 = $inc43;
+ label = 15;
+ break;
+ } else {
+ $flip_0 = 1;
+ label = 16;
+ break;
+ }
+ case 16:
+ $tail = $realedge_0327 + 16 | 0;
+ $17 = HEAP32[$tail >> 2] | 0;
+ $head = $realedge_0327 + 12 | 0;
+ $18 = HEAP32[$head >> 2] | 0;
+ $cmp46 = ($17 | 0) == ($18 | 0);
+ if ($cmp46) {
+ label = 48;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $cmp50319 = ($8 | 0) > 0;
+ if ($cmp50319) {
+ label = 18;
+ break;
+ } else {
+ $pi_2_lcssa = 0;
+ label = 49;
+ break;
+ }
+ case 18:
+ $sub67 = $8 - 1 | 0;
+ $19 = HEAP32[1728] | 0;
+ $pi_0320 = 0;
+ $bi_1321 = 0;
+ label = 19;
+ break;
+ case 19:
+ $cmp53 = ($bi_1321 | 0) > 0;
+ if ($cmp53) {
+ label = 20;
+ break;
+ } else {
+ $prev_0 = 0;
+ label = 21;
+ break;
+ }
+ case 20:
+ $y58 = $7 + ($bi_1321 << 5) + 8 | 0;
+ $20 = +HEAPF64[$y58 >> 3];
+ $sub59 = $bi_1321 - 1 | 0;
+ $y62 = $7 + ($sub59 << 5) + 8 | 0;
+ $21 = +HEAPF64[$y62 >> 3];
+ $cmp63 = $20 > $21;
+ $cond65 = $cmp63 ? -1 : 1;
+ $prev_0 = $cond65;
+ label = 21;
+ break;
+ case 21:
+ $cmp68 = ($bi_1321 | 0) < ($sub67 | 0);
+ if ($cmp68) {
+ label = 22;
+ break;
+ } else {
+ $next_0 = 0;
+ label = 23;
+ break;
+ }
+ case 22:
+ $add71 = $bi_1321 + 1 | 0;
+ $y74 = $7 + ($add71 << 5) + 8 | 0;
+ $22 = +HEAPF64[$y74 >> 3];
+ $y77 = $7 + ($bi_1321 << 5) + 8 | 0;
+ $23 = +HEAPF64[$y77 >> 3];
+ $cmp78 = $22 > $23;
+ $cond80 = $cmp78 ? 1 : -1;
+ $next_0 = $cond80;
+ label = 23;
+ break;
+ case 23:
+ $cmp82 = ($prev_0 | 0) == ($next_0 | 0);
+ if ($cmp82) {
+ label = 27;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $cmp85 = ($next_0 | 0) == -1;
+ $cmp87 = ($prev_0 | 0) == 1;
+ $or_cond = $cmp85 | $cmp87;
+ if ($or_cond) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $x = $7 + ($bi_1321 << 5) | 0;
+ $24 = +HEAPF64[$x >> 3];
+ $x93 = $19 + ($pi_0320 << 4) | 0;
+ HEAPF64[$x93 >> 3] = $24;
+ $y96 = $7 + ($bi_1321 << 5) + 24 | 0;
+ $25 = +HEAPF64[$y96 >> 3];
+ $inc97 = $pi_0320 + 1 | 0;
+ $y99 = $19 + ($pi_0320 << 4) + 8 | 0;
+ HEAPF64[$y99 >> 3] = $25;
+ $26 = +HEAPF64[$x >> 3];
+ $x104 = $19 + ($inc97 << 4) | 0;
+ HEAPF64[$x104 >> 3] = $26;
+ $y107 = $7 + ($bi_1321 << 5) + 8 | 0;
+ $27 = +HEAPF64[$y107 >> 3];
+ $inc108 = $pi_0320 + 2 | 0;
+ $y110 = $19 + ($inc97 << 4) + 8 | 0;
+ HEAPF64[$y110 >> 3] = $27;
+ $pi_1 = $inc108;
+ label = 31;
+ break;
+ case 26:
+ $x114 = $7 + ($bi_1321 << 5) + 16 | 0;
+ $28 = +HEAPF64[$x114 >> 3];
+ $x116 = $19 + ($pi_0320 << 4) | 0;
+ HEAPF64[$x116 >> 3] = $28;
+ $y119 = $7 + ($bi_1321 << 5) + 8 | 0;
+ $29 = +HEAPF64[$y119 >> 3];
+ $inc120 = $pi_0320 + 1 | 0;
+ $y122 = $19 + ($pi_0320 << 4) + 8 | 0;
+ HEAPF64[$y122 >> 3] = $29;
+ $30 = +HEAPF64[$x114 >> 3];
+ $x127 = $19 + ($inc120 << 4) | 0;
+ HEAPF64[$x127 >> 3] = $30;
+ $y130 = $7 + ($bi_1321 << 5) + 24 | 0;
+ $31 = +HEAPF64[$y130 >> 3];
+ $inc131 = $pi_0320 + 2 | 0;
+ $y133 = $19 + ($inc120 << 4) + 8 | 0;
+ HEAPF64[$y133 >> 3] = $31;
+ $pi_1 = $inc131;
+ label = 31;
+ break;
+ case 27:
+ if (($prev_0 | 0) == 0) {
+ label = 28;
+ break;
+ } else if (($prev_0 | 0) == (-1 | 0)) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 28:
+ $x141 = $7 + ($bi_1321 << 5) | 0;
+ $32 = +HEAPF64[$x141 >> 3];
+ $x143 = $19 + ($pi_0320 << 4) | 0;
+ HEAPF64[$x143 >> 3] = $32;
+ $y146 = $7 + ($bi_1321 << 5) + 24 | 0;
+ $33 = +HEAPF64[$y146 >> 3];
+ $inc147 = $pi_0320 + 1 | 0;
+ $y149 = $19 + ($pi_0320 << 4) + 8 | 0;
+ HEAPF64[$y149 >> 3] = $33;
+ $34 = +HEAPF64[$x141 >> 3];
+ $x154 = $19 + ($inc147 << 4) | 0;
+ HEAPF64[$x154 >> 3] = $34;
+ $y157 = $7 + ($bi_1321 << 5) + 8 | 0;
+ $35 = +HEAPF64[$y157 >> 3];
+ $inc158 = $pi_0320 + 2 | 0;
+ $y160 = $19 + ($inc147 << 4) + 8 | 0;
+ HEAPF64[$y160 >> 3] = $35;
+ $pi_1 = $inc158;
+ label = 31;
+ break;
+ case 29:
+ $cmp165 = ($next_0 | 0) == -1;
+ if ($cmp165) {
+ $pi_1 = $pi_0320;
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ _abort();
+ return 0;
+ return 0;
+ case 31:
+ $inc172 = $bi_1321 + 1 | 0;
+ $cmp50 = ($inc172 | 0) < ($8 | 0);
+ if ($cmp50) {
+ $pi_0320 = $pi_1;
+ $bi_1321 = $inc172;
+ label = 19;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $sub174 = $8 - 1 | 0;
+ $cmp176315 = ($8 | 0) > 0;
+ if ($cmp176315) {
+ label = 33;
+ break;
+ } else {
+ $pi_2_lcssa = $pi_1;
+ label = 49;
+ break;
+ }
+ case 33:
+ $36 = HEAP32[1728] | 0;
+ $pi_2316 = $pi_1;
+ $bi_2317 = $sub174;
+ label = 34;
+ break;
+ case 34:
+ $cmp180 = ($bi_2317 | 0) < ($sub174 | 0);
+ if ($cmp180) {
+ label = 35;
+ break;
+ } else {
+ $prev_1 = 0;
+ label = 36;
+ break;
+ }
+ case 35:
+ $y185 = $7 + ($bi_2317 << 5) + 8 | 0;
+ $37 = +HEAPF64[$y185 >> 3];
+ $add186 = $bi_2317 + 1 | 0;
+ $y189 = $7 + ($add186 << 5) + 8 | 0;
+ $38 = +HEAPF64[$y189 >> 3];
+ $cmp190 = $37 > $38;
+ $cond192 = $cmp190 ? -1 : 1;
+ $prev_1 = $cond192;
+ label = 36;
+ break;
+ case 36:
+ $cmp194 = ($bi_2317 | 0) > 0;
+ if ($cmp194) {
+ label = 37;
+ break;
+ } else {
+ $next_1 = 0;
+ label = 38;
+ break;
+ }
+ case 37:
+ $sub197 = $bi_2317 - 1 | 0;
+ $y200 = $7 + ($sub197 << 5) + 8 | 0;
+ $39 = +HEAPF64[$y200 >> 3];
+ $y203 = $7 + ($bi_2317 << 5) + 8 | 0;
+ $40 = +HEAPF64[$y203 >> 3];
+ $cmp204 = $39 > $40;
+ $cond206 = $cmp204 ? 1 : -1;
+ $next_1 = $cond206;
+ label = 38;
+ break;
+ case 38:
+ $cmp208 = ($prev_1 | 0) == ($next_1 | 0);
+ if ($cmp208) {
+ label = 42;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $cmp211 = ($next_1 | 0) == -1;
+ $cmp214 = ($prev_1 | 0) == 1;
+ $or_cond292 = $cmp211 | $cmp214;
+ if ($or_cond292) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 40:
+ $x219 = $7 + ($bi_2317 << 5) | 0;
+ $41 = +HEAPF64[$x219 >> 3];
+ $x221 = $36 + ($pi_2316 << 4) | 0;
+ HEAPF64[$x221 >> 3] = $41;
+ $y224 = $7 + ($bi_2317 << 5) + 24 | 0;
+ $42 = +HEAPF64[$y224 >> 3];
+ $inc225 = $pi_2316 + 1 | 0;
+ $y227 = $36 + ($pi_2316 << 4) + 8 | 0;
+ HEAPF64[$y227 >> 3] = $42;
+ $43 = +HEAPF64[$x219 >> 3];
+ $x232 = $36 + ($inc225 << 4) | 0;
+ HEAPF64[$x232 >> 3] = $43;
+ $y235 = $7 + ($bi_2317 << 5) + 8 | 0;
+ $44 = +HEAPF64[$y235 >> 3];
+ $inc236 = $pi_2316 + 2 | 0;
+ $y238 = $36 + ($inc225 << 4) + 8 | 0;
+ HEAPF64[$y238 >> 3] = $44;
+ $pi_3 = $inc236;
+ label = 47;
+ break;
+ case 41:
+ $x242 = $7 + ($bi_2317 << 5) + 16 | 0;
+ $45 = +HEAPF64[$x242 >> 3];
+ $x244 = $36 + ($pi_2316 << 4) | 0;
+ HEAPF64[$x244 >> 3] = $45;
+ $y247 = $7 + ($bi_2317 << 5) + 8 | 0;
+ $46 = +HEAPF64[$y247 >> 3];
+ $inc248 = $pi_2316 + 1 | 0;
+ $y250 = $36 + ($pi_2316 << 4) + 8 | 0;
+ HEAPF64[$y250 >> 3] = $46;
+ $47 = +HEAPF64[$x242 >> 3];
+ $x255 = $36 + ($inc248 << 4) | 0;
+ HEAPF64[$x255 >> 3] = $47;
+ $y258 = $7 + ($bi_2317 << 5) + 24 | 0;
+ $48 = +HEAPF64[$y258 >> 3];
+ $inc259 = $pi_2316 + 2 | 0;
+ $y261 = $36 + ($inc248 << 4) + 8 | 0;
+ HEAPF64[$y261 >> 3] = $48;
+ $pi_3 = $inc259;
+ label = 47;
+ break;
+ case 42:
+ if (($prev_1 | 0) == 0) {
+ label = 43;
+ break;
+ } else if (($prev_1 | 0) == (-1 | 0)) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 43:
+ $x269 = $7 + ($bi_2317 << 5) + 16 | 0;
+ $49 = +HEAPF64[$x269 >> 3];
+ $x271 = $36 + ($pi_2316 << 4) | 0;
+ HEAPF64[$x271 >> 3] = $49;
+ $y274 = $7 + ($bi_2317 << 5) + 8 | 0;
+ $50 = +HEAPF64[$y274 >> 3];
+ $inc275 = $pi_2316 + 1 | 0;
+ $y277 = $36 + ($pi_2316 << 4) + 8 | 0;
+ HEAPF64[$y277 >> 3] = $50;
+ $51 = +HEAPF64[$x269 >> 3];
+ $x282 = $36 + ($inc275 << 4) | 0;
+ HEAPF64[$x282 >> 3] = $51;
+ $y285 = $7 + ($bi_2317 << 5) + 24 | 0;
+ $52 = +HEAPF64[$y285 >> 3];
+ $inc286 = $pi_2316 + 2 | 0;
+ $y288 = $36 + ($inc275 << 4) + 8 | 0;
+ HEAPF64[$y288 >> 3] = $52;
+ $pi_3 = $inc286;
+ label = 47;
+ break;
+ case 44:
+ $cmp293 = ($next_1 | 0) == -1;
+ if ($cmp293) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ HEAP32[$npoints >> 2] = 0;
+ _abort();
+ return 0;
+ return 0;
+ case 46:
+ $x299 = $7 + ($bi_2317 << 5) + 16 | 0;
+ $53 = +HEAPF64[$x299 >> 3];
+ $x301 = $36 + ($pi_2316 << 4) | 0;
+ HEAPF64[$x301 >> 3] = $53;
+ $y304 = $7 + ($bi_2317 << 5) + 8 | 0;
+ $54 = +HEAPF64[$y304 >> 3];
+ $inc305 = $pi_2316 + 1 | 0;
+ $y307 = $36 + ($pi_2316 << 4) + 8 | 0;
+ HEAPF64[$y307 >> 3] = $54;
+ $55 = +HEAPF64[$x299 >> 3];
+ $x312 = $36 + ($inc305 << 4) | 0;
+ HEAPF64[$x312 >> 3] = $55;
+ $y315 = $7 + ($bi_2317 << 5) + 24 | 0;
+ $56 = +HEAPF64[$y315 >> 3];
+ $inc316 = $pi_2316 + 2 | 0;
+ $y318 = $36 + ($inc305 << 4) + 8 | 0;
+ HEAPF64[$y318 >> 3] = $56;
+ $x321 = $7 + ($bi_2317 << 5) | 0;
+ $57 = +HEAPF64[$x321 >> 3];
+ $x323 = $36 + ($inc316 << 4) | 0;
+ HEAPF64[$x323 >> 3] = $57;
+ $58 = +HEAPF64[$y315 >> 3];
+ $inc327 = $pi_2316 + 3 | 0;
+ $y329 = $36 + ($inc316 << 4) + 8 | 0;
+ HEAPF64[$y329 >> 3] = $58;
+ $59 = +HEAPF64[$x321 >> 3];
+ $x334 = $36 + ($inc327 << 4) | 0;
+ HEAPF64[$x334 >> 3] = $59;
+ $60 = +HEAPF64[$y304 >> 3];
+ $inc338 = $pi_2316 + 4 | 0;
+ $y340 = $36 + ($inc327 << 4) + 8 | 0;
+ HEAPF64[$y340 >> 3] = $60;
+ $pi_3 = $inc338;
+ label = 47;
+ break;
+ case 47:
+ $dec = $bi_2317 - 1 | 0;
+ $cmp176 = ($bi_2317 | 0) > 0;
+ if ($cmp176) {
+ $pi_2316 = $pi_3;
+ $bi_2317 = $dec;
+ label = 34;
+ break;
+ } else {
+ $pi_2_lcssa = $pi_3;
+ label = 49;
+ break;
+ }
+ case 48:
+ _abort();
+ return 0;
+ return 0;
+ case 49:
+ $tobool347 = ($flip_0 | 0) == 0;
+ if ($tobool347) {
+ label = 54;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $cmp350311 = ($8 | 0) > 0;
+ if ($cmp350311) {
+ $bi_3312 = 0;
+ label = 53;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $cmp374309 = ($pi_2_lcssa | 0) > 0;
+ if ($cmp374309) {
+ label = 52;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 52:
+ $61 = HEAP32[1728] | 0;
+ $i_0310 = 0;
+ label = 55;
+ break;
+ case 53:
+ $y356 = $7 + ($bi_3312 << 5) + 24 | 0;
+ $62 = +HEAPF64[$y356 >> 3];
+ $conv357 = ~~$62;
+ $y360 = $7 + ($bi_3312 << 5) + 8 | 0;
+ $63 = +HEAPF64[$y360 >> 3];
+ $mul361 = $63 * -1.0;
+ HEAPF64[$y356 >> 3] = $mul361;
+ $sub365 = -$conv357 | 0;
+ $conv366 = +($sub365 | 0);
+ HEAPF64[$y360 >> 3] = $conv366;
+ $inc371 = $bi_3312 + 1 | 0;
+ $cmp350 = ($inc371 | 0) < ($8 | 0);
+ if ($cmp350) {
+ $bi_3312 = $inc371;
+ label = 53;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 54:
+ $cmp385307 = ($8 | 0) > 0;
+ if ($cmp385307) {
+ $bi_4308 = 0;
+ label = 56;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 55:
+ $y378 = $61 + ($i_0310 << 4) + 8 | 0;
+ $64 = +HEAPF64[$y378 >> 3];
+ $mul379 = $64 * -1.0;
+ HEAPF64[$y378 >> 3] = $mul379;
+ $inc381 = $i_0310 + 1 | 0;
+ $cmp374 = ($inc381 | 0) < ($pi_2_lcssa | 0);
+ if ($cmp374) {
+ $i_0310 = $inc381;
+ label = 55;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 56:
+ $x390 = $7 + ($bi_4308 << 5) | 0;
+ HEAPF64[$x390 >> 3] = 2147483647.0;
+ $x393 = $7 + ($bi_4308 << 5) + 16 | 0;
+ HEAPF64[$x393 >> 3] = -2147483648.0;
+ $inc395 = $bi_4308 + 1 | 0;
+ $cmp385 = ($inc395 | 0) < ($8 | 0);
+ if ($cmp385) {
+ $bi_4308 = $inc395;
+ label = 56;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $65 = HEAP32[1728] | 0;
+ $ps = $poly | 0;
+ HEAP32[$ps >> 2] = $65;
+ $pn = $poly + 4 | 0;
+ HEAP32[$pn >> 2] = $pi_2_lcssa;
+ $x397 = $pp | 0;
+ $66 = +HEAPF64[$x397 >> 3];
+ $arrayidx398 = $eps | 0;
+ $x399 = $eps | 0;
+ HEAPF64[$x399 >> 3] = $66;
+ $y402 = $pp + 8 | 0;
+ $67 = +HEAPF64[$y402 >> 3];
+ $y404 = $eps + 8 | 0;
+ HEAPF64[$y404 >> 3] = $67;
+ $x406 = $pp + 40 | 0;
+ $68 = +HEAPF64[$x406 >> 3];
+ $x408 = $eps + 16 | 0;
+ HEAPF64[$x408 >> 3] = $68;
+ $y411 = $pp + 48 | 0;
+ $69 = +HEAPF64[$y411 >> 3];
+ $y413 = $eps + 24 | 0;
+ HEAPF64[$y413 >> 3] = $69;
+ $call414 = _Pshortestpath($poly, $arrayidx398, $pl) | 0;
+ $cmp415 = ($call414 | 0) == -1;
+ if ($cmp415) {
+ label = 58;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 58:
+ _abort();
+ return 0;
+ return 0;
+ case 59:
+ $tobool419 = ($polyline | 0) == 0;
+ if ($tobool419) {
+ label = 61;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ _make_polyline($pl, $spl);
+ label = 77;
+ break;
+ case 61:
+ $70 = HEAP32[$pn >> 2] | 0;
+ $71 = HEAP32[5082] | 0;
+ $cmp423 = ($70 | 0) > ($71 | 0);
+ if ($cmp423) {
+ label = 62;
+ break;
+ } else {
+ $76 = $70;
+ label = 66;
+ break;
+ }
+ case 62:
+ $72 = HEAP32[5080] | 0;
+ $tobool426 = ($72 | 0) == 0;
+ if ($tobool426) {
+ label = 64;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ $73 = $72;
+ $mul429 = $70 << 5;
+ $call430 = _grealloc($73, $mul429) | 0;
+ $call430_sink = $call430;
+ label = 65;
+ break;
+ case 64:
+ $mul433 = $70 << 5;
+ $call434 = _gmalloc($mul433) | 0;
+ $call430_sink = $call434;
+ label = 65;
+ break;
+ case 65:
+ $74 = $call430_sink;
+ HEAP32[5080] = $74;
+ $75 = HEAP32[$pn >> 2] | 0;
+ HEAP32[5082] = $75;
+ $_pr = HEAP32[$pn >> 2] | 0;
+ $76 = $_pr;
+ label = 66;
+ break;
+ case 66:
+ $cmp441305 = ($76 | 0) > 0;
+ if ($cmp441305) {
+ label = 67;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 67:
+ $77 = HEAP32[5080] | 0;
+ $78 = HEAP32[1728] | 0;
+ $79 = HEAP32[$pn >> 2] | 0;
+ $edgei_0306 = 0;
+ label = 68;
+ break;
+ case 68:
+ $a = $77 + ($edgei_0306 << 5) | 0;
+ $arrayidx445 = $78 + ($edgei_0306 << 4) | 0;
+ $80 = $a;
+ $81 = $arrayidx445;
+ HEAP32[$80 >> 2] = HEAP32[$81 >> 2] | 0;
+ HEAP32[$80 + 4 >> 2] = HEAP32[$81 + 4 >> 2] | 0;
+ HEAP32[$80 + 8 >> 2] = HEAP32[$81 + 8 >> 2] | 0;
+ HEAP32[$80 + 12 >> 2] = HEAP32[$81 + 12 >> 2] | 0;
+ $b = $77 + ($edgei_0306 << 5) + 16 | 0;
+ $add447 = $edgei_0306 + 1 | 0;
+ $rem = ($add447 | 0) % ($79 | 0);
+ $arrayidx449 = $78 + ($rem << 4) | 0;
+ $82 = $b;
+ $83 = $arrayidx449;
+ HEAP32[$82 >> 2] = HEAP32[$83 >> 2] | 0;
+ HEAP32[$82 + 4 >> 2] = HEAP32[$83 + 4 >> 2] | 0;
+ HEAP32[$82 + 8 >> 2] = HEAP32[$83 + 8 >> 2] | 0;
+ HEAP32[$82 + 12 >> 2] = HEAP32[$83 + 12 >> 2] | 0;
+ $cmp441 = ($add447 | 0) < ($79 | 0);
+ if ($cmp441) {
+ $edgei_0306 = $add447;
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 69:
+ $constrained = $pp + 29 | 0;
+ $84 = HEAP8[$constrained] | 0;
+ $tobool454 = $84 << 24 >> 24 == 0;
+ if ($tobool454) {
+ label = 71;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $theta = $pp + 16 | 0;
+ $85 = +HEAPF64[$theta >> 3];
+ $call457 = +Math_cos(+$85);
+ $x459 = $evs | 0;
+ HEAPF64[$x459 >> 3] = $call457;
+ $86 = +HEAPF64[$theta >> 3];
+ $call462 = +Math_sin(+$86);
+ $y464 = $evs + 8 | 0;
+ HEAPF64[$y464 >> 3] = $call462;
+ label = 72;
+ break;
+ case 71:
+ $87 = $evs;
+ _memset($87 | 0, 0, 16);
+ label = 72;
+ break;
+ case 72:
+ $constrained472 = $pp + 69 | 0;
+ $88 = HEAP8[$constrained472] | 0;
+ $tobool473 = $88 << 24 >> 24 == 0;
+ if ($tobool473) {
+ label = 74;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $theta476 = $pp + 56 | 0;
+ $89 = +HEAPF64[$theta476 >> 3];
+ $call477 = +Math_cos(+$89);
+ $sub478 = -0.0 - $call477;
+ $x480 = $evs + 16 | 0;
+ HEAPF64[$x480 >> 3] = $sub478;
+ $90 = +HEAPF64[$theta476 >> 3];
+ $call483 = +Math_sin(+$90);
+ $sub484 = -0.0 - $call483;
+ $y486 = $evs + 24 | 0;
+ HEAPF64[$y486 >> 3] = $sub484;
+ label = 75;
+ break;
+ case 74:
+ $x491 = $evs + 16 | 0;
+ $91 = $x491;
+ _memset($91 | 0, 0, 16);
+ label = 75;
+ break;
+ case 75:
+ $92 = HEAP32[5080] | 0;
+ $93 = HEAP32[$pn >> 2] | 0;
+ $arraydecay494 = $evs | 0;
+ $call495 = _Proutespline($92, $93, $pl, $arraydecay494, $spl) | 0;
+ $cmp496 = ($call495 | 0) == -1;
+ if ($cmp496) {
+ label = 76;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 76:
+ _abort();
+ return 0;
+ return 0;
+ case 77:
+ $pn501 = $spl + 4 | 0;
+ $94 = HEAP32[$pn501 >> 2] | 0;
+ _mkspacep($94);
+ $cmp503303 = ($8 | 0) > 0;
+ if ($cmp503303) {
+ $bi_5304 = 0;
+ label = 80;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $95 = HEAP32[$pn501 >> 2] | 0;
+ $cmp517301 = ($95 | 0) > 0;
+ if ($cmp517301) {
+ label = 79;
+ break;
+ } else {
+ $99 = $95;
+ label = 82;
+ break;
+ }
+ case 79:
+ $96 = HEAP32[1392] | 0;
+ $ps521 = $spl | 0;
+ $97 = HEAP32[$ps521 >> 2] | 0;
+ $98 = HEAP32[$pn501 >> 2] | 0;
+ $splinepi_0302 = 0;
+ label = 83;
+ break;
+ case 80:
+ $x508 = $7 + ($bi_5304 << 5) | 0;
+ HEAPF64[$x508 >> 3] = 2147483647.0;
+ $x511 = $7 + ($bi_5304 << 5) + 16 | 0;
+ HEAPF64[$x511 >> 3] = -2147483648.0;
+ $inc513 = $bi_5304 + 1 | 0;
+ $cmp503 = ($inc513 | 0) < ($8 | 0);
+ if ($cmp503) {
+ $bi_5304 = $inc513;
+ label = 80;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 81:
+ $_pr331 = HEAP32[$pn501 >> 2] | 0;
+ $99 = $_pr331;
+ label = 82;
+ break;
+ case 82:
+ $cmp529298 = ($99 | 0) > 3;
+ $100 = HEAP32[1392] | 0;
+ $cmp683293 = ($8 | 0) > 0;
+ $delta_0 = 10;
+ label = 84;
+ break;
+ case 83:
+ $arrayidx520 = $96 + ($splinepi_0302 << 4) | 0;
+ $arrayidx522 = $97 + ($splinepi_0302 << 4) | 0;
+ $101 = $arrayidx520;
+ $102 = $arrayidx522;
+ HEAP32[$101 >> 2] = HEAP32[$102 >> 2] | 0;
+ HEAP32[$101 + 4 >> 2] = HEAP32[$102 + 4 >> 2] | 0;
+ HEAP32[$101 + 8 >> 2] = HEAP32[$102 + 8 >> 2] | 0;
+ HEAP32[$101 + 12 >> 2] = HEAP32[$102 + 12 >> 2] | 0;
+ $inc524 = $splinepi_0302 + 1 | 0;
+ $cmp517 = ($inc524 | 0) < ($98 | 0);
+ if ($cmp517) {
+ $splinepi_0302 = $inc524;
+ label = 83;
+ break;
+ } else {
+ label = 81;
+ break;
+ }
+ case 84:
+ if ($cmp529298) {
+ label = 85;
+ break;
+ } else {
+ $bi_7 = 0;
+ label = 98;
+ break;
+ }
+ case 85:
+ $mul532 = Math_imul($delta_0, $8);
+ $cmp534296 = ($mul532 | 0) < 0;
+ $conv538 = +($mul532 | 0);
+ $splinepi_1299 = 0;
+ $add527300 = 3;
+ label = 87;
+ break;
+ case 86:
+ $add527 = $add527300 + 3 | 0;
+ $cmp529 = ($add527 | 0) < ($99 | 0);
+ if ($cmp529) {
+ $splinepi_1299 = $add527300;
+ $add527300 = $add527;
+ label = 87;
+ break;
+ } else {
+ $bi_7 = 0;
+ label = 98;
+ break;
+ }
+ case 87:
+ if ($cmp534296) {
+ label = 86;
+ break;
+ } else {
+ label = 88;
+ break;
+ }
+ case 88:
+ $sp_sroa_0_0__idx = $100 + ($splinepi_1299 << 4) | 0;
+ $sp_sroa_1_8__idx229 = $100 + ($splinepi_1299 << 4) + 8 | 0;
+ $add542 = $splinepi_1299 + 1 | 0;
+ $sp_sroa_2_16__idx = $100 + ($add542 << 4) | 0;
+ $sp_sroa_3_24__idx242 = $100 + ($add542 << 4) + 8 | 0;
+ $add545 = $splinepi_1299 + 2 | 0;
+ $sp_sroa_4_32__idx = $100 + ($add545 << 4) | 0;
+ $sp_sroa_5_40__idx249 = $100 + ($add545 << 4) + 8 | 0;
+ $sp_sroa_6_48__idx = $100 + ($add527300 << 4) | 0;
+ $sp_sroa_7_56__idx250 = $100 + ($add527300 << 4) + 8 | 0;
+ $si_0297 = 0;
+ label = 89;
+ break;
+ case 89:
+ $conv537 = +($si_0297 | 0);
+ $div = $conv537 / $conv538;
+ $sp_sroa_0_0_copyload = +HEAPF64[$sp_sroa_0_0__idx >> 3];
+ $sp_sroa_1_8_copyload = +HEAPF64[$sp_sroa_1_8__idx229 >> 3];
+ $sp_sroa_2_16_copyload = +HEAPF64[$sp_sroa_2_16__idx >> 3];
+ $sp_sroa_3_24_copyload = +HEAPF64[$sp_sroa_3_24__idx242 >> 3];
+ $sp_sroa_4_32_copyload = +HEAPF64[$sp_sroa_4_32__idx >> 3];
+ $sp_sroa_5_40_copyload = +HEAPF64[$sp_sroa_5_40__idx249 >> 3];
+ $sp_sroa_6_48_copyload = +HEAPF64[$sp_sroa_6_48__idx >> 3];
+ $sp_sroa_7_56_copyload = +HEAPF64[$sp_sroa_7_56__idx250 >> 3];
+ $sub556 = $sp_sroa_2_16_copyload - $sp_sroa_0_0_copyload;
+ $mul557 = $div * $sub556;
+ $add558 = $sp_sroa_0_0_copyload + $mul557;
+ $sub567 = $sp_sroa_3_24_copyload - $sp_sroa_1_8_copyload;
+ $mul568 = $div * $sub567;
+ $add569 = $sp_sroa_1_8_copyload + $mul568;
+ $sub578 = $sp_sroa_4_32_copyload - $sp_sroa_2_16_copyload;
+ $mul579 = $div * $sub578;
+ $add580 = $sp_sroa_2_16_copyload + $mul579;
+ $sub589 = $sp_sroa_5_40_copyload - $sp_sroa_3_24_copyload;
+ $mul590 = $div * $sub589;
+ $add591 = $sp_sroa_3_24_copyload + $mul590;
+ $sub600 = $sp_sroa_6_48_copyload - $sp_sroa_4_32_copyload;
+ $mul601 = $div * $sub600;
+ $add602 = $sp_sroa_4_32_copyload + $mul601;
+ $sub611 = $sp_sroa_7_56_copyload - $sp_sroa_5_40_copyload;
+ $mul612 = $div * $sub611;
+ $add613 = $sp_sroa_5_40_copyload + $mul612;
+ $sub622 = $add580 - $add558;
+ $mul623 = $div * $sub622;
+ $add624 = $add558 + $mul623;
+ $sub633 = $add591 - $add569;
+ $mul634 = $div * $sub633;
+ $add635 = $add569 + $mul634;
+ $sub644 = $add602 - $add580;
+ $mul645 = $div * $sub644;
+ $add646 = $add580 + $mul645;
+ $sub655 = $add613 - $add591;
+ $mul656 = $div * $sub655;
+ $add657 = $add591 + $mul656;
+ $sub666 = $add646 - $add624;
+ $mul667 = $div * $sub666;
+ $add668 = $add624 + $mul667;
+ $sub677 = $add657 - $add635;
+ $mul678 = $div * $sub677;
+ $add679 = $add635 + $mul678;
+ if ($cmp683293) {
+ $bi_6294 = 0;
+ label = 90;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 90:
+ $y690 = $7 + ($bi_6294 << 5) + 24 | 0;
+ $103 = +HEAPF64[$y690 >> 3];
+ $add691 = $103 + 1.0e-4;
+ $cmp692 = $add679 > $add691;
+ if ($cmp692) {
+ label = 96;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 91:
+ $y699 = $7 + ($bi_6294 << 5) + 8 | 0;
+ $104 = +HEAPF64[$y699 >> 3];
+ $sub700 = $104 + -1.0e-4;
+ $cmp701 = $add679 < $sub700;
+ if ($cmp701) {
+ label = 96;
+ break;
+ } else {
+ label = 92;
+ break;
+ }
+ case 92:
+ $x706 = $7 + ($bi_6294 << 5) | 0;
+ $105 = +HEAPF64[$x706 >> 3];
+ $cmp709 = $105 > $add668;
+ if ($cmp709) {
+ label = 93;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 93:
+ HEAPF64[$x706 >> 3] = $add668;
+ label = 94;
+ break;
+ case 94:
+ $x720 = $7 + ($bi_6294 << 5) + 16 | 0;
+ $106 = +HEAPF64[$x720 >> 3];
+ $cmp723 = $106 < $add668;
+ if ($cmp723) {
+ label = 95;
+ break;
+ } else {
+ label = 96;
+ break;
+ }
+ case 95:
+ HEAPF64[$x720 >> 3] = $add668;
+ label = 96;
+ break;
+ case 96:
+ $inc734 = $bi_6294 + 1 | 0;
+ $cmp683 = ($inc734 | 0) < ($8 | 0);
+ if ($cmp683) {
+ $bi_6294 = $inc734;
+ label = 90;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 97:
+ $inc737 = $si_0297 + 1 | 0;
+ $cmp534 = ($inc737 | 0) > ($mul532 | 0);
+ if ($cmp534) {
+ label = 86;
+ break;
+ } else {
+ $si_0297 = $inc737;
+ label = 89;
+ break;
+ }
+ case 98:
+ $cmp743 = ($bi_7 | 0) < ($8 | 0);
+ if ($cmp743) {
+ label = 99;
+ break;
+ } else {
+ label = 102;
+ break;
+ }
+ case 99:
+ $x748 = $7 + ($bi_7 << 5) | 0;
+ $107 = +HEAPF64[$x748 >> 3];
+ $cmp749 = $107 == 2147483647.0;
+ if ($cmp749) {
+ label = 101;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 100:
+ $x754 = $7 + ($bi_7 << 5) + 16 | 0;
+ $108 = +HEAPF64[$x754 >> 3];
+ $cmp755 = $108 == -2147483648.0;
+ $inc761 = $bi_7 + 1 | 0;
+ if ($cmp755) {
+ label = 101;
+ break;
+ } else {
+ $bi_7 = $inc761;
+ label = 98;
+ break;
+ }
+ case 101:
+ $mul758 = $delta_0 << 1;
+ $delta_0 = $mul758;
+ label = 84;
+ break;
+ case 102:
+ $109 = HEAP32[$pn501 >> 2] | 0;
+ HEAP32[$npoints >> 2] = $109;
+ $110 = HEAP32[1392] | 0;
+ STACKTOP = __stackBase__;
+ return $110 | 0;
+ }
+ return 0;
+}
+function _overlap($i0, $i1, $j0, $j1) {
+ $i0 = $i0 | 0;
+ $i1 = $i1 | 0;
+ $j0 = $j0 | 0;
+ $j1 = $j1 | 0;
+ var $cmp = 0, $cmp1 = 0, $or_cond22 = 0, $cmp4 = 0, $cmp5 = 0, $or_cond = 0, $sub = 0, $cmp8 = 0, $cmp10 = 0, $or_cond21 = 0, $sub12 = 0, $sub14 = 0, $sub15 = 0, $cmp16 = 0, $sub14_sub15 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($i1 | 0) > ($j0 | 0);
+ $cmp1 = ($i0 | 0) < ($j1 | 0);
+ $or_cond22 = $cmp & $cmp1;
+ if ($or_cond22) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ }
+ case 3:
+ $cmp4 = ($j0 | 0) > ($i0 | 0);
+ $cmp5 = ($i0 | 0) > ($j1 | 0);
+ $or_cond = $cmp4 | $cmp5;
+ if ($or_cond) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $sub = $j1 - $i0 | 0;
+ $retval_0 = $sub;
+ label = 8;
+ break;
+ case 5:
+ $cmp8 = ($j0 | 0) > ($i1 | 0);
+ $cmp10 = ($i1 | 0) > ($j1 | 0);
+ $or_cond21 = $cmp8 | $cmp10;
+ if ($or_cond21) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $sub12 = $i1 - $j0 | 0;
+ $retval_0 = $sub12;
+ label = 8;
+ break;
+ case 7:
+ $sub14 = $i1 - $i0 | 0;
+ $sub15 = $j1 - $j0 | 0;
+ $cmp16 = ($sub14 | 0) < ($sub15 | 0);
+ $sub14_sub15 = $cmp16 ? $sub14 : $sub15;
+ $retval_0 = $sub14_sub15;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _printpath($pp) {
+ $pp = $pp | 0;
+ var $0 = 0, $nbox = 0, $1 = 0, $call = 0, $2 = 0, $cmp20 = 0, $3 = 0, $boxes = 0, $4 = 0, $bi_021 = 0, $5 = 0, $x = 0, $6 = 0.0, $y = 0, $7 = 0.0, $x7 = 0, $8 = 0.0, $y11 = 0, $9 = 0.0, $call12 = 0, $inc = 0, $10 = 0, $cmp = 0, $11 = 0, $_lcssa = 0, $x13 = 0, $12 = 0.0, $y16 = 0, $13 = 0.0, $theta = 0, $14 = 0.0, $constrained = 0, $15 = 0, $tobool = 0, $cond = 0, $call19 = 0, $16 = 0, $x21 = 0, $17 = 0.0, $y24 = 0, $18 = 0.0, $theta26 = 0, $19 = 0.0, $constrained28 = 0, $20 = 0, $tobool30 = 0, $cond31 = 0, $call32 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[_stderr >> 2] | 0;
+ $nbox = $pp + 80 | 0;
+ $1 = HEAP32[$nbox >> 2] | 0;
+ $call = _fprintf($0 | 0, 90672, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $1, tempInt) | 0) | 0;
+ $2 = HEAP32[$nbox >> 2] | 0;
+ $cmp20 = ($2 | 0) > 0;
+ $3 = HEAP32[_stderr >> 2] | 0;
+ if ($cmp20) {
+ label = 3;
+ break;
+ } else {
+ $_lcssa = $3;
+ label = 5;
+ break;
+ }
+ case 3:
+ $boxes = $pp + 84 | 0;
+ $bi_021 = 0;
+ $4 = $3;
+ label = 4;
+ break;
+ case 4:
+ $5 = HEAP32[$boxes >> 2] | 0;
+ $x = $5 + ($bi_021 << 5) | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $y = $5 + ($bi_021 << 5) + 8 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $x7 = $5 + ($bi_021 << 5) + 16 | 0;
+ $8 = +HEAPF64[$x7 >> 3];
+ $y11 = $5 + ($bi_021 << 5) + 24 | 0;
+ $9 = +HEAPF64[$y11 >> 3];
+ $call12 = _fprintf($4 | 0, 160832, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = $bi_021, HEAPF64[tempInt + 8 >> 3] = $6, HEAPF64[tempInt + 16 >> 3] = $7, HEAPF64[tempInt + 24 >> 3] = $8, HEAPF64[tempInt + 32 >> 3] = $9, tempInt) | 0) | 0;
+ $inc = $bi_021 + 1 | 0;
+ $10 = HEAP32[$nbox >> 2] | 0;
+ $cmp = ($inc | 0) < ($10 | 0);
+ $11 = HEAP32[_stderr >> 2] | 0;
+ if ($cmp) {
+ $bi_021 = $inc;
+ $4 = $11;
+ label = 4;
+ break;
+ } else {
+ $_lcssa = $11;
+ label = 5;
+ break;
+ }
+ case 5:
+ $x13 = $pp | 0;
+ $12 = +HEAPF64[$x13 >> 3];
+ $y16 = $pp + 8 | 0;
+ $13 = +HEAPF64[$y16 >> 3];
+ $theta = $pp + 16 | 0;
+ $14 = +HEAPF64[$theta >> 3];
+ $constrained = $pp + 29 | 0;
+ $15 = HEAP8[$constrained] | 0;
+ $tobool = $15 << 24 >> 24 != 0;
+ $cond = $tobool ? 153880 : 150200;
+ $call19 = _fprintf($_lcssa | 0, 157096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $12, HEAPF64[tempInt + 8 >> 3] = $13, HEAPF64[tempInt + 16 >> 3] = $14, HEAP32[tempInt + 24 >> 2] = $cond, tempInt) | 0) | 0;
+ $16 = HEAP32[_stderr >> 2] | 0;
+ $x21 = $pp + 40 | 0;
+ $17 = +HEAPF64[$x21 >> 3];
+ $y24 = $pp + 48 | 0;
+ $18 = +HEAPF64[$y24 >> 3];
+ $theta26 = $pp + 56 | 0;
+ $19 = +HEAPF64[$theta26 >> 3];
+ $constrained28 = $pp + 69 | 0;
+ $20 = HEAP8[$constrained28] | 0;
+ $tobool30 = $20 << 24 >> 24 != 0;
+ $cond31 = $tobool30 ? 153880 : 150200;
+ $call32 = _fprintf($16 | 0, 147320, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $17, HEAPF64[tempInt + 8 >> 3] = $18, HEAPF64[tempInt + 16 >> 3] = $19, HEAP32[tempInt + 24 >> 2] = $cond31, tempInt) | 0) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _checkpath($boxn, $boxes, $thepath) {
+ $boxn = $boxn | 0;
+ $boxes = $boxes | 0;
+ $thepath = $thepath | 0;
+ var $cmp207 = 0, $bi_0209 = 0, $i_0208 = 0, $arrayidx = 0, $y = 0, $0 = 0.0, $y2 = 0, $1 = 0.0, $sub = 0.0, $cmp3 = 0, $sub18 = 0.0, $cond = 0.0, $cmp19 = 0, $x = 0, $2 = 0.0, $x24 = 0, $3 = 0.0, $sub25 = 0.0, $cmp26 = 0, $sub43 = 0.0, $cond45 = 0.0, $cmp46 = 0, $cmp49 = 0, $arrayidx51 = 0, $4 = 0, $5 = 0, $inc = 0, $i_1 = 0, $inc54 = 0, $cmp = 0, $i_0_lcssa = 0, $x57 = 0, $6 = 0.0, $x59 = 0, $7 = 0.0, $cmp60 = 0, $y62 = 0, $8 = 0.0, $y64 = 0, $9 = 0.0, $cmp65 = 0, $sub69 = 0, $cmp70205 = 0, $call = 0, $bi_1206 = 0, $add = 0, $x75 = 0, $10 = 0.0, $x77 = 0, $11 = 0.0, $cmp78 = 0, $y81 = 0, $12 = 0.0, $y83 = 0, $13 = 0.0, $cmp84 = 0, $call87 = 0, $x90 = 0, $14 = 0.0, $cmp93 = 0, $cond94 = 0, $x96 = 0, $15 = 0.0, $cmp99 = 0, $cond100 = 0, $y102 = 0, $16 = 0.0, $cmp105 = 0, $cond106 = 0, $y108 = 0, $17 = 0.0, $cmp111 = 0, $cond112 = 0, $add113 = 0, $add114 = 0, $add115 = 0, $cmp116 = 0, $cmp116_not = 0, $18 = 0, $tobool = 0, $or_cond = 0, $19 = 0, $call119 = 0, $20 = 0.0, $conv129 = 0, $21 = 0.0, $conv134 = 0.0, $22 = 0.0, $conv142 = 0, $23 = 0.0, $conv147 = 0.0, $24 = 0.0, $conv156 = 0, $25 = 0.0, $conv161 = 0.0, $26 = 0.0, $conv170 = 0, $27 = 0.0, $conv175 = 0.0, $l_1_ph = 0, $r_1_ph = 0, $d_1_ph = 0, $u_1_ph = 0, $sub183 = 0, $cmp184198 = 0, $u_1203 = 0, $d_1202 = 0, $r_1201 = 0, $l_1200 = 0, $i_2199 = 0, $cmp187 = 0, $28 = 0.0, $29 = 0.0, $add194 = 0.0, $div = 0.0, $add195 = 0.0, $conv196 = 0, $conv197 = 0.0, $cmp203 = 0, $30 = 0.0, $31 = 0.0, $add210 = 0.0, $div211 = 0.0, $add212 = 0.0, $conv213 = 0, $conv214 = 0.0, $cmp220 = 0, $32 = 0.0, $33 = 0.0, $add227 = 0.0, $div228 = 0.0, $add229 = 0.0, $conv230 = 0, $conv231 = 0.0, $cmp237 = 0, $34 = 0.0, $35 = 0.0, $add244 = 0.0, $div245 = 0.0, $add246 = 0.0, $conv247 = 0, $conv248 = 0.0, $l_2 = 0, $r_2 = 0, $d_2 = 0, $u_2 = 0, $inc258 = 0, $cmp184 = 0, $36 = 0.0, $conv263 = 0, $37 = 0.0, $conv266 = 0, $38 = 0.0, $conv269 = 0, $39 = 0.0, $conv272 = 0, $call273 = 0, $40 = 0.0, $conv276 = 0, $41 = 0.0, $conv279 = 0, $42 = 0.0, $conv282 = 0, $43 = 0.0, $conv285 = 0, $call286 = 0, $tobool287 = 0, $tobool289 = 0, $or_cond197 = 0, $cmp70 = 0, $cmp291 = 0, $sub298 = 0.0, $sub303 = 0.0, $cmp304 = 0, $cmp311 = 0, $sub348 = 0.0, $sub353 = 0.0, $cmp354 = 0, $cmp361 = 0, $x398 = 0, $44 = 0.0, $45 = 0.0, $cmp402 = 0, $46 = 0.0, $cmp411 = 0, $y416 = 0, $47 = 0.0, $48 = 0.0, $cmp420 = 0, $49 = 0.0, $cmp429 = 0, $50 = 0, $tobool432 = 0, $51 = 0, $52 = 0, $53 = 0.0, $54 = 0.0, $cmp442 = 0, $55 = 0.0, $56 = 0.0, $cmp458 = 0, $y470 = 0, $57 = 0.0, $58 = 0.0, $cmp474 = 0, $59 = 0.0, $60 = 0.0, $cmp490 = 0, $x502 = 0, $61 = 0.0, $x506 = 0, $62 = 0.0, $cmp507 = 0, $x516 = 0, $63 = 0.0, $cmp517 = 0, $y522 = 0, $64 = 0.0, $y526 = 0, $65 = 0.0, $cmp527 = 0, $y536 = 0, $66 = 0.0, $cmp537 = 0, $67 = 0, $tobool540 = 0, $68 = 0, $69 = 0, $70 = 0.0, $71 = 0.0, $cmp551 = 0, $72 = 0.0, $x568 = 0, $73 = 0.0, $cmp569 = 0, $y582 = 0, $74 = 0.0, $y586 = 0, $75 = 0.0, $cmp587 = 0, $76 = 0.0, $y604 = 0, $77 = 0.0, $cmp605 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp207 = ($boxn | 0) > 0;
+ if ($cmp207) {
+ $i_0208 = 0;
+ $bi_0209 = 0;
+ label = 3;
+ break;
+ } else {
+ $i_0_lcssa = 0;
+ label = 13;
+ break;
+ }
+ case 3:
+ $arrayidx = $boxes + ($bi_0209 << 5) | 0;
+ $y = $boxes + ($bi_0209 << 5) + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $y2 = $boxes + ($bi_0209 << 5) + 24 | 0;
+ $1 = +HEAPF64[$y2 >> 3];
+ $sub = $0 - $1;
+ $cmp3 = $sub < 0.0;
+ if ($cmp3) {
+ label = 4;
+ break;
+ } else {
+ $cond = $sub;
+ label = 5;
+ break;
+ }
+ case 4:
+ $sub18 = -0.0 - $sub;
+ $cond = $sub18;
+ label = 5;
+ break;
+ case 5:
+ $cmp19 = $cond < .01;
+ if ($cmp19) {
+ $i_1 = $i_0208;
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $x = $arrayidx | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x24 = $boxes + ($bi_0209 << 5) + 16 | 0;
+ $3 = +HEAPF64[$x24 >> 3];
+ $sub25 = $2 - $3;
+ $cmp26 = $sub25 < 0.0;
+ if ($cmp26) {
+ label = 7;
+ break;
+ } else {
+ $cond45 = $sub25;
+ label = 8;
+ break;
+ }
+ case 7:
+ $sub43 = -0.0 - $sub25;
+ $cond45 = $sub43;
+ label = 8;
+ break;
+ case 8:
+ $cmp46 = $cond45 < .01;
+ if ($cmp46) {
+ $i_1 = $i_0208;
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp49 = ($i_0208 | 0) == ($bi_0209 | 0);
+ if ($cmp49) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $arrayidx51 = $boxes + ($i_0208 << 5) | 0;
+ $4 = $arrayidx51;
+ $5 = $arrayidx;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ HEAP32[$4 + 16 >> 2] = HEAP32[$5 + 16 >> 2] | 0;
+ HEAP32[$4 + 20 >> 2] = HEAP32[$5 + 20 >> 2] | 0;
+ HEAP32[$4 + 24 >> 2] = HEAP32[$5 + 24 >> 2] | 0;
+ HEAP32[$4 + 28 >> 2] = HEAP32[$5 + 28 >> 2] | 0;
+ label = 11;
+ break;
+ case 11:
+ $inc = $i_0208 + 1 | 0;
+ $i_1 = $inc;
+ label = 12;
+ break;
+ case 12:
+ $inc54 = $bi_0209 + 1 | 0;
+ $cmp = ($inc54 | 0) < ($boxn | 0);
+ if ($cmp) {
+ $i_0208 = $i_1;
+ $bi_0209 = $inc54;
+ label = 3;
+ break;
+ } else {
+ $i_0_lcssa = $i_1;
+ label = 13;
+ break;
+ }
+ case 13:
+ $x57 = $boxes | 0;
+ $6 = +HEAPF64[$x57 >> 3];
+ $x59 = $boxes + 16 | 0;
+ $7 = +HEAPF64[$x59 >> 3];
+ $cmp60 = $6 > $7;
+ if ($cmp60) {
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $y62 = $boxes + 8 | 0;
+ $8 = +HEAPF64[$y62 >> 3];
+ $y64 = $boxes + 24 | 0;
+ $9 = +HEAPF64[$y64 >> 3];
+ $cmp65 = $8 > $9;
+ if ($cmp65) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $sub69 = $i_0_lcssa - 1 | 0;
+ $cmp70205 = ($sub69 | 0) > 0;
+ if ($cmp70205) {
+ $bi_1206 = 0;
+ label = 17;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 16:
+ $call = _agerr(1, 110272, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _printpath($thepath);
+ _abort();
+ case 17:
+ $add = $bi_1206 + 1 | 0;
+ $x75 = $boxes + ($add << 5) | 0;
+ $10 = +HEAPF64[$x75 >> 3];
+ $x77 = $boxes + ($add << 5) + 16 | 0;
+ $11 = +HEAPF64[$x77 >> 3];
+ $cmp78 = $10 > $11;
+ if ($cmp78) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $y81 = $boxes + ($add << 5) + 8 | 0;
+ $12 = +HEAPF64[$y81 >> 3];
+ $y83 = $boxes + ($add << 5) + 24 | 0;
+ $13 = +HEAPF64[$y83 >> 3];
+ $cmp84 = $12 > $13;
+ if ($cmp84) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $call87 = _agerr(1, 106096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $add, tempInt) | 0) | 0;
+ _printpath($thepath);
+ _abort();
+ case 20:
+ $x90 = $boxes + ($bi_1206 << 5) + 16 | 0;
+ $14 = +HEAPF64[$x90 >> 3];
+ $cmp93 = $14 < $10;
+ $cond94 = $cmp93 & 1;
+ $x96 = $boxes + ($bi_1206 << 5) | 0;
+ $15 = +HEAPF64[$x96 >> 3];
+ $cmp99 = $15 > $11;
+ $cond100 = $cmp99 & 1;
+ $y102 = $boxes + ($bi_1206 << 5) + 24 | 0;
+ $16 = +HEAPF64[$y102 >> 3];
+ $cmp105 = $16 < $12;
+ $cond106 = $cmp105 & 1;
+ $y108 = $boxes + ($bi_1206 << 5) + 8 | 0;
+ $17 = +HEAPF64[$y108 >> 3];
+ $cmp111 = $17 > $13;
+ $cond112 = $cmp111 & 1;
+ $add113 = $cond100 + $cond94 | 0;
+ $add114 = $add113 + $cond106 | 0;
+ $add115 = $add114 + $cond112 | 0;
+ $cmp116 = ($add115 | 0) > 0;
+ $cmp116_not = $cmp116 ^ 1;
+ $18 = HEAP8[164912] | 0;
+ $tobool = $18 << 24 >> 24 == 0;
+ $or_cond = $tobool | $cmp116_not;
+ if ($or_cond) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $19 = HEAP32[_stderr >> 2] | 0;
+ $call119 = _fprintf($19 | 0, 102168, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $bi_1206, HEAP32[tempInt + 8 >> 2] = $add, tempInt) | 0) | 0;
+ _printpath($thepath);
+ label = 22;
+ break;
+ case 22:
+ if ($cmp116) {
+ label = 23;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 23:
+ if ($cmp93) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $20 = +HEAPF64[$x90 >> 3];
+ $conv129 = ~~$20;
+ $21 = +HEAPF64[$x75 >> 3];
+ HEAPF64[$x90 >> 3] = $21;
+ $conv134 = +($conv129 | 0);
+ HEAPF64[$x75 >> 3] = $conv134;
+ $u_1_ph = $cond112;
+ $d_1_ph = $cond106;
+ $r_1_ph = $cond100;
+ $l_1_ph = 0;
+ label = 31;
+ break;
+ case 25:
+ if ($cmp99) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $22 = +HEAPF64[$x96 >> 3];
+ $conv142 = ~~$22;
+ $23 = +HEAPF64[$x77 >> 3];
+ HEAPF64[$x96 >> 3] = $23;
+ $conv147 = +($conv142 | 0);
+ HEAPF64[$x77 >> 3] = $conv147;
+ $u_1_ph = $cond112;
+ $d_1_ph = $cond106;
+ $r_1_ph = 0;
+ $l_1_ph = $cond94;
+ label = 31;
+ break;
+ case 27:
+ if ($cmp105) {
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ $24 = +HEAPF64[$y102 >> 3];
+ $conv156 = ~~$24;
+ $25 = +HEAPF64[$y81 >> 3];
+ HEAPF64[$y102 >> 3] = $25;
+ $conv161 = +($conv156 | 0);
+ HEAPF64[$y81 >> 3] = $conv161;
+ $u_1_ph = $cond112;
+ $d_1_ph = 0;
+ $r_1_ph = $cond100;
+ $l_1_ph = $cond94;
+ label = 31;
+ break;
+ case 29:
+ if ($cmp111) {
+ label = 30;
+ break;
+ } else {
+ $u_1_ph = $cond112;
+ $d_1_ph = $cond106;
+ $r_1_ph = $cond100;
+ $l_1_ph = $cond94;
+ label = 31;
+ break;
+ }
+ case 30:
+ $26 = +HEAPF64[$y108 >> 3];
+ $conv170 = ~~$26;
+ $27 = +HEAPF64[$y83 >> 3];
+ HEAPF64[$y108 >> 3] = $27;
+ $conv175 = +($conv170 | 0);
+ HEAPF64[$y83 >> 3] = $conv175;
+ $u_1_ph = 0;
+ $d_1_ph = $cond106;
+ $r_1_ph = $cond100;
+ $l_1_ph = $cond94;
+ label = 31;
+ break;
+ case 31:
+ $sub183 = $add115 - 1 | 0;
+ $cmp184198 = ($sub183 | 0) > 0;
+ if ($cmp184198) {
+ $i_2199 = 0;
+ $l_1200 = $l_1_ph;
+ $r_1201 = $r_1_ph;
+ $d_1202 = $d_1_ph;
+ $u_1203 = $u_1_ph;
+ label = 32;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 32:
+ $cmp187 = ($l_1200 | 0) == 1;
+ if ($cmp187) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ $28 = +HEAPF64[$x90 >> 3];
+ $29 = +HEAPF64[$x75 >> 3];
+ $add194 = $28 + $29;
+ $div = $add194 * .5;
+ $add195 = $div + .5;
+ $conv196 = ~~$add195;
+ $conv197 = +($conv196 | 0);
+ HEAPF64[$x75 >> 3] = $conv197;
+ HEAPF64[$x90 >> 3] = $conv197;
+ $u_2 = $u_1203;
+ $d_2 = $d_1202;
+ $r_2 = $r_1201;
+ $l_2 = 0;
+ label = 40;
+ break;
+ case 34:
+ $cmp203 = ($r_1201 | 0) == 1;
+ if ($cmp203) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ $30 = +HEAPF64[$x96 >> 3];
+ $31 = +HEAPF64[$x77 >> 3];
+ $add210 = $30 + $31;
+ $div211 = $add210 * .5;
+ $add212 = $div211 + .5;
+ $conv213 = ~~$add212;
+ $conv214 = +($conv213 | 0);
+ HEAPF64[$x77 >> 3] = $conv214;
+ HEAPF64[$x96 >> 3] = $conv214;
+ $u_2 = $u_1203;
+ $d_2 = $d_1202;
+ $r_2 = 0;
+ $l_2 = $l_1200;
+ label = 40;
+ break;
+ case 36:
+ $cmp220 = ($d_1202 | 0) == 1;
+ if ($cmp220) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ $32 = +HEAPF64[$y102 >> 3];
+ $33 = +HEAPF64[$y81 >> 3];
+ $add227 = $32 + $33;
+ $div228 = $add227 * .5;
+ $add229 = $div228 + .5;
+ $conv230 = ~~$add229;
+ $conv231 = +($conv230 | 0);
+ HEAPF64[$y81 >> 3] = $conv231;
+ HEAPF64[$y102 >> 3] = $conv231;
+ $u_2 = $u_1203;
+ $d_2 = 0;
+ $r_2 = $r_1201;
+ $l_2 = $l_1200;
+ label = 40;
+ break;
+ case 38:
+ $cmp237 = ($u_1203 | 0) == 1;
+ if ($cmp237) {
+ label = 39;
+ break;
+ } else {
+ $u_2 = $u_1203;
+ $d_2 = $d_1202;
+ $r_2 = $r_1201;
+ $l_2 = $l_1200;
+ label = 40;
+ break;
+ }
+ case 39:
+ $34 = +HEAPF64[$y108 >> 3];
+ $35 = +HEAPF64[$y83 >> 3];
+ $add244 = $34 + $35;
+ $div245 = $add244 * .5;
+ $add246 = $div245 + .5;
+ $conv247 = ~~$add246;
+ $conv248 = +($conv247 | 0);
+ HEAPF64[$y83 >> 3] = $conv248;
+ HEAPF64[$y108 >> 3] = $conv248;
+ $u_2 = 0;
+ $d_2 = $d_1202;
+ $r_2 = $r_1201;
+ $l_2 = $l_1200;
+ label = 40;
+ break;
+ case 40:
+ $inc258 = $i_2199 + 1 | 0;
+ $cmp184 = ($inc258 | 0) < ($sub183 | 0);
+ if ($cmp184) {
+ $i_2199 = $inc258;
+ $l_1200 = $l_2;
+ $r_1201 = $r_2;
+ $d_1202 = $d_2;
+ $u_1203 = $u_2;
+ label = 32;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $36 = +HEAPF64[$x96 >> 3];
+ $conv263 = ~~$36;
+ $37 = +HEAPF64[$x90 >> 3];
+ $conv266 = ~~$37;
+ $38 = +HEAPF64[$x75 >> 3];
+ $conv269 = ~~$38;
+ $39 = +HEAPF64[$x77 >> 3];
+ $conv272 = ~~$39;
+ $call273 = _overlap($conv263, $conv266, $conv269, $conv272) | 0;
+ $40 = +HEAPF64[$y108 >> 3];
+ $conv276 = ~~$40;
+ $41 = +HEAPF64[$y102 >> 3];
+ $conv279 = ~~$41;
+ $42 = +HEAPF64[$y81 >> 3];
+ $conv282 = ~~$42;
+ $43 = +HEAPF64[$y83 >> 3];
+ $conv285 = ~~$43;
+ $call286 = _overlap($conv276, $conv279, $conv282, $conv285) | 0;
+ $tobool287 = ($call273 | 0) == 0;
+ $tobool289 = ($call286 | 0) == 0;
+ $or_cond197 = $tobool287 | $tobool289;
+ if ($or_cond197) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ $cmp70 = ($add | 0) < ($sub69 | 0);
+ if ($cmp70) {
+ $bi_1206 = $add;
+ label = 17;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 43:
+ $cmp291 = ($call273 | 0) < ($call286 | 0);
+ if ($cmp291) {
+ label = 44;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 44:
+ $sub298 = $37 - $36;
+ $sub303 = $39 - $38;
+ $cmp304 = $sub298 > $sub303;
+ $cmp311 = $37 < $39;
+ if ($cmp304) {
+ label = 45;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 45:
+ if ($cmp311) {
+ label = 46;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 46:
+ HEAPF64[$x90 >> 3] = $38;
+ label = 42;
+ break;
+ case 47:
+ HEAPF64[$x96 >> 3] = $39;
+ label = 42;
+ break;
+ case 48:
+ if ($cmp311) {
+ label = 49;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 49:
+ HEAPF64[$x75 >> 3] = $37;
+ label = 42;
+ break;
+ case 50:
+ HEAPF64[$x77 >> 3] = $36;
+ label = 42;
+ break;
+ case 51:
+ $sub348 = $41 - $40;
+ $sub353 = $43 - $42;
+ $cmp354 = $sub348 > $sub353;
+ $cmp361 = $41 < $43;
+ if ($cmp354) {
+ label = 52;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 52:
+ if ($cmp361) {
+ label = 53;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 53:
+ HEAPF64[$y102 >> 3] = $42;
+ label = 42;
+ break;
+ case 54:
+ HEAPF64[$y108 >> 3] = $43;
+ label = 42;
+ break;
+ case 55:
+ if ($cmp361) {
+ label = 56;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 56:
+ HEAPF64[$y81 >> 3] = $41;
+ label = 42;
+ break;
+ case 57:
+ HEAPF64[$y83 >> 3] = $40;
+ label = 42;
+ break;
+ case 58:
+ $x398 = $thepath | 0;
+ $44 = +HEAPF64[$x398 >> 3];
+ $45 = +HEAPF64[$x57 >> 3];
+ $cmp402 = $44 < $45;
+ if ($cmp402) {
+ label = 62;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ $46 = +HEAPF64[$x59 >> 3];
+ $cmp411 = $44 > $46;
+ if ($cmp411) {
+ label = 62;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $y416 = $thepath + 8 | 0;
+ $47 = +HEAPF64[$y416 >> 3];
+ $48 = +HEAPF64[$y62 >> 3];
+ $cmp420 = $47 < $48;
+ if ($cmp420) {
+ label = 62;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 61:
+ $49 = +HEAPF64[$y64 >> 3];
+ $cmp429 = $47 > $49;
+ if ($cmp429) {
+ label = 62;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 62:
+ $50 = HEAP8[164912] | 0;
+ $tobool432 = $50 << 24 >> 24 == 0;
+ if ($tobool432) {
+ label = 64;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ $51 = HEAP32[_stderr >> 2] | 0;
+ $52 = _fwrite(97888, 42, 1, $51 | 0) | 0;
+ _printpath($thepath);
+ label = 64;
+ break;
+ case 64:
+ $53 = +HEAPF64[$x398 >> 3];
+ $54 = +HEAPF64[$x57 >> 3];
+ $cmp442 = $53 < $54;
+ if ($cmp442) {
+ label = 65;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 65:
+ HEAPF64[$x398 >> 3] = $54;
+ label = 66;
+ break;
+ case 66:
+ $55 = +HEAPF64[$x398 >> 3];
+ $56 = +HEAPF64[$x59 >> 3];
+ $cmp458 = $55 > $56;
+ if ($cmp458) {
+ label = 67;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 67:
+ HEAPF64[$x398 >> 3] = $56;
+ label = 68;
+ break;
+ case 68:
+ $y470 = $thepath + 8 | 0;
+ $57 = +HEAPF64[$y470 >> 3];
+ $58 = +HEAPF64[$y62 >> 3];
+ $cmp474 = $57 < $58;
+ if ($cmp474) {
+ label = 69;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 69:
+ HEAPF64[$y470 >> 3] = $58;
+ label = 70;
+ break;
+ case 70:
+ $59 = +HEAPF64[$y470 >> 3];
+ $60 = +HEAPF64[$y64 >> 3];
+ $cmp490 = $59 > $60;
+ if ($cmp490) {
+ label = 71;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 71:
+ HEAPF64[$y470 >> 3] = $60;
+ label = 72;
+ break;
+ case 72:
+ $x502 = $thepath + 40 | 0;
+ $61 = +HEAPF64[$x502 >> 3];
+ $x506 = $boxes + ($sub69 << 5) | 0;
+ $62 = +HEAPF64[$x506 >> 3];
+ $cmp507 = $61 < $62;
+ if ($cmp507) {
+ label = 76;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $x516 = $boxes + ($sub69 << 5) + 16 | 0;
+ $63 = +HEAPF64[$x516 >> 3];
+ $cmp517 = $61 > $63;
+ if ($cmp517) {
+ label = 76;
+ break;
+ } else {
+ label = 74;
+ break;
+ }
+ case 74:
+ $y522 = $thepath + 48 | 0;
+ $64 = +HEAPF64[$y522 >> 3];
+ $y526 = $boxes + ($sub69 << 5) + 8 | 0;
+ $65 = +HEAPF64[$y526 >> 3];
+ $cmp527 = $64 < $65;
+ if ($cmp527) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $y536 = $boxes + ($sub69 << 5) + 24 | 0;
+ $66 = +HEAPF64[$y536 >> 3];
+ $cmp537 = $64 > $66;
+ if ($cmp537) {
+ label = 76;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 76:
+ $67 = HEAP8[164912] | 0;
+ $tobool540 = $67 << 24 >> 24 == 0;
+ if ($tobool540) {
+ label = 78;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 77:
+ $68 = HEAP32[_stderr >> 2] | 0;
+ $69 = _fwrite(94152, 39, 1, $68 | 0) | 0;
+ _printpath($thepath);
+ label = 78;
+ break;
+ case 78:
+ $70 = +HEAPF64[$x502 >> 3];
+ $71 = +HEAPF64[$x506 >> 3];
+ $cmp551 = $70 < $71;
+ if ($cmp551) {
+ label = 79;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 79:
+ HEAPF64[$x502 >> 3] = $71;
+ label = 80;
+ break;
+ case 80:
+ $72 = +HEAPF64[$x502 >> 3];
+ $x568 = $boxes + ($sub69 << 5) + 16 | 0;
+ $73 = +HEAPF64[$x568 >> 3];
+ $cmp569 = $72 > $73;
+ if ($cmp569) {
+ label = 81;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 81:
+ HEAPF64[$x502 >> 3] = $73;
+ label = 82;
+ break;
+ case 82:
+ $y582 = $thepath + 48 | 0;
+ $74 = +HEAPF64[$y582 >> 3];
+ $y586 = $boxes + ($sub69 << 5) + 8 | 0;
+ $75 = +HEAPF64[$y586 >> 3];
+ $cmp587 = $74 < $75;
+ if ($cmp587) {
+ label = 83;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 83:
+ HEAPF64[$y582 >> 3] = $75;
+ label = 84;
+ break;
+ case 84:
+ $76 = +HEAPF64[$y582 >> 3];
+ $y604 = $boxes + ($sub69 << 5) + 24 | 0;
+ $77 = +HEAPF64[$y604 >> 3];
+ $cmp605 = $76 > $77;
+ if ($cmp605) {
+ label = 85;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 85:
+ HEAPF64[$y582 >> 3] = $77;
+ label = 86;
+ break;
+ case 86:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _interpolate_pointf($agg_result, $t, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $t = +$t;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $0 = 0.0, $2 = 0.0, $add8 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $0 = +HEAPF64[$p >> 3];
+ $2 = +HEAPF64[$p + 8 >> 3];
+ $add8 = $2 + (+HEAPF64[$q + 8 >> 3] - $2) * $t;
+ HEAPF64[$agg_result >> 3] = $0 + (+HEAPF64[$q >> 3] - $0) * $t;
+ HEAPF64[$agg_result + 8 >> 3] = $add8;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _shapeOf($n) {
+ $n = $n | 0;
+ var $shape = 0, $0 = 0, $tobool = 0, $fns = 0, $1 = 0, $initfn = 0, $2 = 0, $cmp = 0, $cmp4 = 0, $cmp7 = 0, $cmp10 = 0, $_ = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $shape = $n + 24 | 0;
+ $0 = HEAP32[$shape >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $fns = $0 + 4 | 0;
+ $1 = HEAP32[$fns >> 2] | 0;
+ $initfn = $1 | 0;
+ $2 = HEAP32[$initfn >> 2] | 0;
+ $cmp = ($2 | 0) == 476;
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $cmp4 = ($2 | 0) == 66;
+ if ($cmp4) {
+ $retval_0 = 2;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp7 = ($2 | 0) == 62;
+ if ($cmp7) {
+ $retval_0 = 3;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp10 = ($2 | 0) == 632;
+ $_ = $cmp10 ? 4 : 0;
+ $retval_0 = $_;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _round_corners($job, $fillc, $penc, $AF, $sides, $style, $filled) {
+ $job = $job | 0;
+ $fillc = $fillc | 0;
+ $penc = $penc | 0;
+ $AF = $AF | 0;
+ $sides = $sides | 0;
+ $style = $style | 0;
+ $filled = $filled | 0;
+ var $C = 0, $p0 = 0, $p1 = 0, $tmp = 0, $tmp72 = 0, $tmp76 = 0, $tmp83 = 0, $and = 0, $tobool = 0, $and1 = 0, $tobool2 = 0, $_and1 = 0, $mode_0 = 0, $mul = 0, $mul7 = 0, $call = 0, $0 = 0, $cmp400 = 0, $1 = 0, $sub = 0, $2 = 0, $x = 0, $x15 = 0, $y = 0, $y17 = 0, $3 = 0, $4 = 0, $cmp26397 = 0, $5 = 0, $sub29 = 0, $6 = 0, $x37 = 0, $x38 = 0, $y40 = 0, $y41 = 0, $and48 = 0, $tobool49 = 0, $and53 = 0, $tobool54 = 0, $cmp59 = 0, $7 = 0, $8 = 0, $9 = 0, $10 = 0, $11 = 0, $12 = 0, $seg_0402 = 0, $rbconst_0401 = 0.0, $arrayidx = 0, $13 = 0, $cmp8 = 0, $add10 = 0, $arrayidx11 = 0, $14 = 0, $15 = 0.0, $16 = 0.0, $sub16 = 0.0, $17 = 0.0, $18 = 0.0, $sub18 = 0.0, $mul19 = 0.0, $mul20 = 0.0, $add21 = 0.0, $call22 = 0.0, $div = 0.0, $cmp23 = 0, $rbconst_0_div = 0.0, $inc = 0, $cmp = 0, $seg_1399 = 0, $i_0398 = 0, $arrayidx28 = 0, $19 = 0, $cmp30 = 0, $add32 = 0, $arrayidx33 = 0, $20 = 0, $21 = 0.0, $22 = 0.0, $sub39 = 0.0, $23 = 0.0, $24 = 0.0, $sub42 = 0.0, $mul43 = 0.0, $mul44 = 0.0, $add45 = 0.0, $call46 = 0.0, $div47 = 0.0, $div51 = 0.0, $div56 = 0.0, $t_0 = 0.0, $inc66 = 0, $arrayidx67 = 0, $25 = 0, $mul68 = 0.0, $26 = 0, $inc70 = 0, $arrayidx71 = 0, $27 = 0, $inc73 = 0, $arrayidx74 = 0, $sub75 = 0.0, $28 = 0, $inc79 = 0, $arrayidx80 = 0, $mul81 = 0.0, $sub82 = 0.0, $29 = 0, $i_3 = 0, $inc86 = 0, $cmp26 = 0, $i_0_lcssa = 0, $inc88 = 0, $arrayidx89 = 0, $30 = 0, $inc91 = 0, $arrayidx92 = 0, $arrayidx93 = 0, $31 = 0, $arrayidx95 = 0, $arrayidx96 = 0, $32 = 0, $tobool97 = 0, $mul101 = 0, $mul102 = 0, $call103 = 0, $33 = 0, $cmp105385 = 0, $j_0387 = 0, $seg_2386 = 0, $inc107379 = 0, $arrayidx108 = 0, $mul109 = 0, $add110377 = 0, $arrayidx111 = 0, $34 = 0, $35 = 0, $inc112 = 0, $arrayidx113 = 0, $add115378 = 0, $arrayidx116 = 0, $36 = 0, $37 = 0, $inc118 = 0, $cmp105 = 0, $cmp122383 = 0, $seg_3384 = 0, $mul124 = 0, $add_ptr_sum376 = 0, $add_ptr125 = 0, $inc127 = 0, $cmp122 = 0, $cmp131381 = 0, $seg_4382 = 0, $mul133 = 0, $add_ptr134_sum374 = 0, $add_ptr135 = 0, $add_ptr134_sum375 = 0, $add_ptr138 = 0, $inc140 = 0, $cmp131 = 0, $tobool143 = 0, $conv = 0, $cmp147389 = 0, $arrayidx150 = 0, $38 = 0, $arrayidx154 = 0, $39 = 0, $seg_5390 = 0, $mul151 = 0, $add152 = 0, $arrayidx153 = 0, $40 = 0, $add156 = 0, $arrayidx157 = 0, $41 = 0, $inc159 = 0, $cmp147 = 0, $tobool162 = 0, $add165 = 0, $mul166 = 0, $call167 = 0, $42 = 0, $cmp169391 = 0, $seg_6392 = 0, $arrayidx172 = 0, $arrayidx173 = 0, $43 = 0, $44 = 0, $inc175 = 0, $cmp169 = 0, $45 = 0, $add180 = 0, $arrayidx181 = 0, $46 = 0, $arrayidx182 = 0, $add185 = 0, $arrayidx186 = 0, $47 = 0, $48 = 0, $conv188 = 0, $arrayidx190 = 0, $49 = 0, $arrayidx194 = 0, $50 = 0, $x199 = 0, $51 = 0.0, $x201 = 0, $52 = 0.0, $x205 = 0, $53 = 0.0, $sub206 = 0.0, $add207 = 0.0, $arrayidx208 = 0, $x209 = 0, $y211 = 0, $54 = 0.0, $y213 = 0, $55 = 0.0, $y217 = 0, $56 = 0.0, $sub218 = 0.0, $add219 = 0.0, $y221 = 0, $57 = 0, $tobool228 = 0, $add231 = 0, $mul232 = 0, $call233 = 0, $58 = 0, $59 = 0, $arrayidx236 = 0, $x239 = 0, $60 = 0.0, $arrayidx240 = 0, $x241 = 0, $61 = 0.0, $arrayidx242 = 0, $x243 = 0, $62 = 0.0, $sub244 = 0.0, $div245 = 0.0, $add246 = 0.0, $arrayidx247 = 0, $x248 = 0, $y250 = 0, $63 = 0, $64 = 0.0, $y252 = 0, $65 = 0, $66 = 0.0, $y254 = 0, $67 = 0, $68 = 0.0, $sub255 = 0.0, $div256 = 0.0, $add257 = 0.0, $y259 = 0, $69 = 0, $70 = 0.0, $71 = 0.0, $sub266 = 0.0, $div267 = 0.0, $add268 = 0.0, $arrayidx269 = 0, $x270 = 0, $72 = 0.0, $73 = 0.0, $sub277 = 0.0, $div278 = 0.0, $add279 = 0.0, $y281 = 0, $74 = 0, $cmp284393 = 0, $seg_7394 = 0, $arrayidx287 = 0, $sub288 = 0, $arrayidx289 = 0, $75 = 0, $76 = 0, $inc291 = 0, $cmp284 = 0, $conv294 = 0, $arrayidx295 = 0, $77 = 0, $arrayidx297 = 0, $78 = 0, $tobool301 = 0, $add304 = 0, $mul305 = 0, $call306 = 0, $79 = 0, $80 = 0, $x310 = 0, $81 = 0.0, $x314 = 0, $82 = 0.0, $sub315 = 0.0, $div316 = 0.0, $sub317 = 0.0, $arrayidx318 = 0, $x319 = 0, $y321 = 0, $83 = 0.0, $arrayidx322 = 0, $y323 = 0, $84 = 0, $85 = 0.0, $y325 = 0, $86 = 0, $87 = 0.0, $sub326 = 0.0, $div327 = 0.0, $add328 = 0.0, $y330 = 0, $88 = 0, $89 = 0.0, $90 = 0.0, $sub337 = 0.0, $mul338 = 0.0, $sub339 = 0.0, $arrayidx340 = 0, $x341 = 0, $91 = 0.0, $y345 = 0, $92 = 0, $93 = 0.0, $94 = 0.0, $sub352 = 0.0, $mul353 = 0.0, $sub354 = 0.0, $arrayidx355 = 0, $x356 = 0, $95 = 0.0, $y360 = 0, $96 = 0, $x362 = 0, $97 = 0.0, $arrayidx363 = 0, $x364 = 0, $98 = 0.0, $y368 = 0, $99 = 0, $cmp371395 = 0, $seg_8396 = 0, $arrayidx374 = 0, $sub375 = 0, $arrayidx376 = 0, $100 = 0, $101 = 0, $inc378 = 0, $cmp371 = 0, $conv381 = 0, $cmp383 = 0, $tobool388 = 0, $add391 = 0, $mul392 = 0, $call393 = 0, $102 = 0, $103 = 0, $arrayidx396 = 0, $arrayidx398 = 0, $arrayidx399 = 0, $arrayidx400 = 0, $arrayidx401 = 0, $104 = 0, $arrayidx402 = 0, $arrayidx403 = 0, $arrayidx404 = 0, $arrayidx405 = 0, $conv407 = 0, $x409 = 0, $105 = 0.0, $arrayidx410 = 0, $x411 = 0, $106 = 0.0, $x413 = 0, $107 = 0.0, $sub414 = 0.0, $add415 = 0.0, $arrayidx416 = 0, $x417 = 0, $y419 = 0, $108 = 0, $109 = 0.0, $y421 = 0, $110 = 0, $111 = 0.0, $y423 = 0, $112 = 0, $113 = 0.0, $sub424 = 0.0, $add425 = 0.0, $y427 = 0, $arrayidx428 = 0, $114 = 0, $cmp438 = 0, $tobool443 = 0, $add446 = 0, $mul447 = 0, $call448 = 0, $115 = 0, $116 = 0, $arrayidx451 = 0, $arrayidx452 = 0, $117 = 0, $arrayidx453 = 0, $x454 = 0, $118 = 0.0, $arrayidx455 = 0, $x456 = 0, $119 = 0.0, $sub459 = 0.0, $add460 = 0.0, $arrayidx461 = 0, $x462 = 0, $y464 = 0, $120 = 0, $121 = 0.0, $y466 = 0, $122 = 0, $123 = 0.0, $sub469 = 0.0, $add470 = 0.0, $y472 = 0, $124 = 0, $125 = 0.0, $126 = 0.0, $x478 = 0, $127 = 0.0, $sub479 = 0.0, $add480 = 0.0, $arrayidx481 = 0, $x482 = 0, $128 = 0.0, $129 = 0.0, $y488 = 0, $130 = 0, $131 = 0.0, $sub489 = 0.0, $add490 = 0.0, $y492 = 0, $132 = 0, $133 = 0.0, $134 = 0.0, $135 = 0.0, $sub499 = 0.0, $add500 = 0.0, $arrayidx501 = 0, $x502 = 0, $136 = 0.0, $137 = 0.0, $138 = 0.0, $sub509 = 0.0, $add510 = 0.0, $y512 = 0, $139 = 0, $140 = 0.0, $141 = 0.0, $142 = 0.0, $sub519 = 0.0, $add520 = 0.0, $arrayidx521 = 0, $x522 = 0, $143 = 0.0, $144 = 0.0, $145 = 0.0, $sub529 = 0.0, $add530 = 0.0, $y532 = 0, $146 = 0, $arrayidx533 = 0, $x534 = 0, $147 = 0.0, $arrayidx535 = 0, $x536 = 0, $148 = 0.0, $sub539 = 0.0, $add540 = 0.0, $arrayidx541 = 0, $x542 = 0, $y544 = 0, $149 = 0, $150 = 0.0, $y546 = 0, $151 = 0, $152 = 0.0, $sub549 = 0.0, $add550 = 0.0, $y552 = 0, $153 = 0, $154 = 0.0, $155 = 0.0, $arrayidx557 = 0, $x558 = 0, $156 = 0.0, $sub559 = 0.0, $add560 = 0.0, $arrayidx561 = 0, $x562 = 0, $157 = 0.0, $158 = 0.0, $y568 = 0, $159 = 0, $160 = 0.0, $sub569 = 0.0, $add570 = 0.0, $y572 = 0, $161 = 0, $162 = 0.0, $163 = 0.0, $164 = 0.0, $sub579 = 0.0, $add580 = 0.0, $arrayidx581 = 0, $x582 = 0, $165 = 0.0, $166 = 0.0, $167 = 0.0, $sub589 = 0.0, $add590 = 0.0, $y592 = 0, $168 = 0, $169 = 0.0, $170 = 0.0, $171 = 0.0, $sub599 = 0.0, $add600 = 0.0, $arrayidx601 = 0, $x602 = 0, $172 = 0.0, $173 = 0.0, $174 = 0.0, $sub609 = 0.0, $add610 = 0.0, $y612 = 0, $175 = 0, $arrayidx613 = 0, $arrayidx614 = 0, $176 = 0, $arrayidx615 = 0, $arrayidx616 = 0, $177 = 0, $conv618 = 0, $arrayidx619 = 0, $178 = 0, $179 = 0.0, $180 = 0.0, $sub627 = 0.0, $sub628 = 0.0, $x630 = 0, $181 = 0.0, $182 = 0.0, $sub637 = 0.0, $sub638 = 0.0, $y640 = 0, $183 = 0.0, $184 = 0.0, $185 = 0.0, $sub647 = 0.0, $add648 = 0.0, $x650 = 0, $186 = 0.0, $187 = 0.0, $188 = 0.0, $sub657 = 0.0, $add658 = 0.0, $y660 = 0, $arrayidx661 = 0, $189 = 0, $190 = 0.0, $191 = 0.0, $sub672 = 0.0, $sub673 = 0.0, $192 = 0.0, $193 = 0.0, $sub682 = 0.0, $sub683 = 0.0, $194 = 0.0, $195 = 0.0, $196 = 0.0, $sub692 = 0.0, $add693 = 0.0, $197 = 0.0, $198 = 0.0, $199 = 0.0, $sub702 = 0.0, $add703 = 0.0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 160 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $C = __stackBase__ | 0;
+ $p0 = __stackBase__ + 64 | 0;
+ $p1 = __stackBase__ + 80 | 0;
+ $tmp = __stackBase__ + 96 | 0;
+ $tmp72 = __stackBase__ + 112 | 0;
+ $tmp76 = __stackBase__ + 128 | 0;
+ $tmp83 = __stackBase__ + 144 | 0;
+ $and = $style & 4;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $mode_0 = 4;
+ label = 4;
+ break;
+ }
+ case 3:
+ $and1 = $style & 992;
+ $tobool2 = ($and1 | 0) == 0;
+ $_and1 = $tobool2 ? 2 : $and1;
+ $mode_0 = $_and1;
+ label = 4;
+ break;
+ case 4:
+ $mul = $sides << 6;
+ $mul7 = $mul + 64 | 0;
+ $call = _zmalloc($mul7) | 0;
+ $0 = $call;
+ $cmp400 = ($sides | 0) > 0;
+ if ($cmp400) {
+ label = 5;
+ break;
+ } else {
+ $i_0_lcssa = 0;
+ label = 25;
+ break;
+ }
+ case 5:
+ $1 = $p0;
+ $sub = $sides - 1 | 0;
+ $2 = $p1;
+ $x = $p1 | 0;
+ $x15 = $p0 | 0;
+ $y = $p1 + 8 | 0;
+ $y17 = $p0 + 8 | 0;
+ $3 = $p1;
+ $4 = $AF;
+ $rbconst_0401 = 12.0;
+ $seg_0402 = 0;
+ label = 8;
+ break;
+ case 6:
+ $cmp26397 = ($sides | 0) > 0;
+ if ($cmp26397) {
+ label = 7;
+ break;
+ } else {
+ $i_0_lcssa = 0;
+ label = 25;
+ break;
+ }
+ case 7:
+ $5 = $p0;
+ $sub29 = $sides - 1 | 0;
+ $6 = $p1;
+ $x37 = $p1 | 0;
+ $x38 = $p0 | 0;
+ $y40 = $p1 + 8 | 0;
+ $y41 = $p0 + 8 | 0;
+ $and48 = $style & 768;
+ $tobool49 = ($and48 | 0) == 0;
+ $and53 = $style & 32;
+ $tobool54 = ($and53 | 0) == 0;
+ $cmp59 = ($mode_0 | 0) == 2;
+ $7 = $tmp;
+ $8 = $tmp72;
+ $9 = $tmp76;
+ $10 = $tmp83;
+ $11 = $p1;
+ $12 = $AF;
+ $i_0398 = 0;
+ $seg_1399 = 0;
+ label = 12;
+ break;
+ case 8:
+ $arrayidx = $AF + ($seg_0402 << 4) | 0;
+ $13 = $arrayidx;
+ HEAP32[$1 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ $cmp8 = ($seg_0402 | 0) < ($sub | 0);
+ if ($cmp8) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $add10 = $seg_0402 + 1 | 0;
+ $arrayidx11 = $AF + ($add10 << 4) | 0;
+ $14 = $arrayidx11;
+ HEAP32[$2 >> 2] = HEAP32[$14 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$14 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$14 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$14 + 12 >> 2] | 0;
+ label = 11;
+ break;
+ case 10:
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ label = 11;
+ break;
+ case 11:
+ $15 = +HEAPF64[$x >> 3];
+ $16 = +HEAPF64[$x15 >> 3];
+ $sub16 = $15 - $16;
+ $17 = +HEAPF64[$y >> 3];
+ $18 = +HEAPF64[$y17 >> 3];
+ $sub18 = $17 - $18;
+ $mul19 = $sub16 * $sub16;
+ $mul20 = $sub18 * $sub18;
+ $add21 = $mul19 + $mul20;
+ $call22 = +Math_sqrt(+$add21);
+ $div = $call22 / 3.0;
+ $cmp23 = $rbconst_0401 < $div;
+ $rbconst_0_div = $cmp23 ? $rbconst_0401 : $div;
+ $inc = $seg_0402 + 1 | 0;
+ $cmp = ($inc | 0) < ($sides | 0);
+ if ($cmp) {
+ $rbconst_0401 = $rbconst_0_div;
+ $seg_0402 = $inc;
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 12:
+ $arrayidx28 = $AF + ($seg_1399 << 4) | 0;
+ $19 = $arrayidx28;
+ HEAP32[$5 >> 2] = HEAP32[$19 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$19 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$19 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$19 + 12 >> 2] | 0;
+ $cmp30 = ($seg_1399 | 0) < ($sub29 | 0);
+ if ($cmp30) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $add32 = $seg_1399 + 1 | 0;
+ $arrayidx33 = $AF + ($add32 << 4) | 0;
+ $20 = $arrayidx33;
+ HEAP32[$6 >> 2] = HEAP32[$20 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$20 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$20 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$20 + 12 >> 2] | 0;
+ label = 15;
+ break;
+ case 14:
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ label = 15;
+ break;
+ case 15:
+ $21 = +HEAPF64[$x37 >> 3];
+ $22 = +HEAPF64[$x38 >> 3];
+ $sub39 = $21 - $22;
+ $23 = +HEAPF64[$y40 >> 3];
+ $24 = +HEAPF64[$y41 >> 3];
+ $sub42 = $23 - $24;
+ $mul43 = $sub39 * $sub39;
+ $mul44 = $sub42 * $sub42;
+ $add45 = $mul43 + $mul44;
+ $call46 = +Math_sqrt(+$add45);
+ $div47 = $rbconst_0_div / $call46;
+ if ($tobool49) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $div51 = $div47 / 3.0;
+ $t_0 = $div51;
+ label = 19;
+ break;
+ case 17:
+ if ($tobool54) {
+ $t_0 = $div47;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $div56 = $div47 * .5;
+ $t_0 = $div56;
+ label = 19;
+ break;
+ case 19:
+ $inc66 = $i_0398 + 1 | 0;
+ $arrayidx67 = $0 + ($i_0398 << 4) | 0;
+ if ($cmp59) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $25 = $arrayidx67;
+ HEAP32[$25 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$25 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$25 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$25 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ label = 22;
+ break;
+ case 21:
+ $mul68 = $t_0 * .5;
+ _interpolate_pointf($tmp, $mul68, $p0, $p1);
+ $26 = $arrayidx67;
+ HEAP32[$26 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$26 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$26 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$26 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ label = 22;
+ break;
+ case 22:
+ $inc70 = $i_0398 + 2 | 0;
+ $arrayidx71 = $0 + ($inc66 << 4) | 0;
+ _interpolate_pointf($tmp72, $t_0, $p0, $p1);
+ $27 = $arrayidx71;
+ HEAP32[$27 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$27 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$27 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$27 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $inc73 = $i_0398 + 3 | 0;
+ $arrayidx74 = $0 + ($inc70 << 4) | 0;
+ $sub75 = 1.0 - $t_0;
+ _interpolate_pointf($tmp76, $sub75, $p0, $p1);
+ $28 = $arrayidx74;
+ HEAP32[$28 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$28 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$28 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$28 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ if ($cmp59) {
+ label = 23;
+ break;
+ } else {
+ $i_3 = $inc73;
+ label = 24;
+ break;
+ }
+ case 23:
+ $inc79 = $i_0398 + 4 | 0;
+ $arrayidx80 = $0 + ($inc73 << 4) | 0;
+ $mul81 = $t_0 * .5;
+ $sub82 = 1.0 - $mul81;
+ _interpolate_pointf($tmp83, $sub82, $p0, $p1);
+ $29 = $arrayidx80;
+ HEAP32[$29 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$29 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$29 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$29 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $i_3 = $inc79;
+ label = 24;
+ break;
+ case 24:
+ $inc86 = $seg_1399 + 1 | 0;
+ $cmp26 = ($inc86 | 0) < ($sides | 0);
+ if ($cmp26) {
+ $i_0398 = $i_3;
+ $seg_1399 = $inc86;
+ label = 12;
+ break;
+ } else {
+ $i_0_lcssa = $i_3;
+ label = 25;
+ break;
+ }
+ case 25:
+ $inc88 = $i_0_lcssa + 1 | 0;
+ $arrayidx89 = $0 + ($i_0_lcssa << 4) | 0;
+ $30 = $arrayidx89;
+ HEAP32[$30 >> 2] = HEAP32[$call >> 2] | 0;
+ HEAP32[$30 + 4 >> 2] = HEAP32[$call + 4 >> 2] | 0;
+ HEAP32[$30 + 8 >> 2] = HEAP32[$call + 8 >> 2] | 0;
+ HEAP32[$30 + 12 >> 2] = HEAP32[$call + 12 >> 2] | 0;
+ $inc91 = $i_0_lcssa + 2 | 0;
+ $arrayidx92 = $0 + ($inc88 << 4) | 0;
+ $arrayidx93 = $call + 16 | 0;
+ $31 = $arrayidx92;
+ HEAP32[$31 >> 2] = HEAP32[$arrayidx93 >> 2] | 0;
+ HEAP32[$31 + 4 >> 2] = HEAP32[$arrayidx93 + 4 >> 2] | 0;
+ HEAP32[$31 + 8 >> 2] = HEAP32[$arrayidx93 + 8 >> 2] | 0;
+ HEAP32[$31 + 12 >> 2] = HEAP32[$arrayidx93 + 12 >> 2] | 0;
+ $arrayidx95 = $0 + ($inc91 << 4) | 0;
+ $arrayidx96 = $call + 32 | 0;
+ $32 = $arrayidx95;
+ HEAP32[$32 >> 2] = HEAP32[$arrayidx96 >> 2] | 0;
+ HEAP32[$32 + 4 >> 2] = HEAP32[$arrayidx96 + 4 >> 2] | 0;
+ HEAP32[$32 + 8 >> 2] = HEAP32[$arrayidx96 + 8 >> 2] | 0;
+ HEAP32[$32 + 12 >> 2] = HEAP32[$arrayidx96 + 12 >> 2] | 0;
+ if (($mode_0 | 0) == 2) {
+ label = 26;
+ break;
+ } else if (($mode_0 | 0) == 4) {
+ label = 34;
+ break;
+ } else if (($mode_0 | 0) == 32) {
+ label = 39;
+ break;
+ } else if (($mode_0 | 0) == 64) {
+ label = 44;
+ break;
+ } else if (($mode_0 | 0) == 128) {
+ label = 49;
+ break;
+ } else if (($mode_0 | 0) == 256) {
+ label = 54;
+ break;
+ } else if (($mode_0 | 0) == 512) {
+ label = 59;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 26:
+ $tobool97 = ($filled | 0) == 0;
+ if ($tobool97) {
+ label = 32;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $mul101 = $sides << 1;
+ $mul102 = $sides << 5;
+ $call103 = _gmalloc($mul102) | 0;
+ $33 = $call103;
+ _gvrender_set_pencolor($job, $fillc);
+ _gvrender_set_fillcolor($job, $fillc);
+ $cmp105385 = ($sides | 0) > 0;
+ if ($cmp105385) {
+ $seg_2386 = 0;
+ $j_0387 = 0;
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ $inc107379 = $j_0387 | 1;
+ $arrayidx108 = $33 + ($j_0387 << 4) | 0;
+ $mul109 = $seg_2386 << 2;
+ $add110377 = $mul109 | 1;
+ $arrayidx111 = $0 + ($add110377 << 4) | 0;
+ $34 = $arrayidx108;
+ $35 = $arrayidx111;
+ HEAP32[$34 >> 2] = HEAP32[$35 >> 2] | 0;
+ HEAP32[$34 + 4 >> 2] = HEAP32[$35 + 4 >> 2] | 0;
+ HEAP32[$34 + 8 >> 2] = HEAP32[$35 + 8 >> 2] | 0;
+ HEAP32[$34 + 12 >> 2] = HEAP32[$35 + 12 >> 2] | 0;
+ $inc112 = $j_0387 + 2 | 0;
+ $arrayidx113 = $33 + ($inc107379 << 4) | 0;
+ $add115378 = $mul109 | 2;
+ $arrayidx116 = $0 + ($add115378 << 4) | 0;
+ $36 = $arrayidx113;
+ $37 = $arrayidx116;
+ HEAP32[$36 >> 2] = HEAP32[$37 >> 2] | 0;
+ HEAP32[$36 + 4 >> 2] = HEAP32[$37 + 4 >> 2] | 0;
+ HEAP32[$36 + 8 >> 2] = HEAP32[$37 + 8 >> 2] | 0;
+ HEAP32[$36 + 12 >> 2] = HEAP32[$37 + 12 >> 2] | 0;
+ $inc118 = $seg_2386 + 1 | 0;
+ $cmp105 = ($inc118 | 0) < ($sides | 0);
+ if ($cmp105) {
+ $seg_2386 = $inc118;
+ $j_0387 = $inc112;
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ _gvrender_polygon($job, $33, $mul101, 1);
+ _free($call103);
+ $cmp122383 = ($sides | 0) > 0;
+ if ($cmp122383) {
+ $seg_3384 = 0;
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ _gvrender_set_pencolor($job, $penc);
+ label = 64;
+ break;
+ case 31:
+ $mul124 = $seg_3384 << 2;
+ $add_ptr_sum376 = $mul124 | 2;
+ $add_ptr125 = $0 + ($add_ptr_sum376 << 4) | 0;
+ _gvrender_beziercurve($job, $add_ptr125, 4, 0, 0, 1);
+ $inc127 = $seg_3384 + 1 | 0;
+ $cmp122 = ($inc127 | 0) < ($sides | 0);
+ if ($cmp122) {
+ $seg_3384 = $inc127;
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ _gvrender_set_pencolor($job, $penc);
+ $cmp131381 = ($sides | 0) > 0;
+ if ($cmp131381) {
+ $seg_4382 = 0;
+ label = 33;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 33:
+ $mul133 = $seg_4382 << 2;
+ $add_ptr134_sum374 = $mul133 | 1;
+ $add_ptr135 = $0 + ($add_ptr134_sum374 << 4) | 0;
+ _gvrender_polyline($job, $add_ptr135, 2);
+ $add_ptr134_sum375 = $mul133 | 2;
+ $add_ptr138 = $0 + ($add_ptr134_sum375 << 4) | 0;
+ _gvrender_beziercurve($job, $add_ptr138, 4, 0, 0, 0);
+ $inc140 = $seg_4382 + 1 | 0;
+ $cmp131 = ($inc140 | 0) < ($sides | 0);
+ if ($cmp131) {
+ $seg_4382 = $inc140;
+ label = 33;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 34:
+ _gvrender_set_pencolor($job, $penc);
+ $tobool143 = ($filled | 0) == 0;
+ if ($tobool143) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ _gvrender_set_fillcolor($job, $fillc);
+ label = 36;
+ break;
+ case 36:
+ $conv = $filled & 255;
+ _gvrender_polygon($job, $AF, $sides, $conv);
+ $cmp147389 = ($sides | 0) > 0;
+ if ($cmp147389) {
+ label = 37;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 37:
+ $arrayidx150 = $C | 0;
+ $38 = $C;
+ $arrayidx154 = $C + 16 | 0;
+ $39 = $arrayidx154;
+ $seg_5390 = 0;
+ label = 38;
+ break;
+ case 38:
+ $mul151 = $seg_5390 * 3 & -1;
+ $add152 = $mul151 + 2 | 0;
+ $arrayidx153 = $0 + ($add152 << 4) | 0;
+ $40 = $arrayidx153;
+ HEAP32[$38 >> 2] = HEAP32[$40 >> 2] | 0;
+ HEAP32[$38 + 4 >> 2] = HEAP32[$40 + 4 >> 2] | 0;
+ HEAP32[$38 + 8 >> 2] = HEAP32[$40 + 8 >> 2] | 0;
+ HEAP32[$38 + 12 >> 2] = HEAP32[$40 + 12 >> 2] | 0;
+ $add156 = $mul151 + 4 | 0;
+ $arrayidx157 = $0 + ($add156 << 4) | 0;
+ $41 = $arrayidx157;
+ HEAP32[$39 >> 2] = HEAP32[$41 >> 2] | 0;
+ HEAP32[$39 + 4 >> 2] = HEAP32[$41 + 4 >> 2] | 0;
+ HEAP32[$39 + 8 >> 2] = HEAP32[$41 + 8 >> 2] | 0;
+ HEAP32[$39 + 12 >> 2] = HEAP32[$41 + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx150, 2);
+ $inc159 = $seg_5390 + 1 | 0;
+ $cmp147 = ($inc159 | 0) < ($sides | 0);
+ if ($cmp147) {
+ $seg_5390 = $inc159;
+ label = 38;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 39:
+ _gvrender_set_pencolor($job, $penc);
+ $tobool162 = ($filled | 0) == 0;
+ if ($tobool162) {
+ label = 41;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ _gvrender_set_fillcolor($job, $fillc);
+ label = 41;
+ break;
+ case 41:
+ $add165 = $sides + 1 | 0;
+ $mul166 = $add165 << 4;
+ $call167 = _zmalloc($mul166) | 0;
+ $42 = $call167;
+ $cmp169391 = ($sides | 0) > 1;
+ if ($cmp169391) {
+ $seg_6392 = 1;
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ $arrayidx172 = $42 + ($seg_6392 << 4) | 0;
+ $arrayidx173 = $AF + ($seg_6392 << 4) | 0;
+ $43 = $arrayidx172;
+ $44 = $arrayidx173;
+ HEAP32[$43 >> 2] = HEAP32[$44 >> 2] | 0;
+ HEAP32[$43 + 4 >> 2] = HEAP32[$44 + 4 >> 2] | 0;
+ HEAP32[$43 + 8 >> 2] = HEAP32[$44 + 8 >> 2] | 0;
+ HEAP32[$43 + 12 >> 2] = HEAP32[$44 + 12 >> 2] | 0;
+ $inc175 = $seg_6392 + 1 | 0;
+ $cmp169 = ($inc175 | 0) < ($sides | 0);
+ if ($cmp169) {
+ $seg_6392 = $inc175;
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $45 = $sides * 3 & -1;
+ $add180 = $45 + 1 | 0;
+ $arrayidx181 = $0 + ($add180 << 4) | 0;
+ $46 = $arrayidx181;
+ HEAP32[$call167 >> 2] = HEAP32[$46 >> 2] | 0;
+ HEAP32[$call167 + 4 >> 2] = HEAP32[$46 + 4 >> 2] | 0;
+ HEAP32[$call167 + 8 >> 2] = HEAP32[$46 + 8 >> 2] | 0;
+ HEAP32[$call167 + 12 >> 2] = HEAP32[$46 + 12 >> 2] | 0;
+ $arrayidx182 = $42 + ($sides << 4) | 0;
+ $add185 = $45 - 1 | 0;
+ $arrayidx186 = $0 + ($add185 << 4) | 0;
+ $47 = $arrayidx182;
+ $48 = $arrayidx186;
+ HEAP32[$47 >> 2] = HEAP32[$48 >> 2] | 0;
+ HEAP32[$47 + 4 >> 2] = HEAP32[$48 + 4 >> 2] | 0;
+ HEAP32[$47 + 8 >> 2] = HEAP32[$48 + 8 >> 2] | 0;
+ HEAP32[$47 + 12 >> 2] = HEAP32[$48 + 12 >> 2] | 0;
+ $conv188 = $filled & 255;
+ _gvrender_polygon($job, $42, $add165, $conv188);
+ _free($call167);
+ $arrayidx190 = $C | 0;
+ $49 = $C;
+ HEAP32[$49 >> 2] = HEAP32[$48 >> 2] | 0;
+ HEAP32[$49 + 4 >> 2] = HEAP32[$48 + 4 >> 2] | 0;
+ HEAP32[$49 + 8 >> 2] = HEAP32[$48 + 8 >> 2] | 0;
+ HEAP32[$49 + 12 >> 2] = HEAP32[$48 + 12 >> 2] | 0;
+ $arrayidx194 = $C + 16 | 0;
+ $50 = $arrayidx194;
+ HEAP32[$50 >> 2] = HEAP32[$46 >> 2] | 0;
+ HEAP32[$50 + 4 >> 2] = HEAP32[$46 + 4 >> 2] | 0;
+ HEAP32[$50 + 8 >> 2] = HEAP32[$46 + 8 >> 2] | 0;
+ HEAP32[$50 + 12 >> 2] = HEAP32[$46 + 12 >> 2] | 0;
+ $x199 = $arrayidx194 | 0;
+ $51 = +HEAPF64[$x199 >> 3];
+ $x201 = $C | 0;
+ $52 = +HEAPF64[$x201 >> 3];
+ $x205 = $0 + ($45 << 4) | 0;
+ $53 = +HEAPF64[$x205 >> 3];
+ $sub206 = $52 - $53;
+ $add207 = $51 + $sub206;
+ $arrayidx208 = $C + 32 | 0;
+ $x209 = $arrayidx208 | 0;
+ HEAPF64[$x209 >> 3] = $add207;
+ $y211 = $C + 24 | 0;
+ $54 = +HEAPF64[$y211 >> 3];
+ $y213 = $C + 8 | 0;
+ $55 = +HEAPF64[$y213 >> 3];
+ $y217 = $0 + ($45 << 4) + 8 | 0;
+ $56 = +HEAPF64[$y217 >> 3];
+ $sub218 = $55 - $56;
+ $add219 = $54 + $sub218;
+ $y221 = $C + 40 | 0;
+ HEAPF64[$y221 >> 3] = $add219;
+ _gvrender_polyline($job, $arrayidx194, 2);
+ $57 = $arrayidx208;
+ HEAP32[$50 >> 2] = HEAP32[$57 >> 2] | 0;
+ HEAP32[$50 + 4 >> 2] = HEAP32[$57 + 4 >> 2] | 0;
+ HEAP32[$50 + 8 >> 2] = HEAP32[$57 + 8 >> 2] | 0;
+ HEAP32[$50 + 12 >> 2] = HEAP32[$57 + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx190, 2);
+ label = 64;
+ break;
+ case 44:
+ _gvrender_set_pencolor($job, $penc);
+ $tobool228 = ($filled | 0) == 0;
+ if ($tobool228) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ _gvrender_set_fillcolor($job, $fillc);
+ label = 46;
+ break;
+ case 46:
+ $add231 = $sides + 2 | 0;
+ $mul232 = $add231 << 4;
+ $call233 = _zmalloc($mul232) | 0;
+ $58 = $call233;
+ $59 = $AF;
+ HEAP32[$call233 >> 2] = HEAP32[$59 >> 2] | 0;
+ HEAP32[$call233 + 4 >> 2] = HEAP32[$59 + 4 >> 2] | 0;
+ HEAP32[$call233 + 8 >> 2] = HEAP32[$59 + 8 >> 2] | 0;
+ HEAP32[$call233 + 12 >> 2] = HEAP32[$59 + 12 >> 2] | 0;
+ $arrayidx236 = $call233 + 16 | 0;
+ HEAP32[$arrayidx236 >> 2] = HEAP32[$arrayidx96 >> 2] | 0;
+ HEAP32[$arrayidx236 + 4 >> 2] = HEAP32[$arrayidx96 + 4 >> 2] | 0;
+ HEAP32[$arrayidx236 + 8 >> 2] = HEAP32[$arrayidx96 + 8 >> 2] | 0;
+ HEAP32[$arrayidx236 + 12 >> 2] = HEAP32[$arrayidx96 + 12 >> 2] | 0;
+ $x239 = $arrayidx96;
+ $60 = +HEAPF64[$x239 >> 3];
+ $arrayidx240 = $call + 48 | 0;
+ $x241 = $arrayidx240;
+ $61 = +HEAPF64[$x241 >> 3];
+ $arrayidx242 = $call + 64 | 0;
+ $x243 = $arrayidx242;
+ $62 = +HEAPF64[$x243 >> 3];
+ $sub244 = $61 - $62;
+ $div245 = $sub244 / 3.0;
+ $add246 = $60 + $div245;
+ $arrayidx247 = $call233 + 32 | 0;
+ $x248 = $arrayidx247;
+ HEAPF64[$x248 >> 3] = $add246;
+ $y250 = $call + 40 | 0;
+ $63 = $y250;
+ $64 = +HEAPF64[$63 >> 3];
+ $y252 = $call + 56 | 0;
+ $65 = $y252;
+ $66 = +HEAPF64[$65 >> 3];
+ $y254 = $call + 72 | 0;
+ $67 = $y254;
+ $68 = +HEAPF64[$67 >> 3];
+ $sub255 = $66 - $68;
+ $div256 = $sub255 / 3.0;
+ $add257 = $64 + $div256;
+ $y259 = $call233 + 40 | 0;
+ $69 = $y259;
+ HEAPF64[$69 >> 3] = $add257;
+ $70 = +HEAPF64[$x241 >> 3];
+ $71 = +HEAPF64[$x243 >> 3];
+ $sub266 = $70 - $71;
+ $div267 = $sub266 / 3.0;
+ $add268 = $70 + $div267;
+ $arrayidx269 = $call233 + 48 | 0;
+ $x270 = $arrayidx269;
+ HEAPF64[$x270 >> 3] = $add268;
+ $72 = +HEAPF64[$65 >> 3];
+ $73 = +HEAPF64[$67 >> 3];
+ $sub277 = $72 - $73;
+ $div278 = $sub277 / 3.0;
+ $add279 = $72 + $div278;
+ $y281 = $call233 + 56 | 0;
+ $74 = $y281;
+ HEAPF64[$74 >> 3] = $add279;
+ $cmp284393 = ($add231 | 0) > 4;
+ if ($cmp284393) {
+ $seg_7394 = 4;
+ label = 47;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 47:
+ $arrayidx287 = $58 + ($seg_7394 << 4) | 0;
+ $sub288 = $seg_7394 - 2 | 0;
+ $arrayidx289 = $AF + ($sub288 << 4) | 0;
+ $75 = $arrayidx287;
+ $76 = $arrayidx289;
+ HEAP32[$75 >> 2] = HEAP32[$76 >> 2] | 0;
+ HEAP32[$75 + 4 >> 2] = HEAP32[$76 + 4 >> 2] | 0;
+ HEAP32[$75 + 8 >> 2] = HEAP32[$76 + 8 >> 2] | 0;
+ HEAP32[$75 + 12 >> 2] = HEAP32[$76 + 12 >> 2] | 0;
+ $inc291 = $seg_7394 + 1 | 0;
+ $cmp284 = ($inc291 | 0) < ($add231 | 0);
+ if ($cmp284) {
+ $seg_7394 = $inc291;
+ label = 47;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $conv294 = $filled & 255;
+ _gvrender_polygon($job, $58, $add231, $conv294);
+ _free($call233);
+ $arrayidx295 = $C | 0;
+ $77 = $C;
+ HEAP32[$77 >> 2] = HEAP32[$arrayidx240 >> 2] | 0;
+ HEAP32[$77 + 4 >> 2] = HEAP32[$arrayidx240 + 4 >> 2] | 0;
+ HEAP32[$77 + 8 >> 2] = HEAP32[$arrayidx240 + 8 >> 2] | 0;
+ HEAP32[$77 + 12 >> 2] = HEAP32[$arrayidx240 + 12 >> 2] | 0;
+ $arrayidx297 = $C + 16 | 0;
+ $78 = $arrayidx297;
+ HEAP32[$78 >> 2] = HEAP32[$arrayidx96 >> 2] | 0;
+ HEAP32[$78 + 4 >> 2] = HEAP32[$arrayidx96 + 4 >> 2] | 0;
+ HEAP32[$78 + 8 >> 2] = HEAP32[$arrayidx96 + 8 >> 2] | 0;
+ HEAP32[$78 + 12 >> 2] = HEAP32[$arrayidx96 + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx295, 2);
+ label = 64;
+ break;
+ case 49:
+ _gvrender_set_pencolor($job, $penc);
+ $tobool301 = ($filled | 0) == 0;
+ if ($tobool301) {
+ label = 51;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ _gvrender_set_fillcolor($job, $fillc);
+ label = 51;
+ break;
+ case 51:
+ $add304 = $sides + 3 | 0;
+ $mul305 = $add304 << 4;
+ $call306 = _zmalloc($mul305) | 0;
+ $79 = $call306;
+ $80 = $AF;
+ HEAP32[$call306 >> 2] = HEAP32[$80 >> 2] | 0;
+ HEAP32[$call306 + 4 >> 2] = HEAP32[$80 + 4 >> 2] | 0;
+ HEAP32[$call306 + 8 >> 2] = HEAP32[$80 + 8 >> 2] | 0;
+ HEAP32[$call306 + 12 >> 2] = HEAP32[$80 + 12 >> 2] | 0;
+ $x310 = $AF | 0;
+ $81 = +HEAPF64[$x310 >> 3];
+ $x314 = $arrayidx93;
+ $82 = +HEAPF64[$x314 >> 3];
+ $sub315 = $81 - $82;
+ $div316 = $sub315 * .25;
+ $sub317 = $81 - $div316;
+ $arrayidx318 = $call306 + 16 | 0;
+ $x319 = $arrayidx318;
+ HEAPF64[$x319 >> 3] = $sub317;
+ $y321 = $AF + 8 | 0;
+ $83 = +HEAPF64[$y321 >> 3];
+ $arrayidx322 = $call + 48 | 0;
+ $y323 = $call + 56 | 0;
+ $84 = $y323;
+ $85 = +HEAPF64[$84 >> 3];
+ $y325 = $call + 72 | 0;
+ $86 = $y325;
+ $87 = +HEAPF64[$86 >> 3];
+ $sub326 = $85 - $87;
+ $div327 = $sub326 / 3.0;
+ $add328 = $83 + $div327;
+ $y330 = $call306 + 24 | 0;
+ $88 = $y330;
+ HEAPF64[$88 >> 3] = $add328;
+ $89 = +HEAPF64[$x310 >> 3];
+ $90 = +HEAPF64[$x314 >> 3];
+ $sub337 = $89 - $90;
+ $mul338 = $sub337 * 2.0;
+ $sub339 = $89 - $mul338;
+ $arrayidx340 = $call306 + 32 | 0;
+ $x341 = $arrayidx340;
+ HEAPF64[$x341 >> 3] = $sub339;
+ $91 = +HEAPF64[$88 >> 3];
+ $y345 = $call306 + 40 | 0;
+ $92 = $y345;
+ HEAPF64[$92 >> 3] = $91;
+ $93 = +HEAPF64[$x310 >> 3];
+ $94 = +HEAPF64[$x314 >> 3];
+ $sub352 = $93 - $94;
+ $mul353 = $sub352 * 2.25;
+ $sub354 = $93 - $mul353;
+ $arrayidx355 = $call306 + 48 | 0;
+ $x356 = $arrayidx355;
+ HEAPF64[$x356 >> 3] = $sub354;
+ $95 = +HEAPF64[$84 >> 3];
+ $y360 = $call306 + 56 | 0;
+ $96 = $y360;
+ HEAPF64[$96 >> 3] = $95;
+ $x362 = $arrayidx322;
+ $97 = +HEAPF64[$x362 >> 3];
+ $arrayidx363 = $call306 + 64 | 0;
+ $x364 = $arrayidx363;
+ HEAPF64[$x364 >> 3] = $97;
+ $98 = +HEAPF64[$84 >> 3];
+ $y368 = $call306 + 72 | 0;
+ $99 = $y368;
+ HEAPF64[$99 >> 3] = $98;
+ $cmp371395 = ($add304 | 0) > 4;
+ if ($cmp371395) {
+ $seg_8396 = 4;
+ label = 52;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 52:
+ $arrayidx374 = $79 + ($seg_8396 << 4) | 0;
+ $sub375 = $seg_8396 - 3 | 0;
+ $arrayidx376 = $AF + ($sub375 << 4) | 0;
+ $100 = $arrayidx374;
+ $101 = $arrayidx376;
+ HEAP32[$100 >> 2] = HEAP32[$101 >> 2] | 0;
+ HEAP32[$100 + 4 >> 2] = HEAP32[$101 + 4 >> 2] | 0;
+ HEAP32[$100 + 8 >> 2] = HEAP32[$101 + 8 >> 2] | 0;
+ HEAP32[$100 + 12 >> 2] = HEAP32[$101 + 12 >> 2] | 0;
+ $inc378 = $seg_8396 + 1 | 0;
+ $cmp371 = ($inc378 | 0) < ($add304 | 0);
+ if ($cmp371) {
+ $seg_8396 = $inc378;
+ label = 52;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $conv381 = $filled & 255;
+ _gvrender_polygon($job, $79, $add304, $conv381);
+ _free($call306);
+ label = 64;
+ break;
+ case 54:
+ $cmp383 = ($sides | 0) == 4;
+ if ($cmp383) {
+ label = 56;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ ___assert_func(100480, 562, 163904, 139704);
+ case 56:
+ _gvrender_set_pencolor($job, $penc);
+ $tobool388 = ($filled | 0) == 0;
+ if ($tobool388) {
+ label = 58;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ _gvrender_set_fillcolor($job, $fillc);
+ label = 58;
+ break;
+ case 58:
+ $add391 = $sides + 2 | 0;
+ $mul392 = $add391 << 4;
+ $call393 = _zmalloc($mul392) | 0;
+ $102 = $call393;
+ $103 = $AF;
+ HEAP32[$call393 >> 2] = HEAP32[$103 >> 2] | 0;
+ HEAP32[$call393 + 4 >> 2] = HEAP32[$103 + 4 >> 2] | 0;
+ HEAP32[$call393 + 8 >> 2] = HEAP32[$103 + 8 >> 2] | 0;
+ HEAP32[$call393 + 12 >> 2] = HEAP32[$103 + 12 >> 2] | 0;
+ $arrayidx396 = $call393 + 16 | 0;
+ HEAP32[$arrayidx396 >> 2] = HEAP32[$arrayidx96 >> 2] | 0;
+ HEAP32[$arrayidx396 + 4 >> 2] = HEAP32[$arrayidx96 + 4 >> 2] | 0;
+ HEAP32[$arrayidx396 + 8 >> 2] = HEAP32[$arrayidx96 + 8 >> 2] | 0;
+ HEAP32[$arrayidx396 + 12 >> 2] = HEAP32[$arrayidx96 + 12 >> 2] | 0;
+ $arrayidx398 = $call393 + 32 | 0;
+ $arrayidx399 = $call + 64 | 0;
+ HEAP32[$arrayidx398 >> 2] = HEAP32[$arrayidx399 >> 2] | 0;
+ HEAP32[$arrayidx398 + 4 >> 2] = HEAP32[$arrayidx399 + 4 >> 2] | 0;
+ HEAP32[$arrayidx398 + 8 >> 2] = HEAP32[$arrayidx399 + 8 >> 2] | 0;
+ HEAP32[$arrayidx398 + 12 >> 2] = HEAP32[$arrayidx399 + 12 >> 2] | 0;
+ $arrayidx400 = $call393 + 48 | 0;
+ $arrayidx401 = $AF + 32 | 0;
+ $104 = $arrayidx401;
+ HEAP32[$arrayidx400 >> 2] = HEAP32[$104 >> 2] | 0;
+ HEAP32[$arrayidx400 + 4 >> 2] = HEAP32[$104 + 4 >> 2] | 0;
+ HEAP32[$arrayidx400 + 8 >> 2] = HEAP32[$104 + 8 >> 2] | 0;
+ HEAP32[$arrayidx400 + 12 >> 2] = HEAP32[$104 + 12 >> 2] | 0;
+ $arrayidx402 = $call393 + 64 | 0;
+ $arrayidx403 = $call + 128 | 0;
+ HEAP32[$arrayidx402 >> 2] = HEAP32[$arrayidx403 >> 2] | 0;
+ HEAP32[$arrayidx402 + 4 >> 2] = HEAP32[$arrayidx403 + 4 >> 2] | 0;
+ HEAP32[$arrayidx402 + 8 >> 2] = HEAP32[$arrayidx403 + 8 >> 2] | 0;
+ HEAP32[$arrayidx402 + 12 >> 2] = HEAP32[$arrayidx403 + 12 >> 2] | 0;
+ $arrayidx404 = $call393 + 80 | 0;
+ $arrayidx405 = $call + 160 | 0;
+ HEAP32[$arrayidx404 >> 2] = HEAP32[$arrayidx405 >> 2] | 0;
+ HEAP32[$arrayidx404 + 4 >> 2] = HEAP32[$arrayidx405 + 4 >> 2] | 0;
+ HEAP32[$arrayidx404 + 8 >> 2] = HEAP32[$arrayidx405 + 8 >> 2] | 0;
+ HEAP32[$arrayidx404 + 12 >> 2] = HEAP32[$arrayidx405 + 12 >> 2] | 0;
+ $conv407 = $filled & 255;
+ _gvrender_polygon($job, $102, $add391, $conv407);
+ _free($call393);
+ $x409 = $arrayidx93;
+ $105 = +HEAPF64[$x409 >> 3];
+ $arrayidx410 = $call + 176 | 0;
+ $x411 = $arrayidx410;
+ $106 = +HEAPF64[$x411 >> 3];
+ $x413 = $call;
+ $107 = +HEAPF64[$x413 >> 3];
+ $sub414 = $106 - $107;
+ $add415 = $105 + $sub414;
+ $arrayidx416 = $C | 0;
+ $x417 = $C | 0;
+ HEAPF64[$x417 >> 3] = $add415;
+ $y419 = $call + 24 | 0;
+ $108 = $y419;
+ $109 = +HEAPF64[$108 >> 3];
+ $y421 = $call + 184 | 0;
+ $110 = $y421;
+ $111 = +HEAPF64[$110 >> 3];
+ $y423 = $call + 8 | 0;
+ $112 = $y423;
+ $113 = +HEAPF64[$112 >> 3];
+ $sub424 = $111 - $113;
+ $add425 = $109 + $sub424;
+ $y427 = $C + 8 | 0;
+ HEAPF64[$y427 >> 3] = $add425;
+ $arrayidx428 = $C + 16 | 0;
+ $114 = $arrayidx428;
+ HEAP32[$114 >> 2] = HEAP32[$arrayidx399 >> 2] | 0;
+ HEAP32[$114 + 4 >> 2] = HEAP32[$arrayidx399 + 4 >> 2] | 0;
+ HEAP32[$114 + 8 >> 2] = HEAP32[$arrayidx399 + 8 >> 2] | 0;
+ HEAP32[$114 + 12 >> 2] = HEAP32[$arrayidx399 + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx416, 2);
+ HEAP32[$114 >> 2] = HEAP32[$arrayidx403 >> 2] | 0;
+ HEAP32[$114 + 4 >> 2] = HEAP32[$arrayidx403 + 4 >> 2] | 0;
+ HEAP32[$114 + 8 >> 2] = HEAP32[$arrayidx403 + 8 >> 2] | 0;
+ HEAP32[$114 + 12 >> 2] = HEAP32[$arrayidx403 + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx416, 2);
+ HEAP32[$114 >> 2] = HEAP32[$call >> 2] | 0;
+ HEAP32[$114 + 4 >> 2] = HEAP32[$call + 4 >> 2] | 0;
+ HEAP32[$114 + 8 >> 2] = HEAP32[$call + 8 >> 2] | 0;
+ HEAP32[$114 + 12 >> 2] = HEAP32[$call + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx416, 2);
+ label = 64;
+ break;
+ case 59:
+ $cmp438 = ($sides | 0) == 4;
+ if ($cmp438) {
+ label = 61;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ ___assert_func(100480, 588, 163904, 139704);
+ case 61:
+ _gvrender_set_pencolor($job, $penc);
+ $tobool443 = ($filled | 0) == 0;
+ if ($tobool443) {
+ label = 63;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 62:
+ _gvrender_set_fillcolor($job, $fillc);
+ label = 63;
+ break;
+ case 63:
+ $add446 = $sides + 8 | 0;
+ $mul447 = $add446 << 4;
+ $call448 = _zmalloc($mul447) | 0;
+ $115 = $call448;
+ $116 = $AF;
+ HEAP32[$call448 >> 2] = HEAP32[$116 >> 2] | 0;
+ HEAP32[$call448 + 4 >> 2] = HEAP32[$116 + 4 >> 2] | 0;
+ HEAP32[$call448 + 8 >> 2] = HEAP32[$116 + 8 >> 2] | 0;
+ HEAP32[$call448 + 12 >> 2] = HEAP32[$116 + 12 >> 2] | 0;
+ $arrayidx451 = $call448 + 16 | 0;
+ $arrayidx452 = $AF + 16 | 0;
+ $117 = $arrayidx452;
+ HEAP32[$arrayidx451 >> 2] = HEAP32[$117 >> 2] | 0;
+ HEAP32[$arrayidx451 + 4 >> 2] = HEAP32[$117 + 4 >> 2] | 0;
+ HEAP32[$arrayidx451 + 8 >> 2] = HEAP32[$117 + 8 >> 2] | 0;
+ HEAP32[$arrayidx451 + 12 >> 2] = HEAP32[$117 + 12 >> 2] | 0;
+ $arrayidx453 = $call + 48 | 0;
+ $x454 = $arrayidx453;
+ $118 = +HEAPF64[$x454 >> 3];
+ $arrayidx455 = $call + 64 | 0;
+ $x456 = $arrayidx455;
+ $119 = +HEAPF64[$x456 >> 3];
+ $sub459 = $119 - $118;
+ $add460 = $118 + $sub459;
+ $arrayidx461 = $call448 + 32 | 0;
+ $x462 = $arrayidx461;
+ HEAPF64[$x462 >> 3] = $add460;
+ $y464 = $call + 56 | 0;
+ $120 = $y464;
+ $121 = +HEAPF64[$120 >> 3];
+ $y466 = $call + 72 | 0;
+ $122 = $y466;
+ $123 = +HEAPF64[$122 >> 3];
+ $sub469 = $123 - $121;
+ $add470 = $121 + $sub469;
+ $y472 = $call448 + 40 | 0;
+ $124 = $y472;
+ HEAPF64[$124 >> 3] = $add470;
+ $125 = +HEAPF64[$x462 >> 3];
+ $126 = +HEAPF64[$x454 >> 3];
+ $x478 = $arrayidx96;
+ $127 = +HEAPF64[$x478 >> 3];
+ $sub479 = $126 - $127;
+ $add480 = $125 + $sub479;
+ $arrayidx481 = $call448 + 48 | 0;
+ $x482 = $arrayidx481;
+ HEAPF64[$x482 >> 3] = $add480;
+ $128 = +HEAPF64[$124 >> 3];
+ $129 = +HEAPF64[$120 >> 3];
+ $y488 = $call + 40 | 0;
+ $130 = $y488;
+ $131 = +HEAPF64[$130 >> 3];
+ $sub489 = $129 - $131;
+ $add490 = $128 + $sub489;
+ $y492 = $call448 + 56 | 0;
+ $132 = $y492;
+ HEAPF64[$132 >> 3] = $add490;
+ $133 = +HEAPF64[$x482 >> 3];
+ $134 = +HEAPF64[$x456 >> 3];
+ $135 = +HEAPF64[$x454 >> 3];
+ $sub499 = $134 - $135;
+ $add500 = $133 + $sub499;
+ $arrayidx501 = $call448 + 64 | 0;
+ $x502 = $arrayidx501;
+ HEAPF64[$x502 >> 3] = $add500;
+ $136 = +HEAPF64[$132 >> 3];
+ $137 = +HEAPF64[$122 >> 3];
+ $138 = +HEAPF64[$120 >> 3];
+ $sub509 = $137 - $138;
+ $add510 = $136 + $sub509;
+ $y512 = $call448 + 72 | 0;
+ $139 = $y512;
+ HEAPF64[$139 >> 3] = $add510;
+ $140 = +HEAPF64[$x502 >> 3];
+ $141 = +HEAPF64[$x462 >> 3];
+ $142 = +HEAPF64[$x482 >> 3];
+ $sub519 = $141 - $142;
+ $add520 = $140 + $sub519;
+ $arrayidx521 = $call448 + 80 | 0;
+ $x522 = $arrayidx521;
+ HEAPF64[$x522 >> 3] = $add520;
+ $143 = +HEAPF64[$139 >> 3];
+ $144 = +HEAPF64[$124 >> 3];
+ $145 = +HEAPF64[$132 >> 3];
+ $sub529 = $144 - $145;
+ $add530 = $143 + $sub529;
+ $y532 = $call448 + 88 | 0;
+ $146 = $y532;
+ HEAPF64[$146 >> 3] = $add530;
+ $arrayidx533 = $call + 96 | 0;
+ $x534 = $arrayidx533;
+ $147 = +HEAPF64[$x534 >> 3];
+ $arrayidx535 = $call + 80 | 0;
+ $x536 = $arrayidx535;
+ $148 = +HEAPF64[$x536 >> 3];
+ $sub539 = $148 - $147;
+ $add540 = $147 + $sub539;
+ $arrayidx541 = $call448 + 144 | 0;
+ $x542 = $arrayidx541;
+ HEAPF64[$x542 >> 3] = $add540;
+ $y544 = $call + 104 | 0;
+ $149 = $y544;
+ $150 = +HEAPF64[$149 >> 3];
+ $y546 = $call + 88 | 0;
+ $151 = $y546;
+ $152 = +HEAPF64[$151 >> 3];
+ $sub549 = $152 - $150;
+ $add550 = $150 + $sub549;
+ $y552 = $call448 + 152 | 0;
+ $153 = $y552;
+ HEAPF64[$153 >> 3] = $add550;
+ $154 = +HEAPF64[$x542 >> 3];
+ $155 = +HEAPF64[$x534 >> 3];
+ $arrayidx557 = $call + 112 | 0;
+ $x558 = $arrayidx557;
+ $156 = +HEAPF64[$x558 >> 3];
+ $sub559 = $155 - $156;
+ $add560 = $154 + $sub559;
+ $arrayidx561 = $call448 + 128 | 0;
+ $x562 = $arrayidx561;
+ HEAPF64[$x562 >> 3] = $add560;
+ $157 = +HEAPF64[$153 >> 3];
+ $158 = +HEAPF64[$149 >> 3];
+ $y568 = $call + 120 | 0;
+ $159 = $y568;
+ $160 = +HEAPF64[$159 >> 3];
+ $sub569 = $158 - $160;
+ $add570 = $157 + $sub569;
+ $y572 = $call448 + 136 | 0;
+ $161 = $y572;
+ HEAPF64[$161 >> 3] = $add570;
+ $162 = +HEAPF64[$x562 >> 3];
+ $163 = +HEAPF64[$x536 >> 3];
+ $164 = +HEAPF64[$x534 >> 3];
+ $sub579 = $163 - $164;
+ $add580 = $162 + $sub579;
+ $arrayidx581 = $call448 + 112 | 0;
+ $x582 = $arrayidx581;
+ HEAPF64[$x582 >> 3] = $add580;
+ $165 = +HEAPF64[$161 >> 3];
+ $166 = +HEAPF64[$151 >> 3];
+ $167 = +HEAPF64[$149 >> 3];
+ $sub589 = $166 - $167;
+ $add590 = $165 + $sub589;
+ $y592 = $call448 + 120 | 0;
+ $168 = $y592;
+ HEAPF64[$168 >> 3] = $add590;
+ $169 = +HEAPF64[$x582 >> 3];
+ $170 = +HEAPF64[$x542 >> 3];
+ $171 = +HEAPF64[$x562 >> 3];
+ $sub599 = $170 - $171;
+ $add600 = $169 + $sub599;
+ $arrayidx601 = $call448 + 96 | 0;
+ $x602 = $arrayidx601;
+ HEAPF64[$x602 >> 3] = $add600;
+ $172 = +HEAPF64[$168 >> 3];
+ $173 = +HEAPF64[$153 >> 3];
+ $174 = +HEAPF64[$161 >> 3];
+ $sub609 = $173 - $174;
+ $add610 = $172 + $sub609;
+ $y612 = $call448 + 104 | 0;
+ $175 = $y612;
+ HEAPF64[$175 >> 3] = $add610;
+ $arrayidx613 = $call448 + 160 | 0;
+ $arrayidx614 = $AF + 32 | 0;
+ $176 = $arrayidx614;
+ HEAP32[$arrayidx613 >> 2] = HEAP32[$176 >> 2] | 0;
+ HEAP32[$arrayidx613 + 4 >> 2] = HEAP32[$176 + 4 >> 2] | 0;
+ HEAP32[$arrayidx613 + 8 >> 2] = HEAP32[$176 + 8 >> 2] | 0;
+ HEAP32[$arrayidx613 + 12 >> 2] = HEAP32[$176 + 12 >> 2] | 0;
+ $arrayidx615 = $call448 + 176 | 0;
+ $arrayidx616 = $AF + 48 | 0;
+ $177 = $arrayidx616;
+ HEAP32[$arrayidx615 >> 2] = HEAP32[$177 >> 2] | 0;
+ HEAP32[$arrayidx615 + 4 >> 2] = HEAP32[$177 + 4 >> 2] | 0;
+ HEAP32[$arrayidx615 + 8 >> 2] = HEAP32[$177 + 8 >> 2] | 0;
+ HEAP32[$arrayidx615 + 12 >> 2] = HEAP32[$177 + 12 >> 2] | 0;
+ $conv618 = $filled & 255;
+ _gvrender_polygon($job, $115, $add446, $conv618);
+ $arrayidx619 = $C | 0;
+ $178 = $C;
+ HEAP32[$178 >> 2] = HEAP32[$arrayidx461 >> 2] | 0;
+ HEAP32[$178 + 4 >> 2] = HEAP32[$arrayidx461 + 4 >> 2] | 0;
+ HEAP32[$178 + 8 >> 2] = HEAP32[$arrayidx461 + 8 >> 2] | 0;
+ HEAP32[$178 + 12 >> 2] = HEAP32[$arrayidx461 + 12 >> 2] | 0;
+ $179 = +HEAPF64[$x462 >> 3];
+ $180 = +HEAPF64[$x482 >> 3];
+ $sub627 = $180 - $179;
+ $sub628 = $179 - $sub627;
+ $x630 = $C + 16 | 0;
+ HEAPF64[$x630 >> 3] = $sub628;
+ $181 = +HEAPF64[$124 >> 3];
+ $182 = +HEAPF64[$132 >> 3];
+ $sub637 = $182 - $181;
+ $sub638 = $181 - $sub637;
+ $y640 = $C + 24 | 0;
+ HEAPF64[$y640 >> 3] = $sub638;
+ $183 = +HEAPF64[$x630 >> 3];
+ $184 = +HEAPF64[$x502 >> 3];
+ $185 = +HEAPF64[$x482 >> 3];
+ $sub647 = $184 - $185;
+ $add648 = $183 + $sub647;
+ $x650 = $C + 32 | 0;
+ HEAPF64[$x650 >> 3] = $add648;
+ $186 = +HEAPF64[$y640 >> 3];
+ $187 = +HEAPF64[$139 >> 3];
+ $188 = +HEAPF64[$132 >> 3];
+ $sub657 = $187 - $188;
+ $add658 = $186 + $sub657;
+ $y660 = $C + 40 | 0;
+ HEAPF64[$y660 >> 3] = $add658;
+ $arrayidx661 = $C + 48 | 0;
+ $189 = $arrayidx661;
+ HEAP32[$189 >> 2] = HEAP32[$arrayidx521 >> 2] | 0;
+ HEAP32[$189 + 4 >> 2] = HEAP32[$arrayidx521 + 4 >> 2] | 0;
+ HEAP32[$189 + 8 >> 2] = HEAP32[$arrayidx521 + 8 >> 2] | 0;
+ HEAP32[$189 + 12 >> 2] = HEAP32[$arrayidx521 + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx619, 4);
+ HEAP32[$178 >> 2] = HEAP32[$arrayidx601 >> 2] | 0;
+ HEAP32[$178 + 4 >> 2] = HEAP32[$arrayidx601 + 4 >> 2] | 0;
+ HEAP32[$178 + 8 >> 2] = HEAP32[$arrayidx601 + 8 >> 2] | 0;
+ HEAP32[$178 + 12 >> 2] = HEAP32[$arrayidx601 + 12 >> 2] | 0;
+ $190 = +HEAPF64[$x602 >> 3];
+ $191 = +HEAPF64[$x582 >> 3];
+ $sub672 = $191 - $190;
+ $sub673 = $190 - $sub672;
+ HEAPF64[$x630 >> 3] = $sub673;
+ $192 = +HEAPF64[$175 >> 3];
+ $193 = +HEAPF64[$168 >> 3];
+ $sub682 = $193 - $192;
+ $sub683 = $192 - $sub682;
+ HEAPF64[$y640 >> 3] = $sub683;
+ $194 = +HEAPF64[$x630 >> 3];
+ $195 = +HEAPF64[$x562 >> 3];
+ $196 = +HEAPF64[$x582 >> 3];
+ $sub692 = $195 - $196;
+ $add693 = $194 + $sub692;
+ HEAPF64[$x650 >> 3] = $add693;
+ $197 = +HEAPF64[$y640 >> 3];
+ $198 = +HEAPF64[$161 >> 3];
+ $199 = +HEAPF64[$168 >> 3];
+ $sub702 = $198 - $199;
+ $add703 = $197 + $sub702;
+ HEAPF64[$y660 >> 3] = $add703;
+ HEAP32[$189 >> 2] = HEAP32[$arrayidx541 >> 2] | 0;
+ HEAP32[$189 + 4 >> 2] = HEAP32[$arrayidx541 + 4 >> 2] | 0;
+ HEAP32[$189 + 8 >> 2] = HEAP32[$arrayidx541 + 8 >> 2] | 0;
+ HEAP32[$189 + 12 >> 2] = HEAP32[$arrayidx541 + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx619, 4);
+ _free($call448);
+ label = 64;
+ break;
+ case 64:
+ _free($call);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _poly_init($n) {
+ $n = $n | 0;
+ var $marginx = 0, $marginy = 0, $tmp = 0, $tmp321 = 0, $call = 0, $shape = 0, $0 = 0, $polygon = 0, $1 = 0, $regular1 = 0, $2 = 0, $peripheries5 = 0, $3 = 0, $sides9 = 0, $4 = 0, $orientation13 = 0, $5 = 0.0, $skew17 = 0, $6 = 0.0, $distortion21 = 0, $7 = 0.0, $8 = 0, $call22 = 0, $call23 = 0, $conv = 0, $or = 0, $tobool = 0, $call24 = 0.0, $cmp = 0, $width28 = 0, $9 = 0.0, $height30 = 0, $10 = 0.0, $cmp31 = 0, $cond = 0.0, $mul = 0.0, $cmp33 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv43 = 0, $conv55 = 0.0, $width58 = 0, $11 = 0.0, $mul59 = 0.0, $cmp60 = 0, $add66 = 0.0, $sub72 = 0.0, $add66_sink = 0.0, $conv67 = 0, $conv76 = 0.0, $height78 = 0, $12 = 0.0, $mul79 = 0.0, $cmp80 = 0, $add86 = 0.0, $sub92 = 0.0, $add86_sink = 0.0, $conv87 = 0, $conv96 = 0.0, $width_0 = 0.0, $height_0 = 0.0, $13 = 0, $call98 = 0, $14 = 0, $call99 = 0.0, $add100 = 0.0, $cmp101 = 0, $15 = 0, $call104 = 0.0, $16 = 0, $call105 = 0, $17 = 0, $call106 = 0.0, $distortion_0 = 0.0, $skew_0 = 0.0, $sides_0 = 0, $label = 0, $18 = 0, $dimen_sroa_0_0__idx = 0, $dimen_sroa_0_0_copyload = 0.0, $dimen_sroa_1_8__idx336 = 0, $dimen_sroa_1_8_copyload = 0.0, $conv110 = 0, $ispos = 0, $neg = 0, $call111 = 0, $cmp112 = 0, $ispos389 = 0, $neg390 = 0, $call117 = 0, $conv118 = 0.0, $add119 = 0.0, $conv120 = 0, $tobool121 = 0, $sub127 = 0.0, $conv128 = 0, $tobool129 = 0, $conv130 = 0, $ispos391 = 0, $neg392 = 0, $call131 = 0, $cmp132 = 0, $ispos393 = 0, $neg394 = 0, $call137 = 0, $conv138 = 0.0, $add139 = 0.0, $conv140 = 0, $tobool141 = 0, $sub147 = 0.0, $conv148 = 0, $tobool149 = 0, $call151 = 0, $tobool152 = 0, $call154 = 0, $19 = 0.0, $cmp155 = 0, $20 = 0.0, $cmp159 = 0, $cmp163 = 0, $21 = 0.0, $mul166 = 0.0, $cmp167 = 0, $add171 = 0.0, $sub175 = 0.0, $add171_sink = 0.0, $conv172 = 0, $mul179 = 0, $conv180 = 0.0, $add182 = 0.0, $cmp183 = 0, $22 = 0.0, $mul186 = 0.0, $cmp187 = 0, $add191 = 0.0, $sub195 = 0.0, $add191_sink = 0.0, $conv192 = 0, $mul199 = 0, $conv200 = 0.0, $add202 = 0.0, $23 = 0.0, $mul204 = 0.0, $cmp205 = 0, $add209 = 0.0, $sub213 = 0.0, $add209_sink = 0.0, $conv210 = 0, $mul217 = 0, $conv218 = 0.0, $add220 = 0.0, $add224 = 0.0, $add226 = 0.0, $add230 = 0.0, $add232 = 0.0, $dimen_sroa_0_0 = 0.0, $dimen_sroa_1_0 = 0.0, $24 = 0, $x239 = 0, $25 = 0.0, $sub240 = 0.0, $graph = 0, $26 = 0, $drawing = 0, $27 = 0, $quantum = 0, $28 = 0.0, $cmp242 = 0, $mul245 = 0.0, $cmp246 = 0, $add250 = 0.0, $sub254 = 0.0, $add250_sink = 0.0, $conv251 = 0, $conv258 = 0.0, $call260 = 0.0, $call263 = 0.0, $dimen_sroa_0_1 = 0.0, $dimen_sroa_1_1 = 0.0, $29 = 0, $usershape = 0, $30 = 0, $tobool270 = 0, $name = 0, $31 = 0, $32 = 0, $cmp276 = 0, $call281 = 0, $tobool282 = 0, $call284 = 0, $33 = 0, $imagesize_sroa_0_0__idx262 = 0, $imagesize_sroa_0_0_copyload263 = 0, $imagesize_sroa_1_4__idx272 = 0, $imagesize_sroa_1_4_copyload273 = 0, $cmp287 = 0, $cmp291 = 0, $or_cond = 0, $tobool294 = 0, $cond298 = 0, $name299 = 0, $34 = 0, $call300 = 0, $35 = 0, $has_images = 0, $add307 = 0, $add309 = 0, $call313 = 0, $tobool314 = 0, $36 = 0, $cmp317 = 0, $37 = 0, $imagesize_sroa_0_0__idx = 0, $imagesize_sroa_0_0_copyload = 0, $imagesize_sroa_1_4__idx269 = 0, $imagesize_sroa_1_4_copyload = 0, $cmp323 = 0, $cmp327 = 0, $or_cond385 = 0, $cond334 = 0, $name335 = 0, $38 = 0, $call336 = 0, $39 = 0, $has_images342 = 0, $add344 = 0, $add346 = 0, $imagesize_sroa_0_0 = 0, $imagesize_sroa_1_0 = 0, $conv352 = 0.0, $cmp353 = 0, $dimen_sroa_0_1_conv352 = 0.0, $conv365 = 0.0, $cmp366 = 0, $cond374 = 0.0, $cmp376 = 0, $cmp379 = 0, $cmp382 = 0, $or_cond386 = 0, $_sides_0 = 0, $sides_1 = 0, $call386 = 0, $tobool387 = 0, $40 = 0, $41 = 0, $42 = 0, $valign = 0, $43 = 0, $valign404 = 0, $cmp406 = 0, $cmp409 = 0, $add412 = 0.0, $sub415 = 0.0, $add412_sink = 0.0, $conv413 = 0, $rem = 0, $cmp419 = 0, $cmp422 = 0, $or_cond387 = 0, $cmp424 = 0, $or_cond395 = 0, $mul430 = 0.0, $cmp431 = 0, $44 = 0, $valign436 = 0, $45 = 0, $cmp438 = 0, $div = 0.0, $mul444 = 0.0, $sub445 = 0.0, $div446 = 0.0, $call447 = 0.0, $call447_pn = 0.0, $bb_sroa_1_0 = 0.0, $bb_sroa_0_0 = 0.0, $cmp455 = 0, $conv458 = 0.0, $div459 = 0.0, $call460 = 0.0, $div462 = 0.0, $div464 = 0.0, $46 = 0, $bb_sroa_0_1 = 0.0, $bb_sroa_1_1 = 0.0, $47 = 0, $call467 = 0, $call468 = 0, $tobool469 = 0, $cmp472 = 0, $cmp476 = 0, $or_cond388 = 0, $name479 = 0, $48 = 0, $49 = 0, $name481 = 0, $50 = 0, $call482 = 0, $cmp488 = 0, $width_0_bb_sroa_0_1 = 0.0, $cmp497 = 0, $cond503 = 0.0, $width_1 = 0.0, $height_1 = 0.0, $cmp510 = 0, $width_1_height_1 = 0.0, $width_2 = 0.0, $height_2 = 0.0, $51 = 0, $call521 = 0, $call522 = 0, $tobool523 = 0, $cmp529 = 0, $dimen_sroa_0_1_width_2 = 0.0, $sub537 = 0.0, $52 = 0, $x540 = 0, $cmp544 = 0, $mul550 = 0.0, $mul553 = 0.0, $div554 = 0.0, $sub555 = 0.0, $call556 = 0.0, $mul557 = 0.0, $cmp559 = 0, $dimen_sroa_0_1_mul557 = 0.0, $sub566 = 0.0, $53 = 0, $x570 = 0, $sub573 = 0.0, $54 = 0, $x577 = 0, $sub582 = 0.0, $55 = 0, $x586 = 0, $sub590 = 0.0, $cmp594 = 0, $sub600 = 0.0, $add601 = 0.0, $temp_0 = 0.0, $add604 = 0.0, $56 = 0, $y608 = 0, $cmp609 = 0, $_call98 = 0, $cmp613 = 0, $mul617 = 0, $call618 = 0, $57 = 0, $div620 = 0.0, $div623 = 0.0, $sub626 = 0.0, $x628 = 0, $sub630 = 0.0, $y632 = 0, $58 = 0, $P_sroa_0_0__idx229 = 0, $59 = 0, $P_sroa_1_8__idx254 = 0, $60 = 0, $cmp634 = 0, $j_0400 = 0, $i_0399 = 0, $P_sroa_1_0398 = 0.0, $P_sroa_0_0397 = 0.0, $add640 = 0.0, $add642 = 0.0, $sub644 = 0.0, $x646 = 0, $sub648 = 0.0, $y650 = 0, $inc384 = 0, $x653 = 0, $y656 = 0, $inc657 = 0, $inc658 = 0, $cmp637 = 0, $mul660 = 0.0, $mul663 = 0.0, $mul667 = 0, $mul668 = 0, $call669 = 0, $61 = 0, $conv670 = 0.0, $div671 = 0.0, $div672 = 0.0, $call673 = 0.0, $call674 = 0.0, $call675 = 0.0, $add676 = 0.0, $call677 = 0.0, $mul678 = 0.0, $call680 = 0.0, $div681 = 0.0, $div682 = 0.0, $sub683 = 0.0, $div684 = 0.0, $call685 = 0.0, $call686 = 0.0, $mul687 = 0.0, $mul689 = 0.0, $sub691 = 0.0, $div692 = 0.0, $add693 = 0.0, $div718 = 0.0, $mul719 = 0.0, $R_sroa_0_0 = 0.0, $R_sroa_1_0 = 0.0, $angle_0 = 0.0, $xmax_0 = 0.0, $ymax_0 = 0.0, $i_1 = 0, $cmp695 = 0, $add698 = 0.0, $call699 = 0.0, $call700 = 0.0, $mul701 = 0.0, $add703 = 0.0, $mul704 = 0.0, $add706 = 0.0, $mul709 = 0.0, $add710 = 0.0, $mul711 = 0.0, $mul713 = 0.0, $add714 = 0.0, $call722 = 0.0, $add723 = 0.0, $call724 = 0.0, $call725 = 0.0, $call728 = 0.0, $mul732 = 0.0, $mul734 = 0.0, $mul737 = 0.0, $mul740 = 0.0, $call742 = 0.0, $cmp743 = 0, $call742_xmax_0 = 0.0, $call752 = 0.0, $cmp753 = 0, $cond760 = 0.0, $P_sroa_0_0__idx218 = 0, $P_sroa_1_8__idx242 = 0, $inc788 = 0, $sub765 = 0.0, $arrayidx766 = 0, $x767 = 0, $y770 = 0, $62 = 0, $arrayidx773 = 0, $x774 = 0, $sub776 = 0.0, $y778 = 0, $63 = 0, $arrayidx780 = 0, $x781 = 0, $y785 = 0, $64 = 0, $xmax_1 = 0.0, $ymax_1 = 0.0, $mul790 = 0.0, $mul791 = 0.0, $cmp792 = 0, $cond797 = 0.0, $cmp799 = 0, $cond804 = 0.0, $div807 = 0.0, $div809 = 0.0, $cmp811417 = 0, $i_2418 = 0, $P_sroa_0_0__idx213 = 0, $P_sroa_0_0_copyload214 = 0.0, $P_sroa_1_8__idx237 = 0, $P_sroa_1_8_copyload238 = 0.0, $mul816 = 0.0, $mul818 = 0.0, $inc821 = 0, $cmp811 = 0, $cmp823 = 0, $sub826 = 0, $R_sroa_0_0__idx182 = 0, $R_sroa_0_0_copyload183 = 0.0, $R_sroa_1_8__idx190 = 0, $65 = 0, $R_sroa_1_8_copyload191 = 0.0, $cmp837412 = 0, $Q_sroa_1_8__idx207 = 0, $Q_sroa_0_0__idx200 = 0, $Q_sroa_1_8_copyload208 = 0.0, $Q_sroa_0_0_copyload201 = 0.0, $sub834 = 0.0, $sub831 = 0.0, $call835 = 0.0, $cmp862408 = 0, $cmp837 = 0, $cmp879402 = 0, $sub882 = 0, $mul883 = 0, $i_3416 = 0, $R_sroa_1_1415 = 0.0, $R_sroa_0_1414 = 0.0, $beta_0413 = 0.0, $add840 = 0, $66 = 0, $tmp421 = 0, $R_sroa_0_0__idx = 0, $R_sroa_0_0_copyload = 0.0, $R_sroa_1_8__idx186 = 0, $R_sroa_1_8_copyload = 0.0, $sub845 = 0.0, $sub848 = 0.0, $call849 = 0.0, $add850 = 0.0, $sub851 = 0.0, $div852 = 0.0, $call853 = 0.0, $div854 = 0.0, $sub855 = 0.0, $call856 = 0.0, $call858 = 0.0, $mul859 = 0.0, $mul860 = 0.0, $j_1411 = 0, $Q_sroa_1_1410 = 0.0, $Q_sroa_0_1409 = 0.0, $add866 = 0.0, $add868 = 0.0, $mul869 = 0, $add870 = 0, $Q_sroa_0_0__idx = 0, $Q_sroa_1_8__idx202 = 0, $inc873 = 0, $cmp862 = 0, $bb_sroa_1_4405 = 0.0, $i_4404 = 0, $bb_sroa_0_4403 = 0.0, $add884 = 0, $P_sroa_0_0__idx = 0, $P_sroa_0_0_copyload = 0.0, $P_sroa_1_8__idx233 = 0, $P_sroa_1_8_copyload = 0.0, $call887 = 0.0, $mul888 = 0.0, $cmp890 = 0, $mul888_bb_sroa_0_4 = 0.0, $call902 = 0.0, $mul903 = 0.0, $cmp905 = 0, $cond914 = 0.0, $inc917 = 0, $cmp879 = 0, $vertices_0 = 0, $bb_sroa_0_5 = 0.0, $sides_2 = 0, $bb_sroa_1_5 = 0.0, $regular921 = 0, $peripheries922 = 0, $67 = 0, $sides923 = 0, $68 = 0, $orientation924 = 0, $69 = 0, $skew925 = 0, $70 = 0, $distortion926 = 0, $71 = 0, $vertices927 = 0, $72 = 0, $div929 = 0.0, $width931 = 0, $div933 = 0.0, $height935 = 0, $shape_info = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $marginx = __stackBase__ | 0;
+ $marginy = __stackBase__ + 8 | 0;
+ $tmp = __stackBase__ + 16 | 0;
+ $tmp321 = __stackBase__ + 24 | 0;
+ $call = _zmalloc(48) | 0;
+ $shape = $n + 24 | 0;
+ $0 = HEAP32[$shape >> 2] | 0;
+ $polygon = $0 + 8 | 0;
+ $1 = HEAP32[$polygon >> 2] | 0;
+ $regular1 = $1 | 0;
+ $2 = HEAP32[$regular1 >> 2] | 0;
+ $peripheries5 = $1 + 4 | 0;
+ $3 = HEAP32[$peripheries5 >> 2] | 0;
+ $sides9 = $1 + 8 | 0;
+ $4 = HEAP32[$sides9 >> 2] | 0;
+ $orientation13 = $1 + 16 | 0;
+ $5 = +HEAPF64[$orientation13 >> 3];
+ $skew17 = $1 + 32 | 0;
+ $6 = +HEAPF64[$skew17 >> 3];
+ $distortion21 = $1 + 24 | 0;
+ $7 = +HEAPF64[$distortion21 >> 3];
+ $8 = $n | 0;
+ $call22 = _agget($8, 98792) | 0;
+ $call23 = _mapbool($call22) | 0;
+ $conv = $call23 & 255;
+ $or = $conv | $2;
+ $tobool = ($or | 0) != 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $call24 = +_userSize($n);
+ $cmp = $call24 > 0.0;
+ if ($cmp) {
+ $height_0 = $call24;
+ $width_0 = $call24;
+ label = 15;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $width28 = $n + 48 | 0;
+ $9 = +HEAPF64[$width28 >> 3];
+ $height30 = $n + 56 | 0;
+ $10 = +HEAPF64[$height30 >> 3];
+ $cmp31 = $9 < $10;
+ $cond = $cmp31 ? $9 : $10;
+ $mul = $cond * 72.0;
+ $cmp33 = $mul < 0.0;
+ if ($cmp33) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add = $mul + .5;
+ $add_sink = $add;
+ label = 7;
+ break;
+ case 6:
+ $sub = $mul + -.5;
+ $add_sink = $sub;
+ label = 7;
+ break;
+ case 7:
+ $conv43 = ~~$add_sink;
+ $conv55 = +($conv43 | 0);
+ $height_0 = $conv55;
+ $width_0 = $conv55;
+ label = 15;
+ break;
+ case 8:
+ $width58 = $n + 48 | 0;
+ $11 = +HEAPF64[$width58 >> 3];
+ $mul59 = $11 * 72.0;
+ $cmp60 = $mul59 < 0.0;
+ if ($cmp60) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add66 = $mul59 + .5;
+ $add66_sink = $add66;
+ label = 11;
+ break;
+ case 10:
+ $sub72 = $mul59 + -.5;
+ $add66_sink = $sub72;
+ label = 11;
+ break;
+ case 11:
+ $conv67 = ~~$add66_sink;
+ $conv76 = +($conv67 | 0);
+ $height78 = $n + 56 | 0;
+ $12 = +HEAPF64[$height78 >> 3];
+ $mul79 = $12 * 72.0;
+ $cmp80 = $mul79 < 0.0;
+ if ($cmp80) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $add86 = $mul79 + .5;
+ $add86_sink = $add86;
+ label = 14;
+ break;
+ case 13:
+ $sub92 = $mul79 + -.5;
+ $add86_sink = $sub92;
+ label = 14;
+ break;
+ case 14:
+ $conv87 = ~~$add86_sink;
+ $conv96 = +($conv87 | 0);
+ $height_0 = $conv96;
+ $width_0 = $conv76;
+ label = 15;
+ break;
+ case 15:
+ $13 = HEAP32[41574] | 0;
+ $call98 = _late_int($8, $13, $3, 0) | 0;
+ $14 = HEAP32[41578] | 0;
+ $call99 = +_late_double($8, $14, 0.0, -360.0);
+ $add100 = $5 + $call99;
+ $cmp101 = ($4 | 0) == 0;
+ if ($cmp101) {
+ label = 16;
+ break;
+ } else {
+ $sides_0 = $4;
+ $skew_0 = $6;
+ $distortion_0 = $7;
+ label = 17;
+ break;
+ }
+ case 16:
+ $15 = HEAP32[41562] | 0;
+ $call104 = +_late_double($8, $15, 0.0, -100.0);
+ $16 = HEAP32[41564] | 0;
+ $call105 = _late_int($8, $16, 4, 0) | 0;
+ $17 = HEAP32[41608] | 0;
+ $call106 = +_late_double($8, $17, 0.0, -100.0);
+ $sides_0 = $call105;
+ $skew_0 = $call104;
+ $distortion_0 = $call106;
+ label = 17;
+ break;
+ case 17:
+ $label = $n + 120 | 0;
+ $18 = HEAP32[$label >> 2] | 0;
+ $dimen_sroa_0_0__idx = $18 + 24 | 0;
+ $dimen_sroa_0_0_copyload = +HEAPF64[$dimen_sroa_0_0__idx >> 3];
+ $dimen_sroa_1_8__idx336 = $18 + 32 | 0;
+ $dimen_sroa_1_8_copyload = +HEAPF64[$dimen_sroa_1_8__idx336 >> 3];
+ $conv110 = ~~$dimen_sroa_0_0_copyload;
+ $ispos = ($conv110 | 0) > -1;
+ $neg = -$conv110 | 0;
+ $call111 = $ispos ? $conv110 : $neg;
+ $cmp112 = ($call111 | 0) > -1;
+ $ispos389 = ($conv110 | 0) > -1;
+ $neg390 = -$conv110 | 0;
+ $call117 = $ispos389 ? $conv110 : $neg390;
+ $conv118 = +($call117 | 0);
+ if ($cmp112) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $add119 = $conv118 + .5;
+ $conv120 = ~~$add119;
+ $tobool121 = ($conv120 | 0) == 0;
+ if ($tobool121) {
+ label = 20;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 19:
+ $sub127 = $conv118 + -.5;
+ $conv128 = ~~$sub127;
+ $tobool129 = ($conv128 | 0) == 0;
+ if ($tobool129) {
+ label = 20;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 20:
+ $conv130 = ~~$dimen_sroa_1_8_copyload;
+ $ispos391 = ($conv130 | 0) > -1;
+ $neg392 = -$conv130 | 0;
+ $call131 = $ispos391 ? $conv130 : $neg392;
+ $cmp132 = ($call131 | 0) > -1;
+ $ispos393 = ($conv130 | 0) > -1;
+ $neg394 = -$conv130 | 0;
+ $call137 = $ispos393 ? $conv130 : $neg394;
+ $conv138 = +($call137 | 0);
+ if ($cmp132) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $add139 = $conv138 + .5;
+ $conv140 = ~~$add139;
+ $tobool141 = ($conv140 | 0) == 0;
+ if ($tobool141) {
+ $dimen_sroa_1_0 = $dimen_sroa_1_8_copyload;
+ $dimen_sroa_0_0 = $dimen_sroa_0_0_copyload;
+ label = 43;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $sub147 = $conv138 + -.5;
+ $conv148 = ~~$sub147;
+ $tobool149 = ($conv148 | 0) == 0;
+ if ($tobool149) {
+ $dimen_sroa_1_0 = $dimen_sroa_1_8_copyload;
+ $dimen_sroa_0_0 = $dimen_sroa_0_0_copyload;
+ label = 43;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $call151 = _agget($8, 99584) | 0;
+ $tobool152 = ($call151 | 0) == 0;
+ if ($tobool152) {
+ label = 42;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $call154 = _sscanf($call151 | 0, 99208, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $marginx, HEAP32[tempInt + 8 >> 2] = $marginy, tempInt) | 0) | 0;
+ $19 = +HEAPF64[$marginx >> 3];
+ $cmp155 = $19 < 0.0;
+ if ($cmp155) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ HEAPF64[$marginx >> 3] = 0.0;
+ label = 26;
+ break;
+ case 26:
+ $20 = +HEAPF64[$marginy >> 3];
+ $cmp159 = $20 < 0.0;
+ if ($cmp159) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ HEAPF64[$marginy >> 3] = 0.0;
+ label = 28;
+ break;
+ case 28:
+ $cmp163 = ($call154 | 0) > 0;
+ if ($cmp163) {
+ label = 29;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 29:
+ $21 = +HEAPF64[$marginx >> 3];
+ $mul166 = $21 * 72.0;
+ $cmp167 = $mul166 < 0.0;
+ if ($cmp167) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $add171 = $mul166 + .5;
+ $add171_sink = $add171;
+ label = 32;
+ break;
+ case 31:
+ $sub175 = $mul166 + -.5;
+ $add171_sink = $sub175;
+ label = 32;
+ break;
+ case 32:
+ $conv172 = ~~$add171_sink;
+ $mul179 = $conv172 << 1;
+ $conv180 = +($mul179 | 0);
+ $add182 = $dimen_sroa_0_0_copyload + $conv180;
+ $cmp183 = ($call154 | 0) > 1;
+ if ($cmp183) {
+ label = 33;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 33:
+ $22 = +HEAPF64[$marginy >> 3];
+ $mul186 = $22 * 72.0;
+ $cmp187 = $mul186 < 0.0;
+ if ($cmp187) {
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $add191 = $mul186 + .5;
+ $add191_sink = $add191;
+ label = 36;
+ break;
+ case 35:
+ $sub195 = $mul186 + -.5;
+ $add191_sink = $sub195;
+ label = 36;
+ break;
+ case 36:
+ $conv192 = ~~$add191_sink;
+ $mul199 = $conv192 << 1;
+ $conv200 = +($mul199 | 0);
+ $add202 = $dimen_sroa_1_8_copyload + $conv200;
+ $dimen_sroa_1_0 = $add202;
+ $dimen_sroa_0_0 = $add182;
+ label = 43;
+ break;
+ case 37:
+ $23 = +HEAPF64[$marginx >> 3];
+ $mul204 = $23 * 72.0;
+ $cmp205 = $mul204 < 0.0;
+ if ($cmp205) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $add209 = $mul204 + .5;
+ $add209_sink = $add209;
+ label = 40;
+ break;
+ case 39:
+ $sub213 = $mul204 + -.5;
+ $add209_sink = $sub213;
+ label = 40;
+ break;
+ case 40:
+ $conv210 = ~~$add209_sink;
+ $mul217 = $conv210 << 1;
+ $conv218 = +($mul217 | 0);
+ $add220 = $dimen_sroa_1_8_copyload + $conv218;
+ $dimen_sroa_1_0 = $add220;
+ $dimen_sroa_0_0 = $add182;
+ label = 43;
+ break;
+ case 41:
+ $add224 = $dimen_sroa_0_0_copyload + 16.0;
+ $add226 = $dimen_sroa_1_8_copyload + 8.0;
+ $dimen_sroa_1_0 = $add226;
+ $dimen_sroa_0_0 = $add224;
+ label = 43;
+ break;
+ case 42:
+ $add230 = $dimen_sroa_0_0_copyload + 16.0;
+ $add232 = $dimen_sroa_1_8_copyload + 8.0;
+ $dimen_sroa_1_0 = $add232;
+ $dimen_sroa_0_0 = $add230;
+ label = 43;
+ break;
+ case 43:
+ $24 = HEAP32[$label >> 2] | 0;
+ $x239 = $24 + 24 | 0;
+ $25 = +HEAPF64[$x239 >> 3];
+ $sub240 = $dimen_sroa_0_0 - $25;
+ $graph = $n + 20 | 0;
+ $26 = HEAP32[$graph >> 2] | 0;
+ $drawing = $26 + 48 | 0;
+ $27 = HEAP32[$drawing >> 2] | 0;
+ $quantum = $27 | 0;
+ $28 = +HEAPF64[$quantum >> 3];
+ $cmp242 = $28 > 0.0;
+ if ($cmp242) {
+ label = 44;
+ break;
+ } else {
+ $dimen_sroa_1_1 = $dimen_sroa_1_0;
+ $dimen_sroa_0_1 = $dimen_sroa_0_0;
+ label = 48;
+ break;
+ }
+ case 44:
+ $mul245 = $28 * 72.0;
+ $cmp246 = $mul245 < 0.0;
+ if ($cmp246) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $add250 = $mul245 + .5;
+ $add250_sink = $add250;
+ label = 47;
+ break;
+ case 46:
+ $sub254 = $mul245 + -.5;
+ $add250_sink = $sub254;
+ label = 47;
+ break;
+ case 47:
+ $conv251 = ~~$add250_sink;
+ $conv258 = +($conv251 | 0);
+ $call260 = +_quant($dimen_sroa_0_0, $conv258);
+ $call263 = +_quant($dimen_sroa_1_0, $conv258);
+ $dimen_sroa_1_1 = $call263;
+ $dimen_sroa_0_1 = $call260;
+ label = 48;
+ break;
+ case 48:
+ $29 = HEAP32[$shape >> 2] | 0;
+ $usershape = $29 + 12 | 0;
+ $30 = HEAP8[$usershape] | 0;
+ $tobool270 = $30 << 24 >> 24 == 0;
+ if ($tobool270) {
+ label = 54;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $name = $29 | 0;
+ $31 = HEAP32[$name >> 2] | 0;
+ $32 = HEAP8[$31] | 0;
+ $cmp276 = $32 << 24 >> 24 == 99;
+ if ($cmp276) {
+ label = 50;
+ break;
+ } else {
+ $imagesize_sroa_1_0 = 0;
+ $imagesize_sroa_0_0 = 0;
+ label = 59;
+ break;
+ }
+ case 50:
+ $call281 = _strcmp($31 | 0, 110216) | 0;
+ $tobool282 = ($call281 | 0) == 0;
+ if ($tobool282) {
+ label = 51;
+ break;
+ } else {
+ $imagesize_sroa_1_0 = 0;
+ $imagesize_sroa_0_0 = 0;
+ label = 59;
+ break;
+ }
+ case 51:
+ $call284 = _agget($8, 120672) | 0;
+ $33 = HEAP32[$graph >> 2] | 0;
+ _gvusershape_size($tmp, $33, $call284);
+ $imagesize_sroa_0_0__idx262 = $tmp | 0;
+ $imagesize_sroa_0_0_copyload263 = HEAP32[$imagesize_sroa_0_0__idx262 >> 2] | 0;
+ $imagesize_sroa_1_4__idx272 = $tmp + 4 | 0;
+ $imagesize_sroa_1_4_copyload273 = HEAP32[$imagesize_sroa_1_4__idx272 >> 2] | 0;
+ $cmp287 = ($imagesize_sroa_0_0_copyload263 | 0) == -1;
+ $cmp291 = ($imagesize_sroa_1_4_copyload273 | 0) == -1;
+ $or_cond = $cmp287 & $cmp291;
+ if ($or_cond) {
+ label = 52;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 52:
+ $tobool294 = ($call284 | 0) != 0;
+ $cond298 = $tobool294 ? $call284 : 98008;
+ $name299 = $n + 12 | 0;
+ $34 = HEAP32[$name299 >> 2] | 0;
+ $call300 = _agerr(0, 98360, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $cond298, HEAP32[tempInt + 8 >> 2] = $34, tempInt) | 0) | 0;
+ $imagesize_sroa_1_0 = 0;
+ $imagesize_sroa_0_0 = 0;
+ label = 59;
+ break;
+ case 53:
+ $35 = HEAP32[$graph >> 2] | 0;
+ $has_images = $35 + 154 | 0;
+ HEAP8[$has_images] = 1;
+ $add307 = $imagesize_sroa_0_0_copyload263 + 2 | 0;
+ $add309 = $imagesize_sroa_1_4_copyload273 + 2 | 0;
+ $imagesize_sroa_1_0 = $add309;
+ $imagesize_sroa_0_0 = $add307;
+ label = 59;
+ break;
+ case 54:
+ $call313 = _agget($8, 101440) | 0;
+ $tobool314 = ($call313 | 0) != 0;
+ if ($tobool314) {
+ label = 55;
+ break;
+ } else {
+ $imagesize_sroa_1_0 = 0;
+ $imagesize_sroa_0_0 = 0;
+ label = 59;
+ break;
+ }
+ case 55:
+ $36 = HEAP8[$call313] | 0;
+ $cmp317 = $36 << 24 >> 24 == 0;
+ if ($cmp317) {
+ $imagesize_sroa_1_0 = 0;
+ $imagesize_sroa_0_0 = 0;
+ label = 59;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 56:
+ $37 = HEAP32[$graph >> 2] | 0;
+ _gvusershape_size($tmp321, $37, $call313);
+ $imagesize_sroa_0_0__idx = $tmp321 | 0;
+ $imagesize_sroa_0_0_copyload = HEAP32[$imagesize_sroa_0_0__idx >> 2] | 0;
+ $imagesize_sroa_1_4__idx269 = $tmp321 + 4 | 0;
+ $imagesize_sroa_1_4_copyload = HEAP32[$imagesize_sroa_1_4__idx269 >> 2] | 0;
+ $cmp323 = ($imagesize_sroa_0_0_copyload | 0) == -1;
+ $cmp327 = ($imagesize_sroa_1_4_copyload | 0) == -1;
+ $or_cond385 = $cmp323 & $cmp327;
+ if ($or_cond385) {
+ label = 57;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 57:
+ $cond334 = $tobool314 ? $call313 : 98008;
+ $name335 = $n + 12 | 0;
+ $38 = HEAP32[$name335 >> 2] | 0;
+ $call336 = _agerr(0, 97504, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $cond334, HEAP32[tempInt + 8 >> 2] = $38, tempInt) | 0) | 0;
+ $imagesize_sroa_1_0 = 0;
+ $imagesize_sroa_0_0 = 0;
+ label = 59;
+ break;
+ case 58:
+ $39 = HEAP32[$graph >> 2] | 0;
+ $has_images342 = $39 + 154 | 0;
+ HEAP8[$has_images342] = 1;
+ $add344 = $imagesize_sroa_0_0_copyload + 2 | 0;
+ $add346 = $imagesize_sroa_1_4_copyload + 2 | 0;
+ $imagesize_sroa_1_0 = $add346;
+ $imagesize_sroa_0_0 = $add344;
+ label = 59;
+ break;
+ case 59:
+ $conv352 = +($imagesize_sroa_0_0 | 0);
+ $cmp353 = $dimen_sroa_0_1 > $conv352;
+ $dimen_sroa_0_1_conv352 = $cmp353 ? $dimen_sroa_0_1 : $conv352;
+ $conv365 = +($imagesize_sroa_1_0 | 0);
+ $cmp366 = $dimen_sroa_1_1 > $conv365;
+ $cond374 = $cmp366 ? $dimen_sroa_1_1 : $conv365;
+ $cmp376 = ($sides_0 | 0) < 3;
+ if ($cmp376) {
+ label = 60;
+ break;
+ } else {
+ $sides_1 = $sides_0;
+ label = 61;
+ break;
+ }
+ case 60:
+ $cmp379 = $distortion_0 != 0.0;
+ $cmp382 = $skew_0 != 0.0;
+ $or_cond386 = $cmp379 | $cmp382;
+ $_sides_0 = $or_cond386 ? 120 : $sides_0;
+ $sides_1 = $_sides_0;
+ label = 61;
+ break;
+ case 61:
+ $call386 = _agget($8, 97168) | 0;
+ $tobool387 = ($call386 | 0) == 0;
+ if ($tobool387) {
+ label = 64;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 62:
+ $40 = HEAP8[$call386] | 0;
+ if (($40 << 24 >> 24 | 0) == 116 | ($40 << 24 >> 24 | 0) == 98) {
+ label = 63;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 63:
+ $41 = HEAP8[$call386] | 0;
+ $42 = HEAP32[$label >> 2] | 0;
+ $valign = $42 + 80 | 0;
+ HEAP8[$valign] = $41;
+ label = 65;
+ break;
+ case 64:
+ $43 = HEAP32[$label >> 2] | 0;
+ $valign404 = $43 + 80 | 0;
+ HEAP8[$valign404] = 99;
+ label = 65;
+ break;
+ case 65:
+ $cmp406 = ($sides_1 | 0) == 4;
+ if ($cmp406) {
+ label = 66;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 66:
+ $cmp409 = $add100 < 0.0;
+ if ($cmp409) {
+ label = 68;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 67:
+ $add412 = $add100 + .5;
+ $add412_sink = $add412;
+ label = 69;
+ break;
+ case 68:
+ $sub415 = $add100 + -.5;
+ $add412_sink = $sub415;
+ label = 69;
+ break;
+ case 69:
+ $conv413 = ~~$add412_sink;
+ $rem = ($conv413 | 0) % 90;
+ $cmp419 = ($rem | 0) == 0;
+ $cmp422 = $distortion_0 == 0.0;
+ $or_cond387 = $cmp419 & $cmp422;
+ $cmp424 = $skew_0 == 0.0;
+ $or_cond395 = $or_cond387 & $cmp424;
+ if ($or_cond395) {
+ $bb_sroa_1_1 = $cond374;
+ $bb_sroa_0_1 = $dimen_sroa_0_1_conv352;
+ $46 = 1;
+ label = 75;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $mul430 = $cond374 * 1.4142135623730951;
+ $cmp431 = $height_0 > $mul430;
+ if ($cmp431) {
+ label = 71;
+ break;
+ } else {
+ $bb_sroa_1_0 = $mul430;
+ $call447_pn = 1.4142135623730951;
+ label = 73;
+ break;
+ }
+ case 71:
+ $44 = HEAP32[$label >> 2] | 0;
+ $valign436 = $44 + 80 | 0;
+ $45 = HEAP8[$valign436] | 0;
+ $cmp438 = $45 << 24 >> 24 == 99;
+ if ($cmp438) {
+ label = 72;
+ break;
+ } else {
+ $bb_sroa_1_0 = $mul430;
+ $call447_pn = 1.4142135623730951;
+ label = 73;
+ break;
+ }
+ case 72:
+ $div = $cond374 / $height_0;
+ $mul444 = $div * $div;
+ $sub445 = 1.0 - $mul444;
+ $div446 = 1.0 / $sub445;
+ $call447 = +Math_sqrt(+$div446);
+ $bb_sroa_1_0 = $cond374;
+ $call447_pn = $call447;
+ label = 73;
+ break;
+ case 73:
+ $bb_sroa_0_0 = $dimen_sroa_0_1_conv352 * $call447_pn;
+ $cmp455 = ($sides_1 | 0) > 2;
+ if ($cmp455) {
+ label = 74;
+ break;
+ } else {
+ $bb_sroa_1_1 = $bb_sroa_1_0;
+ $bb_sroa_0_1 = $bb_sroa_0_0;
+ $46 = 0;
+ label = 75;
+ break;
+ }
+ case 74:
+ $conv458 = +($sides_1 | 0);
+ $div459 = 3.141592653589793 / $conv458;
+ $call460 = +Math_cos(+$div459);
+ $div462 = $bb_sroa_0_0 / $call460;
+ $div464 = $bb_sroa_1_0 / $call460;
+ $bb_sroa_1_1 = $div464;
+ $bb_sroa_0_1 = $div462;
+ $46 = 0;
+ label = 75;
+ break;
+ case 75:
+ $47 = HEAP32[41602] | 0;
+ $call467 = _late_string($8, $47, 100880) | 0;
+ $call468 = _mapbool($call467) | 0;
+ $tobool469 = $call468 << 24 >> 24 == 0;
+ if ($tobool469) {
+ label = 78;
+ break;
+ } else {
+ label = 76;
+ break;
+ }
+ case 76:
+ $cmp472 = $width_0 < $bb_sroa_0_1;
+ $cmp476 = $height_0 < $bb_sroa_1_1;
+ $or_cond388 = $cmp472 | $cmp476;
+ if ($or_cond388) {
+ label = 77;
+ break;
+ } else {
+ $height_1 = $height_0;
+ $width_1 = $width_0;
+ label = 79;
+ break;
+ }
+ case 77:
+ $name479 = $n + 12 | 0;
+ $48 = HEAP32[$name479 >> 2] | 0;
+ $49 = HEAP32[$graph >> 2] | 0;
+ $name481 = $49 + 12 | 0;
+ $50 = HEAP32[$name481 >> 2] | 0;
+ $call482 = _agerr(0, 96728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $48, HEAP32[tempInt + 8 >> 2] = $50, tempInt) | 0) | 0;
+ $height_1 = $height_0;
+ $width_1 = $width_0;
+ label = 79;
+ break;
+ case 78:
+ $cmp488 = $width_0 > $bb_sroa_0_1;
+ $width_0_bb_sroa_0_1 = $cmp488 ? $width_0 : $bb_sroa_0_1;
+ $cmp497 = $height_0 > $bb_sroa_1_1;
+ $cond503 = $cmp497 ? $height_0 : $bb_sroa_1_1;
+ $height_1 = $cond503;
+ $width_1 = $width_0_bb_sroa_0_1;
+ label = 79;
+ break;
+ case 79:
+ if ($tobool) {
+ label = 80;
+ break;
+ } else {
+ $height_2 = $height_1;
+ $width_2 = $width_1;
+ label = 81;
+ break;
+ }
+ case 80:
+ $cmp510 = $width_1 > $height_1;
+ $width_1_height_1 = $cmp510 ? $width_1 : $height_1;
+ $height_2 = $width_1_height_1;
+ $width_2 = $width_1_height_1;
+ label = 81;
+ break;
+ case 81:
+ $51 = HEAP32[41582] | 0;
+ $call521 = _late_string($8, $51, 100880) | 0;
+ $call522 = _mapbool($call521) | 0;
+ $tobool523 = $call522 << 24 >> 24 == 0;
+ if ($tobool523) {
+ label = 82;
+ break;
+ } else {
+ label = 87;
+ break;
+ }
+ case 82:
+ if ($46) {
+ label = 83;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 83:
+ $cmp529 = $dimen_sroa_0_1 > $width_2;
+ $dimen_sroa_0_1_width_2 = $cmp529 ? $dimen_sroa_0_1 : $width_2;
+ $sub537 = $dimen_sroa_0_1_width_2 - $sub240;
+ $52 = HEAP32[$label >> 2] | 0;
+ $x540 = $52 + 40 | 0;
+ HEAPF64[$x540 >> 3] = $sub537;
+ label = 88;
+ break;
+ case 84:
+ $cmp544 = $dimen_sroa_1_1 < $height_2;
+ if ($cmp544) {
+ label = 85;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 85:
+ $mul550 = $dimen_sroa_1_1 * $dimen_sroa_1_1;
+ $mul553 = $height_2 * $height_2;
+ $div554 = $mul550 / $mul553;
+ $sub555 = 1.0 - $div554;
+ $call556 = +Math_sqrt(+$sub555);
+ $mul557 = $width_2 * $call556;
+ $cmp559 = $dimen_sroa_0_1 > $mul557;
+ $dimen_sroa_0_1_mul557 = $cmp559 ? $dimen_sroa_0_1 : $mul557;
+ $sub566 = $dimen_sroa_0_1_mul557 - $sub240;
+ $53 = HEAP32[$label >> 2] | 0;
+ $x570 = $53 + 40 | 0;
+ HEAPF64[$x570 >> 3] = $sub566;
+ label = 88;
+ break;
+ case 86:
+ $sub573 = $dimen_sroa_0_1 - $sub240;
+ $54 = HEAP32[$label >> 2] | 0;
+ $x577 = $54 + 40 | 0;
+ HEAPF64[$x577 >> 3] = $sub573;
+ label = 88;
+ break;
+ case 87:
+ $sub582 = $dimen_sroa_0_1 - $sub240;
+ $55 = HEAP32[$label >> 2] | 0;
+ $x586 = $55 + 40 | 0;
+ HEAPF64[$x586 >> 3] = $sub582;
+ label = 88;
+ break;
+ case 88:
+ $sub590 = $height_2 - $bb_sroa_1_1;
+ $cmp594 = $dimen_sroa_1_1 < $conv365;
+ if ($cmp594) {
+ label = 89;
+ break;
+ } else {
+ $temp_0 = $sub590;
+ label = 90;
+ break;
+ }
+ case 89:
+ $sub600 = $conv365 - $dimen_sroa_1_1;
+ $add601 = $sub600 + $sub590;
+ $temp_0 = $add601;
+ label = 90;
+ break;
+ case 90:
+ $add604 = $dimen_sroa_1_1 + $temp_0;
+ $56 = HEAP32[$label >> 2] | 0;
+ $y608 = $56 + 48 | 0;
+ HEAPF64[$y608 >> 3] = $add604;
+ $cmp609 = ($call98 | 0) < 1;
+ $_call98 = $cmp609 ? 1 : $call98;
+ $cmp613 = ($sides_1 | 0) < 3;
+ if ($cmp613) {
+ label = 91;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 91:
+ $mul617 = $_call98 << 5;
+ $call618 = _zmalloc($mul617) | 0;
+ $57 = $call618;
+ $div620 = $width_2 * .5;
+ $div623 = $height_2 * .5;
+ $sub626 = -0.0 - $div620;
+ $x628 = $call618;
+ HEAPF64[$x628 >> 3] = $sub626;
+ $sub630 = -0.0 - $div623;
+ $y632 = $call618 + 8 | 0;
+ $58 = $y632;
+ HEAPF64[$58 >> 3] = $sub630;
+ $P_sroa_0_0__idx229 = $call618 + 16 | 0;
+ $59 = $P_sroa_0_0__idx229;
+ HEAPF64[$59 >> 3] = $div620;
+ $P_sroa_1_8__idx254 = $call618 + 24 | 0;
+ $60 = $P_sroa_1_8__idx254;
+ HEAPF64[$60 >> 3] = $div623;
+ $cmp634 = ($call98 | 0) > 1;
+ if ($cmp634) {
+ $P_sroa_0_0397 = $div620;
+ $P_sroa_1_0398 = $div623;
+ $i_0399 = 2;
+ $j_0400 = 1;
+ label = 92;
+ break;
+ } else {
+ $bb_sroa_1_5 = $height_2;
+ $sides_2 = 2;
+ $bb_sroa_0_5 = $width_2;
+ $vertices_0 = $57;
+ label = 109;
+ break;
+ }
+ case 92:
+ $add640 = $P_sroa_0_0397 + 4.0;
+ $add642 = $P_sroa_1_0398 + 4.0;
+ $sub644 = -0.0 - $add640;
+ $x646 = $57 + ($i_0399 << 4) | 0;
+ HEAPF64[$x646 >> 3] = $sub644;
+ $sub648 = -0.0 - $add642;
+ $y650 = $57 + ($i_0399 << 4) + 8 | 0;
+ HEAPF64[$y650 >> 3] = $sub648;
+ $inc384 = $i_0399 | 1;
+ $x653 = $57 + ($inc384 << 4) | 0;
+ HEAPF64[$x653 >> 3] = $add640;
+ $y656 = $57 + ($inc384 << 4) + 8 | 0;
+ HEAPF64[$y656 >> 3] = $add642;
+ $inc657 = $i_0399 + 2 | 0;
+ $inc658 = $j_0400 + 1 | 0;
+ $cmp637 = ($inc658 | 0) < ($call98 | 0);
+ if ($cmp637) {
+ $P_sroa_0_0397 = $add640;
+ $P_sroa_1_0398 = $add642;
+ $i_0399 = $inc657;
+ $j_0400 = $inc658;
+ label = 92;
+ break;
+ } else {
+ label = 93;
+ break;
+ }
+ case 93:
+ $mul660 = $add640 * 2.0;
+ $mul663 = $add642 * 2.0;
+ $bb_sroa_1_5 = $mul663;
+ $sides_2 = 2;
+ $bb_sroa_0_5 = $mul660;
+ $vertices_0 = $57;
+ label = 109;
+ break;
+ case 94:
+ $mul667 = $_call98 << 4;
+ $mul668 = Math_imul($mul667, $sides_1);
+ $call669 = _zmalloc($mul668) | 0;
+ $61 = $call669;
+ $conv670 = +($sides_1 | 0);
+ $div671 = 6.283185307179586 / $conv670;
+ $div672 = $div671 * .5;
+ $call673 = +Math_sin(+$div672);
+ $call674 = +Math_abs(+$distortion_0);
+ $call675 = +Math_abs(+$skew_0);
+ $add676 = $call674 + $call675;
+ $call677 = +_hypot(+$add676, 1.0);
+ $mul678 = $distortion_0 * 1.4142135623730951;
+ $call680 = +Math_cos(+$div672);
+ $div681 = $mul678 / $call680;
+ $div682 = $skew_0 * .5;
+ $sub683 = $div671 - 3.141592653589793;
+ $div684 = $sub683 * .5;
+ $call685 = +Math_sin(+$div684);
+ $call686 = +Math_cos(+$div684);
+ $mul687 = $call686 * .5;
+ $mul689 = $call685 * .5;
+ $sub691 = 3.141592653589793 - $div671;
+ $div692 = $sub691 * .5;
+ $add693 = $div684 + $div692;
+ $div718 = $add100 / 180.0;
+ $mul719 = $div718 * 3.141592653589793;
+ $i_1 = 0;
+ $ymax_0 = 0.0;
+ $xmax_0 = 0.0;
+ $angle_0 = $add693;
+ $R_sroa_1_0 = $mul689;
+ $R_sroa_0_0 = $mul687;
+ label = 95;
+ break;
+ case 95:
+ $cmp695 = ($i_1 | 0) < ($sides_1 | 0);
+ if ($cmp695) {
+ label = 96;
+ break;
+ } else {
+ $ymax_1 = $ymax_0;
+ $xmax_1 = $xmax_0;
+ label = 98;
+ break;
+ }
+ case 96:
+ $add698 = $div671 + $angle_0;
+ $call699 = +Math_sin(+$add698);
+ $call700 = +Math_cos(+$add698);
+ $mul701 = $call673 * $call700;
+ $add703 = $R_sroa_0_0 + $mul701;
+ $mul704 = $call673 * $call699;
+ $add706 = $R_sroa_1_0 + $mul704;
+ $mul709 = $div681 * $add706;
+ $add710 = $call677 + $mul709;
+ $mul711 = $add703 * $add710;
+ $mul713 = $div682 * $add706;
+ $add714 = $mul713 + $mul711;
+ $call722 = +Math_atan2(+$add706, +$add714);
+ $add723 = $mul719 + $call722;
+ $call724 = +Math_sin(+$add723);
+ $call725 = +Math_cos(+$add723);
+ $call728 = +_hypot(+$add714, +$add706);
+ $mul732 = $call725 * $call728;
+ $mul734 = $call724 * $call728;
+ $mul737 = $width_2 * $mul732;
+ $mul740 = $height_2 * $mul734;
+ $call742 = +Math_abs(+$mul737);
+ $cmp743 = $call742 > $xmax_0;
+ $call742_xmax_0 = $cmp743 ? $call742 : $xmax_0;
+ $call752 = +Math_abs(+$mul740);
+ $cmp753 = $call752 > $ymax_0;
+ $cond760 = $cmp753 ? $call752 : $ymax_0;
+ $P_sroa_0_0__idx218 = $61 + ($i_1 << 4) | 0;
+ HEAPF64[$P_sroa_0_0__idx218 >> 3] = $mul737;
+ $P_sroa_1_8__idx242 = $61 + ($i_1 << 4) + 8 | 0;
+ HEAPF64[$P_sroa_1_8__idx242 >> 3] = $mul740;
+ $inc788 = $i_1 + 1 | 0;
+ if ($46) {
+ label = 97;
+ break;
+ } else {
+ $i_1 = $inc788;
+ $ymax_0 = $cond760;
+ $xmax_0 = $call742_xmax_0;
+ $angle_0 = $add698;
+ $R_sroa_1_0 = $add706;
+ $R_sroa_0_0 = $add703;
+ label = 95;
+ break;
+ }
+ case 97:
+ $sub765 = -0.0 - $mul737;
+ $arrayidx766 = $call669 + 16 | 0;
+ $x767 = $arrayidx766;
+ HEAPF64[$x767 >> 3] = $sub765;
+ $y770 = $call669 + 24 | 0;
+ $62 = $y770;
+ HEAPF64[$62 >> 3] = $mul740;
+ $arrayidx773 = $call669 + 32 | 0;
+ $x774 = $arrayidx773;
+ HEAPF64[$x774 >> 3] = $sub765;
+ $sub776 = -0.0 - $mul740;
+ $y778 = $call669 + 40 | 0;
+ $63 = $y778;
+ HEAPF64[$63 >> 3] = $sub776;
+ $arrayidx780 = $call669 + 48 | 0;
+ $x781 = $arrayidx780;
+ HEAPF64[$x781 >> 3] = $mul737;
+ $y785 = $call669 + 56 | 0;
+ $64 = $y785;
+ HEAPF64[$64 >> 3] = $sub776;
+ $ymax_1 = $cond760;
+ $xmax_1 = $call742_xmax_0;
+ label = 98;
+ break;
+ case 98:
+ $mul790 = $xmax_1 * 2.0;
+ $mul791 = $ymax_1 * 2.0;
+ $cmp792 = $width_2 > $mul790;
+ $cond797 = $cmp792 ? $width_2 : $mul790;
+ $cmp799 = $height_2 > $mul791;
+ $cond804 = $cmp799 ? $height_2 : $mul791;
+ $div807 = $cond797 / $mul790;
+ $div809 = $cond804 / $mul791;
+ $cmp811417 = ($sides_1 | 0) > 0;
+ if ($cmp811417) {
+ $i_2418 = 0;
+ label = 99;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 99:
+ $P_sroa_0_0__idx213 = $61 + ($i_2418 << 4) | 0;
+ $P_sroa_0_0_copyload214 = +HEAPF64[$P_sroa_0_0__idx213 >> 3];
+ $P_sroa_1_8__idx237 = $61 + ($i_2418 << 4) + 8 | 0;
+ $P_sroa_1_8_copyload238 = +HEAPF64[$P_sroa_1_8__idx237 >> 3];
+ $mul816 = $div807 * $P_sroa_0_0_copyload214;
+ $mul818 = $div809 * $P_sroa_1_8_copyload238;
+ HEAPF64[$P_sroa_0_0__idx213 >> 3] = $mul816;
+ HEAPF64[$P_sroa_1_8__idx237 >> 3] = $mul818;
+ $inc821 = $i_2418 + 1 | 0;
+ $cmp811 = ($inc821 | 0) < ($sides_1 | 0);
+ if ($cmp811) {
+ $i_2418 = $inc821;
+ label = 99;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 100:
+ $cmp823 = ($call98 | 0) > 1;
+ if ($cmp823) {
+ label = 101;
+ break;
+ } else {
+ $bb_sroa_1_5 = $cond804;
+ $sides_2 = $sides_1;
+ $bb_sroa_0_5 = $cond797;
+ $vertices_0 = $61;
+ label = 109;
+ break;
+ }
+ case 101:
+ $sub826 = $sides_1 - 1 | 0;
+ $R_sroa_0_0__idx182 = $call669;
+ $R_sroa_0_0_copyload183 = +HEAPF64[$R_sroa_0_0__idx182 >> 3];
+ $R_sroa_1_8__idx190 = $call669 + 8 | 0;
+ $65 = $R_sroa_1_8__idx190;
+ $R_sroa_1_8_copyload191 = +HEAPF64[$65 >> 3];
+ $cmp837412 = ($sides_1 | 0) > 0;
+ if ($cmp837412) {
+ label = 102;
+ break;
+ } else {
+ $bb_sroa_1_5 = $cond804;
+ $sides_2 = $sides_1;
+ $bb_sroa_0_5 = $cond797;
+ $vertices_0 = $61;
+ label = 109;
+ break;
+ }
+ case 102:
+ $Q_sroa_1_8__idx207 = $61 + ($sub826 << 4) + 8 | 0;
+ $Q_sroa_0_0__idx200 = $61 + ($sub826 << 4) | 0;
+ $Q_sroa_1_8_copyload208 = +HEAPF64[$Q_sroa_1_8__idx207 >> 3];
+ $Q_sroa_0_0_copyload201 = +HEAPF64[$Q_sroa_0_0__idx200 >> 3];
+ $sub834 = $R_sroa_0_0_copyload183 - $Q_sroa_0_0_copyload201;
+ $sub831 = $R_sroa_1_8_copyload191 - $Q_sroa_1_8_copyload208;
+ $call835 = +Math_atan2(+$sub831, +$sub834);
+ $cmp862408 = ($call98 | 0) > 1;
+ $beta_0413 = $call835;
+ $R_sroa_0_1414 = $R_sroa_0_0_copyload183;
+ $R_sroa_1_1415 = $R_sroa_1_8_copyload191;
+ $i_3416 = 0;
+ label = 106;
+ break;
+ case 103:
+ $cmp837 = ($add840 | 0) < ($sides_1 | 0);
+ if ($cmp837) {
+ $beta_0413 = $call849;
+ $R_sroa_0_1414 = $R_sroa_0_0_copyload;
+ $R_sroa_1_1415 = $R_sroa_1_8_copyload;
+ $i_3416 = $add840;
+ label = 106;
+ break;
+ } else {
+ label = 104;
+ break;
+ }
+ case 104:
+ $cmp879402 = ($sides_1 | 0) > 0;
+ if ($cmp879402) {
+ label = 105;
+ break;
+ } else {
+ $bb_sroa_1_5 = $cond804;
+ $sides_2 = $sides_1;
+ $bb_sroa_0_5 = $cond797;
+ $vertices_0 = $61;
+ label = 109;
+ break;
+ }
+ case 105:
+ $sub882 = $call98 - 1 | 0;
+ $mul883 = Math_imul($sides_1, $sub882);
+ $bb_sroa_0_4403 = $cond797;
+ $i_4404 = 0;
+ $bb_sroa_1_4405 = $cond804;
+ label = 108;
+ break;
+ case 106:
+ $add840 = $i_3416 + 1 | 0;
+ $66 = ($add840 | 0) == ($sides_1 | 0);
+ $tmp421 = $66 ? 0 : $add840;
+ $R_sroa_0_0__idx = $61 + ($tmp421 << 4) | 0;
+ $R_sroa_0_0_copyload = +HEAPF64[$R_sroa_0_0__idx >> 3];
+ $R_sroa_1_8__idx186 = $61 + ($tmp421 << 4) + 8 | 0;
+ $R_sroa_1_8_copyload = +HEAPF64[$R_sroa_1_8__idx186 >> 3];
+ $sub845 = $R_sroa_1_8_copyload - $R_sroa_1_1415;
+ $sub848 = $R_sroa_0_0_copyload - $R_sroa_0_1414;
+ $call849 = +Math_atan2(+$sub845, +$sub848);
+ $add850 = $beta_0413 + 3.141592653589793;
+ $sub851 = $add850 - $call849;
+ $div852 = $sub851 * .5;
+ $call853 = +Math_sin(+$div852);
+ $div854 = 4.0 / $call853;
+ $sub855 = $beta_0413 - $div852;
+ $call856 = +Math_sin(+$sub855);
+ $call858 = +Math_cos(+$sub855);
+ $mul859 = $div854 * $call856;
+ $mul860 = $div854 * $call858;
+ if ($cmp862408) {
+ $Q_sroa_0_1409 = $R_sroa_0_1414;
+ $Q_sroa_1_1410 = $R_sroa_1_1415;
+ $j_1411 = 1;
+ label = 107;
+ break;
+ } else {
+ label = 103;
+ break;
+ }
+ case 107:
+ $add866 = $mul860 + $Q_sroa_0_1409;
+ $add868 = $mul859 + $Q_sroa_1_1410;
+ $mul869 = Math_imul($j_1411, $sides_1);
+ $add870 = $mul869 + $i_3416 | 0;
+ $Q_sroa_0_0__idx = $61 + ($add870 << 4) | 0;
+ HEAPF64[$Q_sroa_0_0__idx >> 3] = $add866;
+ $Q_sroa_1_8__idx202 = $61 + ($add870 << 4) + 8 | 0;
+ HEAPF64[$Q_sroa_1_8__idx202 >> 3] = $add868;
+ $inc873 = $j_1411 + 1 | 0;
+ $cmp862 = ($inc873 | 0) < ($call98 | 0);
+ if ($cmp862) {
+ $Q_sroa_0_1409 = $add866;
+ $Q_sroa_1_1410 = $add868;
+ $j_1411 = $inc873;
+ label = 107;
+ break;
+ } else {
+ label = 103;
+ break;
+ }
+ case 108:
+ $add884 = $i_4404 + $mul883 | 0;
+ $P_sroa_0_0__idx = $61 + ($add884 << 4) | 0;
+ $P_sroa_0_0_copyload = +HEAPF64[$P_sroa_0_0__idx >> 3];
+ $P_sroa_1_8__idx233 = $61 + ($add884 << 4) + 8 | 0;
+ $P_sroa_1_8_copyload = +HEAPF64[$P_sroa_1_8__idx233 >> 3];
+ $call887 = +Math_abs(+$P_sroa_0_0_copyload);
+ $mul888 = $call887 * 2.0;
+ $cmp890 = $mul888 > $bb_sroa_0_4403;
+ $mul888_bb_sroa_0_4 = $cmp890 ? $mul888 : $bb_sroa_0_4403;
+ $call902 = +Math_abs(+$P_sroa_1_8_copyload);
+ $mul903 = $call902 * 2.0;
+ $cmp905 = $mul903 > $bb_sroa_1_4405;
+ $cond914 = $cmp905 ? $mul903 : $bb_sroa_1_4405;
+ $inc917 = $i_4404 + 1 | 0;
+ $cmp879 = ($inc917 | 0) < ($sides_1 | 0);
+ if ($cmp879) {
+ $bb_sroa_0_4403 = $mul888_bb_sroa_0_4;
+ $i_4404 = $inc917;
+ $bb_sroa_1_4405 = $cond914;
+ label = 108;
+ break;
+ } else {
+ $bb_sroa_1_5 = $cond914;
+ $sides_2 = $sides_1;
+ $bb_sroa_0_5 = $mul888_bb_sroa_0_4;
+ $vertices_0 = $61;
+ label = 109;
+ break;
+ }
+ case 109:
+ $regular921 = $call;
+ HEAP32[$regular921 >> 2] = $or;
+ $peripheries922 = $call + 4 | 0;
+ $67 = $peripheries922;
+ HEAP32[$67 >> 2] = $call98;
+ $sides923 = $call + 8 | 0;
+ $68 = $sides923;
+ HEAP32[$68 >> 2] = $sides_2;
+ $orientation924 = $call + 16 | 0;
+ $69 = $orientation924;
+ HEAPF64[$69 >> 3] = $add100;
+ $skew925 = $call + 32 | 0;
+ $70 = $skew925;
+ HEAPF64[$70 >> 3] = $skew_0;
+ $distortion926 = $call + 24 | 0;
+ $71 = $distortion926;
+ HEAPF64[$71 >> 3] = $distortion_0;
+ $vertices927 = $call + 44 | 0;
+ $72 = $vertices927;
+ HEAP32[$72 >> 2] = $vertices_0;
+ $div929 = $bb_sroa_0_5 / 72.0;
+ $width931 = $n + 48 | 0;
+ HEAPF64[$width931 >> 3] = $div929;
+ $div933 = $bb_sroa_1_5 / 72.0;
+ $height935 = $n + 56 | 0;
+ HEAPF64[$height935 >> 3] = $div933;
+ $shape_info = $n + 28 | 0;
+ HEAP32[$shape_info >> 2] = $call;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _isPolygon($n) {
+ $n = $n | 0;
+ var $shape = 0, $0 = 0, $tobool = 0, $fns = 0, $1 = 0, $initfn = 0, $2 = 0, $cmp = 0, $phitmp = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $shape = $n + 24 | 0;
+ $0 = HEAP32[$shape >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $3 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $fns = $0 + 4 | 0;
+ $1 = HEAP32[$fns >> 2] | 0;
+ $initfn = $1 | 0;
+ $2 = HEAP32[$initfn >> 2] | 0;
+ $cmp = ($2 | 0) == 476;
+ $phitmp = $cmp & 1;
+ $3 = $phitmp;
+ label = 4;
+ break;
+ case 4:
+ return $3 | 0;
+ }
+ return 0;
+}
+function _pointfof795($agg_result, $x, $y) {
+ $agg_result = $agg_result | 0;
+ $x = +$x;
+ $y = +$y;
+ HEAPF64[$agg_result >> 3] = $x;
+ HEAPF64[$agg_result + 8 >> 3] = $y;
+ return;
+}
+function _record_init($n) {
+ $n = $n | 0;
+ var $ul = 0, $sz = 0, $tmp = 0, $graph = 0, $0 = 0, $rankdir = 0, $1 = 0, $and = 0, $and_lobit = 0, $2 = 0, $label = 0, $3 = 0, $text = 0, $4 = 0, $call = 0, $cmp = 0, $call_op = 0, $add = 0, $call2 = 0, $call3 = 0, $tobool4 = 0, $5 = 0, $text7 = 0, $6 = 0, $call8 = 0, $call9 = 0, $info_0 = 0, $width = 0, $7 = 0.0, $mul11 = 0.0, $cmp12 = 0, $add17 = 0.0, $sub = 0.0, $add17_sink = 0.0, $conv = 0, $conv25 = 0.0, $x = 0, $height = 0, $8 = 0.0, $mul27 = 0.0, $cmp28 = 0, $add34 = 0.0, $sub40 = 0.0, $add34_sink = 0.0, $conv35 = 0, $conv44 = 0.0, $y = 0, $9 = 0, $10 = 0, $call45 = 0, $call46 = 0, $tobool47 = 0, $x61 = 0, $11 = 0.0, $12 = 0.0, $cmp63 = 0, $_ = 0.0, $y74 = 0, $13 = 0.0, $14 = 0.0, $cmp76 = 0, $cond84 = 0.0, $15 = 0, $call87 = 0, $call88 = 0, $conv89 = 0, $16 = 0.0, $div = 0.0, $17 = 0.0, $div93 = 0.0, $x96 = 0, $18 = 0.0, $div97 = 0.0, $y101 = 0, $19 = 0.0, $add102 = 0.0, $div103 = 0.0, $20 = 0, $shape_info = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ul = __stackBase__ | 0;
+ $sz = __stackBase__ + 16 | 0;
+ $tmp = __stackBase__ + 32 | 0;
+ $graph = $n + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $0 + 156 | 0;
+ $1 = HEAP32[$rankdir >> 2] | 0;
+ $and = $1 >>> 2;
+ $and_lobit = $and & 1;
+ $2 = $and_lobit ^ 1;
+ $label = $n + 120 | 0;
+ $3 = HEAP32[$label >> 2] | 0;
+ $text = $3 | 0;
+ $4 = HEAP32[$text >> 2] | 0;
+ HEAP32[1158] = $4;
+ $call = _strlen($4 | 0) | 0;
+ $cmp = ($call | 0) > 1;
+ $call_op = $call + 1 | 0;
+ $add = $cmp ? $call_op : 2;
+ $call2 = _zmalloc($add) | 0;
+ $call3 = _parse_reclbl($n, $2, 1, $call2) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 3;
+ break;
+ } else {
+ $info_0 = $call3;
+ label = 4;
+ break;
+ }
+ case 3:
+ $5 = HEAP32[$label >> 2] | 0;
+ $text7 = $5 | 0;
+ $6 = HEAP32[$text7 >> 2] | 0;
+ $call8 = _agerr(1, 100528, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $6, tempInt) | 0) | 0;
+ HEAP32[1158] = 100032;
+ $call9 = _parse_reclbl($n, $2, 1, $call2) | 0;
+ $info_0 = $call9;
+ label = 4;
+ break;
+ case 4:
+ _free($call2);
+ _size_reclbl($tmp, $n, $info_0);
+ $width = $n + 48 | 0;
+ $7 = +HEAPF64[$width >> 3];
+ $mul11 = $7 * 72.0;
+ $cmp12 = $mul11 < 0.0;
+ if ($cmp12) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add17 = $mul11 + .5;
+ $add17_sink = $add17;
+ label = 7;
+ break;
+ case 6:
+ $sub = $mul11 + -.5;
+ $add17_sink = $sub;
+ label = 7;
+ break;
+ case 7:
+ $conv = ~~$add17_sink;
+ $conv25 = +($conv | 0);
+ $x = $sz | 0;
+ HEAPF64[$x >> 3] = $conv25;
+ $height = $n + 56 | 0;
+ $8 = +HEAPF64[$height >> 3];
+ $mul27 = $8 * 72.0;
+ $cmp28 = $mul27 < 0.0;
+ if ($cmp28) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $add34 = $mul27 + .5;
+ $add34_sink = $add34;
+ label = 10;
+ break;
+ case 9:
+ $sub40 = $mul27 + -.5;
+ $add34_sink = $sub40;
+ label = 10;
+ break;
+ case 10:
+ $conv35 = ~~$add34_sink;
+ $conv44 = +($conv35 | 0);
+ $y = $sz + 8 | 0;
+ HEAPF64[$y >> 3] = $conv44;
+ $9 = $n | 0;
+ $10 = HEAP32[41602] | 0;
+ $call45 = _late_string($9, $10, 100880) | 0;
+ $call46 = _mapbool($call45) | 0;
+ $tobool47 = $call46 << 24 >> 24 == 0;
+ if ($tobool47) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $x61 = $info_0 | 0;
+ $11 = +HEAPF64[$x61 >> 3];
+ $12 = +HEAPF64[$x >> 3];
+ $cmp63 = $11 > $12;
+ $_ = $cmp63 ? $11 : $12;
+ HEAPF64[$x >> 3] = $_;
+ $y74 = $info_0 + 8 | 0;
+ $13 = +HEAPF64[$y74 >> 3];
+ $14 = +HEAPF64[$y >> 3];
+ $cmp76 = $13 > $14;
+ $cond84 = $cmp76 ? $13 : $14;
+ HEAPF64[$y >> 3] = $cond84;
+ label = 12;
+ break;
+ case 12:
+ $15 = HEAP32[41582] | 0;
+ $call87 = _late_string($9, $15, 100880) | 0;
+ $call88 = _mapbool($call87) | 0;
+ $conv89 = $call88 & 255;
+ _resize_reclbl($info_0, $sz, $conv89);
+ $16 = +HEAPF64[$x >> 3];
+ $div = $16 * -.5;
+ $17 = +HEAPF64[$y >> 3];
+ $div93 = $17 * .5;
+ _pointfof795($ul, $div, $div93);
+ _pos_reclbl($info_0, $ul, 15);
+ $x96 = $info_0 | 0;
+ $18 = +HEAPF64[$x96 >> 3];
+ $div97 = $18 / 72.0;
+ HEAPF64[$width >> 3] = $div97;
+ $y101 = $info_0 + 8 | 0;
+ $19 = +HEAPF64[$y101 >> 3];
+ $add102 = $19 + 1.0;
+ $div103 = $add102 / 72.0;
+ HEAPF64[$height >> 3] = $div103;
+ $20 = $info_0;
+ $shape_info = $n + 28 | 0;
+ HEAP32[$shape_info >> 2] = $20;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _point_init($n) {
+ $n = $n | 0;
+ var $call = 0, $shape = 0, $0 = 0, $polygon = 0, $1 = 0, $peripheries1 = 0, $2 = 0, $3 = 0, $4 = 0, $call2 = 0.0, $5 = 0, $call3 = 0.0, $cmp = 0, $cond = 0.0, $cmp4 = 0, $cmp5 = 0, $or_cond = 0, $height = 0, $width = 0, $width11 = 0, $width13 = 0, $6 = 0.0, $mul = 0.0, $7 = 0, $call14 = 0, $cmp15 = 0, $phitmp = 0, $outp_0 = 0, $call21 = 0, $8 = 0, $div = 0.0, $sub = 0.0, $x23 = 0, $y27 = 0, $9 = 0, $P_sroa_0_0__idx = 0, $10 = 0, $P_sroa_1_8__idx24 = 0, $11 = 0, $cmp29 = 0, $j_056 = 0, $i_055 = 0, $P_sroa_0_054 = 0.0, $P_sroa_1_053 = 0.0, $add = 0.0, $add34 = 0.0, $sub36 = 0.0, $x38 = 0, $sub40 = 0.0, $y42 = 0, $inc51 = 0, $x45 = 0, $y48 = 0, $inc49 = 0, $inc50 = 0, $cmp31 = 0, $mul52 = 0.0, $sz_0 = 0.0, $regular = 0, $peripheries54 = 0, $12 = 0, $sides55 = 0, $13 = 0, $orientation = 0, $vertices56 = 0, $14 = 0, $div57 = 0.0, $shape_info = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(48) | 0;
+ $shape = $n + 24 | 0;
+ $0 = HEAP32[$shape >> 2] | 0;
+ $polygon = $0 + 8 | 0;
+ $1 = HEAP32[$polygon >> 2] | 0;
+ $peripheries1 = $1 + 4 | 0;
+ $2 = HEAP32[$peripheries1 >> 2] | 0;
+ $3 = $n | 0;
+ $4 = HEAP32[41552] | 0;
+ $call2 = +_late_double($3, $4, 1.7976931348623157e+308, 3.0e-4);
+ $5 = HEAP32[41592] | 0;
+ $call3 = +_late_double($3, $5, 1.7976931348623157e+308, 3.0e-4);
+ $cmp = $call2 < $call3;
+ $cond = $cmp ? $call2 : $call3;
+ $cmp4 = $cond == 1.7976931348623157e+308;
+ $cmp5 = $call3 == 1.7976931348623157e+308;
+ $or_cond = $cmp4 & $cmp5;
+ $height = $n + 56 | 0;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAPF64[$height >> 3] = .05;
+ $width = $n + 48 | 0;
+ HEAPF64[$width >> 3] = .05;
+ label = 5;
+ break;
+ case 4:
+ HEAPF64[$height >> 3] = $cond;
+ $width11 = $n + 48 | 0;
+ HEAPF64[$width11 >> 3] = $cond;
+ label = 5;
+ break;
+ case 5:
+ $width13 = $n + 48 | 0;
+ $6 = +HEAPF64[$width13 >> 3];
+ $mul = $6 * 72.0;
+ $7 = HEAP32[41574] | 0;
+ $call14 = _late_int($3, $7, $2, 0) | 0;
+ $cmp15 = ($call14 | 0) < 1;
+ $phitmp = $call14 << 5;
+ $outp_0 = $cmp15 ? 32 : $phitmp;
+ $call21 = _zmalloc($outp_0) | 0;
+ $8 = $call21;
+ $div = $mul * .5;
+ $sub = -0.0 - $div;
+ $x23 = $call21;
+ HEAPF64[$x23 >> 3] = $sub;
+ $y27 = $call21 + 8 | 0;
+ $9 = $y27;
+ HEAPF64[$9 >> 3] = $sub;
+ $P_sroa_0_0__idx = $call21 + 16 | 0;
+ $10 = $P_sroa_0_0__idx;
+ HEAPF64[$10 >> 3] = $div;
+ $P_sroa_1_8__idx24 = $call21 + 24 | 0;
+ $11 = $P_sroa_1_8__idx24;
+ HEAPF64[$11 >> 3] = $div;
+ $cmp29 = ($call14 | 0) > 1;
+ if ($cmp29) {
+ $P_sroa_1_053 = $div;
+ $P_sroa_0_054 = $div;
+ $i_055 = 2;
+ $j_056 = 1;
+ label = 6;
+ break;
+ } else {
+ $sz_0 = $mul;
+ label = 8;
+ break;
+ }
+ case 6:
+ $add = $P_sroa_0_054 + 4.0;
+ $add34 = $P_sroa_1_053 + 4.0;
+ $sub36 = -0.0 - $add;
+ $x38 = $8 + ($i_055 << 4) | 0;
+ HEAPF64[$x38 >> 3] = $sub36;
+ $sub40 = -0.0 - $add34;
+ $y42 = $8 + ($i_055 << 4) + 8 | 0;
+ HEAPF64[$y42 >> 3] = $sub40;
+ $inc51 = $i_055 | 1;
+ $x45 = $8 + ($inc51 << 4) | 0;
+ HEAPF64[$x45 >> 3] = $add;
+ $y48 = $8 + ($inc51 << 4) + 8 | 0;
+ HEAPF64[$y48 >> 3] = $add34;
+ $inc49 = $i_055 + 2 | 0;
+ $inc50 = $j_056 + 1 | 0;
+ $cmp31 = ($inc50 | 0) < ($call14 | 0);
+ if ($cmp31) {
+ $P_sroa_1_053 = $add34;
+ $P_sroa_0_054 = $add;
+ $i_055 = $inc49;
+ $j_056 = $inc50;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $mul52 = $add * 2.0;
+ $sz_0 = $mul52;
+ label = 8;
+ break;
+ case 8:
+ $regular = $call;
+ HEAP32[$regular >> 2] = 1;
+ $peripheries54 = $call + 4 | 0;
+ $12 = $peripheries54;
+ HEAP32[$12 >> 2] = $call14;
+ $sides55 = $call + 8 | 0;
+ $13 = $sides55;
+ HEAP32[$13 >> 2] = 2;
+ $orientation = $call + 16 | 0;
+ $vertices56 = $call + 44 | 0;
+ $14 = $vertices56;
+ _memset($orientation | 0, 0, 24);
+ HEAP32[$14 >> 2] = $8;
+ $div57 = $sz_0 / 72.0;
+ HEAPF64[$width13 >> 3] = $div57;
+ HEAPF64[$height >> 3] = $div57;
+ $shape_info = $n + 28 | 0;
+ HEAP32[$shape_info >> 2] = $call;
+ return;
+ }
+}
+function _find_user_shape($name) {
+ $name = $name | 0;
+ var $0 = 0, $tobool = 0, $1 = 0, $cmp6 = 0, $or_cond = 0, $2 = 0, $3 = 0, $4 = 0, $i_07 = 0, $arrayidx = 0, $5 = 0, $name1 = 0, $6 = 0, $7 = 0, $cmp3 = 0, $call = 0, $tobool7 = 0, $inc = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41230] | 0;
+ $tobool = ($0 | 0) != 0;
+ $1 = HEAP32[41622] | 0;
+ $cmp6 = ($1 | 0) > 0;
+ $or_cond = $tobool & $cmp6;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[41230] | 0;
+ $3 = HEAP8[$name] | 0;
+ $4 = HEAP32[41622] | 0;
+ $i_07 = 0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $2 + ($i_07 << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $name1 = $5 | 0;
+ $6 = HEAP32[$name1 >> 2] | 0;
+ $7 = HEAP8[$6] | 0;
+ $cmp3 = $7 << 24 >> 24 == $3 << 24 >> 24;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call = _strcmp($6 | 0, $name | 0) | 0;
+ $tobool7 = ($call | 0) == 0;
+ if ($tobool7) {
+ $retval_0 = $5;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $inc = $i_07 + 1 | 0;
+ $cmp = ($inc | 0) < ($4 | 0);
+ if ($cmp) {
+ $i_07 = $inc;
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ }
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _bind_shape($name, $np) {
+ $name = $name | 0;
+ $np = $np | 0;
+ var $0 = 0, $call = 0, $call1 = 0, $tobool = 0, $1 = 0, $cmp = 0, $call5 = 0, $tobool6 = 0, $name_addr_0 = 0, $2 = 0, $cmp9 = 0, $call12 = 0, $tobool13 = 0, $3 = 0, $tobool1614 = 0, $4 = 0, $5 = 0, $ptr_015 = 0, $6 = 0, $cmp20 = 0, $call24 = 0, $tobool25 = 0, $incdec_ptr = 0, $name15 = 0, $7 = 0, $tobool16 = 0, $cmp29 = 0, $call32 = 0, $rv_1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $np | 0;
+ $call = _agget($0, 120672) | 0;
+ $call1 = _safefile($call) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ $name_addr_0 = $name;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$name] | 0;
+ $cmp = $1 << 24 >> 24 == 101;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call5 = _strcmp($name | 0, 115056) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ $name_addr_0 = $name;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $name_addr_0 = 110216;
+ label = 6;
+ break;
+ case 6:
+ $2 = HEAP8[$name_addr_0] | 0;
+ $cmp9 = $2 << 24 >> 24 == 99;
+ if ($cmp9) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call12 = _strcmp($name_addr_0 | 0, 110216) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ label = 14;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $3 = HEAP32[41364] | 0;
+ $tobool1614 = ($3 | 0) == 0;
+ if ($tobool1614) {
+ label = 14;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $4 = HEAP8[$name_addr_0] | 0;
+ $ptr_015 = 165456;
+ $5 = $3;
+ label = 10;
+ break;
+ case 10:
+ $6 = HEAP8[$5] | 0;
+ $cmp20 = $6 << 24 >> 24 == $4 << 24 >> 24;
+ if ($cmp20) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $call24 = _strcmp($5 | 0, $name_addr_0 | 0) | 0;
+ $tobool25 = ($call24 | 0) == 0;
+ if ($tobool25) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $incdec_ptr = $ptr_015 + 16 | 0;
+ $name15 = $incdec_ptr | 0;
+ $7 = HEAP32[$name15 >> 2] | 0;
+ $tobool16 = ($7 | 0) == 0;
+ if ($tobool16) {
+ label = 14;
+ break;
+ } else {
+ $ptr_015 = $incdec_ptr;
+ $5 = $7;
+ label = 10;
+ break;
+ }
+ case 13:
+ $cmp29 = ($ptr_015 | 0) == 0;
+ if ($cmp29) {
+ label = 14;
+ break;
+ } else {
+ $rv_1 = $ptr_015;
+ label = 15;
+ break;
+ }
+ case 14:
+ $call32 = _user_shape($name_addr_0) | 0;
+ $rv_1 = $call32;
+ label = 15;
+ break;
+ case 15:
+ return $rv_1 | 0;
+ }
+ return 0;
+}
+function _user_shape($name) {
+ $name = $name | 0;
+ var $call = 0, $tobool = 0, $0 = 0, $inc = 0, $1 = 0, $tobool1 = 0, $2 = 0, $mul = 0, $call2 = 0, $mul3 = 0, $call4 = 0, $call2_sink = 0, $3 = 0, $call5 = 0, $4 = 0, $5 = 0, $arrayidx = 0, $call6 = 0, $name7 = 0, $6 = 0, $cmp = 0, $7 = 0, $cmp9 = 0, $call12 = 0, $tobool13 = 0, $8 = 0, $9 = 0, $call16 = 0, $10 = 0, $11 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _find_user_shape($name) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = $call;
+ label = 11;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[41622] | 0;
+ $inc = $0 + 1 | 0;
+ HEAP32[41622] = $inc;
+ $1 = HEAP32[41230] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = $1;
+ $mul = $inc << 2;
+ $call2 = _grealloc($2, $mul) | 0;
+ $call2_sink = $call2;
+ label = 6;
+ break;
+ case 5:
+ $mul3 = $inc << 2;
+ $call4 = _gmalloc($mul3) | 0;
+ $call2_sink = $call4;
+ label = 6;
+ break;
+ case 6:
+ $3 = $call2_sink;
+ HEAP32[41230] = $3;
+ $call5 = _zmalloc(16) | 0;
+ $4 = $call5;
+ $5 = HEAP32[41230] | 0;
+ $arrayidx = $5 + ($0 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $4;
+ HEAP32[$call5 >> 2] = HEAP32[41364] | 0;
+ HEAP32[$call5 + 4 >> 2] = HEAP32[41365] | 0;
+ HEAP32[$call5 + 8 >> 2] = HEAP32[41366] | 0;
+ HEAP32[$call5 + 12 >> 2] = HEAP32[41367] | 0;
+ $call6 = _strdup($name | 0) | 0;
+ $name7 = $call5;
+ HEAP32[$name7 >> 2] = $call6;
+ $6 = HEAP32[41648] | 0;
+ $cmp = ($6 | 0) == 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $7 = HEAP8[$name] | 0;
+ $cmp9 = $7 << 24 >> 24 == 99;
+ if ($cmp9) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $call12 = _strcmp($name | 0, 110216) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $8 = HEAP32[41364] | 0;
+ $9 = HEAP32[$name7 >> 2] | 0;
+ $call16 = _agerr(0, 90624, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $8, HEAP32[tempInt + 8 >> 2] = $9, tempInt) | 0) | 0;
+ $10 = $call5 + 12 | 0;
+ HEAP8[$10] = 0;
+ $retval_0 = $4;
+ label = 11;
+ break;
+ case 10:
+ $11 = $call5 + 12 | 0;
+ HEAP8[$11] = 1;
+ $retval_0 = $4;
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _resolvePort($agg_result, $n, $other, $oldport) {
+ $agg_result = $agg_result | 0;
+ $n = $n | 0;
+ $other = $other | 0;
+ $oldport = $oldport | 0;
+ var $rv = 0, $call = 0, $3 = 0, $4 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ $rv = __stackBase__ | 0;
+ $call = _closestSide($n, $other, $oldport) | 0;
+ HEAP32[$rv + 36 >> 2] = HEAP32[$oldport + 36 >> 2] | 0;
+ _compassPort($n, HEAP32[$oldport + 24 >> 2] | 0, $rv, $call, HEAPU8[$oldport + 33 | 0] | 0, 0);
+ $3 = $agg_result;
+ $4 = $rv;
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ HEAP32[$3 + 16 >> 2] = HEAP32[$4 + 16 >> 2] | 0;
+ HEAP32[$3 + 20 >> 2] = HEAP32[$4 + 20 >> 2] | 0;
+ HEAP32[$3 + 24 >> 2] = HEAP32[$4 + 24 >> 2] | 0;
+ HEAP32[$3 + 28 >> 2] = HEAP32[$4 + 28 >> 2] | 0;
+ HEAP32[$3 + 32 >> 2] = HEAP32[$4 + 32 >> 2] | 0;
+ HEAP32[$3 + 36 >> 2] = HEAP32[$4 + 36 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _closestSide($n, $other, $oldport) {
+ $n = $n | 0;
+ $other = $other | 0;
+ $oldport = $oldport | 0;
+ var $pt = 0, $opt = 0, $graph = 0, $0 = 0, $root = 0, $1 = 0, $rankdir = 0, $2 = 0, $and = 0, $coord = 0, $coord3 = 0, $side = 0, $3 = 0, $conv = 0, $bp = 0, $4 = 0, $tobool = 0, $b_sroa_0_0__idx = 0, $b_sroa_0_0_copyload = 0.0, $b_sroa_1_8__idx17 = 0, $b_sroa_1_8_copyload = 0.0, $b_sroa_2_16__idx20 = 0, $b_sroa_2_16_copyload = 0.0, $b_sroa_3_24__idx25 = 0, $b_sroa_3_24_copyload = 0.0, $5 = 0, $rankdir11 = 0, $6 = 0, $and13 = 0, $tobool14 = 0, $ht = 0, $7 = 0.0, $div = 0.0, $sub35 = 0.0, $lw39 = 0, $8 = 0.0, $sub44 = 0.0, $sub35_sub44 = 0.0, $sub44_sub35 = 0.0, $_div = 0.0, $div_ = 0.0, $b_sroa_1_0 = 0.0, $b_sroa_0_0 = 0.0, $b_sroa_2_0 = 0.0, $b_sroa_3_0 = 0.0, $x106 = 0, $9 = 0, $y109 = 0, $10 = 0, $x113 = 0, $11 = 0, $y119 = 0, $12 = 0, $conv70 = 0, $add76 = 0.0, $div77 = 0.0, $conv78 = 0, $conv83 = 0, $add89 = 0.0, $div90 = 0.0, $conv91 = 0, $conv96 = 0, $add102 = 0.0, $div103 = 0.0, $conv104 = 0, $and51 = 0, $cmp52 = 0, $add = 0.0, $div64 = 0.0, $conv65 = 0, $conv58 = 0, $add108 = 0, $add111 = 0, $sub114 = 0, $sub120 = 0, $mul124 = 0, $mul = 0, $add125 = 0, $rv_1 = 0, $mind_1 = 0, $and51_1 = 0, $cmp52_1 = 0, $retval_0 = 0, $add108_1 = 0, $add111_1 = 0, $sub114_1 = 0, $mul_1 = 0, $sub120_1 = 0, $mul124_1 = 0, $add125_1 = 0, $tobool126_1 = 0, $cmp128_1 = 0, $or_cond_1 = 0, $_rv_1 = 0, $add125_1_mind_1 = 0, $rv_1_1 = 0, $mind_1_1 = 0, $and51_2 = 0, $cmp52_2 = 0, $add108_2 = 0, $add111_2 = 0, $sub114_2 = 0, $mul_2 = 0, $sub120_2 = 0, $mul124_2 = 0, $add125_2 = 0, $tobool126_2 = 0, $cmp128_2 = 0, $or_cond_2 = 0, $_rv_1_1 = 0, $add125_2_mind_1_1 = 0, $rv_1_2 = 0, $mind_1_2 = 0, $and51_3 = 0, $cmp52_3 = 0, $add108_3 = 0, $add111_3 = 0, $sub114_3 = 0, $mul_3 = 0, $sub120_3 = 0, $mul124_3 = 0, $add125_3 = 0, $tobool126_3 = 0, $cmp128_3 = 0, $or_cond_3 = 0, $_rv_1_2 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pt = __stackBase__ | 0;
+ $opt = __stackBase__ + 8 | 0;
+ $graph = $n + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ $root = $0 + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $rankdir = $1 + 156 | 0;
+ $2 = HEAP32[$rankdir >> 2] | 0;
+ $and = $2 & 3;
+ $coord = $n + 32 | 0;
+ _cvtPt($pt, $coord, $and);
+ $coord3 = $other + 32 | 0;
+ _cvtPt($opt, $coord3, $and);
+ $side = $oldport + 33 | 0;
+ $3 = HEAP8[$side] | 0;
+ $conv = $3 & 255;
+ if (($3 << 24 >> 24 | 0) == 15 | ($3 << 24 >> 24 | 0) == 0) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $bp = $oldport + 24 | 0;
+ $4 = HEAP32[$bp >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $b_sroa_0_0__idx = $4 | 0;
+ $b_sroa_0_0_copyload = +HEAPF64[$b_sroa_0_0__idx >> 3];
+ $b_sroa_1_8__idx17 = $4 + 8 | 0;
+ $b_sroa_1_8_copyload = +HEAPF64[$b_sroa_1_8__idx17 >> 3];
+ $b_sroa_2_16__idx20 = $4 + 16 | 0;
+ $b_sroa_2_16_copyload = +HEAPF64[$b_sroa_2_16__idx20 >> 3];
+ $b_sroa_3_24__idx25 = $4 + 24 | 0;
+ $b_sroa_3_24_copyload = +HEAPF64[$b_sroa_3_24__idx25 >> 3];
+ $b_sroa_3_0 = $b_sroa_3_24_copyload;
+ $b_sroa_2_0 = $b_sroa_2_16_copyload;
+ $b_sroa_0_0 = $b_sroa_0_0_copyload;
+ $b_sroa_1_0 = $b_sroa_1_8_copyload;
+ label = 6;
+ break;
+ case 5:
+ $5 = HEAP32[$graph >> 2] | 0;
+ $rankdir11 = $5 + 156 | 0;
+ $6 = HEAP32[$rankdir11 >> 2] | 0;
+ $and13 = $6 & 1;
+ $tobool14 = ($and13 | 0) == 0;
+ $ht = $n + 96 | 0;
+ $7 = +HEAPF64[$ht >> 3];
+ $div = $7 * .5;
+ $sub35 = -0.0 - $div;
+ $lw39 = $n + 104 | 0;
+ $8 = +HEAPF64[$lw39 >> 3];
+ $sub44 = -0.0 - $8;
+ $sub35_sub44 = $tobool14 ? $sub35 : $sub44;
+ $sub44_sub35 = $tobool14 ? $sub44 : $sub35;
+ $_div = $tobool14 ? $8 : $div;
+ $div_ = $tobool14 ? $div : $8;
+ $b_sroa_3_0 = $div_;
+ $b_sroa_2_0 = $_div;
+ $b_sroa_0_0 = $sub44_sub35;
+ $b_sroa_1_0 = $sub35_sub44;
+ label = 6;
+ break;
+ case 6:
+ $x106 = $pt | 0;
+ $9 = HEAP32[$x106 >> 2] | 0;
+ $y109 = $pt + 4 | 0;
+ $10 = HEAP32[$y109 >> 2] | 0;
+ $x113 = $opt | 0;
+ $11 = HEAP32[$x113 >> 2] | 0;
+ $y119 = $opt + 4 | 0;
+ $12 = HEAP32[$y119 >> 2] | 0;
+ $conv70 = ~~$b_sroa_2_0;
+ $add76 = $b_sroa_1_0 + $b_sroa_3_0;
+ $div77 = $add76 * .5;
+ $conv78 = ~~$div77;
+ $conv83 = ~~$b_sroa_3_0;
+ $add89 = $b_sroa_0_0 + $b_sroa_2_0;
+ $div90 = $add89 * .5;
+ $conv91 = ~~$div90;
+ $conv96 = ~~$b_sroa_0_0;
+ $add102 = $b_sroa_1_0 + $b_sroa_3_0;
+ $div103 = $add102 * .5;
+ $conv104 = ~~$div103;
+ $and51 = $conv & 1;
+ $cmp52 = ($and51 | 0) == 0;
+ if ($cmp52) {
+ $mind_1 = 0;
+ $rv_1 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add = $b_sroa_0_0 + $b_sroa_2_0;
+ $div64 = $add * .5;
+ $conv65 = ~~$div64;
+ $conv58 = ~~$b_sroa_1_0;
+ $add108 = $9 + $conv65 | 0;
+ $add111 = $10 + $conv58 | 0;
+ $sub114 = $add108 - $11 | 0;
+ $sub120 = $add111 - $12 | 0;
+ $mul124 = Math_imul($sub120, $sub120);
+ $mul = Math_imul($sub114, $sub114);
+ $add125 = $mul124 + $mul | 0;
+ $mind_1 = $add125;
+ $rv_1 = 106048;
+ label = 8;
+ break;
+ case 8:
+ $and51_1 = $conv & 2;
+ $cmp52_1 = ($and51_1 | 0) == 0;
+ if ($cmp52_1) {
+ $mind_1_1 = $mind_1;
+ $rv_1_1 = $rv_1;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ case 10:
+ $add108_1 = $9 + $conv70 | 0;
+ $add111_1 = $10 + $conv78 | 0;
+ $sub114_1 = $add108_1 - $11 | 0;
+ $mul_1 = Math_imul($sub114_1, $sub114_1);
+ $sub120_1 = $add111_1 - $12 | 0;
+ $mul124_1 = Math_imul($sub120_1, $sub120_1);
+ $add125_1 = $mul124_1 + $mul_1 | 0;
+ $tobool126_1 = ($rv_1 | 0) == 0;
+ $cmp128_1 = ($add125_1 | 0) < ($mind_1 | 0);
+ $or_cond_1 = $tobool126_1 | $cmp128_1;
+ $_rv_1 = $or_cond_1 ? 102144 : $rv_1;
+ $add125_1_mind_1 = $or_cond_1 ? $add125_1 : $mind_1;
+ $mind_1_1 = $add125_1_mind_1;
+ $rv_1_1 = $_rv_1;
+ label = 11;
+ break;
+ case 11:
+ $and51_2 = $conv & 4;
+ $cmp52_2 = ($and51_2 | 0) == 0;
+ if ($cmp52_2) {
+ $mind_1_2 = $mind_1_1;
+ $rv_1_2 = $rv_1_1;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $add108_2 = $9 + $conv91 | 0;
+ $add111_2 = $10 + $conv83 | 0;
+ $sub114_2 = $add108_2 - $11 | 0;
+ $mul_2 = Math_imul($sub114_2, $sub114_2);
+ $sub120_2 = $add111_2 - $12 | 0;
+ $mul124_2 = Math_imul($sub120_2, $sub120_2);
+ $add125_2 = $mul124_2 + $mul_2 | 0;
+ $tobool126_2 = ($rv_1_1 | 0) == 0;
+ $cmp128_2 = ($add125_2 | 0) < ($mind_1_1 | 0);
+ $or_cond_2 = $tobool126_2 | $cmp128_2;
+ $_rv_1_1 = $or_cond_2 ? 97864 : $rv_1_1;
+ $add125_2_mind_1_1 = $or_cond_2 ? $add125_2 : $mind_1_1;
+ $mind_1_2 = $add125_2_mind_1_1;
+ $rv_1_2 = $_rv_1_1;
+ label = 13;
+ break;
+ case 13:
+ $and51_3 = $conv & 8;
+ $cmp52_3 = ($and51_3 | 0) == 0;
+ if ($cmp52_3) {
+ $retval_0 = $rv_1_2;
+ label = 9;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $add108_3 = $9 + $conv96 | 0;
+ $add111_3 = $10 + $conv104 | 0;
+ $sub114_3 = $add108_3 - $11 | 0;
+ $mul_3 = Math_imul($sub114_3, $sub114_3);
+ $sub120_3 = $add111_3 - $12 | 0;
+ $mul124_3 = Math_imul($sub120_3, $sub120_3);
+ $add125_3 = $mul124_3 + $mul_3 | 0;
+ $tobool126_3 = ($rv_1_2 | 0) == 0;
+ $cmp128_3 = ($add125_3 | 0) < ($mind_1_2 | 0);
+ $or_cond_3 = $tobool126_3 | $cmp128_3;
+ $_rv_1_2 = $or_cond_3 ? 94128 : $rv_1_2;
+ STACKTOP = __stackBase__;
+ return $_rv_1_2 | 0;
+ }
+ return 0;
+}
+function _compassPort($n, $bp, $pp, $compass, $sides, $ictxt) {
+ $n = $n | 0;
+ $bp = $bp | 0;
+ $pp = $pp | 0;
+ $compass = $compass | 0;
+ $sides = $sides | 0;
+ $ictxt = $ictxt | 0;
+ var $p = 0, $tmp155 = 0, $tobool = 0, $b_sroa_0_0__idx = 0, $b_sroa_0_0_copyload = 0.0, $b_sroa_1_8__idx12 = 0, $b_sroa_1_8_copyload = 0.0, $b_sroa_2_16__idx14 = 0, $b_sroa_2_16_copyload = 0.0, $b_sroa_3_24__idx20 = 0, $b_sroa_3_24_copyload = 0.0, $add = 0.0, $div = 0.0, $add5 = 0.0, $div6 = 0.0, $graph = 0, $0 = 0, $1 = 0, $rankdir = 0, $2 = 0, $and9 = 0, $tobool10 = 0, $ht = 0, $3 = 0.0, $div13 = 0.0, $lw40 = 0, $4 = 0.0, $_div13 = 0.0, $div13_ = 0.0, $b_sroa_0_0 = 0.0, $b_sroa_1_0 = 0.0, $b_sroa_2_1 = 0.0, $b_sroa_1_1 = 0.0, $b_sroa_0_1 = 0.0, $b_sroa_3_1 = 0.0, $defined_0 = 0, $ctr_sroa_0_0__idx = 0, $ctr_sroa_0_0_copyload = 0.0, $ctr_sroa_1_8__idx8 = 0, $ctr_sroa_1_8_copyload = 0.0, $tobool49 = 0, $5 = 0, $tobool50 = 0, $conv = 0, $incdec_ptr = 0, $6 = 0, $tobool53 = 0, $and59 = 0, $7 = 0, $conv65 = 0, $tobool67 = 0, $and75 = 0, $tobool77 = 0, $and85 = 0, $tobool87 = 0, $and95 = 0, $8 = 0, $tobool99 = 0, $and105 = 0, $9 = 0, $conv111 = 0, $tobool113 = 0, $and121 = 0, $tobool123 = 0, $and131 = 0, $tobool133 = 0, $and141 = 0, $rv_0 = 0, $theta_0 = 0.0, $constrain_0 = 0, $dyna_0 = 0, $side_0 = 0, $clip_0 = 0, $defined_1 = 0, $graph151 = 0, $10 = 0, $rankdir153 = 0, $11 = 0, $and154 = 0, $mul = 0, $12 = 0, $13 = 0, $tobool156 = 0, $conv158 = 0, $side159 = 0, $14 = 0, $rankdir163 = 0, $15 = 0, $and164 = 0, $call = 0, $conv165 = 0, $side166 = 0, $bp168 = 0, $16 = 0.0, $cmp = 0, $add172 = 0.0, $sub175 = 0.0, $add172_sink = 0.0, $conv173 = 0, $conv177 = 0.0, $x179 = 0, $17 = 0.0, $cmp181 = 0, $add185 = 0.0, $sub189 = 0.0, $add185_sink = 0.0, $conv186 = 0, $conv193 = 0.0, $y195 = 0, $18 = 0, $rankdir198 = 0, $19 = 0, $and199 = 0, $call200 = 0.0, $theta201 = 0, $20 = 0.0, $cmp203 = 0, $21 = 0.0, $cmp207 = 0, $order = 0, $22 = 0.0, $23 = 0.0, $call214 = 0.0, $add215 = 0.0, $cmp216 = 0, $sub219 = 0.0, $angle_0 = 0.0, $mul221 = 0.0, $div222 = 0.0, $conv223 = 0, $conv224 = 0, $order225 = 0, $constrained = 0, $defined227 = 0, $clip228 = 0, $dyna229 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p = __stackBase__ | 0;
+ $tmp155 = __stackBase__ + 16 | 0;
+ $tobool = ($bp | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $b_sroa_0_0__idx = $bp | 0;
+ $b_sroa_0_0_copyload = +HEAPF64[$b_sroa_0_0__idx >> 3];
+ $b_sroa_1_8__idx12 = $bp + 8 | 0;
+ $b_sroa_1_8_copyload = +HEAPF64[$b_sroa_1_8__idx12 >> 3];
+ $b_sroa_2_16__idx14 = $bp + 16 | 0;
+ $b_sroa_2_16_copyload = +HEAPF64[$b_sroa_2_16__idx14 >> 3];
+ $b_sroa_3_24__idx20 = $bp + 24 | 0;
+ $b_sroa_3_24_copyload = +HEAPF64[$b_sroa_3_24__idx20 >> 3];
+ $add = $b_sroa_0_0_copyload + $b_sroa_2_16_copyload;
+ $div = $add * .5;
+ $add5 = $b_sroa_1_8_copyload + $b_sroa_3_24_copyload;
+ $div6 = $add5 * .5;
+ _pointfof795($p, $div, $div6);
+ $defined_0 = 1;
+ $b_sroa_3_1 = $b_sroa_3_24_copyload;
+ $b_sroa_0_1 = $b_sroa_0_0_copyload;
+ $b_sroa_1_1 = $b_sroa_1_8_copyload;
+ $b_sroa_2_1 = $b_sroa_2_16_copyload;
+ label = 5;
+ break;
+ case 4:
+ $graph = $n + 20 | 0;
+ $0 = $p;
+ _memset($0 | 0, 0, 16);
+ $1 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $1 + 156 | 0;
+ $2 = HEAP32[$rankdir >> 2] | 0;
+ $and9 = $2 & 1;
+ $tobool10 = ($and9 | 0) == 0;
+ $ht = $n + 96 | 0;
+ $3 = +HEAPF64[$ht >> 3];
+ $div13 = $3 * .5;
+ $lw40 = $n + 104 | 0;
+ $4 = +HEAPF64[$lw40 >> 3];
+ $_div13 = $tobool10 ? $4 : $div13;
+ $div13_ = $tobool10 ? $div13 : $4;
+ $b_sroa_0_0 = -0.0 - $_div13;
+ $b_sroa_1_0 = -0.0 - $div13_;
+ $defined_0 = 0;
+ $b_sroa_3_1 = $div13_;
+ $b_sroa_0_1 = $b_sroa_0_0;
+ $b_sroa_1_1 = $b_sroa_1_0;
+ $b_sroa_2_1 = $_div13;
+ label = 5;
+ break;
+ case 5:
+ $ctr_sroa_0_0__idx = $p | 0;
+ $ctr_sroa_0_0_copyload = +HEAPF64[$ctr_sroa_0_0__idx >> 3];
+ $ctr_sroa_1_8__idx8 = $p + 8 | 0;
+ $ctr_sroa_1_8_copyload = +HEAPF64[$ctr_sroa_1_8__idx8 >> 3];
+ $tobool49 = ($compass | 0) == 0;
+ if ($tobool49) {
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = 0;
+ $dyna_0 = 0;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $5 = HEAP8[$compass] | 0;
+ $tobool50 = $5 << 24 >> 24 == 0;
+ if ($tobool50) {
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = 0;
+ $dyna_0 = 0;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $conv = $5 << 24 >> 24;
+ $incdec_ptr = $compass + 1 | 0;
+ if (($conv | 0) == 101) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 115) {
+ label = 10;
+ break;
+ } else if (($conv | 0) == 119) {
+ label = 24;
+ break;
+ } else if (($conv | 0) == 110) {
+ label = 26;
+ break;
+ } else if (($conv | 0) == 95) {
+ label = 40;
+ break;
+ } else if (($conv | 0) == 99) {
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = 0;
+ $dyna_0 = 0;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 8:
+ $6 = HEAP8[$incdec_ptr] | 0;
+ $tobool53 = $6 << 24 >> 24 == 0;
+ if ($tobool53) {
+ label = 9;
+ break;
+ } else {
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = 0;
+ $dyna_0 = 0;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 1;
+ label = 42;
+ break;
+ }
+ case 9:
+ HEAPF64[$ctr_sroa_0_0__idx >> 3] = $b_sroa_2_1;
+ $and59 = $sides & 2;
+ $defined_1 = 1;
+ $clip_0 = 0;
+ $side_0 = $and59;
+ $dyna_0 = 0;
+ $constrain_0 = 1;
+ $theta_0 = 0.0;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 10:
+ HEAPF64[$ctr_sroa_1_8__idx8 >> 3] = $b_sroa_1_1;
+ $7 = HEAP8[$incdec_ptr] | 0;
+ $conv65 = $7 << 24 >> 24;
+ if (($conv65 | 0) == 0) {
+ label = 11;
+ break;
+ } else if (($conv65 | 0) == 101) {
+ label = 15;
+ break;
+ } else if (($conv65 | 0) == 119) {
+ label = 19;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 11:
+ $tobool67 = ($ictxt | 0) == 0;
+ if ($tobool67) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _compassPoint($p, $ictxt, -2147483647.0, $ctr_sroa_0_0_copyload);
+ label = 14;
+ break;
+ case 13:
+ HEAPF64[$ctr_sroa_0_0__idx >> 3] = $ctr_sroa_0_0_copyload;
+ label = 14;
+ break;
+ case 14:
+ $and75 = $sides & 1;
+ $defined_1 = 1;
+ $clip_0 = 0;
+ $side_0 = $and75;
+ $dyna_0 = 0;
+ $constrain_0 = 1;
+ $theta_0 = -1.5707963267948966;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 15:
+ $tobool77 = ($ictxt | 0) == 0;
+ if ($tobool77) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ _compassPoint($p, $ictxt, -2147483647.0, 2147483647.0);
+ label = 18;
+ break;
+ case 17:
+ HEAPF64[$ctr_sroa_0_0__idx >> 3] = $b_sroa_2_1;
+ label = 18;
+ break;
+ case 18:
+ $and85 = $sides & 3;
+ $defined_1 = 1;
+ $clip_0 = 0;
+ $side_0 = $and85;
+ $dyna_0 = 0;
+ $constrain_0 = 1;
+ $theta_0 = -.7853981633974483;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 19:
+ $tobool87 = ($ictxt | 0) == 0;
+ if ($tobool87) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ _compassPoint($p, $ictxt, -2147483647.0, -2147483647.0);
+ label = 22;
+ break;
+ case 21:
+ HEAPF64[$ctr_sroa_0_0__idx >> 3] = $b_sroa_0_1;
+ label = 22;
+ break;
+ case 22:
+ $and95 = $sides & 9;
+ $defined_1 = 1;
+ $clip_0 = 0;
+ $side_0 = $and95;
+ $dyna_0 = 0;
+ $constrain_0 = 1;
+ $theta_0 = -2.356194490192345;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 23:
+ HEAPF64[$ctr_sroa_1_8__idx8 >> 3] = $ctr_sroa_1_8_copyload;
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = 0;
+ $dyna_0 = 0;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 1;
+ label = 42;
+ break;
+ case 24:
+ $8 = HEAP8[$incdec_ptr] | 0;
+ $tobool99 = $8 << 24 >> 24 == 0;
+ if ($tobool99) {
+ label = 25;
+ break;
+ } else {
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = 0;
+ $dyna_0 = 0;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 1;
+ label = 42;
+ break;
+ }
+ case 25:
+ HEAPF64[$ctr_sroa_0_0__idx >> 3] = $b_sroa_0_1;
+ $and105 = $sides & 8;
+ $defined_1 = 1;
+ $clip_0 = 0;
+ $side_0 = $and105;
+ $dyna_0 = 0;
+ $constrain_0 = 1;
+ $theta_0 = 3.141592653589793;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 26:
+ HEAPF64[$ctr_sroa_1_8__idx8 >> 3] = $b_sroa_3_1;
+ $9 = HEAP8[$incdec_ptr] | 0;
+ $conv111 = $9 << 24 >> 24;
+ if (($conv111 | 0) == 0) {
+ label = 27;
+ break;
+ } else if (($conv111 | 0) == 101) {
+ label = 31;
+ break;
+ } else if (($conv111 | 0) == 119) {
+ label = 35;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 27:
+ $tobool113 = ($ictxt | 0) == 0;
+ if ($tobool113) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ _compassPoint($p, $ictxt, 2147483647.0, $ctr_sroa_0_0_copyload);
+ label = 30;
+ break;
+ case 29:
+ HEAPF64[$ctr_sroa_0_0__idx >> 3] = $ctr_sroa_0_0_copyload;
+ label = 30;
+ break;
+ case 30:
+ $and121 = $sides & 4;
+ $defined_1 = 1;
+ $clip_0 = 0;
+ $side_0 = $and121;
+ $dyna_0 = 0;
+ $constrain_0 = 1;
+ $theta_0 = 1.5707963267948966;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 31:
+ $tobool123 = ($ictxt | 0) == 0;
+ if ($tobool123) {
+ label = 33;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ _compassPoint($p, $ictxt, 2147483647.0, 2147483647.0);
+ label = 34;
+ break;
+ case 33:
+ HEAPF64[$ctr_sroa_0_0__idx >> 3] = $b_sroa_2_1;
+ label = 34;
+ break;
+ case 34:
+ $and131 = $sides & 6;
+ $defined_1 = 1;
+ $clip_0 = 0;
+ $side_0 = $and131;
+ $dyna_0 = 0;
+ $constrain_0 = 1;
+ $theta_0 = .7853981633974483;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 35:
+ $tobool133 = ($ictxt | 0) == 0;
+ if ($tobool133) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ _compassPoint($p, $ictxt, 2147483647.0, -2147483647.0);
+ label = 38;
+ break;
+ case 37:
+ HEAPF64[$ctr_sroa_0_0__idx >> 3] = $b_sroa_0_1;
+ label = 38;
+ break;
+ case 38:
+ $and141 = $sides & 12;
+ $defined_1 = 1;
+ $clip_0 = 0;
+ $side_0 = $and141;
+ $dyna_0 = 0;
+ $constrain_0 = 1;
+ $theta_0 = 2.356194490192345;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 39:
+ HEAPF64[$ctr_sroa_1_8__idx8 >> 3] = $ctr_sroa_1_8_copyload;
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = 0;
+ $dyna_0 = 0;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 1;
+ label = 42;
+ break;
+ case 40:
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = $sides;
+ $dyna_0 = 1;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 0;
+ label = 42;
+ break;
+ case 41:
+ $defined_1 = $defined_0;
+ $clip_0 = 1;
+ $side_0 = 0;
+ $dyna_0 = 0;
+ $constrain_0 = 0;
+ $theta_0 = 0.0;
+ $rv_0 = 1;
+ label = 42;
+ break;
+ case 42:
+ $graph151 = $n + 20 | 0;
+ $10 = HEAP32[$graph151 >> 2] | 0;
+ $rankdir153 = $10 + 156 | 0;
+ $11 = HEAP32[$rankdir153 >> 2] | 0;
+ $and154 = $11 & 3;
+ $mul = $and154 * 90 & -1;
+ _cwrotatepf($tmp155, $p, $mul);
+ $12 = $p;
+ $13 = $tmp155;
+ HEAP32[$12 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ $tobool156 = $dyna_0 << 24 >> 24 == 0;
+ if ($tobool156) {
+ label = 44;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $conv158 = $side_0 & 255;
+ $side159 = $pp + 33 | 0;
+ HEAP8[$side159] = $conv158;
+ label = 45;
+ break;
+ case 44:
+ $14 = HEAP32[$graph151 >> 2] | 0;
+ $rankdir163 = $14 + 156 | 0;
+ $15 = HEAP32[$rankdir163 >> 2] | 0;
+ $and164 = $15 & 3;
+ $call = _invflip_side($side_0, $and164) | 0;
+ $conv165 = $call & 255;
+ $side166 = $pp + 33 | 0;
+ HEAP8[$side166] = $conv165;
+ label = 45;
+ break;
+ case 45:
+ $bp168 = $pp + 24 | 0;
+ HEAP32[$bp168 >> 2] = $bp;
+ $16 = +HEAPF64[$ctr_sroa_0_0__idx >> 3];
+ $cmp = $16 < 0.0;
+ if ($cmp) {
+ label = 47;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $add172 = $16 + .5;
+ $add172_sink = $add172;
+ label = 48;
+ break;
+ case 47:
+ $sub175 = $16 + -.5;
+ $add172_sink = $sub175;
+ label = 48;
+ break;
+ case 48:
+ $conv173 = ~~$add172_sink;
+ $conv177 = +($conv173 | 0);
+ $x179 = $pp | 0;
+ HEAPF64[$x179 >> 3] = $conv177;
+ $17 = +HEAPF64[$ctr_sroa_1_8__idx8 >> 3];
+ $cmp181 = $17 < 0.0;
+ if ($cmp181) {
+ label = 50;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $add185 = $17 + .5;
+ $add185_sink = $add185;
+ label = 51;
+ break;
+ case 50:
+ $sub189 = $17 + -.5;
+ $add185_sink = $sub189;
+ label = 51;
+ break;
+ case 51:
+ $conv186 = ~~$add185_sink;
+ $conv193 = +($conv186 | 0);
+ $y195 = $pp + 8 | 0;
+ HEAPF64[$y195 >> 3] = $conv193;
+ $18 = HEAP32[$graph151 >> 2] | 0;
+ $rankdir198 = $18 + 156 | 0;
+ $19 = HEAP32[$rankdir198 >> 2] | 0;
+ $and199 = $19 & 3;
+ $call200 = +_invflip_angle($theta_0, $and199);
+ $theta201 = $pp + 16 | 0;
+ HEAPF64[$theta201 >> 3] = $call200;
+ $20 = +HEAPF64[$ctr_sroa_0_0__idx >> 3];
+ $cmp203 = $20 == 0.0;
+ if ($cmp203) {
+ label = 52;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 52:
+ $21 = +HEAPF64[$ctr_sroa_1_8__idx8 >> 3];
+ $cmp207 = $21 == 0.0;
+ if ($cmp207) {
+ label = 53;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 53:
+ $order = $pp + 32 | 0;
+ HEAP8[$order] = -128;
+ label = 57;
+ break;
+ case 54:
+ $22 = +HEAPF64[$ctr_sroa_1_8__idx8 >> 3];
+ $23 = +HEAPF64[$ctr_sroa_0_0__idx >> 3];
+ $call214 = +Math_atan2(+$22, +$23);
+ $add215 = $call214 + 4.71238898038469;
+ $cmp216 = $add215 < 6.283185307179586;
+ if ($cmp216) {
+ $angle_0 = $add215;
+ label = 56;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ $sub219 = $add215 - 6.283185307179586;
+ $angle_0 = $sub219;
+ label = 56;
+ break;
+ case 56:
+ $mul221 = $angle_0 * 256.0;
+ $div222 = $mul221 / 6.283185307179586;
+ $conv223 = ~~$div222;
+ $conv224 = $conv223 & 255;
+ $order225 = $pp + 32 | 0;
+ HEAP8[$order225] = $conv224;
+ label = 57;
+ break;
+ case 57:
+ $constrained = $pp + 29 | 0;
+ HEAP8[$constrained] = $constrain_0;
+ $defined227 = $pp + 28 | 0;
+ HEAP8[$defined227] = $defined_1;
+ $clip228 = $pp + 30 | 0;
+ HEAP8[$clip228] = $clip_0;
+ $dyna229 = $pp + 31 | 0;
+ HEAP8[$dyna229] = $dyna_0;
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _invflip_side($side, $rankdir) {
+ $side = $side | 0;
+ $rankdir = $rankdir | 0;
+ var $side_addr_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($rankdir | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($rankdir | 0) == 1) {
+ label = 6;
+ break;
+ } else if (($rankdir | 0) == 3) {
+ label = 11;
+ break;
+ } else {
+ $side_addr_0 = $side;
+ label = 16;
+ break;
+ }
+ case 3:
+ if (($side | 0) == 4) {
+ label = 4;
+ break;
+ } else if (($side | 0) == 1) {
+ label = 5;
+ break;
+ } else {
+ $side_addr_0 = $side;
+ label = 16;
+ break;
+ }
+ case 4:
+ $side_addr_0 = 1;
+ label = 16;
+ break;
+ case 5:
+ $side_addr_0 = 4;
+ label = 16;
+ break;
+ case 6:
+ if (($side | 0) == 4) {
+ label = 7;
+ break;
+ } else if (($side | 0) == 1) {
+ label = 8;
+ break;
+ } else if (($side | 0) == 8) {
+ label = 9;
+ break;
+ } else if (($side | 0) == 2) {
+ label = 10;
+ break;
+ } else {
+ $side_addr_0 = $side;
+ label = 16;
+ break;
+ }
+ case 7:
+ $side_addr_0 = 2;
+ label = 16;
+ break;
+ case 8:
+ $side_addr_0 = 8;
+ label = 16;
+ break;
+ case 9:
+ $side_addr_0 = 4;
+ label = 16;
+ break;
+ case 10:
+ $side_addr_0 = 1;
+ label = 16;
+ break;
+ case 11:
+ if (($side | 0) == 4) {
+ label = 12;
+ break;
+ } else if (($side | 0) == 1) {
+ label = 13;
+ break;
+ } else if (($side | 0) == 8) {
+ label = 14;
+ break;
+ } else if (($side | 0) == 2) {
+ label = 15;
+ break;
+ } else {
+ $side_addr_0 = $side;
+ label = 16;
+ break;
+ }
+ case 12:
+ $side_addr_0 = 2;
+ label = 16;
+ break;
+ case 13:
+ $side_addr_0 = 8;
+ label = 16;
+ break;
+ case 14:
+ $side_addr_0 = 1;
+ label = 16;
+ break;
+ case 15:
+ $side_addr_0 = 4;
+ label = 16;
+ break;
+ case 16:
+ return $side_addr_0 | 0;
+ }
+ return 0;
+}
+function _invflip_angle($angle, $rankdir) {
+ $angle = +$angle;
+ $rankdir = $rankdir | 0;
+ var $mul = 0.0, $sub = 0.0, $cmp = 0, $cmp4 = 0, $cmp7 = 0, $cmp10 = 0, $cmp13 = 0, $cmp16 = 0, $cmp19 = 0, $retval = 0.0, $angle_addr_0 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($rankdir | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($rankdir | 0) == 1) {
+ label = 4;
+ break;
+ } else if (($rankdir | 0) == 3) {
+ label = 5;
+ break;
+ } else {
+ $angle_addr_0 = $angle;
+ label = 12;
+ break;
+ }
+ case 3:
+ $mul = $angle * -1.0;
+ $angle_addr_0 = $mul;
+ label = 12;
+ break;
+ case 4:
+ $sub = $angle - 1.5707963267948966;
+ $angle_addr_0 = $sub;
+ label = 12;
+ break;
+ case 5:
+ $cmp = $angle == 3.141592653589793;
+ if ($cmp) {
+ $angle_addr_0 = -1.5707963267948966;
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp4 = $angle == 2.356194490192345;
+ if ($cmp4) {
+ $angle_addr_0 = -.7853981633974483;
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp7 = $angle == 1.5707963267948966;
+ if ($cmp7) {
+ $angle_addr_0 = 0.0;
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp10 = $angle == .7853981633974483;
+ if ($cmp10) {
+ $angle_addr_0 = $angle;
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp13 = $angle == 0.0;
+ if ($cmp13) {
+ $angle_addr_0 = 1.5707963267948966;
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $cmp16 = $angle == -.7853981633974483;
+ if ($cmp16) {
+ $angle_addr_0 = 2.356194490192345;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $cmp19 = $angle == -1.5707963267948966;
+ $retval = $cmp19 ? 3.141592653589793 : $angle;
+ return +$retval;
+ case 12:
+ return +$angle_addr_0;
+ }
+ return 0.0;
+}
+function _cvtPt($agg_result, $p, $rankdir) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $rankdir = $rankdir | 0;
+ var $q_sroa_0_0__idx = 0, $q_sroa_0_0_copyload = 0.0, $q_sroa_1_8__idx4 = 0, $q_sroa_1_8_copyload = 0.0, $x = 0, $0 = 0.0, $y = 0, $1 = 0.0, $sub = 0.0, $x5 = 0, $2 = 0.0, $y7 = 0, $3 = 0.0, $sub8 = 0.0, $x11 = 0, $4 = 0.0, $y13 = 0, $5 = 0.0, $q_sroa_0_0 = 0.0, $q_sroa_1_0 = 0.0, $cmp = 0, $q_sroa_1_08 = 0.0, $q_sroa_0_06 = 0.0, $add = 0.0, $sub18 = 0.0, $q_sroa_1_07 = 0.0, $add_sink = 0.0, $conv = 0, $cmp22 = 0, $add26 = 0.0, $sub30 = 0.0, $add26_sink = 0.0, $conv27 = 0, $Q_sroa_0_0__idx = 0, $Q_sroa_1_4__idx1 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($rankdir | 0) == 0) {
+ label = 3;
+ break;
+ } else if (($rankdir | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($rankdir | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($rankdir | 0) == 3) {
+ label = 6;
+ break;
+ } else {
+ $q_sroa_0_06 = 0.0;
+ $q_sroa_1_08 = 0.0;
+ label = 8;
+ break;
+ }
+ case 3:
+ $q_sroa_0_0__idx = $p | 0;
+ $q_sroa_0_0_copyload = +HEAPF64[$q_sroa_0_0__idx >> 3];
+ $q_sroa_1_8__idx4 = $p + 8 | 0;
+ $q_sroa_1_8_copyload = +HEAPF64[$q_sroa_1_8__idx4 >> 3];
+ $q_sroa_1_0 = $q_sroa_1_8_copyload;
+ $q_sroa_0_0 = $q_sroa_0_0_copyload;
+ label = 7;
+ break;
+ case 4:
+ $x = $p | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $y = $p + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $sub = -0.0 - $1;
+ $q_sroa_1_0 = $sub;
+ $q_sroa_0_0 = $0;
+ label = 7;
+ break;
+ case 5:
+ $x5 = $p | 0;
+ $2 = +HEAPF64[$x5 >> 3];
+ $y7 = $p + 8 | 0;
+ $3 = +HEAPF64[$y7 >> 3];
+ $sub8 = -0.0 - $3;
+ $q_sroa_1_0 = $2;
+ $q_sroa_0_0 = $sub8;
+ label = 7;
+ break;
+ case 6:
+ $x11 = $p | 0;
+ $4 = +HEAPF64[$x11 >> 3];
+ $y13 = $p + 8 | 0;
+ $5 = +HEAPF64[$y13 >> 3];
+ $q_sroa_1_0 = $4;
+ $q_sroa_0_0 = $5;
+ label = 7;
+ break;
+ case 7:
+ $cmp = $q_sroa_0_0 < 0.0;
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ $q_sroa_0_06 = $q_sroa_0_0;
+ $q_sroa_1_08 = $q_sroa_1_0;
+ label = 8;
+ break;
+ }
+ case 8:
+ $add = $q_sroa_0_06 + .5;
+ $add_sink = $add;
+ $q_sroa_1_07 = $q_sroa_1_08;
+ label = 10;
+ break;
+ case 9:
+ $sub18 = $q_sroa_0_0 + -.5;
+ $add_sink = $sub18;
+ $q_sroa_1_07 = $q_sroa_1_0;
+ label = 10;
+ break;
+ case 10:
+ $conv = ~~$add_sink;
+ $cmp22 = $q_sroa_1_07 < 0.0;
+ if ($cmp22) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $add26 = $q_sroa_1_07 + .5;
+ $add26_sink = $add26;
+ label = 13;
+ break;
+ case 12:
+ $sub30 = $q_sroa_1_07 + -.5;
+ $add26_sink = $sub30;
+ label = 13;
+ break;
+ case 13:
+ $conv27 = ~~$add26_sink;
+ $Q_sroa_0_0__idx = $agg_result | 0;
+ HEAP32[$Q_sroa_0_0__idx >> 2] = $conv;
+ $Q_sroa_1_4__idx1 = $agg_result + 4 | 0;
+ HEAP32[$Q_sroa_1_4__idx1 >> 2] = $conv27;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _compassPoint($agg_result, $ictxt, $y, $x) {
+ $agg_result = $agg_result | 0;
+ $ictxt = $ictxt | 0;
+ $y = +$y;
+ $x = +$x;
+ var $curve = 0, $0 = 0, $5 = 0, $6 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ $curve = __stackBase__ | 0;
+ $0 = HEAP32[$ictxt >> 2] | 0;
+ _memset($curve | 0, 0, 16);
+ HEAPF64[$curve + 16 >> 3] = $x / 3.0;
+ HEAPF64[$curve + 24 >> 3] = $y / 3.0;
+ HEAPF64[$curve + 32 >> 3] = $x * 2.0 / 3.0;
+ HEAPF64[$curve + 40 >> 3] = $y * 2.0 / 3.0;
+ HEAPF64[$curve + 48 >> 3] = $x;
+ HEAPF64[$curve + 56 >> 3] = $y;
+ _bezier_clip($ictxt, HEAP32[(HEAP32[(HEAP32[$0 + 24 >> 2] | 0) + 4 >> 2] | 0) + 12 >> 2] | 0, $curve | 0, 1);
+ $5 = $agg_result;
+ $6 = $curve;
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _poly_port($agg_result, $n, $portname, $compass) {
+ $agg_result = $agg_result | 0;
+ $n = $n | 0;
+ $portname = $portname | 0;
+ $compass = $compass | 0;
+ var $rv = 0, $sides = 0, $ictxt = 0, $0 = 0, $cmp = 0, $1 = 0, $cmp2 = 0, $_compass = 0, $label = 0, $2 = 0, $html = 0, $3 = 0, $tobool = 0, $call = 0, $tobool7 = 0, $4 = 0, $call9 = 0, $tobool10 = 0, $name = 0, $5 = 0, $call12 = 0, $shape = 0, $6 = 0, $polygon = 0, $7 = 0, $cmp15 = 0, $8 = 0, $n_c = 0, $bp21 = 0, $ictxtp_0 = 0, $9 = 0, $call23 = 0, $tobool24 = 0, $10 = 0, $11 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 56 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rv = __stackBase__ | 0;
+ $sides = __stackBase__ + 40 | 0;
+ $ictxt = __stackBase__ + 48 | 0;
+ $0 = HEAP8[$portname] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = $agg_result;
+ HEAP32[$1 >> 2] = HEAP32[42020] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[42021] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[42022] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[42023] | 0;
+ HEAP32[$1 + 16 >> 2] = HEAP32[42024] | 0;
+ HEAP32[$1 + 20 >> 2] = HEAP32[42025] | 0;
+ HEAP32[$1 + 24 >> 2] = HEAP32[42026] | 0;
+ HEAP32[$1 + 28 >> 2] = HEAP32[42027] | 0;
+ HEAP32[$1 + 32 >> 2] = HEAP32[42028] | 0;
+ HEAP32[$1 + 36 >> 2] = HEAP32[42029] | 0;
+ label = 13;
+ break;
+ case 4:
+ $cmp2 = ($compass | 0) == 0;
+ $_compass = $cmp2 ? 109560 : $compass;
+ HEAP32[$sides >> 2] = 15;
+ $label = $n + 120 | 0;
+ $2 = HEAP32[$label >> 2] | 0;
+ $html = $2 + 82 | 0;
+ $3 = HEAP8[$html] | 0;
+ $tobool = $3 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call = _html_port($n, $portname, $sides) | 0;
+ $tobool7 = ($call | 0) == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $4 = HEAP32[$sides >> 2] | 0;
+ $call9 = _compassPort($n, $call, $rv, $_compass, $4, 0) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $name = $n + 12 | 0;
+ $5 = HEAP32[$name >> 2] | 0;
+ $call12 = _agerr(0, 109200, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $5, HEAP32[tempInt + 8 >> 2] = $portname, HEAP32[tempInt + 16 >> 2] = $_compass, tempInt) | 0) | 0;
+ label = 12;
+ break;
+ case 8:
+ $shape = $n + 24 | 0;
+ $6 = HEAP32[$shape >> 2] | 0;
+ $polygon = $6 + 8 | 0;
+ $7 = HEAP32[$polygon >> 2] | 0;
+ $cmp15 = ($7 | 0) == 8800;
+ if ($cmp15) {
+ $ictxtp_0 = 0;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $8 = $ictxt | 0;
+ $n_c = $n;
+ HEAP32[$8 >> 2] = $n_c;
+ $bp21 = $ictxt + 4 | 0;
+ HEAP32[$bp21 >> 2] = 0;
+ $ictxtp_0 = $ictxt;
+ label = 10;
+ break;
+ case 10:
+ $9 = HEAP32[$sides >> 2] | 0;
+ $call23 = _compassPort($n, 0, $rv, $portname, $9, $ictxtp_0) | 0;
+ $tobool24 = ($call23 | 0) == 0;
+ if ($tobool24) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ _unrecognized($n, $portname);
+ label = 12;
+ break;
+ case 12:
+ $10 = $agg_result;
+ $11 = $rv;
+ HEAP32[$10 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ HEAP32[$10 + 16 >> 2] = HEAP32[$11 + 16 >> 2] | 0;
+ HEAP32[$10 + 20 >> 2] = HEAP32[$11 + 20 >> 2] | 0;
+ HEAP32[$10 + 24 >> 2] = HEAP32[$11 + 24 >> 2] | 0;
+ HEAP32[$10 + 28 >> 2] = HEAP32[$11 + 28 >> 2] | 0;
+ HEAP32[$10 + 32 >> 2] = HEAP32[$11 + 32 >> 2] | 0;
+ HEAP32[$10 + 36 >> 2] = HEAP32[$11 + 36 >> 2] | 0;
+ label = 13;
+ break;
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _epsf_inside($inside_context, $p) {
+ $inside_context = $inside_context | 0;
+ $p = $p | 0;
+ var $tmp = 0, $n1 = 0, $0 = 0, $graph = 0, $1 = 0, $rankdir = 0, $2 = 0, $and = 0, $mul = 0, $P_sroa_0_0__idx = 0, $P_sroa_0_0_copyload = 0.0, $P_sroa_1_8__idx7 = 0, $P_sroa_1_8_copyload = 0.0, $ht = 0, $3 = 0.0, $div = 0.0, $sub = 0.0, $cmp = 0, $cmp4 = 0, $or_cond = 0, $lw = 0, $4 = 0.0, $sub7 = 0.0, $cmp8 = 0, $rw = 0, $5 = 0.0, $cmp11 = 0, $phitmp = 0, $6 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $n1 = $inside_context;
+ $0 = HEAP32[$n1 >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $1 + 156 | 0;
+ $2 = HEAP32[$rankdir >> 2] | 0;
+ $and = $2 & 3;
+ $mul = $and * 90 & -1;
+ _ccwrotatepf($tmp, $p, $mul);
+ $P_sroa_0_0__idx = $tmp | 0;
+ $P_sroa_0_0_copyload = +HEAPF64[$P_sroa_0_0__idx >> 3];
+ $P_sroa_1_8__idx7 = $tmp + 8 | 0;
+ $P_sroa_1_8_copyload = +HEAPF64[$P_sroa_1_8__idx7 >> 3];
+ $ht = $0 + 96 | 0;
+ $3 = +HEAPF64[$ht >> 3];
+ $div = $3 * .5;
+ $sub = -0.0 - $div;
+ $cmp = $P_sroa_1_8_copyload < $sub;
+ $cmp4 = $P_sroa_1_8_copyload > $div;
+ $or_cond = $cmp | $cmp4;
+ if ($or_cond) {
+ $6 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $lw = $0 + 104 | 0;
+ $4 = +HEAPF64[$lw >> 3];
+ $sub7 = -0.0 - $4;
+ $cmp8 = $P_sroa_0_0_copyload < $sub7;
+ if ($cmp8) {
+ $6 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $rw = $0 + 112 | 0;
+ $5 = +HEAPF64[$rw >> 3];
+ $cmp11 = $P_sroa_0_0_copyload <= $5;
+ $phitmp = $cmp11 & 1;
+ $6 = $phitmp;
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return $6 | 0;
+ }
+ return 0;
+}
+function _epsf_gencode($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $obj1 = 0, $0 = 0, $url = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $4 = 0, $_mask = 0, $tobool2 = 0, $5 = 0, $shape_info = 0, $6 = 0, $tobool3 = 0, $flags = 0, $7 = 0, $and = 0, $tobool5 = 0, $8 = 0, $tooltip = 0, $9 = 0, $target = 0, $10 = 0, $id = 0, $11 = 0, $output_file = 0, $12 = 0, $x = 0, $13 = 0.0, $offset = 0, $x12 = 0, $14 = 0, $conv = 0.0, $add = 0.0, $y = 0, $15 = 0.0, $y16 = 0, $16 = 0, $17 = 0, $conv17 = 0.0, $add18 = 0.0, $macro_id = 0, $18 = 0, $call = 0, $label = 0, $19 = 0, $pos = 0, $coord22 = 0, $20 = 0, $21 = 0, $22 = 0, $flags27 = 0, $23 = 0, $and28 = 0, $tobool29 = 0, $24 = 0, $tooltip32 = 0, $25 = 0, $target33 = 0, $26 = 0, $id34 = 0, $27 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $url = $0 + 160 | 0;
+ $1 = HEAP32[$url >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $5 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $0 + 212 | 0;
+ $3 = $2;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $_mask = $4 & 1;
+ $tobool2 = ($_mask | 0) != 0;
+ $5 = $tobool2;
+ label = 4;
+ break;
+ case 4:
+ $shape_info = $n + 28 | 0;
+ $6 = HEAP32[$shape_info >> 2] | 0;
+ $tobool3 = ($6 | 0) != 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 5:
+ if ($5) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 6:
+ $flags = $job + 152 | 0;
+ $7 = HEAP32[$flags >> 2] | 0;
+ $and = $7 & 4;
+ $tobool5 = ($and | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $8 = HEAP32[$url >> 2] | 0;
+ $tooltip = $0 + 180 | 0;
+ $9 = HEAP32[$tooltip >> 2] | 0;
+ $target = $0 + 196 | 0;
+ $10 = HEAP32[$target >> 2] | 0;
+ $id = $0 + 164 | 0;
+ $11 = HEAP32[$id >> 2] | 0;
+ _gvrender_begin_anchor($job, $8, $9, $10, $11);
+ label = 8;
+ break;
+ case 8:
+ if ($tobool3) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $output_file = $job + 36 | 0;
+ $12 = HEAP32[$output_file >> 2] | 0;
+ $x = $n + 32 | 0;
+ $13 = +HEAPF64[$x >> 3];
+ $offset = $6 + 4 | 0;
+ $x12 = $offset;
+ $14 = HEAP32[$x12 >> 2] | 0;
+ $conv = +($14 | 0);
+ $add = $13 + $conv;
+ $y = $n + 40 | 0;
+ $15 = +HEAPF64[$y >> 3];
+ $y16 = $6 + 8 | 0;
+ $16 = $y16;
+ $17 = HEAP32[$16 >> 2] | 0;
+ $conv17 = +($17 | 0);
+ $add18 = $15 + $conv17;
+ $macro_id = $6;
+ $18 = HEAP32[$macro_id >> 2] | 0;
+ $call = _fprintf($12 | 0, 109912, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAPF64[tempInt >> 3] = $add, HEAPF64[tempInt + 8 >> 3] = $add18, HEAP32[tempInt + 16 >> 2] = $18, tempInt) | 0) | 0;
+ label = 10;
+ break;
+ case 10:
+ $label = $n + 120 | 0;
+ $19 = HEAP32[$label >> 2] | 0;
+ $pos = $19 + 56 | 0;
+ $coord22 = $n + 32 | 0;
+ $20 = $pos;
+ $21 = $coord22;
+ HEAP32[$20 >> 2] = HEAP32[$21 >> 2] | 0;
+ HEAP32[$20 + 4 >> 2] = HEAP32[$21 + 4 >> 2] | 0;
+ HEAP32[$20 + 8 >> 2] = HEAP32[$21 + 8 >> 2] | 0;
+ HEAP32[$20 + 12 >> 2] = HEAP32[$21 + 12 >> 2] | 0;
+ $22 = HEAP32[$label >> 2] | 0;
+ _emit_label($job, 10, $22);
+ if ($5) {
+ label = 11;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 11:
+ $flags27 = $job + 152 | 0;
+ $23 = HEAP32[$flags27 >> 2] | 0;
+ $and28 = $23 & 4;
+ $tobool29 = ($and28 | 0) == 0;
+ if ($tobool29) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $24 = HEAP32[$url >> 2] | 0;
+ $tooltip32 = $0 + 180 | 0;
+ $25 = HEAP32[$tooltip32 >> 2] | 0;
+ $target33 = $0 + 196 | 0;
+ $26 = HEAP32[$target33 >> 2] | 0;
+ $id34 = $0 + 164 | 0;
+ $27 = HEAP32[$id34 >> 2] | 0;
+ _gvrender_begin_anchor($job, $24, $25, $26, $27);
+ label = 13;
+ break;
+ case 13:
+ _gvrender_end_anchor($job);
+ label = 14;
+ break;
+ case 14:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _unrecognized($n, $p) {
+ $n = $n | 0;
+ $p = $p | 0;
+ var __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ _agerr(0, 108792, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = HEAP32[$n + 12 >> 2] | 0, HEAP32[tempInt + 8 >> 2] = $p, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _record_free($n) {
+ $n = $n | 0;
+ _free_field(HEAP32[$n + 28 >> 2] | 0);
+ return;
+}
+function _record_port($agg_result, $n, $portname, $compass) {
+ $agg_result = $agg_result | 0;
+ $n = $n | 0;
+ $portname = $portname | 0;
+ $compass = $compass | 0;
+ var $rv = 0, $0 = 0, $cmp = 0, $1 = 0, $cmp2 = 0, $_compass = 0, $shape_info = 0, $2 = 0, $3 = 0, $call = 0, $tobool = 0, $b = 0, $sides7 = 0, $4 = 0, $conv8 = 0, $call9 = 0, $tobool10 = 0, $name = 0, $5 = 0, $call12 = 0, $b14 = 0, $6 = 0, $call15 = 0, $tobool16 = 0, $7 = 0, $8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rv = __stackBase__ | 0;
+ $0 = HEAP8[$portname] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = $agg_result;
+ HEAP32[$1 >> 2] = HEAP32[42020] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[42021] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[42022] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[42023] | 0;
+ HEAP32[$1 + 16 >> 2] = HEAP32[42024] | 0;
+ HEAP32[$1 + 20 >> 2] = HEAP32[42025] | 0;
+ HEAP32[$1 + 24 >> 2] = HEAP32[42026] | 0;
+ HEAP32[$1 + 28 >> 2] = HEAP32[42027] | 0;
+ HEAP32[$1 + 32 >> 2] = HEAP32[42028] | 0;
+ HEAP32[$1 + 36 >> 2] = HEAP32[42029] | 0;
+ label = 10;
+ break;
+ case 4:
+ $cmp2 = ($compass | 0) == 0;
+ $_compass = $cmp2 ? 109560 : $compass;
+ $shape_info = $n + 28 | 0;
+ $2 = HEAP32[$shape_info >> 2] | 0;
+ $3 = $2;
+ $call = _map_rec_port($3, $portname) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $b = $call + 16 | 0;
+ $sides7 = $call + 65 | 0;
+ $4 = HEAP8[$sides7] | 0;
+ $conv8 = $4 & 255;
+ $call9 = _compassPort($n, $b, $rv, $_compass, $conv8, 0) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $name = $n + 12 | 0;
+ $5 = HEAP32[$name >> 2] | 0;
+ $call12 = _agerr(0, 109200, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $5, HEAP32[tempInt + 8 >> 2] = $portname, HEAP32[tempInt + 16 >> 2] = $_compass, tempInt) | 0) | 0;
+ label = 9;
+ break;
+ case 7:
+ $b14 = $2 + 16 | 0;
+ $6 = $b14;
+ $call15 = _compassPort($n, $6, $rv, $portname, 15, 0) | 0;
+ $tobool16 = ($call15 | 0) == 0;
+ if ($tobool16) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _unrecognized($n, $portname);
+ label = 9;
+ break;
+ case 9:
+ $7 = $agg_result;
+ $8 = $rv;
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ HEAP32[$7 + 16 >> 2] = HEAP32[$8 + 16 >> 2] | 0;
+ HEAP32[$7 + 20 >> 2] = HEAP32[$8 + 20 >> 2] | 0;
+ HEAP32[$7 + 24 >> 2] = HEAP32[$8 + 24 >> 2] | 0;
+ HEAP32[$7 + 28 >> 2] = HEAP32[$8 + 28 >> 2] | 0;
+ HEAP32[$7 + 32 >> 2] = HEAP32[$8 + 32 >> 2] | 0;
+ HEAP32[$7 + 36 >> 2] = HEAP32[$8 + 36 >> 2] | 0;
+ label = 10;
+ break;
+ case 10:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _record_inside($inside_context, $p) {
+ $inside_context = $inside_context | 0;
+ $p = $p | 0;
+ var $tmp = 0, $bp1 = 0, $0 = 0, $n3 = 0, $1 = 0, $graph = 0, $2 = 0, $rankdir = 0, $3 = 0, $and = 0, $mul = 0, $4 = 0, $5 = 0, $cmp = 0, $shape_info = 0, $6 = 0, $bbox_sroa_0_0__idx1 = 0, $7 = 0, $bbox_sroa_1_8__idx4 = 0, $8 = 0, $bbox_sroa_2_16__idx7 = 0, $9 = 0, $bbox_sroa_3_24__idx10 = 0, $10 = 0, $11 = 0, $12 = 0, $13 = 0, $bbox_sroa_3_0_in = 0, $bbox_sroa_2_0_in = 0, $bbox_sroa_1_0_in = 0, $bbox_sroa_0_0_in = 0, $bbox_sroa_0_0 = 0.0, $bbox_sroa_1_0 = 0.0, $bbox_sroa_3_0 = 0.0, $x5 = 0, $14 = 0.0, $cmp6 = 0, $bbox_sroa_2_0 = 0.0, $cmp9 = 0, $y11 = 0, $15 = 0.0, $cmp12 = 0, $cmp17 = 0, $phitmp = 0, $16 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $bp1 = $inside_context + 4 | 0;
+ $0 = HEAP32[$bp1 >> 2] | 0;
+ $n3 = $inside_context;
+ $1 = HEAP32[$n3 >> 2] | 0;
+ $graph = $1 + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $2 + 156 | 0;
+ $3 = HEAP32[$rankdir >> 2] | 0;
+ $and = $3 & 3;
+ $mul = $and * 90 & -1;
+ _ccwrotatepf($tmp, $p, $mul);
+ $4 = $p;
+ $5 = $tmp;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $shape_info = $1 + 28 | 0;
+ $6 = HEAP32[$shape_info >> 2] | 0;
+ $bbox_sroa_0_0__idx1 = $6 + 16 | 0;
+ $7 = $bbox_sroa_0_0__idx1;
+ $bbox_sroa_1_8__idx4 = $6 + 24 | 0;
+ $8 = $bbox_sroa_1_8__idx4;
+ $bbox_sroa_2_16__idx7 = $6 + 32 | 0;
+ $9 = $bbox_sroa_2_16__idx7;
+ $bbox_sroa_3_24__idx10 = $6 + 40 | 0;
+ $10 = $bbox_sroa_3_24__idx10;
+ $bbox_sroa_0_0_in = $7;
+ $bbox_sroa_1_0_in = $8;
+ $bbox_sroa_2_0_in = $9;
+ $bbox_sroa_3_0_in = $10;
+ label = 5;
+ break;
+ case 4:
+ $11 = $0 + 8 | 0;
+ $12 = $0 + 16 | 0;
+ $13 = $0 + 24 | 0;
+ $bbox_sroa_0_0_in = $0;
+ $bbox_sroa_1_0_in = $11;
+ $bbox_sroa_2_0_in = $12;
+ $bbox_sroa_3_0_in = $13;
+ label = 5;
+ break;
+ case 5:
+ $bbox_sroa_0_0 = +HEAPF64[$bbox_sroa_0_0_in >> 3];
+ $bbox_sroa_1_0 = +HEAPF64[$bbox_sroa_1_0_in >> 3];
+ $bbox_sroa_3_0 = +HEAPF64[$bbox_sroa_3_0_in >> 3];
+ $x5 = $p | 0;
+ $14 = +HEAPF64[$x5 >> 3];
+ $cmp6 = $bbox_sroa_0_0 > $14;
+ if ($cmp6) {
+ $16 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $bbox_sroa_2_0 = +HEAPF64[$bbox_sroa_2_0_in >> 3];
+ $cmp9 = $14 > $bbox_sroa_2_0;
+ if ($cmp9) {
+ $16 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $y11 = $p + 8 | 0;
+ $15 = +HEAPF64[$y11 >> 3];
+ $cmp12 = $bbox_sroa_1_0 > $15;
+ if ($cmp12) {
+ $16 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp17 = $15 <= $bbox_sroa_3_0;
+ $phitmp = $cmp17 & 1;
+ $16 = $phitmp;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return $16 | 0;
+ }
+ return 0;
+}
+function _record_path($n, $prt, $side, $rv, $kptr) {
+ $n = $n | 0;
+ $prt = $prt | 0;
+ $side = $side | 0;
+ $rv = $rv | 0;
+ $kptr = $kptr | 0;
+ var $tmp = 0, $defined = 0, $0 = 0, $tobool = 0, $p_sroa_0_0__idx = 0, $p_sroa_0_0_copyload = 0.0, $shape_info = 0, $1 = 0, $n_flds = 0, $2 = 0, $3 = 0, $cmp30 = 0, $graph = 0, $4 = 0, $rankdir = 0, $5 = 0, $and3 = 0, $tobool4 = 0, $fld11 = 0, $6 = 0, $7 = 0, $i_031 = 0, $arrayidx12 = 0, $8 = 0, $x = 0, $x9 = 0, $y = 0, $y20 = 0, $rs_0_in_in = 0, $ls_0_in_in = 0, $ls_0_in = 0.0, $ls_0 = 0, $conv23 = 0.0, $cmp25 = 0, $rs_0_in = 0.0, $rs_0 = 0, $conv28 = 0.0, $cmp29 = 0, $9 = 0, $rankdir34 = 0, $10 = 0, $and36 = 0, $tobool37 = 0, $11 = 0, $arrayidx41 = 0, $12 = 0, $b42 = 0, $coord = 0, $13 = 0, $14 = 0, $x47 = 0, $15 = 0.0, $add = 0.0, $x51 = 0, $y54 = 0, $16 = 0.0, $ht = 0, $17 = 0.0, $div = 0.0, $sub = 0.0, $y58 = 0, $18 = 0.0, $add63 = 0.0, $x66 = 0, $y70 = 0, $19 = 0.0, $ht72 = 0, $20 = 0.0, $div73 = 0.0, $add74 = 0.0, $y77 = 0, $inc = 0, $21 = 0, $cmp = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $defined = $prt + 28 | 0;
+ $0 = HEAP8[$defined] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 15;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $p_sroa_0_0__idx = $prt | 0;
+ $p_sroa_0_0_copyload = +HEAPF64[$p_sroa_0_0__idx >> 3];
+ $shape_info = $n + 28 | 0;
+ $1 = HEAP32[$shape_info >> 2] | 0;
+ $n_flds = $1 + 48 | 0;
+ $2 = $n_flds;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $cmp30 = ($3 | 0) > 0;
+ if ($cmp30) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = $side;
+ label = 15;
+ break;
+ }
+ case 4:
+ $graph = $n + 20 | 0;
+ $4 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $4 + 156 | 0;
+ $5 = HEAP32[$rankdir >> 2] | 0;
+ $and3 = $5 & 1;
+ $tobool4 = ($and3 | 0) == 0;
+ $fld11 = $1 + 56 | 0;
+ $6 = $fld11;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $i_031 = 0;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx12 = $7 + ($i_031 << 2) | 0;
+ $8 = HEAP32[$arrayidx12 >> 2] | 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $x = $8 + 16 | 0;
+ $x9 = $8 + 32 | 0;
+ $ls_0_in_in = $x;
+ $rs_0_in_in = $x9;
+ label = 8;
+ break;
+ case 7:
+ $y = $8 + 24 | 0;
+ $y20 = $8 + 40 | 0;
+ $ls_0_in_in = $y;
+ $rs_0_in_in = $y20;
+ label = 8;
+ break;
+ case 8:
+ $ls_0_in = +HEAPF64[$ls_0_in_in >> 3];
+ $ls_0 = ~~$ls_0_in;
+ $conv23 = +($ls_0 | 0);
+ $cmp25 = $conv23 > $p_sroa_0_0_copyload;
+ if ($cmp25) {
+ label = 14;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $rs_0_in = +HEAPF64[$rs_0_in_in >> 3];
+ $rs_0 = ~~$rs_0_in;
+ $conv28 = +($rs_0 | 0);
+ $cmp29 = $p_sroa_0_0_copyload > $conv28;
+ if ($cmp29) {
+ label = 14;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $9 = HEAP32[$graph >> 2] | 0;
+ $rankdir34 = $9 + 156 | 0;
+ $10 = HEAP32[$rankdir34 >> 2] | 0;
+ $and36 = $10 & 1;
+ $tobool37 = ($and36 | 0) == 0;
+ if ($tobool37) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $11 = HEAP32[$6 >> 2] | 0;
+ $arrayidx41 = $11 + ($i_031 << 2) | 0;
+ $12 = HEAP32[$arrayidx41 >> 2] | 0;
+ $b42 = $12 + 16 | 0;
+ $coord = $n + 32 | 0;
+ _flip_rec_boxf($tmp, $b42, $coord);
+ $13 = $rv;
+ $14 = $tmp;
+ HEAP32[$13 >> 2] = HEAP32[$14 >> 2] | 0;
+ HEAP32[$13 + 4 >> 2] = HEAP32[$14 + 4 >> 2] | 0;
+ HEAP32[$13 + 8 >> 2] = HEAP32[$14 + 8 >> 2] | 0;
+ HEAP32[$13 + 12 >> 2] = HEAP32[$14 + 12 >> 2] | 0;
+ HEAP32[$13 + 16 >> 2] = HEAP32[$14 + 16 >> 2] | 0;
+ HEAP32[$13 + 20 >> 2] = HEAP32[$14 + 20 >> 2] | 0;
+ HEAP32[$13 + 24 >> 2] = HEAP32[$14 + 24 >> 2] | 0;
+ HEAP32[$13 + 28 >> 2] = HEAP32[$14 + 28 >> 2] | 0;
+ label = 13;
+ break;
+ case 12:
+ $x47 = $n + 32 | 0;
+ $15 = +HEAPF64[$x47 >> 3];
+ $add = $conv23 + $15;
+ $x51 = $rv | 0;
+ HEAPF64[$x51 >> 3] = $add;
+ $y54 = $n + 40 | 0;
+ $16 = +HEAPF64[$y54 >> 3];
+ $ht = $n + 96 | 0;
+ $17 = +HEAPF64[$ht >> 3];
+ $div = $17 * .5;
+ $sub = $16 - $div;
+ $y58 = $rv + 8 | 0;
+ HEAPF64[$y58 >> 3] = $sub;
+ $18 = +HEAPF64[$x47 >> 3];
+ $add63 = $conv28 + $18;
+ $x66 = $rv + 16 | 0;
+ HEAPF64[$x66 >> 3] = $add63;
+ label = 13;
+ break;
+ case 13:
+ $y70 = $n + 40 | 0;
+ $19 = +HEAPF64[$y70 >> 3];
+ $ht72 = $n + 96 | 0;
+ $20 = +HEAPF64[$ht72 >> 3];
+ $div73 = $20 * .5;
+ $add74 = $19 + $div73;
+ $y77 = $rv + 24 | 0;
+ HEAPF64[$y77 >> 3] = $add74;
+ HEAP32[$kptr >> 2] = 1;
+ $retval_0 = $side;
+ label = 15;
+ break;
+ case 14:
+ $inc = $i_031 + 1 | 0;
+ $21 = HEAP32[$2 >> 2] | 0;
+ $cmp = ($inc | 0) < ($21 | 0);
+ if ($cmp) {
+ $i_031 = $inc;
+ label = 5;
+ break;
+ } else {
+ $retval_0 = $side;
+ label = 15;
+ break;
+ }
+ case 15:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _record_gencode($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $BF = 0, $AF = 0, $obj1 = 0, $0 = 0, $url = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $4 = 0, $_mask = 0, $tobool2 = 0, $5 = 0, $shape_info = 0, $6 = 0, $7 = 0, $b = 0, $8 = 0, $x = 0, $9 = 0.0, $x4 = 0, $10 = 0.0, $add = 0.0, $y = 0, $11 = 0.0, $y8 = 0, $12 = 0.0, $add9 = 0.0, $13 = 0.0, $UR = 0, $x13 = 0, $14 = 0.0, $add14 = 0.0, $15 = 0.0, $y19 = 0, $16 = 0.0, $add20 = 0.0, $flags = 0, $17 = 0, $and = 0, $tobool22 = 0, $18 = 0, $tooltip = 0, $19 = 0, $target = 0, $20 = 0, $id = 0, $21 = 0, $call = 0, $and24 = 0, $tobool25 = 0, $call27 = 0, $shape = 0, $22 = 0, $name = 0, $23 = 0, $24 = 0, $cmp = 0, $call36 = 0, $tobool37 = 0, $or = 0, $or_call = 0, $style_0 = 0, $and40 = 0, $tobool41 = 0, $arrayidx = 0, $25 = 0, $arrayidx44 = 0, $26 = 0, $27 = 0, $x47 = 0, $28 = 0.0, $x49 = 0, $y51 = 0, $29 = 0.0, $y53 = 0, $x55 = 0, $30 = 0.0, $x57 = 0, $y59 = 0, $31 = 0.0, $y61 = 0, $and62 = 0, $style_0_tr = 0, $conv64 = 0, $flags68 = 0, $32 = 0, $and69 = 0, $tobool70 = 0, $33 = 0, $tooltip73 = 0, $34 = 0, $target74 = 0, $35 = 0, $id75 = 0, $36 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 96 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $BF = __stackBase__ | 0;
+ $AF = __stackBase__ + 32 | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $url = $0 + 160 | 0;
+ $1 = HEAP32[$url >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $5 = 1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $0 + 212 | 0;
+ $3 = $2;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $_mask = $4 & 1;
+ $tobool2 = ($_mask | 0) != 0;
+ $5 = $tobool2;
+ label = 4;
+ break;
+ case 4:
+ $shape_info = $n + 28 | 0;
+ $6 = HEAP32[$shape_info >> 2] | 0;
+ $7 = $6;
+ $b = $6 + 16 | 0;
+ $8 = $BF;
+ HEAP32[$8 >> 2] = HEAP32[$b >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$b + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$b + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$b + 12 >> 2] | 0;
+ HEAP32[$8 + 16 >> 2] = HEAP32[$b + 16 >> 2] | 0;
+ HEAP32[$8 + 20 >> 2] = HEAP32[$b + 20 >> 2] | 0;
+ HEAP32[$8 + 24 >> 2] = HEAP32[$b + 24 >> 2] | 0;
+ HEAP32[$8 + 28 >> 2] = HEAP32[$b + 28 >> 2] | 0;
+ $x = $n + 32 | 0;
+ $9 = +HEAPF64[$x >> 3];
+ $x4 = $BF | 0;
+ $10 = +HEAPF64[$x4 >> 3];
+ $add = $9 + $10;
+ HEAPF64[$x4 >> 3] = $add;
+ $y = $n + 40 | 0;
+ $11 = +HEAPF64[$y >> 3];
+ $y8 = $BF + 8 | 0;
+ $12 = +HEAPF64[$y8 >> 3];
+ $add9 = $11 + $12;
+ HEAPF64[$y8 >> 3] = $add9;
+ $13 = +HEAPF64[$x >> 3];
+ $UR = $BF + 16 | 0;
+ $x13 = $UR | 0;
+ $14 = +HEAPF64[$x13 >> 3];
+ $add14 = $13 + $14;
+ HEAPF64[$x13 >> 3] = $add14;
+ $15 = +HEAPF64[$y >> 3];
+ $y19 = $BF + 24 | 0;
+ $16 = +HEAPF64[$y19 >> 3];
+ $add20 = $15 + $16;
+ HEAPF64[$y19 >> 3] = $add20;
+ if ($5) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $flags = $job + 152 | 0;
+ $17 = HEAP32[$flags >> 2] | 0;
+ $and = $17 & 4;
+ $tobool22 = ($and | 0) == 0;
+ if ($tobool22) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $18 = HEAP32[$url >> 2] | 0;
+ $tooltip = $0 + 180 | 0;
+ $19 = HEAP32[$tooltip >> 2] | 0;
+ $target = $0 + 196 | 0;
+ $20 = HEAP32[$target >> 2] | 0;
+ $id = $0 + 164 | 0;
+ $21 = HEAP32[$id >> 2] | 0;
+ _gvrender_begin_anchor($job, $18, $19, $20, $21);
+ label = 7;
+ break;
+ case 7:
+ $call = _stylenode($job, $n) | 0;
+ _pencolor($job, $n);
+ $and24 = $call & 1;
+ $tobool25 = ($and24 | 0) == 0;
+ if ($tobool25) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call27 = _findFill($n) | 0;
+ _gvrender_set_fillcolor($job, $call27);
+ label = 9;
+ break;
+ case 9:
+ $shape = $n + 24 | 0;
+ $22 = HEAP32[$shape >> 2] | 0;
+ $name = $22 | 0;
+ $23 = HEAP32[$name >> 2] | 0;
+ $24 = HEAP8[$23] | 0;
+ $cmp = $24 << 24 >> 24 == 77;
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ $style_0 = $call;
+ label = 11;
+ break;
+ }
+ case 10:
+ $call36 = _strcmp($23 | 0, 110408) | 0;
+ $tobool37 = ($call36 | 0) == 0;
+ $or = $call | 2;
+ $or_call = $tobool37 ? $or : $call;
+ $style_0 = $or_call;
+ label = 11;
+ break;
+ case 11:
+ $and40 = $style_0 & 998;
+ $tobool41 = ($and40 | 0) == 0;
+ if ($tobool41) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $arrayidx = $AF | 0;
+ $25 = $AF;
+ HEAP32[$25 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$25 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$25 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$25 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $arrayidx44 = $AF + 32 | 0;
+ $26 = $arrayidx44;
+ $27 = $UR;
+ HEAP32[$26 >> 2] = HEAP32[$27 >> 2] | 0;
+ HEAP32[$26 + 4 >> 2] = HEAP32[$27 + 4 >> 2] | 0;
+ HEAP32[$26 + 8 >> 2] = HEAP32[$27 + 8 >> 2] | 0;
+ HEAP32[$26 + 12 >> 2] = HEAP32[$27 + 12 >> 2] | 0;
+ $x47 = $arrayidx44 | 0;
+ $28 = +HEAPF64[$x47 >> 3];
+ $x49 = $AF + 16 | 0;
+ HEAPF64[$x49 >> 3] = $28;
+ $y51 = $AF + 8 | 0;
+ $29 = +HEAPF64[$y51 >> 3];
+ $y53 = $AF + 24 | 0;
+ HEAPF64[$y53 >> 3] = $29;
+ $x55 = $AF | 0;
+ $30 = +HEAPF64[$x55 >> 3];
+ $x57 = $AF + 48 | 0;
+ HEAPF64[$x57 >> 3] = $30;
+ $y59 = $AF + 40 | 0;
+ $31 = +HEAPF64[$y59 >> 3];
+ $y61 = $AF + 56 | 0;
+ HEAPF64[$y61 >> 3] = $31;
+ $and62 = $style_0 & 1;
+ _node_round_corners($job, $n, $arrayidx, 4, $style_0, $and62);
+ label = 14;
+ break;
+ case 13:
+ $style_0_tr = $style_0 & 255;
+ $conv64 = $style_0_tr & 1;
+ _gvrender_box($job, $BF, $conv64);
+ label = 14;
+ break;
+ case 14:
+ _gen_fields($job, $n, $7);
+ if ($5) {
+ label = 15;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 15:
+ $flags68 = $job + 152 | 0;
+ $32 = HEAP32[$flags68 >> 2] | 0;
+ $and69 = $32 & 4;
+ $tobool70 = ($and69 | 0) == 0;
+ if ($tobool70) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $33 = HEAP32[$url >> 2] | 0;
+ $tooltip73 = $0 + 180 | 0;
+ $34 = HEAP32[$tooltip73 >> 2] | 0;
+ $target74 = $0 + 196 | 0;
+ $35 = HEAP32[$target74 >> 2] | 0;
+ $id75 = $0 + 164 | 0;
+ $36 = HEAP32[$id75 >> 2] | 0;
+ _gvrender_begin_anchor($job, $33, $34, $35, $36);
+ label = 17;
+ break;
+ case 17:
+ _gvrender_end_anchor($job);
+ label = 18;
+ break;
+ case 18:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _stylenode($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $istyle = 0, $call = 0, $tobool = 0, $0 = 0, $tobool1 = 0, $1 = 0, $index = 0, $2 = 0, $call2 = 0, $tobool3 = 0, $3 = 0, $tobool5 = 0, $call7 = 0.0, $4 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $istyle = __stackBase__ | 0;
+ $call = _checkStyle($n, $istyle) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _gvrender_set_style($job, $call);
+ label = 4;
+ break;
+ case 4:
+ $0 = HEAP32[41576] | 0;
+ $tobool1 = ($0 | 0) == 0;
+ if ($tobool1) {
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $1 = $n | 0;
+ $index = $0 + 8 | 0;
+ $2 = HEAP32[$index >> 2] | 0;
+ $call2 = _agxget($1, $2) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = HEAP8[$call2] | 0;
+ $tobool5 = $3 << 24 >> 24 == 0;
+ if ($tobool5) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call7 = +_late_double($1, $0, 1.0, 0.0);
+ _gvrender_set_penwidth($job, $call7);
+ label = 8;
+ break;
+ case 8:
+ $4 = HEAP32[$istyle >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return $4 | 0;
+ }
+ return 0;
+}
+function _pencolor($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $0 = 0, $1 = 0, $call = 0, $2 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $n | 0;
+ $1 = HEAP32[41616] | 0;
+ $call = _late_nnstring($0, $1, 108168) | 0;
+ $2 = HEAP8[$call] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _gvrender_set_pencolor($job, $call);
+ label = 5;
+ break;
+ case 4:
+ _gvrender_set_pencolor($job, 107704);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _findFill($n) {
+ $n = $n | 0;
+ return _findFillDflt($n, 107272) | 0;
+}
+function _node_round_corners($job, $n, $AF, $sides, $style, $filled) {
+ $job = $job | 0;
+ $n = $n | 0;
+ $AF = $AF | 0;
+ $sides = $sides | 0;
+ $style = $style | 0;
+ $filled = $filled | 0;
+ var $call = 0;
+ $call = _findFill($n) | 0;
+ _round_corners($job, $call, _findPen($n) | 0, $AF, $sides, $style, $filled);
+ return;
+}
+function _add_pointf796($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $add4 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $add4 = +HEAPF64[$p + 8 >> 3] + +HEAPF64[$q + 8 >> 3];
+ HEAPF64[$agg_result >> 3] = +HEAPF64[$p >> 3] + +HEAPF64[$q >> 3];
+ HEAPF64[$agg_result + 8 >> 3] = $add4;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _mid_pointf797($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $div5 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $div5 = (+HEAPF64[$p + 8 >> 3] + +HEAPF64[$q + 8 >> 3]) * .5;
+ HEAPF64[$agg_result >> 3] = (+HEAPF64[$p >> 3] + +HEAPF64[$q >> 3]) * .5;
+ HEAPF64[$agg_result + 8 >> 3] = $div5;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _gen_fields($job, $n, $f) {
+ $job = $job | 0;
+ $n = $n | 0;
+ $f = $f | 0;
+ var $AF = 0, $coord = 0, $agg_tmp = 0, $tmp = 0, $tmp42 = 0, $tmp45 = 0, $lp = 0, $0 = 0, $tobool = 0, $pos = 0, $LL = 0, $UR = 0, $coord3 = 0, $1 = 0, $2 = 0, $3 = 0, $coord6 = 0, $4 = 0, $5 = 0, $n_flds = 0, $6 = 0, $cmp25 = 0, $LR = 0, $arrayidx23 = 0, $fld24 = 0, $7 = 0, $x34 = 0, $y36 = 0, $y38 = 0, $arrayidx40 = 0, $8 = 0, $9 = 0, $arrayidx43 = 0, $10 = 0, $11 = 0, $fld = 0, $12 = 0, $x = 0, $x16 = 0, $y22 = 0, $fld47 = 0, $i_026 = 0, $cmp7 = 0, $13 = 0, $tobool9 = 0, $14 = 0, $arrayidx11 = 0, $15 = 0, $LL13 = 0, $16 = 0, $17 = 0.0, $18 = 0, $arrayidx18 = 0, $19 = 0, $y = 0, $20 = 0.0, $21 = 0, $arrayidx25 = 0, $22 = 0, $UR27 = 0, $23 = 0, $24 = 0, $arrayidx29 = 0, $25 = 0, $x32 = 0, $26 = 0.0, $27 = 0.0, $28 = 0, $arrayidx48 = 0, $29 = 0, $inc = 0, $30 = 0, $cmp = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 112 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $AF = __stackBase__ | 0;
+ $coord = __stackBase__ + 32 | 0;
+ $agg_tmp = __stackBase__ + 48 | 0;
+ $tmp = __stackBase__ + 64 | 0;
+ $tmp42 = __stackBase__ + 80 | 0;
+ $tmp45 = __stackBase__ + 96 | 0;
+ $lp = $f + 52 | 0;
+ $0 = HEAP32[$lp >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $pos = $0 + 56 | 0;
+ $LL = $f + 16 | 0;
+ $UR = $f + 32 | 0;
+ _mid_pointf797($agg_tmp, $LL, $UR);
+ $coord3 = $n + 32 | 0;
+ _add_pointf796($tmp, $agg_tmp, $coord3);
+ $1 = $pos;
+ $2 = $tmp;
+ HEAP32[$1 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ $3 = HEAP32[$lp >> 2] | 0;
+ _emit_label($job, 10, $3);
+ _pencolor($job, $n);
+ label = 4;
+ break;
+ case 4:
+ $coord6 = $n + 32 | 0;
+ $4 = $coord;
+ $5 = $coord6;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $n_flds = $f + 48 | 0;
+ $6 = HEAP32[$n_flds >> 2] | 0;
+ $cmp25 = ($6 | 0) > 0;
+ if ($cmp25) {
+ label = 5;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 5:
+ $LR = $f + 64 | 0;
+ $arrayidx23 = $AF + 16 | 0;
+ $fld24 = $f + 56 | 0;
+ $7 = $arrayidx23;
+ $x34 = $AF | 0;
+ $y36 = $AF + 24 | 0;
+ $y38 = $AF + 8 | 0;
+ $arrayidx40 = $AF | 0;
+ $8 = $AF;
+ $9 = $tmp42;
+ $arrayidx43 = $AF + 16 | 0;
+ $10 = $arrayidx43;
+ $11 = $tmp45;
+ $fld = $f + 56 | 0;
+ $12 = $AF;
+ $x = $AF | 0;
+ $x16 = $AF + 16 | 0;
+ $y22 = $AF + 24 | 0;
+ $fld47 = $f + 56 | 0;
+ $i_026 = 0;
+ label = 6;
+ break;
+ case 6:
+ $cmp7 = ($i_026 | 0) > 0;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $13 = HEAP8[$LR] | 0;
+ $tobool9 = $13 << 24 >> 24 == 0;
+ if ($tobool9) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $14 = HEAP32[$fld >> 2] | 0;
+ $arrayidx11 = $14 + ($i_026 << 2) | 0;
+ $15 = HEAP32[$arrayidx11 >> 2] | 0;
+ $LL13 = $15 + 16 | 0;
+ $16 = $LL13;
+ HEAP32[$12 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ $17 = +HEAPF64[$x >> 3];
+ HEAPF64[$x16 >> 3] = $17;
+ $18 = HEAP32[$fld >> 2] | 0;
+ $arrayidx18 = $18 + ($i_026 << 2) | 0;
+ $19 = HEAP32[$arrayidx18 >> 2] | 0;
+ $y = $19 + 40 | 0;
+ $20 = +HEAPF64[$y >> 3];
+ HEAPF64[$y22 >> 3] = $20;
+ label = 10;
+ break;
+ case 9:
+ $21 = HEAP32[$fld24 >> 2] | 0;
+ $arrayidx25 = $21 + ($i_026 << 2) | 0;
+ $22 = HEAP32[$arrayidx25 >> 2] | 0;
+ $UR27 = $22 + 32 | 0;
+ $23 = $UR27;
+ HEAP32[$7 >> 2] = HEAP32[$23 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$23 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$23 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$23 + 12 >> 2] | 0;
+ $24 = HEAP32[$fld24 >> 2] | 0;
+ $arrayidx29 = $24 + ($i_026 << 2) | 0;
+ $25 = HEAP32[$arrayidx29 >> 2] | 0;
+ $x32 = $25 + 16 | 0;
+ $26 = +HEAPF64[$x32 >> 3];
+ HEAPF64[$x34 >> 3] = $26;
+ $27 = +HEAPF64[$y36 >> 3];
+ HEAPF64[$y38 >> 3] = $27;
+ label = 10;
+ break;
+ case 10:
+ _add_pointf796($tmp42, $arrayidx40, $coord);
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ _add_pointf796($tmp45, $arrayidx43, $coord);
+ HEAP32[$10 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ _gvrender_polyline($job, $arrayidx40, 2);
+ label = 11;
+ break;
+ case 11:
+ $28 = HEAP32[$fld47 >> 2] | 0;
+ $arrayidx48 = $28 + ($i_026 << 2) | 0;
+ $29 = HEAP32[$arrayidx48 >> 2] | 0;
+ _gen_fields($job, $n, $29);
+ $inc = $i_026 + 1 | 0;
+ $30 = HEAP32[$n_flds >> 2] | 0;
+ $cmp = ($inc | 0) < ($30 | 0);
+ if ($cmp) {
+ $i_026 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _findPen($n) {
+ $n = $n | 0;
+ var $call = 0;
+ $call = _late_nnstring($n | 0, HEAP32[41616] | 0, 108168) | 0;
+ return ((HEAP8[$call] | 0) == 0 ? 107704 : $call) | 0;
+}
+function _findFillDflt($n, $dflt) {
+ $n = $n | 0;
+ $dflt = $dflt | 0;
+ var $0 = 0, $1 = 0, $call = 0, $2 = 0, $tobool = 0, $3 = 0, $call1 = 0, $4 = 0, $tobool3 = 0, $dflt_call1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $n | 0;
+ $1 = HEAP32[41604] | 0;
+ $call = _late_nnstring($0, $1, 108168) | 0;
+ $2 = HEAP8[$call] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $3 = HEAP32[41616] | 0;
+ $call1 = _late_nnstring($0, $3, 108168) | 0;
+ $4 = HEAP8[$call1] | 0;
+ $tobool3 = $4 << 24 >> 24 == 0;
+ $dflt_call1 = $tobool3 ? $dflt : $call1;
+ return $dflt_call1 | 0;
+ case 4:
+ return $call | 0;
+ }
+ return 0;
+}
+function _checkStyle($n, $flagp) {
+ $n = $n | 0;
+ $flagp = $flagp | 0;
+ var $0 = 0, $1 = 0, $call = 0, $2 = 0, $tobool = 0, $call1 = 0, $3 = 0, $tobool23337 = 0, $or28 = 0, $or16 = 0, $4 = 0, $pp_0_ph39 = 0, $istyle_0_ph38 = 0, $5 = 0, $pp_034 = 0, $6 = 0, $cmp = 0, $call5 = 0, $tobool6 = 0, $or = 0, $incdec_ptr = 0, $_pr = 0, $7 = 0, $cmp10 = 0, $call13 = 0, $tobool14 = 0, $qp_0 = 0, $incdec_ptr17 = 0, $8 = 0, $9 = 0, $tobool18 = 0, $10 = 0, $cmp22 = 0, $call25 = 0, $tobool26 = 0, $qp_1 = 0, $incdec_ptr30 = 0, $11 = 0, $12 = 0, $tobool33 = 0, $_pr27 = 0, $13 = 0, $cmp38 = 0, $call41 = 0, $tobool42 = 0, $or44 = 0, $incdec_ptr45 = 0, $istyle_0_ph_be = 0, $pp_0_ph_be = 0, $14 = 0, $tobool233 = 0, $incdec_ptr47 = 0, $15 = 0, $tobool2 = 0, $istyle_1 = 0, $pstyle_0 = 0, $shape = 0, $16 = 0, $polygon = 0, $17 = 0, $tobool52 = 0, $option = 0, $18 = 0, $or54 = 0, $istyle_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $n | 0;
+ $1 = HEAP32[41560] | 0;
+ $call = _late_nnstring($0, $1, 108168) | 0;
+ $2 = HEAP8[$call] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ $pstyle_0 = 0;
+ $istyle_1 = 0;
+ label = 23;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _parse_style($call) | 0;
+ $3 = HEAP32[1820] | 0;
+ $tobool23337 = ($3 | 0) == 0;
+ if ($tobool23337) {
+ $pstyle_0 = 7280;
+ $istyle_1 = 0;
+ label = 23;
+ break;
+ } else {
+ $istyle_0_ph38 = 0;
+ $pp_0_ph39 = 7280;
+ $4 = $3;
+ label = 6;
+ break;
+ }
+ case 4:
+ $or28 = $istyle_0_ph38 | 4;
+ $pp_0_ph_be = $pp_034;
+ $istyle_0_ph_be = $or28;
+ label = 21;
+ break;
+ case 5:
+ $or16 = $istyle_0_ph38 | 2;
+ $pp_0_ph_be = $pp_034;
+ $istyle_0_ph_be = $or16;
+ label = 21;
+ break;
+ case 6:
+ $pp_034 = $pp_0_ph39;
+ $5 = $4;
+ label = 7;
+ break;
+ case 7:
+ $6 = HEAP8[$5] | 0;
+ $cmp = $6 << 24 >> 24 == 102;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ $7 = $6;
+ label = 11;
+ break;
+ }
+ case 8:
+ $call5 = _strcmp($5 | 0, 106944) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $or = $istyle_0_ph38 | 1;
+ $incdec_ptr = $pp_034 + 4 | 0;
+ $pp_0_ph_be = $incdec_ptr;
+ $istyle_0_ph_be = $or;
+ label = 21;
+ break;
+ case 10:
+ $_pr = HEAP8[$5] | 0;
+ $7 = $_pr;
+ label = 11;
+ break;
+ case 11:
+ $cmp10 = $7 << 24 >> 24 == 114;
+ if ($cmp10) {
+ label = 12;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ $call13 = _strcmp($5 | 0, 106552) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ $qp_0 = $pp_034;
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $incdec_ptr17 = $qp_0 + 4 | 0;
+ $8 = HEAP32[$incdec_ptr17 >> 2] | 0;
+ HEAP32[$qp_0 >> 2] = $8;
+ $9 = HEAP32[$incdec_ptr17 >> 2] | 0;
+ $tobool18 = ($9 | 0) == 0;
+ if ($tobool18) {
+ label = 5;
+ break;
+ } else {
+ $qp_0 = $incdec_ptr17;
+ label = 13;
+ break;
+ }
+ case 14:
+ $10 = HEAP8[$5] | 0;
+ $cmp22 = $10 << 24 >> 24 == 100;
+ if ($cmp22) {
+ label = 15;
+ break;
+ } else {
+ $13 = $10;
+ label = 18;
+ break;
+ }
+ case 15:
+ $call25 = _strcmp($5 | 0, 106216) | 0;
+ $tobool26 = ($call25 | 0) == 0;
+ if ($tobool26) {
+ $qp_1 = $pp_034;
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $incdec_ptr30 = $qp_1 + 4 | 0;
+ $11 = HEAP32[$incdec_ptr30 >> 2] | 0;
+ HEAP32[$qp_1 >> 2] = $11;
+ $12 = HEAP32[$incdec_ptr30 >> 2] | 0;
+ $tobool33 = ($12 | 0) == 0;
+ if ($tobool33) {
+ label = 4;
+ break;
+ } else {
+ $qp_1 = $incdec_ptr30;
+ label = 16;
+ break;
+ }
+ case 17:
+ $_pr27 = HEAP8[$5] | 0;
+ $13 = $_pr27;
+ label = 18;
+ break;
+ case 18:
+ $cmp38 = $13 << 24 >> 24 == 105;
+ if ($cmp38) {
+ label = 19;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 19:
+ $call41 = _strcmp($5 | 0, 105840) | 0;
+ $tobool42 = ($call41 | 0) == 0;
+ if ($tobool42) {
+ label = 20;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 20:
+ $or44 = $istyle_0_ph38 | 16;
+ $incdec_ptr45 = $pp_034 + 4 | 0;
+ $pp_0_ph_be = $incdec_ptr45;
+ $istyle_0_ph_be = $or44;
+ label = 21;
+ break;
+ case 21:
+ $14 = HEAP32[$pp_0_ph_be >> 2] | 0;
+ $tobool233 = ($14 | 0) == 0;
+ if ($tobool233) {
+ $pstyle_0 = 7280;
+ $istyle_1 = $istyle_0_ph_be;
+ label = 23;
+ break;
+ } else {
+ $istyle_0_ph38 = $istyle_0_ph_be;
+ $pp_0_ph39 = $pp_0_ph_be;
+ $4 = $14;
+ label = 6;
+ break;
+ }
+ case 22:
+ $incdec_ptr47 = $pp_034 + 4 | 0;
+ $15 = HEAP32[$incdec_ptr47 >> 2] | 0;
+ $tobool2 = ($15 | 0) == 0;
+ if ($tobool2) {
+ $pstyle_0 = 7280;
+ $istyle_1 = $istyle_0_ph38;
+ label = 23;
+ break;
+ } else {
+ $pp_034 = $incdec_ptr47;
+ $5 = $15;
+ label = 7;
+ break;
+ }
+ case 23:
+ $shape = $n + 24 | 0;
+ $16 = HEAP32[$shape >> 2] | 0;
+ $polygon = $16 + 8 | 0;
+ $17 = HEAP32[$polygon >> 2] | 0;
+ $tobool52 = ($17 | 0) == 0;
+ if ($tobool52) {
+ $istyle_2 = $istyle_1;
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $option = $17 + 40 | 0;
+ $18 = HEAP32[$option >> 2] | 0;
+ $or54 = $18 | $istyle_1;
+ $istyle_2 = $or54;
+ label = 25;
+ break;
+ case 25:
+ HEAP32[$flagp >> 2] = $istyle_2;
+ return $pstyle_0 | 0;
+ }
+ return 0;
+}
+function _map_rec_port($f, $str) {
+ $f = $f | 0;
+ $str = $str | 0;
+ var $id = 0, $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $cmp = 0, $call = 0, $tobool6 = 0, $fld = 0, $n_flds = 0, $3 = 0, $sub_0 = 0, $cmp7 = 0, $4 = 0, $arrayidx = 0, $5 = 0, $call9 = 0, $tobool10 = 0, $inc = 0, $rv_1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $id = $f + 60 | 0;
+ $0 = HEAP32[$id >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$0] | 0;
+ $2 = HEAP8[$str] | 0;
+ $cmp = $1 << 24 >> 24 == $2 << 24 >> 24;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call = _strcmp($0 | 0, $str | 0) | 0;
+ $tobool6 = ($call | 0) == 0;
+ if ($tobool6) {
+ $rv_1 = $f;
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $fld = $f + 56 | 0;
+ $n_flds = $f + 48 | 0;
+ $3 = HEAP32[$n_flds >> 2] | 0;
+ $sub_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ $cmp7 = ($sub_0 | 0) < ($3 | 0);
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ $rv_1 = 0;
+ label = 8;
+ break;
+ }
+ case 7:
+ $4 = HEAP32[$fld >> 2] | 0;
+ $arrayidx = $4 + ($sub_0 << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $call9 = _map_rec_port($5, $str) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ $inc = $sub_0 + 1 | 0;
+ if ($tobool10) {
+ $sub_0 = $inc;
+ label = 6;
+ break;
+ } else {
+ $rv_1 = $call9;
+ label = 8;
+ break;
+ }
+ case 8:
+ return $rv_1 | 0;
+ }
+ return 0;
+}
+function _free_field($f) {
+ $f = $f | 0;
+ var $n_flds = 0, $0 = 0, $cmp8 = 0, $fld = 0, $i_09 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $inc = 0, $3 = 0, $cmp = 0, $id = 0, $4 = 0, $lp = 0, $5 = 0, $fld1 = 0, $6 = 0, $7 = 0, $8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_flds = $f + 48 | 0;
+ $0 = HEAP32[$n_flds >> 2] | 0;
+ $cmp8 = ($0 | 0) > 0;
+ if ($cmp8) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $fld = $f + 56 | 0;
+ $i_09 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$fld >> 2] | 0;
+ $arrayidx = $1 + ($i_09 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _free_field($2);
+ $inc = $i_09 + 1 | 0;
+ $3 = HEAP32[$n_flds >> 2] | 0;
+ $cmp = ($inc | 0) < ($3 | 0);
+ if ($cmp) {
+ $i_09 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $id = $f + 60 | 0;
+ $4 = HEAP32[$id >> 2] | 0;
+ _free($4);
+ $lp = $f + 52 | 0;
+ $5 = HEAP32[$lp >> 2] | 0;
+ _free_label($5);
+ $fld1 = $f + 56 | 0;
+ $6 = HEAP32[$fld1 >> 2] | 0;
+ $7 = $6;
+ _free($7);
+ $8 = $f;
+ _free($8);
+ return;
+ }
+}
+function _poly_free($n) {
+ $n = $n | 0;
+ var $shape_info = 0, $0 = 0, $tobool = 0, $vertices = 0, $1 = 0, $2 = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $shape_info = $n + 28 | 0;
+ $0 = HEAP32[$shape_info >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $vertices = $0 + 44 | 0;
+ $1 = $vertices;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $3 = $2;
+ _free($3);
+ _free($0);
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _point_inside($inside_context, $p) {
+ $inside_context = $inside_context | 0;
+ $p = $p | 0;
+ var $tmp = 0, $n1 = 0, $0 = 0, $graph = 0, $1 = 0, $rankdir = 0, $2 = 0, $and = 0, $mul = 0, $P_sroa_0_0__idx = 0, $P_sroa_0_0_copyload = 0.0, $P_sroa_1_8__idx8 = 0, $P_sroa_1_8_copyload = 0.0, $3 = 0, $cmp = 0, $shape_info = 0, $4 = 0, $peripheries = 0, $5 = 0, $6 = 0, $sub = 0, $mul5 = 0, $cmp6 = 0, $mul5_op = 0, $add9 = 0, $vertices = 0, $7 = 0, $8 = 0, $x = 0, $9 = 0.0, $call = 0.0, $10 = 0.0, $cmp10 = 0, $call11 = 0.0, $cmp12 = 0, $call17 = 0.0, $11 = 0.0, $cmp18 = 0, $conv19 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $n1 = $inside_context;
+ $0 = HEAP32[$n1 >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $1 + 156 | 0;
+ $2 = HEAP32[$rankdir >> 2] | 0;
+ $and = $2 & 3;
+ $mul = $and * 90 & -1;
+ _ccwrotatepf($tmp, $p, $mul);
+ $P_sroa_0_0__idx = $tmp | 0;
+ $P_sroa_0_0_copyload = +HEAPF64[$P_sroa_0_0__idx >> 3];
+ $P_sroa_1_8__idx8 = $tmp + 8 | 0;
+ $P_sroa_1_8_copyload = +HEAPF64[$P_sroa_1_8__idx8 >> 3];
+ $3 = HEAP32[1776] | 0;
+ $cmp = ($0 | 0) == ($3 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $shape_info = $0 + 28 | 0;
+ $4 = HEAP32[$shape_info >> 2] | 0;
+ $peripheries = $4 + 4 | 0;
+ $5 = $peripheries;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $sub = $6 << 1;
+ $mul5 = $sub - 2 | 0;
+ $cmp6 = ($mul5 | 0) < 0;
+ $mul5_op = $mul5 | 1;
+ $add9 = $cmp6 ? 1 : $mul5_op;
+ $vertices = $4 + 44 | 0;
+ $7 = $vertices;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $x = $8 + ($add9 << 4) | 0;
+ $9 = +HEAPF64[$x >> 3];
+ HEAPF64[887] = $9;
+ HEAP32[1776] = $0;
+ label = 4;
+ break;
+ case 4:
+ $call = +Math_abs(+$P_sroa_0_0_copyload);
+ $10 = +HEAPF64[887];
+ $cmp10 = $call > $10;
+ if ($cmp10) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call11 = +Math_abs(+$P_sroa_1_8_copyload);
+ $cmp12 = $call11 > $10;
+ if ($cmp12) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call17 = +_hypot(+$P_sroa_0_0_copyload, +$P_sroa_1_8_copyload);
+ $11 = +HEAPF64[887];
+ $cmp18 = $call17 <= $11;
+ $conv19 = $cmp18 & 1;
+ $retval_0 = $conv19;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _point_gencode($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $style = 0, $obj1 = 0, $0 = 0, $url = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $4 = 0, $_mask = 0, $tobool2 = 0, $flags = 0, $5 = 0, $and = 0, $tobool4 = 0, $6 = 0, $tooltip = 0, $7 = 0, $target = 0, $8 = 0, $id = 0, $9 = 0, $10 = 0, $shape_info = 0, $11 = 0, $vertices6 = 0, $12 = 0, $13 = 0, $sides7 = 0, $14 = 0, $15 = 0, $peripheries8 = 0, $16 = 0, $17 = 0, $18 = 0, $cmp = 0, $add = 0, $19 = 0, $tobool10 = 0, $20 = 0, $mul = 0, $call = 0, $mul11 = 0, $call12 = 0, $call_sink = 0, $21 = 0, $call14 = 0, $22 = 0, $and15 = 0, $tobool16 = 0, $gui_state = 0, $23 = 0, $conv = 0, $and20 = 0, $tobool21 = 0, $24 = 0, $25 = 0, $call23 = 0, $26 = 0, $call24 = 0, $and29 = 0, $tobool30 = 0, $27 = 0, $28 = 0, $call32 = 0, $29 = 0, $call33 = 0, $and38 = 0, $tobool39 = 0, $30 = 0, $31 = 0, $call41 = 0, $32 = 0, $call42 = 0, $and47 = 0, $tobool48 = 0, $33 = 0, $34 = 0, $call50 = 0, $35 = 0, $call51 = 0, $call53 = 0, $color_0 = 0, $cmp58 = 0, $36 = 0, $tobool61 = 0, $cmp6568 = 0, $peripheries_072 = 0, $cmp6866 = 0, $x75 = 0, $y81 = 0, $filled_070 = 0, $j_069 = 0, $mul71 = 0, $37 = 0, $i_067 = 0, $add72 = 0, $P_sroa_0_0__idx = 0, $P_sroa_0_0_copyload = 0.0, $P_sroa_1_8__idx12 = 0, $P_sroa_1_8_copyload = 0.0, $38 = 0.0, $add76 = 0.0, $x78 = 0, $39 = 0.0, $add82 = 0.0, $y84 = 0, $inc = 0, $cmp68 = 0, $40 = 0, $inc86 = 0, $cmp65 = 0, $flags90 = 0, $41 = 0, $and91 = 0, $tobool92 = 0, $42 = 0, $tooltip95 = 0, $43 = 0, $target96 = 0, $44 = 0, $id97 = 0, $45 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $style = __stackBase__ | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $url = $0 + 160 | 0;
+ $1 = HEAP32[$url >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $0 + 212 | 0;
+ $3 = $2;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $_mask = $4 & 1;
+ $tobool2 = ($_mask | 0) == 0;
+ if ($tobool2) {
+ $10 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $flags = $job + 152 | 0;
+ $5 = HEAP32[$flags >> 2] | 0;
+ $and = $5 & 4;
+ $tobool4 = ($and | 0) == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ $10 = 1;
+ label = 6;
+ break;
+ }
+ case 5:
+ $6 = HEAP32[$url >> 2] | 0;
+ $tooltip = $0 + 180 | 0;
+ $7 = HEAP32[$tooltip >> 2] | 0;
+ $target = $0 + 196 | 0;
+ $8 = HEAP32[$target >> 2] | 0;
+ $id = $0 + 164 | 0;
+ $9 = HEAP32[$id >> 2] | 0;
+ _gvrender_begin_anchor($job, $6, $7, $8, $9);
+ $10 = 1;
+ label = 6;
+ break;
+ case 6:
+ $shape_info = $n + 28 | 0;
+ $11 = HEAP32[$shape_info >> 2] | 0;
+ $vertices6 = $11 + 44 | 0;
+ $12 = $vertices6;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $sides7 = $11 + 8 | 0;
+ $14 = $sides7;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $peripheries8 = $11 + 4 | 0;
+ $16 = $peripheries8;
+ $17 = HEAP32[$16 >> 2] | 0;
+ $18 = HEAP32[1778] | 0;
+ $cmp = ($18 | 0) < ($15 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $add = $15 + 2 | 0;
+ HEAP32[1778] = $add;
+ $19 = HEAP32[1780] | 0;
+ $tobool10 = ($19 | 0) == 0;
+ if ($tobool10) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $20 = $19;
+ $mul = $add << 4;
+ $call = _grealloc($20, $mul) | 0;
+ $call_sink = $call;
+ label = 10;
+ break;
+ case 9:
+ $mul11 = $add << 4;
+ $call12 = _gmalloc($mul11) | 0;
+ $call_sink = $call12;
+ label = 10;
+ break;
+ case 10:
+ $21 = $call_sink;
+ HEAP32[1780] = $21;
+ label = 11;
+ break;
+ case 11:
+ $call14 = _checkStyle($n, $style) | 0;
+ $22 = HEAP32[$style >> 2] | 0;
+ $and15 = $22 & 16;
+ $tobool16 = ($and15 | 0) == 0;
+ if ($tobool16) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _gvrender_set_style($job, 7080);
+ label = 14;
+ break;
+ case 13:
+ _gvrender_set_style($job, 7084);
+ label = 14;
+ break;
+ case 14:
+ $gui_state = $n + 133 | 0;
+ $23 = HEAP8[$gui_state] | 0;
+ $conv = $23 & 255;
+ $and20 = $conv & 1;
+ $tobool21 = ($and20 | 0) == 0;
+ if ($tobool21) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $24 = $n | 0;
+ $25 = HEAP32[41618] | 0;
+ $call23 = _late_nnstring($24, $25, 105440) | 0;
+ _gvrender_set_pencolor($job, $call23);
+ $26 = HEAP32[41620] | 0;
+ $call24 = _late_nnstring($24, $26, 105128) | 0;
+ _gvrender_set_fillcolor($job, $call24);
+ $color_0 = $call24;
+ label = 23;
+ break;
+ case 16:
+ $and29 = $conv & 2;
+ $tobool30 = ($and29 | 0) == 0;
+ if ($tobool30) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $27 = $n | 0;
+ $28 = HEAP32[41570] | 0;
+ $call32 = _late_nnstring($27, $28, 104760) | 0;
+ _gvrender_set_pencolor($job, $call32);
+ $29 = HEAP32[41572] | 0;
+ $call33 = _late_nnstring($27, $29, 104240) | 0;
+ _gvrender_set_fillcolor($job, $call33);
+ $color_0 = $call33;
+ label = 23;
+ break;
+ case 18:
+ $and38 = $conv & 8;
+ $tobool39 = ($and38 | 0) == 0;
+ if ($tobool39) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $30 = $n | 0;
+ $31 = HEAP32[41610] | 0;
+ $call41 = _late_nnstring($30, $31, 103768) | 0;
+ _gvrender_set_pencolor($job, $call41);
+ $32 = HEAP32[41612] | 0;
+ $call42 = _late_nnstring($30, $32, 103376) | 0;
+ _gvrender_set_fillcolor($job, $call42);
+ $color_0 = $call42;
+ label = 23;
+ break;
+ case 20:
+ $and47 = $conv & 4;
+ $tobool48 = ($and47 | 0) == 0;
+ if ($tobool48) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $33 = $n | 0;
+ $34 = HEAP32[41554] | 0;
+ $call50 = _late_nnstring($33, $34, 103016) | 0;
+ _gvrender_set_pencolor($job, $call50);
+ $35 = HEAP32[41556] | 0;
+ $call51 = _late_nnstring($33, $35, 102672) | 0;
+ _gvrender_set_fillcolor($job, $call51);
+ $color_0 = $call51;
+ label = 23;
+ break;
+ case 22:
+ $call53 = _findFillDflt($n, 107704) | 0;
+ _gvrender_set_fillcolor($job, $call53);
+ _pencolor($job, $n);
+ $color_0 = $call53;
+ label = 23;
+ break;
+ case 23:
+ $cmp58 = ($17 | 0) == 0;
+ if ($cmp58) {
+ label = 24;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 24:
+ $36 = HEAP8[$color_0] | 0;
+ $tobool61 = $36 << 24 >> 24 == 0;
+ if ($tobool61) {
+ $peripheries_072 = 1;
+ label = 27;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ _gvrender_set_pencolor($job, $color_0);
+ $peripheries_072 = 1;
+ label = 27;
+ break;
+ case 26:
+ $cmp6568 = ($17 | 0) > 0;
+ if ($cmp6568) {
+ $peripheries_072 = $17;
+ label = 27;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 27:
+ $cmp6866 = ($15 | 0) > 0;
+ $x75 = $n + 32 | 0;
+ $y81 = $n + 40 | 0;
+ $j_069 = 0;
+ $filled_070 = 1;
+ label = 28;
+ break;
+ case 28:
+ if ($cmp6866) {
+ label = 29;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 29:
+ $mul71 = Math_imul($j_069, $15);
+ $37 = HEAP32[1780] | 0;
+ $i_067 = 0;
+ label = 30;
+ break;
+ case 30:
+ $add72 = $i_067 + $mul71 | 0;
+ $P_sroa_0_0__idx = $13 + ($add72 << 4) | 0;
+ $P_sroa_0_0_copyload = +HEAPF64[$P_sroa_0_0__idx >> 3];
+ $P_sroa_1_8__idx12 = $13 + ($add72 << 4) + 8 | 0;
+ $P_sroa_1_8_copyload = +HEAPF64[$P_sroa_1_8__idx12 >> 3];
+ $38 = +HEAPF64[$x75 >> 3];
+ $add76 = $P_sroa_0_0_copyload + $38;
+ $x78 = $37 + ($i_067 << 4) | 0;
+ HEAPF64[$x78 >> 3] = $add76;
+ $39 = +HEAPF64[$y81 >> 3];
+ $add82 = $P_sroa_1_8_copyload + $39;
+ $y84 = $37 + ($i_067 << 4) + 8 | 0;
+ HEAPF64[$y84 >> 3] = $add82;
+ $inc = $i_067 + 1 | 0;
+ $cmp68 = ($inc | 0) < ($15 | 0);
+ if ($cmp68) {
+ $i_067 = $inc;
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $40 = HEAP32[1780] | 0;
+ _gvrender_ellipse($job, $40, 0, $filled_070);
+ $inc86 = $j_069 + 1 | 0;
+ $cmp65 = ($inc86 | 0) < ($peripheries_072 | 0);
+ if ($cmp65) {
+ $j_069 = $inc86;
+ $filled_070 = 0;
+ label = 28;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ if ($10) {
+ label = 33;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 33:
+ $flags90 = $job + 152 | 0;
+ $41 = HEAP32[$flags90 >> 2] | 0;
+ $and91 = $41 & 4;
+ $tobool92 = ($and91 | 0) == 0;
+ if ($tobool92) {
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $42 = HEAP32[$url >> 2] | 0;
+ $tooltip95 = $0 + 180 | 0;
+ $43 = HEAP32[$tooltip95 >> 2] | 0;
+ $target96 = $0 + 196 | 0;
+ $44 = HEAP32[$target96 >> 2] | 0;
+ $id97 = $0 + 164 | 0;
+ $45 = HEAP32[$id97 >> 2] | 0;
+ _gvrender_begin_anchor($job, $42, $43, $44, $45);
+ label = 35;
+ break;
+ case 35:
+ _gvrender_end_anchor($job);
+ label = 36;
+ break;
+ case 36:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _poly_path($n, $p, $side, $rv, $kptr) {
+ $n = $n | 0;
+ $p = $p | 0;
+ $side = $side | 0;
+ $rv = $rv | 0;
+ $kptr = $kptr | 0;
+ return 0;
+}
+function _same_side($p0, $p1, $L0, $L1) {
+ $p0 = $p0 | 0;
+ $p1 = $p1 | 0;
+ $L0 = $L0 | 0;
+ $L1 = $L1 | 0;
+ var $1 = 0.0, $sub2 = 0.0, $3 = 0.0, $sub4 = 0.0, $add = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p0;
+ $p0 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p0 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p0 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p0 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p0 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $p1;
+ $p1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $L0;
+ $L0 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$L0 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$L0 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$L0 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$L0 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $L1;
+ $L1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$L1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$L1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$L1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$L1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $1 = +HEAPF64[$L0 + 8 >> 3];
+ $sub2 = -0.0 - (+HEAPF64[$L1 + 8 >> 3] - $1);
+ $3 = +HEAPF64[$L0 >> 3];
+ $sub4 = +HEAPF64[$L1 >> 3] - $3;
+ $add = $3 * $sub2 + $1 * $sub4;
+ STACKTOP = __stackBase__;
+ return (+HEAPF64[$p0 >> 3] * $sub2 + $sub4 * +HEAPF64[$p0 + 8 >> 3] - $add >= 0.0 ^ +HEAPF64[$p1 >> 3] * $sub2 + $sub4 * +HEAPF64[$p1 + 8 >> 3] - $add >= 0.0) & 1 ^ 1 | 0;
+}
+function _poly_inside($inside_context, $p) {
+ $inside_context = $inside_context | 0;
+ $p = $p | 0;
+ var $P = 0, $Q = 0, $R = 0, $bp2 = 0, $0 = 0, $n4 = 0, $1 = 0, $graph = 0, $2 = 0, $rankdir = 0, $3 = 0, $and = 0, $mul = 0, $tobool = 0, $bbox_sroa_0_0_copyload = 0.0, $4 = 0, $bbox_sroa_1_8_copyload = 0.0, $5 = 0, $bbox_sroa_3_24_copyload = 0.0, $x6 = 0, $6 = 0.0, $cmp = 0, $7 = 0, $bbox_sroa_2_16_copyload = 0.0, $cmp9 = 0, $y11 = 0, $8 = 0.0, $cmp12 = 0, $cmp17 = 0, $phitmp = 0, $9 = 0, $cmp19 = 0, $shape_info = 0, $10 = 0, $11 = 0, $vertices = 0, $12 = 0, $13 = 0, $sides = 0, $14 = 0, $15 = 0, $16 = 0, $rankdir25 = 0, $17 = 0, $and27 = 0, $tobool28 = 0, $lw = 0, $18 = 0.0, $rw = 0, $19 = 0.0, $add = 0.0, $ht = 0, $20 = 0.0, $ht39 = 0, $21 = 0.0, $22 = 0.0, $cmp41 = 0, $23 = 0.0, $cmp45 = 0, $width = 0, $24 = 0.0, $mul50 = 0.0, $cmp51 = 0, $add56 = 0.0, $sub = 0.0, $add56_sink = 0.0, $conv57 = 0, $conv62 = 0.0, $25 = 0.0, $div = 0.0, $height = 0, $26 = 0.0, $mul64 = 0.0, $cmp65 = 0, $add71 = 0.0, $sub77 = 0.0, $add71_sink = 0.0, $conv72 = 0, $conv81 = 0.0, $27 = 0.0, $div82 = 0.0, $28 = 0.0, $mul85 = 0.0, $cmp86 = 0, $add92 = 0.0, $sub98 = 0.0, $add92_sink = 0.0, $conv93 = 0, $conv102 = 0.0, $div103 = 0.0, $29 = 0.0, $mul106 = 0.0, $cmp107 = 0, $add113 = 0.0, $sub119 = 0.0, $add113_sink = 0.0, $conv114 = 0, $conv123 = 0.0, $div124 = 0.0, $30 = 0, $peripheries = 0, $31 = 0, $sub125 = 0, $32 = 0, $mul126 = 0, $cmp127 = 0, $_mul126 = 0, $33 = 0.0, $x132 = 0, $34 = 0.0, $mul133 = 0.0, $35 = 0.0, $y134 = 0, $36 = 0.0, $mul135 = 0.0, $37 = 0.0, $call = 0.0, $38 = 0.0, $cmp137 = 0, $call140 = 0.0, $39 = 0.0, $cmp141 = 0, $40 = 0, $cmp145 = 0, $div149 = 0.0, $div151 = 0.0, $call152 = 0.0, $cmp153 = 0, $conv155 = 0, $41 = 0, $rem = 0, $add157 = 0, $rem158 = 0, $42 = 0, $add159 = 0, $43 = 0, $arrayidx = 0, $44 = 0, $45 = 0, $46 = 0, $add160 = 0, $47 = 0, $arrayidx161 = 0, $48 = 0, $49 = 0, $call162 = 0, $tobool163 = 0, $call166 = 0, $tobool167 = 0, $call169 = 0, $tobool170 = 0, $50 = 0, $51 = 0, $52 = 0, $j_0 = 0, $i1_0 = 0, $i_0 = 0, $cmp173 = 0, $add177 = 0, $rem178 = 0, $add180 = 0, $sub181 = 0, $rem182 = 0, $i1_1 = 0, $i_1 = 0, $add184 = 0, $arrayidx185 = 0, $add186 = 0, $arrayidx187 = 0, $call188 = 0, $tobool189 = 0, $inc = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $P = __stackBase__ | 0;
+ $Q = __stackBase__ + 16 | 0;
+ $R = __stackBase__ + 32 | 0;
+ $bp2 = $inside_context + 4 | 0;
+ $0 = HEAP32[$bp2 >> 2] | 0;
+ $n4 = $inside_context;
+ $1 = HEAP32[$n4 >> 2] | 0;
+ $graph = $1 + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $2 + 156 | 0;
+ $3 = HEAP32[$rankdir >> 2] | 0;
+ $and = $3 & 3;
+ $mul = $and * 90 & -1;
+ _ccwrotatepf($P, $p, $mul);
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $bbox_sroa_0_0_copyload = +HEAPF64[$0 >> 3];
+ $4 = $0 + 8 | 0;
+ $bbox_sroa_1_8_copyload = +HEAPF64[$4 >> 3];
+ $5 = $0 + 24 | 0;
+ $bbox_sroa_3_24_copyload = +HEAPF64[$5 >> 3];
+ $x6 = $P | 0;
+ $6 = +HEAPF64[$x6 >> 3];
+ $cmp = $bbox_sroa_0_0_copyload > $6;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 43;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $7 = $0 + 16 | 0;
+ $bbox_sroa_2_16_copyload = +HEAPF64[$7 >> 3];
+ $cmp9 = $6 > $bbox_sroa_2_16_copyload;
+ if ($cmp9) {
+ $retval_0 = 0;
+ label = 43;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y11 = $P + 8 | 0;
+ $8 = +HEAPF64[$y11 >> 3];
+ $cmp12 = $bbox_sroa_1_8_copyload > $8;
+ if ($cmp12) {
+ $retval_0 = 0;
+ label = 43;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp17 = $8 <= $bbox_sroa_3_24_copyload;
+ $phitmp = $cmp17 & 1;
+ $retval_0 = $phitmp;
+ label = 43;
+ break;
+ case 7:
+ $9 = HEAP32[1748] | 0;
+ $cmp19 = ($1 | 0) == ($9 | 0);
+ if ($cmp19) {
+ label = 28;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $shape_info = $1 + 28 | 0;
+ $10 = HEAP32[$shape_info >> 2] | 0;
+ $11 = $10;
+ HEAP32[1744] = $11;
+ $vertices = $10 + 44 | 0;
+ $12 = $vertices;
+ $13 = HEAP32[$12 >> 2] | 0;
+ HEAP32[1736] = $13;
+ $sides = $10 + 8 | 0;
+ $14 = $sides;
+ $15 = HEAP32[$14 >> 2] | 0;
+ HEAP32[1738] = $15;
+ $16 = HEAP32[$graph >> 2] | 0;
+ $rankdir25 = $16 + 156 | 0;
+ $17 = HEAP32[$rankdir25 >> 2] | 0;
+ $and27 = $17 & 1;
+ $tobool28 = ($and27 | 0) == 0;
+ $lw = $1 + 104 | 0;
+ $18 = +HEAPF64[$lw >> 3];
+ $rw = $1 + 112 | 0;
+ $19 = +HEAPF64[$rw >> 3];
+ $add = $18 + $19;
+ if ($tobool28) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ HEAPF64[866] = $add;
+ $ht = $1 + 96 | 0;
+ $20 = +HEAPF64[$ht >> 3];
+ HEAPF64[867] = $20;
+ $22 = $20;
+ label = 11;
+ break;
+ case 10:
+ HEAPF64[867] = $add;
+ $ht39 = $1 + 96 | 0;
+ $21 = +HEAPF64[$ht39 >> 3];
+ HEAPF64[866] = $21;
+ $22 = $add;
+ label = 11;
+ break;
+ case 11:
+ $cmp41 = $22 == 0.0;
+ if ($cmp41) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ HEAPF64[867] = 1.0;
+ label = 13;
+ break;
+ case 13:
+ $23 = +HEAPF64[866];
+ $cmp45 = $23 == 0.0;
+ if ($cmp45) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAPF64[866] = 1.0;
+ label = 15;
+ break;
+ case 15:
+ $width = $1 + 48 | 0;
+ $24 = +HEAPF64[$width >> 3];
+ $mul50 = $24 * 72.0;
+ $cmp51 = $mul50 < 0.0;
+ if ($cmp51) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $add56 = $mul50 + .5;
+ $add56_sink = $add56;
+ label = 18;
+ break;
+ case 17:
+ $sub = $mul50 + -.5;
+ $add56_sink = $sub;
+ label = 18;
+ break;
+ case 18:
+ $conv57 = ~~$add56_sink;
+ $conv62 = +($conv57 | 0);
+ $25 = +HEAPF64[867];
+ $div = $conv62 / $25;
+ HEAPF64[871] = $div;
+ $height = $1 + 56 | 0;
+ $26 = +HEAPF64[$height >> 3];
+ $mul64 = $26 * 72.0;
+ $cmp65 = $mul64 < 0.0;
+ if ($cmp65) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $add71 = $mul64 + .5;
+ $add71_sink = $add71;
+ label = 21;
+ break;
+ case 20:
+ $sub77 = $mul64 + -.5;
+ $add71_sink = $sub77;
+ label = 21;
+ break;
+ case 21:
+ $conv72 = ~~$add71_sink;
+ $conv81 = +($conv72 | 0);
+ $27 = +HEAPF64[866];
+ $div82 = $conv81 / $27;
+ HEAPF64[870] = $div82;
+ $28 = +HEAPF64[$width >> 3];
+ $mul85 = $28 * 72.0;
+ $cmp86 = $mul85 < 0.0;
+ if ($cmp86) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $add92 = $mul85 + .5;
+ $add92_sink = $add92;
+ label = 24;
+ break;
+ case 23:
+ $sub98 = $mul85 + -.5;
+ $add92_sink = $sub98;
+ label = 24;
+ break;
+ case 24:
+ $conv93 = ~~$add92_sink;
+ $conv102 = +($conv93 | 0);
+ $div103 = $conv102 * .5;
+ HEAPF64[877] = $div103;
+ $29 = +HEAPF64[$height >> 3];
+ $mul106 = $29 * 72.0;
+ $cmp107 = $mul106 < 0.0;
+ if ($cmp107) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $add113 = $mul106 + .5;
+ $add113_sink = $add113;
+ label = 27;
+ break;
+ case 26:
+ $sub119 = $mul106 + -.5;
+ $add113_sink = $sub119;
+ label = 27;
+ break;
+ case 27:
+ $conv114 = ~~$add113_sink;
+ $conv123 = +($conv114 | 0);
+ $div124 = $conv123 * .5;
+ HEAPF64[876] = $div124;
+ $30 = HEAP32[1744] | 0;
+ $peripheries = $30 + 4 | 0;
+ $31 = HEAP32[$peripheries >> 2] | 0;
+ $sub125 = $31 - 1 | 0;
+ $32 = HEAP32[1738] | 0;
+ $mul126 = Math_imul($sub125, $32);
+ $cmp127 = ($mul126 | 0) < 0;
+ $_mul126 = $cmp127 ? 0 : $mul126;
+ HEAP32[1746] = $_mul126;
+ HEAP32[1748] = $1;
+ label = 28;
+ break;
+ case 28:
+ $33 = +HEAPF64[871];
+ $x132 = $P | 0;
+ $34 = +HEAPF64[$x132 >> 3];
+ $mul133 = $33 * $34;
+ HEAPF64[$x132 >> 3] = $mul133;
+ $35 = +HEAPF64[870];
+ $y134 = $P + 8 | 0;
+ $36 = +HEAPF64[$y134 >> 3];
+ $mul135 = $35 * $36;
+ HEAPF64[$y134 >> 3] = $mul135;
+ $37 = +HEAPF64[$x132 >> 3];
+ $call = +Math_abs(+$37);
+ $38 = +HEAPF64[877];
+ $cmp137 = $call > $38;
+ if ($cmp137) {
+ $retval_0 = 0;
+ label = 43;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $call140 = +Math_abs(+$mul135);
+ $39 = +HEAPF64[876];
+ $cmp141 = $call140 > $39;
+ if ($cmp141) {
+ $retval_0 = 0;
+ label = 43;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $40 = HEAP32[1738] | 0;
+ $cmp145 = ($40 | 0) < 3;
+ if ($cmp145) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ $div149 = $37 / $38;
+ $div151 = $mul135 / $39;
+ $call152 = +_hypot(+$div149, +$div151);
+ $cmp153 = $call152 < 1.0;
+ $conv155 = $cmp153 & 1;
+ $retval_0 = $conv155;
+ label = 43;
+ break;
+ case 32:
+ $41 = HEAP32[1750] | 0;
+ $rem = ($41 | 0) % ($40 | 0);
+ $add157 = $rem + 1 | 0;
+ $rem158 = ($add157 | 0) % ($40 | 0);
+ $42 = HEAP32[1746] | 0;
+ $add159 = $42 + $rem | 0;
+ $43 = HEAP32[1736] | 0;
+ $arrayidx = $43 + ($add159 << 4) | 0;
+ $44 = $Q;
+ $45 = $arrayidx;
+ HEAP32[$44 >> 2] = HEAP32[$45 >> 2] | 0;
+ HEAP32[$44 + 4 >> 2] = HEAP32[$45 + 4 >> 2] | 0;
+ HEAP32[$44 + 8 >> 2] = HEAP32[$45 + 8 >> 2] | 0;
+ HEAP32[$44 + 12 >> 2] = HEAP32[$45 + 12 >> 2] | 0;
+ $46 = HEAP32[1746] | 0;
+ $add160 = $46 + $rem158 | 0;
+ $47 = HEAP32[1736] | 0;
+ $arrayidx161 = $47 + ($add160 << 4) | 0;
+ $48 = $R;
+ $49 = $arrayidx161;
+ HEAP32[$48 >> 2] = HEAP32[$49 >> 2] | 0;
+ HEAP32[$48 + 4 >> 2] = HEAP32[$49 + 4 >> 2] | 0;
+ HEAP32[$48 + 8 >> 2] = HEAP32[$49 + 8 >> 2] | 0;
+ HEAP32[$48 + 12 >> 2] = HEAP32[$49 + 12 >> 2] | 0;
+ $call162 = _same_side($P, 7024, $Q, $R) | 0;
+ $tobool163 = ($call162 | 0) == 0;
+ if ($tobool163) {
+ $retval_0 = 0;
+ label = 43;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $call166 = _same_side($P, $Q, $R, 7024) | 0;
+ $tobool167 = ($call166 | 0) != 0;
+ if ($tobool167) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ $call169 = _same_side($P, $R, 7024, $Q) | 0;
+ $tobool170 = ($call169 | 0) == 0;
+ if ($tobool170) {
+ label = 35;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 43;
+ break;
+ }
+ case 35:
+ $50 = HEAP32[1738] | 0;
+ $51 = HEAP32[1746] | 0;
+ $52 = HEAP32[1736] | 0;
+ $i_0 = $rem;
+ $i1_0 = $rem158;
+ $j_0 = 1;
+ label = 36;
+ break;
+ case 36:
+ $cmp173 = ($j_0 | 0) < ($50 | 0);
+ if ($cmp173) {
+ label = 37;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 37:
+ if ($tobool167) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ $add177 = $i1_0 + 1 | 0;
+ $rem178 = ($add177 | 0) % ($50 | 0);
+ $i_1 = $i1_0;
+ $i1_1 = $rem178;
+ label = 40;
+ break;
+ case 39:
+ $add180 = $i_0 - 1 | 0;
+ $sub181 = $add180 + $50 | 0;
+ $rem182 = ($sub181 | 0) % ($50 | 0);
+ $i_1 = $rem182;
+ $i1_1 = $i_0;
+ label = 40;
+ break;
+ case 40:
+ $add184 = $51 + $i_1 | 0;
+ $arrayidx185 = $52 + ($add184 << 4) | 0;
+ $add186 = $51 + $i1_1 | 0;
+ $arrayidx187 = $52 + ($add186 << 4) | 0;
+ $call188 = _same_side($P, 7024, $arrayidx185, $arrayidx187) | 0;
+ $tobool189 = ($call188 | 0) == 0;
+ $inc = $j_0 + 1 | 0;
+ if ($tobool189) {
+ label = 41;
+ break;
+ } else {
+ $i_0 = $i_1;
+ $i1_0 = $i1_1;
+ $j_0 = $inc;
+ label = 36;
+ break;
+ }
+ case 41:
+ HEAP32[1750] = $i_1;
+ $retval_0 = 0;
+ label = 43;
+ break;
+ case 42:
+ HEAP32[1750] = $i_0;
+ $retval_0 = 1;
+ label = 43;
+ break;
+ case 43:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _poly_gencode($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $obj1 = 0, $0 = 0, $url = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $4 = 0, $_mask = 0, $tobool2 = 0, $flags = 0, $5 = 0, $and = 0, $tobool4 = 0, $6 = 0, $tooltip = 0, $7 = 0, $target = 0, $8 = 0, $id = 0, $9 = 0, $10 = 0, $shape_info = 0, $11 = 0, $vertices6 = 0, $12 = 0, $13 = 0, $sides7 = 0, $14 = 0, $15 = 0, $peripheries8 = 0, $16 = 0, $17 = 0, $18 = 0, $cmp = 0, $add = 0, $19 = 0, $tobool10 = 0, $20 = 0, $mul = 0, $call = 0, $mul11 = 0, $call12 = 0, $call_sink = 0, $21 = 0, $label = 0, $22 = 0, $pos = 0, $coord = 0, $23 = 0, $24 = 0, $lw = 0, $25 = 0.0, $rw = 0, $26 = 0.0, $add18 = 0.0, $width = 0, $27 = 0.0, $mul20 = 0.0, $cmp21 = 0, $add26 = 0.0, $sub = 0.0, $add26_sink = 0.0, $conv = 0, $conv34 = 0.0, $div = 0.0, $ht = 0, $28 = 0.0, $height = 0, $29 = 0.0, $mul37 = 0.0, $cmp38 = 0, $add44 = 0.0, $sub50 = 0.0, $add44_sink = 0.0, $conv45 = 0, $conv54 = 0.0, $div55 = 0.0, $call56 = 0, $gui_state = 0, $30 = 0, $conv58 = 0, $and59 = 0, $tobool60 = 0, $31 = 0, $32 = 0, $call62 = 0, $33 = 0, $call63 = 0, $and67 = 0, $tobool68 = 0, $34 = 0, $35 = 0, $call70 = 0, $36 = 0, $call71 = 0, $and76 = 0, $tobool77 = 0, $37 = 0, $38 = 0, $call79 = 0, $39 = 0, $call80 = 0, $and85 = 0, $tobool86 = 0, $40 = 0, $41 = 0, $call88 = 0, $42 = 0, $call89 = 0, $and91 = 0, $tobool92 = 0, $call94 = 0, $filled_0 = 0, $filled_1 = 0, $shape = 0, $43 = 0, $usershape = 0, $44 = 0, $tobool102 = 0, $name106 = 0, $45 = 0, $46 = 0, $cmp109 = 0, $tobool123140 = 0, $call114 = 0, $phitmp = 0, $47 = 0, $cmp119 = 0, $tobool123 = 0, $or_cond = 0, $or_cond137 = 0, $call129 = 0, $48 = 0, $tobool130 = 0, $tobool126145 = 0, $tobool123144 = 0, $peripheries_0 = 0, $49 = 0, $usershape136 = 0, $50 = 0, $tobool137 = 0, $name141 = 0, $51 = 0, $52 = 0, $cmp144 = 0, $call147 = 0, $tobool148 = 0, $53 = 0, $call150 = 0, $54 = 0, $call153 = 0, $not_tobool154 = 0, $name_1146_ph = 0, $cmp160152 = 0, $x166 = 0, $55 = 0, $y173 = 0, $i_0153 = 0, $P_sroa_0_0__idx23 = 0, $P_sroa_0_0_copyload24 = 0.0, $P_sroa_1_8__idx27 = 0, $P_sroa_1_8_copyload28 = 0.0, $mul163 = 0.0, $56 = 0.0, $add167 = 0.0, $x169 = 0, $mul170 = 0.0, $57 = 0.0, $add174 = 0.0, $y176 = 0, $inc = 0, $cmp160 = 0, $conv177 = 0, $or_cond138 = 0, $cmp183 = 0, $58 = 0, $and186 = 0, $tobool187 = 0, $and191 = 0, $tobool192 = 0, $59 = 0, $60 = 0, $61 = 0, $62 = 0, $call199 = 0, $filled_3_ph = 0, $cmp202149 = 0, $cmp206147 = 0, $cmp231 = 0, $and234 = 0, $tobool235 = 0, $and239 = 0, $tobool240 = 0, $x216 = 0, $y224 = 0, $j_0151 = 0, $filled_3150 = 0, $mul209 = 0, $63 = 0, $i_1148 = 0, $add210 = 0, $P_sroa_0_0__idx = 0, $P_sroa_0_0_copyload = 0.0, $P_sroa_1_8__idx25 = 0, $P_sroa_1_8_copyload = 0.0, $mul213 = 0.0, $64 = 0.0, $add217 = 0.0, $x219 = 0, $mul221 = 0.0, $65 = 0.0, $add225 = 0.0, $y227 = 0, $inc229 = 0, $cmp206 = 0, $66 = 0, $conv242 = 0, $inc247 = 0, $cmp202 = 0, $67 = 0, $flags253 = 0, $68 = 0, $and254 = 0, $tobool255 = 0, $69 = 0, $tooltip258 = 0, $70 = 0, $target259 = 0, $71 = 0, $id260 = 0, $72 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $url = $0 + 160 | 0;
+ $1 = HEAP32[$url >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $0 + 212 | 0;
+ $3 = $2;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $_mask = $4 & 1;
+ $tobool2 = ($_mask | 0) == 0;
+ if ($tobool2) {
+ $10 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $flags = $job + 152 | 0;
+ $5 = HEAP32[$flags >> 2] | 0;
+ $and = $5 & 4;
+ $tobool4 = ($and | 0) == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ $10 = 1;
+ label = 6;
+ break;
+ }
+ case 5:
+ $6 = HEAP32[$url >> 2] | 0;
+ $tooltip = $0 + 180 | 0;
+ $7 = HEAP32[$tooltip >> 2] | 0;
+ $target = $0 + 196 | 0;
+ $8 = HEAP32[$target >> 2] | 0;
+ $id = $0 + 164 | 0;
+ $9 = HEAP32[$id >> 2] | 0;
+ _gvrender_begin_anchor($job, $6, $7, $8, $9);
+ $10 = 1;
+ label = 6;
+ break;
+ case 6:
+ $shape_info = $n + 28 | 0;
+ $11 = HEAP32[$shape_info >> 2] | 0;
+ $vertices6 = $11 + 44 | 0;
+ $12 = $vertices6;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $sides7 = $11 + 8 | 0;
+ $14 = $sides7;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $peripheries8 = $11 + 4 | 0;
+ $16 = $peripheries8;
+ $17 = HEAP32[$16 >> 2] | 0;
+ $18 = HEAP32[1760] | 0;
+ $cmp = ($18 | 0) < ($15 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $add = $15 + 5 | 0;
+ HEAP32[1760] = $add;
+ $19 = HEAP32[1762] | 0;
+ $tobool10 = ($19 | 0) == 0;
+ if ($tobool10) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $20 = $19;
+ $mul = $add << 4;
+ $call = _grealloc($20, $mul) | 0;
+ $call_sink = $call;
+ label = 10;
+ break;
+ case 9:
+ $mul11 = $add << 4;
+ $call12 = _gmalloc($mul11) | 0;
+ $call_sink = $call12;
+ label = 10;
+ break;
+ case 10:
+ $21 = $call_sink;
+ HEAP32[1762] = $21;
+ label = 11;
+ break;
+ case 11:
+ $label = $n + 120 | 0;
+ $22 = HEAP32[$label >> 2] | 0;
+ $pos = $22 + 56 | 0;
+ $coord = $n + 32 | 0;
+ $23 = $pos;
+ $24 = $coord;
+ HEAP32[$23 >> 2] = HEAP32[$24 >> 2] | 0;
+ HEAP32[$23 + 4 >> 2] = HEAP32[$24 + 4 >> 2] | 0;
+ HEAP32[$23 + 8 >> 2] = HEAP32[$24 + 8 >> 2] | 0;
+ HEAP32[$23 + 12 >> 2] = HEAP32[$24 + 12 >> 2] | 0;
+ $lw = $n + 104 | 0;
+ $25 = +HEAPF64[$lw >> 3];
+ $rw = $n + 112 | 0;
+ $26 = +HEAPF64[$rw >> 3];
+ $add18 = $25 + $26;
+ $width = $n + 48 | 0;
+ $27 = +HEAPF64[$width >> 3];
+ $mul20 = $27 * 72.0;
+ $cmp21 = $mul20 < 0.0;
+ if ($cmp21) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $add26 = $mul20 + .5;
+ $add26_sink = $add26;
+ label = 14;
+ break;
+ case 13:
+ $sub = $mul20 + -.5;
+ $add26_sink = $sub;
+ label = 14;
+ break;
+ case 14:
+ $conv = ~~$add26_sink;
+ $conv34 = +($conv | 0);
+ $div = $add18 / $conv34;
+ $ht = $n + 96 | 0;
+ $28 = +HEAPF64[$ht >> 3];
+ $height = $n + 56 | 0;
+ $29 = +HEAPF64[$height >> 3];
+ $mul37 = $29 * 72.0;
+ $cmp38 = $mul37 < 0.0;
+ if ($cmp38) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $add44 = $mul37 + .5;
+ $add44_sink = $add44;
+ label = 17;
+ break;
+ case 16:
+ $sub50 = $mul37 + -.5;
+ $add44_sink = $sub50;
+ label = 17;
+ break;
+ case 17:
+ $conv45 = ~~$add44_sink;
+ $conv54 = +($conv45 | 0);
+ $div55 = $28 / $conv54;
+ $call56 = _stylenode($job, $n) | 0;
+ $gui_state = $n + 133 | 0;
+ $30 = HEAP8[$gui_state] | 0;
+ $conv58 = $30 & 255;
+ $and59 = $conv58 & 1;
+ $tobool60 = ($and59 | 0) == 0;
+ if ($tobool60) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $31 = $n | 0;
+ $32 = HEAP32[41618] | 0;
+ $call62 = _late_nnstring($31, $32, 105440) | 0;
+ _gvrender_set_pencolor($job, $call62);
+ $33 = HEAP32[41620] | 0;
+ $call63 = _late_nnstring($31, $33, 105128) | 0;
+ _gvrender_set_fillcolor($job, $call63);
+ $filled_1 = 1;
+ label = 28;
+ break;
+ case 19:
+ $and67 = $conv58 & 2;
+ $tobool68 = ($and67 | 0) == 0;
+ if ($tobool68) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $34 = $n | 0;
+ $35 = HEAP32[41570] | 0;
+ $call70 = _late_nnstring($34, $35, 104760) | 0;
+ _gvrender_set_pencolor($job, $call70);
+ $36 = HEAP32[41572] | 0;
+ $call71 = _late_nnstring($34, $36, 104240) | 0;
+ _gvrender_set_fillcolor($job, $call71);
+ $filled_1 = 1;
+ label = 28;
+ break;
+ case 21:
+ $and76 = $conv58 & 8;
+ $tobool77 = ($and76 | 0) == 0;
+ if ($tobool77) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $37 = $n | 0;
+ $38 = HEAP32[41610] | 0;
+ $call79 = _late_nnstring($37, $38, 103768) | 0;
+ _gvrender_set_pencolor($job, $call79);
+ $39 = HEAP32[41612] | 0;
+ $call80 = _late_nnstring($37, $39, 103376) | 0;
+ _gvrender_set_fillcolor($job, $call80);
+ $filled_1 = 1;
+ label = 28;
+ break;
+ case 23:
+ $and85 = $conv58 & 4;
+ $tobool86 = ($and85 | 0) == 0;
+ if ($tobool86) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $40 = $n | 0;
+ $41 = HEAP32[41554] | 0;
+ $call88 = _late_nnstring($40, $41, 103016) | 0;
+ _gvrender_set_pencolor($job, $call88);
+ $42 = HEAP32[41556] | 0;
+ $call89 = _late_nnstring($40, $42, 102672) | 0;
+ _gvrender_set_fillcolor($job, $call89);
+ $filled_1 = 1;
+ label = 28;
+ break;
+ case 25:
+ $and91 = $call56 & 1;
+ $tobool92 = ($and91 | 0) == 0;
+ if ($tobool92) {
+ $filled_0 = 0;
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $call94 = _findFill($n) | 0;
+ _gvrender_set_fillcolor($job, $call94);
+ $filled_0 = 1;
+ label = 27;
+ break;
+ case 27:
+ _pencolor($job, $n);
+ $filled_1 = $filled_0;
+ label = 28;
+ break;
+ case 28:
+ $shape = $n + 24 | 0;
+ $43 = HEAP32[$shape >> 2] | 0;
+ $usershape = $43 + 12 | 0;
+ $44 = HEAP8[$usershape] | 0;
+ $tobool102 = $44 << 24 >> 24 == 0;
+ if ($tobool102) {
+ $47 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $name106 = $43 | 0;
+ $45 = HEAP32[$name106 >> 2] | 0;
+ $46 = HEAP8[$45] | 0;
+ $cmp109 = $46 << 24 >> 24 == 99;
+ if ($cmp109) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $tobool123140 = $filled_1 << 24 >> 24 == 0;
+ $peripheries_0 = $17;
+ $tobool123144 = $tobool123140;
+ $tobool126145 = 1;
+ label = 35;
+ break;
+ case 31:
+ $call114 = _strcmp($45 | 0, 110216) | 0;
+ $phitmp = ($call114 | 0) != 0;
+ $47 = $phitmp;
+ label = 32;
+ break;
+ case 32:
+ $cmp119 = ($17 | 0) != 0;
+ $tobool123 = $filled_1 << 24 >> 24 == 0;
+ $or_cond = $cmp119 | $tobool123;
+ $or_cond137 = $or_cond | $47;
+ if ($or_cond137) {
+ $peripheries_0 = $17;
+ $tobool123144 = $tobool123;
+ $tobool126145 = $47;
+ label = 35;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $call129 = _findFill($n) | 0;
+ $48 = HEAP8[$call129] | 0;
+ $tobool130 = $48 << 24 >> 24 == 0;
+ if ($tobool130) {
+ $peripheries_0 = 1;
+ $tobool123144 = $tobool123;
+ $tobool126145 = $47;
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ _gvrender_set_pencolor($job, $call129);
+ $peripheries_0 = 1;
+ $tobool123144 = $tobool123;
+ $tobool126145 = $47;
+ label = 35;
+ break;
+ case 35:
+ $49 = HEAP32[$shape >> 2] | 0;
+ $usershape136 = $49 + 12 | 0;
+ $50 = HEAP8[$usershape136] | 0;
+ $tobool137 = $50 << 24 >> 24 == 0;
+ if ($tobool137) {
+ label = 39;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $name141 = $49 | 0;
+ $51 = HEAP32[$name141 >> 2] | 0;
+ $52 = HEAP8[$51] | 0;
+ $cmp144 = $52 << 24 >> 24 == 99;
+ if ($cmp144) {
+ label = 37;
+ break;
+ } else {
+ $name_1146_ph = $51;
+ label = 40;
+ break;
+ }
+ case 37:
+ $call147 = _strcmp($51 | 0, 110216) | 0;
+ $tobool148 = ($call147 | 0) == 0;
+ if ($tobool148) {
+ label = 38;
+ break;
+ } else {
+ $name_1146_ph = $51;
+ label = 40;
+ break;
+ }
+ case 38:
+ $53 = $n | 0;
+ $call150 = _agget($53, 120672) | 0;
+ $name_1146_ph = $call150;
+ label = 40;
+ break;
+ case 39:
+ $54 = $n | 0;
+ $call153 = _agget($54, 101440) | 0;
+ $not_tobool154 = ($call153 | 0) == 0;
+ if ($not_tobool154) {
+ $filled_3_ph = $filled_1;
+ label = 51;
+ break;
+ } else {
+ $name_1146_ph = $call153;
+ label = 40;
+ break;
+ }
+ case 40:
+ $cmp160152 = ($15 | 0) > 0;
+ if ($cmp160152) {
+ label = 41;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 41:
+ $x166 = $coord | 0;
+ $55 = HEAP32[1762] | 0;
+ $y173 = $n + 40 | 0;
+ $i_0153 = 0;
+ label = 42;
+ break;
+ case 42:
+ $P_sroa_0_0__idx23 = $13 + ($i_0153 << 4) | 0;
+ $P_sroa_0_0_copyload24 = +HEAPF64[$P_sroa_0_0__idx23 >> 3];
+ $P_sroa_1_8__idx27 = $13 + ($i_0153 << 4) + 8 | 0;
+ $P_sroa_1_8_copyload28 = +HEAPF64[$P_sroa_1_8__idx27 >> 3];
+ $mul163 = $div * $P_sroa_0_0_copyload24;
+ $56 = +HEAPF64[$x166 >> 3];
+ $add167 = $mul163 + $56;
+ $x169 = $55 + ($i_0153 << 4) | 0;
+ HEAPF64[$x169 >> 3] = $add167;
+ $mul170 = $div55 * $P_sroa_1_8_copyload28;
+ $57 = +HEAPF64[$y173 >> 3];
+ $add174 = $mul170 + $57;
+ $y176 = $55 + ($i_0153 << 4) + 8 | 0;
+ HEAPF64[$y176 >> 3] = $add174;
+ $inc = $i_0153 + 1 | 0;
+ $cmp160 = ($inc | 0) < ($15 | 0);
+ if ($cmp160) {
+ $i_0153 = $inc;
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $conv177 = $filled_1 & 255;
+ $or_cond138 = $tobool123144 | $tobool126145;
+ if ($or_cond138) {
+ label = 50;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $cmp183 = ($15 | 0) < 3;
+ if ($cmp183) {
+ label = 45;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 45:
+ $58 = HEAP32[1762] | 0;
+ _gvrender_ellipse($job, $58, 0, $filled_1);
+ $and186 = $call56 & 4;
+ $tobool187 = ($and186 | 0) == 0;
+ if ($tobool187) {
+ label = 50;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ _Mcircle_hack($job, $n);
+ label = 50;
+ break;
+ case 47:
+ $and191 = $call56 & 6;
+ $tobool192 = ($and191 | 0) == 0;
+ $59 = HEAP32[1762] | 0;
+ if ($tobool192) {
+ label = 49;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ _node_round_corners($job, $n, $59, $15, $call56, $conv177);
+ label = 50;
+ break;
+ case 49:
+ _gvrender_polygon($job, $59, $15, $filled_1);
+ label = 50;
+ break;
+ case 50:
+ $60 = HEAP32[1762] | 0;
+ $61 = $n | 0;
+ $62 = HEAP32[41590] | 0;
+ $call199 = _late_string($61, $62, 100880) | 0;
+ _gvrender_usershape($job, $name_1146_ph, $60, $15, $filled_1, $call199);
+ $filled_3_ph = 0;
+ label = 51;
+ break;
+ case 51:
+ $cmp202149 = ($peripheries_0 | 0) > 0;
+ if ($cmp202149) {
+ label = 52;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 52:
+ $cmp206147 = ($15 | 0) > 0;
+ $cmp231 = ($15 | 0) < 3;
+ $and234 = $call56 & 4;
+ $tobool235 = ($and234 | 0) == 0;
+ $and239 = $call56 & 998;
+ $tobool240 = ($and239 | 0) == 0;
+ $x216 = $coord | 0;
+ $y224 = $n + 40 | 0;
+ $filled_3150 = $filled_3_ph;
+ $j_0151 = 0;
+ label = 53;
+ break;
+ case 53:
+ if ($cmp206147) {
+ label = 54;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 54:
+ $mul209 = Math_imul($j_0151, $15);
+ $63 = HEAP32[1762] | 0;
+ $i_1148 = 0;
+ label = 55;
+ break;
+ case 55:
+ $add210 = $i_1148 + $mul209 | 0;
+ $P_sroa_0_0__idx = $13 + ($add210 << 4) | 0;
+ $P_sroa_0_0_copyload = +HEAPF64[$P_sroa_0_0__idx >> 3];
+ $P_sroa_1_8__idx25 = $13 + ($add210 << 4) + 8 | 0;
+ $P_sroa_1_8_copyload = +HEAPF64[$P_sroa_1_8__idx25 >> 3];
+ $mul213 = $div * $P_sroa_0_0_copyload;
+ $64 = +HEAPF64[$x216 >> 3];
+ $add217 = $mul213 + $64;
+ $x219 = $63 + ($i_1148 << 4) | 0;
+ HEAPF64[$x219 >> 3] = $add217;
+ $mul221 = $div55 * $P_sroa_1_8_copyload;
+ $65 = +HEAPF64[$y224 >> 3];
+ $add225 = $mul221 + $65;
+ $y227 = $63 + ($i_1148 << 4) + 8 | 0;
+ HEAPF64[$y227 >> 3] = $add225;
+ $inc229 = $i_1148 + 1 | 0;
+ $cmp206 = ($inc229 | 0) < ($15 | 0);
+ if ($cmp206) {
+ $i_1148 = $inc229;
+ label = 55;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 56:
+ $66 = HEAP32[1762] | 0;
+ if ($cmp231) {
+ label = 57;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 57:
+ _gvrender_ellipse($job, $66, 0, $filled_3150);
+ if ($tobool235) {
+ label = 62;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ _Mcircle_hack($job, $n);
+ label = 62;
+ break;
+ case 59:
+ if ($tobool240) {
+ label = 61;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $conv242 = $filled_3150 & 255;
+ _node_round_corners($job, $n, $66, $15, $call56, $conv242);
+ label = 62;
+ break;
+ case 61:
+ _gvrender_polygon($job, $66, $15, $filled_3150);
+ label = 62;
+ break;
+ case 62:
+ $inc247 = $j_0151 + 1 | 0;
+ $cmp202 = ($inc247 | 0) < ($peripheries_0 | 0);
+ if ($cmp202) {
+ $filled_3150 = 0;
+ $j_0151 = $inc247;
+ label = 53;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ $67 = HEAP32[$label >> 2] | 0;
+ _emit_label($job, 10, $67);
+ if ($10) {
+ label = 64;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 64:
+ $flags253 = $job + 152 | 0;
+ $68 = HEAP32[$flags253 >> 2] | 0;
+ $and254 = $68 & 4;
+ $tobool255 = ($and254 | 0) == 0;
+ if ($tobool255) {
+ label = 66;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $69 = HEAP32[$url >> 2] | 0;
+ $tooltip258 = $0 + 180 | 0;
+ $70 = HEAP32[$tooltip258 >> 2] | 0;
+ $target259 = $0 + 196 | 0;
+ $71 = HEAP32[$target259 >> 2] | 0;
+ $id260 = $0 + 164 | 0;
+ $72 = HEAP32[$id260 >> 2] | 0;
+ _gvrender_begin_anchor($job, $69, $70, $71, $72);
+ label = 66;
+ break;
+ case 66:
+ _gvrender_end_anchor($job);
+ label = 67;
+ break;
+ case 67:
+ return;
+ }
+}
+function _Mcircle_hack($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $AF = 0, $p = 0, $y1 = 0, $x4 = 0, $arrayidx = 0, $y7 = 0, $y9 = 0, $sub20 = 0.0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ $AF = __stackBase__ | 0;
+ $p = __stackBase__ + 32 | 0;
+ $y1 = $p + 8 | 0;
+ HEAPF64[$y1 >> 3] = +HEAPF64[$n + 96 >> 3] * .75 * .5;
+ $x4 = $p | 0;
+ HEAPF64[$x4 >> 3] = +HEAPF64[$n + 112 >> 3] * .6614;
+ $arrayidx = $AF | 0;
+ _add_pointf796($AF | 0, $p, $n + 32 | 0);
+ $y7 = $AF + 8 | 0;
+ $y9 = $AF + 24 | 0;
+ HEAPF64[$y9 >> 3] = +HEAPF64[$y7 >> 3];
+ HEAPF64[$AF + 16 >> 3] = +HEAPF64[$AF >> 3] - +HEAPF64[$x4 >> 3] * 2.0;
+ _gvrender_polyline($job, $arrayidx, 2);
+ $sub20 = +HEAPF64[$y7 >> 3] - +HEAPF64[$y1 >> 3] * 2.0;
+ HEAPF64[$y7 >> 3] = $sub20;
+ HEAPF64[$y9 >> 3] = $sub20;
+ _gvrender_polyline($job, $arrayidx, 2);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _quant($val, $q) {
+ $val = +$val;
+ $q = +$q;
+ var $conv = 0;
+ $conv = ~~($val / $q);
+ return +(+((+($conv | 0) * $q + 1.0e-5 < $val & 1) + $conv | 0) * $q);
+}
+function _parse_reclbl($n, $LR, $flag, $text) {
+ $n = $n | 0;
+ $LR = $LR | 0;
+ $flag = $flag | 0;
+ $text = $text | 0;
+ var $call = 0, $0 = 0, $label = 0, $1 = 0, $2 = 0, $sp_0 = 0, $maxf_0 = 0, $cnt_0 = 0, $3 = 0, $incdec_ptr = 0, $4 = 0, $sp_1 = 0, $5 = 0, $inc = 0, $dec = 0, $cmp33 = 0, $inc36 = 0, $inc36_maxf_0 = 0, $maxf_1 = 0, $cnt_1 = 0, $cmp40 = 0, $sp_2 = 0, $maxf_2 = 0, $cnt_2 = 0, $incdec_ptr44 = 0, $maxf_3 = 0, $mul = 0, $call45 = 0, $6 = 0, $fld = 0, $7 = 0, $conv46 = 0, $8 = 0, $lnot = 0, $lnot_ext = 0, $html59 = 0, $add_ptr = 0, $html = 0, $html244 = 0, $html201 = 0, $tobool105 = 0, $add_ptr132 = 0, $9 = 0, $html148 = 0, $fontsize = 0, $fontname = 0, $fontcolor = 0, $fp_0_ph_ph = 0, $tsp_0_ph_ph = 0, $psp_0_ph_ph = 0, $hstsp_0_ph_ph = 0, $hspsp_0_ph_ph = 0, $mode_0_ph_ph = 0, $wflag_0_ph_ph = 0, $ishardspace_0_ph_ph = 0, $fi_0_ph_ph = 0, $fp_0_ph = 0, $tsp_0_ph = 0, $psp_0_ph = 0, $hstsp_0_ph = 0, $hspsp_0_ph = 0, $mode_0_ph = 0, $ishardspace_0_ph = 0, $fi_0_ph = 0, $tsp_0_ph101 = 0, $psp_0_ph102 = 0, $hstsp_0_ph103 = 0, $hspsp_0_ph104 = 0, $tmpport_0_ph = 0, $mode_0_ph105 = 0, $ishardspace_0_ph107 = 0, $fi_0_ph108 = 0, $psp_0_ph110_ph = 0, $hspsp_0_ph112_ph = 0, $tmpport_0_ph113_ph = 0, $mode_0_ph114_ph = 0, $fi_0_ph117_ph = 0, $psp_0_ph110 = 0, $tmpport_0_ph113 = 0, $mode_0_ph114 = 0, $fi_0_ph117 = 0, $mode_0 = 0, $fi_0 = 0, $10 = 0, $11 = 0, $conv49 = 0, $and = 0, $tobool50 = 0, $12 = 0, $tobool54 = 0, $or = 0, $incdec_ptr57 = 0, $13 = 0, $tobool60 = 0, $and63 = 0, $tobool64 = 0, $cmp68 = 0, $add_ptr71 = 0, $cmp72 = 0, $14 = 0, $cmp77 = 0, $add_ptr71_psp_0 = 0, $psp_1 = 0, $call82 = 0, $and83 = 0, $15 = 0, $incdec_ptr84 = 0, $incdec_ptr86 = 0, $cmp87 = 0, $16 = 0, $tobool90 = 0, $call95 = 0, $inc96 = 0, $17 = 0, $arrayidx = 0, $tobool98 = 0, $18 = 0, $19 = 0, $tobool103 = 0, $or_cond = 0, $and107 = 0, $tobool108 = 0, $and112 = 0, $tobool113 = 0, $call115 = 0, $20 = 0, $inc116 = 0, $21 = 0, $arrayidx118 = 0, $fp_1 = 0, $fi_1 = 0, $tobool120 = 0, $id = 0, $and123 = 0, $tobool124 = 0, $or126 = 0, $incdec_ptr127 = 0, $tsp_1 = 0, $mode_1 = 0, $and129 = 0, $tobool130 = 0, $cmp133 = 0, $add_ptr136 = 0, $cmp137 = 0, $22 = 0, $cmp142 = 0, $add_ptr136_tsp_1 = 0, $tsp_2 = 0, $call147 = 0, $23 = 0, $tobool150 = 0, $cond = 0, $24 = 0.0, $25 = 0, $26 = 0, $call151 = 0, $lp = 0, $LR152 = 0, $tsp_3 = 0, $hstsp_1 = 0, $27 = 0, $28 = 0, $incdec_ptr160 = 0, $n_flds = 0, $29 = 0, $incdec_ptr162 = 0, $add_ptr166 = 0, $30 = 0, $31 = 0, $incdec_ptr194 = 0, $32 = 0, $tobool202 = 0, $incdec_ptr206 = 0, $or207 = 0, $33 = 0, $incdec_ptr208 = 0, $tsp_4 = 0, $mode_2 = 0, $ishardspace_1 = 0, $and212 = 0, $tobool213 = 0, $34 = 0, $35 = 0, $cmp216 = 0, $and221 = 0, $tobool222 = 0, $36 = 0, $37 = 0, $cmp225 = 0, $or228 = 0, $mode_2_or228 = 0, $mode_3 = 0, $and230 = 0, $tobool231 = 0, $38 = 0, $39 = 0, $cmp234 = 0, $tobool237 = 0, $or_cond96 = 0, $add_ptr239 = 0, $40 = 0, $cmp241 = 0, $41 = 0, $tobool245 = 0, $42 = 0, $43 = 0, $incdec_ptr247 = 0, $tsp_5 = 0, $add_ptr251 = 0, $and254 = 0, $tobool255 = 0, $44 = 0, $45 = 0, $cmp258 = 0, $tobool261 = 0, $or_cond97 = 0, $cmp263 = 0, $add_ptr266 = 0, $46 = 0, $cmp268 = 0, $47 = 0, $48 = 0, $incdec_ptr271 = 0, $psp_2 = 0, $add_ptr275 = 0, $tsp_6 = 0, $psp_3 = 0, $hstsp_2 = 0, $hspsp_1 = 0, $49 = 0, $incdec_ptr279 = 0, $50 = 0, $tobool28398 = 0, $51 = 0, $tsp_799 = 0, $incdec_ptr285 = 0, $52 = 0, $incdec_ptr286 = 0, $53 = 0, $54 = 0, $tobool283 = 0, $n_flds288 = 0, $55 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(72) | 0;
+ $0 = $call;
+ $label = $n + 120 | 0;
+ $1 = HEAP32[$label >> 2] | 0;
+ $2 = HEAP32[1158] | 0;
+ $cnt_0 = 0;
+ $maxf_0 = 1;
+ $sp_0 = $2;
+ label = 3;
+ break;
+ case 3:
+ $3 = HEAP8[$sp_0] | 0;
+ if (($3 << 24 >> 24 | 0) == 92) {
+ label = 4;
+ break;
+ } else if (($3 << 24 >> 24 | 0) == 0) {
+ $maxf_3 = $maxf_0;
+ label = 11;
+ break;
+ } else {
+ $sp_1 = $sp_0;
+ label = 5;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $sp_0 + 1 | 0;
+ $4 = HEAP8[$incdec_ptr] | 0;
+ if (($4 << 24 >> 24 | 0) == 92 | ($4 << 24 >> 24 | 0) == 123 | ($4 << 24 >> 24 | 0) == 125 | ($4 << 24 >> 24 | 0) == 124) {
+ $cnt_2 = $cnt_0;
+ $maxf_2 = $maxf_0;
+ $sp_2 = $incdec_ptr;
+ label = 10;
+ break;
+ } else {
+ $sp_1 = $incdec_ptr;
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP8[$sp_1] | 0;
+ if (($5 << 24 >> 24 | 0) == 123) {
+ label = 6;
+ break;
+ } else if (($5 << 24 >> 24 | 0) == 125) {
+ label = 7;
+ break;
+ } else if (($5 << 24 >> 24 | 0) == 124) {
+ label = 8;
+ break;
+ } else {
+ $cnt_1 = $cnt_0;
+ $maxf_1 = $maxf_0;
+ label = 9;
+ break;
+ }
+ case 6:
+ $inc = $cnt_0 + 1 | 0;
+ $cnt_1 = $inc;
+ $maxf_1 = $maxf_0;
+ label = 9;
+ break;
+ case 7:
+ $dec = $cnt_0 - 1 | 0;
+ $cnt_1 = $dec;
+ $maxf_1 = $maxf_0;
+ label = 9;
+ break;
+ case 8:
+ $cmp33 = ($cnt_0 | 0) == 0;
+ $inc36 = $cmp33 & 1;
+ $inc36_maxf_0 = $inc36 + $maxf_0 | 0;
+ $cnt_1 = $cnt_0;
+ $maxf_1 = $inc36_maxf_0;
+ label = 9;
+ break;
+ case 9:
+ $cmp40 = ($cnt_1 | 0) < 0;
+ if ($cmp40) {
+ $maxf_3 = $maxf_1;
+ label = 11;
+ break;
+ } else {
+ $cnt_2 = $cnt_1;
+ $maxf_2 = $maxf_1;
+ $sp_2 = $sp_1;
+ label = 10;
+ break;
+ }
+ case 10:
+ $incdec_ptr44 = $sp_2 + 1 | 0;
+ $cnt_0 = $cnt_2;
+ $maxf_0 = $maxf_2;
+ $sp_0 = $incdec_ptr44;
+ label = 3;
+ break;
+ case 11:
+ $mul = $maxf_3 << 2;
+ $call45 = _zmalloc($mul) | 0;
+ $6 = $call45;
+ $fld = $call + 56 | 0;
+ $7 = $fld;
+ HEAP32[$7 >> 2] = $6;
+ $conv46 = $LR & 255;
+ $8 = $call + 64 | 0;
+ HEAP8[$8] = $conv46;
+ $lnot = ($LR | 0) == 0;
+ $lnot_ext = $lnot & 1;
+ $html59 = $1 + 82 | 0;
+ $add_ptr = $text + 1 | 0;
+ $html = $1 + 82 | 0;
+ $html244 = $1 + 82 | 0;
+ $html201 = $1 + 82 | 0;
+ $tobool105 = ($flag | 0) == 0;
+ $add_ptr132 = $text + 1 | 0;
+ $9 = $n | 0;
+ $html148 = $1 + 82 | 0;
+ $fontsize = $1 + 16 | 0;
+ $fontname = $1 + 4 | 0;
+ $fontcolor = $1 + 8 | 0;
+ $fi_0_ph_ph = 0;
+ $ishardspace_0_ph_ph = 0;
+ $wflag_0_ph_ph = 0;
+ $mode_0_ph_ph = 0;
+ $hspsp_0_ph_ph = 0;
+ $hstsp_0_ph_ph = $text;
+ $psp_0_ph_ph = 0;
+ $tsp_0_ph_ph = $text;
+ $fp_0_ph_ph = 0;
+ label = 12;
+ break;
+ case 12:
+ $fi_0_ph = $fi_0_ph_ph;
+ $ishardspace_0_ph = $ishardspace_0_ph_ph;
+ $mode_0_ph = $mode_0_ph_ph;
+ $hspsp_0_ph = $hspsp_0_ph_ph;
+ $hstsp_0_ph = $hstsp_0_ph_ph;
+ $psp_0_ph = $psp_0_ph_ph;
+ $tsp_0_ph = $tsp_0_ph_ph;
+ $fp_0_ph = $fp_0_ph_ph;
+ label = 13;
+ break;
+ case 13:
+ $fi_0_ph108 = $fi_0_ph;
+ $ishardspace_0_ph107 = $ishardspace_0_ph;
+ $mode_0_ph105 = $mode_0_ph;
+ $tmpport_0_ph = 0;
+ $hspsp_0_ph104 = $hspsp_0_ph;
+ $hstsp_0_ph103 = $hstsp_0_ph;
+ $psp_0_ph102 = $psp_0_ph;
+ $tsp_0_ph101 = $tsp_0_ph;
+ label = 14;
+ break;
+ case 14:
+ $fi_0_ph117_ph = $fi_0_ph108;
+ $mode_0_ph114_ph = $mode_0_ph105;
+ $tmpport_0_ph113_ph = $tmpport_0_ph;
+ $hspsp_0_ph112_ph = $hspsp_0_ph104;
+ $psp_0_ph110_ph = $psp_0_ph102;
+ label = 15;
+ break;
+ case 15:
+ $fi_0_ph117 = $fi_0_ph117_ph;
+ $mode_0_ph114 = $mode_0_ph114_ph;
+ $tmpport_0_ph113 = $tmpport_0_ph113_ph;
+ $psp_0_ph110 = $psp_0_ph110_ph;
+ label = 16;
+ break;
+ case 16:
+ $fi_0 = $fi_0_ph117;
+ $mode_0 = $mode_0_ph114;
+ label = 17;
+ break;
+ case 17:
+ if ($wflag_0_ph_ph) {
+ label = 78;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $10 = HEAP32[1158] | 0;
+ $11 = HEAP8[$10] | 0;
+ $conv49 = $11 << 24 >> 24;
+ if (($conv49 | 0) == 60) {
+ label = 19;
+ break;
+ } else if (($conv49 | 0) == 62) {
+ label = 23;
+ break;
+ } else if (($conv49 | 0) == 123) {
+ label = 30;
+ break;
+ } else if (($conv49 | 0) == 125 | ($conv49 | 0) == 124 | ($conv49 | 0) == 0) {
+ label = 35;
+ break;
+ } else if (($conv49 | 0) == 92) {
+ label = 52;
+ break;
+ } else {
+ $ishardspace_1 = $ishardspace_0_ph107;
+ $mode_2 = $mode_0;
+ $tsp_4 = $tsp_0_ph101;
+ label = 57;
+ break;
+ }
+ case 19:
+ $and = $mode_0 & 6;
+ $tobool50 = ($and | 0) == 0;
+ if ($tobool50) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ _parse_error($0, $tmpport_0_ph113);
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 21:
+ $12 = HEAP8[$html] | 0;
+ $tobool54 = $12 << 24 >> 24 == 0;
+ if ($tobool54) {
+ label = 22;
+ break;
+ } else {
+ $ishardspace_1 = $ishardspace_0_ph107;
+ $mode_2 = $mode_0;
+ $tsp_4 = $tsp_0_ph101;
+ label = 57;
+ break;
+ }
+ case 22:
+ $or = $mode_0 | 18;
+ $incdec_ptr57 = $10 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr57;
+ $fi_0_ph117_ph = $fi_0;
+ $mode_0_ph114_ph = $or;
+ $tmpport_0_ph113_ph = $tmpport_0_ph113;
+ $hspsp_0_ph112_ph = $text;
+ $psp_0_ph110_ph = $text;
+ label = 15;
+ break;
+ case 23:
+ $13 = HEAP8[$html59] | 0;
+ $tobool60 = $13 << 24 >> 24 == 0;
+ if ($tobool60) {
+ label = 24;
+ break;
+ } else {
+ $ishardspace_1 = $ishardspace_0_ph107;
+ $mode_2 = $mode_0;
+ $tsp_4 = $tsp_0_ph101;
+ label = 57;
+ break;
+ }
+ case 24:
+ $and63 = $mode_0 & 16;
+ $tobool64 = ($and63 | 0) == 0;
+ if ($tobool64) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ _parse_error($0, $tmpport_0_ph113);
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 26:
+ $cmp68 = $psp_0_ph110 >>> 0 > $add_ptr >>> 0;
+ if ($cmp68) {
+ label = 27;
+ break;
+ } else {
+ $psp_1 = $psp_0_ph110;
+ label = 29;
+ break;
+ }
+ case 27:
+ $add_ptr71 = $psp_0_ph110 - 1 | 0;
+ $cmp72 = ($add_ptr71 | 0) == ($hspsp_0_ph112_ph | 0);
+ if ($cmp72) {
+ $psp_1 = $psp_0_ph110;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $14 = HEAP8[$add_ptr71] | 0;
+ $cmp77 = $14 << 24 >> 24 == 32;
+ $add_ptr71_psp_0 = $cmp77 ? $add_ptr71 : $psp_0_ph110;
+ $psp_1 = $add_ptr71_psp_0;
+ label = 29;
+ break;
+ case 29:
+ HEAP8[$psp_1] = 0;
+ $call82 = _strdup($text | 0) | 0;
+ $and83 = $mode_0 & -17;
+ $15 = HEAP32[1158] | 0;
+ $incdec_ptr84 = $15 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr84;
+ $fi_0_ph117 = $fi_0;
+ $mode_0_ph114 = $and83;
+ $tmpport_0_ph113 = $call82;
+ $psp_0_ph110 = $psp_1;
+ label = 16;
+ break;
+ case 30:
+ $incdec_ptr86 = $10 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr86;
+ $cmp87 = ($mode_0 | 0) == 0;
+ if ($cmp87) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ $16 = HEAP8[$incdec_ptr86] | 0;
+ $tobool90 = $16 << 24 >> 24 == 0;
+ if ($tobool90) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 32:
+ _parse_error($0, $tmpport_0_ph113);
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 33:
+ $call95 = _parse_reclbl($n, $lnot_ext, 0, $text) | 0;
+ $inc96 = $fi_0 + 1 | 0;
+ $17 = HEAP32[$7 >> 2] | 0;
+ $arrayidx = $17 + ($fi_0 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $call95;
+ $tobool98 = ($call95 | 0) == 0;
+ if ($tobool98) {
+ label = 34;
+ break;
+ } else {
+ $fi_0 = $inc96;
+ $mode_0 = 4;
+ label = 17;
+ break;
+ }
+ case 34:
+ _parse_error($0, $tmpport_0_ph113);
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 35:
+ $18 = HEAP32[1158] | 0;
+ $19 = HEAP8[$18] | 0;
+ $tobool103 = $19 << 24 >> 24 == 0;
+ $or_cond = $tobool103 & $tobool105;
+ if ($or_cond) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $and107 = $mode_0 & 16;
+ $tobool108 = ($and107 | 0) == 0;
+ if ($tobool108) {
+ label = 38;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ _parse_error($0, $tmpport_0_ph113);
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 38:
+ $and112 = $mode_0 & 4;
+ $tobool113 = ($and112 | 0) == 0;
+ if ($tobool113) {
+ label = 39;
+ break;
+ } else {
+ $fi_1 = $fi_0;
+ $fp_1 = $fp_0_ph;
+ label = 40;
+ break;
+ }
+ case 39:
+ $call115 = _zmalloc(72) | 0;
+ $20 = $call115;
+ $inc116 = $fi_0 + 1 | 0;
+ $21 = HEAP32[$7 >> 2] | 0;
+ $arrayidx118 = $21 + ($fi_0 << 2) | 0;
+ HEAP32[$arrayidx118 >> 2] = $20;
+ $fi_1 = $inc116;
+ $fp_1 = $20;
+ label = 40;
+ break;
+ case 40:
+ $tobool120 = ($tmpport_0_ph113 | 0) == 0;
+ if ($tobool120) {
+ label = 42;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $id = $fp_1 + 60 | 0;
+ HEAP32[$id >> 2] = $tmpport_0_ph113;
+ label = 42;
+ break;
+ case 42:
+ $and123 = $mode_0 & 5;
+ $tobool124 = ($and123 | 0) == 0;
+ if ($tobool124) {
+ label = 43;
+ break;
+ } else {
+ $mode_1 = $mode_0;
+ $tsp_1 = $tsp_0_ph101;
+ label = 44;
+ break;
+ }
+ case 43:
+ $or126 = $mode_0 | 1;
+ $incdec_ptr127 = $tsp_0_ph101 + 1 | 0;
+ HEAP8[$tsp_0_ph101] = 32;
+ $mode_1 = $or126;
+ $tsp_1 = $incdec_ptr127;
+ label = 44;
+ break;
+ case 44:
+ $and129 = $mode_1 & 1;
+ $tobool130 = ($and129 | 0) == 0;
+ if ($tobool130) {
+ $hstsp_1 = $hstsp_0_ph103;
+ $tsp_3 = $tsp_1;
+ label = 49;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $cmp133 = $tsp_1 >>> 0 > $add_ptr132 >>> 0;
+ if ($cmp133) {
+ label = 46;
+ break;
+ } else {
+ $tsp_2 = $tsp_1;
+ label = 48;
+ break;
+ }
+ case 46:
+ $add_ptr136 = $tsp_1 - 1 | 0;
+ $cmp137 = ($add_ptr136 | 0) == ($hstsp_0_ph103 | 0);
+ if ($cmp137) {
+ $tsp_2 = $tsp_1;
+ label = 48;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $22 = HEAP8[$add_ptr136] | 0;
+ $cmp142 = $22 << 24 >> 24 == 32;
+ $add_ptr136_tsp_1 = $cmp142 ? $add_ptr136 : $tsp_1;
+ $tsp_2 = $add_ptr136_tsp_1;
+ label = 48;
+ break;
+ case 48:
+ HEAP8[$tsp_2] = 0;
+ $call147 = _strdup($text | 0) | 0;
+ $23 = HEAP8[$html148] | 0;
+ $tobool150 = $23 << 24 >> 24 != 0;
+ $cond = $tobool150 ? 2 : 0;
+ $24 = +HEAPF64[$fontsize >> 3];
+ $25 = HEAP32[$fontname >> 2] | 0;
+ $26 = HEAP32[$fontcolor >> 2] | 0;
+ $call151 = _make_label($9, $call147, $cond, $24, $25, $26) | 0;
+ $lp = $fp_1 + 52 | 0;
+ HEAP32[$lp >> 2] = $call151;
+ $LR152 = $fp_1 + 64 | 0;
+ HEAP8[$LR152] = 1;
+ $hstsp_1 = $text;
+ $tsp_3 = $text;
+ label = 49;
+ break;
+ case 49:
+ $27 = HEAP32[1158] | 0;
+ $28 = HEAP8[$27] | 0;
+ if (($28 << 24 >> 24 | 0) == 0) {
+ $fi_0_ph_ph = $fi_1;
+ $ishardspace_0_ph_ph = $ishardspace_0_ph107;
+ $wflag_0_ph_ph = 1;
+ $mode_0_ph_ph = $mode_1;
+ $hspsp_0_ph_ph = $hspsp_0_ph112_ph;
+ $hstsp_0_ph_ph = $hstsp_1;
+ $psp_0_ph_ph = $psp_0_ph110;
+ $tsp_0_ph_ph = $tsp_3;
+ $fp_0_ph_ph = $fp_1;
+ label = 12;
+ break;
+ } else if (($28 << 24 >> 24 | 0) == 125) {
+ label = 50;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 50:
+ $incdec_ptr160 = $27 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr160;
+ $n_flds = $call + 48 | 0;
+ $29 = $n_flds;
+ HEAP32[$29 >> 2] = $fi_1;
+ $retval_0 = $0;
+ label = 79;
+ break;
+ case 51:
+ $incdec_ptr162 = $27 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr162;
+ $fi_0_ph = $fi_1;
+ $ishardspace_0_ph = $ishardspace_0_ph107;
+ $mode_0_ph = 0;
+ $hspsp_0_ph = $hspsp_0_ph112_ph;
+ $hstsp_0_ph = $hstsp_1;
+ $psp_0_ph = $psp_0_ph110;
+ $tsp_0_ph = $tsp_3;
+ $fp_0_ph = $fp_1;
+ label = 13;
+ break;
+ case 52:
+ $add_ptr166 = $10 + 1 | 0;
+ $30 = HEAP8[$add_ptr166] | 0;
+ if (($30 << 24 >> 24 | 0) == 123 | ($30 << 24 >> 24 | 0) == 125 | ($30 << 24 >> 24 | 0) == 124 | ($30 << 24 >> 24 | 0) == 60 | ($30 << 24 >> 24 | 0) == 62) {
+ label = 53;
+ break;
+ } else if (($30 << 24 >> 24 | 0) == 32) {
+ label = 54;
+ break;
+ } else if (($30 << 24 >> 24 | 0) == 0) {
+ $ishardspace_1 = $ishardspace_0_ph107;
+ $mode_2 = $mode_0;
+ $tsp_4 = $tsp_0_ph101;
+ label = 57;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 53:
+ $31 = HEAP32[1158] | 0;
+ $incdec_ptr194 = $31 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr194;
+ $ishardspace_1 = $ishardspace_0_ph107;
+ $mode_2 = $mode_0;
+ $tsp_4 = $tsp_0_ph101;
+ label = 57;
+ break;
+ case 54:
+ $32 = HEAP8[$html201] | 0;
+ $tobool202 = $32 << 24 >> 24 == 0;
+ if ($tobool202) {
+ label = 55;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 55:
+ HEAP32[1158] = $add_ptr166;
+ $ishardspace_1 = 1;
+ $mode_2 = $mode_0;
+ $tsp_4 = $tsp_0_ph101;
+ label = 57;
+ break;
+ case 56:
+ $incdec_ptr206 = $tsp_0_ph101 + 1 | 0;
+ HEAP8[$tsp_0_ph101] = 92;
+ $or207 = $mode_0 | 9;
+ $33 = HEAP32[1158] | 0;
+ $incdec_ptr208 = $33 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr208;
+ $ishardspace_1 = $ishardspace_0_ph107;
+ $mode_2 = $or207;
+ $tsp_4 = $incdec_ptr206;
+ label = 57;
+ break;
+ case 57:
+ $and212 = $mode_2 & 4;
+ $tobool213 = ($and212 | 0) == 0;
+ if ($tobool213) {
+ label = 60;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $34 = HEAP32[1158] | 0;
+ $35 = HEAP8[$34] | 0;
+ $cmp216 = $35 << 24 >> 24 == 32;
+ if ($cmp216) {
+ label = 60;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ _parse_error($0, $tmpport_0_ph113);
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 60:
+ $and221 = $mode_2 & 24;
+ $tobool222 = ($and221 | 0) == 0;
+ if ($tobool222) {
+ label = 61;
+ break;
+ } else {
+ $mode_3 = $mode_2;
+ label = 62;
+ break;
+ }
+ case 61:
+ $36 = HEAP32[1158] | 0;
+ $37 = HEAP8[$36] | 0;
+ $cmp225 = $37 << 24 >> 24 == 32;
+ $or228 = $mode_2 | 9;
+ $mode_2_or228 = $cmp225 ? $mode_2 : $or228;
+ $mode_3 = $mode_2_or228;
+ label = 62;
+ break;
+ case 62:
+ $and230 = $mode_3 & 8;
+ $tobool231 = ($and230 | 0) == 0;
+ if ($tobool231) {
+ label = 69;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ $38 = HEAP32[1158] | 0;
+ $39 = HEAP8[$38] | 0;
+ $cmp234 = $39 << 24 >> 24 == 32;
+ $tobool237 = ($ishardspace_1 | 0) == 0;
+ $or_cond96 = $cmp234 & $tobool237;
+ if ($or_cond96) {
+ label = 64;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 64:
+ $add_ptr239 = $tsp_4 - 1 | 0;
+ $40 = HEAP8[$add_ptr239] | 0;
+ $cmp241 = $40 << 24 >> 24 == 32;
+ if ($cmp241) {
+ label = 65;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 65:
+ $41 = HEAP8[$html244] | 0;
+ $tobool245 = $41 << 24 >> 24 == 0;
+ if ($tobool245) {
+ $tsp_5 = $tsp_4;
+ label = 67;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ $42 = HEAP32[1158] | 0;
+ $43 = HEAP8[$42] | 0;
+ $incdec_ptr247 = $tsp_4 + 1 | 0;
+ HEAP8[$tsp_4] = $43;
+ $tsp_5 = $incdec_ptr247;
+ label = 67;
+ break;
+ case 67:
+ if ($tobool237) {
+ $hspsp_1 = $hspsp_0_ph112_ph;
+ $hstsp_2 = $hstsp_0_ph103;
+ $psp_3 = $psp_0_ph110;
+ $tsp_6 = $tsp_5;
+ label = 76;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $add_ptr251 = $tsp_5 - 1 | 0;
+ $hspsp_1 = $hspsp_0_ph112_ph;
+ $hstsp_2 = $add_ptr251;
+ $psp_3 = $psp_0_ph110;
+ $tsp_6 = $tsp_5;
+ label = 76;
+ break;
+ case 69:
+ $and254 = $mode_3 & 16;
+ $tobool255 = ($and254 | 0) == 0;
+ if ($tobool255) {
+ $hspsp_1 = $hspsp_0_ph112_ph;
+ $hstsp_2 = $hstsp_0_ph103;
+ $psp_3 = $psp_0_ph110;
+ $tsp_6 = $tsp_4;
+ label = 76;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $44 = HEAP32[1158] | 0;
+ $45 = HEAP8[$44] | 0;
+ $cmp258 = $45 << 24 >> 24 == 32;
+ $tobool261 = ($ishardspace_1 | 0) == 0;
+ $or_cond97 = $cmp258 & $tobool261;
+ if ($or_cond97) {
+ label = 71;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 71:
+ $cmp263 = ($psp_0_ph110 | 0) == ($text | 0);
+ if ($cmp263) {
+ $psp_2 = $psp_0_ph110;
+ label = 74;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 72:
+ $add_ptr266 = $psp_0_ph110 - 1 | 0;
+ $46 = HEAP8[$add_ptr266] | 0;
+ $cmp268 = $46 << 24 >> 24 == 32;
+ if ($cmp268) {
+ $psp_2 = $psp_0_ph110;
+ label = 74;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $47 = HEAP32[1158] | 0;
+ $48 = HEAP8[$47] | 0;
+ $incdec_ptr271 = $psp_0_ph110 + 1 | 0;
+ HEAP8[$psp_0_ph110] = $48;
+ $psp_2 = $incdec_ptr271;
+ label = 74;
+ break;
+ case 74:
+ if ($tobool261) {
+ $hspsp_1 = $hspsp_0_ph112_ph;
+ $hstsp_2 = $hstsp_0_ph103;
+ $psp_3 = $psp_2;
+ $tsp_6 = $tsp_4;
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $add_ptr275 = $psp_2 - 1 | 0;
+ $hspsp_1 = $add_ptr275;
+ $hstsp_2 = $hstsp_0_ph103;
+ $psp_3 = $psp_2;
+ $tsp_6 = $tsp_4;
+ label = 76;
+ break;
+ case 76:
+ $49 = HEAP32[1158] | 0;
+ $incdec_ptr279 = $49 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr279;
+ $50 = HEAP8[$incdec_ptr279] | 0;
+ $tobool28398 = $50 << 24 >> 24 < 0;
+ if ($tobool28398) {
+ $tsp_799 = $tsp_6;
+ $51 = $incdec_ptr279;
+ label = 77;
+ break;
+ } else {
+ $fi_0_ph108 = $fi_0;
+ $ishardspace_0_ph107 = $ishardspace_1;
+ $mode_0_ph105 = $mode_3;
+ $tmpport_0_ph = $tmpport_0_ph113;
+ $hspsp_0_ph104 = $hspsp_1;
+ $hstsp_0_ph103 = $hstsp_2;
+ $psp_0_ph102 = $psp_3;
+ $tsp_0_ph101 = $tsp_6;
+ label = 14;
+ break;
+ }
+ case 77:
+ $incdec_ptr285 = $51 + 1 | 0;
+ HEAP32[1158] = $incdec_ptr285;
+ $52 = HEAP8[$51] | 0;
+ $incdec_ptr286 = $tsp_799 + 1 | 0;
+ HEAP8[$tsp_799] = $52;
+ $53 = HEAP32[1158] | 0;
+ $54 = HEAP8[$53] | 0;
+ $tobool283 = $54 << 24 >> 24 < 0;
+ if ($tobool283) {
+ $tsp_799 = $incdec_ptr286;
+ $51 = $53;
+ label = 77;
+ break;
+ } else {
+ $fi_0_ph108 = $fi_0;
+ $ishardspace_0_ph107 = $ishardspace_1;
+ $mode_0_ph105 = $mode_3;
+ $tmpport_0_ph = $tmpport_0_ph113;
+ $hspsp_0_ph104 = $hspsp_1;
+ $hstsp_0_ph103 = $hstsp_2;
+ $psp_0_ph102 = $psp_3;
+ $tsp_0_ph101 = $incdec_ptr286;
+ label = 14;
+ break;
+ }
+ case 78:
+ $n_flds288 = $call + 48 | 0;
+ $55 = $n_flds288;
+ HEAP32[$55 >> 2] = $fi_0;
+ $retval_0 = $0;
+ label = 79;
+ break;
+ case 79:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _size_reclbl($agg_result, $n, $f) {
+ $agg_result = $agg_result | 0;
+ $n = $n | 0;
+ $f = $f | 0;
+ var $marginx = 0, $marginy = 0, $tmp = 0, $lp = 0, $0 = 0, $tobool = 0, $n_flds = 0, $1 = 0, $cmp7137 = 0, $fld = 0, $d0_sroa_0_0__idx = 0, $d0_sroa_1_8__idx17 = 0, $LR = 0, $dimen_sroa_0_0__idx4 = 0, $dimen_sroa_0_0_copyload5 = 0.0, $dimen_sroa_1_8__idx11 = 0, $dimen_sroa_1_8_copyload12 = 0.0, $cmp = 0, $cmp3 = 0, $or_cond = 0, $2 = 0, $call = 0, $tobool5 = 0, $call7 = 0, $cmp8 = 0, $3 = 0.0, $mul = 0.0, $cmp10 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $mul14 = 0, $conv15 = 0.0, $add17 = 0.0, $cmp18 = 0, $4 = 0.0, $mul21 = 0.0, $cmp22 = 0, $add26 = 0.0, $sub30 = 0.0, $add26_sink = 0.0, $conv27 = 0, $mul34 = 0, $conv35 = 0.0, $add37 = 0.0, $add43 = 0.0, $sub47 = 0.0, $add43_sink = 0.0, $conv44 = 0, $mul51 = 0, $conv52 = 0.0, $add54 = 0.0, $add57 = 0.0, $add59 = 0.0, $add63 = 0.0, $add65 = 0.0, $i_040 = 0, $d_sroa_1_039 = 0.0, $d_sroa_0_038 = 0.0, $5 = 0, $arrayidx = 0, $6 = 0, $d0_sroa_0_0_copyload = 0.0, $d0_sroa_1_8_copyload = 0.0, $7 = 0, $tobool73 = 0, $add77 = 0.0, $cmp80 = 0, $d_sroa_1_0_d0_sroa_1_8_copyload = 0.0, $add92 = 0.0, $cmp95 = 0, $d_sroa_0_0_d0_sroa_0_0_copyload = 0.0, $d_sroa_0_1 = 0.0, $d_sroa_1_1 = 0.0, $inc = 0, $8 = 0, $cmp71 = 0, $d_sroa_0_2 = 0.0, $d_sroa_1_2 = 0.0, $d_sroa_0_0__idx18 = 0, $d_sroa_1_8__idx23 = 0, $d_sroa_0_0__idx = 0, $d_sroa_1_8__idx22 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $marginx = __stackBase__ | 0;
+ $marginy = __stackBase__ + 8 | 0;
+ $tmp = __stackBase__ + 16 | 0;
+ $lp = $f + 52 | 0;
+ $0 = HEAP32[$lp >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $n_flds = $f + 48 | 0;
+ $1 = HEAP32[$n_flds >> 2] | 0;
+ $cmp7137 = ($1 | 0) > 0;
+ if ($cmp7137) {
+ label = 4;
+ break;
+ } else {
+ $d_sroa_1_2 = 0.0;
+ $d_sroa_0_2 = 0.0;
+ label = 26;
+ break;
+ }
+ case 4:
+ $fld = $f + 56 | 0;
+ $d0_sroa_0_0__idx = $tmp | 0;
+ $d0_sroa_1_8__idx17 = $tmp + 8 | 0;
+ $LR = $f + 64 | 0;
+ $d_sroa_0_038 = 0.0;
+ $d_sroa_1_039 = 0.0;
+ $i_040 = 0;
+ label = 22;
+ break;
+ case 5:
+ $dimen_sroa_0_0__idx4 = $0 + 24 | 0;
+ $dimen_sroa_0_0_copyload5 = +HEAPF64[$dimen_sroa_0_0__idx4 >> 3];
+ $dimen_sroa_1_8__idx11 = $0 + 32 | 0;
+ $dimen_sroa_1_8_copyload12 = +HEAPF64[$dimen_sroa_1_8__idx11 >> 3];
+ $cmp = $dimen_sroa_0_0_copyload5 > 0.0;
+ $cmp3 = $dimen_sroa_1_8_copyload12 > 0.0;
+ $or_cond = $cmp | $cmp3;
+ if ($or_cond) {
+ label = 6;
+ break;
+ } else {
+ $d_sroa_1_2 = $dimen_sroa_1_8_copyload12;
+ $d_sroa_0_2 = $dimen_sroa_0_0_copyload5;
+ label = 26;
+ break;
+ }
+ case 6:
+ $2 = $n | 0;
+ $call = _agget($2, 99584) | 0;
+ $tobool5 = ($call | 0) == 0;
+ if ($tobool5) {
+ label = 21;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call7 = _sscanf($call | 0, 99208, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $marginx, HEAP32[tempInt + 8 >> 2] = $marginy, tempInt) | 0) | 0;
+ $cmp8 = ($call7 | 0) > 0;
+ if ($cmp8) {
+ label = 8;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 8:
+ $3 = +HEAPF64[$marginx >> 3];
+ $mul = $3 * 72.0;
+ $cmp10 = $mul < 0.0;
+ if ($cmp10) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add = $mul + .5;
+ $add_sink = $add;
+ label = 11;
+ break;
+ case 10:
+ $sub = $mul + -.5;
+ $add_sink = $sub;
+ label = 11;
+ break;
+ case 11:
+ $conv = ~~$add_sink;
+ $mul14 = $conv << 1;
+ $conv15 = +($mul14 | 0);
+ $add17 = $dimen_sroa_0_0_copyload5 + $conv15;
+ $cmp18 = ($call7 | 0) > 1;
+ $4 = +HEAPF64[$marginy >> 3];
+ $mul21 = $4 * 72.0;
+ $cmp22 = $mul21 >= 0.0;
+ if ($cmp18) {
+ label = 12;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 12:
+ if ($cmp22) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $add26 = $mul21 + .5;
+ $add26_sink = $add26;
+ label = 15;
+ break;
+ case 14:
+ $sub30 = $mul21 + -.5;
+ $add26_sink = $sub30;
+ label = 15;
+ break;
+ case 15:
+ $conv27 = ~~$add26_sink;
+ $mul34 = $conv27 << 1;
+ $conv35 = +($mul34 | 0);
+ $add37 = $dimen_sroa_1_8_copyload12 + $conv35;
+ $d_sroa_1_2 = $add37;
+ $d_sroa_0_2 = $add17;
+ label = 26;
+ break;
+ case 16:
+ if ($cmp22) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $add43 = $mul21 + .5;
+ $add43_sink = $add43;
+ label = 19;
+ break;
+ case 18:
+ $sub47 = $mul21 + -.5;
+ $add43_sink = $sub47;
+ label = 19;
+ break;
+ case 19:
+ $conv44 = ~~$add43_sink;
+ $mul51 = $conv44 << 1;
+ $conv52 = +($mul51 | 0);
+ $add54 = $dimen_sroa_1_8_copyload12 + $conv52;
+ $d_sroa_1_2 = $add54;
+ $d_sroa_0_2 = $add17;
+ label = 26;
+ break;
+ case 20:
+ $add57 = $dimen_sroa_0_0_copyload5 + 16.0;
+ $add59 = $dimen_sroa_1_8_copyload12 + 8.0;
+ $d_sroa_1_2 = $add59;
+ $d_sroa_0_2 = $add57;
+ label = 26;
+ break;
+ case 21:
+ $add63 = $dimen_sroa_0_0_copyload5 + 16.0;
+ $add65 = $dimen_sroa_1_8_copyload12 + 8.0;
+ $d_sroa_1_2 = $add65;
+ $d_sroa_0_2 = $add63;
+ label = 26;
+ break;
+ case 22:
+ $5 = HEAP32[$fld >> 2] | 0;
+ $arrayidx = $5 + ($i_040 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ _size_reclbl($tmp, $n, $6);
+ $d0_sroa_0_0_copyload = +HEAPF64[$d0_sroa_0_0__idx >> 3];
+ $d0_sroa_1_8_copyload = +HEAPF64[$d0_sroa_1_8__idx17 >> 3];
+ $7 = HEAP8[$LR] | 0;
+ $tobool73 = $7 << 24 >> 24 == 0;
+ if ($tobool73) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $add77 = $d_sroa_0_038 + $d0_sroa_0_0_copyload;
+ $cmp80 = $d_sroa_1_039 > $d0_sroa_1_8_copyload;
+ $d_sroa_1_0_d0_sroa_1_8_copyload = $cmp80 ? $d_sroa_1_039 : $d0_sroa_1_8_copyload;
+ $d_sroa_1_1 = $d_sroa_1_0_d0_sroa_1_8_copyload;
+ $d_sroa_0_1 = $add77;
+ label = 25;
+ break;
+ case 24:
+ $add92 = $d_sroa_1_039 + $d0_sroa_1_8_copyload;
+ $cmp95 = $d_sroa_0_038 > $d0_sroa_0_0_copyload;
+ $d_sroa_0_0_d0_sroa_0_0_copyload = $cmp95 ? $d_sroa_0_038 : $d0_sroa_0_0_copyload;
+ $d_sroa_1_1 = $add92;
+ $d_sroa_0_1 = $d_sroa_0_0_d0_sroa_0_0_copyload;
+ label = 25;
+ break;
+ case 25:
+ $inc = $i_040 + 1 | 0;
+ $8 = HEAP32[$n_flds >> 2] | 0;
+ $cmp71 = ($inc | 0) < ($8 | 0);
+ if ($cmp71) {
+ $d_sroa_0_038 = $d_sroa_0_1;
+ $d_sroa_1_039 = $d_sroa_1_1;
+ $i_040 = $inc;
+ label = 22;
+ break;
+ } else {
+ $d_sroa_1_2 = $d_sroa_1_1;
+ $d_sroa_0_2 = $d_sroa_0_1;
+ label = 26;
+ break;
+ }
+ case 26:
+ $d_sroa_0_0__idx18 = $f | 0;
+ HEAPF64[$d_sroa_0_0__idx18 >> 3] = $d_sroa_0_2;
+ $d_sroa_1_8__idx23 = $f + 8 | 0;
+ HEAPF64[$d_sroa_1_8__idx23 >> 3] = $d_sroa_1_2;
+ $d_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$d_sroa_0_0__idx >> 3] = $d_sroa_0_2;
+ $d_sroa_1_8__idx22 = $agg_result + 8 | 0;
+ HEAPF64[$d_sroa_1_8__idx22 >> 3] = $d_sroa_1_2;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _resize_reclbl($f, $sz, $nojustify_p) {
+ $f = $f | 0;
+ $sz = $sz | 0;
+ $nojustify_p = $nojustify_p | 0;
+ var $newsz = 0, $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $sub = 0.0, $y = 0, $2 = 0.0, $y4 = 0, $3 = 0.0, $sub5 = 0.0, $4 = 0, $5 = 0, $lp = 0, $6 = 0, $tobool = 0, $tobool8 = 0, $or_cond = 0, $x11 = 0, $7 = 0.0, $add = 0.0, $8 = 0, $y15 = 0, $9 = 0.0, $add16 = 0.0, $n_flds = 0, $10 = 0, $tobool17 = 0, $LR = 0, $11 = 0, $tobool19 = 0, $conv25 = 0.0, $sub_sink = 0.0, $div = 0.0, $12 = 0, $cmp24 = 0, $fld = 0, $13 = 0.0, $14 = 0.0, $i_025 = 0, $15 = 0, $arrayidx = 0, $16 = 0, $add30 = 0, $conv31 = 0.0, $mul = 0.0, $conv32 = 0, $conv33 = 0.0, $mul34 = 0.0, $conv35 = 0, $sub36 = 0, $17 = 0, $tobool38 = 0, $x41 = 0, $18 = 0.0, $conv42 = 0.0, $add43 = 0.0, $y48 = 0, $19 = 0.0, $conv49 = 0.0, $add50 = 0.0, $20 = 0, $cmp = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ tempParam = $sz;
+ $sz = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$sz >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$sz + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$sz + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$sz + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $newsz = __stackBase__ | 0;
+ $x = $sz | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $f | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $sub = $0 - $1;
+ $y = $sz + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $y4 = $f + 8 | 0;
+ $3 = +HEAPF64[$y4 >> 3];
+ $sub5 = $2 - $3;
+ $4 = $f;
+ $5 = $sz;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $lp = $f + 52 | 0;
+ $6 = HEAP32[$lp >> 2] | 0;
+ $tobool = ($6 | 0) != 0;
+ $tobool8 = ($nojustify_p | 0) == 0;
+ $or_cond = $tobool & $tobool8;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $x11 = $6 + 40 | 0;
+ $7 = +HEAPF64[$x11 >> 3];
+ $add = $sub + $7;
+ HEAPF64[$x11 >> 3] = $add;
+ $8 = HEAP32[$lp >> 2] | 0;
+ $y15 = $8 + 48 | 0;
+ $9 = +HEAPF64[$y15 >> 3];
+ $add16 = $sub5 + $9;
+ HEAPF64[$y15 >> 3] = $add16;
+ label = 4;
+ break;
+ case 4:
+ $n_flds = $f + 48 | 0;
+ $10 = HEAP32[$n_flds >> 2] | 0;
+ $tobool17 = ($10 | 0) == 0;
+ if ($tobool17) {
+ label = 11;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $LR = $f + 64 | 0;
+ $11 = HEAP8[$LR] | 0;
+ $tobool19 = $11 << 24 >> 24 == 0;
+ $conv25 = +($10 | 0);
+ $sub_sink = $tobool19 ? $sub5 : $sub;
+ $div = $sub_sink / $conv25;
+ $12 = HEAP32[$n_flds >> 2] | 0;
+ $cmp24 = ($12 | 0) > 0;
+ if ($cmp24) {
+ label = 6;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 6:
+ $fld = $f + 56 | 0;
+ $13 = +HEAPF64[$x >> 3];
+ $14 = +HEAPF64[$y >> 3];
+ $i_025 = 0;
+ label = 7;
+ break;
+ case 7:
+ $15 = HEAP32[$fld >> 2] | 0;
+ $arrayidx = $15 + ($i_025 << 2) | 0;
+ $16 = HEAP32[$arrayidx >> 2] | 0;
+ $add30 = $i_025 + 1 | 0;
+ $conv31 = +($add30 | 0);
+ $mul = $div * $conv31;
+ $conv32 = ~~$mul;
+ $conv33 = +($i_025 | 0);
+ $mul34 = $div * $conv33;
+ $conv35 = ~~$mul34;
+ $sub36 = $conv32 - $conv35 | 0;
+ $17 = HEAP8[$LR] | 0;
+ $tobool38 = $17 << 24 >> 24 == 0;
+ if ($tobool38) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $x41 = $16 | 0;
+ $18 = +HEAPF64[$x41 >> 3];
+ $conv42 = +($sub36 | 0);
+ $add43 = $conv42 + $18;
+ _pointfof795($newsz, $add43, $14);
+ label = 10;
+ break;
+ case 9:
+ $y48 = $16 + 8 | 0;
+ $19 = +HEAPF64[$y48 >> 3];
+ $conv49 = +($sub36 | 0);
+ $add50 = $conv49 + $19;
+ _pointfof795($newsz, $13, $add50);
+ label = 10;
+ break;
+ case 10:
+ _resize_reclbl($16, $newsz, $nojustify_p);
+ $20 = HEAP32[$n_flds >> 2] | 0;
+ $cmp = ($add30 | 0) < ($20 | 0);
+ if ($cmp) {
+ $i_025 = $add30;
+ label = 7;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pos_reclbl($f, $ul, $sides) {
+ $f = $f | 0;
+ $ul = $ul | 0;
+ $sides = $sides | 0;
+ var $tmp = 0, $tmp8 = 0, $conv = 0, $sides1 = 0, $b = 0, $x = 0, $0 = 0.0, $y = 0, $1 = 0.0, $y2 = 0, $2 = 0.0, $sub = 0.0, $3 = 0, $4 = 0, $UR = 0, $5 = 0.0, $x6 = 0, $6 = 0.0, $add = 0.0, $7 = 0.0, $8 = 0, $9 = 0, $n_flds = 0, $10 = 0, $sub9 = 0, $cmp23 = 0, $tobool = 0, $fld = 0, $LR45 = 0, $LR = 0, $i_024 = 0, $11 = 0, $tobool11 = 0, $cmp13 = 0, $cmp16 = 0, $_ = 0, $_20 = 0, $_21 = 0, $_22 = 0, $mask_0 = 0, $12 = 0, $arrayidx = 0, $13 = 0, $and = 0, $14 = 0, $tobool46 = 0, $15 = 0.0, $16 = 0, $arrayidx50 = 0, $17 = 0, $x52 = 0, $18 = 0.0, $add53 = 0.0, $19 = 0.0, $20 = 0, $arrayidx58 = 0, $21 = 0, $y60 = 0, $22 = 0.0, $sub61 = 0.0, $inc = 0, $cmp = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $ul;
+ $ul = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$ul >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$ul + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$ul + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$ul + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmp8 = __stackBase__ + 16 | 0;
+ $conv = $sides & 255;
+ $sides1 = $f + 65 | 0;
+ HEAP8[$sides1] = $conv;
+ $b = $f + 16 | 0;
+ $x = $ul | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $y = $ul + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $y2 = $f + 8 | 0;
+ $2 = +HEAPF64[$y2 >> 3];
+ $sub = $1 - $2;
+ _pointfof795($tmp, $0, $sub);
+ $3 = $b;
+ $4 = $tmp;
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $UR = $f + 32 | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $x6 = $f | 0;
+ $6 = +HEAPF64[$x6 >> 3];
+ $add = $5 + $6;
+ $7 = +HEAPF64[$y >> 3];
+ _pointfof795($tmp8, $add, $7);
+ $8 = $UR;
+ $9 = $tmp8;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $n_flds = $f + 48 | 0;
+ $10 = HEAP32[$n_flds >> 2] | 0;
+ $sub9 = $10 - 1 | 0;
+ $cmp23 = ($sub9 | 0) < 0;
+ if ($cmp23) {
+ label = 16;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tobool = ($sides | 0) == 0;
+ $fld = $f + 56 | 0;
+ $LR45 = $f + 64 | 0;
+ $LR = $f + 64 | 0;
+ $i_024 = 0;
+ label = 4;
+ break;
+ case 4:
+ if ($tobool) {
+ $mask_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $11 = HEAP8[$LR] | 0;
+ $tobool11 = $11 << 24 >> 24 == 0;
+ $cmp13 = ($i_024 | 0) == 0;
+ $cmp16 = ($i_024 | 0) == ($sub9 | 0);
+ if ($tobool11) {
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $_ = $cmp16 ? 15 : 13;
+ $mask_0 = $_;
+ label = 12;
+ break;
+ case 8:
+ $_20 = $cmp16 ? 7 : 5;
+ $mask_0 = $_20;
+ label = 12;
+ break;
+ case 9:
+ if ($cmp13) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $_21 = $cmp16 ? 15 : 14;
+ $mask_0 = $_21;
+ label = 12;
+ break;
+ case 11:
+ $_22 = $cmp16 ? 11 : 10;
+ $mask_0 = $_22;
+ label = 12;
+ break;
+ case 12:
+ $12 = HEAP32[$fld >> 2] | 0;
+ $arrayidx = $12 + ($i_024 << 2) | 0;
+ $13 = HEAP32[$arrayidx >> 2] | 0;
+ $and = $mask_0 & $sides;
+ _pos_reclbl($13, $ul, $and);
+ $14 = HEAP8[$LR45] | 0;
+ $tobool46 = $14 << 24 >> 24 == 0;
+ if ($tobool46) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $15 = +HEAPF64[$x >> 3];
+ $16 = HEAP32[$fld >> 2] | 0;
+ $arrayidx50 = $16 + ($i_024 << 2) | 0;
+ $17 = HEAP32[$arrayidx50 >> 2] | 0;
+ $x52 = $17 | 0;
+ $18 = +HEAPF64[$x52 >> 3];
+ $add53 = $15 + $18;
+ HEAPF64[$x >> 3] = $add53;
+ label = 15;
+ break;
+ case 14:
+ $19 = +HEAPF64[$y >> 3];
+ $20 = HEAP32[$fld >> 2] | 0;
+ $arrayidx58 = $20 + ($i_024 << 2) | 0;
+ $21 = HEAP32[$arrayidx58 >> 2] | 0;
+ $y60 = $21 + 8 | 0;
+ $22 = +HEAPF64[$y60 >> 3];
+ $sub61 = $19 - $22;
+ HEAPF64[$y >> 3] = $sub61;
+ label = 15;
+ break;
+ case 15:
+ $inc = $i_024 + 1 | 0;
+ $cmp = ($inc | 0) > ($sub9 | 0);
+ if ($cmp) {
+ label = 16;
+ break;
+ } else {
+ $i_024 = $inc;
+ label = 4;
+ break;
+ }
+ case 16:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _parse_error($rv, $port) {
+ $rv = $rv | 0;
+ $port = $port | 0;
+ var $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _free_field($rv);
+ $tobool = ($port | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _free($port);
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _userSize($n) {
+ $n = $n | 0;
+ var $0 = 0, $1 = 0, $call = 0.0, $2 = 0, $call1 = 0.0, $cmp = 0, $cond = 0.0, $mul = 0.0, $cmp2 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $conv21 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $n | 0;
+ $1 = HEAP32[41552] | 0;
+ $call = +_late_double($0, $1, 0.0, .01);
+ $2 = HEAP32[41592] | 0;
+ $call1 = +_late_double($0, $2, 0.0, .02);
+ $cmp = $call > $call1;
+ $cond = $cmp ? $call : $call1;
+ $mul = $cond * 72.0;
+ $cmp2 = $mul < 0.0;
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $mul + .5;
+ $add_sink = $add;
+ label = 5;
+ break;
+ case 4:
+ $sub = $mul + -.5;
+ $add_sink = $sub;
+ label = 5;
+ break;
+ case 5:
+ $conv = ~~$add_sink;
+ $conv21 = +($conv | 0);
+ return +$conv21;
+ }
+ return 0.0;
+}
+function _bezier_clip($inside_context, $inside, $sp, $left_inside) {
+ $inside_context = $inside_context | 0;
+ $inside = $inside | 0;
+ $sp = $sp | 0;
+ $left_inside = $left_inside | 0;
+ var $seg = 0, $best = 0, $pt = 0, $low = 0, $high = 0, $tobool = 0, $arraydecay1 = 0, $0 = 0, $1 = 0, $arrayidx2 = 0, $2 = 0, $3 = 0, $right_0 = 0, $left_0 = 0, $idir_0 = 0, $odir_0 = 0, $opt_sroa_0_0__idx = 0, $opt_sroa_1_8__idx16 = 0, $found_0 = 0, $opt_sroa_0_0_copyload = 0.0, $opt_sroa_1_8_copyload = 0.0, $high_0_load21 = 0.0, $low_0_load22 = 0.0, $add = 0.0, $div = 0.0, $call = 0, $tobool3 = 0, $4 = 0, $5 = 0, $arrayidx6_1 = 0, $arrayidx7_1 = 0, $6 = 0, $7 = 0, $arrayidx6_2 = 0, $arrayidx7_2 = 0, $8 = 0, $9 = 0, $arrayidx6_3 = 0, $arrayidx7_3 = 0, $10 = 0, $11 = 0, $found_1 = 0, $12 = 0.0, $sub = 0.0, $cmp10 = 0, $sub17 = 0.0, $cond = 0.0, $cmp18 = 0, $13 = 0.0, $sub20 = 0.0, $cmp21 = 0, $sub30 = 0.0, $cond32 = 0.0, $cmp33 = 0, $tobool34 = 0, $14 = 0, $15 = 0, $arrayidx39_1 = 0, $arrayidx40_1 = 0, $16 = 0, $17 = 0, $arrayidx39_2 = 0, $arrayidx40_2 = 0, $18 = 0, $19 = 0, $arrayidx39_3 = 0, $arrayidx40_3 = 0, $20 = 0, $21 = 0, $22 = 0, $arrayidx48_1 = 0, $arrayidx49_1 = 0, $23 = 0, $24 = 0, $arrayidx48_2 = 0, $arrayidx49_2 = 0, $25 = 0, $26 = 0, $arrayidx48_3 = 0, $arrayidx49_3 = 0, $27 = 0, $28 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 160 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $seg = __stackBase__ | 0;
+ $best = __stackBase__ + 64 | 0;
+ $pt = __stackBase__ + 128 | 0;
+ $low = __stackBase__ + 144 | 0;
+ $high = __stackBase__ + 152 | 0;
+ $tobool = $left_inside << 24 >> 24 == 0;
+ $arraydecay1 = $seg | 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = $pt;
+ $1 = $sp;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $odir_0 = $high;
+ $idir_0 = $low;
+ $left_0 = 0;
+ $right_0 = $arraydecay1;
+ label = 5;
+ break;
+ case 4:
+ $arrayidx2 = $sp + 48 | 0;
+ $2 = $pt;
+ $3 = $arrayidx2;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $odir_0 = $low;
+ $idir_0 = $high;
+ $left_0 = $arraydecay1;
+ $right_0 = 0;
+ label = 5;
+ break;
+ case 5:
+ HEAPF64[$low >> 3] = 0.0;
+ HEAPF64[$high >> 3] = 1.0;
+ $opt_sroa_0_0__idx = $pt | 0;
+ $opt_sroa_1_8__idx16 = $pt + 8 | 0;
+ $found_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ $opt_sroa_0_0_copyload = +HEAPF64[$opt_sroa_0_0__idx >> 3];
+ $opt_sroa_1_8_copyload = +HEAPF64[$opt_sroa_1_8__idx16 >> 3];
+ $high_0_load21 = +HEAPF64[$high >> 3];
+ $low_0_load22 = +HEAPF64[$low >> 3];
+ $add = $high_0_load21 + $low_0_load22;
+ $div = $add * .5;
+ _Bezier($pt, $sp, 3, $div, $left_0, $right_0);
+ $call = FUNCTION_TABLE_iii[$inside & 1023]($inside_context, $pt) | 0;
+ $tobool3 = $call << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ HEAPF64[$idir_0 >> 3] = $div;
+ $found_1 = $found_0;
+ label = 9;
+ break;
+ case 8:
+ $4 = $best;
+ $5 = $seg;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $arrayidx6_1 = $best + 16 | 0;
+ $arrayidx7_1 = $seg + 16 | 0;
+ $6 = $arrayidx6_1;
+ $7 = $arrayidx7_1;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $arrayidx6_2 = $best + 32 | 0;
+ $arrayidx7_2 = $seg + 32 | 0;
+ $8 = $arrayidx6_2;
+ $9 = $arrayidx7_2;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $arrayidx6_3 = $best + 48 | 0;
+ $arrayidx7_3 = $seg + 48 | 0;
+ $10 = $arrayidx6_3;
+ $11 = $arrayidx7_3;
+ HEAP32[$10 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ HEAPF64[$odir_0 >> 3] = $div;
+ $found_1 = 1;
+ label = 9;
+ break;
+ case 9:
+ $12 = +HEAPF64[$opt_sroa_0_0__idx >> 3];
+ $sub = $opt_sroa_0_0_copyload - $12;
+ $cmp10 = $sub < 0.0;
+ if ($cmp10) {
+ label = 10;
+ break;
+ } else {
+ $cond = $sub;
+ label = 11;
+ break;
+ }
+ case 10:
+ $sub17 = -0.0 - $sub;
+ $cond = $sub17;
+ label = 11;
+ break;
+ case 11:
+ $cmp18 = $cond > .5;
+ if ($cmp18) {
+ $found_0 = $found_1;
+ label = 6;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $13 = +HEAPF64[$opt_sroa_1_8__idx16 >> 3];
+ $sub20 = $opt_sroa_1_8_copyload - $13;
+ $cmp21 = $sub20 < 0.0;
+ if ($cmp21) {
+ label = 13;
+ break;
+ } else {
+ $cond32 = $sub20;
+ label = 14;
+ break;
+ }
+ case 13:
+ $sub30 = -0.0 - $sub20;
+ $cond32 = $sub30;
+ label = 14;
+ break;
+ case 14:
+ $cmp33 = $cond32 > .5;
+ if ($cmp33) {
+ $found_0 = $found_1;
+ label = 6;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $tobool34 = $found_1 << 24 >> 24 == 0;
+ $14 = $sp;
+ if ($tobool34) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $15 = $best;
+ HEAP32[$14 >> 2] = HEAP32[$15 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$15 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$15 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$15 + 12 >> 2] | 0;
+ $arrayidx39_1 = $sp + 16 | 0;
+ $arrayidx40_1 = $best + 16 | 0;
+ $16 = $arrayidx39_1;
+ $17 = $arrayidx40_1;
+ HEAP32[$16 >> 2] = HEAP32[$17 >> 2] | 0;
+ HEAP32[$16 + 4 >> 2] = HEAP32[$17 + 4 >> 2] | 0;
+ HEAP32[$16 + 8 >> 2] = HEAP32[$17 + 8 >> 2] | 0;
+ HEAP32[$16 + 12 >> 2] = HEAP32[$17 + 12 >> 2] | 0;
+ $arrayidx39_2 = $sp + 32 | 0;
+ $arrayidx40_2 = $best + 32 | 0;
+ $18 = $arrayidx39_2;
+ $19 = $arrayidx40_2;
+ HEAP32[$18 >> 2] = HEAP32[$19 >> 2] | 0;
+ HEAP32[$18 + 4 >> 2] = HEAP32[$19 + 4 >> 2] | 0;
+ HEAP32[$18 + 8 >> 2] = HEAP32[$19 + 8 >> 2] | 0;
+ HEAP32[$18 + 12 >> 2] = HEAP32[$19 + 12 >> 2] | 0;
+ $arrayidx39_3 = $sp + 48 | 0;
+ $arrayidx40_3 = $best + 48 | 0;
+ $20 = $arrayidx39_3;
+ $21 = $arrayidx40_3;
+ HEAP32[$20 >> 2] = HEAP32[$21 >> 2] | 0;
+ HEAP32[$20 + 4 >> 2] = HEAP32[$21 + 4 >> 2] | 0;
+ HEAP32[$20 + 8 >> 2] = HEAP32[$21 + 8 >> 2] | 0;
+ HEAP32[$20 + 12 >> 2] = HEAP32[$21 + 12 >> 2] | 0;
+ label = 18;
+ break;
+ case 17:
+ $22 = $seg;
+ HEAP32[$14 >> 2] = HEAP32[$22 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$22 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$22 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$22 + 12 >> 2] | 0;
+ $arrayidx48_1 = $sp + 16 | 0;
+ $arrayidx49_1 = $seg + 16 | 0;
+ $23 = $arrayidx48_1;
+ $24 = $arrayidx49_1;
+ HEAP32[$23 >> 2] = HEAP32[$24 >> 2] | 0;
+ HEAP32[$23 + 4 >> 2] = HEAP32[$24 + 4 >> 2] | 0;
+ HEAP32[$23 + 8 >> 2] = HEAP32[$24 + 8 >> 2] | 0;
+ HEAP32[$23 + 12 >> 2] = HEAP32[$24 + 12 >> 2] | 0;
+ $arrayidx48_2 = $sp + 32 | 0;
+ $arrayidx49_2 = $seg + 32 | 0;
+ $25 = $arrayidx48_2;
+ $26 = $arrayidx49_2;
+ HEAP32[$25 >> 2] = HEAP32[$26 >> 2] | 0;
+ HEAP32[$25 + 4 >> 2] = HEAP32[$26 + 4 >> 2] | 0;
+ HEAP32[$25 + 8 >> 2] = HEAP32[$26 + 8 >> 2] | 0;
+ HEAP32[$25 + 12 >> 2] = HEAP32[$26 + 12 >> 2] | 0;
+ $arrayidx48_3 = $sp + 48 | 0;
+ $arrayidx49_3 = $seg + 48 | 0;
+ $27 = $arrayidx48_3;
+ $28 = $arrayidx49_3;
+ HEAP32[$27 >> 2] = HEAP32[$28 >> 2] | 0;
+ HEAP32[$27 + 4 >> 2] = HEAP32[$28 + 4 >> 2] | 0;
+ HEAP32[$27 + 8 >> 2] = HEAP32[$28 + 8 >> 2] | 0;
+ HEAP32[$27 + 12 >> 2] = HEAP32[$28 + 12 >> 2] | 0;
+ label = 18;
+ break;
+ case 18:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _shape_clip($n, $curve) {
+ $n = $n | 0;
+ $curve = $curve | 0;
+ var $c = 0, $inside_context = 0, $shape = 0, $0 = 0, $cmp = 0, $fns = 0, $1 = 0, $insidefn = 0, $2 = 0, $cmp3 = 0, $3 = 0, $n_c = 0, $bp = 0, $rw = 0, $4 = 0.0, $conv = 0, $x = 0, $5 = 0.0, $x8 = 0, $6 = 0.0, $sub = 0.0, $x9 = 0, $y = 0, $7 = 0.0, $y13 = 0, $8 = 0.0, $sub14 = 0.0, $y15 = 0, $9 = 0, $fns18 = 0, $10 = 0, $insidefn19 = 0, $11 = 0, $call = 0, $conv20 = 0.0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 24 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $c = __stackBase__ | 0;
+ $inside_context = __stackBase__ + 16 | 0;
+ $shape = $n + 24 | 0;
+ $0 = HEAP32[$shape >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $fns = $0 + 4 | 0;
+ $1 = HEAP32[$fns >> 2] | 0;
+ $insidefn = $1 + 12 | 0;
+ $2 = HEAP32[$insidefn >> 2] | 0;
+ $cmp3 = ($2 | 0) == 0;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = $inside_context | 0;
+ $n_c = $n;
+ HEAP32[$3 >> 2] = $n_c;
+ $bp = $inside_context + 4 | 0;
+ HEAP32[$bp >> 2] = 0;
+ $rw = $n + 112 | 0;
+ $4 = +HEAPF64[$rw >> 3];
+ $conv = ~~$4;
+ $x = $curve | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $x8 = $n + 32 | 0;
+ $6 = +HEAPF64[$x8 >> 3];
+ $sub = $5 - $6;
+ $x9 = $c | 0;
+ HEAPF64[$x9 >> 3] = $sub;
+ $y = $curve + 8 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $y13 = $n + 40 | 0;
+ $8 = +HEAPF64[$y13 >> 3];
+ $sub14 = $7 - $8;
+ $y15 = $c + 8 | 0;
+ HEAPF64[$y15 >> 3] = $sub14;
+ $9 = HEAP32[$shape >> 2] | 0;
+ $fns18 = $9 + 4 | 0;
+ $10 = HEAP32[$fns18 >> 2] | 0;
+ $insidefn19 = $10 + 12 | 0;
+ $11 = HEAP32[$insidefn19 >> 2] | 0;
+ $call = FUNCTION_TABLE_iii[$11 & 1023]($inside_context, $c) | 0;
+ $conv20 = +($conv | 0);
+ HEAPF64[$rw >> 3] = $conv20;
+ _shape_clip0($inside_context, $n, $curve, $call);
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _shape_clip0($inside_context, $n, $curve, $left_inside) {
+ $inside_context = $inside_context | 0;
+ $n = $n | 0;
+ $curve = $curve | 0;
+ $left_inside = $left_inside | 0;
+ var $c = 0, $rw = 0, $0 = 0.0, $1 = 0.0, $2 = 0.0, $x22 = 0, $y29 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ $c = __stackBase__ | 0;
+ $rw = $n + 112 | 0;
+ $0 = +HEAPF64[$n + 32 >> 3];
+ $1 = +HEAPF64[$n + 40 >> 3];
+ $2 = +HEAPF64[$rw >> 3];
+ HEAPF64[$c >> 3] = +HEAPF64[$curve >> 3] - $0;
+ HEAPF64[$c + 8 >> 3] = +HEAPF64[$curve + 8 >> 3] - $1;
+ HEAPF64[$c + 16 >> 3] = +HEAPF64[$curve + 16 >> 3] - $0;
+ HEAPF64[$c + 24 >> 3] = +HEAPF64[$curve + 24 >> 3] - $1;
+ HEAPF64[$c + 32 >> 3] = +HEAPF64[$curve + 32 >> 3] - $0;
+ HEAPF64[$c + 40 >> 3] = +HEAPF64[$curve + 40 >> 3] - $1;
+ HEAPF64[$c + 48 >> 3] = +HEAPF64[$curve + 48 >> 3] - $0;
+ HEAPF64[$c + 56 >> 3] = +HEAPF64[$curve + 56 >> 3] - $1;
+ _bezier_clip($inside_context, HEAP32[(HEAP32[(HEAP32[$n + 24 >> 2] | 0) + 4 >> 2] | 0) + 12 >> 2] | 0, $c | 0, $left_inside);
+ $x22 = $n + 32 | 0;
+ $y29 = $n + 40 | 0;
+ HEAPF64[$curve >> 3] = +HEAPF64[$c >> 3] + +HEAPF64[$x22 >> 3];
+ HEAPF64[$curve + 8 >> 3] = +HEAPF64[$c + 8 >> 3] + +HEAPF64[$y29 >> 3];
+ HEAPF64[$curve + 16 >> 3] = +HEAPF64[$c + 16 >> 3] + +HEAPF64[$x22 >> 3];
+ HEAPF64[$curve + 24 >> 3] = +HEAPF64[$c + 24 >> 3] + +HEAPF64[$y29 >> 3];
+ HEAPF64[$curve + 32 >> 3] = +HEAPF64[$c + 32 >> 3] + +HEAPF64[$x22 >> 3];
+ HEAPF64[$curve + 40 >> 3] = +HEAPF64[$c + 40 >> 3] + +HEAPF64[$y29 >> 3];
+ HEAPF64[$curve + 48 >> 3] = +HEAPF64[$c + 48 >> 3] + +HEAPF64[$x22 >> 3];
+ HEAPF64[$curve + 56 >> 3] = +HEAPF64[$c + 56 >> 3] + +HEAPF64[$y29 >> 3];
+ HEAPF64[$rw >> 3] = +(~~$2 | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _new_spline($e, $sz) {
+ $e = $e | 0;
+ $sz = $sz | 0;
+ var $edge_type14 = 0, $0 = 0, $cmp15 = 0, $e_addr_016 = 0, $to_orig = 0, $1 = 0, $edge_type = 0, $2 = 0, $cmp = 0, $e_addr_0_lcssa = 0, $spl = 0, $3 = 0, $cmp4 = 0, $call = 0, $4 = 0, $5 = 0, $list = 0, $6 = 0, $tobool = 0, $7 = 0, $size = 0, $8 = 0, $9 = 0, $mul = 0, $call15 = 0, $size18 = 0, $10 = 0, $11 = 0, $mul20 = 0, $call21 = 0, $call15_sink = 0, $12 = 0, $13 = 0, $list24 = 0, $14 = 0, $size27 = 0, $15 = 0, $inc = 0, $16 = 0, $list30 = 0, $17 = 0, $arrayidx = 0, $mul31 = 0, $call32 = 0, $18 = 0, $list33 = 0, $size34 = 0, $eflag = 0, $sflag = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $edge_type14 = $e + 128 | 0;
+ $0 = HEAP8[$edge_type14] | 0;
+ $cmp15 = $0 << 24 >> 24 == 0;
+ if ($cmp15) {
+ $e_addr_0_lcssa = $e;
+ label = 4;
+ break;
+ } else {
+ $e_addr_016 = $e;
+ label = 3;
+ break;
+ }
+ case 3:
+ $to_orig = $e_addr_016 + 132 | 0;
+ $1 = HEAP32[$to_orig >> 2] | 0;
+ $edge_type = $1 + 128 | 0;
+ $2 = HEAP8[$edge_type] | 0;
+ $cmp = $2 << 24 >> 24 == 0;
+ if ($cmp) {
+ $e_addr_0_lcssa = $1;
+ label = 4;
+ break;
+ } else {
+ $e_addr_016 = $1;
+ label = 3;
+ break;
+ }
+ case 4:
+ $spl = $e_addr_0_lcssa + 24 | 0;
+ $3 = HEAP32[$spl >> 2] | 0;
+ $cmp4 = ($3 | 0) == 0;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call = _zmalloc(40) | 0;
+ $4 = $call;
+ HEAP32[$spl >> 2] = $4;
+ label = 6;
+ break;
+ case 6:
+ $5 = HEAP32[$spl >> 2] | 0;
+ $list = $5 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $7 = $6;
+ $size = $5 + 4 | 0;
+ $8 = HEAP32[$size >> 2] | 0;
+ $9 = $8 * 48 & -1;
+ $mul = $9 + 48 | 0;
+ $call15 = _grealloc($7, $mul) | 0;
+ $call15_sink = $call15;
+ label = 9;
+ break;
+ case 8:
+ $size18 = $5 + 4 | 0;
+ $10 = HEAP32[$size18 >> 2] | 0;
+ $11 = $10 * 48 & -1;
+ $mul20 = $11 + 48 | 0;
+ $call21 = _gmalloc($mul20) | 0;
+ $call15_sink = $call21;
+ label = 9;
+ break;
+ case 9:
+ $12 = $call15_sink;
+ $13 = HEAP32[$spl >> 2] | 0;
+ $list24 = $13 | 0;
+ HEAP32[$list24 >> 2] = $12;
+ $14 = HEAP32[$spl >> 2] | 0;
+ $size27 = $14 + 4 | 0;
+ $15 = HEAP32[$size27 >> 2] | 0;
+ $inc = $15 + 1 | 0;
+ HEAP32[$size27 >> 2] = $inc;
+ $16 = HEAP32[$spl >> 2] | 0;
+ $list30 = $16 | 0;
+ $17 = HEAP32[$list30 >> 2] | 0;
+ $arrayidx = $17 + ($15 * 48 & -1) | 0;
+ $mul31 = $sz << 4;
+ $call32 = _zmalloc($mul31) | 0;
+ $18 = $call32;
+ $list33 = $arrayidx | 0;
+ HEAP32[$list33 >> 2] = $18;
+ $size34 = $17 + ($15 * 48 & -1) + 4 | 0;
+ HEAP32[$size34 >> 2] = $sz;
+ $eflag = $17 + ($15 * 48 & -1) + 12 | 0;
+ HEAP32[$eflag >> 2] = 0;
+ $sflag = $17 + ($15 * 48 & -1) + 8 | 0;
+ HEAP32[$sflag >> 2] = 0;
+ return $arrayidx | 0;
+ }
+ return 0;
+}
+function _clip_and_install($fe, $hn, $ps, $pn, $info) {
+ $fe = $fe | 0;
+ $hn = $hn | 0;
+ $ps = $ps | 0;
+ $pn = $pn | 0;
+ $info = $info | 0;
+ var $p2 = 0, $start = 0, $end = 0, $inside_context = 0, $cp = 0, $tail = 0, $0 = 0, $graph = 0, $1 = 0, $call = 0, $edge_type96 = 0, $2 = 0, $cmp97 = 0, $orig_098 = 0, $to_orig = 0, $3 = 0, $edge_type = 0, $4 = 0, $cmp = 0, $orig_0_lcssa = 0, $ignoreSwap = 0, $5 = 0, $tobool = 0, $rank = 0, $6 = 0, $rank5 = 0, $7 = 0, $cmp6 = 0, $order = 0, $8 = 0, $order11 = 0, $9 = 0, $cmp12 = 0, $hn_ = 0, $_hn = 0, $tn_0 = 0, $hn_addr_0 = 0, $tail14 = 0, $10 = 0, $cmp15 = 0, $clip = 0, $clip21 = 0, $bp = 0, $bp27 = 0, $clip30 = 0, $clip34 = 0, $bp38 = 0, $bp41 = 0, $clipTail_0_in_in = 0, $clipHead_0_in_in = 0, $tbox_0_in = 0, $hbox_0_in = 0, $clipHead_0_in = 0, $clipTail_0_in = 0, $hbox_0 = 0, $tbox_0 = 0, $tobool43 = 0, $shape = 0, $11 = 0, $tobool46 = 0, $fns = 0, $12 = 0, $insidefn = 0, $13 = 0, $tobool50 = 0, $14 = 0, $tn_0_c = 0, $bp53 = 0, $tbox_0_c = 0, $sub = 0, $cmp5594 = 0, $x59 = 0, $x61 = 0, $y66 = 0, $y68 = 0, $storemerge8695 = 0, $add = 0, $x = 0, $15 = 0.0, $16 = 0.0, $sub60 = 0.0, $17 = 0, $add62 = 0, $y = 0, $18 = 0.0, $19 = 0.0, $sub67 = 0.0, $20 = 0, $fns71 = 0, $21 = 0, $insidefn72 = 0, $22 = 0, $call73 = 0, $cmp75 = 0, $23 = 0, $add80 = 0, $cmp55 = 0, $24 = 0, $arrayidx82 = 0, $tobool85 = 0, $shape88 = 0, $25 = 0, $tobool89 = 0, $fns93 = 0, $26 = 0, $insidefn94 = 0, $27 = 0, $tobool95 = 0, $28 = 0, $hn_addr_0_c = 0, $bp100 = 0, $hbox_0_c = 0, $sub101 = 0, $cmp10392 = 0, $x110 = 0, $x112 = 0, $y117 = 0, $y119 = 0, $storemerge93 = 0, $x107 = 0, $29 = 0.0, $30 = 0.0, $sub111 = 0.0, $31 = 0, $y114 = 0, $32 = 0.0, $33 = 0.0, $sub118 = 0.0, $34 = 0, $fns122 = 0, $35 = 0, $insidefn123 = 0, $36 = 0, $call124 = 0, $cmp126 = 0, $37 = 0, $sub131 = 0, $cmp103 = 0, $38 = 0, $arrayidx133 = 0, $sub135 = 0, $39 = 0, $sub138 = 0, $cmp13991 = 0, $40 = 0, $x143 = 0, $41 = 0.0, $add144 = 0, $x146 = 0, $42 = 0.0, $sub147 = 0.0, $mul = 0.0, $y155 = 0, $43 = 0.0, $y158 = 0, $44 = 0.0, $sub159 = 0.0, $mul166 = 0.0, $add167 = 0.0, $cmp168 = 0, $cmp139 = 0, $_pr = 0, $cmp17690 = 0, $45 = 0, $x180 = 0, $46 = 0.0, $add181 = 0, $x183 = 0, $47 = 0.0, $sub184 = 0.0, $mul191 = 0.0, $y193 = 0, $48 = 0.0, $y196 = 0, $49 = 0.0, $sub197 = 0.0, $mul204 = 0.0, $add205 = 0.0, $cmp206 = 0, $sub211 = 0, $cmp176 = 0, $50 = 0, $51 = 0, $add21487 = 0, $cmp21588 = 0, $52 = 0, $list = 0, $53 = 0, $54 = 0, $add224 = 0, $arrayidx222 = 0, $arrayidx233 = 0, $55 = 0, $56 = 0, $arrayidx240 = 0, $57 = 0, $arrayidx243 = 0, $58 = 0, $bb = 0, $59 = 0, $add214 = 0, $i_089 = 0, $sub219 = 0, $60 = 0, $arrayidx220 = 0, $arrayidx221 = 0, $61 = 0, $62 = 0, $inc = 0, $cmp225 = 0, $sub229 = 0, $63 = 0, $arrayidx231 = 0, $arrayidx232 = 0, $64 = 0, $65 = 0, $inc235 = 0, $sub236 = 0, $66 = 0, $arrayidx238 = 0, $arrayidx239 = 0, $67 = 0, $68 = 0, $inc242 = 0, $arrayidx244 = 0, $69 = 0, $cmp215 = 0, $70 = 0, $71 = 0, $sub247 = 0, $add248 = 0, $size = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 104 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p2 = __stackBase__ | 0;
+ $start = __stackBase__ + 16 | 0;
+ $end = __stackBase__ + 24 | 0;
+ $inside_context = __stackBase__ + 32 | 0;
+ $cp = __stackBase__ + 40 | 0;
+ $tail = $fe + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $call = _new_spline($fe, $pn) | 0;
+ $edge_type96 = $fe + 128 | 0;
+ $2 = HEAP8[$edge_type96] | 0;
+ $cmp97 = $2 << 24 >> 24 == 0;
+ if ($cmp97) {
+ $orig_0_lcssa = $fe;
+ label = 4;
+ break;
+ } else {
+ $orig_098 = $fe;
+ label = 3;
+ break;
+ }
+ case 3:
+ $to_orig = $orig_098 + 132 | 0;
+ $3 = HEAP32[$to_orig >> 2] | 0;
+ $edge_type = $3 + 128 | 0;
+ $4 = HEAP8[$edge_type] | 0;
+ $cmp = $4 << 24 >> 24 == 0;
+ if ($cmp) {
+ $orig_0_lcssa = $3;
+ label = 4;
+ break;
+ } else {
+ $orig_098 = $3;
+ label = 3;
+ break;
+ }
+ case 4:
+ $ignoreSwap = $info + 8 | 0;
+ $5 = HEAP8[$ignoreSwap] | 0;
+ $tobool = $5 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $hn_addr_0 = $hn;
+ $tn_0 = $0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $rank = $0 + 236 | 0;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $rank5 = $hn + 236 | 0;
+ $7 = HEAP32[$rank5 >> 2] | 0;
+ $cmp6 = ($6 | 0) == ($7 | 0);
+ if ($cmp6) {
+ label = 6;
+ break;
+ } else {
+ $hn_addr_0 = $hn;
+ $tn_0 = $0;
+ label = 7;
+ break;
+ }
+ case 6:
+ $order = $0 + 240 | 0;
+ $8 = HEAP32[$order >> 2] | 0;
+ $order11 = $hn + 240 | 0;
+ $9 = HEAP32[$order11 >> 2] | 0;
+ $cmp12 = ($8 | 0) > ($9 | 0);
+ $hn_ = $cmp12 ? $hn : $0;
+ $_hn = $cmp12 ? $0 : $hn;
+ $hn_addr_0 = $_hn;
+ $tn_0 = $hn_;
+ label = 7;
+ break;
+ case 7:
+ $tail14 = $orig_0_lcssa + 16 | 0;
+ $10 = HEAP32[$tail14 >> 2] | 0;
+ $cmp15 = ($tn_0 | 0) == ($10 | 0);
+ if ($cmp15) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $clip = $orig_0_lcssa + 62 | 0;
+ $clip21 = $orig_0_lcssa + 102 | 0;
+ $bp = $orig_0_lcssa + 56 | 0;
+ $bp27 = $orig_0_lcssa + 96 | 0;
+ $hbox_0_in = $bp27;
+ $tbox_0_in = $bp;
+ $clipHead_0_in_in = $clip21;
+ $clipTail_0_in_in = $clip;
+ label = 10;
+ break;
+ case 9:
+ $clip30 = $orig_0_lcssa + 102 | 0;
+ $clip34 = $orig_0_lcssa + 62 | 0;
+ $bp38 = $orig_0_lcssa + 56 | 0;
+ $bp41 = $orig_0_lcssa + 96 | 0;
+ $hbox_0_in = $bp38;
+ $tbox_0_in = $bp41;
+ $clipHead_0_in_in = $clip34;
+ $clipTail_0_in_in = $clip30;
+ label = 10;
+ break;
+ case 10:
+ $clipHead_0_in = HEAP8[$clipHead_0_in_in] | 0;
+ $clipTail_0_in = HEAP8[$clipTail_0_in_in] | 0;
+ $hbox_0 = HEAP32[$hbox_0_in >> 2] | 0;
+ $tbox_0 = HEAP32[$tbox_0_in >> 2] | 0;
+ $tobool43 = $clipTail_0_in << 24 >> 24 == 0;
+ if ($tobool43) {
+ label = 18;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $shape = $tn_0 + 24 | 0;
+ $11 = HEAP32[$shape >> 2] | 0;
+ $tobool46 = ($11 | 0) == 0;
+ if ($tobool46) {
+ label = 18;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $fns = $11 + 4 | 0;
+ $12 = HEAP32[$fns >> 2] | 0;
+ $insidefn = $12 + 12 | 0;
+ $13 = HEAP32[$insidefn >> 2] | 0;
+ $tobool50 = ($13 | 0) == 0;
+ if ($tobool50) {
+ label = 18;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $14 = $inside_context | 0;
+ $tn_0_c = $tn_0;
+ HEAP32[$14 >> 2] = $tn_0_c;
+ $bp53 = $inside_context + 4 | 0;
+ $tbox_0_c = $tbox_0 | 0;
+ HEAP32[$bp53 >> 2] = $tbox_0_c;
+ HEAP32[$start >> 2] = 0;
+ $sub = $pn - 4 | 0;
+ $cmp5594 = ($sub | 0) > 0;
+ if ($cmp5594) {
+ label = 14;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 14:
+ $x59 = $tn_0 + 32 | 0;
+ $x61 = $p2 | 0;
+ $y66 = $tn_0 + 40 | 0;
+ $y68 = $p2 + 8 | 0;
+ $storemerge8695 = 0;
+ label = 15;
+ break;
+ case 15:
+ $add = $storemerge8695 + 3 | 0;
+ $x = $ps + ($add << 4) | 0;
+ $15 = +HEAPF64[$x >> 3];
+ $16 = +HEAPF64[$x59 >> 3];
+ $sub60 = $15 - $16;
+ HEAPF64[$x61 >> 3] = $sub60;
+ $17 = HEAP32[$start >> 2] | 0;
+ $add62 = $17 + 3 | 0;
+ $y = $ps + ($add62 << 4) + 8 | 0;
+ $18 = +HEAPF64[$y >> 3];
+ $19 = +HEAPF64[$y66 >> 3];
+ $sub67 = $18 - $19;
+ HEAPF64[$y68 >> 3] = $sub67;
+ $20 = HEAP32[$shape >> 2] | 0;
+ $fns71 = $20 + 4 | 0;
+ $21 = HEAP32[$fns71 >> 2] | 0;
+ $insidefn72 = $21 + 12 | 0;
+ $22 = HEAP32[$insidefn72 >> 2] | 0;
+ $call73 = FUNCTION_TABLE_iii[$22 & 1023]($inside_context, $p2) | 0;
+ $cmp75 = $call73 << 24 >> 24 == 0;
+ if ($cmp75) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $23 = HEAP32[$start >> 2] | 0;
+ $add80 = $23 + 3 | 0;
+ HEAP32[$start >> 2] = $add80;
+ $cmp55 = ($add80 | 0) < ($sub | 0);
+ if ($cmp55) {
+ $storemerge8695 = $add80;
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $24 = HEAP32[$start >> 2] | 0;
+ $arrayidx82 = $ps + ($24 << 4) | 0;
+ _shape_clip0($inside_context, $tn_0, $arrayidx82, 1);
+ label = 19;
+ break;
+ case 18:
+ HEAP32[$start >> 2] = 0;
+ label = 19;
+ break;
+ case 19:
+ $tobool85 = $clipHead_0_in << 24 >> 24 == 0;
+ if ($tobool85) {
+ label = 27;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $shape88 = $hn_addr_0 + 24 | 0;
+ $25 = HEAP32[$shape88 >> 2] | 0;
+ $tobool89 = ($25 | 0) == 0;
+ if ($tobool89) {
+ label = 27;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $fns93 = $25 + 4 | 0;
+ $26 = HEAP32[$fns93 >> 2] | 0;
+ $insidefn94 = $26 + 12 | 0;
+ $27 = HEAP32[$insidefn94 >> 2] | 0;
+ $tobool95 = ($27 | 0) == 0;
+ if ($tobool95) {
+ label = 27;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $28 = $inside_context | 0;
+ $hn_addr_0_c = $hn_addr_0;
+ HEAP32[$28 >> 2] = $hn_addr_0_c;
+ $bp100 = $inside_context + 4 | 0;
+ $hbox_0_c = $hbox_0 | 0;
+ HEAP32[$bp100 >> 2] = $hbox_0_c;
+ $sub101 = $pn - 4 | 0;
+ HEAP32[$end >> 2] = $sub101;
+ $cmp10392 = ($sub101 | 0) > 0;
+ if ($cmp10392) {
+ label = 23;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 23:
+ $x110 = $hn_addr_0 + 32 | 0;
+ $x112 = $p2 | 0;
+ $y117 = $hn_addr_0 + 40 | 0;
+ $y119 = $p2 + 8 | 0;
+ $storemerge93 = $sub101;
+ label = 24;
+ break;
+ case 24:
+ $x107 = $ps + ($storemerge93 << 4) | 0;
+ $29 = +HEAPF64[$x107 >> 3];
+ $30 = +HEAPF64[$x110 >> 3];
+ $sub111 = $29 - $30;
+ HEAPF64[$x112 >> 3] = $sub111;
+ $31 = HEAP32[$end >> 2] | 0;
+ $y114 = $ps + ($31 << 4) + 8 | 0;
+ $32 = +HEAPF64[$y114 >> 3];
+ $33 = +HEAPF64[$y117 >> 3];
+ $sub118 = $32 - $33;
+ HEAPF64[$y119 >> 3] = $sub118;
+ $34 = HEAP32[$shape88 >> 2] | 0;
+ $fns122 = $34 + 4 | 0;
+ $35 = HEAP32[$fns122 >> 2] | 0;
+ $insidefn123 = $35 + 12 | 0;
+ $36 = HEAP32[$insidefn123 >> 2] | 0;
+ $call124 = FUNCTION_TABLE_iii[$36 & 1023]($inside_context, $p2) | 0;
+ $cmp126 = $call124 << 24 >> 24 == 0;
+ if ($cmp126) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $37 = HEAP32[$end >> 2] | 0;
+ $sub131 = $37 - 3 | 0;
+ HEAP32[$end >> 2] = $sub131;
+ $cmp103 = ($sub131 | 0) > 0;
+ if ($cmp103) {
+ $storemerge93 = $sub131;
+ label = 24;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $38 = HEAP32[$end >> 2] | 0;
+ $arrayidx133 = $ps + ($38 << 4) | 0;
+ _shape_clip0($inside_context, $hn_addr_0, $arrayidx133, 0);
+ label = 28;
+ break;
+ case 27:
+ $sub135 = $pn - 4 | 0;
+ HEAP32[$end >> 2] = $sub135;
+ label = 28;
+ break;
+ case 28:
+ $39 = HEAP32[$start >> 2] | 0;
+ $sub138 = $pn - 4 | 0;
+ $cmp13991 = ($39 | 0) < ($sub138 | 0);
+ if ($cmp13991) {
+ $40 = $39;
+ label = 29;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 29:
+ $x143 = $ps + ($40 << 4) | 0;
+ $41 = +HEAPF64[$x143 >> 3];
+ $add144 = $40 + 3 | 0;
+ $x146 = $ps + ($add144 << 4) | 0;
+ $42 = +HEAPF64[$x146 >> 3];
+ $sub147 = $41 - $42;
+ $mul = $sub147 * $sub147;
+ $y155 = $ps + ($40 << 4) + 8 | 0;
+ $43 = +HEAPF64[$y155 >> 3];
+ $y158 = $ps + ($add144 << 4) + 8 | 0;
+ $44 = +HEAPF64[$y158 >> 3];
+ $sub159 = $43 - $44;
+ $mul166 = $sub159 * $sub159;
+ $add167 = $mul + $mul166;
+ $cmp168 = $add167 < 1.0e-6;
+ if ($cmp168) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ HEAP32[$start >> 2] = $add144;
+ $cmp139 = ($add144 | 0) < ($sub138 | 0);
+ if ($cmp139) {
+ $40 = $add144;
+ label = 29;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $_pr = HEAP32[$end >> 2] | 0;
+ $cmp17690 = ($_pr | 0) > 0;
+ if ($cmp17690) {
+ $45 = $_pr;
+ label = 32;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 32:
+ $x180 = $ps + ($45 << 4) | 0;
+ $46 = +HEAPF64[$x180 >> 3];
+ $add181 = $45 + 3 | 0;
+ $x183 = $ps + ($add181 << 4) | 0;
+ $47 = +HEAPF64[$x183 >> 3];
+ $sub184 = $46 - $47;
+ $mul191 = $sub184 * $sub184;
+ $y193 = $ps + ($45 << 4) + 8 | 0;
+ $48 = +HEAPF64[$y193 >> 3];
+ $y196 = $ps + ($add181 << 4) + 8 | 0;
+ $49 = +HEAPF64[$y196 >> 3];
+ $sub197 = $48 - $49;
+ $mul204 = $sub197 * $sub197;
+ $add205 = $mul191 + $mul204;
+ $cmp206 = $add205 < 1.0e-6;
+ if ($cmp206) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ $sub211 = $45 - 3 | 0;
+ HEAP32[$end >> 2] = $sub211;
+ $cmp176 = ($sub211 | 0) > 0;
+ if ($cmp176) {
+ $45 = $sub211;
+ label = 32;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ _arrow_clip($fe, $hn_addr_0, $ps, $start, $end, $call, $info);
+ $50 = HEAP32[$start >> 2] | 0;
+ $51 = HEAP32[$end >> 2] | 0;
+ $add21487 = $51 + 4 | 0;
+ $cmp21588 = ($50 | 0) < ($add21487 | 0);
+ if ($cmp21588) {
+ label = 35;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 35:
+ $52 = HEAP32[$start >> 2] | 0;
+ $list = $call | 0;
+ $53 = $cp;
+ $54 = HEAP32[$end >> 2] | 0;
+ $add224 = $54 + 4 | 0;
+ $arrayidx222 = $cp | 0;
+ $arrayidx233 = $cp + 16 | 0;
+ $55 = $arrayidx233;
+ $56 = HEAP32[$start >> 2] | 0;
+ $arrayidx240 = $cp + 32 | 0;
+ $57 = $arrayidx240;
+ $arrayidx243 = $cp + 48 | 0;
+ $58 = $arrayidx243;
+ $bb = $1 + 56 | 0;
+ $59 = HEAP32[$end >> 2] | 0;
+ $add214 = $59 + 4 | 0;
+ $i_089 = $50;
+ label = 36;
+ break;
+ case 36:
+ $sub219 = $i_089 - $52 | 0;
+ $60 = HEAP32[$list >> 2] | 0;
+ $arrayidx220 = $60 + ($sub219 << 4) | 0;
+ $arrayidx221 = $ps + ($i_089 << 4) | 0;
+ $61 = $arrayidx220;
+ $62 = $arrayidx221;
+ HEAP32[$61 >> 2] = HEAP32[$62 >> 2] | 0;
+ HEAP32[$61 + 4 >> 2] = HEAP32[$62 + 4 >> 2] | 0;
+ HEAP32[$61 + 8 >> 2] = HEAP32[$62 + 8 >> 2] | 0;
+ HEAP32[$61 + 12 >> 2] = HEAP32[$62 + 12 >> 2] | 0;
+ HEAP32[$53 >> 2] = HEAP32[$62 >> 2] | 0;
+ HEAP32[$53 + 4 >> 2] = HEAP32[$62 + 4 >> 2] | 0;
+ HEAP32[$53 + 8 >> 2] = HEAP32[$62 + 8 >> 2] | 0;
+ HEAP32[$53 + 12 >> 2] = HEAP32[$62 + 12 >> 2] | 0;
+ $inc = $i_089 + 1 | 0;
+ $cmp225 = ($inc | 0) < ($add224 | 0);
+ if ($cmp225) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ $sub229 = $inc - $52 | 0;
+ $63 = HEAP32[$list >> 2] | 0;
+ $arrayidx231 = $63 + ($sub229 << 4) | 0;
+ $arrayidx232 = $ps + ($inc << 4) | 0;
+ $64 = $arrayidx231;
+ $65 = $arrayidx232;
+ HEAP32[$64 >> 2] = HEAP32[$65 >> 2] | 0;
+ HEAP32[$64 + 4 >> 2] = HEAP32[$65 + 4 >> 2] | 0;
+ HEAP32[$64 + 8 >> 2] = HEAP32[$65 + 8 >> 2] | 0;
+ HEAP32[$64 + 12 >> 2] = HEAP32[$65 + 12 >> 2] | 0;
+ HEAP32[$55 >> 2] = HEAP32[$65 >> 2] | 0;
+ HEAP32[$55 + 4 >> 2] = HEAP32[$65 + 4 >> 2] | 0;
+ HEAP32[$55 + 8 >> 2] = HEAP32[$65 + 8 >> 2] | 0;
+ HEAP32[$55 + 12 >> 2] = HEAP32[$65 + 12 >> 2] | 0;
+ $inc235 = $i_089 + 2 | 0;
+ $sub236 = $inc235 - $56 | 0;
+ $66 = HEAP32[$list >> 2] | 0;
+ $arrayidx238 = $66 + ($sub236 << 4) | 0;
+ $arrayidx239 = $ps + ($inc235 << 4) | 0;
+ $67 = $arrayidx238;
+ $68 = $arrayidx239;
+ HEAP32[$67 >> 2] = HEAP32[$68 >> 2] | 0;
+ HEAP32[$67 + 4 >> 2] = HEAP32[$68 + 4 >> 2] | 0;
+ HEAP32[$67 + 8 >> 2] = HEAP32[$68 + 8 >> 2] | 0;
+ HEAP32[$67 + 12 >> 2] = HEAP32[$68 + 12 >> 2] | 0;
+ HEAP32[$57 >> 2] = HEAP32[$68 >> 2] | 0;
+ HEAP32[$57 + 4 >> 2] = HEAP32[$68 + 4 >> 2] | 0;
+ HEAP32[$57 + 8 >> 2] = HEAP32[$68 + 8 >> 2] | 0;
+ HEAP32[$57 + 12 >> 2] = HEAP32[$68 + 12 >> 2] | 0;
+ $inc242 = $i_089 + 3 | 0;
+ $arrayidx244 = $ps + ($inc242 << 4) | 0;
+ $69 = $arrayidx244;
+ HEAP32[$58 >> 2] = HEAP32[$69 >> 2] | 0;
+ HEAP32[$58 + 4 >> 2] = HEAP32[$69 + 4 >> 2] | 0;
+ HEAP32[$58 + 8 >> 2] = HEAP32[$69 + 8 >> 2] | 0;
+ HEAP32[$58 + 12 >> 2] = HEAP32[$69 + 12 >> 2] | 0;
+ _update_bb_bz($bb, $arrayidx222);
+ $cmp215 = ($inc242 | 0) < ($add214 | 0);
+ if ($cmp215) {
+ $i_089 = $inc242;
+ label = 36;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $70 = HEAP32[$end >> 2] | 0;
+ $71 = HEAP32[$start >> 2] | 0;
+ $sub247 = $70 + 4 | 0;
+ $add248 = $sub247 - $71 | 0;
+ $size = $call + 4 | 0;
+ HEAP32[$size >> 2] = $add248;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _arrow_clip($fe, $hn, $ps, $startp, $endp, $spl, $info) {
+ $fe = $fe | 0;
+ $hn = $hn | 0;
+ $ps = $ps | 0;
+ $startp = $startp | 0;
+ $endp = $endp | 0;
+ $spl = $spl | 0;
+ $info = $info | 0;
+ var $sflag = 0, $eflag = 0, $e_0 = 0, $to_orig = 0, $0 = 0, $tobool = 0, $ignoreSwap = 0, $1 = 0, $tobool3 = 0, $swapEnds = 0, $2 = 0, $call = 0, $conv = 0, $j_0 = 0, $splineMerge = 0, $3 = 0, $call4 = 0, $tobool5 = 0, $4 = 0, $tail = 0, $5 = 0, $call9 = 0, $tobool10 = 0, $tobool13 = 0, $6 = 0, $7 = 0, $isOrtho = 0, $8 = 0, $tobool16 = 0, $9 = 0, $tobool18 = 0, $10 = 0, $tobool19 = 0, $11 = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $tobool23 = 0, $16 = 0, $17 = 0, $call25 = 0, $18 = 0, $tobool27 = 0, $19 = 0, $20 = 0, $call29 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sflag = __stackBase__ | 0;
+ $eflag = __stackBase__ + 8 | 0;
+ $e_0 = $fe;
+ label = 3;
+ break;
+ case 3:
+ $to_orig = $e_0 + 132 | 0;
+ $0 = HEAP32[$to_orig >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $e_0 = $0;
+ label = 3;
+ break;
+ }
+ case 4:
+ $ignoreSwap = $info + 8 | 0;
+ $1 = HEAP8[$ignoreSwap] | 0;
+ $tobool3 = $1 << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ $j_0 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $swapEnds = $info | 0;
+ $2 = HEAP32[$swapEnds >> 2] | 0;
+ $call = FUNCTION_TABLE_ii[$2 & 1023]($e_0) | 0;
+ $conv = $call & 255;
+ $j_0 = $conv;
+ label = 6;
+ break;
+ case 6:
+ _arrow_flags($e_0, $sflag, $eflag);
+ $splineMerge = $info + 4 | 0;
+ $3 = HEAP32[$splineMerge >> 2] | 0;
+ $call4 = FUNCTION_TABLE_ii[$3 & 1023]($hn) | 0;
+ $tobool5 = $call4 << 24 >> 24 == 0;
+ if ($tobool5) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ HEAP32[$eflag >> 2] = 0;
+ label = 8;
+ break;
+ case 8:
+ $4 = HEAP32[$splineMerge >> 2] | 0;
+ $tail = $fe + 16 | 0;
+ $5 = HEAP32[$tail >> 2] | 0;
+ $call9 = FUNCTION_TABLE_ii[$4 & 1023]($5) | 0;
+ $tobool10 = $call9 << 24 >> 24 == 0;
+ if ($tobool10) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ HEAP32[$sflag >> 2] = 0;
+ label = 10;
+ break;
+ case 10:
+ $tobool13 = ($j_0 | 0) == 0;
+ if ($tobool13) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $6 = HEAP32[$sflag >> 2] | 0;
+ $7 = HEAP32[$eflag >> 2] | 0;
+ HEAP32[$sflag >> 2] = $7;
+ HEAP32[$eflag >> 2] = $6;
+ label = 12;
+ break;
+ case 12:
+ $isOrtho = $info + 9 | 0;
+ $8 = HEAP8[$isOrtho] | 0;
+ $tobool16 = $8 << 24 >> 24 == 0;
+ if ($tobool16) {
+ label = 16;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $9 = HEAP32[$eflag >> 2] | 0;
+ $tobool18 = ($9 | 0) == 0;
+ if ($tobool18) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $10 = HEAP32[$sflag >> 2] | 0;
+ $tobool19 = ($10 | 0) == 0;
+ if ($tobool19) {
+ label = 20;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $11 = HEAP32[$startp >> 2] | 0;
+ $12 = HEAP32[$endp >> 2] | 0;
+ $13 = HEAP32[$sflag >> 2] | 0;
+ $14 = HEAP32[$eflag >> 2] | 0;
+ _arrowOrthoClip($e_0, $ps, $11, $12, $spl, $13, $14);
+ label = 20;
+ break;
+ case 16:
+ $15 = HEAP32[$sflag >> 2] | 0;
+ $tobool23 = ($15 | 0) == 0;
+ if ($tobool23) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $16 = HEAP32[$startp >> 2] | 0;
+ $17 = HEAP32[$endp >> 2] | 0;
+ $call25 = _arrowStartClip($e_0, $ps, $16, $17, $spl, $15) | 0;
+ HEAP32[$startp >> 2] = $call25;
+ label = 18;
+ break;
+ case 18:
+ $18 = HEAP32[$eflag >> 2] | 0;
+ $tobool27 = ($18 | 0) == 0;
+ if ($tobool27) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $19 = HEAP32[$startp >> 2] | 0;
+ $20 = HEAP32[$endp >> 2] | 0;
+ $call29 = _arrowEndClip($e_0, $ps, $19, $20, $spl, $18) | 0;
+ HEAP32[$endp >> 2] = $call29;
+ label = 20;
+ break;
+ case 20:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _add_box($P, $b) {
+ $P = $P | 0;
+ $b = $b | 0;
+ var $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $cmp = 0, $y = 0, $2 = 0.0, $y4 = 0, $3 = 0.0, $cmp5 = 0, $nbox = 0, $4 = 0, $inc = 0, $boxes = 0, $5 = 0, $arrayidx = 0, $6 = 0, $7 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $b | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $b + 16 | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $cmp = $0 < $1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $y = $b + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $y4 = $b + 24 | 0;
+ $3 = +HEAPF64[$y4 >> 3];
+ $cmp5 = $2 < $3;
+ if ($cmp5) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $nbox = $P + 80 | 0;
+ $4 = HEAP32[$nbox >> 2] | 0;
+ $inc = $4 + 1 | 0;
+ HEAP32[$nbox >> 2] = $inc;
+ $boxes = $P + 84 | 0;
+ $5 = HEAP32[$boxes >> 2] | 0;
+ $arrayidx = $5 + ($4 << 5) | 0;
+ $6 = $arrayidx;
+ $7 = $b;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ HEAP32[$6 + 16 >> 2] = HEAP32[$7 + 16 >> 2] | 0;
+ HEAP32[$6 + 20 >> 2] = HEAP32[$7 + 20 >> 2] | 0;
+ HEAP32[$6 + 24 >> 2] = HEAP32[$7 + 24 >> 2] | 0;
+ HEAP32[$6 + 28 >> 2] = HEAP32[$7 + 28 >> 2] | 0;
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _add_pointf804($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $add4 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $add4 = +HEAPF64[$p + 8 >> 3] + +HEAPF64[$q + 8 >> 3];
+ HEAPF64[$agg_result >> 3] = +HEAPF64[$p >> 3] + +HEAPF64[$q >> 3];
+ HEAPF64[$agg_result + 8 >> 3] = $add4;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _conc_slope($n) {
+ $n = $n | 0;
+ var $list = 0, $0 = 0, $1 = 0, $tobool22 = 0, $2 = 0, $phitmp = 0.0, $s_in_0_lcssa = 0.0, $cnt_in_0_lcssa = 0.0, $list4 = 0, $3 = 0, $4 = 0, $tobool617 = 0, $5 = 0, $6 = 0, $s_in_024 = 0.0, $cnt_in_023 = 0, $tail = 0, $7 = 0, $x = 0, $8 = 0.0, $add = 0.0, $inc = 0, $arrayidx = 0, $9 = 0, $tobool = 0, $10 = 0, $s_out_019 = 0.0, $cnt_out_018 = 0, $head = 0, $11 = 0, $x10 = 0, $12 = 0.0, $add11 = 0.0, $inc13 = 0, $arrayidx5 = 0, $13 = 0, $tobool6 = 0, $phitmp28 = 0.0, $_lcssa = 0, $s_out_0_lcssa = 0.0, $cnt_out_0_lcssa = 0.0, $x17 = 0, $14 = 0.0, $div = 0.0, $sub = 0.0, $y = 0, $15 = 0.0, $16 = 0, $17 = 0, $tail25 = 0, $18 = 0, $y28 = 0, $19 = 0.0, $sub29 = 0.0, $call = 0.0, $div34 = 0.0, $sub38 = 0.0, $20 = 0, $head44 = 0, $21 = 0, $y47 = 0, $22 = 0.0, $sub51 = 0.0, $call55 = 0.0, $add56 = 0.0, $div57 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $n + 176 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool22 = ($1 | 0) == 0;
+ if ($tobool22) {
+ $cnt_in_0_lcssa = 0.0;
+ $s_in_0_lcssa = 0.0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$list >> 2] | 0;
+ $cnt_in_023 = 0;
+ $s_in_024 = 0.0;
+ $6 = $1;
+ label = 7;
+ break;
+ case 4:
+ $phitmp = +($inc | 0);
+ $cnt_in_0_lcssa = $phitmp;
+ $s_in_0_lcssa = $add;
+ label = 5;
+ break;
+ case 5:
+ $list4 = $n + 184 | 0;
+ $3 = HEAP32[$list4 >> 2] | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $tobool617 = ($4 | 0) == 0;
+ if ($tobool617) {
+ $cnt_out_0_lcssa = 0.0;
+ $s_out_0_lcssa = 0.0;
+ $_lcssa = $3;
+ label = 10;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $5 = HEAP32[$list4 >> 2] | 0;
+ $cnt_out_018 = 0;
+ $s_out_019 = 0.0;
+ $10 = $4;
+ label = 8;
+ break;
+ case 7:
+ $tail = $6 + 16 | 0;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $x = $7 + 32 | 0;
+ $8 = +HEAPF64[$x >> 3];
+ $add = $s_in_024 + $8;
+ $inc = $cnt_in_023 + 1 | 0;
+ $arrayidx = $2 + ($inc << 2) | 0;
+ $9 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($9 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $cnt_in_023 = $inc;
+ $s_in_024 = $add;
+ $6 = $9;
+ label = 7;
+ break;
+ }
+ case 8:
+ $head = $10 + 12 | 0;
+ $11 = HEAP32[$head >> 2] | 0;
+ $x10 = $11 + 32 | 0;
+ $12 = +HEAPF64[$x10 >> 3];
+ $add11 = $s_out_019 + $12;
+ $inc13 = $cnt_out_018 + 1 | 0;
+ $arrayidx5 = $5 + ($inc13 << 2) | 0;
+ $13 = HEAP32[$arrayidx5 >> 2] | 0;
+ $tobool6 = ($13 | 0) == 0;
+ if ($tobool6) {
+ label = 9;
+ break;
+ } else {
+ $cnt_out_018 = $inc13;
+ $s_out_019 = $add11;
+ $10 = $13;
+ label = 8;
+ break;
+ }
+ case 9:
+ $phitmp28 = +($inc13 | 0);
+ $cnt_out_0_lcssa = $phitmp28;
+ $s_out_0_lcssa = $add11;
+ $_lcssa = $5;
+ label = 10;
+ break;
+ case 10:
+ $x17 = $n + 32 | 0;
+ $14 = +HEAPF64[$x17 >> 3];
+ $div = $s_in_0_lcssa / $cnt_in_0_lcssa;
+ $sub = $14 - $div;
+ $y = $n + 40 | 0;
+ $15 = +HEAPF64[$y >> 3];
+ $16 = HEAP32[$list >> 2] | 0;
+ $17 = HEAP32[$16 >> 2] | 0;
+ $tail25 = $17 + 16 | 0;
+ $18 = HEAP32[$tail25 >> 2] | 0;
+ $y28 = $18 + 40 | 0;
+ $19 = +HEAPF64[$y28 >> 3];
+ $sub29 = $15 - $19;
+ $call = +Math_atan2(+$sub29, +$sub);
+ $div34 = $s_out_0_lcssa / $cnt_out_0_lcssa;
+ $sub38 = $div34 - $14;
+ $20 = HEAP32[$_lcssa >> 2] | 0;
+ $head44 = $20 + 12 | 0;
+ $21 = HEAP32[$head44 >> 2] | 0;
+ $y47 = $21 + 40 | 0;
+ $22 = +HEAPF64[$y47 >> 3];
+ $sub51 = $22 - $15;
+ $call55 = +Math_atan2(+$sub51, +$sub38);
+ $add56 = $call + $call55;
+ $div57 = $add56 * .5;
+ return +$div57;
+ }
+ return 0.0;
+}
+function _beginpath($P, $e, $et, $endp, $merge) {
+ $P = $P | 0;
+ $e = $e | 0;
+ $et = $et | 0;
+ $endp = $endp | 0;
+ $merge = $merge | 0;
+ var $tmp = 0, $tmp17 = 0, $tail = 0, $0 = 0, $tail_port = 0, $dyna = 0, $1 = 0, $tobool = 0, $head = 0, $2 = 0, $3 = 0, $4 = 0, $shape = 0, $5 = 0, $tobool7 = 0, $fns = 0, $6 = 0, $pboxfn11 = 0, $7 = 0, $pboxfn_0 = 0, $coord = 0, $p16 = 0, $8 = 0, $9 = 0, $tobool18 = 0, $10 = 0, $call = 0.0, $theta = 0, $constrained = 0, $constrained26 = 0, $11 = 0, $tobool27 = 0, $theta31 = 0, $12 = 0.0, $theta33 = 0, $constrained35 = 0, $constrained38 = 0, $nbox = 0, $13 = 0, $data = 0, $np = 0, $14 = 0, $cmp = 0, $node_type = 0, $15 = 0, $cmp44 = 0, $side49 = 0, $16 = 0, $conv50 = 0, $tobool51 = 0, $b_sroa_0_0__idx62 = 0, $b_sroa_0_0_copyload63 = 0.0, $b_sroa_1_8__idx74 = 0, $b_sroa_1_8_copyload75 = 0.0, $b_sroa_2_16__idx85 = 0, $b_sroa_2_16_copyload86 = 0.0, $b_sroa_3_24__idx98 = 0, $b_sroa_3_24_copyload99 = 0.0, $and = 0, $tobool56 = 0, $sidemask = 0, $x = 0, $17 = 0.0, $x62 = 0, $18 = 0.0, $cmp63 = 0, $sub = 0.0, $y = 0, $19 = 0.0, $y78 = 0, $20 = 0.0, $ht = 0, $21 = 0.0, $cmp80 = 0, $add = 0.0, $sub87 = 0.0, $add_sink = 0.0, $conv84 = 0, $add89 = 0, $div = 0, $conv90 = 0.0, $add91 = 0.0, $graph = 0, $22 = 0, $ranksep = 0, $23 = 0, $div93 = 0, $conv94 = 0.0, $add95 = 0.0, $24 = 0.0, $lw = 0, $25 = 0.0, $sub102 = 0.0, $26 = 0.0, $27 = 0.0, $cmp115 = 0, $add120 = 0.0, $sub125 = 0.0, $add120_sink = 0.0, $conv121 = 0, $add129 = 0, $div130 = 0, $conv131 = 0.0, $sub132 = 0.0, $b0_sroa_0_0__idx101 = 0, $b0_sroa_1_8__idx104 = 0, $b0_sroa_2_16__idx108 = 0, $b0_sroa_3_24__idx111 = 0, $b_sroa_0_0__idx60 = 0, $b_sroa_1_8__idx72 = 0, $b_sroa_2_16__idx83 = 0, $b_sroa_3_24__idx96 = 0, $y147 = 0, $28 = 0.0, $add152 = 0.0, $y157 = 0, $29 = 0.0, $ht159 = 0, $30 = 0.0, $cmp160 = 0, $add165 = 0.0, $sub170 = 0.0, $add165_sink = 0.0, $conv166 = 0, $add174 = 0, $div175 = 0, $conv176 = 0.0, $add177 = 0.0, $graph178 = 0, $31 = 0, $ranksep180 = 0, $32 = 0, $div181 = 0, $conv182 = 0.0, $add183 = 0.0, $33 = 0.0, $rw = 0, $34 = 0.0, $add190 = 0.0, $add191 = 0.0, $35 = 0.0, $36 = 0.0, $cmp203 = 0, $add208 = 0.0, $sub213 = 0.0, $add208_sink = 0.0, $conv209 = 0, $add217 = 0, $div218 = 0, $conv219 = 0.0, $sub220 = 0.0, $b0_sroa_0_0__idx = 0, $b0_sroa_1_8__idx103 = 0, $b0_sroa_2_16__idx107 = 0, $b0_sroa_3_24__idx110 = 0, $b_sroa_0_0__idx58 = 0, $b_sroa_1_8__idx70 = 0, $b_sroa_2_16__idx81 = 0, $b_sroa_3_24__idx94 = 0, $y233 = 0, $37 = 0.0, $add234 = 0.0, $boxn = 0, $and236 = 0, $tobool237 = 0, $sidemask239 = 0, $y244 = 0, $38 = 0.0, $cmp245 = 0, $b_sroa_3_24_copyload99_ = 0.0, $b_sroa_0_0__idx56 = 0, $b_sroa_1_8__idx68 = 0, $b_sroa_2_16__idx79 = 0, $b_sroa_3_24__idx92 = 0, $boxn260 = 0, $39 = 0.0, $sub264 = 0.0, $and266 = 0, $tobool267 = 0, $sidemask269 = 0, $x272 = 0, $40 = 0.0, $y277 = 0, $41 = 0.0, $ht279 = 0, $42 = 0.0, $cmp280 = 0, $add285 = 0.0, $sub290 = 0.0, $add285_sink = 0.0, $conv286 = 0, $add294 = 0, $div295 = 0, $conv296 = 0.0, $sub297 = 0.0, $y302 = 0, $43 = 0.0, $b_sroa_0_0__idx54 = 0, $b_sroa_1_8__idx66 = 0, $b_sroa_2_16__idx77 = 0, $b_sroa_3_24__idx90 = 0, $boxn307 = 0, $44 = 0.0, $sub311 = 0.0, $x316 = 0, $45 = 0.0, $y321 = 0, $46 = 0.0, $ht323 = 0, $47 = 0.0, $cmp324 = 0, $add329 = 0.0, $sub334 = 0.0, $add329_sink = 0.0, $conv330 = 0, $add338 = 0, $div339 = 0, $conv340 = 0.0, $sub341 = 0.0, $y346 = 0, $48 = 0.0, $b_sroa_0_0__idx = 0, $b_sroa_1_8__idx65 = 0, $b_sroa_2_16__idx76 = 0, $b_sroa_3_24__idx89 = 0, $boxn351 = 0, $49 = 0.0, $add355 = 0.0, $edge_type267 = 0, $50 = 0, $cmp361268 = 0, $orig_0269 = 0, $to_orig = 0, $51 = 0, $edge_type = 0, $52 = 0, $cmp361 = 0, $orig_0_lcssa = 0, $tail364 = 0, $53 = 0, $cmp365 = 0, $clip = 0, $clip372 = 0, $cmp375 = 0, $side380 = 0, $54 = 0, $conv381 = 0, $tobool382 = 0, $b387_sroa_0_0__idx12 = 0, $b387_sroa_0_0_copyload13 = 0.0, $b387_sroa_1_8__idx23 = 0, $b387_sroa_1_8_copyload24 = 0.0, $b387_sroa_2_16__idx35 = 0, $b387_sroa_2_16_copyload36 = 0.0, $b387_sroa_3_24__idx47 = 0, $b387_sroa_3_24_copyload48 = 0.0, $and391 = 0, $tobool392 = 0, $y398 = 0, $55 = 0.0, $cmp399 = 0, $b387_sroa_1_8_copyload24_ = 0.0, $b387_sroa_0_0__idx10 = 0, $b387_sroa_1_8__idx21 = 0, $b387_sroa_2_16__idx33 = 0, $b387_sroa_3_24__idx45 = 0, $boxn414 = 0, $and416 = 0, $tobool417 = 0, $sidemask419 = 0, $56 = 0, $cmp420 = 0, $y425 = 0, $57 = 0.0, $ht427 = 0, $58 = 0.0, $cmp428 = 0, $add433 = 0.0, $sub438 = 0.0, $add433_sink = 0.0, $conv434 = 0, $add442 = 0, $div443 = 0, $conv444 = 0.0, $sub445 = 0.0, $add450 = 0.0, $x455 = 0, $59 = 0.0, $graph460 = 0, $60 = 0, $ranksep462 = 0, $61 = 0, $div463 = 0, $conv464 = 0.0, $sub465 = 0.0, $x470 = 0, $62 = 0.0, $rw472 = 0, $63 = 0.0, $add473 = 0.0, $add474 = 0.0, $64 = 0.0, $65 = 0.0, $cmp486 = 0, $add491 = 0.0, $sub496 = 0.0, $add491_sink = 0.0, $conv492 = 0, $add500 = 0, $div501 = 0, $conv502 = 0.0, $add503 = 0.0, $b0385_sroa_0_0__idx = 0, $b0385_sroa_1_8__idx50 = 0, $b0385_sroa_2_16__idx51 = 0, $b0385_sroa_3_24__idx52 = 0, $b387_sroa_0_0__idx8 = 0, $b387_sroa_1_8__idx19 = 0, $b387_sroa_2_16__idx31 = 0, $b387_sroa_3_24__idx43 = 0, $boxn513 = 0, $y519 = 0, $66 = 0.0, $cmp520 = 0, $b387_sroa_3_24_copyload48_ = 0.0, $b387_sroa_0_0__idx6 = 0, $b387_sroa_1_8__idx17 = 0, $b387_sroa_2_16__idx29 = 0, $b387_sroa_3_24__idx41 = 0, $boxn535 = 0, $and538 = 0, $tobool539 = 0, $x543 = 0, $67 = 0.0, $add544 = 0.0, $sidemask547 = 0, $68 = 0, $cmp548 = 0, $y553 = 0, $69 = 0.0, $ht555 = 0, $70 = 0.0, $cmp556 = 0, $add561 = 0.0, $sub566 = 0.0, $add561_sink = 0.0, $conv562 = 0, $add570 = 0, $div571 = 0, $conv572 = 0.0, $add573 = 0.0, $y578 = 0, $71 = 0.0, $sub579 = 0.0, $add593 = 0.0, $sub598 = 0.0, $add593_sink = 0.0, $conv594 = 0, $add602 = 0, $div603 = 0, $conv604 = 0.0, $sub605 = 0.0, $y610 = 0, $72 = 0.0, $add611 = 0.0, $b387_sroa_3_0 = 0.0, $b387_sroa_1_0 = 0.0, $b387_sroa_0_0__idx4 = 0, $b387_sroa_1_8__idx15 = 0, $b387_sroa_2_16__idx27 = 0, $b387_sroa_3_24__idx39 = 0, $boxn617 = 0, $sidemask624 = 0, $73 = 0, $cmp625 = 0, $y630 = 0, $74 = 0.0, $ht632 = 0, $75 = 0.0, $cmp633 = 0, $add638 = 0.0, $sub643 = 0.0, $add638_sink = 0.0, $conv639 = 0, $add647 = 0, $div648 = 0, $conv649 = 0.0, $add650 = 0.0, $y655 = 0, $76 = 0.0, $add669 = 0.0, $sub674 = 0.0, $add669_sink = 0.0, $conv670 = 0, $add678 = 0, $div679 = 0, $conv680 = 0.0, $sub681 = 0.0, $y686 = 0, $77 = 0.0, $add687 = 0.0, $b387_sroa_3_1 = 0.0, $b387_sroa_1_1 = 0.0, $b387_sroa_0_0__idx = 0, $b387_sroa_1_8__idx14 = 0, $b387_sroa_2_16__idx26 = 0, $b387_sroa_3_24__idx38 = 0, $boxn693 = 0, $edge_type699264 = 0, $78 = 0, $cmp701265 = 0, $orig390_0266 = 0, $to_orig706 = 0, $79 = 0, $edge_type699 = 0, $80 = 0, $cmp701 = 0, $orig390_0_lcssa = 0, $tail708 = 0, $81 = 0, $cmp709 = 0, $clip714 = 0, $clip718 = 0, $sidemask720 = 0, $sidemask726 = 0, $82 = 0, $side_0 = 0, $tobool728 = 0, $arrayidx733 = 0, $boxn734 = 0, $call735 = 0, $tobool736 = 0, $sidemask738 = 0, $arrayidx741 = 0, $83 = 0, $84 = 0, $boxn743 = 0, $sidemask745 = 0, $85 = 0, $cmp746 = 0, $y751 = 0, $86 = 0.0, $y755 = 0, $y763 = 0, $y768 = 0, $87 = 0.0, $y772 = 0, $sidemask773 = 0, $88 = 0.0, $sub777 = 0.0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 56 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmp17 = __stackBase__ + 40 | 0;
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $tail_port = $e + 32 | 0;
+ $dyna = $e + 63 | 0;
+ $1 = HEAP8[$dyna] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $e + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ _resolvePort($tmp, $0, $2, $tail_port);
+ $3 = $tail_port;
+ $4 = $tmp;
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ HEAP32[$3 + 16 >> 2] = HEAP32[$4 + 16 >> 2] | 0;
+ HEAP32[$3 + 20 >> 2] = HEAP32[$4 + 20 >> 2] | 0;
+ HEAP32[$3 + 24 >> 2] = HEAP32[$4 + 24 >> 2] | 0;
+ HEAP32[$3 + 28 >> 2] = HEAP32[$4 + 28 >> 2] | 0;
+ HEAP32[$3 + 32 >> 2] = HEAP32[$4 + 32 >> 2] | 0;
+ HEAP32[$3 + 36 >> 2] = HEAP32[$4 + 36 >> 2] | 0;
+ label = 4;
+ break;
+ case 4:
+ $shape = $0 + 24 | 0;
+ $5 = HEAP32[$shape >> 2] | 0;
+ $tobool7 = ($5 | 0) == 0;
+ if ($tobool7) {
+ $pboxfn_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $fns = $5 + 4 | 0;
+ $6 = HEAP32[$fns >> 2] | 0;
+ $pboxfn11 = $6 + 16 | 0;
+ $7 = HEAP32[$pboxfn11 >> 2] | 0;
+ $pboxfn_0 = $7;
+ label = 6;
+ break;
+ case 6:
+ $coord = $0 + 32 | 0;
+ $p16 = $tail_port | 0;
+ _add_pointf804($tmp17, $coord, $p16);
+ $8 = $P;
+ $9 = $tmp17;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $tobool18 = $merge << 24 >> 24 == 0;
+ if ($tobool18) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $10 = HEAP32[$tail >> 2] | 0;
+ $call = +_conc_slope($10);
+ $theta = $P + 16 | 0;
+ HEAPF64[$theta >> 3] = $call;
+ $constrained = $P + 29 | 0;
+ HEAP8[$constrained] = 1;
+ label = 11;
+ break;
+ case 8:
+ $constrained26 = $e + 61 | 0;
+ $11 = HEAP8[$constrained26] | 0;
+ $tobool27 = $11 << 24 >> 24 == 0;
+ if ($tobool27) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $theta31 = $e + 48 | 0;
+ $12 = +HEAPF64[$theta31 >> 3];
+ $theta33 = $P + 16 | 0;
+ HEAPF64[$theta33 >> 3] = $12;
+ $constrained35 = $P + 29 | 0;
+ HEAP8[$constrained35] = 1;
+ label = 11;
+ break;
+ case 10:
+ $constrained38 = $P + 29 | 0;
+ HEAP8[$constrained38] = 0;
+ label = 11;
+ break;
+ case 11:
+ $nbox = $P + 80 | 0;
+ HEAP32[$nbox >> 2] = 0;
+ $13 = $e | 0;
+ $data = $P + 88 | 0;
+ HEAP32[$data >> 2] = $13;
+ $np = $endp + 32 | 0;
+ $14 = $np;
+ HEAP32[$14 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $cmp = ($et | 0) == 1;
+ if ($cmp) {
+ label = 12;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 12:
+ $node_type = $0 + 162 | 0;
+ $15 = HEAP8[$node_type] | 0;
+ $cmp44 = $15 << 24 >> 24 == 0;
+ if ($cmp44) {
+ label = 13;
+ break;
+ } else {
+ $side_0 = 1;
+ label = 90;
+ break;
+ }
+ case 13:
+ $side49 = $e + 65 | 0;
+ $16 = HEAP8[$side49] | 0;
+ $conv50 = $16 & 255;
+ $tobool51 = $16 << 24 >> 24 == 0;
+ if ($tobool51) {
+ label = 47;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $b_sroa_0_0__idx62 = $endp | 0;
+ $b_sroa_0_0_copyload63 = +HEAPF64[$b_sroa_0_0__idx62 >> 3];
+ $b_sroa_1_8__idx74 = $endp + 8 | 0;
+ $b_sroa_1_8_copyload75 = +HEAPF64[$b_sroa_1_8__idx74 >> 3];
+ $b_sroa_2_16__idx85 = $endp + 16 | 0;
+ $b_sroa_2_16_copyload86 = +HEAPF64[$b_sroa_2_16__idx85 >> 3];
+ $b_sroa_3_24__idx98 = $endp + 24 | 0;
+ $b_sroa_3_24_copyload99 = +HEAPF64[$b_sroa_3_24__idx98 >> 3];
+ $and = $conv50 & 4;
+ $tobool56 = ($and | 0) == 0;
+ if ($tobool56) {
+ label = 31;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $sidemask = $endp + 48 | 0;
+ HEAP32[$sidemask >> 2] = 4;
+ $x = $P | 0;
+ $17 = +HEAPF64[$x >> 3];
+ $x62 = $coord | 0;
+ $18 = +HEAPF64[$x62 >> 3];
+ $cmp63 = $17 < $18;
+ if ($cmp63) {
+ label = 16;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 16:
+ $sub = $b_sroa_0_0_copyload63 + -1.0;
+ $y = $P + 8 | 0;
+ $19 = +HEAPF64[$y >> 3];
+ $y78 = $0 + 40 | 0;
+ $20 = +HEAPF64[$y78 >> 3];
+ $ht = $0 + 96 | 0;
+ $21 = +HEAPF64[$ht >> 3];
+ $cmp80 = $21 < 0.0;
+ if ($cmp80) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $add = $21 + .5;
+ $add_sink = $add;
+ label = 19;
+ break;
+ case 18:
+ $sub87 = $21 + -.5;
+ $add_sink = $sub87;
+ label = 19;
+ break;
+ case 19:
+ $conv84 = ~~$add_sink;
+ $add89 = $conv84 + 1 | 0;
+ $div = ($add89 | 0) / 2 & -1;
+ $conv90 = +($div | 0);
+ $add91 = $20 + $conv90;
+ $graph = $0 + 20 | 0;
+ $22 = HEAP32[$graph >> 2] | 0;
+ $ranksep = $22 + 264 | 0;
+ $23 = HEAP32[$ranksep >> 2] | 0;
+ $div93 = ($23 | 0) / 2 & -1;
+ $conv94 = +($div93 | 0);
+ $add95 = $add91 + $conv94;
+ $24 = +HEAPF64[$x62 >> 3];
+ $lw = $0 + 104 | 0;
+ $25 = +HEAPF64[$lw >> 3];
+ $sub102 = $24 - $25;
+ $26 = +HEAPF64[$y78 >> 3];
+ $27 = +HEAPF64[$ht >> 3];
+ $cmp115 = $27 < 0.0;
+ if ($cmp115) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $add120 = $27 + .5;
+ $add120_sink = $add120;
+ label = 22;
+ break;
+ case 21:
+ $sub125 = $27 + -.5;
+ $add120_sink = $sub125;
+ label = 22;
+ break;
+ case 22:
+ $conv121 = ~~$add120_sink;
+ $add129 = $conv121 + 1 | 0;
+ $div130 = ($add129 | 0) / 2 & -1;
+ $conv131 = +($div130 | 0);
+ $sub132 = $26 - $conv131;
+ $b0_sroa_0_0__idx101 = $endp + 56 | 0;
+ HEAPF64[$b0_sroa_0_0__idx101 >> 3] = $sub;
+ $b0_sroa_1_8__idx104 = $endp + 64 | 0;
+ HEAPF64[$b0_sroa_1_8__idx104 >> 3] = $19;
+ $b0_sroa_2_16__idx108 = $endp + 72 | 0;
+ HEAPF64[$b0_sroa_2_16__idx108 >> 3] = $b_sroa_2_16_copyload86;
+ $b0_sroa_3_24__idx111 = $endp + 80 | 0;
+ HEAPF64[$b0_sroa_3_24__idx111 >> 3] = $add95;
+ $b_sroa_0_0__idx60 = $endp + 88 | 0;
+ HEAPF64[$b_sroa_0_0__idx60 >> 3] = $sub;
+ $b_sroa_1_8__idx72 = $endp + 96 | 0;
+ HEAPF64[$b_sroa_1_8__idx72 >> 3] = $sub132;
+ $b_sroa_2_16__idx83 = $endp + 104 | 0;
+ HEAPF64[$b_sroa_2_16__idx83 >> 3] = $sub102;
+ $b_sroa_3_24__idx96 = $endp + 112 | 0;
+ HEAPF64[$b_sroa_3_24__idx96 >> 3] = $19;
+ label = 30;
+ break;
+ case 23:
+ $y147 = $P + 8 | 0;
+ $28 = +HEAPF64[$y147 >> 3];
+ $add152 = $b_sroa_2_16_copyload86 + 1.0;
+ $y157 = $0 + 40 | 0;
+ $29 = +HEAPF64[$y157 >> 3];
+ $ht159 = $0 + 96 | 0;
+ $30 = +HEAPF64[$ht159 >> 3];
+ $cmp160 = $30 < 0.0;
+ if ($cmp160) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $add165 = $30 + .5;
+ $add165_sink = $add165;
+ label = 26;
+ break;
+ case 25:
+ $sub170 = $30 + -.5;
+ $add165_sink = $sub170;
+ label = 26;
+ break;
+ case 26:
+ $conv166 = ~~$add165_sink;
+ $add174 = $conv166 + 1 | 0;
+ $div175 = ($add174 | 0) / 2 & -1;
+ $conv176 = +($div175 | 0);
+ $add177 = $29 + $conv176;
+ $graph178 = $0 + 20 | 0;
+ $31 = HEAP32[$graph178 >> 2] | 0;
+ $ranksep180 = $31 + 264 | 0;
+ $32 = HEAP32[$ranksep180 >> 2] | 0;
+ $div181 = ($32 | 0) / 2 & -1;
+ $conv182 = +($div181 | 0);
+ $add183 = $add177 + $conv182;
+ $33 = +HEAPF64[$x62 >> 3];
+ $rw = $0 + 112 | 0;
+ $34 = +HEAPF64[$rw >> 3];
+ $add190 = $33 + $34;
+ $add191 = $add190 + 0.0;
+ $35 = +HEAPF64[$y157 >> 3];
+ $36 = +HEAPF64[$ht159 >> 3];
+ $cmp203 = $36 < 0.0;
+ if ($cmp203) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $add208 = $36 + .5;
+ $add208_sink = $add208;
+ label = 29;
+ break;
+ case 28:
+ $sub213 = $36 + -.5;
+ $add208_sink = $sub213;
+ label = 29;
+ break;
+ case 29:
+ $conv209 = ~~$add208_sink;
+ $add217 = $conv209 + 1 | 0;
+ $div218 = ($add217 | 0) / 2 & -1;
+ $conv219 = +($div218 | 0);
+ $sub220 = $35 - $conv219;
+ $b0_sroa_0_0__idx = $endp + 56 | 0;
+ HEAPF64[$b0_sroa_0_0__idx >> 3] = $b_sroa_0_0_copyload63;
+ $b0_sroa_1_8__idx103 = $endp + 64 | 0;
+ HEAPF64[$b0_sroa_1_8__idx103 >> 3] = $28;
+ $b0_sroa_2_16__idx107 = $endp + 72 | 0;
+ HEAPF64[$b0_sroa_2_16__idx107 >> 3] = $add152;
+ $b0_sroa_3_24__idx110 = $endp + 80 | 0;
+ HEAPF64[$b0_sroa_3_24__idx110 >> 3] = $add183;
+ $b_sroa_0_0__idx58 = $endp + 88 | 0;
+ HEAPF64[$b_sroa_0_0__idx58 >> 3] = $add191;
+ $b_sroa_1_8__idx70 = $endp + 96 | 0;
+ HEAPF64[$b_sroa_1_8__idx70 >> 3] = $sub220;
+ $b_sroa_2_16__idx81 = $endp + 104 | 0;
+ HEAPF64[$b_sroa_2_16__idx81 >> 3] = $add152;
+ $b_sroa_3_24__idx94 = $endp + 112 | 0;
+ HEAPF64[$b_sroa_3_24__idx94 >> 3] = $28;
+ label = 30;
+ break;
+ case 30:
+ $y233 = $P + 8 | 0;
+ $37 = +HEAPF64[$y233 >> 3];
+ $add234 = $37 + 1.0;
+ HEAPF64[$y233 >> 3] = $add234;
+ $boxn = $endp + 52 | 0;
+ HEAP32[$boxn >> 2] = 2;
+ label = 42;
+ break;
+ case 31:
+ $and236 = $conv50 & 1;
+ $tobool237 = ($and236 | 0) == 0;
+ if ($tobool237) {
+ label = 33;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $sidemask239 = $endp + 48 | 0;
+ HEAP32[$sidemask239 >> 2] = 1;
+ $y244 = $P + 8 | 0;
+ $38 = +HEAPF64[$y244 >> 3];
+ $cmp245 = $b_sroa_3_24_copyload99 > $38;
+ $b_sroa_3_24_copyload99_ = $cmp245 ? $b_sroa_3_24_copyload99 : $38;
+ $b_sroa_0_0__idx56 = $endp + 56 | 0;
+ HEAPF64[$b_sroa_0_0__idx56 >> 3] = $b_sroa_0_0_copyload63;
+ $b_sroa_1_8__idx68 = $endp + 64 | 0;
+ HEAPF64[$b_sroa_1_8__idx68 >> 3] = $b_sroa_1_8_copyload75;
+ $b_sroa_2_16__idx79 = $endp + 72 | 0;
+ HEAPF64[$b_sroa_2_16__idx79 >> 3] = $b_sroa_2_16_copyload86;
+ $b_sroa_3_24__idx92 = $endp + 80 | 0;
+ HEAPF64[$b_sroa_3_24__idx92 >> 3] = $b_sroa_3_24_copyload99_;
+ $boxn260 = $endp + 52 | 0;
+ HEAP32[$boxn260 >> 2] = 1;
+ $39 = +HEAPF64[$y244 >> 3];
+ $sub264 = $39 + -1.0;
+ HEAPF64[$y244 >> 3] = $sub264;
+ label = 42;
+ break;
+ case 33:
+ $and266 = $conv50 & 8;
+ $tobool267 = ($and266 | 0) == 0;
+ $sidemask269 = $endp + 48 | 0;
+ if ($tobool267) {
+ label = 38;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ HEAP32[$sidemask269 >> 2] = 8;
+ $x272 = $P | 0;
+ $40 = +HEAPF64[$x272 >> 3];
+ $y277 = $0 + 40 | 0;
+ $41 = +HEAPF64[$y277 >> 3];
+ $ht279 = $0 + 96 | 0;
+ $42 = +HEAPF64[$ht279 >> 3];
+ $cmp280 = $42 < 0.0;
+ if ($cmp280) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $add285 = $42 + .5;
+ $add285_sink = $add285;
+ label = 37;
+ break;
+ case 36:
+ $sub290 = $42 + -.5;
+ $add285_sink = $sub290;
+ label = 37;
+ break;
+ case 37:
+ $conv286 = ~~$add285_sink;
+ $add294 = $conv286 + 1 | 0;
+ $div295 = ($add294 | 0) / 2 & -1;
+ $conv296 = +($div295 | 0);
+ $sub297 = $41 - $conv296;
+ $y302 = $P + 8 | 0;
+ $43 = +HEAPF64[$y302 >> 3];
+ $b_sroa_0_0__idx54 = $endp + 56 | 0;
+ HEAPF64[$b_sroa_0_0__idx54 >> 3] = $b_sroa_0_0_copyload63;
+ $b_sroa_1_8__idx66 = $endp + 64 | 0;
+ HEAPF64[$b_sroa_1_8__idx66 >> 3] = $sub297;
+ $b_sroa_2_16__idx77 = $endp + 72 | 0;
+ HEAPF64[$b_sroa_2_16__idx77 >> 3] = $40;
+ $b_sroa_3_24__idx90 = $endp + 80 | 0;
+ HEAPF64[$b_sroa_3_24__idx90 >> 3] = $43;
+ $boxn307 = $endp + 52 | 0;
+ HEAP32[$boxn307 >> 2] = 1;
+ $44 = +HEAPF64[$x272 >> 3];
+ $sub311 = $44 + -1.0;
+ HEAPF64[$x272 >> 3] = $sub311;
+ label = 42;
+ break;
+ case 38:
+ HEAP32[$sidemask269 >> 2] = 2;
+ $x316 = $P | 0;
+ $45 = +HEAPF64[$x316 >> 3];
+ $y321 = $0 + 40 | 0;
+ $46 = +HEAPF64[$y321 >> 3];
+ $ht323 = $0 + 96 | 0;
+ $47 = +HEAPF64[$ht323 >> 3];
+ $cmp324 = $47 < 0.0;
+ if ($cmp324) {
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $add329 = $47 + .5;
+ $add329_sink = $add329;
+ label = 41;
+ break;
+ case 40:
+ $sub334 = $47 + -.5;
+ $add329_sink = $sub334;
+ label = 41;
+ break;
+ case 41:
+ $conv330 = ~~$add329_sink;
+ $add338 = $conv330 + 1 | 0;
+ $div339 = ($add338 | 0) / 2 & -1;
+ $conv340 = +($div339 | 0);
+ $sub341 = $46 - $conv340;
+ $y346 = $P + 8 | 0;
+ $48 = +HEAPF64[$y346 >> 3];
+ $b_sroa_0_0__idx = $endp + 56 | 0;
+ HEAPF64[$b_sroa_0_0__idx >> 3] = $45;
+ $b_sroa_1_8__idx65 = $endp + 64 | 0;
+ HEAPF64[$b_sroa_1_8__idx65 >> 3] = $sub341;
+ $b_sroa_2_16__idx76 = $endp + 72 | 0;
+ HEAPF64[$b_sroa_2_16__idx76 >> 3] = $b_sroa_2_16_copyload86;
+ $b_sroa_3_24__idx89 = $endp + 80 | 0;
+ HEAPF64[$b_sroa_3_24__idx89 >> 3] = $48;
+ $boxn351 = $endp + 52 | 0;
+ HEAP32[$boxn351 >> 2] = 1;
+ $49 = +HEAPF64[$x316 >> 3];
+ $add355 = $49 + 1.0;
+ HEAPF64[$x316 >> 3] = $add355;
+ label = 42;
+ break;
+ case 42:
+ $edge_type267 = $e + 128 | 0;
+ $50 = HEAP8[$edge_type267] | 0;
+ $cmp361268 = $50 << 24 >> 24 == 0;
+ if ($cmp361268) {
+ $orig_0_lcssa = $e;
+ label = 44;
+ break;
+ } else {
+ $orig_0269 = $e;
+ label = 43;
+ break;
+ }
+ case 43:
+ $to_orig = $orig_0269 + 132 | 0;
+ $51 = HEAP32[$to_orig >> 2] | 0;
+ $edge_type = $51 + 128 | 0;
+ $52 = HEAP8[$edge_type] | 0;
+ $cmp361 = $52 << 24 >> 24 == 0;
+ if ($cmp361) {
+ $orig_0_lcssa = $51;
+ label = 44;
+ break;
+ } else {
+ $orig_0269 = $51;
+ label = 43;
+ break;
+ }
+ case 44:
+ $tail364 = $orig_0_lcssa + 16 | 0;
+ $53 = HEAP32[$tail364 >> 2] | 0;
+ $cmp365 = ($0 | 0) == ($53 | 0);
+ if ($cmp365) {
+ label = 45;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 45:
+ $clip = $orig_0_lcssa + 62 | 0;
+ HEAP8[$clip] = 0;
+ label = 99;
+ break;
+ case 46:
+ $clip372 = $orig_0_lcssa + 102 | 0;
+ HEAP8[$clip372] = 0;
+ label = 99;
+ break;
+ case 47:
+ $cmp375 = ($et | 0) == 2;
+ if ($cmp375) {
+ label = 48;
+ break;
+ } else {
+ label = 88;
+ break;
+ }
+ case 48:
+ $side380 = $e + 65 | 0;
+ $54 = HEAP8[$side380] | 0;
+ $conv381 = $54 & 255;
+ $tobool382 = $54 << 24 >> 24 == 0;
+ if ($tobool382) {
+ label = 88;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $b387_sroa_0_0__idx12 = $endp | 0;
+ $b387_sroa_0_0_copyload13 = +HEAPF64[$b387_sroa_0_0__idx12 >> 3];
+ $b387_sroa_1_8__idx23 = $endp + 8 | 0;
+ $b387_sroa_1_8_copyload24 = +HEAPF64[$b387_sroa_1_8__idx23 >> 3];
+ $b387_sroa_2_16__idx35 = $endp + 16 | 0;
+ $b387_sroa_2_16_copyload36 = +HEAPF64[$b387_sroa_2_16__idx35 >> 3];
+ $b387_sroa_3_24__idx47 = $endp + 24 | 0;
+ $b387_sroa_3_24_copyload48 = +HEAPF64[$b387_sroa_3_24__idx47 >> 3];
+ $and391 = $conv381 & 4;
+ $tobool392 = ($and391 | 0) == 0;
+ if ($tobool392) {
+ label = 51;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $y398 = $P + 8 | 0;
+ $55 = +HEAPF64[$y398 >> 3];
+ $cmp399 = $b387_sroa_1_8_copyload24 < $55;
+ $b387_sroa_1_8_copyload24_ = $cmp399 ? $b387_sroa_1_8_copyload24 : $55;
+ $b387_sroa_0_0__idx10 = $endp + 56 | 0;
+ HEAPF64[$b387_sroa_0_0__idx10 >> 3] = $b387_sroa_0_0_copyload13;
+ $b387_sroa_1_8__idx21 = $endp + 64 | 0;
+ HEAPF64[$b387_sroa_1_8__idx21 >> 3] = $b387_sroa_1_8_copyload24_;
+ $b387_sroa_2_16__idx33 = $endp + 72 | 0;
+ HEAPF64[$b387_sroa_2_16__idx33 >> 3] = $b387_sroa_2_16_copyload36;
+ $b387_sroa_3_24__idx45 = $endp + 80 | 0;
+ HEAPF64[$b387_sroa_3_24__idx45 >> 3] = $b387_sroa_3_24_copyload48;
+ $boxn414 = $endp + 52 | 0;
+ HEAP32[$boxn414 >> 2] = 1;
+ label = 82;
+ break;
+ case 51:
+ $and416 = $conv381 & 1;
+ $tobool417 = ($and416 | 0) == 0;
+ if ($tobool417) {
+ label = 61;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $sidemask419 = $endp + 48 | 0;
+ $56 = HEAP32[$sidemask419 >> 2] | 0;
+ $cmp420 = ($56 | 0) == 4;
+ if ($cmp420) {
+ label = 53;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 53:
+ $y425 = $0 + 40 | 0;
+ $57 = +HEAPF64[$y425 >> 3];
+ $ht427 = $0 + 96 | 0;
+ $58 = +HEAPF64[$ht427 >> 3];
+ $cmp428 = $58 < 0.0;
+ if ($cmp428) {
+ label = 55;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 54:
+ $add433 = $58 + .5;
+ $add433_sink = $add433;
+ label = 56;
+ break;
+ case 55:
+ $sub438 = $58 + -.5;
+ $add433_sink = $sub438;
+ label = 56;
+ break;
+ case 56:
+ $conv434 = ~~$add433_sink;
+ $add442 = $conv434 + 1 | 0;
+ $div443 = ($add442 | 0) / 2 & -1;
+ $conv444 = +($div443 | 0);
+ $sub445 = $57 - $conv444;
+ $add450 = $b387_sroa_2_16_copyload36 + 1.0;
+ $x455 = $P | 0;
+ $59 = +HEAPF64[$x455 >> 3];
+ $graph460 = $0 + 20 | 0;
+ $60 = HEAP32[$graph460 >> 2] | 0;
+ $ranksep462 = $60 + 264 | 0;
+ $61 = HEAP32[$ranksep462 >> 2] | 0;
+ $div463 = ($61 | 0) / 2 & -1;
+ $conv464 = +($div463 | 0);
+ $sub465 = $sub445 - $conv464;
+ $x470 = $coord | 0;
+ $62 = +HEAPF64[$x470 >> 3];
+ $rw472 = $0 + 112 | 0;
+ $63 = +HEAPF64[$rw472 >> 3];
+ $add473 = $62 + $63;
+ $add474 = $add473 + 0.0;
+ $64 = +HEAPF64[$y425 >> 3];
+ $65 = +HEAPF64[$ht427 >> 3];
+ $cmp486 = $65 < 0.0;
+ if ($cmp486) {
+ label = 58;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $add491 = $65 + .5;
+ $add491_sink = $add491;
+ label = 59;
+ break;
+ case 58:
+ $sub496 = $65 + -.5;
+ $add491_sink = $sub496;
+ label = 59;
+ break;
+ case 59:
+ $conv492 = ~~$add491_sink;
+ $add500 = $conv492 + 1 | 0;
+ $div501 = ($add500 | 0) / 2 & -1;
+ $conv502 = +($div501 | 0);
+ $add503 = $64 + $conv502;
+ $b0385_sroa_0_0__idx = $endp + 56 | 0;
+ HEAPF64[$b0385_sroa_0_0__idx >> 3] = $59;
+ $b0385_sroa_1_8__idx50 = $endp + 64 | 0;
+ HEAPF64[$b0385_sroa_1_8__idx50 >> 3] = $sub465;
+ $b0385_sroa_2_16__idx51 = $endp + 72 | 0;
+ HEAPF64[$b0385_sroa_2_16__idx51 >> 3] = $add450;
+ $b0385_sroa_3_24__idx52 = $endp + 80 | 0;
+ HEAPF64[$b0385_sroa_3_24__idx52 >> 3] = $sub445;
+ $b387_sroa_0_0__idx8 = $endp + 88 | 0;
+ HEAPF64[$b387_sroa_0_0__idx8 >> 3] = $add474;
+ $b387_sroa_1_8__idx19 = $endp + 96 | 0;
+ HEAPF64[$b387_sroa_1_8__idx19 >> 3] = $sub445;
+ $b387_sroa_2_16__idx31 = $endp + 104 | 0;
+ HEAPF64[$b387_sroa_2_16__idx31 >> 3] = $add450;
+ $b387_sroa_3_24__idx43 = $endp + 112 | 0;
+ HEAPF64[$b387_sroa_3_24__idx43 >> 3] = $add503;
+ $boxn513 = $endp + 52 | 0;
+ HEAP32[$boxn513 >> 2] = 2;
+ label = 82;
+ break;
+ case 60:
+ $y519 = $P + 8 | 0;
+ $66 = +HEAPF64[$y519 >> 3];
+ $cmp520 = $b387_sroa_3_24_copyload48 > $66;
+ $b387_sroa_3_24_copyload48_ = $cmp520 ? $b387_sroa_3_24_copyload48 : $66;
+ $b387_sroa_0_0__idx6 = $endp + 56 | 0;
+ HEAPF64[$b387_sroa_0_0__idx6 >> 3] = $b387_sroa_0_0_copyload13;
+ $b387_sroa_1_8__idx17 = $endp + 64 | 0;
+ HEAPF64[$b387_sroa_1_8__idx17 >> 3] = $b387_sroa_1_8_copyload24;
+ $b387_sroa_2_16__idx29 = $endp + 72 | 0;
+ HEAPF64[$b387_sroa_2_16__idx29 >> 3] = $b387_sroa_2_16_copyload36;
+ $b387_sroa_3_24__idx41 = $endp + 80 | 0;
+ HEAPF64[$b387_sroa_3_24__idx41 >> 3] = $b387_sroa_3_24_copyload48_;
+ $boxn535 = $endp + 52 | 0;
+ HEAP32[$boxn535 >> 2] = 1;
+ label = 82;
+ break;
+ case 61:
+ $and538 = $conv381 & 8;
+ $tobool539 = ($and538 | 0) == 0;
+ $x543 = $P | 0;
+ $67 = +HEAPF64[$x543 >> 3];
+ if ($tobool539) {
+ label = 72;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 62:
+ $add544 = $67 + 1.0;
+ $sidemask547 = $endp + 48 | 0;
+ $68 = HEAP32[$sidemask547 >> 2] | 0;
+ $cmp548 = ($68 | 0) == 4;
+ $y553 = $0 + 40 | 0;
+ $69 = +HEAPF64[$y553 >> 3];
+ $ht555 = $0 + 96 | 0;
+ $70 = +HEAPF64[$ht555 >> 3];
+ $cmp556 = $70 >= 0.0;
+ if ($cmp548) {
+ label = 63;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 63:
+ if ($cmp556) {
+ label = 64;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 64:
+ $add561 = $70 + .5;
+ $add561_sink = $add561;
+ label = 66;
+ break;
+ case 65:
+ $sub566 = $70 + -.5;
+ $add561_sink = $sub566;
+ label = 66;
+ break;
+ case 66:
+ $conv562 = ~~$add561_sink;
+ $add570 = $conv562 + 1 | 0;
+ $div571 = ($add570 | 0) / 2 & -1;
+ $conv572 = +($div571 | 0);
+ $add573 = $69 + $conv572;
+ $y578 = $P + 8 | 0;
+ $71 = +HEAPF64[$y578 >> 3];
+ $sub579 = $71 + -1.0;
+ $b387_sroa_1_0 = $sub579;
+ $b387_sroa_3_0 = $add573;
+ label = 71;
+ break;
+ case 67:
+ if ($cmp556) {
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 68:
+ $add593 = $70 + .5;
+ $add593_sink = $add593;
+ label = 70;
+ break;
+ case 69:
+ $sub598 = $70 + -.5;
+ $add593_sink = $sub598;
+ label = 70;
+ break;
+ case 70:
+ $conv594 = ~~$add593_sink;
+ $add602 = $conv594 + 1 | 0;
+ $div603 = ($add602 | 0) / 2 & -1;
+ $conv604 = +($div603 | 0);
+ $sub605 = $69 - $conv604;
+ $y610 = $P + 8 | 0;
+ $72 = +HEAPF64[$y610 >> 3];
+ $add611 = $72 + 1.0;
+ $b387_sroa_1_0 = $sub605;
+ $b387_sroa_3_0 = $add611;
+ label = 71;
+ break;
+ case 71:
+ $b387_sroa_0_0__idx4 = $endp + 56 | 0;
+ HEAPF64[$b387_sroa_0_0__idx4 >> 3] = $b387_sroa_0_0_copyload13;
+ $b387_sroa_1_8__idx15 = $endp + 64 | 0;
+ HEAPF64[$b387_sroa_1_8__idx15 >> 3] = $b387_sroa_1_0;
+ $b387_sroa_2_16__idx27 = $endp + 72 | 0;
+ HEAPF64[$b387_sroa_2_16__idx27 >> 3] = $add544;
+ $b387_sroa_3_24__idx39 = $endp + 80 | 0;
+ HEAPF64[$b387_sroa_3_24__idx39 >> 3] = $b387_sroa_3_0;
+ $boxn617 = $endp + 52 | 0;
+ HEAP32[$boxn617 >> 2] = 1;
+ label = 82;
+ break;
+ case 72:
+ $sidemask624 = $endp + 48 | 0;
+ $73 = HEAP32[$sidemask624 >> 2] | 0;
+ $cmp625 = ($73 | 0) == 4;
+ $y630 = $0 + 40 | 0;
+ $74 = +HEAPF64[$y630 >> 3];
+ $ht632 = $0 + 96 | 0;
+ $75 = +HEAPF64[$ht632 >> 3];
+ $cmp633 = $75 >= 0.0;
+ if ($cmp625) {
+ label = 73;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 73:
+ if ($cmp633) {
+ label = 74;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 74:
+ $add638 = $75 + .5;
+ $add638_sink = $add638;
+ label = 76;
+ break;
+ case 75:
+ $sub643 = $75 + -.5;
+ $add638_sink = $sub643;
+ label = 76;
+ break;
+ case 76:
+ $conv639 = ~~$add638_sink;
+ $add647 = $conv639 + 1 | 0;
+ $div648 = ($add647 | 0) / 2 & -1;
+ $conv649 = +($div648 | 0);
+ $add650 = $74 + $conv649;
+ $y655 = $P + 8 | 0;
+ $76 = +HEAPF64[$y655 >> 3];
+ $b387_sroa_1_1 = $76;
+ $b387_sroa_3_1 = $add650;
+ label = 81;
+ break;
+ case 77:
+ if ($cmp633) {
+ label = 78;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 78:
+ $add669 = $75 + .5;
+ $add669_sink = $add669;
+ label = 80;
+ break;
+ case 79:
+ $sub674 = $75 + -.5;
+ $add669_sink = $sub674;
+ label = 80;
+ break;
+ case 80:
+ $conv670 = ~~$add669_sink;
+ $add678 = $conv670 + 1 | 0;
+ $div679 = ($add678 | 0) / 2 & -1;
+ $conv680 = +($div679 | 0);
+ $sub681 = $74 - $conv680;
+ $y686 = $P + 8 | 0;
+ $77 = +HEAPF64[$y686 >> 3];
+ $add687 = $77 + 1.0;
+ $b387_sroa_1_1 = $sub681;
+ $b387_sroa_3_1 = $add687;
+ label = 81;
+ break;
+ case 81:
+ $b387_sroa_0_0__idx = $endp + 56 | 0;
+ HEAPF64[$b387_sroa_0_0__idx >> 3] = $67;
+ $b387_sroa_1_8__idx14 = $endp + 64 | 0;
+ HEAPF64[$b387_sroa_1_8__idx14 >> 3] = $b387_sroa_1_1;
+ $b387_sroa_2_16__idx26 = $endp + 72 | 0;
+ HEAPF64[$b387_sroa_2_16__idx26 >> 3] = $b387_sroa_2_16_copyload36;
+ $b387_sroa_3_24__idx38 = $endp + 80 | 0;
+ HEAPF64[$b387_sroa_3_24__idx38 >> 3] = $b387_sroa_3_1;
+ $boxn693 = $endp + 52 | 0;
+ HEAP32[$boxn693 >> 2] = 1;
+ label = 82;
+ break;
+ case 82:
+ $edge_type699264 = $e + 128 | 0;
+ $78 = HEAP8[$edge_type699264] | 0;
+ $cmp701265 = $78 << 24 >> 24 == 0;
+ if ($cmp701265) {
+ $orig390_0_lcssa = $e;
+ label = 84;
+ break;
+ } else {
+ $orig390_0266 = $e;
+ label = 83;
+ break;
+ }
+ case 83:
+ $to_orig706 = $orig390_0266 + 132 | 0;
+ $79 = HEAP32[$to_orig706 >> 2] | 0;
+ $edge_type699 = $79 + 128 | 0;
+ $80 = HEAP8[$edge_type699] | 0;
+ $cmp701 = $80 << 24 >> 24 == 0;
+ if ($cmp701) {
+ $orig390_0_lcssa = $79;
+ label = 84;
+ break;
+ } else {
+ $orig390_0266 = $79;
+ label = 83;
+ break;
+ }
+ case 84:
+ $tail708 = $orig390_0_lcssa + 16 | 0;
+ $81 = HEAP32[$tail708 >> 2] | 0;
+ $cmp709 = ($0 | 0) == ($81 | 0);
+ if ($cmp709) {
+ label = 85;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 85:
+ $clip714 = $orig390_0_lcssa + 62 | 0;
+ HEAP8[$clip714] = 0;
+ label = 87;
+ break;
+ case 86:
+ $clip718 = $orig390_0_lcssa + 102 | 0;
+ HEAP8[$clip718] = 0;
+ label = 87;
+ break;
+ case 87:
+ $sidemask720 = $endp + 48 | 0;
+ HEAP32[$sidemask720 >> 2] = $conv381;
+ label = 99;
+ break;
+ case 88:
+ if ($cmp) {
+ $side_0 = 1;
+ label = 90;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 89:
+ $sidemask726 = $endp + 48 | 0;
+ $82 = HEAP32[$sidemask726 >> 2] | 0;
+ $side_0 = $82;
+ label = 90;
+ break;
+ case 90:
+ $tobool728 = ($pboxfn_0 | 0) == 0;
+ if ($tobool728) {
+ label = 93;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 91:
+ $arrayidx733 = $endp + 56 | 0;
+ $boxn734 = $endp + 52 | 0;
+ $call735 = FUNCTION_TABLE_iiiiii[$pboxfn_0 & 1023]($0, $tail_port, $side_0, $arrayidx733, $boxn734) | 0;
+ $tobool736 = ($call735 | 0) == 0;
+ if ($tobool736) {
+ label = 93;
+ break;
+ } else {
+ label = 92;
+ break;
+ }
+ case 92:
+ $sidemask738 = $endp + 48 | 0;
+ HEAP32[$sidemask738 >> 2] = $call735;
+ label = 99;
+ break;
+ case 93:
+ $arrayidx741 = $endp + 56 | 0;
+ $83 = $arrayidx741;
+ $84 = $endp;
+ HEAP32[$83 >> 2] = HEAP32[$84 >> 2] | 0;
+ HEAP32[$83 + 4 >> 2] = HEAP32[$84 + 4 >> 2] | 0;
+ HEAP32[$83 + 8 >> 2] = HEAP32[$84 + 8 >> 2] | 0;
+ HEAP32[$83 + 12 >> 2] = HEAP32[$84 + 12 >> 2] | 0;
+ HEAP32[$83 + 16 >> 2] = HEAP32[$84 + 16 >> 2] | 0;
+ HEAP32[$83 + 20 >> 2] = HEAP32[$84 + 20 >> 2] | 0;
+ HEAP32[$83 + 24 >> 2] = HEAP32[$84 + 24 >> 2] | 0;
+ HEAP32[$83 + 28 >> 2] = HEAP32[$84 + 28 >> 2] | 0;
+ $boxn743 = $endp + 52 | 0;
+ HEAP32[$boxn743 >> 2] = 1;
+ if (($et | 0) == 8) {
+ label = 94;
+ break;
+ } else if (($et | 0) == 2) {
+ label = 95;
+ break;
+ } else if (($et | 0) == 1) {
+ label = 98;
+ break;
+ } else {
+ label = 99;
+ break;
+ }
+ case 94:
+ ___assert_func(96712, 565, 164624, 137288);
+ case 95:
+ $sidemask745 = $endp + 48 | 0;
+ $85 = HEAP32[$sidemask745 >> 2] | 0;
+ $cmp746 = ($85 | 0) == 4;
+ $y751 = $P + 8 | 0;
+ $86 = +HEAPF64[$y751 >> 3];
+ if ($cmp746) {
+ label = 96;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 96:
+ $y755 = $endp + 64 | 0;
+ HEAPF64[$y755 >> 3] = $86;
+ label = 99;
+ break;
+ case 97:
+ $y763 = $endp + 80 | 0;
+ HEAPF64[$y763 >> 3] = $86;
+ label = 99;
+ break;
+ case 98:
+ $y768 = $P + 8 | 0;
+ $87 = +HEAPF64[$y768 >> 3];
+ $y772 = $endp + 80 | 0;
+ HEAPF64[$y772 >> 3] = $87;
+ $sidemask773 = $endp + 48 | 0;
+ HEAP32[$sidemask773 >> 2] = 1;
+ $88 = +HEAPF64[$y768 >> 3];
+ $sub777 = $88 + -1.0;
+ HEAPF64[$y768 >> 3] = $sub777;
+ label = 99;
+ break;
+ case 99:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _selfRightSpace($e) {
+ $e = $e | 0;
+ var $label = 0, $0 = 0, $defined = 0, $1 = 0, $tobool = 0, $defined3 = 0, $2 = 0, $tobool4 = 0, $side = 0, $3 = 0, $conv = 0, $and = 0, $tobool7 = 0, $side11 = 0, $4 = 0, $and13 = 0, $tobool14 = 0, $cmp = 0, $and30 = 0, $tobool31 = 0, $tobool32 = 0, $head = 0, $5 = 0, $graph = 0, $6 = 0, $rankdir = 0, $7 = 0, $and36 = 0, $tobool37 = 0, $y = 0, $x = 0, $cond_in = 0, $cond = 0.0, $add = 0.0, $conv40 = 0, $sw_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $label = $e + 112 | 0;
+ $0 = HEAP32[$label >> 2] | 0;
+ $defined = $e + 60 | 0;
+ $1 = HEAP8[$defined] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $defined3 = $e + 100 | 0;
+ $2 = HEAP8[$defined3] | 0;
+ $tobool4 = $2 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $side = $e + 65 | 0;
+ $3 = HEAP8[$side] | 0;
+ $conv = $3 & 255;
+ $and = $conv & 8;
+ $tobool7 = ($and | 0) == 0;
+ if ($tobool7) {
+ label = 5;
+ break;
+ } else {
+ $sw_0 = 0;
+ label = 10;
+ break;
+ }
+ case 5:
+ $side11 = $e + 105 | 0;
+ $4 = HEAP8[$side11] | 0;
+ $and13 = $4 & 8;
+ $tobool14 = $and13 << 24 >> 24 == 0;
+ if ($tobool14) {
+ label = 6;
+ break;
+ } else {
+ $sw_0 = 0;
+ label = 10;
+ break;
+ }
+ case 6:
+ $cmp = $3 << 24 >> 24 == $4 << 24 >> 24;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $and30 = $conv & 5;
+ $tobool31 = ($and30 | 0) == 0;
+ if ($tobool31) {
+ label = 8;
+ break;
+ } else {
+ $sw_0 = 0;
+ label = 10;
+ break;
+ }
+ case 8:
+ $tobool32 = ($0 | 0) == 0;
+ if ($tobool32) {
+ $sw_0 = 18;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $head = $e + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $graph = $5 + 20 | 0;
+ $6 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $6 + 156 | 0;
+ $7 = HEAP32[$rankdir >> 2] | 0;
+ $and36 = $7 & 1;
+ $tobool37 = ($and36 | 0) == 0;
+ $y = $0 + 32 | 0;
+ $x = $0 + 24 | 0;
+ $cond_in = $tobool37 ? $x : $y;
+ $cond = +HEAPF64[$cond_in >> 3];
+ $add = $cond + 18.0;
+ $conv40 = ~~$add;
+ $sw_0 = $conv40;
+ label = 10;
+ break;
+ case 10:
+ return $sw_0 | 0;
+ }
+ return 0;
+}
+function _endpath($P, $e, $et, $endp, $merge) {
+ $P = $P | 0;
+ $e = $e | 0;
+ $et = $et | 0;
+ $endp = $endp | 0;
+ $merge = $merge | 0;
+ var $tmp = 0, $tmp17 = 0, $head = 0, $0 = 0, $head_port = 0, $dyna = 0, $1 = 0, $tobool = 0, $tail = 0, $2 = 0, $3 = 0, $4 = 0, $shape = 0, $5 = 0, $tobool7 = 0, $fns = 0, $6 = 0, $pboxfn11 = 0, $7 = 0, $pboxfn_0 = 0, $end = 0, $coord = 0, $p16 = 0, $8 = 0, $9 = 0, $tobool18 = 0, $10 = 0, $call = 0.0, $add = 0.0, $theta = 0, $cmp = 0, $constrained = 0, $constrained28 = 0, $11 = 0, $tobool29 = 0, $theta33 = 0, $12 = 0.0, $theta35 = 0, $constrained37 = 0, $constrained40 = 0, $np = 0, $13 = 0, $cmp45 = 0, $node_type = 0, $14 = 0, $cmp47 = 0, $side52 = 0, $15 = 0, $conv53 = 0, $tobool54 = 0, $b_sroa_0_0__idx62 = 0, $b_sroa_0_0_copyload63 = 0.0, $b_sroa_1_8__idx74 = 0, $b_sroa_1_8_copyload75 = 0.0, $b_sroa_2_16__idx86 = 0, $b_sroa_2_16_copyload87 = 0.0, $and = 0, $tobool59 = 0, $b_sroa_3_24__idx99 = 0, $b_sroa_3_24_copyload100 = 0.0, $sidemask = 0, $y63 = 0, $16 = 0.0, $cmp64 = 0, $b_sroa_1_8_copyload75_ = 0.0, $b_sroa_0_0__idx60 = 0, $b_sroa_1_8__idx72 = 0, $b_sroa_2_16__idx84 = 0, $b_sroa_3_24__idx97 = 0, $boxn = 0, $17 = 0.0, $add79 = 0.0, $and81 = 0, $tobool82 = 0, $sidemask84 = 0, $x = 0, $18 = 0.0, $x89 = 0, $19 = 0.0, $cmp90 = 0, $sub = 0.0, $y99 = 0, $20 = 0.0, $y107 = 0, $21 = 0.0, $ht = 0, $22 = 0.0, $cmp109 = 0, $add114 = 0.0, $sub119 = 0.0, $add114_sink = 0.0, $conv115 = 0, $add123 = 0, $div = 0, $conv124 = 0.0, $sub125 = 0.0, $graph = 0, $23 = 0, $ranksep = 0, $24 = 0, $div127 = 0, $conv128 = 0.0, $sub129 = 0.0, $25 = 0.0, $lw = 0, $26 = 0.0, $sub136 = 0.0, $27 = 0.0, $28 = 0.0, $cmp149 = 0, $add154 = 0.0, $sub159 = 0.0, $add154_sink = 0.0, $conv155 = 0, $add163 = 0, $div164 = 0, $conv165 = 0.0, $add166 = 0.0, $b0_sroa_0_0__idx101 = 0, $b0_sroa_1_8__idx104 = 0, $b0_sroa_2_16__idx107 = 0, $b0_sroa_3_24__idx110 = 0, $b_sroa_0_0__idx58 = 0, $b_sroa_1_8__idx70 = 0, $b_sroa_2_16__idx82 = 0, $b_sroa_3_24__idx95 = 0, $y183 = 0, $29 = 0.0, $add188 = 0.0, $y193 = 0, $30 = 0.0, $ht195 = 0, $31 = 0.0, $cmp196 = 0, $add201 = 0.0, $sub206 = 0.0, $add201_sink = 0.0, $conv202 = 0, $add210 = 0, $div211 = 0, $conv212 = 0.0, $sub213 = 0.0, $graph214 = 0, $32 = 0, $ranksep216 = 0, $33 = 0, $div217 = 0, $conv218 = 0.0, $sub219 = 0.0, $34 = 0.0, $rw = 0, $35 = 0.0, $add226 = 0.0, $add227 = 0.0, $36 = 0.0, $37 = 0.0, $cmp239 = 0, $add244 = 0.0, $sub249 = 0.0, $add244_sink = 0.0, $conv245 = 0, $add253 = 0, $div254 = 0, $conv255 = 0.0, $add256 = 0.0, $b0_sroa_0_0__idx = 0, $b0_sroa_1_8__idx103 = 0, $b0_sroa_2_16__idx106 = 0, $b0_sroa_3_24__idx109 = 0, $b_sroa_0_0__idx56 = 0, $b_sroa_1_8__idx68 = 0, $b_sroa_2_16__idx80 = 0, $b_sroa_3_24__idx93 = 0, $boxn267 = 0, $y270 = 0, $38 = 0.0, $sub271 = 0.0, $and273 = 0, $tobool274 = 0, $sidemask276 = 0, $x279 = 0, $39 = 0.0, $y284 = 0, $40 = 0.0, $ht286 = 0, $41 = 0.0, $cmp287 = 0, $add292 = 0.0, $sub297 = 0.0, $add292_sink = 0.0, $conv293 = 0, $add301 = 0, $div302 = 0, $conv303 = 0.0, $add304 = 0.0, $y309 = 0, $42 = 0.0, $b_sroa_0_0__idx54 = 0, $b_sroa_1_8__idx66 = 0, $b_sroa_2_16__idx78 = 0, $b_sroa_3_24__idx91 = 0, $boxn314 = 0, $43 = 0.0, $sub318 = 0.0, $x323 = 0, $44 = 0.0, $y328 = 0, $45 = 0.0, $ht330 = 0, $46 = 0.0, $cmp331 = 0, $add336 = 0.0, $sub341 = 0.0, $add336_sink = 0.0, $conv337 = 0, $add345 = 0, $div346 = 0, $conv347 = 0.0, $add348 = 0.0, $y353 = 0, $47 = 0.0, $b_sroa_0_0__idx = 0, $b_sroa_1_8__idx65 = 0, $b_sroa_2_16__idx77 = 0, $b_sroa_3_24__idx90 = 0, $boxn358 = 0, $48 = 0.0, $add362 = 0.0, $edge_type267 = 0, $49 = 0, $cmp368268 = 0, $orig_0269 = 0, $to_orig = 0, $50 = 0, $edge_type = 0, $51 = 0, $cmp368 = 0, $orig_0_lcssa = 0, $head371 = 0, $52 = 0, $cmp372 = 0, $clip = 0, $clip379 = 0, $sidemask381 = 0, $cmp383 = 0, $side388 = 0, $53 = 0, $conv389 = 0, $tobool390 = 0, $b395_sroa_0_0__idx12 = 0, $b395_sroa_0_0_copyload13 = 0.0, $b395_sroa_1_8__idx24 = 0, $b395_sroa_1_8_copyload25 = 0.0, $b395_sroa_2_16__idx36 = 0, $b395_sroa_2_16_copyload37 = 0.0, $b395_sroa_3_24__idx47 = 0, $b395_sroa_3_24_copyload48 = 0.0, $and399 = 0, $tobool400 = 0, $y406 = 0, $54 = 0.0, $cmp407 = 0, $b395_sroa_1_8_copyload25_ = 0.0, $b395_sroa_0_0__idx10 = 0, $b395_sroa_1_8__idx22 = 0, $b395_sroa_2_16__idx34 = 0, $b395_sroa_3_24__idx45 = 0, $boxn422 = 0, $and424 = 0, $tobool425 = 0, $sidemask427 = 0, $55 = 0, $cmp428 = 0, $sub433 = 0.0, $y438 = 0, $56 = 0.0, $ht440 = 0, $57 = 0.0, $cmp441 = 0, $add446 = 0.0, $sub451 = 0.0, $add446_sink = 0.0, $conv447 = 0, $add455 = 0, $div456 = 0, $conv457 = 0.0, $sub458 = 0.0, $x463 = 0, $58 = 0.0, $graph468 = 0, $59 = 0, $ranksep470 = 0, $60 = 0, $div471 = 0, $conv472 = 0.0, $sub473 = 0.0, $x478 = 0, $61 = 0.0, $lw480 = 0, $62 = 0.0, $sub481 = 0.0, $sub482 = 0.0, $63 = 0.0, $64 = 0.0, $cmp494 = 0, $add499 = 0.0, $sub504 = 0.0, $add499_sink = 0.0, $conv500 = 0, $add508 = 0, $div509 = 0, $conv510 = 0.0, $add511 = 0.0, $b0393_sroa_0_0__idx = 0, $b0393_sroa_1_8__idx50 = 0, $b0393_sroa_2_16__idx51 = 0, $b0393_sroa_3_24__idx52 = 0, $b395_sroa_0_0__idx8 = 0, $b395_sroa_1_8__idx20 = 0, $b395_sroa_2_16__idx32 = 0, $b395_sroa_3_24__idx43 = 0, $boxn521 = 0, $y526 = 0, $65 = 0.0, $cmp527 = 0, $b395_sroa_3_24_copyload48_ = 0.0, $b395_sroa_0_0__idx6 = 0, $b395_sroa_1_8__idx18 = 0, $b395_sroa_2_16__idx30 = 0, $b395_sroa_3_24__idx41 = 0, $boxn542 = 0, $and545 = 0, $tobool546 = 0, $x550 = 0, $66 = 0.0, $add551 = 0.0, $sidemask554 = 0, $67 = 0, $cmp555 = 0, $y560 = 0, $68 = 0.0, $ht562 = 0, $69 = 0.0, $cmp563 = 0, $add568 = 0.0, $sub573 = 0.0, $add568_sink = 0.0, $conv569 = 0, $add577 = 0, $div578 = 0, $conv579 = 0.0, $add580 = 0.0, $y585 = 0, $70 = 0.0, $sub586 = 0.0, $add600 = 0.0, $sub605 = 0.0, $add600_sink = 0.0, $conv601 = 0, $add609 = 0, $div610 = 0, $conv611 = 0.0, $sub612 = 0.0, $y617 = 0, $71 = 0.0, $add618 = 0.0, $b395_sroa_3_0 = 0.0, $b395_sroa_1_0 = 0.0, $b395_sroa_0_0__idx4 = 0, $b395_sroa_1_8__idx16 = 0, $b395_sroa_2_16__idx28 = 0, $b395_sroa_3_24__idx39 = 0, $boxn624 = 0, $sub629 = 0.0, $sidemask632 = 0, $72 = 0, $cmp633 = 0, $y638 = 0, $73 = 0.0, $ht640 = 0, $74 = 0.0, $cmp641 = 0, $add646 = 0.0, $sub651 = 0.0, $add646_sink = 0.0, $conv647 = 0, $add655 = 0, $div656 = 0, $conv657 = 0.0, $add658 = 0.0, $y663 = 0, $75 = 0.0, $sub664 = 0.0, $add678 = 0.0, $sub683 = 0.0, $add678_sink = 0.0, $conv679 = 0, $add687 = 0, $div688 = 0, $conv689 = 0.0, $sub690 = 0.0, $y695 = 0, $76 = 0.0, $b395_sroa_3_1 = 0.0, $b395_sroa_1_1 = 0.0, $b395_sroa_0_0__idx = 0, $b395_sroa_1_8__idx15 = 0, $b395_sroa_2_16__idx27 = 0, $b395_sroa_3_24__idx38 = 0, $boxn701 = 0, $edge_type707264 = 0, $77 = 0, $cmp709265 = 0, $orig398_0266 = 0, $to_orig714 = 0, $78 = 0, $edge_type707 = 0, $79 = 0, $cmp709 = 0, $orig398_0_lcssa = 0, $head716 = 0, $80 = 0, $cmp717 = 0, $clip722 = 0, $clip726 = 0, $sidemask728 = 0, $sidemask734 = 0, $81 = 0, $side_0 = 0, $tobool736 = 0, $arrayidx741 = 0, $boxn742 = 0, $call743 = 0, $tobool744 = 0, $sidemask746 = 0, $arrayidx749 = 0, $82 = 0, $83 = 0, $boxn751 = 0, $sidemask753 = 0, $84 = 0, $cmp754 = 0, $y759 = 0, $85 = 0.0, $y763 = 0, $y771 = 0, $y776 = 0, $86 = 0.0, $y780 = 0, $sidemask781 = 0, $87 = 0.0, $add785 = 0.0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 56 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmp17 = __stackBase__ + 40 | 0;
+ $head = $e + 12 | 0;
+ $0 = HEAP32[$head >> 2] | 0;
+ $head_port = $e + 72 | 0;
+ $dyna = $e + 103 | 0;
+ $1 = HEAP8[$dyna] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail = $e + 16 | 0;
+ $2 = HEAP32[$tail >> 2] | 0;
+ _resolvePort($tmp, $0, $2, $head_port);
+ $3 = $head_port;
+ $4 = $tmp;
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ HEAP32[$3 + 16 >> 2] = HEAP32[$4 + 16 >> 2] | 0;
+ HEAP32[$3 + 20 >> 2] = HEAP32[$4 + 20 >> 2] | 0;
+ HEAP32[$3 + 24 >> 2] = HEAP32[$4 + 24 >> 2] | 0;
+ HEAP32[$3 + 28 >> 2] = HEAP32[$4 + 28 >> 2] | 0;
+ HEAP32[$3 + 32 >> 2] = HEAP32[$4 + 32 >> 2] | 0;
+ HEAP32[$3 + 36 >> 2] = HEAP32[$4 + 36 >> 2] | 0;
+ label = 4;
+ break;
+ case 4:
+ $shape = $0 + 24 | 0;
+ $5 = HEAP32[$shape >> 2] | 0;
+ $tobool7 = ($5 | 0) == 0;
+ if ($tobool7) {
+ $pboxfn_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $fns = $5 + 4 | 0;
+ $6 = HEAP32[$fns >> 2] | 0;
+ $pboxfn11 = $6 + 16 | 0;
+ $7 = HEAP32[$pboxfn11 >> 2] | 0;
+ $pboxfn_0 = $7;
+ label = 6;
+ break;
+ case 6:
+ $end = $P + 40 | 0;
+ $coord = $0 + 32 | 0;
+ $p16 = $head_port | 0;
+ _add_pointf804($tmp17, $coord, $p16);
+ $8 = $end;
+ $9 = $tmp17;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $tobool18 = $merge << 24 >> 24 == 0;
+ if ($tobool18) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $10 = HEAP32[$head >> 2] | 0;
+ $call = +_conc_slope($10);
+ $add = $call + 3.141592653589793;
+ $theta = $P + 56 | 0;
+ HEAPF64[$theta >> 3] = $add;
+ $cmp = $add < 6.283185307179586;
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ ___assert_func(96712, 602, 164328, 120048);
+ case 9:
+ $constrained = $P + 69 | 0;
+ HEAP8[$constrained] = 1;
+ label = 13;
+ break;
+ case 10:
+ $constrained28 = $e + 101 | 0;
+ $11 = HEAP8[$constrained28] | 0;
+ $tobool29 = $11 << 24 >> 24 == 0;
+ if ($tobool29) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $theta33 = $e + 88 | 0;
+ $12 = +HEAPF64[$theta33 >> 3];
+ $theta35 = $P + 56 | 0;
+ HEAPF64[$theta35 >> 3] = $12;
+ $constrained37 = $P + 69 | 0;
+ HEAP8[$constrained37] = 1;
+ label = 13;
+ break;
+ case 12:
+ $constrained40 = $P + 69 | 0;
+ HEAP8[$constrained40] = 0;
+ label = 13;
+ break;
+ case 13:
+ $np = $endp + 32 | 0;
+ $13 = $np;
+ HEAP32[$13 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$13 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$13 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$13 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $cmp45 = ($et | 0) == 1;
+ if ($cmp45) {
+ label = 14;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 14:
+ $node_type = $0 + 162 | 0;
+ $14 = HEAP8[$node_type] | 0;
+ $cmp47 = $14 << 24 >> 24 == 0;
+ if ($cmp47) {
+ label = 15;
+ break;
+ } else {
+ $side_0 = 4;
+ label = 93;
+ break;
+ }
+ case 15:
+ $side52 = $e + 105 | 0;
+ $15 = HEAP8[$side52] | 0;
+ $conv53 = $15 & 255;
+ $tobool54 = $15 << 24 >> 24 == 0;
+ if ($tobool54) {
+ label = 50;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $b_sroa_0_0__idx62 = $endp | 0;
+ $b_sroa_0_0_copyload63 = +HEAPF64[$b_sroa_0_0__idx62 >> 3];
+ $b_sroa_1_8__idx74 = $endp + 8 | 0;
+ $b_sroa_1_8_copyload75 = +HEAPF64[$b_sroa_1_8__idx74 >> 3];
+ $b_sroa_2_16__idx86 = $endp + 16 | 0;
+ $b_sroa_2_16_copyload87 = +HEAPF64[$b_sroa_2_16__idx86 >> 3];
+ $and = $conv53 & 4;
+ $tobool59 = ($and | 0) == 0;
+ if ($tobool59) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $b_sroa_3_24__idx99 = $endp + 24 | 0;
+ $b_sroa_3_24_copyload100 = +HEAPF64[$b_sroa_3_24__idx99 >> 3];
+ $sidemask = $endp + 48 | 0;
+ HEAP32[$sidemask >> 2] = 4;
+ $y63 = $P + 48 | 0;
+ $16 = +HEAPF64[$y63 >> 3];
+ $cmp64 = $b_sroa_1_8_copyload75 < $16;
+ $b_sroa_1_8_copyload75_ = $cmp64 ? $b_sroa_1_8_copyload75 : $16;
+ $b_sroa_0_0__idx60 = $endp + 56 | 0;
+ HEAPF64[$b_sroa_0_0__idx60 >> 3] = $b_sroa_0_0_copyload63;
+ $b_sroa_1_8__idx72 = $endp + 64 | 0;
+ HEAPF64[$b_sroa_1_8__idx72 >> 3] = $b_sroa_1_8_copyload75_;
+ $b_sroa_2_16__idx84 = $endp + 72 | 0;
+ HEAPF64[$b_sroa_2_16__idx84 >> 3] = $b_sroa_2_16_copyload87;
+ $b_sroa_3_24__idx97 = $endp + 80 | 0;
+ HEAPF64[$b_sroa_3_24__idx97 >> 3] = $b_sroa_3_24_copyload100;
+ $boxn = $endp + 52 | 0;
+ HEAP32[$boxn >> 2] = 1;
+ $17 = +HEAPF64[$y63 >> 3];
+ $add79 = $17 + 1.0;
+ HEAPF64[$y63 >> 3] = $add79;
+ label = 44;
+ break;
+ case 18:
+ $and81 = $conv53 & 1;
+ $tobool82 = ($and81 | 0) == 0;
+ if ($tobool82) {
+ label = 35;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $sidemask84 = $endp + 48 | 0;
+ HEAP32[$sidemask84 >> 2] = 1;
+ $x = $end | 0;
+ $18 = +HEAPF64[$x >> 3];
+ $x89 = $coord | 0;
+ $19 = +HEAPF64[$x89 >> 3];
+ $cmp90 = $18 < $19;
+ if ($cmp90) {
+ label = 20;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 20:
+ $sub = $b_sroa_0_0_copyload63 + -1.0;
+ $y99 = $P + 48 | 0;
+ $20 = +HEAPF64[$y99 >> 3];
+ $y107 = $0 + 40 | 0;
+ $21 = +HEAPF64[$y107 >> 3];
+ $ht = $0 + 96 | 0;
+ $22 = +HEAPF64[$ht >> 3];
+ $cmp109 = $22 < 0.0;
+ if ($cmp109) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $add114 = $22 + .5;
+ $add114_sink = $add114;
+ label = 23;
+ break;
+ case 22:
+ $sub119 = $22 + -.5;
+ $add114_sink = $sub119;
+ label = 23;
+ break;
+ case 23:
+ $conv115 = ~~$add114_sink;
+ $add123 = $conv115 + 1 | 0;
+ $div = ($add123 | 0) / 2 & -1;
+ $conv124 = +($div | 0);
+ $sub125 = $21 - $conv124;
+ $graph = $0 + 20 | 0;
+ $23 = HEAP32[$graph >> 2] | 0;
+ $ranksep = $23 + 264 | 0;
+ $24 = HEAP32[$ranksep >> 2] | 0;
+ $div127 = ($24 | 0) / 2 & -1;
+ $conv128 = +($div127 | 0);
+ $sub129 = $sub125 - $conv128;
+ $25 = +HEAPF64[$x89 >> 3];
+ $lw = $0 + 104 | 0;
+ $26 = +HEAPF64[$lw >> 3];
+ $sub136 = $25 - $26;
+ $27 = +HEAPF64[$y107 >> 3];
+ $28 = +HEAPF64[$ht >> 3];
+ $cmp149 = $28 < 0.0;
+ if ($cmp149) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $add154 = $28 + .5;
+ $add154_sink = $add154;
+ label = 26;
+ break;
+ case 25:
+ $sub159 = $28 + -.5;
+ $add154_sink = $sub159;
+ label = 26;
+ break;
+ case 26:
+ $conv155 = ~~$add154_sink;
+ $add163 = $conv155 + 1 | 0;
+ $div164 = ($add163 | 0) / 2 & -1;
+ $conv165 = +($div164 | 0);
+ $add166 = $27 + $conv165;
+ $b0_sroa_0_0__idx101 = $endp + 56 | 0;
+ HEAPF64[$b0_sroa_0_0__idx101 >> 3] = $sub;
+ $b0_sroa_1_8__idx104 = $endp + 64 | 0;
+ HEAPF64[$b0_sroa_1_8__idx104 >> 3] = $sub129;
+ $b0_sroa_2_16__idx107 = $endp + 72 | 0;
+ HEAPF64[$b0_sroa_2_16__idx107 >> 3] = $b_sroa_2_16_copyload87;
+ $b0_sroa_3_24__idx110 = $endp + 80 | 0;
+ HEAPF64[$b0_sroa_3_24__idx110 >> 3] = $20;
+ $b_sroa_0_0__idx58 = $endp + 88 | 0;
+ HEAPF64[$b_sroa_0_0__idx58 >> 3] = $sub;
+ $b_sroa_1_8__idx70 = $endp + 96 | 0;
+ HEAPF64[$b_sroa_1_8__idx70 >> 3] = $20;
+ $b_sroa_2_16__idx82 = $endp + 104 | 0;
+ HEAPF64[$b_sroa_2_16__idx82 >> 3] = $sub136;
+ $b_sroa_3_24__idx95 = $endp + 112 | 0;
+ HEAPF64[$b_sroa_3_24__idx95 >> 3] = $add166;
+ label = 34;
+ break;
+ case 27:
+ $y183 = $P + 48 | 0;
+ $29 = +HEAPF64[$y183 >> 3];
+ $add188 = $b_sroa_2_16_copyload87 + 1.0;
+ $y193 = $0 + 40 | 0;
+ $30 = +HEAPF64[$y193 >> 3];
+ $ht195 = $0 + 96 | 0;
+ $31 = +HEAPF64[$ht195 >> 3];
+ $cmp196 = $31 < 0.0;
+ if ($cmp196) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $add201 = $31 + .5;
+ $add201_sink = $add201;
+ label = 30;
+ break;
+ case 29:
+ $sub206 = $31 + -.5;
+ $add201_sink = $sub206;
+ label = 30;
+ break;
+ case 30:
+ $conv202 = ~~$add201_sink;
+ $add210 = $conv202 + 1 | 0;
+ $div211 = ($add210 | 0) / 2 & -1;
+ $conv212 = +($div211 | 0);
+ $sub213 = $30 - $conv212;
+ $graph214 = $0 + 20 | 0;
+ $32 = HEAP32[$graph214 >> 2] | 0;
+ $ranksep216 = $32 + 264 | 0;
+ $33 = HEAP32[$ranksep216 >> 2] | 0;
+ $div217 = ($33 | 0) / 2 & -1;
+ $conv218 = +($div217 | 0);
+ $sub219 = $sub213 - $conv218;
+ $34 = +HEAPF64[$x89 >> 3];
+ $rw = $0 + 112 | 0;
+ $35 = +HEAPF64[$rw >> 3];
+ $add226 = $34 + $35;
+ $add227 = $add226 + 0.0;
+ $36 = +HEAPF64[$y193 >> 3];
+ $37 = +HEAPF64[$ht195 >> 3];
+ $cmp239 = $37 < 0.0;
+ if ($cmp239) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $add244 = $37 + .5;
+ $add244_sink = $add244;
+ label = 33;
+ break;
+ case 32:
+ $sub249 = $37 + -.5;
+ $add244_sink = $sub249;
+ label = 33;
+ break;
+ case 33:
+ $conv245 = ~~$add244_sink;
+ $add253 = $conv245 + 1 | 0;
+ $div254 = ($add253 | 0) / 2 & -1;
+ $conv255 = +($div254 | 0);
+ $add256 = $36 + $conv255;
+ $b0_sroa_0_0__idx = $endp + 56 | 0;
+ HEAPF64[$b0_sroa_0_0__idx >> 3] = $b_sroa_0_0_copyload63;
+ $b0_sroa_1_8__idx103 = $endp + 64 | 0;
+ HEAPF64[$b0_sroa_1_8__idx103 >> 3] = $sub219;
+ $b0_sroa_2_16__idx106 = $endp + 72 | 0;
+ HEAPF64[$b0_sroa_2_16__idx106 >> 3] = $add188;
+ $b0_sroa_3_24__idx109 = $endp + 80 | 0;
+ HEAPF64[$b0_sroa_3_24__idx109 >> 3] = $29;
+ $b_sroa_0_0__idx56 = $endp + 88 | 0;
+ HEAPF64[$b_sroa_0_0__idx56 >> 3] = $add227;
+ $b_sroa_1_8__idx68 = $endp + 96 | 0;
+ HEAPF64[$b_sroa_1_8__idx68 >> 3] = $29;
+ $b_sroa_2_16__idx80 = $endp + 104 | 0;
+ HEAPF64[$b_sroa_2_16__idx80 >> 3] = $add188;
+ $b_sroa_3_24__idx93 = $endp + 112 | 0;
+ HEAPF64[$b_sroa_3_24__idx93 >> 3] = $add256;
+ label = 34;
+ break;
+ case 34:
+ $boxn267 = $endp + 52 | 0;
+ HEAP32[$boxn267 >> 2] = 2;
+ $y270 = $P + 48 | 0;
+ $38 = +HEAPF64[$y270 >> 3];
+ $sub271 = $38 + -1.0;
+ HEAPF64[$y270 >> 3] = $sub271;
+ label = 44;
+ break;
+ case 35:
+ $and273 = $conv53 & 8;
+ $tobool274 = ($and273 | 0) == 0;
+ $sidemask276 = $endp + 48 | 0;
+ if ($tobool274) {
+ label = 40;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ HEAP32[$sidemask276 >> 2] = 8;
+ $x279 = $end | 0;
+ $39 = +HEAPF64[$x279 >> 3];
+ $y284 = $0 + 40 | 0;
+ $40 = +HEAPF64[$y284 >> 3];
+ $ht286 = $0 + 96 | 0;
+ $41 = +HEAPF64[$ht286 >> 3];
+ $cmp287 = $41 < 0.0;
+ if ($cmp287) {
+ label = 38;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $add292 = $41 + .5;
+ $add292_sink = $add292;
+ label = 39;
+ break;
+ case 38:
+ $sub297 = $41 + -.5;
+ $add292_sink = $sub297;
+ label = 39;
+ break;
+ case 39:
+ $conv293 = ~~$add292_sink;
+ $add301 = $conv293 + 1 | 0;
+ $div302 = ($add301 | 0) / 2 & -1;
+ $conv303 = +($div302 | 0);
+ $add304 = $40 + $conv303;
+ $y309 = $P + 48 | 0;
+ $42 = +HEAPF64[$y309 >> 3];
+ $b_sroa_0_0__idx54 = $endp + 56 | 0;
+ HEAPF64[$b_sroa_0_0__idx54 >> 3] = $b_sroa_0_0_copyload63;
+ $b_sroa_1_8__idx66 = $endp + 64 | 0;
+ HEAPF64[$b_sroa_1_8__idx66 >> 3] = $42;
+ $b_sroa_2_16__idx78 = $endp + 72 | 0;
+ HEAPF64[$b_sroa_2_16__idx78 >> 3] = $39;
+ $b_sroa_3_24__idx91 = $endp + 80 | 0;
+ HEAPF64[$b_sroa_3_24__idx91 >> 3] = $add304;
+ $boxn314 = $endp + 52 | 0;
+ HEAP32[$boxn314 >> 2] = 1;
+ $43 = +HEAPF64[$x279 >> 3];
+ $sub318 = $43 + -1.0;
+ HEAPF64[$x279 >> 3] = $sub318;
+ label = 44;
+ break;
+ case 40:
+ HEAP32[$sidemask276 >> 2] = 2;
+ $x323 = $end | 0;
+ $44 = +HEAPF64[$x323 >> 3];
+ $y328 = $0 + 40 | 0;
+ $45 = +HEAPF64[$y328 >> 3];
+ $ht330 = $0 + 96 | 0;
+ $46 = +HEAPF64[$ht330 >> 3];
+ $cmp331 = $46 < 0.0;
+ if ($cmp331) {
+ label = 42;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $add336 = $46 + .5;
+ $add336_sink = $add336;
+ label = 43;
+ break;
+ case 42:
+ $sub341 = $46 + -.5;
+ $add336_sink = $sub341;
+ label = 43;
+ break;
+ case 43:
+ $conv337 = ~~$add336_sink;
+ $add345 = $conv337 + 1 | 0;
+ $div346 = ($add345 | 0) / 2 & -1;
+ $conv347 = +($div346 | 0);
+ $add348 = $45 + $conv347;
+ $y353 = $P + 48 | 0;
+ $47 = +HEAPF64[$y353 >> 3];
+ $b_sroa_0_0__idx = $endp + 56 | 0;
+ HEAPF64[$b_sroa_0_0__idx >> 3] = $44;
+ $b_sroa_1_8__idx65 = $endp + 64 | 0;
+ HEAPF64[$b_sroa_1_8__idx65 >> 3] = $47;
+ $b_sroa_2_16__idx77 = $endp + 72 | 0;
+ HEAPF64[$b_sroa_2_16__idx77 >> 3] = $b_sroa_2_16_copyload87;
+ $b_sroa_3_24__idx90 = $endp + 80 | 0;
+ HEAPF64[$b_sroa_3_24__idx90 >> 3] = $add348;
+ $boxn358 = $endp + 52 | 0;
+ HEAP32[$boxn358 >> 2] = 1;
+ $48 = +HEAPF64[$x323 >> 3];
+ $add362 = $48 + 1.0;
+ HEAPF64[$x323 >> 3] = $add362;
+ label = 44;
+ break;
+ case 44:
+ $edge_type267 = $e + 128 | 0;
+ $49 = HEAP8[$edge_type267] | 0;
+ $cmp368268 = $49 << 24 >> 24 == 0;
+ if ($cmp368268) {
+ $orig_0_lcssa = $e;
+ label = 46;
+ break;
+ } else {
+ $orig_0269 = $e;
+ label = 45;
+ break;
+ }
+ case 45:
+ $to_orig = $orig_0269 + 132 | 0;
+ $50 = HEAP32[$to_orig >> 2] | 0;
+ $edge_type = $50 + 128 | 0;
+ $51 = HEAP8[$edge_type] | 0;
+ $cmp368 = $51 << 24 >> 24 == 0;
+ if ($cmp368) {
+ $orig_0_lcssa = $50;
+ label = 46;
+ break;
+ } else {
+ $orig_0269 = $50;
+ label = 45;
+ break;
+ }
+ case 46:
+ $head371 = $orig_0_lcssa + 12 | 0;
+ $52 = HEAP32[$head371 >> 2] | 0;
+ $cmp372 = ($0 | 0) == ($52 | 0);
+ if ($cmp372) {
+ label = 47;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 47:
+ $clip = $orig_0_lcssa + 102 | 0;
+ HEAP8[$clip] = 0;
+ label = 49;
+ break;
+ case 48:
+ $clip379 = $orig_0_lcssa + 62 | 0;
+ HEAP8[$clip379] = 0;
+ label = 49;
+ break;
+ case 49:
+ $sidemask381 = $endp + 48 | 0;
+ HEAP32[$sidemask381 >> 2] = $conv53;
+ label = 102;
+ break;
+ case 50:
+ $cmp383 = ($et | 0) == 2;
+ if ($cmp383) {
+ label = 51;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 51:
+ $side388 = $e + 105 | 0;
+ $53 = HEAP8[$side388] | 0;
+ $conv389 = $53 & 255;
+ $tobool390 = $53 << 24 >> 24 == 0;
+ if ($tobool390) {
+ label = 91;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $b395_sroa_0_0__idx12 = $endp | 0;
+ $b395_sroa_0_0_copyload13 = +HEAPF64[$b395_sroa_0_0__idx12 >> 3];
+ $b395_sroa_1_8__idx24 = $endp + 8 | 0;
+ $b395_sroa_1_8_copyload25 = +HEAPF64[$b395_sroa_1_8__idx24 >> 3];
+ $b395_sroa_2_16__idx36 = $endp + 16 | 0;
+ $b395_sroa_2_16_copyload37 = +HEAPF64[$b395_sroa_2_16__idx36 >> 3];
+ $b395_sroa_3_24__idx47 = $endp + 24 | 0;
+ $b395_sroa_3_24_copyload48 = +HEAPF64[$b395_sroa_3_24__idx47 >> 3];
+ $and399 = $conv389 & 4;
+ $tobool400 = ($and399 | 0) == 0;
+ if ($tobool400) {
+ label = 54;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $y406 = $P + 48 | 0;
+ $54 = +HEAPF64[$y406 >> 3];
+ $cmp407 = $b395_sroa_1_8_copyload25 < $54;
+ $b395_sroa_1_8_copyload25_ = $cmp407 ? $b395_sroa_1_8_copyload25 : $54;
+ $b395_sroa_0_0__idx10 = $endp + 56 | 0;
+ HEAPF64[$b395_sroa_0_0__idx10 >> 3] = $b395_sroa_0_0_copyload13;
+ $b395_sroa_1_8__idx22 = $endp + 64 | 0;
+ HEAPF64[$b395_sroa_1_8__idx22 >> 3] = $b395_sroa_1_8_copyload25_;
+ $b395_sroa_2_16__idx34 = $endp + 72 | 0;
+ HEAPF64[$b395_sroa_2_16__idx34 >> 3] = $b395_sroa_2_16_copyload37;
+ $b395_sroa_3_24__idx45 = $endp + 80 | 0;
+ HEAPF64[$b395_sroa_3_24__idx45 >> 3] = $b395_sroa_3_24_copyload48;
+ $boxn422 = $endp + 52 | 0;
+ HEAP32[$boxn422 >> 2] = 1;
+ label = 85;
+ break;
+ case 54:
+ $and424 = $conv389 & 1;
+ $tobool425 = ($and424 | 0) == 0;
+ if ($tobool425) {
+ label = 64;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ $sidemask427 = $endp + 48 | 0;
+ $55 = HEAP32[$sidemask427 >> 2] | 0;
+ $cmp428 = ($55 | 0) == 4;
+ if ($cmp428) {
+ label = 56;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 56:
+ $sub433 = $b395_sroa_0_0_copyload13 + -1.0;
+ $y438 = $0 + 40 | 0;
+ $56 = +HEAPF64[$y438 >> 3];
+ $ht440 = $0 + 96 | 0;
+ $57 = +HEAPF64[$ht440 >> 3];
+ $cmp441 = $57 < 0.0;
+ if ($cmp441) {
+ label = 58;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $add446 = $57 + .5;
+ $add446_sink = $add446;
+ label = 59;
+ break;
+ case 58:
+ $sub451 = $57 + -.5;
+ $add446_sink = $sub451;
+ label = 59;
+ break;
+ case 59:
+ $conv447 = ~~$add446_sink;
+ $add455 = $conv447 + 1 | 0;
+ $div456 = ($add455 | 0) / 2 & -1;
+ $conv457 = +($div456 | 0);
+ $sub458 = $56 - $conv457;
+ $x463 = $end | 0;
+ $58 = +HEAPF64[$x463 >> 3];
+ $graph468 = $0 + 20 | 0;
+ $59 = HEAP32[$graph468 >> 2] | 0;
+ $ranksep470 = $59 + 264 | 0;
+ $60 = HEAP32[$ranksep470 >> 2] | 0;
+ $div471 = ($60 | 0) / 2 & -1;
+ $conv472 = +($div471 | 0);
+ $sub473 = $sub458 - $conv472;
+ $x478 = $coord | 0;
+ $61 = +HEAPF64[$x478 >> 3];
+ $lw480 = $0 + 104 | 0;
+ $62 = +HEAPF64[$lw480 >> 3];
+ $sub481 = $61 - $62;
+ $sub482 = $sub481 + -2.0;
+ $63 = +HEAPF64[$y438 >> 3];
+ $64 = +HEAPF64[$ht440 >> 3];
+ $cmp494 = $64 < 0.0;
+ if ($cmp494) {
+ label = 61;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $add499 = $64 + .5;
+ $add499_sink = $add499;
+ label = 62;
+ break;
+ case 61:
+ $sub504 = $64 + -.5;
+ $add499_sink = $sub504;
+ label = 62;
+ break;
+ case 62:
+ $conv500 = ~~$add499_sink;
+ $add508 = $conv500 + 1 | 0;
+ $div509 = ($add508 | 0) / 2 & -1;
+ $conv510 = +($div509 | 0);
+ $add511 = $63 + $conv510;
+ $b0393_sroa_0_0__idx = $endp + 56 | 0;
+ HEAPF64[$b0393_sroa_0_0__idx >> 3] = $sub433;
+ $b0393_sroa_1_8__idx50 = $endp + 64 | 0;
+ HEAPF64[$b0393_sroa_1_8__idx50 >> 3] = $sub473;
+ $b0393_sroa_2_16__idx51 = $endp + 72 | 0;
+ HEAPF64[$b0393_sroa_2_16__idx51 >> 3] = $58;
+ $b0393_sroa_3_24__idx52 = $endp + 80 | 0;
+ HEAPF64[$b0393_sroa_3_24__idx52 >> 3] = $sub458;
+ $b395_sroa_0_0__idx8 = $endp + 88 | 0;
+ HEAPF64[$b395_sroa_0_0__idx8 >> 3] = $sub433;
+ $b395_sroa_1_8__idx20 = $endp + 96 | 0;
+ HEAPF64[$b395_sroa_1_8__idx20 >> 3] = $sub458;
+ $b395_sroa_2_16__idx32 = $endp + 104 | 0;
+ HEAPF64[$b395_sroa_2_16__idx32 >> 3] = $sub482;
+ $b395_sroa_3_24__idx43 = $endp + 112 | 0;
+ HEAPF64[$b395_sroa_3_24__idx43 >> 3] = $add511;
+ $boxn521 = $endp + 52 | 0;
+ HEAP32[$boxn521 >> 2] = 2;
+ label = 85;
+ break;
+ case 63:
+ $y526 = $P + 8 | 0;
+ $65 = +HEAPF64[$y526 >> 3];
+ $cmp527 = $b395_sroa_3_24_copyload48 > $65;
+ $b395_sroa_3_24_copyload48_ = $cmp527 ? $b395_sroa_3_24_copyload48 : $65;
+ $b395_sroa_0_0__idx6 = $endp + 56 | 0;
+ HEAPF64[$b395_sroa_0_0__idx6 >> 3] = $b395_sroa_0_0_copyload13;
+ $b395_sroa_1_8__idx18 = $endp + 64 | 0;
+ HEAPF64[$b395_sroa_1_8__idx18 >> 3] = $b395_sroa_1_8_copyload25;
+ $b395_sroa_2_16__idx30 = $endp + 72 | 0;
+ HEAPF64[$b395_sroa_2_16__idx30 >> 3] = $b395_sroa_2_16_copyload37;
+ $b395_sroa_3_24__idx41 = $endp + 80 | 0;
+ HEAPF64[$b395_sroa_3_24__idx41 >> 3] = $b395_sroa_3_24_copyload48_;
+ $boxn542 = $endp + 52 | 0;
+ HEAP32[$boxn542 >> 2] = 1;
+ label = 85;
+ break;
+ case 64:
+ $and545 = $conv389 & 8;
+ $tobool546 = ($and545 | 0) == 0;
+ $x550 = $end | 0;
+ $66 = +HEAPF64[$x550 >> 3];
+ if ($tobool546) {
+ label = 75;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $add551 = $66 + 1.0;
+ $sidemask554 = $endp + 48 | 0;
+ $67 = HEAP32[$sidemask554 >> 2] | 0;
+ $cmp555 = ($67 | 0) == 4;
+ $y560 = $0 + 40 | 0;
+ $68 = +HEAPF64[$y560 >> 3];
+ $ht562 = $0 + 96 | 0;
+ $69 = +HEAPF64[$ht562 >> 3];
+ $cmp563 = $69 >= 0.0;
+ if ($cmp555) {
+ label = 66;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 66:
+ if ($cmp563) {
+ label = 67;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 67:
+ $add568 = $69 + .5;
+ $add568_sink = $add568;
+ label = 69;
+ break;
+ case 68:
+ $sub573 = $69 + -.5;
+ $add568_sink = $sub573;
+ label = 69;
+ break;
+ case 69:
+ $conv569 = ~~$add568_sink;
+ $add577 = $conv569 + 1 | 0;
+ $div578 = ($add577 | 0) / 2 & -1;
+ $conv579 = +($div578 | 0);
+ $add580 = $68 + $conv579;
+ $y585 = $P + 48 | 0;
+ $70 = +HEAPF64[$y585 >> 3];
+ $sub586 = $70 + -1.0;
+ $b395_sroa_1_0 = $sub586;
+ $b395_sroa_3_0 = $add580;
+ label = 74;
+ break;
+ case 70:
+ if ($cmp563) {
+ label = 71;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 71:
+ $add600 = $69 + .5;
+ $add600_sink = $add600;
+ label = 73;
+ break;
+ case 72:
+ $sub605 = $69 + -.5;
+ $add600_sink = $sub605;
+ label = 73;
+ break;
+ case 73:
+ $conv601 = ~~$add600_sink;
+ $add609 = $conv601 + 1 | 0;
+ $div610 = ($add609 | 0) / 2 & -1;
+ $conv611 = +($div610 | 0);
+ $sub612 = $68 - $conv611;
+ $y617 = $P + 48 | 0;
+ $71 = +HEAPF64[$y617 >> 3];
+ $add618 = $71 + 1.0;
+ $b395_sroa_1_0 = $sub612;
+ $b395_sroa_3_0 = $add618;
+ label = 74;
+ break;
+ case 74:
+ $b395_sroa_0_0__idx4 = $endp + 56 | 0;
+ HEAPF64[$b395_sroa_0_0__idx4 >> 3] = $b395_sroa_0_0_copyload13;
+ $b395_sroa_1_8__idx16 = $endp + 64 | 0;
+ HEAPF64[$b395_sroa_1_8__idx16 >> 3] = $b395_sroa_1_0;
+ $b395_sroa_2_16__idx28 = $endp + 72 | 0;
+ HEAPF64[$b395_sroa_2_16__idx28 >> 3] = $add551;
+ $b395_sroa_3_24__idx39 = $endp + 80 | 0;
+ HEAPF64[$b395_sroa_3_24__idx39 >> 3] = $b395_sroa_3_0;
+ $boxn624 = $endp + 52 | 0;
+ HEAP32[$boxn624 >> 2] = 1;
+ label = 85;
+ break;
+ case 75:
+ $sub629 = $66 + -1.0;
+ $sidemask632 = $endp + 48 | 0;
+ $72 = HEAP32[$sidemask632 >> 2] | 0;
+ $cmp633 = ($72 | 0) == 4;
+ $y638 = $0 + 40 | 0;
+ $73 = +HEAPF64[$y638 >> 3];
+ $ht640 = $0 + 96 | 0;
+ $74 = +HEAPF64[$ht640 >> 3];
+ $cmp641 = $74 >= 0.0;
+ if ($cmp633) {
+ label = 76;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 76:
+ if ($cmp641) {
+ label = 77;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 77:
+ $add646 = $74 + .5;
+ $add646_sink = $add646;
+ label = 79;
+ break;
+ case 78:
+ $sub651 = $74 + -.5;
+ $add646_sink = $sub651;
+ label = 79;
+ break;
+ case 79:
+ $conv647 = ~~$add646_sink;
+ $add655 = $conv647 + 1 | 0;
+ $div656 = ($add655 | 0) / 2 & -1;
+ $conv657 = +($div656 | 0);
+ $add658 = $73 + $conv657;
+ $y663 = $P + 48 | 0;
+ $75 = +HEAPF64[$y663 >> 3];
+ $sub664 = $75 + -1.0;
+ $b395_sroa_1_1 = $sub664;
+ $b395_sroa_3_1 = $add658;
+ label = 84;
+ break;
+ case 80:
+ if ($cmp641) {
+ label = 81;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 81:
+ $add678 = $74 + .5;
+ $add678_sink = $add678;
+ label = 83;
+ break;
+ case 82:
+ $sub683 = $74 + -.5;
+ $add678_sink = $sub683;
+ label = 83;
+ break;
+ case 83:
+ $conv679 = ~~$add678_sink;
+ $add687 = $conv679 + 1 | 0;
+ $div688 = ($add687 | 0) / 2 & -1;
+ $conv689 = +($div688 | 0);
+ $sub690 = $73 - $conv689;
+ $y695 = $P + 48 | 0;
+ $76 = +HEAPF64[$y695 >> 3];
+ $b395_sroa_1_1 = $sub690;
+ $b395_sroa_3_1 = $76;
+ label = 84;
+ break;
+ case 84:
+ $b395_sroa_0_0__idx = $endp + 56 | 0;
+ HEAPF64[$b395_sroa_0_0__idx >> 3] = $sub629;
+ $b395_sroa_1_8__idx15 = $endp + 64 | 0;
+ HEAPF64[$b395_sroa_1_8__idx15 >> 3] = $b395_sroa_1_1;
+ $b395_sroa_2_16__idx27 = $endp + 72 | 0;
+ HEAPF64[$b395_sroa_2_16__idx27 >> 3] = $b395_sroa_2_16_copyload37;
+ $b395_sroa_3_24__idx38 = $endp + 80 | 0;
+ HEAPF64[$b395_sroa_3_24__idx38 >> 3] = $b395_sroa_3_1;
+ $boxn701 = $endp + 52 | 0;
+ HEAP32[$boxn701 >> 2] = 1;
+ label = 85;
+ break;
+ case 85:
+ $edge_type707264 = $e + 128 | 0;
+ $77 = HEAP8[$edge_type707264] | 0;
+ $cmp709265 = $77 << 24 >> 24 == 0;
+ if ($cmp709265) {
+ $orig398_0_lcssa = $e;
+ label = 87;
+ break;
+ } else {
+ $orig398_0266 = $e;
+ label = 86;
+ break;
+ }
+ case 86:
+ $to_orig714 = $orig398_0266 + 132 | 0;
+ $78 = HEAP32[$to_orig714 >> 2] | 0;
+ $edge_type707 = $78 + 128 | 0;
+ $79 = HEAP8[$edge_type707] | 0;
+ $cmp709 = $79 << 24 >> 24 == 0;
+ if ($cmp709) {
+ $orig398_0_lcssa = $78;
+ label = 87;
+ break;
+ } else {
+ $orig398_0266 = $78;
+ label = 86;
+ break;
+ }
+ case 87:
+ $head716 = $orig398_0_lcssa + 12 | 0;
+ $80 = HEAP32[$head716 >> 2] | 0;
+ $cmp717 = ($0 | 0) == ($80 | 0);
+ if ($cmp717) {
+ label = 88;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 88:
+ $clip722 = $orig398_0_lcssa + 102 | 0;
+ HEAP8[$clip722] = 0;
+ label = 90;
+ break;
+ case 89:
+ $clip726 = $orig398_0_lcssa + 62 | 0;
+ HEAP8[$clip726] = 0;
+ label = 90;
+ break;
+ case 90:
+ $sidemask728 = $endp + 48 | 0;
+ HEAP32[$sidemask728 >> 2] = $conv389;
+ label = 102;
+ break;
+ case 91:
+ if ($cmp45) {
+ $side_0 = 4;
+ label = 93;
+ break;
+ } else {
+ label = 92;
+ break;
+ }
+ case 92:
+ $sidemask734 = $endp + 48 | 0;
+ $81 = HEAP32[$sidemask734 >> 2] | 0;
+ $side_0 = $81;
+ label = 93;
+ break;
+ case 93:
+ $tobool736 = ($pboxfn_0 | 0) == 0;
+ if ($tobool736) {
+ label = 96;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 94:
+ $arrayidx741 = $endp + 56 | 0;
+ $boxn742 = $endp + 52 | 0;
+ $call743 = FUNCTION_TABLE_iiiiii[$pboxfn_0 & 1023]($0, $head_port, $side_0, $arrayidx741, $boxn742) | 0;
+ $tobool744 = ($call743 | 0) == 0;
+ if ($tobool744) {
+ label = 96;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 95:
+ $sidemask746 = $endp + 48 | 0;
+ HEAP32[$sidemask746 >> 2] = $call743;
+ label = 102;
+ break;
+ case 96:
+ $arrayidx749 = $endp + 56 | 0;
+ $82 = $arrayidx749;
+ $83 = $endp;
+ HEAP32[$82 >> 2] = HEAP32[$83 >> 2] | 0;
+ HEAP32[$82 + 4 >> 2] = HEAP32[$83 + 4 >> 2] | 0;
+ HEAP32[$82 + 8 >> 2] = HEAP32[$83 + 8 >> 2] | 0;
+ HEAP32[$82 + 12 >> 2] = HEAP32[$83 + 12 >> 2] | 0;
+ HEAP32[$82 + 16 >> 2] = HEAP32[$83 + 16 >> 2] | 0;
+ HEAP32[$82 + 20 >> 2] = HEAP32[$83 + 20 >> 2] | 0;
+ HEAP32[$82 + 24 >> 2] = HEAP32[$83 + 24 >> 2] | 0;
+ HEAP32[$82 + 28 >> 2] = HEAP32[$83 + 28 >> 2] | 0;
+ $boxn751 = $endp + 52 | 0;
+ HEAP32[$boxn751 >> 2] = 1;
+ if (($et | 0) == 8) {
+ label = 97;
+ break;
+ } else if (($et | 0) == 2) {
+ label = 98;
+ break;
+ } else if (($et | 0) == 1) {
+ label = 101;
+ break;
+ } else {
+ label = 102;
+ break;
+ }
+ case 97:
+ ___assert_func(96712, 757, 164328, 137288);
+ case 98:
+ $sidemask753 = $endp + 48 | 0;
+ $84 = HEAP32[$sidemask753 >> 2] | 0;
+ $cmp754 = ($84 | 0) == 4;
+ $y759 = $P + 48 | 0;
+ $85 = +HEAPF64[$y759 >> 3];
+ if ($cmp754) {
+ label = 99;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 99:
+ $y763 = $endp + 64 | 0;
+ HEAPF64[$y763 >> 3] = $85;
+ label = 102;
+ break;
+ case 100:
+ $y771 = $endp + 80 | 0;
+ HEAPF64[$y771 >> 3] = $85;
+ label = 102;
+ break;
+ case 101:
+ $y776 = $P + 48 | 0;
+ $86 = +HEAPF64[$y776 >> 3];
+ $y780 = $endp + 64 | 0;
+ HEAPF64[$y780 >> 3] = $86;
+ $sidemask781 = $endp + 48 | 0;
+ HEAP32[$sidemask781 >> 2] = 4;
+ $87 = +HEAPF64[$y776 >> 3];
+ $add785 = $87 + 1.0;
+ HEAPF64[$y776 >> 3] = $add785;
+ label = 102;
+ break;
+ case 102:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _selfRight($edges, $ind, $cnt, $stepx, $sizey, $sinfo) {
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $stepx = +$stepx;
+ $sizey = +$sizey;
+ $sinfo = $sinfo | 0;
+ var $points = 0, $tmp = 0, $tmp74 = 0, $tmp83 = 0, $tmp90 = 0, $tmp98 = 0, $arrayidx = 0, $0 = 0, $tail = 0, $1 = 0, $div = 0.0, $conv = 0.0, $div1 = 0.0, $cmp = 0, $cond = 0.0, $np_sroa_0_0__idx = 0, $np_sroa_0_0_copyload = 0.0, $np_sroa_1_8__idx32 = 0, $np_sroa_1_8_copyload = 0.0, $tp_sroa_0_0__idx48 = 0, $tp_sroa_0_0_copyload49 = 0.0, $tp_sroa_1_8__idx55 = 0, $tp_sroa_1_8_copyload56 = 0.0, $add = 0.0, $add6 = 0.0, $hp_sroa_0_0__idx36 = 0, $hp_sroa_0_0_copyload37 = 0.0, $hp_sroa_1_8__idx43 = 0, $hp_sroa_1_8_copyload44 = 0.0, $add11 = 0.0, $add14 = 0.0, $rw = 0, $2 = 0.0, $add21 = 0.0, $sub = 0.0, $mul = 0.0, $sub37 = 0.0, $mul38 = 0.0, $cmp5093 = 0, $cmp39 = 0, $cmp23 = 0, $cmp17 = 0, $_mul38 = 0.0, $cond33 = 0.0, $_ = 0.0, $mul57 = 0.0, $arrayidx60 = 0, $tp_sroa_0_0__idx = 0, $tp_sroa_1_8__idx52 = 0, $arrayidx62 = 0, $3 = 0, $4 = 0, $arrayidx69 = 0, $5 = 0, $6 = 0, $arrayidx76 = 0, $add81 = 0.0, $div82 = 0.0, $7 = 0, $8 = 0, $arrayidx85 = 0, $9 = 0, $10 = 0, $arrayidx92 = 0, $11 = 0, $12 = 0, $hp_sroa_0_0__idx = 0, $hp_sroa_1_8__idx38 = 0, $ind_addr_099 = 0, $i_098 = 0, $dy_097 = 0.0, $dx_096 = 0.0, $tx_095 = 0.0, $hx_094 = 0.0, $inc = 0, $arrayidx52 = 0, $13 = 0, $add53 = 0.0, $add54 = 0.0, $add55 = 0.0, $add58 = 0.0, $div64 = 0.0, $add65 = 0.0, $add67 = 0.0, $add71 = 0.0, $sub89 = 0.0, $div94 = 0.0, $add95 = 0.0, $label = 0, $14 = 0, $tobool = 0, $tail103 = 0, $15 = 0, $graph = 0, $16 = 0, $rankdir = 0, $17 = 0, $and105 = 0, $tobool106 = 0, $dimen = 0, $y110 = 0, $x114 = 0, $x119 = 0, $y123 = 0, $width_0_in = 0, $height_0_in = 0, $height_0 = 0.0, $width_0 = 0.0, $18 = 0.0, $add128 = 0.0, $div129 = 0.0, $add130 = 0.0, $19 = 0, $x133 = 0, $20 = 0.0, $21 = 0, $y140 = 0, $22 = 0, $set = 0, $cmp143 = 0, $sub146 = 0.0, $add147 = 0.0, $dx_1 = 0.0, $add149 = 0.0, $cmp150 = 0, $sub153 = 0.0, $add154 = 0.0, $dx_2 = 0.0, $dy_1 = 0.0, $head = 0, $23 = 0, $inc157 = 0, $cmp50 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16080 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $points = __stackBase__ | 0;
+ $tmp = __stackBase__ + 16e3 | 0;
+ $tmp74 = __stackBase__ + 16016 | 0;
+ $tmp83 = __stackBase__ + 16032 | 0;
+ $tmp90 = __stackBase__ + 16048 | 0;
+ $tmp98 = __stackBase__ + 16064 | 0;
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $tail = $0 + 16 | 0;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $div = $sizey * .5;
+ $conv = +($cnt | 0);
+ $div1 = $div / $conv;
+ $cmp = $div1 > 2.0;
+ $cond = $cmp ? $div1 : 2.0;
+ $np_sroa_0_0__idx = $1 + 32 | 0;
+ $np_sroa_0_0_copyload = +HEAPF64[$np_sroa_0_0__idx >> 3];
+ $np_sroa_1_8__idx32 = $1 + 40 | 0;
+ $np_sroa_1_8_copyload = +HEAPF64[$np_sroa_1_8__idx32 >> 3];
+ $tp_sroa_0_0__idx48 = $0 + 32 | 0;
+ $tp_sroa_0_0_copyload49 = +HEAPF64[$tp_sroa_0_0__idx48 >> 3];
+ $tp_sroa_1_8__idx55 = $0 + 40 | 0;
+ $tp_sroa_1_8_copyload56 = +HEAPF64[$tp_sroa_1_8__idx55 >> 3];
+ $add = $np_sroa_0_0_copyload + $tp_sroa_0_0_copyload49;
+ $add6 = $np_sroa_1_8_copyload + $tp_sroa_1_8_copyload56;
+ $hp_sroa_0_0__idx36 = $0 + 72 | 0;
+ $hp_sroa_0_0_copyload37 = +HEAPF64[$hp_sroa_0_0__idx36 >> 3];
+ $hp_sroa_1_8__idx43 = $0 + 80 | 0;
+ $hp_sroa_1_8_copyload44 = +HEAPF64[$hp_sroa_1_8__idx43 >> 3];
+ $add11 = $np_sroa_0_0_copyload + $hp_sroa_0_0_copyload37;
+ $add14 = $np_sroa_1_8_copyload + $hp_sroa_1_8_copyload44;
+ $rw = $1 + 112 | 0;
+ $2 = +HEAPF64[$rw >> 3];
+ $add21 = $np_sroa_0_0_copyload + $2;
+ $sub = $add21 - $add;
+ $mul = $sub * 3.0;
+ $sub37 = $add21 - $add11;
+ $mul38 = $sub37 * 3.0;
+ $cmp5093 = ($cnt | 0) > 0;
+ if ($cmp5093) {
+ label = 3;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 3:
+ $cmp39 = $2 < $mul38;
+ $cmp23 = $2 < $mul;
+ $cmp17 = $add6 < $add14;
+ $_mul38 = $cmp39 ? $2 : $mul38;
+ $cond33 = $cmp23 ? $2 : $mul;
+ $_ = $cmp17 ? -1.0 : 1.0;
+ $mul57 = $cond * $_;
+ $arrayidx60 = $points | 0;
+ $tp_sroa_0_0__idx = $points | 0;
+ $tp_sroa_1_8__idx52 = $points + 8 | 0;
+ $arrayidx62 = $points + 16 | 0;
+ $3 = $arrayidx62;
+ $4 = $tmp;
+ $arrayidx69 = $points + 32 | 0;
+ $5 = $arrayidx69;
+ $6 = $tmp74;
+ $arrayidx76 = $points + 48 | 0;
+ $add81 = $add6 + $add14;
+ $div82 = $add81 * .5;
+ $7 = $arrayidx76;
+ $8 = $tmp83;
+ $arrayidx85 = $points + 64 | 0;
+ $9 = $arrayidx85;
+ $10 = $tmp90;
+ $arrayidx92 = $points + 80 | 0;
+ $11 = $arrayidx92;
+ $12 = $tmp98;
+ $hp_sroa_0_0__idx = $points + 96 | 0;
+ $hp_sroa_1_8__idx38 = $points + 104 | 0;
+ $hx_094 = $_mul38;
+ $tx_095 = $cond33;
+ $dx_096 = $2;
+ $dy_097 = 0.0;
+ $i_098 = 0;
+ $ind_addr_099 = $ind;
+ label = 4;
+ break;
+ case 4:
+ $inc = $ind_addr_099 + 1 | 0;
+ $arrayidx52 = $edges + ($ind_addr_099 << 2) | 0;
+ $13 = HEAP32[$arrayidx52 >> 2] | 0;
+ $add53 = $dx_096 + $stepx;
+ $add54 = $tx_095 + $stepx;
+ $add55 = $hx_094 + $stepx;
+ $add58 = $mul57 + $dy_097;
+ HEAPF64[$tp_sroa_0_0__idx >> 3] = $add;
+ HEAPF64[$tp_sroa_1_8__idx52 >> 3] = $add6;
+ $div64 = $add54 / 3.0;
+ $add65 = $add + $div64;
+ $add67 = $add6 + $add58;
+ _pointfof805($tmp, $add65, $add67);
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $add71 = $np_sroa_0_0_copyload + $add53;
+ _pointfof805($tmp74, $add71, $add67);
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ _pointfof805($tmp83, $add71, $div82);
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $sub89 = $add14 - $add58;
+ _pointfof805($tmp90, $add71, $sub89);
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $div94 = $add55 / 3.0;
+ $add95 = $add11 + $div94;
+ _pointfof805($tmp98, $add95, $sub89);
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ HEAPF64[$hp_sroa_0_0__idx >> 3] = $add11;
+ HEAPF64[$hp_sroa_1_8__idx38 >> 3] = $add14;
+ $label = $13 + 112 | 0;
+ $14 = HEAP32[$label >> 2] | 0;
+ $tobool = ($14 | 0) == 0;
+ if ($tobool) {
+ $dy_1 = $add58;
+ $dx_2 = $add53;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $tail103 = $13 + 16 | 0;
+ $15 = HEAP32[$tail103 >> 2] | 0;
+ $graph = $15 + 20 | 0;
+ $16 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $16 + 156 | 0;
+ $17 = HEAP32[$rankdir >> 2] | 0;
+ $and105 = $17 & 1;
+ $tobool106 = ($and105 | 0) == 0;
+ $dimen = $14 + 24 | 0;
+ if ($tobool106) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $y110 = $14 + 32 | 0;
+ $x114 = $dimen | 0;
+ $height_0_in = $x114;
+ $width_0_in = $y110;
+ label = 8;
+ break;
+ case 7:
+ $x119 = $dimen | 0;
+ $y123 = $14 + 32 | 0;
+ $height_0_in = $y123;
+ $width_0_in = $x119;
+ label = 8;
+ break;
+ case 8:
+ $height_0 = +HEAPF64[$height_0_in >> 3];
+ $width_0 = +HEAPF64[$width_0_in >> 3];
+ $18 = +HEAPF64[$np_sroa_0_0__idx >> 3];
+ $add128 = $add53 + $18;
+ $div129 = $width_0 * .5;
+ $add130 = $div129 + $add128;
+ $19 = HEAP32[$label >> 2] | 0;
+ $x133 = $19 + 56 | 0;
+ HEAPF64[$x133 >> 3] = $add130;
+ $20 = +HEAPF64[$np_sroa_1_8__idx32 >> 3];
+ $21 = HEAP32[$label >> 2] | 0;
+ $y140 = $21 + 64 | 0;
+ HEAPF64[$y140 >> 3] = $20;
+ $22 = HEAP32[$label >> 2] | 0;
+ $set = $22 + 81 | 0;
+ HEAP8[$set] = 1;
+ $cmp143 = $width_0 > $stepx;
+ if ($cmp143) {
+ label = 9;
+ break;
+ } else {
+ $dx_1 = $add53;
+ label = 10;
+ break;
+ }
+ case 9:
+ $sub146 = $width_0 - $stepx;
+ $add147 = $add53 + $sub146;
+ $dx_1 = $add147;
+ label = 10;
+ break;
+ case 10:
+ $add149 = $cond + $add58;
+ $cmp150 = $add149 < $height_0;
+ if ($cmp150) {
+ label = 11;
+ break;
+ } else {
+ $dy_1 = $add58;
+ $dx_2 = $dx_1;
+ label = 12;
+ break;
+ }
+ case 11:
+ $sub153 = $height_0 - $cond;
+ $add154 = $add58 + $sub153;
+ $dy_1 = $add154;
+ $dx_2 = $dx_1;
+ label = 12;
+ break;
+ case 12:
+ $head = $13 + 12 | 0;
+ $23 = HEAP32[$head >> 2] | 0;
+ _clip_and_install($13, $23, $arrayidx60, 7, $sinfo);
+ $inc157 = $i_098 + 1 | 0;
+ $cmp50 = ($inc157 | 0) < ($cnt | 0);
+ if ($cmp50) {
+ $hx_094 = $add55;
+ $tx_095 = $add54;
+ $dx_096 = $dx_2;
+ $dy_097 = $dy_1;
+ $i_098 = $inc157;
+ $ind_addr_099 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _selfTop($edges, $ind, $cnt, $sizex, $stepy, $sinfo) {
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $sizex = +$sizex;
+ $stepy = +$stepy;
+ $sinfo = $sinfo | 0;
+ var $points = 0, $tmp = 0, $tmp75 = 0, $tmp84 = 0, $tmp91 = 0, $tmp99 = 0, $arrayidx = 0, $0 = 0, $tail = 0, $1 = 0, $div = 0.0, $conv = 0.0, $div1 = 0.0, $cmp = 0, $cond = 0.0, $np_sroa_0_0__idx = 0, $np_sroa_0_0_copyload = 0.0, $np_sroa_1_8__idx32 = 0, $np_sroa_1_8_copyload = 0.0, $tp_sroa_0_0__idx49 = 0, $tp_sroa_0_0_copyload50 = 0.0, $tp_sroa_1_8__idx55 = 0, $tp_sroa_1_8_copyload56 = 0.0, $add = 0.0, $add6 = 0.0, $hp_sroa_0_0__idx37 = 0, $hp_sroa_0_0_copyload38 = 0.0, $hp_sroa_1_8__idx43 = 0, $hp_sroa_1_8_copyload44 = 0.0, $add11 = 0.0, $add14 = 0.0, $ht = 0, $2 = 0.0, $div20 = 0.0, $add22 = 0.0, $sub = 0.0, $mul = 0.0, $sub38 = 0.0, $mul39 = 0.0, $cmp5193 = 0, $cmp40 = 0, $cmp24 = 0, $cmp17 = 0, $div20_mul39 = 0.0, $cond34 = 0.0, $_ = 0.0, $mul58 = 0.0, $arrayidx61 = 0, $tp_sroa_0_0__idx = 0, $tp_sroa_1_8__idx51 = 0, $arrayidx63 = 0, $3 = 0, $4 = 0, $arrayidx70 = 0, $5 = 0, $6 = 0, $arrayidx77 = 0, $add80 = 0.0, $div81 = 0.0, $7 = 0, $8 = 0, $arrayidx86 = 0, $9 = 0, $10 = 0, $arrayidx93 = 0, $11 = 0, $12 = 0, $hp_sroa_0_0__idx = 0, $hp_sroa_1_8__idx39 = 0, $ind_addr_099 = 0, $i_098 = 0, $dy_097 = 0.0, $dx_096 = 0.0, $ty_095 = 0.0, $hy_094 = 0.0, $inc = 0, $arrayidx53 = 0, $13 = 0, $add54 = 0.0, $add55 = 0.0, $add56 = 0.0, $add59 = 0.0, $add65 = 0.0, $div67 = 0.0, $add68 = 0.0, $add74 = 0.0, $sub88 = 0.0, $div97 = 0.0, $add98 = 0.0, $label = 0, $14 = 0, $tobool = 0, $tail104 = 0, $15 = 0, $graph = 0, $16 = 0, $rankdir = 0, $17 = 0, $and106 = 0, $tobool107 = 0, $dimen = 0, $y111 = 0, $x115 = 0, $x120 = 0, $y124 = 0, $width_0_in = 0, $height_0_in = 0, $height_0 = 0.0, $width_0 = 0.0, $18 = 0.0, $add129 = 0.0, $div130 = 0.0, $add131 = 0.0, $19 = 0, $y134 = 0, $20 = 0.0, $21 = 0, $x141 = 0, $22 = 0, $set = 0, $cmp144 = 0, $sub147 = 0.0, $add148 = 0.0, $dy_1 = 0.0, $add150 = 0.0, $cmp151 = 0, $sub154 = 0.0, $add155 = 0.0, $dx_1 = 0.0, $dy_2 = 0.0, $head = 0, $23 = 0, $inc158 = 0, $cmp51 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16080 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $points = __stackBase__ | 0;
+ $tmp = __stackBase__ + 16e3 | 0;
+ $tmp75 = __stackBase__ + 16016 | 0;
+ $tmp84 = __stackBase__ + 16032 | 0;
+ $tmp91 = __stackBase__ + 16048 | 0;
+ $tmp99 = __stackBase__ + 16064 | 0;
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $tail = $0 + 16 | 0;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $div = $sizex * .5;
+ $conv = +($cnt | 0);
+ $div1 = $div / $conv;
+ $cmp = $div1 > 2.0;
+ $cond = $cmp ? $div1 : 2.0;
+ $np_sroa_0_0__idx = $1 + 32 | 0;
+ $np_sroa_0_0_copyload = +HEAPF64[$np_sroa_0_0__idx >> 3];
+ $np_sroa_1_8__idx32 = $1 + 40 | 0;
+ $np_sroa_1_8_copyload = +HEAPF64[$np_sroa_1_8__idx32 >> 3];
+ $tp_sroa_0_0__idx49 = $0 + 32 | 0;
+ $tp_sroa_0_0_copyload50 = +HEAPF64[$tp_sroa_0_0__idx49 >> 3];
+ $tp_sroa_1_8__idx55 = $0 + 40 | 0;
+ $tp_sroa_1_8_copyload56 = +HEAPF64[$tp_sroa_1_8__idx55 >> 3];
+ $add = $np_sroa_0_0_copyload + $tp_sroa_0_0_copyload50;
+ $add6 = $np_sroa_1_8_copyload + $tp_sroa_1_8_copyload56;
+ $hp_sroa_0_0__idx37 = $0 + 72 | 0;
+ $hp_sroa_0_0_copyload38 = +HEAPF64[$hp_sroa_0_0__idx37 >> 3];
+ $hp_sroa_1_8__idx43 = $0 + 80 | 0;
+ $hp_sroa_1_8_copyload44 = +HEAPF64[$hp_sroa_1_8__idx43 >> 3];
+ $add11 = $np_sroa_0_0_copyload + $hp_sroa_0_0_copyload38;
+ $add14 = $np_sroa_1_8_copyload + $hp_sroa_1_8_copyload44;
+ $ht = $1 + 96 | 0;
+ $2 = +HEAPF64[$ht >> 3];
+ $div20 = $2 * .5;
+ $add22 = $np_sroa_1_8_copyload + $div20;
+ $sub = $add22 - $add6;
+ $mul = $sub * 3.0;
+ $sub38 = $add22 - $add14;
+ $mul39 = $sub38 * 3.0;
+ $cmp5193 = ($cnt | 0) > 0;
+ if ($cmp5193) {
+ label = 3;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 3:
+ $cmp40 = $div20 < $mul39;
+ $cmp24 = $div20 < $mul;
+ $cmp17 = $add < $add11;
+ $div20_mul39 = $cmp40 ? $div20 : $mul39;
+ $cond34 = $cmp24 ? $div20 : $mul;
+ $_ = $cmp17 ? -1.0 : 1.0;
+ $mul58 = $cond * $_;
+ $arrayidx61 = $points | 0;
+ $tp_sroa_0_0__idx = $points | 0;
+ $tp_sroa_1_8__idx51 = $points + 8 | 0;
+ $arrayidx63 = $points + 16 | 0;
+ $3 = $arrayidx63;
+ $4 = $tmp;
+ $arrayidx70 = $points + 32 | 0;
+ $5 = $arrayidx70;
+ $6 = $tmp75;
+ $arrayidx77 = $points + 48 | 0;
+ $add80 = $add + $add11;
+ $div81 = $add80 * .5;
+ $7 = $arrayidx77;
+ $8 = $tmp84;
+ $arrayidx86 = $points + 64 | 0;
+ $9 = $arrayidx86;
+ $10 = $tmp91;
+ $arrayidx93 = $points + 80 | 0;
+ $11 = $arrayidx93;
+ $12 = $tmp99;
+ $hp_sroa_0_0__idx = $points + 96 | 0;
+ $hp_sroa_1_8__idx39 = $points + 104 | 0;
+ $hy_094 = $div20_mul39;
+ $ty_095 = $cond34;
+ $dx_096 = 0.0;
+ $dy_097 = $div20;
+ $i_098 = 0;
+ $ind_addr_099 = $ind;
+ label = 4;
+ break;
+ case 4:
+ $inc = $ind_addr_099 + 1 | 0;
+ $arrayidx53 = $edges + ($ind_addr_099 << 2) | 0;
+ $13 = HEAP32[$arrayidx53 >> 2] | 0;
+ $add54 = $dy_097 + $stepy;
+ $add55 = $ty_095 + $stepy;
+ $add56 = $hy_094 + $stepy;
+ $add59 = $mul58 + $dx_096;
+ HEAPF64[$tp_sroa_0_0__idx >> 3] = $add;
+ HEAPF64[$tp_sroa_1_8__idx51 >> 3] = $add6;
+ $add65 = $add + $add59;
+ $div67 = $add55 / 3.0;
+ $add68 = $add6 + $div67;
+ _pointfof805($tmp, $add65, $add68);
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $add74 = $np_sroa_1_8_copyload + $add54;
+ _pointfof805($tmp75, $add65, $add74);
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ _pointfof805($tmp84, $div81, $add74);
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $sub88 = $add11 - $add59;
+ _pointfof805($tmp91, $sub88, $add74);
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $div97 = $add56 / 3.0;
+ $add98 = $add14 + $div97;
+ _pointfof805($tmp99, $sub88, $add98);
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ HEAPF64[$hp_sroa_0_0__idx >> 3] = $add11;
+ HEAPF64[$hp_sroa_1_8__idx39 >> 3] = $add14;
+ $label = $13 + 112 | 0;
+ $14 = HEAP32[$label >> 2] | 0;
+ $tobool = ($14 | 0) == 0;
+ if ($tobool) {
+ $dy_2 = $add54;
+ $dx_1 = $add59;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $tail104 = $13 + 16 | 0;
+ $15 = HEAP32[$tail104 >> 2] | 0;
+ $graph = $15 + 20 | 0;
+ $16 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $16 + 156 | 0;
+ $17 = HEAP32[$rankdir >> 2] | 0;
+ $and106 = $17 & 1;
+ $tobool107 = ($and106 | 0) == 0;
+ $dimen = $14 + 24 | 0;
+ if ($tobool107) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $y111 = $14 + 32 | 0;
+ $x115 = $dimen | 0;
+ $height_0_in = $x115;
+ $width_0_in = $y111;
+ label = 8;
+ break;
+ case 7:
+ $x120 = $dimen | 0;
+ $y124 = $14 + 32 | 0;
+ $height_0_in = $y124;
+ $width_0_in = $x120;
+ label = 8;
+ break;
+ case 8:
+ $height_0 = +HEAPF64[$height_0_in >> 3];
+ $width_0 = +HEAPF64[$width_0_in >> 3];
+ $18 = +HEAPF64[$np_sroa_1_8__idx32 >> 3];
+ $add129 = $add54 + $18;
+ $div130 = $height_0 * .5;
+ $add131 = $div130 + $add129;
+ $19 = HEAP32[$label >> 2] | 0;
+ $y134 = $19 + 64 | 0;
+ HEAPF64[$y134 >> 3] = $add131;
+ $20 = +HEAPF64[$np_sroa_0_0__idx >> 3];
+ $21 = HEAP32[$label >> 2] | 0;
+ $x141 = $21 + 56 | 0;
+ HEAPF64[$x141 >> 3] = $20;
+ $22 = HEAP32[$label >> 2] | 0;
+ $set = $22 + 81 | 0;
+ HEAP8[$set] = 1;
+ $cmp144 = $height_0 > $stepy;
+ if ($cmp144) {
+ label = 9;
+ break;
+ } else {
+ $dy_1 = $add54;
+ label = 10;
+ break;
+ }
+ case 9:
+ $sub147 = $height_0 - $stepy;
+ $add148 = $add54 + $sub147;
+ $dy_1 = $add148;
+ label = 10;
+ break;
+ case 10:
+ $add150 = $cond + $add59;
+ $cmp151 = $add150 < $width_0;
+ if ($cmp151) {
+ label = 11;
+ break;
+ } else {
+ $dy_2 = $dy_1;
+ $dx_1 = $add59;
+ label = 12;
+ break;
+ }
+ case 11:
+ $sub154 = $width_0 - $cond;
+ $add155 = $add59 + $sub154;
+ $dy_2 = $dy_1;
+ $dx_1 = $add155;
+ label = 12;
+ break;
+ case 12:
+ $head = $13 + 12 | 0;
+ $23 = HEAP32[$head >> 2] | 0;
+ _clip_and_install($13, $23, $arrayidx61, 7, $sinfo);
+ $inc158 = $i_098 + 1 | 0;
+ $cmp51 = ($inc158 | 0) < ($cnt | 0);
+ if ($cmp51) {
+ $hy_094 = $add56;
+ $ty_095 = $add55;
+ $dx_096 = $dx_1;
+ $dy_097 = $dy_2;
+ $i_098 = $inc158;
+ $ind_addr_099 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _selfLeft($edges, $ind, $cnt, $stepx, $sizey, $sinfo) {
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $stepx = +$stepx;
+ $sizey = +$sizey;
+ $sinfo = $sinfo | 0;
+ var $points = 0, $tmp = 0, $tmp74 = 0, $tmp83 = 0, $tmp90 = 0, $tmp98 = 0, $arrayidx = 0, $0 = 0, $tail = 0, $1 = 0, $div = 0.0, $conv = 0.0, $div1 = 0.0, $cmp = 0, $cond = 0.0, $np_sroa_0_0__idx = 0, $np_sroa_0_0_copyload = 0.0, $np_sroa_1_8__idx32 = 0, $np_sroa_1_8_copyload = 0.0, $tp_sroa_0_0__idx48 = 0, $tp_sroa_0_0_copyload49 = 0.0, $tp_sroa_1_8__idx55 = 0, $tp_sroa_1_8_copyload56 = 0.0, $add = 0.0, $add6 = 0.0, $hp_sroa_0_0__idx36 = 0, $hp_sroa_0_0_copyload37 = 0.0, $hp_sroa_1_8__idx43 = 0, $hp_sroa_1_8_copyload44 = 0.0, $add11 = 0.0, $add14 = 0.0, $lw = 0, $2 = 0.0, $add21 = 0.0, $sub = 0.0, $mul = 0.0, $add35 = 0.0, $sub37 = 0.0, $mul38 = 0.0, $cmp5093 = 0, $cmp39 = 0, $cmp23 = 0, $cmp17 = 0, $_mul38 = 0.0, $cond33 = 0.0, $_ = 0.0, $mul57 = 0.0, $arrayidx60 = 0, $tp_sroa_0_0__idx = 0, $tp_sroa_1_8__idx52 = 0, $arrayidx62 = 0, $3 = 0, $4 = 0, $arrayidx69 = 0, $5 = 0, $6 = 0, $arrayidx76 = 0, $add81 = 0.0, $div82 = 0.0, $7 = 0, $8 = 0, $arrayidx85 = 0, $9 = 0, $10 = 0, $arrayidx92 = 0, $11 = 0, $12 = 0, $hp_sroa_0_0__idx = 0, $hp_sroa_1_8__idx38 = 0, $ind_addr_099 = 0, $i_098 = 0, $dy_097 = 0.0, $dx_096 = 0.0, $tx_095 = 0.0, $hx_094 = 0.0, $inc = 0, $arrayidx52 = 0, $13 = 0, $add53 = 0.0, $add54 = 0.0, $add55 = 0.0, $add58 = 0.0, $div64 = 0.0, $sub65 = 0.0, $add67 = 0.0, $sub71 = 0.0, $sub89 = 0.0, $div94 = 0.0, $sub95 = 0.0, $label = 0, $14 = 0, $tobool = 0, $tail103 = 0, $15 = 0, $graph = 0, $16 = 0, $rankdir = 0, $17 = 0, $and105 = 0, $tobool106 = 0, $dimen = 0, $y110 = 0, $x114 = 0, $x119 = 0, $y123 = 0, $width_0_in = 0, $height_0_in = 0, $height_0 = 0.0, $width_0 = 0.0, $18 = 0.0, $sub128 = 0.0, $div129 = 0.0, $sub130 = 0.0, $19 = 0, $x133 = 0, $20 = 0.0, $21 = 0, $y140 = 0, $22 = 0, $set = 0, $cmp143 = 0, $sub146 = 0.0, $add147 = 0.0, $dx_1 = 0.0, $add149 = 0.0, $cmp150 = 0, $sub153 = 0.0, $add154 = 0.0, $dx_2 = 0.0, $dy_1 = 0.0, $head = 0, $23 = 0, $inc157 = 0, $cmp50 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16080 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $points = __stackBase__ | 0;
+ $tmp = __stackBase__ + 16e3 | 0;
+ $tmp74 = __stackBase__ + 16016 | 0;
+ $tmp83 = __stackBase__ + 16032 | 0;
+ $tmp90 = __stackBase__ + 16048 | 0;
+ $tmp98 = __stackBase__ + 16064 | 0;
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $tail = $0 + 16 | 0;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $div = $sizey * .5;
+ $conv = +($cnt | 0);
+ $div1 = $div / $conv;
+ $cmp = $div1 > 2.0;
+ $cond = $cmp ? $div1 : 2.0;
+ $np_sroa_0_0__idx = $1 + 32 | 0;
+ $np_sroa_0_0_copyload = +HEAPF64[$np_sroa_0_0__idx >> 3];
+ $np_sroa_1_8__idx32 = $1 + 40 | 0;
+ $np_sroa_1_8_copyload = +HEAPF64[$np_sroa_1_8__idx32 >> 3];
+ $tp_sroa_0_0__idx48 = $0 + 32 | 0;
+ $tp_sroa_0_0_copyload49 = +HEAPF64[$tp_sroa_0_0__idx48 >> 3];
+ $tp_sroa_1_8__idx55 = $0 + 40 | 0;
+ $tp_sroa_1_8_copyload56 = +HEAPF64[$tp_sroa_1_8__idx55 >> 3];
+ $add = $np_sroa_0_0_copyload + $tp_sroa_0_0_copyload49;
+ $add6 = $np_sroa_1_8_copyload + $tp_sroa_1_8_copyload56;
+ $hp_sroa_0_0__idx36 = $0 + 72 | 0;
+ $hp_sroa_0_0_copyload37 = +HEAPF64[$hp_sroa_0_0__idx36 >> 3];
+ $hp_sroa_1_8__idx43 = $0 + 80 | 0;
+ $hp_sroa_1_8_copyload44 = +HEAPF64[$hp_sroa_1_8__idx43 >> 3];
+ $add11 = $np_sroa_0_0_copyload + $hp_sroa_0_0_copyload37;
+ $add14 = $np_sroa_1_8_copyload + $hp_sroa_1_8_copyload44;
+ $lw = $1 + 104 | 0;
+ $2 = +HEAPF64[$lw >> 3];
+ $add21 = $add + $2;
+ $sub = $add21 - $np_sroa_0_0_copyload;
+ $mul = $sub * 3.0;
+ $add35 = $add11 + $2;
+ $sub37 = $add35 - $np_sroa_0_0_copyload;
+ $mul38 = $sub37 * 3.0;
+ $cmp5093 = ($cnt | 0) > 0;
+ if ($cmp5093) {
+ label = 3;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 3:
+ $cmp39 = $2 < $mul38;
+ $cmp23 = $2 < $mul;
+ $cmp17 = $add6 < $add14;
+ $_mul38 = $cmp39 ? $2 : $mul38;
+ $cond33 = $cmp23 ? $2 : $mul;
+ $_ = $cmp17 ? -1.0 : 1.0;
+ $mul57 = $cond * $_;
+ $arrayidx60 = $points | 0;
+ $tp_sroa_0_0__idx = $points | 0;
+ $tp_sroa_1_8__idx52 = $points + 8 | 0;
+ $arrayidx62 = $points + 16 | 0;
+ $3 = $arrayidx62;
+ $4 = $tmp;
+ $arrayidx69 = $points + 32 | 0;
+ $5 = $arrayidx69;
+ $6 = $tmp74;
+ $arrayidx76 = $points + 48 | 0;
+ $add81 = $add6 + $add14;
+ $div82 = $add81 * .5;
+ $7 = $arrayidx76;
+ $8 = $tmp83;
+ $arrayidx85 = $points + 64 | 0;
+ $9 = $arrayidx85;
+ $10 = $tmp90;
+ $arrayidx92 = $points + 80 | 0;
+ $11 = $arrayidx92;
+ $12 = $tmp98;
+ $hp_sroa_0_0__idx = $points + 96 | 0;
+ $hp_sroa_1_8__idx38 = $points + 104 | 0;
+ $hx_094 = $_mul38;
+ $tx_095 = $cond33;
+ $dx_096 = $2;
+ $dy_097 = 0.0;
+ $i_098 = 0;
+ $ind_addr_099 = $ind;
+ label = 4;
+ break;
+ case 4:
+ $inc = $ind_addr_099 + 1 | 0;
+ $arrayidx52 = $edges + ($ind_addr_099 << 2) | 0;
+ $13 = HEAP32[$arrayidx52 >> 2] | 0;
+ $add53 = $dx_096 + $stepx;
+ $add54 = $tx_095 + $stepx;
+ $add55 = $hx_094 + $stepx;
+ $add58 = $mul57 + $dy_097;
+ HEAPF64[$tp_sroa_0_0__idx >> 3] = $add;
+ HEAPF64[$tp_sroa_1_8__idx52 >> 3] = $add6;
+ $div64 = $add54 / 3.0;
+ $sub65 = $add - $div64;
+ $add67 = $add6 + $add58;
+ _pointfof805($tmp, $sub65, $add67);
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $sub71 = $np_sroa_0_0_copyload - $add53;
+ _pointfof805($tmp74, $sub71, $add67);
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ _pointfof805($tmp83, $sub71, $div82);
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $sub89 = $add14 - $add58;
+ _pointfof805($tmp90, $sub71, $sub89);
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $div94 = $add55 / 3.0;
+ $sub95 = $add11 - $div94;
+ _pointfof805($tmp98, $sub95, $sub89);
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ HEAPF64[$hp_sroa_0_0__idx >> 3] = $add11;
+ HEAPF64[$hp_sroa_1_8__idx38 >> 3] = $add14;
+ $label = $13 + 112 | 0;
+ $14 = HEAP32[$label >> 2] | 0;
+ $tobool = ($14 | 0) == 0;
+ if ($tobool) {
+ $dy_1 = $add58;
+ $dx_2 = $add53;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $tail103 = $13 + 16 | 0;
+ $15 = HEAP32[$tail103 >> 2] | 0;
+ $graph = $15 + 20 | 0;
+ $16 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $16 + 156 | 0;
+ $17 = HEAP32[$rankdir >> 2] | 0;
+ $and105 = $17 & 1;
+ $tobool106 = ($and105 | 0) == 0;
+ $dimen = $14 + 24 | 0;
+ if ($tobool106) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $y110 = $14 + 32 | 0;
+ $x114 = $dimen | 0;
+ $height_0_in = $x114;
+ $width_0_in = $y110;
+ label = 8;
+ break;
+ case 7:
+ $x119 = $dimen | 0;
+ $y123 = $14 + 32 | 0;
+ $height_0_in = $y123;
+ $width_0_in = $x119;
+ label = 8;
+ break;
+ case 8:
+ $height_0 = +HEAPF64[$height_0_in >> 3];
+ $width_0 = +HEAPF64[$width_0_in >> 3];
+ $18 = +HEAPF64[$np_sroa_0_0__idx >> 3];
+ $sub128 = $18 - $add53;
+ $div129 = $width_0 * .5;
+ $sub130 = $sub128 - $div129;
+ $19 = HEAP32[$label >> 2] | 0;
+ $x133 = $19 + 56 | 0;
+ HEAPF64[$x133 >> 3] = $sub130;
+ $20 = +HEAPF64[$np_sroa_1_8__idx32 >> 3];
+ $21 = HEAP32[$label >> 2] | 0;
+ $y140 = $21 + 64 | 0;
+ HEAPF64[$y140 >> 3] = $20;
+ $22 = HEAP32[$label >> 2] | 0;
+ $set = $22 + 81 | 0;
+ HEAP8[$set] = 1;
+ $cmp143 = $width_0 > $stepx;
+ if ($cmp143) {
+ label = 9;
+ break;
+ } else {
+ $dx_1 = $add53;
+ label = 10;
+ break;
+ }
+ case 9:
+ $sub146 = $width_0 - $stepx;
+ $add147 = $add53 + $sub146;
+ $dx_1 = $add147;
+ label = 10;
+ break;
+ case 10:
+ $add149 = $cond + $add58;
+ $cmp150 = $add149 < $height_0;
+ if ($cmp150) {
+ label = 11;
+ break;
+ } else {
+ $dy_1 = $add58;
+ $dx_2 = $dx_1;
+ label = 12;
+ break;
+ }
+ case 11:
+ $sub153 = $height_0 - $cond;
+ $add154 = $add58 + $sub153;
+ $dy_1 = $add154;
+ $dx_2 = $dx_1;
+ label = 12;
+ break;
+ case 12:
+ $head = $13 + 12 | 0;
+ $23 = HEAP32[$head >> 2] | 0;
+ _clip_and_install($13, $23, $arrayidx60, 7, $sinfo);
+ $inc157 = $i_098 + 1 | 0;
+ $cmp50 = ($inc157 | 0) < ($cnt | 0);
+ if ($cmp50) {
+ $hx_094 = $add55;
+ $tx_095 = $add54;
+ $dx_096 = $dx_2;
+ $dy_097 = $dy_1;
+ $i_098 = $inc157;
+ $ind_addr_099 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _selfBottom($edges, $ind, $cnt, $sizex, $stepy, $sinfo) {
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $sizex = +$sizex;
+ $stepy = +$stepy;
+ $sinfo = $sinfo | 0;
+ var $points = 0, $tmp = 0, $tmp75 = 0, $tmp84 = 0, $tmp91 = 0, $tmp99 = 0, $arrayidx = 0, $0 = 0, $tail = 0, $1 = 0, $div = 0.0, $conv = 0.0, $div1 = 0.0, $cmp = 0, $cond = 0.0, $np_sroa_0_0__idx = 0, $np_sroa_0_0_copyload = 0.0, $np_sroa_1_8__idx61 = 0, $np_sroa_1_8_copyload = 0.0, $tp_sroa_0_0__idx78 = 0, $tp_sroa_0_0_copyload79 = 0.0, $tp_sroa_1_8__idx84 = 0, $tp_sroa_1_8_copyload85 = 0.0, $add = 0.0, $add6 = 0.0, $hp_sroa_0_0__idx66 = 0, $hp_sroa_0_0_copyload67 = 0.0, $hp_sroa_1_8__idx72 = 0, $hp_sroa_1_8_copyload73 = 0.0, $add11 = 0.0, $add14 = 0.0, $ht = 0, $2 = 0.0, $div20 = 0.0, $add22 = 0.0, $sub = 0.0, $mul = 0.0, $add36 = 0.0, $sub38 = 0.0, $mul39 = 0.0, $cmp5193 = 0, $cmp40 = 0, $cmp24 = 0, $cmp17 = 0, $div20_mul39 = 0.0, $cond34 = 0.0, $_ = 0.0, $mul58 = 0.0, $arrayidx61 = 0, $tp_sroa_0_0__idx = 0, $tp_sroa_1_8__idx80 = 0, $arrayidx63 = 0, $3 = 0, $4 = 0, $arrayidx70 = 0, $5 = 0, $6 = 0, $arrayidx77 = 0, $add80 = 0.0, $div81 = 0.0, $7 = 0, $8 = 0, $arrayidx86 = 0, $9 = 0, $10 = 0, $arrayidx93 = 0, $11 = 0, $12 = 0, $hp_sroa_0_0__idx = 0, $hp_sroa_1_8__idx68 = 0, $dy_099 = 0.0, $dx_098 = 0.0, $ty_097 = 0.0, $hy_096 = 0.0, $i_095 = 0, $ind_addr_094 = 0, $inc = 0, $arrayidx53 = 0, $13 = 0, $add54 = 0.0, $add55 = 0.0, $add56 = 0.0, $add59 = 0.0, $add65 = 0.0, $div67 = 0.0, $sub68 = 0.0, $sub74 = 0.0, $sub88 = 0.0, $div97 = 0.0, $sub98 = 0.0, $label = 0, $14 = 0, $tobool = 0, $tail104 = 0, $15 = 0, $graph = 0, $16 = 0, $rankdir = 0, $17 = 0, $and106 = 0, $tobool107 = 0, $dimen = 0, $y111 = 0, $x115 = 0, $x120 = 0, $y124 = 0, $width_0_in = 0, $height_0_in = 0, $height_0 = 0.0, $width_0 = 0.0, $18 = 0.0, $sub129 = 0.0, $div130 = 0.0, $sub131 = 0.0, $19 = 0, $y134 = 0, $20 = 0.0, $21 = 0, $x141 = 0, $22 = 0, $set = 0, $cmp144 = 0, $sub147 = 0.0, $add148 = 0.0, $dy_1 = 0.0, $add150 = 0.0, $cmp151 = 0, $sub154 = 0.0, $add155 = 0.0, $dx_1 = 0.0, $dy_2 = 0.0, $head = 0, $23 = 0, $inc158 = 0, $cmp51 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16080 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $points = __stackBase__ | 0;
+ $tmp = __stackBase__ + 16e3 | 0;
+ $tmp75 = __stackBase__ + 16016 | 0;
+ $tmp84 = __stackBase__ + 16032 | 0;
+ $tmp91 = __stackBase__ + 16048 | 0;
+ $tmp99 = __stackBase__ + 16064 | 0;
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $tail = $0 + 16 | 0;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $div = $sizex * .5;
+ $conv = +($cnt | 0);
+ $div1 = $div / $conv;
+ $cmp = $div1 > 2.0;
+ $cond = $cmp ? $div1 : 2.0;
+ $np_sroa_0_0__idx = $1 + 32 | 0;
+ $np_sroa_0_0_copyload = +HEAPF64[$np_sroa_0_0__idx >> 3];
+ $np_sroa_1_8__idx61 = $1 + 40 | 0;
+ $np_sroa_1_8_copyload = +HEAPF64[$np_sroa_1_8__idx61 >> 3];
+ $tp_sroa_0_0__idx78 = $0 + 32 | 0;
+ $tp_sroa_0_0_copyload79 = +HEAPF64[$tp_sroa_0_0__idx78 >> 3];
+ $tp_sroa_1_8__idx84 = $0 + 40 | 0;
+ $tp_sroa_1_8_copyload85 = +HEAPF64[$tp_sroa_1_8__idx84 >> 3];
+ $add = $np_sroa_0_0_copyload + $tp_sroa_0_0_copyload79;
+ $add6 = $np_sroa_1_8_copyload + $tp_sroa_1_8_copyload85;
+ $hp_sroa_0_0__idx66 = $0 + 72 | 0;
+ $hp_sroa_0_0_copyload67 = +HEAPF64[$hp_sroa_0_0__idx66 >> 3];
+ $hp_sroa_1_8__idx72 = $0 + 80 | 0;
+ $hp_sroa_1_8_copyload73 = +HEAPF64[$hp_sroa_1_8__idx72 >> 3];
+ $add11 = $np_sroa_0_0_copyload + $hp_sroa_0_0_copyload67;
+ $add14 = $np_sroa_1_8_copyload + $hp_sroa_1_8_copyload73;
+ $ht = $1 + 96 | 0;
+ $2 = +HEAPF64[$ht >> 3];
+ $div20 = $2 * .5;
+ $add22 = $add6 + $div20;
+ $sub = $add22 - $np_sroa_1_8_copyload;
+ $mul = $sub * 3.0;
+ $add36 = $add14 + $div20;
+ $sub38 = $add36 - $np_sroa_1_8_copyload;
+ $mul39 = $sub38 * 3.0;
+ $cmp5193 = ($cnt | 0) > 0;
+ if ($cmp5193) {
+ label = 3;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 3:
+ $cmp40 = $div20 < $mul39;
+ $cmp24 = $div20 < $mul;
+ $cmp17 = $add < $add11;
+ $div20_mul39 = $cmp40 ? $div20 : $mul39;
+ $cond34 = $cmp24 ? $div20 : $mul;
+ $_ = $cmp17 ? -1.0 : 1.0;
+ $mul58 = $cond * $_;
+ $arrayidx61 = $points | 0;
+ $tp_sroa_0_0__idx = $points | 0;
+ $tp_sroa_1_8__idx80 = $points + 8 | 0;
+ $arrayidx63 = $points + 16 | 0;
+ $3 = $arrayidx63;
+ $4 = $tmp;
+ $arrayidx70 = $points + 32 | 0;
+ $5 = $arrayidx70;
+ $6 = $tmp75;
+ $arrayidx77 = $points + 48 | 0;
+ $add80 = $add + $add11;
+ $div81 = $add80 * .5;
+ $7 = $arrayidx77;
+ $8 = $tmp84;
+ $arrayidx86 = $points + 64 | 0;
+ $9 = $arrayidx86;
+ $10 = $tmp91;
+ $arrayidx93 = $points + 80 | 0;
+ $11 = $arrayidx93;
+ $12 = $tmp99;
+ $hp_sroa_0_0__idx = $points + 96 | 0;
+ $hp_sroa_1_8__idx68 = $points + 104 | 0;
+ $ind_addr_094 = $ind;
+ $i_095 = 0;
+ $hy_096 = $div20_mul39;
+ $ty_097 = $cond34;
+ $dx_098 = 0.0;
+ $dy_099 = $div20;
+ label = 4;
+ break;
+ case 4:
+ $inc = $ind_addr_094 + 1 | 0;
+ $arrayidx53 = $edges + ($ind_addr_094 << 2) | 0;
+ $13 = HEAP32[$arrayidx53 >> 2] | 0;
+ $add54 = $dy_099 + $stepy;
+ $add55 = $ty_097 + $stepy;
+ $add56 = $hy_096 + $stepy;
+ $add59 = $mul58 + $dx_098;
+ HEAPF64[$tp_sroa_0_0__idx >> 3] = $add;
+ HEAPF64[$tp_sroa_1_8__idx80 >> 3] = $add6;
+ $add65 = $add + $add59;
+ $div67 = $add55 / 3.0;
+ $sub68 = $add6 - $div67;
+ _pointfof805($tmp, $add65, $sub68);
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $sub74 = $np_sroa_1_8_copyload - $add54;
+ _pointfof805($tmp75, $add65, $sub74);
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ _pointfof805($tmp84, $div81, $sub74);
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $sub88 = $add11 - $add59;
+ _pointfof805($tmp91, $sub88, $sub74);
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $div97 = $add56 / 3.0;
+ $sub98 = $add14 - $div97;
+ _pointfof805($tmp99, $sub88, $sub98);
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ HEAPF64[$hp_sroa_0_0__idx >> 3] = $add11;
+ HEAPF64[$hp_sroa_1_8__idx68 >> 3] = $add14;
+ $label = $13 + 112 | 0;
+ $14 = HEAP32[$label >> 2] | 0;
+ $tobool = ($14 | 0) == 0;
+ if ($tobool) {
+ $dy_2 = $add54;
+ $dx_1 = $add59;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $tail104 = $13 + 16 | 0;
+ $15 = HEAP32[$tail104 >> 2] | 0;
+ $graph = $15 + 20 | 0;
+ $16 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $16 + 156 | 0;
+ $17 = HEAP32[$rankdir >> 2] | 0;
+ $and106 = $17 & 1;
+ $tobool107 = ($and106 | 0) == 0;
+ $dimen = $14 + 24 | 0;
+ if ($tobool107) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $y111 = $14 + 32 | 0;
+ $x115 = $dimen | 0;
+ $height_0_in = $x115;
+ $width_0_in = $y111;
+ label = 8;
+ break;
+ case 7:
+ $x120 = $dimen | 0;
+ $y124 = $14 + 32 | 0;
+ $height_0_in = $y124;
+ $width_0_in = $x120;
+ label = 8;
+ break;
+ case 8:
+ $height_0 = +HEAPF64[$height_0_in >> 3];
+ $width_0 = +HEAPF64[$width_0_in >> 3];
+ $18 = +HEAPF64[$np_sroa_1_8__idx61 >> 3];
+ $sub129 = $18 - $add54;
+ $div130 = $height_0 * .5;
+ $sub131 = $sub129 - $div130;
+ $19 = HEAP32[$label >> 2] | 0;
+ $y134 = $19 + 64 | 0;
+ HEAPF64[$y134 >> 3] = $sub131;
+ $20 = +HEAPF64[$np_sroa_0_0__idx >> 3];
+ $21 = HEAP32[$label >> 2] | 0;
+ $x141 = $21 + 56 | 0;
+ HEAPF64[$x141 >> 3] = $20;
+ $22 = HEAP32[$label >> 2] | 0;
+ $set = $22 + 81 | 0;
+ HEAP8[$set] = 1;
+ $cmp144 = $height_0 > $stepy;
+ if ($cmp144) {
+ label = 9;
+ break;
+ } else {
+ $dy_1 = $add54;
+ label = 10;
+ break;
+ }
+ case 9:
+ $sub147 = $height_0 - $stepy;
+ $add148 = $add54 + $sub147;
+ $dy_1 = $add148;
+ label = 10;
+ break;
+ case 10:
+ $add150 = $cond + $add59;
+ $cmp151 = $add150 < $width_0;
+ if ($cmp151) {
+ label = 11;
+ break;
+ } else {
+ $dy_2 = $dy_1;
+ $dx_1 = $add59;
+ label = 12;
+ break;
+ }
+ case 11:
+ $sub154 = $width_0 - $cond;
+ $add155 = $add59 + $sub154;
+ $dy_2 = $dy_1;
+ $dx_1 = $add155;
+ label = 12;
+ break;
+ case 12:
+ $head = $13 + 12 | 0;
+ $23 = HEAP32[$head >> 2] | 0;
+ _clip_and_install($13, $23, $arrayidx61, 7, $sinfo);
+ $inc158 = $i_095 + 1 | 0;
+ $cmp51 = ($inc158 | 0) < ($cnt | 0);
+ if ($cmp51) {
+ $ind_addr_094 = $inc;
+ $i_095 = $inc158;
+ $hy_096 = $add56;
+ $ty_097 = $add55;
+ $dx_098 = $dx_1;
+ $dy_099 = $dy_2;
+ label = 4;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _makeSelfEdge($P, $edges, $ind, $cnt, $sizex, $sizey, $sinfo) {
+ $P = $P | 0;
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $sizex = +$sizex;
+ $sizey = +$sizey;
+ $sinfo = $sinfo | 0;
+ var $arrayidx = 0, $0 = 0, $defined = 0, $1 = 0, $tobool = 0, $defined2 = 0, $2 = 0, $tobool3 = 0, $side = 0, $3 = 0, $conv = 0, $and = 0, $tobool6 = 0, $side10 = 0, $4 = 0, $and12 = 0, $tobool13 = 0, $cmp = 0, $and29 = 0, $tobool30 = 0, $5 = 0, $conv34 = 0, $and35 = 0, $tobool36 = 0, $side40 = 0, $6 = 0, $and42 = 0, $tobool43 = 0, $7 = 0, $and49 = 0, $tobool50 = 0, $side54 = 0, $8 = 0, $and56 = 0, $tobool57 = 0, $and65 = 0, $tobool66 = 0, $and73 = 0, $tobool74 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $defined = $0 + 60 | 0;
+ $1 = HEAP8[$defined] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $defined2 = $0 + 100 | 0;
+ $2 = HEAP8[$defined2] | 0;
+ $tobool3 = $2 << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $side = $0 + 65 | 0;
+ $3 = HEAP8[$side] | 0;
+ $conv = $3 & 255;
+ $and = $conv & 8;
+ $tobool6 = ($and | 0) == 0;
+ if ($tobool6) {
+ label = 5;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 5:
+ $side10 = $0 + 105 | 0;
+ $4 = HEAP8[$side10] | 0;
+ $and12 = $4 & 8;
+ $tobool13 = $and12 << 24 >> 24 == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 6:
+ $cmp = $3 << 24 >> 24 == $4 << 24 >> 24;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $and29 = $conv & 5;
+ $tobool30 = ($and29 | 0) == 0;
+ if ($tobool30) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ _selfRight($edges, $ind, $cnt, $sizex, $sizey, $sinfo);
+ label = 20;
+ break;
+ case 9:
+ $5 = HEAP8[$side] | 0;
+ $conv34 = $5 & 255;
+ $and35 = $conv34 & 8;
+ $tobool36 = ($and35 | 0) == 0;
+ if ($tobool36) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $side40 = $0 + 105 | 0;
+ $6 = HEAP8[$side40] | 0;
+ $and42 = $6 & 8;
+ $tobool43 = $and42 << 24 >> 24 == 0;
+ if ($tobool43) {
+ label = 15;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $7 = HEAP8[$side] | 0;
+ $and49 = $7 & 2;
+ $tobool50 = $and49 << 24 >> 24 == 0;
+ if ($tobool50) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $side54 = $0 + 105 | 0;
+ $8 = HEAP8[$side54] | 0;
+ $and56 = $8 & 2;
+ $tobool57 = $and56 << 24 >> 24 == 0;
+ if ($tobool57) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _selfTop($edges, $ind, $cnt, $sizex, $sizey, $sinfo);
+ label = 20;
+ break;
+ case 14:
+ _selfLeft($edges, $ind, $cnt, $sizex, $sizey, $sinfo);
+ label = 20;
+ break;
+ case 15:
+ $and65 = $conv34 & 4;
+ $tobool66 = ($and65 | 0) == 0;
+ if ($tobool66) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ _selfTop($edges, $ind, $cnt, $sizex, $sizey, $sinfo);
+ label = 20;
+ break;
+ case 17:
+ $and73 = $conv34 & 1;
+ $tobool74 = ($and73 | 0) == 0;
+ if ($tobool74) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ _selfBottom($edges, $ind, $cnt, $sizex, $sizey, $sinfo);
+ label = 20;
+ break;
+ case 19:
+ ___assert_func(96712, 1114, 164128, 137288);
+ case 20:
+ return;
+ }
+}
+function _pointfof805($agg_result, $x, $y) {
+ $agg_result = $agg_result | 0;
+ $x = +$x;
+ $y = +$y;
+ HEAPF64[$agg_result >> 3] = $x;
+ HEAPF64[$agg_result + 8 >> 3] = $y;
+ return;
+}
+function _place_portlabel($e, $head_p) {
+ $e = $e | 0;
+ $head_p = $head_p | 0;
+ var $c = 0, $tmp = 0, $tmp46 = 0, $edge_type = 0, $0 = 0, $cmp = 0, $tobool = 0, $head_label = 0, $tail_label = 0, $cond_in = 0, $cond = 0, $call = 0, $list = 0, $1 = 0, $sflag = 0, $2 = 0, $tobool7 = 0, $pe_sroa_0_0__idx26 = 0, $pe_sroa_0_0_copyload27 = 0.0, $pe_sroa_1_8__idx34 = 0, $pe_sroa_1_8_copyload35 = 0.0, $list9 = 0, $3 = 0, $pf_sroa_0_0__idx12 = 0, $pf_sroa_0_0_copyload13 = 0.0, $pf_sroa_1_8__idx19 = 0, $pf_sroa_1_8_copyload20 = 0.0, $list11 = 0, $4 = 0, $pe_sroa_1_8__idx32 = 0, $pe_sroa_0_0__idx24 = 0, $pe_sroa_1_8_copyload33 = 0.0, $pe_sroa_0_0_copyload25 = 0.0, $5 = 0, $6 = 0, $arrayidx15_1 = 0, $7 = 0, $arrayidx17_1 = 0, $8 = 0, $9 = 0, $arrayidx15_2 = 0, $10 = 0, $arrayidx17_2 = 0, $11 = 0, $12 = 0, $arrayidx15_3 = 0, $13 = 0, $arrayidx17_3 = 0, $14 = 0, $15 = 0, $arraydecay = 0, $pf_sroa_0_0__idx10 = 0, $pf_sroa_0_0_copyload11 = 0.0, $pf_sroa_1_8__idx17 = 0, $pf_sroa_1_8_copyload18 = 0.0, $size = 0, $16 = 0, $sub = 0, $list20 = 0, $17 = 0, $arrayidx21 = 0, $eflag = 0, $18 = 0, $tobool22 = 0, $pe_sroa_0_0__idx22 = 0, $pe_sroa_0_0_copyload23 = 0.0, $pe_sroa_1_8__idx30 = 0, $pe_sroa_1_8_copyload31 = 0.0, $size24 = 0, $19 = 0, $sub25 = 0, $list26 = 0, $20 = 0, $pf_sroa_0_0__idx8 = 0, $pf_sroa_0_0_copyload9 = 0.0, $pf_sroa_1_8__idx15 = 0, $pf_sroa_1_8_copyload16 = 0.0, $size29 = 0, $21 = 0, $sub30 = 0, $list31 = 0, $22 = 0, $pe_sroa_1_8__idx29 = 0, $pe_sroa_0_0__idx = 0, $pe_sroa_1_8_copyload = 0.0, $pe_sroa_0_0_copyload = 0.0, $23 = 0, $add = 0, $24 = 0, $arrayidx41 = 0, $25 = 0, $26 = 0, $arrayidx37_1 = 0, $27 = 0, $add_1 = 0, $28 = 0, $arrayidx41_1 = 0, $29 = 0, $30 = 0, $arrayidx37_2 = 0, $31 = 0, $add_2 = 0, $32 = 0, $arrayidx41_2 = 0, $33 = 0, $34 = 0, $arrayidx37_3 = 0, $35 = 0, $add_3 = 0, $36 = 0, $arrayidx41_3 = 0, $37 = 0, $38 = 0, $arraydecay45 = 0, $pf_sroa_0_0__idx = 0, $pf_sroa_0_0_copyload = 0.0, $pf_sroa_1_8__idx14 = 0, $pf_sroa_1_8_copyload = 0.0, $pe_sroa_1_0 = 0.0, $pe_sroa_0_0 = 0.0, $pf_sroa_1_0 = 0.0, $pf_sroa_0_0 = 0.0, $sub50 = 0.0, $sub52 = 0.0, $call53 = 0.0, $39 = 0, $40 = 0, $call54 = 0.0, $div = 0.0, $mul = 0.0, $add55 = 0.0, $41 = 0, $call56 = 0.0, $mul57 = 0.0, $call59 = 0.0, $mul60 = 0.0, $add61 = 0.0, $x62 = 0, $call64 = 0.0, $mul65 = 0.0, $add66 = 0.0, $y68 = 0, $set = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 96 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $c = __stackBase__ | 0;
+ $tmp = __stackBase__ + 64 | 0;
+ $tmp46 = __stackBase__ + 80 | 0;
+ $edge_type = $e + 128 | 0;
+ $0 = HEAP8[$edge_type] | 0;
+ $cmp = $0 << 24 >> 24 == 6;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tobool = $head_p << 24 >> 24 == 0;
+ $head_label = $e + 116 | 0;
+ $tail_label = $e + 120 | 0;
+ $cond_in = $tobool ? $tail_label : $head_label;
+ $cond = HEAP32[$cond_in >> 2] | 0;
+ $call = _getsplinepoints($e) | 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $list = $call | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $sflag = $1 + 8 | 0;
+ $2 = HEAP32[$sflag >> 2] | 0;
+ $tobool7 = ($2 | 0) == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $pe_sroa_0_0__idx26 = $1 + 16 | 0;
+ $pe_sroa_0_0_copyload27 = +HEAPF64[$pe_sroa_0_0__idx26 >> 3];
+ $pe_sroa_1_8__idx34 = $1 + 24 | 0;
+ $pe_sroa_1_8_copyload35 = +HEAPF64[$pe_sroa_1_8__idx34 >> 3];
+ $list9 = $1 | 0;
+ $3 = HEAP32[$list9 >> 2] | 0;
+ $pf_sroa_0_0__idx12 = $3 | 0;
+ $pf_sroa_0_0_copyload13 = +HEAPF64[$pf_sroa_0_0__idx12 >> 3];
+ $pf_sroa_1_8__idx19 = $3 + 8 | 0;
+ $pf_sroa_1_8_copyload20 = +HEAPF64[$pf_sroa_1_8__idx19 >> 3];
+ $pf_sroa_0_0 = $pf_sroa_0_0_copyload13;
+ $pf_sroa_1_0 = $pf_sroa_1_8_copyload20;
+ $pe_sroa_0_0 = $pe_sroa_0_0_copyload27;
+ $pe_sroa_1_0 = $pe_sroa_1_8_copyload35;
+ label = 10;
+ break;
+ case 6:
+ $list11 = $1 | 0;
+ $4 = HEAP32[$list11 >> 2] | 0;
+ $pe_sroa_1_8__idx32 = $4 + 8 | 0;
+ $pe_sroa_0_0__idx24 = $4 | 0;
+ $pe_sroa_1_8_copyload33 = +HEAPF64[$pe_sroa_1_8__idx32 >> 3];
+ $pe_sroa_0_0_copyload25 = +HEAPF64[$pe_sroa_0_0__idx24 >> 3];
+ $5 = $c;
+ $6 = $4;
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ $arrayidx15_1 = $c + 16 | 0;
+ $7 = HEAP32[$list11 >> 2] | 0;
+ $arrayidx17_1 = $7 + 16 | 0;
+ $8 = $arrayidx15_1;
+ $9 = $arrayidx17_1;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $arrayidx15_2 = $c + 32 | 0;
+ $10 = HEAP32[$list11 >> 2] | 0;
+ $arrayidx17_2 = $10 + 32 | 0;
+ $11 = $arrayidx15_2;
+ $12 = $arrayidx17_2;
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ $arrayidx15_3 = $c + 48 | 0;
+ $13 = HEAP32[$list11 >> 2] | 0;
+ $arrayidx17_3 = $13 + 48 | 0;
+ $14 = $arrayidx15_3;
+ $15 = $arrayidx17_3;
+ HEAP32[$14 >> 2] = HEAP32[$15 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$15 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$15 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$15 + 12 >> 2] | 0;
+ $arraydecay = $c | 0;
+ _Bezier($tmp, $arraydecay, 3, .1, 0, 0);
+ $pf_sroa_0_0__idx10 = $tmp | 0;
+ $pf_sroa_0_0_copyload11 = +HEAPF64[$pf_sroa_0_0__idx10 >> 3];
+ $pf_sroa_1_8__idx17 = $tmp + 8 | 0;
+ $pf_sroa_1_8_copyload18 = +HEAPF64[$pf_sroa_1_8__idx17 >> 3];
+ $pf_sroa_0_0 = $pf_sroa_0_0_copyload11;
+ $pf_sroa_1_0 = $pf_sroa_1_8_copyload18;
+ $pe_sroa_0_0 = $pe_sroa_0_0_copyload25;
+ $pe_sroa_1_0 = $pe_sroa_1_8_copyload33;
+ label = 10;
+ break;
+ case 7:
+ $size = $call + 4 | 0;
+ $16 = HEAP32[$size >> 2] | 0;
+ $sub = $16 - 1 | 0;
+ $list20 = $call | 0;
+ $17 = HEAP32[$list20 >> 2] | 0;
+ $arrayidx21 = $17 + ($sub * 48 & -1) | 0;
+ $eflag = $17 + ($sub * 48 & -1) + 12 | 0;
+ $18 = HEAP32[$eflag >> 2] | 0;
+ $tobool22 = ($18 | 0) == 0;
+ if ($tobool22) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $pe_sroa_0_0__idx22 = $17 + ($sub * 48 & -1) + 32 | 0;
+ $pe_sroa_0_0_copyload23 = +HEAPF64[$pe_sroa_0_0__idx22 >> 3];
+ $pe_sroa_1_8__idx30 = $17 + ($sub * 48 & -1) + 40 | 0;
+ $pe_sroa_1_8_copyload31 = +HEAPF64[$pe_sroa_1_8__idx30 >> 3];
+ $size24 = $17 + ($sub * 48 & -1) + 4 | 0;
+ $19 = HEAP32[$size24 >> 2] | 0;
+ $sub25 = $19 - 1 | 0;
+ $list26 = $arrayidx21 | 0;
+ $20 = HEAP32[$list26 >> 2] | 0;
+ $pf_sroa_0_0__idx8 = $20 + ($sub25 << 4) | 0;
+ $pf_sroa_0_0_copyload9 = +HEAPF64[$pf_sroa_0_0__idx8 >> 3];
+ $pf_sroa_1_8__idx15 = $20 + ($sub25 << 4) + 8 | 0;
+ $pf_sroa_1_8_copyload16 = +HEAPF64[$pf_sroa_1_8__idx15 >> 3];
+ $pf_sroa_0_0 = $pf_sroa_0_0_copyload9;
+ $pf_sroa_1_0 = $pf_sroa_1_8_copyload16;
+ $pe_sroa_0_0 = $pe_sroa_0_0_copyload23;
+ $pe_sroa_1_0 = $pe_sroa_1_8_copyload31;
+ label = 10;
+ break;
+ case 9:
+ $size29 = $17 + ($sub * 48 & -1) + 4 | 0;
+ $21 = HEAP32[$size29 >> 2] | 0;
+ $sub30 = $21 - 1 | 0;
+ $list31 = $arrayidx21 | 0;
+ $22 = HEAP32[$list31 >> 2] | 0;
+ $pe_sroa_1_8__idx29 = $22 + ($sub30 << 4) + 8 | 0;
+ $pe_sroa_0_0__idx = $22 + ($sub30 << 4) | 0;
+ $pe_sroa_1_8_copyload = +HEAPF64[$pe_sroa_1_8__idx29 >> 3];
+ $pe_sroa_0_0_copyload = +HEAPF64[$pe_sroa_0_0__idx >> 3];
+ $23 = HEAP32[$size29 >> 2] | 0;
+ $add = $23 - 4 | 0;
+ $24 = HEAP32[$list31 >> 2] | 0;
+ $arrayidx41 = $24 + ($add << 4) | 0;
+ $25 = $c;
+ $26 = $arrayidx41;
+ HEAP32[$25 >> 2] = HEAP32[$26 >> 2] | 0;
+ HEAP32[$25 + 4 >> 2] = HEAP32[$26 + 4 >> 2] | 0;
+ HEAP32[$25 + 8 >> 2] = HEAP32[$26 + 8 >> 2] | 0;
+ HEAP32[$25 + 12 >> 2] = HEAP32[$26 + 12 >> 2] | 0;
+ $arrayidx37_1 = $c + 16 | 0;
+ $27 = HEAP32[$size29 >> 2] | 0;
+ $add_1 = $27 - 3 | 0;
+ $28 = HEAP32[$list31 >> 2] | 0;
+ $arrayidx41_1 = $28 + ($add_1 << 4) | 0;
+ $29 = $arrayidx37_1;
+ $30 = $arrayidx41_1;
+ HEAP32[$29 >> 2] = HEAP32[$30 >> 2] | 0;
+ HEAP32[$29 + 4 >> 2] = HEAP32[$30 + 4 >> 2] | 0;
+ HEAP32[$29 + 8 >> 2] = HEAP32[$30 + 8 >> 2] | 0;
+ HEAP32[$29 + 12 >> 2] = HEAP32[$30 + 12 >> 2] | 0;
+ $arrayidx37_2 = $c + 32 | 0;
+ $31 = HEAP32[$size29 >> 2] | 0;
+ $add_2 = $31 - 2 | 0;
+ $32 = HEAP32[$list31 >> 2] | 0;
+ $arrayidx41_2 = $32 + ($add_2 << 4) | 0;
+ $33 = $arrayidx37_2;
+ $34 = $arrayidx41_2;
+ HEAP32[$33 >> 2] = HEAP32[$34 >> 2] | 0;
+ HEAP32[$33 + 4 >> 2] = HEAP32[$34 + 4 >> 2] | 0;
+ HEAP32[$33 + 8 >> 2] = HEAP32[$34 + 8 >> 2] | 0;
+ HEAP32[$33 + 12 >> 2] = HEAP32[$34 + 12 >> 2] | 0;
+ $arrayidx37_3 = $c + 48 | 0;
+ $35 = HEAP32[$size29 >> 2] | 0;
+ $add_3 = $35 - 1 | 0;
+ $36 = HEAP32[$list31 >> 2] | 0;
+ $arrayidx41_3 = $36 + ($add_3 << 4) | 0;
+ $37 = $arrayidx37_3;
+ $38 = $arrayidx41_3;
+ HEAP32[$37 >> 2] = HEAP32[$38 >> 2] | 0;
+ HEAP32[$37 + 4 >> 2] = HEAP32[$38 + 4 >> 2] | 0;
+ HEAP32[$37 + 8 >> 2] = HEAP32[$38 + 8 >> 2] | 0;
+ HEAP32[$37 + 12 >> 2] = HEAP32[$38 + 12 >> 2] | 0;
+ $arraydecay45 = $c | 0;
+ _Bezier($tmp46, $arraydecay45, 3, .9, 0, 0);
+ $pf_sroa_0_0__idx = $tmp46 | 0;
+ $pf_sroa_0_0_copyload = +HEAPF64[$pf_sroa_0_0__idx >> 3];
+ $pf_sroa_1_8__idx14 = $tmp46 + 8 | 0;
+ $pf_sroa_1_8_copyload = +HEAPF64[$pf_sroa_1_8__idx14 >> 3];
+ $pf_sroa_0_0 = $pf_sroa_0_0_copyload;
+ $pf_sroa_1_0 = $pf_sroa_1_8_copyload;
+ $pe_sroa_0_0 = $pe_sroa_0_0_copyload;
+ $pe_sroa_1_0 = $pe_sroa_1_8_copyload;
+ label = 10;
+ break;
+ case 10:
+ $sub50 = $pf_sroa_1_0 - $pe_sroa_1_0;
+ $sub52 = $pf_sroa_0_0 - $pe_sroa_0_0;
+ $call53 = +Math_atan2(+$sub50, +$sub52);
+ $39 = $e | 0;
+ $40 = HEAP32[41930] | 0;
+ $call54 = +_late_double($39, $40, -25.0, -180.0);
+ $div = $call54 / 180.0;
+ $mul = $div * 3.141592653589793;
+ $add55 = $call53 + $mul;
+ $41 = HEAP32[41928] | 0;
+ $call56 = +_late_double($39, $41, 1.0, 0.0);
+ $mul57 = $call56 * 10.0;
+ $call59 = +Math_cos(+$add55);
+ $mul60 = $mul57 * $call59;
+ $add61 = $pe_sroa_0_0 + $mul60;
+ $x62 = $cond + 56 | 0;
+ HEAPF64[$x62 >> 3] = $add61;
+ $call64 = +Math_sin(+$add55);
+ $mul65 = $mul57 * $call64;
+ $add66 = $pe_sroa_1_0 + $mul65;
+ $y68 = $cond + 64 | 0;
+ HEAPF64[$y68 >> 3] = $add66;
+ $set = $cond + 81 | 0;
+ HEAP8[$set] = 1;
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _canontoken($str) {
+ $str = $str | 0;
+ var $call = 0, $0 = 0, $cmp = 0, $add1 = 0, $1 = 0, $call2 = 0, $tobool = 0, $2 = 0, $3 = 0, $tobool57 = 0, $4 = 0, $str_pn = 0, $q_08 = 0, $incdec_ptr9 = 0, $conv = 0, $call6 = 0, $tobool7 = 0, $call10 = 0, $conv11 = 0, $c_0 = 0, $incdec_ptr13 = 0, $5 = 0, $tobool5 = 0, $q_0_lcssa = 0, $6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _strlen($str | 0) | 0;
+ $0 = HEAP32[13352] | 0;
+ $cmp = ($call | 0) < ($0 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add1 = $call + 11 | 0;
+ HEAP32[13352] = $add1;
+ $1 = HEAP32[13350] | 0;
+ $call2 = _grealloc($1, $add1) | 0;
+ HEAP32[13350] = $call2;
+ $tobool = ($call2 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[13350] | 0;
+ $3 = HEAP8[$str] | 0;
+ $tobool57 = $3 << 24 >> 24 == 0;
+ if ($tobool57) {
+ $q_0_lcssa = $2;
+ label = 8;
+ break;
+ } else {
+ $q_08 = $2;
+ $str_pn = $str;
+ $4 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $incdec_ptr9 = $str_pn + 1 | 0;
+ $conv = $4 & 255;
+ $call6 = _isupper($conv | 0) | 0;
+ $tobool7 = ($call6 | 0) == 0;
+ if ($tobool7) {
+ $c_0 = $4;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call10 = _tolower($conv | 0) | 0;
+ $conv11 = $call10 & 255;
+ $c_0 = $conv11;
+ label = 7;
+ break;
+ case 7:
+ $incdec_ptr13 = $q_08 + 1 | 0;
+ HEAP8[$q_08] = $c_0;
+ $5 = HEAP8[$incdec_ptr9] | 0;
+ $tobool5 = $5 << 24 >> 24 == 0;
+ if ($tobool5) {
+ $q_0_lcssa = $incdec_ptr13;
+ label = 8;
+ break;
+ } else {
+ $q_08 = $incdec_ptr13;
+ $str_pn = $incdec_ptr9;
+ $4 = $5;
+ label = 5;
+ break;
+ }
+ case 8:
+ HEAP8[$q_0_lcssa] = 0;
+ $6 = HEAP32[13350] | 0;
+ $retval_0 = $6;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _colorxlate($str, $color, $target_type) {
+ $str = $str | 0;
+ $color = $color | 0;
+ $target_type = $target_type | 0;
+ var $fake = 0, $H = 0, $S = 0, $V = 0, $R = 0, $G = 0, $B = 0, $C = 0, $M = 0, $Y = 0, $K = 0, $r = 0, $g = 0, $b = 0, $a = 0, $type = 0, $str_addr_0 = 0, $0 = 0, $cmp = 0, $incdec_ptr = 0, $1 = 0, $cmp3 = 0, $call = 0, $cmp5 = 0, $2 = 0, $conv7 = 0.0, $div = 0.0, $3 = 0, $conv8 = 0.0, $div9 = 0.0, $4 = 0, $conv10 = 0.0, $div11 = 0.0, $5 = 0, $conv12 = 0.0, $div13 = 0.0, $6 = 0.0, $7 = 0.0, $8 = 0.0, $arrayidx = 0, $9 = 0.0, $arrayidx16 = 0, $10 = 0.0, $arrayidx19 = 0, $arrayidx22 = 0, $11 = 0, $conv24 = 0, $rgba = 0, $arrayidx26 = 0, $12 = 0, $conv27 = 0, $arrayidx30 = 0, $13 = 0, $conv31 = 0, $arrayidx34 = 0, $14 = 0, $conv35 = 0, $arrayidx38 = 0, $15 = 0, $conv40 = 0.0, $div41 = 0.0, $16 = 0, $conv42 = 0.0, $div43 = 0.0, $17 = 0, $conv44 = 0.0, $div45 = 0.0, $18 = 0.0, $19 = 0.0, $conv46 = 0, $mul = 0, $conv47 = 0, $cmyk = 0, $arrayidx49 = 0, $20 = 0.0, $conv50 = 0, $mul51 = 0, $conv52 = 0, $arrayidx55 = 0, $21 = 0.0, $conv56 = 0, $mul57 = 0, $conv58 = 0, $arrayidx61 = 0, $22 = 0.0, $conv62 = 0, $mul63 = 0, $conv64 = 0, $arrayidx67 = 0, $23 = 0, $mul69 = 0, $div70 = 0, $rrggbbaa = 0, $arrayidx72 = 0, $24 = 0, $mul73 = 0, $div74 = 0, $arrayidx77 = 0, $25 = 0, $mul78 = 0, $div79 = 0, $arrayidx82 = 0, $26 = 0, $27 = 0, $mul83 = 0, $div84 = 0, $arrayidx87 = 0, $28 = 0, $conv89 = 0.0, $div90 = 0.0, $arrayidx92 = 0, $29 = 0, $conv93 = 0.0, $div94 = 0.0, $arrayidx97 = 0, $30 = 0, $conv98 = 0.0, $div99 = 0.0, $arrayidx102 = 0, $31 = 0, $conv103 = 0.0, $div104 = 0.0, $arrayidx107 = 0, $_pr = 0, $32 = 0, $cmp111 = 0, $conv110 = 0, $isdigittmp = 0, $isdigit = 0, $call116 = 0, $33 = 0, $cmp117 = 0, $add120 = 0, $34 = 0, $call121 = 0, $tobool122 = 0, $35 = 0, $p_0 = 0, $q_0 = 0, $incdec_ptr126 = 0, $36 = 0, $c_0 = 0, $incdec_ptr133 = 0, $37 = 0, $call134 = 0, $cmp135 = 0, $38 = 0.0, $cmp138 = 0, $cond = 0.0, $cmp140 = 0, $cond151 = 0.0, $39 = 0.0, $cmp152 = 0, $cond157 = 0.0, $cmp158 = 0, $cond169 = 0.0, $40 = 0.0, $cmp170 = 0, $cond175 = 0.0, $cmp176 = 0, $cond187 = 0.0, $41 = 0.0, $arrayidx191 = 0, $42 = 0.0, $arrayidx194 = 0, $43 = 0.0, $arrayidx197 = 0, $arrayidx200 = 0, $44 = 0.0, $45 = 0.0, $46 = 0.0, $mul202 = 0.0, $conv203 = 0, $conv204 = 0, $rgba206 = 0, $arrayidx207 = 0, $47 = 0.0, $mul208 = 0.0, $conv209 = 0, $conv210 = 0, $arrayidx213 = 0, $48 = 0.0, $mul214 = 0.0, $conv215 = 0, $conv216 = 0, $arrayidx219 = 0, $arrayidx222 = 0, $49 = 0.0, $50 = 0.0, $51 = 0.0, $52 = 0.0, $53 = 0.0, $54 = 0.0, $conv224 = 0, $mul225 = 0, $conv226 = 0, $cmyk228 = 0, $arrayidx229 = 0, $55 = 0.0, $conv230 = 0, $mul231 = 0, $conv232 = 0, $arrayidx235 = 0, $56 = 0.0, $conv236 = 0, $mul237 = 0, $conv238 = 0, $arrayidx241 = 0, $57 = 0.0, $conv242 = 0, $mul243 = 0, $conv244 = 0, $arrayidx247 = 0, $58 = 0.0, $59 = 0.0, $60 = 0.0, $mul249 = 0.0, $conv250 = 0, $rrggbbaa252 = 0, $arrayidx253 = 0, $61 = 0.0, $mul254 = 0.0, $conv255 = 0, $arrayidx258 = 0, $62 = 0.0, $mul259 = 0.0, $conv260 = 0, $arrayidx263 = 0, $63 = 0, $arrayidx266 = 0, $64 = 0.0, $65 = 0.0, $66 = 0.0, $arrayidx270 = 0, $67 = 0.0, $arrayidx273 = 0, $68 = 0.0, $arrayidx276 = 0, $arrayidx279 = 0, $call285 = 0, $name = 0, $tobool287 = 0, $69 = 0, $cmp290 = 0, $name293 = 0, $70 = 0, $71 = 0, $72 = 0, $cmp299 = 0, $call304 = 0, $tobool305 = 0, $73 = 0, $call307 = 0, $74 = 0, $_pr99 = 0, $75 = 0, $cmp309 = 0, $h = 0, $76 = 0, $conv313 = 0.0, $div314 = 0.0, $arrayidx317 = 0, $77 = 0, $s = 0, $78 = 0, $conv318 = 0.0, $div319 = 0.0, $arrayidx322 = 0, $79 = 0, $v = 0, $80 = 0, $conv323 = 0.0, $div324 = 0.0, $arrayidx327 = 0, $81 = 0, $a328 = 0, $82 = 0, $conv329 = 0.0, $div330 = 0.0, $arrayidx333 = 0, $r335 = 0, $83 = 0, $rgba337 = 0, $arrayidx338 = 0, $84 = 0, $g339 = 0, $85 = 0, $arrayidx342 = 0, $86 = 0, $b343 = 0, $87 = 0, $arrayidx346 = 0, $88 = 0, $a347 = 0, $89 = 0, $arrayidx350 = 0, $r352 = 0, $90 = 0, $conv353 = 0, $conv354 = 0.0, $div355 = 0.0, $91 = 0, $g356 = 0, $92 = 0, $conv357 = 0, $conv358 = 0.0, $div359 = 0.0, $93 = 0, $b360 = 0, $94 = 0, $conv361 = 0, $conv362 = 0.0, $div363 = 0.0, $95 = 0.0, $96 = 0.0, $97 = 0.0, $conv364 = 0, $mul365 = 0, $conv366 = 0, $cmyk368 = 0, $arrayidx369 = 0, $98 = 0.0, $conv370 = 0, $mul371 = 0, $conv372 = 0, $arrayidx375 = 0, $99 = 0.0, $conv376 = 0, $mul377 = 0, $conv378 = 0, $arrayidx381 = 0, $100 = 0.0, $conv382 = 0, $mul383 = 0, $conv384 = 0, $arrayidx387 = 0, $r389 = 0, $101 = 0, $conv390 = 0, $mul391 = 0, $div392 = 0, $rrggbbaa394 = 0, $arrayidx395 = 0, $102 = 0, $g396 = 0, $103 = 0, $conv397 = 0, $mul398 = 0, $div399 = 0, $arrayidx402 = 0, $104 = 0, $b403 = 0, $105 = 0, $conv404 = 0, $mul405 = 0, $div406 = 0, $arrayidx409 = 0, $106 = 0, $107 = 0, $a410 = 0, $108 = 0, $conv411 = 0, $mul412 = 0, $div413 = 0, $arrayidx416 = 0, $r418 = 0, $109 = 0, $conv419 = 0, $conv420 = 0.0, $div421 = 0.0, $arrayidx424 = 0, $110 = 0, $g425 = 0, $111 = 0, $conv426 = 0, $conv427 = 0.0, $div428 = 0.0, $arrayidx431 = 0, $112 = 0, $b432 = 0, $113 = 0, $conv433 = 0, $conv434 = 0.0, $div435 = 0.0, $arrayidx438 = 0, $114 = 0, $a439 = 0, $115 = 0, $conv440 = 0, $conv441 = 0.0, $div442 = 0.0, $arrayidx445 = 0, $arrayidx462 = 0, $116 = 0, $rgba465 = 0, $arrayidx466 = 0, $arrayidx469 = 0, $arrayidx472 = 0, $arrayidx475 = 0, $117 = 0, $rrggbbaa491 = 0, $arrayidx492 = 0, $118 = 0, $arrayidx495 = 0, $arrayidx498 = 0, $arrayidx501 = 0, $arrayidx514 = 0, $119 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $fake = __stackBase__ | 0;
+ $H = __stackBase__ + 16 | 0;
+ $S = __stackBase__ + 24 | 0;
+ $V = __stackBase__ + 32 | 0;
+ $R = __stackBase__ + 40 | 0;
+ $G = __stackBase__ + 48 | 0;
+ $B = __stackBase__ + 56 | 0;
+ $C = __stackBase__ + 64 | 0;
+ $M = __stackBase__ + 72 | 0;
+ $Y = __stackBase__ + 80 | 0;
+ $K = __stackBase__ + 88 | 0;
+ $r = __stackBase__ + 96 | 0;
+ $g = __stackBase__ + 104 | 0;
+ $b = __stackBase__ + 112 | 0;
+ $a = __stackBase__ + 120 | 0;
+ $type = $color + 32 | 0;
+ HEAP32[$type >> 2] = $target_type;
+ $str_addr_0 = $str;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[$str_addr_0] | 0;
+ $cmp = $0 << 24 >> 24 == 32;
+ $incdec_ptr = $str_addr_0 + 1 | 0;
+ if ($cmp) {
+ $str_addr_0 = $incdec_ptr;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAP32[$a >> 2] = 255;
+ $1 = HEAP8[$str_addr_0] | 0;
+ $cmp3 = $1 << 24 >> 24 == 35;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ $32 = $1;
+ label = 13;
+ break;
+ }
+ case 5:
+ $call = _sscanf($str_addr_0 | 0, 96400, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $r, HEAP32[tempInt + 8 >> 2] = $g, HEAP32[tempInt + 16 >> 2] = $b, HEAP32[tempInt + 24 >> 2] = $a, tempInt) | 0) | 0;
+ $cmp5 = ($call | 0) > 2;
+ if ($cmp5) {
+ label = 6;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 6:
+ if (($target_type | 0) == 0) {
+ label = 7;
+ break;
+ } else if (($target_type | 0) == 1) {
+ label = 8;
+ break;
+ } else if (($target_type | 0) == 3) {
+ label = 9;
+ break;
+ } else if (($target_type | 0) == 2) {
+ label = 10;
+ break;
+ } else if (($target_type | 0) == 4) {
+ label = 11;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 47;
+ break;
+ }
+ case 7:
+ $2 = HEAP32[$r >> 2] | 0;
+ $conv7 = +($2 >>> 0 >>> 0);
+ $div = $conv7 / 255.0;
+ HEAPF64[$R >> 3] = $div;
+ $3 = HEAP32[$g >> 2] | 0;
+ $conv8 = +($3 >>> 0 >>> 0);
+ $div9 = $conv8 / 255.0;
+ HEAPF64[$G >> 3] = $div9;
+ $4 = HEAP32[$b >> 2] | 0;
+ $conv10 = +($4 >>> 0 >>> 0);
+ $div11 = $conv10 / 255.0;
+ HEAPF64[$B >> 3] = $div11;
+ $5 = HEAP32[$a >> 2] | 0;
+ $conv12 = +($5 >>> 0 >>> 0);
+ $div13 = $conv12 / 255.0;
+ $6 = +HEAPF64[$R >> 3];
+ $7 = +HEAPF64[$G >> 3];
+ _rgb2hsv($6, $7, $div11, $H, $S, $V);
+ $8 = +HEAPF64[$H >> 3];
+ $arrayidx = $color | 0;
+ HEAPF64[$arrayidx >> 3] = $8;
+ $9 = +HEAPF64[$S >> 3];
+ $arrayidx16 = $color + 8 | 0;
+ HEAPF64[$arrayidx16 >> 3] = $9;
+ $10 = +HEAPF64[$V >> 3];
+ $arrayidx19 = $color + 16 | 0;
+ HEAPF64[$arrayidx19 >> 3] = $10;
+ $arrayidx22 = $color + 24 | 0;
+ HEAPF64[$arrayidx22 >> 3] = $div13;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 8:
+ $11 = HEAP32[$r >> 2] | 0;
+ $conv24 = $11 & 255;
+ $rgba = $color;
+ $arrayidx26 = $color;
+ HEAP8[$arrayidx26] = $conv24;
+ $12 = HEAP32[$g >> 2] | 0;
+ $conv27 = $12 & 255;
+ $arrayidx30 = $rgba + 1 | 0;
+ HEAP8[$arrayidx30] = $conv27;
+ $13 = HEAP32[$b >> 2] | 0;
+ $conv31 = $13 & 255;
+ $arrayidx34 = $rgba + 2 | 0;
+ HEAP8[$arrayidx34] = $conv31;
+ $14 = HEAP32[$a >> 2] | 0;
+ $conv35 = $14 & 255;
+ $arrayidx38 = $rgba + 3 | 0;
+ HEAP8[$arrayidx38] = $conv35;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 9:
+ $15 = HEAP32[$r >> 2] | 0;
+ $conv40 = +($15 >>> 0 >>> 0);
+ $div41 = $conv40 / 255.0;
+ HEAPF64[$R >> 3] = $div41;
+ $16 = HEAP32[$g >> 2] | 0;
+ $conv42 = +($16 >>> 0 >>> 0);
+ $div43 = $conv42 / 255.0;
+ HEAPF64[$G >> 3] = $div43;
+ $17 = HEAP32[$b >> 2] | 0;
+ $conv44 = +($17 >>> 0 >>> 0);
+ $div45 = $conv44 / 255.0;
+ HEAPF64[$B >> 3] = $div45;
+ $18 = +HEAPF64[$R >> 3];
+ _rgb2cmyk($18, $div43, $div45, $C, $M, $Y, $K);
+ $19 = +HEAPF64[$C >> 3];
+ $conv46 = ~~$19;
+ $mul = $conv46 * 255 & -1;
+ $conv47 = $mul & 255;
+ $cmyk = $color;
+ $arrayidx49 = $color;
+ HEAP8[$arrayidx49] = $conv47;
+ $20 = +HEAPF64[$M >> 3];
+ $conv50 = ~~$20;
+ $mul51 = $conv50 * 255 & -1;
+ $conv52 = $mul51 & 255;
+ $arrayidx55 = $cmyk + 1 | 0;
+ HEAP8[$arrayidx55] = $conv52;
+ $21 = +HEAPF64[$Y >> 3];
+ $conv56 = ~~$21;
+ $mul57 = $conv56 * 255 & -1;
+ $conv58 = $mul57 & 255;
+ $arrayidx61 = $cmyk + 2 | 0;
+ HEAP8[$arrayidx61] = $conv58;
+ $22 = +HEAPF64[$K >> 3];
+ $conv62 = ~~$22;
+ $mul63 = $conv62 * 255 & -1;
+ $conv64 = $mul63 & 255;
+ $arrayidx67 = $cmyk + 3 | 0;
+ HEAP8[$arrayidx67] = $conv64;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 10:
+ $23 = HEAP32[$r >> 2] | 0;
+ $mul69 = $23 * 65535 & -1;
+ $div70 = ($mul69 >>> 0) / 255 >>> 0;
+ $rrggbbaa = $color;
+ $arrayidx72 = $color;
+ HEAP32[$arrayidx72 >> 2] = $div70;
+ $24 = HEAP32[$g >> 2] | 0;
+ $mul73 = $24 * 65535 & -1;
+ $div74 = ($mul73 >>> 0) / 255 >>> 0;
+ $arrayidx77 = $rrggbbaa + 4 | 0;
+ HEAP32[$arrayidx77 >> 2] = $div74;
+ $25 = HEAP32[$b >> 2] | 0;
+ $mul78 = $25 * 65535 & -1;
+ $div79 = ($mul78 >>> 0) / 255 >>> 0;
+ $arrayidx82 = $color + 8 | 0;
+ $26 = $arrayidx82;
+ HEAP32[$26 >> 2] = $div79;
+ $27 = HEAP32[$a >> 2] | 0;
+ $mul83 = $27 * 65535 & -1;
+ $div84 = ($mul83 >>> 0) / 255 >>> 0;
+ $arrayidx87 = $rrggbbaa + 12 | 0;
+ HEAP32[$arrayidx87 >> 2] = $div84;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 11:
+ $28 = HEAP32[$r >> 2] | 0;
+ $conv89 = +($28 >>> 0 >>> 0);
+ $div90 = $conv89 / 255.0;
+ $arrayidx92 = $color | 0;
+ HEAPF64[$arrayidx92 >> 3] = $div90;
+ $29 = HEAP32[$g >> 2] | 0;
+ $conv93 = +($29 >>> 0 >>> 0);
+ $div94 = $conv93 / 255.0;
+ $arrayidx97 = $color + 8 | 0;
+ HEAPF64[$arrayidx97 >> 3] = $div94;
+ $30 = HEAP32[$b >> 2] | 0;
+ $conv98 = +($30 >>> 0 >>> 0);
+ $div99 = $conv98 / 255.0;
+ $arrayidx102 = $color + 16 | 0;
+ HEAPF64[$arrayidx102 >> 3] = $div99;
+ $31 = HEAP32[$a >> 2] | 0;
+ $conv103 = +($31 >>> 0 >>> 0);
+ $div104 = $conv103 / 255.0;
+ $arrayidx107 = $color + 24 | 0;
+ HEAPF64[$arrayidx107 >> 3] = $div104;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 12:
+ $_pr = HEAP8[$str_addr_0] | 0;
+ $32 = $_pr;
+ label = 13;
+ break;
+ case 13:
+ $cmp111 = $32 << 24 >> 24 == 46;
+ if ($cmp111) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $conv110 = $32 & 255;
+ $isdigittmp = $conv110 - 48 | 0;
+ $isdigit = $isdigittmp >>> 0 < 10;
+ if ($isdigit) {
+ label = 15;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 15:
+ $call116 = _strlen($str_addr_0 | 0) | 0;
+ $33 = HEAP32[5820] | 0;
+ $cmp117 = ($call116 | 0) < ($33 | 0);
+ if ($cmp117) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $add120 = $call116 + 11 | 0;
+ HEAP32[5820] = $add120;
+ $34 = HEAP32[5818] | 0;
+ $call121 = _grealloc($34, $add120) | 0;
+ HEAP32[5818] = $call121;
+ $tobool122 = ($call121 | 0) == 0;
+ if ($tobool122) {
+ $retval_0 = -1;
+ label = 47;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $35 = HEAP32[5818] | 0;
+ $q_0 = $35;
+ $p_0 = $str_addr_0;
+ label = 18;
+ break;
+ case 18:
+ $incdec_ptr126 = $p_0 + 1 | 0;
+ $36 = HEAP8[$p_0] | 0;
+ if (($36 << 24 >> 24 | 0) == 44) {
+ label = 19;
+ break;
+ } else if (($36 << 24 >> 24 | 0) == 0) {
+ label = 21;
+ break;
+ } else {
+ $c_0 = $36;
+ label = 20;
+ break;
+ }
+ case 19:
+ $c_0 = 32;
+ label = 20;
+ break;
+ case 20:
+ $incdec_ptr133 = $q_0 + 1 | 0;
+ HEAP8[$q_0] = $c_0;
+ $q_0 = $incdec_ptr133;
+ $p_0 = $incdec_ptr126;
+ label = 18;
+ break;
+ case 21:
+ HEAP8[$q_0] = 0;
+ $37 = HEAP32[5818] | 0;
+ $call134 = _sscanf($37 | 0, 137064, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $H, HEAP32[tempInt + 8 >> 2] = $S, HEAP32[tempInt + 16 >> 2] = $V, tempInt) | 0) | 0;
+ $cmp135 = ($call134 | 0) == 3;
+ if ($cmp135) {
+ label = 22;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 22:
+ $38 = +HEAPF64[$H >> 3];
+ $cmp138 = $38 < 1.0;
+ $cond = $cmp138 ? $38 : 1.0;
+ $cmp140 = $cond > 0.0;
+ $cond151 = $cmp140 ? $cond : 0.0;
+ HEAPF64[$H >> 3] = $cond151;
+ $39 = +HEAPF64[$S >> 3];
+ $cmp152 = $39 < 1.0;
+ $cond157 = $cmp152 ? $39 : 1.0;
+ $cmp158 = $cond157 > 0.0;
+ $cond169 = $cmp158 ? $cond157 : 0.0;
+ HEAPF64[$S >> 3] = $cond169;
+ $40 = +HEAPF64[$V >> 3];
+ $cmp170 = $40 < 1.0;
+ $cond175 = $cmp170 ? $40 : 1.0;
+ $cmp176 = $cond175 > 0.0;
+ $cond187 = $cmp176 ? $cond175 : 0.0;
+ HEAPF64[$V >> 3] = $cond187;
+ if (($target_type | 0) == 0) {
+ label = 23;
+ break;
+ } else if (($target_type | 0) == 1) {
+ label = 24;
+ break;
+ } else if (($target_type | 0) == 3) {
+ label = 25;
+ break;
+ } else if (($target_type | 0) == 2) {
+ label = 26;
+ break;
+ } else if (($target_type | 0) == 4) {
+ label = 27;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 47;
+ break;
+ }
+ case 23:
+ $41 = +HEAPF64[$H >> 3];
+ $arrayidx191 = $color | 0;
+ HEAPF64[$arrayidx191 >> 3] = $41;
+ $42 = +HEAPF64[$S >> 3];
+ $arrayidx194 = $color + 8 | 0;
+ HEAPF64[$arrayidx194 >> 3] = $42;
+ $43 = +HEAPF64[$V >> 3];
+ $arrayidx197 = $color + 16 | 0;
+ HEAPF64[$arrayidx197 >> 3] = $43;
+ $arrayidx200 = $color + 24 | 0;
+ HEAPF64[$arrayidx200 >> 3] = 1.0;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 24:
+ $44 = +HEAPF64[$H >> 3];
+ $45 = +HEAPF64[$S >> 3];
+ _hsv2rgb($44, $45, $cond187, $R, $G, $B);
+ $46 = +HEAPF64[$R >> 3];
+ $mul202 = $46 * 255.0;
+ $conv203 = ~~$mul202;
+ $conv204 = $conv203 & 255;
+ $rgba206 = $color;
+ $arrayidx207 = $color;
+ HEAP8[$arrayidx207] = $conv204;
+ $47 = +HEAPF64[$G >> 3];
+ $mul208 = $47 * 255.0;
+ $conv209 = ~~$mul208;
+ $conv210 = $conv209 & 255;
+ $arrayidx213 = $rgba206 + 1 | 0;
+ HEAP8[$arrayidx213] = $conv210;
+ $48 = +HEAPF64[$B >> 3];
+ $mul214 = $48 * 255.0;
+ $conv215 = ~~$mul214;
+ $conv216 = $conv215 & 255;
+ $arrayidx219 = $rgba206 + 2 | 0;
+ HEAP8[$arrayidx219] = $conv216;
+ $arrayidx222 = $rgba206 + 3 | 0;
+ HEAP8[$arrayidx222] = -1;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 25:
+ $49 = +HEAPF64[$H >> 3];
+ $50 = +HEAPF64[$S >> 3];
+ _hsv2rgb($49, $50, $cond187, $R, $G, $B);
+ $51 = +HEAPF64[$R >> 3];
+ $52 = +HEAPF64[$G >> 3];
+ $53 = +HEAPF64[$B >> 3];
+ _rgb2cmyk($51, $52, $53, $C, $M, $Y, $K);
+ $54 = +HEAPF64[$C >> 3];
+ $conv224 = ~~$54;
+ $mul225 = $conv224 * 255 & -1;
+ $conv226 = $mul225 & 255;
+ $cmyk228 = $color;
+ $arrayidx229 = $color;
+ HEAP8[$arrayidx229] = $conv226;
+ $55 = +HEAPF64[$M >> 3];
+ $conv230 = ~~$55;
+ $mul231 = $conv230 * 255 & -1;
+ $conv232 = $mul231 & 255;
+ $arrayidx235 = $cmyk228 + 1 | 0;
+ HEAP8[$arrayidx235] = $conv232;
+ $56 = +HEAPF64[$Y >> 3];
+ $conv236 = ~~$56;
+ $mul237 = $conv236 * 255 & -1;
+ $conv238 = $mul237 & 255;
+ $arrayidx241 = $cmyk228 + 2 | 0;
+ HEAP8[$arrayidx241] = $conv238;
+ $57 = +HEAPF64[$K >> 3];
+ $conv242 = ~~$57;
+ $mul243 = $conv242 * 255 & -1;
+ $conv244 = $mul243 & 255;
+ $arrayidx247 = $cmyk228 + 3 | 0;
+ HEAP8[$arrayidx247] = $conv244;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 26:
+ $58 = +HEAPF64[$H >> 3];
+ $59 = +HEAPF64[$S >> 3];
+ _hsv2rgb($58, $59, $cond187, $R, $G, $B);
+ $60 = +HEAPF64[$R >> 3];
+ $mul249 = $60 * 65535.0;
+ $conv250 = ~~$mul249;
+ $rrggbbaa252 = $color;
+ $arrayidx253 = $color;
+ HEAP32[$arrayidx253 >> 2] = $conv250;
+ $61 = +HEAPF64[$G >> 3];
+ $mul254 = $61 * 65535.0;
+ $conv255 = ~~$mul254;
+ $arrayidx258 = $rrggbbaa252 + 4 | 0;
+ HEAP32[$arrayidx258 >> 2] = $conv255;
+ $62 = +HEAPF64[$B >> 3];
+ $mul259 = $62 * 65535.0;
+ $conv260 = ~~$mul259;
+ $arrayidx263 = $color + 8 | 0;
+ $63 = $arrayidx263;
+ HEAP32[$63 >> 2] = $conv260;
+ $arrayidx266 = $rrggbbaa252 + 12 | 0;
+ HEAP32[$arrayidx266 >> 2] = 65535;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 27:
+ $64 = +HEAPF64[$H >> 3];
+ $65 = +HEAPF64[$S >> 3];
+ _hsv2rgb($64, $65, $cond187, $R, $G, $B);
+ $66 = +HEAPF64[$R >> 3];
+ $arrayidx270 = $color | 0;
+ HEAPF64[$arrayidx270 >> 3] = $66;
+ $67 = +HEAPF64[$G >> 3];
+ $arrayidx273 = $color + 8 | 0;
+ HEAPF64[$arrayidx273 >> 3] = $67;
+ $68 = +HEAPF64[$B >> 3];
+ $arrayidx276 = $color + 16 | 0;
+ HEAPF64[$arrayidx276 >> 3] = $68;
+ $arrayidx279 = $color + 24 | 0;
+ HEAPF64[$arrayidx279 >> 3] = 1.0;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 28:
+ $call285 = _resolveColor($str_addr_0) | 0;
+ $name = $fake | 0;
+ HEAP32[$name >> 2] = $call285;
+ $tobool287 = ($call285 | 0) == 0;
+ if ($tobool287) {
+ $retval_0 = -1;
+ label = 47;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $69 = HEAP32[5816] | 0;
+ $cmp290 = ($69 | 0) == 0;
+ if ($cmp290) {
+ label = 32;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $name293 = $69 | 0;
+ $70 = HEAP32[$name293 >> 2] | 0;
+ $71 = HEAP8[$70] | 0;
+ $72 = HEAP8[$call285] | 0;
+ $cmp299 = $71 << 24 >> 24 == $72 << 24 >> 24;
+ if ($cmp299) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ $call304 = _strcmp($70 | 0, $call285 | 0) | 0;
+ $tobool305 = ($call304 | 0) == 0;
+ if ($tobool305) {
+ label = 33;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $73 = $fake;
+ $call307 = _bsearch($73 | 0, 23296, 2491, 12, 564) | 0;
+ $74 = $call307;
+ HEAP32[5816] = $74;
+ $75 = $74;
+ label = 34;
+ break;
+ case 33:
+ $_pr99 = HEAP32[5816] | 0;
+ $75 = $_pr99;
+ label = 34;
+ break;
+ case 34:
+ $cmp309 = ($75 | 0) == 0;
+ if ($cmp309) {
+ label = 41;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ if (($target_type | 0) == 0) {
+ label = 36;
+ break;
+ } else if (($target_type | 0) == 1) {
+ label = 37;
+ break;
+ } else if (($target_type | 0) == 3) {
+ label = 38;
+ break;
+ } else if (($target_type | 0) == 2) {
+ label = 39;
+ break;
+ } else if (($target_type | 0) == 4) {
+ label = 40;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 47;
+ break;
+ }
+ case 36:
+ $h = $75 + 4 | 0;
+ $76 = HEAP8[$h] | 0;
+ $conv313 = +(($76 & 255) >>> 0);
+ $div314 = $conv313 / 255.0;
+ $arrayidx317 = $color | 0;
+ HEAPF64[$arrayidx317 >> 3] = $div314;
+ $77 = HEAP32[5816] | 0;
+ $s = $77 + 5 | 0;
+ $78 = HEAP8[$s] | 0;
+ $conv318 = +(($78 & 255) >>> 0);
+ $div319 = $conv318 / 255.0;
+ $arrayidx322 = $color + 8 | 0;
+ HEAPF64[$arrayidx322 >> 3] = $div319;
+ $79 = HEAP32[5816] | 0;
+ $v = $79 + 6 | 0;
+ $80 = HEAP8[$v] | 0;
+ $conv323 = +(($80 & 255) >>> 0);
+ $div324 = $conv323 / 255.0;
+ $arrayidx327 = $color + 16 | 0;
+ HEAPF64[$arrayidx327 >> 3] = $div324;
+ $81 = HEAP32[5816] | 0;
+ $a328 = $81 + 10 | 0;
+ $82 = HEAP8[$a328] | 0;
+ $conv329 = +(($82 & 255) >>> 0);
+ $div330 = $conv329 / 255.0;
+ $arrayidx333 = $color + 24 | 0;
+ HEAPF64[$arrayidx333 >> 3] = $div330;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 37:
+ $r335 = $75 + 7 | 0;
+ $83 = HEAP8[$r335] | 0;
+ $rgba337 = $color;
+ $arrayidx338 = $color;
+ HEAP8[$arrayidx338] = $83;
+ $84 = HEAP32[5816] | 0;
+ $g339 = $84 + 8 | 0;
+ $85 = HEAP8[$g339] | 0;
+ $arrayidx342 = $rgba337 + 1 | 0;
+ HEAP8[$arrayidx342] = $85;
+ $86 = HEAP32[5816] | 0;
+ $b343 = $86 + 9 | 0;
+ $87 = HEAP8[$b343] | 0;
+ $arrayidx346 = $rgba337 + 2 | 0;
+ HEAP8[$arrayidx346] = $87;
+ $88 = HEAP32[5816] | 0;
+ $a347 = $88 + 10 | 0;
+ $89 = HEAP8[$a347] | 0;
+ $arrayidx350 = $rgba337 + 3 | 0;
+ HEAP8[$arrayidx350] = $89;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 38:
+ $r352 = $75 + 7 | 0;
+ $90 = HEAP8[$r352] | 0;
+ $conv353 = $90 & 255;
+ $conv354 = +($conv353 | 0);
+ $div355 = $conv354 / 255.0;
+ HEAPF64[$R >> 3] = $div355;
+ $91 = HEAP32[5816] | 0;
+ $g356 = $91 + 8 | 0;
+ $92 = HEAP8[$g356] | 0;
+ $conv357 = $92 & 255;
+ $conv358 = +($conv357 | 0);
+ $div359 = $conv358 / 255.0;
+ HEAPF64[$G >> 3] = $div359;
+ $93 = HEAP32[5816] | 0;
+ $b360 = $93 + 9 | 0;
+ $94 = HEAP8[$b360] | 0;
+ $conv361 = $94 & 255;
+ $conv362 = +($conv361 | 0);
+ $div363 = $conv362 / 255.0;
+ HEAPF64[$B >> 3] = $div363;
+ $95 = +HEAPF64[$R >> 3];
+ $96 = +HEAPF64[$G >> 3];
+ _rgb2cmyk($95, $96, $div363, $C, $M, $Y, $K);
+ $97 = +HEAPF64[$C >> 3];
+ $conv364 = ~~$97;
+ $mul365 = $conv364 * 255 & -1;
+ $conv366 = $mul365 & 255;
+ $cmyk368 = $color;
+ $arrayidx369 = $color;
+ HEAP8[$arrayidx369] = $conv366;
+ $98 = +HEAPF64[$M >> 3];
+ $conv370 = ~~$98;
+ $mul371 = $conv370 * 255 & -1;
+ $conv372 = $mul371 & 255;
+ $arrayidx375 = $cmyk368 + 1 | 0;
+ HEAP8[$arrayidx375] = $conv372;
+ $99 = +HEAPF64[$Y >> 3];
+ $conv376 = ~~$99;
+ $mul377 = $conv376 * 255 & -1;
+ $conv378 = $mul377 & 255;
+ $arrayidx381 = $cmyk368 + 2 | 0;
+ HEAP8[$arrayidx381] = $conv378;
+ $100 = +HEAPF64[$K >> 3];
+ $conv382 = ~~$100;
+ $mul383 = $conv382 * 255 & -1;
+ $conv384 = $mul383 & 255;
+ $arrayidx387 = $cmyk368 + 3 | 0;
+ HEAP8[$arrayidx387] = $conv384;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 39:
+ $r389 = $75 + 7 | 0;
+ $101 = HEAP8[$r389] | 0;
+ $conv390 = $101 & 255;
+ $mul391 = $conv390 * 65535 & -1;
+ $div392 = ($mul391 >>> 0) / 255 >>> 0;
+ $rrggbbaa394 = $color;
+ $arrayidx395 = $color;
+ HEAP32[$arrayidx395 >> 2] = $div392;
+ $102 = HEAP32[5816] | 0;
+ $g396 = $102 + 8 | 0;
+ $103 = HEAP8[$g396] | 0;
+ $conv397 = $103 & 255;
+ $mul398 = $conv397 * 65535 & -1;
+ $div399 = ($mul398 >>> 0) / 255 >>> 0;
+ $arrayidx402 = $rrggbbaa394 + 4 | 0;
+ HEAP32[$arrayidx402 >> 2] = $div399;
+ $104 = HEAP32[5816] | 0;
+ $b403 = $104 + 9 | 0;
+ $105 = HEAP8[$b403] | 0;
+ $conv404 = $105 & 255;
+ $mul405 = $conv404 * 65535 & -1;
+ $div406 = ($mul405 >>> 0) / 255 >>> 0;
+ $arrayidx409 = $color + 8 | 0;
+ $106 = $arrayidx409;
+ HEAP32[$106 >> 2] = $div406;
+ $107 = HEAP32[5816] | 0;
+ $a410 = $107 + 10 | 0;
+ $108 = HEAP8[$a410] | 0;
+ $conv411 = $108 & 255;
+ $mul412 = $conv411 * 65535 & -1;
+ $div413 = ($mul412 >>> 0) / 255 >>> 0;
+ $arrayidx416 = $rrggbbaa394 + 12 | 0;
+ HEAP32[$arrayidx416 >> 2] = $div413;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 40:
+ $r418 = $75 + 7 | 0;
+ $109 = HEAP8[$r418] | 0;
+ $conv419 = $109 & 255;
+ $conv420 = +($conv419 | 0);
+ $div421 = $conv420 / 255.0;
+ $arrayidx424 = $color | 0;
+ HEAPF64[$arrayidx424 >> 3] = $div421;
+ $110 = HEAP32[5816] | 0;
+ $g425 = $110 + 8 | 0;
+ $111 = HEAP8[$g425] | 0;
+ $conv426 = $111 & 255;
+ $conv427 = +($conv426 | 0);
+ $div428 = $conv427 / 255.0;
+ $arrayidx431 = $color + 8 | 0;
+ HEAPF64[$arrayidx431 >> 3] = $div428;
+ $112 = HEAP32[5816] | 0;
+ $b432 = $112 + 9 | 0;
+ $113 = HEAP8[$b432] | 0;
+ $conv433 = $113 & 255;
+ $conv434 = +($conv433 | 0);
+ $div435 = $conv434 / 255.0;
+ $arrayidx438 = $color + 16 | 0;
+ HEAPF64[$arrayidx438 >> 3] = $div435;
+ $114 = HEAP32[5816] | 0;
+ $a439 = $114 + 10 | 0;
+ $115 = HEAP8[$a439] | 0;
+ $conv440 = $115 & 255;
+ $conv441 = +($conv440 | 0);
+ $div442 = $conv441 / 255.0;
+ $arrayidx445 = $color + 24 | 0;
+ HEAPF64[$arrayidx445 >> 3] = $div442;
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 41:
+ if (($target_type | 0) == 0) {
+ label = 42;
+ break;
+ } else if (($target_type | 0) == 1) {
+ label = 43;
+ break;
+ } else if (($target_type | 0) == 3) {
+ label = 44;
+ break;
+ } else if (($target_type | 0) == 2) {
+ label = 45;
+ break;
+ } else if (($target_type | 0) == 4) {
+ label = 46;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 47;
+ break;
+ }
+ case 42:
+ $arrayidx462 = $color + 24 | 0;
+ $116 = $color;
+ _memset($116 | 0, 0, 24);
+ HEAPF64[$arrayidx462 >> 3] = 1.0;
+ $retval_0 = 1;
+ label = 47;
+ break;
+ case 43:
+ $rgba465 = $color;
+ $arrayidx466 = $rgba465 + 2 | 0;
+ HEAP8[$arrayidx466] = 0;
+ $arrayidx469 = $rgba465 + 1 | 0;
+ HEAP8[$arrayidx469] = 0;
+ $arrayidx472 = $color;
+ HEAP8[$arrayidx472] = 0;
+ $arrayidx475 = $rgba465 + 3 | 0;
+ HEAP8[$arrayidx475] = -1;
+ $retval_0 = 1;
+ label = 47;
+ break;
+ case 44:
+ $117 = $color;
+ tempBigInt = 0;
+ HEAP8[$117] = tempBigInt & 255;
+ tempBigInt = tempBigInt >> 8;
+ HEAP8[$117 + 1 | 0] = tempBigInt & 255;
+ tempBigInt = tempBigInt >> 8;
+ HEAP8[$117 + 2 | 0] = tempBigInt & 255;
+ tempBigInt = tempBigInt >> 8;
+ HEAP8[$117 + 3 | 0] = tempBigInt & 255;
+ $retval_0 = 1;
+ label = 47;
+ break;
+ case 45:
+ $rrggbbaa491 = $color;
+ $arrayidx492 = $color + 8 | 0;
+ $118 = $arrayidx492;
+ HEAP32[$118 >> 2] = 0;
+ $arrayidx495 = $rrggbbaa491 + 4 | 0;
+ HEAP32[$arrayidx495 >> 2] = 0;
+ $arrayidx498 = $color;
+ HEAP32[$arrayidx498 >> 2] = 0;
+ $arrayidx501 = $rrggbbaa491 + 12 | 0;
+ HEAP32[$arrayidx501 >> 2] = 65535;
+ $retval_0 = 1;
+ label = 47;
+ break;
+ case 46:
+ $arrayidx514 = $color + 24 | 0;
+ $119 = $color;
+ _memset($119 | 0, 0, 24);
+ HEAPF64[$arrayidx514 >> 3] = 1.0;
+ $retval_0 = 1;
+ label = 47;
+ break;
+ case 47:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _getsplinepoints($e) {
+ $e = $e | 0;
+ var $spl5 = 0, $0 = 0, $cond6 = 0, $le_07 = 0, $edge_type = 0, $1 = 0, $cmp = 0, $to_orig = 0, $2 = 0, $spl = 0, $3 = 0, $cond = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $spl5 = $e + 24 | 0;
+ $0 = HEAP32[$spl5 >> 2] | 0;
+ $cond6 = ($0 | 0) == 0;
+ if ($cond6) {
+ $le_07 = $e;
+ label = 3;
+ break;
+ } else {
+ $4 = $0;
+ label = 6;
+ break;
+ }
+ case 3:
+ $edge_type = $le_07 + 128 | 0;
+ $1 = HEAP8[$edge_type] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $to_orig = $le_07 + 132 | 0;
+ $2 = HEAP32[$to_orig >> 2] | 0;
+ $spl = $2 + 24 | 0;
+ $3 = HEAP32[$spl >> 2] | 0;
+ $cond = ($3 | 0) == 0;
+ if ($cond) {
+ $le_07 = $2;
+ label = 3;
+ break;
+ } else {
+ $4 = $3;
+ label = 6;
+ break;
+ }
+ case 5:
+ _abort();
+ return 0;
+ return 0;
+ case 6:
+ return $4 | 0;
+ }
+ return 0;
+}
+function _setColorScheme($s) {
+ $s = $s | 0;
+ HEAP32[5822] = $s;
+ return;
+}
+function _rgb2hsv($r, $g, $b, $h, $s, $v) {
+ $r = +$r;
+ $g = +$g;
+ $b = +$b;
+ $h = $h | 0;
+ $s = $s | 0;
+ $v = $v | 0;
+ var $cmp = 0, $cond = 0.0, $cmp1 = 0, $r_cond = 0.0, $cmp11 = 0, $cond15 = 0.0, $cmp16 = 0, $cond25 = 0.0, $cmp26 = 0, $sub = 0.0, $div = 0.0, $cmp27 = 0, $sub29 = 0.0, $sub30 = 0.0, $div31 = 0.0, $sub32 = 0.0, $div34 = 0.0, $sub35 = 0.0, $div37 = 0.0, $cmp38 = 0, $sub40 = 0.0, $cmp41 = 0, $add = 0.0, $sub43 = 0.0, $cmp45 = 0, $add47 = 0.0, $sub48 = 0.0, $ht_0 = 0.0, $mul = 0.0, $cmp52 = 0, $add54 = 0.0, $st_047 = 0.0, $ht_1 = 0.0, $div57 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = $g < $b;
+ $cond = $cmp ? $g : $b;
+ $cmp1 = $cond > $r;
+ $r_cond = $cmp1 ? $r : $cond;
+ $cmp11 = $g > $b;
+ $cond15 = $cmp11 ? $g : $b;
+ $cmp16 = $cond15 < $r;
+ $cond25 = $cmp16 ? $r : $cond15;
+ $cmp26 = $cond25 > 0.0;
+ if ($cmp26) {
+ label = 3;
+ break;
+ } else {
+ $ht_1 = 0.0;
+ $st_047 = 0.0;
+ label = 12;
+ break;
+ }
+ case 3:
+ $sub = $cond25 - $r_cond;
+ $div = $sub / $cond25;
+ $cmp27 = $div > 0.0;
+ if ($cmp27) {
+ label = 4;
+ break;
+ } else {
+ $ht_1 = 0.0;
+ $st_047 = $div;
+ label = 12;
+ break;
+ }
+ case 4:
+ $sub29 = $cond25 - $r;
+ $sub30 = $cond25 - $r_cond;
+ $div31 = $sub29 / $sub30;
+ $sub32 = $cond25 - $g;
+ $div34 = $sub32 / $sub30;
+ $sub35 = $cond25 - $b;
+ $div37 = $sub35 / $sub30;
+ $cmp38 = $cond25 == $r;
+ if ($cmp38) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $sub40 = $div37 - $div34;
+ $ht_0 = $sub40;
+ label = 10;
+ break;
+ case 6:
+ $cmp41 = $cond25 == $g;
+ if ($cmp41) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $add = $div31 + 2.0;
+ $sub43 = $add - $div37;
+ $ht_0 = $sub43;
+ label = 10;
+ break;
+ case 8:
+ $cmp45 = $cond25 == $b;
+ if ($cmp45) {
+ label = 9;
+ break;
+ } else {
+ $ht_0 = 0.0;
+ label = 10;
+ break;
+ }
+ case 9:
+ $add47 = $div34 + 4.0;
+ $sub48 = $add47 - $div31;
+ $ht_0 = $sub48;
+ label = 10;
+ break;
+ case 10:
+ $mul = $ht_0 * 60.0;
+ $cmp52 = $mul < 0.0;
+ if ($cmp52) {
+ label = 11;
+ break;
+ } else {
+ $ht_1 = $mul;
+ $st_047 = $div;
+ label = 12;
+ break;
+ }
+ case 11:
+ $add54 = $mul + 360.0;
+ $ht_1 = $add54;
+ $st_047 = $div;
+ label = 12;
+ break;
+ case 12:
+ $div57 = $ht_1 / 360.0;
+ HEAPF64[$h >> 3] = $div57;
+ HEAPF64[$v >> 3] = $cond25;
+ HEAPF64[$s >> 3] = $st_047;
+ return;
+ }
+}
+function _rgb2cmyk($r, $g, $b, $c, $m, $y, $k) {
+ $r = +$r;
+ $g = +$g;
+ $b = +$b;
+ $c = $c | 0;
+ $m = $m | 0;
+ $y = $y | 0;
+ $k = $k | 0;
+ var $0 = 0.0, $1 = 0.0, $_ = 0.0, $2 = 0.0, $cond7 = 0.0;
+ HEAPF64[$c >> 3] = 1.0 - $r;
+ HEAPF64[$m >> 3] = 1.0 - $g;
+ HEAPF64[$y >> 3] = 1.0 - $b;
+ $0 = +HEAPF64[$c >> 3];
+ $1 = +HEAPF64[$m >> 3];
+ $_ = $0 < $1 ? $0 : $1;
+ HEAPF64[$k >> 3] = $_;
+ $2 = +HEAPF64[$y >> 3];
+ $cond7 = $2 < $_ ? $2 : $_;
+ HEAPF64[$k >> 3] = $cond7;
+ HEAPF64[$c >> 3] = +HEAPF64[$c >> 3] - $cond7;
+ HEAPF64[$m >> 3] = +HEAPF64[$m >> 3] - +HEAPF64[$k >> 3];
+ HEAPF64[$y >> 3] = +HEAPF64[$y >> 3] - +HEAPF64[$k >> 3];
+ return;
+}
+function _hsv2rgb($h, $s, $v, $r, $g, $b) {
+ $h = +$h;
+ $s = +$s;
+ $v = +$v;
+ $r = $r | 0;
+ $g = $g | 0;
+ $b = $b | 0;
+ var $cmp = 0, $cmp1 = 0, $h_op = 0.0, $mul = 0.0, $conv = 0, $conv3 = 0.0, $sub = 0.0, $sub4 = 0.0, $mul5 = 0.0, $mul6 = 0.0, $sub7 = 0.0, $mul8 = 0.0, $sub9 = 0.0, $mul10 = 0.0, $sub11 = 0.0, $mul12 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = $s > 0.0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAPF64[$r >> 3] = $v;
+ HEAPF64[$g >> 3] = $v;
+ HEAPF64[$b >> 3] = $v;
+ label = 11;
+ break;
+ case 4:
+ $cmp1 = $h < 1.0;
+ $h_op = $h * 6.0;
+ $mul = $cmp1 ? $h_op : 0.0;
+ $conv = ~~$mul;
+ $conv3 = +($conv | 0);
+ $sub = $mul - $conv3;
+ $sub4 = 1.0 - $s;
+ $mul5 = $sub4 * $v;
+ $mul6 = $sub * $s;
+ $sub7 = 1.0 - $mul6;
+ $mul8 = $sub7 * $v;
+ $sub9 = 1.0 - $sub;
+ $mul10 = $sub9 * $s;
+ $sub11 = 1.0 - $mul10;
+ $mul12 = $sub11 * $v;
+ if (($conv | 0) == 0) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 1) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 2) {
+ label = 7;
+ break;
+ } else if (($conv | 0) == 3) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 4) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 5:
+ HEAPF64[$r >> 3] = $v;
+ HEAPF64[$g >> 3] = $mul12;
+ HEAPF64[$b >> 3] = $mul5;
+ label = 11;
+ break;
+ case 6:
+ HEAPF64[$r >> 3] = $mul8;
+ HEAPF64[$g >> 3] = $v;
+ HEAPF64[$b >> 3] = $mul5;
+ label = 11;
+ break;
+ case 7:
+ HEAPF64[$r >> 3] = $mul5;
+ HEAPF64[$g >> 3] = $v;
+ HEAPF64[$b >> 3] = $mul12;
+ label = 11;
+ break;
+ case 8:
+ HEAPF64[$r >> 3] = $mul5;
+ HEAPF64[$g >> 3] = $mul8;
+ HEAPF64[$b >> 3] = $v;
+ label = 11;
+ break;
+ case 9:
+ HEAPF64[$r >> 3] = $mul12;
+ HEAPF64[$g >> 3] = $mul5;
+ HEAPF64[$b >> 3] = $v;
+ label = 11;
+ break;
+ case 10:
+ HEAPF64[$r >> 3] = $v;
+ HEAPF64[$g >> 3] = $mul5;
+ HEAPF64[$b >> 3] = $mul8;
+ label = 11;
+ break;
+ case 11:
+ return;
+ }
+}
+function _charsetOf($s) {
+ $s = $s | 0;
+ var $s_addr_0_ph = 0, $r_0_ph = 0, $s_addr_0 = 0, $0 = 0, $tobool = 0, $incdec_ptr = 0, $cmp = 0, $and = 0, $cmp3 = 0, $incdec_ptr6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $r_0_ph = 0;
+ $s_addr_0_ph = $s;
+ label = 3;
+ break;
+ case 3:
+ $s_addr_0 = $s_addr_0_ph;
+ label = 4;
+ break;
+ case 4:
+ $0 = HEAP8[$s_addr_0] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = $r_0_ph;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $incdec_ptr = $s_addr_0 + 1 | 0;
+ $cmp = ($0 & 255) < 127;
+ if ($cmp) {
+ $s_addr_0 = $incdec_ptr;
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $and = $0 & -4;
+ $cmp3 = $and << 24 >> 24 == -64;
+ $incdec_ptr6 = $s_addr_0 + 2 | 0;
+ if ($cmp3) {
+ $r_0_ph = 1;
+ $s_addr_0_ph = $incdec_ptr6;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 2;
+ label = 7;
+ break;
+ }
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _resolveColor($str) {
+ $str = $str | 0;
+ var $0 = 0, $cmp = 0, $add_ptr = 0, $call = 0, $tobool = 0, $cmp3 = 0, $or_cond = 0, $call7 = 0, $tobool8 = 0, $cmp12 = 0, $or_cond18 = 0, $call16 = 0, $tobool17 = 0, $cmp21 = 0, $call25 = 0, $tobool26 = 0, $1 = 0, $cmp29 = 0, $2 = 0, $tobool32 = 0, $3 = 0, $tobool34 = 0, $call36 = 0, $tobool37 = 0, $4 = 0, $add_ptr39 = 0, $call40 = 0, $add_ptr41 = 0, $call44 = 0, $tobool45 = 0, $add_ptr48 = 0, $add_ptr48_str = 0, $5 = 0, $tobool54 = 0, $6 = 0, $tobool57 = 0, $call59 = 0, $tobool60 = 0, $7 = 0, $call62 = 0, $s_0 = 0, $call66 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$str] | 0;
+ $cmp = $0 << 24 >> 24 == 98;
+ if ($cmp) {
+ $retval_0 = $str;
+ label = 20;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add_ptr = $str + 1 | 0;
+ $call = _strncmp($add_ptr | 0, 122072, 4) | 0;
+ $tobool = ($call | 0) == 0;
+ $cmp3 = $0 << 24 >> 24 == 119;
+ $or_cond = $tobool | $cmp3;
+ if ($or_cond) {
+ $retval_0 = $str;
+ label = 20;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call7 = _strncmp($add_ptr | 0, 122064, 4) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ $cmp12 = $0 << 24 >> 24 == 108;
+ $or_cond18 = $tobool8 | $cmp12;
+ if ($or_cond18) {
+ $retval_0 = $str;
+ label = 20;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call16 = _strncmp($add_ptr | 0, 122048, 8) | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ if ($tobool17) {
+ $retval_0 = $str;
+ label = 20;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp21 = $0 << 24 >> 24 == 47;
+ if ($cmp21) {
+ label = 7;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 7:
+ $call25 = _strchr($add_ptr | 0, 47) | 0;
+ $tobool26 = ($call25 | 0) == 0;
+ if ($tobool26) {
+ $s_0 = $add_ptr;
+ label = 19;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $1 = HEAP8[$add_ptr] | 0;
+ $cmp29 = $1 << 24 >> 24 == 47;
+ if ($cmp29) {
+ label = 9;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 9:
+ $2 = HEAP32[5822] | 0;
+ $tobool32 = ($2 | 0) == 0;
+ if ($tobool32) {
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $3 = HEAP8[$2] | 0;
+ $tobool34 = $3 << 24 >> 24 == 0;
+ if ($tobool34) {
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call36 = _strncasecmp(122040, $2, 3) | 0;
+ $tobool37 = ($call36 | 0) == 0;
+ if ($tobool37) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $4 = HEAP32[5822] | 0;
+ $add_ptr39 = $str + 2 | 0;
+ $call40 = _fullColor($4, $add_ptr39) | 0;
+ $s_0 = $call40;
+ label = 19;
+ break;
+ case 13:
+ $add_ptr41 = $str + 2 | 0;
+ $s_0 = $add_ptr41;
+ label = 19;
+ break;
+ case 14:
+ $call44 = _strncasecmp(122040, $add_ptr, 4) | 0;
+ $tobool45 = ($call44 | 0) == 0;
+ $add_ptr48 = $call25 + 1 | 0;
+ $add_ptr48_str = $tobool45 ? $add_ptr48 : $str;
+ $s_0 = $add_ptr48_str;
+ label = 19;
+ break;
+ case 15:
+ $5 = HEAP32[5822] | 0;
+ $tobool54 = ($5 | 0) == 0;
+ if ($tobool54) {
+ $s_0 = $str;
+ label = 19;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $6 = HEAP8[$5] | 0;
+ $tobool57 = $6 << 24 >> 24 == 0;
+ if ($tobool57) {
+ $s_0 = $str;
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $call59 = _strncasecmp(122040, $5, 3) | 0;
+ $tobool60 = ($call59 | 0) == 0;
+ if ($tobool60) {
+ $s_0 = $str;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $7 = HEAP32[5822] | 0;
+ $call62 = _fullColor($7, $str) | 0;
+ $s_0 = $call62;
+ label = 19;
+ break;
+ case 19:
+ $call66 = _canontoken($s_0) | 0;
+ $retval_0 = $call66;
+ label = 20;
+ break;
+ case 20:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _colorcmpf($p0, $p1) {
+ $p0 = $p0 | 0;
+ $p1 = $p1 | 0;
+ return _strcasecmp(HEAP32[$p0 >> 2] | 0, HEAP32[$p1 >> 2] | 0) | 0;
+}
+function _fullColor($prefix, $str) {
+ $prefix = $prefix | 0;
+ $str = $str | 0;
+ var $call = 0, $call1 = 0, $add = 0, $add2 = 0, $0 = 0, $cmp = 0, $add3 = 0, $1 = 0, $call4 = 0, $2 = 0, $call5 = 0, $3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _strlen($prefix | 0) | 0;
+ $call1 = _strlen($str | 0) | 0;
+ $add = $call1 + $call | 0;
+ $add2 = $add + 3 | 0;
+ $0 = HEAP32[4082] | 0;
+ $cmp = ($add2 | 0) < ($0 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add3 = $add + 13 | 0;
+ HEAP32[4082] = $add3;
+ $1 = HEAP32[4080] | 0;
+ $call4 = _grealloc($1, $add3) | 0;
+ HEAP32[4080] = $call4;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[4080] | 0;
+ $call5 = _sprintf($2 | 0, 122032, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $prefix, HEAP32[tempInt + 8 >> 2] = $str, tempInt) | 0) | 0;
+ $3 = HEAP32[4080] | 0;
+ STACKTOP = __stackBase__;
+ return $3 | 0;
+ }
+ return 0;
+}
+function _epsf_init($n) {
+ $n = $n | 0;
+ var $0 = 0, $call = 0, $call1 = 0, $tobool = 0, $call2 = 0, $tobool3 = 0, $w = 0, $1 = 0, $h = 0, $2 = 0, $conv = 0.0, $div = 0.0, $width = 0, $conv5 = 0.0, $div6 = 0.0, $height = 0, $call8 = 0, $shape_info = 0, $macro_id = 0, $3 = 0, $macro_id10 = 0, $x = 0, $4 = 0, $div11_neg = 0, $sub12 = 0, $offset = 0, $x13 = 0, $y = 0, $5 = 0, $div15_neg = 0, $sub16 = 0, $y18 = 0, $6 = 0, $name = 0, $7 = 0, $call19 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $n | 0;
+ $call = _agget($0, 122016) | 0;
+ $call1 = _safefile($call) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call2 = _user_init($call1) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $w = $call2 + 40 | 0;
+ $1 = HEAP32[$w >> 2] | 0;
+ $h = $call2 + 44 | 0;
+ $2 = HEAP32[$h >> 2] | 0;
+ $conv = +($1 | 0);
+ $div = $conv / 72.0;
+ $width = $n + 48 | 0;
+ HEAPF64[$width >> 3] = $div;
+ $conv5 = +($2 | 0);
+ $div6 = $conv5 / 72.0;
+ $height = $n + 56 | 0;
+ HEAPF64[$height >> 3] = $div6;
+ $call8 = _zmalloc(12) | 0;
+ $shape_info = $n + 28 | 0;
+ HEAP32[$shape_info >> 2] = $call8;
+ $macro_id = $call2 + 12 | 0;
+ $3 = HEAP32[$macro_id >> 2] | 0;
+ $macro_id10 = $call8;
+ HEAP32[$macro_id10 >> 2] = $3;
+ $x = $call2 + 32 | 0;
+ $4 = HEAP32[$x >> 2] | 0;
+ $div11_neg = ($1 | 0) / -2 & -1;
+ $sub12 = $div11_neg - $4 | 0;
+ $offset = $call8 + 4 | 0;
+ $x13 = $offset;
+ HEAP32[$x13 >> 2] = $sub12;
+ $y = $call2 + 36 | 0;
+ $5 = HEAP32[$y >> 2] | 0;
+ $div15_neg = ($2 | 0) / -2 & -1;
+ $sub16 = $div15_neg - $5 | 0;
+ $y18 = $call8 + 8 | 0;
+ $6 = $y18;
+ HEAP32[$6 >> 2] = $sub16;
+ label = 6;
+ break;
+ case 5:
+ $name = $n + 12 | 0;
+ $7 = HEAP32[$name >> 2] | 0;
+ $call19 = _agerr(0, 154488, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $7, tempInt) | 0) | 0;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _user_init($str) {
+ $str = $str | 0;
+ var $line = 0, $statbuf = 0, $lx = 0, $ly = 0, $ux = 0, $uy = 0, $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $searchf = 0, $4 = 0, $call1 = 0, $tobool2 = 0, $5 = 0, $call5 = 0, $tobool6 = 0, $arraydecay = 0, $call1024 = 0, $tobool1125 = 0, $call8 = 0, $must_inline_027 = 0, $saw_bb_026 = 0, $call13 = 0, $cmp = 0, $_saw_bb_0 = 0, $6 = 0, $cmp16 = 0, $call19 = 0, $tobool20 = 0, $must_inline_0_ = 0, $must_inline_1 = 0, $tobool23 = 0, $saw_bb_0_be = 0, $must_inline_0_be = 0, $call10 = 0, $tobool11 = 0, $extract_t32 = 0, $tobool25 = 0, $extract_t33 = 0, $must_inline_1_sink_off0 = 0, $saw_bb_2 = 0, $tobool28 = 0, $call30 = 0, $7 = 0, $8 = 0, $x = 0, $9 = 0, $10 = 0, $y = 0, $11 = 0, $12 = 0, $13 = 0, $sub = 0, $w = 0, $14 = 0, $15 = 0, $16 = 0, $sub31 = 0, $name = 0, $17 = 0, $18 = 0, $inc = 0, $macro_id = 0, $19 = 0, $call33 = 0, $call34 = 0, $st_size = 0, $20 = 0, $add = 0, $call35 = 0, $data = 0, $21 = 0, $call36 = 0, $22 = 0, $call38 = 0, $23 = 0, $arrayidx40 = 0, $24 = 0, $searchf41 = 0, $25 = 0, $call42 = 0, $26 = 0, $call45 = 0, $us_0 = 0, $call47 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1128 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $line = __stackBase__ | 0;
+ $statbuf = __stackBase__ + 1024 | 0;
+ $lx = __stackBase__ + 1096 | 0;
+ $ly = __stackBase__ + 1104 | 0;
+ $ux = __stackBase__ + 1112 | 0;
+ $uy = __stackBase__ + 1120 | 0;
+ $0 = HEAP32[41970] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[41978] | 0;
+ $2 = $1;
+ $call = _dtopen(167040, $2) | 0;
+ HEAP32[41970] = $call;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[41970] | 0;
+ $searchf = $3 | 0;
+ $4 = HEAP32[$searchf >> 2] | 0;
+ $call1 = FUNCTION_TABLE_iiii[$4 & 1023]($3, $str, 512) | 0;
+ $tobool2 = ($call1 | 0) == 0;
+ if ($tobool2) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = $call1;
+ $retval_0 = $5;
+ label = 18;
+ break;
+ case 6:
+ $call5 = _fopen($str | 0, 112224) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $arraydecay = $line | 0;
+ $call1024 = _fgets($arraydecay | 0, 1024, $call5 | 0) | 0;
+ $tobool1125 = ($call1024 | 0) == 0;
+ if ($tobool1125) {
+ label = 16;
+ break;
+ } else {
+ $saw_bb_026 = 0;
+ $must_inline_027 = 0;
+ label = 9;
+ break;
+ }
+ case 8:
+ $call8 = _agerr(0, 145840, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $str, tempInt) | 0) | 0;
+ $retval_0 = 0;
+ label = 18;
+ break;
+ case 9:
+ $call13 = _sscanf($arraydecay | 0, 142792, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $lx, HEAP32[tempInt + 8 >> 2] = $ly, HEAP32[tempInt + 16 >> 2] = $ux, HEAP32[tempInt + 24 >> 2] = $uy, tempInt) | 0) | 0;
+ $cmp = ($call13 | 0) == 4;
+ $_saw_bb_0 = $cmp ? 1 : $saw_bb_026;
+ $6 = HEAP8[$arraydecay] | 0;
+ $cmp16 = $6 << 24 >> 24 == 37;
+ if ($cmp16) {
+ $must_inline_1 = $must_inline_027;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call19 = _strstr($arraydecay | 0, 139264) | 0;
+ $tobool20 = ($call19 | 0) == 0;
+ $must_inline_0_ = $tobool20 ? $must_inline_027 : 1;
+ $must_inline_1 = $must_inline_0_;
+ label = 11;
+ break;
+ case 11:
+ $tobool23 = ($_saw_bb_0 | 0) == 0;
+ if ($tobool23) {
+ $must_inline_0_be = $must_inline_1;
+ $saw_bb_0_be = 0;
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $call10 = _fgets($arraydecay | 0, 1024, $call5 | 0) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ $extract_t32 = $must_inline_0_be & 255;
+ if ($tobool11) {
+ $saw_bb_2 = $saw_bb_0_be;
+ $must_inline_1_sink_off0 = $extract_t32;
+ label = 14;
+ break;
+ } else {
+ $saw_bb_026 = $saw_bb_0_be;
+ $must_inline_027 = $must_inline_0_be;
+ label = 9;
+ break;
+ }
+ case 13:
+ $tobool25 = ($must_inline_1 | 0) == 0;
+ $extract_t33 = $must_inline_1 & 255;
+ if ($tobool25) {
+ $must_inline_0_be = 0;
+ $saw_bb_0_be = $_saw_bb_0;
+ label = 12;
+ break;
+ } else {
+ $saw_bb_2 = $_saw_bb_0;
+ $must_inline_1_sink_off0 = $extract_t33;
+ label = 14;
+ break;
+ }
+ case 14:
+ $tobool28 = ($saw_bb_2 | 0) == 0;
+ if ($tobool28) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $call30 = _gmalloc(64) | 0;
+ $7 = $call30;
+ $8 = HEAP32[$lx >> 2] | 0;
+ $x = $call30 + 32 | 0;
+ $9 = $x;
+ HEAP32[$9 >> 2] = $8;
+ $10 = HEAP32[$ly >> 2] | 0;
+ $y = $call30 + 36 | 0;
+ $11 = $y;
+ HEAP32[$11 >> 2] = $10;
+ $12 = HEAP32[$ux >> 2] | 0;
+ $13 = HEAP32[$lx >> 2] | 0;
+ $sub = $12 - $13 | 0;
+ $w = $call30 + 40 | 0;
+ $14 = $w;
+ HEAP32[$14 >> 2] = $sub;
+ $15 = HEAP32[$uy >> 2] | 0;
+ $16 = HEAP32[$ly >> 2] | 0;
+ $sub31 = $15 - $16 | 0;
+ HEAP32[$11 >> 2] = $sub31;
+ $name = $call30 + 8 | 0;
+ $17 = $name;
+ HEAP32[$17 >> 2] = $str;
+ $18 = HEAP32[41624] | 0;
+ $inc = $18 + 1 | 0;
+ HEAP32[41624] = $inc;
+ $macro_id = $call30 + 12 | 0;
+ $19 = $macro_id;
+ HEAP32[$19 >> 2] = $18;
+ $call33 = _fileno($call5 | 0) | 0;
+ $call34 = _fstat($call33 | 0, $statbuf | 0) | 0;
+ $st_size = $statbuf + 28 | 0;
+ $20 = HEAP32[$st_size >> 2] | 0;
+ $add = $20 + 1 | 0;
+ $call35 = _gmalloc($add) | 0;
+ $data = $call30 + 52 | 0;
+ $21 = $data;
+ HEAP32[$21 >> 2] = $call35;
+ $call36 = _fseek($call5 | 0, 0, 0) | 0;
+ $22 = HEAP32[$st_size >> 2] | 0;
+ $call38 = _fread($call35 | 0, $22 | 0, 1, $call5 | 0) | 0;
+ $23 = HEAP32[$st_size >> 2] | 0;
+ $arrayidx40 = $call35 + $23 | 0;
+ HEAP8[$arrayidx40] = 0;
+ $24 = HEAP32[41970] | 0;
+ $searchf41 = $24 | 0;
+ $25 = HEAP32[$searchf41 >> 2] | 0;
+ $call42 = FUNCTION_TABLE_iiii[$25 & 1023]($24, $call30, 1) | 0;
+ $26 = $call30 + 16 | 0;
+ HEAP8[$26] = $must_inline_1_sink_off0;
+ $us_0 = $7;
+ label = 17;
+ break;
+ case 16:
+ $call45 = _agerr(0, 136488, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $str, tempInt) | 0) | 0;
+ $us_0 = 0;
+ label = 17;
+ break;
+ case 17:
+ $call47 = _fclose($call5 | 0) | 0;
+ $retval_0 = $us_0;
+ label = 18;
+ break;
+ case 18:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _epsf_free($n) {
+ $n = $n | 0;
+ var $shape_info = 0, $0 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $shape_info = $n + 28 | 0;
+ $0 = HEAP32[$shape_info >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _free($0);
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _cat_libfile($job, $arglib, $stdlib) {
+ $job = $job | 0;
+ $arglib = $arglib | 0;
+ $stdlib = $stdlib | 0;
+ var $tobool = 0, $use_stdlib_031 = 0, $i_030 = 0, $arrayidx = 0, $0 = 0, $tobool2 = 0, $1 = 0, $cmp = 0, $_use_stdlib_0 = 0, $inc = 0, $tobool1 = 0, $2 = 0, $tobool1026 = 0, $3 = 0, $4 = 0, $s_027 = 0, $call = 0, $call12 = 0, $incdec_ptr = 0, $5 = 0, $tobool10 = 0, $6 = 0, $cmp2024 = 0, $7 = 0, $8 = 0, $i_125 = 0, $9 = 0, $cmp24 = 0, $call28 = 0, $tobool29 = 0, $call31 = 0, $call32 = 0, $tobool33 = 0, $call3521 = 0, $tobool3622 = 0, $call3523 = 0, $call37 = 0, $call35 = 0, $tobool36 = 0, $call38 = 0, $call39 = 0, $call41 = 0, $inc45 = 0, $arrayidx19 = 0, $10 = 0, $cmp20 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($arglib | 0) != 0;
+ if ($tobool) {
+ $i_030 = 0;
+ $use_stdlib_031 = 1;
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $arrayidx = $arglib + ($i_030 << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool2 = ($0 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$0] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ $_use_stdlib_0 = $cmp ? 0 : $use_stdlib_031;
+ $inc = $i_030 + 1 | 0;
+ $tobool1 = $_use_stdlib_0 << 24 >> 24 == 0;
+ if ($tobool1) {
+ label = 8;
+ break;
+ } else {
+ $i_030 = $inc;
+ $use_stdlib_031 = $_use_stdlib_0;
+ label = 3;
+ break;
+ }
+ case 5:
+ $2 = HEAP32[$stdlib >> 2] | 0;
+ $tobool1026 = ($2 | 0) == 0;
+ if ($tobool1026) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = $job;
+ $s_027 = $stdlib;
+ $4 = $2;
+ label = 7;
+ break;
+ case 7:
+ $call = _gvputs($3, $4) | 0;
+ $call12 = _gvputs($3, 127256) | 0;
+ $incdec_ptr = $s_027 + 4 | 0;
+ $5 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool10 = ($5 | 0) == 0;
+ if ($tobool10) {
+ label = 8;
+ break;
+ } else {
+ $s_027 = $incdec_ptr;
+ $4 = $5;
+ label = 7;
+ break;
+ }
+ case 8:
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 9:
+ $6 = HEAP32[$arglib >> 2] | 0;
+ $cmp2024 = ($6 | 0) == 0;
+ if ($cmp2024) {
+ label = 20;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $7 = $job;
+ $i_125 = 0;
+ $8 = $6;
+ label = 11;
+ break;
+ case 11:
+ $9 = HEAP8[$8] | 0;
+ $cmp24 = $9 << 24 >> 24 == 0;
+ if ($cmp24) {
+ label = 19;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call28 = _safefile($8) | 0;
+ $tobool29 = ($call28 | 0) == 0;
+ if ($tobool29) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $call31 = _agerr(0, 117456, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $8, tempInt) | 0) | 0;
+ label = 19;
+ break;
+ case 14:
+ $call32 = _fopen($call28 | 0, 112224) | 0;
+ $tobool33 = ($call32 | 0) == 0;
+ if ($tobool33) {
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $call3521 = _Fgets($call32) | 0;
+ $tobool3622 = ($call3521 | 0) == 0;
+ if ($tobool3622) {
+ label = 17;
+ break;
+ } else {
+ $call3523 = $call3521;
+ label = 16;
+ break;
+ }
+ case 16:
+ $call37 = _gvputs($7, $call3523) | 0;
+ $call35 = _Fgets($call32) | 0;
+ $tobool36 = ($call35 | 0) == 0;
+ if ($tobool36) {
+ label = 17;
+ break;
+ } else {
+ $call3523 = $call35;
+ label = 16;
+ break;
+ }
+ case 17:
+ $call38 = _gvputs($7, 127256) | 0;
+ $call39 = _fclose($call32 | 0) | 0;
+ label = 19;
+ break;
+ case 18:
+ $call41 = _agerr(0, 107872, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call28, tempInt) | 0) | 0;
+ label = 19;
+ break;
+ case 19:
+ $inc45 = $i_125 + 1 | 0;
+ $arrayidx19 = $arglib + ($inc45 << 2) | 0;
+ $10 = HEAP32[$arrayidx19 >> 2] | 0;
+ $cmp20 = ($10 | 0) == 0;
+ if ($cmp20) {
+ label = 20;
+ break;
+ } else {
+ $i_125 = $inc45;
+ $8 = $10;
+ label = 11;
+ break;
+ }
+ case 20:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _epsf_emit_body($job, $us) {
+ $job = $job | 0;
+ $us = $us | 0;
+ var $data = 0, $0 = 0, $1 = 0, $2 = 0, $p_0 = 0, $3 = 0, $arrayidx2 = 0, $4 = 0, $cmp4 = 0, $arrayidx7 = 0, $call = 0, $tobool8 = 0, $call10 = 0, $tobool11 = 0, $call14 = 0, $tobool15 = 0, $call18 = 0, $tobool19 = 0, $p_1 = 0, $5 = 0, $incdec_ptr = 0, $add_ptr = 0, $6 = 0, $cmp36 = 0, $add_ptr39 = 0, $7 = 0, $tobool40 = 0, $incdec_ptr42 = 0, $p_1_incdec_ptr42 = 0, $p_2 = 0, $8 = 0, $conv46 = 0, $call59 = 0, $incdec_ptr60 = 0, $add_ptr66 = 0, $9 = 0, $cmp68 = 0, $add_ptr71 = 0, $10 = 0, $tobool73 = 0, $incdec_ptr75 = 0, $p_2_incdec_ptr75 = 0, $p_3 = 0, $call78 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $data = $us + 52 | 0;
+ $0 = HEAP32[$data >> 2] | 0;
+ $1 = $job;
+ $2 = $job;
+ $p_0 = $0;
+ label = 3;
+ break;
+ case 3:
+ $3 = HEAP8[$p_0] | 0;
+ if (($3 << 24 >> 24 | 0) == 37) {
+ label = 4;
+ break;
+ } else if (($3 << 24 >> 24 | 0) == 0) {
+ label = 20;
+ break;
+ } else {
+ $p_2 = $p_0;
+ label = 14;
+ break;
+ }
+ case 4:
+ $arrayidx2 = $p_0 + 1 | 0;
+ $4 = HEAP8[$arrayidx2] | 0;
+ $cmp4 = $4 << 24 >> 24 == 37;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ $p_2 = $p_0;
+ label = 14;
+ break;
+ }
+ case 5:
+ $arrayidx7 = $p_0 + 2 | 0;
+ $call = _strncasecmp($arrayidx7, 103984, 3) | 0;
+ $tobool8 = ($call | 0) == 0;
+ if ($tobool8) {
+ $p_1 = $p_0;
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call10 = _strncasecmp($arrayidx7, 99792, 5) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ if ($tobool11) {
+ $p_1 = $p_0;
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call14 = _strncasecmp($arrayidx7, 95696, 3) | 0;
+ $tobool15 = ($call14 | 0) == 0;
+ if ($tobool15) {
+ $p_1 = $p_0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call18 = _strncasecmp($arrayidx7, 92288, 7) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ $p_1 = $p_0;
+ label = 9;
+ break;
+ } else {
+ $p_2 = $p_0;
+ label = 14;
+ break;
+ }
+ case 9:
+ $5 = HEAP8[$p_1] | 0;
+ if (($5 << 24 >> 24 | 0) == 13) {
+ label = 11;
+ break;
+ } else if (($5 << 24 >> 24 | 0) == 0 | ($5 << 24 >> 24 | 0) == 10) {
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $incdec_ptr = $p_1 + 1 | 0;
+ $p_1 = $incdec_ptr;
+ label = 9;
+ break;
+ case 11:
+ $add_ptr = $p_1 + 1 | 0;
+ $6 = HEAP8[$add_ptr] | 0;
+ $cmp36 = $6 << 24 >> 24 == 10;
+ if ($cmp36) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $add_ptr39 = $p_1 + 2 | 0;
+ $p_0 = $add_ptr39;
+ label = 3;
+ break;
+ case 13:
+ $7 = HEAP8[$p_1] | 0;
+ $tobool40 = $7 << 24 >> 24 == 0;
+ $incdec_ptr42 = $p_1 + 1 | 0;
+ $p_1_incdec_ptr42 = $tobool40 ? $p_1 : $incdec_ptr42;
+ $p_0 = $p_1_incdec_ptr42;
+ label = 3;
+ break;
+ case 14:
+ $8 = HEAP8[$p_2] | 0;
+ if (($8 << 24 >> 24 | 0) == 13) {
+ label = 16;
+ break;
+ } else if (($8 << 24 >> 24 | 0) == 0 | ($8 << 24 >> 24 | 0) == 10) {
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $conv46 = $8 << 24 >> 24;
+ $call59 = _gvputc($1, $conv46) | 0;
+ $incdec_ptr60 = $p_2 + 1 | 0;
+ $p_2 = $incdec_ptr60;
+ label = 14;
+ break;
+ case 16:
+ $add_ptr66 = $p_2 + 1 | 0;
+ $9 = HEAP8[$add_ptr66] | 0;
+ $cmp68 = $9 << 24 >> 24 == 10;
+ if ($cmp68) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $add_ptr71 = $p_2 + 2 | 0;
+ $p_3 = $add_ptr71;
+ label = 19;
+ break;
+ case 18:
+ $10 = HEAP8[$p_2] | 0;
+ $tobool73 = $10 << 24 >> 24 == 0;
+ $incdec_ptr75 = $p_2 + 1 | 0;
+ $p_2_incdec_ptr75 = $tobool73 ? $p_2 : $incdec_ptr75;
+ $p_3 = $p_2_incdec_ptr75;
+ label = 19;
+ break;
+ case 19:
+ $call78 = _gvputc($2, 10) | 0;
+ $p_0 = $p_3;
+ label = 3;
+ break;
+ case 20:
+ return;
+ }
+}
+function _epsf_define($job) {
+ $job = $job | 0;
+ var $0 = 0, $tobool = 0, $searchf = 0, $1 = 0, $call = 0, $tobool110 = 0, $2 = 0, $us_012_in = 0, $3 = 0, $4 = 0, $tobool2 = 0, $us_012 = 0, $macro_id = 0, $5 = 0, $6 = 0, $call5 = 0, $call6 = 0, $call7 = 0, $7 = 0, $searchf8 = 0, $8 = 0, $call9 = 0, $tobool1 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41970] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, 0, 128) | 0;
+ $tobool110 = ($call | 0) == 0;
+ if ($tobool110) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = $job;
+ $us_012_in = $call;
+ label = 5;
+ break;
+ case 5:
+ $3 = $us_012_in + 16 | 0;
+ $4 = HEAP8[$3] | 0;
+ $tobool2 = $4 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $us_012 = $us_012_in;
+ $macro_id = $us_012_in + 12 | 0;
+ $5 = $macro_id;
+ $6 = HEAP32[$5 >> 2] | 0;
+ _gvprintf($2, 162408, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $6, tempInt) | 0);
+ $call5 = _gvputs($2, 158856) | 0;
+ _epsf_emit_body($job, $us_012);
+ $call6 = _gvputs($2, 155336) | 0;
+ $call7 = _gvputs($2, 151944) | 0;
+ label = 7;
+ break;
+ case 7:
+ $7 = HEAP32[41970] | 0;
+ $searchf8 = $7 | 0;
+ $8 = HEAP32[$searchf8 >> 2] | 0;
+ $call9 = FUNCTION_TABLE_iiii[$8 & 1023]($7, $us_012_in, 8) | 0;
+ $tobool1 = ($call9 | 0) == 0;
+ if ($tobool1) {
+ label = 8;
+ break;
+ } else {
+ $us_012_in = $call9;
+ label = 5;
+ break;
+ }
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _ps_string($ins, $latin) {
+ $ins = $ins | 0;
+ $latin = $latin | 0;
+ var $tobool = 0, $call = 0, $call1 = 0, $call3 = 0, $_b = 0, $call7 = 0, $base_0 = 0, $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $cmp11 = 0, $call12 = 0, $3 = 0, $incdec_ptr = 0, $s_0 = 0, $4 = 0, $5 = 0, $6 = 0, $cmp24 = 0, $call27 = 0, $7 = 0, $incdec_ptr31 = 0, $8 = 0, $9 = 0, $cmp33 = 0, $call36 = 0, $incdec_ptr40 = 0, $10 = 0, $11 = 0, $incdec_ptr41 = 0, $12 = 0, $13 = 0, $cmp43 = 0, $call46 = 0, $14 = 0, $incdec_ptr50 = 0, $cmp51 = 0, $15 = 0, $16 = 0, $cmp55 = 0, $call58 = 0, $17 = 0, $18 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($latin | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _utf8ToLatin1($ins) | 0;
+ $base_0 = $call;
+ label = 8;
+ break;
+ case 4:
+ $call1 = _charsetOf($ins) | 0;
+ if (($call1 | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($call1 | 0) == 2) {
+ label = 6;
+ break;
+ } else {
+ $base_0 = $ins;
+ label = 8;
+ break;
+ }
+ case 5:
+ $call3 = _utf8ToLatin1($ins) | 0;
+ $base_0 = $call3;
+ label = 8;
+ break;
+ case 6:
+ $_b = HEAP8[5560] | 0;
+ if ($_b) {
+ $base_0 = $ins;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call7 = _agerr(0, 148592, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ HEAP8[5560] = 1;
+ $base_0 = $ins;
+ label = 8;
+ break;
+ case 8:
+ $0 = HEAP32[1386] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ _agxbinit(5544, 0, 0);
+ label = 10;
+ break;
+ case 10:
+ $1 = HEAP32[1387] | 0;
+ $2 = HEAP32[1388] | 0;
+ $cmp11 = $1 >>> 0 < $2 >>> 0;
+ if ($cmp11) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call12 = _agxbmore(5544, 1) | 0;
+ label = 12;
+ break;
+ case 12:
+ $3 = HEAP32[1387] | 0;
+ $incdec_ptr = $3 + 1 | 0;
+ HEAP32[1387] = $incdec_ptr;
+ HEAP8[$3] = 40;
+ $s_0 = $base_0;
+ label = 13;
+ break;
+ case 13:
+ $4 = HEAP8[$s_0] | 0;
+ if (($4 << 24 >> 24 | 0) == 40 | ($4 << 24 >> 24 | 0) == 41 | ($4 << 24 >> 24 | 0) == 92) {
+ label = 14;
+ break;
+ } else if (($4 << 24 >> 24 | 0) == 0) {
+ label = 20;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 14:
+ $5 = HEAP32[1387] | 0;
+ $6 = HEAP32[1388] | 0;
+ $cmp24 = $5 >>> 0 < $6 >>> 0;
+ if ($cmp24) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $call27 = _agxbmore(5544, 1) | 0;
+ label = 16;
+ break;
+ case 16:
+ $7 = HEAP32[1387] | 0;
+ $incdec_ptr31 = $7 + 1 | 0;
+ HEAP32[1387] = $incdec_ptr31;
+ HEAP8[$7] = 92;
+ label = 17;
+ break;
+ case 17:
+ $8 = HEAP32[1387] | 0;
+ $9 = HEAP32[1388] | 0;
+ $cmp33 = $8 >>> 0 < $9 >>> 0;
+ if ($cmp33) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $call36 = _agxbmore(5544, 1) | 0;
+ label = 19;
+ break;
+ case 19:
+ $incdec_ptr40 = $s_0 + 1 | 0;
+ $10 = HEAP8[$s_0] | 0;
+ $11 = HEAP32[1387] | 0;
+ $incdec_ptr41 = $11 + 1 | 0;
+ HEAP32[1387] = $incdec_ptr41;
+ HEAP8[$11] = $10;
+ $s_0 = $incdec_ptr40;
+ label = 13;
+ break;
+ case 20:
+ $12 = HEAP32[1387] | 0;
+ $13 = HEAP32[1388] | 0;
+ $cmp43 = $12 >>> 0 < $13 >>> 0;
+ if ($cmp43) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $call46 = _agxbmore(5544, 1) | 0;
+ label = 22;
+ break;
+ case 22:
+ $14 = HEAP32[1387] | 0;
+ $incdec_ptr50 = $14 + 1 | 0;
+ HEAP32[1387] = $incdec_ptr50;
+ HEAP8[$14] = 41;
+ $cmp51 = ($base_0 | 0) == ($ins | 0);
+ if ($cmp51) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ _free($base_0);
+ label = 24;
+ break;
+ case 24:
+ $15 = HEAP32[1387] | 0;
+ $16 = HEAP32[1388] | 0;
+ $cmp55 = $15 >>> 0 < $16 >>> 0;
+ if ($cmp55) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $call58 = _agxbmore(5544, 1) | 0;
+ label = 26;
+ break;
+ case 26:
+ $17 = HEAP32[1387] | 0;
+ HEAP8[$17] = 0;
+ $18 = HEAP32[1386] | 0;
+ HEAP32[1387] = $18;
+ STACKTOP = __stackBase__;
+ return $18 | 0;
+ }
+ return 0;
+}
+function _ps_image_free($dict, $p, $disc) {
+ $dict = $dict | 0;
+ $p = $p | 0;
+ $disc = $disc | 0;
+ _free(HEAP32[$p + 52 >> 2] | 0);
+ return;
+}
+function _graph_init($g, $use_rankdir) {
+ $g = $g | 0;
+ $use_rankdir = $use_rankdir | 0;
+ var $xf = 0, $call = 0, $0 = 0, $drawing = 0, $1 = 0, $call1 = 0, $tobool = 0, $call2 = 0, $tobool3 = 0, $p_0 = 0, $2 = 0, $call4 = 0, $add5 = 0, $call6 = 0, $3 = 0, $call8 = 0, $4 = 0, $call9 = 0, $call10 = 0, $conv = 0, $charset = 0, $root = 0, $5 = 0, $6 = 0, $call12 = 0, $call13 = 0.0, $7 = 0, $quantum = 0, $call16 = 0, $tobool17 = 0, $8 = 0, $cmp = 0, $call22 = 0, $tobool23 = 0, $_pr = 0, $9 = 0, $cmp27 = 0, $call30 = 0, $tobool31 = 0, $10 = 0, $cmp36 = 0, $call39 = 0, $tobool40 = 0, $_ = 0, $rankdir_0 = 0, $tobool46 = 0, $shl = 0, $or = 0, $rankdir49 = 0, $rankdir53 = 0, $11 = 0, $12 = 0, $call56 = 0, $call57 = 0.0, $mul = 0.0, $cmp58 = 0, $add61 = 0.0, $sub = 0.0, $add61_sink = 0.0, $conv62 = 0, $nodesep = 0, $13 = 0, $14 = 0, $call67 = 0, $call68 = 0, $tobool69 = 0, $call71 = 0, $cmp72 = 0, $15 = 0.0, $cmp76 = 0, $call81 = 0, $tobool82 = 0, $exact_ranksep = 0, $16 = 0.0, $mul88 = 0.0, $cmp89 = 0, $add93 = 0.0, $sub97 = 0.0, $add93_sink = 0.0, $conv94 = 0, $ranksep = 0, $17 = 0, $18 = 0, $call103 = 0, $call104 = 0, $conv105 = 0, $showboxes = 0, $19 = 0, $20 = 0, $call108 = 0, $call109 = 0, $call110 = 0, $fontnames = 0, $21 = 0, $size = 0, $call114 = 0, $22 = 0, $filled = 0, $23 = 0, $page = 0, $call119 = 0, $call120 = 0, $call121 = 0, $24 = 0, $centered = 0, $call124 = 0, $tobool125 = 0, $call127 = 0, $cmp128 = 0, $conv130 = 0, $25 = 0, $landscape = 0, $call134 = 0, $tobool135 = 0, $26 = 0, $cmp138 = 0, $cmp142 = 0, $phitmp = 0, $27 = 0, $28 = 0, $landscape147 = 0, $call149 = 0, $tobool150 = 0, $call152 = 0, $29 = 0, $landscape155 = 0, $call159 = 0, $call160 = 0, $call161 = 0, $call162 = 0, $30 = 0, $dpi = 0, $call165 = 0, $tobool166 = 0, $31 = 0, $tobool170 = 0, $call172 = 0, $tobool173 = 0, $32 = 0, $tobool177 = 0, $p_1 = 0, $call179 = 0.0, $33 = 0, $dpi182 = 0, $34 = 0, $35 = 0, $call185 = 0, $proto = 0, $36 = 0, $n = 0, $37 = 0, $38 = 0, $call186 = 0, $39 = 0, $n188 = 0, $40 = 0, $41 = 0, $call189 = 0, $42 = 0, $n191 = 0, $43 = 0, $44 = 0, $call192 = 0, $45 = 0, $n194 = 0, $46 = 0, $47 = 0, $call195 = 0, $48 = 0, $n197 = 0, $49 = 0, $50 = 0, $call198 = 0, $51 = 0, $n200 = 0, $52 = 0, $53 = 0, $call201 = 0, $54 = 0, $n203 = 0, $55 = 0, $56 = 0, $call204 = 0, $57 = 0, $n206 = 0, $58 = 0, $59 = 0, $call207 = 0, $60 = 0, $n209 = 0, $61 = 0, $62 = 0, $call210 = 0, $63 = 0, $n212 = 0, $64 = 0, $65 = 0, $call213 = 0, $66 = 0, $n215 = 0, $67 = 0, $68 = 0, $call216 = 0, $69 = 0, $n218 = 0, $70 = 0, $71 = 0, $call219 = 0, $72 = 0, $n221 = 0, $73 = 0, $74 = 0, $call222 = 0, $75 = 0, $n224 = 0, $76 = 0, $77 = 0, $call225 = 0, $78 = 0, $n227 = 0, $79 = 0, $80 = 0, $call228 = 0, $81 = 0, $n230 = 0, $82 = 0, $83 = 0, $call231 = 0, $84 = 0, $n233 = 0, $85 = 0, $86 = 0, $call234 = 0, $87 = 0, $n236 = 0, $88 = 0, $89 = 0, $call237 = 0, $90 = 0, $n239 = 0, $91 = 0, $92 = 0, $call240 = 0, $93 = 0, $n242 = 0, $94 = 0, $95 = 0, $call243 = 0, $96 = 0, $n245 = 0, $97 = 0, $98 = 0, $call246 = 0, $99 = 0, $n248 = 0, $100 = 0, $101 = 0, $call249 = 0, $102 = 0, $n251 = 0, $103 = 0, $104 = 0, $call252 = 0, $105 = 0, $n254 = 0, $106 = 0, $107 = 0, $call255 = 0, $108 = 0, $n257 = 0, $109 = 0, $110 = 0, $call258 = 0, $111 = 0, $n260 = 0, $112 = 0, $113 = 0, $call261 = 0, $114 = 0, $n263 = 0, $115 = 0, $116 = 0, $call264 = 0, $117 = 0, $e = 0, $118 = 0, $119 = 0, $call266 = 0, $120 = 0, $e268 = 0, $121 = 0, $122 = 0, $call269 = 0, $123 = 0, $e271 = 0, $124 = 0, $125 = 0, $call272 = 0, $126 = 0, $e274 = 0, $127 = 0, $128 = 0, $call275 = 0, $129 = 0, $e277 = 0, $130 = 0, $131 = 0, $call278 = 0, $132 = 0, $e280 = 0, $133 = 0, $134 = 0, $call281 = 0, $135 = 0, $e283 = 0, $136 = 0, $137 = 0, $call284 = 0, $138 = 0, $e286 = 0, $139 = 0, $140 = 0, $call287 = 0, $141 = 0, $e289 = 0, $142 = 0, $143 = 0, $call290 = 0, $144 = 0, $e292 = 0, $145 = 0, $146 = 0, $call293 = 0, $147 = 0, $e295 = 0, $148 = 0, $149 = 0, $call296 = 0, $150 = 0, $e298 = 0, $151 = 0, $152 = 0, $call299 = 0, $153 = 0, $e301 = 0, $154 = 0, $155 = 0, $call302 = 0, $156 = 0, $e304 = 0, $157 = 0, $158 = 0, $call305 = 0, $159 = 0, $e307 = 0, $160 = 0, $161 = 0, $call308 = 0, $162 = 0, $e310 = 0, $163 = 0, $164 = 0, $call311 = 0, $165 = 0, $e313 = 0, $166 = 0, $167 = 0, $call314 = 0, $168 = 0, $e316 = 0, $169 = 0, $170 = 0, $call317 = 0, $171 = 0, $e319 = 0, $172 = 0, $173 = 0, $call320 = 0, $174 = 0, $e322 = 0, $175 = 0, $176 = 0, $call323 = 0, $177 = 0, $e325 = 0, $178 = 0, $179 = 0, $call326 = 0, $180 = 0, $e328 = 0, $181 = 0, $182 = 0, $call329 = 0, $183 = 0, $e331 = 0, $184 = 0, $185 = 0, $call332 = 0, $186 = 0, $e334 = 0, $187 = 0, $188 = 0, $call335 = 0, $189 = 0, $e337 = 0, $190 = 0, $191 = 0, $call338 = 0, $192 = 0, $e340 = 0, $193 = 0, $194 = 0, $call341 = 0, $195 = 0, $e343 = 0, $196 = 0, $197 = 0, $call344 = 0, $198 = 0, $e346 = 0, $199 = 0, $200 = 0, $call347 = 0, $201 = 0, $e349 = 0, $202 = 0, $203 = 0, $call350 = 0, $call351 = 0, $204 = 0, $xdots = 0, $call354 = 0, $tobool355 = 0, $205 = 0, $tobool358 = 0, $call360 = 0, $206 = 0, $id = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $xf = __stackBase__ | 0;
+ $call = _zmalloc(96) | 0;
+ $0 = $call;
+ $drawing = $g + 48 | 0;
+ HEAP32[$drawing >> 2] = $0;
+ $1 = $g | 0;
+ $call1 = _agget($1, 115496) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $p_0 = $call1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $call2 = _getenv(114976) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ $p_0 = $call2;
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[4064] | 0;
+ $call4 = _strlen($p_0 | 0) | 0;
+ $add5 = $call4 + 12 | 0;
+ $call6 = _grealloc($2, $add5) | 0;
+ HEAP32[4064] = $call6;
+ _memcpy($call6 | 0, 114464, 12);
+ $3 = HEAP32[4064] | 0;
+ $call8 = _strcat($3 | 0, $p_0 | 0) | 0;
+ $4 = HEAP32[4064] | 0;
+ $call9 = _putenv($4 | 0) | 0;
+ label = 5;
+ break;
+ case 5:
+ $call10 = _findCharset($g) | 0;
+ $conv = $call10 & 255;
+ $charset = $g + 155 | 0;
+ HEAP8[$charset] = $conv;
+ $root = $g + 32 | 0;
+ $5 = HEAP32[$root >> 2] | 0;
+ $6 = $5 | 0;
+ $call12 = _agfindattr($6, 113904) | 0;
+ $call13 = +_late_double($1, $call12, 0.0, 0.0);
+ $7 = HEAP32[$drawing >> 2] | 0;
+ $quantum = $7 | 0;
+ HEAPF64[$quantum >> 3] = $call13;
+ $call16 = _agget($1, 113448) | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ if ($tobool17) {
+ $rankdir_0 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $8 = HEAP8[$call16] | 0;
+ $cmp = $8 << 24 >> 24 == 76;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ $9 = $8;
+ label = 9;
+ break;
+ }
+ case 7:
+ $call22 = _strcmp($call16 | 0, 112920) | 0;
+ $tobool23 = ($call22 | 0) == 0;
+ if ($tobool23) {
+ $rankdir_0 = 1;
+ label = 13;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $_pr = HEAP8[$call16] | 0;
+ $9 = $_pr;
+ label = 9;
+ break;
+ case 9:
+ $cmp27 = $9 << 24 >> 24 == 66;
+ if ($cmp27) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $call30 = _strcmp($call16 | 0, 112416) | 0;
+ $tobool31 = ($call30 | 0) == 0;
+ if ($tobool31) {
+ $rankdir_0 = 2;
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $10 = HEAP8[$call16] | 0;
+ $cmp36 = $10 << 24 >> 24 == 82;
+ if ($cmp36) {
+ label = 12;
+ break;
+ } else {
+ $rankdir_0 = 0;
+ label = 13;
+ break;
+ }
+ case 12:
+ $call39 = _strcmp($call16 | 0, 111880) | 0;
+ $tobool40 = ($call39 | 0) == 0;
+ $_ = $tobool40 ? 3 : 0;
+ $rankdir_0 = $_;
+ label = 13;
+ break;
+ case 13:
+ $tobool46 = $use_rankdir << 24 >> 24 == 0;
+ $shl = $rankdir_0 << 2;
+ if ($tobool46) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $or = $shl | $rankdir_0;
+ $rankdir49 = $g + 156 | 0;
+ HEAP32[$rankdir49 >> 2] = $or;
+ label = 16;
+ break;
+ case 15:
+ $rankdir53 = $g + 156 | 0;
+ HEAP32[$rankdir53 >> 2] = $shl;
+ label = 16;
+ break;
+ case 16:
+ $11 = HEAP32[$root >> 2] | 0;
+ $12 = $11 | 0;
+ $call56 = _agfindattr($12, 111408) | 0;
+ $call57 = +_late_double($1, $call56, .25, .02);
+ HEAPF64[$xf >> 3] = $call57;
+ $mul = $call57 * 72.0;
+ $cmp58 = $mul < 0.0;
+ if ($cmp58) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $add61 = $mul + .5;
+ $add61_sink = $add61;
+ label = 19;
+ break;
+ case 18:
+ $sub = $mul + -.5;
+ $add61_sink = $sub;
+ label = 19;
+ break;
+ case 19:
+ $conv62 = ~~$add61_sink;
+ $nodesep = $g + 260 | 0;
+ HEAP32[$nodesep >> 2] = $conv62;
+ $13 = HEAP32[$root >> 2] | 0;
+ $14 = $13 | 0;
+ $call67 = _agfindattr($14, 110976) | 0;
+ $call68 = _late_string($1, $call67, 0) | 0;
+ $tobool69 = ($call68 | 0) == 0;
+ if ($tobool69) {
+ label = 26;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $call71 = _sscanf($call68 | 0, 121264, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $xf, tempInt) | 0) | 0;
+ $cmp72 = ($call71 | 0) == 0;
+ if ($cmp72) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ HEAPF64[$xf >> 3] = .5;
+ label = 24;
+ break;
+ case 22:
+ $15 = +HEAPF64[$xf >> 3];
+ $cmp76 = $15 < .02;
+ if ($cmp76) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ HEAPF64[$xf >> 3] = .02;
+ label = 24;
+ break;
+ case 24:
+ $call81 = _strstr($call68 | 0, 110600) | 0;
+ $tobool82 = ($call81 | 0) == 0;
+ if ($tobool82) {
+ label = 27;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $exact_ranksep = $g + 288 | 0;
+ HEAP8[$exact_ranksep] = 1;
+ label = 27;
+ break;
+ case 26:
+ HEAPF64[$xf >> 3] = .5;
+ label = 27;
+ break;
+ case 27:
+ $16 = +HEAPF64[$xf >> 3];
+ $mul88 = $16 * 72.0;
+ $cmp89 = $mul88 < 0.0;
+ if ($cmp89) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $add93 = $mul88 + .5;
+ $add93_sink = $add93;
+ label = 30;
+ break;
+ case 29:
+ $sub97 = $mul88 + -.5;
+ $add93_sink = $sub97;
+ label = 30;
+ break;
+ case 30:
+ $conv94 = ~~$add93_sink;
+ $ranksep = $g + 264 | 0;
+ HEAP32[$ranksep >> 2] = $conv94;
+ $17 = HEAP32[$root >> 2] | 0;
+ $18 = $17 | 0;
+ $call103 = _agfindattr($18, 110168) | 0;
+ $call104 = _late_int($1, $call103, 0, 0) | 0;
+ $conv105 = $call104 & 255;
+ $showboxes = $g + 253 | 0;
+ HEAP8[$showboxes] = $conv105;
+ $19 = HEAP32[$root >> 2] | 0;
+ $20 = $19 | 0;
+ $call108 = _agfindattr($20, 109760) | 0;
+ $call109 = _late_string($1, $call108, 0) | 0;
+ $call110 = _maptoken($call109, 16224, 16240) | 0;
+ $fontnames = $g + 256 | 0;
+ HEAP32[$fontnames >> 2] = $call110;
+ _setRatio($g);
+ $21 = HEAP32[$drawing >> 2] | 0;
+ $size = $21 + 64 | 0;
+ $call114 = _getdoubles2ptf($g, 109432, $size) | 0;
+ $22 = HEAP32[$drawing >> 2] | 0;
+ $filled = $22 + 80 | 0;
+ HEAP8[$filled] = $call114;
+ $23 = HEAP32[$drawing >> 2] | 0;
+ $page = $23 + 48 | 0;
+ $call119 = _getdoubles2ptf($g, 109072, $page) | 0;
+ $call120 = _agget($1, 108448) | 0;
+ $call121 = _mapbool($call120) | 0;
+ $24 = HEAP32[$drawing >> 2] | 0;
+ $centered = $24 + 82 | 0;
+ HEAP8[$centered] = $call121;
+ $call124 = _agget($1, 108024) | 0;
+ $tobool125 = ($call124 | 0) == 0;
+ if ($tobool125) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $call127 = _atoi($call124 | 0) | 0;
+ $cmp128 = ($call127 | 0) == 90;
+ $conv130 = $cmp128 & 1;
+ $25 = HEAP32[$drawing >> 2] | 0;
+ $landscape = $25 + 81 | 0;
+ HEAP8[$landscape] = $conv130;
+ label = 38;
+ break;
+ case 32:
+ $call134 = _agget($1, 107520) | 0;
+ $tobool135 = ($call134 | 0) == 0;
+ if ($tobool135) {
+ label = 36;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $26 = HEAP8[$call134] | 0;
+ $cmp138 = $26 << 24 >> 24 == 108;
+ if ($cmp138) {
+ $27 = 1;
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $cmp142 = $26 << 24 >> 24 == 76;
+ $phitmp = $cmp142 & 1;
+ $27 = $phitmp;
+ label = 35;
+ break;
+ case 35:
+ $28 = HEAP32[$drawing >> 2] | 0;
+ $landscape147 = $28 + 81 | 0;
+ HEAP8[$landscape147] = $27;
+ label = 38;
+ break;
+ case 36:
+ $call149 = _agget($1, 107128) | 0;
+ $tobool150 = ($call149 | 0) == 0;
+ if ($tobool150) {
+ label = 38;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $call152 = _mapbool($call149) | 0;
+ $29 = HEAP32[$drawing >> 2] | 0;
+ $landscape155 = $29 + 81 | 0;
+ HEAP8[$landscape155] = $call152;
+ label = 38;
+ break;
+ case 38:
+ $call159 = _agget($1, 106784) | 0;
+ $call160 = _maptoken($call159, 16192, 16208) | 0;
+ HEAP32[42032] = $call160;
+ $call161 = _agget($1, 106384) | 0;
+ $call162 = _mapbool($call161) | 0;
+ HEAP8[167952] = $call162;
+ HEAP32[41356] = 0;
+ $30 = HEAP32[$drawing >> 2] | 0;
+ $dpi = $30 + 24 | 0;
+ HEAPF64[$dpi >> 3] = 0.0;
+ $call165 = _agget($1, 106016) | 0;
+ $tobool166 = ($call165 | 0) == 0;
+ if ($tobool166) {
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $31 = HEAP8[$call165] | 0;
+ $tobool170 = $31 << 24 >> 24 == 0;
+ if ($tobool170) {
+ label = 40;
+ break;
+ } else {
+ $p_1 = $call165;
+ label = 42;
+ break;
+ }
+ case 40:
+ $call172 = _agget($1, 105656) | 0;
+ $tobool173 = ($call172 | 0) == 0;
+ if ($tobool173) {
+ label = 43;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $32 = HEAP8[$call172] | 0;
+ $tobool177 = $32 << 24 >> 24 == 0;
+ if ($tobool177) {
+ label = 43;
+ break;
+ } else {
+ $p_1 = $call172;
+ label = 42;
+ break;
+ }
+ case 42:
+ $call179 = +_atof($p_1);
+ $33 = HEAP32[$drawing >> 2] | 0;
+ $dpi182 = $33 + 24 | 0;
+ HEAPF64[$dpi182 >> 3] = $call179;
+ label = 43;
+ break;
+ case 43:
+ _do_graph_label($g);
+ HEAPF64[20871] = 1.0e+37;
+ $34 = HEAP32[$root >> 2] | 0;
+ $35 = $34 | 0;
+ $call185 = _agfindattr($35, 105304) | 0;
+ HEAP32[41866] = $call185;
+ $proto = $g + 40 | 0;
+ $36 = HEAP32[$proto >> 2] | 0;
+ $n = $36 | 0;
+ $37 = HEAP32[$n >> 2] | 0;
+ $38 = $37 | 0;
+ $call186 = _agfindattr($38, 104960) | 0;
+ HEAP32[41592] = $call186;
+ $39 = HEAP32[$proto >> 2] | 0;
+ $n188 = $39 | 0;
+ $40 = HEAP32[$n188 >> 2] | 0;
+ $41 = $40 | 0;
+ $call189 = _agfindattr($41, 104480) | 0;
+ HEAP32[41552] = $call189;
+ $42 = HEAP32[$proto >> 2] | 0;
+ $n191 = $42 | 0;
+ $43 = HEAP32[$n191 >> 2] | 0;
+ $44 = $43 | 0;
+ $call192 = _agfindattr($44, 104088) | 0;
+ HEAP32[41568] = $call192;
+ $45 = HEAP32[$proto >> 2] | 0;
+ $n194 = $45 | 0;
+ $46 = HEAP32[$n194 >> 2] | 0;
+ $47 = $46 | 0;
+ $call195 = _agfindattr($47, 103592) | 0;
+ HEAP32[41616] = $call195;
+ $48 = HEAP32[$proto >> 2] | 0;
+ $n197 = $48 | 0;
+ $49 = HEAP32[$n197 >> 2] | 0;
+ $50 = $49 | 0;
+ $call198 = _agfindattr($50, 103240) | 0;
+ HEAP32[41604] = $call198;
+ $51 = HEAP32[$proto >> 2] | 0;
+ $n200 = $51 | 0;
+ $52 = HEAP32[$n200 >> 2] | 0;
+ $53 = $52 | 0;
+ $call201 = _agfindattr($53, 102872) | 0;
+ HEAP32[41560] = $call201;
+ $54 = HEAP32[$proto >> 2] | 0;
+ $n203 = $54 | 0;
+ $55 = HEAP32[$n203 >> 2] | 0;
+ $56 = $55 | 0;
+ $call204 = _agfindattr($56, 102528) | 0;
+ HEAP32[41596] = $call204;
+ $57 = HEAP32[$proto >> 2] | 0;
+ $n206 = $57 | 0;
+ $58 = HEAP32[$n206 >> 2] | 0;
+ $59 = $58 | 0;
+ $call207 = _agfindattr($59, 102080) | 0;
+ HEAP32[41598] = $call207;
+ $60 = HEAP32[$proto >> 2] | 0;
+ $n209 = $60 | 0;
+ $61 = HEAP32[$n209 >> 2] | 0;
+ $62 = $61 | 0;
+ $call210 = _agfindattr($62, 101664) | 0;
+ HEAP32[41600] = $call210;
+ $63 = HEAP32[$proto >> 2] | 0;
+ $n212 = $63 | 0;
+ $64 = HEAP32[$n212 >> 2] | 0;
+ $65 = $64 | 0;
+ $call213 = _agfindattr($65, 123360) | 0;
+ HEAP32[41588] = $call213;
+ $66 = HEAP32[$proto >> 2] | 0;
+ $n215 = $66 | 0;
+ $67 = HEAP32[$n215 >> 2] | 0;
+ $68 = $67 | 0;
+ $call216 = _agfindattr($68, 101104) | 0;
+ HEAP32[41550] = $call216;
+ $69 = HEAP32[$proto >> 2] | 0;
+ $n218 = $69 | 0;
+ $70 = HEAP32[$n218 >> 2] | 0;
+ $71 = $70 | 0;
+ $call219 = _agfindattr($71, 110168) | 0;
+ HEAP32[41566] = $call219;
+ $72 = HEAP32[$proto >> 2] | 0;
+ $n221 = $72 | 0;
+ $73 = HEAP32[$n221 >> 2] | 0;
+ $74 = $73 | 0;
+ $call222 = _agfindattr($74, 100744) | 0;
+ HEAP32[41576] = $call222;
+ $75 = HEAP32[$proto >> 2] | 0;
+ $n224 = $75 | 0;
+ $76 = HEAP32[$n224 >> 2] | 0;
+ $77 = $76 | 0;
+ $call225 = _agfindattr($77, 105304) | 0;
+ HEAP32[41580] = $call225;
+ $78 = HEAP32[$proto >> 2] | 0;
+ $n227 = $78 | 0;
+ $79 = HEAP32[$n227 >> 2] | 0;
+ $80 = $79 | 0;
+ $call228 = _agfindattr($80, 100232) | 0;
+ HEAP32[41564] = $call228;
+ $81 = HEAP32[$proto >> 2] | 0;
+ $n230 = $81 | 0;
+ $82 = HEAP32[$n230 >> 2] | 0;
+ $83 = $82 | 0;
+ $call231 = _agfindattr($83, 99888) | 0;
+ HEAP32[41574] = $call231;
+ $84 = HEAP32[$proto >> 2] | 0;
+ $n233 = $84 | 0;
+ $85 = HEAP32[$n233 >> 2] | 0;
+ $86 = $85 | 0;
+ $call234 = _agfindattr($86, 99424) | 0;
+ HEAP32[41562] = $call234;
+ $87 = HEAP32[$proto >> 2] | 0;
+ $n236 = $87 | 0;
+ $88 = HEAP32[$n236 >> 2] | 0;
+ $89 = $88 | 0;
+ $call237 = _agfindattr($89, 107520) | 0;
+ HEAP32[41578] = $call237;
+ $90 = HEAP32[$proto >> 2] | 0;
+ $n239 = $90 | 0;
+ $91 = HEAP32[$n239 >> 2] | 0;
+ $92 = $91 | 0;
+ $call240 = _agfindattr($92, 99072) | 0;
+ HEAP32[41608] = $call240;
+ $93 = HEAP32[$proto >> 2] | 0;
+ $n242 = $93 | 0;
+ $94 = HEAP32[$n242 >> 2] | 0;
+ $95 = $94 | 0;
+ $call243 = _agfindattr($95, 98616) | 0;
+ HEAP32[41602] = $call243;
+ $96 = HEAP32[$proto >> 2] | 0;
+ $n245 = $96 | 0;
+ $97 = HEAP32[$n245 >> 2] | 0;
+ $98 = $97 | 0;
+ $call246 = _agfindattr($98, 98208) | 0;
+ HEAP32[41590] = $call246;
+ $99 = HEAP32[$proto >> 2] | 0;
+ $n248 = $99 | 0;
+ $100 = HEAP32[$n248 >> 2] | 0;
+ $101 = $100 | 0;
+ $call249 = _agfindattr($101, 97824) | 0;
+ HEAP32[41582] = $call249;
+ $102 = HEAP32[$proto >> 2] | 0;
+ $n251 = $102 | 0;
+ $103 = HEAP32[$n251 >> 2] | 0;
+ $104 = $103 | 0;
+ $call252 = _agfindattr($104, 97344) | 0;
+ HEAP32[41586] = $call252;
+ $105 = HEAP32[$proto >> 2] | 0;
+ $n254 = $105 | 0;
+ $106 = HEAP32[$n254 >> 2] | 0;
+ $107 = $106 | 0;
+ $call255 = _agfindattr($107, 97016) | 0;
+ HEAP32[41594] = $call255;
+ $108 = HEAP32[$proto >> 2] | 0;
+ $n257 = $108 | 0;
+ $109 = HEAP32[$n257 >> 2] | 0;
+ $110 = $109 | 0;
+ $call258 = _agfindattr($110, 96544) | 0;
+ HEAP32[41614] = $call258;
+ $111 = HEAP32[$proto >> 2] | 0;
+ $n260 = $111 | 0;
+ $112 = HEAP32[$n260 >> 2] | 0;
+ $113 = $112 | 0;
+ $call261 = _agfindattr($113, 96096) | 0;
+ HEAP32[41558] = $call261;
+ $114 = HEAP32[$proto >> 2] | 0;
+ $n263 = $114 | 0;
+ $115 = HEAP32[$n263 >> 2] | 0;
+ $116 = $115 | 0;
+ $call264 = _agfindattr($116, 95784) | 0;
+ HEAP32[41548] = $call264;
+ $117 = HEAP32[$proto >> 2] | 0;
+ $e = $117 + 4 | 0;
+ $118 = HEAP32[$e >> 2] | 0;
+ $119 = $118 | 0;
+ $call266 = _agfindattr($119, 95384) | 0;
+ HEAP32[41894] = $call266;
+ $120 = HEAP32[$proto >> 2] | 0;
+ $e268 = $120 + 4 | 0;
+ $121 = HEAP32[$e268 >> 2] | 0;
+ $122 = $121 | 0;
+ $call269 = _agfindattr($122, 103592) | 0;
+ HEAP32[41958] = $call269;
+ $123 = HEAP32[$proto >> 2] | 0;
+ $e271 = $123 + 4 | 0;
+ $124 = HEAP32[$e271 >> 2] | 0;
+ $125 = $124 | 0;
+ $call272 = _agfindattr($125, 102528) | 0;
+ HEAP32[41940] = $call272;
+ $126 = HEAP32[$proto >> 2] | 0;
+ $e274 = $126 + 4 | 0;
+ $127 = HEAP32[$e274 >> 2] | 0;
+ $128 = $127 | 0;
+ $call275 = _agfindattr($128, 102080) | 0;
+ HEAP32[41942] = $call275;
+ $129 = HEAP32[$proto >> 2] | 0;
+ $e277 = $129 + 4 | 0;
+ $130 = HEAP32[$e277 >> 2] | 0;
+ $131 = $130 | 0;
+ $call278 = _agfindattr($131, 101664) | 0;
+ HEAP32[41944] = $call278;
+ $132 = HEAP32[$proto >> 2] | 0;
+ $e280 = $132 + 4 | 0;
+ $133 = HEAP32[$e280 >> 2] | 0;
+ $134 = $133 | 0;
+ $call281 = _agfindattr($134, 123360) | 0;
+ HEAP32[41934] = $call281;
+ $135 = HEAP32[$proto >> 2] | 0;
+ $e283 = $135 + 4 | 0;
+ $136 = HEAP32[$e283 >> 2] | 0;
+ $137 = $136 | 0;
+ $call284 = _agfindattr($137, 101104) | 0;
+ HEAP32[41892] = $call284;
+ $138 = HEAP32[$proto >> 2] | 0;
+ $e286 = $138 + 4 | 0;
+ $139 = HEAP32[$e286 >> 2] | 0;
+ $140 = $139 | 0;
+ $call287 = _agfindattr($140, 95048) | 0;
+ HEAP32[41932] = $call287;
+ $141 = HEAP32[$proto >> 2] | 0;
+ $e289 = $141 + 4 | 0;
+ $142 = HEAP32[$e289 >> 2] | 0;
+ $143 = $142 | 0;
+ $call290 = _agfindattr($143, 94768) | 0;
+ HEAP32[41946] = $call290;
+ $144 = HEAP32[$proto >> 2] | 0;
+ $e292 = $144 + 4 | 0;
+ $145 = HEAP32[$e292 >> 2] | 0;
+ $146 = $145 | 0;
+ $call293 = _agfindattr($146, 94464) | 0;
+ HEAP32[41964] = $call293;
+ $147 = HEAP32[$proto >> 2] | 0;
+ $e295 = $147 + 4 | 0;
+ $148 = HEAP32[$e295 >> 2] | 0;
+ $149 = $148 | 0;
+ $call296 = _agfindattr($149, 94088) | 0;
+ HEAP32[41960] = $call296;
+ $150 = HEAP32[$proto >> 2] | 0;
+ $e298 = $150 + 4 | 0;
+ $151 = HEAP32[$e298 >> 2] | 0;
+ $152 = $151 | 0;
+ $call299 = _agfindattr($152, 93784) | 0;
+ HEAP32[41936] = $call299;
+ $153 = HEAP32[$proto >> 2] | 0;
+ $e301 = $153 + 4 | 0;
+ $154 = HEAP32[$e301 >> 2] | 0;
+ $155 = $154 | 0;
+ $call302 = _agfindattr($155, 93416) | 0;
+ HEAP32[41900] = $call302;
+ $156 = HEAP32[$proto >> 2] | 0;
+ $e304 = $156 + 4 | 0;
+ $157 = HEAP32[$e304 >> 2] | 0;
+ $158 = $157 | 0;
+ $call305 = _agfindattr($158, 93096) | 0;
+ HEAP32[41922] = $call305;
+ $159 = HEAP32[$proto >> 2] | 0;
+ $e307 = $159 + 4 | 0;
+ $160 = HEAP32[$e307 >> 2] | 0;
+ $161 = $160 | 0;
+ $call308 = _agfindattr($161, 92696) | 0;
+ HEAP32[41924] = $call308;
+ $162 = HEAP32[$proto >> 2] | 0;
+ $e310 = $162 + 4 | 0;
+ $163 = HEAP32[$e310 >> 2] | 0;
+ $164 = $163 | 0;
+ $call311 = _agfindattr($164, 92376) | 0;
+ HEAP32[41926] = $call311;
+ $165 = HEAP32[$proto >> 2] | 0;
+ $e313 = $165 + 4 | 0;
+ $166 = HEAP32[$e313 >> 2] | 0;
+ $167 = $166 | 0;
+ $call314 = _agfindattr($167, 91872) | 0;
+ HEAP32[41928] = $call314;
+ $168 = HEAP32[$proto >> 2] | 0;
+ $e316 = $168 + 4 | 0;
+ $169 = HEAP32[$e316 >> 2] | 0;
+ $170 = $169 | 0;
+ $call317 = _agfindattr($170, 91536) | 0;
+ HEAP32[41930] = $call317;
+ $171 = HEAP32[$proto >> 2] | 0;
+ $e319 = $171 + 4 | 0;
+ $172 = HEAP32[$e319 >> 2] | 0;
+ $173 = $172 | 0;
+ $call320 = _agfindattr($173, 91264) | 0;
+ HEAP32[41918] = $call320;
+ $174 = HEAP32[$proto >> 2] | 0;
+ $e322 = $174 + 4 | 0;
+ $175 = HEAP32[$e322 >> 2] | 0;
+ $176 = $175 | 0;
+ $call323 = _agfindattr($176, 110168) | 0;
+ HEAP32[41906] = $call323;
+ $177 = HEAP32[$proto >> 2] | 0;
+ $e325 = $177 + 4 | 0;
+ $178 = HEAP32[$e325 >> 2] | 0;
+ $179 = $178 | 0;
+ $call326 = _agfindattr($179, 102872) | 0;
+ HEAP32[41904] = $call326;
+ $180 = HEAP32[$proto >> 2] | 0;
+ $e328 = $180 + 4 | 0;
+ $181 = HEAP32[$e328 >> 2] | 0;
+ $182 = $181 | 0;
+ $call329 = _agfindattr($182, 90896) | 0;
+ HEAP32[41952] = $call329;
+ $183 = HEAP32[$proto >> 2] | 0;
+ $e331 = $183 + 4 | 0;
+ $184 = HEAP32[$e331 >> 2] | 0;
+ $185 = $184 | 0;
+ $call332 = _agfindattr($185, 90584) | 0;
+ HEAP32[41962] = $call332;
+ $186 = HEAP32[$proto >> 2] | 0;
+ $e334 = $186 + 4 | 0;
+ $187 = HEAP32[$e334 >> 2] | 0;
+ $188 = $187 | 0;
+ $call335 = _agfindattr($188, 90288) | 0;
+ HEAP32[41954] = $call335;
+ $189 = HEAP32[$proto >> 2] | 0;
+ $e337 = $189 + 4 | 0;
+ $190 = HEAP32[$e337 >> 2] | 0;
+ $191 = $190 | 0;
+ $call338 = _agfindattr($191, 97344) | 0;
+ HEAP32[41920] = $call338;
+ $192 = HEAP32[$proto >> 2] | 0;
+ $e340 = $192 + 4 | 0;
+ $193 = HEAP32[$e340 >> 2] | 0;
+ $194 = $193 | 0;
+ $call341 = _agfindattr($194, 96544) | 0;
+ HEAP32[41956] = $call341;
+ $195 = HEAP32[$proto >> 2] | 0;
+ $e343 = $195 + 4 | 0;
+ $196 = HEAP32[$e343 >> 2] | 0;
+ $197 = $196 | 0;
+ $call344 = _agfindattr($197, 89960) | 0;
+ HEAP32[41902] = $call344;
+ $198 = HEAP32[$proto >> 2] | 0;
+ $e346 = $198 + 4 | 0;
+ $199 = HEAP32[$e346 >> 2] | 0;
+ $200 = $199 | 0;
+ $call347 = _agfindattr($200, 163160) | 0;
+ HEAP32[41938] = $call347;
+ $201 = HEAP32[$proto >> 2] | 0;
+ $e349 = $201 + 4 | 0;
+ $202 = HEAP32[$e349 >> 2] | 0;
+ $203 = $202 | 0;
+ $call350 = _agfindattr($203, 100744) | 0;
+ HEAP32[41916] = $call350;
+ $call351 = _init_xdot($g) | 0;
+ $204 = HEAP32[$drawing >> 2] | 0;
+ $xdots = $204 + 88 | 0;
+ HEAP32[$xdots >> 2] = $call351;
+ $call354 = _agget($1, 162816) | 0;
+ $tobool355 = ($call354 | 0) == 0;
+ if ($tobool355) {
+ label = 46;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $205 = HEAP8[$call354] | 0;
+ $tobool358 = $205 << 24 >> 24 == 0;
+ if ($tobool358) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $call360 = _strdup_and_subst_obj($call354, $1) | 0;
+ $206 = HEAP32[$drawing >> 2] | 0;
+ $id = $206 + 92 | 0;
+ HEAP32[$id >> 2] = $call360;
+ label = 46;
+ break;
+ case 46:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _findCharset($g) {
+ $g = $g | 0;
+ var $0 = 0, $root = 0, $1 = 0, $2 = 0, $call = 0, $call1 = 0, $call2 = 0, $tobool = 0, $call3 = 0, $tobool4 = 0, $call6 = 0, $tobool7 = 0, $call9 = 0, $tobool10 = 0, $call12 = 0, $tobool13 = 0, $call15 = 0, $tobool16 = 0, $call18 = 0, $tobool19 = 0, $call20 = 0, $tobool21 = 0, $call23 = 0, $tobool24 = 0, $call27 = 0, $tobool28 = 0, $call30 = 0, $tobool31 = 0, $call34 = 0, $enc_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g | 0;
+ $root = $g + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $2 = $1 | 0;
+ $call = _agfindattr($2, 157048) | 0;
+ $call1 = _late_nnstring($0, $call, 156776) | 0;
+ $call2 = _strcasecmp($call1, 156480) | 0;
+ $tobool = ($call2 | 0) == 0;
+ if ($tobool) {
+ $enc_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call3 = _strcasecmp($call1, 156144) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ $enc_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call6 = _strcasecmp($call1, 155752) | 0;
+ $tobool7 = ($call6 | 0) == 0;
+ if ($tobool7) {
+ $enc_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call9 = _strcasecmp($call1, 162056) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ $enc_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call12 = _strcasecmp($call1, 155456) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ $enc_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call15 = _strcasecmp($call1, 155088) | 0;
+ $tobool16 = ($call15 | 0) == 0;
+ if ($tobool16) {
+ $enc_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call18 = _strcasecmp($call1, 154792) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ $enc_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call20 = _strcasecmp($call1, 154416) | 0;
+ $tobool21 = ($call20 | 0) == 0;
+ if ($tobool21) {
+ $enc_0 = 2;
+ label = 14;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call23 = _strcasecmp($call1, 154184) | 0;
+ $tobool24 = ($call23 | 0) == 0;
+ if ($tobool24) {
+ $enc_0 = 2;
+ label = 14;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call27 = _strcasecmp($call1, 156776) | 0;
+ $tobool28 = ($call27 | 0) == 0;
+ if ($tobool28) {
+ $enc_0 = 0;
+ label = 14;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call30 = _strcasecmp($call1, 153816) | 0;
+ $tobool31 = ($call30 | 0) == 0;
+ if ($tobool31) {
+ $enc_0 = 0;
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $call34 = _agerr(0, 153456, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call1, tempInt) | 0) | 0;
+ $enc_0 = 0;
+ label = 14;
+ break;
+ case 14:
+ STACKTOP = __stackBase__;
+ return $enc_0 | 0;
+ }
+ return 0;
+}
+function _setRatio($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $1 = 0, $tobool1 = 0, $conv = 0, $cmp = 0, $call7 = 0, $tobool8 = 0, $drawing = 0, $2 = 0, $ratio_kind = 0, $cmp13 = 0, $call16 = 0, $tobool17 = 0, $drawing20 = 0, $3 = 0, $ratio_kind21 = 0, $cmp26 = 0, $call29 = 0, $tobool30 = 0, $drawing33 = 0, $4 = 0, $ratio_kind34 = 0, $cmp39 = 0, $call42 = 0, $tobool43 = 0, $drawing46 = 0, $5 = 0, $ratio_kind47 = 0, $call49 = 0.0, $cmp50 = 0, $drawing54 = 0, $6 = 0, $ratio_kind55 = 0, $7 = 0, $ratio58 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g | 0;
+ $call = _agget($0, 158960) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$call] | 0;
+ $tobool1 = $1 << 24 >> 24 == 0;
+ if ($tobool1) {
+ label = 19;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = $1 << 24 >> 24;
+ if (($conv | 0) == 97) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 99) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 101) {
+ label = 11;
+ break;
+ } else if (($conv | 0) == 102) {
+ label = 14;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 5:
+ $cmp = $1 << 24 >> 24 == 97;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 6:
+ $call7 = _strcmp($call | 0, 158568) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 7:
+ $drawing = $g + 48 | 0;
+ $2 = HEAP32[$drawing >> 2] | 0;
+ $ratio_kind = $2 + 84 | 0;
+ HEAP32[$ratio_kind >> 2] = 4;
+ label = 19;
+ break;
+ case 8:
+ $cmp13 = $1 << 24 >> 24 == 99;
+ if ($cmp13) {
+ label = 9;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 9:
+ $call16 = _strcmp($call | 0, 158192) | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ if ($tobool17) {
+ label = 10;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 10:
+ $drawing20 = $g + 48 | 0;
+ $3 = HEAP32[$drawing20 >> 2] | 0;
+ $ratio_kind21 = $3 + 84 | 0;
+ HEAP32[$ratio_kind21 >> 2] = 3;
+ label = 19;
+ break;
+ case 11:
+ $cmp26 = $1 << 24 >> 24 == 101;
+ if ($cmp26) {
+ label = 12;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 12:
+ $call29 = _strcmp($call | 0, 157792) | 0;
+ $tobool30 = ($call29 | 0) == 0;
+ if ($tobool30) {
+ label = 13;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 13:
+ $drawing33 = $g + 48 | 0;
+ $4 = HEAP32[$drawing33 >> 2] | 0;
+ $ratio_kind34 = $4 + 84 | 0;
+ HEAP32[$ratio_kind34 >> 2] = 5;
+ label = 19;
+ break;
+ case 14:
+ $cmp39 = $1 << 24 >> 24 == 102;
+ if ($cmp39) {
+ label = 15;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 15:
+ $call42 = _strcmp($call | 0, 157464) | 0;
+ $tobool43 = ($call42 | 0) == 0;
+ if ($tobool43) {
+ label = 16;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 16:
+ $drawing46 = $g + 48 | 0;
+ $5 = HEAP32[$drawing46 >> 2] | 0;
+ $ratio_kind47 = $5 + 84 | 0;
+ HEAP32[$ratio_kind47 >> 2] = 2;
+ label = 19;
+ break;
+ case 17:
+ $call49 = +_atof($call);
+ $cmp50 = $call49 > 0.0;
+ if ($cmp50) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $drawing54 = $g + 48 | 0;
+ $6 = HEAP32[$drawing54 >> 2] | 0;
+ $ratio_kind55 = $6 + 84 | 0;
+ HEAP32[$ratio_kind55 >> 2] = 1;
+ $7 = HEAP32[$drawing54 >> 2] | 0;
+ $ratio58 = $7 + 16 | 0;
+ HEAPF64[$ratio58 >> 3] = $call49;
+ label = 19;
+ break;
+ case 19:
+ return;
+ }
+}
+function _getdoubles2ptf($g, $name, $result) {
+ $g = $g | 0;
+ $name = $name | 0;
+ $result = $result | 0;
+ var $xf = 0, $yf = 0, $c = 0, $0 = 0, $call = 0, $tobool = 0, $call1 = 0, $cmp = 0, $1 = 0.0, $cmp2 = 0, $2 = 0.0, $cmp4 = 0, $mul = 0.0, $cmp6 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $conv10 = 0.0, $x = 0, $3 = 0.0, $mul11 = 0.0, $cmp12 = 0, $add16 = 0.0, $sub20 = 0.0, $add16_sink = 0.0, $conv17 = 0, $conv24 = 0.0, $y = 0, $4 = 0, $cmp26 = 0, $_ = 0, $call29 = 0, $cmp30 = 0, $5 = 0.0, $cmp33 = 0, $mul36 = 0.0, $cmp37 = 0, $add41 = 0.0, $sub45 = 0.0, $add41_sink = 0.0, $conv42 = 0, $conv49 = 0.0, $x50 = 0, $y51 = 0, $6 = 0, $cmp53 = 0, $_6 = 0, $rv_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 24 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $xf = __stackBase__ | 0;
+ $yf = __stackBase__ + 8 | 0;
+ $c = __stackBase__ + 16 | 0;
+ HEAP8[$c] = 0;
+ $0 = $g | 0;
+ $call = _agget($0, $name) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $rv_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _sscanf($call | 0, 159784, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $xf, HEAP32[tempInt + 8 >> 2] = $yf, HEAP32[tempInt + 16 >> 2] = $c, tempInt) | 0) | 0;
+ $cmp = ($call1 | 0) > 1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 4:
+ $1 = +HEAPF64[$xf >> 3];
+ $cmp2 = $1 > 0.0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 5:
+ $2 = +HEAPF64[$yf >> 3];
+ $cmp4 = $2 > 0.0;
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 6:
+ $mul = $1 * 72.0;
+ $cmp6 = $mul < 0.0;
+ if ($cmp6) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add = $mul + .5;
+ $add_sink = $add;
+ label = 9;
+ break;
+ case 8:
+ $sub = $mul + -.5;
+ $add_sink = $sub;
+ label = 9;
+ break;
+ case 9:
+ $conv = ~~$add_sink;
+ $conv10 = +($conv | 0);
+ $x = $result | 0;
+ HEAPF64[$x >> 3] = $conv10;
+ $3 = +HEAPF64[$yf >> 3];
+ $mul11 = $3 * 72.0;
+ $cmp12 = $mul11 < 0.0;
+ if ($cmp12) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $add16 = $mul11 + .5;
+ $add16_sink = $add16;
+ label = 12;
+ break;
+ case 11:
+ $sub20 = $mul11 + -.5;
+ $add16_sink = $sub20;
+ label = 12;
+ break;
+ case 12:
+ $conv17 = ~~$add16_sink;
+ $conv24 = +($conv17 | 0);
+ $y = $result + 8 | 0;
+ HEAPF64[$y >> 3] = $conv24;
+ $4 = HEAP8[$c] | 0;
+ $cmp26 = $4 << 24 >> 24 == 33;
+ $_ = $cmp26 & 1;
+ $rv_0 = $_;
+ label = 19;
+ break;
+ case 13:
+ HEAP8[$c] = 0;
+ $call29 = _sscanf($call | 0, 159400, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $xf, HEAP32[tempInt + 8 >> 2] = $c, tempInt) | 0) | 0;
+ $cmp30 = ($call29 | 0) > 0;
+ if ($cmp30) {
+ label = 14;
+ break;
+ } else {
+ $rv_0 = 0;
+ label = 19;
+ break;
+ }
+ case 14:
+ $5 = +HEAPF64[$xf >> 3];
+ $cmp33 = $5 > 0.0;
+ if ($cmp33) {
+ label = 15;
+ break;
+ } else {
+ $rv_0 = 0;
+ label = 19;
+ break;
+ }
+ case 15:
+ $mul36 = $5 * 72.0;
+ $cmp37 = $mul36 < 0.0;
+ if ($cmp37) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $add41 = $mul36 + .5;
+ $add41_sink = $add41;
+ label = 18;
+ break;
+ case 17:
+ $sub45 = $mul36 + -.5;
+ $add41_sink = $sub45;
+ label = 18;
+ break;
+ case 18:
+ $conv42 = ~~$add41_sink;
+ $conv49 = +($conv42 | 0);
+ $x50 = $result | 0;
+ HEAPF64[$x50 >> 3] = $conv49;
+ $y51 = $result + 8 | 0;
+ HEAPF64[$y51 >> 3] = $conv49;
+ $6 = HEAP8[$c] | 0;
+ $cmp53 = $6 << 24 >> 24 == 33;
+ $_6 = $cmp53 & 1;
+ STACKTOP = __stackBase__;
+ return $_6 | 0;
+ case 19:
+ STACKTOP = __stackBase__;
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _setYInvert($g) {
+ $g = $g | 0;
+ var $0 = 0, $tobool = 0, $y = 0, $1 = 0.0, $y3 = 0, $2 = 0.0, $add = 0.0, $div = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41182] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $y = $g + 80 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $y3 = $g + 64 | 0;
+ $2 = +HEAPF64[$y3 >> 3];
+ $add = $1 + $2;
+ HEAPF64[20590] = $add;
+ $div = $add / 72.0;
+ HEAPF64[20592] = $div;
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _do_graph_label($sg) {
+ $sg = $sg | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $1 = 0, $cmp = 0, $root = 0, $2 = 0, $has_labels = 0, $3 = 0, $or = 0, $call4 = 0, $tobool5 = 0, $cond = 0, $4 = 0, $5 = 0, $call7 = 0, $call8 = 0.0, $6 = 0, $7 = 0, $call10 = 0, $call11 = 0, $8 = 0, $9 = 0, $call13 = 0, $call14 = 0, $call15 = 0, $label = 0, $call17 = 0, $10 = 0, $cmp19 = 0, $tobool22 = 0, $11 = 0, $cmp25 = 0, $12 = 0, $cmp33 = 0, $pos_flag_0 = 0, $call39 = 0, $tobool40 = 0, $13 = 0, $or48 = 0, $or57 = 0, $pos_flag_1 = 0, $label_pos = 0, $14 = 0, $cmp64 = 0, $15 = 0, $dimen_sroa_0_0__idx2 = 0, $dimen_sroa_0_0_copyload3 = 0.0, $dimen_sroa_1_8__idx6 = 0, $dimen_sroa_1_8_copyload7 = 0.0, $add = 0.0, $add71 = 0.0, $rankdir = 0, $16 = 0, $and74 = 0, $tobool75 = 0, $and91 = 0, $tobool92 = 0, $_ = 0, $dimen_sroa_0_0__idx = 0, $dimen_sroa_1_8__idx4 = 0, $_43 = 0, $x100 = 0, $y105 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $sg | 0;
+ $call = _agget($0, 123360) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$call] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 19;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $root = $sg + 32 | 0;
+ $2 = HEAP32[$root >> 2] | 0;
+ $has_labels = $2 + 153 | 0;
+ $3 = HEAP8[$has_labels] | 0;
+ $or = $3 | 8;
+ HEAP8[$has_labels] = $or;
+ $call4 = _aghtmlstr($call) | 0;
+ $tobool5 = ($call4 | 0) != 0;
+ $cond = $tobool5 ? 2 : 0;
+ $4 = HEAP32[$root >> 2] | 0;
+ $5 = $4 | 0;
+ $call7 = _agfindattr($5, 102528) | 0;
+ $call8 = +_late_double($0, $call7, 14.0, 1.0);
+ $6 = HEAP32[$root >> 2] | 0;
+ $7 = $6 | 0;
+ $call10 = _agfindattr($7, 102080) | 0;
+ $call11 = _late_nnstring($0, $call10, 161152) | 0;
+ $8 = HEAP32[$root >> 2] | 0;
+ $9 = $8 | 0;
+ $call13 = _agfindattr($9, 101664) | 0;
+ $call14 = _late_nnstring($0, $call13, 160776) | 0;
+ $call15 = _make_label($0, $call, $cond, $call8, $call11, $call14) | 0;
+ $label = $sg + 52 | 0;
+ HEAP32[$label >> 2] = $call15;
+ $call17 = _agget($0, 160472) | 0;
+ $10 = HEAP32[$root >> 2] | 0;
+ $cmp19 = ($10 | 0) == ($sg | 0);
+ $tobool22 = ($call17 | 0) != 0;
+ if ($cmp19) {
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ if ($tobool22) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $11 = HEAP8[$call17] | 0;
+ $cmp25 = $11 << 24 >> 24 == 98;
+ if ($cmp25) {
+ $pos_flag_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $pos_flag_0 = 1;
+ label = 11;
+ break;
+ case 8:
+ if ($tobool22) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $12 = HEAP8[$call17] | 0;
+ $cmp33 = $12 << 24 >> 24 == 116;
+ if ($cmp33) {
+ $pos_flag_0 = 1;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $pos_flag_0 = 0;
+ label = 11;
+ break;
+ case 11:
+ $call39 = _agget($0, 160136) | 0;
+ $tobool40 = ($call39 | 0) == 0;
+ if ($tobool40) {
+ $pos_flag_1 = $pos_flag_0;
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $13 = HEAP8[$call39] | 0;
+ if (($13 << 24 >> 24 | 0) == 108) {
+ label = 13;
+ break;
+ } else if (($13 << 24 >> 24 | 0) == 114) {
+ label = 14;
+ break;
+ } else {
+ $pos_flag_1 = $pos_flag_0;
+ label = 15;
+ break;
+ }
+ case 13:
+ $or48 = $pos_flag_0 | 2;
+ $pos_flag_1 = $or48;
+ label = 15;
+ break;
+ case 14:
+ $or57 = $pos_flag_0 | 4;
+ $pos_flag_1 = $or57;
+ label = 15;
+ break;
+ case 15:
+ $label_pos = $sg + 287 | 0;
+ HEAP8[$label_pos] = $pos_flag_1;
+ $14 = HEAP32[$root >> 2] | 0;
+ $cmp64 = ($14 | 0) == ($sg | 0);
+ if ($cmp64) {
+ label = 19;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $15 = HEAP32[$label >> 2] | 0;
+ $dimen_sroa_0_0__idx2 = $15 + 24 | 0;
+ $dimen_sroa_0_0_copyload3 = +HEAPF64[$dimen_sroa_0_0__idx2 >> 3];
+ $dimen_sroa_1_8__idx6 = $15 + 32 | 0;
+ $dimen_sroa_1_8_copyload7 = +HEAPF64[$dimen_sroa_1_8__idx6 >> 3];
+ $add = $dimen_sroa_0_0_copyload3 + 16.0;
+ $add71 = $dimen_sroa_1_8_copyload7 + 8.0;
+ $rankdir = $14 + 156 | 0;
+ $16 = HEAP32[$rankdir >> 2] | 0;
+ $and74 = $16 & 1;
+ $tobool75 = ($and74 | 0) == 0;
+ $and91 = $pos_flag_1 & 1;
+ $tobool92 = $and91 << 24 >> 24 != 0;
+ if ($tobool75) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $_ = $tobool92 ? 2 : 0;
+ $dimen_sroa_0_0__idx = $sg + 88 + ($_ << 4) | 0;
+ HEAPF64[$dimen_sroa_0_0__idx >> 3] = $add;
+ $dimen_sroa_1_8__idx4 = $sg + 88 + ($_ << 4) + 8 | 0;
+ HEAPF64[$dimen_sroa_1_8__idx4 >> 3] = $add71;
+ label = 19;
+ break;
+ case 18:
+ $_43 = $tobool92 ? 1 : 3;
+ $x100 = $sg + 88 + ($_43 << 4) | 0;
+ HEAPF64[$x100 >> 3] = $add71;
+ $y105 = $sg + 88 + ($_43 << 4) + 8 | 0;
+ HEAPF64[$y105 >> 3] = $add;
+ label = 19;
+ break;
+ case 19:
+ return;
+ }
+}
+function _graph_cleanup($g) {
+ $g = $g | 0;
+ var $u = 0, $drawing = 0, $0 = 0, $xdots = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $id = 0, $4 = 0, $tobool6 = 0, $5 = 0, $6 = 0, $label = 0, $7 = 0, $8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = $g + 48 | 0;
+ $drawing = $u | 0;
+ $0 = HEAP32[$drawing >> 2] | 0;
+ $xdots = $0 + 88 | 0;
+ $1 = HEAP32[$xdots >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $1;
+ _freeXDot($2 | 0);
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[$drawing >> 2] | 0;
+ $id = $3 + 92 | 0;
+ $4 = HEAP32[$id >> 2] | 0;
+ $tobool6 = ($4 | 0) == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _free($4);
+ label = 6;
+ break;
+ case 6:
+ $5 = HEAP32[$drawing >> 2] | 0;
+ $6 = $5;
+ _free($6);
+ HEAP32[$drawing >> 2] = 0;
+ $label = $g + 52 | 0;
+ $7 = HEAP32[$label >> 2] | 0;
+ _free_label($7);
+ $8 = $u;
+ _memset($8 | 0, 0, 248);
+ return;
+ }
+}
+function _charsetToStr($c) {
+ $c = $c | 0;
+ var $call = 0, $s_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($c | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($c | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($c | 0) == 0) {
+ $s_0 = 162544;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $s_0 = 162056;
+ label = 6;
+ break;
+ case 4:
+ $s_0 = 161712;
+ label = 6;
+ break;
+ case 5:
+ $call = _agerr(1, 161416, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $c, tempInt) | 0) | 0;
+ $s_0 = 162544;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $s_0 | 0;
+ }
+ return 0;
+}
+function _start_timer() {
+ _times(165400);
+ return;
+}
+function _elapsed_sec() {
+ var $S = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $S = __stackBase__ | 0;
+ _times($S | 0);
+ STACKTOP = __stackBase__;
+ return +(+(((((HEAP32[$S + 4 >> 2] | 0) + (HEAP32[$S >> 2] | 0) | 0) - (HEAP32[41350] | 0) | 0) - (HEAP32[41351] | 0) | 0) >>> 0 >>> 0) / 60.0);
+}
+function _write_plain($job, $g, $f, $extend) {
+ $job = $job | 0;
+ $g = $g | 0;
+ $f = $f | 0;
+ $extend = $extend | 0;
+ var $pt_sroa_0_0__idx = 0, $pt_sroa_0_0_copyload = 0.0, $pt_sroa_1_8__idx2 = 0, $pt_sroa_1_8_copyload = 0.0, $zoom = 0, $0 = 0.0, $div = 0.0, $div1 = 0.0, $call = 0, $1 = 0, $call2 = 0, $tobool99 = 0, $n_0_in100 = 0, $n_0 = 0, $clustnode = 0, $2 = 0, $tobool4 = 0, $3 = 0, $4 = 0, $call5 = 0, $coord = 0, $5 = 0, $label = 0, $6 = 0, $7 = 0, $8 = 0, $tobool8 = 0, $9 = 0, $10 = 0, $index = 0, $11 = 0, $call10 = 0, $call11 = 0, $text = 0, $12 = 0, $call14 = 0, $lbl_0 = 0, $width = 0, $13 = 0, $14 = 0.0, $height = 0, $15 = 0, $16 = 0.0, $17 = 0, $18 = 0, $call18 = 0, $shape = 0, $19 = 0, $20 = 0, $name20 = 0, $21 = 0, $22 = 0, $call21 = 0, $23 = 0, $call22 = 0, $24 = 0, $cmp = 0, $25 = 0, $call25 = 0, $fillcolor_0 = 0, $call27 = 0, $call28 = 0, $tobool = 0, $call29 = 0, $tobool3197 = 0, $tobool38 = 0, $n_1_in98 = 0, $call33 = 0, $tobool3594 = 0, $e_0_in95 = 0, $26 = 0, $27 = 0, $tobool39 = 0, $arrayidx42 = 0, $28 = 0, $arrayidx44 = 0, $29 = 0, $tport_0 = 0, $hport_0 = 0, $u47 = 0, $spl = 0, $30 = 0, $tobool48 = 0, $31 = 0, $size85 = 0, $32 = 0, $cmp5386 = 0, $33 = 0, $size = 0, $34 = 0, $35 = 0, $i_088 = 0, $splinePoints_087 = 0, $list = 0, $36 = 0, $bz_sroa_1_4__idx7 = 0, $bz_sroa_1_4_copyload8 = 0, $add = 0, $inc = 0, $cmp53 = 0, $splinePoints_0_lcssa = 0, $tail = 0, $37 = 0, $38 = 0, $head = 0, $39 = 0, $40 = 0, $41 = 0, $size6591 = 0, $42 = 0, $cmp6692 = 0, $43 = 0, $i_193 = 0, $list71 = 0, $44 = 0, $bz_sroa_0_0__idx = 0, $bz_sroa_0_0_copyload = 0, $bz_sroa_1_4__idx5 = 0, $bz_sroa_1_4_copyload = 0, $cmp7589 = 0, $j_090 = 0, $arrayidx79 = 0, $inc81 = 0, $cmp75 = 0, $inc84 = 0, $45 = 0, $size65 = 0, $46 = 0, $cmp66 = 0, $label88 = 0, $47 = 0, $48 = 0, $tobool89 = 0, $text95 = 0, $49 = 0, $call96 = 0, $50 = 0, $pos = 0, $51 = 0, $52 = 0, $call100 = 0, $53 = 0, $call101 = 0, $call102 = 0, $call104 = 0, $tobool35 = 0, $call107 = 0, $tobool31 = 0, $call109 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _setYInvert($g);
+ $pt_sroa_0_0__idx = $g + 72 | 0;
+ $pt_sroa_0_0_copyload = +HEAPF64[$pt_sroa_0_0__idx >> 3];
+ $pt_sroa_1_8__idx2 = $g + 80 | 0;
+ $pt_sroa_1_8_copyload = +HEAPF64[$pt_sroa_1_8__idx2 >> 3];
+ $zoom = $job + 352 | 0;
+ $0 = +HEAPF64[$zoom >> 3];
+ _printdouble($f, 120912, $0);
+ $div = $pt_sroa_0_0_copyload / 72.0;
+ _printdouble($f, 153984, $div);
+ $div1 = $pt_sroa_1_8_copyload / 72.0;
+ _printdouble($f, 153984, $div1);
+ $call = _agputc(10, $f) | 0;
+ $1 = $g;
+ $call2 = _agfstnode($1) | 0;
+ $tobool99 = ($call2 | 0) == 0;
+ if ($tobool99) {
+ label = 11;
+ break;
+ } else {
+ $n_0_in100 = $call2;
+ label = 3;
+ break;
+ }
+ case 3:
+ $n_0 = $n_0_in100;
+ $clustnode = $n_0 + 134 | 0;
+ $2 = HEAP8[$clustnode] | 0;
+ $tobool4 = $2 << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 4:
+ $3 = $n_0_in100 + 12 | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $call5 = _agcanonical($4) | 0;
+ _printstring($f, 126768, $call5);
+ $coord = $n_0_in100 + 32 | 0;
+ $5 = $coord;
+ _printpoint($f, $5);
+ $label = $n_0_in100 + 120 | 0;
+ $6 = HEAP32[$label >> 2] | 0;
+ $7 = $6 + 82 | 0;
+ $8 = HEAP8[$7] | 0;
+ $tobool8 = $8 << 24 >> 24 == 0;
+ if ($tobool8) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $9 = $n_0_in100 | 0;
+ $10 = HEAP32[41588] | 0;
+ $index = $10 + 8 | 0;
+ $11 = HEAP32[$index >> 2] | 0;
+ $call10 = _agxget($9, $11) | 0;
+ $call11 = _agcanonical($call10) | 0;
+ $lbl_0 = $call11;
+ label = 7;
+ break;
+ case 6:
+ $text = $6;
+ $12 = HEAP32[$text >> 2] | 0;
+ $call14 = _canon($12) | 0;
+ $lbl_0 = $call14;
+ label = 7;
+ break;
+ case 7:
+ $width = $n_0_in100 + 48 | 0;
+ $13 = $width;
+ $14 = +HEAPF64[$13 >> 3];
+ _printdouble($f, 153984, $14);
+ $height = $n_0_in100 + 56 | 0;
+ $15 = $height;
+ $16 = +HEAPF64[$15 >> 3];
+ _printdouble($f, 153984, $16);
+ _printstring($f, 153984, $lbl_0);
+ $17 = $n_0_in100 | 0;
+ $18 = HEAP32[41560] | 0;
+ $call18 = _late_nnstring($17, $18, 117360) | 0;
+ _printstring($f, 153984, $call18);
+ $shape = $n_0_in100 + 24 | 0;
+ $19 = $shape;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $name20 = $20 | 0;
+ $21 = HEAP32[$name20 >> 2] | 0;
+ _printstring($f, 153984, $21);
+ $22 = HEAP32[41616] | 0;
+ $call21 = _late_nnstring($17, $22, 112152) | 0;
+ _printstring($f, 153984, $call21);
+ $23 = HEAP32[41604] | 0;
+ $call22 = _late_nnstring($17, $23, 107768) | 0;
+ $24 = HEAP8[$call22] | 0;
+ $cmp = $24 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ $fillcolor_0 = $call22;
+ label = 9;
+ break;
+ }
+ case 8:
+ $25 = HEAP32[41616] | 0;
+ $call25 = _late_nnstring($17, $25, 103840) | 0;
+ $fillcolor_0 = $call25;
+ label = 9;
+ break;
+ case 9:
+ _printstring($f, 153984, $fillcolor_0);
+ $call27 = _agputc(10, $f) | 0;
+ label = 10;
+ break;
+ case 10:
+ $call28 = _agnxtnode($1, $n_0_in100) | 0;
+ $tobool = ($call28 | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ $n_0_in100 = $call28;
+ label = 3;
+ break;
+ }
+ case 11:
+ $call29 = _agfstnode($1) | 0;
+ $tobool3197 = ($call29 | 0) == 0;
+ if ($tobool3197) {
+ label = 29;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $tobool38 = $extend << 24 >> 24 == 0;
+ $n_1_in98 = $call29;
+ label = 13;
+ break;
+ case 13:
+ $call33 = _agfstout($1, $n_1_in98) | 0;
+ $tobool3594 = ($call33 | 0) == 0;
+ if ($tobool3594) {
+ label = 28;
+ break;
+ } else {
+ $e_0_in95 = $call33;
+ label = 14;
+ break;
+ }
+ case 14:
+ if ($tobool38) {
+ $hport_0 = 107768;
+ $tport_0 = 107768;
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $26 = $e_0_in95 + 4 | 0;
+ $27 = HEAP32[$26 >> 2] | 0;
+ $tobool39 = ($27 | 0) == 0;
+ if ($tobool39) {
+ $hport_0 = 107768;
+ $tport_0 = 107768;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $arrayidx42 = $27 + 4 | 0;
+ $28 = HEAP32[$arrayidx42 >> 2] | 0;
+ $arrayidx44 = $27 + 8 | 0;
+ $29 = HEAP32[$arrayidx44 >> 2] | 0;
+ $hport_0 = $29;
+ $tport_0 = $28;
+ label = 17;
+ break;
+ case 17:
+ $u47 = $e_0_in95 + 24 | 0;
+ $spl = $u47;
+ $30 = HEAP32[$spl >> 2] | 0;
+ $tobool48 = ($30 | 0) == 0;
+ if ($tobool48) {
+ label = 25;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $31 = HEAP32[$spl >> 2] | 0;
+ $size85 = $31 + 4 | 0;
+ $32 = HEAP32[$size85 >> 2] | 0;
+ $cmp5386 = ($32 | 0) > 0;
+ if ($cmp5386) {
+ label = 19;
+ break;
+ } else {
+ $splinePoints_0_lcssa = 0;
+ label = 21;
+ break;
+ }
+ case 19:
+ $33 = HEAP32[$spl >> 2] | 0;
+ $size = $33 + 4 | 0;
+ $34 = HEAP32[$size >> 2] | 0;
+ $splinePoints_087 = 0;
+ $i_088 = 0;
+ $35 = $31;
+ label = 20;
+ break;
+ case 20:
+ $list = $35 | 0;
+ $36 = HEAP32[$list >> 2] | 0;
+ $bz_sroa_1_4__idx7 = $36 + ($i_088 * 48 & -1) + 4 | 0;
+ $bz_sroa_1_4_copyload8 = HEAP32[$bz_sroa_1_4__idx7 >> 2] | 0;
+ $add = $bz_sroa_1_4_copyload8 + $splinePoints_087 | 0;
+ $inc = $i_088 + 1 | 0;
+ $cmp53 = ($inc | 0) < ($34 | 0);
+ if ($cmp53) {
+ $splinePoints_087 = $add;
+ $i_088 = $inc;
+ $35 = $33;
+ label = 20;
+ break;
+ } else {
+ $splinePoints_0_lcssa = $add;
+ label = 21;
+ break;
+ }
+ case 21:
+ _printstring($f, 0, 99664);
+ $tail = $e_0_in95 + 16 | 0;
+ $37 = HEAP32[$tail >> 2] | 0;
+ $38 = $37;
+ _writenodeandport($f, $38, $tport_0);
+ $head = $e_0_in95 + 12 | 0;
+ $39 = HEAP32[$head >> 2] | 0;
+ $40 = $39;
+ _writenodeandport($f, $40, $hport_0);
+ _printint($f, $splinePoints_0_lcssa);
+ $41 = HEAP32[$spl >> 2] | 0;
+ $size6591 = $41 + 4 | 0;
+ $42 = HEAP32[$size6591 >> 2] | 0;
+ $cmp6692 = ($42 | 0) > 0;
+ if ($cmp6692) {
+ $i_193 = 0;
+ $43 = $41;
+ label = 22;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 22:
+ $list71 = $43 | 0;
+ $44 = HEAP32[$list71 >> 2] | 0;
+ $bz_sroa_0_0__idx = $44 + ($i_193 * 48 & -1) | 0;
+ $bz_sroa_0_0_copyload = HEAP32[$bz_sroa_0_0__idx >> 2] | 0;
+ $bz_sroa_1_4__idx5 = $44 + ($i_193 * 48 & -1) + 4 | 0;
+ $bz_sroa_1_4_copyload = HEAP32[$bz_sroa_1_4__idx5 >> 2] | 0;
+ $cmp7589 = ($bz_sroa_1_4_copyload | 0) > 0;
+ if ($cmp7589) {
+ $j_090 = 0;
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ $arrayidx79 = $bz_sroa_0_0_copyload + ($j_090 << 4) | 0;
+ _printpoint($f, $arrayidx79);
+ $inc81 = $j_090 + 1 | 0;
+ $cmp75 = ($inc81 | 0) < ($bz_sroa_1_4_copyload | 0);
+ if ($cmp75) {
+ $j_090 = $inc81;
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $inc84 = $i_193 + 1 | 0;
+ $45 = HEAP32[$spl >> 2] | 0;
+ $size65 = $45 + 4 | 0;
+ $46 = HEAP32[$size65 >> 2] | 0;
+ $cmp66 = ($inc84 | 0) < ($46 | 0);
+ if ($cmp66) {
+ $i_193 = $inc84;
+ $43 = $45;
+ label = 22;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $label88 = $e_0_in95 + 112 | 0;
+ $47 = $label88;
+ $48 = HEAP32[$47 >> 2] | 0;
+ $tobool89 = ($48 | 0) == 0;
+ if ($tobool89) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $text95 = $48 | 0;
+ $49 = HEAP32[$text95 >> 2] | 0;
+ $call96 = _canon($49) | 0;
+ _printstring($f, 153984, $call96);
+ $50 = HEAP32[$47 >> 2] | 0;
+ $pos = $50 + 56 | 0;
+ _printpoint($f, $pos);
+ label = 27;
+ break;
+ case 27:
+ $51 = $e_0_in95 | 0;
+ $52 = HEAP32[41904] | 0;
+ $call100 = _late_nnstring($51, $52, 117360) | 0;
+ _printstring($f, 153984, $call100);
+ $53 = HEAP32[41958] | 0;
+ $call101 = _late_nnstring($51, $53, 112152) | 0;
+ _printstring($f, 153984, $call101);
+ $call102 = _agputc(10, $f) | 0;
+ $call104 = _agnxtout($1, $e_0_in95) | 0;
+ $tobool35 = ($call104 | 0) == 0;
+ if ($tobool35) {
+ label = 28;
+ break;
+ } else {
+ $e_0_in95 = $call104;
+ label = 14;
+ break;
+ }
+ case 28:
+ $call107 = _agnxtnode($1, $n_1_in98) | 0;
+ $tobool31 = ($call107 | 0) == 0;
+ if ($tobool31) {
+ label = 29;
+ break;
+ } else {
+ $n_1_in98 = $call107;
+ label = 13;
+ break;
+ }
+ case 29:
+ $call109 = _agputs(95656, $f) | 0;
+ return;
+ }
+}
+function _printdouble($f, $prefix, $v) {
+ $f = $f | 0;
+ $prefix = $prefix | 0;
+ $v = +$v;
+ var $buf = 0, $tobool = 0, $call = 0, $arraydecay = 0, $call1 = 0, $call3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $tobool = ($prefix | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _agputs($prefix, $f) | 0;
+ label = 4;
+ break;
+ case 4:
+ $arraydecay = $buf | 0;
+ $call1 = _sprintf($arraydecay | 0, 123320, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $v, tempInt) | 0) | 0;
+ $call3 = _agputs($arraydecay, $f) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _printstring($f, $prefix, $s) {
+ $f = $f | 0;
+ $prefix = $prefix | 0;
+ $s = $s | 0;
+ var $tobool = 0, $call = 0, $call1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($prefix | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _agputs($prefix, $f) | 0;
+ label = 4;
+ break;
+ case 4:
+ $call1 = _agputs($s, $f) | 0;
+ return;
+ }
+}
+function _printpoint($f, $p) {
+ $f = $f | 0;
+ $p = $p | 0;
+ var $x = 0, $0 = 0.0, $div = 0.0, $1 = 0, $tobool = 0, $2 = 0.0, $y = 0, $3 = 0.0, $sub = 0.0, $y1 = 0, $4 = 0.0, $cond = 0.0, $div2 = 0.0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $p | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $div = $0 / 72.0;
+ _printdouble($f, 153984, $div);
+ $1 = HEAP32[41182] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = +HEAPF64[20590];
+ $y = $p + 8 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $sub = $2 - $3;
+ $cond = $sub;
+ label = 5;
+ break;
+ case 4:
+ $y1 = $p + 8 | 0;
+ $4 = +HEAPF64[$y1 >> 3];
+ $cond = $4;
+ label = 5;
+ break;
+ case 5:
+ $div2 = $cond / 72.0;
+ _printdouble($f, 153984, $div2);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _canon($s) {
+ $s = $s | 0;
+ var $call = 0, $call1 = 0;
+ $call = _agstrdup($s) | 0;
+ $call1 = _agcanonical($call) | 0;
+ _agstrfree($call);
+ return $call1 | 0;
+}
+function _writenodeandport($f, $node, $port) {
+ $f = $f | 0;
+ $node = $node | 0;
+ $port = $port | 0;
+ var $clustnode = 0, $0 = 0, $tobool = 0, $name3 = 0, $1 = 0, $call = 0, $add_ptr = 0, $call2 = 0, $call4 = 0, $name_0 = 0, $tobool5 = 0, $2 = 0, $tobool6 = 0, $call8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $clustnode = $node + 134 | 0;
+ $0 = HEAP8[$clustnode] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ $name3 = $node + 12 | 0;
+ $1 = HEAP32[$name3 >> 2] | 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _strchr($1 | 0, 58) | 0;
+ $add_ptr = $call + 1 | 0;
+ $call2 = _canon($add_ptr) | 0;
+ $name_0 = $call2;
+ label = 5;
+ break;
+ case 4:
+ $call4 = _agcanonical($1) | 0;
+ $name_0 = $call4;
+ label = 5;
+ break;
+ case 5:
+ _printstring($f, 153984, $name_0);
+ $tobool5 = ($port | 0) == 0;
+ if ($tobool5) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $2 = HEAP8[$port] | 0;
+ $tobool6 = $2 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call8 = _agcanonical($port) | 0;
+ _printstring($f, 116440, $call8);
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _printint($f, $i) {
+ $f = $f | 0;
+ $i = $i | 0;
+ var $arraydecay = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ _agputs(153984, $f);
+ $arraydecay = __stackBase__ | 0;
+ _sprintf($arraydecay | 0, 117016, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $i, tempInt) | 0);
+ _agputs($arraydecay, $f);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _attach_attrs_and_arrows($g, $sp, $ep) {
+ $g = $g | 0;
+ $sp = $sp | 0;
+ $ep = $ep | 0;
+ var $buf = 0, $xbuffer = 0, $xb = 0, $odim = 0, $0 = 0, $cmp = 0, $arraydecay = 0, $proto = 0, $1 = 0, $n2 = 0, $2 = 0, $3 = 0, $call = 0, $4 = 0, $n4 = 0, $5 = 0, $6 = 0, $call5 = 0, $7 = 0, $n7 = 0, $8 = 0, $9 = 0, $call8 = 0, $10 = 0, $n10 = 0, $11 = 0, $12 = 0, $call11 = 0, $13 = 0, $e13 = 0, $14 = 0, $15 = 0, $call14 = 0, $has_labels = 0, $16 = 0, $and = 0, $tobool = 0, $17 = 0, $n18 = 0, $18 = 0, $19 = 0, $call19 = 0, $20 = 0, $and23 = 0, $tobool24 = 0, $21 = 0, $e27 = 0, $22 = 0, $23 = 0, $call28 = 0, $24 = 0, $and33 = 0, $tobool34 = 0, $25 = 0, $e37 = 0, $26 = 0, $27 = 0, $call38 = 0, $28 = 0, $and43 = 0, $tobool44 = 0, $29 = 0, $e47 = 0, $30 = 0, $31 = 0, $call48 = 0, $32 = 0, $and53 = 0, $tobool54 = 0, $33 = 0, $e57 = 0, $34 = 0, $35 = 0, $call58 = 0, $label = 0, $36 = 0, $tobool61 = 0, $37 = 0, $call63 = 0, $call64 = 0, $call65 = 0, $38 = 0, $text = 0, $39 = 0, $40 = 0, $tobool68 = 0, $ptf_sroa_0_0__idx35 = 0, $ptf_sroa_0_0_copyload36 = 0.0, $ptf_sroa_1_8__idx64 = 0, $ptf_sroa_1_8_copyload65 = 0.0, $arraydecay72 = 0, $41 = 0, $tobool73 = 0, $42 = 0.0, $sub = 0.0, $cond = 0.0, $call75 = 0, $call77 = 0, $43 = 0, $ptf_sroa_0_0__idx32 = 0, $ptf_sroa_0_0_copyload33 = 0.0, $ptf_sroa_1_8__idx60 = 0, $ptf_sroa_1_8_copyload61 = 0.0, $div = 0.0, $call82 = 0, $call84 = 0, $div87 = 0.0, $call88 = 0, $call90 = 0, $44 = 0, $call93 = 0, $45 = 0, $call94 = 0, $tobool95215 = 0, $arraydecay98 = 0, $ptr = 0, $eptr = 0, $buf142 = 0, $ptr206 = 0, $eptr207 = 0, $buf217 = 0, $ptr503 = 0, $eptr504 = 0, $buf514 = 0, $ptr373 = 0, $eptr374 = 0, $ptr466 = 0, $eptr467 = 0, $ptr330 = 0, $eptr331 = 0, $buf341 = 0, $ptr251 = 0, $eptr252 = 0, $n_0220_in = 0, $e_arrows_0219 = 0, $s_arrows_0218 = 0, $n_0220 = 0, $u99 = 0, $coord = 0, $x100 = 0, $46 = 0.0, $47 = 0, $tobool101 = 0, $48 = 0.0, $y105 = 0, $49 = 0, $50 = 0.0, $sub106 = 0.0, $y110 = 0, $51 = 0, $52 = 0.0, $cond112 = 0.0, $pos114 = 0, $53 = 0, $54 = 0, $arrayidx115 = 0, $55 = 0.0, $mul = 0.0, $call116 = 0, $call118 = 0, $56 = 0, $cmp123193 = 0, $k_0194 = 0, $57 = 0, $arrayidx129 = 0, $58 = 0.0, $mul130 = 0.0, $call131 = 0, $call133 = 0, $inc = 0, $59 = 0, $conv122 = 0, $cmp123 = 0, $60 = 0, $61 = 0, $62 = 0, $cmp134 = 0, $call137 = 0, $63 = 0, $64 = 0, $call144 = 0, $65 = 0.0, $y153 = 0, $66 = 0, $67 = 0.0, $sub154 = 0.0, $y158 = 0, $68 = 0, $69 = 0.0, $cond160 = 0.0, $call161 = 0, $70 = 0, $call163 = 0, $ht = 0, $71 = 0, $72 = 0.0, $div167 = 0.0, $call168 = 0, $73 = 0, $74 = 0, $index = 0, $75 = 0, $call170 = 0, $lw = 0, $76 = 0, $77 = 0.0, $rw = 0, $78 = 0, $79 = 0.0, $add = 0.0, $div174 = 0.0, $call175 = 0, $80 = 0, $index176 = 0, $81 = 0, $call178 = 0, $xlabel = 0, $82 = 0, $tobool180 = 0, $ptf_sroa_0_0__idx29 = 0, $83 = 0, $ptf_sroa_0_0_copyload30 = 0.0, $ptf_sroa_1_8__idx57 = 0, $84 = 0, $ptf_sroa_1_8_copyload58 = 0.0, $85 = 0, $tobool187 = 0, $86 = 0.0, $sub190 = 0.0, $cond194 = 0.0, $call195 = 0, $call197 = 0, $shape = 0, $87 = 0, $name = 0, $88 = 0, $call200 = 0, $cmp201 = 0, $shape_info = 0, $89 = 0, $90 = 0, $91 = 0, $call205 = 0, $92 = 0, $93 = 0, $cmp208 = 0, $call211 = 0, $94 = 0, $95 = 0, $call219 = 0, $96 = 0, $tobool222 = 0, $call223 = 0, $tobool225 = 0, $shape_info228 = 0, $97 = 0, $98 = 0, $sides229 = 0, $99 = 0, $100 = 0, $cmp230 = 0, $call233 = 0, $tobool234 = 0, $call236 = 0, $sides_0 = 0, $cmp239 = 0, $_sides_0 = 0, $cmp245195 = 0, $sides_1224 = 0, $vertices = 0, $101 = 0, $width = 0, $102 = 0, $conv291 = 0.0, $height311 = 0, $103 = 0, $height = 0, $104 = 0, $i221_0196 = 0, $cmp248 = 0, $105 = 0, $106 = 0, $cmp253 = 0, $call256 = 0, $107 = 0, $incdec_ptr261 = 0, $108 = 0, $cmp264 = 0, $109 = 0, $x269 = 0, $110 = 0.0, $div270 = 0.0, $111 = 0, $tobool271 = 0, $112 = 0.0, $y275 = 0, $113 = 0.0, $div276 = 0.0, $sub277 = 0.0, $y281 = 0, $114 = 0.0, $div282 = 0.0, $cond284 = 0.0, $call285 = 0, $115 = 0.0, $div289 = 0.0, $conv290 = 0.0, $div292 = 0.0, $mul293 = 0.0, $mul294 = 0.0, $call295 = 0.0, $mul296 = 0.0, $116 = 0, $tobool297 = 0, $117 = 0.0, $118 = 0.0, $div300 = 0.0, $call306 = 0.0, $mul307 = 0.0, $sub308 = 0.0, $119 = 0.0, $div312 = 0.0, $call318 = 0.0, $mul319 = 0.0, $cond321 = 0.0, $call322 = 0, $call325 = 0, $inc327 = 0, $cmp245 = 0, $120 = 0, $index329 = 0, $121 = 0, $122 = 0, $123 = 0, $cmp332 = 0, $call335 = 0, $124 = 0, $125 = 0, $call343 = 0, $126 = 0, $cmp346 = 0, $call349 = 0, $tobool351208 = 0, $e_arrows_1211 = 0, $s_arrows_1210 = 0, $e_0_in209 = 0, $edge_type = 0, $127 = 0, $128 = 0, $cmp355 = 0, $u353 = 0, $spl = 0, $129 = 0, $cmp360 = 0, $130 = 0, $size201 = 0, $131 = 0, $cmp367202 = 0, $e_arrows_2206 = 0, $s_arrows_2205 = 0, $i_0203 = 0, $cmp370 = 0, $132 = 0, $133 = 0, $cmp375 = 0, $call378 = 0, $134 = 0, $incdec_ptr383 = 0, $135 = 0, $list = 0, $136 = 0, $sflag = 0, $137 = 0, $tobool388 = 0, $x396 = 0, $138 = 0.0, $139 = 0, $tobool397 = 0, $140 = 0.0, $y404 = 0, $141 = 0.0, $sub405 = 0.0, $y412 = 0, $142 = 0.0, $cond414 = 0.0, $call415 = 0, $call417 = 0, $s_arrows_3 = 0, $143 = 0, $list421 = 0, $144 = 0, $eflag = 0, $145 = 0, $tobool423 = 0, $x431 = 0, $146 = 0.0, $147 = 0, $tobool432 = 0, $148 = 0.0, $y439 = 0, $149 = 0.0, $sub440 = 0.0, $y447 = 0, $150 = 0.0, $cond449 = 0.0, $call450 = 0, $call452 = 0, $e_arrows_3 = 0, $151 = 0, $list457197 = 0, $152 = 0, $size459198 = 0, $153 = 0, $cmp460199 = 0, $j_0200 = 0, $cmp463 = 0, $154 = 0, $155 = 0, $cmp468 = 0, $call471 = 0, $156 = 0, $incdec_ptr476 = 0, $157 = 0, $list480 = 0, $158 = 0, $list482 = 0, $159 = 0, $ptf_sroa_0_0__idx26 = 0, $ptf_sroa_0_0_copyload27 = 0.0, $ptf_sroa_1_8__idx53 = 0, $ptf_sroa_1_8_copyload54 = 0.0, $160 = 0, $tobool486 = 0, $161 = 0.0, $sub489 = 0.0, $cond493 = 0.0, $call494 = 0, $call496 = 0, $inc498 = 0, $162 = 0, $list457 = 0, $163 = 0, $size459 = 0, $164 = 0, $cmp460 = 0, $inc501 = 0, $165 = 0, $size = 0, $166 = 0, $cmp367 = 0, $e_arrows_2_lcssa = 0, $s_arrows_2_lcssa = 0, $167 = 0, $168 = 0, $169 = 0, $cmp505 = 0, $call508 = 0, $170 = 0, $171 = 0, $call516 = 0, $label518 = 0, $172 = 0, $173 = 0, $tobool519 = 0, $ptf_sroa_0_0__idx23 = 0, $ptf_sroa_0_0_copyload24 = 0.0, $ptf_sroa_1_8__idx49 = 0, $ptf_sroa_1_8_copyload50 = 0.0, $174 = 0, $tobool526 = 0, $175 = 0.0, $sub529 = 0.0, $cond533 = 0.0, $call534 = 0, $call536 = 0, $xlabel539 = 0, $176 = 0, $tobool540 = 0, $ptf_sroa_0_0__idx20 = 0, $177 = 0, $ptf_sroa_0_0_copyload21 = 0.0, $ptf_sroa_1_8__idx45 = 0, $178 = 0, $ptf_sroa_1_8_copyload46 = 0.0, $179 = 0, $tobool547 = 0, $180 = 0.0, $sub550 = 0.0, $cond554 = 0.0, $call555 = 0, $call557 = 0, $head_label = 0, $181 = 0, $tobool560 = 0, $ptf_sroa_0_0__idx17 = 0, $182 = 0, $ptf_sroa_0_0_copyload18 = 0.0, $ptf_sroa_1_8__idx41 = 0, $183 = 0, $ptf_sroa_1_8_copyload42 = 0.0, $184 = 0, $tobool567 = 0, $185 = 0.0, $sub570 = 0.0, $cond574 = 0.0, $call575 = 0, $call577 = 0, $tail_label = 0, $186 = 0, $tobool580 = 0, $ptf_sroa_0_0__idx = 0, $187 = 0, $ptf_sroa_0_0_copyload = 0.0, $ptf_sroa_1_8__idx38 = 0, $188 = 0, $ptf_sroa_1_8_copyload = 0.0, $189 = 0, $tobool587 = 0, $190 = 0.0, $sub590 = 0.0, $cond594 = 0.0, $call595 = 0, $call597 = 0, $s_arrows_4 = 0, $e_arrows_4 = 0, $call600 = 0, $tobool351 = 0, $s_arrows_5 = 0, $e_arrows_5 = 0, $call604 = 0, $tobool95 = 0, $e_arrows_0_lcssa = 0, $s_arrows_0_lcssa = 0, $flags = 0, $191 = 0, $and608 = 0, $tobool609 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 2064 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $xbuffer = __stackBase__ + 1024 | 0;
+ $xb = __stackBase__ + 2048 | 0;
+ $odim = $g + 210 | 0;
+ $0 = HEAP16[$odim >> 1] | 0;
+ $cmp = ($0 & 65535) > 2;
+ _gv_fixLocale(1);
+ _setYInvert($g);
+ $arraydecay = $xbuffer | 0;
+ _agxbinit($xb, 1024, $arraydecay);
+ $proto = $g + 40 | 0;
+ $1 = HEAP32[$proto >> 2] | 0;
+ $n2 = $1 | 0;
+ $2 = HEAP32[$n2 >> 2] | 0;
+ $3 = $2 | 0;
+ $call = _safe_dcl($g, $3, 92192, 107768, 380) | 0;
+ $4 = HEAP32[$proto >> 2] | 0;
+ $n4 = $4 | 0;
+ $5 = HEAP32[$n4 >> 2] | 0;
+ $6 = $5 | 0;
+ $call5 = _safe_dcl($g, $6, 162328, 107768, 380) | 0;
+ $7 = HEAP32[$proto >> 2] | 0;
+ $n7 = $7 | 0;
+ $8 = HEAP32[$n7 >> 2] | 0;
+ $9 = $8 | 0;
+ $call8 = _safe_dcl($g, $9, 158784, 107768, 380) | 0;
+ HEAP32[41552] = $call8;
+ $10 = HEAP32[$proto >> 2] | 0;
+ $n10 = $10 | 0;
+ $11 = HEAP32[$n10 >> 2] | 0;
+ $12 = $11 | 0;
+ $call11 = _safe_dcl($g, $12, 155304, 107768, 380) | 0;
+ HEAP32[41592] = $call11;
+ $13 = HEAP32[$proto >> 2] | 0;
+ $e13 = $13 + 4 | 0;
+ $14 = HEAP32[$e13 >> 2] | 0;
+ $15 = $14 | 0;
+ $call14 = _safe_dcl($g, $15, 92192, 107768, 654) | 0;
+ $has_labels = $g + 153 | 0;
+ $16 = HEAP8[$has_labels] | 0;
+ $and = $16 & 16;
+ $tobool = $and << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $17 = HEAP32[$proto >> 2] | 0;
+ $n18 = $17 | 0;
+ $18 = HEAP32[$n18 >> 2] | 0;
+ $19 = $18 | 0;
+ $call19 = _safe_dcl($g, $19, 151840, 107768, 380) | 0;
+ label = 4;
+ break;
+ case 4:
+ $20 = HEAP8[$has_labels] | 0;
+ $and23 = $20 & 1;
+ $tobool24 = $and23 << 24 >> 24 == 0;
+ if ($tobool24) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $21 = HEAP32[$proto >> 2] | 0;
+ $e27 = $21 + 4 | 0;
+ $22 = HEAP32[$e27 >> 2] | 0;
+ $23 = $22 | 0;
+ $call28 = _safe_dcl($g, $23, 148568, 107768, 654) | 0;
+ label = 6;
+ break;
+ case 6:
+ $24 = HEAP8[$has_labels] | 0;
+ $and33 = $24 & 32;
+ $tobool34 = $and33 << 24 >> 24 == 0;
+ if ($tobool34) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $25 = HEAP32[$proto >> 2] | 0;
+ $e37 = $25 + 4 | 0;
+ $26 = HEAP32[$e37 >> 2] | 0;
+ $27 = $26 | 0;
+ $call38 = _safe_dcl($g, $27, 151840, 107768, 654) | 0;
+ label = 8;
+ break;
+ case 8:
+ $28 = HEAP8[$has_labels] | 0;
+ $and43 = $28 & 2;
+ $tobool44 = $and43 << 24 >> 24 == 0;
+ if ($tobool44) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $29 = HEAP32[$proto >> 2] | 0;
+ $e47 = $29 + 4 | 0;
+ $30 = HEAP32[$e47 >> 2] | 0;
+ $31 = $30 | 0;
+ $call48 = _safe_dcl($g, $31, 145808, 107768, 654) | 0;
+ label = 10;
+ break;
+ case 10:
+ $32 = HEAP8[$has_labels] | 0;
+ $and53 = $32 & 4;
+ $tobool54 = $and53 << 24 >> 24 == 0;
+ if ($tobool54) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $33 = HEAP32[$proto >> 2] | 0;
+ $e57 = $33 + 4 | 0;
+ $34 = HEAP32[$e57 >> 2] | 0;
+ $35 = $34 | 0;
+ $call58 = _safe_dcl($g, $35, 142760, 107768, 654) | 0;
+ label = 12;
+ break;
+ case 12:
+ $label = $g + 52 | 0;
+ $36 = HEAP32[$label >> 2] | 0;
+ $tobool61 = ($36 | 0) == 0;
+ if ($tobool61) {
+ label = 17;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $37 = $g | 0;
+ $call63 = _safe_dcl($g, $37, 148568, 107768, 360) | 0;
+ $call64 = _safe_dcl($g, $37, 139232, 107768, 360) | 0;
+ $call65 = _safe_dcl($g, $37, 136456, 107768, 360) | 0;
+ $38 = HEAP32[$label >> 2] | 0;
+ $text = $38 | 0;
+ $39 = HEAP32[$text >> 2] | 0;
+ $40 = HEAP8[$39] | 0;
+ $tobool68 = $40 << 24 >> 24 == 0;
+ if ($tobool68) {
+ label = 17;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $ptf_sroa_0_0__idx35 = $38 + 56 | 0;
+ $ptf_sroa_0_0_copyload36 = +HEAPF64[$ptf_sroa_0_0__idx35 >> 3];
+ $ptf_sroa_1_8__idx64 = $38 + 64 | 0;
+ $ptf_sroa_1_8_copyload65 = +HEAPF64[$ptf_sroa_1_8__idx64 >> 3];
+ $arraydecay72 = $buf | 0;
+ $41 = HEAP32[41182] | 0;
+ $tobool73 = ($41 | 0) == 0;
+ if ($tobool73) {
+ $cond = $ptf_sroa_1_8_copyload65;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $42 = +HEAPF64[20590];
+ $sub = $42 - $ptf_sroa_1_8_copyload65;
+ $cond = $sub;
+ label = 16;
+ break;
+ case 16:
+ $call75 = _sprintf($arraydecay72 | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $ptf_sroa_0_0_copyload36, HEAPF64[tempInt + 8 >> 3] = $cond, tempInt) | 0) | 0;
+ $call77 = _agset($37, 148568, $arraydecay72) | 0;
+ $43 = HEAP32[$label >> 2] | 0;
+ $ptf_sroa_0_0__idx32 = $43 + 24 | 0;
+ $ptf_sroa_0_0_copyload33 = +HEAPF64[$ptf_sroa_0_0__idx32 >> 3];
+ $ptf_sroa_1_8__idx60 = $43 + 32 | 0;
+ $ptf_sroa_1_8_copyload61 = +HEAPF64[$ptf_sroa_1_8__idx60 >> 3];
+ $div = $ptf_sroa_0_0_copyload33 / 72.0;
+ $call82 = _sprintf($arraydecay72 | 0, 131848, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $div, tempInt) | 0) | 0;
+ $call84 = _agset($37, 139232, $arraydecay72) | 0;
+ $div87 = $ptf_sroa_1_8_copyload61 / 72.0;
+ $call88 = _sprintf($arraydecay72 | 0, 131848, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $div87, tempInt) | 0) | 0;
+ $call90 = _agset($37, 136456, $arraydecay72) | 0;
+ label = 17;
+ break;
+ case 17:
+ $44 = $g | 0;
+ $call93 = _safe_dcl($g, $44, 129992, 107768, 360) | 0;
+ $45 = $g;
+ $call94 = _agfstnode($45) | 0;
+ $tobool95215 = ($call94 | 0) == 0;
+ if ($tobool95215) {
+ $s_arrows_0_lcssa = 0;
+ $e_arrows_0_lcssa = 0;
+ label = 112;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $arraydecay98 = $buf | 0;
+ $ptr = $xb + 4 | 0;
+ $eptr = $xb + 8 | 0;
+ $buf142 = $xb | 0;
+ $ptr206 = $xb + 4 | 0;
+ $eptr207 = $xb + 8 | 0;
+ $buf217 = $xb | 0;
+ $ptr503 = $xb + 4 | 0;
+ $eptr504 = $xb + 8 | 0;
+ $buf514 = $xb | 0;
+ $ptr373 = $xb + 4 | 0;
+ $eptr374 = $xb + 8 | 0;
+ $ptr466 = $xb + 4 | 0;
+ $eptr467 = $xb + 8 | 0;
+ $ptr330 = $xb + 4 | 0;
+ $eptr331 = $xb + 8 | 0;
+ $buf341 = $xb | 0;
+ $ptr251 = $xb + 4 | 0;
+ $eptr252 = $xb + 8 | 0;
+ $s_arrows_0218 = 0;
+ $e_arrows_0219 = 0;
+ $n_0220_in = $call94;
+ label = 19;
+ break;
+ case 19:
+ $n_0220 = $n_0220_in;
+ $u99 = $n_0220_in + 24 | 0;
+ $coord = $n_0220_in + 32 | 0;
+ $x100 = $coord;
+ $46 = +HEAPF64[$x100 >> 3];
+ $47 = HEAP32[41182] | 0;
+ $tobool101 = ($47 | 0) != 0;
+ if ($cmp) {
+ label = 20;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 20:
+ if ($tobool101) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $48 = +HEAPF64[20590];
+ $y105 = $coord + 8 | 0;
+ $49 = $y105;
+ $50 = +HEAPF64[$49 >> 3];
+ $sub106 = $48 - $50;
+ $cond112 = $sub106;
+ label = 23;
+ break;
+ case 22:
+ $y110 = $coord + 8 | 0;
+ $51 = $y110;
+ $52 = +HEAPF64[$51 >> 3];
+ $cond112 = $52;
+ label = 23;
+ break;
+ case 23:
+ $pos114 = $u99 + 124 | 0;
+ $53 = $pos114;
+ $54 = HEAP32[$53 >> 2] | 0;
+ $arrayidx115 = $54 + 16 | 0;
+ $55 = +HEAPF64[$arrayidx115 >> 3];
+ $mul = $55 * 72.0;
+ $call116 = _sprintf($arraydecay98 | 0, 127904, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAPF64[tempInt >> 3] = $46, HEAPF64[tempInt + 8 >> 3] = $cond112, HEAPF64[tempInt + 16 >> 3] = $mul, tempInt) | 0) | 0;
+ $call118 = _agxbput($xb, $arraydecay98) | 0;
+ $56 = HEAP16[$odim >> 1] | 0;
+ $cmp123193 = ($56 & 65535) > 3;
+ if ($cmp123193) {
+ $k_0194 = 3;
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $57 = HEAP32[$53 >> 2] | 0;
+ $arrayidx129 = $57 + ($k_0194 << 3) | 0;
+ $58 = +HEAPF64[$arrayidx129 >> 3];
+ $mul130 = $58 * 72.0;
+ $call131 = _sprintf($arraydecay98 | 0, 125368, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $mul130, tempInt) | 0) | 0;
+ $call133 = _agxbput($xb, $arraydecay98) | 0;
+ $inc = $k_0194 + 1 | 0;
+ $59 = HEAP16[$odim >> 1] | 0;
+ $conv122 = $59 & 65535;
+ $cmp123 = ($inc | 0) < ($conv122 | 0);
+ if ($cmp123) {
+ $k_0194 = $inc;
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $60 = $n_0220_in | 0;
+ $61 = HEAP32[$ptr >> 2] | 0;
+ $62 = HEAP32[$eptr >> 2] | 0;
+ $cmp134 = $61 >>> 0 < $62 >>> 0;
+ if ($cmp134) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $call137 = _agxbmore($xb, 1) | 0;
+ label = 27;
+ break;
+ case 27:
+ $63 = HEAP32[$ptr >> 2] | 0;
+ HEAP8[$63] = 0;
+ $64 = HEAP32[$buf142 >> 2] | 0;
+ HEAP32[$ptr >> 2] = $64;
+ $call144 = _agset($60, 92192, $64) | 0;
+ label = 32;
+ break;
+ case 28:
+ if ($tobool101) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ $65 = +HEAPF64[20590];
+ $y153 = $coord + 8 | 0;
+ $66 = $y153;
+ $67 = +HEAPF64[$66 >> 3];
+ $sub154 = $65 - $67;
+ $cond160 = $sub154;
+ label = 31;
+ break;
+ case 30:
+ $y158 = $n_0220_in + 40 | 0;
+ $68 = $y158;
+ $69 = +HEAPF64[$68 >> 3];
+ $cond160 = $69;
+ label = 31;
+ break;
+ case 31:
+ $call161 = _sprintf($arraydecay98 | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $46, HEAPF64[tempInt + 8 >> 3] = $cond160, tempInt) | 0) | 0;
+ $70 = $n_0220_in | 0;
+ $call163 = _agset($70, 92192, $arraydecay98) | 0;
+ label = 32;
+ break;
+ case 32:
+ $ht = $n_0220_in + 96 | 0;
+ $71 = $ht;
+ $72 = +HEAPF64[$71 >> 3];
+ $div167 = $72 / 72.0;
+ $call168 = _sprintf($arraydecay98 | 0, 123320, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $div167, tempInt) | 0) | 0;
+ $73 = $n_0220_in | 0;
+ $74 = HEAP32[41592] | 0;
+ $index = $74 + 8 | 0;
+ $75 = HEAP32[$index >> 2] | 0;
+ $call170 = _agxset($73, $75, $arraydecay98) | 0;
+ $lw = $n_0220_in + 104 | 0;
+ $76 = $lw;
+ $77 = +HEAPF64[$76 >> 3];
+ $rw = $n_0220_in + 112 | 0;
+ $78 = $rw;
+ $79 = +HEAPF64[$78 >> 3];
+ $add = $77 + $79;
+ $div174 = $add / 72.0;
+ $call175 = _sprintf($arraydecay98 | 0, 123320, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $div174, tempInt) | 0) | 0;
+ $80 = HEAP32[41552] | 0;
+ $index176 = $80 + 8 | 0;
+ $81 = HEAP32[$index176 >> 2] | 0;
+ $call178 = _agxset($73, $81, $arraydecay98) | 0;
+ $xlabel = $n_0220_in + 124 | 0;
+ $82 = HEAP32[$xlabel >> 2] | 0;
+ $tobool180 = ($82 | 0) == 0;
+ if ($tobool180) {
+ label = 36;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $ptf_sroa_0_0__idx29 = $82 + 56 | 0;
+ $83 = $ptf_sroa_0_0__idx29;
+ $ptf_sroa_0_0_copyload30 = +HEAPF64[$83 >> 3];
+ $ptf_sroa_1_8__idx57 = $82 + 64 | 0;
+ $84 = $ptf_sroa_1_8__idx57;
+ $ptf_sroa_1_8_copyload58 = +HEAPF64[$84 >> 3];
+ $85 = HEAP32[41182] | 0;
+ $tobool187 = ($85 | 0) == 0;
+ if ($tobool187) {
+ $cond194 = $ptf_sroa_1_8_copyload58;
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $86 = +HEAPF64[20590];
+ $sub190 = $86 - $ptf_sroa_1_8_copyload58;
+ $cond194 = $sub190;
+ label = 35;
+ break;
+ case 35:
+ $call195 = _sprintf($arraydecay98 | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $ptf_sroa_0_0_copyload30, HEAPF64[tempInt + 8 >> 3] = $cond194, tempInt) | 0) | 0;
+ $call197 = _agset($73, 151840, $arraydecay98) | 0;
+ label = 36;
+ break;
+ case 36:
+ $shape = $u99;
+ $87 = HEAP32[$shape >> 2] | 0;
+ $name = $87 | 0;
+ $88 = HEAP32[$name >> 2] | 0;
+ $call200 = _strcmp($88 | 0, 121808) | 0;
+ $cmp201 = ($call200 | 0) == 0;
+ if ($cmp201) {
+ label = 37;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 37:
+ $shape_info = $u99 + 4 | 0;
+ $89 = $shape_info;
+ $90 = HEAP32[$89 >> 2] | 0;
+ $91 = $90;
+ _set_record_rects($n_0220, $91, $xb);
+ $call205 = _agxbpop($xb) | 0;
+ $92 = HEAP32[$ptr206 >> 2] | 0;
+ $93 = HEAP32[$eptr207 >> 2] | 0;
+ $cmp208 = $92 >>> 0 < $93 >>> 0;
+ if ($cmp208) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $call211 = _agxbmore($xb, 1) | 0;
+ label = 39;
+ break;
+ case 39:
+ $94 = HEAP32[$ptr206 >> 2] | 0;
+ HEAP8[$94] = 0;
+ $95 = HEAP32[$buf217 >> 2] | 0;
+ HEAP32[$ptr206 >> 2] = $95;
+ $call219 = _agset($73, 162328, $95) | 0;
+ label = 64;
+ break;
+ case 40:
+ $96 = HEAP32[41558] | 0;
+ $tobool222 = ($96 | 0) == 0;
+ if ($tobool222) {
+ label = 64;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $call223 = _isPolygon($n_0220) | 0;
+ $tobool225 = $call223 << 24 >> 24 == 0;
+ if ($tobool225) {
+ label = 64;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $shape_info228 = $u99 + 4 | 0;
+ $97 = $shape_info228;
+ $98 = HEAP32[$97 >> 2] | 0;
+ $sides229 = $98 + 8 | 0;
+ $99 = $sides229;
+ $100 = HEAP32[$99 >> 2] | 0;
+ $cmp230 = ($100 | 0) < 3;
+ if ($cmp230) {
+ label = 43;
+ break;
+ } else {
+ $sides_1224 = $100;
+ label = 46;
+ break;
+ }
+ case 43:
+ $call233 = _agget($73, 121240) | 0;
+ $tobool234 = ($call233 | 0) == 0;
+ if ($tobool234) {
+ $sides_0 = 8;
+ label = 45;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $call236 = _atoi($call233 | 0) | 0;
+ $sides_0 = $call236;
+ label = 45;
+ break;
+ case 45:
+ $cmp239 = ($sides_0 | 0) < 3;
+ $_sides_0 = $cmp239 ? 8 : $sides_0;
+ $cmp245195 = ($_sides_0 | 0) > 0;
+ if ($cmp245195) {
+ $sides_1224 = $_sides_0;
+ label = 46;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 46:
+ $vertices = $98 + 44 | 0;
+ $101 = $vertices;
+ $width = $u99 + 24 | 0;
+ $102 = $width;
+ $conv291 = +($sides_1224 | 0);
+ $height311 = $u99 + 32 | 0;
+ $103 = $height311;
+ $height = $u99 + 32 | 0;
+ $104 = $height;
+ $i221_0196 = 0;
+ label = 47;
+ break;
+ case 47:
+ $cmp248 = ($i221_0196 | 0) > 0;
+ if ($cmp248) {
+ label = 48;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 48:
+ $105 = HEAP32[$ptr251 >> 2] | 0;
+ $106 = HEAP32[$eptr252 >> 2] | 0;
+ $cmp253 = $105 >>> 0 < $106 >>> 0;
+ if ($cmp253) {
+ label = 50;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $call256 = _agxbmore($xb, 1) | 0;
+ label = 50;
+ break;
+ case 50:
+ $107 = HEAP32[$ptr251 >> 2] | 0;
+ $incdec_ptr261 = $107 + 1 | 0;
+ HEAP32[$ptr251 >> 2] = $incdec_ptr261;
+ HEAP8[$107] = 32;
+ label = 51;
+ break;
+ case 51:
+ $108 = HEAP32[$99 >> 2] | 0;
+ $cmp264 = ($108 | 0) > 2;
+ if ($cmp264) {
+ label = 52;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 52:
+ $109 = HEAP32[$101 >> 2] | 0;
+ $x269 = $109 + ($i221_0196 << 4) | 0;
+ $110 = +HEAPF64[$x269 >> 3];
+ $div270 = $110 / 72.0;
+ $111 = HEAP32[41182] | 0;
+ $tobool271 = ($111 | 0) == 0;
+ if ($tobool271) {
+ label = 54;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $112 = +HEAPF64[20592];
+ $y275 = $109 + ($i221_0196 << 4) + 8 | 0;
+ $113 = +HEAPF64[$y275 >> 3];
+ $div276 = $113 / 72.0;
+ $sub277 = $112 - $div276;
+ $cond284 = $sub277;
+ label = 55;
+ break;
+ case 54:
+ $y281 = $109 + ($i221_0196 << 4) + 8 | 0;
+ $114 = +HEAPF64[$y281 >> 3];
+ $div282 = $114 / 72.0;
+ $cond284 = $div282;
+ label = 55;
+ break;
+ case 55:
+ $call285 = _sprintf($arraydecay98 | 0, 120536, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $div270, HEAPF64[tempInt + 8 >> 3] = $cond284, tempInt) | 0) | 0;
+ label = 60;
+ break;
+ case 56:
+ $115 = +HEAPF64[$102 >> 3];
+ $div289 = $115 * .5;
+ $conv290 = +($i221_0196 | 0);
+ $div292 = $conv290 / $conv291;
+ $mul293 = $div292 * 3.141592653589793;
+ $mul294 = $mul293 * 2.0;
+ $call295 = +Math_cos(+$mul294);
+ $mul296 = $div289 * $call295;
+ $116 = HEAP32[41182] | 0;
+ $tobool297 = ($116 | 0) == 0;
+ if ($tobool297) {
+ label = 58;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $117 = +HEAPF64[20592];
+ $118 = +HEAPF64[$104 >> 3];
+ $div300 = $118 * .5;
+ $call306 = +Math_sin(+$mul294);
+ $mul307 = $div300 * $call306;
+ $sub308 = $117 - $mul307;
+ $cond321 = $sub308;
+ label = 59;
+ break;
+ case 58:
+ $119 = +HEAPF64[$103 >> 3];
+ $div312 = $119 * .5;
+ $call318 = +Math_sin(+$mul294);
+ $mul319 = $div312 * $call318;
+ $cond321 = $mul319;
+ label = 59;
+ break;
+ case 59:
+ $call322 = _sprintf($arraydecay98 | 0, 120536, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $mul296, HEAPF64[tempInt + 8 >> 3] = $cond321, tempInt) | 0) | 0;
+ label = 60;
+ break;
+ case 60:
+ $call325 = _agxbput($xb, $arraydecay98) | 0;
+ $inc327 = $i221_0196 + 1 | 0;
+ $cmp245 = ($inc327 | 0) < ($sides_1224 | 0);
+ if ($cmp245) {
+ $i221_0196 = $inc327;
+ label = 47;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 61:
+ $120 = HEAP32[41558] | 0;
+ $index329 = $120 + 8 | 0;
+ $121 = HEAP32[$index329 >> 2] | 0;
+ $122 = HEAP32[$ptr330 >> 2] | 0;
+ $123 = HEAP32[$eptr331 >> 2] | 0;
+ $cmp332 = $122 >>> 0 < $123 >>> 0;
+ if ($cmp332) {
+ label = 63;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 62:
+ $call335 = _agxbmore($xb, 1) | 0;
+ label = 63;
+ break;
+ case 63:
+ $124 = HEAP32[$ptr330 >> 2] | 0;
+ HEAP8[$124] = 0;
+ $125 = HEAP32[$buf341 >> 2] | 0;
+ HEAP32[$ptr330 >> 2] = $125;
+ $call343 = _agxset($73, $121, $125) | 0;
+ label = 64;
+ break;
+ case 64:
+ $126 = HEAP32[41356] | 0;
+ $cmp346 = ($126 | 0) > 0;
+ if ($cmp346) {
+ label = 65;
+ break;
+ } else {
+ $e_arrows_5 = $e_arrows_0219;
+ $s_arrows_5 = $s_arrows_0218;
+ label = 111;
+ break;
+ }
+ case 65:
+ $call349 = _agfstout($45, $n_0220_in) | 0;
+ $tobool351208 = ($call349 | 0) == 0;
+ if ($tobool351208) {
+ $e_arrows_5 = $e_arrows_0219;
+ $s_arrows_5 = $s_arrows_0218;
+ label = 111;
+ break;
+ } else {
+ $e_0_in209 = $call349;
+ $s_arrows_1210 = $s_arrows_0218;
+ $e_arrows_1211 = $e_arrows_0219;
+ label = 66;
+ break;
+ }
+ case 66:
+ $edge_type = $e_0_in209 + 128 | 0;
+ $127 = $edge_type;
+ $128 = HEAP8[$127] | 0;
+ $cmp355 = $128 << 24 >> 24 == 6;
+ if ($cmp355) {
+ $e_arrows_4 = $e_arrows_1211;
+ $s_arrows_4 = $s_arrows_1210;
+ label = 110;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 67:
+ $u353 = $e_0_in209 + 24 | 0;
+ $spl = $u353;
+ $129 = HEAP32[$spl >> 2] | 0;
+ $cmp360 = ($129 | 0) == 0;
+ if ($cmp360) {
+ $e_arrows_4 = $e_arrows_1211;
+ $s_arrows_4 = $s_arrows_1210;
+ label = 110;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $130 = HEAP32[$spl >> 2] | 0;
+ $size201 = $130 + 4 | 0;
+ $131 = HEAP32[$size201 >> 2] | 0;
+ $cmp367202 = ($131 | 0) > 0;
+ if ($cmp367202) {
+ $i_0203 = 0;
+ $s_arrows_2205 = $s_arrows_1210;
+ $e_arrows_2206 = $e_arrows_1211;
+ label = 69;
+ break;
+ } else {
+ $s_arrows_2_lcssa = $s_arrows_1210;
+ $e_arrows_2_lcssa = $e_arrows_1211;
+ label = 92;
+ break;
+ }
+ case 69:
+ $cmp370 = ($i_0203 | 0) > 0;
+ if ($cmp370) {
+ label = 70;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 70:
+ $132 = HEAP32[$ptr373 >> 2] | 0;
+ $133 = HEAP32[$eptr374 >> 2] | 0;
+ $cmp375 = $132 >>> 0 < $133 >>> 0;
+ if ($cmp375) {
+ label = 72;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 71:
+ $call378 = _agxbmore($xb, 1) | 0;
+ label = 72;
+ break;
+ case 72:
+ $134 = HEAP32[$ptr373 >> 2] | 0;
+ $incdec_ptr383 = $134 + 1 | 0;
+ HEAP32[$ptr373 >> 2] = $incdec_ptr383;
+ HEAP8[$134] = 59;
+ label = 73;
+ break;
+ case 73:
+ $135 = HEAP32[$spl >> 2] | 0;
+ $list = $135 | 0;
+ $136 = HEAP32[$list >> 2] | 0;
+ $sflag = $136 + ($i_0203 * 48 & -1) + 8 | 0;
+ $137 = HEAP32[$sflag >> 2] | 0;
+ $tobool388 = ($137 | 0) == 0;
+ if ($tobool388) {
+ $s_arrows_3 = $s_arrows_2205;
+ label = 78;
+ break;
+ } else {
+ label = 74;
+ break;
+ }
+ case 74:
+ $x396 = $136 + ($i_0203 * 48 & -1) + 16 | 0;
+ $138 = +HEAPF64[$x396 >> 3];
+ $139 = HEAP32[41182] | 0;
+ $tobool397 = ($139 | 0) == 0;
+ if ($tobool397) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $140 = +HEAPF64[20590];
+ $y404 = $136 + ($i_0203 * 48 & -1) + 24 | 0;
+ $141 = +HEAPF64[$y404 >> 3];
+ $sub405 = $140 - $141;
+ $cond414 = $sub405;
+ label = 77;
+ break;
+ case 76:
+ $y412 = $136 + ($i_0203 * 48 & -1) + 24 | 0;
+ $142 = +HEAPF64[$y412 >> 3];
+ $cond414 = $142;
+ label = 77;
+ break;
+ case 77:
+ $call415 = _sprintf($arraydecay98 | 0, 119848, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $138, HEAPF64[tempInt + 8 >> 3] = $cond414, tempInt) | 0) | 0;
+ $call417 = _agxbput($xb, $arraydecay98) | 0;
+ $s_arrows_3 = 1;
+ label = 78;
+ break;
+ case 78:
+ $143 = HEAP32[$spl >> 2] | 0;
+ $list421 = $143 | 0;
+ $144 = HEAP32[$list421 >> 2] | 0;
+ $eflag = $144 + ($i_0203 * 48 & -1) + 12 | 0;
+ $145 = HEAP32[$eflag >> 2] | 0;
+ $tobool423 = ($145 | 0) == 0;
+ if ($tobool423) {
+ $e_arrows_3 = $e_arrows_2206;
+ label = 83;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 79:
+ $x431 = $144 + ($i_0203 * 48 & -1) + 32 | 0;
+ $146 = +HEAPF64[$x431 >> 3];
+ $147 = HEAP32[41182] | 0;
+ $tobool432 = ($147 | 0) == 0;
+ if ($tobool432) {
+ label = 81;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 80:
+ $148 = +HEAPF64[20590];
+ $y439 = $144 + ($i_0203 * 48 & -1) + 40 | 0;
+ $149 = +HEAPF64[$y439 >> 3];
+ $sub440 = $148 - $149;
+ $cond449 = $sub440;
+ label = 82;
+ break;
+ case 81:
+ $y447 = $144 + ($i_0203 * 48 & -1) + 40 | 0;
+ $150 = +HEAPF64[$y447 >> 3];
+ $cond449 = $150;
+ label = 82;
+ break;
+ case 82:
+ $call450 = _sprintf($arraydecay98 | 0, 119320, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $146, HEAPF64[tempInt + 8 >> 3] = $cond449, tempInt) | 0) | 0;
+ $call452 = _agxbput($xb, $arraydecay98) | 0;
+ $e_arrows_3 = 1;
+ label = 83;
+ break;
+ case 83:
+ $151 = HEAP32[$spl >> 2] | 0;
+ $list457197 = $151 | 0;
+ $152 = HEAP32[$list457197 >> 2] | 0;
+ $size459198 = $152 + ($i_0203 * 48 & -1) + 4 | 0;
+ $153 = HEAP32[$size459198 >> 2] | 0;
+ $cmp460199 = ($153 | 0) > 0;
+ if ($cmp460199) {
+ $j_0200 = 0;
+ label = 84;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 84:
+ $cmp463 = ($j_0200 | 0) > 0;
+ if ($cmp463) {
+ label = 85;
+ break;
+ } else {
+ label = 88;
+ break;
+ }
+ case 85:
+ $154 = HEAP32[$ptr466 >> 2] | 0;
+ $155 = HEAP32[$eptr467 >> 2] | 0;
+ $cmp468 = $154 >>> 0 < $155 >>> 0;
+ if ($cmp468) {
+ label = 87;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 86:
+ $call471 = _agxbmore($xb, 1) | 0;
+ label = 87;
+ break;
+ case 87:
+ $156 = HEAP32[$ptr466 >> 2] | 0;
+ $incdec_ptr476 = $156 + 1 | 0;
+ HEAP32[$ptr466 >> 2] = $incdec_ptr476;
+ HEAP8[$156] = 32;
+ label = 88;
+ break;
+ case 88:
+ $157 = HEAP32[$spl >> 2] | 0;
+ $list480 = $157 | 0;
+ $158 = HEAP32[$list480 >> 2] | 0;
+ $list482 = $158 + ($i_0203 * 48 & -1) | 0;
+ $159 = HEAP32[$list482 >> 2] | 0;
+ $ptf_sroa_0_0__idx26 = $159 + ($j_0200 << 4) | 0;
+ $ptf_sroa_0_0_copyload27 = +HEAPF64[$ptf_sroa_0_0__idx26 >> 3];
+ $ptf_sroa_1_8__idx53 = $159 + ($j_0200 << 4) + 8 | 0;
+ $ptf_sroa_1_8_copyload54 = +HEAPF64[$ptf_sroa_1_8__idx53 >> 3];
+ $160 = HEAP32[41182] | 0;
+ $tobool486 = ($160 | 0) == 0;
+ if ($tobool486) {
+ $cond493 = $ptf_sroa_1_8_copyload54;
+ label = 90;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 89:
+ $161 = +HEAPF64[20590];
+ $sub489 = $161 - $ptf_sroa_1_8_copyload54;
+ $cond493 = $sub489;
+ label = 90;
+ break;
+ case 90:
+ $call494 = _sprintf($arraydecay98 | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $ptf_sroa_0_0_copyload27, HEAPF64[tempInt + 8 >> 3] = $cond493, tempInt) | 0) | 0;
+ $call496 = _agxbput($xb, $arraydecay98) | 0;
+ $inc498 = $j_0200 + 1 | 0;
+ $162 = HEAP32[$spl >> 2] | 0;
+ $list457 = $162 | 0;
+ $163 = HEAP32[$list457 >> 2] | 0;
+ $size459 = $163 + ($i_0203 * 48 & -1) + 4 | 0;
+ $164 = HEAP32[$size459 >> 2] | 0;
+ $cmp460 = ($inc498 | 0) < ($164 | 0);
+ if ($cmp460) {
+ $j_0200 = $inc498;
+ label = 84;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 91:
+ $inc501 = $i_0203 + 1 | 0;
+ $165 = HEAP32[$spl >> 2] | 0;
+ $size = $165 + 4 | 0;
+ $166 = HEAP32[$size >> 2] | 0;
+ $cmp367 = ($inc501 | 0) < ($166 | 0);
+ if ($cmp367) {
+ $i_0203 = $inc501;
+ $s_arrows_2205 = $s_arrows_3;
+ $e_arrows_2206 = $e_arrows_3;
+ label = 69;
+ break;
+ } else {
+ $s_arrows_2_lcssa = $s_arrows_3;
+ $e_arrows_2_lcssa = $e_arrows_3;
+ label = 92;
+ break;
+ }
+ case 92:
+ $167 = $e_0_in209 | 0;
+ $168 = HEAP32[$ptr503 >> 2] | 0;
+ $169 = HEAP32[$eptr504 >> 2] | 0;
+ $cmp505 = $168 >>> 0 < $169 >>> 0;
+ if ($cmp505) {
+ label = 94;
+ break;
+ } else {
+ label = 93;
+ break;
+ }
+ case 93:
+ $call508 = _agxbmore($xb, 1) | 0;
+ label = 94;
+ break;
+ case 94:
+ $170 = HEAP32[$ptr503 >> 2] | 0;
+ HEAP8[$170] = 0;
+ $171 = HEAP32[$buf514 >> 2] | 0;
+ HEAP32[$ptr503 >> 2] = $171;
+ $call516 = _agset($167, 92192, $171) | 0;
+ $label518 = $e_0_in209 + 112 | 0;
+ $172 = $label518;
+ $173 = HEAP32[$172 >> 2] | 0;
+ $tobool519 = ($173 | 0) == 0;
+ if ($tobool519) {
+ label = 98;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 95:
+ $ptf_sroa_0_0__idx23 = $173 + 56 | 0;
+ $ptf_sroa_0_0_copyload24 = +HEAPF64[$ptf_sroa_0_0__idx23 >> 3];
+ $ptf_sroa_1_8__idx49 = $173 + 64 | 0;
+ $ptf_sroa_1_8_copyload50 = +HEAPF64[$ptf_sroa_1_8__idx49 >> 3];
+ $174 = HEAP32[41182] | 0;
+ $tobool526 = ($174 | 0) == 0;
+ if ($tobool526) {
+ $cond533 = $ptf_sroa_1_8_copyload50;
+ label = 97;
+ break;
+ } else {
+ label = 96;
+ break;
+ }
+ case 96:
+ $175 = +HEAPF64[20590];
+ $sub529 = $175 - $ptf_sroa_1_8_copyload50;
+ $cond533 = $sub529;
+ label = 97;
+ break;
+ case 97:
+ $call534 = _sprintf($arraydecay98 | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $ptf_sroa_0_0_copyload24, HEAPF64[tempInt + 8 >> 3] = $cond533, tempInt) | 0) | 0;
+ $call536 = _agset($167, 148568, $arraydecay98) | 0;
+ label = 98;
+ break;
+ case 98:
+ $xlabel539 = $e_0_in209 + 124 | 0;
+ $176 = HEAP32[$xlabel539 >> 2] | 0;
+ $tobool540 = ($176 | 0) == 0;
+ if ($tobool540) {
+ label = 102;
+ break;
+ } else {
+ label = 99;
+ break;
+ }
+ case 99:
+ $ptf_sroa_0_0__idx20 = $176 + 56 | 0;
+ $177 = $ptf_sroa_0_0__idx20;
+ $ptf_sroa_0_0_copyload21 = +HEAPF64[$177 >> 3];
+ $ptf_sroa_1_8__idx45 = $176 + 64 | 0;
+ $178 = $ptf_sroa_1_8__idx45;
+ $ptf_sroa_1_8_copyload46 = +HEAPF64[$178 >> 3];
+ $179 = HEAP32[41182] | 0;
+ $tobool547 = ($179 | 0) == 0;
+ if ($tobool547) {
+ $cond554 = $ptf_sroa_1_8_copyload46;
+ label = 101;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 100:
+ $180 = +HEAPF64[20590];
+ $sub550 = $180 - $ptf_sroa_1_8_copyload46;
+ $cond554 = $sub550;
+ label = 101;
+ break;
+ case 101:
+ $call555 = _sprintf($arraydecay98 | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $ptf_sroa_0_0_copyload21, HEAPF64[tempInt + 8 >> 3] = $cond554, tempInt) | 0) | 0;
+ $call557 = _agset($167, 151840, $arraydecay98) | 0;
+ label = 102;
+ break;
+ case 102:
+ $head_label = $e_0_in209 + 116 | 0;
+ $181 = HEAP32[$head_label >> 2] | 0;
+ $tobool560 = ($181 | 0) == 0;
+ if ($tobool560) {
+ label = 106;
+ break;
+ } else {
+ label = 103;
+ break;
+ }
+ case 103:
+ $ptf_sroa_0_0__idx17 = $181 + 56 | 0;
+ $182 = $ptf_sroa_0_0__idx17;
+ $ptf_sroa_0_0_copyload18 = +HEAPF64[$182 >> 3];
+ $ptf_sroa_1_8__idx41 = $181 + 64 | 0;
+ $183 = $ptf_sroa_1_8__idx41;
+ $ptf_sroa_1_8_copyload42 = +HEAPF64[$183 >> 3];
+ $184 = HEAP32[41182] | 0;
+ $tobool567 = ($184 | 0) == 0;
+ if ($tobool567) {
+ $cond574 = $ptf_sroa_1_8_copyload42;
+ label = 105;
+ break;
+ } else {
+ label = 104;
+ break;
+ }
+ case 104:
+ $185 = +HEAPF64[20590];
+ $sub570 = $185 - $ptf_sroa_1_8_copyload42;
+ $cond574 = $sub570;
+ label = 105;
+ break;
+ case 105:
+ $call575 = _sprintf($arraydecay98 | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $ptf_sroa_0_0_copyload18, HEAPF64[tempInt + 8 >> 3] = $cond574, tempInt) | 0) | 0;
+ $call577 = _agset($167, 145808, $arraydecay98) | 0;
+ label = 106;
+ break;
+ case 106:
+ $tail_label = $e_0_in209 + 120 | 0;
+ $186 = HEAP32[$tail_label >> 2] | 0;
+ $tobool580 = ($186 | 0) == 0;
+ if ($tobool580) {
+ $e_arrows_4 = $e_arrows_2_lcssa;
+ $s_arrows_4 = $s_arrows_2_lcssa;
+ label = 110;
+ break;
+ } else {
+ label = 107;
+ break;
+ }
+ case 107:
+ $ptf_sroa_0_0__idx = $186 + 56 | 0;
+ $187 = $ptf_sroa_0_0__idx;
+ $ptf_sroa_0_0_copyload = +HEAPF64[$187 >> 3];
+ $ptf_sroa_1_8__idx38 = $186 + 64 | 0;
+ $188 = $ptf_sroa_1_8__idx38;
+ $ptf_sroa_1_8_copyload = +HEAPF64[$188 >> 3];
+ $189 = HEAP32[41182] | 0;
+ $tobool587 = ($189 | 0) == 0;
+ if ($tobool587) {
+ $cond594 = $ptf_sroa_1_8_copyload;
+ label = 109;
+ break;
+ } else {
+ label = 108;
+ break;
+ }
+ case 108:
+ $190 = +HEAPF64[20590];
+ $sub590 = $190 - $ptf_sroa_1_8_copyload;
+ $cond594 = $sub590;
+ label = 109;
+ break;
+ case 109:
+ $call595 = _sprintf($arraydecay98 | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $ptf_sroa_0_0_copyload, HEAPF64[tempInt + 8 >> 3] = $cond594, tempInt) | 0) | 0;
+ $call597 = _agset($167, 142760, $arraydecay98) | 0;
+ $e_arrows_4 = $e_arrows_2_lcssa;
+ $s_arrows_4 = $s_arrows_2_lcssa;
+ label = 110;
+ break;
+ case 110:
+ $call600 = _agnxtout($45, $e_0_in209) | 0;
+ $tobool351 = ($call600 | 0) == 0;
+ if ($tobool351) {
+ $e_arrows_5 = $e_arrows_4;
+ $s_arrows_5 = $s_arrows_4;
+ label = 111;
+ break;
+ } else {
+ $e_0_in209 = $call600;
+ $s_arrows_1210 = $s_arrows_4;
+ $e_arrows_1211 = $e_arrows_4;
+ label = 66;
+ break;
+ }
+ case 111:
+ $call604 = _agnxtnode($45, $n_0220_in) | 0;
+ $tobool95 = ($call604 | 0) == 0;
+ if ($tobool95) {
+ $s_arrows_0_lcssa = $s_arrows_5;
+ $e_arrows_0_lcssa = $e_arrows_5;
+ label = 112;
+ break;
+ } else {
+ $s_arrows_0218 = $s_arrows_5;
+ $e_arrows_0219 = $e_arrows_5;
+ $n_0220_in = $call604;
+ label = 19;
+ break;
+ }
+ case 112:
+ _rec_attach_bb($g, $call93);
+ _agxbfree($xb);
+ $flags = $g + 168 | 0;
+ $191 = HEAP16[$flags >> 1] | 0;
+ $and608 = $191 & 1;
+ $tobool609 = $and608 << 16 >> 16 == 0;
+ if ($tobool609) {
+ label = 114;
+ break;
+ } else {
+ label = 113;
+ break;
+ }
+ case 113:
+ _undoClusterEdges($g);
+ label = 114;
+ break;
+ case 114:
+ HEAP32[$sp >> 2] = $s_arrows_0_lcssa;
+ HEAP32[$ep >> 2] = $e_arrows_0_lcssa;
+ _gv_fixLocale(0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _set_record_rects($n, $f, $xb) {
+ $n = $n | 0;
+ $f = $f | 0;
+ $xb = $xb | 0;
+ var $buf = 0, $n_flds = 0, $0 = 0, $cmp = 0, $arraydecay = 0, $x = 0, $1 = 0.0, $x1 = 0, $2 = 0.0, $add = 0.0, $3 = 0, $tobool = 0, $4 = 0.0, $y = 0, $5 = 0.0, $y6 = 0, $6 = 0.0, $add7 = 0.0, $sub = 0.0, $y10 = 0, $7 = 0.0, $y13 = 0, $8 = 0.0, $add14 = 0.0, $cond = 0.0, $x16 = 0, $9 = 0.0, $10 = 0.0, $add20 = 0.0, $11 = 0, $tobool21 = 0, $12 = 0.0, $y25 = 0, $13 = 0.0, $y28 = 0, $14 = 0.0, $add29 = 0.0, $sub30 = 0.0, $y34 = 0, $15 = 0.0, $y37 = 0, $16 = 0.0, $add38 = 0.0, $cond40 = 0.0, $call = 0, $call42 = 0, $_pr = 0, $17 = 0, $cmp4418 = 0, $fld = 0, $i_019 = 0, $18 = 0, $arrayidx = 0, $19 = 0, $inc = 0, $20 = 0, $cmp44 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $n_flds = $f + 48 | 0;
+ $0 = HEAP32[$n_flds >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $17 = $0;
+ label = 10;
+ break;
+ }
+ case 3:
+ $arraydecay = $buf | 0;
+ $x = $f + 16 | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $x1 = $n + 32 | 0;
+ $2 = +HEAPF64[$x1 >> 3];
+ $add = $1 + $2;
+ $3 = HEAP32[41182] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $4 = +HEAPF64[20590];
+ $y = $f + 24 | 0;
+ $5 = +HEAPF64[$y >> 3];
+ $y6 = $n + 40 | 0;
+ $6 = +HEAPF64[$y6 >> 3];
+ $add7 = $5 + $6;
+ $sub = $4 - $add7;
+ $cond = $sub;
+ label = 6;
+ break;
+ case 5:
+ $y10 = $f + 24 | 0;
+ $7 = +HEAPF64[$y10 >> 3];
+ $y13 = $n + 40 | 0;
+ $8 = +HEAPF64[$y13 >> 3];
+ $add14 = $7 + $8;
+ $cond = $add14;
+ label = 6;
+ break;
+ case 6:
+ $x16 = $f + 32 | 0;
+ $9 = +HEAPF64[$x16 >> 3];
+ $10 = +HEAPF64[$x1 >> 3];
+ $add20 = $9 + $10;
+ $11 = HEAP32[41182] | 0;
+ $tobool21 = ($11 | 0) == 0;
+ if ($tobool21) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $12 = +HEAPF64[20590];
+ $y25 = $f + 40 | 0;
+ $13 = +HEAPF64[$y25 >> 3];
+ $y28 = $n + 40 | 0;
+ $14 = +HEAPF64[$y28 >> 3];
+ $add29 = $13 + $14;
+ $sub30 = $12 - $add29;
+ $cond40 = $sub30;
+ label = 9;
+ break;
+ case 8:
+ $y34 = $f + 40 | 0;
+ $15 = +HEAPF64[$y34 >> 3];
+ $y37 = $n + 40 | 0;
+ $16 = +HEAPF64[$y37 >> 3];
+ $add38 = $15 + $16;
+ $cond40 = $add38;
+ label = 9;
+ break;
+ case 9:
+ $call = _sprintf($arraydecay | 0, 117640, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $add, HEAPF64[tempInt + 8 >> 3] = $cond, HEAPF64[tempInt + 16 >> 3] = $add20, HEAPF64[tempInt + 24 >> 3] = $cond40, tempInt) | 0) | 0;
+ $call42 = _agxbput($xb, $arraydecay) | 0;
+ $_pr = HEAP32[$n_flds >> 2] | 0;
+ $17 = $_pr;
+ label = 10;
+ break;
+ case 10:
+ $cmp4418 = ($17 | 0) > 0;
+ if ($cmp4418) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $fld = $f + 56 | 0;
+ $i_019 = 0;
+ label = 12;
+ break;
+ case 12:
+ $18 = HEAP32[$fld >> 2] | 0;
+ $arrayidx = $18 + ($i_019 << 2) | 0;
+ $19 = HEAP32[$arrayidx >> 2] | 0;
+ _set_record_rects($n, $19, $xb);
+ $inc = $i_019 + 1 | 0;
+ $20 = HEAP32[$n_flds >> 2] | 0;
+ $cmp44 = ($inc | 0) < ($20 | 0);
+ if ($cmp44) {
+ $i_019 = $inc;
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _rec_attach_bb($g, $bbsym) {
+ $g = $g | 0;
+ $bbsym = $bbsym | 0;
+ var $buf = 0, $arraydecay = 0, $x = 0, $0 = 0.0, $1 = 0, $tobool = 0, $2 = 0.0, $y = 0, $3 = 0.0, $sub = 0.0, $y7 = 0, $4 = 0.0, $cond = 0.0, $x10 = 0, $5 = 0.0, $6 = 0, $tobool11 = 0, $7 = 0.0, $y16 = 0, $8 = 0.0, $sub17 = 0.0, $y22 = 0, $9 = 0.0, $cond24 = 0.0, $call = 0, $10 = 0, $index = 0, $11 = 0, $call26 = 0, $label = 0, $12 = 0, $tobool28 = 0, $text = 0, $13 = 0, $14 = 0, $tobool31 = 0, $pt_sroa_0_0__idx2 = 0, $pt_sroa_0_0_copyload3 = 0.0, $pt_sroa_1_8__idx7 = 0, $pt_sroa_1_8_copyload8 = 0.0, $15 = 0, $tobool36 = 0, $16 = 0.0, $sub39 = 0.0, $cond43 = 0.0, $call44 = 0, $call46 = 0, $17 = 0, $pt_sroa_0_0__idx = 0, $pt_sroa_0_0_copyload = 0.0, $pt_sroa_1_8__idx4 = 0, $pt_sroa_1_8_copyload = 0.0, $div = 0.0, $call51 = 0, $call53 = 0, $div56 = 0.0, $call57 = 0, $call59 = 0, $n_cluster = 0, $18 = 0, $cmp27 = 0, $clust = 0, $c_028 = 0, $19 = 0, $arrayidx63 = 0, $20 = 0, $inc = 0, $21 = 0, $cmp = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $arraydecay = $buf | 0;
+ $x = $g + 56 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $1 = HEAP32[41182] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = +HEAPF64[20590];
+ $y = $g + 64 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $sub = $2 - $3;
+ $cond = $sub;
+ label = 5;
+ break;
+ case 4:
+ $y7 = $g + 64 | 0;
+ $4 = +HEAPF64[$y7 >> 3];
+ $cond = $4;
+ label = 5;
+ break;
+ case 5:
+ $x10 = $g + 72 | 0;
+ $5 = +HEAPF64[$x10 >> 3];
+ $6 = HEAP32[41182] | 0;
+ $tobool11 = ($6 | 0) == 0;
+ if ($tobool11) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $7 = +HEAPF64[20590];
+ $y16 = $g + 80 | 0;
+ $8 = +HEAPF64[$y16 >> 3];
+ $sub17 = $7 - $8;
+ $cond24 = $sub17;
+ label = 8;
+ break;
+ case 7:
+ $y22 = $g + 80 | 0;
+ $9 = +HEAPF64[$y22 >> 3];
+ $cond24 = $9;
+ label = 8;
+ break;
+ case 8:
+ $call = _sprintf($arraydecay | 0, 118184, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $0, HEAPF64[tempInt + 8 >> 3] = $cond, HEAPF64[tempInt + 16 >> 3] = $5, HEAPF64[tempInt + 24 >> 3] = $cond24, tempInt) | 0) | 0;
+ $10 = $g | 0;
+ $index = $bbsym + 8 | 0;
+ $11 = HEAP32[$index >> 2] | 0;
+ $call26 = _agxset($10, $11, $arraydecay) | 0;
+ $label = $g + 52 | 0;
+ $12 = HEAP32[$label >> 2] | 0;
+ $tobool28 = ($12 | 0) == 0;
+ if ($tobool28) {
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $text = $12 | 0;
+ $13 = HEAP32[$text >> 2] | 0;
+ $14 = HEAP8[$13] | 0;
+ $tobool31 = $14 << 24 >> 24 == 0;
+ if ($tobool31) {
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $pt_sroa_0_0__idx2 = $12 + 56 | 0;
+ $pt_sroa_0_0_copyload3 = +HEAPF64[$pt_sroa_0_0__idx2 >> 3];
+ $pt_sroa_1_8__idx7 = $12 + 64 | 0;
+ $pt_sroa_1_8_copyload8 = +HEAPF64[$pt_sroa_1_8__idx7 >> 3];
+ $15 = HEAP32[41182] | 0;
+ $tobool36 = ($15 | 0) == 0;
+ if ($tobool36) {
+ $cond43 = $pt_sroa_1_8_copyload8;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $16 = +HEAPF64[20590];
+ $sub39 = $16 - $pt_sroa_1_8_copyload8;
+ $cond43 = $sub39;
+ label = 12;
+ break;
+ case 12:
+ $call44 = _sprintf($arraydecay | 0, 134096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $pt_sroa_0_0_copyload3, HEAPF64[tempInt + 8 >> 3] = $cond43, tempInt) | 0) | 0;
+ $call46 = _agset($10, 148568, $arraydecay) | 0;
+ $17 = HEAP32[$label >> 2] | 0;
+ $pt_sroa_0_0__idx = $17 + 24 | 0;
+ $pt_sroa_0_0_copyload = +HEAPF64[$pt_sroa_0_0__idx >> 3];
+ $pt_sroa_1_8__idx4 = $17 + 32 | 0;
+ $pt_sroa_1_8_copyload = +HEAPF64[$pt_sroa_1_8__idx4 >> 3];
+ $div = $pt_sroa_0_0_copyload / 72.0;
+ $call51 = _sprintf($arraydecay | 0, 131848, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $div, tempInt) | 0) | 0;
+ $call53 = _agset($10, 139232, $arraydecay) | 0;
+ $div56 = $pt_sroa_1_8_copyload / 72.0;
+ $call57 = _sprintf($arraydecay | 0, 131848, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $div56, tempInt) | 0) | 0;
+ $call59 = _agset($10, 136456, $arraydecay) | 0;
+ label = 13;
+ break;
+ case 13:
+ $n_cluster = $g + 212 | 0;
+ $18 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp27 = ($18 | 0) < 1;
+ if ($cmp27) {
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $clust = $g + 216 | 0;
+ $c_028 = 1;
+ label = 15;
+ break;
+ case 15:
+ $19 = HEAP32[$clust >> 2] | 0;
+ $arrayidx63 = $19 + ($c_028 << 2) | 0;
+ $20 = HEAP32[$arrayidx63 >> 2] | 0;
+ _rec_attach_bb($20, $bbsym);
+ $inc = $c_028 + 1 | 0;
+ $21 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($21 | 0);
+ if ($cmp) {
+ label = 16;
+ break;
+ } else {
+ $c_028 = $inc;
+ label = 15;
+ break;
+ }
+ case 16:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _attach_attrs($g) {
+ $g = $g | 0;
+ var __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ _attach_attrs_and_arrows($g, __stackBase__ + 8 | 0, __stackBase__ | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _output_point($xbuf, $p) {
+ $xbuf = $xbuf | 0;
+ $p = $p | 0;
+ var $buf = 0, $arraydecay = 0, $x = 0, $0 = 0.0, $cmp = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $1 = 0, $tobool = 0, $2 = 0.0, $y = 0, $3 = 0.0, $sub5 = 0.0, $y7 = 0, $4 = 0.0, $cond9 = 0.0, $cmp10 = 0, $5 = 0, $tobool13 = 0, $6 = 0.0, $y15 = 0, $7 = 0.0, $sub16 = 0.0, $y18 = 0, $8 = 0.0, $cond20 = 0.0, $add21 = 0.0, $9 = 0.0, $y26 = 0, $10 = 0.0, $sub27 = 0.0, $y29 = 0, $11 = 0.0, $cond31 = 0.0, $sub32 = 0.0, $add21_sink = 0.0, $conv22 = 0, $call = 0, $call37 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $arraydecay = $buf | 0;
+ $x = $p | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $cmp = $0 < 0.0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $0 + .5;
+ $add_sink = $add;
+ label = 5;
+ break;
+ case 4:
+ $sub = $0 + -.5;
+ $add_sink = $sub;
+ label = 5;
+ break;
+ case 5:
+ $conv = ~~$add_sink;
+ $1 = HEAP32[41182] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $2 = +HEAPF64[20590];
+ $y = $p + 8 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $sub5 = $2 - $3;
+ $cond9 = $sub5;
+ label = 8;
+ break;
+ case 7:
+ $y7 = $p + 8 | 0;
+ $4 = +HEAPF64[$y7 >> 3];
+ $cond9 = $4;
+ label = 8;
+ break;
+ case 8:
+ $cmp10 = $cond9 < 0.0;
+ $5 = HEAP32[41182] | 0;
+ $tobool13 = ($5 | 0) != 0;
+ if ($cmp10) {
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ if ($tobool13) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $6 = +HEAPF64[20590];
+ $y15 = $p + 8 | 0;
+ $7 = +HEAPF64[$y15 >> 3];
+ $sub16 = $6 - $7;
+ $cond20 = $sub16;
+ label = 12;
+ break;
+ case 11:
+ $y18 = $p + 8 | 0;
+ $8 = +HEAPF64[$y18 >> 3];
+ $cond20 = $8;
+ label = 12;
+ break;
+ case 12:
+ $add21 = $cond20 + .5;
+ $add21_sink = $add21;
+ label = 17;
+ break;
+ case 13:
+ if ($tobool13) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $9 = +HEAPF64[20590];
+ $y26 = $p + 8 | 0;
+ $10 = +HEAPF64[$y26 >> 3];
+ $sub27 = $9 - $10;
+ $cond31 = $sub27;
+ label = 16;
+ break;
+ case 15:
+ $y29 = $p + 8 | 0;
+ $11 = +HEAPF64[$y29 >> 3];
+ $cond31 = $11;
+ label = 16;
+ break;
+ case 16:
+ $sub32 = $cond31 + -.5;
+ $add21_sink = $sub32;
+ label = 17;
+ break;
+ case 17:
+ $conv22 = ~~$add21_sink;
+ $call = _sprintf($arraydecay | 0, 118768, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $conv, HEAP32[tempInt + 8 >> 2] = $conv22, tempInt) | 0) | 0;
+ $call37 = _agxbput($xbuf, $arraydecay) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvContext() {
+ var $call1 = 0;
+ _aginitlib(296, 304, 192);
+ _agnodeattr(0, 122008, 154456);
+ $call1 = _gvNEWcontext(0, 1) | 0;
+ _gvconfig($call1, 0);
+ return $call1 | 0;
+}
+function _gvLayout($gvc, $g, $engine) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ $engine = $engine | 0;
+ var $buf = 0, $call = 0, $cmp = 0, $call1 = 0, $call2 = 0, $call3 = 0, $drawing = 0, $0 = 0, $landscape = 0, $1 = 0, $tobool = 0, $arraydecay = 0, $bb = 0, $y = 0, $2 = 0.0, $cmp6 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $x = 0, $3 = 0.0, $cmp19 = 0, $add26 = 0.0, $sub33 = 0.0, $add26_sink = 0.0, $conv27 = 0, $y39 = 0, $4 = 0.0, $cmp40 = 0, $add47 = 0.0, $sub54 = 0.0, $add47_sink = 0.0, $conv48 = 0, $x61 = 0, $5 = 0.0, $cmp62 = 0, $add69 = 0.0, $sub76 = 0.0, $add69_sink = 0.0, $conv70 = 0, $call80 = 0, $x85 = 0, $6 = 0.0, $cmp86 = 0, $add93 = 0.0, $sub100 = 0.0, $add93_sink = 0.0, $conv94 = 0, $y107 = 0, $7 = 0.0, $cmp108 = 0, $add115 = 0.0, $sub122 = 0.0, $add115_sink = 0.0, $conv116 = 0, $x129 = 0, $8 = 0.0, $cmp130 = 0, $add137 = 0.0, $sub144 = 0.0, $add137_sink = 0.0, $conv138 = 0, $y151 = 0, $9 = 0.0, $cmp152 = 0, $add159 = 0.0, $sub166 = 0.0, $add159_sink = 0.0, $conv160 = 0, $call170 = 0, $10 = 0, $call173 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 256 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $call = _gvlayout_select($gvc, $engine) | 0;
+ $cmp = ($call | 0) == 999;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call1 = _gvplugin_list($gvc, 1, $engine) | 0;
+ $call2 = _agerr(1, 127200, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $engine, HEAP32[tempInt + 8 >> 2] = $call1, tempInt) | 0) | 0;
+ $retval_0 = -1;
+ label = 32;
+ break;
+ case 4:
+ $call3 = _gvLayoutJobs($gvc, $g) | 0;
+ $drawing = $g + 48 | 0;
+ $0 = HEAP32[$drawing >> 2] | 0;
+ $landscape = $0 + 81 | 0;
+ $1 = HEAP8[$landscape] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ $arraydecay = $buf | 0;
+ $bb = $g + 56 | 0;
+ if ($tobool) {
+ label = 18;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y = $g + 64 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $cmp6 = $2 < 0.0;
+ if ($cmp6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $add = $2 + .5;
+ $add_sink = $add;
+ label = 8;
+ break;
+ case 7:
+ $sub = $2 + -.5;
+ $add_sink = $sub;
+ label = 8;
+ break;
+ case 8:
+ $conv = ~~$add_sink;
+ $x = $bb | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $cmp19 = $3 < 0.0;
+ if ($cmp19) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add26 = $3 + .5;
+ $add26_sink = $add26;
+ label = 11;
+ break;
+ case 10:
+ $sub33 = $3 + -.5;
+ $add26_sink = $sub33;
+ label = 11;
+ break;
+ case 11:
+ $conv27 = ~~$add26_sink;
+ $y39 = $g + 80 | 0;
+ $4 = +HEAPF64[$y39 >> 3];
+ $cmp40 = $4 < 0.0;
+ if ($cmp40) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $add47 = $4 + .5;
+ $add47_sink = $add47;
+ label = 14;
+ break;
+ case 13:
+ $sub54 = $4 + -.5;
+ $add47_sink = $sub54;
+ label = 14;
+ break;
+ case 14:
+ $conv48 = ~~$add47_sink;
+ $x61 = $g + 72 | 0;
+ $5 = +HEAPF64[$x61 >> 3];
+ $cmp62 = $5 < 0.0;
+ if ($cmp62) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $add69 = $5 + .5;
+ $add69_sink = $add69;
+ label = 17;
+ break;
+ case 16:
+ $sub76 = $5 + -.5;
+ $add69_sink = $sub76;
+ label = 17;
+ break;
+ case 17:
+ $conv70 = ~~$add69_sink;
+ $call80 = _sprintf($arraydecay | 0, 117440, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $conv, HEAP32[tempInt + 8 >> 2] = $conv27, HEAP32[tempInt + 16 >> 2] = $conv48, HEAP32[tempInt + 24 >> 2] = $conv70, tempInt) | 0) | 0;
+ label = 31;
+ break;
+ case 18:
+ $x85 = $bb | 0;
+ $6 = +HEAPF64[$x85 >> 3];
+ $cmp86 = $6 < 0.0;
+ if ($cmp86) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $add93 = $6 + .5;
+ $add93_sink = $add93;
+ label = 21;
+ break;
+ case 20:
+ $sub100 = $6 + -.5;
+ $add93_sink = $sub100;
+ label = 21;
+ break;
+ case 21:
+ $conv94 = ~~$add93_sink;
+ $y107 = $g + 64 | 0;
+ $7 = +HEAPF64[$y107 >> 3];
+ $cmp108 = $7 < 0.0;
+ if ($cmp108) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $add115 = $7 + .5;
+ $add115_sink = $add115;
+ label = 24;
+ break;
+ case 23:
+ $sub122 = $7 + -.5;
+ $add115_sink = $sub122;
+ label = 24;
+ break;
+ case 24:
+ $conv116 = ~~$add115_sink;
+ $x129 = $g + 72 | 0;
+ $8 = +HEAPF64[$x129 >> 3];
+ $cmp130 = $8 < 0.0;
+ if ($cmp130) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $add137 = $8 + .5;
+ $add137_sink = $add137;
+ label = 27;
+ break;
+ case 26:
+ $sub144 = $8 + -.5;
+ $add137_sink = $sub144;
+ label = 27;
+ break;
+ case 27:
+ $conv138 = ~~$add137_sink;
+ $y151 = $g + 80 | 0;
+ $9 = +HEAPF64[$y151 >> 3];
+ $cmp152 = $9 < 0.0;
+ if ($cmp152) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $add159 = $9 + .5;
+ $add159_sink = $add159;
+ label = 30;
+ break;
+ case 29:
+ $sub166 = $9 + -.5;
+ $add159_sink = $sub166;
+ label = 30;
+ break;
+ case 30:
+ $conv160 = ~~$add159_sink;
+ $call170 = _sprintf($arraydecay | 0, 117440, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $conv94, HEAP32[tempInt + 8 >> 2] = $conv116, HEAP32[tempInt + 16 >> 2] = $conv138, HEAP32[tempInt + 24 >> 2] = $conv160, tempInt) | 0) | 0;
+ label = 31;
+ break;
+ case 31:
+ $10 = $g | 0;
+ $call173 = _agsafeset($10, 112216, $arraydecay, 107864) | 0;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 32:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvRender($gvc, $g, $format, $out) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ $format = $format | 0;
+ $out = $out | 0;
+ var $root = 0, $0 = 0, $call = 0, $job1 = 0, $1 = 0, $output_langname = 0, $2 = 0, $call5 = 0, $output_lang = 0, $drawing = 0, $3 = 0, $tobool = 0, $flags = 0, $4 = 0, $and = 0, $tobool6 = 0, $5 = 0, $6 = 0, $output_file = 0, $cmp10 = 0, $flags13 = 0, $7 = 0, $or = 0, $call15 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $call = _gvjobs_output_langname($gvc, $format) | 0;
+ $job1 = $gvc + 124 | 0;
+ $1 = HEAP32[$job1 >> 2] | 0;
+ $output_langname = $1 + 52 | 0;
+ $2 = HEAP32[$output_langname >> 2] | 0;
+ $call5 = _gvrender_select($1, $2) | 0;
+ $output_lang = $1 + 56 | 0;
+ HEAP32[$output_lang >> 2] = $call5;
+ $drawing = $0 + 48 | 0;
+ $3 = HEAP32[$drawing >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $flags = $1 + 152 | 0;
+ $4 = HEAP32[$flags >> 2] | 0;
+ $and = $4 & 67108864;
+ $tobool6 = ($and | 0) == 0;
+ if ($tobool6) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $5 = HEAP32[_stderr >> 2] | 0;
+ $6 = _fwrite(99768, 20, 1, $5 | 0) | 0;
+ $retval_0 = -1;
+ label = 8;
+ break;
+ case 5:
+ $output_file = $1 + 36 | 0;
+ HEAP32[$output_file >> 2] = $out;
+ $cmp10 = ($out | 0) == 0;
+ if ($cmp10) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $flags13 = $1 + 152 | 0;
+ $7 = HEAP32[$flags13 >> 2] | 0;
+ $or = $7 | 134217728;
+ HEAP32[$flags13 >> 2] = $or;
+ label = 7;
+ break;
+ case 7:
+ $call15 = _gvRenderJobs($gvc, $0) | 0;
+ _gvrender_end_job($1);
+ _gvjobs_delete($gvc);
+ $retval_0 = $call15;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvRenderFilename($gvc, $g, $format, $filename) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ $format = $format | 0;
+ $filename = $filename | 0;
+ var $root = 0, $0 = 0, $call = 0, $job1 = 0, $1 = 0, $output_langname = 0, $2 = 0, $call5 = 0, $output_lang = 0, $drawing = 0, $3 = 0, $tobool = 0, $flags = 0, $4 = 0, $and = 0, $tobool6 = 0, $5 = 0, $6 = 0, $call10 = 0, $7 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $call = _gvjobs_output_langname($gvc, $format) | 0;
+ $job1 = $gvc + 124 | 0;
+ $1 = HEAP32[$job1 >> 2] | 0;
+ $output_langname = $1 + 52 | 0;
+ $2 = HEAP32[$output_langname >> 2] | 0;
+ $call5 = _gvrender_select($1, $2) | 0;
+ $output_lang = $1 + 56 | 0;
+ HEAP32[$output_lang >> 2] = $call5;
+ $drawing = $0 + 48 | 0;
+ $3 = HEAP32[$drawing >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $flags = $1 + 152 | 0;
+ $4 = HEAP32[$flags >> 2] | 0;
+ $and = $4 & 67108864;
+ $tobool6 = ($and | 0) == 0;
+ if ($tobool6) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $5 = HEAP32[_stderr >> 2] | 0;
+ $6 = _fwrite(99768, 20, 1, $5 | 0) | 0;
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 5:
+ _gvjobs_output_filename($gvc, $filename);
+ $call10 = _gvRenderJobs($gvc, $0) | 0;
+ _gvrender_end_job($1);
+ $7 = $1;
+ _gvdevice_finalize($7);
+ _gvjobs_delete($gvc);
+ $retval_0 = $call10;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvAddLibrary($gvc, $lib) {
+ $gvc = $gvc | 0;
+ $lib = $lib | 0;
+ _gvconfig_plugin_install_from_library($gvc, 0, $lib);
+ return;
+}
+function _gvconfig_plugin_install_from_library($gvc, $path, $library) {
+ $gvc = $gvc | 0;
+ $path = $path | 0;
+ $library = $library | 0;
+ var $packagename = 0, $0 = 0, $call = 0, $apis1 = 0, $1 = 0, $types215 = 0, $2 = 0, $tobool16 = 0, $3 = 0, $apis_017 = 0, $type12 = 0, $4 = 0, $tobool413 = 0, $api = 0, $5 = 0, $i_014 = 0, $arrayidx = 0, $6 = 0, $quality = 0, $7 = 0, $call10 = 0, $inc = 0, $type = 0, $8 = 0, $tobool4 = 0, $incdec_ptr = 0, $types2 = 0, $9 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $packagename = $library | 0;
+ $0 = HEAP32[$packagename >> 2] | 0;
+ $call = _gvplugin_package_record($gvc, $path, $0) | 0;
+ $apis1 = $library + 4 | 0;
+ $1 = HEAP32[$apis1 >> 2] | 0;
+ $types215 = $1 + 4 | 0;
+ $2 = HEAP32[$types215 >> 2] | 0;
+ $tobool16 = ($2 | 0) == 0;
+ if ($tobool16) {
+ label = 7;
+ break;
+ } else {
+ $apis_017 = $1;
+ $3 = $2;
+ label = 3;
+ break;
+ }
+ case 3:
+ $type12 = $3 + 4 | 0;
+ $4 = HEAP32[$type12 >> 2] | 0;
+ $tobool413 = ($4 | 0) == 0;
+ if ($tobool413) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $api = $apis_017 | 0;
+ $i_014 = 0;
+ $5 = $4;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx = $3 + ($i_014 * 20 & -1) | 0;
+ $6 = HEAP32[$api >> 2] | 0;
+ $quality = $3 + ($i_014 * 20 & -1) + 8 | 0;
+ $7 = HEAP32[$quality >> 2] | 0;
+ $call10 = _gvplugin_install($gvc, $6, $5, $7, $call, $arrayidx) | 0;
+ $inc = $i_014 + 1 | 0;
+ $type = $3 + ($inc * 20 & -1) + 4 | 0;
+ $8 = HEAP32[$type >> 2] | 0;
+ $tobool4 = ($8 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ $i_014 = $inc;
+ $5 = $8;
+ label = 5;
+ break;
+ }
+ case 6:
+ $incdec_ptr = $apis_017 + 8 | 0;
+ $types2 = $apis_017 + 12 | 0;
+ $9 = HEAP32[$types2 >> 2] | 0;
+ $tobool = ($9 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $apis_017 = $incdec_ptr;
+ $3 = $9;
+ label = 3;
+ break;
+ }
+ case 7:
+ return;
+ }
+}
+function _gvplugin_package_record($gvc, $path, $name) {
+ $gvc = $gvc | 0;
+ $path = $path | 0;
+ $name = $name | 0;
+ var $call = 0, $0 = 0, $tobool = 0, $call1 = 0, $cond = 0, $path2 = 0, $1 = 0, $call3 = 0, $name4 = 0, $2 = 0, $packages = 0, $3 = 0, $next = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _gmalloc(12) | 0;
+ $0 = $call;
+ $tobool = ($path | 0) == 0;
+ if ($tobool) {
+ $cond = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _strdup($path | 0) | 0;
+ $cond = $call1;
+ label = 4;
+ break;
+ case 4:
+ $path2 = $call + 4 | 0;
+ $1 = $path2;
+ HEAP32[$1 >> 2] = $cond;
+ $call3 = _strdup($name | 0) | 0;
+ $name4 = $call + 8 | 0;
+ $2 = $name4;
+ HEAP32[$2 >> 2] = $call3;
+ $packages = $gvc + 100 | 0;
+ $3 = HEAP32[$packages >> 2] | 0;
+ $next = $call;
+ HEAP32[$next >> 2] = $3;
+ HEAP32[$packages >> 2] = $0;
+ return $0 | 0;
+ }
+ return 0;
+}
+function _gvconfig($gvc, $rescan) {
+ $gvc = $gvc | 0;
+ $rescan = $rescan | 0;
+ _gvconfig_plugin_install_builtins($gvc);
+ HEAP8[$gvc + 44 | 0] = 0;
+ _gvtextlayout_select($gvc);
+ return;
+}
+function _gvconfig_plugin_install_builtins($gvc) {
+ $gvc = $gvc | 0;
+ var $builtins = 0, $0 = 0, $cmp = 0, $name36 = 0, $1 = 0, $tobool7 = 0, $2 = 0, $s_08 = 0, $3 = 0, $cmp4 = 0, $call = 0, $tobool6 = 0, $address = 0, $4 = 0, $5 = 0, $incdec_ptr = 0, $name3 = 0, $6 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $builtins = $gvc + 32 | 0;
+ $0 = HEAP32[$builtins >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $name36 = $0 | 0;
+ $1 = HEAP32[$name36 >> 2] | 0;
+ $tobool7 = ($1 | 0) == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ $s_08 = $0;
+ $2 = $1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP8[$2] | 0;
+ $cmp4 = $3 << 24 >> 24 == 103;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $call = _strstr($2 | 0, 92272) | 0;
+ $tobool6 = ($call | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $address = $s_08 + 4 | 0;
+ $4 = HEAP32[$address >> 2] | 0;
+ $5 = $4;
+ _gvconfig_plugin_install_from_library($gvc, 0, $5);
+ label = 7;
+ break;
+ case 7:
+ $incdec_ptr = $s_08 + 8 | 0;
+ $name3 = $incdec_ptr | 0;
+ $6 = HEAP32[$name3 >> 2] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $s_08 = $incdec_ptr;
+ $2 = $6;
+ label = 4;
+ break;
+ }
+ case 8:
+ return;
+ }
+}
+function _gvNEWcontext($builtins, $demand_loading) {
+ $builtins = $builtins | 0;
+ $demand_loading = $demand_loading | 0;
+ var $call = 0, $0 = 0, $tobool = 0, $info = 0, $errorfn = 0, $1 = 0, $builtins3 = 0, $2 = 0, $demand_loading5 = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(360) | 0;
+ $0 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $info = $call;
+ HEAP32[$info >> 2] = 166576;
+ $errorfn = $call + 16 | 0;
+ $1 = $errorfn;
+ HEAP32[$1 >> 2] = 502;
+ $builtins3 = $call + 32 | 0;
+ $2 = $builtins3;
+ HEAP32[$2 >> 2] = $builtins;
+ $demand_loading5 = $call + 36 | 0;
+ $3 = $demand_loading5;
+ HEAP32[$3 >> 2] = $demand_loading;
+ label = 4;
+ break;
+ case 4:
+ return $0 | 0;
+ }
+ return 0;
+}
+function _gvFreeContext($gvc) {
+ $gvc = $gvc | 0;
+ var $gvgs = 0, $0 = 0, $tobool14 = 0, $gvg_next_015 = 0, $next = 0, $1 = 0, $2 = 0, $tobool = 0, $packages = 0, $3 = 0, $tobool212 = 0, $package_next_013 = 0, $next4 = 0, $4 = 0, $path = 0, $5 = 0, $name = 0, $6 = 0, $7 = 0, $tobool2 = 0, $config_path = 0, $8 = 0, $tobool6 = 0, $input_filenames = 0, $9 = 0, $tobool8 = 0, $10 = 0, $11 = 0, $12 = 0, $call = 0, $add = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _emit_once_reset();
+ $gvgs = $gvc + 52 | 0;
+ $0 = HEAP32[$gvgs >> 2] | 0;
+ $tobool14 = ($0 | 0) == 0;
+ if ($tobool14) {
+ label = 4;
+ break;
+ } else {
+ $gvg_next_015 = $0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $next = $gvg_next_015 + 4 | 0;
+ $1 = HEAP32[$next >> 2] | 0;
+ $2 = $gvg_next_015;
+ _free($2);
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $gvg_next_015 = $1;
+ label = 3;
+ break;
+ }
+ case 4:
+ $packages = $gvc + 100 | 0;
+ $3 = HEAP32[$packages >> 2] | 0;
+ $tobool212 = ($3 | 0) == 0;
+ if ($tobool212) {
+ label = 6;
+ break;
+ } else {
+ $package_next_013 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $next4 = $package_next_013 | 0;
+ $4 = HEAP32[$next4 >> 2] | 0;
+ $path = $package_next_013 + 4 | 0;
+ $5 = HEAP32[$path >> 2] | 0;
+ _free($5);
+ $name = $package_next_013 + 8 | 0;
+ $6 = HEAP32[$name >> 2] | 0;
+ _free($6);
+ $7 = $package_next_013;
+ _free($7);
+ $tobool2 = ($4 | 0) == 0;
+ if ($tobool2) {
+ label = 6;
+ break;
+ } else {
+ $package_next_013 = $4;
+ label = 5;
+ break;
+ }
+ case 6:
+ _gvjobs_delete($gvc);
+ $config_path = $gvc + 40 | 0;
+ $8 = HEAP32[$config_path >> 2] | 0;
+ $tobool6 = ($8 | 0) == 0;
+ if ($tobool6) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _free($8);
+ label = 8;
+ break;
+ case 8:
+ $input_filenames = $gvc + 48 | 0;
+ $9 = HEAP32[$input_filenames >> 2] | 0;
+ $tobool8 = ($9 | 0) == 0;
+ if ($tobool8) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $10 = $9;
+ _free($10);
+ label = 10;
+ break;
+ case 10:
+ $11 = $gvc;
+ _free($11);
+ $12 = HEAP32[4046] | 0;
+ $call = _agerrors() | 0;
+ $add = $call + $12 | 0;
+ return $add | 0;
+ }
+ return 0;
+}
+function _gvdevice_initialize($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $gvc1 = 0, $1 = 0, $tobool = 0, $initialize = 0, $2 = 0, $tobool2 = 0, $output_data = 0, $3 = 0, $tobool4 = 0, $output_file = 0, $4 = 0, $tobool7 = 0, $auto_outfile_names = 0, $5 = 0, $tobool9 = 0, $output_filename = 0, $6 = 0, $tobool11 = 0, $call = 0, $cmp = 0, $common17 = 0, $7 = 0, $errorfn = 0, $8 = 0, $9 = 0, $call19 = 0, $10 = 0, $call20 = 0, $11 = 0, $flags = 0, $12 = 0, $and = 0, $tobool28 = 0, $common30 = 0, $13 = 0, $errorfn31 = 0, $14 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 76 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $gvc1 = $job | 0;
+ $1 = HEAP32[$gvc1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $initialize = $0 | 0;
+ $2 = HEAP32[$initialize >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$2 & 1023]($job);
+ label = 13;
+ break;
+ case 5:
+ $output_data = $job + 40 | 0;
+ $3 = HEAP32[$output_data >> 2] | 0;
+ $tobool4 = ($3 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 6:
+ $output_file = $job + 36 | 0;
+ $4 = HEAP32[$output_file >> 2] | 0;
+ $tobool7 = ($4 | 0) == 0;
+ if ($tobool7) {
+ label = 7;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 7:
+ $auto_outfile_names = $1 + 13 | 0;
+ $5 = HEAP8[$auto_outfile_names] | 0;
+ $tobool9 = $5 << 24 >> 24 == 0;
+ if ($tobool9) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _auto_output_filename($job);
+ label = 9;
+ break;
+ case 9:
+ $output_filename = $job + 32 | 0;
+ $6 = HEAP32[$output_filename >> 2] | 0;
+ $tobool11 = ($6 | 0) == 0;
+ if ($tobool11) {
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call = _fopen($6 | 0, 134128) | 0;
+ HEAP32[$output_file >> 2] = $call;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $common17 = $job + 12 | 0;
+ $7 = HEAP32[$common17 >> 2] | 0;
+ $errorfn = $7 + 16 | 0;
+ $8 = HEAP32[$errorfn >> 2] | 0;
+ $9 = HEAP32[$output_filename >> 2] | 0;
+ $call19 = ___errno_location() | 0;
+ $10 = HEAP32[$call19 >> 2] | 0;
+ $call20 = _strerror($10 | 0) | 0;
+ FUNCTION_TABLE_vii[$8 & 1023](156152, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $9, HEAP32[tempInt + 8 >> 2] = $call20, tempInt) | 0);
+ $retval_0 = 1;
+ label = 15;
+ break;
+ case 12:
+ $11 = HEAP32[_stdout >> 2] | 0;
+ HEAP32[$output_file >> 2] = $11;
+ label = 13;
+ break;
+ case 13:
+ $flags = $job + 152 | 0;
+ $12 = HEAP32[$flags >> 2] | 0;
+ $and = $12 & 1024;
+ $tobool28 = ($and | 0) == 0;
+ if ($tobool28) {
+ $retval_0 = 0;
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $common30 = $job + 12 | 0;
+ $13 = HEAP32[$common30 >> 2] | 0;
+ $errorfn31 = $13 + 16 | 0;
+ $14 = HEAP32[$errorfn31 >> 2] | 0;
+ FUNCTION_TABLE_vii[$14 & 1023](128392, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ $retval_0 = 1;
+ label = 15;
+ break;
+ case 15:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _auto_output_filename($job) {
+ $job = $job | 0;
+ var $gidx = 0, $graph_index = 0, $0 = 0, $tobool = 0, $arraydecay = 0, $add = 0, $call = 0, $input_filename = 0, $1 = 0, $tobool2 = 0, $_ = 0, $call5 = 0, $call7 = 0, $output_langname = 0, $2 = 0, $call10 = 0, $add8 = 0, $add9 = 0, $add11 = 0, $add12 = 0, $3 = 0, $cmp = 0, $add14 = 0, $4 = 0, $call15 = 0, $5 = 0, $call17 = 0, $6 = 0, $call19 = 0, $7 = 0, $strlen = 0, $endptr = 0, $8 = 0, $9 = 0, $call22 = 0, $call2313 = 0, $tobool2414 = 0, $10 = 0, $11 = 0, $call2315 = 0, $add_ptr = 0, $call25 = 0, $12 = 0, $strlen11 = 0, $endptr12 = 0, $13 = 0, $call23 = 0, $tobool24 = 0, $14 = 0, $_lcssa = 0, $call27 = 0, $15 = 0, $output_filename = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 104 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gidx = __stackBase__ | 0;
+ $graph_index = $job + 24 | 0;
+ $0 = HEAP32[$graph_index >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ $arraydecay = $gidx | 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $0 + 1 | 0;
+ $call = _sprintf($arraydecay | 0, 162400, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $add, tempInt) | 0) | 0;
+ label = 5;
+ break;
+ case 4:
+ HEAP8[$arraydecay] = 0;
+ label = 5;
+ break;
+ case 5:
+ $input_filename = $job + 20 | 0;
+ $1 = HEAP32[$input_filename >> 2] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ $_ = $tobool2 ? 158840 : $1;
+ $call5 = _strlen($_ | 0) | 0;
+ $call7 = _strlen($arraydecay | 0) | 0;
+ $output_langname = $job + 52 | 0;
+ $2 = HEAP32[$output_langname >> 2] | 0;
+ $call10 = _strlen($2 | 0) | 0;
+ $add8 = $call5 + 1 | 0;
+ $add9 = $add8 + $call7 | 0;
+ $add11 = $add9 + $call10 | 0;
+ $add12 = $add11 + 1 | 0;
+ $3 = HEAP32[21448] | 0;
+ $cmp = $3 >>> 0 < $add12 >>> 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $add14 = $add11 + 11 | 0;
+ HEAP32[21448] = $add14;
+ $4 = HEAP32[21450] | 0;
+ $call15 = _realloc($4, $add14) | 0;
+ HEAP32[21450] = $call15;
+ label = 7;
+ break;
+ case 7:
+ $5 = HEAP32[21450] | 0;
+ $call17 = _strcpy($5 | 0, $_ | 0) | 0;
+ $6 = HEAP32[21450] | 0;
+ $call19 = _strcat($6 | 0, $arraydecay | 0) | 0;
+ $7 = HEAP32[21450] | 0;
+ $strlen = _strlen($7 | 0) | 0;
+ $endptr = $7 + $strlen | 0;
+ $8 = $endptr;
+ tempBigInt = 46;
+ HEAP8[$8] = tempBigInt & 255;
+ tempBigInt = tempBigInt >> 8;
+ HEAP8[$8 + 1 | 0] = tempBigInt & 255;
+ $9 = HEAP32[$output_langname >> 2] | 0;
+ $call22 = _strdup($9 | 0) | 0;
+ $call2313 = _strrchr($call22 | 0, 58) | 0;
+ $tobool2414 = ($call2313 | 0) == 0;
+ $10 = HEAP32[21450] | 0;
+ if ($tobool2414) {
+ $_lcssa = $10;
+ label = 9;
+ break;
+ } else {
+ $call2315 = $call2313;
+ $11 = $10;
+ label = 8;
+ break;
+ }
+ case 8:
+ $add_ptr = $call2315 + 1 | 0;
+ $call25 = _strcat($11 | 0, $add_ptr | 0) | 0;
+ $12 = HEAP32[21450] | 0;
+ $strlen11 = _strlen($12 | 0) | 0;
+ $endptr12 = $12 + $strlen11 | 0;
+ $13 = $endptr12;
+ tempBigInt = 46;
+ HEAP8[$13] = tempBigInt & 255;
+ tempBigInt = tempBigInt >> 8;
+ HEAP8[$13 + 1 | 0] = tempBigInt & 255;
+ HEAP8[$call2315] = 0;
+ $call23 = _strrchr($call22 | 0, 58) | 0;
+ $tobool24 = ($call23 | 0) == 0;
+ $14 = HEAP32[21450] | 0;
+ if ($tobool24) {
+ $_lcssa = $14;
+ label = 9;
+ break;
+ } else {
+ $call2315 = $call23;
+ $11 = $14;
+ label = 8;
+ break;
+ }
+ case 9:
+ $call27 = _strcat($_lcssa | 0, $call22 | 0) | 0;
+ _free($call22);
+ $15 = HEAP32[21450] | 0;
+ $output_filename = $job + 32 | 0;
+ HEAP32[$output_filename >> 2] = $15;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvwrite($job, $s, $len) {
+ $job = $job | 0;
+ $s = $s | 0;
+ $len = $len | 0;
+ var $tobool = 0, $tobool1 = 0, $or_cond = 0, $flags = 0, $0 = 0, $and = 0, $tobool2 = 0, $common = 0, $1 = 0, $errorfn = 0, $2 = 0, $call = 0, $cmp = 0, $common5 = 0, $3 = 0, $errorfn6 = 0, $4 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($len | 0) == 0;
+ $tobool1 = ($s | 0) == 0;
+ $or_cond = $tobool | $tobool1;
+ if ($or_cond) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $flags = $job + 152 | 0;
+ $0 = HEAP32[$flags >> 2] | 0;
+ $and = $0 & 1024;
+ $tobool2 = ($and | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $common = $job + 12 | 0;
+ $1 = HEAP32[$common >> 2] | 0;
+ $errorfn = $1 + 16 | 0;
+ $2 = HEAP32[$errorfn >> 2] | 0;
+ FUNCTION_TABLE_vii[$2 & 1023](128392, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _exit(1);
+ return 0;
+ case 5:
+ $call = _gvwrite_no_z($job, $s, $len) | 0;
+ $cmp = ($call | 0) == ($len | 0);
+ if ($cmp) {
+ $retval_0 = $len;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $common5 = $job + 12 | 0;
+ $3 = HEAP32[$common5 >> 2] | 0;
+ $errorfn6 = $3 + 16 | 0;
+ $4 = HEAP32[$errorfn6 >> 2] | 0;
+ FUNCTION_TABLE_vii[$4 & 1023](117688, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $len, tempInt) | 0);
+ _exit(1);
+ return 0;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvwrite_no_z($job, $s, $len) {
+ $job = $job | 0;
+ $s = $s | 0;
+ $len = $len | 0;
+ var $gvc = 0, $0 = 0, $write_fn = 0, $1 = 0, $tobool = 0, $call = 0, $output_data = 0, $2 = 0, $tobool3 = 0, $output_data_allocated = 0, $3 = 0, $output_data_position = 0, $4 = 0, $add_neg = 0, $sub = 0, $cmp = 0, $add7 = 0, $add9 = 0, $and = 0, $5 = 0, $call13 = 0, $tobool16 = 0, $common = 0, $6 = 0, $errorfn = 0, $7 = 0, $8 = 0, $9 = 0, $add_ptr = 0, $10 = 0, $add23 = 0, $11 = 0, $arrayidx = 0, $output_file = 0, $12 = 0, $call26 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc = $job | 0;
+ $0 = HEAP32[$gvc >> 2] | 0;
+ $write_fn = $0 + 116 | 0;
+ $1 = HEAP32[$write_fn >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($job, $s, $len) | 0;
+ $retval_0 = $call;
+ label = 10;
+ break;
+ case 4:
+ $output_data = $job + 40 | 0;
+ $2 = HEAP32[$output_data >> 2] | 0;
+ $tobool3 = ($2 | 0) == 0;
+ if ($tobool3) {
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $output_data_allocated = $job + 44 | 0;
+ $3 = HEAP32[$output_data_allocated >> 2] | 0;
+ $output_data_position = $job + 48 | 0;
+ $4 = HEAP32[$output_data_position >> 2] | 0;
+ $add_neg = $3 - 1 | 0;
+ $sub = $add_neg - $4 | 0;
+ $cmp = $sub >>> 0 < $len >>> 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $add7 = $len + 4096 | 0;
+ $add9 = $add7 + $4 | 0;
+ $and = $add9 & -4096;
+ HEAP32[$output_data_allocated >> 2] = $and;
+ $5 = HEAP32[$output_data >> 2] | 0;
+ $call13 = _realloc($5, $and) | 0;
+ HEAP32[$output_data >> 2] = $call13;
+ $tobool16 = ($call13 | 0) == 0;
+ if ($tobool16) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $common = $job + 12 | 0;
+ $6 = HEAP32[$common >> 2] | 0;
+ $errorfn = $6 + 16 | 0;
+ $7 = HEAP32[$errorfn >> 2] | 0;
+ FUNCTION_TABLE_vii[$7 & 1023](92096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _exit(1);
+ return 0;
+ case 8:
+ $8 = HEAP32[$output_data >> 2] | 0;
+ $9 = HEAP32[$output_data_position >> 2] | 0;
+ $add_ptr = $8 + $9 | 0;
+ _memcpy($add_ptr | 0, $s | 0, $len);
+ $10 = HEAP32[$output_data_position >> 2] | 0;
+ $add23 = $10 + $len | 0;
+ HEAP32[$output_data_position >> 2] = $add23;
+ $11 = HEAP32[$output_data >> 2] | 0;
+ $arrayidx = $11 + $add23 | 0;
+ HEAP8[$arrayidx] = 0;
+ $retval_0 = $len;
+ label = 10;
+ break;
+ case 9:
+ $output_file = $job + 36 | 0;
+ $12 = HEAP32[$output_file >> 2] | 0;
+ $call26 = _fwrite($s | 0, 1, $len | 0, $12 | 0) | 0;
+ $retval_0 = $call26;
+ label = 10;
+ break;
+ case 10:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _quit_cb($job) {
+ $job = $job | 0;
+ return 1;
+}
+function _gvevent_modify($job, $name, $value) {
+ $job = $job | 0;
+ $name = $name | 0;
+ $value = $value | 0;
+ return;
+}
+function _gvevent_delete($job) {
+ $job = $job | 0;
+ return;
+}
+function _gvprintnum($len, $number) {
+ $len = $len | 0;
+ $number = +$number;
+ var $cmp = 0, $cmp1 = 0, $mul = 0.0, $cmp4 = 0, $sub6 = 0.0, $add = 0.0, $N_0_in = 0.0, $N_0 = 0, $cmp9 = 0, $tobool = 0, $sub17 = 0, $sub17_N_0 = 0, $i_026 = 0, $showzeros_025 = 0, $N_224 = 0, $result_023 = 0, $rem = 0, $div = 0, $tobool22 = 0, $tobool24 = 0, $or_cond21 = 0, $or = 0, $conv26 = 0, $incdec_ptr = 0, $result_1 = 0, $showzeros_1 = 0, $cmp28 = 0, $tobool31 = 0, $incdec_ptr33 = 0, $result_3 = 0, $showzeros_2 = 0, $dec = 0, $N_224_off = 0, $0 = 0, $cmp20 = 0, $or_cond = 0, $incdec_ptr38 = 0, $result_4 = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = $number < -1.0e15;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[$len >> 2] = 19;
+ $retval_0 = 11248;
+ label = 21;
+ break;
+ case 4:
+ $cmp1 = $number > 1.0e15;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAP32[$len >> 2] = 18;
+ $retval_0 = 11249;
+ label = 21;
+ break;
+ case 6:
+ $mul = $number * 100.0;
+ $cmp4 = $mul < 0.0;
+ if ($cmp4) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $sub6 = $mul + -.5;
+ $N_0_in = $sub6;
+ label = 9;
+ break;
+ case 8:
+ $add = $mul + .5;
+ $N_0_in = $add;
+ label = 9;
+ break;
+ case 9:
+ $N_0 = ~~$N_0_in;
+ $cmp9 = ($N_0 | 0) == 0;
+ if ($cmp9) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$len >> 2] = 1;
+ $retval_0 = 95632;
+ label = 21;
+ break;
+ case 11:
+ $tobool = ($N_0 | 0) < 0;
+ $sub17 = -$N_0 | 0;
+ $sub17_N_0 = $tobool ? $sub17 : $N_0;
+ $result_023 = 14364;
+ $N_224 = $sub17_N_0;
+ $showzeros_025 = 0;
+ $i_026 = 2;
+ label = 12;
+ break;
+ case 12:
+ $rem = ($N_224 | 0) % 10;
+ $div = ($N_224 | 0) / 10 & -1;
+ $tobool22 = ($rem | 0) == 0;
+ $tobool24 = $showzeros_025 << 24 >> 24 == 0;
+ $or_cond21 = $tobool22 & $tobool24;
+ if ($or_cond21) {
+ $showzeros_1 = $showzeros_025;
+ $result_1 = $result_023;
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $or = $rem | 48;
+ $conv26 = $or & 255;
+ $incdec_ptr = $result_023 - 1 | 0;
+ HEAP8[$incdec_ptr] = $conv26;
+ $showzeros_1 = 1;
+ $result_1 = $incdec_ptr;
+ label = 14;
+ break;
+ case 14:
+ $cmp28 = ($i_026 | 0) == 1;
+ if ($cmp28) {
+ label = 15;
+ break;
+ } else {
+ $showzeros_2 = $showzeros_1;
+ $result_3 = $result_1;
+ label = 17;
+ break;
+ }
+ case 15:
+ $tobool31 = $showzeros_1 << 24 >> 24 == 0;
+ if ($tobool31) {
+ $showzeros_2 = 1;
+ $result_3 = $result_1;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $incdec_ptr33 = $result_1 - 1 | 0;
+ HEAP8[$incdec_ptr33] = 46;
+ $showzeros_2 = 1;
+ $result_3 = $incdec_ptr33;
+ label = 17;
+ break;
+ case 17:
+ $dec = $i_026 - 1 | 0;
+ $N_224_off = $N_224 + 9 | 0;
+ $0 = $N_224_off >>> 0 > 18;
+ $cmp20 = ($dec | 0) > 0;
+ $or_cond = $0 | $cmp20;
+ if ($or_cond) {
+ $result_023 = $result_3;
+ $N_224 = $div;
+ $showzeros_025 = $showzeros_2;
+ $i_026 = $dec;
+ label = 12;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ if ($tobool) {
+ label = 19;
+ break;
+ } else {
+ $result_4 = $result_3;
+ label = 20;
+ break;
+ }
+ case 19:
+ $incdec_ptr38 = $result_3 - 1 | 0;
+ HEAP8[$incdec_ptr38] = 45;
+ $result_4 = $incdec_ptr38;
+ label = 20;
+ break;
+ case 20:
+ $sub_ptr_rhs_cast = $result_4;
+ $sub_ptr_sub = 14364 - $sub_ptr_rhs_cast | 0;
+ HEAP32[$len >> 2] = $sub_ptr_sub;
+ $retval_0 = $result_4;
+ label = 21;
+ break;
+ case 21:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _left_cb($job) {
+ $job = $job | 0;
+ var $x = 0;
+ HEAP8[$job + 536 | 0] = 0;
+ $x = $job + 336 | 0;
+ HEAPF64[$x >> 3] = 10.0 / +HEAPF64[$job + 352 >> 3] + +HEAPF64[$x >> 3];
+ HEAP8[$job + 537 | 0] = 1;
+ return 0;
+}
+function _right_cb($job) {
+ $job = $job | 0;
+ var $x = 0;
+ HEAP8[$job + 536 | 0] = 0;
+ $x = $job + 336 | 0;
+ HEAPF64[$x >> 3] = +HEAPF64[$x >> 3] - 10.0 / +HEAPF64[$job + 352 >> 3];
+ HEAP8[$job + 537 | 0] = 1;
+ return 0;
+}
+function _up_cb($job) {
+ $job = $job | 0;
+ var $y = 0;
+ HEAP8[$job + 536 | 0] = 0;
+ $y = $job + 344 | 0;
+ HEAPF64[$y >> 3] = +HEAPF64[$y >> 3] - 10.0 / +HEAPF64[$job + 352 >> 3];
+ HEAP8[$job + 537 | 0] = 1;
+ return 0;
+}
+function _down_cb($job) {
+ $job = $job | 0;
+ var $y = 0;
+ HEAP8[$job + 536 | 0] = 0;
+ $y = $job + 344 | 0;
+ HEAPF64[$y >> 3] = 10.0 / +HEAPF64[$job + 352 >> 3] + +HEAPF64[$y >> 3];
+ HEAP8[$job + 537 | 0] = 1;
+ return 0;
+}
+function _zoom_in_cb($job) {
+ $job = $job | 0;
+ var $zoom = 0;
+ HEAP8[$job + 536 | 0] = 0;
+ $zoom = $job + 352 | 0;
+ HEAPF64[$zoom >> 3] = +HEAPF64[$zoom >> 3] * 1.1;
+ HEAP8[$job + 537 | 0] = 1;
+ return 0;
+}
+function _zoom_out_cb($job) {
+ $job = $job | 0;
+ var $zoom = 0;
+ HEAP8[$job + 536 | 0] = 0;
+ $zoom = $job + 352 | 0;
+ HEAPF64[$zoom >> 3] = +HEAPF64[$zoom >> 3] / 1.1;
+ HEAP8[$job + 537 | 0] = 1;
+ return 0;
+}
+function _gvevent_button_release($job, $button, $pointer) {
+ $job = $job | 0;
+ $button = $button | 0;
+ $pointer = $pointer | 0;
+ var tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $pointer;
+ $pointer = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pointer >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pointer + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pointer + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pointer + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ HEAP8[$job + 538 | 0] = 0;
+ HEAP8[$job + 541 | 0] = 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _gvferror($stream) {
+ $stream = $stream | 0;
+ var $gvc = 0, $0 = 0, $write_fn = 0, $1 = 0, $tobool = 0, $output_data = 0, $2 = 0, $tobool1 = 0, $output_file = 0, $3 = 0, $4 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc = $stream;
+ $0 = HEAP32[$gvc >> 2] | 0;
+ $write_fn = $0 + 116 | 0;
+ $1 = HEAP32[$write_fn >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 3:
+ $output_data = $stream + 40 | 0;
+ $2 = HEAP32[$output_data >> 2] | 0;
+ $tobool1 = ($2 | 0) == 0;
+ if ($tobool1) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 4:
+ $output_file = $stream + 36 | 0;
+ $3 = HEAP32[$output_file >> 2] | 0;
+ $4 = $3;
+ $call = _ferror($4 | 0) | 0;
+ $retval_0 = $call;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvfwrite($ptr, $size, $nmemb, $stream) {
+ $ptr = $ptr | 0;
+ $size = $size | 0;
+ $nmemb = $nmemb | 0;
+ $stream = $stream | 0;
+ return _gvwrite($stream, $ptr, $nmemb) | 0;
+}
+function _gvputs($job, $s) {
+ $job = $job | 0;
+ $s = $s | 0;
+ var $call = 0;
+ $call = _strlen($s | 0) | 0;
+ return ((_gvwrite($job, $s, $call) | 0) == ($call | 0) ? 1 : -1) | 0;
+}
+function _gvputc($job, $c) {
+ $job = $job | 0;
+ $c = $c | 0;
+ var $cc = 0, $c_ = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $cc = __stackBase__ | 0;
+ HEAP8[$cc] = $c & 255;
+ $c_ = (_gvwrite($job, $cc, 1) | 0) == 1 ? $c : -1;
+ STACKTOP = __stackBase__;
+ return $c_ | 0;
+}
+function _gvflush($job) {
+ $job = $job | 0;
+ var $output_file = 0, $0 = 0, $tobool = 0, $external_context = 0, $1 = 0, $tobool1 = 0, $gvc = 0, $2 = 0, $write_fn = 0, $3 = 0, $tobool3 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $output_file = $job + 36 | 0;
+ $0 = HEAP32[$output_file >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $external_context = $job + 144 | 0;
+ $1 = HEAP8[$external_context] | 0;
+ $tobool1 = $1 << 24 >> 24 == 0;
+ if ($tobool1) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ }
+ case 4:
+ $gvc = $job | 0;
+ $2 = HEAP32[$gvc >> 2] | 0;
+ $write_fn = $2 + 116 | 0;
+ $3 = HEAP32[$write_fn >> 2] | 0;
+ $tobool3 = ($3 | 0) == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $call = _fflush($0 | 0) | 0;
+ $retval_0 = $call;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvdevice_format($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $format = 0, $1 = 0, $tobool1 = 0, $call = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 76 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $format = $0 + 4 | 0;
+ $1 = HEAP32[$format >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ $call = _gvflush($job) | 0;
+ return;
+ }
+}
+function _gvdevice_close($job) {
+ $job = $job | 0;
+ var $output_filename = 0, $0 = 0, $tobool = 0, $output_file = 0, $1 = 0, $2 = 0, $cmp = 0, $external_context = 0, $3 = 0, $tobool2 = 0, $tobool4 = 0, $call = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $output_filename = $job + 32 | 0;
+ $0 = HEAP32[$output_filename >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $output_file = $job + 36 | 0;
+ $1 = HEAP32[$output_file >> 2] | 0;
+ $2 = HEAP32[_stdout >> 2] | 0;
+ $cmp = ($1 | 0) == ($2 | 0);
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $external_context = $job + 144 | 0;
+ $3 = HEAP8[$external_context] | 0;
+ $tobool2 = $3 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $tobool4 = ($1 | 0) == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call = _fclose($1 | 0) | 0;
+ HEAP32[$output_file >> 2] = 0;
+ label = 7;
+ break;
+ case 7:
+ HEAP32[$output_filename >> 2] = 0;
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _gvprintf($job, $format, varrp) {
+ $job = $job | 0;
+ $format = $format | 0;
+ varrp = varrp | 0;
+ var $argp = 0, $arraydecay1 = 0, $arraydecay2 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1040 | 0;
+ $argp = __stackBase__ + 1024 | 0;
+ $arraydecay1 = $argp;
+ HEAP32[$arraydecay1 >> 2] = varrp;
+ HEAP32[$arraydecay1 + 4 >> 2] = 0;
+ $arraydecay2 = __stackBase__ | 0;
+ _gvwrite($job, $arraydecay2, _vsprintf($arraydecay2 | 0, $format | 0, $argp | 0) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _gvprintdouble($job, $num) {
+ $job = $job | 0;
+ $num = +$num;
+ var $len = 0, $call = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $len = __stackBase__ | 0;
+ $call = _gvprintnum($len, $num) | 0;
+ _gvwrite($job, $call, HEAP32[$len >> 2] | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _gvprintpointf($job, $p) {
+ $job = $job | 0;
+ $p = $p | 0;
+ var $len = 0, $call = 0, $call3 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $len = __stackBase__ | 0;
+ $call = _gvprintnum($len, +HEAPF64[$p >> 3]) | 0;
+ _gvwrite($job, $call, HEAP32[$len >> 2] | 0);
+ _gvwrite($job, 99672, 1);
+ $call3 = _gvprintnum($len, +HEAPF64[$p + 8 >> 3]) | 0;
+ _gvwrite($job, $call3, HEAP32[$len >> 2] | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _gvprintpointflist($job, $p, $n) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $n = $n | 0;
+ var $cmp3 = 0, $inc4 = 0, $call = 0, $arrayidx = 0, $inc = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _gvprintpointf($job, $p);
+ $cmp3 = ($n | 0) > 1;
+ if ($cmp3) {
+ $inc4 = 1;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _gvwrite($job, 99672, 1) | 0;
+ $arrayidx = $p + ($inc4 << 4) | 0;
+ _gvprintpointf($job, $arrayidx);
+ $inc = $inc4 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $inc4 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _gvlayout_select($gvc, $layout) {
+ $gvc = $gvc | 0;
+ $layout = $layout | 0;
+ var $call = 0, $tobool = 0, $typeptr1 = 0, $0 = 0, $type = 0, $1 = 0, $type3 = 0, $engine = 0, $2 = 0, $3 = 0, $engine5 = 0, $id = 0, $4 = 0, $id7 = 0, $features = 0, $5 = 0, $6 = 0, $features9 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _gvplugin_load($gvc, 1, $layout) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 999;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $typeptr1 = $call + 16 | 0;
+ $0 = HEAP32[$typeptr1 >> 2] | 0;
+ $type = $0 + 4 | 0;
+ $1 = HEAP32[$type >> 2] | 0;
+ $type3 = $gvc + 156 | 0;
+ HEAP32[$type3 >> 2] = $1;
+ $engine = $0 + 12 | 0;
+ $2 = HEAP32[$engine >> 2] | 0;
+ $3 = $2;
+ $engine5 = $gvc + 144 | 0;
+ HEAP32[$engine5 >> 2] = $3;
+ $id = $0 | 0;
+ $4 = HEAP32[$id >> 2] | 0;
+ $id7 = $gvc + 148 | 0;
+ HEAP32[$id7 >> 2] = $4;
+ $features = $0 + 16 | 0;
+ $5 = HEAP32[$features >> 2] | 0;
+ $6 = $5;
+ $features9 = $gvc + 152 | 0;
+ HEAP32[$features9 >> 2] = $6;
+ $retval_0 = 300;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvLayoutJobs($gvc, $g) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ var $gvc1 = 0, $root = 0, $0 = 0, $cmp = 0, $gvc4 = 0, $1 = 0, $call = 0, $tobool = 0, $call6 = 0, $cmp7 = 0, $call9 = 0, $call10 = 0, $engine = 0, $2 = 0, $tobool13 = 0, $features = 0, $3 = 0, $flags = 0, $4 = 0, $_tr = 0, $conv = 0, $drawing = 0, $5 = 0, $6 = 0, $drawing20 = 0, $layout22 = 0, $7 = 0, $tobool23 = 0, $cleanup = 0, $8 = 0, $tobool26 = 0, $cleanup30 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc1 = $g + 176 | 0;
+ HEAP32[$gvc1 >> 2] = $gvc;
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $cmp = ($0 | 0) == ($g | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $gvc4 = $0 + 176 | 0;
+ HEAP32[$gvc4 >> 2] = $gvc;
+ label = 4;
+ break;
+ case 4:
+ $1 = $g | 0;
+ $call = _agget($1, 118216) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call6 = _gvlayout_select($gvc, $call) | 0;
+ $cmp7 = ($call6 | 0) == 999;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call9 = _gvplugin_list($gvc, 1, $call) | 0;
+ $call10 = _agerr(1, 152056, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $call, HEAP32[tempInt + 8 >> 2] = $call9, tempInt) | 0) | 0;
+ $retval_0 = -1;
+ label = 12;
+ break;
+ case 7:
+ $engine = $gvc + 144 | 0;
+ $2 = HEAP32[$engine >> 2] | 0;
+ $tobool13 = ($2 | 0) == 0;
+ if ($tobool13) {
+ $retval_0 = -1;
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _gv_fixLocale(1);
+ $features = $gvc + 152 | 0;
+ $3 = HEAP32[$features >> 2] | 0;
+ $flags = $3 | 0;
+ $4 = HEAP32[$flags >> 2] | 0;
+ $_tr = $4 & 255;
+ $conv = $_tr & 1;
+ _graph_init($g, $conv);
+ $drawing = $g + 48 | 0;
+ $5 = HEAP32[$drawing >> 2] | 0;
+ $6 = HEAP32[$root >> 2] | 0;
+ $drawing20 = $6 + 48 | 0;
+ HEAP32[$drawing20 >> 2] = $5;
+ $layout22 = $2 | 0;
+ $7 = HEAP32[$layout22 >> 2] | 0;
+ $tobool23 = ($7 | 0) == 0;
+ if ($tobool23) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ FUNCTION_TABLE_vi[$7 & 1023]($g);
+ $cleanup = $2 + 4 | 0;
+ $8 = HEAP32[$cleanup >> 2] | 0;
+ $tobool26 = ($8 | 0) == 0;
+ if ($tobool26) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $cleanup30 = $g + 180 | 0;
+ HEAP32[$cleanup30 >> 2] = $8;
+ label = 11;
+ break;
+ case 11:
+ _gv_fixLocale(0);
+ $retval_0 = 0;
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvFreeLayout($gvc, $g) {
+ $gvc = $gvc | 0;
+ $g = $g | 0;
+ var $cleanup = 0, $0 = 0, $tobool = 0, $drawing = 0, $1 = 0, $tobool6 = 0, $root = 0, $2 = 0, $drawing11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cleanup = $g + 180 | 0;
+ $0 = HEAP32[$cleanup >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ FUNCTION_TABLE_vi[$0 & 1023]($g);
+ HEAP32[$cleanup >> 2] = 0;
+ label = 4;
+ break;
+ case 4:
+ $drawing = $g + 48 | 0;
+ $1 = HEAP32[$drawing >> 2] | 0;
+ $tobool6 = ($1 | 0) == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _graph_cleanup($g);
+ HEAP32[$drawing >> 2] = 0;
+ $root = $g + 32 | 0;
+ $2 = HEAP32[$root >> 2] | 0;
+ $drawing11 = $2 + 48 | 0;
+ HEAP32[$drawing11 >> 2] = 0;
+ label = 6;
+ break;
+ case 6:
+ return 0;
+ }
+ return 0;
+}
+function _toggle_fit_cb($job) {
+ $job = $job | 0;
+ var $fit_mode = 0, $0 = 0, $lnot = 0, $conv = 0, $width = 0, $1 = 0, $height = 0, $2 = 0, $conv5 = 0.0, $conv6 = 0.0, $div = 0.0, $conv8 = 0.0, $conv9 = 0.0, $div10 = 0.0, $cmp = 0, $div_div10 = 0.0, $zoom = 0, $x = 0, $needs_refresh = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $fit_mode = $job + 536 | 0;
+ $0 = HEAP8[$fit_mode] | 0;
+ $lnot = $0 << 24 >> 24 == 0;
+ $conv = $lnot & 1;
+ HEAP8[$fit_mode] = $conv;
+ if ($lnot) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $width = $job + 448 | 0;
+ $1 = HEAP32[$width >> 2] | 0;
+ $height = $job + 452 | 0;
+ $2 = HEAP32[$height >> 2] | 0;
+ $conv5 = +($1 >>> 0 >>> 0);
+ $conv6 = +($1 | 0);
+ $div = $conv5 / $conv6;
+ $conv8 = +($2 >>> 0 >>> 0);
+ $conv9 = +($2 | 0);
+ $div10 = $conv8 / $conv9;
+ $cmp = $div < $div10;
+ $div_div10 = $cmp ? $div : $div10;
+ $zoom = $job + 352 | 0;
+ HEAPF64[$zoom >> 3] = $div_div10;
+ $x = $job + 336 | 0;
+ $needs_refresh = $job + 537 | 0;
+ $3 = $x;
+ _memset($3 | 0, 0, 16);
+ HEAP8[$needs_refresh] = 1;
+ label = 4;
+ break;
+ case 4:
+ return 0;
+ }
+ return 0;
+}
+function _gvevent_refresh($job) {
+ $job = $job | 0;
+ var $gvc = 0, $0 = 0, $g1 = 0, $1 = 0, $selected_obj = 0, $2 = 0, $tobool = 0, $3 = 0, $gui_state = 0, $4 = 0, $or = 0, $has_been_rendered = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc = $job | 0;
+ $0 = HEAP32[$gvc >> 2] | 0;
+ $g1 = $0 + 128 | 0;
+ $1 = HEAP32[$g1 >> 2] | 0;
+ $selected_obj = $job + 580 | 0;
+ $2 = HEAP32[$selected_obj >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $3 = $1 | 0;
+ HEAP32[$selected_obj >> 2] = $3;
+ $gui_state = $1 + 152 | 0;
+ $4 = HEAP8[$gui_state] | 0;
+ $or = $4 | 2;
+ HEAP8[$gui_state] = $or;
+ _gv_graph_state($job, $1);
+ label = 4;
+ break;
+ case 4:
+ _emit_graph($job, $1);
+ $has_been_rendered = $job + 540 | 0;
+ HEAP8[$has_been_rendered] = 1;
+ return;
+ }
+}
+function _gvevent_button_press($job, $button, $pointer) {
+ $job = $job | 0;
+ $button = $button | 0;
+ $pointer = $pointer | 0;
+ var $click = 0, $conv = 0, $button1 = 0, $needs_refresh = 0, $click3 = 0, $conv4 = 0, $button5 = 0, $needs_refresh6 = 0, $click8 = 0, $conv9 = 0, $button10 = 0, $needs_refresh11 = 0, $fit_mode = 0, $rotation = 0, $0 = 0, $tobool = 0, $y = 0, $1 = 0.0, $height = 0, $2 = 0, $conv13 = 0.0, $div = 0.0, $sub = 0.0, $mul = 0.0, $zoom = 0, $3 = 0.0, $y14 = 0, $4 = 0.0, $mul15 = 0.0, $div16 = 0.0, $x = 0, $5 = 0.0, $sub17 = 0.0, $x18 = 0, $6 = 0.0, $width = 0, $7 = 0, $conv19 = 0.0, $div20 = 0.0, $sub21 = 0.0, $mul22 = 0.0, $8 = 0.0, $x25 = 0, $9 = 0.0, $mul26 = 0.0, $div27 = 0.0, $y29 = 0, $10 = 0.0, $add = 0.0, $x30 = 0, $11 = 0.0, $width31 = 0, $12 = 0, $conv32 = 0.0, $div33 = 0.0, $sub34 = 0.0, $mul35 = 0.0, $zoom36 = 0, $13 = 0.0, $x38 = 0, $14 = 0.0, $mul39 = 0.0, $div40 = 0.0, $x42 = 0, $15 = 0.0, $add43 = 0.0, $y44 = 0, $16 = 0.0, $height45 = 0, $17 = 0, $conv46 = 0.0, $div47 = 0.0, $sub48 = 0.0, $mul49 = 0.0, $18 = 0.0, $y52 = 0, $19 = 0.0, $mul53 = 0.0, $div54 = 0.0, $y56 = 0, $20 = 0.0, $add57 = 0.0, $zoom58 = 0, $21 = 0.0, $mul59 = 0.0, $needs_refresh60 = 0, $fit_mode62 = 0, $zoom63 = 0, $22 = 0.0, $div64 = 0.0, $rotation65 = 0, $23 = 0, $tobool66 = 0, $y68 = 0, $24 = 0.0, $height69 = 0, $25 = 0, $conv70 = 0.0, $div71 = 0.0, $sub72 = 0.0, $mul73 = 0.0, $y76 = 0, $26 = 0.0, $mul77 = 0.0, $div78 = 0.0, $x80 = 0, $27 = 0.0, $add81 = 0.0, $x82 = 0, $28 = 0.0, $width83 = 0, $29 = 0, $conv84 = 0.0, $div85 = 0.0, $sub86 = 0.0, $mul87 = 0.0, $30 = 0.0, $x90 = 0, $31 = 0.0, $mul91 = 0.0, $div92 = 0.0, $y94 = 0, $32 = 0.0, $sub95 = 0.0, $x97 = 0, $33 = 0.0, $width98 = 0, $34 = 0, $conv99 = 0.0, $div100 = 0.0, $sub101 = 0.0, $mul102 = 0.0, $x105 = 0, $35 = 0.0, $mul106 = 0.0, $div107 = 0.0, $x109 = 0, $36 = 0.0, $sub110 = 0.0, $y111 = 0, $37 = 0.0, $height112 = 0, $38 = 0, $conv113 = 0.0, $div114 = 0.0, $sub115 = 0.0, $mul116 = 0.0, $39 = 0.0, $y119 = 0, $40 = 0.0, $mul120 = 0.0, $div121 = 0.0, $y123 = 0, $41 = 0.0, $sub124 = 0.0, $needs_refresh126 = 0, $oldpointer = 0, $42 = 0, $43 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $pointer;
+ $pointer = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pointer >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pointer + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pointer + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pointer + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($button | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($button | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($button | 0) == 3) {
+ label = 5;
+ break;
+ } else if (($button | 0) == 4) {
+ label = 6;
+ break;
+ } else if (($button | 0) == 5) {
+ label = 10;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 3:
+ _gvevent_find_current_obj($job, $pointer);
+ _gvevent_select_current_obj($job);
+ $click = $job + 538 | 0;
+ HEAP8[$click] = 1;
+ $conv = $button & 255;
+ $button1 = $job + 541 | 0;
+ HEAP8[$button1] = $conv;
+ $needs_refresh = $job + 537 | 0;
+ HEAP8[$needs_refresh] = 1;
+ label = 14;
+ break;
+ case 4:
+ $click3 = $job + 538 | 0;
+ HEAP8[$click3] = 1;
+ $conv4 = $button & 255;
+ $button5 = $job + 541 | 0;
+ HEAP8[$button5] = $conv4;
+ $needs_refresh6 = $job + 537 | 0;
+ HEAP8[$needs_refresh6] = 1;
+ label = 14;
+ break;
+ case 5:
+ _gvevent_find_current_obj($job, $pointer);
+ $click8 = $job + 538 | 0;
+ HEAP8[$click8] = 1;
+ $conv9 = $button & 255;
+ $button10 = $job + 541 | 0;
+ HEAP8[$button10] = $conv9;
+ $needs_refresh11 = $job + 537 | 0;
+ HEAP8[$needs_refresh11] = 1;
+ label = 14;
+ break;
+ case 6:
+ $fit_mode = $job + 536 | 0;
+ HEAP8[$fit_mode] = 0;
+ $rotation = $job + 360 | 0;
+ $0 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $y = $pointer + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $height = $job + 452 | 0;
+ $2 = HEAP32[$height >> 2] | 0;
+ $conv13 = +($2 >>> 0 >>> 0);
+ $div = $conv13 * .5;
+ $sub = $1 - $div;
+ $mul = $sub * .10000000000000009;
+ $zoom = $job + 352 | 0;
+ $3 = +HEAPF64[$zoom >> 3];
+ $y14 = $job + 528 | 0;
+ $4 = +HEAPF64[$y14 >> 3];
+ $mul15 = $3 * $4;
+ $div16 = $mul / $mul15;
+ $x = $job + 336 | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $sub17 = $5 - $div16;
+ HEAPF64[$x >> 3] = $sub17;
+ $x18 = $pointer | 0;
+ $6 = +HEAPF64[$x18 >> 3];
+ $width = $job + 448 | 0;
+ $7 = HEAP32[$width >> 2] | 0;
+ $conv19 = +($7 >>> 0 >>> 0);
+ $div20 = $conv19 * .5;
+ $sub21 = $6 - $div20;
+ $mul22 = $sub21 * .10000000000000009;
+ $8 = +HEAPF64[$zoom >> 3];
+ $x25 = $job + 520 | 0;
+ $9 = +HEAPF64[$x25 >> 3];
+ $mul26 = $8 * $9;
+ $div27 = $mul22 / $mul26;
+ $y29 = $job + 344 | 0;
+ $10 = +HEAPF64[$y29 >> 3];
+ $add = $div27 + $10;
+ HEAPF64[$y29 >> 3] = $add;
+ label = 9;
+ break;
+ case 8:
+ $x30 = $pointer | 0;
+ $11 = +HEAPF64[$x30 >> 3];
+ $width31 = $job + 448 | 0;
+ $12 = HEAP32[$width31 >> 2] | 0;
+ $conv32 = +($12 >>> 0 >>> 0);
+ $div33 = $conv32 * .5;
+ $sub34 = $11 - $div33;
+ $mul35 = $sub34 * .10000000000000009;
+ $zoom36 = $job + 352 | 0;
+ $13 = +HEAPF64[$zoom36 >> 3];
+ $x38 = $job + 520 | 0;
+ $14 = +HEAPF64[$x38 >> 3];
+ $mul39 = $13 * $14;
+ $div40 = $mul35 / $mul39;
+ $x42 = $job + 336 | 0;
+ $15 = +HEAPF64[$x42 >> 3];
+ $add43 = $div40 + $15;
+ HEAPF64[$x42 >> 3] = $add43;
+ $y44 = $pointer + 8 | 0;
+ $16 = +HEAPF64[$y44 >> 3];
+ $height45 = $job + 452 | 0;
+ $17 = HEAP32[$height45 >> 2] | 0;
+ $conv46 = +($17 >>> 0 >>> 0);
+ $div47 = $conv46 * .5;
+ $sub48 = $16 - $div47;
+ $mul49 = $sub48 * .10000000000000009;
+ $18 = +HEAPF64[$zoom36 >> 3];
+ $y52 = $job + 528 | 0;
+ $19 = +HEAPF64[$y52 >> 3];
+ $mul53 = $18 * $19;
+ $div54 = $mul49 / $mul53;
+ $y56 = $job + 344 | 0;
+ $20 = +HEAPF64[$y56 >> 3];
+ $add57 = $div54 + $20;
+ HEAPF64[$y56 >> 3] = $add57;
+ label = 9;
+ break;
+ case 9:
+ $zoom58 = $job + 352 | 0;
+ $21 = +HEAPF64[$zoom58 >> 3];
+ $mul59 = $21 * 1.1;
+ HEAPF64[$zoom58 >> 3] = $mul59;
+ $needs_refresh60 = $job + 537 | 0;
+ HEAP8[$needs_refresh60] = 1;
+ label = 14;
+ break;
+ case 10:
+ $fit_mode62 = $job + 536 | 0;
+ HEAP8[$fit_mode62] = 0;
+ $zoom63 = $job + 352 | 0;
+ $22 = +HEAPF64[$zoom63 >> 3];
+ $div64 = $22 / 1.1;
+ HEAPF64[$zoom63 >> 3] = $div64;
+ $rotation65 = $job + 360 | 0;
+ $23 = HEAP32[$rotation65 >> 2] | 0;
+ $tobool66 = ($23 | 0) == 0;
+ if ($tobool66) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $y68 = $pointer + 8 | 0;
+ $24 = +HEAPF64[$y68 >> 3];
+ $height69 = $job + 452 | 0;
+ $25 = HEAP32[$height69 >> 2] | 0;
+ $conv70 = +($25 >>> 0 >>> 0);
+ $div71 = $conv70 * .5;
+ $sub72 = $24 - $div71;
+ $mul73 = $sub72 * .10000000000000009;
+ $y76 = $job + 528 | 0;
+ $26 = +HEAPF64[$y76 >> 3];
+ $mul77 = $div64 * $26;
+ $div78 = $mul73 / $mul77;
+ $x80 = $job + 336 | 0;
+ $27 = +HEAPF64[$x80 >> 3];
+ $add81 = $div78 + $27;
+ HEAPF64[$x80 >> 3] = $add81;
+ $x82 = $pointer | 0;
+ $28 = +HEAPF64[$x82 >> 3];
+ $width83 = $job + 448 | 0;
+ $29 = HEAP32[$width83 >> 2] | 0;
+ $conv84 = +($29 >>> 0 >>> 0);
+ $div85 = $conv84 * .5;
+ $sub86 = $28 - $div85;
+ $mul87 = $sub86 * .10000000000000009;
+ $30 = +HEAPF64[$zoom63 >> 3];
+ $x90 = $job + 520 | 0;
+ $31 = +HEAPF64[$x90 >> 3];
+ $mul91 = $30 * $31;
+ $div92 = $mul87 / $mul91;
+ $y94 = $job + 344 | 0;
+ $32 = +HEAPF64[$y94 >> 3];
+ $sub95 = $32 - $div92;
+ HEAPF64[$y94 >> 3] = $sub95;
+ label = 13;
+ break;
+ case 12:
+ $x97 = $pointer | 0;
+ $33 = +HEAPF64[$x97 >> 3];
+ $width98 = $job + 448 | 0;
+ $34 = HEAP32[$width98 >> 2] | 0;
+ $conv99 = +($34 >>> 0 >>> 0);
+ $div100 = $conv99 * .5;
+ $sub101 = $33 - $div100;
+ $mul102 = $sub101 * .10000000000000009;
+ $x105 = $job + 520 | 0;
+ $35 = +HEAPF64[$x105 >> 3];
+ $mul106 = $div64 * $35;
+ $div107 = $mul102 / $mul106;
+ $x109 = $job + 336 | 0;
+ $36 = +HEAPF64[$x109 >> 3];
+ $sub110 = $36 - $div107;
+ HEAPF64[$x109 >> 3] = $sub110;
+ $y111 = $pointer + 8 | 0;
+ $37 = +HEAPF64[$y111 >> 3];
+ $height112 = $job + 452 | 0;
+ $38 = HEAP32[$height112 >> 2] | 0;
+ $conv113 = +($38 >>> 0 >>> 0);
+ $div114 = $conv113 * .5;
+ $sub115 = $37 - $div114;
+ $mul116 = $sub115 * .10000000000000009;
+ $39 = +HEAPF64[$zoom63 >> 3];
+ $y119 = $job + 528 | 0;
+ $40 = +HEAPF64[$y119 >> 3];
+ $mul120 = $39 * $40;
+ $div121 = $mul116 / $mul120;
+ $y123 = $job + 344 | 0;
+ $41 = +HEAPF64[$y123 >> 3];
+ $sub124 = $41 - $div121;
+ HEAPF64[$y123 >> 3] = $sub124;
+ label = 13;
+ break;
+ case 13:
+ $needs_refresh126 = $job + 537 | 0;
+ HEAP8[$needs_refresh126] = 1;
+ label = 14;
+ break;
+ case 14:
+ $oldpointer = $job + 560 | 0;
+ $42 = $oldpointer;
+ $43 = $pointer;
+ HEAP32[$42 >> 2] = HEAP32[$43 >> 2] | 0;
+ HEAP32[$42 + 4 >> 2] = HEAP32[$43 + 4 >> 2] | 0;
+ HEAP32[$42 + 8 >> 2] = HEAP32[$43 + 8 >> 2] | 0;
+ HEAP32[$42 + 12 >> 2] = HEAP32[$43 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvevent_motion($job, $pointer) {
+ $job = $job | 0;
+ $pointer = $pointer | 0;
+ var $x = 0, $0 = 0.0, $oldpointer = 0, $x1 = 0, $1 = 0.0, $sub = 0.0, $x2 = 0, $2 = 0.0, $div = 0.0, $y = 0, $3 = 0.0, $y4 = 0, $4 = 0.0, $sub5 = 0.0, $y7 = 0, $5 = 0.0, $div8 = 0.0, $conv = 0, $ispos = 0, $neg = 0, $call = 0, $cmp = 0, $conv11 = 0, $ispos21 = 0, $neg22 = 0, $call12 = 0, $cmp14 = 0, $button = 0, $6 = 0, $conv16 = 0, $rotation = 0, $7 = 0, $tobool = 0, $zoom27 = 0, $8 = 0.0, $div20 = 0.0, $x21 = 0, $9 = 0.0, $sub22 = 0.0, $10 = 0.0, $div24 = 0.0, $y26 = 0, $11 = 0.0, $add = 0.0, $div28 = 0.0, $x30 = 0, $12 = 0.0, $sub31 = 0.0, $13 = 0.0, $div33 = 0.0, $y35 = 0, $14 = 0.0, $sub36 = 0.0, $needs_refresh = 0, $15 = 0, $16 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $pointer;
+ $pointer = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pointer >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pointer + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pointer + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pointer + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $pointer | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $oldpointer = $job + 560 | 0;
+ $x1 = $oldpointer | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $sub = $0 - $1;
+ $x2 = $job + 520 | 0;
+ $2 = +HEAPF64[$x2 >> 3];
+ $div = $sub / $2;
+ $y = $pointer + 8 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $y4 = $job + 568 | 0;
+ $4 = +HEAPF64[$y4 >> 3];
+ $sub5 = $3 - $4;
+ $y7 = $job + 528 | 0;
+ $5 = +HEAPF64[$y7 >> 3];
+ $div8 = $sub5 / $5;
+ $conv = ~~$div;
+ $ispos = ($conv | 0) > -1;
+ $neg = -$conv | 0;
+ $call = $ispos ? $conv : $neg;
+ $cmp = ($call | 0) < 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $conv11 = ~~$div8;
+ $ispos21 = ($conv11 | 0) > -1;
+ $neg22 = -$conv11 | 0;
+ $call12 = $ispos21 ? $conv11 : $neg22;
+ $cmp14 = ($call12 | 0) < 1;
+ if ($cmp14) {
+ label = 11;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $button = $job + 541 | 0;
+ $6 = HEAP8[$button] | 0;
+ $conv16 = $6 & 255;
+ if (($conv16 | 0) == 0) {
+ label = 5;
+ break;
+ } else if (($conv16 | 0) == 2) {
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ _gvevent_find_current_obj($job, $pointer);
+ label = 10;
+ break;
+ case 6:
+ $rotation = $job + 360 | 0;
+ $7 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($7 | 0) == 0;
+ $zoom27 = $job + 352 | 0;
+ $8 = +HEAPF64[$zoom27 >> 3];
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $div20 = $div8 / $8;
+ $x21 = $job + 336 | 0;
+ $9 = +HEAPF64[$x21 >> 3];
+ $sub22 = $9 - $div20;
+ HEAPF64[$x21 >> 3] = $sub22;
+ $10 = +HEAPF64[$zoom27 >> 3];
+ $div24 = $div / $10;
+ $y26 = $job + 344 | 0;
+ $11 = +HEAPF64[$y26 >> 3];
+ $add = $div24 + $11;
+ HEAPF64[$y26 >> 3] = $add;
+ label = 9;
+ break;
+ case 8:
+ $div28 = $div / $8;
+ $x30 = $job + 336 | 0;
+ $12 = +HEAPF64[$x30 >> 3];
+ $sub31 = $12 - $div28;
+ HEAPF64[$x30 >> 3] = $sub31;
+ $13 = +HEAPF64[$zoom27 >> 3];
+ $div33 = $div8 / $13;
+ $y35 = $job + 344 | 0;
+ $14 = +HEAPF64[$y35 >> 3];
+ $sub36 = $14 - $div33;
+ HEAPF64[$y35 >> 3] = $sub36;
+ label = 9;
+ break;
+ case 9:
+ $needs_refresh = $job + 537 | 0;
+ HEAP8[$needs_refresh] = 1;
+ label = 10;
+ break;
+ case 10:
+ $15 = $oldpointer;
+ $16 = $pointer;
+ HEAP32[$15 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvdevice_finalize($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $flags = 0, $1 = 0, $and = 0, $tobool = 0, $common = 0, $2 = 0, $errorfn = 0, $3 = 0, $tobool1 = 0, $finalize = 0, $4 = 0, $tobool3 = 0, $call = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 76 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $flags = $job + 152 | 0;
+ $1 = HEAP32[$flags >> 2] | 0;
+ $and = $1 & 1024;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $common = $job + 12 | 0;
+ $2 = HEAP32[$common >> 2] | 0;
+ $errorfn = $2 + 16 | 0;
+ $3 = HEAP32[$errorfn >> 2] | 0;
+ FUNCTION_TABLE_vii[$3 & 1023](103960, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _exit(1);
+ case 4:
+ $tobool1 = ($0 | 0) == 0;
+ if ($tobool1) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $finalize = $0 + 8 | 0;
+ $4 = HEAP32[$finalize >> 2] | 0;
+ $tobool3 = ($4 | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ FUNCTION_TABLE_vi[$4 & 1023]($job);
+ label = 8;
+ break;
+ case 7:
+ $call = _gvflush($job) | 0;
+ _gvdevice_close($job);
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pointer2graph($agg_result, $job, $pointer) {
+ $agg_result = $agg_result | 0;
+ $job = $job | 0;
+ $pointer = $pointer | 0;
+ var $rotation = 0, $0 = 0, $tobool = 0, $y = 0, $1 = 0.0, $zoom = 0, $2 = 0.0, $y1 = 0, $3 = 0.0, $mul = 0.0, $div = 0.0, $x = 0, $4 = 0.0, $sub = 0.0, $x3 = 0, $5 = 0.0, $sub4 = 0.0, $x7 = 0, $6 = 0.0, $mul8 = 0.0, $div9 = 0.0, $y11 = 0, $7 = 0.0, $sub12 = 0.0, $x14 = 0, $8 = 0.0, $zoom15 = 0, $9 = 0.0, $x17 = 0, $10 = 0.0, $mul18 = 0.0, $div19 = 0.0, $x21 = 0, $11 = 0.0, $sub22 = 0.0, $y24 = 0, $12 = 0.0, $y27 = 0, $13 = 0.0, $mul28 = 0.0, $div29 = 0.0, $y31 = 0, $14 = 0.0, $sub32 = 0.0, $p_sroa_1_0 = 0.0, $p_sroa_0_0 = 0.0, $p_sroa_0_0__idx = 0, $p_sroa_1_8__idx1 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $pointer;
+ $pointer = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pointer >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pointer + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pointer + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pointer + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rotation = $job + 360 | 0;
+ $0 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $y = $pointer + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $zoom = $job + 352 | 0;
+ $2 = +HEAPF64[$zoom >> 3];
+ $y1 = $job + 528 | 0;
+ $3 = +HEAPF64[$y1 >> 3];
+ $mul = $2 * $3;
+ $div = $1 / $mul;
+ $x = $job + 504 | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $sub = $div - $4;
+ $x3 = $pointer | 0;
+ $5 = +HEAPF64[$x3 >> 3];
+ $sub4 = -0.0 - $5;
+ $x7 = $job + 520 | 0;
+ $6 = +HEAPF64[$x7 >> 3];
+ $mul8 = $2 * $6;
+ $div9 = $sub4 / $mul8;
+ $y11 = $job + 512 | 0;
+ $7 = +HEAPF64[$y11 >> 3];
+ $sub12 = $div9 - $7;
+ $p_sroa_0_0 = $sub;
+ $p_sroa_1_0 = $sub12;
+ label = 5;
+ break;
+ case 4:
+ $x14 = $pointer | 0;
+ $8 = +HEAPF64[$x14 >> 3];
+ $zoom15 = $job + 352 | 0;
+ $9 = +HEAPF64[$zoom15 >> 3];
+ $x17 = $job + 520 | 0;
+ $10 = +HEAPF64[$x17 >> 3];
+ $mul18 = $9 * $10;
+ $div19 = $8 / $mul18;
+ $x21 = $job + 504 | 0;
+ $11 = +HEAPF64[$x21 >> 3];
+ $sub22 = $div19 - $11;
+ $y24 = $pointer + 8 | 0;
+ $12 = +HEAPF64[$y24 >> 3];
+ $y27 = $job + 528 | 0;
+ $13 = +HEAPF64[$y27 >> 3];
+ $mul28 = $9 * $13;
+ $div29 = $12 / $mul28;
+ $y31 = $job + 512 | 0;
+ $14 = +HEAPF64[$y31 >> 3];
+ $sub32 = $div29 - $14;
+ $p_sroa_0_0 = $sub22;
+ $p_sroa_1_0 = $sub32;
+ label = 5;
+ break;
+ case 5:
+ $p_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$p_sroa_0_0__idx >> 3] = $p_sroa_0_0;
+ $p_sroa_1_8__idx1 = $agg_result + 8 | 0;
+ HEAPF64[$p_sroa_1_8__idx1 >> 3] = $p_sroa_1_0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvevent_leave_obj($job) {
+ $job = $job | 0;
+ var $current_obj = 0, $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $3 = 0, $bf_val_sext = 0, $4 = 0, $5 = 0, $and = 0, $6 = 0, $7 = 0, $and6 = 0, $8 = 0, $9 = 0, $and12 = 0, $active_tooltip = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $current_obj = $job + 576 | 0;
+ $0 = HEAP32[$current_obj >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $3 = $2 << 28;
+ $bf_val_sext = $3 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $4 = $0 + 152 | 0;
+ $5 = HEAP8[$4] | 0;
+ $and = $5 & -2;
+ HEAP8[$4] = $and;
+ label = 7;
+ break;
+ case 5:
+ $6 = $0 + 133 | 0;
+ $7 = HEAP8[$6] | 0;
+ $and6 = $7 & -2;
+ HEAP8[$6] = $and6;
+ label = 7;
+ break;
+ case 6:
+ $8 = $0 + 131 | 0;
+ $9 = HEAP8[$8] | 0;
+ $and12 = $9 & -2;
+ HEAP8[$8] = $and12;
+ label = 7;
+ break;
+ case 7:
+ $active_tooltip = $job + 584 | 0;
+ HEAP32[$active_tooltip >> 2] = 0;
+ return;
+ }
+}
+function _gvevent_read($job, $filename, $layout) {
+ $job = $job | 0;
+ $filename = $filename | 0;
+ $layout = $layout | 0;
+ var $gvc1 = 0, $0 = 0, $tobool = 0, $call = 0, $1 = 0, $output_filename = 0, $call2 = 0, $tobool3 = 0, $call5 = 0, $2 = 0, $call6 = 0, $g_0 = 0, $tobool8 = 0, $g11 = 0, $3 = 0, $tobool12 = 0, $engine = 0, $4 = 0, $tobool15 = 0, $cleanup = 0, $5 = 0, $tobool16 = 0, $6 = 0, $7 = 0, $8 = 0, $gvc25 = 0, $call26 = 0, $selected_obj = 0, $current_obj = 0, $needs_refresh = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $tobool = ($filename | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _agopen(147864, 1) | 0;
+ $1 = $call;
+ $output_filename = $job + 32 | 0;
+ HEAP32[$output_filename >> 2] = 145832;
+ $g_0 = $1;
+ label = 6;
+ break;
+ case 4:
+ $call2 = _fopen($filename | 0, 142784) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ label = 13;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call5 = _agread($call2) | 0;
+ $2 = $call5;
+ $call6 = _fclose($call2 | 0) | 0;
+ $g_0 = $2;
+ label = 6;
+ break;
+ case 6:
+ $tobool8 = ($g_0 | 0) == 0;
+ if ($tobool8) {
+ label = 13;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $g11 = $0 + 128 | 0;
+ $3 = HEAP32[$g11 >> 2] | 0;
+ $tobool12 = ($3 | 0) == 0;
+ if ($tobool12) {
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $engine = $0 + 144 | 0;
+ $4 = HEAP32[$engine >> 2] | 0;
+ $tobool15 = ($4 | 0) == 0;
+ if ($tobool15) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cleanup = $4 + 4 | 0;
+ $5 = HEAP32[$cleanup >> 2] | 0;
+ $tobool16 = ($5 | 0) == 0;
+ if ($tobool16) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ FUNCTION_TABLE_vi[$5 & 1023]($3);
+ label = 11;
+ break;
+ case 11:
+ $6 = HEAP32[$g11 >> 2] | 0;
+ _graph_cleanup($6);
+ $7 = HEAP32[$g11 >> 2] | 0;
+ $8 = $7;
+ _agclose($8);
+ label = 12;
+ break;
+ case 12:
+ HEAP32[$g11 >> 2] = $g_0;
+ $gvc25 = $g_0 + 176 | 0;
+ HEAP32[$gvc25 >> 2] = $0;
+ $call26 = _gvLayout($0, $g_0, $layout) | 0;
+ $selected_obj = $job + 580 | 0;
+ HEAP32[$selected_obj >> 2] = 0;
+ $current_obj = $job + 576 | 0;
+ HEAP32[$current_obj >> 2] = 0;
+ $needs_refresh = $job + 537 | 0;
+ HEAP8[$needs_refresh] = 1;
+ label = 13;
+ break;
+ case 13:
+ return;
+ }
+}
+function _gvevent_layout($job, $layout) {
+ $job = $job | 0;
+ $layout = $layout | 0;
+ var $0 = 0;
+ $0 = HEAP32[$job >> 2] | 0;
+ _gvLayout($0, HEAP32[$0 + 128 >> 2] | 0, $layout);
+ return;
+}
+function _gvevent_render($job, $format, $filename) {
+ $job = $job | 0;
+ $format = $format | 0;
+ $filename = $filename | 0;
+ var $0 = 0;
+ $0 = HEAP32[$job >> 2] | 0;
+ _gvRenderFilename($0, HEAP32[$0 + 128 >> 2] | 0, $format, $filename);
+ return;
+}
+function _gvevent_find_current_obj($job, $pointer) {
+ $job = $job | 0;
+ $pointer = $pointer | 0;
+ var $b = 0, $tmp = 0, $p_sroa_0_0__idx = 0, $p_sroa_0_0_copyload = 0.0, $p_sroa_1_8__idx3 = 0, $p_sroa_1_8_copyload = 0.0, $zoom = 0, $0 = 0.0, $div = 0.0, $add = 0.0, $x1 = 0, $add2 = 0.0, $y4 = 0, $sub = 0.0, $x6 = 0, $sub8 = 0.0, $y10 = 0, $gvc = 0, $1 = 0, $g = 0, $2 = 0, $call = 0, $current_obj = 0, $3 = 0, $cmp = 0, $needs_refresh = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 48 | 0;
+ tempParam = $pointer;
+ $pointer = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pointer >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pointer + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pointer + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pointer + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $b = __stackBase__ | 0;
+ $tmp = __stackBase__ + 32 | 0;
+ _pointer2graph($tmp, $job, $pointer);
+ $p_sroa_0_0__idx = $tmp | 0;
+ $p_sroa_0_0_copyload = +HEAPF64[$p_sroa_0_0__idx >> 3];
+ $p_sroa_1_8__idx3 = $tmp + 8 | 0;
+ $p_sroa_1_8_copyload = +HEAPF64[$p_sroa_1_8__idx3 >> 3];
+ $zoom = $job + 352 | 0;
+ $0 = +HEAPF64[$zoom >> 3];
+ $div = 1.0 / $0;
+ $add = $p_sroa_0_0_copyload + $div;
+ $x1 = $b + 16 | 0;
+ HEAPF64[$x1 >> 3] = $add;
+ $add2 = $p_sroa_1_8_copyload + $div;
+ $y4 = $b + 24 | 0;
+ HEAPF64[$y4 >> 3] = $add2;
+ $sub = $p_sroa_0_0_copyload - $div;
+ $x6 = $b | 0;
+ HEAPF64[$x6 >> 3] = $sub;
+ $sub8 = $p_sroa_1_8_copyload - $div;
+ $y10 = $b + 8 | 0;
+ HEAPF64[$y10 >> 3] = $sub8;
+ $gvc = $job | 0;
+ $1 = HEAP32[$gvc >> 2] | 0;
+ $g = $1 + 128 | 0;
+ $2 = HEAP32[$g >> 2] | 0;
+ $call = _gvevent_find_obj($2, $b) | 0;
+ $current_obj = $job + 576 | 0;
+ $3 = HEAP32[$current_obj >> 2] | 0;
+ $cmp = ($call | 0) == ($3 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _gvevent_leave_obj($job);
+ HEAP32[$current_obj >> 2] = $call;
+ _gvevent_enter_obj($job);
+ $needs_refresh = $job + 537 | 0;
+ HEAP8[$needs_refresh] = 1;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvevent_find_obj($g, $b) {
+ $g = $g | 0;
+ $b = $b | 0;
+ var $0 = 0, $call = 0, $tobool24 = 0, $n_0_in25 = 0, $call1 = 0, $tobool321 = 0, $e_0_in22 = 0, $e_0 = 0, $call5 = 0, $tobool6 = 0, $1 = 0, $call7 = 0, $tobool3 = 0, $call9 = 0, $tobool = 0, $call11 = 0, $tobool1318 = 0, $n_1_in19 = 0, $n_1 = 0, $call15 = 0, $tobool16 = 0, $2 = 0, $call20 = 0, $tobool13 = 0, $call22 = 0, $tobool23 = 0, $3 = 0, $4 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool24 = ($call | 0) == 0;
+ if ($tobool24) {
+ label = 8;
+ break;
+ } else {
+ $n_0_in25 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agfstout($0, $n_0_in25) | 0;
+ $tobool321 = ($call1 | 0) == 0;
+ if ($tobool321) {
+ label = 7;
+ break;
+ } else {
+ $e_0_in22 = $call1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $e_0 = $e_0_in22;
+ $call5 = _overlap_edge($e_0, $b) | 0;
+ $tobool6 = $call5 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $1 = $e_0_in22 | 0;
+ $retval_0 = $1;
+ label = 15;
+ break;
+ case 6:
+ $call7 = _agnxtout($0, $e_0_in22) | 0;
+ $tobool3 = ($call7 | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ $e_0_in22 = $call7;
+ label = 4;
+ break;
+ }
+ case 7:
+ $call9 = _agnxtnode($0, $n_0_in25) | 0;
+ $tobool = ($call9 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $n_0_in25 = $call9;
+ label = 3;
+ break;
+ }
+ case 8:
+ $call11 = _aglstnode($0) | 0;
+ $tobool1318 = ($call11 | 0) == 0;
+ if ($tobool1318) {
+ label = 12;
+ break;
+ } else {
+ $n_1_in19 = $call11;
+ label = 9;
+ break;
+ }
+ case 9:
+ $n_1 = $n_1_in19;
+ $call15 = _overlap_node($n_1, $b) | 0;
+ $tobool16 = $call15 << 24 >> 24 == 0;
+ if ($tobool16) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $2 = $n_1_in19 | 0;
+ $retval_0 = $2;
+ label = 15;
+ break;
+ case 11:
+ $call20 = _agprvnode($0, $n_1_in19) | 0;
+ $tobool13 = ($call20 | 0) == 0;
+ if ($tobool13) {
+ label = 12;
+ break;
+ } else {
+ $n_1_in19 = $call20;
+ label = 9;
+ break;
+ }
+ case 12:
+ $call22 = _gvevent_find_cluster($g, $b) | 0;
+ $tobool23 = ($call22 | 0) == 0;
+ if ($tobool23) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $3 = $call22 | 0;
+ $retval_0 = $3;
+ label = 15;
+ break;
+ case 14:
+ $4 = $g | 0;
+ $retval_0 = $4;
+ label = 15;
+ break;
+ case 15:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvevent_enter_obj($job) {
+ $job = $job | 0;
+ var $active_tooltip = 0, $0 = 0, $tobool = 0, $current_obj = 0, $1 = 0, $tobool3 = 0, $2 = 0, $3 = 0, $4 = 0, $bf_val_sext = 0, $5 = 0, $6 = 0, $or = 0, $root = 0, $7 = 0, $8 = 0, $9 = 0, $call = 0, $tobool6 = 0, $index = 0, $10 = 0, $call8 = 0, $call9 = 0, $11 = 0, $12 = 0, $or16 = 0, $graph = 0, $13 = 0, $14 = 0, $proto = 0, $15 = 0, $n18 = 0, $16 = 0, $17 = 0, $call19 = 0, $tobool20 = 0, $index22 = 0, $18 = 0, $call23 = 0, $call24 = 0, $19 = 0, $20 = 0, $or31 = 0, $head = 0, $21 = 0, $22 = 0, $graph33 = 0, $23 = 0, $proto34 = 0, $24 = 0, $e35 = 0, $25 = 0, $26 = 0, $call36 = 0, $tobool37 = 0, $index39 = 0, $27 = 0, $call40 = 0, $call41 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $active_tooltip = $job + 584 | 0;
+ $0 = HEAP32[$active_tooltip >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _free($0);
+ HEAP32[$active_tooltip >> 2] = 0;
+ label = 4;
+ break;
+ case 4:
+ $current_obj = $job + 576 | 0;
+ $1 = HEAP32[$current_obj >> 2] | 0;
+ $tobool3 = ($1 | 0) == 0;
+ if ($tobool3) {
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = $1;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $4 = $3 << 28;
+ $bf_val_sext = $4 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 6;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 8;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 10;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 6:
+ $5 = $1 + 152 | 0;
+ $6 = HEAP8[$5] | 0;
+ $or = $6 | 1;
+ HEAP8[$5] = $or;
+ $root = $1 + 32 | 0;
+ $7 = $root;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $9 = $8 | 0;
+ $call = _agfindattr($9, 139256) | 0;
+ $tobool6 = ($call | 0) == 0;
+ if ($tobool6) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $index = $call + 8 | 0;
+ $10 = HEAP32[$index >> 2] | 0;
+ $call8 = _agxget($1, $10) | 0;
+ $call9 = _strdup_and_subst_obj($call8, $1) | 0;
+ HEAP32[$active_tooltip >> 2] = $call9;
+ label = 12;
+ break;
+ case 8:
+ $11 = $1 + 133 | 0;
+ $12 = HEAP8[$11] | 0;
+ $or16 = $12 | 1;
+ HEAP8[$11] = $or16;
+ $graph = $1 + 20 | 0;
+ $13 = $graph;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $proto = $14 + 40 | 0;
+ $15 = HEAP32[$proto >> 2] | 0;
+ $n18 = $15 | 0;
+ $16 = HEAP32[$n18 >> 2] | 0;
+ $17 = $16 | 0;
+ $call19 = _agfindattr($17, 139256) | 0;
+ $tobool20 = ($call19 | 0) == 0;
+ if ($tobool20) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $index22 = $call19 + 8 | 0;
+ $18 = HEAP32[$index22 >> 2] | 0;
+ $call23 = _agxget($1, $18) | 0;
+ $call24 = _strdup_and_subst_obj($call23, $1) | 0;
+ HEAP32[$active_tooltip >> 2] = $call24;
+ label = 12;
+ break;
+ case 10:
+ $19 = $1 + 131 | 0;
+ $20 = HEAP8[$19] | 0;
+ $or31 = $20 | 1;
+ HEAP8[$19] = $or31;
+ $head = $1 + 12 | 0;
+ $21 = $head;
+ $22 = HEAP32[$21 >> 2] | 0;
+ $graph33 = $22 + 20 | 0;
+ $23 = HEAP32[$graph33 >> 2] | 0;
+ $proto34 = $23 + 40 | 0;
+ $24 = HEAP32[$proto34 >> 2] | 0;
+ $e35 = $24 + 4 | 0;
+ $25 = HEAP32[$e35 >> 2] | 0;
+ $26 = $25 | 0;
+ $call36 = _agfindattr($26, 139256) | 0;
+ $tobool37 = ($call36 | 0) == 0;
+ if ($tobool37) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $index39 = $call36 + 8 | 0;
+ $27 = HEAP32[$index39 >> 2] | 0;
+ $call40 = _agxget($1, $27) | 0;
+ $call41 = _strdup_and_subst_obj($call40, $1) | 0;
+ HEAP32[$active_tooltip >> 2] = $call41;
+ label = 12;
+ break;
+ case 12:
+ return;
+ }
+}
+function _gvevent_find_cluster($g, $b) {
+ $g = $g | 0;
+ $b = $b | 0;
+ var $n_cluster = 0, $0 = 0, $clust = 0, $i_0 = 0, $cmp = 0, $1 = 0, $arrayidx = 0, $2 = 0, $call = 0, $tobool = 0, $inc = 0, $x = 0, $3 = 0.0, $y = 0, $4 = 0.0, $y19 = 0, $5 = 0.0, $x23 = 0, $6 = 0.0, $cmp26 = 0, $x13 = 0, $7 = 0.0, $x30 = 0, $8 = 0.0, $cmp31 = 0, $y34 = 0, $9 = 0.0, $cmp37 = 0, $y42 = 0, $10 = 0.0, $cmp43 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $clust = $g + 216 | 0;
+ $i_0 = 1;
+ label = 3;
+ break;
+ case 3:
+ $cmp = ($i_0 | 0) > ($0 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $1 + ($i_0 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $call = _gvevent_find_cluster($2, $b) | 0;
+ $tobool = ($call | 0) == 0;
+ $inc = $i_0 + 1 | 0;
+ if ($tobool) {
+ $i_0 = $inc;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = $call;
+ label = 10;
+ break;
+ }
+ case 5:
+ $x = $g + 56 | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $y = $g + 64 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y19 = $g + 80 | 0;
+ $5 = +HEAPF64[$y19 >> 3];
+ $x23 = $b + 16 | 0;
+ $6 = +HEAPF64[$x23 >> 3];
+ $cmp26 = $6 < $3;
+ if ($cmp26) {
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $x13 = $g + 72 | 0;
+ $7 = +HEAPF64[$x13 >> 3];
+ $x30 = $b | 0;
+ $8 = +HEAPF64[$x30 >> 3];
+ $cmp31 = $7 < $8;
+ if ($cmp31) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $y34 = $b + 24 | 0;
+ $9 = +HEAPF64[$y34 >> 3];
+ $cmp37 = $9 < $4;
+ if ($cmp37) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $y42 = $b + 8 | 0;
+ $10 = +HEAPF64[$y42 >> 3];
+ $cmp43 = $5 < $10;
+ if ($cmp43) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = $g;
+ label = 10;
+ break;
+ }
+ case 9:
+ $retval_0 = 0;
+ label = 10;
+ break;
+ case 10:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvevent_select_current_obj($job) {
+ $job = $job | 0;
+ var $selected_obj = 0, $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $3 = 0, $bf_val_sext = 0, $4 = 0, $5 = 0, $or = 0, $and = 0, $6 = 0, $7 = 0, $or10 = 0, $and15 = 0, $8 = 0, $9 = 0, $or21 = 0, $and26 = 0, $selected_href = 0, $10 = 0, $tobool28 = 0, $current_obj = 0, $11 = 0, $tobool34 = 0, $12 = 0, $13 = 0, $14 = 0, $bf_val_sext37 = 0, $15 = 0, $16 = 0, $17 = 0, $or42 = 0, $18 = 0, $19 = 0, $20 = 0, $or48 = 0, $21 = 0, $22 = 0, $23 = 0, $or54 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $selected_obj = $job + 580 | 0;
+ $0 = HEAP32[$selected_obj >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $3 = $2 << 28;
+ $bf_val_sext = $3 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $4 = $0 + 152 | 0;
+ $5 = HEAP8[$4] | 0;
+ $or = $5 & -7;
+ $and = $or | 4;
+ HEAP8[$4] = $and;
+ label = 7;
+ break;
+ case 5:
+ $6 = $0 + 133 | 0;
+ $7 = HEAP8[$6] | 0;
+ $or10 = $7 & -7;
+ $and15 = $or10 | 4;
+ HEAP8[$6] = $and15;
+ label = 7;
+ break;
+ case 6:
+ $8 = $0 + 131 | 0;
+ $9 = HEAP8[$8] | 0;
+ $or21 = $9 & -7;
+ $and26 = $or21 | 4;
+ HEAP8[$8] = $and26;
+ label = 7;
+ break;
+ case 7:
+ $selected_href = $job + 588 | 0;
+ $10 = HEAP32[$selected_href >> 2] | 0;
+ $tobool28 = ($10 | 0) == 0;
+ if ($tobool28) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _free($10);
+ HEAP32[$selected_href >> 2] = 0;
+ label = 9;
+ break;
+ case 9:
+ $current_obj = $job + 576 | 0;
+ $11 = HEAP32[$current_obj >> 2] | 0;
+ HEAP32[$selected_obj >> 2] = $11;
+ $tobool34 = ($11 | 0) == 0;
+ if ($tobool34) {
+ label = 14;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $12 = $11;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $14 = $13 << 28;
+ $bf_val_sext37 = $14 >> 28;
+ if (($bf_val_sext37 | 0) == 3) {
+ label = 11;
+ break;
+ } else if (($bf_val_sext37 | 0) == 1) {
+ label = 12;
+ break;
+ } else if (($bf_val_sext37 | 0) == 2) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 11:
+ $15 = $11;
+ $16 = $11 + 152 | 0;
+ $17 = HEAP8[$16] | 0;
+ $or42 = $17 | 2;
+ HEAP8[$16] = $or42;
+ _gv_graph_state($job, $15);
+ label = 14;
+ break;
+ case 12:
+ $18 = $11;
+ $19 = $11 + 133 | 0;
+ $20 = HEAP8[$19] | 0;
+ $or48 = $20 | 2;
+ HEAP8[$19] = $or48;
+ _gv_node_state($job, $18);
+ label = 14;
+ break;
+ case 13:
+ $21 = $11;
+ $22 = $11 + 131 | 0;
+ $23 = HEAP8[$22] | 0;
+ $or54 = $23 | 2;
+ HEAP8[$22] = $or54;
+ _gv_edge_state($job, $21);
+ label = 14;
+ break;
+ case 14:
+ return;
+ }
+}
+function _gv_graph_state($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $selected_obj_type_name = 0, $root = 0, $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $and = 0, $tobool = 0, $name = 0, $3 = 0, $argc = 0, $selected_obj_attributes = 0, $univ = 0, $4 = 0, $globattr36 = 0, $5 = 0, $dict37 = 0, $6 = 0, $call38 = 0, $cmp739 = 0, $7 = 0, $j_141 = 0, $i_040 = 0, $8 = 0, $globattr9 = 0, $9 = 0, $list10 = 0, $10 = 0, $arrayidx = 0, $11 = 0, $inc11 = 0, $name12 = 0, $12 = 0, $inc13 = 0, $index = 0, $13 = 0, $call14 = 0, $inc15 = 0, $inc16 = 0, $14 = 0, $globattr = 0, $15 = 0, $dict = 0, $16 = 0, $call = 0, $cmp7 = 0, $j_1_lcssa = 0, $argc17 = 0, $17 = 0, $18 = 0, $call19 = 0, $tobool20 = 0, $19 = 0, $20 = 0, $call23 = 0, $tobool25 = 0, $a_035 = 0, $21 = 0, $index27 = 0, $22 = 0, $call28 = 0, $call29 = 0, $selected_href = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $selected_obj_type_name = $job + 592 | 0;
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $cmp = ($0 | 0) == ($g | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $1 = $g;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $and = $2 & 16;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _gv_argvlist_set_item($selected_obj_type_name, 0, 119336);
+ label = 7;
+ break;
+ case 5:
+ _gv_argvlist_set_item($selected_obj_type_name, 0, 119864);
+ label = 7;
+ break;
+ case 6:
+ _gv_argvlist_set_item($selected_obj_type_name, 0, 120552);
+ label = 7;
+ break;
+ case 7:
+ $name = $g + 12 | 0;
+ $3 = HEAP32[$name >> 2] | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 1, $3);
+ $argc = $job + 596 | 0;
+ HEAP32[$argc >> 2] = 2;
+ $selected_obj_attributes = $job + 604 | 0;
+ $univ = $g + 16 | 0;
+ $4 = HEAP32[$univ >> 2] | 0;
+ $globattr36 = $4 + 12 | 0;
+ $5 = HEAP32[$globattr36 >> 2] | 0;
+ $dict37 = $5 + 4 | 0;
+ $6 = HEAP32[$dict37 >> 2] | 0;
+ $call38 = _dtsize($6) | 0;
+ $cmp739 = ($call38 | 0) > 0;
+ if ($cmp739) {
+ label = 8;
+ break;
+ } else {
+ $j_1_lcssa = 0;
+ label = 10;
+ break;
+ }
+ case 8:
+ $7 = $g | 0;
+ $i_040 = 0;
+ $j_141 = 0;
+ label = 9;
+ break;
+ case 9:
+ $8 = HEAP32[$univ >> 2] | 0;
+ $globattr9 = $8 + 12 | 0;
+ $9 = HEAP32[$globattr9 >> 2] | 0;
+ $list10 = $9 + 8 | 0;
+ $10 = HEAP32[$list10 >> 2] | 0;
+ $arrayidx = $10 + ($i_040 << 2) | 0;
+ $11 = HEAP32[$arrayidx >> 2] | 0;
+ $inc11 = $j_141 + 1 | 0;
+ $name12 = $11 | 0;
+ $12 = HEAP32[$name12 >> 2] | 0;
+ _gv_argvlist_set_item($selected_obj_attributes, $j_141, $12);
+ $inc13 = $j_141 + 2 | 0;
+ $index = $11 + 8 | 0;
+ $13 = HEAP32[$index >> 2] | 0;
+ $call14 = _agxget($7, $13) | 0;
+ _gv_argvlist_set_item($selected_obj_attributes, $inc11, $call14);
+ $inc15 = $j_141 + 3 | 0;
+ _gv_argvlist_set_item($selected_obj_attributes, $inc13, 0);
+ $inc16 = $i_040 + 1 | 0;
+ $14 = HEAP32[$univ >> 2] | 0;
+ $globattr = $14 + 12 | 0;
+ $15 = HEAP32[$globattr >> 2] | 0;
+ $dict = $15 + 4 | 0;
+ $16 = HEAP32[$dict >> 2] | 0;
+ $call = _dtsize($16) | 0;
+ $cmp7 = ($inc16 | 0) < ($call | 0);
+ if ($cmp7) {
+ $i_040 = $inc16;
+ $j_141 = $inc15;
+ label = 9;
+ break;
+ } else {
+ $j_1_lcssa = $inc15;
+ label = 10;
+ break;
+ }
+ case 10:
+ $argc17 = $job + 608 | 0;
+ HEAP32[$argc17 >> 2] = $j_1_lcssa;
+ $17 = HEAP32[$root >> 2] | 0;
+ $18 = $17 | 0;
+ $call19 = _agfindattr($18, 130008) | 0;
+ $tobool20 = ($call19 | 0) == 0;
+ if ($tobool20) {
+ label = 11;
+ break;
+ } else {
+ $a_035 = $call19;
+ label = 12;
+ break;
+ }
+ case 11:
+ $19 = HEAP32[$root >> 2] | 0;
+ $20 = $19 | 0;
+ $call23 = _agfindattr($20, 131864) | 0;
+ $tobool25 = ($call23 | 0) == 0;
+ if ($tobool25) {
+ label = 13;
+ break;
+ } else {
+ $a_035 = $call23;
+ label = 12;
+ break;
+ }
+ case 12:
+ $21 = $g | 0;
+ $index27 = $a_035 + 8 | 0;
+ $22 = HEAP32[$index27 >> 2] | 0;
+ $call28 = _agxget($21, $22) | 0;
+ $call29 = _strdup_and_subst_obj($call28, $21) | 0;
+ $selected_href = $job + 588 | 0;
+ HEAP32[$selected_href >> 2] = $call29;
+ label = 13;
+ break;
+ case 13:
+ return;
+ }
+}
+function _gv_node_state($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $selected_obj_type_name = 0, $name = 0, $0 = 0, $argc = 0, $selected_obj_attributes = 0, $graph = 0, $1 = 0, $root = 0, $2 = 0, $univ = 0, $3 = 0, $nodeattr29 = 0, $4 = 0, $dict30 = 0, $5 = 0, $call31 = 0, $cmp32 = 0, $6 = 0, $i_034 = 0, $j_033 = 0, $7 = 0, $nodeattr3 = 0, $8 = 0, $list4 = 0, $9 = 0, $arrayidx = 0, $10 = 0, $inc526 = 0, $name6 = 0, $11 = 0, $inc7 = 0, $index = 0, $12 = 0, $call8 = 0, $inc9 = 0, $13 = 0, $nodeattr = 0, $14 = 0, $dict = 0, $15 = 0, $call = 0, $cmp = 0, $j_0_lcssa = 0, $argc10 = 0, $16 = 0, $proto = 0, $17 = 0, $n12 = 0, $18 = 0, $19 = 0, $call13 = 0, $tobool = 0, $20 = 0, $proto15 = 0, $21 = 0, $n16 = 0, $22 = 0, $23 = 0, $call17 = 0, $tobool18 = 0, $a_028 = 0, $24 = 0, $index20 = 0, $25 = 0, $call21 = 0, $call22 = 0, $selected_href = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $selected_obj_type_name = $job + 592 | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 0, 121256);
+ $name = $n + 12 | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 1, $0);
+ $argc = $job + 596 | 0;
+ HEAP32[$argc >> 2] = 2;
+ $selected_obj_attributes = $job + 604 | 0;
+ $graph = $n + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $root = $1 + 32 | 0;
+ $2 = HEAP32[$root >> 2] | 0;
+ $univ = $2 + 16 | 0;
+ $3 = HEAP32[$univ >> 2] | 0;
+ $nodeattr29 = $3 + 4 | 0;
+ $4 = HEAP32[$nodeattr29 >> 2] | 0;
+ $dict30 = $4 + 4 | 0;
+ $5 = HEAP32[$dict30 >> 2] | 0;
+ $call31 = _dtsize($5) | 0;
+ $cmp32 = ($call31 | 0) > 0;
+ if ($cmp32) {
+ label = 3;
+ break;
+ } else {
+ $j_0_lcssa = 0;
+ label = 5;
+ break;
+ }
+ case 3:
+ $6 = $n | 0;
+ $j_033 = 0;
+ $i_034 = 0;
+ label = 4;
+ break;
+ case 4:
+ $7 = HEAP32[$univ >> 2] | 0;
+ $nodeattr3 = $7 + 4 | 0;
+ $8 = HEAP32[$nodeattr3 >> 2] | 0;
+ $list4 = $8 + 8 | 0;
+ $9 = HEAP32[$list4 >> 2] | 0;
+ $arrayidx = $9 + ($i_034 << 2) | 0;
+ $10 = HEAP32[$arrayidx >> 2] | 0;
+ $inc526 = $j_033 | 1;
+ $name6 = $10 | 0;
+ $11 = HEAP32[$name6 >> 2] | 0;
+ _gv_argvlist_set_item($selected_obj_attributes, $j_033, $11);
+ $inc7 = $j_033 + 2 | 0;
+ $index = $10 + 8 | 0;
+ $12 = HEAP32[$index >> 2] | 0;
+ $call8 = _agxget($6, $12) | 0;
+ _gv_argvlist_set_item($selected_obj_attributes, $inc526, $call8);
+ $inc9 = $i_034 + 1 | 0;
+ $13 = HEAP32[$univ >> 2] | 0;
+ $nodeattr = $13 + 4 | 0;
+ $14 = HEAP32[$nodeattr >> 2] | 0;
+ $dict = $14 + 4 | 0;
+ $15 = HEAP32[$dict >> 2] | 0;
+ $call = _dtsize($15) | 0;
+ $cmp = ($inc9 | 0) < ($call | 0);
+ if ($cmp) {
+ $j_033 = $inc7;
+ $i_034 = $inc9;
+ label = 4;
+ break;
+ } else {
+ $j_0_lcssa = $inc7;
+ label = 5;
+ break;
+ }
+ case 5:
+ $argc10 = $job + 608 | 0;
+ HEAP32[$argc10 >> 2] = $j_0_lcssa;
+ $16 = HEAP32[$graph >> 2] | 0;
+ $proto = $16 + 40 | 0;
+ $17 = HEAP32[$proto >> 2] | 0;
+ $n12 = $17 | 0;
+ $18 = HEAP32[$n12 >> 2] | 0;
+ $19 = $18 | 0;
+ $call13 = _agfindattr($19, 130008) | 0;
+ $tobool = ($call13 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $a_028 = $call13;
+ label = 7;
+ break;
+ }
+ case 6:
+ $20 = HEAP32[$graph >> 2] | 0;
+ $proto15 = $20 + 40 | 0;
+ $21 = HEAP32[$proto15 >> 2] | 0;
+ $n16 = $21 | 0;
+ $22 = HEAP32[$n16 >> 2] | 0;
+ $23 = $22 | 0;
+ $call17 = _agfindattr($23, 131864) | 0;
+ $tobool18 = ($call17 | 0) == 0;
+ if ($tobool18) {
+ label = 8;
+ break;
+ } else {
+ $a_028 = $call17;
+ label = 7;
+ break;
+ }
+ case 7:
+ $24 = $n | 0;
+ $index20 = $a_028 + 8 | 0;
+ $25 = HEAP32[$index20 >> 2] | 0;
+ $call21 = _agxget($24, $25) | 0;
+ $call22 = _strdup_and_subst_obj($call21, $24) | 0;
+ $selected_href = $job + 588 | 0;
+ HEAP32[$selected_href >> 2] = $call22;
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _gv_edge_state($job, $e) {
+ $job = $job | 0;
+ $e = $e | 0;
+ var $selected_obj_type_name = 0, $tail = 0, $0 = 0, $name = 0, $1 = 0, $2 = 0, $graph = 0, $3 = 0, $4 = 0, $5 = 0, $and = 0, $tobool = 0, $cond = 0, $head = 0, $6 = 0, $name6 = 0, $7 = 0, $argc = 0, $selected_obj_attributes = 0, $8 = 0, $graph10 = 0, $9 = 0, $root = 0, $10 = 0, $univ = 0, $11 = 0, $edgeattr49 = 0, $12 = 0, $dict50 = 0, $13 = 0, $call51 = 0, $cmp52 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $i_054 = 0, $j_053 = 0, $18 = 0, $edgeattr12 = 0, $19 = 0, $list = 0, $20 = 0, $arrayidx = 0, $21 = 0, $name13 = 0, $22 = 0, $call14 = 0, $cmp15 = 0, $index = 0, $23 = 0, $call16 = 0, $call18 = 0, $cmp19 = 0, $index21 = 0, $24 = 0, $call22 = 0, $call25 = 0, $cmp26 = 0, $index28 = 0, $25 = 0, $call29 = 0, $inc32 = 0, $26 = 0, $inc34 = 0, $index35 = 0, $27 = 0, $call36 = 0, $j_1 = 0, $inc37 = 0, $28 = 0, $edgeattr = 0, $29 = 0, $dict = 0, $30 = 0, $call = 0, $cmp = 0, $j_0_lcssa = 0, $argc38 = 0, $31 = 0, $graph40 = 0, $32 = 0, $proto = 0, $33 = 0, $e41 = 0, $34 = 0, $35 = 0, $call42 = 0, $tobool43 = 0, $36 = 0, $graph46 = 0, $37 = 0, $proto47 = 0, $38 = 0, $e48 = 0, $39 = 0, $40 = 0, $call49 = 0, $tobool51 = 0, $a_048 = 0, $41 = 0, $index53 = 0, $42 = 0, $call54 = 0, $call55 = 0, $selected_href = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $selected_obj_type_name = $job + 592 | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 0, 121816);
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $name = $0 + 12 | 0;
+ $1 = HEAP32[$name >> 2] | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 1, $1);
+ $2 = HEAP32[$tail >> 2] | 0;
+ $graph = $2 + 20 | 0;
+ $3 = HEAP32[$graph >> 2] | 0;
+ $4 = $3;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $and = $5 & 16;
+ $tobool = ($and | 0) != 0;
+ $cond = $tobool ? 136480 : 133352;
+ _gv_argvlist_set_item($selected_obj_type_name, 3, $cond);
+ $head = $e + 12 | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ $name6 = $6 + 12 | 0;
+ $7 = HEAP32[$name6 >> 2] | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 4, $7);
+ $argc = $job + 596 | 0;
+ HEAP32[$argc >> 2] = 7;
+ $selected_obj_attributes = $job + 604 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $graph10 = $8 + 20 | 0;
+ $9 = HEAP32[$graph10 >> 2] | 0;
+ $root = $9 + 32 | 0;
+ $10 = HEAP32[$root >> 2] | 0;
+ $univ = $10 + 16 | 0;
+ $11 = HEAP32[$univ >> 2] | 0;
+ $edgeattr49 = $11 + 8 | 0;
+ $12 = HEAP32[$edgeattr49 >> 2] | 0;
+ $dict50 = $12 + 4 | 0;
+ $13 = HEAP32[$dict50 >> 2] | 0;
+ $call51 = _dtsize($13) | 0;
+ $cmp52 = ($call51 | 0) > 0;
+ if ($cmp52) {
+ label = 3;
+ break;
+ } else {
+ $j_0_lcssa = 0;
+ label = 12;
+ break;
+ }
+ case 3:
+ $14 = $e | 0;
+ $15 = $e | 0;
+ $16 = $e | 0;
+ $17 = $e | 0;
+ $j_053 = 0;
+ $i_054 = 0;
+ label = 4;
+ break;
+ case 4:
+ $18 = HEAP32[$univ >> 2] | 0;
+ $edgeattr12 = $18 + 8 | 0;
+ $19 = HEAP32[$edgeattr12 >> 2] | 0;
+ $list = $19 + 8 | 0;
+ $20 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $20 + ($i_054 << 2) | 0;
+ $21 = HEAP32[$arrayidx >> 2] | 0;
+ $name13 = $21 | 0;
+ $22 = HEAP32[$name13 >> 2] | 0;
+ $call14 = _strcmp($22 | 0, 123344) | 0;
+ $cmp15 = ($call14 | 0) == 0;
+ if ($cmp15) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $index = $21 + 8 | 0;
+ $23 = HEAP32[$index >> 2] | 0;
+ $call16 = _agxget($14, $23) | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 2, $call16);
+ label = 10;
+ break;
+ case 6:
+ $call18 = _strcmp($22 | 0, 125392) | 0;
+ $cmp19 = ($call18 | 0) == 0;
+ if ($cmp19) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $index21 = $21 + 8 | 0;
+ $24 = HEAP32[$index21 >> 2] | 0;
+ $call22 = _agxget($16, $24) | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 5, $call22);
+ label = 10;
+ break;
+ case 8:
+ $call25 = _strcmp($22 | 0, 127936) | 0;
+ $cmp26 = ($call25 | 0) == 0;
+ if ($cmp26) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $index28 = $21 + 8 | 0;
+ $25 = HEAP32[$index28 >> 2] | 0;
+ $call29 = _agxget($17, $25) | 0;
+ _gv_argvlist_set_item($selected_obj_type_name, 6, $call29);
+ $j_1 = $j_053;
+ label = 11;
+ break;
+ case 10:
+ $inc32 = $j_053 + 1 | 0;
+ $26 = HEAP32[$name13 >> 2] | 0;
+ _gv_argvlist_set_item($selected_obj_attributes, $j_053, $26);
+ $inc34 = $j_053 + 2 | 0;
+ $index35 = $21 + 8 | 0;
+ $27 = HEAP32[$index35 >> 2] | 0;
+ $call36 = _agxget($15, $27) | 0;
+ _gv_argvlist_set_item($selected_obj_attributes, $inc32, $call36);
+ $j_1 = $inc34;
+ label = 11;
+ break;
+ case 11:
+ $inc37 = $i_054 + 1 | 0;
+ $28 = HEAP32[$univ >> 2] | 0;
+ $edgeattr = $28 + 8 | 0;
+ $29 = HEAP32[$edgeattr >> 2] | 0;
+ $dict = $29 + 4 | 0;
+ $30 = HEAP32[$dict >> 2] | 0;
+ $call = _dtsize($30) | 0;
+ $cmp = ($inc37 | 0) < ($call | 0);
+ if ($cmp) {
+ $j_053 = $j_1;
+ $i_054 = $inc37;
+ label = 4;
+ break;
+ } else {
+ $j_0_lcssa = $j_1;
+ label = 12;
+ break;
+ }
+ case 12:
+ $argc38 = $job + 608 | 0;
+ HEAP32[$argc38 >> 2] = $j_0_lcssa;
+ $31 = HEAP32[$head >> 2] | 0;
+ $graph40 = $31 + 20 | 0;
+ $32 = HEAP32[$graph40 >> 2] | 0;
+ $proto = $32 + 40 | 0;
+ $33 = HEAP32[$proto >> 2] | 0;
+ $e41 = $33 + 4 | 0;
+ $34 = HEAP32[$e41 >> 2] | 0;
+ $35 = $34 | 0;
+ $call42 = _agfindattr($35, 130008) | 0;
+ $tobool43 = ($call42 | 0) == 0;
+ if ($tobool43) {
+ label = 13;
+ break;
+ } else {
+ $a_048 = $call42;
+ label = 14;
+ break;
+ }
+ case 13:
+ $36 = HEAP32[$head >> 2] | 0;
+ $graph46 = $36 + 20 | 0;
+ $37 = HEAP32[$graph46 >> 2] | 0;
+ $proto47 = $37 + 40 | 0;
+ $38 = HEAP32[$proto47 >> 2] | 0;
+ $e48 = $38 + 4 | 0;
+ $39 = HEAP32[$e48 >> 2] | 0;
+ $40 = $39 | 0;
+ $call49 = _agfindattr($40, 131864) | 0;
+ $tobool51 = ($call49 | 0) == 0;
+ if ($tobool51) {
+ label = 15;
+ break;
+ } else {
+ $a_048 = $call49;
+ label = 14;
+ break;
+ }
+ case 14:
+ $41 = $e | 0;
+ $index53 = $a_048 + 8 | 0;
+ $42 = HEAP32[$index53 >> 2] | 0;
+ $call54 = _agxget($41, $42) | 0;
+ $call55 = _strdup_and_subst_obj($call54, $41) | 0;
+ $selected_href = $job + 588 | 0;
+ HEAP32[$selected_href >> 2] = $call55;
+ label = 15;
+ break;
+ case 15:
+ return;
+ }
+}
+function _gvjobs_first($gvc) {
+ $gvc = $gvc | 0;
+ var $0 = 0;
+ $0 = HEAP32[$gvc + 120 >> 2] | 0;
+ HEAP32[$gvc + 124 >> 2] = $0;
+ return $0 | 0;
+}
+function _gvjobs_next($gvc) {
+ $gvc = $gvc | 0;
+ var $job1 = 0, $0 = 0, $next = 0, $1 = 0, $tobool = 0, $output_langname = 0, $2 = 0, $tobool2 = 0, $output_langname5 = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $job1 = $gvc + 124 | 0;
+ $0 = HEAP32[$job1 >> 2] | 0;
+ $next = $0 + 4 | 0;
+ $1 = HEAP32[$next >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $output_langname = $1 + 52 | 0;
+ $2 = HEAP32[$output_langname >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $output_langname5 = $0 + 52 | 0;
+ $3 = HEAP32[$output_langname5 >> 2] | 0;
+ HEAP32[$output_langname >> 2] = $3;
+ label = 5;
+ break;
+ case 5:
+ HEAP32[$job1 >> 2] = $1;
+ return $1 | 0;
+ }
+ return 0;
+}
+function _gvrender_ptf($agg_result, $job, $p) {
+ $agg_result = $agg_result | 0;
+ $job = $job | 0;
+ $p = $p | 0;
+ var $translation_sroa_0_0__idx = 0, $translation_sroa_0_0_copyload = 0.0, $translation_sroa_1_8__idx5 = 0, $translation_sroa_1_8_copyload = 0.0, $zoom = 0, $0 = 0.0, $x = 0, $1 = 0.0, $mul = 0.0, $y = 0, $2 = 0.0, $mul5 = 0.0, $rotation = 0, $3 = 0, $tobool = 0, $y7 = 0, $4 = 0.0, $add = 0.0, $sub = 0.0, $x12 = 0, $5 = 0.0, $add14 = 0.0, $x18 = 0, $6 = 0.0, $add20 = 0.0, $y24 = 0, $7 = 0.0, $add26 = 0.0, $sub_pn = 0.0, $add14_pn = 0.0, $rv_sroa_1_0 = 0.0, $rv_sroa_0_0 = 0.0, $rv_sroa_0_0__idx = 0, $rv_sroa_1_8__idx6 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $translation_sroa_0_0__idx = $job + 504 | 0;
+ $translation_sroa_0_0_copyload = +HEAPF64[$translation_sroa_0_0__idx >> 3];
+ $translation_sroa_1_8__idx5 = $job + 512 | 0;
+ $translation_sroa_1_8_copyload = +HEAPF64[$translation_sroa_1_8__idx5 >> 3];
+ $zoom = $job + 352 | 0;
+ $0 = +HEAPF64[$zoom >> 3];
+ $x = $job + 520 | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $mul = $0 * $1;
+ $y = $job + 528 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $mul5 = $0 * $2;
+ $rotation = $job + 360 | 0;
+ $3 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $y7 = $p + 8 | 0;
+ $4 = +HEAPF64[$y7 >> 3];
+ $add = $translation_sroa_1_8_copyload + $4;
+ $sub = -0.0 - $add;
+ $x12 = $p | 0;
+ $5 = +HEAPF64[$x12 >> 3];
+ $add14 = $translation_sroa_0_0_copyload + $5;
+ $add14_pn = $add14;
+ $sub_pn = $sub;
+ label = 5;
+ break;
+ case 4:
+ $x18 = $p | 0;
+ $6 = +HEAPF64[$x18 >> 3];
+ $add20 = $translation_sroa_0_0_copyload + $6;
+ $y24 = $p + 8 | 0;
+ $7 = +HEAPF64[$y24 >> 3];
+ $add26 = $translation_sroa_1_8_copyload + $7;
+ $add14_pn = $add26;
+ $sub_pn = $add20;
+ label = 5;
+ break;
+ case 5:
+ $rv_sroa_1_0 = $mul5 * $add14_pn;
+ $rv_sroa_0_0 = $mul * $sub_pn;
+ $rv_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$rv_sroa_0_0__idx >> 3] = $rv_sroa_0_0;
+ $rv_sroa_1_8__idx6 = $agg_result + 8 | 0;
+ HEAPF64[$rv_sroa_1_8__idx6 >> 3] = $rv_sroa_1_0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvrender_ptf_A($job, $af, $AF, $n) {
+ $job = $job | 0;
+ $af = $af | 0;
+ $AF = $AF | 0;
+ $n = $n | 0;
+ var $translation_sroa_0_0__idx = 0, $translation_sroa_0_0_copyload = 0.0, $translation_sroa_1_8__idx5 = 0, $translation_sroa_1_8_copyload = 0.0, $zoom = 0, $0 = 0.0, $x = 0, $1 = 0.0, $mul = 0.0, $y = 0, $2 = 0.0, $mul5 = 0.0, $rotation = 0, $3 = 0, $tobool = 0, $cmp2230 = 0, $i_034 = 0, $y7 = 0, $4 = 0.0, $add = 0.0, $sub = 0.0, $mul10 = 0.0, $x12 = 0, $5 = 0.0, $add14 = 0.0, $mul16 = 0.0, $y18 = 0, $x20 = 0, $inc = 0, $cmp = 0, $i_131 = 0, $x25 = 0, $6 = 0.0, $add27 = 0.0, $mul29 = 0.0, $x31 = 0, $y33 = 0, $7 = 0.0, $add35 = 0.0, $mul37 = 0.0, $y39 = 0, $inc41 = 0, $cmp22 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $translation_sroa_0_0__idx = $job + 504 | 0;
+ $translation_sroa_0_0_copyload = +HEAPF64[$translation_sroa_0_0__idx >> 3];
+ $translation_sroa_1_8__idx5 = $job + 512 | 0;
+ $translation_sroa_1_8_copyload = +HEAPF64[$translation_sroa_1_8__idx5 >> 3];
+ $zoom = $job + 352 | 0;
+ $0 = +HEAPF64[$zoom >> 3];
+ $x = $job + 520 | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $mul = $0 * $1;
+ $y = $job + 528 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $mul5 = $0 * $2;
+ $rotation = $job + 360 | 0;
+ $3 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ $cmp2230 = ($n | 0) > 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ if ($cmp2230) {
+ $i_034 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ if ($cmp2230) {
+ $i_131 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $y7 = $af + ($i_034 << 4) + 8 | 0;
+ $4 = +HEAPF64[$y7 >> 3];
+ $add = $translation_sroa_1_8_copyload + $4;
+ $sub = -0.0 - $add;
+ $mul10 = $mul * $sub;
+ $x12 = $af + ($i_034 << 4) | 0;
+ $5 = +HEAPF64[$x12 >> 3];
+ $add14 = $translation_sroa_0_0_copyload + $5;
+ $mul16 = $mul5 * $add14;
+ $y18 = $AF + ($i_034 << 4) + 8 | 0;
+ HEAPF64[$y18 >> 3] = $mul16;
+ $x20 = $AF + ($i_034 << 4) | 0;
+ HEAPF64[$x20 >> 3] = $mul10;
+ $inc = $i_034 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_034 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $x25 = $af + ($i_131 << 4) | 0;
+ $6 = +HEAPF64[$x25 >> 3];
+ $add27 = $translation_sroa_0_0_copyload + $6;
+ $mul29 = $mul * $add27;
+ $x31 = $AF + ($i_131 << 4) | 0;
+ HEAPF64[$x31 >> 3] = $mul29;
+ $y33 = $af + ($i_131 << 4) + 8 | 0;
+ $7 = +HEAPF64[$y33 >> 3];
+ $add35 = $translation_sroa_1_8_copyload + $7;
+ $mul37 = $mul5 * $add35;
+ $y39 = $AF + ($i_131 << 4) + 8 | 0;
+ HEAPF64[$y39 >> 3] = $mul37;
+ $inc41 = $i_131 + 1 | 0;
+ $cmp22 = ($inc41 | 0) < ($n | 0);
+ if ($cmp22) {
+ $i_131 = $inc41;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ return $AF | 0;
+ }
+ return 0;
+}
+function _gvjobs_output_filename($gvc, $name) {
+ $gvc = $gvc | 0;
+ $name = $name | 0;
+ var $jobs = 0, $0 = 0, $tobool = 0, $call = 0, $1 = 0, $job = 0, $2 = 0, $tobool2 = 0, $next = 0, $3 = 0, $tobool6 = 0, $call8 = 0, $4 = 0, $5 = 0, $next9 = 0, $6 = 0, $next10 = 0, $7 = 0, $8 = 0, $output_filename = 0, $9 = 0, $gvc13 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $jobs = $gvc + 120 | 0;
+ $0 = HEAP32[$jobs >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _zmalloc(632) | 0;
+ $1 = $call;
+ HEAP32[$jobs >> 2] = $1;
+ $job = $gvc + 124 | 0;
+ HEAP32[$job >> 2] = $1;
+ HEAP32[2250] = $1;
+ label = 9;
+ break;
+ case 4:
+ $2 = HEAP32[2250] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAP32[2250] = $0;
+ label = 9;
+ break;
+ case 6:
+ $next = $2 + 4 | 0;
+ $3 = HEAP32[$next >> 2] | 0;
+ $tobool6 = ($3 | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call8 = _zmalloc(632) | 0;
+ $4 = $call8;
+ $5 = HEAP32[2250] | 0;
+ $next9 = $5 + 4 | 0;
+ HEAP32[$next9 >> 2] = $4;
+ label = 8;
+ break;
+ case 8:
+ $6 = HEAP32[2250] | 0;
+ $next10 = $6 + 4 | 0;
+ $7 = HEAP32[$next10 >> 2] | 0;
+ HEAP32[2250] = $7;
+ label = 9;
+ break;
+ case 9:
+ $8 = HEAP32[2250] | 0;
+ $output_filename = $8 + 32 | 0;
+ HEAP32[$output_filename >> 2] = $name;
+ $9 = HEAP32[2250] | 0;
+ $gvc13 = $9 | 0;
+ HEAP32[$gvc13 >> 2] = $gvc;
+ return;
+ }
+}
+function _gvjobs_output_langname($gvc, $name) {
+ $gvc = $gvc | 0;
+ $name = $name | 0;
+ var $jobs = 0, $0 = 0, $tobool = 0, $call = 0, $1 = 0, $job = 0, $2 = 0, $tobool2 = 0, $next = 0, $3 = 0, $tobool6 = 0, $call8 = 0, $4 = 0, $5 = 0, $next9 = 0, $6 = 0, $next10 = 0, $7 = 0, $8 = 0, $output_langname = 0, $9 = 0, $gvc13 = 0, $call14 = 0, $not_tobool15 = 0, $_ = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $jobs = $gvc + 120 | 0;
+ $0 = HEAP32[$jobs >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _zmalloc(632) | 0;
+ $1 = $call;
+ HEAP32[$jobs >> 2] = $1;
+ $job = $gvc + 124 | 0;
+ HEAP32[$job >> 2] = $1;
+ HEAP32[2248] = $1;
+ label = 9;
+ break;
+ case 4:
+ $2 = HEAP32[2248] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAP32[2248] = $0;
+ label = 9;
+ break;
+ case 6:
+ $next = $2 + 4 | 0;
+ $3 = HEAP32[$next >> 2] | 0;
+ $tobool6 = ($3 | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call8 = _zmalloc(632) | 0;
+ $4 = $call8;
+ $5 = HEAP32[2248] | 0;
+ $next9 = $5 + 4 | 0;
+ HEAP32[$next9 >> 2] = $4;
+ label = 8;
+ break;
+ case 8:
+ $6 = HEAP32[2248] | 0;
+ $next10 = $6 + 4 | 0;
+ $7 = HEAP32[$next10 >> 2] | 0;
+ HEAP32[2248] = $7;
+ label = 9;
+ break;
+ case 9:
+ $8 = HEAP32[2248] | 0;
+ $output_langname = $8 + 52 | 0;
+ HEAP32[$output_langname >> 2] = $name;
+ $9 = HEAP32[2248] | 0;
+ $gvc13 = $9 | 0;
+ HEAP32[$gvc13 >> 2] = $gvc;
+ $call14 = _gvplugin_load($gvc, 3, $name) | 0;
+ $not_tobool15 = ($call14 | 0) != 0;
+ $_ = $not_tobool15 & 1;
+ return $_ | 0;
+ }
+ return 0;
+}
+function _gv_argvlist_set_item($list, $index, $item) {
+ $list = $list | 0;
+ $index = $index | 0;
+ $item = $item | 0;
+ var $alloc = 0, $0 = 0, $cmp = 0, $add = 0, $argv = 0, $1 = 0, $2 = 0, $mul = 0, $call = 0, $3 = 0, $argv4 = 0, $4 = 0, $arrayidx = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $alloc = $list + 8 | 0;
+ $0 = HEAP32[$alloc >> 2] | 0;
+ $cmp = ($0 | 0) > ($index | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $index + 10 | 0;
+ HEAP32[$alloc >> 2] = $add;
+ $argv = $list | 0;
+ $1 = HEAP32[$argv >> 2] | 0;
+ $2 = $1;
+ $mul = $add << 2;
+ $call = _grealloc($2, $mul) | 0;
+ $3 = $call;
+ HEAP32[$argv >> 2] = $3;
+ label = 4;
+ break;
+ case 4:
+ $argv4 = $list | 0;
+ $4 = HEAP32[$argv4 >> 2] | 0;
+ $arrayidx = $4 + ($index << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $item;
+ return;
+ }
+}
+function _gv_argvlist_reset($list) {
+ $list = $list | 0;
+ var $argv = 0, $0 = 0, $tobool = 0, $1 = 0, $alloc = 0, $argc = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $argv = $list | 0;
+ $0 = HEAP32[$argv >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $0;
+ _free($1);
+ label = 4;
+ break;
+ case 4:
+ HEAP32[$argv >> 2] = 0;
+ $alloc = $list + 8 | 0;
+ HEAP32[$alloc >> 2] = 0;
+ $argc = $list + 4 | 0;
+ HEAP32[$argc >> 2] = 0;
+ return;
+ }
+}
+function _gvjobs_delete($gvc) {
+ $gvc = $gvc | 0;
+ var $jobs = 0, $0 = 0, $tobool12 = 0, $job_013 = 0, $next = 0, $1 = 0, $selected_obj_attributes = 0, $selected_obj_type_name = 0, $active_tooltip = 0, $2 = 0, $tobool1 = 0, $selected_href = 0, $3 = 0, $tobool3 = 0, $4 = 0, $tobool = 0, $active_jobs = 0, $job7 = 0, $viewNum = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $jobs = $gvc + 120 | 0;
+ $0 = HEAP32[$jobs >> 2] | 0;
+ $tobool12 = ($0 | 0) == 0;
+ if ($tobool12) {
+ label = 8;
+ break;
+ } else {
+ $job_013 = $0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $next = $job_013 + 4 | 0;
+ $1 = HEAP32[$next >> 2] | 0;
+ $selected_obj_attributes = $job_013 + 604 | 0;
+ _gv_argvlist_reset($selected_obj_attributes);
+ $selected_obj_type_name = $job_013 + 592 | 0;
+ _gv_argvlist_reset($selected_obj_type_name);
+ $active_tooltip = $job_013 + 584 | 0;
+ $2 = HEAP32[$active_tooltip >> 2] | 0;
+ $tobool1 = ($2 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _free($2);
+ label = 5;
+ break;
+ case 5:
+ $selected_href = $job_013 + 588 | 0;
+ $3 = HEAP32[$selected_href >> 2] | 0;
+ $tobool3 = ($3 | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _free($3);
+ label = 7;
+ break;
+ case 7:
+ $4 = $job_013;
+ _free($4);
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $job_013 = $1;
+ label = 3;
+ break;
+ }
+ case 8:
+ HEAP32[2248] = 0;
+ HEAP32[2250] = 0;
+ $active_jobs = $gvc + 164 | 0;
+ HEAP32[$active_jobs >> 2] = 0;
+ $job7 = $gvc + 124 | 0;
+ HEAP32[$job7 >> 2] = 0;
+ HEAP32[$jobs >> 2] = 0;
+ $viewNum = $gvc + 28 | 0;
+ HEAP32[$viewNum >> 2] = 0;
+ return;
+ }
+}
+function _gvplugin_install($gvc, $api, $typestr, $quality, $package, $typeptr) {
+ $gvc = $gvc | 0;
+ $api = $api | 0;
+ $typestr = $typestr | 0;
+ $quality = $quality | 0;
+ $package = $package | 0;
+ $typeptr = $typeptr | 0;
+ var $pins = 0, $pnxt = 0, $arraydecay = 0, $call = 0, $call2 = 0, $tobool = 0, $arrayidx = 0, $0 = 0, $tobool519 = 0, $arraydecay6 = 0, $pnext_0_lcssa = 0, $arraydecay23 = 0, $1 = 0, $pnext_020 = 0, $typestr7 = 0, $2 = 0, $call8 = 0, $call10 = 0, $tobool11 = 0, $call16 = 0, $cmp17 = 0, $3 = 0, $next = 0, $4 = 0, $tobool5 = 0, $pnext_1 = 0, $5 = 0, $tobool21 = 0, $typestr24 = 0, $6 = 0, $call25 = 0, $call27 = 0, $tobool28 = 0, $call33 = 0, $cmp34 = 0, $7 = 0, $quality37 = 0, $8 = 0, $cmp38 = 0, $next41 = 0, $call43 = 0, $9 = 0, $10 = 0, $next44 = 0, $typestr45 = 0, $11 = 0, $quality46 = 0, $12 = 0, $package47 = 0, $13 = 0, $typeptr48 = 0, $14 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pins = __stackBase__ | 0;
+ $pnxt = __stackBase__ + 64 | 0;
+ $arraydecay = $pins | 0;
+ $call = _strncpy($arraydecay | 0, $typestr | 0, 63) | 0;
+ $call2 = _strchr($arraydecay | 0, 58) | 0;
+ $tobool = ($call2 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAP8[$call2] = 0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $gvc + 60 + ($api << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool519 = ($0 | 0) == 0;
+ if ($tobool519) {
+ $pnext_0_lcssa = $arrayidx;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $arraydecay6 = $pnxt | 0;
+ $pnext_020 = $arrayidx;
+ $1 = $0;
+ label = 7;
+ break;
+ case 6:
+ $arraydecay23 = $pnxt | 0;
+ $pnext_1 = $pnext_0_lcssa;
+ label = 11;
+ break;
+ case 7:
+ $typestr7 = $1 + 4 | 0;
+ $2 = HEAP32[$typestr7 >> 2] | 0;
+ $call8 = _strncpy($arraydecay6 | 0, $2 | 0, 63) | 0;
+ $call10 = _strchr($arraydecay6 | 0, 58) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ if ($tobool11) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ HEAP8[$call10] = 0;
+ label = 9;
+ break;
+ case 9:
+ $call16 = _strcmp($arraydecay | 0, $arraydecay6 | 0) | 0;
+ $cmp17 = ($call16 | 0) < 1;
+ if ($cmp17) {
+ $pnext_0_lcssa = $pnext_020;
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $3 = HEAP32[$pnext_020 >> 2] | 0;
+ $next = $3 | 0;
+ $4 = HEAP32[$next >> 2] | 0;
+ $tobool5 = ($4 | 0) == 0;
+ if ($tobool5) {
+ $pnext_0_lcssa = $next;
+ label = 6;
+ break;
+ } else {
+ $pnext_020 = $next;
+ $1 = $4;
+ label = 7;
+ break;
+ }
+ case 11:
+ $5 = HEAP32[$pnext_1 >> 2] | 0;
+ $tobool21 = ($5 | 0) == 0;
+ if ($tobool21) {
+ label = 16;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $typestr24 = $5 + 4 | 0;
+ $6 = HEAP32[$typestr24 >> 2] | 0;
+ $call25 = _strncpy($arraydecay23 | 0, $6 | 0, 63) | 0;
+ $call27 = _strchr($arraydecay23 | 0, 58) | 0;
+ $tobool28 = ($call27 | 0) == 0;
+ if ($tobool28) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ HEAP8[$call27] = 0;
+ label = 14;
+ break;
+ case 14:
+ $call33 = _strcmp($arraydecay | 0, $arraydecay23 | 0) | 0;
+ $cmp34 = ($call33 | 0) == 0;
+ if ($cmp34) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $7 = HEAP32[$pnext_1 >> 2] | 0;
+ $quality37 = $7 + 8 | 0;
+ $8 = HEAP32[$quality37 >> 2] | 0;
+ $cmp38 = ($8 | 0) > ($quality | 0);
+ $next41 = $7 | 0;
+ if ($cmp38) {
+ $pnext_1 = $next41;
+ label = 11;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $call43 = _gmalloc(20) | 0;
+ $9 = $call43;
+ $10 = HEAP32[$pnext_1 >> 2] | 0;
+ $next44 = $call43;
+ HEAP32[$next44 >> 2] = $10;
+ HEAP32[$pnext_1 >> 2] = $9;
+ $typestr45 = $call43 + 4 | 0;
+ $11 = $typestr45;
+ HEAP32[$11 >> 2] = $typestr;
+ $quality46 = $call43 + 8 | 0;
+ $12 = $quality46;
+ HEAP32[$12 >> 2] = $quality;
+ $package47 = $call43 + 12 | 0;
+ $13 = $package47;
+ HEAP32[$13 >> 2] = $package;
+ $typeptr48 = $call43 + 16 | 0;
+ $14 = $typeptr48;
+ HEAP32[$14 >> 2] = $typeptr;
+ STACKTOP = __stackBase__;
+ return 1;
+ }
+ return 0;
+}
+function _gvplugin_library_load($gvc, $path) {
+ $gvc = $gvc | 0;
+ $path = $path | 0;
+ var __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ _agerr(1, 104968, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return 0;
+}
+function _gvplugin_load($gvc, $api, $str) {
+ $gvc = $gvc | 0;
+ $api = $api | 0;
+ $str = $str | 0;
+ var $reqtyp = 0, $typ = 0, $api_off = 0, $0 = 0, $apidep_0 = 0, $arraydecay = 0, $call = 0, $call6 = 0, $tobool = 0, $incdec_ptr = 0, $call8 = 0, $tobool9 = 0, $incdec_ptr11 = 0, $reqdep_0 = 0, $reqpkg_0 = 0, $arrayidx = 0, $1 = 0, $tobool1658 = 0, $arraydecay17 = 0, $tobool32 = 0, $tobool38 = 0, $cmp45 = 0, $2 = 0, $pnext_059 = 0, $typestr = 0, $3 = 0, $call18 = 0, $call20 = 0, $tobool21 = 0, $incdec_ptr23 = 0, $dep_0 = 0, $call27 = 0, $tobool28 = 0, $tobool31_not = 0, $or_cond = 0, $call34 = 0, $tobool35 = 0, $4 = 0, $package = 0, $5 = 0, $name = 0, $6 = 0, $call40 = 0, $cmp41 = 0, $or_cond53 = 0, $call47 = 0, $tobool48 = 0, $7 = 0, $next = 0, $8 = 0, $tobool16 = 0, $_pr = 0, $tobool53 = 0, $typeptr = 0, $9 = 0, $cmp55 = 0, $call58 = 0, $10 = 0, $cmp96 = 0, $_ = 0, $tobool99 = 0, $verbose102 = 0, $11 = 0, $cmp103 = 0, $12 = 0, $arrayidx105 = 0, $13 = 0, $typestr106 = 0, $14 = 0, $package107 = 0, $15 = 0, $name108 = 0, $16 = 0, $call109 = 0, $rv_056 = 0, $arrayidx112 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $reqtyp = __stackBase__ | 0;
+ $typ = __stackBase__ + 64 | 0;
+ $api_off = $api - 3 | 0;
+ $0 = $api_off >>> 0 < 2;
+ $apidep_0 = $0 ? 0 : $api;
+ $arraydecay = $reqtyp | 0;
+ $call = _strncpy($arraydecay | 0, $str | 0, 63) | 0;
+ $call6 = _strchr($arraydecay | 0, 58) | 0;
+ $tobool = ($call6 | 0) == 0;
+ if ($tobool) {
+ $reqpkg_0 = 0;
+ $reqdep_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $incdec_ptr = $call6 + 1 | 0;
+ HEAP8[$call6] = 0;
+ $call8 = _strchr($incdec_ptr | 0, 58) | 0;
+ $tobool9 = ($call8 | 0) == 0;
+ if ($tobool9) {
+ $reqpkg_0 = 0;
+ $reqdep_0 = $incdec_ptr;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr11 = $call8 + 1 | 0;
+ HEAP8[$call8] = 0;
+ $reqpkg_0 = $incdec_ptr11;
+ $reqdep_0 = $incdec_ptr;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx = $gvc + 60 + ($api << 2) | 0;
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool1658 = ($1 | 0) == 0;
+ if ($tobool1658) {
+ $rv_056 = 0;
+ label = 23;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $arraydecay17 = $typ | 0;
+ $tobool32 = ($reqdep_0 | 0) == 0;
+ $tobool38 = ($reqpkg_0 | 0) == 0;
+ $cmp45 = ($apidep_0 | 0) == ($api | 0);
+ $pnext_059 = $arrayidx;
+ $2 = $1;
+ label = 7;
+ break;
+ case 7:
+ $typestr = $2 + 4 | 0;
+ $3 = HEAP32[$typestr >> 2] | 0;
+ $call18 = _strncpy($arraydecay17 | 0, $3 | 0, 63) | 0;
+ $call20 = _strchr($arraydecay17 | 0, 58) | 0;
+ $tobool21 = ($call20 | 0) == 0;
+ if ($tobool21) {
+ $dep_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $incdec_ptr23 = $call20 + 1 | 0;
+ HEAP8[$call20] = 0;
+ $dep_0 = $incdec_ptr23;
+ label = 9;
+ break;
+ case 9:
+ $call27 = _strcmp($arraydecay17 | 0, $arraydecay | 0) | 0;
+ $tobool28 = ($call27 | 0) == 0;
+ if ($tobool28) {
+ label = 10;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 10:
+ $tobool31_not = ($dep_0 | 0) == 0;
+ $or_cond = $tobool31_not | $tobool32;
+ if ($or_cond) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call34 = _strcmp($dep_0 | 0, $reqdep_0 | 0) | 0;
+ $tobool35 = ($call34 | 0) == 0;
+ if ($tobool35) {
+ label = 12;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 12:
+ if ($tobool38) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $4 = HEAP32[$pnext_059 >> 2] | 0;
+ $package = $4 + 12 | 0;
+ $5 = HEAP32[$package >> 2] | 0;
+ $name = $5 + 8 | 0;
+ $6 = HEAP32[$name >> 2] | 0;
+ $call40 = _strcmp($reqpkg_0 | 0, $6 | 0) | 0;
+ $cmp41 = ($call40 | 0) == 0;
+ if ($cmp41) {
+ label = 14;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 14:
+ $or_cond53 = $tobool31_not | $cmp45;
+ if ($or_cond53) {
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $call47 = _gvplugin_load($gvc, $apidep_0, $dep_0) | 0;
+ $tobool48 = ($call47 | 0) == 0;
+ if ($tobool48) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $7 = HEAP32[$pnext_059 >> 2] | 0;
+ $next = $7 | 0;
+ $8 = HEAP32[$next >> 2] | 0;
+ $tobool16 = ($8 | 0) == 0;
+ if ($tobool16) {
+ $rv_056 = 0;
+ label = 23;
+ break;
+ } else {
+ $pnext_059 = $next;
+ $2 = $8;
+ label = 7;
+ break;
+ }
+ case 17:
+ $_pr = HEAP32[$pnext_059 >> 2] | 0;
+ $tobool53 = ($_pr | 0) == 0;
+ if ($tobool53) {
+ $rv_056 = 0;
+ label = 23;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $typeptr = $_pr + 16 | 0;
+ $9 = HEAP32[$typeptr >> 2] | 0;
+ $cmp55 = ($9 | 0) == 0;
+ if ($cmp55) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $call58 = _gvplugin_library_load(0, 0) | 0;
+ label = 20;
+ break;
+ case 20:
+ $10 = HEAP32[$typeptr >> 2] | 0;
+ $cmp96 = ($10 | 0) == 0;
+ $_ = $cmp96 ? 0 : $_pr;
+ $tobool99 = ($_ | 0) == 0;
+ if ($tobool99) {
+ $rv_056 = 0;
+ label = 23;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $verbose102 = $gvc + 8 | 0;
+ $11 = HEAP32[$verbose102 >> 2] | 0;
+ $cmp103 = ($11 | 0) > 0;
+ if ($cmp103) {
+ label = 22;
+ break;
+ } else {
+ $rv_056 = $_;
+ label = 23;
+ break;
+ }
+ case 22:
+ $12 = HEAP32[_stderr >> 2] | 0;
+ $arrayidx105 = 88456 + ($api << 2) | 0;
+ $13 = HEAP32[$arrayidx105 >> 2] | 0;
+ $typestr106 = $_ + 4 | 0;
+ $14 = HEAP32[$typestr106 >> 2] | 0;
+ $package107 = $_ + 12 | 0;
+ $15 = HEAP32[$package107 >> 2] | 0;
+ $name108 = $15 + 8 | 0;
+ $16 = HEAP32[$name108 >> 2] | 0;
+ $call109 = _fprintf($12 | 0, 115448, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $13, HEAP32[tempInt + 8 >> 2] = $14, HEAP32[tempInt + 16 >> 2] = $16, tempInt) | 0) | 0;
+ $rv_056 = $_;
+ label = 23;
+ break;
+ case 23:
+ $arrayidx112 = $gvc + 80 + ($api << 2) | 0;
+ HEAP32[$arrayidx112 >> 2] = $rv_056;
+ STACKTOP = __stackBase__;
+ return $rv_056 | 0;
+ }
+ return 0;
+}
+function _gvplugin_list($gvc, $api, $str) {
+ $gvc = $gvc | 0;
+ $api = $api | 0;
+ $str = $str | 0;
+ var $_b = 0, $call = 0, $call3 = 0, $tobool4 = 0, $arrayidx29 = 0, $incdec_ptr = 0, $arrayidx = 0, $tobool7 = 0, $0 = 0, $tobool940 = 0, $1 = 0, $new_042 = 0, $pnext_041 = 0, $typestr = 0, $2 = 0, $call10 = 0, $call11 = 0, $tobool12 = 0, $3 = 0, $tobool17 = 0, $call18 = 0, $cmp19 = 0, $4 = 0, $5 = 0, $cmp21 = 0, $call22 = 0, $6 = 0, $incdec_ptr23 = 0, $7 = 0, $typestr24 = 0, $8 = 0, $call25 = 0, $9 = 0, $10 = 0, $cmp26 = 0, $call28 = 0, $11 = 0, $incdec_ptr32 = 0, $12 = 0, $package = 0, $13 = 0, $name = 0, $14 = 0, $call33 = 0, $new_1 = 0, $15 = 0, $next = 0, $16 = 0, $tobool9 = 0, $arrayidx31_ph = 0, $tobool36 = 0, $pnext_1_ph = 0, $new_3_ph = 0, $17 = 0, $tobool3935 = 0, $18 = 0, $new_338 = 0, $typestr_last_037 = 0, $pnext_136 = 0, $typestr41 = 0, $19 = 0, $call42 = 0, $call43 = 0, $tobool44 = 0, $tobool48 = 0, $call50 = 0, $cmp51 = 0, $20 = 0, $21 = 0, $cmp53 = 0, $call55 = 0, $22 = 0, $incdec_ptr59 = 0, $call60 = 0, $new_433 = 0, $23 = 0, $next66 = 0, $24 = 0, $tobool39 = 0, $tobool68 = 0, $new_3_lcssa48 = 0, $new_3_lcssa47 = 0, $tobool72 = 0, $25 = 0, $26 = 0, $cmp74 = 0, $call76 = 0, $27 = 0, $28 = 0, $bp_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $_b = HEAP8[14384] | 0;
+ if ($_b) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _agxbinit(14368, 0, 0);
+ HEAP8[14384] = 1;
+ label = 4;
+ break;
+ case 4:
+ $call = _strdup($str | 0) | 0;
+ $call3 = _strchr($call | 0, 58) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $arrayidx29 = $gvc + 60 + ($api << 2) | 0;
+ $arrayidx31_ph = $arrayidx29;
+ label = 19;
+ break;
+ case 6:
+ $incdec_ptr = $call3 + 1 | 0;
+ HEAP8[$call3] = 0;
+ $arrayidx = $gvc + 60 + ($api << 2) | 0;
+ $tobool7 = ($incdec_ptr | 0) == 0;
+ if ($tobool7) {
+ $arrayidx31_ph = $arrayidx;
+ label = 19;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool940 = ($0 | 0) == 0;
+ if ($tobool940) {
+ label = 8;
+ break;
+ } else {
+ $pnext_041 = $arrayidx;
+ $new_042 = 1;
+ $1 = $0;
+ label = 9;
+ break;
+ }
+ case 8:
+ _free($call);
+ $new_3_ph = 1;
+ $pnext_1_ph = $arrayidx;
+ label = 21;
+ break;
+ case 9:
+ $typestr = $1 + 4 | 0;
+ $2 = HEAP32[$typestr >> 2] | 0;
+ $call10 = _strdup($2 | 0) | 0;
+ $call11 = _strchr($call10 | 0, 58) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ HEAP8[$call11] = 0;
+ label = 11;
+ break;
+ case 11:
+ $3 = HEAP8[$call] | 0;
+ $tobool17 = $3 << 24 >> 24 == 0;
+ if ($tobool17) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call18 = _strcasecmp($call, $call10) | 0;
+ $cmp19 = ($call18 | 0) == 0;
+ if ($cmp19) {
+ label = 13;
+ break;
+ } else {
+ $new_1 = $new_042;
+ label = 18;
+ break;
+ }
+ case 13:
+ $4 = HEAP32[3593] | 0;
+ $5 = HEAP32[3594] | 0;
+ $cmp21 = $4 >>> 0 < $5 >>> 0;
+ if ($cmp21) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $call22 = _agxbmore(14368, 1) | 0;
+ label = 15;
+ break;
+ case 15:
+ $6 = HEAP32[3593] | 0;
+ $incdec_ptr23 = $6 + 1 | 0;
+ HEAP32[3593] = $incdec_ptr23;
+ HEAP8[$6] = 32;
+ $7 = HEAP32[$pnext_041 >> 2] | 0;
+ $typestr24 = $7 + 4 | 0;
+ $8 = HEAP32[$typestr24 >> 2] | 0;
+ $call25 = _agxbput(14368, $8) | 0;
+ $9 = HEAP32[3593] | 0;
+ $10 = HEAP32[3594] | 0;
+ $cmp26 = $9 >>> 0 < $10 >>> 0;
+ if ($cmp26) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $call28 = _agxbmore(14368, 1) | 0;
+ label = 17;
+ break;
+ case 17:
+ $11 = HEAP32[3593] | 0;
+ $incdec_ptr32 = $11 + 1 | 0;
+ HEAP32[3593] = $incdec_ptr32;
+ HEAP8[$11] = 58;
+ $12 = HEAP32[$pnext_041 >> 2] | 0;
+ $package = $12 + 12 | 0;
+ $13 = HEAP32[$package >> 2] | 0;
+ $name = $13 + 8 | 0;
+ $14 = HEAP32[$name >> 2] | 0;
+ $call33 = _agxbput(14368, $14) | 0;
+ $new_1 = 0;
+ label = 18;
+ break;
+ case 18:
+ _free($call10);
+ $15 = HEAP32[$pnext_041 >> 2] | 0;
+ $next = $15 | 0;
+ $16 = HEAP32[$next >> 2] | 0;
+ $tobool9 = ($16 | 0) == 0;
+ if ($tobool9) {
+ label = 20;
+ break;
+ } else {
+ $pnext_041 = $next;
+ $new_042 = $new_1;
+ $1 = $16;
+ label = 9;
+ break;
+ }
+ case 19:
+ _free($call);
+ $new_3_ph = 1;
+ $pnext_1_ph = $arrayidx31_ph;
+ label = 21;
+ break;
+ case 20:
+ _free($call);
+ $tobool36 = $new_1 << 24 >> 24 == 0;
+ if ($tobool36) {
+ label = 34;
+ break;
+ } else {
+ $new_3_ph = $new_1;
+ $pnext_1_ph = $arrayidx;
+ label = 21;
+ break;
+ }
+ case 21:
+ $17 = HEAP32[$pnext_1_ph >> 2] | 0;
+ $tobool3935 = ($17 | 0) == 0;
+ if ($tobool3935) {
+ $new_3_lcssa48 = $new_3_ph;
+ label = 32;
+ break;
+ } else {
+ $pnext_136 = $pnext_1_ph;
+ $typestr_last_037 = 0;
+ $new_338 = $new_3_ph;
+ $18 = $17;
+ label = 22;
+ break;
+ }
+ case 22:
+ $typestr41 = $18 + 4 | 0;
+ $19 = HEAP32[$typestr41 >> 2] | 0;
+ $call42 = _strdup($19 | 0) | 0;
+ $call43 = _strchr($call42 | 0, 58) | 0;
+ $tobool44 = ($call43 | 0) == 0;
+ if ($tobool44) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ HEAP8[$call43] = 0;
+ label = 24;
+ break;
+ case 24:
+ $tobool48 = ($typestr_last_037 | 0) != 0;
+ if ($tobool48) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $call50 = _strcasecmp($typestr_last_037, $call42) | 0;
+ $cmp51 = ($call50 | 0) == 0;
+ if ($cmp51) {
+ $new_433 = $new_338;
+ label = 30;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $20 = HEAP32[3593] | 0;
+ $21 = HEAP32[3594] | 0;
+ $cmp53 = $20 >>> 0 < $21 >>> 0;
+ if ($cmp53) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $call55 = _agxbmore(14368, 1) | 0;
+ label = 28;
+ break;
+ case 28:
+ $22 = HEAP32[3593] | 0;
+ $incdec_ptr59 = $22 + 1 | 0;
+ HEAP32[3593] = $incdec_ptr59;
+ HEAP8[$22] = 32;
+ $call60 = _agxbput(14368, $call42) | 0;
+ if ($tobool48) {
+ $new_433 = 0;
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ _free($typestr_last_037);
+ $new_433 = 0;
+ label = 30;
+ break;
+ case 30:
+ $23 = HEAP32[$pnext_136 >> 2] | 0;
+ $next66 = $23 | 0;
+ $24 = HEAP32[$next66 >> 2] | 0;
+ $tobool39 = ($24 | 0) == 0;
+ if ($tobool39) {
+ label = 31;
+ break;
+ } else {
+ $pnext_136 = $next66;
+ $typestr_last_037 = $call42;
+ $new_338 = $new_433;
+ $18 = $24;
+ label = 22;
+ break;
+ }
+ case 31:
+ $tobool68 = ($call42 | 0) == 0;
+ if ($tobool68) {
+ $new_3_lcssa48 = $new_433;
+ label = 32;
+ break;
+ } else {
+ $new_3_lcssa47 = $new_433;
+ label = 33;
+ break;
+ }
+ case 32:
+ _free(0);
+ $new_3_lcssa47 = $new_3_lcssa48;
+ label = 33;
+ break;
+ case 33:
+ $tobool72 = $new_3_lcssa47 << 24 >> 24 == 0;
+ if ($tobool72) {
+ label = 34;
+ break;
+ } else {
+ $bp_0 = 110504;
+ label = 37;
+ break;
+ }
+ case 34:
+ $25 = HEAP32[3593] | 0;
+ $26 = HEAP32[3594] | 0;
+ $cmp74 = $25 >>> 0 < $26 >>> 0;
+ if ($cmp74) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $call76 = _agxbmore(14368, 1) | 0;
+ label = 36;
+ break;
+ case 36:
+ $27 = HEAP32[3593] | 0;
+ HEAP8[$27] = 0;
+ $28 = HEAP32[3592] | 0;
+ HEAP32[3593] = $28;
+ $bp_0 = $28;
+ label = 37;
+ break;
+ case 37:
+ return $bp_0 | 0;
+ }
+ return 0;
+}
+function _gvrender_select($job, $str) {
+ $job = $job | 0;
+ $str = $str | 0;
+ var $gvc1 = 0, $0 = 0, $call = 0, $arrayidx = 0, $1 = 0, $tobool = 0, $typeptr2 = 0, $2 = 0, $engine = 0, $3 = 0, $4 = 0, $engine3 = 0, $features = 0, $5 = 0, $6 = 0, $features5 = 0, $id = 0, $7 = 0, $id7 = 0, $typestr = 0, $8 = 0, $type = 0, $9 = 0, $flags = 0, $10 = 0, $flags11 = 0, $11 = 0, $or = 0, $arrayidx13 = 0, $12 = 0, $tobool14 = 0, $typeptr16 = 0, $13 = 0, $engine17 = 0, $14 = 0, $15 = 0, $engine18 = 0, $features19 = 0, $16 = 0, $17 = 0, $features21 = 0, $typestr22 = 0, $18 = 0, $type24 = 0, $19 = 0, $flags27 = 0, $20 = 0, $21 = 0, $or29 = 0, $22 = 0, $tobool32 = 0, $id34 = 0, $23 = 0, $id36 = 0, $24 = 0, $id41 = 0, $engine45 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $call = _gvplugin_load($0, 3, $str) | 0;
+ $arrayidx = $0 + 92 | 0;
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 999;
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $typeptr2 = $1 + 16 | 0;
+ $2 = HEAP32[$typeptr2 >> 2] | 0;
+ $engine = $2 + 12 | 0;
+ $3 = HEAP32[$engine >> 2] | 0;
+ $4 = $3;
+ $engine3 = $job + 76 | 0;
+ HEAP32[$engine3 >> 2] = $4;
+ $features = $2 + 16 | 0;
+ $5 = HEAP32[$features >> 2] | 0;
+ $6 = $5;
+ $features5 = $job + 84 | 0;
+ HEAP32[$features5 >> 2] = $6;
+ $id = $2 | 0;
+ $7 = HEAP32[$id >> 2] | 0;
+ $id7 = $job + 80 | 0;
+ HEAP32[$id7 >> 2] = $7;
+ $typestr = $1 + 4 | 0;
+ $8 = HEAP32[$typestr >> 2] | 0;
+ $type = $job + 88 | 0;
+ HEAP32[$type >> 2] = $8;
+ $9 = HEAP32[$features5 >> 2] | 0;
+ $flags = $9 | 0;
+ $10 = HEAP32[$flags >> 2] | 0;
+ $flags11 = $job + 152 | 0;
+ $11 = HEAP32[$flags11 >> 2] | 0;
+ $or = $11 | $10;
+ HEAP32[$flags11 >> 2] = $or;
+ $arrayidx13 = $0 + 80 | 0;
+ $12 = HEAP32[$arrayidx13 >> 2] | 0;
+ $tobool14 = ($12 | 0) == 0;
+ if ($tobool14) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $typeptr16 = $12 + 16 | 0;
+ $13 = HEAP32[$typeptr16 >> 2] | 0;
+ $engine17 = $13 + 12 | 0;
+ $14 = HEAP32[$engine17 >> 2] | 0;
+ $15 = $14;
+ $engine18 = $job + 60 | 0;
+ HEAP32[$engine18 >> 2] = $15;
+ $features19 = $13 + 16 | 0;
+ $16 = HEAP32[$features19 >> 2] | 0;
+ $17 = $16;
+ $features21 = $job + 68 | 0;
+ HEAP32[$features21 >> 2] = $17;
+ $typestr22 = $12 + 4 | 0;
+ $18 = HEAP32[$typestr22 >> 2] | 0;
+ $type24 = $job + 72 | 0;
+ HEAP32[$type24 >> 2] = $18;
+ $19 = HEAP32[$features21 >> 2] | 0;
+ $flags27 = $19 | 0;
+ $20 = HEAP32[$flags27 >> 2] | 0;
+ $21 = HEAP32[$flags11 >> 2] | 0;
+ $or29 = $21 | $20;
+ HEAP32[$flags11 >> 2] = $or29;
+ $22 = HEAP32[$engine3 >> 2] | 0;
+ $tobool32 = ($22 | 0) == 0;
+ if ($tobool32) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $id34 = $13 | 0;
+ $23 = HEAP32[$id34 >> 2] | 0;
+ $id36 = $job + 64 | 0;
+ HEAP32[$id36 >> 2] = $23;
+ $retval_0 = 300;
+ label = 8;
+ break;
+ case 6:
+ $24 = HEAP32[$id7 >> 2] | 0;
+ $id41 = $job + 64 | 0;
+ HEAP32[$id41 >> 2] = $24;
+ $retval_0 = 300;
+ label = 8;
+ break;
+ case 7:
+ $engine45 = $job + 60 | 0;
+ HEAP32[$engine45 >> 2] = 0;
+ $retval_0 = 999;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvrender_begin_job($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $1 = 0, $call = 0, $tobool = 0, $tobool1 = 0, $begin_job = 0, $2 = 0, $tobool3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $1 = $job;
+ $call = _gvdevice_initialize($1) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 6;
+ break;
+ }
+ case 3:
+ $tobool1 = ($0 | 0) == 0;
+ if ($tobool1) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $begin_job = $0 | 0;
+ $2 = HEAP32[$begin_job >> 2] | 0;
+ $tobool3 = ($2 | 0) == 0;
+ if ($tobool3) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ FUNCTION_TABLE_vi[$2 & 1023]($job);
+ $retval_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvrender_end_job($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_job = 0, $1 = 0, $tobool1 = 0, $gvc = 0, $2 = 0, $lib = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_job = $0 + 4 | 0;
+ $1 = HEAP32[$end_job >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ $gvc = $job | 0;
+ $2 = HEAP32[$gvc >> 2] | 0;
+ $lib = $2 + 24 | 0;
+ HEAP32[$lib >> 2] = 0;
+ $3 = $job;
+ _gvdevice_finalize($3);
+ return;
+ }
+}
+function _gvrender_begin_graph($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $gvc1 = 0, $0 = 0, $engine = 0, $1 = 0, $tobool = 0, $begin_graph = 0, $2 = 0, $tobool2 = 0, $3 = 0, $call = 0, $cmp = 0, $4 = 0, $tobool5 = 0, $features = 0, $5 = 0, $bgcolor = 0, $resolve_color = 0, $6 = 0, $tobool8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc1 = $job | 0;
+ $0 = HEAP32[$gvc1 >> 2] | 0;
+ $engine = $job + 60 | 0;
+ $1 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_graph = $1 + 8 | 0;
+ $2 = HEAP32[$begin_graph >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$2 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ $3 = $g | 0;
+ $call = _agget($3, 90304) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $4 = HEAP8[$call] | 0;
+ $tobool5 = $4 << 24 >> 24 == 0;
+ if ($tobool5) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $features = $job + 68 | 0;
+ $5 = HEAP32[$features >> 2] | 0;
+ $bgcolor = $0 + 312 | 0;
+ _gvrender_resolve_color($5, $call, $bgcolor);
+ $resolve_color = $1 + 92 | 0;
+ $6 = HEAP32[$resolve_color >> 2] | 0;
+ $tobool8 = ($6 | 0) == 0;
+ if ($tobool8) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ FUNCTION_TABLE_vii[$6 & 1023]($job, $bgcolor);
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _gvrender_resolve_color($features, $name, $color) {
+ $features = $features | 0;
+ $name = $name | 0;
+ $color = $color | 0;
+ var $tok = 0, $string = 0, $type = 0, $call = 0, $knowncolors = 0, $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $sz_knowncolors = 0, $3 = 0, $call2 = 0, $cmp = 0, $color_type = 0, $4 = 0, $call3 = 0, $call8 = 0, $add = 0, $call9 = 0, $call10 = 0, $call11 = 0, $tobool12 = 0, $call14 = 0, $call15 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tok = __stackBase__ | 0;
+ $string = $color;
+ HEAP32[$string >> 2] = $name;
+ $type = $color + 32 | 0;
+ HEAP32[$type >> 2] = 5;
+ $call = _canontoken($name) | 0;
+ HEAP32[$tok >> 2] = $call;
+ $knowncolors = $features + 16 | 0;
+ $0 = HEAP32[$knowncolors >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $tok;
+ $2 = $0;
+ $sz_knowncolors = $features + 20 | 0;
+ $3 = HEAP32[$sz_knowncolors >> 2] | 0;
+ $call2 = _bsearch($1 | 0, $2 | 0, $3 | 0, 4, 254) | 0;
+ $cmp = ($call2 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 4:
+ $color_type = $features + 24 | 0;
+ $4 = HEAP32[$color_type >> 2] | 0;
+ $call3 = _colorxlate($name, $color, $4) | 0;
+ if (($call3 | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($call3 | 0) == 0) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $call8 = _strlen($name | 0) | 0;
+ $add = $call8 + 16 | 0;
+ $call9 = _gmalloc($add) | 0;
+ $call10 = _sprintf($call9 | 0, 146272, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $name, tempInt) | 0) | 0;
+ $call11 = _emit_once($call9) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call14 = _agerr(0, 143304, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $name, tempInt) | 0) | 0;
+ label = 7;
+ break;
+ case 7:
+ _free($call9);
+ label = 9;
+ break;
+ case 8:
+ $call15 = _agerr(1, 139648, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvrender_end_graph($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_graph = 0, $1 = 0, $tobool1 = 0, $2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_graph = $0 + 12 | 0;
+ $1 = HEAP32[$end_graph >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ $2 = $job;
+ _gvdevice_format($2);
+ return;
+ }
+}
+function _gvrender_begin_page($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_page = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_page = $0 + 24 | 0;
+ $1 = HEAP32[$begin_page >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_page($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_page = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_page = $0 + 28 | 0;
+ $1 = HEAP32[$end_page >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_begin_layer($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_layer = 0, $1 = 0, $tobool1 = 0, $layerNum = 0, $2 = 0, $gvc = 0, $3 = 0, $layerIDs = 0, $4 = 0, $arrayidx = 0, $5 = 0, $numLayers = 0, $6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_layer = $0 + 16 | 0;
+ $1 = HEAP32[$begin_layer >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $layerNum = $job + 160 | 0;
+ $2 = HEAP32[$layerNum >> 2] | 0;
+ $gvc = $job | 0;
+ $3 = HEAP32[$gvc >> 2] | 0;
+ $layerIDs = $3 + 280 | 0;
+ $4 = HEAP32[$layerIDs >> 2] | 0;
+ $arrayidx = $4 + ($2 << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $numLayers = $job + 156 | 0;
+ $6 = HEAP32[$numLayers >> 2] | 0;
+ FUNCTION_TABLE_viiii[$1 & 1023]($job, $5, $2, $6);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_layer($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_layer = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_layer = $0 + 20 | 0;
+ $1 = HEAP32[$end_layer >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_begin_cluster($job, $sg) {
+ $job = $job | 0;
+ $sg = $sg | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_cluster = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_cluster = $0 + 32 | 0;
+ $1 = HEAP32[$begin_cluster >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_cluster($job, $g) {
+ $job = $job | 0;
+ $g = $g | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_cluster = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_cluster = $0 + 36 | 0;
+ $1 = HEAP32[$end_cluster >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_begin_nodes($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_nodes = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_nodes = $0 + 40 | 0;
+ $1 = HEAP32[$begin_nodes >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_nodes($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_nodes = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_nodes = $0 + 44 | 0;
+ $1 = HEAP32[$end_nodes >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_begin_edges($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_edges = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_edges = $0 + 48 | 0;
+ $1 = HEAP32[$begin_edges >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_edges($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_edges = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_edges = $0 + 52 | 0;
+ $1 = HEAP32[$end_edges >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_begin_node($job, $n) {
+ $job = $job | 0;
+ $n = $n | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_node = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_node = $0 + 56 | 0;
+ $1 = HEAP32[$begin_node >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_node($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_node = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_node = $0 + 60 | 0;
+ $1 = HEAP32[$end_node >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_begin_edge($job, $e) {
+ $job = $job | 0;
+ $e = $e | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_edge = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_edge = $0 + 64 | 0;
+ $1 = HEAP32[$begin_edge >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_edge($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_edge = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_edge = $0 + 68 | 0;
+ $1 = HEAP32[$end_edge >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_begin_anchor($job, $href, $tooltip, $target, $id) {
+ $job = $job | 0;
+ $href = $href | 0;
+ $tooltip = $tooltip | 0;
+ $target = $target | 0;
+ $id = $id | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_anchor = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_anchor = $0 + 72 | 0;
+ $1 = HEAP32[$begin_anchor >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_viiiii[$1 & 1023]($job, $href, $tooltip, $target, $id);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_anchor($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_anchor = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_anchor = $0 + 76 | 0;
+ $1 = HEAP32[$end_anchor >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_begin_label($job, $type) {
+ $job = $job | 0;
+ $type = $type | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $begin_label = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $begin_label = $0 + 80 | 0;
+ $1 = HEAP32[$begin_label >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vii[$1 & 1023]($job, $type);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_end_label($job) {
+ $job = $job | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $end_label = 0, $1 = 0, $tobool1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $end_label = $0 + 84 | 0;
+ $1 = HEAP32[$end_label >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ FUNCTION_TABLE_vi[$1 & 1023]($job);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvrender_textpara($job, $p, $para) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $para = $para | 0;
+ var $PF = 0, $tmp = 0, $engine = 0, $0 = 0, $str = 0, $1 = 0, $tobool = 0, $2 = 0, $tobool2 = 0, $obj = 0, $3 = 0, $tobool4 = 0, $pen = 0, $4 = 0, $cmp = 0, $flags = 0, $5 = 0, $and = 0, $tobool7 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $tobool9 = 0, $textpara = 0, $10 = 0, $tobool11 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $PF = __stackBase__ | 0;
+ $tmp = __stackBase__ + 16 | 0;
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $str = $para | 0;
+ $1 = HEAP32[$str >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP8[$1] | 0;
+ $tobool2 = $2 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 12;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $obj = $job + 16 | 0;
+ $3 = HEAP32[$obj >> 2] | 0;
+ $tobool4 = ($3 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $pen = $3 + 96 | 0;
+ $4 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($4 | 0) == 0;
+ if ($cmp) {
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $flags = $job + 152 | 0;
+ $5 = HEAP32[$flags >> 2] | 0;
+ $and = $5 & 8192;
+ $tobool7 = ($and | 0) == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $6 = $PF;
+ $7 = $p;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ label = 9;
+ break;
+ case 8:
+ _gvrender_ptf($tmp, $job, $p);
+ $8 = $PF;
+ $9 = $tmp;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ label = 9;
+ break;
+ case 9:
+ $tobool9 = ($0 | 0) == 0;
+ if ($tobool9) {
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $textpara = $0 + 88 | 0;
+ $10 = HEAP32[$textpara >> 2] | 0;
+ $tobool11 = ($10 | 0) == 0;
+ if ($tobool11) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ FUNCTION_TABLE_viii[$10 & 1023]($job, $PF, $para);
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvrender_set_pencolor($job, $name) {
+ $job = $job | 0;
+ $name = $name | 0;
+ var $engine = 0, $0 = 0, $obj = 0, $1 = 0, $pencolor = 0, $strchr = 0, $tobool = 0, $tobool1 = 0, $features = 0, $2 = 0, $resolve_color = 0, $3 = 0, $tobool4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $obj = $job + 16 | 0;
+ $1 = HEAP32[$obj >> 2] | 0;
+ $pencolor = $1 + 16 | 0;
+ $strchr = _strchr($name | 0, 58) | 0;
+ $tobool = ($strchr | 0) != 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP8[$strchr] = 0;
+ label = 4;
+ break;
+ case 4:
+ $tobool1 = ($0 | 0) == 0;
+ if ($tobool1) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $features = $job + 68 | 0;
+ $2 = HEAP32[$features >> 2] | 0;
+ _gvrender_resolve_color($2, $name, $pencolor);
+ $resolve_color = $0 + 92 | 0;
+ $3 = HEAP32[$resolve_color >> 2] | 0;
+ $tobool4 = ($3 | 0) == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ FUNCTION_TABLE_vii[$3 & 1023]($job, $pencolor);
+ label = 7;
+ break;
+ case 7:
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ HEAP8[$strchr] = 58;
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _gvrender_set_fillcolor($job, $name) {
+ $job = $job | 0;
+ $name = $name | 0;
+ var $engine = 0, $0 = 0, $obj = 0, $1 = 0, $fillcolor = 0, $strchr = 0, $tobool = 0, $tobool1 = 0, $features = 0, $2 = 0, $resolve_color = 0, $3 = 0, $tobool4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $obj = $job + 16 | 0;
+ $1 = HEAP32[$obj >> 2] | 0;
+ $fillcolor = $1 + 56 | 0;
+ $strchr = _strchr($name | 0, 58) | 0;
+ $tobool = ($strchr | 0) != 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP8[$strchr] = 0;
+ label = 4;
+ break;
+ case 4:
+ $tobool1 = ($0 | 0) == 0;
+ if ($tobool1) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $features = $job + 68 | 0;
+ $2 = HEAP32[$features >> 2] | 0;
+ _gvrender_resolve_color($2, $name, $fillcolor);
+ $resolve_color = $0 + 92 | 0;
+ $3 = HEAP32[$resolve_color >> 2] | 0;
+ $tobool4 = ($3 | 0) == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ FUNCTION_TABLE_vii[$3 & 1023]($job, $fillcolor);
+ label = 7;
+ break;
+ case 7:
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ HEAP8[$strchr] = 58;
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _gvrender_set_style($job, $s) {
+ $job = $job | 0;
+ $s = $s | 0;
+ var $engine = 0, $0 = 0, $obj1 = 0, $1 = 0, $rawstyle = 0, $tobool = 0, $tobool2 = 0, $or_cond = 0, $2 = 0, $tobool436 = 0, $pen = 0, $pen17 = 0, $pen27 = 0, $pen44 = 0, $penwidth = 0, $penwidth69 = 0, $fill = 0, $fill88 = 0, $3 = 0, $s_pn = 0, $incdec_ptr37 = 0, $4 = 0, $cmp = 0, $call = 0, $tobool7 = 0, $_pr = 0, $5 = 0, $cmp11 = 0, $call14 = 0, $tobool15 = 0, $6 = 0, $tobool4 = 0, $7 = 0, $cmp21 = 0, $call24 = 0, $tobool25 = 0, $_pr32 = 0, $8 = 0, $cmp31 = 0, $call34 = 0, $tobool35 = 0, $9 = 0, $cmp38 = 0, $call41 = 0, $tobool42 = 0, $_pr33 = 0, $10 = 0, $cmp48 = 0, $call51 = 0, $tobool52 = 0, $11 = 0, $cmp57 = 0, $call60 = 0, $tobool61 = 0, $p_0 = 0, $12 = 0, $tobool64 = 0, $incdec_ptr66 = 0, $call68 = 0.0, $_pr34 = 0, $13 = 0, $cmp73 = 0, $call76 = 0, $tobool77 = 0, $14 = 0, $cmp82 = 0, $call85 = 0, $tobool86 = 0, $call90 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $obj1 = $job + 16 | 0;
+ $1 = HEAP32[$obj1 >> 2] | 0;
+ $rawstyle = $1 + 112 | 0;
+ HEAP32[$rawstyle >> 2] = $s;
+ $tobool = ($0 | 0) == 0;
+ $tobool2 = ($s | 0) == 0;
+ $or_cond = $tobool | $tobool2;
+ if ($or_cond) {
+ label = 38;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$s >> 2] | 0;
+ $tobool436 = ($2 | 0) == 0;
+ if ($tobool436) {
+ label = 38;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $pen = $1 + 96 | 0;
+ $pen17 = $1 + 96 | 0;
+ $pen27 = $1 + 96 | 0;
+ $pen44 = $1 + 96 | 0;
+ $penwidth = $1 + 104 | 0;
+ $penwidth69 = $1 + 104 | 0;
+ $fill = $1 + 100 | 0;
+ $fill88 = $1 + 100 | 0;
+ $s_pn = $s;
+ $3 = $2;
+ label = 5;
+ break;
+ case 5:
+ $incdec_ptr37 = $s_pn + 4 | 0;
+ $4 = HEAP8[$3] | 0;
+ $cmp = $4 << 24 >> 24 == 115;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ $5 = $4;
+ label = 9;
+ break;
+ }
+ case 6:
+ $call = _strcmp($3 | 0, 130512) | 0;
+ $tobool7 = ($call | 0) == 0;
+ if ($tobool7) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$pen >> 2] = 3;
+ label = 12;
+ break;
+ case 8:
+ $_pr = HEAP8[$3] | 0;
+ $5 = $_pr;
+ label = 9;
+ break;
+ case 9:
+ $cmp11 = $5 << 24 >> 24 == 100;
+ if ($cmp11) {
+ label = 10;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 10:
+ $call14 = _strcmp($3 | 0, 118464) | 0;
+ $tobool15 = ($call14 | 0) == 0;
+ if ($tobool15) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ HEAP32[$pen17 >> 2] = 1;
+ label = 12;
+ break;
+ case 12:
+ $6 = HEAP32[$incdec_ptr37 >> 2] | 0;
+ $tobool4 = ($6 | 0) == 0;
+ if ($tobool4) {
+ label = 38;
+ break;
+ } else {
+ $s_pn = $incdec_ptr37;
+ $3 = $6;
+ label = 5;
+ break;
+ }
+ case 13:
+ $7 = HEAP8[$3] | 0;
+ $cmp21 = $7 << 24 >> 24 == 100;
+ if ($cmp21) {
+ label = 14;
+ break;
+ } else {
+ $8 = $7;
+ label = 17;
+ break;
+ }
+ case 14:
+ $call24 = _strcmp($3 | 0, 113072) | 0;
+ $tobool25 = ($call24 | 0) == 0;
+ if ($tobool25) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ HEAP32[$pen27 >> 2] = 2;
+ label = 12;
+ break;
+ case 16:
+ $_pr32 = HEAP8[$3] | 0;
+ $8 = $_pr32;
+ label = 17;
+ break;
+ case 17:
+ $cmp31 = $8 << 24 >> 24 == 105;
+ if ($cmp31) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $call34 = _strcmp($3 | 0, 108704) | 0;
+ $tobool35 = ($call34 | 0) == 0;
+ if ($tobool35) {
+ label = 21;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $9 = HEAP8[$3] | 0;
+ $cmp38 = $9 << 24 >> 24 == 105;
+ if ($cmp38) {
+ label = 20;
+ break;
+ } else {
+ $10 = $9;
+ label = 23;
+ break;
+ }
+ case 20:
+ $call41 = _strcmp($3 | 0, 104616) | 0;
+ $tobool42 = ($call41 | 0) == 0;
+ if ($tobool42) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ HEAP32[$pen44 >> 2] = 0;
+ label = 12;
+ break;
+ case 22:
+ $_pr33 = HEAP8[$3] | 0;
+ $10 = $_pr33;
+ label = 23;
+ break;
+ case 23:
+ $cmp48 = $10 << 24 >> 24 == 98;
+ if ($cmp48) {
+ label = 24;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 24:
+ $call51 = _strcmp($3 | 0, 100424) | 0;
+ $tobool52 = ($call51 | 0) == 0;
+ if ($tobool52) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ HEAPF64[$penwidth >> 3] = 2.0;
+ label = 12;
+ break;
+ case 26:
+ $11 = HEAP8[$3] | 0;
+ $cmp57 = $11 << 24 >> 24 == 115;
+ if ($cmp57) {
+ label = 27;
+ break;
+ } else {
+ $13 = $11;
+ label = 31;
+ break;
+ }
+ case 27:
+ $call60 = _strcmp($3 | 0, 96216) | 0;
+ $tobool61 = ($call60 | 0) == 0;
+ if ($tobool61) {
+ $p_0 = $3;
+ label = 28;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 28:
+ $12 = HEAP8[$p_0] | 0;
+ $tobool64 = $12 << 24 >> 24 == 0;
+ $incdec_ptr66 = $p_0 + 1 | 0;
+ if ($tobool64) {
+ label = 29;
+ break;
+ } else {
+ $p_0 = $incdec_ptr66;
+ label = 28;
+ break;
+ }
+ case 29:
+ $call68 = +_atof($incdec_ptr66);
+ HEAPF64[$penwidth69 >> 3] = $call68;
+ label = 12;
+ break;
+ case 30:
+ $_pr34 = HEAP8[$3] | 0;
+ $13 = $_pr34;
+ label = 31;
+ break;
+ case 31:
+ $cmp73 = $13 << 24 >> 24 == 102;
+ if ($cmp73) {
+ label = 32;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 32:
+ $call76 = _strcmp($3 | 0, 92800) | 0;
+ $tobool77 = ($call76 | 0) == 0;
+ if ($tobool77) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ HEAP32[$fill >> 2] = 1;
+ label = 12;
+ break;
+ case 34:
+ $14 = HEAP8[$3] | 0;
+ $cmp82 = $14 << 24 >> 24 == 117;
+ if ($cmp82) {
+ label = 35;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 35:
+ $call85 = _strcmp($3 | 0, 162912) | 0;
+ $tobool86 = ($call85 | 0) == 0;
+ if ($tobool86) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ HEAP32[$fill88 >> 2] = 0;
+ label = 12;
+ break;
+ case 37:
+ $call90 = _agerr(0, 159472, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $3, tempInt) | 0) | 0;
+ label = 12;
+ break;
+ case 38:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvrender_ellipse($job, $pf, $n, $filled) {
+ $job = $job | 0;
+ $pf = $pf | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $af = 0, $engine = 0, $0 = 0, $tobool = 0, $ellipse = 0, $1 = 0, $tobool1 = 0, $obj = 0, $2 = 0, $pen = 0, $3 = 0, $cmp = 0, $x = 0, $4 = 0.0, $arrayidx3 = 0, $x4 = 0, $5 = 0.0, $add = 0.0, $div = 0.0, $arrayidx5 = 0, $x6 = 0, $y = 0, $6 = 0.0, $y9 = 0, $7 = 0.0, $add10 = 0.0, $div11 = 0.0, $y13 = 0, $arrayidx14 = 0, $8 = 0, $9 = 0, $flags = 0, $10 = 0, $and = 0, $tobool16 = 0, $call = 0, $11 = 0, $conv = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $af = __stackBase__ | 0;
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $ellipse = $0 + 96 | 0;
+ $1 = HEAP32[$ellipse >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $obj = $job + 16 | 0;
+ $2 = HEAP32[$obj >> 2] | 0;
+ $pen = $2 + 96 | 0;
+ $3 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($3 | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $x = $pf | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $arrayidx3 = $pf + 16 | 0;
+ $x4 = $arrayidx3 | 0;
+ $5 = +HEAPF64[$x4 >> 3];
+ $add = $4 + $5;
+ $div = $add * .5;
+ $arrayidx5 = $af | 0;
+ $x6 = $af | 0;
+ HEAPF64[$x6 >> 3] = $div;
+ $y = $pf + 8 | 0;
+ $6 = +HEAPF64[$y >> 3];
+ $y9 = $pf + 24 | 0;
+ $7 = +HEAPF64[$y9 >> 3];
+ $add10 = $6 + $7;
+ $div11 = $add10 * .5;
+ $y13 = $af + 8 | 0;
+ HEAPF64[$y13 >> 3] = $div11;
+ $arrayidx14 = $af + 16 | 0;
+ $8 = $arrayidx14;
+ $9 = $arrayidx3;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $flags = $job + 152 | 0;
+ $10 = HEAP32[$flags >> 2] | 0;
+ $and = $10 & 8192;
+ $tobool16 = ($and | 0) == 0;
+ if ($tobool16) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call = _gvrender_ptf_A($job, $arrayidx5, $arrayidx5, 2) | 0;
+ label = 7;
+ break;
+ case 7:
+ $11 = HEAP32[$ellipse >> 2] | 0;
+ $conv = $filled & 255;
+ FUNCTION_TABLE_viii[$11 & 1023]($job, $arrayidx5, $conv);
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvrender_polygon($job, $af, $n, $filled) {
+ $job = $job | 0;
+ $af = $af | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $polygon = 0, $1 = 0, $tobool1 = 0, $obj = 0, $2 = 0, $pen = 0, $3 = 0, $cmp = 0, $flags = 0, $4 = 0, $and = 0, $tobool3 = 0, $conv = 0, $5 = 0, $cmp6 = 0, $add = 0, $6 = 0, $7 = 0, $mul = 0, $call = 0, $8 = 0, $9 = 0, $call9 = 0, $10 = 0, $11 = 0, $conv11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $polygon = $0 + 100 | 0;
+ $1 = HEAP32[$polygon >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $obj = $job + 16 | 0;
+ $2 = HEAP32[$obj >> 2] | 0;
+ $pen = $2 + 96 | 0;
+ $3 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($3 | 0) == 0;
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $flags = $job + 152 | 0;
+ $4 = HEAP32[$flags >> 2] | 0;
+ $and = $4 & 8192;
+ $tobool3 = ($and | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $conv = $filled & 255;
+ FUNCTION_TABLE_viiii[$1 & 1023]($job, $af, $n, $conv);
+ label = 10;
+ break;
+ case 7:
+ $5 = HEAP32[1052] | 0;
+ $cmp6 = ($5 | 0) < ($n | 0);
+ if ($cmp6) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $add = $n + 10 | 0;
+ HEAP32[1052] = $add;
+ $6 = HEAP32[42146] | 0;
+ $7 = $6;
+ $mul = $add << 4;
+ $call = _grealloc($7, $mul) | 0;
+ $8 = $call;
+ HEAP32[42146] = $8;
+ label = 9;
+ break;
+ case 9:
+ $9 = HEAP32[42146] | 0;
+ $call9 = _gvrender_ptf_A($job, $af, $9, $n) | 0;
+ $10 = HEAP32[$polygon >> 2] | 0;
+ $11 = HEAP32[42146] | 0;
+ $conv11 = $filled & 255;
+ FUNCTION_TABLE_viiii[$10 & 1023]($job, $11, $n, $conv11);
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _gvrender_box($job, $B, $filled) {
+ $job = $job | 0;
+ $B = $B | 0;
+ $filled = $filled | 0;
+ var $A = 0, $0 = 0, $1 = 0, $arrayidx1 = 0, $2 = 0, $3 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ tempParam = $B;
+ $B = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($B, tempParam, 32);
+ $A = __stackBase__ | 0;
+ $0 = $A;
+ $1 = $B;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $arrayidx1 = $A + 32 | 0;
+ $2 = $arrayidx1;
+ $3 = $B + 16 | 0;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ HEAPF64[$A + 16 >> 3] = +HEAPF64[$A >> 3];
+ HEAPF64[$A + 24 >> 3] = +HEAPF64[$A + 40 >> 3];
+ HEAPF64[$A + 48 >> 3] = +HEAPF64[$arrayidx1 >> 3];
+ HEAPF64[$A + 56 >> 3] = +HEAPF64[$A + 8 >> 3];
+ _gvrender_polygon($job, $A | 0, 4, $filled);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _gvrender_set_penwidth($job, $penwidth) {
+ $job = $job | 0;
+ $penwidth = +$penwidth;
+ var $engine = 0, $0 = 0, $tobool = 0, $obj = 0, $1 = 0, $penwidth1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $obj = $job + 16 | 0;
+ $1 = HEAP32[$obj >> 2] | 0;
+ $penwidth1 = $1 + 104 | 0;
+ HEAPF64[$penwidth1 >> 3] = $penwidth;
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _gvusershape_size_dpi($agg_result, $us, $dpi) {
+ $agg_result = $agg_result | 0;
+ $us = $us | 0;
+ $dpi = $dpi | 0;
+ var $tobool = 0, $dpi1 = 0, $0 = 0, $cmp = 0, $conv = 0.0, $y4 = 0, $x5 = 0, $w = 0, $1 = 0, $mul = 0, $conv6 = 0.0, $x7 = 0, $2 = 0.0, $div = 0.0, $conv8 = 0, $h = 0, $3 = 0, $mul10 = 0, $conv11 = 0.0, $y12 = 0, $4 = 0.0, $div13 = 0.0, $conv14 = 0, $rv_sroa_1_0 = 0, $rv_sroa_0_0 = 0, $rv_sroa_0_0__idx = 0, $rv_sroa_1_4__idx1 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $dpi;
+ $dpi = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$dpi >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$dpi + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$dpi + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$dpi + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($us | 0) == 0;
+ if ($tobool) {
+ $rv_sroa_0_0 = -1;
+ $rv_sroa_1_0 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $dpi1 = $us + 48 | 0;
+ $0 = HEAP32[$dpi1 >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = +($0 | 0);
+ $y4 = $dpi + 8 | 0;
+ HEAPF64[$y4 >> 3] = $conv;
+ $x5 = $dpi | 0;
+ HEAPF64[$x5 >> 3] = $conv;
+ label = 5;
+ break;
+ case 5:
+ $w = $us + 40 | 0;
+ $1 = HEAP32[$w >> 2] | 0;
+ $mul = $1 * 72 & -1;
+ $conv6 = +($mul | 0);
+ $x7 = $dpi | 0;
+ $2 = +HEAPF64[$x7 >> 3];
+ $div = $conv6 / $2;
+ $conv8 = ~~$div;
+ $h = $us + 44 | 0;
+ $3 = HEAP32[$h >> 2] | 0;
+ $mul10 = $3 * 72 & -1;
+ $conv11 = +($mul10 | 0);
+ $y12 = $dpi + 8 | 0;
+ $4 = +HEAPF64[$y12 >> 3];
+ $div13 = $conv11 / $4;
+ $conv14 = ~~$div13;
+ $rv_sroa_0_0 = $conv8;
+ $rv_sroa_1_0 = $conv14;
+ label = 6;
+ break;
+ case 6:
+ $rv_sroa_0_0__idx = $agg_result | 0;
+ HEAP32[$rv_sroa_0_0__idx >> 2] = $rv_sroa_0_0;
+ $rv_sroa_1_4__idx1 = $agg_result + 4 | 0;
+ HEAP32[$rv_sroa_1_4__idx1 >> 2] = $rv_sroa_1_0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvrender_beziercurve($job, $af, $n, $arrow_at_start, $arrow_at_end, $filled) {
+ $job = $job | 0;
+ $af = $af | 0;
+ $n = $n | 0;
+ $arrow_at_start = $arrow_at_start | 0;
+ $arrow_at_end = $arrow_at_end | 0;
+ $filled = $filled | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $beziercurve = 0, $1 = 0, $tobool1 = 0, $obj = 0, $2 = 0, $pen = 0, $3 = 0, $cmp = 0, $flags = 0, $4 = 0, $and = 0, $tobool3 = 0, $conv = 0, $5 = 0, $cmp6 = 0, $add = 0, $6 = 0, $7 = 0, $mul = 0, $call = 0, $8 = 0, $9 = 0, $call9 = 0, $10 = 0, $11 = 0, $conv11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $beziercurve = $0 + 104 | 0;
+ $1 = HEAP32[$beziercurve >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $obj = $job + 16 | 0;
+ $2 = HEAP32[$obj >> 2] | 0;
+ $pen = $2 + 96 | 0;
+ $3 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($3 | 0) == 0;
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $flags = $job + 152 | 0;
+ $4 = HEAP32[$flags >> 2] | 0;
+ $and = $4 & 8192;
+ $tobool3 = ($and | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $conv = $filled & 255;
+ FUNCTION_TABLE_viiiiii[$1 & 1023]($job, $af, $n, $arrow_at_start, $arrow_at_end, $conv);
+ label = 10;
+ break;
+ case 7:
+ $5 = HEAP32[1052] | 0;
+ $cmp6 = ($5 | 0) < ($n | 0);
+ if ($cmp6) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $add = $n + 10 | 0;
+ HEAP32[1052] = $add;
+ $6 = HEAP32[42146] | 0;
+ $7 = $6;
+ $mul = $add << 4;
+ $call = _grealloc($7, $mul) | 0;
+ $8 = $call;
+ HEAP32[42146] = $8;
+ label = 9;
+ break;
+ case 9:
+ $9 = HEAP32[42146] | 0;
+ $call9 = _gvrender_ptf_A($job, $af, $9, $n) | 0;
+ $10 = HEAP32[$beziercurve >> 2] | 0;
+ $11 = HEAP32[42146] | 0;
+ $conv11 = $filled & 255;
+ FUNCTION_TABLE_viiiiii[$10 & 1023]($job, $11, $n, $arrow_at_start, $arrow_at_end, $conv11);
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _gvrender_polyline($job, $af, $n) {
+ $job = $job | 0;
+ $af = $af | 0;
+ $n = $n | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $polyline = 0, $1 = 0, $tobool1 = 0, $obj = 0, $2 = 0, $pen = 0, $3 = 0, $cmp = 0, $flags = 0, $4 = 0, $and = 0, $tobool3 = 0, $5 = 0, $cmp6 = 0, $add = 0, $6 = 0, $7 = 0, $mul = 0, $call = 0, $8 = 0, $9 = 0, $call8 = 0, $10 = 0, $11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $polyline = $0 + 108 | 0;
+ $1 = HEAP32[$polyline >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $obj = $job + 16 | 0;
+ $2 = HEAP32[$obj >> 2] | 0;
+ $pen = $2 + 96 | 0;
+ $3 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($3 | 0) == 0;
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $flags = $job + 152 | 0;
+ $4 = HEAP32[$flags >> 2] | 0;
+ $and = $4 & 8192;
+ $tobool3 = ($and | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ FUNCTION_TABLE_viii[$1 & 1023]($job, $af, $n);
+ label = 10;
+ break;
+ case 7:
+ $5 = HEAP32[1052] | 0;
+ $cmp6 = ($5 | 0) < ($n | 0);
+ if ($cmp6) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $add = $n + 10 | 0;
+ HEAP32[1052] = $add;
+ $6 = HEAP32[42146] | 0;
+ $7 = $6;
+ $mul = $add << 4;
+ $call = _grealloc($7, $mul) | 0;
+ $8 = $call;
+ HEAP32[42146] = $8;
+ label = 9;
+ break;
+ case 9:
+ $9 = HEAP32[42146] | 0;
+ $call8 = _gvrender_ptf_A($job, $af, $9, $n) | 0;
+ $10 = HEAP32[$polyline >> 2] | 0;
+ $11 = HEAP32[42146] | 0;
+ FUNCTION_TABLE_viii[$10 & 1023]($job, $11, $n);
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _gvrender_comment($job, $str) {
+ $job = $job | 0;
+ $str = $str | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $1 = 0, $tobool1 = 0, $tobool2 = 0, $or_cond = 0, $comment = 0, $2 = 0, $tobool4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($str | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$str] | 0;
+ $tobool1 = $1 << 24 >> 24 == 0;
+ $tobool2 = ($0 | 0) == 0;
+ $or_cond = $tobool1 | $tobool2;
+ if ($or_cond) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $comment = $0 + 112 | 0;
+ $2 = HEAP32[$comment >> 2] | 0;
+ $tobool4 = ($2 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ FUNCTION_TABLE_vii[$2 & 1023]($job, $str);
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _gvrender_usershape($job, $name, $a, $n, $filled, $imagescale) {
+ $job = $job | 0;
+ $name = $name | 0;
+ $a = $a | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ $imagescale = $imagescale | 0;
+ var $b = 0, $tmp = 0, $tmp139 = 0, $tmp142 = 0, $engine = 0, $0 = 0, $call = 0, $tobool = 0, $call1 = 0, $tobool2 = 0, $tobool4 = 0, $or_cond = 0, $library_shape = 0, $1 = 0, $tobool5 = 0, $conv = 0, $dpi = 0, $isz_sroa_0_0__idx = 0, $isz_sroa_0_0_copyload = 0, $isz_sroa_1_4__idx3 = 0, $isz_sroa_1_4_copyload = 0, $cmp = 0, $cmp12 = 0, $or_cond65 = 0, $LL = 0, $UR = 0, $2 = 0, $3 = 0, $4 = 0, $cmp1667 = 0, $x19 = 0, $y31 = 0, $x47 = 0, $y63 = 0, $x19_promoted = 0.0, $y31_promoted = 0.0, $x47_promoted = 0.0, $y63_promoted = 0.0, $5 = 0.0, $_6669 = 0.0, $6 = 0.0, $7 = 0.0, $i_068 = 0, $x21 = 0, $8 = 0.0, $cmp22 = 0, $_ = 0.0, $y33 = 0, $9 = 0.0, $cmp34 = 0, $cond43 = 0.0, $10 = 0.0, $cmp50 = 0, $_66 = 0.0, $cmp66 = 0, $cond75 = 0.0, $inc = 0, $cmp16 = 0, $x79 = 0, $11 = 0.0, $x81 = 0, $12 = 0.0, $sub = 0.0, $y83 = 0, $13 = 0.0, $y85 = 0, $14 = 0.0, $sub86 = 0.0, $conv88 = 0.0, $conv90 = 0.0, $div = 0.0, $div91 = 0.0, $call92 = 0, $cmp93 = 0, $mul = 0.0, $mul96 = 0.0, $mul97 = 0.0, $mul98 = 0.0, $mul101 = 0.0, $mul103 = 0.0, $mul105 = 0.0, $mul106 = 0.0, $ih_0 = 0.0, $iw_0 = 0.0, $cmp108 = 0, $sub111 = 0.0, $div112 = 0.0, $15 = 0.0, $add = 0.0, $16 = 0.0, $sub119 = 0.0, $cmp121 = 0, $sub124 = 0.0, $div125 = 0.0, $17 = 0.0, $add128 = 0.0, $18 = 0.0, $sub133 = 0.0, $flags = 0, $19 = 0, $and = 0, $tobool135 = 0, $20 = 0, $21 = 0, $22 = 0.0, $23 = 0.0, $cmp148 = 0, $24 = 0.0, $25 = 0.0, $cmp165 = 0, $tobool179 = 0, $type = 0, $26 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 72 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $b = __stackBase__ | 0;
+ $tmp = __stackBase__ + 32 | 0;
+ $tmp139 = __stackBase__ + 40 | 0;
+ $tmp142 = __stackBase__ + 56 | 0;
+ $engine = $job + 60 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $call = _gvusershape_find($name) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $call1 = _find_user_shape($name) | 0;
+ $tobool2 = ($call1 | 0) == 0;
+ $tobool4 = ($0 | 0) == 0;
+ $or_cond = $tobool2 | $tobool4;
+ if ($or_cond) {
+ label = 30;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $library_shape = $0 + 116 | 0;
+ $1 = HEAP32[$library_shape >> 2] | 0;
+ $tobool5 = ($1 | 0) == 0;
+ if ($tobool5) {
+ label = 30;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $conv = $filled & 255;
+ FUNCTION_TABLE_viiiii[$1 & 1023]($job, $name, $a, $n, $conv);
+ label = 30;
+ break;
+ case 6:
+ $dpi = $job + 432 | 0;
+ _gvusershape_size_dpi($tmp, $call, $dpi);
+ $isz_sroa_0_0__idx = $tmp | 0;
+ $isz_sroa_0_0_copyload = HEAP32[$isz_sroa_0_0__idx >> 2] | 0;
+ $isz_sroa_1_4__idx3 = $tmp + 4 | 0;
+ $isz_sroa_1_4_copyload = HEAP32[$isz_sroa_1_4__idx3 >> 2] | 0;
+ $cmp = ($isz_sroa_0_0_copyload | 0) < 1;
+ $cmp12 = ($isz_sroa_1_4_copyload | 0) < 1;
+ $or_cond65 = $cmp & $cmp12;
+ if ($or_cond65) {
+ label = 30;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $LL = $b | 0;
+ $UR = $b + 16 | 0;
+ $2 = $UR;
+ $3 = $a;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $4 = $b;
+ HEAP32[$4 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $cmp1667 = ($n | 0) > 1;
+ if ($cmp1667) {
+ label = 8;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ $x19 = $b | 0;
+ $y31 = $b + 8 | 0;
+ $x47 = $UR | 0;
+ $y63 = $b + 24 | 0;
+ $x19_promoted = +HEAPF64[$x19 >> 3];
+ $y31_promoted = +HEAPF64[$y31 >> 3];
+ $x47_promoted = +HEAPF64[$x47 >> 3];
+ $y63_promoted = +HEAPF64[$y63 >> 3];
+ $i_068 = 1;
+ $7 = $x19_promoted;
+ $6 = $y31_promoted;
+ $_6669 = $x47_promoted;
+ $5 = $y63_promoted;
+ label = 9;
+ break;
+ case 9:
+ $x21 = $a + ($i_068 << 4) | 0;
+ $8 = +HEAPF64[$x21 >> 3];
+ $cmp22 = $7 < $8;
+ $_ = $cmp22 ? $7 : $8;
+ $y33 = $a + ($i_068 << 4) + 8 | 0;
+ $9 = +HEAPF64[$y33 >> 3];
+ $cmp34 = $6 < $9;
+ $cond43 = $cmp34 ? $6 : $9;
+ $10 = +HEAPF64[$x21 >> 3];
+ $cmp50 = $_6669 > $10;
+ $_66 = $cmp50 ? $_6669 : $10;
+ $cmp66 = $5 > $9;
+ $cond75 = $cmp66 ? $5 : $9;
+ $inc = $i_068 + 1 | 0;
+ $cmp16 = ($inc | 0) < ($n | 0);
+ if ($cmp16) {
+ $i_068 = $inc;
+ $7 = $_;
+ $6 = $cond43;
+ $_6669 = $_66;
+ $5 = $cond75;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ HEAPF64[$x19 >> 3] = $_;
+ HEAPF64[$y31 >> 3] = $cond43;
+ HEAPF64[$x47 >> 3] = $_66;
+ HEAPF64[$y63 >> 3] = $cond75;
+ label = 11;
+ break;
+ case 11:
+ $x79 = $UR | 0;
+ $11 = +HEAPF64[$x79 >> 3];
+ $x81 = $b | 0;
+ $12 = +HEAPF64[$x81 >> 3];
+ $sub = $11 - $12;
+ $y83 = $b + 24 | 0;
+ $13 = +HEAPF64[$y83 >> 3];
+ $y85 = $b + 8 | 0;
+ $14 = +HEAPF64[$y85 >> 3];
+ $sub86 = $13 - $14;
+ $conv88 = +($isz_sroa_1_4_copyload | 0);
+ $conv90 = +($isz_sroa_0_0_copyload | 0);
+ $div = $sub / $conv90;
+ $div91 = $sub86 / $conv88;
+ $call92 = _get_imagescale($imagescale) | 0;
+ if (($call92 | 0) == 1) {
+ label = 12;
+ break;
+ } else if (($call92 | 0) == 2) {
+ label = 15;
+ break;
+ } else if (($call92 | 0) == 3) {
+ label = 16;
+ break;
+ } else if (($call92 | 0) == 4) {
+ label = 17;
+ break;
+ } else {
+ $iw_0 = $conv90;
+ $ih_0 = $conv88;
+ label = 18;
+ break;
+ }
+ case 12:
+ $cmp93 = $div < $div91;
+ if ($cmp93) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $mul = $conv90 * $div;
+ $mul96 = $conv88 * $div;
+ $iw_0 = $mul;
+ $ih_0 = $mul96;
+ label = 18;
+ break;
+ case 14:
+ $mul97 = $conv90 * $div91;
+ $mul98 = $conv88 * $div91;
+ $iw_0 = $mul97;
+ $ih_0 = $mul98;
+ label = 18;
+ break;
+ case 15:
+ $mul101 = $conv90 * $div;
+ $iw_0 = $mul101;
+ $ih_0 = $conv88;
+ label = 18;
+ break;
+ case 16:
+ $mul103 = $conv88 * $div91;
+ $iw_0 = $conv90;
+ $ih_0 = $mul103;
+ label = 18;
+ break;
+ case 17:
+ $mul105 = $conv90 * $div;
+ $mul106 = $conv88 * $div91;
+ $iw_0 = $mul105;
+ $ih_0 = $mul106;
+ label = 18;
+ break;
+ case 18:
+ $cmp108 = $iw_0 < $sub;
+ if ($cmp108) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $sub111 = $sub - $iw_0;
+ $div112 = $sub111 * .5;
+ $15 = +HEAPF64[$x81 >> 3];
+ $add = $div112 + $15;
+ HEAPF64[$x81 >> 3] = $add;
+ $16 = +HEAPF64[$x79 >> 3];
+ $sub119 = $16 - $div112;
+ HEAPF64[$x79 >> 3] = $sub119;
+ label = 20;
+ break;
+ case 20:
+ $cmp121 = $ih_0 < $sub86;
+ if ($cmp121) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $sub124 = $sub86 - $ih_0;
+ $div125 = $sub124 * .5;
+ $17 = +HEAPF64[$y85 >> 3];
+ $add128 = $div125 + $17;
+ HEAPF64[$y85 >> 3] = $add128;
+ $18 = +HEAPF64[$y83 >> 3];
+ $sub133 = $18 - $div125;
+ HEAPF64[$y83 >> 3] = $sub133;
+ label = 22;
+ break;
+ case 22:
+ $flags = $job + 152 | 0;
+ $19 = HEAP32[$flags >> 2] | 0;
+ $and = $19 & 8192;
+ $tobool135 = ($and | 0) == 0;
+ if ($tobool135) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ _gvrender_ptf($tmp139, $job, $LL);
+ $20 = $tmp139;
+ HEAP32[$4 >> 2] = HEAP32[$20 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$20 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$20 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$20 + 12 >> 2] | 0;
+ _gvrender_ptf($tmp142, $job, $UR);
+ $21 = $tmp142;
+ HEAP32[$2 >> 2] = HEAP32[$21 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$21 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$21 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$21 + 12 >> 2] | 0;
+ label = 24;
+ break;
+ case 24:
+ $22 = +HEAPF64[$x81 >> 3];
+ $23 = +HEAPF64[$x79 >> 3];
+ $cmp148 = $22 > $23;
+ if ($cmp148) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ HEAPF64[$x81 >> 3] = $23;
+ HEAPF64[$x79 >> 3] = $22;
+ label = 26;
+ break;
+ case 26:
+ $24 = +HEAPF64[$y85 >> 3];
+ $25 = +HEAPF64[$y83 >> 3];
+ $cmp165 = $24 > $25;
+ if ($cmp165) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ HEAPF64[$y85 >> 3] = $25;
+ HEAPF64[$y83 >> 3] = $24;
+ label = 28;
+ break;
+ case 28:
+ $tobool179 = ($0 | 0) == 0;
+ if ($tobool179) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $type = $job + 72 | 0;
+ $26 = HEAP32[$type >> 2] | 0;
+ _gvloadimage($job, $call, $b, $filled, $26);
+ label = 30;
+ break;
+ case 30:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _get_imagescale($s) {
+ $s = $s | 0;
+ var $0 = 0, $cmp = 0, $call = 0, $tobool = 0, $call4 = 0, $tobool5 = 0, $call8 = 0, $tobool9 = 0, $call12 = 0, $not_tobool13 = 0, $_ = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$s] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _strcasecmp($s, 155848) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 2;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call4 = _strcasecmp($s, 152504) | 0;
+ $tobool5 = ($call4 | 0) == 0;
+ if ($tobool5) {
+ $retval_0 = 3;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call8 = _strcasecmp($s, 149064) | 0;
+ $tobool9 = ($call8 | 0) == 0;
+ if ($tobool9) {
+ $retval_0 = 4;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call12 = _mapbool($s) | 0;
+ $not_tobool13 = $call12 << 24 >> 24 != 0;
+ $_ = $not_tobool13 & 1;
+ $retval_0 = $_;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvrender_comparestr($s1, $s2) {
+ $s1 = $s1 | 0;
+ $s2 = $s2 | 0;
+ return _strcmp(HEAP32[$s1 >> 2] | 0, HEAP32[$s2 >> 2] | 0) | 0;
+}
+function _gvusershape_find($name) {
+ $name = $name | 0;
+ var $probe = 0, $0 = 0, $tobool = 0, $name1 = 0, $1 = 0, $searchf = 0, $2 = 0, $3 = 0, $call = 0, $4 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $probe = __stackBase__ | 0;
+ $0 = HEAP32[41770] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $name1 = $probe + 8 | 0;
+ HEAP32[$name1 >> 2] = $name;
+ $1 = HEAP32[41770] | 0;
+ $searchf = $1 | 0;
+ $2 = HEAP32[$searchf >> 2] | 0;
+ $3 = $probe;
+ $call = FUNCTION_TABLE_iiii[$2 & 1023]($1, $3, 4) | 0;
+ $4 = $call;
+ $retval_0 = $4;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvusershape_file_release($us) {
+ $us = $us | 0;
+ var $nocache = 0, $0 = 0, $tobool = 0, $f = 0, $1 = 0, $tobool1 = 0, $call = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nocache = $us + 17 | 0;
+ $0 = HEAP8[$nocache] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $f = $us + 20 | 0;
+ $1 = HEAP32[$f >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _fclose($1 | 0) | 0;
+ HEAP32[$f >> 2] = 0;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _gvusershape_size($agg_result, $g, $name) {
+ $agg_result = $agg_result | 0;
+ $g = $g | 0;
+ $name = $name | 0;
+ var $dpi = 0, $tobool = 0, $0 = 0, $cmp = 0, $rv_sroa_0_0__idx = 0, $rv_sroa_1_4__idx1 = 0, $drawing = 0, $1 = 0, $dpi2 = 0, $2 = 0.0, $y3 = 0, $cmp4 = 0, $x8 = 0, $x10 = 0, $call = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $dpi = __stackBase__ | 0;
+ $tobool = ($name | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$name] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $rv_sroa_0_0__idx = $agg_result | 0;
+ HEAP32[$rv_sroa_0_0__idx >> 2] = -1;
+ $rv_sroa_1_4__idx1 = $agg_result + 4 | 0;
+ HEAP32[$rv_sroa_1_4__idx1 >> 2] = -1;
+ label = 9;
+ break;
+ case 5:
+ $drawing = $g + 48 | 0;
+ $1 = HEAP32[$drawing >> 2] | 0;
+ $dpi2 = $1 + 24 | 0;
+ $2 = +HEAPF64[$dpi2 >> 3];
+ $y3 = $dpi + 8 | 0;
+ HEAPF64[$y3 >> 3] = $2;
+ $cmp4 = $2 < 1.0;
+ if ($cmp4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $x8 = $dpi | 0;
+ HEAPF64[$x8 >> 3] = $2;
+ label = 8;
+ break;
+ case 7:
+ HEAPF64[$y3 >> 3] = 96.0;
+ $x10 = $dpi | 0;
+ HEAPF64[$x10 >> 3] = 96.0;
+ label = 8;
+ break;
+ case 8:
+ $call = _gvusershape_open($name) | 0;
+ _gvusershape_size_dpi($agg_result, $call, $dpi);
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvusershape_open($name) {
+ $name = $name | 0;
+ var $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $call = 0, $call1 = 0, $tobool2 = 0, $call4 = 0, $3 = 0, $tobool5 = 0, $name8 = 0, $4 = 0, $call9 = 0, $tobool10 = 0, $call13 = 0, $5 = 0, $call15 = 0, $6 = 0, $data = 0, $7 = 0, $tobool16 = 0, $8 = 0, $call19 = 0, $9 = 0, $searchf = 0, $10 = 0, $call28 = 0, $us_0 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41770] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[41974] | 0;
+ $2 = $1;
+ $call = _dtopen(167e3, $2) | 0;
+ HEAP32[41770] = $call;
+ label = 4;
+ break;
+ case 4:
+ $call1 = _gvusershape_find($name) | 0;
+ $tobool2 = ($call1 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ $us_0 = $call1;
+ label = 18;
+ break;
+ }
+ case 5:
+ $call4 = _zmalloc(64) | 0;
+ $3 = $call4;
+ $tobool5 = ($call4 | 0) == 0;
+ if ($tobool5) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $name8 = $call4 + 8 | 0;
+ $4 = $name8;
+ HEAP32[$4 >> 2] = $name;
+ $call9 = _gvusershape_file_access($3) | 0;
+ $tobool10 = $call9 << 24 >> 24 == 0;
+ if ($tobool10) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call13 = _imagetype($3) | 0;
+ if (($call13 | 0) == 0) {
+ label = 8;
+ break;
+ } else if (($call13 | 0) == 2) {
+ label = 11;
+ break;
+ } else if (($call13 | 0) == 3) {
+ label = 12;
+ break;
+ } else if (($call13 | 0) == 1) {
+ label = 13;
+ break;
+ } else if (($call13 | 0) == 4) {
+ label = 14;
+ break;
+ } else if (($call13 | 0) == 6) {
+ label = 15;
+ break;
+ } else if (($call13 | 0) == 8) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 8:
+ $5 = HEAP32[$4 >> 2] | 0;
+ $call15 = _find_user_shape($5) | 0;
+ $6 = $call15;
+ $data = $call4 + 52 | 0;
+ $7 = $data;
+ HEAP32[$7 >> 2] = $6;
+ $tobool16 = ($call15 | 0) == 0;
+ if ($tobool16) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $8 = HEAP32[$4 >> 2] | 0;
+ $call19 = _agerr(0, 108384, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $8, tempInt) | 0) | 0;
+ label = 10;
+ break;
+ case 10:
+ _free($call4);
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 11:
+ _gif_size($3);
+ label = 17;
+ break;
+ case 12:
+ _png_size($3);
+ label = 17;
+ break;
+ case 13:
+ _bmp_size($3);
+ label = 17;
+ break;
+ case 14:
+ _jpeg_size($3);
+ label = 17;
+ break;
+ case 15:
+ _ps_size($3);
+ label = 17;
+ break;
+ case 16:
+ _svg_size($3);
+ label = 17;
+ break;
+ case 17:
+ $9 = HEAP32[41770] | 0;
+ $searchf = $9 | 0;
+ $10 = HEAP32[$searchf >> 2] | 0;
+ $call28 = FUNCTION_TABLE_iiii[$10 & 1023]($9, $call4, 1) | 0;
+ $us_0 = $3;
+ label = 18;
+ break;
+ case 18:
+ _gvusershape_file_release($us_0);
+ $retval_0 = $us_0;
+ label = 19;
+ break;
+ case 19:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _imagetype($us) {
+ $us = $us | 0;
+ var $header = 0, $line = 0, $f = 0, $0 = 0, $tobool = 0, $arraydecay = 0, $call = 0, $cmp = 0, $stringtype9 = 0, $type11 = 0, $arraydecay16 = 0, $i_019 = 0, $template = 0, $1 = 0, $size = 0, $2 = 0, $call5 = 0, $tobool6 = 0, $stringtype = 0, $3 = 0, $type = 0, $4 = 0, $cmp13 = 0, $5 = 0, $call18 = 0, $cmp19 = 0, $call21 = 0, $tobool22 = 0, $inc = 0, $cmp2 = 0, $stringtype29 = 0, $type30 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 224 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $header = __stackBase__ | 0;
+ $line = __stackBase__ + 24 | 0;
+ $f = $us + 20 | 0;
+ $0 = HEAP32[$f >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arraydecay = $header | 0;
+ $call = _fread($arraydecay | 0, 1, 20, $0 | 0) | 0;
+ $cmp = ($call | 0) == 20;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 4:
+ $stringtype9 = $us + 28 | 0;
+ $type11 = $us + 24 | 0;
+ $arraydecay16 = $line | 0;
+ $i_019 = 0;
+ label = 5;
+ break;
+ case 5:
+ $template = 12208 + ($i_019 << 4) | 0;
+ $1 = HEAP32[$template >> 2] | 0;
+ $size = 12212 + ($i_019 << 4) | 0;
+ $2 = HEAP32[$size >> 2] | 0;
+ $call5 = _memcmp($arraydecay | 0, $1 | 0, $2 | 0) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 6:
+ $stringtype = 12220 + ($i_019 << 4) | 0;
+ $3 = HEAP32[$stringtype >> 2] | 0;
+ HEAP32[$stringtype9 >> 2] = $3;
+ $type = 12216 + ($i_019 << 4) | 0;
+ $4 = HEAP32[$type >> 2] | 0;
+ HEAP32[$type11 >> 2] = $4;
+ $cmp13 = ($i_019 | 0) == 7;
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = $4;
+ label = 12;
+ break;
+ }
+ case 7:
+ $5 = HEAP32[$f >> 2] | 0;
+ $call18 = _fgets($arraydecay16 | 0, 200, $5 | 0) | 0;
+ $cmp19 = ($call18 | 0) == 0;
+ if ($cmp19) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call21 = _memcmp($arraydecay16 | 0, 136856, 4) | 0;
+ $tobool22 = ($call21 | 0) == 0;
+ if ($tobool22) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 9:
+ HEAP32[$stringtype9 >> 2] = 134424;
+ HEAP32[$type11 >> 2] = 8;
+ $retval_0 = 8;
+ label = 12;
+ break;
+ case 10:
+ $inc = $i_019 + 1 | 0;
+ $cmp2 = $inc >>> 0 < 8;
+ if ($cmp2) {
+ $i_019 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $stringtype29 = $us + 28 | 0;
+ HEAP32[$stringtype29 >> 2] = 132040;
+ $type30 = $us + 24 | 0;
+ HEAP32[$type30 >> 2] = 0;
+ $retval_0 = 0;
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gif_size($us) {
+ $us = $us | 0;
+ var $w = 0, $h = 0, $dpi = 0, $f = 0, $0 = 0, $call = 0, $1 = 0, $call2 = 0, $tobool = 0, $2 = 0, $call4 = 0, $tobool6 = 0, $3 = 0, $w7 = 0, $4 = 0, $h8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $w = __stackBase__ | 0;
+ $h = __stackBase__ + 8 | 0;
+ $dpi = $us + 48 | 0;
+ HEAP32[$dpi >> 2] = 0;
+ $f = $us + 20 | 0;
+ $0 = HEAP32[$f >> 2] | 0;
+ $call = _fseek($0 | 0, 6, 0) | 0;
+ $1 = HEAP32[$f >> 2] | 0;
+ $call2 = _get_int_lsb_first($1, $w) | 0;
+ $tobool = $call2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$f >> 2] | 0;
+ $call4 = _get_int_lsb_first($2, $h) | 0;
+ $tobool6 = $call4 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP32[$w >> 2] | 0;
+ $w7 = $us + 40 | 0;
+ HEAP32[$w7 >> 2] = $3;
+ $4 = HEAP32[$h >> 2] | 0;
+ $h8 = $us + 44 | 0;
+ HEAP32[$h8 >> 2] = $4;
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _png_size($us) {
+ $us = $us | 0;
+ var $w = 0, $h = 0, $dpi = 0, $f = 0, $0 = 0, $call = 0, $1 = 0, $call2 = 0, $tobool = 0, $2 = 0, $call4 = 0, $tobool6 = 0, $3 = 0, $w7 = 0, $4 = 0, $h8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $w = __stackBase__ | 0;
+ $h = __stackBase__ + 8 | 0;
+ $dpi = $us + 48 | 0;
+ HEAP32[$dpi >> 2] = 0;
+ $f = $us + 20 | 0;
+ $0 = HEAP32[$f >> 2] | 0;
+ $call = _fseek($0 | 0, 16, 0) | 0;
+ $1 = HEAP32[$f >> 2] | 0;
+ $call2 = _get_int_msb_first($1, 4, $w) | 0;
+ $tobool = $call2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$f >> 2] | 0;
+ $call4 = _get_int_msb_first($2, 4, $h) | 0;
+ $tobool6 = $call4 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP32[$w >> 2] | 0;
+ $w7 = $us + 40 | 0;
+ HEAP32[$w7 >> 2] = $3;
+ $4 = HEAP32[$h >> 2] | 0;
+ $h8 = $us + 44 | 0;
+ HEAP32[$h8 >> 2] = $4;
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _bmp_size($us) {
+ $us = $us | 0;
+ var $size_x_msw = 0, $size_x_lsw = 0, $size_y_msw = 0, $size_y_lsw = 0, $dpi = 0, $f = 0, $0 = 0, $call = 0, $1 = 0, $call2 = 0, $tobool = 0, $2 = 0, $call4 = 0, $tobool6 = 0, $3 = 0, $call9 = 0, $tobool11 = 0, $4 = 0, $call14 = 0, $tobool16 = 0, $5 = 0, $shl = 0, $6 = 0, $or = 0, $w = 0, $7 = 0, $shl17 = 0, $8 = 0, $or18 = 0, $h = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size_x_msw = __stackBase__ | 0;
+ $size_x_lsw = __stackBase__ + 8 | 0;
+ $size_y_msw = __stackBase__ + 16 | 0;
+ $size_y_lsw = __stackBase__ + 24 | 0;
+ $dpi = $us + 48 | 0;
+ HEAP32[$dpi >> 2] = 0;
+ $f = $us + 20 | 0;
+ $0 = HEAP32[$f >> 2] | 0;
+ $call = _fseek($0 | 0, 16, 0) | 0;
+ $1 = HEAP32[$f >> 2] | 0;
+ $call2 = _get_int_lsb_first($1, $size_x_msw) | 0;
+ $tobool = $call2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$f >> 2] | 0;
+ $call4 = _get_int_lsb_first($2, $size_x_lsw) | 0;
+ $tobool6 = $call4 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP32[$f >> 2] | 0;
+ $call9 = _get_int_lsb_first($3, $size_y_msw) | 0;
+ $tobool11 = $call9 << 24 >> 24 == 0;
+ if ($tobool11) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $4 = HEAP32[$f >> 2] | 0;
+ $call14 = _get_int_lsb_first($4, $size_y_lsw) | 0;
+ $tobool16 = $call14 << 24 >> 24 == 0;
+ if ($tobool16) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $5 = HEAP32[$size_x_msw >> 2] | 0;
+ $shl = $5 << 16;
+ $6 = HEAP32[$size_x_lsw >> 2] | 0;
+ $or = $shl | $6;
+ $w = $us + 40 | 0;
+ HEAP32[$w >> 2] = $or;
+ $7 = HEAP32[$size_y_msw >> 2] | 0;
+ $shl17 = $7 << 16;
+ $8 = HEAP32[$size_y_lsw >> 2] | 0;
+ $or18 = $shl17 | $8;
+ $h = $us + 44 | 0;
+ HEAP32[$h >> 2] = $or18;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvusershape_file_access($us) {
+ $us = $us | 0;
+ var $tobool = 0, $name = 0, $0 = 0, $tobool1 = 0, $f = 0, $1 = 0, $tobool5 = 0, $call = 0, $call8 = 0, $tobool9 = 0, $call11 = 0, $cmp = 0, $call15 = 0, $2 = 0, $call16 = 0, $call17 = 0, $3 = 0, $cmp18 = 0, $nocache = 0, $inc = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($us | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(155760, 363, 164216, 158976);
+ return 0;
+ case 4:
+ $name = $us + 8 | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ $tobool1 = ($0 | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ ___assert_func(155760, 364, 164216, 130056);
+ return 0;
+ case 6:
+ $f = $us + 20 | 0;
+ $1 = HEAP32[$f >> 2] | 0;
+ $tobool5 = ($1 | 0) == 0;
+ if ($tobool5) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call = _fseek($1 | 0, 0, 0) | 0;
+ $retval_0 = 1;
+ label = 14;
+ break;
+ case 8:
+ $call8 = _safefile($0) | 0;
+ $tobool9 = ($call8 | 0) == 0;
+ if ($tobool9) {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call11 = _fopen($call8 | 0, 118240) | 0;
+ HEAP32[$f >> 2] = $call11;
+ $cmp = ($call11 | 0) == 0;
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $call15 = ___errno_location() | 0;
+ $2 = HEAP32[$call15 >> 2] | 0;
+ $call16 = _strerror($2 | 0) | 0;
+ $call17 = _agerr(0, 112944, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $call16, HEAP32[tempInt + 8 >> 2] = $call8, tempInt) | 0) | 0;
+ $retval_0 = 0;
+ label = 14;
+ break;
+ case 11:
+ $3 = HEAP32[3508] | 0;
+ $cmp18 = ($3 | 0) > 49;
+ if ($cmp18) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $nocache = $us + 17 | 0;
+ HEAP8[$nocache] = 1;
+ $retval_0 = 1;
+ label = 14;
+ break;
+ case 13:
+ $inc = $3 + 1 | 0;
+ HEAP32[3508] = $inc;
+ $retval_0 = 1;
+ label = 14;
+ break;
+ case 14:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _B1($t) {
+ $t = +$t;
+ var $sub = 0.0;
+ $sub = 1.0 - $t;
+ return +($sub * $t * 3.0 * $sub);
+}
+function _B2($t) {
+ $t = +$t;
+ return +((1.0 - $t) * $t * 3.0 * $t);
+}
+function _jpeg_size($us) {
+ $us = $us | 0;
+ var $marker = 0, $length = 0, $size_x = 0, $size_y = 0, $junk = 0, $dpi = 0, $f = 0, $0 = 0, $call15 = 0, $tobool16 = 0, $1 = 0, $cmp = 0, $call3 = 0, $tobool4 = 0, $cmp7 = 0, $2 = 0, $call10 = 0, $tobool11 = 0, $3 = 0, $call13 = 0, $tobool15 = 0, $4 = 0, $call18 = 0, $tobool20 = 0, $5 = 0, $h = 0, $6 = 0, $w = 0, $cmp24 = 0, $7 = 0, $call28 = 0, $tobool29 = 0, $8 = 0, $call33 = 0, $tobool35 = 0, $9 = 0, $call38 = 0, $tobool40 = 0, $10 = 0, $h42 = 0, $11 = 0, $w43 = 0, $call47 = 0, $tobool48 = 0, $12 = 0, $13 = 0, $sub = 0, $call52 = 0, $14 = 0, $call = 0, $tobool = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $marker = __stackBase__ | 0;
+ $length = __stackBase__ + 8 | 0;
+ $size_x = __stackBase__ + 16 | 0;
+ $size_y = __stackBase__ + 24 | 0;
+ $junk = __stackBase__ + 32 | 0;
+ $dpi = $us + 48 | 0;
+ HEAP32[$dpi >> 2] = 0;
+ $f = $us + 20 | 0;
+ $0 = HEAP32[$f >> 2] | 0;
+ $call15 = _get_int_msb_first($0, 1, $marker) | 0;
+ $tobool16 = $call15 << 24 >> 24 == 0;
+ if ($tobool16) {
+ label = 18;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[$marker >> 2] | 0;
+ $cmp = ($1 | 0) == 255;
+ if ($cmp) {
+ label = 17;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call3 = _strchr(12336, $1 | 0) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 5:
+ $cmp7 = ($1 | 0) == 192;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 6:
+ $2 = HEAP32[$f >> 2] | 0;
+ $call10 = _get_int_msb_first($2, 3, $junk) | 0;
+ $tobool11 = $call10 << 24 >> 24 == 0;
+ if ($tobool11) {
+ label = 18;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $3 = HEAP32[$f >> 2] | 0;
+ $call13 = _get_int_msb_first($3, 2, $size_x) | 0;
+ $tobool15 = $call13 << 24 >> 24 == 0;
+ if ($tobool15) {
+ label = 18;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $4 = HEAP32[$f >> 2] | 0;
+ $call18 = _get_int_msb_first($4, 2, $size_y) | 0;
+ $tobool20 = $call18 << 24 >> 24 == 0;
+ if ($tobool20) {
+ label = 18;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $5 = HEAP32[$size_x >> 2] | 0;
+ $h = $us + 44 | 0;
+ HEAP32[$h >> 2] = $5;
+ $6 = HEAP32[$size_y >> 2] | 0;
+ $w = $us + 40 | 0;
+ HEAP32[$w >> 2] = $6;
+ label = 18;
+ break;
+ case 10:
+ $cmp24 = ($1 | 0) == 194;
+ $7 = HEAP32[$f >> 2] | 0;
+ if ($cmp24) {
+ label = 11;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 11:
+ $call28 = _get_int_msb_first($7, 3, $junk) | 0;
+ $tobool29 = $call28 << 24 >> 24 == 0;
+ if ($tobool29) {
+ label = 18;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $8 = HEAP32[$f >> 2] | 0;
+ $call33 = _get_int_msb_first($8, 2, $size_x) | 0;
+ $tobool35 = $call33 << 24 >> 24 == 0;
+ if ($tobool35) {
+ label = 18;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $9 = HEAP32[$f >> 2] | 0;
+ $call38 = _get_int_msb_first($9, 2, $size_y) | 0;
+ $tobool40 = $call38 << 24 >> 24 == 0;
+ if ($tobool40) {
+ label = 18;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $10 = HEAP32[$size_x >> 2] | 0;
+ $h42 = $us + 44 | 0;
+ HEAP32[$h42 >> 2] = $10;
+ $11 = HEAP32[$size_y >> 2] | 0;
+ $w43 = $us + 40 | 0;
+ HEAP32[$w43 >> 2] = $11;
+ label = 18;
+ break;
+ case 15:
+ $call47 = _get_int_msb_first($7, 2, $length) | 0;
+ $tobool48 = $call47 << 24 >> 24 == 0;
+ if ($tobool48) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $12 = HEAP32[$f >> 2] | 0;
+ $13 = HEAP32[$length >> 2] | 0;
+ $sub = $13 - 2 | 0;
+ $call52 = _fseek($12 | 0, $sub | 0, 1) | 0;
+ label = 17;
+ break;
+ case 17:
+ $14 = HEAP32[$f >> 2] | 0;
+ $call = _get_int_msb_first($14, 1, $marker) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 18;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 18:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _ps_size($us) {
+ $us = $us | 0;
+ var $line = 0, $lx = 0, $ly = 0, $ux = 0, $uy = 0, $dpi = 0, $f = 0, $0 = 0, $call = 0, $arraydecay = 0, $1 = 0, $call27 = 0, $tobool8 = 0, $call4 = 0, $tobool5 = 0, $call6 = 0, $cmp = 0, $2 = 0, $call2 = 0, $tobool = 0, $3 = 0, $x = 0, $4 = 0, $y = 0, $5 = 0, $6 = 0, $sub = 0, $w = 0, $7 = 0, $8 = 0, $sub11 = 0, $h = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1056 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $line = __stackBase__ | 0;
+ $lx = __stackBase__ + 1024 | 0;
+ $ly = __stackBase__ + 1032 | 0;
+ $ux = __stackBase__ + 1040 | 0;
+ $uy = __stackBase__ + 1048 | 0;
+ $dpi = $us + 48 | 0;
+ HEAP32[$dpi >> 2] = 72;
+ $f = $us + 20 | 0;
+ $0 = HEAP32[$f >> 2] | 0;
+ $call = _fseek($0 | 0, 0, 0) | 0;
+ $arraydecay = $line | 0;
+ $1 = HEAP32[$f >> 2] | 0;
+ $call27 = _fgets($arraydecay | 0, 1024, $1 | 0) | 0;
+ $tobool8 = ($call27 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call4 = _strstr($arraydecay | 0, 143176) | 0;
+ $tobool5 = ($call4 | 0) == 0;
+ if ($tobool5) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call6 = _sscanf($call4 | 0, 139544, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $lx, HEAP32[tempInt + 8 >> 2] = $ly, HEAP32[tempInt + 16 >> 2] = $ux, HEAP32[tempInt + 24 >> 2] = $uy, tempInt) | 0) | 0;
+ $cmp = ($call6 | 0) == 4;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP32[$f >> 2] | 0;
+ $call2 = _fgets($arraydecay | 0, 1024, $2 | 0) | 0;
+ $tobool = ($call2 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 6:
+ $3 = HEAP32[$lx >> 2] | 0;
+ $x = $us + 32 | 0;
+ HEAP32[$x >> 2] = $3;
+ $4 = HEAP32[$ly >> 2] | 0;
+ $y = $us + 36 | 0;
+ HEAP32[$y >> 2] = $4;
+ $5 = HEAP32[$ux >> 2] | 0;
+ $6 = HEAP32[$lx >> 2] | 0;
+ $sub = $5 - $6 | 0;
+ $w = $us + 40 | 0;
+ HEAP32[$w >> 2] = $sub;
+ $7 = HEAP32[$uy >> 2] | 0;
+ $8 = HEAP32[$ly >> 2] | 0;
+ $sub11 = $7 - $8 | 0;
+ $h = $us + 44 | 0;
+ HEAP32[$h >> 2] = $sub11;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_size($us) {
+ $us = $us | 0;
+ var $n = 0, $u = 0, $line = 0, $f = 0, $0 = 0, $arraydecay = 0, $call = 0, $sub = 0, $call1 = 0, $1 = 0, $call420 = 0, $cmp21 = 0, $arraydecay17 = 0, $w_0_ph = 0, $h_0_ph = 0, $wFlag_0_ph = 0, $hFlag_0_ph = 0, $2 = 0, $call4 = 0, $cmp = 0, $hFlag_025 = 0, $wFlag_024 = 0, $h_023 = 0, $w_022 = 0, $tobool = 0, $lnot = 0, $or_cond = 0, $call7 = 0, $cmp911 = 0, $hFlag_116 = 0, $wFlag_115 = 0, $token_014 = 0, $h_113 = 0, $w_112 = 0, $call11 = 0, $sub12 = 0, $arrayidx = 0, $3 = 0, $cmp13 = 0, $call18 = 0, $cmp19 = 0, $4 = 0.0, $call22 = 0, $tobool23 = 0, $w_2 = 0, $wFlag_2 = 0, $call27 = 0, $cmp28 = 0, $5 = 0.0, $call32 = 0, $tobool33 = 0, $h_2 = 0, $hFlag_2 = 0, $call37 = 0, $cmp9 = 0, $h_0_lcssa = 0, $w_0_lcssa = 0, $dpi = 0, $w39 = 0, $h40 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 224 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n = __stackBase__ | 0;
+ $u = __stackBase__ + 8 | 0;
+ $line = __stackBase__ + 24 | 0;
+ $f = $us + 20 | 0;
+ $0 = HEAP32[$f >> 2] | 0;
+ $arraydecay = $line | 0;
+ $call = _strlen($arraydecay | 0) | 0;
+ $sub = -$call | 0;
+ $call1 = _fseek($0 | 0, $sub | 0, 1) | 0;
+ $1 = HEAP32[$f >> 2] | 0;
+ $call420 = _fgets($arraydecay | 0, 200, $1 | 0) | 0;
+ $cmp21 = ($call420 | 0) == 0;
+ if ($cmp21) {
+ $w_0_lcssa = 0;
+ $h_0_lcssa = 0;
+ label = 13;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arraydecay17 = $u | 0;
+ $w_022 = 0;
+ $h_023 = 0;
+ $wFlag_024 = 0;
+ $hFlag_025 = 0;
+ label = 5;
+ break;
+ case 4:
+ $2 = HEAP32[$f >> 2] | 0;
+ $call4 = _fgets($arraydecay | 0, 200, $2 | 0) | 0;
+ $cmp = ($call4 | 0) == 0;
+ if ($cmp) {
+ $w_0_lcssa = $w_0_ph;
+ $h_0_lcssa = $h_0_ph;
+ label = 13;
+ break;
+ } else {
+ $w_022 = $w_0_ph;
+ $h_023 = $h_0_ph;
+ $wFlag_024 = $wFlag_0_ph;
+ $hFlag_025 = $hFlag_0_ph;
+ label = 5;
+ break;
+ }
+ case 5:
+ $tobool = $wFlag_024 << 24 >> 24 == 0;
+ $lnot = $hFlag_025 << 24 >> 24 == 0;
+ $or_cond = $tobool | $lnot;
+ if ($or_cond) {
+ label = 6;
+ break;
+ } else {
+ $w_0_lcssa = $w_022;
+ $h_0_lcssa = $h_023;
+ label = 13;
+ break;
+ }
+ case 6:
+ $call7 = _strtok($arraydecay | 0, 104472) | 0;
+ $cmp911 = ($call7 | 0) == 0;
+ if ($cmp911) {
+ $hFlag_0_ph = $hFlag_025;
+ $wFlag_0_ph = $wFlag_024;
+ $h_0_ph = $h_023;
+ $w_0_ph = $w_022;
+ label = 4;
+ break;
+ } else {
+ $w_112 = $w_022;
+ $h_113 = $h_023;
+ $token_014 = $call7;
+ $wFlag_115 = $wFlag_024;
+ $hFlag_116 = $hFlag_025;
+ label = 7;
+ break;
+ }
+ case 7:
+ $call11 = _strlen($token_014 | 0) | 0;
+ $sub12 = $call11 - 1 | 0;
+ $arrayidx = $token_014 + $sub12 | 0;
+ $3 = HEAP8[$arrayidx] | 0;
+ $cmp13 = $3 << 24 >> 24 == 62;
+ if ($cmp13) {
+ $hFlag_0_ph = $hFlag_116;
+ $wFlag_0_ph = $wFlag_115;
+ $h_0_ph = $h_113;
+ $w_0_ph = $w_112;
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call18 = _sscanf($token_014 | 0, 100216, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $n, HEAP32[tempInt + 8 >> 2] = $arraydecay17, tempInt) | 0) | 0;
+ $cmp19 = ($call18 | 0) == 2;
+ if ($cmp19) {
+ label = 9;
+ break;
+ } else {
+ $wFlag_2 = $wFlag_115;
+ $w_2 = $w_112;
+ label = 10;
+ break;
+ }
+ case 9:
+ $4 = +HEAPF64[$n >> 3];
+ $call22 = _svg_units_convert($4, $arraydecay17) | 0;
+ $tobool23 = $hFlag_116 << 24 >> 24 == 0;
+ if ($tobool23) {
+ $wFlag_2 = 1;
+ $w_2 = $call22;
+ label = 10;
+ break;
+ } else {
+ $hFlag_0_ph = $hFlag_116;
+ $wFlag_0_ph = 1;
+ $h_0_ph = $h_113;
+ $w_0_ph = $call22;
+ label = 4;
+ break;
+ }
+ case 10:
+ $call27 = _sscanf($token_014 | 0, 96080, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $n, HEAP32[tempInt + 8 >> 2] = $arraydecay17, tempInt) | 0) | 0;
+ $cmp28 = ($call27 | 0) == 2;
+ if ($cmp28) {
+ label = 11;
+ break;
+ } else {
+ $hFlag_2 = $hFlag_116;
+ $h_2 = $h_113;
+ label = 12;
+ break;
+ }
+ case 11:
+ $5 = +HEAPF64[$n >> 3];
+ $call32 = _svg_units_convert($5, $arraydecay17) | 0;
+ $tobool33 = $wFlag_2 << 24 >> 24 == 0;
+ if ($tobool33) {
+ $hFlag_2 = 1;
+ $h_2 = $call32;
+ label = 12;
+ break;
+ } else {
+ $hFlag_0_ph = 1;
+ $wFlag_0_ph = $wFlag_2;
+ $h_0_ph = $call32;
+ $w_0_ph = $w_2;
+ label = 4;
+ break;
+ }
+ case 12:
+ $call37 = _strtok(0, 104472) | 0;
+ $cmp9 = ($call37 | 0) == 0;
+ if ($cmp9) {
+ $hFlag_0_ph = $hFlag_2;
+ $wFlag_0_ph = $wFlag_2;
+ $h_0_ph = $h_2;
+ $w_0_ph = $w_2;
+ label = 4;
+ break;
+ } else {
+ $w_112 = $w_2;
+ $h_113 = $h_2;
+ $token_014 = $call37;
+ $wFlag_115 = $wFlag_2;
+ $hFlag_116 = $hFlag_2;
+ label = 7;
+ break;
+ }
+ case 13:
+ $dpi = $us + 48 | 0;
+ HEAP32[$dpi >> 2] = 72;
+ $w39 = $us + 40 | 0;
+ HEAP32[$w39 >> 2] = $w_0_lcssa;
+ $h40 = $us + 44 | 0;
+ HEAP32[$h40 >> 2] = $h_0_lcssa;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_units_convert($n, $u) {
+ $n = +$n;
+ $u = $u | 0;
+ var $call = 0, $cmp = 0, $mul = 0.0, $cmp1 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $call5 = 0, $cmp6 = 0, $mul9 = 0.0, $div = 0.0, $cmp10 = 0, $add15 = 0.0, $sub20 = 0.0, $add15_sink = 0.0, $conv16 = 0, $call25 = 0, $cmp26 = 0, $mul29 = 0.0, $div30 = 0.0, $cmp31 = 0, $add36 = 0.0, $sub41 = 0.0, $add36_sink = 0.0, $conv37 = 0, $call46 = 0, $cmp47 = 0, $call49 = 0, $cmp50 = 0, $cmp53 = 0, $add56 = 0.0, $sub59 = 0.0, $add56_sink = 0.0, $conv57 = 0, $call64 = 0, $cmp65 = 0, $mul68 = 0.0, $cmp69 = 0, $add73 = 0.0, $sub77 = 0.0, $add73_sink = 0.0, $conv74 = 0, $call82 = 0, $cmp83 = 0, $mul86 = 0.0, $cmp87 = 0, $add91 = 0.0, $sub95 = 0.0, $add91_sink = 0.0, $conv92 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _strcmp($u | 0, 92672) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $mul = $n * 72.0;
+ $cmp1 = $mul < 0.0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $add = $mul + .5;
+ $add_sink = $add;
+ label = 6;
+ break;
+ case 5:
+ $sub = $mul + -.5;
+ $add_sink = $sub;
+ label = 6;
+ break;
+ case 6:
+ $conv = ~~$add_sink;
+ $retval_0 = $conv;
+ label = 33;
+ break;
+ case 7:
+ $call5 = _strcmp($u | 0, 162792) | 0;
+ $cmp6 = ($call5 | 0) == 0;
+ if ($cmp6) {
+ label = 8;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 8:
+ $mul9 = $n * 72.0;
+ $div = $mul9 / 96.0;
+ $cmp10 = $div < 0.0;
+ if ($cmp10) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add15 = $div + .5;
+ $add15_sink = $add15;
+ label = 11;
+ break;
+ case 10:
+ $sub20 = $div + -.5;
+ $add15_sink = $sub20;
+ label = 11;
+ break;
+ case 11:
+ $conv16 = ~~$add15_sink;
+ $retval_0 = $conv16;
+ label = 33;
+ break;
+ case 12:
+ $call25 = _strcmp($u | 0, 159320) | 0;
+ $cmp26 = ($call25 | 0) == 0;
+ if ($cmp26) {
+ label = 13;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 13:
+ $mul29 = $n * 72.0;
+ $div30 = $mul29 / 6.0;
+ $cmp31 = $div30 < 0.0;
+ if ($cmp31) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $add36 = $div30 + .5;
+ $add36_sink = $add36;
+ label = 16;
+ break;
+ case 15:
+ $sub41 = $div30 + -.5;
+ $add36_sink = $sub41;
+ label = 16;
+ break;
+ case 16:
+ $conv37 = ~~$add36_sink;
+ $retval_0 = $conv37;
+ label = 33;
+ break;
+ case 17:
+ $call46 = _strcmp($u | 0, 155696) | 0;
+ $cmp47 = ($call46 | 0) == 0;
+ if ($cmp47) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $call49 = _strcmp($u | 0, 152336) | 0;
+ $cmp50 = ($call49 | 0) == 0;
+ if ($cmp50) {
+ label = 19;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 19:
+ $cmp53 = $n < 0.0;
+ if ($cmp53) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $add56 = $n + .5;
+ $add56_sink = $add56;
+ label = 22;
+ break;
+ case 21:
+ $sub59 = $n + -.5;
+ $add56_sink = $sub59;
+ label = 22;
+ break;
+ case 22:
+ $conv57 = ~~$add56_sink;
+ $retval_0 = $conv57;
+ label = 33;
+ break;
+ case 23:
+ $call64 = _strcmp($u | 0, 148968) | 0;
+ $cmp65 = ($call64 | 0) == 0;
+ if ($cmp65) {
+ label = 24;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 24:
+ $mul68 = $n * 28.346456664;
+ $cmp69 = $mul68 < 0.0;
+ if ($cmp69) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $add73 = $mul68 + .5;
+ $add73_sink = $add73;
+ label = 27;
+ break;
+ case 26:
+ $sub77 = $mul68 + -.5;
+ $add73_sink = $sub77;
+ label = 27;
+ break;
+ case 27:
+ $conv74 = ~~$add73_sink;
+ $retval_0 = $conv74;
+ label = 33;
+ break;
+ case 28:
+ $call82 = _strcmp($u | 0, 146168) | 0;
+ $cmp83 = ($call82 | 0) == 0;
+ if ($cmp83) {
+ label = 29;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 33;
+ break;
+ }
+ case 29:
+ $mul86 = $n * 2.8346456663999997;
+ $cmp87 = $mul86 < 0.0;
+ if ($cmp87) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $add91 = $mul86 + .5;
+ $add91_sink = $add91;
+ label = 32;
+ break;
+ case 31:
+ $sub95 = $mul86 + -.5;
+ $add91_sink = $sub95;
+ label = 32;
+ break;
+ case 32:
+ $conv92 = ~~$add91_sink;
+ $retval_0 = $conv92;
+ label = 33;
+ break;
+ case 33:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _get_int_msb_first($f, $sz, $val) {
+ $f = $f | 0;
+ $sz = $sz | 0;
+ $val = $val | 0;
+ var $cmp5 = 0, $i_06 = 0, $call = 0, $call1 = 0, $tobool = 0, $0 = 0, $shl = 0, $or = 0, $inc = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[$val >> 2] = 0;
+ $cmp5 = ($sz | 0) == 0;
+ if ($cmp5) {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ } else {
+ $i_06 = 0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _fgetc($f | 0) | 0;
+ $call1 = _feof($f | 0) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 4:
+ $0 = HEAP32[$val >> 2] | 0;
+ $shl = $0 << 8;
+ $or = $shl | $call;
+ HEAP32[$val >> 2] = $or;
+ $inc = $i_06 + 1 | 0;
+ $cmp = $inc >>> 0 < $sz >>> 0;
+ if ($cmp) {
+ $i_06 = $inc;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _get_int_lsb_first($f, $val) {
+ $f = $f | 0;
+ $val = $val | 0;
+ var $call = 0, $call1 = 0, $tobool = 0, $0 = 0, $or = 0, $call_1 = 0, $call1_1 = 0, $tobool_1 = 0, $retval_0 = 0, $shl_1 = 0, $1 = 0, $or_1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[$val >> 2] = 0;
+ $call = _fgetc($f | 0) | 0;
+ $call1 = _feof($f | 0) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$val >> 2] | 0;
+ $or = $0 | $call;
+ HEAP32[$val >> 2] = $or;
+ $call_1 = _fgetc($f | 0) | 0;
+ $call1_1 = _feof($f | 0) | 0;
+ $tobool_1 = ($call1_1 | 0) == 0;
+ if ($tobool_1) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ }
+ case 4:
+ return $retval_0 | 0;
+ case 5:
+ $shl_1 = $call_1 << 8;
+ $1 = HEAP32[$val >> 2] | 0;
+ $or_1 = $1 | $shl_1;
+ HEAP32[$val >> 2] = $or_1;
+ $retval_0 = 1;
+ label = 4;
+ break;
+ }
+ return 0;
+}
+function _usershape_close($dict, $p, $disc) {
+ $dict = $dict | 0;
+ $p = $p | 0;
+ $disc = $disc | 0;
+ var $0 = 0, $f = 0, $1 = 0, $2 = 0, $tobool = 0, $call = 0, $data = 0, $3 = 0, $4 = 0, $tobool2 = 0, $datafree = 0, $5 = 0, $6 = 0, $tobool3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $p;
+ $f = $p + 20 | 0;
+ $1 = $f;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _fclose($2 | 0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $data = $p + 52 | 0;
+ $3 = $data;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $tobool2 = ($4 | 0) == 0;
+ if ($tobool2) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $datafree = $p + 60 | 0;
+ $5 = $datafree;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $tobool3 = ($6 | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ FUNCTION_TABLE_vi[$6 & 1023]($0);
+ label = 7;
+ break;
+ case 7:
+ _free($p);
+ return;
+ }
+}
+function _gvloadimage($job, $us, $b, $filled, $target) {
+ $job = $job | 0;
+ $us = $us | 0;
+ $b = $b | 0;
+ $filled = $filled | 0;
+ $target = $target | 0;
+ var $type = 0, $arraydecay = 0, $stringtype = 0, $0 = 0, $call = 0, $strlen = 0, $endptr = 0, $1 = 0, $call4 = 0, $call6 = 0, $cmp = 0, $call8 = 0, $engine = 0, $2 = 0, $tobool = 0, $loadimage9 = 0, $3 = 0, $tobool10 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = __stackBase__ | 0;
+ $arraydecay = $type | 0;
+ $stringtype = $us + 28 | 0;
+ $0 = HEAP32[$stringtype >> 2] | 0;
+ $call = _strcpy($arraydecay | 0, $0 | 0) | 0;
+ $strlen = _strlen($arraydecay | 0) | 0;
+ $endptr = $type + $strlen | 0;
+ $1 = $endptr;
+ tempBigInt = 58;
+ HEAP8[$1] = tempBigInt & 255;
+ tempBigInt = tempBigInt >> 8;
+ HEAP8[$1 + 1 | 0] = tempBigInt & 255;
+ $call4 = _strcat($arraydecay | 0, $target | 0) | 0;
+ $call6 = _gvloadimage_select($job, $arraydecay) | 0;
+ $cmp = ($call6 | 0) == 999;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call8 = _agerr(0, 157312, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $arraydecay, tempInt) | 0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $engine = $job + 92 | 0;
+ $2 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $loadimage9 = $2 | 0;
+ $3 = HEAP32[$loadimage9 >> 2] | 0;
+ $tobool10 = ($3 | 0) == 0;
+ if ($tobool10) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ FUNCTION_TABLE_viiii[$3 & 1023]($job, $us, $b, $filled);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _gvloadimage_select($job, $str) {
+ $job = $job | 0;
+ $str = $str | 0;
+ var $gvc = 0, $0 = 0, $call = 0, $tobool = 0, $typeptr1 = 0, $1 = 0, $engine = 0, $2 = 0, $3 = 0, $engine2 = 0, $id = 0, $4 = 0, $id4 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $gvc = $job | 0;
+ $0 = HEAP32[$gvc >> 2] | 0;
+ $call = _gvplugin_load($0, 4, $str) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 999;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $typeptr1 = $call + 16 | 0;
+ $1 = HEAP32[$typeptr1 >> 2] | 0;
+ $engine = $1 + 12 | 0;
+ $2 = HEAP32[$engine >> 2] | 0;
+ $3 = $2;
+ $engine2 = $job + 92 | 0;
+ HEAP32[$engine2 >> 2] = $3;
+ $id = $1 | 0;
+ $4 = HEAP32[$id >> 2] | 0;
+ $id4 = $job + 96 | 0;
+ HEAP32[$id4 >> 2] = $4;
+ $retval_0 = 300;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvtextlayout_select($gvc) {
+ $gvc = $gvc | 0;
+ var $call = 0, $tobool = 0, $typeptr1 = 0, $0 = 0, $engine = 0, $1 = 0, $2 = 0, $engine2 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _gvplugin_load($gvc, 2, 141752) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 999;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $typeptr1 = $call + 16 | 0;
+ $0 = HEAP32[$typeptr1 >> 2] | 0;
+ $engine = $0 + 12 | 0;
+ $1 = HEAP32[$engine >> 2] | 0;
+ $2 = $1;
+ $engine2 = $gvc + 132 | 0;
+ HEAP32[$engine2 >> 2] = $2;
+ $retval_0 = 300;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _gvtextlayout($gvc, $para, $fontpath) {
+ $gvc = $gvc | 0;
+ $para = $para | 0;
+ $fontpath = $fontpath | 0;
+ var $engine = 0, $0 = 0, $tobool = 0, $textlayout1 = 0, $1 = 0, $tobool2 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $engine = $gvc + 132 | 0;
+ $0 = HEAP32[$engine >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $textlayout1 = $0 | 0;
+ $1 = HEAP32[$textlayout1 >> 2] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ if ($tobool2) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = FUNCTION_TABLE_iii[$1 & 1023]($para, $fontpath) | 0;
+ $retval_0 = $call;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _Proutespline($edges, $edgen, $input, $evs, $output) {
+ $edges = $edges | 0;
+ $edgen = $edgen | 0;
+ $input = $input | 0;
+ $evs = $evs | 0;
+ $output = $output | 0;
+ var $tmp = 0, $tmp4 = 0, $ps = 0, $0 = 0, $pn = 0, $1 = 0, $2 = 0, $3 = 0, $arrayidx2 = 0, $4 = 0, $5 = 0, $6 = 0, $inc = 0, $7 = 0, $arrayidx5 = 0, $8 = 0, $9 = 0, $call = 0, $cmp = 0, $10 = 0, $pn9 = 0, $11 = 0, $ps10 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $input;
+ $input = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$input >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$input + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $tmp4 = __stackBase__ + 16 | 0;
+ $ps = $input | 0;
+ $0 = HEAP32[$ps >> 2] | 0;
+ $pn = $input + 4 | 0;
+ $1 = HEAP32[$pn >> 2] | 0;
+ _normv($tmp, $evs);
+ $2 = $evs;
+ $3 = $tmp;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $arrayidx2 = $evs + 16 | 0;
+ _normv($tmp4, $arrayidx2);
+ $4 = $arrayidx2;
+ $5 = $tmp4;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ HEAP32[2292] = 0;
+ _growops(4);
+ $6 = HEAP32[2292] | 0;
+ $inc = $6 + 1 | 0;
+ HEAP32[2292] = $inc;
+ $7 = HEAP32[2286] | 0;
+ $arrayidx5 = $7 + ($6 << 4) | 0;
+ $8 = $arrayidx5;
+ $9 = $0;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $call = _reallyroutespline($edges, $edgen, $0, $1, $evs, $arrayidx2) | 0;
+ $cmp = ($call | 0) == -1;
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $10 = HEAP32[2292] | 0;
+ $pn9 = $output + 4 | 0;
+ HEAP32[$pn9 >> 2] = $10;
+ $11 = HEAP32[2286] | 0;
+ $ps10 = $output | 0;
+ HEAP32[$ps10 >> 2] = $11;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normv($agg_result, $v) {
+ $agg_result = $agg_result | 0;
+ $v = $v | 0;
+ var $x = 0, $0 = 0.0, $mul = 0.0, $y = 0, $1 = 0.0, $mul3 = 0.0, $add = 0.0, $cmp = 0, $call = 0.0, $div = 0.0, $2 = 0.0, $div6 = 0.0, $3 = 0, $4 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $v;
+ $v = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$v >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$v + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$v + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$v + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $v | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $mul = $0 * $0;
+ $y = $v + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $mul3 = $1 * $1;
+ $add = $mul + $mul3;
+ $cmp = $add > 1.0e-6;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = +Math_sqrt(+$add);
+ $div = $0 / $call;
+ HEAPF64[$x >> 3] = $div;
+ $2 = +HEAPF64[$y >> 3];
+ $div6 = $2 / $call;
+ HEAPF64[$y >> 3] = $div6;
+ label = 4;
+ break;
+ case 4:
+ $3 = $agg_result;
+ $4 = $v;
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _reallyroutespline($edges, $edgen, $inps, $inpn, $ev0, $ev1) {
+ $edges = $edges | 0;
+ $edgen = $edgen | 0;
+ $inps = $inps | 0;
+ $inpn = $inpn | 0;
+ $ev0 = $ev0 | 0;
+ $ev1 = $ev1 | 0;
+ var $p1 = 0, $p2 = 0, $p = 0, $v1 = 0, $v2 = 0, $splitv = 0, $splitv1 = 0, $splitv2 = 0, $tmp = 0, $tmp46 = 0, $agg_tmp = 0, $tmp58 = 0, $agg_tmp59 = 0, $tmp60 = 0, $agg_tmp105 = 0, $agg_tmp110 = 0, $agg_tmp115 = 0, $0 = 0, $cmp = 0, $1 = 0, $tobool = 0, $mul = 0, $call = 0, $2 = 0, $tobool2 = 0, $3 = 0, $mul4 = 0, $call5 = 0, $4 = 0, $tobool6 = 0, $5 = 0, $t11 = 0, $cmp1269 = 0, $cmp2267 = 0, $sub24 = 0, $6 = 0, $t26 = 0, $i_070 = 0, $sub = 0, $7 = 0, $t14 = 0, $8 = 0.0, $arrayidx15 = 0, $arrayidx17 = 0, $call18 = 0.0, $add = 0.0, $t20 = 0, $inc = 0, $cmp12 = 0, $cmp3364 = 0, $9 = 0, $10 = 0, $11 = 0, $i_168 = 0, $12 = 0.0, $t28 = 0, $13 = 0.0, $div = 0.0, $inc30 = 0, $cmp22 = 0, $14 = 0, $i_265 = 0, $arrayidx36 = 0, $t38 = 0, $15 = 0.0, $call39 = 0.0, $16 = 0, $17 = 0, $arrayidx42 = 0, $t44 = 0, $18 = 0.0, $call45 = 0.0, $19 = 0, $inc48 = 0, $cmp33 = 0, $20 = 0, $_lcssa = 0, $call54 = 0, $tobool55 = 0, $cp1_sroa_0_0__idx = 0, $cp1_sroa_0_0_copyload = 0.0, $cp1_sroa_1_8__idx34 = 0, $cp1_sroa_1_8_copyload = 0.0, $cp2_sroa_0_0__idx = 0, $cp2_sroa_0_0_copyload = 0.0, $cp2_sroa_1_8__idx33 = 0, $cp2_sroa_1_8_copyload = 0.0, $sub62 = 0, $cmp6360 = 0, $x = 0, $21 = 0.0, $x78 = 0, $22 = 0.0, $x81 = 0, $y = 0, $23 = 0.0, $y93 = 0, $24 = 0.0, $y96 = 0, $i_363 = 0, $maxi_062 = 0, $maxd_061 = 0.0, $25 = 0, $t66 = 0, $26 = 0.0, $call67 = 0.0, $mul68 = 0.0, $call69 = 0.0, $mul71 = 0.0, $add72 = 0.0, $call73 = 0.0, $mul75 = 0.0, $add76 = 0.0, $call77 = 0.0, $mul79 = 0.0, $add80 = 0.0, $mul83 = 0.0, $mul86 = 0.0, $add87 = 0.0, $mul90 = 0.0, $add91 = 0.0, $mul94 = 0.0, $add95 = 0.0, $arrayidx97 = 0, $call98 = 0.0, $cmp99 = 0, $maxd_1 = 0.0, $maxi_1 = 0, $inc103 = 0, $cmp63 = 0, $maxi_0_lcssa = 0, $arrayidx106 = 0, $sub107 = 0, $arrayidx108 = 0, $add111 = 0, $arrayidx112 = 0, $call118 = 0, $sub120 = 0, $call121 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 272 | 0;
+ tempParam = $ev0;
+ $ev0 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$ev0 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$ev0 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$ev0 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$ev0 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $ev1;
+ $ev1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$ev1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$ev1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$ev1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$ev1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p1 = __stackBase__ | 0;
+ $p2 = __stackBase__ + 16 | 0;
+ $p = __stackBase__ + 32 | 0;
+ $v1 = __stackBase__ + 48 | 0;
+ $v2 = __stackBase__ + 64 | 0;
+ $splitv = __stackBase__ + 80 | 0;
+ $splitv1 = __stackBase__ + 96 | 0;
+ $splitv2 = __stackBase__ + 112 | 0;
+ $tmp = __stackBase__ + 128 | 0;
+ $tmp46 = __stackBase__ + 144 | 0;
+ $agg_tmp = __stackBase__ + 160 | 0;
+ $tmp58 = __stackBase__ + 176 | 0;
+ $agg_tmp59 = __stackBase__ + 192 | 0;
+ $tmp60 = __stackBase__ + 208 | 0;
+ $agg_tmp105 = __stackBase__ + 224 | 0;
+ $agg_tmp110 = __stackBase__ + 240 | 0;
+ $agg_tmp115 = __stackBase__ + 256 | 0;
+ $0 = HEAP32[1162] | 0;
+ $cmp = ($0 | 0) < ($inpn | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[1160] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $mul = $inpn * 40 & -1;
+ $call = _malloc($mul) | 0;
+ $2 = $call;
+ HEAP32[1160] = $2;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ $retval_0 = -1;
+ label = 20;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $3 = $1;
+ $mul4 = $inpn * 40 & -1;
+ $call5 = _realloc($3, $mul4) | 0;
+ $4 = $call5;
+ HEAP32[1160] = $4;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ $retval_0 = -1;
+ label = 20;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ HEAP32[1162] = $inpn;
+ label = 7;
+ break;
+ case 7:
+ $5 = HEAP32[1160] | 0;
+ $t11 = $5 | 0;
+ HEAPF64[$t11 >> 3] = 0.0;
+ $cmp1269 = ($inpn | 0) > 1;
+ if ($cmp1269) {
+ $i_070 = 1;
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ $cmp2267 = ($inpn | 0) > 1;
+ if ($cmp2267) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $sub24 = $inpn - 1 | 0;
+ $6 = HEAP32[1160] | 0;
+ $t26 = $6 + ($sub24 * 40 & -1) | 0;
+ $i_168 = 1;
+ label = 13;
+ break;
+ case 10:
+ $sub = $i_070 - 1 | 0;
+ $7 = HEAP32[1160] | 0;
+ $t14 = $7 + ($sub * 40 & -1) | 0;
+ $8 = +HEAPF64[$t14 >> 3];
+ $arrayidx15 = $inps + ($i_070 << 4) | 0;
+ $arrayidx17 = $inps + ($sub << 4) | 0;
+ $call18 = +_dist($arrayidx15, $arrayidx17);
+ $add = $8 + $call18;
+ $t20 = $7 + ($i_070 * 40 & -1) | 0;
+ HEAPF64[$t20 >> 3] = $add;
+ $inc = $i_070 + 1 | 0;
+ $cmp12 = ($inc | 0) < ($inpn | 0);
+ if ($cmp12) {
+ $i_070 = $inc;
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 11:
+ $cmp3364 = ($inpn | 0) > 0;
+ $9 = HEAP32[1160] | 0;
+ if ($cmp3364) {
+ label = 12;
+ break;
+ } else {
+ $_lcssa = $9;
+ label = 15;
+ break;
+ }
+ case 12:
+ $10 = $tmp;
+ $11 = $tmp46;
+ $i_265 = 0;
+ $14 = $9;
+ label = 14;
+ break;
+ case 13:
+ $12 = +HEAPF64[$t26 >> 3];
+ $t28 = $6 + ($i_168 * 40 & -1) | 0;
+ $13 = +HEAPF64[$t28 >> 3];
+ $div = $13 / $12;
+ HEAPF64[$t28 >> 3] = $div;
+ $inc30 = $i_168 + 1 | 0;
+ $cmp22 = ($inc30 | 0) < ($inpn | 0);
+ if ($cmp22) {
+ $i_168 = $inc30;
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 14:
+ $arrayidx36 = $14 + ($i_265 * 40 & -1) + 8 | 0;
+ $t38 = $14 + ($i_265 * 40 & -1) | 0;
+ $15 = +HEAPF64[$t38 >> 3];
+ $call39 = +_B1($15);
+ _scale2744($tmp, $ev0, $call39);
+ $16 = $arrayidx36;
+ HEAP32[$16 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$16 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$16 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$16 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $17 = HEAP32[1160] | 0;
+ $arrayidx42 = $17 + ($i_265 * 40 & -1) + 24 | 0;
+ $t44 = $17 + ($i_265 * 40 & -1) | 0;
+ $18 = +HEAPF64[$t44 >> 3];
+ $call45 = +_B2($18);
+ _scale2744($tmp46, $ev1, $call45);
+ $19 = $arrayidx42;
+ HEAP32[$19 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$19 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$19 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$19 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ $inc48 = $i_265 + 1 | 0;
+ $cmp33 = ($inc48 | 0) < ($inpn | 0);
+ $20 = HEAP32[1160] | 0;
+ if ($cmp33) {
+ $i_265 = $inc48;
+ $14 = $20;
+ label = 14;
+ break;
+ } else {
+ $_lcssa = $20;
+ label = 15;
+ break;
+ }
+ case 15:
+ _mkspline($inps, $inpn, $_lcssa, $ev0, $ev1, $p1, $v1, $p2, $v2);
+ $call54 = _splinefits($edges, $edgen, $p1, $v1, $p2, $v2, $inps, $inpn) | 0;
+ $tobool55 = ($call54 | 0) == 0;
+ if ($tobool55) {
+ label = 16;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 20;
+ break;
+ }
+ case 16:
+ _scale2744($agg_tmp, $v1, .3333333333333333);
+ _add($tmp58, $p1, $agg_tmp);
+ $cp1_sroa_0_0__idx = $tmp58 | 0;
+ $cp1_sroa_0_0_copyload = +HEAPF64[$cp1_sroa_0_0__idx >> 3];
+ $cp1_sroa_1_8__idx34 = $tmp58 + 8 | 0;
+ $cp1_sroa_1_8_copyload = +HEAPF64[$cp1_sroa_1_8__idx34 >> 3];
+ _scale2744($agg_tmp59, $v2, .3333333333333333);
+ _sub($tmp60, $p2, $agg_tmp59);
+ $cp2_sroa_0_0__idx = $tmp60 | 0;
+ $cp2_sroa_0_0_copyload = +HEAPF64[$cp2_sroa_0_0__idx >> 3];
+ $cp2_sroa_1_8__idx33 = $tmp60 + 8 | 0;
+ $cp2_sroa_1_8_copyload = +HEAPF64[$cp2_sroa_1_8__idx33 >> 3];
+ $sub62 = $inpn - 1 | 0;
+ $cmp6360 = ($sub62 | 0) > 1;
+ if ($cmp6360) {
+ label = 17;
+ break;
+ } else {
+ $maxi_0_lcssa = -1;
+ label = 19;
+ break;
+ }
+ case 17:
+ $x = $p1 | 0;
+ $21 = +HEAPF64[$x >> 3];
+ $x78 = $p2 | 0;
+ $22 = +HEAPF64[$x78 >> 3];
+ $x81 = $p | 0;
+ $y = $p1 + 8 | 0;
+ $23 = +HEAPF64[$y >> 3];
+ $y93 = $p2 + 8 | 0;
+ $24 = +HEAPF64[$y93 >> 3];
+ $y96 = $p + 8 | 0;
+ $maxd_061 = -1.0;
+ $maxi_062 = -1;
+ $i_363 = 1;
+ label = 18;
+ break;
+ case 18:
+ $25 = HEAP32[1160] | 0;
+ $t66 = $25 + ($i_363 * 40 & -1) | 0;
+ $26 = +HEAPF64[$t66 >> 3];
+ $call67 = +_B0($26);
+ $mul68 = $call67 * $21;
+ $call69 = +_B1($26);
+ $mul71 = $cp1_sroa_0_0_copyload * $call69;
+ $add72 = $mul68 + $mul71;
+ $call73 = +_B2($26);
+ $mul75 = $cp2_sroa_0_0_copyload * $call73;
+ $add76 = $add72 + $mul75;
+ $call77 = +_B3($26);
+ $mul79 = $call77 * $22;
+ $add80 = $add76 + $mul79;
+ HEAPF64[$x81 >> 3] = $add80;
+ $mul83 = $call67 * $23;
+ $mul86 = $cp1_sroa_1_8_copyload * $call69;
+ $add87 = $mul86 + $mul83;
+ $mul90 = $cp2_sroa_1_8_copyload * $call73;
+ $add91 = $mul90 + $add87;
+ $mul94 = $call77 * $24;
+ $add95 = $mul94 + $add91;
+ HEAPF64[$y96 >> 3] = $add95;
+ $arrayidx97 = $inps + ($i_363 << 4) | 0;
+ $call98 = +_dist($p, $arrayidx97);
+ $cmp99 = $call98 > $maxd_061;
+ $maxd_1 = $cmp99 ? $call98 : $maxd_061;
+ $maxi_1 = $cmp99 ? $i_363 : $maxi_062;
+ $inc103 = $i_363 + 1 | 0;
+ $cmp63 = ($inc103 | 0) < ($sub62 | 0);
+ if ($cmp63) {
+ $maxd_061 = $maxd_1;
+ $maxi_062 = $maxi_1;
+ $i_363 = $inc103;
+ label = 18;
+ break;
+ } else {
+ $maxi_0_lcssa = $maxi_1;
+ label = 19;
+ break;
+ }
+ case 19:
+ $arrayidx106 = $inps + ($maxi_0_lcssa << 4) | 0;
+ $sub107 = $maxi_0_lcssa - 1 | 0;
+ $arrayidx108 = $inps + ($sub107 << 4) | 0;
+ _sub($agg_tmp105, $arrayidx106, $arrayidx108);
+ _normv($splitv1, $agg_tmp105);
+ $add111 = $maxi_0_lcssa + 1 | 0;
+ $arrayidx112 = $inps + ($add111 << 4) | 0;
+ _sub($agg_tmp110, $arrayidx112, $arrayidx106);
+ _normv($splitv2, $agg_tmp110);
+ _add($agg_tmp115, $splitv1, $splitv2);
+ _normv($splitv, $agg_tmp115);
+ $call118 = _reallyroutespline($edges, $edgen, $inps, $add111, $ev0, $splitv) | 0;
+ $sub120 = $inpn - $maxi_0_lcssa | 0;
+ $call121 = _reallyroutespline($edges, $edgen, $arrayidx106, $sub120, $splitv, $ev1) | 0;
+ $retval_0 = 0;
+ label = 20;
+ break;
+ case 20:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dist($p1, $p2) {
+ $p1 = $p1 | 0;
+ $p2 = $p2 | 0;
+ var $sub = 0.0, $sub3 = 0.0, $call = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p1;
+ $p1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $p2;
+ $p2 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p2 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p2 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p2 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p2 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $sub = +HEAPF64[$p2 >> 3] - +HEAPF64[$p1 >> 3];
+ $sub3 = +HEAPF64[$p2 + 8 >> 3] - +HEAPF64[$p1 + 8 >> 3];
+ $call = +Math_sqrt(+($sub * $sub + $sub3 * $sub3));
+ STACKTOP = __stackBase__;
+ return +$call;
+}
+function _scale2744($agg_result, $p, $c) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $c = +$c;
+ var $x = 0, $y = 0, $2 = 0, $3 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $x = $p | 0;
+ HEAPF64[$x >> 3] = +HEAPF64[$x >> 3] * $c;
+ $y = $p + 8 | 0;
+ HEAPF64[$y >> 3] = +HEAPF64[$y >> 3] * $c;
+ $2 = $agg_result;
+ $3 = $p;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _growops($newopn) {
+ $newopn = $newopn | 0;
+ var $0 = 0, $cmp = 0, $1 = 0, $tobool = 0, $mul = 0, $call = 0, $2 = 0, $tobool2 = 0, $3 = 0, $call4 = 0, $4 = 0, $mul6 = 0, $call7 = 0, $5 = 0, $tobool8 = 0, $6 = 0, $call10 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[2290] | 0;
+ $cmp = ($0 | 0) < ($newopn | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[2286] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $mul = $newopn << 4;
+ $call = _malloc($mul) | 0;
+ $2 = $call;
+ HEAP32[2286] = $2;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $3 = HEAP32[_stderr >> 2] | 0;
+ $call4 = _fprintf($3 | 0, 126624, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 151816, HEAP32[tempInt + 8 >> 2] = 519, HEAP32[tempInt + 16 >> 2] = 123280, tempInt) | 0) | 0;
+ _abort();
+ case 6:
+ $4 = $1;
+ $mul6 = $newopn << 4;
+ $call7 = _realloc($4, $mul6) | 0;
+ $5 = $call7;
+ HEAP32[2286] = $5;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $6 = HEAP32[_stderr >> 2] | 0;
+ $call10 = _fprintf($6 | 0, 126624, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 151816, HEAP32[tempInt + 8 >> 2] = 525, HEAP32[tempInt + 16 >> 2] = 117312, tempInt) | 0) | 0;
+ _abort();
+ case 8:
+ HEAP32[2290] = $newopn;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _B0($t) {
+ $t = +$t;
+ var $sub = 0.0;
+ $sub = 1.0 - $t;
+ return +($sub * $sub * $sub);
+}
+function _B3($t) {
+ $t = +$t;
+ return +($t * $t * $t);
+}
+function _B01($t) {
+ $t = +$t;
+ var $sub = 0.0;
+ $sub = 1.0 - $t;
+ return +($sub * $sub * ($sub + $t * 3.0));
+}
+function _B23($t) {
+ $t = +$t;
+ return +($t * $t * ((1.0 - $t) * 3.0 + $t));
+}
+function _points2coeff($v0, $v1, $v2, $v3, $coeff) {
+ $v0 = +$v0;
+ $v1 = +$v1;
+ $v2 = +$v2;
+ $v3 = +$v3;
+ $coeff = $coeff | 0;
+ var $mul1 = 0.0;
+ $mul1 = $v2 * 3.0;
+ HEAPF64[$coeff + 24 >> 3] = $v1 * 3.0 + $v3 - ($mul1 + $v0);
+ HEAPF64[$coeff + 16 >> 3] = $v0 * 3.0 + $mul1 - $v1 * 6.0;
+ HEAPF64[$coeff + 8 >> 3] = ($v1 - $v0) * 3.0;
+ HEAPF64[$coeff >> 3] = $v0;
+ return;
+}
+function _addroot($root, $roots, $rootnp) {
+ $root = +$root;
+ $roots = $roots | 0;
+ $rootnp = $rootnp | 0;
+ var $cmp = 0, $cmp1 = 0, $or_cond = 0, $0 = 0, $arrayidx = 0, $1 = 0, $inc = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = $root >= 0.0;
+ $cmp1 = $root <= 1.0;
+ $or_cond = $cmp & $cmp1;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[$rootnp >> 2] | 0;
+ $arrayidx = $roots + ($0 << 3) | 0;
+ HEAPF64[$arrayidx >> 3] = $root;
+ $1 = HEAP32[$rootnp >> 2] | 0;
+ $inc = $1 + 1 | 0;
+ HEAP32[$rootnp >> 2] = $inc;
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _dot($p1, $p2) {
+ $p1 = $p1 | 0;
+ $p2 = $p2 | 0;
+ var tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p1;
+ $p1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $p2;
+ $p2 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p2 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p2 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p2 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p2 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return +(+HEAPF64[$p1 >> 3] * +HEAPF64[$p2 >> 3] + +HEAPF64[$p1 + 8 >> 3] * +HEAPF64[$p2 + 8 >> 3]);
+}
+function _mkspline($inps, $inpn, $tnas, $ev0, $ev1, $sp0, $sv0, $sp1, $sv1) {
+ $inps = $inps | 0;
+ $inpn = $inpn | 0;
+ $tnas = $tnas | 0;
+ $ev0 = $ev0 | 0;
+ $ev1 = $ev1 | 0;
+ $sp0 = $sp0 | 0;
+ $sv0 = $sv0 | 0;
+ $sp1 = $sp1 | 0;
+ $sv1 = $sv1 | 0;
+ var $tmp = 0, $agg_tmp = 0, $agg_tmp51 = 0, $agg_tmp55 = 0, $tmp123 = 0, $tmp126 = 0, $cmp2 = 0, $sub = 0, $arrayidx56 = 0, $i_08 = 0, $c_sroa_3_07 = 0.0, $c_sroa_1_06 = 0.0, $c_sroa_0_05 = 0.0, $x_sroa_0_04 = 0.0, $x_sroa_1_03 = 0.0, $arrayidx20 = 0, $call = 0.0, $add = 0.0, $arrayidx31 = 0, $call32 = 0.0, $add35 = 0.0, $call46 = 0.0, $add49 = 0.0, $arrayidx50 = 0, $t = 0, $0 = 0.0, $call54 = 0.0, $1 = 0.0, $call59 = 0.0, $call64 = 0.0, $add66 = 0.0, $call70 = 0.0, $add72 = 0.0, $inc = 0, $cmp = 0, $c_sroa_3_0_lcssa = 0.0, $c_sroa_1_0_lcssa = 0.0, $c_sroa_0_0_lcssa = 0.0, $x_sroa_0_0_lcssa = 0.0, $x_sroa_1_0_lcssa = 0.0, $mul = 0.0, $mul81 = 0.0, $sub82 = 0.0, $mul86 = 0.0, $mul90 = 0.0, $sub91 = 0.0, $mul95 = 0.0, $mul99 = 0.0, $sub100 = 0.0, $cmp101 = 0, $sub102 = 0.0, $cond = 0.0, $cmp103 = 0, $div = 0.0, $div104 = 0.0, $scale0_0 = 0.0, $scale3_0 = 0.0, $sub108 = 0.0, $cond110 = 0.0, $cmp111 = 0, $cmp112 = 0, $or_cond = 0, $cmp114 = 0, $or_cond1 = 0, $sub117 = 0, $arrayidx118 = 0, $call119 = 0.0, $div120 = 0.0, $scale0_1 = 0.0, $scale3_1 = 0.0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $sub124 = 0, $arrayidx125 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 96 | 0;
+ tempParam = $ev0;
+ $ev0 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$ev0 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$ev0 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$ev0 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$ev0 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $ev1;
+ $ev1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$ev1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$ev1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$ev1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$ev1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tmp = __stackBase__ | 0;
+ $agg_tmp = __stackBase__ + 16 | 0;
+ $agg_tmp51 = __stackBase__ + 32 | 0;
+ $agg_tmp55 = __stackBase__ + 48 | 0;
+ $tmp123 = __stackBase__ + 64 | 0;
+ $tmp126 = __stackBase__ + 80 | 0;
+ $cmp2 = ($inpn | 0) > 0;
+ if ($cmp2) {
+ label = 3;
+ break;
+ } else {
+ $x_sroa_1_0_lcssa = 0.0;
+ $x_sroa_0_0_lcssa = 0.0;
+ $c_sroa_0_0_lcssa = 0.0;
+ $c_sroa_1_0_lcssa = 0.0;
+ $c_sroa_3_0_lcssa = 0.0;
+ label = 5;
+ break;
+ }
+ case 3:
+ $sub = $inpn - 1 | 0;
+ $arrayidx56 = $inps + ($sub << 4) | 0;
+ $x_sroa_1_03 = 0.0;
+ $x_sroa_0_04 = 0.0;
+ $c_sroa_0_05 = 0.0;
+ $c_sroa_1_06 = 0.0;
+ $c_sroa_3_07 = 0.0;
+ $i_08 = 0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx20 = $tnas + ($i_08 * 40 & -1) + 8 | 0;
+ $call = +_dot($arrayidx20, $arrayidx20);
+ $add = $c_sroa_0_05 + $call;
+ $arrayidx31 = $tnas + ($i_08 * 40 & -1) + 24 | 0;
+ $call32 = +_dot($arrayidx20, $arrayidx31);
+ $add35 = $c_sroa_1_06 + $call32;
+ $call46 = +_dot($arrayidx31, $arrayidx31);
+ $add49 = $c_sroa_3_07 + $call46;
+ $arrayidx50 = $inps + ($i_08 << 4) | 0;
+ $t = $tnas + ($i_08 * 40 & -1) | 0;
+ $0 = +HEAPF64[$t >> 3];
+ $call54 = +_B01($0);
+ _scale2744($agg_tmp51, $inps, $call54);
+ $1 = +HEAPF64[$t >> 3];
+ $call59 = +_B23($1);
+ _scale2744($agg_tmp55, $arrayidx56, $call59);
+ _add($agg_tmp, $agg_tmp51, $agg_tmp55);
+ _sub($tmp, $arrayidx50, $agg_tmp);
+ $call64 = +_dot($arrayidx20, $tmp);
+ $add66 = $x_sroa_0_04 + $call64;
+ $call70 = +_dot($arrayidx31, $tmp);
+ $add72 = $x_sroa_1_03 + $call70;
+ $inc = $i_08 + 1 | 0;
+ $cmp = ($inc | 0) < ($inpn | 0);
+ if ($cmp) {
+ $x_sroa_1_03 = $add72;
+ $x_sroa_0_04 = $add66;
+ $c_sroa_0_05 = $add;
+ $c_sroa_1_06 = $add35;
+ $c_sroa_3_07 = $add49;
+ $i_08 = $inc;
+ label = 4;
+ break;
+ } else {
+ $x_sroa_1_0_lcssa = $add72;
+ $x_sroa_0_0_lcssa = $add66;
+ $c_sroa_0_0_lcssa = $add;
+ $c_sroa_1_0_lcssa = $add35;
+ $c_sroa_3_0_lcssa = $add49;
+ label = 5;
+ break;
+ }
+ case 5:
+ $mul = $c_sroa_0_0_lcssa * $c_sroa_3_0_lcssa;
+ $mul81 = $c_sroa_1_0_lcssa * $c_sroa_1_0_lcssa;
+ $sub82 = $mul - $mul81;
+ $mul86 = $x_sroa_1_0_lcssa * $c_sroa_0_0_lcssa;
+ $mul90 = $x_sroa_0_0_lcssa * $c_sroa_1_0_lcssa;
+ $sub91 = $mul86 - $mul90;
+ $mul95 = $x_sroa_0_0_lcssa * $c_sroa_3_0_lcssa;
+ $mul99 = $x_sroa_1_0_lcssa * $c_sroa_1_0_lcssa;
+ $sub100 = $mul95 - $mul99;
+ $cmp101 = $sub82 >= 0.0;
+ if ($cmp101) {
+ $cond = $sub82;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $sub102 = -0.0 - $sub82;
+ $cond = $sub102;
+ label = 7;
+ break;
+ case 7:
+ $cmp103 = $cond < 1.0e-6;
+ if ($cmp103) {
+ $scale3_0 = 0.0;
+ $scale0_0 = 0.0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $div = $sub100 / $sub82;
+ $div104 = $sub91 / $sub82;
+ $scale3_0 = $div104;
+ $scale0_0 = $div;
+ label = 9;
+ break;
+ case 9:
+ if ($cmp101) {
+ $cond110 = $sub82;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $sub108 = -0.0 - $sub82;
+ $cond110 = $sub108;
+ label = 11;
+ break;
+ case 11:
+ $cmp111 = $cond110 >= 1.0e-6;
+ $cmp112 = $scale0_0 > 0.0;
+ $or_cond = $cmp111 & $cmp112;
+ $cmp114 = $scale3_0 > 0.0;
+ $or_cond1 = $or_cond & $cmp114;
+ if ($or_cond1) {
+ $scale3_1 = $scale3_0;
+ $scale0_1 = $scale0_0;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $sub117 = $inpn - 1 | 0;
+ $arrayidx118 = $inps + ($sub117 << 4) | 0;
+ $call119 = +_dist($inps, $arrayidx118);
+ $div120 = $call119 / 3.0;
+ $scale3_1 = $div120;
+ $scale0_1 = $div120;
+ label = 13;
+ break;
+ case 13:
+ $2 = $sp0;
+ $3 = $inps;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ _scale2744($tmp123, $ev0, $scale0_1);
+ $4 = $sv0;
+ $5 = $tmp123;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $sub124 = $inpn - 1 | 0;
+ $arrayidx125 = $inps + ($sub124 << 4) | 0;
+ $6 = $sp1;
+ $7 = $arrayidx125;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ _scale2744($tmp126, $ev1, $scale3_1);
+ $8 = $sv1;
+ $9 = $tmp126;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _splinefits($edges, $edgen, $pa, $va, $pb, $vb, $inps, $inpn) {
+ $edges = $edges | 0;
+ $edgen = $edgen | 0;
+ $pa = $pa | 0;
+ $va = $va | 0;
+ $pb = $pb | 0;
+ $vb = $vb | 0;
+ $inps = $inps | 0;
+ $inpn = $inpn | 0;
+ var $sps = 0, $cmp = 0, $x = 0, $0 = 0.0, $arrayidx = 0, $x1 = 0, $y = 0, $1 = 0.0, $y3 = 0, $x5 = 0, $2 = 0.0, $x7 = 0, $y9 = 0, $3 = 0.0, $y14 = 0, $x15 = 0, $4 = 0.0, $x16 = 0, $5 = 0.0, $x20 = 0, $y21 = 0, $6 = 0.0, $y22 = 0, $7 = 0.0, $y27 = 0, $8 = 0.0, $x30 = 0, $y33 = 0, $a_0 = 0.0, $b_0 = 0.0, $first_0 = 0, $mul = 0.0, $div = 0.0, $add = 0.0, $mul10 = 0.0, $div11 = 0.0, $add12 = 0.0, $mul17 = 0.0, $div18 = 0.0, $sub = 0.0, $mul23 = 0.0, $div24 = 0.0, $sub25 = 0.0, $call = 0.0, $call34 = 0.0, $sub35 = 0.0, $cmp36 = 0, $call38 = 0, $tobool39 = 0, $9 = 0, $add41 = 0, $10 = 0, $opl_promoted20 = 0, $x45 = 0, $11 = 0.0, $x47 = 0, $y49 = 0, $12 = 0.0, $inc = 0, $y51 = 0, $x45_1 = 0, $13 = 0.0, $x47_1 = 0, $y49_1 = 0, $14 = 0.0, $inc_1 = 0, $y51_1 = 0, $x45_2 = 0, $15 = 0.0, $x47_2 = 0, $y49_2 = 0, $16 = 0.0, $y51_2 = 0, $17 = 0, $cmp54 = 0, $cmp56 = 0, $or_cond = 0, $18 = 0, $add60 = 0, $19 = 0, $opl_promoted = 0, $x65 = 0, $20 = 0.0, $x67 = 0, $y69 = 0, $21 = 0.0, $inc70 = 0, $y72 = 0, $x65_1 = 0, $22 = 0.0, $x67_1 = 0, $y69_1 = 0, $23 = 0.0, $inc70_1 = 0, $y72_1 = 0, $x65_2 = 0, $24 = 0.0, $x67_2 = 0, $y69_2 = 0, $25 = 0.0, $y72_2 = 0, $26 = 0, $cmp78 = 0, $div80 = 0.0, $div81 = 0.0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ tempParam = $pa;
+ $pa = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pa >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pa + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pa + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pa + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $va;
+ $va = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$va >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$va + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$va + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$va + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $pb;
+ $pb = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pb >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pb + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pb + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pb + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $vb;
+ $vb = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$vb >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$vb + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$vb + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$vb + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sps = __stackBase__ | 0;
+ $cmp = ($inpn | 0) == 2;
+ $x = $pa | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $arrayidx = $sps | 0;
+ $x1 = $sps | 0;
+ $y = $pa + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $y3 = $sps + 8 | 0;
+ $x5 = $va | 0;
+ $2 = +HEAPF64[$x5 >> 3];
+ $x7 = $sps + 16 | 0;
+ $y9 = $va + 8 | 0;
+ $3 = +HEAPF64[$y9 >> 3];
+ $y14 = $sps + 24 | 0;
+ $x15 = $pb | 0;
+ $4 = +HEAPF64[$x15 >> 3];
+ $x16 = $vb | 0;
+ $5 = +HEAPF64[$x16 >> 3];
+ $x20 = $sps + 32 | 0;
+ $y21 = $pb + 8 | 0;
+ $6 = +HEAPF64[$y21 >> 3];
+ $y22 = $vb + 8 | 0;
+ $7 = +HEAPF64[$y22 >> 3];
+ $y27 = $sps + 40 | 0;
+ $8 = +HEAPF64[$x15 >> 3];
+ $x30 = $sps + 48 | 0;
+ $y33 = $sps + 56 | 0;
+ $first_0 = 1;
+ $b_0 = 4.0;
+ $a_0 = 4.0;
+ label = 3;
+ break;
+ case 3:
+ HEAPF64[$x1 >> 3] = $0;
+ HEAPF64[$y3 >> 3] = $1;
+ $mul = $a_0 * $2;
+ $div = $mul / 3.0;
+ $add = $0 + $div;
+ HEAPF64[$x7 >> 3] = $add;
+ $mul10 = $a_0 * $3;
+ $div11 = $mul10 / 3.0;
+ $add12 = $1 + $div11;
+ HEAPF64[$y14 >> 3] = $add12;
+ $mul17 = $b_0 * $5;
+ $div18 = $mul17 / 3.0;
+ $sub = $4 - $div18;
+ HEAPF64[$x20 >> 3] = $sub;
+ $mul23 = $b_0 * $7;
+ $div24 = $mul23 / 3.0;
+ $sub25 = $6 - $div24;
+ HEAPF64[$y27 >> 3] = $sub25;
+ HEAPF64[$x30 >> 3] = $8;
+ HEAPF64[$y33 >> 3] = $6;
+ if ($first_0) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call = +_dist_n($arrayidx, 4);
+ $call34 = +_dist_n($inps, $inpn);
+ $sub35 = $call34 + -.001;
+ $cmp36 = $call < $sub35;
+ if ($cmp36) {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call38 = _splineisinside($edges, $edgen, $arrayidx) | 0;
+ $tobool39 = ($call38 | 0) == 0;
+ if ($tobool39) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $9 = HEAP32[2292] | 0;
+ $add41 = $9 + 4 | 0;
+ _growops($add41);
+ $10 = HEAP32[2286] | 0;
+ $opl_promoted20 = HEAP32[2292] | 0;
+ $x45 = $sps + 16 | 0;
+ $11 = +HEAPF64[$x45 >> 3];
+ $x47 = $10 + ($opl_promoted20 << 4) | 0;
+ HEAPF64[$x47 >> 3] = $11;
+ $y49 = $sps + 24 | 0;
+ $12 = +HEAPF64[$y49 >> 3];
+ $inc = $opl_promoted20 + 1 | 0;
+ $y51 = $10 + ($opl_promoted20 << 4) + 8 | 0;
+ HEAPF64[$y51 >> 3] = $12;
+ $x45_1 = $sps + 32 | 0;
+ $13 = +HEAPF64[$x45_1 >> 3];
+ $x47_1 = $10 + ($inc << 4) | 0;
+ HEAPF64[$x47_1 >> 3] = $13;
+ $y49_1 = $sps + 40 | 0;
+ $14 = +HEAPF64[$y49_1 >> 3];
+ $inc_1 = $opl_promoted20 + 2 | 0;
+ $y51_1 = $10 + ($inc << 4) + 8 | 0;
+ HEAPF64[$y51_1 >> 3] = $14;
+ $x45_2 = $sps + 48 | 0;
+ $15 = +HEAPF64[$x45_2 >> 3];
+ $x47_2 = $10 + ($inc_1 << 4) | 0;
+ HEAPF64[$x47_2 >> 3] = $15;
+ $y49_2 = $sps + 56 | 0;
+ $16 = +HEAPF64[$y49_2 >> 3];
+ $y51_2 = $10 + ($inc_1 << 4) + 8 | 0;
+ HEAPF64[$y51_2 >> 3] = $16;
+ $17 = $opl_promoted20 + 3 | 0;
+ HEAP32[2292] = $17;
+ $retval_0 = 1;
+ label = 12;
+ break;
+ case 7:
+ $cmp54 = $a_0 == 0.0;
+ $cmp56 = $b_0 == 0.0;
+ $or_cond = $cmp54 & $cmp56;
+ if ($or_cond) {
+ label = 8;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 8:
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ }
+ case 9:
+ $18 = HEAP32[2292] | 0;
+ $add60 = $18 + 4 | 0;
+ _growops($add60);
+ $19 = HEAP32[2286] | 0;
+ $opl_promoted = HEAP32[2292] | 0;
+ $x65 = $sps + 16 | 0;
+ $20 = +HEAPF64[$x65 >> 3];
+ $x67 = $19 + ($opl_promoted << 4) | 0;
+ HEAPF64[$x67 >> 3] = $20;
+ $y69 = $sps + 24 | 0;
+ $21 = +HEAPF64[$y69 >> 3];
+ $inc70 = $opl_promoted + 1 | 0;
+ $y72 = $19 + ($opl_promoted << 4) + 8 | 0;
+ HEAPF64[$y72 >> 3] = $21;
+ $x65_1 = $sps + 32 | 0;
+ $22 = +HEAPF64[$x65_1 >> 3];
+ $x67_1 = $19 + ($inc70 << 4) | 0;
+ HEAPF64[$x67_1 >> 3] = $22;
+ $y69_1 = $sps + 40 | 0;
+ $23 = +HEAPF64[$y69_1 >> 3];
+ $inc70_1 = $opl_promoted + 2 | 0;
+ $y72_1 = $19 + ($inc70 << 4) + 8 | 0;
+ HEAPF64[$y72_1 >> 3] = $23;
+ $x65_2 = $sps + 48 | 0;
+ $24 = +HEAPF64[$x65_2 >> 3];
+ $x67_2 = $19 + ($inc70_1 << 4) | 0;
+ HEAPF64[$x67_2 >> 3] = $24;
+ $y69_2 = $sps + 56 | 0;
+ $25 = +HEAPF64[$y69_2 >> 3];
+ $y72_2 = $19 + ($inc70_1 << 4) + 8 | 0;
+ HEAPF64[$y72_2 >> 3] = $25;
+ $26 = $opl_promoted + 3 | 0;
+ HEAP32[2292] = $26;
+ $retval_0 = 1;
+ label = 12;
+ break;
+ case 10:
+ $cmp78 = $a_0 > .01;
+ if ($cmp78) {
+ label = 11;
+ break;
+ } else {
+ $first_0 = 0;
+ $b_0 = 0.0;
+ $a_0 = 0.0;
+ label = 3;
+ break;
+ }
+ case 11:
+ $div80 = $a_0 * .5;
+ $div81 = $b_0 * .5;
+ $first_0 = 0;
+ $b_0 = $div81;
+ $a_0 = $div80;
+ label = 3;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _add($agg_result, $p1, $p2) {
+ $agg_result = $agg_result | 0;
+ $p1 = $p1 | 0;
+ $p2 = $p2 | 0;
+ var $x1 = 0, $y2 = 0, $4 = 0, $5 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p1;
+ $p1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $p2;
+ $p2 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p2 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p2 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p2 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p2 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $x1 = $p1 | 0;
+ HEAPF64[$x1 >> 3] = +HEAPF64[$p2 >> 3] + +HEAPF64[$x1 >> 3];
+ $y2 = $p1 + 8 | 0;
+ HEAPF64[$y2 >> 3] = +HEAPF64[$p2 + 8 >> 3] + +HEAPF64[$y2 >> 3];
+ $4 = $agg_result;
+ $5 = $p1;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _sub($agg_result, $p1, $p2) {
+ $agg_result = $agg_result | 0;
+ $p1 = $p1 | 0;
+ $p2 = $p2 | 0;
+ var $x1 = 0, $y2 = 0, $4 = 0, $5 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p1;
+ $p1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $p2;
+ $p2 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p2 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p2 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p2 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p2 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $x1 = $p1 | 0;
+ HEAPF64[$x1 >> 3] = +HEAPF64[$x1 >> 3] - +HEAPF64[$p2 >> 3];
+ $y2 = $p1 + 8 | 0;
+ HEAPF64[$y2 >> 3] = +HEAPF64[$y2 >> 3] - +HEAPF64[$p2 + 8 >> 3];
+ $4 = $agg_result;
+ $5 = $p1;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _dist_n($p, $n) {
+ $p = $p | 0;
+ $n = $n | 0;
+ var $cmp18 = 0, $rv_020 = 0.0, $i_019 = 0, $x = 0, $0 = 0.0, $sub = 0, $x2 = 0, $1 = 0.0, $sub3 = 0.0, $mul = 0.0, $y = 0, $2 = 0.0, $y13 = 0, $3 = 0.0, $sub14 = 0.0, $mul21 = 0.0, $add = 0.0, $call = 0.0, $add22 = 0.0, $inc = 0, $cmp = 0, $rv_0_lcssa = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp18 = ($n | 0) > 1;
+ if ($cmp18) {
+ $i_019 = 1;
+ $rv_020 = 0.0;
+ label = 3;
+ break;
+ } else {
+ $rv_0_lcssa = 0.0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $x = $p + ($i_019 << 4) | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $sub = $i_019 - 1 | 0;
+ $x2 = $p + ($sub << 4) | 0;
+ $1 = +HEAPF64[$x2 >> 3];
+ $sub3 = $0 - $1;
+ $mul = $sub3 * $sub3;
+ $y = $p + ($i_019 << 4) + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $y13 = $p + ($sub << 4) + 8 | 0;
+ $3 = +HEAPF64[$y13 >> 3];
+ $sub14 = $2 - $3;
+ $mul21 = $sub14 * $sub14;
+ $add = $mul + $mul21;
+ $call = +Math_sqrt(+$add);
+ $add22 = $rv_020 + $call;
+ $inc = $i_019 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_019 = $inc;
+ $rv_020 = $add22;
+ label = 3;
+ break;
+ } else {
+ $rv_0_lcssa = $add22;
+ label = 4;
+ break;
+ }
+ case 4:
+ return +$rv_0_lcssa;
+ }
+ return 0.0;
+}
+function _splineisinside($edges, $edgen, $sps) {
+ $edges = $edges | 0;
+ $edgen = $edgen | 0;
+ $sps = $sps | 0;
+ var $roots = 0, $lps = 0, $cmp41 = 0, $arrayidx = 0, $0 = 0, $arrayidx2 = 0, $1 = 0, $arraydecay4 = 0, $x = 0, $x33 = 0, $x36 = 0, $x40 = 0, $y = 0, $y47 = 0, $y51 = 0, $y55 = 0, $x61 = 0, $y70 = 0, $x82 = 0, $y91 = 0, $ei_042 = 0, $arrayidx1 = 0, $2 = 0, $b = 0, $3 = 0, $call = 0, $cmp5 = 0, $cmp738 = 0, $or_cond43 = 0, $4 = 0.0, $5 = 0.0, $6 = 0.0, $7 = 0.0, $rooti_039 = 0, $arrayidx9 = 0, $8 = 0.0, $cmp10 = 0, $cmp12 = 0, $or_cond = 0, $mul = 0.0, $mul16 = 0.0, $mul17 = 0.0, $mul18 = 0.0, $sub = 0.0, $mul19 = 0.0, $mul22 = 0.0, $mul24 = 0.0, $mul27 = 0.0, $mul29 = 0.0, $9 = 0.0, $mul31 = 0.0, $10 = 0.0, $mul34 = 0.0, $add = 0.0, $11 = 0.0, $mul37 = 0.0, $add38 = 0.0, $12 = 0.0, $mul41 = 0.0, $add42 = 0.0, $13 = 0.0, $mul45 = 0.0, $14 = 0.0, $mul48 = 0.0, $add49 = 0.0, $15 = 0.0, $mul52 = 0.0, $add53 = 0.0, $16 = 0.0, $mul56 = 0.0, $add57 = 0.0, $sub62 = 0.0, $mul67 = 0.0, $sub71 = 0.0, $mul76 = 0.0, $add77 = 0.0, $cmp78 = 0, $sub83 = 0.0, $mul88 = 0.0, $sub92 = 0.0, $mul97 = 0.0, $add98 = 0.0, $cmp99 = 0, $inc = 0, $cmp7 = 0, $inc103 = 0, $cmp = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $roots = __stackBase__ | 0;
+ $lps = __stackBase__ + 32 | 0;
+ $cmp41 = ($edgen | 0) > 0;
+ if ($cmp41) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ }
+ case 3:
+ $arrayidx = $lps | 0;
+ $0 = $lps;
+ $arrayidx2 = $lps + 16 | 0;
+ $1 = $arrayidx2;
+ $arraydecay4 = $roots | 0;
+ $x = $sps | 0;
+ $x33 = $sps + 16 | 0;
+ $x36 = $sps + 32 | 0;
+ $x40 = $sps + 48 | 0;
+ $y = $sps + 8 | 0;
+ $y47 = $sps + 24 | 0;
+ $y51 = $sps + 40 | 0;
+ $y55 = $sps + 56 | 0;
+ $x61 = $lps | 0;
+ $y70 = $lps + 8 | 0;
+ $x82 = $arrayidx2 | 0;
+ $y91 = $lps + 24 | 0;
+ $ei_042 = 0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx1 = $edges + ($ei_042 << 5) | 0;
+ $2 = $arrayidx1;
+ HEAP32[$0 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ $b = $edges + ($ei_042 << 5) + 16 | 0;
+ $3 = $b;
+ HEAP32[$1 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $call = _splineintersectsline($sps, $arrayidx, $arraydecay4) | 0;
+ $cmp5 = ($call | 0) != 4;
+ $cmp738 = ($call | 0) > 0;
+ $or_cond43 = $cmp5 & $cmp738;
+ if ($or_cond43) {
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ $4 = +HEAPF64[$x61 >> 3];
+ $5 = +HEAPF64[$y70 >> 3];
+ $6 = +HEAPF64[$x82 >> 3];
+ $7 = +HEAPF64[$y91 >> 3];
+ $rooti_039 = 0;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx9 = $roots + ($rooti_039 << 3) | 0;
+ $8 = +HEAPF64[$arrayidx9 >> 3];
+ $cmp10 = $8 < 1.0e-6;
+ $cmp12 = $8 > .999999;
+ $or_cond = $cmp10 | $cmp12;
+ if ($or_cond) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $mul = $8 * $8;
+ $mul16 = $8 * $mul;
+ $mul17 = $8 * 3.0;
+ $mul18 = $8 * $mul17;
+ $sub = 1.0 - $8;
+ $mul19 = $sub * $mul18;
+ $mul22 = $mul17 * $sub;
+ $mul24 = $sub * $mul22;
+ $mul27 = $sub * $sub;
+ $mul29 = $sub * $mul27;
+ $9 = +HEAPF64[$x >> 3];
+ $mul31 = $mul29 * $9;
+ $10 = +HEAPF64[$x33 >> 3];
+ $mul34 = $mul24 * $10;
+ $add = $mul31 + $mul34;
+ $11 = +HEAPF64[$x36 >> 3];
+ $mul37 = $mul19 * $11;
+ $add38 = $add + $mul37;
+ $12 = +HEAPF64[$x40 >> 3];
+ $mul41 = $mul16 * $12;
+ $add42 = $add38 + $mul41;
+ $13 = +HEAPF64[$y >> 3];
+ $mul45 = $mul29 * $13;
+ $14 = +HEAPF64[$y47 >> 3];
+ $mul48 = $mul24 * $14;
+ $add49 = $mul45 + $mul48;
+ $15 = +HEAPF64[$y51 >> 3];
+ $mul52 = $mul19 * $15;
+ $add53 = $add49 + $mul52;
+ $16 = +HEAPF64[$y55 >> 3];
+ $mul56 = $mul16 * $16;
+ $add57 = $add53 + $mul56;
+ $sub62 = $add42 - $4;
+ $mul67 = $sub62 * $sub62;
+ $sub71 = $add57 - $5;
+ $mul76 = $sub71 * $sub71;
+ $add77 = $mul67 + $mul76;
+ $cmp78 = $add77 < .001;
+ if ($cmp78) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $sub83 = $add42 - $6;
+ $mul88 = $sub83 * $sub83;
+ $sub92 = $add57 - $7;
+ $mul97 = $sub92 * $sub92;
+ $add98 = $mul88 + $mul97;
+ $cmp99 = $add98 < .001;
+ if ($cmp99) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 11;
+ break;
+ }
+ case 9:
+ $inc = $rooti_039 + 1 | 0;
+ $cmp7 = ($inc | 0) < ($call | 0);
+ if ($cmp7) {
+ $rooti_039 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $inc103 = $ei_042 + 1 | 0;
+ $cmp = ($inc103 | 0) < ($edgen | 0);
+ if ($cmp) {
+ $ei_042 = $inc103;
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ }
+ case 11:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _splineintersectsline($sps, $lps, $roots) {
+ $sps = $sps | 0;
+ $lps = $lps | 0;
+ $roots = $roots | 0;
+ var $scoeff = 0, $xroots = 0, $yroots = 0, $rootn = 0, $x = 0, $0 = 0.0, $x3 = 0, $1 = 0.0, $sub = 0.0, $y = 0, $2 = 0.0, $y10 = 0, $3 = 0.0, $sub13 = 0.0, $cmp = 0, $cmp17 = 0, $x20 = 0, $4 = 0.0, $x22 = 0, $5 = 0.0, $x24 = 0, $6 = 0.0, $x26 = 0, $7 = 0.0, $arraydecay = 0, $8 = 0.0, $sub29 = 0.0, $arraydecay31 = 0, $call = 0, $y33 = 0, $9 = 0.0, $y35 = 0, $10 = 0.0, $y37 = 0, $11 = 0.0, $y39 = 0, $12 = 0.0, $13 = 0.0, $sub43 = 0.0, $arraydecay45 = 0, $call46 = 0, $cmp47 = 0, $cmp49 = 0, $cmp5187 = 0, $j_088 = 0, $arrayidx52 = 0, $14 = 0.0, $inc = 0, $cmp51 = 0, $cmp5790 = 0, $cmp6892 = 0, $i_091 = 0, $arrayidx59 = 0, $15 = 0.0, $inc61 = 0, $cmp57 = 0, $i_196 = 0, $arrayidx70 = 0, $16 = 0.0, $j_193 = 0, $arrayidx71 = 0, $17 = 0.0, $cmp72 = 0, $inc77 = 0, $cmp68 = 0, $inc80 = 0, $cmp65 = 0, $18 = 0, $cmp100 = 0, $cmp10497 = 0, $y111 = 0, $y113 = 0, $y115 = 0, $y117 = 0, $arrayidx120 = 0, $arrayidx121 = 0, $arrayidx122 = 0, $i_298 = 0, $arrayidx106 = 0, $19 = 0.0, $cmp107 = 0, $cmp108 = 0, $or_cond = 0, $20 = 0.0, $21 = 0.0, $22 = 0.0, $23 = 0.0, $24 = 0.0, $25 = 0.0, $26 = 0.0, $27 = 0.0, $mul = 0.0, $add = 0.0, $mul123 = 0.0, $add124 = 0.0, $mul125 = 0.0, $add126 = 0.0, $sub128 = 0.0, $div = 0.0, $cmp130 = 0, $cmp132 = 0, $or_cond1 = 0, $inc137 = 0, $cmp104 = 0, $28 = 0, $div142 = 0.0, $y144 = 0, $29 = 0.0, $x146 = 0, $30 = 0.0, $mul147 = 0.0, $sub148 = 0.0, $y150 = 0, $31 = 0.0, $x152 = 0, $32 = 0.0, $mul153 = 0.0, $sub154 = 0.0, $y156 = 0, $33 = 0.0, $x158 = 0, $34 = 0.0, $mul159 = 0.0, $sub160 = 0.0, $y162 = 0, $35 = 0.0, $x164 = 0, $36 = 0.0, $mul165 = 0.0, $sub166 = 0.0, $arraydecay167 = 0, $mul169 = 0.0, $sub171 = 0.0, $37 = 0.0, $add173 = 0.0, $arraydecay175 = 0, $call176 = 0, $cmp177 = 0, $cmp18199 = 0, $arrayidx198 = 0, $arrayidx199 = 0, $arrayidx200 = 0, $i_3100 = 0, $arrayidx183 = 0, $38 = 0.0, $cmp184 = 0, $cmp186 = 0, $or_cond2 = 0, $39 = 0.0, $40 = 0.0, $41 = 0.0, $42 = 0.0, $43 = 0.0, $44 = 0.0, $45 = 0.0, $46 = 0.0, $mul201 = 0.0, $add202 = 0.0, $mul203 = 0.0, $add204 = 0.0, $mul205 = 0.0, $add206 = 0.0, $sub208 = 0.0, $div210 = 0.0, $cmp211 = 0, $cmp213 = 0, $or_cond3 = 0, $inc218 = 0, $cmp181 = 0, $47 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 88 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $scoeff = __stackBase__ | 0;
+ $xroots = __stackBase__ + 32 | 0;
+ $yroots = __stackBase__ + 56 | 0;
+ $rootn = __stackBase__ + 80 | 0;
+ $x = $lps | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x3 = $lps + 16 | 0;
+ $1 = +HEAPF64[$x3 >> 3];
+ $sub = $1 - $0;
+ $y = $lps + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $y10 = $lps + 24 | 0;
+ $3 = +HEAPF64[$y10 >> 3];
+ $sub13 = $3 - $2;
+ HEAP32[$rootn >> 2] = 0;
+ $cmp = $sub == 0.0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 3:
+ $cmp17 = $sub13 == 0.0;
+ $x20 = $sps | 0;
+ $4 = +HEAPF64[$x20 >> 3];
+ $x22 = $sps + 16 | 0;
+ $5 = +HEAPF64[$x22 >> 3];
+ $x24 = $sps + 32 | 0;
+ $6 = +HEAPF64[$x24 >> 3];
+ $x26 = $sps + 48 | 0;
+ $7 = +HEAPF64[$x26 >> 3];
+ $arraydecay = $scoeff | 0;
+ _points2coeff($4, $5, $6, $7, $arraydecay);
+ $8 = +HEAPF64[$arraydecay >> 3];
+ $sub29 = $8 - $0;
+ HEAPF64[$arraydecay >> 3] = $sub29;
+ $arraydecay31 = $xroots | 0;
+ $call = _solve3($arraydecay, $arraydecay31) | 0;
+ if ($cmp17) {
+ label = 4;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 4:
+ $y33 = $sps + 8 | 0;
+ $9 = +HEAPF64[$y33 >> 3];
+ $y35 = $sps + 24 | 0;
+ $10 = +HEAPF64[$y35 >> 3];
+ $y37 = $sps + 40 | 0;
+ $11 = +HEAPF64[$y37 >> 3];
+ $y39 = $sps + 56 | 0;
+ $12 = +HEAPF64[$y39 >> 3];
+ _points2coeff($9, $10, $11, $12, $arraydecay);
+ $13 = +HEAPF64[$arraydecay >> 3];
+ $sub43 = $13 - $2;
+ HEAPF64[$arraydecay >> 3] = $sub43;
+ $arraydecay45 = $yroots | 0;
+ $call46 = _solve3($arraydecay, $arraydecay45) | 0;
+ $cmp47 = ($call | 0) == 4;
+ $cmp49 = ($call46 | 0) == 4;
+ if ($cmp47) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ if ($cmp49) {
+ $retval_0 = 4;
+ label = 36;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp5187 = ($call46 | 0) > 0;
+ if ($cmp5187) {
+ $j_088 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 7:
+ $arrayidx52 = $yroots + ($j_088 << 3) | 0;
+ $14 = +HEAPF64[$arrayidx52 >> 3];
+ _addroot($14, $roots, $rootn);
+ $inc = $j_088 + 1 | 0;
+ $cmp51 = ($inc | 0) < ($call46 | 0);
+ if ($cmp51) {
+ $j_088 = $inc;
+ label = 7;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 8:
+ $cmp5790 = ($call | 0) > 0;
+ if ($cmp49) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ if ($cmp5790) {
+ label = 10;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 10:
+ $cmp6892 = ($call46 | 0) > 0;
+ $i_196 = 0;
+ label = 13;
+ break;
+ case 11:
+ if ($cmp5790) {
+ $i_091 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 12:
+ $arrayidx59 = $xroots + ($i_091 << 3) | 0;
+ $15 = +HEAPF64[$arrayidx59 >> 3];
+ _addroot($15, $roots, $rootn);
+ $inc61 = $i_091 + 1 | 0;
+ $cmp57 = ($inc61 | 0) < ($call | 0);
+ if ($cmp57) {
+ $i_091 = $inc61;
+ label = 12;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 13:
+ if ($cmp6892) {
+ label = 14;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 14:
+ $arrayidx70 = $xroots + ($i_196 << 3) | 0;
+ $16 = +HEAPF64[$arrayidx70 >> 3];
+ $j_193 = 0;
+ label = 15;
+ break;
+ case 15:
+ $arrayidx71 = $yroots + ($j_193 << 3) | 0;
+ $17 = +HEAPF64[$arrayidx71 >> 3];
+ $cmp72 = $16 == $17;
+ if ($cmp72) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ _addroot($16, $roots, $rootn);
+ label = 17;
+ break;
+ case 17:
+ $inc77 = $j_193 + 1 | 0;
+ $cmp68 = ($inc77 | 0) < ($call46 | 0);
+ if ($cmp68) {
+ $j_193 = $inc77;
+ label = 15;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $inc80 = $i_196 + 1 | 0;
+ $cmp65 = ($inc80 | 0) < ($call | 0);
+ if ($cmp65) {
+ $i_196 = $inc80;
+ label = 13;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $18 = HEAP32[$rootn >> 2] | 0;
+ $retval_0 = $18;
+ label = 36;
+ break;
+ case 20:
+ $cmp100 = ($call | 0) == 4;
+ if ($cmp100) {
+ $retval_0 = 4;
+ label = 36;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $cmp10497 = ($call | 0) > 0;
+ if ($cmp10497) {
+ label = 22;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 22:
+ $y111 = $sps + 8 | 0;
+ $y113 = $sps + 24 | 0;
+ $y115 = $sps + 40 | 0;
+ $y117 = $sps + 56 | 0;
+ $arrayidx120 = $scoeff + 8 | 0;
+ $arrayidx121 = $scoeff + 16 | 0;
+ $arrayidx122 = $scoeff + 24 | 0;
+ $i_298 = 0;
+ label = 23;
+ break;
+ case 23:
+ $arrayidx106 = $xroots + ($i_298 << 3) | 0;
+ $19 = +HEAPF64[$arrayidx106 >> 3];
+ $cmp107 = $19 >= 0.0;
+ $cmp108 = $19 <= 1.0;
+ $or_cond = $cmp107 & $cmp108;
+ if ($or_cond) {
+ label = 24;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 24:
+ $20 = +HEAPF64[$y111 >> 3];
+ $21 = +HEAPF64[$y113 >> 3];
+ $22 = +HEAPF64[$y115 >> 3];
+ $23 = +HEAPF64[$y117 >> 3];
+ _points2coeff($20, $21, $22, $23, $arraydecay);
+ $24 = +HEAPF64[$arraydecay >> 3];
+ $25 = +HEAPF64[$arrayidx120 >> 3];
+ $26 = +HEAPF64[$arrayidx121 >> 3];
+ $27 = +HEAPF64[$arrayidx122 >> 3];
+ $mul = $19 * $27;
+ $add = $26 + $mul;
+ $mul123 = $19 * $add;
+ $add124 = $25 + $mul123;
+ $mul125 = $19 * $add124;
+ $add126 = $24 + $mul125;
+ $sub128 = $add126 - $2;
+ $div = $sub128 / $sub13;
+ $cmp130 = $div >= 0.0;
+ $cmp132 = $div <= 1.0;
+ $or_cond1 = $cmp130 & $cmp132;
+ if ($or_cond1) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ _addroot($19, $roots, $rootn);
+ label = 26;
+ break;
+ case 26:
+ $inc137 = $i_298 + 1 | 0;
+ $cmp104 = ($inc137 | 0) < ($call | 0);
+ if ($cmp104) {
+ $i_298 = $inc137;
+ label = 23;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $28 = HEAP32[$rootn >> 2] | 0;
+ $retval_0 = $28;
+ label = 36;
+ break;
+ case 28:
+ $div142 = $sub13 / $sub;
+ $y144 = $sps + 8 | 0;
+ $29 = +HEAPF64[$y144 >> 3];
+ $x146 = $sps | 0;
+ $30 = +HEAPF64[$x146 >> 3];
+ $mul147 = $div142 * $30;
+ $sub148 = $29 - $mul147;
+ $y150 = $sps + 24 | 0;
+ $31 = +HEAPF64[$y150 >> 3];
+ $x152 = $sps + 16 | 0;
+ $32 = +HEAPF64[$x152 >> 3];
+ $mul153 = $div142 * $32;
+ $sub154 = $31 - $mul153;
+ $y156 = $sps + 40 | 0;
+ $33 = +HEAPF64[$y156 >> 3];
+ $x158 = $sps + 32 | 0;
+ $34 = +HEAPF64[$x158 >> 3];
+ $mul159 = $div142 * $34;
+ $sub160 = $33 - $mul159;
+ $y162 = $sps + 56 | 0;
+ $35 = +HEAPF64[$y162 >> 3];
+ $x164 = $sps + 48 | 0;
+ $36 = +HEAPF64[$x164 >> 3];
+ $mul165 = $div142 * $36;
+ $sub166 = $35 - $mul165;
+ $arraydecay167 = $scoeff | 0;
+ _points2coeff($sub148, $sub154, $sub160, $sub166, $arraydecay167);
+ $mul169 = $0 * $div142;
+ $sub171 = $mul169 - $2;
+ $37 = +HEAPF64[$arraydecay167 >> 3];
+ $add173 = $sub171 + $37;
+ HEAPF64[$arraydecay167 >> 3] = $add173;
+ $arraydecay175 = $xroots | 0;
+ $call176 = _solve3($arraydecay167, $arraydecay175) | 0;
+ $cmp177 = ($call176 | 0) == 4;
+ if ($cmp177) {
+ $retval_0 = 4;
+ label = 36;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $cmp18199 = ($call176 | 0) > 0;
+ if ($cmp18199) {
+ label = 30;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 30:
+ $arrayidx198 = $scoeff + 8 | 0;
+ $arrayidx199 = $scoeff + 16 | 0;
+ $arrayidx200 = $scoeff + 24 | 0;
+ $i_3100 = 0;
+ label = 31;
+ break;
+ case 31:
+ $arrayidx183 = $xroots + ($i_3100 << 3) | 0;
+ $38 = +HEAPF64[$arrayidx183 >> 3];
+ $cmp184 = $38 >= 0.0;
+ $cmp186 = $38 <= 1.0;
+ $or_cond2 = $cmp184 & $cmp186;
+ if ($or_cond2) {
+ label = 32;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 32:
+ $39 = +HEAPF64[$x146 >> 3];
+ $40 = +HEAPF64[$x152 >> 3];
+ $41 = +HEAPF64[$x158 >> 3];
+ $42 = +HEAPF64[$x164 >> 3];
+ _points2coeff($39, $40, $41, $42, $arraydecay167);
+ $43 = +HEAPF64[$arraydecay167 >> 3];
+ $44 = +HEAPF64[$arrayidx198 >> 3];
+ $45 = +HEAPF64[$arrayidx199 >> 3];
+ $46 = +HEAPF64[$arrayidx200 >> 3];
+ $mul201 = $38 * $46;
+ $add202 = $45 + $mul201;
+ $mul203 = $38 * $add202;
+ $add204 = $44 + $mul203;
+ $mul205 = $38 * $add204;
+ $add206 = $43 + $mul205;
+ $sub208 = $add206 - $0;
+ $div210 = $sub208 / $sub;
+ $cmp211 = $div210 >= 0.0;
+ $cmp213 = $div210 <= 1.0;
+ $or_cond3 = $cmp211 & $cmp213;
+ if ($or_cond3) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ _addroot($38, $roots, $rootn);
+ label = 34;
+ break;
+ case 34:
+ $inc218 = $i_3100 + 1 | 0;
+ $cmp181 = ($inc218 | 0) < ($call176 | 0);
+ if ($cmp181) {
+ $i_3100 = $inc218;
+ label = 31;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $47 = HEAP32[$rootn >> 2] | 0;
+ $retval_0 = $47;
+ label = 36;
+ break;
+ case 36:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _ccw($p1p, $p2p, $p3p) {
+ $p1p = $p1p | 0;
+ $p2p = $p2p | 0;
+ $p3p = $p3p | 0;
+ var $y = 0, $0 = 0.0, $y1 = 0, $1 = 0.0, $sub = 0.0, $x = 0, $2 = 0.0, $x2 = 0, $3 = 0.0, $sub3 = 0.0, $mul = 0.0, $y4 = 0, $4 = 0.0, $sub6 = 0.0, $x7 = 0, $5 = 0.0, $sub9 = 0.0, $mul10 = 0.0, $sub11 = 0.0, $cmp = 0, $cmp12 = 0, $cond = 0, $cond13 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $y = $p1p + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $y1 = $p2p + 8 | 0;
+ $1 = +HEAPF64[$y1 >> 3];
+ $sub = $0 - $1;
+ $x = $p3p | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x2 = $p2p | 0;
+ $3 = +HEAPF64[$x2 >> 3];
+ $sub3 = $2 - $3;
+ $mul = $sub * $sub3;
+ $y4 = $p3p + 8 | 0;
+ $4 = +HEAPF64[$y4 >> 3];
+ $sub6 = $4 - $1;
+ $x7 = $p1p | 0;
+ $5 = +HEAPF64[$x7 >> 3];
+ $sub9 = $5 - $3;
+ $mul10 = $sub6 * $sub9;
+ $sub11 = $mul - $mul10;
+ $cmp = $sub11 > 0.0;
+ if ($cmp) {
+ $cond13 = 1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp12 = $sub11 < 0.0;
+ $cond = $cmp12 ? 2 : 3;
+ $cond13 = $cond;
+ label = 4;
+ break;
+ case 4:
+ return $cond13 | 0;
+ }
+ return 0;
+}
+function _connecttris($tri1, $tri2) {
+ $tri1 = $tri1 | 0;
+ $tri2 = $tri2 | 0;
+ var $ei_025 = 0, $0 = 0, $arrayidx = 0, $arrayidx4 = 0, $pnl0p = 0, $1 = 0, $pp = 0, $2 = 0, $pnl0p8 = 0, $3 = 0, $pp9 = 0, $4 = 0, $cmp10 = 0, $pnl1p = 0, $5 = 0, $pp13 = 0, $6 = 0, $pnl1p16 = 0, $7 = 0, $pp17 = 0, $8 = 0, $cmp18 = 0, $9 = 0, $pp22 = 0, $10 = 0, $pnl1p25 = 0, $11 = 0, $pp26 = 0, $12 = 0, $cmp27 = 0, $pnl1p31 = 0, $13 = 0, $pp32 = 0, $14 = 0, $15 = 0, $pp36 = 0, $16 = 0, $cmp37 = 0, $rtp = 0, $rtp42 = 0, $17 = 0, $arrayidx_1 = 0, $arrayidx4_1 = 0, $pnl0p_1 = 0, $18 = 0, $pp_1 = 0, $19 = 0, $pnl0p8_1 = 0, $20 = 0, $pp9_1 = 0, $21 = 0, $cmp10_1 = 0, $pnl1p_1 = 0, $22 = 0, $pp13_1 = 0, $23 = 0, $pnl1p16_1 = 0, $24 = 0, $pp17_1 = 0, $25 = 0, $cmp18_1 = 0, $26 = 0, $pp22_1 = 0, $27 = 0, $pnl1p25_1 = 0, $28 = 0, $pp26_1 = 0, $29 = 0, $cmp27_1 = 0, $pnl1p31_1 = 0, $30 = 0, $pp32_1 = 0, $31 = 0, $32 = 0, $pp36_1 = 0, $33 = 0, $cmp37_1 = 0, $rtp_1 = 0, $rtp42_1 = 0, $34 = 0, $arrayidx_2 = 0, $arrayidx4_2 = 0, $pnl0p_2 = 0, $35 = 0, $pp_2 = 0, $36 = 0, $pnl0p8_2 = 0, $37 = 0, $pp9_2 = 0, $38 = 0, $cmp10_2 = 0, $pnl1p_2 = 0, $39 = 0, $pp13_2 = 0, $40 = 0, $pnl1p16_2 = 0, $41 = 0, $pp17_2 = 0, $42 = 0, $cmp18_2 = 0, $43 = 0, $pp22_2 = 0, $44 = 0, $pnl1p25_2 = 0, $45 = 0, $pp26_2 = 0, $46 = 0, $cmp27_2 = 0, $pnl1p31_2 = 0, $47 = 0, $pp32_2 = 0, $48 = 0, $49 = 0, $pp36_2 = 0, $50 = 0, $cmp37_2 = 0, $rtp_2 = 0, $rtp42_2 = 0, $inc44 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ei_025 = 0;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP32[230] | 0;
+ $arrayidx = $0 + ($tri1 * 52 & -1) | 0;
+ $arrayidx4 = $0 + ($tri2 * 52 & -1) | 0;
+ $pnl0p = $0 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) | 0;
+ $1 = HEAP32[$pnl0p >> 2] | 0;
+ $pp = $1 | 0;
+ $2 = HEAP32[$pp >> 2] | 0;
+ $pnl0p8 = $0 + ($tri2 * 52 & -1) + 4 | 0;
+ $3 = HEAP32[$pnl0p8 >> 2] | 0;
+ $pp9 = $3 | 0;
+ $4 = HEAP32[$pp9 >> 2] | 0;
+ $cmp10 = ($2 | 0) == ($4 | 0);
+ if ($cmp10) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $pnl1p = $0 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 4 | 0;
+ $5 = HEAP32[$pnl1p >> 2] | 0;
+ $pp13 = $5 | 0;
+ $6 = HEAP32[$pp13 >> 2] | 0;
+ $pnl1p16 = $0 + ($tri2 * 52 & -1) + 8 | 0;
+ $7 = HEAP32[$pnl1p16 >> 2] | 0;
+ $pp17 = $7 | 0;
+ $8 = HEAP32[$pp17 >> 2] | 0;
+ $cmp18 = ($6 | 0) == ($8 | 0);
+ if ($cmp18) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $9 = HEAP32[$pnl0p >> 2] | 0;
+ $pp22 = $9 | 0;
+ $10 = HEAP32[$pp22 >> 2] | 0;
+ $pnl1p25 = $0 + ($tri2 * 52 & -1) + 8 | 0;
+ $11 = HEAP32[$pnl1p25 >> 2] | 0;
+ $pp26 = $11 | 0;
+ $12 = HEAP32[$pp26 >> 2] | 0;
+ $cmp27 = ($10 | 0) == ($12 | 0);
+ if ($cmp27) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $pnl1p31 = $0 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 4 | 0;
+ $13 = HEAP32[$pnl1p31 >> 2] | 0;
+ $pp32 = $13 | 0;
+ $14 = HEAP32[$pp32 >> 2] | 0;
+ $15 = HEAP32[$pnl0p8 >> 2] | 0;
+ $pp36 = $15 | 0;
+ $16 = HEAP32[$pp36 >> 2] | 0;
+ $cmp37 = ($14 | 0) == ($16 | 0);
+ if ($cmp37) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $rtp = $0 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 12 | 0;
+ HEAP32[$rtp >> 2] = $arrayidx4;
+ $rtp42 = $0 + ($tri2 * 52 & -1) + 16 | 0;
+ HEAP32[$rtp42 >> 2] = $arrayidx;
+ label = 8;
+ break;
+ case 8:
+ $17 = HEAP32[230] | 0;
+ $arrayidx_1 = $17 + ($tri1 * 52 & -1) | 0;
+ $arrayidx4_1 = $17 + ($tri2 * 52 & -1) | 0;
+ $pnl0p_1 = $17 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) | 0;
+ $18 = HEAP32[$pnl0p_1 >> 2] | 0;
+ $pp_1 = $18 | 0;
+ $19 = HEAP32[$pp_1 >> 2] | 0;
+ $pnl0p8_1 = $17 + ($tri2 * 52 & -1) + 20 | 0;
+ $20 = HEAP32[$pnl0p8_1 >> 2] | 0;
+ $pp9_1 = $20 | 0;
+ $21 = HEAP32[$pp9_1 >> 2] | 0;
+ $cmp10_1 = ($19 | 0) == ($21 | 0);
+ if ($cmp10_1) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ return;
+ case 10:
+ $pnl1p_1 = $17 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 4 | 0;
+ $22 = HEAP32[$pnl1p_1 >> 2] | 0;
+ $pp13_1 = $22 | 0;
+ $23 = HEAP32[$pp13_1 >> 2] | 0;
+ $pnl1p16_1 = $17 + ($tri2 * 52 & -1) + 24 | 0;
+ $24 = HEAP32[$pnl1p16_1 >> 2] | 0;
+ $pp17_1 = $24 | 0;
+ $25 = HEAP32[$pp17_1 >> 2] | 0;
+ $cmp18_1 = ($23 | 0) == ($25 | 0);
+ if ($cmp18_1) {
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $26 = HEAP32[$pnl0p_1 >> 2] | 0;
+ $pp22_1 = $26 | 0;
+ $27 = HEAP32[$pp22_1 >> 2] | 0;
+ $pnl1p25_1 = $17 + ($tri2 * 52 & -1) + 24 | 0;
+ $28 = HEAP32[$pnl1p25_1 >> 2] | 0;
+ $pp26_1 = $28 | 0;
+ $29 = HEAP32[$pp26_1 >> 2] | 0;
+ $cmp27_1 = ($27 | 0) == ($29 | 0);
+ if ($cmp27_1) {
+ label = 12;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ $pnl1p31_1 = $17 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 4 | 0;
+ $30 = HEAP32[$pnl1p31_1 >> 2] | 0;
+ $pp32_1 = $30 | 0;
+ $31 = HEAP32[$pp32_1 >> 2] | 0;
+ $32 = HEAP32[$pnl0p8_1 >> 2] | 0;
+ $pp36_1 = $32 | 0;
+ $33 = HEAP32[$pp36_1 >> 2] | 0;
+ $cmp37_1 = ($31 | 0) == ($33 | 0);
+ if ($cmp37_1) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $rtp_1 = $17 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 12 | 0;
+ HEAP32[$rtp_1 >> 2] = $arrayidx4_1;
+ $rtp42_1 = $17 + ($tri2 * 52 & -1) + 32 | 0;
+ HEAP32[$rtp42_1 >> 2] = $arrayidx_1;
+ label = 14;
+ break;
+ case 14:
+ $34 = HEAP32[230] | 0;
+ $arrayidx_2 = $34 + ($tri1 * 52 & -1) | 0;
+ $arrayidx4_2 = $34 + ($tri2 * 52 & -1) | 0;
+ $pnl0p_2 = $34 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) | 0;
+ $35 = HEAP32[$pnl0p_2 >> 2] | 0;
+ $pp_2 = $35 | 0;
+ $36 = HEAP32[$pp_2 >> 2] | 0;
+ $pnl0p8_2 = $34 + ($tri2 * 52 & -1) + 36 | 0;
+ $37 = HEAP32[$pnl0p8_2 >> 2] | 0;
+ $pp9_2 = $37 | 0;
+ $38 = HEAP32[$pp9_2 >> 2] | 0;
+ $cmp10_2 = ($36 | 0) == ($38 | 0);
+ if ($cmp10_2) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $pnl1p_2 = $34 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 4 | 0;
+ $39 = HEAP32[$pnl1p_2 >> 2] | 0;
+ $pp13_2 = $39 | 0;
+ $40 = HEAP32[$pp13_2 >> 2] | 0;
+ $pnl1p16_2 = $34 + ($tri2 * 52 & -1) + 40 | 0;
+ $41 = HEAP32[$pnl1p16_2 >> 2] | 0;
+ $pp17_2 = $41 | 0;
+ $42 = HEAP32[$pp17_2 >> 2] | 0;
+ $cmp18_2 = ($40 | 0) == ($42 | 0);
+ if ($cmp18_2) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $43 = HEAP32[$pnl0p_2 >> 2] | 0;
+ $pp22_2 = $43 | 0;
+ $44 = HEAP32[$pp22_2 >> 2] | 0;
+ $pnl1p25_2 = $34 + ($tri2 * 52 & -1) + 40 | 0;
+ $45 = HEAP32[$pnl1p25_2 >> 2] | 0;
+ $pp26_2 = $45 | 0;
+ $46 = HEAP32[$pp26_2 >> 2] | 0;
+ $cmp27_2 = ($44 | 0) == ($46 | 0);
+ if ($cmp27_2) {
+ label = 17;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 17:
+ $pnl1p31_2 = $34 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 4 | 0;
+ $47 = HEAP32[$pnl1p31_2 >> 2] | 0;
+ $pp32_2 = $47 | 0;
+ $48 = HEAP32[$pp32_2 >> 2] | 0;
+ $49 = HEAP32[$pnl0p8_2 >> 2] | 0;
+ $pp36_2 = $49 | 0;
+ $50 = HEAP32[$pp36_2 >> 2] | 0;
+ $cmp37_2 = ($48 | 0) == ($50 | 0);
+ if ($cmp37_2) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $rtp_2 = $34 + ($tri1 * 52 & -1) + 4 + ($ei_025 << 4) + 12 | 0;
+ HEAP32[$rtp_2 >> 2] = $arrayidx4_2;
+ $rtp42_2 = $34 + ($tri2 * 52 & -1) + 48 | 0;
+ HEAP32[$rtp42_2 >> 2] = $arrayidx_2;
+ label = 19;
+ break;
+ case 19:
+ $inc44 = $ei_025 + 1 | 0;
+ $cmp = ($inc44 | 0) < 3;
+ if ($cmp) {
+ $ei_025 = $inc44;
+ label = 3;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ }
+}
+function _Pshortestpath($polyp, $eps, $output) {
+ $polyp = $polyp | 0;
+ $eps = $eps | 0;
+ $output = $output | 0;
+ var $p1 = 0, $p2 = 0, $p3 = 0, $epnls = 0, $pn = 0, $0 = 0, $1 = 0, $mul = 0, $2 = 0, $div = 0, $sub = 0, $3 = 0, $cmp154 = 0, $ps = 0, $4 = 0, $arrayidx8162 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $pi_0157 = 0, $minpi_0156 = 0, $minx_0155 = 0.0, $x = 0, $10 = 0.0, $cmp3 = 0, $minx_1 = 0.0, $minpi_1 = 0, $inc = 0, $cmp = 0, $arrayidx8 = 0, $11 = 0, $12 = 0, $cmp9 = 0, $13 = 0, $minpi_0_lcssa164 = 0, $_sink = 0, $sub11 = 0, $14 = 0, $arrayidx14 = 0, $15 = 0, $16 = 0, $17 = 0, $sub16 = 0, $cmp17 = 0, $add = 0, $_add = 0, $18 = 0, $arrayidx23 = 0, $19 = 0, $20 = 0, $x24 = 0, $21 = 0.0, $x25 = 0, $22 = 0.0, $cmp26 = 0, $x28 = 0, $23 = 0.0, $cmp29 = 0, $y = 0, $24 = 0.0, $y31 = 0, $25 = 0.0, $cmp32 = 0, $call = 0, $cmp33 = 0, $26 = 0, $cmp76150 = 0, $27 = 0, $cmp38146 = 0, $pi_1148_in = 0, $pi_1148 = 0, $28 = 0, $sub41 = 0, $cmp42 = 0, $29 = 0, $x46 = 0, $30 = 0.0, $x50 = 0, $31 = 0.0, $cmp51 = 0, $y55 = 0, $32 = 0.0, $y59 = 0, $33 = 0.0, $cmp60 = 0, $cmp38 = 0, $34 = 0, $arrayidx64 = 0, $35 = 0, $36 = 0, $pp = 0, $37 = 0, $38 = 0, $rem = 0, $39 = 0, $arrayidx67 = 0, $link = 0, $40 = 0, $41 = 0, $arrayidx69 = 0, $42 = 0, $arrayidx70 = 0, $43 = 0, $inc71 = 0, $pi_2151 = 0, $cmp78 = 0, $44 = 0, $x82 = 0, $45 = 0.0, $sub83 = 0, $x86 = 0, $46 = 0.0, $cmp87 = 0, $y91 = 0, $47 = 0.0, $y95 = 0, $48 = 0.0, $cmp96 = 0, $49 = 0, $arrayidx100 = 0, $50 = 0, $51 = 0, $pp102 = 0, $52 = 0, $53 = 0, $rem104 = 0, $54 = 0, $arrayidx105 = 0, $link107 = 0, $55 = 0, $56 = 0, $arrayidx108 = 0, $57 = 0, $arrayidx109 = 0, $58 = 0, $inc110 = 0, $inc112 = 0, $59 = 0, $cmp76 = 0, $60 = 0, $61 = 0, $62 = 0, $cmp116143 = 0, $63 = 0, $cmp116 = 0, $64 = 0, $trii_0144 = 0, $add118 = 0, $65 = 0, $cmp120141 = 0, $trij_0142 = 0, $inc123 = 0, $66 = 0, $cmp120 = 0, $trii_1 = 0, $cmp129 = 0, $call132 = 0, $tobool = 0, $inc136 = 0, $67 = 0, $cmp138 = 0, $arrayidx145 = 0, $68 = 0, $69 = 0, $call140 = 0, $trii_2 = 0, $cmp143 = 0, $call146 = 0, $tobool147 = 0, $inc151 = 0, $70 = 0, $cmp153 = 0, $71 = 0, $call155 = 0, $call157 = 0, $tobool158 = 0, $72 = 0, $call160 = 0, $pn161 = 0, $73 = 0, $74 = 0, $75 = 0, $76 = 0, $arrayidx164 = 0, $arrayidx165 = 0, $77 = 0, $78 = 0, $79 = 0, $ps166 = 0, $cmp168 = 0, $pn170 = 0, $80 = 0, $81 = 0, $82 = 0, $83 = 0, $arrayidx173 = 0, $arrayidx174 = 0, $84 = 0, $85 = 0, $86 = 0, $ps175 = 0, $arrayidx178 = 0, $pp179 = 0, $link181 = 0, $arrayidx182 = 0, $arrayidx183 = 0, $pp184 = 0, $link186 = 0, $87 = 0, $cmp188139 = 0, $trii_3140 = 0, $88 = 0, $mark = 0, $rtp = 0, $89 = 0, $tobool194 = 0, $mark199 = 0, $90 = 0, $cmp200 = 0, $rtp_1 = 0, $91 = 0, $tobool194_1 = 0, $92 = 0, $93 = 0, $arrayidx209 = 0, $94 = 0, $pp210 = 0, $95 = 0, $96 = 0, $arrayidx211 = 0, $97 = 0, $pp212 = 0, $98 = 0, $call213 = 0, $cmp214 = 0, $_arrayidx183 = 0, $arrayidx183_ = 0, $ei_0_lcssa_ph = 0, $add223 = 0, $rem224 = 0, $pnl1p = 0, $99 = 0, $pnl0p = 0, $100 = 0, $pp229 = 0, $101 = 0, $pp230 = 0, $102 = 0, $pnl1p233 = 0, $103 = 0, $pp234 = 0, $104 = 0, $call235 = 0, $cmp236 = 0, $_ = 0, $_130 = 0, $lpnlp_0 = 0, $rpnlp_0 = 0, $cmp253 = 0, $105 = 0, $106 = 0, $arrayidx256 = 0, $107 = 0, $cmp257 = 0, $108 = 0, $arrayidx259 = 0, $109 = 0, $cmp260 = 0, $call262 = 0, $110 = 0, $cmp263 = 0, $call267 = 0, $111 = 0, $cmp268 = 0, $rtp278 = 0, $112 = 0, $tobool279 = 0, $mark284 = 0, $113 = 0, $cmp285 = 0, $_lcssa160 = 0, $114 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $sub_ptr_div = 0, $115 = 0, $rtp278_1 = 0, $116 = 0, $tobool279_1 = 0, $pnlp_0135 = 0, $pi_3134 = 0, $inc298 = 0, $link300 = 0, $117 = 0, $tobool296 = 0, $pn302 = 0, $118 = 0, $119 = 0, $pi_4133 = 0, $pnlp_1132 = 0, $arrayidx308 = 0, $pp309 = 0, $120 = 0, $121 = 0, $122 = 0, $link312 = 0, $123 = 0, $pi_4 = 0, $tobool306 = 0, $124 = 0, $ps314 = 0, $retval_0 = 0, $mark199_1 = 0, $125 = 0, $cmp200_1 = 0, $rtp_2 = 0, $126 = 0, $tobool194_2 = 0, $mark199_2 = 0, $127 = 0, $cmp200_2 = 0, $mark284_1 = 0, $128 = 0, $cmp285_1 = 0, $rtp278_2 = 0, $129 = 0, $tobool279_2 = 0, $mark284_2 = 0, $130 = 0, $cmp285_2 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p1 = __stackBase__ | 0;
+ $p2 = __stackBase__ + 16 | 0;
+ $p3 = __stackBase__ + 32 | 0;
+ $epnls = __stackBase__ + 48 | 0;
+ $pn = $polyp + 4 | 0;
+ $0 = HEAP32[$pn >> 2] | 0;
+ _growpnls($0);
+ HEAP32[1794] = 0;
+ HEAP32[234] = 0;
+ $1 = HEAP32[$pn >> 2] | 0;
+ $mul = $1 << 1;
+ _growdq($mul);
+ $2 = HEAP32[5090] | 0;
+ $div = ($2 | 0) / 2 & -1;
+ HEAP32[5088] = $div;
+ $sub = $div - 1 | 0;
+ HEAP32[5086] = $sub;
+ $3 = HEAP32[$pn >> 2] | 0;
+ $cmp154 = ($3 | 0) > 0;
+ $ps = $polyp | 0;
+ $4 = HEAP32[$ps >> 2] | 0;
+ if ($cmp154) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx8162 = $4 - 16 | 0;
+ $5 = $p2;
+ $6 = $arrayidx8162;
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ $_sink = -1;
+ $minpi_0_lcssa164 = -1;
+ label = 8;
+ break;
+ case 4:
+ $7 = HEAP32[$pn >> 2] | 0;
+ $8 = HEAP32[$ps >> 2] | 0;
+ $minx_0155 = +Infinity;
+ $minpi_0156 = -1;
+ $pi_0157 = 0;
+ $9 = $4;
+ label = 5;
+ break;
+ case 5:
+ $x = $9 + ($pi_0157 << 4) | 0;
+ $10 = +HEAPF64[$x >> 3];
+ $cmp3 = $minx_0155 > $10;
+ $minx_1 = $cmp3 ? $10 : $minx_0155;
+ $minpi_1 = $cmp3 ? $pi_0157 : $minpi_0156;
+ $inc = $pi_0157 + 1 | 0;
+ $cmp = ($inc | 0) < ($7 | 0);
+ if ($cmp) {
+ $minx_0155 = $minx_1;
+ $minpi_0156 = $minpi_1;
+ $pi_0157 = $inc;
+ $9 = $8;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $arrayidx8 = $8 + ($minpi_1 << 4) | 0;
+ $11 = $p2;
+ $12 = $arrayidx8;
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ $cmp9 = ($minpi_1 | 0) == 0;
+ if ($cmp9) {
+ label = 7;
+ break;
+ } else {
+ $_sink = $minpi_1;
+ $minpi_0_lcssa164 = $minpi_1;
+ label = 8;
+ break;
+ }
+ case 7:
+ $13 = HEAP32[$pn >> 2] | 0;
+ $_sink = $13;
+ $minpi_0_lcssa164 = 0;
+ label = 8;
+ break;
+ case 8:
+ $sub11 = $_sink - 1 | 0;
+ $14 = HEAP32[$ps >> 2] | 0;
+ $arrayidx14 = $14 + ($sub11 << 4) | 0;
+ $15 = $p1;
+ $16 = $arrayidx14;
+ HEAP32[$15 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ $17 = HEAP32[$pn >> 2] | 0;
+ $sub16 = $17 - 1 | 0;
+ $cmp17 = ($minpi_0_lcssa164 | 0) == ($sub16 | 0);
+ $add = $minpi_0_lcssa164 + 1 | 0;
+ $_add = $cmp17 ? 0 : $add;
+ $18 = HEAP32[$ps >> 2] | 0;
+ $arrayidx23 = $18 + ($_add << 4) | 0;
+ $19 = $p3;
+ $20 = $arrayidx23;
+ HEAP32[$19 >> 2] = HEAP32[$20 >> 2] | 0;
+ HEAP32[$19 + 4 >> 2] = HEAP32[$20 + 4 >> 2] | 0;
+ HEAP32[$19 + 8 >> 2] = HEAP32[$20 + 8 >> 2] | 0;
+ HEAP32[$19 + 12 >> 2] = HEAP32[$20 + 12 >> 2] | 0;
+ $x24 = $p1 | 0;
+ $21 = +HEAPF64[$x24 >> 3];
+ $x25 = $p2 | 0;
+ $22 = +HEAPF64[$x25 >> 3];
+ $cmp26 = $21 == $22;
+ if ($cmp26) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $x28 = $p3 | 0;
+ $23 = +HEAPF64[$x28 >> 3];
+ $cmp29 = $22 == $23;
+ if ($cmp29) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $y = $p3 + 8 | 0;
+ $24 = +HEAPF64[$y >> 3];
+ $y31 = $p2 + 8 | 0;
+ $25 = +HEAPF64[$y31 >> 3];
+ $cmp32 = $24 > $25;
+ if ($cmp32) {
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call = _ccw($p1, $p2, $p3) | 0;
+ $cmp33 = ($call | 0) == 1;
+ if ($cmp33) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $26 = HEAP32[$pn >> 2] | 0;
+ $cmp76150 = ($26 | 0) > 0;
+ if ($cmp76150) {
+ $pi_2151 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 13:
+ $27 = HEAP32[$pn >> 2] | 0;
+ $cmp38146 = ($27 | 0) > 0;
+ if ($cmp38146) {
+ $pi_1148_in = $27;
+ label = 14;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 14:
+ $pi_1148 = $pi_1148_in - 1 | 0;
+ $28 = HEAP32[$pn >> 2] | 0;
+ $sub41 = $28 - 1 | 0;
+ $cmp42 = ($pi_1148 | 0) < ($sub41 | 0);
+ if ($cmp42) {
+ label = 15;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 15:
+ $29 = HEAP32[$ps >> 2] | 0;
+ $x46 = $29 + ($pi_1148 << 4) | 0;
+ $30 = +HEAPF64[$x46 >> 3];
+ $x50 = $29 + ($pi_1148_in << 4) | 0;
+ $31 = +HEAPF64[$x50 >> 3];
+ $cmp51 = $30 == $31;
+ if ($cmp51) {
+ label = 16;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 16:
+ $y55 = $29 + ($pi_1148 << 4) + 8 | 0;
+ $32 = +HEAPF64[$y55 >> 3];
+ $y59 = $29 + ($pi_1148_in << 4) + 8 | 0;
+ $33 = +HEAPF64[$y59 >> 3];
+ $cmp60 = $32 == $33;
+ if ($cmp60) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $cmp38 = ($pi_1148 | 0) > 0;
+ if ($cmp38) {
+ $pi_1148_in = $pi_1148;
+ label = 14;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 18:
+ $34 = HEAP32[$ps >> 2] | 0;
+ $arrayidx64 = $34 + ($pi_1148 << 4) | 0;
+ $35 = HEAP32[1794] | 0;
+ $36 = HEAP32[1788] | 0;
+ $pp = $36 + ($35 << 3) | 0;
+ HEAP32[$pp >> 2] = $arrayidx64;
+ $37 = HEAP32[1794] | 0;
+ $38 = HEAP32[$pn >> 2] | 0;
+ $rem = ($37 | 0) % ($38 | 0);
+ $39 = HEAP32[1788] | 0;
+ $arrayidx67 = $39 + ($rem << 3) | 0;
+ $link = $39 + ($37 << 3) + 4 | 0;
+ HEAP32[$link >> 2] = $arrayidx67;
+ $40 = HEAP32[1794] | 0;
+ $41 = HEAP32[1788] | 0;
+ $arrayidx69 = $41 + ($40 << 3) | 0;
+ $42 = HEAP32[1790] | 0;
+ $arrayidx70 = $42 + ($40 << 2) | 0;
+ HEAP32[$arrayidx70 >> 2] = $arrayidx69;
+ $43 = HEAP32[1794] | 0;
+ $inc71 = $43 + 1 | 0;
+ HEAP32[1794] = $inc71;
+ label = 17;
+ break;
+ case 19:
+ $cmp78 = ($pi_2151 | 0) > 0;
+ if ($cmp78) {
+ label = 20;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 20:
+ $44 = HEAP32[$ps >> 2] | 0;
+ $x82 = $44 + ($pi_2151 << 4) | 0;
+ $45 = +HEAPF64[$x82 >> 3];
+ $sub83 = $pi_2151 - 1 | 0;
+ $x86 = $44 + ($sub83 << 4) | 0;
+ $46 = +HEAPF64[$x86 >> 3];
+ $cmp87 = $45 == $46;
+ if ($cmp87) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $y91 = $44 + ($pi_2151 << 4) + 8 | 0;
+ $47 = +HEAPF64[$y91 >> 3];
+ $y95 = $44 + ($sub83 << 4) + 8 | 0;
+ $48 = +HEAPF64[$y95 >> 3];
+ $cmp96 = $47 == $48;
+ if ($cmp96) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $49 = HEAP32[$ps >> 2] | 0;
+ $arrayidx100 = $49 + ($pi_2151 << 4) | 0;
+ $50 = HEAP32[1794] | 0;
+ $51 = HEAP32[1788] | 0;
+ $pp102 = $51 + ($50 << 3) | 0;
+ HEAP32[$pp102 >> 2] = $arrayidx100;
+ $52 = HEAP32[1794] | 0;
+ $53 = HEAP32[$pn >> 2] | 0;
+ $rem104 = ($52 | 0) % ($53 | 0);
+ $54 = HEAP32[1788] | 0;
+ $arrayidx105 = $54 + ($rem104 << 3) | 0;
+ $link107 = $54 + ($52 << 3) + 4 | 0;
+ HEAP32[$link107 >> 2] = $arrayidx105;
+ $55 = HEAP32[1794] | 0;
+ $56 = HEAP32[1788] | 0;
+ $arrayidx108 = $56 + ($55 << 3) | 0;
+ $57 = HEAP32[1790] | 0;
+ $arrayidx109 = $57 + ($55 << 2) | 0;
+ HEAP32[$arrayidx109 >> 2] = $arrayidx108;
+ $58 = HEAP32[1794] | 0;
+ $inc110 = $58 + 1 | 0;
+ HEAP32[1794] = $inc110;
+ label = 23;
+ break;
+ case 23:
+ $inc112 = $pi_2151 + 1 | 0;
+ $59 = HEAP32[$pn >> 2] | 0;
+ $cmp76 = ($inc112 | 0) < ($59 | 0);
+ if ($cmp76) {
+ $pi_2151 = $inc112;
+ label = 19;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $60 = HEAP32[1790] | 0;
+ $61 = HEAP32[1794] | 0;
+ _triangulate($60, $61);
+ $62 = HEAP32[234] | 0;
+ $cmp116143 = ($62 | 0) > 0;
+ if ($cmp116143) {
+ $trii_0144 = 0;
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $63 = HEAP32[234] | 0;
+ $cmp116 = ($add118 | 0) < ($63 | 0);
+ if ($cmp116) {
+ $trii_0144 = $add118;
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $64 = HEAP32[234] | 0;
+ $trii_1 = 0;
+ label = 29;
+ break;
+ case 27:
+ $add118 = $trii_0144 + 1 | 0;
+ $65 = HEAP32[234] | 0;
+ $cmp120141 = ($add118 | 0) < ($65 | 0);
+ if ($cmp120141) {
+ $trij_0142 = $add118;
+ label = 28;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 28:
+ _connecttris($trii_0144, $trij_0142);
+ $inc123 = $trij_0142 + 1 | 0;
+ $66 = HEAP32[234] | 0;
+ $cmp120 = ($inc123 | 0) < ($66 | 0);
+ if ($cmp120) {
+ $trij_0142 = $inc123;
+ label = 28;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 29:
+ $cmp129 = ($trii_1 | 0) < ($64 | 0);
+ if ($cmp129) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $call132 = _pointintri($trii_1, $eps) | 0;
+ $tobool = ($call132 | 0) == 0;
+ $inc136 = $trii_1 + 1 | 0;
+ if ($tobool) {
+ $trii_1 = $inc136;
+ label = 29;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $67 = HEAP32[234] | 0;
+ $cmp138 = ($trii_1 | 0) == ($67 | 0);
+ if ($cmp138) {
+ label = 33;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $arrayidx145 = $eps + 16 | 0;
+ $68 = HEAP32[234] | 0;
+ $trii_2 = 0;
+ label = 34;
+ break;
+ case 33:
+ $69 = HEAP32[_stderr >> 2] | 0;
+ $call140 = _fprintf($69 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 183, HEAP32[tempInt + 16 >> 2] = 120496, tempInt) | 0) | 0;
+ $retval_0 = -1;
+ label = 64;
+ break;
+ case 34:
+ $cmp143 = ($trii_2 | 0) < ($68 | 0);
+ if ($cmp143) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ $call146 = _pointintri($trii_2, $arrayidx145) | 0;
+ $tobool147 = ($call146 | 0) == 0;
+ $inc151 = $trii_2 + 1 | 0;
+ if ($tobool147) {
+ $trii_2 = $inc151;
+ label = 34;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $70 = HEAP32[234] | 0;
+ $cmp153 = ($trii_2 | 0) == ($70 | 0);
+ if ($cmp153) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ $71 = HEAP32[_stderr >> 2] | 0;
+ $call155 = _fprintf($71 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 191, HEAP32[tempInt + 16 >> 2] = 114416, tempInt) | 0) | 0;
+ $retval_0 = -1;
+ label = 64;
+ break;
+ case 38:
+ $call157 = _marktripath($trii_1, $trii_2) | 0;
+ $tobool158 = ($call157 | 0) == 0;
+ if ($tobool158) {
+ label = 39;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 39:
+ $72 = HEAP32[_stderr >> 2] | 0;
+ $call160 = _fprintf($72 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 198, HEAP32[tempInt + 16 >> 2] = 112096, tempInt) | 0) | 0;
+ _growops13(2);
+ $pn161 = $output + 4 | 0;
+ HEAP32[$pn161 >> 2] = 2;
+ $73 = HEAP32[2284] | 0;
+ $74 = $73;
+ $75 = $eps;
+ HEAP32[$74 >> 2] = HEAP32[$75 >> 2] | 0;
+ HEAP32[$74 + 4 >> 2] = HEAP32[$75 + 4 >> 2] | 0;
+ HEAP32[$74 + 8 >> 2] = HEAP32[$75 + 8 >> 2] | 0;
+ HEAP32[$74 + 12 >> 2] = HEAP32[$75 + 12 >> 2] | 0;
+ $76 = HEAP32[2284] | 0;
+ $arrayidx164 = $76 + 16 | 0;
+ $arrayidx165 = $eps + 16 | 0;
+ $77 = $arrayidx164;
+ $78 = $arrayidx165;
+ HEAP32[$77 >> 2] = HEAP32[$78 >> 2] | 0;
+ HEAP32[$77 + 4 >> 2] = HEAP32[$78 + 4 >> 2] | 0;
+ HEAP32[$77 + 8 >> 2] = HEAP32[$78 + 8 >> 2] | 0;
+ HEAP32[$77 + 12 >> 2] = HEAP32[$78 + 12 >> 2] | 0;
+ $79 = HEAP32[2284] | 0;
+ $ps166 = $output | 0;
+ HEAP32[$ps166 >> 2] = $79;
+ $retval_0 = 0;
+ label = 64;
+ break;
+ case 40:
+ $cmp168 = ($trii_1 | 0) == ($trii_2 | 0);
+ if ($cmp168) {
+ label = 41;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 41:
+ _growops13(2);
+ $pn170 = $output + 4 | 0;
+ HEAP32[$pn170 >> 2] = 2;
+ $80 = HEAP32[2284] | 0;
+ $81 = $80;
+ $82 = $eps;
+ HEAP32[$81 >> 2] = HEAP32[$82 >> 2] | 0;
+ HEAP32[$81 + 4 >> 2] = HEAP32[$82 + 4 >> 2] | 0;
+ HEAP32[$81 + 8 >> 2] = HEAP32[$82 + 8 >> 2] | 0;
+ HEAP32[$81 + 12 >> 2] = HEAP32[$82 + 12 >> 2] | 0;
+ $83 = HEAP32[2284] | 0;
+ $arrayidx173 = $83 + 16 | 0;
+ $arrayidx174 = $eps + 16 | 0;
+ $84 = $arrayidx173;
+ $85 = $arrayidx174;
+ HEAP32[$84 >> 2] = HEAP32[$85 >> 2] | 0;
+ HEAP32[$84 + 4 >> 2] = HEAP32[$85 + 4 >> 2] | 0;
+ HEAP32[$84 + 8 >> 2] = HEAP32[$85 + 8 >> 2] | 0;
+ HEAP32[$84 + 12 >> 2] = HEAP32[$85 + 12 >> 2] | 0;
+ $86 = HEAP32[2284] | 0;
+ $ps175 = $output | 0;
+ HEAP32[$ps175 >> 2] = $86;
+ $retval_0 = 0;
+ label = 64;
+ break;
+ case 42:
+ $arrayidx178 = $epnls | 0;
+ $pp179 = $epnls | 0;
+ HEAP32[$pp179 >> 2] = $eps;
+ $link181 = $epnls + 4 | 0;
+ HEAP32[$link181 >> 2] = 0;
+ $arrayidx182 = $eps + 16 | 0;
+ $arrayidx183 = $epnls + 8 | 0;
+ $pp184 = $arrayidx183 | 0;
+ HEAP32[$pp184 >> 2] = $arrayidx182;
+ $link186 = $epnls + 12 | 0;
+ HEAP32[$link186 >> 2] = 0;
+ _add2dq(1, $arrayidx178);
+ $87 = HEAP32[5088] | 0;
+ HEAP32[5084] = $87;
+ $cmp188139 = ($trii_1 | 0) == -1;
+ if ($cmp188139) {
+ $pi_3134 = 0;
+ $pnlp_0135 = $arrayidx183;
+ label = 60;
+ break;
+ } else {
+ $trii_3140 = $trii_1;
+ label = 43;
+ break;
+ }
+ case 43:
+ $88 = HEAP32[230] | 0;
+ $mark = $88 + ($trii_3140 * 52 & -1) | 0;
+ HEAP32[$mark >> 2] = 2;
+ $rtp = $88 + ($trii_3140 * 52 & -1) + 16 | 0;
+ $89 = HEAP32[$rtp >> 2] | 0;
+ $tobool194 = ($89 | 0) == 0;
+ if ($tobool194) {
+ label = 45;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $mark199 = $89 | 0;
+ $90 = HEAP32[$mark199 >> 2] | 0;
+ $cmp200 = ($90 | 0) == 1;
+ if ($cmp200) {
+ $ei_0_lcssa_ph = 0;
+ label = 47;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $rtp_1 = $88 + ($trii_3140 * 52 & -1) + 32 | 0;
+ $91 = HEAP32[$rtp_1 >> 2] | 0;
+ $tobool194_1 = ($91 | 0) == 0;
+ if ($tobool194_1) {
+ label = 66;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 46:
+ $92 = HEAP32[5088] | 0;
+ $93 = HEAP32[5092] | 0;
+ $arrayidx209 = $93 + ($92 << 2) | 0;
+ $94 = HEAP32[$arrayidx209 >> 2] | 0;
+ $pp210 = $94 | 0;
+ $95 = HEAP32[$pp210 >> 2] | 0;
+ $96 = HEAP32[5086] | 0;
+ $arrayidx211 = $93 + ($96 << 2) | 0;
+ $97 = HEAP32[$arrayidx211 >> 2] | 0;
+ $pp212 = $97 | 0;
+ $98 = HEAP32[$pp212 >> 2] | 0;
+ $call213 = _ccw($arrayidx182, $95, $98) | 0;
+ $cmp214 = ($call213 | 0) == 1;
+ $_arrayidx183 = $cmp214 ? $97 : $arrayidx183;
+ $arrayidx183_ = $cmp214 ? $arrayidx183 : $97;
+ $rpnlp_0 = $arrayidx183_;
+ $lpnlp_0 = $_arrayidx183;
+ label = 48;
+ break;
+ case 47:
+ $add223 = $ei_0_lcssa_ph + 1 | 0;
+ $rem224 = ($add223 >>> 0) % 3;
+ $pnl1p = $88 + ($trii_3140 * 52 & -1) + 4 + ($rem224 << 4) + 4 | 0;
+ $99 = HEAP32[$pnl1p >> 2] | 0;
+ $pnl0p = $88 + ($trii_3140 * 52 & -1) + 4 + ($ei_0_lcssa_ph << 4) | 0;
+ $100 = HEAP32[$pnl0p >> 2] | 0;
+ $pp229 = $100 | 0;
+ $101 = HEAP32[$pp229 >> 2] | 0;
+ $pp230 = $99 | 0;
+ $102 = HEAP32[$pp230 >> 2] | 0;
+ $pnl1p233 = $88 + ($trii_3140 * 52 & -1) + 4 + ($ei_0_lcssa_ph << 4) + 4 | 0;
+ $103 = HEAP32[$pnl1p233 >> 2] | 0;
+ $pp234 = $103 | 0;
+ $104 = HEAP32[$pp234 >> 2] | 0;
+ $call235 = _ccw($101, $102, $104) | 0;
+ $cmp236 = ($call235 | 0) == 1;
+ $_ = $cmp236 ? $103 : $100;
+ $_130 = $cmp236 ? $100 : $103;
+ $rpnlp_0 = $_130;
+ $lpnlp_0 = $_;
+ label = 48;
+ break;
+ case 48:
+ $cmp253 = ($trii_3140 | 0) == ($trii_1 | 0);
+ if ($cmp253) {
+ label = 49;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 49:
+ _add2dq(2, $lpnlp_0);
+ _add2dq(1, $rpnlp_0);
+ label = 56;
+ break;
+ case 50:
+ $105 = HEAP32[5088] | 0;
+ $106 = HEAP32[5092] | 0;
+ $arrayidx256 = $106 + ($105 << 2) | 0;
+ $107 = HEAP32[$arrayidx256 >> 2] | 0;
+ $cmp257 = ($107 | 0) == ($rpnlp_0 | 0);
+ if ($cmp257) {
+ label = 54;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $108 = HEAP32[5086] | 0;
+ $arrayidx259 = $106 + ($108 << 2) | 0;
+ $109 = HEAP32[$arrayidx259 >> 2] | 0;
+ $cmp260 = ($109 | 0) == ($rpnlp_0 | 0);
+ if ($cmp260) {
+ label = 54;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $call262 = _finddqsplit($rpnlp_0) | 0;
+ _splitdq(2, $call262);
+ _add2dq(1, $rpnlp_0);
+ $110 = HEAP32[5084] | 0;
+ $cmp263 = ($call262 | 0) > ($110 | 0);
+ if ($cmp263) {
+ label = 53;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 53:
+ HEAP32[5084] = $call262;
+ label = 56;
+ break;
+ case 54:
+ $call267 = _finddqsplit($lpnlp_0) | 0;
+ _splitdq(1, $call267);
+ _add2dq(2, $lpnlp_0);
+ $111 = HEAP32[5084] | 0;
+ $cmp268 = ($call267 | 0) < ($111 | 0);
+ if ($cmp268) {
+ label = 55;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 55:
+ HEAP32[5084] = $call267;
+ label = 56;
+ break;
+ case 56:
+ $rtp278 = $88 + ($trii_3140 * 52 & -1) + 16 | 0;
+ $112 = HEAP32[$rtp278 >> 2] | 0;
+ $tobool279 = ($112 | 0) == 0;
+ if ($tobool279) {
+ label = 59;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $mark284 = $112 | 0;
+ $113 = HEAP32[$mark284 >> 2] | 0;
+ $cmp285 = ($113 | 0) == 1;
+ if ($cmp285) {
+ $_lcssa160 = $112;
+ label = 58;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 58:
+ $114 = HEAP32[230] | 0;
+ $sub_ptr_lhs_cast = $_lcssa160;
+ $sub_ptr_rhs_cast = $114;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $sub_ptr_div = ($sub_ptr_sub | 0) / 52 & -1;
+ $115 = ($sub_ptr_sub | 0) == -52;
+ if ($115) {
+ $pi_3134 = 0;
+ $pnlp_0135 = $arrayidx183;
+ label = 60;
+ break;
+ } else {
+ $trii_3140 = $sub_ptr_div;
+ label = 43;
+ break;
+ }
+ case 59:
+ $rtp278_1 = $88 + ($trii_3140 * 52 & -1) + 32 | 0;
+ $116 = HEAP32[$rtp278_1 >> 2] | 0;
+ $tobool279_1 = ($116 | 0) == 0;
+ if ($tobool279_1) {
+ label = 69;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 60:
+ $inc298 = $pi_3134 + 1 | 0;
+ $link300 = $pnlp_0135 + 4 | 0;
+ $117 = HEAP32[$link300 >> 2] | 0;
+ $tobool296 = ($117 | 0) == 0;
+ if ($tobool296) {
+ label = 61;
+ break;
+ } else {
+ $pi_3134 = $inc298;
+ $pnlp_0135 = $117;
+ label = 60;
+ break;
+ }
+ case 61:
+ _growops13($inc298);
+ $pn302 = $output + 4 | 0;
+ HEAP32[$pn302 >> 2] = $inc298;
+ $118 = HEAP32[2284] | 0;
+ $pnlp_1132 = $arrayidx183;
+ $pi_4133 = $pi_3134;
+ $119 = $118;
+ label = 62;
+ break;
+ case 62:
+ $arrayidx308 = $119 + ($pi_4133 << 4) | 0;
+ $pp309 = $pnlp_1132 | 0;
+ $120 = HEAP32[$pp309 >> 2] | 0;
+ $121 = $arrayidx308;
+ $122 = $120;
+ HEAP32[$121 >> 2] = HEAP32[$122 >> 2] | 0;
+ HEAP32[$121 + 4 >> 2] = HEAP32[$122 + 4 >> 2] | 0;
+ HEAP32[$121 + 8 >> 2] = HEAP32[$122 + 8 >> 2] | 0;
+ HEAP32[$121 + 12 >> 2] = HEAP32[$122 + 12 >> 2] | 0;
+ $link312 = $pnlp_1132 + 4 | 0;
+ $123 = HEAP32[$link312 >> 2] | 0;
+ $pi_4 = $pi_4133 - 1 | 0;
+ $tobool306 = ($123 | 0) == 0;
+ $124 = HEAP32[2284] | 0;
+ if ($tobool306) {
+ label = 63;
+ break;
+ } else {
+ $pnlp_1132 = $123;
+ $pi_4133 = $pi_4;
+ $119 = $124;
+ label = 62;
+ break;
+ }
+ case 63:
+ $ps314 = $output | 0;
+ HEAP32[$ps314 >> 2] = $124;
+ $retval_0 = 0;
+ label = 64;
+ break;
+ case 64:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ case 65:
+ $mark199_1 = $91 | 0;
+ $125 = HEAP32[$mark199_1 >> 2] | 0;
+ $cmp200_1 = ($125 | 0) == 1;
+ if ($cmp200_1) {
+ $ei_0_lcssa_ph = 1;
+ label = 47;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ $rtp_2 = $88 + ($trii_3140 * 52 & -1) + 48 | 0;
+ $126 = HEAP32[$rtp_2 >> 2] | 0;
+ $tobool194_2 = ($126 | 0) == 0;
+ if ($tobool194_2) {
+ label = 46;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 67:
+ $mark199_2 = $126 | 0;
+ $127 = HEAP32[$mark199_2 >> 2] | 0;
+ $cmp200_2 = ($127 | 0) == 1;
+ if ($cmp200_2) {
+ $ei_0_lcssa_ph = 2;
+ label = 47;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 68:
+ $mark284_1 = $116 | 0;
+ $128 = HEAP32[$mark284_1 >> 2] | 0;
+ $cmp285_1 = ($128 | 0) == 1;
+ if ($cmp285_1) {
+ $_lcssa160 = $116;
+ label = 58;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 69:
+ $rtp278_2 = $88 + ($trii_3140 * 52 & -1) + 48 | 0;
+ $129 = HEAP32[$rtp278_2 >> 2] | 0;
+ $tobool279_2 = ($129 | 0) == 0;
+ if ($tobool279_2) {
+ $pi_3134 = 0;
+ $pnlp_0135 = $arrayidx183;
+ label = 60;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $mark284_2 = $129 | 0;
+ $130 = HEAP32[$mark284_2 >> 2] | 0;
+ $cmp285_2 = ($130 | 0) == 1;
+ if ($cmp285_2) {
+ $_lcssa160 = $129;
+ label = 58;
+ break;
+ } else {
+ $pi_3134 = 0;
+ $pnlp_0135 = $arrayidx183;
+ label = 60;
+ break;
+ }
+ }
+ return 0;
+}
+function _triangulate($pnlps, $pnln) {
+ $pnlps = $pnlps | 0;
+ $pnln = $pnln | 0;
+ var $cmp29 = 0, $cmp = 0, $pnln_tr30 = 0, $pnli_0 = 0, $cmp1 = 0, $add = 0, $rem = 0, $add2 = 0, $rem3 = 0, $call = 0, $tobool = 0, $arrayidx = 0, $0 = 0, $arrayidx5 = 0, $1 = 0, $arrayidx6 = 0, $2 = 0, $sub = 0, $cmp827 = 0, $pnli_128 = 0, $add10 = 0, $arrayidx11 = 0, $3 = 0, $arrayidx12 = 0, $cmp8 = 0, $4 = 0, $call17 = 0, $5 = 0, $arrayidx19 = 0, $6 = 0, $arrayidx20 = 0, $7 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp29 = ($pnln | 0) > 3;
+ if ($cmp29) {
+ $pnln_tr30 = $pnln;
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $cmp = ($sub | 0) > 3;
+ if ($cmp) {
+ $pnln_tr30 = $sub;
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 4:
+ $pnli_0 = 0;
+ label = 5;
+ break;
+ case 5:
+ $cmp1 = ($pnli_0 | 0) < ($pnln_tr30 | 0);
+ if ($cmp1) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 6:
+ $add = $pnli_0 + 1 | 0;
+ $rem = ($add | 0) % ($pnln_tr30 | 0);
+ $add2 = $pnli_0 + 2 | 0;
+ $rem3 = ($add2 | 0) % ($pnln_tr30 | 0);
+ $call = _isdiagonal($pnli_0, $rem3, $pnlps, $pnln_tr30) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $pnli_0 = $add;
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $arrayidx = $pnlps + ($pnli_0 << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $arrayidx5 = $pnlps + ($rem << 2) | 0;
+ $1 = HEAP32[$arrayidx5 >> 2] | 0;
+ $arrayidx6 = $pnlps + ($rem3 << 2) | 0;
+ $2 = HEAP32[$arrayidx6 >> 2] | 0;
+ _loadtriangle($0, $1, $2);
+ $sub = $pnln_tr30 - 1 | 0;
+ $cmp827 = ($rem | 0) < ($sub | 0);
+ if ($cmp827) {
+ $pnli_128 = $rem;
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 8:
+ $add10 = $pnli_128 + 1 | 0;
+ $arrayidx11 = $pnlps + ($add10 << 2) | 0;
+ $3 = HEAP32[$arrayidx11 >> 2] | 0;
+ $arrayidx12 = $pnlps + ($pnli_128 << 2) | 0;
+ HEAP32[$arrayidx12 >> 2] = $3;
+ $cmp8 = ($add10 | 0) < ($sub | 0);
+ if ($cmp8) {
+ $pnli_128 = $add10;
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 9:
+ $4 = HEAP32[_stderr >> 2] | 0;
+ $call17 = _fprintf($4 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 315, HEAP32[tempInt + 16 >> 2] = 152464, tempInt) | 0) | 0;
+ label = 11;
+ break;
+ case 10:
+ $5 = HEAP32[$pnlps >> 2] | 0;
+ $arrayidx19 = $pnlps + 4 | 0;
+ $6 = HEAP32[$arrayidx19 >> 2] | 0;
+ $arrayidx20 = $pnlps + 8 | 0;
+ $7 = HEAP32[$arrayidx20 >> 2] | 0;
+ _loadtriangle($5, $6, $7);
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _growpnls($newpnln) {
+ $newpnln = $newpnln | 0;
+ var $0 = 0, $cmp = 0, $1 = 0, $tobool = 0, $mul = 0, $call = 0, $2 = 0, $tobool2 = 0, $3 = 0, $call4 = 0, $mul6 = 0, $call7 = 0, $4 = 0, $tobool8 = 0, $5 = 0, $call10 = 0, $6 = 0, $mul12 = 0, $call13 = 0, $7 = 0, $tobool14 = 0, $8 = 0, $call16 = 0, $9 = 0, $10 = 0, $mul18 = 0, $call19 = 0, $11 = 0, $tobool20 = 0, $12 = 0, $call22 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[1792] | 0;
+ $cmp = ($0 | 0) < ($newpnln | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[1788] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $mul = $newpnln << 3;
+ $call = _malloc($mul) | 0;
+ $2 = $call;
+ HEAP32[1788] = $2;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $3 = HEAP32[_stderr >> 2] | 0;
+ $call4 = _fprintf($3 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 514, HEAP32[tempInt + 16 >> 2] = 92152, tempInt) | 0) | 0;
+ _abort();
+ case 6:
+ $mul6 = $newpnln << 2;
+ $call7 = _malloc($mul6) | 0;
+ $4 = $call7;
+ HEAP32[1790] = $4;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 7:
+ $5 = HEAP32[_stderr >> 2] | 0;
+ $call10 = _fprintf($5 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 518, HEAP32[tempInt + 16 >> 2] = 162288, tempInt) | 0) | 0;
+ _abort();
+ case 8:
+ $6 = $1;
+ $mul12 = $newpnln << 3;
+ $call13 = _realloc($6, $mul12) | 0;
+ $7 = $call13;
+ HEAP32[1788] = $7;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $8 = HEAP32[_stderr >> 2] | 0;
+ $call16 = _fprintf($8 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 524, HEAP32[tempInt + 16 >> 2] = 158744, tempInt) | 0) | 0;
+ _abort();
+ case 10:
+ $9 = HEAP32[1790] | 0;
+ $10 = $9;
+ $mul18 = $newpnln << 2;
+ $call19 = _realloc($10, $mul18) | 0;
+ $11 = $call19;
+ HEAP32[1790] = $11;
+ $tobool20 = ($call19 | 0) == 0;
+ if ($tobool20) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $12 = HEAP32[_stderr >> 2] | 0;
+ $call22 = _fprintf($12 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 530, HEAP32[tempInt + 16 >> 2] = 155264, tempInt) | 0) | 0;
+ _abort();
+ case 12:
+ HEAP32[1792] = $newpnln;
+ label = 13;
+ break;
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _growdq($newdqn) {
+ $newdqn = $newdqn | 0;
+ var $0 = 0, $cmp = 0, $1 = 0, $tobool = 0, $mul = 0, $call = 0, $2 = 0, $tobool2 = 0, $3 = 0, $call4 = 0, $4 = 0, $mul6 = 0, $call7 = 0, $5 = 0, $tobool8 = 0, $6 = 0, $call10 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[5090] | 0;
+ $cmp = ($0 | 0) < ($newdqn | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[5092] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $mul = $newdqn << 2;
+ $call = _malloc($mul) | 0;
+ $2 = $call;
+ HEAP32[5092] = $2;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $3 = HEAP32[_stderr >> 2] | 0;
+ $call4 = _fprintf($3 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 564, HEAP32[tempInt + 16 >> 2] = 99600, tempInt) | 0) | 0;
+ _abort();
+ case 6:
+ $4 = $1;
+ $mul6 = $newdqn << 2;
+ $call7 = _realloc($4, $mul6) | 0;
+ $5 = $call7;
+ HEAP32[5092] = $5;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $6 = HEAP32[_stderr >> 2] | 0;
+ $call10 = _fprintf($6 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 571, HEAP32[tempInt + 16 >> 2] = 95608, tempInt) | 0) | 0;
+ _abort();
+ case 8:
+ HEAP32[5090] = $newdqn;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _splitdq($side, $index) {
+ $side = $side | 0;
+ $index = $index | 0;
+ var $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($side | 0) == 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[5086] = $index;
+ label = 5;
+ break;
+ case 4:
+ HEAP32[5088] = $index;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _add2dq($side, $pnlp) {
+ $side = $side | 0;
+ $pnlp = $pnlp | 0;
+ var $cmp = 0, $0 = 0, $1 = 0, $sub = 0, $cmp1 = 0, $2 = 0, $arrayidx = 0, $3 = 0, $link = 0, $4 = 0, $dec = 0, $5 = 0, $arrayidx3 = 0, $6 = 0, $arrayidx7 = 0, $7 = 0, $link8 = 0, $8 = 0, $inc = 0, $9 = 0, $arrayidx10 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($side | 0) == 1;
+ $0 = HEAP32[5086] | 0;
+ $1 = HEAP32[5088] | 0;
+ $sub = $0 - $1 | 0;
+ $cmp1 = ($sub | 0) > -1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[5092] | 0;
+ $arrayidx = $2 + ($1 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $link = $pnlp + 4 | 0;
+ HEAP32[$link >> 2] = $3;
+ label = 5;
+ break;
+ case 5:
+ $4 = HEAP32[5088] | 0;
+ $dec = $4 - 1 | 0;
+ HEAP32[5088] = $dec;
+ $5 = HEAP32[5092] | 0;
+ $arrayidx3 = $5 + ($dec << 2) | 0;
+ HEAP32[$arrayidx3 >> 2] = $pnlp;
+ label = 9;
+ break;
+ case 6:
+ if ($cmp1) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $6 = HEAP32[5092] | 0;
+ $arrayidx7 = $6 + ($0 << 2) | 0;
+ $7 = HEAP32[$arrayidx7 >> 2] | 0;
+ $link8 = $pnlp + 4 | 0;
+ HEAP32[$link8 >> 2] = $7;
+ label = 8;
+ break;
+ case 8:
+ $8 = HEAP32[5086] | 0;
+ $inc = $8 + 1 | 0;
+ HEAP32[5086] = $inc;
+ $9 = HEAP32[5092] | 0;
+ $arrayidx10 = $9 + ($inc << 2) | 0;
+ HEAP32[$arrayidx10 >> 2] = $pnlp;
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _solve1($coeff, $roots) {
+ $coeff = $coeff | 0;
+ $roots = $roots | 0;
+ var $arrayidx = 0, $0 = 0.0, $1 = 0.0, $cmp = 0, $cmp2 = 0, $or_cond = 0, $cmp3 = 0, $cmp5 = 0, $or_cond1 = 0, $_ = 0, $sub = 0.0, $div = 0.0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $arrayidx = $coeff + 8 | 0;
+ $0 = +HEAPF64[$arrayidx >> 3];
+ $1 = +HEAPF64[$coeff >> 3];
+ $cmp = $0 < 1.0e-7;
+ $cmp2 = $0 > -1.0e-7;
+ $or_cond = $cmp & $cmp2;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $cmp3 = $1 < 1.0e-7;
+ $cmp5 = $1 > -1.0e-7;
+ $or_cond1 = $cmp3 & $cmp5;
+ $_ = $or_cond1 ? 4 : 0;
+ $retval_0 = $_;
+ label = 5;
+ break;
+ case 4:
+ $sub = -0.0 - $1;
+ $div = $sub / $0;
+ HEAPF64[$roots >> 3] = $div;
+ $retval_0 = 1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _pointintri($trii, $pp) {
+ $trii = $trii | 0;
+ $pp = $pp | 0;
+ var $0 = 0, $pnl0p = 0, $1 = 0, $pp2 = 0, $2 = 0, $pnl1p = 0, $3 = 0, $pp6 = 0, $4 = 0, $call = 0, $not_cmp7 = 0, $inc = 0, $pnl0p_1 = 0, $5 = 0, $pp2_1 = 0, $6 = 0, $pnl1p_1 = 0, $7 = 0, $pp6_1 = 0, $8 = 0, $call_1 = 0, $not_cmp7_1 = 0, $inc_1 = 0, $sum_0_inc_1 = 0, $pnl0p_2 = 0, $9 = 0, $pp2_2 = 0, $10 = 0, $pnl1p_2 = 0, $11 = 0, $pp6_2 = 0, $12 = 0, $call_2 = 0, $not_cmp7_2 = 0, $inc_2 = 0, $sum_0_inc_2 = 0, $cmp9 = 0, $cmp10 = 0, $phitmp = 0, $13 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[230] | 0;
+ $pnl0p = $0 + ($trii * 52 & -1) + 4 | 0;
+ $1 = HEAP32[$pnl0p >> 2] | 0;
+ $pp2 = $1 | 0;
+ $2 = HEAP32[$pp2 >> 2] | 0;
+ $pnl1p = $0 + ($trii * 52 & -1) + 8 | 0;
+ $3 = HEAP32[$pnl1p >> 2] | 0;
+ $pp6 = $3 | 0;
+ $4 = HEAP32[$pp6 >> 2] | 0;
+ $call = _ccw($2, $4, $pp) | 0;
+ $not_cmp7 = ($call | 0) != 2;
+ $inc = $not_cmp7 & 1;
+ $pnl0p_1 = $0 + ($trii * 52 & -1) + 20 | 0;
+ $5 = HEAP32[$pnl0p_1 >> 2] | 0;
+ $pp2_1 = $5 | 0;
+ $6 = HEAP32[$pp2_1 >> 2] | 0;
+ $pnl1p_1 = $0 + ($trii * 52 & -1) + 24 | 0;
+ $7 = HEAP32[$pnl1p_1 >> 2] | 0;
+ $pp6_1 = $7 | 0;
+ $8 = HEAP32[$pp6_1 >> 2] | 0;
+ $call_1 = _ccw($6, $8, $pp) | 0;
+ $not_cmp7_1 = ($call_1 | 0) != 2;
+ $inc_1 = $not_cmp7_1 & 1;
+ $sum_0_inc_1 = $inc_1 + $inc | 0;
+ $pnl0p_2 = $0 + ($trii * 52 & -1) + 36 | 0;
+ $9 = HEAP32[$pnl0p_2 >> 2] | 0;
+ $pp2_2 = $9 | 0;
+ $10 = HEAP32[$pp2_2 >> 2] | 0;
+ $pnl1p_2 = $0 + ($trii * 52 & -1) + 40 | 0;
+ $11 = HEAP32[$pnl1p_2 >> 2] | 0;
+ $pp6_2 = $11 | 0;
+ $12 = HEAP32[$pp6_2 >> 2] | 0;
+ $call_2 = _ccw($10, $12, $pp) | 0;
+ $not_cmp7_2 = ($call_2 | 0) != 2;
+ $inc_2 = $not_cmp7_2 & 1;
+ $sum_0_inc_2 = $inc_2 + $sum_0_inc_1 | 0;
+ $cmp9 = ($sum_0_inc_2 | 0) == 3;
+ if ($cmp9) {
+ $13 = 1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp10 = ($sum_0_inc_2 | 0) == 0;
+ $phitmp = $cmp10 & 1;
+ $13 = $phitmp;
+ label = 4;
+ break;
+ case 4:
+ return $13 | 0;
+ }
+ return 0;
+}
+function _marktripath($trii, $trij) {
+ $trii = $trii | 0;
+ $trij = $trij | 0;
+ var $0 = 0, $mark = 0, $1 = 0, $tobool = 0, $cmp = 0, $2 = 0, $rtp = 0, $3 = 0, $tobool8 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $sub_ptr_div = 0, $call = 0, $tobool13 = 0, $4 = 0, $rtp_1 = 0, $5 = 0, $tobool8_1 = 0, $retval_0 = 0, $sub_ptr_lhs_cast_1 = 0, $sub_ptr_rhs_cast_1 = 0, $sub_ptr_sub_1 = 0, $sub_ptr_div_1 = 0, $call_1 = 0, $tobool13_1 = 0, $6 = 0, $rtp_2 = 0, $7 = 0, $tobool8_2 = 0, $sub_ptr_lhs_cast_2 = 0, $sub_ptr_rhs_cast_2 = 0, $sub_ptr_sub_2 = 0, $sub_ptr_div_2 = 0, $call_2 = 0, $tobool13_2 = 0, $8 = 0, $mark17 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[230] | 0;
+ $mark = $0 + ($trii * 52 & -1) | 0;
+ $1 = HEAP32[$mark >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ }
+ case 3:
+ HEAP32[$mark >> 2] = 1;
+ $cmp = ($trii | 0) == ($trij | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[230] | 0;
+ $rtp = $2 + ($trii * 52 & -1) + 16 | 0;
+ $3 = HEAP32[$rtp >> 2] | 0;
+ $tobool8 = ($3 | 0) == 0;
+ if ($tobool8) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $sub_ptr_lhs_cast = $3;
+ $sub_ptr_rhs_cast = $2;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $sub_ptr_div = ($sub_ptr_sub | 0) / 52 & -1;
+ $call = _marktripath($sub_ptr_div, $trij) | 0;
+ $tobool13 = ($call | 0) == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ }
+ case 6:
+ $4 = HEAP32[230] | 0;
+ $rtp_1 = $4 + ($trii * 52 & -1) + 32 | 0;
+ $5 = HEAP32[$rtp_1 >> 2] | 0;
+ $tobool8_1 = ($5 | 0) == 0;
+ if ($tobool8_1) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ return $retval_0 | 0;
+ case 8:
+ $sub_ptr_lhs_cast_1 = $5;
+ $sub_ptr_rhs_cast_1 = $4;
+ $sub_ptr_sub_1 = $sub_ptr_lhs_cast_1 - $sub_ptr_rhs_cast_1 | 0;
+ $sub_ptr_div_1 = ($sub_ptr_sub_1 | 0) / 52 & -1;
+ $call_1 = _marktripath($sub_ptr_div_1, $trij) | 0;
+ $tobool13_1 = ($call_1 | 0) == 0;
+ if ($tobool13_1) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ }
+ case 9:
+ $6 = HEAP32[230] | 0;
+ $rtp_2 = $6 + ($trii * 52 & -1) + 48 | 0;
+ $7 = HEAP32[$rtp_2 >> 2] | 0;
+ $tobool8_2 = ($7 | 0) == 0;
+ if ($tobool8_2) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $sub_ptr_lhs_cast_2 = $7;
+ $sub_ptr_rhs_cast_2 = $6;
+ $sub_ptr_sub_2 = $sub_ptr_lhs_cast_2 - $sub_ptr_rhs_cast_2 | 0;
+ $sub_ptr_div_2 = ($sub_ptr_sub_2 | 0) / 52 & -1;
+ $call_2 = _marktripath($sub_ptr_div_2, $trij) | 0;
+ $tobool13_2 = ($call_2 | 0) == 0;
+ if ($tobool13_2) {
+ label = 11;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ }
+ case 11:
+ $8 = HEAP32[230] | 0;
+ $mark17 = $8 + ($trii * 52 & -1) | 0;
+ HEAP32[$mark17 >> 2] = 0;
+ $retval_0 = 0;
+ label = 7;
+ break;
+ }
+ return 0;
+}
+function _finddqsplit($pnlp) {
+ $pnlp = $pnlp | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $pp3 = 0, $index_0 = 0, $cmp = 0, $add = 0, $arrayidx = 0, $3 = 0, $pp = 0, $4 = 0, $arrayidx1 = 0, $5 = 0, $pp2 = 0, $6 = 0, $7 = 0, $call = 0, $cmp4 = 0, $8 = 0, $9 = 0, $10 = 0, $pp12 = 0, $index_1 = 0, $cmp6 = 0, $sub = 0, $arrayidx8 = 0, $11 = 0, $pp9 = 0, $12 = 0, $arrayidx10 = 0, $13 = 0, $pp11 = 0, $14 = 0, $15 = 0, $call13 = 0, $cmp14 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[5088] | 0;
+ $1 = HEAP32[5084] | 0;
+ $2 = HEAP32[5092] | 0;
+ $pp3 = $pnlp | 0;
+ $index_0 = $0;
+ label = 3;
+ break;
+ case 3:
+ $cmp = ($index_0 | 0) < ($1 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $add = $index_0 + 1 | 0;
+ $arrayidx = $2 + ($add << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $pp = $3 | 0;
+ $4 = HEAP32[$pp >> 2] | 0;
+ $arrayidx1 = $2 + ($index_0 << 2) | 0;
+ $5 = HEAP32[$arrayidx1 >> 2] | 0;
+ $pp2 = $5 | 0;
+ $6 = HEAP32[$pp2 >> 2] | 0;
+ $7 = HEAP32[$pp3 >> 2] | 0;
+ $call = _ccw($4, $6, $7) | 0;
+ $cmp4 = ($call | 0) == 1;
+ if ($cmp4) {
+ $retval_0 = $index_0;
+ label = 8;
+ break;
+ } else {
+ $index_0 = $add;
+ label = 3;
+ break;
+ }
+ case 5:
+ $8 = HEAP32[5086] | 0;
+ $9 = HEAP32[5084] | 0;
+ $10 = HEAP32[5092] | 0;
+ $pp12 = $pnlp | 0;
+ $index_1 = $8;
+ label = 6;
+ break;
+ case 6:
+ $cmp6 = ($index_1 | 0) > ($9 | 0);
+ if ($cmp6) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = $9;
+ label = 8;
+ break;
+ }
+ case 7:
+ $sub = $index_1 - 1 | 0;
+ $arrayidx8 = $10 + ($sub << 2) | 0;
+ $11 = HEAP32[$arrayidx8 >> 2] | 0;
+ $pp9 = $11 | 0;
+ $12 = HEAP32[$pp9 >> 2] | 0;
+ $arrayidx10 = $10 + ($index_1 << 2) | 0;
+ $13 = HEAP32[$arrayidx10 >> 2] | 0;
+ $pp11 = $13 | 0;
+ $14 = HEAP32[$pp11 >> 2] | 0;
+ $15 = HEAP32[$pp12 >> 2] | 0;
+ $call13 = _ccw($12, $14, $15) | 0;
+ $cmp14 = ($call13 | 0) == 2;
+ if ($cmp14) {
+ $retval_0 = $index_1;
+ label = 8;
+ break;
+ } else {
+ $index_1 = $sub;
+ label = 6;
+ break;
+ }
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _isdiagonal($pnli, $pnlip2, $pnlps, $pnln) {
+ $pnli = $pnli | 0;
+ $pnlip2 = $pnlip2 | 0;
+ $pnlps = $pnlps | 0;
+ $pnln = $pnln | 0;
+ var $add = 0, $rem = 0, $add1 = 0, $sub = 0, $rem2 = 0, $arrayidx = 0, $0 = 0, $pp = 0, $1 = 0, $arrayidx3 = 0, $2 = 0, $pp4 = 0, $3 = 0, $arrayidx5 = 0, $4 = 0, $pp6 = 0, $5 = 0, $call = 0, $cmp = 0, $arrayidx9 = 0, $6 = 0, $pp10 = 0, $7 = 0, $call13 = 0, $cmp14 = 0, $call29 = 0, $cmp30 = 0, $call21 = 0, $cmp22 = 0, $cmp3341 = 0, $pnlj_042 = 0, $add35 = 0, $8 = 0, $tmp = 0, $cmp37 = 0, $cmp39 = 0, $or_cond = 0, $cmp42 = 0, $or_cond39 = 0, $cmp45 = 0, $or_cond40 = 0, $9 = 0, $pp49 = 0, $10 = 0, $11 = 0, $pp51 = 0, $12 = 0, $arrayidx52 = 0, $13 = 0, $pp53 = 0, $14 = 0, $arrayidx54 = 0, $15 = 0, $pp55 = 0, $16 = 0, $call56 = 0, $tobool57 = 0, $cmp33 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add = $pnli + 1 | 0;
+ $rem = ($add | 0) % ($pnln | 0);
+ $add1 = $pnli - 1 | 0;
+ $sub = $add1 + $pnln | 0;
+ $rem2 = ($sub | 0) % ($pnln | 0);
+ $arrayidx = $pnlps + ($rem2 << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $pp = $0 | 0;
+ $1 = HEAP32[$pp >> 2] | 0;
+ $arrayidx3 = $pnlps + ($pnli << 2) | 0;
+ $2 = HEAP32[$arrayidx3 >> 2] | 0;
+ $pp4 = $2 | 0;
+ $3 = HEAP32[$pp4 >> 2] | 0;
+ $arrayidx5 = $pnlps + ($rem << 2) | 0;
+ $4 = HEAP32[$arrayidx5 >> 2] | 0;
+ $pp6 = $4 | 0;
+ $5 = HEAP32[$pp6 >> 2] | 0;
+ $call = _ccw($1, $3, $5) | 0;
+ $cmp = ($call | 0) == 1;
+ $arrayidx9 = $pnlps + ($pnlip2 << 2) | 0;
+ $6 = HEAP32[$arrayidx9 >> 2] | 0;
+ $pp10 = $6 | 0;
+ $7 = HEAP32[$pp10 >> 2] | 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call13 = _ccw($3, $7, $1) | 0;
+ $cmp14 = ($call13 | 0) == 1;
+ if ($cmp14) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ }
+ case 4:
+ $call29 = _ccw($3, $7, $5) | 0;
+ $cmp30 = ($call29 | 0) == 2;
+ if ($cmp30) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ }
+ case 5:
+ $call21 = _ccw($7, $3, $5) | 0;
+ $cmp22 = ($call21 | 0) == 1;
+ if ($cmp22) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ }
+ case 6:
+ $cmp3341 = ($pnln | 0) > 0;
+ if ($cmp3341) {
+ $pnlj_042 = 0;
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ }
+ case 7:
+ $add35 = $pnlj_042 + 1 | 0;
+ $8 = ($add35 | 0) == ($pnln | 0);
+ $tmp = $8 ? 0 : $add35;
+ $cmp37 = ($pnlj_042 | 0) == ($pnli | 0);
+ $cmp39 = ($tmp | 0) == ($pnli | 0);
+ $or_cond = $cmp37 | $cmp39;
+ $cmp42 = ($pnlj_042 | 0) == ($pnlip2 | 0);
+ $or_cond39 = $or_cond | $cmp42;
+ $cmp45 = ($tmp | 0) == ($pnlip2 | 0);
+ $or_cond40 = $or_cond39 | $cmp45;
+ if ($or_cond40) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $9 = HEAP32[$arrayidx3 >> 2] | 0;
+ $pp49 = $9 | 0;
+ $10 = HEAP32[$pp49 >> 2] | 0;
+ $11 = HEAP32[$arrayidx9 >> 2] | 0;
+ $pp51 = $11 | 0;
+ $12 = HEAP32[$pp51 >> 2] | 0;
+ $arrayidx52 = $pnlps + ($pnlj_042 << 2) | 0;
+ $13 = HEAP32[$arrayidx52 >> 2] | 0;
+ $pp53 = $13 | 0;
+ $14 = HEAP32[$pp53 >> 2] | 0;
+ $arrayidx54 = $pnlps + ($tmp << 2) | 0;
+ $15 = HEAP32[$arrayidx54 >> 2] | 0;
+ $pp55 = $15 | 0;
+ $16 = HEAP32[$pp55 >> 2] | 0;
+ $call56 = _intersects($10, $12, $14, $16) | 0;
+ $tobool57 = ($call56 | 0) == 0;
+ if ($tobool57) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 10;
+ break;
+ }
+ case 9:
+ $cmp33 = ($add35 | 0) < ($pnln | 0);
+ if ($cmp33) {
+ $pnlj_042 = $add35;
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ }
+ case 10:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _loadtriangle($pnlap, $pnlbp, $pnlcp) {
+ $pnlap = $pnlap | 0;
+ $pnlbp = $pnlbp | 0;
+ $pnlcp = $pnlcp | 0;
+ var $0 = 0, $1 = 0, $cmp = 0, $add = 0, $2 = 0, $inc = 0, $3 = 0, $arrayidx = 0, $mark = 0, $pnl0p = 0, $pnl1p = 0, $rtp = 0, $pnl0p8 = 0, $pnl1p11 = 0, $rtp14 = 0, $pnl0p17 = 0, $pnl1p20 = 0, $rtp23 = 0, $ltp = 0, $ltp_1 = 0, $ltp_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[234] | 0;
+ $1 = HEAP32[232] | 0;
+ $cmp = ($0 | 0) < ($1 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $1 + 20 | 0;
+ _growtris($add);
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[234] | 0;
+ $inc = $2 + 1 | 0;
+ HEAP32[234] = $inc;
+ $3 = HEAP32[230] | 0;
+ $arrayidx = $3 + ($2 * 52 & -1) | 0;
+ $mark = $arrayidx | 0;
+ HEAP32[$mark >> 2] = 0;
+ $pnl0p = $3 + ($2 * 52 & -1) + 4 | 0;
+ HEAP32[$pnl0p >> 2] = $pnlap;
+ $pnl1p = $3 + ($2 * 52 & -1) + 8 | 0;
+ HEAP32[$pnl1p >> 2] = $pnlbp;
+ $rtp = $3 + ($2 * 52 & -1) + 16 | 0;
+ HEAP32[$rtp >> 2] = 0;
+ $pnl0p8 = $3 + ($2 * 52 & -1) + 20 | 0;
+ HEAP32[$pnl0p8 >> 2] = $pnlbp;
+ $pnl1p11 = $3 + ($2 * 52 & -1) + 24 | 0;
+ HEAP32[$pnl1p11 >> 2] = $pnlcp;
+ $rtp14 = $3 + ($2 * 52 & -1) + 32 | 0;
+ HEAP32[$rtp14 >> 2] = 0;
+ $pnl0p17 = $3 + ($2 * 52 & -1) + 36 | 0;
+ HEAP32[$pnl0p17 >> 2] = $pnlcp;
+ $pnl1p20 = $3 + ($2 * 52 & -1) + 40 | 0;
+ HEAP32[$pnl1p20 >> 2] = $pnlap;
+ $rtp23 = $3 + ($2 * 52 & -1) + 48 | 0;
+ HEAP32[$rtp23 >> 2] = 0;
+ $ltp = $3 + ($2 * 52 & -1) + 12 | 0;
+ HEAP32[$ltp >> 2] = $arrayidx;
+ $ltp_1 = $3 + ($2 * 52 & -1) + 28 | 0;
+ HEAP32[$ltp_1 >> 2] = $arrayidx;
+ $ltp_2 = $3 + ($2 * 52 & -1) + 44 | 0;
+ HEAP32[$ltp_2 >> 2] = $arrayidx;
+ return;
+ }
+}
+function _intersects($pap, $pbp, $pcp, $pdp) {
+ $pap = $pap | 0;
+ $pbp = $pbp | 0;
+ $pcp = $pcp | 0;
+ $pdp = $pdp | 0;
+ var $call = 0, $cmp = 0, $call1 = 0, $cmp2 = 0, $call4 = 0, $cmp5 = 0, $call7 = 0, $cmp8 = 0, $call9 = 0, $tobool = 0, $call11 = 0, $tobool12 = 0, $call14 = 0, $tobool15 = 0, $call17 = 0, $not_tobool18 = 0, $_ = 0, $cmp21 = 0, $cmp23 = 0, $xor33 = 0, $cmp29 = 0, $cmp26 = 0, $xor3234 = 0, $xor32 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _ccw($pap, $pbp, $pcp) | 0;
+ $cmp = ($call | 0) == 3;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _ccw($pap, $pbp, $pdp) | 0;
+ $cmp2 = ($call1 | 0) == 3;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call4 = _ccw($pcp, $pdp, $pap) | 0;
+ $cmp5 = ($call4 | 0) == 3;
+ if ($cmp5) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call7 = _ccw($pcp, $pdp, $pbp) | 0;
+ $cmp8 = ($call7 | 0) == 3;
+ if ($cmp8) {
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 6:
+ $call9 = _between($pap, $pbp, $pcp) | 0;
+ $tobool = ($call9 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ }
+ case 7:
+ $call11 = _between($pap, $pbp, $pdp) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ }
+ case 8:
+ $call14 = _between($pcp, $pdp, $pap) | 0;
+ $tobool15 = ($call14 | 0) == 0;
+ if ($tobool15) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ }
+ case 9:
+ $call17 = _between($pcp, $pdp, $pbp) | 0;
+ $not_tobool18 = ($call17 | 0) != 0;
+ $_ = $not_tobool18 & 1;
+ return $_ | 0;
+ case 10:
+ $cmp21 = ($call | 0) == 1;
+ $cmp23 = ($call1 | 0) == 1;
+ $xor33 = $cmp21 ^ $cmp23;
+ if ($xor33) {
+ label = 11;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ }
+ case 11:
+ $cmp29 = ($call7 | 0) == 1;
+ $cmp26 = ($call4 | 0) == 1;
+ $xor3234 = $cmp26 ^ $cmp29;
+ $xor32 = $xor3234 & 1;
+ $retval_0 = $xor32;
+ label = 12;
+ break;
+ case 12:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _between($pap, $pbp, $pcp) {
+ $pap = $pap | 0;
+ $pbp = $pbp | 0;
+ $pcp = $pcp | 0;
+ var $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $sub = 0.0, $y = 0, $2 = 0.0, $y3 = 0, $3 = 0.0, $sub4 = 0.0, $x6 = 0, $4 = 0.0, $sub8 = 0.0, $y10 = 0, $5 = 0.0, $sub12 = 0.0, $call = 0, $cmp = 0, $mul = 0.0, $mul18 = 0.0, $add = 0.0, $cmp19 = 0, $mul22 = 0.0, $mul25 = 0.0, $add26 = 0.0, $mul29 = 0.0, $mul32 = 0.0, $add33 = 0.0, $cmp34 = 0, $phitmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $pbp | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $pap | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $sub = $0 - $1;
+ $y = $pbp + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $y3 = $pap + 8 | 0;
+ $3 = +HEAPF64[$y3 >> 3];
+ $sub4 = $2 - $3;
+ $x6 = $pcp | 0;
+ $4 = +HEAPF64[$x6 >> 3];
+ $sub8 = $4 - $1;
+ $y10 = $pcp + 8 | 0;
+ $5 = +HEAPF64[$y10 >> 3];
+ $sub12 = $5 - $3;
+ $call = _ccw($pap, $pbp, $pcp) | 0;
+ $cmp = ($call | 0) == 3;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 3:
+ $mul = $sub * $sub8;
+ $mul18 = $sub4 * $sub12;
+ $add = $mul + $mul18;
+ $cmp19 = $add < 0.0;
+ if ($cmp19) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $mul22 = $sub8 * $sub8;
+ $mul25 = $sub12 * $sub12;
+ $add26 = $mul22 + $mul25;
+ $mul29 = $sub * $sub;
+ $mul32 = $sub4 * $sub4;
+ $add33 = $mul29 + $mul32;
+ $cmp34 = $add26 <= $add33;
+ $phitmp = $cmp34 & 1;
+ $retval_0 = $phitmp;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _solve3($coeff, $roots) {
+ $coeff = $coeff | 0;
+ $roots = $roots | 0;
+ var $arrayidx = 0, $0 = 0.0, $cmp = 0, $cmp4 = 0, $or_cond = 0, $call = 0, $arrayidx2 = 0, $arrayidx1 = 0, $1 = 0.0, $2 = 0.0, $3 = 0.0, $mul = 0.0, $div = 0.0, $div5 = 0.0, $div6 = 0.0, $mul7 = 0.0, $mul8 = 0.0, $mul9 = 0.0, $mul10 = 0.0, $sub = 0.0, $add = 0.0, $div11 = 0.0, $sub12 = 0.0, $mul13 = 0.0, $mul14 = 0.0, $mul15 = 0.0, $mul16 = 0.0, $add17 = 0.0, $cmp18 = 0, $sub20 = 0.0, $add22 = 0.0, $call23 = 0.0, $mul24 = 0.0, $call26 = 0.0, $sub27 = 0.0, $call28 = 0.0, $cmp29 = 0, $sub30 = 0.0, $4 = 0.0, $mul31 = 0.0, $5 = 0.0, $cond = 0.0, $mul32 = 0.0, $div33 = 0.0, $call34 = 0.0, $mul35 = 0.0, $add37 = 0.0, $add38 = 0.0, $div39 = 0.0, $call40 = 0.0, $mul41 = 0.0, $arrayidx42 = 0, $sub43 = 0.0, $sub44 = 0.0, $div45 = 0.0, $call46 = 0.0, $mul47 = 0.0, $arrayidx48 = 0, $call49 = 0.0, $sub50 = 0.0, $mul51 = 0.0, $sub52 = 0.0, $sub53 = 0.0, $cmp54 = 0, $sub56 = 0.0, $6 = 0.0, $mul57 = 0.0, $7 = 0.0, $cond60 = 0.0, $cmp61 = 0, $sub63 = 0.0, $8 = 0.0, $mul64 = 0.0, $9 = 0.0, $cond67 = 0.0, $add68 = 0.0, $cmp70 = 0, $mul74 = 0.0, $arrayidx75 = 0, $arrayidx76 = 0, $rootn_0 = 0, $i_046 = 0, $arrayidx80 = 0, $10 = 0.0, $sub81 = 0.0, $inc = 0, $cmp79 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $arrayidx = $coeff + 24 | 0;
+ $0 = +HEAPF64[$arrayidx >> 3];
+ $cmp = $0 < 1.0e-7;
+ $cmp4 = $0 > -1.0e-7;
+ $or_cond = $cmp & $cmp4;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _solve2($coeff, $roots) | 0;
+ $retval_0 = $call;
+ label = 19;
+ break;
+ case 4:
+ $arrayidx2 = $coeff + 8 | 0;
+ $arrayidx1 = $coeff + 16 | 0;
+ $1 = +HEAPF64[$coeff >> 3];
+ $2 = +HEAPF64[$arrayidx2 >> 3];
+ $3 = +HEAPF64[$arrayidx1 >> 3];
+ $mul = $0 * 3.0;
+ $div = $3 / $mul;
+ $div5 = $2 / $0;
+ $div6 = $1 / $0;
+ $mul7 = $div * $div;
+ $mul8 = $div * 2.0;
+ $mul9 = $mul8 * $mul7;
+ $mul10 = $div * $div5;
+ $sub = $mul9 - $mul10;
+ $add = $div6 + $sub;
+ $div11 = $div5 / 3.0;
+ $sub12 = $div11 - $mul7;
+ $mul13 = $add * $add;
+ $mul14 = $sub12 * 4.0;
+ $mul15 = $sub12 * $mul14;
+ $mul16 = $sub12 * $mul15;
+ $add17 = $mul13 + $mul16;
+ $cmp18 = $add17 < 0.0;
+ if ($cmp18) {
+ label = 5;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 5:
+ $sub20 = -0.0 - $add17;
+ $add22 = $mul13 - $add17;
+ $call23 = +Math_sqrt(+$add22);
+ $mul24 = $call23 * .5;
+ $call26 = +Math_sqrt(+$sub20);
+ $sub27 = -0.0 - $add;
+ $call28 = +Math_atan2(+$call26, +$sub27);
+ $cmp29 = $mul24 < 0.0;
+ if ($cmp29) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $sub30 = -0.0 - $mul24;
+ $4 = +Math_pow(+$sub30, .3333333333333333);
+ $mul31 = $4 * -1.0;
+ $cond = $mul31;
+ label = 8;
+ break;
+ case 7:
+ $5 = +Math_pow(+$mul24, .3333333333333333);
+ $cond = $5;
+ label = 8;
+ break;
+ case 8:
+ $mul32 = $cond * 2.0;
+ $div33 = $call28 / 3.0;
+ $call34 = +Math_cos(+$div33);
+ $mul35 = $mul32 * $call34;
+ HEAPF64[$roots >> 3] = $mul35;
+ $add37 = $call28 + 3.141592653589793;
+ $add38 = $add37 + 3.141592653589793;
+ $div39 = $add38 / 3.0;
+ $call40 = +Math_cos(+$div39);
+ $mul41 = $mul32 * $call40;
+ $arrayidx42 = $roots + 8 | 0;
+ HEAPF64[$arrayidx42 >> 3] = $mul41;
+ $sub43 = $call28 - 3.141592653589793;
+ $sub44 = $sub43 - 3.141592653589793;
+ $div45 = $sub44 / 3.0;
+ $call46 = +Math_cos(+$div45);
+ $mul47 = $mul32 * $call46;
+ $arrayidx48 = $roots + 16 | 0;
+ HEAPF64[$arrayidx48 >> 3] = $mul47;
+ $rootn_0 = 3;
+ label = 17;
+ break;
+ case 9:
+ $call49 = +Math_sqrt(+$add17);
+ $sub50 = $call49 - $add;
+ $mul51 = $sub50 * .5;
+ $sub52 = -0.0 - $add;
+ $sub53 = $sub52 - $mul51;
+ $cmp54 = $mul51 < 0.0;
+ if ($cmp54) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $sub56 = -0.0 - $mul51;
+ $6 = +Math_pow(+$sub56, .3333333333333333);
+ $mul57 = $6 * -1.0;
+ $cond60 = $mul57;
+ label = 12;
+ break;
+ case 11:
+ $7 = +Math_pow(+$mul51, .3333333333333333);
+ $cond60 = $7;
+ label = 12;
+ break;
+ case 12:
+ $cmp61 = $sub53 < 0.0;
+ if ($cmp61) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $sub63 = -0.0 - $sub53;
+ $8 = +Math_pow(+$sub63, .3333333333333333);
+ $mul64 = $8 * -1.0;
+ $cond67 = $mul64;
+ label = 15;
+ break;
+ case 14:
+ $9 = +Math_pow(+$sub53, .3333333333333333);
+ $cond67 = $9;
+ label = 15;
+ break;
+ case 15:
+ $add68 = $cond60 + $cond67;
+ HEAPF64[$roots >> 3] = $add68;
+ $cmp70 = $add17 > 0.0;
+ if ($cmp70) {
+ $rootn_0 = 1;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $mul74 = $add68 * -.5;
+ $arrayidx75 = $roots + 16 | 0;
+ HEAPF64[$arrayidx75 >> 3] = $mul74;
+ $arrayidx76 = $roots + 8 | 0;
+ HEAPF64[$arrayidx76 >> 3] = $mul74;
+ $rootn_0 = 3;
+ label = 17;
+ break;
+ case 17:
+ $i_046 = 0;
+ label = 18;
+ break;
+ case 18:
+ $arrayidx80 = $roots + ($i_046 << 3) | 0;
+ $10 = +HEAPF64[$arrayidx80 >> 3];
+ $sub81 = $10 - $div;
+ HEAPF64[$arrayidx80 >> 3] = $sub81;
+ $inc = $i_046 + 1 | 0;
+ $cmp79 = ($inc | 0) < ($rootn_0 | 0);
+ if ($cmp79) {
+ $i_046 = $inc;
+ label = 18;
+ break;
+ } else {
+ $retval_0 = $rootn_0;
+ label = 19;
+ break;
+ }
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _solve2($coeff, $roots) {
+ $coeff = $coeff | 0;
+ $roots = $roots | 0;
+ var $arrayidx = 0, $0 = 0.0, $cmp = 0, $cmp3 = 0, $or_cond = 0, $call = 0, $arrayidx1 = 0, $1 = 0.0, $2 = 0.0, $mul = 0.0, $div = 0.0, $div4 = 0.0, $mul5 = 0.0, $sub = 0.0, $cmp6 = 0, $cmp8 = 0, $sub10 = 0.0, $call14 = 0.0, $add = 0.0, $mul16 = 0.0, $sub18 = 0.0, $arrayidx19 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $arrayidx = $coeff + 16 | 0;
+ $0 = +HEAPF64[$arrayidx >> 3];
+ $cmp = $0 < 1.0e-7;
+ $cmp3 = $0 > -1.0e-7;
+ $or_cond = $cmp & $cmp3;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _solve1($coeff, $roots) | 0;
+ $retval_0 = $call;
+ label = 8;
+ break;
+ case 4:
+ $arrayidx1 = $coeff + 8 | 0;
+ $1 = +HEAPF64[$coeff >> 3];
+ $2 = +HEAPF64[$arrayidx1 >> 3];
+ $mul = $0 * 2.0;
+ $div = $2 / $mul;
+ $div4 = $1 / $0;
+ $mul5 = $div * $div;
+ $sub = $mul5 - $div4;
+ $cmp6 = $sub < 0.0;
+ if ($cmp6) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp8 = $sub == 0.0;
+ if ($cmp8) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $sub10 = -0.0 - $div;
+ HEAPF64[$roots >> 3] = $sub10;
+ $retval_0 = 1;
+ label = 8;
+ break;
+ case 7:
+ $call14 = +Math_sqrt(+$sub);
+ $add = $call14 - $div;
+ HEAPF64[$roots >> 3] = $add;
+ $mul16 = $div * -2.0;
+ $sub18 = $mul16 - $add;
+ $arrayidx19 = $roots + 8 | 0;
+ HEAPF64[$arrayidx19 >> 3] = $sub18;
+ $retval_0 = 2;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _make_polyline($line, $sline) {
+ $line = $line | 0;
+ $sline = $sline | 0;
+ var $pn = 0, $0 = 0, $1 = 0, $add = 0, $2 = 0, $cmp = 0, $3 = 0, $tobool = 0, $4 = 0, $mul1 = 0, $call = 0, $mul2 = 0, $call3 = 0, $call_sink = 0, $5 = 0, $6 = 0, $arrayidx = 0, $ps = 0, $7 = 0, $8 = 0, $9 = 0, $10 = 0, $11 = 0, $sub918 = 0, $cmp1019 = 0, $12 = 0, $13 = 0, $14 = 0, $sub9 = 0, $15 = 0, $smax = 0, $16 = 0, $i_021 = 0, $j_020 = 0, $add11 = 0, $arrayidx12 = 0, $add13 = 0, $arrayidx14 = 0, $arrayidx15 = 0, $arrayidx17 = 0, $17 = 0, $18 = 0, $19 = 0, $20 = 0, $add18 = 0, $inc19 = 0, $cmp10 = 0, $21 = 0, $i_0_lcssa = 0, $j_0_lcssa = 0, $add20 = 0, $22 = 0, $arrayidx21 = 0, $arrayidx22 = 0, $23 = 0, $arrayidx24 = 0, $24 = 0, $25 = 0, $26 = 0, $pn25 = 0, $27 = 0, $ps26 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $line;
+ $line = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$line >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$line + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pn = $line + 4 | 0;
+ $0 = HEAP32[$pn >> 2] | 0;
+ $1 = $0 * 3 & -1;
+ $add = $1 - 2 | 0;
+ $2 = HEAP32[2860] | 0;
+ $cmp = ($add | 0) > ($2 | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $3 = HEAP32[2862] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $4 = $3;
+ $mul1 = $add << 4;
+ $call = _realloc($4, $mul1) | 0;
+ $call_sink = $call;
+ label = 6;
+ break;
+ case 5:
+ $mul2 = $add << 4;
+ $call3 = _malloc($mul2) | 0;
+ $call_sink = $call3;
+ label = 6;
+ break;
+ case 6:
+ $5 = $call_sink;
+ HEAP32[2862] = $5;
+ HEAP32[2860] = $add;
+ label = 7;
+ break;
+ case 7:
+ $6 = HEAP32[2862] | 0;
+ $arrayidx = $6 + 16 | 0;
+ $ps = $line | 0;
+ $7 = HEAP32[$ps >> 2] | 0;
+ $8 = $6;
+ $9 = $7;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $10 = $arrayidx;
+ _memmove($10 | 0, $9 | 0, 16);
+ $11 = HEAP32[$pn >> 2] | 0;
+ $sub918 = $11 - 1 | 0;
+ $cmp1019 = ($sub918 | 0) > 1;
+ if ($cmp1019) {
+ label = 8;
+ break;
+ } else {
+ $j_0_lcssa = 2;
+ $i_0_lcssa = 1;
+ label = 11;
+ break;
+ }
+ case 8:
+ $12 = HEAP32[2862] | 0;
+ $13 = HEAP32[$ps >> 2] | 0;
+ $14 = HEAP32[$pn >> 2] | 0;
+ $sub9 = $14 - 1 | 0;
+ $15 = ($sub9 | 0) > 2;
+ $smax = $15 ? $sub9 : 2;
+ $16 = $smax * 3 & -1;
+ $j_020 = 2;
+ $i_021 = 1;
+ label = 9;
+ break;
+ case 9:
+ $add11 = $j_020 + 2 | 0;
+ $arrayidx12 = $12 + ($add11 << 4) | 0;
+ $add13 = $j_020 + 1 | 0;
+ $arrayidx14 = $12 + ($add13 << 4) | 0;
+ $arrayidx15 = $12 + ($j_020 << 4) | 0;
+ $arrayidx17 = $13 + ($i_021 << 4) | 0;
+ $17 = $arrayidx15;
+ $18 = $arrayidx17;
+ HEAP32[$17 >> 2] = HEAP32[$18 >> 2] | 0;
+ HEAP32[$17 + 4 >> 2] = HEAP32[$18 + 4 >> 2] | 0;
+ HEAP32[$17 + 8 >> 2] = HEAP32[$18 + 8 >> 2] | 0;
+ HEAP32[$17 + 12 >> 2] = HEAP32[$18 + 12 >> 2] | 0;
+ $19 = $arrayidx14;
+ _memmove($19 | 0, $18 | 0, 16);
+ $20 = $arrayidx12;
+ HEAP32[$20 >> 2] = HEAP32[$19 >> 2] | 0;
+ HEAP32[$20 + 4 >> 2] = HEAP32[$19 + 4 >> 2] | 0;
+ HEAP32[$20 + 8 >> 2] = HEAP32[$19 + 8 >> 2] | 0;
+ HEAP32[$20 + 12 >> 2] = HEAP32[$19 + 12 >> 2] | 0;
+ $add18 = $j_020 + 3 | 0;
+ $inc19 = $i_021 + 1 | 0;
+ $cmp10 = ($inc19 | 0) < ($sub9 | 0);
+ if ($cmp10) {
+ $j_020 = $add18;
+ $i_021 = $inc19;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $21 = $16 - 1 | 0;
+ $j_0_lcssa = $21;
+ $i_0_lcssa = $smax;
+ label = 11;
+ break;
+ case 11:
+ $add20 = $j_0_lcssa + 1 | 0;
+ $22 = HEAP32[2862] | 0;
+ $arrayidx21 = $22 + ($add20 << 4) | 0;
+ $arrayidx22 = $22 + ($j_0_lcssa << 4) | 0;
+ $23 = HEAP32[$ps >> 2] | 0;
+ $arrayidx24 = $23 + ($i_0_lcssa << 4) | 0;
+ $24 = $arrayidx22;
+ $25 = $arrayidx24;
+ HEAP32[$24 >> 2] = HEAP32[$25 >> 2] | 0;
+ HEAP32[$24 + 4 >> 2] = HEAP32[$25 + 4 >> 2] | 0;
+ HEAP32[$24 + 8 >> 2] = HEAP32[$25 + 8 >> 2] | 0;
+ HEAP32[$24 + 12 >> 2] = HEAP32[$25 + 12 >> 2] | 0;
+ $26 = $arrayidx21;
+ _memmove($26 | 0, $25 | 0, 16);
+ $pn25 = $sline + 4 | 0;
+ HEAP32[$pn25 >> 2] = $add;
+ $27 = HEAP32[2862] | 0;
+ $ps26 = $sline | 0;
+ HEAP32[$ps26 >> 2] = $27;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _agxbinit($xb, $hint, $init) {
+ $xb = $xb | 0;
+ $hint = $hint | 0;
+ $init = $init | 0;
+ var $tobool = 0, $buf = 0, $dyna = 0, $cmp = 0, $_hint = 0, $dyna2 = 0, $call = 0, $buf3 = 0, $hint_addr_1 = 0, $buf5 = 0, $0 = 0, $add_ptr = 0, $eptr = 0, $1 = 0, $ptr = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($init | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $buf = $xb | 0;
+ HEAP32[$buf >> 2] = $init;
+ $dyna = $xb + 12 | 0;
+ HEAP32[$dyna >> 2] = 0;
+ $hint_addr_1 = $hint;
+ label = 5;
+ break;
+ case 4:
+ $cmp = ($hint | 0) == 0;
+ $_hint = $cmp ? 1024 : $hint;
+ $dyna2 = $xb + 12 | 0;
+ HEAP32[$dyna2 >> 2] = 1;
+ $call = _malloc($_hint) | 0;
+ $buf3 = $xb | 0;
+ HEAP32[$buf3 >> 2] = $call;
+ $hint_addr_1 = $_hint;
+ label = 5;
+ break;
+ case 5:
+ $buf5 = $xb | 0;
+ $0 = HEAP32[$buf5 >> 2] | 0;
+ $add_ptr = $0 + $hint_addr_1 | 0;
+ $eptr = $xb + 8 | 0;
+ HEAP32[$eptr >> 2] = $add_ptr;
+ $1 = HEAP32[$buf5 >> 2] | 0;
+ $ptr = $xb + 4 | 0;
+ HEAP32[$ptr >> 2] = $1;
+ HEAP8[$1] = 0;
+ return;
+ }
+}
+function _agxbmore($xb, $ssz) {
+ $xb = $xb | 0;
+ $ssz = $ssz | 0;
+ var $eptr = 0, $0 = 0, $buf = 0, $1 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $mul = 0, $add = 0, $cmp = 0, $add_mul = 0, $ptr = 0, $2 = 0, $sub_ptr_lhs_cast3 = 0, $sub_ptr_sub5 = 0, $dyna = 0, $3 = 0, $tobool = 0, $call = 0, $call9 = 0, $4 = 0, $nbuf_0 = 0, $add_ptr = 0, $5 = 0, $add_ptr17 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $eptr = $xb + 8 | 0;
+ $0 = HEAP32[$eptr >> 2] | 0;
+ $buf = $xb | 0;
+ $1 = HEAP32[$buf >> 2] | 0;
+ $sub_ptr_lhs_cast = $0;
+ $sub_ptr_rhs_cast = $1;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $mul = $sub_ptr_sub << 1;
+ $add = $sub_ptr_sub + $ssz | 0;
+ $cmp = $add >>> 0 > $mul >>> 0;
+ $add_mul = $cmp ? $add : $mul;
+ $ptr = $xb + 4 | 0;
+ $2 = HEAP32[$ptr >> 2] | 0;
+ $sub_ptr_lhs_cast3 = $2;
+ $sub_ptr_sub5 = $sub_ptr_lhs_cast3 - $sub_ptr_rhs_cast | 0;
+ $dyna = $xb + 12 | 0;
+ $3 = HEAP32[$dyna >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _realloc($1, $add_mul) | 0;
+ $nbuf_0 = $call;
+ label = 5;
+ break;
+ case 4:
+ $call9 = _malloc($add_mul) | 0;
+ $4 = HEAP32[$buf >> 2] | 0;
+ _memcpy($call9 | 0, $4 | 0, $sub_ptr_sub5);
+ HEAP32[$dyna >> 2] = 1;
+ $nbuf_0 = $call9;
+ label = 5;
+ break;
+ case 5:
+ HEAP32[$buf >> 2] = $nbuf_0;
+ $add_ptr = $nbuf_0 + $sub_ptr_sub5 | 0;
+ HEAP32[$ptr >> 2] = $add_ptr;
+ $5 = HEAP32[$buf >> 2] | 0;
+ $add_ptr17 = $5 + $add_mul | 0;
+ HEAP32[$eptr >> 2] = $add_ptr17;
+ return 0;
+ }
+ return 0;
+}
+function _growops13($newopn) {
+ $newopn = $newopn | 0;
+ var $0 = 0, $cmp = 0, $1 = 0, $tobool = 0, $mul = 0, $call = 0, $2 = 0, $tobool2 = 0, $3 = 0, $call4 = 0, $4 = 0, $mul6 = 0, $call7 = 0, $5 = 0, $tobool8 = 0, $6 = 0, $call10 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[2288] | 0;
+ $cmp = ($0 | 0) < ($newopn | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[2284] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $mul = $newopn << 4;
+ $call = _malloc($mul) | 0;
+ $2 = $call;
+ HEAP32[2284] = $2;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $3 = HEAP32[_stderr >> 2] | 0;
+ $call4 = _fprintf($3 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 584, HEAP32[tempInt + 16 >> 2] = 108664, tempInt) | 0) | 0;
+ _abort();
+ case 6:
+ $4 = $1;
+ $mul6 = $newopn << 4;
+ $call7 = _realloc($4, $mul6) | 0;
+ $5 = $call7;
+ HEAP32[2284] = $5;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $6 = HEAP32[_stderr >> 2] | 0;
+ $call10 = _fprintf($6 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 590, HEAP32[tempInt + 16 >> 2] = 103784, tempInt) | 0) | 0;
+ _abort();
+ case 8:
+ HEAP32[2288] = $newopn;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _growtris($newtrin) {
+ $newtrin = $newtrin | 0;
+ var $0 = 0, $cmp = 0, $1 = 0, $tobool = 0, $mul = 0, $call = 0, $2 = 0, $tobool2 = 0, $3 = 0, $call4 = 0, $4 = 0, $mul6 = 0, $call7 = 0, $5 = 0, $tobool8 = 0, $6 = 0, $call10 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[232] | 0;
+ $cmp = ($0 | 0) < ($newtrin | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[230] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $mul = $newtrin * 52 & -1;
+ $call = _malloc($mul) | 0;
+ $2 = $call;
+ HEAP32[230] = $2;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $3 = HEAP32[_stderr >> 2] | 0;
+ $call4 = _fprintf($3 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 543, HEAP32[tempInt + 16 >> 2] = 148528, tempInt) | 0) | 0;
+ _abort();
+ case 6:
+ $4 = $1;
+ $mul6 = $newtrin * 52 & -1;
+ $call7 = _realloc($4, $mul6) | 0;
+ $5 = $call7;
+ HEAP32[230] = $5;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $6 = HEAP32[_stderr >> 2] | 0;
+ $call10 = _fprintf($6 | 0, 107728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 142728, HEAP32[tempInt + 8 >> 2] = 549, HEAP32[tempInt + 16 >> 2] = 145760, tempInt) | 0) | 0;
+ _abort();
+ case 8:
+ HEAP32[232] = $newtrin;
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _agxbpop($xb) {
+ $xb = $xb | 0;
+ var $ptr = 0, $0 = 0, $buf = 0, $1 = 0, $cmp = 0, $incdec_ptr = 0, $2 = 0, $conv = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr = $xb + 4 | 0;
+ $0 = HEAP32[$ptr >> 2] | 0;
+ $buf = $xb | 0;
+ $1 = HEAP32[$buf >> 2] | 0;
+ $cmp = $0 >>> 0 > $1 >>> 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = -1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $incdec_ptr = $0 - 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ $2 = HEAP8[$0] | 0;
+ $conv = $2 & 255;
+ $retval_0 = $conv;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agdictof($obj) {
+ $obj = $obj | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $univ = 0, $3 = 0, $4 = 0, $globattr = 0, $5 = 0, $graph = 0, $6 = 0, $7 = 0, $univ2 = 0, $8 = 0, $nodeattr = 0, $9 = 0, $tail = 0, $10 = 0, $11 = 0, $graph4 = 0, $12 = 0, $univ5 = 0, $13 = 0, $edgeattr = 0, $14 = 0, $d_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $obj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 3;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 5;
+ break;
+ } else {
+ $d_0 = 0;
+ label = 6;
+ break;
+ }
+ case 3:
+ $univ = $obj + 16 | 0;
+ $3 = $univ;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $globattr = $4 + 12 | 0;
+ $5 = HEAP32[$globattr >> 2] | 0;
+ $d_0 = $5;
+ label = 6;
+ break;
+ case 4:
+ $graph = $obj + 20 | 0;
+ $6 = $graph;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $univ2 = $7 + 16 | 0;
+ $8 = HEAP32[$univ2 >> 2] | 0;
+ $nodeattr = $8 + 4 | 0;
+ $9 = HEAP32[$nodeattr >> 2] | 0;
+ $d_0 = $9;
+ label = 6;
+ break;
+ case 5:
+ $tail = $obj + 16 | 0;
+ $10 = $tail;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $graph4 = $11 + 20 | 0;
+ $12 = HEAP32[$graph4 >> 2] | 0;
+ $univ5 = $12 + 16 | 0;
+ $13 = HEAP32[$univ5 >> 2] | 0;
+ $edgeattr = $13 + 8 | 0;
+ $14 = HEAP32[$edgeattr >> 2] | 0;
+ $d_0 = $14;
+ label = 6;
+ break;
+ case 6:
+ return $d_0 | 0;
+ }
+ return 0;
+}
+function _agxget($obj, $index) {
+ $obj = $obj | 0;
+ $index = $index | 0;
+ var $cmp = 0, $attr = 0, $0 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($index | 0) > -1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $attr = $obj + 4 | 0;
+ $0 = $attr;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $arrayidx = $1 + ($index << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $retval_0 = $2;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agxbput_n($xb, $s, $ssz) {
+ $xb = $xb | 0;
+ $s = $s | 0;
+ $ssz = $ssz | 0;
+ var $ptr = 0, $0 = 0, $add_ptr = 0, $eptr = 0, $1 = 0, $cmp = 0, $call = 0, $2 = 0, $3 = 0, $add_ptr3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr = $xb + 4 | 0;
+ $0 = HEAP32[$ptr >> 2] | 0;
+ $add_ptr = $0 + $ssz | 0;
+ $eptr = $xb + 8 | 0;
+ $1 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $add_ptr >>> 0 > $1 >>> 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _agxbmore($xb, $ssz) | 0;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$ptr >> 2] | 0;
+ _memcpy($2 | 0, $s | 0, $ssz);
+ $3 = HEAP32[$ptr >> 2] | 0;
+ $add_ptr3 = $3 + $ssz | 0;
+ HEAP32[$ptr >> 2] = $add_ptr3;
+ return $ssz | 0;
+ }
+ return 0;
+}
+function _agxbput($xb, $s) {
+ $xb = $xb | 0;
+ $s = $s | 0;
+ return _agxbput_n($xb, $s, _strlen($s | 0) | 0) | 0;
+}
+function _agxbfree($xb) {
+ $xb = $xb | 0;
+ var $dyna = 0, $0 = 0, $tobool = 0, $buf = 0, $1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $dyna = $xb + 12 | 0;
+ $0 = HEAP32[$dyna >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $buf = $xb | 0;
+ $1 = HEAP32[$buf >> 2] | 0;
+ _free($1);
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _agNEWsym($dict, $name, $value) {
+ $dict = $dict | 0;
+ $name = $name | 0;
+ $value = $value | 0;
+ var $call = 0, $0 = 0, $call1 = 0, $name2 = 0, $call3 = 0, $value4 = 0, $1 = 0, $2 = 0, $dict5 = 0, $3 = 0, $call6 = 0, $index = 0, $4 = 0, $list = 0, $5 = 0, $tobool = 0, $6 = 0, $add = 0, $mul = 0, $call8 = 0, $add9 = 0, $mul10 = 0, $call11 = 0, $call8_sink = 0, $7 = 0, $inc = 0, $arrayidx = 0, $8 = 0, $arrayidx16 = 0, $9 = 0, $searchf = 0, $10 = 0, $call19 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _calloc(1, 16) | 0;
+ $0 = $call;
+ $call1 = _agstrdup($name) | 0;
+ $name2 = $call;
+ HEAP32[$name2 >> 2] = $call1;
+ $call3 = _agstrdup($value) | 0;
+ $value4 = $call + 4 | 0;
+ $1 = $value4;
+ HEAP32[$1 >> 2] = $call3;
+ $2 = $call + 12 | 0;
+ HEAP8[$2] = 1;
+ $dict5 = $dict + 4 | 0;
+ $3 = HEAP32[$dict5 >> 2] | 0;
+ $call6 = _dtsize($3) | 0;
+ $index = $call + 8 | 0;
+ $4 = $index;
+ HEAP32[$4 >> 2] = $call6;
+ $list = $dict + 8 | 0;
+ $5 = HEAP32[$list >> 2] | 0;
+ $tobool = ($5 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $6 = $5;
+ $add = $call6 << 2;
+ $mul = $add + 8 | 0;
+ $call8 = _realloc($6, $mul) | 0;
+ $call8_sink = $call8;
+ label = 5;
+ break;
+ case 4:
+ $add9 = $call6 << 2;
+ $mul10 = $add9 + 8 | 0;
+ $call11 = _malloc($mul10) | 0;
+ $call8_sink = $call11;
+ label = 5;
+ break;
+ case 5:
+ $7 = $call8_sink;
+ HEAP32[$list >> 2] = $7;
+ $inc = $call6 + 1 | 0;
+ $arrayidx = $7 + ($call6 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $0;
+ $8 = HEAP32[$list >> 2] | 0;
+ $arrayidx16 = $8 + ($inc << 2) | 0;
+ HEAP32[$arrayidx16 >> 2] = 0;
+ $9 = HEAP32[$dict5 >> 2] | 0;
+ $searchf = $9 | 0;
+ $10 = HEAP32[$searchf >> 2] | 0;
+ $call19 = FUNCTION_TABLE_iiii[$10 & 1023]($9, $call, 1) | 0;
+ return $0 | 0;
+ }
+ return 0;
+}
+function _agattr($obj, $name, $value) {
+ $obj = $obj | 0;
+ $name = $name | 0;
+ $value = $value | 0;
+ var $call = 0, $tobool = 0, $value1 = 0, $0 = 0, $call2 = 0, $tobool3 = 0, $call6 = 0, $call9 = 0, $call10 = 0, $rv_0 = 0, $isnew_0 = 0, $tobool12 = 0, $1 = 0, $2 = 0, $3 = 0, $bf_val_sext = 0, $4 = 0, $graph = 0, $5 = 0, $6 = 0, $head = 0, $7 = 0, $8 = 0, $graph16 = 0, $9 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agfindattr($obj, $name) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $value1 = $call + 4 | 0;
+ $0 = HEAP32[$value1 >> 2] | 0;
+ $call2 = _strcmp($0 | 0, $value | 0) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ $retval_0 = $call;
+ label = 11;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _agstrfree($0);
+ $call6 = _agstrdup($value) | 0;
+ HEAP32[$value1 >> 2] = $call6;
+ $isnew_0 = 0;
+ $rv_0 = $call;
+ label = 6;
+ break;
+ case 5:
+ $call9 = _agdictof($obj) | 0;
+ $call10 = _agNEWsym($call9, $name, $value) | 0;
+ $isnew_0 = 1;
+ $rv_0 = $call10;
+ label = 6;
+ break;
+ case 6:
+ $tobool12 = ($rv_0 | 0) == 0;
+ if ($tobool12) {
+ $retval_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $1 = $obj;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $3 = $2 << 28;
+ $bf_val_sext = $3 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 8;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 9;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = $rv_0;
+ label = 11;
+ break;
+ }
+ case 8:
+ $4 = $obj;
+ _add_graph_attr($4, $rv_0, $isnew_0);
+ $retval_0 = $rv_0;
+ label = 11;
+ break;
+ case 9:
+ $graph = $obj + 20 | 0;
+ $5 = $graph;
+ $6 = HEAP32[$5 >> 2] | 0;
+ _add_node_attr($6, $rv_0, $isnew_0);
+ $retval_0 = $rv_0;
+ label = 11;
+ break;
+ case 10:
+ $head = $obj + 12 | 0;
+ $7 = $head;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $graph16 = $8 + 20 | 0;
+ $9 = HEAP32[$graph16 >> 2] | 0;
+ _add_edge_attr($9, $rv_0, $isnew_0);
+ $retval_0 = $rv_0;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agfindattr($obj, $name) {
+ $obj = $obj | 0;
+ $name = $name | 0;
+ var $0 = 0;
+ $0 = HEAP32[(_agdictof($obj) | 0) + 4 >> 2] | 0;
+ return FUNCTION_TABLE_iiii[HEAP32[$0 >> 2] & 1023]($0, $name, 512) | 0;
+}
+function _add_graph_attr($g, $attr, $isnew) {
+ $g = $g | 0;
+ $attr = $attr | 0;
+ $isnew = $isnew | 0;
+ var $meta_node = 0, $0 = 0, $tobool = 0, $graph = 0, $1 = 0, $call = 0, $tobool27 = 0, $n_08 = 0, $2 = 0, $call3 = 0, $3 = 0, $4 = 0, $graph5 = 0, $5 = 0, $call6 = 0, $tobool2 = 0, $6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $meta_node = $g + 36 | 0;
+ $0 = HEAP32[$meta_node >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $call = _agfstnode($1) | 0;
+ $tobool27 = ($call | 0) == 0;
+ if ($tobool27) {
+ label = 6;
+ break;
+ } else {
+ $n_08 = $call;
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = $n_08;
+ $call3 = _agusergraph($2) | 0;
+ $3 = $call3 | 0;
+ _obj_init_attr($3, $attr, $isnew);
+ $4 = HEAP32[$meta_node >> 2] | 0;
+ $graph5 = $4 + 20 | 0;
+ $5 = HEAP32[$graph5 >> 2] | 0;
+ $call6 = _agnxtnode($5, $n_08) | 0;
+ $tobool2 = ($call6 | 0) == 0;
+ if ($tobool2) {
+ label = 6;
+ break;
+ } else {
+ $n_08 = $call6;
+ label = 4;
+ break;
+ }
+ case 5:
+ $6 = $g | 0;
+ _obj_init_attr($6, $attr, $isnew);
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _add_node_attr($g, $attr, $isnew) {
+ $g = $g | 0;
+ $attr = $attr | 0;
+ $isnew = $isnew | 0;
+ var $call = 0, $tobool27 = 0, $n_028 = 0, $0 = 0, $call1 = 0, $tobool = 0, $meta_node = 0, $1 = 0, $tobool2 = 0, $graph = 0, $2 = 0, $call4 = 0, $tobool625 = 0, $n_126 = 0, $3 = 0, $call8 = 0, $proto9 = 0, $4 = 0, $tobool1122 = 0, $5 = 0, $proto_023 = 0, $n13 = 0, $6 = 0, $7 = 0, $prev = 0, $8 = 0, $tobool11 = 0, $9 = 0, $graph18 = 0, $10 = 0, $call19 = 0, $tobool6 = 0, $proto21 = 0, $proto_119 = 0, $tobool2320 = 0, $proto_121 = 0, $n25 = 0, $11 = 0, $12 = 0, $prev27 = 0, $proto_1 = 0, $tobool23 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agfstnode($g) | 0;
+ $tobool27 = ($call | 0) == 0;
+ if ($tobool27) {
+ label = 4;
+ break;
+ } else {
+ $n_028 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = $n_028 | 0;
+ _obj_init_attr($0, $attr, $isnew);
+ $call1 = _agnxtnode($g, $n_028) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_028 = $call1;
+ label = 3;
+ break;
+ }
+ case 4:
+ $meta_node = $g + 36 | 0;
+ $1 = HEAP32[$meta_node >> 2] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ if ($tobool2) {
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $graph = $1 + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $call4 = _agfstnode($2) | 0;
+ $tobool625 = ($call4 | 0) == 0;
+ if ($tobool625) {
+ label = 12;
+ break;
+ } else {
+ $n_126 = $call4;
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = $n_126;
+ $call8 = _agusergraph($3) | 0;
+ $proto9 = $call8 + 40 | 0;
+ $4 = HEAP32[$proto9 >> 2] | 0;
+ $tobool1122 = ($4 | 0) == 0;
+ if ($tobool1122) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $5 = $4;
+ $proto_023 = $5;
+ label = 8;
+ break;
+ case 8:
+ $n13 = $proto_023 | 0;
+ $6 = HEAP32[$n13 >> 2] | 0;
+ $7 = $6 | 0;
+ _obj_init_attr($7, $attr, $isnew);
+ $prev = $proto_023 + 8 | 0;
+ $8 = HEAP32[$prev >> 2] | 0;
+ $tobool11 = ($8 | 0) == 0;
+ if ($tobool11) {
+ label = 9;
+ break;
+ } else {
+ $proto_023 = $8;
+ label = 8;
+ break;
+ }
+ case 9:
+ $9 = HEAP32[$meta_node >> 2] | 0;
+ $graph18 = $9 + 20 | 0;
+ $10 = HEAP32[$graph18 >> 2] | 0;
+ $call19 = _agnxtnode($10, $n_126) | 0;
+ $tobool6 = ($call19 | 0) == 0;
+ if ($tobool6) {
+ label = 12;
+ break;
+ } else {
+ $n_126 = $call19;
+ label = 6;
+ break;
+ }
+ case 10:
+ $proto21 = $g + 40 | 0;
+ $proto_119 = HEAP32[$proto21 >> 2] | 0;
+ $tobool2320 = ($proto_119 | 0) == 0;
+ if ($tobool2320) {
+ label = 12;
+ break;
+ } else {
+ $proto_121 = $proto_119;
+ label = 11;
+ break;
+ }
+ case 11:
+ $n25 = $proto_121 | 0;
+ $11 = HEAP32[$n25 >> 2] | 0;
+ $12 = $11 | 0;
+ _obj_init_attr($12, $attr, $isnew);
+ $prev27 = $proto_121 + 8 | 0;
+ $proto_1 = HEAP32[$prev27 >> 2] | 0;
+ $tobool23 = ($proto_1 | 0) == 0;
+ if ($tobool23) {
+ label = 12;
+ break;
+ } else {
+ $proto_121 = $proto_1;
+ label = 11;
+ break;
+ }
+ case 12:
+ return;
+ }
+}
+function _add_edge_attr($g, $attr, $isnew) {
+ $g = $g | 0;
+ $attr = $attr | 0;
+ $isnew = $isnew | 0;
+ var $call = 0, $tobool32 = 0, $n_033 = 0, $call1 = 0, $tobool330 = 0, $e_031 = 0, $0 = 0, $call5 = 0, $tobool3 = 0, $call7 = 0, $tobool = 0, $meta_node = 0, $1 = 0, $tobool9 = 0, $graph = 0, $2 = 0, $call11 = 0, $tobool1328 = 0, $n_129 = 0, $3 = 0, $call15 = 0, $proto16 = 0, $4 = 0, $tobool1825 = 0, $5 = 0, $proto_026 = 0, $e20 = 0, $6 = 0, $7 = 0, $prev = 0, $8 = 0, $tobool18 = 0, $9 = 0, $graph25 = 0, $10 = 0, $call26 = 0, $tobool13 = 0, $proto28 = 0, $proto_122 = 0, $tobool3023 = 0, $proto_124 = 0, $e32 = 0, $11 = 0, $12 = 0, $prev34 = 0, $proto_1 = 0, $tobool30 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agfstnode($g) | 0;
+ $tobool32 = ($call | 0) == 0;
+ if ($tobool32) {
+ label = 6;
+ break;
+ } else {
+ $n_033 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agfstout($g, $n_033) | 0;
+ $tobool330 = ($call1 | 0) == 0;
+ if ($tobool330) {
+ label = 5;
+ break;
+ } else {
+ $e_031 = $call1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $0 = $e_031 | 0;
+ _obj_init_attr($0, $attr, $isnew);
+ $call5 = _agnxtout($g, $e_031) | 0;
+ $tobool3 = ($call5 | 0) == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ $e_031 = $call5;
+ label = 4;
+ break;
+ }
+ case 5:
+ $call7 = _agnxtnode($g, $n_033) | 0;
+ $tobool = ($call7 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_033 = $call7;
+ label = 3;
+ break;
+ }
+ case 6:
+ $meta_node = $g + 36 | 0;
+ $1 = HEAP32[$meta_node >> 2] | 0;
+ $tobool9 = ($1 | 0) == 0;
+ if ($tobool9) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $graph = $1 + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $call11 = _agfstnode($2) | 0;
+ $tobool1328 = ($call11 | 0) == 0;
+ if ($tobool1328) {
+ label = 14;
+ break;
+ } else {
+ $n_129 = $call11;
+ label = 8;
+ break;
+ }
+ case 8:
+ $3 = $n_129;
+ $call15 = _agusergraph($3) | 0;
+ $proto16 = $call15 + 40 | 0;
+ $4 = HEAP32[$proto16 >> 2] | 0;
+ $tobool1825 = ($4 | 0) == 0;
+ if ($tobool1825) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $5 = $4;
+ $proto_026 = $5;
+ label = 10;
+ break;
+ case 10:
+ $e20 = $proto_026 + 4 | 0;
+ $6 = HEAP32[$e20 >> 2] | 0;
+ $7 = $6 | 0;
+ _obj_init_attr($7, $attr, $isnew);
+ $prev = $proto_026 + 8 | 0;
+ $8 = HEAP32[$prev >> 2] | 0;
+ $tobool18 = ($8 | 0) == 0;
+ if ($tobool18) {
+ label = 11;
+ break;
+ } else {
+ $proto_026 = $8;
+ label = 10;
+ break;
+ }
+ case 11:
+ $9 = HEAP32[$meta_node >> 2] | 0;
+ $graph25 = $9 + 20 | 0;
+ $10 = HEAP32[$graph25 >> 2] | 0;
+ $call26 = _agnxtnode($10, $n_129) | 0;
+ $tobool13 = ($call26 | 0) == 0;
+ if ($tobool13) {
+ label = 14;
+ break;
+ } else {
+ $n_129 = $call26;
+ label = 8;
+ break;
+ }
+ case 12:
+ $proto28 = $g + 40 | 0;
+ $proto_122 = HEAP32[$proto28 >> 2] | 0;
+ $tobool3023 = ($proto_122 | 0) == 0;
+ if ($tobool3023) {
+ label = 14;
+ break;
+ } else {
+ $proto_124 = $proto_122;
+ label = 13;
+ break;
+ }
+ case 13:
+ $e32 = $proto_124 + 4 | 0;
+ $11 = HEAP32[$e32 >> 2] | 0;
+ $12 = $11 | 0;
+ _obj_init_attr($12, $attr, $isnew);
+ $prev34 = $proto_124 + 8 | 0;
+ $proto_1 = HEAP32[$prev34 >> 2] | 0;
+ $tobool30 = ($proto_1 | 0) == 0;
+ if ($tobool30) {
+ label = 14;
+ break;
+ } else {
+ $proto_124 = $proto_1;
+ label = 13;
+ break;
+ }
+ case 14:
+ return;
+ }
+}
+function _agraphattr($g, $name, $value) {
+ $g = $g | 0;
+ $name = $name | 0;
+ $value = $value | 0;
+ var $cmp = 0, $0 = 0, $_g = 0, $root = 0, $1 = 0, $cmp1 = 0, $2 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($g | 0) == 0;
+ $0 = HEAP32[42137] | 0;
+ $_g = $cmp ? $0 : $g;
+ $root = $_g + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $cmp1 = ($_g | 0) == ($1 | 0);
+ if ($cmp1) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $_g | 0;
+ $call = _agattr($2, $name, $value) | 0;
+ $retval_0 = $call;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agnodeattr($g, $name, $value) {
+ $g = $g | 0;
+ $name = $name | 0;
+ $value = $value | 0;
+ var $cmp = 0, $0 = 0, $_g = 0, $root = 0, $1 = 0, $cmp1 = 0, $proto = 0, $2 = 0, $n = 0, $3 = 0, $4 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($g | 0) == 0;
+ $0 = HEAP32[42137] | 0;
+ $_g = $cmp ? $0 : $g;
+ $root = $_g + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $cmp1 = ($_g | 0) == ($1 | 0);
+ if ($cmp1) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $proto = $_g + 40 | 0;
+ $2 = HEAP32[$proto >> 2] | 0;
+ $n = $2 | 0;
+ $3 = HEAP32[$n >> 2] | 0;
+ $4 = $3 | 0;
+ $call = _agattr($4, $name, $value) | 0;
+ $retval_0 = $call;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agedgeattr($g, $name, $value) {
+ $g = $g | 0;
+ $name = $name | 0;
+ $value = $value | 0;
+ var $cmp = 0, $0 = 0, $_g = 0, $root = 0, $1 = 0, $cmp1 = 0, $proto = 0, $2 = 0, $e = 0, $3 = 0, $4 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($g | 0) == 0;
+ $0 = HEAP32[42137] | 0;
+ $_g = $cmp ? $0 : $g;
+ $root = $_g + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $cmp1 = ($_g | 0) == ($1 | 0);
+ if ($cmp1) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $proto = $_g + 40 | 0;
+ $2 = HEAP32[$proto >> 2] | 0;
+ $e = $2 + 4 | 0;
+ $3 = HEAP32[$e >> 2] | 0;
+ $4 = $3 | 0;
+ $call = _agattr($4, $name, $value) | 0;
+ $retval_0 = $call;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agFREEdict($g, $dict) {
+ $g = $g | 0;
+ $dict = $dict | 0;
+ var $dict1 = 0, $0 = 0, $call = 0, $list = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $tobool35 = 0, $4 = 0, $i_06 = 0, $inc = 0, $5 = 0, $6 = 0, $arrayidx = 0, $7 = 0, $tobool3 = 0, $_lcssa = 0, $8 = 0, $9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $dict1 = $dict + 4 | 0;
+ $0 = HEAP32[$dict1 >> 2] | 0;
+ $call = _dtclose($0) | 0;
+ $list = $dict + 8 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$list >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool35 = ($3 | 0) == 0;
+ if ($tobool35) {
+ $_lcssa = $2;
+ label = 5;
+ break;
+ } else {
+ $i_06 = 0;
+ $4 = $3;
+ label = 4;
+ break;
+ }
+ case 4:
+ $inc = $i_06 + 1 | 0;
+ $5 = $4;
+ _agfreesym($5);
+ $6 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $6 + ($inc << 2) | 0;
+ $7 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool3 = ($7 | 0) == 0;
+ if ($tobool3) {
+ $_lcssa = $6;
+ label = 5;
+ break;
+ } else {
+ $i_06 = $inc;
+ $4 = $7;
+ label = 4;
+ break;
+ }
+ case 5:
+ $8 = $_lcssa;
+ _free($8);
+ label = 6;
+ break;
+ case 6:
+ $9 = $dict;
+ _free($9);
+ return;
+ }
+}
+function _agfreesym($ptr) {
+ $ptr = $ptr | 0;
+ _agstrfree(HEAP32[$ptr >> 2] | 0);
+ _agstrfree(HEAP32[$ptr + 4 >> 2] | 0);
+ _free($ptr);
+ return;
+}
+function _agNEWdict($name) {
+ $name = $name | 0;
+ var $call = 0;
+ $call = _calloc(1, 12) | 0;
+ HEAP32[$call >> 2] = $name;
+ HEAP32[$call + 4 >> 2] = _dtopen(89552, HEAP32[41974] | 0) | 0;
+ HEAP32[$call + 8 >> 2] = 0;
+ return $call | 0;
+}
+function _agcopydict($to_dict, $from_dict) {
+ $to_dict = $to_dict | 0;
+ $from_dict = $from_dict | 0;
+ var $dict = 0, $0 = 0, $call = 0, $cmp8 = 0, $list = 0, $i_09 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $name = 0, $3 = 0, $value = 0, $4 = 0, $call1 = 0, $printed = 0, $5 = 0, $printed2 = 0, $fixed = 0, $6 = 0, $fixed3 = 0, $inc = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $dict = $from_dict + 4 | 0;
+ $0 = HEAP32[$dict >> 2] | 0;
+ $call = _dtsize($0) | 0;
+ $cmp8 = ($call | 0) > 0;
+ if ($cmp8) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $list = $from_dict + 8 | 0;
+ $i_09 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($i_09 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $name = $2 | 0;
+ $3 = HEAP32[$name >> 2] | 0;
+ $value = $2 + 4 | 0;
+ $4 = HEAP32[$value >> 2] | 0;
+ $call1 = _agNEWsym($to_dict, $3, $4) | 0;
+ $printed = $2 + 12 | 0;
+ $5 = HEAP8[$printed] | 0;
+ $printed2 = $call1 + 12 | 0;
+ HEAP8[$printed2] = $5;
+ $fixed = $2 + 13 | 0;
+ $6 = HEAP8[$fixed] | 0;
+ $fixed3 = $call1 + 13 | 0;
+ HEAP8[$fixed3] = $6;
+ $inc = $i_09 + 1 | 0;
+ $cmp = ($inc | 0) < ($call | 0);
+ if ($cmp) {
+ $i_09 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ return;
+ }
+}
+function _aginitlib($gs, $ns, $es) {
+ $gs = $gs | 0;
+ $ns = $ns | 0;
+ $es = $es | 0;
+ var $0 = 0, $cmp = 0, $1 = 0, $cmp1 = 0, $2 = 0, $cmp2 = 0, $or_cond = 0, $3 = 0, $cmp4 = 0, $or_cond4 = 0, $call = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[42137] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[42134] = $gs;
+ HEAP32[42135] = $ns;
+ HEAP32[42136] = $es;
+ HEAP8[168567] = 1;
+ _initproto();
+ label = 6;
+ break;
+ case 4:
+ $1 = HEAP32[42134] | 0;
+ $cmp1 = ($1 | 0) == ($gs | 0);
+ $2 = HEAP32[42135] | 0;
+ $cmp2 = ($2 | 0) == ($ns | 0);
+ $or_cond = $cmp1 & $cmp2;
+ $3 = HEAP32[42136] | 0;
+ $cmp4 = ($3 | 0) == ($es | 0);
+ $or_cond4 = $or_cond & $cmp4;
+ if ($or_cond4) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call = _agerr(0, 120304, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _agget($obj, $attr) {
+ $obj = $obj | 0;
+ $attr = $attr | 0;
+ return _agxget($obj, _agindex($obj, $attr) | 0) | 0;
+}
+function _agindex($obj, $name) {
+ $obj = $obj | 0;
+ $name = $name | 0;
+ var $call = 0, $tobool = 0, $index = 0, $0 = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agfindattr($obj, $name) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $rv_0 = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $index = $call + 8 | 0;
+ $0 = HEAP32[$index >> 2] | 0;
+ $rv_0 = $0;
+ label = 4;
+ break;
+ case 4:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _agset($obj, $attr, $value) {
+ $obj = $obj | 0;
+ $attr = $attr | 0;
+ $value = $value | 0;
+ return _agxset($obj, _agindex($obj, $attr) | 0, $value) | 0;
+}
+function _agxset($obj, $index, $buf) {
+ $obj = $obj | 0;
+ $index = $index | 0;
+ $buf = $buf | 0;
+ var $cmp = 0, $attr = 0, $0 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $call = 0, $rem7 = 0, $shl = 0, $div = 0, $didset = 0, $3 = 0, $4 = 0, $arrayidx2 = 0, $5 = 0, $conv8 = 0, $or = 0, $conv3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($index | 0) > -1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = -1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $attr = $obj + 4 | 0;
+ $0 = $attr;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $arrayidx = $1 + ($index << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _agstrfree($2);
+ $call = _agstrdup($buf) | 0;
+ HEAP32[$arrayidx >> 2] = $call;
+ $rem7 = $index & 7;
+ $shl = 1 << $rem7;
+ $div = ($index | 0) / 8 & -1;
+ $didset = $obj + 8 | 0;
+ $3 = $didset;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $arrayidx2 = $4 + $div | 0;
+ $5 = HEAP8[$arrayidx2] | 0;
+ $conv8 = $5 & 255;
+ $or = $conv8 | $shl;
+ $conv3 = $or & 255;
+ HEAP8[$arrayidx2] = $conv3;
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agsafeset($obj, $name, $value, $def) {
+ $obj = $obj | 0;
+ $name = $name | 0;
+ $value = $value | 0;
+ $def = $def | 0;
+ var $call = 0, $cmp = 0, $tobool = 0, $_def = 0, $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $root = 0, $3 = 0, $4 = 0, $call2 = 0, $graph = 0, $5 = 0, $6 = 0, $call4 = 0, $head = 0, $7 = 0, $8 = 0, $graph6 = 0, $9 = 0, $call7 = 0, $a_0 = 0, $index = 0, $10 = 0, $call9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agfindattr($obj, $name) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $a_0 = $call;
+ label = 7;
+ break;
+ }
+ case 3:
+ $tobool = ($def | 0) == 0;
+ $_def = $tobool ? 153736 : $def;
+ $0 = $obj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ if (($bf_val_sext | 0) == 3) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 6;
+ break;
+ } else {
+ $a_0 = 0;
+ label = 7;
+ break;
+ }
+ case 4:
+ $root = $obj + 32 | 0;
+ $3 = $root;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $call2 = _agraphattr($4, $name, $_def) | 0;
+ $a_0 = $call2;
+ label = 7;
+ break;
+ case 5:
+ $graph = $obj + 20 | 0;
+ $5 = $graph;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $call4 = _agnodeattr($6, $name, $_def) | 0;
+ $a_0 = $call4;
+ label = 7;
+ break;
+ case 6:
+ $head = $obj + 12 | 0;
+ $7 = $head;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $graph6 = $8 + 20 | 0;
+ $9 = HEAP32[$graph6 >> 2] | 0;
+ $call7 = _agedgeattr($9, $name, $_def) | 0;
+ $a_0 = $call7;
+ label = 7;
+ break;
+ case 7:
+ $index = $a_0 + 8 | 0;
+ $10 = HEAP32[$index >> 2] | 0;
+ $call9 = _agxset($obj, $10, $value) | 0;
+ return $call9 | 0;
+ }
+ return 0;
+}
+function _agcopyattr($oldobj, $newobj) {
+ $oldobj = $oldobj | 0;
+ $newobj = $newobj | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $cmp = 0, $3 = 0, $4 = 0, $5 = 0, $bf_val_sext5 = 0, $cmp6 = 0, $call = 0, $list1 = 0, $6 = 0, $list_0_ph = 0, $r_0_ph = 0, $tobool = 0, $list_0 = 0, $incdec_ptr = 0, $7 = 0, $tobool8 = 0, $index = 0, $8 = 0, $cmp10 = 0, $name = 0, $9 = 0, $call14 = 0, $tobool15 = 0, $index18 = 0, $10 = 0, $index19 = 0, $11 = 0, $call20 = 0, $call21 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $oldobj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ $cmp = ($bf_val_sext | 0) == 2;
+ $3 = $newobj;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $5 = $4 << 28;
+ $bf_val_sext5 = $5 >> 28;
+ $cmp6 = ($bf_val_sext | 0) == ($bf_val_sext5 | 0);
+ if ($cmp6) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ }
+ case 3:
+ $call = _agdictof($oldobj) | 0;
+ $list1 = $call + 8 | 0;
+ $6 = HEAP32[$list1 >> 2] | 0;
+ $r_0_ph = 0;
+ $list_0_ph = $6;
+ label = 4;
+ break;
+ case 4:
+ $tobool = ($r_0_ph | 0) == 0;
+ $list_0 = $list_0_ph;
+ label = 5;
+ break;
+ case 5:
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = $r_0_ph;
+ label = 11;
+ break;
+ }
+ case 6:
+ $incdec_ptr = $list_0 + 4 | 0;
+ $7 = HEAP32[$list_0 >> 2] | 0;
+ $tobool8 = ($7 | 0) == 0;
+ if ($tobool8) {
+ $retval_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $index = $7 + 8 | 0;
+ $8 = HEAP32[$index >> 2] | 0;
+ $cmp10 = ($8 | 0) == 0;
+ if ($cmp10) {
+ $list_0 = $incdec_ptr;
+ label = 5;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $name = $7 | 0;
+ $9 = HEAP32[$name >> 2] | 0;
+ $call14 = _agfindattr($newobj, $9) | 0;
+ $tobool15 = ($call14 | 0) == 0;
+ if ($tobool15) {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $index18 = $call14 + 8 | 0;
+ $10 = HEAP32[$index18 >> 2] | 0;
+ $index19 = $7 + 8 | 0;
+ $11 = HEAP32[$index19 >> 2] | 0;
+ $call20 = _agxget($oldobj, $11) | 0;
+ $call21 = _agxset($newobj, $10, $call20) | 0;
+ $r_0_ph = $call21;
+ $list_0_ph = $incdec_ptr;
+ label = 4;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _obj_init_attr($obj, $attr, $isnew) {
+ $obj = $obj | 0;
+ $attr = $attr | 0;
+ $isnew = $isnew | 0;
+ var $index = 0, $0 = 0, $tobool = 0, $attr1 = 0, $1 = 0, $2 = 0, $tobool2 = 0, $3 = 0, $add = 0, $mul = 0, $call = 0, $add4 = 0, $mul5 = 0, $call6 = 0, $call_sink = 0, $4 = 0, $value = 0, $5 = 0, $call8 = 0, $6 = 0, $arrayidx = 0, $rem24 = 0, $cmp = 0, $didset = 0, $7 = 0, $8 = 0, $tobool11 = 0, $div18 = 0, $add19 = 0, $call16 = 0, $call21 = 0, $cond23 = 0, $arrayidx27 = 0, $div28 = 0, $didset29 = 0, $9 = 0, $10 = 0, $arrayidx30 = 0, $11 = 0, $conv = 0, $rem3123 = 0, $shl = 0, $and = 0, $cmp32 = 0, $attr35 = 0, $12 = 0, $13 = 0, $arrayidx36 = 0, $14 = 0, $value37 = 0, $15 = 0, $call38 = 0, $16 = 0, $arrayidx40 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $index = $attr + 8 | 0;
+ $0 = HEAP32[$index >> 2] | 0;
+ $tobool = ($isnew | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $attr1 = $obj + 4 | 0;
+ $1 = $attr1;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = $2;
+ $add = $0 << 2;
+ $mul = $add + 4 | 0;
+ $call = _realloc($3, $mul) | 0;
+ $call_sink = $call;
+ label = 6;
+ break;
+ case 5:
+ $add4 = $0 << 2;
+ $mul5 = $add4 + 4 | 0;
+ $call6 = _malloc($mul5) | 0;
+ $call_sink = $call6;
+ label = 6;
+ break;
+ case 6:
+ $4 = $call_sink;
+ HEAP32[$1 >> 2] = $4;
+ $value = $attr + 4 | 0;
+ $5 = HEAP32[$value >> 2] | 0;
+ $call8 = _agstrdup($5) | 0;
+ $6 = HEAP32[$1 >> 2] | 0;
+ $arrayidx = $6 + ($0 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $call8;
+ $rem24 = $0 & 7;
+ $cmp = ($rem24 | 0) == 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 7:
+ $didset = $obj + 8 | 0;
+ $7 = $didset;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $tobool11 = ($8 | 0) == 0;
+ $div18 = ($0 | 0) / 8 & -1;
+ $add19 = $div18 + 1 | 0;
+ if ($tobool11) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call16 = _realloc($8, $add19) | 0;
+ $cond23 = $call16;
+ label = 10;
+ break;
+ case 9:
+ $call21 = _malloc($add19) | 0;
+ $cond23 = $call21;
+ label = 10;
+ break;
+ case 10:
+ HEAP32[$7 >> 2] = $cond23;
+ $arrayidx27 = $cond23 + $div18 | 0;
+ HEAP8[$arrayidx27] = 0;
+ label = 13;
+ break;
+ case 11:
+ $div28 = ($0 | 0) / 8 & -1;
+ $didset29 = $obj + 8 | 0;
+ $9 = $didset29;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $arrayidx30 = $10 + $div28 | 0;
+ $11 = HEAP8[$arrayidx30] | 0;
+ $conv = $11 << 24 >> 24;
+ $rem3123 = $0 & 7;
+ $shl = 1 << $rem3123;
+ $and = $conv & $shl;
+ $cmp32 = ($and | 0) == 0;
+ if ($cmp32) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $attr35 = $obj + 4 | 0;
+ $12 = $attr35;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $arrayidx36 = $13 + ($0 << 2) | 0;
+ $14 = HEAP32[$arrayidx36 >> 2] | 0;
+ _agstrfree($14);
+ $value37 = $attr + 4 | 0;
+ $15 = HEAP32[$value37 >> 2] | 0;
+ $call38 = _agstrdup($15) | 0;
+ $16 = HEAP32[$12 >> 2] | 0;
+ $arrayidx40 = $16 + ($0 << 2) | 0;
+ HEAP32[$arrayidx40 >> 2] = $call38;
+ label = 13;
+ break;
+ case 13:
+ return;
+ }
+}
+function _initproto() {
+ var $call = 0, $0 = 0, $proto = 0, $1 = 0, $e = 0, $2 = 0, $3 = 0, $call1 = 0, $index = 0, $4 = 0, $cmp = 0, $5 = 0, $e3 = 0, $6 = 0, $7 = 0, $call4 = 0, $index5 = 0, $8 = 0, $cmp6 = 0, $printed = 0, $9 = 0, $e10 = 0, $10 = 0, $11 = 0, $call11 = 0, $index12 = 0, $12 = 0, $cmp13 = 0, $printed16 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agopen(126536, 0) | 0;
+ $0 = $call;
+ HEAP32[42137] = $0;
+ $proto = $call + 40 | 0;
+ $1 = HEAP32[$proto >> 2] | 0;
+ $e = $1 + 4 | 0;
+ $2 = HEAP32[$e >> 2] | 0;
+ $3 = $2 | 0;
+ $call1 = _agattr($3, 117288, 153736) | 0;
+ $index = $call1 + 8 | 0;
+ $4 = HEAP32[$index >> 2] | 0;
+ $cmp = ($4 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _abort();
+ case 4:
+ $5 = HEAP32[$proto >> 2] | 0;
+ $e3 = $5 + 4 | 0;
+ $6 = HEAP32[$e3 >> 2] | 0;
+ $7 = $6 | 0;
+ $call4 = _agattr($7, 112040, 153736) | 0;
+ $index5 = $call4 + 8 | 0;
+ $8 = HEAP32[$index5 >> 2] | 0;
+ $cmp6 = ($8 | 0) == 1;
+ if ($cmp6) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _abort();
+ case 6:
+ $printed = $call4 + 12 | 0;
+ HEAP8[$printed] = 0;
+ $9 = HEAP32[$proto >> 2] | 0;
+ $e10 = $9 + 4 | 0;
+ $10 = HEAP32[$e10 >> 2] | 0;
+ $11 = $10 | 0;
+ $call11 = _agattr($11, 107712, 153736) | 0;
+ $index12 = $call11 + 8 | 0;
+ $12 = HEAP32[$index12 >> 2] | 0;
+ $cmp13 = ($12 | 0) == 2;
+ if ($cmp13) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _abort();
+ case 8:
+ $printed16 = $call11 + 12 | 0;
+ HEAP8[$printed16] = 0;
+ return;
+ }
+}
+function _agcmpid($dict, $id0, $id1, $disc) {
+ $dict = $dict | 0;
+ $id0 = $id0 | 0;
+ $id1 = $id1 | 0;
+ $disc = $disc | 0;
+ return (HEAP32[$id0 >> 2] | 0) - (HEAP32[$id1 >> 2] | 0) | 0;
+}
+function _agfindedge($g, $tail, $head) {
+ $g = $g | 0;
+ $tail = $tail | 0;
+ $head = $head | 0;
+ var $call = 0, $cmp = 0, $0 = 0, $1 = 0, $and = 0, $tobool = 0, $call1 = 0, $e_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _esearch($g, $tail, $head, 0) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $e_0 = $call;
+ label = 5;
+ break;
+ }
+ case 3:
+ $0 = $g;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $and = $1 & 16;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $e_0 = 0;
+ label = 5;
+ break;
+ }
+ case 4:
+ $call1 = _esearch($g, $head, $tail, 0) | 0;
+ $e_0 = $call1;
+ label = 5;
+ break;
+ case 5:
+ return $e_0 | 0;
+ }
+ return 0;
+}
+function _esearch($g, $tail, $head, $usrkey) {
+ $g = $g | 0;
+ $tail = $tail | 0;
+ $head = $head | 0;
+ $usrkey = $usrkey | 0;
+ var $key = 0, $attr = 0, $arrayidx = 0, $tail1 = 0, $head2 = 0, $tobool = 0, $cond = 0, $attr3 = 0, $inedges = 0, $0 = 0, $searchf = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $call9 = 0, $4 = 0, $tobool10 = 0, $tail11 = 0, $5 = 0, $6 = 0, $cmp = 0, $head12 = 0, $7 = 0, $8 = 0, $cmp13 = 0, $e_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $key = __stackBase__ | 0;
+ $attr = __stackBase__ + 32 | 0;
+ $arrayidx = $attr | 0;
+ HEAP32[$arrayidx >> 2] = $usrkey;
+ $tail1 = $key + 16 | 0;
+ HEAP32[$tail1 >> 2] = $tail;
+ $head2 = $key + 12 | 0;
+ HEAP32[$head2 >> 2] = $head;
+ $tobool = ($usrkey | 0) != 0;
+ $cond = $tobool ? $arrayidx : 0;
+ $attr3 = $key + 4 | 0;
+ HEAP32[$attr3 >> 2] = $cond;
+ $inedges = $g + 24 | 0;
+ $0 = HEAP32[$inedges >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $2 = $key | 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $2, 4) | 0;
+ $3 = $call;
+ $e_0 = $3;
+ label = 8;
+ break;
+ case 4:
+ $call9 = FUNCTION_TABLE_iiii[$1 & 1023]($0, $2, 8) | 0;
+ $4 = $call9;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ $e_0 = $4;
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $tail11 = $call9 + 16 | 0;
+ $5 = $tail11;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $cmp = ($6 | 0) == ($tail | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $head12 = $call9 + 12 | 0;
+ $7 = $head12;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $cmp13 = ($8 | 0) == ($head | 0);
+ if ($cmp13) {
+ $e_0 = $4;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $e_0 = 0;
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return $e_0 | 0;
+ }
+ return 0;
+}
+function _agINSedge($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $0 = 0, $1 = 0, $_mask = 0, $cmp = 0, $2 = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $e;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $_mask = $1 & 240;
+ $cmp = ($_mask | 0) == 16;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = $1 & -241;
+ $3 = $2 | 32;
+ HEAP32[$0 >> 2] = $3;
+ label = 4;
+ break;
+ case 4:
+ _install_edge($g, $e);
+ return;
+ }
+}
+function _install_edge($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $inedges = 0, $0 = 0, $searchf = 0, $1 = 0, $2 = 0, $call = 0, $tobool = 0, $tail = 0, $3 = 0, $head = 0, $4 = 0, $outedges = 0, $5 = 0, $searchf2 = 0, $6 = 0, $call4 = 0, $7 = 0, $searchf6 = 0, $8 = 0, $call8 = 0, $9 = 0, $searchf10 = 0, $10 = 0, $call12 = 0, $tobool13 = 0, $tail14 = 0, $11 = 0, $12 = 0, $13 = 0, $cmp = 0, $head17 = 0, $14 = 0, $15 = 0, $16 = 0, $cmp19 = 0, $17 = 0, $18 = 0, $_mask = 0, $cmp21 = 0, $19 = 0, $20 = 0, $21 = 0, $22 = 0, $and = 0, $cmp26 = 0, $meta_node = 0, $23 = 0, $graph = 0, $24 = 0, $call29 = 0, $tobool3030 = 0, $f_031 = 0, $tail31 = 0, $25 = 0, $26 = 0, $call32 = 0, $27 = 0, $call33 = 0, $tobool30 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $inedges = $g + 24 | 0;
+ $0 = HEAP32[$inedges >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $2 = $e | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $2, 4) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 3:
+ $tail = $e + 16 | 0;
+ $3 = HEAP32[$tail >> 2] | 0;
+ _agINSnode($g, $3);
+ $head = $e + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ _agINSnode($g, $4);
+ $outedges = $g + 28 | 0;
+ $5 = HEAP32[$outedges >> 2] | 0;
+ $searchf2 = $5 | 0;
+ $6 = HEAP32[$searchf2 >> 2] | 0;
+ $call4 = FUNCTION_TABLE_iiii[$6 & 1023]($5, $2, 1) | 0;
+ $7 = HEAP32[$inedges >> 2] | 0;
+ $searchf6 = $7 | 0;
+ $8 = HEAP32[$searchf6 >> 2] | 0;
+ $call8 = FUNCTION_TABLE_iiii[$8 & 1023]($7, $2, 1) | 0;
+ $9 = HEAP32[$outedges >> 2] | 0;
+ $searchf10 = $9 | 0;
+ $10 = HEAP32[$searchf10 >> 2] | 0;
+ $call12 = FUNCTION_TABLE_iiii[$10 & 1023]($9, $2, 16) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $tail14 = $call12 + 16 | 0;
+ $11 = $tail14;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $13 = HEAP32[$tail >> 2] | 0;
+ $cmp = ($12 | 0) == ($13 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $head17 = $call12 + 12 | 0;
+ $14 = $head17;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $16 = HEAP32[$head >> 2] | 0;
+ $cmp19 = ($15 | 0) == ($16 | 0);
+ if ($cmp19) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $17 = $e;
+ $18 = HEAP32[$17 >> 2] | 0;
+ $_mask = $18 & 240;
+ $cmp21 = ($_mask | 0) == 0;
+ if ($cmp21) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $19 = $18 & -241;
+ $20 = $19 | 16;
+ HEAP32[$17 >> 2] = $20;
+ label = 8;
+ break;
+ case 8:
+ $21 = $g;
+ $22 = HEAP32[$21 >> 2] | 0;
+ $and = $22 & 64;
+ $cmp26 = ($and | 0) == 0;
+ if ($cmp26) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $meta_node = $g + 36 | 0;
+ $23 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $23 + 20 | 0;
+ $24 = HEAP32[$graph >> 2] | 0;
+ $call29 = _agfstin($24, $23) | 0;
+ $tobool3030 = ($call29 | 0) == 0;
+ if ($tobool3030) {
+ label = 11;
+ break;
+ } else {
+ $f_031 = $call29;
+ label = 10;
+ break;
+ }
+ case 10:
+ $tail31 = $f_031 + 16 | 0;
+ $25 = HEAP32[$tail31 >> 2] | 0;
+ $26 = $25;
+ $call32 = _agusergraph($26) | 0;
+ $27 = $call32;
+ _install_edge($27, $e);
+ $call33 = _agnxtin($24, $f_031) | 0;
+ $tobool30 = ($call33 | 0) == 0;
+ if ($tobool30) {
+ label = 11;
+ break;
+ } else {
+ $f_031 = $call33;
+ label = 10;
+ break;
+ }
+ case 11:
+ return;
+ }
+}
+function _agfstedge($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $cmp = 0, $cmp1 = 0, $or_cond = 0, $call = 0, $cmp2 = 0, $call4 = 0, $e_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($g | 0) == 0;
+ $cmp1 = ($n | 0) == 0;
+ $or_cond = $cmp | $cmp1;
+ if ($or_cond) {
+ $e_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _agfstout($g, $n) | 0;
+ $cmp2 = ($call | 0) == 0;
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ $e_0 = $call;
+ label = 5;
+ break;
+ }
+ case 4:
+ $call4 = _agfstin($g, $n) | 0;
+ $e_0 = $call4;
+ label = 5;
+ break;
+ case 5:
+ return $e_0 | 0;
+ }
+ return 0;
+}
+function _agfstout($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $key = 0, $cmp = 0, $cmp1 = 0, $or_cond = 0, $tail = 0, $head = 0, $attr = 0, $outedges = 0, $0 = 0, $searchf = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $tobool = 0, $tail4 = 0, $4 = 0, $5 = 0, $cmp5 = 0, $_ = 0, $f_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $key = __stackBase__ | 0;
+ $cmp = ($g | 0) == 0;
+ $cmp1 = ($n | 0) == 0;
+ $or_cond = $cmp | $cmp1;
+ if ($or_cond) {
+ $f_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail = $key + 16 | 0;
+ HEAP32[$tail >> 2] = $n;
+ $head = $key + 12 | 0;
+ HEAP32[$head >> 2] = 0;
+ $attr = $key + 4 | 0;
+ HEAP32[$attr >> 2] = 0;
+ $outedges = $g + 28 | 0;
+ $0 = HEAP32[$outedges >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $2 = $key | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $2, 8) | 0;
+ $3 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $f_0 = $3;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $tail4 = $call + 16 | 0;
+ $4 = $tail4;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $cmp5 = ($5 | 0) == ($n | 0);
+ $_ = $cmp5 ? $3 : 0;
+ STACKTOP = __stackBase__;
+ return $_ | 0;
+ case 5:
+ STACKTOP = __stackBase__;
+ return $f_0 | 0;
+ }
+ return 0;
+}
+function _agfstin($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $key = 0, $cmp = 0, $cmp1 = 0, $or_cond = 0, $head = 0, $tail = 0, $attr = 0, $inedges = 0, $0 = 0, $searchf = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $tobool = 0, $head4 = 0, $4 = 0, $5 = 0, $cmp5 = 0, $_ = 0, $f_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $key = __stackBase__ | 0;
+ $cmp = ($g | 0) == 0;
+ $cmp1 = ($n | 0) == 0;
+ $or_cond = $cmp | $cmp1;
+ if ($or_cond) {
+ $f_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $key + 12 | 0;
+ HEAP32[$head >> 2] = $n;
+ $tail = $key + 16 | 0;
+ HEAP32[$tail >> 2] = 0;
+ $attr = $key + 4 | 0;
+ HEAP32[$attr >> 2] = 0;
+ $inedges = $g + 24 | 0;
+ $0 = HEAP32[$inedges >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $2 = $key | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $2, 8) | 0;
+ $3 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $f_0 = $3;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $head4 = $call + 12 | 0;
+ $4 = $head4;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $cmp5 = ($5 | 0) == ($n | 0);
+ $_ = $cmp5 ? $3 : 0;
+ STACKTOP = __stackBase__;
+ return $_ | 0;
+ case 5:
+ STACKTOP = __stackBase__;
+ return $f_0 | 0;
+ }
+ return 0;
+}
+function _agnxtedge($g, $e, $n) {
+ $g = $g | 0;
+ $e = $e | 0;
+ $n = $n | 0;
+ var $cmp = 0, $cmp1 = 0, $or_cond = 0, $cmp3 = 0, $or_cond38 = 0, $tail = 0, $0 = 0, $cmp4 = 0, $outedges = 0, $1 = 0, $searchf = 0, $2 = 0, $3 = 0, $call = 0, $cmp7 = 0, $4 = 0, $tail9 = 0, $5 = 0, $6 = 0, $cmp10 = 0, $call12 = 0, $tobool44 = 0, $inedges = 0, $f_045 = 0, $head = 0, $7 = 0, $tail14 = 0, $8 = 0, $cmp15 = 0, $cmp17 = 0, $or_cond39 = 0, $9 = 0, $searchf18 = 0, $10 = 0, $11 = 0, $call20 = 0, $12 = 0, $tobool = 0, $head21 = 0, $13 = 0, $cmp22 = 0, $inedges25 = 0, $14 = 0, $searchf26 = 0, $15 = 0, $16 = 0, $call28 = 0, $17 = 0, $f_1_ph = 0, $tobool3242 = 0, $inedges42 = 0, $f_143 = 0, $head34 = 0, $18 = 0, $tail35 = 0, $19 = 0, $cmp36 = 0, $cmp39 = 0, $or_cond40 = 0, $20 = 0, $searchf43 = 0, $21 = 0, $22 = 0, $call45 = 0, $23 = 0, $tobool32 = 0, $f_1_ = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($g | 0) == 0;
+ $cmp1 = ($e | 0) == 0;
+ $or_cond = $cmp | $cmp1;
+ $cmp3 = ($n | 0) == 0;
+ $or_cond38 = $or_cond | $cmp3;
+ if ($or_cond38) {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $cmp4 = ($0 | 0) == ($n | 0);
+ if ($cmp4) {
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 4:
+ $outedges = $g + 28 | 0;
+ $1 = HEAP32[$outedges >> 2] | 0;
+ $searchf = $1 | 0;
+ $2 = HEAP32[$searchf >> 2] | 0;
+ $3 = $e | 0;
+ $call = FUNCTION_TABLE_iiii[$2 & 1023]($1, $3, 8) | 0;
+ $cmp7 = ($call | 0) == 0;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $4 = $call;
+ $tail9 = $call + 16 | 0;
+ $5 = $tail9;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $cmp10 = ($6 | 0) == ($n | 0);
+ if ($cmp10) {
+ $retval_0 = $4;
+ label = 17;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call12 = _agfstin($g, $n) | 0;
+ $tobool44 = ($call12 | 0) == 0;
+ if ($tobool44) {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $inedges = $g + 24 | 0;
+ $f_045 = $call12;
+ label = 8;
+ break;
+ case 8:
+ $head = $f_045 + 12 | 0;
+ $7 = HEAP32[$head >> 2] | 0;
+ $tail14 = $f_045 + 16 | 0;
+ $8 = HEAP32[$tail14 >> 2] | 0;
+ $cmp15 = ($7 | 0) == ($8 | 0);
+ $cmp17 = ($7 | 0) == ($n | 0);
+ $or_cond39 = $cmp15 & $cmp17;
+ if ($or_cond39) {
+ label = 9;
+ break;
+ } else {
+ $f_1_ph = $f_045;
+ label = 12;
+ break;
+ }
+ case 9:
+ $9 = HEAP32[$inedges >> 2] | 0;
+ $searchf18 = $9 | 0;
+ $10 = HEAP32[$searchf18 >> 2] | 0;
+ $11 = $f_045 | 0;
+ $call20 = FUNCTION_TABLE_iiii[$10 & 1023]($9, $11, 8) | 0;
+ $12 = $call20;
+ $tobool = ($call20 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ } else {
+ $f_045 = $12;
+ label = 8;
+ break;
+ }
+ case 10:
+ $head21 = $e + 12 | 0;
+ $13 = HEAP32[$head21 >> 2] | 0;
+ $cmp22 = ($13 | 0) == ($n | 0);
+ if ($cmp22) {
+ label = 11;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ }
+ case 11:
+ $inedges25 = $g + 24 | 0;
+ $14 = HEAP32[$inedges25 >> 2] | 0;
+ $searchf26 = $14 | 0;
+ $15 = HEAP32[$searchf26 >> 2] | 0;
+ $16 = $e | 0;
+ $call28 = FUNCTION_TABLE_iiii[$15 & 1023]($14, $16, 8) | 0;
+ $17 = $call28;
+ $f_1_ph = $17;
+ label = 12;
+ break;
+ case 12:
+ $tobool3242 = ($f_1_ph | 0) == 0;
+ if ($tobool3242) {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $inedges42 = $g + 24 | 0;
+ $f_143 = $f_1_ph;
+ label = 14;
+ break;
+ case 14:
+ $head34 = $f_143 + 12 | 0;
+ $18 = HEAP32[$head34 >> 2] | 0;
+ $tail35 = $f_143 + 16 | 0;
+ $19 = HEAP32[$tail35 >> 2] | 0;
+ $cmp36 = ($18 | 0) == ($19 | 0);
+ $cmp39 = ($18 | 0) == ($n | 0);
+ $or_cond40 = $cmp36 & $cmp39;
+ if ($or_cond40) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $20 = HEAP32[$inedges42 >> 2] | 0;
+ $searchf43 = $20 | 0;
+ $21 = HEAP32[$searchf43 >> 2] | 0;
+ $22 = $f_143 | 0;
+ $call45 = FUNCTION_TABLE_iiii[$21 & 1023]($20, $22, 8) | 0;
+ $23 = $call45;
+ $tobool32 = ($call45 | 0) == 0;
+ if ($tobool32) {
+ $retval_0 = 0;
+ label = 17;
+ break;
+ } else {
+ $f_143 = $23;
+ label = 14;
+ break;
+ }
+ case 16:
+ $f_1_ = $cmp39 ? $f_143 : 0;
+ return $f_1_ | 0;
+ case 17:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agnxtout($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $outedges = 0, $0 = 0, $searchf = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $tobool = 0, $tail = 0, $4 = 0, $5 = 0, $tail2 = 0, $6 = 0, $cmp = 0, $_ = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $outedges = $g + 28 | 0;
+ $0 = HEAP32[$outedges >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $2 = $e | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $2, 8) | 0;
+ $3 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail = $call + 16 | 0;
+ $4 = $tail;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $tail2 = $e + 16 | 0;
+ $6 = HEAP32[$tail2 >> 2] | 0;
+ $cmp = ($5 | 0) == ($6 | 0);
+ $_ = $cmp ? $3 : 0;
+ return $_ | 0;
+ case 4:
+ return $3 | 0;
+ }
+ return 0;
+}
+function _agnxtin($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $inedges = 0, $0 = 0, $searchf = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $tobool = 0, $head = 0, $4 = 0, $5 = 0, $head2 = 0, $6 = 0, $cmp = 0, $_ = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $inedges = $g + 24 | 0;
+ $0 = HEAP32[$inedges >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $2 = $e | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $2, 8) | 0;
+ $3 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $call + 12 | 0;
+ $4 = $head;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $head2 = $e + 12 | 0;
+ $6 = HEAP32[$head2 >> 2] | 0;
+ $cmp = ($5 | 0) == ($6 | 0);
+ $_ = $cmp ? $3 : 0;
+ return $_ | 0;
+ case 4:
+ return $3 | 0;
+ }
+ return 0;
+}
+function _agNEWedge($subg, $tail, $head, $proto) {
+ $subg = $subg | 0;
+ $tail = $tail | 0;
+ $head = $head | 0;
+ $proto = $proto | 0;
+ var $0 = 0, $call = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $tail1 = 0, $6 = 0, $head2 = 0, $7 = 0, $univ = 0, $8 = 0, $max_edge_id = 0, $9 = 0, $inc = 0, $id = 0, $10 = 0, $11 = 0, $edgeattr = 0, $12 = 0, $dict = 0, $13 = 0, $call4 = 0, $tobool = 0, $attr7 = 0, $14 = 0, $didset8 = 0, $15 = 0, $call5 = 0, $16 = 0, $attr = 0, $17 = 0, $sub = 0, $div = 0, $call6 = 0, $didset = 0, $18 = 0, $cmp19 = 0, $tobool9 = 0, $attr15 = 0, $19 = 0, $attr10 = 0, $i_020 = 0, $20 = 0, $arrayidx = 0, $21 = 0, $edgeattr12 = 0, $22 = 0, $list = 0, $23 = 0, $arrayidx13 = 0, $24 = 0, $value = 0, $cond_in = 0, $cond = 0, $call14 = 0, $25 = 0, $arrayidx16 = 0, $inc17 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[42136] | 0;
+ $call = _calloc(1, $0) | 0;
+ $1 = $call;
+ $2 = $call;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $4 = $3 & -16;
+ $5 = $4 | 2;
+ HEAP32[$2 >> 2] = $5;
+ $tail1 = $call + 16 | 0;
+ $6 = $tail1;
+ HEAP32[$6 >> 2] = $tail;
+ $head2 = $call + 12 | 0;
+ $7 = $head2;
+ HEAP32[$7 >> 2] = $head;
+ $univ = $subg + 16 | 0;
+ $8 = HEAP32[$univ >> 2] | 0;
+ $max_edge_id = $8 + 20 | 0;
+ $9 = HEAP32[$max_edge_id >> 2] | 0;
+ $inc = $9 + 1 | 0;
+ HEAP32[$max_edge_id >> 2] = $inc;
+ $id = $call + 20 | 0;
+ $10 = $id;
+ HEAP32[$10 >> 2] = $9;
+ $11 = HEAP32[$univ >> 2] | 0;
+ $edgeattr = $11 + 8 | 0;
+ $12 = HEAP32[$edgeattr >> 2] | 0;
+ $dict = $12 + 4 | 0;
+ $13 = HEAP32[$dict >> 2] | 0;
+ $call4 = _dtsize($13) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $attr7 = $call + 4 | 0;
+ $14 = $attr7;
+ HEAP32[$14 >> 2] = 0;
+ $didset8 = $call + 8 | 0;
+ $15 = $didset8;
+ HEAP32[$15 >> 2] = 0;
+ label = 10;
+ break;
+ case 4:
+ $call5 = _calloc($call4, 4) | 0;
+ $16 = $call5;
+ $attr = $call + 4 | 0;
+ $17 = $attr;
+ HEAP32[$17 >> 2] = $16;
+ $sub = $call4 + 7 | 0;
+ $div = ($sub | 0) / 8 & -1;
+ $call6 = _calloc($div, 1) | 0;
+ $didset = $call + 8 | 0;
+ $18 = $didset;
+ HEAP32[$18 >> 2] = $call6;
+ $cmp19 = ($call4 | 0) > 0;
+ if ($cmp19) {
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ $tobool9 = ($proto | 0) == 0;
+ $attr15 = $call + 4 | 0;
+ $19 = $attr15;
+ $attr10 = $proto + 4 | 0;
+ $i_020 = 0;
+ label = 6;
+ break;
+ case 6:
+ if ($tobool9) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $20 = HEAP32[$attr10 >> 2] | 0;
+ $arrayidx = $20 + ($i_020 << 2) | 0;
+ $cond_in = $arrayidx;
+ label = 9;
+ break;
+ case 8:
+ $21 = HEAP32[$univ >> 2] | 0;
+ $edgeattr12 = $21 + 8 | 0;
+ $22 = HEAP32[$edgeattr12 >> 2] | 0;
+ $list = $22 + 8 | 0;
+ $23 = HEAP32[$list >> 2] | 0;
+ $arrayidx13 = $23 + ($i_020 << 2) | 0;
+ $24 = HEAP32[$arrayidx13 >> 2] | 0;
+ $value = $24 + 4 | 0;
+ $cond_in = $value;
+ label = 9;
+ break;
+ case 9:
+ $cond = HEAP32[$cond_in >> 2] | 0;
+ $call14 = _agstrdup($cond) | 0;
+ $25 = HEAP32[$19 >> 2] | 0;
+ $arrayidx16 = $25 + ($i_020 << 2) | 0;
+ HEAP32[$arrayidx16 >> 2] = $call14;
+ $inc17 = $i_020 + 1 | 0;
+ $cmp = ($inc17 | 0) < ($call4 | 0);
+ if ($cmp) {
+ $i_020 = $inc17;
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ return $1 | 0;
+ }
+ return 0;
+}
+function _agedge($g, $tail, $head) {
+ $g = $g | 0;
+ $tail = $tail | 0;
+ $head = $head | 0;
+ var $key = 0, $proto = 0, $0 = 0, $e1 = 0, $1 = 0, $attr = 0, $2 = 0, $3 = 0, $head4 = 0, $4 = 0, $e6 = 0, $5 = 0, $tail7 = 0, $6 = 0, $7 = 0, $and = 0, $tobool = 0, $call = 0, $tobool8 = 0, $8 = 0, $and11 = 0, $tobool12 = 0, $call14 = 0, $tobool15 = 0, $e_048 = 0, $9 = 0, $tobool19 = 0, $call21 = 0, $tobool22 = 0, $10 = 0, $and26 = 0, $tobool27 = 0, $call29 = 0, $tobool31 = 0, $e_152 = 0, $arraydecay = 0, $11 = 0, $inc = 0, $call36 = 0, $12 = 0, $e39 = 0, $13 = 0, $attr40 = 0, $14 = 0, $printkey_054 = 0, $15 = 0, $e46 = 0, $16 = 0, $call47 = 0, $17 = 0, $n = 0, $18 = 0, $e50 = 0, $19 = 0, $tail51 = 0, $20 = 0, $e53 = 0, $21 = 0, $head54 = 0, $22 = 0, $23 = 0, $24 = 0, $25 = 0, $e_3 = 0, $26 = 0, $e57 = 0, $27 = 0, $attr58 = 0, $28 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $key = __stackBase__ | 0;
+ $proto = $g + 40 | 0;
+ $0 = HEAP32[$proto >> 2] | 0;
+ $e1 = $0 + 4 | 0;
+ $1 = HEAP32[$e1 >> 2] | 0;
+ $attr = $1 + 4 | 0;
+ $2 = HEAP32[$attr >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $head4 = $1 + 12 | 0;
+ HEAP32[$head4 >> 2] = $head;
+ $4 = HEAP32[$proto >> 2] | 0;
+ $e6 = $4 + 4 | 0;
+ $5 = HEAP32[$e6 >> 2] | 0;
+ $tail7 = $5 + 16 | 0;
+ HEAP32[$tail7 >> 2] = $tail;
+ $6 = $g;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $and = $7 & 32;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _esearch($g, $tail, $head, 0) | 0;
+ $tobool8 = ($call | 0) == 0;
+ if ($tobool8) {
+ label = 4;
+ break;
+ } else {
+ $e_048 = $call;
+ label = 6;
+ break;
+ }
+ case 4:
+ $8 = HEAP32[$6 >> 2] | 0;
+ $and11 = $8 & 16;
+ $tobool12 = ($and11 | 0) == 0;
+ if ($tobool12) {
+ label = 5;
+ break;
+ } else {
+ $printkey_054 = 0;
+ label = 13;
+ break;
+ }
+ case 5:
+ $call14 = _esearch($g, $head, $tail, 0) | 0;
+ $tobool15 = ($call14 | 0) == 0;
+ if ($tobool15) {
+ $printkey_054 = 0;
+ label = 13;
+ break;
+ } else {
+ $e_048 = $call14;
+ label = 6;
+ break;
+ }
+ case 6:
+ _install_edge($g, $e_048);
+ $e_3 = $e_048;
+ label = 14;
+ break;
+ case 7:
+ $9 = HEAP8[$3] | 0;
+ $tobool19 = $9 << 24 >> 24 == 0;
+ if ($tobool19) {
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call21 = _esearch($g, $tail, $head, $3) | 0;
+ $tobool22 = ($call21 | 0) == 0;
+ if ($tobool22) {
+ label = 9;
+ break;
+ } else {
+ $e_152 = $call21;
+ label = 11;
+ break;
+ }
+ case 9:
+ $10 = HEAP32[$6 >> 2] | 0;
+ $and26 = $10 & 16;
+ $tobool27 = ($and26 | 0) == 0;
+ if ($tobool27) {
+ label = 10;
+ break;
+ } else {
+ $printkey_054 = 32;
+ label = 13;
+ break;
+ }
+ case 10:
+ $call29 = _esearch($g, $head, $tail, $3) | 0;
+ $tobool31 = ($call29 | 0) == 0;
+ if ($tobool31) {
+ $printkey_054 = 32;
+ label = 13;
+ break;
+ } else {
+ $e_152 = $call29;
+ label = 11;
+ break;
+ }
+ case 11:
+ _agINSedge($g, $e_152);
+ $e_3 = $e_152;
+ label = 14;
+ break;
+ case 12:
+ $arraydecay = $key | 0;
+ $11 = HEAP32[22298] | 0;
+ $inc = $11 + 1 | 0;
+ HEAP32[22298] = $inc;
+ $call36 = _sprintf($arraydecay | 0, 103776, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $11, tempInt) | 0) | 0;
+ $12 = HEAP32[$proto >> 2] | 0;
+ $e39 = $12 + 4 | 0;
+ $13 = HEAP32[$e39 >> 2] | 0;
+ $attr40 = $13 + 4 | 0;
+ $14 = HEAP32[$attr40 >> 2] | 0;
+ HEAP32[$14 >> 2] = $arraydecay;
+ $printkey_054 = 0;
+ label = 13;
+ break;
+ case 13:
+ $15 = HEAP32[$proto >> 2] | 0;
+ $e46 = $15 + 4 | 0;
+ $16 = HEAP32[$e46 >> 2] | 0;
+ $call47 = _agNEWedge($g, $tail, $head, $16) | 0;
+ _install_edge($g, $call47);
+ $17 = HEAP32[$proto >> 2] | 0;
+ $n = $17 | 0;
+ $18 = HEAP32[$n >> 2] | 0;
+ $e50 = $17 + 4 | 0;
+ $19 = HEAP32[$e50 >> 2] | 0;
+ $tail51 = $19 + 16 | 0;
+ HEAP32[$tail51 >> 2] = $18;
+ $20 = HEAP32[$proto >> 2] | 0;
+ $e53 = $20 + 4 | 0;
+ $21 = HEAP32[$e53 >> 2] | 0;
+ $head54 = $21 + 12 | 0;
+ HEAP32[$head54 >> 2] = $18;
+ $22 = $call47;
+ $23 = HEAP32[$22 >> 2] | 0;
+ $24 = $23 & -241;
+ $25 = $24 | $printkey_054;
+ HEAP32[$22 >> 2] = $25;
+ $e_3 = $call47;
+ label = 14;
+ break;
+ case 14:
+ $26 = HEAP32[$proto >> 2] | 0;
+ $e57 = $26 + 4 | 0;
+ $27 = HEAP32[$e57 >> 2] | 0;
+ $attr58 = $27 + 4 | 0;
+ $28 = HEAP32[$attr58 >> 2] | 0;
+ HEAP32[$28 >> 2] = $3;
+ STACKTOP = __stackBase__;
+ return $e_3 | 0;
+ }
+ return 0;
+}
+function _agFREEedge($e) {
+ $e = $e | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $3 = 0, $tail = 0, $4 = 0, $graph = 0, $5 = 0, $univ = 0, $6 = 0, $edgeattr = 0, $7 = 0, $dict1 = 0, $8 = 0, $call2 = 0, $cmp9 = 0, $attr = 0, $9 = 0, $10 = 0, $i_010 = 0, $arrayidx = 0, $11 = 0, $inc = 0, $cmp = 0, $12 = 0, $_lcssa = 0, $13 = 0, $didset = 0, $14 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $e | 0;
+ $1 = $e;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $3 = $2 | 15;
+ HEAP32[$1 >> 2] = $3;
+ $tail = $e + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $graph = $4 + 20 | 0;
+ $5 = HEAP32[$graph >> 2] | 0;
+ $univ = $5 + 16 | 0;
+ $6 = HEAP32[$univ >> 2] | 0;
+ $edgeattr = $6 + 8 | 0;
+ $7 = HEAP32[$edgeattr >> 2] | 0;
+ $dict1 = $7 + 4 | 0;
+ $8 = HEAP32[$dict1 >> 2] | 0;
+ $call2 = _dtsize($8) | 0;
+ $cmp9 = ($call2 | 0) > 0;
+ $attr = $e + 4 | 0;
+ $9 = HEAP32[$attr >> 2] | 0;
+ if ($cmp9) {
+ $i_010 = 0;
+ $10 = $9;
+ label = 3;
+ break;
+ } else {
+ $_lcssa = $9;
+ label = 4;
+ break;
+ }
+ case 3:
+ $arrayidx = $10 + ($i_010 << 2) | 0;
+ $11 = HEAP32[$arrayidx >> 2] | 0;
+ _agstrfree($11);
+ $inc = $i_010 + 1 | 0;
+ $cmp = ($inc | 0) < ($call2 | 0);
+ $12 = HEAP32[$attr >> 2] | 0;
+ if ($cmp) {
+ $i_010 = $inc;
+ $10 = $12;
+ label = 3;
+ break;
+ } else {
+ $_lcssa = $12;
+ label = 4;
+ break;
+ }
+ case 4:
+ $13 = $_lcssa;
+ _free($13);
+ $didset = $e + 8 | 0;
+ $14 = HEAP32[$didset >> 2] | 0;
+ _free($14);
+ _free($0);
+ return;
+ }
+}
+function _agDELedge($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $inedges = 0, $0 = 0, $searchf = 0, $1 = 0, $2 = 0, $call = 0, $cmp = 0, $call2 = 0, $3 = 0, $call4 = 0, $4 = 0, $5 = 0, $and = 0, $cmp5 = 0, $meta_node = 0, $6 = 0, $graph = 0, $7 = 0, $call8 = 0, $tobool24 = 0, $f_025 = 0, $head = 0, $8 = 0, $9 = 0, $call9 = 0, $inedges10 = 0, $10 = 0, $11 = 0, $searchf11 = 0, $12 = 0, $call13 = 0, $tobool14 = 0, $13 = 0, $call17 = 0, $tobool = 0, $14 = 0, $searchf20 = 0, $15 = 0, $call22 = 0, $outedges = 0, $16 = 0, $searchf23 = 0, $17 = 0, $call25 = 0, $root = 0, $18 = 0, $cmp26 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $inedges = $g + 24 | 0;
+ $0 = HEAP32[$inedges >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $2 = $e | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $2, 4) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call2 = _agerr(1, 139192, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $e, tempInt) | 0) | 0;
+ $3 = HEAP32[$inedges >> 2] | 0;
+ $call4 = _dtwalk($3, 98, 0) | 0;
+ label = 11;
+ break;
+ case 4:
+ $4 = $g;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $and = $5 & 64;
+ $cmp5 = ($and | 0) == 0;
+ if ($cmp5) {
+ label = 5;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 5:
+ $meta_node = $g + 36 | 0;
+ $6 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $6 + 20 | 0;
+ $7 = HEAP32[$graph >> 2] | 0;
+ $call8 = _agfstout($7, $6) | 0;
+ $tobool24 = ($call8 | 0) == 0;
+ if ($tobool24) {
+ label = 9;
+ break;
+ } else {
+ $f_025 = $call8;
+ label = 6;
+ break;
+ }
+ case 6:
+ $head = $f_025 + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $9 = $8;
+ $call9 = _agusergraph($9) | 0;
+ $inedges10 = $call9 + 24 | 0;
+ $10 = HEAP32[$inedges10 >> 2] | 0;
+ $11 = $10;
+ $searchf11 = $10;
+ $12 = HEAP32[$searchf11 >> 2] | 0;
+ $call13 = FUNCTION_TABLE_iiii[$12 & 1023]($11, $2, 4) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $13 = $call9;
+ _agDELedge($13, $e);
+ label = 8;
+ break;
+ case 8:
+ $call17 = _agnxtout($7, $f_025) | 0;
+ $tobool = ($call17 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ $f_025 = $call17;
+ label = 6;
+ break;
+ }
+ case 9:
+ $14 = HEAP32[$inedges >> 2] | 0;
+ $searchf20 = $14 | 0;
+ $15 = HEAP32[$searchf20 >> 2] | 0;
+ $call22 = FUNCTION_TABLE_iiii[$15 & 1023]($14, $2, 2) | 0;
+ $outedges = $g + 28 | 0;
+ $16 = HEAP32[$outedges >> 2] | 0;
+ $searchf23 = $16 | 0;
+ $17 = HEAP32[$searchf23 >> 2] | 0;
+ $call25 = FUNCTION_TABLE_iiii[$17 & 1023]($16, $2, 2) | 0;
+ $root = $g + 32 | 0;
+ $18 = HEAP32[$root >> 2] | 0;
+ $cmp26 = ($18 | 0) == ($g | 0);
+ if ($cmp26) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _agFREEedge($e);
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _printedge($d, $p, $ignored) {
+ $d = $d | 0;
+ $p = $p | 0;
+ $ignored = $ignored | 0;
+ var $2 = 0, $5 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $2 = HEAP32[(HEAP32[$p + 16 >> 2] | 0) + 12 >> 2] | 0;
+ $5 = HEAP32[(HEAP32[$p + 12 >> 2] | 0) + 12 >> 2] | 0;
+ _agerr(3, 119832, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $p, HEAP32[tempInt + 8 >> 2] = $2, HEAP32[tempInt + 16 >> 2] = $5, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return 0;
+}
+function _agcmpin($d, $e0, $e1, $disc) {
+ $d = $d | 0;
+ $e0 = $e0 | 0;
+ $e1 = $e1 | 0;
+ $disc = $disc | 0;
+ var $tail = 0, $0 = 0, $tobool = 0, $id = 0, $1 = 0, $cond = 0, $head = 0, $2 = 0, $tobool2 = 0, $id5 = 0, $3 = 0, $cond8 = 0, $tail9 = 0, $4 = 0, $tobool10 = 0, $id13 = 0, $5 = 0, $cond16 = 0, $head17 = 0, $6 = 0, $tobool18 = 0, $id21 = 0, $7 = 0, $cond24 = 0, $cmp = 0, $sub = 0, $cmp25 = 0, $sub27 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e0 + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $cond = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $id = $0 + 16 | 0;
+ $1 = HEAP32[$id >> 2] | 0;
+ $cond = $1;
+ label = 4;
+ break;
+ case 4:
+ $head = $e0 + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ $cond8 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $id5 = $2 + 16 | 0;
+ $3 = HEAP32[$id5 >> 2] | 0;
+ $cond8 = $3;
+ label = 6;
+ break;
+ case 6:
+ $tail9 = $e1 + 16 | 0;
+ $4 = HEAP32[$tail9 >> 2] | 0;
+ $tobool10 = ($4 | 0) == 0;
+ if ($tobool10) {
+ $cond16 = -1;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $id13 = $4 + 16 | 0;
+ $5 = HEAP32[$id13 >> 2] | 0;
+ $cond16 = $5;
+ label = 8;
+ break;
+ case 8:
+ $head17 = $e1 + 12 | 0;
+ $6 = HEAP32[$head17 >> 2] | 0;
+ $tobool18 = ($6 | 0) == 0;
+ if ($tobool18) {
+ $cond24 = -1;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $id21 = $6 + 16 | 0;
+ $7 = HEAP32[$id21 >> 2] | 0;
+ $cond24 = $7;
+ label = 10;
+ break;
+ case 10:
+ $cmp = ($cond8 | 0) == ($cond24 | 0);
+ if ($cmp) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $sub = $cond8 - $cond24 | 0;
+ $retval_0 = $sub;
+ label = 15;
+ break;
+ case 12:
+ $cmp25 = ($cond | 0) == ($cond16 | 0);
+ if ($cmp25) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $sub27 = $cond - $cond16 | 0;
+ $retval_0 = $sub27;
+ label = 15;
+ break;
+ case 14:
+ $call = _keycmp($e0, $e1) | 0;
+ $retval_0 = $call;
+ label = 15;
+ break;
+ case 15:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agcmpout($d, $e0, $e1, $disc) {
+ $d = $d | 0;
+ $e0 = $e0 | 0;
+ $e1 = $e1 | 0;
+ $disc = $disc | 0;
+ var $tail = 0, $0 = 0, $tobool = 0, $id = 0, $1 = 0, $cond = 0, $head = 0, $2 = 0, $tobool2 = 0, $id5 = 0, $3 = 0, $cond8 = 0, $tail9 = 0, $4 = 0, $tobool10 = 0, $id13 = 0, $5 = 0, $cond16 = 0, $head17 = 0, $6 = 0, $tobool18 = 0, $id21 = 0, $7 = 0, $cond24 = 0, $cmp = 0, $sub = 0, $cmp25 = 0, $sub27 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e0 + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $cond = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $id = $0 + 16 | 0;
+ $1 = HEAP32[$id >> 2] | 0;
+ $cond = $1;
+ label = 4;
+ break;
+ case 4:
+ $head = $e0 + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ if ($tobool2) {
+ $cond8 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $id5 = $2 + 16 | 0;
+ $3 = HEAP32[$id5 >> 2] | 0;
+ $cond8 = $3;
+ label = 6;
+ break;
+ case 6:
+ $tail9 = $e1 + 16 | 0;
+ $4 = HEAP32[$tail9 >> 2] | 0;
+ $tobool10 = ($4 | 0) == 0;
+ if ($tobool10) {
+ $cond16 = -1;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $id13 = $4 + 16 | 0;
+ $5 = HEAP32[$id13 >> 2] | 0;
+ $cond16 = $5;
+ label = 8;
+ break;
+ case 8:
+ $head17 = $e1 + 12 | 0;
+ $6 = HEAP32[$head17 >> 2] | 0;
+ $tobool18 = ($6 | 0) == 0;
+ if ($tobool18) {
+ $cond24 = -1;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $id21 = $6 + 16 | 0;
+ $7 = HEAP32[$id21 >> 2] | 0;
+ $cond24 = $7;
+ label = 10;
+ break;
+ case 10:
+ $cmp = ($cond | 0) == ($cond16 | 0);
+ if ($cmp) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $sub = $cond - $cond16 | 0;
+ $retval_0 = $sub;
+ label = 15;
+ break;
+ case 12:
+ $cmp25 = ($cond8 | 0) == ($cond24 | 0);
+ if ($cmp25) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $sub27 = $cond8 - $cond24 | 0;
+ $retval_0 = $sub27;
+ label = 15;
+ break;
+ case 14:
+ $call = _keycmp($e0, $e1) | 0;
+ $retval_0 = $call;
+ label = 15;
+ break;
+ case 15:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agusergraph($n) {
+ $n = $n | 0;
+ var $graph = 0, $0 = 0, $meta_node = 0, $1 = 0, $tobool = 0, $attr = 0, $2 = 0, $3 = 0, $4 = 0, $cond = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $graph = $n + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ $meta_node = $0 + 36 | 0;
+ $1 = HEAP32[$meta_node >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $cond = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $attr = $n + 4 | 0;
+ $2 = HEAP32[$attr >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $4 = $3;
+ $cond = $4;
+ label = 4;
+ break;
+ case 4:
+ return $cond | 0;
+ }
+ return 0;
+}
+function _keycmp($e0, $e1) {
+ $e0 = $e0 | 0;
+ $e1 = $e1 | 0;
+ var $attr = 0, $0 = 0, $tobool = 0, $1 = 0, $cond = 0, $attr2 = 0, $2 = 0, $tobool3 = 0, $3 = 0, $cond9 = 0, $cmp = 0, $tobool10 = 0, $cond11 = 0, $cmp12 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $attr = $e0 + 4 | 0;
+ $0 = HEAP32[$attr >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $cond = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[$0 >> 2] | 0;
+ $cond = $1;
+ label = 4;
+ break;
+ case 4:
+ $attr2 = $e1 + 4 | 0;
+ $2 = HEAP32[$attr2 >> 2] | 0;
+ $tobool3 = ($2 | 0) == 0;
+ if ($tobool3) {
+ $cond9 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = HEAP32[$2 >> 2] | 0;
+ $cond9 = $3;
+ label = 6;
+ break;
+ case 6:
+ $cmp = ($cond | 0) == 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $tobool10 = ($cond9 | 0) != 0;
+ $cond11 = $tobool10 << 31 >> 31;
+ $retval_0 = $cond11;
+ label = 10;
+ break;
+ case 8:
+ $cmp12 = ($cond9 | 0) == 0;
+ if ($cmp12) {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call = _strcmp($cond | 0, $cond9 | 0) | 0;
+ $retval_0 = $call;
+ label = 10;
+ break;
+ case 10:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agpushproto($g) {
+ $g = $g | 0;
+ _dup_proto($g, HEAP32[$g + 40 >> 2] | 0);
+ return;
+}
+function _dup_proto($g, $proto) {
+ $g = $g | 0;
+ $proto = $proto | 0;
+ var $call = 0, $0 = 0, $proto1 = 0, $1 = 0, $prev = 0, $2 = 0, $tobool = 0, $n2 = 0, $3 = 0, $e3 = 0, $4 = 0, $phitmp = 0, $phitmp11 = 0, $e_0 = 0, $n_0 = 0, $5 = 0, $call4 = 0, $6 = 0, $n5 = 0, $call8 = 0, $7 = 0, $e9 = 0, $8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _calloc(1, 12) | 0;
+ $0 = $call;
+ $proto1 = $g + 40 | 0;
+ $1 = HEAP32[$proto1 >> 2] | 0;
+ $prev = $call + 8 | 0;
+ $2 = $prev;
+ HEAP32[$2 >> 2] = $1;
+ $tobool = ($proto | 0) == 0;
+ if ($tobool) {
+ $n_0 = 0;
+ $e_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $n2 = $proto | 0;
+ $3 = HEAP32[$n2 >> 2] | 0;
+ $e3 = $proto + 4 | 0;
+ $4 = HEAP32[$e3 >> 2] | 0;
+ $phitmp = $3;
+ $phitmp11 = $4;
+ $n_0 = $phitmp;
+ $e_0 = $phitmp11;
+ label = 4;
+ break;
+ case 4:
+ $5 = $g;
+ $call4 = _agNEWnode($5, 108144, $n_0) | 0;
+ $6 = $call4;
+ $n5 = $call;
+ HEAP32[$n5 >> 2] = $6;
+ $call8 = _agNEWedge($5, $call4, $call4, $e_0) | 0;
+ $7 = $call8;
+ $e9 = $call + 4 | 0;
+ $8 = $e9;
+ HEAP32[$8 >> 2] = $7;
+ HEAP32[$proto1 >> 2] = $0;
+ return;
+ }
+}
+function _agpopproto($g) {
+ $g = $g | 0;
+ var $proto = 0, $0 = 0, $cmp = 0, $prev = 0, $1 = 0, $n = 0, $2 = 0, $e = 0, $3 = 0, $head = 0, $4 = 0, $tail = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $proto = $g + 40 | 0;
+ $0 = HEAP32[$proto >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $prev = $0 + 8 | 0;
+ $1 = HEAP32[$prev >> 2] | 0;
+ HEAP32[$proto >> 2] = $1;
+ $n = $0 | 0;
+ $2 = HEAP32[$n >> 2] | 0;
+ $e = $0 + 4 | 0;
+ $3 = HEAP32[$e >> 2] | 0;
+ $head = $3 + 12 | 0;
+ HEAP32[$head >> 2] = $2;
+ $4 = HEAP32[$e >> 2] | 0;
+ $tail = $4 + 16 | 0;
+ HEAP32[$tail >> 2] = $2;
+ $5 = HEAP32[$e >> 2] | 0;
+ $6 = $5;
+ _agFREEedge($6);
+ $7 = HEAP32[$n >> 2] | 0;
+ $8 = $7;
+ _agFREEnode($8);
+ $9 = $0;
+ _free($9);
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _agopen($name, $kind) {
+ $name = $name | 0;
+ $kind = $kind | 0;
+ var $call = 0, $call1 = 0, $tobool = 0, $tobool2 = 0, $or_cond = 0, $0 = 0, $call3 = 0, $call4 = 0, $1 = 0, $meta_node = 0, $2 = 0, $3 = 0, $4 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agNEWgraph($name, 0, $kind) | 0;
+ $call1 = _agNEWgraph($name, 0, 7) | 0;
+ $tobool = ($call | 0) == 0;
+ $tobool2 = ($call1 | 0) == 0;
+ $or_cond = $tobool | $tobool2;
+ if ($or_cond) {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = $call1;
+ $call3 = _agnodeattr($0, 151800, 0) | 0;
+ $call4 = _agnode($0, $name) | 0;
+ $1 = $call4;
+ $meta_node = $call + 36 | 0;
+ HEAP32[$meta_node >> 2] = $1;
+ $2 = $call | 0;
+ $3 = $call4 + 4 | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ HEAP32[$4 >> 2] = $2;
+ $retval_0 = $call;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agNEWgraph($name, $parent, $kind) {
+ $name = $name | 0;
+ $parent = $parent | 0;
+ $kind = $kind | 0;
+ var $0 = 0, $cmp = 0, $call = 0, $1 = 0, $call2 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $bf_value = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $10 = 0, $call3 = 0, $11 = 0, $nodes = 0, $12 = 0, $13 = 0, $14 = 0, $call4 = 0, $15 = 0, $inedges = 0, $16 = 0, $17 = 0, $18 = 0, $call5 = 0, $19 = 0, $outedges = 0, $20 = 0, $cmp6 = 0, $call9 = 0, $univ = 0, $21 = 0, $root = 0, $22 = 0, $23 = 0, $globattr = 0, $24 = 0, $dict = 0, $25 = 0, $26 = 0, $call11 = 0, $tobool = 0, $attr15 = 0, $27 = 0, $didset16 = 0, $28 = 0, $call13 = 0, $29 = 0, $attr = 0, $30 = 0, $sub = 0, $div = 0, $call14 = 0, $didset = 0, $31 = 0, $cmp1846 = 0, $attr22 = 0, $32 = 0, $i_047 = 0, $33 = 0, $34 = 0, $35 = 0, $arrayidx = 0, $36 = 0, $call21 = 0, $37 = 0, $arrayidx23 = 0, $inc = 0, $cmp18 = 0, $univ25 = 0, $38 = 0, $univ26 = 0, $39 = 0, $root27 = 0, $40 = 0, $root28 = 0, $41 = 0, $42 = 0, $globattr30 = 0, $43 = 0, $dict31 = 0, $44 = 0, $45 = 0, $call32 = 0, $tobool33 = 0, $attr43 = 0, $46 = 0, $didset44 = 0, $47 = 0, $call35 = 0, $48 = 0, $attr36 = 0, $49 = 0, $sub38 = 0, $div39 = 0, $call40 = 0, $didset41 = 0, $50 = 0, $cmp4749 = 0, $attr50 = 0, $attr53 = 0, $51 = 0, $i_150 = 0, $52 = 0, $arrayidx51 = 0, $53 = 0, $call52 = 0, $54 = 0, $arrayidx54 = 0, $inc56 = 0, $cmp47 = 0, $meta_node = 0, $55 = 0, $call59 = 0, $name60 = 0, $56 = 0, $proto = 0, $57 = 0, $proto63 = 0, $58 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[168567] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _agerr(1, 158152, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $retval_0 = 0;
+ label = 18;
+ break;
+ case 4:
+ $1 = HEAP32[42134] | 0;
+ $call2 = _calloc(1, $1) | 0;
+ $2 = $call2;
+ $3 = $call2;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $5 = $4 & -256;
+ $bf_value = $kind << 4;
+ $6 = $bf_value & 240;
+ $7 = $6 | $5;
+ $8 = $7 | 3;
+ HEAP32[$3 >> 2] = $8;
+ $9 = HEAP32[41974] | 0;
+ $10 = $9;
+ $call3 = _dtopen(89472, $10) | 0;
+ $11 = $call3;
+ $nodes = $call2 + 20 | 0;
+ $12 = $nodes;
+ HEAP32[$12 >> 2] = $11;
+ $13 = HEAP32[41974] | 0;
+ $14 = $13;
+ $call4 = _dtopen(89592, $14) | 0;
+ $15 = $call4;
+ $inedges = $call2 + 24 | 0;
+ $16 = $inedges;
+ HEAP32[$16 >> 2] = $15;
+ $17 = HEAP32[41974] | 0;
+ $18 = $17;
+ $call5 = _dtopen(89432, $18) | 0;
+ $19 = $call5;
+ $outedges = $call2 + 28 | 0;
+ $20 = $outedges;
+ HEAP32[$20 >> 2] = $19;
+ $cmp6 = ($parent | 0) == 0;
+ if ($cmp6) {
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ $call9 = _agnewdata() | 0;
+ $univ = $call2 + 16 | 0;
+ $21 = $univ;
+ HEAP32[$21 >> 2] = $call9;
+ $root = $call2 + 32 | 0;
+ $22 = $root;
+ HEAP32[$22 >> 2] = $2;
+ $23 = HEAP32[$21 >> 2] | 0;
+ $globattr = $23 + 12 | 0;
+ $24 = HEAP32[$globattr >> 2] | 0;
+ $dict = $24 + 4 | 0;
+ $25 = HEAP32[$dict >> 2] | 0;
+ $26 = $25;
+ $call11 = _dtsize($26) | 0;
+ $tobool = ($call11 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $attr15 = $call2 + 4 | 0;
+ $27 = $attr15;
+ HEAP32[$27 >> 2] = 0;
+ $didset16 = $call2 + 8 | 0;
+ $28 = $didset16;
+ HEAP32[$28 >> 2] = 0;
+ label = 15;
+ break;
+ case 7:
+ $call13 = _calloc($call11, 4) | 0;
+ $29 = $call13;
+ $attr = $call2 + 4 | 0;
+ $30 = $attr;
+ HEAP32[$30 >> 2] = $29;
+ $sub = $call11 + 7 | 0;
+ $div = ($sub | 0) / 8 & -1;
+ $call14 = _calloc($div, 1) | 0;
+ $didset = $call2 + 8 | 0;
+ $31 = $didset;
+ HEAP32[$31 >> 2] = $call14;
+ $cmp1846 = ($call11 | 0) > 0;
+ if ($cmp1846) {
+ label = 8;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 8:
+ $attr22 = $call2 + 4 | 0;
+ $32 = $attr22;
+ $i_047 = 0;
+ label = 9;
+ break;
+ case 9:
+ $33 = HEAP32[42137] | 0;
+ $34 = $33 + 4 | 0;
+ $35 = HEAP32[$34 >> 2] | 0;
+ $arrayidx = $35 + ($i_047 << 2) | 0;
+ $36 = HEAP32[$arrayidx >> 2] | 0;
+ $call21 = _agstrdup($36) | 0;
+ $37 = HEAP32[$32 >> 2] | 0;
+ $arrayidx23 = $37 + ($i_047 << 2) | 0;
+ HEAP32[$arrayidx23 >> 2] = $call21;
+ $inc = $i_047 + 1 | 0;
+ $cmp18 = ($inc | 0) < ($call11 | 0);
+ if ($cmp18) {
+ $i_047 = $inc;
+ label = 9;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 10:
+ $univ25 = $parent + 16 | 0;
+ $38 = HEAP32[$univ25 >> 2] | 0;
+ $univ26 = $call2 + 16 | 0;
+ $39 = $univ26;
+ HEAP32[$39 >> 2] = $38;
+ $root27 = $parent + 32 | 0;
+ $40 = HEAP32[$root27 >> 2] | 0;
+ $root28 = $call2 + 32 | 0;
+ $41 = $root28;
+ HEAP32[$41 >> 2] = $40;
+ $42 = HEAP32[$univ25 >> 2] | 0;
+ $globattr30 = $42 + 12 | 0;
+ $43 = HEAP32[$globattr30 >> 2] | 0;
+ $dict31 = $43 + 4 | 0;
+ $44 = HEAP32[$dict31 >> 2] | 0;
+ $45 = $44;
+ $call32 = _dtsize($45) | 0;
+ $tobool33 = ($call32 | 0) == 0;
+ if ($tobool33) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $attr43 = $call2 + 4 | 0;
+ $46 = $attr43;
+ HEAP32[$46 >> 2] = 0;
+ $didset44 = $call2 + 8 | 0;
+ $47 = $didset44;
+ HEAP32[$47 >> 2] = 0;
+ label = 15;
+ break;
+ case 12:
+ $call35 = _calloc($call32, 4) | 0;
+ $48 = $call35;
+ $attr36 = $call2 + 4 | 0;
+ $49 = $attr36;
+ HEAP32[$49 >> 2] = $48;
+ $sub38 = $call32 + 7 | 0;
+ $div39 = ($sub38 | 0) / 8 & -1;
+ $call40 = _calloc($div39, 1) | 0;
+ $didset41 = $call2 + 8 | 0;
+ $50 = $didset41;
+ HEAP32[$50 >> 2] = $call40;
+ $cmp4749 = ($call32 | 0) > 0;
+ if ($cmp4749) {
+ label = 13;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $attr50 = $parent + 4 | 0;
+ $attr53 = $call2 + 4 | 0;
+ $51 = $attr53;
+ $i_150 = 0;
+ label = 14;
+ break;
+ case 14:
+ $52 = HEAP32[$attr50 >> 2] | 0;
+ $arrayidx51 = $52 + ($i_150 << 2) | 0;
+ $53 = HEAP32[$arrayidx51 >> 2] | 0;
+ $call52 = _agstrdup($53) | 0;
+ $54 = HEAP32[$51 >> 2] | 0;
+ $arrayidx54 = $54 + ($i_150 << 2) | 0;
+ HEAP32[$arrayidx54 >> 2] = $call52;
+ $inc56 = $i_150 + 1 | 0;
+ $cmp47 = ($inc56 | 0) < ($call32 | 0);
+ if ($cmp47) {
+ $i_150 = $inc56;
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $meta_node = $call2 + 36 | 0;
+ $55 = $meta_node;
+ HEAP32[$55 >> 2] = 0;
+ $call59 = _agstrdup($name) | 0;
+ $name60 = $call2 + 12 | 0;
+ $56 = $name60;
+ HEAP32[$56 >> 2] = $call59;
+ $proto = $call2 + 40 | 0;
+ $57 = $proto;
+ HEAP32[$57 >> 2] = 0;
+ if ($cmp6) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $proto63 = $parent + 40 | 0;
+ $58 = HEAP32[$proto63 >> 2] | 0;
+ _dup_proto($2, $58);
+ $retval_0 = $2;
+ label = 18;
+ break;
+ case 17:
+ _agpushproto($2);
+ $retval_0 = $2;
+ label = 18;
+ break;
+ case 18:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agsubg($g, $name) {
+ $g = $g | 0;
+ $name = $name | 0;
+ var $meta_node = 0, $0 = 0, $graph = 0, $1 = 0, $2 = 0, $call = 0, $tobool = 0, $3 = 0, $call1 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, $bf_val_sext = 0, $call2 = 0, $tobool3 = 0, $call5 = 0, $8 = 0, $meta_node6 = 0, $9 = 0, $10 = 0, $11 = 0, $subg_0 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $meta_node = $g + 36 | 0;
+ $0 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $2 = $1;
+ $call = _agfindnode($2, $name) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $3 = $call;
+ $call1 = _agusergraph($3) | 0;
+ $subg_0 = $call1;
+ label = 6;
+ break;
+ case 4:
+ $4 = $g;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $6 = $5 >>> 4;
+ $7 = $6 << 28;
+ $bf_val_sext = $7 >> 28;
+ $call2 = _agNEWgraph($name, $g, $bf_val_sext) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call5 = _agnode($2, $name) | 0;
+ $8 = $call5;
+ $meta_node6 = $call2 + 36 | 0;
+ HEAP32[$meta_node6 >> 2] = $8;
+ $9 = $call2 | 0;
+ $10 = $call5 + 4 | 0;
+ $11 = HEAP32[$10 >> 2] | 0;
+ HEAP32[$11 >> 2] = $9;
+ $subg_0 = $call2;
+ label = 6;
+ break;
+ case 6:
+ _agINSgraph($g, $subg_0);
+ $retval_0 = $subg_0;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agINSgraph($g, $subg) {
+ $g = $g | 0;
+ $subg = $subg | 0;
+ var $meta_node = 0, $0 = 0, $meta_node1 = 0, $1 = 0, $tobool = 0, $tobool2 = 0, $or_cond = 0, $call = 0, $cmp = 0, $graph = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $call4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $meta_node = $g + 36 | 0;
+ $0 = HEAP32[$meta_node >> 2] | 0;
+ $meta_node1 = $subg + 36 | 0;
+ $1 = HEAP32[$meta_node1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ $tobool2 = ($1 | 0) == 0;
+ $or_cond = $tobool | $tobool2;
+ if ($or_cond) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _reach($1, $0) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $graph = $0 + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $3 = $2;
+ $4 = $0;
+ $5 = $1;
+ $call4 = _agedge($3, $4, $5) | 0;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _agfindsubg($g, $name) {
+ $g = $g | 0;
+ $name = $name | 0;
+ var $meta_node = 0, $0 = 0, $tobool = 0, $graph = 0, $1 = 0, $2 = 0, $call = 0, $tobool2 = 0, $3 = 0, $call4 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $meta_node = $g + 36 | 0;
+ $0 = HEAP32[$meta_node >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $2 = $1;
+ $call = _agfindnode($2, $name) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = $call;
+ $call4 = _agusergraph($3) | 0;
+ $retval_0 = $call4;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _reach($from, $to) {
+ $from = $from | 0;
+ $to = $to | 0;
+ var $call = 0, $call1 = 0;
+ $call = _dtopen(89472, HEAP32[41974] | 0) | 0;
+ $call1 = _reach0($call, $from, $to) | 0;
+ _dtclose($call);
+ return $call1 | 0;
+}
+function _agclose($g) {
+ $g = $g | 0;
+ var $cmp = 0, $0 = 0, $1 = 0, $_mask = 0, $cmp1 = 0, $and = 0, $cmp4 = 0, $meta_node = 0, $2 = 0, $graph = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $call = 0, $flag_0_ph = 0, $e_0_in_ph = 0, $e_0_in = 0, $tobool = 0, $call7 = 0, $head = 0, $7 = 0, $call8 = 0, $call9 = 0, $cmp10 = 0, $8 = 0, $9 = 0, $call13 = 0, $tobool15 = 0, $meta_0_ph = 0, $proto = 0, $10 = 0, $tobool1746 = 0, $11 = 0, $tobool17 = 0, $univ = 0, $12 = 0, $globattr = 0, $13 = 0, $dict = 0, $14 = 0, $15 = 0, $call20 = 0, $cmp2244 = 0, $attr = 0, $i_045 = 0, $16 = 0, $arrayidx = 0, $17 = 0, $inc = 0, $cmp22 = 0, $attr27 = 0, $18 = 0, $tobool28 = 0, $19 = 0, $didset = 0, $20 = 0, $tobool32 = 0, $root = 0, $21 = 0, $cmp36 = 0, $22 = 0, $call38 = 0, $tobool4042 = 0, $n_0_in43 = 0, $call42 = 0, $tobool40 = 0, $meta_node47 = 0, $23 = 0, $graph48 = 0, $24 = 0, $meta_node52 = 0, $25 = 0, $26 = 0, $nodes = 0, $27 = 0, $28 = 0, $call55 = 0, $inedges = 0, $29 = 0, $30 = 0, $call56 = 0, $outedges = 0, $31 = 0, $32 = 0, $call57 = 0, $name = 0, $33 = 0, $34 = 0, $35 = 0, $36 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($g | 0) == 0;
+ if ($cmp) {
+ label = 31;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = $g;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $_mask = $1 & 15;
+ $cmp1 = ($_mask | 0) == 3;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 4:
+ $and = $1 & 64;
+ $cmp4 = ($and | 0) == 0;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ $meta_0_ph = 0;
+ label = 12;
+ break;
+ }
+ case 5:
+ $meta_node = $g + 36 | 0;
+ $2 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $2 + 20 | 0;
+ $3 = HEAP32[$graph >> 2] | 0;
+ $4 = $3;
+ label = 6;
+ break;
+ case 6:
+ $5 = HEAP32[$meta_node >> 2] | 0;
+ $6 = $5;
+ $call = _agfstout($4, $6) | 0;
+ $e_0_in_ph = $call;
+ $flag_0_ph = 0;
+ label = 7;
+ break;
+ case 7:
+ $e_0_in = $e_0_in_ph;
+ label = 8;
+ break;
+ case 8:
+ $tobool = ($e_0_in | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call7 = _agnxtout($4, $e_0_in) | 0;
+ $head = $e_0_in + 12 | 0;
+ $7 = HEAP32[$head >> 2] | 0;
+ $call8 = _agfstin($4, $7) | 0;
+ $call9 = _agnxtin($4, $call8) | 0;
+ $cmp10 = ($call9 | 0) == 0;
+ if ($cmp10) {
+ label = 10;
+ break;
+ } else {
+ $e_0_in = $call7;
+ label = 8;
+ break;
+ }
+ case 10:
+ $8 = HEAP32[$head >> 2] | 0;
+ $9 = $8;
+ $call13 = _agusergraph($9) | 0;
+ _agclose($call13);
+ $e_0_in_ph = $call7;
+ $flag_0_ph = 1;
+ label = 7;
+ break;
+ case 11:
+ $tobool15 = ($flag_0_ph | 0) == 0;
+ if ($tobool15) {
+ $meta_0_ph = $3;
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 12:
+ $proto = $g + 40 | 0;
+ $10 = HEAP32[$proto >> 2] | 0;
+ $tobool1746 = ($10 | 0) == 0;
+ if ($tobool1746) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _agpopproto($g);
+ $11 = HEAP32[$proto >> 2] | 0;
+ $tobool17 = ($11 | 0) == 0;
+ if ($tobool17) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 14:
+ if ($cmp4) {
+ label = 15;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 15:
+ $univ = $g + 16 | 0;
+ $12 = HEAP32[$univ >> 2] | 0;
+ $globattr = $12 + 12 | 0;
+ $13 = HEAP32[$globattr >> 2] | 0;
+ $dict = $13 + 4 | 0;
+ $14 = HEAP32[$dict >> 2] | 0;
+ $15 = $14;
+ $call20 = _dtsize($15) | 0;
+ $cmp2244 = ($call20 | 0) > 0;
+ if ($cmp2244) {
+ label = 16;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 16:
+ $attr = $g + 4 | 0;
+ $i_045 = 0;
+ label = 17;
+ break;
+ case 17:
+ $16 = HEAP32[$attr >> 2] | 0;
+ $arrayidx = $16 + ($i_045 << 2) | 0;
+ $17 = HEAP32[$arrayidx >> 2] | 0;
+ _agstrfree($17);
+ $inc = $i_045 + 1 | 0;
+ $cmp22 = ($inc | 0) < ($call20 | 0);
+ if ($cmp22) {
+ $i_045 = $inc;
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $attr27 = $g + 4 | 0;
+ $18 = HEAP32[$attr27 >> 2] | 0;
+ $tobool28 = ($18 | 0) == 0;
+ if ($tobool28) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $19 = $18;
+ _free($19);
+ label = 20;
+ break;
+ case 20:
+ $didset = $g + 8 | 0;
+ $20 = HEAP32[$didset >> 2] | 0;
+ $tobool32 = ($20 | 0) == 0;
+ if ($tobool32) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ _free($20);
+ label = 22;
+ break;
+ case 22:
+ $root = $g + 32 | 0;
+ $21 = HEAP32[$root >> 2] | 0;
+ $cmp36 = ($21 | 0) == ($g | 0);
+ if ($cmp36) {
+ label = 23;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 23:
+ $22 = $g;
+ $call38 = _agfstnode($22) | 0;
+ $tobool4042 = ($call38 | 0) == 0;
+ if ($tobool4042) {
+ label = 25;
+ break;
+ } else {
+ $n_0_in43 = $call38;
+ label = 24;
+ break;
+ }
+ case 24:
+ $call42 = _agnxtnode($22, $n_0_in43) | 0;
+ _agDELnode($22, $n_0_in43);
+ $tobool40 = ($call42 | 0) == 0;
+ if ($tobool40) {
+ label = 25;
+ break;
+ } else {
+ $n_0_in43 = $call42;
+ label = 24;
+ break;
+ }
+ case 25:
+ if ($cmp4) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $meta_node47 = $g + 36 | 0;
+ $23 = HEAP32[$meta_node47 >> 2] | 0;
+ $graph48 = $23 + 20 | 0;
+ $24 = HEAP32[$graph48 >> 2] | 0;
+ _agclose($24);
+ label = 27;
+ break;
+ case 27:
+ _agfreedata($g);
+ label = 30;
+ break;
+ case 28:
+ if ($cmp4) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ $meta_node52 = $g + 36 | 0;
+ $25 = HEAP32[$meta_node52 >> 2] | 0;
+ $26 = $25 | 0;
+ _agdelete($meta_0_ph, $26);
+ label = 30;
+ break;
+ case 30:
+ $nodes = $g + 20 | 0;
+ $27 = HEAP32[$nodes >> 2] | 0;
+ $28 = $27;
+ $call55 = _dtclose($28) | 0;
+ $inedges = $g + 24 | 0;
+ $29 = HEAP32[$inedges >> 2] | 0;
+ $30 = $29;
+ $call56 = _dtclose($30) | 0;
+ $outedges = $g + 28 | 0;
+ $31 = HEAP32[$outedges >> 2] | 0;
+ $32 = $31;
+ $call57 = _dtclose($32) | 0;
+ $name = $g + 12 | 0;
+ $33 = HEAP32[$name >> 2] | 0;
+ _agstrfree($33);
+ $34 = HEAP32[$0 >> 2] | 0;
+ $35 = $34 | 15;
+ HEAP32[$0 >> 2] = $35;
+ $36 = $g | 0;
+ _free($36);
+ label = 31;
+ break;
+ case 31:
+ return;
+ }
+}
+function _agfreedata($g) {
+ $g = $g | 0;
+ var $univ = 0, $2 = 0;
+ $univ = $g + 16 | 0;
+ $2 = $g;
+ _agFREEdict($2, HEAP32[(HEAP32[$univ >> 2] | 0) + 12 >> 2] | 0);
+ _agFREEdict($2, HEAP32[(HEAP32[$univ >> 2] | 0) + 4 >> 2] | 0);
+ _agFREEdict($2, HEAP32[(HEAP32[$univ >> 2] | 0) + 8 >> 2] | 0);
+ _dtclose(HEAP32[HEAP32[$univ >> 2] >> 2] | 0);
+ _free(HEAP32[$univ >> 2] | 0);
+ return;
+}
+function _agdelete($g, $obj) {
+ $g = $g | 0;
+ $obj = $obj | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $obj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ if (($bf_val_sext | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 3) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $3 = $g;
+ $4 = $obj;
+ _agDELnode($3, $4);
+ label = 6;
+ break;
+ case 4:
+ $5 = $g;
+ $6 = $obj;
+ _agDELedge($5, $6);
+ label = 6;
+ break;
+ case 5:
+ $7 = $obj;
+ _agclose($7);
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _agcontains($g, $obj) {
+ $g = $g | 0;
+ $obj = $obj | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $id = 0, $3 = 0, $4 = 0, $5 = 0, $call = 0, $cmp = 0, $conv = 0, $inedges = 0, $6 = 0, $searchf = 0, $7 = 0, $call3 = 0, $cmp4 = 0, $conv5 = 0, $meta_node = 0, $8 = 0, $meta_node7 = 0, $9 = 0, $10 = 0, $call8 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $obj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ if (($bf_val_sext | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 3) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ }
+ case 3:
+ $id = $obj + 16 | 0;
+ $3 = $id;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $5 = $g;
+ $call = _agidnode($5, $4) | 0;
+ $cmp = ($call | 0) != 0;
+ $conv = $cmp & 1;
+ $retval_0 = $conv;
+ label = 6;
+ break;
+ case 4:
+ $inedges = $g + 24 | 0;
+ $6 = HEAP32[$inedges >> 2] | 0;
+ $searchf = $6 | 0;
+ $7 = HEAP32[$searchf >> 2] | 0;
+ $call3 = FUNCTION_TABLE_iiii[$7 & 1023]($6, $obj, 4) | 0;
+ $cmp4 = ($call3 | 0) != 0;
+ $conv5 = $cmp4 & 1;
+ $retval_0 = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $meta_node = $g + 36 | 0;
+ $8 = HEAP32[$meta_node >> 2] | 0;
+ $meta_node7 = $obj + 36 | 0;
+ $9 = $meta_node7;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $call8 = _reach($8, $10) | 0;
+ $retval_0 = $call8;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _aginsert($g, $obj) {
+ $g = $g | 0;
+ $obj = $obj | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $bf_val_sext = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $obj;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 << 28;
+ $bf_val_sext = $2 >> 28;
+ if (($bf_val_sext | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($bf_val_sext | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($bf_val_sext | 0) == 3) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $3 = $g;
+ $4 = $obj;
+ _agINSnode($3, $4);
+ label = 6;
+ break;
+ case 4:
+ $5 = $g;
+ $6 = $obj;
+ _agINSedge($5, $6);
+ label = 6;
+ break;
+ case 5:
+ $7 = $obj;
+ _agINSgraph($g, $7);
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _agnnodes($g) {
+ $g = $g | 0;
+ return _dtsize(HEAP32[$g + 20 >> 2] | 0) | 0;
+}
+function _agnedges($g) {
+ $g = $g | 0;
+ return _dtsize(HEAP32[$g + 28 >> 2] | 0) | 0;
+}
+function _reach0($m, $from, $to) {
+ $m = $m | 0;
+ $from = $from | 0;
+ $to = $to | 0;
+ var $cmp = 0, $graph = 0, $0 = 0, $root = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $call = 0, $tobool = 0, $searchf = 0, $5 = 0, $6 = 0, $call3 = 0, $7 = 0, $8 = 0, $call5 = 0, $tobool616 = 0, $e_0_in17 = 0, $9 = 0, $head = 0, $10 = 0, $11 = 0, $call8 = 0, $cmp9 = 0, $12 = 0, $13 = 0, $call11 = 0, $tobool12 = 0, $14 = 0, $15 = 0, $call16 = 0, $tobool6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($from | 0) == ($to | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $graph = $from + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ $root = $0 + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $2 = $1;
+ $3 = $from;
+ $4 = $to;
+ $call = _agfindedge($2, $3, $4) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 8;
+ break;
+ }
+ case 4:
+ $searchf = $m | 0;
+ $5 = HEAP32[$searchf >> 2] | 0;
+ $6 = $from | 0;
+ $call3 = FUNCTION_TABLE_iiii[$5 & 1023]($m, $6, 1) | 0;
+ $7 = HEAP32[$graph >> 2] | 0;
+ $8 = $7;
+ $call5 = _agfstout($8, $3) | 0;
+ $tobool616 = ($call5 | 0) == 0;
+ if ($tobool616) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ $e_0_in17 = $call5;
+ label = 5;
+ break;
+ }
+ case 5:
+ $9 = HEAP32[$searchf >> 2] | 0;
+ $head = $e_0_in17 + 12 | 0;
+ $10 = HEAP32[$head >> 2] | 0;
+ $11 = $10 | 0;
+ $call8 = FUNCTION_TABLE_iiii[$9 & 1023]($m, $11, 4) | 0;
+ $cmp9 = ($call8 | 0) == 0;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $12 = HEAP32[$head >> 2] | 0;
+ $13 = $12;
+ $call11 = _reach0($m, $13, $to) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 8;
+ break;
+ }
+ case 7:
+ $14 = HEAP32[$graph >> 2] | 0;
+ $15 = $14;
+ $call16 = _agnxtout($15, $e_0_in17) | 0;
+ $tobool6 = ($call16 | 0) == 0;
+ if ($tobool6) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ $e_0_in17 = $call16;
+ label = 5;
+ break;
+ }
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agnewdata() {
+ var $call = 0, $0 = 0, $1 = 0, $2 = 0, $call1 = 0, $3 = 0, $node_dict = 0, $call2 = 0, $4 = 0, $globattr = 0, $5 = 0, $call3 = 0, $6 = 0, $nodeattr = 0, $7 = 0, $call4 = 0, $8 = 0, $edgeattr = 0, $9 = 0, $10 = 0, $tobool = 0, $11 = 0, $univ = 0, $12 = 0, $globattr6 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, $univ8 = 0, $17 = 0, $nodeattr9 = 0, $18 = 0, $19 = 0, $20 = 0, $21 = 0, $univ11 = 0, $22 = 0, $edgeattr12 = 0, $23 = 0, $24 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _calloc(1, 24) | 0;
+ $0 = $call;
+ $1 = HEAP32[41974] | 0;
+ $2 = $1;
+ $call1 = _dtopen(89512, $2) | 0;
+ $3 = $call1;
+ $node_dict = $call;
+ HEAP32[$node_dict >> 2] = $3;
+ $call2 = _agNEWdict(129568) | 0;
+ $4 = $call2;
+ $globattr = $call + 12 | 0;
+ $5 = $globattr;
+ HEAP32[$5 >> 2] = $4;
+ $call3 = _agNEWdict(118008) | 0;
+ $6 = $call3;
+ $nodeattr = $call + 4 | 0;
+ $7 = $nodeattr;
+ HEAP32[$7 >> 2] = $6;
+ $call4 = _agNEWdict(112624) | 0;
+ $8 = $call4;
+ $edgeattr = $call + 8 | 0;
+ $9 = $edgeattr;
+ HEAP32[$9 >> 2] = $8;
+ $10 = HEAP32[42137] | 0;
+ $tobool = ($10 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $11 = HEAP32[$5 >> 2] | 0;
+ $univ = $10 + 16 | 0;
+ $12 = HEAP32[$univ >> 2] | 0;
+ $globattr6 = $12 + 12 | 0;
+ $13 = HEAP32[$globattr6 >> 2] | 0;
+ $14 = $11;
+ _agcopydict($14, $13);
+ $15 = HEAP32[$7 >> 2] | 0;
+ $16 = HEAP32[42137] | 0;
+ $univ8 = $16 + 16 | 0;
+ $17 = HEAP32[$univ8 >> 2] | 0;
+ $nodeattr9 = $17 + 4 | 0;
+ $18 = HEAP32[$nodeattr9 >> 2] | 0;
+ $19 = $15;
+ _agcopydict($19, $18);
+ $20 = HEAP32[$9 >> 2] | 0;
+ $21 = HEAP32[42137] | 0;
+ $univ11 = $21 + 16 | 0;
+ $22 = HEAP32[$univ11 >> 2] | 0;
+ $edgeattr12 = $22 + 8 | 0;
+ $23 = HEAP32[$edgeattr12 >> 2] | 0;
+ $24 = $20;
+ _agcopydict($24, $23);
+ label = 4;
+ break;
+ case 4:
+ return $0 | 0;
+ }
+ return 0;
+}
+function _agread($fp) {
+ $fp = $fp | 0;
+ _aglexinit($fp, 0);
+ _agparse();
+ return HEAP32[42138] | 0;
+}
+function _agmemread($cp) {
+ $cp = $cp | 0;
+ var $0 = 0;
+ $0 = HEAP32[42142] | 0;
+ HEAP32[42142] = 676;
+ _aglexinit($cp, 0);
+ _agparse();
+ HEAP32[42142] = $0;
+ return HEAP32[42138] | 0;
+}
+function _memgets($ubuf, $n, $mbuf) {
+ $ubuf = $ubuf | 0;
+ $n = $n | 0;
+ $mbuf = $mbuf | 0;
+ var $tobool = 0, $0 = 0, $sub = 0, $to_0 = 0, $i_0 = 0, $cmp = 0, $1 = 0, $2 = 0, $cmp1 = 0, $tobool4 = 0, $incdec_ptr = 0, $cmp9 = 0, $incdec_ptr12 = 0, $3 = 0, $incdec_ptr13 = 0, $inc = 0, $to_1 = 0, $clp_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($n | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = $mbuf;
+ HEAP32[2808] = $0;
+ label = 4;
+ break;
+ case 4:
+ $sub = $n - 1 | 0;
+ $i_0 = 0;
+ $to_0 = $ubuf;
+ label = 5;
+ break;
+ case 5:
+ $cmp = ($i_0 | 0) < ($sub | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ $clp_0 = $ubuf;
+ $to_1 = $to_0;
+ label = 11;
+ break;
+ }
+ case 6:
+ $1 = HEAP32[2808] | 0;
+ $2 = HEAP8[$1] | 0;
+ $cmp1 = $2 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $tobool4 = ($i_0 | 0) == 0;
+ if ($tobool4) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $incdec_ptr = $to_0 + 1 | 0;
+ HEAP8[$to_0] = 10;
+ $clp_0 = $ubuf;
+ $to_1 = $incdec_ptr;
+ label = 11;
+ break;
+ case 9:
+ HEAP32[2808] = 0;
+ $clp_0 = 0;
+ $to_1 = $to_0;
+ label = 11;
+ break;
+ case 10:
+ $cmp9 = $2 << 24 >> 24 == 10;
+ $incdec_ptr12 = $1 + 1 | 0;
+ HEAP32[2808] = $incdec_ptr12;
+ $3 = HEAP8[$1] | 0;
+ $incdec_ptr13 = $to_0 + 1 | 0;
+ HEAP8[$to_0] = $3;
+ $inc = $i_0 + 1 | 0;
+ if ($cmp9) {
+ $clp_0 = $ubuf;
+ $to_1 = $incdec_ptr13;
+ label = 11;
+ break;
+ } else {
+ $i_0 = $inc;
+ $to_0 = $incdec_ptr13;
+ label = 5;
+ break;
+ }
+ case 11:
+ HEAP8[$to_1] = 0;
+ return $clp_0 | 0;
+ }
+ return 0;
+}
+function _agstrcanon($arg, $buf) {
+ $arg = $arg | 0;
+ $buf = $buf | 0;
+ var $call = 0, $tobool = 0, $p_09 = 0, $0 = 0, $tobool110 = 0, $1 = 0, $p_012 = 0, $s_011 = 0, $incdec_ptr2 = 0, $p_0 = 0, $2 = 0, $tobool1 = 0, $p_0_lcssa = 0, $buf_pn_lcssa = 0, $incdec_ptr4 = 0, $call5 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _aghtmlstr($arg) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAP8[$buf] = 60;
+ $p_09 = $buf + 1 | 0;
+ $0 = HEAP8[$arg] | 0;
+ $tobool110 = $0 << 24 >> 24 == 0;
+ if ($tobool110) {
+ $buf_pn_lcssa = $buf;
+ $p_0_lcssa = $p_09;
+ label = 5;
+ break;
+ } else {
+ $s_011 = $arg;
+ $p_012 = $p_09;
+ $1 = $0;
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr2 = $s_011 + 1 | 0;
+ HEAP8[$p_012] = $1;
+ $p_0 = $p_012 + 1 | 0;
+ $2 = HEAP8[$incdec_ptr2] | 0;
+ $tobool1 = $2 << 24 >> 24 == 0;
+ if ($tobool1) {
+ $buf_pn_lcssa = $p_012;
+ $p_0_lcssa = $p_0;
+ label = 5;
+ break;
+ } else {
+ $s_011 = $incdec_ptr2;
+ $p_012 = $p_0;
+ $1 = $2;
+ label = 4;
+ break;
+ }
+ case 5:
+ $incdec_ptr4 = $buf_pn_lcssa + 2 | 0;
+ HEAP8[$p_0_lcssa] = 62;
+ HEAP8[$incdec_ptr4] = 0;
+ $retval_0 = $buf;
+ label = 7;
+ break;
+ case 6:
+ $call5 = __agstrcanon($arg, $buf) | 0;
+ $retval_0 = $call5;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agsetiodisc($myfgets, $myfwrite, $myferror) {
+ $myfgets = $myfgets | 0;
+ $myfwrite = $myfwrite | 0;
+ $myferror = $myferror | 0;
+ var $tobool = 0, $tobool1 = 0, $tobool4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($myfgets | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAP32[42142] = $myfgets;
+ label = 4;
+ break;
+ case 4:
+ $tobool1 = ($myfwrite | 0) == 0;
+ if ($tobool1) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[42143] = $myfwrite;
+ label = 6;
+ break;
+ case 6:
+ $tobool4 = ($myferror | 0) == 0;
+ if ($tobool4) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ HEAP32[42144] = $myferror;
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function __agstrcanon($arg, $buf) {
+ $arg = $arg | 0;
+ $buf = $buf | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $incdec_ptr = 0, $incdec_ptr3 = 0, $1 = 0, $call = 0, $tobool22 = 0, $s_0_ph = 0, $uc_0_ph = 0, $p_0_ph = 0, $cnt_0_ph = 0, $has_special_0_ph = 0, $backslash_pending_0_ph = 0, $s_0 = 0, $uc_0 = 0, $p_0 = 0, $cnt_0 = 0, $has_special_0 = 0, $incdec_ptr8 = 0, $conv4 = 0, $call10 = 0, $notlhs = 0, $notrhs = 0, $or_cond_not = 0, $cmp18 = 0, $or_cond37 = 0, $brmerge = 0, $_mux = 0, $call23 = 0, $tobool24 = 0, $_has_special_0 = 0, $p_1 = 0, $has_special_1 = 0, $incdec_ptr29 = 0, $incdec_ptr30 = 0, $2 = 0, $inc = 0, $conv31 = 0, $tobool32 = 0, $tobool32_not = 0, $or_cond38 = 0, $call36 = 0, $tobool37 = 0, $3 = 0, $conv40 = 0, $call41 = 0, $tobool42 = 0, $4 = 0, $cmp46 = 0, $call49 = 0, $tobool50 = 0, $call53 = 0, $tobool54 = 0, $incdec_ptr56 = 0, $incdec_ptr57 = 0, $rem36 = 0, $cmp62 = 0, $5 = 0, $call66 = 0, $tobool67 = 0, $6 = 0, $conv70 = 0, $call71 = 0, $tobool72 = 0, $7 = 0, $cmp76 = 0, $call79 = 0, $tobool80 = 0, $call83 = 0, $tobool84 = 0, $incdec_ptr86 = 0, $incdec_ptr87 = 0, $incdec_ptr92 = 0, $tobool93 = 0, $call96 = 0, $cmp97 = 0, $buf_arg = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($arg | 0) == 0;
+ if ($cmp) {
+ $retval_0 = 142720;
+ label = 27;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$arg] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ if ($cmp1) {
+ $retval_0 = 142720;
+ label = 27;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $buf + 1 | 0;
+ HEAP8[$buf] = 34;
+ $incdec_ptr3 = $arg + 1 | 0;
+ $1 = HEAP8[$arg] | 0;
+ $call = __is_number_char($1) | 0;
+ $tobool22 = ($call | 0) == 0;
+ $backslash_pending_0_ph = 1;
+ $has_special_0_ph = 0;
+ $cnt_0_ph = 0;
+ $p_0_ph = $incdec_ptr;
+ $uc_0_ph = $1;
+ $s_0_ph = $incdec_ptr3;
+ label = 5;
+ break;
+ case 5:
+ $has_special_0 = $has_special_0_ph;
+ $cnt_0 = $cnt_0_ph;
+ $p_0 = $p_0_ph;
+ $uc_0 = $uc_0_ph;
+ $s_0 = $s_0_ph;
+ label = 6;
+ break;
+ case 6:
+ if (($uc_0 << 24 >> 24 | 0) == 34) {
+ label = 7;
+ break;
+ } else if (($uc_0 << 24 >> 24 | 0) == 0) {
+ label = 25;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $incdec_ptr8 = $p_0 + 1 | 0;
+ HEAP8[$p_0] = 92;
+ $has_special_1 = 1;
+ $p_1 = $incdec_ptr8;
+ label = 10;
+ break;
+ case 8:
+ $conv4 = $uc_0 & 255;
+ $call10 = _isalnum($conv4 | 0) | 0;
+ $notlhs = ($call10 | 0) == 0;
+ $notrhs = $uc_0 << 24 >> 24 != 95;
+ $or_cond_not = $notrhs & $notlhs;
+ $cmp18 = $uc_0 << 24 >> 24 > -1;
+ $or_cond37 = $or_cond_not & $cmp18;
+ $brmerge = $or_cond37 | $tobool22;
+ $_mux = $or_cond37 ? 1 : $has_special_0;
+ if ($brmerge) {
+ $has_special_1 = $_mux;
+ $p_1 = $p_0;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call23 = __is_number_char($uc_0) | 0;
+ $tobool24 = ($call23 | 0) == 0;
+ $_has_special_0 = $tobool24 ? 1 : $has_special_0;
+ $has_special_1 = $_has_special_0;
+ $p_1 = $p_0;
+ label = 10;
+ break;
+ case 10:
+ $incdec_ptr29 = $p_1 + 1 | 0;
+ HEAP8[$p_1] = $uc_0;
+ $incdec_ptr30 = $s_0 + 1 | 0;
+ $2 = HEAP8[$s_0] | 0;
+ $inc = $cnt_0 + 1 | 0;
+ $conv31 = $2 & 255;
+ $tobool32 = $2 << 24 >> 24 != 0;
+ $tobool32_not = $tobool32 ^ 1;
+ $or_cond38 = $backslash_pending_0_ph | $tobool32_not;
+ if ($or_cond38) {
+ label = 17;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call36 = __is_number_char($uc_0) | 0;
+ $tobool37 = ($call36 | 0) == 0;
+ if ($tobool37) {
+ label = 12;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ $3 = HEAP8[$p_1] | 0;
+ $conv40 = $3 << 24 >> 24;
+ $call41 = _isalpha($conv40 | 0) | 0;
+ $tobool42 = ($call41 | 0) == 0;
+ if ($tobool42) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $4 = HEAP8[$p_1] | 0;
+ $cmp46 = $4 << 24 >> 24 == 92;
+ if ($cmp46) {
+ label = 14;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 14:
+ $call49 = __is_number_char($2) | 0;
+ $tobool50 = ($call49 | 0) == 0;
+ if ($tobool50) {
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 15:
+ $call53 = _isalpha($conv31 | 0) | 0;
+ $tobool54 = ($call53 | 0) == 0;
+ if ($tobool54) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $incdec_ptr56 = $p_1 + 2 | 0;
+ HEAP8[$incdec_ptr29] = 92;
+ $incdec_ptr57 = $p_1 + 3 | 0;
+ HEAP8[$incdec_ptr56] = 10;
+ $backslash_pending_0_ph = 1;
+ $has_special_0_ph = 1;
+ $cnt_0_ph = $inc;
+ $p_0_ph = $incdec_ptr57;
+ $uc_0_ph = $2;
+ $s_0_ph = $incdec_ptr30;
+ label = 5;
+ break;
+ case 17:
+ if ($tobool32) {
+ label = 18;
+ break;
+ } else {
+ $has_special_0 = $has_special_1;
+ $cnt_0 = $inc;
+ $p_0 = $incdec_ptr29;
+ $uc_0 = 0;
+ $s_0 = $incdec_ptr30;
+ label = 6;
+ break;
+ }
+ case 18:
+ $rem36 = $inc & 127;
+ $cmp62 = ($rem36 | 0) == 0;
+ if ($cmp62) {
+ label = 19;
+ break;
+ } else {
+ $has_special_0 = $has_special_1;
+ $cnt_0 = $inc;
+ $p_0 = $incdec_ptr29;
+ $uc_0 = $2;
+ $s_0 = $incdec_ptr30;
+ label = 6;
+ break;
+ }
+ case 19:
+ $5 = HEAP8[$p_1] | 0;
+ $call66 = __is_number_char($5) | 0;
+ $tobool67 = ($call66 | 0) == 0;
+ if ($tobool67) {
+ label = 20;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 20:
+ $6 = HEAP8[$p_1] | 0;
+ $conv70 = $6 << 24 >> 24;
+ $call71 = _isalpha($conv70 | 0) | 0;
+ $tobool72 = ($call71 | 0) == 0;
+ if ($tobool72) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $7 = HEAP8[$p_1] | 0;
+ $cmp76 = $7 << 24 >> 24 == 92;
+ if ($cmp76) {
+ label = 22;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 22:
+ $call79 = __is_number_char($2) | 0;
+ $tobool80 = ($call79 | 0) == 0;
+ if ($tobool80) {
+ label = 23;
+ break;
+ } else {
+ $backslash_pending_0_ph = 0;
+ $has_special_0_ph = $has_special_1;
+ $cnt_0_ph = $inc;
+ $p_0_ph = $incdec_ptr29;
+ $uc_0_ph = $2;
+ $s_0_ph = $incdec_ptr30;
+ label = 5;
+ break;
+ }
+ case 23:
+ $call83 = _isalpha($conv31 | 0) | 0;
+ $tobool84 = ($call83 | 0) == 0;
+ if ($tobool84) {
+ label = 24;
+ break;
+ } else {
+ $backslash_pending_0_ph = 0;
+ $has_special_0_ph = $has_special_1;
+ $cnt_0_ph = $inc;
+ $p_0_ph = $incdec_ptr29;
+ $uc_0_ph = $2;
+ $s_0_ph = $incdec_ptr30;
+ label = 5;
+ break;
+ }
+ case 24:
+ $incdec_ptr86 = $p_1 + 2 | 0;
+ HEAP8[$incdec_ptr29] = 92;
+ $incdec_ptr87 = $p_1 + 3 | 0;
+ HEAP8[$incdec_ptr86] = 10;
+ $has_special_0 = 1;
+ $cnt_0 = $inc;
+ $p_0 = $incdec_ptr87;
+ $uc_0 = $2;
+ $s_0 = $incdec_ptr30;
+ label = 6;
+ break;
+ case 25:
+ $incdec_ptr92 = $p_0 + 1 | 0;
+ HEAP8[$p_0] = 34;
+ HEAP8[$incdec_ptr92] = 0;
+ $tobool93 = ($has_special_0 | 0) == 0;
+ if ($tobool93) {
+ label = 26;
+ break;
+ } else {
+ $retval_0 = $buf;
+ label = 27;
+ break;
+ }
+ case 26:
+ $call96 = _agtoken($arg) | 0;
+ $cmp97 = ($call96 | 0) > -1;
+ $buf_arg = $cmp97 ? $buf : $arg;
+ $retval_0 = $buf_arg;
+ label = 27;
+ break;
+ case 27:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agputs($s, $fp) {
+ $s = $s | 0;
+ $fp = $fp | 0;
+ var $call = 0;
+ $call = _strlen($s | 0) | 0;
+ return ((FUNCTION_TABLE_iiiii[HEAP32[42143] & 1023]($s, 1, $call, $fp) | 0) == ($call | 0) ? 1 : -1) | 0;
+}
+function _agputc($c, $fp) {
+ $c = $c | 0;
+ $fp = $fp | 0;
+ var $cc = 0, $c_ = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $cc = __stackBase__ | 0;
+ HEAP8[$cc] = $c & 255;
+ $c_ = (FUNCTION_TABLE_iiiii[HEAP32[42143] & 1023]($cc, 1, 1, $fp) | 0) == 1 ? $c : -1;
+ STACKTOP = __stackBase__;
+ return $c_ | 0;
+}
+function _agcanonical($str) {
+ $str = $str | 0;
+ return _agstrcanon($str, _getoutputbuffer($str) | 0) | 0;
+}
+function _getoutputbuffer($str) {
+ $str = $str | 0;
+ var $call = 0, $mul = 0, $add = 0, $cmp = 0, $add_ = 0, $0 = 0, $cmp4 = 0, $1 = 0, $tobool = 0, $call6 = 0, $call7 = 0, $storemerge = 0, $2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _strlen($str | 0) | 0;
+ $mul = $call << 1;
+ $add = $mul + 2 | 0;
+ $cmp = $add >>> 0 > 1024;
+ $add_ = $cmp ? $add : 1024;
+ $0 = HEAP32[4072] | 0;
+ $cmp4 = ($add_ | 0) > ($0 | 0);
+ if ($cmp4) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[4070] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call6 = _realloc($1, $add_) | 0;
+ $storemerge = $call6;
+ label = 6;
+ break;
+ case 5:
+ $call7 = _malloc($add_) | 0;
+ $storemerge = $call7;
+ label = 6;
+ break;
+ case 6:
+ HEAP32[4070] = $storemerge;
+ HEAP32[4072] = $add_;
+ label = 7;
+ break;
+ case 7:
+ $2 = HEAP32[4070] | 0;
+ return $2 | 0;
+ }
+ return 0;
+}
+function _agwrnode($g, $fp, $n, $full, $indent) {
+ $g = $g | 0;
+ $fp = $fp | 0;
+ $n = $n | 0;
+ $full = $full | 0;
+ $indent = $indent | 0;
+ var $nprint = 0, $graph = 0, $0 = 0, $univ = 0, $1 = 0, $nodeattr = 0, $2 = 0, $tobool = 0, $dict = 0, $3 = 0, $call26 = 0, $cmp28 = 0, $list = 0, $4 = 0, $name19 = 0, $proto = 0, $i_030 = 0, $didwrite_029 = 0, $5 = 0, $arrayidx = 0, $6 = 0, $printed = 0, $7 = 0, $cmp1 = 0, $name = 0, $8 = 0, $call4 = 0, $9 = 0, $cmp6 = 0, $value = 0, $10 = 0, $11 = 0, $n9 = 0, $12 = 0, $13 = 0, $14 = 0, $call11 = 0, $defval_0 = 0, $call13 = 0, $tobool14 = 0, $cmp16 = 0, $15 = 0, $call20 = 0, $call21 = 0, $didwrite_1 = 0, $16 = 0, $didwrite_2 = 0, $inc = 0, $17 = 0, $call = 0, $cmp = 0, $tobool25 = 0, $18 = 0, $cmp27 = 0, $cond = 0, $call29 = 0, $call32 = 0, $cmp33 = 0, $call35 = 0, $cmp36 = 0, $name39 = 0, $19 = 0, $call40 = 0, $call41 = 0, $call42 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nprint = __stackBase__ | 0;
+ HEAP32[$nprint >> 2] = 0;
+ $graph = $n + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ $univ = $0 + 16 | 0;
+ $1 = HEAP32[$univ >> 2] | 0;
+ $nodeattr = $1 + 4 | 0;
+ $2 = HEAP32[$nodeattr >> 2] | 0;
+ $tobool = ($full | 0) == 0;
+ if ($tobool) {
+ label = 16;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $dict = $2 + 4 | 0;
+ $3 = HEAP32[$dict >> 2] | 0;
+ $call26 = _dtsize($3) | 0;
+ $cmp28 = ($call26 | 0) > 0;
+ if ($cmp28) {
+ label = 4;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 4:
+ $list = $2 + 8 | 0;
+ $4 = $n | 0;
+ $name19 = $n + 12 | 0;
+ $proto = $g + 40 | 0;
+ $didwrite_029 = 0;
+ $i_030 = 0;
+ label = 5;
+ break;
+ case 5:
+ $5 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $5 + ($i_030 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ $printed = $6 + 12 | 0;
+ $7 = HEAP8[$printed] | 0;
+ $cmp1 = $7 << 24 >> 24 == 0;
+ if ($cmp1) {
+ $didwrite_2 = $didwrite_029;
+ label = 13;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $name = $6 | 0;
+ $8 = HEAP32[$name >> 2] | 0;
+ $call4 = _agget($4, $8) | 0;
+ $9 = HEAP32[$graph >> 2] | 0;
+ $cmp6 = ($9 | 0) == ($g | 0);
+ if ($cmp6) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $value = $6 + 4 | 0;
+ $10 = HEAP32[$value >> 2] | 0;
+ $defval_0 = $10;
+ label = 9;
+ break;
+ case 8:
+ $11 = HEAP32[$proto >> 2] | 0;
+ $n9 = $11 | 0;
+ $12 = HEAP32[$n9 >> 2] | 0;
+ $13 = $12 | 0;
+ $14 = HEAP32[$name >> 2] | 0;
+ $call11 = _agget($13, $14) | 0;
+ $defval_0 = $call11;
+ label = 9;
+ break;
+ case 9:
+ $call13 = _strcmp($defval_0 | 0, $call4 | 0) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ $didwrite_2 = $didwrite_029;
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $cmp16 = ($didwrite_029 | 0) == 0;
+ if ($cmp16) {
+ label = 11;
+ break;
+ } else {
+ $didwrite_1 = $didwrite_029;
+ label = 12;
+ break;
+ }
+ case 11:
+ _tabover($fp, $indent);
+ $15 = HEAP32[$name19 >> 2] | 0;
+ $call20 = _agcanonical($15) | 0;
+ $call21 = _agputs($call20, $fp) | 0;
+ $didwrite_1 = 1;
+ label = 12;
+ break;
+ case 12:
+ $16 = HEAP32[$name >> 2] | 0;
+ _writeattr($fp, $nprint, $16, $call4);
+ $didwrite_2 = $didwrite_1;
+ label = 13;
+ break;
+ case 13:
+ $inc = $i_030 + 1 | 0;
+ $17 = HEAP32[$dict >> 2] | 0;
+ $call = _dtsize($17) | 0;
+ $cmp = ($inc | 0) < ($call | 0);
+ if ($cmp) {
+ $didwrite_029 = $didwrite_2;
+ $i_030 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $tobool25 = ($didwrite_2 | 0) == 0;
+ if ($tobool25) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $18 = HEAP32[$nprint >> 2] | 0;
+ $cmp27 = ($18 | 0) > 0;
+ $cond = $cmp27 ? 125344 : 154784;
+ $call29 = _agputs($cond, $fp) | 0;
+ label = 19;
+ break;
+ case 16:
+ $call32 = _agfstout($g, $n) | 0;
+ $cmp33 = ($call32 | 0) == 0;
+ if ($cmp33) {
+ label = 17;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 17:
+ $call35 = _agfstin($g, $n) | 0;
+ $cmp36 = ($call35 | 0) == 0;
+ if ($cmp36) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ _tabover($fp, $indent);
+ $name39 = $n + 12 | 0;
+ $19 = HEAP32[$name39 >> 2] | 0;
+ $call40 = _agcanonical($19) | 0;
+ $call41 = _agputs($call40, $fp) | 0;
+ $call42 = _agputs(154784, $fp) | 0;
+ label = 19;
+ break;
+ case 19:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _tabover($fp, $tab) {
+ $fp = $fp | 0;
+ $tab = $tab | 0;
+ var $tobool1 = 0, $tab_addr_02 = 0, $dec = 0, $call = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool1 = ($tab | 0) == 0;
+ if ($tobool1) {
+ label = 4;
+ break;
+ } else {
+ $tab_addr_02 = $tab;
+ label = 3;
+ break;
+ }
+ case 3:
+ $dec = $tab_addr_02 - 1 | 0;
+ $call = _agputc(9, $fp) | 0;
+ $tobool = ($dec | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $tab_addr_02 = $dec;
+ label = 3;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _writeattr($fp, $npp, $name, $val) {
+ $fp = $fp | 0;
+ $npp = $npp | 0;
+ $name = $name | 0;
+ $val = $val | 0;
+ var $0 = 0;
+ $0 = HEAP32[$npp >> 2] | 0;
+ HEAP32[$npp >> 2] = $0 + 1 | 0;
+ _agputs(($0 | 0) > 0 ? 145752 : 151712, $fp);
+ _agputs(_agcanonical($name) | 0, $fp);
+ _agputc(61, $fp);
+ _agputs(_agcanonical($val) | 0, $fp);
+ return;
+}
+function _agwredge($g, $fp, $e, $list_all) {
+ $g = $g | 0;
+ $fp = $fp | 0;
+ $e = $e | 0;
+ $list_all = $list_all | 0;
+ var $nprint = 0, $tail = 0, $0 = 0, $graph = 0, $1 = 0, $univ = 0, $2 = 0, $edgeattr = 0, $3 = 0, $attr = 0, $4 = 0, $tobool = 0, $arrayidx = 0, $5 = 0, $arrayidx3 = 0, $6 = 0, $hport_0 = 0, $tport_0 = 0, $7 = 0, $name = 0, $8 = 0, $9 = 0, $10 = 0, $and = 0, $tobool5 = 0, $cond = 0, $call = 0, $head = 0, $11 = 0, $name6 = 0, $12 = 0, $tobool7 = 0, $dict = 0, $13 = 0, $call925 = 0, $cmp26 = 0, $list = 0, $14 = 0, $15 = 0, $root = 0, $proto = 0, $i_027 = 0, $16 = 0, $arrayidx10 = 0, $17 = 0, $printed = 0, $18 = 0, $cmp11 = 0, $cmp13 = 0, $19 = 0, $_mask = 0, $cmp17 = 0, $name21 = 0, $20 = 0, $call22 = 0, $21 = 0, $cmp23 = 0, $value = 0, $22 = 0, $23 = 0, $e27 = 0, $24 = 0, $25 = 0, $26 = 0, $call29 = 0, $defval_0 = 0, $call31 = 0, $tobool32 = 0, $27 = 0, $inc = 0, $28 = 0, $call9 = 0, $cmp = 0, $29 = 0, $cmp37 = 0, $cond39 = 0, $call40 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nprint = __stackBase__ | 0;
+ HEAP32[$nprint >> 2] = 0;
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $univ = $1 + 16 | 0;
+ $2 = HEAP32[$univ >> 2] | 0;
+ $edgeattr = $2 + 8 | 0;
+ $3 = HEAP32[$edgeattr >> 2] | 0;
+ $attr = $e + 4 | 0;
+ $4 = HEAP32[$attr >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ $tport_0 = 127144;
+ $hport_0 = 127144;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $4 + 4 | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $arrayidx3 = $4 + 8 | 0;
+ $6 = HEAP32[$arrayidx3 >> 2] | 0;
+ $tport_0 = $5;
+ $hport_0 = $6;
+ label = 4;
+ break;
+ case 4:
+ $7 = HEAP32[$tail >> 2] | 0;
+ $name = $7 + 12 | 0;
+ $8 = HEAP32[$name >> 2] | 0;
+ _writenodeandport2898($fp, $8, $tport_0);
+ $9 = $g;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $and = $10 & 16;
+ $tobool5 = ($and | 0) != 0;
+ $cond = $tobool5 ? 117392 : 112128;
+ $call = _agputs($cond, $fp) | 0;
+ $head = $e + 12 | 0;
+ $11 = HEAP32[$head >> 2] | 0;
+ $name6 = $11 + 12 | 0;
+ $12 = HEAP32[$name6 >> 2] | 0;
+ _writenodeandport2898($fp, $12, $hport_0);
+ $tobool7 = ($list_all | 0) == 0;
+ if ($tobool7) {
+ label = 16;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $dict = $3 + 4 | 0;
+ $13 = HEAP32[$dict >> 2] | 0;
+ $call925 = _dtsize($13) | 0;
+ $cmp26 = ($call925 | 0) > 0;
+ if ($cmp26) {
+ label = 6;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 6:
+ $list = $3 + 8 | 0;
+ $14 = $e;
+ $15 = $e | 0;
+ $root = $g + 32 | 0;
+ $proto = $g + 40 | 0;
+ $i_027 = 0;
+ label = 7;
+ break;
+ case 7:
+ $16 = HEAP32[$list >> 2] | 0;
+ $arrayidx10 = $16 + ($i_027 << 2) | 0;
+ $17 = HEAP32[$arrayidx10 >> 2] | 0;
+ $printed = $17 + 12 | 0;
+ $18 = HEAP8[$printed] | 0;
+ $cmp11 = $18 << 24 >> 24 == 0;
+ if ($cmp11) {
+ label = 15;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp13 = ($i_027 | 0) == 0;
+ if ($cmp13) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $19 = HEAP32[$14 >> 2] | 0;
+ $_mask = $19 & 240;
+ $cmp17 = ($_mask | 0) == 32;
+ if ($cmp17) {
+ label = 10;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 10:
+ $name21 = $17 | 0;
+ $20 = HEAP32[$name21 >> 2] | 0;
+ $call22 = _agget($15, $20) | 0;
+ $21 = HEAP32[$root >> 2] | 0;
+ $cmp23 = ($21 | 0) == ($g | 0);
+ if ($cmp23) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $value = $17 + 4 | 0;
+ $22 = HEAP32[$value >> 2] | 0;
+ $defval_0 = $22;
+ label = 13;
+ break;
+ case 12:
+ $23 = HEAP32[$proto >> 2] | 0;
+ $e27 = $23 + 4 | 0;
+ $24 = HEAP32[$e27 >> 2] | 0;
+ $25 = $24 | 0;
+ $26 = HEAP32[$name21 >> 2] | 0;
+ $call29 = _agget($25, $26) | 0;
+ $defval_0 = $call29;
+ label = 13;
+ break;
+ case 13:
+ $call31 = _strcmp($defval_0 | 0, $call22 | 0) | 0;
+ $tobool32 = ($call31 | 0) == 0;
+ if ($tobool32) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $27 = HEAP32[$name21 >> 2] | 0;
+ _writeattr($fp, $nprint, $27, $call22);
+ label = 15;
+ break;
+ case 15:
+ $inc = $i_027 + 1 | 0;
+ $28 = HEAP32[$dict >> 2] | 0;
+ $call9 = _dtsize($28) | 0;
+ $cmp = ($inc | 0) < ($call9 | 0);
+ if ($cmp) {
+ $i_027 = $inc;
+ label = 7;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $29 = HEAP32[$nprint >> 2] | 0;
+ $cmp37 = ($29 | 0) > 0;
+ $cond39 = $cmp37 ? 125344 : 154784;
+ $call40 = _agputs($cond39, $fp) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _writenodeandport2898($fp, $node, $port) {
+ $fp = $fp | 0;
+ $node = $node | 0;
+ $port = $port | 0;
+ var $call = 0, $call1 = 0, $tobool = 0, $0 = 0, $tobool2 = 0, $call3 = 0, $tobool4 = 0, $call6 = 0, $call7 = 0, $call8 = 0, $call9 = 0, $call10 = 0, $tobool11 = 0, $call13 = 0, $call14 = 0, $call15 = 0, $call16 = 0, $call17 = 0, $add_ptr = 0, $call19 = 0, $call20 = 0, $call21 = 0, $call23 = 0, $call24 = 0, $call25 = 0, $call26 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agcanonical($node) | 0;
+ $call1 = _agputs($call, $fp) | 0;
+ $tobool = ($port | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$port] | 0;
+ $tobool2 = $0 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 9;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call3 = _aghtmlstr($port) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call6 = _agputc(58, $fp) | 0;
+ $call7 = _getoutputbuffer($port) | 0;
+ $call8 = _agstrcanon($port, $call7) | 0;
+ $call9 = _agputs($call8, $fp) | 0;
+ label = 9;
+ break;
+ case 6:
+ $call10 = _strchr($port | 0, 58) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ if ($tobool11) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ HEAP8[$call10] = 0;
+ $call13 = _agputc(58, $fp) | 0;
+ $call14 = _getoutputbuffer($port) | 0;
+ $call15 = __agstrcanon($port, $call14) | 0;
+ $call16 = _agputs($call15, $fp) | 0;
+ $call17 = _agputc(58, $fp) | 0;
+ $add_ptr = $call10 + 1 | 0;
+ $call19 = _getoutputbuffer($add_ptr) | 0;
+ $call20 = __agstrcanon($add_ptr, $call19) | 0;
+ $call21 = _agputs($call20, $fp) | 0;
+ HEAP8[$call10] = 58;
+ label = 9;
+ break;
+ case 8:
+ $call23 = _agputc(58, $fp) | 0;
+ $call24 = _getoutputbuffer($port) | 0;
+ $call25 = __agstrcanon($port, $call24) | 0;
+ $call26 = _agputs($call25, $fp) | 0;
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _agwrite($g, $fp) {
+ $g = $g | 0;
+ $fp = $fp | 0;
+ var $0 = 0, $cmp = 0, $1 = 0, $cmp1 = 0, $2 = 0, $3 = 0, $and = 0, $tobool = 0, $cond = 0, $call = 0, $4 = 0, $and6 = 0, $tobool7 = 0, $cond8 = 0, $call9 = 0, $name = 0, $5 = 0, $call10 = 0, $tobool11 = 0, $call13 = 0, $6 = 0, $call15 = 0, $call16 = 0, $call18 = 0, $univ = 0, $7 = 0, $globattr = 0, $8 = 0, $9 = 0, $nodeattr = 0, $10 = 0, $11 = 0, $edgeattr = 0, $12 = 0, $call21 = 0, $call22 = 0, $13 = 0, $call23 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[42143] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[42143] = 308;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[42144] | 0;
+ $cmp1 = ($1 | 0) == 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAP32[42144] = 74;
+ label = 6;
+ break;
+ case 6:
+ $2 = $g;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $and = $3 & 32;
+ $tobool = ($and | 0) != 0;
+ $cond = $tobool ? 107680 : 127144;
+ $call = _agputs($cond, $fp) | 0;
+ $4 = HEAP32[$2 >> 2] | 0;
+ $and6 = $4 & 16;
+ $tobool7 = ($and6 | 0) != 0;
+ $cond8 = $tobool7 ? 103712 : 99592;
+ $call9 = _agputs($cond8, $fp) | 0;
+ $name = $g + 12 | 0;
+ $5 = HEAP32[$name >> 2] | 0;
+ $call10 = _strncmp($5 | 0, 95592, 10) | 0;
+ $tobool11 = ($call10 | 0) == 0;
+ if ($tobool11) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call13 = _agputc(32, $fp) | 0;
+ $6 = HEAP32[$name >> 2] | 0;
+ $call15 = _agcanonical($6) | 0;
+ $call16 = _agputs($call15, $fp) | 0;
+ label = 8;
+ break;
+ case 8:
+ $call18 = _agputs(92144, $fp) | 0;
+ $univ = $g + 16 | 0;
+ $7 = HEAP32[$univ >> 2] | 0;
+ $globattr = $7 + 12 | 0;
+ $8 = HEAP32[$globattr >> 2] | 0;
+ _write_dict($8, $fp);
+ $9 = HEAP32[$univ >> 2] | 0;
+ $nodeattr = $9 + 4 | 0;
+ $10 = HEAP32[$nodeattr >> 2] | 0;
+ _write_dict($10, $fp);
+ $11 = HEAP32[$univ >> 2] | 0;
+ $edgeattr = $11 + 8 | 0;
+ $12 = HEAP32[$edgeattr >> 2] | 0;
+ _write_dict($12, $fp);
+ $call21 = _new_printdict_t($g) | 0;
+ _write_subg($g, $fp, 0, 0, $call21);
+ $call22 = _agputs(162280, $fp) | 0;
+ _free_printdict_t($call21);
+ $13 = HEAP32[42144] | 0;
+ $call23 = FUNCTION_TABLE_ii[$13 & 1023]($fp) | 0;
+ return $call23 | 0;
+ }
+ return 0;
+}
+function _write_dict($dict, $fp) {
+ $dict = $dict | 0;
+ $fp = $fp | 0;
+ var $dict1 = 0, $0 = 0, $call18 = 0, $cmp19 = 0, $list = 0, $name = 0, $i_021 = 0, $cnt_020 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $value = 0, $3 = 0, $cmp2 = 0, $4 = 0, $phitmp15 = 0, $inc = 0, $cmp8 = 0, $call11 = 0, $5 = 0, $call12 = 0, $call13 = 0, $call14 = 0, $name15 = 0, $6 = 0, $call16 = 0, $call17 = 0, $7 = 0, $call19 = 0, $call20 = 0, $cnt_1 = 0, $inc22 = 0, $8 = 0, $call = 0, $cmp = 0, $cmp23 = 0, $call26 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $dict1 = $dict + 4 | 0;
+ $0 = HEAP32[$dict1 >> 2] | 0;
+ $call18 = _dtsize($0) | 0;
+ $cmp19 = ($call18 | 0) > 0;
+ if ($cmp19) {
+ label = 3;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 3:
+ $list = $dict + 8 | 0;
+ $name = $dict | 0;
+ $cnt_020 = 0;
+ $i_021 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($i_021 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $value = $2 + 4 | 0;
+ $3 = HEAP32[$value >> 2] | 0;
+ $cmp2 = ($3 | 0) == 0;
+ if ($cmp2) {
+ $cnt_1 = $cnt_020;
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $4 = HEAP8[$3] | 0;
+ $phitmp15 = $4 << 24 >> 24 == 0;
+ if ($phitmp15) {
+ $cnt_1 = $cnt_020;
+ label = 10;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $inc = $cnt_020 + 1 | 0;
+ $cmp8 = ($cnt_020 | 0) == 0;
+ if ($cmp8) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call11 = _agputc(9, $fp) | 0;
+ $5 = HEAP32[$name >> 2] | 0;
+ $call12 = _agputs($5, $fp) | 0;
+ $call13 = _agputs(151712, $fp) | 0;
+ label = 9;
+ break;
+ case 8:
+ $call14 = _agputs(145752, $fp) | 0;
+ label = 9;
+ break;
+ case 9:
+ $name15 = $2 | 0;
+ $6 = HEAP32[$name15 >> 2] | 0;
+ $call16 = _agputs($6, $fp) | 0;
+ $call17 = _agputc(61, $fp) | 0;
+ $7 = HEAP32[$value >> 2] | 0;
+ $call19 = _agcanonical($7) | 0;
+ $call20 = _agputs($call19, $fp) | 0;
+ $cnt_1 = $inc;
+ label = 10;
+ break;
+ case 10:
+ $inc22 = $i_021 + 1 | 0;
+ $8 = HEAP32[$dict1 >> 2] | 0;
+ $call = _dtsize($8) | 0;
+ $cmp = ($inc22 | 0) < ($call | 0);
+ if ($cmp) {
+ $cnt_020 = $cnt_1;
+ $i_021 = $inc22;
+ label = 4;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $cmp23 = ($cnt_1 | 0) > 0;
+ if ($cmp23) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $call26 = _agputs(125344, $fp) | 0;
+ label = 13;
+ break;
+ case 13:
+ return;
+ }
+}
+function _new_printdict_t($g) {
+ $g = $g | 0;
+ var $call = 0, $call1 = 0, $call3 = 0, $call7 = 0;
+ $call = _calloc(1, 20) | 0;
+ $call1 = _dtopen(89472, HEAP32[41974] | 0) | 0;
+ HEAP32[$call >> 2] = $call1;
+ _copydict(HEAP32[$g + 20 >> 2] | 0, $call1);
+ $call3 = _dtopen(89632, HEAP32[41974] | 0) | 0;
+ HEAP32[$call + 4 >> 2] = $call3;
+ _copydict(HEAP32[$g + 28 >> 2] | 0, $call3);
+ HEAP32[$call + 16 >> 2] = _dtopen(89472, HEAP32[41974] | 0) | 0;
+ HEAP32[$call + 12 >> 2] = _dtopen(89432, HEAP32[41974] | 0) | 0;
+ $call7 = _dtopen(89472, HEAP32[41974] | 0) | 0;
+ HEAP32[$call + 8 >> 2] = $call7;
+ _copydict(HEAP32[(HEAP32[(HEAP32[$g + 36 >> 2] | 0) + 20 >> 2] | 0) + 20 >> 2] | 0, $call7);
+ return $call | 0;
+}
+function _aglinenumber() {
+ return HEAP32[41638] | 0;
+}
+function __is_number_char($c) {
+ $c = $c | 0;
+ var $conv = 0, $isdigittmp = 0, $isdigit = 0, $c_off = 0, $switch = 0, $or_cond = 0, $cmp8 = 0, $phitmp = 0, $0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $conv = $c << 24 >> 24;
+ $isdigittmp = $conv - 48 | 0;
+ $isdigit = $isdigittmp >>> 0 < 10;
+ $c_off = $c - 45 & 255;
+ $switch = ($c_off & 255) < 2;
+ $or_cond = $isdigit | $switch;
+ if ($or_cond) {
+ $0 = 1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp8 = $c << 24 >> 24 == 43;
+ $phitmp = $cmp8 & 1;
+ $0 = $phitmp;
+ label = 4;
+ break;
+ case 4:
+ return $0 | 0;
+ }
+ return 0;
+}
+function _write_subg($g, $fp, $par, $indent, $state) {
+ $g = $g | 0;
+ $fp = $fp | 0;
+ $par = $par | 0;
+ $indent = $indent | 0;
+ $state = $state | 0;
+ var $tobool = 0, $inc = 0, $subgleft = 0, $0 = 0, $searchf = 0, $1 = 0, $meta_node = 0, $2 = 0, $3 = 0, $call = 0, $tobool2 = 0, $name = 0, $4 = 0, $call4 = 0, $tobool5 = 0, $call7 = 0, $5 = 0, $call9 = 0, $call10 = 0, $call11 = 0, $call12 = 0, $6 = 0, $7 = 0, $univ = 0, $8 = 0, $globattr = 0, $9 = 0, $root = 0, $10 = 0, $cmp = 0, $proto = 0, $11 = 0, $n15 = 0, $12 = 0, $e17 = 0, $13 = 0, $pn_0 = 0, $pe_0 = 0, $proto19 = 0, $14 = 0, $n20 = 0, $15 = 0, $16 = 0, $17 = 0, $18 = 0, $nodeattr = 0, $19 = 0, $20 = 0, $e23 = 0, $21 = 0, $22 = 0, $23 = 0, $24 = 0, $edgeattr = 0, $25 = 0, $26 = 0, $searchf26 = 0, $27 = 0, $28 = 0, $29 = 0, $call29 = 0, $call31 = 0, $name32 = 0, $30 = 0, $call33 = 0, $call34 = 0, $call35 = 0, $31 = 0, $univ39 = 0, $32 = 0, $globattr40 = 0, $33 = 0, $n_insubg = 0, $34 = 0, $e_insubg = 0, $35 = 0, $meta_node42 = 0, $36 = 0, $graph = 0, $37 = 0, $38 = 0, $39 = 0, $call43 = 0, $40 = 0, $41 = 0, $call45 = 0, $42 = 0, $call48 = 0, $tobool49113 = 0, $e_0114 = 0, $head = 0, $43 = 0, $44 = 0, $call50 = 0, $45 = 0, $call51 = 0, $tobool49 = 0, $call52 = 0, $tobool54111 = 0, $nodesleft = 0, $searchf74 = 0, $n_0112 = 0, $46 = 0, $searchf56 = 0, $47 = 0, $48 = 0, $call58 = 0, $tobool59 = 0, $49 = 0, $searchf62 = 0, $50 = 0, $call64 = 0, $51 = 0, $searchf67 = 0, $52 = 0, $call69 = 0, $cmp70 = 0, $53 = 0, $call75 = 0, $call77 = 0, $tobool54 = 0, $outedges = 0, $54 = 0, $call79 = 0, $55 = 0, $searchf81 = 0, $56 = 0, $call83 = 0, $tobool85108 = 0, $edgesleft = 0, $searchf105 = 0, $e_1110_in = 0, $e_1110 = 0, $57 = 0, $searchf87 = 0, $58 = 0, $call89 = 0, $tobool90 = 0, $59 = 0, $searchf93 = 0, $60 = 0, $call95 = 0, $61 = 0, $searchf98 = 0, $62 = 0, $call100 = 0, $cmp101 = 0, $63 = 0, $call106 = 0, $64 = 0, $searchf109 = 0, $65 = 0, $call111 = 0, $tobool85 = 0, $66 = 0, $call114 = 0, $67 = 0, $call116 = 0, $68 = 0, $call119 = 0, $cmp121 = 0, $call123 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($indent | 0) == 0;
+ $inc = $indent + 1 | 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _tabover($fp, $indent);
+ $subgleft = $state + 8 | 0;
+ $0 = HEAP32[$subgleft >> 2] | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $meta_node = $g + 36 | 0;
+ $2 = HEAP32[$meta_node >> 2] | 0;
+ $3 = $2 | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $3, 4) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $name = $g + 12 | 0;
+ $4 = HEAP32[$name >> 2] | 0;
+ $call4 = _strncmp($4 | 0, 95592, 10) | 0;
+ $tobool5 = ($call4 | 0) == 0;
+ if ($tobool5) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call7 = _agputs(158728, $fp) | 0;
+ $5 = HEAP32[$name >> 2] | 0;
+ $call9 = _agcanonical($5) | 0;
+ $call10 = _agputs($call9, $fp) | 0;
+ $call11 = _agputs(92144, $fp) | 0;
+ label = 7;
+ break;
+ case 6:
+ $call12 = _agputs(155256, $fp) | 0;
+ label = 7;
+ break;
+ case 7:
+ $6 = $g | 0;
+ $7 = $par | 0;
+ $univ = $g + 16 | 0;
+ $8 = HEAP32[$univ >> 2] | 0;
+ $globattr = $8 + 12 | 0;
+ $9 = HEAP32[$globattr >> 2] | 0;
+ _write_diffattr($fp, $inc, $6, $7, $9);
+ $root = $g + 32 | 0;
+ $10 = HEAP32[$root >> 2] | 0;
+ $cmp = ($10 | 0) == ($par | 0);
+ if ($cmp) {
+ $pe_0 = 0;
+ $pn_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $proto = $par + 40 | 0;
+ $11 = HEAP32[$proto >> 2] | 0;
+ $n15 = $11 | 0;
+ $12 = HEAP32[$n15 >> 2] | 0;
+ $e17 = $11 + 4 | 0;
+ $13 = HEAP32[$e17 >> 2] | 0;
+ $pe_0 = $13;
+ $pn_0 = $12;
+ label = 9;
+ break;
+ case 9:
+ $proto19 = $g + 40 | 0;
+ $14 = HEAP32[$proto19 >> 2] | 0;
+ $n20 = $14 | 0;
+ $15 = HEAP32[$n20 >> 2] | 0;
+ $16 = $15 | 0;
+ $17 = $pn_0 | 0;
+ $18 = HEAP32[$univ >> 2] | 0;
+ $nodeattr = $18 + 4 | 0;
+ $19 = HEAP32[$nodeattr >> 2] | 0;
+ _write_diffattr($fp, $inc, $16, $17, $19);
+ $20 = HEAP32[$proto19 >> 2] | 0;
+ $e23 = $20 + 4 | 0;
+ $21 = HEAP32[$e23 >> 2] | 0;
+ $22 = $21 | 0;
+ $23 = $pe_0 | 0;
+ $24 = HEAP32[$univ >> 2] | 0;
+ $edgeattr = $24 + 8 | 0;
+ $25 = HEAP32[$edgeattr >> 2] | 0;
+ _write_diffattr($fp, $inc, $22, $23, $25);
+ $26 = HEAP32[$subgleft >> 2] | 0;
+ $searchf26 = $26 | 0;
+ $27 = HEAP32[$searchf26 >> 2] | 0;
+ $28 = HEAP32[$meta_node >> 2] | 0;
+ $29 = $28 | 0;
+ $call29 = FUNCTION_TABLE_iiii[$27 & 1023]($26, $29, 2) | 0;
+ label = 12;
+ break;
+ case 10:
+ $call31 = _agputs(158728, $fp) | 0;
+ $name32 = $g + 12 | 0;
+ $30 = HEAP32[$name32 >> 2] | 0;
+ $call33 = _agcanonical($30) | 0;
+ $call34 = _agputs($call33, $fp) | 0;
+ $call35 = _agputs(154784, $fp) | 0;
+ label = 30;
+ break;
+ case 11:
+ $31 = $g | 0;
+ $univ39 = $g + 16 | 0;
+ $32 = HEAP32[$univ39 >> 2] | 0;
+ $globattr40 = $32 + 12 | 0;
+ $33 = HEAP32[$globattr40 >> 2] | 0;
+ _write_diffattr($fp, $inc, $31, 0, $33);
+ label = 12;
+ break;
+ case 12:
+ $n_insubg = $state + 16 | 0;
+ $34 = HEAP32[$n_insubg >> 2] | 0;
+ $e_insubg = $state + 12 | 0;
+ $35 = HEAP32[$e_insubg >> 2] | 0;
+ $meta_node42 = $g + 36 | 0;
+ $36 = HEAP32[$meta_node42 >> 2] | 0;
+ $graph = $36 + 20 | 0;
+ $37 = HEAP32[$graph >> 2] | 0;
+ $38 = HEAP32[41974] | 0;
+ $39 = $38;
+ $call43 = _dtopen(89512, $39) | 0;
+ HEAP32[$n_insubg >> 2] = $call43;
+ $40 = HEAP32[41974] | 0;
+ $41 = $40;
+ $call45 = _dtopen(89432, $41) | 0;
+ HEAP32[$e_insubg >> 2] = $call45;
+ $42 = HEAP32[$meta_node42 >> 2] | 0;
+ $call48 = _agfstout($37, $42) | 0;
+ $tobool49113 = ($call48 | 0) == 0;
+ if ($tobool49113) {
+ label = 14;
+ break;
+ } else {
+ $e_0114 = $call48;
+ label = 13;
+ break;
+ }
+ case 13:
+ $head = $e_0114 + 12 | 0;
+ $43 = HEAP32[$head >> 2] | 0;
+ $44 = $43;
+ $call50 = _agusergraph($44) | 0;
+ $45 = $call50;
+ _write_subg($45, $fp, $g, $inc, $state);
+ $call51 = _agnxtout($37, $e_0114) | 0;
+ $tobool49 = ($call51 | 0) == 0;
+ if ($tobool49) {
+ label = 14;
+ break;
+ } else {
+ $e_0114 = $call51;
+ label = 13;
+ break;
+ }
+ case 14:
+ $call52 = _agfstnode($g) | 0;
+ $tobool54111 = ($call52 | 0) == 0;
+ if ($tobool54111) {
+ label = 21;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $nodesleft = $state | 0;
+ $searchf74 = $34 | 0;
+ $n_0112 = $call52;
+ label = 16;
+ break;
+ case 16:
+ $46 = HEAP32[$nodesleft >> 2] | 0;
+ $searchf56 = $46 | 0;
+ $47 = HEAP32[$searchf56 >> 2] | 0;
+ $48 = $n_0112 | 0;
+ $call58 = FUNCTION_TABLE_iiii[$47 & 1023]($46, $48, 4) | 0;
+ $tobool59 = ($call58 | 0) == 0;
+ if ($tobool59) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ _agwrnode($g, $fp, $n_0112, 1, $inc);
+ $49 = HEAP32[$nodesleft >> 2] | 0;
+ $searchf62 = $49 | 0;
+ $50 = HEAP32[$searchf62 >> 2] | 0;
+ $call64 = FUNCTION_TABLE_iiii[$50 & 1023]($49, $48, 2) | 0;
+ label = 20;
+ break;
+ case 18:
+ $51 = HEAP32[$n_insubg >> 2] | 0;
+ $searchf67 = $51 | 0;
+ $52 = HEAP32[$searchf67 >> 2] | 0;
+ $call69 = FUNCTION_TABLE_iiii[$52 & 1023]($51, $48, 4) | 0;
+ $cmp70 = ($call69 | 0) == 0;
+ if ($cmp70) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ _agwrnode($g, $fp, $n_0112, 0, $inc);
+ label = 20;
+ break;
+ case 20:
+ $53 = HEAP32[$searchf74 >> 2] | 0;
+ $call75 = FUNCTION_TABLE_iiii[$53 & 1023]($34, $48, 1) | 0;
+ $call77 = _agnxtnode($g, $n_0112) | 0;
+ $tobool54 = ($call77 | 0) == 0;
+ if ($tobool54) {
+ label = 21;
+ break;
+ } else {
+ $n_0112 = $call77;
+ label = 16;
+ break;
+ }
+ case 21:
+ $outedges = $g + 28 | 0;
+ $54 = HEAP32[$outedges >> 2] | 0;
+ $call79 = _dtdisc($54, 89632, 0) | 0;
+ $55 = HEAP32[$outedges >> 2] | 0;
+ $searchf81 = $55 | 0;
+ $56 = HEAP32[$searchf81 >> 2] | 0;
+ $call83 = FUNCTION_TABLE_iiii[$56 & 1023]($55, 0, 128) | 0;
+ $tobool85108 = ($call83 | 0) == 0;
+ if ($tobool85108) {
+ label = 28;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $edgesleft = $state + 4 | 0;
+ $searchf105 = $35 | 0;
+ $e_1110_in = $call83;
+ label = 23;
+ break;
+ case 23:
+ $e_1110 = $e_1110_in;
+ $57 = HEAP32[$edgesleft >> 2] | 0;
+ $searchf87 = $57 | 0;
+ $58 = HEAP32[$searchf87 >> 2] | 0;
+ $call89 = FUNCTION_TABLE_iiii[$58 & 1023]($57, $e_1110_in, 4) | 0;
+ $tobool90 = ($call89 | 0) == 0;
+ if ($tobool90) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ _tabover($fp, $inc);
+ _agwredge($g, $fp, $e_1110, 1);
+ $59 = HEAP32[$edgesleft >> 2] | 0;
+ $searchf93 = $59 | 0;
+ $60 = HEAP32[$searchf93 >> 2] | 0;
+ $call95 = FUNCTION_TABLE_iiii[$60 & 1023]($59, $e_1110_in, 2) | 0;
+ label = 27;
+ break;
+ case 25:
+ $61 = HEAP32[$e_insubg >> 2] | 0;
+ $searchf98 = $61 | 0;
+ $62 = HEAP32[$searchf98 >> 2] | 0;
+ $call100 = FUNCTION_TABLE_iiii[$62 & 1023]($61, $e_1110_in, 4) | 0;
+ $cmp101 = ($call100 | 0) == 0;
+ if ($cmp101) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ _tabover($fp, $inc);
+ _agwredge($g, $fp, $e_1110, 0);
+ label = 27;
+ break;
+ case 27:
+ $63 = HEAP32[$searchf105 >> 2] | 0;
+ $call106 = FUNCTION_TABLE_iiii[$63 & 1023]($35, $e_1110_in, 1) | 0;
+ $64 = HEAP32[$outedges >> 2] | 0;
+ $searchf109 = $64 | 0;
+ $65 = HEAP32[$searchf109 >> 2] | 0;
+ $call111 = FUNCTION_TABLE_iiii[$65 & 1023]($64, $e_1110_in, 8) | 0;
+ $tobool85 = ($call111 | 0) == 0;
+ if ($tobool85) {
+ label = 28;
+ break;
+ } else {
+ $e_1110_in = $call111;
+ label = 23;
+ break;
+ }
+ case 28:
+ $66 = HEAP32[$outedges >> 2] | 0;
+ $call114 = _dtdisc($66, 89432, 0) | 0;
+ $67 = HEAP32[$n_insubg >> 2] | 0;
+ $call116 = _dtclose($67) | 0;
+ HEAP32[$n_insubg >> 2] = $34;
+ $68 = HEAP32[$e_insubg >> 2] | 0;
+ $call119 = _dtclose($68) | 0;
+ HEAP32[$e_insubg >> 2] = $35;
+ $cmp121 = ($indent | 0) > 0;
+ if ($cmp121) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ _tabover($fp, $indent);
+ $call123 = _agputs(162280, $fp) | 0;
+ label = 30;
+ break;
+ case 30:
+ return;
+ }
+}
+function _free_printdict_t($dict) {
+ $dict = $dict | 0;
+ _dtclose(HEAP32[$dict >> 2] | 0);
+ _dtclose(HEAP32[$dict + 16 >> 2] | 0);
+ _dtclose(HEAP32[$dict + 4 >> 2] | 0);
+ _dtclose(HEAP32[$dict + 12 >> 2] | 0);
+ _dtclose(HEAP32[$dict + 8 >> 2] | 0);
+ _free($dict);
+ return;
+}
+function _write_diffattr($fp, $indent, $obj, $par, $dict) {
+ $fp = $fp | 0;
+ $indent = $indent | 0;
+ $obj = $obj | 0;
+ $par = $par | 0;
+ $dict = $dict | 0;
+ var $dict1 = 0, $0 = 0, $call20 = 0, $cmp21 = 0, $list = 0, $tobool = 0, $name = 0, $add = 0, $cnt_023 = 0, $i_022 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $printed = 0, $3 = 0, $cmp2 = 0, $index = 0, $4 = 0, $call4 = 0, $call7 = 0, $value = 0, $5 = 0, $q_0 = 0, $call9 = 0, $tobool10 = 0, $inc = 0, $cmp12 = 0, $6 = 0, $call15 = 0, $call16 = 0, $call18 = 0, $name20 = 0, $7 = 0, $call21 = 0, $call22 = 0, $call23 = 0, $call24 = 0, $call25 = 0, $cnt_1 = 0, $inc27 = 0, $8 = 0, $call = 0, $cmp = 0, $cmp28 = 0, $call31 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $dict1 = $dict + 4 | 0;
+ $0 = HEAP32[$dict1 >> 2] | 0;
+ $call20 = _dtsize($0) | 0;
+ $cmp21 = ($call20 | 0) > 0;
+ if ($cmp21) {
+ label = 3;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 3:
+ $list = $dict + 8 | 0;
+ $tobool = ($par | 0) == 0;
+ $name = $dict | 0;
+ $add = $indent + 1 | 0;
+ $i_022 = 0;
+ $cnt_023 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($i_022 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $printed = $2 + 12 | 0;
+ $3 = HEAP8[$printed] | 0;
+ $cmp2 = $3 << 24 >> 24 == 0;
+ if ($cmp2) {
+ $cnt_1 = $cnt_023;
+ label = 13;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $index = $2 + 8 | 0;
+ $4 = HEAP32[$index >> 2] | 0;
+ $call4 = _agxget($obj, $4) | 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call7 = _agxget($par, $4) | 0;
+ $q_0 = $call7;
+ label = 8;
+ break;
+ case 7:
+ $value = $2 + 4 | 0;
+ $5 = HEAP32[$value >> 2] | 0;
+ $q_0 = $5;
+ label = 8;
+ break;
+ case 8:
+ $call9 = _strcmp($call4 | 0, $q_0 | 0) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ $cnt_1 = $cnt_023;
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $inc = $cnt_023 + 1 | 0;
+ $cmp12 = ($cnt_023 | 0) == 0;
+ if ($cmp12) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _tabover($fp, $indent);
+ $6 = HEAP32[$name >> 2] | 0;
+ $call15 = _agputs($6, $fp) | 0;
+ $call16 = _agputs(151712, $fp) | 0;
+ label = 12;
+ break;
+ case 11:
+ $call18 = _agputs(148520, $fp) | 0;
+ _tabover($fp, $add);
+ label = 12;
+ break;
+ case 12:
+ $name20 = $2 | 0;
+ $7 = HEAP32[$name20 >> 2] | 0;
+ $call21 = _agcanonical($7) | 0;
+ $call22 = _agputs($call21, $fp) | 0;
+ $call23 = _agputc(61, $fp) | 0;
+ $call24 = _agcanonical($call4) | 0;
+ $call25 = _agputs($call24, $fp) | 0;
+ $cnt_1 = $inc;
+ label = 13;
+ break;
+ case 13:
+ $inc27 = $i_022 + 1 | 0;
+ $8 = HEAP32[$dict1 >> 2] | 0;
+ $call = _dtsize($8) | 0;
+ $cmp = ($inc27 | 0) < ($call | 0);
+ if ($cmp) {
+ $i_022 = $inc27;
+ $cnt_023 = $cnt_1;
+ label = 4;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $cmp28 = ($cnt_1 | 0) > 0;
+ if ($cmp28) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $call31 = _agputs(125344, $fp) | 0;
+ label = 16;
+ break;
+ case 16:
+ return;
+ }
+}
+function _copydict($from, $to) {
+ $from = $from | 0;
+ $to = $to | 0;
+ HEAP32[41984] = $to;
+ _dtwalk($from, 372, 0);
+ return;
+}
+function _copydictf($d, $a, $ignored) {
+ $d = $d | 0;
+ $a = $a | 0;
+ $ignored = $ignored | 0;
+ var $0 = 0;
+ $0 = HEAP32[41984] | 0;
+ FUNCTION_TABLE_iiii[HEAP32[$0 >> 2] & 1023]($0, $a, 1);
+ return 0;
+}
+function _aglexinit($fp, $mygets) {
+ $fp = $fp | 0;
+ $mygets = $mygets | 0;
+ var $tobool = 0, $_pr = 0, $cmp = 0, $0 = 0, $cmp3 = 0, $call = 0, $1 = 0, $call5 = 0, $2 = 0, $3 = 0, $call7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[41650] = $fp;
+ $tobool = ($mygets | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAP32[42142] = $mygets;
+ label = 6;
+ break;
+ case 4:
+ $_pr = HEAP32[42142] | 0;
+ $cmp = ($_pr | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAP32[42142] = 608;
+ label = 6;
+ break;
+ case 6:
+ HEAP32[41652] = 0;
+ $0 = HEAP32[42140] | 0;
+ $cmp3 = ($0 | 0) == 0;
+ if ($cmp3) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[41640] = 1024;
+ $call = _calloc(1024, 1) | 0;
+ HEAP32[42140] = $call;
+ $1 = HEAP32[41640] | 0;
+ $call5 = _calloc($1, 1) | 0;
+ HEAP32[41342] = $call5;
+ label = 8;
+ break;
+ case 8:
+ $2 = HEAP32[42142] | 0;
+ $3 = HEAP32[42140] | 0;
+ $call7 = FUNCTION_TABLE_iiii[$2 & 1023]($3, 0, $fp) | 0;
+ HEAP16[84282] = 0;
+ return;
+ }
+}
+function _aglex() {
+ var $xb = 0, $htmlbuf = 0, $0 = 0, $tobool = 0, $_pr = 0, $1 = 0, $cmp = 0, $2 = 0, $cmp1 = 0, $call = 0, $cmp4 = 0, $_b = 0, $3 = 0, $conv9 = 0, $call10 = 0, $4 = 0, $cmp14 = 0, $5 = 0, $call16 = 0, $tobool17 = 0, $add_ptr = 0, $6 = 0, $call20 = 0, $7 = 0, $cmp23 = 0, $8 = 0, $call30 = 0, $call31 = 0, $arraydecay = 0, $9 = 0, $call38 = 0, $ptr = 0, $10 = 0, $eptr = 0, $11 = 0, $cmp39 = 0, $call41 = 0, $12 = 0, $buf = 0, $13 = 0, $call44 = 0, $14 = 0, $tobool46 = 0, $call48 = 0, $call49 = 0, $cmp50 = 0, $add_ptr54 = 0, $15 = 0, $call56 = 0, $tobool57 = 0, $call59 = 0, $16 = 0, $17 = 0, $conv60 = 0, $call61 = 0, $tobool62 = 0, $cmp65 = 0, $or_cond = 0, $18 = 0, $incdec_ptr68 = 0, $19 = 0, $conv69 = 0, $call71 = 0, $call74 = 0, $cmp75 = 0, $call78 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1040 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $xb = __stackBase__ | 0;
+ $htmlbuf = __stackBase__ + 16 | 0;
+ $0 = HEAP8[168566] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAP8[168566] = 0;
+ $retval_0 = -1;
+ label = 28;
+ break;
+ case 4:
+ $_pr = HEAP32[41652] | 0;
+ $1 = $_pr;
+ label = 5;
+ break;
+ case 5:
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $2 = HEAP8[$1] | 0;
+ $cmp1 = $2 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $call = _lex_gets() | 0;
+ HEAP32[41652] = $call;
+ $cmp4 = ($call | 0) == 0;
+ if ($cmp4) {
+ label = 8;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 8:
+ $_b = HEAP8[166992] | 0;
+ if ($_b) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = -1;
+ label = 28;
+ break;
+ }
+ case 9:
+ $3 = HEAP8[167960] | 0;
+ $conv9 = $3 & 255;
+ $call10 = _agerr(0, 125096, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $conv9, tempInt) | 0) | 0;
+ $retval_0 = -1;
+ label = 28;
+ break;
+ case 10:
+ $4 = HEAP32[41638] | 0;
+ $cmp14 = ($4 | 0) == 1;
+ if ($cmp14) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $5 = HEAP32[41652] | 0;
+ $call16 = _strncmp($5 | 0, 89152, 3) | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ if ($tobool17) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $add_ptr = $5 + 3 | 0;
+ HEAP32[41652] = $add_ptr;
+ label = 13;
+ break;
+ case 13:
+ $6 = HEAP32[41652] | 0;
+ $call20 = _skip_wscomments($6) | 0;
+ HEAP32[41652] = $call20;
+ $7 = HEAP8[$call20] | 0;
+ $cmp23 = $7 << 24 >> 24 == 0;
+ if ($cmp23) {
+ $1 = $call20;
+ label = 5;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $8 = HEAP32[41342] | 0;
+ if (($7 << 24 >> 24 | 0) == 34) {
+ label = 15;
+ break;
+ } else if (($7 << 24 >> 24 | 0) == 60) {
+ label = 16;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 15:
+ $call30 = _quoted_string($call20, $8) | 0;
+ HEAP32[41652] = $call30;
+ $call31 = _agstrdup($8) | 0;
+ HEAP32[22286] = $call31;
+ $retval_0 = 265;
+ label = 28;
+ break;
+ case 16:
+ $arraydecay = $htmlbuf | 0;
+ _agxbinit($xb, 1024, $arraydecay);
+ $9 = HEAP32[41652] | 0;
+ $call38 = _html_string3314($9, $xb) | 0;
+ HEAP32[41652] = $call38;
+ $ptr = $xb + 4 | 0;
+ $10 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $xb + 8 | 0;
+ $11 = HEAP32[$eptr >> 2] | 0;
+ $cmp39 = $10 >>> 0 < $11 >>> 0;
+ if ($cmp39) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $call41 = _agxbmore($xb, 1) | 0;
+ label = 18;
+ break;
+ case 18:
+ $12 = HEAP32[$ptr >> 2] | 0;
+ HEAP8[$12] = 0;
+ $buf = $xb | 0;
+ $13 = HEAP32[$buf >> 2] | 0;
+ HEAP32[$ptr >> 2] = $13;
+ $call44 = _agstrdup_html($13) | 0;
+ HEAP32[22286] = $call44;
+ _agxbfree($xb);
+ $retval_0 = 264;
+ label = 28;
+ break;
+ case 19:
+ $14 = HEAP32[42139] | 0;
+ $tobool46 = ($14 | 0) == 0;
+ if ($tobool46) {
+ label = 22;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $call48 = _strlen($14 | 0) | 0;
+ $call49 = _strncmp($call20 | 0, $14 | 0, $call48 | 0) | 0;
+ $cmp50 = ($call49 | 0) == 0;
+ if ($cmp50) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $add_ptr54 = $call20 + $call48 | 0;
+ HEAP32[41652] = $add_ptr54;
+ $retval_0 = 263;
+ label = 28;
+ break;
+ case 22:
+ $15 = HEAP32[41652] | 0;
+ $call56 = _scan_num($15, $8) | 0;
+ $tobool57 = ($call56 | 0) == 0;
+ if ($tobool57) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ HEAP32[41652] = $call56;
+ $call59 = _agstrdup($8) | 0;
+ HEAP32[22286] = $call59;
+ $retval_0 = 264;
+ label = 28;
+ break;
+ case 24:
+ $16 = HEAP32[41652] | 0;
+ $17 = HEAP8[$16] | 0;
+ $conv60 = $17 & 255;
+ $call61 = _ispunct($conv60 | 0) | 0;
+ $tobool62 = ($call61 | 0) == 0;
+ $cmp65 = $17 << 24 >> 24 == 95;
+ $or_cond = $tobool62 | $cmp65;
+ $18 = HEAP32[41652] | 0;
+ if ($or_cond) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $incdec_ptr68 = $18 + 1 | 0;
+ HEAP32[41652] = $incdec_ptr68;
+ $19 = HEAP8[$18] | 0;
+ $conv69 = $19 << 24 >> 24;
+ $retval_0 = $conv69;
+ label = 28;
+ break;
+ case 26:
+ $call71 = _scan_token($18, $8) | 0;
+ HEAP32[41652] = $call71;
+ $call74 = _agtoken($8) | 0;
+ $cmp75 = ($call74 | 0) == -1;
+ if ($cmp75) {
+ label = 27;
+ break;
+ } else {
+ $retval_0 = $call74;
+ label = 28;
+ break;
+ }
+ case 27:
+ $call78 = _agstrdup($8) | 0;
+ HEAP32[22286] = $call78;
+ $retval_0 = 264;
+ label = 28;
+ break;
+ case 28:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agtoken($p) {
+ $p = $p | 0;
+ var $0 = 0, $tobool8 = 0, $1 = 0, $2 = 0, $p_addr_09 = 0, $tobool1 = 0, $_ = 0, $cmp = 0, $conv6 = 0, $call = 0, $tobool7 = 0, $call10 = 0, $conv11 = 0, $call13 = 0, $tobool14 = 0, $c_0 = 0, $3 = 0, $idxprom = 0, $mask = 0, $4 = 0, $conv17 = 0, $sub = 0, $arrayidx18 = 0, $5 = 0, $and19 = 0, $tobool20 = 0, $trans_base = 0, $6 = 0, $i_0 = 0, $idxprom25 = 0, $c27 = 0, $7 = 0, $conv28 = 0, $cmp30 = 0, $inc = 0, $next_state = 0, $8 = 0, $incdec_ptr = 0, $9 = 0, $tobool = 0, $_pr10 = 0, $cmp40 = 0, $10 = 0, $conv39 = 0, $def = 0, $11 = 0, $conv46 = 0, $cond48 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP16[82692] = 0;
+ $0 = HEAP8[$p] | 0;
+ $tobool8 = $0 << 24 >> 24 == 0;
+ if ($tobool8) {
+ $10 = 0;
+ label = 15;
+ break;
+ } else {
+ $p_addr_09 = $p;
+ $2 = $0;
+ $1 = 0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $tobool1 = $2 << 24 >> 24 < 0;
+ $_ = $tobool1 ? 127 : $2;
+ $cmp = $1 << 16 >> 16 > -1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 4:
+ $conv6 = $_ & 255;
+ $call = _isupper($conv6 | 0) | 0;
+ $tobool7 = ($call | 0) == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call10 = _tolower($conv6 | 0) | 0;
+ $conv11 = $call10 & 255;
+ $c_0 = $conv11;
+ label = 8;
+ break;
+ case 6:
+ $call13 = _islower($conv6 | 0) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ label = 7;
+ break;
+ } else {
+ $c_0 = $_;
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP16[82692] = -1;
+ label = 13;
+ break;
+ case 8:
+ $3 = HEAP16[82692] | 0;
+ $idxprom = $3 << 16 >> 16;
+ $mask = 165068 + ($idxprom << 3) | 0;
+ $4 = HEAP32[$mask >> 2] | 0;
+ $conv17 = $c_0 & 255;
+ $sub = $conv17 - 97 | 0;
+ $arrayidx18 = 167976 + ($sub << 2) | 0;
+ $5 = HEAP32[$arrayidx18 >> 2] | 0;
+ $and19 = $5 & $4;
+ $tobool20 = ($and19 | 0) == 0;
+ if ($tobool20) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $trans_base = 165066 + ($idxprom << 3) | 0;
+ $6 = HEAP16[$trans_base >> 1] | 0;
+ $i_0 = $6;
+ label = 10;
+ break;
+ case 10:
+ $idxprom25 = $i_0 << 16 >> 16;
+ $c27 = 164928 + ($idxprom25 << 2) | 0;
+ $7 = HEAP16[$c27 >> 1] | 0;
+ $conv28 = $7 << 16 >> 16;
+ $cmp30 = ($conv28 | 0) == ($conv17 | 0);
+ $inc = $i_0 + 1 & 65535;
+ if ($cmp30) {
+ label = 11;
+ break;
+ } else {
+ $i_0 = $inc;
+ label = 10;
+ break;
+ }
+ case 11:
+ $next_state = 164930 + ($idxprom25 << 2) | 0;
+ $8 = HEAP16[$next_state >> 1] | 0;
+ HEAP16[82692] = $8;
+ label = 13;
+ break;
+ case 12:
+ HEAP16[82692] = -1;
+ label = 13;
+ break;
+ case 13:
+ $incdec_ptr = $p_addr_09 + 1 | 0;
+ $9 = HEAP8[$incdec_ptr] | 0;
+ $tobool = $9 << 24 >> 24 == 0;
+ $_pr10 = HEAP16[82692] | 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ $p_addr_09 = $incdec_ptr;
+ $2 = $9;
+ $1 = $_pr10;
+ label = 3;
+ break;
+ }
+ case 14:
+ $cmp40 = $_pr10 << 16 >> 16 < 0;
+ if ($cmp40) {
+ $cond48 = -1;
+ label = 16;
+ break;
+ } else {
+ $10 = $_pr10;
+ label = 15;
+ break;
+ }
+ case 15:
+ $conv39 = $10 << 16 >> 16;
+ $def = 165064 + ($conv39 << 3) | 0;
+ $11 = HEAP16[$def >> 1] | 0;
+ $conv46 = $11 << 16 >> 16;
+ $cond48 = $conv46;
+ label = 16;
+ break;
+ case 16:
+ return $cond48 | 0;
+ }
+ return 0;
+}
+function _lex_gets() {
+ var $cnt = 0, $buf = 0, $arraydecay = 0, $curlen_0 = 0, $add = 0, $0 = 0, $cmp = 0, $add1 = 0, $1 = 0, $call = 0, $2 = 0, $3 = 0, $call2 = 0, $4 = 0, $5 = 0, $add_ptr_sum = 0, $add_ptr3 = 0, $6 = 0, $sub = 0, $sub4 = 0, $7 = 0, $call5 = 0, $cmp6 = 0, $call9 = 0, $sub10 = 0, $arrayidx = 0, $8 = 0, $cmp11 = 0, $9 = 0, $cmp16 = 0, $cmp18 = 0, $or_cond = 0, $add_ptr21 = 0, $call22 = 0, $cmp23 = 0, $add_ptr26 = 0, $add_ptr26_add_ptr21 = 0, $call28 = 0, $cmp29 = 0, $10 = 0, $inc = 0, $dec = 0, $cmp32 = 0, $11 = 0, $add_ptr35 = 0, $e_0 = 0, $12 = 0, $incdec_ptr = 0, $cmp40 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $13 = 0, $inc48 = 0, $sub49 = 0, $arrayidx50 = 0, $14 = 0, $cmp52 = 0, $len_0 = 0, $add59 = 0, $curlen_1 = 0, $len_1 = 0, $sub60 = 0, $arrayidx61 = 0, $15 = 0, $cmp63 = 0, $curlen_2 = 0, $cmp65 = 0, $16 = 0, $add_ptr68 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cnt = __stackBase__ | 0;
+ $buf = __stackBase__ + 8 | 0;
+ $arraydecay = $buf | 0;
+ $curlen_0 = 0;
+ label = 3;
+ break;
+ case 3:
+ $add = $curlen_0 + 128 | 0;
+ $0 = HEAP32[41640] | 0;
+ $cmp = ($add | 0) < ($0 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $add1 = $0 + 1024 | 0;
+ HEAP32[41640] = $add1;
+ $1 = HEAP32[42140] | 0;
+ $call = _realloc($1, $add1) | 0;
+ HEAP32[42140] = $call;
+ $2 = HEAP32[41342] | 0;
+ $3 = HEAP32[41640] | 0;
+ $call2 = _realloc($2, $3) | 0;
+ HEAP32[41342] = $call2;
+ label = 5;
+ break;
+ case 5:
+ $4 = HEAP32[42142] | 0;
+ $5 = HEAP32[42140] | 0;
+ $add_ptr_sum = $curlen_0 + 1 | 0;
+ $add_ptr3 = $5 + $add_ptr_sum | 0;
+ $6 = HEAP32[41640] | 0;
+ $sub = $curlen_0 ^ -1;
+ $sub4 = $6 + $sub | 0;
+ $7 = HEAP32[41650] | 0;
+ $call5 = FUNCTION_TABLE_iiii[$4 & 1023]($add_ptr3, $sub4, $7) | 0;
+ $cmp6 = ($call5 | 0) == 0;
+ if ($cmp6) {
+ $curlen_2 = $curlen_0;
+ label = 21;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call9 = _strlen($call5 | 0) | 0;
+ $sub10 = $call9 - 1 | 0;
+ $arrayidx = $call5 + $sub10 | 0;
+ $8 = HEAP8[$arrayidx] | 0;
+ $cmp11 = $8 << 24 >> 24 == 10;
+ if ($cmp11) {
+ label = 7;
+ break;
+ } else {
+ $len_0 = $call9;
+ label = 19;
+ break;
+ }
+ case 7:
+ $9 = HEAP8[$call5] | 0;
+ $cmp16 = $9 << 24 >> 24 == 35;
+ $cmp18 = ($curlen_0 | 0) == 0;
+ $or_cond = $cmp16 & $cmp18;
+ if ($or_cond) {
+ label = 8;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 8:
+ $add_ptr21 = $call5 + 1 | 0;
+ $call22 = _strncmp($add_ptr21 | 0, 142152, 4) | 0;
+ $cmp23 = ($call22 | 0) == 0;
+ $add_ptr26 = $call5 + 5 | 0;
+ $add_ptr26_add_ptr21 = $cmp23 ? $add_ptr26 : $add_ptr21;
+ $call28 = _sscanf($add_ptr26_add_ptr21 | 0, 138608, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = 166552, HEAP32[tempInt + 8 >> 2] = $arraydecay, HEAP32[tempInt + 16 >> 2] = $cnt, tempInt) | 0) | 0;
+ $cmp29 = ($call28 | 0) < 1;
+ $10 = HEAP32[41638] | 0;
+ if ($cmp29) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $inc = $10 + 1 | 0;
+ HEAP32[41638] = $inc;
+ label = 16;
+ break;
+ case 10:
+ $dec = $10 - 1 | 0;
+ HEAP32[41638] = $dec;
+ $cmp32 = ($call28 | 0) > 1;
+ if ($cmp32) {
+ label = 11;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 11:
+ $11 = HEAP32[$cnt >> 2] | 0;
+ $add_ptr35 = $add_ptr26_add_ptr21 + $11 | 0;
+ $e_0 = $add_ptr35;
+ label = 12;
+ break;
+ case 12:
+ $12 = HEAP8[$e_0] | 0;
+ if (($12 << 24 >> 24 | 0) == 34 | ($12 << 24 >> 24 | 0) == 0) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $incdec_ptr = $e_0 + 1 | 0;
+ $e_0 = $incdec_ptr;
+ label = 12;
+ break;
+ case 14:
+ $cmp40 = ($e_0 | 0) == ($add_ptr35 | 0);
+ if ($cmp40) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ HEAP8[$e_0] = 0;
+ $sub_ptr_lhs_cast = $e_0;
+ $sub_ptr_rhs_cast = $add_ptr35;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ _storeFileName($add_ptr35, $sub_ptr_sub);
+ label = 16;
+ break;
+ case 16:
+ HEAP8[$call5] = 0;
+ $len_1 = 1;
+ $curlen_1 = $curlen_0;
+ label = 20;
+ break;
+ case 17:
+ $13 = HEAP32[41638] | 0;
+ $inc48 = $13 + 1 | 0;
+ HEAP32[41638] = $inc48;
+ $sub49 = $call9 - 2 | 0;
+ $arrayidx50 = $call5 + $sub49 | 0;
+ $14 = HEAP8[$arrayidx50] | 0;
+ $cmp52 = $14 << 24 >> 24 == 92;
+ if ($cmp52) {
+ label = 18;
+ break;
+ } else {
+ $len_0 = $call9;
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP8[$arrayidx50] = 0;
+ $len_0 = $sub49;
+ label = 19;
+ break;
+ case 19:
+ $add59 = $len_0 + $curlen_0 | 0;
+ $len_1 = $len_0;
+ $curlen_1 = $add59;
+ label = 20;
+ break;
+ case 20:
+ $sub60 = $len_1 - 1 | 0;
+ $arrayidx61 = $call5 + $sub60 | 0;
+ $15 = HEAP8[$arrayidx61] | 0;
+ $cmp63 = $15 << 24 >> 24 == 10;
+ if ($cmp63) {
+ $curlen_2 = $curlen_1;
+ label = 21;
+ break;
+ } else {
+ $curlen_0 = $curlen_1;
+ label = 3;
+ break;
+ }
+ case 21:
+ $cmp65 = ($curlen_2 | 0) > 0;
+ if ($cmp65) {
+ label = 22;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 23;
+ break;
+ }
+ case 22:
+ $16 = HEAP32[42140] | 0;
+ $add_ptr68 = $16 + 1 | 0;
+ $retval_0 = $add_ptr68;
+ label = 23;
+ break;
+ case 23:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agerr($level, $fmt, varrp) {
+ $level = $level | 0;
+ $fmt = $fmt | 0;
+ varrp = varrp | 0;
+ var $args = 0, $arraydecay1 = 0, $call = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $args = __stackBase__ | 0;
+ $arraydecay1 = $args;
+ HEAP32[$arraydecay1 >> 2] = varrp;
+ HEAP32[$arraydecay1 + 4 >> 2] = 0;
+ $call = _agerr_va($level, $fmt, $args | 0) | 0;
+ STACKTOP = __stackBase__;
+ return $call | 0;
+}
+function _agerrors() {
+ var $0 = 0, $conv = 0;
+ $0 = HEAP32[22284] | 0;
+ $conv = HEAP16[84282] | 0;
+ return (($0 | 0) > ($conv | 0) ? $0 : $conv) | 0;
+}
+function _skip_wscomments($pp) {
+ $pp = $pp | 0;
+ var $p_0 = 0, $0 = 0, $cmp = 0, $conv = 0, $call = 0, $tobool = 0, $1 = 0, $conv3 = 0, $call4 = 0, $tobool5 = 0, $_b22 = 0, $_b = 0, $incdec_ptr = 0, $p_123 = 0, $2 = 0, $tobool11 = 0, $p_2 = 0, $3 = 0, $tobool17 = 0, $cmp21 = 0, $not_tobool17 = 0, $_cmp21 = 0, $incdec_ptr25 = 0, $p_1_be = 0, $arrayidx29 = 0, $4 = 0, $cmp31 = 0, $add_ptr = 0, $p_3 = 0, $5 = 0, $arrayidx42 = 0, $6 = 0, $p_4 = 0, $7 = 0, $tobool48 = 0, $incdec_ptr50 = 0, $8 = 0, $conv58 = 0, $add_ptr59 = 0, $conv38 = 0, $call67 = 0, $tobool68 = 0, $9 = 0, $conv69 = 0, $call70 = 0, $tobool71 = 0, $p_5 = 0, $10 = 0, $tobool76 = 0, $p_6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p_0 = $pp;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[$p_0] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = $0 & 255;
+ $call = _isspace($conv | 0) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $1 = HEAP8[$p_0] | 0;
+ $conv3 = $1 & 255;
+ $call4 = _iscntrl($conv3 | 0) | 0;
+ $tobool5 = ($call4 | 0) == 0;
+ if ($tobool5) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $_b22 = HEAP8[166992] | 0;
+ if ($_b22) {
+ label = 7;
+ break;
+ } else {
+ $p_3 = $p_0;
+ label = 15;
+ break;
+ }
+ case 7:
+ $_b = HEAP8[166992] | 0;
+ $p_123 = $p_0;
+ label = 9;
+ break;
+ case 8:
+ $incdec_ptr = $p_0 + 1 | 0;
+ $p_0 = $incdec_ptr;
+ label = 3;
+ break;
+ case 9:
+ $2 = HEAP8[$p_123] | 0;
+ $tobool11 = $2 << 24 >> 24 == 0;
+ if ($tobool11) {
+ $p_3 = $p_123;
+ label = 15;
+ break;
+ } else {
+ $p_2 = $p_123;
+ label = 10;
+ break;
+ }
+ case 10:
+ $3 = HEAP8[$p_2] | 0;
+ $tobool17 = $3 << 24 >> 24 == 0;
+ $cmp21 = $3 << 24 >> 24 != 42;
+ $not_tobool17 = $tobool17 ^ 1;
+ $_cmp21 = $cmp21 & $not_tobool17;
+ $incdec_ptr25 = $p_2 + 1 | 0;
+ if ($_cmp21) {
+ $p_2 = $incdec_ptr25;
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ if ($tobool17) {
+ $p_1_be = $p_2;
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ if ($_b) {
+ $p_123 = $p_1_be;
+ label = 9;
+ break;
+ } else {
+ $p_3 = $p_1_be;
+ label = 15;
+ break;
+ }
+ case 13:
+ $arrayidx29 = $p_2 + 1 | 0;
+ $4 = HEAP8[$arrayidx29] | 0;
+ $cmp31 = $4 << 24 >> 24 == 47;
+ if ($cmp31) {
+ label = 14;
+ break;
+ } else {
+ $p_1_be = $arrayidx29;
+ label = 12;
+ break;
+ }
+ case 14:
+ HEAP8[166992] = 0;
+ $add_ptr = $p_2 + 2 | 0;
+ $p_3 = $add_ptr;
+ label = 15;
+ break;
+ case 15:
+ $5 = HEAP8[$p_3] | 0;
+ if (($5 << 24 >> 24 | 0) == 47) {
+ label = 16;
+ break;
+ } else if (($5 << 24 >> 24 | 0) == 0) {
+ $p_6 = $p_3;
+ label = 22;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 16:
+ $arrayidx42 = $p_3 + 1 | 0;
+ $6 = HEAP8[$arrayidx42] | 0;
+ if (($6 << 24 >> 24 | 0) == 47) {
+ $p_4 = $p_3;
+ label = 17;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 42) {
+ label = 18;
+ break;
+ } else {
+ $p_6 = $p_3;
+ label = 22;
+ break;
+ }
+ case 17:
+ $7 = HEAP8[$p_4] | 0;
+ $tobool48 = $7 << 24 >> 24 == 0;
+ $incdec_ptr50 = $p_4 + 1 | 0;
+ if ($tobool48) {
+ $p_5 = $p_4;
+ label = 21;
+ break;
+ } else {
+ $p_4 = $incdec_ptr50;
+ label = 17;
+ break;
+ }
+ case 18:
+ HEAP8[166992] = 1;
+ $8 = HEAP32[41638] | 0;
+ $conv58 = $8 & 255;
+ HEAP8[167960] = $conv58;
+ $add_ptr59 = $p_3 + 2 | 0;
+ $p_5 = $add_ptr59;
+ label = 21;
+ break;
+ case 19:
+ $conv38 = $5 & 255;
+ $call67 = _isspace($conv38 | 0) | 0;
+ $tobool68 = ($call67 | 0) == 0;
+ if ($tobool68) {
+ label = 20;
+ break;
+ } else {
+ $p_5 = $p_3;
+ label = 21;
+ break;
+ }
+ case 20:
+ $9 = HEAP8[$p_3] | 0;
+ $conv69 = $9 & 255;
+ $call70 = _iscntrl($conv69 | 0) | 0;
+ $tobool71 = ($call70 | 0) == 0;
+ if ($tobool71) {
+ $p_6 = $p_3;
+ label = 22;
+ break;
+ } else {
+ $p_5 = $p_3;
+ label = 21;
+ break;
+ }
+ case 21:
+ $10 = HEAP8[$p_5] | 0;
+ $tobool76 = $10 << 24 >> 24 == 0;
+ if ($tobool76) {
+ $p_6 = $p_5;
+ label = 22;
+ break;
+ } else {
+ $p_0 = $p_5;
+ label = 3;
+ break;
+ }
+ case 22:
+ return $p_6 | 0;
+ }
+ return 0;
+}
+function _quoted_string($p, $token) {
+ $p = $p | 0;
+ $token = $token | 0;
+ var $0 = 0, $p_addr_013 = 0, $1 = 0, $tobool14 = 0, $cmp16 = 0, $not_tobool17 = 0, $2 = 0, $3 = 0, $p_addr_020 = 0, $q_019 = 0, $p_pn18 = 0, $cmp5 = 0, $add_ptr = 0, $4 = 0, $cmp9 = 0, $cmp15 = 0, $incdec_ptr19 = 0, $p_addr_1 = 0, $q_1 = 0, $5 = 0, $incdec_ptr23 = 0, $p_addr_0 = 0, $6 = 0, $tobool = 0, $cmp = 0, $not_tobool = 0, $7 = 0, $tobool_lcssa = 0, $p_addr_0_lcssa = 0, $q_0_lcssa = 0, $p_pn_lcssa = 0, $8 = 0, $tobool28 = 0, $cond = 0, $9 = 0, $call = 0, $incdec_ptr30 = 0, $p_addr_2 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$p] | 0;
+ $p_addr_013 = $p + 1 | 0;
+ $1 = HEAP8[$p_addr_013] | 0;
+ $tobool14 = $1 << 24 >> 24 == 0;
+ $cmp16 = $1 << 24 >> 24 != $0 << 24 >> 24;
+ $not_tobool17 = $tobool14 ^ 1;
+ $2 = $cmp16 & $not_tobool17;
+ if ($2) {
+ $p_pn18 = $p;
+ $q_019 = $token;
+ $p_addr_020 = $p_addr_013;
+ $3 = $1;
+ label = 3;
+ break;
+ } else {
+ $p_pn_lcssa = $p;
+ $q_0_lcssa = $token;
+ $p_addr_0_lcssa = $p_addr_013;
+ $tobool_lcssa = $tobool14;
+ label = 8;
+ break;
+ }
+ case 3:
+ $cmp5 = $3 << 24 >> 24 == 92;
+ if ($cmp5) {
+ label = 4;
+ break;
+ } else {
+ $q_1 = $q_019;
+ $p_addr_1 = $p_addr_020;
+ label = 7;
+ break;
+ }
+ case 4:
+ $add_ptr = $p_pn18 + 2 | 0;
+ $4 = HEAP8[$add_ptr] | 0;
+ $cmp9 = $4 << 24 >> 24 == $0 << 24 >> 24;
+ if ($cmp9) {
+ $q_1 = $q_019;
+ $p_addr_1 = $add_ptr;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp15 = $4 << 24 >> 24 == 92;
+ if ($cmp15) {
+ label = 6;
+ break;
+ } else {
+ $q_1 = $q_019;
+ $p_addr_1 = $p_addr_020;
+ label = 7;
+ break;
+ }
+ case 6:
+ $incdec_ptr19 = $q_019 + 1 | 0;
+ HEAP8[$q_019] = $3;
+ $q_1 = $incdec_ptr19;
+ $p_addr_1 = $add_ptr;
+ label = 7;
+ break;
+ case 7:
+ $5 = HEAP8[$p_addr_1] | 0;
+ $incdec_ptr23 = $q_1 + 1 | 0;
+ HEAP8[$q_1] = $5;
+ $p_addr_0 = $p_addr_1 + 1 | 0;
+ $6 = HEAP8[$p_addr_0] | 0;
+ $tobool = $6 << 24 >> 24 == 0;
+ $cmp = $6 << 24 >> 24 != $0 << 24 >> 24;
+ $not_tobool = $tobool ^ 1;
+ $7 = $cmp & $not_tobool;
+ if ($7) {
+ $p_pn18 = $p_addr_1;
+ $q_019 = $incdec_ptr23;
+ $p_addr_020 = $p_addr_0;
+ $3 = $6;
+ label = 3;
+ break;
+ } else {
+ $p_pn_lcssa = $p_addr_1;
+ $q_0_lcssa = $incdec_ptr23;
+ $p_addr_0_lcssa = $p_addr_0;
+ $tobool_lcssa = $tobool;
+ label = 8;
+ break;
+ }
+ case 8:
+ if ($tobool_lcssa) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $8 = HEAP32[41740] | 0;
+ $tobool28 = ($8 | 0) != 0;
+ $cond = $tobool28 ? $8 : 111640;
+ $9 = HEAP32[41638] | 0;
+ $call = _agerr(0, 145192, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $cond, HEAP32[tempInt + 8 >> 2] = $9, tempInt) | 0) | 0;
+ $p_addr_2 = $p_addr_0_lcssa;
+ label = 11;
+ break;
+ case 10:
+ $incdec_ptr30 = $p_pn_lcssa + 2 | 0;
+ $p_addr_2 = $incdec_ptr30;
+ label = 11;
+ break;
+ case 11:
+ HEAP8[$q_0_lcssa] = 0;
+ STACKTOP = __stackBase__;
+ return $p_addr_2 | 0;
+ }
+ return 0;
+}
+function _html_string3314($p, $token) {
+ $p = $p | 0;
+ $token = $token | 0;
+ var $call = 0;
+ HEAP8[165432] = HEAP32[41638] & 255;
+ $call = _html_pair($p + 1 | 0, $token) | 0;
+ return (($call | 0) == 0 ? 0 : $call + 1 | 0) | 0;
+}
+function _scan_num($p, $token) {
+ $p = $p | 0;
+ $token = $token | 0;
+ var $0 = 0, $cmp = 0, $incdec_ptr = 0, $incdec_ptr2 = 0, $z_0 = 0, $q_0 = 0, $1 = 0, $cmp4 = 0, $incdec_ptr7 = 0, $incdec_ptr8 = 0, $z_1_ph = 0, $saw_rp_0_ph = 0, $q_1_ph = 0, $2 = 0, $conv1040 = 0, $isdigittmp41 = 0, $isdigit42 = 0, $q_144 = 0, $z_143 = 0, $incdec_ptr11 = 0, $3 = 0, $incdec_ptr12 = 0, $4 = 0, $conv10 = 0, $isdigittmp = 0, $isdigit = 0, $q_1_lcssa = 0, $saw_digit_0_lcssa = 0, $z_1_lcssa = 0, $5 = 0, $cmp14 = 0, $cmp16 = 0, $or_cond = 0, $q_231 = 0, $z_232 = 0, $6 = 0, $conv2233 = 0, $isdigittmp2934 = 0, $isdigit3035 = 0, $z_237 = 0, $q_236 = 0, $7 = 0, $q_2 = 0, $z_2 = 0, $8 = 0, $conv22 = 0, $isdigittmp29 = 0, $isdigit30 = 0, $z_3 = 0, $q_3 = 0, $cond28 = 0, $z_351 = 0, $9 = 0, $tobool33 = 0, $conv32 = 0, $call36 = 0, $tobool37 = 0, $10 = 0, $cmp39 = 0, $z_3_pn = 0, $endp_0 = 0, $11 = 0, $tobool44 = 0, $conv43 = 0, $call46 = 0, $cmp49 = 0, $not_tobool47 = 0, $cmp49_ = 0, $12 = 0, $tobool54 = 0, $cond = 0, $13 = 0, $call55 = 0, $z_4 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$p] | 0;
+ $cmp = $0 << 24 >> 24 == 45;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $q_0 = $token;
+ $z_0 = $p;
+ label = 4;
+ break;
+ }
+ case 3:
+ $incdec_ptr = $p + 1 | 0;
+ $incdec_ptr2 = $token + 1 | 0;
+ HEAP8[$token] = $0;
+ $q_0 = $incdec_ptr2;
+ $z_0 = $incdec_ptr;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP8[$z_0] | 0;
+ $cmp4 = $1 << 24 >> 24 == 46;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ $q_1_ph = $q_0;
+ $saw_rp_0_ph = 0;
+ $z_1_ph = $z_0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $incdec_ptr7 = $z_0 + 1 | 0;
+ $incdec_ptr8 = $q_0 + 1 | 0;
+ HEAP8[$q_0] = $1;
+ $q_1_ph = $incdec_ptr8;
+ $saw_rp_0_ph = 1;
+ $z_1_ph = $incdec_ptr7;
+ label = 6;
+ break;
+ case 6:
+ $2 = HEAP8[$z_1_ph] | 0;
+ $conv1040 = $2 & 255;
+ $isdigittmp41 = $conv1040 - 48 | 0;
+ $isdigit42 = $isdigittmp41 >>> 0 < 10;
+ if ($isdigit42) {
+ $z_143 = $z_1_ph;
+ $q_144 = $q_1_ph;
+ label = 7;
+ break;
+ } else {
+ $z_1_lcssa = $z_1_ph;
+ $saw_digit_0_lcssa = 0;
+ $q_1_lcssa = $q_1_ph;
+ label = 8;
+ break;
+ }
+ case 7:
+ $incdec_ptr11 = $z_143 + 1 | 0;
+ $3 = HEAP8[$z_143] | 0;
+ $incdec_ptr12 = $q_144 + 1 | 0;
+ HEAP8[$q_144] = $3;
+ $4 = HEAP8[$incdec_ptr11] | 0;
+ $conv10 = $4 & 255;
+ $isdigittmp = $conv10 - 48 | 0;
+ $isdigit = $isdigittmp >>> 0 < 10;
+ if ($isdigit) {
+ $z_143 = $incdec_ptr11;
+ $q_144 = $incdec_ptr12;
+ label = 7;
+ break;
+ } else {
+ $z_1_lcssa = $incdec_ptr11;
+ $saw_digit_0_lcssa = 1;
+ $q_1_lcssa = $incdec_ptr12;
+ label = 8;
+ break;
+ }
+ case 8:
+ $5 = HEAP8[$z_1_lcssa] | 0;
+ $cmp14 = $5 << 24 >> 24 == 46;
+ $cmp16 = ($saw_rp_0_ph | 0) == 0;
+ $or_cond = $cmp14 & $cmp16;
+ if ($or_cond) {
+ label = 9;
+ break;
+ } else {
+ $q_3 = $q_1_lcssa;
+ $z_3 = $z_1_lcssa;
+ label = 12;
+ break;
+ }
+ case 9:
+ HEAP8[$q_1_lcssa] = $5;
+ $q_231 = $q_1_lcssa + 1 | 0;
+ $z_232 = $z_1_lcssa + 1 | 0;
+ $6 = HEAP8[$z_232] | 0;
+ $conv2233 = $6 & 255;
+ $isdigittmp2934 = $conv2233 - 48 | 0;
+ $isdigit3035 = $isdigittmp2934 >>> 0 < 10;
+ if ($isdigit3035) {
+ $q_236 = $q_231;
+ $z_237 = $z_232;
+ label = 10;
+ break;
+ } else {
+ $q_3 = $q_231;
+ $z_3 = $z_232;
+ label = 12;
+ break;
+ }
+ case 10:
+ $7 = HEAP8[$z_237] | 0;
+ HEAP8[$q_236] = $7;
+ $q_2 = $q_236 + 1 | 0;
+ $z_2 = $z_237 + 1 | 0;
+ $8 = HEAP8[$z_2] | 0;
+ $conv22 = $8 & 255;
+ $isdigittmp29 = $conv22 - 48 | 0;
+ $isdigit30 = $isdigittmp29 >>> 0 < 10;
+ if ($isdigit30) {
+ $q_236 = $q_2;
+ $z_237 = $z_2;
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ HEAP8[$q_2] = 0;
+ $z_351 = $z_2;
+ label = 13;
+ break;
+ case 12:
+ HEAP8[$q_3] = 0;
+ $cond28 = ($saw_digit_0_lcssa | 0) == 0;
+ if ($cond28) {
+ $z_4 = 0;
+ label = 19;
+ break;
+ } else {
+ $z_351 = $z_3;
+ label = 13;
+ break;
+ }
+ case 13:
+ $9 = HEAP8[$z_351] | 0;
+ $tobool33 = $9 << 24 >> 24 == 0;
+ if ($tobool33) {
+ $z_4 = $z_351;
+ label = 19;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $conv32 = $9 & 255;
+ $call36 = _isalpha($conv32 | 0) | 0;
+ $tobool37 = ($call36 | 0) == 0;
+ if ($tobool37) {
+ label = 15;
+ break;
+ } else {
+ $z_3_pn = $z_351;
+ label = 16;
+ break;
+ }
+ case 15:
+ $10 = HEAP8[$z_351] | 0;
+ $cmp39 = $10 << 24 >> 24 == 95;
+ if ($cmp39) {
+ $z_3_pn = $z_351;
+ label = 16;
+ break;
+ } else {
+ $z_4 = $z_351;
+ label = 19;
+ break;
+ }
+ case 16:
+ $endp_0 = $z_3_pn + 1 | 0;
+ $11 = HEAP8[$endp_0] | 0;
+ $tobool44 = $11 << 24 >> 24 == 0;
+ if ($tobool44) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $conv43 = $11 & 255;
+ $call46 = _isalpha($conv43 | 0) | 0;
+ $cmp49 = $11 << 24 >> 24 == 95;
+ $not_tobool47 = ($call46 | 0) != 0;
+ $cmp49_ = $cmp49 | $not_tobool47;
+ if ($cmp49_) {
+ $z_3_pn = $endp_0;
+ label = 16;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ HEAP8[$endp_0] = 0;
+ $12 = HEAP32[41740] | 0;
+ $tobool54 = ($12 | 0) != 0;
+ $cond = $tobool54 ? $12 : 111640;
+ $13 = HEAP32[41638] | 0;
+ $call55 = _agerr(0, 151040, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = $cond, HEAP32[tempInt + 8 >> 2] = $13, HEAP32[tempInt + 16 >> 2] = $p, HEAP32[tempInt + 24 >> 2] = $token, HEAP32[tempInt + 32 >> 2] = $z_351, tempInt) | 0) | 0;
+ HEAP8[$endp_0] = $11;
+ $z_4 = $z_351;
+ label = 19;
+ break;
+ case 19:
+ STACKTOP = __stackBase__;
+ return $z_4 | 0;
+ }
+ return 0;
+}
+function _scan_token($p, $token) {
+ $p = $p | 0;
+ $token = $token | 0;
+ var $cmp = 0, $p_addr_0 = 0, $q_0 = 0, $0 = 0, $conv = 0, $call = 0, $tobool = 0, $1 = 0, $cmp2 = 0, $lnot = 0, $or_cond = 0, $incdec_ptr = 0, $2 = 0, $incdec_ptr7 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($p | 0) == 0;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ $q_0 = $token;
+ $p_addr_0 = $p;
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$p_addr_0] | 0;
+ $conv = $0 & 255;
+ $call = _isalnum($conv | 0) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$p_addr_0] | 0;
+ $cmp2 = $1 << 24 >> 24 == 95;
+ $lnot = $1 << 24 >> 24 < 0;
+ $or_cond = $cmp2 | $lnot;
+ if ($or_cond) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $incdec_ptr = $p_addr_0 + 1 | 0;
+ $2 = HEAP8[$p_addr_0] | 0;
+ $incdec_ptr7 = $q_0 + 1 | 0;
+ HEAP8[$q_0] = $2;
+ $q_0 = $incdec_ptr7;
+ $p_addr_0 = $incdec_ptr;
+ label = 3;
+ break;
+ case 6:
+ HEAP8[$q_0] = 0;
+ $retval_0 = $p_addr_0;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agerror($msg) {
+ $msg = $msg | 0;
+ var $0 = 0, $inc = 0, $tobool = 0, $1 = 0, $tobool1 = 0, $cond = 0, $2 = 0, $call = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP16[84282] | 0;
+ $inc = $0 + 1 & 65535;
+ HEAP16[84282] = $inc;
+ $tobool = $0 << 16 >> 16 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[41740] | 0;
+ $tobool1 = ($1 | 0) != 0;
+ $cond = $tobool1 ? $1 : 111640;
+ $2 = HEAP32[41638] | 0;
+ $call = _agerr(1, 116856, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $cond, HEAP32[tempInt + 8 >> 2] = $2, HEAP32[tempInt + 16 >> 2] = $msg, HEAP32[tempInt + 24 >> 2] = $2, tempInt) | 0) | 0;
+ _error_context2903();
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _error_context2903() {
+ var $0 = 0, $add_ptr = 0, $1 = 0, $cmp = 0, $call = 0, $2 = 0, $_pn = 0, $p_0 = 0, $cmp2 = 0, $3 = 0, $conv = 0, $call3 = 0, $lnot = 0, $4 = 0, $call7 = 0, $call9 = 0, $5 = 0, $6 = 0, $call10 = 0, $7 = 0, $call11 = 0, $8 = 0, $call12 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[42140] | 0;
+ $add_ptr = $0 + 1 | 0;
+ $1 = HEAP32[41652] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _agerr(3, 161744, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $2 = HEAP32[41652] | 0;
+ $_pn = $2;
+ label = 4;
+ break;
+ case 4:
+ $p_0 = $_pn - 1 | 0;
+ $cmp2 = $p_0 >>> 0 > $add_ptr >>> 0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $3 = HEAP8[$p_0] | 0;
+ $conv = $3 & 255;
+ $call3 = _isspace($conv | 0) | 0;
+ $lnot = ($call3 | 0) == 0;
+ if ($lnot) {
+ $_pn = $p_0;
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $4 = HEAP8[$p_0] | 0;
+ HEAP8[$p_0] = 0;
+ $call7 = _agerr(3, $add_ptr, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ HEAP8[$p_0] = $4;
+ label = 7;
+ break;
+ case 7:
+ $call9 = _agerr(3, 158208, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $5 = HEAP32[41652] | 0;
+ $6 = HEAP8[$5] | 0;
+ HEAP8[$5] = 0;
+ $call10 = _agerr(3, $p_0, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $7 = HEAP32[41652] | 0;
+ HEAP8[$7] = $6;
+ $call11 = _agerr(3, 154728, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ $8 = HEAP32[41652] | 0;
+ $call12 = _agerr(3, $8, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _agerr_va($level, $fmt, $args) {
+ $level = $level | 0;
+ $fmt = $fmt | 0;
+ $args = $args | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $cond = 0, $cond5 = 0, $1 = 0, $cmp6 = 0, $cond10 = 0, $2 = 0, $cmp11 = 0, $3 = 0, $tobool = 0, $4 = 0, $cmp15 = 0, $cond16 = 0, $call = 0, $5 = 0, $call17 = 0, $6 = 0, $7 = 0, $tobool20 = 0, $call22 = 0, $tobool23 = 0, $8 = 0, $call29 = 0, $9 = 0, $call31 = 0, $10 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($level | 0) == 3;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[22294] | 0;
+ $cond5 = $0;
+ label = 5;
+ break;
+ case 4:
+ $cmp1 = ($level | 0) == 2;
+ $cond = $cmp1 ? 1 : $level;
+ $cond5 = $cond;
+ label = 5;
+ break;
+ case 5:
+ HEAP32[22294] = $cond5;
+ $1 = HEAP32[22284] | 0;
+ $cmp6 = $1 >>> 0 > $cond5 >>> 0;
+ $cond10 = $cmp6 ? $1 : $cond5;
+ HEAP32[22284] = $cond10;
+ $2 = HEAP32[22296] | 0;
+ $cmp11 = $cond5 >>> 0 < $2 >>> 0;
+ if ($cmp11) {
+ label = 11;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = HEAP32[228] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _userout($level, $fmt, $args);
+ $retval_0 = 0;
+ label = 16;
+ break;
+ case 8:
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $4 = HEAP32[_stderr >> 2] | 0;
+ $cmp15 = ($level | 0) == 1;
+ $cond16 = $cmp15 ? 103384 : 99184;
+ $call = _fprintf($4 | 0, 107312, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $cond16, tempInt) | 0) | 0;
+ label = 10;
+ break;
+ case 10:
+ $5 = HEAP32[_stderr >> 2] | 0;
+ $call17 = _vfprintf($5 | 0, $fmt | 0, $args | 0) | 0;
+ $6 = $args;
+ $retval_0 = 0;
+ label = 16;
+ break;
+ case 11:
+ $7 = HEAP32[22292] | 0;
+ $tobool20 = ($7 | 0) == 0;
+ if ($tobool20) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $call22 = _tmpfile() | 0;
+ HEAP32[22292] = $call22;
+ $tobool23 = ($call22 | 0) == 0;
+ if ($tobool23) {
+ $retval_0 = 1;
+ label = 16;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ if ($cmp) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $8 = HEAP32[22292] | 0;
+ $call29 = _ftell($8 | 0) | 0;
+ HEAP32[22290] = $call29;
+ label = 15;
+ break;
+ case 15:
+ $9 = HEAP32[22292] | 0;
+ $call31 = _vfprintf($9 | 0, $fmt | 0, $args | 0) | 0;
+ $10 = $args;
+ $retval_0 = 0;
+ label = 16;
+ break;
+ case 16:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agerrorf($fmt, varrp) {
+ $fmt = $fmt | 0;
+ varrp = varrp | 0;
+ var $args = 0, $arraydecay1 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $args = __stackBase__ | 0;
+ $arraydecay1 = $args;
+ HEAP32[$arraydecay1 >> 2] = varrp;
+ HEAP32[$arraydecay1 + 4 >> 2] = 0;
+ _agerr_va(1, $fmt, $args | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _userout($level, $fmt, $args) {
+ $level = $level | 0;
+ $fmt = $fmt | 0;
+ $args = $args | 0;
+ var $0 = 0, $tobool = 0, $1 = 0, $call = 0, $tobool1 = 0, $2 = 0, $3 = 0, $cmp = 0, $4 = 0, $cmp6 = 0, $cond = 0, $call7 = 0, $5 = 0, $call8 = 0, $6 = 0, $7 = 0, $call10 = 0, $cmp11 = 0, $8 = 0, $cmp12 = 0, $or_cond = 0, $9 = 0, $10 = 0, $call14 = 0, $11 = 0, $mul = 0, $add = 0, $cmp16 = 0, $mul_add = 0, $12 = 0, $call20 = 0, $cmp21 = 0, $13 = 0, $14 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[226] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[224] | 0;
+ $call = _malloc($1) | 0;
+ HEAP32[226] = $call;
+ $tobool1 = ($call | 0) == 0;
+ if ($tobool1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $2 = HEAP32[_stderr >> 2] | 0;
+ $3 = _fwrite(95136, 35, 1, $2 | 0) | 0;
+ label = 11;
+ break;
+ case 5:
+ $cmp = ($level | 0) == 3;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $4 = HEAP32[228] | 0;
+ $cmp6 = ($level | 0) == 1;
+ $cond = $cmp6 ? 103384 : 99184;
+ $call7 = FUNCTION_TABLE_ii[$4 & 1023]($cond) | 0;
+ $5 = HEAP32[228] | 0;
+ $call8 = FUNCTION_TABLE_ii[$5 & 1023](91592) | 0;
+ label = 7;
+ break;
+ case 7:
+ $6 = HEAP32[226] | 0;
+ $7 = HEAP32[224] | 0;
+ $call10 = _vsnprintf($6 | 0, $7 | 0, $fmt | 0, $args | 0) | 0;
+ $cmp11 = ($call10 | 0) > -1;
+ $8 = HEAP32[224] | 0;
+ $cmp12 = ($call10 | 0) < ($8 | 0);
+ $or_cond = $cmp11 & $cmp12;
+ if ($or_cond) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $9 = HEAP32[228] | 0;
+ $10 = HEAP32[226] | 0;
+ $call14 = FUNCTION_TABLE_ii[$9 & 1023]($10) | 0;
+ $11 = $args;
+ label = 11;
+ break;
+ case 9:
+ $mul = $8 << 1;
+ $add = $call10 + 1 | 0;
+ $cmp16 = ($mul | 0) > ($add | 0);
+ $mul_add = $cmp16 ? $mul : $add;
+ HEAP32[224] = $mul_add;
+ $12 = HEAP32[226] | 0;
+ $call20 = _realloc($12, $mul_add) | 0;
+ $cmp21 = ($call20 | 0) == 0;
+ if ($cmp21) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ $13 = HEAP32[_stderr >> 2] | 0;
+ $14 = _fwrite(95136, 35, 1, $13 | 0) | 0;
+ label = 11;
+ break;
+ case 11:
+ return;
+ }
+}
+function _html_pair($p, $tokp) {
+ $p = $p | 0;
+ $tokp = $tokp | 0;
+ var $ptr = 0, $eptr = 0, $p_addr_0_ph = 0, $depth_0_ph = 0, $p_addr_0 = 0, $0 = 0, $dec = 0, $cmp4 = 0, $inc = 0, $depth_1 = 0, $1 = 0, $2 = 0, $cmp13 = 0, $call = 0, $3 = 0, $incdec_ptr = 0, $incdec_ptr17 = 0, $call18 = 0, $cmp19 = 0, $4 = 0, $conv22 = 0, $5 = 0, $tobool23 = 0, $cond27 = 0, $call28 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr = $tokp + 4 | 0;
+ $eptr = $tokp + 8 | 0;
+ $depth_0_ph = 1;
+ $p_addr_0_ph = $p;
+ label = 3;
+ break;
+ case 3:
+ $p_addr_0 = $p_addr_0_ph;
+ label = 4;
+ break;
+ case 4:
+ $0 = HEAP8[$p_addr_0] | 0;
+ if (($0 << 24 >> 24 | 0) == 62) {
+ label = 5;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 60) {
+ label = 6;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 0) {
+ label = 10;
+ break;
+ } else {
+ $depth_1 = $depth_0_ph;
+ label = 7;
+ break;
+ }
+ case 5:
+ $dec = $depth_0_ph - 1 | 0;
+ $cmp4 = ($dec | 0) == 0;
+ if ($cmp4) {
+ $retval_0 = $p_addr_0;
+ label = 12;
+ break;
+ } else {
+ $depth_1 = $dec;
+ label = 7;
+ break;
+ }
+ case 6:
+ $inc = $depth_0_ph + 1 | 0;
+ $depth_1 = $inc;
+ label = 7;
+ break;
+ case 7:
+ $1 = HEAP32[$ptr >> 2] | 0;
+ $2 = HEAP32[$eptr >> 2] | 0;
+ $cmp13 = $1 >>> 0 < $2 >>> 0;
+ if ($cmp13) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call = _agxbmore($tokp, 1) | 0;
+ label = 9;
+ break;
+ case 9:
+ $3 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $3 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$3] = $0;
+ $incdec_ptr17 = $p_addr_0 + 1 | 0;
+ $depth_0_ph = $depth_1;
+ $p_addr_0_ph = $incdec_ptr17;
+ label = 3;
+ break;
+ case 10:
+ $call18 = _lex_gets() | 0;
+ $cmp19 = ($call18 | 0) == 0;
+ if ($cmp19) {
+ label = 11;
+ break;
+ } else {
+ $p_addr_0 = $call18;
+ label = 4;
+ break;
+ }
+ case 11:
+ $4 = HEAP8[165432] | 0;
+ $conv22 = $4 & 255;
+ $5 = HEAP32[41740] | 0;
+ $tobool23 = ($5 | 0) != 0;
+ $cond27 = $tobool23 ? $5 : 111640;
+ $call28 = _agerr(0, 147984, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $conv22, HEAP32[tempInt + 8 >> 2] = $cond27, tempInt) | 0) | 0;
+ $retval_0 = 0;
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _storeFileName($fname, $len) {
+ $fname = $fname | 0;
+ $len = $len | 0;
+ var $0 = 0, $cmp = 0, $tobool = 0, $1 = 0, $add = 0, $call = 0, $add2 = 0, $call3 = 0, $storemerge = 0, $2 = 0, $call5 = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[1026] | 0;
+ $cmp = ($0 | 0) < ($len | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[1028] | 0;
+ $add = $len + 1 | 0;
+ $call = _realloc($1, $add) | 0;
+ $storemerge = $call;
+ label = 6;
+ break;
+ case 5:
+ $add2 = $len + 1 | 0;
+ $call3 = _malloc($add2) | 0;
+ $storemerge = $call3;
+ label = 6;
+ break;
+ case 6:
+ HEAP32[1028] = $storemerge;
+ HEAP32[1026] = $len;
+ label = 7;
+ break;
+ case 7:
+ $2 = HEAP32[1028] | 0;
+ $call5 = _strcpy($2 | 0, $fname | 0) | 0;
+ $3 = HEAP32[1028] | 0;
+ HEAP32[41740] = $3;
+ return;
+ }
+}
+function _agfindnode($g, $name) {
+ $g = $g | 0;
+ $name = $name | 0;
+ var $univ = 0, $0 = 0, $node_dict = 0, $1 = 0, $searchf = 0, $2 = 0, $call = 0, $3 = 0, $tobool = 0, $root = 0, $4 = 0, $cmp = 0, $nodes = 0, $5 = 0, $searchf3 = 0, $6 = 0, $call5 = 0, $7 = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $univ = $g + 16 | 0;
+ $0 = HEAP32[$univ >> 2] | 0;
+ $node_dict = $0 | 0;
+ $1 = HEAP32[$node_dict >> 2] | 0;
+ $searchf = $1 | 0;
+ $2 = HEAP32[$searchf >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$2 & 1023]($1, $name, 512) | 0;
+ $3 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $rv_0 = $3;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $root = $g + 32 | 0;
+ $4 = HEAP32[$root >> 2] | 0;
+ $cmp = ($4 | 0) == ($g | 0);
+ if ($cmp) {
+ $rv_0 = $3;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $nodes = $g + 20 | 0;
+ $5 = HEAP32[$nodes >> 2] | 0;
+ $searchf3 = $5 | 0;
+ $6 = HEAP32[$searchf3 >> 2] | 0;
+ $call5 = FUNCTION_TABLE_iiii[$6 & 1023]($5, $call, 4) | 0;
+ $7 = $call5;
+ $rv_0 = $7;
+ label = 5;
+ break;
+ case 5:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _agidnode($g, $index) {
+ $g = $g | 0;
+ $index = $index | 0;
+ var $index_addr = 0, $0 = 0, $3 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $index_addr = __stackBase__ | 0;
+ HEAP32[$index_addr >> 2] = $index;
+ $0 = HEAP32[$g + 20 >> 2] | 0;
+ $3 = FUNCTION_TABLE_iiii[HEAP32[$0 >> 2] & 1023]($0, $index_addr, 512) | 0;
+ STACKTOP = __stackBase__;
+ return $3 | 0;
+}
+function _agnode($g, $name) {
+ $g = $g | 0;
+ $name = $name | 0;
+ var $root = 0, $0 = 0, $call = 0, $cmp = 0, $proto = 0, $1 = 0, $n1 = 0, $2 = 0, $call2 = 0, $univ = 0, $3 = 0, $node_dict = 0, $4 = 0, $searchf = 0, $5 = 0, $6 = 0, $call5 = 0, $n_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $call = _agfindnode($0, $name) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $n_0 = $call;
+ label = 4;
+ break;
+ }
+ case 3:
+ $proto = $g + 40 | 0;
+ $1 = HEAP32[$proto >> 2] | 0;
+ $n1 = $1 | 0;
+ $2 = HEAP32[$n1 >> 2] | 0;
+ $call2 = _agNEWnode($g, $name, $2) | 0;
+ $univ = $g + 16 | 0;
+ $3 = HEAP32[$univ >> 2] | 0;
+ $node_dict = $3 | 0;
+ $4 = HEAP32[$node_dict >> 2] | 0;
+ $searchf = $4 | 0;
+ $5 = HEAP32[$searchf >> 2] | 0;
+ $6 = $call2 | 0;
+ $call5 = FUNCTION_TABLE_iiii[$5 & 1023]($4, $6, 1) | 0;
+ $n_0 = $call2;
+ label = 4;
+ break;
+ case 4:
+ _agINSnode($g, $n_0);
+ return $n_0 | 0;
+ }
+ return 0;
+}
+function _agNEWnode($subg, $name, $proto) {
+ $subg = $subg | 0;
+ $name = $name | 0;
+ $proto = $proto | 0;
+ var $0 = 0, $call = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $call1 = 0, $name2 = 0, $6 = 0, $univ = 0, $7 = 0, $max_node_id = 0, $8 = 0, $inc = 0, $id = 0, $9 = 0, $root = 0, $10 = 0, $graph = 0, $11 = 0, $12 = 0, $nodeattr = 0, $13 = 0, $dict = 0, $14 = 0, $call4 = 0, $tobool = 0, $attr7 = 0, $15 = 0, $didset8 = 0, $16 = 0, $call5 = 0, $17 = 0, $attr = 0, $18 = 0, $sub = 0, $div = 0, $call6 = 0, $didset = 0, $19 = 0, $cmp20 = 0, $tobool9 = 0, $attr15 = 0, $20 = 0, $attr10 = 0, $i_021 = 0, $21 = 0, $arrayidx = 0, $22 = 0, $nodeattr12 = 0, $23 = 0, $list = 0, $24 = 0, $arrayidx13 = 0, $25 = 0, $value = 0, $cond_in = 0, $cond = 0, $call14 = 0, $26 = 0, $arrayidx16 = 0, $inc17 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[42135] | 0;
+ $call = _calloc(1, $0) | 0;
+ $1 = $call;
+ $2 = $call;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $4 = $3 & -16;
+ $5 = $4 | 1;
+ HEAP32[$2 >> 2] = $5;
+ $call1 = _agstrdup($name) | 0;
+ $name2 = $call + 12 | 0;
+ $6 = $name2;
+ HEAP32[$6 >> 2] = $call1;
+ $univ = $subg + 16 | 0;
+ $7 = HEAP32[$univ >> 2] | 0;
+ $max_node_id = $7 + 16 | 0;
+ $8 = HEAP32[$max_node_id >> 2] | 0;
+ $inc = $8 + 1 | 0;
+ HEAP32[$max_node_id >> 2] = $inc;
+ $id = $call + 16 | 0;
+ $9 = $id;
+ HEAP32[$9 >> 2] = $8;
+ $root = $subg + 32 | 0;
+ $10 = HEAP32[$root >> 2] | 0;
+ $graph = $call + 20 | 0;
+ $11 = $graph;
+ HEAP32[$11 >> 2] = $10;
+ $12 = HEAP32[$univ >> 2] | 0;
+ $nodeattr = $12 + 4 | 0;
+ $13 = HEAP32[$nodeattr >> 2] | 0;
+ $dict = $13 + 4 | 0;
+ $14 = HEAP32[$dict >> 2] | 0;
+ $call4 = _dtsize($14) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $attr7 = $call + 4 | 0;
+ $15 = $attr7;
+ HEAP32[$15 >> 2] = 0;
+ $didset8 = $call + 8 | 0;
+ $16 = $didset8;
+ HEAP32[$16 >> 2] = 0;
+ label = 10;
+ break;
+ case 4:
+ $call5 = _calloc($call4, 4) | 0;
+ $17 = $call5;
+ $attr = $call + 4 | 0;
+ $18 = $attr;
+ HEAP32[$18 >> 2] = $17;
+ $sub = $call4 + 7 | 0;
+ $div = ($sub | 0) / 8 & -1;
+ $call6 = _calloc($div, 1) | 0;
+ $didset = $call + 8 | 0;
+ $19 = $didset;
+ HEAP32[$19 >> 2] = $call6;
+ $cmp20 = ($call4 | 0) > 0;
+ if ($cmp20) {
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ $tobool9 = ($proto | 0) == 0;
+ $attr15 = $call + 4 | 0;
+ $20 = $attr15;
+ $attr10 = $proto + 4 | 0;
+ $i_021 = 0;
+ label = 6;
+ break;
+ case 6:
+ if ($tobool9) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $21 = HEAP32[$attr10 >> 2] | 0;
+ $arrayidx = $21 + ($i_021 << 2) | 0;
+ $cond_in = $arrayidx;
+ label = 9;
+ break;
+ case 8:
+ $22 = HEAP32[$univ >> 2] | 0;
+ $nodeattr12 = $22 + 4 | 0;
+ $23 = HEAP32[$nodeattr12 >> 2] | 0;
+ $list = $23 + 8 | 0;
+ $24 = HEAP32[$list >> 2] | 0;
+ $arrayidx13 = $24 + ($i_021 << 2) | 0;
+ $25 = HEAP32[$arrayidx13 >> 2] | 0;
+ $value = $25 + 4 | 0;
+ $cond_in = $value;
+ label = 9;
+ break;
+ case 9:
+ $cond = HEAP32[$cond_in >> 2] | 0;
+ $call14 = _agstrdup($cond) | 0;
+ $26 = HEAP32[$20 >> 2] | 0;
+ $arrayidx16 = $26 + ($i_021 << 2) | 0;
+ HEAP32[$arrayidx16 >> 2] = $call14;
+ $inc17 = $i_021 + 1 | 0;
+ $cmp = ($inc17 | 0) < ($call4 | 0);
+ if ($cmp) {
+ $i_021 = $inc17;
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ return $1 | 0;
+ }
+ return 0;
+}
+function _agINSnode($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $id = 0, $0 = 0, $call = 0, $tobool = 0, $nodes = 0, $1 = 0, $searchf = 0, $2 = 0, $3 = 0, $call2 = 0, $4 = 0, $5 = 0, $and = 0, $cmp = 0, $meta_node = 0, $6 = 0, $graph = 0, $7 = 0, $call5 = 0, $tobool612 = 0, $e_013 = 0, $tail = 0, $8 = 0, $9 = 0, $call7 = 0, $10 = 0, $call8 = 0, $tobool6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $id = $n + 16 | 0;
+ $0 = HEAP32[$id >> 2] | 0;
+ $call = _agidnode($g, $0) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $nodes = $g + 20 | 0;
+ $1 = HEAP32[$nodes >> 2] | 0;
+ $searchf = $1 | 0;
+ $2 = HEAP32[$searchf >> 2] | 0;
+ $3 = $n | 0;
+ $call2 = FUNCTION_TABLE_iiii[$2 & 1023]($1, $3, 1) | 0;
+ $4 = $g;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $and = $5 & 64;
+ $cmp = ($and | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $meta_node = $g + 36 | 0;
+ $6 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $6 + 20 | 0;
+ $7 = HEAP32[$graph >> 2] | 0;
+ $call5 = _agfstin($7, $6) | 0;
+ $tobool612 = ($call5 | 0) == 0;
+ if ($tobool612) {
+ label = 6;
+ break;
+ } else {
+ $e_013 = $call5;
+ label = 5;
+ break;
+ }
+ case 5:
+ $tail = $e_013 + 16 | 0;
+ $8 = HEAP32[$tail >> 2] | 0;
+ $9 = $8;
+ $call7 = _agusergraph($9) | 0;
+ $10 = $call7;
+ _agINSnode($10, $n);
+ $call8 = _agnxtin($7, $e_013) | 0;
+ $tobool6 = ($call8 | 0) == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ $e_013 = $call8;
+ label = 5;
+ break;
+ }
+ case 6:
+ return;
+ }
+}
+function _agDELnode($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $call = 0, $tobool25 = 0, $e_026 = 0, $call1 = 0, $tobool = 0, $0 = 0, $1 = 0, $and = 0, $cmp = 0, $meta_node = 0, $2 = 0, $graph = 0, $3 = 0, $call3 = 0, $tobool523 = 0, $4 = 0, $e_124 = 0, $head = 0, $5 = 0, $6 = 0, $call7 = 0, $nodes = 0, $7 = 0, $8 = 0, $searchf = 0, $9 = 0, $call9 = 0, $tobool10 = 0, $10 = 0, $call13 = 0, $tobool5 = 0, $nodes16 = 0, $11 = 0, $searchf17 = 0, $12 = 0, $13 = 0, $call19 = 0, $root = 0, $14 = 0, $cmp20 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _agfstedge($g, $n) | 0;
+ $tobool25 = ($call | 0) == 0;
+ if ($tobool25) {
+ label = 4;
+ break;
+ } else {
+ $e_026 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agnxtedge($g, $e_026, $n) | 0;
+ _agDELedge($g, $e_026);
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $e_026 = $call1;
+ label = 3;
+ break;
+ }
+ case 4:
+ $0 = $g;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $and = $1 & 64;
+ $cmp = ($and | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ $meta_node = $g + 36 | 0;
+ $2 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $2 + 20 | 0;
+ $3 = HEAP32[$graph >> 2] | 0;
+ $call3 = _agfstout($3, $2) | 0;
+ $tobool523 = ($call3 | 0) == 0;
+ if ($tobool523) {
+ label = 10;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $4 = $n | 0;
+ $e_124 = $call3;
+ label = 7;
+ break;
+ case 7:
+ $head = $e_124 + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $6 = $5;
+ $call7 = _agusergraph($6) | 0;
+ $nodes = $call7 + 20 | 0;
+ $7 = HEAP32[$nodes >> 2] | 0;
+ $8 = $7;
+ $searchf = $7;
+ $9 = HEAP32[$searchf >> 2] | 0;
+ $call9 = FUNCTION_TABLE_iiii[$9 & 1023]($8, $4, 4) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ if ($tobool10) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $10 = $call7;
+ _agDELnode($10, $n);
+ label = 9;
+ break;
+ case 9:
+ $call13 = _agnxtout($3, $e_124) | 0;
+ $tobool5 = ($call13 | 0) == 0;
+ if ($tobool5) {
+ label = 10;
+ break;
+ } else {
+ $e_124 = $call13;
+ label = 7;
+ break;
+ }
+ case 10:
+ $nodes16 = $g + 20 | 0;
+ $11 = HEAP32[$nodes16 >> 2] | 0;
+ $searchf17 = $11 | 0;
+ $12 = HEAP32[$searchf17 >> 2] | 0;
+ $13 = $n | 0;
+ $call19 = FUNCTION_TABLE_iiii[$12 & 1023]($11, $13, 2) | 0;
+ $root = $g + 32 | 0;
+ $14 = HEAP32[$root >> 2] | 0;
+ $cmp20 = ($14 | 0) == ($g | 0);
+ if ($cmp20) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ _agFREEnode($n);
+ label = 12;
+ break;
+ case 12:
+ return;
+ }
+}
+function _agFREEnode($n) {
+ $n = $n | 0;
+ var $0 = 0, $graph = 0, $1 = 0, $univ = 0, $2 = 0, $node_dict = 0, $3 = 0, $searchf = 0, $4 = 0, $call4 = 0, $5 = 0, $6 = 0, $7 = 0, $name = 0, $8 = 0, $9 = 0, $10 = 0, $11 = 0, $and = 0, $cmp = 0, $univ7 = 0, $12 = 0, $nodeattr = 0, $13 = 0, $dict8 = 0, $14 = 0, $call9 = 0, $cmp1015 = 0, $attr = 0, $i_016 = 0, $15 = 0, $arrayidx = 0, $16 = 0, $inc = 0, $cmp10 = 0, $attr11 = 0, $17 = 0, $18 = 0, $didset = 0, $19 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $n | 0;
+ $graph = $n + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $univ = $1 + 16 | 0;
+ $2 = HEAP32[$univ >> 2] | 0;
+ $node_dict = $2 | 0;
+ $3 = HEAP32[$node_dict >> 2] | 0;
+ $searchf = $3 | 0;
+ $4 = HEAP32[$searchf >> 2] | 0;
+ $call4 = FUNCTION_TABLE_iiii[$4 & 1023]($3, $0, 2) | 0;
+ $5 = $n;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $7 = $6 | 15;
+ HEAP32[$5 >> 2] = $7;
+ $name = $n + 12 | 0;
+ $8 = HEAP32[$name >> 2] | 0;
+ _agstrfree($8);
+ $9 = HEAP32[$graph >> 2] | 0;
+ $10 = $9;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $and = $11 & 64;
+ $cmp = ($and | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $univ7 = $9 + 16 | 0;
+ $12 = HEAP32[$univ7 >> 2] | 0;
+ $nodeattr = $12 + 4 | 0;
+ $13 = HEAP32[$nodeattr >> 2] | 0;
+ $dict8 = $13 + 4 | 0;
+ $14 = HEAP32[$dict8 >> 2] | 0;
+ $call9 = _dtsize($14) | 0;
+ $cmp1015 = ($call9 | 0) > 0;
+ if ($cmp1015) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $attr = $n + 4 | 0;
+ $i_016 = 0;
+ label = 5;
+ break;
+ case 5:
+ $15 = HEAP32[$attr >> 2] | 0;
+ $arrayidx = $15 + ($i_016 << 2) | 0;
+ $16 = HEAP32[$arrayidx >> 2] | 0;
+ _agstrfree($16);
+ $inc = $i_016 + 1 | 0;
+ $cmp10 = ($inc | 0) < ($call9 | 0);
+ if ($cmp10) {
+ $i_016 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $attr11 = $n + 4 | 0;
+ $17 = HEAP32[$attr11 >> 2] | 0;
+ $18 = $17;
+ _free($18);
+ $didset = $n + 8 | 0;
+ $19 = HEAP32[$didset >> 2] | 0;
+ _free($19);
+ _free($0);
+ return;
+ }
+}
+function _agfstnode($g) {
+ $g = $g | 0;
+ var $0 = 0;
+ $0 = HEAP32[$g + 20 >> 2] | 0;
+ return FUNCTION_TABLE_iiii[HEAP32[$0 >> 2] & 1023]($0, 0, 128) | 0;
+}
+function _agnxtnode($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $0 = 0;
+ $0 = HEAP32[$g + 20 >> 2] | 0;
+ return FUNCTION_TABLE_iiii[HEAP32[$0 >> 2] & 1023]($0, $n | 0, 8) | 0;
+}
+function _aglstnode($g) {
+ $g = $g | 0;
+ var $0 = 0;
+ $0 = HEAP32[$g + 20 >> 2] | 0;
+ return FUNCTION_TABLE_iiii[HEAP32[$0 >> 2] & 1023]($0, 0, 256) | 0;
+}
+function _agprvnode($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $0 = 0;
+ $0 = HEAP32[$g + 20 >> 2] | 0;
+ return FUNCTION_TABLE_iiii[HEAP32[$0 >> 2] & 1023]($0, $n | 0, 16) | 0;
+}
+function _agparse() {
+ var $agssa = 0, $agvsa = 0, $tmp = 0, $tmp211 = 0, $tmp215 = 0, $tmp218 = 0, $arraydecay = 0, $arraydecay1 = 0, $agval_sroa_0_0__idx28 = 0, $agval_sroa_1_4__idx39 = 0, $agval_sroa_0_0__idx26 = 0, $agval_sroa_1_4__idx37 = 0, $agval_sroa_0_0__idx24 = 0, $agval_sroa_1_4__idx35 = 0, $agval_sroa_0_0__idx22 = 0, $agval_sroa_1_4__idx33 = 0, $agvsp_0 = 0, $agssp_0 = 0, $agerrstatus_0 = 0, $agstate_0 = 0, $incdec_ptr = 0, $agstacksize_0 = 0, $agvsp_1 = 0, $agvs_0 = 0, $agssp_1 = 0, $agss_0 = 0, $agerrstatus_1 = 0, $agstate_1 = 0, $conv = 0, $add_ptr_sum = 0, $add_ptr2 = 0, $cmp = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $sub_ptr_div = 0, $add = 0, $cmp4 = 0, $mul = 0, $cmp7 = 0, $_mul = 0, $mul11 = 0, $add12 = 0, $call = 0, $tobool = 0, $0 = 0, $agss_alloc = 0, $1 = 0, $mul15 = 0, $mul17 = 0, $add18 = 0, $div = 0, $agvs_alloc = 0, $2 = 0, $3 = 0, $mul22 = 0, $cmp30 = 0, $add_ptr35 = 0, $add_ptr37 = 0, $add_ptr38_sum = 0, $cmp40 = 0, $agstacksize_2 = 0, $agvsp_2 = 0, $agvs_1 = 0, $agssp_2 = 0, $agss_1 = 0, $cmp45 = 0, $arrayidx = 0, $4 = 0, $conv49 = 0, $cmp50 = 0, $5 = 0, $cmp54 = 0, $call57 = 0, $6 = 0, $cmp59 = 0, $cmp62 = 0, $arrayidx64 = 0, $7 = 0, $conv65 = 0, $agtoken_2 = 0, $add67 = 0, $8 = 0, $arrayidx73 = 0, $9 = 0, $conv74 = 0, $cmp75 = 0, $arrayidx79 = 0, $10 = 0, $conv80 = 0, $cmp81 = 0, $cmp84 = 0, $sub = 0, $tobool92 = 0, $dec = 0, $agerrstatus_1_dec = 0, $incdec_ptr95 = 0, $11 = 0, $$etemp$0 = 0, $ld$1$0 = 0, $12$0 = 0, $ld$2$1 = 0, $12$1 = 0, $st$3$0 = 0, $st$4$1 = 0, $arrayidx96 = 0, $13 = 0, $conv97 = 0, $cmp98 = 0, $agn_0 = 0, $arrayidx102 = 0, $14 = 0, $conv103 = 0, $sub104 = 0, $agval_sroa_0_0__idx20 = 0, $agval_sroa_0_0_copyload21 = 0, $agval_sroa_1_4__idx31 = 0, $agval_sroa_1_4_copyload32 = 0, $str = 0, $15 = 0, $16 = 0, $17 = 0, $tobool111 = 0, $18 = 0, $str117 = 0, $19 = 0, $20 = 0, $proto = 0, $21 = 0, $n = 0, $22 = 0, $23 = 0, $proto128 = 0, $24 = 0, $e = 0, $25 = 0, $str131 = 0, $26 = 0, $str133 = 0, $27 = 0, $28 = 0, $29 = 0, $str140 = 0, $30 = 0, $31 = 0, $arrayidx148 = 0, $n149 = 0, $32 = 0, $33 = 0, $34 = 0, $str153 = 0, $35 = 0, $call154 = 0, $36 = 0, $37 = 0, $str160 = 0, $38 = 0, $str163 = 0, $39 = 0, $str165 = 0, $40 = 0, $call166 = 0, $41 = 0, $42 = 0, $obj174 = 0, $43 = 0, $44 = 0, $port178 = 0, $45 = 0, $obj181 = 0, $46 = 0, $subg = 0, $47 = 0, $proto183 = 0, $48 = 0, $e184 = 0, $49 = 0, $obj188 = 0, $50 = 0, $subg190 = 0, $51 = 0, $proto191 = 0, $52 = 0, $e192 = 0, $53 = 0, $obj196 = 0, $obj199 = 0, $obj202 = 0, $obj205 = 0, $agval_sroa_0_0_copyload29 = 0, $agval_sroa_1_4_copyload40 = 0, $agval_sroa_0_0_copyload27 = 0, $agval_sroa_1_4_copyload38 = 0, $agval_sroa_0_0_copyload25 = 0, $agval_sroa_1_4_copyload36 = 0, $agval_sroa_0_0_copyload23 = 0, $agval_sroa_1_4_copyload34 = 0, $54 = 0, $str223 = 0, $55 = 0, $56 = 0, $call224 = 0, $tobool225 = 0, $57 = 0, $58 = 0, $59 = 0, $60 = 0, $61 = 0, $call230 = 0, $subg221_0_in = 0, $subg221_0 = 0, $62 = 0, $str236 = 0, $63 = 0, $str240 = 0, $64 = 0, $str244 = 0, $65 = 0, $str248 = 0, $66 = 0, $str250 = 0, $67 = 0, $call251 = 0, $68 = 0, $69 = 0, $agval_sroa_1_0 = 0, $agval_sroa_0_0 = 0, $idx_neg = 0, $add_ptr259 = 0, $add_ptr257_sum = 0, $incdec_ptr260 = 0, $agval_sroa_0_0__idx = 0, $agval_sroa_1_4__idx30 = 0, $arrayidx261 = 0, $70 = 0, $conv262 = 0, $sub263 = 0, $arrayidx264 = 0, $71 = 0, $conv265 = 0, $72 = 0, $conv266 = 0, $add267 = 0, $73 = 0, $arrayidx273 = 0, $74 = 0, $conv274 = 0, $cmp276 = 0, $arrayidx279 = 0, $75 = 0, $conv280 = 0, $arrayidx283 = 0, $76 = 0, $conv284 = 0, $77 = 0, $inc = 0, $78 = 0, $cmp292 = 0, $cmp295 = 0, $agvsp_3 = 0, $agssp_3 = 0, $agstate_2 = 0, $arrayidx307 = 0, $79 = 0, $cmp309 = 0, $conv308 = 0, $add312 = 0, $80 = 0, $arrayidx319 = 0, $81 = 0, $cmp321 = 0, $arrayidx324 = 0, $82 = 0, $cmp326 = 0, $cmp332 = 0, $add_ptr338 = 0, $add_ptr339 = 0, $83 = 0, $conv340 = 0, $conv325 = 0, $incdec_ptr341 = 0, $84 = 0, $$etemp$5 = 0, $ld$6$0 = 0, $85$0 = 0, $ld$7$1 = 0, $85$1 = 0, $st$8$0 = 0, $st$9$1 = 0, $agresult_0 = 0, $agss_3 = 0, $cmp357 = 0, $86 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 2032 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $agssa = __stackBase__ | 0;
+ $agvsa = __stackBase__ + 400 | 0;
+ $tmp = __stackBase__ + 2e3 | 0;
+ $tmp211 = __stackBase__ + 2008 | 0;
+ $tmp215 = __stackBase__ + 2016 | 0;
+ $tmp218 = __stackBase__ + 2024 | 0;
+ $arraydecay = $agssa | 0;
+ $arraydecay1 = $agvsa | 0;
+ HEAP32[22282] = 0;
+ HEAP32[22356] = -2;
+ $agval_sroa_0_0__idx28 = $tmp | 0;
+ $agval_sroa_1_4__idx39 = $tmp + 4 | 0;
+ $agval_sroa_0_0__idx26 = $tmp211 | 0;
+ $agval_sroa_1_4__idx37 = $tmp211 + 4 | 0;
+ $agval_sroa_0_0__idx24 = $tmp215 | 0;
+ $agval_sroa_1_4__idx35 = $tmp215 + 4 | 0;
+ $agval_sroa_0_0__idx22 = $tmp218 | 0;
+ $agval_sroa_1_4__idx33 = $tmp218 + 4 | 0;
+ $agstate_1 = 0;
+ $agerrstatus_1 = 0;
+ $agss_0 = $arraydecay;
+ $agssp_1 = $arraydecay;
+ $agvs_0 = $arraydecay1;
+ $agvsp_1 = $arraydecay1;
+ $agstacksize_0 = 200;
+ label = 4;
+ break;
+ case 3:
+ $incdec_ptr = $agssp_0 + 2 | 0;
+ $agstate_1 = $agstate_0;
+ $agerrstatus_1 = $agerrstatus_0;
+ $agss_0 = $agss_1;
+ $agssp_1 = $incdec_ptr;
+ $agvs_0 = $agvs_1;
+ $agvsp_1 = $agvsp_0;
+ $agstacksize_0 = $agstacksize_2;
+ label = 4;
+ break;
+ case 4:
+ $conv = $agstate_1 & 65535;
+ HEAP16[$agssp_1 >> 1] = $conv;
+ $add_ptr_sum = $agstacksize_0 - 1 | 0;
+ $add_ptr2 = $agss_0 + ($add_ptr_sum << 1) | 0;
+ $cmp = $add_ptr2 >>> 0 > $agssp_1 >>> 0;
+ if ($cmp) {
+ $agss_1 = $agss_0;
+ $agssp_2 = $agssp_1;
+ $agvs_1 = $agvs_0;
+ $agvsp_2 = $agvsp_1;
+ $agstacksize_2 = $agstacksize_0;
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $sub_ptr_lhs_cast = $agssp_1;
+ $sub_ptr_rhs_cast = $agss_0;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $sub_ptr_div = $sub_ptr_sub >> 1;
+ $add = $sub_ptr_div + 1 | 0;
+ $cmp4 = $agstacksize_0 >>> 0 > 9999;
+ if ($cmp4) {
+ label = 92;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $mul = $agstacksize_0 << 1;
+ $cmp7 = $mul >>> 0 > 1e4;
+ $_mul = $cmp7 ? 1e4 : $mul;
+ $mul11 = $_mul * 10 & -1;
+ $add12 = $mul11 + 7 | 0;
+ $call = _malloc($add12) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 92;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $0 = $call;
+ $agss_alloc = $call;
+ $1 = $agss_0;
+ $mul15 = $add << 1;
+ _memcpy($call | 0, $1 | 0, $mul15);
+ $mul17 = $_mul << 1;
+ $add18 = $mul17 + 7 | 0;
+ $div = $add18 >>> 3;
+ $agvs_alloc = $0 + ($div << 3) | 0;
+ $2 = $agvs_alloc;
+ $3 = $agvs_0;
+ $mul22 = $add << 3;
+ _memcpy($2 | 0, $3 | 0, $mul22);
+ $cmp30 = ($agss_0 | 0) == ($arraydecay | 0);
+ if ($cmp30) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _free($1);
+ label = 9;
+ break;
+ case 9:
+ $add_ptr35 = $agss_alloc + ($sub_ptr_div << 1) | 0;
+ $add_ptr37 = $agvs_alloc + ($sub_ptr_div << 3) | 0;
+ $add_ptr38_sum = $_mul - 1 | 0;
+ $cmp40 = ($add_ptr38_sum | 0) > ($sub_ptr_div | 0);
+ if ($cmp40) {
+ $agss_1 = $agss_alloc;
+ $agssp_2 = $add_ptr35;
+ $agvs_1 = $agvs_alloc;
+ $agvsp_2 = $add_ptr37;
+ $agstacksize_2 = $_mul;
+ label = 10;
+ break;
+ } else {
+ $agss_3 = $agss_alloc;
+ $agresult_0 = 1;
+ label = 93;
+ break;
+ }
+ case 10:
+ $cmp45 = ($agstate_1 | 0) == 9;
+ if ($cmp45) {
+ $agss_3 = $agss_1;
+ $agresult_0 = 0;
+ label = 93;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $arrayidx = $agstate_1 + 89032 | 0;
+ $4 = HEAP8[$arrayidx] | 0;
+ $conv49 = $4 << 24 >> 24;
+ $cmp50 = $4 << 24 >> 24 == -68;
+ if ($cmp50) {
+ label = 24;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $5 = HEAP32[22356] | 0;
+ $cmp54 = ($5 | 0) == -2;
+ if ($cmp54) {
+ label = 13;
+ break;
+ } else {
+ $6 = $5;
+ label = 14;
+ break;
+ }
+ case 13:
+ $call57 = _aglex() | 0;
+ HEAP32[22356] = $call57;
+ $6 = $call57;
+ label = 14;
+ break;
+ case 14:
+ $cmp59 = ($6 | 0) < 1;
+ if ($cmp59) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ HEAP32[22356] = 0;
+ $agtoken_2 = 0;
+ label = 18;
+ break;
+ case 16:
+ $cmp62 = $6 >>> 0 < 267;
+ if ($cmp62) {
+ label = 17;
+ break;
+ } else {
+ $agtoken_2 = 2;
+ label = 18;
+ break;
+ }
+ case 17:
+ $arrayidx64 = $6 + 88488 | 0;
+ $7 = HEAP8[$arrayidx64] | 0;
+ $conv65 = $7 & 255;
+ $agtoken_2 = $conv65;
+ label = 18;
+ break;
+ case 18:
+ $add67 = $agtoken_2 + $conv49 | 0;
+ $8 = $add67 >>> 0 > 80;
+ if ($8) {
+ label = 24;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $arrayidx73 = $add67 + 89336 | 0;
+ $9 = HEAP8[$arrayidx73] | 0;
+ $conv74 = $9 << 24 >> 24;
+ $cmp75 = ($conv74 | 0) == ($agtoken_2 | 0);
+ if ($cmp75) {
+ label = 20;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 20:
+ $arrayidx79 = $add67 + 88760 | 0;
+ $10 = HEAP8[$arrayidx79] | 0;
+ $conv80 = $10 << 24 >> 24;
+ $cmp81 = $10 << 24 >> 24 < 1;
+ if ($cmp81) {
+ label = 21;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 21:
+ $cmp84 = $10 << 24 >> 24 == 0;
+ if ($cmp84) {
+ label = 80;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $sub = -$conv80 | 0;
+ $agn_0 = $sub;
+ label = 25;
+ break;
+ case 23:
+ $tobool92 = ($agerrstatus_1 | 0) == 0;
+ $dec = $agerrstatus_1 - 1 | 0;
+ $agerrstatus_1_dec = $tobool92 ? 0 : $dec;
+ HEAP32[22356] = -2;
+ $incdec_ptr95 = $agvsp_2 + 8 | 0;
+ $11 = $incdec_ptr95;
+ $$etemp$0 = 89144;
+ $ld$1$0 = $$etemp$0 | 0;
+ $12$0 = HEAP32[$ld$1$0 >> 2] | 0;
+ $ld$2$1 = $$etemp$0 + 4 | 0;
+ $12$1 = HEAP32[$ld$2$1 >> 2] | 0;
+ $st$3$0 = $11 | 0;
+ HEAP32[$st$3$0 >> 2] = $12$0;
+ $st$4$1 = $11 + 4 | 0;
+ HEAP32[$st$4$1 >> 2] = $12$1;
+ $agstate_0 = $conv80;
+ $agerrstatus_0 = $agerrstatus_1_dec;
+ $agssp_0 = $agssp_2;
+ $agvsp_0 = $incdec_ptr95;
+ label = 3;
+ break;
+ case 24:
+ $arrayidx96 = $agstate_1 + 89240 | 0;
+ $13 = HEAP8[$arrayidx96] | 0;
+ $conv97 = $13 & 255;
+ $cmp98 = $13 << 24 >> 24 == 0;
+ if ($cmp98) {
+ label = 80;
+ break;
+ } else {
+ $agn_0 = $conv97;
+ label = 25;
+ break;
+ }
+ case 25:
+ $arrayidx102 = $agn_0 + 88848 | 0;
+ $14 = HEAP8[$arrayidx102] | 0;
+ $conv103 = $14 & 255;
+ $sub104 = 1 - $conv103 | 0;
+ $agval_sroa_0_0__idx20 = $agvsp_2 + ($sub104 << 3) | 0;
+ $agval_sroa_0_0_copyload21 = HEAP32[$agval_sroa_0_0__idx20 >> 2] | 0;
+ $agval_sroa_1_4__idx31 = $agvsp_2 + ($sub104 << 3) + 4 | 0;
+ $agval_sroa_1_4_copyload32 = HEAP32[$agval_sroa_1_4__idx31 >> 2] | 0;
+ if (($agn_0 | 0) == 2) {
+ label = 26;
+ break;
+ } else if (($agn_0 | 0) == 3) {
+ label = 27;
+ break;
+ } else if (($agn_0 | 0) == 4) {
+ label = 28;
+ break;
+ } else if (($agn_0 | 0) == 5) {
+ label = 31;
+ break;
+ } else if (($agn_0 | 0) == 6) {
+ label = 32;
+ break;
+ } else if (($agn_0 | 0) == 7) {
+ label = 33;
+ break;
+ } else if (($agn_0 | 0) == 8) {
+ label = 34;
+ break;
+ } else if (($agn_0 | 0) == 9) {
+ label = 35;
+ break;
+ } else if (($agn_0 | 0) == 10) {
+ label = 36;
+ break;
+ } else if (($agn_0 | 0) == 11) {
+ label = 37;
+ break;
+ } else if (($agn_0 | 0) == 12) {
+ label = 38;
+ break;
+ } else if (($agn_0 | 0) == 13) {
+ label = 39;
+ break;
+ } else if (($agn_0 | 0) == 14) {
+ label = 40;
+ break;
+ } else if (($agn_0 | 0) == 23) {
+ label = 41;
+ break;
+ } else if (($agn_0 | 0) == 25) {
+ label = 42;
+ break;
+ } else if (($agn_0 | 0) == 32) {
+ label = 43;
+ break;
+ } else if (($agn_0 | 0) == 37) {
+ label = 44;
+ break;
+ } else if (($agn_0 | 0) == 38) {
+ label = 45;
+ break;
+ } else if (($agn_0 | 0) == 39) {
+ label = 46;
+ break;
+ } else if (($agn_0 | 0) == 40) {
+ label = 47;
+ break;
+ } else if (($agn_0 | 0) == 42) {
+ label = 48;
+ break;
+ } else if (($agn_0 | 0) == 43) {
+ label = 49;
+ break;
+ } else if (($agn_0 | 0) == 44) {
+ label = 50;
+ break;
+ } else if (($agn_0 | 0) == 45) {
+ label = 51;
+ break;
+ } else if (($agn_0 | 0) == 46) {
+ label = 52;
+ break;
+ } else if (($agn_0 | 0) == 47) {
+ label = 53;
+ break;
+ } else if (($agn_0 | 0) == 48) {
+ label = 54;
+ break;
+ } else if (($agn_0 | 0) == 49) {
+ label = 55;
+ break;
+ } else if (($agn_0 | 0) == 50) {
+ label = 56;
+ break;
+ } else if (($agn_0 | 0) == 51) {
+ label = 57;
+ break;
+ } else if (($agn_0 | 0) == 52) {
+ label = 58;
+ break;
+ } else if (($agn_0 | 0) == 53) {
+ label = 59;
+ break;
+ } else if (($agn_0 | 0) == 55) {
+ label = 60;
+ break;
+ } else if (($agn_0 | 0) == 56) {
+ label = 61;
+ break;
+ } else if (($agn_0 | 0) == 58) {
+ label = 62;
+ break;
+ } else if (($agn_0 | 0) == 59) {
+ label = 63;
+ break;
+ } else if (($agn_0 | 0) == 60) {
+ label = 64;
+ break;
+ } else if (($agn_0 | 0) == 61) {
+ label = 65;
+ break;
+ } else if (($agn_0 | 0) == 62) {
+ label = 66;
+ break;
+ } else if (($agn_0 | 0) == 63) {
+ label = 67;
+ break;
+ } else if (($agn_0 | 0) == 64) {
+ label = 68;
+ break;
+ } else if (($agn_0 | 0) == 65) {
+ label = 72;
+ break;
+ } else if (($agn_0 | 0) == 66) {
+ label = 73;
+ break;
+ } else if (($agn_0 | 0) == 67) {
+ label = 74;
+ break;
+ } else if (($agn_0 | 0) == 68) {
+ label = 75;
+ break;
+ } else {
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ }
+ case 26:
+ $str = $agvsp_2 | 0;
+ $15 = HEAP32[$str >> 2] | 0;
+ _begin_graph($15);
+ $16 = HEAP32[$str >> 2] | 0;
+ _agstrfree($16);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 27:
+ HEAP8[168566] = 1;
+ _end_graph();
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 28:
+ $17 = HEAP32[42138] | 0;
+ $tobool111 = ($17 | 0) == 0;
+ if ($tobool111) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $18 = $17;
+ _agclose($18);
+ label = 30;
+ break;
+ case 30:
+ HEAP32[42138] = 0;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 31:
+ HEAP32[42138] = 0;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 32:
+ $str117 = $agvsp_2 | 0;
+ $19 = HEAP32[$str117 >> 2] | 0;
+ $agval_sroa_0_0 = $19;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 33:
+ $agval_sroa_0_0 = 0;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 34:
+ HEAP32[42132] = 0;
+ HEAP32[42139] = 98608;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 35:
+ HEAP32[42132] = 2;
+ HEAP32[42139] = 98608;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 36:
+ HEAP32[42132] = 1;
+ HEAP32[42139] = 138272;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 37:
+ HEAP32[42132] = 3;
+ HEAP32[42139] = 138272;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 38:
+ HEAP32[41982] = 3;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 39:
+ HEAP32[41982] = 1;
+ $20 = HEAP32[41880] | 0;
+ $proto = $20 + 40 | 0;
+ $21 = HEAP32[$proto >> 2] | 0;
+ $n = $21 | 0;
+ $22 = HEAP32[$n >> 2] | 0;
+ HEAP32[41626] = $22;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 40:
+ HEAP32[41982] = 2;
+ $23 = HEAP32[41880] | 0;
+ $proto128 = $23 + 40 | 0;
+ $24 = HEAP32[$proto128 >> 2] | 0;
+ $e = $24 + 4 | 0;
+ $25 = HEAP32[$e >> 2] | 0;
+ HEAP32[41972] = $25;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 41:
+ $str131 = $agvsp_2 - 16 | 0;
+ $26 = HEAP32[$str131 >> 2] | 0;
+ $str133 = $agvsp_2 | 0;
+ $27 = HEAP32[$str133 >> 2] | 0;
+ _attr_set($26, $27);
+ $28 = HEAP32[$str131 >> 2] | 0;
+ _agstrfree($28);
+ $29 = HEAP32[$str133 >> 2] | 0;
+ _agstrfree($29);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 42:
+ $str140 = $agvsp_2 | 0;
+ $30 = HEAP32[$str140 >> 2] | 0;
+ _attr_set($30, 120160);
+ $31 = HEAP32[$str140 >> 2] | 0;
+ _agstrfree($31);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 43:
+ _agerror(114616);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 44:
+ HEAP32[41982] = 3;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 45:
+ HEAP32[41982] = 3;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 46:
+ $arrayidx148 = $agvsp_2 - 8 | 0;
+ $n149 = $arrayidx148;
+ $32 = HEAP32[$n149 >> 2] | 0;
+ $33 = $32 | 0;
+ $34 = HEAP32[41542] | 0;
+ HEAP32[41542] = 0;
+ $agval_sroa_0_0 = $33;
+ $agval_sroa_1_0 = $34;
+ label = 76;
+ break;
+ case 47:
+ $str153 = $agvsp_2 | 0;
+ $35 = HEAP32[$str153 >> 2] | 0;
+ $call154 = _bind_node($35) | 0;
+ $36 = $call154 | 0;
+ $37 = HEAP32[$str153 >> 2] | 0;
+ _agstrfree($37);
+ $agval_sroa_0_0 = $36;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 48:
+ $str160 = $agvsp_2 | 0;
+ $38 = HEAP32[$str160 >> 2] | 0;
+ HEAP32[41542] = $38;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 49:
+ $str163 = $agvsp_2 - 16 | 0;
+ $39 = HEAP32[$str163 >> 2] | 0;
+ $str165 = $agvsp_2 | 0;
+ $40 = HEAP32[$str165 >> 2] | 0;
+ $call166 = _concat3($39, $40) | 0;
+ HEAP32[41542] = $call166;
+ $41 = HEAP32[$str163 >> 2] | 0;
+ _agstrfree($41);
+ $42 = HEAP32[$str165 >> 2] | 0;
+ _agstrfree($42);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 50:
+ HEAP32[41982] = 1;
+ $obj174 = $agvsp_2 | 0;
+ $43 = HEAP32[$obj174 >> 2] | 0;
+ $44 = $43;
+ HEAP32[41626] = $44;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 51:
+ $port178 = $agvsp_2 - 16 + 4 | 0;
+ $45 = HEAP32[$port178 >> 2] | 0;
+ _agstrfree($45);
+ HEAP32[41982] = 3;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 52:
+ $obj181 = $agvsp_2 | 0;
+ _begin_edgestmt($obj181);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 53:
+ $46 = HEAP32[41524] | 0;
+ $subg = $46 | 0;
+ $47 = HEAP32[$subg >> 2] | 0;
+ $proto183 = $47 + 40 | 0;
+ $48 = HEAP32[$proto183 >> 2] | 0;
+ $e184 = $48 + 4 | 0;
+ $49 = HEAP32[$e184 >> 2] | 0;
+ HEAP32[41972] = $49;
+ HEAP32[41982] = 2;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 54:
+ _end_edgestmt();
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 55:
+ $obj188 = $agvsp_2 | 0;
+ _begin_edgestmt($obj188);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 56:
+ $50 = HEAP32[41524] | 0;
+ $subg190 = $50 | 0;
+ $51 = HEAP32[$subg190 >> 2] | 0;
+ $proto191 = $51 + 40 | 0;
+ $52 = HEAP32[$proto191 >> 2] | 0;
+ $e192 = $52 + 4 | 0;
+ $53 = HEAP32[$e192 >> 2] | 0;
+ HEAP32[41972] = $53;
+ HEAP32[41982] = 2;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 57:
+ _end_edgestmt();
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 58:
+ $obj196 = $agvsp_2 | 0;
+ _mid_edgestmt($obj196);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 59:
+ $obj199 = $agvsp_2 | 0;
+ _mid_edgestmt($obj199);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 60:
+ $obj202 = $agvsp_2 | 0;
+ _mid_edgestmt($obj202);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 61:
+ $obj205 = $agvsp_2 | 0;
+ _mid_edgestmt($obj205);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 62:
+ _pop_gobj($tmp);
+ $agval_sroa_0_0_copyload29 = HEAP32[$agval_sroa_0_0__idx28 >> 2] | 0;
+ $agval_sroa_1_4_copyload40 = HEAP32[$agval_sroa_1_4__idx39 >> 2] | 0;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload29;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload40;
+ label = 76;
+ break;
+ case 63:
+ _anonsubg();
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 64:
+ _pop_gobj($tmp211);
+ $agval_sroa_0_0_copyload27 = HEAP32[$agval_sroa_0_0__idx26 >> 2] | 0;
+ $agval_sroa_1_4_copyload38 = HEAP32[$agval_sroa_1_4__idx37 >> 2] | 0;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload27;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload38;
+ label = 76;
+ break;
+ case 65:
+ _anonsubg();
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 66:
+ _pop_gobj($tmp215);
+ $agval_sroa_0_0_copyload25 = HEAP32[$agval_sroa_0_0__idx24 >> 2] | 0;
+ $agval_sroa_1_4_copyload36 = HEAP32[$agval_sroa_1_4__idx35 >> 2] | 0;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload25;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload36;
+ label = 76;
+ break;
+ case 67:
+ _subgraph_warn();
+ _pop_gobj($tmp218);
+ $agval_sroa_0_0_copyload23 = HEAP32[$agval_sroa_0_0__idx22 >> 2] | 0;
+ $agval_sroa_1_4_copyload34 = HEAP32[$agval_sroa_1_4__idx33 >> 2] | 0;
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload23;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload34;
+ label = 76;
+ break;
+ case 68:
+ $54 = HEAP32[42138] | 0;
+ $str223 = $agvsp_2 | 0;
+ $55 = HEAP32[$str223 >> 2] | 0;
+ $56 = $54;
+ $call224 = _agfindsubg($56, $55) | 0;
+ $tobool225 = ($call224 | 0) == 0;
+ $57 = HEAP32[41880] | 0;
+ if ($tobool225) {
+ label = 70;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 69:
+ $58 = $call224 | 0;
+ $59 = $57;
+ _aginsert($59, $58);
+ $subg221_0_in = $call224;
+ label = 71;
+ break;
+ case 70:
+ $60 = HEAP32[$str223 >> 2] | 0;
+ $61 = $57;
+ $call230 = _agsubg($61, $60) | 0;
+ $subg221_0_in = $call230;
+ label = 71;
+ break;
+ case 71:
+ $subg221_0 = $subg221_0_in;
+ _push_subg($subg221_0);
+ HEAP8[166984] = 0;
+ $62 = HEAP32[$str223 >> 2] | 0;
+ _agstrfree($62);
+ $agval_sroa_0_0 = $agval_sroa_0_0_copyload21;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 72:
+ $str236 = $agvsp_2 | 0;
+ $63 = HEAP32[$str236 >> 2] | 0;
+ $agval_sroa_0_0 = $63;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 73:
+ $str240 = $agvsp_2 | 0;
+ $64 = HEAP32[$str240 >> 2] | 0;
+ $agval_sroa_0_0 = $64;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 74:
+ $str244 = $agvsp_2 | 0;
+ $65 = HEAP32[$str244 >> 2] | 0;
+ $agval_sroa_0_0 = $65;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 75:
+ $str248 = $agvsp_2 - 16 | 0;
+ $66 = HEAP32[$str248 >> 2] | 0;
+ $str250 = $agvsp_2 | 0;
+ $67 = HEAP32[$str250 >> 2] | 0;
+ $call251 = _concat($66, $67) | 0;
+ $68 = HEAP32[$str248 >> 2] | 0;
+ _agstrfree($68);
+ $69 = HEAP32[$str250 >> 2] | 0;
+ _agstrfree($69);
+ $agval_sroa_0_0 = $call251;
+ $agval_sroa_1_0 = $agval_sroa_1_4_copyload32;
+ label = 76;
+ break;
+ case 76:
+ $idx_neg = -$conv103 | 0;
+ $add_ptr259 = $agssp_2 + ($idx_neg << 1) | 0;
+ $add_ptr257_sum = 1 - $conv103 | 0;
+ $incdec_ptr260 = $agvsp_2 + ($add_ptr257_sum << 3) | 0;
+ $agval_sroa_0_0__idx = $agvsp_2 + ($add_ptr257_sum << 3) | 0;
+ HEAP32[$agval_sroa_0_0__idx >> 2] = $agval_sroa_0_0;
+ $agval_sroa_1_4__idx30 = $agvsp_2 + ($add_ptr257_sum << 3) + 4 | 0;
+ HEAP32[$agval_sroa_1_4__idx30 >> 2] = $agval_sroa_1_0;
+ $arrayidx261 = $agn_0 + 88920 | 0;
+ $70 = HEAP8[$arrayidx261] | 0;
+ $conv262 = $70 & 255;
+ $sub263 = $conv262 - 21 | 0;
+ $arrayidx264 = $sub263 + 88992 | 0;
+ $71 = HEAP8[$arrayidx264] | 0;
+ $conv265 = $71 << 24 >> 24;
+ $72 = HEAP16[$add_ptr259 >> 1] | 0;
+ $conv266 = $72 << 16 >> 16;
+ $add267 = $conv266 + $conv265 | 0;
+ $73 = $add267 >>> 0 < 81;
+ if ($73) {
+ label = 77;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 77:
+ $arrayidx273 = $add267 + 89336 | 0;
+ $74 = HEAP8[$arrayidx273] | 0;
+ $conv274 = $74 << 24 >> 24;
+ $cmp276 = ($conv274 | 0) == ($conv266 | 0);
+ if ($cmp276) {
+ label = 78;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 78:
+ $arrayidx279 = $add267 + 88760 | 0;
+ $75 = HEAP8[$arrayidx279] | 0;
+ $conv280 = $75 << 24 >> 24;
+ $agstate_0 = $conv280;
+ $agerrstatus_0 = $agerrstatus_1;
+ $agssp_0 = $add_ptr259;
+ $agvsp_0 = $incdec_ptr260;
+ label = 3;
+ break;
+ case 79:
+ $arrayidx283 = $sub263 + 89200 | 0;
+ $76 = HEAP8[$arrayidx283] | 0;
+ $conv284 = $76 << 24 >> 24;
+ $agstate_0 = $conv284;
+ $agerrstatus_0 = $agerrstatus_1;
+ $agssp_0 = $add_ptr259;
+ $agvsp_0 = $incdec_ptr260;
+ label = 3;
+ break;
+ case 80:
+ if (($agerrstatus_1 | 0) == 0) {
+ label = 81;
+ break;
+ } else if (($agerrstatus_1 | 0) == 3) {
+ label = 82;
+ break;
+ } else {
+ $agstate_2 = $agstate_1;
+ $agssp_3 = $agssp_2;
+ $agvsp_3 = $agvsp_2;
+ label = 85;
+ break;
+ }
+ case 81:
+ $77 = HEAP32[22282] | 0;
+ $inc = $77 + 1 | 0;
+ HEAP32[22282] = $inc;
+ _agerror(105728);
+ $agstate_2 = $agstate_1;
+ $agssp_3 = $agssp_2;
+ $agvsp_3 = $agvsp_2;
+ label = 85;
+ break;
+ case 82:
+ $78 = HEAP32[22356] | 0;
+ $cmp292 = ($78 | 0) < 1;
+ if ($cmp292) {
+ label = 83;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 83:
+ $cmp295 = ($78 | 0) == 0;
+ if ($cmp295) {
+ $agss_3 = $agss_1;
+ $agresult_0 = 1;
+ label = 93;
+ break;
+ } else {
+ $agstate_2 = $agstate_1;
+ $agssp_3 = $agssp_2;
+ $agvsp_3 = $agvsp_2;
+ label = 85;
+ break;
+ }
+ case 84:
+ HEAP32[22356] = -2;
+ $agstate_2 = $agstate_1;
+ $agssp_3 = $agssp_2;
+ $agvsp_3 = $agvsp_2;
+ label = 85;
+ break;
+ case 85:
+ $arrayidx307 = $agstate_2 + 89032 | 0;
+ $79 = HEAP8[$arrayidx307] | 0;
+ $cmp309 = $79 << 24 >> 24 == -68;
+ if ($cmp309) {
+ label = 89;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 86:
+ $conv308 = $79 << 24 >> 24;
+ $add312 = $conv308 + 1 | 0;
+ $80 = $add312 >>> 0 < 81;
+ if ($80) {
+ label = 87;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 87:
+ $arrayidx319 = $add312 + 89336 | 0;
+ $81 = HEAP8[$arrayidx319] | 0;
+ $cmp321 = $81 << 24 >> 24 == 1;
+ if ($cmp321) {
+ label = 88;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 88:
+ $arrayidx324 = $add312 + 88760 | 0;
+ $82 = HEAP8[$arrayidx324] | 0;
+ $cmp326 = $82 << 24 >> 24 > 0;
+ if ($cmp326) {
+ label = 91;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 89:
+ $cmp332 = ($agssp_3 | 0) == ($agss_1 | 0);
+ if ($cmp332) {
+ $agss_3 = $agss_1;
+ $agresult_0 = 1;
+ label = 93;
+ break;
+ } else {
+ label = 90;
+ break;
+ }
+ case 90:
+ $add_ptr338 = $agvsp_3 - 8 | 0;
+ $add_ptr339 = $agssp_3 - 2 | 0;
+ $83 = HEAP16[$add_ptr339 >> 1] | 0;
+ $conv340 = $83 << 16 >> 16;
+ $agstate_2 = $conv340;
+ $agssp_3 = $add_ptr339;
+ $agvsp_3 = $add_ptr338;
+ label = 85;
+ break;
+ case 91:
+ $conv325 = $82 << 24 >> 24;
+ $incdec_ptr341 = $agvsp_3 + 8 | 0;
+ $84 = $incdec_ptr341;
+ $$etemp$5 = 89144;
+ $ld$6$0 = $$etemp$5 | 0;
+ $85$0 = HEAP32[$ld$6$0 >> 2] | 0;
+ $ld$7$1 = $$etemp$5 + 4 | 0;
+ $85$1 = HEAP32[$ld$7$1 >> 2] | 0;
+ $st$8$0 = $84 | 0;
+ HEAP32[$st$8$0 >> 2] = $85$0;
+ $st$9$1 = $84 + 4 | 0;
+ HEAP32[$st$9$1 >> 2] = $85$1;
+ $agstate_0 = $conv325;
+ $agerrstatus_0 = 3;
+ $agssp_0 = $agssp_3;
+ $agvsp_0 = $incdec_ptr341;
+ label = 3;
+ break;
+ case 92:
+ _agerror(93720);
+ $agss_3 = $agss_0;
+ $agresult_0 = 2;
+ label = 93;
+ break;
+ case 93:
+ $cmp357 = ($agss_3 | 0) == ($arraydecay | 0);
+ if ($cmp357) {
+ label = 95;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 94:
+ $86 = $agss_3;
+ _free($86);
+ label = 95;
+ break;
+ case 95:
+ STACKTOP = __stackBase__;
+ return $agresult_0 | 0;
+ }
+ return 0;
+}
+function _begin_graph($name) {
+ $name = $name | 0;
+ var $buf = 0, $tobool = 0, $arraydecay = 0, $name_addr_0 = 0, $0 = 0, $call = 0, $1 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $tobool = ($name | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $name_addr_0 = $name;
+ label = 4;
+ break;
+ }
+ case 3:
+ $arraydecay = $buf | 0;
+ _anonname($arraydecay);
+ $name_addr_0 = $arraydecay;
+ label = 4;
+ break;
+ case 4:
+ $0 = HEAP32[42132] | 0;
+ $call = _agopen($name_addr_0, $0) | 0;
+ $1 = $call;
+ HEAP32[42138] = $1;
+ HEAP32[41982] = 3;
+ _push_subg($1);
+ HEAP8[166984] = 1;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _end_graph() {
+ _pop_subg();
+ return;
+}
+function _aghtmlstr($s) {
+ $s = $s | 0;
+ var $0 = 0, $cmp = 0, $cmp1 = 0, $or_cond = 0, $refcnt = 0, $1 = 0, $2 = 0, $_b = 0, $3 = 0, $and = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41354] | 0;
+ $cmp = ($0 | 0) == 0;
+ $cmp1 = ($s | 0) == 0;
+ $or_cond = $cmp | $cmp1;
+ if ($or_cond) {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $refcnt = $s - 4 | 0;
+ $1 = $refcnt;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $_b = HEAP8[167144] | 0;
+ $3 = $_b ? -2147483648 : 0;
+ $and = $3 & $2;
+ $retval_0 = $and;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attr_set($name, $value) {
+ $name = $name | 0;
+ $value = $value | 0;
+ var $_b21 = 0, $0 = 0, $root = 0, $1 = 0, $cmp = 0, $value_ = 0, $defval_0 = 0, $2 = 0, $3 = 0, $proto = 0, $4 = 0, $n = 0, $5 = 0, $6 = 0, $call = 0, $cmp2 = 0, $7 = 0, $call5 = 0, $fixed = 0, $8 = 0, $tobool7 = 0, $_b20 = 0, $ap_0 = 0, $9 = 0, $10 = 0, $index = 0, $11 = 0, $call14 = 0, $12 = 0, $proto16 = 0, $13 = 0, $e = 0, $14 = 0, $15 = 0, $call17 = 0, $cmp18 = 0, $16 = 0, $call21 = 0, $fixed23 = 0, $17 = 0, $tobool25 = 0, $_b19 = 0, $18 = 0, $root30 = 0, $19 = 0, $cmp31 = 0, $ap_1 = 0, $20 = 0, $21 = 0, $index36 = 0, $22 = 0, $call37 = 0, $23 = 0, $24 = 0, $call39 = 0, $cmp40 = 0, $25 = 0, $call43 = 0, $fixed45 = 0, $26 = 0, $tobool47 = 0, $_b = 0, $ap_2 = 0, $27 = 0, $28 = 0, $index54 = 0, $29 = 0, $call55 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $_b21 = HEAP8[166984] | 0;
+ if ($_b21) {
+ label = 3;
+ break;
+ } else {
+ $defval_0 = 136416;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[41880] | 0;
+ $root = $0 + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $cmp = ($1 | 0) == ($0 | 0);
+ $value_ = $cmp ? $value : 136416;
+ $defval_0 = $value_;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[41982] | 0;
+ if (($2 | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($2 | 0) == 2) {
+ label = 10;
+ break;
+ } else if (($2 | 0) == 0 | ($2 | 0) == 3) {
+ label = 16;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 5:
+ $3 = HEAP32[41880] | 0;
+ $proto = $3 + 40 | 0;
+ $4 = HEAP32[$proto >> 2] | 0;
+ $n = $4 | 0;
+ $5 = HEAP32[$n >> 2] | 0;
+ $6 = $5 | 0;
+ $call = _agfindattr($6, $name) | 0;
+ $cmp2 = ($call | 0) == 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $7 = HEAP32[42138] | 0;
+ $call5 = _agnodeattr($7, $name, $defval_0) | 0;
+ $ap_0 = $call5;
+ label = 9;
+ break;
+ case 7:
+ $fixed = $call + 13 | 0;
+ $8 = HEAP8[$fixed] | 0;
+ $tobool7 = $8 << 24 >> 24 == 0;
+ if ($tobool7) {
+ $ap_0 = $call;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $_b20 = HEAP8[166984] | 0;
+ if ($_b20) {
+ label = 21;
+ break;
+ } else {
+ $ap_0 = $call;
+ label = 9;
+ break;
+ }
+ case 9:
+ $9 = HEAP32[41626] | 0;
+ $10 = $9 | 0;
+ $index = $ap_0 + 8 | 0;
+ $11 = HEAP32[$index >> 2] | 0;
+ $call14 = _agxset($10, $11, $value) | 0;
+ label = 21;
+ break;
+ case 10:
+ $12 = HEAP32[41880] | 0;
+ $proto16 = $12 + 40 | 0;
+ $13 = HEAP32[$proto16 >> 2] | 0;
+ $e = $13 + 4 | 0;
+ $14 = HEAP32[$e >> 2] | 0;
+ $15 = $14 | 0;
+ $call17 = _agfindattr($15, $name) | 0;
+ $cmp18 = ($call17 | 0) == 0;
+ if ($cmp18) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $16 = HEAP32[42138] | 0;
+ $call21 = _agedgeattr($16, $name, $defval_0) | 0;
+ $ap_1 = $call21;
+ label = 15;
+ break;
+ case 12:
+ $fixed23 = $call17 + 13 | 0;
+ $17 = HEAP8[$fixed23] | 0;
+ $tobool25 = $17 << 24 >> 24 == 0;
+ if ($tobool25) {
+ $ap_1 = $call17;
+ label = 15;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $_b19 = HEAP8[166984] | 0;
+ if ($_b19) {
+ label = 14;
+ break;
+ } else {
+ $ap_1 = $call17;
+ label = 15;
+ break;
+ }
+ case 14:
+ $18 = HEAP32[41880] | 0;
+ $root30 = $18 + 32 | 0;
+ $19 = HEAP32[$root30 >> 2] | 0;
+ $cmp31 = ($19 | 0) == ($18 | 0);
+ if ($cmp31) {
+ label = 21;
+ break;
+ } else {
+ $ap_1 = $call17;
+ label = 15;
+ break;
+ }
+ case 15:
+ $20 = HEAP32[41972] | 0;
+ $21 = $20 | 0;
+ $index36 = $ap_1 + 8 | 0;
+ $22 = HEAP32[$index36 >> 2] | 0;
+ $call37 = _agxset($21, $22, $value) | 0;
+ label = 21;
+ break;
+ case 16:
+ $23 = HEAP32[41880] | 0;
+ $24 = $23 | 0;
+ $call39 = _agfindattr($24, $name) | 0;
+ $cmp40 = ($call39 | 0) == 0;
+ if ($cmp40) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $25 = HEAP32[42138] | 0;
+ $call43 = _agraphattr($25, $name, $defval_0) | 0;
+ $ap_2 = $call43;
+ label = 20;
+ break;
+ case 18:
+ $fixed45 = $call39 + 13 | 0;
+ $26 = HEAP8[$fixed45] | 0;
+ $tobool47 = $26 << 24 >> 24 == 0;
+ if ($tobool47) {
+ $ap_2 = $call39;
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $_b = HEAP8[166984] | 0;
+ if ($_b) {
+ label = 21;
+ break;
+ } else {
+ $ap_2 = $call39;
+ label = 20;
+ break;
+ }
+ case 20:
+ $27 = HEAP32[41880] | 0;
+ $28 = $27 | 0;
+ $index54 = $ap_2 + 8 | 0;
+ $29 = HEAP32[$index54 >> 2] | 0;
+ $call55 = _agxset($28, $29, $value) | 0;
+ label = 21;
+ break;
+ case 21:
+ return;
+ }
+}
+function _bind_node($name) {
+ $name = $name | 0;
+ var $call = 0;
+ $call = _agnode(HEAP32[41880] | 0, $name) | 0;
+ HEAP8[166984] = 0;
+ return $call | 0;
+}
+function _concat3($s1, $s3) {
+ $s1 = $s1 | 0;
+ $s3 = $s3 | 0;
+ var $buf = 0, $call = 0, $call2 = 0, $add3 = 0, $add4 = 0, $cmp = 0, $arraydecay = 0, $call5 = 0, $sym_0 = 0, $call6 = 0, $strlen = 0, $endptr = 0, $0 = 0, $call8 = 0, $call9 = 0, $arraydecay10 = 0, $cmp11 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $call = _strlen($s1 | 0) | 0;
+ $call2 = _strlen($s3 | 0) | 0;
+ $add3 = $call + 2 | 0;
+ $add4 = $add3 + $call2 | 0;
+ $cmp = ($add4 | 0) < 1025;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $arraydecay = $buf | 0;
+ $sym_0 = $arraydecay;
+ label = 5;
+ break;
+ case 4:
+ $call5 = _malloc($add4) | 0;
+ $sym_0 = $call5;
+ label = 5;
+ break;
+ case 5:
+ $call6 = _strcpy($sym_0 | 0, $s1 | 0) | 0;
+ $strlen = _strlen($sym_0 | 0) | 0;
+ $endptr = $sym_0 + $strlen | 0;
+ $0 = $endptr;
+ tempBigInt = 58;
+ HEAP8[$0] = tempBigInt & 255;
+ tempBigInt = tempBigInt >> 8;
+ HEAP8[$0 + 1 | 0] = tempBigInt & 255;
+ $call8 = _strcat($sym_0 | 0, $s3 | 0) | 0;
+ $call9 = _agstrdup($sym_0) | 0;
+ $arraydecay10 = $buf | 0;
+ $cmp11 = ($sym_0 | 0) == ($arraydecay10 | 0);
+ if ($cmp11) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _free($sym_0);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $call9 | 0;
+ }
+ return 0;
+}
+function _begin_edgestmt($objp) {
+ $objp = $objp | 0;
+ var $call = 0, $3 = 0, $8 = 0, $9 = 0, $10$1 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $objp;
+ $objp = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$objp >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$objp + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ $call = _calloc(1, 20) | 0;
+ HEAP32[$call + 16 >> 2] = HEAP32[41524] | 0;
+ HEAP32[41524] = $call;
+ $3 = _calloc(1, 12) | 0;
+ HEAP32[(HEAP32[41524] | 0) + 8 >> 2] = $3;
+ HEAP32[(HEAP32[41524] | 0) + 4 >> 2] = $3;
+ $8 = $objp;
+ $9 = HEAP32[(HEAP32[41524] | 0) + 4 >> 2] | 0;
+ $10$1 = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$9 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = $10$1;
+ HEAP32[(HEAP32[(HEAP32[41524] | 0) + 4 >> 2] | 0) + 8 >> 2] = 0;
+ HEAP32[(HEAP32[41524] | 0) + 12 >> 2] = HEAP8[166976] | 0;
+ HEAP32[HEAP32[41524] >> 2] = HEAP32[41880] | 0;
+ _agpushproto(HEAP32[41880] | 0);
+ HEAP8[166976] = 1;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _mid_edgestmt($objp) {
+ $objp = $objp | 0;
+ var $0 = 0, $last1 = 0, $8 = 0, $9 = 0, $10$1 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $objp;
+ $objp = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$objp >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$objp + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ $0 = _calloc(1, 12) | 0;
+ HEAP32[(HEAP32[(HEAP32[41524] | 0) + 8 >> 2] | 0) + 8 >> 2] = $0;
+ $last1 = (HEAP32[41524] | 0) + 8 | 0;
+ HEAP32[$last1 >> 2] = HEAP32[(HEAP32[$last1 >> 2] | 0) + 8 >> 2] | 0;
+ $8 = $objp;
+ $9 = HEAP32[(HEAP32[41524] | 0) + 8 >> 2] | 0;
+ $10$1 = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$9 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = $10$1;
+ HEAP32[(HEAP32[(HEAP32[41524] | 0) + 8 >> 2] | 0) + 8 >> 2] = 0;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _pop_gobj($agg_result) {
+ $agg_result = $agg_result | 0;
+ HEAP32[$agg_result >> 2] = _pop_subg() | 0;
+ HEAP32[$agg_result + 4 >> 2] = 0;
+ return;
+}
+function _anonsubg() {
+ var $arraydecay = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ HEAP8[166984] = 0;
+ $arraydecay = __stackBase__ | 0;
+ _anonname($arraydecay);
+ _push_subg(_agsubg(HEAP32[41880] | 0, $arraydecay) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _subgraph_warn() {
+ var $1 = 0, $call = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $1 = HEAP32[(HEAP32[41880] | 0) + 12 >> 2] | 0;
+ $call = _aglinenumber() | 0;
+ _agerr(0, 149672, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $1, HEAP32[tempInt + 8 >> 2] = $call, tempInt) | 0);
+ _agerr(3, 146832, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _agerr(3, 144008, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = HEAP32[(HEAP32[167160 + ((HEAP32[41876] | 0) - 2 << 2) >> 2] | 0) + 12 >> 2] | 0, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _concat($s1, $s2) {
+ $s1 = $s1 | 0;
+ $s2 = $s2 | 0;
+ var $buf = 0, $call = 0, $call1 = 0, $add = 0, $add2 = 0, $cmp = 0, $arraydecay = 0, $call3 = 0, $sym_0 = 0, $call4 = 0, $call5 = 0, $call6 = 0, $arraydecay7 = 0, $cmp8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $call = _strlen($s1 | 0) | 0;
+ $call1 = _strlen($s2 | 0) | 0;
+ $add = $call + 1 | 0;
+ $add2 = $add + $call1 | 0;
+ $cmp = ($add2 | 0) < 1025;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $arraydecay = $buf | 0;
+ $sym_0 = $arraydecay;
+ label = 5;
+ break;
+ case 4:
+ $call3 = _malloc($add2) | 0;
+ $sym_0 = $call3;
+ label = 5;
+ break;
+ case 5:
+ $call4 = _strcpy($sym_0 | 0, $s1 | 0) | 0;
+ $call5 = _strcat($sym_0 | 0, $s2 | 0) | 0;
+ $call6 = _agstrdup($sym_0) | 0;
+ $arraydecay7 = $buf | 0;
+ $cmp8 = ($sym_0 | 0) == ($arraydecay7 | 0);
+ if ($cmp8) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _free($sym_0);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $call6 | 0;
+ }
+ return 0;
+}
+function _anonname($buf) {
+ $buf = $buf | 0;
+ var $0 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $0 = HEAP32[22120] | 0;
+ HEAP32[22120] = $0 + 1 | 0;
+ _sprintf($buf | 0, 140200, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $0, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _agstrdup($s) {
+ $s = $s | 0;
+ var $0 = 0, $cmp = 0, $cmp1 = 0, $add_ptr = 0, $1 = 0, $searchf = 0, $2 = 0, $call = 0, $tobool = 0, $refcnt = 0, $3 = 0, $4 = 0, $inc = 0, $call5 = 0, $add = 0, $call6 = 0, $refcnt7 = 0, $5 = 0, $s8 = 0, $call9 = 0, $6 = 0, $searchf10 = 0, $7 = 0, $call11 = 0, $r_0_in = 0, $8 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41354] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _initialize_strings();
+ label = 4;
+ break;
+ case 4:
+ $cmp1 = ($s | 0) == 0;
+ if ($cmp1) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add_ptr = $s - 12 | 0;
+ $1 = HEAP32[41354] | 0;
+ $searchf = $1 | 0;
+ $2 = HEAP32[$searchf >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$2 & 1023]($1, $add_ptr, 4) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $refcnt = $call + 8 | 0;
+ $3 = $refcnt;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $inc = $4 + 1 | 0;
+ HEAP32[$3 >> 2] = $inc;
+ $r_0_in = $call;
+ label = 8;
+ break;
+ case 7:
+ $call5 = _strlen($s | 0) | 0;
+ $add = $call5 + 16 | 0;
+ $call6 = _malloc($add) | 0;
+ $refcnt7 = $call6 + 8 | 0;
+ $5 = $refcnt7;
+ HEAP32[$5 >> 2] = 1;
+ $s8 = $call6 + 12 | 0;
+ $call9 = _strcpy($s8 | 0, $s | 0) | 0;
+ $6 = HEAP32[41354] | 0;
+ $searchf10 = $6 | 0;
+ $7 = HEAP32[$searchf10 >> 2] | 0;
+ $call11 = FUNCTION_TABLE_iiii[$7 & 1023]($6, $call6, 1) | 0;
+ $r_0_in = $call6;
+ label = 8;
+ break;
+ case 8:
+ $8 = $r_0_in + 12 | 0;
+ $retval_0 = $8;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _initialize_strings() {
+ HEAP32[41354] = _dtopen(166112, HEAP32[41974] | 0) | 0;
+ HEAP8[167144] = 1;
+ HEAP8[168120] = 1;
+ return;
+}
+function _agstrdup_html($s) {
+ $s = $s | 0;
+ var $0 = 0, $cmp = 0, $cmp1 = 0, $add_ptr = 0, $1 = 0, $searchf = 0, $2 = 0, $call = 0, $tobool = 0, $refcnt = 0, $3 = 0, $4 = 0, $inc = 0, $call5 = 0, $add = 0, $call6 = 0, $_b = 0, $or = 0, $refcnt7 = 0, $5 = 0, $s8 = 0, $call9 = 0, $6 = 0, $searchf10 = 0, $7 = 0, $call11 = 0, $r_0_in = 0, $8 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41354] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _initialize_strings();
+ label = 4;
+ break;
+ case 4:
+ $cmp1 = ($s | 0) == 0;
+ if ($cmp1) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add_ptr = $s - 12 | 0;
+ $1 = HEAP32[41354] | 0;
+ $searchf = $1 | 0;
+ $2 = HEAP32[$searchf >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$2 & 1023]($1, $add_ptr, 4) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $refcnt = $call + 8 | 0;
+ $3 = $refcnt;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $inc = $4 + 1 | 0;
+ HEAP32[$3 >> 2] = $inc;
+ $r_0_in = $call;
+ label = 8;
+ break;
+ case 7:
+ $call5 = _strlen($s | 0) | 0;
+ $add = $call5 + 16 | 0;
+ $call6 = _malloc($add) | 0;
+ $_b = HEAP8[167144] | 0;
+ $or = $_b ? -2147483647 : 1;
+ $refcnt7 = $call6 + 8 | 0;
+ $5 = $refcnt7;
+ HEAP32[$5 >> 2] = $or;
+ $s8 = $call6 + 12 | 0;
+ $call9 = _strcpy($s8 | 0, $s | 0) | 0;
+ $6 = HEAP32[41354] | 0;
+ $searchf10 = $6 | 0;
+ $7 = HEAP32[$searchf10 >> 2] | 0;
+ $call11 = FUNCTION_TABLE_iiii[$7 & 1023]($6, $call6, 1) | 0;
+ $r_0_in = $call6;
+ label = 8;
+ break;
+ case 8:
+ $8 = $r_0_in + 12 | 0;
+ $retval_0 = $8;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _agstrfree($s) {
+ $s = $s | 0;
+ var $0 = 0, $cmp = 0, $cmp1 = 0, $or_cond = 0, $add_ptr = 0, $searchf = 0, $1 = 0, $call = 0, $tobool = 0, $refcnt = 0, $2 = 0, $3 = 0, $dec = 0, $tobool4 = 0, $_b = 0, $phitmp7 = 0, $or_cond8 = 0, $4 = 0, $searchf8 = 0, $5 = 0, $call9 = 0, $call11 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41354] | 0;
+ $cmp = ($0 | 0) == 0;
+ $cmp1 = ($s | 0) == 0;
+ $or_cond = $cmp | $cmp1;
+ if ($or_cond) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add_ptr = $s - 12 | 0;
+ $searchf = $0 | 0;
+ $1 = HEAP32[$searchf >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($0, $add_ptr, 4) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $refcnt = $call + 8 | 0;
+ $2 = $refcnt;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $dec = $3 - 1 | 0;
+ HEAP32[$2 >> 2] = $dec;
+ $tobool4 = ($dec | 0) == 0;
+ $_b = HEAP8[168120] | 0;
+ $phitmp7 = $_b ^ 1;
+ $or_cond8 = $tobool4 | $phitmp7;
+ if ($or_cond8) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $4 = HEAP32[41354] | 0;
+ $searchf8 = $4 | 0;
+ $5 = HEAP32[$searchf8 >> 2] | 0;
+ $call9 = FUNCTION_TABLE_iiii[$5 & 1023]($4, $call, 2) | 0;
+ _free($call);
+ label = 7;
+ break;
+ case 6:
+ $call11 = _agerr(1, 91240, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $s, tempInt) | 0) | 0;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _reverse_edge($e) {
+ $e = $e | 0;
+ var $head = 0, $0 = 0, $tail = 0, $1 = 0, $call = 0, $tobool = 0, $call3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _delete_fast_edge($e);
+ $head = $e + 12 | 0;
+ $0 = HEAP32[$head >> 2] | 0;
+ $tail = $e + 16 | 0;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $call = _find_fast_edge($0, $1) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _merge_oneway($e, $call);
+ label = 5;
+ break;
+ case 4:
+ $call3 = _virtual_edge($0, $1, $e) | 0;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _acyclic($g) {
+ $g = $g | 0;
+ var $size = 0, $0 = 0, $cmp17 = 0, $list = 0, $nlist = 0, $c_018 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $tobool12 = 0, $n_013 = 0, $mark = 0, $next = 0, $3 = 0, $tobool = 0, $n_114_pr = 0, $tobool1315 = 0, $n_116 = 0, $next17 = 0, $n_1 = 0, $tobool13 = 0, $inc = 0, $4 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $g + 232 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp17 = ($0 | 0) > 0;
+ if ($cmp17) {
+ label = 3;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $list = $g + 228 | 0;
+ $nlist = $g + 220 | 0;
+ $c_018 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($c_018 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ HEAP32[$nlist >> 2] = $2;
+ $tobool12 = ($2 | 0) == 0;
+ if ($tobool12) {
+ label = 8;
+ break;
+ } else {
+ $n_013 = $2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $mark = $n_013 + 163 | 0;
+ HEAP8[$mark] = 0;
+ $next = $n_013 + 168 | 0;
+ $3 = HEAP32[$next >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_013 = $3;
+ label = 5;
+ break;
+ }
+ case 6:
+ $n_114_pr = HEAP32[$nlist >> 2] | 0;
+ $tobool1315 = ($n_114_pr | 0) == 0;
+ if ($tobool1315) {
+ label = 8;
+ break;
+ } else {
+ $n_116 = $n_114_pr;
+ label = 7;
+ break;
+ }
+ case 7:
+ _dfs($n_116);
+ $next17 = $n_116 + 168 | 0;
+ $n_1 = HEAP32[$next17 >> 2] | 0;
+ $tobool13 = ($n_1 | 0) == 0;
+ if ($tobool13) {
+ label = 8;
+ break;
+ } else {
+ $n_116 = $n_1;
+ label = 7;
+ break;
+ }
+ case 8:
+ $inc = $c_018 + 1 | 0;
+ $4 = HEAP32[$size >> 2] | 0;
+ $cmp = ($inc | 0) < ($4 | 0);
+ if ($cmp) {
+ $c_018 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _dfs($n) {
+ $n = $n | 0;
+ var $mark = 0, $0 = 0, $tobool = 0, $onstack = 0, $list = 0, $1 = 0, $2 = 0, $tobool510 = 0, $3 = 0, $i_011 = 0, $head = 0, $4 = 0, $onstack7 = 0, $5 = 0, $tobool8 = 0, $dec = 0, $mark11 = 0, $6 = 0, $cmp = 0, $i_1 = 0, $inc = 0, $7 = 0, $arrayidx = 0, $8 = 0, $tobool5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $mark = $n + 163 | 0;
+ $0 = HEAP8[$mark] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ HEAP8[$mark] = 1;
+ $onstack = $n + 164 | 0;
+ HEAP8[$onstack] = 1;
+ $list = $n + 184 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool510 = ($2 | 0) == 0;
+ if ($tobool510) {
+ label = 9;
+ break;
+ } else {
+ $i_011 = 0;
+ $3 = $2;
+ label = 4;
+ break;
+ }
+ case 4:
+ $head = $3 + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ $onstack7 = $4 + 164 | 0;
+ $5 = HEAP8[$onstack7] | 0;
+ $tobool8 = $5 << 24 >> 24 == 0;
+ if ($tobool8) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _reverse_edge($3);
+ $dec = $i_011 - 1 | 0;
+ $i_1 = $dec;
+ label = 8;
+ break;
+ case 6:
+ $mark11 = $4 + 163 | 0;
+ $6 = HEAP8[$mark11] | 0;
+ $cmp = $6 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ $i_1 = $i_011;
+ label = 8;
+ break;
+ }
+ case 7:
+ _dfs($4);
+ $i_1 = $i_011;
+ label = 8;
+ break;
+ case 8:
+ $inc = $i_1 + 1 | 0;
+ $7 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $7 + ($inc << 2) | 0;
+ $8 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool5 = ($8 | 0) == 0;
+ if ($tobool5) {
+ label = 9;
+ break;
+ } else {
+ $i_011 = $inc;
+ $3 = $8;
+ label = 4;
+ break;
+ }
+ case 9:
+ HEAP8[$onstack] = 0;
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _countDummyNodes($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool15 = 0, $n_0_in17 = 0, $count_016 = 0, $call1 = 0, $tobool312 = 0, $e_0_in14 = 0, $count_113 = 0, $head = 0, $1 = 0, $rank = 0, $2 = 0, $3 = 0, $tail = 0, $4 = 0, $rank6 = 0, $5 = 0, $6 = 0, $cmp = 0, $sub = 0, $ispos = 0, $neg = 0, $call13 = 0, $sub14 = 0, $add = 0, $count_2 = 0, $call15 = 0, $tobool3 = 0, $count_1_lcssa = 0, $call17 = 0, $tobool = 0, $count_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool15 = ($call | 0) == 0;
+ if ($tobool15) {
+ $count_0_lcssa = 0;
+ label = 8;
+ break;
+ } else {
+ $count_016 = 0;
+ $n_0_in17 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agfstout($0, $n_0_in17) | 0;
+ $tobool312 = ($call1 | 0) == 0;
+ if ($tobool312) {
+ $count_1_lcssa = $count_016;
+ label = 7;
+ break;
+ } else {
+ $count_113 = $count_016;
+ $e_0_in14 = $call1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $head = $e_0_in14 + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $rank = $1 + 236 | 0;
+ $2 = $rank;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tail = $e_0_in14 + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $rank6 = $4 + 236 | 0;
+ $5 = $rank6;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $cmp = ($3 | 0) == ($6 | 0);
+ if ($cmp) {
+ $count_2 = $count_113;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $sub = $3 - $6 | 0;
+ $ispos = ($sub | 0) > -1;
+ $neg = -$sub | 0;
+ $call13 = $ispos ? $sub : $neg;
+ $sub14 = $count_113 - 1 | 0;
+ $add = $sub14 + $call13 | 0;
+ $count_2 = $add;
+ label = 6;
+ break;
+ case 6:
+ $call15 = _agnxtout($0, $e_0_in14) | 0;
+ $tobool3 = ($call15 | 0) == 0;
+ if ($tobool3) {
+ $count_1_lcssa = $count_2;
+ label = 7;
+ break;
+ } else {
+ $count_113 = $count_2;
+ $e_0_in14 = $call15;
+ label = 4;
+ break;
+ }
+ case 7:
+ $call17 = _agnxtnode($0, $n_0_in17) | 0;
+ $tobool = ($call17 | 0) == 0;
+ if ($tobool) {
+ $count_0_lcssa = $count_1_lcssa;
+ label = 8;
+ break;
+ } else {
+ $count_016 = $count_1_lcssa;
+ $n_0_in17 = $call17;
+ label = 3;
+ break;
+ }
+ case 8:
+ return $count_0_lcssa | 0;
+ }
+ return 0;
+}
+function _initEdgeTypes($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool10 = 0, $n_0_in11 = 0, $size = 0, $1 = 0, $2 = 0, $cmp8 = 0, $in = 0, $lc_09 = 0, $list7 = 0, $3 = 0, $arrayidx = 0, $4 = 0, $edge_type = 0, $inc = 0, $5 = 0, $cmp = 0, $call7 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool10 = ($call | 0) == 0;
+ if ($tobool10) {
+ label = 7;
+ break;
+ } else {
+ $n_0_in11 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $size = $n_0_in11 + 180 | 0;
+ $1 = $size;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $cmp8 = ($2 | 0) > 0;
+ if ($cmp8) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $in = $n_0_in11 + 176 | 0;
+ $lc_09 = 0;
+ label = 5;
+ break;
+ case 5:
+ $list7 = HEAP32[$in >> 2] | 0;
+ $3 = $list7;
+ $arrayidx = $3 + ($lc_09 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $edge_type = $4 + 128 | 0;
+ HEAP8[$edge_type] = 0;
+ $inc = $lc_09 + 1 | 0;
+ $5 = HEAP32[$1 >> 2] | 0;
+ $cmp = ($inc | 0) < ($5 | 0);
+ if ($cmp) {
+ $lc_09 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call7 = _agnxtnode($0, $n_0_in11) | 0;
+ $tobool = ($call7 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $n_0_in11 = $call7;
+ label = 3;
+ break;
+ }
+ case 7:
+ return;
+ }
+}
+function _end_edgestmt() {
+ var $0 = 0, $list = 0, $tailptr_045 = 0, $link46 = 0, $1 = 0, $tobool47 = 0, $tailptr_0 = 0, $link = 0, $2 = 0, $tobool = 0, $3 = 0, $link49 = 0, $tailptr_048 = 0, $port = 0, $4 = 0, $port3 = 0, $5 = 0, $obj = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $_mask36 = 0, $cmp = 0, $10 = 0, $call = 0, $t_first_0 = 0, $t_graph_0 = 0, $obj10 = 0, $11 = 0, $12 = 0, $13 = 0, $14 = 0, $_mask37 = 0, $cmp13 = 0, $15 = 0, $call20 = 0, $h_first_0 = 0, $h_graph_0 = 0, $tobool2342 = 0, $tobool2640 = 0, $tobool54 = 0, $tobool51 = 0, $t_node_043 = 0, $h_node_041 = 0, $16 = 0, $call28 = 0, $tobool29 = 0, $tail = 0, $17 = 0, $head = 0, $18 = 0, $cmp31 = 0, $cmp33 = 0, $or_cond = 0, $tp_0 = 0, $hp_0 = 0, $tobool36 = 0, $19 = 0, $tobool38 = 0, $20 = 0, $call40 = 0, $tobool42 = 0, $21 = 0, $tobool46 = 0, $22 = 0, $call48 = 0, $call52 = 0, $tobool26 = 0, $call56 = 0, $tobool23 = 0, $23 = 0, $list64 = 0, $24 = 0, $tobool6538 = 0, $tailptr_139 = 0, $link66 = 0, $25 = 0, $obj68 = 0, $26 = 0, $27 = 0, $28 = 0, $_mask = 0, $cmp71 = 0, $29 = 0, $tobool65 = 0, $30 = 0, $31 = 0, $subg = 0, $32 = 0, $cmp75 = 0, $33 = 0, $34 = 0, $in_edge_stmt = 0, $35 = 0, $conv79 = 0, $link80 = 0, $36 = 0, $37 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41524] | 0;
+ $list = $0 + 4 | 0;
+ $tailptr_045 = HEAP32[$list >> 2] | 0;
+ $link46 = $tailptr_045 + 8 | 0;
+ $1 = HEAP32[$link46 >> 2] | 0;
+ $tobool47 = ($1 | 0) == 0;
+ if ($tobool47) {
+ label = 24;
+ break;
+ } else {
+ $tailptr_048 = $tailptr_045;
+ $link49 = $link46;
+ $3 = $1;
+ label = 4;
+ break;
+ }
+ case 3:
+ $tailptr_0 = HEAP32[$link49 >> 2] | 0;
+ $link = $tailptr_0 + 8 | 0;
+ $2 = HEAP32[$link >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 24;
+ break;
+ } else {
+ $tailptr_048 = $tailptr_0;
+ $link49 = $link;
+ $3 = $2;
+ label = 4;
+ break;
+ }
+ case 4:
+ $port = $tailptr_048 + 4 | 0;
+ $4 = HEAP32[$port >> 2] | 0;
+ $port3 = $3 + 4 | 0;
+ $5 = HEAP32[$port3 >> 2] | 0;
+ $obj = $tailptr_048 | 0;
+ $6 = HEAP32[$obj >> 2] | 0;
+ $7 = $6;
+ $8 = $6;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $_mask36 = $9 & 15;
+ $cmp = ($_mask36 | 0) == 1;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $10 = $6;
+ $t_graph_0 = 0;
+ $t_first_0 = $10;
+ label = 7;
+ break;
+ case 6:
+ $call = _agfstnode($7) | 0;
+ $t_graph_0 = $7;
+ $t_first_0 = $call;
+ label = 7;
+ break;
+ case 7:
+ $obj10 = $3 | 0;
+ $11 = HEAP32[$obj10 >> 2] | 0;
+ $12 = $11;
+ $13 = $11;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $_mask37 = $14 & 15;
+ $cmp13 = ($_mask37 | 0) == 1;
+ if ($cmp13) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $15 = $11;
+ $h_graph_0 = 0;
+ $h_first_0 = $15;
+ label = 10;
+ break;
+ case 9:
+ $call20 = _agfstnode($12) | 0;
+ $h_graph_0 = $12;
+ $h_first_0 = $call20;
+ label = 10;
+ break;
+ case 10:
+ $tobool2342 = ($t_first_0 | 0) == 0;
+ if ($tobool2342) {
+ label = 3;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $tobool2640 = ($h_first_0 | 0) == 0;
+ $tobool54 = ($t_graph_0 | 0) == 0;
+ $tobool51 = ($h_graph_0 | 0) == 0;
+ $t_node_043 = $t_first_0;
+ label = 12;
+ break;
+ case 12:
+ if ($tobool2640) {
+ label = 22;
+ break;
+ } else {
+ $h_node_041 = $h_first_0;
+ label = 13;
+ break;
+ }
+ case 13:
+ $16 = HEAP32[41880] | 0;
+ $call28 = _agedge($16, $t_node_043, $h_node_041) | 0;
+ $tobool29 = ($call28 | 0) == 0;
+ if ($tobool29) {
+ label = 20;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $tail = $call28 + 16 | 0;
+ $17 = HEAP32[$tail >> 2] | 0;
+ $head = $call28 + 12 | 0;
+ $18 = HEAP32[$head >> 2] | 0;
+ $cmp31 = ($17 | 0) != ($18 | 0);
+ $cmp33 = ($18 | 0) == ($t_node_043 | 0);
+ $or_cond = $cmp31 & $cmp33;
+ $tp_0 = $or_cond ? $5 : $4;
+ $hp_0 = $or_cond ? $4 : $5;
+ $tobool36 = ($tp_0 | 0) == 0;
+ if ($tobool36) {
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $19 = HEAP8[$tp_0] | 0;
+ $tobool38 = $19 << 24 >> 24 == 0;
+ if ($tobool38) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $20 = $call28 | 0;
+ $call40 = _agxset($20, 1, $tp_0) | 0;
+ _agstrfree($tp_0);
+ label = 17;
+ break;
+ case 17:
+ $tobool42 = ($hp_0 | 0) == 0;
+ if ($tobool42) {
+ label = 20;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $21 = HEAP8[$hp_0] | 0;
+ $tobool46 = $21 << 24 >> 24 == 0;
+ if ($tobool46) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $22 = $call28 | 0;
+ $call48 = _agxset($22, 2, $hp_0) | 0;
+ _agstrfree($hp_0);
+ label = 20;
+ break;
+ case 20:
+ if ($tobool51) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $call52 = _agnxtnode($h_graph_0, $h_node_041) | 0;
+ $tobool26 = ($call52 | 0) == 0;
+ if ($tobool26) {
+ label = 22;
+ break;
+ } else {
+ $h_node_041 = $call52;
+ label = 13;
+ break;
+ }
+ case 22:
+ if ($tobool54) {
+ label = 3;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $call56 = _agnxtnode($t_graph_0, $t_node_043) | 0;
+ $tobool23 = ($call56 | 0) == 0;
+ if ($tobool23) {
+ label = 3;
+ break;
+ } else {
+ $t_node_043 = $call56;
+ label = 12;
+ break;
+ }
+ case 24:
+ $23 = HEAP32[41524] | 0;
+ $list64 = $23 + 4 | 0;
+ $24 = HEAP32[$list64 >> 2] | 0;
+ $tobool6538 = ($24 | 0) == 0;
+ if ($tobool6538) {
+ label = 28;
+ break;
+ } else {
+ $tailptr_139 = $24;
+ label = 25;
+ break;
+ }
+ case 25:
+ $link66 = $tailptr_139 + 8 | 0;
+ $25 = HEAP32[$link66 >> 2] | 0;
+ $obj68 = $tailptr_139 | 0;
+ $26 = HEAP32[$obj68 >> 2] | 0;
+ $27 = $26;
+ $28 = HEAP32[$27 >> 2] | 0;
+ $_mask = $28 & 15;
+ $cmp71 = ($_mask | 0) == 1;
+ if ($cmp71) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $29 = $tailptr_139;
+ _free($29);
+ label = 27;
+ break;
+ case 27:
+ $tobool65 = ($25 | 0) == 0;
+ if ($tobool65) {
+ label = 28;
+ break;
+ } else {
+ $tailptr_139 = $25;
+ label = 25;
+ break;
+ }
+ case 28:
+ $30 = HEAP32[41880] | 0;
+ $31 = HEAP32[41524] | 0;
+ $subg = $31 | 0;
+ $32 = HEAP32[$subg >> 2] | 0;
+ $cmp75 = ($30 | 0) == ($32 | 0);
+ if ($cmp75) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ _abort();
+ case 30:
+ $33 = $30;
+ _agpopproto($33);
+ $34 = HEAP32[41524] | 0;
+ $in_edge_stmt = $34 + 12 | 0;
+ $35 = HEAP32[$in_edge_stmt >> 2] | 0;
+ $conv79 = $35 & 255;
+ HEAP8[166976] = $conv79;
+ $link80 = $34 + 16 | 0;
+ $36 = HEAP32[$link80 >> 2] | 0;
+ HEAP32[41524] = $36;
+ HEAP8[166984] = 0;
+ $37 = $34;
+ _free($37);
+ HEAP32[41982] = 3;
+ return;
+ }
+}
+function _push_subg($g) {
+ $g = $g | 0;
+ var $0 = 0, $cmp = 0, $call = 0, $inc = 0, $arrayidx = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41876] | 0;
+ $cmp = ($0 | 0) > 63;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _agerr(1, 153272, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _exit(1);
+ case 4:
+ $inc = $0 + 1 | 0;
+ HEAP32[41876] = $inc;
+ $arrayidx = 167160 + ($0 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $g;
+ HEAP32[41880] = $g;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pop_subg() {
+ var $0 = 0, $cmp = 0, $call = 0, $dec = 0, $arrayidx = 0, $1 = 0, $cmp1 = 0, $sub = 0, $arrayidx3 = 0, $2 = 0, $storemerge = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41876] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _agerr(1, 137472, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ _exit(1);
+ return 0;
+ case 4:
+ $dec = $0 - 1 | 0;
+ HEAP32[41876] = $dec;
+ $arrayidx = 167160 + ($dec << 2) | 0;
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp1 = ($dec | 0) > 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ $storemerge = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $sub = $0 - 2 | 0;
+ $arrayidx3 = 167160 + ($sub << 2) | 0;
+ $2 = HEAP32[$arrayidx3 >> 2] | 0;
+ $storemerge = $2;
+ label = 6;
+ break;
+ case 6:
+ HEAP32[41880] = $storemerge;
+ STACKTOP = __stackBase__;
+ return $1 | 0;
+ }
+ return 0;
+}
+function _zapLayers() {
+ var $0 = 0, $cmp6 = 0, $i_09 = 0, $count_08 = 0, $start_07 = 0, $1 = 0, $arrayidx = 0, $nNodeGroupsInLayer = 0, $2 = 0, $cmp1 = 0, $cmp2 = 0, $layerNumber = 0, $3 = 0, $start_1 = 0, $inc = 0, $layerNumber6 = 0, $4 = 0, $cmp7 = 0, $5 = 0, $nNodeGroupsInLayer113 = 0, $6 = 0, $cmp124 = 0, $7 = 0, $j_05 = 0, $nodeGroupsInLayer = 0, $8 = 0, $arrayidx15 = 0, $9 = 0, $nNodes = 0, $10 = 0, $cmp171 = 0, $nodes = 0, $q_02 = 0, $11 = 0, $arrayidx19 = 0, $12 = 0, $rank = 0, $13 = 0, $sub = 0, $inc20 = 0, $14 = 0, $cmp17 = 0, $inc22 = 0, $15 = 0, $nNodeGroupsInLayer11 = 0, $16 = 0, $cmp12 = 0, $start_2 = 0, $count_1 = 0, $inc27 = 0, $17 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[2800] | 0;
+ $cmp6 = ($0 | 0) > 0;
+ if ($cmp6) {
+ $start_07 = 0;
+ $count_08 = 0;
+ $i_09 = 0;
+ label = 3;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[2958] | 0;
+ $arrayidx = $1 + ($i_09 * 40 & -1) | 0;
+ $nNodeGroupsInLayer = $1 + ($i_09 * 40 & -1) + 12 | 0;
+ $2 = HEAP32[$nNodeGroupsInLayer >> 2] | 0;
+ $cmp1 = ($2 | 0) == 0;
+ $cmp2 = ($count_08 | 0) == 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ $start_1 = $start_07;
+ label = 6;
+ break;
+ }
+ case 5:
+ $layerNumber = $arrayidx | 0;
+ $3 = HEAP32[$layerNumber >> 2] | 0;
+ $start_1 = $3;
+ label = 6;
+ break;
+ case 6:
+ $inc = $count_08 + 1 | 0;
+ $count_1 = $inc;
+ $start_2 = $start_1;
+ label = 14;
+ break;
+ case 7:
+ if ($cmp2) {
+ $count_1 = 0;
+ $start_2 = $start_07;
+ label = 14;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $layerNumber6 = $arrayidx | 0;
+ $4 = HEAP32[$layerNumber6 >> 2] | 0;
+ $cmp7 = ($4 | 0) > ($start_07 | 0);
+ if ($cmp7) {
+ label = 9;
+ break;
+ } else {
+ $count_1 = $count_08;
+ $start_2 = $start_07;
+ label = 14;
+ break;
+ }
+ case 9:
+ $5 = HEAP32[2958] | 0;
+ $nNodeGroupsInLayer113 = $5 + ($i_09 * 40 & -1) + 12 | 0;
+ $6 = HEAP32[$nNodeGroupsInLayer113 >> 2] | 0;
+ $cmp124 = ($6 | 0) > 0;
+ if ($cmp124) {
+ $j_05 = 0;
+ $7 = $5;
+ label = 10;
+ break;
+ } else {
+ $count_1 = $count_08;
+ $start_2 = $start_07;
+ label = 14;
+ break;
+ }
+ case 10:
+ $nodeGroupsInLayer = $7 + ($i_09 * 40 & -1) + 4 | 0;
+ $8 = HEAP32[$nodeGroupsInLayer >> 2] | 0;
+ $arrayidx15 = $8 + ($j_05 << 2) | 0;
+ $9 = HEAP32[$arrayidx15 >> 2] | 0;
+ $nNodes = $9 + 4 | 0;
+ $10 = HEAP32[$nNodes >> 2] | 0;
+ $cmp171 = ($10 | 0) > 0;
+ if ($cmp171) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $nodes = $9 | 0;
+ $q_02 = 0;
+ label = 12;
+ break;
+ case 12:
+ $11 = HEAP32[$nodes >> 2] | 0;
+ $arrayidx19 = $11 + ($q_02 << 2) | 0;
+ $12 = HEAP32[$arrayidx19 >> 2] | 0;
+ $rank = $12 + 236 | 0;
+ $13 = HEAP32[$rank >> 2] | 0;
+ $sub = $13 - $count_08 | 0;
+ HEAP32[$rank >> 2] = $sub;
+ $inc20 = $q_02 + 1 | 0;
+ $14 = HEAP32[$nNodes >> 2] | 0;
+ $cmp17 = ($inc20 | 0) < ($14 | 0);
+ if ($cmp17) {
+ $q_02 = $inc20;
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $inc22 = $j_05 + 1 | 0;
+ $15 = HEAP32[2958] | 0;
+ $nNodeGroupsInLayer11 = $15 + ($i_09 * 40 & -1) + 12 | 0;
+ $16 = HEAP32[$nNodeGroupsInLayer11 >> 2] | 0;
+ $cmp12 = ($inc22 | 0) < ($16 | 0);
+ if ($cmp12) {
+ $j_05 = $inc22;
+ $7 = $15;
+ label = 10;
+ break;
+ } else {
+ $count_1 = $count_08;
+ $start_2 = $start_07;
+ label = 14;
+ break;
+ }
+ case 14:
+ $inc27 = $i_09 + 1 | 0;
+ $17 = HEAP32[2800] | 0;
+ $cmp = ($inc27 | 0) < ($17 | 0);
+ if ($cmp) {
+ $start_07 = $start_2;
+ $count_08 = $count_1;
+ $i_09 = $inc27;
+ label = 3;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ return;
+ }
+}
+function _rank3($g, $asp) {
+ $g = $g | 0;
+ $asp = $asp | 0;
+ var $nextIter = 0, $0 = 0, $cmp27 = 0, $cmp1 = 0, $or_cond28 = 0, $1 = 0, $2 = 0, $combiAR = 0, $targetAR = 0, $i_029 = 0, $call = 0, $tobool24 = 0, $n_0_in25 = 0, $rank = 0, $call4 = 0, $tobool = 0, $call5 = 0.0, $3 = 0, $tobool6 = 0, $4 = 0, $call8 = 0, $5 = 0.0, $6 = 0.0, $cmp11 = 0, $curIterations = 0, $7 = 0, $prevIterations = 0, $inc = 0, $cmp = 0, $or_cond = 0, $8 = 0, $call17 = 0.0, $combiAR18 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nextIter = $asp + 24 | 0;
+ $0 = HEAP32[$nextIter >> 2] | 0;
+ _computeNodeGroups($g);
+ $cmp27 = ($0 | 0) > 0;
+ $cmp1 = ($0 | 0) == -1;
+ $or_cond28 = $cmp27 | $cmp1;
+ if ($or_cond28) {
+ label = 3;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 3:
+ $1 = $g;
+ $2 = $g;
+ $combiAR = $asp + 8 | 0;
+ $targetAR = $asp | 0;
+ $i_029 = 0;
+ label = 4;
+ break;
+ case 4:
+ $call = _agfstnode($1) | 0;
+ $tobool24 = ($call | 0) == 0;
+ if ($tobool24) {
+ label = 6;
+ break;
+ } else {
+ $n_0_in25 = $call;
+ label = 5;
+ break;
+ }
+ case 5:
+ $rank = $n_0_in25 + 236 | 0;
+ HEAP32[$rank >> 2] = 0;
+ $call4 = _agnxtnode($1, $n_0_in25) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_0_in25 = $call4;
+ label = 5;
+ break;
+ }
+ case 6:
+ _rank1($2);
+ $call5 = +_computeCombiAR($g);
+ HEAPF64[$combiAR >> 3] = $call5;
+ $3 = HEAP8[164912] | 0;
+ $tobool6 = $3 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $4 = HEAP32[_stderr >> 2] | 0;
+ $call8 = _fprintf($4 | 0, 119304, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $call5, tempInt) | 0) | 0;
+ label = 8;
+ break;
+ case 8:
+ if ($cmp1) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $5 = +HEAPF64[$combiAR >> 3];
+ $6 = +HEAPF64[$targetAR >> 3];
+ $cmp11 = $5 > $6;
+ if ($cmp11) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $curIterations = $asp + 20 | 0;
+ $7 = HEAP32[$curIterations >> 2] | 0;
+ $prevIterations = $asp + 16 | 0;
+ HEAP32[$prevIterations >> 2] = $7;
+ HEAP32[$curIterations >> 2] = $i_029;
+ label = 12;
+ break;
+ case 11:
+ _applyPacking2($g);
+ $inc = $i_029 + 1 | 0;
+ $cmp = ($inc | 0) < ($0 | 0);
+ $or_cond = $cmp | $cmp1;
+ if ($or_cond) {
+ $i_029 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $8 = $g;
+ _rank1($8);
+ _computeLayerWidths($g);
+ _zapLayers();
+ $call17 = +_computeCombiAR($g);
+ $combiAR18 = $asp + 8 | 0;
+ HEAPF64[$combiAR18 >> 3] = $call17;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _computeNodeGroups($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $mul = 0, $call1 = 0, $1 = 0, $2 = 0, $call2 = 0, $tobool46 = 0, $n_0_in47 = 0, $id = 0, $3 = 0, $call3 = 0, $tobool = 0, $call4 = 0, $tobool643 = 0, $n_145_in = 0, $n_145 = 0, $u8 = 0, $UF_size = 0, $4 = 0, $5 = 0, $cmp = 0, $call9 = 0, $6 = 0, $7 = 0, $8 = 0, $nodes = 0, $9 = 0, $10 = 0, $nodes11 = 0, $11 = 0, $12 = 0, $13 = 0, $nNodes = 0, $width = 0, $14 = 0, $15 = 0.0, $16 = 0, $17 = 0, $width16 = 0, $height = 0, $18 = 0, $19 = 0.0, $20 = 0, $21 = 0, $height19 = 0, $22 = 0, $id21 = 0, $23 = 0, $24 = 0, $inc = 0, $call22 = 0, $id24 = 0, $25 = 0, $cmp25 = 0, $26 = 0, $nNodes30 = 0, $27 = 0, $inc31 = 0, $28 = 0, $nodes33 = 0, $29 = 0, $arrayidx34 = 0, $width36 = 0, $30 = 0, $31 = 0.0, $32 = 0, $width38 = 0, $33 = 0.0, $add = 0.0, $34 = 0, $height40 = 0, $35 = 0.0, $height42 = 0, $36 = 0, $37 = 0.0, $cmp43 = 0, $_ = 0.0, $id51 = 0, $38 = 0, $UF_size54 = 0, $39 = 0, $mul55 = 0, $call56 = 0, $40 = 0, $41 = 0, $42 = 0, $nodes58 = 0, $cmp59 = 0, $43 = 0, $44 = 0, $nodes62 = 0, $45 = 0, $46 = 0, $47 = 0, $nNodes65 = 0, $width67 = 0, $48 = 0.0, $49 = 0, $50 = 0, $width69 = 0, $height71 = 0, $51 = 0.0, $52 = 0, $53 = 0, $height73 = 0, $nodes79 = 0, $54 = 0, $arrayidx80 = 0, $55 = 0, $56 = 0, $nNodes82 = 0, $width84 = 0, $57 = 0.0, $width86 = 0, $58 = 0, $59 = 0.0, $add87 = 0.0, $60 = 0, $61 = 0, $width89 = 0, $height91 = 0, $62 = 0.0, $height93 = 0, $63 = 0, $64 = 0.0, $cmp94 = 0, $_41 = 0.0, $65 = 0, $66 = 0, $height104 = 0, $67 = 0, $68 = 0, $id108 = 0, $69 = 0, $70 = 0, $inc109 = 0, $call113 = 0, $tobool6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agnnodes($0) | 0;
+ $mul = $call * 24 & -1;
+ $call1 = _gmalloc($mul) | 0;
+ $1 = $call1;
+ HEAP32[2294] = $1;
+ HEAP32[2798] = 0;
+ $2 = $g;
+ $call2 = _agfstnode($2) | 0;
+ $tobool46 = ($call2 | 0) == 0;
+ if ($tobool46) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in47 = $call2;
+ label = 3;
+ break;
+ }
+ case 3:
+ $id = $n_0_in47 + 136 | 0;
+ $3 = $id;
+ HEAP32[$3 >> 2] = -1;
+ $call3 = _agnxtnode($2, $n_0_in47) | 0;
+ $tobool = ($call3 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in47 = $call3;
+ label = 3;
+ break;
+ }
+ case 4:
+ $call4 = _agfstnode($2) | 0;
+ $tobool643 = ($call4 | 0) == 0;
+ if ($tobool643) {
+ label = 14;
+ break;
+ } else {
+ $n_145_in = $call4;
+ label = 5;
+ break;
+ }
+ case 5:
+ $n_145 = $n_145_in;
+ $u8 = $n_145_in + 24 | 0;
+ $UF_size = $n_145_in + 220 | 0;
+ $4 = $UF_size;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $cmp = ($5 | 0) == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call9 = _zmalloc(4) | 0;
+ $6 = $call9;
+ $7 = HEAP32[2798] | 0;
+ $8 = HEAP32[2294] | 0;
+ $nodes = $8 + ($7 * 24 & -1) | 0;
+ HEAP32[$nodes >> 2] = $6;
+ $9 = HEAP32[2798] | 0;
+ $10 = HEAP32[2294] | 0;
+ $nodes11 = $10 + ($9 * 24 & -1) | 0;
+ $11 = HEAP32[$nodes11 >> 2] | 0;
+ HEAP32[$11 >> 2] = $n_145;
+ $12 = HEAP32[2798] | 0;
+ $13 = HEAP32[2294] | 0;
+ $nNodes = $13 + ($12 * 24 & -1) + 4 | 0;
+ HEAP32[$nNodes >> 2] = 1;
+ $width = $u8 + 24 | 0;
+ $14 = $width;
+ $15 = +HEAPF64[$14 >> 3];
+ $16 = HEAP32[2798] | 0;
+ $17 = HEAP32[2294] | 0;
+ $width16 = $17 + ($16 * 24 & -1) + 8 | 0;
+ HEAPF64[$width16 >> 3] = $15;
+ $height = $u8 + 32 | 0;
+ $18 = $height;
+ $19 = +HEAPF64[$18 >> 3];
+ $20 = HEAP32[2798] | 0;
+ $21 = HEAP32[2294] | 0;
+ $height19 = $21 + ($20 * 24 & -1) + 16 | 0;
+ HEAPF64[$height19 >> 3] = $19;
+ $22 = HEAP32[2798] | 0;
+ $id21 = $u8 + 112 | 0;
+ $23 = $id21;
+ HEAP32[$23 >> 2] = $22;
+ $24 = HEAP32[2798] | 0;
+ $inc = $24 + 1 | 0;
+ HEAP32[2798] = $inc;
+ label = 13;
+ break;
+ case 7:
+ $call22 = _UF_find($n_145) | 0;
+ $id24 = $call22 + 136 | 0;
+ $25 = HEAP32[$id24 >> 2] | 0;
+ $cmp25 = ($25 | 0) > -1;
+ if ($cmp25) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $26 = HEAP32[2294] | 0;
+ $nNodes30 = $26 + ($25 * 24 & -1) + 4 | 0;
+ $27 = HEAP32[$nNodes30 >> 2] | 0;
+ $inc31 = $27 + 1 | 0;
+ HEAP32[$nNodes30 >> 2] = $inc31;
+ $28 = HEAP32[2294] | 0;
+ $nodes33 = $28 + ($25 * 24 & -1) | 0;
+ $29 = HEAP32[$nodes33 >> 2] | 0;
+ $arrayidx34 = $29 + ($27 << 2) | 0;
+ HEAP32[$arrayidx34 >> 2] = $n_145;
+ $width36 = $u8 + 24 | 0;
+ $30 = $width36;
+ $31 = +HEAPF64[$30 >> 3];
+ $32 = HEAP32[2294] | 0;
+ $width38 = $32 + ($25 * 24 & -1) + 8 | 0;
+ $33 = +HEAPF64[$width38 >> 3];
+ $add = $31 + $33;
+ HEAPF64[$width38 >> 3] = $add;
+ $34 = HEAP32[2294] | 0;
+ $height40 = $34 + ($25 * 24 & -1) + 16 | 0;
+ $35 = +HEAPF64[$height40 >> 3];
+ $height42 = $u8 + 32 | 0;
+ $36 = $height42;
+ $37 = +HEAPF64[$36 >> 3];
+ $cmp43 = $35 < $37;
+ $_ = $cmp43 ? $37 : $35;
+ HEAPF64[$height40 >> 3] = $_;
+ $id51 = $u8 + 112 | 0;
+ $38 = $id51;
+ HEAP32[$38 >> 2] = $25;
+ label = 13;
+ break;
+ case 9:
+ $UF_size54 = $call22 + 220 | 0;
+ $39 = HEAP32[$UF_size54 >> 2] | 0;
+ $mul55 = $39 << 2;
+ $call56 = _zmalloc($mul55) | 0;
+ $40 = $call56;
+ $41 = HEAP32[2798] | 0;
+ $42 = HEAP32[2294] | 0;
+ $nodes58 = $42 + ($41 * 24 & -1) | 0;
+ HEAP32[$nodes58 >> 2] = $40;
+ $cmp59 = ($call22 | 0) == ($n_145 | 0);
+ $43 = HEAP32[2798] | 0;
+ $44 = HEAP32[2294] | 0;
+ $nodes62 = $44 + ($43 * 24 & -1) | 0;
+ $45 = HEAP32[$nodes62 >> 2] | 0;
+ HEAP32[$45 >> 2] = $call22;
+ $46 = HEAP32[2798] | 0;
+ $47 = HEAP32[2294] | 0;
+ if ($cmp59) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $nNodes65 = $47 + ($46 * 24 & -1) + 4 | 0;
+ HEAP32[$nNodes65 >> 2] = 1;
+ $width67 = $call22 + 48 | 0;
+ $48 = +HEAPF64[$width67 >> 3];
+ $49 = HEAP32[2798] | 0;
+ $50 = HEAP32[2294] | 0;
+ $width69 = $50 + ($49 * 24 & -1) + 8 | 0;
+ HEAPF64[$width69 >> 3] = $48;
+ $height71 = $call22 + 56 | 0;
+ $51 = +HEAPF64[$height71 >> 3];
+ $52 = HEAP32[2798] | 0;
+ $53 = HEAP32[2294] | 0;
+ $height73 = $53 + ($52 * 24 & -1) + 16 | 0;
+ HEAPF64[$height73 >> 3] = $51;
+ label = 12;
+ break;
+ case 11:
+ $nodes79 = $47 + ($46 * 24 & -1) | 0;
+ $54 = HEAP32[$nodes79 >> 2] | 0;
+ $arrayidx80 = $54 + 4 | 0;
+ HEAP32[$arrayidx80 >> 2] = $n_145;
+ $55 = HEAP32[2798] | 0;
+ $56 = HEAP32[2294] | 0;
+ $nNodes82 = $56 + ($55 * 24 & -1) + 4 | 0;
+ HEAP32[$nNodes82 >> 2] = 2;
+ $width84 = $call22 + 48 | 0;
+ $57 = +HEAPF64[$width84 >> 3];
+ $width86 = $n_145_in + 48 | 0;
+ $58 = $width86;
+ $59 = +HEAPF64[$58 >> 3];
+ $add87 = $57 + $59;
+ $60 = HEAP32[2798] | 0;
+ $61 = HEAP32[2294] | 0;
+ $width89 = $61 + ($60 * 24 & -1) + 8 | 0;
+ HEAPF64[$width89 >> 3] = $add87;
+ $height91 = $call22 + 56 | 0;
+ $62 = +HEAPF64[$height91 >> 3];
+ $height93 = $n_145_in + 56 | 0;
+ $63 = $height93;
+ $64 = +HEAPF64[$63 >> 3];
+ $cmp94 = $62 < $64;
+ $_41 = $cmp94 ? $64 : $62;
+ $65 = HEAP32[2798] | 0;
+ $66 = HEAP32[2294] | 0;
+ $height104 = $66 + ($65 * 24 & -1) + 16 | 0;
+ HEAPF64[$height104 >> 3] = $_41;
+ label = 12;
+ break;
+ case 12:
+ $67 = HEAP32[2798] | 0;
+ HEAP32[$id24 >> 2] = $67;
+ $68 = HEAP32[2798] | 0;
+ $id108 = $n_145_in + 136 | 0;
+ $69 = $id108;
+ HEAP32[$69 >> 2] = $68;
+ $70 = HEAP32[2798] | 0;
+ $inc109 = $70 + 1 | 0;
+ HEAP32[2798] = $inc109;
+ label = 13;
+ break;
+ case 13:
+ $call113 = _agnxtnode($2, $n_145_in) | 0;
+ $tobool6 = ($call113 | 0) == 0;
+ if ($tobool6) {
+ label = 14;
+ break;
+ } else {
+ $n_145_in = $call113;
+ label = 5;
+ break;
+ }
+ case 14:
+ return;
+ }
+}
+function _computeCombiAR($g) {
+ $g = $g | 0;
+ var $0 = 0, $sub = 0, $ranksep = 0, $1 = 0, $mul = 0, $conv = 0.0, $cmp12 = 0, $2 = 0, $nodesep = 0, $3 = 0, $4 = 0, $i_015 = 0, $maxH_014 = 0.0, $maxW_013 = 0.0, $width = 0, $5 = 0.0, $nDummyNodes = 0, $6 = 0, $mul4 = 0, $conv5 = 0.0, $add = 0.0, $cmp6 = 0, $maxW_1 = 0.0, $height = 0, $7 = 0.0, $add18 = 0.0, $inc = 0, $cmp = 0, $maxH_0_lcssa = 0.0, $maxW_0_lcssa = 0.0, $div = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _computeLayerWidths($g);
+ $0 = HEAP32[2800] | 0;
+ $sub = $0 - 1 | 0;
+ $ranksep = $g + 264 | 0;
+ $1 = HEAP32[$ranksep >> 2] | 0;
+ $mul = Math_imul($sub, $1);
+ $conv = +($mul | 0);
+ $cmp12 = ($0 | 0) > 0;
+ if ($cmp12) {
+ label = 3;
+ break;
+ } else {
+ $maxW_0_lcssa = 0.0;
+ $maxH_0_lcssa = $conv;
+ label = 5;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[2958] | 0;
+ $nodesep = $g + 260 | 0;
+ $3 = HEAP32[$nodesep >> 2] | 0;
+ $4 = HEAP32[2800] | 0;
+ $maxW_013 = 0.0;
+ $maxH_014 = $conv;
+ $i_015 = 0;
+ label = 4;
+ break;
+ case 4:
+ $width = $2 + ($i_015 * 40 & -1) + 24 | 0;
+ $5 = +HEAPF64[$width >> 3];
+ $nDummyNodes = $2 + ($i_015 * 40 & -1) + 16 | 0;
+ $6 = HEAP32[$nDummyNodes >> 2] | 0;
+ $mul4 = Math_imul($3, $6);
+ $conv5 = +($mul4 | 0);
+ $add = $5 + $conv5;
+ $cmp6 = $maxW_013 < $add;
+ $maxW_1 = $cmp6 ? $add : $maxW_013;
+ $height = $2 + ($i_015 * 40 & -1) + 32 | 0;
+ $7 = +HEAPF64[$height >> 3];
+ $add18 = $maxH_014 + $7;
+ $inc = $i_015 + 1 | 0;
+ $cmp = ($inc | 0) < ($4 | 0);
+ if ($cmp) {
+ $maxW_013 = $maxW_1;
+ $maxH_014 = $add18;
+ $i_015 = $inc;
+ label = 4;
+ break;
+ } else {
+ $maxW_0_lcssa = $maxW_1;
+ $maxH_0_lcssa = $add18;
+ label = 5;
+ break;
+ }
+ case 5:
+ $div = $maxW_0_lcssa / $maxH_0_lcssa;
+ return +$div;
+ }
+ return 0.0;
+}
+function _applyPacking2($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $mul = 0, $call1 = 0, $1 = 0, $call28 = 0, $cmp9 = 0, $i_010 = 0, $2 = 0, $arrayidx = 0, $inc = 0, $call2 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agnnodes($0) | 0;
+ $mul = $call << 2;
+ $call1 = _zmalloc($mul) | 0;
+ $1 = $call1;
+ HEAP32[1044] = $1;
+ $call28 = _agnnodes($0) | 0;
+ $cmp9 = ($call28 | 0) > 0;
+ if ($cmp9) {
+ $i_010 = 0;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[1044] | 0;
+ $arrayidx = $2 + ($i_010 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $i_010;
+ $inc = $i_010 + 1 | 0;
+ $call2 = _agnnodes($0) | 0;
+ $cmp = ($inc | 0) < ($call2 | 0);
+ if ($cmp) {
+ $i_010 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _computeLayerWidths($g);
+ _sortLayers($g);
+ _reduceMaxWidth2($g);
+ return;
+ }
+}
+function _computeLayerWidths($g) {
+ $g = $g | 0;
+ var $0 = 0, $tobool = 0, $1 = 0, $cmp57 = 0, $2 = 0, $3 = 0, $i_058 = 0, $nodeGroupsInLayer = 0, $4 = 0, $tobool1 = 0, $5 = 0, $nodeGroupsInLayer8 = 0, $6 = 0, $7 = 0, $8 = 0, $removed = 0, $9 = 0, $tobool10 = 0, $10 = 0, $inc16 = 0, $11 = 0, $cmp = 0, $12 = 0, $_lcssa56 = 0, $13 = 0, $14 = 0, $mul = 0, $call = 0, $15 = 0, $16 = 0, $cmp2054 = 0, $17 = 0, $i_155 = 0, $mul22 = 0, $call23 = 0, $18 = 0, $19 = 0, $nodeGroupsInLayer25 = 0, $20 = 0, $mul26 = 0, $call27 = 0, $21 = 0, $22 = 0, $removed29 = 0, $23 = 0, $layerNumber = 0, $24 = 0, $nNodeGroupsInLayer32 = 0, $25 = 0, $nDummyNodes = 0, $26 = 0, $width = 0, $27 = 0, $height = 0, $inc37 = 0, $28 = 0, $cmp20 = 0, $29 = 0, $call39 = 0, $tobool4152 = 0, $30 = 0, $cmp6544 = 0, $nodesep = 0, $n_0_in53 = 0, $call43 = 0, $tobool4550 = 0, $e_0_in51 = 0, $tail = 0, $31 = 0, $rank = 0, $32 = 0, $33 = 0, $k_046 = 0, $head = 0, $34 = 0, $rank4947 = 0, $35 = 0, $36 = 0, $cmp5048 = 0, $k_049 = 0, $37 = 0, $nDummyNodes53 = 0, $38 = 0, $inc54 = 0, $k_0 = 0, $39 = 0, $rank49 = 0, $40 = 0, $41 = 0, $cmp50 = 0, $call59 = 0, $tobool45 = 0, $call62 = 0, $tobool41 = 0, $i_245 = 0, $42 = 0, $nodes = 0, $43 = 0, $44 = 0, $rank70 = 0, $45 = 0, $add71 = 0, $46 = 0, $cmp72 = 0, $47 = 0, $width79 = 0, $48 = 0.0, $mul80 = 0.0, $49 = 0, $50 = 0, $width84 = 0, $51 = 0.0, $cmp85 = 0, $conv = 0, $52 = 0, $53 = 0, $mul87 = 0, $conv88 = 0.0, $add89 = 0.0, $add94 = 0.0, $54 = 0, $55 = 0, $height98 = 0, $56 = 0.0, $57 = 0, $height100 = 0, $58 = 0.0, $mul101 = 0.0, $cmp102 = 0, $59 = 0, $arrayidx113 = 0, $60 = 0, $61 = 0, $nNodeGroupsInLayer117 = 0, $62 = 0, $nodeGroupsInLayer121 = 0, $63 = 0, $arrayidx122 = 0, $64 = 0, $65 = 0, $nNodeGroupsInLayer126 = 0, $66 = 0, $inc127 = 0, $inc129 = 0, $67 = 0, $cmp65 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[2800] = 0;
+ $0 = HEAP32[2958] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[2798] | 0;
+ $cmp57 = ($1 | 0) > 0;
+ $2 = HEAP32[2958] | 0;
+ if ($cmp57) {
+ $i_058 = 0;
+ $3 = $2;
+ label = 4;
+ break;
+ } else {
+ $_lcssa56 = $2;
+ label = 9;
+ break;
+ }
+ case 4:
+ $nodeGroupsInLayer = $3 + ($i_058 * 40 & -1) + 4 | 0;
+ $4 = HEAP32[$nodeGroupsInLayer >> 2] | 0;
+ $tobool1 = ($4 | 0) == 0;
+ if ($tobool1) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[2958] | 0;
+ $nodeGroupsInLayer8 = $5 + ($i_058 * 40 & -1) + 4 | 0;
+ $6 = HEAP32[$nodeGroupsInLayer8 >> 2] | 0;
+ $7 = $6;
+ _free($7);
+ label = 6;
+ break;
+ case 6:
+ $8 = HEAP32[2958] | 0;
+ $removed = $8 + ($i_058 * 40 & -1) + 8 | 0;
+ $9 = HEAP32[$removed >> 2] | 0;
+ $tobool10 = ($9 | 0) == 0;
+ if ($tobool10) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $10 = $9;
+ _free($10);
+ label = 8;
+ break;
+ case 8:
+ $inc16 = $i_058 + 1 | 0;
+ $11 = HEAP32[2798] | 0;
+ $cmp = ($inc16 | 0) < ($11 | 0);
+ $12 = HEAP32[2958] | 0;
+ if ($cmp) {
+ $i_058 = $inc16;
+ $3 = $12;
+ label = 4;
+ break;
+ } else {
+ $_lcssa56 = $12;
+ label = 9;
+ break;
+ }
+ case 9:
+ $13 = $_lcssa56;
+ _free($13);
+ label = 10;
+ break;
+ case 10:
+ $14 = HEAP32[2798] | 0;
+ $mul = $14 * 40 & -1;
+ $call = _zmalloc($mul) | 0;
+ $15 = $call;
+ HEAP32[2958] = $15;
+ $16 = HEAP32[2798] | 0;
+ $cmp2054 = ($16 | 0) > 0;
+ if ($cmp2054) {
+ $i_155 = 0;
+ $17 = $16;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $mul22 = $17 << 2;
+ $call23 = _zmalloc($mul22) | 0;
+ $18 = $call23;
+ $19 = HEAP32[2958] | 0;
+ $nodeGroupsInLayer25 = $19 + ($i_155 * 40 & -1) + 4 | 0;
+ HEAP32[$nodeGroupsInLayer25 >> 2] = $18;
+ $20 = HEAP32[2798] | 0;
+ $mul26 = $20 << 2;
+ $call27 = _zmalloc($mul26) | 0;
+ $21 = $call27;
+ $22 = HEAP32[2958] | 0;
+ $removed29 = $22 + ($i_155 * 40 & -1) + 8 | 0;
+ HEAP32[$removed29 >> 2] = $21;
+ $23 = HEAP32[2958] | 0;
+ $layerNumber = $23 + ($i_155 * 40 & -1) | 0;
+ HEAP32[$layerNumber >> 2] = $i_155;
+ $24 = HEAP32[2958] | 0;
+ $nNodeGroupsInLayer32 = $24 + ($i_155 * 40 & -1) + 12 | 0;
+ HEAP32[$nNodeGroupsInLayer32 >> 2] = 0;
+ $25 = HEAP32[2958] | 0;
+ $nDummyNodes = $25 + ($i_155 * 40 & -1) + 16 | 0;
+ HEAP32[$nDummyNodes >> 2] = 0;
+ $26 = HEAP32[2958] | 0;
+ $width = $26 + ($i_155 * 40 & -1) + 24 | 0;
+ HEAPF64[$width >> 3] = 0.0;
+ $27 = HEAP32[2958] | 0;
+ $height = $27 + ($i_155 * 40 & -1) + 32 | 0;
+ HEAPF64[$height >> 3] = 0.0;
+ $inc37 = $i_155 + 1 | 0;
+ $28 = HEAP32[2798] | 0;
+ $cmp20 = ($inc37 | 0) < ($28 | 0);
+ if ($cmp20) {
+ $i_155 = $inc37;
+ $17 = $28;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $29 = $g;
+ $call39 = _agfstnode($29) | 0;
+ $tobool4152 = ($call39 | 0) == 0;
+ if ($tobool4152) {
+ label = 13;
+ break;
+ } else {
+ $n_0_in53 = $call39;
+ label = 15;
+ break;
+ }
+ case 13:
+ $30 = HEAP32[2798] | 0;
+ $cmp6544 = ($30 | 0) > 0;
+ if ($cmp6544) {
+ label = 14;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 14:
+ $nodesep = $g + 260 | 0;
+ $i_245 = 0;
+ label = 20;
+ break;
+ case 15:
+ $call43 = _agfstout($29, $n_0_in53) | 0;
+ $tobool4550 = ($call43 | 0) == 0;
+ if ($tobool4550) {
+ label = 19;
+ break;
+ } else {
+ $e_0_in51 = $call43;
+ label = 16;
+ break;
+ }
+ case 16:
+ $tail = $e_0_in51 + 16 | 0;
+ $31 = HEAP32[$tail >> 2] | 0;
+ $rank = $31 + 236 | 0;
+ $32 = $rank;
+ $33 = HEAP32[$32 >> 2] | 0;
+ $k_046 = $33 + 1 | 0;
+ $head = $e_0_in51 + 12 | 0;
+ $34 = HEAP32[$head >> 2] | 0;
+ $rank4947 = $34 + 236 | 0;
+ $35 = $rank4947;
+ $36 = HEAP32[$35 >> 2] | 0;
+ $cmp5048 = ($k_046 | 0) < ($36 | 0);
+ if ($cmp5048) {
+ $k_049 = $k_046;
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $37 = HEAP32[2958] | 0;
+ $nDummyNodes53 = $37 + ($k_049 * 40 & -1) + 16 | 0;
+ $38 = HEAP32[$nDummyNodes53 >> 2] | 0;
+ $inc54 = $38 + 1 | 0;
+ HEAP32[$nDummyNodes53 >> 2] = $inc54;
+ $k_0 = $k_049 + 1 | 0;
+ $39 = HEAP32[$head >> 2] | 0;
+ $rank49 = $39 + 236 | 0;
+ $40 = $rank49;
+ $41 = HEAP32[$40 >> 2] | 0;
+ $cmp50 = ($k_0 | 0) < ($41 | 0);
+ if ($cmp50) {
+ $k_049 = $k_0;
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $call59 = _agnxtout($29, $e_0_in51) | 0;
+ $tobool45 = ($call59 | 0) == 0;
+ if ($tobool45) {
+ label = 19;
+ break;
+ } else {
+ $e_0_in51 = $call59;
+ label = 16;
+ break;
+ }
+ case 19:
+ $call62 = _agnxtnode($29, $n_0_in53) | 0;
+ $tobool41 = ($call62 | 0) == 0;
+ if ($tobool41) {
+ label = 13;
+ break;
+ } else {
+ $n_0_in53 = $call62;
+ label = 15;
+ break;
+ }
+ case 20:
+ $42 = HEAP32[2294] | 0;
+ $nodes = $42 + ($i_245 * 24 & -1) | 0;
+ $43 = HEAP32[$nodes >> 2] | 0;
+ $44 = HEAP32[$43 >> 2] | 0;
+ $rank70 = $44 + 236 | 0;
+ $45 = HEAP32[$rank70 >> 2] | 0;
+ $add71 = $45 + 1 | 0;
+ $46 = HEAP32[2800] | 0;
+ $cmp72 = ($add71 | 0) > ($46 | 0);
+ if ($cmp72) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ HEAP32[2800] = $add71;
+ label = 22;
+ break;
+ case 22:
+ $47 = HEAP32[2294] | 0;
+ $width79 = $47 + ($i_245 * 24 & -1) + 8 | 0;
+ $48 = +HEAPF64[$width79 >> 3];
+ $mul80 = $48 * 72.0;
+ $49 = HEAP32[$rank70 >> 2] | 0;
+ $50 = HEAP32[2958] | 0;
+ $width84 = $50 + ($49 * 40 & -1) + 24 | 0;
+ $51 = +HEAPF64[$width84 >> 3];
+ $cmp85 = $51 > 0.0;
+ $conv = $cmp85 & 1;
+ $52 = HEAP32[$nodesep >> 2] | 0;
+ $53 = -$conv | 0;
+ $mul87 = $52 & $53;
+ $conv88 = +($mul87 | 0);
+ $add89 = $mul80 + $conv88;
+ $add94 = $51 + $add89;
+ HEAPF64[$width84 >> 3] = $add94;
+ $54 = HEAP32[$rank70 >> 2] | 0;
+ $55 = HEAP32[2958] | 0;
+ $height98 = $55 + ($54 * 40 & -1) + 32 | 0;
+ $56 = +HEAPF64[$height98 >> 3];
+ $57 = HEAP32[2294] | 0;
+ $height100 = $57 + ($i_245 * 24 & -1) + 16 | 0;
+ $58 = +HEAPF64[$height100 >> 3];
+ $mul101 = $58 * 72.0;
+ $cmp102 = $56 < $mul101;
+ if ($cmp102) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ HEAPF64[$height98 >> 3] = $mul101;
+ label = 24;
+ break;
+ case 24:
+ $59 = HEAP32[2294] | 0;
+ $arrayidx113 = $59 + ($i_245 * 24 & -1) | 0;
+ $60 = HEAP32[$rank70 >> 2] | 0;
+ $61 = HEAP32[2958] | 0;
+ $nNodeGroupsInLayer117 = $61 + ($60 * 40 & -1) + 12 | 0;
+ $62 = HEAP32[$nNodeGroupsInLayer117 >> 2] | 0;
+ $nodeGroupsInLayer121 = $61 + ($60 * 40 & -1) + 4 | 0;
+ $63 = HEAP32[$nodeGroupsInLayer121 >> 2] | 0;
+ $arrayidx122 = $63 + ($62 << 2) | 0;
+ HEAP32[$arrayidx122 >> 2] = $arrayidx113;
+ $64 = HEAP32[$rank70 >> 2] | 0;
+ $65 = HEAP32[2958] | 0;
+ $nNodeGroupsInLayer126 = $65 + ($64 * 40 & -1) + 12 | 0;
+ $66 = HEAP32[$nNodeGroupsInLayer126 >> 2] | 0;
+ $inc127 = $66 + 1 | 0;
+ HEAP32[$nNodeGroupsInLayer126 >> 2] = $inc127;
+ $inc129 = $i_245 + 1 | 0;
+ $67 = HEAP32[2798] | 0;
+ $cmp65 = ($inc129 | 0) < ($67 | 0);
+ if ($cmp65) {
+ $i_245 = $inc129;
+ label = 20;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ return;
+ }
+}
+function _init_UF_size($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool4 = 0, $n_0_in5 = 0, $UF_size = 0, $1 = 0, $call1 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool4 = ($call | 0) == 0;
+ if ($tobool4) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in5 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $UF_size = $n_0_in5 + 220 | 0;
+ $1 = $UF_size;
+ HEAP32[$1 >> 2] = 0;
+ $call1 = _agnxtnode($0, $n_0_in5) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in5 = $call1;
+ label = 3;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _sortLayers($g) {
+ $g = $g | 0;
+ var $1 = 0;
+ $1 = HEAP32[1044] | 0;
+ _qsort($1 | 0, _agnnodes($g) | 0, 4, 592);
+ return;
+}
+function _reduceMaxWidth2($g) {
+ $g = $g | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $i_0 = 0, $cmp = 0, $arrayidx = 0, $3 = 0, $nNodeGroupsInLayer = 0, $4 = 0, $cmp2 = 0, $inc = 0, $cmp4 = 0, $arrayidx6 = 0, $5 = 0, $width = 0, $6 = 0.0, $nextMaxWidth_0 = 0.0, $maxLayerIndex_0 = 0, $7 = 0, $cmp8 = 0, $8 = 0, $nodeGroupsInLayer = 0, $9 = 0, $10 = 0, $nNodeGroupsInLayer12 = 0, $11 = 0, $12 = 0, $width14 = 0, $13 = 0.0, $div = 0.0, $cmp15 = 0, $mul = 0.0, $div18 = 0.0, $cmp19 = 0, $14 = 0, $width22 = 0, $15 = 0.0, $div23 = 0.0, $nextMaxWidth_1 = 0.0, $16 = 0, $nNodeGroupsInLayer26 = 0, $17 = 0, $cmp2950 = 0, $nodesep = 0, $i_157 = 0, $rem_055 = 0, $fstNdGrp_053 = 0, $fst_052 = 0, $w_051 = 0.0, $18 = 0, $removed = 0, $19 = 0, $arrayidx32 = 0, $20 = 0, $tobool = 0, $inc34 = 0, $nodeGroupsInLayer37 = 0, $21 = 0, $arrayidx38 = 0, $22 = 0, $width39 = 0, $23 = 0.0, $mul40 = 0.0, $add41 = 0.0, $cmp42 = 0, $conv = 0, $24 = 0, $25 = 0, $mul43 = 0, $conv44 = 0.0, $add45 = 0.0, $cmp46 = 0, $tobool49 = 0, $or_cond = 0, $nNodes = 0, $26 = 0, $cmp7546 = 0, $nNodes79 = 0, $nodes = 0, $nodes84 = 0, $add62 = 0.0, $add63 = 0.0, $_fst_0 = 0, $_fstNdGrp_0 = 0, $p_048 = 0, $27 = 0, $cmp8043 = 0, $q_045 = 0, $28 = 0, $arrayidx83 = 0, $29 = 0, $30 = 0, $arrayidx85 = 0, $31 = 0, $call = 0, $edge_type = 0, $inc89 = 0, $32 = 0, $cmp80 = 0, $inc92 = 0, $33 = 0, $cmp75 = 0, $34 = 0, $removed95 = 0, $35 = 0, $arrayidx96 = 0, $36 = 0, $nNodeGroupsInLayer99 = 0, $37 = 0, $dec = 0, $38 = 0, $nDummyNodes = 0, $39 = 0, $inc101 = 0, $40 = 0.0, $mul103 = 0.0, $41 = 0, $conv106 = 0.0, $add107 = 0.0, $42 = 0, $width109 = 0, $43 = 0.0, $sub = 0.0, $w_1 = 0.0, $fst_1 = 0, $fstNdGrp_1 = 0, $rem_1 = 0, $inc112 = 0, $add28 = 0, $cmp29 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[2800] | 0;
+ $1 = HEAP32[1044] | 0;
+ $2 = HEAP32[2958] | 0;
+ $i_0 = 0;
+ label = 3;
+ break;
+ case 3:
+ $cmp = ($i_0 | 0) < ($0 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $maxLayerIndex_0 = 0;
+ $nextMaxWidth_0 = 0.0;
+ label = 7;
+ break;
+ }
+ case 4:
+ $arrayidx = $1 + ($i_0 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $nNodeGroupsInLayer = $2 + ($3 * 40 & -1) + 12 | 0;
+ $4 = HEAP32[$nNodeGroupsInLayer >> 2] | 0;
+ $cmp2 = ($4 | 0) < 2;
+ $inc = $i_0 + 1 | 0;
+ if ($cmp2) {
+ $i_0 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp4 = ($0 | 0) > ($inc | 0);
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ $maxLayerIndex_0 = $3;
+ $nextMaxWidth_0 = 0.0;
+ label = 7;
+ break;
+ }
+ case 6:
+ $arrayidx6 = $1 + ($inc << 2) | 0;
+ $5 = HEAP32[$arrayidx6 >> 2] | 0;
+ $width = $2 + ($5 * 40 & -1) + 24 | 0;
+ $6 = +HEAPF64[$width >> 3];
+ $maxLayerIndex_0 = $3;
+ $nextMaxWidth_0 = $6;
+ label = 7;
+ break;
+ case 7:
+ $7 = HEAP32[2800] | 0;
+ $cmp8 = ($i_0 | 0) == ($7 | 0);
+ if ($cmp8) {
+ label = 24;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $8 = HEAP32[2958] | 0;
+ $nodeGroupsInLayer = $8 + ($maxLayerIndex_0 * 40 & -1) + 4 | 0;
+ $9 = HEAP32[$nodeGroupsInLayer >> 2] | 0;
+ $10 = $9;
+ $nNodeGroupsInLayer12 = $8 + ($maxLayerIndex_0 * 40 & -1) + 12 | 0;
+ $11 = HEAP32[$nNodeGroupsInLayer12 >> 2] | 0;
+ _qsort($10 | 0, $11 | 0, 4, 14);
+ $12 = HEAP32[2958] | 0;
+ $width14 = $12 + ($maxLayerIndex_0 * 40 & -1) + 24 | 0;
+ $13 = +HEAPF64[$width14 >> 3];
+ $div = $13 * .25;
+ $cmp15 = $nextMaxWidth_0 > $div;
+ if ($cmp15) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $mul = $13 * 3.0;
+ $div18 = $mul * .25;
+ $cmp19 = $nextMaxWidth_0 < $div18;
+ if ($cmp19) {
+ $nextMaxWidth_1 = $nextMaxWidth_0;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $14 = HEAP32[2958] | 0;
+ $width22 = $14 + ($maxLayerIndex_0 * 40 & -1) + 24 | 0;
+ $15 = +HEAPF64[$width22 >> 3];
+ $div23 = $15 * .5;
+ $nextMaxWidth_1 = $div23;
+ label = 11;
+ break;
+ case 11:
+ $16 = HEAP32[2958] | 0;
+ $nNodeGroupsInLayer26 = $16 + ($maxLayerIndex_0 * 40 & -1) + 12 | 0;
+ $17 = HEAP32[$nNodeGroupsInLayer26 >> 2] | 0;
+ $cmp2950 = ($17 | 0) > 0;
+ if ($cmp2950) {
+ label = 12;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 12:
+ $nodesep = $g + 260 | 0;
+ $w_051 = 0.0;
+ $fst_052 = 0;
+ $fstNdGrp_053 = 0;
+ $rem_055 = 0;
+ $i_157 = 0;
+ label = 13;
+ break;
+ case 13:
+ $18 = HEAP32[2958] | 0;
+ $removed = $18 + ($maxLayerIndex_0 * 40 & -1) + 8 | 0;
+ $19 = HEAP32[$removed >> 2] | 0;
+ $arrayidx32 = $19 + ($i_157 << 2) | 0;
+ $20 = HEAP32[$arrayidx32 >> 2] | 0;
+ $tobool = ($20 | 0) == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $inc34 = $rem_055 + 1 | 0;
+ $rem_1 = $inc34;
+ $fstNdGrp_1 = $fstNdGrp_053;
+ $fst_1 = $fst_052;
+ $w_1 = $w_051;
+ label = 23;
+ break;
+ case 15:
+ $nodeGroupsInLayer37 = $18 + ($maxLayerIndex_0 * 40 & -1) + 4 | 0;
+ $21 = HEAP32[$nodeGroupsInLayer37 >> 2] | 0;
+ $arrayidx38 = $21 + ($i_157 << 2) | 0;
+ $22 = HEAP32[$arrayidx38 >> 2] | 0;
+ $width39 = $22 + 8 | 0;
+ $23 = +HEAPF64[$width39 >> 3];
+ $mul40 = $23 * 72.0;
+ $add41 = $w_051 + $mul40;
+ $cmp42 = $w_051 > 0.0;
+ $conv = $cmp42 & 1;
+ $24 = HEAP32[$nodesep >> 2] | 0;
+ $25 = -$conv | 0;
+ $mul43 = $24 & $25;
+ $conv44 = +($mul43 | 0);
+ $add45 = $add41 + $conv44;
+ $cmp46 = $add45 <= $nextMaxWidth_1;
+ $tobool49 = ($fst_052 | 0) == 0;
+ $or_cond = $cmp46 | $tobool49;
+ if ($or_cond) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $nNodes = $fstNdGrp_053 + 4 | 0;
+ $26 = HEAP32[$nNodes >> 2] | 0;
+ $cmp7546 = ($26 | 0) > 0;
+ if ($cmp7546) {
+ label = 17;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 17:
+ $nNodes79 = $22 + 4 | 0;
+ $nodes = $fstNdGrp_053 | 0;
+ $nodes84 = $22 | 0;
+ $p_048 = 0;
+ label = 19;
+ break;
+ case 18:
+ $add62 = $mul40 + $conv44;
+ $add63 = $w_051 + $add62;
+ $_fst_0 = $tobool49 ? 1 : $fst_052;
+ $_fstNdGrp_0 = $tobool49 ? $22 : $fstNdGrp_053;
+ $rem_1 = $rem_055;
+ $fstNdGrp_1 = $_fstNdGrp_0;
+ $fst_1 = $_fst_0;
+ $w_1 = $add63;
+ label = 23;
+ break;
+ case 19:
+ $27 = HEAP32[$nNodes79 >> 2] | 0;
+ $cmp8043 = ($27 | 0) > 0;
+ if ($cmp8043) {
+ $q_045 = 0;
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $28 = HEAP32[$nodes >> 2] | 0;
+ $arrayidx83 = $28 + ($p_048 << 2) | 0;
+ $29 = HEAP32[$arrayidx83 >> 2] | 0;
+ $30 = HEAP32[$nodes84 >> 2] | 0;
+ $arrayidx85 = $30 + ($q_045 << 2) | 0;
+ $31 = HEAP32[$arrayidx85 >> 2] | 0;
+ $call = _virtual_edge($29, $31, 0) | 0;
+ $edge_type = $call + 128 | 0;
+ HEAP8[$edge_type] = 1;
+ $inc89 = $q_045 + 1 | 0;
+ $32 = HEAP32[$nNodes79 >> 2] | 0;
+ $cmp80 = ($inc89 | 0) < ($32 | 0);
+ if ($cmp80) {
+ $q_045 = $inc89;
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $inc92 = $p_048 + 1 | 0;
+ $33 = HEAP32[$nNodes >> 2] | 0;
+ $cmp75 = ($inc92 | 0) < ($33 | 0);
+ if ($cmp75) {
+ $p_048 = $inc92;
+ label = 19;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $34 = HEAP32[2958] | 0;
+ $removed95 = $34 + ($maxLayerIndex_0 * 40 & -1) + 8 | 0;
+ $35 = HEAP32[$removed95 >> 2] | 0;
+ $arrayidx96 = $35 + ($i_157 << 2) | 0;
+ HEAP32[$arrayidx96 >> 2] = 1;
+ $36 = HEAP32[2958] | 0;
+ $nNodeGroupsInLayer99 = $36 + ($maxLayerIndex_0 * 40 & -1) + 12 | 0;
+ $37 = HEAP32[$nNodeGroupsInLayer99 >> 2] | 0;
+ $dec = $37 - 1 | 0;
+ HEAP32[$nNodeGroupsInLayer99 >> 2] = $dec;
+ $38 = HEAP32[2958] | 0;
+ $nDummyNodes = $38 + ($maxLayerIndex_0 * 40 & -1) + 16 | 0;
+ $39 = HEAP32[$nDummyNodes >> 2] | 0;
+ $inc101 = $39 + 1 | 0;
+ HEAP32[$nDummyNodes >> 2] = $inc101;
+ $40 = +HEAPF64[$width39 >> 3];
+ $mul103 = $40 * 72.0;
+ $41 = HEAP32[$nodesep >> 2] | 0;
+ $conv106 = +($41 | 0);
+ $add107 = $mul103 + $conv106;
+ $42 = HEAP32[2958] | 0;
+ $width109 = $42 + ($maxLayerIndex_0 * 40 & -1) + 24 | 0;
+ $43 = +HEAPF64[$width109 >> 3];
+ $sub = $43 - $add107;
+ HEAPF64[$width109 >> 3] = $sub;
+ $rem_1 = $rem_055;
+ $fstNdGrp_1 = $fstNdGrp_053;
+ $fst_1 = $fst_052;
+ $w_1 = $w_051;
+ label = 23;
+ break;
+ case 23:
+ $inc112 = $i_157 + 1 | 0;
+ $add28 = $rem_1 + $17 | 0;
+ $cmp29 = ($inc112 | 0) < ($add28 | 0);
+ if ($cmp29) {
+ $w_051 = $w_1;
+ $fst_052 = $fst_1;
+ $fstNdGrp_053 = $fstNdGrp_1;
+ $rem_055 = $rem_1;
+ $i_157 = $inc112;
+ label = 13;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ return;
+ }
+}
+function _compFunction2($a, $b) {
+ $a = $a | 0;
+ $b = $b | 0;
+ var $call = 0, $call1 = 0;
+ $call = _getOutDegree(HEAP32[$a >> 2] | 0) | 0;
+ $call1 = _getOutDegree(HEAP32[$b >> 2] | 0) | 0;
+ return (($call1 | 0) < ($call | 0) & 1) - (($call1 | 0) > ($call | 0) & 1) | 0;
+}
+function _getOutDegree($ng) {
+ $ng = $ng | 0;
+ var $nNodes = 0, $0 = 0, $cmp11 = 0, $nodes = 0, $i_013 = 0, $cnt_012 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $graph = 0, $3 = 0, $4 = 0, $5 = 0, $call = 0, $tobool8 = 0, $e_0_in10 = 0, $cnt_19 = 0, $inc = 0, $call3 = 0, $tobool = 0, $cnt_1_lcssa = 0, $inc5 = 0, $6 = 0, $cmp = 0, $cnt_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nNodes = $ng + 4 | 0;
+ $0 = HEAP32[$nNodes >> 2] | 0;
+ $cmp11 = ($0 | 0) > 0;
+ if ($cmp11) {
+ label = 3;
+ break;
+ } else {
+ $cnt_0_lcssa = 0;
+ label = 7;
+ break;
+ }
+ case 3:
+ $nodes = $ng | 0;
+ $cnt_012 = 0;
+ $i_013 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$nodes >> 2] | 0;
+ $arrayidx = $1 + ($i_013 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $graph = $2 + 20 | 0;
+ $3 = HEAP32[$graph >> 2] | 0;
+ $4 = $3;
+ $5 = $2;
+ $call = _agfstout($4, $5) | 0;
+ $tobool8 = ($call | 0) == 0;
+ if ($tobool8) {
+ $cnt_1_lcssa = $cnt_012;
+ label = 6;
+ break;
+ } else {
+ $cnt_19 = $cnt_012;
+ $e_0_in10 = $call;
+ label = 5;
+ break;
+ }
+ case 5:
+ $inc = $cnt_19 + 1 | 0;
+ $call3 = _agnxtout($4, $e_0_in10) | 0;
+ $tobool = ($call3 | 0) == 0;
+ if ($tobool) {
+ $cnt_1_lcssa = $inc;
+ label = 6;
+ break;
+ } else {
+ $cnt_19 = $inc;
+ $e_0_in10 = $call3;
+ label = 5;
+ break;
+ }
+ case 6:
+ $inc5 = $i_013 + 1 | 0;
+ $6 = HEAP32[$nNodes >> 2] | 0;
+ $cmp = ($inc5 | 0) < ($6 | 0);
+ if ($cmp) {
+ $cnt_012 = $cnt_1_lcssa;
+ $i_013 = $inc5;
+ label = 4;
+ break;
+ } else {
+ $cnt_0_lcssa = $cnt_1_lcssa;
+ label = 7;
+ break;
+ }
+ case 7:
+ return $cnt_0_lcssa | 0;
+ }
+ return 0;
+}
+function _compFunction($a, $b) {
+ $a = $a | 0;
+ $b = $b | 0;
+ var $3 = 0, $4 = 0.0, $6 = 0.0;
+ $3 = HEAP32[2958] | 0;
+ $4 = +HEAPF64[$3 + ((HEAP32[$b >> 2] | 0) * 40 & -1) + 24 >> 3];
+ $6 = +HEAPF64[$3 + ((HEAP32[$a >> 2] | 0) * 40 & -1) + 24 >> 3];
+ return ($4 > $6 & 1) - ($4 < $6 & 1) | 0;
+}
+function _incr_width($g, $v) {
+ $g = $g | 0;
+ $v = $v | 0;
+ var $conv = 0.0, $lw = 0, $rw = 0;
+ $conv = +((HEAP32[$g + 260 >> 2] | 0) / 2 & -1 | 0);
+ $lw = $v + 104 | 0;
+ HEAPF64[$lw >> 3] = +HEAPF64[$lw >> 3] + $conv;
+ $rw = $v + 112 | 0;
+ HEAPF64[$rw >> 3] = $conv + +HEAPF64[$rw >> 3];
+ return;
+}
+function _is_cluster_edge($e) {
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $ranktype = 0, $1 = 0, $cmp = 0, $head = 0, $2 = 0, $ranktype3 = 0, $3 = 0, $cmp5 = 0, $phitmp = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $ranktype = $0 + 165 | 0;
+ $1 = HEAP8[$ranktype] | 0;
+ $cmp = $1 << 24 >> 24 == 7;
+ if ($cmp) {
+ $4 = 1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $e + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $ranktype3 = $2 + 165 | 0;
+ $3 = HEAP8[$ranktype3] | 0;
+ $cmp5 = $3 << 24 >> 24 == 7;
+ $phitmp = $cmp5 & 1;
+ $4 = $phitmp;
+ label = 4;
+ break;
+ case 4:
+ return $4 | 0;
+ }
+ return 0;
+}
+function _nonconstraint_edge($e) {
+ $e = $e | 0;
+ var $0 = 0, $tobool = 0, $1 = 0, $index = 0, $2 = 0, $call = 0, $tobool1 = 0, $3 = 0, $tobool2 = 0, $call4 = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41954] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $e | 0;
+ $index = $0 + 8 | 0;
+ $2 = HEAP32[$index >> 2] | 0;
+ $call = _agxget($1, $2) | 0;
+ $tobool1 = ($call | 0) == 0;
+ if ($tobool1) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP8[$call] | 0;
+ $tobool2 = $3 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call4 = _mapbool($call) | 0;
+ $cmp = $call4 << 24 >> 24 == 0;
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $retval_0 = 0;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _class1($g) {
+ $g = $g | 0;
+ var $0 = 0, $1 = 0, $call = 0, $tobool28 = 0, $n_0_in29 = 0, $call1 = 0, $tobool325 = 0, $e_027_in = 0, $e_027 = 0, $to_virt = 0, $2 = 0, $3 = 0, $tobool5 = 0, $call6 = 0, $tobool7 = 0, $tail = 0, $4 = 0, $5 = 0, $call10 = 0, $head = 0, $6 = 0, $7 = 0, $call11 = 0, $cmp = 0, $clust = 0, $8 = 0, $tobool15 = 0, $clust17 = 0, $9 = 0, $tobool18 = 0, $10 = 0, $11 = 0, $12 = 0, $13 = 0, $call23 = 0, $tobool24 = 0, $call26 = 0, $call28 = 0, $tobool3 = 0, $call30 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ _mark_clusters($0);
+ $1 = $g;
+ $call = _agfstnode($1) | 0;
+ $tobool28 = ($call | 0) == 0;
+ if ($tobool28) {
+ label = 15;
+ break;
+ } else {
+ $n_0_in29 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agfstout($1, $n_0_in29) | 0;
+ $tobool325 = ($call1 | 0) == 0;
+ if ($tobool325) {
+ label = 14;
+ break;
+ } else {
+ $e_027_in = $call1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $e_027 = $e_027_in;
+ $to_virt = $e_027_in + 188 | 0;
+ $2 = $to_virt;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool5 = ($3 | 0) == 0;
+ if ($tobool5) {
+ label = 5;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 5:
+ $call6 = _nonconstraint_edge($e_027) | 0;
+ $tobool7 = ($call6 | 0) == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 6:
+ $tail = $e_027_in + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $5 = $4;
+ $call10 = _UF_find($5) | 0;
+ $head = $e_027_in + 12 | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ $7 = $6;
+ $call11 = _UF_find($7) | 0;
+ $cmp = ($call10 | 0) == ($call11 | 0);
+ if ($cmp) {
+ label = 13;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $clust = $call10 + 216 | 0;
+ $8 = HEAP32[$clust >> 2] | 0;
+ $tobool15 = ($8 | 0) == 0;
+ if ($tobool15) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $clust17 = $call11 + 216 | 0;
+ $9 = HEAP32[$clust17 >> 2] | 0;
+ $tobool18 = ($9 | 0) == 0;
+ if ($tobool18) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $10 = HEAP32[$tail >> 2] | 0;
+ $11 = $10;
+ $12 = HEAP32[$head >> 2] | 0;
+ $13 = $12;
+ _interclust1($g, $11, $13, $e_027);
+ label = 13;
+ break;
+ case 10:
+ $call23 = _find_fast_edge($call10, $call11) | 0;
+ $tobool24 = ($call23 | 0) == 0;
+ if ($tobool24) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ _merge_oneway($e_027, $call23);
+ label = 13;
+ break;
+ case 12:
+ $call26 = _virtual_edge($call10, $call11, $e_027) | 0;
+ label = 13;
+ break;
+ case 13:
+ $call28 = _agnxtout($1, $e_027_in) | 0;
+ $tobool3 = ($call28 | 0) == 0;
+ if ($tobool3) {
+ label = 14;
+ break;
+ } else {
+ $e_027_in = $call28;
+ label = 4;
+ break;
+ }
+ case 14:
+ $call30 = _agnxtnode($1, $n_0_in29) | 0;
+ $tobool = ($call30 | 0) == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ $n_0_in29 = $call30;
+ label = 3;
+ break;
+ }
+ case 15:
+ return;
+ }
+}
+function _interclust1($g, $t, $h, $e) {
+ $g = $g | 0;
+ $t = $t | 0;
+ $h = $h | 0;
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $clust = 0, $1 = 0, $tobool = 0, $rank = 0, $2 = 0, $leader = 0, $3 = 0, $rank8 = 0, $4 = 0, $sub = 0, $t_rank_0 = 0, $head = 0, $5 = 0, $clust10 = 0, $6 = 0, $tobool11 = 0, $rank15 = 0, $7 = 0, $leader20 = 0, $8 = 0, $rank22 = 0, $9 = 0, $sub23 = 0, $h_rank_0 = 0, $minlen = 0, $10 = 0, $conv = 0, $add = 0, $sub27 = 0, $cmp = 0, $phitmp14 = 0.0, $sub31 = 0, $phitmp = 0.0, $h_len_0 = 0.0, $t_len_0 = 0.0, $call = 0, $node_type = 0, $call34 = 0, $call35 = 0, $weight = 0, $11 = 0.0, $mul = 0.0, $conv38 = 0, $call39 = 0, $12 = 0.0, $conv43 = 0, $call44 = 0, $to_orig = 0, $to_orig47 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $clust = $0 + 216 | 0;
+ $1 = HEAP32[$clust >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ $t_rank_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $rank = $0 + 236 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $leader = $1 + 276 | 0;
+ $3 = HEAP32[$leader >> 2] | 0;
+ $rank8 = $3 + 236 | 0;
+ $4 = HEAP32[$rank8 >> 2] | 0;
+ $sub = $2 - $4 | 0;
+ $t_rank_0 = $sub;
+ label = 4;
+ break;
+ case 4:
+ $head = $e + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $clust10 = $5 + 216 | 0;
+ $6 = HEAP32[$clust10 >> 2] | 0;
+ $tobool11 = ($6 | 0) == 0;
+ if ($tobool11) {
+ $h_rank_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $rank15 = $5 + 236 | 0;
+ $7 = HEAP32[$rank15 >> 2] | 0;
+ $leader20 = $6 + 276 | 0;
+ $8 = HEAP32[$leader20 >> 2] | 0;
+ $rank22 = $8 + 236 | 0;
+ $9 = HEAP32[$rank22 >> 2] | 0;
+ $sub23 = $7 - $9 | 0;
+ $h_rank_0 = $sub23;
+ label = 6;
+ break;
+ case 6:
+ $minlen = $e + 186 | 0;
+ $10 = HEAP16[$minlen >> 1] | 0;
+ $conv = $10 & 65535;
+ $add = $t_rank_0 - $h_rank_0 | 0;
+ $sub27 = $add + $conv | 0;
+ $cmp = ($sub27 | 0) > 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $phitmp14 = +($sub27 | 0);
+ $t_len_0 = 0.0;
+ $h_len_0 = $phitmp14;
+ label = 9;
+ break;
+ case 8:
+ $sub31 = -$sub27 | 0;
+ $phitmp = +($sub31 | 0);
+ $t_len_0 = $phitmp;
+ $h_len_0 = 0.0;
+ label = 9;
+ break;
+ case 9:
+ $call = _virtual_node($g) | 0;
+ $node_type = $call + 162 | 0;
+ HEAP8[$node_type] = 2;
+ $call34 = _UF_find($t) | 0;
+ $call35 = _UF_find($h) | 0;
+ $weight = $e + 172 | 0;
+ $11 = +HEAPF32[$weight >> 2];
+ $mul = $11 * 10.0;
+ $conv38 = ~~$mul;
+ $call39 = _make_aux_edge($call, $call34, $t_len_0, $conv38) | 0;
+ $12 = +HEAPF32[$weight >> 2];
+ $conv43 = ~~$12;
+ $call44 = _make_aux_edge($call, $call35, $h_len_0, $conv43) | 0;
+ $to_orig = $call44 + 132 | 0;
+ HEAP32[$to_orig >> 2] = $e;
+ $to_orig47 = $call39 + 132 | 0;
+ HEAP32[$to_orig47 >> 2] = $e;
+ return;
+ }
+}
+function _mergeable($e, $f) {
+ $e = $e | 0;
+ $f = $f | 0;
+ var $tobool = 0, $tobool1 = 0, $or_cond = 0, $tail = 0, $0 = 0, $tail3 = 0, $1 = 0, $cmp = 0, $head = 0, $2 = 0, $head5 = 0, $3 = 0, $cmp6 = 0, $label = 0, $4 = 0, $label9 = 0, $5 = 0, $cmp10 = 0, $call = 0, $tobool12 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($e | 0) == 0;
+ $tobool1 = ($f | 0) == 0;
+ $or_cond = $tobool | $tobool1;
+ if ($or_cond) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $tail3 = $f + 16 | 0;
+ $1 = HEAP32[$tail3 >> 2] | 0;
+ $cmp = ($0 | 0) == ($1 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $head = $e + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $head5 = $f + 12 | 0;
+ $3 = HEAP32[$head5 >> 2] | 0;
+ $cmp6 = ($2 | 0) == ($3 | 0);
+ if ($cmp6) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $label = $e + 112 | 0;
+ $4 = HEAP32[$label >> 2] | 0;
+ $label9 = $f + 112 | 0;
+ $5 = HEAP32[$label9 >> 2] | 0;
+ $cmp10 = ($4 | 0) == ($5 | 0);
+ if ($cmp10) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call = _ports_eq($e, $f) | 0;
+ $tobool12 = ($call | 0) == 0;
+ if ($tobool12) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 8;
+ break;
+ }
+ case 7:
+ $retval_0 = 0;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _class2($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_nodes = 0, $0 = 0, $n_cluster = 0, $1 = 0, $cmp126 = 0, $clust = 0, $c_0127 = 0, $2 = 0, $arrayidx = 0, $3 = 0, $4 = 0, $inc = 0, $5 = 0, $cmp = 0, $6 = 0, $call = 0, $tobool124 = 0, $n_0_in125 = 0, $call6 = 0, $tobool8122 = 0, $e_0_in123 = 0, $head = 0, $7 = 0, $8 = 0, $weight_class = 0, $9 = 0, $cmp11 = 0, $inc16 = 0, $tail = 0, $10 = 0, $11 = 0, $weight_class18 = 0, $12 = 0, $cmp20 = 0, $inc26 = 0, $call29 = 0, $tobool8 = 0, $call32 = 0, $tobool = 0, $call34 = 0, $tobool36119 = 0, $n_1121_in = 0, $n_1121 = 0, $clust39 = 0, $13 = 0, $cmp40 = 0, $call42 = 0, $cmp43 = 0, $14 = 0, $inc48 = 0, $call50 = 0, $tobool52113 = 0, $e_1117_in = 0, $prev_0116 = 0, $e_1117 = 0, $u54 = 0, $to_virt = 0, $15 = 0, $16 = 0, $tobool55 = 0, $call58 = 0, $tobool59 = 0, $call61 = 0, $tobool62 = 0, $to_virt65 = 0, $17 = 0, $tobool66 = 0, $tail70 = 0, $18 = 0, $u71 = 0, $rank = 0, $19 = 0, $20 = 0, $head72 = 0, $21 = 0, $u73 = 0, $rank74 = 0, $22 = 0, $23 = 0, $cmp75 = 0, $tobool82 = 0, $tail84 = 0, $24 = 0, $25 = 0, $tail85 = 0, $26 = 0, $cmp86 = 0, $head89 = 0, $27 = 0, $28 = 0, $head90 = 0, $29 = 0, $cmp91 = 0, $u95 = 0, $rank96 = 0, $30 = 0, $31 = 0, $u98 = 0, $rank99 = 0, $32 = 0, $33 = 0, $cmp100 = 0, $label = 0, $34 = 0, $35 = 0, $cmp105 = 0, $label109 = 0, $36 = 0, $cmp110 = 0, $call113 = 0, $tobool114 = 0, $37 = 0, $tobool116 = 0, $38 = 0, $to_virt121 = 0, $39 = 0, $tail125 = 0, $40 = 0, $head126 = 0, $41 = 0, $cmp127 = 0, $42 = 0, $call132 = 0, $43 = 0, $44 = 0, $call134 = 0, $45 = 0, $46 = 0, $cmp136 = 0, $47 = 0, $48 = 0, $cmp139 = 0, $rank145 = 0, $49 = 0, $50 = 0, $rank148 = 0, $51 = 0, $52 = 0, $cmp149 = 0, $cmp159 = 0, $call167 = 0, $53 = 0, $tobool168 = 0, $cmp170 = 0, $or_cond = 0, $u173 = 0, $to_virt174 = 0, $54 = 0, $55 = 0, $cmp175 = 0, $tail178 = 0, $56 = 0, $57 = 0, $head179 = 0, $58 = 0, $59 = 0, $label182 = 0, $60 = 0, $61 = 0, $cmp183 = 0, $label187 = 0, $62 = 0, $63 = 0, $cmp188 = 0, $call191 = 0, $tobool192 = 0, $64 = 0, $tobool194 = 0, $65 = 0, $66 = 0, $67 = 0, $68 = 0, $69 = 0, $70 = 0, $71 = 0, $prev_1 = 0, $call209 = 0, $tobool52 = 0, $call212 = 0, $tobool36 = 0, $root = 0, $72 = 0, $cmp214 = 0, $list = 0, $73 = 0, $tobool218 = 0, $74 = 0, $call222 = 0, $call223 = 0, $call222_sink = 0, $75 = 0, $76 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ HEAP32[$nlist >> 2] = 0;
+ $n_nodes = $g + 244 | 0;
+ HEAP32[$n_nodes >> 2] = 0;
+ $0 = $g;
+ _mark_clusters($0);
+ $n_cluster = $g + 212 | 0;
+ $1 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp126 = ($1 | 0) < 1;
+ if ($cmp126) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $c_0127 = 1;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $2 + ($c_0127 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $4 = $3;
+ _build_skeleton($0, $4);
+ $inc = $c_0127 + 1 | 0;
+ $5 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($5 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $c_0127 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ $6 = $g;
+ $call = _agfstnode($6) | 0;
+ $tobool124 = ($call | 0) == 0;
+ if ($tobool124) {
+ label = 13;
+ break;
+ } else {
+ $n_0_in125 = $call;
+ label = 6;
+ break;
+ }
+ case 6:
+ $call6 = _agfstout($6, $n_0_in125) | 0;
+ $tobool8122 = ($call6 | 0) == 0;
+ if ($tobool8122) {
+ label = 12;
+ break;
+ } else {
+ $e_0_in123 = $call6;
+ label = 7;
+ break;
+ }
+ case 7:
+ $head = $e_0_in123 + 12 | 0;
+ $7 = HEAP32[$head >> 2] | 0;
+ $8 = $7;
+ $weight_class = $8 + 166 | 0;
+ $9 = HEAP8[$weight_class] | 0;
+ $cmp11 = $9 << 24 >> 24 < 3;
+ if ($cmp11) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $inc16 = $9 + 1 & 255;
+ HEAP8[$weight_class] = $inc16;
+ label = 9;
+ break;
+ case 9:
+ $tail = $e_0_in123 + 16 | 0;
+ $10 = HEAP32[$tail >> 2] | 0;
+ $11 = $10;
+ $weight_class18 = $11 + 166 | 0;
+ $12 = HEAP8[$weight_class18] | 0;
+ $cmp20 = $12 << 24 >> 24 < 3;
+ if ($cmp20) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $inc26 = $12 + 1 & 255;
+ HEAP8[$weight_class18] = $inc26;
+ label = 11;
+ break;
+ case 11:
+ $call29 = _agnxtout($6, $e_0_in123) | 0;
+ $tobool8 = ($call29 | 0) == 0;
+ if ($tobool8) {
+ label = 12;
+ break;
+ } else {
+ $e_0_in123 = $call29;
+ label = 7;
+ break;
+ }
+ case 12:
+ $call32 = _agnxtnode($6, $n_0_in125) | 0;
+ $tobool = ($call32 | 0) == 0;
+ if ($tobool) {
+ label = 13;
+ break;
+ } else {
+ $n_0_in125 = $call32;
+ label = 6;
+ break;
+ }
+ case 13:
+ $call34 = _agfstnode($6) | 0;
+ $tobool36119 = ($call34 | 0) == 0;
+ if ($tobool36119) {
+ label = 57;
+ break;
+ } else {
+ $n_1121_in = $call34;
+ label = 14;
+ break;
+ }
+ case 14:
+ $n_1121 = $n_1121_in;
+ $clust39 = $n_1121_in + 216 | 0;
+ $13 = HEAP32[$clust39 >> 2] | 0;
+ $cmp40 = ($13 | 0) == 0;
+ if ($cmp40) {
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 15:
+ $call42 = _UF_find($n_1121) | 0;
+ $cmp43 = ($n_1121 | 0) == ($call42 | 0);
+ if ($cmp43) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ _fast_node($g, $n_1121);
+ $14 = HEAP32[$n_nodes >> 2] | 0;
+ $inc48 = $14 + 1 | 0;
+ HEAP32[$n_nodes >> 2] = $inc48;
+ label = 17;
+ break;
+ case 17:
+ $call50 = _agfstout($6, $n_1121_in) | 0;
+ $tobool52113 = ($call50 | 0) == 0;
+ if ($tobool52113) {
+ label = 56;
+ break;
+ } else {
+ $prev_0116 = 0;
+ $e_1117_in = $call50;
+ label = 18;
+ break;
+ }
+ case 18:
+ $e_1117 = $e_1117_in;
+ $u54 = $e_1117_in + 24 | 0;
+ $to_virt = $e_1117_in + 188 | 0;
+ $15 = $to_virt;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $tobool55 = ($16 | 0) == 0;
+ if ($tobool55) {
+ label = 19;
+ break;
+ } else {
+ $prev_1 = $e_1117;
+ label = 55;
+ break;
+ }
+ case 19:
+ $call58 = _is_cluster_edge($e_1117) | 0;
+ $tobool59 = ($call58 | 0) == 0;
+ if ($tobool59) {
+ label = 26;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $call61 = _mergeable($prev_0116, $e_1117) | 0;
+ $tobool62 = ($call61 | 0) == 0;
+ if ($tobool62) {
+ label = 25;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $to_virt65 = $prev_0116 + 188 | 0;
+ $17 = HEAP32[$to_virt65 >> 2] | 0;
+ $tobool66 = ($17 | 0) == 0;
+ if ($tobool66) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ _merge_chain($g, $e_1117, $17, 0);
+ _other_edge($e_1117);
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ case 23:
+ $tail70 = $e_1117_in + 16 | 0;
+ $18 = HEAP32[$tail70 >> 2] | 0;
+ $u71 = $18 + 24 | 0;
+ $rank = $u71 + 212 | 0;
+ $19 = $rank;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $head72 = $e_1117_in + 12 | 0;
+ $21 = HEAP32[$head72 >> 2] | 0;
+ $u73 = $21 + 24 | 0;
+ $rank74 = $u73 + 212 | 0;
+ $22 = $rank74;
+ $23 = HEAP32[$22 >> 2] | 0;
+ $cmp75 = ($20 | 0) == ($23 | 0);
+ if ($cmp75) {
+ label = 24;
+ break;
+ } else {
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ }
+ case 24:
+ _merge_oneway($e_1117, $prev_0116);
+ _other_edge($e_1117);
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ case 25:
+ _interclrep($g, $e_1117);
+ $prev_1 = $e_1117;
+ label = 55;
+ break;
+ case 26:
+ $tobool82 = ($prev_0116 | 0) == 0;
+ if ($tobool82) {
+ label = 37;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $tail84 = $e_1117_in + 16 | 0;
+ $24 = HEAP32[$tail84 >> 2] | 0;
+ $25 = $24;
+ $tail85 = $prev_0116 + 16 | 0;
+ $26 = HEAP32[$tail85 >> 2] | 0;
+ $cmp86 = ($25 | 0) == ($26 | 0);
+ if ($cmp86) {
+ label = 28;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 28:
+ $head89 = $e_1117_in + 12 | 0;
+ $27 = HEAP32[$head89 >> 2] | 0;
+ $28 = $27;
+ $head90 = $prev_0116 + 12 | 0;
+ $29 = HEAP32[$head90 >> 2] | 0;
+ $cmp91 = ($28 | 0) == ($29 | 0);
+ if ($cmp91) {
+ label = 29;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 29:
+ $u95 = $24 + 24 | 0;
+ $rank96 = $u95 + 212 | 0;
+ $30 = $rank96;
+ $31 = HEAP32[$30 >> 2] | 0;
+ $u98 = $27 + 24 | 0;
+ $rank99 = $u98 + 212 | 0;
+ $32 = $rank99;
+ $33 = HEAP32[$32 >> 2] | 0;
+ $cmp100 = ($31 | 0) == ($33 | 0);
+ if ($cmp100) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ _merge_oneway($e_1117, $prev_0116);
+ _other_edge($e_1117);
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ case 31:
+ $label = $u54 + 88 | 0;
+ $34 = $label;
+ $35 = HEAP32[$34 >> 2] | 0;
+ $cmp105 = ($35 | 0) == 0;
+ if ($cmp105) {
+ label = 32;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 32:
+ $label109 = $prev_0116 + 112 | 0;
+ $36 = HEAP32[$label109 >> 2] | 0;
+ $cmp110 = ($36 | 0) == 0;
+ if ($cmp110) {
+ label = 33;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 33:
+ $call113 = _ports_eq($e_1117, $prev_0116) | 0;
+ $tobool114 = ($call113 | 0) == 0;
+ if ($tobool114) {
+ label = 37;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $37 = HEAP8[167952] | 0;
+ $tobool116 = $37 << 24 >> 24 == 0;
+ if ($tobool116) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $38 = $u54 + 104 | 0;
+ HEAP8[$38] = 6;
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ case 36:
+ $to_virt121 = $prev_0116 + 188 | 0;
+ $39 = HEAP32[$to_virt121 >> 2] | 0;
+ _merge_chain($g, $e_1117, $39, 1);
+ _other_edge($e_1117);
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ case 37:
+ $tail125 = $e_1117_in + 16 | 0;
+ $40 = HEAP32[$tail125 >> 2] | 0;
+ $head126 = $e_1117_in + 12 | 0;
+ $41 = HEAP32[$head126 >> 2] | 0;
+ $cmp127 = ($40 | 0) == ($41 | 0);
+ if ($cmp127) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ _other_edge($e_1117);
+ $prev_1 = $e_1117;
+ label = 55;
+ break;
+ case 39:
+ $42 = $40;
+ $call132 = _UF_find($42) | 0;
+ $43 = HEAP32[$head126 >> 2] | 0;
+ $44 = $43;
+ $call134 = _UF_find($44) | 0;
+ $45 = HEAP32[$tail125 >> 2] | 0;
+ $46 = $45;
+ $cmp136 = ($46 | 0) == ($call132 | 0);
+ if ($cmp136) {
+ label = 40;
+ break;
+ } else {
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ }
+ case 40:
+ $47 = HEAP32[$head126 >> 2] | 0;
+ $48 = $47;
+ $cmp139 = ($48 | 0) == ($call134 | 0);
+ if ($cmp139) {
+ label = 41;
+ break;
+ } else {
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ }
+ case 41:
+ $rank145 = $45 + 236 | 0;
+ $49 = $rank145;
+ $50 = HEAP32[$49 >> 2] | 0;
+ $rank148 = $47 + 236 | 0;
+ $51 = $rank148;
+ $52 = HEAP32[$51 >> 2] | 0;
+ $cmp149 = ($50 | 0) == ($52 | 0);
+ if ($cmp149) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ _flat_edge($g, $e_1117);
+ $prev_1 = $e_1117;
+ label = 55;
+ break;
+ case 43:
+ $cmp159 = ($52 | 0) > ($50 | 0);
+ if ($cmp159) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 44:
+ _make_chain($g, $46, $48, $e_1117);
+ $prev_1 = $e_1117;
+ label = 55;
+ break;
+ case 45:
+ $call167 = _agfindedge($6, $47, $45) | 0;
+ $53 = $call167;
+ $tobool168 = ($call167 | 0) == 0;
+ $cmp170 = ($call167 | 0) == ($e_1117_in | 0);
+ $or_cond = $tobool168 | $cmp170;
+ if ($or_cond) {
+ label = 54;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $u173 = $call167 + 24 | 0;
+ $to_virt174 = $u173 + 164 | 0;
+ $54 = $to_virt174;
+ $55 = HEAP32[$54 >> 2] | 0;
+ $cmp175 = ($55 | 0) == 0;
+ if ($cmp175) {
+ label = 47;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 47:
+ $tail178 = $call167 + 16 | 0;
+ $56 = HEAP32[$tail178 >> 2] | 0;
+ $57 = $56;
+ $head179 = $call167 + 12 | 0;
+ $58 = HEAP32[$head179 >> 2] | 0;
+ $59 = $58;
+ _make_chain($g, $57, $59, $53);
+ label = 48;
+ break;
+ case 48:
+ $label182 = $u54 + 88 | 0;
+ $60 = $label182;
+ $61 = HEAP32[$60 >> 2] | 0;
+ $cmp183 = ($61 | 0) == 0;
+ if ($cmp183) {
+ label = 49;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 49:
+ $label187 = $u173 + 88 | 0;
+ $62 = $label187;
+ $63 = HEAP32[$62 >> 2] | 0;
+ $cmp188 = ($63 | 0) == 0;
+ if ($cmp188) {
+ label = 50;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 50:
+ $call191 = _ports_eq($e_1117, $53) | 0;
+ $tobool192 = ($call191 | 0) == 0;
+ if ($tobool192) {
+ label = 54;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $64 = HEAP8[167952] | 0;
+ $tobool194 = $64 << 24 >> 24 == 0;
+ if ($tobool194) {
+ label = 53;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $65 = $u54 + 104 | 0;
+ HEAP8[$65] = 6;
+ $66 = $u173 + 145 | 0;
+ HEAP8[$66] = 1;
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ case 53:
+ _other_edge($e_1117);
+ $67 = HEAP32[$54 >> 2] | 0;
+ _merge_chain($g, $e_1117, $67, 1);
+ $prev_1 = $prev_0116;
+ label = 55;
+ break;
+ case 54:
+ $68 = HEAP32[$head126 >> 2] | 0;
+ $69 = $68;
+ $70 = HEAP32[$tail125 >> 2] | 0;
+ $71 = $70;
+ _make_chain($g, $69, $71, $e_1117);
+ $prev_1 = $e_1117;
+ label = 55;
+ break;
+ case 55:
+ $call209 = _agnxtout($6, $e_1117_in) | 0;
+ $tobool52 = ($call209 | 0) == 0;
+ if ($tobool52) {
+ label = 56;
+ break;
+ } else {
+ $prev_0116 = $prev_1;
+ $e_1117_in = $call209;
+ label = 18;
+ break;
+ }
+ case 56:
+ $call212 = _agnxtnode($6, $n_1121_in) | 0;
+ $tobool36 = ($call212 | 0) == 0;
+ if ($tobool36) {
+ label = 57;
+ break;
+ } else {
+ $n_1121_in = $call212;
+ label = 14;
+ break;
+ }
+ case 57:
+ $root = $g + 32 | 0;
+ $72 = HEAP32[$root >> 2] | 0;
+ $cmp214 = ($72 | 0) == ($g | 0);
+ if ($cmp214) {
+ label = 62;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $list = $g + 228 | 0;
+ $73 = HEAP32[$list >> 2] | 0;
+ $tobool218 = ($73 | 0) == 0;
+ if ($tobool218) {
+ label = 60;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ $74 = $73;
+ $call222 = _grealloc($74, 4) | 0;
+ $call222_sink = $call222;
+ label = 61;
+ break;
+ case 60:
+ $call223 = _gmalloc(4) | 0;
+ $call222_sink = $call223;
+ label = 61;
+ break;
+ case 61:
+ $75 = $call222_sink;
+ HEAP32[$list >> 2] = $75;
+ $76 = HEAP32[$nlist >> 2] | 0;
+ HEAP32[$75 >> 2] = $76;
+ label = 62;
+ break;
+ case 62:
+ return;
+ }
+}
+function _interclrep($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $call = 0, $head = 0, $1 = 0, $call1 = 0, $rank = 0, $2 = 0, $rank3 = 0, $3 = 0, $cmp = 0, $call_call1 = 0, $call1_call = 0, $clust = 0, $4 = 0, $clust6 = 0, $5 = 0, $cmp7 = 0, $call9 = 0, $tobool = 0, $rank13 = 0, $6 = 0, $rank15 = 0, $7 = 0, $cmp16 = 0, $to_virt = 0, $ve_023 = 0, $tobool2024 = 0, $ve_025 = 0, $head21 = 0, $8 = 0, $rank23 = 0, $9 = 0, $10 = 0, $cmp26 = 0, $edge_type = 0, $11 = 0, $list = 0, $12 = 0, $ve_0 = 0, $tobool20 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $call = _leader_of($0) | 0;
+ $head = $e + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $call1 = _leader_of($1) | 0;
+ $rank = $call + 236 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $rank3 = $call1 + 236 | 0;
+ $3 = HEAP32[$rank3 >> 2] | 0;
+ $cmp = ($2 | 0) > ($3 | 0);
+ $call_call1 = $cmp ? $call : $call1;
+ $call1_call = $cmp ? $call1 : $call;
+ $clust = $call1_call + 216 | 0;
+ $4 = HEAP32[$clust >> 2] | 0;
+ $clust6 = $call_call1 + 216 | 0;
+ $5 = HEAP32[$clust6 >> 2] | 0;
+ $cmp7 = ($4 | 0) == ($5 | 0);
+ if ($cmp7) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call9 = _find_fast_edge($call1_call, $call_call1) | 0;
+ $tobool = ($call9 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _merge_chain($g, $e, $call9, 1);
+ label = 9;
+ break;
+ case 5:
+ $rank13 = $call1_call + 236 | 0;
+ $6 = HEAP32[$rank13 >> 2] | 0;
+ $rank15 = $call_call1 + 236 | 0;
+ $7 = HEAP32[$rank15 >> 2] | 0;
+ $cmp16 = ($6 | 0) == ($7 | 0);
+ if ($cmp16) {
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _make_chain($g, $call1_call, $call_call1, $e);
+ $to_virt = $e + 188 | 0;
+ $ve_023 = HEAP32[$to_virt >> 2] | 0;
+ $tobool2024 = ($ve_023 | 0) == 0;
+ if ($tobool2024) {
+ label = 9;
+ break;
+ } else {
+ $ve_025 = $ve_023;
+ label = 7;
+ break;
+ }
+ case 7:
+ $head21 = $ve_025 + 12 | 0;
+ $8 = HEAP32[$head21 >> 2] | 0;
+ $rank23 = $8 + 236 | 0;
+ $9 = HEAP32[$rank23 >> 2] | 0;
+ $10 = HEAP32[$rank15 >> 2] | 0;
+ $cmp26 = ($9 | 0) > ($10 | 0);
+ if ($cmp26) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $edge_type = $ve_025 + 128 | 0;
+ HEAP8[$edge_type] = 5;
+ $11 = HEAP32[$head21 >> 2] | 0;
+ $list = $11 + 184 | 0;
+ $12 = HEAP32[$list >> 2] | 0;
+ $ve_0 = HEAP32[$12 >> 2] | 0;
+ $tobool20 = ($ve_0 | 0) == 0;
+ if ($tobool20) {
+ label = 9;
+ break;
+ } else {
+ $ve_025 = $ve_0;
+ label = 7;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _label_vnode($g, $orig) {
+ $g = $g | 0;
+ $orig = $orig | 0;
+ var $label = 0, $0 = 0, $dimen_sroa_0_0__idx = 0, $dimen_sroa_0_0_copyload = 0.0, $dimen_sroa_1_8__idx3 = 0, $dimen_sroa_1_8_copyload = 0.0, $call = 0, $1 = 0, $label5 = 0, $graph = 0, $2 = 0, $root = 0, $3 = 0, $nodesep = 0, $4 = 0, $conv = 0.0, $lw = 0, $label_ontop = 0, $5 = 0, $tobool = 0, $root9 = 0, $6 = 0, $rankdir = 0, $7 = 0, $and11 = 0, $tobool12 = 0, $ht18 = 0, $rw = 0, $rw21 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $label = $orig + 112 | 0;
+ $0 = HEAP32[$label >> 2] | 0;
+ $dimen_sroa_0_0__idx = $0 + 24 | 0;
+ $dimen_sroa_0_0_copyload = +HEAPF64[$dimen_sroa_0_0__idx >> 3];
+ $dimen_sroa_1_8__idx3 = $0 + 32 | 0;
+ $dimen_sroa_1_8_copyload = +HEAPF64[$dimen_sroa_1_8__idx3 >> 3];
+ $call = _virtual_node($g) | 0;
+ $1 = HEAP32[$label >> 2] | 0;
+ $label5 = $call + 120 | 0;
+ HEAP32[$label5 >> 2] = $1;
+ $graph = $call + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $root = $2 + 32 | 0;
+ $3 = HEAP32[$root >> 2] | 0;
+ $nodesep = $3 + 260 | 0;
+ $4 = HEAP32[$nodesep >> 2] | 0;
+ $conv = +($4 | 0);
+ $lw = $call + 104 | 0;
+ HEAPF64[$lw >> 3] = $conv;
+ $label_ontop = $orig + 130 | 0;
+ $5 = HEAP8[$label_ontop] | 0;
+ $tobool = $5 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $root9 = $g + 32 | 0;
+ $6 = HEAP32[$root9 >> 2] | 0;
+ $rankdir = $6 + 156 | 0;
+ $7 = HEAP32[$rankdir >> 2] | 0;
+ $and11 = $7 & 1;
+ $tobool12 = ($and11 | 0) == 0;
+ $ht18 = $call + 96 | 0;
+ if ($tobool12) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAPF64[$ht18 >> 3] = $dimen_sroa_0_0_copyload;
+ $rw = $call + 112 | 0;
+ HEAPF64[$rw >> 3] = $dimen_sroa_1_8_copyload;
+ label = 6;
+ break;
+ case 5:
+ HEAPF64[$ht18 >> 3] = $dimen_sroa_1_8_copyload;
+ $rw21 = $call + 112 | 0;
+ HEAPF64[$rw21 >> 3] = $dimen_sroa_0_0_copyload;
+ label = 6;
+ break;
+ case 6:
+ return $call | 0;
+ }
+ return 0;
+}
+function _plain_vnode($g) {
+ $g = $g | 0;
+ var $call = 0;
+ $call = _virtual_node($g) | 0;
+ _incr_width($g, $call);
+ return $call | 0;
+}
+function _merge_chain($g, $e, $f, $flag) {
+ $g = $g | 0;
+ $e = $e | 0;
+ $f = $f | 0;
+ $flag = $flag | 0;
+ var $tail = 0, $0 = 0, $rank = 0, $1 = 0, $head = 0, $2 = 0, $rank2 = 0, $3 = 0, $cmp = 0, $_ = 0, $to_virt = 0, $4 = 0, $cmp10 = 0, $tobool = 0, $xpenalty = 0, $weight = 0, $count = 0, $rep_0 = 0, $5 = 0, $count18 = 0, $6 = 0, $add = 0, $7 = 0, $xpenalty24 = 0, $8 = 0, $add26 = 0, $9 = 0.0, $weight30 = 0, $10 = 0.0, $add31 = 0.0, $head32 = 0, $11 = 0, $rank34 = 0, $12 = 0, $cmp35 = 0, $13 = 0, $list = 0, $14 = 0, $15 = 0, $tobool42 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $rank = $0 + 236 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $head = $e + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $rank2 = $2 + 236 | 0;
+ $3 = HEAP32[$rank2 >> 2] | 0;
+ $cmp = ($1 | 0) > ($3 | 0);
+ $_ = $cmp ? $1 : $3;
+ $to_virt = $e + 188 | 0;
+ $4 = HEAP32[$to_virt >> 2] | 0;
+ $cmp10 = ($4 | 0) == 0;
+ if ($cmp10) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ ___assert_func(153128, 149, 164032, 155184);
+ case 4:
+ HEAP32[$to_virt >> 2] = $f;
+ $tobool = ($flag | 0) == 0;
+ $xpenalty = $e + 170 | 0;
+ $weight = $e + 172 | 0;
+ $count = $e + 184 | 0;
+ $rep_0 = $f;
+ label = 5;
+ break;
+ case 5:
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $5 = HEAP16[$count >> 1] | 0;
+ $count18 = $rep_0 + 184 | 0;
+ $6 = HEAP16[$count18 >> 1] | 0;
+ $add = $6 + $5 & 65535;
+ HEAP16[$count18 >> 1] = $add;
+ label = 7;
+ break;
+ case 7:
+ $7 = HEAP16[$xpenalty >> 1] | 0;
+ $xpenalty24 = $rep_0 + 170 | 0;
+ $8 = HEAP16[$xpenalty24 >> 1] | 0;
+ $add26 = $8 + $7 & 65535;
+ HEAP16[$xpenalty24 >> 1] = $add26;
+ $9 = +HEAPF32[$weight >> 2];
+ $weight30 = $rep_0 + 172 | 0;
+ $10 = +HEAPF32[$weight30 >> 2];
+ $add31 = $9 + $10;
+ HEAPF32[$weight30 >> 2] = $add31;
+ $head32 = $rep_0 + 12 | 0;
+ $11 = HEAP32[$head32 >> 2] | 0;
+ $rank34 = $11 + 236 | 0;
+ $12 = HEAP32[$rank34 >> 2] | 0;
+ $cmp35 = ($12 | 0) == ($_ | 0);
+ if ($cmp35) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _incr_width($g, $11);
+ $13 = HEAP32[$head32 >> 2] | 0;
+ $list = $13 + 184 | 0;
+ $14 = HEAP32[$list >> 2] | 0;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $tobool42 = ($15 | 0) == 0;
+ if ($tobool42) {
+ label = 9;
+ break;
+ } else {
+ $rep_0 = $15;
+ label = 5;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _make_chain($g, $from, $to, $orig) {
+ $g = $g | 0;
+ $from = $from | 0;
+ $to = $to | 0;
+ $orig = $orig | 0;
+ var $label = 0, $0 = 0, $tobool = 0, $rank = 0, $1 = 0, $rank4 = 0, $2 = 0, $add = 0, $div = 0, $label_rank_0 = 0, $to_virt = 0, $3 = 0, $cmp = 0, $rank7 = 0, $4 = 0, $r_016 = 0, $rank10 = 0, $5 = 0, $cmp1117 = 0, $6 = 0, $r_019 = 0, $u_018 = 0, $cmp14 = 0, $cmp16 = 0, $call = 0, $call19 = 0, $v_0 = 0, $rank22 = 0, $v_1 = 0, $call25 = 0, $r_0 = 0, $7 = 0, $cmp11 = 0, $8 = 0, $cmp28 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $label = $orig + 112 | 0;
+ $0 = HEAP32[$label >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $label_rank_0 = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $rank = $from + 236 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $rank4 = $to + 236 | 0;
+ $2 = HEAP32[$rank4 >> 2] | 0;
+ $add = $2 + $1 | 0;
+ $div = ($add | 0) / 2 & -1;
+ $label_rank_0 = $div;
+ label = 4;
+ break;
+ case 4:
+ $to_virt = $orig + 188 | 0;
+ $3 = HEAP32[$to_virt >> 2] | 0;
+ $cmp = ($3 | 0) == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ ___assert_func(153128, 90, 164112, 126200);
+ case 6:
+ $rank7 = $from + 236 | 0;
+ $4 = HEAP32[$rank7 >> 2] | 0;
+ $r_016 = $4 + 1 | 0;
+ $rank10 = $to + 236 | 0;
+ $5 = HEAP32[$rank10 >> 2] | 0;
+ $cmp1117 = ($r_016 | 0) > ($5 | 0);
+ if ($cmp1117) {
+ label = 13;
+ break;
+ } else {
+ $u_018 = $from;
+ $r_019 = $r_016;
+ $6 = $5;
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp14 = ($r_019 | 0) < ($6 | 0);
+ if ($cmp14) {
+ label = 8;
+ break;
+ } else {
+ $v_1 = $to;
+ label = 12;
+ break;
+ }
+ case 8:
+ $cmp16 = ($r_019 | 0) == ($label_rank_0 | 0);
+ if ($cmp16) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $call = _label_vnode($g, $orig) | 0;
+ $v_0 = $call;
+ label = 11;
+ break;
+ case 10:
+ $call19 = _plain_vnode($g) | 0;
+ $v_0 = $call19;
+ label = 11;
+ break;
+ case 11:
+ $rank22 = $v_0 + 236 | 0;
+ HEAP32[$rank22 >> 2] = $r_019;
+ $v_1 = $v_0;
+ label = 12;
+ break;
+ case 12:
+ $call25 = _virtual_edge($u_018, $v_1, $orig) | 0;
+ _virtual_weight($call25);
+ $r_0 = $r_019 + 1 | 0;
+ $7 = HEAP32[$rank10 >> 2] | 0;
+ $cmp11 = ($r_0 | 0) > ($7 | 0);
+ if ($cmp11) {
+ label = 13;
+ break;
+ } else {
+ $u_018 = $v_1;
+ $r_019 = $r_0;
+ $6 = $7;
+ label = 7;
+ break;
+ }
+ case 13:
+ $8 = HEAP32[$to_virt >> 2] | 0;
+ $cmp28 = ($8 | 0) == 0;
+ if ($cmp28) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ ___assert_func(153128, 104, 164112, 117208);
+ case 15:
+ return;
+ }
+}
+function _leader_of($v) {
+ $v = $v | 0;
+ var $ranktype = 0, $0 = 0, $cmp = 0, $call = 0, $clust3 = 0, $1 = 0, $rank = 0, $2 = 0, $rankleader = 0, $3 = 0, $arrayidx = 0, $4 = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ranktype = $v + 165 | 0;
+ $0 = HEAP8[$ranktype] | 0;
+ $cmp = $0 << 24 >> 24 == 7;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _UF_find($v) | 0;
+ $rv_0 = $call;
+ label = 5;
+ break;
+ case 4:
+ $clust3 = $v + 216 | 0;
+ $1 = HEAP32[$clust3 >> 2] | 0;
+ $rank = $v + 236 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $rankleader = $1 + 280 | 0;
+ $3 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx = $3 + ($2 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $rv_0 = $4;
+ label = 5;
+ break;
+ case 5:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _make_interclust_chain($from, $to, $orig) {
+ $from = $from | 0;
+ $to = $to | 0;
+ $orig = $orig | 0;
+ var $call = 0, $call1 = 0;
+ $call = _map_interclust_node($from) | 0;
+ $call1 = _map_interclust_node($to) | 0;
+ _map_path($call, $call1, $orig, HEAP32[$orig + 188 >> 2] | 0, ($call | 0) == ($from | 0) & ($call1 | 0) == ($to | 0) ? 1 : 5);
+ return;
+}
+function _expand_cluster($subg) {
+ $subg = $subg | 0;
+ var $0 = 0;
+ $0 = $subg;
+ _class2($0);
+ HEAP32[$subg + 232 >> 2] = 1;
+ HEAP32[HEAP32[$subg + 228 >> 2] >> 2] = HEAP32[$subg + 220 >> 2] | 0;
+ _allocate_ranks($0);
+ _build_ranks($0, 0);
+ _merge_ranks($subg);
+ _interclexp($subg);
+ _remove_rankleaders($subg);
+ return;
+}
+function _merge_ranks($subg) {
+ $subg = $subg | 0;
+ var $root1 = 0, $0 = 0, $minrank = 0, $1 = 0, $cmp = 0, $conv = 0, $sub = 0, $rank = 0, $2 = 0, $valid = 0, $3 = 0, $conv9 = 0, $maxrank = 0, $4 = 0, $cmp1244 = 0, $rank15 = 0, $rankleader = 0, $rank47 = 0, $rank34 = 0, $5 = 0, $r_045 = 0, $6 = 0, $n = 0, $7 = 0, $8 = 0, $arrayidx18 = 0, $9 = 0, $order = 0, $10 = 0, $11 = 0, $n2439 = 0, $12 = 0, $cmp2540 = 0, $13 = 0, $i_042 = 0, $pos_041 = 0, $v31 = 0, $14 = 0, $arrayidx32 = 0, $15 = 0, $16 = 0, $v36 = 0, $17 = 0, $arrayidx37 = 0, $inc = 0, $order39 = 0, $18 = 0, $graph = 0, $19 = 0, $20 = 0, $21 = 0, $22 = 0, $n_nodes = 0, $23 = 0, $inc44 = 0, $inc45 = 0, $24 = 0, $n24 = 0, $25 = 0, $cmp25 = 0, $_lcssa = 0, $26 = 0, $v49 = 0, $27 = 0, $add_ptr = 0, $v53 = 0, $28 = 0, $valid57 = 0, $inc59 = 0, $29 = 0, $conv11 = 0, $cmp12 = 0, $r_0_lcssa = 0, $maxrank62 = 0, $30 = 0, $conv63 = 0, $cmp64 = 0, $rank68 = 0, $31 = 0, $valid70 = 0, $expanded = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root1 = $subg + 32 | 0;
+ $0 = HEAP32[$root1 >> 2] | 0;
+ $minrank = $subg + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $cmp = $1 << 16 >> 16 > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $conv = $1 << 16 >> 16;
+ $sub = $conv - 1 | 0;
+ $rank = $0 + 224 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $valid = $2 + ($sub * 44 & -1) + 33 | 0;
+ HEAP8[$valid] = 0;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP16[$minrank >> 1] | 0;
+ $conv9 = $3 << 16 >> 16;
+ $maxrank = $subg + 250 | 0;
+ $4 = HEAP16[$maxrank >> 1] | 0;
+ $cmp1244 = $3 << 16 >> 16 > $4 << 16 >> 16;
+ if ($cmp1244) {
+ $r_0_lcssa = $conv9;
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $rank15 = $subg + 224 | 0;
+ $rankleader = $subg + 280 | 0;
+ $rank47 = $0 + 224 | 0;
+ $rank34 = $0 + 224 | 0;
+ $5 = $subg;
+ $r_045 = $conv9;
+ label = 6;
+ break;
+ case 6:
+ $6 = HEAP32[$rank15 >> 2] | 0;
+ $n = $6 + ($r_045 * 44 & -1) | 0;
+ $7 = HEAP32[$n >> 2] | 0;
+ $8 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx18 = $8 + ($r_045 << 2) | 0;
+ $9 = HEAP32[$arrayidx18 >> 2] | 0;
+ $order = $9 + 240 | 0;
+ $10 = HEAP32[$order >> 2] | 0;
+ _make_slots($0, $r_045, $10, $7);
+ $11 = HEAP32[$rank15 >> 2] | 0;
+ $n2439 = $11 + ($r_045 * 44 & -1) | 0;
+ $12 = HEAP32[$n2439 >> 2] | 0;
+ $cmp2540 = ($12 | 0) > 0;
+ if ($cmp2540) {
+ $pos_041 = $10;
+ $i_042 = 0;
+ $13 = $11;
+ label = 7;
+ break;
+ } else {
+ $_lcssa = $11;
+ label = 8;
+ break;
+ }
+ case 7:
+ $v31 = $13 + ($r_045 * 44 & -1) + 4 | 0;
+ $14 = HEAP32[$v31 >> 2] | 0;
+ $arrayidx32 = $14 + ($i_042 << 2) | 0;
+ $15 = HEAP32[$arrayidx32 >> 2] | 0;
+ $16 = HEAP32[$rank34 >> 2] | 0;
+ $v36 = $16 + ($r_045 * 44 & -1) + 4 | 0;
+ $17 = HEAP32[$v36 >> 2] | 0;
+ $arrayidx37 = $17 + ($pos_041 << 2) | 0;
+ HEAP32[$arrayidx37 >> 2] = $15;
+ $inc = $pos_041 + 1 | 0;
+ $order39 = $15 + 240 | 0;
+ HEAP32[$order39 >> 2] = $pos_041;
+ $18 = HEAP32[$root1 >> 2] | 0;
+ $graph = $15 + 20 | 0;
+ HEAP32[$graph >> 2] = $18;
+ $19 = $15;
+ _delete_fast_node($5, $19);
+ $20 = HEAP32[$root1 >> 2] | 0;
+ $21 = $20;
+ _fast_node($21, $19);
+ $22 = HEAP32[$root1 >> 2] | 0;
+ $n_nodes = $22 + 244 | 0;
+ $23 = HEAP32[$n_nodes >> 2] | 0;
+ $inc44 = $23 + 1 | 0;
+ HEAP32[$n_nodes >> 2] = $inc44;
+ $inc45 = $i_042 + 1 | 0;
+ $24 = HEAP32[$rank15 >> 2] | 0;
+ $n24 = $24 + ($r_045 * 44 & -1) | 0;
+ $25 = HEAP32[$n24 >> 2] | 0;
+ $cmp25 = ($inc45 | 0) < ($25 | 0);
+ if ($cmp25) {
+ $pos_041 = $inc;
+ $i_042 = $inc45;
+ $13 = $24;
+ label = 7;
+ break;
+ } else {
+ $_lcssa = $24;
+ label = 8;
+ break;
+ }
+ case 8:
+ $26 = HEAP32[$rank47 >> 2] | 0;
+ $v49 = $26 + ($r_045 * 44 & -1) + 4 | 0;
+ $27 = HEAP32[$v49 >> 2] | 0;
+ $add_ptr = $27 + ($10 << 2) | 0;
+ $v53 = $_lcssa + ($r_045 * 44 & -1) + 4 | 0;
+ HEAP32[$v53 >> 2] = $add_ptr;
+ $28 = HEAP32[$rank47 >> 2] | 0;
+ $valid57 = $28 + ($r_045 * 44 & -1) + 33 | 0;
+ HEAP8[$valid57] = 0;
+ $inc59 = $r_045 + 1 | 0;
+ $29 = HEAP16[$maxrank >> 1] | 0;
+ $conv11 = $29 << 16 >> 16;
+ $cmp12 = ($inc59 | 0) > ($conv11 | 0);
+ if ($cmp12) {
+ $r_0_lcssa = $inc59;
+ label = 9;
+ break;
+ } else {
+ $r_045 = $inc59;
+ label = 6;
+ break;
+ }
+ case 9:
+ $maxrank62 = $0 + 250 | 0;
+ $30 = HEAP16[$maxrank62 >> 1] | 0;
+ $conv63 = $30 << 16 >> 16;
+ $cmp64 = ($r_0_lcssa | 0) < ($conv63 | 0);
+ if ($cmp64) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $rank68 = $0 + 224 | 0;
+ $31 = HEAP32[$rank68 >> 2] | 0;
+ $valid70 = $31 + ($r_0_lcssa * 44 & -1) + 33 | 0;
+ HEAP8[$valid70] = 0;
+ label = 11;
+ break;
+ case 11:
+ $expanded = $subg + 284 | 0;
+ HEAP8[$expanded] = 1;
+ return;
+ }
+}
+function _remove_rankleaders($g) {
+ $g = $g | 0;
+ var $minrank = 0, $0 = 0, $maxrank = 0, $1 = 0, $cmp15 = 0, $conv = 0, $rankleader = 0, $root = 0, $r_016 = 0, $2 = 0, $arrayidx = 0, $3 = 0, $list = 0, $4 = 0, $5 = 0, $tobool12 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $tobool = 0, $list9 = 0, $10 = 0, $11 = 0, $tobool1113 = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $tobool11 = 0, $16 = 0, $17 = 0, $18 = 0, $19 = 0, $arrayidx16 = 0, $inc = 0, $20 = 0, $conv2 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $cmp15 = $0 << 16 >> 16 > $1 << 16 >> 16;
+ if ($cmp15) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rankleader = $g + 280 | 0;
+ $root = $g + 32 | 0;
+ $r_016 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx = $2 + ($r_016 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $list = $3 + 184 | 0;
+ $4 = HEAP32[$list >> 2] | 0;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $tobool12 = ($5 | 0) == 0;
+ if ($tobool12) {
+ label = 6;
+ break;
+ } else {
+ $6 = $5;
+ label = 5;
+ break;
+ }
+ case 5:
+ $7 = $6;
+ _delete_fast_edge($7);
+ $8 = HEAP32[$list >> 2] | 0;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $tobool = ($9 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $6 = $9;
+ label = 5;
+ break;
+ }
+ case 6:
+ $list9 = $3 + 176 | 0;
+ $10 = HEAP32[$list9 >> 2] | 0;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $tobool1113 = ($11 | 0) == 0;
+ if ($tobool1113) {
+ label = 8;
+ break;
+ } else {
+ $12 = $11;
+ label = 7;
+ break;
+ }
+ case 7:
+ $13 = $12;
+ _delete_fast_edge($13);
+ $14 = HEAP32[$list9 >> 2] | 0;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $tobool11 = ($15 | 0) == 0;
+ if ($tobool11) {
+ label = 8;
+ break;
+ } else {
+ $12 = $15;
+ label = 7;
+ break;
+ }
+ case 8:
+ $16 = HEAP32[$root >> 2] | 0;
+ $17 = $16;
+ $18 = $3;
+ _delete_fast_node($17, $18);
+ $19 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx16 = $19 + ($r_016 << 2) | 0;
+ HEAP32[$arrayidx16 >> 2] = 0;
+ $inc = $r_016 + 1 | 0;
+ $20 = HEAP16[$maxrank >> 1] | 0;
+ $conv2 = $20 << 16 >> 16;
+ $cmp = ($inc | 0) > ($conv2 | 0);
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ $r_016 = $inc;
+ label = 4;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _mark_clusters($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool39 = 0, $n_cluster = 0, $1 = 0, $cmp736 = 0, $clust11 = 0, $name23 = 0, $n_0_in40 = 0, $n_0 = 0, $ranktype = 0, $2 = 0, $cmp = 0, $3 = 0, $clust3 = 0, $call4 = 0, $tobool = 0, $c_037 = 0, $4 = 0, $arrayidx = 0, $5 = 0, $6 = 0, $call12 = 0, $tobool1434 = 0, $leader = 0, $7 = 0, $n_1_in35 = 0, $call16 = 0, $u17 = 0, $8 = 0, $9 = 0, $cmp20 = 0, $10 = 0, $11 = 0, $12 = 0, $call24 = 0, $13 = 0, $tobool14 = 0, $14 = 0, $15 = 0, $16 = 0, $clust28 = 0, $17 = 0, $call31 = 0, $tobool3332 = 0, $orig_0_in33 = 0, $to_virt = 0, $18 = 0, $19 = 0, $tobool36 = 0, $e_031 = 0, $head = 0, $20 = 0, $node_type = 0, $21 = 0, $cmp41 = 0, $clust44 = 0, $22 = 0, $list = 0, $23 = 0, $24 = 0, $tobool38 = 0, $call50 = 0, $tobool33 = 0, $inc = 0, $25 = 0, $cmp7 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool39 = ($call | 0) == 0;
+ if ($tobool39) {
+ label = 3;
+ break;
+ } else {
+ $n_0_in40 = $call;
+ label = 5;
+ break;
+ }
+ case 3:
+ $n_cluster = $g + 212 | 0;
+ $1 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp736 = ($1 | 0) < 1;
+ if ($cmp736) {
+ label = 19;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $clust11 = $g + 216 | 0;
+ $name23 = $g + 12 | 0;
+ $c_037 = 1;
+ label = 8;
+ break;
+ case 5:
+ $n_0 = $n_0_in40;
+ $ranktype = $n_0 + 165 | 0;
+ $2 = HEAP8[$ranktype] | 0;
+ $cmp = $2 << 24 >> 24 == 7;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $3 = $n_0_in40;
+ _UF_singleton($3);
+ label = 7;
+ break;
+ case 7:
+ $clust3 = $n_0_in40 + 216 | 0;
+ HEAP32[$clust3 >> 2] = 0;
+ $call4 = _agnxtnode($0, $n_0_in40) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $n_0_in40 = $call4;
+ label = 5;
+ break;
+ }
+ case 8:
+ $4 = HEAP32[$clust11 >> 2] | 0;
+ $arrayidx = $4 + ($c_037 << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $6 = $5;
+ $call12 = _agfstnode($6) | 0;
+ $tobool1434 = ($call12 | 0) == 0;
+ if ($tobool1434) {
+ label = 18;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $leader = $5 + 276 | 0;
+ $7 = $5;
+ $n_1_in35 = $call12;
+ label = 10;
+ break;
+ case 10:
+ $call16 = _agnxtnode($6, $n_1_in35) | 0;
+ $u17 = $n_1_in35 + 24 | 0;
+ $8 = $u17 + 141 | 0;
+ $9 = HEAP8[$8] | 0;
+ $cmp20 = $9 << 24 >> 24 == 0;
+ if ($cmp20) {
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $10 = $n_1_in35 + 12 | 0;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $12 = HEAP32[$name23 >> 2] | 0;
+ $call24 = _agerr(0, 121184, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $11, HEAP32[tempInt + 8 >> 2] = $12, tempInt) | 0) | 0;
+ $13 = $n_1_in35 | 0;
+ _agdelete($7, $13);
+ label = 12;
+ break;
+ case 12:
+ $tobool14 = ($call16 | 0) == 0;
+ if ($tobool14) {
+ label = 18;
+ break;
+ } else {
+ $n_1_in35 = $call16;
+ label = 10;
+ break;
+ }
+ case 13:
+ $14 = HEAP32[$leader >> 2] | 0;
+ $15 = $n_1_in35;
+ $16 = $14;
+ _UF_setname($15, $16);
+ $clust28 = $u17 + 192 | 0;
+ $17 = $clust28;
+ HEAP32[$17 >> 2] = $5;
+ HEAP8[$8] = 7;
+ $call31 = _agfstout($6, $n_1_in35) | 0;
+ $tobool3332 = ($call31 | 0) == 0;
+ if ($tobool3332) {
+ label = 12;
+ break;
+ } else {
+ $orig_0_in33 = $call31;
+ label = 14;
+ break;
+ }
+ case 14:
+ $to_virt = $orig_0_in33 + 188 | 0;
+ $18 = $to_virt;
+ $19 = HEAP32[$18 >> 2] | 0;
+ $tobool36 = ($19 | 0) == 0;
+ if ($tobool36) {
+ label = 17;
+ break;
+ } else {
+ $e_031 = $19;
+ label = 15;
+ break;
+ }
+ case 15:
+ $head = $e_031 + 12 | 0;
+ $20 = HEAP32[$head >> 2] | 0;
+ $node_type = $20 + 162 | 0;
+ $21 = HEAP8[$node_type] | 0;
+ $cmp41 = $21 << 24 >> 24 == 1;
+ if ($cmp41) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $clust44 = $20 + 216 | 0;
+ HEAP32[$clust44 >> 2] = $5;
+ $22 = HEAP32[$head >> 2] | 0;
+ $list = $22 + 184 | 0;
+ $23 = HEAP32[$list >> 2] | 0;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $tobool38 = ($24 | 0) == 0;
+ if ($tobool38) {
+ label = 17;
+ break;
+ } else {
+ $e_031 = $24;
+ label = 15;
+ break;
+ }
+ case 17:
+ $call50 = _agnxtout($6, $orig_0_in33) | 0;
+ $tobool33 = ($call50 | 0) == 0;
+ if ($tobool33) {
+ label = 12;
+ break;
+ } else {
+ $orig_0_in33 = $call50;
+ label = 14;
+ break;
+ }
+ case 18:
+ $inc = $c_037 + 1 | 0;
+ $25 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp7 = ($inc | 0) > ($25 | 0);
+ if ($cmp7) {
+ label = 19;
+ break;
+ } else {
+ $c_037 = $inc;
+ label = 8;
+ break;
+ }
+ case 19:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _build_skeleton($g, $subg) {
+ $g = $g | 0;
+ $subg = $subg | 0;
+ var $maxrank = 0, $0 = 0, $conv = 0, $add = 0, $mul = 0, $call = 0, $1 = 0, $rankleader = 0, $minrank = 0, $2 = 0, $3 = 0, $cmp49 = 0, $conv3 = 0, $4 = 0, $subg_c = 0, $prev_051 = 0, $r_050 = 0, $call8 = 0, $5 = 0, $6 = 0, $arrayidx = 0, $7 = 0, $8 = 0, $clust = 0, $tobool = 0, $9 = 0, $call14 = 0, $10 = 0, $11 = 0, $mul17 = 0, $inc = 0, $12 = 0, $conv6 = 0, $cmp = 0, $13 = 0, $call19 = 0, $tobool2146 = 0, $v_0_in47 = 0, $rank24 = 0, $14 = 0, $15 = 0, $16 = 0, $arrayidx27 = 0, $17 = 0, $UF_size = 0, $18 = 0, $inc29 = 0, $call30 = 0, $tobool3244 = 0, $list = 0, $e_0_in45 = 0, $tail = 0, $19 = 0, $rank35 = 0, $20 = 0, $21 = 0, $head = 0, $22 = 0, $rank3841 = 0, $23 = 0, $24 = 0, $cmp3942 = 0, $r_143 = 0, $25 = 0, $26 = 0, $count = 0, $27 = 0, $inc45 = 0, $inc47 = 0, $28 = 0, $rank38 = 0, $29 = 0, $30 = 0, $cmp39 = 0, $call50 = 0, $tobool32 = 0, $call53 = 0, $tobool21 = 0, $31 = 0, $32 = 0, $cmp6239 = 0, $conv57 = 0, $r_240 = 0, $33 = 0, $arrayidx67 = 0, $34 = 0, $UF_size69 = 0, $35 = 0, $cmp70 = 0, $dec = 0, $inc77 = 0, $36 = 0, $conv61 = 0, $cmp62 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $maxrank = $subg + 250 | 0;
+ $0 = HEAP16[$maxrank >> 1] | 0;
+ $conv = $0 << 16 >> 16;
+ $add = $conv << 2;
+ $mul = $add + 8 | 0;
+ $call = _zmalloc($mul) | 0;
+ $1 = $call;
+ $rankleader = $subg + 280 | 0;
+ HEAP32[$rankleader >> 2] = $1;
+ $minrank = $subg + 248 | 0;
+ $2 = HEAP16[$minrank >> 1] | 0;
+ $3 = HEAP16[$maxrank >> 1] | 0;
+ $cmp49 = $2 << 16 >> 16 > $3 << 16 >> 16;
+ if ($cmp49) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv3 = $2 << 16 >> 16;
+ $4 = $g;
+ $subg_c = $subg;
+ $r_050 = $conv3;
+ $prev_051 = 0;
+ label = 4;
+ break;
+ case 4:
+ $call8 = _virtual_node($4) | 0;
+ $5 = $call8;
+ $6 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx = $6 + ($r_050 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $5;
+ $7 = $call8 + 236 | 0;
+ HEAP32[$7 >> 2] = $r_050;
+ $8 = $call8 + 165 | 0;
+ HEAP8[$8] = 7;
+ $clust = $call8 + 216 | 0;
+ HEAP32[$clust >> 2] = $subg_c;
+ $tobool = ($prev_051 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $9 = $prev_051;
+ $call14 = _virtual_edge($9, $call8, 0) | 0;
+ $10 = $call14 + 170 | 0;
+ $11 = HEAP16[$10 >> 1] | 0;
+ $mul17 = $11 * 1e3 & 65535;
+ HEAP16[$10 >> 1] = $mul17;
+ label = 6;
+ break;
+ case 6:
+ $inc = $r_050 + 1 | 0;
+ $12 = HEAP16[$maxrank >> 1] | 0;
+ $conv6 = $12 << 16 >> 16;
+ $cmp = ($inc | 0) > ($conv6 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ $r_050 = $inc;
+ $prev_051 = $5;
+ label = 4;
+ break;
+ }
+ case 7:
+ $13 = $subg;
+ $call19 = _agfstnode($13) | 0;
+ $tobool2146 = ($call19 | 0) == 0;
+ if ($tobool2146) {
+ label = 14;
+ break;
+ } else {
+ $v_0_in47 = $call19;
+ label = 8;
+ break;
+ }
+ case 8:
+ $rank24 = $v_0_in47 + 236 | 0;
+ $14 = $rank24;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $16 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx27 = $16 + ($15 << 2) | 0;
+ $17 = HEAP32[$arrayidx27 >> 2] | 0;
+ $UF_size = $17 + 220 | 0;
+ $18 = HEAP32[$UF_size >> 2] | 0;
+ $inc29 = $18 + 1 | 0;
+ HEAP32[$UF_size >> 2] = $inc29;
+ $call30 = _agfstout($13, $v_0_in47) | 0;
+ $tobool3244 = ($call30 | 0) == 0;
+ if ($tobool3244) {
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $list = $17 + 184 | 0;
+ $e_0_in45 = $call30;
+ label = 10;
+ break;
+ case 10:
+ $tail = $e_0_in45 + 16 | 0;
+ $19 = HEAP32[$tail >> 2] | 0;
+ $rank35 = $19 + 236 | 0;
+ $20 = $rank35;
+ $21 = HEAP32[$20 >> 2] | 0;
+ $head = $e_0_in45 + 12 | 0;
+ $22 = HEAP32[$head >> 2] | 0;
+ $rank3841 = $22 + 236 | 0;
+ $23 = $rank3841;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $cmp3942 = ($21 | 0) < ($24 | 0);
+ if ($cmp3942) {
+ $r_143 = $21;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $25 = HEAP32[$list >> 2] | 0;
+ $26 = HEAP32[$25 >> 2] | 0;
+ $count = $26 + 184 | 0;
+ $27 = HEAP16[$count >> 1] | 0;
+ $inc45 = $27 + 1 & 65535;
+ HEAP16[$count >> 1] = $inc45;
+ $inc47 = $r_143 + 1 | 0;
+ $28 = HEAP32[$head >> 2] | 0;
+ $rank38 = $28 + 236 | 0;
+ $29 = $rank38;
+ $30 = HEAP32[$29 >> 2] | 0;
+ $cmp39 = ($inc47 | 0) < ($30 | 0);
+ if ($cmp39) {
+ $r_143 = $inc47;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call50 = _agnxtout($13, $e_0_in45) | 0;
+ $tobool32 = ($call50 | 0) == 0;
+ if ($tobool32) {
+ label = 13;
+ break;
+ } else {
+ $e_0_in45 = $call50;
+ label = 10;
+ break;
+ }
+ case 13:
+ $call53 = _agnxtnode($13, $v_0_in47) | 0;
+ $tobool21 = ($call53 | 0) == 0;
+ if ($tobool21) {
+ label = 14;
+ break;
+ } else {
+ $v_0_in47 = $call53;
+ label = 8;
+ break;
+ }
+ case 14:
+ $31 = HEAP16[$minrank >> 1] | 0;
+ $32 = HEAP16[$maxrank >> 1] | 0;
+ $cmp6239 = $31 << 16 >> 16 > $32 << 16 >> 16;
+ if ($cmp6239) {
+ label = 19;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $conv57 = $31 << 16 >> 16;
+ $r_240 = $conv57;
+ label = 16;
+ break;
+ case 16:
+ $33 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx67 = $33 + ($r_240 << 2) | 0;
+ $34 = HEAP32[$arrayidx67 >> 2] | 0;
+ $UF_size69 = $34 + 220 | 0;
+ $35 = HEAP32[$UF_size69 >> 2] | 0;
+ $cmp70 = ($35 | 0) > 1;
+ if ($cmp70) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $dec = $35 - 1 | 0;
+ HEAP32[$UF_size69 >> 2] = $dec;
+ label = 18;
+ break;
+ case 18:
+ $inc77 = $r_240 + 1 | 0;
+ $36 = HEAP16[$maxrank >> 1] | 0;
+ $conv61 = $36 << 16 >> 16;
+ $cmp62 = ($inc77 | 0) > ($conv61 | 0);
+ if ($cmp62) {
+ label = 19;
+ break;
+ } else {
+ $r_240 = $inc77;
+ label = 16;
+ break;
+ }
+ case 19:
+ return;
+ }
+}
+function _install_cluster($g, $n, $pass, $q) {
+ $g = $g | 0;
+ $n = $n | 0;
+ $pass = $pass | 0;
+ $q = $q | 0;
+ var $clust1 = 0, $0 = 0, $installed = 0, $1 = 0, $conv = 0, $add = 0, $cmp = 0, $minrank = 0, $2 = 0, $maxrank = 0, $3 = 0, $cmp819 = 0, $conv5 = 0, $rankleader = 0, $4 = 0, $r_020 = 0, $5 = 0, $arrayidx = 0, $6 = 0, $7 = 0, $inc = 0, $8 = 0, $conv7 = 0, $cmp8 = 0, $9 = 0, $10 = 0, $cmp1816 = 0, $conv13 = 0, $rankleader22 = 0, $11 = 0, $r_117 = 0, $12 = 0, $arrayidx23 = 0, $13 = 0, $14 = 0, $inc25 = 0, $15 = 0, $conv17 = 0, $cmp18 = 0, $conv28 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $clust1 = $n + 216 | 0;
+ $0 = HEAP32[$clust1 >> 2] | 0;
+ $installed = $0 + 285 | 0;
+ $1 = HEAP8[$installed] | 0;
+ $conv = $1 << 24 >> 24;
+ $add = $pass + 1 | 0;
+ $cmp = ($conv | 0) == ($add | 0);
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $minrank = $0 + 248 | 0;
+ $2 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $0 + 250 | 0;
+ $3 = HEAP16[$maxrank >> 1] | 0;
+ $cmp819 = $2 << 16 >> 16 > $3 << 16 >> 16;
+ if ($cmp819) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv5 = $2 << 16 >> 16;
+ $rankleader = $0 + 280 | 0;
+ $4 = $g;
+ $r_020 = $conv5;
+ label = 5;
+ break;
+ case 5:
+ $5 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx = $5 + ($r_020 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ $7 = $6;
+ _install_in_rank($4, $7);
+ $inc = $r_020 + 1 | 0;
+ $8 = HEAP16[$maxrank >> 1] | 0;
+ $conv7 = $8 << 16 >> 16;
+ $cmp8 = ($inc | 0) > ($conv7 | 0);
+ if ($cmp8) {
+ label = 6;
+ break;
+ } else {
+ $r_020 = $inc;
+ label = 5;
+ break;
+ }
+ case 6:
+ $9 = HEAP16[$minrank >> 1] | 0;
+ $10 = HEAP16[$maxrank >> 1] | 0;
+ $cmp1816 = $9 << 16 >> 16 > $10 << 16 >> 16;
+ if ($cmp1816) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $conv13 = $9 << 16 >> 16;
+ $rankleader22 = $0 + 280 | 0;
+ $11 = $q;
+ $r_117 = $conv13;
+ label = 8;
+ break;
+ case 8:
+ $12 = HEAP32[$rankleader22 >> 2] | 0;
+ $arrayidx23 = $12 + ($r_117 << 2) | 0;
+ $13 = HEAP32[$arrayidx23 >> 2] | 0;
+ $14 = $13;
+ _enqueue_neighbors($11, $14, $pass);
+ $inc25 = $r_117 + 1 | 0;
+ $15 = HEAP16[$maxrank >> 1] | 0;
+ $conv17 = $15 << 16 >> 16;
+ $cmp18 = ($inc25 | 0) > ($conv17 | 0);
+ if ($cmp18) {
+ label = 9;
+ break;
+ } else {
+ $r_117 = $inc25;
+ label = 8;
+ break;
+ }
+ case 9:
+ $conv28 = $add & 255;
+ HEAP8[$installed] = $conv28;
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _mark_lowclusters($root) {
+ $root = $root | 0;
+ var $0 = 0, $call = 0, $tobool16 = 0, $n_0_in17 = 0, $clust = 0, $call1 = 0, $tobool314 = 0, $orig_0_in15 = 0, $to_virt = 0, $1 = 0, $2 = 0, $tobool6 = 0, $e_013 = 0, $head = 0, $3 = 0, $node_type = 0, $4 = 0, $cmp = 0, $clust11 = 0, $5 = 0, $list = 0, $6 = 0, $7 = 0, $tobool7 = 0, $call14 = 0, $tobool3 = 0, $call16 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $root;
+ $call = _agfstnode($0) | 0;
+ $tobool16 = ($call | 0) == 0;
+ if ($tobool16) {
+ label = 9;
+ break;
+ } else {
+ $n_0_in17 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $n_0_in17 + 216 | 0;
+ HEAP32[$clust >> 2] = 0;
+ $call1 = _agfstout($0, $n_0_in17) | 0;
+ $tobool314 = ($call1 | 0) == 0;
+ if ($tobool314) {
+ label = 8;
+ break;
+ } else {
+ $orig_0_in15 = $call1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $to_virt = $orig_0_in15 + 188 | 0;
+ $1 = $to_virt;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool6 = ($2 | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ $e_013 = $2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $head = $e_013 + 12 | 0;
+ $3 = HEAP32[$head >> 2] | 0;
+ $node_type = $3 + 162 | 0;
+ $4 = HEAP8[$node_type] | 0;
+ $cmp = $4 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $clust11 = $3 + 216 | 0;
+ HEAP32[$clust11 >> 2] = 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $list = $5 + 184 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $tobool7 = ($7 | 0) == 0;
+ if ($tobool7) {
+ label = 7;
+ break;
+ } else {
+ $e_013 = $7;
+ label = 5;
+ break;
+ }
+ case 7:
+ $call14 = _agnxtout($0, $orig_0_in15) | 0;
+ $tobool3 = ($call14 | 0) == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ $orig_0_in15 = $call14;
+ label = 4;
+ break;
+ }
+ case 8:
+ $call16 = _agnxtnode($0, $n_0_in17) | 0;
+ $tobool = ($call16 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ $n_0_in17 = $call16;
+ label = 3;
+ break;
+ }
+ case 9:
+ _mark_lowcluster_basic($root);
+ return;
+ }
+}
+function _mark_lowcluster_basic($g) {
+ $g = $g | 0;
+ var $n_cluster = 0, $0 = 0, $cmp25 = 0, $clust2 = 0, $c_026 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $inc = 0, $3 = 0, $cmp = 0, $4 = 0, $call = 0, $tobool23 = 0, $n_0_in24 = 0, $clust6 = 0, $5 = 0, $cmp7 = 0, $call10 = 0, $tobool1221 = 0, $orig_0_in22 = 0, $to_virt = 0, $6 = 0, $7 = 0, $tobool15 = 0, $e_020 = 0, $head = 0, $8 = 0, $node_type = 0, $9 = 0, $cmp19 = 0, $clust22 = 0, $10 = 0, $cmp23 = 0, $11 = 0, $list = 0, $12 = 0, $13 = 0, $tobool17 = 0, $call34 = 0, $tobool12 = 0, $call37 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp25 = ($0 | 0) < 1;
+ if ($cmp25) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust2 = $g + 216 | 0;
+ $c_026 = 1;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$clust2 >> 2] | 0;
+ $arrayidx = $1 + ($c_026 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _mark_lowcluster_basic($2);
+ $inc = $c_026 + 1 | 0;
+ $3 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($3 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $c_026 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ $4 = $g;
+ $call = _agfstnode($4) | 0;
+ $tobool23 = ($call | 0) == 0;
+ if ($tobool23) {
+ label = 16;
+ break;
+ } else {
+ $n_0_in24 = $call;
+ label = 6;
+ break;
+ }
+ case 6:
+ $clust6 = $n_0_in24 + 216 | 0;
+ $5 = HEAP32[$clust6 >> 2] | 0;
+ $cmp7 = ($5 | 0) == 0;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$clust6 >> 2] = $4;
+ label = 8;
+ break;
+ case 8:
+ $call10 = _agfstout($4, $n_0_in24) | 0;
+ $tobool1221 = ($call10 | 0) == 0;
+ if ($tobool1221) {
+ label = 15;
+ break;
+ } else {
+ $orig_0_in22 = $call10;
+ label = 9;
+ break;
+ }
+ case 9:
+ $to_virt = $orig_0_in22 + 188 | 0;
+ $6 = $to_virt;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $tobool15 = ($7 | 0) == 0;
+ if ($tobool15) {
+ label = 14;
+ break;
+ } else {
+ $e_020 = $7;
+ label = 10;
+ break;
+ }
+ case 10:
+ $head = $e_020 + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $node_type = $8 + 162 | 0;
+ $9 = HEAP8[$node_type] | 0;
+ $cmp19 = $9 << 24 >> 24 == 1;
+ if ($cmp19) {
+ label = 11;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 11:
+ $clust22 = $8 + 216 | 0;
+ $10 = HEAP32[$clust22 >> 2] | 0;
+ $cmp23 = ($10 | 0) == 0;
+ if ($cmp23) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ HEAP32[$clust22 >> 2] = $g;
+ label = 13;
+ break;
+ case 13:
+ $11 = HEAP32[$head >> 2] | 0;
+ $list = $11 + 184 | 0;
+ $12 = HEAP32[$list >> 2] | 0;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $tobool17 = ($13 | 0) == 0;
+ if ($tobool17) {
+ label = 14;
+ break;
+ } else {
+ $e_020 = $13;
+ label = 10;
+ break;
+ }
+ case 14:
+ $call34 = _agnxtout($4, $orig_0_in22) | 0;
+ $tobool12 = ($call34 | 0) == 0;
+ if ($tobool12) {
+ label = 15;
+ break;
+ } else {
+ $orig_0_in22 = $call34;
+ label = 9;
+ break;
+ }
+ case 15:
+ $call37 = _agnxtnode($4, $n_0_in24) | 0;
+ $tobool = ($call37 | 0) == 0;
+ if ($tobool) {
+ label = 16;
+ break;
+ } else {
+ $n_0_in24 = $call37;
+ label = 6;
+ break;
+ }
+ case 16:
+ return;
+ }
+}
+function _make_slots($root, $r, $pos, $d) {
+ $root = $root | 0;
+ $r = $r | 0;
+ $pos = $pos | 0;
+ $d = $d | 0;
+ var $rank = 0, $0 = 0, $v1 = 0, $1 = 0, $cmp = 0, $sub = 0, $i_046 = 0, $2 = 0, $n47 = 0, $3 = 0, $cmp548 = 0, $i_050 = 0, $i_0_in49 = 0, $arrayidx6 = 0, $4 = 0, $sub8 = 0, $order = 0, $arrayidx12 = 0, $i_0 = 0, $5 = 0, $n = 0, $6 = 0, $cmp5 = 0, $_lcssa = 0, $add17 = 0, $sub18 = 0, $7 = 0, $n2343 = 0, $8 = 0, $cmp2444 = 0, $i_145 = 0, $arrayidx26 = 0, $inc28 = 0, $9 = 0, $n23 = 0, $10 = 0, $cmp24 = 0, $n33 = 0, $11 = 0, $i_255 = 0, $cmp3656 = 0, $add39 = 0, $cmp5153 = 0, $i_257 = 0, $arrayidx38 = 0, $12 = 0, $sub40 = 0, $order42 = 0, $arrayidx45 = 0, $i_2 = 0, $cmp36 = 0, $13 = 0, $scevgep = 0, $scevgep59 = 0, $14 = 0, $15 = 0, $sub57 = 0, $16 = 0, $n61 = 0, $17 = 0, $add62 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $root + 224 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $v1 = $0 + ($r * 44 & -1) + 4 | 0;
+ $1 = HEAP32[$v1 >> 2] | 0;
+ $cmp = ($d | 0) < 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $sub = $pos - $d | 0;
+ $i_046 = $sub + 1 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $n47 = $2 + ($r * 44 & -1) | 0;
+ $3 = HEAP32[$n47 >> 2] | 0;
+ $cmp548 = ($i_046 | 0) < ($3 | 0);
+ if ($cmp548) {
+ $i_0_in49 = $sub;
+ $i_050 = $i_046;
+ label = 4;
+ break;
+ } else {
+ $_lcssa = $3;
+ label = 5;
+ break;
+ }
+ case 4:
+ $arrayidx6 = $1 + ($i_050 << 2) | 0;
+ $4 = HEAP32[$arrayidx6 >> 2] | 0;
+ $sub8 = $i_0_in49 + $d | 0;
+ $order = $4 + 240 | 0;
+ HEAP32[$order >> 2] = $sub8;
+ $arrayidx12 = $1 + ($sub8 << 2) | 0;
+ HEAP32[$arrayidx12 >> 2] = $4;
+ $i_0 = $i_050 + 1 | 0;
+ $5 = HEAP32[$rank >> 2] | 0;
+ $n = $5 + ($r * 44 & -1) | 0;
+ $6 = HEAP32[$n >> 2] | 0;
+ $cmp5 = ($i_0 | 0) < ($6 | 0);
+ if ($cmp5) {
+ $i_0_in49 = $i_050;
+ $i_050 = $i_0;
+ label = 4;
+ break;
+ } else {
+ $_lcssa = $6;
+ label = 5;
+ break;
+ }
+ case 5:
+ $add17 = $d - 1 | 0;
+ $sub18 = $add17 + $_lcssa | 0;
+ $7 = HEAP32[$rank >> 2] | 0;
+ $n2343 = $7 + ($r * 44 & -1) | 0;
+ $8 = HEAP32[$n2343 >> 2] | 0;
+ $cmp2444 = ($sub18 | 0) < ($8 | 0);
+ if ($cmp2444) {
+ $i_145 = $sub18;
+ label = 6;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 6:
+ $arrayidx26 = $1 + ($i_145 << 2) | 0;
+ HEAP32[$arrayidx26 >> 2] = 0;
+ $inc28 = $i_145 + 1 | 0;
+ $9 = HEAP32[$rank >> 2] | 0;
+ $n23 = $9 + ($r * 44 & -1) | 0;
+ $10 = HEAP32[$n23 >> 2] | 0;
+ $cmp24 = ($inc28 | 0) < ($10 | 0);
+ if ($cmp24) {
+ $i_145 = $inc28;
+ label = 6;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 7:
+ $n33 = $0 + ($r * 44 & -1) | 0;
+ $11 = HEAP32[$n33 >> 2] | 0;
+ $i_255 = $11 - 1 | 0;
+ $cmp3656 = ($i_255 | 0) > ($pos | 0);
+ if ($cmp3656) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $add39 = $d - 1 | 0;
+ $i_257 = $i_255;
+ label = 10;
+ break;
+ case 9:
+ $cmp5153 = ($d | 0) > 1;
+ if ($cmp5153) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 10:
+ $arrayidx38 = $1 + ($i_257 << 2) | 0;
+ $12 = HEAP32[$arrayidx38 >> 2] | 0;
+ $sub40 = $add39 + $i_257 | 0;
+ $order42 = $12 + 240 | 0;
+ HEAP32[$order42 >> 2] = $sub40;
+ $arrayidx45 = $1 + ($sub40 << 2) | 0;
+ HEAP32[$arrayidx45 >> 2] = $12;
+ $i_2 = $i_257 - 1 | 0;
+ $cmp36 = ($i_2 | 0) > ($pos | 0);
+ if ($cmp36) {
+ $i_257 = $i_2;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 11:
+ $13 = $pos + 1 | 0;
+ $scevgep = $1 + ($13 << 2) | 0;
+ $scevgep59 = $scevgep;
+ $14 = $d << 2;
+ $15 = $14 - 4 | 0;
+ _memset($scevgep59 | 0, 0, $15 | 0);
+ label = 12;
+ break;
+ case 12:
+ $sub57 = $d - 1 | 0;
+ $16 = HEAP32[$rank >> 2] | 0;
+ $n61 = $16 + ($r * 44 & -1) | 0;
+ $17 = HEAP32[$n61 >> 2] | 0;
+ $add62 = $sub57 + $17 | 0;
+ HEAP32[$n61 >> 2] = $add62;
+ return;
+ }
+}
+function _interclexp($subg) {
+ $subg = $subg | 0;
+ var $root = 0, $0 = 0, $1 = 0, $call = 0, $tobool45 = 0, $2 = 0, $3 = 0, $4 = 0, $n_0_in46 = 0, $5 = 0, $6 = 0, $call2 = 0, $tobool441 = 0, $e_044_in = 0, $prev_043 = 0, $e_044 = 0, $7 = 0, $call6 = 0, $tobool7 = 0, $8 = 0, $9 = 0, $call8 = 0, $tobool9 = 0, $tail = 0, $10 = 0, $11 = 0, $rank = 0, $12 = 0, $13 = 0, $head = 0, $14 = 0, $15 = 0, $rank12 = 0, $16 = 0, $17 = 0, $cmp = 0, $u14 = 0, $to_virt = 0, $18 = 0, $prev_0_ = 0, $to_virt19 = 0, $19 = 0, $cmp20 = 0, $20 = 0, $21 = 0, $22 = 0, $call36 = 0, $cmp37 = 0, $23 = 0, $cmp40 = 0, $u42 = 0, $to_virt43 = 0, $24 = 0, $25 = 0, $tobool44 = 0, $to_virt51 = 0, $26 = 0, $27 = 0, $cmp52 = 0, $cmp59 = 0, $prev_1 = 0, $28 = 0, $29 = 0, $call68 = 0, $tobool4 = 0, $call70 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $subg + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $1 = $subg;
+ $call = _agfstnode($1) | 0;
+ $tobool45 = ($call | 0) == 0;
+ if ($tobool45) {
+ label = 22;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $subg;
+ $3 = $0;
+ $4 = $subg;
+ $n_0_in46 = $call;
+ label = 4;
+ break;
+ case 4:
+ $5 = HEAP32[$root >> 2] | 0;
+ $6 = $5;
+ $call2 = _agfstedge($6, $n_0_in46) | 0;
+ $tobool441 = ($call2 | 0) == 0;
+ if ($tobool441) {
+ label = 21;
+ break;
+ } else {
+ $prev_043 = 0;
+ $e_044_in = $call2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $e_044 = $e_044_in;
+ $7 = $e_044_in | 0;
+ $call6 = _agcontains($2, $7) | 0;
+ $tobool7 = ($call6 | 0) == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ $prev_1 = $prev_043;
+ label = 20;
+ break;
+ }
+ case 6:
+ $8 = $prev_043;
+ $9 = $e_044_in;
+ $call8 = _mergeable($8, $9) | 0;
+ $tobool9 = ($call8 | 0) == 0;
+ $tail = $e_044_in + 16 | 0;
+ $10 = HEAP32[$tail >> 2] | 0;
+ $11 = $10;
+ $rank = $10 + 236 | 0;
+ $12 = $rank;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $head = $e_044_in + 12 | 0;
+ $14 = HEAP32[$head >> 2] | 0;
+ $15 = $14;
+ $rank12 = $14 + 236 | 0;
+ $16 = $rank12;
+ $17 = HEAP32[$16 >> 2] | 0;
+ $cmp = ($13 | 0) == ($17 | 0);
+ if ($tobool9) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $u14 = $e_044_in + 24 | 0;
+ $to_virt = $u14 + 164 | 0;
+ $18 = $to_virt;
+ $prev_0_ = $cmp ? $prev_043 : 0;
+ HEAP32[$18 >> 2] = $prev_0_;
+ $to_virt19 = $prev_043 + 188 | 0;
+ $19 = HEAP32[$to_virt19 >> 2] | 0;
+ $cmp20 = ($19 | 0) == 0;
+ if ($cmp20) {
+ $prev_1 = $prev_043;
+ label = 20;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $20 = $19;
+ _merge_chain($4, $9, $20, 0);
+ _safe_other_edge($9);
+ $prev_1 = $prev_043;
+ label = 20;
+ break;
+ case 9:
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 10:
+ $21 = $10;
+ $22 = $14;
+ $call36 = _find_flat_edge($21, $22) | 0;
+ $cmp37 = ($call36 | 0) == 0;
+ if ($cmp37) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ _flat_edge($3, $9);
+ $prev_1 = $e_044;
+ label = 20;
+ break;
+ case 12:
+ $23 = $call36;
+ $cmp40 = ($e_044_in | 0) == ($23 | 0);
+ if ($cmp40) {
+ $prev_1 = $prev_043;
+ label = 20;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _safe_other_edge($9);
+ $u42 = $e_044_in + 24 | 0;
+ $to_virt43 = $u42 + 164 | 0;
+ $24 = $to_virt43;
+ $25 = HEAP32[$24 >> 2] | 0;
+ $tobool44 = ($25 | 0) == 0;
+ if ($tobool44) {
+ label = 14;
+ break;
+ } else {
+ $prev_1 = $prev_043;
+ label = 20;
+ break;
+ }
+ case 14:
+ _merge_oneway($9, $call36);
+ $prev_1 = $prev_043;
+ label = 20;
+ break;
+ case 15:
+ $to_virt51 = $e_044_in + 188 | 0;
+ $26 = $to_virt51;
+ $27 = HEAP32[$26 >> 2] | 0;
+ $cmp52 = ($27 | 0) == 0;
+ if ($cmp52) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ ___assert_func(111976, 234, 164168, 145696);
+ case 17:
+ $cmp59 = ($17 | 0) > ($13 | 0);
+ if ($cmp59) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ _make_interclust_chain($11, $15, $e_044);
+ $prev_1 = $e_044;
+ label = 20;
+ break;
+ case 19:
+ _make_interclust_chain($15, $11, $e_044);
+ $prev_1 = $e_044;
+ label = 20;
+ break;
+ case 20:
+ $28 = HEAP32[$root >> 2] | 0;
+ $29 = $28;
+ $call68 = _agnxtedge($29, $e_044_in, $n_0_in46) | 0;
+ $tobool4 = ($call68 | 0) == 0;
+ if ($tobool4) {
+ label = 21;
+ break;
+ } else {
+ $prev_043 = $prev_1;
+ $e_044_in = $call68;
+ label = 5;
+ break;
+ }
+ case 21:
+ $call70 = _agnxtnode($1, $n_0_in46) | 0;
+ $tobool = ($call70 | 0) == 0;
+ if ($tobool) {
+ label = 22;
+ break;
+ } else {
+ $n_0_in46 = $call70;
+ label = 4;
+ break;
+ }
+ case 22:
+ return;
+ }
+}
+function _map_interclust_node($n) {
+ $n = $n | 0;
+ var $clust = 0, $0 = 0, $cmp = 0, $expanded = 0, $1 = 0, $tobool = 0, $rank = 0, $2 = 0, $rankleader = 0, $3 = 0, $arrayidx = 0, $4 = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $clust = $n + 216 | 0;
+ $0 = HEAP32[$clust >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ $rv_0 = $n;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $expanded = $0 + 284 | 0;
+ $1 = HEAP8[$expanded] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $rv_0 = $n;
+ label = 5;
+ break;
+ }
+ case 4:
+ $rank = $n + 236 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $rankleader = $0 + 280 | 0;
+ $3 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx = $3 + ($2 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $rv_0 = $4;
+ label = 5;
+ break;
+ case 5:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _inBoxf($p, $bb) {
+ $p = $p | 0;
+ $bb = $bb | 0;
+ var $x = 0, $0 = 0.0, $x1 = 0, $1 = 0.0, $cmp = 0, $x3 = 0, $2 = 0.0, $cmp4 = 0, $y = 0, $3 = 0.0, $y6 = 0, $4 = 0.0, $cmp7 = 0, $y11 = 0, $5 = 0.0, $cmp12 = 0, $phitmp = 0, $6 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $bb | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x1 = $p | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $cmp = $0 > $1;
+ if ($cmp) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x3 = $bb + 16 | 0;
+ $2 = +HEAPF64[$x3 >> 3];
+ $cmp4 = $1 > $2;
+ if ($cmp4) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $bb + 8 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $y6 = $p + 8 | 0;
+ $4 = +HEAPF64[$y6 >> 3];
+ $cmp7 = $3 > $4;
+ if ($cmp7) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y11 = $bb + 24 | 0;
+ $5 = +HEAPF64[$y11 >> 3];
+ $cmp12 = $4 <= $5;
+ $phitmp = $cmp12 & 1;
+ $6 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $6 | 0;
+ }
+ return 0;
+}
+function _clone_vn($g, $vn) {
+ $g = $g | 0;
+ $vn = $vn | 0;
+ var $rank = 0, $0 = 0, $order = 0, $call = 0, $3 = 0, $add = 0;
+ $rank = $vn + 236 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $order = $vn + 240 | 0;
+ _make_slots($g, $0, HEAP32[$order >> 2] | 0, 2);
+ $call = _virtual_node($g) | 0;
+ $3 = $call;
+ HEAPF64[$call + 104 >> 3] = +HEAPF64[$vn + 104 >> 3];
+ HEAPF64[$call + 112 >> 3] = +HEAPF64[$vn + 112 >> 3];
+ HEAP32[$call + 236 >> 2] = HEAP32[$rank >> 2] | 0;
+ $add = (HEAP32[$order >> 2] | 0) + 1 | 0;
+ HEAP32[$call + 240 >> 2] = $add;
+ HEAP32[(HEAP32[(HEAP32[$g + 224 >> 2] | 0) + ($0 * 44 & -1) + 4 >> 2] | 0) + ($add << 2) >> 2] = $3;
+ return $3 | 0;
+}
+function _dot_compoundEdges($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool10 = 0, $n_0_in11 = 0, $call1 = 0, $tobool38 = 0, $e_0_in9 = 0, $e_0 = 0, $call5 = 0, $tobool3 = 0, $call7 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool10 = ($call | 0) == 0;
+ if ($tobool10) {
+ label = 6;
+ break;
+ } else {
+ $n_0_in11 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agfstout($0, $n_0_in11) | 0;
+ $tobool38 = ($call1 | 0) == 0;
+ if ($tobool38) {
+ label = 5;
+ break;
+ } else {
+ $e_0_in9 = $call1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $e_0 = $e_0_in9;
+ _makeCompoundEdge($g, $e_0);
+ $call5 = _agnxtout($0, $e_0_in9) | 0;
+ $tobool3 = ($call5 | 0) == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ $e_0_in9 = $call5;
+ label = 4;
+ break;
+ }
+ case 5:
+ $call7 = _agnxtnode($0, $n_0_in11) | 0;
+ $tobool = ($call7 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_0_in11 = $call7;
+ label = 3;
+ break;
+ }
+ case 6:
+ return;
+ }
+}
+function _getCluster($g, $cluster_name) {
+ $g = $g | 0;
+ $cluster_name = $cluster_name | 0;
+ var $tobool = 0, $0 = 0, $cmp = 0, $1 = 0, $call = 0, $2 = 0, $cmp2 = 0, $call5 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($cluster_name | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$cluster_name] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = $g;
+ $call = _agfindsubg($1, $cluster_name) | 0;
+ $2 = $call;
+ $cmp2 = ($call | 0) == 0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = $2;
+ label = 6;
+ break;
+ }
+ case 5:
+ $call5 = _agerr(0, 152184, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $cluster_name, tempInt) | 0) | 0;
+ $retval_0 = $2;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _map_path($from, $to, $orig, $ve, $type) {
+ $from = $from | 0;
+ $to = $to | 0;
+ $orig = $orig | 0;
+ $ve = $ve | 0;
+ $type = $type | 0;
+ var $rank = 0, $0 = 0, $rank3 = 0, $1 = 0, $cmp = 0, $tail = 0, $2 = 0, $cmp4 = 0, $head = 0, $3 = 0, $cmp5 = 0, $count = 0, $4 = 0, $cmp7 = 0, $to_virt = 0, $5 = 0, $6 = 0, $sub = 0, $cmp15 = 0, $7 = 0, $8 = 0, $call = 0, $tobool = 0, $9 = 0, $call19 = 0, $tobool20 = 0, $node_type = 0, $10 = 0, $cmp24 = 0, $node_type28 = 0, $11 = 0, $cmp30 = 0, $12 = 0, $13 = 0, $cmp4072 = 0, $graph = 0, $14 = 0, $conv52 = 0, $15 = 0, $u_075 = 0, $r_074 = 0, $ve_addr_073 = 0, $sub44 = 0, $cmp45 = 0, $16 = 0, $head48 = 0, $17 = 0, $call49 = 0, $v_0 = 0, $18 = 0, $19 = 0, $call51 = 0, $20 = 0, $count55 = 0, $21 = 0, $dec = 0, $head56 = 0, $22 = 0, $list = 0, $23 = 0, $24 = 0, $inc = 0, $25 = 0, $cmp40 = 0, $26 = 0, $27 = 0, $sub63 = 0, $cmp64 = 0, $28 = 0, $29 = 0, $call67 = 0, $30 = 0, $tobool68 = 0, $31 = 0, $call70 = 0, $tobool71 = 0, $to_virt74 = 0, $conv75 = 0, $32 = 0, $33 = 0, $34 = 0, $inc80 = 0, $node_type82 = 0, $35 = 0, $cmp84 = 0, $node_type88 = 0, $36 = 0, $cmp90 = 0, $to_virt96 = 0, $37 = 0, $call97 = 0, $38 = 0, $conv98 = 0, $39 = 0, $ve_addr_1 = 0, $40 = 0, $41 = 0, $sub107 = 0, $cmp108 = 0, $tail111 = 0, $42 = 0, $cmp112 = 0, $to_virt116 = 0, $head117 = 0, $43 = 0, $44 = 0, $45 = 0, $46 = 0, $call118 = 0, $47 = 0, $48 = 0, $e_0_ph = 0, $head12376 = 0, $49 = 0, $rank12577 = 0, $50 = 0, $51 = 0, $cmp12878 = 0, $52 = 0, $53 = 0, $list133 = 0, $54 = 0, $55 = 0, $head123 = 0, $56 = 0, $rank125 = 0, $57 = 0, $cmp128 = 0, $_lcssa = 0, $e_0_lcssa = 0, $cmp136 = 0, $tail139 = 0, $58 = 0, $59 = 0, $60 = 0, $61 = 0, $call140 = 0, $conv141 = 0, $62 = 0, $63 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $from + 236 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $rank3 = $to + 236 | 0;
+ $1 = HEAP32[$rank3 >> 2] | 0;
+ $cmp = ($0 | 0) < ($1 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ ___assert_func(111976, 109, 164048, 114944);
+ case 4:
+ $tail = $ve + 16 | 0;
+ $2 = HEAP32[$tail >> 2] | 0;
+ $cmp4 = ($2 | 0) == ($from | 0);
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $head = $ve + 12 | 0;
+ $3 = HEAP32[$head >> 2] | 0;
+ $cmp5 = ($3 | 0) == ($to | 0);
+ if ($cmp5) {
+ label = 33;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $count = $ve + 184 | 0;
+ $4 = HEAP16[$count >> 1] | 0;
+ $cmp7 = $4 << 16 >> 16 > 1;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 7:
+ $to_virt = $orig + 188 | 0;
+ HEAP32[$to_virt >> 2] = 0;
+ $5 = HEAP32[$rank3 >> 2] | 0;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $sub = $5 - $6 | 0;
+ $cmp15 = ($sub | 0) == 1;
+ if ($cmp15) {
+ label = 8;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 8:
+ $7 = $from;
+ $8 = $to;
+ $call = _find_fast_edge($7, $8) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $9 = $orig;
+ $call19 = _ports_eq($9, $call) | 0;
+ $tobool20 = ($call19 | 0) == 0;
+ if ($tobool20) {
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ _merge_oneway($9, $call);
+ $node_type = $from + 162 | 0;
+ $10 = HEAP8[$node_type] | 0;
+ $cmp24 = $10 << 24 >> 24 == 0;
+ if ($cmp24) {
+ label = 11;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 11:
+ $node_type28 = $to + 162 | 0;
+ $11 = HEAP8[$node_type28] | 0;
+ $cmp30 = $11 << 24 >> 24 == 0;
+ if ($cmp30) {
+ label = 12;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 12:
+ _other_edge($9);
+ label = 33;
+ break;
+ case 13:
+ $12 = HEAP32[$rank >> 2] | 0;
+ $13 = HEAP32[$rank3 >> 2] | 0;
+ $cmp4072 = ($12 | 0) < ($13 | 0);
+ if ($cmp4072) {
+ label = 14;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 14:
+ $graph = $from + 20 | 0;
+ $14 = $orig;
+ $conv52 = $type & 255;
+ $ve_addr_073 = $ve;
+ $r_074 = $12;
+ $u_075 = $from;
+ $15 = $13;
+ label = 15;
+ break;
+ case 15:
+ $sub44 = $15 - 1 | 0;
+ $cmp45 = ($r_074 | 0) < ($sub44 | 0);
+ if ($cmp45) {
+ label = 16;
+ break;
+ } else {
+ $v_0 = $to;
+ label = 17;
+ break;
+ }
+ case 16:
+ $16 = HEAP32[$graph >> 2] | 0;
+ $head48 = $ve_addr_073 + 12 | 0;
+ $17 = HEAP32[$head48 >> 2] | 0;
+ $call49 = _clone_vn($16, $17) | 0;
+ $v_0 = $call49;
+ label = 17;
+ break;
+ case 17:
+ $18 = $u_075;
+ $19 = $v_0;
+ $call51 = _virtual_edge($18, $19, $14) | 0;
+ $20 = $call51 + 128 | 0;
+ HEAP8[$20] = $conv52;
+ $count55 = $ve_addr_073 + 184 | 0;
+ $21 = HEAP16[$count55 >> 1] | 0;
+ $dec = $21 - 1 & 65535;
+ HEAP16[$count55 >> 1] = $dec;
+ $head56 = $ve_addr_073 + 12 | 0;
+ $22 = HEAP32[$head56 >> 2] | 0;
+ $list = $22 + 184 | 0;
+ $23 = HEAP32[$list >> 2] | 0;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $inc = $r_074 + 1 | 0;
+ $25 = HEAP32[$rank3 >> 2] | 0;
+ $cmp40 = ($inc | 0) < ($25 | 0);
+ if ($cmp40) {
+ $ve_addr_073 = $24;
+ $r_074 = $inc;
+ $u_075 = $v_0;
+ $15 = $25;
+ label = 15;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 18:
+ $26 = HEAP32[$rank3 >> 2] | 0;
+ $27 = HEAP32[$rank >> 2] | 0;
+ $sub63 = $26 - $27 | 0;
+ $cmp64 = ($sub63 | 0) == 1;
+ if ($cmp64) {
+ label = 19;
+ break;
+ } else {
+ $ve_addr_1 = $ve;
+ label = 25;
+ break;
+ }
+ case 19:
+ $28 = $from;
+ $29 = $to;
+ $call67 = _find_fast_edge($28, $29) | 0;
+ $30 = $call67;
+ $tobool68 = ($call67 | 0) == 0;
+ if ($tobool68) {
+ label = 24;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $31 = $orig;
+ $call70 = _ports_eq($31, $call67) | 0;
+ $tobool71 = ($call70 | 0) == 0;
+ if ($tobool71) {
+ label = 24;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $to_virt74 = $orig + 188 | 0;
+ HEAP32[$to_virt74 >> 2] = $30;
+ $conv75 = $type & 255;
+ $32 = $call67 + 128 | 0;
+ HEAP8[$32] = $conv75;
+ $33 = $call67 + 184 | 0;
+ $34 = HEAP16[$33 >> 1] | 0;
+ $inc80 = $34 + 1 & 65535;
+ HEAP16[$33 >> 1] = $inc80;
+ $node_type82 = $from + 162 | 0;
+ $35 = HEAP8[$node_type82] | 0;
+ $cmp84 = $35 << 24 >> 24 == 0;
+ if ($cmp84) {
+ label = 22;
+ break;
+ } else {
+ $ve_addr_1 = $30;
+ label = 25;
+ break;
+ }
+ case 22:
+ $node_type88 = $to + 162 | 0;
+ $36 = HEAP8[$node_type88] | 0;
+ $cmp90 = $36 << 24 >> 24 == 0;
+ if ($cmp90) {
+ label = 23;
+ break;
+ } else {
+ $ve_addr_1 = $30;
+ label = 25;
+ break;
+ }
+ case 23:
+ _other_edge($31);
+ $ve_addr_1 = $30;
+ label = 25;
+ break;
+ case 24:
+ $to_virt96 = $orig + 188 | 0;
+ HEAP32[$to_virt96 >> 2] = 0;
+ $37 = $orig;
+ $call97 = _virtual_edge($28, $29, $37) | 0;
+ $38 = $call97;
+ $conv98 = $type & 255;
+ $39 = $call97 + 128 | 0;
+ HEAP8[$39] = $conv98;
+ $ve_addr_1 = $38;
+ label = 25;
+ break;
+ case 25:
+ $40 = HEAP32[$rank3 >> 2] | 0;
+ $41 = HEAP32[$rank >> 2] | 0;
+ $sub107 = $40 - $41 | 0;
+ $cmp108 = ($sub107 | 0) > 1;
+ if ($cmp108) {
+ label = 26;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 26:
+ $tail111 = $ve_addr_1 + 16 | 0;
+ $42 = HEAP32[$tail111 >> 2] | 0;
+ $cmp112 = ($42 | 0) == ($from | 0);
+ if ($cmp112) {
+ $e_0_ph = $ve_addr_1;
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $to_virt116 = $orig + 188 | 0;
+ HEAP32[$to_virt116 >> 2] = 0;
+ $head117 = $ve_addr_1 + 12 | 0;
+ $43 = HEAP32[$head117 >> 2] | 0;
+ $44 = $from;
+ $45 = $43;
+ $46 = $orig;
+ $call118 = _virtual_edge($44, $45, $46) | 0;
+ $47 = $call118;
+ HEAP32[$to_virt116 >> 2] = $47;
+ $48 = $ve_addr_1;
+ _delete_fast_edge($48);
+ $e_0_ph = $47;
+ label = 28;
+ break;
+ case 28:
+ $head12376 = $e_0_ph + 12 | 0;
+ $49 = HEAP32[$head12376 >> 2] | 0;
+ $rank12577 = $49 + 236 | 0;
+ $50 = HEAP32[$rank12577 >> 2] | 0;
+ $51 = HEAP32[$rank3 >> 2] | 0;
+ $cmp12878 = ($50 | 0) == ($51 | 0);
+ if ($cmp12878) {
+ $e_0_lcssa = $e_0_ph;
+ $_lcssa = $49;
+ label = 31;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $52 = HEAP32[$rank3 >> 2] | 0;
+ $53 = $49;
+ label = 30;
+ break;
+ case 30:
+ $list133 = $53 + 184 | 0;
+ $54 = HEAP32[$list133 >> 2] | 0;
+ $55 = HEAP32[$54 >> 2] | 0;
+ $head123 = $55 + 12 | 0;
+ $56 = HEAP32[$head123 >> 2] | 0;
+ $rank125 = $56 + 236 | 0;
+ $57 = HEAP32[$rank125 >> 2] | 0;
+ $cmp128 = ($57 | 0) == ($52 | 0);
+ if ($cmp128) {
+ $e_0_lcssa = $55;
+ $_lcssa = $56;
+ label = 31;
+ break;
+ } else {
+ $53 = $56;
+ label = 30;
+ break;
+ }
+ case 31:
+ $cmp136 = ($_lcssa | 0) == ($to | 0);
+ if ($cmp136) {
+ label = 33;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $tail139 = $e_0_lcssa + 16 | 0;
+ $58 = HEAP32[$tail139 >> 2] | 0;
+ $59 = $58;
+ $60 = $to;
+ $61 = $orig;
+ $call140 = _virtual_edge($59, $60, $61) | 0;
+ $conv141 = $type & 255;
+ $62 = $call140 + 128 | 0;
+ HEAP8[$62] = $conv141;
+ $63 = $e_0_lcssa;
+ _delete_fast_edge($63);
+ label = 33;
+ break;
+ case 33:
+ return;
+ }
+}
+function _makeCompoundEdge($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $pts = 0, $p = 0, $tmp64 = 0, $tmp70 = 0, $tmp75 = 0, $tmp104 = 0, $tmp177 = 0, $tmp185 = 0, $tmp192 = 0, $tmp243 = 0, $0 = 0, $call = 0, $call1 = 0, $call2 = 0, $call3 = 0, $tobool = 0, $tobool_not = 0, $tobool4 = 0, $or_cond = 0, $spl = 0, $1 = 0, $tobool5 = 0, $size10 = 0, $2 = 0, $cmp = 0, $tail12 = 0, $3 = 0, $name = 0, $4 = 0, $head13 = 0, $5 = 0, $name14 = 0, $6 = 0, $call15 = 0, $list = 0, $7 = 0, $size19 = 0, $8 = 0, $head20 = 0, $9 = 0, $tail21 = 0, $10 = 0, $call22 = 0, $11 = 0, $eflag = 0, $12 = 0, $eflag23 = 0, $13 = 0, $sflag = 0, $14 = 0, $sflag24 = 0, $15 = 0, $bb28 = 0, $coord = 0, $call30 = 0, $tobool31 = 0, $16 = 0, $name34 = 0, $17 = 0, $18 = 0, $name36 = 0, $19 = 0, $call37 = 0, $call38 = 0, $list39 = 0, $20 = 0, $call40 = 0, $tobool41 = 0, $sub = 0, $coord44 = 0, $call45 = 0, $tobool46 = 0, $21 = 0, $name49 = 0, $22 = 0, $23 = 0, $name51 = 0, $24 = 0, $call52 = 0, $call53 = 0, $25 = 0, $tobool56 = 0, $sp = 0, $26 = 0, $27 = 0, $arrayidx60 = 0, $28 = 0, $29 = 0, $arrayidx62 = 0, $30 = 0, $31 = 0, $32 = 0, $arrayidx68 = 0, $33 = 0, $34 = 0, $35 = 0, $arrayidx72 = 0, $arrayidx74 = 0, $36 = 0, $37 = 0, $38 = 0, $tobool77 = 0, $39 = 0, $40 = 0, $call81 = 0, $phitmp = 0, $endi_1 = 0, $cmp85 = 0, $41 = 0, $arrayidx87 = 0, $call88 = 0, $tobool89 = 0, $add92 = 0, $cmp94 = 0, $42 = 0, $tobool97 = 0, $ep = 0, $ep101 = 0, $43 = 0, $arrayidx103 = 0, $44 = 0, $45 = 0, $46 = 0, $call111 = 0, $endi_2 = 0, $add113 = 0, $sub120 = 0, $47 = 0, $tobool122 = 0, $ep124 = 0, $ep125 = 0, $48 = 0, $endi_5 = 0, $bb131 = 0, $coord133 = 0, $call134 = 0, $tobool135 = 0, $49 = 0, $name138 = 0, $50 = 0, $51 = 0, $name140 = 0, $52 = 0, $call141 = 0, $call142 = 0, $list144 = 0, $53 = 0, $arrayidx145 = 0, $call146 = 0, $tobool147 = 0, $arraydecay = 0, $coord150 = 0, $call151 = 0, $tobool152 = 0, $54 = 0, $name155 = 0, $55 = 0, $56 = 0, $name157 = 0, $57 = 0, $call158 = 0, $call159 = 0, $58 = 0, $tobool162 = 0, $ep168 = 0, $59 = 0, $60 = 0, $sub170 = 0, $61 = 0, $arrayidx172 = 0, $62 = 0, $add173 = 0, $63 = 0, $arrayidx175 = 0, $64 = 0, $65 = 0, $66 = 0, $arrayidx180 = 0, $arrayidx183 = 0, $67 = 0, $68 = 0, $add186 = 0, $69 = 0, $arrayidx188 = 0, $arrayidx191 = 0, $70 = 0, $71 = 0, $72 = 0, $tobool194 = 0, $73 = 0, $74 = 0, $call199 = 0, $starti_1 = 0, $cmp204 = 0, $75 = 0, $arrayidx212 = 0, $76 = 0, $77 = 0, $arrayidx209_1 = 0, $sub210_1 = 0, $78 = 0, $arrayidx212_1 = 0, $79 = 0, $80 = 0, $arrayidx209_2 = 0, $sub210_2 = 0, $81 = 0, $arrayidx212_2 = 0, $82 = 0, $83 = 0, $arrayidx209_3 = 0, $sub210_3 = 0, $84 = 0, $arrayidx212_3 = 0, $85 = 0, $86 = 0, $call215 = 0, $tobool216 = 0, $sub230 = 0, $87 = 0, $arrayidx223 = 0, $88 = 0, $89 = 0, $sub221_1 = 0, $90 = 0, $arrayidx223_1 = 0, $arrayidx224_1 = 0, $91 = 0, $92 = 0, $sub221_2 = 0, $93 = 0, $arrayidx223_2 = 0, $arrayidx224_2 = 0, $94 = 0, $95 = 0, $sub221_3 = 0, $96 = 0, $arrayidx223_3 = 0, $arrayidx224_3 = 0, $97 = 0, $98 = 0, $cmp232 = 0, $99 = 0, $tobool235 = 0, $sp239 = 0, $sp240 = 0, $100 = 0, $arrayidx242 = 0, $101 = 0, $sub245 = 0, $102 = 0, $tobool247 = 0, $103 = 0, $sub250 = 0, $104 = 0, $call252 = 0, $105 = 0, $tobool261 = 0, $sp263 = 0, $sp264 = 0, $106 = 0, $starti_3157 = 0, $sub267 = 0, $add268 = 0, $size269 = 0, $107 = 0, $mul = 0, $call271 = 0, $108 = 0, $list272 = 0, $109 = 0, $cmp275158 = 0, $list279 = 0, $j_0160 = 0, $i_2159 = 0, $110 = 0, $arrayidx278 = 0, $111 = 0, $arrayidx280 = 0, $112 = 0, $113 = 0, $inc282 = 0, $inc283 = 0, $114 = 0, $cmp275 = 0, $list285 = 0, $115 = 0, $116 = 0, $117 = 0, $118 = 0, $list288 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 208 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pts = __stackBase__ | 0;
+ $p = __stackBase__ + 64 | 0;
+ $tmp64 = __stackBase__ + 80 | 0;
+ $tmp70 = __stackBase__ + 96 | 0;
+ $tmp75 = __stackBase__ + 112 | 0;
+ $tmp104 = __stackBase__ + 128 | 0;
+ $tmp177 = __stackBase__ + 144 | 0;
+ $tmp185 = __stackBase__ + 160 | 0;
+ $tmp192 = __stackBase__ + 176 | 0;
+ $tmp243 = __stackBase__ + 192 | 0;
+ $0 = $e | 0;
+ $call = _agget($0, 151760) | 0;
+ $call1 = _getCluster($g, $call) | 0;
+ $call2 = _agget($0, 158144) | 0;
+ $call3 = _getCluster($g, $call2) | 0;
+ $tobool = ($call3 | 0) != 0;
+ $tobool_not = $tobool ^ 1;
+ $tobool4 = ($call1 | 0) == 0;
+ $or_cond = $tobool4 & $tobool_not;
+ if ($or_cond) {
+ label = 54;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $spl = $e + 24 | 0;
+ $1 = HEAP32[$spl >> 2] | 0;
+ $tobool5 = ($1 | 0) == 0;
+ if ($tobool5) {
+ label = 54;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $size10 = $1 + 4 | 0;
+ $2 = HEAP32[$size10 >> 2] | 0;
+ $cmp = ($2 | 0) > 1;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $tail12 = $e + 16 | 0;
+ $3 = HEAP32[$tail12 >> 2] | 0;
+ $name = $3 + 12 | 0;
+ $4 = HEAP32[$name >> 2] | 0;
+ $head13 = $e + 12 | 0;
+ $5 = HEAP32[$head13 >> 2] | 0;
+ $name14 = $5 + 12 | 0;
+ $6 = HEAP32[$name14 >> 2] | 0;
+ $call15 = _agerr(0, 129520, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $4, HEAP32[tempInt + 8 >> 2] = $6, tempInt) | 0) | 0;
+ label = 54;
+ break;
+ case 6:
+ $list = $1 | 0;
+ $7 = HEAP32[$list >> 2] | 0;
+ $size19 = $7 + 4 | 0;
+ $8 = HEAP32[$size19 >> 2] | 0;
+ $head20 = $e + 12 | 0;
+ $9 = HEAP32[$head20 >> 2] | 0;
+ $tail21 = $e + 16 | 0;
+ $10 = HEAP32[$tail21 >> 2] | 0;
+ $call22 = _gmalloc(48) | 0;
+ $11 = $call22;
+ $eflag = $7 + 12 | 0;
+ $12 = HEAP32[$eflag >> 2] | 0;
+ $eflag23 = $call22 + 12 | 0;
+ $13 = $eflag23;
+ HEAP32[$13 >> 2] = $12;
+ $sflag = $7 + 8 | 0;
+ $14 = HEAP32[$sflag >> 2] | 0;
+ $sflag24 = $call22 + 8 | 0;
+ $15 = $sflag24;
+ HEAP32[$15 >> 2] = $14;
+ if ($tobool4) {
+ label = 26;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $bb28 = $call1 + 56 | 0;
+ $coord = $9 + 32 | 0;
+ $call30 = _inBoxf($coord, $bb28) | 0;
+ $tobool31 = ($call30 | 0) == 0;
+ if ($tobool31) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $16 = HEAP32[$tail21 >> 2] | 0;
+ $name34 = $16 + 12 | 0;
+ $17 = HEAP32[$name34 >> 2] | 0;
+ $18 = HEAP32[$head20 >> 2] | 0;
+ $name36 = $18 + 12 | 0;
+ $19 = HEAP32[$name36 >> 2] | 0;
+ $call37 = _agget($0, 151760) | 0;
+ $call38 = _agerr(0, 117960, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $17, HEAP32[tempInt + 8 >> 2] = $19, HEAP32[tempInt + 16 >> 2] = $call37, tempInt) | 0) | 0;
+ label = 26;
+ break;
+ case 9:
+ $list39 = $7 | 0;
+ $20 = HEAP32[$list39 >> 2] | 0;
+ $call40 = _inBoxf($20, $bb28) | 0;
+ $tobool41 = ($call40 | 0) == 0;
+ if ($tobool41) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $sub = $8 - 1 | 0;
+ $endi_1 = 0;
+ label = 17;
+ break;
+ case 11:
+ $coord44 = $10 + 32 | 0;
+ $call45 = _inBoxf($coord44, $bb28) | 0;
+ $tobool46 = ($call45 | 0) == 0;
+ if ($tobool46) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $21 = HEAP32[$tail21 >> 2] | 0;
+ $name49 = $21 + 12 | 0;
+ $22 = HEAP32[$name49 >> 2] | 0;
+ $23 = HEAP32[$head20 >> 2] | 0;
+ $name51 = $23 + 12 | 0;
+ $24 = HEAP32[$name51 >> 2] | 0;
+ $call52 = _agget($0, 151760) | 0;
+ $call53 = _agerr(0, 112576, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $22, HEAP32[tempInt + 8 >> 2] = $24, HEAP32[tempInt + 16 >> 2] = $call52, tempInt) | 0) | 0;
+ label = 26;
+ break;
+ case 13:
+ $25 = HEAP32[$sflag >> 2] | 0;
+ $tobool56 = ($25 | 0) == 0;
+ if ($tobool56) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ ___assert_func(107624, 364, 164144, 103696);
+ case 15:
+ $sp = $7 + 16 | 0;
+ _boxIntersectf($p, $20, $sp, $bb28);
+ $26 = $p;
+ $27 = HEAP32[$list39 >> 2] | 0;
+ $arrayidx60 = $27 + 48 | 0;
+ $28 = $arrayidx60;
+ HEAP32[$28 >> 2] = HEAP32[$26 >> 2] | 0;
+ HEAP32[$28 + 4 >> 2] = HEAP32[$26 + 4 >> 2] | 0;
+ HEAP32[$28 + 8 >> 2] = HEAP32[$26 + 8 >> 2] | 0;
+ HEAP32[$28 + 12 >> 2] = HEAP32[$26 + 12 >> 2] | 0;
+ $29 = HEAP32[$list39 >> 2] | 0;
+ $arrayidx62 = $29 + 16 | 0;
+ _mid_pointf3014($tmp64, $p, $sp);
+ $30 = $arrayidx62;
+ $31 = $tmp64;
+ HEAP32[$30 >> 2] = HEAP32[$31 >> 2] | 0;
+ HEAP32[$30 + 4 >> 2] = HEAP32[$31 + 4 >> 2] | 0;
+ HEAP32[$30 + 8 >> 2] = HEAP32[$31 + 8 >> 2] | 0;
+ HEAP32[$30 + 12 >> 2] = HEAP32[$31 + 12 >> 2] | 0;
+ $32 = HEAP32[$list39 >> 2] | 0;
+ $arrayidx68 = $32 + 16 | 0;
+ _mid_pointf3014($tmp70, $arrayidx68, $sp);
+ $33 = $32;
+ $34 = $tmp70;
+ HEAP32[$33 >> 2] = HEAP32[$34 >> 2] | 0;
+ HEAP32[$33 + 4 >> 2] = HEAP32[$34 + 4 >> 2] | 0;
+ HEAP32[$33 + 8 >> 2] = HEAP32[$34 + 8 >> 2] | 0;
+ HEAP32[$33 + 12 >> 2] = HEAP32[$34 + 12 >> 2] | 0;
+ $35 = HEAP32[$list39 >> 2] | 0;
+ $arrayidx72 = $35 + 32 | 0;
+ $arrayidx74 = $35 + 16 | 0;
+ _mid_pointf3014($tmp75, $arrayidx74, $p);
+ $36 = $arrayidx72;
+ $37 = $tmp75;
+ HEAP32[$36 >> 2] = HEAP32[$37 >> 2] | 0;
+ HEAP32[$36 + 4 >> 2] = HEAP32[$37 + 4 >> 2] | 0;
+ HEAP32[$36 + 8 >> 2] = HEAP32[$37 + 8 >> 2] | 0;
+ HEAP32[$36 + 12 >> 2] = HEAP32[$37 + 12 >> 2] | 0;
+ $38 = HEAP32[$eflag >> 2] | 0;
+ $tobool77 = ($38 | 0) == 0;
+ if ($tobool77) {
+ $endi_5 = 3;
+ label = 28;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $39 = HEAP32[$list39 >> 2] | 0;
+ $40 = $e;
+ $call81 = _arrowEndClip($40, $39, 0, 0, $11, $38) | 0;
+ $phitmp = $call81 + 3 | 0;
+ $endi_5 = $phitmp;
+ label = 28;
+ break;
+ case 17:
+ $cmp85 = ($endi_1 | 0) < ($sub | 0);
+ if ($cmp85) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $41 = HEAP32[$list39 >> 2] | 0;
+ $arrayidx87 = $41 + ($endi_1 << 4) | 0;
+ $call88 = _splineIntersectf($arrayidx87, $bb28) | 0;
+ $tobool89 = ($call88 | 0) == 0;
+ $add92 = $endi_1 + 3 | 0;
+ if ($tobool89) {
+ $endi_1 = $add92;
+ label = 17;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $cmp94 = ($endi_1 | 0) == ($sub | 0);
+ $42 = HEAP32[$eflag >> 2] | 0;
+ $tobool97 = ($42 | 0) != 0;
+ if ($cmp94) {
+ label = 20;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 20:
+ if ($tobool97) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ ___assert_func(107624, 382, 164144, 99520);
+ case 22:
+ $ep = $call22 + 32 | 0;
+ $ep101 = $7 + 32 | 0;
+ $43 = HEAP32[$list39 >> 2] | 0;
+ $arrayidx103 = $43 + ($endi_1 << 4) | 0;
+ _boxIntersectf($tmp104, $ep101, $arrayidx103, $bb28);
+ $44 = $tmp104;
+ HEAP32[$ep >> 2] = HEAP32[$44 >> 2] | 0;
+ HEAP32[$ep + 4 >> 2] = HEAP32[$44 + 4 >> 2] | 0;
+ HEAP32[$ep + 8 >> 2] = HEAP32[$44 + 8 >> 2] | 0;
+ HEAP32[$ep + 12 >> 2] = HEAP32[$44 + 12 >> 2] | 0;
+ $endi_5 = $endi_1;
+ label = 28;
+ break;
+ case 23:
+ if ($tobool97) {
+ label = 24;
+ break;
+ } else {
+ $endi_2 = $endi_1;
+ label = 25;
+ break;
+ }
+ case 24:
+ $45 = HEAP32[$list39 >> 2] | 0;
+ $46 = $e;
+ $call111 = _arrowEndClip($46, $45, 0, $endi_1, $11, $42) | 0;
+ $endi_2 = $call111;
+ label = 25;
+ break;
+ case 25:
+ $add113 = $endi_2 + 3 | 0;
+ $endi_5 = $add113;
+ label = 28;
+ break;
+ case 26:
+ $sub120 = $8 - 1 | 0;
+ $47 = HEAP32[$eflag >> 2] | 0;
+ $tobool122 = ($47 | 0) == 0;
+ if ($tobool122) {
+ $endi_5 = $sub120;
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $ep124 = $call22 + 32 | 0;
+ $ep125 = $7 + 32 | 0;
+ $48 = $ep125;
+ HEAP32[$ep124 >> 2] = HEAP32[$48 >> 2] | 0;
+ HEAP32[$ep124 + 4 >> 2] = HEAP32[$48 + 4 >> 2] | 0;
+ HEAP32[$ep124 + 8 >> 2] = HEAP32[$48 + 8 >> 2] | 0;
+ HEAP32[$ep124 + 12 >> 2] = HEAP32[$48 + 12 >> 2] | 0;
+ $endi_5 = $sub120;
+ label = 28;
+ break;
+ case 28:
+ if ($tobool) {
+ label = 29;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 29:
+ $bb131 = $call3 + 56 | 0;
+ $coord133 = $10 + 32 | 0;
+ $call134 = _inBoxf($coord133, $bb131) | 0;
+ $tobool135 = ($call134 | 0) == 0;
+ if ($tobool135) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $49 = HEAP32[$tail21 >> 2] | 0;
+ $name138 = $49 + 12 | 0;
+ $50 = HEAP32[$name138 >> 2] | 0;
+ $51 = HEAP32[$head20 >> 2] | 0;
+ $name140 = $51 + 12 | 0;
+ $52 = HEAP32[$name140 >> 2] | 0;
+ $call141 = _agget($0, 158144) | 0;
+ $call142 = _agerr(0, 95480, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $50, HEAP32[tempInt + 8 >> 2] = $52, HEAP32[tempInt + 16 >> 2] = $call141, tempInt) | 0) | 0;
+ label = 48;
+ break;
+ case 31:
+ $list144 = $7 | 0;
+ $53 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx145 = $53 + ($endi_5 << 4) | 0;
+ $call146 = _inBoxf($arrayidx145, $bb131) | 0;
+ $tobool147 = ($call146 | 0) == 0;
+ if ($tobool147) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 32:
+ $arraydecay = $pts | 0;
+ $starti_1 = $endi_5;
+ label = 39;
+ break;
+ case 33:
+ $coord150 = $9 + 32 | 0;
+ $call151 = _inBoxf($coord150, $bb131) | 0;
+ $tobool152 = ($call151 | 0) == 0;
+ if ($tobool152) {
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $54 = HEAP32[$tail21 >> 2] | 0;
+ $name155 = $54 + 12 | 0;
+ $55 = HEAP32[$name155 >> 2] | 0;
+ $56 = HEAP32[$head20 >> 2] | 0;
+ $name157 = $56 + 12 | 0;
+ $57 = HEAP32[$name157 >> 2] | 0;
+ $call158 = _agget($0, 158144) | 0;
+ $call159 = _agerr(0, 91984, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $55, HEAP32[tempInt + 8 >> 2] = $57, HEAP32[tempInt + 16 >> 2] = $call158, tempInt) | 0) | 0;
+ label = 48;
+ break;
+ case 35:
+ $58 = HEAP32[$eflag >> 2] | 0;
+ $tobool162 = ($58 | 0) == 0;
+ if ($tobool162) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ ___assert_func(107624, 424, 164144, 99520);
+ case 37:
+ $ep168 = $call22 + 32 | 0;
+ $59 = $ep168;
+ _boxIntersectf($p, $arrayidx145, $59, $bb131);
+ $60 = $p;
+ $sub170 = $endi_5 - 3 | 0;
+ $61 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx172 = $61 + ($sub170 << 4) | 0;
+ $62 = $arrayidx172;
+ HEAP32[$62 >> 2] = HEAP32[$60 >> 2] | 0;
+ HEAP32[$62 + 4 >> 2] = HEAP32[$60 + 4 >> 2] | 0;
+ HEAP32[$62 + 8 >> 2] = HEAP32[$60 + 8 >> 2] | 0;
+ HEAP32[$62 + 12 >> 2] = HEAP32[$60 + 12 >> 2] | 0;
+ $add173 = $endi_5 - 1 | 0;
+ $63 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx175 = $63 + ($add173 << 4) | 0;
+ _mid_pointf3014($tmp177, $p, $59);
+ $64 = $arrayidx175;
+ $65 = $tmp177;
+ HEAP32[$64 >> 2] = HEAP32[$65 >> 2] | 0;
+ HEAP32[$64 + 4 >> 2] = HEAP32[$65 + 4 >> 2] | 0;
+ HEAP32[$64 + 8 >> 2] = HEAP32[$65 + 8 >> 2] | 0;
+ HEAP32[$64 + 12 >> 2] = HEAP32[$65 + 12 >> 2] | 0;
+ $66 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx180 = $66 + ($endi_5 << 4) | 0;
+ $arrayidx183 = $66 + ($add173 << 4) | 0;
+ _mid_pointf3014($tmp185, $arrayidx183, $59);
+ $67 = $arrayidx180;
+ $68 = $tmp185;
+ HEAP32[$67 >> 2] = HEAP32[$68 >> 2] | 0;
+ HEAP32[$67 + 4 >> 2] = HEAP32[$68 + 4 >> 2] | 0;
+ HEAP32[$67 + 8 >> 2] = HEAP32[$68 + 8 >> 2] | 0;
+ HEAP32[$67 + 12 >> 2] = HEAP32[$68 + 12 >> 2] | 0;
+ $add186 = $endi_5 - 2 | 0;
+ $69 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx188 = $69 + ($add186 << 4) | 0;
+ $arrayidx191 = $69 + ($add173 << 4) | 0;
+ _mid_pointf3014($tmp192, $arrayidx191, $p);
+ $70 = $arrayidx188;
+ $71 = $tmp192;
+ HEAP32[$70 >> 2] = HEAP32[$71 >> 2] | 0;
+ HEAP32[$70 + 4 >> 2] = HEAP32[$71 + 4 >> 2] | 0;
+ HEAP32[$70 + 8 >> 2] = HEAP32[$71 + 8 >> 2] | 0;
+ HEAP32[$70 + 12 >> 2] = HEAP32[$71 + 12 >> 2] | 0;
+ $72 = HEAP32[$sflag >> 2] | 0;
+ $tobool194 = ($72 | 0) == 0;
+ if ($tobool194) {
+ $starti_3157 = $sub170;
+ label = 50;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $73 = HEAP32[$list144 >> 2] | 0;
+ $74 = $e;
+ $call199 = _arrowStartClip($74, $73, $sub170, $sub170, $11, $72) | 0;
+ $starti_3157 = $call199;
+ label = 50;
+ break;
+ case 39:
+ $cmp204 = ($starti_1 | 0) > 0;
+ if ($cmp204) {
+ label = 40;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 40:
+ $75 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx212 = $75 + ($starti_1 << 4) | 0;
+ $76 = $pts;
+ $77 = $arrayidx212;
+ HEAP32[$76 >> 2] = HEAP32[$77 >> 2] | 0;
+ HEAP32[$76 + 4 >> 2] = HEAP32[$77 + 4 >> 2] | 0;
+ HEAP32[$76 + 8 >> 2] = HEAP32[$77 + 8 >> 2] | 0;
+ HEAP32[$76 + 12 >> 2] = HEAP32[$77 + 12 >> 2] | 0;
+ $arrayidx209_1 = $pts + 16 | 0;
+ $sub210_1 = $starti_1 - 1 | 0;
+ $78 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx212_1 = $78 + ($sub210_1 << 4) | 0;
+ $79 = $arrayidx209_1;
+ $80 = $arrayidx212_1;
+ HEAP32[$79 >> 2] = HEAP32[$80 >> 2] | 0;
+ HEAP32[$79 + 4 >> 2] = HEAP32[$80 + 4 >> 2] | 0;
+ HEAP32[$79 + 8 >> 2] = HEAP32[$80 + 8 >> 2] | 0;
+ HEAP32[$79 + 12 >> 2] = HEAP32[$80 + 12 >> 2] | 0;
+ $arrayidx209_2 = $pts + 32 | 0;
+ $sub210_2 = $starti_1 - 2 | 0;
+ $81 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx212_2 = $81 + ($sub210_2 << 4) | 0;
+ $82 = $arrayidx209_2;
+ $83 = $arrayidx212_2;
+ HEAP32[$82 >> 2] = HEAP32[$83 >> 2] | 0;
+ HEAP32[$82 + 4 >> 2] = HEAP32[$83 + 4 >> 2] | 0;
+ HEAP32[$82 + 8 >> 2] = HEAP32[$83 + 8 >> 2] | 0;
+ HEAP32[$82 + 12 >> 2] = HEAP32[$83 + 12 >> 2] | 0;
+ $arrayidx209_3 = $pts + 48 | 0;
+ $sub210_3 = $starti_1 - 3 | 0;
+ $84 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx212_3 = $84 + ($sub210_3 << 4) | 0;
+ $85 = $arrayidx209_3;
+ $86 = $arrayidx212_3;
+ HEAP32[$85 >> 2] = HEAP32[$86 >> 2] | 0;
+ HEAP32[$85 + 4 >> 2] = HEAP32[$86 + 4 >> 2] | 0;
+ HEAP32[$85 + 8 >> 2] = HEAP32[$86 + 8 >> 2] | 0;
+ HEAP32[$85 + 12 >> 2] = HEAP32[$86 + 12 >> 2] | 0;
+ $call215 = _splineIntersectf($arraydecay, $bb131) | 0;
+ $tobool216 = ($call215 | 0) == 0;
+ $sub230 = $starti_1 - 3 | 0;
+ if ($tobool216) {
+ $starti_1 = $sub230;
+ label = 39;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $87 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx223 = $87 + ($starti_1 << 4) | 0;
+ $88 = $arrayidx223;
+ $89 = $pts;
+ HEAP32[$88 >> 2] = HEAP32[$89 >> 2] | 0;
+ HEAP32[$88 + 4 >> 2] = HEAP32[$89 + 4 >> 2] | 0;
+ HEAP32[$88 + 8 >> 2] = HEAP32[$89 + 8 >> 2] | 0;
+ HEAP32[$88 + 12 >> 2] = HEAP32[$89 + 12 >> 2] | 0;
+ $sub221_1 = $starti_1 - 1 | 0;
+ $90 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx223_1 = $90 + ($sub221_1 << 4) | 0;
+ $arrayidx224_1 = $pts + 16 | 0;
+ $91 = $arrayidx223_1;
+ $92 = $arrayidx224_1;
+ HEAP32[$91 >> 2] = HEAP32[$92 >> 2] | 0;
+ HEAP32[$91 + 4 >> 2] = HEAP32[$92 + 4 >> 2] | 0;
+ HEAP32[$91 + 8 >> 2] = HEAP32[$92 + 8 >> 2] | 0;
+ HEAP32[$91 + 12 >> 2] = HEAP32[$92 + 12 >> 2] | 0;
+ $sub221_2 = $starti_1 - 2 | 0;
+ $93 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx223_2 = $93 + ($sub221_2 << 4) | 0;
+ $arrayidx224_2 = $pts + 32 | 0;
+ $94 = $arrayidx223_2;
+ $95 = $arrayidx224_2;
+ HEAP32[$94 >> 2] = HEAP32[$95 >> 2] | 0;
+ HEAP32[$94 + 4 >> 2] = HEAP32[$95 + 4 >> 2] | 0;
+ HEAP32[$94 + 8 >> 2] = HEAP32[$95 + 8 >> 2] | 0;
+ HEAP32[$94 + 12 >> 2] = HEAP32[$95 + 12 >> 2] | 0;
+ $sub221_3 = $starti_1 - 3 | 0;
+ $96 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx223_3 = $96 + ($sub221_3 << 4) | 0;
+ $arrayidx224_3 = $pts + 48 | 0;
+ $97 = $arrayidx223_3;
+ $98 = $arrayidx224_3;
+ HEAP32[$97 >> 2] = HEAP32[$98 >> 2] | 0;
+ HEAP32[$97 + 4 >> 2] = HEAP32[$98 + 4 >> 2] | 0;
+ HEAP32[$97 + 8 >> 2] = HEAP32[$98 + 8 >> 2] | 0;
+ HEAP32[$97 + 12 >> 2] = HEAP32[$98 + 12 >> 2] | 0;
+ label = 46;
+ break;
+ case 42:
+ $cmp232 = ($starti_1 | 0) == 0;
+ if ($cmp232) {
+ label = 43;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 43:
+ $99 = HEAP32[$sflag >> 2] | 0;
+ $tobool235 = ($99 | 0) == 0;
+ if ($tobool235) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 44:
+ ___assert_func(107624, 447, 164144, 103696);
+ case 45:
+ $sp239 = $call22 + 16 | 0;
+ $sp240 = $7 + 16 | 0;
+ $100 = HEAP32[$list144 >> 2] | 0;
+ $arrayidx242 = $100 + ($starti_1 << 4) | 0;
+ _boxIntersectf($tmp243, $sp240, $arrayidx242, $bb131);
+ $101 = $tmp243;
+ HEAP32[$sp239 >> 2] = HEAP32[$101 >> 2] | 0;
+ HEAP32[$sp239 + 4 >> 2] = HEAP32[$101 + 4 >> 2] | 0;
+ HEAP32[$sp239 + 8 >> 2] = HEAP32[$101 + 8 >> 2] | 0;
+ HEAP32[$sp239 + 12 >> 2] = HEAP32[$101 + 12 >> 2] | 0;
+ $starti_3157 = $starti_1;
+ label = 50;
+ break;
+ case 46:
+ $sub245 = $starti_1 - 3 | 0;
+ $102 = HEAP32[$sflag >> 2] | 0;
+ $tobool247 = ($102 | 0) == 0;
+ if ($tobool247) {
+ $starti_3157 = $sub245;
+ label = 50;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $103 = HEAP32[$list144 >> 2] | 0;
+ $sub250 = $endi_5 - 3 | 0;
+ $104 = $e;
+ $call252 = _arrowStartClip($104, $103, $sub245, $sub250, $11, $102) | 0;
+ $starti_3157 = $call252;
+ label = 50;
+ break;
+ case 48:
+ $105 = HEAP32[$sflag >> 2] | 0;
+ $tobool261 = ($105 | 0) == 0;
+ if ($tobool261) {
+ $starti_3157 = 0;
+ label = 50;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $sp263 = $call22 + 16 | 0;
+ $sp264 = $7 + 16 | 0;
+ $106 = $sp264;
+ HEAP32[$sp263 >> 2] = HEAP32[$106 >> 2] | 0;
+ HEAP32[$sp263 + 4 >> 2] = HEAP32[$106 + 4 >> 2] | 0;
+ HEAP32[$sp263 + 8 >> 2] = HEAP32[$106 + 8 >> 2] | 0;
+ HEAP32[$sp263 + 12 >> 2] = HEAP32[$106 + 12 >> 2] | 0;
+ $starti_3157 = 0;
+ label = 50;
+ break;
+ case 50:
+ $sub267 = $endi_5 - $starti_3157 | 0;
+ $add268 = $sub267 + 1 | 0;
+ $size269 = $call22 + 4 | 0;
+ $107 = $size269;
+ HEAP32[$107 >> 2] = $add268;
+ $mul = $add268 << 4;
+ $call271 = _gmalloc($mul) | 0;
+ $108 = $call271;
+ $list272 = $call22;
+ HEAP32[$list272 >> 2] = $108;
+ $109 = HEAP32[$107 >> 2] | 0;
+ $cmp275158 = ($109 | 0) > 0;
+ if ($cmp275158) {
+ label = 51;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 51:
+ $list279 = $7 | 0;
+ $i_2159 = 0;
+ $j_0160 = $starti_3157;
+ label = 52;
+ break;
+ case 52:
+ $110 = HEAP32[$list272 >> 2] | 0;
+ $arrayidx278 = $110 + ($i_2159 << 4) | 0;
+ $111 = HEAP32[$list279 >> 2] | 0;
+ $arrayidx280 = $111 + ($j_0160 << 4) | 0;
+ $112 = $arrayidx278;
+ $113 = $arrayidx280;
+ HEAP32[$112 >> 2] = HEAP32[$113 >> 2] | 0;
+ HEAP32[$112 + 4 >> 2] = HEAP32[$113 + 4 >> 2] | 0;
+ HEAP32[$112 + 8 >> 2] = HEAP32[$113 + 8 >> 2] | 0;
+ HEAP32[$112 + 12 >> 2] = HEAP32[$113 + 12 >> 2] | 0;
+ $inc282 = $i_2159 + 1 | 0;
+ $inc283 = $j_0160 + 1 | 0;
+ $114 = HEAP32[$107 >> 2] | 0;
+ $cmp275 = ($inc282 | 0) < ($114 | 0);
+ if ($cmp275) {
+ $i_2159 = $inc282;
+ $j_0160 = $inc283;
+ label = 52;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $list285 = $7 | 0;
+ $115 = HEAP32[$list285 >> 2] | 0;
+ $116 = $115;
+ _free($116);
+ $117 = $7;
+ _free($117);
+ $118 = HEAP32[$spl >> 2] | 0;
+ $list288 = $118 | 0;
+ HEAP32[$list288 >> 2] = $11;
+ label = 54;
+ break;
+ case 54:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _mid_pointf3014($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $div5 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $div5 = (+HEAPF64[$p + 8 >> 3] + +HEAPF64[$q + 8 >> 3]) * .5;
+ HEAPF64[$agg_result >> 3] = (+HEAPF64[$p >> 3] + +HEAPF64[$q >> 3]) * .5;
+ HEAPF64[$agg_result + 8 >> 3] = $div5;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _countHorzCross($pts, $ycoord) {
+ $pts = $pts | 0;
+ $ycoord = +$ycoord;
+ var $y = 0, $0 = 0.0, $cmp = 0, $cmp3 = 0, $cond = 0, $cond4 = 0, $cmp5 = 0, $_ = 0, $y8 = 0, $1 = 0.0, $cmp9 = 0, $cmp14 = 0, $cond15 = 0, $cond17 = 0, $cmp18 = 0, $cmp19 = 0, $or_cond = 0, $inc21 = 0, $inc21_num_crossings_1 = 0, $y8_1 = 0, $2 = 0.0, $cmp9_1 = 0, $cmp14_1 = 0, $cond15_1 = 0, $cond17_1 = 0, $cmp18_1 = 0, $cmp19_1 = 0, $or_cond_1 = 0, $inc21_1 = 0, $inc21_num_crossings_1_1 = 0, $y8_2 = 0, $3 = 0.0, $cmp9_2 = 0, $cmp14_2 = 0, $cond15_2 = 0, $cond17_2 = 0, $cmp18_2 = 0, $cmp19_2 = 0, $or_cond_2 = 0, $inc21_2 = 0, $inc21_num_crossings_1_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $y = $pts + 8 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $cmp = $0 < $ycoord;
+ if ($cmp) {
+ $cond4 = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp3 = $0 > $ycoord;
+ $cond = $cmp3 & 1;
+ $cond4 = $cond;
+ label = 4;
+ break;
+ case 4:
+ $cmp5 = ($cond4 | 0) == 0;
+ $_ = $cmp5 & 1;
+ $y8 = $pts + 24 | 0;
+ $1 = +HEAPF64[$y8 >> 3];
+ $cmp9 = $1 < $ycoord;
+ if ($cmp9) {
+ $cond17 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp14 = $1 > $ycoord;
+ $cond15 = $cmp14 & 1;
+ $cond17 = $cond15;
+ label = 6;
+ break;
+ case 6:
+ $cmp18 = ($cond17 | 0) != ($cond4 | 0);
+ $cmp19 = ($cond4 | 0) != 0;
+ $or_cond = $cmp18 & $cmp19;
+ $inc21 = $or_cond & 1;
+ $inc21_num_crossings_1 = $inc21 + $_ | 0;
+ $y8_1 = $pts + 40 | 0;
+ $2 = +HEAPF64[$y8_1 >> 3];
+ $cmp9_1 = $2 < $ycoord;
+ if ($cmp9_1) {
+ $cond17_1 = -1;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp14_1 = $2 > $ycoord;
+ $cond15_1 = $cmp14_1 & 1;
+ $cond17_1 = $cond15_1;
+ label = 8;
+ break;
+ case 8:
+ $cmp18_1 = ($cond17_1 | 0) != ($cond17 | 0);
+ $cmp19_1 = ($cond17 | 0) != 0;
+ $or_cond_1 = $cmp18_1 & $cmp19_1;
+ $inc21_1 = $or_cond_1 & 1;
+ $inc21_num_crossings_1_1 = $inc21_1 + $inc21_num_crossings_1 | 0;
+ $y8_2 = $pts + 56 | 0;
+ $3 = +HEAPF64[$y8_2 >> 3];
+ $cmp9_2 = $3 < $ycoord;
+ if ($cmp9_2) {
+ $cond17_2 = -1;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp14_2 = $3 > $ycoord;
+ $cond15_2 = $cmp14_2 & 1;
+ $cond17_2 = $cond15_2;
+ label = 10;
+ break;
+ case 10:
+ $cmp18_2 = ($cond17_2 | 0) != ($cond17_1 | 0);
+ $cmp19_2 = ($cond17_1 | 0) != 0;
+ $or_cond_2 = $cmp18_2 & $cmp19_2;
+ $inc21_2 = $or_cond_2 & 1;
+ $inc21_num_crossings_1_2 = $inc21_2 + $inc21_num_crossings_1_1 | 0;
+ return $inc21_num_crossings_1_2 | 0;
+ }
+ return 0;
+}
+function _countVertCross($pts, $xcoord) {
+ $pts = $pts | 0;
+ $xcoord = +$xcoord;
+ var $x = 0, $0 = 0.0, $cmp = 0, $cmp3 = 0, $cond = 0, $cond4 = 0, $cmp5 = 0, $_ = 0, $x8 = 0, $1 = 0.0, $cmp9 = 0, $cmp14 = 0, $cond15 = 0, $cond17 = 0, $cmp18 = 0, $cmp19 = 0, $or_cond = 0, $inc21 = 0, $inc21_num_crossings_1 = 0, $x8_1 = 0, $2 = 0.0, $cmp9_1 = 0, $cmp14_1 = 0, $cond15_1 = 0, $cond17_1 = 0, $cmp18_1 = 0, $cmp19_1 = 0, $or_cond_1 = 0, $inc21_1 = 0, $inc21_num_crossings_1_1 = 0, $x8_2 = 0, $3 = 0.0, $cmp9_2 = 0, $cmp14_2 = 0, $cond15_2 = 0, $cond17_2 = 0, $cmp18_2 = 0, $cmp19_2 = 0, $or_cond_2 = 0, $inc21_2 = 0, $inc21_num_crossings_1_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $pts | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $cmp = $0 < $xcoord;
+ if ($cmp) {
+ $cond4 = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp3 = $0 > $xcoord;
+ $cond = $cmp3 & 1;
+ $cond4 = $cond;
+ label = 4;
+ break;
+ case 4:
+ $cmp5 = ($cond4 | 0) == 0;
+ $_ = $cmp5 & 1;
+ $x8 = $pts + 16 | 0;
+ $1 = +HEAPF64[$x8 >> 3];
+ $cmp9 = $1 < $xcoord;
+ if ($cmp9) {
+ $cond17 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp14 = $1 > $xcoord;
+ $cond15 = $cmp14 & 1;
+ $cond17 = $cond15;
+ label = 6;
+ break;
+ case 6:
+ $cmp18 = ($cond17 | 0) != ($cond4 | 0);
+ $cmp19 = ($cond4 | 0) != 0;
+ $or_cond = $cmp18 & $cmp19;
+ $inc21 = $or_cond & 1;
+ $inc21_num_crossings_1 = $inc21 + $_ | 0;
+ $x8_1 = $pts + 32 | 0;
+ $2 = +HEAPF64[$x8_1 >> 3];
+ $cmp9_1 = $2 < $xcoord;
+ if ($cmp9_1) {
+ $cond17_1 = -1;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp14_1 = $2 > $xcoord;
+ $cond15_1 = $cmp14_1 & 1;
+ $cond17_1 = $cond15_1;
+ label = 8;
+ break;
+ case 8:
+ $cmp18_1 = ($cond17_1 | 0) != ($cond17 | 0);
+ $cmp19_1 = ($cond17 | 0) != 0;
+ $or_cond_1 = $cmp18_1 & $cmp19_1;
+ $inc21_1 = $or_cond_1 & 1;
+ $inc21_num_crossings_1_1 = $inc21_1 + $inc21_num_crossings_1 | 0;
+ $x8_2 = $pts + 48 | 0;
+ $3 = +HEAPF64[$x8_2 >> 3];
+ $cmp9_2 = $3 < $xcoord;
+ if ($cmp9_2) {
+ $cond17_2 = -1;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp14_2 = $3 > $xcoord;
+ $cond15_2 = $cmp14_2 & 1;
+ $cond17_2 = $cond15_2;
+ label = 10;
+ break;
+ case 10:
+ $cmp18_2 = ($cond17_2 | 0) != ($cond17_1 | 0);
+ $cmp19_2 = ($cond17_1 | 0) != 0;
+ $or_cond_2 = $cmp18_2 & $cmp19_2;
+ $inc21_2 = $or_cond_2 & 1;
+ $inc21_num_crossings_1_2 = $inc21_2 + $inc21_num_crossings_1_1 | 0;
+ return $inc21_num_crossings_1_2 | 0;
+ }
+ return 0;
+}
+function _downcandidate($v) {
+ $v = $v | 0;
+ var $node_type = 0, $0 = 0, $cmp = 0, $size = 0, $1 = 0, $cmp3 = 0, $size7 = 0, $2 = 0, $cmp8 = 0, $label = 0, $3 = 0, $cmp11 = 0, $phitmp = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $v + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 3:
+ $size = $v + 180 | 0;
+ $1 = HEAP32[$size >> 2] | 0;
+ $cmp3 = ($1 | 0) == 1;
+ if ($cmp3) {
+ label = 4;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 4:
+ $size7 = $v + 188 | 0;
+ $2 = HEAP32[$size7 >> 2] | 0;
+ $cmp8 = ($2 | 0) == 1;
+ if ($cmp8) {
+ label = 5;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $label = $v + 120 | 0;
+ $3 = HEAP32[$label >> 2] | 0;
+ $cmp11 = ($3 | 0) == 0;
+ $phitmp = $cmp11 & 1;
+ $4 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ return $4 | 0;
+ }
+ return 0;
+}
+function _splineIntersectf($pts, $bb) {
+ $pts = $pts | 0;
+ $bb = $bb | 0;
+ var $origpts = 0, $tmp = 0, $tmp19 = 0, $tmp38 = 0, $tmp57 = 0, $0 = 0, $1 = 0, $arrayidx_1 = 0, $arrayidx1_1 = 0, $2 = 0, $3 = 0, $arrayidx_2 = 0, $arrayidx1_2 = 0, $4 = 0, $5 = 0, $arrayidx_3 = 0, $arrayidx1_3 = 0, $6 = 0, $7 = 0, $x = 0, $8 = 0.0, $y = 0, $9 = 0.0, $y3 = 0, $10 = 0.0, $call = 0.0, $cmp4 = 0, $cmp5 = 0, $or_cond = 0, $arraydecay = 0, $tmin_0 = 0.0, $cmp6 = 0, $cond = 0.0, $x8 = 0, $11 = 0.0, $12 = 0.0, $13 = 0.0, $call13 = 0.0, $cmp14 = 0, $cmp16 = 0, $or_cond48 = 0, $arraydecay18 = 0, $tmin_1 = 0.0, $cmp21 = 0, $cond25 = 0.0, $14 = 0.0, $15 = 0.0, $16 = 0.0, $call32 = 0.0, $cmp33 = 0, $cmp35 = 0, $or_cond49 = 0, $arraydecay37 = 0, $tmin_2 = 0.0, $cmp40 = 0, $cond44 = 0.0, $17 = 0.0, $18 = 0.0, $19 = 0.0, $call51 = 0.0, $cmp52 = 0, $cmp54 = 0, $or_cond50 = 0, $arraydecay56 = 0, $tmin_3 = 0.0, $cmp59 = 0, $_ = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 128 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $origpts = __stackBase__ | 0;
+ $tmp = __stackBase__ + 64 | 0;
+ $tmp19 = __stackBase__ + 80 | 0;
+ $tmp38 = __stackBase__ + 96 | 0;
+ $tmp57 = __stackBase__ + 112 | 0;
+ $0 = $origpts;
+ $1 = $pts;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $arrayidx_1 = $origpts + 16 | 0;
+ $arrayidx1_1 = $pts + 16 | 0;
+ $2 = $arrayidx_1;
+ $3 = $arrayidx1_1;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $arrayidx_2 = $origpts + 32 | 0;
+ $arrayidx1_2 = $pts + 32 | 0;
+ $4 = $arrayidx_2;
+ $5 = $arrayidx1_2;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $arrayidx_3 = $origpts + 48 | 0;
+ $arrayidx1_3 = $pts + 48 | 0;
+ $6 = $arrayidx_3;
+ $7 = $arrayidx1_3;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $x = $bb | 0;
+ $8 = +HEAPF64[$x >> 3];
+ $y = $bb + 8 | 0;
+ $9 = +HEAPF64[$y >> 3];
+ $y3 = $bb + 24 | 0;
+ $10 = +HEAPF64[$y3 >> 3];
+ $call = +_findVertical($pts, 0.0, 1.0, $8, $9, $10);
+ $cmp4 = $call >= 0.0;
+ $cmp5 = $call < 2.0;
+ $or_cond = $cmp4 & $cmp5;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ $tmin_0 = 2.0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $arraydecay = $origpts | 0;
+ _Bezier($tmp, $arraydecay, 3, $call, $pts, 0);
+ $tmin_0 = $call;
+ label = 4;
+ break;
+ case 4:
+ $cmp6 = $tmin_0 > 1.0;
+ $cond = $cmp6 ? 1.0 : $tmin_0;
+ $x8 = $bb + 16 | 0;
+ $11 = +HEAPF64[$x8 >> 3];
+ $12 = +HEAPF64[$y >> 3];
+ $13 = +HEAPF64[$y3 >> 3];
+ $call13 = +_findVertical($pts, 0.0, $cond, $11, $12, $13);
+ $cmp14 = $call13 >= 0.0;
+ $cmp16 = $call13 < $tmin_0;
+ $or_cond48 = $cmp14 & $cmp16;
+ if ($or_cond48) {
+ label = 5;
+ break;
+ } else {
+ $tmin_1 = $tmin_0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $arraydecay18 = $origpts | 0;
+ _Bezier($tmp19, $arraydecay18, 3, $call13, $pts, 0);
+ $tmin_1 = $call13;
+ label = 6;
+ break;
+ case 6:
+ $cmp21 = $tmin_1 > 1.0;
+ $cond25 = $cmp21 ? 1.0 : $tmin_1;
+ $14 = +HEAPF64[$y >> 3];
+ $15 = +HEAPF64[$x >> 3];
+ $16 = +HEAPF64[$x8 >> 3];
+ $call32 = +_findHorizontal($pts, 0.0, $cond25, $14, $15, $16);
+ $cmp33 = $call32 >= 0.0;
+ $cmp35 = $call32 < $tmin_1;
+ $or_cond49 = $cmp33 & $cmp35;
+ if ($or_cond49) {
+ label = 7;
+ break;
+ } else {
+ $tmin_2 = $tmin_1;
+ label = 8;
+ break;
+ }
+ case 7:
+ $arraydecay37 = $origpts | 0;
+ _Bezier($tmp38, $arraydecay37, 3, $call32, $pts, 0);
+ $tmin_2 = $call32;
+ label = 8;
+ break;
+ case 8:
+ $cmp40 = $tmin_2 > 1.0;
+ $cond44 = $cmp40 ? 1.0 : $tmin_2;
+ $17 = +HEAPF64[$y3 >> 3];
+ $18 = +HEAPF64[$x >> 3];
+ $19 = +HEAPF64[$x8 >> 3];
+ $call51 = +_findHorizontal($pts, 0.0, $cond44, $17, $18, $19);
+ $cmp52 = $call51 >= 0.0;
+ $cmp54 = $call51 < $tmin_2;
+ $or_cond50 = $cmp52 & $cmp54;
+ if ($or_cond50) {
+ label = 9;
+ break;
+ } else {
+ $tmin_3 = $tmin_2;
+ label = 10;
+ break;
+ }
+ case 9:
+ $arraydecay56 = $origpts | 0;
+ _Bezier($tmp57, $arraydecay56, 3, $call51, $pts, 0);
+ $tmin_3 = $call51;
+ label = 10;
+ break;
+ case 10:
+ $cmp59 = $tmin_3 < 2.0;
+ $_ = $cmp59 & 1;
+ STACKTOP = __stackBase__;
+ return $_ | 0;
+ }
+ return 0;
+}
+function _findVertical($pts, $tmin, $tmax, $xcoord, $ymin, $ymax) {
+ $pts = $pts | 0;
+ $tmin = +$tmin;
+ $tmax = +$tmax;
+ $xcoord = +$xcoord;
+ $ymin = +$ymin;
+ $ymax = +$ymax;
+ var $Left = 0, $Right = 0, $tmp = 0, $call = 0, $x = 0, $0 = 0.0, $cmp2 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $cmp8 = 0, $add11 = 0.0, $sub14 = 0.0, $add11_sink = 0.0, $conv12 = 0, $cmp18 = 0, $y = 0, $1 = 0.0, $cmp22 = 0, $cmp27 = 0, $or_cond = 0, $_tmax = 0.0, $arraydecay = 0, $arraydecay31 = 0, $add33 = 0.0, $div = 0.0, $call34 = 0.0, $cmp35 = 0, $call42 = 0.0, $retval_0 = 0.0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $Left = __stackBase__ | 0;
+ $Right = __stackBase__ + 64 | 0;
+ $tmp = __stackBase__ + 128 | 0;
+ $call = _countVertCross($pts, $xcoord) | 0;
+ if (($call | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($call | 0) == 0) {
+ $retval_0 = -1.0;
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 3:
+ $x = $pts + 48 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $cmp2 = $0 < 0.0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $add = $0 + .5;
+ $add_sink = $add;
+ label = 6;
+ break;
+ case 5:
+ $sub = $0 + -.5;
+ $add_sink = $sub;
+ label = 6;
+ break;
+ case 6:
+ $conv = ~~$add_sink;
+ $cmp8 = $xcoord < 0.0;
+ if ($cmp8) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add11 = $xcoord + .5;
+ $add11_sink = $add11;
+ label = 9;
+ break;
+ case 8:
+ $sub14 = $xcoord + -.5;
+ $add11_sink = $sub14;
+ label = 9;
+ break;
+ case 9:
+ $conv12 = ~~$add11_sink;
+ $cmp18 = ($conv | 0) == ($conv12 | 0);
+ if ($cmp18) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $y = $pts + 56 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $cmp22 = $1 < $ymin;
+ $cmp27 = $1 > $ymax;
+ $or_cond = $cmp22 | $cmp27;
+ $_tmax = $or_cond ? -1.0 : $tmax;
+ STACKTOP = __stackBase__;
+ return +$_tmax;
+ case 11:
+ $arraydecay = $Left | 0;
+ $arraydecay31 = $Right | 0;
+ _Bezier($tmp, $pts, 3, .5, $arraydecay, $arraydecay31);
+ $add33 = $tmin + $tmax;
+ $div = $add33 * .5;
+ $call34 = +_findVertical($arraydecay, $tmin, $div, $xcoord, $ymin, $ymax);
+ $cmp35 = $call34 < 0.0;
+ if ($cmp35) {
+ label = 12;
+ break;
+ } else {
+ $retval_0 = $call34;
+ label = 13;
+ break;
+ }
+ case 12:
+ $call42 = +_findVertical($arraydecay31, $div, $tmax, $xcoord, $ymin, $ymax);
+ $retval_0 = $call42;
+ label = 13;
+ break;
+ case 13:
+ STACKTOP = __stackBase__;
+ return +$retval_0;
+ }
+ return 0.0;
+}
+function _findHorizontal($pts, $tmin, $tmax, $ycoord, $xmin, $xmax) {
+ $pts = $pts | 0;
+ $tmin = +$tmin;
+ $tmax = +$tmax;
+ $ycoord = +$ycoord;
+ $xmin = +$xmin;
+ $xmax = +$xmax;
+ var $Left = 0, $Right = 0, $tmp = 0, $call = 0, $y = 0, $0 = 0.0, $cmp2 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $cmp8 = 0, $add11 = 0.0, $sub14 = 0.0, $add11_sink = 0.0, $conv12 = 0, $cmp18 = 0, $x = 0, $1 = 0.0, $cmp22 = 0, $cmp27 = 0, $or_cond = 0, $_tmax = 0.0, $arraydecay = 0, $arraydecay31 = 0, $add33 = 0.0, $div = 0.0, $call34 = 0.0, $cmp35 = 0, $call42 = 0.0, $retval_0 = 0.0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $Left = __stackBase__ | 0;
+ $Right = __stackBase__ + 64 | 0;
+ $tmp = __stackBase__ + 128 | 0;
+ $call = _countHorzCross($pts, $ycoord) | 0;
+ if (($call | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($call | 0) == 0) {
+ $retval_0 = -1.0;
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 3:
+ $y = $pts + 56 | 0;
+ $0 = +HEAPF64[$y >> 3];
+ $cmp2 = $0 < 0.0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $add = $0 + .5;
+ $add_sink = $add;
+ label = 6;
+ break;
+ case 5:
+ $sub = $0 + -.5;
+ $add_sink = $sub;
+ label = 6;
+ break;
+ case 6:
+ $conv = ~~$add_sink;
+ $cmp8 = $ycoord < 0.0;
+ if ($cmp8) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add11 = $ycoord + .5;
+ $add11_sink = $add11;
+ label = 9;
+ break;
+ case 8:
+ $sub14 = $ycoord + -.5;
+ $add11_sink = $sub14;
+ label = 9;
+ break;
+ case 9:
+ $conv12 = ~~$add11_sink;
+ $cmp18 = ($conv | 0) == ($conv12 | 0);
+ if ($cmp18) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $x = $pts + 48 | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $cmp22 = $1 < $xmin;
+ $cmp27 = $1 > $xmax;
+ $or_cond = $cmp22 | $cmp27;
+ $_tmax = $or_cond ? -1.0 : $tmax;
+ STACKTOP = __stackBase__;
+ return +$_tmax;
+ case 11:
+ $arraydecay = $Left | 0;
+ $arraydecay31 = $Right | 0;
+ _Bezier($tmp, $pts, 3, .5, $arraydecay, $arraydecay31);
+ $add33 = $tmin + $tmax;
+ $div = $add33 * .5;
+ $call34 = +_findHorizontal($arraydecay, $tmin, $div, $ycoord, $xmin, $xmax);
+ $cmp35 = $call34 < 0.0;
+ if ($cmp35) {
+ label = 12;
+ break;
+ } else {
+ $retval_0 = $call34;
+ label = 13;
+ break;
+ }
+ case 12:
+ $call42 = +_findHorizontal($arraydecay31, $div, $tmax, $ycoord, $xmin, $xmax);
+ $retval_0 = $call42;
+ label = 13;
+ break;
+ case 13:
+ STACKTOP = __stackBase__;
+ return +$retval_0;
+ }
+ return 0.0;
+}
+function _pf2s($p, $buf) {
+ $p = $p | 0;
+ $buf = $buf | 0;
+ var $1 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $1 = +HEAPF64[$p + 8 >> 3];
+ _sprintf($buf | 0, 155560, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = +HEAPF64[$p >> 3], HEAPF64[tempInt + 8 >> 3] = $1, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return $buf | 0;
+}
+function _dot_concentrate($g) {
+ $g = $g | 0;
+ var $maxrank = 0, $0 = 0, $conv = 0, $minrank = 0, $1 = 0, $conv2 = 0, $sub = 0, $cmp = 0, $rank = 0, $2 = 0, $n67 = 0, $3 = 0, $tobool68 = 0, $add = 0, $4 = 0, $n = 0, $5 = 0, $tobool = 0, $add70 = 0, $r_069 = 0, $6 = 0, $n963 = 0, $7 = 0, $cmp1064 = 0, $cmp5460 = 0, $8 = 0, $leftpos_065 = 0, $v = 0, $9 = 0, $arrayidx16 = 0, $10 = 0, $call = 0, $cmp18 = 0, $11 = 0, $n27 = 0, $12 = 0, $v34 = 0, $rightpos_0_in = 0, $rightpos_0 = 0, $cmp28 = 0, $13 = 0, $arrayidx35 = 0, $14 = 0, $call36 = 0, $cmp38 = 0, $sub42 = 0, $cmp43 = 0, $inc49 = 0, $15 = 0, $n9 = 0, $16 = 0, $cmp10 = 0, $r_161 = 0, $17 = 0, $n6056 = 0, $18 = 0, $cmp6157 = 0, $n_cluster = 0, $19 = 0, $cmp10954 = 0, $clust = 0, $20 = 0, $leftpos_158 = 0, $v67 = 0, $21 = 0, $arrayidx68 = 0, $22 = 0, $call69 = 0, $cmp71 = 0, $23 = 0, $n80 = 0, $24 = 0, $v87 = 0, $rightpos_1_in = 0, $rightpos_1 = 0, $cmp81 = 0, $25 = 0, $arrayidx88 = 0, $26 = 0, $call89 = 0, $cmp91 = 0, $sub98 = 0, $cmp99 = 0, $inc105 = 0, $27 = 0, $n60 = 0, $28 = 0, $cmp61 = 0, $dec = 0, $cmp54 = 0, $c_055 = 0, $29 = 0, $arrayidx113 = 0, $30 = 0, $inc115 = 0, $31 = 0, $cmp109 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $maxrank = $g + 250 | 0;
+ $0 = HEAP16[$maxrank >> 1] | 0;
+ $conv = $0 << 16 >> 16;
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $conv2 = $1 << 16 >> 16;
+ $sub = $conv - $conv2 | 0;
+ $cmp = ($sub | 0) < 2;
+ if ($cmp) {
+ label = 26;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $rank = $g + 224 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $n67 = $2 + 88 | 0;
+ $3 = HEAP32[$n67 >> 2] | 0;
+ $tobool68 = ($3 | 0) == 0;
+ if ($tobool68) {
+ $r_161 = 1;
+ label = 14;
+ break;
+ } else {
+ $r_069 = 1;
+ $add70 = 2;
+ label = 5;
+ break;
+ }
+ case 4:
+ $add = $add70 + 1 | 0;
+ $4 = HEAP32[$rank >> 2] | 0;
+ $n = $4 + ($add * 44 & -1) | 0;
+ $5 = HEAP32[$n >> 2] | 0;
+ $tobool = ($5 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $r_069 = $add70;
+ $add70 = $add;
+ label = 5;
+ break;
+ }
+ case 5:
+ $6 = HEAP32[$rank >> 2] | 0;
+ $n963 = $6 + ($r_069 * 44 & -1) | 0;
+ $7 = HEAP32[$n963 >> 2] | 0;
+ $cmp1064 = ($7 | 0) > 0;
+ if ($cmp1064) {
+ $leftpos_065 = 0;
+ $8 = $6;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 6:
+ $cmp5460 = ($add70 | 0) > 0;
+ if ($cmp5460) {
+ $r_161 = $add70;
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 7:
+ $v = $8 + ($r_069 * 44 & -1) + 4 | 0;
+ $9 = HEAP32[$v >> 2] | 0;
+ $arrayidx16 = $9 + ($leftpos_065 << 2) | 0;
+ $10 = HEAP32[$arrayidx16 >> 2] | 0;
+ $call = _downcandidate($10) | 0;
+ $cmp18 = $call << 24 >> 24 == 0;
+ if ($cmp18) {
+ label = 13;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $11 = HEAP32[$rank >> 2] | 0;
+ $n27 = $11 + ($r_069 * 44 & -1) | 0;
+ $12 = HEAP32[$n27 >> 2] | 0;
+ $v34 = $11 + ($r_069 * 44 & -1) + 4 | 0;
+ $rightpos_0_in = $leftpos_065;
+ label = 9;
+ break;
+ case 9:
+ $rightpos_0 = $rightpos_0_in + 1 | 0;
+ $cmp28 = ($rightpos_0 | 0) < ($12 | 0);
+ if ($cmp28) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $13 = HEAP32[$v34 >> 2] | 0;
+ $arrayidx35 = $13 + ($rightpos_0 << 2) | 0;
+ $14 = HEAP32[$arrayidx35 >> 2] | 0;
+ $call36 = _bothdowncandidates($10, $14) | 0;
+ $cmp38 = $call36 << 24 >> 24 == 0;
+ if ($cmp38) {
+ label = 11;
+ break;
+ } else {
+ $rightpos_0_in = $rightpos_0;
+ label = 9;
+ break;
+ }
+ case 11:
+ $sub42 = $rightpos_0 - $leftpos_065 | 0;
+ $cmp43 = ($sub42 | 0) > 1;
+ if ($cmp43) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ _mergevirtual($g, $r_069, $leftpos_065, $rightpos_0_in, 1);
+ label = 13;
+ break;
+ case 13:
+ $inc49 = $leftpos_065 + 1 | 0;
+ $15 = HEAP32[$rank >> 2] | 0;
+ $n9 = $15 + ($r_069 * 44 & -1) | 0;
+ $16 = HEAP32[$n9 >> 2] | 0;
+ $cmp10 = ($inc49 | 0) < ($16 | 0);
+ if ($cmp10) {
+ $leftpos_065 = $inc49;
+ $8 = $15;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 14:
+ $17 = HEAP32[$rank >> 2] | 0;
+ $n6056 = $17 + ($r_161 * 44 & -1) | 0;
+ $18 = HEAP32[$n6056 >> 2] | 0;
+ $cmp6157 = ($18 | 0) > 0;
+ if ($cmp6157) {
+ $leftpos_158 = 0;
+ $20 = $17;
+ label = 17;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 15:
+ $n_cluster = $g + 212 | 0;
+ $19 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp10954 = ($19 | 0) < 1;
+ if ($cmp10954) {
+ label = 26;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $clust = $g + 216 | 0;
+ $c_055 = 1;
+ label = 25;
+ break;
+ case 17:
+ $v67 = $20 + ($r_161 * 44 & -1) + 4 | 0;
+ $21 = HEAP32[$v67 >> 2] | 0;
+ $arrayidx68 = $21 + ($leftpos_158 << 2) | 0;
+ $22 = HEAP32[$arrayidx68 >> 2] | 0;
+ $call69 = _upcandidate($22) | 0;
+ $cmp71 = $call69 << 24 >> 24 == 0;
+ if ($cmp71) {
+ label = 23;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $23 = HEAP32[$rank >> 2] | 0;
+ $n80 = $23 + ($r_161 * 44 & -1) | 0;
+ $24 = HEAP32[$n80 >> 2] | 0;
+ $v87 = $23 + ($r_161 * 44 & -1) + 4 | 0;
+ $rightpos_1_in = $leftpos_158;
+ label = 19;
+ break;
+ case 19:
+ $rightpos_1 = $rightpos_1_in + 1 | 0;
+ $cmp81 = ($rightpos_1 | 0) < ($24 | 0);
+ if ($cmp81) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $25 = HEAP32[$v87 >> 2] | 0;
+ $arrayidx88 = $25 + ($rightpos_1 << 2) | 0;
+ $26 = HEAP32[$arrayidx88 >> 2] | 0;
+ $call89 = _bothupcandidates($22, $26) | 0;
+ $cmp91 = $call89 << 24 >> 24 == 0;
+ if ($cmp91) {
+ label = 21;
+ break;
+ } else {
+ $rightpos_1_in = $rightpos_1;
+ label = 19;
+ break;
+ }
+ case 21:
+ $sub98 = $rightpos_1 - $leftpos_158 | 0;
+ $cmp99 = ($sub98 | 0) > 1;
+ if ($cmp99) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ _mergevirtual($g, $r_161, $leftpos_158, $rightpos_1_in, 0);
+ label = 23;
+ break;
+ case 23:
+ $inc105 = $leftpos_158 + 1 | 0;
+ $27 = HEAP32[$rank >> 2] | 0;
+ $n60 = $27 + ($r_161 * 44 & -1) | 0;
+ $28 = HEAP32[$n60 >> 2] | 0;
+ $cmp61 = ($inc105 | 0) < ($28 | 0);
+ if ($cmp61) {
+ $leftpos_158 = $inc105;
+ $20 = $27;
+ label = 17;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $dec = $r_161 - 1 | 0;
+ $cmp54 = ($dec | 0) > 0;
+ if ($cmp54) {
+ $r_161 = $dec;
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 25:
+ $29 = HEAP32[$clust >> 2] | 0;
+ $arrayidx113 = $29 + ($c_055 << 2) | 0;
+ $30 = HEAP32[$arrayidx113 >> 2] | 0;
+ _rebuild_vlists($30);
+ $inc115 = $c_055 + 1 | 0;
+ $31 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp109 = ($inc115 | 0) > ($31 | 0);
+ if ($cmp109) {
+ label = 26;
+ break;
+ } else {
+ $c_055 = $inc115;
+ label = 25;
+ break;
+ }
+ case 26:
+ return;
+ }
+}
+function _bothdowncandidates($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ var $list = 0, $0 = 0, $1 = 0, $list4 = 0, $2 = 0, $3 = 0, $call = 0, $tobool = 0, $tail = 0, $4 = 0, $tail6 = 0, $5 = 0, $cmp = 0, $call8 = 0, $tobool10 = 0, $tail_port = 0, $tail_port13 = 0, $call14 = 0, $cmp15 = 0, $phitmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $u + 176 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $list4 = $v + 176 | 0;
+ $2 = HEAP32[$list4 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $call = _downcandidate($v) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail = $1 + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $tail6 = $3 + 16 | 0;
+ $5 = HEAP32[$tail6 >> 2] | 0;
+ $cmp = ($4 | 0) == ($5 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ }
+ case 4:
+ $call8 = _samedir($1, $3) | 0;
+ $tobool10 = $call8 << 24 >> 24 == 0;
+ if ($tobool10) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $tail_port = $1 + 32 | 0;
+ $tail_port13 = $3 + 32 | 0;
+ $call14 = _portcmp($tail_port, $tail_port13) | 0;
+ $cmp15 = ($call14 | 0) == 0;
+ $phitmp = $cmp15 & 1;
+ $retval_0 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _boxIntersectf($agg_result, $pp, $cp, $bp) {
+ $agg_result = $agg_result | 0;
+ $pp = $pp | 0;
+ $cp = $cp | 0;
+ $bp = $bp | 0;
+ var $ll = 0, $ur = 0, $ppbuf = 0, $cpbuf = 0, $llbuf = 0, $urbuf = 0, $x = 0, $0 = 0.0, $y = 0, $1 = 0.0, $x1 = 0, $2 = 0.0, $y2 = 0, $3 = 0.0, $4 = 0, $5 = 0, $UR = 0, $6 = 0, $7 = 0, $8 = 0.0, $x4 = 0, $9 = 0.0, $cmp = 0, $10 = 0.0, $sub = 0.0, $sub9 = 0.0, $mul = 0.0, $sub10 = 0.0, $div = 0.0, $conv = 0, $conv11 = 0.0, $add = 0.0, $y14 = 0, $11 = 0.0, $cmp15 = 0, $y18 = 0, $12 = 0.0, $cmp19 = 0, $ipp_sroa_0_0__idx25 = 0, $ipp_sroa_1_8__idx36 = 0, $13 = 0.0, $x24 = 0, $14 = 0.0, $cmp25 = 0, $15 = 0.0, $sub32 = 0.0, $sub33 = 0.0, $mul34 = 0.0, $sub35 = 0.0, $div36 = 0.0, $conv37 = 0, $conv38 = 0.0, $add39 = 0.0, $y42 = 0, $16 = 0.0, $cmp43 = 0, $y47 = 0, $17 = 0.0, $cmp48 = 0, $ipp_sroa_0_0__idx22 = 0, $ipp_sroa_1_8__idx32 = 0, $18 = 0.0, $y54 = 0, $19 = 0.0, $cmp55 = 0, $20 = 0.0, $sub62 = 0.0, $sub63 = 0.0, $mul64 = 0.0, $sub65 = 0.0, $div66 = 0.0, $conv67 = 0, $conv68 = 0.0, $add69 = 0.0, $21 = 0.0, $cmp73 = 0, $22 = 0.0, $cmp78 = 0, $ipp_sroa_0_0__idx18 = 0, $ipp_sroa_1_8__idx29 = 0, $23 = 0.0, $y84 = 0, $24 = 0.0, $cmp85 = 0, $25 = 0.0, $sub92 = 0.0, $sub93 = 0.0, $mul94 = 0.0, $sub95 = 0.0, $div96 = 0.0, $conv97 = 0, $conv98 = 0.0, $add99 = 0.0, $26 = 0.0, $cmp103 = 0, $27 = 0.0, $cmp108 = 0, $ipp_sroa_0_0__idx = 0, $ipp_sroa_1_8__idx28 = 0, $arraydecay = 0, $call = 0, $arraydecay113 = 0, $call114 = 0, $arraydecay115 = 0, $call116 = 0, $arraydecay117 = 0, $call118 = 0, $call119 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 448 | 0;
+ tempParam = $pp;
+ $pp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$pp >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$pp + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$pp + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$pp + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $cp;
+ $cp = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$cp >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$cp + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$cp + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$cp + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ll = __stackBase__ | 0;
+ $ur = __stackBase__ + 16 | 0;
+ $ppbuf = __stackBase__ + 32 | 0;
+ $cpbuf = __stackBase__ + 136 | 0;
+ $llbuf = __stackBase__ + 240 | 0;
+ $urbuf = __stackBase__ + 344 | 0;
+ $x = $pp | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $y = $pp + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $x1 = $cp | 0;
+ $2 = +HEAPF64[$x1 >> 3];
+ $y2 = $cp + 8 | 0;
+ $3 = +HEAPF64[$y2 >> 3];
+ $4 = $ll;
+ $5 = $bp;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $UR = $bp + 16 | 0;
+ $6 = $ur;
+ $7 = $UR;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ $8 = +HEAPF64[$x1 >> 3];
+ $x4 = $ll | 0;
+ $9 = +HEAPF64[$x4 >> 3];
+ $cmp = $8 < $9;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $10 = +HEAPF64[$y >> 3];
+ $sub = $9 - $0;
+ $sub9 = $1 - $3;
+ $mul = $sub9 * $sub;
+ $sub10 = $0 - $2;
+ $div = $mul / $sub10;
+ $conv = ~~$div;
+ $conv11 = +($conv | 0);
+ $add = $10 + $conv11;
+ $y14 = $ll + 8 | 0;
+ $11 = +HEAPF64[$y14 >> 3];
+ $cmp15 = $add < $11;
+ if ($cmp15) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y18 = $ur + 8 | 0;
+ $12 = +HEAPF64[$y18 >> 3];
+ $cmp19 = $add > $12;
+ if ($cmp19) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $ipp_sroa_0_0__idx25 = $agg_result | 0;
+ HEAPF64[$ipp_sroa_0_0__idx25 >> 3] = $9;
+ $ipp_sroa_1_8__idx36 = $agg_result + 8 | 0;
+ HEAPF64[$ipp_sroa_1_8__idx36 >> 3] = $add;
+ label = 19;
+ break;
+ case 6:
+ $13 = +HEAPF64[$x1 >> 3];
+ $x24 = $ur | 0;
+ $14 = +HEAPF64[$x24 >> 3];
+ $cmp25 = $13 > $14;
+ if ($cmp25) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $15 = +HEAPF64[$y >> 3];
+ $sub32 = $14 - $0;
+ $sub33 = $1 - $3;
+ $mul34 = $sub33 * $sub32;
+ $sub35 = $0 - $2;
+ $div36 = $mul34 / $sub35;
+ $conv37 = ~~$div36;
+ $conv38 = +($conv37 | 0);
+ $add39 = $15 + $conv38;
+ $y42 = $ll + 8 | 0;
+ $16 = +HEAPF64[$y42 >> 3];
+ $cmp43 = $add39 < $16;
+ if ($cmp43) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $y47 = $ur + 8 | 0;
+ $17 = +HEAPF64[$y47 >> 3];
+ $cmp48 = $add39 > $17;
+ if ($cmp48) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $ipp_sroa_0_0__idx22 = $agg_result | 0;
+ HEAPF64[$ipp_sroa_0_0__idx22 >> 3] = $14;
+ $ipp_sroa_1_8__idx32 = $agg_result + 8 | 0;
+ HEAPF64[$ipp_sroa_1_8__idx32 >> 3] = $add39;
+ label = 19;
+ break;
+ case 10:
+ $18 = +HEAPF64[$y2 >> 3];
+ $y54 = $ll + 8 | 0;
+ $19 = +HEAPF64[$y54 >> 3];
+ $cmp55 = $18 < $19;
+ if ($cmp55) {
+ label = 11;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 11:
+ $20 = +HEAPF64[$x >> 3];
+ $sub62 = $19 - $1;
+ $sub63 = $0 - $2;
+ $mul64 = $sub63 * $sub62;
+ $sub65 = $1 - $3;
+ $div66 = $mul64 / $sub65;
+ $conv67 = ~~$div66;
+ $conv68 = +($conv67 | 0);
+ $add69 = $20 + $conv68;
+ $21 = +HEAPF64[$x4 >> 3];
+ $cmp73 = $add69 < $21;
+ if ($cmp73) {
+ label = 14;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $22 = +HEAPF64[$x24 >> 3];
+ $cmp78 = $add69 > $22;
+ if ($cmp78) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $ipp_sroa_0_0__idx18 = $agg_result | 0;
+ HEAPF64[$ipp_sroa_0_0__idx18 >> 3] = $add69;
+ $ipp_sroa_1_8__idx29 = $agg_result + 8 | 0;
+ HEAPF64[$ipp_sroa_1_8__idx29 >> 3] = $19;
+ label = 19;
+ break;
+ case 14:
+ $23 = +HEAPF64[$y2 >> 3];
+ $y84 = $ur + 8 | 0;
+ $24 = +HEAPF64[$y84 >> 3];
+ $cmp85 = $23 > $24;
+ if ($cmp85) {
+ label = 15;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 15:
+ $25 = +HEAPF64[$x >> 3];
+ $sub92 = $24 - $1;
+ $sub93 = $0 - $2;
+ $mul94 = $sub93 * $sub92;
+ $sub95 = $1 - $3;
+ $div96 = $mul94 / $sub95;
+ $conv97 = ~~$div96;
+ $conv98 = +($conv97 | 0);
+ $add99 = $25 + $conv98;
+ $26 = +HEAPF64[$x4 >> 3];
+ $cmp103 = $add99 < $26;
+ if ($cmp103) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $27 = +HEAPF64[$x24 >> 3];
+ $cmp108 = $add99 > $27;
+ if ($cmp108) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $ipp_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$ipp_sroa_0_0__idx >> 3] = $add99;
+ $ipp_sroa_1_8__idx28 = $agg_result + 8 | 0;
+ HEAPF64[$ipp_sroa_1_8__idx28 >> 3] = $24;
+ label = 19;
+ break;
+ case 18:
+ $arraydecay = $ppbuf | 0;
+ $call = _pf2s($pp, $arraydecay) | 0;
+ $arraydecay113 = $cpbuf | 0;
+ $call114 = _pf2s($cp, $arraydecay113) | 0;
+ $arraydecay115 = $llbuf | 0;
+ $call116 = _pf2s($ll, $arraydecay115) | 0;
+ $arraydecay117 = $urbuf | 0;
+ $call118 = _pf2s($ur, $arraydecay117) | 0;
+ $call119 = _agerr(1, 162176, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $call, HEAP32[tempInt + 8 >> 2] = $call114, HEAP32[tempInt + 16 >> 2] = $call116, HEAP32[tempInt + 24 >> 2] = $call118, tempInt) | 0) | 0;
+ ___assert_func(107624, 78, 164592, 158672);
+ case 19:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _upcandidate($v) {
+ $v = $v | 0;
+ var $node_type = 0, $0 = 0, $cmp = 0, $size = 0, $1 = 0, $cmp3 = 0, $size7 = 0, $2 = 0, $cmp8 = 0, $label = 0, $3 = 0, $cmp11 = 0, $phitmp = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $v + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 3:
+ $size = $v + 188 | 0;
+ $1 = HEAP32[$size >> 2] | 0;
+ $cmp3 = ($1 | 0) == 1;
+ if ($cmp3) {
+ label = 4;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 4:
+ $size7 = $v + 180 | 0;
+ $2 = HEAP32[$size7 >> 2] | 0;
+ $cmp8 = ($2 | 0) == 1;
+ if ($cmp8) {
+ label = 5;
+ break;
+ } else {
+ $4 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $label = $v + 120 | 0;
+ $3 = HEAP32[$label >> 2] | 0;
+ $cmp11 = ($3 | 0) == 0;
+ $phitmp = $cmp11 & 1;
+ $4 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ return $4 | 0;
+ }
+ return 0;
+}
+function _infuse($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $rank = 0, $0 = 0, $rankleader = 0, $1 = 0, $arrayidx = 0, $2 = 0, $cmp = 0, $order = 0, $3 = 0, $order4 = 0, $4 = 0, $cmp5 = 0, $5 = 0, $6 = 0, $arrayidx10 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $n + 236 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $rankleader = $g + 280 | 0;
+ $1 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx = $1 + ($0 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp = ($2 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $order = $2 + 240 | 0;
+ $3 = HEAP32[$order >> 2] | 0;
+ $order4 = $n + 240 | 0;
+ $4 = HEAP32[$order4 >> 2] | 0;
+ $cmp5 = ($3 | 0) > ($4 | 0);
+ if ($cmp5) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $5 = HEAP32[$rank >> 2] | 0;
+ $6 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx10 = $6 + ($5 << 2) | 0;
+ HEAP32[$arrayidx10 >> 2] = $n;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _samedir($e, $f) {
+ $e = $e | 0;
+ $f = $f | 0;
+ var $edge_type12 = 0, $0 = 0, $cmp13 = 0, $e0_0_lcssa = 0, $edge_type59 = 0, $1 = 0, $cmp710 = 0, $e0_014 = 0, $to_orig = 0, $2 = 0, $edge_type = 0, $3 = 0, $cmp = 0, $f0_011 = 0, $to_orig12 = 0, $4 = 0, $edge_type5 = 0, $5 = 0, $cmp7 = 0, $f0_0_lcssa = 0, $conc_opp_flag = 0, $6 = 0, $tobool = 0, $conc_opp_flag16 = 0, $7 = 0, $tobool17 = 0, $tail = 0, $8 = 0, $rank = 0, $9 = 0, $head = 0, $10 = 0, $rank22 = 0, $11 = 0, $sub = 0, $tail23 = 0, $12 = 0, $rank25 = 0, $13 = 0, $head26 = 0, $14 = 0, $rank28 = 0, $15 = 0, $sub29 = 0, $mul = 0, $cmp30 = 0, $conv32 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $edge_type12 = $e + 128 | 0;
+ $0 = HEAP8[$edge_type12] | 0;
+ $cmp13 = $0 << 24 >> 24 == 0;
+ if ($cmp13) {
+ $e0_0_lcssa = $e;
+ label = 3;
+ break;
+ } else {
+ $e0_014 = $e;
+ label = 4;
+ break;
+ }
+ case 3:
+ $edge_type59 = $f + 128 | 0;
+ $1 = HEAP8[$edge_type59] | 0;
+ $cmp710 = $1 << 24 >> 24 == 0;
+ if ($cmp710) {
+ $f0_0_lcssa = $f;
+ label = 6;
+ break;
+ } else {
+ $f0_011 = $f;
+ label = 5;
+ break;
+ }
+ case 4:
+ $to_orig = $e0_014 + 132 | 0;
+ $2 = HEAP32[$to_orig >> 2] | 0;
+ $edge_type = $2 + 128 | 0;
+ $3 = HEAP8[$edge_type] | 0;
+ $cmp = $3 << 24 >> 24 == 0;
+ if ($cmp) {
+ $e0_0_lcssa = $2;
+ label = 3;
+ break;
+ } else {
+ $e0_014 = $2;
+ label = 4;
+ break;
+ }
+ case 5:
+ $to_orig12 = $f0_011 + 132 | 0;
+ $4 = HEAP32[$to_orig12 >> 2] | 0;
+ $edge_type5 = $4 + 128 | 0;
+ $5 = HEAP8[$edge_type5] | 0;
+ $cmp7 = $5 << 24 >> 24 == 0;
+ if ($cmp7) {
+ $f0_0_lcssa = $4;
+ label = 6;
+ break;
+ } else {
+ $f0_011 = $4;
+ label = 5;
+ break;
+ }
+ case 6:
+ $conc_opp_flag = $e0_0_lcssa + 169 | 0;
+ $6 = HEAP8[$conc_opp_flag] | 0;
+ $tobool = $6 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ }
+ case 7:
+ $conc_opp_flag16 = $f0_0_lcssa + 169 | 0;
+ $7 = HEAP8[$conc_opp_flag16] | 0;
+ $tobool17 = $7 << 24 >> 24 == 0;
+ if ($tobool17) {
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ }
+ case 8:
+ $tail = $f0_0_lcssa + 16 | 0;
+ $8 = HEAP32[$tail >> 2] | 0;
+ $rank = $8 + 236 | 0;
+ $9 = HEAP32[$rank >> 2] | 0;
+ $head = $f0_0_lcssa + 12 | 0;
+ $10 = HEAP32[$head >> 2] | 0;
+ $rank22 = $10 + 236 | 0;
+ $11 = HEAP32[$rank22 >> 2] | 0;
+ $sub = $9 - $11 | 0;
+ $tail23 = $e0_0_lcssa + 16 | 0;
+ $12 = HEAP32[$tail23 >> 2] | 0;
+ $rank25 = $12 + 236 | 0;
+ $13 = HEAP32[$rank25 >> 2] | 0;
+ $head26 = $e0_0_lcssa + 12 | 0;
+ $14 = HEAP32[$head26 >> 2] | 0;
+ $rank28 = $14 + 236 | 0;
+ $15 = HEAP32[$rank28 >> 2] | 0;
+ $sub29 = $13 - $15 | 0;
+ $mul = Math_imul($sub29, $sub);
+ $cmp30 = ($mul | 0) > 0;
+ $conv32 = $cmp30 & 1;
+ $retval_0 = $conv32;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _begin_component() {
+ HEAP32[(HEAP32[41878] | 0) + 220 >> 2] = 0;
+ HEAP32[41654] = 0;
+ return;
+}
+function _bothupcandidates($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ var $list = 0, $0 = 0, $1 = 0, $list4 = 0, $2 = 0, $3 = 0, $call = 0, $tobool = 0, $head = 0, $4 = 0, $head6 = 0, $5 = 0, $cmp = 0, $call8 = 0, $tobool10 = 0, $head_port = 0, $head_port13 = 0, $call14 = 0, $cmp15 = 0, $phitmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $u + 184 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $list4 = $v + 184 | 0;
+ $2 = HEAP32[$list4 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $call = _upcandidate($v) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $1 + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ $head6 = $3 + 12 | 0;
+ $5 = HEAP32[$head6 >> 2] | 0;
+ $cmp = ($4 | 0) == ($5 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ }
+ case 4:
+ $call8 = _samedir($1, $3) | 0;
+ $tobool10 = $call8 << 24 >> 24 == 0;
+ if ($tobool10) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $head_port = $1 + 72 | 0;
+ $head_port13 = $3 + 72 | 0;
+ $call14 = _portcmp($head_port, $head_port13) | 0;
+ $cmp15 = ($call14 | 0) == 0;
+ $phitmp = $cmp15 & 1;
+ $retval_0 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _decompose($g, $pass) {
+ $g = $g | 0;
+ $pass = $pass | 0;
+ var $0 = 0, $inc = 0, $cmp = 0, $_inc = 0, $size = 0, $n_nodes = 0, $1 = 0, $call = 0, $tobool14 = 0, $cmp3 = 0, $n_016_in = 0, $n_016 = 0, $u5 = 0, $clust = 0, $2 = 0, $3 = 0, $tobool6 = 0, $rank = 0, $4 = 0, $5 = 0, $rankleader = 0, $6 = 0, $arrayidx = 0, $7 = 0, $call10 = 0, $cmp11 = 0, $v_0 = 0, $mark = 0, $8 = 0, $9 = 0, $cmp19 = 0, $call23 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[41878] = $g;
+ $0 = HEAP8[167968] | 0;
+ $inc = $0 + 1 & 255;
+ $cmp = $inc << 24 >> 24 == 0;
+ $_inc = $cmp ? 1 : $inc;
+ HEAP8[167968] = $_inc;
+ $size = $g + 232 | 0;
+ HEAP32[$size >> 2] = 0;
+ $n_nodes = $g + 244 | 0;
+ HEAP32[$n_nodes >> 2] = 0;
+ $1 = $g;
+ $call = _agfstnode($1) | 0;
+ $tobool14 = ($call | 0) == 0;
+ if ($tobool14) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp3 = ($pass | 0) > 0;
+ $n_016_in = $call;
+ label = 4;
+ break;
+ case 4:
+ $n_016 = $n_016_in;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $u5 = $n_016_in + 24 | 0;
+ $clust = $u5 + 192 | 0;
+ $2 = $clust;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool6 = ($3 | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $rank = $u5 + 212 | 0;
+ $4 = $rank;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $rankleader = $3 + 280 | 0;
+ $6 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx = $6 + ($5 << 2) | 0;
+ $7 = HEAP32[$arrayidx >> 2] | 0;
+ $v_0 = $7;
+ label = 8;
+ break;
+ case 7:
+ $call10 = _UF_find($n_016) | 0;
+ $cmp11 = ($n_016 | 0) == ($call10 | 0);
+ if ($cmp11) {
+ $v_0 = $n_016;
+ label = 8;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 8:
+ $mark = $v_0 + 163 | 0;
+ $8 = HEAP8[$mark] | 0;
+ $9 = HEAP8[167968] | 0;
+ $cmp19 = $8 << 24 >> 24 == $9 << 24 >> 24;
+ if ($cmp19) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ _begin_component();
+ _search_component($v_0);
+ _end_component();
+ label = 10;
+ break;
+ case 10:
+ $call23 = _agnxtnode($1, $n_016_in) | 0;
+ $tobool = ($call23 | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ $n_016_in = $call23;
+ label = 4;
+ break;
+ }
+ case 11:
+ return;
+ }
+}
+function _search_component($n) {
+ $n = $n | 0;
+ var $vec1 = 0, $vec1_sub = 0, $out = 0, $0 = 0, $ld$0$0 = 0, $1$0 = 0, $ld$1$1 = 0, $1$1 = 0, $st$2$0 = 0, $st$3$1 = 0, $arrayidx1 = 0, $in = 0, $2 = 0, $ld$4$0 = 0, $3$0 = 0, $ld$5$1 = 0, $3$1 = 0, $st$6$0 = 0, $st$7$1 = 0, $arrayidx3 = 0, $flat_out = 0, $4 = 0, $ld$8$0 = 0, $5$0 = 0, $ld$9$1 = 0, $5$1 = 0, $st$10$0 = 0, $st$11$1 = 0, $arrayidx5 = 0, $flat_in = 0, $6 = 0, $ld$12$0 = 0, $7$0 = 0, $ld$13$1 = 0, $7$1 = 0, $st$14$0 = 0, $st$15$1 = 0, $list = 0, $8 = 0, $tobool = 0, $9 = 0, $10 = 0, $tobool123 = 0, $11 = 0, $12 = 0, $i_04 = 0, $head = 0, $13 = 0, $cmp14 = 0, $tail = 0, $14 = 0, $other_0 = 0, $mark = 0, $15 = 0, $16 = 0, $cmp18 = 0, $call = 0, $cmp20 = 0, $inc = 0, $arrayidx11 = 0, $17 = 0, $tobool12 = 0, $list_1 = 0, $18 = 0, $19 = 0, $tobool_1 = 0, $20 = 0, $21 = 0, $tobool123_1 = 0, $22 = 0, $23 = 0, $i_04_1 = 0, $head_1 = 0, $24 = 0, $cmp14_1 = 0, $tail_1 = 0, $25 = 0, $other_0_1 = 0, $mark_1 = 0, $26 = 0, $27 = 0, $cmp18_1 = 0, $call_1 = 0, $cmp20_1 = 0, $inc_1 = 0, $arrayidx11_1 = 0, $28 = 0, $tobool12_1 = 0, $list_2 = 0, $29 = 0, $30 = 0, $tobool_2 = 0, $31 = 0, $32 = 0, $tobool123_2 = 0, $33 = 0, $34 = 0, $i_04_2 = 0, $head_2 = 0, $35 = 0, $cmp14_2 = 0, $tail_2 = 0, $36 = 0, $other_0_2 = 0, $mark_2 = 0, $37 = 0, $38 = 0, $cmp18_2 = 0, $call_2 = 0, $cmp20_2 = 0, $inc_2 = 0, $arrayidx11_2 = 0, $39 = 0, $tobool12_2 = 0, $list_3 = 0, $40 = 0, $41 = 0, $tobool_3 = 0, $42 = 0, $43 = 0, $tobool123_3 = 0, $44 = 0, $45 = 0, $i_04_3 = 0, $head_3 = 0, $46 = 0, $cmp14_3 = 0, $tail_3 = 0, $47 = 0, $other_0_3 = 0, $mark_3 = 0, $48 = 0, $49 = 0, $cmp18_3 = 0, $call_3 = 0, $cmp20_3 = 0, $inc_3 = 0, $arrayidx11_3 = 0, $50 = 0, $tobool12_3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $vec1 = __stackBase__ | 0;
+ $vec1_sub = $vec1 | 0;
+ _add_to_component($n);
+ $out = $n + 184 | 0;
+ $0 = $out;
+ $ld$0$0 = $0 | 0;
+ $1$0 = HEAP32[$ld$0$0 >> 2] | 0;
+ $ld$1$1 = $0 + 4 | 0;
+ $1$1 = HEAP32[$ld$1$1 >> 2] | 0;
+ $st$2$0 = $vec1_sub | 0;
+ HEAP32[$st$2$0 >> 2] = $1$0;
+ $st$3$1 = $vec1_sub + 4 | 0;
+ HEAP32[$st$3$1 >> 2] = $1$1;
+ $arrayidx1 = $vec1 + 8 | 0;
+ $in = $n + 176 | 0;
+ $2 = $in;
+ $ld$4$0 = $2 | 0;
+ $3$0 = HEAP32[$ld$4$0 >> 2] | 0;
+ $ld$5$1 = $2 + 4 | 0;
+ $3$1 = HEAP32[$ld$5$1 >> 2] | 0;
+ $st$6$0 = $arrayidx1 | 0;
+ HEAP32[$st$6$0 >> 2] = $3$0;
+ $st$7$1 = $arrayidx1 + 4 | 0;
+ HEAP32[$st$7$1 >> 2] = $3$1;
+ $arrayidx3 = $vec1 + 16 | 0;
+ $flat_out = $n + 192 | 0;
+ $4 = $flat_out;
+ $ld$8$0 = $4 | 0;
+ $5$0 = HEAP32[$ld$8$0 >> 2] | 0;
+ $ld$9$1 = $4 + 4 | 0;
+ $5$1 = HEAP32[$ld$9$1 >> 2] | 0;
+ $st$10$0 = $arrayidx3 | 0;
+ HEAP32[$st$10$0 >> 2] = $5$0;
+ $st$11$1 = $arrayidx3 + 4 | 0;
+ HEAP32[$st$11$1 >> 2] = $5$1;
+ $arrayidx5 = $vec1 + 24 | 0;
+ $flat_in = $n + 200 | 0;
+ $6 = $flat_in;
+ $ld$12$0 = $6 | 0;
+ $7$0 = HEAP32[$ld$12$0 >> 2] | 0;
+ $ld$13$1 = $6 + 4 | 0;
+ $7$1 = HEAP32[$ld$13$1 >> 2] | 0;
+ $st$14$0 = $arrayidx5 | 0;
+ HEAP32[$st$14$0 >> 2] = $7$0;
+ $st$15$1 = $arrayidx5 + 4 | 0;
+ HEAP32[$st$15$1 >> 2] = $7$1;
+ $list = $vec1;
+ $8 = HEAP32[$list >> 2] | 0;
+ $tobool = ($8 | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $9 = HEAP32[$list >> 2] | 0;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $tobool123 = ($10 | 0) == 0;
+ if ($tobool123) {
+ label = 11;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $11 = HEAP32[$list >> 2] | 0;
+ $i_04 = 0;
+ $12 = $10;
+ label = 5;
+ break;
+ case 5:
+ $head = $12 + 12 | 0;
+ $13 = HEAP32[$head >> 2] | 0;
+ $cmp14 = ($13 | 0) == ($n | 0);
+ if ($cmp14) {
+ label = 6;
+ break;
+ } else {
+ $other_0 = $13;
+ label = 7;
+ break;
+ }
+ case 6:
+ $tail = $12 + 16 | 0;
+ $14 = HEAP32[$tail >> 2] | 0;
+ $other_0 = $14;
+ label = 7;
+ break;
+ case 7:
+ $mark = $other_0 + 163 | 0;
+ $15 = HEAP8[$mark] | 0;
+ $16 = HEAP8[167968] | 0;
+ $cmp18 = $15 << 24 >> 24 == $16 << 24 >> 24;
+ if ($cmp18) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call = _UF_find($other_0) | 0;
+ $cmp20 = ($other_0 | 0) == ($call | 0);
+ if ($cmp20) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ _search_component($other_0);
+ label = 10;
+ break;
+ case 10:
+ $inc = $i_04 + 1 | 0;
+ $arrayidx11 = $11 + ($inc << 2) | 0;
+ $17 = HEAP32[$arrayidx11 >> 2] | 0;
+ $tobool12 = ($17 | 0) == 0;
+ if ($tobool12) {
+ label = 11;
+ break;
+ } else {
+ $i_04 = $inc;
+ $12 = $17;
+ label = 5;
+ break;
+ }
+ case 11:
+ $list_1 = $vec1 + 8 | 0;
+ $18 = $list_1;
+ $19 = HEAP32[$18 >> 2] | 0;
+ $tobool_1 = ($19 | 0) == 0;
+ if ($tobool_1) {
+ label = 20;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $20 = HEAP32[$18 >> 2] | 0;
+ $21 = HEAP32[$20 >> 2] | 0;
+ $tobool123_1 = ($21 | 0) == 0;
+ if ($tobool123_1) {
+ label = 20;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $22 = HEAP32[$18 >> 2] | 0;
+ $i_04_1 = 0;
+ $23 = $21;
+ label = 14;
+ break;
+ case 14:
+ $head_1 = $23 + 12 | 0;
+ $24 = HEAP32[$head_1 >> 2] | 0;
+ $cmp14_1 = ($24 | 0) == ($n | 0);
+ if ($cmp14_1) {
+ label = 15;
+ break;
+ } else {
+ $other_0_1 = $24;
+ label = 16;
+ break;
+ }
+ case 15:
+ $tail_1 = $23 + 16 | 0;
+ $25 = HEAP32[$tail_1 >> 2] | 0;
+ $other_0_1 = $25;
+ label = 16;
+ break;
+ case 16:
+ $mark_1 = $other_0_1 + 163 | 0;
+ $26 = HEAP8[$mark_1] | 0;
+ $27 = HEAP8[167968] | 0;
+ $cmp18_1 = $26 << 24 >> 24 == $27 << 24 >> 24;
+ if ($cmp18_1) {
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $call_1 = _UF_find($other_0_1) | 0;
+ $cmp20_1 = ($other_0_1 | 0) == ($call_1 | 0);
+ if ($cmp20_1) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ _search_component($other_0_1);
+ label = 19;
+ break;
+ case 19:
+ $inc_1 = $i_04_1 + 1 | 0;
+ $arrayidx11_1 = $22 + ($inc_1 << 2) | 0;
+ $28 = HEAP32[$arrayidx11_1 >> 2] | 0;
+ $tobool12_1 = ($28 | 0) == 0;
+ if ($tobool12_1) {
+ label = 20;
+ break;
+ } else {
+ $i_04_1 = $inc_1;
+ $23 = $28;
+ label = 14;
+ break;
+ }
+ case 20:
+ $list_2 = $vec1 + 16 | 0;
+ $29 = $list_2;
+ $30 = HEAP32[$29 >> 2] | 0;
+ $tobool_2 = ($30 | 0) == 0;
+ if ($tobool_2) {
+ label = 29;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $31 = HEAP32[$29 >> 2] | 0;
+ $32 = HEAP32[$31 >> 2] | 0;
+ $tobool123_2 = ($32 | 0) == 0;
+ if ($tobool123_2) {
+ label = 29;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $33 = HEAP32[$29 >> 2] | 0;
+ $i_04_2 = 0;
+ $34 = $32;
+ label = 23;
+ break;
+ case 23:
+ $head_2 = $34 + 12 | 0;
+ $35 = HEAP32[$head_2 >> 2] | 0;
+ $cmp14_2 = ($35 | 0) == ($n | 0);
+ if ($cmp14_2) {
+ label = 24;
+ break;
+ } else {
+ $other_0_2 = $35;
+ label = 25;
+ break;
+ }
+ case 24:
+ $tail_2 = $34 + 16 | 0;
+ $36 = HEAP32[$tail_2 >> 2] | 0;
+ $other_0_2 = $36;
+ label = 25;
+ break;
+ case 25:
+ $mark_2 = $other_0_2 + 163 | 0;
+ $37 = HEAP8[$mark_2] | 0;
+ $38 = HEAP8[167968] | 0;
+ $cmp18_2 = $37 << 24 >> 24 == $38 << 24 >> 24;
+ if ($cmp18_2) {
+ label = 28;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $call_2 = _UF_find($other_0_2) | 0;
+ $cmp20_2 = ($other_0_2 | 0) == ($call_2 | 0);
+ if ($cmp20_2) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ _search_component($other_0_2);
+ label = 28;
+ break;
+ case 28:
+ $inc_2 = $i_04_2 + 1 | 0;
+ $arrayidx11_2 = $33 + ($inc_2 << 2) | 0;
+ $39 = HEAP32[$arrayidx11_2 >> 2] | 0;
+ $tobool12_2 = ($39 | 0) == 0;
+ if ($tobool12_2) {
+ label = 29;
+ break;
+ } else {
+ $i_04_2 = $inc_2;
+ $34 = $39;
+ label = 23;
+ break;
+ }
+ case 29:
+ $list_3 = $vec1 + 24 | 0;
+ $40 = $list_3;
+ $41 = HEAP32[$40 >> 2] | 0;
+ $tobool_3 = ($41 | 0) == 0;
+ if ($tobool_3) {
+ label = 38;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $42 = HEAP32[$40 >> 2] | 0;
+ $43 = HEAP32[$42 >> 2] | 0;
+ $tobool123_3 = ($43 | 0) == 0;
+ if ($tobool123_3) {
+ label = 38;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $44 = HEAP32[$40 >> 2] | 0;
+ $i_04_3 = 0;
+ $45 = $43;
+ label = 32;
+ break;
+ case 32:
+ $head_3 = $45 + 12 | 0;
+ $46 = HEAP32[$head_3 >> 2] | 0;
+ $cmp14_3 = ($46 | 0) == ($n | 0);
+ if ($cmp14_3) {
+ label = 33;
+ break;
+ } else {
+ $other_0_3 = $46;
+ label = 34;
+ break;
+ }
+ case 33:
+ $tail_3 = $45 + 16 | 0;
+ $47 = HEAP32[$tail_3 >> 2] | 0;
+ $other_0_3 = $47;
+ label = 34;
+ break;
+ case 34:
+ $mark_3 = $other_0_3 + 163 | 0;
+ $48 = HEAP8[$mark_3] | 0;
+ $49 = HEAP8[167968] | 0;
+ $cmp18_3 = $48 << 24 >> 24 == $49 << 24 >> 24;
+ if ($cmp18_3) {
+ label = 37;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $call_3 = _UF_find($other_0_3) | 0;
+ $cmp20_3 = ($other_0_3 | 0) == ($call_3 | 0);
+ if ($cmp20_3) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ _search_component($other_0_3);
+ label = 37;
+ break;
+ case 37:
+ $inc_3 = $i_04_3 + 1 | 0;
+ $arrayidx11_3 = $44 + ($inc_3 << 2) | 0;
+ $50 = HEAP32[$arrayidx11_3 >> 2] | 0;
+ $tobool12_3 = ($50 | 0) == 0;
+ if ($tobool12_3) {
+ label = 38;
+ break;
+ } else {
+ $i_04_3 = $inc_3;
+ $45 = $50;
+ label = 32;
+ break;
+ }
+ case 38:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _mergevirtual($g, $r, $lpos, $rpos, $dir) {
+ $g = $g | 0;
+ $r = $r | 0;
+ $lpos = $lpos | 0;
+ $rpos = $rpos | 0;
+ $dir = $dir | 0;
+ var $rank = 0, $0 = 0, $v = 0, $1 = 0, $arrayidx1 = 0, $2 = 0, $add = 0, $cmp69 = 0, $cmp7 = 0, $3 = 0, $list41 = 0, $4 = 0, $list13 = 0, $5 = 0, $i_156 = 0, $6 = 0, $n57 = 0, $7 = 0, $cmp8358 = 0, $i_070 = 0, $8 = 0, $v5 = 0, $9 = 0, $arrayidx6 = 0, $10 = 0, $list = 0, $11 = 0, $12 = 0, $tobool68 = 0, $list26 = 0, $list34 = 0, $13 = 0, $14 = 0, $tobool3664 = 0, $list60 = 0, $15 = 0, $16 = 0, $head17 = 0, $k_0 = 0, $arrayidx14 = 0, $17 = 0, $cond = 0, $head = 0, $18 = 0, $19 = 0, $cmp18 = 0, $inc = 0, $head22 = 0, $20 = 0, $21 = 0, $22 = 0, $call = 0, $23 = 0, $f_0_ph = 0, $24 = 0, $25 = 0, $tobool2866 = 0, $26 = 0, $27 = 0, $28 = 0, $29 = 0, $30 = 0, $tobool28 = 0, $31 = 0, $32 = 0, $33 = 0, $tobool = 0, $34 = 0, $35 = 0, $tail45 = 0, $k_1 = 0, $arrayidx42 = 0, $36 = 0, $cond55 = 0, $tail = 0, $37 = 0, $38 = 0, $cmp46 = 0, $inc50 = 0, $tail54 = 0, $39 = 0, $40 = 0, $41 = 0, $call55 = 0, $42 = 0, $f_1_ph = 0, $43 = 0, $44 = 0, $tobool6263 = 0, $45 = 0, $46 = 0, $47 = 0, $48 = 0, $49 = 0, $tobool62 = 0, $50 = 0, $51 = 0, $52 = 0, $tobool36 = 0, $size = 0, $53 = 0, $size71 = 0, $54 = 0, $add72 = 0, $cmp73 = 0, $55 = 0, $inc75 = 0, $cmp = 0, $56 = 0, $i_160 = 0, $k_259 = 0, $v89 = 0, $57 = 0, $arrayidx90 = 0, $58 = 0, $arrayidx95 = 0, $order = 0, $inc97 = 0, $i_1 = 0, $59 = 0, $n = 0, $60 = 0, $cmp83 = 0, $n_lcssa = 0, $k_2_lcssa = 0, $61 = 0, $v107 = 0, $62 = 0, $arrayidx108 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $g + 224 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $v = $0 + ($r * 44 & -1) + 4 | 0;
+ $1 = HEAP32[$v >> 2] | 0;
+ $arrayidx1 = $1 + ($lpos << 2) | 0;
+ $2 = HEAP32[$arrayidx1 >> 2] | 0;
+ $add = $lpos + 1 | 0;
+ $cmp69 = ($add | 0) > ($rpos | 0);
+ if ($cmp69) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp7 = ($dir | 0) == 1;
+ $3 = $g;
+ $list41 = $2 + 176 | 0;
+ $4 = $2;
+ $list13 = $2 + 184 | 0;
+ $5 = $2;
+ $i_070 = $add;
+ label = 5;
+ break;
+ case 4:
+ $i_156 = $rpos + 1 | 0;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $n57 = $6 + ($r * 44 & -1) | 0;
+ $7 = HEAP32[$n57 >> 2] | 0;
+ $cmp8358 = ($i_156 | 0) < ($7 | 0);
+ if ($cmp8358) {
+ $k_259 = $add;
+ $i_160 = $i_156;
+ $56 = $6;
+ label = 29;
+ break;
+ } else {
+ $k_2_lcssa = $add;
+ $n_lcssa = $n57;
+ label = 30;
+ break;
+ }
+ case 5:
+ $8 = HEAP32[$rank >> 2] | 0;
+ $v5 = $8 + ($r * 44 & -1) + 4 | 0;
+ $9 = HEAP32[$v5 >> 2] | 0;
+ $arrayidx6 = $9 + ($i_070 << 2) | 0;
+ $10 = HEAP32[$arrayidx6 >> 2] | 0;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $list = $10 + 184 | 0;
+ $11 = HEAP32[$list >> 2] | 0;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $tobool68 = ($12 | 0) == 0;
+ if ($tobool68) {
+ label = 26;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $list26 = $10 + 176 | 0;
+ $15 = $12;
+ label = 10;
+ break;
+ case 8:
+ $list34 = $10 + 176 | 0;
+ $13 = HEAP32[$list34 >> 2] | 0;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $tobool3664 = ($14 | 0) == 0;
+ if ($tobool3664) {
+ label = 26;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $list60 = $10 + 184 | 0;
+ $34 = $14;
+ label = 18;
+ break;
+ case 10:
+ $16 = HEAP32[$list13 >> 2] | 0;
+ $head17 = $15 + 12 | 0;
+ $k_0 = 0;
+ label = 11;
+ break;
+ case 11:
+ $arrayidx14 = $16 + ($k_0 << 2) | 0;
+ $17 = HEAP32[$arrayidx14 >> 2] | 0;
+ $cond = ($17 | 0) == 0;
+ if ($cond) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $head = $17 + 12 | 0;
+ $18 = HEAP32[$head >> 2] | 0;
+ $19 = HEAP32[$head17 >> 2] | 0;
+ $cmp18 = ($18 | 0) == ($19 | 0);
+ $inc = $k_0 + 1 | 0;
+ if ($cmp18) {
+ $f_0_ph = $17;
+ label = 14;
+ break;
+ } else {
+ $k_0 = $inc;
+ label = 11;
+ break;
+ }
+ case 13:
+ $head22 = $15 + 12 | 0;
+ $20 = HEAP32[$head22 >> 2] | 0;
+ $21 = $20;
+ $22 = $15;
+ $call = _virtual_edge($5, $21, $22) | 0;
+ $23 = $call;
+ $f_0_ph = $23;
+ label = 14;
+ break;
+ case 14:
+ $24 = HEAP32[$list26 >> 2] | 0;
+ $25 = HEAP32[$24 >> 2] | 0;
+ $tobool2866 = ($25 | 0) == 0;
+ if ($tobool2866) {
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $26 = $f_0_ph;
+ $27 = $25;
+ label = 16;
+ break;
+ case 16:
+ $28 = $27;
+ _merge_oneway($28, $26);
+ _delete_fast_edge($28);
+ $29 = HEAP32[$list26 >> 2] | 0;
+ $30 = HEAP32[$29 >> 2] | 0;
+ $tobool28 = ($30 | 0) == 0;
+ if ($tobool28) {
+ label = 17;
+ break;
+ } else {
+ $27 = $30;
+ label = 16;
+ break;
+ }
+ case 17:
+ $31 = $15;
+ _delete_fast_edge($31);
+ $32 = HEAP32[$list >> 2] | 0;
+ $33 = HEAP32[$32 >> 2] | 0;
+ $tobool = ($33 | 0) == 0;
+ if ($tobool) {
+ label = 26;
+ break;
+ } else {
+ $15 = $33;
+ label = 10;
+ break;
+ }
+ case 18:
+ $35 = HEAP32[$list41 >> 2] | 0;
+ $tail45 = $34 + 16 | 0;
+ $k_1 = 0;
+ label = 19;
+ break;
+ case 19:
+ $arrayidx42 = $35 + ($k_1 << 2) | 0;
+ $36 = HEAP32[$arrayidx42 >> 2] | 0;
+ $cond55 = ($36 | 0) == 0;
+ if ($cond55) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $tail = $36 + 16 | 0;
+ $37 = HEAP32[$tail >> 2] | 0;
+ $38 = HEAP32[$tail45 >> 2] | 0;
+ $cmp46 = ($37 | 0) == ($38 | 0);
+ $inc50 = $k_1 + 1 | 0;
+ if ($cmp46) {
+ $f_1_ph = $36;
+ label = 22;
+ break;
+ } else {
+ $k_1 = $inc50;
+ label = 19;
+ break;
+ }
+ case 21:
+ $tail54 = $34 + 16 | 0;
+ $39 = HEAP32[$tail54 >> 2] | 0;
+ $40 = $39;
+ $41 = $34;
+ $call55 = _virtual_edge($40, $4, $41) | 0;
+ $42 = $call55;
+ $f_1_ph = $42;
+ label = 22;
+ break;
+ case 22:
+ $43 = HEAP32[$list60 >> 2] | 0;
+ $44 = HEAP32[$43 >> 2] | 0;
+ $tobool6263 = ($44 | 0) == 0;
+ if ($tobool6263) {
+ label = 25;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $45 = $f_1_ph;
+ $46 = $44;
+ label = 24;
+ break;
+ case 24:
+ $47 = $46;
+ _merge_oneway($47, $45);
+ _delete_fast_edge($47);
+ $48 = HEAP32[$list60 >> 2] | 0;
+ $49 = HEAP32[$48 >> 2] | 0;
+ $tobool62 = ($49 | 0) == 0;
+ if ($tobool62) {
+ label = 25;
+ break;
+ } else {
+ $46 = $49;
+ label = 24;
+ break;
+ }
+ case 25:
+ $50 = $34;
+ _delete_fast_edge($50);
+ $51 = HEAP32[$list34 >> 2] | 0;
+ $52 = HEAP32[$51 >> 2] | 0;
+ $tobool36 = ($52 | 0) == 0;
+ if ($tobool36) {
+ label = 26;
+ break;
+ } else {
+ $34 = $52;
+ label = 18;
+ break;
+ }
+ case 26:
+ $size = $10 + 180 | 0;
+ $53 = HEAP32[$size >> 2] | 0;
+ $size71 = $10 + 188 | 0;
+ $54 = HEAP32[$size71 >> 2] | 0;
+ $add72 = -$54 | 0;
+ $cmp73 = ($53 | 0) == ($add72 | 0);
+ if ($cmp73) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ ___assert_func(155744, 113, 164e3, 128048);
+ case 28:
+ $55 = $10;
+ _delete_fast_node($3, $55);
+ $inc75 = $i_070 + 1 | 0;
+ $cmp = ($inc75 | 0) > ($rpos | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $i_070 = $inc75;
+ label = 5;
+ break;
+ }
+ case 29:
+ $v89 = $56 + ($r * 44 & -1) + 4 | 0;
+ $57 = HEAP32[$v89 >> 2] | 0;
+ $arrayidx90 = $57 + ($i_160 << 2) | 0;
+ $58 = HEAP32[$arrayidx90 >> 2] | 0;
+ $arrayidx95 = $57 + ($k_259 << 2) | 0;
+ HEAP32[$arrayidx95 >> 2] = $58;
+ $order = $58 + 240 | 0;
+ HEAP32[$order >> 2] = $k_259;
+ $inc97 = $k_259 + 1 | 0;
+ $i_1 = $i_160 + 1 | 0;
+ $59 = HEAP32[$rank >> 2] | 0;
+ $n = $59 + ($r * 44 & -1) | 0;
+ $60 = HEAP32[$n >> 2] | 0;
+ $cmp83 = ($i_1 | 0) < ($60 | 0);
+ if ($cmp83) {
+ $k_259 = $inc97;
+ $i_160 = $i_1;
+ $56 = $59;
+ label = 29;
+ break;
+ } else {
+ $k_2_lcssa = $inc97;
+ $n_lcssa = $n;
+ label = 30;
+ break;
+ }
+ case 30:
+ HEAP32[$n_lcssa >> 2] = $k_2_lcssa;
+ $61 = HEAP32[$rank >> 2] | 0;
+ $v107 = $61 + ($r * 44 & -1) + 4 | 0;
+ $62 = HEAP32[$v107 >> 2] | 0;
+ $arrayidx108 = $62 + ($k_2_lcssa << 2) | 0;
+ HEAP32[$arrayidx108 >> 2] = 0;
+ return;
+ }
+}
+function _rebuild_vlists($g) {
+ $g = $g | 0;
+ var $minrank = 0, $0 = 0, $maxrank = 0, $1 = 0, $cmp85 = 0, $conv = 0, $rankleader = 0, $r_086 = 0, $2 = 0, $arrayidx = 0, $inc = 0, $3 = 0, $conv2 = 0, $cmp = 0, $4 = 0, $call = 0, $tobool82 = 0, $n_0_in83 = 0, $n_0 = 0, $call7 = 0, $tobool980 = 0, $e_0_in81 = 0, $e_0 = 0, $rep_0 = 0, $to_virt = 0, $5 = 0, $tobool13 = 0, $head75 = 0, $6 = 0, $rank76 = 0, $7 = 0, $head20 = 0, $8 = 0, $rank2277 = 0, $9 = 0, $10 = 0, $cmp2378 = 0, $11 = 0, $head79 = 0, $12 = 0, $list = 0, $13 = 0, $14 = 0, $head = 0, $15 = 0, $rank = 0, $16 = 0, $17 = 0, $rank22 = 0, $18 = 0, $19 = 0, $cmp23 = 0, $call30 = 0, $tobool9 = 0, $call33 = 0, $tobool = 0, $20 = 0, $21 = 0, $cmp4272 = 0, $conv37 = 0, $rankleader46 = 0, $root = 0, $rank66 = 0, $name = 0, $22 = 0, $23 = 0, $n_cluster = 0, $24 = 0, $cmp13663 = 0, $clust = 0, $r_173 = 0, $25 = 0, $arrayidx47 = 0, $26 = 0, $order = 0, $27 = 0, $28 = 0, $rank50 = 0, $29 = 0, $v = 0, $30 = 0, $arrayidx52 = 0, $31 = 0, $cmp53 = 0, $32 = 0, $v68 = 0, $33 = 0, $n7366 = 0, $34 = 0, $cmp7467 = 0, $35 = 0, $maxi_070 = 0, $i_068 = 0, $v80 = 0, $36 = 0, $arrayidx81 = 0, $37 = 0, $cmp82 = 0, $node_type = 0, $38 = 0, $cmp88 = 0, $39 = 0, $call91 = 0, $tobool92 = 0, $list98 = 0, $40 = 0, $41 = 0, $e96_0 = 0, $tobool101 = 0, $to_orig = 0, $42 = 0, $tobool103 = 0, $tail = 0, $43 = 0, $44 = 0, $call110 = 0, $tobool111 = 0, $head113 = 0, $45 = 0, $46 = 0, $call114 = 0, $tobool115 = 0, $maxi_0_i_0 = 0, $maxi_1 = 0, $inc120 = 0, $47 = 0, $n73 = 0, $48 = 0, $cmp74 = 0, $maxi_0_lcssa = 0, $cmp122 = 0, $49 = 0, $call125 = 0, $maxi_0_lcssa91 = 0, $add = 0, $50 = 0, $n130 = 0, $inc132 = 0, $51 = 0, $conv41 = 0, $cmp42 = 0, $c_064 = 0, $52 = 0, $arrayidx140 = 0, $53 = 0, $inc142 = 0, $54 = 0, $cmp136 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $cmp85 = $0 << 16 >> 16 > $1 << 16 >> 16;
+ if ($cmp85) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rankleader = $g + 280 | 0;
+ $r_086 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx = $2 + ($r_086 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = 0;
+ $inc = $r_086 + 1 | 0;
+ $3 = HEAP16[$maxrank >> 1] | 0;
+ $conv2 = $3 << 16 >> 16;
+ $cmp = ($inc | 0) > ($conv2 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $r_086 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ _dot_scan_ranks($g);
+ $4 = $g;
+ $call = _agfstnode($4) | 0;
+ $tobool82 = ($call | 0) == 0;
+ if ($tobool82) {
+ label = 13;
+ break;
+ } else {
+ $n_0_in83 = $call;
+ label = 6;
+ break;
+ }
+ case 6:
+ $n_0 = $n_0_in83;
+ _infuse($g, $n_0);
+ $call7 = _agfstout($4, $n_0_in83) | 0;
+ $tobool980 = ($call7 | 0) == 0;
+ if ($tobool980) {
+ label = 12;
+ break;
+ } else {
+ $e_0_in81 = $call7;
+ label = 7;
+ break;
+ }
+ case 7:
+ $e_0 = $e_0_in81;
+ $rep_0 = $e_0;
+ label = 8;
+ break;
+ case 8:
+ $to_virt = $rep_0 + 188 | 0;
+ $5 = HEAP32[$to_virt >> 2] | 0;
+ $tobool13 = ($5 | 0) == 0;
+ if ($tobool13) {
+ label = 9;
+ break;
+ } else {
+ $rep_0 = $5;
+ label = 8;
+ break;
+ }
+ case 9:
+ $head75 = $rep_0 + 12 | 0;
+ $6 = HEAP32[$head75 >> 2] | 0;
+ $rank76 = $6 + 236 | 0;
+ $7 = HEAP32[$rank76 >> 2] | 0;
+ $head20 = $e_0_in81 + 12 | 0;
+ $8 = HEAP32[$head20 >> 2] | 0;
+ $rank2277 = $8 + 236 | 0;
+ $9 = $rank2277;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $cmp2378 = ($7 | 0) < ($10 | 0);
+ if ($cmp2378) {
+ $head79 = $head75;
+ $11 = $6;
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _infuse($g, $11);
+ $12 = HEAP32[$head79 >> 2] | 0;
+ $list = $12 + 184 | 0;
+ $13 = HEAP32[$list >> 2] | 0;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $head = $14 + 12 | 0;
+ $15 = HEAP32[$head >> 2] | 0;
+ $rank = $15 + 236 | 0;
+ $16 = HEAP32[$rank >> 2] | 0;
+ $17 = HEAP32[$head20 >> 2] | 0;
+ $rank22 = $17 + 236 | 0;
+ $18 = $rank22;
+ $19 = HEAP32[$18 >> 2] | 0;
+ $cmp23 = ($16 | 0) < ($19 | 0);
+ if ($cmp23) {
+ $head79 = $head;
+ $11 = $15;
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call30 = _agnxtout($4, $e_0_in81) | 0;
+ $tobool9 = ($call30 | 0) == 0;
+ if ($tobool9) {
+ label = 12;
+ break;
+ } else {
+ $e_0_in81 = $call30;
+ label = 7;
+ break;
+ }
+ case 12:
+ $call33 = _agnxtnode($4, $n_0_in83) | 0;
+ $tobool = ($call33 | 0) == 0;
+ if ($tobool) {
+ label = 13;
+ break;
+ } else {
+ $n_0_in83 = $call33;
+ label = 6;
+ break;
+ }
+ case 13:
+ $20 = HEAP16[$minrank >> 1] | 0;
+ $21 = HEAP16[$maxrank >> 1] | 0;
+ $cmp4272 = $20 << 16 >> 16 > $21 << 16 >> 16;
+ if ($cmp4272) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $conv37 = $20 << 16 >> 16;
+ $rankleader46 = $g + 280 | 0;
+ $root = $g + 32 | 0;
+ $rank66 = $g + 224 | 0;
+ $name = $g + 12 | 0;
+ $22 = $g;
+ $23 = $g;
+ $r_173 = $conv37;
+ label = 17;
+ break;
+ case 15:
+ $n_cluster = $g + 212 | 0;
+ $24 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp13663 = ($24 | 0) < 1;
+ if ($cmp13663) {
+ label = 33;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $clust = $g + 216 | 0;
+ $c_064 = 1;
+ label = 32;
+ break;
+ case 17:
+ $25 = HEAP32[$rankleader46 >> 2] | 0;
+ $arrayidx47 = $25 + ($r_173 << 2) | 0;
+ $26 = HEAP32[$arrayidx47 >> 2] | 0;
+ $order = $26 + 240 | 0;
+ $27 = HEAP32[$order >> 2] | 0;
+ $28 = HEAP32[$root >> 2] | 0;
+ $rank50 = $28 + 224 | 0;
+ $29 = HEAP32[$rank50 >> 2] | 0;
+ $v = $29 + ($r_173 * 44 & -1) + 4 | 0;
+ $30 = HEAP32[$v >> 2] | 0;
+ $arrayidx52 = $30 + ($27 << 2) | 0;
+ $31 = HEAP32[$arrayidx52 >> 2] | 0;
+ $cmp53 = ($31 | 0) == ($26 | 0);
+ if ($cmp53) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ _abort();
+ case 19:
+ $32 = HEAP32[$rank66 >> 2] | 0;
+ $v68 = $32 + ($r_173 * 44 & -1) + 4 | 0;
+ HEAP32[$v68 >> 2] = $arrayidx52;
+ $33 = HEAP32[$rank66 >> 2] | 0;
+ $n7366 = $33 + ($r_173 * 44 & -1) | 0;
+ $34 = HEAP32[$n7366 >> 2] | 0;
+ $cmp7467 = ($34 | 0) > 0;
+ if ($cmp7467) {
+ $i_068 = 0;
+ $maxi_070 = -1;
+ $35 = $33;
+ label = 20;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 20:
+ $v80 = $35 + ($r_173 * 44 & -1) + 4 | 0;
+ $36 = HEAP32[$v80 >> 2] | 0;
+ $arrayidx81 = $36 + ($i_068 << 2) | 0;
+ $37 = HEAP32[$arrayidx81 >> 2] | 0;
+ $cmp82 = ($37 | 0) == 0;
+ if ($cmp82) {
+ $maxi_0_lcssa = $maxi_070;
+ label = 29;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $node_type = $37 + 162 | 0;
+ $38 = HEAP8[$node_type] | 0;
+ $cmp88 = $38 << 24 >> 24 == 0;
+ if ($cmp88) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $39 = $37 | 0;
+ $call91 = _agcontains($22, $39) | 0;
+ $tobool92 = ($call91 | 0) == 0;
+ if ($tobool92) {
+ $maxi_0_lcssa = $maxi_070;
+ label = 29;
+ break;
+ } else {
+ $maxi_1 = $i_068;
+ label = 28;
+ break;
+ }
+ case 23:
+ $list98 = $37 + 176 | 0;
+ $40 = HEAP32[$list98 >> 2] | 0;
+ $41 = HEAP32[$40 >> 2] | 0;
+ $e96_0 = $41;
+ label = 24;
+ break;
+ case 24:
+ $tobool101 = ($e96_0 | 0) == 0;
+ if ($tobool101) {
+ $maxi_1 = $maxi_070;
+ label = 28;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $to_orig = $e96_0 + 132 | 0;
+ $42 = HEAP32[$to_orig >> 2] | 0;
+ $tobool103 = ($42 | 0) == 0;
+ if ($tobool103) {
+ label = 26;
+ break;
+ } else {
+ $e96_0 = $42;
+ label = 24;
+ break;
+ }
+ case 26:
+ $tail = $e96_0 + 16 | 0;
+ $43 = HEAP32[$tail >> 2] | 0;
+ $44 = $43 | 0;
+ $call110 = _agcontains($23, $44) | 0;
+ $tobool111 = ($call110 | 0) == 0;
+ if ($tobool111) {
+ $maxi_1 = $maxi_070;
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $head113 = $e96_0 + 12 | 0;
+ $45 = HEAP32[$head113 >> 2] | 0;
+ $46 = $45 | 0;
+ $call114 = _agcontains($23, $46) | 0;
+ $tobool115 = ($call114 | 0) == 0;
+ $maxi_0_i_0 = $tobool115 ? $maxi_070 : $i_068;
+ $maxi_1 = $maxi_0_i_0;
+ label = 28;
+ break;
+ case 28:
+ $inc120 = $i_068 + 1 | 0;
+ $47 = HEAP32[$rank66 >> 2] | 0;
+ $n73 = $47 + ($r_173 * 44 & -1) | 0;
+ $48 = HEAP32[$n73 >> 2] | 0;
+ $cmp74 = ($inc120 | 0) < ($48 | 0);
+ if ($cmp74) {
+ $i_068 = $inc120;
+ $maxi_070 = $maxi_1;
+ $35 = $47;
+ label = 20;
+ break;
+ } else {
+ $maxi_0_lcssa = $maxi_1;
+ label = 29;
+ break;
+ }
+ case 29:
+ $cmp122 = ($maxi_0_lcssa | 0) == -1;
+ if ($cmp122) {
+ label = 30;
+ break;
+ } else {
+ $maxi_0_lcssa91 = $maxi_0_lcssa;
+ label = 31;
+ break;
+ }
+ case 30:
+ $49 = HEAP32[$name >> 2] | 0;
+ $call125 = _agerr(0, 131784, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $49, HEAP32[tempInt + 8 >> 2] = $r_173, tempInt) | 0) | 0;
+ $maxi_0_lcssa91 = -1;
+ label = 31;
+ break;
+ case 31:
+ $add = $maxi_0_lcssa91 + 1 | 0;
+ $50 = HEAP32[$rank66 >> 2] | 0;
+ $n130 = $50 + ($r_173 * 44 & -1) | 0;
+ HEAP32[$n130 >> 2] = $add;
+ $inc132 = $r_173 + 1 | 0;
+ $51 = HEAP16[$maxrank >> 1] | 0;
+ $conv41 = $51 << 16 >> 16;
+ $cmp42 = ($inc132 | 0) > ($conv41 | 0);
+ if ($cmp42) {
+ label = 15;
+ break;
+ } else {
+ $r_173 = $inc132;
+ label = 17;
+ break;
+ }
+ case 32:
+ $52 = HEAP32[$clust >> 2] | 0;
+ $arrayidx140 = $52 + ($c_064 << 2) | 0;
+ $53 = HEAP32[$arrayidx140 >> 2] | 0;
+ _rebuild_vlists($53);
+ $inc142 = $c_064 + 1 | 0;
+ $54 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp136 = ($inc142 | 0) > ($54 | 0);
+ if ($cmp136) {
+ label = 33;
+ break;
+ } else {
+ $c_064 = $inc142;
+ label = 32;
+ break;
+ }
+ case 33:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _add_to_component($n) {
+ $n = $n | 0;
+ var $0 = 0, $n_nodes = 0, $1 = 0, $inc = 0, $2 = 0, $mark = 0, $3 = 0, $tobool = 0, $prev5 = 0, $4 = 0, $next = 0, $5 = 0, $nlist = 0, $next8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41878] | 0;
+ $n_nodes = $0 + 244 | 0;
+ $1 = HEAP32[$n_nodes >> 2] | 0;
+ $inc = $1 + 1 | 0;
+ HEAP32[$n_nodes >> 2] = $inc;
+ $2 = HEAP8[167968] | 0;
+ $mark = $n + 163 | 0;
+ HEAP8[$mark] = $2;
+ $3 = HEAP32[41654] | 0;
+ $tobool = ($3 | 0) == 0;
+ $prev5 = $n + 172 | 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ HEAP32[$prev5 >> 2] = $3;
+ $4 = HEAP32[41654] | 0;
+ $next = $4 + 168 | 0;
+ HEAP32[$next >> 2] = $n;
+ label = 5;
+ break;
+ case 4:
+ HEAP32[$prev5 >> 2] = 0;
+ $5 = HEAP32[41878] | 0;
+ $nlist = $5 + 220 | 0;
+ HEAP32[$nlist >> 2] = $n;
+ label = 5;
+ break;
+ case 5:
+ HEAP32[41654] = $n;
+ $next8 = $n + 168 | 0;
+ HEAP32[$next8 >> 2] = 0;
+ return;
+ }
+}
+function _portcmp($p0, $p1) {
+ $p0 = $p0 | 0;
+ $p1 = $p1 | 0;
+ var $defined = 0, $0 = 0, $cmp = 0, $defined2 = 0, $1 = 0, $tobool = 0, $cond = 0, $cmp6 = 0, $x = 0, $2 = 0.0, $x11 = 0, $3 = 0.0, $sub = 0.0, $conv12 = 0, $cmp13 = 0, $y = 0, $4 = 0.0, $y18 = 0, $5 = 0.0, $sub19 = 0.0, $conv20 = 0, $retval_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p0;
+ $p0 = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ _memcpy($p0, tempParam, 40);
+ tempParam = $p1;
+ $p1 = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ _memcpy($p1, tempParam, 40);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $defined = $p1 + 28 | 0;
+ $0 = HEAP8[$defined] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ $defined2 = $p0 + 28 | 0;
+ $1 = HEAP8[$defined2] | 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $tobool = $1 << 24 >> 24 != 0;
+ $cond = $tobool & 1;
+ $retval_0 = $cond;
+ label = 7;
+ break;
+ case 4:
+ $cmp6 = $1 << 24 >> 24 == 0;
+ if ($cmp6) {
+ $retval_0 = -1;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $x = $p0 | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x11 = $p1 | 0;
+ $3 = +HEAPF64[$x11 >> 3];
+ $sub = $2 - $3;
+ $conv12 = ~~$sub;
+ $cmp13 = ($conv12 | 0) == 0;
+ if ($cmp13) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = $conv12;
+ label = 7;
+ break;
+ }
+ case 6:
+ $y = $p0 + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y18 = $p1 + 8 | 0;
+ $5 = +HEAPF64[$y18 >> 3];
+ $sub19 = $4 - $5;
+ $conv20 = ~~$sub19;
+ $retval_0 = $conv20;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _end_component() {
+ var $0 = 0, $size = 0, $1 = 0, $inc = 0, $2 = 0, $list = 0, $3 = 0, $tobool = 0, $4 = 0, $size8 = 0, $5 = 0, $mul = 0, $call = 0, $size11 = 0, $6 = 0, $mul12 = 0, $call13 = 0, $call_sink = 0, $7 = 0, $8 = 0, $list16 = 0, $9 = 0, $nlist = 0, $10 = 0, $list20 = 0, $11 = 0, $arrayidx = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41878] | 0;
+ $size = $0 + 232 | 0;
+ $1 = HEAP32[$size >> 2] | 0;
+ $inc = $1 + 1 | 0;
+ HEAP32[$size >> 2] = $inc;
+ $2 = HEAP32[41878] | 0;
+ $list = $2 + 228 | 0;
+ $3 = HEAP32[$list >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $4 = $3;
+ $size8 = $2 + 232 | 0;
+ $5 = HEAP32[$size8 >> 2] | 0;
+ $mul = $5 << 2;
+ $call = _grealloc($4, $mul) | 0;
+ $call_sink = $call;
+ label = 5;
+ break;
+ case 4:
+ $size11 = $2 + 232 | 0;
+ $6 = HEAP32[$size11 >> 2] | 0;
+ $mul12 = $6 << 2;
+ $call13 = _gmalloc($mul12) | 0;
+ $call_sink = $call13;
+ label = 5;
+ break;
+ case 5:
+ $7 = $call_sink;
+ $8 = HEAP32[41878] | 0;
+ $list16 = $8 + 228 | 0;
+ HEAP32[$list16 >> 2] = $7;
+ $9 = HEAP32[41878] | 0;
+ $nlist = $9 + 220 | 0;
+ $10 = HEAP32[$nlist >> 2] | 0;
+ $list20 = $9 + 228 | 0;
+ $11 = HEAP32[$list20 >> 2] | 0;
+ $arrayidx = $11 + ($1 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $10;
+ return;
+ }
+}
+function _dot_init_node_edge($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool17 = 0, $n_0_in18 = 0, $n_0 = 0, $call1 = 0, $tobool = 0, $call2 = 0, $tobool415 = 0, $n_1_in16 = 0, $call6 = 0, $tobool813 = 0, $e_0_in14 = 0, $e_0 = 0, $call11 = 0, $tobool8 = 0, $call14 = 0, $tobool4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool17 = ($call | 0) == 0;
+ if ($tobool17) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in18 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $n_0 = $n_0_in18;
+ _dot_init_node($n_0);
+ $call1 = _agnxtnode($0, $n_0_in18) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in18 = $call1;
+ label = 3;
+ break;
+ }
+ case 4:
+ $call2 = _agfstnode($0) | 0;
+ $tobool415 = ($call2 | 0) == 0;
+ if ($tobool415) {
+ label = 8;
+ break;
+ } else {
+ $n_1_in16 = $call2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $call6 = _agfstout($0, $n_1_in16) | 0;
+ $tobool813 = ($call6 | 0) == 0;
+ if ($tobool813) {
+ label = 7;
+ break;
+ } else {
+ $e_0_in14 = $call6;
+ label = 6;
+ break;
+ }
+ case 6:
+ $e_0 = $e_0_in14;
+ _dot_init_edge($e_0);
+ $call11 = _agnxtout($0, $e_0_in14) | 0;
+ $tobool8 = ($call11 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ $e_0_in14 = $call11;
+ label = 6;
+ break;
+ }
+ case 7:
+ $call14 = _agnxtnode($0, $n_1_in16) | 0;
+ $tobool4 = ($call14 | 0) == 0;
+ if ($tobool4) {
+ label = 8;
+ break;
+ } else {
+ $n_1_in16 = $call14;
+ label = 5;
+ break;
+ }
+ case 8:
+ return;
+ }
+}
+function _dot_init_node($n) {
+ $n = $n | 0;
+ var $0 = 0;
+ $0 = $n;
+ _common_init_node($0);
+ _gv_nodesize($0, HEAP32[(HEAP32[$n + 20 >> 2] | 0) + 156 >> 2] & 1);
+ HEAP32[$n + 180 >> 2] = 0;
+ HEAP32[$n + 176 >> 2] = _zmalloc(20) | 0;
+ HEAP32[$n + 188 >> 2] = 0;
+ HEAP32[$n + 184 >> 2] = _zmalloc(20) | 0;
+ HEAP32[$n + 204 >> 2] = 0;
+ HEAP32[$n + 200 >> 2] = _zmalloc(12) | 0;
+ HEAP32[$n + 196 >> 2] = 0;
+ HEAP32[$n + 192 >> 2] = _zmalloc(12) | 0;
+ HEAP32[$n + 212 >> 2] = 0;
+ HEAP32[$n + 208 >> 2] = _zmalloc(12) | 0;
+ HEAP32[$n + 220 >> 2] = 1;
+ return;
+}
+function _dot_init_edge($e) {
+ $e = $e | 0;
+ var $0 = 0, $call = 0, $1 = 0, $2 = 0, $call1 = 0.0, $conv = 0.0, $weight = 0, $tail = 0, $3 = 0, $4 = 0, $5 = 0, $call2 = 0, $head = 0, $6 = 0, $7 = 0, $call3 = 0, $xpenalty = 0, $count = 0, $8 = 0, $tobool = 0, $cmp = 0, $or_cond = 0, $9 = 0.0, $mul = 0.0, $call12 = 0, $tobool13 = 0, $10 = 0, $call20 = 0, $conv21 = 0, $showboxes = 0, $11 = 0, $call23 = 0, $conv24 = 0, $minlen = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $e;
+ $call = _common_init_edge($0) | 0;
+ $1 = $e | 0;
+ $2 = HEAP32[41894] | 0;
+ $call1 = +_late_double($1, $2, 1.0, 0.0);
+ $conv = $call1;
+ $weight = $e + 172 | 0;
+ HEAPF32[$weight >> 2] = $conv;
+ $tail = $e + 16 | 0;
+ $3 = HEAP32[$tail >> 2] | 0;
+ $4 = $3 | 0;
+ $5 = HEAP32[41594] | 0;
+ $call2 = _late_string($4, $5, 107672) | 0;
+ $head = $e + 12 | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ $7 = $6 | 0;
+ $call3 = _late_string($7, $5, 107672) | 0;
+ $xpenalty = $e + 170 | 0;
+ HEAP16[$xpenalty >> 1] = 1;
+ $count = $e + 184 | 0;
+ HEAP16[$count >> 1] = 1;
+ $8 = HEAP8[$call2] | 0;
+ $tobool = $8 << 24 >> 24 != 0;
+ $cmp = ($call2 | 0) == ($call3 | 0);
+ $or_cond = $tobool & $cmp;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP16[$xpenalty >> 1] = 1e3;
+ $9 = +HEAPF32[$weight >> 2];
+ $mul = $9 * 100.0;
+ HEAPF32[$weight >> 2] = $mul;
+ label = 4;
+ break;
+ case 4:
+ $call12 = _nonconstraint_edge($0) | 0;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP16[$xpenalty >> 1] = 0;
+ HEAPF32[$weight >> 2] = 0.0;
+ label = 6;
+ break;
+ case 6:
+ $10 = HEAP32[41906] | 0;
+ $call20 = _late_int($1, $10, 0, 0) | 0;
+ $conv21 = $call20 & 255;
+ $showboxes = $e + 168 | 0;
+ HEAP8[$showboxes] = $conv21;
+ $11 = HEAP32[41918] | 0;
+ $call23 = _late_int($1, $11, 1, 0) | 0;
+ $conv24 = $call23 & 65535;
+ $minlen = $e + 186 | 0;
+ HEAP16[$minlen >> 1] = $conv24;
+ return;
+ }
+}
+function _dot_cleanup($g) {
+ $g = $g | 0;
+ var $nlist = 0, $0 = 0, $1 = 0, $call = 0, $tobool13 = 0, $n_015_in = 0, $n_015 = 0, $call1 = 0, $tobool310 = 0, $e_0_in11 = 0, $2 = 0, $call5 = 0, $tobool3 = 0, $call7 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $0 = HEAP32[$nlist >> 2] | 0;
+ _free_virtual_node_list($0);
+ $1 = $g;
+ $call = _agfstnode($1) | 0;
+ $tobool13 = ($call | 0) == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ $n_015_in = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $n_015 = $n_015_in;
+ $call1 = _agfstout($1, $n_015_in) | 0;
+ $tobool310 = ($call1 | 0) == 0;
+ if ($tobool310) {
+ label = 5;
+ break;
+ } else {
+ $e_0_in11 = $call1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = $e_0_in11;
+ _gv_cleanup_edge($2);
+ $call5 = _agnxtout($1, $e_0_in11) | 0;
+ $tobool3 = ($call5 | 0) == 0;
+ if ($tobool3) {
+ label = 5;
+ break;
+ } else {
+ $e_0_in11 = $call5;
+ label = 4;
+ break;
+ }
+ case 5:
+ _dot_cleanup_node($n_015);
+ $call7 = _agnxtnode($1, $n_015_in) | 0;
+ $tobool = ($call7 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_015_in = $call7;
+ label = 3;
+ break;
+ }
+ case 6:
+ _dot_cleanup_graph($g);
+ return;
+ }
+}
+function _free_virtual_node_list($vn) {
+ $vn = $vn | 0;
+ var $tobool9 = 0, $vn_addr_010 = 0, $next = 0, $0 = 0, $node_type = 0, $1 = 0, $cmp = 0, $list = 0, $2 = 0, $tobool4 = 0, $3 = 0, $list11 = 0, $4 = 0, $tobool12 = 0, $5 = 0, $6 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool9 = ($vn | 0) == 0;
+ if ($tobool9) {
+ label = 10;
+ break;
+ } else {
+ $vn_addr_010 = $vn;
+ label = 3;
+ break;
+ }
+ case 3:
+ $next = $vn_addr_010 + 168 | 0;
+ $0 = HEAP32[$next >> 2] | 0;
+ _free_virtual_edge_list($vn_addr_010);
+ $node_type = $vn_addr_010 + 162 | 0;
+ $1 = HEAP8[$node_type] | 0;
+ $cmp = $1 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 4:
+ $list = $vn_addr_010 + 184 | 0;
+ $2 = HEAP32[$list >> 2] | 0;
+ $tobool4 = ($2 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = $2;
+ _free($3);
+ label = 6;
+ break;
+ case 6:
+ $list11 = $vn_addr_010 + 176 | 0;
+ $4 = HEAP32[$list11 >> 2] | 0;
+ $tobool12 = ($4 | 0) == 0;
+ if ($tobool12) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $5 = $4;
+ _free($5);
+ label = 8;
+ break;
+ case 8:
+ $6 = $vn_addr_010 | 0;
+ _free($6);
+ label = 9;
+ break;
+ case 9:
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ $vn_addr_010 = $0;
+ label = 3;
+ break;
+ }
+ case 10:
+ return;
+ }
+}
+function _dot_cleanup_node($n) {
+ $n = $n | 0;
+ var $u = 0, $list = 0, $0 = 0, $tobool = 0, $1 = 0, $list6 = 0, $2 = 0, $tobool7 = 0, $3 = 0, $list16 = 0, $4 = 0, $tobool17 = 0, $5 = 0, $list26 = 0, $6 = 0, $tobool27 = 0, $7 = 0, $list36 = 0, $8 = 0, $tobool37 = 0, $9 = 0, $label = 0, $10 = 0, $shape = 0, $11 = 0, $tobool46 = 0, $fns = 0, $12 = 0, $freefn = 0, $13 = 0, $14 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = $n + 24 | 0;
+ $list = $n + 176 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $0;
+ _free($1);
+ label = 4;
+ break;
+ case 4:
+ $list6 = $n + 184 | 0;
+ $2 = HEAP32[$list6 >> 2] | 0;
+ $tobool7 = ($2 | 0) == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = $2;
+ _free($3);
+ label = 6;
+ break;
+ case 6:
+ $list16 = $n + 192 | 0;
+ $4 = HEAP32[$list16 >> 2] | 0;
+ $tobool17 = ($4 | 0) == 0;
+ if ($tobool17) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $5 = $4;
+ _free($5);
+ label = 8;
+ break;
+ case 8:
+ $list26 = $n + 200 | 0;
+ $6 = HEAP32[$list26 >> 2] | 0;
+ $tobool27 = ($6 | 0) == 0;
+ if ($tobool27) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $7 = $6;
+ _free($7);
+ label = 10;
+ break;
+ case 10:
+ $list36 = $n + 208 | 0;
+ $8 = HEAP32[$list36 >> 2] | 0;
+ $tobool37 = ($8 | 0) == 0;
+ if ($tobool37) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $9 = $8;
+ _free($9);
+ label = 12;
+ break;
+ case 12:
+ $label = $n + 120 | 0;
+ $10 = HEAP32[$label >> 2] | 0;
+ _free_label($10);
+ $shape = $u | 0;
+ $11 = HEAP32[$shape >> 2] | 0;
+ $tobool46 = ($11 | 0) == 0;
+ if ($tobool46) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $fns = $11 + 4 | 0;
+ $12 = HEAP32[$fns >> 2] | 0;
+ $freefn = $12 + 4 | 0;
+ $13 = HEAP32[$freefn >> 2] | 0;
+ FUNCTION_TABLE_vi[$13 & 1023]($n);
+ label = 14;
+ break;
+ case 14:
+ $14 = $u;
+ _memset($14 | 0, 0, 280);
+ return;
+ }
+}
+function _dot_cleanup_graph($g) {
+ $g = $g | 0;
+ var $u = 0, $n_cluster = 0, $0 = 0, $cmp25 = 0, $clust5 = 0, $1 = 0, $2 = 0, $c_026 = 0, $arrayidx = 0, $3 = 0, $cluster_was_collapsed = 0, $inc = 0, $4 = 0, $cmp = 0, $5 = 0, $_lcssa = 0, $tobool = 0, $6 = 0, $rankleader = 0, $7 = 0, $tobool9 = 0, $8 = 0, $list = 0, $9 = 0, $tobool15 = 0, $10 = 0, $rank = 0, $11 = 0, $tobool22 = 0, $minrank = 0, $12 = 0, $maxrank = 0, $13 = 0, $cmp2823 = 0, $conv = 0, $i_024 = 0, $14 = 0, $av = 0, $15 = 0, $16 = 0, $inc35 = 0, $17 = 0, $conv27 = 0, $cmp28 = 0, $_pr = 0, $18 = 0, $cmp40 = 0, $19 = 0, $add_ptr = 0, $20 = 0, $21 = 0, $root = 0, $22 = 0, $cmp49 = 0, $23 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $u = $g + 48 | 0;
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp25 = ($0 | 0) < 1;
+ $clust5 = $g + 216 | 0;
+ $1 = HEAP32[$clust5 >> 2] | 0;
+ if ($cmp25) {
+ $_lcssa = $1;
+ label = 4;
+ break;
+ } else {
+ $c_026 = 1;
+ $2 = $1;
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $2 + ($c_026 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $cluster_was_collapsed = $3 + 254 | 0;
+ HEAP8[$cluster_was_collapsed] = 0;
+ _dot_cleanup($3);
+ $inc = $c_026 + 1 | 0;
+ $4 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($4 | 0);
+ $5 = HEAP32[$clust5 >> 2] | 0;
+ if ($cmp) {
+ $_lcssa = $5;
+ label = 4;
+ break;
+ } else {
+ $c_026 = $inc;
+ $2 = $5;
+ label = 3;
+ break;
+ }
+ case 4:
+ $tobool = ($_lcssa | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $6 = $_lcssa;
+ _free($6);
+ label = 6;
+ break;
+ case 6:
+ $rankleader = $g + 280 | 0;
+ $7 = HEAP32[$rankleader >> 2] | 0;
+ $tobool9 = ($7 | 0) == 0;
+ if ($tobool9) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $8 = $7;
+ _free($8);
+ label = 8;
+ break;
+ case 8:
+ $list = $g + 228 | 0;
+ $9 = HEAP32[$list >> 2] | 0;
+ $tobool15 = ($9 | 0) == 0;
+ if ($tobool15) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $10 = $9;
+ _free($10);
+ label = 10;
+ break;
+ case 10:
+ $rank = $g + 224 | 0;
+ $11 = HEAP32[$rank >> 2] | 0;
+ $tobool22 = ($11 | 0) == 0;
+ if ($tobool22) {
+ label = 18;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $minrank = $g + 248 | 0;
+ $12 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $13 = HEAP16[$maxrank >> 1] | 0;
+ $cmp2823 = $12 << 16 >> 16 > $13 << 16 >> 16;
+ if ($cmp2823) {
+ $18 = $12;
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $conv = $12 << 16 >> 16;
+ $i_024 = $conv;
+ label = 13;
+ break;
+ case 13:
+ $14 = HEAP32[$rank >> 2] | 0;
+ $av = $14 + ($i_024 * 44 & -1) + 12 | 0;
+ $15 = HEAP32[$av >> 2] | 0;
+ $16 = $15;
+ _free($16);
+ $inc35 = $i_024 + 1 | 0;
+ $17 = HEAP16[$maxrank >> 1] | 0;
+ $conv27 = $17 << 16 >> 16;
+ $cmp28 = ($inc35 | 0) > ($conv27 | 0);
+ if ($cmp28) {
+ label = 14;
+ break;
+ } else {
+ $i_024 = $inc35;
+ label = 13;
+ break;
+ }
+ case 14:
+ $_pr = HEAP16[$minrank >> 1] | 0;
+ $18 = $_pr;
+ label = 15;
+ break;
+ case 15:
+ $cmp40 = $18 << 16 >> 16 == -1;
+ $19 = HEAP32[$rank >> 2] | 0;
+ if ($cmp40) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $add_ptr = $19 - 44 | 0;
+ $20 = $add_ptr;
+ _free($20);
+ label = 18;
+ break;
+ case 17:
+ $21 = $19;
+ _free($21);
+ label = 18;
+ break;
+ case 18:
+ $root = $g + 32 | 0;
+ $22 = HEAP32[$root >> 2] | 0;
+ $cmp49 = ($22 | 0) == ($g | 0);
+ if ($cmp49) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $23 = $u;
+ _memset($23 | 0, 0, 248);
+ label = 20;
+ break;
+ case 20:
+ return;
+ }
+}
+function _dot_layout($g) {
+ $g = $g | 0;
+ var $aspect = 0, $0 = 0, $call = 0, $1 = 0, $badGraph = 0, $nPasses = 0, $nextIter2 = 0, $nextIter = 0, $asp_0 = 0, $2 = 0, $tobool = 0, $call1 = 0, $asp_1 = 0, $cmp = 0, $conv = 0, $3 = 0, $dec = 0, $4 = 0, $tobool3 = 0, $tobool5 = 0, $or_cond = 0, $5 = 0, $call6 = 0, $call7 = 0, $tobool8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $aspect = __stackBase__ | 0;
+ $0 = $g;
+ _setEdgeType($0, 8);
+ $call = _setAspect($g, $aspect) | 0;
+ _dot_init_node_edge($g);
+ $1 = $g;
+ $badGraph = $aspect + 32 | 0;
+ $nPasses = $aspect + 28 | 0;
+ $nextIter2 = $aspect + 24 | 0;
+ $nextIter = $aspect + 24 | 0;
+ $asp_0 = $call;
+ label = 3;
+ break;
+ case 3:
+ _dot_rank($1, $asp_0);
+ $2 = HEAP32[$badGraph >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ $asp_1 = $asp_0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call1 = _agerr(0, 125216, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ HEAP32[$nextIter >> 2] = 0;
+ $asp_1 = 0;
+ label = 5;
+ break;
+ case 5:
+ $cmp = ($asp_1 | 0) != 0;
+ $conv = $cmp & 1;
+ _dot_mincross($0, $conv);
+ _dot_position($0, $asp_1);
+ $3 = HEAP32[$nPasses >> 2] | 0;
+ $dec = $3 - 1 | 0;
+ HEAP32[$nPasses >> 2] = $dec;
+ $4 = HEAP32[$nextIter2 >> 2] | 0;
+ $tobool3 = ($4 | 0) == 0;
+ $tobool5 = ($dec | 0) == 0;
+ $or_cond = $tobool3 | $tobool5;
+ if ($or_cond) {
+ label = 6;
+ break;
+ } else {
+ $asp_0 = $asp_1;
+ label = 3;
+ break;
+ }
+ case 6:
+ _dot_sameports($g);
+ _dot_splines($g);
+ $5 = $g | 0;
+ $call6 = _agget($5, 154768) | 0;
+ $call7 = _mapbool($call6) | 0;
+ $tobool8 = $call7 << 24 >> 24 == 0;
+ if ($tobool8) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _dot_compoundEdges($g);
+ label = 8;
+ break;
+ case 8:
+ _dotneato_postprocess($0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _setAspect($g, $adata) {
+ $g = $g | 0;
+ $adata = $adata | 0;
+ var $rv = 0, $passes = 0, $0 = 0, $call = 0, $tobool = 0, $call1 = 0, $cmp = 0, $nextIter = 0, $badGraph = 0, $1 = 0.0, $cmp2 = 0, $cmp4 = 0, $2 = 0.0, $targetAR = 0, $nextIter8 = 0, $3 = 0, $nPasses = 0, $badGraph9 = 0, $4 = 0, $tobool10 = 0, $5 = 0, $6 = 0.0, $call13 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rv = __stackBase__ | 0;
+ $passes = __stackBase__ + 8 | 0;
+ HEAP32[$passes >> 2] = 5;
+ $0 = $g | 0;
+ $call = _agget($0, 127136) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _sscanf($call | 0, 117384, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $rv, HEAP32[tempInt + 8 >> 2] = $passes, tempInt) | 0) | 0;
+ $cmp = ($call1 | 0) < 1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $nextIter = $adata + 24 | 0;
+ HEAP32[$nextIter >> 2] = 0;
+ $badGraph = $adata + 32 | 0;
+ HEAP32[$badGraph >> 2] = 0;
+ $retval_0 = 0;
+ label = 11;
+ break;
+ case 5:
+ $1 = +HEAPF64[$rv >> 3];
+ $cmp2 = $1 < 1.0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ HEAPF64[$rv >> 3] = 1.0;
+ label = 9;
+ break;
+ case 7:
+ $cmp4 = $1 > 20.0;
+ if ($cmp4) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ HEAPF64[$rv >> 3] = 20.0;
+ label = 9;
+ break;
+ case 9:
+ $2 = +HEAPF64[$rv >> 3];
+ $targetAR = $adata | 0;
+ HEAPF64[$targetAR >> 3] = $2;
+ $nextIter8 = $adata + 24 | 0;
+ HEAP32[$nextIter8 >> 2] = -1;
+ $3 = HEAP32[$passes >> 2] | 0;
+ $nPasses = $adata + 28 | 0;
+ HEAP32[$nPasses >> 2] = $3;
+ $badGraph9 = $adata + 32 | 0;
+ HEAP32[$badGraph9 >> 2] = 0;
+ $4 = HEAP8[164912] | 0;
+ $tobool10 = $4 << 24 >> 24 == 0;
+ if ($tobool10) {
+ $retval_0 = $adata;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $5 = HEAP32[_stderr >> 2] | 0;
+ $6 = +HEAPF64[$targetAR >> 3];
+ $call13 = _fprintf($5 | 0, 112080, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $6, tempInt) | 0) | 0;
+ $retval_0 = $adata;
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _free_virtual_edge_list($n) {
+ $n = $n | 0;
+ var $size = 0, $0 = 0, $cmp16 = 0, $list = 0, $i_017_in = 0, $i_017 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $3 = 0, $4 = 0, $cmp = 0, $size4 = 0, $5 = 0, $cmp713 = 0, $list11 = 0, $i_114_in = 0, $i_114 = 0, $6 = 0, $arrayidx12 = 0, $7 = 0, $8 = 0, $9 = 0, $cmp7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $n + 180 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp16 = ($0 | 0) > 0;
+ if ($cmp16) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $list = $n + 176 | 0;
+ $i_017_in = $0;
+ label = 4;
+ break;
+ case 4:
+ $i_017 = $i_017_in - 1 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($i_017 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $3 = $2;
+ _delete_fast_edge($3);
+ $4 = $2 | 0;
+ _free($4);
+ $cmp = ($i_017 | 0) > 0;
+ if ($cmp) {
+ $i_017_in = $i_017;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $size4 = $n + 188 | 0;
+ $5 = HEAP32[$size4 >> 2] | 0;
+ $cmp713 = ($5 | 0) > 0;
+ if ($cmp713) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $list11 = $n + 184 | 0;
+ $i_114_in = $5;
+ label = 7;
+ break;
+ case 7:
+ $i_114 = $i_114_in - 1 | 0;
+ $6 = HEAP32[$list11 >> 2] | 0;
+ $arrayidx12 = $6 + ($i_114 << 2) | 0;
+ $7 = HEAP32[$arrayidx12 >> 2] | 0;
+ $8 = $7;
+ _delete_fast_edge($8);
+ $9 = $7 | 0;
+ _free($9);
+ $cmp7 = ($i_114 | 0) > 0;
+ if ($cmp7) {
+ $i_114_in = $i_114;
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ return;
+ }
+}
+function _dot_splines($g) {
+ $g = $g | 0;
+ __dot_splines($g, 1);
+ return;
+}
+function _setflags($e, $hint1, $hint2, $f3) {
+ $e = $e | 0;
+ $hint1 = $hint1 | 0;
+ $hint2 = $hint2 | 0;
+ $f3 = $f3 | 0;
+ var $cmp = 0, $tail = 0, $0 = 0, $head = 0, $1 = 0, $cmp1 = 0, $defined = 0, $2 = 0, $tobool = 0, $defined4 = 0, $3 = 0, $tobool6 = 0, $_14 = 0, $rank = 0, $4 = 0, $rank14 = 0, $5 = 0, $cmp15 = 0, $_ = 0, $f1_0 = 0, $cmp22 = 0, $tail29 = 0, $6 = 0, $rank31 = 0, $7 = 0, $head32 = 0, $8 = 0, $rank34 = 0, $9 = 0, $cmp35 = 0, $cond = 0, $tail41 = 0, $10 = 0, $order = 0, $11 = 0, $head43 = 0, $12 = 0, $order45 = 0, $13 = 0, $cmp46 = 0, $cond48 = 0, $f2_0 = 0, $or = 0, $or53 = 0, $tree_index = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($hint1 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $f1_0 = $hint1;
+ label = 7;
+ break;
+ }
+ case 3:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $head = $e + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $cmp1 = ($0 | 0) == ($1 | 0);
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $defined = $e + 60 | 0;
+ $2 = HEAP8[$defined] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $f1_0 = 4;
+ label = 7;
+ break;
+ }
+ case 5:
+ $defined4 = $e + 100 | 0;
+ $3 = HEAP8[$defined4] | 0;
+ $tobool6 = $3 << 24 >> 24 == 0;
+ $_14 = $tobool6 ? 8 : 4;
+ $f1_0 = $_14;
+ label = 7;
+ break;
+ case 6:
+ $rank = $0 + 236 | 0;
+ $4 = HEAP32[$rank >> 2] | 0;
+ $rank14 = $1 + 236 | 0;
+ $5 = HEAP32[$rank14 >> 2] | 0;
+ $cmp15 = ($4 | 0) == ($5 | 0);
+ $_ = $cmp15 ? 2 : 1;
+ $f1_0 = $_;
+ label = 7;
+ break;
+ case 7:
+ $cmp22 = ($hint2 | 0) == 0;
+ if ($cmp22) {
+ label = 8;
+ break;
+ } else {
+ $f2_0 = $hint2;
+ label = 11;
+ break;
+ }
+ case 8:
+ if (($f1_0 | 0) == 1) {
+ label = 9;
+ break;
+ } else if (($f1_0 | 0) == 2) {
+ label = 10;
+ break;
+ } else {
+ $f2_0 = 16;
+ label = 11;
+ break;
+ }
+ case 9:
+ $tail29 = $e + 16 | 0;
+ $6 = HEAP32[$tail29 >> 2] | 0;
+ $rank31 = $6 + 236 | 0;
+ $7 = HEAP32[$rank31 >> 2] | 0;
+ $head32 = $e + 12 | 0;
+ $8 = HEAP32[$head32 >> 2] | 0;
+ $rank34 = $8 + 236 | 0;
+ $9 = HEAP32[$rank34 >> 2] | 0;
+ $cmp35 = ($7 | 0) < ($9 | 0);
+ $cond = $cmp35 ? 16 : 32;
+ $f2_0 = $cond;
+ label = 11;
+ break;
+ case 10:
+ $tail41 = $e + 16 | 0;
+ $10 = HEAP32[$tail41 >> 2] | 0;
+ $order = $10 + 240 | 0;
+ $11 = HEAP32[$order >> 2] | 0;
+ $head43 = $e + 12 | 0;
+ $12 = HEAP32[$head43 >> 2] | 0;
+ $order45 = $12 + 240 | 0;
+ $13 = HEAP32[$order45 >> 2] | 0;
+ $cmp46 = ($11 | 0) < ($13 | 0);
+ $cond48 = $cmp46 ? 16 : 32;
+ $f2_0 = $cond48;
+ label = 11;
+ break;
+ case 11:
+ $or = $f1_0 | $f3;
+ $or53 = $or | $f2_0;
+ $tree_index = $e + 180 | 0;
+ HEAP32[$tree_index >> 2] = $or53;
+ return;
+ }
+}
+function __dot_splines($g, $normalize) {
+ $g = $g | 0;
+ $normalize = $normalize | 0;
+ var $fwdedgea = 0, $fwdedgeb = 0, $sd = 0, $flags = 0, $0 = 0, $conv = 0, $and = 0, $cmp = 0, $1 = 0, $call = 0, $2 = 0, $nodesep = 0, $3 = 0, $div = 0, $Splinesep = 0, $4 = 0, $Multisep = 0, $call5 = 0, $5 = 0, $RightBound = 0, $LeftBound = 0, $minrank = 0, $6 = 0, $conv7 = 0, $maxrank = 0, $7 = 0, $cmp10272 = 0, $rank = 0, $i_0276 = 0, $n_nodes_0275 = 0, $n_edges_0274 = 0, $edges_0273 = 0, $8 = 0, $n13 = 0, $9 = 0, $add = 0, $v = 0, $10 = 0, $11 = 0, $tobool = 0, $12 = 0, $conv20 = 0.0, $x = 0, $13 = 0.0, $lw = 0, $14 = 0.0, $sub = 0.0, $cmp23 = 0, $conv20_sub = 0.0, $conv33 = 0, $15 = 0, $n39 = 0, $16 = 0, $tobool40 = 0, $sub45 = 0, $v49 = 0, $17 = 0, $arrayidx50 = 0, $18 = 0, $tobool51 = 0, $19 = 0, $conv54 = 0.0, $x57 = 0, $20 = 0.0, $rw = 0, $21 = 0.0, $add59 = 0.0, $cmp60 = 0, $conv54_add59 = 0.0, $conv74 = 0, $22 = 0, $sub78 = 0, $23 = 0, $add80 = 0, $24 = 0, $n85259 = 0, $25 = 0, $cmp86260 = 0, $26 = 0, $j_0263 = 0, $n_edges_1262 = 0, $edges_1261 = 0, $v92 = 0, $27 = 0, $arrayidx93 = 0, $28 = 0, $alg = 0, $29 = 0, $tobool95 = 0, $label = 0, $30 = 0, $31 = 0, $tobool100 = 0, $pos = 0, $coord107 = 0, $32 = 0, $33 = 0, $34 = 0, $set = 0, $node_type = 0, $35 = 0, $cmp113 = 0, $36 = 0, $call116 = 0, $cmp118 = 0, $list = 0, $37 = 0, $38 = 0, $tobool125237 = 0, $39 = 0, $k_0240 = 0, $n_edges_2239 = 0, $edges_2238 = 0, $edge_type = 0, $40 = 0, $inc = 0, $arrayidx138 = 0, $rem213 = 0, $cmp139 = 0, $tobool142 = 0, $41 = 0, $add144 = 0, $mul = 0, $call145 = 0, $add147 = 0, $mul148 = 0, $call149 = 0, $call145_sink = 0, $42 = 0, $edges_3 = 0, $n_edges_3 = 0, $inc153 = 0, $43 = 0, $arrayidx124 = 0, $44 = 0, $tobool125 = 0, $n_edges_2_lcssa = 0, $edges_2_lcssa = 0, $list155 = 0, $45 = 0, $tobool156 = 0, $46 = 0, $47 = 0, $tobool163244 = 0, $48 = 0, $k_1247 = 0, $n_edges_4246 = 0, $edges_4245 = 0, $inc165 = 0, $arrayidx166 = 0, $rem167212 = 0, $cmp168 = 0, $tobool171 = 0, $49 = 0, $add173 = 0, $mul174 = 0, $call175 = 0, $add177 = 0, $mul178 = 0, $call179 = 0, $call175_sink = 0, $50 = 0, $edges_5 = 0, $inc184 = 0, $51 = 0, $arrayidx162 = 0, $52 = 0, $tobool163 = 0, $edges_6 = 0, $n_edges_5 = 0, $list188 = 0, $53 = 0, $tobool189 = 0, $54 = 0, $cmp194 = 0, $rw198 = 0, $55 = 0.0, $mval = 0, $56 = 0, $conv200 = 0.0, $conv203 = 0, $57 = 0, $58 = 0, $tobool212251 = 0, $59 = 0, $k_2254 = 0, $n_edges_6253 = 0, $edges_7252 = 0, $inc214 = 0, $arrayidx215 = 0, $rem216211 = 0, $cmp217 = 0, $tobool220 = 0, $60 = 0, $add222 = 0, $mul223 = 0, $call224 = 0, $add226 = 0, $mul227 = 0, $call228 = 0, $call224_sink = 0, $61 = 0, $edges_8 = 0, $inc233 = 0, $62 = 0, $arrayidx211 = 0, $63 = 0, $tobool212 = 0, $edges_9 = 0, $n_edges_7 = 0, $inc237 = 0, $64 = 0, $n85 = 0, $65 = 0, $cmp86 = 0, $n_edges_1_lcssa = 0, $edges_1_lcssa = 0, $inc240 = 0, $66 = 0, $conv9 = 0, $cmp10 = 0, $phitmp = 0, $phitmp283 = 0, $i_0_lcssa = 0, $n_nodes_0_lcssa = 0, $n_edges_0_lcssa = 0, $edges_0_lcssa = 0, $67 = 0, $call245 = 0, $68 = 0, $boxes = 0, $69 = 0, $mul246 = 0, $call247 = 0, $70 = 0, $Rank_box = 0, $cmp248 = 0, $cmp271231 = 0, $rank424 = 0, $71 = 0, $72 = 0, $rank450 = 0, $rank463 = 0, $73 = 0, $tail345 = 0, $head347 = 0, $tail_port349 = 0, $74 = 0, $head_port353 = 0, $75 = 0, $edge_type357 = 0, $to_orig359 = 0, $76 = 0, $tail = 0, $head295 = 0, $tail_port297 = 0, $77 = 0, $head_port301 = 0, $78 = 0, $edge_type305 = 0, $to_orig = 0, $nlist = 0, $n_0233 = 0, $tobool253234 = 0, $n_0235 = 0, $node_type256 = 0, $79 = 0, $cmp258 = 0, $label262 = 0, $80 = 0, $tobool263 = 0, $next = 0, $n_0 = 0, $tobool253 = 0, $i_1232 = 0, $arrayidx275 = 0, $81 = 0, $call276 = 0, $defined = 0, $82 = 0, $tobool279 = 0, $defined282 = 0, $83 = 0, $tobool284 = 0, $call276_ = 0, $cond288 = 0, $tree_index = 0, $84 = 0, $and290 = 0, $tobool291 = 0, $85 = 0, $head = 0, $86 = 0, $tail294 = 0, $87 = 0, $head_port299 = 0, $88 = 0, $tail_port303 = 0, $89 = 0, $ea_0 = 0, $head_port370 = 0, $label384 = 0, $i_2223 = 0, $cmp309224 = 0, $adjacent = 0, $tail_port362 = 0, $tree_index378 = 0, $i_2227 = 0, $cnt_0225 = 0, $arrayidx312 = 0, $90 = 0, $call313 = 0, $cmp314 = 0, $91 = 0, $tobool319 = 0, $defined324 = 0, $92 = 0, $tobool326 = 0, $defined330 = 0, $93 = 0, $tobool332 = 0, $call313_ = 0, $cond336 = 0, $tree_index338 = 0, $94 = 0, $and339 = 0, $tobool340 = 0, $95 = 0, $head344 = 0, $96 = 0, $tail346 = 0, $97 = 0, $head_port351 = 0, $98 = 0, $tail_port355 = 0, $99 = 0, $eb_0 = 0, $tail_port364 = 0, $call365 = 0, $tobool366 = 0, $head_port372 = 0, $call373 = 0, $tobool374 = 0, $100 = 0, $and379 = 0, $cmp380 = 0, $101 = 0, $label386 = 0, $102 = 0, $cmp387 = 0, $103 = 0, $tree_index393 = 0, $104 = 0, $and394 = 0, $tobool395 = 0, $inc399 = 0, $i_2 = 0, $cmp309 = 0, $i_2_lcssa = 0, $cnt_0_lcssa = 0, $tail402 = 0, $105 = 0, $head403 = 0, $106 = 0, $cmp404 = 0, $rank412 = 0, $107 = 0, $108 = 0, $conv415 = 0, $cmp416 = 0, $cmp419 = 0, $sub422 = 0, $109 = 0, $v426 = 0, $110 = 0, $111 = 0, $y = 0, $112 = 0.0, $y432 = 0, $113 = 0.0, $sub433 = 0.0, $conv434 = 0, $ht = 0, $114 = 0.0, $conv436 = 0, $115 = 0, $conv441 = 0, $cmp442 = 0, $y447 = 0, $116 = 0.0, $add448 = 0, $117 = 0, $v452 = 0, $118 = 0, $119 = 0, $y456 = 0, $120 = 0.0, $sub457 = 0.0, $conv458 = 0, $sub461 = 0, $121 = 0, $v465 = 0, $122 = 0, $123 = 0, $y469 = 0, $124 = 0.0, $y472 = 0, $125 = 0.0, $sub473 = 0.0, $conv474 = 0, $add479 = 0, $v483 = 0, $126 = 0, $127 = 0, $y487 = 0, $128 = 0.0, $sub488 = 0.0, $conv489 = 0, $cmp490 = 0, $cond495 = 0, $sizey_0 = 0, $129 = 0, $conv499 = 0.0, $div500 = 0, $conv501 = 0.0, $cmp503229 = 0, $b_0230 = 0, $add506 = 0, $arrayidx507 = 0, $130 = 0, $label509 = 0, $131 = 0, $tobool510 = 0, $inc516 = 0, $cmp503 = 0, $rank524 = 0, $132 = 0, $cmp525 = 0, $cmp271 = 0, $nlist533 = 0, $n_1220 = 0, $tobool535221 = 0, $133 = 0, $n_1222 = 0, $node_type538 = 0, $134 = 0, $cmp540 = 0, $label544 = 0, $135 = 0, $tobool545 = 0, $136 = 0, $next552 = 0, $n_1 = 0, $tobool535 = 0, $tobool554 = 0, $137 = 0, $tobool557 = 0, $138 = 0, $tobool559 = 0, $or_cond = 0, $139 = 0, $call561 = 0, $tobool563218 = 0, $140 = 0, $141 = 0, $n_2_in219 = 0, $142 = 0, $tobool565 = 0, $call567 = 0, $tobool569214 = 0, $e_0_in215 = 0, $head_label = 0, $143 = 0, $tobool572 = 0, $144 = 0, $145 = 0, $146 = 0, $call578 = 0, $tobool569 = 0, $147 = 0, $tobool581 = 0, $call583 = 0, $tobool585216 = 0, $e_1_in217 = 0, $tail_label = 0, $148 = 0, $tobool588 = 0, $149 = 0, $150 = 0, $151 = 0, $call594 = 0, $tobool585 = 0, $call598 = 0, $tobool563 = 0, $152 = 0, $153 = 0, $154 = 0, $155 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 408 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $fwdedgea = __stackBase__ | 0;
+ $fwdedgeb = __stackBase__ + 192 | 0;
+ $sd = __stackBase__ + 384 | 0;
+ $flags = $g + 168 | 0;
+ $0 = HEAP16[$flags >> 1] | 0;
+ $conv = $0 & 65535;
+ $and = $conv & 14;
+ $cmp = ($and | 0) == 0;
+ if ($cmp) {
+ label = 111;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $g;
+ _mark_lowclusters($1);
+ _routesplinesinit();
+ $call = _zmalloc(96) | 0;
+ $2 = $call;
+ $nodesep = $g + 260 | 0;
+ $3 = HEAP32[$nodesep >> 2] | 0;
+ $div = ($3 | 0) / 4 & -1;
+ $Splinesep = $sd + 8 | 0;
+ HEAP32[$Splinesep >> 2] = $div;
+ $4 = HEAP32[$nodesep >> 2] | 0;
+ $Multisep = $sd + 12 | 0;
+ HEAP32[$Multisep >> 2] = $4;
+ $call5 = _zmalloc(512) | 0;
+ $5 = $call5;
+ $RightBound = $sd + 4 | 0;
+ HEAP32[$RightBound >> 2] = 0;
+ $LeftBound = $sd | 0;
+ HEAP32[$LeftBound >> 2] = 0;
+ $minrank = $g + 248 | 0;
+ $6 = HEAP16[$minrank >> 1] | 0;
+ $conv7 = $6 << 16 >> 16;
+ $maxrank = $g + 250 | 0;
+ $7 = HEAP16[$maxrank >> 1] | 0;
+ $cmp10272 = $6 << 16 >> 16 > $7 << 16 >> 16;
+ if ($cmp10272) {
+ $edges_0_lcssa = $5;
+ $n_edges_0_lcssa = 0;
+ $n_nodes_0_lcssa = 11520;
+ $i_0_lcssa = $conv7;
+ label = 46;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $rank = $g + 224 | 0;
+ $edges_0273 = $5;
+ $n_edges_0274 = 0;
+ $n_nodes_0275 = 0;
+ $i_0276 = $conv7;
+ label = 5;
+ break;
+ case 5:
+ $8 = HEAP32[$rank >> 2] | 0;
+ $n13 = $8 + ($i_0276 * 44 & -1) | 0;
+ $9 = HEAP32[$n13 >> 2] | 0;
+ $add = $9 + $n_nodes_0275 | 0;
+ $v = $8 + ($i_0276 * 44 & -1) + 4 | 0;
+ $10 = HEAP32[$v >> 2] | 0;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $tobool = ($11 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $12 = HEAP32[$LeftBound >> 2] | 0;
+ $conv20 = +($12 | 0);
+ $x = $11 + 32 | 0;
+ $13 = +HEAPF64[$x >> 3];
+ $lw = $11 + 104 | 0;
+ $14 = +HEAPF64[$lw >> 3];
+ $sub = $13 - $14;
+ $cmp23 = $conv20 < $sub;
+ $conv20_sub = $cmp23 ? $conv20 : $sub;
+ $conv33 = ~~$conv20_sub;
+ HEAP32[$LeftBound >> 2] = $conv33;
+ label = 7;
+ break;
+ case 7:
+ $15 = HEAP32[$rank >> 2] | 0;
+ $n39 = $15 + ($i_0276 * 44 & -1) | 0;
+ $16 = HEAP32[$n39 >> 2] | 0;
+ $tobool40 = ($16 | 0) == 0;
+ if ($tobool40) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $sub45 = $16 - 1 | 0;
+ $v49 = $15 + ($i_0276 * 44 & -1) + 4 | 0;
+ $17 = HEAP32[$v49 >> 2] | 0;
+ $arrayidx50 = $17 + ($sub45 << 2) | 0;
+ $18 = HEAP32[$arrayidx50 >> 2] | 0;
+ $tobool51 = ($18 | 0) == 0;
+ if ($tobool51) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $19 = HEAP32[$RightBound >> 2] | 0;
+ $conv54 = +($19 | 0);
+ $x57 = $18 + 32 | 0;
+ $20 = +HEAPF64[$x57 >> 3];
+ $rw = $18 + 112 | 0;
+ $21 = +HEAPF64[$rw >> 3];
+ $add59 = $20 + $21;
+ $cmp60 = $conv54 > $add59;
+ $conv54_add59 = $cmp60 ? $conv54 : $add59;
+ $conv74 = ~~$conv54_add59;
+ HEAP32[$RightBound >> 2] = $conv74;
+ label = 10;
+ break;
+ case 10:
+ $22 = HEAP32[$LeftBound >> 2] | 0;
+ $sub78 = $22 - 16 | 0;
+ HEAP32[$LeftBound >> 2] = $sub78;
+ $23 = HEAP32[$RightBound >> 2] | 0;
+ $add80 = $23 + 16 | 0;
+ HEAP32[$RightBound >> 2] = $add80;
+ $24 = HEAP32[$rank >> 2] | 0;
+ $n85259 = $24 + ($i_0276 * 44 & -1) | 0;
+ $25 = HEAP32[$n85259 >> 2] | 0;
+ $cmp86260 = ($25 | 0) > 0;
+ if ($cmp86260) {
+ $edges_1261 = $edges_0273;
+ $n_edges_1262 = $n_edges_0274;
+ $j_0263 = 0;
+ $26 = $24;
+ label = 11;
+ break;
+ } else {
+ $edges_1_lcssa = $edges_0273;
+ $n_edges_1_lcssa = $n_edges_0274;
+ label = 44;
+ break;
+ }
+ case 11:
+ $v92 = $26 + ($i_0276 * 44 & -1) + 4 | 0;
+ $27 = HEAP32[$v92 >> 2] | 0;
+ $arrayidx93 = $27 + ($j_0263 << 2) | 0;
+ $28 = HEAP32[$arrayidx93 >> 2] | 0;
+ $alg = $28 + 128 | 0;
+ $29 = HEAP32[$alg >> 2] | 0;
+ $tobool95 = ($29 | 0) == 0;
+ if ($tobool95) {
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $label = $29 + 112 | 0;
+ $30 = $label;
+ $31 = HEAP32[$30 >> 2] | 0;
+ $tobool100 = ($31 | 0) == 0;
+ if ($tobool100) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ ___assert_func(119288, 318, 164664, 152792);
+ case 14:
+ $pos = $31 + 56 | 0;
+ $coord107 = $28 + 32 | 0;
+ $32 = $pos;
+ $33 = $coord107;
+ HEAP32[$32 >> 2] = HEAP32[$33 >> 2] | 0;
+ HEAP32[$32 + 4 >> 2] = HEAP32[$33 + 4 >> 2] | 0;
+ HEAP32[$32 + 8 >> 2] = HEAP32[$33 + 8 >> 2] | 0;
+ HEAP32[$32 + 12 >> 2] = HEAP32[$33 + 12 >> 2] | 0;
+ $34 = HEAP32[$30 >> 2] | 0;
+ $set = $34 + 81 | 0;
+ HEAP8[$set] = 1;
+ label = 15;
+ break;
+ case 15:
+ $node_type = $28 + 162 | 0;
+ $35 = HEAP8[$node_type] | 0;
+ $cmp113 = $35 << 24 >> 24 == 0;
+ if ($cmp113) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $36 = HEAP32[1055] | 0;
+ $call116 = FUNCTION_TABLE_ii[$36 & 1023]($28) | 0;
+ $cmp118 = $call116 << 24 >> 24 == 0;
+ if ($cmp118) {
+ $n_edges_7 = $n_edges_1262;
+ $edges_9 = $edges_1261;
+ label = 43;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $list = $28 + 184 | 0;
+ $37 = HEAP32[$list >> 2] | 0;
+ $38 = HEAP32[$37 >> 2] | 0;
+ $tobool125237 = ($38 | 0) == 0;
+ if ($tobool125237) {
+ $edges_2_lcssa = $edges_1261;
+ $n_edges_2_lcssa = $n_edges_1262;
+ label = 25;
+ break;
+ } else {
+ $edges_2238 = $edges_1261;
+ $n_edges_2239 = $n_edges_1262;
+ $k_0240 = 0;
+ $39 = $38;
+ label = 18;
+ break;
+ }
+ case 18:
+ $edge_type = $39 + 128 | 0;
+ $40 = HEAP8[$edge_type] | 0;
+ if (($40 << 24 >> 24 | 0) == 4 | ($40 << 24 >> 24 | 0) == 6) {
+ $n_edges_3 = $n_edges_2239;
+ $edges_3 = $edges_2238;
+ label = 24;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ _setflags($39, 1, 16, 64);
+ $inc = $n_edges_2239 + 1 | 0;
+ $arrayidx138 = $edges_2238 + ($n_edges_2239 << 2) | 0;
+ HEAP32[$arrayidx138 >> 2] = $39;
+ $rem213 = $inc & 127;
+ $cmp139 = ($rem213 | 0) == 0;
+ if ($cmp139) {
+ label = 20;
+ break;
+ } else {
+ $n_edges_3 = $inc;
+ $edges_3 = $edges_2238;
+ label = 24;
+ break;
+ }
+ case 20:
+ $tobool142 = ($edges_2238 | 0) == 0;
+ if ($tobool142) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $41 = $edges_2238;
+ $add144 = $n_edges_2239 << 2;
+ $mul = $add144 + 516 | 0;
+ $call145 = _grealloc($41, $mul) | 0;
+ $call145_sink = $call145;
+ label = 23;
+ break;
+ case 22:
+ $add147 = $n_edges_2239 << 2;
+ $mul148 = $add147 + 516 | 0;
+ $call149 = _gmalloc($mul148) | 0;
+ $call145_sink = $call149;
+ label = 23;
+ break;
+ case 23:
+ $42 = $call145_sink;
+ $n_edges_3 = $inc;
+ $edges_3 = $42;
+ label = 24;
+ break;
+ case 24:
+ $inc153 = $k_0240 + 1 | 0;
+ $43 = HEAP32[$list >> 2] | 0;
+ $arrayidx124 = $43 + ($inc153 << 2) | 0;
+ $44 = HEAP32[$arrayidx124 >> 2] | 0;
+ $tobool125 = ($44 | 0) == 0;
+ if ($tobool125) {
+ $edges_2_lcssa = $edges_3;
+ $n_edges_2_lcssa = $n_edges_3;
+ label = 25;
+ break;
+ } else {
+ $edges_2238 = $edges_3;
+ $n_edges_2239 = $n_edges_3;
+ $k_0240 = $inc153;
+ $39 = $44;
+ label = 18;
+ break;
+ }
+ case 25:
+ $list155 = $28 + 192 | 0;
+ $45 = HEAP32[$list155 >> 2] | 0;
+ $tobool156 = ($45 | 0) == 0;
+ if ($tobool156) {
+ $n_edges_5 = $n_edges_2_lcssa;
+ $edges_6 = $edges_2_lcssa;
+ label = 33;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $46 = HEAP32[$list155 >> 2] | 0;
+ $47 = HEAP32[$46 >> 2] | 0;
+ $tobool163244 = ($47 | 0) == 0;
+ if ($tobool163244) {
+ $n_edges_5 = $n_edges_2_lcssa;
+ $edges_6 = $edges_2_lcssa;
+ label = 33;
+ break;
+ } else {
+ $edges_4245 = $edges_2_lcssa;
+ $n_edges_4246 = $n_edges_2_lcssa;
+ $k_1247 = 0;
+ $48 = $47;
+ label = 27;
+ break;
+ }
+ case 27:
+ _setflags($48, 2, 0, 128);
+ $inc165 = $n_edges_4246 + 1 | 0;
+ $arrayidx166 = $edges_4245 + ($n_edges_4246 << 2) | 0;
+ HEAP32[$arrayidx166 >> 2] = $48;
+ $rem167212 = $inc165 & 127;
+ $cmp168 = ($rem167212 | 0) == 0;
+ if ($cmp168) {
+ label = 28;
+ break;
+ } else {
+ $edges_5 = $edges_4245;
+ label = 32;
+ break;
+ }
+ case 28:
+ $tobool171 = ($edges_4245 | 0) == 0;
+ if ($tobool171) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $49 = $edges_4245;
+ $add173 = $n_edges_4246 << 2;
+ $mul174 = $add173 + 516 | 0;
+ $call175 = _grealloc($49, $mul174) | 0;
+ $call175_sink = $call175;
+ label = 31;
+ break;
+ case 30:
+ $add177 = $n_edges_4246 << 2;
+ $mul178 = $add177 + 516 | 0;
+ $call179 = _gmalloc($mul178) | 0;
+ $call175_sink = $call179;
+ label = 31;
+ break;
+ case 31:
+ $50 = $call175_sink;
+ $edges_5 = $50;
+ label = 32;
+ break;
+ case 32:
+ $inc184 = $k_1247 + 1 | 0;
+ $51 = HEAP32[$list155 >> 2] | 0;
+ $arrayidx162 = $51 + ($inc184 << 2) | 0;
+ $52 = HEAP32[$arrayidx162 >> 2] | 0;
+ $tobool163 = ($52 | 0) == 0;
+ if ($tobool163) {
+ $n_edges_5 = $inc165;
+ $edges_6 = $edges_5;
+ label = 33;
+ break;
+ } else {
+ $edges_4245 = $edges_5;
+ $n_edges_4246 = $inc165;
+ $k_1247 = $inc184;
+ $48 = $52;
+ label = 27;
+ break;
+ }
+ case 33:
+ $list188 = $28 + 208 | 0;
+ $53 = HEAP32[$list188 >> 2] | 0;
+ $tobool189 = ($53 | 0) == 0;
+ if ($tobool189) {
+ $n_edges_7 = $n_edges_5;
+ $edges_9 = $edges_6;
+ label = 43;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $54 = HEAP8[$node_type] | 0;
+ $cmp194 = $54 << 24 >> 24 == 0;
+ if ($cmp194) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ $rw198 = $28 + 112 | 0;
+ $55 = +HEAPF64[$rw198 >> 3];
+ $mval = $28 + 244 | 0;
+ $56 = HEAP32[$mval >> 2] | 0;
+ $conv200 = +($56 | 0);
+ HEAPF64[$rw198 >> 3] = $conv200;
+ $conv203 = ~~$55;
+ HEAP32[$mval >> 2] = $conv203;
+ label = 36;
+ break;
+ case 36:
+ $57 = HEAP32[$list188 >> 2] | 0;
+ $58 = HEAP32[$57 >> 2] | 0;
+ $tobool212251 = ($58 | 0) == 0;
+ if ($tobool212251) {
+ $n_edges_7 = $n_edges_5;
+ $edges_9 = $edges_6;
+ label = 43;
+ break;
+ } else {
+ $edges_7252 = $edges_6;
+ $n_edges_6253 = $n_edges_5;
+ $k_2254 = 0;
+ $59 = $58;
+ label = 37;
+ break;
+ }
+ case 37:
+ _setflags($59, 0, 0, 128);
+ $inc214 = $n_edges_6253 + 1 | 0;
+ $arrayidx215 = $edges_7252 + ($n_edges_6253 << 2) | 0;
+ HEAP32[$arrayidx215 >> 2] = $59;
+ $rem216211 = $inc214 & 127;
+ $cmp217 = ($rem216211 | 0) == 0;
+ if ($cmp217) {
+ label = 38;
+ break;
+ } else {
+ $edges_8 = $edges_7252;
+ label = 42;
+ break;
+ }
+ case 38:
+ $tobool220 = ($edges_7252 | 0) == 0;
+ if ($tobool220) {
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $60 = $edges_7252;
+ $add222 = $n_edges_6253 << 2;
+ $mul223 = $add222 + 516 | 0;
+ $call224 = _grealloc($60, $mul223) | 0;
+ $call224_sink = $call224;
+ label = 41;
+ break;
+ case 40:
+ $add226 = $n_edges_6253 << 2;
+ $mul227 = $add226 + 516 | 0;
+ $call228 = _gmalloc($mul227) | 0;
+ $call224_sink = $call228;
+ label = 41;
+ break;
+ case 41:
+ $61 = $call224_sink;
+ $edges_8 = $61;
+ label = 42;
+ break;
+ case 42:
+ $inc233 = $k_2254 + 1 | 0;
+ $62 = HEAP32[$list188 >> 2] | 0;
+ $arrayidx211 = $62 + ($inc233 << 2) | 0;
+ $63 = HEAP32[$arrayidx211 >> 2] | 0;
+ $tobool212 = ($63 | 0) == 0;
+ if ($tobool212) {
+ $n_edges_7 = $inc214;
+ $edges_9 = $edges_8;
+ label = 43;
+ break;
+ } else {
+ $edges_7252 = $edges_8;
+ $n_edges_6253 = $inc214;
+ $k_2254 = $inc233;
+ $59 = $63;
+ label = 37;
+ break;
+ }
+ case 43:
+ $inc237 = $j_0263 + 1 | 0;
+ $64 = HEAP32[$rank >> 2] | 0;
+ $n85 = $64 + ($i_0276 * 44 & -1) | 0;
+ $65 = HEAP32[$n85 >> 2] | 0;
+ $cmp86 = ($inc237 | 0) < ($65 | 0);
+ if ($cmp86) {
+ $edges_1261 = $edges_9;
+ $n_edges_1262 = $n_edges_7;
+ $j_0263 = $inc237;
+ $26 = $64;
+ label = 11;
+ break;
+ } else {
+ $edges_1_lcssa = $edges_9;
+ $n_edges_1_lcssa = $n_edges_7;
+ label = 44;
+ break;
+ }
+ case 44:
+ $inc240 = $i_0276 + 1 | 0;
+ $66 = HEAP16[$maxrank >> 1] | 0;
+ $conv9 = $66 << 16 >> 16;
+ $cmp10 = ($inc240 | 0) > ($conv9 | 0);
+ if ($cmp10) {
+ label = 45;
+ break;
+ } else {
+ $edges_0273 = $edges_1_lcssa;
+ $n_edges_0274 = $n_edges_1_lcssa;
+ $n_nodes_0275 = $add;
+ $i_0276 = $inc240;
+ label = 5;
+ break;
+ }
+ case 45:
+ $phitmp = $add << 5;
+ $phitmp283 = $phitmp + 11520 | 0;
+ $edges_0_lcssa = $edges_1_lcssa;
+ $n_edges_0_lcssa = $n_edges_1_lcssa;
+ $n_nodes_0_lcssa = $phitmp283;
+ $i_0_lcssa = $inc240;
+ label = 46;
+ break;
+ case 46:
+ $67 = $edges_0_lcssa;
+ _qsort($67 | 0, $n_edges_0_lcssa | 0, 4, 576);
+ $call245 = _zmalloc($n_nodes_0_lcssa) | 0;
+ $68 = $call245;
+ $boxes = $call + 84 | 0;
+ $69 = $boxes;
+ HEAP32[$69 >> 2] = $68;
+ $mul246 = $i_0_lcssa << 5;
+ $call247 = _zmalloc($mul246) | 0;
+ $70 = $call247;
+ $Rank_box = $sd + 16 | 0;
+ HEAP32[$Rank_box >> 2] = $70;
+ $cmp248 = ($and | 0) == 2;
+ if ($cmp248) {
+ label = 49;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $cmp271231 = ($n_edges_0_lcssa | 0) > 0;
+ if ($cmp271231) {
+ label = 48;
+ break;
+ } else {
+ label = 88;
+ break;
+ }
+ case 48:
+ $rank424 = $g + 224 | 0;
+ $71 = $edges_0_lcssa;
+ $72 = $g;
+ $rank450 = $g + 224 | 0;
+ $rank463 = $g + 224 | 0;
+ $73 = $fwdedgeb | 0;
+ $tail345 = $fwdedgeb + 16 | 0;
+ $head347 = $fwdedgeb + 12 | 0;
+ $tail_port349 = $fwdedgeb + 32 | 0;
+ $74 = $tail_port349;
+ $head_port353 = $fwdedgeb + 72 | 0;
+ $75 = $head_port353;
+ $edge_type357 = $fwdedgeb + 128 | 0;
+ $to_orig359 = $fwdedgeb + 132 | 0;
+ $76 = $fwdedgea | 0;
+ $tail = $fwdedgea + 16 | 0;
+ $head295 = $fwdedgea + 12 | 0;
+ $tail_port297 = $fwdedgea + 32 | 0;
+ $77 = $tail_port297;
+ $head_port301 = $fwdedgea + 72 | 0;
+ $78 = $head_port301;
+ $edge_type305 = $fwdedgea + 128 | 0;
+ $to_orig = $fwdedgea + 132 | 0;
+ $i_1232 = 0;
+ label = 54;
+ break;
+ case 49:
+ $nlist = $g + 220 | 0;
+ $n_0233 = HEAP32[$nlist >> 2] | 0;
+ $tobool253234 = ($n_0233 | 0) == 0;
+ if ($tobool253234) {
+ label = 47;
+ break;
+ } else {
+ $n_0235 = $n_0233;
+ label = 50;
+ break;
+ }
+ case 50:
+ $node_type256 = $n_0235 + 162 | 0;
+ $79 = HEAP8[$node_type256] | 0;
+ $cmp258 = $79 << 24 >> 24 == 1;
+ if ($cmp258) {
+ label = 51;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 51:
+ $label262 = $n_0235 + 120 | 0;
+ $80 = HEAP32[$label262 >> 2] | 0;
+ $tobool263 = ($80 | 0) == 0;
+ if ($tobool263) {
+ label = 53;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ _place_vnlabel($n_0235);
+ label = 53;
+ break;
+ case 53:
+ $next = $n_0235 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool253 = ($n_0 | 0) == 0;
+ if ($tobool253) {
+ label = 47;
+ break;
+ } else {
+ $n_0235 = $n_0;
+ label = 50;
+ break;
+ }
+ case 54:
+ $arrayidx275 = $edges_0_lcssa + ($i_1232 << 2) | 0;
+ $81 = HEAP32[$arrayidx275 >> 2] | 0;
+ $call276 = _getmainedge($81) | 0;
+ $defined = $81 + 60 | 0;
+ $82 = HEAP8[$defined] | 0;
+ $tobool279 = $82 << 24 >> 24 == 0;
+ if ($tobool279) {
+ label = 55;
+ break;
+ } else {
+ $cond288 = $81;
+ label = 56;
+ break;
+ }
+ case 55:
+ $defined282 = $81 + 100 | 0;
+ $83 = HEAP8[$defined282] | 0;
+ $tobool284 = $83 << 24 >> 24 == 0;
+ $call276_ = $tobool284 ? $call276 : $81;
+ $cond288 = $call276_;
+ label = 56;
+ break;
+ case 56:
+ $tree_index = $cond288 + 180 | 0;
+ $84 = HEAP32[$tree_index >> 2] | 0;
+ $and290 = $84 & 32;
+ $tobool291 = ($and290 | 0) == 0;
+ if ($tobool291) {
+ $ea_0 = $cond288;
+ label = 58;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $85 = $cond288 | 0;
+ _memcpy($76 | 0, $85 | 0, 192);
+ $head = $cond288 + 12 | 0;
+ $86 = HEAP32[$head >> 2] | 0;
+ HEAP32[$tail >> 2] = $86;
+ $tail294 = $cond288 + 16 | 0;
+ $87 = HEAP32[$tail294 >> 2] | 0;
+ HEAP32[$head295 >> 2] = $87;
+ $head_port299 = $cond288 + 72 | 0;
+ $88 = $head_port299;
+ HEAP32[$77 >> 2] = HEAP32[$88 >> 2] | 0;
+ HEAP32[$77 + 4 >> 2] = HEAP32[$88 + 4 >> 2] | 0;
+ HEAP32[$77 + 8 >> 2] = HEAP32[$88 + 8 >> 2] | 0;
+ HEAP32[$77 + 12 >> 2] = HEAP32[$88 + 12 >> 2] | 0;
+ HEAP32[$77 + 16 >> 2] = HEAP32[$88 + 16 >> 2] | 0;
+ HEAP32[$77 + 20 >> 2] = HEAP32[$88 + 20 >> 2] | 0;
+ HEAP32[$77 + 24 >> 2] = HEAP32[$88 + 24 >> 2] | 0;
+ HEAP32[$77 + 28 >> 2] = HEAP32[$88 + 28 >> 2] | 0;
+ HEAP32[$77 + 32 >> 2] = HEAP32[$88 + 32 >> 2] | 0;
+ HEAP32[$77 + 36 >> 2] = HEAP32[$88 + 36 >> 2] | 0;
+ $tail_port303 = $cond288 + 32 | 0;
+ $89 = $tail_port303;
+ HEAP32[$78 >> 2] = HEAP32[$89 >> 2] | 0;
+ HEAP32[$78 + 4 >> 2] = HEAP32[$89 + 4 >> 2] | 0;
+ HEAP32[$78 + 8 >> 2] = HEAP32[$89 + 8 >> 2] | 0;
+ HEAP32[$78 + 12 >> 2] = HEAP32[$89 + 12 >> 2] | 0;
+ HEAP32[$78 + 16 >> 2] = HEAP32[$89 + 16 >> 2] | 0;
+ HEAP32[$78 + 20 >> 2] = HEAP32[$89 + 20 >> 2] | 0;
+ HEAP32[$78 + 24 >> 2] = HEAP32[$89 + 24 >> 2] | 0;
+ HEAP32[$78 + 28 >> 2] = HEAP32[$89 + 28 >> 2] | 0;
+ HEAP32[$78 + 32 >> 2] = HEAP32[$89 + 32 >> 2] | 0;
+ HEAP32[$78 + 36 >> 2] = HEAP32[$89 + 36 >> 2] | 0;
+ HEAP8[$edge_type305] = 1;
+ HEAP32[$to_orig >> 2] = $cond288;
+ $ea_0 = $fwdedgea;
+ label = 58;
+ break;
+ case 58:
+ $head_port370 = $ea_0 + 72 | 0;
+ $label384 = $81 + 112 | 0;
+ $i_2223 = $i_1232 + 1 | 0;
+ $cmp309224 = ($i_2223 | 0) < ($n_edges_0_lcssa | 0);
+ if ($cmp309224) {
+ label = 59;
+ break;
+ } else {
+ $cnt_0_lcssa = 1;
+ $i_2_lcssa = $i_2223;
+ label = 72;
+ break;
+ }
+ case 59:
+ $adjacent = $81 + 129 | 0;
+ $tail_port362 = $ea_0 + 32 | 0;
+ $tree_index378 = $81 + 180 | 0;
+ $cnt_0225 = 1;
+ $i_2227 = $i_2223;
+ label = 60;
+ break;
+ case 60:
+ $arrayidx312 = $edges_0_lcssa + ($i_2227 << 2) | 0;
+ $90 = HEAP32[$arrayidx312 >> 2] | 0;
+ $call313 = _getmainedge($90) | 0;
+ $cmp314 = ($call276 | 0) == ($call313 | 0);
+ if ($cmp314) {
+ label = 61;
+ break;
+ } else {
+ $cnt_0_lcssa = $cnt_0225;
+ $i_2_lcssa = $i_2227;
+ label = 72;
+ break;
+ }
+ case 61:
+ $91 = HEAP8[$adjacent] | 0;
+ $tobool319 = $91 << 24 >> 24 == 0;
+ if ($tobool319) {
+ label = 62;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 62:
+ $defined324 = $90 + 60 | 0;
+ $92 = HEAP8[$defined324] | 0;
+ $tobool326 = $92 << 24 >> 24 == 0;
+ if ($tobool326) {
+ label = 63;
+ break;
+ } else {
+ $cond336 = $90;
+ label = 64;
+ break;
+ }
+ case 63:
+ $defined330 = $90 + 100 | 0;
+ $93 = HEAP8[$defined330] | 0;
+ $tobool332 = $93 << 24 >> 24 == 0;
+ $call313_ = $tobool332 ? $call313 : $90;
+ $cond336 = $call313_;
+ label = 64;
+ break;
+ case 64:
+ $tree_index338 = $cond336 + 180 | 0;
+ $94 = HEAP32[$tree_index338 >> 2] | 0;
+ $and339 = $94 & 32;
+ $tobool340 = ($and339 | 0) == 0;
+ if ($tobool340) {
+ $eb_0 = $cond336;
+ label = 66;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $95 = $cond336 | 0;
+ _memcpy($73 | 0, $95 | 0, 192);
+ $head344 = $cond336 + 12 | 0;
+ $96 = HEAP32[$head344 >> 2] | 0;
+ HEAP32[$tail345 >> 2] = $96;
+ $tail346 = $cond336 + 16 | 0;
+ $97 = HEAP32[$tail346 >> 2] | 0;
+ HEAP32[$head347 >> 2] = $97;
+ $head_port351 = $cond336 + 72 | 0;
+ $98 = $head_port351;
+ HEAP32[$74 >> 2] = HEAP32[$98 >> 2] | 0;
+ HEAP32[$74 + 4 >> 2] = HEAP32[$98 + 4 >> 2] | 0;
+ HEAP32[$74 + 8 >> 2] = HEAP32[$98 + 8 >> 2] | 0;
+ HEAP32[$74 + 12 >> 2] = HEAP32[$98 + 12 >> 2] | 0;
+ HEAP32[$74 + 16 >> 2] = HEAP32[$98 + 16 >> 2] | 0;
+ HEAP32[$74 + 20 >> 2] = HEAP32[$98 + 20 >> 2] | 0;
+ HEAP32[$74 + 24 >> 2] = HEAP32[$98 + 24 >> 2] | 0;
+ HEAP32[$74 + 28 >> 2] = HEAP32[$98 + 28 >> 2] | 0;
+ HEAP32[$74 + 32 >> 2] = HEAP32[$98 + 32 >> 2] | 0;
+ HEAP32[$74 + 36 >> 2] = HEAP32[$98 + 36 >> 2] | 0;
+ $tail_port355 = $cond336 + 32 | 0;
+ $99 = $tail_port355;
+ HEAP32[$75 >> 2] = HEAP32[$99 >> 2] | 0;
+ HEAP32[$75 + 4 >> 2] = HEAP32[$99 + 4 >> 2] | 0;
+ HEAP32[$75 + 8 >> 2] = HEAP32[$99 + 8 >> 2] | 0;
+ HEAP32[$75 + 12 >> 2] = HEAP32[$99 + 12 >> 2] | 0;
+ HEAP32[$75 + 16 >> 2] = HEAP32[$99 + 16 >> 2] | 0;
+ HEAP32[$75 + 20 >> 2] = HEAP32[$99 + 20 >> 2] | 0;
+ HEAP32[$75 + 24 >> 2] = HEAP32[$99 + 24 >> 2] | 0;
+ HEAP32[$75 + 28 >> 2] = HEAP32[$99 + 28 >> 2] | 0;
+ HEAP32[$75 + 32 >> 2] = HEAP32[$99 + 32 >> 2] | 0;
+ HEAP32[$75 + 36 >> 2] = HEAP32[$99 + 36 >> 2] | 0;
+ HEAP8[$edge_type357] = 1;
+ HEAP32[$to_orig359 >> 2] = $cond336;
+ $eb_0 = $fwdedgeb;
+ label = 66;
+ break;
+ case 66:
+ $tail_port364 = $eb_0 + 32 | 0;
+ $call365 = _portcmp($tail_port362, $tail_port364) | 0;
+ $tobool366 = ($call365 | 0) == 0;
+ if ($tobool366) {
+ label = 67;
+ break;
+ } else {
+ $cnt_0_lcssa = $cnt_0225;
+ $i_2_lcssa = $i_2227;
+ label = 72;
+ break;
+ }
+ case 67:
+ $head_port372 = $eb_0 + 72 | 0;
+ $call373 = _portcmp($head_port370, $head_port372) | 0;
+ $tobool374 = ($call373 | 0) == 0;
+ if ($tobool374) {
+ label = 68;
+ break;
+ } else {
+ $cnt_0_lcssa = $cnt_0225;
+ $i_2_lcssa = $i_2227;
+ label = 72;
+ break;
+ }
+ case 68:
+ $100 = HEAP32[$tree_index378 >> 2] | 0;
+ $and379 = $100 & 15;
+ $cmp380 = ($and379 | 0) == 2;
+ if ($cmp380) {
+ label = 69;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 69:
+ $101 = HEAP32[$label384 >> 2] | 0;
+ $label386 = $90 + 112 | 0;
+ $102 = HEAP32[$label386 >> 2] | 0;
+ $cmp387 = ($101 | 0) == ($102 | 0);
+ if ($cmp387) {
+ label = 70;
+ break;
+ } else {
+ $cnt_0_lcssa = $cnt_0225;
+ $i_2_lcssa = $i_2227;
+ label = 72;
+ break;
+ }
+ case 70:
+ $103 = HEAP32[$arrayidx312 >> 2] | 0;
+ $tree_index393 = $103 + 180 | 0;
+ $104 = HEAP32[$tree_index393 >> 2] | 0;
+ $and394 = $104 & 64;
+ $tobool395 = ($and394 | 0) == 0;
+ if ($tobool395) {
+ label = 71;
+ break;
+ } else {
+ $cnt_0_lcssa = $cnt_0225;
+ $i_2_lcssa = $i_2227;
+ label = 72;
+ break;
+ }
+ case 71:
+ $inc399 = $cnt_0225 + 1 | 0;
+ $i_2 = $i_2227 + 1 | 0;
+ $cmp309 = ($i_2 | 0) < ($n_edges_0_lcssa | 0);
+ if ($cmp309) {
+ $cnt_0225 = $inc399;
+ $i_2227 = $i_2;
+ label = 60;
+ break;
+ } else {
+ $cnt_0_lcssa = $inc399;
+ $i_2_lcssa = $i_2;
+ label = 72;
+ break;
+ }
+ case 72:
+ $tail402 = $81 + 16 | 0;
+ $105 = HEAP32[$tail402 >> 2] | 0;
+ $head403 = $81 + 12 | 0;
+ $106 = HEAP32[$head403 >> 2] | 0;
+ $cmp404 = ($105 | 0) == ($106 | 0);
+ $rank412 = $105 + 236 | 0;
+ $107 = HEAP32[$rank412 >> 2] | 0;
+ if ($cmp404) {
+ label = 73;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 73:
+ $108 = HEAP16[$maxrank >> 1] | 0;
+ $conv415 = $108 << 16 >> 16;
+ $cmp416 = ($107 | 0) == ($conv415 | 0);
+ if ($cmp416) {
+ label = 74;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 74:
+ $cmp419 = ($107 | 0) > 0;
+ if ($cmp419) {
+ label = 75;
+ break;
+ } else {
+ label = 76;
+ break;
+ }
+ case 75:
+ $sub422 = $107 - 1 | 0;
+ $109 = HEAP32[$rank424 >> 2] | 0;
+ $v426 = $109 + ($sub422 * 44 & -1) + 4 | 0;
+ $110 = HEAP32[$v426 >> 2] | 0;
+ $111 = HEAP32[$110 >> 2] | 0;
+ $y = $111 + 40 | 0;
+ $112 = +HEAPF64[$y >> 3];
+ $y432 = $105 + 40 | 0;
+ $113 = +HEAPF64[$y432 >> 3];
+ $sub433 = $112 - $113;
+ $conv434 = ~~$sub433;
+ $sizey_0 = $conv434;
+ label = 80;
+ break;
+ case 76:
+ $ht = $105 + 96 | 0;
+ $114 = +HEAPF64[$ht >> 3];
+ $conv436 = ~~$114;
+ $sizey_0 = $conv436;
+ label = 80;
+ break;
+ case 77:
+ $115 = HEAP16[$minrank >> 1] | 0;
+ $conv441 = $115 << 16 >> 16;
+ $cmp442 = ($107 | 0) == ($conv441 | 0);
+ if ($cmp442) {
+ label = 78;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 78:
+ $y447 = $105 + 40 | 0;
+ $116 = +HEAPF64[$y447 >> 3];
+ $add448 = $107 + 1 | 0;
+ $117 = HEAP32[$rank450 >> 2] | 0;
+ $v452 = $117 + ($add448 * 44 & -1) + 4 | 0;
+ $118 = HEAP32[$v452 >> 2] | 0;
+ $119 = HEAP32[$118 >> 2] | 0;
+ $y456 = $119 + 40 | 0;
+ $120 = +HEAPF64[$y456 >> 3];
+ $sub457 = $116 - $120;
+ $conv458 = ~~$sub457;
+ $sizey_0 = $conv458;
+ label = 80;
+ break;
+ case 79:
+ $sub461 = $107 - 1 | 0;
+ $121 = HEAP32[$rank463 >> 2] | 0;
+ $v465 = $121 + ($sub461 * 44 & -1) + 4 | 0;
+ $122 = HEAP32[$v465 >> 2] | 0;
+ $123 = HEAP32[$122 >> 2] | 0;
+ $y469 = $123 + 40 | 0;
+ $124 = +HEAPF64[$y469 >> 3];
+ $y472 = $105 + 40 | 0;
+ $125 = +HEAPF64[$y472 >> 3];
+ $sub473 = $124 - $125;
+ $conv474 = ~~$sub473;
+ $add479 = $107 + 1 | 0;
+ $v483 = $121 + ($add479 * 44 & -1) + 4 | 0;
+ $126 = HEAP32[$v483 >> 2] | 0;
+ $127 = HEAP32[$126 >> 2] | 0;
+ $y487 = $127 + 40 | 0;
+ $128 = +HEAPF64[$y487 >> 3];
+ $sub488 = $125 - $128;
+ $conv489 = ~~$sub488;
+ $cmp490 = ($conv474 | 0) < ($conv489 | 0);
+ $cond495 = $cmp490 ? $conv474 : $conv489;
+ $sizey_0 = $cond495;
+ label = 80;
+ break;
+ case 80:
+ $129 = HEAP32[$Multisep >> 2] | 0;
+ $conv499 = +($129 | 0);
+ $div500 = ($sizey_0 | 0) / 2 & -1;
+ $conv501 = +($div500 | 0);
+ _makeSelfEdge($2, $71, $i_1232, $cnt_0_lcssa, $conv499, $conv501, 4216);
+ $cmp503229 = ($cnt_0_lcssa | 0) > 0;
+ if ($cmp503229) {
+ $b_0230 = 0;
+ label = 81;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 81:
+ $add506 = $b_0230 + $i_1232 | 0;
+ $arrayidx507 = $edges_0_lcssa + ($add506 << 2) | 0;
+ $130 = HEAP32[$arrayidx507 >> 2] | 0;
+ $label509 = $130 + 112 | 0;
+ $131 = HEAP32[$label509 >> 2] | 0;
+ $tobool510 = ($131 | 0) == 0;
+ if ($tobool510) {
+ label = 83;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 82:
+ _updateBB($72, $131);
+ label = 83;
+ break;
+ case 83:
+ $inc516 = $b_0230 + 1 | 0;
+ $cmp503 = ($inc516 | 0) < ($cnt_0_lcssa | 0);
+ if ($cmp503) {
+ $b_0230 = $inc516;
+ label = 81;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 84:
+ $rank524 = $106 + 236 | 0;
+ $132 = HEAP32[$rank524 >> 2] | 0;
+ $cmp525 = ($107 | 0) == ($132 | 0);
+ if ($cmp525) {
+ label = 85;
+ break;
+ } else {
+ label = 87;
+ break;
+ }
+ case 85:
+ _make_flat_edge($sd, $2, $edges_0_lcssa, $i_1232, $cnt_0_lcssa, $and);
+ label = 86;
+ break;
+ case 86:
+ $cmp271 = ($i_2_lcssa | 0) < ($n_edges_0_lcssa | 0);
+ if ($cmp271) {
+ $i_1232 = $i_2_lcssa;
+ label = 54;
+ break;
+ } else {
+ label = 88;
+ break;
+ }
+ case 87:
+ _make_regular_edge($sd, $2, $edges_0_lcssa, $i_1232, $cnt_0_lcssa, $and);
+ label = 86;
+ break;
+ case 88:
+ $nlist533 = $g + 220 | 0;
+ $n_1220 = HEAP32[$nlist533 >> 2] | 0;
+ $tobool535221 = ($n_1220 | 0) == 0;
+ if ($tobool535221) {
+ label = 94;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 89:
+ $133 = $g;
+ $n_1222 = $n_1220;
+ label = 90;
+ break;
+ case 90:
+ $node_type538 = $n_1222 + 162 | 0;
+ $134 = HEAP8[$node_type538] | 0;
+ $cmp540 = $134 << 24 >> 24 == 1;
+ if ($cmp540) {
+ label = 91;
+ break;
+ } else {
+ label = 93;
+ break;
+ }
+ case 91:
+ $label544 = $n_1222 + 120 | 0;
+ $135 = HEAP32[$label544 >> 2] | 0;
+ $tobool545 = ($135 | 0) == 0;
+ if ($tobool545) {
+ label = 93;
+ break;
+ } else {
+ label = 92;
+ break;
+ }
+ case 92:
+ _place_vnlabel($n_1222);
+ $136 = HEAP32[$label544 >> 2] | 0;
+ _updateBB($133, $136);
+ label = 93;
+ break;
+ case 93:
+ $next552 = $n_1222 + 168 | 0;
+ $n_1 = HEAP32[$next552 >> 2] | 0;
+ $tobool535 = ($n_1 | 0) == 0;
+ if ($tobool535) {
+ label = 94;
+ break;
+ } else {
+ $n_1222 = $n_1;
+ label = 90;
+ break;
+ }
+ case 94:
+ $tobool554 = ($normalize | 0) == 0;
+ if ($tobool554) {
+ label = 96;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 95:
+ _edge_normalize($g);
+ label = 96;
+ break;
+ case 96:
+ $137 = HEAP32[41936] | 0;
+ $tobool557 = ($137 | 0) != 0;
+ $138 = HEAP32[41900] | 0;
+ $tobool559 = ($138 | 0) != 0;
+ $or_cond = $tobool557 | $tobool559;
+ if ($or_cond) {
+ label = 97;
+ break;
+ } else {
+ label = 110;
+ break;
+ }
+ case 97:
+ $139 = $g;
+ $call561 = _agfstnode($139) | 0;
+ $tobool563218 = ($call561 | 0) == 0;
+ if ($tobool563218) {
+ label = 110;
+ break;
+ } else {
+ label = 98;
+ break;
+ }
+ case 98:
+ $140 = $g;
+ $141 = $g;
+ $n_2_in219 = $call561;
+ label = 99;
+ break;
+ case 99:
+ $142 = HEAP32[41936] | 0;
+ $tobool565 = ($142 | 0) == 0;
+ if ($tobool565) {
+ label = 104;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 100:
+ $call567 = _agfstin($139, $n_2_in219) | 0;
+ $tobool569214 = ($call567 | 0) == 0;
+ if ($tobool569214) {
+ label = 104;
+ break;
+ } else {
+ $e_0_in215 = $call567;
+ label = 101;
+ break;
+ }
+ case 101:
+ $head_label = $e_0_in215 + 116 | 0;
+ $143 = HEAP32[$head_label >> 2] | 0;
+ $tobool572 = ($143 | 0) == 0;
+ if ($tobool572) {
+ label = 103;
+ break;
+ } else {
+ label = 102;
+ break;
+ }
+ case 102:
+ $144 = $e_0_in215;
+ _place_portlabel($144, 1);
+ $145 = HEAP32[$head_label >> 2] | 0;
+ $146 = $145;
+ _updateBB($141, $146);
+ label = 103;
+ break;
+ case 103:
+ $call578 = _agnxtin($139, $e_0_in215) | 0;
+ $tobool569 = ($call578 | 0) == 0;
+ if ($tobool569) {
+ label = 104;
+ break;
+ } else {
+ $e_0_in215 = $call578;
+ label = 101;
+ break;
+ }
+ case 104:
+ $147 = HEAP32[41900] | 0;
+ $tobool581 = ($147 | 0) == 0;
+ if ($tobool581) {
+ label = 109;
+ break;
+ } else {
+ label = 105;
+ break;
+ }
+ case 105:
+ $call583 = _agfstout($139, $n_2_in219) | 0;
+ $tobool585216 = ($call583 | 0) == 0;
+ if ($tobool585216) {
+ label = 109;
+ break;
+ } else {
+ $e_1_in217 = $call583;
+ label = 106;
+ break;
+ }
+ case 106:
+ $tail_label = $e_1_in217 + 120 | 0;
+ $148 = HEAP32[$tail_label >> 2] | 0;
+ $tobool588 = ($148 | 0) == 0;
+ if ($tobool588) {
+ label = 108;
+ break;
+ } else {
+ label = 107;
+ break;
+ }
+ case 107:
+ $149 = $e_1_in217;
+ _place_portlabel($149, 0);
+ $150 = HEAP32[$tail_label >> 2] | 0;
+ $151 = $150;
+ _updateBB($140, $151);
+ label = 108;
+ break;
+ case 108:
+ $call594 = _agnxtout($139, $e_1_in217) | 0;
+ $tobool585 = ($call594 | 0) == 0;
+ if ($tobool585) {
+ label = 109;
+ break;
+ } else {
+ $e_1_in217 = $call594;
+ label = 106;
+ break;
+ }
+ case 109:
+ $call598 = _agnxtnode($139, $n_2_in219) | 0;
+ $tobool563 = ($call598 | 0) == 0;
+ if ($tobool563) {
+ label = 110;
+ break;
+ } else {
+ $n_2_in219 = $call598;
+ label = 99;
+ break;
+ }
+ case 110:
+ _free($67);
+ $152 = HEAP32[$69 >> 2] | 0;
+ $153 = $152;
+ _free($153);
+ _free($call);
+ $154 = HEAP32[$Rank_box >> 2] | 0;
+ $155 = $154;
+ _free($155);
+ _routesplinesterm();
+ HEAP32[41356] = 1;
+ label = 111;
+ break;
+ case 111:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _place_vnlabel($n) {
+ $n = $n | 0;
+ var $size = 0, $0 = 0, $cmp = 0, $list = 0, $1 = 0, $e_0_in = 0, $e_0 = 0, $edge_type = 0, $2 = 0, $cmp3 = 0, $to_orig = 0, $label = 0, $3 = 0, $graph = 0, $4 = 0, $rankdir = 0, $5 = 0, $and9 = 0, $tobool = 0, $dimen_sroa_1_8__idx5 = 0, $dimen_sroa_0_0__idx = 0, $cond_in = 0, $cond = 0.0, $x11 = 0, $6 = 0.0, $div = 0.0, $add = 0.0, $x14 = 0, $y17 = 0, $7 = 0.0, $8 = 0, $y21 = 0, $9 = 0, $set = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $n + 180 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $list = $n + 184 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $e_0_in = $1;
+ label = 4;
+ break;
+ case 4:
+ $e_0 = HEAP32[$e_0_in >> 2] | 0;
+ $edge_type = $e_0 + 128 | 0;
+ $2 = HEAP8[$edge_type] | 0;
+ $cmp3 = $2 << 24 >> 24 == 0;
+ $to_orig = $e_0 + 132 | 0;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ $e_0_in = $to_orig;
+ label = 4;
+ break;
+ }
+ case 5:
+ $label = $e_0 + 112 | 0;
+ $3 = HEAP32[$label >> 2] | 0;
+ $graph = $n + 20 | 0;
+ $4 = HEAP32[$graph >> 2] | 0;
+ $rankdir = $4 + 156 | 0;
+ $5 = HEAP32[$rankdir >> 2] | 0;
+ $and9 = $5 & 1;
+ $tobool = ($and9 | 0) == 0;
+ $dimen_sroa_1_8__idx5 = $3 + 32 | 0;
+ $dimen_sroa_0_0__idx = $3 + 24 | 0;
+ $cond_in = $tobool ? $dimen_sroa_0_0__idx : $dimen_sroa_1_8__idx5;
+ $cond = +HEAPF64[$cond_in >> 3];
+ $x11 = $n + 32 | 0;
+ $6 = +HEAPF64[$x11 >> 3];
+ $div = $cond * .5;
+ $add = $6 + $div;
+ $x14 = $3 + 56 | 0;
+ HEAPF64[$x14 >> 3] = $add;
+ $y17 = $n + 40 | 0;
+ $7 = +HEAPF64[$y17 >> 3];
+ $8 = HEAP32[$label >> 2] | 0;
+ $y21 = $8 + 64 | 0;
+ HEAPF64[$y21 >> 3] = $7;
+ $9 = HEAP32[$label >> 2] | 0;
+ $set = $9 + 81 | 0;
+ HEAP8[$set] = 1;
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _getmainedge($e) {
+ $e = $e | 0;
+ var $le_0 = 0, $to_virt = 0, $0 = 0, $tobool = 0, $le_1 = 0, $to_orig = 0, $1 = 0, $tobool5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $le_0 = $e;
+ label = 3;
+ break;
+ case 3:
+ $to_virt = $le_0 + 188 | 0;
+ $0 = HEAP32[$to_virt >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $le_1 = $le_0;
+ label = 4;
+ break;
+ } else {
+ $le_0 = $0;
+ label = 3;
+ break;
+ }
+ case 4:
+ $to_orig = $le_1 + 132 | 0;
+ $1 = HEAP32[$to_orig >> 2] | 0;
+ $tobool5 = ($1 | 0) == 0;
+ if ($tobool5) {
+ label = 5;
+ break;
+ } else {
+ $le_1 = $1;
+ label = 4;
+ break;
+ }
+ case 5:
+ return $le_1 | 0;
+ }
+ return 0;
+}
+function _edgecmp($ptr0, $ptr1) {
+ $ptr0 = $ptr0 | 0;
+ $ptr1 = $ptr1 | 0;
+ var $fwdedgea = 0, $fwdedgeb = 0, $0 = 0, $1 = 0, $tree_index = 0, $2 = 0, $and = 0, $tree_index2 = 0, $3 = 0, $and3 = 0, $cmp = 0, $sub = 0, $call = 0, $call4 = 0, $tail = 0, $4 = 0, $rank = 0, $5 = 0, $head = 0, $6 = 0, $rank7 = 0, $7 = 0, $sub8 = 0, $tail9 = 0, $8 = 0, $rank11 = 0, $9 = 0, $head12 = 0, $10 = 0, $rank14 = 0, $11 = 0, $sub15 = 0, $cmp18 = 0, $sub22 = 0, $cond = 0, $cmp24 = 0, $sub30 = 0, $cond32 = 0, $cmp33 = 0, $sub36 = 0, $x = 0, $12 = 0.0, $x43 = 0, $13 = 0.0, $sub44 = 0.0, $x48 = 0, $14 = 0.0, $x52 = 0, $15 = 0.0, $sub53 = 0.0, $conv54 = 0, $cmp55 = 0, $sub61 = 0, $cond63 = 0, $conv64 = 0, $cmp65 = 0, $sub71 = 0, $cond73 = 0, $cmp74 = 0, $sub77 = 0, $id = 0, $16 = 0, $id79 = 0, $17 = 0, $cmp80 = 0, $sub85 = 0, $defined = 0, $18 = 0, $tobool = 0, $defined90 = 0, $19 = 0, $tobool92 = 0, $call_ = 0, $cond96 = 0, $tree_index98 = 0, $20 = 0, $and99 = 0, $tobool100 = 0, $21 = 0, $22 = 0, $head102 = 0, $23 = 0, $tail103 = 0, $tail104 = 0, $24 = 0, $head105 = 0, $tail_port107 = 0, $head_port109 = 0, $25 = 0, $26 = 0, $head_port111 = 0, $tail_port113 = 0, $27 = 0, $28 = 0, $edge_type = 0, $to_orig = 0, $ea_0 = 0, $defined119 = 0, $29 = 0, $tobool121 = 0, $defined125 = 0, $30 = 0, $tobool127 = 0, $call4_ = 0, $cond131 = 0, $tree_index133 = 0, $31 = 0, $and134 = 0, $tobool135 = 0, $32 = 0, $33 = 0, $head138 = 0, $34 = 0, $tail139 = 0, $tail140 = 0, $35 = 0, $head141 = 0, $tail_port143 = 0, $head_port145 = 0, $36 = 0, $37 = 0, $head_port147 = 0, $tail_port149 = 0, $38 = 0, $39 = 0, $edge_type151 = 0, $to_orig153 = 0, $eb_0 = 0, $tail_port156 = 0, $tail_port158 = 0, $call159 = 0, $tobool160 = 0, $head_port164 = 0, $head_port166 = 0, $call167 = 0, $tobool168 = 0, $40 = 0, $and173 = 0, $41 = 0, $and176 = 0, $cmp177 = 0, $sub180 = 0, $id195 = 0, $42 = 0, $id196 = 0, $43 = 0, $sub197 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 384 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $fwdedgea = __stackBase__ | 0;
+ $fwdedgeb = __stackBase__ + 192 | 0;
+ $0 = HEAP32[$ptr0 >> 2] | 0;
+ $1 = HEAP32[$ptr1 >> 2] | 0;
+ $tree_index = $0 + 180 | 0;
+ $2 = HEAP32[$tree_index >> 2] | 0;
+ $and = $2 & 15;
+ $tree_index2 = $1 + 180 | 0;
+ $3 = HEAP32[$tree_index2 >> 2] | 0;
+ $and3 = $3 & 15;
+ $cmp = ($and | 0) == ($and3 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub = $and3 - $and | 0;
+ $retval_0 = $sub;
+ label = 23;
+ break;
+ case 4:
+ $call = _getmainedge($0) | 0;
+ $call4 = _getmainedge($1) | 0;
+ $tail = $call + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $rank = $4 + 236 | 0;
+ $5 = HEAP32[$rank >> 2] | 0;
+ $head = $call + 12 | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ $rank7 = $6 + 236 | 0;
+ $7 = HEAP32[$rank7 >> 2] | 0;
+ $sub8 = $5 - $7 | 0;
+ $tail9 = $call4 + 16 | 0;
+ $8 = HEAP32[$tail9 >> 2] | 0;
+ $rank11 = $8 + 236 | 0;
+ $9 = HEAP32[$rank11 >> 2] | 0;
+ $head12 = $call4 + 12 | 0;
+ $10 = HEAP32[$head12 >> 2] | 0;
+ $rank14 = $10 + 236 | 0;
+ $11 = HEAP32[$rank14 >> 2] | 0;
+ $sub15 = $9 - $11 | 0;
+ $cmp18 = ($sub8 | 0) > -1;
+ $sub22 = -$sub8 | 0;
+ $cond = $cmp18 ? $sub8 : $sub22;
+ $cmp24 = ($sub15 | 0) > -1;
+ $sub30 = -$sub15 | 0;
+ $cond32 = $cmp24 ? $sub15 : $sub30;
+ $cmp33 = ($cond | 0) == ($cond32 | 0);
+ if ($cmp33) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $sub36 = $cond - $cond32 | 0;
+ $retval_0 = $sub36;
+ label = 23;
+ break;
+ case 6:
+ $x = $4 + 32 | 0;
+ $12 = +HEAPF64[$x >> 3];
+ $x43 = $6 + 32 | 0;
+ $13 = +HEAPF64[$x43 >> 3];
+ $sub44 = $12 - $13;
+ $x48 = $8 + 32 | 0;
+ $14 = +HEAPF64[$x48 >> 3];
+ $x52 = $10 + 32 | 0;
+ $15 = +HEAPF64[$x52 >> 3];
+ $sub53 = $14 - $15;
+ $conv54 = ~~$sub44;
+ $cmp55 = ($conv54 | 0) > -1;
+ $sub61 = -$conv54 | 0;
+ $cond63 = $cmp55 ? $conv54 : $sub61;
+ $conv64 = ~~$sub53;
+ $cmp65 = ($conv64 | 0) > -1;
+ $sub71 = -$conv64 | 0;
+ $cond73 = $cmp65 ? $conv64 : $sub71;
+ $cmp74 = ($cond63 | 0) == ($cond73 | 0);
+ if ($cmp74) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub77 = $cond63 - $cond73 | 0;
+ $retval_0 = $sub77;
+ label = 23;
+ break;
+ case 8:
+ $id = $call + 20 | 0;
+ $16 = HEAP32[$id >> 2] | 0;
+ $id79 = $call4 + 20 | 0;
+ $17 = HEAP32[$id79 >> 2] | 0;
+ $cmp80 = ($16 | 0) == ($17 | 0);
+ if ($cmp80) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $sub85 = $16 - $17 | 0;
+ $retval_0 = $sub85;
+ label = 23;
+ break;
+ case 10:
+ $defined = $0 + 60 | 0;
+ $18 = HEAP8[$defined] | 0;
+ $tobool = $18 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ $cond96 = $0;
+ label = 12;
+ break;
+ }
+ case 11:
+ $defined90 = $0 + 100 | 0;
+ $19 = HEAP8[$defined90] | 0;
+ $tobool92 = $19 << 24 >> 24 == 0;
+ $call_ = $tobool92 ? $call : $0;
+ $cond96 = $call_;
+ label = 12;
+ break;
+ case 12:
+ $tree_index98 = $cond96 + 180 | 0;
+ $20 = HEAP32[$tree_index98 >> 2] | 0;
+ $and99 = $20 & 32;
+ $tobool100 = ($and99 | 0) == 0;
+ if ($tobool100) {
+ $ea_0 = $cond96;
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $21 = $fwdedgea | 0;
+ $22 = $cond96 | 0;
+ _memcpy($21 | 0, $22 | 0, 192);
+ $head102 = $cond96 + 12 | 0;
+ $23 = HEAP32[$head102 >> 2] | 0;
+ $tail103 = $fwdedgea + 16 | 0;
+ HEAP32[$tail103 >> 2] = $23;
+ $tail104 = $cond96 + 16 | 0;
+ $24 = HEAP32[$tail104 >> 2] | 0;
+ $head105 = $fwdedgea + 12 | 0;
+ HEAP32[$head105 >> 2] = $24;
+ $tail_port107 = $fwdedgea + 32 | 0;
+ $head_port109 = $cond96 + 72 | 0;
+ $25 = $tail_port107;
+ $26 = $head_port109;
+ HEAP32[$25 >> 2] = HEAP32[$26 >> 2] | 0;
+ HEAP32[$25 + 4 >> 2] = HEAP32[$26 + 4 >> 2] | 0;
+ HEAP32[$25 + 8 >> 2] = HEAP32[$26 + 8 >> 2] | 0;
+ HEAP32[$25 + 12 >> 2] = HEAP32[$26 + 12 >> 2] | 0;
+ HEAP32[$25 + 16 >> 2] = HEAP32[$26 + 16 >> 2] | 0;
+ HEAP32[$25 + 20 >> 2] = HEAP32[$26 + 20 >> 2] | 0;
+ HEAP32[$25 + 24 >> 2] = HEAP32[$26 + 24 >> 2] | 0;
+ HEAP32[$25 + 28 >> 2] = HEAP32[$26 + 28 >> 2] | 0;
+ HEAP32[$25 + 32 >> 2] = HEAP32[$26 + 32 >> 2] | 0;
+ HEAP32[$25 + 36 >> 2] = HEAP32[$26 + 36 >> 2] | 0;
+ $head_port111 = $fwdedgea + 72 | 0;
+ $tail_port113 = $cond96 + 32 | 0;
+ $27 = $head_port111;
+ $28 = $tail_port113;
+ HEAP32[$27 >> 2] = HEAP32[$28 >> 2] | 0;
+ HEAP32[$27 + 4 >> 2] = HEAP32[$28 + 4 >> 2] | 0;
+ HEAP32[$27 + 8 >> 2] = HEAP32[$28 + 8 >> 2] | 0;
+ HEAP32[$27 + 12 >> 2] = HEAP32[$28 + 12 >> 2] | 0;
+ HEAP32[$27 + 16 >> 2] = HEAP32[$28 + 16 >> 2] | 0;
+ HEAP32[$27 + 20 >> 2] = HEAP32[$28 + 20 >> 2] | 0;
+ HEAP32[$27 + 24 >> 2] = HEAP32[$28 + 24 >> 2] | 0;
+ HEAP32[$27 + 28 >> 2] = HEAP32[$28 + 28 >> 2] | 0;
+ HEAP32[$27 + 32 >> 2] = HEAP32[$28 + 32 >> 2] | 0;
+ HEAP32[$27 + 36 >> 2] = HEAP32[$28 + 36 >> 2] | 0;
+ $edge_type = $fwdedgea + 128 | 0;
+ HEAP8[$edge_type] = 1;
+ $to_orig = $fwdedgea + 132 | 0;
+ HEAP32[$to_orig >> 2] = $cond96;
+ $ea_0 = $fwdedgea;
+ label = 14;
+ break;
+ case 14:
+ $defined119 = $1 + 60 | 0;
+ $29 = HEAP8[$defined119] | 0;
+ $tobool121 = $29 << 24 >> 24 == 0;
+ if ($tobool121) {
+ label = 15;
+ break;
+ } else {
+ $cond131 = $1;
+ label = 16;
+ break;
+ }
+ case 15:
+ $defined125 = $1 + 100 | 0;
+ $30 = HEAP8[$defined125] | 0;
+ $tobool127 = $30 << 24 >> 24 == 0;
+ $call4_ = $tobool127 ? $call4 : $1;
+ $cond131 = $call4_;
+ label = 16;
+ break;
+ case 16:
+ $tree_index133 = $cond131 + 180 | 0;
+ $31 = HEAP32[$tree_index133 >> 2] | 0;
+ $and134 = $31 & 32;
+ $tobool135 = ($and134 | 0) == 0;
+ if ($tobool135) {
+ $eb_0 = $cond131;
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $32 = $fwdedgeb | 0;
+ $33 = $cond131 | 0;
+ _memcpy($32 | 0, $33 | 0, 192);
+ $head138 = $cond131 + 12 | 0;
+ $34 = HEAP32[$head138 >> 2] | 0;
+ $tail139 = $fwdedgeb + 16 | 0;
+ HEAP32[$tail139 >> 2] = $34;
+ $tail140 = $cond131 + 16 | 0;
+ $35 = HEAP32[$tail140 >> 2] | 0;
+ $head141 = $fwdedgeb + 12 | 0;
+ HEAP32[$head141 >> 2] = $35;
+ $tail_port143 = $fwdedgeb + 32 | 0;
+ $head_port145 = $cond131 + 72 | 0;
+ $36 = $tail_port143;
+ $37 = $head_port145;
+ HEAP32[$36 >> 2] = HEAP32[$37 >> 2] | 0;
+ HEAP32[$36 + 4 >> 2] = HEAP32[$37 + 4 >> 2] | 0;
+ HEAP32[$36 + 8 >> 2] = HEAP32[$37 + 8 >> 2] | 0;
+ HEAP32[$36 + 12 >> 2] = HEAP32[$37 + 12 >> 2] | 0;
+ HEAP32[$36 + 16 >> 2] = HEAP32[$37 + 16 >> 2] | 0;
+ HEAP32[$36 + 20 >> 2] = HEAP32[$37 + 20 >> 2] | 0;
+ HEAP32[$36 + 24 >> 2] = HEAP32[$37 + 24 >> 2] | 0;
+ HEAP32[$36 + 28 >> 2] = HEAP32[$37 + 28 >> 2] | 0;
+ HEAP32[$36 + 32 >> 2] = HEAP32[$37 + 32 >> 2] | 0;
+ HEAP32[$36 + 36 >> 2] = HEAP32[$37 + 36 >> 2] | 0;
+ $head_port147 = $fwdedgeb + 72 | 0;
+ $tail_port149 = $cond131 + 32 | 0;
+ $38 = $head_port147;
+ $39 = $tail_port149;
+ HEAP32[$38 >> 2] = HEAP32[$39 >> 2] | 0;
+ HEAP32[$38 + 4 >> 2] = HEAP32[$39 + 4 >> 2] | 0;
+ HEAP32[$38 + 8 >> 2] = HEAP32[$39 + 8 >> 2] | 0;
+ HEAP32[$38 + 12 >> 2] = HEAP32[$39 + 12 >> 2] | 0;
+ HEAP32[$38 + 16 >> 2] = HEAP32[$39 + 16 >> 2] | 0;
+ HEAP32[$38 + 20 >> 2] = HEAP32[$39 + 20 >> 2] | 0;
+ HEAP32[$38 + 24 >> 2] = HEAP32[$39 + 24 >> 2] | 0;
+ HEAP32[$38 + 28 >> 2] = HEAP32[$39 + 28 >> 2] | 0;
+ HEAP32[$38 + 32 >> 2] = HEAP32[$39 + 32 >> 2] | 0;
+ HEAP32[$38 + 36 >> 2] = HEAP32[$39 + 36 >> 2] | 0;
+ $edge_type151 = $fwdedgeb + 128 | 0;
+ HEAP8[$edge_type151] = 1;
+ $to_orig153 = $fwdedgeb + 132 | 0;
+ HEAP32[$to_orig153 >> 2] = $cond131;
+ $eb_0 = $fwdedgeb;
+ label = 18;
+ break;
+ case 18:
+ $tail_port156 = $ea_0 + 32 | 0;
+ $tail_port158 = $eb_0 + 32 | 0;
+ $call159 = _portcmp($tail_port156, $tail_port158) | 0;
+ $tobool160 = ($call159 | 0) == 0;
+ if ($tobool160) {
+ label = 19;
+ break;
+ } else {
+ $retval_0 = $call159;
+ label = 23;
+ break;
+ }
+ case 19:
+ $head_port164 = $ea_0 + 72 | 0;
+ $head_port166 = $eb_0 + 72 | 0;
+ $call167 = _portcmp($head_port164, $head_port166) | 0;
+ $tobool168 = ($call167 | 0) == 0;
+ if ($tobool168) {
+ label = 20;
+ break;
+ } else {
+ $retval_0 = $call167;
+ label = 23;
+ break;
+ }
+ case 20:
+ $40 = HEAP32[$tree_index >> 2] | 0;
+ $and173 = $40 & 192;
+ $41 = HEAP32[$tree_index2 >> 2] | 0;
+ $and176 = $41 & 192;
+ $cmp177 = ($and173 | 0) == ($and176 | 0);
+ if ($cmp177) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $sub180 = $and173 - $and176 | 0;
+ $retval_0 = $sub180;
+ label = 23;
+ break;
+ case 22:
+ $id195 = $0 + 20 | 0;
+ $42 = HEAP32[$id195 >> 2] | 0;
+ $id196 = $1 + 20 | 0;
+ $43 = HEAP32[$id196 >> 2] | 0;
+ $sub197 = $42 - $43 | 0;
+ $retval_0 = $sub197;
+ label = 23;
+ break;
+ case 23:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _make_flat_edge($sp, $P, $edges, $ind, $cnt, $et) {
+ $sp = $sp | 0;
+ $P = $P | 0;
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $et = $et | 0;
+ var $fwdedge = 0, $pn = 0, $tend = 0, $hend = 0, $arrayidx = 0, $0 = 0, $tree_index = 0, $1 = 0, $and = 0, $tobool = 0, $2 = 0, $3 = 0, $head = 0, $4 = 0, $tail = 0, $tail1 = 0, $5 = 0, $head2 = 0, $tail_port = 0, $head_port = 0, $6 = 0, $7 = 0, $head_port6 = 0, $tail_port8 = 0, $8 = 0, $9 = 0, $edge_type = 0, $to_orig = 0, $e_0 = 0, $10 = 0, $adjacent = 0, $11 = 0, $tobool13 = 0, $label = 0, $12 = 0, $tobool17 = 0, $cmp = 0, $tail21 = 0, $13 = 0, $head22 = 0, $14 = 0, $side = 0, $15 = 0, $side28 = 0, $16 = 0, $cmp30 = 0, $cmp32 = 0, $or_cond = 0, $cmp34 = 0, $cmp37 = 0, $or_cond117 = 0, $cmp40 = 0, $conv41 = 0, $tail43 = 0, $17 = 0, $head44 = 0, $18 = 0, $graph = 0, $19 = 0, $rank = 0, $20 = 0, $cmp46 = 0, $has_labels = 0, $21 = 0, $and51 = 0, $tobool52 = 0, $rank55 = 0, $22 = 0, $sub_pn_v = 0, $sub_pn = 0, $v = 0, $23 = 0, $24 = 0, $y = 0, $25 = 0.0, $ht1 = 0, $26 = 0, $conv63 = 0.0, $sub64 = 0.0, $y67 = 0, $27 = 0.0, $sub68 = 0.0, $ht2 = 0, $28 = 0, $conv72 = 0.0, $sub73 = 0.0, $ranksep = 0, $29 = 0, $conv76 = 0.0, $vspace_0 = 0.0, $Multisep = 0, $30 = 0, $conv78 = 0.0, $add = 0, $conv79 = 0.0, $div = 0.0, $div82 = 0.0, $cmp83124 = 0, $boxn87 = 0, $boxn130 = 0, $cmp204 = 0, $nbox = 0, $i_0125 = 0, $add85 = 0, $arrayidx86 = 0, $31 = 0, $32 = 0, $sub88 = 0, $b_sroa_0_0__idx1 = 0, $b_sroa_0_0_copyload2 = 0.0, $b_sroa_2_16__idx8 = 0, $b_sroa_2_16_copyload9 = 0.0, $b_sroa_3_24__idx12 = 0, $b_sroa_3_24_copyload13 = 0.0, $add99 = 0, $conv100 = 0.0, $mul = 0.0, $add101 = 0.0, $mul109 = 0.0, $add110 = 0.0, $33 = 0, $sub115 = 0, $x119 = 0, $34 = 0.0, $35 = 0.0, $36 = 0, $sub131 = 0, $x135 = 0, $37 = 0.0, $38 = 0.0, $add142 = 0.0, $39 = 0, $sub148 = 0, $b_sroa_0_0__idx = 0, $b_sroa_0_0_copyload = 0.0, $b_sroa_2_16__idx7 = 0, $b_sroa_2_16_copyload = 0.0, $b_sroa_3_24__idx11 = 0, $b_sroa_3_24_copyload = 0.0, $sub166 = 0.0, $40 = 0.0, $41 = 0, $cmp180118 = 0, $j_0119 = 0, $arrayidx184 = 0, $inc185 = 0, $42 = 0, $cmp180 = 0, $43 = 0, $cmp197122 = 0, $j_2123_in = 0, $j_2123 = 0, $arrayidx201 = 0, $cmp197 = 0, $call = 0, $call208 = 0, $ps_0 = 0, $44 = 0, $cmp210 = 0, $head214 = 0, $45 = 0, $46 = 0, $47 = 0, $cmp83 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1592 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $fwdedge = __stackBase__ | 0;
+ $pn = __stackBase__ + 192 | 0;
+ $tend = __stackBase__ + 200 | 0;
+ $hend = __stackBase__ + 896 | 0;
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $tree_index = $0 + 180 | 0;
+ $1 = HEAP32[$tree_index >> 2] | 0;
+ $and = $1 & 32;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ $e_0 = $0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $fwdedge | 0;
+ $3 = $0 | 0;
+ _memcpy($2 | 0, $3 | 0, 192);
+ $head = $0 + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ $tail = $fwdedge + 16 | 0;
+ HEAP32[$tail >> 2] = $4;
+ $tail1 = $0 + 16 | 0;
+ $5 = HEAP32[$tail1 >> 2] | 0;
+ $head2 = $fwdedge + 12 | 0;
+ HEAP32[$head2 >> 2] = $5;
+ $tail_port = $fwdedge + 32 | 0;
+ $head_port = $0 + 72 | 0;
+ $6 = $tail_port;
+ $7 = $head_port;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ HEAP32[$6 + 16 >> 2] = HEAP32[$7 + 16 >> 2] | 0;
+ HEAP32[$6 + 20 >> 2] = HEAP32[$7 + 20 >> 2] | 0;
+ HEAP32[$6 + 24 >> 2] = HEAP32[$7 + 24 >> 2] | 0;
+ HEAP32[$6 + 28 >> 2] = HEAP32[$7 + 28 >> 2] | 0;
+ HEAP32[$6 + 32 >> 2] = HEAP32[$7 + 32 >> 2] | 0;
+ HEAP32[$6 + 36 >> 2] = HEAP32[$7 + 36 >> 2] | 0;
+ $head_port6 = $fwdedge + 72 | 0;
+ $tail_port8 = $0 + 32 | 0;
+ $8 = $head_port6;
+ $9 = $tail_port8;
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ HEAP32[$8 + 16 >> 2] = HEAP32[$9 + 16 >> 2] | 0;
+ HEAP32[$8 + 20 >> 2] = HEAP32[$9 + 20 >> 2] | 0;
+ HEAP32[$8 + 24 >> 2] = HEAP32[$9 + 24 >> 2] | 0;
+ HEAP32[$8 + 28 >> 2] = HEAP32[$9 + 28 >> 2] | 0;
+ HEAP32[$8 + 32 >> 2] = HEAP32[$9 + 32 >> 2] | 0;
+ HEAP32[$8 + 36 >> 2] = HEAP32[$9 + 36 >> 2] | 0;
+ $edge_type = $fwdedge + 128 | 0;
+ HEAP8[$edge_type] = 1;
+ $to_orig = $fwdedge + 132 | 0;
+ HEAP32[$to_orig >> 2] = $0;
+ $e_0 = $fwdedge;
+ label = 4;
+ break;
+ case 4:
+ $10 = HEAP32[$arrayidx >> 2] | 0;
+ $adjacent = $10 + 129 | 0;
+ $11 = HEAP8[$adjacent] | 0;
+ $tobool13 = $11 << 24 >> 24 == 0;
+ if ($tobool13) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _make_flat_adj_edges($edges, $ind, $cnt, $e_0, $et);
+ label = 27;
+ break;
+ case 6:
+ $label = $e_0 + 112 | 0;
+ $12 = HEAP32[$label >> 2] | 0;
+ $tobool17 = ($12 | 0) == 0;
+ if ($tobool17) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _make_flat_labeled_edge($sp, $P, $e_0, $et);
+ label = 27;
+ break;
+ case 8:
+ $cmp = ($et | 0) == 2;
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $tail21 = $e_0 + 16 | 0;
+ $13 = HEAP32[$tail21 >> 2] | 0;
+ $head22 = $e_0 + 12 | 0;
+ $14 = HEAP32[$head22 >> 2] | 0;
+ _makeSimpleFlat($13, $14, $edges, $ind, $cnt, $et);
+ label = 27;
+ break;
+ case 10:
+ $side = $e_0 + 65 | 0;
+ $15 = HEAP8[$side] | 0;
+ $side28 = $e_0 + 105 | 0;
+ $16 = HEAP8[$side28] | 0;
+ $cmp30 = $15 << 24 >> 24 != 1;
+ $cmp32 = $16 << 24 >> 24 == 4;
+ $or_cond = $cmp30 | $cmp32;
+ if ($or_cond) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $cmp34 = $16 << 24 >> 24 != 1;
+ $cmp37 = $15 << 24 >> 24 == 4;
+ $or_cond117 = $cmp34 | $cmp37;
+ if ($or_cond117) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $cmp40 = ($et | 0) == 8;
+ $conv41 = $cmp40 & 1;
+ _make_flat_bottom_edges($sp, $P, $edges, $ind, $cnt, $e_0, $conv41);
+ label = 27;
+ break;
+ case 13:
+ $tail43 = $e_0 + 16 | 0;
+ $17 = HEAP32[$tail43 >> 2] | 0;
+ $head44 = $e_0 + 12 | 0;
+ $18 = HEAP32[$head44 >> 2] | 0;
+ $graph = $17 + 20 | 0;
+ $19 = HEAP32[$graph >> 2] | 0;
+ $rank = $17 + 236 | 0;
+ $20 = HEAP32[$rank >> 2] | 0;
+ $cmp46 = ($20 | 0) > 0;
+ if ($cmp46) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $has_labels = $19 + 153 | 0;
+ $21 = HEAP8[$has_labels] | 0;
+ $and51 = $21 & 1;
+ $tobool52 = $and51 << 24 >> 24 == 0;
+ $rank55 = $19 + 224 | 0;
+ $22 = HEAP32[$rank55 >> 2] | 0;
+ $sub_pn_v = $tobool52 ? -1 : -2;
+ $sub_pn = $sub_pn_v + $20 | 0;
+ $v = $22 + ($sub_pn * 44 & -1) + 4 | 0;
+ $23 = HEAP32[$v >> 2] | 0;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $y = $24 + 40 | 0;
+ $25 = +HEAPF64[$y >> 3];
+ $ht1 = $22 + ($sub_pn * 44 & -1) + 16 | 0;
+ $26 = HEAP32[$ht1 >> 2] | 0;
+ $conv63 = +($26 | 0);
+ $sub64 = $25 - $conv63;
+ $y67 = $17 + 40 | 0;
+ $27 = +HEAPF64[$y67 >> 3];
+ $sub68 = $sub64 - $27;
+ $ht2 = $22 + ($20 * 44 & -1) + 20 | 0;
+ $28 = HEAP32[$ht2 >> 2] | 0;
+ $conv72 = +($28 | 0);
+ $sub73 = $sub68 - $conv72;
+ $vspace_0 = $sub73;
+ label = 16;
+ break;
+ case 15:
+ $ranksep = $19 + 264 | 0;
+ $29 = HEAP32[$ranksep >> 2] | 0;
+ $conv76 = +($29 | 0);
+ $vspace_0 = $conv76;
+ label = 16;
+ break;
+ case 16:
+ $Multisep = $sp + 12 | 0;
+ $30 = HEAP32[$Multisep >> 2] | 0;
+ $conv78 = +($30 | 0);
+ $add = $cnt + 1 | 0;
+ $conv79 = +($add | 0);
+ $div = $conv78 / $conv79;
+ $div82 = $vspace_0 / $conv79;
+ _makeFlatEnd($sp, $P, $17, $e_0, $tend, 1);
+ _makeFlatEnd($sp, $P, $18, $e_0, $hend, 0);
+ $cmp83124 = ($cnt | 0) > 0;
+ if ($cmp83124) {
+ label = 17;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 17:
+ $boxn87 = $tend + 52 | 0;
+ $boxn130 = $hend + 52 | 0;
+ $cmp204 = ($et | 0) == 8;
+ $nbox = $P + 80 | 0;
+ $i_0125 = 0;
+ label = 18;
+ break;
+ case 18:
+ $add85 = $i_0125 + $ind | 0;
+ $arrayidx86 = $edges + ($add85 << 2) | 0;
+ $31 = HEAP32[$arrayidx86 >> 2] | 0;
+ $32 = HEAP32[$boxn87 >> 2] | 0;
+ $sub88 = $32 - 1 | 0;
+ $b_sroa_0_0__idx1 = $tend + 56 + ($sub88 << 5) | 0;
+ $b_sroa_0_0_copyload2 = +HEAPF64[$b_sroa_0_0__idx1 >> 3];
+ $b_sroa_2_16__idx8 = $tend + 56 + ($sub88 << 5) + 16 | 0;
+ $b_sroa_2_16_copyload9 = +HEAPF64[$b_sroa_2_16__idx8 >> 3];
+ $b_sroa_3_24__idx12 = $tend + 56 + ($sub88 << 5) + 24 | 0;
+ $b_sroa_3_24_copyload13 = +HEAPF64[$b_sroa_3_24__idx12 >> 3];
+ HEAPF64[6678] = $b_sroa_0_0_copyload2;
+ HEAPF64[6679] = $b_sroa_3_24_copyload13;
+ $add99 = $i_0125 + 1 | 0;
+ $conv100 = +($add99 | 0);
+ $mul = $div * $conv100;
+ $add101 = $mul + $b_sroa_2_16_copyload9;
+ HEAPF64[6680] = $add101;
+ $mul109 = $div82 * $conv100;
+ $add110 = $mul109 + $b_sroa_3_24_copyload13;
+ HEAPF64[6681] = $add110;
+ $33 = HEAP32[$boxn87 >> 2] | 0;
+ $sub115 = $33 - 1 | 0;
+ $x119 = $tend + 56 + ($sub115 << 5) | 0;
+ $34 = +HEAPF64[$x119 >> 3];
+ HEAPF64[6682] = $34;
+ $35 = +HEAPF64[6681];
+ HEAPF64[6683] = $35;
+ $36 = HEAP32[$boxn130 >> 2] | 0;
+ $sub131 = $36 - 1 | 0;
+ $x135 = $hend + 56 + ($sub131 << 5) + 16 | 0;
+ $37 = +HEAPF64[$x135 >> 3];
+ HEAPF64[6684] = $37;
+ $38 = +HEAPF64[6683];
+ $add142 = $div82 + $38;
+ HEAPF64[6685] = $add142;
+ $39 = HEAP32[$boxn130 >> 2] | 0;
+ $sub148 = $39 - 1 | 0;
+ $b_sroa_0_0__idx = $hend + 56 + ($sub148 << 5) | 0;
+ $b_sroa_0_0_copyload = +HEAPF64[$b_sroa_0_0__idx >> 3];
+ $b_sroa_2_16__idx7 = $hend + 56 + ($sub148 << 5) + 16 | 0;
+ $b_sroa_2_16_copyload = +HEAPF64[$b_sroa_2_16__idx7 >> 3];
+ $b_sroa_3_24__idx11 = $hend + 56 + ($sub148 << 5) + 24 | 0;
+ $b_sroa_3_24_copyload = +HEAPF64[$b_sroa_3_24__idx11 >> 3];
+ HEAPF64[6688] = $b_sroa_2_16_copyload;
+ HEAPF64[6687] = $b_sroa_3_24_copyload;
+ $sub166 = $b_sroa_0_0_copyload - $mul;
+ HEAPF64[6686] = $sub166;
+ $40 = +HEAPF64[6683];
+ HEAPF64[6689] = $40;
+ $41 = HEAP32[$boxn87 >> 2] | 0;
+ $cmp180118 = ($41 | 0) > 0;
+ if ($cmp180118) {
+ $j_0119 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $arrayidx184 = $tend + 56 + ($j_0119 << 5) | 0;
+ _add_box($P, $arrayidx184);
+ $inc185 = $j_0119 + 1 | 0;
+ $42 = HEAP32[$boxn87 >> 2] | 0;
+ $cmp180 = ($inc185 | 0) < ($42 | 0);
+ if ($cmp180) {
+ $j_0119 = $inc185;
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ _add_box($P, 53424);
+ _add_box($P, 53456);
+ _add_box($P, 53488);
+ $43 = HEAP32[$boxn130 >> 2] | 0;
+ $cmp197122 = ($43 | 0) > 0;
+ if ($cmp197122) {
+ $j_2123_in = $43;
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $j_2123 = $j_2123_in - 1 | 0;
+ $arrayidx201 = $hend + 56 + ($j_2123 << 5) | 0;
+ _add_box($P, $arrayidx201);
+ $cmp197 = ($j_2123 | 0) > 0;
+ if ($cmp197) {
+ $j_2123_in = $j_2123;
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ if ($cmp204) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ $call = _routesplines($P, $pn) | 0;
+ $ps_0 = $call;
+ label = 25;
+ break;
+ case 24:
+ $call208 = _routepolylines($P, $pn) | 0;
+ $ps_0 = $call208;
+ label = 25;
+ break;
+ case 25:
+ $44 = HEAP32[$pn >> 2] | 0;
+ $cmp210 = ($44 | 0) == 0;
+ if ($cmp210) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $head214 = $31 + 12 | 0;
+ $45 = HEAP32[$head214 >> 2] | 0;
+ $46 = $31;
+ $47 = $45;
+ _clip_and_install($46, $47, $ps_0, $44, 4216);
+ HEAP32[$nbox >> 2] = 0;
+ $cmp83 = ($add99 | 0) < ($cnt | 0);
+ if ($cmp83) {
+ $i_0125 = $add99;
+ label = 18;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _make_regular_edge($sp, $P, $edges, $ind, $cnt, $et) {
+ $sp = $sp | 0;
+ $P = $P | 0;
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $et = $et | 0;
+ var $hn = 0, $fwdedgea = 0, $fwdedgeb = 0, $fwdedge = 0, $tend = 0, $hend = 0, $b = 0, $pn = 0, $pointn = 0, $tmp = 0, $tmp122 = 0, $tmp153 = 0, $tmp175 = 0, $tmp188 = 0, $tmp275 = 0, $tmp322 = 0, $tmp324 = 0, $tmp361 = 0, $0 = 0, $tobool = 0, $call = 0, $1 = 0, $call1 = 0, $2 = 0, $arrayidx = 0, $3 = 0, $tail = 0, $4 = 0, $graph = 0, $5 = 0, $rank = 0, $6 = 0, $head = 0, $7 = 0, $rank4 = 0, $8 = 0, $sub = 0, $cmp = 0, $sub19 = 0, $cond = 0, $cmp20 = 0, $9 = 0, $10 = 0, $tree_index = 0, $11 = 0, $and = 0, $tobool23 = 0, $12 = 0, $13 = 0, $tail26 = 0, $14 = 0, $head28 = 0, $tail_port = 0, $head_port = 0, $15 = 0, $16 = 0, $head_port32 = 0, $tail_port34 = 0, $17 = 0, $18 = 0, $edge_type = 0, $to_orig = 0, $19 = 0, $tail38 = 0, $tail_port40 = 0, $20 = 0, $21 = 0, $tail44 = 0, $call46 = 0, $le_0 = 0, $to_virt = 0, $22 = 0, $tobool48 = 0, $head51 = 0, $23 = 0, $head52 = 0, $defined = 0, $edge_type56 = 0, $x = 0, $to_orig63 = 0, $24 = 0, $tree_index66 = 0, $25 = 0, $and67 = 0, $tobool68 = 0, $26 = 0, $27 = 0, $28 = 0, $tail72 = 0, $29 = 0, $head74 = 0, $tail_port76 = 0, $head_port78 = 0, $30 = 0, $31 = 0, $head_port80 = 0, $tail_port82 = 0, $32 = 0, $33 = 0, $edge_type84 = 0, $to_orig86 = 0, $hackflag_0 = 0, $e_0 = 0, $cmp89 = 0, $34 = 0, $call90 = 0, $tobool91 = 0, $cmp94 = 0, $tail95 = 0, $35 = 0, $head96 = 0, $36 = 0, $37 = 0, $38 = 0, $39 = 0, $call97 = 0, $40 = 0, $boxn98 = 0, $41 = 0, $sub99 = 0, $y101 = 0, $42 = 0.0, $y103 = 0, $43 = 0, $sub105 = 0, $y108 = 0, $44 = 0.0, $y110 = 0, $y112 = 0, $45 = 0.0, $rank114 = 0, $46 = 0, $graph115 = 0, $47 = 0, $rank117 = 0, $48 = 0, $ht1 = 0, $49 = 0, $conv119 = 0.0, $sub120 = 0.0, $conv121 = 0, $50 = 0, $x124 = 0, $51 = 0.0, $x126 = 0, $52 = 0.0, $cmp127 = 0, $53 = 0.0, $54 = 0.0, $cmp134 = 0, $55 = 0, $inc = 0, $arrayidx139 = 0, $56 = 0, $57 = 0, $node_type194215 = 0, $58 = 0, $cmp144195216 = 0, $59 = 0, $has_labels = 0, $60 = 0, $61 = 0, $62 = 0, $boxn191 = 0, $theta = 0, $constrained = 0, $63 = 0, $theta314 = 0, $constrained316 = 0, $64 = 0, $tn_0_ph221 = 0, $e_1_ph220 = 0, $si_0_ph218 = 0, $sl_0_ph217 = 0, $65 = 0, $tn_0201 = 0, $e_1200 = 0, $smode_0199 = 0, $si_0198 = 0, $sl_0197 = 0, $boxn_0196 = 0, $66 = 0, $call146 = 0, $lnot = 0, $inc149225 = 0, $arrayidx150 = 0, $rank152 = 0, $67 = 0, $68 = 0, $tobool154 = 0, $69 = 0, $call156 = 0, $70 = 0, $and159 = 0, $tobool160 = 0, $cond161 = 0, $cmp162 = 0, $sub165 = 0, $call156_sub165 = 0, $si_0_ = 0, $smode_0_ = 0, $sl_1 = 0, $si_1 = 0, $smode_1 = 0, $tobool167 = 0, $cmp168 = 0, $or_cond = 0, $dec = 0, $inc171 = 0, $arrayidx172 = 0, $71 = 0, $list = 0, $72 = 0, $73 = 0, $74 = 0, $75 = 0, $list178 = 0, $76 = 0, $77 = 0, $tail180 = 0, $78 = 0, $head181 = 0, $79 = 0, $node_type = 0, $80 = 0, $cmp144 = 0, $81 = 0, $list186 = 0, $82 = 0, $83 = 0, $head189 = 0, $84 = 0, $call190 = 0, $85 = 0, $86 = 0, $sub192 = 0, $arrayidx194 = 0, $87 = 0, $y197 = 0, $88 = 0.0, $rank199 = 0, $89 = 0, $graph200 = 0, $90 = 0, $rank202 = 0, $91 = 0, $ht2 = 0, $92 = 0, $conv204 = 0.0, $add = 0.0, $conv205 = 0, $93 = 0.0, $94 = 0.0, $cmp211 = 0, $95 = 0.0, $96 = 0.0, $cmp218 = 0, $97 = 0, $inc222 = 0, $arrayidx224 = 0, $98 = 0, $call229 = 0, $call231 = 0, $99 = 0, $cmp235 = 0, $arrayidx238 = 0, $100 = 0, $101 = 0, $arrayidx240 = 0, $arrayidx241 = 0, $102 = 0, $sub242 = 0, $arrayidx243 = 0, $103 = 0, $104 = 0, $105 = 0, $ps_0_ph = 0, $_pr = 0, $106 = 0, $ps_0 = 0, $cmp246 = 0, $ps_0165 = 0, $107 = 0, $108 = 0, $add250 = 0, $109 = 0, $cmp251 = 0, $mul = 0, $110 = 0, $111 = 0, $mul255 = 0, $call256 = 0, $112 = 0, $113 = 0, $cmp258186 = 0, $114 = 0, $115 = 0, $pointn_promoted188 = 0, $116 = 0, $smax236 = 0, $inc260189 = 0, $i_0187 = 0, $inc260 = 0, $arrayidx261 = 0, $arrayidx262 = 0, $117 = 0, $118 = 0, $inc263 = 0, $cmp258 = 0, $119 = 0, $120 = 0, $list266 = 0, $121 = 0, $122 = 0, $123 = 0, $call268 = 0, $tail269 = 0, $124 = 0, $head270 = 0, $125 = 0, $list273 = 0, $126 = 0, $127 = 0, $call276 = 0, $128 = 0, $129 = 0, $sub278 = 0, $arrayidx280 = 0, $y283 = 0, $130 = 0.0, $rank285 = 0, $131 = 0, $graph286 = 0, $132 = 0, $rank288 = 0, $133 = 0, $ht1290 = 0, $134 = 0, $conv291 = 0.0, $sub292 = 0.0, $conv293 = 0, $135 = 0.0, $136 = 0.0, $cmp299 = 0, $137 = 0.0, $138 = 0.0, $cmp306 = 0, $139 = 0, $inc310 = 0, $arrayidx312 = 0, $140 = 0, $141 = 0, $node_type194 = 0, $142 = 0, $cmp144195 = 0, $segfirst_0_ph208 = 0, $tn_0_lcssa = 0, $e_1_lcssa = 0, $boxn_0_lcssa = 0, $inc318 = 0, $arrayidx319 = 0, $rank321 = 0, $143 = 0, $144 = 0, $145 = 0, $146 = 0, $147 = 0, $148 = 0, $tobool325 = 0, $cond329 = 0, $head330 = 0, $149 = 0, $call331 = 0, $150 = 0, $boxn332 = 0, $151 = 0, $sub333 = 0, $y337 = 0, $152 = 0.0, $153 = 0, $sub341 = 0, $y345 = 0, $154 = 0.0, $155 = 0, $y350 = 0, $156 = 0.0, $rank352 = 0, $157 = 0, $graph353 = 0, $158 = 0, $rank355 = 0, $159 = 0, $ht2357 = 0, $160 = 0, $conv358 = 0.0, $add359 = 0.0, $conv360 = 0, $161 = 0, $162 = 0.0, $163 = 0.0, $cmp366 = 0, $164 = 0.0, $165 = 0.0, $cmp373 = 0, $166 = 0, $inc377 = 0, $arrayidx379 = 0, $167 = 0, $call383 = 0, $call385 = 0, $ps_1 = 0, $168 = 0, $cmp390 = 0, $or_cond168 = 0, $arrayidx393 = 0, $169 = 0, $170 = 0, $arrayidx395 = 0, $arrayidx396 = 0, $171 = 0, $sub397 = 0, $arrayidx398 = 0, $172 = 0, $173 = 0, $174 = 0, $cmp400 = 0, $175 = 0, $176 = 0, $add404 = 0, $177 = 0, $cmp405 = 0, $mul409 = 0, $178 = 0, $179 = 0, $mul410 = 0, $call411 = 0, $180 = 0, $181 = 0, $cmp414183 = 0, $182 = 0, $183 = 0, $pointn_promoted = 0, $184 = 0, $smax = 0, $inc417185 = 0, $i_1184 = 0, $inc417 = 0, $arrayidx418 = 0, $arrayidx419 = 0, $185 = 0, $186 = 0, $inc421 = 0, $cmp414 = 0, $187 = 0, $head425 = 0, $188 = 0, $189 = 0, $cond429 = 0, $cmp431 = 0, $190 = 0, $191 = 0, $192 = 0, $193 = 0, $194 = 0, $Multisep = 0, $195 = 0, $sub438180 = 0, $cmp439181 = 0, $sub435 = 0, $196 = 0, $mul436 = 0, $div = 0, $conv442 = 0.0, $197 = 0, $198 = 0, $sub438 = 0, $i_2182 = 0, $x444 = 0, $199 = 0.0, $sub445 = 0.0, $inc447 = 0, $cmp439 = 0, $200 = 0, $201 = 0, $cmp449 = 0, $202 = 0, $203 = 0, $mul452 = 0, $call453 = 0, $204 = 0, $205 = 0, $cmp456177 = 0, $206 = 0, $207 = 0, $208 = 0, $i_3178 = 0, $arrayidx459 = 0, $arrayidx460 = 0, $209 = 0, $210 = 0, $inc462 = 0, $cmp456 = 0, $_lcssa176 = 0, $211 = 0, $212 = 0, $213 = 0, $214 = 0, $cmp465174 = 0, $215 = 0, $sub495169 = 0, $cmp496170 = 0, $cmp508172 = 0, $sub495 = 0, $216 = 0, $tail478 = 0, $head480 = 0, $tail_port482 = 0, $217 = 0, $head_port486 = 0, $218 = 0, $edge_type490 = 0, $to_orig492 = 0, $j_0175 = 0, $add468 = 0, $arrayidx469 = 0, $219 = 0, $tree_index471 = 0, $220 = 0, $and472 = 0, $tobool473 = 0, $221 = 0, $head477 = 0, $222 = 0, $tail479 = 0, $223 = 0, $head_port484 = 0, $224 = 0, $tail_port488 = 0, $225 = 0, $e_2 = 0, $i_4171 = 0, $226 = 0, $conv500 = 0.0, $227 = 0, $x502 = 0, $228 = 0.0, $add503 = 0.0, $inc505 = 0, $cmp496 = 0, $229 = 0, $230 = 0, $i_5173 = 0, $arrayidx511 = 0, $arrayidx512 = 0, $231 = 0, $232 = 0, $inc514 = 0, $cmp508 = 0, $head516 = 0, $233 = 0, $234 = 0, $235 = 0, $236 = 0, $inc518 = 0, $cmp465 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 2312 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $hn = __stackBase__ | 0;
+ $fwdedgea = __stackBase__ + 8 | 0;
+ $fwdedgeb = __stackBase__ + 200 | 0;
+ $fwdedge = __stackBase__ + 392 | 0;
+ $tend = __stackBase__ + 584 | 0;
+ $hend = __stackBase__ + 1280 | 0;
+ $b = __stackBase__ + 1976 | 0;
+ $pn = __stackBase__ + 2008 | 0;
+ $pointn = __stackBase__ + 2016 | 0;
+ $tmp = __stackBase__ + 2024 | 0;
+ $tmp122 = __stackBase__ + 2056 | 0;
+ $tmp153 = __stackBase__ + 2088 | 0;
+ $tmp175 = __stackBase__ + 2120 | 0;
+ $tmp188 = __stackBase__ + 2152 | 0;
+ $tmp275 = __stackBase__ + 2184 | 0;
+ $tmp322 = __stackBase__ + 2216 | 0;
+ $tmp324 = __stackBase__ + 2248 | 0;
+ $tmp361 = __stackBase__ + 2280 | 0;
+ $0 = HEAP32[2854] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _gmalloc(32e3) | 0;
+ $1 = $call;
+ HEAP32[2854] = $1;
+ $call1 = _gmalloc(32e3) | 0;
+ $2 = $call1;
+ HEAP32[2852] = $2;
+ HEAP32[2858] = 2e3;
+ HEAP32[2856] = 2e3;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $tail = $3 + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $graph = $4 + 20 | 0;
+ $5 = HEAP32[$graph >> 2] | 0;
+ $rank = $4 + 236 | 0;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $head = $3 + 12 | 0;
+ $7 = HEAP32[$head >> 2] | 0;
+ $rank4 = $7 + 236 | 0;
+ $8 = HEAP32[$rank4 >> 2] | 0;
+ $sub = $6 - $8 | 0;
+ $cmp = ($sub | 0) > -1;
+ $sub19 = -$sub | 0;
+ $cond = $cmp ? $sub : $sub19;
+ $cmp20 = ($cond | 0) > 1;
+ if ($cmp20) {
+ label = 5;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 5:
+ $9 = $fwdedgea | 0;
+ $10 = $3 | 0;
+ _memcpy($9 | 0, $10 | 0, 192);
+ $tree_index = $3 + 180 | 0;
+ $11 = HEAP32[$tree_index >> 2] | 0;
+ $and = $11 & 32;
+ $tobool23 = ($and | 0) == 0;
+ $12 = $fwdedgeb | 0;
+ _memcpy($12 | 0, $10 | 0, 192);
+ if ($tobool23) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $13 = HEAP32[$head >> 2] | 0;
+ $tail26 = $fwdedgeb + 16 | 0;
+ HEAP32[$tail26 >> 2] = $13;
+ $14 = HEAP32[$tail >> 2] | 0;
+ $head28 = $fwdedgeb + 12 | 0;
+ HEAP32[$head28 >> 2] = $14;
+ $tail_port = $fwdedgeb + 32 | 0;
+ $head_port = $3 + 72 | 0;
+ $15 = $tail_port;
+ $16 = $head_port;
+ HEAP32[$15 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ HEAP32[$15 + 16 >> 2] = HEAP32[$16 + 16 >> 2] | 0;
+ HEAP32[$15 + 20 >> 2] = HEAP32[$16 + 20 >> 2] | 0;
+ HEAP32[$15 + 24 >> 2] = HEAP32[$16 + 24 >> 2] | 0;
+ HEAP32[$15 + 28 >> 2] = HEAP32[$16 + 28 >> 2] | 0;
+ HEAP32[$15 + 32 >> 2] = HEAP32[$16 + 32 >> 2] | 0;
+ HEAP32[$15 + 36 >> 2] = HEAP32[$16 + 36 >> 2] | 0;
+ $head_port32 = $fwdedgeb + 72 | 0;
+ $tail_port34 = $3 + 32 | 0;
+ $17 = $head_port32;
+ $18 = $tail_port34;
+ HEAP32[$17 >> 2] = HEAP32[$18 >> 2] | 0;
+ HEAP32[$17 + 4 >> 2] = HEAP32[$18 + 4 >> 2] | 0;
+ HEAP32[$17 + 8 >> 2] = HEAP32[$18 + 8 >> 2] | 0;
+ HEAP32[$17 + 12 >> 2] = HEAP32[$18 + 12 >> 2] | 0;
+ HEAP32[$17 + 16 >> 2] = HEAP32[$18 + 16 >> 2] | 0;
+ HEAP32[$17 + 20 >> 2] = HEAP32[$18 + 20 >> 2] | 0;
+ HEAP32[$17 + 24 >> 2] = HEAP32[$18 + 24 >> 2] | 0;
+ HEAP32[$17 + 28 >> 2] = HEAP32[$18 + 28 >> 2] | 0;
+ HEAP32[$17 + 32 >> 2] = HEAP32[$18 + 32 >> 2] | 0;
+ HEAP32[$17 + 36 >> 2] = HEAP32[$18 + 36 >> 2] | 0;
+ $edge_type = $fwdedgeb + 128 | 0;
+ HEAP8[$edge_type] = 1;
+ $to_orig = $fwdedgeb + 132 | 0;
+ HEAP32[$to_orig >> 2] = $3;
+ $19 = HEAP32[$head >> 2] | 0;
+ $tail38 = $fwdedgea + 16 | 0;
+ HEAP32[$tail38 >> 2] = $19;
+ $tail_port40 = $fwdedgea + 32 | 0;
+ $20 = $tail_port40;
+ HEAP32[$20 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$20 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$20 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$20 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ HEAP32[$20 + 16 >> 2] = HEAP32[$16 + 16 >> 2] | 0;
+ HEAP32[$20 + 20 >> 2] = HEAP32[$16 + 20 >> 2] | 0;
+ HEAP32[$20 + 24 >> 2] = HEAP32[$16 + 24 >> 2] | 0;
+ HEAP32[$20 + 28 >> 2] = HEAP32[$16 + 28 >> 2] | 0;
+ HEAP32[$20 + 32 >> 2] = HEAP32[$16 + 32 >> 2] | 0;
+ HEAP32[$20 + 36 >> 2] = HEAP32[$16 + 36 >> 2] | 0;
+ label = 8;
+ break;
+ case 7:
+ $21 = HEAP32[$tail >> 2] | 0;
+ $tail44 = $fwdedgea + 16 | 0;
+ HEAP32[$tail44 >> 2] = $21;
+ label = 8;
+ break;
+ case 8:
+ $call46 = _getmainedge($3) | 0;
+ $le_0 = $call46;
+ label = 9;
+ break;
+ case 9:
+ $to_virt = $le_0 + 188 | 0;
+ $22 = HEAP32[$to_virt >> 2] | 0;
+ $tobool48 = ($22 | 0) == 0;
+ if ($tobool48) {
+ label = 10;
+ break;
+ } else {
+ $le_0 = $22;
+ label = 9;
+ break;
+ }
+ case 10:
+ $head51 = $le_0 + 12 | 0;
+ $23 = HEAP32[$head51 >> 2] | 0;
+ $head52 = $fwdedgea + 12 | 0;
+ HEAP32[$head52 >> 2] = $23;
+ $defined = $fwdedgea + 100 | 0;
+ HEAP8[$defined] = 0;
+ $edge_type56 = $fwdedgea + 128 | 0;
+ HEAP8[$edge_type56] = 1;
+ $x = $fwdedgea + 72 | 0;
+ $to_orig63 = $fwdedgea + 132 | 0;
+ $24 = $x;
+ _memset($24 | 0, 0, 16);
+ HEAP32[$to_orig63 >> 2] = $3;
+ $e_0 = $fwdedgea;
+ $hackflag_0 = 1;
+ label = 13;
+ break;
+ case 11:
+ $tree_index66 = $3 + 180 | 0;
+ $25 = HEAP32[$tree_index66 >> 2] | 0;
+ $and67 = $25 & 32;
+ $tobool68 = ($and67 | 0) == 0;
+ if ($tobool68) {
+ $e_0 = $3;
+ $hackflag_0 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $26 = $fwdedgea | 0;
+ $27 = $3 | 0;
+ _memcpy($26 | 0, $27 | 0, 192);
+ $28 = HEAP32[$head >> 2] | 0;
+ $tail72 = $fwdedgea + 16 | 0;
+ HEAP32[$tail72 >> 2] = $28;
+ $29 = HEAP32[$tail >> 2] | 0;
+ $head74 = $fwdedgea + 12 | 0;
+ HEAP32[$head74 >> 2] = $29;
+ $tail_port76 = $fwdedgea + 32 | 0;
+ $head_port78 = $3 + 72 | 0;
+ $30 = $tail_port76;
+ $31 = $head_port78;
+ HEAP32[$30 >> 2] = HEAP32[$31 >> 2] | 0;
+ HEAP32[$30 + 4 >> 2] = HEAP32[$31 + 4 >> 2] | 0;
+ HEAP32[$30 + 8 >> 2] = HEAP32[$31 + 8 >> 2] | 0;
+ HEAP32[$30 + 12 >> 2] = HEAP32[$31 + 12 >> 2] | 0;
+ HEAP32[$30 + 16 >> 2] = HEAP32[$31 + 16 >> 2] | 0;
+ HEAP32[$30 + 20 >> 2] = HEAP32[$31 + 20 >> 2] | 0;
+ HEAP32[$30 + 24 >> 2] = HEAP32[$31 + 24 >> 2] | 0;
+ HEAP32[$30 + 28 >> 2] = HEAP32[$31 + 28 >> 2] | 0;
+ HEAP32[$30 + 32 >> 2] = HEAP32[$31 + 32 >> 2] | 0;
+ HEAP32[$30 + 36 >> 2] = HEAP32[$31 + 36 >> 2] | 0;
+ $head_port80 = $fwdedgea + 72 | 0;
+ $tail_port82 = $3 + 32 | 0;
+ $32 = $head_port80;
+ $33 = $tail_port82;
+ HEAP32[$32 >> 2] = HEAP32[$33 >> 2] | 0;
+ HEAP32[$32 + 4 >> 2] = HEAP32[$33 + 4 >> 2] | 0;
+ HEAP32[$32 + 8 >> 2] = HEAP32[$33 + 8 >> 2] | 0;
+ HEAP32[$32 + 12 >> 2] = HEAP32[$33 + 12 >> 2] | 0;
+ HEAP32[$32 + 16 >> 2] = HEAP32[$33 + 16 >> 2] | 0;
+ HEAP32[$32 + 20 >> 2] = HEAP32[$33 + 20 >> 2] | 0;
+ HEAP32[$32 + 24 >> 2] = HEAP32[$33 + 24 >> 2] | 0;
+ HEAP32[$32 + 28 >> 2] = HEAP32[$33 + 28 >> 2] | 0;
+ HEAP32[$32 + 32 >> 2] = HEAP32[$33 + 32 >> 2] | 0;
+ HEAP32[$32 + 36 >> 2] = HEAP32[$33 + 36 >> 2] | 0;
+ $edge_type84 = $fwdedgea + 128 | 0;
+ HEAP8[$edge_type84] = 1;
+ $to_orig86 = $fwdedgea + 132 | 0;
+ HEAP32[$to_orig86 >> 2] = $3;
+ $e_0 = $fwdedgea;
+ $hackflag_0 = 0;
+ label = 13;
+ break;
+ case 13:
+ $cmp89 = ($et | 0) == 2;
+ if ($cmp89) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $34 = HEAP32[2854] | 0;
+ $call90 = _makeLineEdge($e_0, $34, $hn) | 0;
+ HEAP32[$pointn >> 2] = $call90;
+ $tobool91 = ($call90 | 0) == 0;
+ if ($tobool91) {
+ label = 15;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 15:
+ $cmp94 = ($et | 0) == 8;
+ HEAP32[$pointn >> 2] = 0;
+ $tail95 = $e_0 + 16 | 0;
+ $35 = HEAP32[$tail95 >> 2] | 0;
+ $head96 = $e_0 + 12 | 0;
+ $36 = HEAP32[$head96 >> 2] | 0;
+ HEAP32[$hn >> 2] = $36;
+ _maximal_bbox($tmp, $sp, $35, 0, $e_0);
+ $37 = $tend;
+ $38 = $tmp;
+ HEAP32[$37 >> 2] = HEAP32[$38 >> 2] | 0;
+ HEAP32[$37 + 4 >> 2] = HEAP32[$38 + 4 >> 2] | 0;
+ HEAP32[$37 + 8 >> 2] = HEAP32[$38 + 8 >> 2] | 0;
+ HEAP32[$37 + 12 >> 2] = HEAP32[$38 + 12 >> 2] | 0;
+ HEAP32[$37 + 16 >> 2] = HEAP32[$38 + 16 >> 2] | 0;
+ HEAP32[$37 + 20 >> 2] = HEAP32[$38 + 20 >> 2] | 0;
+ HEAP32[$37 + 24 >> 2] = HEAP32[$38 + 24 >> 2] | 0;
+ HEAP32[$37 + 28 >> 2] = HEAP32[$38 + 28 >> 2] | 0;
+ $39 = $b;
+ HEAP32[$39 >> 2] = HEAP32[$38 >> 2] | 0;
+ HEAP32[$39 + 4 >> 2] = HEAP32[$38 + 4 >> 2] | 0;
+ HEAP32[$39 + 8 >> 2] = HEAP32[$38 + 8 >> 2] | 0;
+ HEAP32[$39 + 12 >> 2] = HEAP32[$38 + 12 >> 2] | 0;
+ HEAP32[$39 + 16 >> 2] = HEAP32[$38 + 16 >> 2] | 0;
+ HEAP32[$39 + 20 >> 2] = HEAP32[$38 + 20 >> 2] | 0;
+ $call97 = _spline_merge($35) | 0;
+ $40 = $e_0;
+ _beginpath($P, $40, 1, $tend, $call97);
+ $boxn98 = $tend + 52 | 0;
+ $41 = HEAP32[$boxn98 >> 2] | 0;
+ $sub99 = $41 - 1 | 0;
+ $y101 = $tend + 56 + ($sub99 << 5) + 24 | 0;
+ $42 = +HEAPF64[$y101 >> 3];
+ $y103 = $b + 24 | 0;
+ HEAPF64[$y103 >> 3] = $42;
+ $43 = HEAP32[$boxn98 >> 2] | 0;
+ $sub105 = $43 - 1 | 0;
+ $y108 = $tend + 56 + ($sub105 << 5) + 8 | 0;
+ $44 = +HEAPF64[$y108 >> 3];
+ $y110 = $b + 8 | 0;
+ HEAPF64[$y110 >> 3] = $44;
+ $y112 = $35 + 40 | 0;
+ $45 = +HEAPF64[$y112 >> 3];
+ $rank114 = $35 + 236 | 0;
+ $46 = HEAP32[$rank114 >> 2] | 0;
+ $graph115 = $35 + 20 | 0;
+ $47 = HEAP32[$graph115 >> 2] | 0;
+ $rank117 = $47 + 224 | 0;
+ $48 = HEAP32[$rank117 >> 2] | 0;
+ $ht1 = $48 + ($46 * 44 & -1) + 16 | 0;
+ $49 = HEAP32[$ht1 >> 2] | 0;
+ $conv119 = +($49 | 0);
+ $sub120 = $45 - $conv119;
+ $conv121 = ~~$sub120;
+ _makeregularend($tmp122, $b, 1, $conv121);
+ $50 = $tmp122;
+ HEAP32[$39 >> 2] = HEAP32[$50 >> 2] | 0;
+ HEAP32[$39 + 4 >> 2] = HEAP32[$50 + 4 >> 2] | 0;
+ HEAP32[$39 + 8 >> 2] = HEAP32[$50 + 8 >> 2] | 0;
+ HEAP32[$39 + 12 >> 2] = HEAP32[$50 + 12 >> 2] | 0;
+ HEAP32[$39 + 16 >> 2] = HEAP32[$50 + 16 >> 2] | 0;
+ HEAP32[$39 + 20 >> 2] = HEAP32[$50 + 20 >> 2] | 0;
+ HEAP32[$39 + 24 >> 2] = HEAP32[$50 + 24 >> 2] | 0;
+ HEAP32[$39 + 28 >> 2] = HEAP32[$50 + 28 >> 2] | 0;
+ $x124 = $b | 0;
+ $51 = +HEAPF64[$x124 >> 3];
+ $x126 = $b + 16 | 0;
+ $52 = +HEAPF64[$x126 >> 3];
+ $cmp127 = $51 < $52;
+ if ($cmp127) {
+ label = 16;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 16:
+ $53 = +HEAPF64[$y110 >> 3];
+ $54 = +HEAPF64[$y103 >> 3];
+ $cmp134 = $53 < $54;
+ if ($cmp134) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $55 = HEAP32[$boxn98 >> 2] | 0;
+ $inc = $55 + 1 | 0;
+ HEAP32[$boxn98 >> 2] = $inc;
+ $arrayidx139 = $tend + 56 + ($55 << 5) | 0;
+ $56 = $arrayidx139;
+ HEAP32[$56 >> 2] = HEAP32[$39 >> 2] | 0;
+ HEAP32[$56 + 4 >> 2] = HEAP32[$39 + 4 >> 2] | 0;
+ HEAP32[$56 + 8 >> 2] = HEAP32[$39 + 8 >> 2] | 0;
+ HEAP32[$56 + 12 >> 2] = HEAP32[$39 + 12 >> 2] | 0;
+ HEAP32[$56 + 16 >> 2] = HEAP32[$39 + 16 >> 2] | 0;
+ HEAP32[$56 + 20 >> 2] = HEAP32[$39 + 20 >> 2] | 0;
+ HEAP32[$56 + 24 >> 2] = HEAP32[$39 + 24 >> 2] | 0;
+ HEAP32[$56 + 28 >> 2] = HEAP32[$39 + 28 >> 2] | 0;
+ label = 18;
+ break;
+ case 18:
+ $57 = HEAP32[$hn >> 2] | 0;
+ $node_type194215 = $57 + 162 | 0;
+ $58 = HEAP8[$node_type194215] | 0;
+ $cmp144195216 = $58 << 24 >> 24 == 1;
+ if ($cmp144195216) {
+ label = 19;
+ break;
+ } else {
+ $boxn_0_lcssa = 0;
+ $e_1_lcssa = $e_0;
+ $tn_0_lcssa = $35;
+ $segfirst_0_ph208 = $e_0;
+ label = 46;
+ break;
+ }
+ case 19:
+ $59 = $tmp153;
+ $has_labels = $5 + 153 | 0;
+ $60 = $tmp175;
+ $61 = $hend;
+ $62 = $tmp188;
+ $boxn191 = $hend + 52 | 0;
+ $theta = $P + 56 | 0;
+ $constrained = $P + 69 | 0;
+ $63 = $tmp275;
+ $theta314 = $P + 16 | 0;
+ $constrained316 = $P + 29 | 0;
+ $sl_0_ph217 = 0;
+ $si_0_ph218 = -1;
+ $e_1_ph220 = $e_0;
+ $tn_0_ph221 = $35;
+ $64 = $57;
+ label = 20;
+ break;
+ case 20:
+ $boxn_0196 = 0;
+ $sl_0197 = $sl_0_ph217;
+ $si_0198 = $si_0_ph218;
+ $smode_0199 = 0;
+ $e_1200 = $e_1_ph220;
+ $tn_0201 = $tn_0_ph221;
+ $65 = $64;
+ label = 21;
+ break;
+ case 21:
+ $66 = HEAP32[1055] | 0;
+ $call146 = FUNCTION_TABLE_ii[$66 & 1023]($65) | 0;
+ $lnot = $call146 << 24 >> 24 == 0;
+ if ($lnot) {
+ label = 22;
+ break;
+ } else {
+ $boxn_0_lcssa = $boxn_0196;
+ $e_1_lcssa = $e_1200;
+ $tn_0_lcssa = $tn_0201;
+ $segfirst_0_ph208 = $e_1_ph220;
+ label = 46;
+ break;
+ }
+ case 22:
+ $inc149225 = $boxn_0196 | 1;
+ $arrayidx150 = 53424 + ($boxn_0196 << 5) | 0;
+ $rank152 = $tn_0201 + 236 | 0;
+ $67 = HEAP32[$rank152 >> 2] | 0;
+ _rank_box($tmp153, $sp, $5, $67);
+ $68 = $arrayidx150;
+ HEAP32[$68 >> 2] = HEAP32[$59 >> 2] | 0;
+ HEAP32[$68 + 4 >> 2] = HEAP32[$59 + 4 >> 2] | 0;
+ HEAP32[$68 + 8 >> 2] = HEAP32[$59 + 8 >> 2] | 0;
+ HEAP32[$68 + 12 >> 2] = HEAP32[$59 + 12 >> 2] | 0;
+ HEAP32[$68 + 16 >> 2] = HEAP32[$59 + 16 >> 2] | 0;
+ HEAP32[$68 + 20 >> 2] = HEAP32[$59 + 20 >> 2] | 0;
+ HEAP32[$68 + 24 >> 2] = HEAP32[$59 + 24 >> 2] | 0;
+ HEAP32[$68 + 28 >> 2] = HEAP32[$59 + 28 >> 2] | 0;
+ $tobool154 = ($smode_0199 | 0) == 0;
+ if ($tobool154) {
+ label = 23;
+ break;
+ } else {
+ $smode_1 = $smode_0199;
+ $si_1 = $si_0198;
+ $sl_1 = $sl_0197;
+ label = 24;
+ break;
+ }
+ case 23:
+ $69 = HEAP32[$hn >> 2] | 0;
+ $call156 = _straight_len($69) | 0;
+ $70 = HEAP8[$has_labels] | 0;
+ $and159 = $70 & 1;
+ $tobool160 = $and159 << 24 >> 24 != 0;
+ $cond161 = $tobool160 ? 5 : 3;
+ $cmp162 = ($call156 | 0) < ($cond161 | 0);
+ $sub165 = $call156 - 2 | 0;
+ $call156_sub165 = $cmp162 ? $call156 : $sub165;
+ $si_0_ = $cmp162 ? $si_0198 : 1;
+ $smode_0_ = $cmp162 ? $smode_0199 : 1;
+ $smode_1 = $smode_0_;
+ $si_1 = $si_0_;
+ $sl_1 = $call156_sub165;
+ label = 24;
+ break;
+ case 24:
+ $tobool167 = ($smode_1 | 0) == 0;
+ $cmp168 = ($si_1 | 0) > 0;
+ $or_cond = $tobool167 | $cmp168;
+ if ($or_cond) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $dec = $si_1 - 1 | 0;
+ $inc171 = $boxn_0196 + 2 | 0;
+ $arrayidx172 = 53424 + ($inc149225 << 5) | 0;
+ $71 = HEAP32[$hn >> 2] | 0;
+ $list = $71 + 184 | 0;
+ $72 = HEAP32[$list >> 2] | 0;
+ $73 = HEAP32[$72 >> 2] | 0;
+ _maximal_bbox($tmp175, $sp, $71, $e_1200, $73);
+ $74 = $arrayidx172;
+ HEAP32[$74 >> 2] = HEAP32[$60 >> 2] | 0;
+ HEAP32[$74 + 4 >> 2] = HEAP32[$60 + 4 >> 2] | 0;
+ HEAP32[$74 + 8 >> 2] = HEAP32[$60 + 8 >> 2] | 0;
+ HEAP32[$74 + 12 >> 2] = HEAP32[$60 + 12 >> 2] | 0;
+ HEAP32[$74 + 16 >> 2] = HEAP32[$60 + 16 >> 2] | 0;
+ HEAP32[$74 + 20 >> 2] = HEAP32[$60 + 20 >> 2] | 0;
+ HEAP32[$74 + 24 >> 2] = HEAP32[$60 + 24 >> 2] | 0;
+ HEAP32[$74 + 28 >> 2] = HEAP32[$60 + 28 >> 2] | 0;
+ $75 = HEAP32[$hn >> 2] | 0;
+ $list178 = $75 + 184 | 0;
+ $76 = HEAP32[$list178 >> 2] | 0;
+ $77 = HEAP32[$76 >> 2] | 0;
+ $tail180 = $77 + 16 | 0;
+ $78 = HEAP32[$tail180 >> 2] | 0;
+ $head181 = $77 + 12 | 0;
+ $79 = HEAP32[$head181 >> 2] | 0;
+ HEAP32[$hn >> 2] = $79;
+ $node_type = $79 + 162 | 0;
+ $80 = HEAP8[$node_type] | 0;
+ $cmp144 = $80 << 24 >> 24 == 1;
+ if ($cmp144) {
+ $boxn_0196 = $inc171;
+ $sl_0197 = $sl_1;
+ $si_0198 = $dec;
+ $smode_0199 = $smode_1;
+ $e_1200 = $77;
+ $tn_0201 = $78;
+ $65 = $79;
+ label = 21;
+ break;
+ } else {
+ $boxn_0_lcssa = $inc171;
+ $e_1_lcssa = $77;
+ $tn_0_lcssa = $78;
+ $segfirst_0_ph208 = $e_1_ph220;
+ label = 46;
+ break;
+ }
+ case 26:
+ $81 = HEAP32[$hn >> 2] | 0;
+ $list186 = $81 + 184 | 0;
+ $82 = HEAP32[$list186 >> 2] | 0;
+ $83 = HEAP32[$82 >> 2] | 0;
+ _maximal_bbox($tmp188, $sp, $81, $e_1200, $83);
+ HEAP32[$61 >> 2] = HEAP32[$62 >> 2] | 0;
+ HEAP32[$61 + 4 >> 2] = HEAP32[$62 + 4 >> 2] | 0;
+ HEAP32[$61 + 8 >> 2] = HEAP32[$62 + 8 >> 2] | 0;
+ HEAP32[$61 + 12 >> 2] = HEAP32[$62 + 12 >> 2] | 0;
+ HEAP32[$61 + 16 >> 2] = HEAP32[$62 + 16 >> 2] | 0;
+ HEAP32[$61 + 20 >> 2] = HEAP32[$62 + 20 >> 2] | 0;
+ HEAP32[$61 + 24 >> 2] = HEAP32[$62 + 24 >> 2] | 0;
+ HEAP32[$61 + 28 >> 2] = HEAP32[$62 + 28 >> 2] | 0;
+ $head189 = $e_1200 + 12 | 0;
+ $84 = HEAP32[$head189 >> 2] | 0;
+ $call190 = _spline_merge($84) | 0;
+ $85 = $e_1200;
+ _endpath($P, $85, 1, $hend, $call190);
+ $86 = HEAP32[$boxn191 >> 2] | 0;
+ $sub192 = $86 - 1 | 0;
+ $arrayidx194 = $hend + 56 + ($sub192 << 5) | 0;
+ $87 = HEAP32[$hn >> 2] | 0;
+ $y197 = $87 + 40 | 0;
+ $88 = +HEAPF64[$y197 >> 3];
+ $rank199 = $87 + 236 | 0;
+ $89 = HEAP32[$rank199 >> 2] | 0;
+ $graph200 = $87 + 20 | 0;
+ $90 = HEAP32[$graph200 >> 2] | 0;
+ $rank202 = $90 + 224 | 0;
+ $91 = HEAP32[$rank202 >> 2] | 0;
+ $ht2 = $91 + ($89 * 44 & -1) + 20 | 0;
+ $92 = HEAP32[$ht2 >> 2] | 0;
+ $conv204 = +($92 | 0);
+ $add = $88 + $conv204;
+ $conv205 = ~~$add;
+ _makeregularend($b, $arrayidx194, 4, $conv205);
+ $93 = +HEAPF64[$x124 >> 3];
+ $94 = +HEAPF64[$x126 >> 3];
+ $cmp211 = $93 < $94;
+ if ($cmp211) {
+ label = 27;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 27:
+ $95 = +HEAPF64[$y110 >> 3];
+ $96 = +HEAPF64[$y103 >> 3];
+ $cmp218 = $95 < $96;
+ if ($cmp218) {
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ $97 = HEAP32[$boxn191 >> 2] | 0;
+ $inc222 = $97 + 1 | 0;
+ HEAP32[$boxn191 >> 2] = $inc222;
+ $arrayidx224 = $hend + 56 + ($97 << 5) | 0;
+ $98 = $arrayidx224;
+ HEAP32[$98 >> 2] = HEAP32[$39 >> 2] | 0;
+ HEAP32[$98 + 4 >> 2] = HEAP32[$39 + 4 >> 2] | 0;
+ HEAP32[$98 + 8 >> 2] = HEAP32[$39 + 8 >> 2] | 0;
+ HEAP32[$98 + 12 >> 2] = HEAP32[$39 + 12 >> 2] | 0;
+ HEAP32[$98 + 16 >> 2] = HEAP32[$39 + 16 >> 2] | 0;
+ HEAP32[$98 + 20 >> 2] = HEAP32[$39 + 20 >> 2] | 0;
+ HEAP32[$98 + 24 >> 2] = HEAP32[$39 + 24 >> 2] | 0;
+ HEAP32[$98 + 28 >> 2] = HEAP32[$39 + 28 >> 2] | 0;
+ label = 29;
+ break;
+ case 29:
+ HEAPF64[$theta >> 3] = 1.5707963267948966;
+ HEAP8[$constrained] = 1;
+ _completeregularpath($P, $e_1_ph220, $e_1200, $tend, $hend, $inc149225);
+ if ($cmp94) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $call229 = _routesplines($P, $pn) | 0;
+ $ps_0_ph = $call229;
+ label = 34;
+ break;
+ case 31:
+ $call231 = _routepolylines($P, $pn) | 0;
+ if ($cmp89) {
+ label = 32;
+ break;
+ } else {
+ $ps_0_ph = $call231;
+ label = 34;
+ break;
+ }
+ case 32:
+ $99 = HEAP32[$pn >> 2] | 0;
+ $cmp235 = ($99 | 0) > 4;
+ if ($cmp235) {
+ label = 33;
+ break;
+ } else {
+ $ps_0 = $call231;
+ $106 = $99;
+ label = 35;
+ break;
+ }
+ case 33:
+ $arrayidx238 = $call231 + 16 | 0;
+ $100 = $arrayidx238;
+ $101 = $call231;
+ HEAP32[$100 >> 2] = HEAP32[$101 >> 2] | 0;
+ HEAP32[$100 + 4 >> 2] = HEAP32[$101 + 4 >> 2] | 0;
+ HEAP32[$100 + 8 >> 2] = HEAP32[$101 + 8 >> 2] | 0;
+ HEAP32[$100 + 12 >> 2] = HEAP32[$101 + 12 >> 2] | 0;
+ $arrayidx240 = $call231 + 48 | 0;
+ $arrayidx241 = $call231 + 32 | 0;
+ $102 = HEAP32[$pn >> 2] | 0;
+ $sub242 = $102 - 1 | 0;
+ $arrayidx243 = $call231 + ($sub242 << 4) | 0;
+ $103 = $arrayidx241;
+ $104 = $arrayidx243;
+ HEAP32[$103 >> 2] = HEAP32[$104 >> 2] | 0;
+ HEAP32[$103 + 4 >> 2] = HEAP32[$104 + 4 >> 2] | 0;
+ HEAP32[$103 + 8 >> 2] = HEAP32[$104 + 8 >> 2] | 0;
+ HEAP32[$103 + 12 >> 2] = HEAP32[$104 + 12 >> 2] | 0;
+ $105 = $arrayidx240;
+ _memmove($105 | 0, $104 | 0, 16);
+ HEAP32[$pn >> 2] = 4;
+ $107 = 4;
+ $ps_0165 = $call231;
+ label = 36;
+ break;
+ case 34:
+ $_pr = HEAP32[$pn >> 2] | 0;
+ $ps_0 = $ps_0_ph;
+ $106 = $_pr;
+ label = 35;
+ break;
+ case 35:
+ $cmp246 = ($106 | 0) == 0;
+ if ($cmp246) {
+ label = 85;
+ break;
+ } else {
+ $107 = $106;
+ $ps_0165 = $ps_0;
+ label = 36;
+ break;
+ }
+ case 36:
+ $108 = HEAP32[$pointn >> 2] | 0;
+ $add250 = $108 + $107 | 0;
+ $109 = HEAP32[2858] | 0;
+ $cmp251 = ($add250 | 0) > ($109 | 0);
+ if ($cmp251) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ $mul = $add250 << 1;
+ HEAP32[2858] = $mul;
+ $110 = HEAP32[2854] | 0;
+ $111 = $110;
+ $mul255 = $add250 << 5;
+ $call256 = _grealloc($111, $mul255) | 0;
+ $112 = $call256;
+ HEAP32[2854] = $112;
+ label = 38;
+ break;
+ case 38:
+ $113 = HEAP32[$pn >> 2] | 0;
+ $cmp258186 = ($113 | 0) > 0;
+ if ($cmp258186) {
+ label = 39;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 39:
+ $114 = HEAP32[2854] | 0;
+ $115 = HEAP32[$pn >> 2] | 0;
+ $pointn_promoted188 = HEAP32[$pointn >> 2] | 0;
+ $116 = ($115 | 0) > 1;
+ $smax236 = $116 ? $115 : 1;
+ $i_0187 = 0;
+ $inc260189 = $pointn_promoted188;
+ label = 40;
+ break;
+ case 40:
+ $inc260 = $inc260189 + 1 | 0;
+ $arrayidx261 = $114 + ($inc260189 << 4) | 0;
+ $arrayidx262 = $ps_0165 + ($i_0187 << 4) | 0;
+ $117 = $arrayidx261;
+ $118 = $arrayidx262;
+ HEAP32[$117 >> 2] = HEAP32[$118 >> 2] | 0;
+ HEAP32[$117 + 4 >> 2] = HEAP32[$118 + 4 >> 2] | 0;
+ HEAP32[$117 + 8 >> 2] = HEAP32[$118 + 8 >> 2] | 0;
+ HEAP32[$117 + 12 >> 2] = HEAP32[$118 + 12 >> 2] | 0;
+ $inc263 = $i_0187 + 1 | 0;
+ $cmp258 = ($inc263 | 0) < ($115 | 0);
+ if ($cmp258) {
+ $i_0187 = $inc263;
+ $inc260189 = $inc260;
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $119 = $pointn_promoted188 + $smax236 | 0;
+ HEAP32[$pointn >> 2] = $119;
+ label = 42;
+ break;
+ case 42:
+ $120 = HEAP32[$hn >> 2] | 0;
+ $list266 = $120 + 184 | 0;
+ $121 = HEAP32[$list266 >> 2] | 0;
+ $122 = HEAP32[$121 >> 2] | 0;
+ $123 = HEAP32[2854] | 0;
+ $call268 = _straight_path($122, $sl_1, $123, $pointn) | 0;
+ _recover_slack($e_1_ph220, $P);
+ $tail269 = $call268 + 16 | 0;
+ $124 = HEAP32[$tail269 >> 2] | 0;
+ $head270 = $call268 + 12 | 0;
+ $125 = HEAP32[$head270 >> 2] | 0;
+ HEAP32[$hn >> 2] = $125;
+ $list273 = $124 + 176 | 0;
+ $126 = HEAP32[$list273 >> 2] | 0;
+ $127 = HEAP32[$126 >> 2] | 0;
+ _maximal_bbox($tmp275, $sp, $124, $127, $call268);
+ HEAP32[$37 >> 2] = HEAP32[$63 >> 2] | 0;
+ HEAP32[$37 + 4 >> 2] = HEAP32[$63 + 4 >> 2] | 0;
+ HEAP32[$37 + 8 >> 2] = HEAP32[$63 + 8 >> 2] | 0;
+ HEAP32[$37 + 12 >> 2] = HEAP32[$63 + 12 >> 2] | 0;
+ HEAP32[$37 + 16 >> 2] = HEAP32[$63 + 16 >> 2] | 0;
+ HEAP32[$37 + 20 >> 2] = HEAP32[$63 + 20 >> 2] | 0;
+ HEAP32[$37 + 24 >> 2] = HEAP32[$63 + 24 >> 2] | 0;
+ HEAP32[$37 + 28 >> 2] = HEAP32[$63 + 28 >> 2] | 0;
+ $call276 = _spline_merge($124) | 0;
+ $128 = $call268;
+ _beginpath($P, $128, 1, $tend, $call276);
+ $129 = HEAP32[$boxn98 >> 2] | 0;
+ $sub278 = $129 - 1 | 0;
+ $arrayidx280 = $tend + 56 + ($sub278 << 5) | 0;
+ $y283 = $124 + 40 | 0;
+ $130 = +HEAPF64[$y283 >> 3];
+ $rank285 = $124 + 236 | 0;
+ $131 = HEAP32[$rank285 >> 2] | 0;
+ $graph286 = $124 + 20 | 0;
+ $132 = HEAP32[$graph286 >> 2] | 0;
+ $rank288 = $132 + 224 | 0;
+ $133 = HEAP32[$rank288 >> 2] | 0;
+ $ht1290 = $133 + ($131 * 44 & -1) + 16 | 0;
+ $134 = HEAP32[$ht1290 >> 2] | 0;
+ $conv291 = +($134 | 0);
+ $sub292 = $130 - $conv291;
+ $conv293 = ~~$sub292;
+ _makeregularend($b, $arrayidx280, 1, $conv293);
+ $135 = +HEAPF64[$x124 >> 3];
+ $136 = +HEAPF64[$x126 >> 3];
+ $cmp299 = $135 < $136;
+ if ($cmp299) {
+ label = 43;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 43:
+ $137 = +HEAPF64[$y110 >> 3];
+ $138 = +HEAPF64[$y103 >> 3];
+ $cmp306 = $137 < $138;
+ if ($cmp306) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 44:
+ $139 = HEAP32[$boxn98 >> 2] | 0;
+ $inc310 = $139 + 1 | 0;
+ HEAP32[$boxn98 >> 2] = $inc310;
+ $arrayidx312 = $tend + 56 + ($139 << 5) | 0;
+ $140 = $arrayidx312;
+ HEAP32[$140 >> 2] = HEAP32[$39 >> 2] | 0;
+ HEAP32[$140 + 4 >> 2] = HEAP32[$39 + 4 >> 2] | 0;
+ HEAP32[$140 + 8 >> 2] = HEAP32[$39 + 8 >> 2] | 0;
+ HEAP32[$140 + 12 >> 2] = HEAP32[$39 + 12 >> 2] | 0;
+ HEAP32[$140 + 16 >> 2] = HEAP32[$39 + 16 >> 2] | 0;
+ HEAP32[$140 + 20 >> 2] = HEAP32[$39 + 20 >> 2] | 0;
+ HEAP32[$140 + 24 >> 2] = HEAP32[$39 + 24 >> 2] | 0;
+ HEAP32[$140 + 28 >> 2] = HEAP32[$39 + 28 >> 2] | 0;
+ label = 45;
+ break;
+ case 45:
+ HEAPF64[$theta314 >> 3] = -1.5707963267948966;
+ HEAP8[$constrained316] = 1;
+ $141 = HEAP32[$hn >> 2] | 0;
+ $node_type194 = $141 + 162 | 0;
+ $142 = HEAP8[$node_type194] | 0;
+ $cmp144195 = $142 << 24 >> 24 == 1;
+ if ($cmp144195) {
+ $sl_0_ph217 = $sl_1;
+ $si_0_ph218 = $si_1;
+ $e_1_ph220 = $call268;
+ $tn_0_ph221 = $124;
+ $64 = $141;
+ label = 20;
+ break;
+ } else {
+ $boxn_0_lcssa = 0;
+ $e_1_lcssa = $call268;
+ $tn_0_lcssa = $124;
+ $segfirst_0_ph208 = $call268;
+ label = 46;
+ break;
+ }
+ case 46:
+ $inc318 = $boxn_0_lcssa + 1 | 0;
+ $arrayidx319 = 53424 + ($boxn_0_lcssa << 5) | 0;
+ $rank321 = $tn_0_lcssa + 236 | 0;
+ $143 = HEAP32[$rank321 >> 2] | 0;
+ _rank_box($tmp322, $sp, $5, $143);
+ $144 = $arrayidx319;
+ $145 = $tmp322;
+ HEAP32[$144 >> 2] = HEAP32[$145 >> 2] | 0;
+ HEAP32[$144 + 4 >> 2] = HEAP32[$145 + 4 >> 2] | 0;
+ HEAP32[$144 + 8 >> 2] = HEAP32[$145 + 8 >> 2] | 0;
+ HEAP32[$144 + 12 >> 2] = HEAP32[$145 + 12 >> 2] | 0;
+ HEAP32[$144 + 16 >> 2] = HEAP32[$145 + 16 >> 2] | 0;
+ HEAP32[$144 + 20 >> 2] = HEAP32[$145 + 20 >> 2] | 0;
+ HEAP32[$144 + 24 >> 2] = HEAP32[$145 + 24 >> 2] | 0;
+ HEAP32[$144 + 28 >> 2] = HEAP32[$145 + 28 >> 2] | 0;
+ $146 = HEAP32[$hn >> 2] | 0;
+ _maximal_bbox($tmp324, $sp, $146, $e_1_lcssa, 0);
+ $147 = $hend;
+ $148 = $tmp324;
+ HEAP32[$147 >> 2] = HEAP32[$148 >> 2] | 0;
+ HEAP32[$147 + 4 >> 2] = HEAP32[$148 + 4 >> 2] | 0;
+ HEAP32[$147 + 8 >> 2] = HEAP32[$148 + 8 >> 2] | 0;
+ HEAP32[$147 + 12 >> 2] = HEAP32[$148 + 12 >> 2] | 0;
+ HEAP32[$147 + 16 >> 2] = HEAP32[$148 + 16 >> 2] | 0;
+ HEAP32[$147 + 20 >> 2] = HEAP32[$148 + 20 >> 2] | 0;
+ HEAP32[$147 + 24 >> 2] = HEAP32[$148 + 24 >> 2] | 0;
+ HEAP32[$147 + 28 >> 2] = HEAP32[$148 + 28 >> 2] | 0;
+ HEAP32[$39 >> 2] = HEAP32[$148 >> 2] | 0;
+ HEAP32[$39 + 4 >> 2] = HEAP32[$148 + 4 >> 2] | 0;
+ HEAP32[$39 + 8 >> 2] = HEAP32[$148 + 8 >> 2] | 0;
+ HEAP32[$39 + 12 >> 2] = HEAP32[$148 + 12 >> 2] | 0;
+ HEAP32[$39 + 16 >> 2] = HEAP32[$148 + 16 >> 2] | 0;
+ HEAP32[$39 + 20 >> 2] = HEAP32[$148 + 20 >> 2] | 0;
+ HEAP32[$39 + 24 >> 2] = HEAP32[$148 + 24 >> 2] | 0;
+ HEAP32[$39 + 28 >> 2] = HEAP32[$148 + 28 >> 2] | 0;
+ $tobool325 = ($hackflag_0 | 0) != 0;
+ $cond329 = $tobool325 ? $fwdedgeb : $e_1_lcssa;
+ $head330 = $e_1_lcssa + 12 | 0;
+ $149 = HEAP32[$head330 >> 2] | 0;
+ $call331 = _spline_merge($149) | 0;
+ $150 = $cond329;
+ _endpath($P, $150, 1, $hend, $call331);
+ $boxn332 = $hend + 52 | 0;
+ $151 = HEAP32[$boxn332 >> 2] | 0;
+ $sub333 = $151 - 1 | 0;
+ $y337 = $hend + 56 + ($sub333 << 5) + 24 | 0;
+ $152 = +HEAPF64[$y337 >> 3];
+ HEAPF64[$y103 >> 3] = $152;
+ $153 = HEAP32[$boxn332 >> 2] | 0;
+ $sub341 = $153 - 1 | 0;
+ $y345 = $hend + 56 + ($sub341 << 5) + 8 | 0;
+ $154 = +HEAPF64[$y345 >> 3];
+ HEAPF64[$y110 >> 3] = $154;
+ $155 = HEAP32[$hn >> 2] | 0;
+ $y350 = $155 + 40 | 0;
+ $156 = +HEAPF64[$y350 >> 3];
+ $rank352 = $155 + 236 | 0;
+ $157 = HEAP32[$rank352 >> 2] | 0;
+ $graph353 = $155 + 20 | 0;
+ $158 = HEAP32[$graph353 >> 2] | 0;
+ $rank355 = $158 + 224 | 0;
+ $159 = HEAP32[$rank355 >> 2] | 0;
+ $ht2357 = $159 + ($157 * 44 & -1) + 20 | 0;
+ $160 = HEAP32[$ht2357 >> 2] | 0;
+ $conv358 = +($160 | 0);
+ $add359 = $156 + $conv358;
+ $conv360 = ~~$add359;
+ _makeregularend($tmp361, $b, 4, $conv360);
+ $161 = $tmp361;
+ HEAP32[$39 >> 2] = HEAP32[$161 >> 2] | 0;
+ HEAP32[$39 + 4 >> 2] = HEAP32[$161 + 4 >> 2] | 0;
+ HEAP32[$39 + 8 >> 2] = HEAP32[$161 + 8 >> 2] | 0;
+ HEAP32[$39 + 12 >> 2] = HEAP32[$161 + 12 >> 2] | 0;
+ HEAP32[$39 + 16 >> 2] = HEAP32[$161 + 16 >> 2] | 0;
+ HEAP32[$39 + 20 >> 2] = HEAP32[$161 + 20 >> 2] | 0;
+ HEAP32[$39 + 24 >> 2] = HEAP32[$161 + 24 >> 2] | 0;
+ HEAP32[$39 + 28 >> 2] = HEAP32[$161 + 28 >> 2] | 0;
+ $162 = +HEAPF64[$x124 >> 3];
+ $163 = +HEAPF64[$x126 >> 3];
+ $cmp366 = $162 < $163;
+ if ($cmp366) {
+ label = 47;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 47:
+ $164 = +HEAPF64[$y110 >> 3];
+ $165 = +HEAPF64[$y103 >> 3];
+ $cmp373 = $164 < $165;
+ if ($cmp373) {
+ label = 48;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 48:
+ $166 = HEAP32[$boxn332 >> 2] | 0;
+ $inc377 = $166 + 1 | 0;
+ HEAP32[$boxn332 >> 2] = $inc377;
+ $arrayidx379 = $hend + 56 + ($166 << 5) | 0;
+ $167 = $arrayidx379;
+ HEAP32[$167 >> 2] = HEAP32[$39 >> 2] | 0;
+ HEAP32[$167 + 4 >> 2] = HEAP32[$39 + 4 >> 2] | 0;
+ HEAP32[$167 + 8 >> 2] = HEAP32[$39 + 8 >> 2] | 0;
+ HEAP32[$167 + 12 >> 2] = HEAP32[$39 + 12 >> 2] | 0;
+ HEAP32[$167 + 16 >> 2] = HEAP32[$39 + 16 >> 2] | 0;
+ HEAP32[$167 + 20 >> 2] = HEAP32[$39 + 20 >> 2] | 0;
+ HEAP32[$167 + 24 >> 2] = HEAP32[$39 + 24 >> 2] | 0;
+ HEAP32[$167 + 28 >> 2] = HEAP32[$39 + 28 >> 2] | 0;
+ label = 49;
+ break;
+ case 49:
+ _completeregularpath($P, $segfirst_0_ph208, $e_1_lcssa, $tend, $hend, $inc318);
+ if ($cmp94) {
+ label = 50;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 50:
+ $call383 = _routesplines($P, $pn) | 0;
+ $ps_1 = $call383;
+ label = 52;
+ break;
+ case 51:
+ $call385 = _routepolylines($P, $pn) | 0;
+ $ps_1 = $call385;
+ label = 52;
+ break;
+ case 52:
+ $168 = HEAP32[$pn >> 2] | 0;
+ $cmp390 = ($168 | 0) > 4;
+ $or_cond168 = $cmp89 & $cmp390;
+ if ($or_cond168) {
+ label = 53;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 53:
+ $arrayidx393 = $ps_1 + 16 | 0;
+ $169 = $arrayidx393;
+ $170 = $ps_1;
+ HEAP32[$169 >> 2] = HEAP32[$170 >> 2] | 0;
+ HEAP32[$169 + 4 >> 2] = HEAP32[$170 + 4 >> 2] | 0;
+ HEAP32[$169 + 8 >> 2] = HEAP32[$170 + 8 >> 2] | 0;
+ HEAP32[$169 + 12 >> 2] = HEAP32[$170 + 12 >> 2] | 0;
+ $arrayidx395 = $ps_1 + 48 | 0;
+ $arrayidx396 = $ps_1 + 32 | 0;
+ $171 = HEAP32[$pn >> 2] | 0;
+ $sub397 = $171 - 1 | 0;
+ $arrayidx398 = $ps_1 + ($sub397 << 4) | 0;
+ $172 = $arrayidx396;
+ $173 = $arrayidx398;
+ HEAP32[$172 >> 2] = HEAP32[$173 >> 2] | 0;
+ HEAP32[$172 + 4 >> 2] = HEAP32[$173 + 4 >> 2] | 0;
+ HEAP32[$172 + 8 >> 2] = HEAP32[$173 + 8 >> 2] | 0;
+ HEAP32[$172 + 12 >> 2] = HEAP32[$173 + 12 >> 2] | 0;
+ $174 = $arrayidx395;
+ _memmove($174 | 0, $173 | 0, 16);
+ HEAP32[$pn >> 2] = 4;
+ $175 = 4;
+ label = 55;
+ break;
+ case 54:
+ $cmp400 = ($168 | 0) == 0;
+ if ($cmp400) {
+ label = 85;
+ break;
+ } else {
+ $175 = $168;
+ label = 55;
+ break;
+ }
+ case 55:
+ $176 = HEAP32[$pointn >> 2] | 0;
+ $add404 = $176 + $175 | 0;
+ $177 = HEAP32[2858] | 0;
+ $cmp405 = ($add404 | 0) > ($177 | 0);
+ if ($cmp405) {
+ label = 56;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 56:
+ $mul409 = $add404 << 1;
+ HEAP32[2858] = $mul409;
+ $178 = HEAP32[2854] | 0;
+ $179 = $178;
+ $mul410 = $add404 << 5;
+ $call411 = _grealloc($179, $mul410) | 0;
+ $180 = $call411;
+ HEAP32[2854] = $180;
+ label = 57;
+ break;
+ case 57:
+ $181 = HEAP32[$pn >> 2] | 0;
+ $cmp414183 = ($181 | 0) > 0;
+ if ($cmp414183) {
+ label = 58;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 58:
+ $182 = HEAP32[2854] | 0;
+ $183 = HEAP32[$pn >> 2] | 0;
+ $pointn_promoted = HEAP32[$pointn >> 2] | 0;
+ $184 = ($183 | 0) > 1;
+ $smax = $184 ? $183 : 1;
+ $i_1184 = 0;
+ $inc417185 = $pointn_promoted;
+ label = 59;
+ break;
+ case 59:
+ $inc417 = $inc417185 + 1 | 0;
+ $arrayidx418 = $182 + ($inc417185 << 4) | 0;
+ $arrayidx419 = $ps_1 + ($i_1184 << 4) | 0;
+ $185 = $arrayidx418;
+ $186 = $arrayidx419;
+ HEAP32[$185 >> 2] = HEAP32[$186 >> 2] | 0;
+ HEAP32[$185 + 4 >> 2] = HEAP32[$186 + 4 >> 2] | 0;
+ HEAP32[$185 + 8 >> 2] = HEAP32[$186 + 8 >> 2] | 0;
+ HEAP32[$185 + 12 >> 2] = HEAP32[$186 + 12 >> 2] | 0;
+ $inc421 = $i_1184 + 1 | 0;
+ $cmp414 = ($inc421 | 0) < ($183 | 0);
+ if ($cmp414) {
+ $i_1184 = $inc421;
+ $inc417185 = $inc417;
+ label = 59;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $187 = $pointn_promoted + $smax | 0;
+ HEAP32[$pointn >> 2] = $187;
+ label = 61;
+ break;
+ case 61:
+ _recover_slack($segfirst_0_ph208, $P);
+ if ($tobool325) {
+ label = 62;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 62:
+ $head425 = $fwdedgeb + 12 | 0;
+ $188 = HEAP32[$head425 >> 2] | 0;
+ $cond429 = $188;
+ label = 64;
+ break;
+ case 63:
+ $189 = HEAP32[$head330 >> 2] | 0;
+ $cond429 = $189;
+ label = 64;
+ break;
+ case 64:
+ HEAP32[$hn >> 2] = $cond429;
+ label = 65;
+ break;
+ case 65:
+ $cmp431 = ($cnt | 0) == 1;
+ if ($cmp431) {
+ label = 66;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 66:
+ $190 = HEAP32[$hn >> 2] | 0;
+ $191 = HEAP32[2854] | 0;
+ $192 = HEAP32[$pointn >> 2] | 0;
+ $193 = $e_0;
+ $194 = $190;
+ _clip_and_install($193, $194, $191, $192, 4216);
+ label = 85;
+ break;
+ case 67:
+ $Multisep = $sp + 12 | 0;
+ $195 = HEAP32[$pointn >> 2] | 0;
+ $sub438180 = $195 - 1 | 0;
+ $cmp439181 = ($sub438180 | 0) > 1;
+ if ($cmp439181) {
+ label = 68;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 68:
+ $sub435 = $cnt - 1 | 0;
+ $196 = HEAP32[$Multisep >> 2] | 0;
+ $mul436 = Math_imul($196, $sub435);
+ $div = ($mul436 | 0) / 2 & -1;
+ $conv442 = +($div | 0);
+ $197 = HEAP32[2854] | 0;
+ $198 = HEAP32[$pointn >> 2] | 0;
+ $sub438 = $198 - 1 | 0;
+ $i_2182 = 1;
+ label = 69;
+ break;
+ case 69:
+ $x444 = $197 + ($i_2182 << 4) | 0;
+ $199 = +HEAPF64[$x444 >> 3];
+ $sub445 = $199 - $conv442;
+ HEAPF64[$x444 >> 3] = $sub445;
+ $inc447 = $i_2182 + 1 | 0;
+ $cmp439 = ($inc447 | 0) < ($sub438 | 0);
+ if ($cmp439) {
+ $i_2182 = $inc447;
+ label = 69;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $200 = HEAP32[2858] | 0;
+ $201 = HEAP32[2856] | 0;
+ $cmp449 = ($200 | 0) > ($201 | 0);
+ if ($cmp449) {
+ label = 71;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 71:
+ HEAP32[2856] = $200;
+ $202 = HEAP32[2852] | 0;
+ $203 = $202;
+ $mul452 = $200 << 4;
+ $call453 = _grealloc($203, $mul452) | 0;
+ $204 = $call453;
+ HEAP32[2852] = $204;
+ label = 72;
+ break;
+ case 72:
+ $205 = HEAP32[$pointn >> 2] | 0;
+ $cmp456177 = ($205 | 0) > 0;
+ if ($cmp456177) {
+ label = 73;
+ break;
+ } else {
+ $_lcssa176 = $205;
+ label = 75;
+ break;
+ }
+ case 73:
+ $206 = HEAP32[2852] | 0;
+ $207 = HEAP32[2854] | 0;
+ $208 = HEAP32[$pointn >> 2] | 0;
+ $i_3178 = 0;
+ label = 74;
+ break;
+ case 74:
+ $arrayidx459 = $206 + ($i_3178 << 4) | 0;
+ $arrayidx460 = $207 + ($i_3178 << 4) | 0;
+ $209 = $arrayidx459;
+ $210 = $arrayidx460;
+ HEAP32[$209 >> 2] = HEAP32[$210 >> 2] | 0;
+ HEAP32[$209 + 4 >> 2] = HEAP32[$210 + 4 >> 2] | 0;
+ HEAP32[$209 + 8 >> 2] = HEAP32[$210 + 8 >> 2] | 0;
+ HEAP32[$209 + 12 >> 2] = HEAP32[$210 + 12 >> 2] | 0;
+ $inc462 = $i_3178 + 1 | 0;
+ $cmp456 = ($inc462 | 0) < ($208 | 0);
+ if ($cmp456) {
+ $i_3178 = $inc462;
+ label = 74;
+ break;
+ } else {
+ $_lcssa176 = $208;
+ label = 75;
+ break;
+ }
+ case 75:
+ $211 = HEAP32[$hn >> 2] | 0;
+ $212 = HEAP32[2852] | 0;
+ $213 = $e_0;
+ $214 = $211;
+ _clip_and_install($213, $214, $212, $_lcssa176, 4216);
+ $cmp465174 = ($cnt | 0) > 1;
+ if ($cmp465174) {
+ label = 76;
+ break;
+ } else {
+ label = 85;
+ break;
+ }
+ case 76:
+ $215 = HEAP32[$pointn >> 2] | 0;
+ $sub495169 = $215 - 1 | 0;
+ $cmp496170 = ($sub495169 | 0) > 1;
+ $cmp508172 = ($215 | 0) > 0;
+ $sub495 = $215 - 1 | 0;
+ $216 = $fwdedge | 0;
+ $tail478 = $fwdedge + 16 | 0;
+ $head480 = $fwdedge + 12 | 0;
+ $tail_port482 = $fwdedge + 32 | 0;
+ $217 = $tail_port482;
+ $head_port486 = $fwdedge + 72 | 0;
+ $218 = $head_port486;
+ $edge_type490 = $fwdedge + 128 | 0;
+ $to_orig492 = $fwdedge + 132 | 0;
+ $j_0175 = 1;
+ label = 77;
+ break;
+ case 77:
+ $add468 = $j_0175 + $ind | 0;
+ $arrayidx469 = $edges + ($add468 << 2) | 0;
+ $219 = HEAP32[$arrayidx469 >> 2] | 0;
+ $tree_index471 = $219 + 180 | 0;
+ $220 = HEAP32[$tree_index471 >> 2] | 0;
+ $and472 = $220 & 32;
+ $tobool473 = ($and472 | 0) == 0;
+ if ($tobool473) {
+ $e_2 = $219;
+ label = 79;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $221 = $219 | 0;
+ _memcpy($216 | 0, $221 | 0, 192);
+ $head477 = $219 + 12 | 0;
+ $222 = HEAP32[$head477 >> 2] | 0;
+ HEAP32[$tail478 >> 2] = $222;
+ $tail479 = $219 + 16 | 0;
+ $223 = HEAP32[$tail479 >> 2] | 0;
+ HEAP32[$head480 >> 2] = $223;
+ $head_port484 = $219 + 72 | 0;
+ $224 = $head_port484;
+ HEAP32[$217 >> 2] = HEAP32[$224 >> 2] | 0;
+ HEAP32[$217 + 4 >> 2] = HEAP32[$224 + 4 >> 2] | 0;
+ HEAP32[$217 + 8 >> 2] = HEAP32[$224 + 8 >> 2] | 0;
+ HEAP32[$217 + 12 >> 2] = HEAP32[$224 + 12 >> 2] | 0;
+ HEAP32[$217 + 16 >> 2] = HEAP32[$224 + 16 >> 2] | 0;
+ HEAP32[$217 + 20 >> 2] = HEAP32[$224 + 20 >> 2] | 0;
+ HEAP32[$217 + 24 >> 2] = HEAP32[$224 + 24 >> 2] | 0;
+ HEAP32[$217 + 28 >> 2] = HEAP32[$224 + 28 >> 2] | 0;
+ HEAP32[$217 + 32 >> 2] = HEAP32[$224 + 32 >> 2] | 0;
+ HEAP32[$217 + 36 >> 2] = HEAP32[$224 + 36 >> 2] | 0;
+ $tail_port488 = $219 + 32 | 0;
+ $225 = $tail_port488;
+ HEAP32[$218 >> 2] = HEAP32[$225 >> 2] | 0;
+ HEAP32[$218 + 4 >> 2] = HEAP32[$225 + 4 >> 2] | 0;
+ HEAP32[$218 + 8 >> 2] = HEAP32[$225 + 8 >> 2] | 0;
+ HEAP32[$218 + 12 >> 2] = HEAP32[$225 + 12 >> 2] | 0;
+ HEAP32[$218 + 16 >> 2] = HEAP32[$225 + 16 >> 2] | 0;
+ HEAP32[$218 + 20 >> 2] = HEAP32[$225 + 20 >> 2] | 0;
+ HEAP32[$218 + 24 >> 2] = HEAP32[$225 + 24 >> 2] | 0;
+ HEAP32[$218 + 28 >> 2] = HEAP32[$225 + 28 >> 2] | 0;
+ HEAP32[$218 + 32 >> 2] = HEAP32[$225 + 32 >> 2] | 0;
+ HEAP32[$218 + 36 >> 2] = HEAP32[$225 + 36 >> 2] | 0;
+ HEAP8[$edge_type490] = 1;
+ HEAP32[$to_orig492 >> 2] = $219;
+ $e_2 = $fwdedge;
+ label = 79;
+ break;
+ case 79:
+ if ($cmp496170) {
+ $i_4171 = 1;
+ label = 80;
+ break;
+ } else {
+ label = 81;
+ break;
+ }
+ case 80:
+ $226 = HEAP32[$Multisep >> 2] | 0;
+ $conv500 = +($226 | 0);
+ $227 = HEAP32[2854] | 0;
+ $x502 = $227 + ($i_4171 << 4) | 0;
+ $228 = +HEAPF64[$x502 >> 3];
+ $add503 = $conv500 + $228;
+ HEAPF64[$x502 >> 3] = $add503;
+ $inc505 = $i_4171 + 1 | 0;
+ $cmp496 = ($inc505 | 0) < ($sub495 | 0);
+ if ($cmp496) {
+ $i_4171 = $inc505;
+ label = 80;
+ break;
+ } else {
+ label = 81;
+ break;
+ }
+ case 81:
+ if ($cmp508172) {
+ label = 82;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 82:
+ $229 = HEAP32[2852] | 0;
+ $230 = HEAP32[2854] | 0;
+ $i_5173 = 0;
+ label = 83;
+ break;
+ case 83:
+ $arrayidx511 = $229 + ($i_5173 << 4) | 0;
+ $arrayidx512 = $230 + ($i_5173 << 4) | 0;
+ $231 = $arrayidx511;
+ $232 = $arrayidx512;
+ HEAP32[$231 >> 2] = HEAP32[$232 >> 2] | 0;
+ HEAP32[$231 + 4 >> 2] = HEAP32[$232 + 4 >> 2] | 0;
+ HEAP32[$231 + 8 >> 2] = HEAP32[$232 + 8 >> 2] | 0;
+ HEAP32[$231 + 12 >> 2] = HEAP32[$232 + 12 >> 2] | 0;
+ $inc514 = $i_5173 + 1 | 0;
+ $cmp508 = ($inc514 | 0) < ($215 | 0);
+ if ($cmp508) {
+ $i_5173 = $inc514;
+ label = 83;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 84:
+ $head516 = $e_2 + 12 | 0;
+ $233 = HEAP32[$head516 >> 2] | 0;
+ $234 = HEAP32[2852] | 0;
+ $235 = $e_2;
+ $236 = $233;
+ _clip_and_install($235, $236, $234, $215, 4216);
+ $inc518 = $j_0175 + 1 | 0;
+ $cmp465 = ($inc518 | 0) < ($cnt | 0);
+ if ($cmp465) {
+ $j_0175 = $inc518;
+ label = 77;
+ break;
+ } else {
+ label = 85;
+ break;
+ }
+ case 85:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _edge_normalize($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool12 = 0, $n_0_in13 = 0, $call1 = 0, $tobool310 = 0, $e_0_in11 = 0, $e_0 = 0, $1 = 0, $call5 = 0, $tobool6 = 0, $u = 0, $spl = 0, $2 = 0, $tobool7 = 0, $call10 = 0, $tobool3 = 0, $call12 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool12 = ($call | 0) == 0;
+ if ($tobool12) {
+ label = 9;
+ break;
+ } else {
+ $n_0_in13 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _agfstout($0, $n_0_in13) | 0;
+ $tobool310 = ($call1 | 0) == 0;
+ if ($tobool310) {
+ label = 8;
+ break;
+ } else {
+ $e_0_in11 = $call1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $e_0 = $e_0_in11;
+ $1 = HEAP32[1054] | 0;
+ $call5 = FUNCTION_TABLE_ii[$1 & 1023]($e_0) | 0;
+ $tobool6 = $call5 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $u = $e_0_in11 + 24 | 0;
+ $spl = $u;
+ $2 = HEAP32[$spl >> 2] | 0;
+ $tobool7 = ($2 | 0) == 0;
+ if ($tobool7) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _swap_spline($2);
+ label = 7;
+ break;
+ case 7:
+ $call10 = _agnxtout($0, $e_0_in11) | 0;
+ $tobool3 = ($call10 | 0) == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ $e_0_in11 = $call10;
+ label = 4;
+ break;
+ }
+ case 8:
+ $call12 = _agnxtnode($0, $n_0_in13) | 0;
+ $tobool = ($call12 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ $n_0_in13 = $call12;
+ label = 3;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _spline_merge($n) {
+ $n = $n | 0;
+ var $node_type = 0, $0 = 0, $cmp = 0, $size = 0, $1 = 0, $cmp3 = 0, $size6 = 0, $2 = 0, $cmp7 = 0, $phitmp = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $n + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $3 = 0;
+ label = 5;
+ break;
+ }
+ case 3:
+ $size = $n + 180 | 0;
+ $1 = HEAP32[$size >> 2] | 0;
+ $cmp3 = ($1 | 0) > 1;
+ if ($cmp3) {
+ $3 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $size6 = $n + 188 | 0;
+ $2 = HEAP32[$size6 >> 2] | 0;
+ $cmp7 = ($2 | 0) > 1;
+ $phitmp = $cmp7 & 1;
+ $3 = $phitmp;
+ label = 5;
+ break;
+ case 5:
+ return $3 | 0;
+ }
+ return 0;
+}
+function _rank_box($agg_result, $sp, $g, $r) {
+ $agg_result = $agg_result | 0;
+ $sp = $sp | 0;
+ $g = $g | 0;
+ $r = $r | 0;
+ var $Rank_box = 0, $0 = 0, $b_sroa_0_0__idx3 = 0, $b_sroa_0_0_copyload4 = 0.0, $b_sroa_1_8__idx8 = 0, $b_sroa_1_8_copyload9 = 0.0, $b_sroa_2_16__idx13 = 0, $b_sroa_2_16_copyload14 = 0.0, $b_sroa_3_24__idx18 = 0, $b_sroa_3_24_copyload19 = 0.0, $cmp = 0, $rank = 0, $1 = 0, $v = 0, $2 = 0, $3 = 0, $add = 0, $v7 = 0, $4 = 0, $5 = 0, $LeftBound = 0, $6 = 0, $conv = 0.0, $y = 0, $7 = 0.0, $ht2 = 0, $8 = 0, $conv16 = 0.0, $add17 = 0.0, $RightBound = 0, $9 = 0, $conv20 = 0.0, $y25 = 0, $10 = 0.0, $ht1 = 0, $11 = 0, $conv29 = 0.0, $sub = 0.0, $b_sroa_1_0 = 0.0, $b_sroa_0_0 = 0.0, $b_sroa_2_0 = 0.0, $b_sroa_3_0 = 0.0, $b_sroa_0_0__idx = 0, $b_sroa_1_8__idx5 = 0, $b_sroa_2_16__idx10 = 0, $b_sroa_3_24__idx15 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $Rank_box = $sp + 16 | 0;
+ $0 = HEAP32[$Rank_box >> 2] | 0;
+ $b_sroa_0_0__idx3 = $0 + ($r << 5) | 0;
+ $b_sroa_0_0_copyload4 = +HEAPF64[$b_sroa_0_0__idx3 >> 3];
+ $b_sroa_1_8__idx8 = $0 + ($r << 5) + 8 | 0;
+ $b_sroa_1_8_copyload9 = +HEAPF64[$b_sroa_1_8__idx8 >> 3];
+ $b_sroa_2_16__idx13 = $0 + ($r << 5) + 16 | 0;
+ $b_sroa_2_16_copyload14 = +HEAPF64[$b_sroa_2_16__idx13 >> 3];
+ $b_sroa_3_24__idx18 = $0 + ($r << 5) + 24 | 0;
+ $b_sroa_3_24_copyload19 = +HEAPF64[$b_sroa_3_24__idx18 >> 3];
+ $cmp = $b_sroa_0_0_copyload4 == $b_sroa_2_16_copyload14;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $b_sroa_3_0 = $b_sroa_3_24_copyload19;
+ $b_sroa_2_0 = $b_sroa_2_16_copyload14;
+ $b_sroa_0_0 = $b_sroa_0_0_copyload4;
+ $b_sroa_1_0 = $b_sroa_1_8_copyload9;
+ label = 4;
+ break;
+ }
+ case 3:
+ $rank = $g + 224 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $v = $1 + ($r * 44 & -1) + 4 | 0;
+ $2 = HEAP32[$v >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $add = $r + 1 | 0;
+ $v7 = $1 + ($add * 44 & -1) + 4 | 0;
+ $4 = HEAP32[$v7 >> 2] | 0;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $LeftBound = $sp | 0;
+ $6 = HEAP32[$LeftBound >> 2] | 0;
+ $conv = +($6 | 0);
+ $y = $5 + 40 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $ht2 = $1 + ($add * 44 & -1) + 20 | 0;
+ $8 = HEAP32[$ht2 >> 2] | 0;
+ $conv16 = +($8 | 0);
+ $add17 = $7 + $conv16;
+ $RightBound = $sp + 4 | 0;
+ $9 = HEAP32[$RightBound >> 2] | 0;
+ $conv20 = +($9 | 0);
+ $y25 = $3 + 40 | 0;
+ $10 = +HEAPF64[$y25 >> 3];
+ $ht1 = $1 + ($r * 44 & -1) + 16 | 0;
+ $11 = HEAP32[$ht1 >> 2] | 0;
+ $conv29 = +($11 | 0);
+ $sub = $10 - $conv29;
+ HEAPF64[$b_sroa_0_0__idx3 >> 3] = $conv;
+ HEAPF64[$b_sroa_1_8__idx8 >> 3] = $add17;
+ HEAPF64[$b_sroa_2_16__idx13 >> 3] = $conv20;
+ HEAPF64[$b_sroa_3_24__idx18 >> 3] = $sub;
+ $b_sroa_3_0 = $sub;
+ $b_sroa_2_0 = $conv20;
+ $b_sroa_0_0 = $conv;
+ $b_sroa_1_0 = $add17;
+ label = 4;
+ break;
+ case 4:
+ $b_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$b_sroa_0_0__idx >> 3] = $b_sroa_0_0;
+ $b_sroa_1_8__idx5 = $agg_result + 8 | 0;
+ HEAPF64[$b_sroa_1_8__idx5 >> 3] = $b_sroa_1_0;
+ $b_sroa_2_16__idx10 = $agg_result + 16 | 0;
+ HEAPF64[$b_sroa_2_16__idx10 >> 3] = $b_sroa_2_0;
+ $b_sroa_3_24__idx15 = $agg_result + 24 | 0;
+ HEAPF64[$b_sroa_3_24__idx15 >> 3] = $b_sroa_3_0;
+ return;
+ }
+}
+function _straight_len($n) {
+ $n = $n | 0;
+ var $x16 = 0, $cnt_0 = 0, $v_0 = 0, $list = 0, $0 = 0, $1 = 0, $head = 0, $2 = 0, $node_type = 0, $3 = 0, $cmp = 0, $size = 0, $4 = 0, $cmp5 = 0, $size8 = 0, $5 = 0, $cmp9 = 0, $x = 0, $6 = 0.0, $7 = 0.0, $cmp17 = 0, $inc = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x16 = $n + 32 | 0;
+ $v_0 = $n;
+ $cnt_0 = 0;
+ label = 3;
+ break;
+ case 3:
+ $list = $v_0 + 184 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $head = $1 + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $node_type = $2 + 162 | 0;
+ $3 = HEAP8[$node_type] | 0;
+ $cmp = $3 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $size = $2 + 188 | 0;
+ $4 = HEAP32[$size >> 2] | 0;
+ $cmp5 = ($4 | 0) == 1;
+ if ($cmp5) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $size8 = $2 + 180 | 0;
+ $5 = HEAP32[$size8 >> 2] | 0;
+ $cmp9 = ($5 | 0) == 1;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $x = $2 + 32 | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $7 = +HEAPF64[$x16 >> 3];
+ $cmp17 = $6 != $7;
+ $inc = $cnt_0 + 1 | 0;
+ if ($cmp17) {
+ label = 7;
+ break;
+ } else {
+ $v_0 = $2;
+ $cnt_0 = $inc;
+ label = 3;
+ break;
+ }
+ case 7:
+ return $cnt_0 | 0;
+ }
+ return 0;
+}
+function _resize_vn($vn, $lx, $cx, $rx) {
+ $vn = $vn | 0;
+ $lx = $lx | 0;
+ $cx = $cx | 0;
+ $rx = $rx | 0;
+ HEAPF64[$vn + 32 >> 3] = +($cx | 0);
+ HEAPF64[$vn + 104 >> 3] = +($cx - $lx | 0);
+ HEAPF64[$vn + 112 >> 3] = +($rx - $cx | 0);
+ return;
+}
+function _swap_spline($s) {
+ $s = $s | 0;
+ var $size = 0, $0 = 0, $mul = 0, $call = 0, $1 = 0, $list1 = 0, $cmp15 = 0, $2 = 0, $sub = 0, $3 = 0, $add_ptr = 0, $cmp413 = 0, $4 = 0, $lp_018 = 0, $i_017 = 0, $olp_016 = 0, $incdec_ptr = 0, $incdec_ptr2 = 0, $inc = 0, $cmp = 0, $5 = 0, $i_114 = 0, $list7 = 0, $6 = 0, $7 = 0, $inc9 = 0, $cmp4 = 0, $8 = 0, $_lcssa = 0, $9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $s + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $mul = $0 * 48 & -1;
+ $call = _gmalloc($mul) | 0;
+ $1 = $call;
+ $list1 = $s | 0;
+ $cmp15 = ($0 | 0) > 0;
+ if ($cmp15) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$list1 >> 2] | 0;
+ $_lcssa = $2;
+ label = 8;
+ break;
+ case 4:
+ $sub = $0 - 1 | 0;
+ $3 = HEAP32[$list1 >> 2] | 0;
+ $add_ptr = $3 + ($sub * 48 & -1) | 0;
+ $olp_016 = $add_ptr;
+ $i_017 = 0;
+ $lp_018 = $1;
+ label = 6;
+ break;
+ case 5:
+ $cmp413 = ($0 | 0) > 0;
+ $4 = HEAP32[$list1 >> 2] | 0;
+ if ($cmp413) {
+ $i_114 = 0;
+ $5 = $4;
+ label = 7;
+ break;
+ } else {
+ $_lcssa = $4;
+ label = 8;
+ break;
+ }
+ case 6:
+ $incdec_ptr = $olp_016 - 48 | 0;
+ $incdec_ptr2 = $lp_018 + 48 | 0;
+ _swap_bezier($olp_016, $lp_018);
+ $inc = $i_017 + 1 | 0;
+ $cmp = ($inc | 0) < ($0 | 0);
+ if ($cmp) {
+ $olp_016 = $incdec_ptr;
+ $i_017 = $inc;
+ $lp_018 = $incdec_ptr2;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 7:
+ $list7 = $5 + ($i_114 * 48 & -1) | 0;
+ $6 = HEAP32[$list7 >> 2] | 0;
+ $7 = $6;
+ _free($7);
+ $inc9 = $i_114 + 1 | 0;
+ $cmp4 = ($inc9 | 0) < ($0 | 0);
+ $8 = HEAP32[$list1 >> 2] | 0;
+ if ($cmp4) {
+ $i_114 = $inc9;
+ $5 = $8;
+ label = 7;
+ break;
+ } else {
+ $_lcssa = $8;
+ label = 8;
+ break;
+ }
+ case 8:
+ $9 = $_lcssa;
+ _free($9);
+ HEAP32[$list1 >> 2] = $1;
+ return;
+ }
+}
+function _swap_bezier($old, $new) {
+ $old = $old | 0;
+ $new = $new | 0;
+ var $size = 0, $0 = 0, $mul = 0, $call = 0, $1 = 0, $cmp16 = 0, $list1 = 0, $sub = 0, $2 = 0, $add_ptr = 0, $lp_019 = 0, $i_018 = 0, $olp_017 = 0, $incdec_ptr = 0, $incdec_ptr2 = 0, $3 = 0, $4 = 0, $inc = 0, $cmp = 0, $list3 = 0, $size4 = 0, $eflag = 0, $5 = 0, $sflag = 0, $sflag5 = 0, $6 = 0, $eflag6 = 0, $sp = 0, $ep = 0, $7 = 0, $8 = 0, $ep7 = 0, $sp8 = 0, $9 = 0, $10 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $old + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $mul = $0 << 4;
+ $call = _gmalloc($mul) | 0;
+ $1 = $call;
+ $cmp16 = ($0 | 0) > 0;
+ if ($cmp16) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $list1 = $old | 0;
+ $sub = $0 - 1 | 0;
+ $2 = HEAP32[$list1 >> 2] | 0;
+ $add_ptr = $2 + ($sub << 4) | 0;
+ $olp_017 = $add_ptr;
+ $i_018 = 0;
+ $lp_019 = $1;
+ label = 4;
+ break;
+ case 4:
+ $incdec_ptr = $lp_019 + 16 | 0;
+ $incdec_ptr2 = $olp_017 - 16 | 0;
+ $3 = $lp_019;
+ $4 = $olp_017;
+ HEAP32[$3 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $inc = $i_018 + 1 | 0;
+ $cmp = ($inc | 0) < ($0 | 0);
+ if ($cmp) {
+ $olp_017 = $incdec_ptr2;
+ $i_018 = $inc;
+ $lp_019 = $incdec_ptr;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $list3 = $new | 0;
+ HEAP32[$list3 >> 2] = $1;
+ $size4 = $new + 4 | 0;
+ HEAP32[$size4 >> 2] = $0;
+ $eflag = $old + 12 | 0;
+ $5 = HEAP32[$eflag >> 2] | 0;
+ $sflag = $new + 8 | 0;
+ HEAP32[$sflag >> 2] = $5;
+ $sflag5 = $old + 8 | 0;
+ $6 = HEAP32[$sflag5 >> 2] | 0;
+ $eflag6 = $new + 12 | 0;
+ HEAP32[$eflag6 >> 2] = $6;
+ $sp = $new + 16 | 0;
+ $ep = $old + 32 | 0;
+ $7 = $sp;
+ $8 = $ep;
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $ep7 = $new + 32 | 0;
+ $sp8 = $old + 16 | 0;
+ $9 = $ep7;
+ $10 = $sp8;
+ HEAP32[$9 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ return;
+ }
+}
+function _makeLineEdge($fe, $points, $hp) {
+ $fe = $fe | 0;
+ $points = $points | 0;
+ $hp = $hp | 0;
+ var $startp = 0, $endp = 0, $lp = 0, $tmp = 0, $tmp36 = 0, $tmp42 = 0, $tmp48 = 0, $edge_type38 = 0, $0 = 0, $cmp39 = 0, $e_040 = 0, $to_orig = 0, $1 = 0, $edge_type = 0, $2 = 0, $cmp = 0, $e_0_lcssa = 0, $head = 0, $3 = 0, $tail = 0, $4 = 0, $rank = 0, $5 = 0, $rank5 = 0, $6 = 0, $sub = 0, $cmp6 = 0, $sub18 = 0, $cond = 0, $graph = 0, $7 = 0, $has_labels = 0, $8 = 0, $and = 0, $tobool = 0, $tail25 = 0, $9 = 0, $10 = 0, $cmp27 = 0, $coord = 0, $p = 0, $11 = 0, $12 = 0, $coord33 = 0, $p35 = 0, $13 = 0, $14 = 0, $coord38 = 0, $p41 = 0, $15 = 0, $16 = 0, $coord44 = 0, $p47 = 0, $17 = 0, $18 = 0, $label = 0, $19 = 0, $tobool51 = 0, $dimen_sroa_0_0__idx = 0, $dimen_sroa_0_0_copyload = 0.0, $dimen_sroa_1_8__idx4 = 0, $dimen_sroa_1_8_copyload = 0.0, $graph56 = 0, $20 = 0, $rankdir = 0, $21 = 0, $and59 = 0, $tobool60 = 0, $dimen_sroa_0_0_copyload_dimen_sroa_1_8_copyload = 0.0, $dimen_sroa_1_8_copyload_dimen_sroa_0_0_copyload = 0.0, $pos = 0, $22 = 0, $23 = 0, $call = 0, $tobool68 = 0, $div = 0.0, $x70 = 0, $24 = 0.0, $add = 0.0, $div71 = 0.0, $y72 = 0, $25 = 0.0, $sub73 = 0.0, $sub77 = 0.0, $div78 = 0.0, $y79 = 0, $26 = 0.0, $add80 = 0.0, $arrayidx = 0, $27 = 0, $28 = 0, $29 = 0, $arrayidx83 = 0, $arrayidx84 = 0, $arrayidx85 = 0, $30 = 0, $31 = 0, $32 = 0, $arrayidx86 = 0, $arrayidx87 = 0, $33 = 0, $34 = 0, $35 = 0, $arrayidx89 = 0, $36 = 0, $37 = 0, $38 = 0, $arrayidx91 = 0, $arrayidx92 = 0, $39 = 0, $40 = 0, $41 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 112 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $startp = __stackBase__ | 0;
+ $endp = __stackBase__ + 16 | 0;
+ $lp = __stackBase__ + 32 | 0;
+ $tmp = __stackBase__ + 48 | 0;
+ $tmp36 = __stackBase__ + 64 | 0;
+ $tmp42 = __stackBase__ + 80 | 0;
+ $tmp48 = __stackBase__ + 96 | 0;
+ $edge_type38 = $fe + 128 | 0;
+ $0 = HEAP8[$edge_type38] | 0;
+ $cmp39 = $0 << 24 >> 24 == 0;
+ if ($cmp39) {
+ $e_0_lcssa = $fe;
+ label = 4;
+ break;
+ } else {
+ $e_040 = $fe;
+ label = 3;
+ break;
+ }
+ case 3:
+ $to_orig = $e_040 + 132 | 0;
+ $1 = HEAP32[$to_orig >> 2] | 0;
+ $edge_type = $1 + 128 | 0;
+ $2 = HEAP8[$edge_type] | 0;
+ $cmp = $2 << 24 >> 24 == 0;
+ if ($cmp) {
+ $e_0_lcssa = $1;
+ label = 4;
+ break;
+ } else {
+ $e_040 = $1;
+ label = 3;
+ break;
+ }
+ case 4:
+ $head = $e_0_lcssa + 12 | 0;
+ $3 = HEAP32[$head >> 2] | 0;
+ $tail = $e_0_lcssa + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $rank = $3 + 236 | 0;
+ $5 = HEAP32[$rank >> 2] | 0;
+ $rank5 = $4 + 236 | 0;
+ $6 = HEAP32[$rank5 >> 2] | 0;
+ $sub = $5 - $6 | 0;
+ $cmp6 = ($sub | 0) > -1;
+ $sub18 = -$sub | 0;
+ $cond = $cmp6 ? $sub : $sub18;
+ if (($cond | 0) == 2) {
+ label = 5;
+ break;
+ } else if (($cond | 0) == 1) {
+ $retval_0 = 0;
+ label = 15;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $graph = $3 + 20 | 0;
+ $7 = HEAP32[$graph >> 2] | 0;
+ $has_labels = $7 + 153 | 0;
+ $8 = HEAP8[$has_labels] | 0;
+ $and = $8 & 1;
+ $tobool = $and << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 15;
+ break;
+ }
+ case 6:
+ $tail25 = $fe + 16 | 0;
+ $9 = HEAP32[$tail25 >> 2] | 0;
+ $10 = HEAP32[$tail >> 2] | 0;
+ $cmp27 = ($9 | 0) == ($10 | 0);
+ if ($cmp27) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$hp >> 2] = $3;
+ $coord = $4 + 32 | 0;
+ $p = $e_0_lcssa + 32 | 0;
+ _add_pointf3016($tmp, $coord, $p);
+ $11 = $startp;
+ $12 = $tmp;
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ $coord33 = $3 + 32 | 0;
+ $p35 = $e_0_lcssa + 72 | 0;
+ _add_pointf3016($tmp36, $coord33, $p35);
+ $13 = $endp;
+ $14 = $tmp36;
+ HEAP32[$13 >> 2] = HEAP32[$14 >> 2] | 0;
+ HEAP32[$13 + 4 >> 2] = HEAP32[$14 + 4 >> 2] | 0;
+ HEAP32[$13 + 8 >> 2] = HEAP32[$14 + 8 >> 2] | 0;
+ HEAP32[$13 + 12 >> 2] = HEAP32[$14 + 12 >> 2] | 0;
+ label = 9;
+ break;
+ case 8:
+ HEAP32[$hp >> 2] = $4;
+ $coord38 = $3 + 32 | 0;
+ $p41 = $e_0_lcssa + 72 | 0;
+ _add_pointf3016($tmp42, $coord38, $p41);
+ $15 = $startp;
+ $16 = $tmp42;
+ HEAP32[$15 >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ $coord44 = $4 + 32 | 0;
+ $p47 = $e_0_lcssa + 32 | 0;
+ _add_pointf3016($tmp48, $coord44, $p47);
+ $17 = $endp;
+ $18 = $tmp48;
+ HEAP32[$17 >> 2] = HEAP32[$18 >> 2] | 0;
+ HEAP32[$17 + 4 >> 2] = HEAP32[$18 + 4 >> 2] | 0;
+ HEAP32[$17 + 8 >> 2] = HEAP32[$18 + 8 >> 2] | 0;
+ HEAP32[$17 + 12 >> 2] = HEAP32[$18 + 12 >> 2] | 0;
+ label = 9;
+ break;
+ case 9:
+ $label = $e_0_lcssa + 112 | 0;
+ $19 = HEAP32[$label >> 2] | 0;
+ $tobool51 = ($19 | 0) == 0;
+ if ($tobool51) {
+ label = 14;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $dimen_sroa_0_0__idx = $19 + 24 | 0;
+ $dimen_sroa_0_0_copyload = +HEAPF64[$dimen_sroa_0_0__idx >> 3];
+ $dimen_sroa_1_8__idx4 = $19 + 32 | 0;
+ $dimen_sroa_1_8_copyload = +HEAPF64[$dimen_sroa_1_8__idx4 >> 3];
+ $graph56 = $3 + 20 | 0;
+ $20 = HEAP32[$graph56 >> 2] | 0;
+ $rankdir = $20 + 156 | 0;
+ $21 = HEAP32[$rankdir >> 2] | 0;
+ $and59 = $21 & 1;
+ $tobool60 = ($and59 | 0) == 0;
+ $dimen_sroa_0_0_copyload_dimen_sroa_1_8_copyload = $tobool60 ? $dimen_sroa_0_0_copyload : $dimen_sroa_1_8_copyload;
+ $dimen_sroa_1_8_copyload_dimen_sroa_0_0_copyload = $tobool60 ? $dimen_sroa_1_8_copyload : $dimen_sroa_0_0_copyload;
+ $pos = $19 + 56 | 0;
+ $22 = $lp;
+ $23 = $pos;
+ HEAP32[$22 >> 2] = HEAP32[$23 >> 2] | 0;
+ HEAP32[$22 + 4 >> 2] = HEAP32[$23 + 4 >> 2] | 0;
+ HEAP32[$22 + 8 >> 2] = HEAP32[$23 + 8 >> 2] | 0;
+ HEAP32[$22 + 12 >> 2] = HEAP32[$23 + 12 >> 2] | 0;
+ $call = _leftOf($endp, $startp, $lp) | 0;
+ $tobool68 = ($call | 0) == 0;
+ $div = $dimen_sroa_0_0_copyload_dimen_sroa_1_8_copyload * .5;
+ $x70 = $lp | 0;
+ $24 = +HEAPF64[$x70 >> 3];
+ if ($tobool68) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $add = $24 + $div;
+ HEAPF64[$x70 >> 3] = $add;
+ $div71 = $dimen_sroa_1_8_copyload_dimen_sroa_0_0_copyload * .5;
+ $y72 = $lp + 8 | 0;
+ $25 = +HEAPF64[$y72 >> 3];
+ $sub73 = $25 - $div71;
+ HEAPF64[$y72 >> 3] = $sub73;
+ label = 13;
+ break;
+ case 12:
+ $sub77 = $24 - $div;
+ HEAPF64[$x70 >> 3] = $sub77;
+ $div78 = $dimen_sroa_1_8_copyload_dimen_sroa_0_0_copyload * .5;
+ $y79 = $lp + 8 | 0;
+ $26 = +HEAPF64[$y79 >> 3];
+ $add80 = $div78 + $26;
+ HEAPF64[$y79 >> 3] = $add80;
+ label = 13;
+ break;
+ case 13:
+ $arrayidx = $points + 16 | 0;
+ $27 = $points;
+ $28 = $startp;
+ HEAP32[$27 >> 2] = HEAP32[$28 >> 2] | 0;
+ HEAP32[$27 + 4 >> 2] = HEAP32[$28 + 4 >> 2] | 0;
+ HEAP32[$27 + 8 >> 2] = HEAP32[$28 + 8 >> 2] | 0;
+ HEAP32[$27 + 12 >> 2] = HEAP32[$28 + 12 >> 2] | 0;
+ $29 = $arrayidx;
+ HEAP32[$29 >> 2] = HEAP32[$28 >> 2] | 0;
+ HEAP32[$29 + 4 >> 2] = HEAP32[$28 + 4 >> 2] | 0;
+ HEAP32[$29 + 8 >> 2] = HEAP32[$28 + 8 >> 2] | 0;
+ HEAP32[$29 + 12 >> 2] = HEAP32[$28 + 12 >> 2] | 0;
+ $arrayidx83 = $points + 32 | 0;
+ $arrayidx84 = $points + 48 | 0;
+ $arrayidx85 = $points + 64 | 0;
+ $30 = $arrayidx85;
+ HEAP32[$30 >> 2] = HEAP32[$22 >> 2] | 0;
+ HEAP32[$30 + 4 >> 2] = HEAP32[$22 + 4 >> 2] | 0;
+ HEAP32[$30 + 8 >> 2] = HEAP32[$22 + 8 >> 2] | 0;
+ HEAP32[$30 + 12 >> 2] = HEAP32[$22 + 12 >> 2] | 0;
+ $31 = $arrayidx84;
+ HEAP32[$31 >> 2] = HEAP32[$22 >> 2] | 0;
+ HEAP32[$31 + 4 >> 2] = HEAP32[$22 + 4 >> 2] | 0;
+ HEAP32[$31 + 8 >> 2] = HEAP32[$22 + 8 >> 2] | 0;
+ HEAP32[$31 + 12 >> 2] = HEAP32[$22 + 12 >> 2] | 0;
+ $32 = $arrayidx83;
+ HEAP32[$32 >> 2] = HEAP32[$22 >> 2] | 0;
+ HEAP32[$32 + 4 >> 2] = HEAP32[$22 + 4 >> 2] | 0;
+ HEAP32[$32 + 8 >> 2] = HEAP32[$22 + 8 >> 2] | 0;
+ HEAP32[$32 + 12 >> 2] = HEAP32[$22 + 12 >> 2] | 0;
+ $arrayidx86 = $points + 80 | 0;
+ $arrayidx87 = $points + 96 | 0;
+ $33 = $arrayidx87;
+ $34 = $endp;
+ HEAP32[$33 >> 2] = HEAP32[$34 >> 2] | 0;
+ HEAP32[$33 + 4 >> 2] = HEAP32[$34 + 4 >> 2] | 0;
+ HEAP32[$33 + 8 >> 2] = HEAP32[$34 + 8 >> 2] | 0;
+ HEAP32[$33 + 12 >> 2] = HEAP32[$34 + 12 >> 2] | 0;
+ $35 = $arrayidx86;
+ HEAP32[$35 >> 2] = HEAP32[$34 >> 2] | 0;
+ HEAP32[$35 + 4 >> 2] = HEAP32[$34 + 4 >> 2] | 0;
+ HEAP32[$35 + 8 >> 2] = HEAP32[$34 + 8 >> 2] | 0;
+ HEAP32[$35 + 12 >> 2] = HEAP32[$34 + 12 >> 2] | 0;
+ $retval_0 = 7;
+ label = 15;
+ break;
+ case 14:
+ $arrayidx89 = $points + 16 | 0;
+ $36 = $points;
+ $37 = $startp;
+ HEAP32[$36 >> 2] = HEAP32[$37 >> 2] | 0;
+ HEAP32[$36 + 4 >> 2] = HEAP32[$37 + 4 >> 2] | 0;
+ HEAP32[$36 + 8 >> 2] = HEAP32[$37 + 8 >> 2] | 0;
+ HEAP32[$36 + 12 >> 2] = HEAP32[$37 + 12 >> 2] | 0;
+ $38 = $arrayidx89;
+ HEAP32[$38 >> 2] = HEAP32[$37 >> 2] | 0;
+ HEAP32[$38 + 4 >> 2] = HEAP32[$37 + 4 >> 2] | 0;
+ HEAP32[$38 + 8 >> 2] = HEAP32[$37 + 8 >> 2] | 0;
+ HEAP32[$38 + 12 >> 2] = HEAP32[$37 + 12 >> 2] | 0;
+ $arrayidx91 = $points + 48 | 0;
+ $arrayidx92 = $points + 32 | 0;
+ $39 = $arrayidx92;
+ $40 = $endp;
+ HEAP32[$39 >> 2] = HEAP32[$40 >> 2] | 0;
+ HEAP32[$39 + 4 >> 2] = HEAP32[$40 + 4 >> 2] | 0;
+ HEAP32[$39 + 8 >> 2] = HEAP32[$40 + 8 >> 2] | 0;
+ HEAP32[$39 + 12 >> 2] = HEAP32[$40 + 12 >> 2] | 0;
+ $41 = $arrayidx91;
+ HEAP32[$41 >> 2] = HEAP32[$40 >> 2] | 0;
+ HEAP32[$41 + 4 >> 2] = HEAP32[$40 + 4 >> 2] | 0;
+ HEAP32[$41 + 8 >> 2] = HEAP32[$40 + 8 >> 2] | 0;
+ HEAP32[$41 + 12 >> 2] = HEAP32[$40 + 12 >> 2] | 0;
+ $retval_0 = 4;
+ label = 15;
+ break;
+ case 15:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _maximal_bbox($agg_result, $sp, $vn, $ie, $oe) {
+ $agg_result = $agg_result | 0;
+ $sp = $sp | 0;
+ $vn = $vn | 0;
+ $ie = $ie | 0;
+ $oe = $oe | 0;
+ var $graph = 0, $0 = 0, $x = 0, $1 = 0.0, $lw = 0, $2 = 0.0, $sub = 0.0, $sub2 = 0.0, $call = 0, $tobool = 0, $call3 = 0, $tobool4 = 0, $x7 = 0, $3 = 0.0, $Splinesep = 0, $4 = 0, $conv = 0.0, $add = 0.0, $x10 = 0, $5 = 0.0, $mval = 0, $6 = 0, $conv12 = 0.0, $add13 = 0.0, $node_type = 0, $7 = 0, $cmp = 0, $nodesep = 0, $8 = 0, $conv19 = 0.0, $div = 0.0, $add20 = 0.0, $Splinesep22 = 0, $9 = 0, $conv23 = 0.0, $add24 = 0.0, $nb_0 = 0.0, $cmp26 = 0, $b_0 = 0.0, $cmp30 = 0, $add32 = 0.0, $sub34 = 0.0, $add32_sink = 0.0, $conv33 = 0, $cmp39 = 0, $add42 = 0.0, $sub45 = 0.0, $add42_sink = 0.0, $conv43 = 0, $LeftBound = 0, $10 = 0, $cmp49 = 0, $add55 = 0.0, $sub58 = 0.0, $add55_sink = 0.0, $conv56 = 0, $rv_sroa_0_0_in = 0, $rv_sroa_0_0 = 0.0, $node_type71 = 0, $11 = 0, $cmp73 = 0, $label = 0, $12 = 0, $tobool76 = 0, $13 = 0.0, $add81 = 0.0, $14 = 0.0, $rw = 0, $15 = 0.0, $add87 = 0.0, $add88 = 0.0, $b_1 = 0.0, $call90 = 0, $tobool91 = 0, $call93 = 0, $tobool94 = 0, $x99 = 0, $16 = 0.0, $Splinesep100 = 0, $17 = 0, $conv101 = 0.0, $sub102 = 0.0, $x106 = 0, $18 = 0.0, $lw108 = 0, $19 = 0.0, $sub109 = 0.0, $node_type111 = 0, $20 = 0, $cmp113 = 0, $nodesep117 = 0, $21 = 0, $conv118 = 0.0, $div119 = 0.0, $sub120 = 0.0, $Splinesep122 = 0, $22 = 0, $conv123 = 0.0, $sub124 = 0.0, $nb_1 = 0.0, $cmp127 = 0, $b_2 = 0.0, $cmp131 = 0, $add134 = 0.0, $sub137 = 0.0, $add134_sink = 0.0, $conv135 = 0, $cmp145 = 0, $add148 = 0.0, $sub151 = 0.0, $add148_sink = 0.0, $conv149 = 0, $RightBound = 0, $23 = 0, $cmp155 = 0, $add161 = 0.0, $sub164 = 0.0, $add161_sink = 0.0, $conv162 = 0, $rv_sroa_2_0_in = 0, $rv_sroa_2_0 = 0.0, $24 = 0, $cmp179 = 0, $label183 = 0, $25 = 0, $tobool184 = 0, $rw187 = 0, $26 = 0.0, $sub190 = 0.0, $rv_sroa_2_1 = 0.0, $y = 0, $27 = 0.0, $rank = 0, $28 = 0, $rank196 = 0, $29 = 0, $ht1 = 0, $30 = 0, $conv197 = 0.0, $sub198 = 0.0, $ht2 = 0, $31 = 0, $conv209 = 0.0, $add210 = 0.0, $rv_sroa_0_0__idx = 0, $rv_sroa_1_8__idx1 = 0, $rv_sroa_2_16__idx2 = 0, $rv_sroa_3_24__idx3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $graph = $vn + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ $x = $vn + 32 | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $lw = $vn + 104 | 0;
+ $2 = +HEAPF64[$lw >> 3];
+ $sub = $1 - $2;
+ $sub2 = $sub + -4.0;
+ $call = _neighbor($vn, $ie, $oe, -1) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call3 = _cl_bound($vn, $call) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $x7 = $call3 + 72 | 0;
+ $3 = +HEAPF64[$x7 >> 3];
+ $Splinesep = $sp + 8 | 0;
+ $4 = HEAP32[$Splinesep >> 2] | 0;
+ $conv = +($4 | 0);
+ $add = $3 + $conv;
+ $nb_0 = $add;
+ label = 8;
+ break;
+ case 5:
+ $x10 = $call + 32 | 0;
+ $5 = +HEAPF64[$x10 >> 3];
+ $mval = $call + 244 | 0;
+ $6 = HEAP32[$mval >> 2] | 0;
+ $conv12 = +($6 | 0);
+ $add13 = $5 + $conv12;
+ $node_type = $call + 162 | 0;
+ $7 = HEAP8[$node_type] | 0;
+ $cmp = $7 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $nodesep = $0 + 260 | 0;
+ $8 = HEAP32[$nodesep >> 2] | 0;
+ $conv19 = +($8 | 0);
+ $div = $conv19 * .5;
+ $add20 = $add13 + $div;
+ $nb_0 = $add20;
+ label = 8;
+ break;
+ case 7:
+ $Splinesep22 = $sp + 8 | 0;
+ $9 = HEAP32[$Splinesep22 >> 2] | 0;
+ $conv23 = +($9 | 0);
+ $add24 = $add13 + $conv23;
+ $nb_0 = $add24;
+ label = 8;
+ break;
+ case 8:
+ $cmp26 = $nb_0 < $sub2;
+ $b_0 = $cmp26 ? $nb_0 : $sub2;
+ $cmp30 = $b_0 < 0.0;
+ if ($cmp30) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add32 = $b_0 + .5;
+ $add32_sink = $add32;
+ label = 11;
+ break;
+ case 10:
+ $sub34 = $b_0 + -.5;
+ $add32_sink = $sub34;
+ label = 11;
+ break;
+ case 11:
+ $conv33 = ~~$add32_sink;
+ $rv_sroa_0_0_in = $conv33;
+ label = 20;
+ break;
+ case 12:
+ $cmp39 = $sub2 >= 0.0;
+ if ($cmp39) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $add42 = $sub2 + .5;
+ $add42_sink = $add42;
+ label = 15;
+ break;
+ case 14:
+ $sub45 = $sub2 + -.5;
+ $add42_sink = $sub45;
+ label = 15;
+ break;
+ case 15:
+ $conv43 = ~~$add42_sink;
+ $LeftBound = $sp | 0;
+ $10 = HEAP32[$LeftBound >> 2] | 0;
+ $cmp49 = ($conv43 | 0) < ($10 | 0);
+ if ($cmp49) {
+ label = 16;
+ break;
+ } else {
+ $rv_sroa_0_0_in = $10;
+ label = 20;
+ break;
+ }
+ case 16:
+ if ($cmp39) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $add55 = $sub2 + .5;
+ $add55_sink = $add55;
+ label = 19;
+ break;
+ case 18:
+ $sub58 = $sub2 + -.5;
+ $add55_sink = $sub58;
+ label = 19;
+ break;
+ case 19:
+ $conv56 = ~~$add55_sink;
+ $rv_sroa_0_0_in = $conv56;
+ label = 20;
+ break;
+ case 20:
+ $rv_sroa_0_0 = +($rv_sroa_0_0_in | 0);
+ $node_type71 = $vn + 162 | 0;
+ $11 = HEAP8[$node_type71] | 0;
+ $cmp73 = $11 << 24 >> 24 == 1;
+ if ($cmp73) {
+ label = 21;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 21:
+ $label = $vn + 120 | 0;
+ $12 = HEAP32[$label >> 2] | 0;
+ $tobool76 = ($12 | 0) == 0;
+ if ($tobool76) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $13 = +HEAPF64[$x >> 3];
+ $add81 = $13 + 10.0;
+ $b_1 = $add81;
+ label = 24;
+ break;
+ case 23:
+ $14 = +HEAPF64[$x >> 3];
+ $rw = $vn + 112 | 0;
+ $15 = +HEAPF64[$rw >> 3];
+ $add87 = $14 + $15;
+ $add88 = $add87 + 4.0;
+ $b_1 = $add88;
+ label = 24;
+ break;
+ case 24:
+ $call90 = _neighbor($vn, $ie, $oe, 1) | 0;
+ $tobool91 = ($call90 | 0) == 0;
+ if ($tobool91) {
+ label = 34;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $call93 = _cl_bound($vn, $call90) | 0;
+ $tobool94 = ($call93 | 0) == 0;
+ if ($tobool94) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $x99 = $call93 + 56 | 0;
+ $16 = +HEAPF64[$x99 >> 3];
+ $Splinesep100 = $sp + 8 | 0;
+ $17 = HEAP32[$Splinesep100 >> 2] | 0;
+ $conv101 = +($17 | 0);
+ $sub102 = $16 - $conv101;
+ $nb_1 = $sub102;
+ label = 30;
+ break;
+ case 27:
+ $x106 = $call90 + 32 | 0;
+ $18 = +HEAPF64[$x106 >> 3];
+ $lw108 = $call90 + 104 | 0;
+ $19 = +HEAPF64[$lw108 >> 3];
+ $sub109 = $18 - $19;
+ $node_type111 = $call90 + 162 | 0;
+ $20 = HEAP8[$node_type111] | 0;
+ $cmp113 = $20 << 24 >> 24 == 0;
+ if ($cmp113) {
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ $nodesep117 = $0 + 260 | 0;
+ $21 = HEAP32[$nodesep117 >> 2] | 0;
+ $conv118 = +($21 | 0);
+ $div119 = $conv118 * .5;
+ $sub120 = $sub109 - $div119;
+ $nb_1 = $sub120;
+ label = 30;
+ break;
+ case 29:
+ $Splinesep122 = $sp + 8 | 0;
+ $22 = HEAP32[$Splinesep122 >> 2] | 0;
+ $conv123 = +($22 | 0);
+ $sub124 = $sub109 - $conv123;
+ $nb_1 = $sub124;
+ label = 30;
+ break;
+ case 30:
+ $cmp127 = $nb_1 > $b_1;
+ $b_2 = $cmp127 ? $nb_1 : $b_1;
+ $cmp131 = $b_2 < 0.0;
+ if ($cmp131) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $add134 = $b_2 + .5;
+ $add134_sink = $add134;
+ label = 33;
+ break;
+ case 32:
+ $sub137 = $b_2 + -.5;
+ $add134_sink = $sub137;
+ label = 33;
+ break;
+ case 33:
+ $conv135 = ~~$add134_sink;
+ $rv_sroa_2_0_in = $conv135;
+ label = 42;
+ break;
+ case 34:
+ $cmp145 = $b_1 >= 0.0;
+ if ($cmp145) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ $add148 = $b_1 + .5;
+ $add148_sink = $add148;
+ label = 37;
+ break;
+ case 36:
+ $sub151 = $b_1 + -.5;
+ $add148_sink = $sub151;
+ label = 37;
+ break;
+ case 37:
+ $conv149 = ~~$add148_sink;
+ $RightBound = $sp + 4 | 0;
+ $23 = HEAP32[$RightBound >> 2] | 0;
+ $cmp155 = ($conv149 | 0) > ($23 | 0);
+ if ($cmp155) {
+ label = 38;
+ break;
+ } else {
+ $rv_sroa_2_0_in = $23;
+ label = 42;
+ break;
+ }
+ case 38:
+ if ($cmp145) {
+ label = 39;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 39:
+ $add161 = $b_1 + .5;
+ $add161_sink = $add161;
+ label = 41;
+ break;
+ case 40:
+ $sub164 = $b_1 + -.5;
+ $add161_sink = $sub164;
+ label = 41;
+ break;
+ case 41:
+ $conv162 = ~~$add161_sink;
+ $rv_sroa_2_0_in = $conv162;
+ label = 42;
+ break;
+ case 42:
+ $rv_sroa_2_0 = +($rv_sroa_2_0_in | 0);
+ $24 = HEAP8[$node_type71] | 0;
+ $cmp179 = $24 << 24 >> 24 == 1;
+ if ($cmp179) {
+ label = 43;
+ break;
+ } else {
+ $rv_sroa_2_1 = $rv_sroa_2_0;
+ label = 45;
+ break;
+ }
+ case 43:
+ $label183 = $vn + 120 | 0;
+ $25 = HEAP32[$label183 >> 2] | 0;
+ $tobool184 = ($25 | 0) == 0;
+ if ($tobool184) {
+ $rv_sroa_2_1 = $rv_sroa_2_0;
+ label = 45;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $rw187 = $vn + 112 | 0;
+ $26 = +HEAPF64[$rw187 >> 3];
+ $sub190 = $rv_sroa_2_0 - $26;
+ $rv_sroa_2_1 = $sub190;
+ label = 45;
+ break;
+ case 45:
+ $y = $vn + 40 | 0;
+ $27 = +HEAPF64[$y >> 3];
+ $rank = $vn + 236 | 0;
+ $28 = HEAP32[$rank >> 2] | 0;
+ $rank196 = $0 + 224 | 0;
+ $29 = HEAP32[$rank196 >> 2] | 0;
+ $ht1 = $29 + ($28 * 44 & -1) + 16 | 0;
+ $30 = HEAP32[$ht1 >> 2] | 0;
+ $conv197 = +($30 | 0);
+ $sub198 = $27 - $conv197;
+ $ht2 = $29 + ($28 * 44 & -1) + 20 | 0;
+ $31 = HEAP32[$ht2 >> 2] | 0;
+ $conv209 = +($31 | 0);
+ $add210 = $27 + $conv209;
+ $rv_sroa_0_0__idx = $agg_result | 0;
+ HEAPF64[$rv_sroa_0_0__idx >> 3] = $rv_sroa_0_0;
+ $rv_sroa_1_8__idx1 = $agg_result + 8 | 0;
+ HEAPF64[$rv_sroa_1_8__idx1 >> 3] = $sub198;
+ $rv_sroa_2_16__idx2 = $agg_result + 16 | 0;
+ HEAPF64[$rv_sroa_2_16__idx2 >> 3] = $rv_sroa_2_1;
+ $rv_sroa_3_24__idx3 = $agg_result + 24 | 0;
+ HEAPF64[$rv_sroa_3_24__idx3 >> 3] = $add210;
+ return;
+ }
+}
+function _makeregularend($agg_result, $b, $side, $y) {
+ $agg_result = $agg_result | 0;
+ $b = $b | 0;
+ $side = $side | 0;
+ $y = $y | 0;
+ var $newb = 0, $x = 0, $0 = 0.0, $conv = 0.0, $x1 = 0, $1 = 0.0, $y3 = 0, $2 = 0.0, $x6 = 0, $3 = 0.0, $y8 = 0, $4 = 0.0, $x10 = 0, $5 = 0.0, $conv11 = 0.0, $6 = 0, $7 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $newb = __stackBase__ | 0;
+ if (($side | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($side | 0) == 4) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $x = $b | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $conv = +($y | 0);
+ $x1 = $b + 16 | 0;
+ $1 = +HEAPF64[$x1 >> 3];
+ $y3 = $b + 8 | 0;
+ $2 = +HEAPF64[$y3 >> 3];
+ _boxfof3015($newb, $0, $conv, $1, $2);
+ label = 5;
+ break;
+ case 4:
+ $x6 = $b | 0;
+ $3 = +HEAPF64[$x6 >> 3];
+ $y8 = $b + 24 | 0;
+ $4 = +HEAPF64[$y8 >> 3];
+ $x10 = $b + 16 | 0;
+ $5 = +HEAPF64[$x10 >> 3];
+ $conv11 = +($y | 0);
+ _boxfof3015($newb, $3, $4, $5, $conv11);
+ label = 5;
+ break;
+ case 5:
+ $6 = $agg_result;
+ $7 = $newb;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ HEAP32[$6 + 16 >> 2] = HEAP32[$7 + 16 >> 2] | 0;
+ HEAP32[$6 + 20 >> 2] = HEAP32[$7 + 20 >> 2] | 0;
+ HEAP32[$6 + 24 >> 2] = HEAP32[$7 + 24 >> 2] | 0;
+ HEAP32[$6 + 28 >> 2] = HEAP32[$7 + 28 >> 2] | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _completeregularpath($P, $first, $last, $tendp, $hendp, $boxn) {
+ $P = $P | 0;
+ $first = $first | 0;
+ $last = $last | 0;
+ $tendp = $tendp | 0;
+ $hendp = $hendp | 0;
+ $boxn = $boxn | 0;
+ var $call = 0, $call1 = 0, $tobool = 0, $0 = 0, $call2 = 0, $tobool6 = 0, $1 = 0, $call8 = 0, $call16 = 0, $call17 = 0, $tobool18 = 0, $2 = 0, $call20 = 0, $tobool31 = 0, $3 = 0, $call33 = 0, $boxn45 = 0, $4 = 0, $cmp6 = 0, $i_07 = 0, $arrayidx47 = 0, $inc = 0, $5 = 0, $cmp = 0, $nbox = 0, $6 = 0, $add = 0, $add48 = 0, $sub49 = 0, $cmp514 = 0, $i_15 = 0, $arrayidx53 = 0, $inc55 = 0, $cmp51 = 0, $boxn57 = 0, $7 = 0, $cmp602 = 0, $i_23_in = 0, $i_23 = 0, $arrayidx63 = 0, $cmp60 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _top_bound($first, -1) | 0;
+ $call1 = _top_bound($first, 1) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = $call;
+ $call2 = _getsplinepoints($0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $tobool6 = ($call1 | 0) == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $1 = $call1;
+ $call8 = _getsplinepoints($1) | 0;
+ label = 6;
+ break;
+ case 6:
+ $call16 = _bot_bound($last, -1) | 0;
+ $call17 = _bot_bound($last, 1) | 0;
+ $tobool18 = ($call16 | 0) == 0;
+ if ($tobool18) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $2 = $call16;
+ $call20 = _getsplinepoints($2) | 0;
+ label = 8;
+ break;
+ case 8:
+ $tobool31 = ($call17 | 0) == 0;
+ if ($tobool31) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $3 = $call17;
+ $call33 = _getsplinepoints($3) | 0;
+ label = 10;
+ break;
+ case 10:
+ $boxn45 = $tendp + 52 | 0;
+ $4 = HEAP32[$boxn45 >> 2] | 0;
+ $cmp6 = ($4 | 0) > 0;
+ if ($cmp6) {
+ $i_07 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $arrayidx47 = $tendp + 56 + ($i_07 << 5) | 0;
+ _add_box($P, $arrayidx47);
+ $inc = $i_07 + 1 | 0;
+ $5 = HEAP32[$boxn45 >> 2] | 0;
+ $cmp = ($inc | 0) < ($5 | 0);
+ if ($cmp) {
+ $i_07 = $inc;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $nbox = $P + 80 | 0;
+ $6 = HEAP32[$nbox >> 2] | 0;
+ $add = $6 + 1 | 0;
+ $add48 = $boxn - 3 | 0;
+ $sub49 = $add48 + $add | 0;
+ $cmp514 = ($boxn | 0) > 0;
+ if ($cmp514) {
+ $i_15 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $arrayidx53 = 53424 + ($i_15 << 5) | 0;
+ _add_box($P, $arrayidx53);
+ $inc55 = $i_15 + 1 | 0;
+ $cmp51 = ($inc55 | 0) < ($boxn | 0);
+ if ($cmp51) {
+ $i_15 = $inc55;
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $boxn57 = $hendp + 52 | 0;
+ $7 = HEAP32[$boxn57 >> 2] | 0;
+ $cmp602 = ($7 | 0) > 0;
+ if ($cmp602) {
+ $i_23_in = $7;
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $i_23 = $i_23_in - 1 | 0;
+ $arrayidx63 = $hendp + 56 + ($i_23 << 5) | 0;
+ _add_box($P, $arrayidx63);
+ $cmp60 = ($i_23 | 0) > 0;
+ if ($cmp60) {
+ $i_23_in = $i_23;
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ _adjustregularpath($P, $add, $sub49);
+ return;
+ }
+}
+function _straight_path($e, $cnt, $plist, $np) {
+ $e = $e | 0;
+ $cnt = $cnt | 0;
+ $plist = $plist | 0;
+ $np = $np | 0;
+ var $0 = 0, $tobool11 = 0, $f_013 = 0, $cnt_addr_012 = 0, $dec = 0, $head = 0, $1 = 0, $list = 0, $2 = 0, $3 = 0, $tobool = 0, $f_0_lcssa = 0, $4 = 0, $inc = 0, $arrayidx1 = 0, $sub = 0, $arrayidx2 = 0, $5 = 0, $6 = 0, $7 = 0, $inc3 = 0, $arrayidx4 = 0, $8 = 0, $9 = 0, $arrayidx7 = 0, $tail = 0, $10 = 0, $coord = 0, $11 = 0, $12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$np >> 2] | 0;
+ $tobool11 = ($cnt | 0) == 0;
+ if ($tobool11) {
+ $f_0_lcssa = $e;
+ label = 4;
+ break;
+ } else {
+ $cnt_addr_012 = $cnt;
+ $f_013 = $e;
+ label = 3;
+ break;
+ }
+ case 3:
+ $dec = $cnt_addr_012 - 1 | 0;
+ $head = $f_013 + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $list = $1 + 184 | 0;
+ $2 = HEAP32[$list >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool = ($dec | 0) == 0;
+ if ($tobool) {
+ $f_0_lcssa = $3;
+ label = 4;
+ break;
+ } else {
+ $cnt_addr_012 = $dec;
+ $f_013 = $3;
+ label = 3;
+ break;
+ }
+ case 4:
+ $4 = HEAP32[$np >> 2] | 0;
+ $inc = $4 + 1 | 0;
+ HEAP32[$np >> 2] = $inc;
+ $arrayidx1 = $plist + ($4 << 4) | 0;
+ $sub = $0 - 1 | 0;
+ $arrayidx2 = $plist + ($sub << 4) | 0;
+ $5 = $arrayidx1;
+ $6 = $arrayidx2;
+ HEAP32[$5 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$5 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$5 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$5 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ $7 = HEAP32[$np >> 2] | 0;
+ $inc3 = $7 + 1 | 0;
+ HEAP32[$np >> 2] = $inc3;
+ $arrayidx4 = $plist + ($7 << 4) | 0;
+ $8 = $arrayidx4;
+ HEAP32[$8 >> 2] = HEAP32[$6 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$6 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$6 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$6 + 12 >> 2] | 0;
+ $9 = HEAP32[$np >> 2] | 0;
+ $arrayidx7 = $plist + ($9 << 4) | 0;
+ $tail = $f_0_lcssa + 16 | 0;
+ $10 = HEAP32[$tail >> 2] | 0;
+ $coord = $10 + 32 | 0;
+ $11 = $arrayidx7;
+ $12 = $coord;
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ return $f_0_lcssa | 0;
+ }
+ return 0;
+}
+function _recover_slack($e, $p) {
+ $e = $e | 0;
+ $p = $p | 0;
+ var $vn_0_in24 = 0, $vn_025 = 0, $node_type26 = 0, $0 = 0, $cmp27 = 0, $boxes = 0, $nbox = 0, $boxes13 = 0, $vn_029 = 0, $b_028 = 0, $1 = 0, $call = 0, $lnot = 0, $2 = 0, $y6 = 0, $b_1 = 0, $cmp2 = 0, $3 = 0, $y = 0, $4 = 0.0, $5 = 0.0, $cmp7 = 0, $inc = 0, $6 = 0, $cmp11 = 0, $7 = 0, $y15 = 0, $8 = 0.0, $y18 = 0, $9 = 0.0, $cmp19 = 0, $label = 0, $10 = 0, $tobool24 = 0, $x = 0, $11 = 0.0, $conv29 = 0, $x53 = 0, $12 = 0.0, $conv34 = 0, $rw = 0, $13 = 0.0, $add = 0.0, $conv40 = 0, $add54 = 0.0, $div = 0.0, $conv55 = 0, $conv60 = 0, $list = 0, $14 = 0, $15 = 0, $vn_0_in = 0, $vn_0 = 0, $node_type = 0, $16 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $vn_0_in24 = $e + 12 | 0;
+ $vn_025 = HEAP32[$vn_0_in24 >> 2] | 0;
+ $node_type26 = $vn_025 + 162 | 0;
+ $0 = HEAP8[$node_type26] | 0;
+ $cmp27 = $0 << 24 >> 24 == 1;
+ if ($cmp27) {
+ label = 3;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 3:
+ $boxes = $p + 84 | 0;
+ $nbox = $p + 80 | 0;
+ $boxes13 = $p + 84 | 0;
+ $b_028 = 0;
+ $vn_029 = $vn_025;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[1055] | 0;
+ $call = FUNCTION_TABLE_ii[$1 & 1023]($vn_029) | 0;
+ $lnot = $call << 24 >> 24 == 0;
+ if ($lnot) {
+ label = 5;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 5:
+ $2 = HEAP32[$nbox >> 2] | 0;
+ $y6 = $vn_029 + 40 | 0;
+ $b_1 = $b_028;
+ label = 6;
+ break;
+ case 6:
+ $cmp2 = ($b_1 | 0) < ($2 | 0);
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $3 = HEAP32[$boxes >> 2] | 0;
+ $y = $3 + ($b_1 << 5) + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $5 = +HEAPF64[$y6 >> 3];
+ $cmp7 = $4 > $5;
+ $inc = $b_1 + 1 | 0;
+ if ($cmp7) {
+ $b_1 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $6 = HEAP32[$nbox >> 2] | 0;
+ $cmp11 = ($b_1 | 0) < ($6 | 0);
+ if ($cmp11) {
+ label = 9;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 9:
+ $7 = HEAP32[$boxes13 >> 2] | 0;
+ $y15 = $7 + ($b_1 << 5) + 24 | 0;
+ $8 = +HEAPF64[$y15 >> 3];
+ $y18 = $vn_029 + 40 | 0;
+ $9 = +HEAPF64[$y18 >> 3];
+ $cmp19 = $8 < $9;
+ if ($cmp19) {
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $label = $vn_029 + 120 | 0;
+ $10 = HEAP32[$label >> 2] | 0;
+ $tobool24 = ($10 | 0) == 0;
+ $x = $7 + ($b_1 << 5) | 0;
+ $11 = +HEAPF64[$x >> 3];
+ $conv29 = ~~$11;
+ $x53 = $7 + ($b_1 << 5) + 16 | 0;
+ $12 = +HEAPF64[$x53 >> 3];
+ if ($tobool24) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $conv34 = ~~$12;
+ $rw = $vn_029 + 112 | 0;
+ $13 = +HEAPF64[$rw >> 3];
+ $add = $12 + $13;
+ $conv40 = ~~$add;
+ _resize_vn($vn_029, $conv29, $conv34, $conv40);
+ label = 13;
+ break;
+ case 12:
+ $add54 = $11 + $12;
+ $div = $add54 * .5;
+ $conv55 = ~~$div;
+ $conv60 = ~~$12;
+ _resize_vn($vn_029, $conv29, $conv55, $conv60);
+ label = 13;
+ break;
+ case 13:
+ $list = $vn_029 + 184 | 0;
+ $14 = HEAP32[$list >> 2] | 0;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $vn_0_in = $15 + 12 | 0;
+ $vn_0 = HEAP32[$vn_0_in >> 2] | 0;
+ $node_type = $vn_0 + 162 | 0;
+ $16 = HEAP8[$node_type] | 0;
+ $cmp = $16 << 24 >> 24 == 1;
+ if ($cmp) {
+ $b_028 = $b_1;
+ $vn_029 = $vn_0;
+ label = 4;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ return;
+ }
+}
+function _top_bound($e, $side) {
+ $e = $e | 0;
+ $side = $side | 0;
+ var $tail = 0, $0 = 0, $list11 = 0, $1 = 0, $2 = 0, $tobool12 = 0, $head2 = 0, $3 = 0, $order4 = 0, $4 = 0, $5 = 0, $list = 0, $6 = 0, $7 = 0, $i_014 = 0, $ans_013 = 0, $head = 0, $8 = 0, $order = 0, $9 = 0, $sub = 0, $mul = 0, $cmp = 0, $spl = 0, $10 = 0, $cmp6 = 0, $to_orig = 0, $11 = 0, $cmp8 = 0, $spl12 = 0, $12 = 0, $cmp13 = 0, $cmp16 = 0, $head18 = 0, $13 = 0, $order20 = 0, $14 = 0, $15 = 0, $order23 = 0, $16 = 0, $sub24 = 0, $mul25 = 0, $cmp26 = 0, $ans_1 = 0, $inc = 0, $arrayidx = 0, $17 = 0, $tobool = 0, $ans_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $list11 = $0 + 184 | 0;
+ $1 = HEAP32[$list11 >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool12 = ($2 | 0) == 0;
+ if ($tobool12) {
+ $ans_0_lcssa = 0;
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $head2 = $e + 12 | 0;
+ $3 = HEAP32[$head2 >> 2] | 0;
+ $order4 = $3 + 240 | 0;
+ $4 = HEAP32[$order4 >> 2] | 0;
+ $5 = HEAP32[$tail >> 2] | 0;
+ $list = $5 + 184 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $ans_013 = 0;
+ $i_014 = 0;
+ $7 = $2;
+ label = 4;
+ break;
+ case 4:
+ $head = $7 + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $order = $8 + 240 | 0;
+ $9 = HEAP32[$order >> 2] | 0;
+ $sub = $9 - $4 | 0;
+ $mul = Math_imul($sub, $side);
+ $cmp = ($mul | 0) < 1;
+ if ($cmp) {
+ $ans_1 = $ans_013;
+ label = 11;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $spl = $7 + 24 | 0;
+ $10 = HEAP32[$spl >> 2] | 0;
+ $cmp6 = ($10 | 0) == 0;
+ if ($cmp6) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $to_orig = $7 + 132 | 0;
+ $11 = HEAP32[$to_orig >> 2] | 0;
+ $cmp8 = ($11 | 0) == 0;
+ if ($cmp8) {
+ $ans_1 = $ans_013;
+ label = 11;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $spl12 = $11 + 24 | 0;
+ $12 = HEAP32[$spl12 >> 2] | 0;
+ $cmp13 = ($12 | 0) == 0;
+ if ($cmp13) {
+ $ans_1 = $ans_013;
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp16 = ($ans_013 | 0) == 0;
+ if ($cmp16) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $head18 = $ans_013 + 12 | 0;
+ $13 = HEAP32[$head18 >> 2] | 0;
+ $order20 = $13 + 240 | 0;
+ $14 = HEAP32[$order20 >> 2] | 0;
+ $15 = HEAP32[$head >> 2] | 0;
+ $order23 = $15 + 240 | 0;
+ $16 = HEAP32[$order23 >> 2] | 0;
+ $sub24 = $14 - $16 | 0;
+ $mul25 = Math_imul($sub24, $side);
+ $cmp26 = ($mul25 | 0) > 0;
+ if ($cmp26) {
+ label = 10;
+ break;
+ } else {
+ $ans_1 = $ans_013;
+ label = 11;
+ break;
+ }
+ case 10:
+ $ans_1 = $7;
+ label = 11;
+ break;
+ case 11:
+ $inc = $i_014 + 1 | 0;
+ $arrayidx = $6 + ($inc << 2) | 0;
+ $17 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($17 | 0) == 0;
+ if ($tobool) {
+ $ans_0_lcssa = $ans_1;
+ label = 12;
+ break;
+ } else {
+ $ans_013 = $ans_1;
+ $i_014 = $inc;
+ $7 = $17;
+ label = 4;
+ break;
+ }
+ case 12:
+ return $ans_0_lcssa | 0;
+ }
+ return 0;
+}
+function _bot_bound($e, $side) {
+ $e = $e | 0;
+ $side = $side | 0;
+ var $head = 0, $0 = 0, $list11 = 0, $1 = 0, $2 = 0, $tobool12 = 0, $tail2 = 0, $3 = 0, $order4 = 0, $4 = 0, $5 = 0, $list = 0, $6 = 0, $7 = 0, $i_014 = 0, $ans_013 = 0, $tail = 0, $8 = 0, $order = 0, $9 = 0, $sub = 0, $mul = 0, $cmp = 0, $spl = 0, $10 = 0, $cmp6 = 0, $to_orig = 0, $11 = 0, $cmp8 = 0, $spl12 = 0, $12 = 0, $cmp13 = 0, $cmp16 = 0, $tail18 = 0, $13 = 0, $order20 = 0, $14 = 0, $15 = 0, $order23 = 0, $16 = 0, $sub24 = 0, $mul25 = 0, $cmp26 = 0, $ans_1 = 0, $inc = 0, $arrayidx = 0, $17 = 0, $tobool = 0, $ans_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $head = $e + 12 | 0;
+ $0 = HEAP32[$head >> 2] | 0;
+ $list11 = $0 + 176 | 0;
+ $1 = HEAP32[$list11 >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool12 = ($2 | 0) == 0;
+ if ($tobool12) {
+ $ans_0_lcssa = 0;
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail2 = $e + 16 | 0;
+ $3 = HEAP32[$tail2 >> 2] | 0;
+ $order4 = $3 + 240 | 0;
+ $4 = HEAP32[$order4 >> 2] | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $list = $5 + 176 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $ans_013 = 0;
+ $i_014 = 0;
+ $7 = $2;
+ label = 4;
+ break;
+ case 4:
+ $tail = $7 + 16 | 0;
+ $8 = HEAP32[$tail >> 2] | 0;
+ $order = $8 + 240 | 0;
+ $9 = HEAP32[$order >> 2] | 0;
+ $sub = $9 - $4 | 0;
+ $mul = Math_imul($sub, $side);
+ $cmp = ($mul | 0) < 1;
+ if ($cmp) {
+ $ans_1 = $ans_013;
+ label = 11;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $spl = $7 + 24 | 0;
+ $10 = HEAP32[$spl >> 2] | 0;
+ $cmp6 = ($10 | 0) == 0;
+ if ($cmp6) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $to_orig = $7 + 132 | 0;
+ $11 = HEAP32[$to_orig >> 2] | 0;
+ $cmp8 = ($11 | 0) == 0;
+ if ($cmp8) {
+ $ans_1 = $ans_013;
+ label = 11;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $spl12 = $11 + 24 | 0;
+ $12 = HEAP32[$spl12 >> 2] | 0;
+ $cmp13 = ($12 | 0) == 0;
+ if ($cmp13) {
+ $ans_1 = $ans_013;
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp16 = ($ans_013 | 0) == 0;
+ if ($cmp16) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $tail18 = $ans_013 + 16 | 0;
+ $13 = HEAP32[$tail18 >> 2] | 0;
+ $order20 = $13 + 240 | 0;
+ $14 = HEAP32[$order20 >> 2] | 0;
+ $15 = HEAP32[$tail >> 2] | 0;
+ $order23 = $15 + 240 | 0;
+ $16 = HEAP32[$order23 >> 2] | 0;
+ $sub24 = $14 - $16 | 0;
+ $mul25 = Math_imul($sub24, $side);
+ $cmp26 = ($mul25 | 0) > 0;
+ if ($cmp26) {
+ label = 10;
+ break;
+ } else {
+ $ans_1 = $ans_013;
+ label = 11;
+ break;
+ }
+ case 10:
+ $ans_1 = $7;
+ label = 11;
+ break;
+ case 11:
+ $inc = $i_014 + 1 | 0;
+ $arrayidx = $6 + ($inc << 2) | 0;
+ $17 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($17 | 0) == 0;
+ if ($tobool) {
+ $ans_0_lcssa = $ans_1;
+ label = 12;
+ break;
+ } else {
+ $ans_013 = $ans_1;
+ $i_014 = $inc;
+ $7 = $17;
+ label = 4;
+ break;
+ }
+ case 12:
+ return $ans_0_lcssa | 0;
+ }
+ return 0;
+}
+function _adjustregularpath($P, $fb, $lb) {
+ $P = $P | 0;
+ $fb = $fb | 0;
+ $lb = $lb | 0;
+ var $sub = 0, $add = 0, $cmp59 = 0, $boxes = 0, $nbox = 0, $0 = 0, $sub4656 = 0, $cmp4757 = 0, $boxes50 = 0, $i_060 = 0, $1 = 0, $sub1 = 0, $rem54 = 0, $cmp2 = 0, $x3 = 0, $2 = 0.0, $x4 = 0, $3 = 0.0, $cmp5 = 0, $add11 = 0.0, $div = 0.0, $conv = 0, $sub12 = 0, $conv13 = 0.0, $add16 = 0, $conv17 = 0.0, $add22 = 0.0, $x24 = 0, $4 = 0.0, $cmp25 = 0, $add32 = 0.0, $div33 = 0.0, $conv34 = 0, $sub35 = 0, $conv36 = 0.0, $add39 = 0, $conv40 = 0.0, $inc = 0, $cmp = 0, $i_158 = 0, $5 = 0, $arrayidx51 = 0, $add52 = 0, $arrayidx54 = 0, $cmp55 = 0, $cmp57 = 0, $or_cond = 0, $sub60 = 0, $rem6153 = 0, $cmp62 = 0, $x66 = 0, $6 = 0.0, $add67 = 0.0, $x69 = 0, $7 = 0.0, $cmp70 = 0, $x80 = 0, $8 = 0.0, $sub81 = 0.0, $x83 = 0, $9 = 0.0, $cmp84 = 0, $cmp95 = 0, $cmp98 = 0, $or_cond55 = 0, $10 = 0, $sub46 = 0, $cmp47 = 0, $sub102 = 0, $rem10352 = 0, $cmp104 = 0, $x108 = 0, $11 = 0.0, $add109 = 0.0, $x111 = 0, $12 = 0.0, $cmp112 = 0, $sub117 = 0.0, $x122 = 0, $13 = 0.0, $sub123 = 0.0, $x125 = 0, $14 = 0.0, $cmp126 = 0, $add131 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub = $fb - 1 | 0;
+ $add = $lb + 1 | 0;
+ $cmp59 = ($sub | 0) < ($add | 0);
+ if ($cmp59) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $boxes = $P + 84 | 0;
+ $i_060 = $sub;
+ label = 6;
+ break;
+ case 4:
+ $nbox = $P + 80 | 0;
+ $0 = HEAP32[$nbox >> 2] | 0;
+ $sub4656 = $0 - 1 | 0;
+ $cmp4757 = ($sub4656 | 0) > 0;
+ if ($cmp4757) {
+ label = 5;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 5:
+ $boxes50 = $P + 84 | 0;
+ $i_158 = 0;
+ label = 12;
+ break;
+ case 6:
+ $1 = HEAP32[$boxes >> 2] | 0;
+ $sub1 = $i_060 - $fb | 0;
+ $rem54 = $sub1 & 1;
+ $cmp2 = ($rem54 | 0) == 0;
+ $x3 = $1 + ($i_060 << 5) | 0;
+ $2 = +HEAPF64[$x3 >> 3];
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 7:
+ $x4 = $1 + ($i_060 << 5) + 16 | 0;
+ $3 = +HEAPF64[$x4 >> 3];
+ $cmp5 = $2 < $3;
+ if ($cmp5) {
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $add11 = $2 + $3;
+ $div = $add11 * .5;
+ $conv = ~~$div;
+ $sub12 = $conv - 8 | 0;
+ $conv13 = +($sub12 | 0);
+ HEAPF64[$x3 >> 3] = $conv13;
+ $add16 = $conv + 8 | 0;
+ $conv17 = +($add16 | 0);
+ HEAPF64[$x4 >> 3] = $conv17;
+ label = 11;
+ break;
+ case 9:
+ $add22 = $2 + 16.0;
+ $x24 = $1 + ($i_060 << 5) + 16 | 0;
+ $4 = +HEAPF64[$x24 >> 3];
+ $cmp25 = $add22 > $4;
+ if ($cmp25) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $add32 = $2 + $4;
+ $div33 = $add32 * .5;
+ $conv34 = ~~$div33;
+ $sub35 = $conv34 - 8 | 0;
+ $conv36 = +($sub35 | 0);
+ HEAPF64[$x3 >> 3] = $conv36;
+ $add39 = $conv34 + 8 | 0;
+ $conv40 = +($add39 | 0);
+ HEAPF64[$x24 >> 3] = $conv40;
+ label = 11;
+ break;
+ case 11:
+ $inc = $i_060 + 1 | 0;
+ $cmp = ($inc | 0) < ($add | 0);
+ if ($cmp) {
+ $i_060 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 12:
+ $5 = HEAP32[$boxes50 >> 2] | 0;
+ $arrayidx51 = $5 + ($i_158 << 5) | 0;
+ $add52 = $i_158 + 1 | 0;
+ $arrayidx54 = $5 + ($add52 << 5) | 0;
+ $cmp55 = ($i_158 | 0) < ($fb | 0);
+ $cmp57 = ($i_158 | 0) > ($lb | 0);
+ $or_cond = $cmp55 | $cmp57;
+ if ($or_cond) {
+ label = 18;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $sub60 = $i_158 - $fb | 0;
+ $rem6153 = $sub60 & 1;
+ $cmp62 = ($rem6153 | 0) == 0;
+ if ($cmp62) {
+ label = 14;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 14:
+ $x66 = $arrayidx51 | 0;
+ $6 = +HEAPF64[$x66 >> 3];
+ $add67 = $6 + 16.0;
+ $x69 = $5 + ($add52 << 5) + 16 | 0;
+ $7 = +HEAPF64[$x69 >> 3];
+ $cmp70 = $add67 > $7;
+ if ($cmp70) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ HEAPF64[$x69 >> 3] = $add67;
+ label = 16;
+ break;
+ case 16:
+ $x80 = $5 + ($i_158 << 5) + 16 | 0;
+ $8 = +HEAPF64[$x80 >> 3];
+ $sub81 = $8 + -16.0;
+ $x83 = $arrayidx54 | 0;
+ $9 = +HEAPF64[$x83 >> 3];
+ $cmp84 = $sub81 < $9;
+ if ($cmp84) {
+ label = 17;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 17:
+ HEAPF64[$x83 >> 3] = $sub81;
+ label = 19;
+ break;
+ case 18:
+ $cmp95 = ($add52 | 0) >= ($fb | 0);
+ $cmp98 = ($i_158 | 0) < ($lb | 0);
+ $or_cond55 = $cmp95 & $cmp98;
+ if ($or_cond55) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $10 = HEAP32[$nbox >> 2] | 0;
+ $sub46 = $10 - 1 | 0;
+ $cmp47 = ($add52 | 0) < ($sub46 | 0);
+ if ($cmp47) {
+ $i_158 = $add52;
+ label = 12;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 20:
+ $sub102 = $add52 - $fb | 0;
+ $rem10352 = $sub102 & 1;
+ $cmp104 = ($rem10352 | 0) == 0;
+ if ($cmp104) {
+ label = 21;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 21:
+ $x108 = $arrayidx51 | 0;
+ $11 = +HEAPF64[$x108 >> 3];
+ $add109 = $11 + 16.0;
+ $x111 = $5 + ($add52 << 5) + 16 | 0;
+ $12 = +HEAPF64[$x111 >> 3];
+ $cmp112 = $add109 > $12;
+ if ($cmp112) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $sub117 = $12 + -16.0;
+ HEAPF64[$x108 >> 3] = $sub117;
+ label = 23;
+ break;
+ case 23:
+ $x122 = $5 + ($i_158 << 5) + 16 | 0;
+ $13 = +HEAPF64[$x122 >> 3];
+ $sub123 = $13 + -16.0;
+ $x125 = $arrayidx54 | 0;
+ $14 = +HEAPF64[$x125 >> 3];
+ $cmp126 = $sub123 < $14;
+ if ($cmp126) {
+ label = 24;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 24:
+ $add131 = $14 + 16.0;
+ HEAPF64[$x122 >> 3] = $add131;
+ label = 19;
+ break;
+ case 25:
+ return;
+ }
+}
+function _boxfof3015($agg_result, $llx, $lly, $urx, $ury) {
+ $agg_result = $agg_result | 0;
+ $llx = +$llx;
+ $lly = +$lly;
+ $urx = +$urx;
+ $ury = +$ury;
+ HEAPF64[$agg_result >> 3] = $llx;
+ HEAPF64[$agg_result + 8 >> 3] = $lly;
+ HEAPF64[$agg_result + 16 >> 3] = $urx;
+ HEAPF64[$agg_result + 24 >> 3] = $ury;
+ return;
+}
+function _cl_vninside($cl, $n) {
+ $cl = $cl | 0;
+ $n = $n | 0;
+ var $x = 0, $0 = 0.0, $x2 = 0, $1 = 0.0, $cmp = 0, $x8 = 0, $2 = 0.0, $cmp9 = 0, $y = 0, $3 = 0.0, $y15 = 0, $4 = 0.0, $cmp16 = 0, $y24 = 0, $5 = 0.0, $cmp25 = 0, $phitmp = 0, $6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $cl + 56 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x2 = $n + 32 | 0;
+ $1 = +HEAPF64[$x2 >> 3];
+ $cmp = $0 > $1;
+ if ($cmp) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x8 = $cl + 72 | 0;
+ $2 = +HEAPF64[$x8 >> 3];
+ $cmp9 = $1 > $2;
+ if ($cmp9) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $cl + 64 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $y15 = $n + 40 | 0;
+ $4 = +HEAPF64[$y15 >> 3];
+ $cmp16 = $3 > $4;
+ if ($cmp16) {
+ $6 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y24 = $cl + 80 | 0;
+ $5 = +HEAPF64[$y24 >> 3];
+ $cmp25 = $4 <= $5;
+ $phitmp = $cmp25 & 1;
+ $6 = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ return $6 | 0;
+ }
+ return 0;
+}
+function _pathscross($n0, $n1, $ie1, $oe1) {
+ $n0 = $n0 | 0;
+ $n1 = $n1 | 0;
+ $ie1 = $ie1 | 0;
+ $oe1 = $oe1 | 0;
+ var $order1 = 0, $0 = 0, $order3 = 0, $1 = 0, $cmp = 0, $size = 0, $2 = 0, $cmp5 = 0, $tobool = 0, $or_cond = 0, $list = 0, $3 = 0, $4 = 0, $head = 0, $5 = 0, $head23 = 0, $6 = 0, $cmp24 = 0, $order29 = 0, $7 = 0, $order31 = 0, $8 = 0, $cmp32 = 0, $cmp34 = 0, $size40 = 0, $9 = 0, $cmp41 = 0, $node_type = 0, $10 = 0, $cmp45 = 0, $list51 = 0, $11 = 0, $12 = 0, $size55 = 0, $13 = 0, $cmp56 = 0, $node_type60 = 0, $14 = 0, $cmp62 = 0, $list68 = 0, $15 = 0, $16 = 0, $head_1 = 0, $17 = 0, $head23_1 = 0, $18 = 0, $cmp24_1 = 0, $size72 = 0, $19 = 0, $cmp73 = 0, $tobool76 = 0, $or_cond29 = 0, $list80 = 0, $20 = 0, $21 = 0, $tail = 0, $22 = 0, $tail86 = 0, $23 = 0, $cmp87 = 0, $order92 = 0, $24 = 0, $order94 = 0, $25 = 0, $cmp95 = 0, $cmp97 = 0, $size103 = 0, $26 = 0, $cmp104 = 0, $node_type108 = 0, $27 = 0, $cmp110 = 0, $list116 = 0, $28 = 0, $29 = 0, $size120 = 0, $30 = 0, $cmp121 = 0, $node_type125 = 0, $31 = 0, $cmp127 = 0, $list133 = 0, $32 = 0, $33 = 0, $tail_1 = 0, $34 = 0, $tail86_1 = 0, $35 = 0, $cmp87_1 = 0, $retval_0 = 0, $order92_1 = 0, $36 = 0, $order94_1 = 0, $37 = 0, $cmp95_1 = 0, $cmp97_1 = 0, $retval = 0, $order29_1 = 0, $38 = 0, $order31_1 = 0, $39 = 0, $cmp32_1 = 0, $cmp34_1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $order1 = $n0 + 240 | 0;
+ $0 = HEAP32[$order1 >> 2] | 0;
+ $order3 = $n1 + 240 | 0;
+ $1 = HEAP32[$order3 >> 2] | 0;
+ $cmp = ($0 | 0) > ($1 | 0);
+ $size = $n0 + 188 | 0;
+ $2 = HEAP32[$size >> 2] | 0;
+ $cmp5 = ($2 | 0) != 1;
+ if ($cmp5) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tobool = ($oe1 | 0) == 0;
+ $or_cond = $cmp5 | $tobool;
+ if ($or_cond) {
+ label = 11;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $list = $n0 + 184 | 0;
+ $3 = HEAP32[$list >> 2] | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $head = $4 + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $head23 = $oe1 + 12 | 0;
+ $6 = HEAP32[$head23 >> 2] | 0;
+ $cmp24 = ($5 | 0) == ($6 | 0);
+ if ($cmp24) {
+ label = 11;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $order29 = $5 + 240 | 0;
+ $7 = HEAP32[$order29 >> 2] | 0;
+ $order31 = $6 + 240 | 0;
+ $8 = HEAP32[$order31 >> 2] | 0;
+ $cmp32 = ($7 | 0) > ($8 | 0);
+ $cmp34 = $cmp ^ $cmp32;
+ if ($cmp34) {
+ $retval_0 = 1;
+ label = 19;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $size40 = $5 + 188 | 0;
+ $9 = HEAP32[$size40 >> 2] | 0;
+ $cmp41 = ($9 | 0) == 1;
+ if ($cmp41) {
+ label = 7;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $node_type = $5 + 162 | 0;
+ $10 = HEAP8[$node_type] | 0;
+ $cmp45 = $10 << 24 >> 24 == 0;
+ if ($cmp45) {
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $list51 = $5 + 184 | 0;
+ $11 = HEAP32[$list51 >> 2] | 0;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $size55 = $6 + 188 | 0;
+ $13 = HEAP32[$size55 >> 2] | 0;
+ $cmp56 = ($13 | 0) == 1;
+ if ($cmp56) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $node_type60 = $6 + 162 | 0;
+ $14 = HEAP8[$node_type60] | 0;
+ $cmp62 = $14 << 24 >> 24 == 0;
+ if ($cmp62) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $list68 = $6 + 184 | 0;
+ $15 = HEAP32[$list68 >> 2] | 0;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $head_1 = $12 + 12 | 0;
+ $17 = HEAP32[$head_1 >> 2] | 0;
+ $head23_1 = $16 + 12 | 0;
+ $18 = HEAP32[$head23_1 >> 2] | 0;
+ $cmp24_1 = ($17 | 0) == ($18 | 0);
+ if ($cmp24_1) {
+ label = 11;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 11:
+ $size72 = $n0 + 180 | 0;
+ $19 = HEAP32[$size72 >> 2] | 0;
+ $cmp73 = ($19 | 0) != 1;
+ $tobool76 = ($ie1 | 0) == 0;
+ $or_cond29 = $cmp73 | $tobool76;
+ if ($or_cond29) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $list80 = $n0 + 176 | 0;
+ $20 = HEAP32[$list80 >> 2] | 0;
+ $21 = HEAP32[$20 >> 2] | 0;
+ $tail = $21 + 16 | 0;
+ $22 = HEAP32[$tail >> 2] | 0;
+ $tail86 = $ie1 + 16 | 0;
+ $23 = HEAP32[$tail86 >> 2] | 0;
+ $cmp87 = ($22 | 0) == ($23 | 0);
+ if ($cmp87) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $order92 = $22 + 240 | 0;
+ $24 = HEAP32[$order92 >> 2] | 0;
+ $order94 = $23 + 240 | 0;
+ $25 = HEAP32[$order94 >> 2] | 0;
+ $cmp95 = ($24 | 0) > ($25 | 0);
+ $cmp97 = $cmp ^ $cmp95;
+ if ($cmp97) {
+ $retval_0 = 1;
+ label = 19;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $size103 = $22 + 180 | 0;
+ $26 = HEAP32[$size103 >> 2] | 0;
+ $cmp104 = ($26 | 0) == 1;
+ if ($cmp104) {
+ label = 15;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 15:
+ $node_type108 = $22 + 162 | 0;
+ $27 = HEAP8[$node_type108] | 0;
+ $cmp110 = $27 << 24 >> 24 == 0;
+ if ($cmp110) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $list116 = $22 + 176 | 0;
+ $28 = HEAP32[$list116 >> 2] | 0;
+ $29 = HEAP32[$28 >> 2] | 0;
+ $size120 = $23 + 180 | 0;
+ $30 = HEAP32[$size120 >> 2] | 0;
+ $cmp121 = ($30 | 0) == 1;
+ if ($cmp121) {
+ label = 17;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 17:
+ $node_type125 = $23 + 162 | 0;
+ $31 = HEAP8[$node_type125] | 0;
+ $cmp127 = $31 << 24 >> 24 == 0;
+ if ($cmp127) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $list133 = $23 + 176 | 0;
+ $32 = HEAP32[$list133 >> 2] | 0;
+ $33 = HEAP32[$32 >> 2] | 0;
+ $tail_1 = $29 + 16 | 0;
+ $34 = HEAP32[$tail_1 >> 2] | 0;
+ $tail86_1 = $33 + 16 | 0;
+ $35 = HEAP32[$tail86_1 >> 2] | 0;
+ $cmp87_1 = ($34 | 0) == ($35 | 0);
+ if ($cmp87_1) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ return $retval_0 | 0;
+ case 20:
+ $order92_1 = $34 + 240 | 0;
+ $36 = HEAP32[$order92_1 >> 2] | 0;
+ $order94_1 = $35 + 240 | 0;
+ $37 = HEAP32[$order94_1 >> 2] | 0;
+ $cmp95_1 = ($36 | 0) > ($37 | 0);
+ $cmp97_1 = $cmp ^ $cmp95_1;
+ $retval = $cmp97_1 & 1;
+ return $retval | 0;
+ case 21:
+ $order29_1 = $17 + 240 | 0;
+ $38 = HEAP32[$order29_1 >> 2] | 0;
+ $order31_1 = $18 + 240 | 0;
+ $39 = HEAP32[$order31_1 >> 2] | 0;
+ $cmp32_1 = ($38 | 0) > ($39 | 0);
+ $cmp34_1 = $cmp ^ $cmp32_1;
+ if ($cmp34_1) {
+ $retval_0 = 1;
+ label = 19;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ }
+ return 0;
+}
+function _add_pointf3016($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $add4 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $add4 = +HEAPF64[$p + 8 >> 3] + +HEAPF64[$q + 8 >> 3];
+ HEAPF64[$agg_result >> 3] = +HEAPF64[$p >> 3] + +HEAPF64[$q >> 3];
+ HEAPF64[$agg_result + 8 >> 3] = $add4;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _leftOf($p1, $p2, $p3) {
+ $p1 = $p1 | 0;
+ $p2 = $p2 | 0;
+ $p3 = $p3 | 0;
+ var $1 = 0.0, $3 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p1;
+ $p1 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p1 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p1 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p1 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p1 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $p2;
+ $p2 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p2 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p2 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p2 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p2 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $p3;
+ $p3 = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p3 >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p3 + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p3 + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p3 + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $1 = +HEAPF64[$p2 + 8 >> 3];
+ $3 = +HEAPF64[$p2 >> 3];
+ STACKTOP = __stackBase__;
+ return (~~((+HEAPF64[$p1 + 8 >> 3] - $1) * (+HEAPF64[$p3 >> 3] - $3) - (+HEAPF64[$p3 + 8 >> 3] - $1) * (+HEAPF64[$p1 >> 3] - $3)) | 0) > 0 & 1 | 0;
+}
+function _neighbor($vn, $ie, $oe, $dir) {
+ $vn = $vn | 0;
+ $ie = $ie | 0;
+ $oe = $oe | 0;
+ $dir = $dir | 0;
+ var $rank1 = 0, $0 = 0, $graph = 0, $1 = 0, $rank3 = 0, $2 = 0, $order = 0, $3 = 0, $n5 = 0, $v = 0, $_pn = 0, $i_0 = 0, $cmp = 0, $4 = 0, $cmp6 = 0, $5 = 0, $arrayidx7 = 0, $6 = 0, $node_type = 0, $7 = 0, $cmp9 = 0, $label = 0, $8 = 0, $tobool = 0, $_pr = 0, $9 = 0, $cmp15 = 0, $call = 0, $cmp20 = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank1 = $vn + 236 | 0;
+ $0 = HEAP32[$rank1 >> 2] | 0;
+ $graph = $vn + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $rank3 = $1 + 224 | 0;
+ $2 = HEAP32[$rank3 >> 2] | 0;
+ $order = $vn + 240 | 0;
+ $3 = HEAP32[$order >> 2] | 0;
+ $n5 = $2 + ($0 * 44 & -1) | 0;
+ $v = $2 + ($0 * 44 & -1) + 4 | 0;
+ $_pn = $3;
+ label = 3;
+ break;
+ case 3:
+ $i_0 = $_pn + $dir | 0;
+ $cmp = ($i_0 | 0) > -1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $rv_0 = 0;
+ label = 10;
+ break;
+ }
+ case 4:
+ $4 = HEAP32[$n5 >> 2] | 0;
+ $cmp6 = ($i_0 | 0) < ($4 | 0);
+ if ($cmp6) {
+ label = 5;
+ break;
+ } else {
+ $rv_0 = 0;
+ label = 10;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[$v >> 2] | 0;
+ $arrayidx7 = $5 + ($i_0 << 2) | 0;
+ $6 = HEAP32[$arrayidx7 >> 2] | 0;
+ $node_type = $6 + 162 | 0;
+ $7 = HEAP8[$node_type] | 0;
+ $cmp9 = $7 << 24 >> 24 == 1;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ $9 = $7;
+ label = 8;
+ break;
+ }
+ case 6:
+ $label = $6 + 120 | 0;
+ $8 = HEAP32[$label >> 2] | 0;
+ $tobool = ($8 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $rv_0 = $6;
+ label = 10;
+ break;
+ }
+ case 7:
+ $_pr = HEAP8[$node_type] | 0;
+ $9 = $_pr;
+ label = 8;
+ break;
+ case 8:
+ $cmp15 = $9 << 24 >> 24 == 0;
+ if ($cmp15) {
+ $rv_0 = $6;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call = _pathscross($6, $vn, $ie, $oe) | 0;
+ $cmp20 = $call << 24 >> 24 == 0;
+ if ($cmp20) {
+ $rv_0 = $6;
+ label = 10;
+ break;
+ } else {
+ $_pn = $i_0;
+ label = 3;
+ break;
+ }
+ case 10:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _cl_bound($n, $adj) {
+ $n = $n | 0;
+ $adj = $adj | 0;
+ var $node_type = 0, $0 = 0, $cmp = 0, $clust = 0, $1 = 0, $list = 0, $2 = 0, $3 = 0, $to_orig = 0, $4 = 0, $tail = 0, $5 = 0, $clust6 = 0, $6 = 0, $head = 0, $7 = 0, $clust8 = 0, $8 = 0, $tcl_0 = 0, $hcl_0 = 0, $node_type10 = 0, $9 = 0, $cmp12 = 0, $clust16 = 0, $10 = 0, $tobool = 0, $cmp17 = 0, $or_cond = 0, $cmp20 = 0, $or_cond25 = 0, $_30 = 0, $list27 = 0, $11 = 0, $12 = 0, $to_orig30 = 0, $13 = 0, $tail31 = 0, $14 = 0, $clust33 = 0, $15 = 0, $tobool34 = 0, $cmp36 = 0, $or_cond26 = 0, $cmp39 = 0, $or_cond27 = 0, $call = 0, $tobool42 = 0, $head45 = 0, $16 = 0, $clust47 = 0, $17 = 0, $tobool48 = 0, $cmp50 = 0, $or_cond28 = 0, $cmp53 = 0, $or_cond29 = 0, $call56 = 0, $tobool57 = 0, $_ = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $n + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $clust = $n + 216 | 0;
+ $1 = HEAP32[$clust >> 2] | 0;
+ $hcl_0 = $1;
+ $tcl_0 = $1;
+ label = 5;
+ break;
+ case 4:
+ $list = $n + 184 | 0;
+ $2 = HEAP32[$list >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $to_orig = $3 + 132 | 0;
+ $4 = HEAP32[$to_orig >> 2] | 0;
+ $tail = $4 + 16 | 0;
+ $5 = HEAP32[$tail >> 2] | 0;
+ $clust6 = $5 + 216 | 0;
+ $6 = HEAP32[$clust6 >> 2] | 0;
+ $head = $4 + 12 | 0;
+ $7 = HEAP32[$head >> 2] | 0;
+ $clust8 = $7 + 216 | 0;
+ $8 = HEAP32[$clust8 >> 2] | 0;
+ $hcl_0 = $8;
+ $tcl_0 = $6;
+ label = 5;
+ break;
+ case 5:
+ $node_type10 = $adj + 162 | 0;
+ $9 = HEAP8[$node_type10] | 0;
+ $cmp12 = $9 << 24 >> 24 == 0;
+ if ($cmp12) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $clust16 = $adj + 216 | 0;
+ $10 = HEAP32[$clust16 >> 2] | 0;
+ $tobool = ($10 | 0) == 0;
+ $cmp17 = ($10 | 0) == ($tcl_0 | 0);
+ $or_cond = $tobool | $cmp17;
+ $cmp20 = ($10 | 0) == ($hcl_0 | 0);
+ $or_cond25 = $or_cond | $cmp20;
+ $_30 = $or_cond25 ? 0 : $10;
+ return $_30 | 0;
+ case 7:
+ $list27 = $adj + 184 | 0;
+ $11 = HEAP32[$list27 >> 2] | 0;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $to_orig30 = $12 + 132 | 0;
+ $13 = HEAP32[$to_orig30 >> 2] | 0;
+ $tail31 = $13 + 16 | 0;
+ $14 = HEAP32[$tail31 >> 2] | 0;
+ $clust33 = $14 + 216 | 0;
+ $15 = HEAP32[$clust33 >> 2] | 0;
+ $tobool34 = ($15 | 0) == 0;
+ $cmp36 = ($15 | 0) == ($tcl_0 | 0);
+ $or_cond26 = $tobool34 | $cmp36;
+ $cmp39 = ($15 | 0) == ($hcl_0 | 0);
+ $or_cond27 = $or_cond26 | $cmp39;
+ if ($or_cond27) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call = _cl_vninside($15, $adj) | 0;
+ $tobool42 = ($call | 0) == 0;
+ if ($tobool42) {
+ label = 9;
+ break;
+ } else {
+ $rv_0 = $15;
+ label = 11;
+ break;
+ }
+ case 9:
+ $head45 = $13 + 12 | 0;
+ $16 = HEAP32[$head45 >> 2] | 0;
+ $clust47 = $16 + 216 | 0;
+ $17 = HEAP32[$clust47 >> 2] | 0;
+ $tobool48 = ($17 | 0) == 0;
+ $cmp50 = ($17 | 0) == ($tcl_0 | 0);
+ $or_cond28 = $tobool48 | $cmp50;
+ $cmp53 = ($17 | 0) == ($hcl_0 | 0);
+ $or_cond29 = $or_cond28 | $cmp53;
+ if ($or_cond29) {
+ $rv_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call56 = _cl_vninside($17, $adj) | 0;
+ $tobool57 = ($call56 | 0) == 0;
+ $_ = $tobool57 ? 0 : $17;
+ return $_ | 0;
+ case 11:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _make_flat_adj_edges($edges, $ind, $cnt, $e0, $et) {
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $e0 = $e0 | 0;
+ $et = $et | 0;
+ var $del = 0, $tmp = 0, $tmp230 = 0, $cp = 0, $tmp246 = 0, $tmp262 = 0, $tmp273 = 0, $tmp282 = 0, $tmp298 = 0, $tail = 0, $0 = 0, $graph = 0, $1 = 0, $head = 0, $2 = 0, $cmp13 = 0, $labels_016 = 0, $ports_015 = 0, $i_014 = 0, $add = 0, $arrayidx = 0, $3 = 0, $label = 0, $4 = 0, $not_tobool = 0, $inc = 0, $labels_0_inc = 0, $defined = 0, $5 = 0, $tobool3 = 0, $defined5 = 0, $6 = 0, $tobool7 = 0, $ports_1 = 0, $inc10 = 0, $cmp = 0, $cmp11 = 0, $cmp14 = 0, $call = 0, $7 = 0, $call19 = 0, $8 = 0, $9 = 0, $call20 = 0, $x = 0, $10 = 0.0, $conv22 = 0, $x25 = 0, $11 = 0.0, $conv26 = 0, $rankdir = 0, $12 = 0, $and28 = 0, $tobool29 = 0, $_ = 0, $_2 = 0, $call37 = 0, $call42 = 0, $cmp4410 = 0, $hvye_012 = 0, $i_111 = 0, $add47 = 0, $arrayidx48 = 0, $e_0_in = 0, $e_0 = 0, $edge_type = 0, $13 = 0, $cmp52 = 0, $to_orig = 0, $tail58 = 0, $14 = 0, $cmp59 = 0, $call62 = 0, $call64 = 0, $auxe_0 = 0, $15 = 0, $alg = 0, $tobool67 = 0, $defined70 = 0, $16 = 0, $tobool71 = 0, $defined75 = 0, $17 = 0, $tobool76 = 0, $18 = 0, $alg79 = 0, $hvye_1 = 0, $inc82 = 0, $cmp44 = 0, $tobool84 = 0, $19 = 0, $20 = 0, $21 = 0, $call86 = 0, $22 = 0, $hvye_2 = 0, $23 = 0, $24 = 0, $index = 0, $25 = 0, $call88 = 0, $gvc = 0, $26 = 0, $gvc91 = 0, $27 = 0, $28 = 0, $x94 = 0, $x105 = 0, $29 = 0.0, $x108 = 0, $30 = 0.0, $add109 = 0.0, $div110 = 0.0, $conv111 = 0, $nlist = 0, $n_07 = 0, $tobool1148 = 0, $rw = 0, $x98 = 0, $31 = 0.0, $32 = 0.0, $lw = 0, $33 = 0.0, $sub = 0.0, $34 = 0.0, $add99 = 0.0, $add101 = 0.0, $div = 0.0, $conv102 = 0, $conv119 = 0.0, $conv122 = 0.0, $conv130 = 0.0, $conv134 = 0.0, $conv139 = 0.0, $n_09 = 0, $cmp116 = 0, $y = 0, $x125 = 0, $cmp127 = 0, $y133 = 0, $x137 = 0, $next = 0, $n_0 = 0, $tobool114 = 0, $35 = 0, $and151 = 0, $tobool152 = 0, $36 = 0.0, $y159 = 0, $37 = 0.0, $sub160 = 0.0, $x161 = 0, $y164 = 0, $38 = 0.0, $39 = 0.0, $add168 = 0.0, $y169 = 0, $40 = 0.0, $sub177 = 0.0, $x178 = 0, $y181 = 0, $41 = 0.0, $y184 = 0, $42 = 0.0, $sub185 = 0.0, $y186 = 0, $cmp1895 = 0, $43 = 0, $44 = 0, $45 = 0, $46 = 0, $47 = 0, $48 = 0, $arrayidx237 = 0, $arrayidx253 = 0, $49 = 0, $50 = 0, $arrayidx264 = 0, $51 = 0, $52 = 0, $arrayidx275 = 0, $53 = 0, $54 = 0, $bb = 0, $i_26 = 0, $add192 = 0, $arrayidx193 = 0, $e_1_in = 0, $e_1 = 0, $edge_type196 = 0, $55 = 0, $cmp198 = 0, $to_orig203 = 0, $alg206 = 0, $56 = 0, $57 = 0, $cmp207 = 0, $alg210 = 0, $58 = 0, $59 = 0, $lnot = 0, $and2121 = 0, $u209 = 0, $spl = 0, $60 = 0, $list = 0, $61 = 0, $size = 0, $62 = 0, $63 = 0, $call217 = 0, $sflag = 0, $64 = 0, $sflag218 = 0, $sp = 0, $sp219 = 0, $65 = 0, $and223 = 0, $66 = 0, $eflag = 0, $67 = 0, $eflag224 = 0, $ep = 0, $ep225 = 0, $68 = 0, $and229 = 0, $69 = 0, $list238 = 0, $70 = 0, $cmp2333 = 0, $list240 = 0, $j_04 = 0, $71 = 0, $arrayidx239 = 0, $72 = 0, $arrayidx241 = 0, $73 = 0, $and245 = 0, $74 = 0, $inc247 = 0, $75 = 0, $cmp249 = 0, $76 = 0, $arrayidx255 = 0, $77 = 0, $arrayidx257 = 0, $78 = 0, $and261 = 0, $79 = 0, $inc263 = 0, $80 = 0, $arrayidx266 = 0, $81 = 0, $arrayidx268 = 0, $82 = 0, $and272 = 0, $83 = 0, $inc274 = 0, $84 = 0, $arrayidx277 = 0, $85 = 0, $and281 = 0, $86 = 0, $cmp233 = 0, $label286 = 0, $87 = 0, $tobool287 = 0, $pos = 0, $label292 = 0, $88 = 0, $89 = 0, $pos293 = 0, $90 = 0, $and297 = 0, $91 = 0, $92 = 0, $set = 0, $93 = 0, $inc305 = 0, $cmp189 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 192 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $del = __stackBase__ | 0;
+ $tmp = __stackBase__ + 16 | 0;
+ $tmp230 = __stackBase__ + 32 | 0;
+ $cp = __stackBase__ + 48 | 0;
+ $tmp246 = __stackBase__ + 112 | 0;
+ $tmp262 = __stackBase__ + 128 | 0;
+ $tmp273 = __stackBase__ + 144 | 0;
+ $tmp282 = __stackBase__ + 160 | 0;
+ $tmp298 = __stackBase__ + 176 | 0;
+ $tail = $e0 + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $head = $e0 + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $cmp13 = ($cnt | 0) > 0;
+ if ($cmp13) {
+ $i_014 = 0;
+ $ports_015 = 0;
+ $labels_016 = 0;
+ label = 3;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $add = $i_014 + $ind | 0;
+ $arrayidx = $edges + ($add << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $label = $3 + 112 | 0;
+ $4 = HEAP32[$label >> 2] | 0;
+ $not_tobool = ($4 | 0) != 0;
+ $inc = $not_tobool & 1;
+ $labels_0_inc = $inc + $labels_016 | 0;
+ $defined = $3 + 60 | 0;
+ $5 = HEAP8[$defined] | 0;
+ $tobool3 = $5 << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $defined5 = $3 + 100 | 0;
+ $6 = HEAP8[$defined5] | 0;
+ $tobool7 = $6 << 24 >> 24 == 0;
+ if ($tobool7) {
+ $ports_1 = $ports_015;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $ports_1 = 1;
+ label = 6;
+ break;
+ case 6:
+ $inc10 = $i_014 + 1 | 0;
+ $cmp = ($inc10 | 0) < ($cnt | 0);
+ if ($cmp) {
+ $i_014 = $inc10;
+ $ports_015 = $ports_1;
+ $labels_016 = $labels_0_inc;
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp11 = ($ports_1 | 0) == 0;
+ if ($cmp11) {
+ label = 8;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ $cmp14 = ($labels_0_inc | 0) == 0;
+ if ($cmp14) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ _makeSimpleFlat($0, $2, $edges, $ind, $cnt, $et);
+ label = 48;
+ break;
+ case 10:
+ _makeSimpleFlatLabels($0, $2, $edges, $ind, $cnt, $et, $labels_0_inc);
+ label = 48;
+ break;
+ case 11:
+ $call = _cloneGraph($1) | 0;
+ $7 = $call;
+ $call19 = _agsubg($7, 125768) | 0;
+ $8 = $call19;
+ $9 = $call19 | 0;
+ $call20 = _agset($9, 117048, 111736) | 0;
+ $x = $2 + 32 | 0;
+ $10 = +HEAPF64[$x >> 3];
+ $conv22 = ~~$10;
+ $x25 = $0 + 32 | 0;
+ $11 = +HEAPF64[$x25 >> 3];
+ $conv26 = ~~$11;
+ $rankdir = $1 + 156 | 0;
+ $12 = HEAP32[$rankdir >> 2] | 0;
+ $and28 = $12 & 1;
+ $tobool29 = ($and28 | 0) == 0;
+ $_ = $tobool29 ? $2 : $0;
+ $_2 = $tobool29 ? $0 : $2;
+ $call37 = _cloneNode($8, $_2) | 0;
+ $call42 = _cloneNode($call, $_) | 0;
+ $cmp4410 = ($cnt | 0) > 0;
+ if ($cmp4410) {
+ $i_111 = 0;
+ $hvye_012 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 12:
+ $add47 = $i_111 + $ind | 0;
+ $arrayidx48 = $edges + ($add47 << 2) | 0;
+ $e_0_in = $arrayidx48;
+ label = 13;
+ break;
+ case 13:
+ $e_0 = HEAP32[$e_0_in >> 2] | 0;
+ $edge_type = $e_0 + 128 | 0;
+ $13 = HEAP8[$edge_type] | 0;
+ $cmp52 = $13 << 24 >> 24 == 0;
+ $to_orig = $e_0 + 132 | 0;
+ if ($cmp52) {
+ label = 14;
+ break;
+ } else {
+ $e_0_in = $to_orig;
+ label = 13;
+ break;
+ }
+ case 14:
+ $tail58 = $e_0 + 16 | 0;
+ $14 = HEAP32[$tail58 >> 2] | 0;
+ $cmp59 = ($14 | 0) == ($_2 | 0);
+ if ($cmp59) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $call62 = _cloneEdge3018($call, $call37, $call42, $e_0) | 0;
+ $auxe_0 = $call62;
+ label = 17;
+ break;
+ case 16:
+ $call64 = _cloneEdge3018($call, $call42, $call37, $e_0) | 0;
+ $auxe_0 = $call64;
+ label = 17;
+ break;
+ case 17:
+ $15 = $auxe_0 | 0;
+ $alg = $e_0 + 136 | 0;
+ HEAP32[$alg >> 2] = $15;
+ $tobool67 = ($hvye_012 | 0) == 0;
+ if ($tobool67) {
+ label = 18;
+ break;
+ } else {
+ $hvye_1 = $hvye_012;
+ label = 21;
+ break;
+ }
+ case 18:
+ $defined70 = $e_0 + 60 | 0;
+ $16 = HEAP8[$defined70] | 0;
+ $tobool71 = $16 << 24 >> 24 == 0;
+ if ($tobool71) {
+ label = 19;
+ break;
+ } else {
+ $hvye_1 = 0;
+ label = 21;
+ break;
+ }
+ case 19:
+ $defined75 = $e_0 + 100 | 0;
+ $17 = HEAP8[$defined75] | 0;
+ $tobool76 = $17 << 24 >> 24 == 0;
+ if ($tobool76) {
+ label = 20;
+ break;
+ } else {
+ $hvye_1 = $hvye_012;
+ label = 21;
+ break;
+ }
+ case 20:
+ $18 = $e_0 | 0;
+ $alg79 = $auxe_0 + 136 | 0;
+ HEAP32[$alg79 >> 2] = $18;
+ $hvye_1 = $auxe_0;
+ label = 21;
+ break;
+ case 21:
+ $inc82 = $i_111 + 1 | 0;
+ $cmp44 = ($inc82 | 0) < ($cnt | 0);
+ if ($cmp44) {
+ $i_111 = $inc82;
+ $hvye_012 = $hvye_1;
+ label = 12;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $tobool84 = ($hvye_1 | 0) == 0;
+ if ($tobool84) {
+ label = 23;
+ break;
+ } else {
+ $hvye_2 = $hvye_1;
+ label = 24;
+ break;
+ }
+ case 23:
+ $19 = $call;
+ $20 = $call37;
+ $21 = $call42;
+ $call86 = _agedge($19, $20, $21) | 0;
+ $22 = $call86;
+ $hvye_2 = $22;
+ label = 24;
+ break;
+ case 24:
+ $23 = $hvye_2 | 0;
+ $24 = HEAP32[41894] | 0;
+ $index = $24 + 8 | 0;
+ $25 = HEAP32[$index >> 2] | 0;
+ $call88 = _agxset($23, $25, 107384) | 0;
+ $gvc = $1 + 176 | 0;
+ $26 = HEAP32[$gvc >> 2] | 0;
+ $gvc91 = $call + 176 | 0;
+ HEAP32[$gvc91 >> 2] = $26;
+ $27 = $call;
+ _setEdgeType($27, $et);
+ _dot_init_node_edge($call);
+ $28 = $call;
+ _dot_rank($28, 0);
+ _dot_mincross($27, 0);
+ _dot_position($27, 0);
+ $x94 = $_2 + 32 | 0;
+ $x105 = $call37 + 32 | 0;
+ $29 = +HEAPF64[$x105 >> 3];
+ $x108 = $call42 + 32 | 0;
+ $30 = +HEAPF64[$x108 >> 3];
+ $add109 = $29 + $30;
+ $div110 = $add109 * .5;
+ $conv111 = ~~$div110;
+ $nlist = $call + 220 | 0;
+ $n_07 = HEAP32[$nlist >> 2] | 0;
+ $tobool1148 = ($n_07 | 0) == 0;
+ if ($tobool1148) {
+ label = 32;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $rw = $_2 + 112 | 0;
+ $x98 = $_ + 32 | 0;
+ $31 = +HEAPF64[$rw >> 3];
+ $32 = +HEAPF64[$x94 >> 3];
+ $lw = $_ + 104 | 0;
+ $33 = +HEAPF64[$x98 >> 3];
+ $sub = $32 - $31;
+ $34 = +HEAPF64[$lw >> 3];
+ $add99 = $sub + $33;
+ $add101 = $add99 + $34;
+ $div = $add101 * .5;
+ $conv102 = ~~$div;
+ $conv119 = +($conv22 | 0);
+ $conv122 = +($conv111 | 0);
+ $conv130 = +($conv26 | 0);
+ $conv134 = +($conv111 | 0);
+ $conv139 = +($conv102 | 0);
+ $n_09 = $n_07;
+ label = 26;
+ break;
+ case 26:
+ $cmp116 = ($n_09 | 0) == ($call37 | 0);
+ if ($cmp116) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $y = $n_09 + 40 | 0;
+ HEAPF64[$y >> 3] = $conv119;
+ $x125 = $n_09 + 32 | 0;
+ HEAPF64[$x125 >> 3] = $conv122;
+ label = 31;
+ break;
+ case 28:
+ $cmp127 = ($n_09 | 0) == ($call42 | 0);
+ $y133 = $n_09 + 40 | 0;
+ if ($cmp127) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ HEAPF64[$y133 >> 3] = $conv130;
+ $x137 = $n_09 + 32 | 0;
+ HEAPF64[$x137 >> 3] = $conv134;
+ label = 31;
+ break;
+ case 30:
+ HEAPF64[$y133 >> 3] = $conv139;
+ label = 31;
+ break;
+ case 31:
+ $next = $n_09 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool114 = ($n_0 | 0) == 0;
+ if ($tobool114) {
+ label = 32;
+ break;
+ } else {
+ $n_09 = $n_0;
+ label = 26;
+ break;
+ }
+ case 32:
+ _dot_sameports($call);
+ __dot_splines($call, 0);
+ _dotneato_postprocess($27);
+ $35 = HEAP32[$rankdir >> 2] | 0;
+ $and151 = $35 & 1;
+ $tobool152 = ($and151 | 0) == 0;
+ $36 = +HEAPF64[$x94 >> 3];
+ if ($tobool152) {
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $y159 = $call37 + 40 | 0;
+ $37 = +HEAPF64[$y159 >> 3];
+ $sub160 = $36 - $37;
+ $x161 = $del | 0;
+ HEAPF64[$x161 >> 3] = $sub160;
+ $y164 = $_2 + 40 | 0;
+ $38 = +HEAPF64[$y164 >> 3];
+ $39 = +HEAPF64[$x105 >> 3];
+ $add168 = $38 + $39;
+ $y169 = $del + 8 | 0;
+ HEAPF64[$y169 >> 3] = $add168;
+ label = 35;
+ break;
+ case 34:
+ $40 = +HEAPF64[$x105 >> 3];
+ $sub177 = $36 - $40;
+ $x178 = $del | 0;
+ HEAPF64[$x178 >> 3] = $sub177;
+ $y181 = $_2 + 40 | 0;
+ $41 = +HEAPF64[$y181 >> 3];
+ $y184 = $call37 + 40 | 0;
+ $42 = +HEAPF64[$y184 >> 3];
+ $sub185 = $41 - $42;
+ $y186 = $del + 8 | 0;
+ HEAPF64[$y186 >> 3] = $sub185;
+ label = 35;
+ break;
+ case 35:
+ $cmp1895 = ($cnt | 0) > 0;
+ if ($cmp1895) {
+ label = 36;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 36:
+ $43 = $tmp;
+ $44 = $tmp230;
+ $45 = $tmp298;
+ $46 = $1;
+ $47 = $tmp246;
+ $48 = $cp;
+ $arrayidx237 = $cp | 0;
+ $arrayidx253 = $cp + 16 | 0;
+ $49 = $tmp262;
+ $50 = $arrayidx253;
+ $arrayidx264 = $cp + 32 | 0;
+ $51 = $tmp273;
+ $52 = $arrayidx264;
+ $arrayidx275 = $cp + 48 | 0;
+ $53 = $arrayidx275;
+ $54 = $tmp282;
+ $bb = $1 + 56 | 0;
+ $i_26 = 0;
+ label = 37;
+ break;
+ case 37:
+ $add192 = $i_26 + $ind | 0;
+ $arrayidx193 = $edges + ($add192 << 2) | 0;
+ $e_1_in = $arrayidx193;
+ label = 38;
+ break;
+ case 38:
+ $e_1 = HEAP32[$e_1_in >> 2] | 0;
+ $edge_type196 = $e_1 + 128 | 0;
+ $55 = HEAP8[$edge_type196] | 0;
+ $cmp198 = $55 << 24 >> 24 == 0;
+ $to_orig203 = $e_1 + 132 | 0;
+ if ($cmp198) {
+ label = 39;
+ break;
+ } else {
+ $e_1_in = $to_orig203;
+ label = 38;
+ break;
+ }
+ case 39:
+ $alg206 = $e_1 + 136 | 0;
+ $56 = HEAP32[$alg206 >> 2] | 0;
+ $57 = $56;
+ $cmp207 = ($57 | 0) == ($hvye_2 | 0);
+ $alg210 = $56 + 136 | 0;
+ $58 = $alg210;
+ $59 = HEAP32[$58 >> 2] | 0;
+ $lnot = ($59 | 0) == 0;
+ $and2121 = $cmp207 & $lnot;
+ if ($and2121) {
+ label = 46;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $u209 = $56 + 24 | 0;
+ $spl = $u209;
+ $60 = HEAP32[$spl >> 2] | 0;
+ $list = $60 | 0;
+ $61 = HEAP32[$list >> 2] | 0;
+ $size = $61 + 4 | 0;
+ $62 = HEAP32[$size >> 2] | 0;
+ $63 = $e_1;
+ $call217 = _new_spline($63, $62) | 0;
+ $sflag = $61 + 8 | 0;
+ $64 = HEAP32[$sflag >> 2] | 0;
+ $sflag218 = $call217 + 8 | 0;
+ HEAP32[$sflag218 >> 2] = $64;
+ $sp = $call217 + 16 | 0;
+ $sp219 = $61 + 16 | 0;
+ $65 = HEAP32[$rankdir >> 2] | 0;
+ $and223 = $65 & 1;
+ _transformf($tmp, $sp219, $del, $and223);
+ $66 = $sp;
+ HEAP32[$66 >> 2] = HEAP32[$43 >> 2] | 0;
+ HEAP32[$66 + 4 >> 2] = HEAP32[$43 + 4 >> 2] | 0;
+ HEAP32[$66 + 8 >> 2] = HEAP32[$43 + 8 >> 2] | 0;
+ HEAP32[$66 + 12 >> 2] = HEAP32[$43 + 12 >> 2] | 0;
+ $eflag = $61 + 12 | 0;
+ $67 = HEAP32[$eflag >> 2] | 0;
+ $eflag224 = $call217 + 12 | 0;
+ HEAP32[$eflag224 >> 2] = $67;
+ $ep = $call217 + 32 | 0;
+ $ep225 = $61 + 32 | 0;
+ $68 = HEAP32[$rankdir >> 2] | 0;
+ $and229 = $68 & 1;
+ _transformf($tmp230, $ep225, $del, $and229);
+ $69 = $ep;
+ HEAP32[$69 >> 2] = HEAP32[$44 >> 2] | 0;
+ HEAP32[$69 + 4 >> 2] = HEAP32[$44 + 4 >> 2] | 0;
+ HEAP32[$69 + 8 >> 2] = HEAP32[$44 + 8 >> 2] | 0;
+ HEAP32[$69 + 12 >> 2] = HEAP32[$44 + 12 >> 2] | 0;
+ $list238 = $call217 | 0;
+ $70 = HEAP32[$size >> 2] | 0;
+ $cmp2333 = ($70 | 0) > 0;
+ if ($cmp2333) {
+ label = 41;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 41:
+ $list240 = $61 | 0;
+ $j_04 = 0;
+ label = 42;
+ break;
+ case 42:
+ $71 = HEAP32[$list238 >> 2] | 0;
+ $arrayidx239 = $71 + ($j_04 << 4) | 0;
+ $72 = HEAP32[$list240 >> 2] | 0;
+ $arrayidx241 = $72 + ($j_04 << 4) | 0;
+ $73 = HEAP32[$rankdir >> 2] | 0;
+ $and245 = $73 & 1;
+ _transformf($tmp246, $arrayidx241, $del, $and245);
+ $74 = $arrayidx239;
+ HEAP32[$74 >> 2] = HEAP32[$47 >> 2] | 0;
+ HEAP32[$74 + 4 >> 2] = HEAP32[$47 + 4 >> 2] | 0;
+ HEAP32[$74 + 8 >> 2] = HEAP32[$47 + 8 >> 2] | 0;
+ HEAP32[$74 + 12 >> 2] = HEAP32[$47 + 12 >> 2] | 0;
+ HEAP32[$48 >> 2] = HEAP32[$47 >> 2] | 0;
+ HEAP32[$48 + 4 >> 2] = HEAP32[$47 + 4 >> 2] | 0;
+ HEAP32[$48 + 8 >> 2] = HEAP32[$47 + 8 >> 2] | 0;
+ HEAP32[$48 + 12 >> 2] = HEAP32[$47 + 12 >> 2] | 0;
+ $inc247 = $j_04 + 1 | 0;
+ $75 = HEAP32[$size >> 2] | 0;
+ $cmp249 = ($inc247 | 0) < ($75 | 0);
+ if ($cmp249) {
+ label = 43;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 43:
+ $76 = HEAP32[$list238 >> 2] | 0;
+ $arrayidx255 = $76 + ($inc247 << 4) | 0;
+ $77 = HEAP32[$list240 >> 2] | 0;
+ $arrayidx257 = $77 + ($inc247 << 4) | 0;
+ $78 = HEAP32[$rankdir >> 2] | 0;
+ $and261 = $78 & 1;
+ _transformf($tmp262, $arrayidx257, $del, $and261);
+ $79 = $arrayidx255;
+ HEAP32[$79 >> 2] = HEAP32[$49 >> 2] | 0;
+ HEAP32[$79 + 4 >> 2] = HEAP32[$49 + 4 >> 2] | 0;
+ HEAP32[$79 + 8 >> 2] = HEAP32[$49 + 8 >> 2] | 0;
+ HEAP32[$79 + 12 >> 2] = HEAP32[$49 + 12 >> 2] | 0;
+ HEAP32[$50 >> 2] = HEAP32[$49 >> 2] | 0;
+ HEAP32[$50 + 4 >> 2] = HEAP32[$49 + 4 >> 2] | 0;
+ HEAP32[$50 + 8 >> 2] = HEAP32[$49 + 8 >> 2] | 0;
+ HEAP32[$50 + 12 >> 2] = HEAP32[$49 + 12 >> 2] | 0;
+ $inc263 = $j_04 + 2 | 0;
+ $80 = HEAP32[$list238 >> 2] | 0;
+ $arrayidx266 = $80 + ($inc263 << 4) | 0;
+ $81 = HEAP32[$list240 >> 2] | 0;
+ $arrayidx268 = $81 + ($inc263 << 4) | 0;
+ $82 = HEAP32[$rankdir >> 2] | 0;
+ $and272 = $82 & 1;
+ _transformf($tmp273, $arrayidx268, $del, $and272);
+ $83 = $arrayidx266;
+ HEAP32[$83 >> 2] = HEAP32[$51 >> 2] | 0;
+ HEAP32[$83 + 4 >> 2] = HEAP32[$51 + 4 >> 2] | 0;
+ HEAP32[$83 + 8 >> 2] = HEAP32[$51 + 8 >> 2] | 0;
+ HEAP32[$83 + 12 >> 2] = HEAP32[$51 + 12 >> 2] | 0;
+ HEAP32[$52 >> 2] = HEAP32[$51 >> 2] | 0;
+ HEAP32[$52 + 4 >> 2] = HEAP32[$51 + 4 >> 2] | 0;
+ HEAP32[$52 + 8 >> 2] = HEAP32[$51 + 8 >> 2] | 0;
+ HEAP32[$52 + 12 >> 2] = HEAP32[$51 + 12 >> 2] | 0;
+ $inc274 = $j_04 + 3 | 0;
+ $84 = HEAP32[$list240 >> 2] | 0;
+ $arrayidx277 = $84 + ($inc274 << 4) | 0;
+ $85 = HEAP32[$rankdir >> 2] | 0;
+ $and281 = $85 & 1;
+ _transformf($tmp282, $arrayidx277, $del, $and281);
+ HEAP32[$53 >> 2] = HEAP32[$54 >> 2] | 0;
+ HEAP32[$53 + 4 >> 2] = HEAP32[$54 + 4 >> 2] | 0;
+ HEAP32[$53 + 8 >> 2] = HEAP32[$54 + 8 >> 2] | 0;
+ HEAP32[$53 + 12 >> 2] = HEAP32[$54 + 12 >> 2] | 0;
+ _update_bb_bz($bb, $arrayidx237);
+ $86 = HEAP32[$size >> 2] | 0;
+ $cmp233 = ($inc274 | 0) < ($86 | 0);
+ if ($cmp233) {
+ $j_04 = $inc274;
+ label = 42;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $label286 = $e_1 + 112 | 0;
+ $87 = HEAP32[$label286 >> 2] | 0;
+ $tobool287 = ($87 | 0) == 0;
+ if ($tobool287) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $pos = $87 + 56 | 0;
+ $label292 = $56 + 112 | 0;
+ $88 = $label292;
+ $89 = HEAP32[$88 >> 2] | 0;
+ $pos293 = $89 + 56 | 0;
+ $90 = HEAP32[$rankdir >> 2] | 0;
+ $and297 = $90 & 1;
+ _transformf($tmp298, $pos293, $del, $and297);
+ $91 = $pos;
+ HEAP32[$91 >> 2] = HEAP32[$45 >> 2] | 0;
+ HEAP32[$91 + 4 >> 2] = HEAP32[$45 + 4 >> 2] | 0;
+ HEAP32[$91 + 8 >> 2] = HEAP32[$45 + 8 >> 2] | 0;
+ HEAP32[$91 + 12 >> 2] = HEAP32[$45 + 12 >> 2] | 0;
+ $92 = HEAP32[$label286 >> 2] | 0;
+ $set = $92 + 81 | 0;
+ HEAP8[$set] = 1;
+ $93 = HEAP32[$label286 >> 2] | 0;
+ _updateBB($46, $93);
+ label = 46;
+ break;
+ case 46:
+ $inc305 = $i_26 + 1 | 0;
+ $cmp189 = ($inc305 | 0) < ($cnt | 0);
+ if ($cmp189) {
+ $i_26 = $inc305;
+ label = 37;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ _cleanupCloneGraph($call);
+ label = 48;
+ break;
+ case 48:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _make_flat_labeled_edge($sp, $P, $e, $et) {
+ $sp = $sp | 0;
+ $P = $P | 0;
+ $e = $e | 0;
+ $et = $et | 0;
+ var $tend = 0, $hend = 0, $pn = 0, $points = 0, $startp = 0, $endp = 0, $tail = 0, $0 = 0, $head = 0, $1 = 0, $graph = 0, $2 = 0, $to_virt = 0, $3 = 0, $f_0 = 0, $to_virt2 = 0, $4 = 0, $tobool = 0, $tail5 = 0, $5 = 0, $label = 0, $6 = 0, $pos = 0, $coord = 0, $7 = 0, $8 = 0, $9 = 0, $set = 0, $cmp = 0, $coord11 = 0, $p = 0, $10 = 0, $coord14 = 0, $p16 = 0, $11 = 0, $12 = 0, $lp_sroa_0_0__idx1 = 0, $lp_sroa_0_0_copyload2 = 0.0, $lp_sroa_1_8__idx4 = 0, $lp_sroa_1_8_copyload5 = 0.0, $y = 0, $13 = 0.0, $div = 0.0, $sub = 0.0, $arrayidx = 0, $arrayidx24 = 0, $14 = 0, $15 = 0, $arrayidx25 = 0, $arrayidx26 = 0, $arrayidx27 = 0, $lp_sroa_0_0__idx = 0, $lp_sroa_1_8__idx3 = 0, $16 = 0, $17 = 0, $18 = 0, $arrayidx28 = 0, $arrayidx29 = 0, $19 = 0, $20 = 0, $x = 0, $21 = 0.0, $lw = 0, $22 = 0.0, $sub33 = 0.0, $rw = 0, $23 = 0.0, $add = 0.0, $y42 = 0, $24 = 0.0, $ht = 0, $25 = 0.0, $div44 = 0.0, $add45 = 0.0, $rank = 0, $26 = 0, $rank53 = 0, $27 = 0, $ht1 = 0, $28 = 0, $conv = 0.0, $sub55 = 0.0, $y58 = 0, $29 = 0.0, $sub59 = 0.0, $ht2 = 0, $30 = 0, $conv65 = 0.0, $add66 = 0.0, $conv67 = 0, $conv68 = 0.0, $div69 = 0.0, $conv70 = 0, $cmp74 = 0, $conv73 = 0.0, $cond = 0.0, $sub77 = 0.0, $boxn80 = 0, $31 = 0, $sub81 = 0, $x84 = 0, $32 = 0.0, $33 = 0, $sub89 = 0, $y93 = 0, $34 = 0.0, $35 = 0, $sub108 = 0, $x112 = 0, $36 = 0.0, $boxn121 = 0, $37 = 0, $sub122 = 0, $x126 = 0, $38 = 0.0, $39 = 0, $sub147 = 0, $y151 = 0, $40 = 0.0, $41 = 0, $sub156 = 0, $x160 = 0, $42 = 0.0, $43 = 0, $cmp16772 = 0, $i_073 = 0, $arrayidx171 = 0, $inc173 = 0, $44 = 0, $cmp167 = 0, $45 = 0, $cmp18669 = 0, $i_270_in = 0, $i_270 = 0, $arrayidx190 = 0, $cmp186 = 0, $cmp193 = 0, $call = 0, $call197 = 0, $ps_0 = 0, $46 = 0, $cmp198 = 0, $ps_1 = 0, $47 = 0, $48 = 0, $49 = 0, $50 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1544 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tend = __stackBase__ | 0;
+ $hend = __stackBase__ + 696 | 0;
+ $pn = __stackBase__ + 1392 | 0;
+ $points = __stackBase__ + 1400 | 0;
+ $startp = __stackBase__ + 1512 | 0;
+ $endp = __stackBase__ + 1528 | 0;
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $head = $e + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $to_virt = $e + 188 | 0;
+ $3 = HEAP32[$to_virt >> 2] | 0;
+ $f_0 = $3;
+ label = 3;
+ break;
+ case 3:
+ $to_virt2 = $f_0 + 188 | 0;
+ $4 = HEAP32[$to_virt2 >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $f_0 = $4;
+ label = 3;
+ break;
+ }
+ case 4:
+ $tail5 = $f_0 + 16 | 0;
+ $5 = HEAP32[$tail5 >> 2] | 0;
+ $label = $e + 112 | 0;
+ $6 = HEAP32[$label >> 2] | 0;
+ $pos = $6 + 56 | 0;
+ $coord = $5 + 32 | 0;
+ $7 = $pos;
+ $8 = $coord;
+ HEAP32[$7 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$7 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$7 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$7 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ $9 = HEAP32[$label >> 2] | 0;
+ $set = $9 + 81 | 0;
+ HEAP8[$set] = 1;
+ $cmp = ($et | 0) == 2;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $coord11 = $0 + 32 | 0;
+ $p = $e + 32 | 0;
+ _add_pointf3016($startp, $coord11, $p);
+ $10 = $startp;
+ $coord14 = $1 + 32 | 0;
+ $p16 = $e + 72 | 0;
+ _add_pointf3016($endp, $coord14, $p16);
+ $11 = $endp;
+ $12 = HEAP32[$label >> 2] | 0;
+ $lp_sroa_0_0__idx1 = $12 + 56 | 0;
+ $lp_sroa_0_0_copyload2 = +HEAPF64[$lp_sroa_0_0__idx1 >> 3];
+ $lp_sroa_1_8__idx4 = $12 + 64 | 0;
+ $lp_sroa_1_8_copyload5 = +HEAPF64[$lp_sroa_1_8__idx4 >> 3];
+ $y = $12 + 32 | 0;
+ $13 = +HEAPF64[$y >> 3];
+ $div = $13 * .5;
+ $sub = $lp_sroa_1_8_copyload5 - $div;
+ $arrayidx = $points + 16 | 0;
+ $arrayidx24 = $points | 0;
+ $14 = $points;
+ HEAP32[$14 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $15 = $arrayidx;
+ HEAP32[$15 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$15 + 4 >> 2] = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$15 + 8 >> 2] = HEAP32[$10 + 8 >> 2] | 0;
+ HEAP32[$15 + 12 >> 2] = HEAP32[$10 + 12 >> 2] | 0;
+ $arrayidx25 = $points + 32 | 0;
+ $arrayidx26 = $points + 48 | 0;
+ $arrayidx27 = $points + 64 | 0;
+ $lp_sroa_0_0__idx = $points + 64 | 0;
+ HEAPF64[$lp_sroa_0_0__idx >> 3] = $lp_sroa_0_0_copyload2;
+ $lp_sroa_1_8__idx3 = $points + 72 | 0;
+ HEAPF64[$lp_sroa_1_8__idx3 >> 3] = $sub;
+ $16 = $arrayidx26;
+ $17 = $arrayidx27;
+ HEAP32[$16 >> 2] = HEAP32[$17 >> 2] | 0;
+ HEAP32[$16 + 4 >> 2] = HEAP32[$17 + 4 >> 2] | 0;
+ HEAP32[$16 + 8 >> 2] = HEAP32[$17 + 8 >> 2] | 0;
+ HEAP32[$16 + 12 >> 2] = HEAP32[$17 + 12 >> 2] | 0;
+ $18 = $arrayidx25;
+ HEAP32[$18 >> 2] = HEAP32[$17 >> 2] | 0;
+ HEAP32[$18 + 4 >> 2] = HEAP32[$17 + 4 >> 2] | 0;
+ HEAP32[$18 + 8 >> 2] = HEAP32[$17 + 8 >> 2] | 0;
+ HEAP32[$18 + 12 >> 2] = HEAP32[$17 + 12 >> 2] | 0;
+ $arrayidx28 = $points + 80 | 0;
+ $arrayidx29 = $points + 96 | 0;
+ $19 = $arrayidx29;
+ HEAP32[$19 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$19 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$19 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$19 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ $20 = $arrayidx28;
+ HEAP32[$20 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$20 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$20 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$20 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ HEAP32[$pn >> 2] = 7;
+ $ps_1 = $arrayidx24;
+ label = 16;
+ break;
+ case 6:
+ $x = $coord | 0;
+ $21 = +HEAPF64[$x >> 3];
+ $lw = $5 + 104 | 0;
+ $22 = +HEAPF64[$lw >> 3];
+ $sub33 = $21 - $22;
+ $rw = $5 + 112 | 0;
+ $23 = +HEAPF64[$rw >> 3];
+ $add = $21 + $23;
+ $y42 = $5 + 40 | 0;
+ $24 = +HEAPF64[$y42 >> 3];
+ $ht = $5 + 96 | 0;
+ $25 = +HEAPF64[$ht >> 3];
+ $div44 = $25 * .5;
+ $add45 = $24 + $div44;
+ $rank = $0 + 236 | 0;
+ $26 = HEAP32[$rank >> 2] | 0;
+ $rank53 = $2 + 224 | 0;
+ $27 = HEAP32[$rank53 >> 2] | 0;
+ $ht1 = $27 + ($26 * 44 & -1) + 16 | 0;
+ $28 = HEAP32[$ht1 >> 2] | 0;
+ $conv = +($28 | 0);
+ $sub55 = $24 - $conv;
+ $y58 = $0 + 40 | 0;
+ $29 = +HEAPF64[$y58 >> 3];
+ $sub59 = $sub55 - $29;
+ $ht2 = $27 + ($26 * 44 & -1) + 20 | 0;
+ $30 = HEAP32[$ht2 >> 2] | 0;
+ $conv65 = +($30 | 0);
+ $add66 = $sub59 + $conv65;
+ $conv67 = ~~$add66;
+ $conv68 = +($conv67 | 0);
+ $div69 = $conv68 / 6.0;
+ $conv70 = ~~$div69;
+ $cmp74 = ($conv70 | 0) < 5;
+ if ($cmp74) {
+ $cond = 5.0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $conv73 = +($conv70 | 0);
+ $cond = $conv73;
+ label = 8;
+ break;
+ case 8:
+ $sub77 = $add45 - $cond;
+ _makeFlatEnd($sp, $P, $0, $e, $tend, 1);
+ _makeFlatEnd($sp, $P, $1, $e, $hend, 0);
+ $boxn80 = $tend + 52 | 0;
+ $31 = HEAP32[$boxn80 >> 2] | 0;
+ $sub81 = $31 - 1 | 0;
+ $x84 = $tend + 56 + ($sub81 << 5) | 0;
+ $32 = +HEAPF64[$x84 >> 3];
+ HEAPF64[6678] = $32;
+ $33 = HEAP32[$boxn80 >> 2] | 0;
+ $sub89 = $33 - 1 | 0;
+ $y93 = $tend + 56 + ($sub89 << 5) + 24 | 0;
+ $34 = +HEAPF64[$y93 >> 3];
+ HEAPF64[6679] = $34;
+ HEAPF64[6680] = $sub33;
+ HEAPF64[6681] = $sub77;
+ $35 = HEAP32[$boxn80 >> 2] | 0;
+ $sub108 = $35 - 1 | 0;
+ $x112 = $tend + 56 + ($sub108 << 5) | 0;
+ $36 = +HEAPF64[$x112 >> 3];
+ HEAPF64[6682] = $36;
+ HEAPF64[6683] = $sub77;
+ $boxn121 = $hend + 52 | 0;
+ $37 = HEAP32[$boxn121 >> 2] | 0;
+ $sub122 = $37 - 1 | 0;
+ $x126 = $hend + 56 + ($sub122 << 5) + 16 | 0;
+ $38 = +HEAPF64[$x126 >> 3];
+ HEAPF64[6684] = $38;
+ HEAPF64[6685] = $add45;
+ HEAPF64[6686] = $add;
+ HEAPF64[6689] = $sub77;
+ $39 = HEAP32[$boxn121 >> 2] | 0;
+ $sub147 = $39 - 1 | 0;
+ $y151 = $hend + 56 + ($sub147 << 5) + 24 | 0;
+ $40 = +HEAPF64[$y151 >> 3];
+ HEAPF64[6687] = $40;
+ $41 = HEAP32[$boxn121 >> 2] | 0;
+ $sub156 = $41 - 1 | 0;
+ $x160 = $hend + 56 + ($sub156 << 5) + 16 | 0;
+ $42 = +HEAPF64[$x160 >> 3];
+ HEAPF64[6688] = $42;
+ $43 = HEAP32[$boxn80 >> 2] | 0;
+ $cmp16772 = ($43 | 0) > 0;
+ if ($cmp16772) {
+ $i_073 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $arrayidx171 = $tend + 56 + ($i_073 << 5) | 0;
+ _add_box($P, $arrayidx171);
+ $inc173 = $i_073 + 1 | 0;
+ $44 = HEAP32[$boxn80 >> 2] | 0;
+ $cmp167 = ($inc173 | 0) < ($44 | 0);
+ if ($cmp167) {
+ $i_073 = $inc173;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ _add_box($P, 53424);
+ _add_box($P, 53456);
+ _add_box($P, 53488);
+ $45 = HEAP32[$boxn121 >> 2] | 0;
+ $cmp18669 = ($45 | 0) > 0;
+ if ($cmp18669) {
+ $i_270_in = $45;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $i_270 = $i_270_in - 1 | 0;
+ $arrayidx190 = $hend + 56 + ($i_270 << 5) | 0;
+ _add_box($P, $arrayidx190);
+ $cmp186 = ($i_270 | 0) > 0;
+ if ($cmp186) {
+ $i_270_in = $i_270;
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $cmp193 = ($et | 0) == 8;
+ if ($cmp193) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $call = _routesplines($P, $pn) | 0;
+ $ps_0 = $call;
+ label = 15;
+ break;
+ case 14:
+ $call197 = _routepolylines($P, $pn) | 0;
+ $ps_0 = $call197;
+ label = 15;
+ break;
+ case 15:
+ $46 = HEAP32[$pn >> 2] | 0;
+ $cmp198 = ($46 | 0) == 0;
+ if ($cmp198) {
+ label = 17;
+ break;
+ } else {
+ $ps_1 = $ps_0;
+ label = 16;
+ break;
+ }
+ case 16:
+ $47 = HEAP32[$head >> 2] | 0;
+ $48 = HEAP32[$pn >> 2] | 0;
+ $49 = $e;
+ $50 = $47;
+ _clip_and_install($49, $50, $ps_1, $48, 4216);
+ label = 17;
+ break;
+ case 17:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _makeSimpleFlat($tn, $hn, $edges, $ind, $cnt, $et) {
+ $tn = $tn | 0;
+ $hn = $hn | 0;
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $et = $et | 0;
+ var $points = 0, $tmp = 0, $tmp6 = 0, $tmp31 = 0, $tmp39 = 0, $tmp53 = 0, $tmp61 = 0, $tmp69 = 0, $tmp77 = 0, $tmp85 = 0, $tmp93 = 0, $arrayidx = 0, $0 = 0, $coord = 0, $p = 0, $tp_sroa_0_0__idx52 = 0, $tp_sroa_0_0_copyload53 = 0.0, $tp_sroa_1_8__idx57 = 0, $tp_sroa_1_8_copyload58 = 0.0, $coord3 = 0, $p5 = 0, $hp_sroa_0_0__idx34 = 0, $hp_sroa_0_0_copyload35 = 0.0, $hp_sroa_1_8__idx41 = 0, $hp_sroa_1_8_copyload42 = 0.0, $cmp = 0, $ht = 0, $1 = 0.0, $sub = 0, $conv = 0.0, $div = 0.0, $div13 = 0.0, $cmp1872 = 0, $cond1677 = 0.0, $cond7076 = 0.0, $sub17 = 0.0, $arrayidx25 = 0, $tp_sroa_0_0__idx50 = 0, $tp_sroa_1_8__idx55 = 0, $arrayidx27 = 0, $tp_sroa_0_0__idx = 0, $tp_sroa_1_8__idx54 = 0, $arrayidx47 = 0, $mul49 = 0.0, $add51 = 0.0, $div52 = 0.0, $2 = 0, $3 = 0, $arrayidx55 = 0, $4 = 0, $5 = 0, $arrayidx63 = 0, $6 = 0, $7 = 0, $arrayidx71 = 0, $mul73 = 0.0, $add75 = 0.0, $div76 = 0.0, $8 = 0, $9 = 0, $arrayidx79 = 0, $10 = 0, $11 = 0, $arrayidx87 = 0, $12 = 0, $13 = 0, $hp_sroa_0_0__idx23 = 0, $hp_sroa_1_8__idx37 = 0, $hp_sroa_0_0__idx = 0, $hp_sroa_1_8__idx36 = 0, $mul = 0.0, $add29 = 0.0, $div30 = 0.0, $14 = 0, $15 = 0, $arrayidx33 = 0, $mul35 = 0.0, $add37 = 0.0, $div38 = 0.0, $16 = 0, $17 = 0, $hp_sroa_0_0__idx30 = 0, $hp_sroa_1_8__idx39 = 0, $dy_074 = 0.0, $i_073 = 0, $add = 0, $arrayidx20 = 0, $18 = 0, $pointn_0 = 0, $add98 = 0.0, $head = 0, $19 = 0, $20 = 0, $21 = 0, $inc99 = 0, $cmp18 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 320 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $points = __stackBase__ | 0;
+ $tmp = __stackBase__ + 160 | 0;
+ $tmp6 = __stackBase__ + 176 | 0;
+ $tmp31 = __stackBase__ + 192 | 0;
+ $tmp39 = __stackBase__ + 208 | 0;
+ $tmp53 = __stackBase__ + 224 | 0;
+ $tmp61 = __stackBase__ + 240 | 0;
+ $tmp69 = __stackBase__ + 256 | 0;
+ $tmp77 = __stackBase__ + 272 | 0;
+ $tmp85 = __stackBase__ + 288 | 0;
+ $tmp93 = __stackBase__ + 304 | 0;
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $coord = $tn + 32 | 0;
+ $p = $0 + 32 | 0;
+ _add_pointf3016($tmp, $coord, $p);
+ $tp_sroa_0_0__idx52 = $tmp | 0;
+ $tp_sroa_0_0_copyload53 = +HEAPF64[$tp_sroa_0_0__idx52 >> 3];
+ $tp_sroa_1_8__idx57 = $tmp + 8 | 0;
+ $tp_sroa_1_8_copyload58 = +HEAPF64[$tp_sroa_1_8__idx57 >> 3];
+ $coord3 = $hn + 32 | 0;
+ $p5 = $0 + 72 | 0;
+ _add_pointf3016($tmp6, $coord3, $p5);
+ $hp_sroa_0_0__idx34 = $tmp6 | 0;
+ $hp_sroa_0_0_copyload35 = +HEAPF64[$hp_sroa_0_0__idx34 >> 3];
+ $hp_sroa_1_8__idx41 = $tmp6 + 8 | 0;
+ $hp_sroa_1_8_copyload42 = +HEAPF64[$hp_sroa_1_8__idx41 >> 3];
+ $cmp = ($cnt | 0) > 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $ht = $tn + 96 | 0;
+ $1 = +HEAPF64[$ht >> 3];
+ $sub = $cnt - 1 | 0;
+ $conv = +($sub | 0);
+ $div = $1 / $conv;
+ $div13 = $1 * .5;
+ $cond7076 = $div;
+ $cond1677 = $div13;
+ label = 5;
+ break;
+ case 4:
+ $cmp1872 = ($cnt | 0) > 0;
+ if ($cmp1872) {
+ $cond7076 = 0.0;
+ $cond1677 = 0.0;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ $sub17 = $tp_sroa_1_8_copyload58 - $cond1677;
+ $arrayidx25 = $points | 0;
+ $tp_sroa_0_0__idx50 = $points | 0;
+ $tp_sroa_1_8__idx55 = $points + 8 | 0;
+ $arrayidx27 = $points + 16 | 0;
+ $tp_sroa_0_0__idx = $arrayidx27 | 0;
+ $tp_sroa_1_8__idx54 = $points + 24 | 0;
+ $arrayidx47 = $points + 32 | 0;
+ $mul49 = $tp_sroa_0_0_copyload53 * 2.0;
+ $add51 = $mul49 + $hp_sroa_0_0_copyload35;
+ $div52 = $add51 / 3.0;
+ $2 = $arrayidx47;
+ $3 = $tmp53;
+ $arrayidx55 = $points + 48 | 0;
+ $4 = $arrayidx55;
+ $5 = $tmp61;
+ $arrayidx63 = $points + 64 | 0;
+ $6 = $arrayidx63;
+ $7 = $tmp69;
+ $arrayidx71 = $points + 80 | 0;
+ $mul73 = $hp_sroa_0_0_copyload35 * 2.0;
+ $add75 = $tp_sroa_0_0_copyload53 + $mul73;
+ $div76 = $add75 / 3.0;
+ $8 = $arrayidx71;
+ $9 = $tmp77;
+ $arrayidx79 = $points + 96 | 0;
+ $10 = $arrayidx79;
+ $11 = $tmp85;
+ $arrayidx87 = $points + 112 | 0;
+ $12 = $arrayidx87;
+ $13 = $tmp93;
+ $hp_sroa_0_0__idx23 = $points + 128 | 0;
+ $hp_sroa_1_8__idx37 = $points + 136 | 0;
+ $hp_sroa_0_0__idx = $points + 144 | 0;
+ $hp_sroa_1_8__idx36 = $points + 152 | 0;
+ $mul = $tp_sroa_0_0_copyload53 * 2.0;
+ $add29 = $mul + $hp_sroa_0_0_copyload35;
+ $div30 = $add29 / 3.0;
+ $14 = $arrayidx27;
+ $15 = $tmp31;
+ $arrayidx33 = $points + 32 | 0;
+ $mul35 = $hp_sroa_0_0_copyload35 * 2.0;
+ $add37 = $tp_sroa_0_0_copyload53 + $mul35;
+ $div38 = $add37 / 3.0;
+ $16 = $arrayidx33;
+ $17 = $tmp39;
+ $hp_sroa_0_0__idx30 = $points + 48 | 0;
+ $hp_sroa_1_8__idx39 = $points + 56 | 0;
+ $i_073 = 0;
+ $dy_074 = $sub17;
+ label = 6;
+ break;
+ case 6:
+ $add = $i_073 + $ind | 0;
+ $arrayidx20 = $edges + ($add << 2) | 0;
+ $18 = HEAP32[$arrayidx20 >> 2] | 0;
+ HEAPF64[$tp_sroa_0_0__idx50 >> 3] = $tp_sroa_0_0_copyload53;
+ HEAPF64[$tp_sroa_1_8__idx55 >> 3] = $tp_sroa_1_8_copyload58;
+ if (($et | 0) == 8 | ($et | 0) == 2) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ _pointfof3017($tmp31, $div30, $dy_074);
+ HEAP32[$14 >> 2] = HEAP32[$15 >> 2] | 0;
+ HEAP32[$14 + 4 >> 2] = HEAP32[$15 + 4 >> 2] | 0;
+ HEAP32[$14 + 8 >> 2] = HEAP32[$15 + 8 >> 2] | 0;
+ HEAP32[$14 + 12 >> 2] = HEAP32[$15 + 12 >> 2] | 0;
+ _pointfof3017($tmp39, $div38, $dy_074);
+ HEAP32[$16 >> 2] = HEAP32[$17 >> 2] | 0;
+ HEAP32[$16 + 4 >> 2] = HEAP32[$17 + 4 >> 2] | 0;
+ HEAP32[$16 + 8 >> 2] = HEAP32[$17 + 8 >> 2] | 0;
+ HEAP32[$16 + 12 >> 2] = HEAP32[$17 + 12 >> 2] | 0;
+ HEAPF64[$hp_sroa_0_0__idx30 >> 3] = $hp_sroa_0_0_copyload35;
+ HEAPF64[$hp_sroa_1_8__idx39 >> 3] = $hp_sroa_1_8_copyload42;
+ $pointn_0 = 4;
+ label = 9;
+ break;
+ case 8:
+ HEAPF64[$tp_sroa_0_0__idx >> 3] = $tp_sroa_0_0_copyload53;
+ HEAPF64[$tp_sroa_1_8__idx54 >> 3] = $tp_sroa_1_8_copyload58;
+ _pointfof3017($tmp53, $div52, $dy_074);
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ _pointfof3017($tmp61, $div52, $dy_074);
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ _pointfof3017($tmp69, $div52, $dy_074);
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ _pointfof3017($tmp77, $div76, $dy_074);
+ HEAP32[$8 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$8 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$8 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$8 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ _pointfof3017($tmp85, $div76, $dy_074);
+ HEAP32[$10 >> 2] = HEAP32[$11 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$11 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$11 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$11 + 12 >> 2] | 0;
+ _pointfof3017($tmp93, $div76, $dy_074);
+ HEAP32[$12 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ HEAPF64[$hp_sroa_0_0__idx23 >> 3] = $hp_sroa_0_0_copyload35;
+ HEAPF64[$hp_sroa_1_8__idx37 >> 3] = $hp_sroa_1_8_copyload42;
+ HEAPF64[$hp_sroa_0_0__idx >> 3] = $hp_sroa_0_0_copyload35;
+ HEAPF64[$hp_sroa_1_8__idx36 >> 3] = $hp_sroa_1_8_copyload42;
+ $pointn_0 = 10;
+ label = 9;
+ break;
+ case 9:
+ $add98 = $cond7076 + $dy_074;
+ $head = $18 + 12 | 0;
+ $19 = HEAP32[$head >> 2] | 0;
+ $20 = $18;
+ $21 = $19;
+ _clip_and_install($20, $21, $arrayidx25, $pointn_0, 4216);
+ $inc99 = $i_073 + 1 | 0;
+ $cmp18 = ($inc99 | 0) < ($cnt | 0);
+ if ($cmp18) {
+ $i_073 = $inc99;
+ $dy_074 = $add98;
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _pointfof3017($agg_result, $x, $y) {
+ $agg_result = $agg_result | 0;
+ $x = +$x;
+ $y = +$y;
+ HEAPF64[$agg_result >> 3] = $x;
+ HEAPF64[$agg_result + 8 >> 3] = $y;
+ return;
+}
+function _make_flat_bottom_edges($sp, $P, $edges, $ind, $cnt, $e, $splines) {
+ $sp = $sp | 0;
+ $P = $P | 0;
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $e = $e | 0;
+ $splines = $splines | 0;
+ var $pn = 0, $tend = 0, $hend = 0, $tail = 0, $0 = 0, $head = 0, $1 = 0, $graph = 0, $2 = 0, $rank = 0, $3 = 0, $maxrank = 0, $4 = 0, $conv = 0, $cmp = 0, $rank4 = 0, $5 = 0, $add = 0, $y = 0, $6 = 0.0, $pht1 = 0, $7 = 0, $conv8 = 0.0, $sub = 0.0, $v = 0, $8 = 0, $9 = 0, $y12 = 0, $10 = 0.0, $pht2 = 0, $11 = 0, $conv13 = 0.0, $add14 = 0.0, $sub15 = 0.0, $ranksep = 0, $12 = 0, $conv17 = 0.0, $vspace_0 = 0.0, $Multisep = 0, $13 = 0, $conv18 = 0.0, $add19 = 0, $conv20 = 0.0, $div = 0.0, $div23 = 0.0, $cmp2478 = 0, $boxn28 = 0, $boxn71 = 0, $tobool = 0, $nbox = 0, $i_079 = 0, $add26 = 0, $arrayidx27 = 0, $14 = 0, $15 = 0, $sub29 = 0, $b_sroa_0_0__idx1 = 0, $b_sroa_0_0_copyload2 = 0.0, $b_sroa_1_8__idx5 = 0, $b_sroa_1_8_copyload6 = 0.0, $b_sroa_2_16__idx10 = 0, $b_sroa_2_16_copyload11 = 0.0, $add40 = 0, $conv41 = 0.0, $mul = 0.0, $add42 = 0.0, $mul50 = 0.0, $sub51 = 0.0, $16 = 0, $sub56 = 0, $x60 = 0, $17 = 0.0, $18 = 0.0, $19 = 0, $sub72 = 0, $x76 = 0, $20 = 0.0, $21 = 0.0, $sub83 = 0.0, $22 = 0, $sub89 = 0, $b_sroa_0_0__idx = 0, $b_sroa_0_0_copyload = 0.0, $b_sroa_1_8__idx4 = 0, $b_sroa_1_8_copyload = 0.0, $b_sroa_2_16__idx9 = 0, $b_sroa_2_16_copyload = 0.0, $sub107 = 0.0, $23 = 0.0, $24 = 0, $cmp12172 = 0, $j_073 = 0, $arrayidx125 = 0, $inc126 = 0, $25 = 0, $cmp121 = 0, $26 = 0, $cmp13876 = 0, $j_277_in = 0, $j_277 = 0, $arrayidx142 = 0, $cmp138 = 0, $call = 0, $call147 = 0, $ps_0 = 0, $27 = 0, $cmp149 = 0, $head153 = 0, $28 = 0, $29 = 0, $30 = 0, $cmp24 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1400 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pn = __stackBase__ | 0;
+ $tend = __stackBase__ + 8 | 0;
+ $hend = __stackBase__ + 704 | 0;
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $head = $e + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $rank = $0 + 236 | 0;
+ $3 = HEAP32[$rank >> 2] | 0;
+ $maxrank = $2 + 250 | 0;
+ $4 = HEAP16[$maxrank >> 1] | 0;
+ $conv = $4 << 16 >> 16;
+ $cmp = ($3 | 0) < ($conv | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $rank4 = $2 + 224 | 0;
+ $5 = HEAP32[$rank4 >> 2] | 0;
+ $add = $3 + 1 | 0;
+ $y = $0 + 40 | 0;
+ $6 = +HEAPF64[$y >> 3];
+ $pht1 = $5 + ($3 * 44 & -1) + 24 | 0;
+ $7 = HEAP32[$pht1 >> 2] | 0;
+ $conv8 = +($7 | 0);
+ $sub = $6 - $conv8;
+ $v = $5 + ($add * 44 & -1) + 4 | 0;
+ $8 = HEAP32[$v >> 2] | 0;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $y12 = $9 + 40 | 0;
+ $10 = +HEAPF64[$y12 >> 3];
+ $pht2 = $5 + ($add * 44 & -1) + 28 | 0;
+ $11 = HEAP32[$pht2 >> 2] | 0;
+ $conv13 = +($11 | 0);
+ $add14 = $10 + $conv13;
+ $sub15 = $sub - $add14;
+ $vspace_0 = $sub15;
+ label = 5;
+ break;
+ case 4:
+ $ranksep = $2 + 264 | 0;
+ $12 = HEAP32[$ranksep >> 2] | 0;
+ $conv17 = +($12 | 0);
+ $vspace_0 = $conv17;
+ label = 5;
+ break;
+ case 5:
+ $Multisep = $sp + 12 | 0;
+ $13 = HEAP32[$Multisep >> 2] | 0;
+ $conv18 = +($13 | 0);
+ $add19 = $cnt + 1 | 0;
+ $conv20 = +($add19 | 0);
+ $div = $conv18 / $conv20;
+ $div23 = $vspace_0 / $conv20;
+ _makeBottomFlatEnd($sp, $P, $0, $e, $tend, 1);
+ _makeBottomFlatEnd($sp, $P, $1, $e, $hend, 0);
+ $cmp2478 = ($cnt | 0) > 0;
+ if ($cmp2478) {
+ label = 6;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 6:
+ $boxn28 = $tend + 52 | 0;
+ $boxn71 = $hend + 52 | 0;
+ $tobool = ($splines | 0) == 0;
+ $nbox = $P + 80 | 0;
+ $i_079 = 0;
+ label = 7;
+ break;
+ case 7:
+ $add26 = $i_079 + $ind | 0;
+ $arrayidx27 = $edges + ($add26 << 2) | 0;
+ $14 = HEAP32[$arrayidx27 >> 2] | 0;
+ $15 = HEAP32[$boxn28 >> 2] | 0;
+ $sub29 = $15 - 1 | 0;
+ $b_sroa_0_0__idx1 = $tend + 56 + ($sub29 << 5) | 0;
+ $b_sroa_0_0_copyload2 = +HEAPF64[$b_sroa_0_0__idx1 >> 3];
+ $b_sroa_1_8__idx5 = $tend + 56 + ($sub29 << 5) + 8 | 0;
+ $b_sroa_1_8_copyload6 = +HEAPF64[$b_sroa_1_8__idx5 >> 3];
+ $b_sroa_2_16__idx10 = $tend + 56 + ($sub29 << 5) + 16 | 0;
+ $b_sroa_2_16_copyload11 = +HEAPF64[$b_sroa_2_16__idx10 >> 3];
+ HEAPF64[6678] = $b_sroa_0_0_copyload2;
+ HEAPF64[6681] = $b_sroa_1_8_copyload6;
+ $add40 = $i_079 + 1 | 0;
+ $conv41 = +($add40 | 0);
+ $mul = $div * $conv41;
+ $add42 = $mul + $b_sroa_2_16_copyload11;
+ HEAPF64[6680] = $add42;
+ $mul50 = $div23 * $conv41;
+ $sub51 = $b_sroa_1_8_copyload6 - $mul50;
+ HEAPF64[6679] = $sub51;
+ $16 = HEAP32[$boxn28 >> 2] | 0;
+ $sub56 = $16 - 1 | 0;
+ $x60 = $tend + 56 + ($sub56 << 5) | 0;
+ $17 = +HEAPF64[$x60 >> 3];
+ HEAPF64[6682] = $17;
+ $18 = +HEAPF64[6679];
+ HEAPF64[6685] = $18;
+ $19 = HEAP32[$boxn71 >> 2] | 0;
+ $sub72 = $19 - 1 | 0;
+ $x76 = $hend + 56 + ($sub72 << 5) + 16 | 0;
+ $20 = +HEAPF64[$x76 >> 3];
+ HEAPF64[6684] = $20;
+ $21 = +HEAPF64[6685];
+ $sub83 = $21 - $div23;
+ HEAPF64[6683] = $sub83;
+ $22 = HEAP32[$boxn71 >> 2] | 0;
+ $sub89 = $22 - 1 | 0;
+ $b_sroa_0_0__idx = $hend + 56 + ($sub89 << 5) | 0;
+ $b_sroa_0_0_copyload = +HEAPF64[$b_sroa_0_0__idx >> 3];
+ $b_sroa_1_8__idx4 = $hend + 56 + ($sub89 << 5) + 8 | 0;
+ $b_sroa_1_8_copyload = +HEAPF64[$b_sroa_1_8__idx4 >> 3];
+ $b_sroa_2_16__idx9 = $hend + 56 + ($sub89 << 5) + 16 | 0;
+ $b_sroa_2_16_copyload = +HEAPF64[$b_sroa_2_16__idx9 >> 3];
+ HEAPF64[6688] = $b_sroa_2_16_copyload;
+ HEAPF64[6689] = $b_sroa_1_8_copyload;
+ $sub107 = $b_sroa_0_0_copyload - $mul;
+ HEAPF64[6686] = $sub107;
+ $23 = +HEAPF64[6685];
+ HEAPF64[6687] = $23;
+ $24 = HEAP32[$boxn28 >> 2] | 0;
+ $cmp12172 = ($24 | 0) > 0;
+ if ($cmp12172) {
+ $j_073 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $arrayidx125 = $tend + 56 + ($j_073 << 5) | 0;
+ _add_box($P, $arrayidx125);
+ $inc126 = $j_073 + 1 | 0;
+ $25 = HEAP32[$boxn28 >> 2] | 0;
+ $cmp121 = ($inc126 | 0) < ($25 | 0);
+ if ($cmp121) {
+ $j_073 = $inc126;
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ _add_box($P, 53424);
+ _add_box($P, 53456);
+ _add_box($P, 53488);
+ $26 = HEAP32[$boxn71 >> 2] | 0;
+ $cmp13876 = ($26 | 0) > 0;
+ if ($cmp13876) {
+ $j_277_in = $26;
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $j_277 = $j_277_in - 1 | 0;
+ $arrayidx142 = $hend + 56 + ($j_277 << 5) | 0;
+ _add_box($P, $arrayidx142);
+ $cmp138 = ($j_277 | 0) > 0;
+ if ($cmp138) {
+ $j_277_in = $j_277;
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ if ($tobool) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call = _routesplines($P, $pn) | 0;
+ $ps_0 = $call;
+ label = 14;
+ break;
+ case 13:
+ $call147 = _routepolylines($P, $pn) | 0;
+ $ps_0 = $call147;
+ label = 14;
+ break;
+ case 14:
+ $27 = HEAP32[$pn >> 2] | 0;
+ $cmp149 = ($27 | 0) == 0;
+ if ($cmp149) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $head153 = $14 + 12 | 0;
+ $28 = HEAP32[$head153 >> 2] | 0;
+ $29 = $14;
+ $30 = $28;
+ _clip_and_install($29, $30, $ps_0, $27, 4216);
+ HEAP32[$nbox >> 2] = 0;
+ $cmp24 = ($add40 | 0) < ($cnt | 0);
+ if ($cmp24) {
+ $i_079 = $add40;
+ label = 7;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _makeFlatEnd($sp, $P, $n, $e, $endp, $isBegin) {
+ $sp = $sp | 0;
+ $P = $P | 0;
+ $n = $n | 0;
+ $e = $e | 0;
+ $endp = $endp | 0;
+ $isBegin = $isBegin | 0;
+ var $b = 0, $tmp = 0, $tmp16 = 0, $graph = 0, $0 = 0, $1 = 0, $2 = 0, $3 = 0, $sidemask = 0, $tobool = 0, $4 = 0, $boxn = 0, $5 = 0, $sub = 0, $y = 0, $6 = 0.0, $y2 = 0, $7 = 0, $sub4 = 0, $y7 = 0, $8 = 0.0, $y9 = 0, $y10 = 0, $9 = 0.0, $rank = 0, $10 = 0, $rank13 = 0, $11 = 0, $ht2 = 0, $12 = 0, $conv = 0.0, $add = 0.0, $conv15 = 0, $13 = 0, $x = 0, $14 = 0.0, $x19 = 0, $15 = 0.0, $cmp = 0, $16 = 0.0, $17 = 0.0, $cmp25 = 0, $18 = 0, $inc = 0, $arrayidx30 = 0, $19 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 96 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $b = __stackBase__ | 0;
+ $tmp = __stackBase__ + 32 | 0;
+ $tmp16 = __stackBase__ + 64 | 0;
+ $graph = $n + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ _maximal_bbox($tmp, $sp, $n, 0, $e);
+ $1 = $endp;
+ $2 = $tmp;
+ HEAP32[$1 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ HEAP32[$1 + 16 >> 2] = HEAP32[$2 + 16 >> 2] | 0;
+ HEAP32[$1 + 20 >> 2] = HEAP32[$2 + 20 >> 2] | 0;
+ HEAP32[$1 + 24 >> 2] = HEAP32[$2 + 24 >> 2] | 0;
+ HEAP32[$1 + 28 >> 2] = HEAP32[$2 + 28 >> 2] | 0;
+ $3 = $b;
+ HEAP32[$3 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ HEAP32[$3 + 16 >> 2] = HEAP32[$2 + 16 >> 2] | 0;
+ HEAP32[$3 + 20 >> 2] = HEAP32[$2 + 20 >> 2] | 0;
+ HEAP32[$3 + 24 >> 2] = HEAP32[$2 + 24 >> 2] | 0;
+ HEAP32[$3 + 28 >> 2] = HEAP32[$2 + 28 >> 2] | 0;
+ $sidemask = $endp + 48 | 0;
+ HEAP32[$sidemask >> 2] = 4;
+ $tobool = $isBegin << 24 >> 24 == 0;
+ $4 = $e;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _beginpath($P, $4, 2, $endp, 0);
+ label = 5;
+ break;
+ case 4:
+ _endpath($P, $4, 2, $endp, 0);
+ label = 5;
+ break;
+ case 5:
+ $boxn = $endp + 52 | 0;
+ $5 = HEAP32[$boxn >> 2] | 0;
+ $sub = $5 - 1 | 0;
+ $y = $endp + 56 + ($sub << 5) + 24 | 0;
+ $6 = +HEAPF64[$y >> 3];
+ $y2 = $b + 24 | 0;
+ HEAPF64[$y2 >> 3] = $6;
+ $7 = HEAP32[$boxn >> 2] | 0;
+ $sub4 = $7 - 1 | 0;
+ $y7 = $endp + 56 + ($sub4 << 5) + 8 | 0;
+ $8 = +HEAPF64[$y7 >> 3];
+ $y9 = $b + 8 | 0;
+ HEAPF64[$y9 >> 3] = $8;
+ $y10 = $n + 40 | 0;
+ $9 = +HEAPF64[$y10 >> 3];
+ $rank = $n + 236 | 0;
+ $10 = HEAP32[$rank >> 2] | 0;
+ $rank13 = $0 + 224 | 0;
+ $11 = HEAP32[$rank13 >> 2] | 0;
+ $ht2 = $11 + ($10 * 44 & -1) + 20 | 0;
+ $12 = HEAP32[$ht2 >> 2] | 0;
+ $conv = +($12 | 0);
+ $add = $9 + $conv;
+ $conv15 = ~~$add;
+ _makeregularend($tmp16, $b, 4, $conv15);
+ $13 = $tmp16;
+ HEAP32[$3 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ HEAP32[$3 + 16 >> 2] = HEAP32[$13 + 16 >> 2] | 0;
+ HEAP32[$3 + 20 >> 2] = HEAP32[$13 + 20 >> 2] | 0;
+ HEAP32[$3 + 24 >> 2] = HEAP32[$13 + 24 >> 2] | 0;
+ HEAP32[$3 + 28 >> 2] = HEAP32[$13 + 28 >> 2] | 0;
+ $x = $b | 0;
+ $14 = +HEAPF64[$x >> 3];
+ $x19 = $b + 16 | 0;
+ $15 = +HEAPF64[$x19 >> 3];
+ $cmp = $14 < $15;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $16 = +HEAPF64[$y9 >> 3];
+ $17 = +HEAPF64[$y2 >> 3];
+ $cmp25 = $16 < $17;
+ if ($cmp25) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $18 = HEAP32[$boxn >> 2] | 0;
+ $inc = $18 + 1 | 0;
+ HEAP32[$boxn >> 2] = $inc;
+ $arrayidx30 = $endp + 56 + ($18 << 5) | 0;
+ $19 = $arrayidx30;
+ HEAP32[$19 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$19 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$19 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$19 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ HEAP32[$19 + 16 >> 2] = HEAP32[$3 + 16 >> 2] | 0;
+ HEAP32[$19 + 20 >> 2] = HEAP32[$3 + 20 >> 2] | 0;
+ HEAP32[$19 + 24 >> 2] = HEAP32[$3 + 24 >> 2] | 0;
+ HEAP32[$19 + 28 >> 2] = HEAP32[$3 + 28 >> 2] | 0;
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _makeBottomFlatEnd($sp, $P, $n, $e, $endp, $isBegin) {
+ $sp = $sp | 0;
+ $P = $P | 0;
+ $n = $n | 0;
+ $e = $e | 0;
+ $endp = $endp | 0;
+ $isBegin = $isBegin | 0;
+ var $b = 0, $tmp = 0, $tmp17 = 0, $graph = 0, $0 = 0, $1 = 0, $2 = 0, $3 = 0, $sidemask = 0, $tobool = 0, $4 = 0, $boxn = 0, $5 = 0, $sub = 0, $y = 0, $6 = 0.0, $y2 = 0, $7 = 0, $sub4 = 0, $y7 = 0, $8 = 0.0, $y9 = 0, $y10 = 0, $9 = 0.0, $rank = 0, $10 = 0, $rank13 = 0, $11 = 0, $ht2 = 0, $12 = 0, $conv = 0.0, $sub15 = 0.0, $conv16 = 0, $13 = 0, $x = 0, $14 = 0.0, $x20 = 0, $15 = 0.0, $cmp = 0, $16 = 0.0, $17 = 0.0, $cmp26 = 0, $18 = 0, $inc = 0, $arrayidx31 = 0, $19 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 96 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $b = __stackBase__ | 0;
+ $tmp = __stackBase__ + 32 | 0;
+ $tmp17 = __stackBase__ + 64 | 0;
+ $graph = $n + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ _maximal_bbox($tmp, $sp, $n, 0, $e);
+ $1 = $endp;
+ $2 = $tmp;
+ HEAP32[$1 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ HEAP32[$1 + 16 >> 2] = HEAP32[$2 + 16 >> 2] | 0;
+ HEAP32[$1 + 20 >> 2] = HEAP32[$2 + 20 >> 2] | 0;
+ HEAP32[$1 + 24 >> 2] = HEAP32[$2 + 24 >> 2] | 0;
+ HEAP32[$1 + 28 >> 2] = HEAP32[$2 + 28 >> 2] | 0;
+ $3 = $b;
+ HEAP32[$3 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ HEAP32[$3 + 16 >> 2] = HEAP32[$2 + 16 >> 2] | 0;
+ HEAP32[$3 + 20 >> 2] = HEAP32[$2 + 20 >> 2] | 0;
+ HEAP32[$3 + 24 >> 2] = HEAP32[$2 + 24 >> 2] | 0;
+ HEAP32[$3 + 28 >> 2] = HEAP32[$2 + 28 >> 2] | 0;
+ $sidemask = $endp + 48 | 0;
+ HEAP32[$sidemask >> 2] = 1;
+ $tobool = $isBegin << 24 >> 24 == 0;
+ $4 = $e;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _beginpath($P, $4, 2, $endp, 0);
+ label = 5;
+ break;
+ case 4:
+ _endpath($P, $4, 2, $endp, 0);
+ label = 5;
+ break;
+ case 5:
+ $boxn = $endp + 52 | 0;
+ $5 = HEAP32[$boxn >> 2] | 0;
+ $sub = $5 - 1 | 0;
+ $y = $endp + 56 + ($sub << 5) + 24 | 0;
+ $6 = +HEAPF64[$y >> 3];
+ $y2 = $b + 24 | 0;
+ HEAPF64[$y2 >> 3] = $6;
+ $7 = HEAP32[$boxn >> 2] | 0;
+ $sub4 = $7 - 1 | 0;
+ $y7 = $endp + 56 + ($sub4 << 5) + 8 | 0;
+ $8 = +HEAPF64[$y7 >> 3];
+ $y9 = $b + 8 | 0;
+ HEAPF64[$y9 >> 3] = $8;
+ $y10 = $n + 40 | 0;
+ $9 = +HEAPF64[$y10 >> 3];
+ $rank = $n + 236 | 0;
+ $10 = HEAP32[$rank >> 2] | 0;
+ $rank13 = $0 + 224 | 0;
+ $11 = HEAP32[$rank13 >> 2] | 0;
+ $ht2 = $11 + ($10 * 44 & -1) + 20 | 0;
+ $12 = HEAP32[$ht2 >> 2] | 0;
+ $conv = +($12 | 0);
+ $sub15 = $9 - $conv;
+ $conv16 = ~~$sub15;
+ _makeregularend($tmp17, $b, 1, $conv16);
+ $13 = $tmp17;
+ HEAP32[$3 >> 2] = HEAP32[$13 >> 2] | 0;
+ HEAP32[$3 + 4 >> 2] = HEAP32[$13 + 4 >> 2] | 0;
+ HEAP32[$3 + 8 >> 2] = HEAP32[$13 + 8 >> 2] | 0;
+ HEAP32[$3 + 12 >> 2] = HEAP32[$13 + 12 >> 2] | 0;
+ HEAP32[$3 + 16 >> 2] = HEAP32[$13 + 16 >> 2] | 0;
+ HEAP32[$3 + 20 >> 2] = HEAP32[$13 + 20 >> 2] | 0;
+ HEAP32[$3 + 24 >> 2] = HEAP32[$13 + 24 >> 2] | 0;
+ HEAP32[$3 + 28 >> 2] = HEAP32[$13 + 28 >> 2] | 0;
+ $x = $b | 0;
+ $14 = +HEAPF64[$x >> 3];
+ $x20 = $b + 16 | 0;
+ $15 = +HEAPF64[$x20 >> 3];
+ $cmp = $14 < $15;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $16 = +HEAPF64[$y9 >> 3];
+ $17 = +HEAPF64[$y2 >> 3];
+ $cmp26 = $16 < $17;
+ if ($cmp26) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $18 = HEAP32[$boxn >> 2] | 0;
+ $inc = $18 + 1 | 0;
+ HEAP32[$boxn >> 2] = $inc;
+ $arrayidx31 = $endp + 56 + ($18 << 5) | 0;
+ $19 = $arrayidx31;
+ HEAP32[$19 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$19 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$19 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$19 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ HEAP32[$19 + 16 >> 2] = HEAP32[$3 + 16 >> 2] | 0;
+ HEAP32[$19 + 20 >> 2] = HEAP32[$3 + 20 >> 2] | 0;
+ HEAP32[$19 + 24 >> 2] = HEAP32[$3 + 24 >> 2] | 0;
+ HEAP32[$19 + 28 >> 2] = HEAP32[$3 + 28 >> 2] | 0;
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _makeSimpleFlatLabels($tn, $hn, $edges, $ind, $cnt, $et, $n_lbls) {
+ $tn = $tn | 0;
+ $hn = $hn | 0;
+ $edges = $edges | 0;
+ $ind = $ind | 0;
+ $cnt = $cnt | 0;
+ $et = $et | 0;
+ $n_lbls = $n_lbls | 0;
+ var $poly = 0, $pn = 0, $points = 0, $tp = 0, $hp = 0, $arrayidx = 0, $0 = 0, $mul = 0, $call = 0, $1 = 0, $cmp120 = 0, $i_0121 = 0, $add = 0, $arrayidx1 = 0, $2 = 0, $arrayidx2 = 0, $inc = 0, $cmp = 0, $coord = 0, $p = 0, $3 = 0, $coord5 = 0, $p7 = 0, $4 = 0, $x = 0, $5 = 0.0, $rw = 0, $6 = 0.0, $add10 = 0.0, $x11 = 0, $7 = 0.0, $lw = 0, $8 = 0.0, $sub = 0.0, $add13 = 0.0, $div = 0.0, $arrayidx15 = 0, $9 = 0, $arrayidx17 = 0, $10 = 0, $arrayidx19 = 0, $11 = 0, $arrayidx21 = 0, $12 = 0, $head = 0, $13 = 0, $14 = 0, $15 = 0, $label = 0, $16 = 0, $x23 = 0, $y = 0, $17 = 0.0, $18 = 0, $y26 = 0, $19 = 0.0, $add27 = 0.0, $div28 = 0.0, $add29 = 0.0, $y33 = 0, $20 = 0, $set = 0, $21 = 0.0, $add37 = 0.0, $22 = 0, $y41 = 0, $23 = 0.0, $add42 = 0.0, $x46 = 0, $24 = 0.0, $div47 = 0.0, $sub48 = 0.0, $add54 = 0.0, $cmp56110 = 0, $x121 = 0, $y124 = 0, $x126 = 0, $y128 = 0, $x130 = 0, $y132 = 0, $x134 = 0, $y135 = 0, $y137 = 0, $x140 = 0, $y143 = 0, $x146 = 0, $y149 = 0, $x152 = 0, $y155 = 0, $pn170 = 0, $ps172 = 0, $cmp173 = 0, $conv = 0, $x83 = 0, $y86 = 0, $x89 = 0, $y93 = 0, $x96 = 0, $y97 = 0, $y99 = 0, $x101 = 0, $y103 = 0, $x105 = 0, $y107 = 0, $x109 = 0, $y112 = 0, $lmaxx_0_lcssa = 0.0, $lminx_0_lcssa = 0.0, $i_1_lcssa = 0, $maxy_0_lcssa = 0.0, $miny_0_lcssa = 0.0, $cmp19598 = 0, $x250 = 0, $y253 = 0, $x255 = 0, $y257 = 0, $x259 = 0, $y261 = 0, $x263 = 0, $y264 = 0, $y266 = 0, $x269 = 0, $y272 = 0, $x275 = 0, $y278 = 0, $x281 = 0, $y284 = 0, $pn287 = 0, $ps289 = 0, $cmp290 = 0, $conv291 = 0, $mul206 = 0.0, $add207 = 0.0, $div208 = 0.0, $mul209 = 0.0, $add210 = 0.0, $div211 = 0.0, $x217 = 0, $y220 = 0, $x223 = 0, $y227 = 0, $x230 = 0, $y231 = 0, $y233 = 0, $x235 = 0, $y237 = 0, $x239 = 0, $y241 = 0, $x243 = 0, $y246 = 0, $lmaxx_0115 = 0.0, $lminx_0114 = 0.0, $i_1113 = 0, $maxy_0112 = 0.0, $miny_0111 = 0.0, $add58 = 0, $arrayidx59 = 0, $25 = 0, $rem97 = 0, $tobool = 0, $cmp60 = 0, $label63 = 0, $26 = 0, $x65 = 0, $27 = 0.0, $div66 = 0.0, $sub67 = 0.0, $add73 = 0.0, $lminx_1 = 0.0, $lmaxx_1 = 0.0, $label75 = 0, $28 = 0, $y77 = 0, $29 = 0.0, $add78 = 0.0, $sub79 = 0.0, $30 = 0.0, $sub84 = 0.0, $31 = 0.0, $32 = 0.0, $33 = 0.0, $34 = 0.0, $35 = 0, $y116 = 0, $36 = 0.0, $div117 = 0.0, $add118 = 0.0, $37 = 0.0, $38 = 0.0, $39 = 0.0, $40 = 0.0, $41 = 0.0, $add147 = 0.0, $42 = 0.0, $label157 = 0, $43 = 0, $y159 = 0, $44 = 0.0, $div160 = 0.0, $add161 = 0.0, $add162 = 0.0, $add167 = 0.0, $add168 = 0.0, $ctry_0 = 0.0, $miny_1 = 0.0, $maxy_1 = 0.0, $lminx_2 = 0.0, $lmaxx_2 = 0.0, $call174 = 0, $45 = 0, $cmp175 = 0, $label180 = 0, $46 = 0, $x182 = 0, $47 = 0, $y186 = 0, $48 = 0, $set189 = 0, $head190 = 0, $49 = 0, $50 = 0, $51 = 0, $52 = 0, $inc192 = 0, $cmp56 = 0, $lmaxx_3103 = 0.0, $lminx_3102 = 0.0, $i_2101 = 0, $maxy_2100 = 0.0, $miny_299 = 0.0, $add198 = 0, $arrayidx199 = 0, $53 = 0, $rem20096 = 0, $tobool201 = 0, $cmp203 = 0, $div208_lminx_3102 = 0.0, $div211_lmaxx_3103 = 0.0, $sub213 = 0.0, $54 = 0.0, $sub218 = 0.0, $55 = 0.0, $56 = 0.0, $57 = 0.0, $58 = 0.0, $59 = 0.0, $60 = 0.0, $61 = 0.0, $62 = 0.0, $63 = 0.0, $add276 = 0.0, $64 = 0.0, $miny_3 = 0.0, $maxy_3 = 0.0, $lminx_5 = 0.0, $lmaxx_5 = 0.0, $call292 = 0, $65 = 0, $cmp293 = 0, $head297 = 0, $66 = 0, $67 = 0, $68 = 0, $inc299 = 0, $cmp195 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 208 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $poly = __stackBase__ | 0;
+ $pn = __stackBase__ + 8 | 0;
+ $points = __stackBase__ + 16 | 0;
+ $tp = __stackBase__ + 176 | 0;
+ $hp = __stackBase__ + 192 | 0;
+ $arrayidx = $edges + ($ind << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $mul = $cnt << 2;
+ $call = _zmalloc($mul) | 0;
+ $1 = $call;
+ $cmp120 = ($cnt | 0) > 0;
+ if ($cmp120) {
+ $i_0121 = 0;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $add = $i_0121 + $ind | 0;
+ $arrayidx1 = $edges + ($add << 2) | 0;
+ $2 = HEAP32[$arrayidx1 >> 2] | 0;
+ $arrayidx2 = $1 + ($i_0121 << 2) | 0;
+ HEAP32[$arrayidx2 >> 2] = $2;
+ $inc = $i_0121 + 1 | 0;
+ $cmp = ($inc | 0) < ($cnt | 0);
+ if ($cmp) {
+ $i_0121 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _qsort($call | 0, $cnt | 0, 4, 56);
+ $coord = $tn + 32 | 0;
+ $p = $0 + 32 | 0;
+ _add_pointf3016($tp, $coord, $p);
+ $3 = $tp;
+ $coord5 = $hn + 32 | 0;
+ $p7 = $0 + 72 | 0;
+ _add_pointf3016($hp, $coord5, $p7);
+ $4 = $hp;
+ $x = $tp | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $rw = $tn + 112 | 0;
+ $6 = +HEAPF64[$rw >> 3];
+ $add10 = $5 + $6;
+ $x11 = $hp | 0;
+ $7 = +HEAPF64[$x11 >> 3];
+ $lw = $hn + 104 | 0;
+ $8 = +HEAPF64[$lw >> 3];
+ $sub = $7 - $8;
+ $add13 = $add10 + $sub;
+ $div = $add13 * .5;
+ $arrayidx15 = $points | 0;
+ $9 = $points;
+ HEAP32[$9 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $arrayidx17 = $points + 16 | 0;
+ $10 = $arrayidx17;
+ HEAP32[$10 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$10 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$10 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$10 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $arrayidx19 = $points + 32 | 0;
+ $11 = $arrayidx19;
+ HEAP32[$11 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $arrayidx21 = $points + 48 | 0;
+ $12 = $arrayidx21;
+ HEAP32[$12 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ $head = $0 + 12 | 0;
+ $13 = HEAP32[$head >> 2] | 0;
+ $14 = $0;
+ $15 = $13;
+ _clip_and_install($14, $15, $arrayidx15, 4, 4216);
+ $label = $0 + 112 | 0;
+ $16 = HEAP32[$label >> 2] | 0;
+ $x23 = $16 + 56 | 0;
+ HEAPF64[$x23 >> 3] = $div;
+ $y = $tp + 8 | 0;
+ $17 = +HEAPF64[$y >> 3];
+ $18 = HEAP32[$label >> 2] | 0;
+ $y26 = $18 + 32 | 0;
+ $19 = +HEAPF64[$y26 >> 3];
+ $add27 = $19 + 6.0;
+ $div28 = $add27 * .5;
+ $add29 = $17 + $div28;
+ $y33 = $18 + 64 | 0;
+ HEAPF64[$y33 >> 3] = $add29;
+ $20 = HEAP32[$label >> 2] | 0;
+ $set = $20 + 81 | 0;
+ HEAP8[$set] = 1;
+ $21 = +HEAPF64[$y >> 3];
+ $add37 = $21 + 3.0;
+ $22 = HEAP32[$label >> 2] | 0;
+ $y41 = $22 + 32 | 0;
+ $23 = +HEAPF64[$y41 >> 3];
+ $add42 = $add37 + $23;
+ $x46 = $22 + 24 | 0;
+ $24 = +HEAPF64[$x46 >> 3];
+ $div47 = $24 * .5;
+ $sub48 = $div - $div47;
+ $add54 = $div + $div47;
+ $cmp56110 = ($n_lbls | 0) > 1;
+ if ($cmp56110) {
+ label = 5;
+ break;
+ } else {
+ $miny_0_lcssa = $add37;
+ $maxy_0_lcssa = $add42;
+ $i_1_lcssa = 1;
+ $lminx_0_lcssa = 0.0;
+ $lmaxx_0_lcssa = 0.0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $x121 = $arrayidx17 | 0;
+ $y124 = $points + 24 | 0;
+ $x126 = $arrayidx19 | 0;
+ $y128 = $points + 40 | 0;
+ $x130 = $arrayidx21 | 0;
+ $y132 = $points + 56 | 0;
+ $x134 = $points + 64 | 0;
+ $y135 = $hp + 8 | 0;
+ $y137 = $points + 72 | 0;
+ $x140 = $points + 80 | 0;
+ $y143 = $points + 88 | 0;
+ $x146 = $points + 96 | 0;
+ $y149 = $points + 104 | 0;
+ $x152 = $points + 112 | 0;
+ $y155 = $points + 120 | 0;
+ $pn170 = $poly + 4 | 0;
+ $ps172 = $poly | 0;
+ $cmp173 = ($et | 0) == 4;
+ $conv = $cmp173 & 1;
+ $x83 = $arrayidx17 | 0;
+ $y86 = $points + 24 | 0;
+ $x89 = $arrayidx19 | 0;
+ $y93 = $points + 40 | 0;
+ $x96 = $points + 64 | 0;
+ $y97 = $hp + 8 | 0;
+ $y99 = $points + 72 | 0;
+ $x101 = $points + 80 | 0;
+ $y103 = $points + 88 | 0;
+ $x105 = $points + 96 | 0;
+ $y107 = $points + 104 | 0;
+ $x109 = $points + 112 | 0;
+ $y112 = $points + 120 | 0;
+ $miny_0111 = $add37;
+ $maxy_0112 = $add42;
+ $i_1113 = 1;
+ $lminx_0114 = 0.0;
+ $lmaxx_0115 = 0.0;
+ label = 8;
+ break;
+ case 6:
+ $cmp19598 = ($i_1_lcssa | 0) < ($cnt | 0);
+ if ($cmp19598) {
+ label = 7;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 7:
+ $x250 = $arrayidx17 | 0;
+ $y253 = $points + 24 | 0;
+ $x255 = $arrayidx19 | 0;
+ $y257 = $points + 40 | 0;
+ $x259 = $arrayidx21 | 0;
+ $y261 = $points + 56 | 0;
+ $x263 = $points + 64 | 0;
+ $y264 = $hp + 8 | 0;
+ $y266 = $points + 72 | 0;
+ $x269 = $points + 80 | 0;
+ $y272 = $points + 88 | 0;
+ $x275 = $points + 96 | 0;
+ $y278 = $points + 104 | 0;
+ $x281 = $points + 112 | 0;
+ $y284 = $points + 120 | 0;
+ $pn287 = $poly + 4 | 0;
+ $ps289 = $poly | 0;
+ $cmp290 = ($et | 0) == 4;
+ $conv291 = $cmp290 & 1;
+ $mul206 = $add10 * 2.0;
+ $add207 = $mul206 + $sub;
+ $div208 = $add207 / 3.0;
+ $mul209 = $sub * 2.0;
+ $add210 = $add10 + $mul209;
+ $div211 = $add210 / 3.0;
+ $x217 = $arrayidx17 | 0;
+ $y220 = $points + 24 | 0;
+ $x223 = $arrayidx19 | 0;
+ $y227 = $points + 40 | 0;
+ $x230 = $points + 64 | 0;
+ $y231 = $hp + 8 | 0;
+ $y233 = $points + 72 | 0;
+ $x235 = $points + 80 | 0;
+ $y237 = $points + 88 | 0;
+ $x239 = $points + 96 | 0;
+ $y241 = $points + 104 | 0;
+ $x243 = $points + 112 | 0;
+ $y246 = $points + 120 | 0;
+ $miny_299 = $miny_0_lcssa;
+ $maxy_2100 = $maxy_0_lcssa;
+ $i_2101 = $i_1_lcssa;
+ $lminx_3102 = $lminx_0_lcssa;
+ $lmaxx_3103 = $lmaxx_0_lcssa;
+ label = 15;
+ break;
+ case 8:
+ $add58 = $i_1113 + $ind | 0;
+ $arrayidx59 = $edges + ($add58 << 2) | 0;
+ $25 = HEAP32[$arrayidx59 >> 2] | 0;
+ $rem97 = $i_1113 & 1;
+ $tobool = ($rem97 | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp60 = ($i_1113 | 0) == 1;
+ if ($cmp60) {
+ label = 10;
+ break;
+ } else {
+ $lmaxx_1 = $lmaxx_0115;
+ $lminx_1 = $lminx_0114;
+ label = 11;
+ break;
+ }
+ case 10:
+ $label63 = $25 + 112 | 0;
+ $26 = HEAP32[$label63 >> 2] | 0;
+ $x65 = $26 + 24 | 0;
+ $27 = +HEAPF64[$x65 >> 3];
+ $div66 = $27 * .5;
+ $sub67 = $div - $div66;
+ $add73 = $div + $div66;
+ $lmaxx_1 = $add73;
+ $lminx_1 = $sub67;
+ label = 11;
+ break;
+ case 11:
+ $label75 = $25 + 112 | 0;
+ $28 = HEAP32[$label75 >> 2] | 0;
+ $y77 = $28 + 32 | 0;
+ $29 = +HEAPF64[$y77 >> 3];
+ $add78 = $29 + 6.0;
+ $sub79 = $miny_0111 - $add78;
+ HEAP32[$9 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $30 = +HEAPF64[$x >> 3];
+ HEAPF64[$x83 >> 3] = $30;
+ $sub84 = $sub79 + -6.0;
+ HEAPF64[$y86 >> 3] = $sub84;
+ $31 = +HEAPF64[$x11 >> 3];
+ HEAPF64[$x89 >> 3] = $31;
+ $32 = +HEAPF64[$y86 >> 3];
+ HEAPF64[$y93 >> 3] = $32;
+ HEAP32[$12 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ HEAPF64[$x96 >> 3] = $lmaxx_1;
+ $33 = +HEAPF64[$y97 >> 3];
+ HEAPF64[$y99 >> 3] = $33;
+ HEAPF64[$x101 >> 3] = $lmaxx_1;
+ HEAPF64[$y103 >> 3] = $sub79;
+ HEAPF64[$x105 >> 3] = $lminx_1;
+ HEAPF64[$y107 >> 3] = $sub79;
+ HEAPF64[$x109 >> 3] = $lminx_1;
+ $34 = +HEAPF64[$y >> 3];
+ HEAPF64[$y112 >> 3] = $34;
+ $35 = HEAP32[$label75 >> 2] | 0;
+ $y116 = $35 + 32 | 0;
+ $36 = +HEAPF64[$y116 >> 3];
+ $div117 = $36 * .5;
+ $add118 = $sub79 + $div117;
+ $lmaxx_2 = $lmaxx_1;
+ $lminx_2 = $lminx_1;
+ $maxy_1 = $maxy_0112;
+ $miny_1 = $sub79;
+ $ctry_0 = $add118;
+ label = 13;
+ break;
+ case 12:
+ HEAP32[$9 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ HEAPF64[$x121 >> 3] = $sub48;
+ $37 = +HEAPF64[$y >> 3];
+ HEAPF64[$y124 >> 3] = $37;
+ HEAPF64[$x126 >> 3] = $sub48;
+ HEAPF64[$y128 >> 3] = $maxy_0112;
+ HEAPF64[$x130 >> 3] = $add54;
+ HEAPF64[$y132 >> 3] = $maxy_0112;
+ HEAPF64[$x134 >> 3] = $add54;
+ $38 = +HEAPF64[$y135 >> 3];
+ HEAPF64[$y137 >> 3] = $38;
+ $39 = +HEAPF64[$x11 >> 3];
+ HEAPF64[$x140 >> 3] = $39;
+ $40 = +HEAPF64[$y135 >> 3];
+ HEAPF64[$y143 >> 3] = $40;
+ $41 = +HEAPF64[$x11 >> 3];
+ HEAPF64[$x146 >> 3] = $41;
+ $add147 = $maxy_0112 + 6.0;
+ HEAPF64[$y149 >> 3] = $add147;
+ $42 = +HEAPF64[$x >> 3];
+ HEAPF64[$x152 >> 3] = $42;
+ HEAPF64[$y155 >> 3] = $add147;
+ $label157 = $25 + 112 | 0;
+ $43 = HEAP32[$label157 >> 2] | 0;
+ $y159 = $43 + 32 | 0;
+ $44 = +HEAPF64[$y159 >> 3];
+ $div160 = $44 * .5;
+ $add161 = $maxy_0112 + $div160;
+ $add162 = $add161 + 6.0;
+ $add167 = $44 + 6.0;
+ $add168 = $maxy_0112 + $add167;
+ $lmaxx_2 = $lmaxx_0115;
+ $lminx_2 = $lminx_0114;
+ $maxy_1 = $add168;
+ $miny_1 = $miny_0111;
+ $ctry_0 = $add162;
+ label = 13;
+ break;
+ case 13:
+ HEAP32[$pn170 >> 2] = 8;
+ HEAP32[$ps172 >> 2] = $arrayidx15;
+ $call174 = _simpleSplineRoute($tp, $hp, $poly, $pn, $conv) | 0;
+ $45 = HEAP32[$pn >> 2] | 0;
+ $cmp175 = ($45 | 0) == 0;
+ if ($cmp175) {
+ label = 21;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $label180 = $25 + 112 | 0;
+ $46 = HEAP32[$label180 >> 2] | 0;
+ $x182 = $46 + 56 | 0;
+ HEAPF64[$x182 >> 3] = $div;
+ $47 = HEAP32[$label180 >> 2] | 0;
+ $y186 = $47 + 64 | 0;
+ HEAPF64[$y186 >> 3] = $ctry_0;
+ $48 = HEAP32[$label180 >> 2] | 0;
+ $set189 = $48 + 81 | 0;
+ HEAP8[$set189] = 1;
+ $head190 = $25 + 12 | 0;
+ $49 = HEAP32[$head190 >> 2] | 0;
+ $50 = HEAP32[$pn >> 2] | 0;
+ $51 = $25;
+ $52 = $49;
+ _clip_and_install($51, $52, $call174, $50, 4216);
+ $inc192 = $i_1113 + 1 | 0;
+ $cmp56 = ($inc192 | 0) < ($n_lbls | 0);
+ if ($cmp56) {
+ $miny_0111 = $miny_1;
+ $maxy_0112 = $maxy_1;
+ $i_1113 = $inc192;
+ $lminx_0114 = $lminx_2;
+ $lmaxx_0115 = $lmaxx_2;
+ label = 8;
+ break;
+ } else {
+ $miny_0_lcssa = $miny_1;
+ $maxy_0_lcssa = $maxy_1;
+ $i_1_lcssa = $inc192;
+ $lminx_0_lcssa = $lminx_2;
+ $lmaxx_0_lcssa = $lmaxx_2;
+ label = 6;
+ break;
+ }
+ case 15:
+ $add198 = $i_2101 + $ind | 0;
+ $arrayidx199 = $edges + ($add198 << 2) | 0;
+ $53 = HEAP32[$arrayidx199 >> 2] | 0;
+ $rem20096 = $i_2101 & 1;
+ $tobool201 = ($rem20096 | 0) == 0;
+ if ($tobool201) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $cmp203 = ($i_2101 | 0) == 1;
+ $div208_lminx_3102 = $cmp203 ? $div208 : $lminx_3102;
+ $div211_lmaxx_3103 = $cmp203 ? $div211 : $lmaxx_3103;
+ $sub213 = $miny_299 + -6.0;
+ HEAP32[$9 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $54 = +HEAPF64[$x >> 3];
+ HEAPF64[$x217 >> 3] = $54;
+ $sub218 = $sub213 + -6.0;
+ HEAPF64[$y220 >> 3] = $sub218;
+ $55 = +HEAPF64[$x11 >> 3];
+ HEAPF64[$x223 >> 3] = $55;
+ $56 = +HEAPF64[$y220 >> 3];
+ HEAPF64[$y227 >> 3] = $56;
+ HEAP32[$12 >> 2] = HEAP32[$4 >> 2] | 0;
+ HEAP32[$12 + 4 >> 2] = HEAP32[$4 + 4 >> 2] | 0;
+ HEAP32[$12 + 8 >> 2] = HEAP32[$4 + 8 >> 2] | 0;
+ HEAP32[$12 + 12 >> 2] = HEAP32[$4 + 12 >> 2] | 0;
+ HEAPF64[$x230 >> 3] = $div211_lmaxx_3103;
+ $57 = +HEAPF64[$y231 >> 3];
+ HEAPF64[$y233 >> 3] = $57;
+ HEAPF64[$x235 >> 3] = $div211_lmaxx_3103;
+ HEAPF64[$y237 >> 3] = $sub213;
+ HEAPF64[$x239 >> 3] = $div208_lminx_3102;
+ HEAPF64[$y241 >> 3] = $sub213;
+ HEAPF64[$x243 >> 3] = $div208_lminx_3102;
+ $58 = +HEAPF64[$y >> 3];
+ HEAPF64[$y246 >> 3] = $58;
+ $lmaxx_5 = $div211_lmaxx_3103;
+ $lminx_5 = $div208_lminx_3102;
+ $maxy_3 = $maxy_2100;
+ $miny_3 = $sub213;
+ label = 18;
+ break;
+ case 17:
+ HEAP32[$9 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$9 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$9 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$9 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ HEAPF64[$x250 >> 3] = $sub48;
+ $59 = +HEAPF64[$y >> 3];
+ HEAPF64[$y253 >> 3] = $59;
+ HEAPF64[$x255 >> 3] = $sub48;
+ HEAPF64[$y257 >> 3] = $maxy_2100;
+ HEAPF64[$x259 >> 3] = $add54;
+ HEAPF64[$y261 >> 3] = $maxy_2100;
+ HEAPF64[$x263 >> 3] = $add54;
+ $60 = +HEAPF64[$y264 >> 3];
+ HEAPF64[$y266 >> 3] = $60;
+ $61 = +HEAPF64[$x11 >> 3];
+ HEAPF64[$x269 >> 3] = $61;
+ $62 = +HEAPF64[$y264 >> 3];
+ HEAPF64[$y272 >> 3] = $62;
+ $63 = +HEAPF64[$x11 >> 3];
+ HEAPF64[$x275 >> 3] = $63;
+ $add276 = $maxy_2100 + 6.0;
+ HEAPF64[$y278 >> 3] = $add276;
+ $64 = +HEAPF64[$x >> 3];
+ HEAPF64[$x281 >> 3] = $64;
+ HEAPF64[$y284 >> 3] = $add276;
+ $lmaxx_5 = $lmaxx_3103;
+ $lminx_5 = $lminx_3102;
+ $maxy_3 = $add276;
+ $miny_3 = $miny_299;
+ label = 18;
+ break;
+ case 18:
+ HEAP32[$pn287 >> 2] = 8;
+ HEAP32[$ps289 >> 2] = $arrayidx15;
+ $call292 = _simpleSplineRoute($tp, $hp, $poly, $pn, $conv291) | 0;
+ $65 = HEAP32[$pn >> 2] | 0;
+ $cmp293 = ($65 | 0) == 0;
+ if ($cmp293) {
+ label = 21;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $head297 = $53 + 12 | 0;
+ $66 = HEAP32[$head297 >> 2] | 0;
+ $67 = $53;
+ $68 = $66;
+ _clip_and_install($67, $68, $call292, $65, 4216);
+ $inc299 = $i_2101 + 1 | 0;
+ $cmp195 = ($inc299 | 0) < ($cnt | 0);
+ if ($cmp195) {
+ $miny_299 = $miny_3;
+ $maxy_2100 = $maxy_3;
+ $i_2101 = $inc299;
+ $lminx_3102 = $lminx_5;
+ $lmaxx_3103 = $lmaxx_5;
+ label = 15;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ _free($call);
+ label = 21;
+ break;
+ case 21:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _cloneGraph($g) {
+ $g = $g | 0;
+ var $0 = 0, $1 = 0, $2 = 0, $and = 0, $call = 0, $3 = 0, $4 = 0, $call1 = 0, $call2 = 0, $5 = 0, $u = 0, $6 = 0, $drawing = 0, $drawing4 = 0, $7 = 0, $quantum = 0, $8 = 0.0, $quantum7 = 0, $9 = 0, $dpi = 0, $10 = 0.0, $11 = 0, $dpi12 = 0, $charset = 0, $12 = 0, $charset15 = 0, $rankdir = 0, $13 = 0, $and18 = 0, $tobool19 = 0, $rankdir21 = 0, $_ = 0, $nodesep = 0, $14 = 0, $nodesep26 = 0, $_c = 0, $ranksep = 0, $15 = 0, $ranksep29 = 0, $_c31 = 0, $root = 0, $16 = 0, $univ = 0, $17 = 0, $nodeattr = 0, $18 = 0, $list30 = 0, $19 = 0, $20 = 0, $tobool3134 = 0, $21 = 0, $list_035 = 0, $incdec_ptr = 0, $name = 0, $22 = 0, $value = 0, $23 = 0, $call32 = 0, $24 = 0, $tobool31 = 0, $25 = 0, $univ34 = 0, $26 = 0, $edgeattr = 0, $27 = 0, $list35 = 0, $28 = 0, $29 = 0, $tobool3832 = 0, $30 = 0, $list_133 = 0, $incdec_ptr37 = 0, $name40 = 0, $31 = 0, $value41 = 0, $32 = 0, $call42 = 0, $33 = 0, $tobool38 = 0, $proto = 0, $34 = 0, $e = 0, $35 = 0, $36 = 0, $call44 = 0, $tobool45 = 0, $call47 = 0, $37 = 0, $e50 = 0, $38 = 0, $39 = 0, $call51 = 0, $tobool52 = 0, $call54 = 0, $40 = 0, $41 = 0, $42 = 0, $43 = 0, $44 = 0, $45 = 0, $46 = 0, $47 = 0, $e57 = 0, $48 = 0, $49 = 0, $call58 = 0, $50 = 0, $e60 = 0, $51 = 0, $52 = 0, $call61 = 0, $53 = 0, $e63 = 0, $54 = 0, $55 = 0, $call64 = 0, $tobool65 = 0, $call67 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $2 = $1 >>> 4;
+ $and = $2 & 1;
+ $call = _agopen(95224, $and) | 0;
+ $3 = $call;
+ $4 = $call;
+ $call1 = _agraphattr($4, 117048, 91664) | 0;
+ $call2 = _zmalloc(96) | 0;
+ $5 = $call2;
+ $u = $call + 48 | 0;
+ $6 = $u;
+ $drawing = $u;
+ HEAP32[$drawing >> 2] = $5;
+ $drawing4 = $g + 48 | 0;
+ $7 = HEAP32[$drawing4 >> 2] | 0;
+ $quantum = $7 | 0;
+ $8 = +HEAPF64[$quantum >> 3];
+ $quantum7 = $call2;
+ HEAPF64[$quantum7 >> 3] = $8;
+ $9 = HEAP32[$drawing4 >> 2] | 0;
+ $dpi = $9 + 24 | 0;
+ $10 = +HEAPF64[$dpi >> 3];
+ $11 = HEAP32[$drawing >> 2] | 0;
+ $dpi12 = $11 + 24 | 0;
+ HEAPF64[$dpi12 >> 3] = $10;
+ $charset = $g + 155 | 0;
+ $12 = HEAP8[$charset] | 0;
+ $charset15 = $6 + 107 | 0;
+ HEAP8[$charset15] = $12;
+ $rankdir = $g + 156 | 0;
+ $13 = HEAP32[$rankdir >> 2] | 0;
+ $and18 = $13 & 1;
+ $tobool19 = ($and18 | 0) == 0;
+ $rankdir21 = $call + 156 | 0;
+ $_ = $tobool19 ? 1 : 0;
+ HEAP32[$rankdir21 >> 2] = $_;
+ $nodesep = $g + 260 | 0;
+ $14 = HEAP32[$nodesep >> 2] | 0;
+ $nodesep26 = $call + 260 | 0;
+ $_c = $14;
+ HEAP32[$nodesep26 >> 2] = $_c;
+ $ranksep = $g + 264 | 0;
+ $15 = HEAP32[$ranksep >> 2] | 0;
+ $ranksep29 = $call + 264 | 0;
+ $_c31 = $15;
+ HEAP32[$ranksep29 >> 2] = $_c31;
+ $root = $g + 32 | 0;
+ $16 = HEAP32[$root >> 2] | 0;
+ $univ = $16 + 16 | 0;
+ $17 = HEAP32[$univ >> 2] | 0;
+ $nodeattr = $17 + 4 | 0;
+ $18 = HEAP32[$nodeattr >> 2] | 0;
+ $list30 = $18 + 8 | 0;
+ $19 = HEAP32[$list30 >> 2] | 0;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $tobool3134 = ($20 | 0) == 0;
+ if ($tobool3134) {
+ label = 4;
+ break;
+ } else {
+ $list_035 = $19;
+ $21 = $20;
+ label = 3;
+ break;
+ }
+ case 3:
+ $incdec_ptr = $list_035 + 4 | 0;
+ $name = $21 | 0;
+ $22 = HEAP32[$name >> 2] | 0;
+ $value = $21 + 4 | 0;
+ $23 = HEAP32[$value >> 2] | 0;
+ $call32 = _agnodeattr($4, $22, $23) | 0;
+ $24 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool31 = ($24 | 0) == 0;
+ if ($tobool31) {
+ label = 4;
+ break;
+ } else {
+ $list_035 = $incdec_ptr;
+ $21 = $24;
+ label = 3;
+ break;
+ }
+ case 4:
+ $25 = HEAP32[$root >> 2] | 0;
+ $univ34 = $25 + 16 | 0;
+ $26 = HEAP32[$univ34 >> 2] | 0;
+ $edgeattr = $26 + 8 | 0;
+ $27 = HEAP32[$edgeattr >> 2] | 0;
+ $list35 = $27 + 8 | 0;
+ $28 = HEAP32[$list35 >> 2] | 0;
+ $29 = HEAP32[$28 >> 2] | 0;
+ $tobool3832 = ($29 | 0) == 0;
+ if ($tobool3832) {
+ label = 6;
+ break;
+ } else {
+ $list_133 = $28;
+ $30 = $29;
+ label = 5;
+ break;
+ }
+ case 5:
+ $incdec_ptr37 = $list_133 + 4 | 0;
+ $name40 = $30 | 0;
+ $31 = HEAP32[$name40 >> 2] | 0;
+ $value41 = $30 + 4 | 0;
+ $32 = HEAP32[$value41 >> 2] | 0;
+ $call42 = _agedgeattr($4, $31, $32) | 0;
+ $33 = HEAP32[$incdec_ptr37 >> 2] | 0;
+ $tobool38 = ($33 | 0) == 0;
+ if ($tobool38) {
+ label = 6;
+ break;
+ } else {
+ $list_133 = $incdec_ptr37;
+ $30 = $33;
+ label = 5;
+ break;
+ }
+ case 6:
+ $proto = $call + 40 | 0;
+ $34 = HEAP32[$proto >> 2] | 0;
+ $e = $34 + 4 | 0;
+ $35 = HEAP32[$e >> 2] | 0;
+ $36 = $35 | 0;
+ $call44 = _agfindattr($36, 161800) | 0;
+ $tobool45 = ($call44 | 0) == 0;
+ if ($tobool45) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call47 = _agedgeattr($4, 161800, 91664) | 0;
+ label = 8;
+ break;
+ case 8:
+ $37 = HEAP32[$proto >> 2] | 0;
+ $e50 = $37 + 4 | 0;
+ $38 = HEAP32[$e50 >> 2] | 0;
+ $39 = $38 | 0;
+ $call51 = _agfindattr($39, 158248) | 0;
+ $tobool52 = ($call51 | 0) == 0;
+ if ($tobool52) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $call54 = _agedgeattr($4, 158248, 91664) | 0;
+ label = 10;
+ break;
+ case 10:
+ $40 = HEAP32[41954] | 0;
+ HEAP32[21464] = $40;
+ $41 = HEAP32[41914] | 0;
+ HEAP32[21462] = $41;
+ $42 = HEAP32[41912] | 0;
+ HEAP32[21460] = $42;
+ $43 = HEAP32[41894] | 0;
+ HEAP32[21458] = $43;
+ $44 = HEAP32[41918] | 0;
+ HEAP32[21456] = $44;
+ $45 = HEAP32[41594] | 0;
+ HEAP32[21454] = $45;
+ $46 = HEAP32[41356] | 0;
+ HEAP32[21452] = $46;
+ HEAP32[41954] = 0;
+ $47 = HEAP32[$proto >> 2] | 0;
+ $e57 = $47 + 4 | 0;
+ $48 = HEAP32[$e57 >> 2] | 0;
+ $49 = $48 | 0;
+ $call58 = _agfindattr($49, 154824) | 0;
+ HEAP32[41914] = $call58;
+ $50 = HEAP32[$proto >> 2] | 0;
+ $e60 = $50 + 4 | 0;
+ $51 = HEAP32[$e60 >> 2] | 0;
+ $52 = $51 | 0;
+ $call61 = _agfindattr($52, 151264) | 0;
+ HEAP32[41912] = $call61;
+ $53 = HEAP32[$proto >> 2] | 0;
+ $e63 = $53 + 4 | 0;
+ $54 = HEAP32[$e63 >> 2] | 0;
+ $55 = $54 | 0;
+ $call64 = _agfindattr($55, 148464) | 0;
+ HEAP32[41894] = $call64;
+ $tobool65 = ($call64 | 0) == 0;
+ if ($tobool65) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $call67 = _agedgeattr($4, 148464, 91664) | 0;
+ HEAP32[41894] = $call67;
+ label = 12;
+ break;
+ case 12:
+ HEAP32[41918] = 0;
+ HEAP32[41594] = 0;
+ return $3 | 0;
+ }
+ return 0;
+}
+function _cloneNode($g, $orign) {
+ $g = $g | 0;
+ $orign = $orign | 0;
+ var $name = 0, $0 = 0, $1 = 0, $call = 0, $2 = 0, $3 = 0, $4 = 0, $call1 = 0, $5 = 0, $call2 = 0, $cmp = 0, $label = 0, $6 = 0, $text = 0, $7 = 0, $call3 = 0, $add = 0, $call4 = 0, $8 = 0, $text7 = 0, $9 = 0, $call8 = 0, $call9 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $name = $orign + 12 | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ $1 = $g;
+ $call = _agnode($1, $0) | 0;
+ $2 = $call;
+ $3 = $orign | 0;
+ $4 = $call | 0;
+ $call1 = _agcopyattr($3, $4) | 0;
+ $5 = $orign;
+ $call2 = _shapeOf($5) | 0;
+ $cmp = ($call2 | 0) == 2;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $label = $orign + 120 | 0;
+ $6 = HEAP32[$label >> 2] | 0;
+ $text = $6 | 0;
+ $7 = HEAP32[$text >> 2] | 0;
+ $call3 = _strlen($7 | 0) | 0;
+ $add = $call3 + 3 | 0;
+ $call4 = _gmalloc($add) | 0;
+ $8 = HEAP32[$label >> 2] | 0;
+ $text7 = $8 | 0;
+ $9 = HEAP32[$text7 >> 2] | 0;
+ $call8 = _sprintf($call4 | 0, 103472, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $9, tempInt) | 0) | 0;
+ $call9 = _agset($4, 99240, $call4) | 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $2 | 0;
+ }
+ return 0;
+}
+function _cloneEdge3018($g, $tn, $hn, $orig) {
+ $g = $g | 0;
+ $tn = $tn | 0;
+ $hn = $hn | 0;
+ $orig = $orig | 0;
+ var $call = 0;
+ $call = _agedge($g, $tn, $hn) | 0;
+ _agcopyattr($orig | 0, $call | 0);
+ return $call | 0;
+}
+function _transformf($agg_result, $p, $del, $flip) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $del = $del | 0;
+ $flip = $flip | 0;
+ var $tobool = 0, $x = 0, $0 = 0.0, $y = 0, $1 = 0.0, $sub = 0.0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $del;
+ $del = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$del >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$del + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$del + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$del + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($flip | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x = $p | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $y = $p + 8 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ HEAPF64[$x >> 3] = $1;
+ $sub = -0.0 - $0;
+ HEAPF64[$y >> 3] = $sub;
+ label = 4;
+ break;
+ case 4:
+ _add_pointf3016($agg_result, $p, $del);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _edgelblcmpfn($ptr0, $ptr1) {
+ $ptr0 = $ptr0 | 0;
+ $ptr1 = $ptr1 | 0;
+ var $0 = 0, $1 = 0, $label = 0, $2 = 0, $tobool = 0, $label2 = 0, $3 = 0, $tobool3 = 0, $sz0_sroa_0_0__idx = 0, $sz0_sroa_0_0_copyload = 0.0, $sz0_sroa_1_8__idx6 = 0, $sz0_sroa_1_8_copyload = 0.0, $sz1_sroa_0_0__idx = 0, $sz1_sroa_0_0_copyload = 0.0, $sz1_sroa_1_8__idx3 = 0, $sz1_sroa_1_8_copyload = 0.0, $cmp = 0, $cmp14 = 0, $cmp18 = 0, $cmp23 = 0, $_ = 0, $_9 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$ptr0 >> 2] | 0;
+ $1 = HEAP32[$ptr1 >> 2] | 0;
+ $label = $0 + 112 | 0;
+ $2 = HEAP32[$label >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ $label2 = $1 + 112 | 0;
+ $3 = HEAP32[$label2 >> 2] | 0;
+ $tobool3 = ($3 | 0) != 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ if ($tobool3) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = -1;
+ label = 9;
+ break;
+ }
+ case 4:
+ $sz0_sroa_0_0__idx = $2 + 24 | 0;
+ $sz0_sroa_0_0_copyload = +HEAPF64[$sz0_sroa_0_0__idx >> 3];
+ $sz0_sroa_1_8__idx6 = $2 + 32 | 0;
+ $sz0_sroa_1_8_copyload = +HEAPF64[$sz0_sroa_1_8__idx6 >> 3];
+ $sz1_sroa_0_0__idx = $3 + 24 | 0;
+ $sz1_sroa_0_0_copyload = +HEAPF64[$sz1_sroa_0_0__idx >> 3];
+ $sz1_sroa_1_8__idx3 = $3 + 32 | 0;
+ $sz1_sroa_1_8_copyload = +HEAPF64[$sz1_sroa_1_8__idx3 >> 3];
+ $cmp = $sz0_sroa_0_0_copyload > $sz1_sroa_0_0_copyload;
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp14 = $sz0_sroa_0_0_copyload < $sz1_sroa_0_0_copyload;
+ if ($cmp14) {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp18 = $sz0_sroa_1_8_copyload > $sz1_sroa_1_8_copyload;
+ if ($cmp18) {
+ $retval_0 = -1;
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp23 = $sz0_sroa_1_8_copyload < $sz1_sroa_1_8_copyload;
+ $_ = $cmp23 & 1;
+ $retval_0 = $_;
+ label = 9;
+ break;
+ case 8:
+ $_9 = $tobool3 & 1;
+ $retval_0 = $_9;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _swap_ends_p($e) {
+ $e = $e | 0;
+ var $e_addr_0 = 0, $to_orig = 0, $0 = 0, $tobool = 0, $head = 0, $1 = 0, $rank = 0, $2 = 0, $tail = 0, $3 = 0, $rank5 = 0, $4 = 0, $cmp = 0, $cmp12 = 0, $order = 0, $5 = 0, $order19 = 0, $6 = 0, $cmp20 = 0, $_ = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $e_addr_0 = $e;
+ label = 3;
+ break;
+ case 3:
+ $to_orig = $e_addr_0 + 132 | 0;
+ $0 = HEAP32[$to_orig >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $e_addr_0 = $0;
+ label = 3;
+ break;
+ }
+ case 4:
+ $head = $e_addr_0 + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $rank = $1 + 236 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $tail = $e_addr_0 + 16 | 0;
+ $3 = HEAP32[$tail >> 2] | 0;
+ $rank5 = $3 + 236 | 0;
+ $4 = HEAP32[$rank5 >> 2] | 0;
+ $cmp = ($2 | 0) > ($4 | 0);
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp12 = ($2 | 0) < ($4 | 0);
+ if ($cmp12) {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $order = $1 + 240 | 0;
+ $5 = HEAP32[$order >> 2] | 0;
+ $order19 = $3 + 240 | 0;
+ $6 = HEAP32[$order19 >> 2] | 0;
+ $cmp20 = ($5 | 0) < ($6 | 0);
+ $_ = $cmp20 & 1;
+ $retval_0 = $_;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _ffe($u, $uL, $v, $vL) {
+ $u = $u | 0;
+ $uL = $uL | 0;
+ $v = $v | 0;
+ $vL = $vL | 0;
+ var $size = 0, $0 = 0, $cmp = 0, $size1 = 0, $1 = 0, $cmp2 = 0, $cmp5 = 0, $list10 = 0, $2 = 0, $list = 0, $3 = 0, $i_0 = 0, $arrayidx = 0, $4 = 0, $tobool = 0, $head = 0, $5 = 0, $cmp7 = 0, $inc = 0, $i_1 = 0, $arrayidx11 = 0, $6 = 0, $tobool12 = 0, $tail = 0, $7 = 0, $cmp14 = 0, $inc18 = 0, $e_0 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $uL;
+ $uL = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$uL >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$uL + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ tempParam = $vL;
+ $vL = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$vL >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$vL + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $uL + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp = ($0 | 0) > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $e_0 = 0;
+ label = 11;
+ break;
+ }
+ case 3:
+ $size1 = $vL + 4 | 0;
+ $1 = HEAP32[$size1 >> 2] | 0;
+ $cmp2 = ($1 | 0) > 0;
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ $e_0 = 0;
+ label = 11;
+ break;
+ }
+ case 4:
+ $cmp5 = ($0 | 0) < ($1 | 0);
+ if ($cmp5) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $list10 = $vL | 0;
+ $2 = HEAP32[$list10 >> 2] | 0;
+ $i_1 = 0;
+ label = 9;
+ break;
+ case 6:
+ $list = $uL | 0;
+ $3 = HEAP32[$list >> 2] | 0;
+ $i_0 = 0;
+ label = 7;
+ break;
+ case 7:
+ $arrayidx = $3 + ($i_0 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ $e_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $head = $4 + 12 | 0;
+ $5 = HEAP32[$head >> 2] | 0;
+ $cmp7 = ($5 | 0) == ($v | 0);
+ $inc = $i_0 + 1 | 0;
+ if ($cmp7) {
+ $e_0 = $4;
+ label = 11;
+ break;
+ } else {
+ $i_0 = $inc;
+ label = 7;
+ break;
+ }
+ case 9:
+ $arrayidx11 = $2 + ($i_1 << 2) | 0;
+ $6 = HEAP32[$arrayidx11 >> 2] | 0;
+ $tobool12 = ($6 | 0) == 0;
+ if ($tobool12) {
+ $e_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $tail = $6 + 16 | 0;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $cmp14 = ($7 | 0) == ($u | 0);
+ $inc18 = $i_1 + 1 | 0;
+ if ($cmp14) {
+ $e_0 = $6;
+ label = 11;
+ break;
+ } else {
+ $i_1 = $inc18;
+ label = 9;
+ break;
+ }
+ case 11:
+ STACKTOP = __stackBase__;
+ return $e_0 | 0;
+ }
+ return 0;
+}
+function _zapinlist($L, $e) {
+ $L = $L | 0;
+ $e = $e | 0;
+ var $size = 0, $0 = 0, $list = 0, $i_0 = 0, $cmp = 0, $1 = 0, $arrayidx = 0, $2 = 0, $cmp1 = 0, $inc = 0, $dec = 0, $3 = 0, $arrayidx5 = 0, $4 = 0, $arrayidx7 = 0, $5 = 0, $6 = 0, $arrayidx10 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $L + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $list = $L | 0;
+ $i_0 = 0;
+ label = 3;
+ break;
+ case 3:
+ $cmp = ($i_0 | 0) < ($0 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($i_0 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp1 = ($2 | 0) == ($e | 0);
+ $inc = $i_0 + 1 | 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ $i_0 = $inc;
+ label = 3;
+ break;
+ }
+ case 5:
+ $dec = $0 - 1 | 0;
+ HEAP32[$size >> 2] = $dec;
+ $3 = HEAP32[$list >> 2] | 0;
+ $arrayidx5 = $3 + ($dec << 2) | 0;
+ $4 = HEAP32[$arrayidx5 >> 2] | 0;
+ $arrayidx7 = $3 + ($i_0 << 2) | 0;
+ HEAP32[$arrayidx7 >> 2] = $4;
+ $5 = HEAP32[$size >> 2] | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $arrayidx10 = $6 + ($5 << 2) | 0;
+ HEAP32[$arrayidx10 >> 2] = 0;
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _find_fast_node($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $nlist = 0, $v_0_in = 0, $v_0 = 0, $tobool = 0, $cmp = 0, $or_cond = 0, $next = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $v_0_in = $nlist;
+ label = 3;
+ break;
+ case 3:
+ $v_0 = HEAP32[$v_0_in >> 2] | 0;
+ $tobool = ($v_0 | 0) == 0;
+ $cmp = ($v_0 | 0) == ($n | 0);
+ $or_cond = $tobool | $cmp;
+ $next = $v_0 + 168 | 0;
+ if ($or_cond) {
+ label = 4;
+ break;
+ } else {
+ $v_0_in = $next;
+ label = 3;
+ break;
+ }
+ case 4:
+ return $v_0 | 0;
+ }
+ return 0;
+}
+function _basic_merge($e, $rep) {
+ $e = $e | 0;
+ $rep = $rep | 0;
+ var $minlen = 0, $0 = 0, $minlen2 = 0, $1 = 0, $cmp = 0, $count = 0, $xpenalty = 0, $weight = 0, $rep_addr_016 = 0, $2 = 0, $count12 = 0, $3 = 0, $add = 0, $4 = 0, $xpenalty18 = 0, $5 = 0, $add20 = 0, $6 = 0.0, $weight24 = 0, $7 = 0.0, $add25 = 0.0, $to_virt = 0, $8 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minlen = $rep + 186 | 0;
+ $0 = HEAP16[$minlen >> 1] | 0;
+ $minlen2 = $e + 186 | 0;
+ $1 = HEAP16[$minlen2 >> 1] | 0;
+ $cmp = ($0 & 65535) < ($1 & 65535);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP16[$minlen >> 1] = $1;
+ label = 4;
+ break;
+ case 4:
+ $count = $e + 184 | 0;
+ $xpenalty = $e + 170 | 0;
+ $weight = $e + 172 | 0;
+ $rep_addr_016 = $rep;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP16[$count >> 1] | 0;
+ $count12 = $rep_addr_016 + 184 | 0;
+ $3 = HEAP16[$count12 >> 1] | 0;
+ $add = $3 + $2 & 65535;
+ HEAP16[$count12 >> 1] = $add;
+ $4 = HEAP16[$xpenalty >> 1] | 0;
+ $xpenalty18 = $rep_addr_016 + 170 | 0;
+ $5 = HEAP16[$xpenalty18 >> 1] | 0;
+ $add20 = $5 + $4 & 65535;
+ HEAP16[$xpenalty18 >> 1] = $add20;
+ $6 = +HEAPF32[$weight >> 2];
+ $weight24 = $rep_addr_016 + 172 | 0;
+ $7 = +HEAPF32[$weight24 >> 2];
+ $add25 = $6 + $7;
+ HEAPF32[$weight24 >> 2] = $add25;
+ $to_virt = $rep_addr_016 + 188 | 0;
+ $8 = HEAP32[$to_virt >> 2] | 0;
+ $tobool = ($8 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $rep_addr_016 = $8;
+ label = 5;
+ break;
+ }
+ case 6:
+ return;
+ }
+}
+function _cleanupCloneGraph($g) {
+ $g = $g | 0;
+ HEAP32[41954] = HEAP32[21464] | 0;
+ HEAP32[41914] = HEAP32[21462] | 0;
+ HEAP32[41912] = HEAP32[21460] | 0;
+ HEAP32[41894] = HEAP32[21458] | 0;
+ HEAP32[41918] = HEAP32[21456] | 0;
+ HEAP32[41594] = HEAP32[21454] | 0;
+ HEAP32[41356] = HEAP32[21452] | 0;
+ _dot_cleanup($g);
+ _agclose($g);
+ return;
+}
+function _find_fast_edge($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ return _ffe($u, $u + 184 | 0, $v, $v + 176 | 0) | 0;
+}
+function _find_flat_edge($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ return _ffe($u, $u + 192 | 0, $v, $v + 200 | 0) | 0;
+}
+function _fast_edge($e) {
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $list = 0, $1 = 0, $tobool = 0, $2 = 0, $size = 0, $3 = 0, $add = 0, $mul = 0, $call = 0, $size11 = 0, $4 = 0, $add12 = 0, $mul13 = 0, $call14 = 0, $call_sink = 0, $5 = 0, $6 = 0, $list18 = 0, $7 = 0, $size22 = 0, $8 = 0, $inc = 0, $9 = 0, $list26 = 0, $10 = 0, $arrayidx = 0, $11 = 0, $size30 = 0, $12 = 0, $list34 = 0, $13 = 0, $arrayidx35 = 0, $head = 0, $14 = 0, $list38 = 0, $15 = 0, $tobool39 = 0, $16 = 0, $size48 = 0, $17 = 0, $add49 = 0, $mul50 = 0, $call51 = 0, $size56 = 0, $18 = 0, $add57 = 0, $mul58 = 0, $call59 = 0, $call51_sink = 0, $19 = 0, $20 = 0, $list65 = 0, $21 = 0, $size69 = 0, $22 = 0, $inc70 = 0, $23 = 0, $list74 = 0, $24 = 0, $arrayidx75 = 0, $25 = 0, $size79 = 0, $26 = 0, $list83 = 0, $27 = 0, $arrayidx84 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $list = $0 + 184 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $1;
+ $size = $0 + 188 | 0;
+ $3 = HEAP32[$size >> 2] | 0;
+ $add = $3 << 2;
+ $mul = $add + 8 | 0;
+ $call = _grealloc($2, $mul) | 0;
+ $call_sink = $call;
+ label = 5;
+ break;
+ case 4:
+ $size11 = $0 + 188 | 0;
+ $4 = HEAP32[$size11 >> 2] | 0;
+ $add12 = $4 << 2;
+ $mul13 = $add12 + 8 | 0;
+ $call14 = _gmalloc($mul13) | 0;
+ $call_sink = $call14;
+ label = 5;
+ break;
+ case 5:
+ $5 = $call_sink;
+ $6 = HEAP32[$tail >> 2] | 0;
+ $list18 = $6 + 184 | 0;
+ HEAP32[$list18 >> 2] = $5;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $size22 = $7 + 188 | 0;
+ $8 = HEAP32[$size22 >> 2] | 0;
+ $inc = $8 + 1 | 0;
+ HEAP32[$size22 >> 2] = $inc;
+ $9 = HEAP32[$tail >> 2] | 0;
+ $list26 = $9 + 184 | 0;
+ $10 = HEAP32[$list26 >> 2] | 0;
+ $arrayidx = $10 + ($8 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $e;
+ $11 = HEAP32[$tail >> 2] | 0;
+ $size30 = $11 + 188 | 0;
+ $12 = HEAP32[$size30 >> 2] | 0;
+ $list34 = $11 + 184 | 0;
+ $13 = HEAP32[$list34 >> 2] | 0;
+ $arrayidx35 = $13 + ($12 << 2) | 0;
+ HEAP32[$arrayidx35 >> 2] = 0;
+ $head = $e + 12 | 0;
+ $14 = HEAP32[$head >> 2] | 0;
+ $list38 = $14 + 176 | 0;
+ $15 = HEAP32[$list38 >> 2] | 0;
+ $tobool39 = ($15 | 0) == 0;
+ if ($tobool39) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $16 = $15;
+ $size48 = $14 + 180 | 0;
+ $17 = HEAP32[$size48 >> 2] | 0;
+ $add49 = $17 << 2;
+ $mul50 = $add49 + 8 | 0;
+ $call51 = _grealloc($16, $mul50) | 0;
+ $call51_sink = $call51;
+ label = 8;
+ break;
+ case 7:
+ $size56 = $14 + 180 | 0;
+ $18 = HEAP32[$size56 >> 2] | 0;
+ $add57 = $18 << 2;
+ $mul58 = $add57 + 8 | 0;
+ $call59 = _gmalloc($mul58) | 0;
+ $call51_sink = $call59;
+ label = 8;
+ break;
+ case 8:
+ $19 = $call51_sink;
+ $20 = HEAP32[$head >> 2] | 0;
+ $list65 = $20 + 176 | 0;
+ HEAP32[$list65 >> 2] = $19;
+ $21 = HEAP32[$head >> 2] | 0;
+ $size69 = $21 + 180 | 0;
+ $22 = HEAP32[$size69 >> 2] | 0;
+ $inc70 = $22 + 1 | 0;
+ HEAP32[$size69 >> 2] = $inc70;
+ $23 = HEAP32[$head >> 2] | 0;
+ $list74 = $23 + 176 | 0;
+ $24 = HEAP32[$list74 >> 2] | 0;
+ $arrayidx75 = $24 + ($22 << 2) | 0;
+ HEAP32[$arrayidx75 >> 2] = $e;
+ $25 = HEAP32[$head >> 2] | 0;
+ $size79 = $25 + 180 | 0;
+ $26 = HEAP32[$size79 >> 2] | 0;
+ $list83 = $25 + 176 | 0;
+ $27 = HEAP32[$list83 >> 2] | 0;
+ $arrayidx84 = $27 + ($26 << 2) | 0;
+ HEAP32[$arrayidx84 >> 2] = 0;
+ return $e | 0;
+ }
+ return 0;
+}
+function _other_edge($e) {
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $list = 0, $1 = 0, $tobool = 0, $2 = 0, $size = 0, $3 = 0, $add = 0, $mul = 0, $call = 0, $size11 = 0, $4 = 0, $add12 = 0, $mul13 = 0, $call14 = 0, $call_sink = 0, $5 = 0, $6 = 0, $list18 = 0, $7 = 0, $size22 = 0, $8 = 0, $inc = 0, $9 = 0, $list26 = 0, $10 = 0, $arrayidx = 0, $11 = 0, $size30 = 0, $12 = 0, $list34 = 0, $13 = 0, $arrayidx35 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $list = $0 + 208 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $1;
+ $size = $0 + 212 | 0;
+ $3 = HEAP32[$size >> 2] | 0;
+ $add = $3 << 2;
+ $mul = $add + 8 | 0;
+ $call = _grealloc($2, $mul) | 0;
+ $call_sink = $call;
+ label = 5;
+ break;
+ case 4:
+ $size11 = $0 + 212 | 0;
+ $4 = HEAP32[$size11 >> 2] | 0;
+ $add12 = $4 << 2;
+ $mul13 = $add12 + 8 | 0;
+ $call14 = _gmalloc($mul13) | 0;
+ $call_sink = $call14;
+ label = 5;
+ break;
+ case 5:
+ $5 = $call_sink;
+ $6 = HEAP32[$tail >> 2] | 0;
+ $list18 = $6 + 208 | 0;
+ HEAP32[$list18 >> 2] = $5;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $size22 = $7 + 212 | 0;
+ $8 = HEAP32[$size22 >> 2] | 0;
+ $inc = $8 + 1 | 0;
+ HEAP32[$size22 >> 2] = $inc;
+ $9 = HEAP32[$tail >> 2] | 0;
+ $list26 = $9 + 208 | 0;
+ $10 = HEAP32[$list26 >> 2] | 0;
+ $arrayidx = $10 + ($8 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $e;
+ $11 = HEAP32[$tail >> 2] | 0;
+ $size30 = $11 + 212 | 0;
+ $12 = HEAP32[$size30 >> 2] | 0;
+ $list34 = $11 + 208 | 0;
+ $13 = HEAP32[$list34 >> 2] | 0;
+ $arrayidx35 = $13 + ($12 << 2) | 0;
+ HEAP32[$arrayidx35 >> 2] = 0;
+ return;
+ }
+}
+function _safe_other_edge($e) {
+ $e = $e | 0;
+ _safe_list_append($e, (HEAP32[$e + 16 >> 2] | 0) + 208 | 0);
+ return;
+}
+function _safe_list_append($e, $L) {
+ $e = $e | 0;
+ $L = $L | 0;
+ var $size = 0, $0 = 0, $list = 0, $1 = 0, $i_0 = 0, $cmp = 0, $arrayidx = 0, $2 = 0, $cmp1 = 0, $inc = 0, $tobool = 0, $3 = 0, $add = 0, $mul = 0, $call = 0, $add6 = 0, $mul7 = 0, $call8 = 0, $call_sink = 0, $4 = 0, $5 = 0, $inc11 = 0, $6 = 0, $arrayidx13 = 0, $7 = 0, $8 = 0, $arrayidx16 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $L + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $list = $L | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $i_0 = 0;
+ label = 3;
+ break;
+ case 3:
+ $cmp = ($i_0 | 0) < ($0 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $arrayidx = $1 + ($i_0 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp1 = ($2 | 0) == ($e | 0);
+ $inc = $i_0 + 1 | 0;
+ if ($cmp1) {
+ label = 9;
+ break;
+ } else {
+ $i_0 = $inc;
+ label = 3;
+ break;
+ }
+ case 5:
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = $1;
+ $add = $0 << 2;
+ $mul = $add + 8 | 0;
+ $call = _grealloc($3, $mul) | 0;
+ $call_sink = $call;
+ label = 8;
+ break;
+ case 7:
+ $add6 = $0 << 2;
+ $mul7 = $add6 + 8 | 0;
+ $call8 = _gmalloc($mul7) | 0;
+ $call_sink = $call8;
+ label = 8;
+ break;
+ case 8:
+ $4 = $call_sink;
+ HEAP32[$list >> 2] = $4;
+ $5 = HEAP32[$size >> 2] | 0;
+ $inc11 = $5 + 1 | 0;
+ HEAP32[$size >> 2] = $inc11;
+ $6 = HEAP32[$list >> 2] | 0;
+ $arrayidx13 = $6 + ($5 << 2) | 0;
+ HEAP32[$arrayidx13 >> 2] = $e;
+ $7 = HEAP32[$size >> 2] | 0;
+ $8 = HEAP32[$list >> 2] | 0;
+ $arrayidx16 = $8 + ($7 << 2) | 0;
+ HEAP32[$arrayidx16 >> 2] = 0;
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _new_virtual_edge($u, $v, $orig) {
+ $u = $u | 0;
+ $v = $v | 0;
+ $orig = $orig | 0;
+ var $call = 0, $0 = 0, $tail = 0, $1 = 0, $head = 0, $2 = 0, $3 = 0, $tobool = 0, $id = 0, $4 = 0, $id2 = 0, $5 = 0, $count = 0, $6 = 0, $count5 = 0, $7 = 0, $xpenalty = 0, $8 = 0, $xpenalty8 = 0, $9 = 0, $weight = 0, $10 = 0.0, $weight11 = 0, $11 = 0, $minlen = 0, $12 = 0, $minlen14 = 0, $13 = 0, $14 = 0, $tail16 = 0, $15 = 0, $cmp = 0, $tail_port = 0, $tail_port20 = 0, $16 = 0, $head22 = 0, $17 = 0, $cmp23 = 0, $tail_port26 = 0, $head_port = 0, $18 = 0, $19 = 0, $head30 = 0, $20 = 0, $cmp31 = 0, $head_port34 = 0, $head_port36 = 0, $21 = 0, $22 = 0, $cmp40 = 0, $head_port43 = 0, $tail_port45 = 0, $23 = 0, $to_virt = 0, $24 = 0, $cmp49 = 0, $to_orig = 0, $25 = 0, $weight57 = 0, $26 = 0, $xpenalty59 = 0, $27 = 0, $count61 = 0, $28 = 0, $minlen63 = 0, $29 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(192) | 0;
+ $0 = $call;
+ $tail = $call + 16 | 0;
+ $1 = $tail;
+ HEAP32[$1 >> 2] = $u;
+ $head = $call + 12 | 0;
+ $2 = $head;
+ HEAP32[$2 >> 2] = $v;
+ $3 = $call + 128 | 0;
+ HEAP8[$3] = 1;
+ $tobool = ($orig | 0) == 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $id = $orig + 20 | 0;
+ $4 = HEAP32[$id >> 2] | 0;
+ $id2 = $call + 20 | 0;
+ $5 = $id2;
+ HEAP32[$5 >> 2] = $4;
+ $count = $orig + 184 | 0;
+ $6 = HEAP16[$count >> 1] | 0;
+ $count5 = $call + 184 | 0;
+ $7 = $count5;
+ HEAP16[$7 >> 1] = $6;
+ $xpenalty = $orig + 170 | 0;
+ $8 = HEAP16[$xpenalty >> 1] | 0;
+ $xpenalty8 = $call + 170 | 0;
+ $9 = $xpenalty8;
+ HEAP16[$9 >> 1] = $8;
+ $weight = $orig + 172 | 0;
+ $10 = +HEAPF32[$weight >> 2];
+ $weight11 = $call + 172 | 0;
+ $11 = $weight11;
+ HEAPF32[$11 >> 2] = $10;
+ $minlen = $orig + 186 | 0;
+ $12 = HEAP16[$minlen >> 1] | 0;
+ $minlen14 = $call + 186 | 0;
+ $13 = $minlen14;
+ HEAP16[$13 >> 1] = $12;
+ $14 = HEAP32[$1 >> 2] | 0;
+ $tail16 = $orig + 16 | 0;
+ $15 = HEAP32[$tail16 >> 2] | 0;
+ $cmp = ($14 | 0) == ($15 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $tail_port = $call + 32 | 0;
+ $tail_port20 = $orig + 32 | 0;
+ $16 = $tail_port20;
+ HEAP32[$tail_port >> 2] = HEAP32[$16 >> 2] | 0;
+ HEAP32[$tail_port + 4 >> 2] = HEAP32[$16 + 4 >> 2] | 0;
+ HEAP32[$tail_port + 8 >> 2] = HEAP32[$16 + 8 >> 2] | 0;
+ HEAP32[$tail_port + 12 >> 2] = HEAP32[$16 + 12 >> 2] | 0;
+ HEAP32[$tail_port + 16 >> 2] = HEAP32[$16 + 16 >> 2] | 0;
+ HEAP32[$tail_port + 20 >> 2] = HEAP32[$16 + 20 >> 2] | 0;
+ HEAP32[$tail_port + 24 >> 2] = HEAP32[$16 + 24 >> 2] | 0;
+ HEAP32[$tail_port + 28 >> 2] = HEAP32[$16 + 28 >> 2] | 0;
+ HEAP32[$tail_port + 32 >> 2] = HEAP32[$16 + 32 >> 2] | 0;
+ HEAP32[$tail_port + 36 >> 2] = HEAP32[$16 + 36 >> 2] | 0;
+ label = 7;
+ break;
+ case 5:
+ $head22 = $orig + 12 | 0;
+ $17 = HEAP32[$head22 >> 2] | 0;
+ $cmp23 = ($14 | 0) == ($17 | 0);
+ if ($cmp23) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $tail_port26 = $call + 32 | 0;
+ $head_port = $orig + 72 | 0;
+ $18 = $head_port;
+ HEAP32[$tail_port26 >> 2] = HEAP32[$18 >> 2] | 0;
+ HEAP32[$tail_port26 + 4 >> 2] = HEAP32[$18 + 4 >> 2] | 0;
+ HEAP32[$tail_port26 + 8 >> 2] = HEAP32[$18 + 8 >> 2] | 0;
+ HEAP32[$tail_port26 + 12 >> 2] = HEAP32[$18 + 12 >> 2] | 0;
+ HEAP32[$tail_port26 + 16 >> 2] = HEAP32[$18 + 16 >> 2] | 0;
+ HEAP32[$tail_port26 + 20 >> 2] = HEAP32[$18 + 20 >> 2] | 0;
+ HEAP32[$tail_port26 + 24 >> 2] = HEAP32[$18 + 24 >> 2] | 0;
+ HEAP32[$tail_port26 + 28 >> 2] = HEAP32[$18 + 28 >> 2] | 0;
+ HEAP32[$tail_port26 + 32 >> 2] = HEAP32[$18 + 32 >> 2] | 0;
+ HEAP32[$tail_port26 + 36 >> 2] = HEAP32[$18 + 36 >> 2] | 0;
+ label = 7;
+ break;
+ case 7:
+ $19 = HEAP32[$2 >> 2] | 0;
+ $head30 = $orig + 12 | 0;
+ $20 = HEAP32[$head30 >> 2] | 0;
+ $cmp31 = ($19 | 0) == ($20 | 0);
+ if ($cmp31) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $head_port34 = $call + 72 | 0;
+ $head_port36 = $orig + 72 | 0;
+ $21 = $head_port36;
+ HEAP32[$head_port34 >> 2] = HEAP32[$21 >> 2] | 0;
+ HEAP32[$head_port34 + 4 >> 2] = HEAP32[$21 + 4 >> 2] | 0;
+ HEAP32[$head_port34 + 8 >> 2] = HEAP32[$21 + 8 >> 2] | 0;
+ HEAP32[$head_port34 + 12 >> 2] = HEAP32[$21 + 12 >> 2] | 0;
+ HEAP32[$head_port34 + 16 >> 2] = HEAP32[$21 + 16 >> 2] | 0;
+ HEAP32[$head_port34 + 20 >> 2] = HEAP32[$21 + 20 >> 2] | 0;
+ HEAP32[$head_port34 + 24 >> 2] = HEAP32[$21 + 24 >> 2] | 0;
+ HEAP32[$head_port34 + 28 >> 2] = HEAP32[$21 + 28 >> 2] | 0;
+ HEAP32[$head_port34 + 32 >> 2] = HEAP32[$21 + 32 >> 2] | 0;
+ HEAP32[$head_port34 + 36 >> 2] = HEAP32[$21 + 36 >> 2] | 0;
+ label = 11;
+ break;
+ case 9:
+ $22 = HEAP32[$tail16 >> 2] | 0;
+ $cmp40 = ($19 | 0) == ($22 | 0);
+ if ($cmp40) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $head_port43 = $call + 72 | 0;
+ $tail_port45 = $orig + 32 | 0;
+ $23 = $tail_port45;
+ HEAP32[$head_port43 >> 2] = HEAP32[$23 >> 2] | 0;
+ HEAP32[$head_port43 + 4 >> 2] = HEAP32[$23 + 4 >> 2] | 0;
+ HEAP32[$head_port43 + 8 >> 2] = HEAP32[$23 + 8 >> 2] | 0;
+ HEAP32[$head_port43 + 12 >> 2] = HEAP32[$23 + 12 >> 2] | 0;
+ HEAP32[$head_port43 + 16 >> 2] = HEAP32[$23 + 16 >> 2] | 0;
+ HEAP32[$head_port43 + 20 >> 2] = HEAP32[$23 + 20 >> 2] | 0;
+ HEAP32[$head_port43 + 24 >> 2] = HEAP32[$23 + 24 >> 2] | 0;
+ HEAP32[$head_port43 + 28 >> 2] = HEAP32[$23 + 28 >> 2] | 0;
+ HEAP32[$head_port43 + 32 >> 2] = HEAP32[$23 + 32 >> 2] | 0;
+ HEAP32[$head_port43 + 36 >> 2] = HEAP32[$23 + 36 >> 2] | 0;
+ label = 11;
+ break;
+ case 11:
+ $to_virt = $orig + 188 | 0;
+ $24 = HEAP32[$to_virt >> 2] | 0;
+ $cmp49 = ($24 | 0) == 0;
+ if ($cmp49) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ HEAP32[$to_virt >> 2] = $0;
+ label = 13;
+ break;
+ case 13:
+ $to_orig = $call + 132 | 0;
+ $25 = $to_orig;
+ HEAP32[$25 >> 2] = $orig;
+ label = 15;
+ break;
+ case 14:
+ $weight57 = $call + 172 | 0;
+ $26 = $weight57;
+ HEAPF32[$26 >> 2] = 1.0;
+ $xpenalty59 = $call + 170 | 0;
+ $27 = $xpenalty59;
+ HEAP16[$27 >> 1] = 1;
+ $count61 = $call + 184 | 0;
+ $28 = $count61;
+ HEAP16[$28 >> 1] = 1;
+ $minlen63 = $call + 186 | 0;
+ $29 = $minlen63;
+ HEAP16[$29 >> 1] = 1;
+ label = 15;
+ break;
+ case 15:
+ return $0 | 0;
+ }
+ return 0;
+}
+function _virtual_edge($u, $v, $orig) {
+ $u = $u | 0;
+ $v = $v | 0;
+ $orig = $orig | 0;
+ return _fast_edge(_new_virtual_edge($u, $v, $orig) | 0) | 0;
+}
+function _virtual_node($g) {
+ $g = $g | 0;
+ var $call = 0, $0 = 0, $n_nodes = 0;
+ $call = _zmalloc(304) | 0;
+ $0 = $call;
+ HEAP32[$call + 12 >> 2] = 102808;
+ HEAP32[$call + 20 >> 2] = $g;
+ HEAP8[$call + 162 | 0] = 1;
+ HEAPF64[$call + 112 >> 3] = 1.0;
+ HEAPF64[$call + 104 >> 3] = 1.0;
+ HEAPF64[$call + 96 >> 3] = 1.0;
+ HEAP32[$call + 220 >> 2] = 1;
+ HEAP32[$call + 180 >> 2] = 0;
+ HEAP32[$call + 176 >> 2] = _zmalloc(20) | 0;
+ HEAP32[$call + 188 >> 2] = 0;
+ HEAP32[$call + 184 >> 2] = _zmalloc(20) | 0;
+ _fast_node($g, $0);
+ $n_nodes = $g + 244 | 0;
+ HEAP32[$n_nodes >> 2] = (HEAP32[$n_nodes >> 2] | 0) + 1 | 0;
+ return $0 | 0;
+}
+function _flat_edge($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $list = 0, $1 = 0, $tobool = 0, $2 = 0, $size = 0, $3 = 0, $add = 0, $mul = 0, $call = 0, $size11 = 0, $4 = 0, $add12 = 0, $mul13 = 0, $call14 = 0, $call_sink = 0, $5 = 0, $6 = 0, $list18 = 0, $7 = 0, $size22 = 0, $8 = 0, $inc = 0, $9 = 0, $list26 = 0, $10 = 0, $arrayidx = 0, $11 = 0, $size30 = 0, $12 = 0, $list34 = 0, $13 = 0, $arrayidx35 = 0, $head = 0, $14 = 0, $list38 = 0, $15 = 0, $tobool39 = 0, $16 = 0, $size48 = 0, $17 = 0, $add49 = 0, $mul50 = 0, $call51 = 0, $size56 = 0, $18 = 0, $add57 = 0, $mul58 = 0, $call59 = 0, $call51_sink = 0, $19 = 0, $20 = 0, $list65 = 0, $21 = 0, $size69 = 0, $22 = 0, $inc70 = 0, $23 = 0, $list74 = 0, $24 = 0, $arrayidx75 = 0, $25 = 0, $size79 = 0, $26 = 0, $list83 = 0, $27 = 0, $arrayidx84 = 0, $has_flat_edges = 0, $root = 0, $28 = 0, $has_flat_edges88 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $list = $0 + 192 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $1;
+ $size = $0 + 196 | 0;
+ $3 = HEAP32[$size >> 2] | 0;
+ $add = $3 << 2;
+ $mul = $add + 8 | 0;
+ $call = _grealloc($2, $mul) | 0;
+ $call_sink = $call;
+ label = 5;
+ break;
+ case 4:
+ $size11 = $0 + 196 | 0;
+ $4 = HEAP32[$size11 >> 2] | 0;
+ $add12 = $4 << 2;
+ $mul13 = $add12 + 8 | 0;
+ $call14 = _gmalloc($mul13) | 0;
+ $call_sink = $call14;
+ label = 5;
+ break;
+ case 5:
+ $5 = $call_sink;
+ $6 = HEAP32[$tail >> 2] | 0;
+ $list18 = $6 + 192 | 0;
+ HEAP32[$list18 >> 2] = $5;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $size22 = $7 + 196 | 0;
+ $8 = HEAP32[$size22 >> 2] | 0;
+ $inc = $8 + 1 | 0;
+ HEAP32[$size22 >> 2] = $inc;
+ $9 = HEAP32[$tail >> 2] | 0;
+ $list26 = $9 + 192 | 0;
+ $10 = HEAP32[$list26 >> 2] | 0;
+ $arrayidx = $10 + ($8 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $e;
+ $11 = HEAP32[$tail >> 2] | 0;
+ $size30 = $11 + 196 | 0;
+ $12 = HEAP32[$size30 >> 2] | 0;
+ $list34 = $11 + 192 | 0;
+ $13 = HEAP32[$list34 >> 2] | 0;
+ $arrayidx35 = $13 + ($12 << 2) | 0;
+ HEAP32[$arrayidx35 >> 2] = 0;
+ $head = $e + 12 | 0;
+ $14 = HEAP32[$head >> 2] | 0;
+ $list38 = $14 + 200 | 0;
+ $15 = HEAP32[$list38 >> 2] | 0;
+ $tobool39 = ($15 | 0) == 0;
+ if ($tobool39) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $16 = $15;
+ $size48 = $14 + 204 | 0;
+ $17 = HEAP32[$size48 >> 2] | 0;
+ $add49 = $17 << 2;
+ $mul50 = $add49 + 8 | 0;
+ $call51 = _grealloc($16, $mul50) | 0;
+ $call51_sink = $call51;
+ label = 8;
+ break;
+ case 7:
+ $size56 = $14 + 204 | 0;
+ $18 = HEAP32[$size56 >> 2] | 0;
+ $add57 = $18 << 2;
+ $mul58 = $add57 + 8 | 0;
+ $call59 = _gmalloc($mul58) | 0;
+ $call51_sink = $call59;
+ label = 8;
+ break;
+ case 8:
+ $19 = $call51_sink;
+ $20 = HEAP32[$head >> 2] | 0;
+ $list65 = $20 + 200 | 0;
+ HEAP32[$list65 >> 2] = $19;
+ $21 = HEAP32[$head >> 2] | 0;
+ $size69 = $21 + 204 | 0;
+ $22 = HEAP32[$size69 >> 2] | 0;
+ $inc70 = $22 + 1 | 0;
+ HEAP32[$size69 >> 2] = $inc70;
+ $23 = HEAP32[$head >> 2] | 0;
+ $list74 = $23 + 200 | 0;
+ $24 = HEAP32[$list74 >> 2] | 0;
+ $arrayidx75 = $24 + ($22 << 2) | 0;
+ HEAP32[$arrayidx75 >> 2] = $e;
+ $25 = HEAP32[$head >> 2] | 0;
+ $size79 = $25 + 204 | 0;
+ $26 = HEAP32[$size79 >> 2] | 0;
+ $list83 = $25 + 200 | 0;
+ $27 = HEAP32[$list83 >> 2] | 0;
+ $arrayidx84 = $27 + ($26 << 2) | 0;
+ HEAP32[$arrayidx84 >> 2] = 0;
+ $has_flat_edges = $g + 252 | 0;
+ HEAP8[$has_flat_edges] = 1;
+ $root = $g + 32 | 0;
+ $28 = HEAP32[$root >> 2] | 0;
+ $has_flat_edges88 = $28 + 252 | 0;
+ HEAP8[$has_flat_edges88] = 1;
+ return;
+ }
+}
+function _delete_fast_edge($e) {
+ $e = $e | 0;
+ var $cmp = 0, $tail = 0, $0 = 0, $out = 0, $head = 0, $1 = 0, $in = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($e | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(110136, 117, 164416, 147040);
+ case 4:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $out = $0 + 184 | 0;
+ _zapinlist($out, $e);
+ $head = $e + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $in = $1 + 176 | 0;
+ _zapinlist($in, $e);
+ return;
+ }
+}
+function _fast_node($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $nlist = 0, $0 = 0, $next = 0, $tobool = 0, $prev = 0, $prev10 = 0, $1 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $0 = HEAP32[$nlist >> 2] | 0;
+ $next = $n + 168 | 0;
+ HEAP32[$next >> 2] = $0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $prev = $0 + 172 | 0;
+ HEAP32[$prev >> 2] = $n;
+ label = 4;
+ break;
+ case 4:
+ HEAP32[$nlist >> 2] = $n;
+ $prev10 = $n + 172 | 0;
+ HEAP32[$prev10 >> 2] = 0;
+ $1 = HEAP32[$next >> 2] | 0;
+ $cmp = ($1 | 0) == ($n | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ ___assert_func(110136, 215, 164312, 122080);
+ case 6:
+ return;
+ }
+}
+function _fast_nodeapp($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ var $cmp = 0, $next = 0, $0 = 0, $cmp2 = 0, $next7 = 0, $1 = 0, $2 = 0, $tobool = 0, $prev = 0, $prev16 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($u | 0) == ($v | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(110136, 220, 164296, 116120);
+ case 4:
+ $next = $v + 168 | 0;
+ $0 = HEAP32[$next >> 2] | 0;
+ $cmp2 = ($0 | 0) == 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ ___assert_func(110136, 221, 164296, 111008);
+ case 6:
+ $next7 = $u + 168 | 0;
+ $1 = HEAP32[$next7 >> 2] | 0;
+ HEAP32[$next >> 2] = $1;
+ $2 = HEAP32[$next7 >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $prev = $2 + 172 | 0;
+ HEAP32[$prev >> 2] = $v;
+ label = 8;
+ break;
+ case 8:
+ $prev16 = $v + 172 | 0;
+ HEAP32[$prev16 >> 2] = $u;
+ HEAP32[$next7 >> 2] = $v;
+ return;
+ }
+}
+function _delete_fast_node($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $call = 0, $tobool = 0, $next = 0, $0 = 0, $tobool1 = 0, $prev = 0, $1 = 0, $prev6 = 0, $prev8 = 0, $2 = 0, $tobool9 = 0, $3 = 0, $next16 = 0, $nlist = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _find_fast_node($g, $n) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(110136, 231, 164392, 106800);
+ case 4:
+ $next = $n + 168 | 0;
+ $0 = HEAP32[$next >> 2] | 0;
+ $tobool1 = ($0 | 0) == 0;
+ if ($tobool1) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $prev = $n + 172 | 0;
+ $1 = HEAP32[$prev >> 2] | 0;
+ $prev6 = $0 + 172 | 0;
+ HEAP32[$prev6 >> 2] = $1;
+ label = 6;
+ break;
+ case 6:
+ $prev8 = $n + 172 | 0;
+ $2 = HEAP32[$prev8 >> 2] | 0;
+ $tobool9 = ($2 | 0) == 0;
+ $3 = HEAP32[$next >> 2] | 0;
+ if ($tobool9) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $next16 = $2 + 168 | 0;
+ HEAP32[$next16 >> 2] = $3;
+ label = 9;
+ break;
+ case 8:
+ $nlist = $g + 220 | 0;
+ HEAP32[$nlist >> 2] = $3;
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _delete_flat_edge($e) {
+ $e = $e | 0;
+ var $cmp = 0, $to_orig = 0, $0 = 0, $tobool = 0, $to_virt = 0, $1 = 0, $cmp4 = 0, $tail = 0, $2 = 0, $flat_out = 0, $head = 0, $3 = 0, $flat_in = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($e | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(110136, 272, 164368, 147040);
+ case 4:
+ $to_orig = $e + 132 | 0;
+ $0 = HEAP32[$to_orig >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $to_virt = $0 + 188 | 0;
+ $1 = HEAP32[$to_virt >> 2] | 0;
+ $cmp4 = ($1 | 0) == ($e | 0);
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ HEAP32[$to_virt >> 2] = 0;
+ label = 7;
+ break;
+ case 7:
+ $tail = $e + 16 | 0;
+ $2 = HEAP32[$tail >> 2] | 0;
+ $flat_out = $2 + 192 | 0;
+ _zapinlist($flat_out, $e);
+ $head = $e + 12 | 0;
+ $3 = HEAP32[$head >> 2] | 0;
+ $flat_in = $3 + 200 | 0;
+ _zapinlist($flat_in, $e);
+ return;
+ }
+}
+function _merge_oneway($e, $rep) {
+ $e = $e | 0;
+ $rep = $rep | 0;
+ var $to_virt = 0, $0 = 0, $cmp = 0, $call = 0, $cmp3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $to_virt = $e + 188 | 0;
+ $0 = HEAP32[$to_virt >> 2] | 0;
+ $cmp = ($0 | 0) == ($rep | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _agerr(0, 98512, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ label = 7;
+ break;
+ case 4:
+ $cmp3 = ($0 | 0) == 0;
+ if ($cmp3) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ ___assert_func(110136, 343, 164016, 94648);
+ case 6:
+ HEAP32[$to_virt >> 2] = $rep;
+ _basic_merge($e, $rep);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _unrep($rep, $e) {
+ $rep = $rep | 0;
+ $e = $e | 0;
+ var $count2 = 0, $xpenalty8 = 0, $weight14 = 0;
+ $count2 = $rep + 184 | 0;
+ HEAP16[$count2 >> 1] = (HEAP16[$count2 >> 1] | 0) - (HEAP16[$e + 184 >> 1] | 0) & 65535;
+ $xpenalty8 = $rep + 170 | 0;
+ HEAP16[$xpenalty8 >> 1] = (HEAP16[$xpenalty8 >> 1] | 0) - (HEAP16[$e + 170 >> 1] | 0) & 65535;
+ $weight14 = $rep + 172 | 0;
+ HEAPF32[$weight14 >> 2] = +HEAPF32[$weight14 >> 2] - +HEAPF32[$e + 172 >> 2];
+ return;
+}
+function _flatAdjacent($e) {
+ $e = $e | 0;
+ var $tail = 0, $0 = 0, $head = 0, $1 = 0, $order = 0, $2 = 0, $order2 = 0, $3 = 0, $cmp = 0, $_ = 0, $_14 = 0, $rank12 = 0, $4 = 0, $graph = 0, $5 = 0, $rank14 = 0, $6 = 0, $v = 0, $i_0_in = 0, $i_0 = 0, $cmp15 = 0, $7 = 0, $arrayidx16 = 0, $8 = 0, $node_type = 0, $9 = 0, $cmp18 = 0, $label = 0, $10 = 0, $tobool = 0, $_pr = 0, $11 = 0, $cmp24 = 0, $cmp28 = 0, $conv29 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $head = $e + 12 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $order = $0 + 240 | 0;
+ $2 = HEAP32[$order >> 2] | 0;
+ $order2 = $1 + 240 | 0;
+ $3 = HEAP32[$order2 >> 2] | 0;
+ $cmp = ($2 | 0) < ($3 | 0);
+ $_ = $cmp ? $3 : $2;
+ $_14 = $cmp ? $2 : $3;
+ $rank12 = $0 + 236 | 0;
+ $4 = HEAP32[$rank12 >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $5 = HEAP32[$graph >> 2] | 0;
+ $rank14 = $5 + 224 | 0;
+ $6 = HEAP32[$rank14 >> 2] | 0;
+ $v = $6 + ($4 * 44 & -1) + 4 | 0;
+ $i_0_in = $_14;
+ label = 3;
+ break;
+ case 3:
+ $i_0 = $i_0_in + 1 | 0;
+ $cmp15 = ($i_0 | 0) < ($_ | 0);
+ if ($cmp15) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $7 = HEAP32[$v >> 2] | 0;
+ $arrayidx16 = $7 + ($i_0 << 2) | 0;
+ $8 = HEAP32[$arrayidx16 >> 2] | 0;
+ $node_type = $8 + 162 | 0;
+ $9 = HEAP8[$node_type] | 0;
+ $cmp18 = $9 << 24 >> 24 == 1;
+ if ($cmp18) {
+ label = 5;
+ break;
+ } else {
+ $11 = $9;
+ label = 7;
+ break;
+ }
+ case 5:
+ $label = $8 + 120 | 0;
+ $10 = HEAP32[$label >> 2] | 0;
+ $tobool = ($10 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $_pr = HEAP8[$node_type] | 0;
+ $11 = $_pr;
+ label = 7;
+ break;
+ case 7:
+ $cmp24 = $11 << 24 >> 24 == 0;
+ if ($cmp24) {
+ label = 8;
+ break;
+ } else {
+ $i_0_in = $i_0;
+ label = 3;
+ break;
+ }
+ case 8:
+ $cmp28 = ($i_0 | 0) == ($_ | 0);
+ $conv29 = $cmp28 & 1;
+ return $conv29 | 0;
+ }
+ return 0;
+}
+function _findlr($u, $v, $lp, $rp) {
+ $u = $u | 0;
+ $v = $v | 0;
+ $lp = $lp | 0;
+ $rp = $rp | 0;
+ var $0 = 0, $1 = 0, $cmp = 0;
+ $0 = HEAP32[$u + 240 >> 2] | 0;
+ $1 = HEAP32[$v + 240 >> 2] | 0;
+ $cmp = ($0 | 0) > ($1 | 0);
+ HEAP32[$lp >> 2] = $cmp ? $1 : $0;
+ HEAP32[$rp >> 2] = $cmp ? $0 : $1;
+ return;
+}
+function _unmerge_oneway($e) {
+ $e = $e | 0;
+ var $to_virt = 0, $0 = 0, $tobool17 = 0, $tobool = 0, $rep_018 = 0, $to_virt2 = 0, $1 = 0, $count = 0, $2 = 0, $cmp = 0, $edge_type14 = 0, $3 = 0, $cmp715 = 0, $rep_116 = 0, $head = 0, $4 = 0, $node_type = 0, $5 = 0, $cmp11 = 0, $size = 0, $6 = 0, $cmp15 = 0, $list = 0, $7 = 0, $8 = 0, $edge_type = 0, $9 = 0, $cmp7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $to_virt = $e + 188 | 0;
+ $0 = HEAP32[$to_virt >> 2] | 0;
+ $tobool17 = ($0 | 0) == 0;
+ if ($tobool17) {
+ label = 10;
+ break;
+ } else {
+ $rep_018 = $0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ $rep_018 = $1;
+ label = 4;
+ break;
+ }
+ case 4:
+ _unrep($rep_018, $e);
+ $to_virt2 = $rep_018 + 188 | 0;
+ $1 = HEAP32[$to_virt2 >> 2] | 0;
+ $count = $rep_018 + 184 | 0;
+ $2 = HEAP16[$count >> 1] | 0;
+ $cmp = $2 << 16 >> 16 == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ _safe_delete_fast_edge($rep_018);
+ label = 6;
+ break;
+ case 6:
+ $edge_type14 = $rep_018 + 128 | 0;
+ $3 = HEAP8[$edge_type14] | 0;
+ $cmp715 = $3 << 24 >> 24 == 1;
+ if ($cmp715) {
+ $rep_116 = $rep_018;
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 7:
+ $head = $rep_116 + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ $node_type = $4 + 162 | 0;
+ $5 = HEAP8[$node_type] | 0;
+ $cmp11 = $5 << 24 >> 24 == 1;
+ if ($cmp11) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 8:
+ $size = $4 + 188 | 0;
+ $6 = HEAP32[$size >> 2] | 0;
+ $cmp15 = ($6 | 0) == 1;
+ if ($cmp15) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 9:
+ $list = $4 + 184 | 0;
+ $7 = HEAP32[$list >> 2] | 0;
+ $8 = HEAP32[$7 >> 2] | 0;
+ _unrep($8, $e);
+ $edge_type = $8 + 128 | 0;
+ $9 = HEAP8[$edge_type] | 0;
+ $cmp7 = $9 << 24 >> 24 == 1;
+ if ($cmp7) {
+ $rep_116 = $8;
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 10:
+ HEAP32[$to_virt >> 2] = 0;
+ return;
+ }
+}
+function _flat_edges($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_078 = 0, $tobool79 = 0, $n_080 = 0, $list = 0, $0 = 0, $tobool2 = 0, $1 = 0, $2 = 0, $tobool776 = 0, $3 = 0, $j_077 = 0, $call = 0, $tobool9 = 0, $adjacent = 0, $inc = 0, $4 = 0, $arrayidx = 0, $5 = 0, $tobool7 = 0, $next = 0, $n_0 = 0, $tobool = 0, $rank = 0, $6 = 0, $flat = 0, $7 = 0, $tobool18 = 0, $n_cluster = 0, $8 = 0, $cmp = 0, $9 = 0, $v72 = 0, $10 = 0, $11 = 0, $tobool2673 = 0, $12 = 0, $i_074 = 0, $list30 = 0, $13 = 0, $14 = 0, $tobool3270 = 0, $15 = 0, $j_171 = 0, $label = 0, $16 = 0, $tobool35 = 0, $adjacent37 = 0, $17 = 0, $tobool38 = 0, $inc42 = 0, $18 = 0, $arrayidx31 = 0, $19 = 0, $tobool32 = 0, $inc48 = 0, $20 = 0, $v = 0, $21 = 0, $arrayidx25 = 0, $22 = 0, $tobool26 = 0, $n_163 = 0, $tobool5464 = 0, $rankdir132 = 0, $rankdir = 0, $n_166 = 0, $reset_065 = 0, $list58 = 0, $23 = 0, $tobool59 = 0, $24 = 0, $25 = 0, $tobool6656 = 0, $26 = 0, $reset_158 = 0, $i_157 = 0, $label69 = 0, $27 = 0, $tobool70 = 0, $adjacent73 = 0, $28 = 0, $tobool74 = 0, $29 = 0, $and77 = 0, $tobool78 = 0, $y = 0, $30 = 0.0, $dist = 0, $x = 0, $31 = 0.0, $dist87 = 0, $reset_2 = 0, $inc93 = 0, $32 = 0, $arrayidx65 = 0, $33 = 0, $tobool66 = 0, $reset_1_lcssa = 0, $size = 0, $34 = 0, $cmp9759 = 0, $list101 = 0, $reset_361 = 0, $j_260 = 0, $35 = 0, $arrayidx102 = 0, $36 = 0, $tail = 0, $37 = 0, $rank104 = 0, $38 = 0, $head = 0, $39 = 0, $rank106 = 0, $40 = 0, $cmp107 = 0, $cmp112 = 0, $or_cond = 0, $le_0 = 0, $to_virt = 0, $41 = 0, $tobool116 = 0, $adjacent120 = 0, $42 = 0, $adjacent122 = 0, $label124 = 0, $43 = 0, $tobool125 = 0, $tobool129 = 0, $44 = 0, $and134 = 0, $tobool135 = 0, $y140 = 0, $x145 = 0, $lw_0_in = 0, $lw_0 = 0.0, $dist148 = 0, $45 = 0.0, $cmp149 = 0, $lw_0_ = 0.0, $reset_4 = 0, $inc158 = 0, $46 = 0, $cmp97 = 0, $reset_5 = 0, $next163 = 0, $n_1 = 0, $tobool54 = 0, $tobool165 = 0, $reset_0_lcssa82 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $n_078 = HEAP32[$nlist >> 2] | 0;
+ $tobool79 = ($n_078 | 0) == 0;
+ if ($tobool79) {
+ label = 9;
+ break;
+ } else {
+ $n_080 = $n_078;
+ label = 3;
+ break;
+ }
+ case 3:
+ $list = $n_080 + 192 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $tobool2 = ($0 | 0) == 0;
+ if ($tobool2) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool776 = ($2 | 0) == 0;
+ if ($tobool776) {
+ label = 8;
+ break;
+ } else {
+ $j_077 = 0;
+ $3 = $2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $call = _flatAdjacent($3) | 0;
+ $tobool9 = ($call | 0) == 0;
+ if ($tobool9) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $adjacent = $3 + 129 | 0;
+ HEAP8[$adjacent] = 1;
+ label = 7;
+ break;
+ case 7:
+ $inc = $j_077 + 1 | 0;
+ $4 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $4 + ($inc << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool7 = ($5 | 0) == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ $j_077 = $inc;
+ $3 = $5;
+ label = 5;
+ break;
+ }
+ case 8:
+ $next = $n_080 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ $n_080 = $n_0;
+ label = 3;
+ break;
+ }
+ case 9:
+ $rank = $g + 224 | 0;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $flat = $6 + 40 | 0;
+ $7 = HEAP32[$flat >> 2] | 0;
+ $tobool18 = ($7 | 0) == 0;
+ if ($tobool18) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $n_cluster = $g + 212 | 0;
+ $8 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($8 | 0) > 0;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 11:
+ $9 = HEAP32[$rank >> 2] | 0;
+ $v72 = $9 + 4 | 0;
+ $10 = HEAP32[$v72 >> 2] | 0;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $tobool2673 = ($11 | 0) == 0;
+ if ($tobool2673) {
+ label = 18;
+ break;
+ } else {
+ $i_074 = 0;
+ $12 = $11;
+ label = 12;
+ break;
+ }
+ case 12:
+ $list30 = $12 + 200 | 0;
+ $13 = HEAP32[$list30 >> 2] | 0;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $tobool3270 = ($14 | 0) == 0;
+ if ($tobool3270) {
+ label = 17;
+ break;
+ } else {
+ $j_171 = 0;
+ $15 = $14;
+ label = 13;
+ break;
+ }
+ case 13:
+ $label = $15 + 112 | 0;
+ $16 = HEAP32[$label >> 2] | 0;
+ $tobool35 = ($16 | 0) == 0;
+ if ($tobool35) {
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $adjacent37 = $15 + 129 | 0;
+ $17 = HEAP8[$adjacent37] | 0;
+ $tobool38 = $17 << 24 >> 24 == 0;
+ if ($tobool38) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ _abomination($g);
+ label = 18;
+ break;
+ case 16:
+ $inc42 = $j_171 + 1 | 0;
+ $18 = HEAP32[$list30 >> 2] | 0;
+ $arrayidx31 = $18 + ($inc42 << 2) | 0;
+ $19 = HEAP32[$arrayidx31 >> 2] | 0;
+ $tobool32 = ($19 | 0) == 0;
+ if ($tobool32) {
+ label = 17;
+ break;
+ } else {
+ $j_171 = $inc42;
+ $15 = $19;
+ label = 13;
+ break;
+ }
+ case 17:
+ $inc48 = $i_074 + 1 | 0;
+ $20 = HEAP32[$rank >> 2] | 0;
+ $v = $20 + 4 | 0;
+ $21 = HEAP32[$v >> 2] | 0;
+ $arrayidx25 = $21 + ($inc48 << 2) | 0;
+ $22 = HEAP32[$arrayidx25 >> 2] | 0;
+ $tobool26 = ($22 | 0) == 0;
+ if ($tobool26) {
+ label = 18;
+ break;
+ } else {
+ $i_074 = $inc48;
+ $12 = $22;
+ label = 12;
+ break;
+ }
+ case 18:
+ _rec_save_vlists($g);
+ $n_163 = HEAP32[$nlist >> 2] | 0;
+ $tobool5464 = ($n_163 | 0) == 0;
+ if ($tobool5464) {
+ $reset_0_lcssa82 = 0;
+ label = 41;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $rankdir132 = $g + 156 | 0;
+ $rankdir = $g + 156 | 0;
+ $reset_065 = 0;
+ $n_166 = $n_163;
+ label = 20;
+ break;
+ case 20:
+ $list58 = $n_166 + 192 | 0;
+ $23 = HEAP32[$list58 >> 2] | 0;
+ $tobool59 = ($23 | 0) == 0;
+ if ($tobool59) {
+ $reset_5 = $reset_065;
+ label = 38;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $24 = HEAP32[$list58 >> 2] | 0;
+ $25 = HEAP32[$24 >> 2] | 0;
+ $tobool6656 = ($25 | 0) == 0;
+ if ($tobool6656) {
+ $reset_1_lcssa = $reset_065;
+ label = 29;
+ break;
+ } else {
+ $i_157 = 0;
+ $reset_158 = $reset_065;
+ $26 = $25;
+ label = 22;
+ break;
+ }
+ case 22:
+ $label69 = $26 + 112 | 0;
+ $27 = HEAP32[$label69 >> 2] | 0;
+ $tobool70 = ($27 | 0) == 0;
+ if ($tobool70) {
+ $reset_2 = $reset_158;
+ label = 28;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $adjacent73 = $26 + 129 | 0;
+ $28 = HEAP8[$adjacent73] | 0;
+ $tobool74 = $28 << 24 >> 24 == 0;
+ if ($tobool74) {
+ label = 27;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $29 = HEAP32[$rankdir >> 2] | 0;
+ $and77 = $29 & 1;
+ $tobool78 = ($and77 | 0) == 0;
+ if ($tobool78) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $y = $27 + 32 | 0;
+ $30 = +HEAPF64[$y >> 3];
+ $dist = $26 + 152 | 0;
+ HEAPF64[$dist >> 3] = $30;
+ $reset_2 = $reset_158;
+ label = 28;
+ break;
+ case 26:
+ $x = $27 + 24 | 0;
+ $31 = +HEAPF64[$x >> 3];
+ $dist87 = $26 + 152 | 0;
+ HEAPF64[$dist87 >> 3] = $31;
+ $reset_2 = $reset_158;
+ label = 28;
+ break;
+ case 27:
+ _flat_node($26);
+ $reset_2 = 1;
+ label = 28;
+ break;
+ case 28:
+ $inc93 = $i_157 + 1 | 0;
+ $32 = HEAP32[$list58 >> 2] | 0;
+ $arrayidx65 = $32 + ($inc93 << 2) | 0;
+ $33 = HEAP32[$arrayidx65 >> 2] | 0;
+ $tobool66 = ($33 | 0) == 0;
+ if ($tobool66) {
+ $reset_1_lcssa = $reset_2;
+ label = 29;
+ break;
+ } else {
+ $i_157 = $inc93;
+ $reset_158 = $reset_2;
+ $26 = $33;
+ label = 22;
+ break;
+ }
+ case 29:
+ $size = $n_166 + 212 | 0;
+ $34 = HEAP32[$size >> 2] | 0;
+ $cmp9759 = ($34 | 0) > 0;
+ if ($cmp9759) {
+ label = 30;
+ break;
+ } else {
+ $reset_5 = $reset_1_lcssa;
+ label = 38;
+ break;
+ }
+ case 30:
+ $list101 = $n_166 + 208 | 0;
+ $j_260 = 0;
+ $reset_361 = $reset_1_lcssa;
+ label = 31;
+ break;
+ case 31:
+ $35 = HEAP32[$list101 >> 2] | 0;
+ $arrayidx102 = $35 + ($j_260 << 2) | 0;
+ $36 = HEAP32[$arrayidx102 >> 2] | 0;
+ $tail = $36 + 16 | 0;
+ $37 = HEAP32[$tail >> 2] | 0;
+ $rank104 = $37 + 236 | 0;
+ $38 = HEAP32[$rank104 >> 2] | 0;
+ $head = $36 + 12 | 0;
+ $39 = HEAP32[$head >> 2] | 0;
+ $rank106 = $39 + 236 | 0;
+ $40 = HEAP32[$rank106 >> 2] | 0;
+ $cmp107 = ($38 | 0) != ($40 | 0);
+ $cmp112 = ($37 | 0) == ($39 | 0);
+ $or_cond = $cmp107 | $cmp112;
+ if ($or_cond) {
+ $reset_4 = $reset_361;
+ label = 37;
+ break;
+ } else {
+ $le_0 = $36;
+ label = 32;
+ break;
+ }
+ case 32:
+ $to_virt = $le_0 + 188 | 0;
+ $41 = HEAP32[$to_virt >> 2] | 0;
+ $tobool116 = ($41 | 0) == 0;
+ if ($tobool116) {
+ label = 33;
+ break;
+ } else {
+ $le_0 = $41;
+ label = 32;
+ break;
+ }
+ case 33:
+ $adjacent120 = $le_0 + 129 | 0;
+ $42 = HEAP8[$adjacent120] | 0;
+ $adjacent122 = $36 + 129 | 0;
+ HEAP8[$adjacent122] = $42;
+ $label124 = $36 + 112 | 0;
+ $43 = HEAP32[$label124 >> 2] | 0;
+ $tobool125 = ($43 | 0) == 0;
+ if ($tobool125) {
+ $reset_4 = $reset_361;
+ label = 37;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $tobool129 = $42 << 24 >> 24 == 0;
+ if ($tobool129) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $44 = HEAP32[$rankdir132 >> 2] | 0;
+ $and134 = $44 & 1;
+ $tobool135 = ($and134 | 0) == 0;
+ $y140 = $43 + 32 | 0;
+ $x145 = $43 + 24 | 0;
+ $lw_0_in = $tobool135 ? $x145 : $y140;
+ $lw_0 = +HEAPF64[$lw_0_in >> 3];
+ $dist148 = $le_0 + 152 | 0;
+ $45 = +HEAPF64[$dist148 >> 3];
+ $cmp149 = $lw_0 > $45;
+ $lw_0_ = $cmp149 ? $lw_0 : $45;
+ HEAPF64[$dist148 >> 3] = $lw_0_;
+ $reset_4 = $reset_361;
+ label = 37;
+ break;
+ case 36:
+ _flat_node($36);
+ $reset_4 = 1;
+ label = 37;
+ break;
+ case 37:
+ $inc158 = $j_260 + 1 | 0;
+ $46 = HEAP32[$size >> 2] | 0;
+ $cmp97 = ($inc158 | 0) < ($46 | 0);
+ if ($cmp97) {
+ $j_260 = $inc158;
+ $reset_361 = $reset_4;
+ label = 31;
+ break;
+ } else {
+ $reset_5 = $reset_4;
+ label = 38;
+ break;
+ }
+ case 38:
+ $next163 = $n_166 + 168 | 0;
+ $n_1 = HEAP32[$next163 >> 2] | 0;
+ $tobool54 = ($n_1 | 0) == 0;
+ if ($tobool54) {
+ label = 39;
+ break;
+ } else {
+ $reset_065 = $reset_5;
+ $n_166 = $n_1;
+ label = 20;
+ break;
+ }
+ case 39:
+ $tobool165 = ($reset_5 | 0) == 0;
+ if ($tobool165) {
+ $reset_0_lcssa82 = 0;
+ label = 41;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ _rec_reset_vlists($g);
+ $reset_0_lcssa82 = $reset_5;
+ label = 41;
+ break;
+ case 41:
+ return $reset_0_lcssa82 | 0;
+ }
+ return 0;
+}
+function _flat_node($e) {
+ $e = $e | 0;
+ var $label = 0, $0 = 0, $cmp = 0, $tail = 0, $1 = 0, $graph = 0, $2 = 0, $rank = 0, $3 = 0, $call = 0, $sub = 0, $rank4 = 0, $4 = 0, $v = 0, $5 = 0, $6 = 0, $tobool = 0, $y = 0, $7 = 0.0, $ht1 = 0, $8 = 0, $conv = 0.0, $sub12 = 0.0, $v17 = 0, $9 = 0, $10 = 0, $y21 = 0, $11 = 0.0, $ht2 = 0, $12 = 0, $conv25 = 0.0, $add = 0.0, $ranksep = 0, $13 = 0, $conv27 = 0.0, $add28 = 0.0, $ypos_0_in = 0.0, $ypos_0 = 0, $call32 = 0, $14 = 0, $dimen_sroa_0_0__idx = 0, $dimen_sroa_0_0_copyload = 0.0, $dimen_sroa_1_8__idx3 = 0, $dimen_sroa_1_8_copyload = 0.0, $rankdir = 0, $15 = 0, $and37 = 0, $tobool38 = 0, $dimen_sroa_1_8_copyload_dimen_sroa_0_0_copyload = 0.0, $dimen_sroa_0_0_copyload_dimen_sroa_1_8_copyload = 0.0, $ht = 0, $div = 0.0, $conv48 = 0, $div50 = 0.0, $rw = 0, $lw = 0, $16 = 0, $label56 = 0, $add57 = 0, $conv58 = 0.0, $y61 = 0, $17 = 0, $call63 = 0, $18 = 0.0, $sub66 = 0.0, $x68 = 0, $19 = 0, $rw71 = 0, $20 = 0.0, $x74 = 0, $edge_type = 0, $head = 0, $21 = 0, $call76 = 0, $22 = 0.0, $x82 = 0, $23 = 0, $lw85 = 0, $24 = 0.0, $x89 = 0, $edge_type91 = 0, $25 = 0, $ht196 = 0, $26 = 0, $cmp97 = 0, $27 = 0, $ht2110 = 0, $28 = 0, $cmp111 = 0, $29 = 0, $alg = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $label = $e + 112 | 0;
+ $0 = HEAP32[$label >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail = $e + 16 | 0;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $graph = $1 + 20 | 0;
+ $2 = HEAP32[$graph >> 2] | 0;
+ $rank = $1 + 236 | 0;
+ $3 = HEAP32[$rank >> 2] | 0;
+ $call = _flat_limits($2, $e) | 0;
+ $sub = $3 - 1 | 0;
+ $rank4 = $2 + 224 | 0;
+ $4 = HEAP32[$rank4 >> 2] | 0;
+ $v = $4 + ($sub * 44 & -1) + 4 | 0;
+ $5 = HEAP32[$v >> 2] | 0;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $y = $6 + 40 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $ht1 = $4 + ($sub * 44 & -1) + 16 | 0;
+ $8 = HEAP32[$ht1 >> 2] | 0;
+ $conv = +($8 | 0);
+ $sub12 = $7 - $conv;
+ $ypos_0_in = $sub12;
+ label = 6;
+ break;
+ case 5:
+ $v17 = $4 + ($3 * 44 & -1) + 4 | 0;
+ $9 = HEAP32[$v17 >> 2] | 0;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $y21 = $10 + 40 | 0;
+ $11 = +HEAPF64[$y21 >> 3];
+ $ht2 = $4 + ($3 * 44 & -1) + 20 | 0;
+ $12 = HEAP32[$ht2 >> 2] | 0;
+ $conv25 = +($12 | 0);
+ $add = $11 + $conv25;
+ $ranksep = $2 + 264 | 0;
+ $13 = HEAP32[$ranksep >> 2] | 0;
+ $conv27 = +($13 | 0);
+ $add28 = $add + $conv27;
+ $ypos_0_in = $add28;
+ label = 6;
+ break;
+ case 6:
+ $ypos_0 = ~~$ypos_0_in;
+ $call32 = _make_vn_slot($2, $sub, $call) | 0;
+ $14 = HEAP32[$label >> 2] | 0;
+ $dimen_sroa_0_0__idx = $14 + 24 | 0;
+ $dimen_sroa_0_0_copyload = +HEAPF64[$dimen_sroa_0_0__idx >> 3];
+ $dimen_sroa_1_8__idx3 = $14 + 32 | 0;
+ $dimen_sroa_1_8_copyload = +HEAPF64[$dimen_sroa_1_8__idx3 >> 3];
+ $rankdir = $2 + 156 | 0;
+ $15 = HEAP32[$rankdir >> 2] | 0;
+ $and37 = $15 & 1;
+ $tobool38 = ($and37 | 0) == 0;
+ $dimen_sroa_1_8_copyload_dimen_sroa_0_0_copyload = $tobool38 ? $dimen_sroa_1_8_copyload : $dimen_sroa_0_0_copyload;
+ $dimen_sroa_0_0_copyload_dimen_sroa_1_8_copyload = $tobool38 ? $dimen_sroa_0_0_copyload : $dimen_sroa_1_8_copyload;
+ $ht = $call32 + 96 | 0;
+ HEAPF64[$ht >> 3] = $dimen_sroa_1_8_copyload_dimen_sroa_0_0_copyload;
+ $div = $dimen_sroa_1_8_copyload_dimen_sroa_0_0_copyload * .5;
+ $conv48 = ~~$div;
+ $div50 = $dimen_sroa_0_0_copyload_dimen_sroa_1_8_copyload * .5;
+ $rw = $call32 + 112 | 0;
+ HEAPF64[$rw >> 3] = $div50;
+ $lw = $call32 + 104 | 0;
+ HEAPF64[$lw >> 3] = $div50;
+ $16 = HEAP32[$label >> 2] | 0;
+ $label56 = $call32 + 120 | 0;
+ HEAP32[$label56 >> 2] = $16;
+ $add57 = $conv48 + $ypos_0 | 0;
+ $conv58 = +($add57 | 0);
+ $y61 = $call32 + 40 | 0;
+ HEAPF64[$y61 >> 3] = $conv58;
+ $17 = HEAP32[$tail >> 2] | 0;
+ $call63 = _virtual_edge($call32, $17, $e) | 0;
+ $18 = +HEAPF64[$lw >> 3];
+ $sub66 = -0.0 - $18;
+ $x68 = $call63 + 32 | 0;
+ HEAPF64[$x68 >> 3] = $sub66;
+ $19 = HEAP32[$tail >> 2] | 0;
+ $rw71 = $19 + 112 | 0;
+ $20 = +HEAPF64[$rw71 >> 3];
+ $x74 = $call63 + 72 | 0;
+ HEAPF64[$x74 >> 3] = $20;
+ $edge_type = $call63 + 128 | 0;
+ HEAP8[$edge_type] = 4;
+ $head = $e + 12 | 0;
+ $21 = HEAP32[$head >> 2] | 0;
+ $call76 = _virtual_edge($call32, $21, $e) | 0;
+ $22 = +HEAPF64[$rw >> 3];
+ $x82 = $call76 + 32 | 0;
+ HEAPF64[$x82 >> 3] = $22;
+ $23 = HEAP32[$head >> 2] | 0;
+ $lw85 = $23 + 104 | 0;
+ $24 = +HEAPF64[$lw85 >> 3];
+ $x89 = $call76 + 72 | 0;
+ HEAPF64[$x89 >> 3] = $24;
+ $edge_type91 = $call76 + 128 | 0;
+ HEAP8[$edge_type91] = 4;
+ $25 = HEAP32[$rank4 >> 2] | 0;
+ $ht196 = $25 + ($sub * 44 & -1) + 16 | 0;
+ $26 = HEAP32[$ht196 >> 2] | 0;
+ $cmp97 = ($26 | 0) < ($conv48 | 0);
+ if ($cmp97) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$ht196 >> 2] = $conv48;
+ label = 8;
+ break;
+ case 8:
+ $27 = HEAP32[$rank4 >> 2] | 0;
+ $ht2110 = $27 + ($sub * 44 & -1) + 20 | 0;
+ $28 = HEAP32[$ht2110 >> 2] | 0;
+ $cmp111 = ($28 | 0) < ($conv48 | 0);
+ if ($cmp111) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ HEAP32[$ht2110 >> 2] = $conv48;
+ label = 10;
+ break;
+ case 10:
+ $29 = $e | 0;
+ $alg = $call32 + 128 | 0;
+ HEAP32[$alg >> 2] = $29;
+ label = 11;
+ break;
+ case 11:
+ return;
+ }
+}
+function _flat_limits($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $bounds = 0, $lpos = 0, $rpos = 0, $tail = 0, $0 = 0, $rank1 = 0, $1 = 0, $sub = 0, $rank3 = 0, $2 = 0, $v = 0, $3 = 0, $n = 0, $4 = 0, $arrayidx9 = 0, $arrayidx10 = 0, $arrayidx11 = 0, $arrayidx12 = 0, $5 = 0, $head = 0, $6 = 0, $7 = 0, $8 = 0, $rnode_0_in = 0, $lnode_0 = 0, $rnode_0 = 0, $cmp = 0, $arrayidx14 = 0, $9 = 0, $cmp15 = 0, $arrayidx16 = 0, $10 = 0, $inc = 0, $11 = 0, $12 = 0, $sub20 = 0, $cmp21 = 0, $13 = 0, $14 = 0, $cmp26 = 0, $add30 = 0, $15 = 0, $16 = 0, $add34 = 0, $pos_0_in_in = 0, $pos_0_in = 0, $pos_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $bounds = __stackBase__ | 0;
+ $lpos = __stackBase__ + 16 | 0;
+ $rpos = __stackBase__ + 24 | 0;
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $rank1 = $0 + 236 | 0;
+ $1 = HEAP32[$rank1 >> 2] | 0;
+ $sub = $1 - 1 | 0;
+ $rank3 = $g + 224 | 0;
+ $2 = HEAP32[$rank3 >> 2] | 0;
+ $v = $2 + ($sub * 44 & -1) + 4 | 0;
+ $3 = HEAP32[$v >> 2] | 0;
+ $n = $2 + ($sub * 44 & -1) | 0;
+ $4 = HEAP32[$n >> 2] | 0;
+ $arrayidx9 = $bounds + 8 | 0;
+ HEAP32[$arrayidx9 >> 2] = -1;
+ $arrayidx10 = $bounds | 0;
+ HEAP32[$arrayidx10 >> 2] = -1;
+ $arrayidx11 = $bounds + 12 | 0;
+ HEAP32[$arrayidx11 >> 2] = $4;
+ $arrayidx12 = $bounds + 4 | 0;
+ HEAP32[$arrayidx12 >> 2] = $4;
+ $5 = HEAP32[$tail >> 2] | 0;
+ $head = $e + 12 | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ _findlr($5, $6, $lpos, $rpos);
+ $7 = HEAP32[$lpos >> 2] | 0;
+ $8 = HEAP32[$rpos >> 2] | 0;
+ $lnode_0 = 0;
+ $rnode_0_in = $4;
+ label = 3;
+ break;
+ case 3:
+ $rnode_0 = $rnode_0_in - 1 | 0;
+ $cmp = ($lnode_0 | 0) > ($rnode_0 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $arrayidx14 = $3 + ($lnode_0 << 2) | 0;
+ $9 = HEAP32[$arrayidx14 >> 2] | 0;
+ _setbounds($9, $arrayidx10, $7, $8);
+ $cmp15 = ($lnode_0 | 0) == ($rnode_0 | 0);
+ if ($cmp15) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $arrayidx16 = $3 + ($rnode_0 << 2) | 0;
+ $10 = HEAP32[$arrayidx16 >> 2] | 0;
+ _setbounds($10, $arrayidx10, $7, $8);
+ label = 6;
+ break;
+ case 6:
+ $inc = $lnode_0 + 1 | 0;
+ $11 = HEAP32[$arrayidx12 >> 2] | 0;
+ $12 = HEAP32[$arrayidx10 >> 2] | 0;
+ $sub20 = $11 - $12 | 0;
+ $cmp21 = ($sub20 | 0) < 2;
+ if ($cmp21) {
+ label = 7;
+ break;
+ } else {
+ $lnode_0 = $inc;
+ $rnode_0_in = $rnode_0;
+ label = 3;
+ break;
+ }
+ case 7:
+ $13 = HEAP32[$arrayidx10 >> 2] | 0;
+ $14 = HEAP32[$arrayidx12 >> 2] | 0;
+ $cmp26 = ($13 | 0) > ($14 | 0);
+ if ($cmp26) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $add30 = $14 + $13 | 0;
+ $pos_0_in_in = $add30;
+ label = 10;
+ break;
+ case 9:
+ $15 = HEAP32[$arrayidx9 >> 2] | 0;
+ $16 = HEAP32[$arrayidx11 >> 2] | 0;
+ $add34 = $16 + $15 | 0;
+ $pos_0_in_in = $add34;
+ label = 10;
+ break;
+ case 10:
+ $pos_0_in = $pos_0_in_in + 1 | 0;
+ $pos_0 = ($pos_0_in | 0) / 2 & -1;
+ STACKTOP = __stackBase__;
+ return $pos_0 | 0;
+ }
+ return 0;
+}
+function _make_vn_slot($g, $r, $pos) {
+ $g = $g | 0;
+ $r = $r | 0;
+ $pos = $pos | 0;
+ var $rank = 0, $0 = 0, $arrayidx = 0, $v1 = 0, $1 = 0, $tobool = 0, $2 = 0, $n9 = 0, $3 = 0, $add = 0, $mul = 0, $call = 0, $n13 = 0, $4 = 0, $add14 = 0, $mul15 = 0, $call16 = 0, $call_sink = 0, $5 = 0, $6 = 0, $v20 = 0, $7 = 0, $n24 = 0, $8 = 0, $cmp26 = 0, $i_027 = 0, $sub = 0, $arrayidx25 = 0, $9 = 0, $arrayidx26 = 0, $order = 0, $10 = 0, $inc = 0, $cmp = 0, $call29 = 0, $arrayidx30 = 0, $order32 = 0, $rank34 = 0, $11 = 0, $n38 = 0, $12 = 0, $inc39 = 0, $arrayidx40 = 0, $13 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $g + 224 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $arrayidx = $0 + ($r * 44 & -1) | 0;
+ $v1 = $0 + ($r * 44 & -1) + 4 | 0;
+ $1 = HEAP32[$v1 >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $1;
+ $n9 = $arrayidx | 0;
+ $3 = HEAP32[$n9 >> 2] | 0;
+ $add = $3 << 2;
+ $mul = $add + 8 | 0;
+ $call = _grealloc($2, $mul) | 0;
+ $call_sink = $call;
+ label = 5;
+ break;
+ case 4:
+ $n13 = $arrayidx | 0;
+ $4 = HEAP32[$n13 >> 2] | 0;
+ $add14 = $4 << 2;
+ $mul15 = $add14 + 8 | 0;
+ $call16 = _gmalloc($mul15) | 0;
+ $call_sink = $call16;
+ label = 5;
+ break;
+ case 5:
+ $5 = $call_sink;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $v20 = $6 + ($r * 44 & -1) + 4 | 0;
+ HEAP32[$v20 >> 2] = $5;
+ $7 = HEAP32[$rank >> 2] | 0;
+ $n24 = $7 + ($r * 44 & -1) | 0;
+ $8 = HEAP32[$n24 >> 2] | 0;
+ $cmp26 = ($8 | 0) > ($pos | 0);
+ if ($cmp26) {
+ $i_027 = $8;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $sub = $i_027 - 1 | 0;
+ $arrayidx25 = $5 + ($sub << 2) | 0;
+ $9 = HEAP32[$arrayidx25 >> 2] | 0;
+ $arrayidx26 = $5 + ($i_027 << 2) | 0;
+ HEAP32[$arrayidx26 >> 2] = $9;
+ $order = $9 + 240 | 0;
+ $10 = HEAP32[$order >> 2] | 0;
+ $inc = $10 + 1 | 0;
+ HEAP32[$order >> 2] = $inc;
+ $cmp = ($sub | 0) > ($pos | 0);
+ if ($cmp) {
+ $i_027 = $sub;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call29 = _virtual_node($g) | 0;
+ $arrayidx30 = $5 + ($pos << 2) | 0;
+ HEAP32[$arrayidx30 >> 2] = $call29;
+ $order32 = $call29 + 240 | 0;
+ HEAP32[$order32 >> 2] = $pos;
+ $rank34 = $call29 + 236 | 0;
+ HEAP32[$rank34 >> 2] = $r;
+ $11 = HEAP32[$rank >> 2] | 0;
+ $n38 = $11 + ($r * 44 & -1) | 0;
+ $12 = HEAP32[$n38 >> 2] | 0;
+ $inc39 = $12 + 1 | 0;
+ HEAP32[$n38 >> 2] = $inc39;
+ $arrayidx40 = $5 + ($inc39 << 2) | 0;
+ HEAP32[$arrayidx40 >> 2] = 0;
+ $13 = HEAP32[$arrayidx30 >> 2] | 0;
+ return $13 | 0;
+ }
+ return 0;
+}
+function _safe_delete_fast_edge($e) {
+ $e = $e | 0;
+ var $cmp = 0, $tail = 0, $0 = 0, $out18 = 0, $list19 = 0, $1 = 0, $2 = 0, $tobool20 = 0, $head = 0, $3 = 0, $in13 = 0, $list714 = 0, $4 = 0, $5 = 0, $tobool915 = 0, $6 = 0, $out22 = 0, $i_021 = 0, $cmp1 = 0, $inc = 0, $7 = 0, $out = 0, $list = 0, $8 = 0, $arrayidx = 0, $9 = 0, $tobool = 0, $10 = 0, $in17 = 0, $i_116 = 0, $cmp11 = 0, $inc18 = 0, $11 = 0, $in = 0, $list7 = 0, $12 = 0, $arrayidx8 = 0, $13 = 0, $tobool9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($e | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tail = $e + 16 | 0;
+ $0 = HEAP32[$tail >> 2] | 0;
+ $out18 = $0 + 184 | 0;
+ $list19 = $out18 | 0;
+ $1 = HEAP32[$list19 >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool20 = ($2 | 0) == 0;
+ if ($tobool20) {
+ label = 5;
+ break;
+ } else {
+ $i_021 = 0;
+ $out22 = $out18;
+ $6 = $2;
+ label = 6;
+ break;
+ }
+ case 4:
+ ___assert_func(110136, 128, 163880, 147040);
+ case 5:
+ $head = $e + 12 | 0;
+ $3 = HEAP32[$head >> 2] | 0;
+ $in13 = $3 + 176 | 0;
+ $list714 = $in13 | 0;
+ $4 = HEAP32[$list714 >> 2] | 0;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $tobool915 = ($5 | 0) == 0;
+ if ($tobool915) {
+ label = 12;
+ break;
+ } else {
+ $i_116 = 0;
+ $in17 = $in13;
+ $10 = $5;
+ label = 9;
+ break;
+ }
+ case 6:
+ $cmp1 = ($6 | 0) == ($e | 0);
+ if ($cmp1) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ _zapinlist($out22, $e);
+ label = 8;
+ break;
+ case 8:
+ $inc = $i_021 + 1 | 0;
+ $7 = HEAP32[$tail >> 2] | 0;
+ $out = $7 + 184 | 0;
+ $list = $out | 0;
+ $8 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $8 + ($inc << 2) | 0;
+ $9 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($9 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $i_021 = $inc;
+ $out22 = $out;
+ $6 = $9;
+ label = 6;
+ break;
+ }
+ case 9:
+ $cmp11 = ($10 | 0) == ($e | 0);
+ if ($cmp11) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _zapinlist($in17, $e);
+ label = 11;
+ break;
+ case 11:
+ $inc18 = $i_116 + 1 | 0;
+ $11 = HEAP32[$head >> 2] | 0;
+ $in = $11 + 176 | 0;
+ $list7 = $in | 0;
+ $12 = HEAP32[$list7 >> 2] | 0;
+ $arrayidx8 = $12 + ($inc18 << 2) | 0;
+ $13 = HEAP32[$arrayidx8 >> 2] | 0;
+ $tobool9 = ($13 | 0) == 0;
+ if ($tobool9) {
+ label = 12;
+ break;
+ } else {
+ $i_116 = $inc18;
+ $in17 = $in;
+ $10 = $13;
+ label = 9;
+ break;
+ }
+ case 12:
+ return;
+ }
+}
+function _abomination($g) {
+ $g = $g | 0;
+ var $minrank = 0, $0 = 0, $cmp = 0, $maxrank = 0, $1 = 0, $conv3 = 0, $add = 0, $rank = 0, $2 = 0, $tobool = 0, $3 = 0, $mul = 0, $call = 0, $mul9 = 0, $call10 = 0, $call_sink = 0, $add_ptr = 0, $4 = 0, $5 = 0, $conv16 = 0, $cmp1730 = 0, $6 = 0, $r_031 = 0, $arrayidx = 0, $sub = 0, $arrayidx23 = 0, $7 = 0, $8 = 0, $cmp17 = 0, $9 = 0, $_lcssa = 0, $r_0_lcssa = 0, $an = 0, $10 = 0, $n = 0, $call30 = 0, $11 = 0, $12 = 0, $av = 0, $13 = 0, $v = 0, $14 = 0, $flat = 0, $15 = 0, $ht2 = 0, $16 = 0, $ht1 = 0, $17 = 0, $pht2 = 0, $18 = 0, $pht1 = 0, $19 = 0, $dec54 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $cmp = $0 << 16 >> 16 == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ ___assert_func(97320, 190, 164648, 120008);
+ case 4:
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $conv3 = $1 << 16 >> 16;
+ $add = $conv3 + 3 | 0;
+ $rank = $g + 224 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = $2;
+ $mul = $add * 44 & -1;
+ $call = _grealloc($3, $mul) | 0;
+ $call_sink = $call;
+ label = 7;
+ break;
+ case 6:
+ $mul9 = $add * 44 & -1;
+ $call10 = _gmalloc($mul9) | 0;
+ $call_sink = $call10;
+ label = 7;
+ break;
+ case 7:
+ $add_ptr = $call_sink + 44 | 0;
+ $4 = $add_ptr;
+ HEAP32[$rank >> 2] = $4;
+ $5 = HEAP16[$maxrank >> 1] | 0;
+ $conv16 = $5 << 16 >> 16;
+ $cmp1730 = $5 << 16 >> 16 > -1;
+ if ($cmp1730) {
+ label = 8;
+ break;
+ } else {
+ $r_0_lcssa = $conv16;
+ $_lcssa = $4;
+ label = 11;
+ break;
+ }
+ case 8:
+ $r_031 = $conv16;
+ $6 = $4;
+ label = 9;
+ break;
+ case 9:
+ $arrayidx = $6 + ($r_031 * 44 & -1) | 0;
+ $sub = $r_031 - 1 | 0;
+ $arrayidx23 = $6 + ($sub * 44 & -1) | 0;
+ $7 = $arrayidx;
+ $8 = $arrayidx23;
+ _memcpy($7 | 0, $8 | 0, 44);
+ $cmp17 = ($r_031 | 0) > 0;
+ $9 = HEAP32[$rank >> 2] | 0;
+ if ($cmp17) {
+ $r_031 = $sub;
+ $6 = $9;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $r_0_lcssa = -1;
+ $_lcssa = $9;
+ label = 11;
+ break;
+ case 11:
+ $an = $_lcssa + ($r_0_lcssa * 44 & -1) + 8 | 0;
+ HEAP32[$an >> 2] = 0;
+ $10 = HEAP32[$rank >> 2] | 0;
+ $n = $10 + ($r_0_lcssa * 44 & -1) | 0;
+ HEAP32[$n >> 2] = 0;
+ $call30 = _zmalloc(8) | 0;
+ $11 = $call30;
+ $12 = HEAP32[$rank >> 2] | 0;
+ $av = $12 + ($r_0_lcssa * 44 & -1) + 12 | 0;
+ HEAP32[$av >> 2] = $11;
+ $13 = HEAP32[$rank >> 2] | 0;
+ $v = $13 + ($r_0_lcssa * 44 & -1) + 4 | 0;
+ HEAP32[$v >> 2] = $11;
+ $14 = HEAP32[$rank >> 2] | 0;
+ $flat = $14 + ($r_0_lcssa * 44 & -1) + 40 | 0;
+ HEAP32[$flat >> 2] = 0;
+ $15 = HEAP32[$rank >> 2] | 0;
+ $ht2 = $15 + ($r_0_lcssa * 44 & -1) + 20 | 0;
+ HEAP32[$ht2 >> 2] = 1;
+ $16 = HEAP32[$rank >> 2] | 0;
+ $ht1 = $16 + ($r_0_lcssa * 44 & -1) + 16 | 0;
+ HEAP32[$ht1 >> 2] = 1;
+ $17 = HEAP32[$rank >> 2] | 0;
+ $pht2 = $17 + ($r_0_lcssa * 44 & -1) + 28 | 0;
+ HEAP32[$pht2 >> 2] = 1;
+ $18 = HEAP32[$rank >> 2] | 0;
+ $pht1 = $18 + ($r_0_lcssa * 44 & -1) + 24 | 0;
+ HEAP32[$pht1 >> 2] = 1;
+ $19 = HEAP16[$minrank >> 1] | 0;
+ $dec54 = $19 - 1 & 65535;
+ HEAP16[$minrank >> 1] = $dec54;
+ return;
+ }
+}
+function _init_mccomp($g, $c) {
+ $g = $g | 0;
+ $c = $c | 0;
+ var $list = 0, $0 = 0, $arrayidx = 0, $1 = 0, $nlist = 0, $cmp = 0, $minrank = 0, $2 = 0, $maxrank = 0, $3 = 0, $cmp515 = 0, $conv = 0, $rank = 0, $r_016 = 0, $4 = 0, $v = 0, $5 = 0, $n = 0, $6 = 0, $add_ptr = 0, $7 = 0, $n19 = 0, $inc = 0, $8 = 0, $conv4 = 0, $cmp5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $g + 228 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $0 + ($c << 2) | 0;
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $nlist = $g + 220 | 0;
+ HEAP32[$nlist >> 2] = $1;
+ $cmp = ($c | 0) > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $minrank = $g + 248 | 0;
+ $2 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $3 = HEAP16[$maxrank >> 1] | 0;
+ $cmp515 = $2 << 16 >> 16 > $3 << 16 >> 16;
+ if ($cmp515) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = $2 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $r_016 = $conv;
+ label = 5;
+ break;
+ case 5:
+ $4 = HEAP32[$rank >> 2] | 0;
+ $v = $4 + ($r_016 * 44 & -1) + 4 | 0;
+ $5 = HEAP32[$v >> 2] | 0;
+ $n = $4 + ($r_016 * 44 & -1) | 0;
+ $6 = HEAP32[$n >> 2] | 0;
+ $add_ptr = $5 + ($6 << 2) | 0;
+ HEAP32[$v >> 2] = $add_ptr;
+ $7 = HEAP32[$rank >> 2] | 0;
+ $n19 = $7 + ($r_016 * 44 & -1) | 0;
+ HEAP32[$n19 >> 2] = 0;
+ $inc = $r_016 + 1 | 0;
+ $8 = HEAP16[$maxrank >> 1] | 0;
+ $conv4 = $8 << 16 >> 16;
+ $cmp5 = ($inc | 0) > ($conv4 | 0);
+ if ($cmp5) {
+ label = 6;
+ break;
+ } else {
+ $r_016 = $inc;
+ label = 5;
+ break;
+ }
+ case 6:
+ return;
+ }
+}
+function _save_vlist($g) {
+ $g = $g | 0;
+ var $rankleader = 0, $0 = 0, $tobool = 0, $minrank = 0, $1 = 0, $maxrank = 0, $2 = 0, $cmp9 = 0, $conv = 0, $rank = 0, $r_010 = 0, $3 = 0, $v = 0, $4 = 0, $5 = 0, $6 = 0, $arrayidx9 = 0, $inc = 0, $7 = 0, $conv3 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rankleader = $g + 280 | 0;
+ $0 = HEAP32[$rankleader >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $cmp9 = $1 << 16 >> 16 > $2 << 16 >> 16;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = $1 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $r_010 = $conv;
+ label = 5;
+ break;
+ case 5:
+ $3 = HEAP32[$rank >> 2] | 0;
+ $v = $3 + ($r_010 * 44 & -1) + 4 | 0;
+ $4 = HEAP32[$v >> 2] | 0;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $6 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx9 = $6 + ($r_010 << 2) | 0;
+ HEAP32[$arrayidx9 >> 2] = $5;
+ $inc = $r_010 + 1 | 0;
+ $7 = HEAP16[$maxrank >> 1] | 0;
+ $conv3 = $7 << 16 >> 16;
+ $cmp = ($inc | 0) > ($conv3 | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ $r_010 = $inc;
+ label = 5;
+ break;
+ }
+ case 6:
+ return;
+ }
+}
+function _dot_mincross($g, $doBalance) {
+ $g = $g | 0;
+ $doBalance = $doBalance | 0;
+ var $size = 0, $0 = 0, $cmp24 = 0, $c_026 = 0, $nc_025 = 0, $call = 0, $add = 0, $inc = 0, $1 = 0, $cmp = 0, $nc_0_lcssa = 0, $n_cluster = 0, $2 = 0, $cmp320 = 0, $clust = 0, $c_122 = 0, $nc_121 = 0, $3 = 0, $arrayidx = 0, $4 = 0, $call6 = 0, $add7 = 0, $inc9 = 0, $5 = 0, $cmp3 = 0, $cmp13 = 0, $6 = 0, $call14 = 0, $tobool = 0, $call15 = 0, $tobool16 = 0, $7 = 0, $call17 = 0, $nc_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _init_mincross($g);
+ $size = $g + 232 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp24 = ($0 | 0) > 0;
+ if ($cmp24) {
+ $nc_025 = 0;
+ $c_026 = 0;
+ label = 3;
+ break;
+ } else {
+ $nc_0_lcssa = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ _init_mccomp($g, $c_026);
+ $call = _mincross($g, 0, $doBalance) | 0;
+ $add = $call + $nc_025 | 0;
+ $inc = $c_026 + 1 | 0;
+ $1 = HEAP32[$size >> 2] | 0;
+ $cmp = ($inc | 0) < ($1 | 0);
+ if ($cmp) {
+ $nc_025 = $add;
+ $c_026 = $inc;
+ label = 3;
+ break;
+ } else {
+ $nc_0_lcssa = $add;
+ label = 4;
+ break;
+ }
+ case 4:
+ _merge2($g);
+ $n_cluster = $g + 212 | 0;
+ $2 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp320 = ($2 | 0) < 1;
+ if ($cmp320) {
+ $nc_2 = $nc_0_lcssa;
+ label = 11;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $clust = $g + 216 | 0;
+ $nc_121 = $nc_0_lcssa;
+ $c_122 = 1;
+ label = 6;
+ break;
+ case 6:
+ $3 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $3 + ($c_122 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $call6 = _mincross_clust($4, $doBalance) | 0;
+ $add7 = $call6 + $nc_121 | 0;
+ $inc9 = $c_122 + 1 | 0;
+ $5 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp3 = ($inc9 | 0) > ($5 | 0);
+ if ($cmp3) {
+ label = 7;
+ break;
+ } else {
+ $nc_121 = $add7;
+ $c_122 = $inc9;
+ label = 6;
+ break;
+ }
+ case 7:
+ $cmp13 = ($5 | 0) > 0;
+ if ($cmp13) {
+ label = 8;
+ break;
+ } else {
+ $nc_2 = $add7;
+ label = 11;
+ break;
+ }
+ case 8:
+ $6 = $g | 0;
+ $call14 = _agget($6, 96048) | 0;
+ $tobool = ($call14 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call15 = _mapbool($call14) | 0;
+ $tobool16 = $call15 << 24 >> 24 == 0;
+ if ($tobool16) {
+ $nc_2 = $add7;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $7 = $g;
+ _mark_lowclusters($7);
+ HEAP8[166152] = 1;
+ $call17 = _mincross($g, 2, $doBalance) | 0;
+ $nc_2 = $call17;
+ label = 11;
+ break;
+ case 11:
+ _cleanup2($g, $nc_2);
+ return;
+ }
+}
+function _init_mincross($g) {
+ $g = $g | 0;
+ var $0 = 0, $tobool = 0, $root = 0, $1 = 0, $2 = 0, $call = 0, $add = 0, $mul = 0, $call1 = 0, $3 = 0, $call3 = 0, $4 = 0, $minrank = 0, $5 = 0, $conv = 0, $maxrank = 0, $6 = 0, $conv5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[164912] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _start_timer();
+ label = 4;
+ break;
+ case 4:
+ HEAP8[166152] = 0;
+ HEAP32[41526] = $g;
+ $root = $g + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $2 = $1;
+ $call = _agnedges($2) | 0;
+ $add = $call << 2;
+ $mul = $add + 4 | 0;
+ $call1 = _zmalloc($mul) | 0;
+ $3 = $call1;
+ HEAP32[41348] = $3;
+ $call3 = _zmalloc($mul) | 0;
+ $4 = $call3;
+ HEAP32[41344] = $4;
+ _mincross_options($g);
+ _class2($g);
+ _decompose($g, 1);
+ _allocate_ranks($g);
+ _ordered_edges($g);
+ $minrank = $g + 248 | 0;
+ $5 = HEAP16[$minrank >> 1] | 0;
+ $conv = $5 << 16 >> 16;
+ HEAP32[41854] = $conv;
+ $maxrank = $g + 250 | 0;
+ $6 = HEAP16[$maxrank >> 1] | 0;
+ $conv5 = $6 << 16 >> 16;
+ HEAP32[41856] = $conv5;
+ return;
+ }
+}
+function _mincross($g, $startpass, $doBalance) {
+ $g = $g | 0;
+ $startpass = $startpass | 0;
+ $doBalance = $doBalance | 0;
+ var $cmp = 0, $call = 0, $cur_cross_1_ph = 0, $root = 0, $maxthispass_0 = 0, $pass_0 = 0, $cur_cross_1 = 0, $best_cross_1 = 0, $cmp1 = 0, $cmp2 = 0, $0 = 0, $cmp4 = 0, $cond = 0, $1 = 0, $cmp5 = 0, $cmp8 = 0, $call11 = 0, $cmp12 = 0, $cmp16 = 0, $maxthispass_1 = 0, $cur_cross_2 = 0, $best_cross_3 = 0, $cmp213 = 0, $best_cross_47 = 0, $cur_cross_36 = 0, $trying_05 = 0, $iter_04 = 0, $2 = 0, $tobool = 0, $3 = 0, $call24 = 0, $inc = 0, $4 = 0, $cmp26 = 0, $cmp29 = 0, $or_cond = 0, $call32 = 0, $cmp33 = 0, $conv = 0.0, $5 = 0.0, $conv35 = 0.0, $mul = 0.0, $cmp36 = 0, $trying_1 = 0, $trying_2 = 0, $best_cross_5 = 0, $inc41 = 0, $cmp21 = 0, $best_cross_4_lcssa = 0, $cur_cross_3_lcssa = 0, $cmp42 = 0, $inc47 = 0, $maxthispass_2 = 0, $cur_cross_4 = 0, $best_cross_6 = 0, $cmp49 = 0, $cmp53 = 0, $call56 = 0, $best_cross_7 = 0, $tobool58 = 0, $cmp611 = 0, $or_cond11 = 0, $iter_12 = 0, $inc66 = 0, $cmp61 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($startpass | 0) > 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $cur_cross_1_ph = 2147483647;
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _ncross(0) | 0;
+ _save_best($g);
+ $cur_cross_1_ph = $call;
+ label = 4;
+ break;
+ case 4:
+ $root = $g + 32 | 0;
+ $best_cross_1 = $cur_cross_1_ph;
+ $cur_cross_1 = $cur_cross_1_ph;
+ $pass_0 = $startpass;
+ $maxthispass_0 = 0;
+ label = 5;
+ break;
+ case 5:
+ $cmp1 = ($pass_0 | 0) < 3;
+ if ($cmp1) {
+ label = 6;
+ break;
+ } else {
+ $best_cross_6 = $best_cross_1;
+ $cur_cross_4 = $cur_cross_1;
+ $maxthispass_2 = $maxthispass_0;
+ label = 23;
+ break;
+ }
+ case 6:
+ $cmp2 = ($pass_0 | 0) < 2;
+ $0 = HEAP32[41634] | 0;
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 7:
+ $cmp4 = ($0 | 0) > 4;
+ $cond = $cmp4 ? 4 : $0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $cmp5 = ($1 | 0) == ($g | 0);
+ if ($cmp5) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ _build_ranks($g, $pass_0);
+ label = 9;
+ break;
+ case 9:
+ $cmp8 = ($pass_0 | 0) == 0;
+ if ($cmp8) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _flat_breakcycles($g);
+ label = 11;
+ break;
+ case 11:
+ _flat_reorder($g);
+ $call11 = _ncross(0) | 0;
+ $cmp12 = ($call11 | 0) > ($best_cross_1 | 0);
+ if ($cmp12) {
+ $best_cross_3 = $best_cross_1;
+ $cur_cross_2 = $call11;
+ $maxthispass_1 = $cond;
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _save_best($g);
+ $best_cross_3 = $call11;
+ $cur_cross_2 = $call11;
+ $maxthispass_1 = $cond;
+ label = 15;
+ break;
+ case 13:
+ $cmp16 = ($cur_cross_1 | 0) > ($best_cross_1 | 0);
+ if ($cmp16) {
+ label = 14;
+ break;
+ } else {
+ $best_cross_3 = $best_cross_1;
+ $cur_cross_2 = $best_cross_1;
+ $maxthispass_1 = $0;
+ label = 15;
+ break;
+ }
+ case 14:
+ _restore_best($g);
+ $best_cross_3 = $best_cross_1;
+ $cur_cross_2 = $best_cross_1;
+ $maxthispass_1 = $0;
+ label = 15;
+ break;
+ case 15:
+ $cmp213 = ($maxthispass_1 | 0) > 0;
+ if ($cmp213) {
+ $iter_04 = 0;
+ $trying_05 = 0;
+ $cur_cross_36 = $cur_cross_2;
+ $best_cross_47 = $best_cross_3;
+ label = 16;
+ break;
+ } else {
+ $cur_cross_3_lcssa = $cur_cross_2;
+ $best_cross_4_lcssa = $best_cross_3;
+ label = 22;
+ break;
+ }
+ case 16:
+ $2 = HEAP8[164912] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $3 = HEAP32[_stderr >> 2] | 0;
+ $call24 = _fprintf($3 | 0, 149432, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = $pass_0, HEAP32[tempInt + 8 >> 2] = $iter_04, HEAP32[tempInt + 16 >> 2] = $trying_05, HEAP32[tempInt + 24 >> 2] = $cur_cross_36, HEAP32[tempInt + 32 >> 2] = $best_cross_47, tempInt) | 0) | 0;
+ label = 18;
+ break;
+ case 18:
+ $inc = $trying_05 + 1 | 0;
+ $4 = HEAP32[41630] | 0;
+ $cmp26 = ($trying_05 | 0) >= ($4 | 0);
+ $cmp29 = ($cur_cross_36 | 0) == 0;
+ $or_cond = $cmp26 | $cmp29;
+ if ($or_cond) {
+ $cur_cross_3_lcssa = $cur_cross_36;
+ $best_cross_4_lcssa = $best_cross_47;
+ label = 22;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ _mincross_step($g, $iter_04);
+ $call32 = _ncross(0) | 0;
+ $cmp33 = ($call32 | 0) > ($best_cross_47 | 0);
+ if ($cmp33) {
+ $best_cross_5 = $best_cross_47;
+ $trying_2 = $inc;
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ _save_best($g);
+ $conv = +($call32 | 0);
+ $5 = +HEAPF64[20993];
+ $conv35 = +($best_cross_47 | 0);
+ $mul = $conv35 * $5;
+ $cmp36 = $conv < $mul;
+ $trying_1 = $cmp36 ? 0 : $inc;
+ $best_cross_5 = $call32;
+ $trying_2 = $trying_1;
+ label = 21;
+ break;
+ case 21:
+ $inc41 = $iter_04 + 1 | 0;
+ $cmp21 = ($inc41 | 0) < ($maxthispass_1 | 0);
+ if ($cmp21) {
+ $iter_04 = $inc41;
+ $trying_05 = $trying_2;
+ $cur_cross_36 = $call32;
+ $best_cross_47 = $best_cross_5;
+ label = 16;
+ break;
+ } else {
+ $cur_cross_3_lcssa = $call32;
+ $best_cross_4_lcssa = $best_cross_5;
+ label = 22;
+ break;
+ }
+ case 22:
+ $cmp42 = ($cur_cross_3_lcssa | 0) == 0;
+ $inc47 = $pass_0 + 1 | 0;
+ if ($cmp42) {
+ $best_cross_6 = $best_cross_4_lcssa;
+ $cur_cross_4 = 0;
+ $maxthispass_2 = $maxthispass_1;
+ label = 23;
+ break;
+ } else {
+ $best_cross_1 = $best_cross_4_lcssa;
+ $cur_cross_1 = $cur_cross_3_lcssa;
+ $pass_0 = $inc47;
+ $maxthispass_0 = $maxthispass_1;
+ label = 5;
+ break;
+ }
+ case 23:
+ $cmp49 = ($cur_cross_4 | 0) > ($best_cross_6 | 0);
+ if ($cmp49) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ _restore_best($g);
+ label = 25;
+ break;
+ case 25:
+ $cmp53 = ($best_cross_6 | 0) > 0;
+ if ($cmp53) {
+ label = 26;
+ break;
+ } else {
+ $best_cross_7 = $best_cross_6;
+ label = 27;
+ break;
+ }
+ case 26:
+ _transpose($g, 0);
+ $call56 = _ncross(0) | 0;
+ $best_cross_7 = $call56;
+ label = 27;
+ break;
+ case 27:
+ $tobool58 = ($doBalance | 0) != 0;
+ $cmp611 = ($maxthispass_2 | 0) > 0;
+ $or_cond11 = $tobool58 & $cmp611;
+ if ($or_cond11) {
+ $iter_12 = 0;
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ _balance($g);
+ $inc66 = $iter_12 + 1 | 0;
+ $cmp61 = ($inc66 | 0) < ($maxthispass_2 | 0);
+ if ($cmp61) {
+ $iter_12 = $inc66;
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ STACKTOP = __stackBase__;
+ return $best_cross_7 | 0;
+ }
+ return 0;
+}
+function _merge2($g) {
+ $g = $g | 0;
+ var $minrank = 0, $0 = 0, $maxrank = 0, $1 = 0, $cmp34 = 0, $conv = 0, $rank = 0, $name = 0, $r_035 = 0, $2 = 0, $an = 0, $3 = 0, $n = 0, $4 = 0, $av = 0, $5 = 0, $v14 = 0, $6 = 0, $n1930 = 0, $7 = 0, $cmp2031 = 0, $8 = 0, $9 = 0, $i_032 = 0, $v26 = 0, $10 = 0, $arrayidx27 = 0, $11 = 0, $cmp28 = 0, $12 = 0, $tobool = 0, $13 = 0, $14 = 0, $call = 0, $15 = 0, $n38 = 0, $order = 0, $inc = 0, $16 = 0, $n19 = 0, $17 = 0, $cmp20 = 0, $inc42 = 0, $18 = 0, $conv2 = 0, $cmp = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _merge_components($g);
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $cmp34 = $0 << 16 >> 16 > $1 << 16 >> 16;
+ if ($cmp34) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $name = $g + 12 | 0;
+ $r_035 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$rank >> 2] | 0;
+ $an = $2 + ($r_035 * 44 & -1) + 8 | 0;
+ $3 = HEAP32[$an >> 2] | 0;
+ $n = $2 + ($r_035 * 44 & -1) | 0;
+ HEAP32[$n >> 2] = $3;
+ $4 = HEAP32[$rank >> 2] | 0;
+ $av = $4 + ($r_035 * 44 & -1) + 12 | 0;
+ $5 = HEAP32[$av >> 2] | 0;
+ $v14 = $4 + ($r_035 * 44 & -1) + 4 | 0;
+ HEAP32[$v14 >> 2] = $5;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $n1930 = $6 + ($r_035 * 44 & -1) | 0;
+ $7 = HEAP32[$n1930 >> 2] | 0;
+ $cmp2031 = ($7 | 0) > 0;
+ if ($cmp2031) {
+ $i_032 = 0;
+ $9 = $6;
+ $8 = $7;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ $v26 = $9 + ($r_035 * 44 & -1) + 4 | 0;
+ $10 = HEAP32[$v26 >> 2] | 0;
+ $arrayidx27 = $10 + ($i_032 << 2) | 0;
+ $11 = HEAP32[$arrayidx27 >> 2] | 0;
+ $cmp28 = ($11 | 0) == 0;
+ if ($cmp28) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 6:
+ $12 = HEAP8[164912] | 0;
+ $tobool = $12 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $13 = HEAP32[_stderr >> 2] | 0;
+ $14 = HEAP32[$name >> 2] | 0;
+ $call = _fprintf($13 | 0, 153024, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $14, HEAP32[tempInt + 8 >> 2] = $r_035, HEAP32[tempInt + 16 >> 2] = $i_032, HEAP32[tempInt + 24 >> 2] = $8, tempInt) | 0) | 0;
+ label = 8;
+ break;
+ case 8:
+ $15 = HEAP32[$rank >> 2] | 0;
+ $n38 = $15 + ($r_035 * 44 & -1) | 0;
+ HEAP32[$n38 >> 2] = $i_032;
+ label = 10;
+ break;
+ case 9:
+ $order = $11 + 240 | 0;
+ HEAP32[$order >> 2] = $i_032;
+ $inc = $i_032 + 1 | 0;
+ $16 = HEAP32[$rank >> 2] | 0;
+ $n19 = $16 + ($r_035 * 44 & -1) | 0;
+ $17 = HEAP32[$n19 >> 2] | 0;
+ $cmp20 = ($inc | 0) < ($17 | 0);
+ if ($cmp20) {
+ $i_032 = $inc;
+ $9 = $16;
+ $8 = $17;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $inc42 = $r_035 + 1 | 0;
+ $18 = HEAP16[$maxrank >> 1] | 0;
+ $conv2 = $18 << 16 >> 16;
+ $cmp = ($inc42 | 0) > ($conv2 | 0);
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ $r_035 = $inc42;
+ label = 4;
+ break;
+ }
+ case 11:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _mincross_clust($g, $doBalance) {
+ $g = $g | 0;
+ $doBalance = $doBalance | 0;
+ var $0 = 0, $call = 0, $n_cluster = 0, $1 = 0, $cmp1 = 0, $clust = 0, $nc_03 = 0, $c_02 = 0, $2 = 0, $arrayidx = 0, $3 = 0, $call2 = 0, $add = 0, $inc = 0, $4 = 0, $cmp = 0, $nc_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ _expand_cluster($0);
+ _ordered_edges($g);
+ _flat_breakcycles($g);
+ _flat_reorder($g);
+ $call = _mincross($g, 2, $doBalance) | 0;
+ $n_cluster = $g + 212 | 0;
+ $1 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp1 = ($1 | 0) < 1;
+ if ($cmp1) {
+ $nc_0_lcssa = $call;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $c_02 = 1;
+ $nc_03 = $call;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $2 + ($c_02 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $call2 = _mincross_clust($3, $doBalance) | 0;
+ $add = $call2 + $nc_03 | 0;
+ $inc = $c_02 + 1 | 0;
+ $4 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($4 | 0);
+ if ($cmp) {
+ $nc_0_lcssa = $add;
+ label = 5;
+ break;
+ } else {
+ $c_02 = $inc;
+ $nc_03 = $add;
+ label = 4;
+ break;
+ }
+ case 5:
+ _save_vlist($g);
+ return $nc_0_lcssa | 0;
+ }
+ return 0;
+}
+function _cleanup2($g, $nc) {
+ $g = $g | 0;
+ $nc = $nc | 0;
+ var $0 = 0, $tobool = 0, $1 = 0, $2 = 0, $tobool1 = 0, $3 = 0, $n_cluster = 0, $4 = 0, $cmp33 = 0, $clust = 0, $c_034 = 0, $5 = 0, $arrayidx = 0, $6 = 0, $inc = 0, $7 = 0, $cmp = 0, $minrank = 0, $8 = 0, $maxrank = 0, $9 = 0, $cmp930 = 0, $conv = 0, $rank = 0, $r_031 = 0, $10 = 0, $n26 = 0, $11 = 0, $cmp1527 = 0, $12 = 0, $i_028 = 0, $v21 = 0, $13 = 0, $arrayidx22 = 0, $14 = 0, $order = 0, $list = 0, $15 = 0, $tobool25 = 0, $16 = 0, $17 = 0, $tobool3224 = 0, $18 = 0, $j_025 = 0, $edge_type = 0, $19 = 0, $cmp36 = 0, $20 = 0, $dec = 0, $j_1 = 0, $inc41 = 0, $21 = 0, $arrayidx31 = 0, $22 = 0, $tobool32 = 0, $inc45 = 0, $23 = 0, $n = 0, $24 = 0, $cmp15 = 0, $_lcssa = 0, $flat = 0, $25 = 0, $inc51 = 0, $26 = 0, $conv8 = 0, $cmp9 = 0, $27 = 0, $tobool53 = 0, $28 = 0, $name = 0, $29 = 0, $call = 0.0, $call55 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41344] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $0;
+ _free($1);
+ HEAP32[41344] = 0;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[41348] | 0;
+ $tobool1 = ($2 | 0) == 0;
+ if ($tobool1) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = $2;
+ _free($3);
+ HEAP32[41348] = 0;
+ label = 6;
+ break;
+ case 6:
+ $n_cluster = $g + 212 | 0;
+ $4 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp33 = ($4 | 0) < 1;
+ if ($cmp33) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $clust = $g + 216 | 0;
+ $c_034 = 1;
+ label = 8;
+ break;
+ case 8:
+ $5 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $5 + ($c_034 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ _rec_reset_vlists($6);
+ $inc = $c_034 + 1 | 0;
+ $7 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($7 | 0);
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ $c_034 = $inc;
+ label = 8;
+ break;
+ }
+ case 9:
+ $minrank = $g + 248 | 0;
+ $8 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $9 = HEAP16[$maxrank >> 1] | 0;
+ $cmp930 = $8 << 16 >> 16 > $9 << 16 >> 16;
+ if ($cmp930) {
+ label = 19;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $conv = $8 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $r_031 = $conv;
+ label = 11;
+ break;
+ case 11:
+ $10 = HEAP32[$rank >> 2] | 0;
+ $n26 = $10 + ($r_031 * 44 & -1) | 0;
+ $11 = HEAP32[$n26 >> 2] | 0;
+ $cmp1527 = ($11 | 0) > 0;
+ if ($cmp1527) {
+ $i_028 = 0;
+ $12 = $10;
+ label = 12;
+ break;
+ } else {
+ $_lcssa = $10;
+ label = 18;
+ break;
+ }
+ case 12:
+ $v21 = $12 + ($r_031 * 44 & -1) + 4 | 0;
+ $13 = HEAP32[$v21 >> 2] | 0;
+ $arrayidx22 = $13 + ($i_028 << 2) | 0;
+ $14 = HEAP32[$arrayidx22 >> 2] | 0;
+ $order = $14 + 240 | 0;
+ HEAP32[$order >> 2] = $i_028;
+ $list = $14 + 192 | 0;
+ $15 = HEAP32[$list >> 2] | 0;
+ $tobool25 = ($15 | 0) == 0;
+ if ($tobool25) {
+ label = 17;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $16 = HEAP32[$list >> 2] | 0;
+ $17 = HEAP32[$16 >> 2] | 0;
+ $tobool3224 = ($17 | 0) == 0;
+ if ($tobool3224) {
+ label = 17;
+ break;
+ } else {
+ $j_025 = 0;
+ $18 = $17;
+ label = 14;
+ break;
+ }
+ case 14:
+ $edge_type = $18 + 128 | 0;
+ $19 = HEAP8[$edge_type] | 0;
+ $cmp36 = $19 << 24 >> 24 == 4;
+ if ($cmp36) {
+ label = 15;
+ break;
+ } else {
+ $j_1 = $j_025;
+ label = 16;
+ break;
+ }
+ case 15:
+ _delete_flat_edge($18);
+ $20 = $18 | 0;
+ _free($20);
+ $dec = $j_025 - 1 | 0;
+ $j_1 = $dec;
+ label = 16;
+ break;
+ case 16:
+ $inc41 = $j_1 + 1 | 0;
+ $21 = HEAP32[$list >> 2] | 0;
+ $arrayidx31 = $21 + ($inc41 << 2) | 0;
+ $22 = HEAP32[$arrayidx31 >> 2] | 0;
+ $tobool32 = ($22 | 0) == 0;
+ if ($tobool32) {
+ label = 17;
+ break;
+ } else {
+ $j_025 = $inc41;
+ $18 = $22;
+ label = 14;
+ break;
+ }
+ case 17:
+ $inc45 = $i_028 + 1 | 0;
+ $23 = HEAP32[$rank >> 2] | 0;
+ $n = $23 + ($r_031 * 44 & -1) | 0;
+ $24 = HEAP32[$n >> 2] | 0;
+ $cmp15 = ($inc45 | 0) < ($24 | 0);
+ if ($cmp15) {
+ $i_028 = $inc45;
+ $12 = $23;
+ label = 12;
+ break;
+ } else {
+ $_lcssa = $23;
+ label = 18;
+ break;
+ }
+ case 18:
+ $flat = $_lcssa + ($r_031 * 44 & -1) + 40 | 0;
+ $25 = HEAP32[$flat >> 2] | 0;
+ _free_matrix($25);
+ $inc51 = $r_031 + 1 | 0;
+ $26 = HEAP16[$maxrank >> 1] | 0;
+ $conv8 = $26 << 16 >> 16;
+ $cmp9 = ($inc51 | 0) > ($conv8 | 0);
+ if ($cmp9) {
+ label = 19;
+ break;
+ } else {
+ $r_031 = $inc51;
+ label = 11;
+ break;
+ }
+ case 19:
+ $27 = HEAP8[164912] | 0;
+ $tobool53 = $27 << 24 >> 24 == 0;
+ if ($tobool53) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $28 = HEAP32[_stderr >> 2] | 0;
+ $name = $g + 12 | 0;
+ $29 = HEAP32[$name >> 2] | 0;
+ $call = +_elapsed_sec();
+ $call55 = _fprintf($28 | 0, 156488, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $29, HEAP32[tempInt + 8 >> 2] = $nc, HEAPF64[tempInt + 16 >> 3] = $call, tempInt) | 0) | 0;
+ label = 21;
+ break;
+ case 21:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _rec_save_vlists($g) {
+ $g = $g | 0;
+ var $n_cluster = 0, $0 = 0, $cmp5 = 0, $clust = 0, $c_06 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $inc = 0, $3 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _save_vlist($g);
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp5 = ($0 | 0) < 1;
+ if ($cmp5) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $c_06 = 1;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $1 + ($c_06 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _rec_save_vlists($2);
+ $inc = $c_06 + 1 | 0;
+ $3 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($3 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $c_06 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ return;
+ }
+}
+function _rec_reset_vlists($g) {
+ $g = $g | 0;
+ var $n_cluster = 0, $0 = 0, $cmp26 = 0, $clust = 0, $c_027 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $inc = 0, $3 = 0, $cmp = 0, $rankleader = 0, $4 = 0, $tobool = 0, $minrank = 0, $5 = 0, $maxrank = 0, $6 = 0, $cmp824 = 0, $conv = 0, $root = 0, $rank23 = 0, $r_025 = 0, $7 = 0, $arrayidx13 = 0, $8 = 0, $call = 0, $call14 = 0, $9 = 0, $arrayidx17 = 0, $10 = 0, $rank = 0, $11 = 0, $v20 = 0, $12 = 0, $order = 0, $13 = 0, $add_ptr = 0, $14 = 0, $v25 = 0, $order27 = 0, $15 = 0, $16 = 0, $sub = 0, $add = 0, $17 = 0, $n = 0, $inc34 = 0, $18 = 0, $conv7 = 0, $cmp8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp26 = ($0 | 0) < 1;
+ if ($cmp26) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $c_027 = 1;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $1 + ($c_027 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _rec_reset_vlists($2);
+ $inc = $c_027 + 1 | 0;
+ $3 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($3 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $c_027 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ $rankleader = $g + 280 | 0;
+ $4 = HEAP32[$rankleader >> 2] | 0;
+ $tobool = ($4 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $minrank = $g + 248 | 0;
+ $5 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $6 = HEAP16[$maxrank >> 1] | 0;
+ $cmp824 = $5 << 16 >> 16 > $6 << 16 >> 16;
+ if ($cmp824) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $conv = $5 << 16 >> 16;
+ $root = $g + 32 | 0;
+ $rank23 = $g + 224 | 0;
+ $r_025 = $conv;
+ label = 8;
+ break;
+ case 8:
+ $7 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx13 = $7 + ($r_025 << 2) | 0;
+ $8 = HEAP32[$arrayidx13 >> 2] | 0;
+ $call = _furthestnode($g, $8, -1) | 0;
+ $call14 = _furthestnode($g, $8, 1) | 0;
+ $9 = HEAP32[$rankleader >> 2] | 0;
+ $arrayidx17 = $9 + ($r_025 << 2) | 0;
+ HEAP32[$arrayidx17 >> 2] = $call;
+ $10 = HEAP32[$root >> 2] | 0;
+ $rank = $10 + 224 | 0;
+ $11 = HEAP32[$rank >> 2] | 0;
+ $v20 = $11 + ($r_025 * 44 & -1) + 4 | 0;
+ $12 = HEAP32[$v20 >> 2] | 0;
+ $order = $call + 240 | 0;
+ $13 = HEAP32[$order >> 2] | 0;
+ $add_ptr = $12 + ($13 << 2) | 0;
+ $14 = HEAP32[$rank23 >> 2] | 0;
+ $v25 = $14 + ($r_025 * 44 & -1) + 4 | 0;
+ HEAP32[$v25 >> 2] = $add_ptr;
+ $order27 = $call14 + 240 | 0;
+ $15 = HEAP32[$order27 >> 2] | 0;
+ $16 = HEAP32[$order >> 2] | 0;
+ $sub = $15 + 1 | 0;
+ $add = $sub - $16 | 0;
+ $17 = HEAP32[$rank23 >> 2] | 0;
+ $n = $17 + ($r_025 * 44 & -1) | 0;
+ HEAP32[$n >> 2] = $add;
+ $inc34 = $r_025 + 1 | 0;
+ $18 = HEAP16[$maxrank >> 1] | 0;
+ $conv7 = $18 << 16 >> 16;
+ $cmp8 = ($inc34 | 0) > ($conv7 | 0);
+ if ($cmp8) {
+ label = 9;
+ break;
+ } else {
+ $r_025 = $inc34;
+ label = 8;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _furthestnode($g, $v, $dir) {
+ $g = $g | 0;
+ $v = $v | 0;
+ $dir = $dir | 0;
+ var $call6 = 0, $tobool7 = 0, $call9 = 0, $rv_08 = 0, $call1 = 0, $tobool2 = 0, $rv_0_be = 0, $call = 0, $tobool = 0, $call3 = 0, $tobool4 = 0, $rv_0_call = 0, $rv_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call6 = _neighbor113($v, $dir) | 0;
+ $tobool7 = ($call6 | 0) == 0;
+ if ($tobool7) {
+ $rv_0_lcssa = $v;
+ label = 6;
+ break;
+ } else {
+ $rv_08 = $v;
+ $call9 = $call6;
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _is_a_normal_node_of($g, $call9) | 0;
+ $tobool2 = ($call1 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ $rv_0_be = $call9;
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _neighbor113($call9, $dir) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $rv_0_lcssa = $rv_0_be;
+ label = 6;
+ break;
+ } else {
+ $rv_08 = $rv_0_be;
+ $call9 = $call;
+ label = 3;
+ break;
+ }
+ case 5:
+ $call3 = _is_a_vnode_of_an_edge_of($g, $call9) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ $rv_0_call = $tobool4 ? $rv_08 : $call9;
+ $rv_0_be = $rv_0_call;
+ label = 4;
+ break;
+ case 6:
+ return $rv_0_lcssa | 0;
+ }
+ return 0;
+}
+function _setbounds($v, $bounds, $lpos, $rpos) {
+ $v = $v | 0;
+ $bounds = $bounds | 0;
+ $lpos = $lpos | 0;
+ $rpos = $rpos | 0;
+ var $l = 0, $r = 0, $node_type = 0, $0 = 0, $cmp = 0, $order = 0, $1 = 0, $size = 0, $2 = 0, $cmp4 = 0, $list61 = 0, $3 = 0, $4 = 0, $tobool36 = 0, $5 = 0, $size8 = 0, $6 = 0, $cmp9 = 0, $list = 0, $7 = 0, $8 = 0, $head = 0, $9 = 0, $arrayidx16 = 0, $10 = 0, $head17 = 0, $11 = 0, $12 = 0, $cmp18 = 0, $arrayidx22 = 0, $13 = 0, $cmp23 = 0, $arrayidx26 = 0, $arrayidx27 = 0, $cmp29 = 0, $cmp31 = 0, $or_cond = 0, $cmp37 = 0, $cmp40 = 0, $or_cond35 = 0, $arrayidx43 = 0, $14 = 0, $cmp44 = 0, $cmp47 = 0, $15 = 0, $cmp50 = 0, $arrayidx53 = 0, $16 = 0, $onright_039 = 0, $onleft_038 = 0, $i_037 = 0, $head63 = 0, $17 = 0, $order65 = 0, $18 = 0, $cmp66 = 0, $cmp73 = 0, $onright_0_ = 0, $onleft_1 = 0, $onright_1 = 0, $inc = 0, $arrayidx62 = 0, $19 = 0, $tobool = 0, $tobool78 = 0, $cmp81 = 0, $or_cond33 = 0, $add = 0, $tobool87 = 0, $cmp90 = 0, $or_cond34 = 0, $sub = 0, $arrayidx93 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $l = __stackBase__ | 0;
+ $r = __stackBase__ + 8 | 0;
+ $node_type = $v + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 3:
+ $order = $v + 240 | 0;
+ $1 = HEAP32[$order >> 2] | 0;
+ $size = $v + 180 | 0;
+ $2 = HEAP32[$size >> 2] | 0;
+ $cmp4 = ($2 | 0) == 0;
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $list61 = $v + 184 | 0;
+ $3 = HEAP32[$list61 >> 2] | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $tobool36 = ($4 | 0) == 0;
+ if ($tobool36) {
+ label = 27;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[$list61 >> 2] | 0;
+ $i_037 = 0;
+ $onleft_038 = 0;
+ $onright_039 = 0;
+ $16 = $4;
+ label = 20;
+ break;
+ case 6:
+ $size8 = $v + 188 | 0;
+ $6 = HEAP32[$size8 >> 2] | 0;
+ $cmp9 = ($6 | 0) == 2;
+ if ($cmp9) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ ___assert_func(97320, 63, 163864, 137424);
+ case 8:
+ $list = $v + 184 | 0;
+ $7 = HEAP32[$list >> 2] | 0;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $head = $8 + 12 | 0;
+ $9 = HEAP32[$head >> 2] | 0;
+ $arrayidx16 = $7 + 4 | 0;
+ $10 = HEAP32[$arrayidx16 >> 2] | 0;
+ $head17 = $10 + 12 | 0;
+ $11 = HEAP32[$head17 >> 2] | 0;
+ _findlr($9, $11, $l, $r);
+ $12 = HEAP32[$r >> 2] | 0;
+ $cmp18 = ($12 | 0) > ($lpos | 0);
+ if ($cmp18) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ HEAP32[$bounds >> 2] = $1;
+ $arrayidx22 = $bounds + 8 | 0;
+ HEAP32[$arrayidx22 >> 2] = $1;
+ label = 27;
+ break;
+ case 10:
+ $13 = HEAP32[$l >> 2] | 0;
+ $cmp23 = ($13 | 0) < ($rpos | 0);
+ if ($cmp23) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $arrayidx26 = $bounds + 4 | 0;
+ HEAP32[$arrayidx26 >> 2] = $1;
+ $arrayidx27 = $bounds + 12 | 0;
+ HEAP32[$arrayidx27 >> 2] = $1;
+ label = 27;
+ break;
+ case 12:
+ $cmp29 = ($13 | 0) < ($lpos | 0);
+ $cmp31 = ($12 | 0) > ($rpos | 0);
+ $or_cond = $cmp29 & $cmp31;
+ if ($or_cond) {
+ label = 27;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ if ($cmp29) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $cmp37 = ($13 | 0) == ($lpos | 0);
+ $cmp40 = ($12 | 0) < ($rpos | 0);
+ $or_cond35 = $cmp37 & $cmp40;
+ if ($or_cond35) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $arrayidx43 = $bounds + 8 | 0;
+ HEAP32[$arrayidx43 >> 2] = $1;
+ label = 16;
+ break;
+ case 16:
+ $14 = HEAP32[$r >> 2] | 0;
+ $cmp44 = ($14 | 0) > ($rpos | 0);
+ if ($cmp44) {
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $cmp47 = ($14 | 0) == ($rpos | 0);
+ if ($cmp47) {
+ label = 18;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 18:
+ $15 = HEAP32[$l >> 2] | 0;
+ $cmp50 = ($15 | 0) > ($lpos | 0);
+ if ($cmp50) {
+ label = 19;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 19:
+ $arrayidx53 = $bounds + 12 | 0;
+ HEAP32[$arrayidx53 >> 2] = $1;
+ label = 27;
+ break;
+ case 20:
+ $head63 = $16 + 12 | 0;
+ $17 = HEAP32[$head63 >> 2] | 0;
+ $order65 = $17 + 240 | 0;
+ $18 = HEAP32[$order65 >> 2] | 0;
+ $cmp66 = ($18 | 0) > ($lpos | 0);
+ if ($cmp66) {
+ label = 21;
+ break;
+ } else {
+ $onright_1 = $onright_039;
+ $onleft_1 = 1;
+ label = 22;
+ break;
+ }
+ case 21:
+ $cmp73 = ($18 | 0) < ($rpos | 0);
+ $onright_0_ = $cmp73 ? $onright_039 : 1;
+ $onright_1 = $onright_0_;
+ $onleft_1 = $onleft_038;
+ label = 22;
+ break;
+ case 22:
+ $inc = $i_037 + 1 | 0;
+ $arrayidx62 = $5 + ($inc << 2) | 0;
+ $19 = HEAP32[$arrayidx62 >> 2] | 0;
+ $tobool = ($19 | 0) == 0;
+ if ($tobool) {
+ label = 23;
+ break;
+ } else {
+ $i_037 = $inc;
+ $onleft_038 = $onleft_1;
+ $onright_039 = $onright_1;
+ $16 = $19;
+ label = 20;
+ break;
+ }
+ case 23:
+ $tobool78 = $onleft_1 << 24 >> 24 != 0;
+ $cmp81 = $onright_1 << 24 >> 24 == 0;
+ $or_cond33 = $tobool78 & $cmp81;
+ if ($or_cond33) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $add = $1 + 1 | 0;
+ HEAP32[$bounds >> 2] = $add;
+ label = 25;
+ break;
+ case 25:
+ $tobool87 = $onright_1 << 24 >> 24 != 0;
+ $cmp90 = $onleft_1 << 24 >> 24 == 0;
+ $or_cond34 = $tobool87 & $cmp90;
+ if ($or_cond34) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $sub = $1 - 1 | 0;
+ $arrayidx93 = $bounds + 4 | 0;
+ HEAP32[$arrayidx93 >> 2] = $sub;
+ label = 27;
+ break;
+ case 27:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _exchange($v, $w) {
+ $v = $v | 0;
+ $w = $w | 0;
+ var $0 = 0, $order = 0, $1 = 0, $order3 = 0, $2 = 0;
+ $0 = HEAP32[$v + 236 >> 2] | 0;
+ $order = $v + 240 | 0;
+ $1 = HEAP32[$order >> 2] | 0;
+ $order3 = $w + 240 | 0;
+ $2 = HEAP32[$order3 >> 2] | 0;
+ HEAP32[$order >> 2] = $2;
+ HEAP32[(HEAP32[(HEAP32[(HEAP32[41526] | 0) + 224 >> 2] | 0) + ($0 * 44 & -1) + 4 >> 2] | 0) + ($2 << 2) >> 2] = $v;
+ HEAP32[$order3 >> 2] = $1;
+ HEAP32[(HEAP32[(HEAP32[(HEAP32[41526] | 0) + 224 >> 2] | 0) + ($0 * 44 & -1) + 4 >> 2] | 0) + ($1 << 2) >> 2] = $w;
+ return;
+}
+function _flat_rev($g, $e) {
+ $g = $g | 0;
+ $e = $e | 0;
+ var $head = 0, $0 = 0, $list = 0, $1 = 0, $tobool = 0, $2 = 0, $list4 = 0, $3 = 0, $tail = 0, $j_0 = 0, $arrayidx = 0, $4 = 0, $tobool5 = 0, $head6 = 0, $5 = 0, $6 = 0, $cmp = 0, $inc = 0, $to_virt = 0, $7 = 0, $cmp12 = 0, $edge_type = 0, $8 = 0, $cmp18 = 0, $to_orig = 0, $9 = 0, $cmp21 = 0, $tail27 = 0, $10 = 0, $list29 = 0, $11 = 0, $tobool30 = 0, $12 = 0, $size = 0, $13 = 0, $add = 0, $mul = 0, $call = 0, $size41 = 0, $14 = 0, $add42 = 0, $mul43 = 0, $call44 = 0, $call_sink = 0, $15 = 0, $16 = 0, $list48 = 0, $17 = 0, $size52 = 0, $18 = 0, $inc53 = 0, $19 = 0, $list57 = 0, $20 = 0, $arrayidx58 = 0, $21 = 0, $size62 = 0, $22 = 0, $list66 = 0, $23 = 0, $arrayidx67 = 0, $24 = 0, $tail70 = 0, $25 = 0, $call71 = 0, $edge_type73 = 0, $26 = 0, $cmp75 = 0, $edge_type79 = 0, $_ = 0, $label = 0, $27 = 0, $label86 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $head = $e + 12 | 0;
+ $0 = HEAP32[$head >> 2] | 0;
+ $list = $0 + 192 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$head >> 2] | 0;
+ $list4 = $2 + 192 | 0;
+ $3 = HEAP32[$list4 >> 2] | 0;
+ $tail = $e + 16 | 0;
+ $j_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $3 + ($j_0 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool5 = ($4 | 0) == 0;
+ if ($tobool5) {
+ label = 15;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $head6 = $4 + 12 | 0;
+ $5 = HEAP32[$head6 >> 2] | 0;
+ $6 = HEAP32[$tail >> 2] | 0;
+ $cmp = ($5 | 0) == ($6 | 0);
+ $inc = $j_0 + 1 | 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ $j_0 = $inc;
+ label = 4;
+ break;
+ }
+ case 6:
+ _merge_oneway($e, $4);
+ $to_virt = $e + 188 | 0;
+ $7 = HEAP32[$to_virt >> 2] | 0;
+ $cmp12 = ($7 | 0) == 0;
+ if ($cmp12) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$to_virt >> 2] = $4;
+ label = 8;
+ break;
+ case 8:
+ $edge_type = $4 + 128 | 0;
+ $8 = HEAP8[$edge_type] | 0;
+ $cmp18 = $8 << 24 >> 24 == 4;
+ if ($cmp18) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $to_orig = $4 + 132 | 0;
+ $9 = HEAP32[$to_orig >> 2] | 0;
+ $cmp21 = ($9 | 0) == 0;
+ if ($cmp21) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$to_orig >> 2] = $e;
+ label = 11;
+ break;
+ case 11:
+ $tail27 = $e + 16 | 0;
+ $10 = HEAP32[$tail27 >> 2] | 0;
+ $list29 = $10 + 208 | 0;
+ $11 = HEAP32[$list29 >> 2] | 0;
+ $tobool30 = ($11 | 0) == 0;
+ if ($tobool30) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $12 = $11;
+ $size = $10 + 212 | 0;
+ $13 = HEAP32[$size >> 2] | 0;
+ $add = $13 << 2;
+ $mul = $add + 8 | 0;
+ $call = _grealloc($12, $mul) | 0;
+ $call_sink = $call;
+ label = 14;
+ break;
+ case 13:
+ $size41 = $10 + 212 | 0;
+ $14 = HEAP32[$size41 >> 2] | 0;
+ $add42 = $14 << 2;
+ $mul43 = $add42 + 8 | 0;
+ $call44 = _gmalloc($mul43) | 0;
+ $call_sink = $call44;
+ label = 14;
+ break;
+ case 14:
+ $15 = $call_sink;
+ $16 = HEAP32[$tail27 >> 2] | 0;
+ $list48 = $16 + 208 | 0;
+ HEAP32[$list48 >> 2] = $15;
+ $17 = HEAP32[$tail27 >> 2] | 0;
+ $size52 = $17 + 212 | 0;
+ $18 = HEAP32[$size52 >> 2] | 0;
+ $inc53 = $18 + 1 | 0;
+ HEAP32[$size52 >> 2] = $inc53;
+ $19 = HEAP32[$tail27 >> 2] | 0;
+ $list57 = $19 + 208 | 0;
+ $20 = HEAP32[$list57 >> 2] | 0;
+ $arrayidx58 = $20 + ($18 << 2) | 0;
+ HEAP32[$arrayidx58 >> 2] = $e;
+ $21 = HEAP32[$tail27 >> 2] | 0;
+ $size62 = $21 + 212 | 0;
+ $22 = HEAP32[$size62 >> 2] | 0;
+ $list66 = $21 + 208 | 0;
+ $23 = HEAP32[$list66 >> 2] | 0;
+ $arrayidx67 = $23 + ($22 << 2) | 0;
+ HEAP32[$arrayidx67 >> 2] = 0;
+ label = 16;
+ break;
+ case 15:
+ $24 = HEAP32[$head >> 2] | 0;
+ $tail70 = $e + 16 | 0;
+ $25 = HEAP32[$tail70 >> 2] | 0;
+ $call71 = _new_virtual_edge($24, $25, $e) | 0;
+ $edge_type73 = $e + 128 | 0;
+ $26 = HEAP8[$edge_type73] | 0;
+ $cmp75 = $26 << 24 >> 24 == 4;
+ $edge_type79 = $call71 + 128 | 0;
+ $_ = $cmp75 ? 4 : 3;
+ HEAP8[$edge_type79] = $_;
+ $label = $e + 112 | 0;
+ $27 = HEAP32[$label >> 2] | 0;
+ $label86 = $call71 + 112 | 0;
+ HEAP32[$label86 >> 2] = $27;
+ _flat_edge($g, $call71);
+ label = 16;
+ break;
+ case 16:
+ return;
+ }
+}
+function _allocate_ranks($g) {
+ $g = $g | 0;
+ var $maxrank = 0, $0 = 0, $conv = 0, $add = 0, $mul = 0, $call = 0, $1 = 0, $2 = 0, $call1 = 0, $tobool46 = 0, $n_0_in47 = 0, $rank = 0, $3 = 0, $4 = 0, $arrayidx = 0, $5 = 0, $inc = 0, $call3 = 0, $tobool544 = 0, $e_0_in45 = 0, $tail = 0, $6 = 0, $rank8 = 0, $7 = 0, $8 = 0, $head = 0, $9 = 0, $rank10 = 0, $10 = 0, $11 = 0, $cmp = 0, $_ = 0, $_37 = 0, $r_041 = 0, $cmp1442 = 0, $r_043 = 0, $arrayidx17 = 0, $12 = 0, $inc18 = 0, $r_0 = 0, $cmp14 = 0, $call21 = 0, $tobool5 = 0, $call24 = 0, $tobool = 0, $13 = 0, $conv28 = 0, $14 = 0, $mul30 = 0, $call31 = 0, $15 = 0, $rank33 = 0, $minrank = 0, $16 = 0, $17 = 0, $cmp4039 = 0, $conv35 = 0, $r_140 = 0, $arrayidx43 = 0, $18 = 0, $19 = 0, $n47 = 0, $20 = 0, $an = 0, $21 = 0, $add52 = 0, $mul53 = 0, $call54 = 0, $22 = 0, $23 = 0, $v = 0, $24 = 0, $av = 0, $inc62 = 0, $25 = 0, $conv39 = 0, $cmp40 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $maxrank = $g + 250 | 0;
+ $0 = HEAP16[$maxrank >> 1] | 0;
+ $conv = $0 << 16 >> 16;
+ $add = $conv << 2;
+ $mul = $add + 8 | 0;
+ $call = _zmalloc($mul) | 0;
+ $1 = $call;
+ $2 = $g;
+ $call1 = _agfstnode($2) | 0;
+ $tobool46 = ($call1 | 0) == 0;
+ if ($tobool46) {
+ label = 8;
+ break;
+ } else {
+ $n_0_in47 = $call1;
+ label = 3;
+ break;
+ }
+ case 3:
+ $rank = $n_0_in47 + 236 | 0;
+ $3 = $rank;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $arrayidx = $1 + ($4 << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $inc = $5 + 1 | 0;
+ HEAP32[$arrayidx >> 2] = $inc;
+ $call3 = _agfstout($2, $n_0_in47) | 0;
+ $tobool544 = ($call3 | 0) == 0;
+ if ($tobool544) {
+ label = 7;
+ break;
+ } else {
+ $e_0_in45 = $call3;
+ label = 4;
+ break;
+ }
+ case 4:
+ $tail = $e_0_in45 + 16 | 0;
+ $6 = HEAP32[$tail >> 2] | 0;
+ $rank8 = $6 + 236 | 0;
+ $7 = $rank8;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $head = $e_0_in45 + 12 | 0;
+ $9 = HEAP32[$head >> 2] | 0;
+ $rank10 = $9 + 236 | 0;
+ $10 = $rank10;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $cmp = ($8 | 0) > ($11 | 0);
+ $_ = $cmp ? $8 : $11;
+ $_37 = $cmp ? $11 : $8;
+ $r_041 = $_37 + 1 | 0;
+ $cmp1442 = ($r_041 | 0) < ($_ | 0);
+ if ($cmp1442) {
+ $r_043 = $r_041;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $arrayidx17 = $1 + ($r_043 << 2) | 0;
+ $12 = HEAP32[$arrayidx17 >> 2] | 0;
+ $inc18 = $12 + 1 | 0;
+ HEAP32[$arrayidx17 >> 2] = $inc18;
+ $r_0 = $r_043 + 1 | 0;
+ $cmp14 = ($r_0 | 0) < ($_ | 0);
+ if ($cmp14) {
+ $r_043 = $r_0;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call21 = _agnxtout($2, $e_0_in45) | 0;
+ $tobool5 = ($call21 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ $e_0_in45 = $call21;
+ label = 4;
+ break;
+ }
+ case 7:
+ $call24 = _agnxtnode($2, $n_0_in47) | 0;
+ $tobool = ($call24 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $n_0_in47 = $call24;
+ label = 3;
+ break;
+ }
+ case 8:
+ $13 = HEAP16[$maxrank >> 1] | 0;
+ $conv28 = $13 << 16 >> 16;
+ $14 = $conv28 * 44 & -1;
+ $mul30 = $14 + 88 | 0;
+ $call31 = _zmalloc($mul30) | 0;
+ $15 = $call31;
+ $rank33 = $g + 224 | 0;
+ HEAP32[$rank33 >> 2] = $15;
+ $minrank = $g + 248 | 0;
+ $16 = HEAP16[$minrank >> 1] | 0;
+ $17 = HEAP16[$maxrank >> 1] | 0;
+ $cmp4039 = $16 << 16 >> 16 > $17 << 16 >> 16;
+ if ($cmp4039) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $conv35 = $16 << 16 >> 16;
+ $r_140 = $conv35;
+ label = 10;
+ break;
+ case 10:
+ $arrayidx43 = $1 + ($r_140 << 2) | 0;
+ $18 = HEAP32[$arrayidx43 >> 2] | 0;
+ $19 = HEAP32[$rank33 >> 2] | 0;
+ $n47 = $19 + ($r_140 * 44 & -1) | 0;
+ HEAP32[$n47 >> 2] = $18;
+ $20 = HEAP32[$rank33 >> 2] | 0;
+ $an = $20 + ($r_140 * 44 & -1) + 8 | 0;
+ HEAP32[$an >> 2] = $18;
+ $21 = HEAP32[$arrayidx43 >> 2] | 0;
+ $add52 = $21 << 2;
+ $mul53 = $add52 + 4 | 0;
+ $call54 = _zmalloc($mul53) | 0;
+ $22 = $call54;
+ $23 = HEAP32[$rank33 >> 2] | 0;
+ $v = $23 + ($r_140 * 44 & -1) + 4 | 0;
+ HEAP32[$v >> 2] = $22;
+ $24 = HEAP32[$rank33 >> 2] | 0;
+ $av = $24 + ($r_140 * 44 & -1) + 12 | 0;
+ HEAP32[$av >> 2] = $22;
+ $inc62 = $r_140 + 1 | 0;
+ $25 = HEAP16[$maxrank >> 1] | 0;
+ $conv39 = $25 << 16 >> 16;
+ $cmp40 = ($inc62 | 0) > ($conv39 | 0);
+ if ($cmp40) {
+ label = 11;
+ break;
+ } else {
+ $r_140 = $inc62;
+ label = 10;
+ break;
+ }
+ case 11:
+ _free($call);
+ return;
+ }
+}
+function _build_ranks($g, $pass) {
+ $g = $g | 0;
+ $pass = $pass | 0;
+ var $n_nodes = 0, $0 = 0, $call = 0, $nlist = 0, $n_061 = 0, $tobool62 = 0, $n_063 = 0, $mark = 0, $next = 0, $n_0 = 0, $tobool = 0, $minrank = 0, $1 = 0, $maxrank = 0, $2 = 0, $cmp59 = 0, $conv = 0, $rank = 0, $n_155 = 0, $tobool1756 = 0, $cmp19 = 0, $3 = 0, $4 = 0, $i_060 = 0, $5 = 0, $n11 = 0, $inc = 0, $6 = 0, $conv7 = 0, $cmp = 0, $n_157 = 0, $list = 0, $list23 = 0, $cond_in = 0, $cond = 0, $7 = 0, $cmp25 = 0, $mark28 = 0, $8 = 0, $cmp30 = 0, $call3552 = 0, $tobool3653 = 0, $call3554 = 0, $ranktype = 0, $9 = 0, $cmp39 = 0, $10 = 0, $call35 = 0, $tobool36 = 0, $next46 = 0, $n_1 = 0, $tobool17 = 0, $call48 = 0, $tobool49 = 0, $call51 = 0, $11 = 0, $12 = 0, $cmp6050 = 0, $conv55 = 0, $rankdir = 0, $rank70 = 0, $i_151 = 0, $13 = 0, $rank64 = 0, $14 = 0, $valid = 0, $15 = 0, $and67 = 0, $tobool68 = 0, $16 = 0, $n72 = 0, $17 = 0, $cmp73 = 0, $v = 0, $18 = 0, $sub = 0, $div = 0, $j_048 = 0, $arrayidx88 = 0, $19 = 0, $sub89 = 0, $arrayidx90 = 0, $20 = 0, $inc92 = 0, $cmp85 = 0, $inc96 = 0, $21 = 0, $conv59 = 0, $cmp60 = 0, $root = 0, $22 = 0, $cmp98 = 0, $call101 = 0, $cmp102 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_nodes = $g + 244 | 0;
+ $0 = HEAP32[$n_nodes >> 2] | 0;
+ $call = _new_queue($0) | 0;
+ $nlist = $g + 220 | 0;
+ $n_061 = HEAP32[$nlist >> 2] | 0;
+ $tobool62 = ($n_061 | 0) == 0;
+ if ($tobool62) {
+ label = 4;
+ break;
+ } else {
+ $n_063 = $n_061;
+ label = 3;
+ break;
+ }
+ case 3:
+ $mark = $n_063 + 163 | 0;
+ HEAP8[$mark] = 0;
+ $next = $n_063 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_063 = $n_0;
+ label = 3;
+ break;
+ }
+ case 4:
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $cmp59 = $1 << 16 >> 16 > $2 << 16 >> 16;
+ if ($cmp59) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $conv = $1 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $i_060 = $conv;
+ label = 8;
+ break;
+ case 6:
+ $n_155 = HEAP32[$nlist >> 2] | 0;
+ $tobool1756 = ($n_155 | 0) == 0;
+ if ($tobool1756) {
+ label = 17;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp19 = ($pass | 0) == 0;
+ $3 = $g;
+ $4 = $call;
+ $n_157 = $n_155;
+ label = 9;
+ break;
+ case 8:
+ $5 = HEAP32[$rank >> 2] | 0;
+ $n11 = $5 + ($i_060 * 44 & -1) | 0;
+ HEAP32[$n11 >> 2] = 0;
+ $inc = $i_060 + 1 | 0;
+ $6 = HEAP16[$maxrank >> 1] | 0;
+ $conv7 = $6 << 16 >> 16;
+ $cmp = ($inc | 0) > ($conv7 | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ $i_060 = $inc;
+ label = 8;
+ break;
+ }
+ case 9:
+ $list = $n_157 + 176 | 0;
+ $list23 = $n_157 + 184 | 0;
+ $cond_in = $cmp19 ? $list : $list23;
+ $cond = HEAP32[$cond_in >> 2] | 0;
+ $7 = HEAP32[$cond >> 2] | 0;
+ $cmp25 = ($7 | 0) == 0;
+ if ($cmp25) {
+ label = 10;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 10:
+ $mark28 = $n_157 + 163 | 0;
+ $8 = HEAP8[$mark28] | 0;
+ $cmp30 = $8 << 24 >> 24 == 0;
+ if ($cmp30) {
+ label = 11;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 11:
+ HEAP8[$mark28] = 1;
+ _enqueue($call, $n_157);
+ $call3552 = _dequeue($call) | 0;
+ $tobool3653 = ($call3552 | 0) == 0;
+ if ($tobool3653) {
+ label = 16;
+ break;
+ } else {
+ $call3554 = $call3552;
+ label = 12;
+ break;
+ }
+ case 12:
+ $ranktype = $call3554 + 165 | 0;
+ $9 = HEAP8[$ranktype] | 0;
+ $cmp39 = $9 << 24 >> 24 == 7;
+ if ($cmp39) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _install_in_rank($g, $call3554);
+ _enqueue_neighbors($call, $call3554, $pass);
+ label = 15;
+ break;
+ case 14:
+ $10 = $call3554;
+ _install_cluster($3, $10, $pass, $4);
+ label = 15;
+ break;
+ case 15:
+ $call35 = _dequeue($call) | 0;
+ $tobool36 = ($call35 | 0) == 0;
+ if ($tobool36) {
+ label = 16;
+ break;
+ } else {
+ $call3554 = $call35;
+ label = 12;
+ break;
+ }
+ case 16:
+ $next46 = $n_157 + 168 | 0;
+ $n_1 = HEAP32[$next46 >> 2] | 0;
+ $tobool17 = ($n_1 | 0) == 0;
+ if ($tobool17) {
+ label = 17;
+ break;
+ } else {
+ $n_157 = $n_1;
+ label = 9;
+ break;
+ }
+ case 17:
+ $call48 = _dequeue($call) | 0;
+ $tobool49 = ($call48 | 0) == 0;
+ if ($tobool49) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $call51 = _agerr(1, 109616, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0) | 0;
+ label = 19;
+ break;
+ case 19:
+ $11 = HEAP16[$minrank >> 1] | 0;
+ $12 = HEAP16[$maxrank >> 1] | 0;
+ $cmp6050 = $11 << 16 >> 16 > $12 << 16 >> 16;
+ if ($cmp6050) {
+ label = 26;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $conv55 = $11 << 16 >> 16;
+ $rankdir = $g + 156 | 0;
+ $rank70 = $g + 224 | 0;
+ $i_151 = $conv55;
+ label = 21;
+ break;
+ case 21:
+ $13 = HEAP32[41526] | 0;
+ $rank64 = $13 + 224 | 0;
+ $14 = HEAP32[$rank64 >> 2] | 0;
+ $valid = $14 + ($i_151 * 44 & -1) + 33 | 0;
+ HEAP8[$valid] = 0;
+ $15 = HEAP32[$rankdir >> 2] | 0;
+ $and67 = $15 & 1;
+ $tobool68 = ($and67 | 0) == 0;
+ if ($tobool68) {
+ label = 25;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $16 = HEAP32[$rank70 >> 2] | 0;
+ $n72 = $16 + ($i_151 * 44 & -1) | 0;
+ $17 = HEAP32[$n72 >> 2] | 0;
+ $cmp73 = ($17 | 0) > 0;
+ if ($cmp73) {
+ label = 23;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 23:
+ $v = $16 + ($i_151 * 44 & -1) + 4 | 0;
+ $18 = HEAP32[$v >> 2] | 0;
+ $sub = $17 - 1 | 0;
+ $div = ($sub | 0) / 2 & -1;
+ $j_048 = 0;
+ label = 24;
+ break;
+ case 24:
+ $arrayidx88 = $18 + ($j_048 << 2) | 0;
+ $19 = HEAP32[$arrayidx88 >> 2] | 0;
+ $sub89 = $sub - $j_048 | 0;
+ $arrayidx90 = $18 + ($sub89 << 2) | 0;
+ $20 = HEAP32[$arrayidx90 >> 2] | 0;
+ _exchange($19, $20);
+ $inc92 = $j_048 + 1 | 0;
+ $cmp85 = ($inc92 | 0) > ($div | 0);
+ if ($cmp85) {
+ label = 25;
+ break;
+ } else {
+ $j_048 = $inc92;
+ label = 24;
+ break;
+ }
+ case 25:
+ $inc96 = $i_151 + 1 | 0;
+ $21 = HEAP16[$maxrank >> 1] | 0;
+ $conv59 = $21 << 16 >> 16;
+ $cmp60 = ($inc96 | 0) > ($conv59 | 0);
+ if ($cmp60) {
+ label = 26;
+ break;
+ } else {
+ $i_151 = $inc96;
+ label = 21;
+ break;
+ }
+ case 26:
+ $root = $g + 32 | 0;
+ $22 = HEAP32[$root >> 2] | 0;
+ $cmp98 = ($22 | 0) == ($g | 0);
+ if ($cmp98) {
+ label = 27;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 27:
+ $call101 = _ncross(0) | 0;
+ $cmp102 = ($call101 | 0) > 0;
+ if ($cmp102) {
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ _transpose($g, 0);
+ label = 29;
+ break;
+ case 29:
+ _free_queue($call);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _enqueue_neighbors($q, $n0, $pass) {
+ $q = $q | 0;
+ $n0 = $n0 | 0;
+ $pass = $pass | 0;
+ var $cmp = 0, $size14 = 0, $0 = 0, $cmp1518 = 0, $list20 = 0, $size = 0, $1 = 0, $cmp115 = 0, $list = 0, $i_016 = 0, $2 = 0, $arrayidx = 0, $3 = 0, $head = 0, $4 = 0, $mark = 0, $5 = 0, $cmp5 = 0, $6 = 0, $inc = 0, $7 = 0, $cmp1 = 0, $i_119 = 0, $8 = 0, $arrayidx21 = 0, $9 = 0, $tail = 0, $10 = 0, $mark23 = 0, $11 = 0, $cmp25 = 0, $12 = 0, $inc34 = 0, $13 = 0, $cmp15 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($pass | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $size14 = $n0 + 180 | 0;
+ $0 = HEAP32[$size14 >> 2] | 0;
+ $cmp1518 = ($0 | 0) > 0;
+ if ($cmp1518) {
+ label = 4;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 4:
+ $list20 = $n0 + 176 | 0;
+ $i_119 = 0;
+ label = 10;
+ break;
+ case 5:
+ $size = $n0 + 188 | 0;
+ $1 = HEAP32[$size >> 2] | 0;
+ $cmp115 = ($1 | 0) > 0;
+ if ($cmp115) {
+ label = 6;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 6:
+ $list = $n0 + 184 | 0;
+ $i_016 = 0;
+ label = 7;
+ break;
+ case 7:
+ $2 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $2 + ($i_016 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $head = $3 + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ $mark = $4 + 163 | 0;
+ $5 = HEAP8[$mark] | 0;
+ $cmp5 = $5 << 24 >> 24 == 0;
+ if ($cmp5) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ HEAP8[$mark] = 1;
+ $6 = HEAP32[$head >> 2] | 0;
+ _enqueue($q, $6);
+ label = 9;
+ break;
+ case 9:
+ $inc = $i_016 + 1 | 0;
+ $7 = HEAP32[$size >> 2] | 0;
+ $cmp1 = ($inc | 0) < ($7 | 0);
+ if ($cmp1) {
+ $i_016 = $inc;
+ label = 7;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 10:
+ $8 = HEAP32[$list20 >> 2] | 0;
+ $arrayidx21 = $8 + ($i_119 << 2) | 0;
+ $9 = HEAP32[$arrayidx21 >> 2] | 0;
+ $tail = $9 + 16 | 0;
+ $10 = HEAP32[$tail >> 2] | 0;
+ $mark23 = $10 + 163 | 0;
+ $11 = HEAP8[$mark23] | 0;
+ $cmp25 = $11 << 24 >> 24 == 0;
+ if ($cmp25) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ HEAP8[$mark23] = 1;
+ $12 = HEAP32[$tail >> 2] | 0;
+ _enqueue($q, $12);
+ label = 12;
+ break;
+ case 12:
+ $inc34 = $i_119 + 1 | 0;
+ $13 = HEAP32[$size14 >> 2] | 0;
+ $cmp15 = ($inc34 | 0) < ($13 | 0);
+ if ($cmp15) {
+ $i_119 = $inc34;
+ label = 10;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ return;
+ }
+}
+function _ncross($g) {
+ $g = $g | 0;
+ var $0 = 0, $minrank = 0, $1 = 0, $maxrank = 0, $2 = 0, $cmp16 = 0, $conv = 0, $rank = 0, $count_018 = 0, $r_017 = 0, $3 = 0, $valid = 0, $4 = 0, $tobool = 0, $cache_nc = 0, $5 = 0, $call = 0, $6 = 0, $cache_nc11 = 0, $7 = 0, $valid16 = 0, $_pn = 0, $count_1 = 0, $inc = 0, $8 = 0, $conv2 = 0, $cmp = 0, $count_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41526] | 0;
+ $minrank = $0 + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $0 + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $cmp16 = $1 << 16 >> 16 < $2 << 16 >> 16;
+ if ($cmp16) {
+ label = 3;
+ break;
+ } else {
+ $count_0_lcssa = 0;
+ label = 8;
+ break;
+ }
+ case 3:
+ $conv = $1 << 16 >> 16;
+ $rank = $0 + 224 | 0;
+ $r_017 = $conv;
+ $count_018 = 0;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[$rank >> 2] | 0;
+ $valid = $3 + ($r_017 * 44 & -1) + 33 | 0;
+ $4 = HEAP8[$valid] | 0;
+ $tobool = $4 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cache_nc = $3 + ($r_017 * 44 & -1) + 36 | 0;
+ $5 = HEAP32[$cache_nc >> 2] | 0;
+ $_pn = $5;
+ label = 7;
+ break;
+ case 6:
+ $call = _rcross($0, $r_017) | 0;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $cache_nc11 = $6 + ($r_017 * 44 & -1) + 36 | 0;
+ HEAP32[$cache_nc11 >> 2] = $call;
+ $7 = HEAP32[$rank >> 2] | 0;
+ $valid16 = $7 + ($r_017 * 44 & -1) + 33 | 0;
+ HEAP8[$valid16] = 1;
+ $_pn = $call;
+ label = 7;
+ break;
+ case 7:
+ $count_1 = $_pn + $count_018 | 0;
+ $inc = $r_017 + 1 | 0;
+ $8 = HEAP16[$maxrank >> 1] | 0;
+ $conv2 = $8 << 16 >> 16;
+ $cmp = ($inc | 0) < ($conv2 | 0);
+ if ($cmp) {
+ $r_017 = $inc;
+ $count_018 = $count_1;
+ label = 4;
+ break;
+ } else {
+ $count_0_lcssa = $count_1;
+ label = 8;
+ break;
+ }
+ case 8:
+ return $count_0_lcssa | 0;
+ }
+ return 0;
+}
+function _transpose($g, $reverse) {
+ $g = $g | 0;
+ $reverse = $reverse | 0;
+ var $minrank = 0, $0 = 0, $maxrank = 0, $1 = 0, $cmp19 = 0, $conv = 0, $rank = 0, $rank16 = 0, $r_020 = 0, $2 = 0, $candidate = 0, $inc = 0, $3 = 0, $conv2 = 0, $cmp = 0, $4 = 0, $5 = 0, $cmp1215 = 0, $conv7 = 0, $delta_017 = 0, $r_116 = 0, $6 = 0, $candidate18 = 0, $7 = 0, $tobool = 0, $call = 0, $add = 0, $delta_1 = 0, $inc20 = 0, $8 = 0, $conv11 = 0, $cmp12 = 0, $cmp22 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $cmp19 = $0 << 16 >> 16 > $1 << 16 >> 16;
+ if ($cmp19) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $r_020 = $conv;
+ label = 5;
+ break;
+ case 4:
+ $rank16 = $g + 224 | 0;
+ label = 6;
+ break;
+ case 5:
+ $2 = HEAP32[$rank >> 2] | 0;
+ $candidate = $2 + ($r_020 * 44 & -1) + 32 | 0;
+ HEAP8[$candidate] = 1;
+ $inc = $r_020 + 1 | 0;
+ $3 = HEAP16[$maxrank >> 1] | 0;
+ $conv2 = $3 << 16 >> 16;
+ $cmp = ($inc | 0) > ($conv2 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $r_020 = $inc;
+ label = 5;
+ break;
+ }
+ case 6:
+ $4 = HEAP16[$minrank >> 1] | 0;
+ $5 = HEAP16[$maxrank >> 1] | 0;
+ $cmp1215 = $4 << 16 >> 16 > $5 << 16 >> 16;
+ if ($cmp1215) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $conv7 = $4 << 16 >> 16;
+ $r_116 = $conv7;
+ $delta_017 = 0;
+ label = 8;
+ break;
+ case 8:
+ $6 = HEAP32[$rank16 >> 2] | 0;
+ $candidate18 = $6 + ($r_116 * 44 & -1) + 32 | 0;
+ $7 = HEAP8[$candidate18] | 0;
+ $tobool = $7 << 24 >> 24 == 0;
+ if ($tobool) {
+ $delta_1 = $delta_017;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $call = _transpose_step($g, $r_116, $reverse) | 0;
+ $add = $call + $delta_017 | 0;
+ $delta_1 = $add;
+ label = 10;
+ break;
+ case 10:
+ $inc20 = $r_116 + 1 | 0;
+ $8 = HEAP16[$maxrank >> 1] | 0;
+ $conv11 = $8 << 16 >> 16;
+ $cmp12 = ($inc20 | 0) > ($conv11 | 0);
+ if ($cmp12) {
+ label = 11;
+ break;
+ } else {
+ $r_116 = $inc20;
+ $delta_017 = $delta_1;
+ label = 8;
+ break;
+ }
+ case 11:
+ $cmp22 = ($delta_1 | 0) > 0;
+ if ($cmp22) {
+ label = 6;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ return;
+ }
+}
+function _install_in_rank($g, $n) {
+ $g = $g | 0;
+ $n = $n | 0;
+ var $rank = 0, $0 = 0, $rank2 = 0, $1 = 0, $n3 = 0, $2 = 0, $an = 0, $3 = 0, $cmp = 0, $name = 0, $4 = 0, $name7 = 0, $5 = 0, $call = 0, $v = 0, $6 = 0, $arrayidx11 = 0, $order = 0, $7 = 0, $n16 = 0, $8 = 0, $inc = 0, $9 = 0, $n20 = 0, $10 = 0, $an24 = 0, $11 = 0, $cmp25 = 0, $12 = 0, $13 = 0, $rank29 = 0, $14 = 0, $an31 = 0, $15 = 0, $cmp32 = 0, $minrank = 0, $16 = 0, $conv = 0, $cmp36 = 0, $maxrank = 0, $17 = 0, $conv39 = 0, $cmp40 = 0, $v47 = 0, $18 = 0, $add_ptr = 0, $av = 0, $19 = 0, $add_ptr57 = 0, $cmp58 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $n + 236 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $rank2 = $g + 224 | 0;
+ $1 = HEAP32[$rank2 >> 2] | 0;
+ $n3 = $1 + ($0 * 44 & -1) | 0;
+ $2 = HEAP32[$n3 >> 2] | 0;
+ $an = $1 + ($0 * 44 & -1) + 8 | 0;
+ $3 = HEAP32[$an >> 2] | 0;
+ $cmp = ($3 | 0) < 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $name = $g + 12 | 0;
+ $4 = HEAP32[$name >> 2] | 0;
+ $name7 = $n + 12 | 0;
+ $5 = HEAP32[$name7 >> 2] | 0;
+ $call = _agerr(1, 136624, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $4, HEAP32[tempInt + 8 >> 2] = $5, HEAP32[tempInt + 16 >> 2] = $0, HEAP32[tempInt + 24 >> 2] = $2, tempInt) | 0) | 0;
+ _abort();
+ case 4:
+ $v = $1 + ($0 * 44 & -1) + 4 | 0;
+ $6 = HEAP32[$v >> 2] | 0;
+ $arrayidx11 = $6 + ($2 << 2) | 0;
+ HEAP32[$arrayidx11 >> 2] = $n;
+ $order = $n + 240 | 0;
+ HEAP32[$order >> 2] = $2;
+ $7 = HEAP32[$rank2 >> 2] | 0;
+ $n16 = $7 + ($0 * 44 & -1) | 0;
+ $8 = HEAP32[$n16 >> 2] | 0;
+ $inc = $8 + 1 | 0;
+ HEAP32[$n16 >> 2] = $inc;
+ $9 = HEAP32[$rank2 >> 2] | 0;
+ $n20 = $9 + ($0 * 44 & -1) | 0;
+ $10 = HEAP32[$n20 >> 2] | 0;
+ $an24 = $9 + ($0 * 44 & -1) + 8 | 0;
+ $11 = HEAP32[$an24 >> 2] | 0;
+ $cmp25 = ($10 | 0) > ($11 | 0);
+ if ($cmp25) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ ___assert_func(119784, 1028, 164184, 114216);
+ case 6:
+ $12 = HEAP32[$order >> 2] | 0;
+ $13 = HEAP32[41526] | 0;
+ $rank29 = $13 + 224 | 0;
+ $14 = HEAP32[$rank29 >> 2] | 0;
+ $an31 = $14 + ($0 * 44 & -1) + 8 | 0;
+ $15 = HEAP32[$an31 >> 2] | 0;
+ $cmp32 = ($12 | 0) > ($15 | 0);
+ if ($cmp32) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ _abort();
+ case 8:
+ $minrank = $g + 248 | 0;
+ $16 = HEAP16[$minrank >> 1] | 0;
+ $conv = $16 << 16 >> 16;
+ $cmp36 = ($0 | 0) < ($conv | 0);
+ if ($cmp36) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $maxrank = $g + 250 | 0;
+ $17 = HEAP16[$maxrank >> 1] | 0;
+ $conv39 = $17 << 16 >> 16;
+ $cmp40 = ($0 | 0) > ($conv39 | 0);
+ if ($cmp40) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _abort();
+ case 11:
+ $v47 = $9 + ($0 * 44 & -1) + 4 | 0;
+ $18 = HEAP32[$v47 >> 2] | 0;
+ $add_ptr = $18 + ($12 << 2) | 0;
+ $av = $9 + ($0 * 44 & -1) + 12 | 0;
+ $19 = HEAP32[$av >> 2] | 0;
+ $add_ptr57 = $19 + ($15 << 2) | 0;
+ $cmp58 = $add_ptr >>> 0 > $add_ptr57 >>> 0;
+ if ($cmp58) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ _abort();
+ case 13:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _endpoint_class($n) {
+ $n = $n | 0;
+ var $node_type = 0, $0 = 0, $cmp = 0, $weight_class = 0, $1 = 0, $cmp4 = 0, $_ = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $n + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 1;
+ if ($cmp) {
+ $retval_0 = 2;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $weight_class = $n + 166 | 0;
+ $1 = HEAP8[$weight_class] | 0;
+ $cmp4 = $1 << 24 >> 24 < 2;
+ $_ = $cmp4 & 1;
+ $retval_0 = $_;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _local_cross($l, $dir) {
+ $l = $l | 0;
+ $dir = $dir | 0;
+ var $cmp = 0, $list = 0, $0 = 0, $1 = 0, $tobool28 = 0, $2 = 0, $cross_0_be = 0, $arrayidx = 0, $3 = 0, $tobool = 0, $4 = 0, $i_030 = 0, $cross_029 = 0, $add = 0, $arrayidx523 = 0, $5 = 0, $tobool624 = 0, $head8 = 0, $6 = 0, $order10 = 0, $7 = 0, $x15 = 0, $8 = 0.0, $xpenalty = 0, $tail37 = 0, $9 = 0, $order39 = 0, $10 = 0, $x48 = 0, $11 = 0.0, $xpenalty55 = 0, $12 = 0, $cross_126 = 0, $j_025 = 0, $head = 0, $13 = 0, $order = 0, $14 = 0, $sub = 0, $conv = 0.0, $x = 0, $15 = 0.0, $sub16 = 0.0, $mul = 0.0, $cmp17 = 0, $16 = 0, $conv21 = 0, $xpenalty23 = 0, $17 = 0, $conv24 = 0, $mul25 = 0, $add26 = 0, $cross_2 = 0, $inc = 0, $arrayidx5 = 0, $18 = 0, $tobool6 = 0, $19 = 0, $cross_321 = 0, $j_120 = 0, $tail = 0, $20 = 0, $order36 = 0, $21 = 0, $sub40 = 0, $conv41 = 0.0, $x44 = 0, $22 = 0.0, $sub49 = 0.0, $mul50 = 0.0, $cmp51 = 0, $23 = 0, $conv56 = 0, $xpenalty58 = 0, $24 = 0, $conv59 = 0, $mul60 = 0, $add61 = 0, $cross_4 = 0, $inc64 = 0, $arrayidx32 = 0, $25 = 0, $tobool33 = 0, $cross_0_lcssa = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $l;
+ $l = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$l >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$l + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($dir | 0) > 0;
+ $list = $l | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool28 = ($1 | 0) == 0;
+ if ($tobool28) {
+ $cross_0_lcssa = 0;
+ label = 16;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$list >> 2] | 0;
+ $cross_029 = 0;
+ $i_030 = 0;
+ $4 = $1;
+ label = 5;
+ break;
+ case 4:
+ $arrayidx = $2 + ($add << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ $cross_0_lcssa = $cross_0_be;
+ label = 16;
+ break;
+ } else {
+ $cross_029 = $cross_0_be;
+ $i_030 = $add;
+ $4 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $add = $i_030 + 1 | 0;
+ $arrayidx523 = $2 + ($add << 2) | 0;
+ $5 = HEAP32[$arrayidx523 >> 2] | 0;
+ $tobool624 = ($5 | 0) == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ if ($tobool624) {
+ $cross_0_be = $cross_029;
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $head8 = $4 + 12 | 0;
+ $6 = HEAP32[$head8 >> 2] | 0;
+ $order10 = $6 + 240 | 0;
+ $7 = HEAP32[$order10 >> 2] | 0;
+ $x15 = $4 + 32 | 0;
+ $8 = +HEAPF64[$x15 >> 3];
+ $xpenalty = $4 + 170 | 0;
+ $j_025 = $add;
+ $cross_126 = $cross_029;
+ $12 = $5;
+ label = 10;
+ break;
+ case 8:
+ if ($tobool624) {
+ $cross_0_be = $cross_029;
+ label = 4;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $tail37 = $4 + 16 | 0;
+ $9 = HEAP32[$tail37 >> 2] | 0;
+ $order39 = $9 + 240 | 0;
+ $10 = HEAP32[$order39 >> 2] | 0;
+ $x48 = $4 + 72 | 0;
+ $11 = +HEAPF64[$x48 >> 3];
+ $xpenalty55 = $4 + 170 | 0;
+ $j_120 = $add;
+ $cross_321 = $cross_029;
+ $19 = $5;
+ label = 13;
+ break;
+ case 10:
+ $head = $12 + 12 | 0;
+ $13 = HEAP32[$head >> 2] | 0;
+ $order = $13 + 240 | 0;
+ $14 = HEAP32[$order >> 2] | 0;
+ $sub = $14 - $7 | 0;
+ $conv = +($sub | 0);
+ $x = $12 + 32 | 0;
+ $15 = +HEAPF64[$x >> 3];
+ $sub16 = $15 - $8;
+ $mul = $conv * $sub16;
+ $cmp17 = $mul < 0.0;
+ if ($cmp17) {
+ label = 11;
+ break;
+ } else {
+ $cross_2 = $cross_126;
+ label = 12;
+ break;
+ }
+ case 11:
+ $16 = HEAP16[$xpenalty >> 1] | 0;
+ $conv21 = $16 << 16 >> 16;
+ $xpenalty23 = $12 + 170 | 0;
+ $17 = HEAP16[$xpenalty23 >> 1] | 0;
+ $conv24 = $17 << 16 >> 16;
+ $mul25 = Math_imul($conv24, $conv21);
+ $add26 = $mul25 + $cross_126 | 0;
+ $cross_2 = $add26;
+ label = 12;
+ break;
+ case 12:
+ $inc = $j_025 + 1 | 0;
+ $arrayidx5 = $2 + ($inc << 2) | 0;
+ $18 = HEAP32[$arrayidx5 >> 2] | 0;
+ $tobool6 = ($18 | 0) == 0;
+ if ($tobool6) {
+ $cross_0_be = $cross_2;
+ label = 4;
+ break;
+ } else {
+ $j_025 = $inc;
+ $cross_126 = $cross_2;
+ $12 = $18;
+ label = 10;
+ break;
+ }
+ case 13:
+ $tail = $19 + 16 | 0;
+ $20 = HEAP32[$tail >> 2] | 0;
+ $order36 = $20 + 240 | 0;
+ $21 = HEAP32[$order36 >> 2] | 0;
+ $sub40 = $21 - $10 | 0;
+ $conv41 = +($sub40 | 0);
+ $x44 = $19 + 72 | 0;
+ $22 = +HEAPF64[$x44 >> 3];
+ $sub49 = $22 - $11;
+ $mul50 = $conv41 * $sub49;
+ $cmp51 = $mul50 < 0.0;
+ if ($cmp51) {
+ label = 14;
+ break;
+ } else {
+ $cross_4 = $cross_321;
+ label = 15;
+ break;
+ }
+ case 14:
+ $23 = HEAP16[$xpenalty55 >> 1] | 0;
+ $conv56 = $23 << 16 >> 16;
+ $xpenalty58 = $19 + 170 | 0;
+ $24 = HEAP16[$xpenalty58 >> 1] | 0;
+ $conv59 = $24 << 16 >> 16;
+ $mul60 = Math_imul($conv59, $conv56);
+ $add61 = $mul60 + $cross_321 | 0;
+ $cross_4 = $add61;
+ label = 15;
+ break;
+ case 15:
+ $inc64 = $j_120 + 1 | 0;
+ $arrayidx32 = $2 + ($inc64 << 2) | 0;
+ $25 = HEAP32[$arrayidx32 >> 2] | 0;
+ $tobool33 = ($25 | 0) == 0;
+ if ($tobool33) {
+ $cross_0_be = $cross_4;
+ label = 4;
+ break;
+ } else {
+ $j_120 = $inc64;
+ $cross_321 = $cross_4;
+ $19 = $25;
+ label = 13;
+ break;
+ }
+ case 16:
+ STACKTOP = __stackBase__;
+ return $cross_0_lcssa | 0;
+ }
+ return 0;
+}
+function _left2right($g, $v, $w) {
+ $g = $g | 0;
+ $v = $v | 0;
+ $w = $w | 0;
+ var $_b = 0, $clust = 0, $0 = 0, $clust3 = 0, $1 = 0, $cmp4 = 0, $cmp4_not = 0, $tobool = 0, $or_cond = 0, $tobool11 = 0, $or_cond15 = 0, $ranktype = 0, $2 = 0, $cmp15 = 0, $node_type = 0, $3 = 0, $cmp20 = 0, $ranktype24 = 0, $4 = 0, $cmp26 = 0, $node_type30 = 0, $5 = 0, $cmp32 = 0, $rank = 0, $6 = 0, $rank48 = 0, $7 = 0, $flat = 0, $8 = 0, $cmp49 = 0, $rankdir = 0, $9 = 0, $and54 = 0, $tobool55 = 0, $w_v = 0, $v_w = 0, $low = 0, $10 = 0, $ncols = 0, $11 = 0, $mul = 0, $low60 = 0, $12 = 0, $add = 0, $data = 0, $13 = 0, $arrayidx61 = 0, $14 = 0, $conv62 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $_b = HEAP8[166152] | 0;
+ $clust = $v + 216 | 0;
+ $0 = HEAP32[$clust >> 2] | 0;
+ $clust3 = $w + 216 | 0;
+ $1 = HEAP32[$clust3 >> 2] | 0;
+ $cmp4 = ($0 | 0) != ($1 | 0);
+ if ($_b) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp4_not = $cmp4 ^ 1;
+ $tobool = ($0 | 0) == 0;
+ $or_cond = $tobool | $cmp4_not;
+ $tobool11 = ($1 | 0) == 0;
+ $or_cond15 = $or_cond | $tobool11;
+ if ($or_cond15) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $ranktype = $v + 165 | 0;
+ $2 = HEAP8[$ranktype] | 0;
+ $cmp15 = $2 << 24 >> 24 == 7;
+ if ($cmp15) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $node_type = $v + 162 | 0;
+ $3 = HEAP8[$node_type] | 0;
+ $cmp20 = $3 << 24 >> 24 == 1;
+ if ($cmp20) {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $ranktype24 = $w + 165 | 0;
+ $4 = HEAP8[$ranktype24] | 0;
+ $cmp26 = $4 << 24 >> 24 == 7;
+ if ($cmp26) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $node_type30 = $w + 162 | 0;
+ $5 = HEAP8[$node_type30] | 0;
+ $cmp32 = $5 << 24 >> 24 == 1;
+ if ($cmp32) {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $retval_0 = 1;
+ label = 12;
+ break;
+ case 9:
+ if ($cmp4) {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $rank = $v + 236 | 0;
+ $6 = HEAP32[$rank >> 2] | 0;
+ $rank48 = $g + 224 | 0;
+ $7 = HEAP32[$rank48 >> 2] | 0;
+ $flat = $7 + ($6 * 44 & -1) + 40 | 0;
+ $8 = HEAP32[$flat >> 2] | 0;
+ $cmp49 = ($8 | 0) == 0;
+ if ($cmp49) {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $rankdir = $g + 156 | 0;
+ $9 = HEAP32[$rankdir >> 2] | 0;
+ $and54 = $9 & 1;
+ $tobool55 = ($and54 | 0) == 0;
+ $w_v = $tobool55 ? $w : $v;
+ $v_w = $tobool55 ? $v : $w;
+ $low = $v_w + 284 | 0;
+ $10 = HEAP32[$low >> 2] | 0;
+ $ncols = $8 + 4 | 0;
+ $11 = HEAP32[$ncols >> 2] | 0;
+ $mul = Math_imul($11, $10);
+ $low60 = $w_v + 284 | 0;
+ $12 = HEAP32[$low60 >> 2] | 0;
+ $add = $mul + $12 | 0;
+ $data = $8 + 8 | 0;
+ $13 = HEAP32[$data >> 2] | 0;
+ $arrayidx61 = $13 + $add | 0;
+ $14 = HEAP8[$arrayidx61] | 0;
+ $conv62 = $14 << 24 >> 24;
+ $retval_0 = $conv62;
+ label = 12;
+ break;
+ case 12:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _in_cross($v, $w) {
+ $v = $v | 0;
+ $w = $w | 0;
+ var $list = 0, $0 = 0, $1 = 0, $tobool14 = 0, $list5 = 0, $2 = 0, $3 = 0, $tobool711 = 0, $4 = 0, $e2_016 = 0, $cross_015 = 0, $xpenalty = 0, $5 = 0, $conv = 0, $tail = 0, $6 = 0, $order = 0, $7 = 0, $8 = 0, $e1_013 = 0, $cross_112 = 0, $tail9 = 0, $9 = 0, $order11 = 0, $10 = 0, $sub = 0, $cmp = 0, $cmp13 = 0, $x = 0, $11 = 0.0, $12 = 0, $x19 = 0, $13 = 0.0, $cmp20 = 0, $14 = 0, $xpenalty23 = 0, $15 = 0, $conv24 = 0, $mul = 0, $add = 0, $cross_2 = 0, $incdec_ptr = 0, $16 = 0, $tobool7 = 0, $cross_1_lcssa = 0, $incdec_ptr26 = 0, $17 = 0, $tobool = 0, $cross_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $w + 176 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool14 = ($1 | 0) == 0;
+ if ($tobool14) {
+ $cross_0_lcssa = 0;
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $list5 = $v + 176 | 0;
+ $2 = HEAP32[$list5 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool711 = ($3 | 0) == 0;
+ $cross_015 = 0;
+ $e2_016 = $0;
+ $4 = $1;
+ label = 4;
+ break;
+ case 4:
+ $xpenalty = $4 + 170 | 0;
+ $5 = HEAP16[$xpenalty >> 1] | 0;
+ $conv = $5 << 16 >> 16;
+ $tail = $4 + 16 | 0;
+ $6 = HEAP32[$tail >> 2] | 0;
+ $order = $6 + 240 | 0;
+ $7 = HEAP32[$order >> 2] | 0;
+ if ($tobool711) {
+ $cross_1_lcssa = $cross_015;
+ label = 10;
+ break;
+ } else {
+ $cross_112 = $cross_015;
+ $e1_013 = $2;
+ $8 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $tail9 = $8 + 16 | 0;
+ $9 = HEAP32[$tail9 >> 2] | 0;
+ $order11 = $9 + 240 | 0;
+ $10 = HEAP32[$order11 >> 2] | 0;
+ $sub = $10 - $7 | 0;
+ $cmp = ($sub | 0) > 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp13 = ($10 | 0) == ($7 | 0);
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ $cross_2 = $cross_112;
+ label = 9;
+ break;
+ }
+ case 7:
+ $x = $8 + 32 | 0;
+ $11 = +HEAPF64[$x >> 3];
+ $12 = HEAP32[$e2_016 >> 2] | 0;
+ $x19 = $12 + 32 | 0;
+ $13 = +HEAPF64[$x19 >> 3];
+ $cmp20 = $11 > $13;
+ if ($cmp20) {
+ label = 8;
+ break;
+ } else {
+ $cross_2 = $cross_112;
+ label = 9;
+ break;
+ }
+ case 8:
+ $14 = HEAP32[$e1_013 >> 2] | 0;
+ $xpenalty23 = $14 + 170 | 0;
+ $15 = HEAP16[$xpenalty23 >> 1] | 0;
+ $conv24 = $15 << 16 >> 16;
+ $mul = Math_imul($conv24, $conv);
+ $add = $mul + $cross_112 | 0;
+ $cross_2 = $add;
+ label = 9;
+ break;
+ case 9:
+ $incdec_ptr = $e1_013 + 4 | 0;
+ $16 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool7 = ($16 | 0) == 0;
+ if ($tobool7) {
+ $cross_1_lcssa = $cross_2;
+ label = 10;
+ break;
+ } else {
+ $cross_112 = $cross_2;
+ $e1_013 = $incdec_ptr;
+ $8 = $16;
+ label = 5;
+ break;
+ }
+ case 10:
+ $incdec_ptr26 = $e2_016 + 4 | 0;
+ $17 = HEAP32[$incdec_ptr26 >> 2] | 0;
+ $tobool = ($17 | 0) == 0;
+ if ($tobool) {
+ $cross_0_lcssa = $cross_1_lcssa;
+ label = 11;
+ break;
+ } else {
+ $cross_015 = $cross_1_lcssa;
+ $e2_016 = $incdec_ptr26;
+ $4 = $17;
+ label = 4;
+ break;
+ }
+ case 11:
+ return $cross_0_lcssa | 0;
+ }
+ return 0;
+}
+function _out_cross($v, $w) {
+ $v = $v | 0;
+ $w = $w | 0;
+ var $list = 0, $0 = 0, $1 = 0, $tobool14 = 0, $list5 = 0, $2 = 0, $3 = 0, $tobool711 = 0, $4 = 0, $e2_016 = 0, $cross_015 = 0, $xpenalty = 0, $5 = 0, $conv = 0, $head = 0, $6 = 0, $order = 0, $7 = 0, $8 = 0, $e1_013 = 0, $cross_112 = 0, $head9 = 0, $9 = 0, $order11 = 0, $10 = 0, $sub = 0, $cmp = 0, $cmp13 = 0, $x = 0, $11 = 0.0, $12 = 0, $x19 = 0, $13 = 0.0, $cmp20 = 0, $14 = 0, $xpenalty23 = 0, $15 = 0, $conv24 = 0, $mul = 0, $add = 0, $cross_2 = 0, $incdec_ptr = 0, $16 = 0, $tobool7 = 0, $cross_1_lcssa = 0, $incdec_ptr26 = 0, $17 = 0, $tobool = 0, $cross_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $list = $w + 184 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool14 = ($1 | 0) == 0;
+ if ($tobool14) {
+ $cross_0_lcssa = 0;
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $list5 = $v + 184 | 0;
+ $2 = HEAP32[$list5 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool711 = ($3 | 0) == 0;
+ $cross_015 = 0;
+ $e2_016 = $0;
+ $4 = $1;
+ label = 4;
+ break;
+ case 4:
+ $xpenalty = $4 + 170 | 0;
+ $5 = HEAP16[$xpenalty >> 1] | 0;
+ $conv = $5 << 16 >> 16;
+ $head = $4 + 12 | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ $order = $6 + 240 | 0;
+ $7 = HEAP32[$order >> 2] | 0;
+ if ($tobool711) {
+ $cross_1_lcssa = $cross_015;
+ label = 10;
+ break;
+ } else {
+ $cross_112 = $cross_015;
+ $e1_013 = $2;
+ $8 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $head9 = $8 + 12 | 0;
+ $9 = HEAP32[$head9 >> 2] | 0;
+ $order11 = $9 + 240 | 0;
+ $10 = HEAP32[$order11 >> 2] | 0;
+ $sub = $10 - $7 | 0;
+ $cmp = ($sub | 0) > 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp13 = ($10 | 0) == ($7 | 0);
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ $cross_2 = $cross_112;
+ label = 9;
+ break;
+ }
+ case 7:
+ $x = $8 + 72 | 0;
+ $11 = +HEAPF64[$x >> 3];
+ $12 = HEAP32[$e2_016 >> 2] | 0;
+ $x19 = $12 + 72 | 0;
+ $13 = +HEAPF64[$x19 >> 3];
+ $cmp20 = $11 > $13;
+ if ($cmp20) {
+ label = 8;
+ break;
+ } else {
+ $cross_2 = $cross_112;
+ label = 9;
+ break;
+ }
+ case 8:
+ $14 = HEAP32[$e1_013 >> 2] | 0;
+ $xpenalty23 = $14 + 170 | 0;
+ $15 = HEAP16[$xpenalty23 >> 1] | 0;
+ $conv24 = $15 << 16 >> 16;
+ $mul = Math_imul($conv24, $conv);
+ $add = $mul + $cross_112 | 0;
+ $cross_2 = $add;
+ label = 9;
+ break;
+ case 9:
+ $incdec_ptr = $e1_013 + 4 | 0;
+ $16 = HEAP32[$incdec_ptr >> 2] | 0;
+ $tobool7 = ($16 | 0) == 0;
+ if ($tobool7) {
+ $cross_1_lcssa = $cross_2;
+ label = 10;
+ break;
+ } else {
+ $cross_112 = $cross_2;
+ $e1_013 = $incdec_ptr;
+ $8 = $16;
+ label = 5;
+ break;
+ }
+ case 10:
+ $incdec_ptr26 = $e2_016 + 4 | 0;
+ $17 = HEAP32[$incdec_ptr26 >> 2] | 0;
+ $tobool = ($17 | 0) == 0;
+ if ($tobool) {
+ $cross_0_lcssa = $cross_1_lcssa;
+ label = 11;
+ break;
+ } else {
+ $cross_015 = $cross_1_lcssa;
+ $e2_016 = $incdec_ptr26;
+ $4 = $17;
+ label = 4;
+ break;
+ }
+ case 11:
+ return $cross_0_lcssa | 0;
+ }
+ return 0;
+}
+function _rcross($g, $r) {
+ $g = $g | 0;
+ $r = $r | 0;
+ var $rank = 0, $0 = 0, $v1 = 0, $1 = 0, $2 = 0, $add = 0, $3 = 0, $rank3 = 0, $4 = 0, $n = 0, $5 = 0, $cmp = 0, $add10 = 0, $6 = 0, $tobool = 0, $7 = 0, $mul = 0, $call = 0, $mul11 = 0, $call12 = 0, $call_sink = 0, $8 = 0, $9 = 0, $n1777 = 0, $10 = 0, $cmp1878 = 0, $11 = 0, $n2471 = 0, $12 = 0, $cmp2572 = 0, $i_079 = 0, $13 = 0, $arrayidx19 = 0, $inc = 0, $14 = 0, $n17 = 0, $15 = 0, $cmp18 = 0, $cross_0_lcssa = 0, $16 = 0, $n8149 = 0, $17 = 0, $cmp8250 = 0, $18 = 0, $n81 = 0, $19 = 0, $top_075 = 0, $max_074 = 0, $cross_073 = 0, $cmp27 = 0, $arrayidx30 = 0, $20 = 0, $list59 = 0, $21 = 0, $22 = 0, $tobool3361 = 0, $23 = 0, $list = 0, $24 = 0, $25 = 0, $26 = 0, $i_163 = 0, $cross_162 = 0, $head = 0, $27 = 0, $order = 0, $28 = 0, $k_054 = 0, $cmp3855 = 0, $xpenalty = 0, $29 = 0, $conv = 0, $k_057 = 0, $cross_256 = 0, $arrayidx40 = 0, $30 = 0, $mul42 = 0, $add43 = 0, $k_0 = 0, $cmp38 = 0, $cross_2_lcssa = 0, $inc48 = 0, $arrayidx32 = 0, $31 = 0, $tobool33 = 0, $cross_3 = 0, $arrayidx52 = 0, $32 = 0, $list5565 = 0, $33 = 0, $34 = 0, $tobool5767 = 0, $35 = 0, $i_269 = 0, $max_168 = 0, $head59 = 0, $36 = 0, $order61 = 0, $37 = 0, $cmp62 = 0, $_max_1 = 0, $xpenalty67 = 0, $38 = 0, $conv68 = 0, $39 = 0, $arrayidx69 = 0, $40 = 0, $add70 = 0, $inc72 = 0, $41 = 0, $list55 = 0, $42 = 0, $arrayidx56 = 0, $43 = 0, $tobool57 = 0, $max_1_lcssa = 0, $inc75 = 0, $44 = 0, $n24 = 0, $45 = 0, $cmp25 = 0, $cross_4_lcssa = 0, $46 = 0, $n10645 = 0, $47 = 0, $cmp10746 = 0, $48 = 0, $n106 = 0, $49 = 0, $50 = 0, $top_152 = 0, $cross_451 = 0, $v88 = 0, $51 = 0, $arrayidx89 = 0, $52 = 0, $has_port = 0, $53 = 0, $tobool91 = 0, $out94 = 0, $call95 = 0, $add96 = 0, $cross_5 = 0, $inc99 = 0, $cmp82 = 0, $54 = 0, $bot_048 = 0, $cross_647 = 0, $v114 = 0, $55 = 0, $arrayidx115 = 0, $56 = 0, $has_port117 = 0, $57 = 0, $tobool118 = 0, $in = 0, $call121 = 0, $add122 = 0, $cross_7 = 0, $inc125 = 0, $cmp107 = 0, $cross_6_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $g + 224 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $v1 = $0 + ($r * 44 & -1) + 4 | 0;
+ $1 = HEAP32[$v1 >> 2] | 0;
+ $2 = HEAP32[1166] | 0;
+ $add = $r + 1 | 0;
+ $3 = HEAP32[41526] | 0;
+ $rank3 = $3 + 224 | 0;
+ $4 = HEAP32[$rank3 >> 2] | 0;
+ $n = $4 + ($add * 44 & -1) | 0;
+ $5 = HEAP32[$n >> 2] | 0;
+ $cmp = ($2 | 0) > ($5 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add10 = $5 + 1 | 0;
+ HEAP32[1166] = $add10;
+ $6 = HEAP32[1164] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $7 = $6;
+ $mul = $add10 << 2;
+ $call = _grealloc($7, $mul) | 0;
+ $call_sink = $call;
+ label = 6;
+ break;
+ case 5:
+ $mul11 = $add10 << 2;
+ $call12 = _gmalloc($mul11) | 0;
+ $call_sink = $call12;
+ label = 6;
+ break;
+ case 6:
+ $8 = $call_sink;
+ HEAP32[1164] = $8;
+ label = 7;
+ break;
+ case 7:
+ $9 = HEAP32[$rank >> 2] | 0;
+ $n1777 = $9 + ($add * 44 & -1) | 0;
+ $10 = HEAP32[$n1777 >> 2] | 0;
+ $cmp1878 = ($10 | 0) > 0;
+ if ($cmp1878) {
+ $i_079 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $11 = HEAP32[$rank >> 2] | 0;
+ $n2471 = $11 + ($r * 44 & -1) | 0;
+ $12 = HEAP32[$n2471 >> 2] | 0;
+ $cmp2572 = ($12 | 0) > 0;
+ if ($cmp2572) {
+ $cross_073 = 0;
+ $max_074 = 0;
+ $top_075 = 0;
+ label = 12;
+ break;
+ } else {
+ $cross_0_lcssa = 0;
+ label = 10;
+ break;
+ }
+ case 9:
+ $13 = HEAP32[1164] | 0;
+ $arrayidx19 = $13 + ($i_079 << 2) | 0;
+ HEAP32[$arrayidx19 >> 2] = 0;
+ $inc = $i_079 + 1 | 0;
+ $14 = HEAP32[$rank >> 2] | 0;
+ $n17 = $14 + ($add * 44 & -1) | 0;
+ $15 = HEAP32[$n17 >> 2] | 0;
+ $cmp18 = ($inc | 0) < ($15 | 0);
+ if ($cmp18) {
+ $i_079 = $inc;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 10:
+ $16 = HEAP32[$rank >> 2] | 0;
+ $n8149 = $16 + ($r * 44 & -1) | 0;
+ $17 = HEAP32[$n8149 >> 2] | 0;
+ $cmp8250 = ($17 | 0) > 0;
+ if ($cmp8250) {
+ label = 11;
+ break;
+ } else {
+ $cross_4_lcssa = $cross_0_lcssa;
+ label = 22;
+ break;
+ }
+ case 11:
+ $18 = HEAP32[$rank >> 2] | 0;
+ $n81 = $18 + ($r * 44 & -1) | 0;
+ $19 = HEAP32[$n81 >> 2] | 0;
+ $cross_451 = $cross_0_lcssa;
+ $top_152 = 0;
+ $50 = $16;
+ label = 24;
+ break;
+ case 12:
+ $cmp27 = ($max_074 | 0) > 0;
+ if ($cmp27) {
+ label = 13;
+ break;
+ } else {
+ $cross_3 = $cross_073;
+ label = 19;
+ break;
+ }
+ case 13:
+ $arrayidx30 = $1 + ($top_075 << 2) | 0;
+ $20 = HEAP32[$arrayidx30 >> 2] | 0;
+ $list59 = $20 + 184 | 0;
+ $21 = HEAP32[$list59 >> 2] | 0;
+ $22 = HEAP32[$21 >> 2] | 0;
+ $tobool3361 = ($22 | 0) == 0;
+ if ($tobool3361) {
+ $cross_3 = $cross_073;
+ label = 19;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $23 = HEAP32[$arrayidx30 >> 2] | 0;
+ $list = $23 + 184 | 0;
+ $24 = HEAP32[$list >> 2] | 0;
+ $25 = HEAP32[1164] | 0;
+ $cross_162 = $cross_073;
+ $i_163 = 0;
+ $26 = $22;
+ label = 15;
+ break;
+ case 15:
+ $head = $26 + 12 | 0;
+ $27 = HEAP32[$head >> 2] | 0;
+ $order = $27 + 240 | 0;
+ $28 = HEAP32[$order >> 2] | 0;
+ $k_054 = $28 + 1 | 0;
+ $cmp3855 = ($k_054 | 0) > ($max_074 | 0);
+ if ($cmp3855) {
+ $cross_2_lcssa = $cross_162;
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $xpenalty = $26 + 170 | 0;
+ $29 = HEAP16[$xpenalty >> 1] | 0;
+ $conv = $29 << 16 >> 16;
+ $cross_256 = $cross_162;
+ $k_057 = $k_054;
+ label = 17;
+ break;
+ case 17:
+ $arrayidx40 = $25 + ($k_057 << 2) | 0;
+ $30 = HEAP32[$arrayidx40 >> 2] | 0;
+ $mul42 = Math_imul($conv, $30);
+ $add43 = $mul42 + $cross_256 | 0;
+ $k_0 = $k_057 + 1 | 0;
+ $cmp38 = ($k_0 | 0) > ($max_074 | 0);
+ if ($cmp38) {
+ $cross_2_lcssa = $add43;
+ label = 18;
+ break;
+ } else {
+ $cross_256 = $add43;
+ $k_057 = $k_0;
+ label = 17;
+ break;
+ }
+ case 18:
+ $inc48 = $i_163 + 1 | 0;
+ $arrayidx32 = $24 + ($inc48 << 2) | 0;
+ $31 = HEAP32[$arrayidx32 >> 2] | 0;
+ $tobool33 = ($31 | 0) == 0;
+ if ($tobool33) {
+ $cross_3 = $cross_2_lcssa;
+ label = 19;
+ break;
+ } else {
+ $cross_162 = $cross_2_lcssa;
+ $i_163 = $inc48;
+ $26 = $31;
+ label = 15;
+ break;
+ }
+ case 19:
+ $arrayidx52 = $1 + ($top_075 << 2) | 0;
+ $32 = HEAP32[$arrayidx52 >> 2] | 0;
+ $list5565 = $32 + 184 | 0;
+ $33 = HEAP32[$list5565 >> 2] | 0;
+ $34 = HEAP32[$33 >> 2] | 0;
+ $tobool5767 = ($34 | 0) == 0;
+ if ($tobool5767) {
+ $max_1_lcssa = $max_074;
+ label = 21;
+ break;
+ } else {
+ $max_168 = $max_074;
+ $i_269 = 0;
+ $35 = $34;
+ label = 20;
+ break;
+ }
+ case 20:
+ $head59 = $35 + 12 | 0;
+ $36 = HEAP32[$head59 >> 2] | 0;
+ $order61 = $36 + 240 | 0;
+ $37 = HEAP32[$order61 >> 2] | 0;
+ $cmp62 = ($37 | 0) > ($max_168 | 0);
+ $_max_1 = $cmp62 ? $37 : $max_168;
+ $xpenalty67 = $35 + 170 | 0;
+ $38 = HEAP16[$xpenalty67 >> 1] | 0;
+ $conv68 = $38 << 16 >> 16;
+ $39 = HEAP32[1164] | 0;
+ $arrayidx69 = $39 + ($37 << 2) | 0;
+ $40 = HEAP32[$arrayidx69 >> 2] | 0;
+ $add70 = $40 + $conv68 | 0;
+ HEAP32[$arrayidx69 >> 2] = $add70;
+ $inc72 = $i_269 + 1 | 0;
+ $41 = HEAP32[$arrayidx52 >> 2] | 0;
+ $list55 = $41 + 184 | 0;
+ $42 = HEAP32[$list55 >> 2] | 0;
+ $arrayidx56 = $42 + ($inc72 << 2) | 0;
+ $43 = HEAP32[$arrayidx56 >> 2] | 0;
+ $tobool57 = ($43 | 0) == 0;
+ if ($tobool57) {
+ $max_1_lcssa = $_max_1;
+ label = 21;
+ break;
+ } else {
+ $max_168 = $_max_1;
+ $i_269 = $inc72;
+ $35 = $43;
+ label = 20;
+ break;
+ }
+ case 21:
+ $inc75 = $top_075 + 1 | 0;
+ $44 = HEAP32[$rank >> 2] | 0;
+ $n24 = $44 + ($r * 44 & -1) | 0;
+ $45 = HEAP32[$n24 >> 2] | 0;
+ $cmp25 = ($inc75 | 0) < ($45 | 0);
+ if ($cmp25) {
+ $cross_073 = $cross_3;
+ $max_074 = $max_1_lcssa;
+ $top_075 = $inc75;
+ label = 12;
+ break;
+ } else {
+ $cross_0_lcssa = $cross_3;
+ label = 10;
+ break;
+ }
+ case 22:
+ $46 = HEAP32[$rank >> 2] | 0;
+ $n10645 = $46 + ($add * 44 & -1) | 0;
+ $47 = HEAP32[$n10645 >> 2] | 0;
+ $cmp10746 = ($47 | 0) > 0;
+ if ($cmp10746) {
+ label = 23;
+ break;
+ } else {
+ $cross_6_lcssa = $cross_4_lcssa;
+ label = 30;
+ break;
+ }
+ case 23:
+ $48 = HEAP32[$rank >> 2] | 0;
+ $n106 = $48 + ($add * 44 & -1) | 0;
+ $49 = HEAP32[$n106 >> 2] | 0;
+ $cross_647 = $cross_4_lcssa;
+ $bot_048 = 0;
+ $54 = $46;
+ label = 27;
+ break;
+ case 24:
+ $v88 = $50 + ($r * 44 & -1) + 4 | 0;
+ $51 = HEAP32[$v88 >> 2] | 0;
+ $arrayidx89 = $51 + ($top_152 << 2) | 0;
+ $52 = HEAP32[$arrayidx89 >> 2] | 0;
+ $has_port = $52 + 161 | 0;
+ $53 = HEAP8[$has_port] | 0;
+ $tobool91 = $53 << 24 >> 24 == 0;
+ if ($tobool91) {
+ $cross_5 = $cross_451;
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $out94 = $52 + 184 | 0;
+ $call95 = _local_cross($out94, 1) | 0;
+ $add96 = $call95 + $cross_451 | 0;
+ $cross_5 = $add96;
+ label = 26;
+ break;
+ case 26:
+ $inc99 = $top_152 + 1 | 0;
+ $cmp82 = ($inc99 | 0) < ($19 | 0);
+ if ($cmp82) {
+ $cross_451 = $cross_5;
+ $top_152 = $inc99;
+ $50 = $18;
+ label = 24;
+ break;
+ } else {
+ $cross_4_lcssa = $cross_5;
+ label = 22;
+ break;
+ }
+ case 27:
+ $v114 = $54 + ($add * 44 & -1) + 4 | 0;
+ $55 = HEAP32[$v114 >> 2] | 0;
+ $arrayidx115 = $55 + ($bot_048 << 2) | 0;
+ $56 = HEAP32[$arrayidx115 >> 2] | 0;
+ $has_port117 = $56 + 161 | 0;
+ $57 = HEAP8[$has_port117] | 0;
+ $tobool118 = $57 << 24 >> 24 == 0;
+ if ($tobool118) {
+ $cross_7 = $cross_647;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $in = $56 + 176 | 0;
+ $call121 = _local_cross($in, -1) | 0;
+ $add122 = $call121 + $cross_647 | 0;
+ $cross_7 = $add122;
+ label = 29;
+ break;
+ case 29:
+ $inc125 = $bot_048 + 1 | 0;
+ $cmp107 = ($inc125 | 0) < ($49 | 0);
+ if ($cmp107) {
+ $cross_647 = $cross_7;
+ $bot_048 = $inc125;
+ $54 = $48;
+ label = 27;
+ break;
+ } else {
+ $cross_6_lcssa = $cross_7;
+ label = 30;
+ break;
+ }
+ case 30:
+ return $cross_6_lcssa | 0;
+ }
+ return 0;
+}
+function _virtual_weight($e) {
+ $e = $e | 0;
+ var $call = 0, $conv = 0.0, $weight = 0;
+ $call = _endpoint_class(HEAP32[$e + 12 >> 2] | 0) | 0;
+ $conv = +(HEAP32[3304 + ((_endpoint_class(HEAP32[$e + 16 >> 2] | 0) | 0) * 12 & -1) + ($call << 2) >> 2] | 0);
+ $weight = $e + 172 | 0;
+ HEAPF32[$weight >> 2] = +HEAPF32[$weight >> 2] * $conv;
+ return;
+}
+function _mincross_options($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $call1 = 0.0, $cmp = 0, $1 = 0, $conv = 0.0, $mul = 0.0, $cmp2 = 0, $phitmp = 0, $cond = 0, $2 = 0, $conv7 = 0.0, $mul8 = 0.0, $cmp9 = 0, $phitmp5 = 0, $cond16 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[41630] = 8;
+ HEAP32[41634] = 24;
+ HEAPF64[20993] = .995;
+ $0 = $g | 0;
+ $call = _agget($0, 160176) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = +_atof($call);
+ $cmp = $call1 > 0.0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[41630] | 0;
+ $conv = +($1 | 0);
+ $mul = $call1 * $conv;
+ $cmp2 = $mul < 1.0;
+ if ($cmp2) {
+ $cond = 1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $phitmp = ~~$mul;
+ $cond = $phitmp;
+ label = 6;
+ break;
+ case 6:
+ HEAP32[41630] = $cond;
+ $2 = HEAP32[41634] | 0;
+ $conv7 = +($2 | 0);
+ $mul8 = $call1 * $conv7;
+ $cmp9 = $mul8 < 1.0;
+ if ($cmp9) {
+ $cond16 = 1;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $phitmp5 = ~~$mul8;
+ $cond16 = $phitmp5;
+ label = 8;
+ break;
+ case 8:
+ HEAP32[41634] = $cond16;
+ label = 9;
+ break;
+ case 9:
+ return;
+ }
+}
+function _ordered_edges($g) {
+ $g = $g | 0;
+ var $0 = 0, $tobool = 0, $1 = 0, $tobool1 = 0, $or_cond = 0, $2 = 0, $call = 0, $tobool2 = 0, $3 = 0, $cmp = 0, $call7 = 0, $tobool8 = 0, $_pr = 0, $4 = 0, $cmp12 = 0, $call15 = 0, $tobool16 = 0, $5 = 0, $tobool19 = 0, $call21 = 0, $meta_node = 0, $6 = 0, $graph = 0, $7 = 0, $8 = 0, $9 = 0, $call26 = 0, $tobool2715 = 0, $me_0_in16 = 0, $head = 0, $10 = 0, $11 = 0, $call28 = 0, $12 = 0, $call29 = 0, $tobool30 = 0, $13 = 0, $call33 = 0, $tobool27 = 0, $14 = 0, $tobool34 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41866] | 0;
+ $tobool = ($0 | 0) != 0;
+ $1 = HEAP32[41580] | 0;
+ $tobool1 = ($1 | 0) != 0;
+ $or_cond = $tobool | $tobool1;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 3:
+ $2 = $g | 0;
+ $call = _late_string($2, $0, 0) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 13;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP8[$call] | 0;
+ $cmp = $3 << 24 >> 24 == 111;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $4 = $3;
+ label = 8;
+ break;
+ }
+ case 5:
+ $call7 = _strcmp($call | 0, 101448) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ _do_ordering($g, 1);
+ label = 19;
+ break;
+ case 7:
+ $_pr = HEAP8[$call] | 0;
+ $4 = $_pr;
+ label = 8;
+ break;
+ case 8:
+ $cmp12 = $4 << 24 >> 24 == 105;
+ if ($cmp12) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $call15 = _strcmp($call | 0, 97144) | 0;
+ $tobool16 = ($call15 | 0) == 0;
+ if ($tobool16) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _do_ordering($g, 0);
+ label = 19;
+ break;
+ case 11:
+ $5 = HEAP8[$call] | 0;
+ $tobool19 = $5 << 24 >> 24 == 0;
+ if ($tobool19) {
+ label = 19;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call21 = _agerr(1, 93496, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call, tempInt) | 0) | 0;
+ label = 19;
+ break;
+ case 13:
+ $meta_node = $g + 36 | 0;
+ $6 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $6 + 20 | 0;
+ $7 = HEAP32[$graph >> 2] | 0;
+ $8 = $7;
+ $9 = $6;
+ $call26 = _agfstout($8, $9) | 0;
+ $tobool2715 = ($call26 | 0) == 0;
+ if ($tobool2715) {
+ label = 17;
+ break;
+ } else {
+ $me_0_in16 = $call26;
+ label = 14;
+ break;
+ }
+ case 14:
+ $head = $me_0_in16 + 12 | 0;
+ $10 = HEAP32[$head >> 2] | 0;
+ $11 = $10;
+ $call28 = _agusergraph($11) | 0;
+ $12 = $call28;
+ $call29 = _is_cluster($12) | 0;
+ $tobool30 = ($call29 | 0) == 0;
+ if ($tobool30) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $13 = $call28;
+ _ordered_edges($13);
+ label = 16;
+ break;
+ case 16:
+ $call33 = _agnxtout($8, $me_0_in16) | 0;
+ $tobool27 = ($call33 | 0) == 0;
+ if ($tobool27) {
+ label = 17;
+ break;
+ } else {
+ $me_0_in16 = $call33;
+ label = 14;
+ break;
+ }
+ case 17:
+ $14 = HEAP32[41580] | 0;
+ $tobool34 = ($14 | 0) == 0;
+ if ($tobool34) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ _do_ordering_for_nodes($g);
+ label = 19;
+ break;
+ case 19:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _do_ordering($g, $outflag) {
+ $g = $g | 0;
+ $outflag = $outflag | 0;
+ var $0 = 0, $call = 0, $tobool5 = 0, $n_0_in6 = 0, $n_0 = 0, $call1 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool5 = ($call | 0) == 0;
+ if ($tobool5) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in6 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $n_0 = $n_0_in6;
+ _do_ordering_node($g, $n_0, $outflag);
+ $call1 = _agnxtnode($0, $n_0_in6) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_0_in6 = $call1;
+ label = 3;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _transpose_step($g, $r, $reverse) {
+ $g = $g | 0;
+ $r = $r | 0;
+ $reverse = $reverse | 0;
+ var $rank = 0, $0 = 0, $candidate = 0, $1 = 0, $n5360 = 0, $2 = 0, $sub5461 = 0, $cmp5562 = 0, $cmp18 = 0, $add25 = 0, $notrhs = 0, $minrank = 0, $sub56 = 0, $maxrank = 0, $3 = 0, $i_0_ph64 = 0, $rv_0_ph63 = 0, $4 = 0, $i_056 = 0, $v7 = 0, $5 = 0, $arrayidx8 = 0, $6 = 0, $add = 0, $arrayidx13 = 0, $7 = 0, $order = 0, $8 = 0, $order16 = 0, $9 = 0, $cmp17 = 0, $call = 0, $tobool = 0, $call20 = 0, $call22 = 0, $c1_0 = 0, $c0_0 = 0, $10 = 0, $n29 = 0, $11 = 0, $cmp30 = 0, $call32 = 0, $add33 = 0, $call34 = 0, $add35 = 0, $c1_1 = 0, $c0_1 = 0, $cmp37 = 0, $notlhs = 0, $or_cond_not = 0, $cmp41 = 0, $or_cond49 = 0, $12 = 0, $n = 0, $13 = 0, $sub = 0, $cmp = 0, $sub43 = 0, $add44 = 0, $14 = 0, $rank46 = 0, $15 = 0, $valid = 0, $16 = 0, $candidate51 = 0, $17 = 0, $conv = 0, $cmp53 = 0, $18 = 0, $rank58 = 0, $19 = 0, $valid60 = 0, $20 = 0, $candidate65 = 0, $21 = 0, $conv68 = 0, $cmp69 = 0, $22 = 0, $rank74 = 0, $23 = 0, $valid76 = 0, $24 = 0, $candidate81 = 0, $25 = 0, $n53 = 0, $26 = 0, $sub54 = 0, $cmp55 = 0, $rv_0_ph59 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $g + 224 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $candidate = $0 + ($r * 44 & -1) + 32 | 0;
+ HEAP8[$candidate] = 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $n5360 = $1 + ($r * 44 & -1) | 0;
+ $2 = HEAP32[$n5360 >> 2] | 0;
+ $sub5461 = $2 - 1 | 0;
+ $cmp5562 = ($sub5461 | 0) > 0;
+ if ($cmp5562) {
+ label = 3;
+ break;
+ } else {
+ $rv_0_ph59 = 0;
+ label = 20;
+ break;
+ }
+ case 3:
+ $cmp18 = ($r | 0) > 0;
+ $add25 = $r + 1 | 0;
+ $notrhs = ($reverse | 0) != 0;
+ $minrank = $g + 248 | 0;
+ $sub56 = $r - 1 | 0;
+ $maxrank = $g + 250 | 0;
+ $rv_0_ph63 = 0;
+ $i_0_ph64 = 0;
+ $3 = $1;
+ label = 4;
+ break;
+ case 4:
+ $i_056 = $i_0_ph64;
+ $4 = $3;
+ label = 5;
+ break;
+ case 5:
+ $v7 = $4 + ($r * 44 & -1) + 4 | 0;
+ $5 = HEAP32[$v7 >> 2] | 0;
+ $arrayidx8 = $5 + ($i_056 << 2) | 0;
+ $6 = HEAP32[$arrayidx8 >> 2] | 0;
+ $add = $i_056 + 1 | 0;
+ $arrayidx13 = $5 + ($add << 2) | 0;
+ $7 = HEAP32[$arrayidx13 >> 2] | 0;
+ $order = $6 + 240 | 0;
+ $8 = HEAP32[$order >> 2] | 0;
+ $order16 = $7 + 240 | 0;
+ $9 = HEAP32[$order16 >> 2] | 0;
+ $cmp17 = ($8 | 0) < ($9 | 0);
+ if ($cmp17) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ ___assert_func(119784, 523, 163768, 105480);
+ return 0;
+ case 7:
+ $call = _left2right($g, $6, $7) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 8:
+ if ($cmp18) {
+ label = 9;
+ break;
+ } else {
+ $c0_0 = 0;
+ $c1_0 = 0;
+ label = 10;
+ break;
+ }
+ case 9:
+ $call20 = _in_cross($6, $7) | 0;
+ $call22 = _in_cross($7, $6) | 0;
+ $c0_0 = $call20;
+ $c1_0 = $call22;
+ label = 10;
+ break;
+ case 10:
+ $10 = HEAP32[$rank >> 2] | 0;
+ $n29 = $10 + ($add25 * 44 & -1) | 0;
+ $11 = HEAP32[$n29 >> 2] | 0;
+ $cmp30 = ($11 | 0) > 0;
+ if ($cmp30) {
+ label = 11;
+ break;
+ } else {
+ $c0_1 = $c0_0;
+ $c1_1 = $c1_0;
+ label = 12;
+ break;
+ }
+ case 11:
+ $call32 = _out_cross($6, $7) | 0;
+ $add33 = $call32 + $c0_0 | 0;
+ $call34 = _out_cross($7, $6) | 0;
+ $add35 = $call34 + $c1_0 | 0;
+ $c0_1 = $add33;
+ $c1_1 = $add35;
+ label = 12;
+ break;
+ case 12:
+ $cmp37 = ($c1_1 | 0) < ($c0_1 | 0);
+ if ($cmp37) {
+ label = 15;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $notlhs = ($c0_1 | 0) > 0;
+ $or_cond_not = $notrhs & $notlhs;
+ $cmp41 = ($c1_1 | 0) == ($c0_1 | 0);
+ $or_cond49 = $or_cond_not & $cmp41;
+ if ($or_cond49) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $12 = HEAP32[$rank >> 2] | 0;
+ $n = $12 + ($r * 44 & -1) | 0;
+ $13 = HEAP32[$n >> 2] | 0;
+ $sub = $13 - 1 | 0;
+ $cmp = ($add | 0) < ($sub | 0);
+ if ($cmp) {
+ $i_056 = $add;
+ $4 = $12;
+ label = 5;
+ break;
+ } else {
+ $rv_0_ph59 = $rv_0_ph63;
+ label = 20;
+ break;
+ }
+ case 15:
+ _exchange($6, $7);
+ $sub43 = $c0_1 - $c1_1 | 0;
+ $add44 = $sub43 + $rv_0_ph63 | 0;
+ $14 = HEAP32[41526] | 0;
+ $rank46 = $14 + 224 | 0;
+ $15 = HEAP32[$rank46 >> 2] | 0;
+ $valid = $15 + ($r * 44 & -1) + 33 | 0;
+ HEAP8[$valid] = 0;
+ $16 = HEAP32[$rank >> 2] | 0;
+ $candidate51 = $16 + ($r * 44 & -1) + 32 | 0;
+ HEAP8[$candidate51] = 1;
+ $17 = HEAP16[$minrank >> 1] | 0;
+ $conv = $17 << 16 >> 16;
+ $cmp53 = ($conv | 0) < ($r | 0);
+ if ($cmp53) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $18 = HEAP32[41526] | 0;
+ $rank58 = $18 + 224 | 0;
+ $19 = HEAP32[$rank58 >> 2] | 0;
+ $valid60 = $19 + ($sub56 * 44 & -1) + 33 | 0;
+ HEAP8[$valid60] = 0;
+ $20 = HEAP32[$rank >> 2] | 0;
+ $candidate65 = $20 + ($sub56 * 44 & -1) + 32 | 0;
+ HEAP8[$candidate65] = 1;
+ label = 17;
+ break;
+ case 17:
+ $21 = HEAP16[$maxrank >> 1] | 0;
+ $conv68 = $21 << 16 >> 16;
+ $cmp69 = ($conv68 | 0) > ($r | 0);
+ if ($cmp69) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $22 = HEAP32[41526] | 0;
+ $rank74 = $22 + 224 | 0;
+ $23 = HEAP32[$rank74 >> 2] | 0;
+ $valid76 = $23 + ($add25 * 44 & -1) + 33 | 0;
+ HEAP8[$valid76] = 0;
+ $24 = HEAP32[$rank >> 2] | 0;
+ $candidate81 = $24 + ($add25 * 44 & -1) + 32 | 0;
+ HEAP8[$candidate81] = 1;
+ label = 19;
+ break;
+ case 19:
+ $25 = HEAP32[$rank >> 2] | 0;
+ $n53 = $25 + ($r * 44 & -1) | 0;
+ $26 = HEAP32[$n53 >> 2] | 0;
+ $sub54 = $26 - 1 | 0;
+ $cmp55 = ($add | 0) < ($sub54 | 0);
+ if ($cmp55) {
+ $rv_0_ph63 = $add44;
+ $i_0_ph64 = $add;
+ $3 = $25;
+ label = 4;
+ break;
+ } else {
+ $rv_0_ph59 = $add44;
+ label = 20;
+ break;
+ }
+ case 20:
+ return $rv_0_ph59 | 0;
+ }
+ return 0;
+}
+function _betweenclust($e) {
+ $e = $e | 0;
+ var $e_addr_0 = 0, $to_orig = 0, $0 = 0, $tobool = 0, $tail = 0, $1 = 0, $clust = 0, $2 = 0, $head = 0, $3 = 0, $clust5 = 0, $4 = 0, $cmp = 0, $conv = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $e_addr_0 = $e;
+ label = 3;
+ break;
+ case 3:
+ $to_orig = $e_addr_0 + 132 | 0;
+ $0 = HEAP32[$to_orig >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $e_addr_0 = $0;
+ label = 3;
+ break;
+ }
+ case 4:
+ $tail = $e_addr_0 + 16 | 0;
+ $1 = HEAP32[$tail >> 2] | 0;
+ $clust = $1 + 216 | 0;
+ $2 = HEAP32[$clust >> 2] | 0;
+ $head = $e_addr_0 + 12 | 0;
+ $3 = HEAP32[$head >> 2] | 0;
+ $clust5 = $3 + 216 | 0;
+ $4 = HEAP32[$clust5 >> 2] | 0;
+ $cmp = ($2 | 0) != ($4 | 0);
+ $conv = $cmp & 1;
+ return $conv | 0;
+ }
+ return 0;
+}
+function _edgeidcmpf($e0, $e1) {
+ $e0 = $e0 | 0;
+ $e1 = $e1 | 0;
+ return (HEAP32[(HEAP32[$e0 >> 2] | 0) + 20 >> 2] | 0) - (HEAP32[(HEAP32[$e1 >> 2] | 0) + 20 >> 2] | 0) | 0;
+}
+function _neighbor113($v, $dir) {
+ $v = $v | 0;
+ $dir = $dir | 0;
+ var $cmp = 0, $order = 0, $0 = 0, $cmp1 = 0, $sub = 0, $rank = 0, $1 = 0, $2 = 0, $rank7 = 0, $3 = 0, $v8 = 0, $4 = 0, $arrayidx9 = 0, $5 = 0, $add = 0, $rank13 = 0, $6 = 0, $7 = 0, $rank15 = 0, $8 = 0, $v17 = 0, $9 = 0, $arrayidx18 = 0, $10 = 0, $rv_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($dir | 0) < 0;
+ $order = $v + 240 | 0;
+ $0 = HEAP32[$order >> 2] | 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $cmp1 = ($0 | 0) > 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ $rv_0 = 0;
+ label = 6;
+ break;
+ }
+ case 4:
+ $sub = $0 - 1 | 0;
+ $rank = $v + 236 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $2 = HEAP32[41526] | 0;
+ $rank7 = $2 + 224 | 0;
+ $3 = HEAP32[$rank7 >> 2] | 0;
+ $v8 = $3 + ($1 * 44 & -1) + 4 | 0;
+ $4 = HEAP32[$v8 >> 2] | 0;
+ $arrayidx9 = $4 + ($sub << 2) | 0;
+ $5 = HEAP32[$arrayidx9 >> 2] | 0;
+ $rv_0 = $5;
+ label = 6;
+ break;
+ case 5:
+ $add = $0 + 1 | 0;
+ $rank13 = $v + 236 | 0;
+ $6 = HEAP32[$rank13 >> 2] | 0;
+ $7 = HEAP32[41526] | 0;
+ $rank15 = $7 + 224 | 0;
+ $8 = HEAP32[$rank15 >> 2] | 0;
+ $v17 = $8 + ($6 * 44 & -1) + 4 | 0;
+ $9 = HEAP32[$v17 >> 2] | 0;
+ $arrayidx18 = $9 + ($add << 2) | 0;
+ $10 = HEAP32[$arrayidx18 >> 2] | 0;
+ $rv_0 = $10;
+ label = 6;
+ break;
+ case 6:
+ return $rv_0 | 0;
+ }
+ return 0;
+}
+function _merge_components($g) {
+ $g = $g | 0;
+ var $comp = 0, $size = 0, $0 = 0, $cmp = 0, $1 = 0, $cmp515 = 0, $list = 0, $u_017 = 0, $c_016 = 0, $2 = 0, $arrayidx = 0, $3 = 0, $tobool = 0, $next = 0, $prev = 0, $v_0 = 0, $next13 = 0, $4 = 0, $tobool14 = 0, $inc = 0, $5 = 0, $cmp5 = 0, $list22 = 0, $6 = 0, $7 = 0, $nlist = 0, $8 = 0, $conv = 0, $minrank = 0, $9 = 0, $conv26 = 0, $maxrank = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $comp = $g + 228 | 0;
+ $size = $g + 232 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp = ($0 | 0) < 2;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[$size >> 2] | 0;
+ $cmp515 = ($1 | 0) > 0;
+ if ($cmp515) {
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 4:
+ $list = $comp | 0;
+ $c_016 = 0;
+ $u_017 = 0;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $2 + ($c_016 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($u_017 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $next = $u_017 + 168 | 0;
+ HEAP32[$next >> 2] = $3;
+ label = 7;
+ break;
+ case 7:
+ $prev = $3 + 172 | 0;
+ HEAP32[$prev >> 2] = $u_017;
+ $v_0 = $3;
+ label = 8;
+ break;
+ case 8:
+ $next13 = $v_0 + 168 | 0;
+ $4 = HEAP32[$next13 >> 2] | 0;
+ $tobool14 = ($4 | 0) == 0;
+ if ($tobool14) {
+ label = 9;
+ break;
+ } else {
+ $v_0 = $4;
+ label = 8;
+ break;
+ }
+ case 9:
+ $inc = $c_016 + 1 | 0;
+ $5 = HEAP32[$size >> 2] | 0;
+ $cmp5 = ($inc | 0) < ($5 | 0);
+ if ($cmp5) {
+ $c_016 = $inc;
+ $u_017 = $v_0;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ HEAP32[$size >> 2] = 1;
+ $list22 = $comp | 0;
+ $6 = HEAP32[$list22 >> 2] | 0;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $nlist = $g + 220 | 0;
+ HEAP32[$nlist >> 2] = $7;
+ $8 = HEAP32[41854] | 0;
+ $conv = $8 & 65535;
+ $minrank = $g + 248 | 0;
+ HEAP16[$minrank >> 1] = $conv;
+ $9 = HEAP32[41856] | 0;
+ $conv26 = $9 & 65535;
+ $maxrank = $g + 250 | 0;
+ HEAP16[$maxrank >> 1] = $conv26;
+ label = 11;
+ break;
+ case 11:
+ return;
+ }
+}
+function _save_best($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_04 = 0, $tobool5 = 0, $n_06 = 0, $order = 0, $0 = 0, $conv = 0.0, $x = 0, $next = 0, $n_0 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $n_04 = HEAP32[$nlist >> 2] | 0;
+ $tobool5 = ($n_04 | 0) == 0;
+ if ($tobool5) {
+ label = 4;
+ break;
+ } else {
+ $n_06 = $n_04;
+ label = 3;
+ break;
+ }
+ case 3:
+ $order = $n_06 + 240 | 0;
+ $0 = HEAP32[$order >> 2] | 0;
+ $conv = +($0 | 0);
+ $x = $n_06 + 32 | 0;
+ HEAPF64[$x >> 3] = $conv;
+ $next = $n_06 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_06 = $n_0;
+ label = 3;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _do_ordering_for_nodes($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool15 = 0, $n_018_in = 0, $n_018 = 0, $1 = 0, $2 = 0, $call1 = 0, $tobool2 = 0, $3 = 0, $cmp = 0, $call5 = 0, $tobool6 = 0, $_pr = 0, $4 = 0, $cmp10 = 0, $call13 = 0, $tobool14 = 0, $5 = 0, $tobool17 = 0, $6 = 0, $7 = 0, $call19 = 0, $call23 = 0, $tobool = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool15 = ($call | 0) == 0;
+ if ($tobool15) {
+ label = 14;
+ break;
+ } else {
+ $n_018_in = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $n_018 = $n_018_in;
+ $1 = $n_018_in | 0;
+ $2 = HEAP32[41580] | 0;
+ $call1 = _late_string($1, $2, 0) | 0;
+ $tobool2 = ($call1 | 0) == 0;
+ if ($tobool2) {
+ label = 13;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP8[$call1] | 0;
+ $cmp = $3 << 24 >> 24 == 111;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $4 = $3;
+ label = 8;
+ break;
+ }
+ case 5:
+ $call5 = _strcmp($call1 | 0, 101448) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ _do_ordering_node($g, $n_018, 1);
+ label = 13;
+ break;
+ case 7:
+ $_pr = HEAP8[$call1] | 0;
+ $4 = $_pr;
+ label = 8;
+ break;
+ case 8:
+ $cmp10 = $4 << 24 >> 24 == 105;
+ if ($cmp10) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $call13 = _strcmp($call1 | 0, 97144) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ _do_ordering_node($g, $n_018, 0);
+ label = 13;
+ break;
+ case 11:
+ $5 = HEAP8[$call1] | 0;
+ $tobool17 = $5 << 24 >> 24 == 0;
+ if ($tobool17) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $6 = $n_018_in + 12 | 0;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $call19 = _agerr(1, 90016, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $call1, HEAP32[tempInt + 8 >> 2] = $7, tempInt) | 0) | 0;
+ label = 13;
+ break;
+ case 13:
+ $call23 = _agnxtnode($0, $n_018_in) | 0;
+ $tobool = ($call23 | 0) == 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ $n_018_in = $call23;
+ label = 3;
+ break;
+ }
+ case 14:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _do_ordering_node($g, $n, $outflag) {
+ $g = $g | 0;
+ $n = $n | 0;
+ $outflag = $outflag | 0;
+ var $0 = 0, $clust = 0, $1 = 0, $tobool = 0, $tobool2 = 0, $list13 = 0, $2 = 0, $3 = 0, $tobool1534 = 0, $list = 0, $4 = 0, $5 = 0, $tobool530 = 0, $6 = 0, $i_032 = 0, $ne_031 = 0, $call = 0, $tobool6 = 0, $inc = 0, $arrayidx8 = 0, $ne_1 = 0, $inc10 = 0, $7 = 0, $arrayidx = 0, $8 = 0, $tobool5 = 0, $9 = 0, $i_136 = 0, $ne_235 = 0, $call17 = 0, $tobool18 = 0, $inc20 = 0, $arrayidx21 = 0, $ne_3 = 0, $inc24 = 0, $10 = 0, $arrayidx14 = 0, $11 = 0, $tobool15 = 0, $ne_4 = 0, $cmp = 0, $arrayidx29 = 0, $12 = 0, $arrayidx3127 = 0, $13 = 0, $tobool3228 = 0, $14 = 0, $ne_529 = 0, $sub = 0, $arrayidx34 = 0, $15 = 0, $head = 0, $head37 = 0, $tail = 0, $tail39 = 0, $v_0_in = 0, $u_0_in = 0, $u_0 = 0, $v_0 = 0, $call41 = 0, $tobool42 = 0, $call45 = 0, $edge_type = 0, $inc48 = 0, $arrayidx31 = 0, $16 = 0, $tobool32 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41348] | 0;
+ $clust = $n + 216 | 0;
+ $1 = HEAP32[$clust >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 3:
+ $tobool2 = ($outflag | 0) != 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $list13 = $n + 176 | 0;
+ $2 = HEAP32[$list13 >> 2] | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $tobool1534 = ($3 | 0) == 0;
+ if ($tobool1534) {
+ label = 19;
+ break;
+ } else {
+ $ne_235 = 0;
+ $i_136 = 0;
+ $9 = $3;
+ label = 9;
+ break;
+ }
+ case 5:
+ $list = $n + 184 | 0;
+ $4 = HEAP32[$list >> 2] | 0;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $tobool530 = ($5 | 0) == 0;
+ if ($tobool530) {
+ label = 19;
+ break;
+ } else {
+ $ne_031 = 0;
+ $i_032 = 0;
+ $6 = $5;
+ label = 6;
+ break;
+ }
+ case 6:
+ $call = _betweenclust($6) | 0;
+ $tobool6 = ($call | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ $ne_1 = $ne_031;
+ label = 8;
+ break;
+ }
+ case 7:
+ $inc = $ne_031 + 1 | 0;
+ $arrayidx8 = $0 + ($ne_031 << 2) | 0;
+ HEAP32[$arrayidx8 >> 2] = $6;
+ $ne_1 = $inc;
+ label = 8;
+ break;
+ case 8:
+ $inc10 = $i_032 + 1 | 0;
+ $7 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $7 + ($inc10 << 2) | 0;
+ $8 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool5 = ($8 | 0) == 0;
+ if ($tobool5) {
+ $ne_4 = $ne_1;
+ label = 12;
+ break;
+ } else {
+ $ne_031 = $ne_1;
+ $i_032 = $inc10;
+ $6 = $8;
+ label = 6;
+ break;
+ }
+ case 9:
+ $call17 = _betweenclust($9) | 0;
+ $tobool18 = ($call17 | 0) == 0;
+ if ($tobool18) {
+ label = 10;
+ break;
+ } else {
+ $ne_3 = $ne_235;
+ label = 11;
+ break;
+ }
+ case 10:
+ $inc20 = $ne_235 + 1 | 0;
+ $arrayidx21 = $0 + ($ne_235 << 2) | 0;
+ HEAP32[$arrayidx21 >> 2] = $9;
+ $ne_3 = $inc20;
+ label = 11;
+ break;
+ case 11:
+ $inc24 = $i_136 + 1 | 0;
+ $10 = HEAP32[$list13 >> 2] | 0;
+ $arrayidx14 = $10 + ($inc24 << 2) | 0;
+ $11 = HEAP32[$arrayidx14 >> 2] | 0;
+ $tobool15 = ($11 | 0) == 0;
+ if ($tobool15) {
+ $ne_4 = $ne_3;
+ label = 12;
+ break;
+ } else {
+ $ne_235 = $ne_3;
+ $i_136 = $inc24;
+ $9 = $11;
+ label = 9;
+ break;
+ }
+ case 12:
+ $cmp = ($ne_4 | 0) < 2;
+ if ($cmp) {
+ label = 19;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $arrayidx29 = $0 + ($ne_4 << 2) | 0;
+ HEAP32[$arrayidx29 >> 2] = 0;
+ $12 = $0;
+ _qsort($12 | 0, $ne_4 | 0, 4, 200);
+ $arrayidx3127 = $0 + 4 | 0;
+ $13 = HEAP32[$arrayidx3127 >> 2] | 0;
+ $tobool3228 = ($13 | 0) == 0;
+ if ($tobool3228) {
+ label = 19;
+ break;
+ } else {
+ $ne_529 = 1;
+ $14 = $13;
+ label = 14;
+ break;
+ }
+ case 14:
+ $sub = $ne_529 - 1 | 0;
+ $arrayidx34 = $0 + ($sub << 2) | 0;
+ $15 = HEAP32[$arrayidx34 >> 2] | 0;
+ if ($tobool2) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $head = $15 + 12 | 0;
+ $head37 = $14 + 12 | 0;
+ $u_0_in = $head;
+ $v_0_in = $head37;
+ label = 17;
+ break;
+ case 16:
+ $tail = $15 + 16 | 0;
+ $tail39 = $14 + 16 | 0;
+ $u_0_in = $tail;
+ $v_0_in = $tail39;
+ label = 17;
+ break;
+ case 17:
+ $u_0 = HEAP32[$u_0_in >> 2] | 0;
+ $v_0 = HEAP32[$v_0_in >> 2] | 0;
+ $call41 = _find_flat_edge($u_0, $v_0) | 0;
+ $tobool42 = ($call41 | 0) == 0;
+ if ($tobool42) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $call45 = _new_virtual_edge($u_0, $v_0, 0) | 0;
+ $edge_type = $call45 + 128 | 0;
+ HEAP8[$edge_type] = 4;
+ _flat_edge($g, $call45);
+ $inc48 = $ne_529 + 1 | 0;
+ $arrayidx31 = $0 + ($inc48 << 2) | 0;
+ $16 = HEAP32[$arrayidx31 >> 2] | 0;
+ $tobool32 = ($16 | 0) == 0;
+ if ($tobool32) {
+ label = 19;
+ break;
+ } else {
+ $ne_529 = $inc48;
+ $14 = $16;
+ label = 14;
+ break;
+ }
+ case 19:
+ return;
+ }
+}
+function _is_a_normal_node_of($g, $v) {
+ $g = $g | 0;
+ $v = $v | 0;
+ var $node_type = 0, $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $call = 0, $tobool = 0, $phitmp = 0, $3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $v + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $3 = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = $v | 0;
+ $2 = $g;
+ $call = _agcontains($2, $1) | 0;
+ $tobool = ($call | 0) != 0;
+ $phitmp = $tobool & 1;
+ $3 = $phitmp;
+ label = 4;
+ break;
+ case 4:
+ return $3 | 0;
+ }
+ return 0;
+}
+function _is_a_vnode_of_an_edge_of($g, $v) {
+ $g = $g | 0;
+ $v = $v | 0;
+ var $node_type = 0, $0 = 0, $cmp = 0, $size = 0, $1 = 0, $cmp3 = 0, $size7 = 0, $2 = 0, $cmp8 = 0, $list = 0, $3 = 0, $e_0_in = 0, $e_0 = 0, $edge_type = 0, $4 = 0, $cmp14 = 0, $to_orig = 0, $5 = 0, $6 = 0, $call = 0, $tobool = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $v + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $size = $v + 180 | 0;
+ $1 = HEAP32[$size >> 2] | 0;
+ $cmp3 = ($1 | 0) == 1;
+ if ($cmp3) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $size7 = $v + 188 | 0;
+ $2 = HEAP32[$size7 >> 2] | 0;
+ $cmp8 = ($2 | 0) == 1;
+ if ($cmp8) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 5:
+ $list = $v + 184 | 0;
+ $3 = HEAP32[$list >> 2] | 0;
+ $e_0_in = $3;
+ label = 6;
+ break;
+ case 6:
+ $e_0 = HEAP32[$e_0_in >> 2] | 0;
+ $edge_type = $e_0 + 128 | 0;
+ $4 = HEAP8[$edge_type] | 0;
+ $cmp14 = $4 << 24 >> 24 == 0;
+ $to_orig = $e_0 + 132 | 0;
+ if ($cmp14) {
+ label = 7;
+ break;
+ } else {
+ $e_0_in = $to_orig;
+ label = 6;
+ break;
+ }
+ case 7:
+ $5 = $e_0 | 0;
+ $6 = $g;
+ $call = _agcontains($6, $5) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 9;
+ break;
+ }
+ case 8:
+ $retval_0 = 0;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _free_matrix($p) {
+ $p = $p | 0;
+ var $tobool = 0, $data = 0, $0 = 0, $1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($p | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $data = $p + 8 | 0;
+ $0 = HEAP32[$data >> 2] | 0;
+ _free($0);
+ $1 = $p;
+ _free($1);
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _flat_breakcycles($g) {
+ $g = $g | 0;
+ var $minrank = 0, $0 = 0, $maxrank = 0, $1 = 0, $cmp39 = 0, $conv = 0, $rank = 0, $r_040 = 0, $2 = 0, $n30 = 0, $3 = 0, $cmp631 = 0, $4 = 0, $flat_033 = 0, $i_032 = 0, $v12 = 0, $5 = 0, $arrayidx13 = 0, $6 = 0, $onstack = 0, $mark = 0, $low = 0, $size = 0, $7 = 0, $cmp18 = 0, $cmp20 = 0, $or_cond = 0, $8 = 0, $n25 = 0, $9 = 0, $call = 0, $10 = 0, $flat33 = 0, $flat_1 = 0, $inc = 0, $11 = 0, $n = 0, $12 = 0, $cmp6 = 0, $tobool = 0, $13 = 0, $n3935 = 0, $14 = 0, $cmp4036 = 0, $15 = 0, $i_137 = 0, $v46 = 0, $16 = 0, $arrayidx47 = 0, $17 = 0, $mark49 = 0, $18 = 0, $cmp51 = 0, $inc56 = 0, $19 = 0, $n39 = 0, $20 = 0, $cmp40 = 0, $inc60 = 0, $21 = 0, $conv2 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $cmp39 = $0 << 16 >> 16 > $1 << 16 >> 16;
+ if ($cmp39) {
+ label = 14;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $r_040 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$rank >> 2] | 0;
+ $n30 = $2 + ($r_040 * 44 & -1) | 0;
+ $3 = HEAP32[$n30 >> 2] | 0;
+ $cmp631 = ($3 | 0) > 0;
+ if ($cmp631) {
+ $i_032 = 0;
+ $flat_033 = 0;
+ $4 = $2;
+ label = 5;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 5:
+ $v12 = $4 + ($r_040 * 44 & -1) + 4 | 0;
+ $5 = HEAP32[$v12 >> 2] | 0;
+ $arrayidx13 = $5 + ($i_032 << 2) | 0;
+ $6 = HEAP32[$arrayidx13 >> 2] | 0;
+ $onstack = $6 + 164 | 0;
+ HEAP8[$onstack] = 0;
+ $mark = $6 + 163 | 0;
+ HEAP8[$mark] = 0;
+ $low = $6 + 284 | 0;
+ HEAP32[$low >> 2] = $i_032;
+ $size = $6 + 196 | 0;
+ $7 = HEAP32[$size >> 2] | 0;
+ $cmp18 = ($7 | 0) > 0;
+ $cmp20 = ($flat_033 | 0) == 0;
+ $or_cond = $cmp18 & $cmp20;
+ if ($or_cond) {
+ label = 6;
+ break;
+ } else {
+ $flat_1 = $flat_033;
+ label = 7;
+ break;
+ }
+ case 6:
+ $8 = HEAP32[$rank >> 2] | 0;
+ $n25 = $8 + ($r_040 * 44 & -1) | 0;
+ $9 = HEAP32[$n25 >> 2] | 0;
+ $call = _new_matrix($9, $9) | 0;
+ $10 = HEAP32[$rank >> 2] | 0;
+ $flat33 = $10 + ($r_040 * 44 & -1) + 40 | 0;
+ HEAP32[$flat33 >> 2] = $call;
+ $flat_1 = 1;
+ label = 7;
+ break;
+ case 7:
+ $inc = $i_032 + 1 | 0;
+ $11 = HEAP32[$rank >> 2] | 0;
+ $n = $11 + ($r_040 * 44 & -1) | 0;
+ $12 = HEAP32[$n >> 2] | 0;
+ $cmp6 = ($inc | 0) < ($12 | 0);
+ if ($cmp6) {
+ $i_032 = $inc;
+ $flat_033 = $flat_1;
+ $4 = $11;
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $tobool = ($flat_1 | 0) == 0;
+ if ($tobool) {
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $13 = HEAP32[$rank >> 2] | 0;
+ $n3935 = $13 + ($r_040 * 44 & -1) | 0;
+ $14 = HEAP32[$n3935 >> 2] | 0;
+ $cmp4036 = ($14 | 0) > 0;
+ if ($cmp4036) {
+ $i_137 = 0;
+ $15 = $13;
+ label = 10;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 10:
+ $v46 = $15 + ($r_040 * 44 & -1) + 4 | 0;
+ $16 = HEAP32[$v46 >> 2] | 0;
+ $arrayidx47 = $16 + ($i_137 << 2) | 0;
+ $17 = HEAP32[$arrayidx47 >> 2] | 0;
+ $mark49 = $17 + 163 | 0;
+ $18 = HEAP8[$mark49] | 0;
+ $cmp51 = $18 << 24 >> 24 == 0;
+ if ($cmp51) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ _flat_search($g, $17);
+ label = 12;
+ break;
+ case 12:
+ $inc56 = $i_137 + 1 | 0;
+ $19 = HEAP32[$rank >> 2] | 0;
+ $n39 = $19 + ($r_040 * 44 & -1) | 0;
+ $20 = HEAP32[$n39 >> 2] | 0;
+ $cmp40 = ($inc56 | 0) < ($20 | 0);
+ if ($cmp40) {
+ $i_137 = $inc56;
+ $15 = $19;
+ label = 10;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $inc60 = $r_040 + 1 | 0;
+ $21 = HEAP16[$maxrank >> 1] | 0;
+ $conv2 = $21 << 16 >> 16;
+ $cmp = ($inc60 | 0) > ($conv2 | 0);
+ if ($cmp) {
+ label = 14;
+ break;
+ } else {
+ $r_040 = $inc60;
+ label = 4;
+ break;
+ }
+ case 14:
+ return;
+ }
+}
+function _flat_reorder($g) {
+ $g = $g | 0;
+ var $has_flat_edges = 0, $0 = 0, $cmp = 0, $minrank = 0, $1 = 0, $maxrank = 0, $2 = 0, $cmp6119 = 0, $conv3 = 0, $rank = 0, $rankdir = 0, $temprank_0123 = 0, $r_0120 = 0, $3 = 0, $n89 = 0, $4 = 0, $cmp1090 = 0, $5 = 0, $i_091 = 0, $v16 = 0, $6 = 0, $arrayidx17 = 0, $7 = 0, $mark = 0, $inc = 0, $8 = 0, $n = 0, $9 = 0, $cmp10 = 0, $phitmp = 0, $phitmp125 = 0, $i_0_lcssa = 0, $tobool = 0, $10 = 0, $call = 0, $call21 = 0, $call_sink = 0, $11 = 0, $12 = 0, $n26104 = 0, $13 = 0, $cmp27105 = 0, $14 = 0, $i_1107 = 0, $pos_0106 = 0, $v33 = 0, $15 = 0, $arrayidx34 = 0, $16 = 0, $size = 0, $17 = 0, $cmp3793 = 0, $list = 0, $j_095 = 0, $local_in_cnt_094 = 0, $18 = 0, $arrayidx42 = 0, $19 = 0, $weight = 0, $20 = 0.0, $cmp44 = 0, $tail = 0, $21 = 0, $call46 = 0, $not_tobool47 = 0, $inc49 = 0, $local_in_cnt_0_inc49 = 0, $local_in_cnt_1 = 0, $inc52 = 0, $22 = 0, $cmp37 = 0, $local_in_cnt_0_lcssa = 0, $size56 = 0, $23 = 0, $cmp5797 = 0, $list62 = 0, $j_199 = 0, $local_out_cnt_098 = 0, $24 = 0, $arrayidx63 = 0, $25 = 0, $weight65 = 0, $26 = 0.0, $cmp66 = 0, $head = 0, $27 = 0, $call69 = 0, $not_tobool70 = 0, $inc72 = 0, $local_out_cnt_0_inc72 = 0, $local_out_cnt_1 = 0, $inc75 = 0, $28 = 0, $cmp57 = 0, $local_out_cnt_0_lcssa = 0, $29 = 0, $30 = 0, $inc83 = 0, $arrayidx84 = 0, $mark86 = 0, $31 = 0, $cmp88_not = 0, $cmp77_not = 0, $brmerge = 0, $add_ptr = 0, $call94 = 0, $32 = 0, $and96 = 0, $cmp97 = 0, $add_ptr_sum = 0, $add_ptr100_sum = 0, $cmp102101 = 0, $add_ptr101 = 0, $right_0103 = 0, $left_0102 = 0, $33 = 0, $34 = 0, $incdec_ptr = 0, $incdec_ptr104 = 0, $cmp102 = 0, $add106 = 0, $pos_1 = 0, $inc110 = 0, $35 = 0, $n26 = 0, $36 = 0, $cmp27 = 0, $tobool112 = 0, $37 = 0, $n118109 = 0, $38 = 0, $cmp119110 = 0, $39 = 0, $i_2111 = 0, $arrayidx122 = 0, $40 = 0, $v126 = 0, $41 = 0, $arrayidx127 = 0, $42 = 0, $v131 = 0, $43 = 0, $44 = 0, $rank133 = 0, $45 = 0, $v135 = 0, $46 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $sub_ptr_div = 0, $add136 = 0, $order = 0, $inc139 = 0, $47 = 0, $n118 = 0, $48 = 0, $cmp119 = 0, $49 = 0, $n145115 = 0, $50 = 0, $cmp146116 = 0, $51 = 0, $i_3117 = 0, $v152 = 0, $52 = 0, $arrayidx153 = 0, $53 = 0, $list156 = 0, $54 = 0, $tobool157 = 0, $55 = 0, $56 = 0, $tobool164113 = 0, $57 = 0, $j_2114 = 0, $head166 = 0, $58 = 0, $order168 = 0, $59 = 0, $tail169 = 0, $60 = 0, $order171 = 0, $61 = 0, $cmp172 = 0, $dec = 0, $j_3 = 0, $inc177 = 0, $62 = 0, $arrayidx163 = 0, $63 = 0, $tobool164 = 0, $inc181 = 0, $64 = 0, $n145 = 0, $65 = 0, $cmp146 = 0, $66 = 0, $rank185 = 0, $67 = 0, $valid = 0, $inc188 = 0, $68 = 0, $conv5 = 0, $cmp6 = 0, $tobool190 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $has_flat_edges = $g + 252 | 0;
+ $0 = HEAP8[$has_flat_edges] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 44;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $cmp6119 = $1 << 16 >> 16 > $2 << 16 >> 16;
+ if ($cmp6119) {
+ label = 44;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv3 = $1 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $rankdir = $g + 156 | 0;
+ $r_0120 = $conv3;
+ $temprank_0123 = 0;
+ label = 5;
+ break;
+ case 5:
+ $3 = HEAP32[$rank >> 2] | 0;
+ $n89 = $3 + ($r_0120 * 44 & -1) | 0;
+ $4 = HEAP32[$n89 >> 2] | 0;
+ $cmp1090 = ($4 | 0) > 0;
+ if ($cmp1090) {
+ $i_091 = 0;
+ $5 = $3;
+ label = 6;
+ break;
+ } else {
+ $i_0_lcssa = 4;
+ label = 8;
+ break;
+ }
+ case 6:
+ $v16 = $5 + ($r_0120 * 44 & -1) + 4 | 0;
+ $6 = HEAP32[$v16 >> 2] | 0;
+ $arrayidx17 = $6 + ($i_091 << 2) | 0;
+ $7 = HEAP32[$arrayidx17 >> 2] | 0;
+ $mark = $7 + 163 | 0;
+ HEAP8[$mark] = 0;
+ $inc = $i_091 + 1 | 0;
+ $8 = HEAP32[$rank >> 2] | 0;
+ $n = $8 + ($r_0120 * 44 & -1) | 0;
+ $9 = HEAP32[$n >> 2] | 0;
+ $cmp10 = ($inc | 0) < ($9 | 0);
+ if ($cmp10) {
+ $i_091 = $inc;
+ $5 = $8;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $phitmp = $inc << 2;
+ $phitmp125 = $phitmp + 4 | 0;
+ $i_0_lcssa = $phitmp125;
+ label = 8;
+ break;
+ case 8:
+ $tobool = ($temprank_0123 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $10 = $temprank_0123;
+ $call = _grealloc($10, $i_0_lcssa) | 0;
+ $call_sink = $call;
+ label = 11;
+ break;
+ case 10:
+ $call21 = _gmalloc($i_0_lcssa) | 0;
+ $call_sink = $call21;
+ label = 11;
+ break;
+ case 11:
+ $11 = $call_sink;
+ $12 = HEAP32[$rank >> 2] | 0;
+ $n26104 = $12 + ($r_0120 * 44 & -1) | 0;
+ $13 = HEAP32[$n26104 >> 2] | 0;
+ $cmp27105 = ($13 | 0) > 0;
+ if ($cmp27105) {
+ $pos_0106 = 0;
+ $i_1107 = 0;
+ $14 = $12;
+ label = 12;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 12:
+ $v33 = $14 + ($r_0120 * 44 & -1) + 4 | 0;
+ $15 = HEAP32[$v33 >> 2] | 0;
+ $arrayidx34 = $15 + ($i_1107 << 2) | 0;
+ $16 = HEAP32[$arrayidx34 >> 2] | 0;
+ $size = $16 + 204 | 0;
+ $17 = HEAP32[$size >> 2] | 0;
+ $cmp3793 = ($17 | 0) > 0;
+ if ($cmp3793) {
+ label = 13;
+ break;
+ } else {
+ $local_in_cnt_0_lcssa = 0;
+ label = 17;
+ break;
+ }
+ case 13:
+ $list = $16 + 200 | 0;
+ $local_in_cnt_094 = 0;
+ $j_095 = 0;
+ label = 14;
+ break;
+ case 14:
+ $18 = HEAP32[$list >> 2] | 0;
+ $arrayidx42 = $18 + ($j_095 << 2) | 0;
+ $19 = HEAP32[$arrayidx42 >> 2] | 0;
+ $weight = $19 + 172 | 0;
+ $20 = +HEAPF32[$weight >> 2];
+ $cmp44 = $20 > 0.0;
+ if ($cmp44) {
+ label = 15;
+ break;
+ } else {
+ $local_in_cnt_1 = $local_in_cnt_094;
+ label = 16;
+ break;
+ }
+ case 15:
+ $tail = $19 + 16 | 0;
+ $21 = HEAP32[$tail >> 2] | 0;
+ $call46 = _inside_cluster($g, $21) | 0;
+ $not_tobool47 = ($call46 | 0) != 0;
+ $inc49 = $not_tobool47 & 1;
+ $local_in_cnt_0_inc49 = $inc49 + $local_in_cnt_094 | 0;
+ $local_in_cnt_1 = $local_in_cnt_0_inc49;
+ label = 16;
+ break;
+ case 16:
+ $inc52 = $j_095 + 1 | 0;
+ $22 = HEAP32[$size >> 2] | 0;
+ $cmp37 = ($inc52 | 0) < ($22 | 0);
+ if ($cmp37) {
+ $local_in_cnt_094 = $local_in_cnt_1;
+ $j_095 = $inc52;
+ label = 14;
+ break;
+ } else {
+ $local_in_cnt_0_lcssa = $local_in_cnt_1;
+ label = 17;
+ break;
+ }
+ case 17:
+ $size56 = $16 + 196 | 0;
+ $23 = HEAP32[$size56 >> 2] | 0;
+ $cmp5797 = ($23 | 0) > 0;
+ if ($cmp5797) {
+ label = 18;
+ break;
+ } else {
+ $local_out_cnt_0_lcssa = 0;
+ label = 22;
+ break;
+ }
+ case 18:
+ $list62 = $16 + 192 | 0;
+ $local_out_cnt_098 = 0;
+ $j_199 = 0;
+ label = 19;
+ break;
+ case 19:
+ $24 = HEAP32[$list62 >> 2] | 0;
+ $arrayidx63 = $24 + ($j_199 << 2) | 0;
+ $25 = HEAP32[$arrayidx63 >> 2] | 0;
+ $weight65 = $25 + 172 | 0;
+ $26 = +HEAPF32[$weight65 >> 2];
+ $cmp66 = $26 > 0.0;
+ if ($cmp66) {
+ label = 20;
+ break;
+ } else {
+ $local_out_cnt_1 = $local_out_cnt_098;
+ label = 21;
+ break;
+ }
+ case 20:
+ $head = $25 + 12 | 0;
+ $27 = HEAP32[$head >> 2] | 0;
+ $call69 = _inside_cluster($g, $27) | 0;
+ $not_tobool70 = ($call69 | 0) != 0;
+ $inc72 = $not_tobool70 & 1;
+ $local_out_cnt_0_inc72 = $inc72 + $local_out_cnt_098 | 0;
+ $local_out_cnt_1 = $local_out_cnt_0_inc72;
+ label = 21;
+ break;
+ case 21:
+ $inc75 = $j_199 + 1 | 0;
+ $28 = HEAP32[$size56 >> 2] | 0;
+ $cmp57 = ($inc75 | 0) < ($28 | 0);
+ if ($cmp57) {
+ $local_out_cnt_098 = $local_out_cnt_1;
+ $j_199 = $inc75;
+ label = 19;
+ break;
+ } else {
+ $local_out_cnt_0_lcssa = $local_out_cnt_1;
+ label = 22;
+ break;
+ }
+ case 22:
+ $29 = $local_out_cnt_0_lcssa | $local_in_cnt_0_lcssa;
+ $30 = ($29 | 0) == 0;
+ if ($30) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ $inc83 = $pos_0106 + 1 | 0;
+ $arrayidx84 = $11 + ($pos_0106 << 2) | 0;
+ HEAP32[$arrayidx84 >> 2] = $16;
+ $pos_1 = $inc83;
+ label = 30;
+ break;
+ case 24:
+ $mark86 = $16 + 163 | 0;
+ $31 = HEAP8[$mark86] | 0;
+ $cmp88_not = $31 << 24 >> 24 != 0;
+ $cmp77_not = ($local_in_cnt_0_lcssa | 0) != 0;
+ $brmerge = $cmp88_not | $cmp77_not;
+ if ($brmerge) {
+ $pos_1 = $pos_0106;
+ label = 30;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $add_ptr = $11 + ($pos_0106 << 2) | 0;
+ $call94 = _postorder($g, $16, $add_ptr, $r_0120) | 0;
+ $32 = HEAP32[$rankdir >> 2] | 0;
+ $and96 = $32 & 1;
+ $cmp97 = ($and96 | 0) == 0;
+ if ($cmp97) {
+ label = 26;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 26:
+ $add_ptr_sum = $pos_0106 - 1 | 0;
+ $add_ptr100_sum = $add_ptr_sum + $call94 | 0;
+ $cmp102101 = ($pos_0106 | 0) < ($add_ptr100_sum | 0);
+ if ($cmp102101) {
+ label = 27;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 27:
+ $add_ptr101 = $11 + ($add_ptr100_sum << 2) | 0;
+ $left_0102 = $add_ptr;
+ $right_0103 = $add_ptr101;
+ label = 28;
+ break;
+ case 28:
+ $33 = HEAP32[$left_0102 >> 2] | 0;
+ $34 = HEAP32[$right_0103 >> 2] | 0;
+ HEAP32[$left_0102 >> 2] = $34;
+ HEAP32[$right_0103 >> 2] = $33;
+ $incdec_ptr = $left_0102 + 4 | 0;
+ $incdec_ptr104 = $right_0103 - 4 | 0;
+ $cmp102 = $incdec_ptr >>> 0 < $incdec_ptr104 >>> 0;
+ if ($cmp102) {
+ $left_0102 = $incdec_ptr;
+ $right_0103 = $incdec_ptr104;
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $add106 = $call94 + $pos_0106 | 0;
+ $pos_1 = $add106;
+ label = 30;
+ break;
+ case 30:
+ $inc110 = $i_1107 + 1 | 0;
+ $35 = HEAP32[$rank >> 2] | 0;
+ $n26 = $35 + ($r_0120 * 44 & -1) | 0;
+ $36 = HEAP32[$n26 >> 2] | 0;
+ $cmp27 = ($inc110 | 0) < ($36 | 0);
+ if ($cmp27) {
+ $pos_0106 = $pos_1;
+ $i_1107 = $inc110;
+ $14 = $35;
+ label = 12;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $tobool112 = ($pos_1 | 0) == 0;
+ if ($tobool112) {
+ label = 41;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $37 = HEAP32[$rank >> 2] | 0;
+ $n118109 = $37 + ($r_0120 * 44 & -1) | 0;
+ $38 = HEAP32[$n118109 >> 2] | 0;
+ $cmp119110 = ($38 | 0) > 0;
+ if ($cmp119110) {
+ $i_2111 = 0;
+ $39 = $37;
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ $arrayidx122 = $11 + ($i_2111 << 2) | 0;
+ $40 = HEAP32[$arrayidx122 >> 2] | 0;
+ $v126 = $39 + ($r_0120 * 44 & -1) + 4 | 0;
+ $41 = HEAP32[$v126 >> 2] | 0;
+ $arrayidx127 = $41 + ($i_2111 << 2) | 0;
+ HEAP32[$arrayidx127 >> 2] = $40;
+ $42 = HEAP32[$rank >> 2] | 0;
+ $v131 = $42 + ($r_0120 * 44 & -1) + 4 | 0;
+ $43 = HEAP32[$v131 >> 2] | 0;
+ $44 = HEAP32[41526] | 0;
+ $rank133 = $44 + 224 | 0;
+ $45 = HEAP32[$rank133 >> 2] | 0;
+ $v135 = $45 + ($r_0120 * 44 & -1) + 4 | 0;
+ $46 = HEAP32[$v135 >> 2] | 0;
+ $sub_ptr_lhs_cast = $43;
+ $sub_ptr_rhs_cast = $46;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $sub_ptr_div = $sub_ptr_sub >> 2;
+ $add136 = $sub_ptr_div + $i_2111 | 0;
+ $order = $40 + 240 | 0;
+ HEAP32[$order >> 2] = $add136;
+ $inc139 = $i_2111 + 1 | 0;
+ $47 = HEAP32[$rank >> 2] | 0;
+ $n118 = $47 + ($r_0120 * 44 & -1) | 0;
+ $48 = HEAP32[$n118 >> 2] | 0;
+ $cmp119 = ($inc139 | 0) < ($48 | 0);
+ if ($cmp119) {
+ $i_2111 = $inc139;
+ $39 = $47;
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $49 = HEAP32[$rank >> 2] | 0;
+ $n145115 = $49 + ($r_0120 * 44 & -1) | 0;
+ $50 = HEAP32[$n145115 >> 2] | 0;
+ $cmp146116 = ($50 | 0) > 0;
+ if ($cmp146116) {
+ $i_3117 = 0;
+ $51 = $49;
+ label = 35;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 35:
+ $v152 = $51 + ($r_0120 * 44 & -1) + 4 | 0;
+ $52 = HEAP32[$v152 >> 2] | 0;
+ $arrayidx153 = $52 + ($i_3117 << 2) | 0;
+ $53 = HEAP32[$arrayidx153 >> 2] | 0;
+ $list156 = $53 + 192 | 0;
+ $54 = HEAP32[$list156 >> 2] | 0;
+ $tobool157 = ($54 | 0) == 0;
+ if ($tobool157) {
+ label = 40;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $55 = HEAP32[$list156 >> 2] | 0;
+ $56 = HEAP32[$55 >> 2] | 0;
+ $tobool164113 = ($56 | 0) == 0;
+ if ($tobool164113) {
+ label = 40;
+ break;
+ } else {
+ $j_2114 = 0;
+ $57 = $56;
+ label = 37;
+ break;
+ }
+ case 37:
+ $head166 = $57 + 12 | 0;
+ $58 = HEAP32[$head166 >> 2] | 0;
+ $order168 = $58 + 240 | 0;
+ $59 = HEAP32[$order168 >> 2] | 0;
+ $tail169 = $57 + 16 | 0;
+ $60 = HEAP32[$tail169 >> 2] | 0;
+ $order171 = $60 + 240 | 0;
+ $61 = HEAP32[$order171 >> 2] | 0;
+ $cmp172 = ($59 | 0) < ($61 | 0);
+ if ($cmp172) {
+ label = 38;
+ break;
+ } else {
+ $j_3 = $j_2114;
+ label = 39;
+ break;
+ }
+ case 38:
+ _delete_flat_edge($57);
+ $dec = $j_2114 - 1 | 0;
+ _flat_rev($g, $57);
+ $j_3 = $dec;
+ label = 39;
+ break;
+ case 39:
+ $inc177 = $j_3 + 1 | 0;
+ $62 = HEAP32[$list156 >> 2] | 0;
+ $arrayidx163 = $62 + ($inc177 << 2) | 0;
+ $63 = HEAP32[$arrayidx163 >> 2] | 0;
+ $tobool164 = ($63 | 0) == 0;
+ if ($tobool164) {
+ label = 40;
+ break;
+ } else {
+ $j_2114 = $inc177;
+ $57 = $63;
+ label = 37;
+ break;
+ }
+ case 40:
+ $inc181 = $i_3117 + 1 | 0;
+ $64 = HEAP32[$rank >> 2] | 0;
+ $n145 = $64 + ($r_0120 * 44 & -1) | 0;
+ $65 = HEAP32[$n145 >> 2] | 0;
+ $cmp146 = ($inc181 | 0) < ($65 | 0);
+ if ($cmp146) {
+ $i_3117 = $inc181;
+ $51 = $64;
+ label = 35;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $66 = HEAP32[41526] | 0;
+ $rank185 = $66 + 224 | 0;
+ $67 = HEAP32[$rank185 >> 2] | 0;
+ $valid = $67 + ($r_0120 * 44 & -1) + 33 | 0;
+ HEAP8[$valid] = 0;
+ $inc188 = $r_0120 + 1 | 0;
+ $68 = HEAP16[$maxrank >> 1] | 0;
+ $conv5 = $68 << 16 >> 16;
+ $cmp6 = ($inc188 | 0) > ($conv5 | 0);
+ if ($cmp6) {
+ label = 42;
+ break;
+ } else {
+ $r_0120 = $inc188;
+ $temprank_0123 = $11;
+ label = 5;
+ break;
+ }
+ case 42:
+ $tobool190 = ($call_sink | 0) == 0;
+ if ($tobool190) {
+ label = 44;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ _free($call_sink);
+ label = 44;
+ break;
+ case 44:
+ return;
+ }
+}
+function _restore_best($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_015 = 0, $tobool16 = 0, $n_017 = 0, $x = 0, $0 = 0.0, $conv = 0, $order = 0, $next = 0, $n_0 = 0, $tobool = 0, $minrank = 0, $1 = 0, $maxrank = 0, $2 = 0, $cmp13 = 0, $conv5 = 0, $rank13 = 0, $r_014 = 0, $3 = 0, $rank = 0, $4 = 0, $valid = 0, $5 = 0, $v = 0, $6 = 0, $7 = 0, $n18 = 0, $8 = 0, $inc = 0, $9 = 0, $conv8 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $n_015 = HEAP32[$nlist >> 2] | 0;
+ $tobool16 = ($n_015 | 0) == 0;
+ if ($tobool16) {
+ label = 4;
+ break;
+ } else {
+ $n_017 = $n_015;
+ label = 3;
+ break;
+ }
+ case 3:
+ $x = $n_017 + 32 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $conv = ~~$0;
+ $order = $n_017 + 240 | 0;
+ HEAP32[$order >> 2] = $conv;
+ $next = $n_017 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $n_017 = $n_0;
+ label = 3;
+ break;
+ }
+ case 4:
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $cmp13 = $1 << 16 >> 16 > $2 << 16 >> 16;
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $conv5 = $1 << 16 >> 16;
+ $rank13 = $g + 224 | 0;
+ $r_014 = $conv5;
+ label = 6;
+ break;
+ case 6:
+ $3 = HEAP32[41526] | 0;
+ $rank = $3 + 224 | 0;
+ $4 = HEAP32[$rank >> 2] | 0;
+ $valid = $4 + ($r_014 * 44 & -1) + 33 | 0;
+ HEAP8[$valid] = 0;
+ $5 = HEAP32[$rank13 >> 2] | 0;
+ $v = $5 + ($r_014 * 44 & -1) + 4 | 0;
+ $6 = HEAP32[$v >> 2] | 0;
+ $7 = $6;
+ $n18 = $5 + ($r_014 * 44 & -1) | 0;
+ $8 = HEAP32[$n18 >> 2] | 0;
+ _qsort($7 | 0, $8 | 0, 4, 406);
+ $inc = $r_014 + 1 | 0;
+ $9 = HEAP16[$maxrank >> 1] | 0;
+ $conv8 = $9 << 16 >> 16;
+ $cmp = ($inc | 0) > ($conv8 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ $r_014 = $inc;
+ label = 6;
+ break;
+ }
+ case 7:
+ return;
+ }
+}
+function _ordercmpf($i0, $i1) {
+ $i0 = $i0 | 0;
+ $i1 = $i1 | 0;
+ return (HEAP32[$i0 >> 2] | 0) - (HEAP32[$i1 >> 2] | 0) | 0;
+}
+function _flat_mval($n) {
+ $n = $n | 0;
+ var $size = 0, $0 = 0, $cmp = 0, $list = 0, $1 = 0, $2 = 0, $tail = 0, $3 = 0, $arrayidx319 = 0, $4 = 0, $tobool20 = 0, $5 = 0, $nn_022 = 0, $i_021 = 0, $tail4 = 0, $6 = 0, $order = 0, $7 = 0, $order7 = 0, $8 = 0, $cmp8 = 0, $_nn_0 = 0, $inc = 0, $arrayidx3 = 0, $9 = 0, $tobool = 0, $nn_0_lcssa = 0, $mval = 0, $10 = 0, $cmp12 = 0, $add = 0, $mval17 = 0, $size20 = 0, $11 = 0, $cmp21 = 0, $list25 = 0, $12 = 0, $13 = 0, $head = 0, $14 = 0, $arrayidx2823 = 0, $15 = 0, $tobool2924 = 0, $16 = 0, $nn_226 = 0, $i_125 = 0, $head31 = 0, $17 = 0, $order33 = 0, $18 = 0, $order35 = 0, $19 = 0, $cmp36 = 0, $_nn_2 = 0, $inc41 = 0, $arrayidx28 = 0, $20 = 0, $tobool29 = 0, $nn_2_lcssa = 0, $mval44 = 0, $21 = 0, $cmp45 = 0, $sub = 0, $mval50 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $n + 204 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp = ($0 | 0) > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $list = $n + 200 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tail = $2 + 16 | 0;
+ $3 = HEAP32[$tail >> 2] | 0;
+ $arrayidx319 = $1 + 4 | 0;
+ $4 = HEAP32[$arrayidx319 >> 2] | 0;
+ $tobool20 = ($4 | 0) == 0;
+ if ($tobool20) {
+ $nn_0_lcssa = $3;
+ label = 5;
+ break;
+ } else {
+ $i_021 = 1;
+ $nn_022 = $3;
+ $5 = $4;
+ label = 4;
+ break;
+ }
+ case 4:
+ $tail4 = $5 + 16 | 0;
+ $6 = HEAP32[$tail4 >> 2] | 0;
+ $order = $6 + 240 | 0;
+ $7 = HEAP32[$order >> 2] | 0;
+ $order7 = $nn_022 + 240 | 0;
+ $8 = HEAP32[$order7 >> 2] | 0;
+ $cmp8 = ($7 | 0) > ($8 | 0);
+ $_nn_0 = $cmp8 ? $6 : $nn_022;
+ $inc = $i_021 + 1 | 0;
+ $arrayidx3 = $1 + ($inc << 2) | 0;
+ $9 = HEAP32[$arrayidx3 >> 2] | 0;
+ $tobool = ($9 | 0) == 0;
+ if ($tobool) {
+ $nn_0_lcssa = $_nn_0;
+ label = 5;
+ break;
+ } else {
+ $i_021 = $inc;
+ $nn_022 = $_nn_0;
+ $5 = $9;
+ label = 4;
+ break;
+ }
+ case 5:
+ $mval = $nn_0_lcssa + 244 | 0;
+ $10 = HEAP32[$mval >> 2] | 0;
+ $cmp12 = ($10 | 0) > -1;
+ if ($cmp12) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ }
+ case 6:
+ $add = $10 + 1 | 0;
+ $mval17 = $n + 244 | 0;
+ HEAP32[$mval17 >> 2] = $add;
+ $retval_0 = 0;
+ label = 12;
+ break;
+ case 7:
+ $size20 = $n + 196 | 0;
+ $11 = HEAP32[$size20 >> 2] | 0;
+ $cmp21 = ($11 | 0) > 0;
+ if ($cmp21) {
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ }
+ case 8:
+ $list25 = $n + 192 | 0;
+ $12 = HEAP32[$list25 >> 2] | 0;
+ $13 = HEAP32[$12 >> 2] | 0;
+ $head = $13 + 12 | 0;
+ $14 = HEAP32[$head >> 2] | 0;
+ $arrayidx2823 = $12 + 4 | 0;
+ $15 = HEAP32[$arrayidx2823 >> 2] | 0;
+ $tobool2924 = ($15 | 0) == 0;
+ if ($tobool2924) {
+ $nn_2_lcssa = $14;
+ label = 10;
+ break;
+ } else {
+ $i_125 = 1;
+ $nn_226 = $14;
+ $16 = $15;
+ label = 9;
+ break;
+ }
+ case 9:
+ $head31 = $16 + 12 | 0;
+ $17 = HEAP32[$head31 >> 2] | 0;
+ $order33 = $17 + 240 | 0;
+ $18 = HEAP32[$order33 >> 2] | 0;
+ $order35 = $nn_226 + 240 | 0;
+ $19 = HEAP32[$order35 >> 2] | 0;
+ $cmp36 = ($18 | 0) < ($19 | 0);
+ $_nn_2 = $cmp36 ? $17 : $nn_226;
+ $inc41 = $i_125 + 1 | 0;
+ $arrayidx28 = $12 + ($inc41 << 2) | 0;
+ $20 = HEAP32[$arrayidx28 >> 2] | 0;
+ $tobool29 = ($20 | 0) == 0;
+ if ($tobool29) {
+ $nn_2_lcssa = $_nn_2;
+ label = 10;
+ break;
+ } else {
+ $i_125 = $inc41;
+ $nn_226 = $_nn_2;
+ $16 = $20;
+ label = 9;
+ break;
+ }
+ case 10:
+ $mval44 = $nn_2_lcssa + 244 | 0;
+ $21 = HEAP32[$mval44 >> 2] | 0;
+ $cmp45 = ($21 | 0) > 0;
+ if ($cmp45) {
+ label = 11;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ }
+ case 11:
+ $sub = $21 - 1 | 0;
+ $mval50 = $n + 244 | 0;
+ HEAP32[$mval50 >> 2] = $sub;
+ $retval_0 = 0;
+ label = 12;
+ break;
+ case 12:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _nodeposcmpf($n0, $n1) {
+ $n0 = $n0 | 0;
+ $n1 = $n1 | 0;
+ return (HEAP32[(HEAP32[$n0 >> 2] | 0) + 240 >> 2] | 0) - (HEAP32[(HEAP32[$n1 >> 2] | 0) + 240 >> 2] | 0) | 0;
+}
+function _mincross_step($g, $pass) {
+ $g = $g | 0;
+ $pass = $pass | 0;
+ var $rem = 0, $cmp = 0, $_ = 0, $rem120 = 0, $cmp6 = 0, $minrank = 0, $0 = 0, $conv10 = 0, $1 = 0, $minrank15 = 0, $2 = 0, $not_cmp17 = 0, $add = 0, $conv10_add = 0, $maxrank22 = 0, $maxrank26 = 0, $3 = 0, $conv27 = 0, $minrank30 = 0, $4 = 0, $maxrank36 = 0, $5 = 0, $not_cmp38 = 0, $sub28 = 0, $conv27_sub28 = 0, $first_2 = 0, $last_0_in_in = 0, $dir_0 = 0, $last_0_in = 0, $last_0 = 0, $add43 = 0, $cmp4421 = 0, $r_022 = 0, $sub46 = 0, $call = 0, $conv47 = 0, $add48 = 0, $cmp44 = 0, $6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rem = ($pass | 0) % 4;
+ $cmp = ($rem | 0) < 2;
+ $_ = $cmp & 1;
+ $rem120 = $pass & 1;
+ $cmp6 = ($rem120 | 0) == 0;
+ if ($cmp6) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $conv10 = $0 << 16 >> 16;
+ $1 = HEAP32[41526] | 0;
+ $minrank15 = $1 + 248 | 0;
+ $2 = HEAP16[$minrank15 >> 1] | 0;
+ $not_cmp17 = $0 << 16 >> 16 <= $2 << 16 >> 16;
+ $add = $not_cmp17 & 1;
+ $conv10_add = $add + $conv10 | 0;
+ $maxrank22 = $g + 250 | 0;
+ $dir_0 = 1;
+ $last_0_in_in = $maxrank22;
+ $first_2 = $conv10_add;
+ label = 5;
+ break;
+ case 4:
+ $maxrank26 = $g + 250 | 0;
+ $3 = HEAP16[$maxrank26 >> 1] | 0;
+ $conv27 = $3 << 16 >> 16;
+ $minrank30 = $g + 248 | 0;
+ $4 = HEAP32[41526] | 0;
+ $maxrank36 = $4 + 250 | 0;
+ $5 = HEAP16[$maxrank36 >> 1] | 0;
+ $not_cmp38 = $3 << 16 >> 16 >= $5 << 16 >> 16;
+ $sub28 = $not_cmp38 << 31 >> 31;
+ $conv27_sub28 = $sub28 + $conv27 | 0;
+ $dir_0 = -1;
+ $last_0_in_in = $minrank30;
+ $first_2 = $conv27_sub28;
+ label = 5;
+ break;
+ case 5:
+ $last_0_in = HEAP16[$last_0_in_in >> 1] | 0;
+ $last_0 = $last_0_in << 16 >> 16;
+ $add43 = $last_0 + $dir_0 | 0;
+ $cmp4421 = ($first_2 | 0) == ($add43 | 0);
+ if ($cmp4421) {
+ label = 7;
+ break;
+ } else {
+ $r_022 = $first_2;
+ label = 6;
+ break;
+ }
+ case 6:
+ $sub46 = $r_022 - $dir_0 | 0;
+ $call = _medians($g, $r_022, $sub46) | 0;
+ $conv47 = $call & 255;
+ _reorder($g, $r_022, $_, $conv47);
+ $add48 = $r_022 + $dir_0 | 0;
+ $cmp44 = ($add48 | 0) == ($add43 | 0);
+ if ($cmp44) {
+ label = 7;
+ break;
+ } else {
+ $r_022 = $add48;
+ label = 6;
+ break;
+ }
+ case 7:
+ $6 = $_ ^ 1;
+ _transpose($g, $6);
+ return;
+ }
+}
+function _balanceNodes($g, $r, $v, $w) {
+ $g = $g | 0;
+ $r = $r | 0;
+ $v = $v | 0;
+ $w = $w | 0;
+ var $node_type = 0, $0 = 0, $node_type2 = 0, $1 = 0, $cmp = 0, $rank = 0, $2 = 0, $n79 = 0, $3 = 0, $cmp680 = 0, $4 = 0, $cmp2888 = 0, $5 = 0, $n = 0, $6 = 0, $7 = 0, $i_083 = 0, $cntOri_082 = 0, $cntDummy_081 = 0, $v11 = 0, $8 = 0, $arrayidx12 = 0, $9 = 0, $node_type14 = 0, $10 = 0, $cmp16 = 0, $11 = 0, $inc19 = 0, $cntDummy_1 = 0, $inc = 0, $cntOri_1 = 0, $inc21 = 0, $cmp6 = 0, $cmp22 = 0, $12 = 0, $cmp28 = 0, $v_w = 0, $cmp2889 = 0, $w_v = 0, $s_0 = 0, $13 = 0, $n4774 = 0, $14 = 0, $cmp4875 = 0, $15 = 0, $n47 = 0, $16 = 0, $17 = 0, $i_177 = 0, $sepIndex_076 = 0, $v54 = 0, $18 = 0, $arrayidx55 = 0, $19 = 0, $cmp56 = 0, $i_1_sepIndex_0 = 0, $inc61 = 0, $cmp48 = 0, $sepIndex_0_lcssa = 0, $node_type64 = 0, $20 = 0, $cmp66 = 0, $cond = 0, $k_0 = 0, $i_2_in = 0, $i_2 = 0, $cmp69 = 0, $21 = 0, $n92 = 0, $22 = 0, $v99 = 0, $23 = 0, $v75 = 0, $24 = 0, $arrayidx76 = 0, $25 = 0, $node_type78 = 0, $26 = 0, $conv79 = 0, $cmp80 = 0, $inc83 = 0, $m_0 = 0, $i_3_in = 0, $i_3 = 0, $cmp93 = 0, $27 = 0, $arrayidx100 = 0, $28 = 0, $node_type102 = 0, $29 = 0, $conv103 = 0, $cmp104 = 0, $inc107 = 0, $30 = 0, $n11770 = 0, $31 = 0, $cmp11871 = 0, $32 = 0, $n117 = 0, $33 = 0, $sepIndex_2_lcssa = 0, $34 = 0, $i_473 = 0, $sepIndex_272 = 0, $v124 = 0, $35 = 0, $arrayidx125 = 0, $36 = 0, $cmp126 = 0, $i_4_sepIndex_2 = 0, $inc131 = 0, $cmp118 = 0, $k1_0 = 0, $i_5_in = 0, $i_5 = 0, $cmp135 = 0, $37 = 0, $n160 = 0, $38 = 0, $v167 = 0, $39 = 0, $v141 = 0, $40 = 0, $arrayidx142 = 0, $41 = 0, $node_type144 = 0, $42 = 0, $conv145 = 0, $cmp146 = 0, $inc149 = 0, $m1_0 = 0, $i_6_in = 0, $i_6 = 0, $cmp161 = 0, $43 = 0, $arrayidx168 = 0, $44 = 0, $node_type170 = 0, $45 = 0, $conv171 = 0, $cmp172 = 0, $inc175 = 0, $sub181 = 0, $ispos = 0, $neg = 0, $call = 0, $sub182 = 0, $ispos68 = 0, $neg69 = 0, $call183 = 0, $cmp184 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $v + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $node_type2 = $w + 162 | 0;
+ $1 = HEAP8[$node_type2] | 0;
+ $cmp = $0 << 24 >> 24 == $1 << 24 >> 24;
+ if ($cmp) {
+ label = 30;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $rank = $g + 224 | 0;
+ $2 = HEAP32[$rank >> 2] | 0;
+ $n79 = $2 + ($r * 44 & -1) | 0;
+ $3 = HEAP32[$n79 >> 2] | 0;
+ $cmp680 = ($3 | 0) > 0;
+ if ($cmp680) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $4 = HEAP8[$node_type] | 0;
+ $cmp2888 = $4 << 24 >> 24 == 0;
+ $cmp2889 = $cmp2888;
+ label = 9;
+ break;
+ case 5:
+ $5 = HEAP32[$rank >> 2] | 0;
+ $n = $5 + ($r * 44 & -1) | 0;
+ $6 = HEAP32[$n >> 2] | 0;
+ $cntDummy_081 = 0;
+ $cntOri_082 = 0;
+ $i_083 = 0;
+ $7 = $2;
+ label = 6;
+ break;
+ case 6:
+ $v11 = $7 + ($r * 44 & -1) + 4 | 0;
+ $8 = HEAP32[$v11 >> 2] | 0;
+ $arrayidx12 = $8 + ($i_083 << 2) | 0;
+ $9 = HEAP32[$arrayidx12 >> 2] | 0;
+ $node_type14 = $9 + 162 | 0;
+ $10 = HEAP8[$node_type14] | 0;
+ $cmp16 = $10 << 24 >> 24 == 0;
+ $11 = $cmp16 & 1;
+ $inc19 = $11 ^ 1;
+ $cntDummy_1 = $inc19 + $cntDummy_081 | 0;
+ $inc = $cmp16 & 1;
+ $cntOri_1 = $inc + $cntOri_082 | 0;
+ $inc21 = $i_083 + 1 | 0;
+ $cmp6 = ($inc21 | 0) < ($6 | 0);
+ if ($cmp6) {
+ $cntDummy_081 = $cntDummy_1;
+ $cntOri_082 = $cntOri_1;
+ $i_083 = $inc21;
+ $7 = $5;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $cmp22 = ($cntOri_1 | 0) < ($cntDummy_1 | 0);
+ $12 = HEAP8[$node_type] | 0;
+ $cmp28 = $12 << 24 >> 24 == 0;
+ if ($cmp22) {
+ label = 8;
+ break;
+ } else {
+ $cmp2889 = $cmp28;
+ label = 9;
+ break;
+ }
+ case 8:
+ $v_w = $cmp28 ? $v : $w;
+ $s_0 = $v_w;
+ label = 10;
+ break;
+ case 9:
+ $w_v = $cmp2889 ? $w : $v;
+ $s_0 = $w_v;
+ label = 10;
+ break;
+ case 10:
+ $13 = HEAP32[$rank >> 2] | 0;
+ $n4774 = $13 + ($r * 44 & -1) | 0;
+ $14 = HEAP32[$n4774 >> 2] | 0;
+ $cmp4875 = ($14 | 0) > 0;
+ if ($cmp4875) {
+ label = 11;
+ break;
+ } else {
+ $sepIndex_0_lcssa = 0;
+ label = 13;
+ break;
+ }
+ case 11:
+ $15 = HEAP32[$rank >> 2] | 0;
+ $n47 = $15 + ($r * 44 & -1) | 0;
+ $16 = HEAP32[$n47 >> 2] | 0;
+ $sepIndex_076 = 0;
+ $i_177 = 0;
+ $17 = $13;
+ label = 12;
+ break;
+ case 12:
+ $v54 = $17 + ($r * 44 & -1) + 4 | 0;
+ $18 = HEAP32[$v54 >> 2] | 0;
+ $arrayidx55 = $18 + ($i_177 << 2) | 0;
+ $19 = HEAP32[$arrayidx55 >> 2] | 0;
+ $cmp56 = ($19 | 0) == ($s_0 | 0);
+ $i_1_sepIndex_0 = $cmp56 ? $i_177 : $sepIndex_076;
+ $inc61 = $i_177 + 1 | 0;
+ $cmp48 = ($inc61 | 0) < ($16 | 0);
+ if ($cmp48) {
+ $sepIndex_076 = $i_1_sepIndex_0;
+ $i_177 = $inc61;
+ $17 = $15;
+ label = 12;
+ break;
+ } else {
+ $sepIndex_0_lcssa = $i_1_sepIndex_0;
+ label = 13;
+ break;
+ }
+ case 13:
+ $node_type64 = $s_0 + 162 | 0;
+ $20 = HEAP8[$node_type64] | 0;
+ $cmp66 = $20 << 24 >> 24 == 0;
+ $cond = $cmp66 & 1;
+ $i_2_in = $sepIndex_0_lcssa;
+ $k_0 = 0;
+ label = 14;
+ break;
+ case 14:
+ $i_2 = $i_2_in - 1 | 0;
+ $cmp69 = ($i_2_in | 0) > 0;
+ if ($cmp69) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $21 = HEAP32[$rank >> 2] | 0;
+ $n92 = $21 + ($r * 44 & -1) | 0;
+ $22 = HEAP32[$n92 >> 2] | 0;
+ $v99 = $21 + ($r * 44 & -1) + 4 | 0;
+ $i_3_in = $sepIndex_0_lcssa;
+ $m_0 = 0;
+ label = 17;
+ break;
+ case 16:
+ $23 = HEAP32[$rank >> 2] | 0;
+ $v75 = $23 + ($r * 44 & -1) + 4 | 0;
+ $24 = HEAP32[$v75 >> 2] | 0;
+ $arrayidx76 = $24 + ($i_2 << 2) | 0;
+ $25 = HEAP32[$arrayidx76 >> 2] | 0;
+ $node_type78 = $25 + 162 | 0;
+ $26 = HEAP8[$node_type78] | 0;
+ $conv79 = $26 << 24 >> 24;
+ $cmp80 = ($conv79 | 0) == ($cond | 0);
+ $inc83 = $k_0 + 1 | 0;
+ if ($cmp80) {
+ $i_2_in = $i_2;
+ $k_0 = $inc83;
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 17:
+ $i_3 = $i_3_in + 1 | 0;
+ $cmp93 = ($i_3 | 0) < ($22 | 0);
+ if ($cmp93) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $27 = HEAP32[$v99 >> 2] | 0;
+ $arrayidx100 = $27 + ($i_3 << 2) | 0;
+ $28 = HEAP32[$arrayidx100 >> 2] | 0;
+ $node_type102 = $28 + 162 | 0;
+ $29 = HEAP8[$node_type102] | 0;
+ $conv103 = $29 << 24 >> 24;
+ $cmp104 = ($conv103 | 0) == ($cond | 0);
+ $inc107 = $m_0 + 1 | 0;
+ if ($cmp104) {
+ $i_3_in = $i_3;
+ $m_0 = $inc107;
+ label = 17;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ _exchange($v, $w);
+ $30 = HEAP32[$rank >> 2] | 0;
+ $n11770 = $30 + ($r * 44 & -1) | 0;
+ $31 = HEAP32[$n11770 >> 2] | 0;
+ $cmp11871 = ($31 | 0) > 0;
+ if ($cmp11871) {
+ label = 20;
+ break;
+ } else {
+ $sepIndex_2_lcssa = $sepIndex_0_lcssa;
+ label = 21;
+ break;
+ }
+ case 20:
+ $32 = HEAP32[$rank >> 2] | 0;
+ $n117 = $32 + ($r * 44 & -1) | 0;
+ $33 = HEAP32[$n117 >> 2] | 0;
+ $sepIndex_272 = $sepIndex_0_lcssa;
+ $i_473 = 0;
+ $34 = $30;
+ label = 22;
+ break;
+ case 21:
+ $i_5_in = $sepIndex_2_lcssa;
+ $k1_0 = 0;
+ label = 23;
+ break;
+ case 22:
+ $v124 = $34 + ($r * 44 & -1) + 4 | 0;
+ $35 = HEAP32[$v124 >> 2] | 0;
+ $arrayidx125 = $35 + ($i_473 << 2) | 0;
+ $36 = HEAP32[$arrayidx125 >> 2] | 0;
+ $cmp126 = ($36 | 0) == ($s_0 | 0);
+ $i_4_sepIndex_2 = $cmp126 ? $i_473 : $sepIndex_272;
+ $inc131 = $i_473 + 1 | 0;
+ $cmp118 = ($inc131 | 0) < ($33 | 0);
+ if ($cmp118) {
+ $sepIndex_272 = $i_4_sepIndex_2;
+ $i_473 = $inc131;
+ $34 = $32;
+ label = 22;
+ break;
+ } else {
+ $sepIndex_2_lcssa = $i_4_sepIndex_2;
+ label = 21;
+ break;
+ }
+ case 23:
+ $i_5 = $i_5_in - 1 | 0;
+ $cmp135 = ($i_5_in | 0) > 0;
+ if ($cmp135) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $37 = HEAP32[$rank >> 2] | 0;
+ $n160 = $37 + ($r * 44 & -1) | 0;
+ $38 = HEAP32[$n160 >> 2] | 0;
+ $v167 = $37 + ($r * 44 & -1) + 4 | 0;
+ $i_6_in = $sepIndex_2_lcssa;
+ $m1_0 = 0;
+ label = 26;
+ break;
+ case 25:
+ $39 = HEAP32[$rank >> 2] | 0;
+ $v141 = $39 + ($r * 44 & -1) + 4 | 0;
+ $40 = HEAP32[$v141 >> 2] | 0;
+ $arrayidx142 = $40 + ($i_5 << 2) | 0;
+ $41 = HEAP32[$arrayidx142 >> 2] | 0;
+ $node_type144 = $41 + 162 | 0;
+ $42 = HEAP8[$node_type144] | 0;
+ $conv145 = $42 << 24 >> 24;
+ $cmp146 = ($conv145 | 0) == ($cond | 0);
+ $inc149 = $k1_0 + 1 | 0;
+ if ($cmp146) {
+ $i_5_in = $i_5;
+ $k1_0 = $inc149;
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 26:
+ $i_6 = $i_6_in + 1 | 0;
+ $cmp161 = ($i_6 | 0) < ($38 | 0);
+ if ($cmp161) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $43 = HEAP32[$v167 >> 2] | 0;
+ $arrayidx168 = $43 + ($i_6 << 2) | 0;
+ $44 = HEAP32[$arrayidx168 >> 2] | 0;
+ $node_type170 = $44 + 162 | 0;
+ $45 = HEAP8[$node_type170] | 0;
+ $conv171 = $45 << 24 >> 24;
+ $cmp172 = ($conv171 | 0) == ($cond | 0);
+ $inc175 = $m1_0 + 1 | 0;
+ if ($cmp172) {
+ $i_6_in = $i_6;
+ $m1_0 = $inc175;
+ label = 26;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $sub181 = $k1_0 - $m1_0 | 0;
+ $ispos = ($sub181 | 0) > -1;
+ $neg = -$sub181 | 0;
+ $call = $ispos ? $sub181 : $neg;
+ $sub182 = $k_0 - $m_0 | 0;
+ $ispos68 = ($sub182 | 0) > -1;
+ $neg69 = -$sub182 | 0;
+ $call183 = $ispos68 ? $sub182 : $neg69;
+ $cmp184 = ($call | 0) > ($call183 | 0);
+ if ($cmp184) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ _exchange($v, $w);
+ label = 30;
+ break;
+ case 30:
+ return;
+ }
+}
+function _medians($g, $r0, $r1) {
+ $g = $g | 0;
+ $r0 = $r0 | 0;
+ $r1 = $r1 | 0;
+ var $0 = 0, $rank = 0, $1 = 0, $v1 = 0, $2 = 0, $n574 = 0, $3 = 0, $cmp76 = 0, $cmp7 = 0, $4 = 0, $arrayidx56 = 0, $5 = 0, $n10359 = 0, $6 = 0, $cmp10460 = 0, $i_077 = 0, $arrayidx6 = 0, $7 = 0, $list10 = 0, $8 = 0, $9 = 0, $tobool70 = 0, $list25 = 0, $10 = 0, $11 = 0, $tobool2764 = 0, $12 = 0, $j_072 = 0, $j0_071 = 0, $xpenalty = 0, $13 = 0, $cmp14 = 0, $head = 0, $14 = 0, $order = 0, $15 = 0, $mul = 0, $order19 = 0, $16 = 0, $conv20 = 0, $add = 0, $inc = 0, $arrayidx21 = 0, $j_1 = 0, $inc22 = 0, $17 = 0, $arrayidx11 = 0, $18 = 0, $tobool = 0, $19 = 0, $j_266 = 0, $j0_165 = 0, $xpenalty30 = 0, $20 = 0, $cmp32 = 0, $tail = 0, $21 = 0, $order36 = 0, $22 = 0, $mul37 = 0, $order39 = 0, $23 = 0, $conv40 = 0, $add41 = 0, $inc42 = 0, $arrayidx43 = 0, $j_3 = 0, $inc46 = 0, $24 = 0, $arrayidx26 = 0, $25 = 0, $tobool27 = 0, $j_4 = 0, $mval = 0, $26 = 0, $mval53 = 0, $27 = 0, $28 = 0, $add57 = 0, $div = 0, $mval59 = 0, $rem58 = 0, $tobool60 = 0, $div62 = 0, $arrayidx63 = 0, $29 = 0, $mval65 = 0, $sub = 0, $sub68 = 0, $arrayidx69 = 0, $30 = 0, $arrayidx70 = 0, $31 = 0, $sub71 = 0, $arrayidx72 = 0, $32 = 0, $33 = 0, $sub74 = 0, $cmp75 = 0, $add80 = 0, $div81 = 0, $mval83 = 0, $mul86 = 0, $mul88 = 0, $add89 = 0, $add90 = 0, $div91 = 0, $mval93 = 0, $inc97 = 0, $34 = 0, $n5 = 0, $35 = 0, $cmp = 0, $i_162 = 0, $hasfixed_061 = 0, $arrayidx107 = 0, $36 = 0, $size = 0, $37 = 0, $cmp110 = 0, $size114 = 0, $38 = 0, $cmp115 = 0, $call = 0, $conv118 = 0, $or = 0, $conv119 = 0, $hasfixed_1 = 0, $inc122 = 0, $39 = 0, $n103 = 0, $40 = 0, $cmp104 = 0, $hasfixed_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[41344] | 0;
+ $rank = $g + 224 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $v1 = $1 + ($r0 * 44 & -1) + 4 | 0;
+ $2 = HEAP32[$v1 >> 2] | 0;
+ $n574 = $1 + ($r0 * 44 & -1) | 0;
+ $3 = HEAP32[$n574 >> 2] | 0;
+ $cmp76 = ($3 | 0) > 0;
+ if ($cmp76) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $cmp7 = ($r1 | 0) > ($r0 | 0);
+ $4 = $0;
+ $arrayidx56 = $0 + 4 | 0;
+ $i_077 = 0;
+ label = 5;
+ break;
+ case 4:
+ $5 = HEAP32[$rank >> 2] | 0;
+ $n10359 = $5 + ($r0 * 44 & -1) | 0;
+ $6 = HEAP32[$n10359 >> 2] | 0;
+ $cmp10460 = ($6 | 0) > 0;
+ if ($cmp10460) {
+ $hasfixed_061 = 0;
+ $i_162 = 0;
+ label = 24;
+ break;
+ } else {
+ $hasfixed_0_lcssa = 0;
+ label = 28;
+ break;
+ }
+ case 5:
+ $arrayidx6 = $2 + ($i_077 << 2) | 0;
+ $7 = HEAP32[$arrayidx6 >> 2] | 0;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $list10 = $7 + 184 | 0;
+ $8 = HEAP32[$list10 >> 2] | 0;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $tobool70 = ($9 | 0) == 0;
+ if ($tobool70) {
+ label = 15;
+ break;
+ } else {
+ $j0_071 = 0;
+ $j_072 = 0;
+ $12 = $9;
+ label = 8;
+ break;
+ }
+ case 7:
+ $list25 = $7 + 176 | 0;
+ $10 = HEAP32[$list25 >> 2] | 0;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $tobool2764 = ($11 | 0) == 0;
+ if ($tobool2764) {
+ label = 15;
+ break;
+ } else {
+ $j0_165 = 0;
+ $j_266 = 0;
+ $19 = $11;
+ label = 11;
+ break;
+ }
+ case 8:
+ $xpenalty = $12 + 170 | 0;
+ $13 = HEAP16[$xpenalty >> 1] | 0;
+ $cmp14 = $13 << 16 >> 16 > 0;
+ if ($cmp14) {
+ label = 9;
+ break;
+ } else {
+ $j_1 = $j_072;
+ label = 10;
+ break;
+ }
+ case 9:
+ $head = $12 + 12 | 0;
+ $14 = HEAP32[$head >> 2] | 0;
+ $order = $14 + 240 | 0;
+ $15 = HEAP32[$order >> 2] | 0;
+ $mul = $15 << 8;
+ $order19 = $12 + 104 | 0;
+ $16 = HEAP8[$order19] | 0;
+ $conv20 = $16 & 255;
+ $add = $conv20 | $mul;
+ $inc = $j_072 + 1 | 0;
+ $arrayidx21 = $0 + ($j_072 << 2) | 0;
+ HEAP32[$arrayidx21 >> 2] = $add;
+ $j_1 = $inc;
+ label = 10;
+ break;
+ case 10:
+ $inc22 = $j0_071 + 1 | 0;
+ $17 = HEAP32[$list10 >> 2] | 0;
+ $arrayidx11 = $17 + ($inc22 << 2) | 0;
+ $18 = HEAP32[$arrayidx11 >> 2] | 0;
+ $tobool = ($18 | 0) == 0;
+ if ($tobool) {
+ $j_4 = $j_1;
+ label = 14;
+ break;
+ } else {
+ $j0_071 = $inc22;
+ $j_072 = $j_1;
+ $12 = $18;
+ label = 8;
+ break;
+ }
+ case 11:
+ $xpenalty30 = $19 + 170 | 0;
+ $20 = HEAP16[$xpenalty30 >> 1] | 0;
+ $cmp32 = $20 << 16 >> 16 > 0;
+ if ($cmp32) {
+ label = 12;
+ break;
+ } else {
+ $j_3 = $j_266;
+ label = 13;
+ break;
+ }
+ case 12:
+ $tail = $19 + 16 | 0;
+ $21 = HEAP32[$tail >> 2] | 0;
+ $order36 = $21 + 240 | 0;
+ $22 = HEAP32[$order36 >> 2] | 0;
+ $mul37 = $22 << 8;
+ $order39 = $19 + 64 | 0;
+ $23 = HEAP8[$order39] | 0;
+ $conv40 = $23 & 255;
+ $add41 = $conv40 | $mul37;
+ $inc42 = $j_266 + 1 | 0;
+ $arrayidx43 = $0 + ($j_266 << 2) | 0;
+ HEAP32[$arrayidx43 >> 2] = $add41;
+ $j_3 = $inc42;
+ label = 13;
+ break;
+ case 13:
+ $inc46 = $j0_165 + 1 | 0;
+ $24 = HEAP32[$list25 >> 2] | 0;
+ $arrayidx26 = $24 + ($inc46 << 2) | 0;
+ $25 = HEAP32[$arrayidx26 >> 2] | 0;
+ $tobool27 = ($25 | 0) == 0;
+ if ($tobool27) {
+ $j_4 = $j_3;
+ label = 14;
+ break;
+ } else {
+ $j0_165 = $inc46;
+ $j_266 = $j_3;
+ $19 = $25;
+ label = 11;
+ break;
+ }
+ case 14:
+ if (($j_4 | 0) == 0) {
+ label = 15;
+ break;
+ } else if (($j_4 | 0) == 1) {
+ label = 16;
+ break;
+ } else if (($j_4 | 0) == 2) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 15:
+ $mval = $7 + 244 | 0;
+ HEAP32[$mval >> 2] = -1;
+ label = 23;
+ break;
+ case 16:
+ $26 = HEAP32[$0 >> 2] | 0;
+ $mval53 = $7 + 244 | 0;
+ HEAP32[$mval53 >> 2] = $26;
+ label = 23;
+ break;
+ case 17:
+ $27 = HEAP32[$0 >> 2] | 0;
+ $28 = HEAP32[$arrayidx56 >> 2] | 0;
+ $add57 = $28 + $27 | 0;
+ $div = ($add57 | 0) / 2 & -1;
+ $mval59 = $7 + 244 | 0;
+ HEAP32[$mval59 >> 2] = $div;
+ label = 23;
+ break;
+ case 18:
+ _qsort($4 | 0, $j_4 | 0, 4, 136);
+ $rem58 = $j_4 & 1;
+ $tobool60 = ($rem58 | 0) == 0;
+ $div62 = ($j_4 | 0) / 2 & -1;
+ if ($tobool60) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $arrayidx63 = $0 + ($div62 << 2) | 0;
+ $29 = HEAP32[$arrayidx63 >> 2] | 0;
+ $mval65 = $7 + 244 | 0;
+ HEAP32[$mval65 >> 2] = $29;
+ label = 23;
+ break;
+ case 20:
+ $sub = $div62 - 1 | 0;
+ $sub68 = $j_4 - 1 | 0;
+ $arrayidx69 = $0 + ($sub68 << 2) | 0;
+ $30 = HEAP32[$arrayidx69 >> 2] | 0;
+ $arrayidx70 = $0 + ($div62 << 2) | 0;
+ $31 = HEAP32[$arrayidx70 >> 2] | 0;
+ $sub71 = $30 - $31 | 0;
+ $arrayidx72 = $0 + ($sub << 2) | 0;
+ $32 = HEAP32[$arrayidx72 >> 2] | 0;
+ $33 = HEAP32[$0 >> 2] | 0;
+ $sub74 = $32 - $33 | 0;
+ $cmp75 = ($sub74 | 0) == ($sub71 | 0);
+ if ($cmp75) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $add80 = $32 + $31 | 0;
+ $div81 = ($add80 | 0) / 2 & -1;
+ $mval83 = $7 + 244 | 0;
+ HEAP32[$mval83 >> 2] = $div81;
+ label = 23;
+ break;
+ case 22:
+ $mul86 = Math_imul($32, $sub71);
+ $mul88 = Math_imul($sub74, $31);
+ $add89 = $mul88 + $mul86 | 0;
+ $add90 = $sub74 + $sub71 | 0;
+ $div91 = ($add89 | 0) / ($add90 | 0) & -1;
+ $mval93 = $7 + 244 | 0;
+ HEAP32[$mval93 >> 2] = $div91;
+ label = 23;
+ break;
+ case 23:
+ $inc97 = $i_077 + 1 | 0;
+ $34 = HEAP32[$rank >> 2] | 0;
+ $n5 = $34 + ($r0 * 44 & -1) | 0;
+ $35 = HEAP32[$n5 >> 2] | 0;
+ $cmp = ($inc97 | 0) < ($35 | 0);
+ if ($cmp) {
+ $i_077 = $inc97;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 24:
+ $arrayidx107 = $2 + ($i_162 << 2) | 0;
+ $36 = HEAP32[$arrayidx107 >> 2] | 0;
+ $size = $36 + 188 | 0;
+ $37 = HEAP32[$size >> 2] | 0;
+ $cmp110 = ($37 | 0) == 0;
+ if ($cmp110) {
+ label = 25;
+ break;
+ } else {
+ $hasfixed_1 = $hasfixed_061;
+ label = 27;
+ break;
+ }
+ case 25:
+ $size114 = $36 + 180 | 0;
+ $38 = HEAP32[$size114 >> 2] | 0;
+ $cmp115 = ($38 | 0) == 0;
+ if ($cmp115) {
+ label = 26;
+ break;
+ } else {
+ $hasfixed_1 = $hasfixed_061;
+ label = 27;
+ break;
+ }
+ case 26:
+ $call = _flat_mval($36) | 0;
+ $conv118 = $hasfixed_061 & 255;
+ $or = $call | $conv118;
+ $conv119 = $or & 255;
+ $hasfixed_1 = $conv119;
+ label = 27;
+ break;
+ case 27:
+ $inc122 = $i_162 + 1 | 0;
+ $39 = HEAP32[$rank >> 2] | 0;
+ $n103 = $39 + ($r0 * 44 & -1) | 0;
+ $40 = HEAP32[$n103 >> 2] | 0;
+ $cmp104 = ($inc122 | 0) < ($40 | 0);
+ if ($cmp104) {
+ $hasfixed_061 = $hasfixed_1;
+ $i_162 = $inc122;
+ label = 24;
+ break;
+ } else {
+ $hasfixed_0_lcssa = $hasfixed_1;
+ label = 28;
+ break;
+ }
+ case 28:
+ return $hasfixed_0_lcssa | 0;
+ }
+ return 0;
+}
+function _reorder($g, $r, $reverse, $hasfixed) {
+ $g = $g | 0;
+ $r = $r | 0;
+ $reverse = $reverse | 0;
+ $hasfixed = $hasfixed | 0;
+ var $rank = 0, $0 = 0, $v = 0, $1 = 0, $n = 0, $2 = 0, $cmp56 = 0, $add_ptr = 0, $3 = 0, $4 = 0, $tobool55 = 0, $nelt_062_in = 0, $changed_061 = 0, $ep_057 = 0, $nelt_062 = 0, $cmp84452 = 0, $changed_1_ph54 = 0, $lp_0_ph53 = 0, $lp_1 = 0, $cmp10 = 0, $5 = 0, $mval = 0, $6 = 0, $cmp12 = 0, $incdec_ptr = 0, $sawclust_0_ph = 0, $lp_1_pn_ph = 0, $tobool = 0, $lp_1_pn = 0, $rp_0 = 0, $cmp17 = 0, $7 = 0, $clust = 0, $8 = 0, $tobool20 = 0, $9 = 0, $10 = 0, $call = 0, $tobool23 = 0, $mval27 = 0, $11 = 0, $cmp28 = 0, $clust33 = 0, $12 = 0, $tobool34 = 0, $sawclust_0_ = 0, $muststay_0 = 0, $cmp43 = 0, $13 = 0, $mval47 = 0, $14 = 0, $15 = 0, $mval49 = 0, $16 = 0, $cmp50 = 0, $cmp52 = 0, $or_cond = 0, $or_cond77 = 0, $cmp8 = 0, $17 = 0, $18 = 0, $inc = 0, $cmp844 = 0, $changed_1_ph50 = 0, $incdec_ptr66 = 0, $ep_1 = 0, $cmp = 0, $tobool70 = 0, $19 = 0, $rank73 = 0, $20 = 0, $valid = 0, $cmp75 = 0, $sub78 = 0, $21 = 0, $rank80 = 0, $22 = 0, $valid82 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $g + 224 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $v = $0 + ($r * 44 & -1) + 4 | 0;
+ $1 = HEAP32[$v >> 2] | 0;
+ $n = $0 + ($r * 44 & -1) | 0;
+ $2 = HEAP32[$n >> 2] | 0;
+ $cmp56 = ($2 | 0) > 0;
+ if ($cmp56) {
+ label = 3;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 3:
+ $add_ptr = $1 + ($2 << 2) | 0;
+ $3 = $hasfixed | $reverse;
+ $4 = ($3 | 0) == 0;
+ $tobool55 = ($reverse | 0) == 0;
+ $ep_057 = $add_ptr;
+ $changed_061 = 0;
+ $nelt_062_in = $2;
+ label = 4;
+ break;
+ case 4:
+ $nelt_062 = $nelt_062_in - 1 | 0;
+ $cmp84452 = $1 >>> 0 < $ep_057 >>> 0;
+ if ($cmp84452) {
+ $lp_0_ph53 = $1;
+ $changed_1_ph54 = $changed_061;
+ label = 5;
+ break;
+ } else {
+ $changed_1_ph50 = $changed_061;
+ label = 20;
+ break;
+ }
+ case 5:
+ $lp_1 = $lp_0_ph53;
+ label = 6;
+ break;
+ case 6:
+ $cmp10 = $lp_1 >>> 0 < $ep_057 >>> 0;
+ if ($cmp10) {
+ label = 7;
+ break;
+ } else {
+ $changed_1_ph50 = $changed_1_ph54;
+ label = 20;
+ break;
+ }
+ case 7:
+ $5 = HEAP32[$lp_1 >> 2] | 0;
+ $mval = $5 + 244 | 0;
+ $6 = HEAP32[$mval >> 2] | 0;
+ $cmp12 = ($6 | 0) < 0;
+ $incdec_ptr = $lp_1 + 4 | 0;
+ if ($cmp12) {
+ $lp_1 = $incdec_ptr;
+ label = 6;
+ break;
+ } else {
+ $lp_1_pn_ph = $lp_1;
+ $sawclust_0_ph = 0;
+ label = 8;
+ break;
+ }
+ case 8:
+ $tobool = $sawclust_0_ph << 24 >> 24 == 0;
+ $lp_1_pn = $lp_1_pn_ph;
+ label = 9;
+ break;
+ case 9:
+ $rp_0 = $lp_1_pn + 4 | 0;
+ $cmp17 = $rp_0 >>> 0 < $ep_057 >>> 0;
+ if ($cmp17) {
+ label = 10;
+ break;
+ } else {
+ $changed_1_ph50 = $changed_1_ph54;
+ label = 20;
+ break;
+ }
+ case 10:
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $7 = HEAP32[$rp_0 >> 2] | 0;
+ $clust = $7 + 216 | 0;
+ $8 = HEAP32[$clust >> 2] | 0;
+ $tobool20 = ($8 | 0) == 0;
+ if ($tobool20) {
+ label = 12;
+ break;
+ } else {
+ $lp_1_pn = $rp_0;
+ label = 9;
+ break;
+ }
+ case 12:
+ $9 = HEAP32[$lp_1 >> 2] | 0;
+ $10 = HEAP32[$rp_0 >> 2] | 0;
+ $call = _left2right($g, $9, $10) | 0;
+ $tobool23 = ($call | 0) == 0;
+ if ($tobool23) {
+ label = 13;
+ break;
+ } else {
+ $muststay_0 = 1;
+ label = 15;
+ break;
+ }
+ case 13:
+ $mval27 = $10 + 244 | 0;
+ $11 = HEAP32[$mval27 >> 2] | 0;
+ $cmp28 = ($11 | 0) > -1;
+ if ($cmp28) {
+ $muststay_0 = 0;
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $clust33 = $10 + 216 | 0;
+ $12 = HEAP32[$clust33 >> 2] | 0;
+ $tobool34 = ($12 | 0) == 0;
+ $sawclust_0_ = $tobool34 ? $sawclust_0_ph : 1;
+ $lp_1_pn_ph = $rp_0;
+ $sawclust_0_ph = $sawclust_0_;
+ label = 8;
+ break;
+ case 15:
+ if ($cmp17) {
+ label = 16;
+ break;
+ } else {
+ $changed_1_ph50 = $changed_1_ph54;
+ label = 20;
+ break;
+ }
+ case 16:
+ $cmp43 = ($muststay_0 | 0) == 0;
+ if ($cmp43) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $13 = HEAP32[$lp_1 >> 2] | 0;
+ $mval47 = $13 + 244 | 0;
+ $14 = HEAP32[$mval47 >> 2] | 0;
+ $15 = HEAP32[$rp_0 >> 2] | 0;
+ $mval49 = $15 + 244 | 0;
+ $16 = HEAP32[$mval49 >> 2] | 0;
+ $cmp50 = ($14 | 0) <= ($16 | 0);
+ $cmp52 = ($14 | 0) != ($16 | 0);
+ $or_cond = $cmp52 | $tobool55;
+ $or_cond77 = $cmp50 & $or_cond;
+ if ($or_cond77) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $cmp8 = $rp_0 >>> 0 < $ep_057 >>> 0;
+ if ($cmp8) {
+ $lp_1 = $rp_0;
+ label = 6;
+ break;
+ } else {
+ $changed_1_ph50 = $changed_1_ph54;
+ label = 20;
+ break;
+ }
+ case 19:
+ $17 = HEAP32[$lp_1 >> 2] | 0;
+ $18 = HEAP32[$rp_0 >> 2] | 0;
+ _exchange($17, $18);
+ $inc = $changed_1_ph54 + 1 | 0;
+ $cmp844 = $rp_0 >>> 0 < $ep_057 >>> 0;
+ if ($cmp844) {
+ $lp_0_ph53 = $rp_0;
+ $changed_1_ph54 = $inc;
+ label = 5;
+ break;
+ } else {
+ $changed_1_ph50 = $inc;
+ label = 20;
+ break;
+ }
+ case 20:
+ $incdec_ptr66 = $ep_057 - 4 | 0;
+ $ep_1 = $4 ? $incdec_ptr66 : $ep_057;
+ $cmp = ($nelt_062 | 0) > 0;
+ if ($cmp) {
+ $ep_057 = $ep_1;
+ $changed_061 = $changed_1_ph50;
+ $nelt_062_in = $nelt_062;
+ label = 4;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $tobool70 = ($changed_1_ph50 | 0) == 0;
+ if ($tobool70) {
+ label = 24;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $19 = HEAP32[41526] | 0;
+ $rank73 = $19 + 224 | 0;
+ $20 = HEAP32[$rank73 >> 2] | 0;
+ $valid = $20 + ($r * 44 & -1) + 33 | 0;
+ HEAP8[$valid] = 0;
+ $cmp75 = ($r | 0) > 0;
+ if ($cmp75) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ $sub78 = $r - 1 | 0;
+ $21 = HEAP32[41526] | 0;
+ $rank80 = $21 + 224 | 0;
+ $22 = HEAP32[$rank80 >> 2] | 0;
+ $valid82 = $22 + ($sub78 * 44 & -1) + 33 | 0;
+ HEAP8[$valid82] = 0;
+ label = 24;
+ break;
+ case 24:
+ return;
+ }
+}
+function _inside_cluster($g, $v) {
+ $g = $g | 0;
+ $v = $v | 0;
+ var $call = 0;
+ $call = _is_a_normal_node_of($g, $v) | 0;
+ return _is_a_vnode_of_an_edge_of($g, $v) | $call | 0;
+}
+function _balance($g) {
+ $g = $g | 0;
+ var $maxrank = 0, $0 = 0, $minrank = 0, $1 = 0, $cmp6 = 0, $conv = 0, $rank = 0, $r_07 = 0, $2 = 0, $candidate = 0, $3 = 0, $n1 = 0, $4 = 0, $sub2 = 0, $cmp93 = 0, $cmp27 = 0, $add35 = 0, $5 = 0, $i_04 = 0, $v15 = 0, $6 = 0, $arrayidx16 = 0, $7 = 0, $add = 0, $arrayidx21 = 0, $8 = 0, $order = 0, $9 = 0, $order24 = 0, $10 = 0, $cmp25 = 0, $call = 0, $tobool = 0, $call30 = 0, $call32 = 0, $c1_0 = 0, $c0_0 = 0, $11 = 0, $n39 = 0, $12 = 0, $cmp40 = 0, $call43 = 0, $add44 = 0, $call45 = 0, $add46 = 0, $c1_1 = 0, $c0_1 = 0, $cmp48 = 0, $13 = 0, $n = 0, $14 = 0, $sub = 0, $cmp9 = 0, $dec = 0, $15 = 0, $conv2 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $maxrank = $g + 250 | 0;
+ $0 = HEAP16[$maxrank >> 1] | 0;
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $cmp6 = $0 << 16 >> 16 < $1 << 16 >> 16;
+ if ($cmp6) {
+ label = 17;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $r_07 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$rank >> 2] | 0;
+ $candidate = $2 + ($r_07 * 44 & -1) + 32 | 0;
+ HEAP8[$candidate] = 0;
+ $3 = HEAP32[$rank >> 2] | 0;
+ $n1 = $3 + ($r_07 * 44 & -1) | 0;
+ $4 = HEAP32[$n1 >> 2] | 0;
+ $sub2 = $4 - 1 | 0;
+ $cmp93 = ($sub2 | 0) > 0;
+ if ($cmp93) {
+ label = 5;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 5:
+ $cmp27 = ($r_07 | 0) > 0;
+ $add35 = $r_07 + 1 | 0;
+ $i_04 = 0;
+ $5 = $3;
+ label = 6;
+ break;
+ case 6:
+ $v15 = $5 + ($r_07 * 44 & -1) + 4 | 0;
+ $6 = HEAP32[$v15 >> 2] | 0;
+ $arrayidx16 = $6 + ($i_04 << 2) | 0;
+ $7 = HEAP32[$arrayidx16 >> 2] | 0;
+ $add = $i_04 + 1 | 0;
+ $arrayidx21 = $6 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx21 >> 2] | 0;
+ $order = $7 + 240 | 0;
+ $9 = HEAP32[$order >> 2] | 0;
+ $order24 = $8 + 240 | 0;
+ $10 = HEAP32[$order24 >> 2] | 0;
+ $cmp25 = ($9 | 0) < ($10 | 0);
+ if ($cmp25) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ ___assert_func(119784, 474, 164640, 105480);
+ case 8:
+ $call = _left2right($g, $7, $8) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 9:
+ if ($cmp27) {
+ label = 10;
+ break;
+ } else {
+ $c0_0 = 0;
+ $c1_0 = 0;
+ label = 11;
+ break;
+ }
+ case 10:
+ $call30 = _in_cross($7, $8) | 0;
+ $call32 = _in_cross($8, $7) | 0;
+ $c0_0 = $call30;
+ $c1_0 = $call32;
+ label = 11;
+ break;
+ case 11:
+ $11 = HEAP32[$rank >> 2] | 0;
+ $n39 = $11 + ($add35 * 44 & -1) | 0;
+ $12 = HEAP32[$n39 >> 2] | 0;
+ $cmp40 = ($12 | 0) > 0;
+ if ($cmp40) {
+ label = 12;
+ break;
+ } else {
+ $c0_1 = $c0_0;
+ $c1_1 = $c1_0;
+ label = 13;
+ break;
+ }
+ case 12:
+ $call43 = _out_cross($7, $8) | 0;
+ $add44 = $call43 + $c0_0 | 0;
+ $call45 = _out_cross($8, $7) | 0;
+ $add46 = $call45 + $c1_0 | 0;
+ $c0_1 = $add44;
+ $c1_1 = $add46;
+ label = 13;
+ break;
+ case 13:
+ $cmp48 = ($c1_1 | 0) > ($c0_1 | 0);
+ if ($cmp48) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $13 = HEAP32[$rank >> 2] | 0;
+ $n = $13 + ($r_07 * 44 & -1) | 0;
+ $14 = HEAP32[$n >> 2] | 0;
+ $sub = $14 - 1 | 0;
+ $cmp9 = ($add | 0) < ($sub | 0);
+ if ($cmp9) {
+ $i_04 = $add;
+ $5 = $13;
+ label = 6;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ _balanceNodes($g, $r_07, $7, $8);
+ label = 14;
+ break;
+ case 16:
+ $dec = $r_07 - 1 | 0;
+ $15 = HEAP16[$minrank >> 1] | 0;
+ $conv2 = $15 << 16 >> 16;
+ $cmp = ($dec | 0) < ($conv2 | 0);
+ if ($cmp) {
+ label = 17;
+ break;
+ } else {
+ $r_07 = $dec;
+ label = 4;
+ break;
+ }
+ case 17:
+ return;
+ }
+}
+function _set_xcoords($g) {
+ $g = $g | 0;
+ var $rank1 = 0, $0 = 0, $minrank = 0, $1 = 0, $maxrank = 0, $2 = 0, $cmp15 = 0, $conv = 0, $i_016 = 0, $n = 0, $3 = 0, $cmp712 = 0, $v11 = 0, $j_013 = 0, $4 = 0, $arrayidx12 = 0, $5 = 0, $rank14 = 0, $6 = 0, $conv15 = 0.0, $x = 0, $inc = 0, $7 = 0, $cmp7 = 0, $inc20 = 0, $8 = 0, $conv4 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank1 = $g + 224 | 0;
+ $0 = HEAP32[$rank1 >> 2] | 0;
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $cmp15 = $1 << 16 >> 16 > $2 << 16 >> 16;
+ if ($cmp15) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $1 << 16 >> 16;
+ $i_016 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $n = $0 + ($i_016 * 44 & -1) | 0;
+ $3 = HEAP32[$n >> 2] | 0;
+ $cmp712 = ($3 | 0) > 0;
+ if ($cmp712) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $v11 = $0 + ($i_016 * 44 & -1) + 4 | 0;
+ $j_013 = 0;
+ label = 6;
+ break;
+ case 6:
+ $4 = HEAP32[$v11 >> 2] | 0;
+ $arrayidx12 = $4 + ($j_013 << 2) | 0;
+ $5 = HEAP32[$arrayidx12 >> 2] | 0;
+ $rank14 = $5 + 236 | 0;
+ $6 = HEAP32[$rank14 >> 2] | 0;
+ $conv15 = +($6 | 0);
+ $x = $5 + 32 | 0;
+ HEAPF64[$x >> 3] = $conv15;
+ HEAP32[$rank14 >> 2] = $i_016;
+ $inc = $j_013 + 1 | 0;
+ $7 = HEAP32[$n >> 2] | 0;
+ $cmp7 = ($inc | 0) < ($7 | 0);
+ if ($cmp7) {
+ $j_013 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $inc20 = $i_016 + 1 | 0;
+ $8 = HEAP16[$maxrank >> 1] | 0;
+ $conv4 = $8 << 16 >> 16;
+ $cmp = ($inc20 | 0) > ($conv4 | 0);
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ $i_016 = $inc20;
+ label = 4;
+ break;
+ }
+ case 8:
+ return;
+ }
+}
+function _new_matrix($i, $j) {
+ $i = $i | 0;
+ $j = $j | 0;
+ var $call = 0;
+ $call = _zmalloc(12) | 0;
+ HEAP32[$call >> 2] = $i;
+ HEAP32[$call + 4 >> 2] = $j;
+ HEAP32[$call + 8 >> 2] = _zmalloc(Math_imul($j, $i)) | 0;
+ return $call | 0;
+}
+function _set_ycoords($g) {
+ $g = $g | 0;
+ var $rank1 = 0, $0 = 0, $minrank = 0, $1 = 0, $maxrank = 0, $2 = 0, $cmp124 = 0, $conv = 0, $r_0125 = 0, $n7 = 0, $3 = 0, $cmp8121 = 0, $v = 0, $pht2 = 0, $ht261 = 0, $pht1 = 0, $ht1 = 0, $i_0122 = 0, $4 = 0, $arrayidx12 = 0, $5 = 0, $ht = 0, $6 = 0.0, $cmp14 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv18 = 0, $add22 = 0, $div = 0, $list = 0, $7 = 0, $tobool = 0, $8 = 0, $9 = 0, $tobool29117 = 0, $10 = 0, $11 = 0, $j_0119 = 0, $ht2_0118 = 0, $tail = 0, $12 = 0, $head = 0, $13 = 0, $cmp31 = 0, $label = 0, $14 = 0, $tobool35 = 0, $conv37 = 0.0, $y = 0, $15 = 0.0, $div40 = 0.0, $cmp41 = 0, $conv37_div40 = 0.0, $conv53 = 0, $ht2_1 = 0, $inc = 0, $arrayidx28 = 0, $16 = 0, $tobool29 = 0, $ht2_2 = 0, $17 = 0, $cmp57 = 0, $18 = 0, $cmp66 = 0, $clust74 = 0, $19 = 0, $tobool75 = 0, $cmp77 = 0, $cond79 = 0, $rank81 = 0, $20 = 0, $minrank83 = 0, $21 = 0, $conv84 = 0, $cmp85 = 0, $ht289 = 0, $22 = 0, $add90 = 0, $cmp91 = 0, $_add90 = 0, $23 = 0, $maxrank106 = 0, $24 = 0, $conv107 = 0, $cmp108 = 0, $ht1112 = 0, $25 = 0, $add113 = 0, $cmp114 = 0, $_add113 = 0, $inc128 = 0, $26 = 0, $cmp8 = 0, $inc131 = 0, $27 = 0, $conv4 = 0, $cmp = 0, $call = 0, $28 = 0, $conv135 = 0, $ht1137 = 0, $29 = 0, $conv138 = 0.0, $v140 = 0, $30 = 0, $31 = 0, $y143 = 0, $dec110 = 0, $32 = 0, $conv146111 = 0, $cmp147112 = 0, $ranksep = 0, $dec115 = 0, $r_1114 = 0, $maxht_0113 = 0, $pht2151 = 0, $33 = 0, $pht1153 = 0, $34 = 0, $add154 = 0, $35 = 0, $add156 = 0, $ht2159 = 0, $36 = 0, $ht1161 = 0, $37 = 0, $add162 = 0, $add163 = 0, $cmp164 = 0, $cond169 = 0, $n171 = 0, $38 = 0, $cmp172 = 0, $v177 = 0, $39 = 0, $40 = 0, $y181 = 0, $41 = 0.0, $conv182 = 0.0, $add183 = 0.0, $v185 = 0, $42 = 0, $43 = 0, $y189 = 0, $cmp191 = 0, $cond196 = 0, $dec = 0, $44 = 0, $conv146 = 0, $cmp147 = 0, $phitmp = 0.0, $maxht_0_lcssa = 0.0, $exact_ranksep = 0, $45 = 0, $tobool198 = 0, $46 = 0, $conv202 = 0, $r_2105 = 0, $47 = 0, $conv207106 = 0, $cmp208107 = 0, $r_2109 = 0, $r_2_in108 = 0, $n212 = 0, $48 = 0, $cmp213 = 0, $r_2 = 0, $49 = 0, $conv207 = 0, $cmp208 = 0, $v218 = 0, $50 = 0, $51 = 0, $y222 = 0, $52 = 0.0, $add224 = 0.0, $v226 = 0, $53 = 0, $54 = 0, $y230 = 0, $tobool236 = 0, $rankdir = 0, $55 = 0, $and238 = 0, $tobool239 = 0, $56 = 0, $conv243 = 0, $nlist = 0, $n_0102 = 0, $tobool247103 = 0, $n_0104 = 0, $rank250 = 0, $57 = 0, $v252 = 0, $58 = 0, $59 = 0, $y256 = 0, $60 = 0.0, $y259 = 0, $next = 0, $n_0 = 0, $tobool247 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank1 = $g + 224 | 0;
+ $0 = HEAP32[$rank1 >> 2] | 0;
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $cmp124 = $1 << 16 >> 16 > $2 << 16 >> 16;
+ if ($cmp124) {
+ label = 27;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $1 << 16 >> 16;
+ $r_0125 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $n7 = $0 + ($r_0125 * 44 & -1) | 0;
+ $3 = HEAP32[$n7 >> 2] | 0;
+ $cmp8121 = ($3 | 0) > 0;
+ if ($cmp8121) {
+ label = 5;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 5:
+ $v = $0 + ($r_0125 * 44 & -1) + 4 | 0;
+ $pht2 = $0 + ($r_0125 * 44 & -1) + 28 | 0;
+ $ht261 = $0 + ($r_0125 * 44 & -1) + 20 | 0;
+ $pht1 = $0 + ($r_0125 * 44 & -1) + 24 | 0;
+ $ht1 = $0 + ($r_0125 * 44 & -1) + 16 | 0;
+ $i_0122 = 0;
+ label = 6;
+ break;
+ case 6:
+ $4 = HEAP32[$v >> 2] | 0;
+ $arrayidx12 = $4 + ($i_0122 << 2) | 0;
+ $5 = HEAP32[$arrayidx12 >> 2] | 0;
+ $ht = $5 + 96 | 0;
+ $6 = +HEAPF64[$ht >> 3];
+ $cmp14 = $6 < 0.0;
+ if ($cmp14) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add = $6 + .5;
+ $add_sink = $add;
+ label = 9;
+ break;
+ case 8:
+ $sub = $6 + -.5;
+ $add_sink = $sub;
+ label = 9;
+ break;
+ case 9:
+ $conv18 = ~~$add_sink;
+ $add22 = $conv18 + 1 | 0;
+ $div = ($add22 | 0) / 2 & -1;
+ $list = $5 + 208 | 0;
+ $7 = HEAP32[$list >> 2] | 0;
+ $tobool = ($7 | 0) == 0;
+ if ($tobool) {
+ $ht2_2 = $div;
+ label = 16;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $8 = HEAP32[$list >> 2] | 0;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $tobool29117 = ($9 | 0) == 0;
+ if ($tobool29117) {
+ $ht2_2 = $div;
+ label = 16;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $10 = HEAP32[$list >> 2] | 0;
+ $ht2_0118 = $div;
+ $j_0119 = 0;
+ $11 = $9;
+ label = 12;
+ break;
+ case 12:
+ $tail = $11 + 16 | 0;
+ $12 = HEAP32[$tail >> 2] | 0;
+ $head = $11 + 12 | 0;
+ $13 = HEAP32[$head >> 2] | 0;
+ $cmp31 = ($12 | 0) == ($13 | 0);
+ if ($cmp31) {
+ label = 13;
+ break;
+ } else {
+ $ht2_1 = $ht2_0118;
+ label = 15;
+ break;
+ }
+ case 13:
+ $label = $11 + 112 | 0;
+ $14 = HEAP32[$label >> 2] | 0;
+ $tobool35 = ($14 | 0) == 0;
+ if ($tobool35) {
+ $ht2_1 = $ht2_0118;
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $conv37 = +($ht2_0118 | 0);
+ $y = $14 + 32 | 0;
+ $15 = +HEAPF64[$y >> 3];
+ $div40 = $15 * .5;
+ $cmp41 = $conv37 > $div40;
+ $conv37_div40 = $cmp41 ? $conv37 : $div40;
+ $conv53 = ~~$conv37_div40;
+ $ht2_1 = $conv53;
+ label = 15;
+ break;
+ case 15:
+ $inc = $j_0119 + 1 | 0;
+ $arrayidx28 = $10 + ($inc << 2) | 0;
+ $16 = HEAP32[$arrayidx28 >> 2] | 0;
+ $tobool29 = ($16 | 0) == 0;
+ if ($tobool29) {
+ $ht2_2 = $ht2_1;
+ label = 16;
+ break;
+ } else {
+ $ht2_0118 = $ht2_1;
+ $j_0119 = $inc;
+ $11 = $16;
+ label = 12;
+ break;
+ }
+ case 16:
+ $17 = HEAP32[$pht2 >> 2] | 0;
+ $cmp57 = ($17 | 0) < ($ht2_2 | 0);
+ if ($cmp57) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ HEAP32[$ht261 >> 2] = $ht2_2;
+ HEAP32[$pht2 >> 2] = $ht2_2;
+ label = 18;
+ break;
+ case 18:
+ $18 = HEAP32[$pht1 >> 2] | 0;
+ $cmp66 = ($18 | 0) < ($ht2_2 | 0);
+ if ($cmp66) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ HEAP32[$ht1 >> 2] = $ht2_2;
+ HEAP32[$pht1 >> 2] = $ht2_2;
+ label = 20;
+ break;
+ case 20:
+ $clust74 = $5 + 216 | 0;
+ $19 = HEAP32[$clust74 >> 2] | 0;
+ $tobool75 = ($19 | 0) == 0;
+ if ($tobool75) {
+ label = 25;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $cmp77 = ($19 | 0) == ($g | 0);
+ $cond79 = $cmp77 ? 0 : 8;
+ $rank81 = $5 + 236 | 0;
+ $20 = HEAP32[$rank81 >> 2] | 0;
+ $minrank83 = $19 + 248 | 0;
+ $21 = HEAP16[$minrank83 >> 1] | 0;
+ $conv84 = $21 << 16 >> 16;
+ $cmp85 = ($20 | 0) == ($conv84 | 0);
+ if ($cmp85) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $ht289 = $19 + 164 | 0;
+ $22 = HEAP32[$ht289 >> 2] | 0;
+ $add90 = $cond79 + $ht2_2 | 0;
+ $cmp91 = ($22 | 0) > ($add90 | 0);
+ $_add90 = $cmp91 ? $22 : $add90;
+ HEAP32[$ht289 >> 2] = $_add90;
+ label = 23;
+ break;
+ case 23:
+ $23 = HEAP32[$rank81 >> 2] | 0;
+ $maxrank106 = $19 + 250 | 0;
+ $24 = HEAP16[$maxrank106 >> 1] | 0;
+ $conv107 = $24 << 16 >> 16;
+ $cmp108 = ($23 | 0) == ($conv107 | 0);
+ if ($cmp108) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $ht1112 = $19 + 160 | 0;
+ $25 = HEAP32[$ht1112 >> 2] | 0;
+ $add113 = $cond79 + $ht2_2 | 0;
+ $cmp114 = ($25 | 0) > ($add113 | 0);
+ $_add113 = $cmp114 ? $25 : $add113;
+ HEAP32[$ht1112 >> 2] = $_add113;
+ label = 25;
+ break;
+ case 25:
+ $inc128 = $i_0122 + 1 | 0;
+ $26 = HEAP32[$n7 >> 2] | 0;
+ $cmp8 = ($inc128 | 0) < ($26 | 0);
+ if ($cmp8) {
+ $i_0122 = $inc128;
+ label = 6;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $inc131 = $r_0125 + 1 | 0;
+ $27 = HEAP16[$maxrank >> 1] | 0;
+ $conv4 = $27 << 16 >> 16;
+ $cmp = ($inc131 | 0) > ($conv4 | 0);
+ if ($cmp) {
+ label = 27;
+ break;
+ } else {
+ $r_0125 = $inc131;
+ label = 4;
+ break;
+ }
+ case 27:
+ $call = _clust_ht($g) | 0;
+ $28 = HEAP16[$maxrank >> 1] | 0;
+ $conv135 = $28 << 16 >> 16;
+ $ht1137 = $0 + ($conv135 * 44 & -1) + 16 | 0;
+ $29 = HEAP32[$ht1137 >> 2] | 0;
+ $conv138 = +($29 | 0);
+ $v140 = $0 + ($conv135 * 44 & -1) + 4 | 0;
+ $30 = HEAP32[$v140 >> 2] | 0;
+ $31 = HEAP32[$30 >> 2] | 0;
+ $y143 = $31 + 40 | 0;
+ HEAPF64[$y143 >> 3] = $conv138;
+ $dec110 = $conv135 - 1 | 0;
+ $32 = HEAP16[$minrank >> 1] | 0;
+ $conv146111 = $32 << 16 >> 16;
+ $cmp147112 = ($dec110 | 0) < ($conv146111 | 0);
+ if ($cmp147112) {
+ $maxht_0_lcssa = 0.0;
+ label = 33;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $ranksep = $g + 264 | 0;
+ $maxht_0113 = 0;
+ $r_1114 = $conv135;
+ $dec115 = $dec110;
+ label = 29;
+ break;
+ case 29:
+ $pht2151 = $0 + ($r_1114 * 44 & -1) + 28 | 0;
+ $33 = HEAP32[$pht2151 >> 2] | 0;
+ $pht1153 = $0 + ($dec115 * 44 & -1) + 24 | 0;
+ $34 = HEAP32[$pht1153 >> 2] | 0;
+ $add154 = $34 + $33 | 0;
+ $35 = HEAP32[$ranksep >> 2] | 0;
+ $add156 = $add154 + $35 | 0;
+ $ht2159 = $0 + ($r_1114 * 44 & -1) + 20 | 0;
+ $36 = HEAP32[$ht2159 >> 2] | 0;
+ $ht1161 = $0 + ($dec115 * 44 & -1) + 16 | 0;
+ $37 = HEAP32[$ht1161 >> 2] | 0;
+ $add162 = $36 + 8 | 0;
+ $add163 = $add162 + $37 | 0;
+ $cmp164 = ($add156 | 0) > ($add163 | 0);
+ $cond169 = $cmp164 ? $add156 : $add163;
+ $n171 = $0 + ($dec115 * 44 & -1) | 0;
+ $38 = HEAP32[$n171 >> 2] | 0;
+ $cmp172 = ($38 | 0) > 0;
+ if ($cmp172) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $v177 = $0 + ($r_1114 * 44 & -1) + 4 | 0;
+ $39 = HEAP32[$v177 >> 2] | 0;
+ $40 = HEAP32[$39 >> 2] | 0;
+ $y181 = $40 + 40 | 0;
+ $41 = +HEAPF64[$y181 >> 3];
+ $conv182 = +($cond169 | 0);
+ $add183 = $conv182 + $41;
+ $v185 = $0 + ($dec115 * 44 & -1) + 4 | 0;
+ $42 = HEAP32[$v185 >> 2] | 0;
+ $43 = HEAP32[$42 >> 2] | 0;
+ $y189 = $43 + 40 | 0;
+ HEAPF64[$y189 >> 3] = $add183;
+ label = 31;
+ break;
+ case 31:
+ $cmp191 = ($maxht_0113 | 0) > ($cond169 | 0);
+ $cond196 = $cmp191 ? $maxht_0113 : $cond169;
+ $dec = $dec115 - 1 | 0;
+ $44 = HEAP16[$minrank >> 1] | 0;
+ $conv146 = $44 << 16 >> 16;
+ $cmp147 = ($dec | 0) < ($conv146 | 0);
+ if ($cmp147) {
+ label = 32;
+ break;
+ } else {
+ $maxht_0113 = $cond196;
+ $r_1114 = $dec115;
+ $dec115 = $dec;
+ label = 29;
+ break;
+ }
+ case 32:
+ $phitmp = +($cond196 | 0);
+ $maxht_0_lcssa = $phitmp;
+ label = 33;
+ break;
+ case 33:
+ $exact_ranksep = $g + 288 | 0;
+ $45 = HEAP8[$exact_ranksep] | 0;
+ $tobool198 = $45 << 24 >> 24 == 0;
+ if ($tobool198) {
+ label = 38;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $46 = HEAP16[$maxrank >> 1] | 0;
+ $conv202 = $46 << 16 >> 16;
+ $r_2105 = $conv202 - 1 | 0;
+ $47 = HEAP16[$minrank >> 1] | 0;
+ $conv207106 = $47 << 16 >> 16;
+ $cmp208107 = ($r_2105 | 0) < ($conv207106 | 0);
+ if ($cmp208107) {
+ label = 38;
+ break;
+ } else {
+ $r_2_in108 = $conv202;
+ $r_2109 = $r_2105;
+ label = 35;
+ break;
+ }
+ case 35:
+ $n212 = $0 + ($r_2109 * 44 & -1) | 0;
+ $48 = HEAP32[$n212 >> 2] | 0;
+ $cmp213 = ($48 | 0) > 0;
+ if ($cmp213) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $r_2 = $r_2109 - 1 | 0;
+ $49 = HEAP16[$minrank >> 1] | 0;
+ $conv207 = $49 << 16 >> 16;
+ $cmp208 = ($r_2 | 0) < ($conv207 | 0);
+ if ($cmp208) {
+ label = 38;
+ break;
+ } else {
+ $r_2_in108 = $r_2109;
+ $r_2109 = $r_2;
+ label = 35;
+ break;
+ }
+ case 37:
+ $v218 = $0 + ($r_2_in108 * 44 & -1) + 4 | 0;
+ $50 = HEAP32[$v218 >> 2] | 0;
+ $51 = HEAP32[$50 >> 2] | 0;
+ $y222 = $51 + 40 | 0;
+ $52 = +HEAPF64[$y222 >> 3];
+ $add224 = $maxht_0_lcssa + $52;
+ $v226 = $0 + ($r_2109 * 44 & -1) + 4 | 0;
+ $53 = HEAP32[$v226 >> 2] | 0;
+ $54 = HEAP32[$53 >> 2] | 0;
+ $y230 = $54 + 40 | 0;
+ HEAPF64[$y230 >> 3] = $add224;
+ label = 36;
+ break;
+ case 38:
+ $tobool236 = ($call | 0) == 0;
+ if ($tobool236) {
+ label = 41;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $rankdir = $g + 156 | 0;
+ $55 = HEAP32[$rankdir >> 2] | 0;
+ $and238 = $55 & 1;
+ $tobool239 = ($and238 | 0) == 0;
+ if ($tobool239) {
+ label = 41;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $56 = HEAP8[$exact_ranksep] | 0;
+ $conv243 = $56 & 255;
+ _adjustRanks($g, $conv243);
+ label = 41;
+ break;
+ case 41:
+ $nlist = $g + 220 | 0;
+ $n_0102 = HEAP32[$nlist >> 2] | 0;
+ $tobool247103 = ($n_0102 | 0) == 0;
+ if ($tobool247103) {
+ label = 43;
+ break;
+ } else {
+ $n_0104 = $n_0102;
+ label = 42;
+ break;
+ }
+ case 42:
+ $rank250 = $n_0104 + 236 | 0;
+ $57 = HEAP32[$rank250 >> 2] | 0;
+ $v252 = $0 + ($57 * 44 & -1) + 4 | 0;
+ $58 = HEAP32[$v252 >> 2] | 0;
+ $59 = HEAP32[$58 >> 2] | 0;
+ $y256 = $59 + 40 | 0;
+ $60 = +HEAPF64[$y256 >> 3];
+ $y259 = $n_0104 + 40 | 0;
+ HEAPF64[$y259 >> 3] = $60;
+ $next = $n_0104 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool247 = ($n_0 | 0) == 0;
+ if ($tobool247) {
+ label = 43;
+ break;
+ } else {
+ $n_0104 = $n_0;
+ label = 42;
+ break;
+ }
+ case 43:
+ return;
+ }
+}
+function _expand_leaves($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_019 = 0, $tobool20 = 0, $n_021 = 0, $inleaf = 0, $0 = 0, $tobool2 = 0, $outleaf = 0, $1 = 0, $tobool6 = 0, $list = 0, $2 = 0, $tobool12 = 0, $3 = 0, $i_0 = 0, $arrayidx = 0, $4 = 0, $tobool18 = 0, $inc = 0, $next = 0, $n_0 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _make_leafslots($g);
+ $nlist = $g + 220 | 0;
+ $n_019 = HEAP32[$nlist >> 2] | 0;
+ $tobool20 = ($n_019 | 0) == 0;
+ if ($tobool20) {
+ label = 11;
+ break;
+ } else {
+ $n_021 = $n_019;
+ label = 3;
+ break;
+ }
+ case 3:
+ $inleaf = $n_021 + 228 | 0;
+ $0 = HEAP32[$inleaf >> 2] | 0;
+ $tobool2 = ($0 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _do_leaves($g, $0);
+ label = 5;
+ break;
+ case 5:
+ $outleaf = $n_021 + 232 | 0;
+ $1 = HEAP32[$outleaf >> 2] | 0;
+ $tobool6 = ($1 | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _do_leaves($g, $1);
+ label = 7;
+ break;
+ case 7:
+ $list = $n_021 + 208 | 0;
+ $2 = HEAP32[$list >> 2] | 0;
+ $tobool12 = ($2 | 0) == 0;
+ if ($tobool12) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $3 = HEAP32[$list >> 2] | 0;
+ $i_0 = 0;
+ label = 9;
+ break;
+ case 9:
+ $arrayidx = $3 + ($i_0 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool18 = ($4 | 0) == 0;
+ $inc = $i_0 + 1 | 0;
+ if ($tobool18) {
+ label = 10;
+ break;
+ } else {
+ $i_0 = $inc;
+ label = 9;
+ break;
+ }
+ case 10:
+ $next = $n_021 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ $n_021 = $n_0;
+ label = 3;
+ break;
+ }
+ case 11:
+ return;
+ }
+}
+function _create_aux_edges($g) {
+ $g = $g | 0;
+ _allocate_aux_edges($g);
+ _make_LR_constraints($g);
+ _make_edge_pairs($g);
+ _pos_clusters($g);
+ _compress_graph($g);
+ return;
+}
+function _nsiter2($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $call1 = 0.0, $1 = 0, $call2 = 0, $conv = 0.0, $mul = 0.0, $conv3 = 0, $maxiter_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g | 0;
+ $call = _agget($0, 96112) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $maxiter_0 = 2147483647;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = +_atof($call);
+ $1 = $g;
+ $call2 = _agnnodes($1) | 0;
+ $conv = +($call2 | 0);
+ $mul = $call1 * $conv;
+ $conv3 = ~~$mul;
+ $maxiter_0 = $conv3;
+ label = 4;
+ break;
+ case 4:
+ return $maxiter_0 | 0;
+ }
+ return 0;
+}
+function _postorder($g, $v, $list, $r) {
+ $g = $g | 0;
+ $v = $v | 0;
+ $list = $list | 0;
+ $r = $r | 0;
+ var $mark = 0, $size = 0, $0 = 0, $cmp = 0, $list4 = 0, $1 = 0, $2 = 0, $tobool19 = 0, $3 = 0, $4 = 0, $cnt_021 = 0, $i_020 = 0, $weight = 0, $5 = 0.0, $cmp6 = 0, $head = 0, $6 = 0, $node_type = 0, $7 = 0, $cmp9 = 0, $8 = 0, $call = 0, $lnot = 0, $and18 = 0, $9 = 0, $clust = 0, $10 = 0, $tail = 0, $11 = 0, $clust19 = 0, $12 = 0, $cmp20 = 0, $mark26 = 0, $13 = 0, $cmp28 = 0, $add_ptr = 0, $call32 = 0, $add = 0, $cnt_1 = 0, $inc = 0, $14 = 0, $arrayidx = 0, $15 = 0, $tobool = 0, $cnt_2 = 0, $rank = 0, $16 = 0, $cmp36 = 0, $inc38 = 0, $arrayidx39 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $mark = $v + 163 | 0;
+ HEAP8[$mark] = 1;
+ $size = $v + 196 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp = ($0 | 0) > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $cnt_2 = 0;
+ label = 11;
+ break;
+ }
+ case 3:
+ $list4 = $v + 192 | 0;
+ $1 = HEAP32[$list4 >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool19 = ($2 | 0) == 0;
+ if ($tobool19) {
+ $cnt_2 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = $g;
+ $i_020 = 0;
+ $cnt_021 = 0;
+ $4 = $2;
+ label = 5;
+ break;
+ case 5:
+ $weight = $4 + 172 | 0;
+ $5 = +HEAPF32[$weight >> 2];
+ $cmp6 = $5 == 0.0;
+ if ($cmp6) {
+ $cnt_1 = $cnt_021;
+ label = 10;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $head = $4 + 12 | 0;
+ $6 = HEAP32[$head >> 2] | 0;
+ $node_type = $6 + 162 | 0;
+ $7 = HEAP8[$node_type] | 0;
+ $cmp9 = $7 << 24 >> 24 == 0;
+ $8 = $6 | 0;
+ $call = _agcontains($3, $8) | 0;
+ $lnot = ($call | 0) == 0;
+ $and18 = $cmp9 & $lnot;
+ if ($and18) {
+ $cnt_1 = $cnt_021;
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $9 = HEAP32[$head >> 2] | 0;
+ $clust = $9 + 216 | 0;
+ $10 = HEAP32[$clust >> 2] | 0;
+ $tail = $4 + 16 | 0;
+ $11 = HEAP32[$tail >> 2] | 0;
+ $clust19 = $11 + 216 | 0;
+ $12 = HEAP32[$clust19 >> 2] | 0;
+ $cmp20 = ($10 | 0) == ($12 | 0);
+ if ($cmp20) {
+ label = 8;
+ break;
+ } else {
+ $cnt_1 = $cnt_021;
+ label = 10;
+ break;
+ }
+ case 8:
+ $mark26 = $9 + 163 | 0;
+ $13 = HEAP8[$mark26] | 0;
+ $cmp28 = $13 << 24 >> 24 == 0;
+ if ($cmp28) {
+ label = 9;
+ break;
+ } else {
+ $cnt_1 = $cnt_021;
+ label = 10;
+ break;
+ }
+ case 9:
+ $add_ptr = $list + ($cnt_021 << 2) | 0;
+ $call32 = _postorder($g, $9, $add_ptr, $r) | 0;
+ $add = $call32 + $cnt_021 | 0;
+ $cnt_1 = $add;
+ label = 10;
+ break;
+ case 10:
+ $inc = $i_020 + 1 | 0;
+ $14 = HEAP32[$list4 >> 2] | 0;
+ $arrayidx = $14 + ($inc << 2) | 0;
+ $15 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($15 | 0) == 0;
+ if ($tobool) {
+ $cnt_2 = $cnt_1;
+ label = 11;
+ break;
+ } else {
+ $i_020 = $inc;
+ $cnt_021 = $cnt_1;
+ $4 = $15;
+ label = 5;
+ break;
+ }
+ case 11:
+ $rank = $v + 236 | 0;
+ $16 = HEAP32[$rank >> 2] | 0;
+ $cmp36 = ($16 | 0) == ($r | 0);
+ if ($cmp36) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ ___assert_func(119784, 1161, 163920, 146624);
+ return 0;
+ case 13:
+ $inc38 = $cnt_2 + 1 | 0;
+ $arrayidx39 = $list + ($cnt_2 << 2) | 0;
+ HEAP32[$arrayidx39 >> 2] = $v;
+ return $inc38 | 0;
+ }
+ return 0;
+}
+function _flat_search($g, $v) {
+ $g = $g | 0;
+ $v = $v | 0;
+ var $rank = 0, $0 = 0, $rank2 = 0, $1 = 0, $flat = 0, $2 = 0, $mark = 0, $onstack = 0, $root = 0, $3 = 0, $n_cluster = 0, $4 = 0, $cmp = 0, $list = 0, $5 = 0, $tobool = 0, $6 = 0, $7 = 0, $tobool1234 = 0, $8 = 0, $nrows = 0, $ncols = 0, $data = 0, $ncols70 = 0, $data85 = 0, $9 = 0, $i_035 = 0, $tail = 0, $10 = 0, $11 = 0, $call = 0, $tobool15 = 0, $head = 0, $12 = 0, $13 = 0, $call17 = 0, $tobool18 = 0, $weight = 0, $14 = 0.0, $cmp21 = 0, $head25 = 0, $15 = 0, $onstack27 = 0, $16 = 0, $cmp29 = 0, $low = 0, $17 = 0, $18 = 0, $cmp34 = 0, $tail36 = 0, $19 = 0, $low38 = 0, $20 = 0, $21 = 0, $cmp39 = 0, $mul = 0, $add = 0, $22 = 0, $arrayidx51 = 0, $dec = 0, $edge_type = 0, $23 = 0, $cmp54 = 0, $tail67 = 0, $24 = 0, $low69 = 0, $25 = 0, $26 = 0, $cmp71 = 0, $mul80 = 0, $add84 = 0, $27 = 0, $arrayidx86 = 0, $28 = 0, $mark89 = 0, $29 = 0, $cmp91 = 0, $i_1 = 0, $inc = 0, $30 = 0, $arrayidx11 = 0, $31 = 0, $tobool12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $rank = $v + 236 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $rank2 = $g + 224 | 0;
+ $1 = HEAP32[$rank2 >> 2] | 0;
+ $flat = $1 + ($0 * 44 & -1) + 40 | 0;
+ $2 = HEAP32[$flat >> 2] | 0;
+ $mark = $v + 163 | 0;
+ HEAP8[$mark] = 1;
+ $onstack = $v + 164 | 0;
+ HEAP8[$onstack] = 1;
+ $root = $g + 32 | 0;
+ $3 = HEAP32[$root >> 2] | 0;
+ $n_cluster = $3 + 212 | 0;
+ $4 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($4 | 0) > 0;
+ $list = $v + 192 | 0;
+ $5 = HEAP32[$list >> 2] | 0;
+ $tobool = ($5 | 0) == 0;
+ if ($tobool) {
+ label = 23;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $6 = HEAP32[$list >> 2] | 0;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $tobool1234 = ($7 | 0) == 0;
+ if ($tobool1234) {
+ label = 23;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $8 = $g;
+ $nrows = $2 | 0;
+ $ncols = $2 + 4 | 0;
+ $data = $2 + 8 | 0;
+ $ncols70 = $2 + 4 | 0;
+ $data85 = $2 + 8 | 0;
+ $i_035 = 0;
+ $9 = $7;
+ label = 5;
+ break;
+ case 5:
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $tail = $9 + 16 | 0;
+ $10 = HEAP32[$tail >> 2] | 0;
+ $11 = $10 | 0;
+ $call = _agcontains($8, $11) | 0;
+ $tobool15 = ($call | 0) == 0;
+ if ($tobool15) {
+ $i_1 = $i_035;
+ label = 22;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $head = $9 + 12 | 0;
+ $12 = HEAP32[$head >> 2] | 0;
+ $13 = $12 | 0;
+ $call17 = _agcontains($8, $13) | 0;
+ $tobool18 = ($call17 | 0) == 0;
+ if ($tobool18) {
+ $i_1 = $i_035;
+ label = 22;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $weight = $9 + 172 | 0;
+ $14 = +HEAPF32[$weight >> 2];
+ $cmp21 = $14 == 0.0;
+ if ($cmp21) {
+ $i_1 = $i_035;
+ label = 22;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $head25 = $9 + 12 | 0;
+ $15 = HEAP32[$head25 >> 2] | 0;
+ $onstack27 = $15 + 164 | 0;
+ $16 = HEAP8[$onstack27] | 0;
+ $cmp29 = $16 << 24 >> 24 == 1;
+ $low = $15 + 284 | 0;
+ $17 = HEAP32[$low >> 2] | 0;
+ $18 = HEAP32[$nrows >> 2] | 0;
+ $cmp34 = ($17 | 0) < ($18 | 0);
+ if ($cmp29) {
+ label = 10;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 10:
+ if ($cmp34) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ ___assert_func(119784, 933, 164240, 143792);
+ case 12:
+ $tail36 = $9 + 16 | 0;
+ $19 = HEAP32[$tail36 >> 2] | 0;
+ $low38 = $19 + 284 | 0;
+ $20 = HEAP32[$low38 >> 2] | 0;
+ $21 = HEAP32[$ncols >> 2] | 0;
+ $cmp39 = ($20 | 0) < ($21 | 0);
+ if ($cmp39) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ ___assert_func(119784, 934, 164240, 142616);
+ case 14:
+ $mul = Math_imul($21, $17);
+ $add = $mul + $20 | 0;
+ $22 = HEAP32[$data >> 2] | 0;
+ $arrayidx51 = $22 + $add | 0;
+ HEAP8[$arrayidx51] = 1;
+ _delete_flat_edge($9);
+ $dec = $i_035 - 1 | 0;
+ $edge_type = $9 + 128 | 0;
+ $23 = HEAP8[$edge_type] | 0;
+ $cmp54 = $23 << 24 >> 24 == 4;
+ if ($cmp54) {
+ $i_1 = $dec;
+ label = 22;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ _flat_rev($g, $9);
+ $i_1 = $dec;
+ label = 22;
+ break;
+ case 16:
+ if ($cmp34) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ ___assert_func(119784, 942, 164240, 143792);
+ case 18:
+ $tail67 = $9 + 16 | 0;
+ $24 = HEAP32[$tail67 >> 2] | 0;
+ $low69 = $24 + 284 | 0;
+ $25 = HEAP32[$low69 >> 2] | 0;
+ $26 = HEAP32[$ncols70 >> 2] | 0;
+ $cmp71 = ($25 | 0) < ($26 | 0);
+ if ($cmp71) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ ___assert_func(119784, 943, 164240, 142616);
+ case 20:
+ $mul80 = Math_imul($26, $25);
+ $add84 = $mul80 + $17 | 0;
+ $27 = HEAP32[$data85 >> 2] | 0;
+ $arrayidx86 = $27 + $add84 | 0;
+ HEAP8[$arrayidx86] = 1;
+ $28 = HEAP32[$head25 >> 2] | 0;
+ $mark89 = $28 + 163 | 0;
+ $29 = HEAP8[$mark89] | 0;
+ $cmp91 = $29 << 24 >> 24 == 0;
+ if ($cmp91) {
+ label = 21;
+ break;
+ } else {
+ $i_1 = $i_035;
+ label = 22;
+ break;
+ }
+ case 21:
+ _flat_search($g, $28);
+ $i_1 = $i_035;
+ label = 22;
+ break;
+ case 22:
+ $inc = $i_1 + 1 | 0;
+ $30 = HEAP32[$list >> 2] | 0;
+ $arrayidx11 = $30 + ($inc << 2) | 0;
+ $31 = HEAP32[$arrayidx11 >> 2] | 0;
+ $tobool12 = ($31 | 0) == 0;
+ if ($tobool12) {
+ label = 23;
+ break;
+ } else {
+ $i_035 = $inc;
+ $9 = $31;
+ label = 5;
+ break;
+ }
+ case 23:
+ HEAP8[$onstack] = 0;
+ return;
+ }
+}
+function _dot_position($g, $asp) {
+ $g = $g | 0;
+ $asp = $asp | 0;
+ var $nlist = 0, $0 = 0, $cmp = 0, $1 = 0, $2 = 0, $tobool = 0, $call = 0, $tobool3 = 0, $call6 = 0, $call7 = 0, $tobool8 = 0, $call10 = 0, $call11 = 0, $cmp12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $0 = HEAP32[$nlist >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $g;
+ _mark_lowclusters($1);
+ _set_ycoords($g);
+ $2 = HEAP8[167952] | 0;
+ $tobool = $2 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _dot_concentrate($1);
+ label = 5;
+ break;
+ case 5:
+ _expand_leaves($g);
+ $call = _flat_edges($g) | 0;
+ $tobool3 = ($call | 0) == 0;
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _set_ycoords($g);
+ label = 7;
+ break;
+ case 7:
+ _create_aux_edges($g);
+ $call6 = _nsiter2($g) | 0;
+ $call7 = _rank($g, 2, $call6) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _connectGraph($g);
+ $call10 = _nsiter2($g) | 0;
+ $call11 = _rank($g, 2, $call10) | 0;
+ $cmp12 = ($call11 | 0) == 0;
+ if ($cmp12) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ ___assert_func(157760, 133, 164352, 159168);
+ case 10:
+ _set_xcoords($g);
+ _set_aspect($g, $asp);
+ _remove_aux_edges($g);
+ label = 11;
+ break;
+ case 11:
+ return;
+ }
+}
+function _connectGraph($g) {
+ $g = $g | 0;
+ var $minrank = 0, $0 = 0, $maxrank = 0, $1 = 0, $cmp51 = 0, $conv = 0, $rank = 0, $r_052 = 0, $2 = 0, $n = 0, $3 = 0, $cmp647 = 0, $v = 0, $4 = 0, $i_048 = 0, $arrayidx = 0, $5 = 0, $list = 0, $6 = 0, $tobool = 0, $7 = 0, $j_0 = 0, $arrayidx14 = 0, $8 = 0, $tobool15 = 0, $head = 0, $9 = 0, $rank18 = 0, $10 = 0, $cmp19 = 0, $tail = 0, $11 = 0, $rank22 = 0, $12 = 0, $cmp23 = 0, $inc = 0, $list31 = 0, $13 = 0, $tobool32 = 0, $14 = 0, $j_1 = 0, $arrayidx38 = 0, $15 = 0, $tobool39 = 0, $tail41 = 0, $16 = 0, $rank43 = 0, $17 = 0, $cmp44 = 0, $head47 = 0, $18 = 0, $rank49 = 0, $19 = 0, $cmp50 = 0, $inc55 = 0, $inc62 = 0, $20 = 0, $cmp6 = 0, $phitmp = 0, $v69 = 0, $21 = 0, $22 = 0, $23 = 0, $conv73 = 0, $cmp74 = 0, $add_ptr_sum38_pn_v = 0, $add_ptr_sum38_pn = 0, $hp_0_in_in = 0, $hp_0_in = 0, $hp_0 = 0, $tobool84 = 0, $call = 0, $node_type = 0, $call86 = 0, $call87 = 0, $rank89 = 0, $24 = 0, $rank91 = 0, $25 = 0, $cmp92 = 0, $_ = 0, $rank102 = 0, $inc104 = 0, $26 = 0, $conv2 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $cmp51 = $0 << 16 >> 16 > $1 << 16 >> 16;
+ if ($cmp51) {
+ label = 22;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $r_052 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$rank >> 2] | 0;
+ $n = $2 + ($r_052 * 44 & -1) | 0;
+ $3 = HEAP32[$n >> 2] | 0;
+ $cmp647 = ($3 | 0) > 0;
+ if ($cmp647) {
+ label = 5;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 5:
+ $v = $2 + ($r_052 * 44 & -1) + 4 | 0;
+ $4 = HEAP32[$v >> 2] | 0;
+ $i_048 = 0;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx = $4 + ($i_048 << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $list = $5 + 256 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $7 = HEAP32[$list >> 2] | 0;
+ $j_0 = 0;
+ label = 8;
+ break;
+ case 8:
+ $arrayidx14 = $7 + ($j_0 << 2) | 0;
+ $8 = HEAP32[$arrayidx14 >> 2] | 0;
+ $tobool15 = ($8 | 0) == 0;
+ if ($tobool15) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $head = $8 + 12 | 0;
+ $9 = HEAP32[$head >> 2] | 0;
+ $rank18 = $9 + 236 | 0;
+ $10 = HEAP32[$rank18 >> 2] | 0;
+ $cmp19 = ($10 | 0) > ($r_052 | 0);
+ if ($cmp19) {
+ label = 21;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $tail = $8 + 16 | 0;
+ $11 = HEAP32[$tail >> 2] | 0;
+ $rank22 = $11 + 236 | 0;
+ $12 = HEAP32[$rank22 >> 2] | 0;
+ $cmp23 = ($12 | 0) > ($r_052 | 0);
+ $inc = $j_0 + 1 | 0;
+ if ($cmp23) {
+ label = 21;
+ break;
+ } else {
+ $j_0 = $inc;
+ label = 8;
+ break;
+ }
+ case 11:
+ $list31 = $5 + 248 | 0;
+ $13 = HEAP32[$list31 >> 2] | 0;
+ $tobool32 = ($13 | 0) == 0;
+ if ($tobool32) {
+ label = 16;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $14 = HEAP32[$list31 >> 2] | 0;
+ $j_1 = 0;
+ label = 13;
+ break;
+ case 13:
+ $arrayidx38 = $14 + ($j_1 << 2) | 0;
+ $15 = HEAP32[$arrayidx38 >> 2] | 0;
+ $tobool39 = ($15 | 0) == 0;
+ if ($tobool39) {
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $tail41 = $15 + 16 | 0;
+ $16 = HEAP32[$tail41 >> 2] | 0;
+ $rank43 = $16 + 236 | 0;
+ $17 = HEAP32[$rank43 >> 2] | 0;
+ $cmp44 = ($17 | 0) > ($r_052 | 0);
+ if ($cmp44) {
+ label = 21;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $head47 = $15 + 12 | 0;
+ $18 = HEAP32[$head47 >> 2] | 0;
+ $rank49 = $18 + 236 | 0;
+ $19 = HEAP32[$rank49 >> 2] | 0;
+ $cmp50 = ($19 | 0) > ($r_052 | 0);
+ $inc55 = $j_1 + 1 | 0;
+ if ($cmp50) {
+ label = 21;
+ break;
+ } else {
+ $j_1 = $inc55;
+ label = 13;
+ break;
+ }
+ case 16:
+ $inc62 = $i_048 + 1 | 0;
+ $20 = HEAP32[$n >> 2] | 0;
+ $cmp6 = ($inc62 | 0) < ($20 | 0);
+ if ($cmp6) {
+ $i_048 = $inc62;
+ label = 6;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $phitmp = ($5 | 0) == 0;
+ if ($phitmp) {
+ label = 21;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $v69 = $2 + ($r_052 * 44 & -1) + 4 | 0;
+ $21 = HEAP32[$v69 >> 2] | 0;
+ $22 = HEAP32[$21 >> 2] | 0;
+ $23 = HEAP16[$maxrank >> 1] | 0;
+ $conv73 = $23 << 16 >> 16;
+ $cmp74 = ($r_052 | 0) < ($conv73 | 0);
+ $add_ptr_sum38_pn_v = $cmp74 ? 1 : -1;
+ $add_ptr_sum38_pn = $add_ptr_sum38_pn_v + $r_052 | 0;
+ $hp_0_in_in = $2 + ($add_ptr_sum38_pn * 44 & -1) + 4 | 0;
+ $hp_0_in = HEAP32[$hp_0_in_in >> 2] | 0;
+ $hp_0 = HEAP32[$hp_0_in >> 2] | 0;
+ $tobool84 = ($hp_0 | 0) == 0;
+ if ($tobool84) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ ___assert_func(157760, 110, 164560, 92712);
+ case 20:
+ $call = _virtual_node($g) | 0;
+ $node_type = $call + 162 | 0;
+ HEAP8[$node_type] = 2;
+ $call86 = _make_aux_edge($call, $22, 0.0, 0) | 0;
+ $call87 = _make_aux_edge($call, $hp_0, 0.0, 0) | 0;
+ $rank89 = $22 + 236 | 0;
+ $24 = HEAP32[$rank89 >> 2] | 0;
+ $rank91 = $hp_0 + 236 | 0;
+ $25 = HEAP32[$rank91 >> 2] | 0;
+ $cmp92 = ($24 | 0) < ($25 | 0);
+ $_ = $cmp92 ? $24 : $25;
+ $rank102 = $call + 236 | 0;
+ HEAP32[$rank102 >> 2] = $_;
+ label = 21;
+ break;
+ case 21:
+ $inc104 = $r_052 + 1 | 0;
+ $26 = HEAP16[$maxrank >> 1] | 0;
+ $conv2 = $26 << 16 >> 16;
+ $cmp = ($inc104 | 0) > ($conv2 | 0);
+ if ($cmp) {
+ label = 22;
+ break;
+ } else {
+ $r_052 = $inc104;
+ label = 4;
+ break;
+ }
+ case 22:
+ return;
+ }
+}
+function _ports_eq($e, $f) {
+ $e = $e | 0;
+ $f = $f | 0;
+ var $defined = 0, $0 = 0, $defined3 = 0, $1 = 0, $cmp = 0, $x = 0, $2 = 0.0, $x11 = 0, $3 = 0.0, $cmp12 = 0, $y = 0, $4 = 0.0, $y21 = 0, $5 = 0.0, $cmp22 = 0, $6 = 0, $cmp28 = 0, $x32 = 0, $7 = 0.0, $x36 = 0, $8 = 0.0, $cmp37 = 0, $y43 = 0, $9 = 0.0, $y47 = 0, $10 = 0.0, $cmp48 = 0, $defined52 = 0, $11 = 0, $cmp54 = 0, $phitmp = 0, $12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $defined = $e + 100 | 0;
+ $0 = HEAP8[$defined] | 0;
+ $defined3 = $f + 100 | 0;
+ $1 = HEAP8[$defined3] | 0;
+ $cmp = $0 << 24 >> 24 == $1 << 24 >> 24;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $12 = 0;
+ label = 9;
+ break;
+ }
+ case 3:
+ $x = $e + 72 | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x11 = $f + 72 | 0;
+ $3 = +HEAPF64[$x11 >> 3];
+ $cmp12 = $2 == $3;
+ if ($cmp12) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $y = $e + 80 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y21 = $f + 80 | 0;
+ $5 = +HEAPF64[$y21 >> 3];
+ $cmp22 = $4 == $5;
+ if ($cmp22) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $6 = HEAP8[$defined] | 0;
+ $cmp28 = $6 << 24 >> 24 == 0;
+ if ($cmp28) {
+ label = 6;
+ break;
+ } else {
+ $12 = 0;
+ label = 9;
+ break;
+ }
+ case 6:
+ $x32 = $e + 32 | 0;
+ $7 = +HEAPF64[$x32 >> 3];
+ $x36 = $f + 32 | 0;
+ $8 = +HEAPF64[$x36 >> 3];
+ $cmp37 = $7 == $8;
+ if ($cmp37) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $y43 = $e + 40 | 0;
+ $9 = +HEAPF64[$y43 >> 3];
+ $y47 = $f + 40 | 0;
+ $10 = +HEAPF64[$y47 >> 3];
+ $cmp48 = $9 == $10;
+ if ($cmp48) {
+ $12 = 1;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $defined52 = $e + 60 | 0;
+ $11 = HEAP8[$defined52] | 0;
+ $cmp54 = $11 << 24 >> 24 == 0;
+ $phitmp = $cmp54 & 1;
+ $12 = $phitmp;
+ label = 9;
+ break;
+ case 9:
+ return $12 | 0;
+ }
+ return 0;
+}
+function _set_aspect($g, $asp) {
+ $g = $g | 0;
+ $asp = $asp | 0;
+ var $maxrank = 0, $0 = 0, $cmp = 0, $drawing = 0, $1 = 0, $ratio_kind = 0, $2 = 0, $tobool = 0, $x = 0, $3 = 0.0, $x6 = 0, $4 = 0.0, $sub = 0.0, $conv7 = 0, $y = 0, $5 = 0.0, $y15 = 0, $6 = 0.0, $sub16 = 0.0, $conv17 = 0, $rankdir = 0, $7 = 0, $and20 = 0, $tobool21 = 0, $conv17_conv7 = 0, $conv7_conv17 = 0, $cmp30 = 0, $call = 0, $cmp36 = 0, $conv38 = 0, $filled_0 = 0, $tobool40 = 0, $8 = 0, $x44 = 0, $9 = 0.0, $cmp45 = 0, $conv54 = 0.0, $div = 0.0, $y58 = 0, $10 = 0.0, $conv60 = 0.0, $div61 = 0.0, $cmp62 = 0, $cmp64 = 0, $or_cond = 0, $cmp67 = 0, $div70 = 0.0, $div72 = 0.0, $ratio_kind79 = 0, $11 = 0, $x86 = 0, $12 = 0.0, $cmp87 = 0, $13 = 0.0, $div99 = 0.0, $y103 = 0, $14 = 0.0, $15 = 0.0, $div108 = 0.0, $cmp109 = 0, $cmp112 = 0, $or_cond61 = 0, $cmp115 = 0, $cond = 0.0, $ratio = 0, $16 = 0.0, $conv130 = 0.0, $conv132 = 0.0, $div133 = 0.0, $cmp134 = 0, $div137 = 0.0, $div139 = 0.0, $yf_0_ph = 0.0, $xf_0_ph = 0.0, $17 = 0, $and150 = 0, $tobool151 = 0, $yf_0_xf_0 = 0.0, $xf_0_yf_0 = 0.0, $nlist = 0, $n_064 = 0, $tobool15665 = 0, $n_066 = 0, $x158 = 0, $18 = 0.0, $mul = 0.0, $cmp159 = 0, $add = 0.0, $sub172 = 0.0, $add_sink = 0.0, $conv166 = 0, $conv176 = 0.0, $y182 = 0, $19 = 0.0, $mul183 = 0.0, $cmp184 = 0, $add191 = 0.0, $sub198 = 0.0, $add191_sink = 0.0, $conv192 = 0, $conv202 = 0.0, $next = 0, $n_0 = 0, $tobool156 = 0, $tobool209 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _rec_bb($g, $g);
+ $maxrank = $g + 250 | 0;
+ $0 = HEAP16[$maxrank >> 1] | 0;
+ $cmp = $0 << 16 >> 16 > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 3:
+ $drawing = $g + 48 | 0;
+ $1 = HEAP32[$drawing >> 2] | 0;
+ $ratio_kind = $1 + 84 | 0;
+ $2 = HEAP32[$ratio_kind >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 29;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $x = $g + 72 | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $x6 = $g + 56 | 0;
+ $4 = +HEAPF64[$x6 >> 3];
+ $sub = $3 - $4;
+ $conv7 = ~~$sub;
+ $y = $g + 80 | 0;
+ $5 = +HEAPF64[$y >> 3];
+ $y15 = $g + 64 | 0;
+ $6 = +HEAPF64[$y15 >> 3];
+ $sub16 = $5 - $6;
+ $conv17 = ~~$sub16;
+ $rankdir = $g + 156 | 0;
+ $7 = HEAP32[$rankdir >> 2] | 0;
+ $and20 = $7 & 1;
+ $tobool21 = ($and20 | 0) == 0;
+ $conv17_conv7 = $tobool21 ? $conv17 : $conv7;
+ $conv7_conv17 = $tobool21 ? $conv7 : $conv17;
+ $cmp30 = ($2 | 0) == 4;
+ if ($cmp30) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call = _idealsize($g) | 0;
+ $filled_0 = $call;
+ label = 7;
+ break;
+ case 6:
+ $cmp36 = ($2 | 0) == 2;
+ $conv38 = $cmp36 & 1;
+ $filled_0 = $conv38;
+ label = 7;
+ break;
+ case 7:
+ $tobool40 = $filled_0 << 24 >> 24 == 0;
+ $8 = HEAP32[$drawing >> 2] | 0;
+ if ($tobool40) {
+ label = 13;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $x44 = $8 + 64 | 0;
+ $9 = +HEAPF64[$x44 >> 3];
+ $cmp45 = $9 > 0.0;
+ if ($cmp45) {
+ label = 9;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 9:
+ $conv54 = +($conv7_conv17 | 0);
+ $div = $9 / $conv54;
+ $y58 = $8 + 72 | 0;
+ $10 = +HEAPF64[$y58 >> 3];
+ $conv60 = +($conv17_conv7 | 0);
+ $div61 = $10 / $conv60;
+ $cmp62 = $div < 1.0;
+ $cmp64 = $div61 < 1.0;
+ $or_cond = $cmp62 | $cmp64;
+ if ($or_cond) {
+ label = 10;
+ break;
+ } else {
+ $xf_0_ph = $div;
+ $yf_0_ph = $div61;
+ label = 20;
+ break;
+ }
+ case 10:
+ $cmp67 = $div < $div61;
+ if ($cmp67) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $div70 = $div61 / $div;
+ $xf_0_ph = 1.0;
+ $yf_0_ph = $div70;
+ label = 20;
+ break;
+ case 12:
+ $div72 = $div / $div61;
+ $xf_0_ph = $div72;
+ $yf_0_ph = 1.0;
+ label = 20;
+ break;
+ case 13:
+ $ratio_kind79 = $8 + 84 | 0;
+ $11 = HEAP32[$ratio_kind79 >> 2] | 0;
+ if (($11 | 0) == 5) {
+ label = 14;
+ break;
+ } else if (($11 | 0) == 1) {
+ label = 17;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 14:
+ $x86 = $8 + 64 | 0;
+ $12 = +HEAPF64[$x86 >> 3];
+ $cmp87 = $12 > 0.0;
+ if ($cmp87) {
+ label = 15;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 15:
+ $13 = +HEAPF64[$x >> 3];
+ $div99 = $12 / $13;
+ $y103 = $8 + 72 | 0;
+ $14 = +HEAPF64[$y103 >> 3];
+ $15 = +HEAPF64[$y >> 3];
+ $div108 = $14 / $15;
+ $cmp109 = $div99 > 1.0;
+ $cmp112 = $div108 > 1.0;
+ $or_cond61 = $cmp109 & $cmp112;
+ if ($or_cond61) {
+ label = 16;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 16:
+ $cmp115 = $div99 < $div108;
+ $cond = $cmp115 ? $div99 : $div108;
+ $xf_0_ph = $cond;
+ $yf_0_ph = $cond;
+ label = 20;
+ break;
+ case 17:
+ $ratio = $8 + 16 | 0;
+ $16 = +HEAPF64[$ratio >> 3];
+ $conv130 = +($conv17_conv7 | 0);
+ $conv132 = +($conv7_conv17 | 0);
+ $div133 = $conv130 / $conv132;
+ $cmp134 = $div133 < $16;
+ if ($cmp134) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $div137 = $16 / $div133;
+ $xf_0_ph = 1.0;
+ $yf_0_ph = $div137;
+ label = 20;
+ break;
+ case 19:
+ $div139 = $div133 / $16;
+ $xf_0_ph = $div139;
+ $yf_0_ph = 1.0;
+ label = 20;
+ break;
+ case 20:
+ $17 = HEAP32[$rankdir >> 2] | 0;
+ $and150 = $17 & 1;
+ $tobool151 = ($and150 | 0) == 0;
+ $yf_0_xf_0 = $tobool151 ? $yf_0_ph : $xf_0_ph;
+ $xf_0_yf_0 = $tobool151 ? $xf_0_ph : $yf_0_ph;
+ $nlist = $g + 220 | 0;
+ $n_064 = HEAP32[$nlist >> 2] | 0;
+ $tobool15665 = ($n_064 | 0) == 0;
+ if ($tobool15665) {
+ label = 28;
+ break;
+ } else {
+ $n_066 = $n_064;
+ label = 21;
+ break;
+ }
+ case 21:
+ $x158 = $n_066 + 32 | 0;
+ $18 = +HEAPF64[$x158 >> 3];
+ $mul = $xf_0_yf_0 * $18;
+ $cmp159 = $mul < 0.0;
+ if ($cmp159) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $add = $mul + .5;
+ $add_sink = $add;
+ label = 24;
+ break;
+ case 23:
+ $sub172 = $mul + -.5;
+ $add_sink = $sub172;
+ label = 24;
+ break;
+ case 24:
+ $conv166 = ~~$add_sink;
+ $conv176 = +($conv166 | 0);
+ HEAPF64[$x158 >> 3] = $conv176;
+ $y182 = $n_066 + 40 | 0;
+ $19 = +HEAPF64[$y182 >> 3];
+ $mul183 = $yf_0_xf_0 * $19;
+ $cmp184 = $mul183 < 0.0;
+ if ($cmp184) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $add191 = $mul183 + .5;
+ $add191_sink = $add191;
+ label = 27;
+ break;
+ case 26:
+ $sub198 = $mul183 + -.5;
+ $add191_sink = $sub198;
+ label = 27;
+ break;
+ case 27:
+ $conv192 = ~~$add191_sink;
+ $conv202 = +($conv192 | 0);
+ HEAPF64[$y182 >> 3] = $conv202;
+ $next = $n_066 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool156 = ($n_0 | 0) == 0;
+ if ($tobool156) {
+ label = 28;
+ break;
+ } else {
+ $n_066 = $n_0;
+ label = 21;
+ break;
+ }
+ case 28:
+ _scale_bb($g, $xf_0_yf_0, $yf_0_xf_0);
+ label = 29;
+ break;
+ case 29:
+ $tobool209 = ($asp | 0) == 0;
+ if ($tobool209) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ _adjustAspectRatio($g, $asp);
+ label = 31;
+ break;
+ case 31:
+ return;
+ }
+}
+function _remove_aux_edges($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_030 = 0, $tobool31 = 0, $n_032 = 0, $out = 0, $list = 0, $0 = 0, $1 = 0, $tobool327 = 0, $2 = 0, $i_028 = 0, $3 = 0, $inc = 0, $4 = 0, $arrayidx = 0, $5 = 0, $tobool3 = 0, $_lcssa25 = 0, $tobool8 = 0, $6 = 0, $in = 0, $list14 = 0, $7 = 0, $tobool15 = 0, $8 = 0, $save_out = 0, $9 = 0, $10 = 0, $ld$0$0 = 0, $11$0 = 0, $ld$1$1 = 0, $11$1 = 0, $st$2$0 = 0, $st$3$1 = 0, $save_in = 0, $12 = 0, $13 = 0, $ld$4$0 = 0, $14$0 = 0, $ld$5$1 = 0, $14$1 = 0, $st$6$0 = 0, $st$7$1 = 0, $next = 0, $n_0 = 0, $tobool = 0, $_pr = 0, $tobool342333 = 0, $tobool3423 = 0, $nprev_0_ph35 = 0, $n_1_ph34 = 0, $tobool41 = 0, $next44 = 0, $n_124 = 0, $next37 = 0, $15 = 0, $node_type = 0, $16 = 0, $cmp = 0, $17 = 0, $tobool34 = 0, $18 = 0, $prev = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $n_030 = HEAP32[$nlist >> 2] | 0;
+ $tobool31 = ($n_030 | 0) == 0;
+ if ($tobool31) {
+ label = 18;
+ break;
+ } else {
+ $n_032 = $n_030;
+ label = 3;
+ break;
+ }
+ case 3:
+ $out = $n_032 + 184 | 0;
+ $list = $out | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $tobool327 = ($1 | 0) == 0;
+ if ($tobool327) {
+ $_lcssa25 = $0;
+ label = 5;
+ break;
+ } else {
+ $i_028 = 0;
+ $2 = $1;
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = $2 | 0;
+ _free($3);
+ $inc = $i_028 + 1 | 0;
+ $4 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $4 + ($inc << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool3 = ($5 | 0) == 0;
+ if ($tobool3) {
+ $_lcssa25 = $4;
+ label = 5;
+ break;
+ } else {
+ $i_028 = $inc;
+ $2 = $5;
+ label = 4;
+ break;
+ }
+ case 5:
+ $tobool8 = ($_lcssa25 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $6 = $_lcssa25;
+ _free($6);
+ label = 7;
+ break;
+ case 7:
+ $in = $n_032 + 176 | 0;
+ $list14 = $in | 0;
+ $7 = HEAP32[$list14 >> 2] | 0;
+ $tobool15 = ($7 | 0) == 0;
+ if ($tobool15) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $8 = $7;
+ _free($8);
+ label = 9;
+ break;
+ case 9:
+ $save_out = $n_032 + 256 | 0;
+ $9 = $save_out;
+ $10 = $out;
+ $ld$0$0 = $9 | 0;
+ $11$0 = HEAP32[$ld$0$0 >> 2] | 0;
+ $ld$1$1 = $9 + 4 | 0;
+ $11$1 = HEAP32[$ld$1$1 >> 2] | 0;
+ $st$2$0 = $10 | 0;
+ HEAP32[$st$2$0 >> 2] = $11$0;
+ $st$3$1 = $10 + 4 | 0;
+ HEAP32[$st$3$1 >> 2] = $11$1;
+ $save_in = $n_032 + 248 | 0;
+ $12 = $save_in;
+ $13 = $in;
+ $ld$4$0 = $12 | 0;
+ $14$0 = HEAP32[$ld$4$0 >> 2] | 0;
+ $ld$5$1 = $12 + 4 | 0;
+ $14$1 = HEAP32[$ld$5$1 >> 2] | 0;
+ $st$6$0 = $13 | 0;
+ HEAP32[$st$6$0 >> 2] = $14$0;
+ $st$7$1 = $13 + 4 | 0;
+ HEAP32[$st$7$1 >> 2] = $14$1;
+ $next = $n_032 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ $n_032 = $n_0;
+ label = 3;
+ break;
+ }
+ case 10:
+ $_pr = HEAP32[$nlist >> 2] | 0;
+ $tobool342333 = ($_pr | 0) == 0;
+ if ($tobool342333) {
+ label = 18;
+ break;
+ } else {
+ $n_1_ph34 = $_pr;
+ $nprev_0_ph35 = 0;
+ label = 12;
+ break;
+ }
+ case 11:
+ $tobool3423 = ($15 | 0) == 0;
+ if ($tobool3423) {
+ label = 18;
+ break;
+ } else {
+ $n_1_ph34 = $15;
+ $nprev_0_ph35 = $n_124;
+ label = 12;
+ break;
+ }
+ case 12:
+ $tobool41 = ($nprev_0_ph35 | 0) == 0;
+ $next44 = $nprev_0_ph35 + 168 | 0;
+ $n_124 = $n_1_ph34;
+ label = 13;
+ break;
+ case 13:
+ $next37 = $n_124 + 168 | 0;
+ $15 = HEAP32[$next37 >> 2] | 0;
+ $node_type = $n_124 + 162 | 0;
+ $16 = HEAP8[$node_type] | 0;
+ $cmp = $16 << 24 >> 24 == 2;
+ if ($cmp) {
+ label = 14;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 14:
+ if ($tobool41) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ HEAP32[$next44 >> 2] = $15;
+ label = 17;
+ break;
+ case 16:
+ HEAP32[$nlist >> 2] = $15;
+ label = 17;
+ break;
+ case 17:
+ $17 = $n_124 | 0;
+ _free($17);
+ $tobool34 = ($15 | 0) == 0;
+ if ($tobool34) {
+ label = 18;
+ break;
+ } else {
+ $n_124 = $15;
+ label = 13;
+ break;
+ }
+ case 18:
+ $18 = HEAP32[$nlist >> 2] | 0;
+ $prev = $18 + 172 | 0;
+ HEAP32[$prev >> 2] = 0;
+ return;
+ }
+}
+function _make_leafslots($g) {
+ $g = $g | 0;
+ var $minrank = 0, $0 = 0, $maxrank = 0, $1 = 0, $cmp54 = 0, $conv = 0, $rank = 0, $r_055 = 0, $2 = 0, $n41 = 0, $3 = 0, $cmp642 = 0, $4 = 0, $j_044 = 0, $i_043 = 0, $v12 = 0, $5 = 0, $arrayidx13 = 0, $6 = 0, $order = 0, $ranktype = 0, $7 = 0, $cmp17 = 0, $UF_size = 0, $8 = 0, $_pn = 0, $j_1 = 0, $inc20 = 0, $9 = 0, $n = 0, $10 = 0, $cmp6 = 0, $_lcssa40 = 0, $_lcssa = 0, $j_0_lcssa = 0, $cmp25 = 0, $v32 = 0, $11 = 0, $tobool = 0, $12 = 0, $add37 = 0, $mul = 0, $call = 0, $add38 = 0, $mul39 = 0, $call40 = 0, $call_sink = 0, $13 = 0, $14 = 0, $v44 = 0, $15 = 0, $n48 = 0, $16 = 0, $cmp5050 = 0, $17 = 0, $i_151_in = 0, $i_151 = 0, $v56 = 0, $18 = 0, $arrayidx57 = 0, $19 = 0, $order59 = 0, $20 = 0, $arrayidx64 = 0, $cmp50 = 0, $21 = 0, $_lcssa48 = 0, $n70 = 0, $22 = 0, $v74 = 0, $23 = 0, $arrayidx75 = 0, $inc77 = 0, $24 = 0, $conv2 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $cmp54 = $0 << 16 >> 16 > $1 << 16 >> 16;
+ if ($cmp54) {
+ label = 16;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $r_055 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP32[$rank >> 2] | 0;
+ $n41 = $2 + ($r_055 * 44 & -1) | 0;
+ $3 = HEAP32[$n41 >> 2] | 0;
+ $cmp642 = ($3 | 0) > 0;
+ if ($cmp642) {
+ $i_043 = 0;
+ $j_044 = 0;
+ $4 = $2;
+ label = 5;
+ break;
+ } else {
+ $j_0_lcssa = 0;
+ $_lcssa = $2;
+ $_lcssa40 = $3;
+ label = 8;
+ break;
+ }
+ case 5:
+ $v12 = $4 + ($r_055 * 44 & -1) + 4 | 0;
+ $5 = HEAP32[$v12 >> 2] | 0;
+ $arrayidx13 = $5 + ($i_043 << 2) | 0;
+ $6 = HEAP32[$arrayidx13 >> 2] | 0;
+ $order = $6 + 240 | 0;
+ HEAP32[$order >> 2] = $j_044;
+ $ranktype = $6 + 165 | 0;
+ $7 = HEAP8[$ranktype] | 0;
+ $cmp17 = $7 << 24 >> 24 == 6;
+ if ($cmp17) {
+ label = 6;
+ break;
+ } else {
+ $_pn = 1;
+ label = 7;
+ break;
+ }
+ case 6:
+ $UF_size = $6 + 220 | 0;
+ $8 = HEAP32[$UF_size >> 2] | 0;
+ $_pn = $8;
+ label = 7;
+ break;
+ case 7:
+ $j_1 = $_pn + $j_044 | 0;
+ $inc20 = $i_043 + 1 | 0;
+ $9 = HEAP32[$rank >> 2] | 0;
+ $n = $9 + ($r_055 * 44 & -1) | 0;
+ $10 = HEAP32[$n >> 2] | 0;
+ $cmp6 = ($inc20 | 0) < ($10 | 0);
+ if ($cmp6) {
+ $i_043 = $inc20;
+ $j_044 = $j_1;
+ $4 = $9;
+ label = 5;
+ break;
+ } else {
+ $j_0_lcssa = $j_1;
+ $_lcssa = $9;
+ $_lcssa40 = $10;
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp25 = ($j_0_lcssa | 0) > ($_lcssa40 | 0);
+ if ($cmp25) {
+ label = 9;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 9:
+ $v32 = $_lcssa + ($r_055 * 44 & -1) + 4 | 0;
+ $11 = HEAP32[$v32 >> 2] | 0;
+ $tobool = ($11 | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $12 = $11;
+ $add37 = $j_0_lcssa << 2;
+ $mul = $add37 + 4 | 0;
+ $call = _grealloc($12, $mul) | 0;
+ $call_sink = $call;
+ label = 12;
+ break;
+ case 11:
+ $add38 = $j_0_lcssa << 2;
+ $mul39 = $add38 + 4 | 0;
+ $call40 = _gmalloc($mul39) | 0;
+ $call_sink = $call40;
+ label = 12;
+ break;
+ case 12:
+ $13 = $call_sink;
+ $14 = HEAP32[$rank >> 2] | 0;
+ $v44 = $14 + ($r_055 * 44 & -1) + 4 | 0;
+ HEAP32[$v44 >> 2] = $13;
+ $15 = HEAP32[$rank >> 2] | 0;
+ $n48 = $15 + ($r_055 * 44 & -1) | 0;
+ $16 = HEAP32[$n48 >> 2] | 0;
+ $cmp5050 = ($16 | 0) > 0;
+ if ($cmp5050) {
+ $i_151_in = $16;
+ $17 = $15;
+ label = 13;
+ break;
+ } else {
+ $_lcssa48 = $15;
+ label = 14;
+ break;
+ }
+ case 13:
+ $i_151 = $i_151_in - 1 | 0;
+ $v56 = $17 + ($r_055 * 44 & -1) + 4 | 0;
+ $18 = HEAP32[$v56 >> 2] | 0;
+ $arrayidx57 = $18 + ($i_151 << 2) | 0;
+ $19 = HEAP32[$arrayidx57 >> 2] | 0;
+ $order59 = $19 + 240 | 0;
+ $20 = HEAP32[$order59 >> 2] | 0;
+ $arrayidx64 = $18 + ($20 << 2) | 0;
+ HEAP32[$arrayidx64 >> 2] = $19;
+ $cmp50 = ($i_151 | 0) > 0;
+ $21 = HEAP32[$rank >> 2] | 0;
+ if ($cmp50) {
+ $i_151_in = $i_151;
+ $17 = $21;
+ label = 13;
+ break;
+ } else {
+ $_lcssa48 = $21;
+ label = 14;
+ break;
+ }
+ case 14:
+ $n70 = $_lcssa48 + ($r_055 * 44 & -1) | 0;
+ HEAP32[$n70 >> 2] = $j_0_lcssa;
+ $22 = HEAP32[$rank >> 2] | 0;
+ $v74 = $22 + ($r_055 * 44 & -1) + 4 | 0;
+ $23 = HEAP32[$v74 >> 2] | 0;
+ $arrayidx75 = $23 + ($j_0_lcssa << 2) | 0;
+ HEAP32[$arrayidx75 >> 2] = 0;
+ label = 15;
+ break;
+ case 15:
+ $inc77 = $r_055 + 1 | 0;
+ $24 = HEAP16[$maxrank >> 1] | 0;
+ $conv2 = $24 << 16 >> 16;
+ $cmp = ($inc77 | 0) > ($conv2 | 0);
+ if ($cmp) {
+ label = 16;
+ break;
+ } else {
+ $r_055 = $inc77;
+ label = 4;
+ break;
+ }
+ case 16:
+ return;
+ }
+}
+function _do_leaves($g, $leader) {
+ $g = $g | 0;
+ $leader = $leader | 0;
+ var $lbound = 0, $tmpcast = 0, $tmp = 0, $tmp23 = 0, $tmpcast49 = 0, $tmp93 = 0, $tmpcast48 = 0, $UF_size = 0, $0 = 0, $cmp = 0, $tmpcast47 = 0, $x = 0, $1 = 0.0, $lw = 0, $2 = 0.0, $sub = 0.0, $conv = 0, $x3 = 0, $y = 0, $3 = 0.0, $conv6 = 0, $y7 = 0, $ld$0$0 = 0, $4$0 = 0, $ld$1$1 = 0, $4$1 = 0, $st$2$0 = 0, $st$3$1 = 0, $size = 0, $5 = 0, $cmp9 = 0, $list = 0, $6 = 0, $7 = 0, $head = 0, $8 = 0, $order = 0, $9 = 0, $10 = 0, $11 = 0, $call = 0, $tobool51 = 0, $add = 0, $e_054_in = 0, $j_052 = 0, $e_054 = 0, $tail = 0, $12 = 0, $13 = 0, $cmp15 = 0, $call18 = 0, $cmp19 = 0, $14 = 0, $15 = 0, $inc = 0, $ld$4$0 = 0, $16$0 = 0, $ld$5$1 = 0, $16$1 = 0, $st$6$0 = 0, $st$7$1 = 0, $head24 = 0, $17 = 0, $u25 = 0, $in = 0, $list26 = 0, $18 = 0, $tobool27 = 0, $19 = 0, $size35 = 0, $20 = 0, $21 = 0, $add36 = 0, $mul = 0, $call37 = 0, $size41 = 0, $22 = 0, $23 = 0, $add42 = 0, $mul43 = 0, $call44 = 0, $call37_sink = 0, $24 = 0, $25 = 0, $u46 = 0, $in47 = 0, $list48 = 0, $26 = 0, $u50 = 0, $size52 = 0, $27 = 0, $28 = 0, $inc53 = 0, $29 = 0, $u55 = 0, $in56 = 0, $list57 = 0, $30 = 0, $arrayidx58 = 0, $31 = 0, $u60 = 0, $in61 = 0, $size62 = 0, $32 = 0, $33 = 0, $list66 = 0, $34 = 0, $arrayidx67 = 0, $j_1 = 0, $call69 = 0, $tobool = 0, $list72 = 0, $35 = 0, $36 = 0, $tail74 = 0, $37 = 0, $order76 = 0, $38 = 0, $39 = 0, $40 = 0, $call78 = 0, $tobool8057 = 0, $add77 = 0, $e_160_in = 0, $j_258 = 0, $e_160 = 0, $head82 = 0, $41 = 0, $42 = 0, $cmp83 = 0, $call87 = 0, $cmp88 = 0, $43 = 0, $44 = 0, $inc92 = 0, $ld$8$0 = 0, $45$0 = 0, $ld$9$1 = 0, $45$1 = 0, $st$10$0 = 0, $st$11$1 = 0, $tail95 = 0, $46 = 0, $u96 = 0, $out97 = 0, $list98 = 0, $47 = 0, $tobool99 = 0, $48 = 0, $size108 = 0, $49 = 0, $50 = 0, $add109 = 0, $mul110 = 0, $call111 = 0, $size116 = 0, $51 = 0, $52 = 0, $add117 = 0, $mul118 = 0, $call119 = 0, $call111_sink = 0, $53 = 0, $54 = 0, $u123 = 0, $out124 = 0, $list125 = 0, $55 = 0, $u127 = 0, $size129 = 0, $56 = 0, $57 = 0, $inc130 = 0, $58 = 0, $u132 = 0, $out133 = 0, $list134 = 0, $59 = 0, $arrayidx135 = 0, $60 = 0, $u137 = 0, $out138 = 0, $size139 = 0, $61 = 0, $62 = 0, $list143 = 0, $63 = 0, $arrayidx144 = 0, $j_3 = 0, $call148 = 0, $tobool80 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $lbound = __stackBase__ | 0;
+ $tmpcast = $lbound;
+ $tmp = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmp23 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast49 = $tmp23;
+ $tmp93 = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast48 = $tmp93;
+ $UF_size = $leader + 220 | 0;
+ $0 = HEAP32[$UF_size >> 2] | 0;
+ $cmp = ($0 | 0) < 2;
+ if ($cmp) {
+ label = 22;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tmpcast47 = $tmp;
+ $x = $leader + 32 | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $lw = $leader + 104 | 0;
+ $2 = +HEAPF64[$lw >> 3];
+ $sub = $1 - $2;
+ $conv = ~~$sub;
+ $x3 = $lbound;
+ HEAP32[$x3 >> 2] = $conv;
+ $y = $leader + 40 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $conv6 = ~~$3;
+ $y7 = $tmpcast + 4 | 0;
+ HEAP32[$y7 >> 2] = $conv6;
+ _resize_leaf($tmpcast47, $leader, $tmpcast);
+ $ld$0$0 = $tmp | 0;
+ $4$0 = HEAP32[$ld$0$0 >> 2] | 0;
+ $ld$1$1 = $tmp + 4 | 0;
+ $4$1 = HEAP32[$ld$1$1 >> 2] | 0;
+ $st$2$0 = $lbound | 0;
+ HEAP32[$st$2$0 >> 2] = $4$0;
+ $st$3$1 = $lbound + 4 | 0;
+ HEAP32[$st$3$1 >> 2] = $4$1;
+ $size = $leader + 188 | 0;
+ $5 = HEAP32[$size >> 2] | 0;
+ $cmp9 = ($5 | 0) > 0;
+ if ($cmp9) {
+ label = 4;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 4:
+ $list = $leader + 184 | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $head = $7 + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $order = $leader + 240 | 0;
+ $9 = HEAP32[$order >> 2] | 0;
+ $10 = $g;
+ $11 = $8;
+ $call = _agfstin($10, $11) | 0;
+ $tobool51 = ($call | 0) == 0;
+ if ($tobool51) {
+ label = 22;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add = $9 + 1 | 0;
+ $j_052 = $add;
+ $e_054_in = $call;
+ label = 6;
+ break;
+ case 6:
+ $e_054 = $e_054_in;
+ $tail = $e_054_in + 16 | 0;
+ $12 = HEAP32[$tail >> 2] | 0;
+ $13 = $12;
+ $cmp15 = ($13 | 0) == ($leader | 0);
+ if ($cmp15) {
+ $j_1 = $j_052;
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call18 = _UF_find($13) | 0;
+ $cmp19 = ($call18 | 0) == ($leader | 0);
+ if ($cmp19) {
+ label = 8;
+ break;
+ } else {
+ $j_1 = $j_052;
+ label = 12;
+ break;
+ }
+ case 8:
+ $14 = HEAP32[$tail >> 2] | 0;
+ $15 = $14;
+ $inc = $j_052 + 1 | 0;
+ _place_leaf($tmpcast49, $15, $tmpcast, $j_052);
+ $ld$4$0 = $tmp23 | 0;
+ $16$0 = HEAP32[$ld$4$0 >> 2] | 0;
+ $ld$5$1 = $tmp23 + 4 | 0;
+ $16$1 = HEAP32[$ld$5$1 >> 2] | 0;
+ $st$6$0 = $lbound | 0;
+ HEAP32[$st$6$0 >> 2] = $16$0;
+ $st$7$1 = $lbound + 4 | 0;
+ HEAP32[$st$7$1 >> 2] = $16$1;
+ _unmerge_oneway($e_054);
+ $head24 = $e_054_in + 12 | 0;
+ $17 = HEAP32[$head24 >> 2] | 0;
+ $u25 = $17 + 24 | 0;
+ $in = $u25 + 152 | 0;
+ $list26 = $in;
+ $18 = HEAP32[$list26 >> 2] | 0;
+ $tobool27 = ($18 | 0) == 0;
+ if ($tobool27) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $19 = $18;
+ $size35 = $u25 + 156 | 0;
+ $20 = $size35;
+ $21 = HEAP32[$20 >> 2] | 0;
+ $add36 = $21 << 2;
+ $mul = $add36 + 8 | 0;
+ $call37 = _grealloc($19, $mul) | 0;
+ $call37_sink = $call37;
+ label = 11;
+ break;
+ case 10:
+ $size41 = $u25 + 156 | 0;
+ $22 = $size41;
+ $23 = HEAP32[$22 >> 2] | 0;
+ $add42 = $23 << 2;
+ $mul43 = $add42 + 8 | 0;
+ $call44 = _gmalloc($mul43) | 0;
+ $call37_sink = $call44;
+ label = 11;
+ break;
+ case 11:
+ $24 = $call37_sink;
+ $25 = HEAP32[$head24 >> 2] | 0;
+ $u46 = $25 + 24 | 0;
+ $in47 = $u46 + 152 | 0;
+ $list48 = $in47;
+ HEAP32[$list48 >> 2] = $24;
+ $26 = HEAP32[$head24 >> 2] | 0;
+ $u50 = $26 + 24 | 0;
+ $size52 = $u50 + 156 | 0;
+ $27 = $size52;
+ $28 = HEAP32[$27 >> 2] | 0;
+ $inc53 = $28 + 1 | 0;
+ HEAP32[$27 >> 2] = $inc53;
+ $29 = HEAP32[$head24 >> 2] | 0;
+ $u55 = $29 + 24 | 0;
+ $in56 = $u55 + 152 | 0;
+ $list57 = $in56;
+ $30 = HEAP32[$list57 >> 2] | 0;
+ $arrayidx58 = $30 + ($28 << 2) | 0;
+ HEAP32[$arrayidx58 >> 2] = $e_054;
+ $31 = HEAP32[$head24 >> 2] | 0;
+ $u60 = $31 + 24 | 0;
+ $in61 = $u60 + 152 | 0;
+ $size62 = $u60 + 156 | 0;
+ $32 = $size62;
+ $33 = HEAP32[$32 >> 2] | 0;
+ $list66 = $in61;
+ $34 = HEAP32[$list66 >> 2] | 0;
+ $arrayidx67 = $34 + ($33 << 2) | 0;
+ HEAP32[$arrayidx67 >> 2] = 0;
+ $j_1 = $inc;
+ label = 12;
+ break;
+ case 12:
+ $call69 = _agnxtin($10, $e_054_in) | 0;
+ $tobool = ($call69 | 0) == 0;
+ if ($tobool) {
+ label = 22;
+ break;
+ } else {
+ $j_052 = $j_1;
+ $e_054_in = $call69;
+ label = 6;
+ break;
+ }
+ case 13:
+ $list72 = $leader + 176 | 0;
+ $35 = HEAP32[$list72 >> 2] | 0;
+ $36 = HEAP32[$35 >> 2] | 0;
+ $tail74 = $36 + 16 | 0;
+ $37 = HEAP32[$tail74 >> 2] | 0;
+ $order76 = $leader + 240 | 0;
+ $38 = HEAP32[$order76 >> 2] | 0;
+ $39 = $g;
+ $40 = $37;
+ $call78 = _agfstout($39, $40) | 0;
+ $tobool8057 = ($call78 | 0) == 0;
+ if ($tobool8057) {
+ label = 22;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $add77 = $38 + 1 | 0;
+ $j_258 = $add77;
+ $e_160_in = $call78;
+ label = 15;
+ break;
+ case 15:
+ $e_160 = $e_160_in;
+ $head82 = $e_160_in + 12 | 0;
+ $41 = HEAP32[$head82 >> 2] | 0;
+ $42 = $41;
+ $cmp83 = ($42 | 0) == ($leader | 0);
+ if ($cmp83) {
+ $j_3 = $j_258;
+ label = 21;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $call87 = _UF_find($42) | 0;
+ $cmp88 = ($call87 | 0) == ($leader | 0);
+ if ($cmp88) {
+ label = 17;
+ break;
+ } else {
+ $j_3 = $j_258;
+ label = 21;
+ break;
+ }
+ case 17:
+ $43 = HEAP32[$head82 >> 2] | 0;
+ $44 = $43;
+ $inc92 = $j_258 + 1 | 0;
+ _place_leaf($tmpcast48, $44, $tmpcast, $j_258);
+ $ld$8$0 = $tmp93 | 0;
+ $45$0 = HEAP32[$ld$8$0 >> 2] | 0;
+ $ld$9$1 = $tmp93 + 4 | 0;
+ $45$1 = HEAP32[$ld$9$1 >> 2] | 0;
+ $st$10$0 = $lbound | 0;
+ HEAP32[$st$10$0 >> 2] = $45$0;
+ $st$11$1 = $lbound + 4 | 0;
+ HEAP32[$st$11$1 >> 2] = $45$1;
+ _unmerge_oneway($e_160);
+ $tail95 = $e_160_in + 16 | 0;
+ $46 = HEAP32[$tail95 >> 2] | 0;
+ $u96 = $46 + 24 | 0;
+ $out97 = $u96 + 160 | 0;
+ $list98 = $out97;
+ $47 = HEAP32[$list98 >> 2] | 0;
+ $tobool99 = ($47 | 0) == 0;
+ if ($tobool99) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $48 = $47;
+ $size108 = $u96 + 164 | 0;
+ $49 = $size108;
+ $50 = HEAP32[$49 >> 2] | 0;
+ $add109 = $50 << 2;
+ $mul110 = $add109 + 8 | 0;
+ $call111 = _grealloc($48, $mul110) | 0;
+ $call111_sink = $call111;
+ label = 20;
+ break;
+ case 19:
+ $size116 = $u96 + 164 | 0;
+ $51 = $size116;
+ $52 = HEAP32[$51 >> 2] | 0;
+ $add117 = $52 << 2;
+ $mul118 = $add117 + 8 | 0;
+ $call119 = _gmalloc($mul118) | 0;
+ $call111_sink = $call119;
+ label = 20;
+ break;
+ case 20:
+ $53 = $call111_sink;
+ $54 = HEAP32[$tail95 >> 2] | 0;
+ $u123 = $54 + 24 | 0;
+ $out124 = $u123 + 160 | 0;
+ $list125 = $out124;
+ HEAP32[$list125 >> 2] = $53;
+ $55 = HEAP32[$tail95 >> 2] | 0;
+ $u127 = $55 + 24 | 0;
+ $size129 = $u127 + 164 | 0;
+ $56 = $size129;
+ $57 = HEAP32[$56 >> 2] | 0;
+ $inc130 = $57 + 1 | 0;
+ HEAP32[$56 >> 2] = $inc130;
+ $58 = HEAP32[$tail95 >> 2] | 0;
+ $u132 = $58 + 24 | 0;
+ $out133 = $u132 + 160 | 0;
+ $list134 = $out133;
+ $59 = HEAP32[$list134 >> 2] | 0;
+ $arrayidx135 = $59 + ($57 << 2) | 0;
+ HEAP32[$arrayidx135 >> 2] = $e_160;
+ $60 = HEAP32[$tail95 >> 2] | 0;
+ $u137 = $60 + 24 | 0;
+ $out138 = $u137 + 160 | 0;
+ $size139 = $u137 + 164 | 0;
+ $61 = $size139;
+ $62 = HEAP32[$61 >> 2] | 0;
+ $list143 = $out138;
+ $63 = HEAP32[$list143 >> 2] | 0;
+ $arrayidx144 = $63 + ($62 << 2) | 0;
+ HEAP32[$arrayidx144 >> 2] = 0;
+ $j_3 = $inc92;
+ label = 21;
+ break;
+ case 21:
+ $call148 = _agnxtout($39, $e_160_in) | 0;
+ $tobool80 = ($call148 | 0) == 0;
+ if ($tobool80) {
+ label = 22;
+ break;
+ } else {
+ $j_258 = $j_3;
+ $e_160_in = $call148;
+ label = 15;
+ break;
+ }
+ case 22:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _resize_leaf($agg_result, $leaf, $lbound) {
+ $agg_result = $agg_result | 0;
+ $leaf = $leaf | 0;
+ $lbound = $lbound | 0;
+ var $graph = 0, $x = 0, $lw = 0, $10 = 0, $11 = 0, $12$1 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $lbound;
+ $lbound = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$lbound >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$lbound + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ $graph = $leaf + 20 | 0;
+ _gv_nodesize($leaf, HEAP32[(HEAP32[$graph >> 2] | 0) + 156 >> 2] & 1);
+ HEAPF64[$leaf + 40 >> 3] = +(HEAP32[$lbound + 4 >> 2] | 0);
+ $x = $lbound | 0;
+ $lw = $leaf + 104 | 0;
+ HEAPF64[$leaf + 32 >> 3] = +(HEAP32[$x >> 2] | 0) + +HEAPF64[$lw >> 3];
+ HEAP32[$x >> 2] = ~~(+(HEAP32[$x >> 2] | 0) + +HEAPF64[$lw >> 3] + +HEAPF64[$leaf + 112 >> 3] + +(HEAP32[(HEAP32[$graph >> 2] | 0) + 260 >> 2] | 0));
+ $10 = $lbound;
+ $11 = $agg_result;
+ $12$1 = HEAP32[$10 + 4 >> 2] | 0;
+ HEAP32[$11 >> 2] = HEAP32[$10 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = $12$1;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _place_leaf($agg_result, $leaf, $lbound, $order) {
+ $agg_result = $agg_result | 0;
+ $leaf = $leaf | 0;
+ $lbound = $lbound | 0;
+ $order = $order | 0;
+ var $graph = 0, $0 = 0, $call = 0, $cmp = 0, $order1 = 0, $rank = 0, $1 = 0, $rank4 = 0, $2 = 0, $rank10 = 0, $3 = 0, $v = 0, $4 = 0, $arrayidx11 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $lbound;
+ $lbound = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$lbound >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$lbound + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $graph = $leaf + 20 | 0;
+ $0 = HEAP32[$graph >> 2] | 0;
+ $call = _UF_find($leaf) | 0;
+ $cmp = ($call | 0) == ($leaf | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _fast_nodeapp($call, $leaf);
+ label = 4;
+ break;
+ case 4:
+ $order1 = $leaf + 240 | 0;
+ HEAP32[$order1 >> 2] = $order;
+ $rank = $call + 236 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $rank4 = $leaf + 236 | 0;
+ HEAP32[$rank4 >> 2] = $1;
+ $2 = HEAP32[$order1 >> 2] | 0;
+ $rank10 = $0 + 224 | 0;
+ $3 = HEAP32[$rank10 >> 2] | 0;
+ $v = $3 + ($1 * 44 & -1) + 4 | 0;
+ $4 = HEAP32[$v >> 2] | 0;
+ $arrayidx11 = $4 + ($2 << 2) | 0;
+ HEAP32[$arrayidx11 >> 2] = $leaf;
+ _resize_leaf($agg_result, $leaf, $lbound);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _rec_bb($g, $root) {
+ $g = $g | 0;
+ $root = $root | 0;
+ var $n_cluster = 0, $0 = 0, $cmp6 = 0, $clust = 0, $c_07 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $inc = 0, $3 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp6 = ($0 | 0) < 1;
+ if ($cmp6) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $c_07 = 1;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $1 + ($c_07 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _rec_bb($2, $root);
+ $inc = $c_07 + 1 | 0;
+ $3 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($3 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $c_07 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ _dot_compute_bb($g, $root);
+ return;
+ }
+}
+function _idealsize($g) {
+ $g = $g | 0;
+ var $relpage = 0, $margin = 0, $tmp = 0, $tmp5 = 0, $drawing = 0, $0 = 0, $page = 0, $1 = 0, $2 = 0, $x = 0, $3 = 0.0, $cmp = 0, $y = 0, $4 = 0.0, $cmp1 = 0, $5 = 0, $margin4 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $x7 = 0, $10 = 0.0, $y12 = 0, $11 = 0.0, $12 = 0.0, $div = 0.0, $13 = 0.0, $div18 = 0.0, $cmp19 = 0, $cmp20 = 0, $or_cond = 0, $cmp23 = 0, $cond = 0.0, $cmp24 = 0, $cond28 = 0.0, $mul = 0.0, $div31 = 0.0, $call = 0.0, $mul33 = 0.0, $div35 = 0.0, $mul37 = 0.0, $div39 = 0.0, $call40 = 0.0, $mul42 = 0.0, $div44 = 0.0, $mul46 = 0.0, $14 = 0, $x49 = 0, $mul51 = 0.0, $15 = 0, $y55 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $relpage = __stackBase__ | 0;
+ $margin = __stackBase__ + 16 | 0;
+ $tmp = __stackBase__ + 32 | 0;
+ $tmp5 = __stackBase__ + 48 | 0;
+ $drawing = $g + 48 | 0;
+ $0 = HEAP32[$drawing >> 2] | 0;
+ $page = $0 + 48 | 0;
+ $1 = $relpage;
+ $2 = $page;
+ HEAP32[$1 >> 2] = HEAP32[$2 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$2 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$2 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$2 + 12 >> 2] | 0;
+ $x = $relpage | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $cmp = $3 < .001;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $y = $relpage + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $cmp1 = $4 < .001;
+ if ($cmp1) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $5 = HEAP32[$drawing >> 2] | 0;
+ $margin4 = $5 + 32 | 0;
+ $6 = $margin;
+ $7 = $margin4;
+ HEAP32[$6 >> 2] = HEAP32[$7 >> 2] | 0;
+ HEAP32[$6 + 4 >> 2] = HEAP32[$7 + 4 >> 2] | 0;
+ HEAP32[$6 + 8 >> 2] = HEAP32[$7 + 8 >> 2] | 0;
+ HEAP32[$6 + 12 >> 2] = HEAP32[$7 + 12 >> 2] | 0;
+ _sub_pointf3019($tmp, $relpage, $margin);
+ $8 = $tmp;
+ HEAP32[$1 >> 2] = HEAP32[$8 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$8 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$8 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$8 + 12 >> 2] | 0;
+ _sub_pointf3019($tmp5, $relpage, $margin);
+ $9 = $tmp5;
+ HEAP32[$1 >> 2] = HEAP32[$9 >> 2] | 0;
+ HEAP32[$1 + 4 >> 2] = HEAP32[$9 + 4 >> 2] | 0;
+ HEAP32[$1 + 8 >> 2] = HEAP32[$9 + 8 >> 2] | 0;
+ HEAP32[$1 + 12 >> 2] = HEAP32[$9 + 12 >> 2] | 0;
+ $x7 = $g + 72 | 0;
+ $10 = +HEAPF64[$x7 >> 3];
+ $y12 = $g + 80 | 0;
+ $11 = +HEAPF64[$y12 >> 3];
+ $12 = +HEAPF64[$x >> 3];
+ $div = $12 / $10;
+ $13 = +HEAPF64[$y >> 3];
+ $div18 = $13 / $11;
+ $cmp19 = $div < 1.0;
+ $cmp20 = $div18 < 1.0;
+ $or_cond = $cmp19 | $cmp20;
+ if ($or_cond) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $cmp23 = $div < $div18;
+ $cond = $cmp23 ? $div : $div18;
+ $cmp24 = $cond > .5;
+ $cond28 = $cmp24 ? $cond : .5;
+ $mul = $10 * $cond28;
+ $div31 = $mul / $12;
+ $call = +Math_ceil(+$div31);
+ $mul33 = $12 * $call;
+ $div35 = $mul33 / $10;
+ $mul37 = $11 * $cond28;
+ $div39 = $mul37 / $13;
+ $call40 = +Math_ceil(+$div39);
+ $mul42 = $13 * $call40;
+ $div44 = $mul42 / $11;
+ $mul46 = $10 * $div35;
+ $14 = HEAP32[$drawing >> 2] | 0;
+ $x49 = $14 + 64 | 0;
+ HEAPF64[$x49 >> 3] = $mul46;
+ $mul51 = $11 * $div44;
+ $15 = HEAP32[$drawing >> 2] | 0;
+ $y55 = $15 + 72 | 0;
+ HEAPF64[$y55 >> 3] = $mul51;
+ $retval_0 = 1;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _make_aux_edge($u, $v, $len, $wt) {
+ $u = $u | 0;
+ $v = $v | 0;
+ $len = +$len;
+ $wt = $wt | 0;
+ var $call = 0, $0 = 0, $tail = 0, $1 = 0, $head = 0, $2 = 0, $cmp = 0, $cmp1 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $conv3 = 0, $minlen = 0, $3 = 0, $conv5 = 0.0, $weight = 0, $4 = 0, $call7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _zmalloc(192) | 0;
+ $0 = $call;
+ $tail = $call + 16 | 0;
+ $1 = $tail;
+ HEAP32[$1 >> 2] = $u;
+ $head = $call + 12 | 0;
+ $2 = $head;
+ HEAP32[$2 >> 2] = $v;
+ $cmp = $len > 65535.0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _largeMinlen($len);
+ return 0;
+ case 4:
+ $cmp1 = $len < 0.0;
+ if ($cmp1) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add = $len + .5;
+ $add_sink = $add;
+ label = 7;
+ break;
+ case 6:
+ $sub = $len + -.5;
+ $add_sink = $sub;
+ label = 7;
+ break;
+ case 7:
+ $conv = ~~$add_sink;
+ $conv3 = $conv & 65535;
+ $minlen = $call + 186 | 0;
+ $3 = $minlen;
+ HEAP16[$3 >> 1] = $conv3;
+ $conv5 = +($wt | 0);
+ $weight = $call + 172 | 0;
+ $4 = $weight;
+ HEAPF32[$4 >> 2] = $conv5;
+ $call7 = _fast_edge($0) | 0;
+ return $0 | 0;
+ }
+ return 0;
+}
+function _largeMinlen($l) {
+ $l = +$l;
+ _agerr(1, 100240, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $l, HEAP32[tempInt + 8 >> 2] = 65535, tempInt) | 0);
+ _exit(1);
+}
+function _sub_pointf3019($agg_result, $p, $q) {
+ $agg_result = $agg_result | 0;
+ $p = $p | 0;
+ $q = $q | 0;
+ var $sub4 = 0.0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ tempParam = $q;
+ $q = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$q >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$q + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$q + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$q + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ $sub4 = +HEAPF64[$p + 8 >> 3] - +HEAPF64[$q + 8 >> 3];
+ HEAPF64[$agg_result >> 3] = +HEAPF64[$p >> 3] - +HEAPF64[$q >> 3];
+ HEAPF64[$agg_result + 8 >> 3] = $sub4;
+ STACKTOP = __stackBase__;
+ return;
+}
+function _dot_compute_bb($g, $root) {
+ $g = $g | 0;
+ $root = $root | 0;
+ var $root1 = 0, $0 = 0, $cmp = 0, $minrank = 0, $1 = 0, $maxrank = 0, $2 = 0, $cmp678 = 0, $conv = 0, $rank = 0, $3 = 0, $4 = 0, $conv5 = 0, $UR_sroa_0_0_lcssa = 0.0, $LL_sroa_0_0_lcssa = 0.0, $n_cluster = 0, $5 = 0, $cmp9460 = 0, $clust = 0, $6 = 0, $7 = 0, $r_081 = 0, $UR_sroa_0_080 = 0.0, $LL_sroa_0_079 = 0.0, $n = 0, $8 = 0, $cmp9 = 0, $v15 = 0, $9 = 0, $10 = 0, $cmp17 = 0, $node_type65 = 0, $11 = 0, $cmp2466 = 0, $cmp2667 = 0, $or_cond68 = 0, $12 = 0, $v32 = 0, $13 = 0, $c_069 = 0, $arrayidx33 = 0, $14 = 0, $inc = 0, $node_type = 0, $15 = 0, $cmp24 = 0, $cmp26 = 0, $or_cond = 0, $_lcssa = 0, $v_0_lcssa = 0, $cmp37 = 0, $x41 = 0, $16 = 0.0, $lw = 0, $17 = 0.0, $sub = 0.0, $conv43 = 0, $conv45 = 0.0, $cmp46 = 0, $LL_sroa_0_0_conv45 = 0.0, $sub52 = 0, $18 = 0, $v56 = 0, $19 = 0, $arrayidx57 = 0, $v_172 = 0, $node_type6173 = 0, $20 = 0, $cmp6374 = 0, $sub58 = 0, $21 = 0, $v69 = 0, $22 = 0, $c_175 = 0, $arrayidx70 = 0, $dec = 0, $v_1 = 0, $node_type61 = 0, $23 = 0, $cmp63 = 0, $v_1_lcssa = 0, $x75 = 0, $24 = 0.0, $rw = 0, $25 = 0.0, $add = 0.0, $conv77 = 0, $conv79 = 0.0, $cmp80 = 0, $UR_sroa_0_0_conv79 = 0.0, $LL_sroa_0_1 = 0.0, $UR_sroa_0_1 = 0.0, $inc90 = 0, $cmp6 = 0, $UR_sroa_0_263 = 0.0, $c_262 = 0, $LL_sroa_0_261 = 0.0, $arrayidx98 = 0, $26 = 0, $x101 = 0, $27 = 0.0, $sub103 = 0.0, $conv104 = 0, $conv106 = 0.0, $cmp107 = 0, $LL_sroa_0_2_conv106 = 0.0, $x122 = 0, $28 = 0.0, $add124 = 0.0, $conv125 = 0, $conv127 = 0.0, $cmp128 = 0, $cond135 = 0.0, $inc138 = 0, $cmp94 = 0, $ln = 0, $29 = 0, $rank143 = 0, $30 = 0, $conv144 = 0.0, $rn = 0, $31 = 0, $rank148 = 0, $32 = 0, $conv149 = 0.0, $LL_sroa_0_3 = 0.0, $UR_sroa_0_3 = 0.0, $maxrank153 = 0, $33 = 0, $idxprom = 0, $rank155 = 0, $34 = 0, $v157 = 0, $35 = 0, $36 = 0, $y = 0, $37 = 0.0, $ht1 = 0, $38 = 0, $conv162 = 0.0, $sub163 = 0.0, $minrank166 = 0, $39 = 0, $idxprom167 = 0, $v171 = 0, $40 = 0, $41 = 0, $y175 = 0, $42 = 0.0, $ht2 = 0, $43 = 0, $conv177 = 0.0, $add178 = 0.0, $LL_sroa_0_0__idx = 0, $LL_sroa_1_8__idx11 = 0, $UR_sroa_0_0__idx = 0, $UR_sroa_1_8__idx7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root1 = $g + 32 | 0;
+ $0 = HEAP32[$root1 >> 2] | 0;
+ $cmp = ($0 | 0) == ($g | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 3:
+ $minrank = $g + 248 | 0;
+ $1 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $cmp678 = $1 << 16 >> 16 > $2 << 16 >> 16;
+ if ($cmp678) {
+ $LL_sroa_0_0_lcssa = 2147483647.0;
+ $UR_sroa_0_0_lcssa = -2147483647.0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv = $1 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $3 = HEAP32[$rank >> 2] | 0;
+ $4 = HEAP16[$maxrank >> 1] | 0;
+ $conv5 = $4 << 16 >> 16;
+ $LL_sroa_0_079 = 2147483647.0;
+ $UR_sroa_0_080 = -2147483647.0;
+ $r_081 = $conv;
+ label = 7;
+ break;
+ case 5:
+ $n_cluster = $g + 212 | 0;
+ $5 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp9460 = ($5 | 0) < 1;
+ if ($cmp9460) {
+ $UR_sroa_0_3 = $UR_sroa_0_0_lcssa;
+ $LL_sroa_0_3 = $LL_sroa_0_0_lcssa;
+ label = 20;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $clust = $g + 216 | 0;
+ $6 = HEAP32[$clust >> 2] | 0;
+ $7 = HEAP32[$n_cluster >> 2] | 0;
+ $LL_sroa_0_261 = $LL_sroa_0_0_lcssa;
+ $c_262 = 1;
+ $UR_sroa_0_263 = $UR_sroa_0_0_lcssa;
+ label = 18;
+ break;
+ case 7:
+ $n = $3 + ($r_081 * 44 & -1) | 0;
+ $8 = HEAP32[$n >> 2] | 0;
+ $cmp9 = ($8 | 0) == 0;
+ if ($cmp9) {
+ $UR_sroa_0_1 = $UR_sroa_0_080;
+ $LL_sroa_0_1 = $LL_sroa_0_079;
+ label = 17;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $v15 = $3 + ($r_081 * 44 & -1) + 4 | 0;
+ $9 = HEAP32[$v15 >> 2] | 0;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $cmp17 = ($10 | 0) == 0;
+ if ($cmp17) {
+ $UR_sroa_0_1 = $UR_sroa_0_080;
+ $LL_sroa_0_1 = $LL_sroa_0_079;
+ label = 17;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $node_type65 = $10 + 162 | 0;
+ $11 = HEAP8[$node_type65] | 0;
+ $cmp2466 = $11 << 24 >> 24 != 0;
+ $cmp2667 = ($8 | 0) > 1;
+ $or_cond68 = $cmp2466 & $cmp2667;
+ if ($or_cond68) {
+ label = 10;
+ break;
+ } else {
+ $v_0_lcssa = $10;
+ $_lcssa = $11;
+ label = 12;
+ break;
+ }
+ case 10:
+ $12 = HEAP32[$rank >> 2] | 0;
+ $v32 = $12 + ($r_081 * 44 & -1) + 4 | 0;
+ $13 = HEAP32[$v32 >> 2] | 0;
+ $c_069 = 1;
+ label = 11;
+ break;
+ case 11:
+ $arrayidx33 = $13 + ($c_069 << 2) | 0;
+ $14 = HEAP32[$arrayidx33 >> 2] | 0;
+ $inc = $c_069 + 1 | 0;
+ $node_type = $14 + 162 | 0;
+ $15 = HEAP8[$node_type] | 0;
+ $cmp24 = $15 << 24 >> 24 != 0;
+ $cmp26 = ($inc | 0) < ($8 | 0);
+ $or_cond = $cmp24 & $cmp26;
+ if ($or_cond) {
+ $c_069 = $inc;
+ label = 11;
+ break;
+ } else {
+ $v_0_lcssa = $14;
+ $_lcssa = $15;
+ label = 12;
+ break;
+ }
+ case 12:
+ $cmp37 = $_lcssa << 24 >> 24 == 0;
+ if ($cmp37) {
+ label = 13;
+ break;
+ } else {
+ $UR_sroa_0_1 = $UR_sroa_0_080;
+ $LL_sroa_0_1 = $LL_sroa_0_079;
+ label = 17;
+ break;
+ }
+ case 13:
+ $x41 = $v_0_lcssa + 32 | 0;
+ $16 = +HEAPF64[$x41 >> 3];
+ $lw = $v_0_lcssa + 104 | 0;
+ $17 = +HEAPF64[$lw >> 3];
+ $sub = $16 - $17;
+ $conv43 = ~~$sub;
+ $conv45 = +($conv43 | 0);
+ $cmp46 = $LL_sroa_0_079 < $conv45;
+ $LL_sroa_0_0_conv45 = $cmp46 ? $LL_sroa_0_079 : $conv45;
+ $sub52 = $8 - 1 | 0;
+ $18 = HEAP32[$rank >> 2] | 0;
+ $v56 = $18 + ($r_081 * 44 & -1) + 4 | 0;
+ $19 = HEAP32[$v56 >> 2] | 0;
+ $arrayidx57 = $19 + ($sub52 << 2) | 0;
+ $v_172 = HEAP32[$arrayidx57 >> 2] | 0;
+ $node_type6173 = $v_172 + 162 | 0;
+ $20 = HEAP8[$node_type6173] | 0;
+ $cmp6374 = $20 << 24 >> 24 == 0;
+ if ($cmp6374) {
+ $v_1_lcssa = $v_172;
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $sub58 = $8 - 2 | 0;
+ $21 = HEAP32[$rank >> 2] | 0;
+ $v69 = $21 + ($r_081 * 44 & -1) + 4 | 0;
+ $22 = HEAP32[$v69 >> 2] | 0;
+ $c_175 = $sub58;
+ label = 15;
+ break;
+ case 15:
+ $arrayidx70 = $22 + ($c_175 << 2) | 0;
+ $dec = $c_175 - 1 | 0;
+ $v_1 = HEAP32[$arrayidx70 >> 2] | 0;
+ $node_type61 = $v_1 + 162 | 0;
+ $23 = HEAP8[$node_type61] | 0;
+ $cmp63 = $23 << 24 >> 24 == 0;
+ if ($cmp63) {
+ $v_1_lcssa = $v_1;
+ label = 16;
+ break;
+ } else {
+ $c_175 = $dec;
+ label = 15;
+ break;
+ }
+ case 16:
+ $x75 = $v_1_lcssa + 32 | 0;
+ $24 = +HEAPF64[$x75 >> 3];
+ $rw = $v_1_lcssa + 112 | 0;
+ $25 = +HEAPF64[$rw >> 3];
+ $add = $24 + $25;
+ $conv77 = ~~$add;
+ $conv79 = +($conv77 | 0);
+ $cmp80 = $UR_sroa_0_080 > $conv79;
+ $UR_sroa_0_0_conv79 = $cmp80 ? $UR_sroa_0_080 : $conv79;
+ $UR_sroa_0_1 = $UR_sroa_0_0_conv79;
+ $LL_sroa_0_1 = $LL_sroa_0_0_conv45;
+ label = 17;
+ break;
+ case 17:
+ $inc90 = $r_081 + 1 | 0;
+ $cmp6 = ($inc90 | 0) > ($conv5 | 0);
+ if ($cmp6) {
+ $LL_sroa_0_0_lcssa = $LL_sroa_0_1;
+ $UR_sroa_0_0_lcssa = $UR_sroa_0_1;
+ label = 5;
+ break;
+ } else {
+ $LL_sroa_0_079 = $LL_sroa_0_1;
+ $UR_sroa_0_080 = $UR_sroa_0_1;
+ $r_081 = $inc90;
+ label = 7;
+ break;
+ }
+ case 18:
+ $arrayidx98 = $6 + ($c_262 << 2) | 0;
+ $26 = HEAP32[$arrayidx98 >> 2] | 0;
+ $x101 = $26 + 56 | 0;
+ $27 = +HEAPF64[$x101 >> 3];
+ $sub103 = $27 + -8.0;
+ $conv104 = ~~$sub103;
+ $conv106 = +($conv104 | 0);
+ $cmp107 = $LL_sroa_0_261 < $conv106;
+ $LL_sroa_0_2_conv106 = $cmp107 ? $LL_sroa_0_261 : $conv106;
+ $x122 = $26 + 72 | 0;
+ $28 = +HEAPF64[$x122 >> 3];
+ $add124 = $28 + 8.0;
+ $conv125 = ~~$add124;
+ $conv127 = +($conv125 | 0);
+ $cmp128 = $UR_sroa_0_263 > $conv127;
+ $cond135 = $cmp128 ? $UR_sroa_0_263 : $conv127;
+ $inc138 = $c_262 + 1 | 0;
+ $cmp94 = ($inc138 | 0) > ($7 | 0);
+ if ($cmp94) {
+ $UR_sroa_0_3 = $cond135;
+ $LL_sroa_0_3 = $LL_sroa_0_2_conv106;
+ label = 20;
+ break;
+ } else {
+ $LL_sroa_0_261 = $LL_sroa_0_2_conv106;
+ $c_262 = $inc138;
+ $UR_sroa_0_263 = $cond135;
+ label = 18;
+ break;
+ }
+ case 19:
+ $ln = $g + 268 | 0;
+ $29 = HEAP32[$ln >> 2] | 0;
+ $rank143 = $29 + 236 | 0;
+ $30 = HEAP32[$rank143 >> 2] | 0;
+ $conv144 = +($30 | 0);
+ $rn = $g + 272 | 0;
+ $31 = HEAP32[$rn >> 2] | 0;
+ $rank148 = $31 + 236 | 0;
+ $32 = HEAP32[$rank148 >> 2] | 0;
+ $conv149 = +($32 | 0);
+ $UR_sroa_0_3 = $conv149;
+ $LL_sroa_0_3 = $conv144;
+ label = 20;
+ break;
+ case 20:
+ $maxrank153 = $g + 250 | 0;
+ $33 = HEAP16[$maxrank153 >> 1] | 0;
+ $idxprom = $33 << 16 >> 16;
+ $rank155 = $root + 224 | 0;
+ $34 = HEAP32[$rank155 >> 2] | 0;
+ $v157 = $34 + ($idxprom * 44 & -1) + 4 | 0;
+ $35 = HEAP32[$v157 >> 2] | 0;
+ $36 = HEAP32[$35 >> 2] | 0;
+ $y = $36 + 40 | 0;
+ $37 = +HEAPF64[$y >> 3];
+ $ht1 = $g + 160 | 0;
+ $38 = HEAP32[$ht1 >> 2] | 0;
+ $conv162 = +($38 | 0);
+ $sub163 = $37 - $conv162;
+ $minrank166 = $g + 248 | 0;
+ $39 = HEAP16[$minrank166 >> 1] | 0;
+ $idxprom167 = $39 << 16 >> 16;
+ $v171 = $34 + ($idxprom167 * 44 & -1) + 4 | 0;
+ $40 = HEAP32[$v171 >> 2] | 0;
+ $41 = HEAP32[$40 >> 2] | 0;
+ $y175 = $41 + 40 | 0;
+ $42 = +HEAPF64[$y175 >> 3];
+ $ht2 = $g + 164 | 0;
+ $43 = HEAP32[$ht2 >> 2] | 0;
+ $conv177 = +($43 | 0);
+ $add178 = $42 + $conv177;
+ $LL_sroa_0_0__idx = $g + 56 | 0;
+ HEAPF64[$LL_sroa_0_0__idx >> 3] = $LL_sroa_0_3;
+ $LL_sroa_1_8__idx11 = $g + 64 | 0;
+ HEAPF64[$LL_sroa_1_8__idx11 >> 3] = $sub163;
+ $UR_sroa_0_0__idx = $g + 72 | 0;
+ HEAPF64[$UR_sroa_0_0__idx >> 3] = $UR_sroa_0_3;
+ $UR_sroa_1_8__idx7 = $g + 80 | 0;
+ HEAPF64[$UR_sroa_1_8__idx7 >> 3] = $add178;
+ return;
+ }
+}
+function _adjustEqual($g, $delta) {
+ $g = $g | 0;
+ $delta = $delta | 0;
+ var $root1 = 0, $0 = 0, $rank2 = 0, $1 = 0, $maxrank = 0, $2 = 0, $conv = 0, $minrank = 0, $3 = 0, $conv5 = 0, $ht2 = 0, $4 = 0, $ht27 = 0, $5 = 0, $sub = 0, $ht1 = 0, $6 = 0, $ht110 = 0, $7 = 0, $sub11 = 0, $add = 0, $cmp = 0, $add13 = 0, $div = 0, $cmp14 = 0, $cmp17 = 0, $add22 = 0, $sub23 = 0, $8 = 0, $add26 = 0, $sub30 = 0, $9 = 0, $add33 = 0, $cmp35 = 0, $add40 = 0, $sub41 = 0, $10 = 0, $add44 = 0, $sub49 = 0, $11 = 0, $add52 = 0, $sub56 = 0, $add57 = 0, $sub58 = 0, $add59 = 0, $div60 = 0, $maxrank62 = 0, $12 = 0, $conv63 = 0, $r_048 = 0, $minrank66 = 0, $13 = 0, $conv6749 = 0, $cmp6850 = 0, $r_052 = 0, $y_051 = 0, $n = 0, $14 = 0, $cmp71 = 0, $conv74 = 0.0, $v = 0, $15 = 0, $16 = 0, $y78 = 0, $17 = 0.0, $add79 = 0.0, $add81 = 0, $r_0 = 0, $18 = 0, $conv67 = 0, $cmp68 = 0, $19 = 0, $add84 = 0, $20 = 0, $add87 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root1 = $g + 32 | 0;
+ $0 = HEAP32[$root1 >> 2] | 0;
+ $rank2 = $0 + 224 | 0;
+ $1 = HEAP32[$rank2 >> 2] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $conv = $2 << 16 >> 16;
+ $minrank = $g + 248 | 0;
+ $3 = HEAP16[$minrank >> 1] | 0;
+ $conv5 = $3 << 16 >> 16;
+ $ht2 = $1 + ($conv5 * 44 & -1) + 20 | 0;
+ $4 = HEAP32[$ht2 >> 2] | 0;
+ $ht27 = $g + 164 | 0;
+ $5 = HEAP32[$ht27 >> 2] | 0;
+ $sub = $4 - $5 | 0;
+ $ht1 = $1 + ($conv * 44 & -1) + 16 | 0;
+ $6 = HEAP32[$ht1 >> 2] | 0;
+ $ht110 = $g + 160 | 0;
+ $7 = HEAP32[$ht110 >> 2] | 0;
+ $sub11 = $6 - $7 | 0;
+ $add = $sub11 + $sub | 0;
+ $cmp = ($add | 0) < ($delta | 0);
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add13 = $delta + 1 | 0;
+ $div = ($add13 | 0) / 2 & -1;
+ $cmp14 = ($sub | 0) > ($sub11 | 0);
+ if ($cmp14) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $cmp17 = ($div | 0) > ($sub | 0);
+ if ($cmp17) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add22 = $div + $5 | 0;
+ HEAP32[$ht27 >> 2] = $add22;
+ $sub23 = $delta - $div | 0;
+ $8 = HEAP32[$ht110 >> 2] | 0;
+ $add26 = $sub23 + $8 | 0;
+ HEAP32[$ht110 >> 2] = $add26;
+ label = 15;
+ break;
+ case 6:
+ HEAP32[$ht27 >> 2] = $4;
+ $sub30 = $delta - $sub | 0;
+ $9 = HEAP32[$ht110 >> 2] | 0;
+ $add33 = $sub30 + $9 | 0;
+ HEAP32[$ht110 >> 2] = $add33;
+ label = 15;
+ break;
+ case 7:
+ $cmp35 = ($div | 0) > ($sub11 | 0);
+ if ($cmp35) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $add40 = $div + $7 | 0;
+ HEAP32[$ht110 >> 2] = $add40;
+ $sub41 = $delta - $div | 0;
+ $10 = HEAP32[$ht27 >> 2] | 0;
+ $add44 = $sub41 + $10 | 0;
+ HEAP32[$ht27 >> 2] = $add44;
+ label = 15;
+ break;
+ case 9:
+ HEAP32[$ht110 >> 2] = $6;
+ $sub49 = $delta - $sub11 | 0;
+ $11 = HEAP32[$ht27 >> 2] | 0;
+ $add52 = $sub49 + $11 | 0;
+ HEAP32[$ht27 >> 2] = $add52;
+ label = 15;
+ break;
+ case 10:
+ $sub56 = $conv - $conv5 | 0;
+ $add57 = $sub56 + 2 | 0;
+ $sub58 = $delta + 1 | 0;
+ $add59 = $sub58 + $sub56 | 0;
+ $div60 = ($add59 | 0) / ($add57 | 0) & -1;
+ $maxrank62 = $0 + 250 | 0;
+ $12 = HEAP16[$maxrank62 >> 1] | 0;
+ $conv63 = $12 << 16 >> 16;
+ $r_048 = $conv63 - 1 | 0;
+ $minrank66 = $0 + 248 | 0;
+ $13 = HEAP16[$minrank66 >> 1] | 0;
+ $conv6749 = $13 << 16 >> 16;
+ $cmp6850 = ($r_048 | 0) < ($conv6749 | 0);
+ if ($cmp6850) {
+ label = 14;
+ break;
+ } else {
+ $y_051 = $div60;
+ $r_052 = $r_048;
+ label = 11;
+ break;
+ }
+ case 11:
+ $n = $1 + ($r_052 * 44 & -1) | 0;
+ $14 = HEAP32[$n >> 2] | 0;
+ $cmp71 = ($14 | 0) > 0;
+ if ($cmp71) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $conv74 = +($y_051 | 0);
+ $v = $1 + ($r_052 * 44 & -1) + 4 | 0;
+ $15 = HEAP32[$v >> 2] | 0;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $y78 = $16 + 40 | 0;
+ $17 = +HEAPF64[$y78 >> 3];
+ $add79 = $conv74 + $17;
+ HEAPF64[$y78 >> 3] = $add79;
+ label = 13;
+ break;
+ case 13:
+ $add81 = $y_051 + $div60 | 0;
+ $r_0 = $r_052 - 1 | 0;
+ $18 = HEAP16[$minrank66 >> 1] | 0;
+ $conv67 = $18 << 16 >> 16;
+ $cmp68 = ($r_0 | 0) < ($conv67 | 0);
+ if ($cmp68) {
+ label = 14;
+ break;
+ } else {
+ $y_051 = $add81;
+ $r_052 = $r_0;
+ label = 11;
+ break;
+ }
+ case 14:
+ $19 = HEAP32[$ht27 >> 2] | 0;
+ $add84 = $19 + $div60 | 0;
+ HEAP32[$ht27 >> 2] = $add84;
+ $20 = HEAP32[$ht110 >> 2] | 0;
+ $add87 = $20 + $div60 | 0;
+ HEAP32[$ht110 >> 2] = $add87;
+ label = 15;
+ break;
+ case 15:
+ return;
+ }
+}
+function _adjustSimple($g, $delta) {
+ $g = $g | 0;
+ $delta = $delta | 0;
+ var $root1 = 0, $0 = 0, $rank2 = 0, $1 = 0, $maxrank = 0, $2 = 0, $conv = 0, $minrank = 0, $3 = 0, $conv5 = 0, $add = 0, $div = 0, $ht1 = 0, $4 = 0, $add7 = 0, $ht18 = 0, $5 = 0, $sub = 0, $cmp = 0, $cmp1042 = 0, $conv16 = 0.0, $r_043 = 0, $n = 0, $6 = 0, $cmp13 = 0, $v = 0, $7 = 0, $8 = 0, $y = 0, $9 = 0.0, $add20 = 0.0, $dec = 0, $cmp10 = 0, $ht2 = 0, $10 = 0, $sub22 = 0, $ht226 = 0, $11 = 0, $add23 = 0, $add24 = 0, $sub27 = 0, $ht229 = 0, $12 = 0, $sub30 = 0, $add31 = 0, $ht233 = 0, $13 = 0, $sub34 = 0, $deltop_0 = 0, $cmp36 = 0, $r_138 = 0, $minrank42 = 0, $14 = 0, $conv4339 = 0, $cmp4440 = 0, $conv52 = 0.0, $r_141 = 0, $n48 = 0, $15 = 0, $cmp49 = 0, $r_1 = 0, $16 = 0, $conv43 = 0, $cmp44 = 0, $v54 = 0, $17 = 0, $18 = 0, $y58 = 0, $19 = 0.0, $add59 = 0.0, $sub65 = 0, $ht267 = 0, $20 = 0, $add68 = 0, $21 = 0, $add71 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root1 = $g + 32 | 0;
+ $0 = HEAP32[$root1 >> 2] | 0;
+ $rank2 = $0 + 224 | 0;
+ $1 = HEAP32[$rank2 >> 2] | 0;
+ $maxrank = $g + 250 | 0;
+ $2 = HEAP16[$maxrank >> 1] | 0;
+ $conv = $2 << 16 >> 16;
+ $minrank = $g + 248 | 0;
+ $3 = HEAP16[$minrank >> 1] | 0;
+ $conv5 = $3 << 16 >> 16;
+ $add = $delta + 1 | 0;
+ $div = ($add | 0) / 2 & -1;
+ $ht1 = $g + 160 | 0;
+ $4 = HEAP32[$ht1 >> 2] | 0;
+ $add7 = $4 + $div | 0;
+ $ht18 = $1 + ($conv * 44 & -1) + 16 | 0;
+ $5 = HEAP32[$ht18 >> 2] | 0;
+ $sub = $add7 - $5 | 0;
+ $cmp = ($sub | 0) > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $cmp1042 = $2 << 16 >> 16 < $3 << 16 >> 16;
+ if ($cmp1042) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $conv16 = +($sub | 0);
+ $r_043 = $conv;
+ label = 5;
+ break;
+ case 5:
+ $n = $1 + ($r_043 * 44 & -1) | 0;
+ $6 = HEAP32[$n >> 2] | 0;
+ $cmp13 = ($6 | 0) > 0;
+ if ($cmp13) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $v = $1 + ($r_043 * 44 & -1) + 4 | 0;
+ $7 = HEAP32[$v >> 2] | 0;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $y = $8 + 40 | 0;
+ $9 = +HEAPF64[$y >> 3];
+ $add20 = $conv16 + $9;
+ HEAPF64[$y >> 3] = $add20;
+ label = 7;
+ break;
+ case 7:
+ $dec = $r_043 - 1 | 0;
+ $cmp10 = ($dec | 0) < ($conv5 | 0);
+ if ($cmp10) {
+ label = 8;
+ break;
+ } else {
+ $r_043 = $dec;
+ label = 5;
+ break;
+ }
+ case 8:
+ $ht2 = $g + 164 | 0;
+ $10 = HEAP32[$ht2 >> 2] | 0;
+ $sub22 = $delta - $div | 0;
+ $ht226 = $1 + ($conv5 * 44 & -1) + 20 | 0;
+ $11 = HEAP32[$ht226 >> 2] | 0;
+ $add23 = $sub22 + $sub | 0;
+ $add24 = $add23 + $10 | 0;
+ $sub27 = $add24 - $11 | 0;
+ $deltop_0 = $sub27;
+ label = 10;
+ break;
+ case 9:
+ $ht229 = $g + 164 | 0;
+ $12 = HEAP32[$ht229 >> 2] | 0;
+ $sub30 = $delta - $div | 0;
+ $add31 = $sub30 + $12 | 0;
+ $ht233 = $1 + ($conv5 * 44 & -1) + 20 | 0;
+ $13 = HEAP32[$ht233 >> 2] | 0;
+ $sub34 = $add31 - $13 | 0;
+ $deltop_0 = $sub34;
+ label = 10;
+ break;
+ case 10:
+ $cmp36 = ($deltop_0 | 0) > 0;
+ if ($cmp36) {
+ label = 11;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 11:
+ $r_138 = $conv5 - 1 | 0;
+ $minrank42 = $0 + 248 | 0;
+ $14 = HEAP16[$minrank42 >> 1] | 0;
+ $conv4339 = $14 << 16 >> 16;
+ $cmp4440 = ($r_138 | 0) < ($conv4339 | 0);
+ if ($cmp4440) {
+ label = 16;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $conv52 = +($deltop_0 | 0);
+ $r_141 = $r_138;
+ label = 13;
+ break;
+ case 13:
+ $n48 = $1 + ($r_141 * 44 & -1) | 0;
+ $15 = HEAP32[$n48 >> 2] | 0;
+ $cmp49 = ($15 | 0) > 0;
+ if ($cmp49) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $r_1 = $r_141 - 1 | 0;
+ $16 = HEAP16[$minrank42 >> 1] | 0;
+ $conv43 = $16 << 16 >> 16;
+ $cmp44 = ($r_1 | 0) < ($conv43 | 0);
+ if ($cmp44) {
+ label = 16;
+ break;
+ } else {
+ $r_141 = $r_1;
+ label = 13;
+ break;
+ }
+ case 15:
+ $v54 = $1 + ($r_141 * 44 & -1) + 4 | 0;
+ $17 = HEAP32[$v54 >> 2] | 0;
+ $18 = HEAP32[$17 >> 2] | 0;
+ $y58 = $18 + 40 | 0;
+ $19 = +HEAPF64[$y58 >> 3];
+ $add59 = $conv52 + $19;
+ HEAPF64[$y58 >> 3] = $add59;
+ label = 14;
+ break;
+ case 16:
+ $sub65 = $delta - $div | 0;
+ $ht267 = $g + 164 | 0;
+ $20 = HEAP32[$ht267 >> 2] | 0;
+ $add68 = $sub65 + $20 | 0;
+ HEAP32[$ht267 >> 2] = $add68;
+ $21 = HEAP32[$ht1 >> 2] | 0;
+ $add71 = $21 + $div | 0;
+ HEAP32[$ht1 >> 2] = $add71;
+ return;
+ }
+}
+function _scale_bb($g, $xf, $yf) {
+ $g = $g | 0;
+ $xf = +$xf;
+ $yf = +$yf;
+ var $n_cluster = 0, $0 = 0, $cmp1 = 0, $clust = 0, $c_02 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $inc = 0, $3 = 0, $cmp = 0, $x = 0, $4 = 0.0, $mul = 0.0, $y = 0, $5 = 0.0, $mul6 = 0.0, $x9 = 0, $6 = 0.0, $mul10 = 0.0, $y14 = 0, $7 = 0.0, $mul15 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp1 = ($0 | 0) < 1;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $c_02 = 1;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $1 + ($c_02 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _scale_bb($2, $xf, $yf);
+ $inc = $c_02 + 1 | 0;
+ $3 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($3 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $c_02 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ $x = $g + 56 | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $mul = $4 * $xf;
+ HEAPF64[$x >> 3] = $mul;
+ $y = $g + 64 | 0;
+ $5 = +HEAPF64[$y >> 3];
+ $mul6 = $5 * $yf;
+ HEAPF64[$y >> 3] = $mul6;
+ $x9 = $g + 72 | 0;
+ $6 = +HEAPF64[$x9 >> 3];
+ $mul10 = $6 * $xf;
+ HEAPF64[$x9 >> 3] = $mul10;
+ $y14 = $g + 80 | 0;
+ $7 = +HEAPF64[$y14 >> 3];
+ $mul15 = $7 * $yf;
+ HEAPF64[$y14 >> 3] = $mul15;
+ return;
+ }
+}
+function _adjustAspectRatio($g, $asp) {
+ $g = $g | 0;
+ $asp = $asp | 0;
+ var $x = 0, $0 = 0.0, $x3 = 0, $1 = 0.0, $sub = 0.0, $y = 0, $2 = 0.0, $y10 = 0, $3 = 0.0, $sub11 = 0.0, $div = 0.0, $4 = 0, $tobool = 0, $5 = 0, $mul = 0.0, $div30 = 0.0, $call = 0, $6 = 0, $call31 = 0, $call32 = 0, $targetAR = 0, $7 = 0.0, $mul33 = 0.0, $cmp = 0, $curIterations = 0, $8 = 0, $prevIterations = 0, $9 = 0, $sub36 = 0, $conv = 0.0, $mul37 = 0.0, $div38 = 0.0, $conv39 = 0, $nextIter = 0, $mul41 = 0.0, $cmp42 = 0, $nextIter45 = 0, $10 = 0, $tobool46 = 0, $11 = 0, $12 = 0, $_pr = 0, $tobool54 = 0, $13 = 0, $nextIter56 = 0, $14 = 0, $call57 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $x = $g + 72 | 0;
+ $0 = +HEAPF64[$x >> 3];
+ $x3 = $g + 56 | 0;
+ $1 = +HEAPF64[$x3 >> 3];
+ $sub = $0 - $1;
+ $y = $g + 80 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $y10 = $g + 64 | 0;
+ $3 = +HEAPF64[$y10 >> 3];
+ $sub11 = $2 - $3;
+ $div = $sub / $sub11;
+ $4 = HEAP8[164912] | 0;
+ $tobool = $4 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $5 = HEAP32[_stderr >> 2] | 0;
+ $mul = $sub * $sub11;
+ $div30 = $mul / 1.0e4;
+ $call = _fprintf($5 | 0, 130144, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $div, HEAPF64[tempInt + 8 >> 3] = $div30, tempInt) | 0) | 0;
+ $6 = HEAP32[_stderr >> 2] | 0;
+ $call31 = _countDummyNodes($g) | 0;
+ $call32 = _fprintf($6 | 0, 118264, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call31, tempInt) | 0) | 0;
+ label = 4;
+ break;
+ case 4:
+ $targetAR = $asp | 0;
+ $7 = +HEAPF64[$targetAR >> 3];
+ $mul33 = $7 * 1.1;
+ $cmp = $div > $mul33;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $curIterations = $asp + 20 | 0;
+ $8 = HEAP32[$curIterations >> 2] | 0;
+ $prevIterations = $asp + 16 | 0;
+ $9 = HEAP32[$prevIterations >> 2] | 0;
+ $sub36 = $8 - $9 | 0;
+ $conv = +($sub36 | 0);
+ $mul37 = $7 * $conv;
+ $div38 = $mul37 / $div;
+ $conv39 = ~~$div38;
+ $nextIter = $asp + 24 | 0;
+ HEAP32[$nextIter >> 2] = $conv39;
+ label = 10;
+ break;
+ case 6:
+ $mul41 = $7 * .8;
+ $cmp42 = $div > $mul41;
+ $nextIter45 = $asp + 24 | 0;
+ if ($cmp42) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ HEAP32[$nextIter45 >> 2] = -1;
+ $10 = HEAP8[164912] | 0;
+ $tobool46 = $10 << 24 >> 24 == 0;
+ if ($tobool46) {
+ label = 12;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $11 = HEAP32[_stderr >> 2] | 0;
+ $12 = _fwrite(112984, 34, 1, $11 | 0) | 0;
+ label = 10;
+ break;
+ case 9:
+ HEAP32[$nextIter45 >> 2] = 0;
+ label = 10;
+ break;
+ case 10:
+ $_pr = HEAP8[164912] | 0;
+ $tobool54 = $_pr << 24 >> 24 == 0;
+ if ($tobool54) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $13 = HEAP32[_stderr >> 2] | 0;
+ $nextIter56 = $asp + 24 | 0;
+ $14 = HEAP32[$nextIter56 >> 2] | 0;
+ $call57 = _fprintf($13 | 0, 108456, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $14, tempInt) | 0) | 0;
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _clust_ht($g) {
+ $g = $g | 0;
+ var $root = 0, $0 = 0, $rank1 = 0, $1 = 0, $ht13 = 0, $2 = 0, $ht25 = 0, $3 = 0, $n_cluster = 0, $4 = 0, $cmp47 = 0, $clust = 0, $maxrank10 = 0, $minrank24 = 0, $haveClustLabel_051 = 0, $c_050 = 0, $ht1_049 = 0, $ht2_048 = 0, $5 = 0, $arrayidx = 0, $6 = 0, $call = 0, $or = 0, $maxrank = 0, $7 = 0, $8 = 0, $cmp12 = 0, $ht115 = 0, $9 = 0, $add = 0, $cmp16 = 0, $ht1_0_add = 0, $ht1_1 = 0, $minrank = 0, $10 = 0, $11 = 0, $cmp26 = 0, $ht230 = 0, $12 = 0, $add31 = 0, $cmp32 = 0, $ht2_0_add31 = 0, $ht2_1 = 0, $inc = 0, $13 = 0, $cmp = 0, $haveClustLabel_0_lcssa = 0, $ht1_0_lcssa = 0, $ht2_0_lcssa = 0, $14 = 0, $cmp43 = 0, $label = 0, $15 = 0, $tobool = 0, $rankdir = 0, $16 = 0, $and49 = 0, $tobool50 = 0, $y = 0, $17 = 0.0, $conv54 = 0.0, $add55 = 0.0, $conv56 = 0, $y60 = 0, $18 = 0.0, $conv61 = 0.0, $add62 = 0.0, $conv63 = 0, $ht2_2 = 0, $ht1_2 = 0, $haveClustLabel_1 = 0, $19 = 0, $cmp71 = 0, $minrank75 = 0, $20 = 0, $idxprom = 0, $ht277 = 0, $21 = 0, $cmp78 = 0, $_ht2_2 = 0, $maxrank95 = 0, $22 = 0, $idxprom96 = 0, $ht198 = 0, $23 = 0, $cmp99 = 0, $cond109 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $rank1 = $0 + 224 | 0;
+ $1 = HEAP32[$rank1 >> 2] | 0;
+ $ht13 = $g + 160 | 0;
+ $2 = HEAP32[$ht13 >> 2] | 0;
+ $ht25 = $g + 164 | 0;
+ $3 = HEAP32[$ht25 >> 2] | 0;
+ $n_cluster = $g + 212 | 0;
+ $4 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp47 = ($4 | 0) < 1;
+ if ($cmp47) {
+ $ht2_0_lcssa = $3;
+ $ht1_0_lcssa = $2;
+ $haveClustLabel_0_lcssa = 0;
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $maxrank10 = $g + 250 | 0;
+ $minrank24 = $g + 248 | 0;
+ $ht2_048 = $3;
+ $ht1_049 = $2;
+ $c_050 = 1;
+ $haveClustLabel_051 = 0;
+ label = 4;
+ break;
+ case 4:
+ $5 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $5 + ($c_050 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ $call = _clust_ht($6) | 0;
+ $or = $call | $haveClustLabel_051;
+ $maxrank = $6 + 250 | 0;
+ $7 = HEAP16[$maxrank >> 1] | 0;
+ $8 = HEAP16[$maxrank10 >> 1] | 0;
+ $cmp12 = $7 << 16 >> 16 == $8 << 16 >> 16;
+ if ($cmp12) {
+ label = 5;
+ break;
+ } else {
+ $ht1_1 = $ht1_049;
+ label = 6;
+ break;
+ }
+ case 5:
+ $ht115 = $6 + 160 | 0;
+ $9 = HEAP32[$ht115 >> 2] | 0;
+ $add = $9 + 8 | 0;
+ $cmp16 = ($ht1_049 | 0) > ($add | 0);
+ $ht1_0_add = $cmp16 ? $ht1_049 : $add;
+ $ht1_1 = $ht1_0_add;
+ label = 6;
+ break;
+ case 6:
+ $minrank = $6 + 248 | 0;
+ $10 = HEAP16[$minrank >> 1] | 0;
+ $11 = HEAP16[$minrank24 >> 1] | 0;
+ $cmp26 = $10 << 16 >> 16 == $11 << 16 >> 16;
+ if ($cmp26) {
+ label = 7;
+ break;
+ } else {
+ $ht2_1 = $ht2_048;
+ label = 8;
+ break;
+ }
+ case 7:
+ $ht230 = $6 + 164 | 0;
+ $12 = HEAP32[$ht230 >> 2] | 0;
+ $add31 = $12 + 8 | 0;
+ $cmp32 = ($ht2_048 | 0) > ($add31 | 0);
+ $ht2_0_add31 = $cmp32 ? $ht2_048 : $add31;
+ $ht2_1 = $ht2_0_add31;
+ label = 8;
+ break;
+ case 8:
+ $inc = $c_050 + 1 | 0;
+ $13 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($13 | 0);
+ if ($cmp) {
+ $ht2_0_lcssa = $ht2_1;
+ $ht1_0_lcssa = $ht1_1;
+ $haveClustLabel_0_lcssa = $or;
+ label = 9;
+ break;
+ } else {
+ $ht2_048 = $ht2_1;
+ $ht1_049 = $ht1_1;
+ $c_050 = $inc;
+ $haveClustLabel_051 = $or;
+ label = 4;
+ break;
+ }
+ case 9:
+ $14 = HEAP32[$root >> 2] | 0;
+ $cmp43 = ($14 | 0) == ($g | 0);
+ if ($cmp43) {
+ $haveClustLabel_1 = $haveClustLabel_0_lcssa;
+ $ht1_2 = $ht1_0_lcssa;
+ $ht2_2 = $ht2_0_lcssa;
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $label = $g + 52 | 0;
+ $15 = HEAP32[$label >> 2] | 0;
+ $tobool = ($15 | 0) == 0;
+ if ($tobool) {
+ $haveClustLabel_1 = $haveClustLabel_0_lcssa;
+ $ht1_2 = $ht1_0_lcssa;
+ $ht2_2 = $ht2_0_lcssa;
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $rankdir = $14 + 156 | 0;
+ $16 = HEAP32[$rankdir >> 2] | 0;
+ $and49 = $16 & 1;
+ $tobool50 = ($and49 | 0) == 0;
+ if ($tobool50) {
+ label = 12;
+ break;
+ } else {
+ $haveClustLabel_1 = 1;
+ $ht1_2 = $ht1_0_lcssa;
+ $ht2_2 = $ht2_0_lcssa;
+ label = 13;
+ break;
+ }
+ case 12:
+ $y = $g + 96 | 0;
+ $17 = +HEAPF64[$y >> 3];
+ $conv54 = +($ht1_0_lcssa | 0);
+ $add55 = $conv54 + $17;
+ $conv56 = ~~$add55;
+ $y60 = $g + 128 | 0;
+ $18 = +HEAPF64[$y60 >> 3];
+ $conv61 = +($ht2_0_lcssa | 0);
+ $add62 = $conv61 + $18;
+ $conv63 = ~~$add62;
+ $haveClustLabel_1 = 1;
+ $ht1_2 = $conv56;
+ $ht2_2 = $conv63;
+ label = 13;
+ break;
+ case 13:
+ HEAP32[$ht13 >> 2] = $ht1_2;
+ HEAP32[$ht25 >> 2] = $ht2_2;
+ $19 = HEAP32[$root >> 2] | 0;
+ $cmp71 = ($19 | 0) == ($g | 0);
+ if ($cmp71) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $minrank75 = $g + 248 | 0;
+ $20 = HEAP16[$minrank75 >> 1] | 0;
+ $idxprom = $20 << 16 >> 16;
+ $ht277 = $1 + ($idxprom * 44 & -1) + 20 | 0;
+ $21 = HEAP32[$ht277 >> 2] | 0;
+ $cmp78 = ($21 | 0) > ($ht2_2 | 0);
+ $_ht2_2 = $cmp78 ? $21 : $ht2_2;
+ HEAP32[$ht277 >> 2] = $_ht2_2;
+ $maxrank95 = $g + 250 | 0;
+ $22 = HEAP16[$maxrank95 >> 1] | 0;
+ $idxprom96 = $22 << 16 >> 16;
+ $ht198 = $1 + ($idxprom96 * 44 & -1) + 16 | 0;
+ $23 = HEAP32[$ht198 >> 2] | 0;
+ $cmp99 = ($23 | 0) > ($ht1_2 | 0);
+ $cond109 = $cmp99 ? $23 : $ht1_2;
+ HEAP32[$ht198 >> 2] = $cond109;
+ label = 15;
+ break;
+ case 15:
+ return $haveClustLabel_1 | 0;
+ }
+ return 0;
+}
+function _adjustRanks($g, $equal) {
+ $g = $g | 0;
+ $equal = $equal | 0;
+ var $root = 0, $0 = 0, $rank1 = 0, $1 = 0, $ht13 = 0, $2 = 0, $ht25 = 0, $3 = 0, $n_cluster = 0, $4 = 0, $cmp52 = 0, $clust = 0, $maxrank10 = 0, $minrank24 = 0, $c_055 = 0, $ht1_054 = 0, $ht2_053 = 0, $5 = 0, $arrayidx = 0, $6 = 0, $maxrank = 0, $7 = 0, $8 = 0, $cmp12 = 0, $ht115 = 0, $9 = 0, $add = 0, $cmp16 = 0, $ht1_0_add = 0, $ht1_1 = 0, $minrank = 0, $10 = 0, $11 = 0, $cmp26 = 0, $ht230 = 0, $12 = 0, $add31 = 0, $cmp32 = 0, $ht2_0_add31 = 0, $ht2_1 = 0, $inc = 0, $13 = 0, $cmp = 0, $ht1_0_lcssa = 0, $ht2_0_lcssa = 0, $14 = 0, $cmp47 = 0, $label = 0, $15 = 0, $tobool = 0, $y = 0, $16 = 0.0, $y56 = 0, $17 = 0.0, $cmp57 = 0, $_ = 0.0, $conv71 = 0, $maxrank73 = 0, $18 = 0, $conv74 = 0, $minrank76 = 0, $19 = 0, $conv77 = 0, $v = 0, $20 = 0, $21 = 0, $y81 = 0, $22 = 0.0, $v83 = 0, $23 = 0, $24 = 0, $y87 = 0, $25 = 0.0, $sub = 0.0, $conv88 = 0, $sum = 0, $add90_neg = 0, $sub91 = 0, $cmp92 = 0, $tobool95 = 0, $26 = 0, $cmp101 = 0, $minrank105 = 0, $27 = 0, $idxprom = 0, $ht2107 = 0, $28 = 0, $29 = 0, $cmp110 = 0, $_51 = 0, $maxrank129 = 0, $30 = 0, $idxprom130 = 0, $ht1132 = 0, $31 = 0, $32 = 0, $cmp135 = 0, $cond147 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $rank1 = $0 + 224 | 0;
+ $1 = HEAP32[$rank1 >> 2] | 0;
+ $ht13 = $g + 160 | 0;
+ $2 = HEAP32[$ht13 >> 2] | 0;
+ $ht25 = $g + 164 | 0;
+ $3 = HEAP32[$ht25 >> 2] | 0;
+ $n_cluster = $g + 212 | 0;
+ $4 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp52 = ($4 | 0) < 1;
+ if ($cmp52) {
+ $ht2_0_lcssa = $3;
+ $ht1_0_lcssa = $2;
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $maxrank10 = $g + 250 | 0;
+ $minrank24 = $g + 248 | 0;
+ $ht2_053 = $3;
+ $ht1_054 = $2;
+ $c_055 = 1;
+ label = 4;
+ break;
+ case 4:
+ $5 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $5 + ($c_055 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ _adjustRanks($6, $equal);
+ $maxrank = $6 + 250 | 0;
+ $7 = HEAP16[$maxrank >> 1] | 0;
+ $8 = HEAP16[$maxrank10 >> 1] | 0;
+ $cmp12 = $7 << 16 >> 16 == $8 << 16 >> 16;
+ if ($cmp12) {
+ label = 5;
+ break;
+ } else {
+ $ht1_1 = $ht1_054;
+ label = 6;
+ break;
+ }
+ case 5:
+ $ht115 = $6 + 160 | 0;
+ $9 = HEAP32[$ht115 >> 2] | 0;
+ $add = $9 + 8 | 0;
+ $cmp16 = ($ht1_054 | 0) > ($add | 0);
+ $ht1_0_add = $cmp16 ? $ht1_054 : $add;
+ $ht1_1 = $ht1_0_add;
+ label = 6;
+ break;
+ case 6:
+ $minrank = $6 + 248 | 0;
+ $10 = HEAP16[$minrank >> 1] | 0;
+ $11 = HEAP16[$minrank24 >> 1] | 0;
+ $cmp26 = $10 << 16 >> 16 == $11 << 16 >> 16;
+ if ($cmp26) {
+ label = 7;
+ break;
+ } else {
+ $ht2_1 = $ht2_053;
+ label = 8;
+ break;
+ }
+ case 7:
+ $ht230 = $6 + 164 | 0;
+ $12 = HEAP32[$ht230 >> 2] | 0;
+ $add31 = $12 + 8 | 0;
+ $cmp32 = ($ht2_053 | 0) > ($add31 | 0);
+ $ht2_0_add31 = $cmp32 ? $ht2_053 : $add31;
+ $ht2_1 = $ht2_0_add31;
+ label = 8;
+ break;
+ case 8:
+ $inc = $c_055 + 1 | 0;
+ $13 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($13 | 0);
+ if ($cmp) {
+ $ht2_0_lcssa = $ht2_1;
+ $ht1_0_lcssa = $ht1_1;
+ label = 9;
+ break;
+ } else {
+ $ht2_053 = $ht2_1;
+ $ht1_054 = $ht1_1;
+ $c_055 = $inc;
+ label = 4;
+ break;
+ }
+ case 9:
+ HEAP32[$ht13 >> 2] = $ht1_0_lcssa;
+ HEAP32[$ht25 >> 2] = $ht2_0_lcssa;
+ $14 = HEAP32[$root >> 2] | 0;
+ $cmp47 = ($14 | 0) == ($g | 0);
+ if ($cmp47) {
+ label = 15;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $label = $g + 52 | 0;
+ $15 = HEAP32[$label >> 2] | 0;
+ $tobool = ($15 | 0) == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $y = $g + 144 | 0;
+ $16 = +HEAPF64[$y >> 3];
+ $y56 = $g + 112 | 0;
+ $17 = +HEAPF64[$y56 >> 3];
+ $cmp57 = $16 > $17;
+ $_ = $cmp57 ? $16 : $17;
+ $conv71 = ~~$_;
+ $maxrank73 = $g + 250 | 0;
+ $18 = HEAP16[$maxrank73 >> 1] | 0;
+ $conv74 = $18 << 16 >> 16;
+ $minrank76 = $g + 248 | 0;
+ $19 = HEAP16[$minrank76 >> 1] | 0;
+ $conv77 = $19 << 16 >> 16;
+ $v = $1 + ($conv77 * 44 & -1) + 4 | 0;
+ $20 = HEAP32[$v >> 2] | 0;
+ $21 = HEAP32[$20 >> 2] | 0;
+ $y81 = $21 + 40 | 0;
+ $22 = +HEAPF64[$y81 >> 3];
+ $v83 = $1 + ($conv74 * 44 & -1) + 4 | 0;
+ $23 = HEAP32[$v83 >> 2] | 0;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $y87 = $24 + 40 | 0;
+ $25 = +HEAPF64[$y87 >> 3];
+ $sub = $22 - $25;
+ $conv88 = ~~$sub;
+ $sum = $ht1_0_lcssa + $ht2_0_lcssa | 0;
+ $add90_neg = $conv71 - $sum | 0;
+ $sub91 = $add90_neg - $conv88 | 0;
+ $cmp92 = ($sub91 | 0) > 0;
+ if ($cmp92) {
+ label = 12;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 12:
+ $tobool95 = ($equal | 0) == 0;
+ if ($tobool95) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _adjustEqual($g, $sub91);
+ label = 15;
+ break;
+ case 14:
+ _adjustSimple($g, $sub91);
+ label = 15;
+ break;
+ case 15:
+ $26 = HEAP32[$root >> 2] | 0;
+ $cmp101 = ($26 | 0) == ($g | 0);
+ if ($cmp101) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $minrank105 = $g + 248 | 0;
+ $27 = HEAP16[$minrank105 >> 1] | 0;
+ $idxprom = $27 << 16 >> 16;
+ $ht2107 = $1 + ($idxprom * 44 & -1) + 20 | 0;
+ $28 = HEAP32[$ht2107 >> 2] | 0;
+ $29 = HEAP32[$ht25 >> 2] | 0;
+ $cmp110 = ($28 | 0) > ($29 | 0);
+ $_51 = $cmp110 ? $28 : $29;
+ HEAP32[$ht2107 >> 2] = $_51;
+ $maxrank129 = $g + 250 | 0;
+ $30 = HEAP16[$maxrank129 >> 1] | 0;
+ $idxprom130 = $30 << 16 >> 16;
+ $ht1132 = $1 + ($idxprom130 * 44 & -1) + 16 | 0;
+ $31 = HEAP32[$ht1132 >> 2] | 0;
+ $32 = HEAP32[$ht13 >> 2] | 0;
+ $cmp135 = ($31 | 0) > ($32 | 0);
+ $cond147 = $cmp135 ? $31 : $32;
+ HEAP32[$ht1132 >> 2] = $cond147;
+ label = 17;
+ break;
+ case 17:
+ return;
+ }
+}
+function _allocate_aux_edges($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_016 = 0, $tobool17 = 0, $n_018 = 0, $save_in = 0, $in = 0, $0 = 0, $1 = 0, $ld$0$0 = 0, $2$0 = 0, $ld$1$1 = 0, $2$1 = 0, $st$2$0 = 0, $st$3$1 = 0, $save_out = 0, $out = 0, $3 = 0, $4 = 0, $ld$4$0 = 0, $5$0 = 0, $ld$5$1 = 0, $5$1 = 0, $st$6$0 = 0, $st$7$1 = 0, $list = 0, $6 = 0, $i_0 = 0, $arrayidx = 0, $7 = 0, $tobool8 = 0, $inc = 0, $list13 = 0, $8 = 0, $j_0 = 0, $arrayidx14 = 0, $9 = 0, $tobool15 = 0, $inc18 = 0, $add = 0, $size = 0, $add23 = 0, $mul = 0, $call = 0, $10 = 0, $size30 = 0, $call31 = 0, $11 = 0, $next = 0, $n_0 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $n_016 = HEAP32[$nlist >> 2] | 0;
+ $tobool17 = ($n_016 | 0) == 0;
+ if ($tobool17) {
+ label = 8;
+ break;
+ } else {
+ $n_018 = $n_016;
+ label = 3;
+ break;
+ }
+ case 3:
+ $save_in = $n_018 + 248 | 0;
+ $in = $n_018 + 176 | 0;
+ $0 = $in;
+ $1 = $save_in;
+ $ld$0$0 = $0 | 0;
+ $2$0 = HEAP32[$ld$0$0 >> 2] | 0;
+ $ld$1$1 = $0 + 4 | 0;
+ $2$1 = HEAP32[$ld$1$1 >> 2] | 0;
+ $st$2$0 = $1 | 0;
+ HEAP32[$st$2$0 >> 2] = $2$0;
+ $st$3$1 = $1 + 4 | 0;
+ HEAP32[$st$3$1 >> 2] = $2$1;
+ $save_out = $n_018 + 256 | 0;
+ $out = $n_018 + 184 | 0;
+ $3 = $out;
+ $4 = $save_out;
+ $ld$4$0 = $3 | 0;
+ $5$0 = HEAP32[$ld$4$0 >> 2] | 0;
+ $ld$5$1 = $3 + 4 | 0;
+ $5$1 = HEAP32[$ld$5$1 >> 2] | 0;
+ $st$6$0 = $4 | 0;
+ HEAP32[$st$6$0 >> 2] = $5$0;
+ $st$7$1 = $4 + 4 | 0;
+ HEAP32[$st$7$1 >> 2] = $5$1;
+ $list = $out | 0;
+ $6 = HEAP32[$list >> 2] | 0;
+ $i_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $6 + ($i_0 << 2) | 0;
+ $7 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool8 = ($7 | 0) == 0;
+ $inc = $i_0 + 1 | 0;
+ if ($tobool8) {
+ label = 5;
+ break;
+ } else {
+ $i_0 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ $list13 = $in | 0;
+ $8 = HEAP32[$list13 >> 2] | 0;
+ $j_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx14 = $8 + ($j_0 << 2) | 0;
+ $9 = HEAP32[$arrayidx14 >> 2] | 0;
+ $tobool15 = ($9 | 0) == 0;
+ $inc18 = $j_0 + 1 | 0;
+ if ($tobool15) {
+ label = 7;
+ break;
+ } else {
+ $j_0 = $inc18;
+ label = 6;
+ break;
+ }
+ case 7:
+ $add = $j_0 + $i_0 | 0;
+ $size = $n_018 + 180 | 0;
+ HEAP32[$size >> 2] = 0;
+ $add23 = $add << 2;
+ $mul = $add23 + 16 | 0;
+ $call = _zmalloc($mul) | 0;
+ $10 = $call;
+ HEAP32[$list13 >> 2] = $10;
+ $size30 = $n_018 + 188 | 0;
+ HEAP32[$size30 >> 2] = 0;
+ $call31 = _zmalloc(16) | 0;
+ $11 = $call31;
+ HEAP32[$list >> 2] = $11;
+ $next = $n_018 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ $n_018 = $n_0;
+ label = 3;
+ break;
+ }
+ case 8:
+ return;
+ }
+}
+function _make_edge_pairs($g) {
+ $g = $g | 0;
+ var $nlist = 0, $n_026 = 0, $tobool27 = 0, $n_028 = 0, $list = 0, $0 = 0, $tobool2 = 0, $1 = 0, $2 = 0, $tobool724 = 0, $3 = 0, $i_025 = 0, $call = 0, $node_type = 0, $x = 0, $4 = 0.0, $x13 = 0, $5 = 0.0, $sub = 0.0, $conv = 0, $cmp = 0, $sub16 = 0, $m1_0 = 0, $m0_0 = 0, $tail = 0, $6 = 0, $add = 0, $conv17 = 0.0, $weight = 0, $7 = 0.0, $conv19 = 0, $call20 = 0, $head = 0, $8 = 0, $add21 = 0, $conv22 = 0.0, $9 = 0.0, $conv25 = 0, $call26 = 0, $10 = 0, $rank = 0, $11 = 0, $sub29 = 0, $12 = 0, $rank33 = 0, $13 = 0, $sub34 = 0, $cmp36 = 0, $sub29_sub34 = 0, $sub42 = 0, $rank49 = 0, $inc = 0, $14 = 0, $arrayidx = 0, $15 = 0, $tobool7 = 0, $next = 0, $n_0 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $g + 220 | 0;
+ $n_026 = HEAP32[$nlist >> 2] | 0;
+ $tobool27 = ($n_026 | 0) == 0;
+ if ($tobool27) {
+ label = 7;
+ break;
+ } else {
+ $n_028 = $n_026;
+ label = 3;
+ break;
+ }
+ case 3:
+ $list = $n_028 + 256 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $tobool2 = ($0 | 0) == 0;
+ if ($tobool2) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $tobool724 = ($2 | 0) == 0;
+ if ($tobool724) {
+ label = 6;
+ break;
+ } else {
+ $i_025 = 0;
+ $3 = $2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $call = _virtual_node($g) | 0;
+ $node_type = $call + 162 | 0;
+ HEAP8[$node_type] = 2;
+ $x = $3 + 72 | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $x13 = $3 + 32 | 0;
+ $5 = +HEAPF64[$x13 >> 3];
+ $sub = $4 - $5;
+ $conv = ~~$sub;
+ $cmp = ($conv | 0) > 0;
+ $sub16 = -$conv | 0;
+ $m1_0 = $cmp ? 0 : $sub16;
+ $m0_0 = $cmp ? $conv : 0;
+ $tail = $3 + 16 | 0;
+ $6 = HEAP32[$tail >> 2] | 0;
+ $add = $m0_0 + 1 | 0;
+ $conv17 = +($add | 0);
+ $weight = $3 + 172 | 0;
+ $7 = +HEAPF32[$weight >> 2];
+ $conv19 = ~~$7;
+ $call20 = _make_aux_edge($call, $6, $conv17, $conv19) | 0;
+ $head = $3 + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $add21 = $m1_0 + 1 | 0;
+ $conv22 = +($add21 | 0);
+ $9 = +HEAPF32[$weight >> 2];
+ $conv25 = ~~$9;
+ $call26 = _make_aux_edge($call, $8, $conv22, $conv25) | 0;
+ $10 = HEAP32[$tail >> 2] | 0;
+ $rank = $10 + 236 | 0;
+ $11 = HEAP32[$rank >> 2] | 0;
+ $sub29 = $11 - $m0_0 | 0;
+ $12 = HEAP32[$head >> 2] | 0;
+ $rank33 = $12 + 236 | 0;
+ $13 = HEAP32[$rank33 >> 2] | 0;
+ $sub34 = $13 - $m1_0 | 0;
+ $cmp36 = ($sub29 | 0) < ($sub34 | 0);
+ $sub29_sub34 = $cmp36 ? $sub29 : $sub34;
+ $sub42 = $sub29_sub34 - 1 | 0;
+ $rank49 = $call + 236 | 0;
+ HEAP32[$rank49 >> 2] = $sub42;
+ $inc = $i_025 + 1 | 0;
+ $14 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $14 + ($inc << 2) | 0;
+ $15 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool7 = ($15 | 0) == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ $i_025 = $inc;
+ $3 = $15;
+ label = 5;
+ break;
+ }
+ case 6:
+ $next = $n_028 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $n_028 = $n_0;
+ label = 3;
+ break;
+ }
+ case 7:
+ return;
+ }
+}
+function _pos_clusters($g) {
+ $g = $g | 0;
+ var $n_cluster = 0, $0 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($0 | 0) > 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _contain_clustnodes($g);
+ _keepout_othernodes($g);
+ _contain_subclust($g);
+ _separate_subclust($g);
+ label = 4;
+ break;
+ case 4:
+ return;
+ }
+}
+function _compress_graph($g) {
+ $g = $g | 0;
+ var $drawing = 0, $0 = 0, $ratio_kind = 0, $1 = 0, $cmp = 0, $p_sroa_0_0__idx = 0, $p_sroa_0_0_copyload = 0.0, $p_sroa_1_8__idx3 = 0, $p_sroa_1_8_copyload = 0.0, $mul = 0.0, $cmp4 = 0, $rankdir = 0, $2 = 0, $and8 = 0, $cmp9 = 0, $p_sroa_0_0_copyload_p_sroa_1_8_copyload = 0.0, $cmp14 = 0, $cond = 0.0, $ln = 0, $3 = 0, $rn = 0, $4 = 0, $call = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $drawing = $g + 48 | 0;
+ $0 = HEAP32[$drawing >> 2] | 0;
+ $ratio_kind = $0 + 84 | 0;
+ $1 = HEAP32[$ratio_kind >> 2] | 0;
+ $cmp = ($1 | 0) == 3;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $p_sroa_0_0__idx = $0 + 64 | 0;
+ $p_sroa_0_0_copyload = +HEAPF64[$p_sroa_0_0__idx >> 3];
+ $p_sroa_1_8__idx3 = $0 + 72 | 0;
+ $p_sroa_1_8_copyload = +HEAPF64[$p_sroa_1_8__idx3 >> 3];
+ $mul = $p_sroa_0_0_copyload * $p_sroa_1_8_copyload;
+ $cmp4 = $mul > 1.0;
+ if ($cmp4) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ _contain_nodes($g);
+ $rankdir = $g + 156 | 0;
+ $2 = HEAP32[$rankdir >> 2] | 0;
+ $and8 = $2 & 1;
+ $cmp9 = ($and8 | 0) == 0;
+ $p_sroa_0_0_copyload_p_sroa_1_8_copyload = $cmp9 ? $p_sroa_0_0_copyload : $p_sroa_1_8_copyload;
+ $cmp14 = $p_sroa_0_0_copyload_p_sroa_1_8_copyload < 65535.0;
+ $cond = $cmp14 ? $p_sroa_0_0_copyload_p_sroa_1_8_copyload : 65535.0;
+ $ln = $g + 268 | 0;
+ $3 = HEAP32[$ln >> 2] | 0;
+ $rn = $g + 272 | 0;
+ $4 = HEAP32[$rn >> 2] | 0;
+ $call = _make_aux_edge($3, $4, $cond, 1e3) | 0;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _contain_nodes($g) {
+ $g = $g | 0;
+ var $ln1 = 0, $0 = 0, $rn3 = 0, $1 = 0, $minrank = 0, $2 = 0, $maxrank = 0, $3 = 0, $cmp23 = 0, $conv = 0, $rank = 0, $name = 0, $x = 0, $x39 = 0, $r_024 = 0, $4 = 0, $n = 0, $5 = 0, $cmp9 = 0, $v14 = 0, $6 = 0, $7 = 0, $cmp16 = 0, $8 = 0, $call = 0, $lw = 0, $9 = 0.0, $add = 0.0, $10 = 0.0, $add23 = 0.0, $call24 = 0, $11 = 0, $n28 = 0, $12 = 0, $sub = 0, $v32 = 0, $13 = 0, $arrayidx33 = 0, $14 = 0, $rw = 0, $15 = 0.0, $add35 = 0.0, $16 = 0.0, $add40 = 0.0, $call41 = 0, $inc = 0, $17 = 0, $conv6 = 0, $cmp = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _make_lrvn($g);
+ $ln1 = $g + 268 | 0;
+ $0 = HEAP32[$ln1 >> 2] | 0;
+ $rn3 = $g + 272 | 0;
+ $1 = HEAP32[$rn3 >> 2] | 0;
+ $minrank = $g + 248 | 0;
+ $2 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $3 = HEAP16[$maxrank >> 1] | 0;
+ $cmp23 = $2 << 16 >> 16 > $3 << 16 >> 16;
+ if ($cmp23) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $2 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $name = $g + 12 | 0;
+ $x = $g + 136 | 0;
+ $x39 = $g + 104 | 0;
+ $r_024 = $conv;
+ label = 4;
+ break;
+ case 4:
+ $4 = HEAP32[$rank >> 2] | 0;
+ $n = $4 + ($r_024 * 44 & -1) | 0;
+ $5 = HEAP32[$n >> 2] | 0;
+ $cmp9 = ($5 | 0) == 0;
+ if ($cmp9) {
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $v14 = $4 + ($r_024 * 44 & -1) + 4 | 0;
+ $6 = HEAP32[$v14 >> 2] | 0;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $cmp16 = ($7 | 0) == 0;
+ if ($cmp16) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $8 = HEAP32[$name >> 2] | 0;
+ $call = _agerr(1, 104488, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $8, HEAP32[tempInt + 8 >> 2] = $r_024, tempInt) | 0) | 0;
+ label = 8;
+ break;
+ case 7:
+ $lw = $7 + 104 | 0;
+ $9 = +HEAPF64[$lw >> 3];
+ $add = $9 + 8.0;
+ $10 = +HEAPF64[$x >> 3];
+ $add23 = $add + $10;
+ $call24 = _make_aux_edge($0, $7, $add23, 0) | 0;
+ $11 = HEAP32[$rank >> 2] | 0;
+ $n28 = $11 + ($r_024 * 44 & -1) | 0;
+ $12 = HEAP32[$n28 >> 2] | 0;
+ $sub = $12 - 1 | 0;
+ $v32 = $11 + ($r_024 * 44 & -1) + 4 | 0;
+ $13 = HEAP32[$v32 >> 2] | 0;
+ $arrayidx33 = $13 + ($sub << 2) | 0;
+ $14 = HEAP32[$arrayidx33 >> 2] | 0;
+ $rw = $14 + 112 | 0;
+ $15 = +HEAPF64[$rw >> 3];
+ $add35 = $15 + 8.0;
+ $16 = +HEAPF64[$x39 >> 3];
+ $add40 = $add35 + $16;
+ $call41 = _make_aux_edge($14, $1, $add40, 0) | 0;
+ label = 8;
+ break;
+ case 8:
+ $inc = $r_024 + 1 | 0;
+ $17 = HEAP16[$maxrank >> 1] | 0;
+ $conv6 = $17 << 16 >> 16;
+ $cmp = ($inc | 0) > ($conv6 | 0);
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ $r_024 = $inc;
+ label = 4;
+ break;
+ }
+ case 9:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _make_lrvn($g) {
+ $g = $g | 0;
+ var $ln1 = 0, $0 = 0, $tobool = 0, $root = 0, $1 = 0, $call = 0, $node_type = 0, $2 = 0, $call4 = 0, $node_type6 = 0, $label = 0, $3 = 0, $tobool8 = 0, $4 = 0, $cmp = 0, $rankdir = 0, $5 = 0, $and13 = 0, $tobool14 = 0, $x = 0, $6 = 0.0, $x20 = 0, $7 = 0.0, $cmp21 = 0, $_ = 0.0, $conv = 0, $conv30 = 0.0, $call31 = 0, $rn36 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ln1 = $g + 268 | 0;
+ $0 = HEAP32[$ln1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $root = $g + 32 | 0;
+ $1 = HEAP32[$root >> 2] | 0;
+ $call = _virtual_node($1) | 0;
+ $node_type = $call + 162 | 0;
+ HEAP8[$node_type] = 2;
+ $2 = HEAP32[$root >> 2] | 0;
+ $call4 = _virtual_node($2) | 0;
+ $node_type6 = $call4 + 162 | 0;
+ HEAP8[$node_type6] = 2;
+ $label = $g + 52 | 0;
+ $3 = HEAP32[$label >> 2] | 0;
+ $tobool8 = ($3 | 0) == 0;
+ if ($tobool8) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $4 = HEAP32[$root >> 2] | 0;
+ $cmp = ($4 | 0) == ($g | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $rankdir = $4 + 156 | 0;
+ $5 = HEAP32[$rankdir >> 2] | 0;
+ $and13 = $5 & 1;
+ $tobool14 = ($and13 | 0) == 0;
+ if ($tobool14) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $x = $g + 88 | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $x20 = $g + 120 | 0;
+ $7 = +HEAPF64[$x20 >> 3];
+ $cmp21 = $6 > $7;
+ $_ = $cmp21 ? $6 : $7;
+ $conv = ~~$_;
+ $conv30 = +($conv | 0);
+ $call31 = _make_aux_edge($call, $call4, $conv30, 0) | 0;
+ label = 7;
+ break;
+ case 7:
+ HEAP32[$ln1 >> 2] = $call;
+ $rn36 = $g + 272 | 0;
+ HEAP32[$rn36 >> 2] = $call4;
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _contain_clustnodes($g) {
+ $g = $g | 0;
+ var $root = 0, $0 = 0, $cmp = 0, $ln = 0, $1 = 0, $rn = 0, $2 = 0, $call = 0, $tobool = 0, $weight = 0, $3 = 0.0, $add = 0.0, $call8 = 0, $n_cluster = 0, $4 = 0, $cmp1111 = 0, $clust = 0, $c_012 = 0, $5 = 0, $arrayidx = 0, $6 = 0, $inc = 0, $7 = 0, $cmp11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $root = $g + 32 | 0;
+ $0 = HEAP32[$root >> 2] | 0;
+ $cmp = ($0 | 0) == ($g | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _contain_nodes($g);
+ $ln = $g + 268 | 0;
+ $1 = HEAP32[$ln >> 2] | 0;
+ $rn = $g + 272 | 0;
+ $2 = HEAP32[$rn >> 2] | 0;
+ $call = _find_fast_edge($1, $2) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $weight = $call + 172 | 0;
+ $3 = +HEAPF32[$weight >> 2];
+ $add = $3 + 128.0;
+ HEAPF32[$weight >> 2] = $add;
+ label = 6;
+ break;
+ case 5:
+ $call8 = _make_aux_edge($1, $2, 1.0, 128) | 0;
+ label = 6;
+ break;
+ case 6:
+ $n_cluster = $g + 212 | 0;
+ $4 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp1111 = ($4 | 0) < 1;
+ if ($cmp1111) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $clust = $g + 216 | 0;
+ $c_012 = 1;
+ label = 8;
+ break;
+ case 8:
+ $5 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $5 + ($c_012 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ _contain_clustnodes($6);
+ $inc = $c_012 + 1 | 0;
+ $7 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp11 = ($inc | 0) > ($7 | 0);
+ if ($cmp11) {
+ label = 9;
+ break;
+ } else {
+ $c_012 = $inc;
+ label = 8;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _keepout_othernodes($g) {
+ $g = $g | 0;
+ var $minrank = 0, $0 = 0, $maxrank = 0, $1 = 0, $cmp41 = 0, $conv = 0, $rank = 0, $root = 0, $ln = 0, $root44 = 0, $rn = 0, $n_cluster = 0, $2 = 0, $cmp7937 = 0, $clust = 0, $r_042 = 0, $3 = 0, $n = 0, $4 = 0, $cmp6 = 0, $v11 = 0, $5 = 0, $6 = 0, $cmp13 = 0, $order = 0, $7 = 0, $i_0_in = 0, $i_0 = 0, $cmp19 = 0, $8 = 0, $rank23 = 0, $9 = 0, $v25 = 0, $10 = 0, $arrayidx26 = 0, $11 = 0, $node_type = 0, $12 = 0, $cmp29 = 0, $call = 0, $tobool = 0, $13 = 0, $rw = 0, $14 = 0.0, $add = 0.0, $call34 = 0, $15 = 0, $16 = 0, $n41 = 0, $17 = 0, $add42 = 0, $i_1 = 0, $18 = 0, $rank46 = 0, $19 = 0, $n48 = 0, $20 = 0, $cmp49 = 0, $v56 = 0, $21 = 0, $arrayidx57 = 0, $22 = 0, $node_type59 = 0, $23 = 0, $cmp61 = 0, $call64 = 0, $tobool65 = 0, $inc = 0, $24 = 0, $lw = 0, $25 = 0.0, $add69 = 0.0, $call70 = 0, $inc75 = 0, $26 = 0, $conv3 = 0, $cmp = 0, $c_038 = 0, $27 = 0, $arrayidx83 = 0, $28 = 0, $inc85 = 0, $29 = 0, $cmp79 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ $0 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $cmp41 = $0 << 16 >> 16 > $1 << 16 >> 16;
+ if ($cmp41) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $0 << 16 >> 16;
+ $rank = $g + 224 | 0;
+ $root = $g + 32 | 0;
+ $ln = $g + 268 | 0;
+ $root44 = $g + 32 | 0;
+ $rn = $g + 272 | 0;
+ $r_042 = $conv;
+ label = 6;
+ break;
+ case 4:
+ $n_cluster = $g + 212 | 0;
+ $2 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp7937 = ($2 | 0) < 1;
+ if ($cmp7937) {
+ label = 20;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $clust = $g + 216 | 0;
+ $c_038 = 1;
+ label = 19;
+ break;
+ case 6:
+ $3 = HEAP32[$rank >> 2] | 0;
+ $n = $3 + ($r_042 * 44 & -1) | 0;
+ $4 = HEAP32[$n >> 2] | 0;
+ $cmp6 = ($4 | 0) == 0;
+ if ($cmp6) {
+ label = 18;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $v11 = $3 + ($r_042 * 44 & -1) + 4 | 0;
+ $5 = HEAP32[$v11 >> 2] | 0;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $cmp13 = ($6 | 0) == 0;
+ if ($cmp13) {
+ label = 18;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $order = $6 + 240 | 0;
+ $7 = HEAP32[$order >> 2] | 0;
+ $i_0_in = $7;
+ label = 9;
+ break;
+ case 9:
+ $i_0 = $i_0_in - 1 | 0;
+ $cmp19 = ($i_0_in | 0) > 0;
+ if ($cmp19) {
+ label = 10;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 10:
+ $8 = HEAP32[$root >> 2] | 0;
+ $rank23 = $8 + 224 | 0;
+ $9 = HEAP32[$rank23 >> 2] | 0;
+ $v25 = $9 + ($r_042 * 44 & -1) + 4 | 0;
+ $10 = HEAP32[$v25 >> 2] | 0;
+ $arrayidx26 = $10 + ($i_0 << 2) | 0;
+ $11 = HEAP32[$arrayidx26 >> 2] | 0;
+ $node_type = $11 + 162 | 0;
+ $12 = HEAP8[$node_type] | 0;
+ $cmp29 = $12 << 24 >> 24 == 0;
+ if ($cmp29) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $call = _vnode_not_related_to($g, $11) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $i_0_in = $i_0;
+ label = 9;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $13 = HEAP32[$ln >> 2] | 0;
+ $rw = $11 + 112 | 0;
+ $14 = +HEAPF64[$rw >> 3];
+ $add = $14 + 8.0;
+ $call34 = _make_aux_edge($11, $13, $add, 0) | 0;
+ label = 13;
+ break;
+ case 13:
+ $15 = HEAP32[$order >> 2] | 0;
+ $16 = HEAP32[$rank >> 2] | 0;
+ $n41 = $16 + ($r_042 * 44 & -1) | 0;
+ $17 = HEAP32[$n41 >> 2] | 0;
+ $add42 = $17 + $15 | 0;
+ $i_1 = $add42;
+ label = 14;
+ break;
+ case 14:
+ $18 = HEAP32[$root44 >> 2] | 0;
+ $rank46 = $18 + 224 | 0;
+ $19 = HEAP32[$rank46 >> 2] | 0;
+ $n48 = $19 + ($r_042 * 44 & -1) | 0;
+ $20 = HEAP32[$n48 >> 2] | 0;
+ $cmp49 = ($i_1 | 0) < ($20 | 0);
+ if ($cmp49) {
+ label = 15;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 15:
+ $v56 = $19 + ($r_042 * 44 & -1) + 4 | 0;
+ $21 = HEAP32[$v56 >> 2] | 0;
+ $arrayidx57 = $21 + ($i_1 << 2) | 0;
+ $22 = HEAP32[$arrayidx57 >> 2] | 0;
+ $node_type59 = $22 + 162 | 0;
+ $23 = HEAP8[$node_type59] | 0;
+ $cmp61 = $23 << 24 >> 24 == 0;
+ if ($cmp61) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $call64 = _vnode_not_related_to($g, $22) | 0;
+ $tobool65 = ($call64 | 0) == 0;
+ $inc = $i_1 + 1 | 0;
+ if ($tobool65) {
+ $i_1 = $inc;
+ label = 14;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $24 = HEAP32[$rn >> 2] | 0;
+ $lw = $22 + 104 | 0;
+ $25 = +HEAPF64[$lw >> 3];
+ $add69 = $25 + 8.0;
+ $call70 = _make_aux_edge($24, $22, $add69, 0) | 0;
+ label = 18;
+ break;
+ case 18:
+ $inc75 = $r_042 + 1 | 0;
+ $26 = HEAP16[$maxrank >> 1] | 0;
+ $conv3 = $26 << 16 >> 16;
+ $cmp = ($inc75 | 0) > ($conv3 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $r_042 = $inc75;
+ label = 6;
+ break;
+ }
+ case 19:
+ $27 = HEAP32[$clust >> 2] | 0;
+ $arrayidx83 = $27 + ($c_038 << 2) | 0;
+ $28 = HEAP32[$arrayidx83 >> 2] | 0;
+ _keepout_othernodes($28);
+ $inc85 = $c_038 + 1 | 0;
+ $29 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp79 = ($inc85 | 0) > ($29 | 0);
+ if ($cmp79) {
+ label = 20;
+ break;
+ } else {
+ $c_038 = $inc85;
+ label = 19;
+ break;
+ }
+ case 20:
+ return;
+ }
+}
+function _contain_subclust($g) {
+ $g = $g | 0;
+ var $n_cluster = 0, $0 = 0, $cmp12 = 0, $clust = 0, $ln = 0, $x = 0, $rn9 = 0, $x13 = 0, $c_013 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $3 = 0, $ln4 = 0, $4 = 0, $5 = 0.0, $add = 0.0, $call = 0, $rn = 0, $6 = 0, $7 = 0, $8 = 0.0, $add14 = 0.0, $call15 = 0, $inc = 0, $9 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _make_lrvn($g);
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp12 = ($0 | 0) < 1;
+ if ($cmp12) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $ln = $g + 268 | 0;
+ $x = $g + 136 | 0;
+ $rn9 = $g + 272 | 0;
+ $x13 = $g + 104 | 0;
+ $c_013 = 1;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $1 + ($c_013 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _make_lrvn($2);
+ $3 = HEAP32[$ln >> 2] | 0;
+ $ln4 = $2 + 268 | 0;
+ $4 = HEAP32[$ln4 >> 2] | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $add = $5 + 8.0;
+ $call = _make_aux_edge($3, $4, $add, 0) | 0;
+ $rn = $2 + 272 | 0;
+ $6 = HEAP32[$rn >> 2] | 0;
+ $7 = HEAP32[$rn9 >> 2] | 0;
+ $8 = +HEAPF64[$x13 >> 3];
+ $add14 = $8 + 8.0;
+ $call15 = _make_aux_edge($6, $7, $add14, 0) | 0;
+ _contain_subclust($2);
+ $inc = $c_013 + 1 | 0;
+ $9 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($9 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $c_013 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ return;
+ }
+}
+function _separate_subclust($g) {
+ $g = $g | 0;
+ var $n_cluster = 0, $0 = 0, $cmp32 = 0, $clust = 0, $cmp530 = 0, $clust13 = 0, $i_033 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $inc = 0, $3 = 0, $cmp = 0, $i_131 = 0, $add = 0, $4 = 0, $cmp1027 = 0, $5 = 0, $arrayidx1428 = 0, $6 = 0, $7 = 0, $8 = 0, $j_029 = 0, $arrayidx17 = 0, $9 = 0, $minrank = 0, $10 = 0, $minrank20 = 0, $11 = 0, $cmp22 = 0, $_ = 0, $_26 = 0, $maxrank = 0, $12 = 0, $minrank27 = 0, $13 = 0, $conv28 = 0, $cmp29 = 0, $rank = 0, $14 = 0, $v = 0, $15 = 0, $16 = 0, $order = 0, $17 = 0, $rank43 = 0, $18 = 0, $v45 = 0, $19 = 0, $20 = 0, $order48 = 0, $21 = 0, $cmp49 = 0, $___26 = 0, $_26__ = 0, $rn = 0, $22 = 0, $ln = 0, $23 = 0, $call = 0, $inc56 = 0, $24 = 0, $cmp10 = 0, $25 = 0, $arrayidx14 = 0, $26 = 0, $_lcssa = 0, $27 = 0, $cmp5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp32 = ($0 | 0) < 1;
+ if ($cmp32) {
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $i_033 = 1;
+ label = 6;
+ break;
+ case 4:
+ $cmp530 = ($3 | 0) < 1;
+ if ($cmp530) {
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $clust13 = $g + 216 | 0;
+ $i_131 = 1;
+ label = 7;
+ break;
+ case 6:
+ $1 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $1 + ($i_033 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ _make_lrvn($2);
+ $inc = $i_033 + 1 | 0;
+ $3 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($3 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $i_033 = $inc;
+ label = 6;
+ break;
+ }
+ case 7:
+ $add = $i_131 + 1 | 0;
+ $4 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp1027 = ($add | 0) > ($4 | 0);
+ $5 = HEAP32[$clust13 >> 2] | 0;
+ $arrayidx1428 = $5 + ($i_131 << 2) | 0;
+ $6 = HEAP32[$arrayidx1428 >> 2] | 0;
+ if ($cmp1027) {
+ $_lcssa = $6;
+ label = 11;
+ break;
+ } else {
+ $j_029 = $add;
+ $8 = $5;
+ $7 = $6;
+ label = 8;
+ break;
+ }
+ case 8:
+ $arrayidx17 = $8 + ($j_029 << 2) | 0;
+ $9 = HEAP32[$arrayidx17 >> 2] | 0;
+ $minrank = $7 + 248 | 0;
+ $10 = HEAP16[$minrank >> 1] | 0;
+ $minrank20 = $9 + 248 | 0;
+ $11 = HEAP16[$minrank20 >> 1] | 0;
+ $cmp22 = $10 << 16 >> 16 > $11 << 16 >> 16;
+ $_ = $cmp22 ? $9 : $7;
+ $_26 = $cmp22 ? $7 : $9;
+ $maxrank = $_ + 250 | 0;
+ $12 = HEAP16[$maxrank >> 1] | 0;
+ $minrank27 = $_26 + 248 | 0;
+ $13 = HEAP16[$minrank27 >> 1] | 0;
+ $conv28 = $13 << 16 >> 16;
+ $cmp29 = $12 << 16 >> 16 < $13 << 16 >> 16;
+ if ($cmp29) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $rank = $_ + 224 | 0;
+ $14 = HEAP32[$rank >> 2] | 0;
+ $v = $14 + ($conv28 * 44 & -1) + 4 | 0;
+ $15 = HEAP32[$v >> 2] | 0;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $order = $16 + 240 | 0;
+ $17 = HEAP32[$order >> 2] | 0;
+ $rank43 = $_26 + 224 | 0;
+ $18 = HEAP32[$rank43 >> 2] | 0;
+ $v45 = $18 + ($conv28 * 44 & -1) + 4 | 0;
+ $19 = HEAP32[$v45 >> 2] | 0;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $order48 = $20 + 240 | 0;
+ $21 = HEAP32[$order48 >> 2] | 0;
+ $cmp49 = ($17 | 0) < ($21 | 0);
+ $___26 = $cmp49 ? $_ : $_26;
+ $_26__ = $cmp49 ? $_26 : $_;
+ $rn = $___26 + 272 | 0;
+ $22 = HEAP32[$rn >> 2] | 0;
+ $ln = $_26__ + 268 | 0;
+ $23 = HEAP32[$ln >> 2] | 0;
+ $call = _make_aux_edge($22, $23, 8.0, 0) | 0;
+ label = 10;
+ break;
+ case 10:
+ $inc56 = $j_029 + 1 | 0;
+ $24 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp10 = ($inc56 | 0) > ($24 | 0);
+ $25 = HEAP32[$clust13 >> 2] | 0;
+ $arrayidx14 = $25 + ($i_131 << 2) | 0;
+ $26 = HEAP32[$arrayidx14 >> 2] | 0;
+ if ($cmp10) {
+ $_lcssa = $26;
+ label = 11;
+ break;
+ } else {
+ $j_029 = $inc56;
+ $8 = $25;
+ $7 = $26;
+ label = 8;
+ break;
+ }
+ case 11:
+ _separate_subclust($_lcssa);
+ $27 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp5 = ($add | 0) > ($27 | 0);
+ if ($cmp5) {
+ label = 12;
+ break;
+ } else {
+ $i_131 = $add;
+ label = 7;
+ break;
+ }
+ case 12:
+ return;
+ }
+}
+function _make_LR_constraints($g) {
+ $g = $g | 0;
+ var $sep = 0, $rank2 = 0, $0 = 0, $has_labels = 0, $1 = 0, $and = 0, $tobool = 0, $nodesep5 = 0, $2 = 0, $arrayidx = 0, $arrayidx6 = 0, $_ = 0, $minrank = 0, $3 = 0, $maxrank = 0, $4 = 0, $cmp106 = 0, $conv12 = 0, $i_0107 = 0, $v17 = 0, $5 = 0, $6 = 0, $rank20 = 0, $n = 0, $7 = 0, $cmp25102 = 0, $and21 = 0, $arrayidx22 = 0, $8 = 0, $conv63 = 0.0, $9 = 0, $cmp25 = 0, $last_0104 = 0.0, $j_0103 = 0, $10 = 0, $arrayidx30 = 0, $11 = 0, $rw = 0, $12 = 0.0, $conv32 = 0, $mval = 0, $size = 0, $13 = 0, $cmp35 = 0, $list = 0, $14 = 0, $15 = 0, $tobool4297 = 0, $16 = 0, $17 = 0, $k_099 = 0, $sw_098 = 0, $tail = 0, $18 = 0, $head = 0, $19 = 0, $cmp44 = 0, $call = 0, $add = 0, $sw_1 = 0, $inc = 0, $arrayidx41 = 0, $20 = 0, $tobool42 = 0, $sw_0_lcssa = 0, $conv48 = 0.0, $21 = 0.0, $add51 = 0.0, $add53 = 0, $22 = 0, $arrayidx56 = 0, $23 = 0, $tobool57 = 0, $24 = 0.0, $lw = 0, $25 = 0.0, $add62 = 0.0, $add64 = 0.0, $call65 = 0, $add66 = 0.0, $conv67 = 0, $rank69 = 0, $conv70 = 0.0, $last_1 = 0.0, $alg = 0, $26 = 0, $tobool73 = 0, $list76 = 0, $27 = 0, $28 = 0, $arrayidx81 = 0, $29 = 0, $head82 = 0, $30 = 0, $order = 0, $31 = 0, $head84 = 0, $32 = 0, $order86 = 0, $33 = 0, $cmp87 = 0, $_92 = 0, $_93 = 0, $minlen = 0, $34 = 0, $35 = 0, $conv92 = 0, $36 = 0, $mul = 0, $div = 0, $conv95 = 0.0, $head96 = 0, $37 = 0, $tail100 = 0, $38 = 0, $call107 = 0, $cmp108 = 0, $lw102 = 0, $rw98 = 0, $39 = 0.0, $40 = 0.0, $add99 = 0.0, $add103 = 0.0, $conv104 = 0, $conv113 = 0.0, $weight = 0, $41 = 0, $42 = 0.0, $conv115 = 0, $call116 = 0, $tail119 = 0, $43 = 0, $head123 = 0, $44 = 0, $call130 = 0, $cmp131 = 0, $lw125 = 0, $rw121 = 0, $45 = 0.0, $46 = 0.0, $add122 = 0.0, $add126 = 0.0, $conv127 = 0, $conv136 = 0.0, $weight138 = 0, $47 = 0, $48 = 0.0, $conv139 = 0, $call140 = 0, $size145 = 0, $49 = 0, $cmp146100 = 0, $list151 = 0, $k_1101 = 0, $50 = 0, $arrayidx152 = 0, $51 = 0, $tail153 = 0, $52 = 0, $order155 = 0, $53 = 0, $head156 = 0, $54 = 0, $order158 = 0, $55 = 0, $cmp159 = 0, $_94 = 0, $_95 = 0, $rw169 = 0, $56 = 0.0, $lw171 = 0, $57 = 0.0, $add172 = 0.0, $minlen174 = 0, $58 = 0, $conv175 = 0, $59 = 0, $mul178 = 0, $conv179 = 0.0, $add180 = 0.0, $conv181 = 0, $call182 = 0, $tobool183 = 0, $conv185 = 0.0, $conv188 = 0.0, $add189 = 0.0, $dist = 0, $60 = 0.0, $cmp191 = 0, $add195 = 0.0, $sub = 0.0, $add195_sink = 0.0, $conv196 = 0, $conv200 = 0.0, $add201 = 0.0, $cmp202 = 0, $61 = 0, $conv209 = 0.0, $add210 = 0.0, $62 = 0.0, $cmp213 = 0, $add218 = 0.0, $sub223 = 0.0, $add218_sink = 0.0, $conv219 = 0, $conv227 = 0.0, $add228 = 0.0, $cond230 = 0.0, $conv231 = 0, $cmp232 = 0, $conv235 = 0.0, $minlen238 = 0, $63 = 0, $conv239 = 0, $cmp240 = 0, $extract_t91 = 0, $cond248_off0 = 0, $label = 0, $64 = 0, $tobool254 = 0, $conv256 = 0.0, $weight258 = 0, $65 = 0.0, $conv259 = 0, $call260 = 0, $inc264 = 0, $66 = 0, $cmp146 = 0, $inc270 = 0, $67 = 0, $conv14 = 0, $cmp = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sep = __stackBase__ | 0;
+ $rank2 = $g + 224 | 0;
+ $0 = HEAP32[$rank2 >> 2] | 0;
+ $has_labels = $g + 153 | 0;
+ $1 = HEAP8[$has_labels] | 0;
+ $and = $1 & 1;
+ $tobool = $and << 24 >> 24 == 0;
+ $nodesep5 = $g + 260 | 0;
+ $2 = HEAP32[$nodesep5 >> 2] | 0;
+ $arrayidx = $sep | 0;
+ HEAP32[$arrayidx >> 2] = $2;
+ $arrayidx6 = $sep + 4 | 0;
+ $_ = $tobool ? $2 : 5;
+ HEAP32[$arrayidx6 >> 2] = $_;
+ $minrank = $g + 248 | 0;
+ $3 = HEAP16[$minrank >> 1] | 0;
+ $maxrank = $g + 250 | 0;
+ $4 = HEAP16[$maxrank >> 1] | 0;
+ $cmp106 = $3 << 16 >> 16 > $4 << 16 >> 16;
+ if ($cmp106) {
+ label = 39;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv12 = $3 << 16 >> 16;
+ $i_0107 = $conv12;
+ label = 4;
+ break;
+ case 4:
+ $v17 = $0 + ($i_0107 * 44 & -1) + 4 | 0;
+ $5 = HEAP32[$v17 >> 2] | 0;
+ $6 = HEAP32[$5 >> 2] | 0;
+ $rank20 = $6 + 236 | 0;
+ HEAP32[$rank20 >> 2] = 0;
+ $n = $0 + ($i_0107 * 44 & -1) | 0;
+ $7 = HEAP32[$n >> 2] | 0;
+ $cmp25102 = ($7 | 0) > 0;
+ if ($cmp25102) {
+ label = 5;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 5:
+ $and21 = $i_0107 & 1;
+ $arrayidx22 = $sep + ($and21 << 2) | 0;
+ $8 = HEAP32[$arrayidx22 >> 2] | 0;
+ $conv63 = +($8 | 0);
+ $j_0103 = 0;
+ $last_0104 = 0.0;
+ label = 7;
+ break;
+ case 6:
+ $9 = HEAP32[$n >> 2] | 0;
+ $cmp25 = ($add53 | 0) < ($9 | 0);
+ if ($cmp25) {
+ $j_0103 = $add53;
+ $last_0104 = $last_1;
+ label = 7;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 7:
+ $10 = HEAP32[$v17 >> 2] | 0;
+ $arrayidx30 = $10 + ($j_0103 << 2) | 0;
+ $11 = HEAP32[$arrayidx30 >> 2] | 0;
+ $rw = $11 + 112 | 0;
+ $12 = +HEAPF64[$rw >> 3];
+ $conv32 = ~~$12;
+ $mval = $11 + 244 | 0;
+ HEAP32[$mval >> 2] = $conv32;
+ $size = $11 + 212 | 0;
+ $13 = HEAP32[$size >> 2] | 0;
+ $cmp35 = ($13 | 0) > 0;
+ if ($cmp35) {
+ label = 8;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 8:
+ $list = $11 + 208 | 0;
+ $14 = HEAP32[$list >> 2] | 0;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $tobool4297 = ($15 | 0) == 0;
+ if ($tobool4297) {
+ $sw_0_lcssa = 0;
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $16 = HEAP32[$list >> 2] | 0;
+ $sw_098 = 0;
+ $k_099 = 0;
+ $17 = $15;
+ label = 10;
+ break;
+ case 10:
+ $tail = $17 + 16 | 0;
+ $18 = HEAP32[$tail >> 2] | 0;
+ $head = $17 + 12 | 0;
+ $19 = HEAP32[$head >> 2] | 0;
+ $cmp44 = ($18 | 0) == ($19 | 0);
+ if ($cmp44) {
+ label = 11;
+ break;
+ } else {
+ $sw_1 = $sw_098;
+ label = 12;
+ break;
+ }
+ case 11:
+ $call = _selfRightSpace($17) | 0;
+ $add = $call + $sw_098 | 0;
+ $sw_1 = $add;
+ label = 12;
+ break;
+ case 12:
+ $inc = $k_099 + 1 | 0;
+ $arrayidx41 = $16 + ($inc << 2) | 0;
+ $20 = HEAP32[$arrayidx41 >> 2] | 0;
+ $tobool42 = ($20 | 0) == 0;
+ if ($tobool42) {
+ $sw_0_lcssa = $sw_1;
+ label = 13;
+ break;
+ } else {
+ $sw_098 = $sw_1;
+ $k_099 = $inc;
+ $17 = $20;
+ label = 10;
+ break;
+ }
+ case 13:
+ $conv48 = +($sw_0_lcssa | 0);
+ $21 = +HEAPF64[$rw >> 3];
+ $add51 = $conv48 + $21;
+ HEAPF64[$rw >> 3] = $add51;
+ label = 14;
+ break;
+ case 14:
+ $add53 = $j_0103 + 1 | 0;
+ $22 = HEAP32[$v17 >> 2] | 0;
+ $arrayidx56 = $22 + ($add53 << 2) | 0;
+ $23 = HEAP32[$arrayidx56 >> 2] | 0;
+ $tobool57 = ($23 | 0) == 0;
+ if ($tobool57) {
+ $last_1 = $last_0104;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $24 = +HEAPF64[$rw >> 3];
+ $lw = $23 + 104 | 0;
+ $25 = +HEAPF64[$lw >> 3];
+ $add62 = $24 + $25;
+ $add64 = $conv63 + $add62;
+ $call65 = _make_aux_edge($11, $23, $add64, 0) | 0;
+ $add66 = $last_0104 + $add64;
+ $conv67 = ~~$add66;
+ $rank69 = $23 + 236 | 0;
+ HEAP32[$rank69 >> 2] = $conv67;
+ $conv70 = +($conv67 | 0);
+ $last_1 = $conv70;
+ label = 16;
+ break;
+ case 16:
+ $alg = $11 + 128 | 0;
+ $26 = HEAP32[$alg >> 2] | 0;
+ $tobool73 = ($26 | 0) == 0;
+ if ($tobool73) {
+ label = 21;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $list76 = $11 + 256 | 0;
+ $27 = HEAP32[$list76 >> 2] | 0;
+ $28 = HEAP32[$27 >> 2] | 0;
+ $arrayidx81 = $27 + 4 | 0;
+ $29 = HEAP32[$arrayidx81 >> 2] | 0;
+ $head82 = $28 + 12 | 0;
+ $30 = HEAP32[$head82 >> 2] | 0;
+ $order = $30 + 240 | 0;
+ $31 = HEAP32[$order >> 2] | 0;
+ $head84 = $29 + 12 | 0;
+ $32 = HEAP32[$head84 >> 2] | 0;
+ $order86 = $32 + 240 | 0;
+ $33 = HEAP32[$order86 >> 2] | 0;
+ $cmp87 = ($31 | 0) > ($33 | 0);
+ $_92 = $cmp87 ? $29 : $28;
+ $_93 = $cmp87 ? $28 : $29;
+ $minlen = $26 + 186 | 0;
+ $34 = $minlen;
+ $35 = HEAP16[$34 >> 1] | 0;
+ $conv92 = $35 & 65535;
+ $36 = HEAP32[$nodesep5 >> 2] | 0;
+ $mul = Math_imul($conv92, $36);
+ $div = ($mul | 0) / 2 & -1;
+ $conv95 = +($div | 0);
+ $head96 = $_92 + 12 | 0;
+ $37 = HEAP32[$head96 >> 2] | 0;
+ $tail100 = $_92 + 16 | 0;
+ $38 = HEAP32[$tail100 >> 2] | 0;
+ $call107 = _canreach($38, $37) | 0;
+ $cmp108 = ($call107 | 0) == 0;
+ if ($cmp108) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $lw102 = $38 + 104 | 0;
+ $rw98 = $37 + 112 | 0;
+ $39 = +HEAPF64[$lw102 >> 3];
+ $40 = +HEAPF64[$rw98 >> 3];
+ $add99 = $conv95 + $40;
+ $add103 = $39 + $add99;
+ $conv104 = ~~$add103;
+ $conv113 = +($conv104 | 0);
+ $weight = $26 + 172 | 0;
+ $41 = $weight;
+ $42 = +HEAPF32[$41 >> 2];
+ $conv115 = ~~$42;
+ $call116 = _make_aux_edge($37, $38, $conv113, $conv115) | 0;
+ label = 19;
+ break;
+ case 19:
+ $tail119 = $_93 + 16 | 0;
+ $43 = HEAP32[$tail119 >> 2] | 0;
+ $head123 = $_93 + 12 | 0;
+ $44 = HEAP32[$head123 >> 2] | 0;
+ $call130 = _canreach($44, $43) | 0;
+ $cmp131 = ($call130 | 0) == 0;
+ if ($cmp131) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $lw125 = $44 + 104 | 0;
+ $rw121 = $43 + 112 | 0;
+ $45 = +HEAPF64[$lw125 >> 3];
+ $46 = +HEAPF64[$rw121 >> 3];
+ $add122 = $conv95 + $46;
+ $add126 = $45 + $add122;
+ $conv127 = ~~$add126;
+ $conv136 = +($conv127 | 0);
+ $weight138 = $26 + 172 | 0;
+ $47 = $weight138;
+ $48 = +HEAPF32[$47 >> 2];
+ $conv139 = ~~$48;
+ $call140 = _make_aux_edge($43, $44, $conv136, $conv139) | 0;
+ label = 21;
+ break;
+ case 21:
+ $size145 = $11 + 196 | 0;
+ $49 = HEAP32[$size145 >> 2] | 0;
+ $cmp146100 = ($49 | 0) > 0;
+ if ($cmp146100) {
+ label = 22;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 22:
+ $list151 = $11 + 192 | 0;
+ $k_1101 = 0;
+ label = 23;
+ break;
+ case 23:
+ $50 = HEAP32[$list151 >> 2] | 0;
+ $arrayidx152 = $50 + ($k_1101 << 2) | 0;
+ $51 = HEAP32[$arrayidx152 >> 2] | 0;
+ $tail153 = $51 + 16 | 0;
+ $52 = HEAP32[$tail153 >> 2] | 0;
+ $order155 = $52 + 240 | 0;
+ $53 = HEAP32[$order155 >> 2] | 0;
+ $head156 = $51 + 12 | 0;
+ $54 = HEAP32[$head156 >> 2] | 0;
+ $order158 = $54 + 240 | 0;
+ $55 = HEAP32[$order158 >> 2] | 0;
+ $cmp159 = ($53 | 0) < ($55 | 0);
+ $_94 = $cmp159 ? $52 : $54;
+ $_95 = $cmp159 ? $54 : $52;
+ $rw169 = $_94 + 112 | 0;
+ $56 = +HEAPF64[$rw169 >> 3];
+ $lw171 = $_95 + 104 | 0;
+ $57 = +HEAPF64[$lw171 >> 3];
+ $add172 = $56 + $57;
+ $minlen174 = $51 + 186 | 0;
+ $58 = HEAP16[$minlen174 >> 1] | 0;
+ $conv175 = $58 & 65535;
+ $59 = HEAP32[$nodesep5 >> 2] | 0;
+ $mul178 = Math_imul($conv175, $59);
+ $conv179 = +($mul178 | 0);
+ $add180 = $add172 + $conv179;
+ $conv181 = ~~$add180;
+ $call182 = _find_fast_edge($_94, $_95) | 0;
+ $tobool183 = ($call182 | 0) == 0;
+ if ($tobool183) {
+ label = 35;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $conv185 = +($conv181 | 0);
+ $conv188 = +($59 | 0);
+ $add189 = $add172 + $conv188;
+ $dist = $51 + 152 | 0;
+ $60 = +HEAPF64[$dist >> 3];
+ $cmp191 = $60 < 0.0;
+ if ($cmp191) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $add195 = $60 + .5;
+ $add195_sink = $add195;
+ label = 27;
+ break;
+ case 26:
+ $sub = $60 + -.5;
+ $add195_sink = $sub;
+ label = 27;
+ break;
+ case 27:
+ $conv196 = ~~$add195_sink;
+ $conv200 = +($conv196 | 0);
+ $add201 = $add189 + $conv200;
+ $cmp202 = $conv185 > $add201;
+ if ($cmp202) {
+ $cond230 = $conv185;
+ label = 32;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $61 = HEAP32[$nodesep5 >> 2] | 0;
+ $conv209 = +($61 | 0);
+ $add210 = $add172 + $conv209;
+ $62 = +HEAPF64[$dist >> 3];
+ $cmp213 = $62 < 0.0;
+ if ($cmp213) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $add218 = $62 + .5;
+ $add218_sink = $add218;
+ label = 31;
+ break;
+ case 30:
+ $sub223 = $62 + -.5;
+ $add218_sink = $sub223;
+ label = 31;
+ break;
+ case 31:
+ $conv219 = ~~$add218_sink;
+ $conv227 = +($conv219 | 0);
+ $add228 = $add210 + $conv227;
+ $cond230 = $add228;
+ label = 32;
+ break;
+ case 32:
+ $conv231 = ~~$cond230;
+ $cmp232 = ($conv231 | 0) > 65535;
+ if ($cmp232) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ $conv235 = +($conv231 | 0);
+ _largeMinlen($conv235);
+ case 34:
+ $minlen238 = $call182 + 186 | 0;
+ $63 = HEAP16[$minlen238 >> 1] | 0;
+ $conv239 = $63 & 65535;
+ $cmp240 = ($conv239 | 0) > ($conv231 | 0);
+ $extract_t91 = $conv231 & 65535;
+ $cond248_off0 = $cmp240 ? $63 : $extract_t91;
+ HEAP16[$minlen238 >> 1] = $cond248_off0;
+ label = 37;
+ break;
+ case 35:
+ $label = $51 + 112 | 0;
+ $64 = HEAP32[$label >> 2] | 0;
+ $tobool254 = ($64 | 0) == 0;
+ if ($tobool254) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ $conv256 = +($conv181 | 0);
+ $weight258 = $51 + 172 | 0;
+ $65 = +HEAPF32[$weight258 >> 2];
+ $conv259 = ~~$65;
+ $call260 = _make_aux_edge($_94, $_95, $conv256, $conv259) | 0;
+ label = 37;
+ break;
+ case 37:
+ $inc264 = $k_1101 + 1 | 0;
+ $66 = HEAP32[$size145 >> 2] | 0;
+ $cmp146 = ($inc264 | 0) < ($66 | 0);
+ if ($cmp146) {
+ $k_1101 = $inc264;
+ label = 23;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 38:
+ $inc270 = $i_0107 + 1 | 0;
+ $67 = HEAP16[$maxrank >> 1] | 0;
+ $conv14 = $67 << 16 >> 16;
+ $cmp = ($inc270 | 0) > ($conv14 | 0);
+ if ($cmp) {
+ label = 39;
+ break;
+ } else {
+ $i_0107 = $inc270;
+ label = 4;
+ break;
+ }
+ case 39:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _renewlist($L) {
+ $L = $L | 0;
+ var $size = 0, $0 = 0, $cmp5 = 0, $list = 0, $i_06 = 0, $1 = 0, $arrayidx = 0, $dec = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $L + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp5 = ($0 | 0) > -1;
+ if ($cmp5) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $list = $L | 0;
+ $i_06 = $0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($i_06 << 2) | 0;
+ HEAP32[$arrayidx >> 2] = 0;
+ $dec = $i_06 - 1 | 0;
+ $cmp = ($i_06 | 0) > 0;
+ if ($cmp) {
+ $i_06 = $dec;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[$size >> 2] = 0;
+ return;
+ }
+}
+function _vnode_not_related_to($g, $v) {
+ $g = $g | 0;
+ $v = $v | 0;
+ var $node_type = 0, $0 = 0, $cmp = 0, $list = 0, $1 = 0, $2 = 0, $e_0 = 0, $to_orig = 0, $3 = 0, $tobool = 0, $tail = 0, $4 = 0, $5 = 0, $6 = 0, $call = 0, $tobool6 = 0, $head = 0, $7 = 0, $8 = 0, $call9 = 0, $tobool10 = 0, $_ = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $node_type = $v + 162 | 0;
+ $0 = HEAP8[$node_type] | 0;
+ $cmp = $0 << 24 >> 24 == 1;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ }
+ case 3:
+ $list = $v + 256 | 0;
+ $1 = HEAP32[$list >> 2] | 0;
+ $2 = HEAP32[$1 >> 2] | 0;
+ $e_0 = $2;
+ label = 4;
+ break;
+ case 4:
+ $to_orig = $e_0 + 132 | 0;
+ $3 = HEAP32[$to_orig >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $e_0 = $3;
+ label = 4;
+ break;
+ }
+ case 5:
+ $tail = $e_0 + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $5 = $4 | 0;
+ $6 = $g;
+ $call = _agcontains($6, $5) | 0;
+ $tobool6 = ($call | 0) == 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ }
+ case 6:
+ $head = $e_0 + 12 | 0;
+ $7 = HEAP32[$head >> 2] | 0;
+ $8 = $7 | 0;
+ $call9 = _agcontains($6, $8) | 0;
+ $tobool10 = ($call9 | 0) == 0;
+ $_ = $tobool10 & 1;
+ $retval_0 = $_;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _canreach($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ return _go($u, $v) | 0;
+}
+function _go($u, $v) {
+ $u = $u | 0;
+ $v = $v | 0;
+ var $cmp = 0, $list = 0, $0 = 0, $i_0 = 0, $arrayidx = 0, $1 = 0, $tobool = 0, $head = 0, $2 = 0, $call = 0, $tobool2 = 0, $inc = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($u | 0) == ($v | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $list = $u + 184 | 0;
+ $0 = HEAP32[$list >> 2] | 0;
+ $i_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $0 + ($i_0 << 2) | 0;
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $head = $1 + 12 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $call = _go($2, $v) | 0;
+ $tobool2 = ($call | 0) == 0;
+ $inc = $i_0 + 1 | 0;
+ if ($tobool2) {
+ $i_0 = $inc;
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 6;
+ break;
+ }
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dot_scan_ranks($g) {
+ $g = $g | 0;
+ var $minrank = 0, $maxrank = 0, $0 = 0, $call = 0, $tobool19 = 0, $n_022_in = 0, $leader_021 = 0, $n_022 = 0, $1 = 0, $conv = 0, $rank = 0, $2 = 0, $3 = 0, $cmp = 0, $conv8 = 0, $4 = 0, $conv13 = 0, $5 = 0, $cmp16 = 0, $conv21 = 0, $cmp25 = 0, $6 = 0, $rank31 = 0, $7 = 0, $cmp32 = 0, $n_0_leader_0 = 0, $leader_1 = 0, $call37 = 0, $tobool = 0, $leader_0_lcssa = 0, $leader39 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $minrank = $g + 248 | 0;
+ HEAP16[$minrank >> 1] = 32767;
+ $maxrank = $g + 250 | 0;
+ HEAP16[$maxrank >> 1] = -1;
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool19 = ($call | 0) == 0;
+ if ($tobool19) {
+ $leader_0_lcssa = 0;
+ label = 10;
+ break;
+ } else {
+ $leader_021 = 0;
+ $n_022_in = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $n_022 = $n_022_in;
+ $1 = HEAP16[$maxrank >> 1] | 0;
+ $conv = $1 << 16 >> 16;
+ $rank = $n_022_in + 236 | 0;
+ $2 = $rank;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $cmp = ($conv | 0) < ($3 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $conv8 = $3 & 65535;
+ HEAP16[$maxrank >> 1] = $conv8;
+ label = 5;
+ break;
+ case 5:
+ $4 = HEAP16[$minrank >> 1] | 0;
+ $conv13 = $4 << 16 >> 16;
+ $5 = HEAP32[$2 >> 2] | 0;
+ $cmp16 = ($conv13 | 0) > ($5 | 0);
+ if ($cmp16) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $conv21 = $5 & 65535;
+ HEAP16[$minrank >> 1] = $conv21;
+ label = 7;
+ break;
+ case 7:
+ $cmp25 = ($leader_021 | 0) == 0;
+ if ($cmp25) {
+ $leader_1 = $n_022;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $6 = HEAP32[$2 >> 2] | 0;
+ $rank31 = $leader_021 + 236 | 0;
+ $7 = HEAP32[$rank31 >> 2] | 0;
+ $cmp32 = ($6 | 0) < ($7 | 0);
+ $n_0_leader_0 = $cmp32 ? $n_022 : $leader_021;
+ $leader_1 = $n_0_leader_0;
+ label = 9;
+ break;
+ case 9:
+ $call37 = _agnxtnode($0, $n_022_in) | 0;
+ $tobool = ($call37 | 0) == 0;
+ if ($tobool) {
+ $leader_0_lcssa = $leader_1;
+ label = 10;
+ break;
+ } else {
+ $leader_021 = $leader_1;
+ $n_022_in = $call37;
+ label = 3;
+ break;
+ }
+ case 10:
+ $leader39 = $g + 276 | 0;
+ HEAP32[$leader39 >> 2] = $leader_0_lcssa;
+ return;
+ }
+}
+function _rank1($g) {
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $call1 = 0.0, $1 = 0, $call2 = 0, $conv = 0.0, $mul = 0.0, $conv3 = 0, $maxiter_0 = 0, $size = 0, $2 = 0, $cmp10 = 0, $list = 0, $nlist = 0, $n_cluster = 0, $3 = 0, $c_011 = 0, $4 = 0, $arrayidx = 0, $5 = 0, $6 = 0, $cmp9 = 0, $cond = 0, $call11 = 0, $inc = 0, $7 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g | 0;
+ $call = _agget($0, 152368) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $maxiter_0 = 2147483647;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = +_atof($call);
+ $1 = $g;
+ $call2 = _agnnodes($1) | 0;
+ $conv = +($call2 | 0);
+ $mul = $call1 * $conv;
+ $conv3 = ~~$mul;
+ $maxiter_0 = $conv3;
+ label = 4;
+ break;
+ case 4:
+ $size = $g + 232 | 0;
+ $2 = HEAP32[$size >> 2] | 0;
+ $cmp10 = ($2 | 0) > 0;
+ if ($cmp10) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $list = $g + 228 | 0;
+ $nlist = $g + 220 | 0;
+ $n_cluster = $g + 212 | 0;
+ $3 = $g;
+ $c_011 = 0;
+ label = 6;
+ break;
+ case 6:
+ $4 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $4 + ($c_011 << 2) | 0;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ HEAP32[$nlist >> 2] = $5;
+ $6 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp9 = ($6 | 0) == 0;
+ $cond = $cmp9 & 1;
+ $call11 = _rank($3, $cond, $maxiter_0) | 0;
+ $inc = $c_011 + 1 | 0;
+ $7 = HEAP32[$size >> 2] | 0;
+ $cmp = ($inc | 0) < ($7 | 0);
+ if ($cmp) {
+ $c_011 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ return;
+ }
+}
+function _dot_rank($g, $asp) {
+ $g = $g | 0;
+ $asp = $asp | 0;
+ var $p = 0, $tmpcast = 0, $tmp = 0, $tmpcast21 = 0, $tobool = 0, $0 = 0, $ld$0$0 = 0, $1$0 = 0, $ld$1$1 = 0, $1$1 = 0, $st$2$0 = 0, $st$3$1 = 0, $size = 0, $2 = 0, $cmp = 0, $n_cluster = 0, $3 = 0, $cmp3 = 0, $badGraph = 0, $4 = 0, $ld$4$0 = 0, $5$0 = 0, $ld$5$1 = 0, $5$1 = 0, $st$6$0 = 0, $st$7$1 = 0, $asp_addr_0 = 0, $6 = 0, $call = 0, $tobool6 = 0, $tobool9 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p = __stackBase__ | 0;
+ $tmpcast = $p;
+ $tmp = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $tmpcast21 = $tmp;
+ _edgelabel_ranks($g);
+ $tobool = ($asp | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = $g;
+ _init_UF_size($0);
+ _initEdgeTypes($0);
+ _collapse_sets($g, $g);
+ _class1($0);
+ _minmax_edges($tmpcast21, $g);
+ $ld$0$0 = $tmp | 0;
+ $1$0 = HEAP32[$ld$0$0 >> 2] | 0;
+ $ld$1$1 = $tmp + 4 | 0;
+ $1$1 = HEAP32[$ld$1$1 >> 2] | 0;
+ $st$2$0 = $p | 0;
+ HEAP32[$st$2$0 >> 2] = $1$0;
+ $st$3$1 = $p + 4 | 0;
+ HEAP32[$st$3$1 >> 2] = $1$1;
+ _decompose($0, 0);
+ $size = $g + 232 | 0;
+ $2 = HEAP32[$size >> 2] | 0;
+ $cmp = ($2 | 0) > 1;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $n_cluster = $g + 212 | 0;
+ $3 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp3 = ($3 | 0) > 0;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ $asp_addr_0 = $asp;
+ label = 7;
+ break;
+ }
+ case 5:
+ $badGraph = $asp + 32 | 0;
+ HEAP32[$badGraph >> 2] = 1;
+ $asp_addr_0 = 0;
+ label = 7;
+ break;
+ case 6:
+ _collapse_sets($g, $g);
+ $4 = $g;
+ _class1($4);
+ _minmax_edges($tmpcast21, $g);
+ $ld$4$0 = $tmp | 0;
+ $5$0 = HEAP32[$ld$4$0 >> 2] | 0;
+ $ld$5$1 = $tmp + 4 | 0;
+ $5$1 = HEAP32[$ld$5$1 >> 2] | 0;
+ $st$6$0 = $p | 0;
+ HEAP32[$st$6$0 >> 2] = $5$0;
+ $st$7$1 = $p + 4 | 0;
+ HEAP32[$st$7$1 >> 2] = $5$1;
+ _decompose($4, 0);
+ $asp_addr_0 = 0;
+ label = 7;
+ break;
+ case 7:
+ $6 = $g;
+ _acyclic($6);
+ $call = _minmax_edges2($g, $tmpcast) | 0;
+ $tobool6 = ($call | 0) == 0;
+ if ($tobool6) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _decompose($6, 0);
+ label = 9;
+ break;
+ case 9:
+ $tobool9 = ($asp_addr_0 | 0) == 0;
+ if ($tobool9) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ _rank3($6, $asp_addr_0);
+ label = 12;
+ break;
+ case 11:
+ _rank1($g);
+ label = 12;
+ break;
+ case 12:
+ _expand_ranksets($g, $asp_addr_0);
+ _cleanup1($g);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _edgelabel_ranks($g) {
+ $g = $g | 0;
+ var $has_labels = 0, $0 = 0, $and = 0, $tobool = 0, $1 = 0, $call = 0, $tobool112 = 0, $n_0_in13 = 0, $call2 = 0, $tobool410 = 0, $e_0_in11 = 0, $e_0 = 0, $minlen = 0, $2 = 0, $mul = 0, $call9 = 0, $tobool4 = 0, $call11 = 0, $tobool1 = 0, $ranksep = 0, $3 = 0, $add = 0, $div = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $has_labels = $g + 153 | 0;
+ $0 = HEAP8[$has_labels] | 0;
+ $and = $0 & 1;
+ $tobool = $and << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $g;
+ $call = _agfstnode($1) | 0;
+ $tobool112 = ($call | 0) == 0;
+ if ($tobool112) {
+ label = 7;
+ break;
+ } else {
+ $n_0_in13 = $call;
+ label = 4;
+ break;
+ }
+ case 4:
+ $call2 = _agfstout($1, $n_0_in13) | 0;
+ $tobool410 = ($call2 | 0) == 0;
+ if ($tobool410) {
+ label = 6;
+ break;
+ } else {
+ $e_0_in11 = $call2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $e_0 = $e_0_in11;
+ $minlen = $e_0 + 186 | 0;
+ $2 = HEAP16[$minlen >> 1] | 0;
+ $mul = $2 << 1;
+ HEAP16[$minlen >> 1] = $mul;
+ $call9 = _agnxtout($1, $e_0_in11) | 0;
+ $tobool4 = ($call9 | 0) == 0;
+ if ($tobool4) {
+ label = 6;
+ break;
+ } else {
+ $e_0_in11 = $call9;
+ label = 5;
+ break;
+ }
+ case 6:
+ $call11 = _agnxtnode($1, $n_0_in13) | 0;
+ $tobool1 = ($call11 | 0) == 0;
+ if ($tobool1) {
+ label = 7;
+ break;
+ } else {
+ $n_0_in13 = $call11;
+ label = 4;
+ break;
+ }
+ case 7:
+ $ranksep = $g + 264 | 0;
+ $3 = HEAP32[$ranksep >> 2] | 0;
+ $add = $3 + 1 | 0;
+ $div = ($add | 0) / 2 & -1;
+ HEAP32[$ranksep >> 2] = $div;
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _collapse_sets($rg, $g) {
+ $rg = $rg | 0;
+ $g = $g | 0;
+ var $meta_node = 0, $0 = 0, $graph = 0, $1 = 0, $2 = 0, $3 = 0, $call = 0, $tobool10 = 0, $me_0_in11 = 0, $head = 0, $4 = 0, $5 = 0, $call2 = 0, $6 = 0, $call3 = 0, $tobool4 = 0, $cmp = 0, $7 = 0, $cmp5 = 0, $or_cond = 0, $call9 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $meta_node = $g + 36 | 0;
+ $0 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $2 = $1;
+ $3 = $0;
+ $call = _agfstout($2, $3) | 0;
+ $tobool10 = ($call | 0) == 0;
+ if ($tobool10) {
+ label = 9;
+ break;
+ } else {
+ $me_0_in11 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $me_0_in11 + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ $5 = $4;
+ $call2 = _agusergraph($5) | 0;
+ $6 = $call2;
+ $call3 = _rank_set_class($6) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $cmp = ($call3 | 0) == 7;
+ $7 = HEAP32[42032] | 0;
+ $cmp5 = ($7 | 0) == 100;
+ $or_cond = $cmp & $cmp5;
+ if ($or_cond) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ _collapse_cluster($rg, $6);
+ label = 8;
+ break;
+ case 6:
+ _collapse_rankset($rg, $6, $call3);
+ label = 8;
+ break;
+ case 7:
+ _collapse_sets($rg, $6);
+ label = 8;
+ break;
+ case 8:
+ $call9 = _agnxtout($2, $me_0_in11) | 0;
+ $tobool = ($call9 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ $me_0_in11 = $call9;
+ label = 3;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _minmax_edges2($g, $slen) {
+ $g = $g | 0;
+ $slen = $slen | 0;
+ var $maxset = 0, $0 = 0, $tobool = 0, $minset = 0, $1 = 0, $tobool2 = 0, $2 = 0, $call = 0, $tobool323 = 0, $y = 0, $3 = 0, $conv = 0, $minset27 = 0, $x = 0, $4 = 0, $conv38 = 0, $n_026_in = 0, $e_025 = 0, $n_026 = 0, $5 = 0, $call4 = 0, $6 = 0, $cmp = 0, $size = 0, $7 = 0, $8 = 0, $cmp7 = 0, $9 = 0, $tobool10 = 0, $cmp14 = 0, $or_cond = 0, $10 = 0, $call18 = 0, $11 = 0, $12 = 0, $e_1 = 0, $size22 = 0, $13 = 0, $14 = 0, $cmp23 = 0, $15 = 0, $tobool28 = 0, $cmp32 = 0, $or_cond21 = 0, $16 = 0, $call37 = 0, $17 = 0, $18 = 0, $e_2 = 0, $call42 = 0, $tobool3 = 0, $e_3 = 0, $cmp44 = 0, $conv45 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $slen;
+ $slen = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ HEAP32[$slen >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$slen + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $maxset = $g + 240 | 0;
+ $0 = HEAP32[$maxset >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $minset = $g + 236 | 0;
+ $1 = HEAP32[$minset >> 2] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ if ($tobool2) {
+ $e_3 = 0;
+ label = 14;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = $g;
+ $call = _agfstnode($2) | 0;
+ $tobool323 = ($call | 0) == 0;
+ if ($tobool323) {
+ $e_3 = 0;
+ label = 14;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $y = $slen + 4 | 0;
+ $3 = HEAP32[$y >> 2] | 0;
+ $conv = $3 & 65535;
+ $minset27 = $g + 236 | 0;
+ $x = $slen | 0;
+ $4 = HEAP32[$x >> 2] | 0;
+ $conv38 = $4 & 65535;
+ $e_025 = 0;
+ $n_026_in = $call;
+ label = 6;
+ break;
+ case 6:
+ $n_026 = $n_026_in;
+ $5 = $n_026_in;
+ $call4 = _UF_find($5) | 0;
+ $6 = $call4;
+ $cmp = ($n_026_in | 0) == ($6 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ $e_2 = $e_025;
+ label = 13;
+ break;
+ }
+ case 7:
+ $size = $n_026_in + 188 | 0;
+ $7 = $size;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $cmp7 = ($8 | 0) == 0;
+ if ($cmp7) {
+ label = 8;
+ break;
+ } else {
+ $e_1 = $e_025;
+ label = 10;
+ break;
+ }
+ case 8:
+ $9 = HEAP32[$maxset >> 2] | 0;
+ $tobool10 = ($9 | 0) == 0;
+ $cmp14 = ($n_026 | 0) == ($9 | 0);
+ $or_cond = $tobool10 | $cmp14;
+ if ($or_cond) {
+ $e_1 = $e_025;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $10 = $9;
+ $call18 = _virtual_edge($5, $10, 0) | 0;
+ $11 = $call18;
+ $12 = $call18 + 186 | 0;
+ HEAP16[$12 >> 1] = $conv;
+ $e_1 = $11;
+ label = 10;
+ break;
+ case 10:
+ $size22 = $n_026_in + 180 | 0;
+ $13 = $size22;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $cmp23 = ($14 | 0) == 0;
+ if ($cmp23) {
+ label = 11;
+ break;
+ } else {
+ $e_2 = $e_1;
+ label = 13;
+ break;
+ }
+ case 11:
+ $15 = HEAP32[$minset27 >> 2] | 0;
+ $tobool28 = ($15 | 0) == 0;
+ $cmp32 = ($n_026 | 0) == ($15 | 0);
+ $or_cond21 = $tobool28 | $cmp32;
+ if ($or_cond21) {
+ $e_2 = $e_1;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $16 = $15;
+ $call37 = _virtual_edge($16, $5, 0) | 0;
+ $17 = $call37;
+ $18 = $call37 + 186 | 0;
+ HEAP16[$18 >> 1] = $conv38;
+ $e_2 = $17;
+ label = 13;
+ break;
+ case 13:
+ $call42 = _agnxtnode($2, $n_026_in) | 0;
+ $tobool3 = ($call42 | 0) == 0;
+ if ($tobool3) {
+ $e_3 = $e_2;
+ label = 14;
+ break;
+ } else {
+ $e_025 = $e_2;
+ $n_026_in = $call42;
+ label = 6;
+ break;
+ }
+ case 14:
+ $cmp44 = ($e_3 | 0) != 0;
+ $conv45 = $cmp44 & 1;
+ STACKTOP = __stackBase__;
+ return $conv45 | 0;
+ }
+ return 0;
+}
+function _expand_ranksets($g, $asp) {
+ $g = $g | 0;
+ $asp = $asp | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $minrank = 0, $maxrank = 0, $tobool4 = 0, $n_035_in = 0, $n_035 = 0, $1 = 0, $call3 = 0, $cmp = 0, $u5 = 0, $rank = 0, $2 = 0, $3 = 0, $cmp6 = 0, $4 = 0, $5 = 0, $u10 = 0, $rank11 = 0, $6 = 0, $7 = 0, $add = 0, $8 = 0, $conv = 0, $rank15 = 0, $9 = 0, $10 = 0, $cmp16 = 0, $conv21 = 0, $11 = 0, $conv27 = 0, $12 = 0, $cmp30 = 0, $conv35 = 0, $ranktype = 0, $13 = 0, $call50 = 0, $tobool2 = 0, $root = 0, $14 = 0, $cmp51 = 0, $15 = 0, $cmp54 = 0, $n_cluster = 0, $16 = 0, $cmp5829 = 0, $clust = 0, $c_030 = 0, $17 = 0, $arrayidx = 0, $18 = 0, $inc = 0, $19 = 0, $cmp58 = 0, $maxrank65 = 0, $minrank67 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 21;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $minrank = $g + 248 | 0;
+ HEAP16[$minrank >> 1] = 32767;
+ $maxrank = $g + 250 | 0;
+ HEAP16[$maxrank >> 1] = -1;
+ $tobool4 = ($asp | 0) == 0;
+ $n_035_in = $call;
+ label = 4;
+ break;
+ case 4:
+ $n_035 = $n_035_in;
+ $1 = $n_035_in;
+ $call3 = _UF_find($1) | 0;
+ $cmp = ($call3 | 0) == ($1 | 0);
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $u5 = $n_035_in + 24 | 0;
+ $rank = $u5 + 212 | 0;
+ $2 = $rank;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $cmp6 = ($3 | 0) == 0;
+ if ($cmp6) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $4 = $call3 + 236 | 0;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $u10 = $n_035_in + 24 | 0;
+ $rank11 = $u10 + 212 | 0;
+ $6 = $rank11;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $add = $7 + $5 | 0;
+ HEAP32[$6 >> 2] = $add;
+ label = 8;
+ break;
+ case 8:
+ $8 = HEAP16[$maxrank >> 1] | 0;
+ $conv = $8 << 16 >> 16;
+ $rank15 = $n_035_in + 236 | 0;
+ $9 = $rank15;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $cmp16 = ($conv | 0) < ($10 | 0);
+ if ($cmp16) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $conv21 = $10 & 65535;
+ HEAP16[$maxrank >> 1] = $conv21;
+ label = 10;
+ break;
+ case 10:
+ $11 = HEAP16[$minrank >> 1] | 0;
+ $conv27 = $11 << 16 >> 16;
+ $12 = HEAP32[$9 >> 2] | 0;
+ $cmp30 = ($conv27 | 0) > ($12 | 0);
+ if ($cmp30) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $conv35 = $12 & 65535;
+ HEAP16[$minrank >> 1] = $conv35;
+ label = 12;
+ break;
+ case 12:
+ $ranktype = $n_035 + 165 | 0;
+ $13 = HEAP8[$ranktype] | 0;
+ if (($13 << 24 >> 24 | 0) == 0 | ($13 << 24 >> 24 | 0) == 6) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _UF_singleton($1);
+ label = 14;
+ break;
+ case 14:
+ $call50 = _agnxtnode($0, $n_035_in) | 0;
+ $tobool2 = ($call50 | 0) == 0;
+ if ($tobool2) {
+ label = 15;
+ break;
+ } else {
+ $n_035_in = $call50;
+ label = 4;
+ break;
+ }
+ case 15:
+ $root = $g + 32 | 0;
+ $14 = HEAP32[$root >> 2] | 0;
+ $cmp51 = ($14 | 0) == ($g | 0);
+ if ($cmp51) {
+ label = 16;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 16:
+ $15 = HEAP32[42032] | 0;
+ $cmp54 = ($15 | 0) == 100;
+ if ($cmp54) {
+ label = 17;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 17:
+ $n_cluster = $g + 212 | 0;
+ $16 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp5829 = ($16 | 0) < 1;
+ if ($cmp5829) {
+ label = 22;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $clust = $g + 216 | 0;
+ $c_030 = 1;
+ label = 19;
+ break;
+ case 19:
+ $17 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $17 + ($c_030 << 2) | 0;
+ $18 = HEAP32[$arrayidx >> 2] | 0;
+ _set_minmax($18);
+ $inc = $c_030 + 1 | 0;
+ $19 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp58 = ($inc | 0) > ($19 | 0);
+ if ($cmp58) {
+ label = 22;
+ break;
+ } else {
+ $c_030 = $inc;
+ label = 19;
+ break;
+ }
+ case 20:
+ _find_clusters($g);
+ label = 22;
+ break;
+ case 21:
+ $maxrank65 = $g + 250 | 0;
+ HEAP16[$maxrank65 >> 1] = 0;
+ $minrank67 = $g + 248 | 0;
+ HEAP16[$minrank67 >> 1] = 0;
+ label = 22;
+ break;
+ case 22:
+ return;
+ }
+}
+function _cleanup1($g) {
+ $g = $g | 0;
+ var $comp = 0, $size = 0, $0 = 0, $cmp48 = 0, $list = 0, $nlist = 0, $c_049 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $tobool46 = 0, $n_047 = 0, $in = 0, $out = 0, $mark = 0, $next = 0, $3 = 0, $tobool = 0, $inc = 0, $4 = 0, $cmp = 0, $5 = 0, $call = 0, $tobool1543 = 0, $n_1_in44 = 0, $call17 = 0, $tobool1938 = 0, $e_042_in = 0, $to_virt = 0, $6 = 0, $7 = 0, $tobool22 = 0, $e_042 = 0, $to_orig = 0, $8 = 0, $cmp24 = 0, $call25 = 0, $tobool2735 = 0, $e1_0_in36 = 0, $cmp29 = 0, $u31 = 0, $to_virt32 = 0, $9 = 0, $10 = 0, $tobool33 = 0, $cmp35 = 0, $or_cond = 0, $call41 = 0, $tobool27 = 0, $11 = 0, $call47 = 0, $tobool19 = 0, $call50 = 0, $tobool15 = 0, $list54 = 0, $12 = 0, $13 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $comp = $g + 228 | 0;
+ $size = $g + 232 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp48 = ($0 | 0) > 0;
+ if ($cmp48) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $list = $comp | 0;
+ $nlist = $g + 220 | 0;
+ $c_049 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($c_049 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ HEAP32[$nlist >> 2] = $2;
+ $tobool46 = ($2 | 0) == 0;
+ if ($tobool46) {
+ label = 6;
+ break;
+ } else {
+ $n_047 = $2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $in = $n_047 + 176 | 0;
+ _renewlist($in);
+ $out = $n_047 + 184 | 0;
+ _renewlist($out);
+ $mark = $n_047 + 163 | 0;
+ HEAP8[$mark] = 0;
+ $next = $n_047 + 168 | 0;
+ $3 = HEAP32[$next >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $n_047 = $3;
+ label = 5;
+ break;
+ }
+ case 6:
+ $inc = $c_049 + 1 | 0;
+ $4 = HEAP32[$size >> 2] | 0;
+ $cmp = ($inc | 0) < ($4 | 0);
+ if ($cmp) {
+ $c_049 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $5 = $g;
+ $call = _agfstnode($5) | 0;
+ $tobool1543 = ($call | 0) == 0;
+ if ($tobool1543) {
+ label = 19;
+ break;
+ } else {
+ $n_1_in44 = $call;
+ label = 8;
+ break;
+ }
+ case 8:
+ $call17 = _agfstout($5, $n_1_in44) | 0;
+ $tobool1938 = ($call17 | 0) == 0;
+ if ($tobool1938) {
+ label = 18;
+ break;
+ } else {
+ $e_042_in = $call17;
+ label = 9;
+ break;
+ }
+ case 9:
+ $to_virt = $e_042_in + 188 | 0;
+ $6 = $to_virt;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $tobool22 = ($7 | 0) == 0;
+ if ($tobool22) {
+ label = 17;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $e_042 = $e_042_in;
+ $to_orig = $7 + 132 | 0;
+ $8 = HEAP32[$to_orig >> 2] | 0;
+ $cmp24 = ($e_042 | 0) == ($8 | 0);
+ if ($cmp24) {
+ label = 11;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 11:
+ $call25 = _agfstout($5, $n_1_in44) | 0;
+ $tobool2735 = ($call25 | 0) == 0;
+ if ($tobool2735) {
+ label = 16;
+ break;
+ } else {
+ $e1_0_in36 = $call25;
+ label = 12;
+ break;
+ }
+ case 12:
+ $cmp29 = ($e_042_in | 0) == ($e1_0_in36 | 0);
+ if ($cmp29) {
+ label = 15;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $u31 = $e1_0_in36 + 24 | 0;
+ $to_virt32 = $u31 + 164 | 0;
+ $9 = $to_virt32;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $tobool33 = ($10 | 0) != 0;
+ $cmp35 = ($7 | 0) == ($10 | 0);
+ $or_cond = $tobool33 & $cmp35;
+ if ($or_cond) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[$9 >> 2] = 0;
+ label = 15;
+ break;
+ case 15:
+ $call41 = _agnxtout($5, $e1_0_in36) | 0;
+ $tobool27 = ($call41 | 0) == 0;
+ if ($tobool27) {
+ label = 16;
+ break;
+ } else {
+ $e1_0_in36 = $call41;
+ label = 12;
+ break;
+ }
+ case 16:
+ $11 = $7 | 0;
+ _free($11);
+ label = 17;
+ break;
+ case 17:
+ HEAP32[$to_virt >> 2] = 0;
+ $call47 = _agnxtout($5, $e_042_in) | 0;
+ $tobool19 = ($call47 | 0) == 0;
+ if ($tobool19) {
+ label = 18;
+ break;
+ } else {
+ $e_042_in = $call47;
+ label = 9;
+ break;
+ }
+ case 18:
+ $call50 = _agnxtnode($5, $n_1_in44) | 0;
+ $tobool15 = ($call50 | 0) == 0;
+ if ($tobool15) {
+ label = 19;
+ break;
+ } else {
+ $n_1_in44 = $call50;
+ label = 8;
+ break;
+ }
+ case 19:
+ $list54 = $comp | 0;
+ $12 = HEAP32[$list54 >> 2] | 0;
+ $13 = $12;
+ _free($13);
+ HEAP32[$list54 >> 2] = 0;
+ HEAP32[$size >> 2] = 0;
+ return;
+ }
+}
+function _is_cluster($g) {
+ $g = $g | 0;
+ return (_strncmp(HEAP32[$g + 12 >> 2] | 0, 158576, 7) | 0) == 0 & 1 | 0;
+}
+function _set_minmax($g) {
+ $g = $g | 0;
+ var $leader = 0, $0 = 0, $rank = 0, $1 = 0, $minrank = 0, $2 = 0, $conv8 = 0, $add = 0, $conv3 = 0, $3 = 0, $rank7 = 0, $4 = 0, $maxrank = 0, $5 = 0, $conv99 = 0, $add10 = 0, $conv11 = 0, $n_cluster = 0, $6 = 0, $cmp10 = 0, $clust = 0, $c_011 = 0, $7 = 0, $arrayidx = 0, $8 = 0, $inc = 0, $9 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $leader = $g + 276 | 0;
+ $0 = HEAP32[$leader >> 2] | 0;
+ $rank = $0 + 236 | 0;
+ $1 = HEAP32[$rank >> 2] | 0;
+ $minrank = $g + 248 | 0;
+ $2 = HEAP16[$minrank >> 1] | 0;
+ $conv8 = $2 & 65535;
+ $add = $conv8 + $1 | 0;
+ $conv3 = $add & 65535;
+ HEAP16[$minrank >> 1] = $conv3;
+ $3 = HEAP32[$leader >> 2] | 0;
+ $rank7 = $3 + 236 | 0;
+ $4 = HEAP32[$rank7 >> 2] | 0;
+ $maxrank = $g + 250 | 0;
+ $5 = HEAP16[$maxrank >> 1] | 0;
+ $conv99 = $5 & 65535;
+ $add10 = $conv99 + $4 | 0;
+ $conv11 = $add10 & 65535;
+ HEAP16[$maxrank >> 1] = $conv11;
+ $n_cluster = $g + 212 | 0;
+ $6 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp10 = ($6 | 0) < 1;
+ if ($cmp10) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $clust = $g + 216 | 0;
+ $c_011 = 1;
+ label = 4;
+ break;
+ case 4:
+ $7 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $7 + ($c_011 << 2) | 0;
+ $8 = HEAP32[$arrayidx >> 2] | 0;
+ _set_minmax($8);
+ $inc = $c_011 + 1 | 0;
+ $9 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($inc | 0) > ($9 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $c_011 = $inc;
+ label = 4;
+ break;
+ }
+ case 5:
+ return;
+ }
+}
+function _find_clusters($g) {
+ $g = $g | 0;
+ var $meta_node = 0, $0 = 0, $graph = 0, $1 = 0, $2 = 0, $3 = 0, $call = 0, $tobool7 = 0, $me_0_in8 = 0, $head = 0, $4 = 0, $5 = 0, $call2 = 0, $u = 0, $6 = 0, $set_type = 0, $7 = 0, $cmp = 0, $8 = 0, $call4 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $meta_node = $g + 36 | 0;
+ $0 = HEAP32[$meta_node >> 2] | 0;
+ $graph = $0 + 20 | 0;
+ $1 = HEAP32[$graph >> 2] | 0;
+ $2 = $1;
+ $3 = $0;
+ $call = _agfstout($2, $3) | 0;
+ $tobool7 = ($call | 0) == 0;
+ if ($tobool7) {
+ label = 6;
+ break;
+ } else {
+ $me_0_in8 = $call;
+ label = 3;
+ break;
+ }
+ case 3:
+ $head = $me_0_in8 + 12 | 0;
+ $4 = HEAP32[$head >> 2] | 0;
+ $5 = $4;
+ $call2 = _agusergraph($5) | 0;
+ $u = $call2 + 48 | 0;
+ $6 = $u;
+ $set_type = $6 + 238 | 0;
+ $7 = HEAP8[$set_type] | 0;
+ $cmp = $7 << 24 >> 24 == 7;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $8 = $call2;
+ _collapse_cluster($g, $8);
+ label = 5;
+ break;
+ case 5:
+ $call4 = _agnxtout($2, $me_0_in8) | 0;
+ $tobool = ($call4 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $me_0_in8 = $call4;
+ label = 3;
+ break;
+ }
+ case 6:
+ return;
+ }
+}
+function _collapse_cluster($g, $subg) {
+ $g = $g | 0;
+ $subg = $subg | 0;
+ var $cluster_was_collapsed = 0, $0 = 0, $tobool = 0, $1 = 0, $call = 0, $cmp = 0, $2 = 0, $cmp6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cluster_was_collapsed = $subg + 254 | 0;
+ $0 = HEAP8[$cluster_was_collapsed] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ HEAP8[$cluster_was_collapsed] = 1;
+ _node_induce($g, $subg);
+ $1 = $subg;
+ $call = _agfstnode($1) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _make_new_cluster($g, $subg);
+ $2 = HEAP32[42032] | 0;
+ $cmp6 = ($2 | 0) == 100;
+ if ($cmp6) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ _dot_rank($subg, 0);
+ _cluster_leader($subg);
+ label = 7;
+ break;
+ case 6:
+ _dot_scan_ranks($subg);
+ label = 7;
+ break;
+ case 7:
+ return;
+ }
+}
+function _minmax_edges($agg_result, $g) {
+ $agg_result = $agg_result | 0;
+ $g = $g | 0;
+ var $maxset = 0, $0 = 0, $cmp = 0, $minset = 0, $1 = 0, $cmp2 = 0, $slen_sroa_0_0__idx1 = 0, $slen_sroa_1_4__idx4 = 0, $minset4 = 0, $2 = 0, $cmp5 = 0, $3 = 0, $call = 0, $4 = 0, $5 = 0, $cmp14 = 0, $6 = 0, $call18 = 0, $7 = 0, $tobool = 0, $8 = 0, $9 = 0, $cmp28 = 0, $conv29 = 0, $list = 0, $10 = 0, $11 = 0, $12 = 0, $tobool3225 = 0, $13 = 0, $head = 0, $14 = 0, $15 = 0, $call34 = 0, $16 = 0, $cmp35 = 0, $17 = 0, $18 = 0, $19 = 0, $tobool32 = 0, $slen_sroa_1_0 = 0, $20 = 0, $tobool40 = 0, $ranktype45 = 0, $21 = 0, $cmp47 = 0, $conv48 = 0, $list52 = 0, $22 = 0, $23 = 0, $tobool5424 = 0, $24 = 0, $tail = 0, $25 = 0, $26 = 0, $call57 = 0, $27 = 0, $cmp58 = 0, $28 = 0, $29 = 0, $30 = 0, $tobool54 = 0, $slen_sroa_0_0 = 0, $slen_sroa_0_0__idx = 0, $slen_sroa_1_4__idx3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $maxset = $g + 240 | 0;
+ $0 = HEAP32[$maxset >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $minset = $g + 236 | 0;
+ $1 = HEAP32[$minset >> 2] | 0;
+ $cmp2 = ($1 | 0) == 0;
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $slen_sroa_0_0__idx1 = $agg_result | 0;
+ HEAP32[$slen_sroa_0_0__idx1 >> 2] = 0;
+ $slen_sroa_1_4__idx4 = $agg_result + 4 | 0;
+ HEAP32[$slen_sroa_1_4__idx4 >> 2] = 0;
+ label = 19;
+ break;
+ case 5:
+ $minset4 = $g + 236 | 0;
+ $2 = HEAP32[$minset4 >> 2] | 0;
+ $cmp5 = ($2 | 0) == 0;
+ if ($cmp5) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = $2;
+ $call = _UF_find($3) | 0;
+ $4 = $call;
+ HEAP32[$minset4 >> 2] = $4;
+ label = 7;
+ break;
+ case 7:
+ $5 = HEAP32[$maxset >> 2] | 0;
+ $cmp14 = ($5 | 0) == 0;
+ if ($cmp14) {
+ $slen_sroa_1_0 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $6 = $5;
+ $call18 = _UF_find($6) | 0;
+ $7 = $call18;
+ HEAP32[$maxset >> 2] = $7;
+ $tobool = ($call18 | 0) == 0;
+ if ($tobool) {
+ $slen_sroa_1_0 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $8 = $call18 + 165 | 0;
+ $9 = HEAP8[$8] | 0;
+ $cmp28 = $9 << 24 >> 24 == 5;
+ $conv29 = $cmp28 & 1;
+ $list = $call18 + 184 | 0;
+ $10 = $list;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $tobool3225 = ($12 | 0) == 0;
+ if ($tobool3225) {
+ $slen_sroa_1_0 = $conv29;
+ label = 13;
+ break;
+ } else {
+ $13 = $12;
+ label = 10;
+ break;
+ }
+ case 10:
+ $head = $13 + 12 | 0;
+ $14 = HEAP32[$head >> 2] | 0;
+ $15 = $14;
+ $call34 = _UF_find($15) | 0;
+ $16 = $call34;
+ $cmp35 = ($14 | 0) == ($16 | 0);
+ if ($cmp35) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ ___assert_func(129880, 363, 163984, 108280);
+ case 12:
+ $17 = $13;
+ _reverse_edge($17);
+ $18 = HEAP32[$10 >> 2] | 0;
+ $19 = HEAP32[$18 >> 2] | 0;
+ $tobool32 = ($19 | 0) == 0;
+ if ($tobool32) {
+ $slen_sroa_1_0 = $conv29;
+ label = 13;
+ break;
+ } else {
+ $13 = $19;
+ label = 10;
+ break;
+ }
+ case 13:
+ $20 = HEAP32[$minset4 >> 2] | 0;
+ $tobool40 = ($20 | 0) == 0;
+ if ($tobool40) {
+ $slen_sroa_0_0 = 0;
+ label = 18;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $ranktype45 = $20 + 165 | 0;
+ $21 = HEAP8[$ranktype45] | 0;
+ $cmp47 = $21 << 24 >> 24 == 3;
+ $conv48 = $cmp47 & 1;
+ $list52 = $20 + 176 | 0;
+ $22 = HEAP32[$list52 >> 2] | 0;
+ $23 = HEAP32[$22 >> 2] | 0;
+ $tobool5424 = ($23 | 0) == 0;
+ if ($tobool5424) {
+ $slen_sroa_0_0 = $conv48;
+ label = 18;
+ break;
+ } else {
+ $24 = $23;
+ label = 15;
+ break;
+ }
+ case 15:
+ $tail = $24 + 16 | 0;
+ $25 = HEAP32[$tail >> 2] | 0;
+ $26 = $25;
+ $call57 = _UF_find($26) | 0;
+ $27 = $call57;
+ $cmp58 = ($25 | 0) == ($27 | 0);
+ if ($cmp58) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ ___assert_func(129880, 370, 163984, 104400);
+ case 17:
+ $28 = $24;
+ _reverse_edge($28);
+ $29 = HEAP32[$list52 >> 2] | 0;
+ $30 = HEAP32[$29 >> 2] | 0;
+ $tobool54 = ($30 | 0) == 0;
+ if ($tobool54) {
+ $slen_sroa_0_0 = $conv48;
+ label = 18;
+ break;
+ } else {
+ $24 = $30;
+ label = 15;
+ break;
+ }
+ case 18:
+ $slen_sroa_0_0__idx = $agg_result | 0;
+ HEAP32[$slen_sroa_0_0__idx >> 2] = $slen_sroa_0_0;
+ $slen_sroa_1_4__idx3 = $agg_result + 4 | 0;
+ HEAP32[$slen_sroa_1_4__idx3 >> 2] = $slen_sroa_1_0;
+ label = 19;
+ break;
+ case 19:
+ return;
+ }
+}
+function _node_induce($par, $g) {
+ $par = $par | 0;
+ $g = $g | 0;
+ var $0 = 0, $call = 0, $tobool30 = 0, $1 = 0, $clust = 0, $n_cluster = 0, $2 = 0, $n_0_in31 = 0, $call1 = 0, $u = 0, $3 = 0, $4 = 0, $tobool2 = 0, $5 = 0, $i_0 = 0, $6 = 0, $cmp = 0, $7 = 0, $arrayidx = 0, $8 = 0, $9 = 0, $call7 = 0, $tobool8 = 0, $inc = 0, $10 = 0, $cmp13 = 0, $11 = 0, $clust17 = 0, $12 = 0, $tobool = 0, $call20 = 0, $tobool2227 = 0, $root = 0, $13 = 0, $n_1_in28 = 0, $14 = 0, $15 = 0, $call24 = 0, $tobool2625 = 0, $e_0_in26 = 0, $head = 0, $16 = 0, $17 = 0, $call28 = 0, $tobool29 = 0, $18 = 0, $19 = 0, $20 = 0, $call34 = 0, $tobool26 = 0, $call37 = 0, $tobool22 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $g;
+ $call = _agfstnode($0) | 0;
+ $tobool30 = ($call | 0) == 0;
+ if ($tobool30) {
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = $g;
+ $clust = $par + 216 | 0;
+ $n_cluster = $par + 212 | 0;
+ $2 = $g;
+ $n_0_in31 = $call;
+ label = 4;
+ break;
+ case 4:
+ $call1 = _agnxtnode($0, $n_0_in31) | 0;
+ $u = $n_0_in31 + 24 | 0;
+ $3 = $u + 141 | 0;
+ $4 = HEAP8[$3] | 0;
+ $tobool2 = $4 << 24 >> 24 == 0;
+ $5 = $n_0_in31 | 0;
+ if ($tobool2) {
+ $i_0 = 1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ _agdelete($1, $5);
+ label = 11;
+ break;
+ case 6:
+ $6 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp = ($i_0 | 0) < ($6 | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $7 = HEAP32[$clust >> 2] | 0;
+ $arrayidx = $7 + ($i_0 << 2) | 0;
+ $8 = HEAP32[$arrayidx >> 2] | 0;
+ $9 = $8;
+ $call7 = _agcontains($9, $5) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ $inc = $i_0 + 1 | 0;
+ if ($tobool8) {
+ $i_0 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $10 = HEAP32[$n_cluster >> 2] | 0;
+ $cmp13 = ($i_0 | 0) < ($10 | 0);
+ if ($cmp13) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $11 = $n_0_in31 | 0;
+ _agdelete($2, $11);
+ label = 10;
+ break;
+ case 10:
+ $clust17 = $u + 192 | 0;
+ $12 = $clust17;
+ HEAP32[$12 >> 2] = 0;
+ label = 11;
+ break;
+ case 11:
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ $n_0_in31 = $call1;
+ label = 4;
+ break;
+ }
+ case 12:
+ $call20 = _agfstnode($0) | 0;
+ $tobool2227 = ($call20 | 0) == 0;
+ if ($tobool2227) {
+ label = 19;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $root = $g + 32 | 0;
+ $13 = $g;
+ $n_1_in28 = $call20;
+ label = 14;
+ break;
+ case 14:
+ $14 = HEAP32[$root >> 2] | 0;
+ $15 = $14;
+ $call24 = _agfstout($15, $n_1_in28) | 0;
+ $tobool2625 = ($call24 | 0) == 0;
+ if ($tobool2625) {
+ label = 18;
+ break;
+ } else {
+ $e_0_in26 = $call24;
+ label = 15;
+ break;
+ }
+ case 15:
+ $head = $e_0_in26 + 12 | 0;
+ $16 = HEAP32[$head >> 2] | 0;
+ $17 = $16 | 0;
+ $call28 = _agcontains($13, $17) | 0;
+ $tobool29 = ($call28 | 0) == 0;
+ if ($tobool29) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $18 = $e_0_in26 | 0;
+ _aginsert($13, $18);
+ label = 17;
+ break;
+ case 17:
+ $19 = HEAP32[$root >> 2] | 0;
+ $20 = $19;
+ $call34 = _agnxtout($20, $e_0_in26) | 0;
+ $tobool26 = ($call34 | 0) == 0;
+ if ($tobool26) {
+ label = 18;
+ break;
+ } else {
+ $e_0_in26 = $call34;
+ label = 15;
+ break;
+ }
+ case 18:
+ $call37 = _agnxtnode($0, $n_1_in28) | 0;
+ $tobool22 = ($call37 | 0) == 0;
+ if ($tobool22) {
+ label = 19;
+ break;
+ } else {
+ $n_1_in28 = $call37;
+ label = 14;
+ break;
+ }
+ case 19:
+ return;
+ }
+}
+function _make_new_cluster($g, $subg) {
+ $g = $g | 0;
+ $subg = $subg | 0;
+ var $n_cluster = 0, $0 = 0, $inc = 0, $clust = 0, $1 = 0, $tobool = 0, $2 = 0, $add = 0, $call = 0, $add6 = 0, $mul = 0, $call7 = 0, $call_sink = 0, $3 = 0, $arrayidx = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $n_cluster = $g + 212 | 0;
+ $0 = HEAP32[$n_cluster >> 2] | 0;
+ $inc = $0 + 1 | 0;
+ HEAP32[$n_cluster >> 2] = $inc;
+ $clust = $g + 216 | 0;
+ $1 = HEAP32[$clust >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $1;
+ $add = $0 + 2 | 0;
+ $call = _zrealloc($2, $add, 4, $inc) | 0;
+ $call_sink = $call;
+ label = 5;
+ break;
+ case 4:
+ $add6 = $0 << 2;
+ $mul = $add6 + 8 | 0;
+ $call7 = _zmalloc($mul) | 0;
+ $call_sink = $call7;
+ label = 5;
+ break;
+ case 5:
+ $3 = $call_sink;
+ HEAP32[$clust >> 2] = $3;
+ $arrayidx = $3 + ($inc << 2) | 0;
+ HEAP32[$arrayidx >> 2] = $subg;
+ $4 = $subg;
+ _do_graph_label($4);
+ return;
+ }
+}
+function _rank_set_class($g) {
+ $g = $g | 0;
+ var $call = 0, $tobool = 0, $0 = 0, $call1 = 0, $call2 = 0, $conv = 0, $set_type = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _is_cluster($g) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 7;
+ label = 4;
+ break;
+ }
+ case 3:
+ $0 = $g | 0;
+ $call1 = _agget($0, 155664) | 0;
+ $call2 = _maptoken($call1, 4672, 4696) | 0;
+ $conv = $call2 & 255;
+ $set_type = $g + 286 | 0;
+ HEAP8[$set_type] = $conv;
+ $retval_0 = $call2;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _collapse_rankset($g, $subg, $kind) {
+ $g = $g | 0;
+ $subg = $subg | 0;
+ $kind = $kind | 0;
+ var $0 = 0, $call = 0, $1 = 0, $tobool = 0, $conv = 0, $u1 = 0, $2 = 0, $call224 = 0, $tobool325 = 0, $3 = 0, $call226 = 0, $4 = 0, $call4 = 0, $5 = 0, $u7 = 0, $6 = 0, $call2 = 0, $tobool3 = 0, $minset = 0, $7 = 0, $cmp = 0, $8 = 0, $9 = 0, $call16 = 0, $10 = 0, $maxset = 0, $11 = 0, $cmp21 = 0, $12 = 0, $13 = 0, $call29 = 0, $14 = 0, $minset36 = 0, $15 = 0, $ranktype38 = 0, $maxset42 = 0, $16 = 0, $ranktype44 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $subg;
+ $call = _agfstnode($0) | 0;
+ $1 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 16;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $kind & 255;
+ $u1 = $call + 24 | 0;
+ $2 = $u1 + 141 | 0;
+ HEAP8[$2] = $conv;
+ $call224 = _agnxtnode($0, $call) | 0;
+ $tobool325 = ($call224 | 0) == 0;
+ if ($tobool325) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = $call;
+ $call226 = $call224;
+ label = 5;
+ break;
+ case 5:
+ $4 = $call226;
+ $call4 = _UF_union($3, $4) | 0;
+ $5 = HEAP8[$2] | 0;
+ $u7 = $call226 + 24 | 0;
+ $6 = $u7 + 141 | 0;
+ HEAP8[$6] = $5;
+ $call2 = _agnxtnode($0, $call226) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ label = 6;
+ break;
+ } else {
+ $call226 = $call2;
+ label = 5;
+ break;
+ }
+ case 6:
+ if (($kind | 0) == 2 | ($kind | 0) == 3) {
+ label = 7;
+ break;
+ } else if (($kind | 0) == 4 | ($kind | 0) == 5) {
+ label = 10;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 7:
+ $minset = $g + 236 | 0;
+ $7 = HEAP32[$minset >> 2] | 0;
+ $cmp = ($7 | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ HEAP32[$minset >> 2] = $1;
+ label = 13;
+ break;
+ case 9:
+ $8 = $7;
+ $9 = $call;
+ $call16 = _UF_union($8, $9) | 0;
+ $10 = $call16;
+ HEAP32[$minset >> 2] = $10;
+ label = 13;
+ break;
+ case 10:
+ $maxset = $g + 240 | 0;
+ $11 = HEAP32[$maxset >> 2] | 0;
+ $cmp21 = ($11 | 0) == 0;
+ if ($cmp21) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ HEAP32[$maxset >> 2] = $1;
+ label = 13;
+ break;
+ case 12:
+ $12 = $11;
+ $13 = $call;
+ $call29 = _UF_union($12, $13) | 0;
+ $14 = $call29;
+ HEAP32[$maxset >> 2] = $14;
+ label = 13;
+ break;
+ case 13:
+ if (($kind | 0) == 3) {
+ label = 14;
+ break;
+ } else if (($kind | 0) == 5) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 14:
+ $minset36 = $g + 236 | 0;
+ $15 = HEAP32[$minset36 >> 2] | 0;
+ $ranktype38 = $15 + 165 | 0;
+ HEAP8[$ranktype38] = $conv;
+ label = 16;
+ break;
+ case 15:
+ $maxset42 = $g + 240 | 0;
+ $16 = HEAP32[$maxset42 >> 2] | 0;
+ $ranktype44 = $16 + 165 | 0;
+ HEAP8[$ranktype44] = $conv;
+ label = 16;
+ break;
+ case 16:
+ return;
+ }
+}
+function _dot_sameports($g) {
+ $g = $g | 0;
+ var $same = 0, $proto = 0, $0 = 0, $e1 = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $e3 = 0, $4 = 0, $5 = 0, $call4 = 0, $6 = 0, $tobool = 0, $tobool5 = 0, $or_cond = 0, $7 = 0, $call6 = 0, $tobool738 = 0, $arraydecay = 0, $arraydecay28 = 0, $n_041_in = 0, $n_041 = 0, $call8 = 0, $tobool1031 = 0, $e_034_in = 0, $e_034 = 0, $head = 0, $8 = 0, $cmp = 0, $9 = 0, $tobool12 = 0, $or_cond1 = 0, $10 = 0, $index = 0, $11 = 0, $call14 = 0, $12 = 0, $tobool15 = 0, $tail = 0, $13 = 0, $cmp17 = 0, $14 = 0, $tobool20 = 0, $or_cond2 = 0, $15 = 0, $index22 = 0, $16 = 0, $call23 = 0, $17 = 0, $tobool26 = 0, $call31 = 0, $tobool10 = 0, $18 = 0, $cmp3335 = 0, $i_036 = 0, $l = 0, $size = 0, $19 = 0, $cmp37 = 0, $list = 0, $20 = 0, $tobool46 = 0, $21 = 0, $inc = 0, $22 = 0, $cmp33 = 0, $call55 = 0, $tobool7 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 120 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $same = __stackBase__ | 0;
+ $proto = $g + 40 | 0;
+ $0 = HEAP32[$proto >> 2] | 0;
+ $e1 = $0 + 4 | 0;
+ $1 = HEAP32[$e1 >> 2] | 0;
+ $2 = $1 | 0;
+ $call = _agfindattr($2, 145936) | 0;
+ HEAP32[41914] = $call;
+ $3 = HEAP32[$proto >> 2] | 0;
+ $e3 = $3 + 4 | 0;
+ $4 = HEAP32[$e3 >> 2] | 0;
+ $5 = $4 | 0;
+ $call4 = _agfindattr($5, 157696) | 0;
+ HEAP32[41912] = $call4;
+ $6 = HEAP32[41914] | 0;
+ $tobool = ($6 | 0) != 0;
+ $tobool5 = ($call4 | 0) != 0;
+ $or_cond = $tobool | $tobool5;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 3:
+ $7 = $g;
+ $call6 = _agfstnode($7) | 0;
+ $tobool738 = ($call6 | 0) == 0;
+ if ($tobool738) {
+ label = 20;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $arraydecay = $same | 0;
+ $arraydecay28 = $same | 0;
+ $n_041_in = $call6;
+ label = 5;
+ break;
+ case 5:
+ $n_041 = $n_041_in;
+ HEAP32[2770] = 0;
+ $call8 = _agfstedge($7, $n_041_in) | 0;
+ $tobool1031 = ($call8 | 0) == 0;
+ if ($tobool1031) {
+ label = 13;
+ break;
+ } else {
+ $e_034_in = $call8;
+ label = 6;
+ break;
+ }
+ case 6:
+ $e_034 = $e_034_in;
+ $head = $e_034_in + 12 | 0;
+ $8 = HEAP32[$head >> 2] | 0;
+ $cmp = ($8 | 0) == ($n_041_in | 0);
+ $9 = HEAP32[41914] | 0;
+ $tobool12 = ($9 | 0) != 0;
+ $or_cond1 = $cmp & $tobool12;
+ if ($or_cond1) {
+ label = 7;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 7:
+ $10 = $e_034_in | 0;
+ $index = $9 + 8 | 0;
+ $11 = HEAP32[$index >> 2] | 0;
+ $call14 = _agxget($10, $11) | 0;
+ $12 = HEAP8[$call14] | 0;
+ $tobool15 = $12 << 24 >> 24 == 0;
+ if ($tobool15) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ _sameedge($arraydecay, $n_041, $e_034, $call14);
+ label = 12;
+ break;
+ case 9:
+ $tail = $e_034_in + 16 | 0;
+ $13 = HEAP32[$tail >> 2] | 0;
+ $cmp17 = ($13 | 0) == ($n_041_in | 0);
+ $14 = HEAP32[41912] | 0;
+ $tobool20 = ($14 | 0) != 0;
+ $or_cond2 = $cmp17 & $tobool20;
+ if ($or_cond2) {
+ label = 10;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 10:
+ $15 = $e_034_in | 0;
+ $index22 = $14 + 8 | 0;
+ $16 = HEAP32[$index22 >> 2] | 0;
+ $call23 = _agxget($15, $16) | 0;
+ $17 = HEAP8[$call23] | 0;
+ $tobool26 = $17 << 24 >> 24 == 0;
+ if ($tobool26) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ _sameedge($arraydecay28, $n_041, $e_034, $call23);
+ label = 12;
+ break;
+ case 12:
+ $call31 = _agnxtedge($7, $e_034_in, $n_041_in) | 0;
+ $tobool10 = ($call31 | 0) == 0;
+ if ($tobool10) {
+ label = 13;
+ break;
+ } else {
+ $e_034_in = $call31;
+ label = 6;
+ break;
+ }
+ case 13:
+ $18 = HEAP32[2770] | 0;
+ $cmp3335 = ($18 | 0) > 0;
+ if ($cmp3335) {
+ $i_036 = 0;
+ label = 14;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 14:
+ $l = $same + ($i_036 * 24 & -1) + 4 | 0;
+ $size = $same + ($i_036 * 24 & -1) + 8 | 0;
+ $19 = HEAP32[$size >> 2] | 0;
+ $cmp37 = ($19 | 0) > 1;
+ if ($cmp37) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ _sameport($n_041, $l);
+ label = 16;
+ break;
+ case 16:
+ $list = $l | 0;
+ $20 = HEAP32[$list >> 2] | 0;
+ $tobool46 = ($20 | 0) == 0;
+ if ($tobool46) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $21 = $20;
+ _free($21);
+ label = 18;
+ break;
+ case 18:
+ $inc = $i_036 + 1 | 0;
+ $22 = HEAP32[2770] | 0;
+ $cmp33 = ($inc | 0) < ($22 | 0);
+ if ($cmp33) {
+ $i_036 = $inc;
+ label = 14;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $call55 = _agnxtnode($7, $n_041_in) | 0;
+ $tobool7 = ($call55 | 0) == 0;
+ if ($tobool7) {
+ label = 20;
+ break;
+ } else {
+ $n_041_in = $call55;
+ label = 5;
+ break;
+ }
+ case 20:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _sameedge($same, $n, $e, $id) {
+ $same = $same | 0;
+ $n = $n | 0;
+ $e = $e | 0;
+ $id = $id | 0;
+ var $sflag = 0, $eflag = 0, $0 = 0, $cmp53 = 0, $1 = 0, $2 = 0, $i_054 = 0, $id1 = 0, $3 = 0, $4 = 0, $cmp3 = 0, $call = 0, $tobool = 0, $list = 0, $5 = 0, $tobool8 = 0, $6 = 0, $size = 0, $7 = 0, $add = 0, $mul = 0, $call14 = 0, $size17 = 0, $8 = 0, $add18 = 0, $mul19 = 0, $call20 = 0, $call14_sink = 0, $9 = 0, $size26 = 0, $10 = 0, $inc = 0, $11 = 0, $arrayidx30 = 0, $12 = 0, $13 = 0, $arrayidx37 = 0, $inc38 = 0, $cmp = 0, $_lcssa = 0, $i_0_lcssa = 0, $inc39 = 0, $cmp40 = 0, $name = 0, $14 = 0, $call43 = 0, $size48 = 0, $call49 = 0, $15 = 0, $list52 = 0, $16 = 0, $inc58 = 0, $17 = 0, $arrayidx62 = 0, $18 = 0, $19 = 0, $arrayidx69 = 0, $id72 = 0, $n_arr = 0, $arr_len = 0, $i_051 = 0, $20 = 0, $head = 0, $21 = 0, $cmp75 = 0, $22 = 0, $23 = 0, $cond80 = 0, $tobool81 = 0, $n_arr84 = 0, $24 = 0, $inc85 = 0, $cmp86 = 0, $call89 = 0.0, $cond92 = 0.0, $arr_len94 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sflag = __stackBase__ | 0;
+ $eflag = __stackBase__ + 8 | 0;
+ $0 = HEAP32[2770] | 0;
+ $cmp53 = ($0 | 0) > 0;
+ if ($cmp53) {
+ label = 3;
+ break;
+ } else {
+ $i_0_lcssa = 0;
+ $_lcssa = $0;
+ label = 11;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$id] | 0;
+ $2 = HEAP32[2770] | 0;
+ $i_054 = 0;
+ label = 4;
+ break;
+ case 4:
+ $id1 = $same + ($i_054 * 24 & -1) | 0;
+ $3 = HEAP32[$id1 >> 2] | 0;
+ $4 = HEAP8[$3] | 0;
+ $cmp3 = $4 << 24 >> 24 == $1 << 24 >> 24;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 5:
+ $call = _strcmp($3 | 0, $id | 0) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 6:
+ $list = $same + ($i_054 * 24 & -1) + 4 | 0;
+ $5 = HEAP32[$list >> 2] | 0;
+ $tobool8 = ($5 | 0) == 0;
+ if ($tobool8) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $6 = $5;
+ $size = $same + ($i_054 * 24 & -1) + 8 | 0;
+ $7 = HEAP32[$size >> 2] | 0;
+ $add = $7 << 2;
+ $mul = $add + 8 | 0;
+ $call14 = _grealloc($6, $mul) | 0;
+ $call14_sink = $call14;
+ label = 9;
+ break;
+ case 8:
+ $size17 = $same + ($i_054 * 24 & -1) + 8 | 0;
+ $8 = HEAP32[$size17 >> 2] | 0;
+ $add18 = $8 << 2;
+ $mul19 = $add18 + 8 | 0;
+ $call20 = _gmalloc($mul19) | 0;
+ $call14_sink = $call20;
+ label = 9;
+ break;
+ case 9:
+ $9 = $call14_sink;
+ HEAP32[$list >> 2] = $9;
+ $size26 = $same + ($i_054 * 24 & -1) + 8 | 0;
+ $10 = HEAP32[$size26 >> 2] | 0;
+ $inc = $10 + 1 | 0;
+ HEAP32[$size26 >> 2] = $inc;
+ $11 = HEAP32[$list >> 2] | 0;
+ $arrayidx30 = $11 + ($10 << 2) | 0;
+ HEAP32[$arrayidx30 >> 2] = $e;
+ $12 = HEAP32[$size26 >> 2] | 0;
+ $13 = HEAP32[$list >> 2] | 0;
+ $arrayidx37 = $13 + ($12 << 2) | 0;
+ HEAP32[$arrayidx37 >> 2] = 0;
+ $i_051 = $i_054;
+ label = 14;
+ break;
+ case 10:
+ $inc38 = $i_054 + 1 | 0;
+ $cmp = ($inc38 | 0) < ($2 | 0);
+ if ($cmp) {
+ $i_054 = $inc38;
+ label = 4;
+ break;
+ } else {
+ $i_0_lcssa = $inc38;
+ $_lcssa = $2;
+ label = 11;
+ break;
+ }
+ case 11:
+ $inc39 = $_lcssa + 1 | 0;
+ HEAP32[2770] = $inc39;
+ $cmp40 = ($inc39 | 0) > 5;
+ if ($cmp40) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $name = $n + 12 | 0;
+ $14 = HEAP32[$name >> 2] | 0;
+ $call43 = _agerr(1, 129424, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $14, tempInt) | 0) | 0;
+ label = 18;
+ break;
+ case 13:
+ $size48 = $same + ($i_0_lcssa * 24 & -1) + 8 | 0;
+ HEAP32[$size48 >> 2] = 0;
+ $call49 = _zmalloc(8) | 0;
+ $15 = $call49;
+ $list52 = $same + ($i_0_lcssa * 24 & -1) + 4 | 0;
+ HEAP32[$list52 >> 2] = $15;
+ $16 = HEAP32[$size48 >> 2] | 0;
+ $inc58 = $16 + 1 | 0;
+ HEAP32[$size48 >> 2] = $inc58;
+ $17 = HEAP32[$list52 >> 2] | 0;
+ $arrayidx62 = $17 + ($16 << 2) | 0;
+ HEAP32[$arrayidx62 >> 2] = $e;
+ $18 = HEAP32[$size48 >> 2] | 0;
+ $19 = HEAP32[$list52 >> 2] | 0;
+ $arrayidx69 = $19 + ($18 << 2) | 0;
+ HEAP32[$arrayidx69 >> 2] = 0;
+ $id72 = $same + ($i_0_lcssa * 24 & -1) | 0;
+ HEAP32[$id72 >> 2] = $id;
+ $n_arr = $same + ($i_0_lcssa * 24 & -1) + 12 | 0;
+ HEAP32[$n_arr >> 2] = 0;
+ $arr_len = $same + ($i_0_lcssa * 24 & -1) + 16 | 0;
+ HEAPF64[$arr_len >> 3] = 0.0;
+ $i_051 = $i_0_lcssa;
+ label = 14;
+ break;
+ case 14:
+ $20 = $e;
+ _arrow_flags($20, $sflag, $eflag);
+ $head = $e + 12 | 0;
+ $21 = HEAP32[$head >> 2] | 0;
+ $cmp75 = ($21 | 0) == ($n | 0);
+ $22 = HEAP32[$eflag >> 2] | 0;
+ $23 = HEAP32[$sflag >> 2] | 0;
+ $cond80 = $cmp75 ? $22 : $23;
+ $tobool81 = ($cond80 | 0) == 0;
+ if ($tobool81) {
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $n_arr84 = $same + ($i_051 * 24 & -1) + 12 | 0;
+ $24 = HEAP32[$n_arr84 >> 2] | 0;
+ $inc85 = $24 + 1 | 0;
+ HEAP32[$n_arr84 >> 2] = $inc85;
+ $cmp86 = ($24 | 0) == 0;
+ if ($cmp86) {
+ label = 16;
+ break;
+ } else {
+ $cond92 = 0.0;
+ label = 17;
+ break;
+ }
+ case 16:
+ $call89 = +_arrow_length($20, $cond80);
+ $cond92 = $call89;
+ label = 17;
+ break;
+ case 17:
+ $arr_len94 = $same + ($i_051 * 24 & -1) + 16 | 0;
+ HEAPF64[$arr_len94 >> 3] = $cond92;
+ label = 18;
+ break;
+ case 18:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _sameport($u, $l) {
+ $u = $u | 0;
+ $l = $l | 0;
+ var $sflag = 0, $eflag = 0, $curve = 0, $size = 0, $0 = 0, $cmp16 = 0, $list = 0, $x7 = 0, $y13 = 0, $i_019 = 0, $x_018 = 0.0, $y_017 = 0.0, $1 = 0, $arrayidx = 0, $2 = 0, $head = 0, $3 = 0, $cmp1 = 0, $tail = 0, $4 = 0, $v_0 = 0, $x4 = 0, $5 = 0.0, $6 = 0.0, $sub = 0.0, $y10 = 0, $7 = 0.0, $8 = 0.0, $sub14 = 0.0, $call = 0.0, $div = 0.0, $add = 0.0, $div15 = 0.0, $add16 = 0.0, $inc = 0, $9 = 0, $cmp = 0, $x_0_lcssa = 0.0, $y_0_lcssa = 0.0, $call17 = 0.0, $div18 = 0.0, $div19 = 0.0, $x22 = 0, $10 = 0.0, $y25 = 0, $11 = 0.0, $lw = 0, $12 = 0.0, $rw = 0, $13 = 0.0, $add28 = 0.0, $ht = 0, $14 = 0.0, $graph = 0, $15 = 0, $ranksep = 0, $16 = 0, $conv = 0.0, $add31 = 0.0, $cmp32 = 0, $add28_add31 = 0.0, $mul = 0.0, $add49 = 0.0, $mul50 = 0.0, $add54 = 0.0, $arrayidx55 = 0, $x56 = 0, $y58 = 0, $mul59 = 0.0, $add60 = 0.0, $div61 = 0.0, $x63 = 0, $mul64 = 0.0, $add65 = 0.0, $div66 = 0.0, $y68 = 0, $mul69 = 0.0, $add70 = 0.0, $div71 = 0.0, $x73 = 0, $mul74 = 0.0, $add75 = 0.0, $div76 = 0.0, $y78 = 0, $x80 = 0, $y82 = 0, $17 = 0, $18 = 0.0, $19 = 0.0, $sub88 = 0.0, $20 = 0.0, $21 = 0.0, $sub94 = 0.0, $cmp95 = 0, $add98 = 0.0, $sub101 = 0.0, $add98_sink = 0.0, $conv99 = 0, $conv105 = 0.0, $cmp107 = 0, $add110 = 0.0, $sub113 = 0.0, $add110_sink = 0.0, $conv111 = 0, $conv117 = 0.0, $22 = 0.0, $add124 = 0.0, $mul125 = 0.0, $23 = 0.0, $add130 = 0.0, $div131 = 0.0, $conv132 = 0, $24 = 0, $cmp13514 = 0, $list138 = 0, $i_115 = 0, $25 = 0, $arrayidx139 = 0, $26 = 0, $27 = 0, $tobool12 = 0, $e_013 = 0, $tobool1438 = 0, $f_09 = 0, $head145 = 0, $28 = 0, $cmp146 = 0, $prt_sroa_0_0__idx5 = 0, $prt_sroa_1_8__idx12 = 0, $prt_sroa_2_16__idx19 = 0, $prt_sroa_3_24__idx26 = 0, $prt_sroa_4_28__idx32 = 0, $prt_sroa_5_29__idx38 = 0, $prt_sroa_6_30__idx44 = 0, $prt_sroa_7_31__idx50 = 0, $prt_sroa_8_32__idx56 = 0, $prt_sroa_9_33__idx62 = 0, $prt_sroa_11_36__idx78 = 0, $tail151 = 0, $29 = 0, $cmp152 = 0, $prt_sroa_0_0__idx3 = 0, $prt_sroa_1_8__idx10 = 0, $prt_sroa_2_16__idx17 = 0, $prt_sroa_3_24__idx24 = 0, $prt_sroa_4_28__idx30 = 0, $prt_sroa_5_29__idx36 = 0, $prt_sroa_6_30__idx42 = 0, $prt_sroa_7_31__idx48 = 0, $prt_sroa_8_32__idx54 = 0, $prt_sroa_9_33__idx60 = 0, $prt_sroa_11_36__idx76 = 0, $edge_type = 0, $30 = 0, $cmp160 = 0, $list177 = 0, $31 = 0, $32 = 0, $tobool143 = 0, $33 = 0, $node_type = 0, $34 = 0, $cmp165 = 0, $size170 = 0, $35 = 0, $cmp171 = 0, $tobool18410 = 0, $f_111 = 0, $head186 = 0, $36 = 0, $cmp187 = 0, $prt_sroa_0_0__idx1 = 0, $prt_sroa_1_8__idx8 = 0, $prt_sroa_2_16__idx15 = 0, $prt_sroa_3_24__idx22 = 0, $prt_sroa_4_28__idx28 = 0, $prt_sroa_5_29__idx34 = 0, $prt_sroa_6_30__idx40 = 0, $prt_sroa_7_31__idx46 = 0, $prt_sroa_8_32__idx52 = 0, $prt_sroa_9_33__idx58 = 0, $prt_sroa_11_36__idx74 = 0, $tail193 = 0, $37 = 0, $cmp194 = 0, $prt_sroa_0_0__idx = 0, $prt_sroa_1_8__idx7 = 0, $prt_sroa_2_16__idx14 = 0, $prt_sroa_3_24__idx21 = 0, $prt_sroa_4_28__idx = 0, $prt_sroa_5_29__idx = 0, $prt_sroa_6_30__idx = 0, $prt_sroa_7_31__idx = 0, $prt_sroa_8_32__idx = 0, $prt_sroa_9_33__idx = 0, $prt_sroa_11_36__idx73 = 0, $edge_type202 = 0, $38 = 0, $cmp204 = 0, $list223 = 0, $39 = 0, $40 = 0, $tobool184 = 0, $41 = 0, $node_type209 = 0, $42 = 0, $cmp211 = 0, $size216 = 0, $43 = 0, $cmp217 = 0, $to_virt = 0, $44 = 0, $tobool = 0, $inc233 = 0, $45 = 0, $cmp135 = 0, $has_port = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 80 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sflag = __stackBase__ | 0;
+ $eflag = __stackBase__ + 8 | 0;
+ $curve = __stackBase__ + 16 | 0;
+ $size = $l + 4 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp16 = ($0 | 0) > 0;
+ if ($cmp16) {
+ label = 3;
+ break;
+ } else {
+ $y_0_lcssa = 0.0;
+ $x_0_lcssa = 0.0;
+ label = 7;
+ break;
+ }
+ case 3:
+ $list = $l | 0;
+ $x7 = $u + 32 | 0;
+ $y13 = $u + 40 | 0;
+ $y_017 = 0.0;
+ $x_018 = 0.0;
+ $i_019 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$list >> 2] | 0;
+ $arrayidx = $1 + ($i_019 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $head = $2 + 12 | 0;
+ $3 = HEAP32[$head >> 2] | 0;
+ $cmp1 = ($3 | 0) == ($u | 0);
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ $v_0 = $3;
+ label = 6;
+ break;
+ }
+ case 5:
+ $tail = $2 + 16 | 0;
+ $4 = HEAP32[$tail >> 2] | 0;
+ $v_0 = $4;
+ label = 6;
+ break;
+ case 6:
+ $x4 = $v_0 + 32 | 0;
+ $5 = +HEAPF64[$x4 >> 3];
+ $6 = +HEAPF64[$x7 >> 3];
+ $sub = $5 - $6;
+ $y10 = $v_0 + 40 | 0;
+ $7 = +HEAPF64[$y10 >> 3];
+ $8 = +HEAPF64[$y13 >> 3];
+ $sub14 = $7 - $8;
+ $call = +_hypot(+$sub, +$sub14);
+ $div = $sub / $call;
+ $add = $x_018 + $div;
+ $div15 = $sub14 / $call;
+ $add16 = $y_017 + $div15;
+ $inc = $i_019 + 1 | 0;
+ $9 = HEAP32[$size >> 2] | 0;
+ $cmp = ($inc | 0) < ($9 | 0);
+ if ($cmp) {
+ $y_017 = $add16;
+ $x_018 = $add;
+ $i_019 = $inc;
+ label = 4;
+ break;
+ } else {
+ $y_0_lcssa = $add16;
+ $x_0_lcssa = $add;
+ label = 7;
+ break;
+ }
+ case 7:
+ $call17 = +_hypot(+$x_0_lcssa, +$y_0_lcssa);
+ $div18 = $x_0_lcssa / $call17;
+ $div19 = $y_0_lcssa / $call17;
+ $x22 = $u + 32 | 0;
+ $10 = +HEAPF64[$x22 >> 3];
+ $y25 = $u + 40 | 0;
+ $11 = +HEAPF64[$y25 >> 3];
+ $lw = $u + 104 | 0;
+ $12 = +HEAPF64[$lw >> 3];
+ $rw = $u + 112 | 0;
+ $13 = +HEAPF64[$rw >> 3];
+ $add28 = $12 + $13;
+ $ht = $u + 96 | 0;
+ $14 = +HEAPF64[$ht >> 3];
+ $graph = $u + 20 | 0;
+ $15 = HEAP32[$graph >> 2] | 0;
+ $ranksep = $15 + 264 | 0;
+ $16 = HEAP32[$ranksep >> 2] | 0;
+ $conv = +($16 | 0);
+ $add31 = $14 + $conv;
+ $cmp32 = $add28 > $add31;
+ $add28_add31 = $cmp32 ? $add28 : $add31;
+ $mul = $div18 * $add28_add31;
+ $add49 = $10 + $mul;
+ $mul50 = $div19 * $add28_add31;
+ $add54 = $11 + $mul50;
+ $arrayidx55 = $curve | 0;
+ $x56 = $curve | 0;
+ HEAPF64[$x56 >> 3] = $10;
+ $y58 = $curve + 8 | 0;
+ HEAPF64[$y58 >> 3] = $11;
+ $mul59 = $10 * 2.0;
+ $add60 = $mul59 + $add49;
+ $div61 = $add60 / 3.0;
+ $x63 = $curve + 16 | 0;
+ HEAPF64[$x63 >> 3] = $div61;
+ $mul64 = $11 * 2.0;
+ $add65 = $mul64 + $add54;
+ $div66 = $add65 / 3.0;
+ $y68 = $curve + 24 | 0;
+ HEAPF64[$y68 >> 3] = $div66;
+ $mul69 = $add49 * 2.0;
+ $add70 = $10 + $mul69;
+ $div71 = $add70 / 3.0;
+ $x73 = $curve + 32 | 0;
+ HEAPF64[$x73 >> 3] = $div71;
+ $mul74 = $add54 * 2.0;
+ $add75 = $11 + $mul74;
+ $div76 = $add75 / 3.0;
+ $y78 = $curve + 40 | 0;
+ HEAPF64[$y78 >> 3] = $div76;
+ $x80 = $curve + 48 | 0;
+ HEAPF64[$x80 >> 3] = $add49;
+ $y82 = $curve + 56 | 0;
+ HEAPF64[$y82 >> 3] = $add54;
+ $17 = $u;
+ _shape_clip($17, $arrayidx55);
+ $18 = +HEAPF64[$x56 >> 3];
+ $19 = +HEAPF64[$x22 >> 3];
+ $sub88 = $18 - $19;
+ $20 = +HEAPF64[$y58 >> 3];
+ $21 = +HEAPF64[$y25 >> 3];
+ $sub94 = $20 - $21;
+ $cmp95 = $sub88 < 0.0;
+ if ($cmp95) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $add98 = $sub88 + .5;
+ $add98_sink = $add98;
+ label = 10;
+ break;
+ case 9:
+ $sub101 = $sub88 + -.5;
+ $add98_sink = $sub101;
+ label = 10;
+ break;
+ case 10:
+ $conv99 = ~~$add98_sink;
+ $conv105 = +($conv99 | 0);
+ $cmp107 = $sub94 < 0.0;
+ if ($cmp107) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $add110 = $sub94 + .5;
+ $add110_sink = $add110;
+ label = 13;
+ break;
+ case 12:
+ $sub113 = $sub94 + -.5;
+ $add110_sink = $sub113;
+ label = 13;
+ break;
+ case 13:
+ $conv111 = ~~$add110_sink;
+ $conv117 = +($conv111 | 0);
+ $22 = +HEAPF64[$lw >> 3];
+ $add124 = $conv105 + $22;
+ $mul125 = $add124 * 256.0;
+ $23 = +HEAPF64[$rw >> 3];
+ $add130 = $22 + $23;
+ $div131 = $mul125 / $add130;
+ $conv132 = ~~$div131;
+ $24 = HEAP32[$size >> 2] | 0;
+ $cmp13514 = ($24 | 0) > 0;
+ if ($cmp13514) {
+ label = 14;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 14:
+ $list138 = $l | 0;
+ $i_115 = 0;
+ label = 15;
+ break;
+ case 15:
+ $25 = HEAP32[$list138 >> 2] | 0;
+ $arrayidx139 = $25 + ($i_115 << 2) | 0;
+ $26 = HEAP32[$arrayidx139 >> 2] | 0;
+ $27 = $26;
+ _arrow_flags($27, $sflag, $eflag);
+ $tobool12 = ($26 | 0) == 0;
+ if ($tobool12) {
+ label = 35;
+ break;
+ } else {
+ $e_013 = $26;
+ label = 16;
+ break;
+ }
+ case 16:
+ $tobool1438 = ($e_013 | 0) == 0;
+ if ($tobool1438) {
+ label = 34;
+ break;
+ } else {
+ $f_09 = $e_013;
+ label = 17;
+ break;
+ }
+ case 17:
+ $head145 = $f_09 + 12 | 0;
+ $28 = HEAP32[$head145 >> 2] | 0;
+ $cmp146 = ($28 | 0) == ($u | 0);
+ if ($cmp146) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $prt_sroa_0_0__idx5 = $f_09 + 72 | 0;
+ HEAPF64[$prt_sroa_0_0__idx5 >> 3] = $conv105;
+ $prt_sroa_1_8__idx12 = $f_09 + 80 | 0;
+ HEAPF64[$prt_sroa_1_8__idx12 >> 3] = $conv117;
+ $prt_sroa_2_16__idx19 = $f_09 + 88 | 0;
+ HEAPF64[$prt_sroa_2_16__idx19 >> 3] = 0.0;
+ $prt_sroa_3_24__idx26 = $f_09 + 96 | 0;
+ HEAP32[$prt_sroa_3_24__idx26 >> 2] = 0;
+ $prt_sroa_4_28__idx32 = $f_09 + 100 | 0;
+ HEAP8[$prt_sroa_4_28__idx32] = 1;
+ $prt_sroa_5_29__idx38 = $f_09 + 101 | 0;
+ HEAP8[$prt_sroa_5_29__idx38] = 0;
+ $prt_sroa_6_30__idx44 = $f_09 + 102 | 0;
+ HEAP8[$prt_sroa_6_30__idx44] = 0;
+ $prt_sroa_7_31__idx50 = $f_09 + 103 | 0;
+ HEAP8[$prt_sroa_7_31__idx50] = 0;
+ $prt_sroa_8_32__idx56 = $f_09 + 104 | 0;
+ HEAP8[$prt_sroa_8_32__idx56] = $conv132;
+ $prt_sroa_9_33__idx62 = $f_09 + 105 | 0;
+ HEAP8[$prt_sroa_9_33__idx62] = 0;
+ $prt_sroa_11_36__idx78 = $f_09 + 108 | 0;
+ HEAP32[$prt_sroa_11_36__idx78 >> 2] = 0;
+ label = 19;
+ break;
+ case 19:
+ $tail151 = $f_09 + 16 | 0;
+ $29 = HEAP32[$tail151 >> 2] | 0;
+ $cmp152 = ($29 | 0) == ($u | 0);
+ if ($cmp152) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $prt_sroa_0_0__idx3 = $f_09 + 32 | 0;
+ HEAPF64[$prt_sroa_0_0__idx3 >> 3] = $conv105;
+ $prt_sroa_1_8__idx10 = $f_09 + 40 | 0;
+ HEAPF64[$prt_sroa_1_8__idx10 >> 3] = $conv117;
+ $prt_sroa_2_16__idx17 = $f_09 + 48 | 0;
+ HEAPF64[$prt_sroa_2_16__idx17 >> 3] = 0.0;
+ $prt_sroa_3_24__idx24 = $f_09 + 56 | 0;
+ HEAP32[$prt_sroa_3_24__idx24 >> 2] = 0;
+ $prt_sroa_4_28__idx30 = $f_09 + 60 | 0;
+ HEAP8[$prt_sroa_4_28__idx30] = 1;
+ $prt_sroa_5_29__idx36 = $f_09 + 61 | 0;
+ HEAP8[$prt_sroa_5_29__idx36] = 0;
+ $prt_sroa_6_30__idx42 = $f_09 + 62 | 0;
+ HEAP8[$prt_sroa_6_30__idx42] = 0;
+ $prt_sroa_7_31__idx48 = $f_09 + 63 | 0;
+ HEAP8[$prt_sroa_7_31__idx48] = 0;
+ $prt_sroa_8_32__idx54 = $f_09 + 64 | 0;
+ HEAP8[$prt_sroa_8_32__idx54] = $conv132;
+ $prt_sroa_9_33__idx60 = $f_09 + 65 | 0;
+ HEAP8[$prt_sroa_9_33__idx60] = 0;
+ $prt_sroa_11_36__idx76 = $f_09 + 68 | 0;
+ HEAP32[$prt_sroa_11_36__idx76 >> 2] = 0;
+ label = 21;
+ break;
+ case 21:
+ $edge_type = $f_09 + 128 | 0;
+ $30 = HEAP8[$edge_type] | 0;
+ $cmp160 = $30 << 24 >> 24 == 1;
+ if ($cmp160) {
+ label = 23;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 22:
+ $list177 = $33 + 184 | 0;
+ $31 = HEAP32[$list177 >> 2] | 0;
+ $32 = HEAP32[$31 >> 2] | 0;
+ $tobool143 = ($32 | 0) == 0;
+ if ($tobool143) {
+ label = 25;
+ break;
+ } else {
+ $f_09 = $32;
+ label = 17;
+ break;
+ }
+ case 23:
+ $33 = HEAP32[$head145 >> 2] | 0;
+ $node_type = $33 + 162 | 0;
+ $34 = HEAP8[$node_type] | 0;
+ $cmp165 = $34 << 24 >> 24 == 1;
+ if ($cmp165) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $size170 = $33 + 188 | 0;
+ $35 = HEAP32[$size170 >> 2] | 0;
+ $cmp171 = ($35 | 0) == 1;
+ if ($cmp171) {
+ label = 22;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $tobool18410 = ($e_013 | 0) == 0;
+ if ($tobool18410) {
+ label = 34;
+ break;
+ } else {
+ $f_111 = $e_013;
+ label = 26;
+ break;
+ }
+ case 26:
+ $head186 = $f_111 + 12 | 0;
+ $36 = HEAP32[$head186 >> 2] | 0;
+ $cmp187 = ($36 | 0) == ($u | 0);
+ if ($cmp187) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $prt_sroa_0_0__idx1 = $f_111 + 72 | 0;
+ HEAPF64[$prt_sroa_0_0__idx1 >> 3] = $conv105;
+ $prt_sroa_1_8__idx8 = $f_111 + 80 | 0;
+ HEAPF64[$prt_sroa_1_8__idx8 >> 3] = $conv117;
+ $prt_sroa_2_16__idx15 = $f_111 + 88 | 0;
+ HEAPF64[$prt_sroa_2_16__idx15 >> 3] = 0.0;
+ $prt_sroa_3_24__idx22 = $f_111 + 96 | 0;
+ HEAP32[$prt_sroa_3_24__idx22 >> 2] = 0;
+ $prt_sroa_4_28__idx28 = $f_111 + 100 | 0;
+ HEAP8[$prt_sroa_4_28__idx28] = 1;
+ $prt_sroa_5_29__idx34 = $f_111 + 101 | 0;
+ HEAP8[$prt_sroa_5_29__idx34] = 0;
+ $prt_sroa_6_30__idx40 = $f_111 + 102 | 0;
+ HEAP8[$prt_sroa_6_30__idx40] = 0;
+ $prt_sroa_7_31__idx46 = $f_111 + 103 | 0;
+ HEAP8[$prt_sroa_7_31__idx46] = 0;
+ $prt_sroa_8_32__idx52 = $f_111 + 104 | 0;
+ HEAP8[$prt_sroa_8_32__idx52] = $conv132;
+ $prt_sroa_9_33__idx58 = $f_111 + 105 | 0;
+ HEAP8[$prt_sroa_9_33__idx58] = 0;
+ $prt_sroa_11_36__idx74 = $f_111 + 108 | 0;
+ HEAP32[$prt_sroa_11_36__idx74 >> 2] = 0;
+ label = 28;
+ break;
+ case 28:
+ $tail193 = $f_111 + 16 | 0;
+ $37 = HEAP32[$tail193 >> 2] | 0;
+ $cmp194 = ($37 | 0) == ($u | 0);
+ if ($cmp194) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ $prt_sroa_0_0__idx = $f_111 + 32 | 0;
+ HEAPF64[$prt_sroa_0_0__idx >> 3] = $conv105;
+ $prt_sroa_1_8__idx7 = $f_111 + 40 | 0;
+ HEAPF64[$prt_sroa_1_8__idx7 >> 3] = $conv117;
+ $prt_sroa_2_16__idx14 = $f_111 + 48 | 0;
+ HEAPF64[$prt_sroa_2_16__idx14 >> 3] = 0.0;
+ $prt_sroa_3_24__idx21 = $f_111 + 56 | 0;
+ HEAP32[$prt_sroa_3_24__idx21 >> 2] = 0;
+ $prt_sroa_4_28__idx = $f_111 + 60 | 0;
+ HEAP8[$prt_sroa_4_28__idx] = 1;
+ $prt_sroa_5_29__idx = $f_111 + 61 | 0;
+ HEAP8[$prt_sroa_5_29__idx] = 0;
+ $prt_sroa_6_30__idx = $f_111 + 62 | 0;
+ HEAP8[$prt_sroa_6_30__idx] = 0;
+ $prt_sroa_7_31__idx = $f_111 + 63 | 0;
+ HEAP8[$prt_sroa_7_31__idx] = 0;
+ $prt_sroa_8_32__idx = $f_111 + 64 | 0;
+ HEAP8[$prt_sroa_8_32__idx] = $conv132;
+ $prt_sroa_9_33__idx = $f_111 + 65 | 0;
+ HEAP8[$prt_sroa_9_33__idx] = 0;
+ $prt_sroa_11_36__idx73 = $f_111 + 68 | 0;
+ HEAP32[$prt_sroa_11_36__idx73 >> 2] = 0;
+ label = 30;
+ break;
+ case 30:
+ $edge_type202 = $f_111 + 128 | 0;
+ $38 = HEAP8[$edge_type202] | 0;
+ $cmp204 = $38 << 24 >> 24 == 1;
+ if ($cmp204) {
+ label = 32;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 31:
+ $list223 = $41 + 176 | 0;
+ $39 = HEAP32[$list223 >> 2] | 0;
+ $40 = HEAP32[$39 >> 2] | 0;
+ $tobool184 = ($40 | 0) == 0;
+ if ($tobool184) {
+ label = 34;
+ break;
+ } else {
+ $f_111 = $40;
+ label = 26;
+ break;
+ }
+ case 32:
+ $41 = HEAP32[$tail193 >> 2] | 0;
+ $node_type209 = $41 + 162 | 0;
+ $42 = HEAP8[$node_type209] | 0;
+ $cmp211 = $42 << 24 >> 24 == 1;
+ if ($cmp211) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ $size216 = $41 + 180 | 0;
+ $43 = HEAP32[$size216 >> 2] | 0;
+ $cmp217 = ($43 | 0) == 1;
+ if ($cmp217) {
+ label = 31;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $to_virt = $e_013 + 188 | 0;
+ $44 = HEAP32[$to_virt >> 2] | 0;
+ $tobool = ($44 | 0) == 0;
+ if ($tobool) {
+ label = 35;
+ break;
+ } else {
+ $e_013 = $44;
+ label = 16;
+ break;
+ }
+ case 35:
+ $inc233 = $i_115 + 1 | 0;
+ $45 = HEAP32[$size >> 2] | 0;
+ $cmp135 = ($inc233 | 0) < ($45 | 0);
+ if ($cmp135) {
+ $i_115 = $inc233;
+ label = 15;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $has_port = $u + 161 | 0;
+ HEAP8[$has_port] = 1;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _cluster_leader($clust) {
+ $clust = $clust | 0;
+ var $nlist = 0, $n_023 = 0, $tobool24 = 0, $n_027 = 0, $leader_025 = 0, $rank = 0, $0 = 0, $cmp = 0, $node_type = 0, $1 = 0, $cmp3 = 0, $n_0_leader_0 = 0, $leader_1 = 0, $next = 0, $n_0 = 0, $tobool = 0, $cmp14 = 0, $leader17 = 0, $2 = 0, $call = 0, $tobool1920 = 0, $3 = 0, $n_122_in = 0, $n_122 = 0, $UF_size = 0, $4 = 0, $5 = 0, $cmp22 = 0, $cmp24 = 0, $or_cond = 0, $6 = 0, $call29 = 0, $ranktype = 0, $call32 = 0, $tobool19 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $nlist = $clust + 220 | 0;
+ $n_023 = HEAP32[$nlist >> 2] | 0;
+ $tobool24 = ($n_023 | 0) == 0;
+ if ($tobool24) {
+ label = 7;
+ break;
+ } else {
+ $leader_025 = 0;
+ $n_027 = $n_023;
+ label = 3;
+ break;
+ }
+ case 3:
+ $rank = $n_027 + 236 | 0;
+ $0 = HEAP32[$rank >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $leader_1 = $leader_025;
+ label = 5;
+ break;
+ }
+ case 4:
+ $node_type = $n_027 + 162 | 0;
+ $1 = HEAP8[$node_type] | 0;
+ $cmp3 = $1 << 24 >> 24 == 0;
+ $n_0_leader_0 = $cmp3 ? $n_027 : $leader_025;
+ $leader_1 = $n_0_leader_0;
+ label = 5;
+ break;
+ case 5:
+ $next = $n_027 + 168 | 0;
+ $n_0 = HEAP32[$next >> 2] | 0;
+ $tobool = ($n_0 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ $leader_025 = $leader_1;
+ $n_027 = $n_0;
+ label = 3;
+ break;
+ }
+ case 6:
+ $cmp14 = ($leader_1 | 0) == 0;
+ if ($cmp14) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ ___assert_func(129880, 235, 164576, 118104);
+ case 8:
+ $leader17 = $clust + 276 | 0;
+ HEAP32[$leader17 >> 2] = $leader_1;
+ $2 = $clust;
+ $call = _agfstnode($2) | 0;
+ $tobool1920 = ($call | 0) == 0;
+ if ($tobool1920) {
+ label = 13;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $3 = $leader_1;
+ $n_122_in = $call;
+ label = 10;
+ break;
+ case 10:
+ $n_122 = $n_122_in;
+ $UF_size = $n_122_in + 220 | 0;
+ $4 = $UF_size;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $cmp22 = ($5 | 0) < 2;
+ $cmp24 = ($n_122 | 0) == ($leader_1 | 0);
+ $or_cond = $cmp22 | $cmp24;
+ if ($or_cond) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ ___assert_func(129880, 239, 164576, 112744);
+ case 12:
+ $6 = $n_122_in;
+ $call29 = _UF_union($6, $3) | 0;
+ $ranktype = $n_122 + 165 | 0;
+ HEAP8[$ranktype] = 7;
+ $call32 = _agnxtnode($2, $n_122_in) | 0;
+ $tobool19 = ($call32 | 0) == 0;
+ if ($tobool19) {
+ label = 13;
+ break;
+ } else {
+ $n_122_in = $call32;
+ label = 10;
+ break;
+ }
+ case 13:
+ return;
+ }
+}
+function _core_loadimage_xdot($job, $us, $b, $filled) {
+ $job = $job | 0;
+ $us = $us | 0;
+ $b = $b | 0;
+ $filled = $filled | 0;
+ var $buf = 0, $obj = 0, $0 = 0, $emit_state1 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $call = 0, $3 = 0, $LL = 0, $arraydecay = 0, $x = 0, $4 = 0.0, $x4 = 0, $5 = 0.0, $sub = 0.0, $cmp = 0, $add = 0.0, $sub15 = 0.0, $add_sink = 0.0, $conv = 0, $y = 0, $6 = 0.0, $y19 = 0, $7 = 0.0, $sub20 = 0.0, $cmp21 = 0, $add29 = 0.0, $sub37 = 0.0, $add29_sink = 0.0, $conv30 = 0, $call41 = 0, $8 = 0, $call44 = 0, $name = 0, $9 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $emit_state1 = $0 + 12 | 0;
+ $1 = HEAP32[$emit_state1 >> 2] | 0;
+ $arrayidx = 168 + ($1 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $call = _agxbput($2, 152808) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $LL = $b | 0;
+ _output_point($3, $LL);
+ $arraydecay = $buf | 0;
+ $x = $b + 16 | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $x4 = $b | 0;
+ $5 = +HEAPF64[$x4 >> 3];
+ $sub = $4 - $5;
+ $cmp = $sub < 0.0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $sub + .5;
+ $add_sink = $add;
+ label = 5;
+ break;
+ case 4:
+ $sub15 = $sub + -.5;
+ $add_sink = $sub15;
+ label = 5;
+ break;
+ case 5:
+ $conv = ~~$add_sink;
+ $y = $b + 24 | 0;
+ $6 = +HEAPF64[$y >> 3];
+ $y19 = $b + 8 | 0;
+ $7 = +HEAPF64[$y19 >> 3];
+ $sub20 = $6 - $7;
+ $cmp21 = $sub20 < 0.0;
+ if ($cmp21) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $add29 = $sub20 + .5;
+ $add29_sink = $add29;
+ label = 8;
+ break;
+ case 7:
+ $sub37 = $sub20 + -.5;
+ $add29_sink = $sub37;
+ label = 8;
+ break;
+ case 8:
+ $conv30 = ~~$add29_sink;
+ $call41 = _sprintf($arraydecay | 0, 155152, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $conv, HEAP32[tempInt + 8 >> 2] = $conv30, tempInt) | 0) | 0;
+ $8 = HEAP32[$arrayidx >> 2] | 0;
+ $call44 = _agxbput($8, $arraydecay) | 0;
+ $name = $us + 8 | 0;
+ $9 = HEAP32[$name >> 2] | 0;
+ _xdot_str($job, 125984, $9);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _xdot_str($job, $pfx, $s) {
+ $job = $job | 0;
+ $pfx = $pfx | 0;
+ $s = $s | 0;
+ var $buf = 0, $obj = 0, $0 = 0, $emit_state1 = 0, $1 = 0, $arraydecay = 0, $call = 0, $call2 = 0, $arrayidx = 0, $2 = 0, $call4 = 0, $3 = 0, $call6 = 0, $4 = 0, $ptr = 0, $5 = 0, $eptr = 0, $6 = 0, $cmp = 0, $call10 = 0, $7 = 0, $ptr12 = 0, $8 = 0, $incdec_ptr = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $emit_state1 = $0 + 12 | 0;
+ $1 = HEAP32[$emit_state1 >> 2] | 0;
+ $arraydecay = $buf | 0;
+ $call = _strlen($s | 0) | 0;
+ $call2 = _sprintf($arraydecay | 0, 117608, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $pfx, HEAP32[tempInt + 8 >> 2] = $call, tempInt) | 0) | 0;
+ $arrayidx = 168 + ($1 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $call4 = _agxbput($2, $arraydecay) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $call6 = _agxbput($3, $s) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $ptr = $4 + 4 | 0;
+ $5 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $4 + 8 | 0;
+ $6 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $5 >>> 0 < $6 >>> 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call10 = _agxbmore($4, 1) | 0;
+ label = 4;
+ break;
+ case 4:
+ $7 = HEAP32[$arrayidx >> 2] | 0;
+ $ptr12 = $7 + 4 | 0;
+ $8 = HEAP32[$ptr12 >> 2] | 0;
+ $incdec_ptr = $8 + 1 | 0;
+ HEAP32[$ptr12 >> 2] = $incdec_ptr;
+ HEAP8[$8] = 32;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _dot_begin_graph($job) {
+ $job = $job | 0;
+ var $e_arrows = 0, $s_arrows = 0, $obj = 0, $0 = 0, $g1 = 0, $1 = 0, $id = 0, $2 = 0, $3 = 0, $flags = 0, $4 = 0, $and = 0, $tobool = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $e_arrows = __stackBase__ | 0;
+ $s_arrows = __stackBase__ + 8 | 0;
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $g1 = $0 + 8 | 0;
+ $1 = HEAP32[$g1 >> 2] | 0;
+ $id = $job + 64 | 0;
+ $2 = HEAP32[$id >> 2] | 0;
+ if (($2 | 0) == 0) {
+ label = 3;
+ break;
+ } else if (($2 | 0) == 1) {
+ label = 4;
+ break;
+ } else if (($2 | 0) == 4) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $3 = $1;
+ _attach_attrs($3);
+ label = 7;
+ break;
+ case 4:
+ $flags = $1 + 168 | 0;
+ $4 = HEAP16[$flags >> 1] | 0;
+ $and = $4 & 1;
+ $tobool = $and << 16 >> 16 == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = $1;
+ _undoClusterEdges($5);
+ label = 7;
+ break;
+ case 6:
+ $6 = $1;
+ _attach_attrs_and_arrows($6, $s_arrows, $e_arrows);
+ $7 = HEAP32[$s_arrows >> 2] | 0;
+ $8 = HEAP32[$e_arrows >> 2] | 0;
+ _xdot_begin_graph($1, $7, $8);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _dot_end_graph($job) {
+ $job = $job | 0;
+ var $obj = 0, $0 = 0, $g1 = 0, $1 = 0, $id = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $flags = 0, $9 = 0, $and = 0, $tobool = 0, $10 = 0, $11 = 0, $call = 0, $flags5 = 0, $12 = 0, $and6 = 0, $tobool7 = 0, $13 = 0, $14 = 0, $call9 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $g1 = $0 + 8 | 0;
+ $1 = HEAP32[$g1 >> 2] | 0;
+ _agsetiodisc(0, 170, 288);
+ $id = $job + 64 | 0;
+ $2 = HEAP32[$id >> 2] | 0;
+ if (($2 | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($2 | 0) == 3) {
+ label = 4;
+ break;
+ } else if (($2 | 0) == 0 | ($2 | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($2 | 0) == 4) {
+ label = 7;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $3 = $job;
+ $4 = $job;
+ $5 = $1;
+ _write_plain($4, $5, $3, 0);
+ label = 9;
+ break;
+ case 4:
+ $6 = $job;
+ $7 = $job;
+ $8 = $1;
+ _write_plain($7, $8, $6, 1);
+ label = 9;
+ break;
+ case 5:
+ $flags = $job + 152 | 0;
+ $9 = HEAP32[$flags >> 2] | 0;
+ $and = $9 & 134217728;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 6:
+ $10 = $job;
+ $11 = $1;
+ $call = _agwrite($11, $10) | 0;
+ label = 9;
+ break;
+ case 7:
+ _xdot_end_graph($1);
+ $flags5 = $job + 152 | 0;
+ $12 = HEAP32[$flags5 >> 2] | 0;
+ $and6 = $12 & 134217728;
+ $tobool7 = ($and6 | 0) == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $13 = $job;
+ $14 = $1;
+ $call9 = _agwrite($14, $13) | 0;
+ label = 9;
+ break;
+ case 9:
+ _agsetiodisc(0, 0, 0);
+ return;
+ }
+}
+function _xdot_end_cluster($job) {
+ $job = $job | 0;
+ var $obj = 0, $0 = 0, $sg = 0, $1 = 0, $2 = 0, $3 = 0, $g_draw = 0, $4 = 0, $index = 0, $5 = 0, $6 = 0, $7 = 0, $cmp = 0, $call = 0, $8 = 0, $9 = 0, $call3 = 0, $label = 0, $10 = 0, $tobool = 0, $11 = 0, $g_l_draw = 0, $12 = 0, $index5 = 0, $13 = 0, $14 = 0, $15 = 0, $cmp8 = 0, $call10 = 0, $16 = 0, $17 = 0, $call18 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $sg = $0 + 8 | 0;
+ $1 = HEAP32[$sg >> 2] | 0;
+ $2 = $1 | 0;
+ $3 = HEAP32[40] | 0;
+ $g_draw = $3 | 0;
+ $4 = HEAP32[$g_draw >> 2] | 0;
+ $index = $4 + 8 | 0;
+ $5 = HEAP32[$index >> 2] | 0;
+ $6 = HEAP32[59] | 0;
+ $7 = HEAP32[60] | 0;
+ $cmp = $6 >>> 0 < $7 >>> 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _agxbmore(232, 1) | 0;
+ label = 4;
+ break;
+ case 4:
+ $8 = HEAP32[59] | 0;
+ HEAP8[$8] = 0;
+ $9 = HEAP32[58] | 0;
+ HEAP32[59] = $9;
+ $call3 = _agxset($2, $5, $9) | 0;
+ $label = $1 + 52 | 0;
+ $10 = HEAP32[$label >> 2] | 0;
+ $tobool = ($10 | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $11 = HEAP32[40] | 0;
+ $g_l_draw = $11 + 4 | 0;
+ $12 = HEAP32[$g_l_draw >> 2] | 0;
+ $index5 = $12 + 8 | 0;
+ $13 = HEAP32[$index5 >> 2] | 0;
+ $14 = HEAP32[75] | 0;
+ $15 = HEAP32[76] | 0;
+ $cmp8 = $14 >>> 0 < $15 >>> 0;
+ if ($cmp8) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call10 = _agxbmore(296, 1) | 0;
+ label = 7;
+ break;
+ case 7:
+ $16 = HEAP32[75] | 0;
+ HEAP8[$16] = 0;
+ $17 = HEAP32[74] | 0;
+ HEAP32[75] = $17;
+ $call18 = _agxset($2, $13, $17) | 0;
+ label = 8;
+ break;
+ case 8:
+ HEAPF64[899] = 1.0;
+ HEAPF64[903] = 1.0;
+ return;
+ }
+}
+function _xdot_end_node($job) {
+ $job = $job | 0;
+ var $obj = 0, $0 = 0, $u = 0, $n1 = 0, $1 = 0, $2 = 0, $3 = 0, $tobool = 0, $4 = 0, $5 = 0, $n_draw = 0, $6 = 0, $index = 0, $7 = 0, $8 = 0, $cmp = 0, $call = 0, $9 = 0, $10 = 0, $call6 = 0, $11 = 0, $12 = 0, $tobool12 = 0, $13 = 0, $14 = 0, $n_l_draw = 0, $15 = 0, $index14 = 0, $16 = 0, $17 = 0, $cmp17 = 0, $call19 = 0, $18 = 0, $19 = 0, $call27 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $u = $0 + 8 | 0;
+ $n1 = $u;
+ $1 = HEAP32[$n1 >> 2] | 0;
+ $2 = HEAP32[59] | 0;
+ $3 = HEAP32[58] | 0;
+ $tobool = ($2 | 0) == ($3 | 0);
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $4 = $1 | 0;
+ $5 = HEAP32[40] | 0;
+ $n_draw = $5 + 8 | 0;
+ $6 = HEAP32[$n_draw >> 2] | 0;
+ $index = $6 + 8 | 0;
+ $7 = HEAP32[$index >> 2] | 0;
+ $8 = HEAP32[60] | 0;
+ $cmp = $2 >>> 0 < $8 >>> 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _agxbmore(232, 1) | 0;
+ label = 5;
+ break;
+ case 5:
+ $9 = HEAP32[59] | 0;
+ HEAP8[$9] = 0;
+ $10 = HEAP32[58] | 0;
+ HEAP32[59] = $10;
+ $call6 = _agxset($4, $7, $10) | 0;
+ label = 6;
+ break;
+ case 6:
+ $11 = HEAP32[75] | 0;
+ $12 = HEAP32[74] | 0;
+ $tobool12 = ($11 | 0) == ($12 | 0);
+ if ($tobool12) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $13 = $1 | 0;
+ $14 = HEAP32[40] | 0;
+ $n_l_draw = $14 + 12 | 0;
+ $15 = HEAP32[$n_l_draw >> 2] | 0;
+ $index14 = $15 + 8 | 0;
+ $16 = HEAP32[$index14 >> 2] | 0;
+ $17 = HEAP32[76] | 0;
+ $cmp17 = $11 >>> 0 < $17 >>> 0;
+ if ($cmp17) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call19 = _agxbmore(296, 1) | 0;
+ label = 9;
+ break;
+ case 9:
+ $18 = HEAP32[75] | 0;
+ HEAP8[$18] = 0;
+ $19 = HEAP32[74] | 0;
+ HEAP32[75] = $19;
+ $call27 = _agxset($13, $16, $19) | 0;
+ label = 10;
+ break;
+ case 10:
+ HEAPF64[906] = 1.0;
+ HEAPF64[908] = 1.0;
+ return;
+ }
+}
+function _xdot_end_edge($job) {
+ $job = $job | 0;
+ var $obj = 0, $0 = 0, $u = 0, $e1 = 0, $1 = 0, $2 = 0, $3 = 0, $tobool = 0, $4 = 0, $5 = 0, $e_draw = 0, $6 = 0, $index = 0, $7 = 0, $8 = 0, $cmp = 0, $call = 0, $9 = 0, $10 = 0, $call6 = 0, $11 = 0, $12 = 0, $tobool12 = 0, $13 = 0, $14 = 0, $t_draw = 0, $15 = 0, $index14 = 0, $16 = 0, $17 = 0, $cmp17 = 0, $call19 = 0, $18 = 0, $19 = 0, $call27 = 0, $20 = 0, $21 = 0, $tobool34 = 0, $22 = 0, $23 = 0, $h_draw = 0, $24 = 0, $index36 = 0, $25 = 0, $26 = 0, $cmp39 = 0, $call41 = 0, $27 = 0, $28 = 0, $call49 = 0, $29 = 0, $30 = 0, $tobool56 = 0, $31 = 0, $32 = 0, $e_l_draw = 0, $33 = 0, $index58 = 0, $34 = 0, $35 = 0, $cmp61 = 0, $call63 = 0, $36 = 0, $37 = 0, $call71 = 0, $38 = 0, $39 = 0, $tobool78 = 0, $40 = 0, $41 = 0, $tl_draw = 0, $42 = 0, $index80 = 0, $43 = 0, $44 = 0, $cmp83 = 0, $call85 = 0, $45 = 0, $46 = 0, $call93 = 0, $47 = 0, $48 = 0, $tobool100 = 0, $49 = 0, $50 = 0, $hl_draw = 0, $51 = 0, $index102 = 0, $52 = 0, $53 = 0, $cmp105 = 0, $call107 = 0, $54 = 0, $55 = 0, $call115 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $u = $0 + 8 | 0;
+ $e1 = $u;
+ $1 = HEAP32[$e1 >> 2] | 0;
+ $2 = HEAP32[59] | 0;
+ $3 = HEAP32[58] | 0;
+ $tobool = ($2 | 0) == ($3 | 0);
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $4 = $1 | 0;
+ $5 = HEAP32[40] | 0;
+ $e_draw = $5 + 16 | 0;
+ $6 = HEAP32[$e_draw >> 2] | 0;
+ $index = $6 + 8 | 0;
+ $7 = HEAP32[$index >> 2] | 0;
+ $8 = HEAP32[60] | 0;
+ $cmp = $2 >>> 0 < $8 >>> 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _agxbmore(232, 1) | 0;
+ label = 5;
+ break;
+ case 5:
+ $9 = HEAP32[59] | 0;
+ HEAP8[$9] = 0;
+ $10 = HEAP32[58] | 0;
+ HEAP32[59] = $10;
+ $call6 = _agxset($4, $7, $10) | 0;
+ label = 6;
+ break;
+ case 6:
+ $11 = HEAP32[63] | 0;
+ $12 = HEAP32[62] | 0;
+ $tobool12 = ($11 | 0) == ($12 | 0);
+ if ($tobool12) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $13 = $1 | 0;
+ $14 = HEAP32[40] | 0;
+ $t_draw = $14 + 24 | 0;
+ $15 = HEAP32[$t_draw >> 2] | 0;
+ $index14 = $15 + 8 | 0;
+ $16 = HEAP32[$index14 >> 2] | 0;
+ $17 = HEAP32[64] | 0;
+ $cmp17 = $11 >>> 0 < $17 >>> 0;
+ if ($cmp17) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call19 = _agxbmore(248, 1) | 0;
+ label = 9;
+ break;
+ case 9:
+ $18 = HEAP32[63] | 0;
+ HEAP8[$18] = 0;
+ $19 = HEAP32[62] | 0;
+ HEAP32[63] = $19;
+ $call27 = _agxset($13, $16, $19) | 0;
+ label = 10;
+ break;
+ case 10:
+ $20 = HEAP32[67] | 0;
+ $21 = HEAP32[66] | 0;
+ $tobool34 = ($20 | 0) == ($21 | 0);
+ if ($tobool34) {
+ label = 14;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $22 = $1 | 0;
+ $23 = HEAP32[40] | 0;
+ $h_draw = $23 + 20 | 0;
+ $24 = HEAP32[$h_draw >> 2] | 0;
+ $index36 = $24 + 8 | 0;
+ $25 = HEAP32[$index36 >> 2] | 0;
+ $26 = HEAP32[68] | 0;
+ $cmp39 = $20 >>> 0 < $26 >>> 0;
+ if ($cmp39) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $call41 = _agxbmore(264, 1) | 0;
+ label = 13;
+ break;
+ case 13:
+ $27 = HEAP32[67] | 0;
+ HEAP8[$27] = 0;
+ $28 = HEAP32[66] | 0;
+ HEAP32[67] = $28;
+ $call49 = _agxset($22, $25, $28) | 0;
+ label = 14;
+ break;
+ case 14:
+ $29 = HEAP32[75] | 0;
+ $30 = HEAP32[74] | 0;
+ $tobool56 = ($29 | 0) == ($30 | 0);
+ if ($tobool56) {
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $31 = $1 | 0;
+ $32 = HEAP32[40] | 0;
+ $e_l_draw = $32 + 28 | 0;
+ $33 = HEAP32[$e_l_draw >> 2] | 0;
+ $index58 = $33 + 8 | 0;
+ $34 = HEAP32[$index58 >> 2] | 0;
+ $35 = HEAP32[76] | 0;
+ $cmp61 = $29 >>> 0 < $35 >>> 0;
+ if ($cmp61) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $call63 = _agxbmore(296, 1) | 0;
+ label = 17;
+ break;
+ case 17:
+ $36 = HEAP32[75] | 0;
+ HEAP8[$36] = 0;
+ $37 = HEAP32[74] | 0;
+ HEAP32[75] = $37;
+ $call71 = _agxset($31, $34, $37) | 0;
+ label = 18;
+ break;
+ case 18:
+ $38 = HEAP32[79] | 0;
+ $39 = HEAP32[78] | 0;
+ $tobool78 = ($38 | 0) == ($39 | 0);
+ if ($tobool78) {
+ label = 22;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $40 = $1 | 0;
+ $41 = HEAP32[40] | 0;
+ $tl_draw = $41 + 36 | 0;
+ $42 = HEAP32[$tl_draw >> 2] | 0;
+ $index80 = $42 + 8 | 0;
+ $43 = HEAP32[$index80 >> 2] | 0;
+ $44 = HEAP32[80] | 0;
+ $cmp83 = $38 >>> 0 < $44 >>> 0;
+ if ($cmp83) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $call85 = _agxbmore(312, 1) | 0;
+ label = 21;
+ break;
+ case 21:
+ $45 = HEAP32[79] | 0;
+ HEAP8[$45] = 0;
+ $46 = HEAP32[78] | 0;
+ HEAP32[79] = $46;
+ $call93 = _agxset($40, $43, $46) | 0;
+ label = 22;
+ break;
+ case 22:
+ $47 = HEAP32[83] | 0;
+ $48 = HEAP32[82] | 0;
+ $tobool100 = ($47 | 0) == ($48 | 0);
+ if ($tobool100) {
+ label = 26;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $49 = $1 | 0;
+ $50 = HEAP32[40] | 0;
+ $hl_draw = $50 + 32 | 0;
+ $51 = HEAP32[$hl_draw >> 2] | 0;
+ $index102 = $51 + 8 | 0;
+ $52 = HEAP32[$index102 >> 2] | 0;
+ $53 = HEAP32[84] | 0;
+ $cmp105 = $47 >>> 0 < $53 >>> 0;
+ if ($cmp105) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $call107 = _agxbmore(328, 1) | 0;
+ label = 25;
+ break;
+ case 25:
+ $54 = HEAP32[83] | 0;
+ HEAP8[$54] = 0;
+ $55 = HEAP32[82] | 0;
+ HEAP32[83] = $55;
+ $call115 = _agxset($49, $52, $55) | 0;
+ label = 26;
+ break;
+ case 26:
+ HEAPF64[907] = 1.0;
+ HEAPF64[909] = 1.0;
+ HEAPF64[900] = 1.0;
+ HEAPF64[901] = 1.0;
+ HEAPF64[904] = 1.0;
+ HEAPF64[905] = 1.0;
+ return;
+ }
+}
+function _xdot_textpara($job, $p, $para) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $para = $para | 0;
+ var $buf = 0, $obj = 0, $0 = 0, $emit_state1 = 0, $1 = 0, $arraydecay = 0, $fontsize = 0, $2 = 0.0, $call = 0, $arrayidx = 0, $3 = 0, $call3 = 0, $fontname = 0, $4 = 0, $just = 0, $5 = 0, $conv = 0, $j_0 = 0, $6 = 0, $call7 = 0, $7 = 0, $width = 0, $8 = 0.0, $conv10 = 0, $call11 = 0, $9 = 0, $call14 = 0, $str = 0, $10 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $emit_state1 = $0 + 12 | 0;
+ $1 = HEAP32[$emit_state1 >> 2] | 0;
+ $arraydecay = $buf | 0;
+ $fontsize = $para + 24 | 0;
+ $2 = +HEAPF64[$fontsize >> 3];
+ $call = _sprintf($arraydecay | 0, 127824, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $2, tempInt) | 0) | 0;
+ $arrayidx = 168 + ($1 << 2) | 0;
+ $3 = HEAP32[$arrayidx >> 2] | 0;
+ $call3 = _agxbput($3, $arraydecay) | 0;
+ $fontname = $para + 20 | 0;
+ $4 = HEAP32[$fontname >> 2] | 0;
+ _xdot_str($job, 125984, $4);
+ _xdot_pencolor($job);
+ $just = $para + 72 | 0;
+ $5 = HEAP8[$just] | 0;
+ $conv = $5 << 24 >> 24;
+ if (($conv | 0) == 114) {
+ label = 3;
+ break;
+ } else if (($conv | 0) == 108) {
+ $j_0 = -1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $j_0 = 1;
+ label = 5;
+ break;
+ case 4:
+ $j_0 = 0;
+ label = 5;
+ break;
+ case 5:
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ $call7 = _agxbput($6, 125184) | 0;
+ $7 = HEAP32[$arrayidx >> 2] | 0;
+ _output_point($7, $p);
+ $width = $para + 56 | 0;
+ $8 = +HEAPF64[$width >> 3];
+ $conv10 = ~~$8;
+ $call11 = _sprintf($arraydecay | 0, 155152, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $j_0, HEAP32[tempInt + 8 >> 2] = $conv10, tempInt) | 0) | 0;
+ $9 = HEAP32[$arrayidx >> 2] | 0;
+ $call14 = _agxbput($9, $arraydecay) | 0;
+ $str = $para | 0;
+ $10 = HEAP32[$str >> 2] | 0;
+ _xdot_str($job, 125984, $10);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _xdot_ellipse($job, $A, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $filled = $filled | 0;
+ var $buf = 0, $obj = 0, $0 = 0, $emit_state1 = 0, $1 = 0, $tobool = 0, $arrayidx = 0, $2 = 0, $call = 0, $arrayidx2 = 0, $3 = 0, $call3 = 0, $arrayidx4 = 0, $4 = 0, $arraydecay = 0, $x = 0, $5 = 0.0, $x8 = 0, $6 = 0.0, $sub = 0.0, $cmp = 0, $add = 0.0, $sub19 = 0.0, $add_sink = 0.0, $conv = 0, $y = 0, $7 = 0.0, $y23 = 0, $8 = 0.0, $sub24 = 0.0, $cmp25 = 0, $add33 = 0.0, $sub41 = 0.0, $add33_sink = 0.0, $conv34 = 0, $call45 = 0, $9 = 0, $call48 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $emit_state1 = $0 + 12 | 0;
+ $1 = HEAP32[$emit_state1 >> 2] | 0;
+ _xdot_style($job);
+ _xdot_pencolor($job);
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _xdot_fillcolor($job);
+ $arrayidx = 168 + ($1 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $call = _agxbput($2, 131760) | 0;
+ label = 5;
+ break;
+ case 4:
+ $arrayidx2 = 168 + ($1 << 2) | 0;
+ $3 = HEAP32[$arrayidx2 >> 2] | 0;
+ $call3 = _agxbput($3, 129944) | 0;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx4 = 168 + ($1 << 2) | 0;
+ $4 = HEAP32[$arrayidx4 >> 2] | 0;
+ _output_point($4, $A);
+ $arraydecay = $buf | 0;
+ $x = $A + 16 | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $x8 = $A | 0;
+ $6 = +HEAPF64[$x8 >> 3];
+ $sub = $5 - $6;
+ $cmp = $sub < 0.0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $add = $sub + .5;
+ $add_sink = $add;
+ label = 8;
+ break;
+ case 7:
+ $sub19 = $sub + -.5;
+ $add_sink = $sub19;
+ label = 8;
+ break;
+ case 8:
+ $conv = ~~$add_sink;
+ $y = $A + 24 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $y23 = $A + 8 | 0;
+ $8 = +HEAPF64[$y23 >> 3];
+ $sub24 = $7 - $8;
+ $cmp25 = $sub24 < 0.0;
+ if ($cmp25) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add33 = $sub24 + .5;
+ $add33_sink = $add33;
+ label = 11;
+ break;
+ case 10:
+ $sub41 = $sub24 + -.5;
+ $add33_sink = $sub41;
+ label = 11;
+ break;
+ case 11:
+ $conv34 = ~~$add33_sink;
+ $call45 = _sprintf($arraydecay | 0, 155152, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $conv, HEAP32[tempInt + 8 >> 2] = $conv34, tempInt) | 0) | 0;
+ $9 = HEAP32[$arrayidx4 >> 2] | 0;
+ $call48 = _agxbput($9, $arraydecay) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _xdot_polygon($job, $A, $n, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _xdot_style($job);
+ _xdot_pencolor($job);
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _xdot_fillcolor($job);
+ _xdot_points($job, 80, $A, $n);
+ label = 5;
+ break;
+ case 4:
+ _xdot_points($job, 112, $A, $n);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _xdot_bezier($job, $A, $n, $arrow_at_start, $arrow_at_end, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $arrow_at_start = $arrow_at_start | 0;
+ $arrow_at_end = $arrow_at_end | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ _xdot_style($job);
+ _xdot_pencolor($job);
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _xdot_fillcolor($job);
+ _xdot_points($job, 98, $A, $n);
+ label = 5;
+ break;
+ case 4:
+ _xdot_points($job, 66, $A, $n);
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _xdot_polyline($job, $A, $n) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ _xdot_style($job);
+ _xdot_pencolor($job);
+ _xdot_points($job, 76, $A, $n);
+ return;
+}
+function _xdot_style($job) {
+ $job = $job | 0;
+ var $buf = 0, $xbuf = 0, $obj = 0, $0 = 0, $penwidth = 0, $1 = 0.0, $emit_state = 0, $2 = 0, $arrayidx = 0, $3 = 0.0, $cmp = 0, $arraydecay = 0, $4 = 0, $penwidth8 = 0, $5 = 0.0, $call = 0, $6 = 0, $rawstyle = 0, $7 = 0, $tobool = 0, $arraydecay13 = 0, $8 = 0, $tobool1427 = 0, $ptr87 = 0, $eptr88 = 0, $buf98 = 0, $ptr = 0, $eptr = 0, $9 = 0, $_pn = 0, $incdec_ptr28 = 0, $10 = 0, $cmp16 = 0, $call18 = 0, $tobool19 = 0, $_pr = 0, $11 = 0, $cmp22 = 0, $call25 = 0, $tobool26 = 0, $12 = 0, $cmp30 = 0, $call33 = 0, $tobool34 = 0, $call37 = 0, $p_0 = 0, $13 = 0, $tobool39 = 0, $incdec_ptr41 = 0, $14 = 0, $tobool43 = 0, $15 = 0, $16 = 0, $cmp45 = 0, $call47 = 0, $17 = 0, $incdec_ptr49 = 0, $18 = 0, $tobool5123 = 0, $more_025 = 0, $p_124 = 0, $tobool53 = 0, $19 = 0, $20 = 0, $cmp57 = 0, $call60 = 0, $21 = 0, $incdec_ptr65 = 0, $call67 = 0, $p_2 = 0, $22 = 0, $tobool69 = 0, $incdec_ptr71 = 0, $inc = 0, $23 = 0, $tobool51 = 0, $24 = 0, $25 = 0, $cmp77 = 0, $call80 = 0, $26 = 0, $incdec_ptr85 = 0, $27 = 0, $28 = 0, $cmp89 = 0, $call92 = 0, $29 = 0, $30 = 0, $31 = 0, $tobool14 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1040 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $xbuf = __stackBase__ + 1024 | 0;
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $penwidth = $0 + 104 | 0;
+ $1 = +HEAPF64[$penwidth >> 3];
+ $emit_state = $0 + 12 | 0;
+ $2 = HEAP32[$emit_state >> 2] | 0;
+ $arrayidx = 7184 + ($2 << 3) | 0;
+ $3 = +HEAPF64[$arrayidx >> 3];
+ $cmp = $1 != $3;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAPF64[$arrayidx >> 3] = $1;
+ $arraydecay = $buf | 0;
+ $4 = HEAP32[$obj >> 2] | 0;
+ $penwidth8 = $4 + 104 | 0;
+ $5 = +HEAPF64[$penwidth8 >> 3];
+ $call = _sprintf($arraydecay | 0, 148408, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $5, tempInt) | 0) | 0;
+ _xdot_str($job, 145648, $arraydecay);
+ label = 4;
+ break;
+ case 4:
+ $6 = HEAP32[$obj >> 2] | 0;
+ $rawstyle = $6 + 112 | 0;
+ $7 = HEAP32[$rawstyle >> 2] | 0;
+ $tobool = ($7 | 0) == 0;
+ if ($tobool) {
+ label = 35;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $arraydecay13 = $buf | 0;
+ _agxbinit($xbuf, 1024, $arraydecay13);
+ $8 = HEAP32[$7 >> 2] | 0;
+ $tobool1427 = ($8 | 0) == 0;
+ if ($tobool1427) {
+ label = 34;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $ptr87 = $xbuf + 4 | 0;
+ $eptr88 = $xbuf + 8 | 0;
+ $buf98 = $xbuf | 0;
+ $ptr = $xbuf + 4 | 0;
+ $eptr = $xbuf + 8 | 0;
+ $_pn = $7;
+ $9 = $8;
+ label = 7;
+ break;
+ case 7:
+ $incdec_ptr28 = $_pn + 4 | 0;
+ $10 = HEAP8[$9] | 0;
+ $cmp16 = $10 << 24 >> 24 == 102;
+ if ($cmp16) {
+ label = 8;
+ break;
+ } else {
+ $11 = $10;
+ label = 10;
+ break;
+ }
+ case 8:
+ $call18 = _strcmp($9 | 0, 142608) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 33;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $_pr = HEAP8[$9] | 0;
+ $11 = $_pr;
+ label = 10;
+ break;
+ case 10:
+ $cmp22 = $11 << 24 >> 24 == 98;
+ if ($cmp22) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $call25 = _strcmp($9 | 0, 139112) | 0;
+ $tobool26 = ($call25 | 0) == 0;
+ if ($tobool26) {
+ label = 33;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $12 = HEAP8[$9] | 0;
+ $cmp30 = $12 << 24 >> 24 == 115;
+ if ($cmp30) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $call33 = _strcmp($9 | 0, 136344) | 0;
+ $tobool34 = ($call33 | 0) == 0;
+ if ($tobool34) {
+ label = 33;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $call37 = _agxbput($xbuf, $9) | 0;
+ $p_0 = $9;
+ label = 15;
+ break;
+ case 15:
+ $13 = HEAP8[$p_0] | 0;
+ $tobool39 = $13 << 24 >> 24 == 0;
+ $incdec_ptr41 = $p_0 + 1 | 0;
+ if ($tobool39) {
+ label = 16;
+ break;
+ } else {
+ $p_0 = $incdec_ptr41;
+ label = 15;
+ break;
+ }
+ case 16:
+ $14 = HEAP8[$incdec_ptr41] | 0;
+ $tobool43 = $14 << 24 >> 24 == 0;
+ if ($tobool43) {
+ label = 30;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $15 = HEAP32[$ptr >> 2] | 0;
+ $16 = HEAP32[$eptr >> 2] | 0;
+ $cmp45 = $15 >>> 0 < $16 >>> 0;
+ if ($cmp45) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $call47 = _agxbmore($xbuf, 1) | 0;
+ label = 19;
+ break;
+ case 19:
+ $17 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr49 = $17 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr49;
+ HEAP8[$17] = 40;
+ $18 = HEAP8[$incdec_ptr41] | 0;
+ $tobool5123 = $18 << 24 >> 24 == 0;
+ if ($tobool5123) {
+ label = 27;
+ break;
+ } else {
+ $p_124 = $incdec_ptr41;
+ $more_025 = 0;
+ label = 20;
+ break;
+ }
+ case 20:
+ $tobool53 = ($more_025 | 0) == 0;
+ if ($tobool53) {
+ label = 24;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $19 = HEAP32[$ptr >> 2] | 0;
+ $20 = HEAP32[$eptr >> 2] | 0;
+ $cmp57 = $19 >>> 0 < $20 >>> 0;
+ if ($cmp57) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $call60 = _agxbmore($xbuf, 1) | 0;
+ label = 23;
+ break;
+ case 23:
+ $21 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr65 = $21 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr65;
+ HEAP8[$21] = 44;
+ label = 24;
+ break;
+ case 24:
+ $call67 = _agxbput($xbuf, $p_124) | 0;
+ $p_2 = $p_124;
+ label = 25;
+ break;
+ case 25:
+ $22 = HEAP8[$p_2] | 0;
+ $tobool69 = $22 << 24 >> 24 == 0;
+ $incdec_ptr71 = $p_2 + 1 | 0;
+ if ($tobool69) {
+ label = 26;
+ break;
+ } else {
+ $p_2 = $incdec_ptr71;
+ label = 25;
+ break;
+ }
+ case 26:
+ $inc = $more_025 + 1 | 0;
+ $23 = HEAP8[$incdec_ptr71] | 0;
+ $tobool51 = $23 << 24 >> 24 == 0;
+ if ($tobool51) {
+ label = 27;
+ break;
+ } else {
+ $p_124 = $incdec_ptr71;
+ $more_025 = $inc;
+ label = 20;
+ break;
+ }
+ case 27:
+ $24 = HEAP32[$ptr >> 2] | 0;
+ $25 = HEAP32[$eptr >> 2] | 0;
+ $cmp77 = $24 >>> 0 < $25 >>> 0;
+ if ($cmp77) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $call80 = _agxbmore($xbuf, 1) | 0;
+ label = 29;
+ break;
+ case 29:
+ $26 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr85 = $26 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr85;
+ HEAP8[$26] = 41;
+ label = 30;
+ break;
+ case 30:
+ $27 = HEAP32[$ptr87 >> 2] | 0;
+ $28 = HEAP32[$eptr88 >> 2] | 0;
+ $cmp89 = $27 >>> 0 < $28 >>> 0;
+ if ($cmp89) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $call92 = _agxbmore($xbuf, 1) | 0;
+ label = 32;
+ break;
+ case 32:
+ $29 = HEAP32[$ptr87 >> 2] | 0;
+ HEAP8[$29] = 0;
+ $30 = HEAP32[$buf98 >> 2] | 0;
+ HEAP32[$ptr87 >> 2] = $30;
+ _xdot_str($job, 145648, $30);
+ label = 33;
+ break;
+ case 33:
+ $31 = HEAP32[$incdec_ptr28 >> 2] | 0;
+ $tobool14 = ($31 | 0) == 0;
+ if ($tobool14) {
+ label = 34;
+ break;
+ } else {
+ $_pn = $incdec_ptr28;
+ $9 = $31;
+ label = 7;
+ break;
+ }
+ case 34:
+ _agxbfree($xbuf);
+ label = 35;
+ break;
+ case 35:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _xdot_pencolor($job) {
+ $job = $job | 0;
+ _color2str((HEAP32[$job + 16 >> 2] | 0) + 16 | 0);
+ _xdot_str($job, 153792, 53192);
+ return;
+}
+function _xdot_points($job, $c, $A, $n) {
+ $job = $job | 0;
+ $c = $c | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ var $buf = 0, $obj = 0, $0 = 0, $emit_state1 = 0, $1 = 0, $arrayidx = 0, $2 = 0, $ptr = 0, $3 = 0, $eptr = 0, $4 = 0, $cmp = 0, $call = 0, $5 = 0, $ptr5 = 0, $6 = 0, $incdec_ptr = 0, $arraydecay = 0, $call6 = 0, $7 = 0, $call9 = 0, $cmp109 = 0, $8 = 0, $i_010 = 0, $arrayidx13 = 0, $inc = 0, $cmp10 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1024 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $emit_state1 = $0 + 12 | 0;
+ $1 = HEAP32[$emit_state1 >> 2] | 0;
+ $arrayidx = 168 + ($1 << 2) | 0;
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $ptr = $2 + 4 | 0;
+ $3 = HEAP32[$ptr >> 2] | 0;
+ $eptr = $2 + 8 | 0;
+ $4 = HEAP32[$eptr >> 2] | 0;
+ $cmp = $3 >>> 0 < $4 >>> 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call = _agxbmore($2, 1) | 0;
+ label = 4;
+ break;
+ case 4:
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $ptr5 = $5 + 4 | 0;
+ $6 = HEAP32[$ptr5 >> 2] | 0;
+ $incdec_ptr = $6 + 1 | 0;
+ HEAP32[$ptr5 >> 2] = $incdec_ptr;
+ HEAP8[$6] = $c;
+ $arraydecay = $buf | 0;
+ $call6 = _sprintf($arraydecay | 0, 158640, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $n, tempInt) | 0) | 0;
+ $7 = HEAP32[$arrayidx >> 2] | 0;
+ $call9 = _agxbput($7, $arraydecay) | 0;
+ $cmp109 = ($n | 0) > 0;
+ if ($cmp109) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $8 = HEAP32[$arrayidx >> 2] | 0;
+ $i_010 = 0;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx13 = $A + ($i_010 << 4) | 0;
+ _output_point($8, $arrayidx13);
+ $inc = $i_010 + 1 | 0;
+ $cmp10 = ($inc | 0) < ($n | 0);
+ if ($cmp10) {
+ $i_010 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _color2str($rgba) {
+ $rgba = $rgba | 0;
+ var $conv2 = 0, $conv4 = 0, $conv6 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $conv2 = HEAPU8[$rgba + 1 | 0] | 0;
+ $conv4 = HEAPU8[$rgba + 2 | 0] | 0;
+ $conv6 = HEAPU8[$rgba + 3 | 0] | 0;
+ _sprintf(53192, 151688, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = HEAPU8[$rgba] | 0, HEAP32[tempInt + 8 >> 2] = $conv2, HEAP32[tempInt + 16 >> 2] = $conv4, HEAP32[tempInt + 24 >> 2] = $conv6, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _xdot_fillcolor($job) {
+ $job = $job | 0;
+ _color2str((HEAP32[$job + 16 >> 2] | 0) + 56 | 0);
+ _xdot_str($job, 134e3, 53192);
+ return;
+}
+function _fig_begin_page($job) {
+ $job = $job | 0;
+ HEAP32[41980] = 2;
+ return;
+}
+function _fig_begin_node($job) {
+ $job = $job | 0;
+ HEAP32[41980] = 1;
+ return;
+}
+function _fig_end_node($job) {
+ $job = $job | 0;
+ HEAP32[41980] = 2;
+ return;
+}
+function _fig_begin_edge($job) {
+ $job = $job | 0;
+ HEAP32[41980] = 0;
+ return;
+}
+function _fig_end_edge($job) {
+ $job = $job | 0;
+ HEAP32[41980] = 2;
+ return;
+}
+function _fig_line_style($obj, $line_style, $style_val) {
+ $obj = $obj | 0;
+ $line_style = $line_style | 0;
+ $style_val = $style_val | 0;
+ var $pen = 0, $0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pen = $obj + 96 | 0;
+ $0 = HEAP32[$pen >> 2] | 0;
+ if (($0 | 0) == 1) {
+ label = 3;
+ break;
+ } else if (($0 | 0) == 2) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ HEAP32[$line_style >> 2] = 1;
+ HEAPF64[$style_val >> 3] = 10.0;
+ label = 6;
+ break;
+ case 4:
+ HEAP32[$line_style >> 2] = 2;
+ HEAPF64[$style_val >> 3] = 10.0;
+ label = 6;
+ break;
+ case 5:
+ HEAP32[$line_style >> 2] = 0;
+ HEAPF64[$style_val >> 3] = 0.0;
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _xdot_end_graph($g) {
+ $g = $g | 0;
+ var $0 = 0, $1 = 0, $tobool = 0, $2 = 0, $g_draw = 0, $3 = 0, $tobool1 = 0, $4 = 0, $5 = 0, $call = 0, $6 = 0, $g_draw3 = 0, $7 = 0, $8 = 0, $g_draw4 = 0, $9 = 0, $index = 0, $10 = 0, $11 = 0, $12 = 0, $cmp = 0, $call6 = 0, $13 = 0, $14 = 0, $call10 = 0, $label = 0, $15 = 0, $tobool12 = 0, $16 = 0, $17 = 0, $g_l_draw = 0, $18 = 0, $index14 = 0, $19 = 0, $20 = 0, $21 = 0, $cmp17 = 0, $call19 = 0, $22 = 0, $23 = 0, $call27 = 0, $24 = 0, $call29 = 0, $25 = 0, $26 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[55] | 0;
+ $1 = HEAP32[54] | 0;
+ $tobool = ($0 | 0) == ($1 | 0);
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[40] | 0;
+ $g_draw = $2 | 0;
+ $3 = HEAP32[$g_draw >> 2] | 0;
+ $tobool1 = ($3 | 0) == 0;
+ if ($tobool1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $4 = $g | 0;
+ $5 = $g;
+ $call = _safe_dcl($5, $4, 123216, 125984, 360) | 0;
+ $6 = HEAP32[40] | 0;
+ $g_draw3 = $6 | 0;
+ HEAP32[$g_draw3 >> 2] = $call;
+ label = 5;
+ break;
+ case 5:
+ $7 = $g | 0;
+ $8 = HEAP32[40] | 0;
+ $g_draw4 = $8 | 0;
+ $9 = HEAP32[$g_draw4 >> 2] | 0;
+ $index = $9 + 8 | 0;
+ $10 = HEAP32[$index >> 2] | 0;
+ $11 = HEAP32[55] | 0;
+ $12 = HEAP32[56] | 0;
+ $cmp = $11 >>> 0 < $12 >>> 0;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call6 = _agxbmore(216, 1) | 0;
+ label = 7;
+ break;
+ case 7:
+ $13 = HEAP32[55] | 0;
+ HEAP8[$13] = 0;
+ $14 = HEAP32[54] | 0;
+ HEAP32[55] = $14;
+ $call10 = _agxset($7, $10, $14) | 0;
+ label = 8;
+ break;
+ case 8:
+ $label = $g + 52 | 0;
+ $15 = HEAP32[$label >> 2] | 0;
+ $tobool12 = ($15 | 0) == 0;
+ if ($tobool12) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $16 = $g | 0;
+ $17 = HEAP32[40] | 0;
+ $g_l_draw = $17 + 4 | 0;
+ $18 = HEAP32[$g_l_draw >> 2] | 0;
+ $index14 = $18 + 8 | 0;
+ $19 = HEAP32[$index14 >> 2] | 0;
+ $20 = HEAP32[71] | 0;
+ $21 = HEAP32[72] | 0;
+ $cmp17 = $20 >>> 0 < $21 >>> 0;
+ if ($cmp17) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call19 = _agxbmore(280, 1) | 0;
+ label = 11;
+ break;
+ case 11:
+ $22 = HEAP32[71] | 0;
+ HEAP8[$22] = 0;
+ $23 = HEAP32[70] | 0;
+ HEAP32[71] = $23;
+ $call27 = _agxset($16, $19, $23) | 0;
+ label = 12;
+ break;
+ case 12:
+ $24 = $g | 0;
+ $call29 = _agsafeset($24, 121776, 121168, 125984) | 0;
+ _agxbfree(216);
+ _agxbfree(232);
+ _agxbfree(248);
+ _agxbfree(264);
+ _agxbfree(280);
+ _agxbfree(296);
+ _agxbfree(312);
+ _agxbfree(328);
+ $25 = HEAP32[40] | 0;
+ $26 = $25;
+ _free($26);
+ HEAPF64[898] = 1.0;
+ HEAPF64[902] = 1.0;
+ return;
+ }
+}
+function _xdot_begin_graph($g, $s_arrows, $e_arrows) {
+ $g = $g | 0;
+ $s_arrows = $s_arrows | 0;
+ $e_arrows = $e_arrows | 0;
+ var $call = 0, $0 = 0, $n_cluster = 0, $1 = 0, $tobool = 0, $2 = 0, $3 = 0, $call1 = 0, $4 = 0, $g_draw = 0, $g_draw2 = 0, $has_labels = 0, $5 = 0, $and = 0, $tobool4 = 0, $6 = 0, $7 = 0, $call6 = 0, $8 = 0, $g_l_draw = 0, $9 = 0, $g_l_draw8 = 0, $proto = 0, $10 = 0, $n = 0, $11 = 0, $12 = 0, $13 = 0, $call10 = 0, $14 = 0, $n_draw = 0, $15 = 0, $n12 = 0, $16 = 0, $17 = 0, $call13 = 0, $18 = 0, $n_l_draw = 0, $19 = 0, $e = 0, $20 = 0, $21 = 0, $call15 = 0, $22 = 0, $e_draw = 0, $tobool16 = 0, $23 = 0, $e19 = 0, $24 = 0, $25 = 0, $call20 = 0, $26 = 0, $h_draw = 0, $27 = 0, $h_draw22 = 0, $tobool24 = 0, $28 = 0, $e27 = 0, $29 = 0, $30 = 0, $call28 = 0, $31 = 0, $t_draw = 0, $32 = 0, $t_draw30 = 0, $33 = 0, $and35 = 0, $tobool36 = 0, $34 = 0, $e39 = 0, $35 = 0, $36 = 0, $call40 = 0, $37 = 0, $e_l_draw = 0, $38 = 0, $e_l_draw42 = 0, $39 = 0, $and47 = 0, $tobool48 = 0, $40 = 0, $e51 = 0, $41 = 0, $42 = 0, $call52 = 0, $43 = 0, $hl_draw = 0, $44 = 0, $hl_draw54 = 0, $45 = 0, $and59 = 0, $tobool60 = 0, $46 = 0, $e63 = 0, $47 = 0, $48 = 0, $call64 = 0, $49 = 0, $tl_draw = 0, $50 = 0, $tl_draw66 = 0, $51 = 0, $arraydecay = 0, $52 = 0, $arraydecay_1 = 0, $53 = 0, $arraydecay_2 = 0, $54 = 0, $arraydecay_3 = 0, $55 = 0, $arraydecay_4 = 0, $56 = 0, $arraydecay_5 = 0, $57 = 0, $arraydecay_6 = 0, $58 = 0, $arraydecay_7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _malloc(8232) | 0;
+ $0 = $call;
+ HEAP32[40] = $0;
+ $n_cluster = $g + 212 | 0;
+ $1 = HEAP32[$n_cluster >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $g | 0;
+ $3 = $g;
+ $call1 = _safe_dcl($3, $2, 123216, 125984, 360) | 0;
+ $4 = HEAP32[40] | 0;
+ $g_draw = $4 | 0;
+ HEAP32[$g_draw >> 2] = $call1;
+ label = 5;
+ break;
+ case 4:
+ $g_draw2 = $call;
+ HEAP32[$g_draw2 >> 2] = 0;
+ label = 5;
+ break;
+ case 5:
+ $has_labels = $g + 153 | 0;
+ $5 = HEAP8[$has_labels] | 0;
+ $and = $5 & 8;
+ $tobool4 = $and << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $6 = $g | 0;
+ $7 = $g;
+ $call6 = _safe_dcl($7, $6, 120480, 125984, 360) | 0;
+ $8 = HEAP32[40] | 0;
+ $g_l_draw = $8 + 4 | 0;
+ HEAP32[$g_l_draw >> 2] = $call6;
+ label = 8;
+ break;
+ case 7:
+ $9 = HEAP32[40] | 0;
+ $g_l_draw8 = $9 + 4 | 0;
+ HEAP32[$g_l_draw8 >> 2] = 0;
+ label = 8;
+ break;
+ case 8:
+ $proto = $g + 40 | 0;
+ $10 = HEAP32[$proto >> 2] | 0;
+ $n = $10 | 0;
+ $11 = HEAP32[$n >> 2] | 0;
+ $12 = $11 | 0;
+ $13 = $g;
+ $call10 = _safe_dcl($13, $12, 123216, 125984, 380) | 0;
+ $14 = HEAP32[40] | 0;
+ $n_draw = $14 + 8 | 0;
+ HEAP32[$n_draw >> 2] = $call10;
+ $15 = HEAP32[$proto >> 2] | 0;
+ $n12 = $15 | 0;
+ $16 = HEAP32[$n12 >> 2] | 0;
+ $17 = $16 | 0;
+ $call13 = _safe_dcl($13, $17, 120480, 125984, 380) | 0;
+ $18 = HEAP32[40] | 0;
+ $n_l_draw = $18 + 12 | 0;
+ HEAP32[$n_l_draw >> 2] = $call13;
+ $19 = HEAP32[$proto >> 2] | 0;
+ $e = $19 + 4 | 0;
+ $20 = HEAP32[$e >> 2] | 0;
+ $21 = $20 | 0;
+ $call15 = _safe_dcl($13, $21, 123216, 125984, 654) | 0;
+ $22 = HEAP32[40] | 0;
+ $e_draw = $22 + 16 | 0;
+ HEAP32[$e_draw >> 2] = $call15;
+ $tobool16 = ($e_arrows | 0) == 0;
+ if ($tobool16) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $23 = HEAP32[$proto >> 2] | 0;
+ $e19 = $23 + 4 | 0;
+ $24 = HEAP32[$e19 >> 2] | 0;
+ $25 = $24 | 0;
+ $call20 = _safe_dcl($13, $25, 119816, 125984, 654) | 0;
+ $26 = HEAP32[40] | 0;
+ $h_draw = $26 + 20 | 0;
+ HEAP32[$h_draw >> 2] = $call20;
+ label = 11;
+ break;
+ case 10:
+ $27 = HEAP32[40] | 0;
+ $h_draw22 = $27 + 20 | 0;
+ HEAP32[$h_draw22 >> 2] = 0;
+ label = 11;
+ break;
+ case 11:
+ $tobool24 = ($s_arrows | 0) == 0;
+ if ($tobool24) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $28 = HEAP32[$proto >> 2] | 0;
+ $e27 = $28 + 4 | 0;
+ $29 = HEAP32[$e27 >> 2] | 0;
+ $30 = $29 | 0;
+ $call28 = _safe_dcl($13, $30, 119280, 125984, 654) | 0;
+ $31 = HEAP32[40] | 0;
+ $t_draw = $31 + 24 | 0;
+ HEAP32[$t_draw >> 2] = $call28;
+ label = 14;
+ break;
+ case 13:
+ $32 = HEAP32[40] | 0;
+ $t_draw30 = $32 + 24 | 0;
+ HEAP32[$t_draw30 >> 2] = 0;
+ label = 14;
+ break;
+ case 14:
+ $33 = HEAP8[$has_labels] | 0;
+ $and35 = $33 & 1;
+ $tobool36 = $and35 << 24 >> 24 == 0;
+ if ($tobool36) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $34 = HEAP32[$proto >> 2] | 0;
+ $e39 = $34 + 4 | 0;
+ $35 = HEAP32[$e39 >> 2] | 0;
+ $36 = $35 | 0;
+ $call40 = _safe_dcl($13, $36, 120480, 125984, 654) | 0;
+ $37 = HEAP32[40] | 0;
+ $e_l_draw = $37 + 28 | 0;
+ HEAP32[$e_l_draw >> 2] = $call40;
+ label = 17;
+ break;
+ case 16:
+ $38 = HEAP32[40] | 0;
+ $e_l_draw42 = $38 + 28 | 0;
+ HEAP32[$e_l_draw42 >> 2] = 0;
+ label = 17;
+ break;
+ case 17:
+ $39 = HEAP8[$has_labels] | 0;
+ $and47 = $39 & 2;
+ $tobool48 = $and47 << 24 >> 24 == 0;
+ if ($tobool48) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $40 = HEAP32[$proto >> 2] | 0;
+ $e51 = $40 + 4 | 0;
+ $41 = HEAP32[$e51 >> 2] | 0;
+ $42 = $41 | 0;
+ $call52 = _safe_dcl($13, $42, 118736, 125984, 654) | 0;
+ $43 = HEAP32[40] | 0;
+ $hl_draw = $43 + 32 | 0;
+ HEAP32[$hl_draw >> 2] = $call52;
+ label = 20;
+ break;
+ case 19:
+ $44 = HEAP32[40] | 0;
+ $hl_draw54 = $44 + 32 | 0;
+ HEAP32[$hl_draw54 >> 2] = 0;
+ label = 20;
+ break;
+ case 20:
+ $45 = HEAP8[$has_labels] | 0;
+ $and59 = $45 & 4;
+ $tobool60 = $and59 << 24 >> 24 == 0;
+ if ($tobool60) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $46 = HEAP32[$proto >> 2] | 0;
+ $e63 = $46 + 4 | 0;
+ $47 = HEAP32[$e63 >> 2] | 0;
+ $48 = $47 | 0;
+ $call64 = _safe_dcl($13, $48, 118152, 125984, 654) | 0;
+ $49 = HEAP32[40] | 0;
+ $tl_draw = $49 + 36 | 0;
+ HEAP32[$tl_draw >> 2] = $call64;
+ label = 23;
+ break;
+ case 22:
+ $50 = HEAP32[40] | 0;
+ $tl_draw66 = $50 + 36 | 0;
+ HEAP32[$tl_draw66 >> 2] = 0;
+ label = 23;
+ break;
+ case 23:
+ $51 = HEAP32[40] | 0;
+ $arraydecay = $51 + 40 | 0;
+ _agxbinit(216, 1024, $arraydecay);
+ $52 = HEAP32[40] | 0;
+ $arraydecay_1 = $52 + 1064 | 0;
+ _agxbinit(232, 1024, $arraydecay_1);
+ $53 = HEAP32[40] | 0;
+ $arraydecay_2 = $53 + 2088 | 0;
+ _agxbinit(248, 1024, $arraydecay_2);
+ $54 = HEAP32[40] | 0;
+ $arraydecay_3 = $54 + 3112 | 0;
+ _agxbinit(264, 1024, $arraydecay_3);
+ $55 = HEAP32[40] | 0;
+ $arraydecay_4 = $55 + 4136 | 0;
+ _agxbinit(280, 1024, $arraydecay_4);
+ $56 = HEAP32[40] | 0;
+ $arraydecay_5 = $56 + 5160 | 0;
+ _agxbinit(296, 1024, $arraydecay_5);
+ $57 = HEAP32[40] | 0;
+ $arraydecay_6 = $57 + 6184 | 0;
+ _agxbinit(312, 1024, $arraydecay_6);
+ $58 = HEAP32[40] | 0;
+ $arraydecay_7 = $58 + 7208 | 0;
+ _agxbinit(328, 1024, $arraydecay_7);
+ return;
+ }
+}
+function _fig_begin_graph($job) {
+ $job = $job | 0;
+ var $0 = 0, $1 = 0, $3 = 0, $5 = 0, $6 = 0, $mul = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $0 = HEAP32[$job + 16 >> 2] | 0;
+ $1 = $job;
+ _gvputs($1, 121576);
+ $3 = HEAP32[HEAP32[$job + 12 >> 2] >> 2] | 0;
+ $5 = HEAP32[$3 + 4 >> 2] | 0;
+ $6 = HEAP32[$3 + 8 >> 2] | 0;
+ _gvprintf($1, 120936, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = HEAP32[$3 >> 2] | 0, HEAP32[tempInt + 8 >> 2] = $5, HEAP32[tempInt + 16 >> 2] = $6, tempInt) | 0);
+ _gvprintf($1, 120208, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = HEAP32[(HEAP32[$0 + 8 >> 2] | 0) + 12 >> 2] | 0, tempInt) | 0);
+ $mul = Math_imul(HEAP32[$job + 168 >> 2] | 0, HEAP32[$job + 164 >> 2] | 0);
+ _gvprintf($1, 119592, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $mul, tempInt) | 0);
+ _gvputs($1, 119032);
+ _gvputs($1, 118568);
+ _gvputs($1, 117936);
+ _gvputs($1, 117352);
+ _gvputs($1, 116720);
+ _gvputs($1, 116416);
+ _gvputs($1, 115904);
+ _gvputs($1, 115472);
+ _gvputs($1, 114920);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _fig_end_graph($job) {
+ $job = $job | 0;
+ _gvputs($job, 122592);
+ return;
+}
+function _fig_textpara($job, $p, $para) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $para = $para | 0;
+ var $obj1 = 0, $0 = 0, $u = 0, $index = 0, $1 = 0, $2 = 0, $fontsize = 0, $3 = 0.0, $zoom = 0, $4 = 0.0, $mul = 0.0, $rotation = 0, $5 = 0, $tobool = 0, $cond = 0.0, $postscript_alias = 0, $6 = 0, $tobool2 = 0, $xfig_code = 0, $7 = 0, $font_0 = 0, $just = 0, $8 = 0, $conv = 0, $sub_type_0 = 0, $x = 0, $9 = 0.0, $cmp = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv8 = 0, $y = 0, $10 = 0.0, $cmp12 = 0, $add16 = 0.0, $sub20 = 0.0, $add16_sink = 0.0, $conv17 = 0, $str = 0, $11 = 0, $call = 0, $12 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $u = $0 + 16 | 0;
+ $index = $u;
+ $1 = HEAP32[$index >> 2] | 0;
+ $2 = HEAP32[41980] | 0;
+ $fontsize = $para + 24 | 0;
+ $3 = +HEAPF64[$fontsize >> 3];
+ $zoom = $job + 352 | 0;
+ $4 = +HEAPF64[$zoom >> 3];
+ $mul = $3 * $4;
+ $rotation = $job + 360 | 0;
+ $5 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($5 | 0) != 0;
+ $cond = $tobool ? 1.5707963267948966 : 0.0;
+ $postscript_alias = $para + 4 | 0;
+ $6 = HEAP32[$postscript_alias >> 2] | 0;
+ $tobool2 = ($6 | 0) == 0;
+ if ($tobool2) {
+ $font_0 = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $xfig_code = $6 + 20 | 0;
+ $7 = HEAP32[$xfig_code >> 2] | 0;
+ $font_0 = $7;
+ label = 4;
+ break;
+ case 4:
+ $just = $para + 72 | 0;
+ $8 = HEAP8[$just] | 0;
+ $conv = $8 << 24 >> 24;
+ if (($conv | 0) == 114) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 108) {
+ $sub_type_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $sub_type_0 = 2;
+ label = 7;
+ break;
+ case 6:
+ $sub_type_0 = 1;
+ label = 7;
+ break;
+ case 7:
+ $x = $p | 0;
+ $9 = +HEAPF64[$x >> 3];
+ $cmp = $9 < 0.0;
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $add = $9 + .5;
+ $add_sink = $add;
+ label = 10;
+ break;
+ case 9:
+ $sub = $9 + -.5;
+ $add_sink = $sub;
+ label = 10;
+ break;
+ case 10:
+ $conv8 = ~~$add_sink;
+ $y = $p + 8 | 0;
+ $10 = +HEAPF64[$y >> 3];
+ $cmp12 = $10 < 0.0;
+ if ($cmp12) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $add16 = $10 + .5;
+ $add16_sink = $add16;
+ label = 13;
+ break;
+ case 12:
+ $sub20 = $10 + -.5;
+ $add16_sink = $sub20;
+ label = 13;
+ break;
+ case 13:
+ $conv17 = ~~$add16_sink;
+ $str = $para | 0;
+ $11 = HEAP32[$str >> 2] | 0;
+ $call = _fig_string($11) | 0;
+ $12 = $job;
+ _gvprintf($12, 126944, (tempInt = STACKTOP, STACKTOP = STACKTOP + 112 | 0, HEAP32[tempInt >> 2] = 4, HEAP32[tempInt + 8 >> 2] = $sub_type_0, HEAP32[tempInt + 16 >> 2] = $1, HEAP32[tempInt + 24 >> 2] = $2, HEAP32[tempInt + 32 >> 2] = 0, HEAP32[tempInt + 40 >> 2] = $font_0, HEAPF64[tempInt + 48 >> 3] = $mul, HEAPF64[tempInt + 56 >> 3] = $cond, HEAP32[tempInt + 64 >> 2] = 6, HEAPF64[tempInt + 72 >> 3] = 0.0, HEAPF64[tempInt + 80 >> 3] = 0.0, HEAP32[tempInt + 88 >> 2] = $conv8, HEAP32[tempInt + 96 >> 2] = $conv17, HEAP32[tempInt + 104 >> 2] = $call, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _fig_ellipse($job, $A, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $filled = $filled | 0;
+ var $line_style = 0, $style_val = 0, $obj1 = 0, $0 = 0, $penwidth = 0, $1 = 0.0, $conv = 0, $u = 0, $index = 0, $2 = 0, $u2 = 0, $index3 = 0, $3 = 0, $4 = 0, $tobool = 0, $cond = 0, $x = 0, $5 = 0.0, $cmp = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv7 = 0, $y = 0, $6 = 0.0, $cmp13 = 0, $add18 = 0.0, $sub23 = 0.0, $add18_sink = 0.0, $conv19 = 0, $x28 = 0, $7 = 0.0, $8 = 0.0, $sub31 = 0.0, $cmp32 = 0, $add40 = 0.0, $sub48 = 0.0, $add40_sink = 0.0, $conv41 = 0, $y53 = 0, $9 = 0.0, $10 = 0.0, $sub56 = 0.0, $cmp57 = 0, $add65 = 0.0, $sub73 = 0.0, $add65_sink = 0.0, $conv66 = 0, $11 = 0.0, $cmp79 = 0, $add84 = 0.0, $sub89 = 0.0, $add84_sink = 0.0, $conv85 = 0, $12 = 0.0, $cmp95 = 0, $add100 = 0.0, $sub105 = 0.0, $add100_sink = 0.0, $conv101 = 0, $13 = 0, $14 = 0.0, $15 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $line_style = __stackBase__ | 0;
+ $style_val = __stackBase__ + 8 | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $penwidth = $0 + 104 | 0;
+ $1 = +HEAPF64[$penwidth >> 3];
+ $conv = ~~$1;
+ $u = $0 + 16 | 0;
+ $index = $u;
+ $2 = HEAP32[$index >> 2] | 0;
+ $u2 = $0 + 56 | 0;
+ $index3 = $u2;
+ $3 = HEAP32[$index3 >> 2] | 0;
+ $4 = HEAP32[41980] | 0;
+ $tobool = ($filled | 0) != 0;
+ $cond = $tobool ? 20 : -1;
+ _fig_line_style($0, $line_style, $style_val);
+ $x = $A | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $cmp = $5 < 0.0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $5 + .5;
+ $add_sink = $add;
+ label = 5;
+ break;
+ case 4:
+ $sub = $5 + -.5;
+ $add_sink = $sub;
+ label = 5;
+ break;
+ case 5:
+ $conv7 = ~~$add_sink;
+ $y = $A + 8 | 0;
+ $6 = +HEAPF64[$y >> 3];
+ $cmp13 = $6 < 0.0;
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $add18 = $6 + .5;
+ $add18_sink = $add18;
+ label = 8;
+ break;
+ case 7:
+ $sub23 = $6 + -.5;
+ $add18_sink = $sub23;
+ label = 8;
+ break;
+ case 8:
+ $conv19 = ~~$add18_sink;
+ $x28 = $A + 16 | 0;
+ $7 = +HEAPF64[$x28 >> 3];
+ $8 = +HEAPF64[$x >> 3];
+ $sub31 = $7 - $8;
+ $cmp32 = $sub31 < 0.0;
+ if ($cmp32) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add40 = $sub31 + .5;
+ $add40_sink = $add40;
+ label = 11;
+ break;
+ case 10:
+ $sub48 = $sub31 + -.5;
+ $add40_sink = $sub48;
+ label = 11;
+ break;
+ case 11:
+ $conv41 = ~~$add40_sink;
+ $y53 = $A + 24 | 0;
+ $9 = +HEAPF64[$y53 >> 3];
+ $10 = +HEAPF64[$y >> 3];
+ $sub56 = $9 - $10;
+ $cmp57 = $sub56 < 0.0;
+ if ($cmp57) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $add65 = $sub56 + .5;
+ $add65_sink = $add65;
+ label = 14;
+ break;
+ case 13:
+ $sub73 = $sub56 + -.5;
+ $add65_sink = $sub73;
+ label = 14;
+ break;
+ case 14:
+ $conv66 = ~~$add65_sink;
+ $11 = +HEAPF64[$x28 >> 3];
+ $cmp79 = $11 < 0.0;
+ if ($cmp79) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $add84 = $11 + .5;
+ $add84_sink = $add84;
+ label = 17;
+ break;
+ case 16:
+ $sub89 = $11 + -.5;
+ $add84_sink = $sub89;
+ label = 17;
+ break;
+ case 17:
+ $conv85 = ~~$add84_sink;
+ $12 = +HEAPF64[$y53 >> 3];
+ $cmp95 = $12 < 0.0;
+ if ($cmp95) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $add100 = $12 + .5;
+ $add100_sink = $add100;
+ label = 20;
+ break;
+ case 19:
+ $sub105 = $12 + -.5;
+ $add100_sink = $sub105;
+ label = 20;
+ break;
+ case 20:
+ $conv101 = ~~$add100_sink;
+ $13 = HEAP32[$line_style >> 2] | 0;
+ $14 = +HEAPF64[$style_val >> 3];
+ $15 = $job;
+ _gvprintf($15, 133128, (tempInt = STACKTOP, STACKTOP = STACKTOP + 160 | 0, HEAP32[tempInt >> 2] = 1, HEAP32[tempInt + 8 >> 2] = 1, HEAP32[tempInt + 16 >> 2] = $13, HEAP32[tempInt + 24 >> 2] = $conv, HEAP32[tempInt + 32 >> 2] = $2, HEAP32[tempInt + 40 >> 2] = $3, HEAP32[tempInt + 48 >> 2] = $4, HEAP32[tempInt + 56 >> 2] = 0, HEAP32[tempInt + 64 >> 2] = $cond, HEAPF64[tempInt + 72 >> 3] = $14, HEAP32[tempInt + 80 >> 2] = 0, HEAPF64[tempInt + 88 >> 3] = 0.0, HEAP32[tempInt + 96 >> 2] = $conv7, HEAP32[tempInt + 104 >> 2] = $conv19, HEAP32[tempInt + 112 >> 2] = $conv41, HEAP32[tempInt + 120 >> 2] = $conv66, HEAP32[tempInt + 128 >> 2] = $conv7, HEAP32[tempInt + 136 >> 2] = $conv19, HEAP32[tempInt + 144 >> 2] = $conv85, HEAP32[tempInt + 152 >> 2] = $conv101, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _fig_polygon($job, $A, $n, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $line_style = 0, $style_val = 0, $0 = 0, $conv = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0.0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $line_style = __stackBase__ | 0;
+ $style_val = __stackBase__ + 8 | 0;
+ $0 = HEAP32[$job + 16 >> 2] | 0;
+ $conv = ~~+HEAPF64[$0 + 104 >> 3];
+ $2 = HEAP32[$0 + 16 >> 2] | 0;
+ $3 = HEAP32[$0 + 56 >> 2] | 0;
+ $4 = HEAP32[41980] | 0;
+ _fig_line_style($0, $line_style, $style_val);
+ $5 = HEAP32[$line_style >> 2] | 0;
+ $6 = +HEAPF64[$style_val >> 3];
+ _gvprintf($job, 157904, (tempInt = STACKTOP, STACKTOP = STACKTOP + 128 | 0, HEAP32[tempInt >> 2] = 2, HEAP32[tempInt + 8 >> 2] = 3, HEAP32[tempInt + 16 >> 2] = $5, HEAP32[tempInt + 24 >> 2] = $conv, HEAP32[tempInt + 32 >> 2] = $2, HEAP32[tempInt + 40 >> 2] = $3, HEAP32[tempInt + 48 >> 2] = $4, HEAP32[tempInt + 56 >> 2] = 0, HEAP32[tempInt + 64 >> 2] = ($filled | 0) != 0 ? 20 : -1, HEAPF64[tempInt + 72 >> 3] = $6, HEAP32[tempInt + 80 >> 2] = 0, HEAP32[tempInt + 88 >> 2] = 0, HEAP32[tempInt + 96 >> 2] = 0, HEAP32[tempInt + 104 >> 2] = 0, HEAP32[tempInt + 112 >> 2] = 0, HEAP32[tempInt + 120 >> 2] = $n + 1 | 0, tempInt) | 0);
+ _figptarray($job, $A, $n, 1);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _fig_polyline($job, $A, $n) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ var $line_style = 0, $style_val = 0, $0 = 0, $conv = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0.0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ $line_style = __stackBase__ | 0;
+ $style_val = __stackBase__ + 8 | 0;
+ $0 = HEAP32[$job + 16 >> 2] | 0;
+ $conv = ~~+HEAPF64[$0 + 104 >> 3];
+ $2 = HEAP32[$0 + 16 >> 2] | 0;
+ $3 = HEAP32[41980] | 0;
+ _fig_line_style($0, $line_style, $style_val);
+ $4 = HEAP32[$line_style >> 2] | 0;
+ $5 = +HEAPF64[$style_val >> 3];
+ _gvprintf($job, 157904, (tempInt = STACKTOP, STACKTOP = STACKTOP + 128 | 0, HEAP32[tempInt >> 2] = 2, HEAP32[tempInt + 8 >> 2] = 1, HEAP32[tempInt + 16 >> 2] = $4, HEAP32[tempInt + 24 >> 2] = $conv, HEAP32[tempInt + 32 >> 2] = $2, HEAP32[tempInt + 40 >> 2] = 0, HEAP32[tempInt + 48 >> 2] = $3, HEAP32[tempInt + 56 >> 2] = 0, HEAP32[tempInt + 64 >> 2] = 0, HEAPF64[tempInt + 72 >> 3] = $5, HEAP32[tempInt + 80 >> 2] = 0, HEAP32[tempInt + 88 >> 2] = 0, HEAP32[tempInt + 96 >> 2] = 0, HEAP32[tempInt + 104 >> 2] = 0, HEAP32[tempInt + 112 >> 2] = 0, HEAP32[tempInt + 120 >> 2] = $n, tempInt) | 0);
+ _figptarray($job, $A, $n, 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _fig_comment($job, $str) {
+ $job = $job | 0;
+ $str = $str | 0;
+ var __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ _gvprintf($job, 161568, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $str, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _fig_resolve_color($job, $color) {
+ $job = $job | 0;
+ $color = $color | 0;
+ var $new = 0, $type = 0, $0 = 0, $string = 0, $1 = 0, $2 = 0, $call = 0, $tobool7 = 0, $i_019_lcssa = 0, $index = 0, $rgba = 0, $arrayidx11 = 0, $3 = 0, $conv12 = 0, $arrayidx15 = 0, $4 = 0, $conv16 = 0, $arrayidx19 = 0, $5 = 0, $conv20 = 0, $call21 = 0, $add = 0, $6 = 0, $tobool22 = 0, $7 = 0, $conv27 = 0, $8 = 0, $conv31 = 0, $9 = 0, $conv35 = 0, $10 = 0, $index38 = 0, $call_1 = 0, $tobool7_1 = 0, $call_2 = 0, $tobool7_2 = 0, $call_3 = 0, $tobool7_3 = 0, $call_4 = 0, $tobool7_4 = 0, $call_5 = 0, $tobool7_5 = 0, $call_6 = 0, $tobool7_6 = 0, $call_7 = 0, $tobool7_7 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $new = __stackBase__ | 0;
+ $type = $color + 32 | 0;
+ $0 = HEAP32[$type >> 2] | 0;
+ if (($0 | 0) == 5) {
+ label = 3;
+ break;
+ } else if (($0 | 0) == 1) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $string = $color;
+ $1 = HEAP32[$string >> 2] | 0;
+ $2 = HEAP8[$1] | 0;
+ if (($2 << 24 >> 24 | 0) == 98) {
+ label = 4;
+ break;
+ } else if (($2 << 24 >> 24 | 0) == 103) {
+ label = 12;
+ break;
+ } else if (($2 << 24 >> 24 | 0) == 99) {
+ label = 13;
+ break;
+ } else if (($2 << 24 >> 24 | 0) == 114) {
+ label = 14;
+ break;
+ } else if (($2 << 24 >> 24 | 0) == 109) {
+ label = 15;
+ break;
+ } else if (($2 << 24 >> 24 | 0) == 121) {
+ label = 16;
+ break;
+ } else if (($2 << 24 >> 24 | 0) == 119) {
+ label = 17;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 4:
+ $call = _strcmp(124032, $1 | 0) | 0;
+ $tobool7 = ($call | 0) == 0;
+ if ($tobool7) {
+ $i_019_lcssa = 0;
+ label = 5;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 5:
+ $index = $color;
+ HEAP32[$index >> 2] = $i_019_lcssa;
+ label = 10;
+ break;
+ case 6:
+ $rgba = $color;
+ $arrayidx11 = $color;
+ $3 = HEAP8[$arrayidx11] | 0;
+ $conv12 = $3 & 255;
+ $arrayidx15 = $rgba + 1 | 0;
+ $4 = HEAP8[$arrayidx15] | 0;
+ $conv16 = $4 & 255;
+ $arrayidx19 = $rgba + 2 | 0;
+ $5 = HEAP8[$arrayidx19] | 0;
+ $conv20 = $5 & 255;
+ $call21 = _figColorResolve($new, $conv12, $conv16, $conv20) | 0;
+ $add = $call21 + 32 | 0;
+ $6 = HEAP32[$new >> 2] | 0;
+ $tobool22 = ($6 | 0) == 0;
+ if ($tobool22) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $7 = HEAP8[$arrayidx11] | 0;
+ $conv27 = $7 & 255;
+ $8 = HEAP8[$arrayidx15] | 0;
+ $conv31 = $8 & 255;
+ $9 = HEAP8[$arrayidx19] | 0;
+ $conv35 = $9 & 255;
+ $10 = $job;
+ _gvprintf($10, 131208, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = 0, HEAP32[tempInt + 8 >> 2] = $add, HEAP32[tempInt + 16 >> 2] = $conv27, HEAP32[tempInt + 24 >> 2] = $conv31, HEAP32[tempInt + 32 >> 2] = $conv35, tempInt) | 0);
+ label = 8;
+ break;
+ case 8:
+ $index38 = $color;
+ HEAP32[$index38 >> 2] = $add;
+ label = 10;
+ break;
+ case 9:
+ ___assert_func(147824, 165, 164256, 129376);
+ case 10:
+ HEAP32[$type >> 2] = 6;
+ STACKTOP = __stackBase__;
+ return;
+ case 11:
+ $call_1 = _strcmp(116592, $1 | 0) | 0;
+ $tobool7_1 = ($call_1 | 0) == 0;
+ if ($tobool7_1) {
+ $i_019_lcssa = 1;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 12:
+ $call_2 = _strcmp(107144, $1 | 0) | 0;
+ $tobool7_2 = ($call_2 | 0) == 0;
+ if ($tobool7_2) {
+ $i_019_lcssa = 2;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 13:
+ $call_3 = _strcmp(111440, $1 | 0) | 0;
+ $tobool7_3 = ($call_3 | 0) == 0;
+ if ($tobool7_3) {
+ $i_019_lcssa = 3;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 14:
+ $call_4 = _strcmp(98984, $1 | 0) | 0;
+ $tobool7_4 = ($call_4 | 0) == 0;
+ if ($tobool7_4) {
+ $i_019_lcssa = 4;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 15:
+ $call_5 = _strcmp(103136, $1 | 0) | 0;
+ $tobool7_5 = ($call_5 | 0) == 0;
+ if ($tobool7_5) {
+ $i_019_lcssa = 5;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 16:
+ $call_6 = _strcmp(91416, $1 | 0) | 0;
+ $tobool7_6 = ($call_6 | 0) == 0;
+ if ($tobool7_6) {
+ $i_019_lcssa = 6;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 17:
+ $call_7 = _strcmp(94944, $1 | 0) | 0;
+ $tobool7_7 = ($call_7 | 0) == 0;
+ if ($tobool7_7) {
+ $i_019_lcssa = 7;
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ }
+}
+function _fig_bezier($job, $A, $n, $arrow_at_start, $arrow_at_end, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $arrow_at_start = $arrow_at_start | 0;
+ $arrow_at_end = $arrow_at_end | 0;
+ $filled = $filled | 0;
+ var $line_style = 0, $style_val = 0, $V = 0, $tmp = 0, $obj1 = 0, $0 = 0, $penwidth = 0, $1 = 0.0, $conv = 0, $u = 0, $index = 0, $2 = 0, $3 = 0, $cmp = 0, $4 = 0, $mul5 = 0, $call = 0, $tobool = 0, $5 = 0, $u9 = 0, $index10 = 0, $6 = 0, $area_fill_0 = 0, $fill_color_0 = 0, $sub_type_0 = 0, $x = 0, $7 = 0.0, $arrayidx11 = 0, $x12 = 0, $y = 0, $8 = 0.0, $y15 = 0, $9 = 0.0, $cmp18 = 0, $add23 = 0.0, $sub = 0.0, $add23_sink = 0.0, $conv24 = 0, $10 = 0.0, $cmp33 = 0, $add38 = 0.0, $sub43 = 0.0, $add38_sink = 0.0, $conv39 = 0, $call50 = 0, $cmp5251 = 0, $add_ptr = 0, $arrayidx54 = 0, $11 = 0, $12 = 0, $pf_sroa_0_0__idx = 0, $pf_sroa_1_8__idx22 = 0, $13 = 0, $add51 = 0, $cmp52 = 0, $add5155 = 0, $buf_054 = 0, $count_053 = 0, $i_052 = 0, $add60 = 0, $x62 = 0, $14 = 0.0, $x64 = 0, $y67 = 0, $15 = 0.0, $y69 = 0, $add60_1 = 0, $x62_1 = 0, $16 = 0.0, $x64_1 = 0, $y67_1 = 0, $17 = 0.0, $y69_1 = 0, $add60_2 = 0, $x62_2 = 0, $18 = 0.0, $x64_2 = 0, $y67_2 = 0, $19 = 0.0, $y69_2 = 0, $buf_150 = 0, $step_048 = 0, $conv76 = 0.0, $div = 0.0, $pf_sroa_0_0_copyload = 0.0, $pf_sroa_1_8_copyload = 0.0, $cmp78 = 0, $add82 = 0.0, $sub86 = 0.0, $add82_sink = 0.0, $conv83 = 0, $cmp92 = 0, $add96 = 0.0, $sub100 = 0.0, $add96_sink = 0.0, $conv97 = 0, $call107 = 0, $add_ptr108 = 0, $inc110 = 0, $cmp72 = 0, $count_0_lcssa = 0, $20 = 0, $21 = 0.0, $22 = 0, $cmp11645 = 0, $sub119 = 0, $i_146 = 0, $rem = 0, $tobool120 = 0, $cond121 = 0, $inc123 = 0, $cmp116 = 0, $call125 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 96 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $line_style = __stackBase__ | 0;
+ $style_val = __stackBase__ + 8 | 0;
+ $V = __stackBase__ + 16 | 0;
+ $tmp = __stackBase__ + 80 | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $penwidth = $0 + 104 | 0;
+ $1 = +HEAPF64[$penwidth >> 3];
+ $conv = ~~$1;
+ $u = $0 + 16 | 0;
+ $index = $u;
+ $2 = HEAP32[$index >> 2] | 0;
+ $3 = HEAP32[41980] | 0;
+ $cmp = ($n | 0) > 3;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ ___assert_func(147824, 354, 164280, 145040);
+ case 4:
+ $4 = $n * 140 & -1;
+ $mul5 = $4 + 140 | 0;
+ $call = _malloc($mul5) | 0;
+ _fig_line_style($0, $line_style, $style_val);
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ $sub_type_0 = 4;
+ $fill_color_0 = 0;
+ $area_fill_0 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[$obj1 >> 2] | 0;
+ $u9 = $5 + 56 | 0;
+ $index10 = $u9;
+ $6 = HEAP32[$index10 >> 2] | 0;
+ $sub_type_0 = 5;
+ $fill_color_0 = $6;
+ $area_fill_0 = 20;
+ label = 6;
+ break;
+ case 6:
+ $x = $A | 0;
+ $7 = +HEAPF64[$x >> 3];
+ $arrayidx11 = $V + 48 | 0;
+ $x12 = $arrayidx11 | 0;
+ HEAPF64[$x12 >> 3] = $7;
+ $y = $A + 8 | 0;
+ $8 = +HEAPF64[$y >> 3];
+ $y15 = $V + 56 | 0;
+ HEAPF64[$y15 >> 3] = $8;
+ $9 = +HEAPF64[$x >> 3];
+ $cmp18 = $9 < 0.0;
+ if ($cmp18) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add23 = $9 + .5;
+ $add23_sink = $add23;
+ label = 9;
+ break;
+ case 8:
+ $sub = $9 + -.5;
+ $add23_sink = $sub;
+ label = 9;
+ break;
+ case 9:
+ $conv24 = ~~$add23_sink;
+ $10 = +HEAPF64[$y >> 3];
+ $cmp33 = $10 < 0.0;
+ if ($cmp33) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $add38 = $10 + .5;
+ $add38_sink = $add38;
+ label = 12;
+ break;
+ case 11:
+ $sub43 = $10 + -.5;
+ $add38_sink = $sub43;
+ label = 12;
+ break;
+ case 12:
+ $conv39 = ~~$add38_sink;
+ $call50 = _sprintf($call | 0, 154544, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $conv24, HEAP32[tempInt + 8 >> 2] = $conv39, tempInt) | 0) | 0;
+ $cmp5251 = ($n | 0) > 3;
+ if ($cmp5251) {
+ label = 13;
+ break;
+ } else {
+ $count_0_lcssa = 1;
+ label = 23;
+ break;
+ }
+ case 13:
+ $add_ptr = $call + $call50 | 0;
+ $arrayidx54 = $V | 0;
+ $11 = $V;
+ $12 = $arrayidx11;
+ $pf_sroa_0_0__idx = $tmp | 0;
+ $pf_sroa_1_8__idx22 = $tmp + 8 | 0;
+ $i_052 = 0;
+ $count_053 = 1;
+ $buf_054 = $add_ptr;
+ $add5155 = 3;
+ label = 15;
+ break;
+ case 14:
+ $13 = $count_053 + 6 | 0;
+ $add51 = $add5155 + 3 | 0;
+ $cmp52 = ($add51 | 0) < ($n | 0);
+ if ($cmp52) {
+ $i_052 = $add5155;
+ $count_053 = $13;
+ $buf_054 = $add_ptr108;
+ $add5155 = $add51;
+ label = 15;
+ break;
+ } else {
+ $count_0_lcssa = $13;
+ label = 23;
+ break;
+ }
+ case 15:
+ HEAP32[$11 >> 2] = HEAP32[$12 >> 2] | 0;
+ HEAP32[$11 + 4 >> 2] = HEAP32[$12 + 4 >> 2] | 0;
+ HEAP32[$11 + 8 >> 2] = HEAP32[$12 + 8 >> 2] | 0;
+ HEAP32[$11 + 12 >> 2] = HEAP32[$12 + 12 >> 2] | 0;
+ $add60 = $i_052 + 1 | 0;
+ $x62 = $A + ($add60 << 4) | 0;
+ $14 = +HEAPF64[$x62 >> 3];
+ $x64 = $V + 16 | 0;
+ HEAPF64[$x64 >> 3] = $14;
+ $y67 = $A + ($add60 << 4) + 8 | 0;
+ $15 = +HEAPF64[$y67 >> 3];
+ $y69 = $V + 24 | 0;
+ HEAPF64[$y69 >> 3] = $15;
+ $add60_1 = $i_052 + 2 | 0;
+ $x62_1 = $A + ($add60_1 << 4) | 0;
+ $16 = +HEAPF64[$x62_1 >> 3];
+ $x64_1 = $V + 32 | 0;
+ HEAPF64[$x64_1 >> 3] = $16;
+ $y67_1 = $A + ($add60_1 << 4) + 8 | 0;
+ $17 = +HEAPF64[$y67_1 >> 3];
+ $y69_1 = $V + 40 | 0;
+ HEAPF64[$y69_1 >> 3] = $17;
+ $add60_2 = $i_052 + 3 | 0;
+ $x62_2 = $A + ($add60_2 << 4) | 0;
+ $18 = +HEAPF64[$x62_2 >> 3];
+ $x64_2 = $V + 48 | 0;
+ HEAPF64[$x64_2 >> 3] = $18;
+ $y67_2 = $A + ($add60_2 << 4) + 8 | 0;
+ $19 = +HEAPF64[$y67_2 >> 3];
+ $y69_2 = $V + 56 | 0;
+ HEAPF64[$y69_2 >> 3] = $19;
+ $step_048 = 1;
+ $buf_150 = $buf_054;
+ label = 16;
+ break;
+ case 16:
+ $conv76 = +($step_048 | 0);
+ $div = $conv76 / 6.0;
+ _Bezier($tmp, $arrayidx54, 3, $div, 0, 0);
+ $pf_sroa_0_0_copyload = +HEAPF64[$pf_sroa_0_0__idx >> 3];
+ $pf_sroa_1_8_copyload = +HEAPF64[$pf_sroa_1_8__idx22 >> 3];
+ $cmp78 = $pf_sroa_0_0_copyload < 0.0;
+ if ($cmp78) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $add82 = $pf_sroa_0_0_copyload + .5;
+ $add82_sink = $add82;
+ label = 19;
+ break;
+ case 18:
+ $sub86 = $pf_sroa_0_0_copyload + -.5;
+ $add82_sink = $sub86;
+ label = 19;
+ break;
+ case 19:
+ $conv83 = ~~$add82_sink;
+ $cmp92 = $pf_sroa_1_8_copyload < 0.0;
+ if ($cmp92) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $add96 = $pf_sroa_1_8_copyload + .5;
+ $add96_sink = $add96;
+ label = 22;
+ break;
+ case 21:
+ $sub100 = $pf_sroa_1_8_copyload + -.5;
+ $add96_sink = $sub100;
+ label = 22;
+ break;
+ case 22:
+ $conv97 = ~~$add96_sink;
+ $call107 = _sprintf($buf_150 | 0, 154544, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $conv83, HEAP32[tempInt + 8 >> 2] = $conv97, tempInt) | 0) | 0;
+ $add_ptr108 = $buf_150 + $call107 | 0;
+ $inc110 = $step_048 + 1 | 0;
+ $cmp72 = ($inc110 | 0) < 7;
+ if ($cmp72) {
+ $step_048 = $inc110;
+ $buf_150 = $add_ptr108;
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 23:
+ $20 = HEAP32[$line_style >> 2] | 0;
+ $21 = +HEAPF64[$style_val >> 3];
+ $22 = $job;
+ _gvprintf($22, 141968, (tempInt = STACKTOP, STACKTOP = STACKTOP + 112 | 0, HEAP32[tempInt >> 2] = 3, HEAP32[tempInt + 8 >> 2] = $sub_type_0, HEAP32[tempInt + 16 >> 2] = $20, HEAP32[tempInt + 24 >> 2] = $conv, HEAP32[tempInt + 32 >> 2] = $2, HEAP32[tempInt + 40 >> 2] = $fill_color_0, HEAP32[tempInt + 48 >> 2] = $3, HEAP32[tempInt + 56 >> 2] = 0, HEAP32[tempInt + 64 >> 2] = $area_fill_0, HEAPF64[tempInt + 72 >> 3] = $21, HEAP32[tempInt + 80 >> 2] = 0, HEAP32[tempInt + 88 >> 2] = 0, HEAP32[tempInt + 96 >> 2] = 0, HEAP32[tempInt + 104 >> 2] = $count_0_lcssa, tempInt) | 0);
+ _gvprintf($22, 138432, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call, tempInt) | 0);
+ _free($call);
+ $cmp11645 = ($count_0_lcssa | 0) > 0;
+ if ($cmp11645) {
+ label = 24;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 24:
+ $sub119 = $count_0_lcssa - 1 | 0;
+ $i_146 = 0;
+ label = 25;
+ break;
+ case 25:
+ $rem = ($i_146 | 0) % ($sub119 | 0);
+ $tobool120 = ($rem | 0) != 0;
+ $cond121 = $tobool120 & 1;
+ _gvprintf($22, 135680, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $cond121, tempInt) | 0);
+ $inc123 = $i_146 + 1 | 0;
+ $cmp116 = ($inc123 | 0) < ($count_0_lcssa | 0);
+ if ($cmp116) {
+ $i_146 = $inc123;
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $call125 = _gvputs($22, 150856) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _figColorResolve($new, $r, $g, $b) {
+ $new = $new | 0;
+ $r = $r | 0;
+ $g = $g | 0;
+ $b = $b | 0;
+ var $0 = 0, $cmp23 = 0, $inc1630 = 0, $1 = 0, $mindist_026 = 0, $c_025 = 0, $ct_024 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $sub = 0, $arrayidx1 = 0, $3 = 0, $conv2 = 0, $sub3 = 0, $arrayidx4 = 0, $4 = 0, $conv5 = 0, $sub6 = 0, $mul = 0, $mul7 = 0, $add = 0, $mul8 = 0, $add9 = 0, $cmp10 = 0, $cmp12 = 0, $ct_1 = 0, $mindist_1 = 0, $inc = 0, $cmp = 0, $inc16 = 0, $cmp17 = 0, $c_0_lcssa32 = 0, $conv21 = 0, $arrayidx22 = 0, $conv23 = 0, $arrayidx24 = 0, $conv25 = 0, $arrayidx26 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[$new >> 2] = 0;
+ $0 = HEAP32[4154] | 0;
+ $cmp23 = ($0 | 0) > 0;
+ if ($cmp23) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $inc1630 = $0 + 1 | 0;
+ HEAP32[4154] = $inc1630;
+ $c_0_lcssa32 = 0;
+ label = 9;
+ break;
+ case 4:
+ $1 = HEAP32[4154] | 0;
+ $ct_024 = -1;
+ $c_025 = 0;
+ $mindist_026 = 195075;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx = 16624 + ($c_025 << 1) | 0;
+ $2 = HEAP16[$arrayidx >> 1] | 0;
+ $conv = $2 << 16 >> 16;
+ $sub = $conv - $r | 0;
+ $arrayidx1 = 17136 + ($c_025 << 1) | 0;
+ $3 = HEAP16[$arrayidx1 >> 1] | 0;
+ $conv2 = $3 << 16 >> 16;
+ $sub3 = $conv2 - $g | 0;
+ $arrayidx4 = 17648 + ($c_025 << 1) | 0;
+ $4 = HEAP16[$arrayidx4 >> 1] | 0;
+ $conv5 = $4 << 16 >> 16;
+ $sub6 = $conv5 - $b | 0;
+ $mul = Math_imul($sub, $sub);
+ $mul7 = Math_imul($sub3, $sub3);
+ $add = $mul7 + $mul | 0;
+ $mul8 = Math_imul($sub6, $sub6);
+ $add9 = $add + $mul8 | 0;
+ $cmp10 = ($add9 | 0) < ($mindist_026 | 0);
+ if ($cmp10) {
+ label = 6;
+ break;
+ } else {
+ $mindist_1 = $mindist_026;
+ $ct_1 = $ct_024;
+ label = 7;
+ break;
+ }
+ case 6:
+ $cmp12 = ($add9 | 0) == 0;
+ if ($cmp12) {
+ $retval_0 = $c_025;
+ label = 10;
+ break;
+ } else {
+ $mindist_1 = $add9;
+ $ct_1 = $c_025;
+ label = 7;
+ break;
+ }
+ case 7:
+ $inc = $c_025 + 1 | 0;
+ $cmp = ($inc | 0) < ($1 | 0);
+ if ($cmp) {
+ $ct_024 = $ct_1;
+ $c_025 = $inc;
+ $mindist_026 = $mindist_1;
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $inc16 = $1 + 1 | 0;
+ HEAP32[4154] = $inc16;
+ $cmp17 = ($1 | 0) == 256;
+ if ($cmp17) {
+ $retval_0 = $ct_1;
+ label = 10;
+ break;
+ } else {
+ $c_0_lcssa32 = $inc;
+ label = 9;
+ break;
+ }
+ case 9:
+ $conv21 = $r & 65535;
+ $arrayidx22 = 16624 + ($c_0_lcssa32 << 1) | 0;
+ HEAP16[$arrayidx22 >> 1] = $conv21;
+ $conv23 = $g & 65535;
+ $arrayidx24 = 17136 + ($c_0_lcssa32 << 1) | 0;
+ HEAP16[$arrayidx24 >> 1] = $conv23;
+ $conv25 = $b & 65535;
+ $arrayidx26 = 17648 + ($c_0_lcssa32 << 1) | 0;
+ HEAP16[$arrayidx26 >> 1] = $conv25;
+ HEAP32[$new >> 2] = 1;
+ $retval_0 = $c_0_lcssa32;
+ label = 10;
+ break;
+ case 10:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _figptarray($job, $A, $n, $close) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $close = $close | 0;
+ var $cmp17 = 0, $0 = 0, $i_018 = 0, $x = 0, $1 = 0.0, $cmp1 = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $y = 0, $2 = 0.0, $cmp9 = 0, $add14 = 0.0, $sub19 = 0.0, $add14_sink = 0.0, $conv15 = 0, $inc = 0, $cmp = 0, $tobool = 0, $x27 = 0, $3 = 0.0, $cmp28 = 0, $add33 = 0.0, $sub38 = 0.0, $add33_sink = 0.0, $conv34 = 0, $y44 = 0, $4 = 0.0, $cmp45 = 0, $add50 = 0.0, $sub55 = 0.0, $add50_sink = 0.0, $conv51 = 0, $5 = 0, $6 = 0, $call = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp17 = ($n | 0) > 0;
+ if ($cmp17) {
+ label = 3;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 3:
+ $0 = $job;
+ $i_018 = 0;
+ label = 4;
+ break;
+ case 4:
+ $x = $A + ($i_018 << 4) | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $cmp1 = $1 < 0.0;
+ if ($cmp1) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add = $1 + .5;
+ $add_sink = $add;
+ label = 7;
+ break;
+ case 6:
+ $sub = $1 + -.5;
+ $add_sink = $sub;
+ label = 7;
+ break;
+ case 7:
+ $conv = ~~$add_sink;
+ $y = $A + ($i_018 << 4) + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $cmp9 = $2 < 0.0;
+ if ($cmp9) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $add14 = $2 + .5;
+ $add14_sink = $add14;
+ label = 10;
+ break;
+ case 9:
+ $sub19 = $2 + -.5;
+ $add14_sink = $sub19;
+ label = 10;
+ break;
+ case 10:
+ $conv15 = ~~$add14_sink;
+ _gvprintf($0, 154544, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $conv, HEAP32[tempInt + 8 >> 2] = $conv15, tempInt) | 0);
+ $inc = $i_018 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_018 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $tobool = ($close | 0) == 0;
+ if ($tobool) {
+ label = 19;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $x27 = $A | 0;
+ $3 = +HEAPF64[$x27 >> 3];
+ $cmp28 = $3 < 0.0;
+ if ($cmp28) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $add33 = $3 + .5;
+ $add33_sink = $add33;
+ label = 15;
+ break;
+ case 14:
+ $sub38 = $3 + -.5;
+ $add33_sink = $sub38;
+ label = 15;
+ break;
+ case 15:
+ $conv34 = ~~$add33_sink;
+ $y44 = $A + 8 | 0;
+ $4 = +HEAPF64[$y44 >> 3];
+ $cmp45 = $4 < 0.0;
+ if ($cmp45) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $add50 = $4 + .5;
+ $add50_sink = $add50;
+ label = 18;
+ break;
+ case 17:
+ $sub55 = $4 + -.5;
+ $add50_sink = $sub55;
+ label = 18;
+ break;
+ case 18:
+ $conv51 = ~~$add50_sink;
+ $5 = $job;
+ _gvprintf($5, 154544, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $conv34, HEAP32[tempInt + 8 >> 2] = $conv51, tempInt) | 0);
+ label = 19;
+ break;
+ case 19:
+ $6 = $job;
+ $call = _gvputs($6, 150856) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _fig_string($s) {
+ $s = $s | 0;
+ var $0 = 0, $tobool = 0, $call = 0, $1 = 0, $2 = 0, $tobool114 = 0, $3 = 0, $s_pn = 0, $p_016 = 0, $pos_015 = 0, $incdec_ptr17 = 0, $4 = 0, $sub = 0, $cmp = 0, $mul3 = 0, $5 = 0, $call5 = 0, $add_ptr = 0, $p_1 = 0, $cmp7 = 0, $cmp11 = 0, $incdec_ptr14 = 0, $inc = 0, $pos_1 = 0, $p_2 = 0, $incdec_ptr16 = 0, $inc17 = 0, $conv = 0, $incdec_ptr18 = 0, $call20 = 0, $add_ptr21 = 0, $add = 0, $pos_0_be = 0, $p_0_be = 0, $6 = 0, $tobool1 = 0, $p_0_lcssa = 0, $7 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[4114] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[4112] = 64;
+ $call = _malloc(64) | 0;
+ HEAP32[4114] = $call;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[4114] | 0;
+ $2 = HEAP8[$s] | 0;
+ $tobool114 = $2 << 24 >> 24 == 0;
+ if ($tobool114) {
+ $p_0_lcssa = $1;
+ label = 13;
+ break;
+ } else {
+ $pos_015 = 0;
+ $p_016 = $1;
+ $s_pn = $s;
+ $3 = $2;
+ label = 5;
+ break;
+ }
+ case 5:
+ $incdec_ptr17 = $s_pn + 1 | 0;
+ $4 = HEAP32[4112] | 0;
+ $sub = $4 - 8 | 0;
+ $cmp = ($pos_015 | 0) > ($sub | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ $p_1 = $p_016;
+ label = 7;
+ break;
+ }
+ case 6:
+ $mul3 = $4 << 1;
+ HEAP32[4112] = $mul3;
+ $5 = HEAP32[4114] | 0;
+ $call5 = _realloc($5, $mul3) | 0;
+ HEAP32[4114] = $call5;
+ $add_ptr = $call5 + $pos_015 | 0;
+ $p_1 = $add_ptr;
+ label = 7;
+ break;
+ case 7:
+ $cmp7 = $3 << 24 >> 24 > -1;
+ if ($cmp7) {
+ label = 8;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ $cmp11 = $3 << 24 >> 24 == 92;
+ if ($cmp11) {
+ label = 9;
+ break;
+ } else {
+ $p_2 = $p_1;
+ $pos_1 = $pos_015;
+ label = 10;
+ break;
+ }
+ case 9:
+ $incdec_ptr14 = $p_1 + 1 | 0;
+ HEAP8[$p_1] = 92;
+ $inc = $pos_015 + 1 | 0;
+ $p_2 = $incdec_ptr14;
+ $pos_1 = $inc;
+ label = 10;
+ break;
+ case 10:
+ $incdec_ptr16 = $p_2 + 1 | 0;
+ HEAP8[$p_2] = $3;
+ $inc17 = $pos_1 + 1 | 0;
+ $p_0_be = $incdec_ptr16;
+ $pos_0_be = $inc17;
+ label = 12;
+ break;
+ case 11:
+ $conv = $3 & 255;
+ $incdec_ptr18 = $p_1 + 1 | 0;
+ HEAP8[$p_1] = 92;
+ $call20 = _sprintf($incdec_ptr18 | 0, 124536, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $conv, tempInt) | 0) | 0;
+ $add_ptr21 = $p_1 + 4 | 0;
+ $add = $pos_015 + 4 | 0;
+ $p_0_be = $add_ptr21;
+ $pos_0_be = $add;
+ label = 12;
+ break;
+ case 12:
+ $6 = HEAP8[$incdec_ptr17] | 0;
+ $tobool1 = $6 << 24 >> 24 == 0;
+ if ($tobool1) {
+ $p_0_lcssa = $p_0_be;
+ label = 13;
+ break;
+ } else {
+ $pos_015 = $pos_0_be;
+ $p_016 = $p_0_be;
+ $s_pn = $incdec_ptr17;
+ $3 = $6;
+ label = 5;
+ break;
+ }
+ case 13:
+ HEAP8[$p_0_lcssa] = 0;
+ $7 = HEAP32[4114] | 0;
+ STACKTOP = __stackBase__;
+ return $7 | 0;
+ }
+ return 0;
+}
+function _map_begin_page($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $id = 0, $1 = 0, $2 = 0, $call = 0, $url = 0, $3 = 0, $tobool = 0, $4 = 0, $tobool3 = 0, $call4 = 0, $5 = 0, $call6 = 0, $call7 = 0, $call8 = 0, $url10 = 0, $6 = 0, $tobool11 = 0, $7 = 0, $tobool16 = 0, $8 = 0, $call18 = 0, $9 = 0, $call20 = 0, $call21 = 0, $call22 = 0, $g = 0, $10 = 0, $name = 0, $11 = 0, $call23 = 0, $call24 = 0, $call25 = 0, $g29 = 0, $12 = 0, $name30 = 0, $13 = 0, $call31 = 0, $14 = 0, $call32 = 0, $call33 = 0, $call34 = 0, $call35 = 0, $call36 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $id = $job + 64 | 0;
+ $1 = HEAP32[$id >> 2] | 0;
+ if (($1 | 0) == 0) {
+ label = 3;
+ break;
+ } else if (($1 | 0) == 1) {
+ label = 6;
+ break;
+ } else if (($1 | 0) == 3) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $2 = $job;
+ $call = _gvputs($2, 117808) | 0;
+ $url = $0 + 160 | 0;
+ $3 = HEAP32[$url >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $4 = HEAP8[$3] | 0;
+ $tobool3 = $4 << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 10;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call4 = _gvputs($2, 117128) | 0;
+ $5 = HEAP32[$url >> 2] | 0;
+ $call6 = _xml_string($5) | 0;
+ $call7 = _gvputs($2, $call6) | 0;
+ $call8 = _gvputs($2, 156648) | 0;
+ label = 10;
+ break;
+ case 6:
+ $url10 = $0 + 160 | 0;
+ $6 = HEAP32[$url10 >> 2] | 0;
+ $tobool11 = ($6 | 0) == 0;
+ if ($tobool11) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $7 = HEAP8[$6] | 0;
+ $tobool16 = $7 << 24 >> 24 == 0;
+ if ($tobool16) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $8 = $job;
+ $call18 = _gvputs($8, 117128) | 0;
+ $9 = HEAP32[$url10 >> 2] | 0;
+ $call20 = _xml_string($9) | 0;
+ $call21 = _gvputs($8, $call20) | 0;
+ $call22 = _gvputs($8, 116568) | 0;
+ $g = $0 + 8 | 0;
+ $10 = HEAP32[$g >> 2] | 0;
+ $name = $10 + 12 | 0;
+ $11 = HEAP32[$name >> 2] | 0;
+ $call23 = _xml_string($11) | 0;
+ $call24 = _gvputs($8, $call23) | 0;
+ $call25 = _gvputs($8, 156648) | 0;
+ label = 10;
+ break;
+ case 9:
+ $g29 = $0 + 8 | 0;
+ $12 = HEAP32[$g29 >> 2] | 0;
+ $name30 = $12 + 12 | 0;
+ $13 = HEAP32[$name30 >> 2] | 0;
+ $call31 = _xml_string($13) | 0;
+ $14 = $job;
+ $call32 = _gvputs($14, 116088) | 0;
+ $call33 = _gvputs($14, $call31) | 0;
+ $call34 = _gvputs($14, 115600) | 0;
+ $call35 = _gvputs($14, $call31) | 0;
+ $call36 = _gvputs($14, 118912) | 0;
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _map_end_page($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $id = 0, $1 = 0, $url_map_shape = 0, $2 = 0, $url_map_p = 0, $3 = 0, $url_map_n = 0, $4 = 0, $url = 0, $5 = 0, $tooltip = 0, $6 = 0, $target = 0, $7 = 0, $id2 = 0, $8 = 0, $url_map_shape4 = 0, $9 = 0, $url_map_p5 = 0, $10 = 0, $url_map_n6 = 0, $11 = 0, $url7 = 0, $12 = 0, $tooltip8 = 0, $13 = 0, $target9 = 0, $14 = 0, $id10 = 0, $15 = 0, $16 = 0, $call = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $id = $job + 64 | 0;
+ $1 = HEAP32[$id >> 2] | 0;
+ if (($1 | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($1 | 0) == 3) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $url_map_shape = $0 + 216 | 0;
+ $2 = HEAP32[$url_map_shape >> 2] | 0;
+ $url_map_p = $0 + 224 | 0;
+ $3 = HEAP32[$url_map_p >> 2] | 0;
+ $url_map_n = $0 + 220 | 0;
+ $4 = HEAP32[$url_map_n >> 2] | 0;
+ $url = $0 + 160 | 0;
+ $5 = HEAP32[$url >> 2] | 0;
+ $tooltip = $0 + 180 | 0;
+ $6 = HEAP32[$tooltip >> 2] | 0;
+ $target = $0 + 196 | 0;
+ $7 = HEAP32[$target >> 2] | 0;
+ $id2 = $0 + 164 | 0;
+ $8 = HEAP32[$id2 >> 2] | 0;
+ _map_output_shape($job, $2, $3, $4, $5, $6, $7, $8);
+ label = 5;
+ break;
+ case 4:
+ $url_map_shape4 = $0 + 216 | 0;
+ $9 = HEAP32[$url_map_shape4 >> 2] | 0;
+ $url_map_p5 = $0 + 224 | 0;
+ $10 = HEAP32[$url_map_p5 >> 2] | 0;
+ $url_map_n6 = $0 + 220 | 0;
+ $11 = HEAP32[$url_map_n6 >> 2] | 0;
+ $url7 = $0 + 160 | 0;
+ $12 = HEAP32[$url7 >> 2] | 0;
+ $tooltip8 = $0 + 180 | 0;
+ $13 = HEAP32[$tooltip8 >> 2] | 0;
+ $target9 = $0 + 196 | 0;
+ $14 = HEAP32[$target9 >> 2] | 0;
+ $id10 = $0 + 164 | 0;
+ $15 = HEAP32[$id10 >> 2] | 0;
+ _map_output_shape($job, $9, $10, $11, $12, $13, $14, $15);
+ $16 = $job;
+ $call = _gvputs($16, 118440) | 0;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _map_begin_anchor($job, $url, $tooltip, $target, $id) {
+ $job = $job | 0;
+ $url = $url | 0;
+ $tooltip = $tooltip | 0;
+ $target = $target | 0;
+ $id = $id | 0;
+ var $0 = 0;
+ $0 = HEAP32[$job + 16 >> 2] | 0;
+ _map_output_shape($job, HEAP32[$0 + 216 >> 2] | 0, HEAP32[$0 + 224 >> 2] | 0, HEAP32[$0 + 220 >> 2] | 0, $url, $tooltip, $target, $id);
+ return;
+}
+function _psgen_begin_job($job) {
+ $job = $job | 0;
+ var $0 = 0, $call = 0, $id = 0, $1 = 0, $cmp = 0, $call1 = 0, $call2 = 0, $common = 0, $2 = 0, $info = 0, $3 = 0, $4 = 0, $arrayidx5 = 0, $5 = 0, $arrayidx8 = 0, $6 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 130808) | 0;
+ $id = $job + 64 | 0;
+ $1 = HEAP32[$id >> 2] | 0;
+ $cmp = ($1 | 0) == 2;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call1 = _gvputs($0, 130624) | 0;
+ label = 5;
+ break;
+ case 4:
+ $call2 = _gvputs($0, 143192) | 0;
+ label = 5;
+ break;
+ case 5:
+ $common = $job + 12 | 0;
+ $2 = HEAP32[$common >> 2] | 0;
+ $info = $2 | 0;
+ $3 = HEAP32[$info >> 2] | 0;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $arrayidx5 = $3 + 4 | 0;
+ $5 = HEAP32[$arrayidx5 >> 2] | 0;
+ $arrayidx8 = $3 + 8 | 0;
+ $6 = HEAP32[$arrayidx8 >> 2] | 0;
+ _gvprintf($0, 130432, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $4, HEAP32[tempInt + 8 >> 2] = $5, HEAP32[tempInt + 16 >> 2] = $6, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_end_job($job) {
+ $job = $job | 0;
+ var $0 = 0, $call = 0, $id = 0, $1 = 0, $cmp = 0, $common = 0, $2 = 0, $viewNum = 0, $3 = 0, $common1 = 0, $4 = 0, $show_boxes = 0, $5 = 0, $cmp2 = 0, $6 = 0, $cmp6 = 0, $x = 0, $7 = 0, $y = 0, $8 = 0, $x11 = 0, $9 = 0, $y14 = 0, $10 = 0, $call17 = 0, $call18 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 131448) | 0;
+ $id = $job + 64 | 0;
+ $1 = HEAP32[$id >> 2] | 0;
+ $cmp = ($1 | 0) == 2;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $common = $job + 12 | 0;
+ $2 = HEAP32[$common >> 2] | 0;
+ $viewNum = $2 + 28 | 0;
+ $3 = HEAP32[$viewNum >> 2] | 0;
+ _gvprintf($0, 131288, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $3, tempInt) | 0);
+ label = 4;
+ break;
+ case 4:
+ $common1 = $job + 12 | 0;
+ $4 = HEAP32[$common1 >> 2] | 0;
+ $show_boxes = $4 + 20 | 0;
+ $5 = HEAP32[$show_boxes >> 2] | 0;
+ $cmp2 = ($5 | 0) == 0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $6 = HEAP32[$id >> 2] | 0;
+ $cmp6 = ($6 | 0) == 2;
+ if ($cmp6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $x = $job + 472 | 0;
+ $7 = HEAP32[$x >> 2] | 0;
+ $y = $job + 476 | 0;
+ $8 = HEAP32[$y >> 2] | 0;
+ $x11 = $job + 480 | 0;
+ $9 = HEAP32[$x11 >> 2] | 0;
+ $y14 = $job + 484 | 0;
+ $10 = HEAP32[$y14 >> 2] | 0;
+ _gvprintf($0, 132240, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $7, HEAP32[tempInt + 8 >> 2] = $8, HEAP32[tempInt + 16 >> 2] = $9, HEAP32[tempInt + 24 >> 2] = $10, tempInt) | 0);
+ label = 7;
+ break;
+ case 7:
+ $call17 = _gvputs($0, 131120) | 0;
+ $call18 = _gvputs($0, 130960) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_begin_graph($job) {
+ $job = $job | 0;
+ var $args = 0, $obj1 = 0, $0 = 0, $common = 0, $1 = 0, $viewNum = 0, $2 = 0, $cmp = 0, $g = 0, $3 = 0, $name = 0, $4 = 0, $5 = 0, $id = 0, $6 = 0, $cmp2 = 0, $call = 0, $call4 = 0, $7 = 0, $show_boxes = 0, $8 = 0, $cmp6 = 0, $9 = 0, $cmp10 = 0, $call12 = 0, $x = 0, $10 = 0, $y = 0, $11 = 0, $x17 = 0, $12 = 0, $y20 = 0, $13 = 0, $call23 = 0, $14 = 0, $lib = 0, $15 = 0, $16 = 0, $17 = 0, $show_boxes26 = 0, $18 = 0, $tobool = 0, $19 = 0, $arrayidx30 = 0, $arrayidx31 = 0, $g35 = 0, $20 = 0, $charset = 0, $21 = 0, $cmp37 = 0, $conv38 = 0, $_b = 0, $22 = 0, $call41 = 0, $url = 0, $23 = 0, $tobool43 = 0, $24 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $args = __stackBase__ | 0;
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ HEAP8[4232] = 0;
+ $common = $job + 12 | 0;
+ $1 = HEAP32[$common >> 2] | 0;
+ $viewNum = $1 + 28 | 0;
+ $2 = HEAP32[$viewNum >> 2] | 0;
+ $cmp = ($2 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 3:
+ $g = $0 + 8 | 0;
+ $3 = HEAP32[$g >> 2] | 0;
+ $name = $3 + 12 | 0;
+ $4 = HEAP32[$name >> 2] | 0;
+ $5 = $job;
+ _gvprintf($5, 132992, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $4, tempInt) | 0);
+ $id = $job + 64 | 0;
+ $6 = HEAP32[$id >> 2] | 0;
+ $cmp2 = ($6 | 0) == 2;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call = _gvputs($5, 132736) | 0;
+ label = 6;
+ break;
+ case 5:
+ $call4 = _gvputs($5, 132544) | 0;
+ label = 6;
+ break;
+ case 6:
+ $7 = HEAP32[$common >> 2] | 0;
+ $show_boxes = $7 + 20 | 0;
+ $8 = HEAP32[$show_boxes >> 2] | 0;
+ $cmp6 = ($8 | 0) == 0;
+ if ($cmp6) {
+ label = 7;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 7:
+ $9 = HEAP32[$id >> 2] | 0;
+ $cmp10 = ($9 | 0) == 2;
+ if ($cmp10) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $call12 = _gvputs($5, 132408) | 0;
+ label = 10;
+ break;
+ case 9:
+ $x = $job + 456 | 0;
+ $10 = HEAP32[$x >> 2] | 0;
+ $y = $job + 460 | 0;
+ $11 = HEAP32[$y >> 2] | 0;
+ $x17 = $job + 464 | 0;
+ $12 = HEAP32[$x17 >> 2] | 0;
+ $y20 = $job + 468 | 0;
+ $13 = HEAP32[$y20 >> 2] | 0;
+ _gvprintf($5, 132240, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $10, HEAP32[tempInt + 8 >> 2] = $11, HEAP32[tempInt + 16 >> 2] = $12, HEAP32[tempInt + 24 >> 2] = $13, tempInt) | 0);
+ label = 10;
+ break;
+ case 10:
+ $call23 = _gvputs($5, 132072) | 0;
+ $14 = HEAP32[$common >> 2] | 0;
+ $lib = $14 + 24 | 0;
+ $15 = HEAP32[$lib >> 2] | 0;
+ $16 = $job;
+ _cat_libfile($16, $15, 4856);
+ _epsf_define($16);
+ $17 = HEAP32[$common >> 2] | 0;
+ $show_boxes26 = $17 + 20 | 0;
+ $18 = HEAP32[$show_boxes26 >> 2] | 0;
+ $tobool = ($18 | 0) == 0;
+ if ($tobool) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $19 = HEAP32[$18 >> 2] | 0;
+ $arrayidx30 = $args | 0;
+ HEAP32[$arrayidx30 >> 2] = $19;
+ $arrayidx31 = $args + 4 | 0;
+ HEAP32[$arrayidx31 >> 2] = 0;
+ _cat_libfile($16, 0, $arrayidx30);
+ label = 12;
+ break;
+ case 12:
+ $g35 = $0 + 8 | 0;
+ $20 = HEAP32[$g35 >> 2] | 0;
+ $charset = $20 + 155 | 0;
+ $21 = HEAP8[$charset] | 0;
+ $cmp37 = $21 << 24 >> 24 == 1;
+ $conv38 = $cmp37 & 1;
+ HEAP32[3088] = $conv38;
+ $_b = HEAP8[4232] | 0;
+ if ($_b) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $22 = $job;
+ $call41 = _gvputs($22, 131912) | 0;
+ HEAP8[4232] = 1;
+ label = 14;
+ break;
+ case 14:
+ $url = $0 + 160 | 0;
+ $23 = HEAP32[$url >> 2] | 0;
+ $tobool43 = ($23 | 0) == 0;
+ if ($tobool43) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $24 = $job;
+ _gvprintf($24, 131656, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $23, tempInt) | 0);
+ label = 16;
+ break;
+ case 16:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_begin_layer($job, $layername, $layerNum, $numLayers) {
+ $job = $job | 0;
+ $layername = $layername | 0;
+ $layerNum = $layerNum | 0;
+ $numLayers = $numLayers | 0;
+ var __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ _gvprintf($job, 133304, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $layerNum, HEAP32[tempInt + 8 >> 2] = $numLayers, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _map_output_shape($job, $map_shape, $AF, $nump, $url, $tooltip, $target, $id) {
+ $job = $job | 0;
+ $map_shape = $map_shape | 0;
+ $AF = $AF | 0;
+ $nump = $nump | 0;
+ $url = $url | 0;
+ $tooltip = $tooltip | 0;
+ $target = $target | 0;
+ $id = $id | 0;
+ var $tobool = 0, $tobool1 = 0, $or_cond = 0, $0 = 0, $cmp = 0, $add = 0, $1 = 0, $2 = 0, $mul = 0, $call = 0, $3 = 0, $cmp483 = 0, $i_084 = 0, $x = 0, $4 = 0.0, $cmp5 = 0, $add8 = 0.0, $sub = 0.0, $add8_sink = 0.0, $conv = 0, $5 = 0, $x13 = 0, $y = 0, $6 = 0.0, $cmp15 = 0, $add20 = 0.0, $sub25 = 0.0, $add20_sink = 0.0, $conv21 = 0, $7 = 0, $y30 = 0, $inc = 0, $cmp4 = 0, $id31 = 0, $8 = 0, $cmp32 = 0, $tobool34 = 0, $or_cond77 = 0, $9 = 0, $tobool38 = 0, $10 = 0, $x41 = 0, $11 = 0, $y43 = 0, $12 = 0, $x45 = 0, $13 = 0, $y47 = 0, $14 = 0, $15 = 0, $16 = 0, $x50 = 0, $17 = 0, $y52 = 0, $18 = 0, $x54 = 0, $19 = 0, $sub57 = 0, $20 = 0, $21 = 0, $cmp6081 = 0, $i_182 = 0, $22 = 0, $x64 = 0, $23 = 0, $y66 = 0, $24 = 0, $inc68 = 0, $cmp60 = 0, $call70 = 0, $25 = 0, $cmp73 = 0, $or_cond78 = 0, $26 = 0, $tobool80 = 0, $cond1 = 0, $27 = 0, $x84 = 0, $28 = 0, $y86 = 0, $29 = 0, $x88 = 0, $30 = 0, $y90 = 0, $31 = 0, $32 = 0, $33 = 0, $_off = 0, $switch = 0, $34 = 0, $call105 = 0, $35 = 0, $call107 = 0, $36 = 0, $call109 = 0, $tobool112 = 0, $37 = 0, $tobool116 = 0, $38 = 0, $call118 = 0, $call119 = 0, $call120 = 0, $call121 = 0, $39 = 0, $tobool127 = 0, $40 = 0, $call129 = 0, $call130 = 0, $call131 = 0, $call132 = 0, $tobool134 = 0, $41 = 0, $tobool138 = 0, $42 = 0, $call140 = 0, $call141 = 0, $call142 = 0, $call143 = 0, $tobool145 = 0, $43 = 0, $tobool149 = 0, $44 = 0, $call151 = 0, $call152 = 0, $call153 = 0, $call154 = 0, $45 = 0, $call156 = 0, $call157 = 0, $46 = 0, $x160 = 0, $47 = 0, $y162 = 0, $48 = 0, $x164 = 0, $49 = 0, $sub167 = 0, $50 = 0, $x170 = 0, $51 = 0, $y172 = 0, $52 = 0, $x174 = 0, $53 = 0, $y176 = 0, $54 = 0, $55 = 0, $x179 = 0, $56 = 0, $y181 = 0, $57 = 0, $cmp18379 = 0, $i_280 = 0, $58 = 0, $x187 = 0, $59 = 0, $y189 = 0, $60 = 0, $inc191 = 0, $cmp183 = 0, $61 = 0, $cmp197 = 0, $call200 = 0, $call202 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($AF | 0) == 0;
+ $tobool1 = ($nump | 0) == 0;
+ $or_cond = $tobool | $tobool1;
+ if ($or_cond) {
+ label = 53;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP32[2818] | 0;
+ $cmp = ($0 | 0) < ($nump | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $add = $nump + 10 | 0;
+ HEAP32[2818] = $add;
+ $1 = HEAP32[2820] | 0;
+ $2 = $1;
+ $mul = $add << 3;
+ $call = _realloc($2, $mul) | 0;
+ $3 = $call;
+ HEAP32[2820] = $3;
+ label = 5;
+ break;
+ case 5:
+ $cmp483 = ($nump | 0) > 0;
+ if ($cmp483) {
+ $i_084 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 6:
+ $x = $AF + ($i_084 << 4) | 0;
+ $4 = +HEAPF64[$x >> 3];
+ $cmp5 = $4 < 0.0;
+ if ($cmp5) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add8 = $4 + .5;
+ $add8_sink = $add8;
+ label = 9;
+ break;
+ case 8:
+ $sub = $4 + -.5;
+ $add8_sink = $sub;
+ label = 9;
+ break;
+ case 9:
+ $conv = ~~$add8_sink;
+ $5 = HEAP32[2820] | 0;
+ $x13 = $5 + ($i_084 << 3) | 0;
+ HEAP32[$x13 >> 2] = $conv;
+ $y = $AF + ($i_084 << 4) + 8 | 0;
+ $6 = +HEAPF64[$y >> 3];
+ $cmp15 = $6 < 0.0;
+ if ($cmp15) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $add20 = $6 + .5;
+ $add20_sink = $add20;
+ label = 12;
+ break;
+ case 11:
+ $sub25 = $6 + -.5;
+ $add20_sink = $sub25;
+ label = 12;
+ break;
+ case 12:
+ $conv21 = ~~$add20_sink;
+ $7 = HEAP32[2820] | 0;
+ $y30 = $7 + ($i_084 << 3) + 4 | 0;
+ HEAP32[$y30 >> 2] = $conv21;
+ $inc = $i_084 + 1 | 0;
+ $cmp4 = ($inc | 0) < ($nump | 0);
+ if ($cmp4) {
+ $i_084 = $inc;
+ label = 6;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $id31 = $job + 64 | 0;
+ $8 = HEAP32[$id31 >> 2] | 0;
+ $cmp32 = ($8 | 0) != 0;
+ $tobool34 = ($url | 0) == 0;
+ $or_cond77 = $cmp32 | $tobool34;
+ if ($or_cond77) {
+ label = 22;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $9 = HEAP8[$url] | 0;
+ $tobool38 = $9 << 24 >> 24 == 0;
+ if ($tobool38) {
+ label = 22;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ if (($map_shape | 0) == 0) {
+ label = 16;
+ break;
+ } else if (($map_shape | 0) == 1) {
+ label = 17;
+ break;
+ } else if (($map_shape | 0) == 2) {
+ label = 18;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 16:
+ $10 = HEAP32[2820] | 0;
+ $x41 = $10 | 0;
+ $11 = HEAP32[$x41 >> 2] | 0;
+ $y43 = $10 + 12 | 0;
+ $12 = HEAP32[$y43 >> 2] | 0;
+ $x45 = $10 + 8 | 0;
+ $13 = HEAP32[$x45 >> 2] | 0;
+ $y47 = $10 + 4 | 0;
+ $14 = HEAP32[$y47 >> 2] | 0;
+ $15 = $job;
+ _gvprintf($15, 97352, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = $url, HEAP32[tempInt + 8 >> 2] = $11, HEAP32[tempInt + 16 >> 2] = $12, HEAP32[tempInt + 24 >> 2] = $13, HEAP32[tempInt + 32 >> 2] = $14, tempInt) | 0);
+ label = 53;
+ break;
+ case 17:
+ $16 = HEAP32[2820] | 0;
+ $x50 = $16 | 0;
+ $17 = HEAP32[$x50 >> 2] | 0;
+ $y52 = $16 + 4 | 0;
+ $18 = HEAP32[$y52 >> 2] | 0;
+ $x54 = $16 + 8 | 0;
+ $19 = HEAP32[$x54 >> 2] | 0;
+ $sub57 = $19 - $17 | 0;
+ $20 = $job;
+ _gvprintf($20, 93696, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $url, HEAP32[tempInt + 8 >> 2] = $17, HEAP32[tempInt + 16 >> 2] = $18, HEAP32[tempInt + 24 >> 2] = $sub57, tempInt) | 0);
+ label = 53;
+ break;
+ case 18:
+ $21 = $job;
+ _gvprintf($21, 90216, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $url, tempInt) | 0);
+ $cmp6081 = ($nump | 0) > 0;
+ if ($cmp6081) {
+ $i_182 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $22 = HEAP32[2820] | 0;
+ $x64 = $22 + ($i_182 << 3) | 0;
+ $23 = HEAP32[$x64 >> 2] | 0;
+ $y66 = $22 + ($i_182 << 3) + 4 | 0;
+ $24 = HEAP32[$y66 >> 2] | 0;
+ _gvprintf($21, 160392, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $23, HEAP32[tempInt + 8 >> 2] = $24, tempInt) | 0);
+ $inc68 = $i_182 + 1 | 0;
+ $cmp60 = ($inc68 | 0) < ($nump | 0);
+ if ($cmp60) {
+ $i_182 = $inc68;
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $call70 = _gvputs($21, 156648) | 0;
+ label = 53;
+ break;
+ case 21:
+ ___assert_func(153248, 65, 164064, 149664);
+ case 22:
+ $25 = HEAP32[$id31 >> 2] | 0;
+ $cmp73 = ($25 | 0) != 1;
+ $or_cond78 = $cmp73 | $tobool34;
+ if ($or_cond78) {
+ label = 27;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $26 = HEAP8[$url] | 0;
+ $tobool80 = $26 << 24 >> 24 == 0;
+ if ($tobool80) {
+ label = 27;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $cond1 = ($map_shape | 0) == 0;
+ if ($cond1) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $27 = HEAP32[2820] | 0;
+ $x84 = $27 | 0;
+ $28 = HEAP32[$x84 >> 2] | 0;
+ $y86 = $27 + 12 | 0;
+ $29 = HEAP32[$y86 >> 2] | 0;
+ $x88 = $27 + 8 | 0;
+ $30 = HEAP32[$x88 >> 2] | 0;
+ $y90 = $27 + 4 | 0;
+ $31 = HEAP32[$y90 >> 2] | 0;
+ $32 = $job;
+ _gvprintf($32, 146792, (tempInt = STACKTOP, STACKTOP = STACKTOP + 48 | 0, HEAP32[tempInt >> 2] = $28, HEAP32[tempInt + 8 >> 2] = $29, HEAP32[tempInt + 16 >> 2] = $30, HEAP32[tempInt + 24 >> 2] = $31, HEAP32[tempInt + 32 >> 2] = $url, HEAP32[tempInt + 40 >> 2] = $tooltip, tempInt) | 0);
+ label = 53;
+ break;
+ case 26:
+ ___assert_func(153248, 77, 164064, 149664);
+ case 27:
+ $33 = HEAP32[$id31 >> 2] | 0;
+ $_off = $33 - 2 | 0;
+ $switch = $_off >>> 0 < 2;
+ if ($switch) {
+ label = 28;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 28:
+ if (($map_shape | 0) == 1) {
+ label = 29;
+ break;
+ } else if (($map_shape | 0) == 0) {
+ label = 30;
+ break;
+ } else if (($map_shape | 0) == 2) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 29:
+ $34 = $job;
+ $call105 = _gvputs($34, 143984) | 0;
+ label = 33;
+ break;
+ case 30:
+ $35 = $job;
+ $call107 = _gvputs($35, 140176) | 0;
+ label = 33;
+ break;
+ case 31:
+ $36 = $job;
+ $call109 = _gvputs($36, 137448) | 0;
+ label = 33;
+ break;
+ case 32:
+ ___assert_func(153248, 93, 164064, 149664);
+ case 33:
+ $tobool112 = ($id | 0) == 0;
+ if ($tobool112) {
+ label = 36;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $37 = HEAP8[$id] | 0;
+ $tobool116 = $37 << 24 >> 24 == 0;
+ if ($tobool116) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $38 = $job;
+ $call118 = _gvputs($38, 134880) | 0;
+ $call119 = _xml_url_string($id) | 0;
+ $call120 = _gvputs($38, $call119) | 0;
+ $call121 = _gvputs($38, 132384) | 0;
+ label = 36;
+ break;
+ case 36:
+ if ($tobool34) {
+ label = 39;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $39 = HEAP8[$url] | 0;
+ $tobool127 = $39 << 24 >> 24 == 0;
+ if ($tobool127) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $40 = $job;
+ $call129 = _gvputs($40, 130576) | 0;
+ $call130 = _xml_url_string($url) | 0;
+ $call131 = _gvputs($40, $call130) | 0;
+ $call132 = _gvputs($40, 132384) | 0;
+ label = 39;
+ break;
+ case 39:
+ $tobool134 = ($target | 0) == 0;
+ if ($tobool134) {
+ label = 42;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $41 = HEAP8[$target] | 0;
+ $tobool138 = $41 << 24 >> 24 == 0;
+ if ($tobool138) {
+ label = 42;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $42 = $job;
+ $call140 = _gvputs($42, 128704) | 0;
+ $call141 = _xml_string($target) | 0;
+ $call142 = _gvputs($42, $call141) | 0;
+ $call143 = _gvputs($42, 132384) | 0;
+ label = 42;
+ break;
+ case 42:
+ $tobool145 = ($tooltip | 0) == 0;
+ if ($tobool145) {
+ label = 45;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $43 = HEAP8[$tooltip] | 0;
+ $tobool149 = $43 << 24 >> 24 == 0;
+ if ($tobool149) {
+ label = 45;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $44 = $job;
+ $call151 = _gvputs($44, 126120) | 0;
+ $call152 = _xml_string($tooltip) | 0;
+ $call153 = _gvputs($44, $call152) | 0;
+ $call154 = _gvputs($44, 132384) | 0;
+ label = 45;
+ break;
+ case 45:
+ $45 = $job;
+ $call156 = _gvputs($45, 123944) | 0;
+ $call157 = _gvputs($45, 121992) | 0;
+ if (($map_shape | 0) == 1) {
+ label = 46;
+ break;
+ } else if (($map_shape | 0) == 0) {
+ label = 47;
+ break;
+ } else if (($map_shape | 0) == 2) {
+ label = 48;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 46:
+ $46 = HEAP32[2820] | 0;
+ $x160 = $46 | 0;
+ $47 = HEAP32[$x160 >> 2] | 0;
+ $y162 = $46 + 4 | 0;
+ $48 = HEAP32[$y162 >> 2] | 0;
+ $x164 = $46 + 8 | 0;
+ $49 = HEAP32[$x164 >> 2] | 0;
+ $sub167 = $49 - $47 | 0;
+ _gvprintf($45, 121936, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $47, HEAP32[tempInt + 8 >> 2] = $48, HEAP32[tempInt + 16 >> 2] = $sub167, tempInt) | 0);
+ label = 50;
+ break;
+ case 47:
+ $50 = HEAP32[2820] | 0;
+ $x170 = $50 | 0;
+ $51 = HEAP32[$x170 >> 2] | 0;
+ $y172 = $50 + 12 | 0;
+ $52 = HEAP32[$y172 >> 2] | 0;
+ $x174 = $50 + 8 | 0;
+ $53 = HEAP32[$x174 >> 2] | 0;
+ $y176 = $50 + 4 | 0;
+ $54 = HEAP32[$y176 >> 2] | 0;
+ _gvprintf($45, 121408, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $51, HEAP32[tempInt + 8 >> 2] = $52, HEAP32[tempInt + 16 >> 2] = $53, HEAP32[tempInt + 24 >> 2] = $54, tempInt) | 0);
+ label = 50;
+ break;
+ case 48:
+ $55 = HEAP32[2820] | 0;
+ $x179 = $55 | 0;
+ $56 = HEAP32[$x179 >> 2] | 0;
+ $y181 = $55 + 4 | 0;
+ $57 = HEAP32[$y181 >> 2] | 0;
+ _gvprintf($45, 120688, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $56, HEAP32[tempInt + 8 >> 2] = $57, tempInt) | 0);
+ $cmp18379 = ($nump | 0) > 1;
+ if ($cmp18379) {
+ $i_280 = 1;
+ label = 49;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 49:
+ $58 = HEAP32[2820] | 0;
+ $x187 = $58 + ($i_280 << 3) | 0;
+ $59 = HEAP32[$x187 >> 2] | 0;
+ $y189 = $58 + ($i_280 << 3) + 4 | 0;
+ $60 = HEAP32[$y189 >> 2] | 0;
+ _gvprintf($45, 119976, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $59, HEAP32[tempInt + 8 >> 2] = $60, tempInt) | 0);
+ $inc191 = $i_280 + 1 | 0;
+ $cmp183 = ($inc191 | 0) < ($nump | 0);
+ if ($cmp183) {
+ $i_280 = $inc191;
+ label = 49;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $61 = HEAP32[$id31 >> 2] | 0;
+ $cmp197 = ($61 | 0) == 3;
+ if ($cmp197) {
+ label = 51;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 51:
+ $call200 = _gvputs($45, 119448) | 0;
+ label = 53;
+ break;
+ case 52:
+ $call202 = _gvputs($45, 118912) | 0;
+ label = 53;
+ break;
+ case 53:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_begin_page($job) {
+ $job = $job | 0;
+ var $pbr_sroa_0_0__idx = 0, $pbr_sroa_0_0_copyload = 0, $pbr_sroa_1_4__idx4 = 0, $pbr_sroa_1_4_copyload = 0, $pbr_sroa_2_8__idx8 = 0, $pbr_sroa_2_8_copyload = 0, $pbr_sroa_3_12__idx14 = 0, $pbr_sroa_3_12_copyload = 0, $common = 0, $0 = 0, $viewNum = 0, $1 = 0, $add = 0, $2 = 0, $3 = 0, $show_boxes = 0, $4 = 0, $cmp = 0, $rotation = 0, $5 = 0, $tobool = 0, $cond = 0, $id = 0, $6 = 0, $cmp9 = 0, $x16 = 0, $7 = 0, $y18 = 0, $8 = 0, $numPages = 0, $9 = 0, $10 = 0, $show_boxes20 = 0, $11 = 0, $cmp21 = 0, $sub = 0, $sub35 = 0, $x37 = 0, $12 = 0.0, $y39 = 0, $13 = 0.0, $14 = 0, $x41 = 0, $15 = 0.0, $y43 = 0, $16 = 0.0, $17 = 0, $cmp46 = 0, $cmp50 = 0, $cmp53 = 0, $or_cond = 0, $18 = 0, $errorfn = 0, $19 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $pbr_sroa_0_0__idx = $job + 456 | 0;
+ $pbr_sroa_0_0_copyload = HEAP32[$pbr_sroa_0_0__idx >> 2] | 0;
+ $pbr_sroa_1_4__idx4 = $job + 460 | 0;
+ $pbr_sroa_1_4_copyload = HEAP32[$pbr_sroa_1_4__idx4 >> 2] | 0;
+ $pbr_sroa_2_8__idx8 = $job + 464 | 0;
+ $pbr_sroa_2_8_copyload = HEAP32[$pbr_sroa_2_8__idx8 >> 2] | 0;
+ $pbr_sroa_3_12__idx14 = $job + 468 | 0;
+ $pbr_sroa_3_12_copyload = HEAP32[$pbr_sroa_3_12__idx14 >> 2] | 0;
+ $common = $job + 12 | 0;
+ $0 = HEAP32[$common >> 2] | 0;
+ $viewNum = $0 + 28 | 0;
+ $1 = HEAP32[$viewNum >> 2] | 0;
+ $add = $1 + 1 | 0;
+ $2 = $job;
+ _gvprintf($2, 135968, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $add, HEAP32[tempInt + 8 >> 2] = $add, tempInt) | 0);
+ $3 = HEAP32[$common >> 2] | 0;
+ $show_boxes = $3 + 20 | 0;
+ $4 = HEAP32[$show_boxes >> 2] | 0;
+ $cmp = ($4 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _gvprintf($2, 135736, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $pbr_sroa_0_0_copyload, HEAP32[tempInt + 8 >> 2] = $pbr_sroa_1_4_copyload, HEAP32[tempInt + 16 >> 2] = $pbr_sroa_2_8_copyload, HEAP32[tempInt + 24 >> 2] = $pbr_sroa_3_12_copyload, tempInt) | 0);
+ label = 4;
+ break;
+ case 4:
+ $rotation = $job + 360 | 0;
+ $5 = HEAP32[$rotation >> 2] | 0;
+ $tobool = ($5 | 0) != 0;
+ $cond = $tobool ? 135368 : 135128;
+ _gvprintf($2, 135552, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $cond, tempInt) | 0);
+ $id = $job + 64 | 0;
+ $6 = HEAP32[$id >> 2] | 0;
+ $cmp9 = ($6 | 0) == 1;
+ if ($cmp9) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ _gvprintf($2, 134888, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $pbr_sroa_2_8_copyload, HEAP32[tempInt + 8 >> 2] = $pbr_sroa_3_12_copyload, tempInt) | 0);
+ label = 6;
+ break;
+ case 6:
+ $x16 = $job + 196 | 0;
+ $7 = HEAP32[$x16 >> 2] | 0;
+ $y18 = $job + 200 | 0;
+ $8 = HEAP32[$y18 >> 2] | 0;
+ $numPages = $job + 204 | 0;
+ $9 = HEAP32[$numPages >> 2] | 0;
+ _gvprintf($2, 134680, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $7, HEAP32[tempInt + 8 >> 2] = $8, HEAP32[tempInt + 16 >> 2] = $9, tempInt) | 0);
+ $10 = HEAP32[$common >> 2] | 0;
+ $show_boxes20 = $10 + 20 | 0;
+ $11 = HEAP32[$show_boxes20 >> 2] | 0;
+ $cmp21 = ($11 | 0) == 0;
+ if ($cmp21) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $sub = $pbr_sroa_2_8_copyload - $pbr_sroa_0_0_copyload | 0;
+ $sub35 = $pbr_sroa_3_12_copyload - $pbr_sroa_1_4_copyload | 0;
+ _gvprintf($2, 134448, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $pbr_sroa_0_0_copyload, HEAP32[tempInt + 8 >> 2] = $pbr_sroa_1_4_copyload, HEAP32[tempInt + 16 >> 2] = $sub, HEAP32[tempInt + 24 >> 2] = $sub35, tempInt) | 0);
+ label = 8;
+ break;
+ case 8:
+ $x37 = $job + 488 | 0;
+ $12 = +HEAPF64[$x37 >> 3];
+ $y39 = $job + 496 | 0;
+ $13 = +HEAPF64[$y39 >> 3];
+ $14 = HEAP32[$rotation >> 2] | 0;
+ $x41 = $job + 504 | 0;
+ $15 = +HEAPF64[$x41 >> 3];
+ $y43 = $job + 512 | 0;
+ $16 = +HEAPF64[$y43 >> 3];
+ _gvprintf($2, 134200, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAPF64[tempInt >> 3] = $12, HEAPF64[tempInt + 8 >> 3] = $13, HEAP32[tempInt + 16 >> 2] = $14, HEAPF64[tempInt + 24 >> 3] = $15, HEAPF64[tempInt + 32 >> 3] = $16, tempInt) | 0);
+ $17 = HEAP32[$id >> 2] | 0;
+ $cmp46 = ($17 | 0) == 1;
+ if ($cmp46) {
+ label = 9;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 9:
+ $cmp50 = ($pbr_sroa_2_8_copyload | 0) > 14399;
+ $cmp53 = ($pbr_sroa_3_12_copyload | 0) > 14399;
+ $or_cond = $cmp50 | $cmp53;
+ if ($or_cond) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $18 = HEAP32[$common >> 2] | 0;
+ $errorfn = $18 + 16 | 0;
+ $19 = HEAP32[$errorfn >> 2] | 0;
+ FUNCTION_TABLE_vii[$19 & 1023](133848, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $pbr_sroa_2_8_copyload, HEAP32[tempInt + 8 >> 2] = $pbr_sroa_3_12_copyload, HEAP32[tempInt + 16 >> 2] = 14400, tempInt) | 0);
+ label = 11;
+ break;
+ case 11:
+ _gvprintf($2, 133536, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAP32[tempInt >> 2] = $pbr_sroa_0_0_copyload, HEAP32[tempInt + 8 >> 2] = $pbr_sroa_1_4_copyload, HEAP32[tempInt + 16 >> 2] = $pbr_sroa_2_8_copyload, HEAP32[tempInt + 24 >> 2] = $pbr_sroa_3_12_copyload, tempInt) | 0);
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_end_page($job) {
+ $job = $job | 0;
+ var $common = 0, $0 = 0, $show_boxes = 0, $1 = 0, $tobool = 0, $2 = 0, $call = 0, $3 = 0, $show_boxes2 = 0, $4 = 0, $add_ptr = 0, $5 = 0, $6 = 0, $call3 = 0, $call4 = 0, $7 = 0, $viewNum = 0, $8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $common = $job + 12 | 0;
+ $0 = HEAP32[$common >> 2] | 0;
+ $show_boxes = $0 + 20 | 0;
+ $1 = HEAP32[$show_boxes >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = $job;
+ $call = _gvputs($2, 137152) | 0;
+ $3 = HEAP32[$common >> 2] | 0;
+ $show_boxes2 = $3 + 20 | 0;
+ $4 = HEAP32[$show_boxes2 >> 2] | 0;
+ $add_ptr = $4 + 4 | 0;
+ $5 = $job;
+ _cat_libfile($5, 0, $add_ptr);
+ label = 4;
+ break;
+ case 4:
+ $6 = $job;
+ $call3 = _gvputs($6, 136864) | 0;
+ $call4 = _gvputs($6, 136592) | 0;
+ $7 = HEAP32[$common >> 2] | 0;
+ $viewNum = $7 + 28 | 0;
+ $8 = HEAP32[$viewNum >> 2] | 0;
+ _gvprintf($6, 136264, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $8, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_begin_cluster($job) {
+ $job = $job | 0;
+ var $3 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $3 = $job;
+ _gvprintf($3, 137400, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = HEAP32[(HEAP32[(HEAP32[$job + 16 >> 2] | 0) + 8 >> 2] | 0) + 12 >> 2] | 0, tempInt) | 0);
+ _gvputs($3, 137704);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _psgen_end_cluster($job) {
+ $job = $job | 0;
+ _gvputs($job, 137920);
+ return;
+}
+function _psgen_begin_node($job) {
+ $job = $job | 0;
+ _gvputs($job, 137704);
+ return;
+}
+function _psgen_end_node($job) {
+ $job = $job | 0;
+ _gvputs($job, 137920);
+ return;
+}
+function _psgen_begin_edge($job) {
+ $job = $job | 0;
+ _gvputs($job, 137704);
+ return;
+}
+function _psgen_end_edge($job) {
+ $job = $job | 0;
+ _gvputs($job, 137920);
+ return;
+}
+function _psgen_begin_anchor($job, $url, $tooltip, $target, $id) {
+ $job = $job | 0;
+ $url = $url | 0;
+ $tooltip = $tooltip | 0;
+ $target = $target | 0;
+ $id = $id | 0;
+ var $tobool = 0, $obj1 = 0, $0 = 0, $url_map_p = 0, $1 = 0, $tobool2 = 0, $2 = 0, $call = 0, $3 = 0, $call4 = 0, $4 = 0, $call5 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($url | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $url_map_p = $0 + 224 | 0;
+ $1 = HEAP32[$url_map_p >> 2] | 0;
+ $tobool2 = ($1 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = $job;
+ $call = _gvputs($2, 138784) | 0;
+ $3 = HEAP32[$url_map_p >> 2] | 0;
+ _gvprintpointflist($2, $3, 2);
+ $call4 = _gvputs($2, 138488) | 0;
+ $4 = HEAP32[3088] | 0;
+ $call5 = _ps_string($url, $4) | 0;
+ _gvprintf($2, 138160, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call5, tempInt) | 0);
+ label = 5;
+ break;
+ case 5:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_textpara($job, $p, $para) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $para = $para | 0;
+ var $obj = 0, $0 = 0, $arrayidx = 0, $1 = 0.0, $cmp = 0, $pencolor = 0, $fontsize = 0, $2 = 0.0, $3 = 0, $fontname = 0, $4 = 0, $str3 = 0, $5 = 0, $6 = 0, $call = 0, $just = 0, $7 = 0, $conv = 0, $width = 0, $8 = 0.0, $x = 0, $9 = 0.0, $sub = 0.0, $width8 = 0, $10 = 0.0, $div = 0.0, $x9 = 0, $11 = 0.0, $sub10 = 0.0, $yoffset_centerline = 0, $12 = 0.0, $y = 0, $13 = 0.0, $add = 0.0, $call11 = 0, $width12 = 0, $14 = 0.0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $arrayidx = $0 + 40 | 0;
+ $1 = +HEAPF64[$arrayidx >> 3];
+ $cmp = $1 < .5;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $pencolor = $0 + 16 | 0;
+ _ps_set_color($job, $pencolor);
+ $fontsize = $para + 24 | 0;
+ $2 = +HEAPF64[$fontsize >> 3];
+ $3 = $job;
+ _gvprintdouble($3, $2);
+ $fontname = $para + 20 | 0;
+ $4 = HEAP32[$fontname >> 2] | 0;
+ _gvprintf($3, 139576, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $4, tempInt) | 0);
+ $str3 = $para | 0;
+ $5 = HEAP32[$str3 >> 2] | 0;
+ $6 = HEAP32[3088] | 0;
+ $call = _ps_string($5, $6) | 0;
+ $just = $para + 72 | 0;
+ $7 = HEAP8[$just] | 0;
+ $conv = $7 << 24 >> 24;
+ if (($conv | 0) == 114) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 108) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $width = $para + 56 | 0;
+ $8 = +HEAPF64[$width >> 3];
+ $x = $p | 0;
+ $9 = +HEAPF64[$x >> 3];
+ $sub = $9 - $8;
+ HEAPF64[$x >> 3] = $sub;
+ label = 6;
+ break;
+ case 5:
+ $width8 = $para + 56 | 0;
+ $10 = +HEAPF64[$width8 >> 3];
+ $div = $10 * .5;
+ $x9 = $p | 0;
+ $11 = +HEAPF64[$x9 >> 3];
+ $sub10 = $11 - $div;
+ HEAPF64[$x9 >> 3] = $sub10;
+ label = 6;
+ break;
+ case 6:
+ $yoffset_centerline = $para + 48 | 0;
+ $12 = +HEAPF64[$yoffset_centerline >> 3];
+ $y = $p + 8 | 0;
+ $13 = +HEAPF64[$y >> 3];
+ $add = $12 + $13;
+ HEAPF64[$y >> 3] = $add;
+ _gvprintpointf($3, $p);
+ $call11 = _gvputs($3, 139312) | 0;
+ $width12 = $para + 56 | 0;
+ $14 = +HEAPF64[$width12 >> 3];
+ _gvprintdouble($3, $14);
+ _gvprintf($3, 139032, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call, tempInt) | 0);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_ellipse($job, $A, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $filled = $filled | 0;
+ var $AA = 0, $arrayidx = 0, $0 = 0, $1 = 0, $x = 0, $2 = 0.0, $x4 = 0, $3 = 0.0, $sub = 0.0, $x6 = 0, $y = 0, $4 = 0.0, $y9 = 0, $5 = 0.0, $sub10 = 0.0, $y12 = 0, $tobool = 0, $obj = 0, $6 = 0, $arrayidx13 = 0, $7 = 0.0, $cmp = 0, $fillcolor = 0, $8 = 0, $call = 0, $obj16 = 0, $9 = 0, $arrayidx19 = 0, $10 = 0.0, $cmp20 = 0, $11 = 0, $pencolor23 = 0, $12 = 0, $call25 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $AA = __stackBase__ | 0;
+ $arrayidx = $AA | 0;
+ $0 = $AA;
+ $1 = $A;
+ HEAP32[$0 >> 2] = HEAP32[$1 >> 2] | 0;
+ HEAP32[$0 + 4 >> 2] = HEAP32[$1 + 4 >> 2] | 0;
+ HEAP32[$0 + 8 >> 2] = HEAP32[$1 + 8 >> 2] | 0;
+ HEAP32[$0 + 12 >> 2] = HEAP32[$1 + 12 >> 2] | 0;
+ $x = $A + 16 | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x4 = $A | 0;
+ $3 = +HEAPF64[$x4 >> 3];
+ $sub = $2 - $3;
+ $x6 = $AA + 16 | 0;
+ HEAPF64[$x6 >> 3] = $sub;
+ $y = $A + 24 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y9 = $A + 8 | 0;
+ $5 = +HEAPF64[$y9 >> 3];
+ $sub10 = $4 - $5;
+ $y12 = $AA + 24 | 0;
+ HEAPF64[$y12 >> 3] = $sub10;
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $obj = $job + 16 | 0;
+ $6 = HEAP32[$obj >> 2] | 0;
+ $arrayidx13 = $6 + 80 | 0;
+ $7 = +HEAPF64[$arrayidx13 >> 3];
+ $cmp = $7 > .5;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $fillcolor = $6 + 56 | 0;
+ _ps_set_color($job, $fillcolor);
+ $8 = $job;
+ _gvprintpointflist($8, $arrayidx, 2);
+ $call = _gvputs($8, 140120) | 0;
+ label = 5;
+ break;
+ case 5:
+ $obj16 = $job + 16 | 0;
+ $9 = HEAP32[$obj16 >> 2] | 0;
+ $arrayidx19 = $9 + 40 | 0;
+ $10 = +HEAPF64[$arrayidx19 >> 3];
+ $cmp20 = $10 > .5;
+ if ($cmp20) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ _ps_set_pen_style($job);
+ $11 = HEAP32[$obj16 >> 2] | 0;
+ $pencolor23 = $11 + 16 | 0;
+ _ps_set_color($job, $pencolor23);
+ $12 = $job;
+ _gvprintpointflist($12, $arrayidx, 2);
+ $call25 = _gvputs($12, 139848) | 0;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _psgen_polygon($job, $A, $n, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, $obj = 0, $0 = 0, $arrayidx = 0, $1 = 0.0, $cmp = 0, $fillcolor = 0, $2 = 0, $call = 0, $call4 = 0, $cmp528 = 0, $j_029 = 0, $arrayidx6 = 0, $call7 = 0, $inc = 0, $cmp5 = 0, $call8 = 0, $obj9 = 0, $3 = 0, $arrayidx12 = 0, $4 = 0.0, $cmp13 = 0, $5 = 0, $pencolor16 = 0, $6 = 0, $call17 = 0, $call19 = 0, $cmp2126 = 0, $j_127 = 0, $arrayidx23 = 0, $call24 = 0, $inc26 = 0, $cmp21 = 0, $call28 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $arrayidx = $0 + 80 | 0;
+ $1 = +HEAPF64[$arrayidx >> 3];
+ $cmp = $1 > .5;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $fillcolor = $0 + 56 | 0;
+ _ps_set_color($job, $fillcolor);
+ $2 = $job;
+ $call = _gvputs($2, 142864) | 0;
+ _gvprintpointf($2, $A);
+ $call4 = _gvputs($2, 142520) | 0;
+ $cmp528 = ($n | 0) > 1;
+ if ($cmp528) {
+ $j_029 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $arrayidx6 = $A + ($j_029 << 4) | 0;
+ _gvprintpointf($2, $arrayidx6);
+ $call7 = _gvputs($2, 142256) | 0;
+ $inc = $j_029 + 1 | 0;
+ $cmp5 = ($inc | 0) < ($n | 0);
+ if ($cmp5) {
+ $j_029 = $inc;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call8 = _gvputs($2, 141408) | 0;
+ label = 7;
+ break;
+ case 7:
+ $obj9 = $job + 16 | 0;
+ $3 = HEAP32[$obj9 >> 2] | 0;
+ $arrayidx12 = $3 + 40 | 0;
+ $4 = +HEAPF64[$arrayidx12 >> 3];
+ $cmp13 = $4 > .5;
+ if ($cmp13) {
+ label = 8;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ _ps_set_pen_style($job);
+ $5 = HEAP32[$obj9 >> 2] | 0;
+ $pencolor16 = $5 + 16 | 0;
+ _ps_set_color($job, $pencolor16);
+ $6 = $job;
+ $call17 = _gvputs($6, 142864) | 0;
+ _gvprintpointf($6, $A);
+ $call19 = _gvputs($6, 142520) | 0;
+ $cmp2126 = ($n | 0) > 1;
+ if ($cmp2126) {
+ $j_127 = 1;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $arrayidx23 = $A + ($j_127 << 4) | 0;
+ _gvprintpointf($6, $arrayidx23);
+ $call24 = _gvputs($6, 142256) | 0;
+ $inc26 = $j_127 + 1 | 0;
+ $cmp21 = ($inc26 | 0) < ($n | 0);
+ if ($cmp21) {
+ $j_127 = $inc26;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call28 = _gvputs($6, 141176) | 0;
+ label = 11;
+ break;
+ case 11:
+ return;
+ }
+}
+function _psgen_bezier($job, $A, $n, $arrow_at_start, $arrow_at_end, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $arrow_at_start = $arrow_at_start | 0;
+ $arrow_at_end = $arrow_at_end | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, $obj = 0, $0 = 0, $arrayidx = 0, $1 = 0.0, $cmp = 0, $fillcolor = 0, $2 = 0, $call = 0, $call4 = 0, $cmp528 = 0, $j_029 = 0, $arrayidx6 = 0, $call7 = 0, $add = 0, $cmp5 = 0, $call8 = 0, $obj9 = 0, $3 = 0, $arrayidx12 = 0, $4 = 0.0, $cmp13 = 0, $5 = 0, $pencolor16 = 0, $6 = 0, $call17 = 0, $call19 = 0, $cmp2126 = 0, $j_127 = 0, $arrayidx23 = 0, $call24 = 0, $add26 = 0, $cmp21 = 0, $call28 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $arrayidx = $0 + 80 | 0;
+ $1 = +HEAPF64[$arrayidx >> 3];
+ $cmp = $1 > .5;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $fillcolor = $0 + 56 | 0;
+ _ps_set_color($job, $fillcolor);
+ $2 = $job;
+ $call = _gvputs($2, 142864) | 0;
+ _gvprintpointf($2, $A);
+ $call4 = _gvputs($2, 142520) | 0;
+ $cmp528 = ($n | 0) > 1;
+ if ($cmp528) {
+ $j_029 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $arrayidx6 = $A + ($j_029 << 4) | 0;
+ _gvprintpointflist($2, $arrayidx6, 3);
+ $call7 = _gvputs($2, 141720) | 0;
+ $add = $j_029 + 3 | 0;
+ $cmp5 = ($add | 0) < ($n | 0);
+ if ($cmp5) {
+ $j_029 = $add;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call8 = _gvputs($2, 141408) | 0;
+ label = 7;
+ break;
+ case 7:
+ $obj9 = $job + 16 | 0;
+ $3 = HEAP32[$obj9 >> 2] | 0;
+ $arrayidx12 = $3 + 40 | 0;
+ $4 = +HEAPF64[$arrayidx12 >> 3];
+ $cmp13 = $4 > .5;
+ if ($cmp13) {
+ label = 8;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ _ps_set_pen_style($job);
+ $5 = HEAP32[$obj9 >> 2] | 0;
+ $pencolor16 = $5 + 16 | 0;
+ _ps_set_color($job, $pencolor16);
+ $6 = $job;
+ $call17 = _gvputs($6, 142864) | 0;
+ _gvprintpointf($6, $A);
+ $call19 = _gvputs($6, 142520) | 0;
+ $cmp2126 = ($n | 0) > 1;
+ if ($cmp2126) {
+ $j_127 = 1;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $arrayidx23 = $A + ($j_127 << 4) | 0;
+ _gvprintpointflist($6, $arrayidx23, 3);
+ $call24 = _gvputs($6, 141720) | 0;
+ $add26 = $j_127 + 3 | 0;
+ $cmp21 = ($add26 | 0) < ($n | 0);
+ if ($cmp21) {
+ $j_127 = $add26;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call28 = _gvputs($6, 142016) | 0;
+ label = 11;
+ break;
+ case 11:
+ return;
+ }
+}
+function _psgen_polyline($job, $A, $n) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ var $obj = 0, $0 = 0, $arrayidx = 0, $1 = 0.0, $cmp = 0, $2 = 0, $pencolor2 = 0, $3 = 0, $call = 0, $call4 = 0, $cmp512 = 0, $j_013 = 0, $arrayidx6 = 0, $call7 = 0, $inc = 0, $cmp5 = 0, $call8 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $arrayidx = $0 + 40 | 0;
+ $1 = +HEAPF64[$arrayidx >> 3];
+ $cmp = $1 > .5;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ _ps_set_pen_style($job);
+ $2 = HEAP32[$obj >> 2] | 0;
+ $pencolor2 = $2 + 16 | 0;
+ _ps_set_color($job, $pencolor2);
+ $3 = $job;
+ $call = _gvputs($3, 142864) | 0;
+ _gvprintpointf($3, $A);
+ $call4 = _gvputs($3, 142520) | 0;
+ $cmp512 = ($n | 0) > 1;
+ if ($cmp512) {
+ $j_013 = 1;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $arrayidx6 = $A + ($j_013 << 4) | 0;
+ _gvprintpointf($3, $arrayidx6);
+ $call7 = _gvputs($3, 142256) | 0;
+ $inc = $j_013 + 1 | 0;
+ $cmp5 = ($inc | 0) < ($n | 0);
+ if ($cmp5) {
+ $j_013 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call8 = _gvputs($3, 142016) | 0;
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _psgen_comment($job, $str) {
+ $job = $job | 0;
+ $str = $str | 0;
+ var $0 = 0;
+ $0 = $job;
+ _gvputs($0, 143584);
+ _gvputs($0, $str);
+ _gvputs($0, 143192);
+ return;
+}
+function _psgen_library_shape($job, $name, $A, $n, $filled) {
+ $job = $job | 0;
+ $name = $name | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, $obj = 0, $0 = 0, $arrayidx = 0, $1 = 0.0, $cmp = 0, $fillcolor = 0, $2 = 0, $call = 0, $call3 = 0, $obj5 = 0, $3 = 0, $arrayidx8 = 0, $4 = 0.0, $cmp9 = 0, $5 = 0, $pencolor12 = 0, $6 = 0, $call13 = 0, $call14 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $arrayidx = $0 + 80 | 0;
+ $1 = +HEAPF64[$arrayidx >> 3];
+ $cmp = $1 > .5;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $fillcolor = $0 + 56 | 0;
+ _ps_set_color($job, $fillcolor);
+ $2 = $job;
+ $call = _gvputs($2, 147560) | 0;
+ _gvprintpointflist($2, $A, $n);
+ $call3 = _gvputs($2, 147256) | 0;
+ _gvprintpointf($2, $A);
+ _gvprintf($2, 147008, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $n, HEAP32[tempInt + 8 >> 2] = $name, tempInt) | 0);
+ label = 5;
+ break;
+ case 5:
+ $obj5 = $job + 16 | 0;
+ $3 = HEAP32[$obj5 >> 2] | 0;
+ $arrayidx8 = $3 + 40 | 0;
+ $4 = +HEAPF64[$arrayidx8 >> 3];
+ $cmp9 = $4 > .5;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ _ps_set_pen_style($job);
+ $5 = HEAP32[$obj5 >> 2] | 0;
+ $pencolor12 = $5 + 16 | 0;
+ _ps_set_color($job, $pencolor12);
+ $6 = $job;
+ $call13 = _gvputs($6, 147560) | 0;
+ _gvprintpointflist($6, $A, $n);
+ $call14 = _gvputs($6, 147256) | 0;
+ _gvprintpointf($6, $A);
+ _gvprintf($6, 146680, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $n, HEAP32[tempInt + 8 >> 2] = $name, tempInt) | 0);
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _ps_set_color($job, $color) {
+ $job = $job | 0;
+ $color = $color | 0;
+ var $tobool = 0, $obj = 0, $0 = 0, $type = 0, $1 = 0, $objtype_0 = 0, $arrayidx = 0, $2 = 0.0, $arrayidx5 = 0, $3 = 0.0, $arrayidx8 = 0, $4 = 0.0, $5 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($color | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $type = $0 + 4 | 0;
+ $1 = HEAP32[$type >> 2] | 0;
+ if (($1 | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($1 | 0) == 3) {
+ label = 5;
+ break;
+ } else if (($1 | 0) == 0 | ($1 | 0) == 1) {
+ $objtype_0 = 145016;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $objtype_0 = 144760;
+ label = 7;
+ break;
+ case 5:
+ $objtype_0 = 144496;
+ label = 7;
+ break;
+ case 6:
+ $objtype_0 = 144272;
+ label = 7;
+ break;
+ case 7:
+ $arrayidx = $color | 0;
+ $2 = +HEAPF64[$arrayidx >> 3];
+ $arrayidx5 = $color + 8 | 0;
+ $3 = +HEAPF64[$arrayidx5 >> 3];
+ $arrayidx8 = $color + 16 | 0;
+ $4 = +HEAPF64[$arrayidx8 >> 3];
+ $5 = $job;
+ _gvprintf($5, 143896, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $2, HEAPF64[tempInt + 8 >> 3] = $3, HEAPF64[tempInt + 16 >> 3] = $4, HEAP32[tempInt + 24 >> 2] = $objtype_0, tempInt) | 0);
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _ps_set_pen_style($job) {
+ $job = $job | 0;
+ var $obj = 0, $0 = 0, $penwidth1 = 0, $1 = 0.0, $rawstyle = 0, $2 = 0, $3 = 0, $call = 0, $tobool18 = 0, $s_019 = 0, $incdec_ptr = 0, $4 = 0, $tobool3 = 0, $call4 = 0, $cmp = 0, $p_0 = 0, $5 = 0, $tobool6 = 0, $incdec_ptr8 = 0, $6 = 0, $tobool1116 = 0, $7 = 0, $tobool11 = 0, $p_117 = 0, $p_2 = 0, $8 = 0, $tobool14 = 0, $incdec_ptr16 = 0, $call20 = 0, $cmp21 = 0, $9 = 0, $penwidth24 = 0, $tobool = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj = $job + 16 | 0;
+ $0 = HEAP32[$obj >> 2] | 0;
+ $penwidth1 = $0 + 104 | 0;
+ $1 = +HEAPF64[$penwidth1 >> 3];
+ $rawstyle = $0 + 112 | 0;
+ $2 = HEAP32[$rawstyle >> 2] | 0;
+ $3 = $job;
+ _gvprintdouble($3, $1);
+ $call = _gvputs($3, 146448) | 0;
+ $tobool18 = ($2 | 0) == 0;
+ if ($tobool18) {
+ label = 14;
+ break;
+ } else {
+ $s_019 = $2;
+ label = 3;
+ break;
+ }
+ case 3:
+ $incdec_ptr = $s_019 + 4 | 0;
+ $4 = HEAP32[$s_019 >> 2] | 0;
+ $tobool3 = ($4 | 0) == 0;
+ if ($tobool3) {
+ label = 14;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call4 = _strcmp($4 | 0, 146176) | 0;
+ $cmp = ($call4 | 0) == 0;
+ if ($cmp) {
+ label = 13;
+ break;
+ } else {
+ $p_0 = $4;
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP8[$p_0] | 0;
+ $tobool6 = $5 << 24 >> 24 == 0;
+ $incdec_ptr8 = $p_0 + 1 | 0;
+ if ($tobool6) {
+ label = 6;
+ break;
+ } else {
+ $p_0 = $incdec_ptr8;
+ label = 5;
+ break;
+ }
+ case 6:
+ $6 = HEAP8[$incdec_ptr8] | 0;
+ $tobool1116 = $6 << 24 >> 24 == 0;
+ if ($tobool1116) {
+ label = 10;
+ break;
+ } else {
+ $p_117 = $incdec_ptr8;
+ label = 8;
+ break;
+ }
+ case 7:
+ $7 = HEAP8[$incdec_ptr16] | 0;
+ $tobool11 = $7 << 24 >> 24 == 0;
+ if ($tobool11) {
+ label = 10;
+ break;
+ } else {
+ $p_117 = $incdec_ptr16;
+ label = 8;
+ break;
+ }
+ case 8:
+ _gvprintf($3, 145928, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $p_117, tempInt) | 0);
+ $p_2 = $p_117;
+ label = 9;
+ break;
+ case 9:
+ $8 = HEAP8[$p_2] | 0;
+ $tobool14 = $8 << 24 >> 24 == 0;
+ $incdec_ptr16 = $p_2 + 1 | 0;
+ if ($tobool14) {
+ label = 7;
+ break;
+ } else {
+ $p_2 = $incdec_ptr16;
+ label = 9;
+ break;
+ }
+ case 10:
+ $call20 = _strcmp($4 | 0, 145576) | 0;
+ $cmp21 = ($call20 | 0) == 0;
+ if ($cmp21) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $9 = HEAP32[$obj >> 2] | 0;
+ $penwidth24 = $9 + 104 | 0;
+ HEAPF64[$penwidth24 >> 3] = 0.0;
+ label = 12;
+ break;
+ case 12:
+ _gvprintf($3, 145304, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $4, tempInt) | 0);
+ label = 13;
+ break;
+ case 13:
+ $tobool = ($incdec_ptr | 0) == 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ $s_019 = $incdec_ptr;
+ label = 3;
+ break;
+ }
+ case 14:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_begin_job($job) {
+ $job = $job | 0;
+ var $0 = 0, $call = 0, $gvc = 0, $1 = 0, $g = 0, $2 = 0, $3 = 0, $call1 = 0, $tobool = 0, $4 = 0, $tobool2 = 0, $call3 = 0, $call4 = 0, $call5 = 0, $call6 = 0, $call7 = 0, $call8 = 0, $common = 0, $5 = 0, $info = 0, $6 = 0, $7 = 0, $call10 = 0, $call11 = 0, $call12 = 0, $8 = 0, $info14 = 0, $9 = 0, $arrayidx15 = 0, $10 = 0, $call16 = 0, $call17 = 0, $call18 = 0, $11 = 0, $info20 = 0, $12 = 0, $arrayidx21 = 0, $13 = 0, $call22 = 0, $call23 = 0, $call24 = 0, $call25 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 128896) | 0;
+ $gvc = $job | 0;
+ $1 = HEAP32[$gvc >> 2] | 0;
+ $g = $1 + 128 | 0;
+ $2 = HEAP32[$g >> 2] | 0;
+ $3 = $2 | 0;
+ $call1 = _agget($3, 128768) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $4 = HEAP8[$call1] | 0;
+ $tobool2 = $4 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call3 = _gvputs($0, 128544) | 0;
+ $call4 = _gvputs($0, $call1) | 0;
+ $call5 = _gvputs($0, 128360) | 0;
+ label = 5;
+ break;
+ case 5:
+ $call6 = _gvputs($0, 127984) | 0;
+ $call7 = _gvputs($0, 127704) | 0;
+ $call8 = _gvputs($0, 127424) | 0;
+ $common = $job + 12 | 0;
+ $5 = HEAP32[$common >> 2] | 0;
+ $info = $5 | 0;
+ $6 = HEAP32[$info >> 2] | 0;
+ $7 = HEAP32[$6 >> 2] | 0;
+ $call10 = _xml_string($7) | 0;
+ $call11 = _gvputs($0, $call10) | 0;
+ $call12 = _gvputs($0, 127104) | 0;
+ $8 = HEAP32[$common >> 2] | 0;
+ $info14 = $8 | 0;
+ $9 = HEAP32[$info14 >> 2] | 0;
+ $arrayidx15 = $9 + 4 | 0;
+ $10 = HEAP32[$arrayidx15 >> 2] | 0;
+ $call16 = _xml_string($10) | 0;
+ $call17 = _gvputs($0, $call16) | 0;
+ $call18 = _gvputs($0, 126848) | 0;
+ $11 = HEAP32[$common >> 2] | 0;
+ $info20 = $11 | 0;
+ $12 = HEAP32[$info20 >> 2] | 0;
+ $arrayidx21 = $12 + 8 | 0;
+ $13 = HEAP32[$arrayidx21 >> 2] | 0;
+ $call22 = _xml_string($13) | 0;
+ $call23 = _gvputs($0, $call22) | 0;
+ $call24 = _gvputs($0, 126584) | 0;
+ $call25 = _gvputs($0, 146440) | 0;
+ return;
+ }
+}
+function _svg_begin_graph($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $1 = 0, $call = 0, $g = 0, $2 = 0, $name = 0, $3 = 0, $4 = 0, $tobool = 0, $call2 = 0, $5 = 0, $name5 = 0, $6 = 0, $call6 = 0, $call7 = 0, $x = 0, $7 = 0, $y = 0, $8 = 0, $mul = 0, $width = 0, $9 = 0, $height = 0, $10 = 0, $x9 = 0, $11 = 0.0, $y12 = 0, $12 = 0.0, $x14 = 0, $13 = 0.0, $y17 = 0, $14 = 0.0, $call18 = 0, $call19 = 0, $call20 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $1 = $job;
+ $call = _gvputs($1, 130232) | 0;
+ $g = $0 + 8 | 0;
+ $2 = HEAP32[$g >> 2] | 0;
+ $name = $2 + 12 | 0;
+ $3 = HEAP32[$name >> 2] | 0;
+ $4 = HEAP8[$3] | 0;
+ $tobool = $4 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call2 = _gvputs($1, 130040) | 0;
+ $5 = HEAP32[$g >> 2] | 0;
+ $name5 = $5 + 12 | 0;
+ $6 = HEAP32[$name5 >> 2] | 0;
+ $call6 = _xml_string($6) | 0;
+ $call7 = _gvputs($1, $call6) | 0;
+ label = 4;
+ break;
+ case 4:
+ $x = $job + 164 | 0;
+ $7 = HEAP32[$x >> 2] | 0;
+ $y = $job + 168 | 0;
+ $8 = HEAP32[$y >> 2] | 0;
+ $mul = Math_imul($8, $7);
+ _gvprintf($1, 129888, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $mul, tempInt) | 0);
+ $width = $job + 448 | 0;
+ $9 = HEAP32[$width >> 2] | 0;
+ $height = $job + 452 | 0;
+ $10 = HEAP32[$height >> 2] | 0;
+ _gvprintf($1, 129704, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $9, HEAP32[tempInt + 8 >> 2] = $10, tempInt) | 0);
+ $x9 = $job + 384 | 0;
+ $11 = +HEAPF64[$x9 >> 3];
+ $y12 = $job + 392 | 0;
+ $12 = +HEAPF64[$y12 >> 3];
+ $x14 = $job + 400 | 0;
+ $13 = +HEAPF64[$x14 >> 3];
+ $y17 = $job + 408 | 0;
+ $14 = +HEAPF64[$y17 >> 3];
+ _gvprintf($1, 129480, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $11, HEAPF64[tempInt + 8 >> 3] = $12, HEAPF64[tempInt + 16 >> 3] = $13, HEAPF64[tempInt + 24 >> 3] = $14, tempInt) | 0);
+ $call18 = _gvputs($1, 129256) | 0;
+ $call19 = _gvputs($1, 129072) | 0;
+ $call20 = _gvputs($1, 132528) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_end_graph($job) {
+ $job = $job | 0;
+ _gvputs($job, 130416);
+ return;
+}
+function _svg_begin_layer($job, $layername, $layerNum, $numLayers) {
+ $job = $job | 0;
+ $layername = $layername | 0;
+ $layerNum = $layerNum | 0;
+ $numLayers = $numLayers | 0;
+ var $0 = 0;
+ $0 = $job;
+ _gvputs($0, 132224);
+ _gvputs($0, _xml_string($layername) | 0);
+ _gvputs($0, 130592);
+ return;
+}
+function _svg_end_layer($job) {
+ $job = $job | 0;
+ _gvputs($job, 132392);
+ return;
+}
+function _svg_begin_page($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $1 = 0, $call = 0, $id = 0, $2 = 0, $call2 = 0, $call3 = 0, $call4 = 0, $x = 0, $3 = 0.0, $y = 0, $4 = 0.0, $rotation = 0, $5 = 0, $sub = 0, $x6 = 0, $6 = 0.0, $y8 = 0, $7 = 0.0, $sub9 = 0.0, $g = 0, $8 = 0, $name = 0, $9 = 0, $10 = 0, $tobool = 0, $call10 = 0, $11 = 0, $name13 = 0, $12 = 0, $call14 = 0, $call15 = 0, $call16 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $1 = $job;
+ $call = _gvputs($1, 132224) | 0;
+ $id = $0 + 164 | 0;
+ $2 = HEAP32[$id >> 2] | 0;
+ $call2 = _xml_string($2) | 0;
+ $call3 = _gvputs($1, $call2) | 0;
+ $call4 = _gvputs($1, 130936) | 0;
+ $x = $job + 488 | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $y = $job + 496 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $rotation = $job + 360 | 0;
+ $5 = HEAP32[$rotation >> 2] | 0;
+ $sub = -$5 | 0;
+ $x6 = $job + 504 | 0;
+ $6 = +HEAPF64[$x6 >> 3];
+ $y8 = $job + 512 | 0;
+ $7 = +HEAPF64[$y8 >> 3];
+ $sub9 = -0.0 - $7;
+ _gvprintf($1, 130744, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAPF64[tempInt >> 3] = $3, HEAPF64[tempInt + 8 >> 3] = $4, HEAP32[tempInt + 16 >> 2] = $sub, HEAPF64[tempInt + 24 >> 3] = $6, HEAPF64[tempInt + 32 >> 3] = $sub9, tempInt) | 0);
+ $g = $0 + 8 | 0;
+ $8 = HEAP32[$g >> 2] | 0;
+ $name = $8 + 12 | 0;
+ $9 = HEAP32[$name >> 2] | 0;
+ $10 = HEAP8[$9] | 0;
+ $tobool = $10 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call10 = _gvputs($1, 131880) | 0;
+ $11 = HEAP32[$g >> 2] | 0;
+ $name13 = $11 + 12 | 0;
+ $12 = HEAP32[$name13 >> 2] | 0;
+ $call14 = _xml_string($12) | 0;
+ $call15 = _gvputs($1, $call14) | 0;
+ $call16 = _gvputs($1, 131424) | 0;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_end_page($job) {
+ $job = $job | 0;
+ _gvputs($job, 132392);
+ return;
+}
+function _svg_begin_cluster($job) {
+ $job = $job | 0;
+ var $0 = 0, $1 = 0;
+ $0 = HEAP32[$job + 16 >> 2] | 0;
+ $1 = $job;
+ _gvputs($1, 132224);
+ _gvputs($1, _xml_string(HEAP32[$0 + 164 >> 2] | 0) | 0);
+ _gvputs($1, 131072);
+ _gvputs($1, 131880);
+ _gvputs($1, _xml_string(HEAP32[(HEAP32[$0 + 8 >> 2] | 0) + 12 >> 2] | 0) | 0);
+ _gvputs($1, 131424);
+ return;
+}
+function _svg_end_cluster($job) {
+ $job = $job | 0;
+ _gvputs($job, 132392);
+ return;
+}
+function _svg_begin_node($job) {
+ $job = $job | 0;
+ var $0 = 0, $1 = 0;
+ $0 = HEAP32[$job + 16 >> 2] | 0;
+ $1 = $job;
+ _gvputs($1, 132224);
+ _gvputs($1, _xml_string(HEAP32[$0 + 164 >> 2] | 0) | 0);
+ _gvputs($1, 131264);
+ _gvputs($1, 131880);
+ _gvputs($1, _xml_string(HEAP32[(HEAP32[$0 + 8 >> 2] | 0) + 12 >> 2] | 0) | 0);
+ _gvputs($1, 131424);
+ return;
+}
+function _svg_end_node($job) {
+ $job = $job | 0;
+ _gvputs($job, 132392);
+ return;
+}
+function _svg_begin_edge($job) {
+ $job = $job | 0;
+ var $0 = 0, $1 = 0, $call6 = 0;
+ $0 = HEAP32[$job + 16 >> 2] | 0;
+ $1 = $job;
+ _gvputs($1, 132224);
+ _gvputs($1, _xml_string(HEAP32[$0 + 164 >> 2] | 0) | 0);
+ _gvputs($1, 132024);
+ _gvputs($1, 131880);
+ $call6 = _strdup_and_subst_obj(131584, HEAP32[$0 + 8 >> 2] | 0) | 0;
+ _gvputs($1, _xml_string($call6) | 0);
+ _free($call6);
+ _gvputs($1, 131424);
+ return;
+}
+function _svg_end_edge($job) {
+ $job = $job | 0;
+ _gvputs($job, 132392);
+ return;
+}
+function _svg_begin_anchor($job, $href, $tooltip, $target, $id) {
+ $job = $job | 0;
+ $href = $href | 0;
+ $tooltip = $tooltip | 0;
+ $target = $target | 0;
+ $id = $id | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $1 = 0, $tobool1 = 0, $call2 = 0, $call3 = 0, $call4 = 0, $call5 = 0, $tobool6 = 0, $2 = 0, $tobool10 = 0, $call12 = 0, $call13 = 0, $call14 = 0, $call15 = 0, $tobool17 = 0, $3 = 0, $tobool21 = 0, $call23 = 0, $call24 = 0, $call25 = 0, $call26 = 0, $call28 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 133512) | 0;
+ $tobool = ($href | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$href] | 0;
+ $tobool1 = $1 << 24 >> 24 == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call2 = _gvputs($0, 133272) | 0;
+ $call3 = _xml_url_string($href) | 0;
+ $call4 = _gvputs($0, $call3) | 0;
+ $call5 = _gvputs($0, 142856) | 0;
+ label = 5;
+ break;
+ case 5:
+ $tobool6 = ($tooltip | 0) == 0;
+ if ($tobool6) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $2 = HEAP8[$tooltip] | 0;
+ $tobool10 = $2 << 24 >> 24 == 0;
+ if ($tobool10) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call12 = _gvputs($0, 132936) | 0;
+ $call13 = _xml_string($tooltip) | 0;
+ $call14 = _gvputs($0, $call13) | 0;
+ $call15 = _gvputs($0, 142856) | 0;
+ label = 8;
+ break;
+ case 8:
+ $tobool17 = ($target | 0) == 0;
+ if ($tobool17) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $3 = HEAP8[$target] | 0;
+ $tobool21 = $3 << 24 >> 24 == 0;
+ if ($tobool21) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call23 = _gvputs($0, 132712) | 0;
+ $call24 = _xml_string($target) | 0;
+ $call25 = _gvputs($0, $call24) | 0;
+ $call26 = _gvputs($0, 142856) | 0;
+ label = 11;
+ break;
+ case 11:
+ $call28 = _gvputs($0, 132528) | 0;
+ return;
+ }
+}
+function _tkgen_begin_node($job) {
+ $job = $job | 0;
+ HEAP32[4110] = 1;
+ return;
+}
+function _tkgen_begin_edge($job) {
+ $job = $job | 0;
+ HEAP32[4110] = -1;
+ return;
+}
+function _tkgen_string($s) {
+ $s = $s | 0;
+ return $s | 0;
+}
+function _svg_end_anchor($job) {
+ $job = $job | 0;
+ _gvputs($job, 133800);
+ return;
+}
+function _svg_ellipse($job, $A, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $filled = $filled | 0;
+ var $0 = 0, $x = 0, $y = 0, $sub = 0.0, $sub11 = 0.0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $0 = $job;
+ _gvputs($0, 138968);
+ _svg_grstyle($job, $filled);
+ $x = $A | 0;
+ $y = $A + 8 | 0;
+ $sub = -0.0 - +HEAPF64[$y >> 3];
+ _gvprintf($0, 138712, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = +HEAPF64[$x >> 3], HEAPF64[tempInt + 8 >> 3] = $sub, tempInt) | 0);
+ $sub11 = +HEAPF64[$A + 24 >> 3] - +HEAPF64[$y >> 3];
+ _gvprintf($0, 138464, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = +HEAPF64[$A + 16 >> 3] - +HEAPF64[$x >> 3], HEAPF64[tempInt + 8 >> 3] = $sub11, tempInt) | 0);
+ _gvputs($0, 138136);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _svg_polygon($job, $A, $n, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $0 = 0, $call = 0, $call1 = 0, $cmp11 = 0, $i_012 = 0, $x = 0, $1 = 0.0, $y = 0, $2 = 0.0, $sub = 0.0, $inc = 0, $cmp = 0, $x4 = 0, $3 = 0.0, $y6 = 0, $4 = 0.0, $sub7 = 0.0, $call8 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 139528) | 0;
+ _svg_grstyle($job, $filled);
+ $call1 = _gvputs($0, 145912) | 0;
+ $cmp11 = ($n | 0) > 0;
+ if ($cmp11) {
+ $i_012 = 0;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $x = $A + ($i_012 << 4) | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $y = $A + ($i_012 << 4) + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $sub = -0.0 - $2;
+ _gvprintf($0, 145528, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $1, HEAPF64[tempInt + 8 >> 3] = $sub, tempInt) | 0);
+ $inc = $i_012 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_012 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $x4 = $A | 0;
+ $3 = +HEAPF64[$x4 >> 3];
+ $y6 = $A + 8 | 0;
+ $4 = +HEAPF64[$y6 >> 3];
+ $sub7 = -0.0 - $4;
+ _gvprintf($0, 139304, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $3, HEAPF64[tempInt + 8 >> 3] = $sub7, tempInt) | 0);
+ $call8 = _gvputs($0, 145296) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_bezier($job, $A, $n, $arrow_at_start, $arrow_at_end, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $arrow_at_start = $arrow_at_start | 0;
+ $arrow_at_end = $arrow_at_end | 0;
+ $filled = $filled | 0;
+ var $0 = 0;
+ $0 = $job;
+ _gvputs($0, 141168);
+ _svg_grstyle($job, $filled);
+ _gvputs($0, 140112);
+ _svg_bzptarray($job, $A, $n);
+ _gvputs($0, 145296);
+ return;
+}
+function _svg_polyline($job, $A, $n) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ var $0 = 0, $call = 0, $call1 = 0, $cmp8 = 0, $i_09 = 0, $x = 0, $1 = 0.0, $y = 0, $2 = 0.0, $sub = 0.0, $inc = 0, $cmp = 0, $call3 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 146152) | 0;
+ _svg_grstyle($job, 0);
+ $call1 = _gvputs($0, 145912) | 0;
+ $cmp8 = ($n | 0) > 0;
+ if ($cmp8) {
+ $i_09 = 0;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $x = $A + ($i_09 << 4) | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $y = $A + ($i_09 << 4) + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $sub = -0.0 - $2;
+ _gvprintf($0, 145528, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $1, HEAPF64[tempInt + 8 >> 3] = $sub, tempInt) | 0);
+ $inc = $i_09 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_09 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call3 = _gvputs($0, 145296) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_comment($job, $str) {
+ $job = $job | 0;
+ $str = $str | 0;
+ var $0 = 0;
+ $0 = $job;
+ _gvputs($0, 146672);
+ _gvputs($0, _xml_string($str) | 0);
+ _gvputs($0, 146440);
+ return;
+}
+function _svg_grstyle($job, $filled) {
+ $job = $job | 0;
+ $filled = $filled | 0;
+ var $obj1 = 0, $0 = 0, $1 = 0, $call = 0, $tobool = 0, $fillcolor = 0, $type = 0, $2 = 0, $cmp = 0, $rgba = 0, $arrayidx = 0, $3 = 0, $conv19 = 0.0, $conv20 = 0.0, $div = 0.0, $call21 = 0, $call23 = 0, $pencolor = 0, $penwidth = 0, $4 = 0.0, $cmp24 = 0, $pen = 0, $5 = 0, $type40 = 0, $6 = 0, $cmp41 = 0, $rgba46 = 0, $arrayidx47 = 0, $7 = 0, $conv64 = 0.0, $conv65 = 0.0, $div66 = 0.0, $call68 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $1 = $job;
+ $call = _gvputs($1, 145008) | 0;
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $fillcolor = $0 + 56 | 0;
+ _svg_print_color($job, $fillcolor);
+ $type = $0 + 88 | 0;
+ $2 = HEAP32[$type >> 2] | 0;
+ $cmp = ($2 | 0) == 1;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $rgba = $fillcolor;
+ $arrayidx = $rgba + 3 | 0;
+ $3 = HEAP8[$arrayidx] | 0;
+ if (($3 << 24 >> 24 | 0) == 0 | ($3 << 24 >> 24 | 0) == (-1 | 0)) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $conv19 = +(($3 & 255) >>> 0);
+ $conv20 = $conv19;
+ $div = $conv20 / 255.0;
+ _gvprintf($1, 144720, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $div, tempInt) | 0);
+ label = 7;
+ break;
+ case 6:
+ $call21 = _gvputs($1, 144488) | 0;
+ label = 7;
+ break;
+ case 7:
+ $call23 = _gvputs($1, 144256) | 0;
+ $pencolor = $0 + 16 | 0;
+ _svg_print_color($job, $pencolor);
+ $penwidth = $0 + 104 | 0;
+ $4 = +HEAPF64[$penwidth >> 3];
+ $cmp24 = $4 != 1.0;
+ if ($cmp24) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ _gvprintf($1, 143872, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $4, tempInt) | 0);
+ label = 9;
+ break;
+ case 9:
+ $pen = $0 + 96 | 0;
+ $5 = HEAP32[$pen >> 2] | 0;
+ if (($5 | 0) == 1) {
+ label = 10;
+ break;
+ } else if (($5 | 0) == 2) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 10:
+ _gvprintf($1, 143560, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = 142248, tempInt) | 0);
+ label = 12;
+ break;
+ case 11:
+ _gvprintf($1, 143560, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = 142480, tempInt) | 0);
+ label = 12;
+ break;
+ case 12:
+ $type40 = $0 + 48 | 0;
+ $6 = HEAP32[$type40 >> 2] | 0;
+ $cmp41 = ($6 | 0) == 1;
+ if ($cmp41) {
+ label = 13;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $rgba46 = $pencolor;
+ $arrayidx47 = $rgba46 + 3 | 0;
+ $7 = HEAP8[$arrayidx47] | 0;
+ if (($7 << 24 >> 24 | 0) == 0 | ($7 << 24 >> 24 | 0) == (-1 | 0)) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $conv64 = +(($7 & 255) >>> 0);
+ $conv65 = $conv64;
+ $div66 = $conv65 / 255.0;
+ _gvprintf($1, 143152, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $div66, tempInt) | 0);
+ label = 15;
+ break;
+ case 15:
+ $call68 = _gvputs($1, 142856) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_bzptarray($job, $A, $n) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ var $cmp7 = 0, $0 = 0, $c_09 = 0, $i_08 = 0, $conv6 = 0, $x = 0, $1 = 0.0, $y = 0, $2 = 0.0, $sub = 0.0, $cmp2 = 0, $_ = 0, $inc = 0, $cmp = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp7 = ($n | 0) > 0;
+ if ($cmp7) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $0 = $job;
+ $i_08 = 0;
+ $c_09 = 77;
+ label = 4;
+ break;
+ case 4:
+ $conv6 = $c_09 & 255;
+ $x = $A + ($i_08 << 4) | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $y = $A + ($i_08 << 4) + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $sub = -0.0 - $2;
+ _gvprintf($0, 139840, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $conv6, HEAPF64[tempInt + 8 >> 3] = $1, HEAPF64[tempInt + 16 >> 3] = $sub, tempInt) | 0);
+ $cmp2 = ($i_08 | 0) == 0;
+ $_ = $cmp2 ? 67 : 32;
+ $inc = $i_08 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_08 = $inc;
+ $c_09 = $_;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _tkgen_begin_job($job) {
+ $job = $job | 0;
+ var $0 = 0, $common = 0;
+ $0 = $job;
+ _gvputs($0, 114832);
+ $common = $job + 12 | 0;
+ _gvputs($0, _tkgen_string(HEAP32[HEAP32[HEAP32[$common >> 2] >> 2] >> 2] | 0) | 0);
+ _gvputs($0, 114200);
+ _gvputs($0, _tkgen_string(HEAP32[(HEAP32[HEAP32[$common >> 2] >> 2] | 0) + 4 >> 2] | 0) | 0);
+ _gvputs($0, 113728);
+ _gvputs($0, _tkgen_string(HEAP32[(HEAP32[HEAP32[$common >> 2] >> 2] | 0) + 8 >> 2] | 0) | 0);
+ _gvputs($0, 113296);
+ return;
+}
+function _tkgen_begin_graph($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $1 = 0, $call = 0, $g = 0, $2 = 0, $name = 0, $3 = 0, $4 = 0, $tobool = 0, $call2 = 0, $5 = 0, $name5 = 0, $6 = 0, $call6 = 0, $call7 = 0, $x = 0, $7 = 0, $y = 0, $8 = 0, $mul = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $1 = $job;
+ $call = _gvputs($1, 116336) | 0;
+ $g = $0 + 8 | 0;
+ $2 = HEAP32[$g >> 2] | 0;
+ $name = $2 + 12 | 0;
+ $3 = HEAP32[$name >> 2] | 0;
+ $4 = HEAP8[$3] | 0;
+ $tobool = $4 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call2 = _gvputs($1, 115832) | 0;
+ $5 = HEAP32[$g >> 2] | 0;
+ $name5 = $5 + 12 | 0;
+ $6 = HEAP32[$name5 >> 2] | 0;
+ $call6 = _tkgen_string($6) | 0;
+ $call7 = _gvputs($1, $call6) | 0;
+ label = 4;
+ break;
+ case 4:
+ $x = $job + 164 | 0;
+ $7 = HEAP32[$x >> 2] | 0;
+ $y = $job + 168 | 0;
+ $8 = HEAP32[$y >> 2] | 0;
+ $mul = Math_imul($8, $7);
+ _gvprintf($1, 115376, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $mul, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _tkgen_textpara($job, $p, $para) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $para = $para | 0;
+ var $obj1 = 0, $0 = 0, $pen = 0, $1 = 0, $cmp = 0, $fontsize = 0, $2 = 0.0, $zoom = 0, $3 = 0.0, $mul = 0.0, $conv = 0, $tobool = 0, $4 = 0, $call = 0, $conv3 = 0.0, $mul4 = 0.0, $y = 0, $5 = 0.0, $sub = 0.0, $call5 = 0, $str = 0, $6 = 0, $call6 = 0, $call7 = 0, $call8 = 0, $pencolor = 0, $call9 = 0, $postscript_alias = 0, $7 = 0, $tobool10 = 0, $family = 0, $fontname = 0, $font_0_in = 0, $font_0 = 0, $call13 = 0, $call14 = 0, $call15 = 0, $just = 0, $8 = 0, $conv16 = 0, $call17 = 0, $call19 = 0, $call21 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $pen = $0 + 96 | 0;
+ $1 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $fontsize = $para + 24 | 0;
+ $2 = +HEAPF64[$fontsize >> 3];
+ $zoom = $job + 352 | 0;
+ $3 = +HEAPF64[$zoom >> 3];
+ $mul = $2 * $3;
+ $conv = ~~$mul;
+ $tobool = ($conv | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _tkgen_canvas($job);
+ $4 = $job;
+ $call = _gvputs($4, 121048) | 0;
+ $conv3 = +($conv | 0);
+ $mul4 = $conv3 * .55;
+ $y = $p + 8 | 0;
+ $5 = +HEAPF64[$y >> 3];
+ $sub = $5 - $mul4;
+ HEAPF64[$y >> 3] = $sub;
+ _gvprintpointf($4, $p);
+ $call5 = _gvputs($4, 120360) | 0;
+ $str = $para | 0;
+ $6 = HEAP32[$str >> 2] | 0;
+ $call6 = _gvputs($4, $6) | 0;
+ $call7 = _gvputs($4, 119720) | 0;
+ $call8 = _gvputs($4, 107048) | 0;
+ $pencolor = $0 + 16 | 0;
+ _tkgen_print_color($job, $pencolor);
+ $call9 = _gvputs($4, 119176) | 0;
+ $postscript_alias = $para + 4 | 0;
+ $7 = HEAP32[$postscript_alias >> 2] | 0;
+ $tobool10 = ($7 | 0) == 0;
+ $family = $7 + 4 | 0;
+ $fontname = $para + 20 | 0;
+ $font_0_in = $tobool10 ? $fontname : $family;
+ $font_0 = HEAP32[$font_0_in >> 2] | 0;
+ $call13 = _gvputs($4, 118656) | 0;
+ $call14 = _gvputs($4, $font_0) | 0;
+ $call15 = _gvputs($4, 118656) | 0;
+ _gvprintf($4, 118064, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $conv, tempInt) | 0);
+ $just = $para + 72 | 0;
+ $8 = HEAP8[$just] | 0;
+ $conv16 = $8 << 24 >> 24;
+ if (($conv16 | 0) == 108) {
+ label = 5;
+ break;
+ } else if (($conv16 | 0) == 114) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $call17 = _gvputs($4, 117504) | 0;
+ label = 7;
+ break;
+ case 6:
+ $call19 = _gvputs($4, 116816) | 0;
+ label = 7;
+ break;
+ case 7:
+ _tkgen_print_tags($job);
+ $call21 = _gvputs($4, 116384) | 0;
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _tkgen_ellipse($job, $A, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $filled = $filled | 0;
+ var $obj1 = 0, $0 = 0, $pen = 0, $1 = 0, $cmp = 0, $x = 0, $2 = 0.0, $x3 = 0, $3 = 0.0, $sub = 0.0, $y = 0, $4 = 0.0, $y7 = 0, $5 = 0.0, $sub8 = 0.0, $sub13 = 0.0, $6 = 0.0, $sub17 = 0.0, $7 = 0, $call = 0, $call18 = 0, $tobool = 0, $fillcolor = 0, $8 = 0, $tobool20 = 0, $call22 = 0, $call24 = 0, $9 = 0, $cmp26 = 0, $call29 = 0, $penwidth = 0, $10 = 0.0, $call30 = 0, $pencolor = 0, $11 = 0, $cmp32 = 0, $call34 = 0, $_pr = 0, $12 = 0, $cmp37 = 0, $call39 = 0, $call41 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $pen = $0 + 96 | 0;
+ $1 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 15;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $x = $A + 16 | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $x3 = $A | 0;
+ $3 = +HEAPF64[$x3 >> 3];
+ $sub = $2 - $3;
+ $y = $A + 24 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y7 = $A + 8 | 0;
+ $5 = +HEAPF64[$y7 >> 3];
+ $sub8 = $4 - $5;
+ $sub13 = $3 - $sub;
+ HEAPF64[$x3 >> 3] = $sub13;
+ $6 = +HEAPF64[$y7 >> 3];
+ $sub17 = $6 - $sub8;
+ HEAPF64[$y7 >> 3] = $sub17;
+ _tkgen_canvas($job);
+ $7 = $job;
+ $call = _gvputs($7, 121656) | 0;
+ _gvprintpointflist($7, $A, 2);
+ $call18 = _gvputs($7, 107048) | 0;
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $fillcolor = $0 + 56 | 0;
+ _tkgen_print_color($job, $fillcolor);
+ label = 8;
+ break;
+ case 5:
+ $8 = HEAP32[4110] | 0;
+ $tobool20 = ($8 | 0) == 0;
+ if ($tobool20) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call22 = _gvputs($7, 124864) | 0;
+ label = 8;
+ break;
+ case 7:
+ $call24 = _gvputs($7, 138688) | 0;
+ label = 8;
+ break;
+ case 8:
+ $9 = HEAP32[4110] | 0;
+ $cmp26 = ($9 | 0) == 1;
+ if ($cmp26) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ HEAP32[4110] = 0;
+ label = 10;
+ break;
+ case 10:
+ $call29 = _gvputs($7, 131400) | 0;
+ $penwidth = $0 + 104 | 0;
+ $10 = +HEAPF64[$penwidth >> 3];
+ _gvprintdouble($7, $10);
+ $call30 = _gvputs($7, 122888) | 0;
+ $pencolor = $0 + 16 | 0;
+ _tkgen_print_color($job, $pencolor);
+ $11 = HEAP32[$pen >> 2] | 0;
+ $cmp32 = ($11 | 0) == 1;
+ if ($cmp32) {
+ label = 11;
+ break;
+ } else {
+ $12 = $11;
+ label = 12;
+ break;
+ }
+ case 11:
+ $call34 = _gvputs($7, 103120) | 0;
+ $_pr = HEAP32[$pen >> 2] | 0;
+ $12 = $_pr;
+ label = 12;
+ break;
+ case 12:
+ $cmp37 = ($12 | 0) == 2;
+ if ($cmp37) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $call39 = _gvputs($7, 99016) | 0;
+ label = 14;
+ break;
+ case 14:
+ _tkgen_print_tags($job);
+ $call41 = _gvputs($7, 116384) | 0;
+ label = 15;
+ break;
+ case 15:
+ return;
+ }
+}
+function _tkgen_polygon($job, $A, $n, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $obj1 = 0, $0 = 0, $pen = 0, $1 = 0, $cmp = 0, $2 = 0, $call = 0, $call2 = 0, $tobool = 0, $fillcolor = 0, $3 = 0, $tobool4 = 0, $call6 = 0, $call8 = 0, $4 = 0, $cmp10 = 0, $call13 = 0, $penwidth = 0, $5 = 0.0, $call14 = 0, $pencolor = 0, $6 = 0, $cmp16 = 0, $call18 = 0, $_pr = 0, $7 = 0, $cmp21 = 0, $call23 = 0, $call25 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $pen = $0 + 96 | 0;
+ $1 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 15;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _tkgen_canvas($job);
+ $2 = $job;
+ $call = _gvputs($2, 127368) | 0;
+ _gvprintpointflist($2, $A, $n);
+ $call2 = _gvputs($2, 107048) | 0;
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $fillcolor = $0 + 56 | 0;
+ _tkgen_print_color($job, $fillcolor);
+ label = 8;
+ break;
+ case 5:
+ $3 = HEAP32[4110] | 0;
+ $tobool4 = ($3 | 0) == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call6 = _gvputs($2, 124864) | 0;
+ label = 8;
+ break;
+ case 7:
+ $call8 = _gvputs($2, 138688) | 0;
+ label = 8;
+ break;
+ case 8:
+ $4 = HEAP32[4110] | 0;
+ $cmp10 = ($4 | 0) == 1;
+ if ($cmp10) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ HEAP32[4110] = 0;
+ label = 10;
+ break;
+ case 10:
+ $call13 = _gvputs($2, 131400) | 0;
+ $penwidth = $0 + 104 | 0;
+ $5 = +HEAPF64[$penwidth >> 3];
+ _gvprintdouble($2, $5);
+ $call14 = _gvputs($2, 122888) | 0;
+ $pencolor = $0 + 16 | 0;
+ _tkgen_print_color($job, $pencolor);
+ $6 = HEAP32[$pen >> 2] | 0;
+ $cmp16 = ($6 | 0) == 1;
+ if ($cmp16) {
+ label = 11;
+ break;
+ } else {
+ $7 = $6;
+ label = 12;
+ break;
+ }
+ case 11:
+ $call18 = _gvputs($2, 103120) | 0;
+ $_pr = HEAP32[$pen >> 2] | 0;
+ $7 = $_pr;
+ label = 12;
+ break;
+ case 12:
+ $cmp21 = ($7 | 0) == 2;
+ if ($cmp21) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $call23 = _gvputs($2, 99016) | 0;
+ label = 14;
+ break;
+ case 14:
+ _tkgen_print_tags($job);
+ $call25 = _gvputs($2, 116384) | 0;
+ label = 15;
+ break;
+ case 15:
+ return;
+ }
+}
+function _tkgen_bezier($job, $A, $n, $arrow_at_start, $arrow_at_end, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $arrow_at_start = $arrow_at_start | 0;
+ $arrow_at_end = $arrow_at_end | 0;
+ $filled = $filled | 0;
+ var $obj1 = 0, $0 = 0, $pen = 0, $1 = 0, $cmp = 0, $2 = 0, $call = 0, $call2 = 0, $pencolor = 0, $call3 = 0, $penwidth = 0, $3 = 0.0, $4 = 0, $cmp5 = 0, $call7 = 0, $_pr = 0, $5 = 0, $cmp9 = 0, $call11 = 0, $call13 = 0, $call14 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $pen = $0 + 96 | 0;
+ $1 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _tkgen_canvas($job);
+ $2 = $job;
+ $call = _gvputs($2, 111280) | 0;
+ _gvprintpointflist($2, $A, $n);
+ $call2 = _gvputs($2, 107048) | 0;
+ $pencolor = $0 + 16 | 0;
+ _tkgen_print_color($job, $pencolor);
+ $call3 = _gvputs($2, 131400) | 0;
+ $penwidth = $0 + 104 | 0;
+ $3 = +HEAPF64[$penwidth >> 3];
+ _gvprintdouble($2, $3);
+ $4 = HEAP32[$pen >> 2] | 0;
+ $cmp5 = ($4 | 0) == 1;
+ if ($cmp5) {
+ label = 4;
+ break;
+ } else {
+ $5 = $4;
+ label = 5;
+ break;
+ }
+ case 4:
+ $call7 = _gvputs($2, 103120) | 0;
+ $_pr = HEAP32[$pen >> 2] | 0;
+ $5 = $_pr;
+ label = 5;
+ break;
+ case 5:
+ $cmp9 = ($5 | 0) == 2;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call11 = _gvputs($2, 99016) | 0;
+ label = 7;
+ break;
+ case 7:
+ $call13 = _gvputs($2, 129664) | 0;
+ _tkgen_print_tags($job);
+ $call14 = _gvputs($2, 116384) | 0;
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _tkgen_polyline($job, $A, $n) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ var $obj1 = 0, $0 = 0, $pen = 0, $1 = 0, $cmp = 0, $2 = 0, $call = 0, $call2 = 0, $pencolor = 0, $3 = 0, $cmp4 = 0, $call6 = 0, $_pr = 0, $4 = 0, $cmp8 = 0, $call10 = 0, $call12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $pen = $0 + 96 | 0;
+ $1 = HEAP32[$pen >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ _tkgen_canvas($job);
+ $2 = $job;
+ $call = _gvputs($2, 111280) | 0;
+ _gvprintpointflist($2, $A, $n);
+ $call2 = _gvputs($2, 107048) | 0;
+ $pencolor = $0 + 16 | 0;
+ _tkgen_print_color($job, $pencolor);
+ $3 = HEAP32[$pen >> 2] | 0;
+ $cmp4 = ($3 | 0) == 1;
+ if ($cmp4) {
+ label = 4;
+ break;
+ } else {
+ $4 = $3;
+ label = 5;
+ break;
+ }
+ case 4:
+ $call6 = _gvputs($2, 103120) | 0;
+ $_pr = HEAP32[$pen >> 2] | 0;
+ $4 = $_pr;
+ label = 5;
+ break;
+ case 5:
+ $cmp8 = ($4 | 0) == 2;
+ if ($cmp8) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call10 = _gvputs($2, 99016) | 0;
+ label = 7;
+ break;
+ case 7:
+ _tkgen_print_tags($job);
+ $call12 = _gvputs($2, 116384) | 0;
+ label = 8;
+ break;
+ case 8:
+ return;
+ }
+}
+function _tkgen_comment($job, $str) {
+ $job = $job | 0;
+ $str = $str | 0;
+ var $0 = 0;
+ $0 = $job;
+ _gvputs($0, 123144);
+ _gvputs($0, _tkgen_string($str) | 0);
+ _gvputs($0, 116384);
+ return;
+}
+function _tkgen_canvas($job) {
+ $job = $job | 0;
+ var $external_context = 0, $0 = 0, $tobool = 0, $imagedata = 0, $1 = 0, $2 = 0, $call = 0, $3 = 0, $call1 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $external_context = $job + 144 | 0;
+ $0 = HEAP8[$external_context] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $imagedata = $job + 148 | 0;
+ $1 = HEAP32[$imagedata >> 2] | 0;
+ $2 = $job;
+ $call = _gvputs($2, $1) | 0;
+ label = 5;
+ break;
+ case 4:
+ $3 = $job;
+ $call1 = _gvputs($3, 133488) | 0;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _svg_textpara($job, $p, $para) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $para = $para | 0;
+ var $obj1 = 0, $0 = 0, $1 = 0, $call = 0, $just = 0, $2 = 0, $conv = 0, $call2 = 0, $call4 = 0, $call6 = 0, $yoffset_centerline = 0, $3 = 0.0, $y = 0, $4 = 0.0, $add = 0.0, $x = 0, $5 = 0.0, $sub = 0.0, $postscript_alias = 0, $6 = 0, $tobool = 0, $gvc = 0, $7 = 0, $g = 0, $8 = 0, $fontnames = 0, $9 = 0, $name = 0, $weight9 = 0, $style10 = 0, $svg_font_family = 0, $svg_font_weight = 0, $svg_font_style = 0, $family14 = 0, $weight15 = 0, $style16 = 0, $family_0_in = 0, $weight_0_in = 0, $style_0_in = 0, $style_0 = 0, $weight_0 = 0, $family_0 = 0, $stretch18 = 0, $10 = 0, $svg_font_family19 = 0, $11 = 0, $tobool20 = 0, $call23 = 0, $tobool24 = 0, $tobool27 = 0, $tobool30 = 0, $fontname = 0, $12 = 0, $fontsize = 0, $13 = 0.0, $pencolor = 0, $type = 0, $14 = 0, $string = 0, $15 = 0, $call37 = 0, $tobool38 = 0, $16 = 0, $rgba = 0, $arrayidx = 0, $17 = 0, $conv47 = 0, $arrayidx51 = 0, $18 = 0, $conv52 = 0, $arrayidx56 = 0, $19 = 0, $conv57 = 0, $call60 = 0, $str = 0, $20 = 0, $call61 = 0, $call62 = 0, $call63 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $1 = $job;
+ $call = _gvputs($1, 137912) | 0;
+ $just = $para + 72 | 0;
+ $2 = HEAP8[$just] | 0;
+ $conv = $2 << 24 >> 24;
+ if (($conv | 0) == 108) {
+ label = 3;
+ break;
+ } else if (($conv | 0) == 114) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $call2 = _gvputs($1, 137680) | 0;
+ label = 6;
+ break;
+ case 4:
+ $call4 = _gvputs($1, 137376) | 0;
+ label = 6;
+ break;
+ case 5:
+ $call6 = _gvputs($1, 137128) | 0;
+ label = 6;
+ break;
+ case 6:
+ $yoffset_centerline = $para + 48 | 0;
+ $3 = +HEAPF64[$yoffset_centerline >> 3];
+ $y = $p + 8 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $add = $3 + $4;
+ HEAPF64[$y >> 3] = $add;
+ $x = $p | 0;
+ $5 = +HEAPF64[$x >> 3];
+ $sub = -0.0 - $add;
+ _gvprintf($1, 136840, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $5, HEAPF64[tempInt + 8 >> 3] = $sub, tempInt) | 0);
+ $postscript_alias = $para + 4 | 0;
+ $6 = HEAP32[$postscript_alias >> 2] | 0;
+ $tobool = ($6 | 0) == 0;
+ if ($tobool) {
+ label = 19;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $gvc = $job | 0;
+ $7 = HEAP32[$gvc >> 2] | 0;
+ $g = $7 + 128 | 0;
+ $8 = HEAP32[$g >> 2] | 0;
+ $fontnames = $8 + 256 | 0;
+ $9 = HEAP32[$fontnames >> 2] | 0;
+ if (($9 | 0) == 1) {
+ label = 8;
+ break;
+ } else if (($9 | 0) == 2) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 8:
+ $name = $6 | 0;
+ $weight9 = $6 + 8 | 0;
+ $style10 = $6 + 16 | 0;
+ $style_0_in = $style10;
+ $weight_0_in = $weight9;
+ $family_0_in = $name;
+ label = 11;
+ break;
+ case 9:
+ $svg_font_family = $6 + 24 | 0;
+ $svg_font_weight = $6 + 28 | 0;
+ $svg_font_style = $6 + 32 | 0;
+ $style_0_in = $svg_font_style;
+ $weight_0_in = $svg_font_weight;
+ $family_0_in = $svg_font_family;
+ label = 11;
+ break;
+ case 10:
+ $family14 = $6 + 4 | 0;
+ $weight15 = $6 + 8 | 0;
+ $style16 = $6 + 16 | 0;
+ $style_0_in = $style16;
+ $weight_0_in = $weight15;
+ $family_0_in = $family14;
+ label = 11;
+ break;
+ case 11:
+ $style_0 = HEAP32[$style_0_in >> 2] | 0;
+ $weight_0 = HEAP32[$weight_0_in >> 2] | 0;
+ $family_0 = HEAP32[$family_0_in >> 2] | 0;
+ $stretch18 = $6 + 12 | 0;
+ $10 = HEAP32[$stretch18 >> 2] | 0;
+ _gvprintf($1, 136560, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $family_0, tempInt) | 0);
+ $svg_font_family19 = $6 + 24 | 0;
+ $11 = HEAP32[$svg_font_family19 >> 2] | 0;
+ $tobool20 = ($11 | 0) == 0;
+ if ($tobool20) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ _gvprintf($1, 136208, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $11, tempInt) | 0);
+ label = 13;
+ break;
+ case 13:
+ $call23 = _gvputs($1, 142856) | 0;
+ $tobool24 = ($weight_0 | 0) == 0;
+ if ($tobool24) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ _gvprintf($1, 135944, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $weight_0, tempInt) | 0);
+ label = 15;
+ break;
+ case 15:
+ $tobool27 = ($10 | 0) == 0;
+ if ($tobool27) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ _gvprintf($1, 135704, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $10, tempInt) | 0);
+ label = 17;
+ break;
+ case 17:
+ $tobool30 = ($style_0 | 0) == 0;
+ if ($tobool30) {
+ label = 20;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ _gvprintf($1, 135504, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $style_0, tempInt) | 0);
+ label = 20;
+ break;
+ case 19:
+ $fontname = $para + 20 | 0;
+ $12 = HEAP32[$fontname >> 2] | 0;
+ _gvprintf($1, 135328, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $12, tempInt) | 0);
+ label = 20;
+ break;
+ case 20:
+ $fontsize = $para + 24 | 0;
+ $13 = +HEAPF64[$fontsize >> 3];
+ _gvprintf($1, 135088, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $13, tempInt) | 0);
+ $pencolor = $0 + 16 | 0;
+ $type = $0 + 48 | 0;
+ $14 = HEAP32[$type >> 2] | 0;
+ if (($14 | 0) == 5) {
+ label = 21;
+ break;
+ } else if (($14 | 0) == 1) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 21:
+ $string = $pencolor;
+ $15 = HEAP32[$string >> 2] | 0;
+ $call37 = _strcasecmp($15, 92392) | 0;
+ $tobool38 = ($call37 | 0) == 0;
+ if ($tobool38) {
+ label = 25;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $16 = HEAP32[$string >> 2] | 0;
+ _gvprintf($1, 134856, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $16, tempInt) | 0);
+ label = 25;
+ break;
+ case 23:
+ $rgba = $pencolor;
+ $arrayidx = $pencolor;
+ $17 = HEAP8[$arrayidx] | 0;
+ $conv47 = $17 & 255;
+ $arrayidx51 = $rgba + 1 | 0;
+ $18 = HEAP8[$arrayidx51] | 0;
+ $conv52 = $18 & 255;
+ $arrayidx56 = $rgba + 2 | 0;
+ $19 = HEAP8[$arrayidx56] | 0;
+ $conv57 = $19 & 255;
+ _gvprintf($1, 134648, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $conv47, HEAP32[tempInt + 8 >> 2] = $conv52, HEAP32[tempInt + 16 >> 2] = $conv57, tempInt) | 0);
+ label = 25;
+ break;
+ case 24:
+ ___assert_func(141672, 379, 163832, 141400);
+ case 25:
+ $call60 = _gvputs($1, 134416) | 0;
+ $str = $para | 0;
+ $20 = HEAP32[$str >> 2] | 0;
+ $call61 = _xml_string($20) | 0;
+ $call62 = _gvputs($1, $call61) | 0;
+ $call63 = _gvputs($1, 134152) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _svg_print_color($job, $color) {
+ $job = $job | 0;
+ $color = $color | 0;
+ var $type = 0, $0 = 0, $string = 0, $1 = 0, $2 = 0, $call = 0, $rgba = 0, $arrayidx = 0, $3 = 0, $cmp = 0, $4 = 0, $call4 = 0, $arrayidx7 = 0, $5 = 0, $conv8 = 0, $arrayidx11 = 0, $6 = 0, $conv12 = 0, $arrayidx15 = 0, $7 = 0, $conv16 = 0, $8 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $color;
+ $color = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ _memcpy($color, tempParam, 40);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $color + 32 | 0;
+ $0 = HEAP32[$type >> 2] | 0;
+ if (($0 | 0) == 5) {
+ label = 3;
+ break;
+ } else if (($0 | 0) == 1) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $string = $color;
+ $1 = HEAP32[$string >> 2] | 0;
+ $2 = $job;
+ $call = _gvputs($2, $1) | 0;
+ label = 8;
+ break;
+ case 4:
+ $rgba = $color;
+ $arrayidx = $rgba + 3 | 0;
+ $3 = HEAP8[$arrayidx] | 0;
+ $cmp = $3 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $4 = $job;
+ $call4 = _gvputs($4, 144488) | 0;
+ label = 8;
+ break;
+ case 6:
+ $arrayidx7 = $color;
+ $5 = HEAP8[$arrayidx7] | 0;
+ $conv8 = $5 & 255;
+ $arrayidx11 = $rgba + 1 | 0;
+ $6 = HEAP8[$arrayidx11] | 0;
+ $conv12 = $6 & 255;
+ $arrayidx15 = $rgba + 2 | 0;
+ $7 = HEAP8[$arrayidx15] | 0;
+ $conv16 = $7 & 255;
+ $8 = $job;
+ _gvprintf($8, 141952, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $conv8, HEAP32[tempInt + 8 >> 2] = $conv12, HEAP32[tempInt + 16 >> 2] = $conv16, tempInt) | 0);
+ label = 8;
+ break;
+ case 7:
+ ___assert_func(141672, 86, 163848, 141400);
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _tkgen_print_color($job, $color) {
+ $job = $job | 0;
+ $color = $color | 0;
+ var $type = 0, $0 = 0, $string = 0, $1 = 0, $2 = 0, $call = 0, $rgba = 0, $arrayidx = 0, $3 = 0, $cmp = 0, $4 = 0, $call4 = 0, $arrayidx7 = 0, $5 = 0, $conv8 = 0, $arrayidx11 = 0, $6 = 0, $conv12 = 0, $arrayidx15 = 0, $7 = 0, $conv16 = 0, $8 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $color;
+ $color = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ _memcpy($color, tempParam, 40);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $color + 32 | 0;
+ $0 = HEAP32[$type >> 2] | 0;
+ if (($0 | 0) == 5) {
+ label = 3;
+ break;
+ } else if (($0 | 0) == 1) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $string = $color;
+ $1 = HEAP32[$string >> 2] | 0;
+ $2 = $job;
+ $call = _gvputs($2, $1) | 0;
+ label = 8;
+ break;
+ case 4:
+ $rgba = $color;
+ $arrayidx = $rgba + 3 | 0;
+ $3 = HEAP8[$arrayidx] | 0;
+ $cmp = $3 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $4 = $job;
+ $call4 = _gvputs($4, 138688) | 0;
+ label = 8;
+ break;
+ case 6:
+ $arrayidx7 = $color;
+ $5 = HEAP8[$arrayidx7] | 0;
+ $conv8 = $5 & 255;
+ $arrayidx11 = $rgba + 1 | 0;
+ $6 = HEAP8[$arrayidx11] | 0;
+ $conv12 = $6 & 255;
+ $arrayidx15 = $rgba + 2 | 0;
+ $7 = HEAP8[$arrayidx15] | 0;
+ $conv16 = $7 & 255;
+ $8 = $job;
+ _gvprintf($8, 135912, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $conv8, HEAP32[tempInt + 8 >> 2] = $conv12, HEAP32[tempInt + 16 >> 2] = $conv16, tempInt) | 0);
+ label = 8;
+ break;
+ case 7:
+ ___assert_func(148056, 51, 163808, 145272);
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _xml_isentity3315($s) {
+ $s = $s | 0;
+ var $incdec_ptr = 0, $0 = 0, $cmp = 0, $incdec_ptr2 = 0, $1 = 0, $incdec_ptr10 = 0, $s_addr_0 = 0, $2 = 0, $_off29 = 0, $3 = 0, $_off30 = 0, $4 = 0, $or_cond = 0, $_off31 = 0, $5 = 0, $or_cond35 = 0, $incdec_ptr31 = 0, $s_addr_1 = 0, $6 = 0, $_off32 = 0, $7 = 0, $incdec_ptr42 = 0, $s_addr_2 = 0, $8 = 0, $_off = 0, $9 = 0, $_off28 = 0, $10 = 0, $or_cond37 = 0, $incdec_ptr64 = 0, $s_addr_3 = 0, $11 = 0, $cmp68 = 0, $_ = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $incdec_ptr = $s + 1 | 0;
+ $0 = HEAP8[$incdec_ptr] | 0;
+ $cmp = $0 << 24 >> 24 == 35;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $s_addr_2 = $incdec_ptr;
+ label = 7;
+ break;
+ }
+ case 3:
+ $incdec_ptr2 = $s + 2 | 0;
+ $1 = HEAP8[$incdec_ptr2] | 0;
+ if (($1 << 24 >> 24 | 0) == 120 | ($1 << 24 >> 24 | 0) == 88) {
+ label = 4;
+ break;
+ } else {
+ $s_addr_1 = $incdec_ptr2;
+ label = 6;
+ break;
+ }
+ case 4:
+ $incdec_ptr10 = $s + 3 | 0;
+ $s_addr_0 = $incdec_ptr10;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP8[$s_addr_0] | 0;
+ $_off29 = $2 - 48 & 255;
+ $3 = ($_off29 & 255) < 10;
+ $_off30 = $2 - 97 & 255;
+ $4 = ($_off30 & 255) < 6;
+ $or_cond = $3 | $4;
+ $_off31 = $2 - 65 & 255;
+ $5 = ($_off31 & 255) < 6;
+ $or_cond35 = $or_cond | $5;
+ $incdec_ptr31 = $s_addr_0 + 1 | 0;
+ if ($or_cond35) {
+ $s_addr_0 = $incdec_ptr31;
+ label = 5;
+ break;
+ } else {
+ $s_addr_3 = $s_addr_0;
+ label = 8;
+ break;
+ }
+ case 6:
+ $6 = HEAP8[$s_addr_1] | 0;
+ $_off32 = $6 - 48 & 255;
+ $7 = ($_off32 & 255) < 10;
+ $incdec_ptr42 = $s_addr_1 + 1 | 0;
+ if ($7) {
+ $s_addr_1 = $incdec_ptr42;
+ label = 6;
+ break;
+ } else {
+ $s_addr_3 = $s_addr_1;
+ label = 8;
+ break;
+ }
+ case 7:
+ $8 = HEAP8[$s_addr_2] | 0;
+ $_off = $8 - 97 & 255;
+ $9 = ($_off & 255) < 26;
+ $_off28 = $8 - 65 & 255;
+ $10 = ($_off28 & 255) < 26;
+ $or_cond37 = $9 | $10;
+ $incdec_ptr64 = $s_addr_2 + 1 | 0;
+ if ($or_cond37) {
+ $s_addr_2 = $incdec_ptr64;
+ label = 7;
+ break;
+ } else {
+ $s_addr_3 = $s_addr_2;
+ label = 8;
+ break;
+ }
+ case 8:
+ $11 = HEAP8[$s_addr_3] | 0;
+ $cmp68 = $11 << 24 >> 24 == 59;
+ $_ = $cmp68 & 1;
+ return $_ | 0;
+ }
+ return 0;
+}
+function _vml_begin_job($job) {
+ $job = $job | 0;
+ var $0 = 0, $common = 0;
+ $0 = $job;
+ _gvputs($0, 150304);
+ _gvputs($0, 150048);
+ $common = $job + 12 | 0;
+ _gvputs($0, _html_string(HEAP32[HEAP32[HEAP32[$common >> 2] >> 2] >> 2] | 0) | 0);
+ _gvputs($0, 149776);
+ _gvputs($0, _html_string(HEAP32[(HEAP32[HEAP32[$common >> 2] >> 2] | 0) + 4 >> 2] | 0) | 0);
+ _gvputs($0, 149392);
+ _gvputs($0, _html_string(HEAP32[(HEAP32[HEAP32[$common >> 2] >> 2] | 0) + 8 >> 2] | 0) | 0);
+ _gvputs($0, 149176);
+ return;
+}
+function _vml_begin_graph($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $y = 0, $1 = 0.0, $y3 = 0, $2 = 0.0, $sub = 0.0, $conv = 0, $x = 0, $3 = 0.0, $x8 = 0, $4 = 0.0, $sub9 = 0.0, $conv10 = 0, $5 = 0, $call = 0, $call11 = 0, $g = 0, $6 = 0, $name12 = 0, $7 = 0, $8 = 0, $tobool = 0, $call13 = 0, $call14 = 0, $call15 = 0, $call16 = 0, $x17 = 0, $9 = 0, $y19 = 0, $10 = 0, $mul = 0, $call20 = 0, $call21 = 0, $call22 = 0, $call23 = 0, $call24 = 0, $call25 = 0, $call26 = 0, $call27 = 0, $call28 = 0, $call29 = 0, $call30 = 0, $call31 = 0, $call32 = 0, $call33 = 0, $call34 = 0, $call35 = 0, $call36 = 0, $call37 = 0, $call38 = 0, $call39 = 0, $call40 = 0, $call41 = 0, $call42 = 0, $call43 = 0, $call44 = 0, $call45 = 0, $call46 = 0, $call47 = 0, $call48 = 0, $call49 = 0, $call50 = 0, $call51 = 0, $call52 = 0, $call53 = 0, $call54 = 0, $call55 = 0, $call56 = 0, $call57 = 0, $call58 = 0, $call59 = 0, $call60 = 0, $call61 = 0, $call62 = 0, $call63 = 0, $11 = 0, $12 = 0, $add = 0, $call64 = 0, $call65 = 0, $call66 = 0, $call67 = 0, $call68 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $y = $job + 232 | 0;
+ $1 = +HEAPF64[$y >> 3];
+ $y3 = $job + 216 | 0;
+ $2 = +HEAPF64[$y3 >> 3];
+ $sub = $1 - $2;
+ $conv = ~~$sub;
+ HEAP32[4068] = $conv;
+ $x = $job + 224 | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $x8 = $job + 208 | 0;
+ $4 = +HEAPF64[$x8 >> 3];
+ $sub9 = $3 - $4;
+ $conv10 = ~~$sub9;
+ HEAP32[4066] = $conv10;
+ $5 = $job;
+ $call = _gvputs($5, 91448) | 0;
+ $call11 = _gvputs($5, 91072) | 0;
+ $g = $0 + 8 | 0;
+ $6 = HEAP32[$g >> 2] | 0;
+ $name12 = $6 + 12 | 0;
+ $7 = HEAP32[$name12 >> 2] | 0;
+ $8 = HEAP8[$7] | 0;
+ $tobool = $8 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call13 = _gvputs($5, 90792) | 0;
+ $call14 = _html_string($7) | 0;
+ $call15 = _gvputs($5, $call14) | 0;
+ $call16 = _gvputs($5, 90480) | 0;
+ label = 4;
+ break;
+ case 4:
+ $x17 = $job + 164 | 0;
+ $9 = HEAP32[$x17 >> 2] | 0;
+ $y19 = $job + 168 | 0;
+ $10 = HEAP32[$y19 >> 2] | 0;
+ $mul = Math_imul($10, $9);
+ _gvprintf($5, 90176, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $mul, tempInt) | 0);
+ $call20 = _gvputs($5, 89824) | 0;
+ $call21 = _gvputs($5, 163040) | 0;
+ $call22 = _gvputs($5, 162712) | 0;
+ $call23 = _gvputs($5, 162352) | 0;
+ $call24 = _gvputs($5, 161896) | 0;
+ $call25 = _gvputs($5, 161616) | 0;
+ $call26 = _gvputs($5, 161312) | 0;
+ $call27 = _gvputs($5, 160968) | 0;
+ $call28 = _gvputs($5, 160648) | 0;
+ $call29 = _gvputs($5, 160312) | 0;
+ $call30 = _gvputs($5, 159992) | 0;
+ $call31 = _gvputs($5, 159664) | 0;
+ $call32 = _gvputs($5, 159216) | 0;
+ $call33 = _gvputs($5, 158808) | 0;
+ $call34 = _gvputs($5, 158368) | 0;
+ $call35 = _gvputs($5, 158016) | 0;
+ $call36 = _gvputs($5, 157608) | 0;
+ $call37 = _gvputs($5, 157256) | 0;
+ $call38 = _gvputs($5, 156936) | 0;
+ $call39 = _gvputs($5, 156672) | 0;
+ $call40 = _gvputs($5, 156336) | 0;
+ $call41 = _gvputs($5, 158016) | 0;
+ $call42 = _gvputs($5, 156016) | 0;
+ $call43 = _gvputs($5, 157256) | 0;
+ $call44 = _gvputs($5, 156936) | 0;
+ $call45 = _gvputs($5, 155624) | 0;
+ $call46 = _gvputs($5, 158808) | 0;
+ $call47 = _gvputs($5, 158368) | 0;
+ $call48 = _gvputs($5, 158016) | 0;
+ $call49 = _gvputs($5, 156016) | 0;
+ $call50 = _gvputs($5, 157256) | 0;
+ $call51 = _gvputs($5, 156936) | 0;
+ $call52 = _gvputs($5, 156672) | 0;
+ $call53 = _gvputs($5, 156336) | 0;
+ $call54 = _gvputs($5, 158016) | 0;
+ $call55 = _gvputs($5, 157608) | 0;
+ $call56 = _gvputs($5, 157256) | 0;
+ $call57 = _gvputs($5, 156936) | 0;
+ $call58 = _gvputs($5, 155328) | 0;
+ $call59 = _gvputs($5, 154960) | 0;
+ $call60 = _gvputs($5, 154640) | 0;
+ $call61 = _gvputs($5, 154312) | 0;
+ $call62 = _gvputs($5, 153992) | 0;
+ $call63 = _gvputs($5, 153640) | 0;
+ $11 = HEAP32[4066] | 0;
+ $12 = HEAP32[4068] | 0;
+ $add = $12 + 10 | 0;
+ _gvprintf($5, 153328, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $11, HEAP32[tempInt + 8 >> 2] = $add, tempInt) | 0);
+ $call64 = _gvputs($5, 152952) | 0;
+ $call65 = _gvputs($5, 152616) | 0;
+ $call66 = _gvputs($5, 152264) | 0;
+ $call67 = _gvputs($5, 151848) | 0;
+ $call68 = _gvputs($5, 151400) | 0;
+ $13 = HEAP32[4066] | 0;
+ $14 = HEAP32[4068] | 0;
+ _gvprintf($5, 150960, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $13, HEAP32[tempInt + 8 >> 2] = $14, tempInt) | 0);
+ $15 = HEAP32[4066] | 0;
+ $16 = HEAP32[4068] | 0;
+ _gvprintf($5, 150656, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $15, HEAP32[tempInt + 8 >> 2] = $16, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _vml_end_graph($job) {
+ $job = $job | 0;
+ var $0 = 0;
+ $0 = $job;
+ _gvputs($0, 94928);
+ _gvputs($0, 94640);
+ _gvputs($0, 94304);
+ _gvputs($0, 93968);
+ _gvputs($0, 94640);
+ _gvputs($0, 93608);
+ _gvputs($0, 93272);
+ _gvputs($0, 92912);
+ _gvputs($0, 94640);
+ _gvputs($0, 92544);
+ _gvputs($0, 92216);
+ _gvputs($0, 94640);
+ _gvputs($0, 91720);
+ return;
+}
+function _vml_begin_anchor($job, $href, $tooltip, $target, $id) {
+ $job = $job | 0;
+ $href = $href | 0;
+ $tooltip = $tooltip | 0;
+ $target = $target | 0;
+ $id = $id | 0;
+ var $0 = 0, $call = 0, $tobool = 0, $1 = 0, $tobool1 = 0, $call2 = 0, $tobool3 = 0, $2 = 0, $tobool7 = 0, $call9 = 0, $tobool11 = 0, $3 = 0, $tobool15 = 0, $call17 = 0, $call19 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 96928) | 0;
+ $tobool = ($href | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$href] | 0;
+ $tobool1 = $1 << 24 >> 24 == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call2 = _html_string($href) | 0;
+ _gvprintf($0, 96416, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call2, tempInt) | 0);
+ label = 5;
+ break;
+ case 5:
+ $tobool3 = ($tooltip | 0) == 0;
+ if ($tobool3) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $2 = HEAP8[$tooltip] | 0;
+ $tobool7 = $2 << 24 >> 24 == 0;
+ if ($tobool7) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $call9 = _html_string($tooltip) | 0;
+ _gvprintf($0, 95960, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call9, tempInt) | 0);
+ label = 8;
+ break;
+ case 8:
+ $tobool11 = ($target | 0) == 0;
+ if ($tobool11) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $3 = HEAP8[$target] | 0;
+ $tobool15 = $3 << 24 >> 24 == 0;
+ if ($tobool15) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call17 = _html_string($target) | 0;
+ _gvprintf($0, 95680, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $call17, tempInt) | 0);
+ label = 11;
+ break;
+ case 11:
+ $call19 = _gvputs($0, 95264) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _vml_end_anchor($job) {
+ $job = $job | 0;
+ _gvputs($job, 97256);
+ return;
+}
+function _vml_ellipse($job, $A, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $filled = $filled | 0;
+ var $0 = 0, $2 = 0.0, $sub = 0.0, $4 = 0.0, $sub6 = 0.0, $sub9 = 0.0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $0 = $job;
+ _gvputs($0, 104312);
+ $2 = +HEAPF64[$A >> 3];
+ $sub = +HEAPF64[$A + 16 >> 3] - $2;
+ $4 = +HEAPF64[$A + 8 >> 3];
+ $sub6 = +HEAPF64[$A + 24 >> 3] - $4;
+ $sub9 = +((HEAP32[4068] | 0) >>> 0 >>> 0) - ($4 + $sub6);
+ _gvprintf($0, 103936, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $2 - $sub, HEAPF64[tempInt + 8 >> 3] = $sub9, tempInt) | 0);
+ _gvprintf($0, 103440, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $sub * 2.0, HEAPF64[tempInt + 8 >> 3] = $sub6 * 2.0, tempInt) | 0);
+ _vml_grfill($job, $filled);
+ _gvputs($0, 110032);
+ _vml_grstroke($job);
+ _gvputs($0, 103072);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _vml_polygon($job, $A, $n, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $filled = $filled | 0;
+ var $0 = 0, $call = 0, $1 = 0, $2 = 0, $call1 = 0, $call2 = 0, $cmp20 = 0, $sub12 = 0, $i_021 = 0, $x = 0, $3 = 0.0, $4 = 0, $conv = 0.0, $y = 0, $5 = 0.0, $sub = 0.0, $cmp4 = 0, $call6 = 0, $call10 = 0, $cmp13 = 0, $call16 = 0, $inc = 0, $cmp = 0, $call18 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 119672) | 0;
+ $1 = HEAP32[4066] | 0;
+ $2 = HEAP32[4068] | 0;
+ _gvprintf($0, 110464, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $1, HEAP32[tempInt + 8 >> 2] = $2, tempInt) | 0);
+ _vml_grfill($job, $filled);
+ $call1 = _gvputs($0, 110032) | 0;
+ _vml_grstroke($job);
+ $call2 = _gvputs($0, 109632) | 0;
+ $cmp20 = ($n | 0) > 0;
+ if ($cmp20) {
+ label = 3;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $sub12 = $n - 1 | 0;
+ $i_021 = 0;
+ label = 4;
+ break;
+ case 4:
+ $x = $A + ($i_021 << 4) | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $4 = HEAP32[4068] | 0;
+ $conv = +($4 >>> 0 >>> 0);
+ $y = $A + ($i_021 << 4) + 8 | 0;
+ $5 = +HEAPF64[$y >> 3];
+ $sub = $conv - $5;
+ $cmp4 = ($i_021 | 0) == 0;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call6 = _gvputs($0, 108960) | 0;
+ _gvprintf($0, 105536, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $3, HEAPF64[tempInt + 8 >> 3] = $sub, tempInt) | 0);
+ $call10 = _gvputs($0, 105192) | 0;
+ label = 7;
+ break;
+ case 6:
+ _gvprintf($0, 105536, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $3, HEAPF64[tempInt + 8 >> 3] = $sub, tempInt) | 0);
+ label = 7;
+ break;
+ case 7:
+ $cmp13 = ($i_021 | 0) == ($sub12 | 0);
+ if ($cmp13) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $call16 = _gvputs($0, 104872) | 0;
+ label = 9;
+ break;
+ case 9:
+ $inc = $i_021 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_021 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call18 = _gvputs($0, 115344) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _vml_bezier($job, $A, $n, $arrow_at_start, $arrow_at_end, $filled) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ $arrow_at_start = $arrow_at_start | 0;
+ $arrow_at_end = $arrow_at_end | 0;
+ $filled = $filled | 0;
+ var $0 = 0, $2 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ $0 = $job;
+ _gvputs($0, 119672);
+ $2 = HEAP32[4068] | 0;
+ _gvprintf($0, 110464, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = HEAP32[4066] | 0, HEAP32[tempInt + 8 >> 2] = $2, tempInt) | 0);
+ _vml_grfill($job, $filled);
+ _gvputs($0, 110032);
+ _vml_grstroke($job);
+ _gvputs($0, 109632);
+ _vml_bzptarray($job, $A, $n);
+ _gvputs($0, 109312);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _vml_polyline($job, $A, $n) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ var $0 = 0, $call = 0, $1 = 0, $2 = 0, $call1 = 0, $cmp18 = 0, $sub10 = 0, $i_019 = 0, $cmp2 = 0, $call3 = 0, $x = 0, $3 = 0.0, $4 = 0, $conv = 0.0, $y = 0, $5 = 0.0, $sub = 0.0, $call8 = 0, $x_c = 0, $6 = 0.0, $7 = 0, $conv_c = 0.0, $y_c = 0, $8 = 0.0, $sub_c = 0.0, $cmp11 = 0, $call14 = 0, $inc = 0, $cmp = 0, $call16 = 0, $call17 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $job;
+ $call = _gvputs($0, 119672) | 0;
+ $1 = HEAP32[4066] | 0;
+ $2 = HEAP32[4068] | 0;
+ _gvprintf($0, 119136, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = $1, HEAP32[tempInt + 8 >> 2] = $2, tempInt) | 0);
+ $call1 = _gvputs($0, 118624) | 0;
+ $cmp18 = ($n | 0) > 0;
+ if ($cmp18) {
+ label = 3;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $sub10 = $n - 1 | 0;
+ $i_019 = 0;
+ label = 4;
+ break;
+ case 4:
+ $cmp2 = ($i_019 | 0) == 0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call3 = _gvputs($0, 118040) | 0;
+ $x = $A + ($i_019 << 4) | 0;
+ $3 = +HEAPF64[$x >> 3];
+ $4 = HEAP32[4068] | 0;
+ $conv = +($4 >>> 0 >>> 0);
+ $y = $A + ($i_019 << 4) + 8 | 0;
+ $5 = +HEAPF64[$y >> 3];
+ $sub = $conv - $5;
+ _gvprintf($0, 117424, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $3, HEAPF64[tempInt + 8 >> 3] = $sub, tempInt) | 0);
+ $call8 = _gvputs($0, 116792) | 0;
+ label = 7;
+ break;
+ case 6:
+ $x_c = $A + ($i_019 << 4) | 0;
+ $6 = +HEAPF64[$x_c >> 3];
+ $7 = HEAP32[4068] | 0;
+ $conv_c = +($7 >>> 0 >>> 0);
+ $y_c = $A + ($i_019 << 4) + 8 | 0;
+ $8 = +HEAPF64[$y_c >> 3];
+ $sub_c = $conv_c - $8;
+ _gvprintf($0, 117424, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $6, HEAPF64[tempInt + 8 >> 3] = $sub_c, tempInt) | 0);
+ label = 7;
+ break;
+ case 7:
+ $cmp11 = ($i_019 | 0) == ($sub10 | 0);
+ if ($cmp11) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $call14 = _gvputs($0, 116312) | 0;
+ label = 9;
+ break;
+ case 9:
+ $inc = $i_019 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_019 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $call16 = _gvputs($0, 115808) | 0;
+ _vml_grstroke($job);
+ $call17 = _gvputs($0, 115344) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _vml_comment($job, $str) {
+ $job = $job | 0;
+ $str = $str | 0;
+ var $0 = 0;
+ $0 = $job;
+ _gvputs($0, 121024);
+ _gvputs($0, _html_string($str) | 0);
+ _gvputs($0, 120288);
+ return;
+}
+function _vml_grstroke($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $1 = 0, $call = 0, $pencolor = 0, $penwidth = 0, $2 = 0.0, $cmp = 0, $pen = 0, $3 = 0, $call5 = 0, $call9 = 0, $call12 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $1 = $job;
+ $call = _gvputs($1, 114792) | 0;
+ $pencolor = $0 + 16 | 0;
+ _vml_print_color($job, $pencolor);
+ $penwidth = $0 + 104 | 0;
+ $2 = +HEAPF64[$penwidth >> 3];
+ $cmp = $2 != 1.0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _gvprintf($1, 114160, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $2, tempInt) | 0);
+ label = 4;
+ break;
+ case 4:
+ $pen = $0 + 96 | 0;
+ $3 = HEAP32[$pen >> 2] | 0;
+ if (($3 | 0) == 1) {
+ label = 5;
+ break;
+ } else if (($3 | 0) == 2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $call5 = _gvputs($1, 113688) | 0;
+ label = 7;
+ break;
+ case 6:
+ $call9 = _gvputs($1, 113256) | 0;
+ label = 7;
+ break;
+ case 7:
+ $call12 = _gvputs($1, 112680) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _tkgen_print_tags($job) {
+ $job = $job | 0;
+ var $obj1 = 0, $0 = 0, $emit_state = 0, $1 = 0, $u = 0, $n = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $u5 = 0, $n6 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $u13 = 0, $e = 0, $10 = 0, $11 = 0, $12 = 0, $13 = 0, $u20 = 0, $e21 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $g = 0, $18 = 0, $19 = 0, $20 = 0, $21 = 0, $g33 = 0, $22 = 0, $23 = 0, $24 = 0, $25 = 0, $sg = 0, $26 = 0, $27 = 0, $28 = 0, $29 = 0, $sg45 = 0, $30 = 0, $31 = 0, $32 = 0, $ObjType_0 = 0, $ObjFlag_0 = 0, $ObjHandle_0_in = 0, $ObjHandle_0 = 0, $33 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $emit_state = $0 + 12 | 0;
+ $1 = HEAP32[$emit_state >> 2] | 0;
+ if (($1 | 0) == 8) {
+ label = 3;
+ break;
+ } else if (($1 | 0) == 10) {
+ label = 4;
+ break;
+ } else if (($1 | 0) == 9 | ($1 | 0) == 2 | ($1 | 0) == 3) {
+ label = 5;
+ break;
+ } else if (($1 | 0) == 11 | ($1 | 0) == 6 | ($1 | 0) == 7) {
+ label = 6;
+ break;
+ } else if (($1 | 0) == 0) {
+ label = 7;
+ break;
+ } else if (($1 | 0) == 4) {
+ label = 8;
+ break;
+ } else if (($1 | 0) == 1) {
+ label = 9;
+ break;
+ } else if (($1 | 0) == 5) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 3:
+ $u = $0 + 8 | 0;
+ $n = $u;
+ $2 = HEAP32[$n >> 2] | 0;
+ $3 = $2;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $5 = $4 & -256;
+ $ObjHandle_0_in = $5;
+ $ObjFlag_0 = 1;
+ $ObjType_0 = 94992;
+ label = 12;
+ break;
+ case 4:
+ $u5 = $0 + 8 | 0;
+ $n6 = $u5;
+ $6 = HEAP32[$n6 >> 2] | 0;
+ $7 = $6;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $9 = $8 & -256;
+ $ObjHandle_0_in = $9;
+ $ObjFlag_0 = 0;
+ $ObjType_0 = 94992;
+ label = 12;
+ break;
+ case 5:
+ $u13 = $0 + 8 | 0;
+ $e = $u13;
+ $10 = HEAP32[$e >> 2] | 0;
+ $11 = $10;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $13 = $12 & -256;
+ $ObjHandle_0_in = $13;
+ $ObjFlag_0 = 1;
+ $ObjType_0 = 158056;
+ label = 12;
+ break;
+ case 6:
+ $u20 = $0 + 8 | 0;
+ $e21 = $u20;
+ $14 = HEAP32[$e21 >> 2] | 0;
+ $15 = $14;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $17 = $16 & -256;
+ $ObjHandle_0_in = $17;
+ $ObjFlag_0 = 0;
+ $ObjType_0 = 158056;
+ label = 12;
+ break;
+ case 7:
+ $g = $0 + 8 | 0;
+ $18 = HEAP32[$g >> 2] | 0;
+ $19 = $18;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $21 = $20 & -256;
+ $ObjHandle_0_in = $21;
+ $ObjFlag_0 = 1;
+ $ObjType_0 = 154688;
+ label = 12;
+ break;
+ case 8:
+ $g33 = $0 + 8 | 0;
+ $22 = HEAP32[$g33 >> 2] | 0;
+ $23 = $22;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $25 = $24 & -256;
+ $ObjHandle_0_in = $25;
+ $ObjFlag_0 = 0;
+ $ObjType_0 = 151024;
+ label = 12;
+ break;
+ case 9:
+ $sg = $0 + 8 | 0;
+ $26 = HEAP32[$sg >> 2] | 0;
+ $27 = $26;
+ $28 = HEAP32[$27 >> 2] | 0;
+ $29 = $28 & -256;
+ $ObjHandle_0_in = $29;
+ $ObjFlag_0 = 1;
+ $ObjType_0 = 154688;
+ label = 12;
+ break;
+ case 10:
+ $sg45 = $0 + 8 | 0;
+ $30 = HEAP32[$sg45 >> 2] | 0;
+ $31 = $30;
+ $32 = HEAP32[$31 >> 2] | 0;
+ $ObjHandle_0_in = $32;
+ $ObjFlag_0 = 0;
+ $ObjType_0 = 154688;
+ label = 12;
+ break;
+ case 11:
+ ___assert_func(148056, 148, 163784, 145272);
+ case 12:
+ $ObjHandle_0 = $ObjHandle_0_in >> 8;
+ $33 = $job;
+ _gvprintf($33, 142216, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $ObjFlag_0, HEAP32[tempInt + 8 >> 2] = $ObjType_0, HEAP32[tempInt + 16 >> 2] = $ObjHandle_0, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _html_string($s) {
+ $s = $s | 0;
+ var $workstr = 0, $0 = 0, $tobool = 0, $call = 0, $1 = 0, $arrayidx = 0, $arrayidx75 = 0, $p_0_ph = 0, $prev_0_ph = 0, $pos_0_ph = 0, $s_addr_0_ph = 0, $remaining_0_ph = 0, $charnum_0_ph = 0, $tobool33 = 0, $p_0 = 0, $s_addr_0 = 0, $remaining_0 = 0, $charnum_0 = 0, $tobool1 = 0, $2 = 0, $tobool2 = 0, $3 = 0, $sub3 = 0, $cmp = 0, $mul = 0, $4 = 0, $call6 = 0, $add_ptr = 0, $p_1 = 0, $5 = 0, $cmp9 = 0, $call11 = 0, $tobool12 = 0, $_pr = 0, $6 = 0, $7 = 0, $cmp36 = 0, $8 = 0, $cmp51 = 0, $conv5537 = 0, $conv5541 = 0, $mask_040 = 0, $cnt_039 = 0, $inc = 0, $and = 0, $shr35 = 0, $cmp56 = 0, $cmp63 = 0, $shl = 0, $add = 0, $remaining_1_in = 0, $charnum_1 = 0, $remaining_1 = 0, $cmp71 = 0, $incdec_ptr = 0, $sub_0 = 0, $len_0 = 0, $charnum_2 = 0, $rem = 0, $add7636 = 0, $conv77 = 0, $incdec_ptr78 = 0, $div = 0, $inc79 = 0, $cmp80 = 0, $9 = 0, $10 = 0, $11 = 0, $sub_1_ph_ph = 0, $len_1_ph_ph = 0, $incdec_ptr87 = 0, $tobool9947 = 0, $charnum_3_ph117 = 0, $remaining_2_ph115 = 0, $len_1_ph114 = 0, $sub_1_ph113 = 0, $12 = 0, $len_150 = 0, $sub_149 = 0, $p_248 = 0, $dec98 = 0, $incdec_ptr101 = 0, $13 = 0, $incdec_ptr102 = 0, $tobool99 = 0, $scevgep = 0, $charnum_3_ph118 = 0, $remaining_2_ph116 = 0, $pos_1_lcssa = 0, $p_2_lcssa = 0, $incdec_ptr104 = 0, $14 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $workstr = __stackBase__ | 0;
+ $0 = HEAP32[3506] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[3504] = 64;
+ $call = _gmalloc(64) | 0;
+ HEAP32[3506] = $call;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[3506] | 0;
+ $arrayidx = $workstr + 15 | 0;
+ $arrayidx75 = $workstr + 14 | 0;
+ $charnum_0_ph = 0;
+ $remaining_0_ph = 0;
+ $s_addr_0_ph = $s;
+ $pos_0_ph = 0;
+ $prev_0_ph = 0;
+ $p_0_ph = $1;
+ label = 5;
+ break;
+ case 5:
+ $tobool33 = ($prev_0_ph | 0) == 0;
+ $charnum_0 = $charnum_0_ph;
+ $remaining_0 = $remaining_0_ph;
+ $s_addr_0 = $s_addr_0_ph;
+ $p_0 = $p_0_ph;
+ label = 6;
+ break;
+ case 6:
+ $tobool1 = ($s_addr_0 | 0) == 0;
+ if ($tobool1) {
+ label = 34;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $2 = HEAP8[$s_addr_0] | 0;
+ $tobool2 = $2 << 24 >> 24 == 0;
+ if ($tobool2) {
+ label = 34;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $3 = HEAP32[3504] | 0;
+ $sub3 = $3 - 8 | 0;
+ $cmp = ($pos_0_ph | 0) > ($sub3 | 0);
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ $p_1 = $p_0;
+ label = 10;
+ break;
+ }
+ case 9:
+ $mul = $3 << 1;
+ HEAP32[3504] = $mul;
+ $4 = HEAP32[3506] | 0;
+ $call6 = _grealloc($4, $mul) | 0;
+ HEAP32[3506] = $call6;
+ $add_ptr = $call6 + $pos_0_ph | 0;
+ $p_1 = $add_ptr;
+ label = 10;
+ break;
+ case 10:
+ $5 = HEAP8[$s_addr_0] | 0;
+ $cmp9 = $5 << 24 >> 24 == 38;
+ if ($cmp9) {
+ label = 11;
+ break;
+ } else {
+ $6 = $5;
+ label = 13;
+ break;
+ }
+ case 11:
+ $call11 = _xml_isentity3315($s_addr_0) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ $len_1_ph_ph = 5;
+ $sub_1_ph_ph = 110184;
+ label = 28;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $_pr = HEAP8[$s_addr_0] | 0;
+ $6 = $_pr;
+ label = 13;
+ break;
+ case 13:
+ if (($6 << 24 >> 24 | 0) == 45) {
+ label = 14;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 32) {
+ label = 15;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 60) {
+ $len_1_ph_ph = 4;
+ $sub_1_ph_ph = 147248;
+ label = 28;
+ break;
+ } else if (($6 << 24 >> 24 | 0) == 62) {
+ $sub_1_ph113 = 122360;
+ $len_1_ph114 = 4;
+ $remaining_2_ph115 = $remaining_0;
+ $charnum_3_ph117 = $charnum_0;
+ label = 30;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 14:
+ $sub_1_ph113 = 116224;
+ $len_1_ph114 = 5;
+ $remaining_2_ph115 = $remaining_0;
+ $charnum_3_ph117 = $charnum_0;
+ label = 30;
+ break;
+ case 15:
+ if ($tobool33) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $7 = HEAP8[$prev_0_ph] | 0;
+ $cmp36 = $7 << 24 >> 24 == 32;
+ if ($cmp36) {
+ $len_1_ph_ph = 6;
+ $sub_1_ph_ph = 111136;
+ label = 28;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $8 = HEAP8[$s_addr_0] | 0;
+ if (($8 << 24 >> 24 | 0) == 34) {
+ $len_1_ph_ph = 6;
+ $sub_1_ph_ph = 106936;
+ label = 28;
+ break;
+ } else if (($8 << 24 >> 24 | 0) == 39) {
+ $sub_1_ph113 = 103008;
+ $len_1_ph114 = 5;
+ $remaining_2_ph115 = $remaining_0;
+ $charnum_3_ph117 = $charnum_0;
+ label = 30;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $cmp51 = $8 << 24 >> 24 < 0;
+ if ($cmp51) {
+ label = 19;
+ break;
+ } else {
+ $len_1_ph_ph = 1;
+ $sub_1_ph_ph = $s_addr_0;
+ label = 28;
+ break;
+ }
+ case 19:
+ $conv5537 = $8 & 255;
+ $cnt_039 = 0;
+ $mask_040 = 127;
+ $conv5541 = $conv5537;
+ label = 20;
+ break;
+ case 20:
+ $inc = $cnt_039 + 1 | 0;
+ $and = $conv5541 & $mask_040;
+ $shr35 = $mask_040 >>> 1;
+ $cmp56 = $shr35 >>> 0 < $and >>> 0;
+ if ($cmp56) {
+ $cnt_039 = $inc;
+ $mask_040 = $shr35;
+ $conv5541 = $and;
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $cmp63 = ($cnt_039 | 0) > 0;
+ if ($cmp63) {
+ $charnum_1 = $and;
+ $remaining_1_in = $inc;
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $shl = $charnum_0 << 6;
+ $add = $and + $shl | 0;
+ $charnum_1 = $add;
+ $remaining_1_in = $remaining_0;
+ label = 23;
+ break;
+ case 23:
+ $remaining_1 = $remaining_1_in - 1 | 0;
+ $cmp71 = ($remaining_1 | 0) > 0;
+ $incdec_ptr = $s_addr_0 + 1 | 0;
+ if ($cmp71) {
+ $charnum_0 = $charnum_1;
+ $remaining_0 = $remaining_1;
+ $s_addr_0 = $incdec_ptr;
+ $p_0 = $p_1;
+ label = 6;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ HEAP8[$arrayidx] = 59;
+ $charnum_2 = $charnum_1;
+ $len_0 = 3;
+ $sub_0 = $arrayidx75;
+ label = 25;
+ break;
+ case 25:
+ $rem = ($charnum_2 >>> 0) % 10;
+ $add7636 = $rem | 48;
+ $conv77 = $add7636 & 255;
+ $incdec_ptr78 = $sub_0 - 1 | 0;
+ HEAP8[$sub_0] = $conv77;
+ $div = ($charnum_2 >>> 0) / 10 >>> 0;
+ $inc79 = $len_0 + 1 | 0;
+ $cmp80 = ($inc79 | 0) > 12;
+ if ($cmp80) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $9 = HEAP32[_stderr >> 2] | 0;
+ $10 = _fwrite(98744, 46, 1, $9 | 0) | 0;
+ _exit(1);
+ return 0;
+ case 27:
+ $11 = $charnum_2 >>> 0 > 9;
+ if ($11) {
+ $charnum_2 = $div;
+ $len_0 = $inc79;
+ $sub_0 = $incdec_ptr78;
+ label = 25;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ $sub_1_ph113 = $sub_1_ph_ph;
+ $len_1_ph114 = $len_1_ph_ph;
+ $remaining_2_ph115 = $remaining_0;
+ $charnum_3_ph117 = $charnum_0;
+ label = 30;
+ break;
+ case 29:
+ $incdec_ptr87 = $sub_0 - 2 | 0;
+ HEAP8[$incdec_ptr78] = 35;
+ HEAP8[$incdec_ptr87] = 38;
+ $tobool9947 = ($inc79 | 0) == 0;
+ if ($tobool9947) {
+ $p_2_lcssa = $p_1;
+ $pos_1_lcssa = $pos_0_ph;
+ $remaining_2_ph116 = $remaining_1;
+ $charnum_3_ph118 = $div;
+ label = 33;
+ break;
+ } else {
+ $sub_1_ph113 = $incdec_ptr87;
+ $len_1_ph114 = $inc79;
+ $remaining_2_ph115 = $remaining_1;
+ $charnum_3_ph117 = $div;
+ label = 30;
+ break;
+ }
+ case 30:
+ $12 = $len_1_ph114 + $pos_0_ph | 0;
+ $p_248 = $p_1;
+ $sub_149 = $sub_1_ph113;
+ $len_150 = $len_1_ph114;
+ label = 31;
+ break;
+ case 31:
+ $dec98 = $len_150 - 1 | 0;
+ $incdec_ptr101 = $sub_149 + 1 | 0;
+ $13 = HEAP8[$sub_149] | 0;
+ $incdec_ptr102 = $p_248 + 1 | 0;
+ HEAP8[$p_248] = $13;
+ $tobool99 = ($dec98 | 0) == 0;
+ if ($tobool99) {
+ label = 32;
+ break;
+ } else {
+ $p_248 = $incdec_ptr102;
+ $sub_149 = $incdec_ptr101;
+ $len_150 = $dec98;
+ label = 31;
+ break;
+ }
+ case 32:
+ $scevgep = $p_1 + $len_1_ph114 | 0;
+ $p_2_lcssa = $scevgep;
+ $pos_1_lcssa = $12;
+ $remaining_2_ph116 = $remaining_2_ph115;
+ $charnum_3_ph118 = $charnum_3_ph117;
+ label = 33;
+ break;
+ case 33:
+ $incdec_ptr104 = $s_addr_0 + 1 | 0;
+ $charnum_0_ph = $charnum_3_ph118;
+ $remaining_0_ph = $remaining_2_ph116;
+ $s_addr_0_ph = $incdec_ptr104;
+ $pos_0_ph = $pos_1_lcssa;
+ $prev_0_ph = $s_addr_0;
+ $p_0_ph = $p_2_lcssa;
+ label = 5;
+ break;
+ case 34:
+ HEAP8[$p_0] = 0;
+ $14 = HEAP32[3506] | 0;
+ STACKTOP = __stackBase__;
+ return $14 | 0;
+ }
+ return 0;
+}
+function _vml_textpara($job, $p, $para) {
+ $job = $job | 0;
+ $p = $p | 0;
+ $para = $para | 0;
+ var $obj1 = 0, $0 = 0, $just = 0, $1 = 0, $conv = 0, $x = 0, $2 = 0.0, $x4 = 0, $3 = 0.0, $width = 0, $4 = 0.0, $sub = 0.0, $x7 = 0, $5 = 0.0, $width8 = 0, $6 = 0.0, $div = 0.0, $sub9 = 0.0, $p1_sroa_0_0 = 0.0, $width12 = 0, $7 = 0.0, $add = 0.0, $height = 0, $8 = 0.0, $fontsize = 0, $9 = 0.0, $cmp = 0, $mul = 0.0, $add16 = 0.0, $sub19 = 0.0, $add21 = 0.0, $10 = 0, $conv22 = 0.0, $y = 0, $11 = 0.0, $sub23 = 0.0, $12 = 0.0, $sub27 = 0.0, $13 = 0.0, $cmp30 = 0, $div34 = 0.0, $add35 = 0.0, $add45 = 0.0, $add35_pn = 0.0, $p1_sroa_1_0 = 0.0, $p2_sroa_1_0 = 0.0, $14 = 0, $sub58 = 0.0, $sub61 = 0.0, $call = 0, $call62 = 0, $postscript_alias = 0, $15 = 0, $tobool = 0, $family = 0, $16 = 0, $17 = 0, $weight = 0, $18 = 0, $tobool66 = 0, $19 = 0, $stretch = 0, $20 = 0, $tobool72 = 0, $21 = 0, $style = 0, $22 = 0, $tobool78 = 0, $fontname = 0, $23 = 0, $24 = 0.0, $pencolor = 0, $type = 0, $25 = 0, $string = 0, $26 = 0, $call88 = 0, $tobool89 = 0, $27 = 0, $rgba = 0, $arrayidx = 0, $28 = 0, $conv98 = 0, $arrayidx102 = 0, $29 = 0, $conv103 = 0, $arrayidx107 = 0, $30 = 0, $conv108 = 0, $call111 = 0, $str = 0, $31 = 0, $call112 = 0, $call113 = 0, $call114 = 0, $call115 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $p;
+ $p = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ HEAP32[$p >> 2] = HEAP32[tempParam >> 2] | 0;
+ HEAP32[$p + 4 >> 2] = HEAP32[tempParam + 4 >> 2] | 0;
+ HEAP32[$p + 8 >> 2] = HEAP32[tempParam + 8 >> 2] | 0;
+ HEAP32[$p + 12 >> 2] = HEAP32[tempParam + 12 >> 2] | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $just = $para + 72 | 0;
+ $1 = HEAP8[$just] | 0;
+ $conv = $1 << 24 >> 24;
+ if (($conv | 0) == 108) {
+ label = 3;
+ break;
+ } else if (($conv | 0) == 114) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $x = $p | 0;
+ $2 = +HEAPF64[$x >> 3];
+ $p1_sroa_0_0 = $2;
+ label = 6;
+ break;
+ case 4:
+ $x4 = $p | 0;
+ $3 = +HEAPF64[$x4 >> 3];
+ $width = $para + 56 | 0;
+ $4 = +HEAPF64[$width >> 3];
+ $sub = $3 - $4;
+ $p1_sroa_0_0 = $sub;
+ label = 6;
+ break;
+ case 5:
+ $x7 = $p | 0;
+ $5 = +HEAPF64[$x7 >> 3];
+ $width8 = $para + 56 | 0;
+ $6 = +HEAPF64[$width8 >> 3];
+ $div = $6 * .5;
+ $sub9 = $5 - $div;
+ $p1_sroa_0_0 = $sub9;
+ label = 6;
+ break;
+ case 6:
+ $width12 = $para + 56 | 0;
+ $7 = +HEAPF64[$width12 >> 3];
+ $add = $p1_sroa_0_0 + $7;
+ $height = $para + 64 | 0;
+ $8 = +HEAPF64[$height >> 3];
+ $fontsize = $para + 24 | 0;
+ $9 = +HEAPF64[$fontsize >> 3];
+ $cmp = $8 < $9;
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $mul = $9 * 1.1;
+ $add16 = $mul + 1.0;
+ HEAPF64[$height >> 3] = $add16;
+ label = 8;
+ break;
+ case 8:
+ $sub19 = $p1_sroa_0_0 + -8.0;
+ $add21 = $add + 8.0;
+ $10 = HEAP32[4068] | 0;
+ $conv22 = +($10 >>> 0 >>> 0);
+ $y = $p + 8 | 0;
+ $11 = +HEAPF64[$y >> 3];
+ $sub23 = $conv22 - $11;
+ $12 = +HEAPF64[$height >> 3];
+ $sub27 = $sub23 - $12;
+ $13 = +HEAPF64[$fontsize >> 3];
+ $cmp30 = $13 < 12.0;
+ $div34 = $13 / 5.0;
+ if ($cmp30) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $add35 = $div34 + 1.4;
+ $add35_pn = $add35;
+ label = 11;
+ break;
+ case 10:
+ $add45 = $div34 + 2.0;
+ $add35_pn = $add45;
+ label = 11;
+ break;
+ case 11:
+ $p1_sroa_1_0 = $sub27 + $add35_pn;
+ $p2_sroa_1_0 = $sub23 + $add35_pn;
+ $14 = $job;
+ _gvprintf($14, 102736, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _gvprintf($14, 103936, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $sub19, HEAPF64[tempInt + 8 >> 3] = $p1_sroa_1_0, tempInt) | 0);
+ $sub58 = $add21 - $sub19;
+ $sub61 = $p2_sroa_1_0 - $p1_sroa_1_0;
+ _gvprintf($14, 103440, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $sub58, HEAPF64[tempInt + 8 >> 3] = $sub61, tempInt) | 0);
+ $call = _gvputs($14, 102416) | 0;
+ $call62 = _gvputs($14, 101904) | 0;
+ $postscript_alias = $para + 4 | 0;
+ $15 = HEAP32[$postscript_alias >> 2] | 0;
+ $tobool = ($15 | 0) == 0;
+ if ($tobool) {
+ label = 18;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $family = $15 + 4 | 0;
+ $16 = HEAP32[$family >> 2] | 0;
+ _gvprintf($14, 101560, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $16, tempInt) | 0);
+ $17 = HEAP32[$postscript_alias >> 2] | 0;
+ $weight = $17 + 8 | 0;
+ $18 = HEAP32[$weight >> 2] | 0;
+ $tobool66 = ($18 | 0) == 0;
+ if ($tobool66) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ _gvprintf($14, 100968, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $18, tempInt) | 0);
+ label = 14;
+ break;
+ case 14:
+ $19 = HEAP32[$postscript_alias >> 2] | 0;
+ $stretch = $19 + 12 | 0;
+ $20 = HEAP32[$stretch >> 2] | 0;
+ $tobool72 = ($20 | 0) == 0;
+ if ($tobool72) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ _gvprintf($14, 100608, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $20, tempInt) | 0);
+ label = 16;
+ break;
+ case 16:
+ $21 = HEAP32[$postscript_alias >> 2] | 0;
+ $style = $21 + 16 | 0;
+ $22 = HEAP32[$style >> 2] | 0;
+ $tobool78 = ($22 | 0) == 0;
+ if ($tobool78) {
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ _gvprintf($14, 100120, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $22, tempInt) | 0);
+ label = 19;
+ break;
+ case 18:
+ $fontname = $para + 20 | 0;
+ $23 = HEAP32[$fontname >> 2] | 0;
+ _gvprintf($14, 101560, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $23, tempInt) | 0);
+ label = 19;
+ break;
+ case 19:
+ $24 = +HEAPF64[$fontsize >> 3];
+ _gvprintf($14, 99744, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAPF64[tempInt >> 3] = $24, tempInt) | 0);
+ $pencolor = $0 + 16 | 0;
+ $type = $0 + 48 | 0;
+ $25 = HEAP32[$type >> 2] | 0;
+ if (($25 | 0) == 5) {
+ label = 20;
+ break;
+ } else if (($25 | 0) == 1) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 20:
+ $string = $pencolor;
+ $26 = HEAP32[$string >> 2] | 0;
+ $call88 = _strcasecmp($26, 157896) | 0;
+ $tobool89 = ($call88 | 0) == 0;
+ if ($tobool89) {
+ label = 24;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $27 = HEAP32[$string >> 2] | 0;
+ _gvprintf($14, 99272, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $27, tempInt) | 0);
+ label = 24;
+ break;
+ case 22:
+ $rgba = $pencolor;
+ $arrayidx = $pencolor;
+ $28 = HEAP8[$arrayidx] | 0;
+ $conv98 = $28 & 255;
+ $arrayidx102 = $rgba + 1 | 0;
+ $29 = HEAP8[$arrayidx102] | 0;
+ $conv103 = $29 & 255;
+ $arrayidx107 = $rgba + 2 | 0;
+ $30 = HEAP8[$arrayidx107] | 0;
+ $conv108 = $30 & 255;
+ _gvprintf($14, 98944, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $conv98, HEAP32[tempInt + 8 >> 2] = $conv103, HEAP32[tempInt + 16 >> 2] = $conv108, tempInt) | 0);
+ label = 24;
+ break;
+ case 23:
+ ___assert_func(111200, 442, 163736, 110816);
+ case 24:
+ $call111 = _gvputs($14, 98480) | 0;
+ $str = $para | 0;
+ $31 = HEAP32[$str >> 2] | 0;
+ $call112 = _html_string($31) | 0;
+ $call113 = _gvputs($14, $call112) | 0;
+ $call114 = _gvputs($14, 98088) | 0;
+ $call115 = _gvputs($14, 97672) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _core_loadimage_null($gvc, $us, $b, $filled) {
+ $gvc = $gvc | 0;
+ $us = $us | 0;
+ $b = $b | 0;
+ $filled = $filled | 0;
+ var tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _poolClear($pool) {
+ $pool = $pool | 0;
+ var $freeBlocks = 0, $0 = 0, $tobool = 0, $blocks2 = 0, $1 = 0, $tobool312 = 0, $p_013 = 0, $next = 0, $2 = 0, $3 = 0, $tobool3 = 0, $start = 0, $ptr = 0, $end = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $freeBlocks = $pool + 4 | 0;
+ $0 = HEAP32[$freeBlocks >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ $blocks2 = $pool | 0;
+ $1 = HEAP32[$blocks2 >> 2] | 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $tobool312 = ($1 | 0) == 0;
+ if ($tobool312) {
+ label = 6;
+ break;
+ } else {
+ $p_013 = $1;
+ label = 5;
+ break;
+ }
+ case 4:
+ HEAP32[$freeBlocks >> 2] = $1;
+ label = 6;
+ break;
+ case 5:
+ $next = $p_013 | 0;
+ $2 = HEAP32[$next >> 2] | 0;
+ $3 = HEAP32[$freeBlocks >> 2] | 0;
+ HEAP32[$next >> 2] = $3;
+ HEAP32[$freeBlocks >> 2] = $p_013;
+ $tobool3 = ($2 | 0) == 0;
+ if ($tobool3) {
+ label = 6;
+ break;
+ } else {
+ $p_013 = $2;
+ label = 5;
+ break;
+ }
+ case 6:
+ HEAP32[$blocks2 >> 2] = 0;
+ $start = $pool + 16 | 0;
+ HEAP32[$start >> 2] = 0;
+ $ptr = $pool + 12 | 0;
+ HEAP32[$ptr >> 2] = 0;
+ $end = $pool + 8 | 0;
+ HEAP32[$end >> 2] = 0;
+ return;
+ }
+}
+function _vml_grfill($job, $filled) {
+ $job = $job | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, $obj1 = 0, $0 = 0, $1 = 0, $call = 0, $fillcolor = 0, $call2 = 0, $2 = 0, $call3 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($filled | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $1 = $job;
+ $call = _gvputs($1, 106616) | 0;
+ $fillcolor = $0 + 56 | 0;
+ _vml_print_color($job, $fillcolor);
+ $call2 = _gvputs($1, 106280) | 0;
+ label = 5;
+ break;
+ case 4:
+ $2 = $job;
+ $call3 = _gvputs($2, 105896) | 0;
+ label = 5;
+ break;
+ case 5:
+ return;
+ }
+}
+function _vml_bzptarray($job, $A, $n) {
+ $job = $job | 0;
+ $A = $A | 0;
+ $n = $n | 0;
+ var $cmp6 = 0, $0 = 0, $c_08 = 0, $i_07 = 0, $x = 0, $1 = 0.0, $2 = 0, $conv = 0.0, $y = 0, $3 = 0.0, $sub = 0.0, $cmp2 = 0, $_ = 0, $inc = 0, $cmp = 0, $4 = 0, $call = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp6 = ($n | 0) > 0;
+ if ($cmp6) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $0 = $job;
+ $i_07 = 0;
+ $c_08 = 108960;
+ label = 4;
+ break;
+ case 4:
+ $x = $A + ($i_07 << 4) | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $2 = HEAP32[4068] | 0;
+ $conv = +($2 >>> 0 >>> 0);
+ $y = $A + ($i_07 << 4) + 8 | 0;
+ $3 = +HEAPF64[$y >> 3];
+ $sub = $conv - $3;
+ _gvprintf($0, 108224, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $c_08, HEAPF64[tempInt + 8 >> 3] = $1, HEAPF64[tempInt + 16 >> 3] = $sub, tempInt) | 0);
+ $cmp2 = ($i_07 | 0) == 0;
+ $_ = $cmp2 ? 107840 : 107344;
+ $inc = $i_07 + 1 | 0;
+ $cmp = ($inc | 0) < ($n | 0);
+ if ($cmp) {
+ $i_07 = $inc;
+ $c_08 = $_;
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $4 = $job;
+ $call = _gvputs($4, 107e3) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _core_loadimage_vml($job, $us, $b, $filled) {
+ $job = $job | 0;
+ $us = $us | 0;
+ $b = $b | 0;
+ $filled = $filled | 0;
+ var $4 = 0.0, $sub6 = 0.0, $5 = 0.0, $sub11 = 0.0, $sub17 = 0.0, $7 = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ $4 = +HEAPF64[$b >> 3];
+ $sub6 = +HEAPF64[$b + 16 >> 3] - $4;
+ $5 = +HEAPF64[$b + 24 >> 3];
+ $sub11 = $5 - +HEAPF64[$b + 8 >> 3];
+ $sub17 = +(~~(+HEAPF64[$job + 232 >> 3] - +HEAPF64[$job + 216 >> 3]) >>> 0 >>> 0) - $5;
+ $7 = $job;
+ _gvprintf($7, 108840, (tempInt = STACKTOP, STACKTOP = STACKTOP + 40 | 0, HEAP32[tempInt >> 2] = HEAP32[$us + 8 >> 2] | 0, HEAPF64[tempInt + 8 >> 3] = $sub6, HEAPF64[tempInt + 16 >> 3] = $sub11, HEAPF64[tempInt + 24 >> 3] = $4, HEAPF64[tempInt + 32 >> 3] = $sub17, tempInt) | 0);
+ _gvputs($7, 108192);
+ STACKTOP = __stackBase__;
+ return;
+}
+function _ps_freeimage($us) {
+ $us = $us | 0;
+ _free(HEAP32[$us + 52 >> 2] | 0);
+ return;
+}
+function _XML_ParserCreate($encodingName) {
+ $encodingName = $encodingName | 0;
+ return _XML_ParserCreate_MM($encodingName, 0, 0) | 0;
+}
+function _XML_ParserCreate_MM($encodingName, $memsuite, $nameSep) {
+ $encodingName = $encodingName | 0;
+ $memsuite = $memsuite | 0;
+ $nameSep = $nameSep | 0;
+ return _parserCreate($encodingName, $memsuite, $nameSep) | 0;
+}
+function _parserCreate($encodingName, $memsuite, $nameSep) {
+ $encodingName = $encodingName | 0;
+ $memsuite = $memsuite | 0;
+ $nameSep = $nameSep | 0;
+ var $tobool = 0, $malloc_fcn = 0, $0 = 0, $call = 0, $1 = 0, $cmp = 0, $m_mem = 0, $2 = 0, $malloc_fcn3 = 0, $realloc_fcn = 0, $3 = 0, $realloc_fcn4 = 0, $4 = 0, $free_fcn = 0, $5 = 0, $free_fcn5 = 0, $6 = 0, $call7 = 0, $7 = 0, $cmp8 = 0, $m_mem10 = 0, $malloc_fcn11 = 0, $realloc_fcn12 = 0, $8 = 0, $free_fcn13 = 0, $9 = 0, $parser_0 = 0, $tobool16 = 0, $m_buffer = 0, $m_bufferLim = 0, $m_attsSize = 0, $m_mem19 = 0, $malloc_fcn20 = 0, $10 = 0, $call22 = 0, $11 = 0, $m_atts = 0, $cmp24 = 0, $free_fcn27 = 0, $12 = 0, $13 = 0, $14 = 0, $call31 = 0, $m_dataBuf = 0, $cmp33 = 0, $free_fcn36 = 0, $15 = 0, $16 = 0, $17 = 0, $18 = 0, $19 = 0, $add_ptr = 0, $m_dataBufEnd = 0, $call46 = 0, $m_dtd47 = 0, $cmp49 = 0, $free_fcn52 = 0, $20 = 0, $21 = 0, $22 = 0, $23 = 0, $24 = 0, $25 = 0, $26 = 0, $m_freeBindingList = 0, $m_freeTagList = 0, $m_freeInternalEntities = 0, $m_groupSize = 0, $m_groupConnector = 0, $m_unknownEncodingHandler = 0, $m_unknownEncodingHandlerData = 0, $m_namespaceSeparator = 0, $m_ns = 0, $m_ns_triplets = 0, $m_nsAtts = 0, $m_nsAttsVersion = 0, $m_nsAttsPower = 0, $m_tempPool = 0, $m_temp2Pool = 0, $tobool63 = 0, $m_protocolEncodingName = 0, $27 = 0, $tobool64 = 0, $tobool67 = 0, $m_internalEncoding = 0, $28 = 0, $m_internalEncoding74 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($memsuite | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $malloc_fcn = $memsuite | 0;
+ $0 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call = FUNCTION_TABLE_ii[$0 & 1023](476) | 0;
+ $1 = $call;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ $parser_0 = $1;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $m_mem = $call + 12 | 0;
+ $2 = HEAP32[$malloc_fcn >> 2] | 0;
+ $malloc_fcn3 = $m_mem;
+ HEAP32[$malloc_fcn3 >> 2] = $2;
+ $realloc_fcn = $memsuite + 4 | 0;
+ $3 = HEAP32[$realloc_fcn >> 2] | 0;
+ $realloc_fcn4 = $call + 16 | 0;
+ $4 = $realloc_fcn4;
+ HEAP32[$4 >> 2] = $3;
+ $free_fcn = $memsuite + 8 | 0;
+ $5 = HEAP32[$free_fcn >> 2] | 0;
+ $free_fcn5 = $call + 20 | 0;
+ $6 = $free_fcn5;
+ HEAP32[$6 >> 2] = $5;
+ $parser_0 = $1;
+ label = 7;
+ break;
+ case 5:
+ $call7 = _malloc(476) | 0;
+ $7 = $call7;
+ $cmp8 = ($call7 | 0) == 0;
+ if ($cmp8) {
+ $parser_0 = $7;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $m_mem10 = $call7 + 12 | 0;
+ $malloc_fcn11 = $m_mem10;
+ HEAP32[$malloc_fcn11 >> 2] = 306;
+ $realloc_fcn12 = $call7 + 16 | 0;
+ $8 = $realloc_fcn12;
+ HEAP32[$8 >> 2] = 492;
+ $free_fcn13 = $call7 + 20 | 0;
+ $9 = $free_fcn13;
+ HEAP32[$9 >> 2] = 528;
+ $parser_0 = $7;
+ label = 7;
+ break;
+ case 7:
+ $tobool16 = ($parser_0 | 0) == 0;
+ if ($tobool16) {
+ $retval_0 = 0;
+ label = 20;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $m_buffer = $parser_0 + 8 | 0;
+ HEAP32[$m_buffer >> 2] = 0;
+ $m_bufferLim = $parser_0 + 32 | 0;
+ HEAP32[$m_bufferLim >> 2] = 0;
+ $m_attsSize = $parser_0 + 364 | 0;
+ HEAP32[$m_attsSize >> 2] = 16;
+ $m_mem19 = $parser_0 + 12 | 0;
+ $malloc_fcn20 = $m_mem19 | 0;
+ $10 = HEAP32[$malloc_fcn20 >> 2] | 0;
+ $call22 = FUNCTION_TABLE_ii[$10 & 1023](256) | 0;
+ $11 = $call22;
+ $m_atts = $parser_0 + 376 | 0;
+ HEAP32[$m_atts >> 2] = $11;
+ $cmp24 = ($call22 | 0) == 0;
+ if ($cmp24) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $free_fcn27 = $parser_0 + 20 | 0;
+ $12 = HEAP32[$free_fcn27 >> 2] | 0;
+ $13 = $parser_0;
+ FUNCTION_TABLE_vi[$12 & 1023]($13);
+ $retval_0 = 0;
+ label = 20;
+ break;
+ case 10:
+ $14 = HEAP32[$malloc_fcn20 >> 2] | 0;
+ $call31 = FUNCTION_TABLE_ii[$14 & 1023](1024) | 0;
+ $m_dataBuf = $parser_0 + 44 | 0;
+ HEAP32[$m_dataBuf >> 2] = $call31;
+ $cmp33 = ($call31 | 0) == 0;
+ if ($cmp33) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $free_fcn36 = $parser_0 + 20 | 0;
+ $15 = HEAP32[$free_fcn36 >> 2] | 0;
+ $16 = HEAP32[$m_atts >> 2] | 0;
+ $17 = $16;
+ FUNCTION_TABLE_vi[$15 & 1023]($17);
+ $18 = HEAP32[$free_fcn36 >> 2] | 0;
+ $19 = $parser_0;
+ FUNCTION_TABLE_vi[$18 & 1023]($19);
+ $retval_0 = 0;
+ label = 20;
+ break;
+ case 12:
+ $add_ptr = $call31 + 1024 | 0;
+ $m_dataBufEnd = $parser_0 + 48 | 0;
+ HEAP32[$m_dataBufEnd >> 2] = $add_ptr;
+ $call46 = _dtdCreate($m_mem19) | 0;
+ $m_dtd47 = $parser_0 + 340 | 0;
+ HEAP32[$m_dtd47 >> 2] = $call46;
+ $cmp49 = ($call46 | 0) == 0;
+ if ($cmp49) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $free_fcn52 = $parser_0 + 20 | 0;
+ $20 = HEAP32[$free_fcn52 >> 2] | 0;
+ $21 = HEAP32[$m_dataBuf >> 2] | 0;
+ FUNCTION_TABLE_vi[$20 & 1023]($21);
+ $22 = HEAP32[$free_fcn52 >> 2] | 0;
+ $23 = HEAP32[$m_atts >> 2] | 0;
+ $24 = $23;
+ FUNCTION_TABLE_vi[$22 & 1023]($24);
+ $25 = HEAP32[$free_fcn52 >> 2] | 0;
+ $26 = $parser_0;
+ FUNCTION_TABLE_vi[$25 & 1023]($26);
+ $retval_0 = 0;
+ label = 20;
+ break;
+ case 14:
+ $m_freeBindingList = $parser_0 + 360 | 0;
+ HEAP32[$m_freeBindingList >> 2] = 0;
+ $m_freeTagList = $parser_0 + 352 | 0;
+ HEAP32[$m_freeTagList >> 2] = 0;
+ $m_freeInternalEntities = $parser_0 + 288 | 0;
+ HEAP32[$m_freeInternalEntities >> 2] = 0;
+ $m_groupSize = $parser_0 + 452 | 0;
+ HEAP32[$m_groupSize >> 2] = 0;
+ $m_groupConnector = $parser_0 + 448 | 0;
+ HEAP32[$m_groupConnector >> 2] = 0;
+ $m_unknownEncodingHandler = $parser_0 + 124 | 0;
+ HEAP32[$m_unknownEncodingHandler >> 2] = 0;
+ $m_unknownEncodingHandlerData = $parser_0 + 244 | 0;
+ HEAP32[$m_unknownEncodingHandlerData >> 2] = 0;
+ $m_namespaceSeparator = $parser_0 + 456 | 0;
+ HEAP8[$m_namespaceSeparator] = 33;
+ $m_ns = $parser_0 + 232 | 0;
+ HEAP8[$m_ns] = 0;
+ $m_ns_triplets = $parser_0 + 233 | 0;
+ HEAP8[$m_ns_triplets] = 0;
+ $m_nsAtts = $parser_0 + 380 | 0;
+ HEAP32[$m_nsAtts >> 2] = 0;
+ $m_nsAttsVersion = $parser_0 + 384 | 0;
+ HEAP32[$m_nsAttsVersion >> 2] = 0;
+ $m_nsAttsPower = $parser_0 + 388 | 0;
+ HEAP8[$m_nsAttsPower] = 0;
+ $m_tempPool = $parser_0 + 400 | 0;
+ _poolInit($m_tempPool, $m_mem19);
+ $m_temp2Pool = $parser_0 + 424 | 0;
+ _poolInit($m_temp2Pool, $m_mem19);
+ _parserInit($parser_0, $encodingName);
+ $tobool63 = ($encodingName | 0) == 0;
+ if ($tobool63) {
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $m_protocolEncodingName = $parser_0 + 228 | 0;
+ $27 = HEAP32[$m_protocolEncodingName >> 2] | 0;
+ $tobool64 = ($27 | 0) == 0;
+ if ($tobool64) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ _XML_ParserFree($parser_0);
+ $retval_0 = 0;
+ label = 20;
+ break;
+ case 17:
+ $tobool67 = ($nameSep | 0) == 0;
+ if ($tobool67) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ HEAP8[$m_ns] = 1;
+ $m_internalEncoding = $parser_0 + 224 | 0;
+ HEAP32[$m_internalEncoding >> 2] = 12360;
+ $28 = HEAP8[$nameSep] | 0;
+ HEAP8[$m_namespaceSeparator] = $28;
+ $retval_0 = $parser_0;
+ label = 20;
+ break;
+ case 19:
+ $m_internalEncoding74 = $parser_0 + 224 | 0;
+ HEAP32[$m_internalEncoding74 >> 2] = 12360;
+ $retval_0 = $parser_0;
+ label = 20;
+ break;
+ case 20:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _parserInit($parser, $encodingName) {
+ $parser = $parser | 0;
+ $encodingName = $encodingName | 0;
+ var $m_processor = 0, $m_prologState = 0, $cmp = 0, $m_tempPool = 0, $call = 0, $cond = 0, $m_protocolEncodingName = 0, $m_curBase = 0, $m_initEncoding = 0, $m_encoding = 0, $call1 = 0, $m_userData = 0, $m_handlerArg = 0, $m_startElementHandler = 0, $m_externalEntityRefHandlerArg = 0, $0 = 0, $m_skippedEntityHandler = 0, $m_elementDeclHandler = 0, $m_buffer = 0, $1 = 0, $2 = 0, $m_bufferPtr = 0, $3 = 0, $m_bufferEnd = 0, $m_parseEndByteIndex = 0, $m_parseEndPtr = 0, $m_declEntity = 0, $m_position = 0, $4 = 0, $$etemp$0$0 = 0, $$etemp$0$1 = 0, $st$1$0 = 0, $st$2$1 = 0, $m_errorCode = 0, $m_defaultExpandInternalEntities = 0, $5 = 0, $6 = 0, $m_tagLevel = 0, $m_tagStack = 0, $m_inheritedBindings = 0, $m_nSpecifiedAtts = 0, $m_unknownEncodingMem = 0, $m_unknownEncodingRelease = 0, $m_unknownEncodingData = 0, $m_parentParser = 0, $parsing = 0, $m_hash_secret_salt = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_processor = $parser + 264 | 0;
+ HEAP32[$m_processor >> 2] = 154;
+ $m_prologState = $parser + 252 | 0;
+ _XmlPrologStateInit($m_prologState);
+ $cmp = ($encodingName | 0) == 0;
+ if ($cmp) {
+ $cond = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $m_tempPool = $parser + 400 | 0;
+ $call = _poolCopyString($m_tempPool, $encodingName) | 0;
+ $cond = $call;
+ label = 4;
+ break;
+ case 4:
+ $m_protocolEncodingName = $parser + 228 | 0;
+ HEAP32[$m_protocolEncodingName >> 2] = $cond;
+ $m_curBase = $parser + 344 | 0;
+ HEAP32[$m_curBase >> 2] = 0;
+ $m_initEncoding = $parser + 148 | 0;
+ $m_encoding = $parser + 144 | 0;
+ $call1 = _XmlInitEncoding($m_initEncoding, $m_encoding, 0) | 0;
+ $m_userData = $parser | 0;
+ HEAP32[$m_userData >> 2] = 0;
+ $m_handlerArg = $parser + 4 | 0;
+ HEAP32[$m_handlerArg >> 2] = 0;
+ $m_startElementHandler = $parser + 52 | 0;
+ $m_externalEntityRefHandlerArg = $parser + 116 | 0;
+ $0 = $m_startElementHandler;
+ _memset($0 | 0, 0, 64);
+ HEAP32[$m_externalEntityRefHandlerArg >> 2] = $parser;
+ $m_skippedEntityHandler = $parser + 120 | 0;
+ HEAP32[$m_skippedEntityHandler >> 2] = 0;
+ $m_elementDeclHandler = $parser + 128 | 0;
+ $m_buffer = $parser + 8 | 0;
+ $1 = $m_elementDeclHandler;
+ _memset($1 | 0, 0, 16);
+ $2 = HEAP32[$m_buffer >> 2] | 0;
+ $m_bufferPtr = $parser + 24 | 0;
+ HEAP32[$m_bufferPtr >> 2] = $2;
+ $3 = HEAP32[$m_buffer >> 2] | 0;
+ $m_bufferEnd = $parser + 28 | 0;
+ HEAP32[$m_bufferEnd >> 2] = $3;
+ $m_parseEndByteIndex = $parser + 36 | 0;
+ HEAP32[$m_parseEndByteIndex >> 2] = 0;
+ $m_parseEndPtr = $parser + 40 | 0;
+ HEAP32[$m_parseEndPtr >> 2] = 0;
+ $m_declEntity = $parser + 300 | 0;
+ $m_position = $parser + 392 | 0;
+ $4 = $m_position;
+ $$etemp$0$0 = 0;
+ $$etemp$0$1 = 0;
+ $st$1$0 = $4 | 0;
+ HEAP32[$st$1$0 >> 2] = $$etemp$0$0;
+ $st$2$1 = $4 + 4 | 0;
+ HEAP32[$st$2$1 >> 2] = $$etemp$0$1;
+ $m_errorCode = $parser + 268 | 0;
+ $m_defaultExpandInternalEntities = $parser + 292 | 0;
+ $5 = $m_errorCode;
+ _memset($5 | 0, 0, 20);
+ $6 = $m_declEntity;
+ _memset($6 | 0, 0, 38);
+ HEAP8[$m_defaultExpandInternalEntities] = 1;
+ $m_tagLevel = $parser + 296 | 0;
+ HEAP32[$m_tagLevel >> 2] = 0;
+ $m_tagStack = $parser + 348 | 0;
+ HEAP32[$m_tagStack >> 2] = 0;
+ $m_inheritedBindings = $parser + 356 | 0;
+ HEAP32[$m_inheritedBindings >> 2] = 0;
+ $m_nSpecifiedAtts = $parser + 368 | 0;
+ HEAP32[$m_nSpecifiedAtts >> 2] = 0;
+ $m_unknownEncodingMem = $parser + 236 | 0;
+ HEAP32[$m_unknownEncodingMem >> 2] = 0;
+ $m_unknownEncodingRelease = $parser + 248 | 0;
+ HEAP32[$m_unknownEncodingRelease >> 2] = 0;
+ $m_unknownEncodingData = $parser + 240 | 0;
+ HEAP32[$m_unknownEncodingData >> 2] = 0;
+ $m_parentParser = $parser + 460 | 0;
+ HEAP32[$m_parentParser >> 2] = 0;
+ $parsing = $parser + 464 | 0;
+ HEAP32[$parsing >> 2] = 0;
+ $m_hash_secret_salt = $parser + 472 | 0;
+ HEAP32[$m_hash_secret_salt >> 2] = 0;
+ return;
+ }
+}
+function _poolCopyString($pool, $s) {
+ $pool = $pool | 0;
+ $s = $s | 0;
+ var $ptr = 0, $end = 0, $s_addr_0 = 0, $0 = 0, $1 = 0, $cmp = 0, $call = 0, $tobool = 0, $2 = 0, $3 = 0, $incdec_ptr = 0, $incdec_ptr2 = 0, $4 = 0, $tobool3 = 0, $start = 0, $5 = 0, $6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr = $pool + 12 | 0;
+ $end = $pool + 8 | 0;
+ $s_addr_0 = $s;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP32[$ptr >> 2] | 0;
+ $1 = HEAP32[$end >> 2] | 0;
+ $cmp = ($0 | 0) == ($1 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call = _poolGrow($pool) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP8[$s_addr_0] | 0;
+ $3 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $3 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$3] = $2;
+ $incdec_ptr2 = $s_addr_0 + 1 | 0;
+ $4 = HEAP8[$s_addr_0] | 0;
+ $tobool3 = $4 << 24 >> 24 == 0;
+ if ($tobool3) {
+ label = 6;
+ break;
+ } else {
+ $s_addr_0 = $incdec_ptr2;
+ label = 3;
+ break;
+ }
+ case 6:
+ $start = $pool + 16 | 0;
+ $5 = HEAP32[$start >> 2] | 0;
+ $6 = HEAP32[$ptr >> 2] | 0;
+ HEAP32[$start >> 2] = $6;
+ $retval_0 = $5;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _vml_print_color($job, $color) {
+ $job = $job | 0;
+ $color = $color | 0;
+ var $type = 0, $0 = 0, $string = 0, $1 = 0, $2 = 0, $call = 0, $rgba = 0, $arrayidx = 0, $3 = 0, $cmp = 0, $4 = 0, $call4 = 0, $arrayidx7 = 0, $5 = 0, $conv8 = 0, $arrayidx11 = 0, $6 = 0, $conv12 = 0, $arrayidx15 = 0, $7 = 0, $conv16 = 0, $8 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $color;
+ $color = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ _memcpy($color, tempParam, 40);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $color + 32 | 0;
+ $0 = HEAP32[$type >> 2] | 0;
+ if (($0 | 0) == 5) {
+ label = 3;
+ break;
+ } else if (($0 | 0) == 1) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $string = $color;
+ $1 = HEAP32[$string >> 2] | 0;
+ $2 = $job;
+ $call = _gvputs($2, $1) | 0;
+ label = 8;
+ break;
+ case 4:
+ $rgba = $color;
+ $arrayidx = $rgba + 3 | 0;
+ $3 = HEAP8[$arrayidx] | 0;
+ $cmp = $3 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $4 = $job;
+ $call4 = _gvputs($4, 112208) | 0;
+ label = 8;
+ break;
+ case 6:
+ $arrayidx7 = $color;
+ $5 = HEAP8[$arrayidx7] | 0;
+ $conv8 = $5 & 255;
+ $arrayidx11 = $rgba + 1 | 0;
+ $6 = HEAP8[$arrayidx11] | 0;
+ $conv12 = $6 & 255;
+ $arrayidx15 = $rgba + 2 | 0;
+ $7 = HEAP8[$arrayidx15] | 0;
+ $conv16 = $7 & 255;
+ $8 = $job;
+ _gvprintf($8, 111656, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $conv8, HEAP32[tempInt + 8 >> 2] = $conv12, HEAP32[tempInt + 16 >> 2] = $conv16, tempInt) | 0);
+ label = 8;
+ break;
+ case 7:
+ ___assert_func(111200, 95, 163752, 110816);
+ case 8:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _core_loadimage_pslib($job, $us, $b, $filled) {
+ $job = $job | 0;
+ $us = $us | 0;
+ $b = $b | 0;
+ $filled = $filled | 0;
+ var $AF = 0, $tobool = 0, $tobool1 = 0, $name = 0, $0 = 0, $tobool5 = 0, $data = 0, $1 = 0, $tobool9 = 0, $2 = 0, $3 = 0, $arrayidx10 = 0, $UR = 0, $4 = 0, $5 = 0, $x = 0, $6 = 0.0, $x13 = 0, $y = 0, $7 = 0.0, $y16 = 0, $x18 = 0, $8 = 0.0, $x20 = 0, $y22 = 0, $9 = 0.0, $y24 = 0, $tobool25 = 0, $10 = 0, $x28 = 0, $11 = 0.0, $y30 = 0, $12 = 0.0, $x28_1 = 0, $13 = 0.0, $y30_1 = 0, $14 = 0.0, $x28_2 = 0, $15 = 0.0, $y30_2 = 0, $16 = 0.0, $x28_3 = 0, $17 = 0.0, $y30_3 = 0, $18 = 0.0, $19 = 0.0, $20 = 0.0, $21 = 0, $22 = 0, $x40 = 0, $23 = 0.0, $y42 = 0, $24 = 0.0, $x40_1 = 0, $25 = 0.0, $y42_1 = 0, $26 = 0.0, $x40_2 = 0, $27 = 0.0, $y42_2 = 0, $28 = 0.0, $x40_3 = 0, $29 = 0.0, $y42_3 = 0, $30 = 0.0, $31 = 0.0, $32 = 0.0, $33 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 64 | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $AF = __stackBase__ | 0;
+ $tobool = ($job | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(107776, 205, 164488, 107304);
+ case 4:
+ $tobool1 = ($us | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ ___assert_func(107776, 206, 164488, 106968);
+ case 6:
+ $name = $us + 8 | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ $tobool5 = ($0 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ ___assert_func(107776, 207, 164488, 106576);
+ case 8:
+ $data = $us + 52 | 0;
+ $1 = HEAP32[$data >> 2] | 0;
+ $tobool9 = ($1 | 0) == 0;
+ if ($tobool9) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $2 = $AF;
+ $3 = $b;
+ HEAP32[$2 >> 2] = HEAP32[$3 >> 2] | 0;
+ HEAP32[$2 + 4 >> 2] = HEAP32[$3 + 4 >> 2] | 0;
+ HEAP32[$2 + 8 >> 2] = HEAP32[$3 + 8 >> 2] | 0;
+ HEAP32[$2 + 12 >> 2] = HEAP32[$3 + 12 >> 2] | 0;
+ $arrayidx10 = $AF + 32 | 0;
+ $UR = $b + 16 | 0;
+ $4 = $arrayidx10;
+ $5 = $UR;
+ HEAP32[$4 >> 2] = HEAP32[$5 >> 2] | 0;
+ HEAP32[$4 + 4 >> 2] = HEAP32[$5 + 4 >> 2] | 0;
+ HEAP32[$4 + 8 >> 2] = HEAP32[$5 + 8 >> 2] | 0;
+ HEAP32[$4 + 12 >> 2] = HEAP32[$5 + 12 >> 2] | 0;
+ $x = $AF | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $x13 = $AF + 16 | 0;
+ HEAPF64[$x13 >> 3] = $6;
+ $y = $AF + 40 | 0;
+ $7 = +HEAPF64[$y >> 3];
+ $y16 = $AF + 24 | 0;
+ HEAPF64[$y16 >> 3] = $7;
+ $x18 = $arrayidx10 | 0;
+ $8 = +HEAPF64[$x18 >> 3];
+ $x20 = $AF + 48 | 0;
+ HEAPF64[$x20 >> 3] = $8;
+ $y22 = $AF + 8 | 0;
+ $9 = +HEAPF64[$y22 >> 3];
+ $y24 = $AF + 56 | 0;
+ HEAPF64[$y24 >> 3] = $9;
+ $tobool25 = $filled << 24 >> 24 == 0;
+ if ($tobool25) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $10 = $job;
+ _gvprintf($10, 106248, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ $x28 = $AF | 0;
+ $11 = +HEAPF64[$x28 >> 3];
+ $y30 = $AF + 8 | 0;
+ $12 = +HEAPF64[$y30 >> 3];
+ _gvprintf($10, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $11, HEAPF64[tempInt + 8 >> 3] = $12, tempInt) | 0);
+ $x28_1 = $AF + 16 | 0;
+ $13 = +HEAPF64[$x28_1 >> 3];
+ $y30_1 = $AF + 24 | 0;
+ $14 = +HEAPF64[$y30_1 >> 3];
+ _gvprintf($10, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $13, HEAPF64[tempInt + 8 >> 3] = $14, tempInt) | 0);
+ $x28_2 = $AF + 32 | 0;
+ $15 = +HEAPF64[$x28_2 >> 3];
+ $y30_2 = $AF + 40 | 0;
+ $16 = +HEAPF64[$y30_2 >> 3];
+ _gvprintf($10, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $15, HEAPF64[tempInt + 8 >> 3] = $16, tempInt) | 0);
+ $x28_3 = $AF + 48 | 0;
+ $17 = +HEAPF64[$x28_3 >> 3];
+ $y30_3 = $AF + 56 | 0;
+ $18 = +HEAPF64[$y30_3 >> 3];
+ _gvprintf($10, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $17, HEAPF64[tempInt + 8 >> 3] = $18, tempInt) | 0);
+ $19 = +HEAPF64[$x >> 3];
+ $20 = +HEAPF64[$y22 >> 3];
+ _gvprintf($10, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $19, HEAPF64[tempInt + 8 >> 3] = $20, tempInt) | 0);
+ $21 = HEAP32[$name >> 2] | 0;
+ _gvprintf($10, 105464, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = 4, HEAP32[tempInt + 8 >> 2] = $21, tempInt) | 0);
+ label = 11;
+ break;
+ case 11:
+ $22 = $job;
+ _gvprintf($22, 106248, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ $x40 = $AF | 0;
+ $23 = +HEAPF64[$x40 >> 3];
+ $y42 = $AF + 8 | 0;
+ $24 = +HEAPF64[$y42 >> 3];
+ _gvprintf($22, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $23, HEAPF64[tempInt + 8 >> 3] = $24, tempInt) | 0);
+ $x40_1 = $AF + 16 | 0;
+ $25 = +HEAPF64[$x40_1 >> 3];
+ $y42_1 = $AF + 24 | 0;
+ $26 = +HEAPF64[$y42_1 >> 3];
+ _gvprintf($22, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $25, HEAPF64[tempInt + 8 >> 3] = $26, tempInt) | 0);
+ $x40_2 = $AF + 32 | 0;
+ $27 = +HEAPF64[$x40_2 >> 3];
+ $y42_2 = $AF + 40 | 0;
+ $28 = +HEAPF64[$y42_2 >> 3];
+ _gvprintf($22, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $27, HEAPF64[tempInt + 8 >> 3] = $28, tempInt) | 0);
+ $x40_3 = $AF + 48 | 0;
+ $29 = +HEAPF64[$x40_3 >> 3];
+ $y42_3 = $AF + 56 | 0;
+ $30 = +HEAPF64[$y42_3 >> 3];
+ _gvprintf($22, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $29, HEAPF64[tempInt + 8 >> 3] = $30, tempInt) | 0);
+ $31 = +HEAPF64[$x >> 3];
+ $32 = +HEAPF64[$y22 >> 3];
+ _gvprintf($22, 105864, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $31, HEAPF64[tempInt + 8 >> 3] = $32, tempInt) | 0);
+ $33 = HEAP32[$name >> 2] | 0;
+ _gvprintf($22, 105152, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAP32[tempInt >> 2] = 4, HEAP32[tempInt + 8 >> 2] = $33, tempInt) | 0);
+ label = 12;
+ break;
+ case 12:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _core_loadimage_ps($job, $us, $b, $filled) {
+ $job = $job | 0;
+ $us = $us | 0;
+ $b = $b | 0;
+ $filled = $filled | 0;
+ var $statbuf = 0, $tobool = 0, $tobool1 = 0, $name = 0, $0 = 0, $tobool5 = 0, $data = 0, $1 = 0, $tobool9 = 0, $datafree = 0, $2 = 0, $cmp = 0, $datasize = 0, $_pr = 0, $tobool16 = 0, $call = 0, $tobool18 = 0, $f = 0, $3 = 0, $call21 = 0, $type = 0, $4 = 0, $_off = 0, $switch = 0, $call22 = 0, $st_size = 0, $5 = 0, $datasize23 = 0, $6 = 0, $call25 = 0, $7 = 0, $call29 = 0, $must_inline = 0, $8 = 0, $tobool31 = 0, $datafree33 = 0, $_pr30 = 0, $tobool37 = 0, $x = 0, $9 = 0.0, $x39 = 0, $10 = 0, $conv = 0.0, $sub = 0.0, $y = 0, $11 = 0.0, $y41 = 0, $12 = 0, $conv42 = 0.0, $sub43 = 0.0, $13 = 0, $must_inline44 = 0, $14 = 0, $tobool45 = 0, $15 = 0, $macro_id = 0, $16 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 72 | 0;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $statbuf = __stackBase__ | 0;
+ $tobool = ($job | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(107776, 146, 164512, 107304);
+ case 4:
+ $tobool1 = ($us | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ ___assert_func(107776, 147, 164512, 106968);
+ case 6:
+ $name = $us + 8 | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ $tobool5 = ($0 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ ___assert_func(107776, 148, 164512, 106576);
+ case 8:
+ $data = $us + 52 | 0;
+ $1 = HEAP32[$data >> 2] | 0;
+ $tobool9 = ($1 | 0) == 0;
+ if ($tobool9) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $datafree = $us + 60 | 0;
+ $2 = HEAP32[$datafree >> 2] | 0;
+ $cmp = ($2 | 0) == 160;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ FUNCTION_TABLE_vi[$2 & 1023]($us);
+ HEAP32[$data >> 2] = 0;
+ HEAP32[$datafree >> 2] = 0;
+ $datasize = $us + 56 | 0;
+ HEAP32[$datasize >> 2] = 0;
+ label = 11;
+ break;
+ case 11:
+ $_pr = HEAP32[$data >> 2] | 0;
+ $tobool16 = ($_pr | 0) == 0;
+ if ($tobool16) {
+ label = 12;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 12:
+ $call = _gvusershape_file_access($us) | 0;
+ $tobool18 = $call << 24 >> 24 == 0;
+ if ($tobool18) {
+ label = 22;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $f = $us + 20 | 0;
+ $3 = HEAP32[$f >> 2] | 0;
+ $call21 = _fileno($3 | 0) | 0;
+ $type = $us + 24 | 0;
+ $4 = HEAP32[$type >> 2] | 0;
+ $_off = $4 - 6 | 0;
+ $switch = $_off >>> 0 < 2;
+ if ($switch) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $call22 = _fstat($call21 | 0, $statbuf | 0) | 0;
+ $st_size = $statbuf + 28 | 0;
+ $5 = HEAP32[$st_size >> 2] | 0;
+ $datasize23 = $us + 56 | 0;
+ HEAP32[$datasize23 >> 2] = $5;
+ $6 = HEAP32[$st_size >> 2] | 0;
+ $call25 = _malloc($6) | 0;
+ HEAP32[$data >> 2] = $call25;
+ $7 = HEAP32[$st_size >> 2] | 0;
+ $call29 = _read($call21 | 0, $call25 | 0, $7 | 0) | 0;
+ $must_inline = $us + 16 | 0;
+ HEAP8[$must_inline] = 1;
+ label = 15;
+ break;
+ case 15:
+ $8 = HEAP32[$data >> 2] | 0;
+ $tobool31 = ($8 | 0) == 0;
+ if ($tobool31) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $datafree33 = $us + 60 | 0;
+ HEAP32[$datafree33 >> 2] = 160;
+ label = 17;
+ break;
+ case 17:
+ _gvusershape_file_release($us);
+ $_pr30 = HEAP32[$data >> 2] | 0;
+ $tobool37 = ($_pr30 | 0) == 0;
+ if ($tobool37) {
+ label = 22;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $x = $b | 0;
+ $9 = +HEAPF64[$x >> 3];
+ $x39 = $us + 32 | 0;
+ $10 = HEAP32[$x39 >> 2] | 0;
+ $conv = +($10 | 0);
+ $sub = $9 - $conv;
+ $y = $b + 8 | 0;
+ $11 = +HEAPF64[$y >> 3];
+ $y41 = $us + 36 | 0;
+ $12 = HEAP32[$y41 >> 2] | 0;
+ $conv42 = +($12 | 0);
+ $sub43 = $11 - $conv42;
+ $13 = $job;
+ _gvprintf($13, 104784, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[tempInt >> 3] = $sub, HEAPF64[tempInt + 8 >> 3] = $sub43, tempInt) | 0);
+ $must_inline44 = $us + 16 | 0;
+ $14 = HEAP8[$must_inline44] | 0;
+ $tobool45 = $14 << 24 >> 24 == 0;
+ if ($tobool45) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $15 = $job;
+ _epsf_emit_body($15, $us);
+ label = 21;
+ break;
+ case 20:
+ $macro_id = $us + 12 | 0;
+ $16 = HEAP32[$macro_id >> 2] | 0;
+ _gvprintf($13, 104272, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $16, tempInt) | 0);
+ label = 21;
+ break;
+ case 21:
+ _gvprintf($13, 103824, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ label = 22;
+ break;
+ case 22:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _core_loadimage_vrml($job, $us, $b, $filled) {
+ $job = $job | 0;
+ $us = $us | 0;
+ $b = $b | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, $obj1 = 0, $0 = 0, $tobool2 = 0, $tobool6 = 0, $name = 0, $1 = 0, $tobool10 = 0, $u = 0, $n15 = 0, $2 = 0, $tobool16 = 0, $3 = 0, $4 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($job | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(107776, 114, 164440, 107304);
+ case 4:
+ $obj1 = $job + 16 | 0;
+ $0 = HEAP32[$obj1 >> 2] | 0;
+ $tobool2 = ($0 | 0) == 0;
+ if ($tobool2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ ___assert_func(107776, 116, 164440, 103408);
+ case 6:
+ $tobool6 = ($us | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ ___assert_func(107776, 117, 164440, 106968);
+ case 8:
+ $name = $us + 8 | 0;
+ $1 = HEAP32[$name >> 2] | 0;
+ $tobool10 = ($1 | 0) == 0;
+ if ($tobool10) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ ___assert_func(107776, 118, 164440, 106576);
+ case 10:
+ $u = $0 + 8 | 0;
+ $n15 = $u;
+ $2 = HEAP32[$n15 >> 2] | 0;
+ $tobool16 = ($2 | 0) == 0;
+ if ($tobool16) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ ___assert_func(107776, 121, 164440, 103040);
+ case 12:
+ $3 = $job;
+ _gvprintf($3, 102696, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _gvprintf($3, 102320, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _gvprintf($3, 101848, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _gvprintf($3, 101472, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _gvprintf($3, 100904, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _gvprintf($3, 100568, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ $4 = HEAP32[$name >> 2] | 0;
+ _gvprintf($3, 100056, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[tempInt >> 2] = $4, tempInt) | 0);
+ _gvprintf($3, 99656, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ _gvprintf($3, 99232, (tempInt = STACKTOP, STACKTOP = STACKTOP + 1 | 0, STACKTOP = STACKTOP + 7 >> 3 << 3, HEAP32[tempInt >> 2] = 0, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _core_loadimage_fig($job, $us, $bf, $filled) {
+ $job = $job | 0;
+ $us = $us | 0;
+ $bf = $bf | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, $tobool1 = 0, $name = 0, $0 = 0, $tobool5 = 0, $x = 0, $1 = 0.0, $cmp = 0, $add = 0.0, $sub = 0.0, $add_sink = 0.0, $conv = 0, $y = 0, $2 = 0.0, $cmp20 = 0, $add25 = 0.0, $sub30 = 0.0, $add25_sink = 0.0, $conv26 = 0, $x36 = 0, $3 = 0.0, $cmp37 = 0, $add42 = 0.0, $sub47 = 0.0, $add42_sink = 0.0, $conv43 = 0, $y54 = 0, $4 = 0.0, $cmp55 = 0, $add60 = 0.0, $sub65 = 0.0, $add60_sink = 0.0, $conv61 = 0, $5 = 0, $6 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $bf;
+ $bf = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($bf, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($job | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(107776, 90, 164536, 107304);
+ case 4:
+ $tobool1 = ($us | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ ___assert_func(107776, 91, 164536, 106968);
+ case 6:
+ $name = $us + 8 | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ $tobool5 = ($0 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ ___assert_func(107776, 92, 164536, 106576);
+ case 8:
+ $x = $bf | 0;
+ $1 = +HEAPF64[$x >> 3];
+ $cmp = $1 < 0.0;
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add = $1 + .5;
+ $add_sink = $add;
+ label = 11;
+ break;
+ case 10:
+ $sub = $1 + -.5;
+ $add_sink = $sub;
+ label = 11;
+ break;
+ case 11:
+ $conv = ~~$add_sink;
+ $y = $bf + 8 | 0;
+ $2 = +HEAPF64[$y >> 3];
+ $cmp20 = $2 < 0.0;
+ if ($cmp20) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $add25 = $2 + .5;
+ $add25_sink = $add25;
+ label = 14;
+ break;
+ case 13:
+ $sub30 = $2 + -.5;
+ $add25_sink = $sub30;
+ label = 14;
+ break;
+ case 14:
+ $conv26 = ~~$add25_sink;
+ $x36 = $bf + 16 | 0;
+ $3 = +HEAPF64[$x36 >> 3];
+ $cmp37 = $3 < 0.0;
+ if ($cmp37) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $add42 = $3 + .5;
+ $add42_sink = $add42;
+ label = 17;
+ break;
+ case 16:
+ $sub47 = $3 + -.5;
+ $add42_sink = $sub47;
+ label = 17;
+ break;
+ case 17:
+ $conv43 = ~~$add42_sink;
+ $y54 = $bf + 24 | 0;
+ $4 = +HEAPF64[$y54 >> 3];
+ $cmp55 = $4 < 0.0;
+ if ($cmp55) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $add60 = $4 + .5;
+ $add60_sink = $add60;
+ label = 20;
+ break;
+ case 19:
+ $sub65 = $4 + -.5;
+ $add60_sink = $sub65;
+ label = 20;
+ break;
+ case 20:
+ $conv61 = ~~$add60_sink;
+ $5 = HEAP32[$name >> 2] | 0;
+ $6 = $job;
+ _gvprintf($6, 98816, (tempInt = STACKTOP, STACKTOP = STACKTOP + 144 | 0, HEAP32[tempInt >> 2] = 2, HEAP32[tempInt + 8 >> 2] = 5, HEAP32[tempInt + 16 >> 2] = 0, HEAP32[tempInt + 24 >> 2] = 0, HEAP32[tempInt + 32 >> 2] = 0, HEAP32[tempInt + 40 >> 2] = -1, HEAP32[tempInt + 48 >> 2] = 1, HEAP32[tempInt + 56 >> 2] = -1, HEAP32[tempInt + 64 >> 2] = 0, HEAPF64[tempInt + 72 >> 3] = 0.0, HEAP32[tempInt + 80 >> 2] = 0, HEAP32[tempInt + 88 >> 2] = 0, HEAP32[tempInt + 96 >> 2] = 0, HEAP32[tempInt + 104 >> 2] = 0, HEAP32[tempInt + 112 >> 2] = 0, HEAP32[tempInt + 120 >> 2] = 5, HEAP32[tempInt + 128 >> 2] = 0, HEAP32[tempInt + 136 >> 2] = $5, tempInt) | 0);
+ _gvprintf($6, 98424, (tempInt = STACKTOP, STACKTOP = STACKTOP + 80 | 0, HEAP32[tempInt >> 2] = $conv, HEAP32[tempInt + 8 >> 2] = $conv26, HEAP32[tempInt + 16 >> 2] = $conv, HEAP32[tempInt + 24 >> 2] = $conv61, HEAP32[tempInt + 32 >> 2] = $conv43, HEAP32[tempInt + 40 >> 2] = $conv61, HEAP32[tempInt + 48 >> 2] = $conv43, HEAP32[tempInt + 56 >> 2] = $conv26, HEAP32[tempInt + 64 >> 2] = $conv, HEAP32[tempInt + 72 >> 2] = $conv26, tempInt) | 0);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _core_loadimage_svg($job, $us, $b, $filled) {
+ $job = $job | 0;
+ $us = $us | 0;
+ $b = $b | 0;
+ $filled = $filled | 0;
+ var $tobool = 0, $tobool1 = 0, $name = 0, $0 = 0, $tobool5 = 0, $1 = 0, $call = 0, $2 = 0, $call10 = 0, $rotation = 0, $3 = 0, $tobool11 = 0, $UR = 0, $y = 0, $4 = 0.0, $y12 = 0, $5 = 0.0, $sub = 0.0, $x = 0, $6 = 0.0, $x15 = 0, $7 = 0.0, $sub16 = 0.0, $8 = 0, $9 = 0.0, $10 = 0.0, $x27 = 0, $11 = 0.0, $x29 = 0, $12 = 0.0, $sub30 = 0.0, $y32 = 0, $13 = 0.0, $y34 = 0, $14 = 0.0, $sub35 = 0.0, $sub40 = 0.0, $call41 = 0, label = 0, tempParam = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ tempParam = $b;
+ $b = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ _memcpy($b, tempParam, 32);
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($job | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ ___assert_func(107776, 49, 164464, 107304);
+ case 4:
+ $tobool1 = ($us | 0) == 0;
+ if ($tobool1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ ___assert_func(107776, 50, 164464, 106968);
+ case 6:
+ $name = $us + 8 | 0;
+ $0 = HEAP32[$name >> 2] | 0;
+ $tobool5 = ($0 | 0) == 0;
+ if ($tobool5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ ___assert_func(107776, 51, 164464, 106576);
+ case 8:
+ $1 = $job;
+ $call = _gvputs($1, 98032) | 0;
+ $2 = HEAP32[$name >> 2] | 0;
+ $call10 = _gvputs($1, $2) | 0;
+ $rotation = $job + 360 | 0;
+ $3 = HEAP32[$rotation >> 2] | 0;
+ $tobool11 = ($3 | 0) == 0;
+ $UR = $b + 16 | 0;
+ if ($tobool11) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $y = $b + 24 | 0;
+ $4 = +HEAPF64[$y >> 3];
+ $y12 = $b + 8 | 0;
+ $5 = +HEAPF64[$y12 >> 3];
+ $sub = $4 - $5;
+ $x = $UR | 0;
+ $6 = +HEAPF64[$x >> 3];
+ $x15 = $b | 0;
+ $7 = +HEAPF64[$x15 >> 3];
+ $sub16 = $6 - $7;
+ _gvprintf($1, 97568, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $sub, HEAPF64[tempInt + 8 >> 3] = $sub16, HEAPF64[tempInt + 16 >> 3] = $7, HEAPF64[tempInt + 24 >> 3] = $4, tempInt) | 0);
+ $8 = HEAP32[$rotation >> 2] | 0;
+ $9 = +HEAPF64[$x15 >> 3];
+ $10 = +HEAPF64[$y >> 3];
+ _gvprintf($1, 97200, (tempInt = STACKTOP, STACKTOP = STACKTOP + 24 | 0, HEAP32[tempInt >> 2] = $8, HEAPF64[tempInt + 8 >> 3] = $9, HEAPF64[tempInt + 16 >> 3] = $10, tempInt) | 0);
+ label = 11;
+ break;
+ case 10:
+ $x27 = $UR | 0;
+ $11 = +HEAPF64[$x27 >> 3];
+ $x29 = $b | 0;
+ $12 = +HEAPF64[$x29 >> 3];
+ $sub30 = $11 - $12;
+ $y32 = $b + 24 | 0;
+ $13 = +HEAPF64[$y32 >> 3];
+ $y34 = $b + 8 | 0;
+ $14 = +HEAPF64[$y34 >> 3];
+ $sub35 = $13 - $14;
+ $sub40 = -0.0 - $13;
+ _gvprintf($1, 96792, (tempInt = STACKTOP, STACKTOP = STACKTOP + 32 | 0, HEAPF64[tempInt >> 3] = $sub30, HEAPF64[tempInt + 8 >> 3] = $sub35, HEAPF64[tempInt + 16 >> 3] = $12, HEAPF64[tempInt + 24 >> 3] = $sub40, tempInt) | 0);
+ label = 11;
+ break;
+ case 11:
+ $call41 = _gvputs($1, 96360) | 0;
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _XML_SetElementHandler($parser, $start, $end) {
+ $parser = $parser | 0;
+ $start = $start | 0;
+ $end = $end | 0;
+ HEAP32[$parser + 52 >> 2] = $start;
+ HEAP32[$parser + 56 >> 2] = $end;
+ return;
+}
+function _XML_SetCharacterDataHandler($parser, $handler) {
+ $parser = $parser | 0;
+ $handler = $handler | 0;
+ HEAP32[$parser + 60 >> 2] = $handler;
+ return;
+}
+function _errorProcessor($parser, $s, $end, $nextPtr) {
+ $parser = $parser | 0;
+ $s = $s | 0;
+ $end = $end | 0;
+ $nextPtr = $nextPtr | 0;
+ return HEAP32[$parser + 268 >> 2] | 0;
+}
+function _setContext($parser, $context) {
+ $parser = $parser | 0;
+ $context = $context | 0;
+ var $m_dtd = 0, $0 = 0, $1 = 0, $cmp6467 = 0, $m_tempPool34 = 0, $ptr35 = 0, $end145 = 0, $start37 = 0, $defaultPrefix = 0, $end92 = 0, $m_inheritedBindings = 0, $end45 = 0, $prefixes = 0, $pool = 0, $ptr = 0, $end = 0, $m_tempPool = 0, $generalEntities = 0, $start = 0, $s_0_ph69 = 0, $s_065 = 0, $2 = 0, $3 = 0, $4 = 0, $cmp9 = 0, $call = 0, $tobool = 0, $5 = 0, $incdec_ptr = 0, $6 = 0, $call16 = 0, $tobool17 = 0, $open = 0, $7 = 0, $8 = 0, $cmp21 = 0, $incdec_ptr24 = 0, $s_0_incdec_ptr24 = 0, $9 = 0, $context_addr_0_ph_be = 0, $10 = 0, $cmp64 = 0, $cmp31 = 0, $11 = 0, $12 = 0, $cmp38 = 0, $13 = 0, $cmp46 = 0, $call50 = 0, $tobool51 = 0, $14 = 0, $incdec_ptr56 = 0, $15 = 0, $call61 = 0, $16 = 0, $tobool62 = 0, $name = 0, $17 = 0, $18 = 0, $cmp67 = 0, $call71 = 0, $tobool74 = 0, $19 = 0, $prefix_0 = 0, $s_0_pn = 0, $context_addr_1 = 0, $20 = 0, $21 = 0, $22 = 0, $cmp93 = 0, $call97 = 0, $tobool98 = 0, $23 = 0, $24 = 0, $incdec_ptr103 = 0, $call115 = 0, $tobool116 = 0, $25 = 0, $incdec_ptr121 = 0, $26 = 0, $call126 = 0, $cmp127 = 0, $27 = 0, $28 = 0, $cmp136 = 0, $incdec_ptr139 = 0, $context_addr_1_incdec_ptr139 = 0, $29 = 0, $cmp146 = 0, $call150 = 0, $tobool151 = 0, $30 = 0, $31 = 0, $incdec_ptr156 = 0, $incdec_ptr159 = 0, $32 = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $1 = HEAP8[$context] | 0;
+ $cmp6467 = $1 << 24 >> 24 == 0;
+ if ($cmp6467) {
+ $retval_0 = 1;
+ label = 32;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $m_tempPool34 = $parser + 400 | 0;
+ $ptr35 = $parser + 412 | 0;
+ $end145 = $parser + 408 | 0;
+ $start37 = $parser + 416 | 0;
+ $defaultPrefix = $0 + 132 | 0;
+ $end92 = $parser + 408 | 0;
+ $m_inheritedBindings = $parser + 356 | 0;
+ $end45 = $parser + 408 | 0;
+ $prefixes = $0 + 60 | 0;
+ $pool = $0 + 80 | 0;
+ $ptr = $parser + 412 | 0;
+ $end = $parser + 408 | 0;
+ $m_tempPool = $parser + 400 | 0;
+ $generalEntities = $0 | 0;
+ $start = $parser + 416 | 0;
+ $s_0_ph69 = $context;
+ label = 4;
+ break;
+ case 4:
+ $s_065 = $s_0_ph69;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP8[$s_065] | 0;
+ if (($2 << 24 >> 24 | 0) == 12 | ($2 << 24 >> 24 | 0) == 0) {
+ label = 6;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 6:
+ $3 = HEAP32[$ptr >> 2] | 0;
+ $4 = HEAP32[$end >> 2] | 0;
+ $cmp9 = ($3 | 0) == ($4 | 0);
+ if ($cmp9) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call = _poolGrow($m_tempPool) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $5 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $5 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$5] = 0;
+ $6 = HEAP32[$start >> 2] | 0;
+ $call16 = _lookup($parser, $generalEntities, $6, 0) | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ if ($tobool17) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $open = $call16 + 32 | 0;
+ $7 = $open;
+ HEAP8[$7] = 1;
+ label = 10;
+ break;
+ case 10:
+ $8 = HEAP8[$s_065] | 0;
+ $cmp21 = $8 << 24 >> 24 == 0;
+ $incdec_ptr24 = $s_065 + 1 | 0;
+ $s_0_incdec_ptr24 = $cmp21 ? $s_065 : $incdec_ptr24;
+ $9 = HEAP32[$start >> 2] | 0;
+ HEAP32[$ptr >> 2] = $9;
+ $context_addr_0_ph_be = $s_0_incdec_ptr24;
+ label = 11;
+ break;
+ case 11:
+ $10 = HEAP8[$context_addr_0_ph_be] | 0;
+ $cmp64 = $10 << 24 >> 24 == 0;
+ if ($cmp64) {
+ $retval_0 = 1;
+ label = 32;
+ break;
+ } else {
+ $s_0_ph69 = $context_addr_0_ph_be;
+ label = 4;
+ break;
+ }
+ case 12:
+ $cmp31 = $2 << 24 >> 24 == 61;
+ $11 = HEAP32[$ptr35 >> 2] | 0;
+ if ($cmp31) {
+ label = 13;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 13:
+ $12 = HEAP32[$start37 >> 2] | 0;
+ $cmp38 = ($11 | 0) == ($12 | 0);
+ if ($cmp38) {
+ $prefix_0 = $defaultPrefix;
+ label = 20;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $13 = HEAP32[$end45 >> 2] | 0;
+ $cmp46 = ($11 | 0) == ($13 | 0);
+ if ($cmp46) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $call50 = _poolGrow($m_tempPool34) | 0;
+ $tobool51 = $call50 << 24 >> 24 == 0;
+ if ($tobool51) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $14 = HEAP32[$ptr35 >> 2] | 0;
+ $incdec_ptr56 = $14 + 1 | 0;
+ HEAP32[$ptr35 >> 2] = $incdec_ptr56;
+ HEAP8[$14] = 0;
+ $15 = HEAP32[$start37 >> 2] | 0;
+ $call61 = _lookup($parser, $prefixes, $15, 8) | 0;
+ $16 = $call61;
+ $tobool62 = ($call61 | 0) == 0;
+ if ($tobool62) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $name = $call61 | 0;
+ $17 = HEAP32[$name >> 2] | 0;
+ $18 = HEAP32[$start37 >> 2] | 0;
+ $cmp67 = ($17 | 0) == ($18 | 0);
+ if ($cmp67) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $call71 = _poolCopyString($pool, $17) | 0;
+ HEAP32[$name >> 2] = $call71;
+ $tobool74 = ($call71 | 0) == 0;
+ if ($tobool74) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $19 = HEAP32[$start37 >> 2] | 0;
+ HEAP32[$ptr35 >> 2] = $19;
+ $prefix_0 = $16;
+ label = 20;
+ break;
+ case 20:
+ $s_0_pn = $s_065;
+ label = 21;
+ break;
+ case 21:
+ $context_addr_1 = $s_0_pn + 1 | 0;
+ $20 = HEAP8[$context_addr_1] | 0;
+ $21 = HEAP32[$ptr35 >> 2] | 0;
+ $22 = HEAP32[$end92 >> 2] | 0;
+ $cmp93 = ($21 | 0) == ($22 | 0);
+ if (($20 << 24 >> 24 | 0) == 12 | ($20 << 24 >> 24 | 0) == 0) {
+ label = 25;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ if ($cmp93) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ $call97 = _poolGrow($m_tempPool34) | 0;
+ $tobool98 = $call97 << 24 >> 24 == 0;
+ if ($tobool98) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $23 = HEAP8[$context_addr_1] | 0;
+ $24 = HEAP32[$ptr35 >> 2] | 0;
+ $incdec_ptr103 = $24 + 1 | 0;
+ HEAP32[$ptr35 >> 2] = $incdec_ptr103;
+ HEAP8[$24] = $23;
+ $s_0_pn = $context_addr_1;
+ label = 21;
+ break;
+ case 25:
+ if ($cmp93) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $call115 = _poolGrow($m_tempPool34) | 0;
+ $tobool116 = $call115 << 24 >> 24 == 0;
+ if ($tobool116) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $25 = HEAP32[$ptr35 >> 2] | 0;
+ $incdec_ptr121 = $25 + 1 | 0;
+ HEAP32[$ptr35 >> 2] = $incdec_ptr121;
+ HEAP8[$25] = 0;
+ $26 = HEAP32[$start37 >> 2] | 0;
+ $call126 = _addBinding($parser, $prefix_0, 0, $26, $m_inheritedBindings) | 0;
+ $cmp127 = ($call126 | 0) == 0;
+ if ($cmp127) {
+ label = 28;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ }
+ case 28:
+ $27 = HEAP32[$start37 >> 2] | 0;
+ HEAP32[$ptr35 >> 2] = $27;
+ $28 = HEAP8[$context_addr_1] | 0;
+ $cmp136 = $28 << 24 >> 24 == 0;
+ $incdec_ptr139 = $s_0_pn + 2 | 0;
+ $context_addr_1_incdec_ptr139 = $cmp136 ? $context_addr_1 : $incdec_ptr139;
+ $context_addr_0_ph_be = $context_addr_1_incdec_ptr139;
+ label = 11;
+ break;
+ case 29:
+ $29 = HEAP32[$end145 >> 2] | 0;
+ $cmp146 = ($11 | 0) == ($29 | 0);
+ if ($cmp146) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $call150 = _poolGrow($m_tempPool34) | 0;
+ $tobool151 = $call150 << 24 >> 24 == 0;
+ if ($tobool151) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $30 = HEAP8[$s_065] | 0;
+ $31 = HEAP32[$ptr35 >> 2] | 0;
+ $incdec_ptr156 = $31 + 1 | 0;
+ HEAP32[$ptr35 >> 2] = $incdec_ptr156;
+ HEAP8[$31] = $30;
+ $incdec_ptr159 = $s_065 + 1 | 0;
+ $32 = HEAP8[$s_0_ph69] | 0;
+ $cmp = $32 << 24 >> 24 == 0;
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 32;
+ break;
+ } else {
+ $s_065 = $incdec_ptr159;
+ label = 5;
+ break;
+ }
+ case 32:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _XML_ParserFree($parser) {
+ $parser = $parser | 0;
+ var $cmp = 0, $m_tagStack = 0, $0 = 0, $m_freeTagList = 0, $free_fcn = 0, $tagList_0 = 0, $cmp1 = 0, $1 = 0, $cmp3 = 0, $tagList_1 = 0, $parent = 0, $2 = 0, $3 = 0, $buf = 0, $4 = 0, $bindings = 0, $5 = 0, $6 = 0, $7 = 0, $m_openInternalEntities = 0, $8 = 0, $m_freeInternalEntities = 0, $free_fcn21 = 0, $entityList_0 = 0, $cmp12 = 0, $9 = 0, $cmp14 = 0, $entityList_1 = 0, $next = 0, $10 = 0, $11 = 0, $12 = 0, $m_freeBindingList = 0, $13 = 0, $m_inheritedBindings = 0, $14 = 0, $m_tempPool = 0, $m_temp2Pool = 0, $m_dtd = 0, $15 = 0, $tobool = 0, $m_parentParser = 0, $16 = 0, $lnot = 0, $conv = 0, $m_mem26 = 0, $free_fcn29 = 0, $17 = 0, $m_atts = 0, $18 = 0, $19 = 0, $20 = 0, $m_groupConnector = 0, $21 = 0, $22 = 0, $m_buffer = 0, $23 = 0, $24 = 0, $m_dataBuf = 0, $25 = 0, $26 = 0, $m_nsAtts = 0, $27 = 0, $28 = 0, $29 = 0, $m_unknownEncodingMem = 0, $30 = 0, $m_unknownEncodingRelease = 0, $31 = 0, $tobool40 = 0, $m_unknownEncodingData = 0, $32 = 0, $33 = 0, $34 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($parser | 0) == 0;
+ if ($cmp) {
+ label = 18;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $m_tagStack = $parser + 348 | 0;
+ $0 = HEAP32[$m_tagStack >> 2] | 0;
+ $m_freeTagList = $parser + 352 | 0;
+ $free_fcn = $parser + 20 | 0;
+ $tagList_0 = $0;
+ label = 4;
+ break;
+ case 4:
+ $cmp1 = ($tagList_0 | 0) == 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ $tagList_1 = $tagList_0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $1 = HEAP32[$m_freeTagList >> 2] | 0;
+ $cmp3 = ($1 | 0) == 0;
+ if ($cmp3) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ HEAP32[$m_freeTagList >> 2] = 0;
+ $tagList_1 = $1;
+ label = 7;
+ break;
+ case 7:
+ $parent = $tagList_1 | 0;
+ $2 = HEAP32[$parent >> 2] | 0;
+ $3 = HEAP32[$free_fcn >> 2] | 0;
+ $buf = $tagList_1 + 36 | 0;
+ $4 = HEAP32[$buf >> 2] | 0;
+ FUNCTION_TABLE_vi[$3 & 1023]($4);
+ $bindings = $tagList_1 + 44 | 0;
+ $5 = HEAP32[$bindings >> 2] | 0;
+ _destroyBindings($5, $parser);
+ $6 = HEAP32[$free_fcn >> 2] | 0;
+ $7 = $tagList_1;
+ FUNCTION_TABLE_vi[$6 & 1023]($7);
+ $tagList_0 = $2;
+ label = 4;
+ break;
+ case 8:
+ $m_openInternalEntities = $parser + 284 | 0;
+ $8 = HEAP32[$m_openInternalEntities >> 2] | 0;
+ $m_freeInternalEntities = $parser + 288 | 0;
+ $free_fcn21 = $parser + 20 | 0;
+ $entityList_0 = $8;
+ label = 9;
+ break;
+ case 9:
+ $cmp12 = ($entityList_0 | 0) == 0;
+ if ($cmp12) {
+ label = 10;
+ break;
+ } else {
+ $entityList_1 = $entityList_0;
+ label = 12;
+ break;
+ }
+ case 10:
+ $9 = HEAP32[$m_freeInternalEntities >> 2] | 0;
+ $cmp14 = ($9 | 0) == 0;
+ if ($cmp14) {
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ HEAP32[$m_freeInternalEntities >> 2] = 0;
+ $entityList_1 = $9;
+ label = 12;
+ break;
+ case 12:
+ $next = $entityList_1 + 8 | 0;
+ $10 = HEAP32[$next >> 2] | 0;
+ $11 = HEAP32[$free_fcn21 >> 2] | 0;
+ $12 = $entityList_1;
+ FUNCTION_TABLE_vi[$11 & 1023]($12);
+ $entityList_0 = $10;
+ label = 9;
+ break;
+ case 13:
+ $m_freeBindingList = $parser + 360 | 0;
+ $13 = HEAP32[$m_freeBindingList >> 2] | 0;
+ _destroyBindings($13, $parser);
+ $m_inheritedBindings = $parser + 356 | 0;
+ $14 = HEAP32[$m_inheritedBindings >> 2] | 0;
+ _destroyBindings($14, $parser);
+ $m_tempPool = $parser + 400 | 0;
+ _poolDestroy($m_tempPool);
+ $m_temp2Pool = $parser + 424 | 0;
+ _poolDestroy($m_temp2Pool);
+ $m_dtd = $parser + 340 | 0;
+ $15 = HEAP32[$m_dtd >> 2] | 0;
+ $tobool = ($15 | 0) == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $m_parentParser = $parser + 460 | 0;
+ $16 = HEAP32[$m_parentParser >> 2] | 0;
+ $lnot = ($16 | 0) == 0;
+ $conv = $lnot & 1;
+ $m_mem26 = $parser + 12 | 0;
+ _dtdDestroy($15, $conv, $m_mem26);
+ label = 15;
+ break;
+ case 15:
+ $free_fcn29 = $parser + 20 | 0;
+ $17 = HEAP32[$free_fcn29 >> 2] | 0;
+ $m_atts = $parser + 376 | 0;
+ $18 = HEAP32[$m_atts >> 2] | 0;
+ $19 = $18;
+ FUNCTION_TABLE_vi[$17 & 1023]($19);
+ $20 = HEAP32[$free_fcn29 >> 2] | 0;
+ $m_groupConnector = $parser + 448 | 0;
+ $21 = HEAP32[$m_groupConnector >> 2] | 0;
+ FUNCTION_TABLE_vi[$20 & 1023]($21);
+ $22 = HEAP32[$free_fcn29 >> 2] | 0;
+ $m_buffer = $parser + 8 | 0;
+ $23 = HEAP32[$m_buffer >> 2] | 0;
+ FUNCTION_TABLE_vi[$22 & 1023]($23);
+ $24 = HEAP32[$free_fcn29 >> 2] | 0;
+ $m_dataBuf = $parser + 44 | 0;
+ $25 = HEAP32[$m_dataBuf >> 2] | 0;
+ FUNCTION_TABLE_vi[$24 & 1023]($25);
+ $26 = HEAP32[$free_fcn29 >> 2] | 0;
+ $m_nsAtts = $parser + 380 | 0;
+ $27 = HEAP32[$m_nsAtts >> 2] | 0;
+ $28 = $27;
+ FUNCTION_TABLE_vi[$26 & 1023]($28);
+ $29 = HEAP32[$free_fcn29 >> 2] | 0;
+ $m_unknownEncodingMem = $parser + 236 | 0;
+ $30 = HEAP32[$m_unknownEncodingMem >> 2] | 0;
+ FUNCTION_TABLE_vi[$29 & 1023]($30);
+ $m_unknownEncodingRelease = $parser + 248 | 0;
+ $31 = HEAP32[$m_unknownEncodingRelease >> 2] | 0;
+ $tobool40 = ($31 | 0) == 0;
+ if ($tobool40) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $m_unknownEncodingData = $parser + 240 | 0;
+ $32 = HEAP32[$m_unknownEncodingData >> 2] | 0;
+ FUNCTION_TABLE_vi[$31 & 1023]($32);
+ label = 17;
+ break;
+ case 17:
+ $33 = HEAP32[$free_fcn29 >> 2] | 0;
+ $34 = $parser;
+ FUNCTION_TABLE_vi[$33 & 1023]($34);
+ label = 18;
+ break;
+ case 18:
+ return;
+ }
+}
+function _destroyBindings($bindings, $parser) {
+ $bindings = $bindings | 0;
+ $parser = $parser | 0;
+ var $tobool5 = 0, $free_fcn = 0, $bindings_addr_06 = 0, $nextTagBinding = 0, $0 = 0, $1 = 0, $uri = 0, $2 = 0, $3 = 0, $4 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool5 = ($bindings | 0) == 0;
+ if ($tobool5) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $free_fcn = $parser + 20 | 0;
+ $bindings_addr_06 = $bindings;
+ label = 4;
+ break;
+ case 4:
+ $nextTagBinding = $bindings_addr_06 + 4 | 0;
+ $0 = HEAP32[$nextTagBinding >> 2] | 0;
+ $1 = HEAP32[$free_fcn >> 2] | 0;
+ $uri = $bindings_addr_06 + 16 | 0;
+ $2 = HEAP32[$uri >> 2] | 0;
+ FUNCTION_TABLE_vi[$1 & 1023]($2);
+ $3 = HEAP32[$free_fcn >> 2] | 0;
+ $4 = $bindings_addr_06;
+ FUNCTION_TABLE_vi[$3 & 1023]($4);
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $bindings_addr_06 = $0;
+ label = 4;
+ break;
+ }
+ case 5:
+ return;
+ }
+}
+function _poolDestroy($pool) {
+ $pool = $pool | 0;
+ var $blocks = 0, $0 = 0, $tobool11 = 0, $mem = 0, $p_012 = 0, $next = 0, $1 = 0, $2 = 0, $free_fcn = 0, $3 = 0, $4 = 0, $tobool = 0, $freeBlocks = 0, $5 = 0, $tobool29 = 0, $mem6 = 0, $p_110 = 0, $next5 = 0, $6 = 0, $7 = 0, $free_fcn7 = 0, $8 = 0, $9 = 0, $tobool2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $blocks = $pool | 0;
+ $0 = HEAP32[$blocks >> 2] | 0;
+ $tobool11 = ($0 | 0) == 0;
+ if ($tobool11) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $mem = $pool + 20 | 0;
+ $p_012 = $0;
+ label = 4;
+ break;
+ case 4:
+ $next = $p_012 | 0;
+ $1 = HEAP32[$next >> 2] | 0;
+ $2 = HEAP32[$mem >> 2] | 0;
+ $free_fcn = $2 + 8 | 0;
+ $3 = HEAP32[$free_fcn >> 2] | 0;
+ $4 = $p_012;
+ FUNCTION_TABLE_vi[$3 & 1023]($4);
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $p_012 = $1;
+ label = 4;
+ break;
+ }
+ case 5:
+ $freeBlocks = $pool + 4 | 0;
+ $5 = HEAP32[$freeBlocks >> 2] | 0;
+ $tobool29 = ($5 | 0) == 0;
+ if ($tobool29) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $mem6 = $pool + 20 | 0;
+ $p_110 = $5;
+ label = 7;
+ break;
+ case 7:
+ $next5 = $p_110 | 0;
+ $6 = HEAP32[$next5 >> 2] | 0;
+ $7 = HEAP32[$mem6 >> 2] | 0;
+ $free_fcn7 = $7 + 8 | 0;
+ $8 = HEAP32[$free_fcn7 >> 2] | 0;
+ $9 = $p_110;
+ FUNCTION_TABLE_vi[$8 & 1023]($9);
+ $tobool2 = ($6 | 0) == 0;
+ if ($tobool2) {
+ label = 8;
+ break;
+ } else {
+ $p_110 = $6;
+ label = 7;
+ break;
+ }
+ case 8:
+ return;
+ }
+}
+function _dtdDestroy($p, $isDocEntity, $ms) {
+ $p = $p | 0;
+ $isDocEntity = $isDocEntity | 0;
+ $ms = $ms | 0;
+ var $iter = 0, $elementTypes = 0, $call15 = 0, $tobool16 = 0, $free_fcn = 0, $call17 = 0, $allocDefaultAtts = 0, $0 = 0, $1 = 0, $cmp = 0, $2 = 0, $defaultAtts = 0, $3 = 0, $4 = 0, $5 = 0, $call = 0, $tobool = 0, $generalEntities = 0, $attributeIds = 0, $prefixes = 0, $pool = 0, $entityValuePool = 0, $tobool4 = 0, $free_fcn6 = 0, $6 = 0, $scaffIndex = 0, $7 = 0, $8 = 0, $9 = 0, $scaffold = 0, $10 = 0, $11 = 0, $free_fcn9 = 0, $12 = 0, $13 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $iter = __stackBase__ | 0;
+ $elementTypes = $p + 20 | 0;
+ _hashTableIterInit($iter, $elementTypes);
+ $call15 = _hashTableIterNext($iter) | 0;
+ $tobool16 = ($call15 | 0) == 0;
+ if ($tobool16) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $free_fcn = $ms + 8 | 0;
+ $call17 = $call15;
+ label = 4;
+ break;
+ case 4:
+ $allocDefaultAtts = $call17 + 16 | 0;
+ $0 = $allocDefaultAtts;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP32[$free_fcn >> 2] | 0;
+ $defaultAtts = $call17 + 20 | 0;
+ $3 = $defaultAtts;
+ $4 = HEAP32[$3 >> 2] | 0;
+ $5 = $4;
+ FUNCTION_TABLE_vi[$2 & 1023]($5);
+ label = 6;
+ break;
+ case 6:
+ $call = _hashTableIterNext($iter) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $call17 = $call;
+ label = 4;
+ break;
+ }
+ case 7:
+ $generalEntities = $p | 0;
+ _hashTableDestroy($generalEntities);
+ _hashTableDestroy($elementTypes);
+ $attributeIds = $p + 40 | 0;
+ _hashTableDestroy($attributeIds);
+ $prefixes = $p + 60 | 0;
+ _hashTableDestroy($prefixes);
+ $pool = $p + 80 | 0;
+ _poolDestroy($pool);
+ $entityValuePool = $p + 104 | 0;
+ _poolDestroy($entityValuePool);
+ $tobool4 = $isDocEntity << 24 >> 24 == 0;
+ if ($tobool4) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $free_fcn6 = $ms + 8 | 0;
+ $6 = HEAP32[$free_fcn6 >> 2] | 0;
+ $scaffIndex = $p + 164 | 0;
+ $7 = HEAP32[$scaffIndex >> 2] | 0;
+ $8 = $7;
+ FUNCTION_TABLE_vi[$6 & 1023]($8);
+ $9 = HEAP32[$free_fcn6 >> 2] | 0;
+ $scaffold = $p + 144 | 0;
+ $10 = HEAP32[$scaffold >> 2] | 0;
+ $11 = $10;
+ FUNCTION_TABLE_vi[$9 & 1023]($11);
+ label = 9;
+ break;
+ case 9:
+ $free_fcn9 = $ms + 8 | 0;
+ $12 = HEAP32[$free_fcn9 >> 2] | 0;
+ $13 = $p;
+ FUNCTION_TABLE_vi[$12 & 1023]($13);
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _XML_Parse($parser, $s, $len, $isFinal) {
+ $parser = $parser | 0;
+ $s = $s | 0;
+ $len = $len | 0;
+ $isFinal = $isFinal | 0;
+ var $end = 0, $parsing = 0, $0 = 0, $m_errorCode = 0, $m_errorCode2 = 0, $m_parentParser = 0, $1 = 0, $cmp = 0, $call = 0, $tobool = 0, $m_errorCode4 = 0, $cmp7 = 0, $conv = 0, $finalBuffer = 0, $tobool10 = 0, $m_bufferPtr = 0, $2 = 0, $m_positionPtr = 0, $m_bufferEnd = 0, $3 = 0, $m_parseEndPtr = 0, $m_processor = 0, $4 = 0, $5 = 0, $call16 = 0, $m_errorCode17 = 0, $cmp19 = 0, $6 = 0, $m_encoding = 0, $7 = 0, $updatePosition = 0, $8 = 0, $9 = 0, $10 = 0, $m_position = 0, $11 = 0, $m_eventPtr = 0, $12 = 0, $m_eventEndPtr = 0, $m_bufferPtr36 = 0, $13 = 0, $m_bufferEnd37 = 0, $14 = 0, $cmp38 = 0, $m_parseEndByteIndex = 0, $15 = 0, $add = 0, $m_positionPtr41 = 0, $conv42 = 0, $finalBuffer44 = 0, $m_processor45 = 0, $16 = 0, $add_ptr = 0, $m_parseEndPtr46 = 0, $call47 = 0, $m_errorCode48 = 0, $cmp50 = 0, $m_eventPtr53 = 0, $17 = 0, $m_eventEndPtr54 = 0, $18 = 0, $tobool61 = 0, $result_0 = 0, $m_encoding69 = 0, $19 = 0, $updatePosition70 = 0, $20 = 0, $21 = 0, $22 = 0, $m_position73 = 0, $23 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $tobool75 = 0, $m_buffer = 0, $24 = 0, $cmp77 = 0, $m_bufferLim = 0, $25 = 0, $sub_ptr_lhs_cast80 = 0, $sub_ptr_rhs_cast81 = 0, $sub_ptr_sub82 = 0, $cmp83 = 0, $_pr = 0, $cmp87 = 0, $malloc_fcn = 0, $26 = 0, $mul = 0, $call89 = 0, $realloc_fcn = 0, $27 = 0, $mul92 = 0, $call93 = 0, $cond = 0, $cmp94 = 0, $m_eventEndPtr98 = 0, $m_eventPtr99 = 0, $mul104 = 0, $add_ptr105 = 0, $m_bufferLim106 = 0, $28 = 0, $29 = 0, $m_buffer110 = 0, $30 = 0, $31 = 0, $add_ptr113 = 0, $32 = 0, $33 = 0, $34 = 0, $m_eventPtr120 = 0, $35 = 0, $m_eventEndPtr122 = 0, $call124 = 0, $cmp125 = 0, $call129 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $end = __stackBase__ | 0;
+ $parsing = $parser + 464 | 0;
+ $0 = HEAP32[$parsing >> 2] | 0;
+ if (($0 | 0) == 3) {
+ label = 3;
+ break;
+ } else if (($0 | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($0 | 0) == 0) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $m_errorCode = $parser + 268 | 0;
+ HEAP32[$m_errorCode >> 2] = 33;
+ $retval_0 = 0;
+ label = 35;
+ break;
+ case 4:
+ $m_errorCode2 = $parser + 268 | 0;
+ HEAP32[$m_errorCode2 >> 2] = 36;
+ $retval_0 = 0;
+ label = 35;
+ break;
+ case 5:
+ $m_parentParser = $parser + 460 | 0;
+ $1 = HEAP32[$m_parentParser >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $call = _startParsing($parser) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $m_errorCode4 = $parser + 268 | 0;
+ HEAP32[$m_errorCode4 >> 2] = 1;
+ $retval_0 = 0;
+ label = 35;
+ break;
+ case 8:
+ HEAP32[$parsing >> 2] = 1;
+ $cmp7 = ($len | 0) == 0;
+ if ($cmp7) {
+ label = 9;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 9:
+ $conv = $isFinal & 255;
+ $finalBuffer = $parser + 468 | 0;
+ HEAP8[$finalBuffer] = $conv;
+ $tobool10 = ($isFinal | 0) == 0;
+ if ($tobool10) {
+ $retval_0 = 1;
+ label = 35;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $m_bufferPtr = $parser + 24 | 0;
+ $2 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $m_positionPtr = $parser + 280 | 0;
+ HEAP32[$m_positionPtr >> 2] = $2;
+ $m_bufferEnd = $parser + 28 | 0;
+ $3 = HEAP32[$m_bufferEnd >> 2] | 0;
+ $m_parseEndPtr = $parser + 40 | 0;
+ HEAP32[$m_parseEndPtr >> 2] = $3;
+ $m_processor = $parser + 264 | 0;
+ $4 = HEAP32[$m_processor >> 2] | 0;
+ $5 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $call16 = FUNCTION_TABLE_iiiii[$4 & 1023]($parser, $5, $3, $m_bufferPtr) | 0;
+ $m_errorCode17 = $parser + 268 | 0;
+ HEAP32[$m_errorCode17 >> 2] = $call16;
+ $cmp19 = ($call16 | 0) == 0;
+ if ($cmp19) {
+ label = 11;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 11:
+ $6 = HEAP32[$parsing >> 2] | 0;
+ if (($6 | 0) == 3) {
+ label = 12;
+ break;
+ } else if (($6 | 0) == 0 | ($6 | 0) == 1) {
+ label = 13;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 35;
+ break;
+ }
+ case 12:
+ $m_encoding = $parser + 144 | 0;
+ $7 = HEAP32[$m_encoding >> 2] | 0;
+ $updatePosition = $7 + 48 | 0;
+ $8 = HEAP32[$updatePosition >> 2] | 0;
+ $9 = HEAP32[$m_positionPtr >> 2] | 0;
+ $10 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $m_position = $parser + 392 | 0;
+ FUNCTION_TABLE_viiii[$8 & 1023]($7, $9, $10, $m_position);
+ $11 = HEAP32[$m_bufferPtr >> 2] | 0;
+ HEAP32[$m_positionPtr >> 2] = $11;
+ $retval_0 = 2;
+ label = 35;
+ break;
+ case 13:
+ HEAP32[$parsing >> 2] = 2;
+ $retval_0 = 1;
+ label = 35;
+ break;
+ case 14:
+ $m_eventPtr = $parser + 272 | 0;
+ $12 = HEAP32[$m_eventPtr >> 2] | 0;
+ $m_eventEndPtr = $parser + 276 | 0;
+ HEAP32[$m_eventEndPtr >> 2] = $12;
+ HEAP32[$m_processor >> 2] = 448;
+ $retval_0 = 0;
+ label = 35;
+ break;
+ case 15:
+ $m_bufferPtr36 = $parser + 24 | 0;
+ $13 = HEAP32[$m_bufferPtr36 >> 2] | 0;
+ $m_bufferEnd37 = $parser + 28 | 0;
+ $14 = HEAP32[$m_bufferEnd37 >> 2] | 0;
+ $cmp38 = ($13 | 0) == ($14 | 0);
+ if ($cmp38) {
+ label = 16;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 16:
+ $m_parseEndByteIndex = $parser + 36 | 0;
+ $15 = HEAP32[$m_parseEndByteIndex >> 2] | 0;
+ $add = $15 + $len | 0;
+ HEAP32[$m_parseEndByteIndex >> 2] = $add;
+ $m_positionPtr41 = $parser + 280 | 0;
+ HEAP32[$m_positionPtr41 >> 2] = $s;
+ $conv42 = $isFinal & 255;
+ $finalBuffer44 = $parser + 468 | 0;
+ HEAP8[$finalBuffer44] = $conv42;
+ $m_processor45 = $parser + 264 | 0;
+ $16 = HEAP32[$m_processor45 >> 2] | 0;
+ $add_ptr = $s + $len | 0;
+ $m_parseEndPtr46 = $parser + 40 | 0;
+ HEAP32[$m_parseEndPtr46 >> 2] = $add_ptr;
+ $call47 = FUNCTION_TABLE_iiiii[$16 & 1023]($parser, $s, $add_ptr, $end) | 0;
+ $m_errorCode48 = $parser + 268 | 0;
+ HEAP32[$m_errorCode48 >> 2] = $call47;
+ $cmp50 = ($call47 | 0) == 0;
+ if ($cmp50) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $m_eventPtr53 = $parser + 272 | 0;
+ $17 = HEAP32[$m_eventPtr53 >> 2] | 0;
+ $m_eventEndPtr54 = $parser + 276 | 0;
+ HEAP32[$m_eventEndPtr54 >> 2] = $17;
+ HEAP32[$m_processor45 >> 2] = 448;
+ $retval_0 = 0;
+ label = 35;
+ break;
+ case 18:
+ $18 = HEAP32[$parsing >> 2] | 0;
+ if (($18 | 0) == 0 | ($18 | 0) == 1) {
+ label = 19;
+ break;
+ } else if (($18 | 0) == 3) {
+ $result_0 = 2;
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 19:
+ $tobool61 = ($isFinal | 0) == 0;
+ if ($tobool61) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ HEAP32[$parsing >> 2] = 2;
+ $retval_0 = 1;
+ label = 35;
+ break;
+ case 21:
+ $result_0 = 1;
+ label = 22;
+ break;
+ case 22:
+ $m_encoding69 = $parser + 144 | 0;
+ $19 = HEAP32[$m_encoding69 >> 2] | 0;
+ $updatePosition70 = $19 + 48 | 0;
+ $20 = HEAP32[$updatePosition70 >> 2] | 0;
+ $21 = HEAP32[$m_positionPtr41 >> 2] | 0;
+ $22 = HEAP32[$end >> 2] | 0;
+ $m_position73 = $parser + 392 | 0;
+ FUNCTION_TABLE_viiii[$20 & 1023]($19, $21, $22, $m_position73);
+ $23 = HEAP32[$end >> 2] | 0;
+ $sub_ptr_lhs_cast = $add_ptr;
+ $sub_ptr_rhs_cast = $23;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $tobool75 = ($add_ptr | 0) == ($23 | 0);
+ if ($tobool75) {
+ label = 32;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $m_buffer = $parser + 8 | 0;
+ $24 = HEAP32[$m_buffer >> 2] | 0;
+ $cmp77 = ($24 | 0) == 0;
+ if ($cmp77) {
+ label = 26;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $m_bufferLim = $parser + 32 | 0;
+ $25 = HEAP32[$m_bufferLim >> 2] | 0;
+ $sub_ptr_lhs_cast80 = $25;
+ $sub_ptr_rhs_cast81 = $24;
+ $sub_ptr_sub82 = $sub_ptr_lhs_cast80 - $sub_ptr_rhs_cast81 | 0;
+ $cmp83 = ($sub_ptr_sub | 0) > ($sub_ptr_sub82 | 0);
+ if ($cmp83) {
+ label = 25;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 25:
+ $_pr = HEAP32[$m_buffer >> 2] | 0;
+ $cmp87 = ($_pr | 0) == 0;
+ if ($cmp87) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $malloc_fcn = $parser + 12 | 0;
+ $26 = HEAP32[$malloc_fcn >> 2] | 0;
+ $mul = $len << 1;
+ $call89 = FUNCTION_TABLE_ii[$26 & 1023]($mul) | 0;
+ $cond = $call89;
+ label = 28;
+ break;
+ case 27:
+ $realloc_fcn = $parser + 16 | 0;
+ $27 = HEAP32[$realloc_fcn >> 2] | 0;
+ $mul92 = $len << 1;
+ $call93 = FUNCTION_TABLE_iii[$27 & 1023]($_pr, $mul92) | 0;
+ $cond = $call93;
+ label = 28;
+ break;
+ case 28:
+ $cmp94 = ($cond | 0) == 0;
+ if ($cmp94) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ HEAP32[$m_errorCode48 >> 2] = 1;
+ $m_eventEndPtr98 = $parser + 276 | 0;
+ HEAP32[$m_eventEndPtr98 >> 2] = 0;
+ $m_eventPtr99 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr99 >> 2] = 0;
+ HEAP32[$m_processor45 >> 2] = 448;
+ $retval_0 = 0;
+ label = 35;
+ break;
+ case 30:
+ HEAP32[$m_buffer >> 2] = $cond;
+ $mul104 = $len << 1;
+ $add_ptr105 = $cond + $mul104 | 0;
+ $m_bufferLim106 = $parser + 32 | 0;
+ HEAP32[$m_bufferLim106 >> 2] = $add_ptr105;
+ label = 31;
+ break;
+ case 31:
+ $28 = HEAP32[$m_buffer >> 2] | 0;
+ $29 = HEAP32[$end >> 2] | 0;
+ _memcpy($28 | 0, $29 | 0, $sub_ptr_sub);
+ label = 32;
+ break;
+ case 32:
+ $m_buffer110 = $parser + 8 | 0;
+ $30 = HEAP32[$m_buffer110 >> 2] | 0;
+ HEAP32[$m_bufferPtr36 >> 2] = $30;
+ $31 = HEAP32[$m_buffer110 >> 2] | 0;
+ $add_ptr113 = $31 + $sub_ptr_sub | 0;
+ HEAP32[$m_bufferEnd37 >> 2] = $add_ptr113;
+ $32 = HEAP32[$m_bufferPtr36 >> 2] | 0;
+ HEAP32[$m_positionPtr41 >> 2] = $32;
+ $33 = HEAP32[$m_bufferEnd37 >> 2] | 0;
+ HEAP32[$m_parseEndPtr46 >> 2] = $33;
+ $34 = HEAP32[$m_bufferPtr36 >> 2] | 0;
+ $m_eventPtr120 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr120 >> 2] = $34;
+ $35 = HEAP32[$m_bufferPtr36 >> 2] | 0;
+ $m_eventEndPtr122 = $parser + 276 | 0;
+ HEAP32[$m_eventEndPtr122 >> 2] = $35;
+ $retval_0 = $result_0;
+ label = 35;
+ break;
+ case 33:
+ $call124 = _XML_GetBuffer($parser, $len) | 0;
+ $cmp125 = ($call124 | 0) == 0;
+ if ($cmp125) {
+ $retval_0 = 0;
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ _memcpy($call124 | 0, $s | 0, $len);
+ $call129 = _XML_ParseBuffer($parser, $len, $isFinal) | 0;
+ $retval_0 = $call129;
+ label = 35;
+ break;
+ case 35:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _startParsing($parser) {
+ $parser = $parser | 0;
+ var $m_hash_secret_salt = 0, $0 = 0, $cmp = 0, $call = 0, $m_ns = 0, $1 = 0, $tobool = 0, $call3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_hash_secret_salt = $parser + 472 | 0;
+ $0 = HEAP32[$m_hash_secret_salt >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _generate_hash_secret_salt() | 0;
+ HEAP32[$m_hash_secret_salt >> 2] = $call;
+ label = 4;
+ break;
+ case 4:
+ $m_ns = $parser + 232 | 0;
+ $1 = HEAP8[$m_ns] | 0;
+ $tobool = $1 << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call3 = _setContext($parser, 12776) | 0;
+ $retval_0 = $call3;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _XML_GetBuffer($parser, $len) {
+ $parser = $parser | 0;
+ $len = $len | 0;
+ var $parsing = 0, $0 = 0, $m_errorCode = 0, $m_errorCode2 = 0, $m_bufferLim = 0, $1 = 0, $m_bufferEnd = 0, $2 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp = 0, $m_bufferPtr = 0, $3 = 0, $sub_ptr_rhs_cast5 = 0, $sub_ptr_sub6 = 0, $add = 0, $m_buffer = 0, $4 = 0, $sub_ptr_rhs_cast9 = 0, $sub_ptr_sub10 = 0, $cmp11 = 0, $5 = 0, $6 = 0, $7 = 0, $sub_ptr_lhs_cast23 = 0, $sub_ptr_rhs_cast24 = 0, $sub_ptr_sub25 = 0, $add_ptr = 0, $8 = 0, $sub_ptr_sub33 = 0, $cmp34 = 0, $_sub_ptr_sub33 = 0, $bufferSize_0 = 0, $mul = 0, $cmp36 = 0, $malloc_fcn = 0, $9 = 0, $call = 0, $cmp37 = 0, $m_errorCode39 = 0, $add_ptr41 = 0, $10 = 0, $tobool = 0, $11 = 0, $sub_ptr_lhs_cast48 = 0, $sub_ptr_rhs_cast49 = 0, $sub_ptr_sub50 = 0, $free_fcn = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $sub_ptr_lhs_cast56 = 0, $sub_ptr_rhs_cast57 = 0, $sub_ptr_sub58 = 0, $add_ptr59 = 0, $storemerge = 0, $m_eventEndPtr = 0, $m_eventPtr = 0, $m_positionPtr = 0, $16 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $parsing = $parser + 464 | 0;
+ $0 = HEAP32[$parsing >> 2] | 0;
+ if (($0 | 0) == 3) {
+ label = 3;
+ break;
+ } else if (($0 | 0) == 2) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $m_errorCode = $parser + 268 | 0;
+ HEAP32[$m_errorCode >> 2] = 33;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 4:
+ $m_errorCode2 = $parser + 268 | 0;
+ HEAP32[$m_errorCode2 >> 2] = 36;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 5:
+ $m_bufferLim = $parser + 32 | 0;
+ $1 = HEAP32[$m_bufferLim >> 2] | 0;
+ $m_bufferEnd = $parser + 28 | 0;
+ $2 = HEAP32[$m_bufferEnd >> 2] | 0;
+ $sub_ptr_lhs_cast = $1;
+ $sub_ptr_rhs_cast = $2;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp = ($sub_ptr_sub | 0) < ($len | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 6:
+ $m_bufferPtr = $parser + 24 | 0;
+ $3 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $sub_ptr_rhs_cast5 = $3;
+ $sub_ptr_sub6 = $sub_ptr_rhs_cast - $sub_ptr_rhs_cast5 | 0;
+ $add = $sub_ptr_sub6 + $len | 0;
+ $m_buffer = $parser + 8 | 0;
+ $4 = HEAP32[$m_buffer >> 2] | 0;
+ $sub_ptr_rhs_cast9 = $4;
+ $sub_ptr_sub10 = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast9 | 0;
+ $cmp11 = ($add | 0) > ($sub_ptr_sub10 | 0);
+ if ($cmp11) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _bcopy($3 | 0, $4 | 0, $sub_ptr_sub6 | 0);
+ $5 = HEAP32[$m_buffer >> 2] | 0;
+ $6 = HEAP32[$m_bufferEnd >> 2] | 0;
+ $7 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $sub_ptr_lhs_cast23 = $6;
+ $sub_ptr_rhs_cast24 = $7;
+ $sub_ptr_sub25 = $sub_ptr_lhs_cast23 - $sub_ptr_rhs_cast24 | 0;
+ $add_ptr = $5 + $sub_ptr_sub25 | 0;
+ HEAP32[$m_bufferEnd >> 2] = $add_ptr;
+ $8 = HEAP32[$m_buffer >> 2] | 0;
+ $storemerge = $8;
+ label = 15;
+ break;
+ case 8:
+ $sub_ptr_sub33 = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast5 | 0;
+ $cmp34 = ($1 | 0) == ($3 | 0);
+ $_sub_ptr_sub33 = $cmp34 ? 1024 : $sub_ptr_sub33;
+ $bufferSize_0 = $_sub_ptr_sub33;
+ label = 9;
+ break;
+ case 9:
+ $mul = $bufferSize_0 << 1;
+ $cmp36 = ($mul | 0) < ($add | 0);
+ if ($cmp36) {
+ $bufferSize_0 = $mul;
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $malloc_fcn = $parser + 12 | 0;
+ $9 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call = FUNCTION_TABLE_ii[$9 & 1023]($mul) | 0;
+ $cmp37 = ($call | 0) == 0;
+ if ($cmp37) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $m_errorCode39 = $parser + 268 | 0;
+ HEAP32[$m_errorCode39 >> 2] = 1;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 12:
+ $add_ptr41 = $call + $mul | 0;
+ HEAP32[$m_bufferLim >> 2] = $add_ptr41;
+ $10 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $tobool = ($10 | 0) == 0;
+ if ($tobool) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $11 = HEAP32[$m_bufferEnd >> 2] | 0;
+ $sub_ptr_lhs_cast48 = $11;
+ $sub_ptr_rhs_cast49 = $10;
+ $sub_ptr_sub50 = $sub_ptr_lhs_cast48 - $sub_ptr_rhs_cast49 | 0;
+ _memcpy($call | 0, $10 | 0, $sub_ptr_sub50);
+ $free_fcn = $parser + 20 | 0;
+ $12 = HEAP32[$free_fcn >> 2] | 0;
+ $13 = HEAP32[$m_buffer >> 2] | 0;
+ FUNCTION_TABLE_vi[$12 & 1023]($13);
+ label = 14;
+ break;
+ case 14:
+ $14 = HEAP32[$m_bufferEnd >> 2] | 0;
+ $15 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $sub_ptr_lhs_cast56 = $14;
+ $sub_ptr_rhs_cast57 = $15;
+ $sub_ptr_sub58 = $sub_ptr_lhs_cast56 - $sub_ptr_rhs_cast57 | 0;
+ $add_ptr59 = $call + $sub_ptr_sub58 | 0;
+ HEAP32[$m_bufferEnd >> 2] = $add_ptr59;
+ HEAP32[$m_buffer >> 2] = $call;
+ $storemerge = $call;
+ label = 15;
+ break;
+ case 15:
+ HEAP32[$m_bufferPtr >> 2] = $storemerge;
+ $m_eventEndPtr = $parser + 276 | 0;
+ HEAP32[$m_eventEndPtr >> 2] = 0;
+ $m_eventPtr = $parser + 272 | 0;
+ HEAP32[$m_eventPtr >> 2] = 0;
+ $m_positionPtr = $parser + 280 | 0;
+ HEAP32[$m_positionPtr >> 2] = 0;
+ label = 16;
+ break;
+ case 16:
+ $16 = HEAP32[$m_bufferEnd >> 2] | 0;
+ $retval_0 = $16;
+ label = 17;
+ break;
+ case 17:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _XML_GetErrorCode($parser) {
+ $parser = $parser | 0;
+ return HEAP32[$parser + 268 >> 2] | 0;
+}
+function _XML_ErrorString($code) {
+ $code = $code | 0;
+ var $cmp = 0, $cmp1 = 0, $or_cond = 0, $arrayidx = 0, $0 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($code | 0) != 0;
+ $cmp1 = $code >>> 0 < 41;
+ $or_cond = $cmp & $cmp1;
+ if ($or_cond) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $arrayidx = 164744 + ($code << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $retval_0 = $0;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _hashTableIterInit($iter, $table) {
+ $iter = $iter | 0;
+ $table = $table | 0;
+ var $0 = 0;
+ $0 = HEAP32[$table >> 2] | 0;
+ HEAP32[$iter >> 2] = $0;
+ HEAP32[$iter + 4 >> 2] = $0 + (HEAP32[$table + 8 >> 2] << 2) | 0;
+ return;
+}
+function _hashTableIterNext($iter) {
+ $iter = $iter | 0;
+ var $p = 0, $end = 0, $0 = 0, $1 = 0, $cmp = 0, $incdec_ptr = 0, $2 = 0, $tobool = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p = $iter | 0;
+ $end = $iter + 4 | 0;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP32[$p >> 2] | 0;
+ $1 = HEAP32[$end >> 2] | 0;
+ $cmp = ($0 | 0) == ($1 | 0);
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $0 + 4 | 0;
+ HEAP32[$p >> 2] = $incdec_ptr;
+ $2 = HEAP32[$0 >> 2] | 0;
+ $tobool = ($2 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = $2;
+ label = 5;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _hash($parser, $s) {
+ $parser = $parser | 0;
+ $s = $s | 0;
+ var $m_hash_secret_salt = 0, $0 = 0, $1 = 0, $tobool2 = 0, $2 = 0, $h_04 = 0, $s_addr_03 = 0, $mul = 0, $incdec_ptr = 0, $conv = 0, $xor = 0, $3 = 0, $tobool = 0, $h_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_hash_secret_salt = $parser + 472 | 0;
+ $0 = HEAP32[$m_hash_secret_salt >> 2] | 0;
+ $1 = HEAP8[$s] | 0;
+ $tobool2 = $1 << 24 >> 24 == 0;
+ if ($tobool2) {
+ $h_0_lcssa = $0;
+ label = 4;
+ break;
+ } else {
+ $s_addr_03 = $s;
+ $h_04 = $0;
+ $2 = $1;
+ label = 3;
+ break;
+ }
+ case 3:
+ $mul = $h_04 * 1000003 & -1;
+ $incdec_ptr = $s_addr_03 + 1 | 0;
+ $conv = $2 & 255;
+ $xor = $conv ^ $mul;
+ $3 = HEAP8[$incdec_ptr] | 0;
+ $tobool = $3 << 24 >> 24 == 0;
+ if ($tobool) {
+ $h_0_lcssa = $xor;
+ label = 4;
+ break;
+ } else {
+ $s_addr_03 = $incdec_ptr;
+ $h_04 = $xor;
+ $2 = $3;
+ label = 3;
+ break;
+ }
+ case 4:
+ return $h_0_lcssa | 0;
+ }
+ return 0;
+}
+function _keyeq($s1, $s2) {
+ $s1 = $s1 | 0;
+ $s2 = $s2 | 0;
+ var $0 = 0, $1 = 0, $cmp5 = 0, $2 = 0, $s2_addr_07 = 0, $s1_addr_06 = 0, $cmp4 = 0, $incdec_ptr = 0, $incdec_ptr6 = 0, $3 = 0, $4 = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$s1] | 0;
+ $1 = HEAP8[$s2] | 0;
+ $cmp5 = $0 << 24 >> 24 == $1 << 24 >> 24;
+ if ($cmp5) {
+ $s1_addr_06 = $s1;
+ $s2_addr_07 = $s2;
+ $2 = $0;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 3:
+ $cmp4 = $2 << 24 >> 24 == 0;
+ if ($cmp4) {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $s1_addr_06 + 1 | 0;
+ $incdec_ptr6 = $s2_addr_07 + 1 | 0;
+ $3 = HEAP8[$incdec_ptr] | 0;
+ $4 = HEAP8[$incdec_ptr6] | 0;
+ $cmp = $3 << 24 >> 24 == $4 << 24 >> 24;
+ if ($cmp) {
+ $s1_addr_06 = $incdec_ptr;
+ $s2_addr_07 = $incdec_ptr6;
+ $2 = $3;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _XML_ParseBuffer($parser, $len, $isFinal) {
+ $parser = $parser | 0;
+ $len = $len | 0;
+ $isFinal = $isFinal | 0;
+ var $parsing = 0, $0 = 0, $m_errorCode = 0, $m_errorCode2 = 0, $m_parentParser = 0, $1 = 0, $cmp = 0, $call = 0, $tobool = 0, $m_errorCode4 = 0, $m_bufferPtr = 0, $2 = 0, $m_positionPtr = 0, $m_bufferEnd = 0, $3 = 0, $add_ptr = 0, $m_parseEndPtr = 0, $m_parseEndByteIndex = 0, $4 = 0, $add = 0, $conv = 0, $finalBuffer = 0, $m_processor = 0, $5 = 0, $6 = 0, $call11 = 0, $m_errorCode12 = 0, $cmp14 = 0, $m_eventPtr = 0, $7 = 0, $m_eventEndPtr = 0, $8 = 0, $tobool22 = 0, $result_0 = 0, $m_encoding = 0, $9 = 0, $updatePosition = 0, $10 = 0, $11 = 0, $12 = 0, $m_position = 0, $13 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $parsing = $parser + 464 | 0;
+ $0 = HEAP32[$parsing >> 2] | 0;
+ if (($0 | 0) == 3) {
+ label = 3;
+ break;
+ } else if (($0 | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($0 | 0) == 0) {
+ label = 5;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $m_errorCode = $parser + 268 | 0;
+ HEAP32[$m_errorCode >> 2] = 33;
+ $retval_0 = 0;
+ label = 15;
+ break;
+ case 4:
+ $m_errorCode2 = $parser + 268 | 0;
+ HEAP32[$m_errorCode2 >> 2] = 36;
+ $retval_0 = 0;
+ label = 15;
+ break;
+ case 5:
+ $m_parentParser = $parser + 460 | 0;
+ $1 = HEAP32[$m_parentParser >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $call = _startParsing($parser) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $m_errorCode4 = $parser + 268 | 0;
+ HEAP32[$m_errorCode4 >> 2] = 1;
+ $retval_0 = 0;
+ label = 15;
+ break;
+ case 8:
+ HEAP32[$parsing >> 2] = 1;
+ $m_bufferPtr = $parser + 24 | 0;
+ $2 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $m_positionPtr = $parser + 280 | 0;
+ HEAP32[$m_positionPtr >> 2] = $2;
+ $m_bufferEnd = $parser + 28 | 0;
+ $3 = HEAP32[$m_bufferEnd >> 2] | 0;
+ $add_ptr = $3 + $len | 0;
+ HEAP32[$m_bufferEnd >> 2] = $add_ptr;
+ $m_parseEndPtr = $parser + 40 | 0;
+ HEAP32[$m_parseEndPtr >> 2] = $add_ptr;
+ $m_parseEndByteIndex = $parser + 36 | 0;
+ $4 = HEAP32[$m_parseEndByteIndex >> 2] | 0;
+ $add = $4 + $len | 0;
+ HEAP32[$m_parseEndByteIndex >> 2] = $add;
+ $conv = $isFinal & 255;
+ $finalBuffer = $parser + 468 | 0;
+ HEAP8[$finalBuffer] = $conv;
+ $m_processor = $parser + 264 | 0;
+ $5 = HEAP32[$m_processor >> 2] | 0;
+ $6 = HEAP32[$m_parseEndPtr >> 2] | 0;
+ $call11 = FUNCTION_TABLE_iiiii[$5 & 1023]($parser, $2, $6, $m_bufferPtr) | 0;
+ $m_errorCode12 = $parser + 268 | 0;
+ HEAP32[$m_errorCode12 >> 2] = $call11;
+ $cmp14 = ($call11 | 0) == 0;
+ if ($cmp14) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $m_eventPtr = $parser + 272 | 0;
+ $7 = HEAP32[$m_eventPtr >> 2] | 0;
+ $m_eventEndPtr = $parser + 276 | 0;
+ HEAP32[$m_eventEndPtr >> 2] = $7;
+ HEAP32[$m_processor >> 2] = 448;
+ $retval_0 = 0;
+ label = 15;
+ break;
+ case 10:
+ $8 = HEAP32[$parsing >> 2] | 0;
+ if (($8 | 0) == 3) {
+ label = 11;
+ break;
+ } else if (($8 | 0) == 0 | ($8 | 0) == 1) {
+ label = 12;
+ break;
+ } else {
+ $result_0 = 1;
+ label = 14;
+ break;
+ }
+ case 11:
+ $result_0 = 2;
+ label = 14;
+ break;
+ case 12:
+ $tobool22 = ($isFinal | 0) == 0;
+ if ($tobool22) {
+ $result_0 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ HEAP32[$parsing >> 2] = 2;
+ $retval_0 = 1;
+ label = 15;
+ break;
+ case 14:
+ $m_encoding = $parser + 144 | 0;
+ $9 = HEAP32[$m_encoding >> 2] | 0;
+ $updatePosition = $9 + 48 | 0;
+ $10 = HEAP32[$updatePosition >> 2] | 0;
+ $11 = HEAP32[$m_positionPtr >> 2] | 0;
+ $12 = HEAP32[$m_bufferPtr >> 2] | 0;
+ $m_position = $parser + 392 | 0;
+ FUNCTION_TABLE_viiii[$10 & 1023]($9, $11, $12, $m_position);
+ $13 = HEAP32[$m_bufferPtr >> 2] | 0;
+ HEAP32[$m_positionPtr >> 2] = $13;
+ $retval_0 = $result_0;
+ label = 15;
+ break;
+ case 15:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _XML_GetCurrentLineNumber($parser) {
+ $parser = $parser | 0;
+ var $m_eventPtr = 0, $0 = 0, $tobool = 0, $m_positionPtr = 0, $1 = 0, $cmp = 0, $m_encoding = 0, $2 = 0, $updatePosition = 0, $3 = 0, $m_position = 0, $4 = 0, $lineNumber = 0, $5 = 0, $add = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_eventPtr = $parser + 272 | 0;
+ $0 = HEAP32[$m_eventPtr >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $m_positionPtr = $parser + 280 | 0;
+ $1 = HEAP32[$m_positionPtr >> 2] | 0;
+ $cmp = $0 >>> 0 < $1 >>> 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $m_encoding = $parser + 144 | 0;
+ $2 = HEAP32[$m_encoding >> 2] | 0;
+ $updatePosition = $2 + 48 | 0;
+ $3 = HEAP32[$updatePosition >> 2] | 0;
+ $m_position = $parser + 392 | 0;
+ FUNCTION_TABLE_viiii[$3 & 1023]($2, $1, $0, $m_position);
+ $4 = HEAP32[$m_eventPtr >> 2] | 0;
+ HEAP32[$m_positionPtr >> 2] = $4;
+ label = 5;
+ break;
+ case 5:
+ $lineNumber = $parser + 392 | 0;
+ $5 = HEAP32[$lineNumber >> 2] | 0;
+ $add = $5 + 1 | 0;
+ return $add | 0;
+ }
+ return 0;
+}
+function _reportDefault($parser, $enc, $s, $end) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $s = $s | 0;
+ $end = $end | 0;
+ var $s_addr = 0, $dataPtr = 0, $isUtf8 = 0, $0 = 0, $tobool = 0, $m_encoding = 0, $1 = 0, $cmp = 0, $m_eventPtr = 0, $m_eventEndPtr = 0, $m_openInternalEntities = 0, $2 = 0, $internalEventPtr = 0, $internalEventEndPtr = 0, $eventPP_0_ph = 0, $eventEndPP_0_ph = 0, $m_dataBuf = 0, $utf8Convert = 0, $m_dataBufEnd = 0, $m_defaultHandler = 0, $m_handlerArg = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $10 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $11 = 0, $12 = 0, $cmp5 = 0, $m_defaultHandler7 = 0, $13 = 0, $m_handlerArg8 = 0, $14 = 0, $sub_ptr_lhs_cast9 = 0, $sub_ptr_rhs_cast10 = 0, $sub_ptr_sub11 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s_addr = __stackBase__ | 0;
+ $dataPtr = __stackBase__ + 8 | 0;
+ HEAP32[$s_addr >> 2] = $s;
+ $isUtf8 = $enc + 68 | 0;
+ $0 = HEAP8[$isUtf8] | 0;
+ $tobool = $0 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $m_encoding = $parser + 144 | 0;
+ $1 = HEAP32[$m_encoding >> 2] | 0;
+ $cmp = ($1 | 0) == ($enc | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $m_eventPtr = $parser + 272 | 0;
+ $m_eventEndPtr = $parser + 276 | 0;
+ $eventEndPP_0_ph = $m_eventEndPtr;
+ $eventPP_0_ph = $m_eventPtr;
+ label = 6;
+ break;
+ case 5:
+ $m_openInternalEntities = $parser + 284 | 0;
+ $2 = HEAP32[$m_openInternalEntities >> 2] | 0;
+ $internalEventPtr = $2 | 0;
+ $internalEventEndPtr = $2 + 4 | 0;
+ $eventEndPP_0_ph = $internalEventEndPtr;
+ $eventPP_0_ph = $internalEventPtr;
+ label = 6;
+ break;
+ case 6:
+ $m_dataBuf = $parser + 44 | 0;
+ $utf8Convert = $enc + 56 | 0;
+ $m_dataBufEnd = $parser + 48 | 0;
+ $m_defaultHandler = $parser + 80 | 0;
+ $m_handlerArg = $parser + 4 | 0;
+ label = 7;
+ break;
+ case 7:
+ $3 = HEAP32[$m_dataBuf >> 2] | 0;
+ HEAP32[$dataPtr >> 2] = $3;
+ $4 = HEAP32[$utf8Convert >> 2] | 0;
+ $5 = HEAP32[$m_dataBufEnd >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$4 & 1023]($enc, $s_addr, $end, $dataPtr, $5);
+ $6 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$eventEndPP_0_ph >> 2] = $6;
+ $7 = HEAP32[$m_defaultHandler >> 2] | 0;
+ $8 = HEAP32[$m_handlerArg >> 2] | 0;
+ $9 = HEAP32[$m_dataBuf >> 2] | 0;
+ $10 = HEAP32[$dataPtr >> 2] | 0;
+ $sub_ptr_lhs_cast = $10;
+ $sub_ptr_rhs_cast = $9;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ FUNCTION_TABLE_viii[$7 & 1023]($8, $9, $sub_ptr_sub);
+ $11 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$eventPP_0_ph >> 2] = $11;
+ $12 = HEAP32[$s_addr >> 2] | 0;
+ $cmp5 = ($12 | 0) == ($end | 0);
+ if ($cmp5) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 8:
+ $m_defaultHandler7 = $parser + 80 | 0;
+ $13 = HEAP32[$m_defaultHandler7 >> 2] | 0;
+ $m_handlerArg8 = $parser + 4 | 0;
+ $14 = HEAP32[$m_handlerArg8 >> 2] | 0;
+ $sub_ptr_lhs_cast9 = $end;
+ $sub_ptr_rhs_cast10 = $s;
+ $sub_ptr_sub11 = $sub_ptr_lhs_cast9 - $sub_ptr_rhs_cast10 | 0;
+ FUNCTION_TABLE_viii[$13 & 1023]($14, $s, $sub_ptr_sub11);
+ label = 9;
+ break;
+ case 9:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _poolGrow($pool) {
+ $pool = $pool | 0;
+ var $freeBlocks = 0, $0 = 0, $tobool = 0, $start = 0, $1 = 0, $cmp = 0, $blocks = 0, $2 = 0, $next = 0, $3 = 0, $4 = 0, $next6 = 0, $5 = 0, $arraydecay = 0, $6 = 0, $size = 0, $7 = 0, $add_ptr = 0, $end = 0, $8 = 0, $ptr = 0, $end12 = 0, $9 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $size15 = 0, $10 = 0, $cmp16 = 0, $next19 = 0, $11 = 0, $blocks20 = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $sub_ptr_lhs_cast31 = 0, $sub_ptr_rhs_cast32 = 0, $sub_ptr_sub33 = 0, $18 = 0, $ptr37 = 0, $19 = 0, $20 = 0, $sub_ptr_lhs_cast39 = 0, $sub_ptr_rhs_cast40 = 0, $sub_ptr_sub41 = 0, $add_ptr42 = 0, $21 = 0, $arraydecay46 = 0, $22 = 0, $size50 = 0, $23 = 0, $add_ptr51 = 0, $blocks55 = 0, $24 = 0, $tobool56 = 0, $start57 = 0, $25 = 0, $arraydecay60 = 0, $cmp61 = 0, $end63 = 0, $26 = 0, $sub_ptr_lhs_cast65 = 0, $sub_ptr_rhs_cast66 = 0, $sub_ptr_sub67 = 0, $mul68 = 0, $mem = 0, $27 = 0, $realloc_fcn = 0, $28 = 0, $29 = 0, $add = 0, $call = 0, $cmp71 = 0, $30 = 0, $size76 = 0, $31 = 0, $32 = 0, $ptr80 = 0, $33 = 0, $34 = 0, $sub_ptr_lhs_cast82 = 0, $sub_ptr_rhs_cast83 = 0, $sub_ptr_sub84 = 0, $add_ptr85 = 0, $35 = 0, $arraydecay89 = 0, $add_ptr92 = 0, $end96 = 0, $36 = 0, $start97 = 0, $37 = 0, $sub_ptr_lhs_cast98 = 0, $sub_ptr_rhs_cast99 = 0, $sub_ptr_sub100 = 0, $cmp101 = 0, $mul104 = 0, $blockSize95_0 = 0, $mem106 = 0, $38 = 0, $malloc_fcn = 0, $39 = 0, $add108 = 0, $call109 = 0, $tobool110 = 0, $40 = 0, $size113 = 0, $41 = 0, $42 = 0, $next115 = 0, $ptr117 = 0, $43 = 0, $44 = 0, $cmp119 = 0, $s121 = 0, $sub_ptr_lhs_cast125 = 0, $sub_ptr_rhs_cast126 = 0, $sub_ptr_sub127 = 0, $s130 = 0, $45 = 0, $46 = 0, $sub_ptr_lhs_cast134 = 0, $sub_ptr_rhs_cast135 = 0, $sub_ptr_sub136 = 0, $s130_sum = 0, $add_ptr137 = 0, $add_ptr144 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $freeBlocks = $pool + 4 | 0;
+ $0 = HEAP32[$freeBlocks >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $start = $pool + 16 | 0;
+ $1 = HEAP32[$start >> 2] | 0;
+ $cmp = ($1 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $blocks = $pool | 0;
+ HEAP32[$blocks >> 2] = $0;
+ $2 = HEAP32[$freeBlocks >> 2] | 0;
+ $next = $2 | 0;
+ $3 = HEAP32[$next >> 2] | 0;
+ HEAP32[$freeBlocks >> 2] = $3;
+ $4 = HEAP32[$blocks >> 2] | 0;
+ $next6 = $4 | 0;
+ HEAP32[$next6 >> 2] = 0;
+ $5 = HEAP32[$blocks >> 2] | 0;
+ $arraydecay = $5 + 8 | 0;
+ HEAP32[$start >> 2] = $arraydecay;
+ $6 = HEAP32[$blocks >> 2] | 0;
+ $size = $6 + 4 | 0;
+ $7 = HEAP32[$size >> 2] | 0;
+ $add_ptr = $7 + ($5 + 8) | 0;
+ $end = $pool + 8 | 0;
+ HEAP32[$end >> 2] = $add_ptr;
+ $8 = HEAP32[$start >> 2] | 0;
+ $ptr = $pool + 12 | 0;
+ HEAP32[$ptr >> 2] = $8;
+ $retval_0 = 1;
+ label = 15;
+ break;
+ case 5:
+ $end12 = $pool + 8 | 0;
+ $9 = HEAP32[$end12 >> 2] | 0;
+ $sub_ptr_lhs_cast = $9;
+ $sub_ptr_rhs_cast = $1;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $size15 = $0 + 4 | 0;
+ $10 = HEAP32[$size15 >> 2] | 0;
+ $cmp16 = ($sub_ptr_sub | 0) < ($10 | 0);
+ if ($cmp16) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $next19 = $0 | 0;
+ $11 = HEAP32[$next19 >> 2] | 0;
+ $blocks20 = $pool | 0;
+ $12 = HEAP32[$blocks20 >> 2] | 0;
+ HEAP32[$next19 >> 2] = $12;
+ $13 = HEAP32[$freeBlocks >> 2] | 0;
+ HEAP32[$blocks20 >> 2] = $13;
+ HEAP32[$freeBlocks >> 2] = $11;
+ $14 = HEAP32[$blocks20 >> 2] | 0;
+ $15 = $14 + 8 | 0;
+ $16 = HEAP32[$start >> 2] | 0;
+ $17 = HEAP32[$end12 >> 2] | 0;
+ $sub_ptr_lhs_cast31 = $17;
+ $sub_ptr_rhs_cast32 = $16;
+ $sub_ptr_sub33 = $sub_ptr_lhs_cast31 - $sub_ptr_rhs_cast32 | 0;
+ _memcpy($15 | 0, $16 | 0, $sub_ptr_sub33);
+ $18 = HEAP32[$blocks20 >> 2] | 0;
+ $ptr37 = $pool + 12 | 0;
+ $19 = HEAP32[$ptr37 >> 2] | 0;
+ $20 = HEAP32[$start >> 2] | 0;
+ $sub_ptr_lhs_cast39 = $19;
+ $sub_ptr_rhs_cast40 = $20;
+ $sub_ptr_sub41 = $sub_ptr_lhs_cast39 - $sub_ptr_rhs_cast40 | 0;
+ $add_ptr42 = $sub_ptr_sub41 + ($18 + 8) | 0;
+ HEAP32[$ptr37 >> 2] = $add_ptr42;
+ $21 = HEAP32[$blocks20 >> 2] | 0;
+ $arraydecay46 = $21 + 8 | 0;
+ HEAP32[$start >> 2] = $arraydecay46;
+ $22 = HEAP32[$blocks20 >> 2] | 0;
+ $size50 = $22 + 4 | 0;
+ $23 = HEAP32[$size50 >> 2] | 0;
+ $add_ptr51 = $23 + ($21 + 8) | 0;
+ HEAP32[$end12 >> 2] = $add_ptr51;
+ $retval_0 = 1;
+ label = 15;
+ break;
+ case 7:
+ $blocks55 = $pool | 0;
+ $24 = HEAP32[$blocks55 >> 2] | 0;
+ $tobool56 = ($24 | 0) == 0;
+ if ($tobool56) {
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $start57 = $pool + 16 | 0;
+ $25 = HEAP32[$start57 >> 2] | 0;
+ $arraydecay60 = $24 + 8 | 0;
+ $cmp61 = ($25 | 0) == ($arraydecay60 | 0);
+ if ($cmp61) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $end63 = $pool + 8 | 0;
+ $26 = HEAP32[$end63 >> 2] | 0;
+ $sub_ptr_lhs_cast65 = $26;
+ $sub_ptr_rhs_cast66 = $25;
+ $sub_ptr_sub67 = $sub_ptr_lhs_cast65 - $sub_ptr_rhs_cast66 | 0;
+ $mul68 = $sub_ptr_sub67 << 1;
+ $mem = $pool + 20 | 0;
+ $27 = HEAP32[$mem >> 2] | 0;
+ $realloc_fcn = $27 + 4 | 0;
+ $28 = HEAP32[$realloc_fcn >> 2] | 0;
+ $29 = $24;
+ $add = $mul68 + 8 | 0;
+ $call = FUNCTION_TABLE_iii[$28 & 1023]($29, $add) | 0;
+ $cmp71 = ($call | 0) == 0;
+ if ($cmp71) {
+ $retval_0 = 0;
+ label = 15;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $30 = $call;
+ HEAP32[$blocks55 >> 2] = $30;
+ $size76 = $call + 4 | 0;
+ $31 = $size76;
+ HEAP32[$31 >> 2] = $mul68;
+ $32 = HEAP32[$blocks55 >> 2] | 0;
+ $ptr80 = $pool + 12 | 0;
+ $33 = HEAP32[$ptr80 >> 2] | 0;
+ $34 = HEAP32[$start57 >> 2] | 0;
+ $sub_ptr_lhs_cast82 = $33;
+ $sub_ptr_rhs_cast83 = $34;
+ $sub_ptr_sub84 = $sub_ptr_lhs_cast82 - $sub_ptr_rhs_cast83 | 0;
+ $add_ptr85 = $sub_ptr_sub84 + ($32 + 8) | 0;
+ HEAP32[$ptr80 >> 2] = $add_ptr85;
+ $35 = HEAP32[$blocks55 >> 2] | 0;
+ $arraydecay89 = $35 + 8 | 0;
+ HEAP32[$start57 >> 2] = $arraydecay89;
+ $add_ptr92 = $mul68 + ($35 + 8) | 0;
+ HEAP32[$end63 >> 2] = $add_ptr92;
+ $retval_0 = 1;
+ label = 15;
+ break;
+ case 11:
+ $end96 = $pool + 8 | 0;
+ $36 = HEAP32[$end96 >> 2] | 0;
+ $start97 = $pool + 16 | 0;
+ $37 = HEAP32[$start97 >> 2] | 0;
+ $sub_ptr_lhs_cast98 = $36;
+ $sub_ptr_rhs_cast99 = $37;
+ $sub_ptr_sub100 = $sub_ptr_lhs_cast98 - $sub_ptr_rhs_cast99 | 0;
+ $cmp101 = ($sub_ptr_sub100 | 0) < 1024;
+ $mul104 = $sub_ptr_sub100 << 1;
+ $blockSize95_0 = $cmp101 ? 1024 : $mul104;
+ $mem106 = $pool + 20 | 0;
+ $38 = HEAP32[$mem106 >> 2] | 0;
+ $malloc_fcn = $38 | 0;
+ $39 = HEAP32[$malloc_fcn >> 2] | 0;
+ $add108 = $blockSize95_0 + 8 | 0;
+ $call109 = FUNCTION_TABLE_ii[$39 & 1023]($add108) | 0;
+ $tobool110 = ($call109 | 0) == 0;
+ if ($tobool110) {
+ $retval_0 = 0;
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $40 = $call109;
+ $size113 = $call109 + 4 | 0;
+ $41 = $size113;
+ HEAP32[$41 >> 2] = $blockSize95_0;
+ $42 = HEAP32[$blocks55 >> 2] | 0;
+ $next115 = $call109;
+ HEAP32[$next115 >> 2] = $42;
+ HEAP32[$blocks55 >> 2] = $40;
+ $ptr117 = $pool + 12 | 0;
+ $43 = HEAP32[$ptr117 >> 2] | 0;
+ $44 = HEAP32[$start97 >> 2] | 0;
+ $cmp119 = ($43 | 0) == ($44 | 0);
+ if ($cmp119) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $s121 = $call109 + 8 | 0;
+ $sub_ptr_lhs_cast125 = $43;
+ $sub_ptr_rhs_cast126 = $44;
+ $sub_ptr_sub127 = $sub_ptr_lhs_cast125 - $sub_ptr_rhs_cast126 | 0;
+ _memcpy($s121 | 0, $44 | 0, $sub_ptr_sub127);
+ label = 14;
+ break;
+ case 14:
+ $s130 = $call109 + 8 | 0;
+ $45 = HEAP32[$ptr117 >> 2] | 0;
+ $46 = HEAP32[$start97 >> 2] | 0;
+ $sub_ptr_lhs_cast134 = $45;
+ $sub_ptr_rhs_cast135 = $46;
+ $sub_ptr_sub136 = $sub_ptr_lhs_cast134 + 8 | 0;
+ $s130_sum = $sub_ptr_sub136 - $sub_ptr_rhs_cast135 | 0;
+ $add_ptr137 = $call109 + $s130_sum | 0;
+ HEAP32[$ptr117 >> 2] = $add_ptr137;
+ HEAP32[$start97 >> 2] = $s130;
+ $add_ptr144 = $call109 + $add108 | 0;
+ HEAP32[$end96 >> 2] = $add_ptr144;
+ $retval_0 = 1;
+ label = 15;
+ break;
+ case 15:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _lookup($parser, $table, $name, $createSize) {
+ $parser = $parser | 0;
+ $table = $table | 0;
+ $name = $name | 0;
+ $createSize = $createSize | 0;
+ var $size = 0, $0 = 0, $cmp = 0, $tobool = 0, $power = 0, $mem = 0, $1 = 0, $malloc_fcn = 0, $2 = 0, $call = 0, $3 = 0, $v = 0, $tobool5 = 0, $call10 = 0, $4 = 0, $sub = 0, $and = 0, $call12 = 0, $sub14 = 0, $and15 = 0, $v16 = 0, $5 = 0, $arrayidx116 = 0, $6 = 0, $tobool17117 = 0, $neg = 0, $and29 = 0, $power30 = 0, $shr32 = 0, $7 = 0, $i_0119 = 0, $step_0118 = 0, $name20 = 0, $8 = 0, $call21 = 0, $tobool22 = 0, $tobool27 = 0, $9 = 0, $conv = 0, $sub31 = 0, $shr = 0, $and33 = 0, $or = 0, $conv34 = 0, $step_1 = 0, $conv36 = 0, $cmp37 = 0, $10 = 0, $sub41 = 0, $add = 0, $sub43 = 0, $i_0_be = 0, $11 = 0, $arrayidx = 0, $12 = 0, $tobool17 = 0, $i_0_lcssa = 0, $tobool44 = 0, $used = 0, $13 = 0, $power47 = 0, $14 = 0, $conv48 = 0, $sub49 = 0, $shr50 = 0, $tobool51 = 0, $add55 = 0, $conv57 = 0, $shl = 0, $sub58 = 0, $mul60 = 0, $mem61 = 0, $15 = 0, $malloc_fcn62 = 0, $16 = 0, $call63 = 0, $17 = 0, $tobool64 = 0, $18 = 0, $cmp68111 = 0, $neg85 = 0, $sub88 = 0, $shr90 = 0, $i_1112 = 0, $19 = 0, $arrayidx71 = 0, $20 = 0, $tobool72 = 0, $name76 = 0, $21 = 0, $call77 = 0, $and78 = 0, $arrayidx80106 = 0, $22 = 0, $tobool81107 = 0, $and86 = 0, $shr89 = 0, $and91 = 0, $or92 = 0, $conv93 = 0, $j_0109 = 0, $step_2108 = 0, $tobool83 = 0, $conv93_step_2108 = 0, $conv95 = 0, $cmp96 = 0, $sub100 = 0, $sub100_pn = 0, $j_0_be = 0, $arrayidx80 = 0, $23 = 0, $tobool81 = 0, $arrayidx80_lcssa = 0, $24 = 0, $arrayidx109 = 0, $25 = 0, $inc = 0, $26 = 0, $cmp68 = 0, $27 = 0, $free_fcn = 0, $28 = 0, $29 = 0, $30 = 0, $and117 = 0, $31 = 0, $arrayidx120102 = 0, $32 = 0, $tobool121103 = 0, $neg125 = 0, $and126 = 0, $sub128 = 0, $shr129 = 0, $shr130 = 0, $and131 = 0, $or132 = 0, $conv133 = 0, $33 = 0, $i_2105 = 0, $step_4104 = 0, $tobool123 = 0, $conv133_step_4104 = 0, $conv135 = 0, $cmp136 = 0, $sub140 = 0, $sub140_pn = 0, $i_2_be = 0, $arrayidx120 = 0, $34 = 0, $tobool121 = 0, $i_3 = 0, $mem150 = 0, $35 = 0, $malloc_fcn151 = 0, $36 = 0, $call152 = 0, $37 = 0, $v153 = 0, $38 = 0, $arrayidx154 = 0, $39 = 0, $arrayidx156 = 0, $40 = 0, $tobool157 = 0, $41 = 0, $42 = 0, $arrayidx163 = 0, $43 = 0, $name164 = 0, $used165 = 0, $44 = 0, $inc166 = 0, $45 = 0, $arrayidx168 = 0, $46 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $table + 8 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $tobool = ($createSize | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $power = $table + 4 | 0;
+ HEAP8[$power] = 6;
+ HEAP32[$size >> 2] = 64;
+ $mem = $table + 16 | 0;
+ $1 = HEAP32[$mem >> 2] | 0;
+ $malloc_fcn = $1 | 0;
+ $2 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call = FUNCTION_TABLE_ii[$2 & 1023](256) | 0;
+ $3 = $call;
+ $v = $table | 0;
+ HEAP32[$v >> 2] = $3;
+ $tobool5 = ($call | 0) == 0;
+ if ($tobool5) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAP32[$size >> 2] = 0;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 6:
+ _memset($call | 0, 0, 256);
+ $call10 = _hash($parser, $name) | 0;
+ $4 = HEAP32[$size >> 2] | 0;
+ $sub = $4 - 1 | 0;
+ $and = $sub & $call10;
+ $i_3 = $and;
+ label = 30;
+ break;
+ case 7:
+ $call12 = _hash($parser, $name) | 0;
+ $sub14 = $0 - 1 | 0;
+ $and15 = $call12 & $sub14;
+ $v16 = $table | 0;
+ $5 = HEAP32[$v16 >> 2] | 0;
+ $arrayidx116 = $5 + ($and15 << 2) | 0;
+ $6 = HEAP32[$arrayidx116 >> 2] | 0;
+ $tobool17117 = ($6 | 0) == 0;
+ if ($tobool17117) {
+ $i_0_lcssa = $and15;
+ label = 16;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $neg = -$0 | 0;
+ $and29 = $call12 & $neg;
+ $power30 = $table + 4 | 0;
+ $shr32 = $sub14 >>> 2;
+ $step_0118 = 0;
+ $i_0119 = $and15;
+ $7 = $6;
+ label = 9;
+ break;
+ case 9:
+ $name20 = $7 | 0;
+ $8 = HEAP32[$name20 >> 2] | 0;
+ $call21 = _keyeq($name, $8) | 0;
+ $tobool22 = $call21 << 24 >> 24 == 0;
+ if ($tobool22) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = $7;
+ label = 32;
+ break;
+ }
+ case 10:
+ $tobool27 = $step_0118 << 24 >> 24 == 0;
+ if ($tobool27) {
+ label = 11;
+ break;
+ } else {
+ $step_1 = $step_0118;
+ label = 12;
+ break;
+ }
+ case 11:
+ $9 = HEAP8[$power30] | 0;
+ $conv = $9 & 255;
+ $sub31 = $conv - 1 | 0;
+ $shr = $and29 >>> ($sub31 >>> 0);
+ $and33 = $shr & $shr32;
+ $or = $and33 | 1;
+ $conv34 = $or & 255;
+ $step_1 = $conv34;
+ label = 12;
+ break;
+ case 12:
+ $conv36 = $step_1 & 255;
+ $cmp37 = $i_0119 >>> 0 < $conv36 >>> 0;
+ if ($cmp37) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $10 = HEAP32[$size >> 2] | 0;
+ $sub41 = $i_0119 - $conv36 | 0;
+ $add = $sub41 + $10 | 0;
+ $i_0_be = $add;
+ label = 15;
+ break;
+ case 14:
+ $sub43 = $i_0119 - $conv36 | 0;
+ $i_0_be = $sub43;
+ label = 15;
+ break;
+ case 15:
+ $11 = HEAP32[$v16 >> 2] | 0;
+ $arrayidx = $11 + ($i_0_be << 2) | 0;
+ $12 = HEAP32[$arrayidx >> 2] | 0;
+ $tobool17 = ($12 | 0) == 0;
+ if ($tobool17) {
+ $i_0_lcssa = $i_0_be;
+ label = 16;
+ break;
+ } else {
+ $step_0118 = $step_1;
+ $i_0119 = $i_0_be;
+ $7 = $12;
+ label = 9;
+ break;
+ }
+ case 16:
+ $tobool44 = ($createSize | 0) == 0;
+ if ($tobool44) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $used = $table + 12 | 0;
+ $13 = HEAP32[$used >> 2] | 0;
+ $power47 = $table + 4 | 0;
+ $14 = HEAP8[$power47] | 0;
+ $conv48 = $14 & 255;
+ $sub49 = $conv48 - 1 | 0;
+ $shr50 = $13 >>> ($sub49 >>> 0);
+ $tobool51 = ($shr50 | 0) == 0;
+ if ($tobool51) {
+ $i_3 = $i_0_lcssa;
+ label = 30;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $add55 = $14 + 1 & 255;
+ $conv57 = $add55 & 255;
+ $shl = 1 << $conv57;
+ $sub58 = $shl - 1 | 0;
+ $mul60 = $shl << 2;
+ $mem61 = $table + 16 | 0;
+ $15 = HEAP32[$mem61 >> 2] | 0;
+ $malloc_fcn62 = $15 | 0;
+ $16 = HEAP32[$malloc_fcn62 >> 2] | 0;
+ $call63 = FUNCTION_TABLE_ii[$16 & 1023]($mul60) | 0;
+ $17 = $call63;
+ $tobool64 = ($call63 | 0) == 0;
+ if ($tobool64) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ _memset($call63 | 0, 0, $mul60 | 0);
+ $18 = HEAP32[$size >> 2] | 0;
+ $cmp68111 = ($18 | 0) == 0;
+ if ($cmp68111) {
+ label = 27;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $neg85 = -$shl | 0;
+ $sub88 = $conv57 - 1 | 0;
+ $shr90 = $sub58 >>> 2;
+ $i_1112 = 0;
+ label = 21;
+ break;
+ case 21:
+ $19 = HEAP32[$v16 >> 2] | 0;
+ $arrayidx71 = $19 + ($i_1112 << 2) | 0;
+ $20 = HEAP32[$arrayidx71 >> 2] | 0;
+ $tobool72 = ($20 | 0) == 0;
+ if ($tobool72) {
+ label = 26;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $name76 = $20 | 0;
+ $21 = HEAP32[$name76 >> 2] | 0;
+ $call77 = _hash($parser, $21) | 0;
+ $and78 = $call77 & $sub58;
+ $arrayidx80106 = $17 + ($and78 << 2) | 0;
+ $22 = HEAP32[$arrayidx80106 >> 2] | 0;
+ $tobool81107 = ($22 | 0) == 0;
+ if ($tobool81107) {
+ $arrayidx80_lcssa = $arrayidx80106;
+ label = 25;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $and86 = $call77 & $neg85;
+ $shr89 = $and86 >>> ($sub88 >>> 0);
+ $and91 = $shr89 & $shr90;
+ $or92 = $and91 | 1;
+ $conv93 = $or92 & 255;
+ $step_2108 = 0;
+ $j_0109 = $and78;
+ label = 24;
+ break;
+ case 24:
+ $tobool83 = $step_2108 << 24 >> 24 == 0;
+ $conv93_step_2108 = $tobool83 ? $conv93 : $step_2108;
+ $conv95 = $conv93_step_2108 & 255;
+ $cmp96 = $j_0109 >>> 0 < $conv95 >>> 0;
+ $sub100 = $cmp96 ? $shl : 0;
+ $sub100_pn = $j_0109 + $sub100 | 0;
+ $j_0_be = $sub100_pn - $conv95 | 0;
+ $arrayidx80 = $17 + ($j_0_be << 2) | 0;
+ $23 = HEAP32[$arrayidx80 >> 2] | 0;
+ $tobool81 = ($23 | 0) == 0;
+ if ($tobool81) {
+ $arrayidx80_lcssa = $arrayidx80;
+ label = 25;
+ break;
+ } else {
+ $step_2108 = $conv93_step_2108;
+ $j_0109 = $j_0_be;
+ label = 24;
+ break;
+ }
+ case 25:
+ $24 = HEAP32[$v16 >> 2] | 0;
+ $arrayidx109 = $24 + ($i_1112 << 2) | 0;
+ $25 = HEAP32[$arrayidx109 >> 2] | 0;
+ HEAP32[$arrayidx80_lcssa >> 2] = $25;
+ label = 26;
+ break;
+ case 26:
+ $inc = $i_1112 + 1 | 0;
+ $26 = HEAP32[$size >> 2] | 0;
+ $cmp68 = $inc >>> 0 < $26 >>> 0;
+ if ($cmp68) {
+ $i_1112 = $inc;
+ label = 21;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $27 = HEAP32[$mem61 >> 2] | 0;
+ $free_fcn = $27 + 8 | 0;
+ $28 = HEAP32[$free_fcn >> 2] | 0;
+ $29 = HEAP32[$v16 >> 2] | 0;
+ $30 = $29;
+ FUNCTION_TABLE_vi[$28 & 1023]($30);
+ HEAP32[$v16 >> 2] = $17;
+ HEAP8[$power47] = $add55;
+ HEAP32[$size >> 2] = $shl;
+ $and117 = $sub58 & $call12;
+ $31 = HEAP32[$v16 >> 2] | 0;
+ $arrayidx120102 = $31 + ($and117 << 2) | 0;
+ $32 = HEAP32[$arrayidx120102 >> 2] | 0;
+ $tobool121103 = ($32 | 0) == 0;
+ if ($tobool121103) {
+ $i_3 = $and117;
+ label = 30;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $neg125 = -$shl | 0;
+ $and126 = $call12 & $neg125;
+ $sub128 = $conv57 - 1 | 0;
+ $shr129 = $and126 >>> ($sub128 >>> 0);
+ $shr130 = $sub58 >>> 2;
+ $and131 = $shr129 & $shr130;
+ $or132 = $and131 | 1;
+ $conv133 = $or132 & 255;
+ $33 = HEAP32[$v16 >> 2] | 0;
+ $step_4104 = 0;
+ $i_2105 = $and117;
+ label = 29;
+ break;
+ case 29:
+ $tobool123 = $step_4104 << 24 >> 24 == 0;
+ $conv133_step_4104 = $tobool123 ? $conv133 : $step_4104;
+ $conv135 = $conv133_step_4104 & 255;
+ $cmp136 = $i_2105 >>> 0 < $conv135 >>> 0;
+ $sub140 = $cmp136 ? $shl : 0;
+ $sub140_pn = $i_2105 + $sub140 | 0;
+ $i_2_be = $sub140_pn - $conv135 | 0;
+ $arrayidx120 = $33 + ($i_2_be << 2) | 0;
+ $34 = HEAP32[$arrayidx120 >> 2] | 0;
+ $tobool121 = ($34 | 0) == 0;
+ if ($tobool121) {
+ $i_3 = $i_2_be;
+ label = 30;
+ break;
+ } else {
+ $step_4104 = $conv133_step_4104;
+ $i_2105 = $i_2_be;
+ label = 29;
+ break;
+ }
+ case 30:
+ $mem150 = $table + 16 | 0;
+ $35 = HEAP32[$mem150 >> 2] | 0;
+ $malloc_fcn151 = $35 | 0;
+ $36 = HEAP32[$malloc_fcn151 >> 2] | 0;
+ $call152 = FUNCTION_TABLE_ii[$36 & 1023]($createSize) | 0;
+ $37 = $call152;
+ $v153 = $table | 0;
+ $38 = HEAP32[$v153 >> 2] | 0;
+ $arrayidx154 = $38 + ($i_3 << 2) | 0;
+ HEAP32[$arrayidx154 >> 2] = $37;
+ $39 = HEAP32[$v153 >> 2] | 0;
+ $arrayidx156 = $39 + ($i_3 << 2) | 0;
+ $40 = HEAP32[$arrayidx156 >> 2] | 0;
+ $tobool157 = ($40 | 0) == 0;
+ if ($tobool157) {
+ $retval_0 = 0;
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $41 = $40;
+ _memset($41 | 0, 0, $createSize | 0);
+ $42 = HEAP32[$v153 >> 2] | 0;
+ $arrayidx163 = $42 + ($i_3 << 2) | 0;
+ $43 = HEAP32[$arrayidx163 >> 2] | 0;
+ $name164 = $43 | 0;
+ HEAP32[$name164 >> 2] = $name;
+ $used165 = $table + 12 | 0;
+ $44 = HEAP32[$used165 >> 2] | 0;
+ $inc166 = $44 + 1 | 0;
+ HEAP32[$used165 >> 2] = $inc166;
+ $45 = HEAP32[$v153 >> 2] | 0;
+ $arrayidx168 = $45 + ($i_3 << 2) | 0;
+ $46 = HEAP32[$arrayidx168 >> 2] | 0;
+ $retval_0 = $46;
+ label = 32;
+ break;
+ case 32:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _hashTableDestroy($table) {
+ $table = $table | 0;
+ var $size = 0, $0 = 0, $cmp7 = 0, $mem = 0, $1 = 0, $free_fcn8 = 0, $2 = 0, $v = 0, $3 = 0, $4 = 0, $5 = 0, $i_09 = 0, $arrayidx = 0, $6 = 0, $7 = 0, $inc = 0, $8 = 0, $cmp = 0, $9 = 0, $free_fcn = 0, $10 = 0, $11 = 0, $_lcssa6 = 0, $_lcssa = 0, $12 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $size = $table + 8 | 0;
+ $0 = HEAP32[$size >> 2] | 0;
+ $cmp7 = ($0 | 0) == 0;
+ $mem = $table + 16 | 0;
+ $1 = HEAP32[$mem >> 2] | 0;
+ $free_fcn8 = $1 + 8 | 0;
+ $2 = HEAP32[$free_fcn8 >> 2] | 0;
+ $v = $table | 0;
+ $3 = HEAP32[$v >> 2] | 0;
+ if ($cmp7) {
+ $_lcssa = $2;
+ $_lcssa6 = $3;
+ label = 4;
+ break;
+ } else {
+ $i_09 = 0;
+ $5 = $2;
+ $4 = $3;
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $4 + ($i_09 << 2) | 0;
+ $6 = HEAP32[$arrayidx >> 2] | 0;
+ $7 = $6;
+ FUNCTION_TABLE_vi[$5 & 1023]($7);
+ $inc = $i_09 + 1 | 0;
+ $8 = HEAP32[$size >> 2] | 0;
+ $cmp = $inc >>> 0 < $8 >>> 0;
+ $9 = HEAP32[$mem >> 2] | 0;
+ $free_fcn = $9 + 8 | 0;
+ $10 = HEAP32[$free_fcn >> 2] | 0;
+ $11 = HEAP32[$v >> 2] | 0;
+ if ($cmp) {
+ $i_09 = $inc;
+ $5 = $10;
+ $4 = $11;
+ label = 3;
+ break;
+ } else {
+ $_lcssa = $10;
+ $_lcssa6 = $11;
+ label = 4;
+ break;
+ }
+ case 4:
+ $12 = $_lcssa6;
+ FUNCTION_TABLE_vi[$_lcssa & 1023]($12);
+ return;
+ }
+}
+function _addBinding($parser, $prefix, $attId, $uri, $bindingsPtr) {
+ $parser = $parser | 0;
+ $prefix = $prefix | 0;
+ $attId = $attId | 0;
+ $uri = $uri | 0;
+ $bindingsPtr = $bindingsPtr | 0;
+ var $0 = 0, $cmp = 0, $name = 0, $1 = 0, $tobool = 0, $name2 = 0, $2 = 0, $tobool3 = 0, $3 = 0, $cmp7 = 0, $arrayidx11 = 0, $4 = 0, $cmp13 = 0, $arrayidx17 = 0, $5 = 0, $cmp19 = 0, $arrayidx23 = 0, $6 = 0, $cmp25 = 0, $arrayidx29 = 0, $7 = 0, $cmp31 = 0, $arrayidx35 = 0, $8 = 0, $cmp37 = 0, $9 = 0, $arrayidx42 = 0, $10 = 0, $cmp44 = 0, $_ = 0, $mustBeXML_0 = 0, $11 = 0, $tobool5080 = 0, $tobool64 = 0, $tobool5285 = 0, $12 = 0, $arrayidx4984 = 0, $len_083 = 0, $isXMLNS_082 = 0, $isXML_081 = 0, $cmp54 = 0, $arrayidx58 = 0, $13 = 0, $cmp60 = 0, $isXML_1 = 0, $tobool67 = 0, $or_cond = 0, $cmp69 = 0, $14 = 0, $arrayidx74 = 0, $15 = 0, $cmp76 = 0, $isXMLNS_1 = 0, $inc = 0, $arrayidx49 = 0, $16 = 0, $tobool50 = 0, $tobool52 = 0, $isXMLNS_0_lcssa92 = 0, $len_0_lcssa90 = 0, $cmp82 = 0, $phitmp79 = 0, $isXMLNS_0_lcssa91 = 0, $len_0_lcssa89 = 0, $17 = 0, $tobool86 = 0, $cmp88 = 0, $phitmp78 = 0, $18 = 0, $conv93 = 0, $cmp95 = 0, $tobool99 = 0, $cond = 0, $tobool101 = 0, $m_namespaceSeparator = 0, $19 = 0, $not_tobool104 = 0, $inc106 = 0, $len_0_inc106 = 0, $m_freeBindingList = 0, $20 = 0, $tobool108 = 0, $uriAlloc = 0, $21 = 0, $cmp111 = 0, $realloc_fcn = 0, $22 = 0, $uri114 = 0, $23 = 0, $add = 0, $call = 0, $cmp115 = 0, $nextTagBinding = 0, $24 = 0, $malloc_fcn = 0, $25 = 0, $call125 = 0, $26 = 0, $tobool126 = 0, $27 = 0, $add131 = 0, $call133 = 0, $uri134 = 0, $28 = 0, $tobool136 = 0, $free_fcn = 0, $29 = 0, $uriAlloc141 = 0, $30 = 0, $b_0 = 0, $uriLen = 0, $uri143 = 0, $31 = 0, $32 = 0, $tobool146 = 0, $sub = 0, $33 = 0, $arrayidx150 = 0, $prefix152 = 0, $attId153 = 0, $binding = 0, $34 = 0, $prevPrefixBinding = 0, $35 = 0, $cmp155 = 0, $m_dtd = 0, $36 = 0, $defaultPrefix = 0, $cmp158 = 0, $storemerge = 0, $37 = 0, $nextTagBinding165 = 0, $tobool166 = 0, $m_startNamespaceDeclHandler = 0, $38 = 0, $tobool168 = 0, $m_handlerArg = 0, $39 = 0, $40 = 0, $41 = 0, $tobool173 = 0, $cond174 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$uri] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $name = $prefix | 0;
+ $1 = HEAP32[$name >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 28;
+ label = 47;
+ break;
+ }
+ case 4:
+ $name2 = $prefix | 0;
+ $2 = HEAP32[$name2 >> 2] | 0;
+ $tobool3 = ($2 | 0) == 0;
+ if ($tobool3) {
+ $mustBeXML_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = HEAP8[$2] | 0;
+ $cmp7 = $3 << 24 >> 24 == 120;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ $mustBeXML_0 = 0;
+ label = 12;
+ break;
+ }
+ case 6:
+ $arrayidx11 = $2 + 1 | 0;
+ $4 = HEAP8[$arrayidx11] | 0;
+ $cmp13 = $4 << 24 >> 24 == 109;
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ $mustBeXML_0 = 0;
+ label = 12;
+ break;
+ }
+ case 7:
+ $arrayidx17 = $2 + 2 | 0;
+ $5 = HEAP8[$arrayidx17] | 0;
+ $cmp19 = $5 << 24 >> 24 == 108;
+ if ($cmp19) {
+ label = 8;
+ break;
+ } else {
+ $mustBeXML_0 = 0;
+ label = 12;
+ break;
+ }
+ case 8:
+ $arrayidx23 = $2 + 3 | 0;
+ $6 = HEAP8[$arrayidx23] | 0;
+ $cmp25 = $6 << 24 >> 24 == 110;
+ if ($cmp25) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $arrayidx29 = $2 + 4 | 0;
+ $7 = HEAP8[$arrayidx29] | 0;
+ $cmp31 = $7 << 24 >> 24 == 115;
+ if ($cmp31) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $arrayidx35 = $2 + 5 | 0;
+ $8 = HEAP8[$arrayidx35] | 0;
+ $cmp37 = $8 << 24 >> 24 == 0;
+ if ($cmp37) {
+ $retval_0 = 39;
+ label = 47;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $9 = HEAP32[$name2 >> 2] | 0;
+ $arrayidx42 = $9 + 3 | 0;
+ $10 = HEAP8[$arrayidx42] | 0;
+ $cmp44 = $10 << 24 >> 24 == 0;
+ $_ = $cmp44 & 1;
+ $mustBeXML_0 = $_;
+ label = 12;
+ break;
+ case 12:
+ $11 = HEAP8[$uri] | 0;
+ $tobool5080 = $11 << 24 >> 24 == 0;
+ if ($tobool5080) {
+ $len_0_lcssa90 = 0;
+ $isXMLNS_0_lcssa92 = 1;
+ label = 24;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $tobool64 = $mustBeXML_0 << 24 >> 24 != 0;
+ $isXML_081 = 1;
+ $isXMLNS_082 = 1;
+ $len_083 = 0;
+ $arrayidx4984 = $uri;
+ $12 = $11;
+ $tobool5285 = 1;
+ label = 14;
+ break;
+ case 14:
+ if ($tobool5285) {
+ label = 15;
+ break;
+ } else {
+ $isXML_1 = 0;
+ label = 18;
+ break;
+ }
+ case 15:
+ $cmp54 = ($len_083 | 0) > 36;
+ if ($cmp54) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $arrayidx58 = $len_083 + 89704 | 0;
+ $13 = HEAP8[$arrayidx58] | 0;
+ $cmp60 = $12 << 24 >> 24 == $13 << 24 >> 24;
+ if ($cmp60) {
+ $isXML_1 = $isXML_081;
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $isXML_1 = 0;
+ label = 18;
+ break;
+ case 18:
+ $tobool67 = $isXMLNS_082 << 24 >> 24 == 0;
+ $or_cond = $tobool64 | $tobool67;
+ if ($or_cond) {
+ $isXMLNS_1 = $isXMLNS_082;
+ label = 22;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $cmp69 = ($len_083 | 0) > 29;
+ if ($cmp69) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $14 = HEAP8[$arrayidx4984] | 0;
+ $arrayidx74 = $len_083 + 89672 | 0;
+ $15 = HEAP8[$arrayidx74] | 0;
+ $cmp76 = $14 << 24 >> 24 == $15 << 24 >> 24;
+ if ($cmp76) {
+ $isXMLNS_1 = $isXMLNS_082;
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $isXMLNS_1 = 0;
+ label = 22;
+ break;
+ case 22:
+ $inc = $len_083 + 1 | 0;
+ $arrayidx49 = $uri + $inc | 0;
+ $16 = HEAP8[$arrayidx49] | 0;
+ $tobool50 = $16 << 24 >> 24 == 0;
+ $tobool52 = $isXML_1 << 24 >> 24 != 0;
+ if ($tobool50) {
+ label = 23;
+ break;
+ } else {
+ $isXML_081 = $isXML_1;
+ $isXMLNS_082 = $isXMLNS_1;
+ $len_083 = $inc;
+ $arrayidx4984 = $arrayidx49;
+ $12 = $16;
+ $tobool5285 = $tobool52;
+ label = 14;
+ break;
+ }
+ case 23:
+ if ($tobool52) {
+ $len_0_lcssa90 = $inc;
+ $isXMLNS_0_lcssa92 = $isXMLNS_1;
+ label = 24;
+ break;
+ } else {
+ $17 = 0;
+ $len_0_lcssa89 = $inc;
+ $isXMLNS_0_lcssa91 = $isXMLNS_1;
+ label = 25;
+ break;
+ }
+ case 24:
+ $cmp82 = ($len_0_lcssa90 | 0) == 36;
+ $phitmp79 = $cmp82 & 1;
+ $17 = $phitmp79;
+ $len_0_lcssa89 = $len_0_lcssa90;
+ $isXMLNS_0_lcssa91 = $isXMLNS_0_lcssa92;
+ label = 25;
+ break;
+ case 25:
+ $tobool86 = $isXMLNS_0_lcssa91 << 24 >> 24 == 0;
+ if ($tobool86) {
+ $18 = 0;
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $cmp88 = ($len_0_lcssa89 | 0) == 29;
+ $phitmp78 = $cmp88 & 1;
+ $18 = $phitmp78;
+ label = 27;
+ break;
+ case 27:
+ $conv93 = $mustBeXML_0 & 255;
+ $cmp95 = ($conv93 | 0) == ($17 | 0);
+ if ($cmp95) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $tobool99 = $mustBeXML_0 << 24 >> 24 != 0;
+ $cond = $tobool99 ? 38 : 40;
+ $retval_0 = $cond;
+ label = 47;
+ break;
+ case 29:
+ $tobool101 = $18 << 24 >> 24 == 0;
+ if ($tobool101) {
+ label = 30;
+ break;
+ } else {
+ $retval_0 = 40;
+ label = 47;
+ break;
+ }
+ case 30:
+ $m_namespaceSeparator = $parser + 456 | 0;
+ $19 = HEAP8[$m_namespaceSeparator] | 0;
+ $not_tobool104 = $19 << 24 >> 24 != 0;
+ $inc106 = $not_tobool104 & 1;
+ $len_0_inc106 = $inc106 + $len_0_lcssa89 | 0;
+ $m_freeBindingList = $parser + 360 | 0;
+ $20 = HEAP32[$m_freeBindingList >> 2] | 0;
+ $tobool108 = ($20 | 0) == 0;
+ if ($tobool108) {
+ label = 35;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $uriAlloc = $20 + 24 | 0;
+ $21 = HEAP32[$uriAlloc >> 2] | 0;
+ $cmp111 = ($len_0_inc106 | 0) > ($21 | 0);
+ if ($cmp111) {
+ label = 32;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 32:
+ $realloc_fcn = $parser + 16 | 0;
+ $22 = HEAP32[$realloc_fcn >> 2] | 0;
+ $uri114 = $20 + 16 | 0;
+ $23 = HEAP32[$uri114 >> 2] | 0;
+ $add = $len_0_inc106 + 24 | 0;
+ $call = FUNCTION_TABLE_iii[$22 & 1023]($23, $add) | 0;
+ $cmp115 = ($call | 0) == 0;
+ if ($cmp115) {
+ $retval_0 = 1;
+ label = 47;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ HEAP32[$uri114 >> 2] = $call;
+ HEAP32[$uriAlloc >> 2] = $add;
+ label = 34;
+ break;
+ case 34:
+ $nextTagBinding = $20 + 4 | 0;
+ $24 = HEAP32[$nextTagBinding >> 2] | 0;
+ HEAP32[$m_freeBindingList >> 2] = $24;
+ $b_0 = $20;
+ label = 39;
+ break;
+ case 35:
+ $malloc_fcn = $parser + 12 | 0;
+ $25 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call125 = FUNCTION_TABLE_ii[$25 & 1023](28) | 0;
+ $26 = $call125;
+ $tobool126 = ($call125 | 0) == 0;
+ if ($tobool126) {
+ $retval_0 = 1;
+ label = 47;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $27 = HEAP32[$malloc_fcn >> 2] | 0;
+ $add131 = $len_0_inc106 + 24 | 0;
+ $call133 = FUNCTION_TABLE_ii[$27 & 1023]($add131) | 0;
+ $uri134 = $call125 + 16 | 0;
+ $28 = $uri134;
+ HEAP32[$28 >> 2] = $call133;
+ $tobool136 = ($call133 | 0) == 0;
+ if ($tobool136) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ $free_fcn = $parser + 20 | 0;
+ $29 = HEAP32[$free_fcn >> 2] | 0;
+ FUNCTION_TABLE_vi[$29 & 1023]($call125);
+ $retval_0 = 1;
+ label = 47;
+ break;
+ case 38:
+ $uriAlloc141 = $call125 + 24 | 0;
+ $30 = $uriAlloc141;
+ HEAP32[$30 >> 2] = $add131;
+ $b_0 = $26;
+ label = 39;
+ break;
+ case 39:
+ $uriLen = $b_0 + 20 | 0;
+ HEAP32[$uriLen >> 2] = $len_0_inc106;
+ $uri143 = $b_0 + 16 | 0;
+ $31 = HEAP32[$uri143 >> 2] | 0;
+ _memcpy($31 | 0, $uri | 0, $len_0_inc106);
+ $32 = HEAP8[$m_namespaceSeparator] | 0;
+ $tobool146 = $32 << 24 >> 24 == 0;
+ if ($tobool146) {
+ label = 41;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $sub = $len_0_inc106 - 1 | 0;
+ $33 = HEAP32[$uri143 >> 2] | 0;
+ $arrayidx150 = $33 + $sub | 0;
+ HEAP8[$arrayidx150] = $32;
+ label = 41;
+ break;
+ case 41:
+ $prefix152 = $b_0 | 0;
+ HEAP32[$prefix152 >> 2] = $prefix;
+ $attId153 = $b_0 + 12 | 0;
+ HEAP32[$attId153 >> 2] = $attId;
+ $binding = $prefix + 4 | 0;
+ $34 = HEAP32[$binding >> 2] | 0;
+ $prevPrefixBinding = $b_0 + 8 | 0;
+ HEAP32[$prevPrefixBinding >> 2] = $34;
+ $35 = HEAP8[$uri] | 0;
+ $cmp155 = $35 << 24 >> 24 == 0;
+ if ($cmp155) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ $m_dtd = $parser + 340 | 0;
+ $36 = HEAP32[$m_dtd >> 2] | 0;
+ $defaultPrefix = $36 + 132 | 0;
+ $cmp158 = ($defaultPrefix | 0) == ($prefix | 0);
+ if ($cmp158) {
+ $storemerge = 0;
+ label = 44;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $storemerge = $b_0;
+ label = 44;
+ break;
+ case 44:
+ HEAP32[$binding >> 2] = $storemerge;
+ $37 = HEAP32[$bindingsPtr >> 2] | 0;
+ $nextTagBinding165 = $b_0 + 4 | 0;
+ HEAP32[$nextTagBinding165 >> 2] = $37;
+ HEAP32[$bindingsPtr >> 2] = $b_0;
+ $tobool166 = ($attId | 0) == 0;
+ if ($tobool166) {
+ $retval_0 = 0;
+ label = 47;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $m_startNamespaceDeclHandler = $parser + 100 | 0;
+ $38 = HEAP32[$m_startNamespaceDeclHandler >> 2] | 0;
+ $tobool168 = ($38 | 0) == 0;
+ if ($tobool168) {
+ $retval_0 = 0;
+ label = 47;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $m_handlerArg = $parser + 4 | 0;
+ $39 = HEAP32[$m_handlerArg >> 2] | 0;
+ $40 = HEAP32[$name2 >> 2] | 0;
+ $41 = HEAP32[$binding >> 2] | 0;
+ $tobool173 = ($41 | 0) != 0;
+ $cond174 = $tobool173 ? $uri : 0;
+ FUNCTION_TABLE_viii[$38 & 1023]($39, $40, $cond174);
+ $retval_0 = 0;
+ label = 47;
+ break;
+ case 47:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _initializeEncoding($parser) {
+ $parser = $parser | 0;
+ var $m_protocolEncodingName = 0, $0 = 0, $m_initEncoding = 0, $m_encoding = 0, $call = 0, $tobool1 = 0, $1 = 0, $call3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_protocolEncodingName = $parser + 228 | 0;
+ $0 = HEAP32[$m_protocolEncodingName >> 2] | 0;
+ $m_initEncoding = $parser + 148 | 0;
+ $m_encoding = $parser + 144 | 0;
+ $call = _XmlInitEncoding($m_initEncoding, $m_encoding, $0) | 0;
+ $tobool1 = ($call | 0) == 0;
+ if ($tobool1) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ }
+ case 3:
+ $1 = HEAP32[$m_protocolEncodingName >> 2] | 0;
+ $call3 = _handleUnknownEncoding($parser, $1) | 0;
+ $retval_0 = $call3;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _processXmlDecl($parser, $isGeneralTextEntity, $s, $next) {
+ $parser = $parser | 0;
+ $isGeneralTextEntity = $isGeneralTextEntity | 0;
+ $s = $s | 0;
+ $next = $next | 0;
+ var $encodingName = 0, $newEncoding = 0, $version = 0, $versionend = 0, $standalone = 0, $m_encoding = 0, $0 = 0, $m_eventPtr = 0, $call = 0, $tobool1 = 0, $tobool4 = 0, $_ = 0, $1 = 0, $cmp = 0, $m_dtd = 0, $2 = 0, $standalone7 = 0, $m_xmlDeclHandler = 0, $3 = 0, $tobool9 = 0, $4 = 0, $cmp11 = 0, $m_temp2Pool = 0, $5 = 0, $nameLength = 0, $6 = 0, $call17 = 0, $add_ptr = 0, $call18 = 0, $tobool19 = 0, $ptr = 0, $7 = 0, $start = 0, $storedEncName_0 = 0, $8 = 0, $tobool25 = 0, $m_temp2Pool27 = 0, $9 = 0, $10 = 0, $minBytesPerChar = 0, $11 = 0, $idx_neg = 0, $add_ptr30 = 0, $call31 = 0, $tobool32 = 0, $storedversion_0 = 0, $12 = 0, $m_handlerArg = 0, $13 = 0, $14 = 0, $m_defaultHandler = 0, $15 = 0, $tobool38 = 0, $16 = 0, $storedEncName_1 = 0, $storedversion_1 = 0, $m_protocolEncodingName = 0, $17 = 0, $cmp43 = 0, $18 = 0, $tobool46 = 0, $minBytesPerChar48 = 0, $19 = 0, $20 = 0, $minBytesPerChar50 = 0, $21 = 0, $cmp51 = 0, $22 = 0, $23 = 0, $tobool58 = 0, $tobool60 = 0, $m_temp2Pool62 = 0, $24 = 0, $nameLength65 = 0, $25 = 0, $call67 = 0, $add_ptr68 = 0, $call69 = 0, $tobool70 = 0, $storedEncName_2 = 0, $call74 = 0, $m_temp2Pool75 = 0, $cmp76 = 0, $26 = 0, $tobool84 = 0, $tobool85 = 0, $or_cond = 0, $m_temp2Pool87 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 40 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $encodingName = __stackBase__ | 0;
+ $newEncoding = __stackBase__ + 8 | 0;
+ $version = __stackBase__ + 16 | 0;
+ $versionend = __stackBase__ + 24 | 0;
+ $standalone = __stackBase__ + 32 | 0;
+ HEAP32[$encodingName >> 2] = 0;
+ HEAP32[$newEncoding >> 2] = 0;
+ HEAP32[$version >> 2] = 0;
+ HEAP32[$standalone >> 2] = -1;
+ $m_encoding = $parser + 144 | 0;
+ $0 = HEAP32[$m_encoding >> 2] | 0;
+ $m_eventPtr = $parser + 272 | 0;
+ $call = _XmlParseXmlDecl($isGeneralTextEntity, $0, $s, $next, $m_eventPtr, $version, $versionend, $encodingName, $newEncoding, $standalone) | 0;
+ $tobool1 = ($call | 0) == 0;
+ $tobool4 = ($isGeneralTextEntity | 0) != 0;
+ if ($tobool1) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $_ = $tobool4 ? 31 : 30;
+ $retval_0 = $_;
+ label = 28;
+ break;
+ case 4:
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $1 = HEAP32[$standalone >> 2] | 0;
+ $cmp = ($1 | 0) == 1;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $m_dtd = $parser + 340 | 0;
+ $2 = HEAP32[$m_dtd >> 2] | 0;
+ $standalone7 = $2 + 130 | 0;
+ HEAP8[$standalone7] = 1;
+ label = 7;
+ break;
+ case 7:
+ $m_xmlDeclHandler = $parser + 140 | 0;
+ $3 = HEAP32[$m_xmlDeclHandler >> 2] | 0;
+ $tobool9 = ($3 | 0) == 0;
+ if ($tobool9) {
+ label = 14;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $4 = HEAP32[$encodingName >> 2] | 0;
+ $cmp11 = ($4 | 0) == 0;
+ if ($cmp11) {
+ $storedEncName_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $m_temp2Pool = $parser + 424 | 0;
+ $5 = HEAP32[$m_encoding >> 2] | 0;
+ $nameLength = $5 + 28 | 0;
+ $6 = HEAP32[$nameLength >> 2] | 0;
+ $call17 = FUNCTION_TABLE_iii[$6 & 1023]($5, $4) | 0;
+ $add_ptr = $4 + $call17 | 0;
+ $call18 = _poolStoreString($m_temp2Pool, $5, $4, $add_ptr) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ $retval_0 = 1;
+ label = 28;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $ptr = $parser + 436 | 0;
+ $7 = HEAP32[$ptr >> 2] | 0;
+ $start = $parser + 440 | 0;
+ HEAP32[$start >> 2] = $7;
+ $storedEncName_0 = $call18;
+ label = 11;
+ break;
+ case 11:
+ $8 = HEAP32[$version >> 2] | 0;
+ $tobool25 = ($8 | 0) == 0;
+ if ($tobool25) {
+ $storedversion_0 = 0;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $m_temp2Pool27 = $parser + 424 | 0;
+ $9 = HEAP32[$m_encoding >> 2] | 0;
+ $10 = HEAP32[$versionend >> 2] | 0;
+ $minBytesPerChar = $9 + 64 | 0;
+ $11 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $idx_neg = -$11 | 0;
+ $add_ptr30 = $10 + $idx_neg | 0;
+ $call31 = _poolStoreString($m_temp2Pool27, $9, $8, $add_ptr30) | 0;
+ $tobool32 = ($call31 | 0) == 0;
+ if ($tobool32) {
+ $retval_0 = 1;
+ label = 28;
+ break;
+ } else {
+ $storedversion_0 = $call31;
+ label = 13;
+ break;
+ }
+ case 13:
+ $12 = HEAP32[$m_xmlDeclHandler >> 2] | 0;
+ $m_handlerArg = $parser + 4 | 0;
+ $13 = HEAP32[$m_handlerArg >> 2] | 0;
+ $14 = HEAP32[$standalone >> 2] | 0;
+ FUNCTION_TABLE_viiii[$12 & 1023]($13, $storedversion_0, $storedEncName_0, $14);
+ $storedversion_1 = $storedversion_0;
+ $storedEncName_1 = $storedEncName_0;
+ label = 16;
+ break;
+ case 14:
+ $m_defaultHandler = $parser + 80 | 0;
+ $15 = HEAP32[$m_defaultHandler >> 2] | 0;
+ $tobool38 = ($15 | 0) == 0;
+ if ($tobool38) {
+ $storedversion_1 = 0;
+ $storedEncName_1 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $16 = HEAP32[$m_encoding >> 2] | 0;
+ _reportDefault($parser, $16, $s, $next);
+ $storedversion_1 = 0;
+ $storedEncName_1 = 0;
+ label = 16;
+ break;
+ case 16:
+ $m_protocolEncodingName = $parser + 228 | 0;
+ $17 = HEAP32[$m_protocolEncodingName >> 2] | 0;
+ $cmp43 = ($17 | 0) == 0;
+ if ($cmp43) {
+ label = 17;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 17:
+ $18 = HEAP32[$newEncoding >> 2] | 0;
+ $tobool46 = ($18 | 0) == 0;
+ if ($tobool46) {
+ label = 21;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $minBytesPerChar48 = $18 + 64 | 0;
+ $19 = HEAP32[$minBytesPerChar48 >> 2] | 0;
+ $20 = HEAP32[$m_encoding >> 2] | 0;
+ $minBytesPerChar50 = $20 + 64 | 0;
+ $21 = HEAP32[$minBytesPerChar50 >> 2] | 0;
+ $cmp51 = ($19 | 0) == ($21 | 0);
+ if ($cmp51) {
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $22 = HEAP32[$encodingName >> 2] | 0;
+ HEAP32[$m_eventPtr >> 2] = $22;
+ $retval_0 = 19;
+ label = 28;
+ break;
+ case 20:
+ HEAP32[$m_encoding >> 2] = $18;
+ label = 26;
+ break;
+ case 21:
+ $23 = HEAP32[$encodingName >> 2] | 0;
+ $tobool58 = ($23 | 0) == 0;
+ if ($tobool58) {
+ label = 26;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $tobool60 = ($storedEncName_1 | 0) == 0;
+ if ($tobool60) {
+ label = 23;
+ break;
+ } else {
+ $storedEncName_2 = $storedEncName_1;
+ label = 24;
+ break;
+ }
+ case 23:
+ $m_temp2Pool62 = $parser + 424 | 0;
+ $24 = HEAP32[$m_encoding >> 2] | 0;
+ $nameLength65 = $24 + 28 | 0;
+ $25 = HEAP32[$nameLength65 >> 2] | 0;
+ $call67 = FUNCTION_TABLE_iii[$25 & 1023]($24, $23) | 0;
+ $add_ptr68 = $23 + $call67 | 0;
+ $call69 = _poolStoreString($m_temp2Pool62, $24, $23, $add_ptr68) | 0;
+ $tobool70 = ($call69 | 0) == 0;
+ if ($tobool70) {
+ $retval_0 = 1;
+ label = 28;
+ break;
+ } else {
+ $storedEncName_2 = $call69;
+ label = 24;
+ break;
+ }
+ case 24:
+ $call74 = _handleUnknownEncoding($parser, $storedEncName_2) | 0;
+ $m_temp2Pool75 = $parser + 424 | 0;
+ _poolClear($m_temp2Pool75);
+ $cmp76 = ($call74 | 0) == 18;
+ if ($cmp76) {
+ label = 25;
+ break;
+ } else {
+ $retval_0 = $call74;
+ label = 28;
+ break;
+ }
+ case 25:
+ $26 = HEAP32[$encodingName >> 2] | 0;
+ HEAP32[$m_eventPtr >> 2] = $26;
+ $retval_0 = 18;
+ label = 28;
+ break;
+ case 26:
+ $tobool84 = ($storedEncName_1 | 0) == 0;
+ $tobool85 = ($storedversion_1 | 0) == 0;
+ $or_cond = $tobool84 & $tobool85;
+ if ($or_cond) {
+ $retval_0 = 0;
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $m_temp2Pool87 = $parser + 424 | 0;
+ _poolClear($m_temp2Pool87);
+ $retval_0 = 0;
+ label = 28;
+ break;
+ case 28:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _externalEntityContentProcessor($parser, $start, $end, $endPtr) {
+ $parser = $parser | 0;
+ $start = $start | 0;
+ $end = $end | 0;
+ $endPtr = $endPtr | 0;
+ var $m_encoding = 0, $0 = 0, $finalBuffer = 0, $1 = 0, $lnot = 0, $conv = 0, $call = 0, $cmp = 0, $call2 = 0, $tobool3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_encoding = $parser + 144 | 0;
+ $0 = HEAP32[$m_encoding >> 2] | 0;
+ $finalBuffer = $parser + 468 | 0;
+ $1 = HEAP8[$finalBuffer] | 0;
+ $lnot = $1 << 24 >> 24 == 0;
+ $conv = $lnot & 1;
+ $call = _doContent($parser, 1, $0, $start, $end, $endPtr, $conv) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call2 = _storeRawNames($parser) | 0;
+ $tobool3 = $call2 << 24 >> 24 == 0;
+ if ($tobool3) {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $retval_0 = $call;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doContent($parser, $startTagLevel, $enc, $s, $end, $nextPtr, $haveMore) {
+ $parser = $parser | 0;
+ $startTagLevel = $startTagLevel | 0;
+ $enc = $enc | 0;
+ $s = $s | 0;
+ $end = $end | 0;
+ $nextPtr = $nextPtr | 0;
+ $haveMore = $haveMore | 0;
+ var $s_addr = 0, $next = 0, $c = 0, $ch = 0, $toPtr = 0, $fromPtr = 0, $bindings234 = 0, $name235 = 0, $buf416 = 0, $c432 = 0, $dataPtr = 0, $dataPtr509 = 0, $m_dtd = 0, $0 = 0, $m_encoding = 0, $1 = 0, $cmp = 0, $m_eventPtr = 0, $m_eventEndPtr = 0, $m_openInternalEntities = 0, $2 = 0, $internalEventPtr = 0, $internalEventEndPtr = 0, $eventEndPP_0 = 0, $eventPP_0 = 0, $3 = 0, $arrayidx = 0, $m_defaultHandler546 = 0, $parsing = 0, $predefinedEntityName = 0, $minBytesPerChar = 0, $pool = 0, $generalEntities = 0, $start = 0, $ptr = 0, $hasParamEntityRefs = 0, $m_externalEntityRefHandler = 0, $m_defaultHandler140 = 0, $m_externalEntityRefHandlerArg = 0, $start136 = 0, $ptr138 = 0, $m_defaultExpandInternalEntities = 0, $m_skippedEntityHandler104 = 0, $m_defaultHandler111 = 0, $m_handlerArg108 = 0, $standalone = 0, $m_skippedEntityHandler = 0, $m_defaultHandler87 = 0, $m_handlerArg85 = 0, $m_characterDataHandler44 = 0, $m_defaultHandler50 = 0, $m_handlerArg48 = 0, $m_freeTagList = 0, $malloc_fcn = 0, $m_tagStack = 0, $minBytesPerChar173 = 0, $nameLength = 0, $m_tagLevel177 = 0, $utf8Convert = 0, $realloc_fcn = 0, $m_startElementHandler = 0, $m_defaultHandler223 = 0, $m_tempPool228 = 0, $m_handlerArg219 = 0, $m_atts = 0, $minBytesPerChar231 = 0, $m_tempPool236 = 0, $nameLength237 = 0, $str241 = 0, $ptr247 = 0, $start249 = 0, $m_startElementHandler258 = 0, $m_endElementHandler = 0, $m_defaultHandler278 = 0, $m_tagLevel294 = 0, $m_endNamespaceDeclHandler = 0, $m_freeBindingList = 0, $m_handlerArg287 = 0, $m_handlerArg273 = 0, $m_handlerArg262 = 0, $m_atts264 = 0, $m_tagLevel301 = 0, $m_tagStack308 = 0, $m_freeTagList311 = 0, $minBytesPerChar314 = 0, $nameLength316 = 0, $m_endElementHandler329 = 0, $m_defaultHandler371 = 0, $m_ns = 0, $m_handlerArg367 = 0, $m_ns_triplets = 0, $m_namespaceSeparator = 0, $m_endNamespaceDeclHandler382 = 0, $m_freeBindingList393 = 0, $m_handlerArg386 = 0, $charRefNumber = 0, $m_characterDataHandler413 = 0, $m_defaultHandler422 = 0, $m_handlerArg418 = 0, $arraydecay = 0, $m_characterDataHandler429 = 0, $m_defaultHandler436 = 0, $m_handlerArg434 = 0, $m_startCdataSectionHandler = 0, $m_defaultHandler448 = 0, $m_handlerArg446 = 0, $m_characterDataHandler502 = 0, $m_defaultHandler531 = 0, $isUtf8505 = 0, $m_handlerArg525 = 0, $m_dataBuf510 = 0, $utf8Convert511 = 0, $m_dataBufEnd512 = 0, $m_handlerArg513 = 0, $4 = 0, $5 = 0, $call = 0, $6 = 0, $tobool = 0, $7 = 0, $m_characterDataHandler = 0, $8 = 0, $tobool4 = 0, $9 = 0, $m_handlerArg = 0, $10 = 0, $m_defaultHandler = 0, $11 = 0, $tobool8 = 0, $12 = 0, $cmp12 = 0, $m_tagLevel = 0, $13 = 0, $cmp15 = 0, $tobool19 = 0, $14 = 0, $cmp22 = 0, $m_tagLevel24 = 0, $15 = 0, $cmp25 = 0, $16 = 0, $17 = 0, $tobool31 = 0, $18 = 0, $tobool35 = 0, $19 = 0, $20 = 0, $21 = 0, $22 = 0, $add_ptr = 0, $23 = 0, $idx_neg = 0, $add_ptr40 = 0, $call41 = 0, $conv = 0, $tobool42 = 0, $24 = 0, $tobool45 = 0, $25 = 0, $26 = 0, $tobool51 = 0, $27 = 0, $28 = 0, $29 = 0, $30 = 0, $add_ptr57 = 0, $31 = 0, $idx_neg59 = 0, $add_ptr60 = 0, $call61 = 0, $tobool62 = 0, $call65 = 0, $32 = 0, $33 = 0, $34 = 0, $tobool68 = 0, $35 = 0, $tobool70 = 0, $tobool72 = 0, $is_internal = 0, $36 = 0, $tobool75 = 0, $tobool80 = 0, $37 = 0, $tobool82 = 0, $38 = 0, $39 = 0, $tobool88 = 0, $40 = 0, $41 = 0, $open = 0, $42 = 0, $43 = 0, $tobool94 = 0, $44 = 0, $45 = 0, $tobool97 = 0, $46 = 0, $47 = 0, $tobool100 = 0, $48 = 0, $tobool102 = 0, $49 = 0, $tobool105 = 0, $50 = 0, $name109 = 0, $51 = 0, $52 = 0, $tobool112 = 0, $53 = 0, $54 = 0, $call117 = 0, $cmp118 = 0, $55 = 0, $tobool123 = 0, $call126 = 0, $tobool128 = 0, $56 = 0, $57 = 0, $58 = 0, $59 = 0, $60 = 0, $61 = 0, $62 = 0, $63 = 0, $call132 = 0, $tobool133 = 0, $64 = 0, $65 = 0, $tobool141 = 0, $66 = 0, $67 = 0, $68 = 0, $tobool148 = 0, $parent = 0, $69 = 0, $70 = 0, $call154 = 0, $71 = 0, $tobool155 = 0, $72 = 0, $call160 = 0, $buf = 0, $73 = 0, $tobool162 = 0, $free_fcn = 0, $74 = 0, $add_ptr167 = 0, $bufEnd = 0, $75 = 0, $tag_0 = 0, $bindings = 0, $76 = 0, $parent169 = 0, $name171 = 0, $localPart = 0, $prefix = 0, $77 = 0, $78 = 0, $add_ptr174 = 0, $rawName = 0, $79 = 0, $call176 = 0, $rawNameLength = 0, $80 = 0, $inc = 0, $81 = 0, $82 = 0, $add_ptr180 = 0, $buf182 = 0, $83 = 0, $bufEnd184 = 0, $storemerge = 0, $84 = 0, $85 = 0, $add_ptr185 = 0, $86 = 0, $87 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $88 = 0, $cmp187 = 0, $strLen = 0, $89 = 0, $str = 0, $90 = 0, $91 = 0, $call212 = 0, $tobool213 = 0, $92 = 0, $sub_ptr_lhs_cast194 = 0, $sub_ptr_sub196 = 0, $shl = 0, $93 = 0, $call199 = 0, $cmp200 = 0, $add_ptr205 = 0, $add_ptr207 = 0, $94 = 0, $tobool216 = 0, $95 = 0, $96 = 0, $97 = 0, $98 = 0, $99 = 0, $tobool224 = 0, $100 = 0, $101 = 0, $102 = 0, $103 = 0, $add_ptr232 = 0, $104 = 0, $call238 = 0, $add_ptr232_sum = 0, $add_ptr239 = 0, $call240 = 0, $tobool243 = 0, $105 = 0, $106 = 0, $call250 = 0, $tobool251 = 0, $107 = 0, $108 = 0, $tobool259 = 0, $109 = 0, $110 = 0, $111 = 0, $112 = 0, $noElmHandlers_0 = 0, $113 = 0, $tobool266 = 0, $114 = 0, $tobool269 = 0, $115 = 0, $116 = 0, $117 = 0, $118 = 0, $tobool277 = 0, $119 = 0, $tobool279 = 0, $120 = 0, $121 = 0, $122 = 0, $tobool283334 = 0, $bindings234_promoted = 0, $123 = 0, $124 = 0, $125 = 0, $tobool284 = 0, $126 = 0, $prefix288 = 0, $127 = 0, $name289 = 0, $128 = 0, $nextTagBinding = 0, $129 = 0, $130 = 0, $nextTagBinding291 = 0, $prevPrefixBinding = 0, $131 = 0, $prefix293 = 0, $132 = 0, $binding = 0, $tobool283 = 0, $133 = 0, $cmp295 = 0, $134 = 0, $call298 = 0, $135 = 0, $cmp302 = 0, $136 = 0, $parent309 = 0, $137 = 0, $138 = 0, $139 = 0, $140 = 0, $mul = 0, $add_ptr315 = 0, $141 = 0, $call317 = 0, $rawNameLength318 = 0, $142 = 0, $cmp319 = 0, $rawName322 = 0, $143 = 0, $call323 = 0, $cmp324 = 0, $144 = 0, $dec = 0, $145 = 0, $tobool330 = 0, $name334 = 0, $localPart335 = 0, $146 = 0, $147 = 0, $tobool337 = 0, $tobool339 = 0, $or_cond = 0, $str342 = 0, $148 = 0, $uriLen = 0, $149 = 0, $add_ptr344 = 0, $150 = 0, $tobool346325 = 0, $151 = 0, $uri_0327 = 0, $localPart332_0326 = 0, $incdec_ptr = 0, $incdec_ptr348 = 0, $152 = 0, $tobool346 = 0, $uri_0_lcssa = 0, $prefix351 = 0, $153 = 0, $154 = 0, $tobool353 = 0, $tobool355 = 0, $or_cond323 = 0, $155 = 0, $uri_1328 = 0, $156 = 0, $tobool359329 = 0, $157 = 0, $uri_1331 = 0, $prefix333_0330 = 0, $incdec_ptr361 = 0, $uri_1 = 0, $158 = 0, $tobool359 = 0, $uri_2 = 0, $159 = 0, $160 = 0, $str369 = 0, $161 = 0, $162 = 0, $tobool372 = 0, $163 = 0, $164 = 0, $bindings377 = 0, $165 = 0, $tobool378333 = 0, $166 = 0, $167 = 0, $tobool383 = 0, $168 = 0, $prefix387 = 0, $169 = 0, $name388 = 0, $170 = 0, $171 = 0, $nextTagBinding391 = 0, $172 = 0, $173 = 0, $nextTagBinding394 = 0, $prevPrefixBinding396 = 0, $174 = 0, $prefix397 = 0, $175 = 0, $binding398 = 0, $176 = 0, $tobool378 = 0, $177 = 0, $cmp401 = 0, $178 = 0, $call404 = 0, $179 = 0, $180 = 0, $call408 = 0, $cmp409 = 0, $181 = 0, $tobool414 = 0, $182 = 0, $call420 = 0, $183 = 0, $tobool423 = 0, $184 = 0, $185 = 0, $186 = 0, $tobool430 = 0, $187 = 0, $188 = 0, $189 = 0, $tobool437 = 0, $190 = 0, $191 = 0, $192 = 0, $tobool443 = 0, $193 = 0, $194 = 0, $tobool449 = 0, $195 = 0, $196 = 0, $call453 = 0, $cmp454 = 0, $197 = 0, $tobool458 = 0, $m_processor = 0, $tobool463 = 0, $198 = 0, $m_characterDataHandler466 = 0, $199 = 0, $tobool467 = 0, $isUtf8 = 0, $200 = 0, $tobool469 = 0, $m_dataBuf = 0, $201 = 0, $utf8Convert471 = 0, $202 = 0, $m_dataBufEnd = 0, $203 = 0, $204 = 0, $m_handlerArg473 = 0, $205 = 0, $206 = 0, $207 = 0, $sub_ptr_lhs_cast476 = 0, $sub_ptr_rhs_cast477 = 0, $sub_ptr_sub478 = 0, $m_handlerArg481 = 0, $208 = 0, $209 = 0, $sub_ptr_lhs_cast482 = 0, $sub_ptr_rhs_cast483 = 0, $sub_ptr_sub484 = 0, $m_defaultHandler487 = 0, $210 = 0, $tobool488 = 0, $211 = 0, $cmp492 = 0, $m_tagLevel496 = 0, $212 = 0, $cmp497 = 0, $213 = 0, $tobool503 = 0, $214 = 0, $tobool506 = 0, $215 = 0, $216 = 0, $217 = 0, $218 = 0, $219 = 0, $220 = 0, $221 = 0, $222 = 0, $sub_ptr_lhs_cast516 = 0, $sub_ptr_rhs_cast517 = 0, $sub_ptr_sub518 = 0, $223 = 0, $224 = 0, $cmp519 = 0, $225 = 0, $226 = 0, $227 = 0, $sub_ptr_lhs_cast526 = 0, $sub_ptr_rhs_cast527 = 0, $sub_ptr_sub528 = 0, $228 = 0, $tobool532 = 0, $229 = 0, $230 = 0, $231 = 0, $232 = 0, $call537 = 0, $tobool538 = 0, $233 = 0, $234 = 0, $call542 = 0, $tobool543 = 0, $235 = 0, $tobool547 = 0, $236 = 0, $237 = 0, $238 = 0, $239 = 0, $240 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 112 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s_addr = __stackBase__ | 0;
+ $next = __stackBase__ + 8 | 0;
+ $c = __stackBase__ + 16 | 0;
+ $ch = __stackBase__ + 24 | 0;
+ $toPtr = __stackBase__ + 32 | 0;
+ $fromPtr = __stackBase__ + 40 | 0;
+ $bindings234 = __stackBase__ + 48 | 0;
+ $name235 = __stackBase__ + 56 | 0;
+ $buf416 = __stackBase__ + 80 | 0;
+ $c432 = __stackBase__ + 88 | 0;
+ $dataPtr = __stackBase__ + 96 | 0;
+ $dataPtr509 = __stackBase__ + 104 | 0;
+ HEAP32[$s_addr >> 2] = $s;
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $m_encoding = $parser + 144 | 0;
+ $1 = HEAP32[$m_encoding >> 2] | 0;
+ $cmp = ($1 | 0) == ($enc | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $m_eventPtr = $parser + 272 | 0;
+ $m_eventEndPtr = $parser + 276 | 0;
+ $eventPP_0 = $m_eventPtr;
+ $eventEndPP_0 = $m_eventEndPtr;
+ label = 5;
+ break;
+ case 4:
+ $m_openInternalEntities = $parser + 284 | 0;
+ $2 = HEAP32[$m_openInternalEntities >> 2] | 0;
+ $internalEventPtr = $2 | 0;
+ $internalEventEndPtr = $2 + 4 | 0;
+ $eventPP_0 = $internalEventPtr;
+ $eventEndPP_0 = $internalEventEndPtr;
+ label = 5;
+ break;
+ case 5:
+ $3 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$eventPP_0 >> 2] = $3;
+ $arrayidx = $enc + 4 | 0;
+ $m_defaultHandler546 = $parser + 80 | 0;
+ $parsing = $parser + 464 | 0;
+ $predefinedEntityName = $enc + 44 | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $pool = $0 + 80 | 0;
+ $generalEntities = $0 | 0;
+ $start = $0 + 96 | 0;
+ $ptr = $0 + 92 | 0;
+ $hasParamEntityRefs = $0 + 129 | 0;
+ $m_externalEntityRefHandler = $parser + 112 | 0;
+ $m_defaultHandler140 = $parser + 80 | 0;
+ $m_externalEntityRefHandlerArg = $parser + 116 | 0;
+ $start136 = $parser + 416 | 0;
+ $ptr138 = $parser + 412 | 0;
+ $m_defaultExpandInternalEntities = $parser + 292 | 0;
+ $m_skippedEntityHandler104 = $parser + 120 | 0;
+ $m_defaultHandler111 = $parser + 80 | 0;
+ $m_handlerArg108 = $parser + 4 | 0;
+ $standalone = $0 + 130 | 0;
+ $m_skippedEntityHandler = $parser + 120 | 0;
+ $m_defaultHandler87 = $parser + 80 | 0;
+ $m_handlerArg85 = $parser + 4 | 0;
+ $m_characterDataHandler44 = $parser + 60 | 0;
+ $m_defaultHandler50 = $parser + 80 | 0;
+ $m_handlerArg48 = $parser + 4 | 0;
+ $m_freeTagList = $parser + 352 | 0;
+ $malloc_fcn = $parser + 12 | 0;
+ $m_tagStack = $parser + 348 | 0;
+ $minBytesPerChar173 = $enc + 64 | 0;
+ $nameLength = $enc + 28 | 0;
+ $m_tagLevel177 = $parser + 296 | 0;
+ $utf8Convert = $enc + 56 | 0;
+ $realloc_fcn = $parser + 16 | 0;
+ $m_startElementHandler = $parser + 52 | 0;
+ $m_defaultHandler223 = $parser + 80 | 0;
+ $m_tempPool228 = $parser + 400 | 0;
+ $m_handlerArg219 = $parser + 4 | 0;
+ $m_atts = $parser + 376 | 0;
+ $minBytesPerChar231 = $enc + 64 | 0;
+ $m_tempPool236 = $parser + 400 | 0;
+ $nameLength237 = $enc + 28 | 0;
+ $str241 = $name235 | 0;
+ $ptr247 = $parser + 412 | 0;
+ $start249 = $parser + 416 | 0;
+ $m_startElementHandler258 = $parser + 52 | 0;
+ $m_endElementHandler = $parser + 56 | 0;
+ $m_defaultHandler278 = $parser + 80 | 0;
+ $m_tagLevel294 = $parser + 296 | 0;
+ $m_endNamespaceDeclHandler = $parser + 104 | 0;
+ $m_freeBindingList = $parser + 360 | 0;
+ $m_handlerArg287 = $parser + 4 | 0;
+ $m_handlerArg273 = $parser + 4 | 0;
+ $m_handlerArg262 = $parser + 4 | 0;
+ $m_atts264 = $parser + 376 | 0;
+ $m_tagLevel301 = $parser + 296 | 0;
+ $m_tagStack308 = $parser + 348 | 0;
+ $m_freeTagList311 = $parser + 352 | 0;
+ $minBytesPerChar314 = $enc + 64 | 0;
+ $nameLength316 = $enc + 28 | 0;
+ $m_endElementHandler329 = $parser + 56 | 0;
+ $m_defaultHandler371 = $parser + 80 | 0;
+ $m_ns = $parser + 232 | 0;
+ $m_handlerArg367 = $parser + 4 | 0;
+ $m_ns_triplets = $parser + 233 | 0;
+ $m_namespaceSeparator = $parser + 456 | 0;
+ $m_endNamespaceDeclHandler382 = $parser + 104 | 0;
+ $m_freeBindingList393 = $parser + 360 | 0;
+ $m_handlerArg386 = $parser + 4 | 0;
+ $charRefNumber = $enc + 40 | 0;
+ $m_characterDataHandler413 = $parser + 60 | 0;
+ $m_defaultHandler422 = $parser + 80 | 0;
+ $m_handlerArg418 = $parser + 4 | 0;
+ $arraydecay = $buf416 | 0;
+ $m_characterDataHandler429 = $parser + 60 | 0;
+ $m_defaultHandler436 = $parser + 80 | 0;
+ $m_handlerArg434 = $parser + 4 | 0;
+ $m_startCdataSectionHandler = $parser + 72 | 0;
+ $m_defaultHandler448 = $parser + 80 | 0;
+ $m_handlerArg446 = $parser + 4 | 0;
+ $m_characterDataHandler502 = $parser + 60 | 0;
+ $m_defaultHandler531 = $parser + 80 | 0;
+ $isUtf8505 = $enc + 68 | 0;
+ $m_handlerArg525 = $parser + 4 | 0;
+ $m_dataBuf510 = $parser + 44 | 0;
+ $utf8Convert511 = $enc + 56 | 0;
+ $m_dataBufEnd512 = $parser + 48 | 0;
+ $m_handlerArg513 = $parser + 4 | 0;
+ label = 6;
+ break;
+ case 6:
+ $4 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$next >> 2] = $4;
+ $5 = HEAP32[$arrayidx >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$5 & 1023]($enc, $4, $end, $next) | 0;
+ $6 = HEAP32[$next >> 2] | 0;
+ HEAP32[$eventEndPP_0 >> 2] = $6;
+ if (($call | 0) == (-3 | 0)) {
+ label = 7;
+ break;
+ } else if (($call | 0) == (-4 | 0)) {
+ label = 16;
+ break;
+ } else if (($call | 0) == 0) {
+ label = 21;
+ break;
+ } else if (($call | 0) == (-1 | 0)) {
+ label = 22;
+ break;
+ } else if (($call | 0) == (-2 | 0)) {
+ label = 24;
+ break;
+ } else if (($call | 0) == 9) {
+ label = 26;
+ break;
+ } else if (($call | 0) == 2 | ($call | 0) == 1) {
+ label = 56;
+ break;
+ } else if (($call | 0) == 4 | ($call | 0) == 3) {
+ label = 72;
+ break;
+ } else if (($call | 0) == 5) {
+ label = 91;
+ break;
+ } else if (($call | 0) == 10) {
+ label = 112;
+ break;
+ } else if (($call | 0) == 7) {
+ label = 117;
+ break;
+ } else if (($call | 0) == 8) {
+ label = 121;
+ break;
+ } else if (($call | 0) == (-5 | 0)) {
+ label = 128;
+ break;
+ } else if (($call | 0) == 6) {
+ label = 141;
+ break;
+ } else if (($call | 0) == 11) {
+ label = 148;
+ break;
+ } else if (($call | 0) == 13) {
+ label = 149;
+ break;
+ } else if (($call | 0) == 12) {
+ $retval_0 = 17;
+ label = 154;
+ break;
+ } else {
+ label = 150;
+ break;
+ }
+ case 7:
+ $tobool = $haveMore << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $7 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $7;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 9:
+ HEAP32[$eventEndPP_0 >> 2] = $end;
+ $m_characterDataHandler = $parser + 60 | 0;
+ $8 = HEAP32[$m_characterDataHandler >> 2] | 0;
+ $tobool4 = ($8 | 0) == 0;
+ if ($tobool4) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ HEAP8[$c] = 10;
+ $9 = HEAP32[$m_characterDataHandler >> 2] | 0;
+ $m_handlerArg = $parser + 4 | 0;
+ $10 = HEAP32[$m_handlerArg >> 2] | 0;
+ FUNCTION_TABLE_viii[$9 & 1023]($10, $c, 1);
+ label = 13;
+ break;
+ case 11:
+ $m_defaultHandler = $parser + 80 | 0;
+ $11 = HEAP32[$m_defaultHandler >> 2] | 0;
+ $tobool8 = ($11 | 0) == 0;
+ if ($tobool8) {
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $12 = HEAP32[$s_addr >> 2] | 0;
+ _reportDefault($parser, $enc, $12, $end);
+ label = 13;
+ break;
+ case 13:
+ $cmp12 = ($startTagLevel | 0) == 0;
+ if ($cmp12) {
+ $retval_0 = 3;
+ label = 154;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $m_tagLevel = $parser + 296 | 0;
+ $13 = HEAP32[$m_tagLevel >> 2] | 0;
+ $cmp15 = ($13 | 0) == ($startTagLevel | 0);
+ if ($cmp15) {
+ label = 15;
+ break;
+ } else {
+ $retval_0 = 13;
+ label = 154;
+ break;
+ }
+ case 15:
+ HEAP32[$nextPtr >> 2] = $end;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 16:
+ $tobool19 = $haveMore << 24 >> 24 == 0;
+ if ($tobool19) {
+ label = 18;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $14 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $14;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 18:
+ $cmp22 = ($startTagLevel | 0) > 0;
+ if ($cmp22) {
+ label = 19;
+ break;
+ } else {
+ $retval_0 = 3;
+ label = 154;
+ break;
+ }
+ case 19:
+ $m_tagLevel24 = $parser + 296 | 0;
+ $15 = HEAP32[$m_tagLevel24 >> 2] | 0;
+ $cmp25 = ($15 | 0) == ($startTagLevel | 0);
+ if ($cmp25) {
+ label = 20;
+ break;
+ } else {
+ $retval_0 = 13;
+ label = 154;
+ break;
+ }
+ case 20:
+ $16 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $16;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 21:
+ $17 = HEAP32[$next >> 2] | 0;
+ HEAP32[$eventPP_0 >> 2] = $17;
+ $retval_0 = 4;
+ label = 154;
+ break;
+ case 22:
+ $tobool31 = $haveMore << 24 >> 24 == 0;
+ if ($tobool31) {
+ $retval_0 = 5;
+ label = 154;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $18 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $18;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 24:
+ $tobool35 = $haveMore << 24 >> 24 == 0;
+ if ($tobool35) {
+ $retval_0 = 6;
+ label = 154;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $19 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $19;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 26:
+ $20 = HEAP32[$predefinedEntityName >> 2] | 0;
+ $21 = HEAP32[$s_addr >> 2] | 0;
+ $22 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr = $21 + $22 | 0;
+ $23 = HEAP32[$next >> 2] | 0;
+ $idx_neg = -$22 | 0;
+ $add_ptr40 = $23 + $idx_neg | 0;
+ $call41 = FUNCTION_TABLE_iiii[$20 & 1023]($enc, $add_ptr, $add_ptr40) | 0;
+ $conv = $call41 & 255;
+ HEAP8[$ch] = $conv;
+ $tobool42 = $conv << 24 >> 24 == 0;
+ if ($tobool42) {
+ label = 31;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $24 = HEAP32[$m_characterDataHandler44 >> 2] | 0;
+ $tobool45 = ($24 | 0) == 0;
+ if ($tobool45) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $25 = HEAP32[$m_handlerArg48 >> 2] | 0;
+ FUNCTION_TABLE_viii[$24 & 1023]($25, $ch, 1);
+ label = 152;
+ break;
+ case 29:
+ $26 = HEAP32[$m_defaultHandler50 >> 2] | 0;
+ $tobool51 = ($26 | 0) == 0;
+ if ($tobool51) {
+ label = 152;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $27 = HEAP32[$s_addr >> 2] | 0;
+ $28 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $27, $28);
+ label = 152;
+ break;
+ case 31:
+ $29 = HEAP32[$s_addr >> 2] | 0;
+ $30 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr57 = $29 + $30 | 0;
+ $31 = HEAP32[$next >> 2] | 0;
+ $idx_neg59 = -$30 | 0;
+ $add_ptr60 = $31 + $idx_neg59 | 0;
+ $call61 = _poolStoreString($pool, $enc, $add_ptr57, $add_ptr60) | 0;
+ $tobool62 = ($call61 | 0) == 0;
+ if ($tobool62) {
+ $retval_0 = 1;
+ label = 154;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $call65 = _lookup($parser, $generalEntities, $call61, 0) | 0;
+ $32 = $call65;
+ $33 = HEAP32[$start >> 2] | 0;
+ HEAP32[$ptr >> 2] = $33;
+ $34 = HEAP8[$hasParamEntityRefs] | 0;
+ $tobool68 = $34 << 24 >> 24 == 0;
+ if ($tobool68) {
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $35 = HEAP8[$standalone] | 0;
+ $tobool70 = $35 << 24 >> 24 == 0;
+ if ($tobool70) {
+ label = 36;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $tobool72 = ($call65 | 0) == 0;
+ if ($tobool72) {
+ $retval_0 = 11;
+ label = 154;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $is_internal = $32 + 34 | 0;
+ $36 = HEAP8[$is_internal] | 0;
+ $tobool75 = $36 << 24 >> 24 == 0;
+ if ($tobool75) {
+ $retval_0 = 24;
+ label = 154;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 36:
+ $tobool80 = ($call65 | 0) == 0;
+ if ($tobool80) {
+ label = 37;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 37:
+ $37 = HEAP32[$m_skippedEntityHandler >> 2] | 0;
+ $tobool82 = ($37 | 0) == 0;
+ if ($tobool82) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $38 = HEAP32[$m_handlerArg85 >> 2] | 0;
+ FUNCTION_TABLE_viii[$37 & 1023]($38, $call61, 0);
+ label = 152;
+ break;
+ case 39:
+ $39 = HEAP32[$m_defaultHandler87 >> 2] | 0;
+ $tobool88 = ($39 | 0) == 0;
+ if ($tobool88) {
+ label = 152;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $40 = HEAP32[$s_addr >> 2] | 0;
+ $41 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $40, $41);
+ label = 152;
+ break;
+ case 41:
+ $open = $call65 + 32 | 0;
+ $42 = $open;
+ $43 = HEAP8[$42] | 0;
+ $tobool94 = $43 << 24 >> 24 == 0;
+ if ($tobool94) {
+ label = 42;
+ break;
+ } else {
+ $retval_0 = 12;
+ label = 154;
+ break;
+ }
+ case 42:
+ $44 = $call65 + 28 | 0;
+ $45 = HEAP32[$44 >> 2] | 0;
+ $tobool97 = ($45 | 0) == 0;
+ if ($tobool97) {
+ label = 43;
+ break;
+ } else {
+ $retval_0 = 15;
+ label = 154;
+ break;
+ }
+ case 43:
+ $46 = $call65 + 4 | 0;
+ $47 = HEAP32[$46 >> 2] | 0;
+ $tobool100 = ($47 | 0) == 0;
+ if ($tobool100) {
+ label = 50;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $48 = HEAP8[$m_defaultExpandInternalEntities] | 0;
+ $tobool102 = $48 << 24 >> 24 == 0;
+ if ($tobool102) {
+ label = 45;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 45:
+ $49 = HEAP32[$m_skippedEntityHandler104 >> 2] | 0;
+ $tobool105 = ($49 | 0) == 0;
+ if ($tobool105) {
+ label = 47;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $50 = HEAP32[$m_handlerArg108 >> 2] | 0;
+ $name109 = $call65 | 0;
+ $51 = HEAP32[$name109 >> 2] | 0;
+ FUNCTION_TABLE_viii[$49 & 1023]($50, $51, 0);
+ label = 152;
+ break;
+ case 47:
+ $52 = HEAP32[$m_defaultHandler111 >> 2] | 0;
+ $tobool112 = ($52 | 0) == 0;
+ if ($tobool112) {
+ label = 152;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $53 = HEAP32[$s_addr >> 2] | 0;
+ $54 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $53, $54);
+ label = 152;
+ break;
+ case 49:
+ $call117 = _processInternalEntity($parser, $32) | 0;
+ $cmp118 = ($call117 | 0) == 0;
+ if ($cmp118) {
+ label = 152;
+ break;
+ } else {
+ $retval_0 = $call117;
+ label = 154;
+ break;
+ }
+ case 50:
+ $55 = HEAP32[$m_externalEntityRefHandler >> 2] | 0;
+ $tobool123 = ($55 | 0) == 0;
+ if ($tobool123) {
+ label = 54;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ HEAP8[$42] = 1;
+ $call126 = _getContext($parser) | 0;
+ HEAP8[$42] = 0;
+ $tobool128 = ($call126 | 0) == 0;
+ if ($tobool128) {
+ $retval_0 = 1;
+ label = 154;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $56 = HEAP32[$m_externalEntityRefHandler >> 2] | 0;
+ $57 = HEAP32[$m_externalEntityRefHandlerArg >> 2] | 0;
+ $58 = $call65 + 20 | 0;
+ $59 = HEAP32[$58 >> 2] | 0;
+ $60 = $call65 + 16 | 0;
+ $61 = HEAP32[$60 >> 2] | 0;
+ $62 = $call65 + 24 | 0;
+ $63 = HEAP32[$62 >> 2] | 0;
+ $call132 = FUNCTION_TABLE_iiiiii[$56 & 1023]($57, $call126, $59, $61, $63) | 0;
+ $tobool133 = ($call132 | 0) == 0;
+ if ($tobool133) {
+ $retval_0 = 21;
+ label = 154;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $64 = HEAP32[$start136 >> 2] | 0;
+ HEAP32[$ptr138 >> 2] = $64;
+ label = 152;
+ break;
+ case 54:
+ $65 = HEAP32[$m_defaultHandler140 >> 2] | 0;
+ $tobool141 = ($65 | 0) == 0;
+ if ($tobool141) {
+ label = 152;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ $66 = HEAP32[$s_addr >> 2] | 0;
+ $67 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $66, $67);
+ label = 152;
+ break;
+ case 56:
+ $68 = HEAP32[$m_freeTagList >> 2] | 0;
+ $tobool148 = ($68 | 0) == 0;
+ if ($tobool148) {
+ label = 58;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $parent = $68 | 0;
+ $69 = HEAP32[$parent >> 2] | 0;
+ HEAP32[$m_freeTagList >> 2] = $69;
+ $tag_0 = $68;
+ label = 62;
+ break;
+ case 58:
+ $70 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call154 = FUNCTION_TABLE_ii[$70 & 1023](48) | 0;
+ $71 = $call154;
+ $tobool155 = ($call154 | 0) == 0;
+ if ($tobool155) {
+ $retval_0 = 1;
+ label = 154;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ $72 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call160 = FUNCTION_TABLE_ii[$72 & 1023](32) | 0;
+ $buf = $call154 + 36 | 0;
+ $73 = $buf;
+ HEAP32[$73 >> 2] = $call160;
+ $tobool162 = ($call160 | 0) == 0;
+ if ($tobool162) {
+ label = 60;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 60:
+ $free_fcn = $parser + 20 | 0;
+ $74 = HEAP32[$free_fcn >> 2] | 0;
+ FUNCTION_TABLE_vi[$74 & 1023]($call154);
+ $retval_0 = 1;
+ label = 154;
+ break;
+ case 61:
+ $add_ptr167 = $call160 + 32 | 0;
+ $bufEnd = $call154 + 40 | 0;
+ $75 = $bufEnd;
+ HEAP32[$75 >> 2] = $add_ptr167;
+ $tag_0 = $71;
+ label = 62;
+ break;
+ case 62:
+ $bindings = $tag_0 + 44 | 0;
+ HEAP32[$bindings >> 2] = 0;
+ $76 = HEAP32[$m_tagStack >> 2] | 0;
+ $parent169 = $tag_0 | 0;
+ HEAP32[$parent169 >> 2] = $76;
+ HEAP32[$m_tagStack >> 2] = $tag_0;
+ $name171 = $tag_0 + 12 | 0;
+ $localPart = $tag_0 + 16 | 0;
+ HEAP32[$localPart >> 2] = 0;
+ $prefix = $tag_0 + 20 | 0;
+ HEAP32[$prefix >> 2] = 0;
+ $77 = HEAP32[$s_addr >> 2] | 0;
+ $78 = HEAP32[$minBytesPerChar173 >> 2] | 0;
+ $add_ptr174 = $77 + $78 | 0;
+ $rawName = $tag_0 + 4 | 0;
+ HEAP32[$rawName >> 2] = $add_ptr174;
+ $79 = HEAP32[$nameLength >> 2] | 0;
+ $call176 = FUNCTION_TABLE_iii[$79 & 1023]($enc, $add_ptr174) | 0;
+ $rawNameLength = $tag_0 + 8 | 0;
+ HEAP32[$rawNameLength >> 2] = $call176;
+ $80 = HEAP32[$m_tagLevel177 >> 2] | 0;
+ $inc = $80 + 1 | 0;
+ HEAP32[$m_tagLevel177 >> 2] = $inc;
+ $81 = HEAP32[$rawName >> 2] | 0;
+ $82 = HEAP32[$rawNameLength >> 2] | 0;
+ $add_ptr180 = $81 + $82 | 0;
+ HEAP32[$fromPtr >> 2] = $81;
+ $buf182 = $tag_0 + 36 | 0;
+ $83 = HEAP32[$buf182 >> 2] | 0;
+ $bufEnd184 = $tag_0 + 40 | 0;
+ $storemerge = $83;
+ label = 63;
+ break;
+ case 63:
+ HEAP32[$toPtr >> 2] = $storemerge;
+ $84 = HEAP32[$utf8Convert >> 2] | 0;
+ $85 = HEAP32[$bufEnd184 >> 2] | 0;
+ $add_ptr185 = $85 - 1 | 0;
+ FUNCTION_TABLE_viiiii[$84 & 1023]($enc, $fromPtr, $add_ptr180, $toPtr, $add_ptr185);
+ $86 = HEAP32[$toPtr >> 2] | 0;
+ $87 = HEAP32[$buf182 >> 2] | 0;
+ $sub_ptr_lhs_cast = $86;
+ $sub_ptr_rhs_cast = $87;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $88 = HEAP32[$fromPtr >> 2] | 0;
+ $cmp187 = ($88 | 0) == ($add_ptr180 | 0);
+ if ($cmp187) {
+ label = 64;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 64:
+ $strLen = $tag_0 + 24 | 0;
+ HEAP32[$strLen >> 2] = $sub_ptr_sub;
+ $89 = HEAP32[$buf182 >> 2] | 0;
+ $str = $name171 | 0;
+ HEAP32[$str >> 2] = $89;
+ $90 = HEAP32[$toPtr >> 2] | 0;
+ HEAP8[$90] = 0;
+ $91 = HEAP32[$s_addr >> 2] | 0;
+ $call212 = _storeAtts($parser, $enc, $91, $name171, $bindings) | 0;
+ $tobool213 = ($call212 | 0) == 0;
+ if ($tobool213) {
+ label = 67;
+ break;
+ } else {
+ $retval_0 = $call212;
+ label = 154;
+ break;
+ }
+ case 65:
+ $92 = HEAP32[$bufEnd184 >> 2] | 0;
+ $sub_ptr_lhs_cast194 = $92;
+ $sub_ptr_sub196 = $sub_ptr_lhs_cast194 - $sub_ptr_rhs_cast | 0;
+ $shl = $sub_ptr_sub196 << 1;
+ $93 = HEAP32[$realloc_fcn >> 2] | 0;
+ $call199 = FUNCTION_TABLE_iii[$93 & 1023]($87, $shl) | 0;
+ $cmp200 = ($call199 | 0) == 0;
+ if ($cmp200) {
+ $retval_0 = 1;
+ label = 154;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ HEAP32[$buf182 >> 2] = $call199;
+ $add_ptr205 = $call199 + $shl | 0;
+ HEAP32[$bufEnd184 >> 2] = $add_ptr205;
+ $add_ptr207 = $call199 + $sub_ptr_sub | 0;
+ $storemerge = $add_ptr207;
+ label = 63;
+ break;
+ case 67:
+ $94 = HEAP32[$m_startElementHandler >> 2] | 0;
+ $tobool216 = ($94 | 0) == 0;
+ if ($tobool216) {
+ label = 69;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $95 = HEAP32[$m_handlerArg219 >> 2] | 0;
+ $96 = HEAP32[$str >> 2] | 0;
+ $97 = HEAP32[$m_atts >> 2] | 0;
+ $98 = $97 | 0;
+ FUNCTION_TABLE_viii[$94 & 1023]($95, $96, $98);
+ label = 71;
+ break;
+ case 69:
+ $99 = HEAP32[$m_defaultHandler223 >> 2] | 0;
+ $tobool224 = ($99 | 0) == 0;
+ if ($tobool224) {
+ label = 71;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $100 = HEAP32[$s_addr >> 2] | 0;
+ $101 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $100, $101);
+ label = 71;
+ break;
+ case 71:
+ _poolClear($m_tempPool228);
+ label = 152;
+ break;
+ case 72:
+ $102 = HEAP32[$s_addr >> 2] | 0;
+ $103 = HEAP32[$minBytesPerChar231 >> 2] | 0;
+ $add_ptr232 = $102 + $103 | 0;
+ HEAP32[$bindings234 >> 2] = 0;
+ $104 = HEAP32[$nameLength237 >> 2] | 0;
+ $call238 = FUNCTION_TABLE_iii[$104 & 1023]($enc, $add_ptr232) | 0;
+ $add_ptr232_sum = $call238 + $103 | 0;
+ $add_ptr239 = $102 + $add_ptr232_sum | 0;
+ $call240 = _poolStoreString($m_tempPool236, $enc, $add_ptr232, $add_ptr239) | 0;
+ HEAP32[$str241 >> 2] = $call240;
+ $tobool243 = ($call240 | 0) == 0;
+ if ($tobool243) {
+ $retval_0 = 1;
+ label = 154;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $105 = HEAP32[$ptr247 >> 2] | 0;
+ HEAP32[$start249 >> 2] = $105;
+ $106 = HEAP32[$s_addr >> 2] | 0;
+ $call250 = _storeAtts($parser, $enc, $106, $name235, $bindings234) | 0;
+ $tobool251 = ($call250 | 0) == 0;
+ if ($tobool251) {
+ label = 74;
+ break;
+ } else {
+ $retval_0 = $call250;
+ label = 154;
+ break;
+ }
+ case 74:
+ $107 = HEAP32[$ptr247 >> 2] | 0;
+ HEAP32[$start249 >> 2] = $107;
+ $108 = HEAP32[$m_startElementHandler258 >> 2] | 0;
+ $tobool259 = ($108 | 0) == 0;
+ if ($tobool259) {
+ $noElmHandlers_0 = 1;
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $109 = HEAP32[$m_handlerArg262 >> 2] | 0;
+ $110 = HEAP32[$str241 >> 2] | 0;
+ $111 = HEAP32[$m_atts264 >> 2] | 0;
+ $112 = $111 | 0;
+ FUNCTION_TABLE_viii[$108 & 1023]($109, $110, $112);
+ $noElmHandlers_0 = 0;
+ label = 76;
+ break;
+ case 76:
+ $113 = HEAP32[$m_endElementHandler >> 2] | 0;
+ $tobool266 = ($113 | 0) == 0;
+ if ($tobool266) {
+ label = 80;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 77:
+ $114 = HEAP32[$m_startElementHandler258 >> 2] | 0;
+ $tobool269 = ($114 | 0) == 0;
+ if ($tobool269) {
+ label = 79;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $115 = HEAP32[$eventEndPP_0 >> 2] | 0;
+ HEAP32[$eventPP_0 >> 2] = $115;
+ label = 79;
+ break;
+ case 79:
+ $116 = HEAP32[$m_endElementHandler >> 2] | 0;
+ $117 = HEAP32[$m_handlerArg273 >> 2] | 0;
+ $118 = HEAP32[$str241 >> 2] | 0;
+ FUNCTION_TABLE_vii[$116 & 1023]($117, $118);
+ label = 83;
+ break;
+ case 80:
+ $tobool277 = $noElmHandlers_0 << 24 >> 24 == 0;
+ if ($tobool277) {
+ label = 83;
+ break;
+ } else {
+ label = 81;
+ break;
+ }
+ case 81:
+ $119 = HEAP32[$m_defaultHandler278 >> 2] | 0;
+ $tobool279 = ($119 | 0) == 0;
+ if ($tobool279) {
+ label = 83;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 82:
+ $120 = HEAP32[$s_addr >> 2] | 0;
+ $121 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $120, $121);
+ label = 83;
+ break;
+ case 83:
+ _poolClear($m_tempPool236);
+ $122 = HEAP32[$bindings234 >> 2] | 0;
+ $tobool283334 = ($122 | 0) == 0;
+ if ($tobool283334) {
+ label = 89;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 84:
+ $bindings234_promoted = HEAP32[$bindings234 >> 2] | 0;
+ $124 = $122;
+ $123 = $bindings234_promoted;
+ label = 85;
+ break;
+ case 85:
+ $125 = HEAP32[$m_endNamespaceDeclHandler >> 2] | 0;
+ $tobool284 = ($125 | 0) == 0;
+ if ($tobool284) {
+ label = 87;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 86:
+ $126 = HEAP32[$m_handlerArg287 >> 2] | 0;
+ $prefix288 = $124 | 0;
+ $127 = HEAP32[$prefix288 >> 2] | 0;
+ $name289 = $127 | 0;
+ $128 = HEAP32[$name289 >> 2] | 0;
+ FUNCTION_TABLE_vii[$125 & 1023]($126, $128);
+ label = 87;
+ break;
+ case 87:
+ $nextTagBinding = $123 + 4 | 0;
+ $129 = HEAP32[$nextTagBinding >> 2] | 0;
+ $130 = HEAP32[$m_freeBindingList >> 2] | 0;
+ $nextTagBinding291 = $124 + 4 | 0;
+ HEAP32[$nextTagBinding291 >> 2] = $130;
+ HEAP32[$m_freeBindingList >> 2] = $124;
+ $prevPrefixBinding = $124 + 8 | 0;
+ $131 = HEAP32[$prevPrefixBinding >> 2] | 0;
+ $prefix293 = $124 | 0;
+ $132 = HEAP32[$prefix293 >> 2] | 0;
+ $binding = $132 + 4 | 0;
+ HEAP32[$binding >> 2] = $131;
+ $tobool283 = ($129 | 0) == 0;
+ if ($tobool283) {
+ label = 88;
+ break;
+ } else {
+ $124 = $129;
+ $123 = $129;
+ label = 85;
+ break;
+ }
+ case 88:
+ HEAP32[$bindings234 >> 2] = $129;
+ label = 89;
+ break;
+ case 89:
+ $133 = HEAP32[$m_tagLevel294 >> 2] | 0;
+ $cmp295 = ($133 | 0) == 0;
+ if ($cmp295) {
+ label = 90;
+ break;
+ } else {
+ label = 152;
+ break;
+ }
+ case 90:
+ $134 = HEAP32[$next >> 2] | 0;
+ $call298 = _epilogProcessor($parser, $134, $end, $nextPtr) | 0;
+ $retval_0 = $call298;
+ label = 154;
+ break;
+ case 91:
+ $135 = HEAP32[$m_tagLevel301 >> 2] | 0;
+ $cmp302 = ($135 | 0) == ($startTagLevel | 0);
+ if ($cmp302) {
+ $retval_0 = 13;
+ label = 154;
+ break;
+ } else {
+ label = 92;
+ break;
+ }
+ case 92:
+ $136 = HEAP32[$m_tagStack308 >> 2] | 0;
+ $parent309 = $136 | 0;
+ $137 = HEAP32[$parent309 >> 2] | 0;
+ HEAP32[$m_tagStack308 >> 2] = $137;
+ $138 = HEAP32[$m_freeTagList311 >> 2] | 0;
+ HEAP32[$parent309 >> 2] = $138;
+ HEAP32[$m_freeTagList311 >> 2] = $136;
+ $139 = HEAP32[$s_addr >> 2] | 0;
+ $140 = HEAP32[$minBytesPerChar314 >> 2] | 0;
+ $mul = $140 << 1;
+ $add_ptr315 = $139 + $mul | 0;
+ $141 = HEAP32[$nameLength316 >> 2] | 0;
+ $call317 = FUNCTION_TABLE_iii[$141 & 1023]($enc, $add_ptr315) | 0;
+ $rawNameLength318 = $136 + 8 | 0;
+ $142 = HEAP32[$rawNameLength318 >> 2] | 0;
+ $cmp319 = ($call317 | 0) == ($142 | 0);
+ if ($cmp319) {
+ label = 93;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 93:
+ $rawName322 = $136 + 4 | 0;
+ $143 = HEAP32[$rawName322 >> 2] | 0;
+ $call323 = _memcmp($143 | 0, $add_ptr315 | 0, $call317 | 0) | 0;
+ $cmp324 = ($call323 | 0) == 0;
+ if ($cmp324) {
+ label = 95;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 94:
+ HEAP32[$eventPP_0 >> 2] = $add_ptr315;
+ $retval_0 = 7;
+ label = 154;
+ break;
+ case 95:
+ $144 = HEAP32[$m_tagLevel301 >> 2] | 0;
+ $dec = $144 - 1 | 0;
+ HEAP32[$m_tagLevel301 >> 2] = $dec;
+ $145 = HEAP32[$m_endElementHandler329 >> 2] | 0;
+ $tobool330 = ($145 | 0) == 0;
+ if ($tobool330) {
+ label = 104;
+ break;
+ } else {
+ label = 96;
+ break;
+ }
+ case 96:
+ $name334 = $136 + 12 | 0;
+ $localPart335 = $136 + 16 | 0;
+ $146 = HEAP32[$localPart335 >> 2] | 0;
+ $147 = HEAP8[$m_ns] | 0;
+ $tobool337 = $147 << 24 >> 24 == 0;
+ $tobool339 = ($146 | 0) == 0;
+ $or_cond = $tobool337 | $tobool339;
+ if ($or_cond) {
+ label = 103;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 97:
+ $str342 = $name334 | 0;
+ $148 = HEAP32[$str342 >> 2] | 0;
+ $uriLen = $136 + 28 | 0;
+ $149 = HEAP32[$uriLen >> 2] | 0;
+ $add_ptr344 = $148 + $149 | 0;
+ $150 = HEAP8[$146] | 0;
+ $tobool346325 = $150 << 24 >> 24 == 0;
+ if ($tobool346325) {
+ $uri_0_lcssa = $add_ptr344;
+ label = 99;
+ break;
+ } else {
+ $localPart332_0326 = $146;
+ $uri_0327 = $add_ptr344;
+ $151 = $150;
+ label = 98;
+ break;
+ }
+ case 98:
+ $incdec_ptr = $localPart332_0326 + 1 | 0;
+ $incdec_ptr348 = $uri_0327 + 1 | 0;
+ HEAP8[$uri_0327] = $151;
+ $152 = HEAP8[$incdec_ptr] | 0;
+ $tobool346 = $152 << 24 >> 24 == 0;
+ if ($tobool346) {
+ $uri_0_lcssa = $incdec_ptr348;
+ label = 99;
+ break;
+ } else {
+ $localPart332_0326 = $incdec_ptr;
+ $uri_0327 = $incdec_ptr348;
+ $151 = $152;
+ label = 98;
+ break;
+ }
+ case 99:
+ $prefix351 = $136 + 20 | 0;
+ $153 = HEAP32[$prefix351 >> 2] | 0;
+ $154 = HEAP8[$m_ns_triplets] | 0;
+ $tobool353 = $154 << 24 >> 24 == 0;
+ $tobool355 = ($153 | 0) == 0;
+ $or_cond323 = $tobool353 | $tobool355;
+ if ($or_cond323) {
+ $uri_2 = $uri_0_lcssa;
+ label = 102;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 100:
+ $155 = HEAP8[$m_namespaceSeparator] | 0;
+ HEAP8[$uri_0_lcssa] = $155;
+ $uri_1328 = $uri_0_lcssa + 1 | 0;
+ $156 = HEAP8[$153] | 0;
+ $tobool359329 = $156 << 24 >> 24 == 0;
+ if ($tobool359329) {
+ $uri_2 = $uri_1328;
+ label = 102;
+ break;
+ } else {
+ $prefix333_0330 = $153;
+ $uri_1331 = $uri_1328;
+ $157 = $156;
+ label = 101;
+ break;
+ }
+ case 101:
+ $incdec_ptr361 = $prefix333_0330 + 1 | 0;
+ HEAP8[$uri_1331] = $157;
+ $uri_1 = $uri_1331 + 1 | 0;
+ $158 = HEAP8[$incdec_ptr361] | 0;
+ $tobool359 = $158 << 24 >> 24 == 0;
+ if ($tobool359) {
+ $uri_2 = $uri_1;
+ label = 102;
+ break;
+ } else {
+ $prefix333_0330 = $incdec_ptr361;
+ $uri_1331 = $uri_1;
+ $157 = $158;
+ label = 101;
+ break;
+ }
+ case 102:
+ HEAP8[$uri_2] = 0;
+ label = 103;
+ break;
+ case 103:
+ $159 = HEAP32[$m_endElementHandler329 >> 2] | 0;
+ $160 = HEAP32[$m_handlerArg367 >> 2] | 0;
+ $str369 = $name334 | 0;
+ $161 = HEAP32[$str369 >> 2] | 0;
+ FUNCTION_TABLE_vii[$159 & 1023]($160, $161);
+ label = 106;
+ break;
+ case 104:
+ $162 = HEAP32[$m_defaultHandler371 >> 2] | 0;
+ $tobool372 = ($162 | 0) == 0;
+ if ($tobool372) {
+ label = 106;
+ break;
+ } else {
+ label = 105;
+ break;
+ }
+ case 105:
+ $163 = HEAP32[$s_addr >> 2] | 0;
+ $164 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $163, $164);
+ label = 106;
+ break;
+ case 106:
+ $bindings377 = $136 + 44 | 0;
+ $165 = HEAP32[$bindings377 >> 2] | 0;
+ $tobool378333 = ($165 | 0) == 0;
+ if ($tobool378333) {
+ label = 110;
+ break;
+ } else {
+ $166 = $165;
+ label = 107;
+ break;
+ }
+ case 107:
+ $167 = HEAP32[$m_endNamespaceDeclHandler382 >> 2] | 0;
+ $tobool383 = ($167 | 0) == 0;
+ if ($tobool383) {
+ label = 109;
+ break;
+ } else {
+ label = 108;
+ break;
+ }
+ case 108:
+ $168 = HEAP32[$m_handlerArg386 >> 2] | 0;
+ $prefix387 = $166 | 0;
+ $169 = HEAP32[$prefix387 >> 2] | 0;
+ $name388 = $169 | 0;
+ $170 = HEAP32[$name388 >> 2] | 0;
+ FUNCTION_TABLE_vii[$167 & 1023]($168, $170);
+ label = 109;
+ break;
+ case 109:
+ $171 = HEAP32[$bindings377 >> 2] | 0;
+ $nextTagBinding391 = $171 + 4 | 0;
+ $172 = HEAP32[$nextTagBinding391 >> 2] | 0;
+ HEAP32[$bindings377 >> 2] = $172;
+ $173 = HEAP32[$m_freeBindingList393 >> 2] | 0;
+ $nextTagBinding394 = $166 + 4 | 0;
+ HEAP32[$nextTagBinding394 >> 2] = $173;
+ HEAP32[$m_freeBindingList393 >> 2] = $166;
+ $prevPrefixBinding396 = $166 + 8 | 0;
+ $174 = HEAP32[$prevPrefixBinding396 >> 2] | 0;
+ $prefix397 = $166 | 0;
+ $175 = HEAP32[$prefix397 >> 2] | 0;
+ $binding398 = $175 + 4 | 0;
+ HEAP32[$binding398 >> 2] = $174;
+ $176 = HEAP32[$bindings377 >> 2] | 0;
+ $tobool378 = ($176 | 0) == 0;
+ if ($tobool378) {
+ label = 110;
+ break;
+ } else {
+ $166 = $176;
+ label = 107;
+ break;
+ }
+ case 110:
+ $177 = HEAP32[$m_tagLevel301 >> 2] | 0;
+ $cmp401 = ($177 | 0) == 0;
+ if ($cmp401) {
+ label = 111;
+ break;
+ } else {
+ label = 152;
+ break;
+ }
+ case 111:
+ $178 = HEAP32[$next >> 2] | 0;
+ $call404 = _epilogProcessor($parser, $178, $end, $nextPtr) | 0;
+ $retval_0 = $call404;
+ label = 154;
+ break;
+ case 112:
+ $179 = HEAP32[$charRefNumber >> 2] | 0;
+ $180 = HEAP32[$s_addr >> 2] | 0;
+ $call408 = FUNCTION_TABLE_iii[$179 & 1023]($enc, $180) | 0;
+ $cmp409 = ($call408 | 0) < 0;
+ if ($cmp409) {
+ $retval_0 = 14;
+ label = 154;
+ break;
+ } else {
+ label = 113;
+ break;
+ }
+ case 113:
+ $181 = HEAP32[$m_characterDataHandler413 >> 2] | 0;
+ $tobool414 = ($181 | 0) == 0;
+ if ($tobool414) {
+ label = 115;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 114:
+ $182 = HEAP32[$m_handlerArg418 >> 2] | 0;
+ $call420 = _XmlUtf8Encode($call408, $arraydecay) | 0;
+ FUNCTION_TABLE_viii[$181 & 1023]($182, $arraydecay, $call420);
+ label = 152;
+ break;
+ case 115:
+ $183 = HEAP32[$m_defaultHandler422 >> 2] | 0;
+ $tobool423 = ($183 | 0) == 0;
+ if ($tobool423) {
+ label = 152;
+ break;
+ } else {
+ label = 116;
+ break;
+ }
+ case 116:
+ $184 = HEAP32[$s_addr >> 2] | 0;
+ $185 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $184, $185);
+ label = 152;
+ break;
+ case 117:
+ $186 = HEAP32[$m_characterDataHandler429 >> 2] | 0;
+ $tobool430 = ($186 | 0) == 0;
+ if ($tobool430) {
+ label = 119;
+ break;
+ } else {
+ label = 118;
+ break;
+ }
+ case 118:
+ HEAP8[$c432] = 10;
+ $187 = HEAP32[$m_characterDataHandler429 >> 2] | 0;
+ $188 = HEAP32[$m_handlerArg434 >> 2] | 0;
+ FUNCTION_TABLE_viii[$187 & 1023]($188, $c432, 1);
+ label = 152;
+ break;
+ case 119:
+ $189 = HEAP32[$m_defaultHandler436 >> 2] | 0;
+ $tobool437 = ($189 | 0) == 0;
+ if ($tobool437) {
+ label = 152;
+ break;
+ } else {
+ label = 120;
+ break;
+ }
+ case 120:
+ $190 = HEAP32[$s_addr >> 2] | 0;
+ $191 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $190, $191);
+ label = 152;
+ break;
+ case 121:
+ $192 = HEAP32[$m_startCdataSectionHandler >> 2] | 0;
+ $tobool443 = ($192 | 0) == 0;
+ if ($tobool443) {
+ label = 123;
+ break;
+ } else {
+ label = 122;
+ break;
+ }
+ case 122:
+ $193 = HEAP32[$m_handlerArg446 >> 2] | 0;
+ FUNCTION_TABLE_vi[$192 & 1023]($193);
+ label = 125;
+ break;
+ case 123:
+ $194 = HEAP32[$m_defaultHandler448 >> 2] | 0;
+ $tobool449 = ($194 | 0) == 0;
+ if ($tobool449) {
+ label = 125;
+ break;
+ } else {
+ label = 124;
+ break;
+ }
+ case 124:
+ $195 = HEAP32[$s_addr >> 2] | 0;
+ $196 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $195, $196);
+ label = 125;
+ break;
+ case 125:
+ $call453 = _doCdataSection($parser, $enc, $next, $end, $nextPtr, $haveMore) | 0;
+ $cmp454 = ($call453 | 0) == 0;
+ if ($cmp454) {
+ label = 126;
+ break;
+ } else {
+ $retval_0 = $call453;
+ label = 154;
+ break;
+ }
+ case 126:
+ $197 = HEAP32[$next >> 2] | 0;
+ $tobool458 = ($197 | 0) == 0;
+ if ($tobool458) {
+ label = 127;
+ break;
+ } else {
+ label = 152;
+ break;
+ }
+ case 127:
+ $m_processor = $parser + 264 | 0;
+ HEAP32[$m_processor >> 2] = 80;
+ $retval_0 = $call453;
+ label = 154;
+ break;
+ case 128:
+ $tobool463 = $haveMore << 24 >> 24 == 0;
+ if ($tobool463) {
+ label = 130;
+ break;
+ } else {
+ label = 129;
+ break;
+ }
+ case 129:
+ $198 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $198;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 130:
+ $m_characterDataHandler466 = $parser + 60 | 0;
+ $199 = HEAP32[$m_characterDataHandler466 >> 2] | 0;
+ $tobool467 = ($199 | 0) == 0;
+ if ($tobool467) {
+ label = 134;
+ break;
+ } else {
+ label = 131;
+ break;
+ }
+ case 131:
+ $isUtf8 = $enc + 68 | 0;
+ $200 = HEAP8[$isUtf8] | 0;
+ $tobool469 = $200 << 24 >> 24 == 0;
+ if ($tobool469) {
+ label = 132;
+ break;
+ } else {
+ label = 133;
+ break;
+ }
+ case 132:
+ $m_dataBuf = $parser + 44 | 0;
+ $201 = HEAP32[$m_dataBuf >> 2] | 0;
+ HEAP32[$dataPtr >> 2] = $201;
+ $utf8Convert471 = $enc + 56 | 0;
+ $202 = HEAP32[$utf8Convert471 >> 2] | 0;
+ $m_dataBufEnd = $parser + 48 | 0;
+ $203 = HEAP32[$m_dataBufEnd >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$202 & 1023]($enc, $s_addr, $end, $dataPtr, $203);
+ $204 = HEAP32[$m_characterDataHandler466 >> 2] | 0;
+ $m_handlerArg473 = $parser + 4 | 0;
+ $205 = HEAP32[$m_handlerArg473 >> 2] | 0;
+ $206 = HEAP32[$m_dataBuf >> 2] | 0;
+ $207 = HEAP32[$dataPtr >> 2] | 0;
+ $sub_ptr_lhs_cast476 = $207;
+ $sub_ptr_rhs_cast477 = $206;
+ $sub_ptr_sub478 = $sub_ptr_lhs_cast476 - $sub_ptr_rhs_cast477 | 0;
+ FUNCTION_TABLE_viii[$204 & 1023]($205, $206, $sub_ptr_sub478);
+ label = 136;
+ break;
+ case 133:
+ $m_handlerArg481 = $parser + 4 | 0;
+ $208 = HEAP32[$m_handlerArg481 >> 2] | 0;
+ $209 = HEAP32[$s_addr >> 2] | 0;
+ $sub_ptr_lhs_cast482 = $end;
+ $sub_ptr_rhs_cast483 = $209;
+ $sub_ptr_sub484 = $sub_ptr_lhs_cast482 - $sub_ptr_rhs_cast483 | 0;
+ FUNCTION_TABLE_viii[$199 & 1023]($208, $209, $sub_ptr_sub484);
+ label = 136;
+ break;
+ case 134:
+ $m_defaultHandler487 = $parser + 80 | 0;
+ $210 = HEAP32[$m_defaultHandler487 >> 2] | 0;
+ $tobool488 = ($210 | 0) == 0;
+ if ($tobool488) {
+ label = 136;
+ break;
+ } else {
+ label = 135;
+ break;
+ }
+ case 135:
+ $211 = HEAP32[$s_addr >> 2] | 0;
+ _reportDefault($parser, $enc, $211, $end);
+ label = 136;
+ break;
+ case 136:
+ $cmp492 = ($startTagLevel | 0) == 0;
+ if ($cmp492) {
+ label = 137;
+ break;
+ } else {
+ label = 138;
+ break;
+ }
+ case 137:
+ HEAP32[$eventPP_0 >> 2] = $end;
+ $retval_0 = 3;
+ label = 154;
+ break;
+ case 138:
+ $m_tagLevel496 = $parser + 296 | 0;
+ $212 = HEAP32[$m_tagLevel496 >> 2] | 0;
+ $cmp497 = ($212 | 0) == ($startTagLevel | 0);
+ if ($cmp497) {
+ label = 140;
+ break;
+ } else {
+ label = 139;
+ break;
+ }
+ case 139:
+ HEAP32[$eventPP_0 >> 2] = $end;
+ $retval_0 = 13;
+ label = 154;
+ break;
+ case 140:
+ HEAP32[$nextPtr >> 2] = $end;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 141:
+ $213 = HEAP32[$m_characterDataHandler502 >> 2] | 0;
+ $tobool503 = ($213 | 0) == 0;
+ if ($tobool503) {
+ label = 146;
+ break;
+ } else {
+ label = 142;
+ break;
+ }
+ case 142:
+ $214 = HEAP8[$isUtf8505] | 0;
+ $tobool506 = $214 << 24 >> 24 == 0;
+ if ($tobool506) {
+ label = 143;
+ break;
+ } else {
+ label = 145;
+ break;
+ }
+ case 143:
+ $215 = HEAP32[$m_dataBuf510 >> 2] | 0;
+ HEAP32[$dataPtr509 >> 2] = $215;
+ $216 = HEAP32[$utf8Convert511 >> 2] | 0;
+ $217 = HEAP32[$next >> 2] | 0;
+ $218 = HEAP32[$m_dataBufEnd512 >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$216 & 1023]($enc, $s_addr, $217, $dataPtr509, $218);
+ $219 = HEAP32[$s_addr >> 2] | 0;
+ HEAP32[$eventEndPP_0 >> 2] = $219;
+ $220 = HEAP32[$m_handlerArg513 >> 2] | 0;
+ $221 = HEAP32[$m_dataBuf510 >> 2] | 0;
+ $222 = HEAP32[$dataPtr509 >> 2] | 0;
+ $sub_ptr_lhs_cast516 = $222;
+ $sub_ptr_rhs_cast517 = $221;
+ $sub_ptr_sub518 = $sub_ptr_lhs_cast516 - $sub_ptr_rhs_cast517 | 0;
+ FUNCTION_TABLE_viii[$213 & 1023]($220, $221, $sub_ptr_sub518);
+ $223 = HEAP32[$s_addr >> 2] | 0;
+ $224 = HEAP32[$next >> 2] | 0;
+ $cmp519 = ($223 | 0) == ($224 | 0);
+ if ($cmp519) {
+ label = 152;
+ break;
+ } else {
+ label = 144;
+ break;
+ }
+ case 144:
+ HEAP32[$eventPP_0 >> 2] = $223;
+ label = 143;
+ break;
+ case 145:
+ $225 = HEAP32[$m_handlerArg525 >> 2] | 0;
+ $226 = HEAP32[$s_addr >> 2] | 0;
+ $227 = HEAP32[$next >> 2] | 0;
+ $sub_ptr_lhs_cast526 = $227;
+ $sub_ptr_rhs_cast527 = $226;
+ $sub_ptr_sub528 = $sub_ptr_lhs_cast526 - $sub_ptr_rhs_cast527 | 0;
+ FUNCTION_TABLE_viii[$213 & 1023]($225, $226, $sub_ptr_sub528);
+ label = 152;
+ break;
+ case 146:
+ $228 = HEAP32[$m_defaultHandler531 >> 2] | 0;
+ $tobool532 = ($228 | 0) == 0;
+ if ($tobool532) {
+ label = 152;
+ break;
+ } else {
+ label = 147;
+ break;
+ }
+ case 147:
+ $229 = HEAP32[$s_addr >> 2] | 0;
+ $230 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $229, $230);
+ label = 152;
+ break;
+ case 148:
+ $231 = HEAP32[$s_addr >> 2] | 0;
+ $232 = HEAP32[$next >> 2] | 0;
+ $call537 = _reportProcessingInstruction($parser, $enc, $231, $232) | 0;
+ $tobool538 = ($call537 | 0) == 0;
+ if ($tobool538) {
+ $retval_0 = 1;
+ label = 154;
+ break;
+ } else {
+ label = 152;
+ break;
+ }
+ case 149:
+ $233 = HEAP32[$s_addr >> 2] | 0;
+ $234 = HEAP32[$next >> 2] | 0;
+ $call542 = _reportComment($parser, $enc, $233, $234) | 0;
+ $tobool543 = ($call542 | 0) == 0;
+ if ($tobool543) {
+ $retval_0 = 1;
+ label = 154;
+ break;
+ } else {
+ label = 152;
+ break;
+ }
+ case 150:
+ $235 = HEAP32[$m_defaultHandler546 >> 2] | 0;
+ $tobool547 = ($235 | 0) == 0;
+ if ($tobool547) {
+ label = 152;
+ break;
+ } else {
+ label = 151;
+ break;
+ }
+ case 151:
+ $236 = HEAP32[$s_addr >> 2] | 0;
+ $237 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $236, $237);
+ label = 152;
+ break;
+ case 152:
+ $238 = HEAP32[$next >> 2] | 0;
+ HEAP32[$s_addr >> 2] = $238;
+ HEAP32[$eventPP_0 >> 2] = $238;
+ $239 = HEAP32[$parsing >> 2] | 0;
+ if (($239 | 0) == 3) {
+ label = 153;
+ break;
+ } else if (($239 | 0) == 2) {
+ $retval_0 = 35;
+ label = 154;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 153:
+ $240 = HEAP32[$next >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $240;
+ $retval_0 = 0;
+ label = 154;
+ break;
+ case 154:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _storeRawNames($parser) {
+ $parser = $parser | 0;
+ var $m_tagStack = 0, $realloc_fcn = 0, $tag_033 = 0, $tobool34 = 0, $tag_035 = 0, $strLen = 0, $0 = 0, $add = 0, $buf = 0, $1 = 0, $add_ptr = 0, $rawName = 0, $2 = 0, $cmp = 0, $rawNameLength = 0, $3 = 0, $add2 = 0, $bufEnd = 0, $4 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp4 = 0, $5 = 0, $call = 0, $cmp7 = 0, $str = 0, $6 = 0, $7 = 0, $cmp12 = 0, $localPart = 0, $8 = 0, $tobool18 = 0, $9 = 0, $sub_ptr_lhs_cast23 = 0, $sub_ptr_rhs_cast24 = 0, $sub_ptr_sub25 = 0, $add_ptr26 = 0, $add_ptr31 = 0, $add_ptr33 = 0, $rawNameBuf_0 = 0, $10 = 0, $11 = 0, $parent = 0, $tag_0 = 0, $tobool = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_tagStack = $parser + 348 | 0;
+ $realloc_fcn = $parser + 16 | 0;
+ $tag_033 = HEAP32[$m_tagStack >> 2] | 0;
+ $tobool34 = ($tag_033 | 0) == 0;
+ if ($tobool34) {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ } else {
+ $tag_035 = $tag_033;
+ label = 3;
+ break;
+ }
+ case 3:
+ $strLen = $tag_035 + 24 | 0;
+ $0 = HEAP32[$strLen >> 2] | 0;
+ $add = $0 + 1 | 0;
+ $buf = $tag_035 + 36 | 0;
+ $1 = HEAP32[$buf >> 2] | 0;
+ $add_ptr = $1 + $add | 0;
+ $rawName = $tag_035 + 4 | 0;
+ $2 = HEAP32[$rawName >> 2] | 0;
+ $cmp = ($2 | 0) == ($add_ptr | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $rawNameLength = $tag_035 + 8 | 0;
+ $3 = HEAP32[$rawNameLength >> 2] | 0;
+ $add2 = $3 + $add | 0;
+ $bufEnd = $tag_035 + 40 | 0;
+ $4 = HEAP32[$bufEnd >> 2] | 0;
+ $sub_ptr_lhs_cast = $4;
+ $sub_ptr_rhs_cast = $1;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp4 = ($add2 | 0) > ($sub_ptr_sub | 0);
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ $rawNameBuf_0 = $add_ptr;
+ label = 11;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[$realloc_fcn >> 2] | 0;
+ $call = FUNCTION_TABLE_iii[$5 & 1023]($1, $add2) | 0;
+ $cmp7 = ($call | 0) == 0;
+ if ($cmp7) {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $str = $tag_035 + 12 | 0;
+ $6 = HEAP32[$str >> 2] | 0;
+ $7 = HEAP32[$buf >> 2] | 0;
+ $cmp12 = ($6 | 0) == ($7 | 0);
+ if ($cmp12) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$str >> 2] = $call;
+ label = 8;
+ break;
+ case 8:
+ $localPart = $tag_035 + 16 | 0;
+ $8 = HEAP32[$localPart >> 2] | 0;
+ $tobool18 = ($8 | 0) == 0;
+ if ($tobool18) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $9 = HEAP32[$buf >> 2] | 0;
+ $sub_ptr_lhs_cast23 = $8;
+ $sub_ptr_rhs_cast24 = $9;
+ $sub_ptr_sub25 = $sub_ptr_lhs_cast23 - $sub_ptr_rhs_cast24 | 0;
+ $add_ptr26 = $call + $sub_ptr_sub25 | 0;
+ HEAP32[$localPart >> 2] = $add_ptr26;
+ label = 10;
+ break;
+ case 10:
+ HEAP32[$buf >> 2] = $call;
+ $add_ptr31 = $call + $add2 | 0;
+ HEAP32[$bufEnd >> 2] = $add_ptr31;
+ $add_ptr33 = $call + $add | 0;
+ $rawNameBuf_0 = $add_ptr33;
+ label = 11;
+ break;
+ case 11:
+ $10 = HEAP32[$rawName >> 2] | 0;
+ $11 = HEAP32[$rawNameLength >> 2] | 0;
+ _memcpy($rawNameBuf_0 | 0, $10 | 0, $11);
+ HEAP32[$rawName >> 2] = $rawNameBuf_0;
+ $parent = $tag_035 | 0;
+ $tag_0 = HEAP32[$parent >> 2] | 0;
+ $tobool = ($tag_0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ } else {
+ $tag_035 = $tag_0;
+ label = 3;
+ break;
+ }
+ case 12:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _poolStoreString($pool, $enc, $ptr, $end) {
+ $pool = $pool | 0;
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ var $call = 0, $tobool = 0, $ptr1 = 0, $0 = 0, $end2 = 0, $1 = 0, $cmp = 0, $call3 = 0, $tobool4 = 0, $2 = 0, $incdec_ptr = 0, $start = 0, $3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _poolAppend($pool, $enc, $ptr, $end) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $ptr1 = $pool + 12 | 0;
+ $0 = HEAP32[$ptr1 >> 2] | 0;
+ $end2 = $pool + 8 | 0;
+ $1 = HEAP32[$end2 >> 2] | 0;
+ $cmp = ($0 | 0) == ($1 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call3 = _poolGrow($pool) | 0;
+ $tobool4 = $call3 << 24 >> 24 == 0;
+ if ($tobool4) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $2 = HEAP32[$ptr1 >> 2] | 0;
+ $incdec_ptr = $2 + 1 | 0;
+ HEAP32[$ptr1 >> 2] = $incdec_ptr;
+ HEAP8[$2] = 0;
+ $start = $pool + 16 | 0;
+ $3 = HEAP32[$start >> 2] | 0;
+ $retval_0 = $3;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _processInternalEntity($parser, $entity) {
+ $parser = $parser | 0;
+ $entity = $entity | 0;
+ var $next = 0, $m_freeInternalEntities = 0, $0 = 0, $tobool = 0, $next2 = 0, $1 = 0, $malloc_fcn = 0, $2 = 0, $call = 0, $3 = 0, $tobool4 = 0, $openEntity_0 = 0, $open = 0, $processed = 0, $m_openInternalEntities = 0, $4 = 0, $next7 = 0, $entity9 = 0, $m_tagLevel = 0, $5 = 0, $startTagLevel = 0, $betweenDecl10 = 0, $internalEventPtr = 0, $internalEventEndPtr = 0, $textPtr = 0, $6 = 0, $textLen = 0, $7 = 0, $add_ptr = 0, $8 = 0, $m_internalEncoding = 0, $9 = 0, $call13 = 0, $cmp = 0, $10 = 0, $cmp15 = 0, $parsing = 0, $11 = 0, $cmp16 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $m_processor = 0, $12 = 0, $13 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $next = __stackBase__ | 0;
+ $m_freeInternalEntities = $parser + 288 | 0;
+ $0 = HEAP32[$m_freeInternalEntities >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $next2 = $0 + 8 | 0;
+ $1 = HEAP32[$next2 >> 2] | 0;
+ HEAP32[$m_freeInternalEntities >> 2] = $1;
+ $openEntity_0 = $0;
+ label = 5;
+ break;
+ case 4:
+ $malloc_fcn = $parser + 12 | 0;
+ $2 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call = FUNCTION_TABLE_ii[$2 & 1023](24) | 0;
+ $3 = $call;
+ $tobool4 = ($call | 0) == 0;
+ if ($tobool4) {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ } else {
+ $openEntity_0 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $open = $entity + 32 | 0;
+ HEAP8[$open] = 1;
+ $processed = $entity + 12 | 0;
+ HEAP32[$processed >> 2] = 0;
+ $m_openInternalEntities = $parser + 284 | 0;
+ $4 = HEAP32[$m_openInternalEntities >> 2] | 0;
+ $next7 = $openEntity_0 + 8 | 0;
+ HEAP32[$next7 >> 2] = $4;
+ HEAP32[$m_openInternalEntities >> 2] = $openEntity_0;
+ $entity9 = $openEntity_0 + 12 | 0;
+ HEAP32[$entity9 >> 2] = $entity;
+ $m_tagLevel = $parser + 296 | 0;
+ $5 = HEAP32[$m_tagLevel >> 2] | 0;
+ $startTagLevel = $openEntity_0 + 16 | 0;
+ HEAP32[$startTagLevel >> 2] = $5;
+ $betweenDecl10 = $openEntity_0 + 20 | 0;
+ HEAP8[$betweenDecl10] = 0;
+ $internalEventPtr = $openEntity_0 | 0;
+ HEAP32[$internalEventPtr >> 2] = 0;
+ $internalEventEndPtr = $openEntity_0 + 4 | 0;
+ HEAP32[$internalEventEndPtr >> 2] = 0;
+ $textPtr = $entity + 4 | 0;
+ $6 = HEAP32[$textPtr >> 2] | 0;
+ $textLen = $entity + 8 | 0;
+ $7 = HEAP32[$textLen >> 2] | 0;
+ $add_ptr = $6 + $7 | 0;
+ $8 = HEAP32[$m_tagLevel >> 2] | 0;
+ $m_internalEncoding = $parser + 224 | 0;
+ $9 = HEAP32[$m_internalEncoding >> 2] | 0;
+ $call13 = _doContent($parser, $8, $9, $6, $add_ptr, $next, 0) | 0;
+ $cmp = ($call13 | 0) == 0;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = $call13;
+ label = 10;
+ break;
+ }
+ case 6:
+ $10 = HEAP32[$next >> 2] | 0;
+ $cmp15 = ($add_ptr | 0) == ($10 | 0);
+ if ($cmp15) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $parsing = $parser + 464 | 0;
+ $11 = HEAP32[$parsing >> 2] | 0;
+ $cmp16 = ($11 | 0) == 3;
+ if ($cmp16) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $sub_ptr_lhs_cast = $10;
+ $sub_ptr_rhs_cast = $6;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ HEAP32[$processed >> 2] = $sub_ptr_sub;
+ $m_processor = $parser + 264 | 0;
+ HEAP32[$m_processor >> 2] = 680;
+ $retval_0 = $call13;
+ label = 10;
+ break;
+ case 9:
+ HEAP8[$open] = 0;
+ $12 = HEAP32[$next7 >> 2] | 0;
+ HEAP32[$m_openInternalEntities >> 2] = $12;
+ $13 = HEAP32[$m_freeInternalEntities >> 2] | 0;
+ HEAP32[$next7 >> 2] = $13;
+ HEAP32[$m_freeInternalEntities >> 2] = $openEntity_0;
+ $retval_0 = $call13;
+ label = 10;
+ break;
+ case 10:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _getContext($parser) {
+ $parser = $parser | 0;
+ var $iter = 0, $m_dtd = 0, $0 = 0, $binding = 0, $1 = 0, $tobool = 0, $m_tempPool = 0, $ptr = 0, $2 = 0, $end = 0, $3 = 0, $cmp = 0, $call = 0, $tobool3 = 0, $4 = 0, $incdec_ptr = 0, $5 = 0, $uriLen = 0, $6 = 0, $m_namespaceSeparator = 0, $7 = 0, $not_tobool9 = 0, $dec = 0, $len_0 = 0, $cmp1281 = 0, $i_082 = 0, $8 = 0, $9 = 0, $cmp17 = 0, $call20 = 0, $tobool21 = 0, $10 = 0, $uri = 0, $11 = 0, $arrayidx = 0, $12 = 0, $13 = 0, $incdec_ptr28 = 0, $inc = 0, $cmp12 = 0, $needSep_0 = 0, $prefixes = 0, $m_tempPool65 = 0, $ptr66 = 0, $end68 = 0, $m_namespaceSeparator104 = 0, $ptr46 = 0, $end48 = 0, $m_tempPool45 = 0, $needSep_1_ph = 0, $call35 = 0, $tobool36 = 0, $binding39 = 0, $14 = 0, $15 = 0, $tobool40 = 0, $tobool43 = 0, $16 = 0, $17 = 0, $cmp49 = 0, $call53 = 0, $tobool54 = 0, $18 = 0, $incdec_ptr59 = 0, $name = 0, $19 = 0, $20 = 0, $tobool6368 = 0, $21 = 0, $22 = 0, $cmp6969 = 0, $cmp6971 = 0, $s_070 = 0, $call73 = 0, $tobool74 = 0, $23 = 0, $24 = 0, $incdec_ptr79 = 0, $incdec_ptr83 = 0, $25 = 0, $tobool63 = 0, $26 = 0, $27 = 0, $cmp69 = 0, $cmp69_lcssa = 0, $call93 = 0, $tobool94 = 0, $28 = 0, $incdec_ptr99 = 0, $29 = 0, $uriLen103 = 0, $30 = 0, $31 = 0, $not_tobool105 = 0, $dec107 = 0, $len34_0 = 0, $cmp11076 = 0, $i33_077 = 0, $32 = 0, $33 = 0, $cmp117 = 0, $call121 = 0, $tobool122 = 0, $34 = 0, $uri126 = 0, $35 = 0, $arrayidx127 = 0, $36 = 0, $37 = 0, $incdec_ptr130 = 0, $inc134 = 0, $cmp110 = 0, $generalEntities = 0, $ptr171 = 0, $end173 = 0, $m_tempPool170 = 0, $ptr150 = 0, $end152 = 0, $m_tempPool149 = 0, $needSep_2_ph = 0, $call139 = 0, $tobool140 = 0, $open = 0, $38 = 0, $39 = 0, $tobool143 = 0, $tobool147 = 0, $40 = 0, $41 = 0, $cmp153 = 0, $call157 = 0, $tobool158 = 0, $42 = 0, $incdec_ptr163 = 0, $name166 = 0, $43 = 0, $44 = 0, $tobool16859 = 0, $s138_060 = 0, $45 = 0, $46 = 0, $cmp174 = 0, $call178 = 0, $tobool179 = 0, $47 = 0, $48 = 0, $incdec_ptr184 = 0, $incdec_ptr188 = 0, $49 = 0, $tobool168 = 0, $ptr192 = 0, $50 = 0, $end194 = 0, $51 = 0, $cmp195 = 0, $m_tempPool191 = 0, $call199 = 0, $tobool200 = 0, $52 = 0, $incdec_ptr205 = 0, $start = 0, $53 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $iter = __stackBase__ | 0;
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $binding = $0 + 136 | 0;
+ $1 = HEAP32[$binding >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ $needSep_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $m_tempPool = $parser + 400 | 0;
+ $ptr = $parser + 412 | 0;
+ $2 = HEAP32[$ptr >> 2] | 0;
+ $end = $parser + 408 | 0;
+ $3 = HEAP32[$end >> 2] | 0;
+ $cmp = ($2 | 0) == ($3 | 0);
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $call = _poolGrow($m_tempPool) | 0;
+ $tobool3 = $call << 24 >> 24 == 0;
+ if ($tobool3) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $4 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $4 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$4] = 61;
+ $5 = HEAP32[$binding >> 2] | 0;
+ $uriLen = $5 + 20 | 0;
+ $6 = HEAP32[$uriLen >> 2] | 0;
+ $m_namespaceSeparator = $parser + 456 | 0;
+ $7 = HEAP8[$m_namespaceSeparator] | 0;
+ $not_tobool9 = $7 << 24 >> 24 != 0;
+ $dec = $not_tobool9 << 31 >> 31;
+ $len_0 = $dec + $6 | 0;
+ $cmp1281 = ($len_0 | 0) > 0;
+ if ($cmp1281) {
+ $i_082 = 0;
+ label = 6;
+ break;
+ } else {
+ $needSep_0 = 1;
+ label = 9;
+ break;
+ }
+ case 6:
+ $8 = HEAP32[$ptr >> 2] | 0;
+ $9 = HEAP32[$end >> 2] | 0;
+ $cmp17 = ($8 | 0) == ($9 | 0);
+ if ($cmp17) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $call20 = _poolGrow($m_tempPool) | 0;
+ $tobool21 = $call20 << 24 >> 24 == 0;
+ if ($tobool21) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $10 = HEAP32[$binding >> 2] | 0;
+ $uri = $10 + 16 | 0;
+ $11 = HEAP32[$uri >> 2] | 0;
+ $arrayidx = $11 + $i_082 | 0;
+ $12 = HEAP8[$arrayidx] | 0;
+ $13 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr28 = $13 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr28;
+ HEAP8[$13] = $12;
+ $inc = $i_082 + 1 | 0;
+ $cmp12 = ($inc | 0) < ($len_0 | 0);
+ if ($cmp12) {
+ $i_082 = $inc;
+ label = 6;
+ break;
+ } else {
+ $needSep_0 = 1;
+ label = 9;
+ break;
+ }
+ case 9:
+ $prefixes = $0 + 60 | 0;
+ _hashTableIterInit($iter, $prefixes);
+ $m_tempPool65 = $parser + 400 | 0;
+ $ptr66 = $parser + 412 | 0;
+ $end68 = $parser + 408 | 0;
+ $m_namespaceSeparator104 = $parser + 456 | 0;
+ $ptr46 = $parser + 412 | 0;
+ $end48 = $parser + 408 | 0;
+ $m_tempPool45 = $parser + 400 | 0;
+ $needSep_1_ph = $needSep_0;
+ label = 10;
+ break;
+ case 10:
+ label = 11;
+ break;
+ case 11:
+ $call35 = _hashTableIterNext($iter) | 0;
+ $tobool36 = ($call35 | 0) == 0;
+ if ($tobool36) {
+ label = 27;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $binding39 = $call35 + 4 | 0;
+ $14 = $binding39;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $tobool40 = ($15 | 0) == 0;
+ if ($tobool40) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $tobool43 = $needSep_1_ph << 24 >> 24 == 0;
+ if ($tobool43) {
+ label = 17;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $16 = HEAP32[$ptr46 >> 2] | 0;
+ $17 = HEAP32[$end48 >> 2] | 0;
+ $cmp49 = ($16 | 0) == ($17 | 0);
+ if ($cmp49) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $call53 = _poolGrow($m_tempPool45) | 0;
+ $tobool54 = $call53 << 24 >> 24 == 0;
+ if ($tobool54) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $18 = HEAP32[$ptr46 >> 2] | 0;
+ $incdec_ptr59 = $18 + 1 | 0;
+ HEAP32[$ptr46 >> 2] = $incdec_ptr59;
+ HEAP8[$18] = 12;
+ label = 17;
+ break;
+ case 17:
+ $name = $call35 | 0;
+ $19 = HEAP32[$name >> 2] | 0;
+ $20 = HEAP8[$19] | 0;
+ $tobool6368 = $20 << 24 >> 24 == 0;
+ $21 = HEAP32[$ptr66 >> 2] | 0;
+ $22 = HEAP32[$end68 >> 2] | 0;
+ $cmp6969 = ($21 | 0) == ($22 | 0);
+ if ($tobool6368) {
+ $cmp69_lcssa = $cmp6969;
+ label = 21;
+ break;
+ } else {
+ $s_070 = $19;
+ $cmp6971 = $cmp6969;
+ label = 18;
+ break;
+ }
+ case 18:
+ if ($cmp6971) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $call73 = _poolGrow($m_tempPool65) | 0;
+ $tobool74 = $call73 << 24 >> 24 == 0;
+ if ($tobool74) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $23 = HEAP8[$s_070] | 0;
+ $24 = HEAP32[$ptr66 >> 2] | 0;
+ $incdec_ptr79 = $24 + 1 | 0;
+ HEAP32[$ptr66 >> 2] = $incdec_ptr79;
+ HEAP8[$24] = $23;
+ $incdec_ptr83 = $s_070 + 1 | 0;
+ $25 = HEAP8[$incdec_ptr83] | 0;
+ $tobool63 = $25 << 24 >> 24 == 0;
+ $26 = HEAP32[$ptr66 >> 2] | 0;
+ $27 = HEAP32[$end68 >> 2] | 0;
+ $cmp69 = ($26 | 0) == ($27 | 0);
+ if ($tobool63) {
+ $cmp69_lcssa = $cmp69;
+ label = 21;
+ break;
+ } else {
+ $s_070 = $incdec_ptr83;
+ $cmp6971 = $cmp69;
+ label = 18;
+ break;
+ }
+ case 21:
+ if ($cmp69_lcssa) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $call93 = _poolGrow($m_tempPool65) | 0;
+ $tobool94 = $call93 << 24 >> 24 == 0;
+ if ($tobool94) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $28 = HEAP32[$ptr66 >> 2] | 0;
+ $incdec_ptr99 = $28 + 1 | 0;
+ HEAP32[$ptr66 >> 2] = $incdec_ptr99;
+ HEAP8[$28] = 61;
+ $29 = HEAP32[$14 >> 2] | 0;
+ $uriLen103 = $29 + 20 | 0;
+ $30 = HEAP32[$uriLen103 >> 2] | 0;
+ $31 = HEAP8[$m_namespaceSeparator104] | 0;
+ $not_tobool105 = $31 << 24 >> 24 != 0;
+ $dec107 = $not_tobool105 << 31 >> 31;
+ $len34_0 = $dec107 + $30 | 0;
+ $cmp11076 = ($len34_0 | 0) > 0;
+ if ($cmp11076) {
+ $i33_077 = 0;
+ label = 24;
+ break;
+ } else {
+ $needSep_1_ph = 1;
+ label = 10;
+ break;
+ }
+ case 24:
+ $32 = HEAP32[$ptr66 >> 2] | 0;
+ $33 = HEAP32[$end68 >> 2] | 0;
+ $cmp117 = ($32 | 0) == ($33 | 0);
+ if ($cmp117) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $call121 = _poolGrow($m_tempPool65) | 0;
+ $tobool122 = $call121 << 24 >> 24 == 0;
+ if ($tobool122) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $34 = HEAP32[$14 >> 2] | 0;
+ $uri126 = $34 + 16 | 0;
+ $35 = HEAP32[$uri126 >> 2] | 0;
+ $arrayidx127 = $35 + $i33_077 | 0;
+ $36 = HEAP8[$arrayidx127] | 0;
+ $37 = HEAP32[$ptr66 >> 2] | 0;
+ $incdec_ptr130 = $37 + 1 | 0;
+ HEAP32[$ptr66 >> 2] = $incdec_ptr130;
+ HEAP8[$37] = $36;
+ $inc134 = $i33_077 + 1 | 0;
+ $cmp110 = ($inc134 | 0) < ($len34_0 | 0);
+ if ($cmp110) {
+ $i33_077 = $inc134;
+ label = 24;
+ break;
+ } else {
+ $needSep_1_ph = 1;
+ label = 10;
+ break;
+ }
+ case 27:
+ $generalEntities = $0 | 0;
+ _hashTableIterInit($iter, $generalEntities);
+ $ptr171 = $parser + 412 | 0;
+ $end173 = $parser + 408 | 0;
+ $m_tempPool170 = $parser + 400 | 0;
+ $ptr150 = $parser + 412 | 0;
+ $end152 = $parser + 408 | 0;
+ $m_tempPool149 = $parser + 400 | 0;
+ $needSep_2_ph = $needSep_1_ph;
+ label = 28;
+ break;
+ case 28:
+ label = 29;
+ break;
+ case 29:
+ $call139 = _hashTableIterNext($iter) | 0;
+ $tobool140 = ($call139 | 0) == 0;
+ if ($tobool140) {
+ label = 39;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $open = $call139 + 32 | 0;
+ $38 = $open;
+ $39 = HEAP8[$38] | 0;
+ $tobool143 = $39 << 24 >> 24 == 0;
+ if ($tobool143) {
+ label = 29;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $tobool147 = $needSep_2_ph << 24 >> 24 == 0;
+ if ($tobool147) {
+ label = 35;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $40 = HEAP32[$ptr150 >> 2] | 0;
+ $41 = HEAP32[$end152 >> 2] | 0;
+ $cmp153 = ($40 | 0) == ($41 | 0);
+ if ($cmp153) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ $call157 = _poolGrow($m_tempPool149) | 0;
+ $tobool158 = $call157 << 24 >> 24 == 0;
+ if ($tobool158) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $42 = HEAP32[$ptr150 >> 2] | 0;
+ $incdec_ptr163 = $42 + 1 | 0;
+ HEAP32[$ptr150 >> 2] = $incdec_ptr163;
+ HEAP8[$42] = 12;
+ label = 35;
+ break;
+ case 35:
+ $name166 = $call139 | 0;
+ $43 = HEAP32[$name166 >> 2] | 0;
+ $44 = HEAP8[$43] | 0;
+ $tobool16859 = $44 << 24 >> 24 == 0;
+ if ($tobool16859) {
+ $needSep_2_ph = 1;
+ label = 28;
+ break;
+ } else {
+ $s138_060 = $43;
+ label = 36;
+ break;
+ }
+ case 36:
+ $45 = HEAP32[$ptr171 >> 2] | 0;
+ $46 = HEAP32[$end173 >> 2] | 0;
+ $cmp174 = ($45 | 0) == ($46 | 0);
+ if ($cmp174) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ $call178 = _poolGrow($m_tempPool170) | 0;
+ $tobool179 = $call178 << 24 >> 24 == 0;
+ if ($tobool179) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $47 = HEAP8[$s138_060] | 0;
+ $48 = HEAP32[$ptr171 >> 2] | 0;
+ $incdec_ptr184 = $48 + 1 | 0;
+ HEAP32[$ptr171 >> 2] = $incdec_ptr184;
+ HEAP8[$48] = $47;
+ $incdec_ptr188 = $s138_060 + 1 | 0;
+ $49 = HEAP8[$incdec_ptr188] | 0;
+ $tobool168 = $49 << 24 >> 24 == 0;
+ if ($tobool168) {
+ $needSep_2_ph = 1;
+ label = 28;
+ break;
+ } else {
+ $s138_060 = $incdec_ptr188;
+ label = 36;
+ break;
+ }
+ case 39:
+ $ptr192 = $parser + 412 | 0;
+ $50 = HEAP32[$ptr192 >> 2] | 0;
+ $end194 = $parser + 408 | 0;
+ $51 = HEAP32[$end194 >> 2] | 0;
+ $cmp195 = ($50 | 0) == ($51 | 0);
+ if ($cmp195) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 40:
+ $m_tempPool191 = $parser + 400 | 0;
+ $call199 = _poolGrow($m_tempPool191) | 0;
+ $tobool200 = $call199 << 24 >> 24 == 0;
+ if ($tobool200) {
+ $retval_0 = 0;
+ label = 42;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $52 = HEAP32[$ptr192 >> 2] | 0;
+ $incdec_ptr205 = $52 + 1 | 0;
+ HEAP32[$ptr192 >> 2] = $incdec_ptr205;
+ HEAP8[$52] = 0;
+ $start = $parser + 416 | 0;
+ $53 = HEAP32[$start >> 2] | 0;
+ $retval_0 = $53;
+ label = 42;
+ break;
+ case 42:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _storeAtts($parser, $enc, $attStr, $tagNamePtr, $bindingsPtr) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $attStr = $attStr | 0;
+ $tagNamePtr = $tagNamePtr | 0;
+ $bindingsPtr = $bindingsPtr | 0;
+ var $m_dtd = 0, $0 = 0, $elementTypes = 0, $str = 0, $1 = 0, $call = 0, $2 = 0, $tobool = 0, $pool = 0, $3 = 0, $call2 = 0, $tobool3 = 0, $call6 = 0, $4 = 0, $tobool7 = 0, $m_ns = 0, $5 = 0, $tobool10 = 0, $call11 = 0, $tobool12 = 0, $elementType_0 = 0, $nDefaultAtts16 = 0, $6 = 0, $getAtts = 0, $7 = 0, $m_attsSize = 0, $8 = 0, $m_atts = 0, $9 = 0, $call17 = 0, $add = 0, $10 = 0, $cmp = 0, $add23 = 0, $realloc_fcn = 0, $11 = 0, $12 = 0, $13 = 0, $mul = 0, $call27 = 0, $14 = 0, $cmp28 = 0, $cmp33 = 0, $15 = 0, $call38 = 0, $16 = 0, $17 = 0, $cmp42377 = 0, $nameLength = 0, $m_tempPool = 0, $start = 0, $ptr = 0, $defaultAtts = 0, $m_tempPool102 = 0, $ptr117 = 0, $start119 = 0, $attIndex_0381 = 0, $i_0379 = 0, $nPrefixes_0378 = 0, $18 = 0, $name45 = 0, $19 = 0, $20 = 0, $call48 = 0, $add_ptr = 0, $call49 = 0, $tobool50 = 0, $name53 = 0, $21 = 0, $arrayidx54 = 0, $22 = 0, $tobool55 = 0, $m_encoding = 0, $23 = 0, $cmp57 = 0, $24 = 0, $name62 = 0, $25 = 0, $m_eventPtr = 0, $26 = 0, $inc = 0, $arrayidx68 = 0, $27 = 0, $normalized = 0, $28 = 0, $tobool71 = 0, $maybeTokenized = 0, $29 = 0, $tobool73 = 0, $j_0 = 0, $cmp76 = 0, $30 = 0, $id = 0, $31 = 0, $cmp80 = 0, $inc87 = 0, $isCdata85 = 0, $32 = 0, $isCdata_0 = 0, $33 = 0, $valuePtr = 0, $34 = 0, $valueEnd = 0, $35 = 0, $call93 = 0, $tobool94 = 0, $36 = 0, $arrayidx98 = 0, $37 = 0, $valuePtr105 = 0, $38 = 0, $valueEnd108 = 0, $39 = 0, $call109 = 0, $arrayidx110 = 0, $cmp112 = 0, $40 = 0, $prefix = 0, $41 = 0, $tobool121 = 0, $xmlns = 0, $42 = 0, $tobool123 = 0, $arrayidx127 = 0, $43 = 0, $call128 = 0, $tobool129 = 0, $inc133 = 0, $inc134 = 0, $44 = 0, $arrayidx136 = 0, $inc139 = 0, $nPrefixes_1 = 0, $attIndex_1 = 0, $inc142 = 0, $cmp42 = 0, $attIndex_0_lcssa = 0, $nPrefixes_0_lcssa = 0, $m_nSpecifiedAtts = 0, $idAtt = 0, $45 = 0, $tobool144 = 0, $name147 = 0, $46 = 0, $arrayidx148 = 0, $47 = 0, $tobool150 = 0, $i_1 = 0, $cmp153 = 0, $arrayidx156 = 0, $48 = 0, $49 = 0, $name158 = 0, $50 = 0, $cmp159 = 0, $add164 = 0, $m_idAttIndex = 0, $m_idAttIndex167 = 0, $cmp170362 = 0, $defaultAtts173 = 0, $attIndex_2365 = 0, $i_2364 = 0, $nPrefixes_2363 = 0, $51 = 0, $id175 = 0, $52 = 0, $name176 = 0, $53 = 0, $arrayidx177 = 0, $54 = 0, $tobool178 = 0, $value = 0, $55 = 0, $tobool180 = 0, $prefix183 = 0, $56 = 0, $tobool184 = 0, $xmlns187 = 0, $57 = 0, $tobool188 = 0, $call195 = 0, $tobool196 = 0, $inc203 = 0, $58 = 0, $name205 = 0, $59 = 0, $inc206 = 0, $arrayidx207 = 0, $60 = 0, $inc209 = 0, $arrayidx210 = 0, $61 = 0, $name217 = 0, $62 = 0, $inc218 = 0, $arrayidx219 = 0, $63 = 0, $inc221 = 0, $arrayidx222 = 0, $nPrefixes_3 = 0, $attIndex_3 = 0, $inc226 = 0, $cmp170 = 0, $attIndex_2_lcssa = 0, $nPrefixes_2_lcssa = 0, $arrayidx228 = 0, $tobool229 = 0, $i_4_ph = 0, $cmp465317 = 0, $m_nsAttsVersion = 0, $64 = 0, $m_nsAttsPower = 0, $65 = 0, $conv232 = 0, $shl233 = 0, $shr = 0, $tobool236 = 0, $m_nsAttsPower_promoted = 0, $66 = 0, $inc240 = 0, $conv241 = 0, $shr242 = 0, $tobool243 = 0, $cmp246 = 0, $_inc240 = 0, $conv252 = 0, $realloc_fcn255 = 0, $67 = 0, $m_nsAtts = 0, $68 = 0, $69 = 0, $mul256 = 0, $call257 = 0, $tobool258 = 0, $70 = 0, $nsAttsSize_0307 = 0, $nsAttsSize_0 = 0, $tobool263 = 0, $nsAttsSize_0310_ph = 0, $m_nsAtts270 = 0, $j231_0356 = 0, $dec269 = 0, $71 = 0, $version272 = 0, $cmp266 = 0, $nsAttsSize_0309 = 0, $version_1 = 0, $dec275 = 0, $cmp278351 = 0, $m_hash_secret_salt = 0, $attributeIds = 0, $m_tempPool327 = 0, $ptr328 = 0, $end330 = 0, $sub = 0, $m_nsAtts350 = 0, $m_ns_triplets = 0, $start437 = 0, $m_namespaceSeparator = 0, $start362 = 0, $neg = 0, $shr391 = 0, $ptr302 = 0, $end = 0, $m_tempPool301 = 0, $i_3353 = 0, $nPrefixes_4352 = 0, $arrayidx281 = 0, $72 = 0, $arrayidx282 = 0, $73 = 0, $cmp284 = 0, $74 = 0, $call289 = 0, $prefix290 = 0, $75 = 0, $76 = 0, $binding291 = 0, $77 = 0, $tobool292 = 0, $uriLen = 0, $78 = 0, $cmp296320 = 0, $uri299 = 0, $uriHash_0322 = 0, $j231_1321 = 0, $79 = 0, $arrayidx300 = 0, $80 = 0, $81 = 0, $82 = 0, $cmp304 = 0, $call308 = 0, $tobool309 = 0, $83 = 0, $incdec_ptr = 0, $mul314 = 0, $conv315 = 0, $xor = 0, $inc317 = 0, $84 = 0, $cmp296 = 0, $uriHash_0_lcssa = 0, $s_0 = 0, $incdec_ptr320 = 0, $85 = 0, $cmp322 = 0, $s_1 = 0, $uriHash_1 = 0, $86 = 0, $87 = 0, $88 = 0, $cmp331 = 0, $call335 = 0, $tobool336 = 0, $89 = 0, $90 = 0, $incdec_ptr341 = 0, $mul344 = 0, $conv345 = 0, $xor346 = 0, $incdec_ptr347 = 0, $91 = 0, $tobool348 = 0, $and = 0, $92 = 0, $version352337 = 0, $93 = 0, $cmp353338 = 0, $and386 = 0, $94 = 0, $step_0340 = 0, $j231_2339 = 0, $hash = 0, $95 = 0, $cmp358 = 0, $96 = 0, $uriName = 0, $97 = 0, $98 = 0, $99 = 0, $cmp368328 = 0, $cmp371329 = 0, $or_cond330 = 0, $s2_0332 = 0, $s1_0331 = 0, $incdec_ptr375 = 0, $incdec_ptr376 = 0, $100 = 0, $101 = 0, $cmp368 = 0, $cmp371 = 0, $or_cond = 0, $cmp371_lcssa = 0, $tobool384 = 0, $102 = 0, $conv388 = 0, $sub389 = 0, $shr390 = 0, $and392 = 0, $or = 0, $conv393 = 0, $step_1 = 0, $conv395 = 0, $cmp396 = 0, $sub400 = 0, $sub400_j231_2339 = 0, $j231_2_be = 0, $103 = 0, $version352 = 0, $104 = 0, $cmp353 = 0, $j231_2_lcssa = 0, $105 = 0, $tobool406 = 0, $106 = 0, $107 = 0, $arrayidx410 = 0, $prefix411 = 0, $108 = 0, $name412 = 0, $109 = 0, $s_2 = 0, $110 = 0, $111 = 0, $cmp418 = 0, $call422 = 0, $tobool423 = 0, $112 = 0, $113 = 0, $incdec_ptr428 = 0, $incdec_ptr432 = 0, $114 = 0, $tobool433 = 0, $115 = 0, $116 = 0, $117 = 0, $version445 = 0, $118 = 0, $hash448 = 0, $119 = 0, $uriName451 = 0, $dec452 = 0, $tobool453 = 0, $add455 = 0, $nPrefixes_5 = 0, $add461 = 0, $cmp278 = 0, $binding_0314 = 0, $tobool474315 = 0, $i_4318 = 0, $arrayidx468 = 0, $120 = 0, $arrayidx469 = 0, $add471 = 0, $cmp465 = 0, $binding_0316 = 0, $attId476 = 0, $121 = 0, $name477 = 0, $122 = 0, $arrayidx478 = 0, $nextTagBinding = 0, $binding_0 = 0, $tobool474 = 0, $m_ns481 = 0, $123 = 0, $tobool482 = 0, $prefix485 = 0, $124 = 0, $tobool486 = 0, $binding489 = 0, $125 = 0, $tobool490 = 0, $126 = 0, $localPart_0 = 0, $incdec_ptr495 = 0, $127 = 0, $cmp497 = 0, $binding502 = 0, $128 = 0, $tobool503 = 0, $129 = 0, $localPart_1 = 0, $binding_1 = 0, $m_ns_triplets511 = 0, $130 = 0, $tobool513 = 0, $prefix515 = 0, $131 = 0, $name516 = 0, $132 = 0, $tobool517 = 0, $133 = 0, $name522 = 0, $134 = 0, $prefixLen_0 = 0, $inc520 = 0, $arrayidx523 = 0, $135 = 0, $tobool524 = 0, $prefixLen_1 = 0, $localPart528 = 0, $uriLen529 = 0, $136 = 0, $uriLen530 = 0, $prefix531 = 0, $137 = 0, $name532 = 0, $138 = 0, $prefix533 = 0, $prefixLen534 = 0, $i_5 = 0, $inc536 = 0, $arrayidx537 = 0, $139 = 0, $tobool538 = 0, $140 = 0, $add542 = 0, $add543 = 0, $uriAlloc = 0, $141 = 0, $cmp544 = 0, $malloc_fcn = 0, $142 = 0, $add548 = 0, $call550 = 0, $tobool551 = 0, $uri556 = 0, $143 = 0, $144 = 0, $m_tagStack = 0, $p_0311 = 0, $tobool560312 = 0, $p_0313 = 0, $str563 = 0, $145 = 0, $146 = 0, $cmp565 = 0, $parent = 0, $p_0 = 0, $tobool560 = 0, $free_fcn = 0, $147 = 0, $148 = 0, $uri577 = 0, $149 = 0, $150 = 0, $add_ptr579 = 0, $tobool581 = 0, $add_ptr579_sum = 0, $add_ptr584 = 0, $m_namespaceSeparator585 = 0, $151 = 0, $add_ptr584_sum = 0, $add_ptr586 = 0, $152 = 0, $name588 = 0, $153 = 0, $154 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $elementTypes = $0 + 20 | 0;
+ $str = $tagNamePtr | 0;
+ $1 = HEAP32[$str >> 2] | 0;
+ $call = _lookup($parser, $elementTypes, $1, 0) | 0;
+ $2 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $elementType_0 = $2;
+ label = 7;
+ break;
+ }
+ case 3:
+ $pool = $0 + 80 | 0;
+ $3 = HEAP32[$str >> 2] | 0;
+ $call2 = _poolCopyString($pool, $3) | 0;
+ $tobool3 = ($call2 | 0) == 0;
+ if ($tobool3) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $call6 = _lookup($parser, $elementTypes, $call2, 24) | 0;
+ $4 = $call6;
+ $tobool7 = ($call6 | 0) == 0;
+ if ($tobool7) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $m_ns = $parser + 232 | 0;
+ $5 = HEAP8[$m_ns] | 0;
+ $tobool10 = $5 << 24 >> 24 == 0;
+ if ($tobool10) {
+ $elementType_0 = $4;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call11 = _setElementTypePrefix($parser, $4) | 0;
+ $tobool12 = ($call11 | 0) == 0;
+ if ($tobool12) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ $elementType_0 = $4;
+ label = 7;
+ break;
+ }
+ case 7:
+ $nDefaultAtts16 = $elementType_0 + 12 | 0;
+ $6 = HEAP32[$nDefaultAtts16 >> 2] | 0;
+ $getAtts = $enc + 36 | 0;
+ $7 = HEAP32[$getAtts >> 2] | 0;
+ $m_attsSize = $parser + 364 | 0;
+ $8 = HEAP32[$m_attsSize >> 2] | 0;
+ $m_atts = $parser + 376 | 0;
+ $9 = HEAP32[$m_atts >> 2] | 0;
+ $call17 = FUNCTION_TABLE_iiiii[$7 & 1023]($enc, $attStr, $8, $9) | 0;
+ $add = $call17 + $6 | 0;
+ $10 = HEAP32[$m_attsSize >> 2] | 0;
+ $cmp = ($add | 0) > ($10 | 0);
+ if ($cmp) {
+ label = 8;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 8:
+ $add23 = $add + 16 | 0;
+ HEAP32[$m_attsSize >> 2] = $add23;
+ $realloc_fcn = $parser + 16 | 0;
+ $11 = HEAP32[$realloc_fcn >> 2] | 0;
+ $12 = HEAP32[$m_atts >> 2] | 0;
+ $13 = $12;
+ $mul = $add23 << 4;
+ $call27 = FUNCTION_TABLE_iii[$11 & 1023]($13, $mul) | 0;
+ $14 = $call27;
+ $cmp28 = ($call27 | 0) == 0;
+ if ($cmp28) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ HEAP32[$m_atts >> 2] = $14;
+ $cmp33 = ($call17 | 0) > ($10 | 0);
+ if ($cmp33) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $15 = HEAP32[$getAtts >> 2] | 0;
+ $call38 = FUNCTION_TABLE_iiiii[$15 & 1023]($enc, $attStr, $call17, $14) | 0;
+ label = 11;
+ break;
+ case 11:
+ $16 = HEAP32[$m_atts >> 2] | 0;
+ $17 = $16 | 0;
+ $cmp42377 = ($call17 | 0) > 0;
+ if ($cmp42377) {
+ label = 12;
+ break;
+ } else {
+ $nPrefixes_0_lcssa = 0;
+ $attIndex_0_lcssa = 0;
+ label = 32;
+ break;
+ }
+ case 12:
+ $nameLength = $enc + 28 | 0;
+ $m_tempPool = $parser + 400 | 0;
+ $start = $parser + 416 | 0;
+ $ptr = $parser + 412 | 0;
+ $defaultAtts = $elementType_0 + 20 | 0;
+ $m_tempPool102 = $parser + 400 | 0;
+ $ptr117 = $parser + 412 | 0;
+ $start119 = $parser + 416 | 0;
+ $nPrefixes_0378 = 0;
+ $i_0379 = 0;
+ $attIndex_0381 = 0;
+ label = 13;
+ break;
+ case 13:
+ $18 = HEAP32[$m_atts >> 2] | 0;
+ $name45 = $18 + ($i_0379 << 4) | 0;
+ $19 = HEAP32[$name45 >> 2] | 0;
+ $20 = HEAP32[$nameLength >> 2] | 0;
+ $call48 = FUNCTION_TABLE_iii[$20 & 1023]($enc, $19) | 0;
+ $add_ptr = $19 + $call48 | 0;
+ $call49 = _getAttributeId($parser, $enc, $19, $add_ptr) | 0;
+ $tobool50 = ($call49 | 0) == 0;
+ if ($tobool50) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $name53 = $call49 | 0;
+ $21 = HEAP32[$name53 >> 2] | 0;
+ $arrayidx54 = $21 - 1 | 0;
+ $22 = HEAP8[$arrayidx54] | 0;
+ $tobool55 = $22 << 24 >> 24 == 0;
+ if ($tobool55) {
+ label = 17;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $m_encoding = $parser + 144 | 0;
+ $23 = HEAP32[$m_encoding >> 2] | 0;
+ $cmp57 = ($23 | 0) == ($enc | 0);
+ if ($cmp57) {
+ label = 16;
+ break;
+ } else {
+ $retval_0 = 8;
+ label = 116;
+ break;
+ }
+ case 16:
+ $24 = HEAP32[$m_atts >> 2] | 0;
+ $name62 = $24 + ($i_0379 << 4) | 0;
+ $25 = HEAP32[$name62 >> 2] | 0;
+ $m_eventPtr = $parser + 272 | 0;
+ HEAP32[$m_eventPtr >> 2] = $25;
+ $retval_0 = 8;
+ label = 116;
+ break;
+ case 17:
+ HEAP8[$arrayidx54] = 1;
+ $26 = HEAP32[$name53 >> 2] | 0;
+ $inc = $attIndex_0381 + 1 | 0;
+ $arrayidx68 = $17 + ($attIndex_0381 << 2) | 0;
+ HEAP32[$arrayidx68 >> 2] = $26;
+ $27 = HEAP32[$m_atts >> 2] | 0;
+ $normalized = $27 + ($i_0379 << 4) + 12 | 0;
+ $28 = HEAP8[$normalized] | 0;
+ $tobool71 = $28 << 24 >> 24 == 0;
+ if ($tobool71) {
+ label = 18;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 18:
+ $maybeTokenized = $call49 + 8 | 0;
+ $29 = HEAP8[$maybeTokenized] | 0;
+ $tobool73 = $29 << 24 >> 24 == 0;
+ if ($tobool73) {
+ $isCdata_0 = 1;
+ label = 22;
+ break;
+ } else {
+ $j_0 = 0;
+ label = 19;
+ break;
+ }
+ case 19:
+ $cmp76 = ($j_0 | 0) < ($6 | 0);
+ if ($cmp76) {
+ label = 20;
+ break;
+ } else {
+ $isCdata_0 = 1;
+ label = 22;
+ break;
+ }
+ case 20:
+ $30 = HEAP32[$defaultAtts >> 2] | 0;
+ $id = $30 + ($j_0 * 12 & -1) | 0;
+ $31 = HEAP32[$id >> 2] | 0;
+ $cmp80 = ($call49 | 0) == ($31 | 0);
+ $inc87 = $j_0 + 1 | 0;
+ if ($cmp80) {
+ label = 21;
+ break;
+ } else {
+ $j_0 = $inc87;
+ label = 19;
+ break;
+ }
+ case 21:
+ $isCdata85 = $30 + ($j_0 * 12 & -1) + 4 | 0;
+ $32 = HEAP8[$isCdata85] | 0;
+ $isCdata_0 = $32;
+ label = 22;
+ break;
+ case 22:
+ $33 = HEAP32[$m_atts >> 2] | 0;
+ $valuePtr = $33 + ($i_0379 << 4) + 4 | 0;
+ $34 = HEAP32[$valuePtr >> 2] | 0;
+ $valueEnd = $33 + ($i_0379 << 4) + 8 | 0;
+ $35 = HEAP32[$valueEnd >> 2] | 0;
+ $call93 = _storeAttributeValue($parser, $enc, $isCdata_0, $34, $35, $m_tempPool) | 0;
+ $tobool94 = ($call93 | 0) == 0;
+ if ($tobool94) {
+ label = 23;
+ break;
+ } else {
+ $retval_0 = $call93;
+ label = 116;
+ break;
+ }
+ case 23:
+ $36 = HEAP32[$start >> 2] | 0;
+ $arrayidx98 = $17 + ($inc << 2) | 0;
+ HEAP32[$arrayidx98 >> 2] = $36;
+ $37 = HEAP32[$ptr >> 2] | 0;
+ HEAP32[$start >> 2] = $37;
+ label = 26;
+ break;
+ case 24:
+ $valuePtr105 = $27 + ($i_0379 << 4) + 4 | 0;
+ $38 = HEAP32[$valuePtr105 >> 2] | 0;
+ $valueEnd108 = $27 + ($i_0379 << 4) + 8 | 0;
+ $39 = HEAP32[$valueEnd108 >> 2] | 0;
+ $call109 = _poolStoreString($m_tempPool102, $enc, $38, $39) | 0;
+ $arrayidx110 = $17 + ($inc << 2) | 0;
+ HEAP32[$arrayidx110 >> 2] = $call109;
+ $cmp112 = ($call109 | 0) == 0;
+ if ($cmp112) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $40 = HEAP32[$ptr117 >> 2] | 0;
+ HEAP32[$start119 >> 2] = $40;
+ label = 26;
+ break;
+ case 26:
+ $prefix = $call49 + 4 | 0;
+ $41 = HEAP32[$prefix >> 2] | 0;
+ $tobool121 = ($41 | 0) == 0;
+ if ($tobool121) {
+ label = 30;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $xmlns = $call49 + 9 | 0;
+ $42 = HEAP8[$xmlns] | 0;
+ $tobool123 = $42 << 24 >> 24 == 0;
+ if ($tobool123) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $arrayidx127 = $17 + ($inc << 2) | 0;
+ $43 = HEAP32[$arrayidx127 >> 2] | 0;
+ $call128 = _addBinding($parser, $41, $call49, $43, $bindingsPtr) | 0;
+ $tobool129 = ($call128 | 0) == 0;
+ if ($tobool129) {
+ $attIndex_1 = $attIndex_0381;
+ $nPrefixes_1 = $nPrefixes_0378;
+ label = 31;
+ break;
+ } else {
+ $retval_0 = $call128;
+ label = 116;
+ break;
+ }
+ case 29:
+ $inc133 = $attIndex_0381 + 2 | 0;
+ $inc134 = $nPrefixes_0378 + 1 | 0;
+ $44 = HEAP32[$name53 >> 2] | 0;
+ $arrayidx136 = $44 - 1 | 0;
+ HEAP8[$arrayidx136] = 2;
+ $attIndex_1 = $inc133;
+ $nPrefixes_1 = $inc134;
+ label = 31;
+ break;
+ case 30:
+ $inc139 = $attIndex_0381 + 2 | 0;
+ $attIndex_1 = $inc139;
+ $nPrefixes_1 = $nPrefixes_0378;
+ label = 31;
+ break;
+ case 31:
+ $inc142 = $i_0379 + 1 | 0;
+ $cmp42 = ($inc142 | 0) < ($call17 | 0);
+ if ($cmp42) {
+ $nPrefixes_0378 = $nPrefixes_1;
+ $i_0379 = $inc142;
+ $attIndex_0381 = $attIndex_1;
+ label = 13;
+ break;
+ } else {
+ $nPrefixes_0_lcssa = $nPrefixes_1;
+ $attIndex_0_lcssa = $attIndex_1;
+ label = 32;
+ break;
+ }
+ case 32:
+ $m_nSpecifiedAtts = $parser + 368 | 0;
+ HEAP32[$m_nSpecifiedAtts >> 2] = $attIndex_0_lcssa;
+ $idAtt = $elementType_0 + 8 | 0;
+ $45 = HEAP32[$idAtt >> 2] | 0;
+ $tobool144 = ($45 | 0) == 0;
+ if ($tobool144) {
+ label = 37;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $name147 = $45 | 0;
+ $46 = HEAP32[$name147 >> 2] | 0;
+ $arrayidx148 = $46 - 1 | 0;
+ $47 = HEAP8[$arrayidx148] | 0;
+ $tobool150 = $47 << 24 >> 24 == 0;
+ if ($tobool150) {
+ label = 37;
+ break;
+ } else {
+ $i_1 = 0;
+ label = 34;
+ break;
+ }
+ case 34:
+ $cmp153 = ($i_1 | 0) < ($attIndex_0_lcssa | 0);
+ if ($cmp153) {
+ label = 35;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 35:
+ $arrayidx156 = $17 + ($i_1 << 2) | 0;
+ $48 = HEAP32[$arrayidx156 >> 2] | 0;
+ $49 = HEAP32[$idAtt >> 2] | 0;
+ $name158 = $49 | 0;
+ $50 = HEAP32[$name158 >> 2] | 0;
+ $cmp159 = ($48 | 0) == ($50 | 0);
+ $add164 = $i_1 + 2 | 0;
+ if ($cmp159) {
+ label = 36;
+ break;
+ } else {
+ $i_1 = $add164;
+ label = 34;
+ break;
+ }
+ case 36:
+ $m_idAttIndex = $parser + 372 | 0;
+ HEAP32[$m_idAttIndex >> 2] = $i_1;
+ label = 38;
+ break;
+ case 37:
+ $m_idAttIndex167 = $parser + 372 | 0;
+ HEAP32[$m_idAttIndex167 >> 2] = -1;
+ label = 38;
+ break;
+ case 38:
+ $cmp170362 = ($6 | 0) > 0;
+ if ($cmp170362) {
+ label = 39;
+ break;
+ } else {
+ $nPrefixes_2_lcssa = $nPrefixes_0_lcssa;
+ $attIndex_2_lcssa = $attIndex_0_lcssa;
+ label = 48;
+ break;
+ }
+ case 39:
+ $defaultAtts173 = $elementType_0 + 20 | 0;
+ $nPrefixes_2363 = $nPrefixes_0_lcssa;
+ $i_2364 = 0;
+ $attIndex_2365 = $attIndex_0_lcssa;
+ label = 40;
+ break;
+ case 40:
+ $51 = HEAP32[$defaultAtts173 >> 2] | 0;
+ $id175 = $51 + ($i_2364 * 12 & -1) | 0;
+ $52 = HEAP32[$id175 >> 2] | 0;
+ $name176 = $52 | 0;
+ $53 = HEAP32[$name176 >> 2] | 0;
+ $arrayidx177 = $53 - 1 | 0;
+ $54 = HEAP8[$arrayidx177] | 0;
+ $tobool178 = $54 << 24 >> 24 == 0;
+ if ($tobool178) {
+ label = 41;
+ break;
+ } else {
+ $attIndex_3 = $attIndex_2365;
+ $nPrefixes_3 = $nPrefixes_2363;
+ label = 47;
+ break;
+ }
+ case 41:
+ $value = $51 + ($i_2364 * 12 & -1) + 8 | 0;
+ $55 = HEAP32[$value >> 2] | 0;
+ $tobool180 = ($55 | 0) == 0;
+ if ($tobool180) {
+ $attIndex_3 = $attIndex_2365;
+ $nPrefixes_3 = $nPrefixes_2363;
+ label = 47;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $prefix183 = $52 + 4 | 0;
+ $56 = HEAP32[$prefix183 >> 2] | 0;
+ $tobool184 = ($56 | 0) == 0;
+ if ($tobool184) {
+ label = 46;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $xmlns187 = $52 + 9 | 0;
+ $57 = HEAP8[$xmlns187] | 0;
+ $tobool188 = $57 << 24 >> 24 == 0;
+ if ($tobool188) {
+ label = 45;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $call195 = _addBinding($parser, $56, $52, $55, $bindingsPtr) | 0;
+ $tobool196 = ($call195 | 0) == 0;
+ if ($tobool196) {
+ $attIndex_3 = $attIndex_2365;
+ $nPrefixes_3 = $nPrefixes_2363;
+ label = 47;
+ break;
+ } else {
+ $retval_0 = $call195;
+ label = 116;
+ break;
+ }
+ case 45:
+ HEAP8[$arrayidx177] = 2;
+ $inc203 = $nPrefixes_2363 + 1 | 0;
+ $58 = HEAP32[$id175 >> 2] | 0;
+ $name205 = $58 | 0;
+ $59 = HEAP32[$name205 >> 2] | 0;
+ $inc206 = $attIndex_2365 + 1 | 0;
+ $arrayidx207 = $17 + ($attIndex_2365 << 2) | 0;
+ HEAP32[$arrayidx207 >> 2] = $59;
+ $60 = HEAP32[$value >> 2] | 0;
+ $inc209 = $attIndex_2365 + 2 | 0;
+ $arrayidx210 = $17 + ($inc206 << 2) | 0;
+ HEAP32[$arrayidx210 >> 2] = $60;
+ $attIndex_3 = $inc209;
+ $nPrefixes_3 = $inc203;
+ label = 47;
+ break;
+ case 46:
+ HEAP8[$arrayidx177] = 1;
+ $61 = HEAP32[$id175 >> 2] | 0;
+ $name217 = $61 | 0;
+ $62 = HEAP32[$name217 >> 2] | 0;
+ $inc218 = $attIndex_2365 + 1 | 0;
+ $arrayidx219 = $17 + ($attIndex_2365 << 2) | 0;
+ HEAP32[$arrayidx219 >> 2] = $62;
+ $63 = HEAP32[$value >> 2] | 0;
+ $inc221 = $attIndex_2365 + 2 | 0;
+ $arrayidx222 = $17 + ($inc218 << 2) | 0;
+ HEAP32[$arrayidx222 >> 2] = $63;
+ $attIndex_3 = $inc221;
+ $nPrefixes_3 = $nPrefixes_2363;
+ label = 47;
+ break;
+ case 47:
+ $inc226 = $i_2364 + 1 | 0;
+ $cmp170 = ($inc226 | 0) < ($6 | 0);
+ if ($cmp170) {
+ $nPrefixes_2363 = $nPrefixes_3;
+ $i_2364 = $inc226;
+ $attIndex_2365 = $attIndex_3;
+ label = 40;
+ break;
+ } else {
+ $nPrefixes_2_lcssa = $nPrefixes_3;
+ $attIndex_2_lcssa = $attIndex_3;
+ label = 48;
+ break;
+ }
+ case 48:
+ $arrayidx228 = $17 + ($attIndex_2_lcssa << 2) | 0;
+ HEAP32[$arrayidx228 >> 2] = 0;
+ $tobool229 = ($nPrefixes_2_lcssa | 0) == 0;
+ if ($tobool229) {
+ $i_4_ph = 0;
+ label = 49;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 49:
+ $cmp465317 = ($i_4_ph | 0) < ($attIndex_2_lcssa | 0);
+ if ($cmp465317) {
+ $i_4318 = $i_4_ph;
+ label = 91;
+ break;
+ } else {
+ label = 90;
+ break;
+ }
+ case 50:
+ $m_nsAttsVersion = $parser + 384 | 0;
+ $64 = HEAP32[$m_nsAttsVersion >> 2] | 0;
+ $m_nsAttsPower = $parser + 388 | 0;
+ $65 = HEAP8[$m_nsAttsPower] | 0;
+ $conv232 = $65 & 255;
+ $shl233 = $nPrefixes_2_lcssa << 1;
+ $shr = $shl233 >> $conv232;
+ $tobool236 = ($shr | 0) == 0;
+ if ($tobool236) {
+ label = 55;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $m_nsAttsPower_promoted = HEAP8[$m_nsAttsPower] | 0;
+ $66 = $m_nsAttsPower_promoted;
+ label = 52;
+ break;
+ case 52:
+ $inc240 = $66 + 1 & 255;
+ $conv241 = $66 & 255;
+ $shr242 = $nPrefixes_2_lcssa >> $conv241;
+ $tobool243 = ($shr242 | 0) == 0;
+ if ($tobool243) {
+ label = 53;
+ break;
+ } else {
+ $66 = $inc240;
+ label = 52;
+ break;
+ }
+ case 53:
+ $cmp246 = ($inc240 & 255) < 3;
+ $_inc240 = $cmp246 ? 3 : $inc240;
+ HEAP8[$m_nsAttsPower] = $_inc240;
+ $conv252 = $_inc240 & 255;
+ $realloc_fcn255 = $parser + 16 | 0;
+ $67 = HEAP32[$realloc_fcn255 >> 2] | 0;
+ $m_nsAtts = $parser + 380 | 0;
+ $68 = HEAP32[$m_nsAtts >> 2] | 0;
+ $69 = $68;
+ $mul256 = 12 << $conv252;
+ $call257 = FUNCTION_TABLE_iii[$67 & 1023]($69, $mul256) | 0;
+ $tobool258 = ($call257 | 0) == 0;
+ if ($tobool258) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 54:
+ $70 = $call257;
+ HEAP32[$m_nsAtts >> 2] = $70;
+ $nsAttsSize_0307 = 1 << $conv252;
+ $nsAttsSize_0310_ph = $nsAttsSize_0307;
+ label = 56;
+ break;
+ case 55:
+ $nsAttsSize_0 = 1 << $conv232;
+ $tobool263 = ($64 | 0) == 0;
+ if ($tobool263) {
+ $nsAttsSize_0310_ph = $nsAttsSize_0;
+ label = 56;
+ break;
+ } else {
+ $version_1 = $64;
+ $nsAttsSize_0309 = $nsAttsSize_0;
+ label = 58;
+ break;
+ }
+ case 56:
+ $m_nsAtts270 = $parser + 380 | 0;
+ $j231_0356 = $nsAttsSize_0310_ph;
+ label = 57;
+ break;
+ case 57:
+ $dec269 = $j231_0356 - 1 | 0;
+ $71 = HEAP32[$m_nsAtts270 >> 2] | 0;
+ $version272 = $71 + ($dec269 * 12 & -1) | 0;
+ HEAP32[$version272 >> 2] = -1;
+ $cmp266 = ($dec269 | 0) == 0;
+ if ($cmp266) {
+ $version_1 = -1;
+ $nsAttsSize_0309 = $nsAttsSize_0310_ph;
+ label = 58;
+ break;
+ } else {
+ $j231_0356 = $dec269;
+ label = 57;
+ break;
+ }
+ case 58:
+ $dec275 = $version_1 - 1 | 0;
+ HEAP32[$m_nsAttsVersion >> 2] = $dec275;
+ $cmp278351 = ($attIndex_2_lcssa | 0) > 0;
+ if ($cmp278351) {
+ label = 59;
+ break;
+ } else {
+ $i_4_ph = 0;
+ label = 49;
+ break;
+ }
+ case 59:
+ $m_hash_secret_salt = $parser + 472 | 0;
+ $attributeIds = $0 + 40 | 0;
+ $m_tempPool327 = $parser + 400 | 0;
+ $ptr328 = $parser + 412 | 0;
+ $end330 = $parser + 408 | 0;
+ $sub = $nsAttsSize_0309 - 1 | 0;
+ $m_nsAtts350 = $parser + 380 | 0;
+ $m_ns_triplets = $parser + 233 | 0;
+ $start437 = $parser + 416 | 0;
+ $m_namespaceSeparator = $parser + 456 | 0;
+ $start362 = $parser + 416 | 0;
+ $neg = -$nsAttsSize_0309 | 0;
+ $shr391 = $sub >>> 2;
+ $ptr302 = $parser + 412 | 0;
+ $end = $parser + 408 | 0;
+ $m_tempPool301 = $parser + 400 | 0;
+ $nPrefixes_4352 = $nPrefixes_2_lcssa;
+ $i_3353 = 0;
+ label = 60;
+ break;
+ case 60:
+ $arrayidx281 = $17 + ($i_3353 << 2) | 0;
+ $72 = HEAP32[$arrayidx281 >> 2] | 0;
+ $arrayidx282 = $72 - 1 | 0;
+ $73 = HEAP8[$arrayidx282] | 0;
+ $cmp284 = $73 << 24 >> 24 == 2;
+ if ($cmp284) {
+ label = 61;
+ break;
+ } else {
+ label = 88;
+ break;
+ }
+ case 61:
+ $74 = HEAP32[$m_hash_secret_salt >> 2] | 0;
+ HEAP8[$arrayidx282] = 0;
+ $call289 = _lookup($parser, $attributeIds, $72, 0) | 0;
+ $prefix290 = $call289 + 4 | 0;
+ $75 = $prefix290;
+ $76 = HEAP32[$75 >> 2] | 0;
+ $binding291 = $76 + 4 | 0;
+ $77 = HEAP32[$binding291 >> 2] | 0;
+ $tobool292 = ($77 | 0) == 0;
+ if ($tobool292) {
+ $retval_0 = 27;
+ label = 116;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 62:
+ $uriLen = $77 + 20 | 0;
+ $78 = HEAP32[$uriLen >> 2] | 0;
+ $cmp296320 = ($78 | 0) > 0;
+ if ($cmp296320) {
+ label = 63;
+ break;
+ } else {
+ $uriHash_0_lcssa = $74;
+ label = 67;
+ break;
+ }
+ case 63:
+ $uri299 = $77 + 16 | 0;
+ $j231_1321 = 0;
+ $uriHash_0322 = $74;
+ label = 64;
+ break;
+ case 64:
+ $79 = HEAP32[$uri299 >> 2] | 0;
+ $arrayidx300 = $79 + $j231_1321 | 0;
+ $80 = HEAP8[$arrayidx300] | 0;
+ $81 = HEAP32[$ptr302 >> 2] | 0;
+ $82 = HEAP32[$end >> 2] | 0;
+ $cmp304 = ($81 | 0) == ($82 | 0);
+ if ($cmp304) {
+ label = 65;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 65:
+ $call308 = _poolGrow($m_tempPool301) | 0;
+ $tobool309 = $call308 << 24 >> 24 == 0;
+ if ($tobool309) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ $83 = HEAP32[$ptr302 >> 2] | 0;
+ $incdec_ptr = $83 + 1 | 0;
+ HEAP32[$ptr302 >> 2] = $incdec_ptr;
+ HEAP8[$83] = $80;
+ $mul314 = $uriHash_0322 * 1000003 & -1;
+ $conv315 = $80 & 255;
+ $xor = $conv315 ^ $mul314;
+ $inc317 = $j231_1321 + 1 | 0;
+ $84 = HEAP32[$uriLen >> 2] | 0;
+ $cmp296 = ($inc317 | 0) < ($84 | 0);
+ if ($cmp296) {
+ $j231_1321 = $inc317;
+ $uriHash_0322 = $xor;
+ label = 64;
+ break;
+ } else {
+ $uriHash_0_lcssa = $xor;
+ label = 67;
+ break;
+ }
+ case 67:
+ $s_0 = $72;
+ label = 68;
+ break;
+ case 68:
+ $incdec_ptr320 = $s_0 + 1 | 0;
+ $85 = HEAP8[$s_0] | 0;
+ $cmp322 = $85 << 24 >> 24 == 58;
+ if ($cmp322) {
+ $uriHash_1 = $uriHash_0_lcssa;
+ $s_1 = $incdec_ptr320;
+ label = 69;
+ break;
+ } else {
+ $s_0 = $incdec_ptr320;
+ label = 68;
+ break;
+ }
+ case 69:
+ $86 = HEAP8[$s_1] | 0;
+ $87 = HEAP32[$ptr328 >> 2] | 0;
+ $88 = HEAP32[$end330 >> 2] | 0;
+ $cmp331 = ($87 | 0) == ($88 | 0);
+ if ($cmp331) {
+ label = 70;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 70:
+ $call335 = _poolGrow($m_tempPool327) | 0;
+ $tobool336 = $call335 << 24 >> 24 == 0;
+ if ($tobool336) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 71:
+ $89 = HEAP8[$s_1] | 0;
+ $90 = HEAP32[$ptr328 >> 2] | 0;
+ $incdec_ptr341 = $90 + 1 | 0;
+ HEAP32[$ptr328 >> 2] = $incdec_ptr341;
+ HEAP8[$90] = $89;
+ $mul344 = $uriHash_1 * 1000003 & -1;
+ $conv345 = $86 & 255;
+ $xor346 = $conv345 ^ $mul344;
+ $incdec_ptr347 = $s_1 + 1 | 0;
+ $91 = HEAP8[$s_1] | 0;
+ $tobool348 = $91 << 24 >> 24 == 0;
+ if ($tobool348) {
+ label = 72;
+ break;
+ } else {
+ $uriHash_1 = $xor346;
+ $s_1 = $incdec_ptr347;
+ label = 69;
+ break;
+ }
+ case 72:
+ $and = $xor346 & $sub;
+ $92 = HEAP32[$m_nsAtts350 >> 2] | 0;
+ $version352337 = $92 + ($and * 12 & -1) | 0;
+ $93 = HEAP32[$version352337 >> 2] | 0;
+ $cmp353338 = ($93 | 0) == ($dec275 | 0);
+ if ($cmp353338) {
+ label = 73;
+ break;
+ } else {
+ $j231_2_lcssa = $and;
+ label = 81;
+ break;
+ }
+ case 73:
+ $and386 = $xor346 & $neg;
+ $j231_2339 = $and;
+ $step_0340 = 0;
+ $94 = $92;
+ label = 74;
+ break;
+ case 74:
+ $hash = $94 + ($j231_2339 * 12 & -1) + 4 | 0;
+ $95 = HEAP32[$hash >> 2] | 0;
+ $cmp358 = ($xor346 | 0) == ($95 | 0);
+ if ($cmp358) {
+ label = 75;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 75:
+ $96 = HEAP32[$start362 >> 2] | 0;
+ $uriName = $94 + ($j231_2339 * 12 & -1) + 8 | 0;
+ $97 = HEAP32[$uriName >> 2] | 0;
+ $98 = HEAP8[$96] | 0;
+ $99 = HEAP8[$97] | 0;
+ $cmp368328 = $98 << 24 >> 24 != $99 << 24 >> 24;
+ $cmp371329 = $98 << 24 >> 24 == 0;
+ $or_cond330 = $cmp368328 | $cmp371329;
+ if ($or_cond330) {
+ $cmp371_lcssa = $cmp371329;
+ label = 77;
+ break;
+ } else {
+ $s1_0331 = $96;
+ $s2_0332 = $97;
+ label = 76;
+ break;
+ }
+ case 76:
+ $incdec_ptr375 = $s1_0331 + 1 | 0;
+ $incdec_ptr376 = $s2_0332 + 1 | 0;
+ $100 = HEAP8[$incdec_ptr375] | 0;
+ $101 = HEAP8[$incdec_ptr376] | 0;
+ $cmp368 = $100 << 24 >> 24 != $101 << 24 >> 24;
+ $cmp371 = $100 << 24 >> 24 == 0;
+ $or_cond = $cmp368 | $cmp371;
+ if ($or_cond) {
+ $cmp371_lcssa = $cmp371;
+ label = 77;
+ break;
+ } else {
+ $s1_0331 = $incdec_ptr375;
+ $s2_0332 = $incdec_ptr376;
+ label = 76;
+ break;
+ }
+ case 77:
+ if ($cmp371_lcssa) {
+ $retval_0 = 8;
+ label = 116;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $tobool384 = $step_0340 << 24 >> 24 == 0;
+ if ($tobool384) {
+ label = 79;
+ break;
+ } else {
+ $step_1 = $step_0340;
+ label = 80;
+ break;
+ }
+ case 79:
+ $102 = HEAP8[$m_nsAttsPower] | 0;
+ $conv388 = $102 & 255;
+ $sub389 = $conv388 - 1 | 0;
+ $shr390 = $and386 >>> ($sub389 >>> 0);
+ $and392 = $shr390 & $shr391;
+ $or = $and392 | 1;
+ $conv393 = $or & 255;
+ $step_1 = $conv393;
+ label = 80;
+ break;
+ case 80:
+ $conv395 = $step_1 & 255;
+ $cmp396 = ($j231_2339 | 0) < ($conv395 | 0);
+ $sub400 = $cmp396 ? $nsAttsSize_0309 : 0;
+ $sub400_j231_2339 = $j231_2339 + $sub400 | 0;
+ $j231_2_be = $sub400_j231_2339 - $conv395 | 0;
+ $103 = HEAP32[$m_nsAtts350 >> 2] | 0;
+ $version352 = $103 + ($j231_2_be * 12 & -1) | 0;
+ $104 = HEAP32[$version352 >> 2] | 0;
+ $cmp353 = ($104 | 0) == ($dec275 | 0);
+ if ($cmp353) {
+ $j231_2339 = $j231_2_be;
+ $step_0340 = $step_1;
+ $94 = $103;
+ label = 74;
+ break;
+ } else {
+ $j231_2_lcssa = $j231_2_be;
+ label = 81;
+ break;
+ }
+ case 81:
+ $105 = HEAP8[$m_ns_triplets] | 0;
+ $tobool406 = $105 << 24 >> 24 == 0;
+ if ($tobool406) {
+ label = 86;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 82:
+ $106 = HEAP8[$m_namespaceSeparator] | 0;
+ $107 = HEAP32[$ptr328 >> 2] | 0;
+ $arrayidx410 = $107 - 1 | 0;
+ HEAP8[$arrayidx410] = $106;
+ $prefix411 = $77 | 0;
+ $108 = HEAP32[$prefix411 >> 2] | 0;
+ $name412 = $108 | 0;
+ $109 = HEAP32[$name412 >> 2] | 0;
+ $s_2 = $109;
+ label = 83;
+ break;
+ case 83:
+ $110 = HEAP32[$ptr328 >> 2] | 0;
+ $111 = HEAP32[$end330 >> 2] | 0;
+ $cmp418 = ($110 | 0) == ($111 | 0);
+ if ($cmp418) {
+ label = 84;
+ break;
+ } else {
+ label = 85;
+ break;
+ }
+ case 84:
+ $call422 = _poolGrow($m_tempPool327) | 0;
+ $tobool423 = $call422 << 24 >> 24 == 0;
+ if ($tobool423) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 85;
+ break;
+ }
+ case 85:
+ $112 = HEAP8[$s_2] | 0;
+ $113 = HEAP32[$ptr328 >> 2] | 0;
+ $incdec_ptr428 = $113 + 1 | 0;
+ HEAP32[$ptr328 >> 2] = $incdec_ptr428;
+ HEAP8[$113] = $112;
+ $incdec_ptr432 = $s_2 + 1 | 0;
+ $114 = HEAP8[$s_2] | 0;
+ $tobool433 = $114 << 24 >> 24 == 0;
+ if ($tobool433) {
+ label = 86;
+ break;
+ } else {
+ $s_2 = $incdec_ptr432;
+ label = 83;
+ break;
+ }
+ case 86:
+ $115 = HEAP32[$start437 >> 2] | 0;
+ $116 = HEAP32[$ptr328 >> 2] | 0;
+ HEAP32[$start437 >> 2] = $116;
+ HEAP32[$arrayidx281 >> 2] = $115;
+ $117 = HEAP32[$m_nsAtts350 >> 2] | 0;
+ $version445 = $117 + ($j231_2_lcssa * 12 & -1) | 0;
+ HEAP32[$version445 >> 2] = $dec275;
+ $118 = HEAP32[$m_nsAtts350 >> 2] | 0;
+ $hash448 = $118 + ($j231_2_lcssa * 12 & -1) + 4 | 0;
+ HEAP32[$hash448 >> 2] = $xor346;
+ $119 = HEAP32[$m_nsAtts350 >> 2] | 0;
+ $uriName451 = $119 + ($j231_2_lcssa * 12 & -1) + 8 | 0;
+ HEAP32[$uriName451 >> 2] = $115;
+ $dec452 = $nPrefixes_4352 - 1 | 0;
+ $tobool453 = ($dec452 | 0) == 0;
+ if ($tobool453) {
+ label = 87;
+ break;
+ } else {
+ $nPrefixes_5 = $dec452;
+ label = 89;
+ break;
+ }
+ case 87:
+ $add455 = $i_3353 + 2 | 0;
+ $i_4_ph = $add455;
+ label = 49;
+ break;
+ case 88:
+ HEAP8[$arrayidx282] = 0;
+ $nPrefixes_5 = $nPrefixes_4352;
+ label = 89;
+ break;
+ case 89:
+ $add461 = $i_3353 + 2 | 0;
+ $cmp278 = ($add461 | 0) < ($attIndex_2_lcssa | 0);
+ if ($cmp278) {
+ $nPrefixes_4352 = $nPrefixes_5;
+ $i_3353 = $add461;
+ label = 60;
+ break;
+ } else {
+ $i_4_ph = $add461;
+ label = 49;
+ break;
+ }
+ case 90:
+ $binding_0314 = HEAP32[$bindingsPtr >> 2] | 0;
+ $tobool474315 = ($binding_0314 | 0) == 0;
+ if ($tobool474315) {
+ label = 93;
+ break;
+ } else {
+ $binding_0316 = $binding_0314;
+ label = 92;
+ break;
+ }
+ case 91:
+ $arrayidx468 = $17 + ($i_4318 << 2) | 0;
+ $120 = HEAP32[$arrayidx468 >> 2] | 0;
+ $arrayidx469 = $120 - 1 | 0;
+ HEAP8[$arrayidx469] = 0;
+ $add471 = $i_4318 + 2 | 0;
+ $cmp465 = ($add471 | 0) < ($attIndex_2_lcssa | 0);
+ if ($cmp465) {
+ $i_4318 = $add471;
+ label = 91;
+ break;
+ } else {
+ label = 90;
+ break;
+ }
+ case 92:
+ $attId476 = $binding_0316 + 12 | 0;
+ $121 = HEAP32[$attId476 >> 2] | 0;
+ $name477 = $121 | 0;
+ $122 = HEAP32[$name477 >> 2] | 0;
+ $arrayidx478 = $122 - 1 | 0;
+ HEAP8[$arrayidx478] = 0;
+ $nextTagBinding = $binding_0316 + 4 | 0;
+ $binding_0 = HEAP32[$nextTagBinding >> 2] | 0;
+ $tobool474 = ($binding_0 | 0) == 0;
+ if ($tobool474) {
+ label = 93;
+ break;
+ } else {
+ $binding_0316 = $binding_0;
+ label = 92;
+ break;
+ }
+ case 93:
+ $m_ns481 = $parser + 232 | 0;
+ $123 = HEAP8[$m_ns481] | 0;
+ $tobool482 = $123 << 24 >> 24 == 0;
+ if ($tobool482) {
+ $retval_0 = 0;
+ label = 116;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 94:
+ $prefix485 = $elementType_0 + 4 | 0;
+ $124 = HEAP32[$prefix485 >> 2] | 0;
+ $tobool486 = ($124 | 0) == 0;
+ if ($tobool486) {
+ label = 98;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 95:
+ $binding489 = $124 + 4 | 0;
+ $125 = HEAP32[$binding489 >> 2] | 0;
+ $tobool490 = ($125 | 0) == 0;
+ if ($tobool490) {
+ $retval_0 = 27;
+ label = 116;
+ break;
+ } else {
+ label = 96;
+ break;
+ }
+ case 96:
+ $126 = HEAP32[$str >> 2] | 0;
+ $localPart_0 = $126;
+ label = 97;
+ break;
+ case 97:
+ $incdec_ptr495 = $localPart_0 + 1 | 0;
+ $127 = HEAP8[$localPart_0] | 0;
+ $cmp497 = $127 << 24 >> 24 == 58;
+ if ($cmp497) {
+ $binding_1 = $125;
+ $localPart_1 = $incdec_ptr495;
+ label = 100;
+ break;
+ } else {
+ $localPart_0 = $incdec_ptr495;
+ label = 97;
+ break;
+ }
+ case 98:
+ $binding502 = $0 + 136 | 0;
+ $128 = HEAP32[$binding502 >> 2] | 0;
+ $tobool503 = ($128 | 0) == 0;
+ if ($tobool503) {
+ $retval_0 = 0;
+ label = 116;
+ break;
+ } else {
+ label = 99;
+ break;
+ }
+ case 99:
+ $129 = HEAP32[$str >> 2] | 0;
+ $binding_1 = $128;
+ $localPart_1 = $129;
+ label = 100;
+ break;
+ case 100:
+ $m_ns_triplets511 = $parser + 233 | 0;
+ $130 = HEAP8[$m_ns_triplets511] | 0;
+ $tobool513 = $130 << 24 >> 24 == 0;
+ if ($tobool513) {
+ $prefixLen_1 = 0;
+ label = 104;
+ break;
+ } else {
+ label = 101;
+ break;
+ }
+ case 101:
+ $prefix515 = $binding_1 | 0;
+ $131 = HEAP32[$prefix515 >> 2] | 0;
+ $name516 = $131 | 0;
+ $132 = HEAP32[$name516 >> 2] | 0;
+ $tobool517 = ($132 | 0) == 0;
+ if ($tobool517) {
+ $prefixLen_1 = 0;
+ label = 104;
+ break;
+ } else {
+ label = 102;
+ break;
+ }
+ case 102:
+ $133 = HEAP32[$prefix515 >> 2] | 0;
+ $name522 = $133 | 0;
+ $134 = HEAP32[$name522 >> 2] | 0;
+ $prefixLen_0 = 0;
+ label = 103;
+ break;
+ case 103:
+ $inc520 = $prefixLen_0 + 1 | 0;
+ $arrayidx523 = $134 + $prefixLen_0 | 0;
+ $135 = HEAP8[$arrayidx523] | 0;
+ $tobool524 = $135 << 24 >> 24 == 0;
+ if ($tobool524) {
+ $prefixLen_1 = $inc520;
+ label = 104;
+ break;
+ } else {
+ $prefixLen_0 = $inc520;
+ label = 103;
+ break;
+ }
+ case 104:
+ $localPart528 = $tagNamePtr + 4 | 0;
+ HEAP32[$localPart528 >> 2] = $localPart_1;
+ $uriLen529 = $binding_1 + 20 | 0;
+ $136 = HEAP32[$uriLen529 >> 2] | 0;
+ $uriLen530 = $tagNamePtr + 16 | 0;
+ HEAP32[$uriLen530 >> 2] = $136;
+ $prefix531 = $binding_1 | 0;
+ $137 = HEAP32[$prefix531 >> 2] | 0;
+ $name532 = $137 | 0;
+ $138 = HEAP32[$name532 >> 2] | 0;
+ $prefix533 = $tagNamePtr + 8 | 0;
+ HEAP32[$prefix533 >> 2] = $138;
+ $prefixLen534 = $tagNamePtr + 20 | 0;
+ HEAP32[$prefixLen534 >> 2] = $prefixLen_1;
+ $i_5 = 0;
+ label = 105;
+ break;
+ case 105:
+ $inc536 = $i_5 + 1 | 0;
+ $arrayidx537 = $localPart_1 + $i_5 | 0;
+ $139 = HEAP8[$arrayidx537] | 0;
+ $tobool538 = $139 << 24 >> 24 == 0;
+ if ($tobool538) {
+ label = 106;
+ break;
+ } else {
+ $i_5 = $inc536;
+ label = 105;
+ break;
+ }
+ case 106:
+ $140 = HEAP32[$uriLen529 >> 2] | 0;
+ $add542 = $inc536 + $prefixLen_1 | 0;
+ $add543 = $add542 + $140 | 0;
+ $uriAlloc = $binding_1 + 24 | 0;
+ $141 = HEAP32[$uriAlloc >> 2] | 0;
+ $cmp544 = ($add543 | 0) > ($141 | 0);
+ if ($cmp544) {
+ label = 107;
+ break;
+ } else {
+ label = 113;
+ break;
+ }
+ case 107:
+ $malloc_fcn = $parser + 12 | 0;
+ $142 = HEAP32[$malloc_fcn >> 2] | 0;
+ $add548 = $add543 + 24 | 0;
+ $call550 = FUNCTION_TABLE_ii[$142 & 1023]($add548) | 0;
+ $tobool551 = ($call550 | 0) == 0;
+ if ($tobool551) {
+ $retval_0 = 1;
+ label = 116;
+ break;
+ } else {
+ label = 108;
+ break;
+ }
+ case 108:
+ HEAP32[$uriAlloc >> 2] = $add548;
+ $uri556 = $binding_1 + 16 | 0;
+ $143 = HEAP32[$uri556 >> 2] | 0;
+ $144 = HEAP32[$uriLen529 >> 2] | 0;
+ _memcpy($call550 | 0, $143 | 0, $144);
+ $m_tagStack = $parser + 348 | 0;
+ $p_0311 = HEAP32[$m_tagStack >> 2] | 0;
+ $tobool560312 = ($p_0311 | 0) == 0;
+ if ($tobool560312) {
+ label = 112;
+ break;
+ } else {
+ $p_0313 = $p_0311;
+ label = 109;
+ break;
+ }
+ case 109:
+ $str563 = $p_0313 + 12 | 0;
+ $145 = HEAP32[$str563 >> 2] | 0;
+ $146 = HEAP32[$uri556 >> 2] | 0;
+ $cmp565 = ($145 | 0) == ($146 | 0);
+ if ($cmp565) {
+ label = 110;
+ break;
+ } else {
+ label = 111;
+ break;
+ }
+ case 110:
+ HEAP32[$str563 >> 2] = $call550;
+ label = 111;
+ break;
+ case 111:
+ $parent = $p_0313 | 0;
+ $p_0 = HEAP32[$parent >> 2] | 0;
+ $tobool560 = ($p_0 | 0) == 0;
+ if ($tobool560) {
+ label = 112;
+ break;
+ } else {
+ $p_0313 = $p_0;
+ label = 109;
+ break;
+ }
+ case 112:
+ $free_fcn = $parser + 20 | 0;
+ $147 = HEAP32[$free_fcn >> 2] | 0;
+ $148 = HEAP32[$uri556 >> 2] | 0;
+ FUNCTION_TABLE_vi[$147 & 1023]($148);
+ HEAP32[$uri556 >> 2] = $call550;
+ label = 113;
+ break;
+ case 113:
+ $uri577 = $binding_1 + 16 | 0;
+ $149 = HEAP32[$uri577 >> 2] | 0;
+ $150 = HEAP32[$uriLen529 >> 2] | 0;
+ $add_ptr579 = $149 + $150 | 0;
+ _memcpy($add_ptr579 | 0, $localPart_1 | 0, $inc536);
+ $tobool581 = ($prefixLen_1 | 0) == 0;
+ if ($tobool581) {
+ label = 115;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 114:
+ $add_ptr579_sum = $150 + $i_5 | 0;
+ $add_ptr584 = $149 + $add_ptr579_sum | 0;
+ $m_namespaceSeparator585 = $parser + 456 | 0;
+ $151 = HEAP8[$m_namespaceSeparator585] | 0;
+ HEAP8[$add_ptr584] = $151;
+ $add_ptr584_sum = $add_ptr579_sum + 1 | 0;
+ $add_ptr586 = $149 + $add_ptr584_sum | 0;
+ $152 = HEAP32[$prefix531 >> 2] | 0;
+ $name588 = $152 | 0;
+ $153 = HEAP32[$name588 >> 2] | 0;
+ _memcpy($add_ptr586 | 0, $153 | 0, $prefixLen_1);
+ label = 115;
+ break;
+ case 115:
+ $154 = HEAP32[$uri577 >> 2] | 0;
+ HEAP32[$str >> 2] = $154;
+ $retval_0 = 0;
+ label = 116;
+ break;
+ case 116:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normalizeLines($s) {
+ $s = $s | 0;
+ var $s_addr_0 = 0, $0 = 0, $incdec_ptr = 0, $s_addr_1 = 0, $p_0 = 0, $1 = 0, $cmp8 = 0, $incdec_ptr12 = 0, $2 = 0, $cmp14 = 0, $incdec_ptr17 = 0, $incdec_ptr17_incdec_ptr12 = 0, $incdec_ptr19 = 0, $s_addr_2 = 0, $p_1 = 0, $3 = 0, $tobool = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s_addr_0 = $s;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[$s_addr_0] | 0;
+ if (($0 << 24 >> 24 | 0) == 13) {
+ $p_0 = $s_addr_0;
+ $s_addr_1 = $s_addr_0;
+ label = 5;
+ break;
+ } else if (($0 << 24 >> 24 | 0) == 0) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $s_addr_0 + 1 | 0;
+ $s_addr_0 = $incdec_ptr;
+ label = 3;
+ break;
+ case 5:
+ $1 = HEAP8[$s_addr_1] | 0;
+ $cmp8 = $1 << 24 >> 24 == 13;
+ if ($cmp8) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ HEAP8[$p_0] = 10;
+ $incdec_ptr12 = $s_addr_1 + 1 | 0;
+ $2 = HEAP8[$incdec_ptr12] | 0;
+ $cmp14 = $2 << 24 >> 24 == 10;
+ $incdec_ptr17 = $s_addr_1 + 2 | 0;
+ $incdec_ptr17_incdec_ptr12 = $cmp14 ? $incdec_ptr17 : $incdec_ptr12;
+ $s_addr_2 = $incdec_ptr17_incdec_ptr12;
+ label = 8;
+ break;
+ case 7:
+ $incdec_ptr19 = $s_addr_1 + 1 | 0;
+ HEAP8[$p_0] = $1;
+ $s_addr_2 = $incdec_ptr19;
+ label = 8;
+ break;
+ case 8:
+ $p_1 = $p_0 + 1 | 0;
+ $3 = HEAP8[$s_addr_2] | 0;
+ $tobool = $3 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ $p_0 = $p_1;
+ $s_addr_1 = $s_addr_2;
+ label = 5;
+ break;
+ }
+ case 9:
+ HEAP8[$p_1] = 0;
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _epilogProcessor($parser, $s, $end, $nextPtr) {
+ $parser = $parser | 0;
+ $s = $s | 0;
+ $end = $end | 0;
+ $nextPtr = $nextPtr | 0;
+ var $next = 0, $m_processor = 0, $m_eventPtr = 0, $m_encoding = 0, $m_eventEndPtr = 0, $m_defaultHandler7 = 0, $parsing39 = 0, $s_addr_0 = 0, $0 = 0, $arrayidx = 0, $1 = 0, $call = 0, $2 = 0, $m_defaultHandler = 0, $3 = 0, $tobool = 0, $4 = 0, $5 = 0, $parsing = 0, $6 = 0, $cmp = 0, $7 = 0, $8 = 0, $tobool8 = 0, $9 = 0, $10 = 0, $11 = 0, $12 = 0, $call14 = 0, $tobool15 = 0, $13 = 0, $14 = 0, $call20 = 0, $tobool21 = 0, $15 = 0, $finalBuffer = 0, $16 = 0, $tobool28 = 0, $finalBuffer33 = 0, $17 = 0, $tobool34 = 0, $18 = 0, $19 = 0, $20 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $next = __stackBase__ | 0;
+ $m_processor = $parser + 264 | 0;
+ HEAP32[$m_processor >> 2] = 192;
+ $m_eventPtr = $parser + 272 | 0;
+ HEAP32[$m_eventPtr >> 2] = $s;
+ $m_encoding = $parser + 144 | 0;
+ $m_eventEndPtr = $parser + 276 | 0;
+ $m_defaultHandler7 = $parser + 80 | 0;
+ $parsing39 = $parser + 464 | 0;
+ $s_addr_0 = $s;
+ label = 3;
+ break;
+ case 3:
+ HEAP32[$next >> 2] = 0;
+ $0 = HEAP32[$m_encoding >> 2] | 0;
+ $arrayidx = $0 | 0;
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$1 & 1023]($0, $s_addr_0, $end, $next) | 0;
+ $2 = HEAP32[$next >> 2] | 0;
+ HEAP32[$m_eventEndPtr >> 2] = $2;
+ if (($call | 0) == (-15 | 0)) {
+ label = 4;
+ break;
+ } else if (($call | 0) == (-4 | 0)) {
+ label = 7;
+ break;
+ } else if (($call | 0) == 15) {
+ label = 8;
+ break;
+ } else if (($call | 0) == 11) {
+ label = 10;
+ break;
+ } else if (($call | 0) == 13) {
+ label = 11;
+ break;
+ } else if (($call | 0) == 0) {
+ label = 12;
+ break;
+ } else if (($call | 0) == (-1 | 0)) {
+ label = 13;
+ break;
+ } else if (($call | 0) == (-2 | 0)) {
+ label = 15;
+ break;
+ } else {
+ $retval_0 = 9;
+ label = 19;
+ break;
+ }
+ case 4:
+ $m_defaultHandler = $parser + 80 | 0;
+ $3 = HEAP32[$m_defaultHandler >> 2] | 0;
+ $tobool = ($3 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $4 = HEAP32[$m_encoding >> 2] | 0;
+ $5 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $4, $s_addr_0, $5);
+ $parsing = $parser + 464 | 0;
+ $6 = HEAP32[$parsing >> 2] | 0;
+ $cmp = ($6 | 0) == 2;
+ if ($cmp) {
+ $retval_0 = 35;
+ label = 19;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $7 = HEAP32[$next >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $7;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 7:
+ HEAP32[$nextPtr >> 2] = $s_addr_0;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 8:
+ $8 = HEAP32[$m_defaultHandler7 >> 2] | 0;
+ $tobool8 = ($8 | 0) == 0;
+ if ($tobool8) {
+ label = 17;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $9 = HEAP32[$m_encoding >> 2] | 0;
+ $10 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $9, $s_addr_0, $10);
+ label = 17;
+ break;
+ case 10:
+ $11 = HEAP32[$m_encoding >> 2] | 0;
+ $12 = HEAP32[$next >> 2] | 0;
+ $call14 = _reportProcessingInstruction($parser, $11, $s_addr_0, $12) | 0;
+ $tobool15 = ($call14 | 0) == 0;
+ if ($tobool15) {
+ $retval_0 = 1;
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 11:
+ $13 = HEAP32[$m_encoding >> 2] | 0;
+ $14 = HEAP32[$next >> 2] | 0;
+ $call20 = _reportComment($parser, $13, $s_addr_0, $14) | 0;
+ $tobool21 = ($call20 | 0) == 0;
+ if ($tobool21) {
+ $retval_0 = 1;
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 12:
+ $15 = HEAP32[$next >> 2] | 0;
+ HEAP32[$m_eventPtr >> 2] = $15;
+ $retval_0 = 4;
+ label = 19;
+ break;
+ case 13:
+ $finalBuffer = $parser + 468 | 0;
+ $16 = HEAP8[$finalBuffer] | 0;
+ $tobool28 = $16 << 24 >> 24 == 0;
+ if ($tobool28) {
+ label = 14;
+ break;
+ } else {
+ $retval_0 = 5;
+ label = 19;
+ break;
+ }
+ case 14:
+ HEAP32[$nextPtr >> 2] = $s_addr_0;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 15:
+ $finalBuffer33 = $parser + 468 | 0;
+ $17 = HEAP8[$finalBuffer33] | 0;
+ $tobool34 = $17 << 24 >> 24 == 0;
+ if ($tobool34) {
+ label = 16;
+ break;
+ } else {
+ $retval_0 = 6;
+ label = 19;
+ break;
+ }
+ case 16:
+ HEAP32[$nextPtr >> 2] = $s_addr_0;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 17:
+ $18 = HEAP32[$next >> 2] | 0;
+ HEAP32[$m_eventPtr >> 2] = $18;
+ $19 = HEAP32[$parsing39 >> 2] | 0;
+ if (($19 | 0) == 3) {
+ label = 18;
+ break;
+ } else if (($19 | 0) == 2) {
+ $retval_0 = 35;
+ label = 19;
+ break;
+ } else {
+ $s_addr_0 = $18;
+ label = 3;
+ break;
+ }
+ case 18:
+ $20 = HEAP32[$next >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $20;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 19:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doCdataSection($parser, $enc, $startPtr, $end, $nextPtr, $haveMore) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $startPtr = $startPtr | 0;
+ $end = $end | 0;
+ $nextPtr = $nextPtr | 0;
+ $haveMore = $haveMore | 0;
+ var $s = 0, $next = 0, $c = 0, $dataPtr = 0, $0 = 0, $m_encoding = 0, $1 = 0, $cmp = 0, $m_eventPtr = 0, $m_eventEndPtr = 0, $m_openInternalEntities = 0, $2 = 0, $internalEventPtr = 0, $internalEventEndPtr = 0, $eventEndPP_0 = 0, $eventPP_0 = 0, $3 = 0, $arrayidx = 0, $m_characterDataHandler = 0, $m_defaultHandler18 = 0, $m_handlerArg16 = 0, $parsing58 = 0, $m_characterDataHandler24 = 0, $m_defaultHandler43 = 0, $isUtf8 = 0, $m_handlerArg37 = 0, $m_dataBuf = 0, $utf8Convert = 0, $m_dataBufEnd = 0, $m_handlerArg30 = 0, $4 = 0, $5 = 0, $call = 0, $6 = 0, $m_endCdataSectionHandler = 0, $7 = 0, $tobool = 0, $m_handlerArg = 0, $8 = 0, $m_defaultHandler = 0, $9 = 0, $tobool5 = 0, $10 = 0, $11 = 0, $12 = 0, $13 = 0, $parsing = 0, $14 = 0, $cmp9 = 0, $_ = 0, $15 = 0, $tobool13 = 0, $16 = 0, $17 = 0, $18 = 0, $tobool19 = 0, $19 = 0, $20 = 0, $21 = 0, $tobool25 = 0, $22 = 0, $tobool27 = 0, $23 = 0, $24 = 0, $25 = 0, $26 = 0, $27 = 0, $28 = 0, $29 = 0, $30 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $31 = 0, $32 = 0, $cmp33 = 0, $33 = 0, $34 = 0, $35 = 0, $sub_ptr_lhs_cast38 = 0, $sub_ptr_rhs_cast39 = 0, $sub_ptr_sub40 = 0, $36 = 0, $tobool44 = 0, $37 = 0, $38 = 0, $39 = 0, $tobool50 = 0, $40 = 0, $tobool54 = 0, $41 = 0, $42 = 0, $43 = 0, $44 = 0, $45 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s = __stackBase__ | 0;
+ $next = __stackBase__ + 8 | 0;
+ $c = __stackBase__ + 16 | 0;
+ $dataPtr = __stackBase__ + 24 | 0;
+ $0 = HEAP32[$startPtr >> 2] | 0;
+ HEAP32[$s >> 2] = $0;
+ $m_encoding = $parser + 144 | 0;
+ $1 = HEAP32[$m_encoding >> 2] | 0;
+ $cmp = ($1 | 0) == ($enc | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $m_eventPtr = $parser + 272 | 0;
+ HEAP32[$m_eventPtr >> 2] = $0;
+ $m_eventEndPtr = $parser + 276 | 0;
+ $eventPP_0 = $m_eventPtr;
+ $eventEndPP_0 = $m_eventEndPtr;
+ label = 5;
+ break;
+ case 4:
+ $m_openInternalEntities = $parser + 284 | 0;
+ $2 = HEAP32[$m_openInternalEntities >> 2] | 0;
+ $internalEventPtr = $2 | 0;
+ $internalEventEndPtr = $2 + 4 | 0;
+ $eventPP_0 = $internalEventPtr;
+ $eventEndPP_0 = $internalEventEndPtr;
+ label = 5;
+ break;
+ case 5:
+ $3 = HEAP32[$s >> 2] | 0;
+ HEAP32[$eventPP_0 >> 2] = $3;
+ HEAP32[$startPtr >> 2] = 0;
+ $arrayidx = $enc + 8 | 0;
+ $m_characterDataHandler = $parser + 60 | 0;
+ $m_defaultHandler18 = $parser + 80 | 0;
+ $m_handlerArg16 = $parser + 4 | 0;
+ $parsing58 = $parser + 464 | 0;
+ $m_characterDataHandler24 = $parser + 60 | 0;
+ $m_defaultHandler43 = $parser + 80 | 0;
+ $isUtf8 = $enc + 68 | 0;
+ $m_handlerArg37 = $parser + 4 | 0;
+ $m_dataBuf = $parser + 44 | 0;
+ $utf8Convert = $enc + 56 | 0;
+ $m_dataBufEnd = $parser + 48 | 0;
+ $m_handlerArg30 = $parser + 4 | 0;
+ label = 6;
+ break;
+ case 6:
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $5 = HEAP32[$s >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$4 & 1023]($enc, $5, $end, $next) | 0;
+ $6 = HEAP32[$next >> 2] | 0;
+ HEAP32[$eventEndPP_0 >> 2] = $6;
+ if (($call | 0) == 40) {
+ label = 7;
+ break;
+ } else if (($call | 0) == 7) {
+ label = 12;
+ break;
+ } else if (($call | 0) == 6) {
+ label = 16;
+ break;
+ } else if (($call | 0) == 0) {
+ label = 23;
+ break;
+ } else if (($call | 0) == (-2 | 0)) {
+ label = 24;
+ break;
+ } else if (($call | 0) == (-1 | 0) | ($call | 0) == (-4 | 0)) {
+ label = 26;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 7:
+ $m_endCdataSectionHandler = $parser + 76 | 0;
+ $7 = HEAP32[$m_endCdataSectionHandler >> 2] | 0;
+ $tobool = ($7 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $m_handlerArg = $parser + 4 | 0;
+ $8 = HEAP32[$m_handlerArg >> 2] | 0;
+ FUNCTION_TABLE_vi[$7 & 1023]($8);
+ label = 11;
+ break;
+ case 9:
+ $m_defaultHandler = $parser + 80 | 0;
+ $9 = HEAP32[$m_defaultHandler >> 2] | 0;
+ $tobool5 = ($9 | 0) == 0;
+ if ($tobool5) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $10 = HEAP32[$s >> 2] | 0;
+ $11 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $10, $11);
+ label = 11;
+ break;
+ case 11:
+ $12 = HEAP32[$next >> 2] | 0;
+ HEAP32[$startPtr >> 2] = $12;
+ $13 = HEAP32[$next >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $13;
+ $parsing = $parser + 464 | 0;
+ $14 = HEAP32[$parsing >> 2] | 0;
+ $cmp9 = ($14 | 0) == 2;
+ $_ = $cmp9 ? 35 : 0;
+ $retval_0 = $_;
+ label = 31;
+ break;
+ case 12:
+ $15 = HEAP32[$m_characterDataHandler >> 2] | 0;
+ $tobool13 = ($15 | 0) == 0;
+ if ($tobool13) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ HEAP8[$c] = 10;
+ $16 = HEAP32[$m_characterDataHandler >> 2] | 0;
+ $17 = HEAP32[$m_handlerArg16 >> 2] | 0;
+ FUNCTION_TABLE_viii[$16 & 1023]($17, $c, 1);
+ label = 29;
+ break;
+ case 14:
+ $18 = HEAP32[$m_defaultHandler18 >> 2] | 0;
+ $tobool19 = ($18 | 0) == 0;
+ if ($tobool19) {
+ label = 29;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $19 = HEAP32[$s >> 2] | 0;
+ $20 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $19, $20);
+ label = 29;
+ break;
+ case 16:
+ $21 = HEAP32[$m_characterDataHandler24 >> 2] | 0;
+ $tobool25 = ($21 | 0) == 0;
+ if ($tobool25) {
+ label = 21;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $22 = HEAP8[$isUtf8] | 0;
+ $tobool27 = $22 << 24 >> 24 == 0;
+ if ($tobool27) {
+ label = 18;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 18:
+ $23 = HEAP32[$m_dataBuf >> 2] | 0;
+ HEAP32[$dataPtr >> 2] = $23;
+ $24 = HEAP32[$utf8Convert >> 2] | 0;
+ $25 = HEAP32[$next >> 2] | 0;
+ $26 = HEAP32[$m_dataBufEnd >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$24 & 1023]($enc, $s, $25, $dataPtr, $26);
+ $27 = HEAP32[$next >> 2] | 0;
+ HEAP32[$eventEndPP_0 >> 2] = $27;
+ $28 = HEAP32[$m_handlerArg30 >> 2] | 0;
+ $29 = HEAP32[$m_dataBuf >> 2] | 0;
+ $30 = HEAP32[$dataPtr >> 2] | 0;
+ $sub_ptr_lhs_cast = $30;
+ $sub_ptr_rhs_cast = $29;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ FUNCTION_TABLE_viii[$21 & 1023]($28, $29, $sub_ptr_sub);
+ $31 = HEAP32[$s >> 2] | 0;
+ $32 = HEAP32[$next >> 2] | 0;
+ $cmp33 = ($31 | 0) == ($32 | 0);
+ if ($cmp33) {
+ label = 29;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ HEAP32[$eventPP_0 >> 2] = $31;
+ label = 18;
+ break;
+ case 20:
+ $33 = HEAP32[$m_handlerArg37 >> 2] | 0;
+ $34 = HEAP32[$s >> 2] | 0;
+ $35 = HEAP32[$next >> 2] | 0;
+ $sub_ptr_lhs_cast38 = $35;
+ $sub_ptr_rhs_cast39 = $34;
+ $sub_ptr_sub40 = $sub_ptr_lhs_cast38 - $sub_ptr_rhs_cast39 | 0;
+ FUNCTION_TABLE_viii[$21 & 1023]($33, $34, $sub_ptr_sub40);
+ label = 29;
+ break;
+ case 21:
+ $36 = HEAP32[$m_defaultHandler43 >> 2] | 0;
+ $tobool44 = ($36 | 0) == 0;
+ if ($tobool44) {
+ label = 29;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $37 = HEAP32[$s >> 2] | 0;
+ $38 = HEAP32[$next >> 2] | 0;
+ _reportDefault($parser, $enc, $37, $38);
+ label = 29;
+ break;
+ case 23:
+ $39 = HEAP32[$next >> 2] | 0;
+ HEAP32[$eventPP_0 >> 2] = $39;
+ $retval_0 = 4;
+ label = 31;
+ break;
+ case 24:
+ $tobool50 = $haveMore << 24 >> 24 == 0;
+ if ($tobool50) {
+ $retval_0 = 6;
+ label = 31;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $40 = HEAP32[$s >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $40;
+ $retval_0 = 0;
+ label = 31;
+ break;
+ case 26:
+ $tobool54 = $haveMore << 24 >> 24 == 0;
+ if ($tobool54) {
+ $retval_0 = 20;
+ label = 31;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $41 = HEAP32[$s >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $41;
+ $retval_0 = 0;
+ label = 31;
+ break;
+ case 28:
+ $42 = HEAP32[$next >> 2] | 0;
+ HEAP32[$eventPP_0 >> 2] = $42;
+ $retval_0 = 23;
+ label = 31;
+ break;
+ case 29:
+ $43 = HEAP32[$next >> 2] | 0;
+ HEAP32[$s >> 2] = $43;
+ HEAP32[$eventPP_0 >> 2] = $43;
+ $44 = HEAP32[$parsing58 >> 2] | 0;
+ if (($44 | 0) == 3) {
+ label = 30;
+ break;
+ } else if (($44 | 0) == 2) {
+ $retval_0 = 35;
+ label = 31;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 30:
+ $45 = HEAP32[$next >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $45;
+ $retval_0 = 0;
+ label = 31;
+ break;
+ case 31:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _cdataSectionProcessor($parser, $start, $end, $endPtr) {
+ $parser = $parser | 0;
+ $start = $start | 0;
+ $end = $end | 0;
+ $endPtr = $endPtr | 0;
+ var $start_addr = 0, $m_encoding = 0, $0 = 0, $finalBuffer = 0, $1 = 0, $lnot = 0, $conv = 0, $call = 0, $cmp = 0, $2 = 0, $tobool2 = 0, $or_cond = 0, $m_parentParser = 0, $3 = 0, $tobool4 = 0, $m_processor = 0, $4 = 0, $call6 = 0, $5 = 0, $call8 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $start_addr = __stackBase__ | 0;
+ HEAP32[$start_addr >> 2] = $start;
+ $m_encoding = $parser + 144 | 0;
+ $0 = HEAP32[$m_encoding >> 2] | 0;
+ $finalBuffer = $parser + 468 | 0;
+ $1 = HEAP8[$finalBuffer] | 0;
+ $lnot = $1 << 24 >> 24 == 0;
+ $conv = $lnot & 1;
+ $call = _doCdataSection($parser, $0, $start_addr, $end, $endPtr, $conv) | 0;
+ $cmp = ($call | 0) != 0;
+ $2 = HEAP32[$start_addr >> 2] | 0;
+ $tobool2 = ($2 | 0) == 0;
+ $or_cond = $cmp | $tobool2;
+ if ($or_cond) {
+ $retval_0 = $call;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $m_parentParser = $parser + 460 | 0;
+ $3 = HEAP32[$m_parentParser >> 2] | 0;
+ $tobool4 = ($3 | 0) == 0;
+ $m_processor = $parser + 264 | 0;
+ if ($tobool4) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAP32[$m_processor >> 2] = 48;
+ $4 = HEAP32[$start_addr >> 2] | 0;
+ $call6 = _externalEntityContentProcessor($parser, $4, $end, $endPtr) | 0;
+ $retval_0 = $call6;
+ label = 6;
+ break;
+ case 5:
+ HEAP32[$m_processor >> 2] = 122;
+ $5 = HEAP32[$start_addr >> 2] | 0;
+ $call8 = _contentProcessor($parser, $5, $end, $endPtr) | 0;
+ $retval_0 = $call8;
+ label = 6;
+ break;
+ case 6:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _reportProcessingInstruction($parser, $enc, $start, $end) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $start = $start | 0;
+ $end = $end | 0;
+ var $m_processingInstructionHandler = 0, $0 = 0, $tobool = 0, $m_defaultHandler = 0, $1 = 0, $tobool1 = 0, $minBytesPerChar = 0, $2 = 0, $mul = 0, $add_ptr = 0, $nameLength = 0, $3 = 0, $call = 0, $add_ptr_sum = 0, $add_ptr4 = 0, $m_tempPool = 0, $call5 = 0, $tobool6 = 0, $ptr = 0, $4 = 0, $start11 = 0, $skipS = 0, $5 = 0, $call13 = 0, $6 = 0, $mul15 = 0, $idx_neg = 0, $add_ptr16 = 0, $call17 = 0, $tobool18 = 0, $7 = 0, $m_handlerArg = 0, $8 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_processingInstructionHandler = $parser + 64 | 0;
+ $0 = HEAP32[$m_processingInstructionHandler >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $m_defaultHandler = $parser + 80 | 0;
+ $1 = HEAP32[$m_defaultHandler >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ $retval_0 = 1;
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _reportDefault($parser, $enc, $start, $end);
+ $retval_0 = 1;
+ label = 8;
+ break;
+ case 5:
+ $minBytesPerChar = $enc + 64 | 0;
+ $2 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul = $2 << 1;
+ $add_ptr = $start + $mul | 0;
+ $nameLength = $enc + 28 | 0;
+ $3 = HEAP32[$nameLength >> 2] | 0;
+ $call = FUNCTION_TABLE_iii[$3 & 1023]($enc, $add_ptr) | 0;
+ $add_ptr_sum = $call + $mul | 0;
+ $add_ptr4 = $start + $add_ptr_sum | 0;
+ $m_tempPool = $parser + 400 | 0;
+ $call5 = _poolStoreString($m_tempPool, $enc, $add_ptr, $add_ptr4) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $ptr = $parser + 412 | 0;
+ $4 = HEAP32[$ptr >> 2] | 0;
+ $start11 = $parser + 416 | 0;
+ HEAP32[$start11 >> 2] = $4;
+ $skipS = $enc + 32 | 0;
+ $5 = HEAP32[$skipS >> 2] | 0;
+ $call13 = FUNCTION_TABLE_iii[$5 & 1023]($enc, $add_ptr4) | 0;
+ $6 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul15 = $6 << 1;
+ $idx_neg = -$mul15 | 0;
+ $add_ptr16 = $end + $idx_neg | 0;
+ $call17 = _poolStoreString($m_tempPool, $enc, $call13, $add_ptr16) | 0;
+ $tobool18 = ($call17 | 0) == 0;
+ if ($tobool18) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _normalizeLines($call17);
+ $7 = HEAP32[$m_processingInstructionHandler >> 2] | 0;
+ $m_handlerArg = $parser + 4 | 0;
+ $8 = HEAP32[$m_handlerArg >> 2] | 0;
+ FUNCTION_TABLE_viii[$7 & 1023]($8, $call5, $call17);
+ _poolClear($m_tempPool);
+ $retval_0 = 1;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _reportComment($parser, $enc, $start, $end) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $start = $start | 0;
+ $end = $end | 0;
+ var $m_commentHandler = 0, $0 = 0, $tobool = 0, $m_defaultHandler = 0, $1 = 0, $tobool1 = 0, $m_tempPool = 0, $minBytesPerChar = 0, $2 = 0, $mul = 0, $add_ptr = 0, $3 = 0, $add_ptr6 = 0, $call = 0, $tobool7 = 0, $4 = 0, $m_handlerArg = 0, $5 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_commentHandler = $parser + 68 | 0;
+ $0 = HEAP32[$m_commentHandler >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $m_defaultHandler = $parser + 80 | 0;
+ $1 = HEAP32[$m_defaultHandler >> 2] | 0;
+ $tobool1 = ($1 | 0) == 0;
+ if ($tobool1) {
+ $retval_0 = 1;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _reportDefault($parser, $enc, $start, $end);
+ $retval_0 = 1;
+ label = 7;
+ break;
+ case 5:
+ $m_tempPool = $parser + 400 | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $2 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul = $2 << 2;
+ $add_ptr = $start + $mul | 0;
+ $3 = $2 * -3 & -1;
+ $add_ptr6 = $end + $3 | 0;
+ $call = _poolStoreString($m_tempPool, $enc, $add_ptr, $add_ptr6) | 0;
+ $tobool7 = ($call | 0) == 0;
+ if ($tobool7) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ _normalizeLines($call);
+ $4 = HEAP32[$m_commentHandler >> 2] | 0;
+ $m_handlerArg = $parser + 4 | 0;
+ $5 = HEAP32[$m_handlerArg >> 2] | 0;
+ FUNCTION_TABLE_vii[$4 & 1023]($5, $call);
+ _poolClear($m_tempPool);
+ $retval_0 = 1;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _contentProcessor($parser, $start, $end, $endPtr) {
+ $parser = $parser | 0;
+ $start = $start | 0;
+ $end = $end | 0;
+ $endPtr = $endPtr | 0;
+ var $m_encoding = 0, $0 = 0, $finalBuffer = 0, $1 = 0, $lnot = 0, $conv = 0, $call = 0, $cmp = 0, $call2 = 0, $tobool3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_encoding = $parser + 144 | 0;
+ $0 = HEAP32[$m_encoding >> 2] | 0;
+ $finalBuffer = $parser + 468 | 0;
+ $1 = HEAP8[$finalBuffer] | 0;
+ $lnot = $1 << 24 >> 24 == 0;
+ $conv = $lnot & 1;
+ $call = _doContent($parser, 0, $0, $start, $end, $endPtr, $conv) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call2 = _storeRawNames($parser) | 0;
+ $tobool3 = $call2 << 24 >> 24 == 0;
+ if ($tobool3) {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $retval_0 = $call;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _setElementTypePrefix($parser, $elementType) {
+ $parser = $parser | 0;
+ $elementType = $elementType | 0;
+ var $m_dtd = 0, $0 = 0, $name1 = 0, $1 = 0, $pool = 0, $ptr = 0, $end = 0, $prefixes = 0, $start = 0, $prefix54 = 0, $name_0 = 0, $2 = 0, $3 = 0, $cmp525 = 0, $4 = 0, $5 = 0, $cmp926 = 0, $cmp928 = 0, $s_027 = 0, $call = 0, $tobool12 = 0, $6 = 0, $7 = 0, $incdec_ptr = 0, $incdec_ptr16 = 0, $cmp5 = 0, $8 = 0, $9 = 0, $cmp9 = 0, $cmp9_lcssa = 0, $call25 = 0, $tobool26 = 0, $10 = 0, $incdec_ptr31 = 0, $11 = 0, $call35 = 0, $12 = 0, $tobool36 = 0, $name39 = 0, $13 = 0, $14 = 0, $cmp42 = 0, $15 = 0, $incdec_ptr57 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $name1 = $elementType | 0;
+ $1 = HEAP32[$name1 >> 2] | 0;
+ $pool = $0 + 80 | 0;
+ $ptr = $0 + 92 | 0;
+ $end = $0 + 88 | 0;
+ $prefixes = $0 + 60 | 0;
+ $start = $0 + 96 | 0;
+ $prefix54 = $elementType + 4 | 0;
+ $name_0 = $1;
+ label = 3;
+ break;
+ case 3:
+ $2 = HEAP8[$name_0] | 0;
+ if (($2 << 24 >> 24 | 0) == 58) {
+ label = 4;
+ break;
+ } else if (($2 << 24 >> 24 | 0) == 0) {
+ $retval_0 = 1;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 4:
+ $3 = HEAP32[$name1 >> 2] | 0;
+ $cmp525 = ($3 | 0) == ($name_0 | 0);
+ $4 = HEAP32[$ptr >> 2] | 0;
+ $5 = HEAP32[$end >> 2] | 0;
+ $cmp926 = ($4 | 0) == ($5 | 0);
+ if ($cmp525) {
+ $cmp9_lcssa = $cmp926;
+ label = 8;
+ break;
+ } else {
+ $s_027 = $3;
+ $cmp928 = $cmp926;
+ label = 5;
+ break;
+ }
+ case 5:
+ if ($cmp928) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call = _poolGrow($pool) | 0;
+ $tobool12 = $call << 24 >> 24 == 0;
+ if ($tobool12) {
+ $retval_0 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $6 = HEAP8[$s_027] | 0;
+ $7 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $7 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$7] = $6;
+ $incdec_ptr16 = $s_027 + 1 | 0;
+ $cmp5 = ($incdec_ptr16 | 0) == ($name_0 | 0);
+ $8 = HEAP32[$ptr >> 2] | 0;
+ $9 = HEAP32[$end >> 2] | 0;
+ $cmp9 = ($8 | 0) == ($9 | 0);
+ if ($cmp5) {
+ $cmp9_lcssa = $cmp9;
+ label = 8;
+ break;
+ } else {
+ $s_027 = $incdec_ptr16;
+ $cmp928 = $cmp9;
+ label = 5;
+ break;
+ }
+ case 8:
+ if ($cmp9_lcssa) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $call25 = _poolGrow($pool) | 0;
+ $tobool26 = $call25 << 24 >> 24 == 0;
+ if ($tobool26) {
+ $retval_0 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $10 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr31 = $10 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr31;
+ HEAP8[$10] = 0;
+ $11 = HEAP32[$start >> 2] | 0;
+ $call35 = _lookup($parser, $prefixes, $11, 8) | 0;
+ $12 = $call35;
+ $tobool36 = ($call35 | 0) == 0;
+ if ($tobool36) {
+ $retval_0 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $name39 = $call35 | 0;
+ $13 = HEAP32[$name39 >> 2] | 0;
+ $14 = HEAP32[$start >> 2] | 0;
+ $cmp42 = ($13 | 0) == ($14 | 0);
+ if ($cmp42) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $15 = HEAP32[$ptr >> 2] | 0;
+ HEAP32[$start >> 2] = $15;
+ label = 14;
+ break;
+ case 13:
+ HEAP32[$ptr >> 2] = $14;
+ label = 14;
+ break;
+ case 14:
+ HEAP32[$prefix54 >> 2] = $12;
+ label = 15;
+ break;
+ case 15:
+ $incdec_ptr57 = $name_0 + 1 | 0;
+ $name_0 = $incdec_ptr57;
+ label = 3;
+ break;
+ case 16:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _getAttributeId($parser, $enc, $start, $end) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $start = $start | 0;
+ $end = $end | 0;
+ var $m_dtd = 0, $0 = 0, $pool = 0, $ptr = 0, $1 = 0, $end2 = 0, $2 = 0, $cmp = 0, $call = 0, $tobool = 0, $3 = 0, $incdec_ptr = 0, $call7 = 0, $tobool8 = 0, $incdec_ptr11 = 0, $attributeIds = 0, $call12 = 0, $4 = 0, $tobool13 = 0, $name16 = 0, $5 = 0, $cmp17 = 0, $start20 = 0, $6 = 0, $7 = 0, $start26 = 0, $m_ns = 0, $8 = 0, $tobool27 = 0, $9 = 0, $cmp30 = 0, $arrayidx33 = 0, $10 = 0, $cmp35 = 0, $arrayidx38 = 0, $11 = 0, $cmp40 = 0, $arrayidx43 = 0, $12 = 0, $cmp45 = 0, $arrayidx48 = 0, $13 = 0, $cmp50 = 0, $arrayidx53 = 0, $14 = 0, $defaultPrefix = 0, $15 = 0, $defaultPrefix_c = 0, $prefixes = 0, $add_ptr = 0, $call68 = 0, $16 = 0, $_c55 = 0, $xmlns = 0, $i_0 = 0, $incdec_ptr11_sum = 0, $arrayidx72 = 0, $17 = 0, $cmp8057 = 0, $18 = 0, $19 = 0, $cmp8758 = 0, $cmp8760 = 0, $j_059 = 0, $call91 = 0, $tobool92 = 0, $incdec_ptr11_sum54 = 0, $arrayidx95 = 0, $20 = 0, $21 = 0, $incdec_ptr98 = 0, $inc = 0, $cmp80 = 0, $22 = 0, $23 = 0, $cmp87 = 0, $cmp87_lcssa = 0, $call109 = 0, $tobool110 = 0, $24 = 0, $incdec_ptr115 = 0, $prefixes118 = 0, $25 = 0, $call121 = 0, $26 = 0, $_c = 0, $name124 = 0, $27 = 0, $28 = 0, $cmp127 = 0, $29 = 0, $inc142 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $pool = $0 + 80 | 0;
+ $ptr = $0 + 92 | 0;
+ $1 = HEAP32[$ptr >> 2] | 0;
+ $end2 = $0 + 88 | 0;
+ $2 = HEAP32[$end2 >> 2] | 0;
+ $cmp = ($1 | 0) == ($2 | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _poolGrow($pool) | 0;
+ $tobool = $call << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 29;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $3 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $3 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$3] = 0;
+ $call7 = _poolStoreString($pool, $enc, $start, $end) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ $retval_0 = 0;
+ label = 29;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $incdec_ptr11 = $call7 + 1 | 0;
+ $attributeIds = $0 + 40 | 0;
+ $call12 = _lookup($parser, $attributeIds, $incdec_ptr11, 12) | 0;
+ $4 = $call12;
+ $tobool13 = ($call12 | 0) == 0;
+ if ($tobool13) {
+ $retval_0 = 0;
+ label = 29;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $name16 = $call12 | 0;
+ $5 = HEAP32[$name16 >> 2] | 0;
+ $cmp17 = ($5 | 0) == ($incdec_ptr11 | 0);
+ if ($cmp17) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $start20 = $0 + 96 | 0;
+ $6 = HEAP32[$start20 >> 2] | 0;
+ HEAP32[$ptr >> 2] = $6;
+ $retval_0 = $4;
+ label = 29;
+ break;
+ case 8:
+ $7 = HEAP32[$ptr >> 2] | 0;
+ $start26 = $0 + 96 | 0;
+ HEAP32[$start26 >> 2] = $7;
+ $m_ns = $parser + 232 | 0;
+ $8 = HEAP8[$m_ns] | 0;
+ $tobool27 = $8 << 24 >> 24 == 0;
+ if ($tobool27) {
+ $retval_0 = $4;
+ label = 29;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $9 = HEAP8[$incdec_ptr11] | 0;
+ $cmp30 = $9 << 24 >> 24 == 120;
+ if ($cmp30) {
+ label = 10;
+ break;
+ } else {
+ $i_0 = 0;
+ label = 18;
+ break;
+ }
+ case 10:
+ $arrayidx33 = $call7 + 2 | 0;
+ $10 = HEAP8[$arrayidx33] | 0;
+ $cmp35 = $10 << 24 >> 24 == 109;
+ if ($cmp35) {
+ label = 11;
+ break;
+ } else {
+ $i_0 = 0;
+ label = 18;
+ break;
+ }
+ case 11:
+ $arrayidx38 = $call7 + 3 | 0;
+ $11 = HEAP8[$arrayidx38] | 0;
+ $cmp40 = $11 << 24 >> 24 == 108;
+ if ($cmp40) {
+ label = 12;
+ break;
+ } else {
+ $i_0 = 0;
+ label = 18;
+ break;
+ }
+ case 12:
+ $arrayidx43 = $call7 + 4 | 0;
+ $12 = HEAP8[$arrayidx43] | 0;
+ $cmp45 = $12 << 24 >> 24 == 110;
+ if ($cmp45) {
+ label = 13;
+ break;
+ } else {
+ $i_0 = 0;
+ label = 18;
+ break;
+ }
+ case 13:
+ $arrayidx48 = $call7 + 5 | 0;
+ $13 = HEAP8[$arrayidx48] | 0;
+ $cmp50 = $13 << 24 >> 24 == 115;
+ if ($cmp50) {
+ label = 14;
+ break;
+ } else {
+ $i_0 = 0;
+ label = 18;
+ break;
+ }
+ case 14:
+ $arrayidx53 = $call7 + 6 | 0;
+ $14 = HEAP8[$arrayidx53] | 0;
+ if (($14 << 24 >> 24 | 0) == 0) {
+ label = 15;
+ break;
+ } else if (($14 << 24 >> 24 | 0) == 58) {
+ label = 16;
+ break;
+ } else {
+ $i_0 = 0;
+ label = 18;
+ break;
+ }
+ case 15:
+ $defaultPrefix = $0 + 132 | 0;
+ $15 = $call12 + 4 | 0;
+ $defaultPrefix_c = $defaultPrefix;
+ HEAP32[$15 >> 2] = $defaultPrefix_c;
+ label = 17;
+ break;
+ case 16:
+ $prefixes = $0 + 60 | 0;
+ $add_ptr = $call7 + 7 | 0;
+ $call68 = _lookup($parser, $prefixes, $add_ptr, 8) | 0;
+ $16 = $call12 + 4 | 0;
+ $_c55 = $call68;
+ HEAP32[$16 >> 2] = $_c55;
+ label = 17;
+ break;
+ case 17:
+ $xmlns = $4 + 9 | 0;
+ HEAP8[$xmlns] = 1;
+ $retval_0 = $4;
+ label = 29;
+ break;
+ case 18:
+ $incdec_ptr11_sum = $i_0 + 1 | 0;
+ $arrayidx72 = $call7 + $incdec_ptr11_sum | 0;
+ $17 = HEAP8[$arrayidx72] | 0;
+ if (($17 << 24 >> 24 | 0) == 58) {
+ label = 19;
+ break;
+ } else if (($17 << 24 >> 24 | 0) == 0) {
+ $retval_0 = $4;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 19:
+ $cmp8057 = ($i_0 | 0) > 0;
+ $18 = HEAP32[$ptr >> 2] | 0;
+ $19 = HEAP32[$end2 >> 2] | 0;
+ $cmp8758 = ($18 | 0) == ($19 | 0);
+ if ($cmp8057) {
+ $j_059 = 0;
+ $cmp8760 = $cmp8758;
+ label = 20;
+ break;
+ } else {
+ $cmp87_lcssa = $cmp8758;
+ label = 23;
+ break;
+ }
+ case 20:
+ if ($cmp8760) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $call91 = _poolGrow($pool) | 0;
+ $tobool92 = $call91 << 24 >> 24 == 0;
+ if ($tobool92) {
+ $retval_0 = 0;
+ label = 29;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $incdec_ptr11_sum54 = $j_059 + 1 | 0;
+ $arrayidx95 = $call7 + $incdec_ptr11_sum54 | 0;
+ $20 = HEAP8[$arrayidx95] | 0;
+ $21 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr98 = $21 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr98;
+ HEAP8[$21] = $20;
+ $inc = $j_059 + 1 | 0;
+ $cmp80 = ($inc | 0) < ($i_0 | 0);
+ $22 = HEAP32[$ptr >> 2] | 0;
+ $23 = HEAP32[$end2 >> 2] | 0;
+ $cmp87 = ($22 | 0) == ($23 | 0);
+ if ($cmp80) {
+ $j_059 = $inc;
+ $cmp8760 = $cmp87;
+ label = 20;
+ break;
+ } else {
+ $cmp87_lcssa = $cmp87;
+ label = 23;
+ break;
+ }
+ case 23:
+ if ($cmp87_lcssa) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $call109 = _poolGrow($pool) | 0;
+ $tobool110 = $call109 << 24 >> 24 == 0;
+ if ($tobool110) {
+ $retval_0 = 0;
+ label = 29;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $24 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr115 = $24 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr115;
+ HEAP8[$24] = 0;
+ $prefixes118 = $0 + 60 | 0;
+ $25 = HEAP32[$start26 >> 2] | 0;
+ $call121 = _lookup($parser, $prefixes118, $25, 8) | 0;
+ $26 = $call12 + 4 | 0;
+ $_c = $call121;
+ HEAP32[$26 >> 2] = $_c;
+ $name124 = $call121 | 0;
+ $27 = HEAP32[$name124 >> 2] | 0;
+ $28 = HEAP32[$start26 >> 2] | 0;
+ $cmp127 = ($27 | 0) == ($28 | 0);
+ if ($cmp127) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $29 = HEAP32[$ptr >> 2] | 0;
+ HEAP32[$start26 >> 2] = $29;
+ $retval_0 = $4;
+ label = 29;
+ break;
+ case 27:
+ HEAP32[$ptr >> 2] = $28;
+ $retval_0 = $4;
+ label = 29;
+ break;
+ case 28:
+ $inc142 = $i_0 + 1 | 0;
+ $i_0 = $inc142;
+ label = 18;
+ break;
+ case 29:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _storeAttributeValue($parser, $enc, $isCdata, $ptr, $end, $pool) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $isCdata = $isCdata | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $pool = $pool | 0;
+ var $call = 0, $tobool = 0, $tobool1 = 0, $ptr2 = 0, $0 = 0, $start = 0, $1 = 0, $tobool3 = 0, $arrayidx = 0, $2 = 0, $cmp = 0, $ptr10 = 0, $3 = 0, $end11 = 0, $4 = 0, $cmp12 = 0, $call15 = 0, $tobool16 = 0, $5 = 0, $incdec_ptr18 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _appendAttributeValue($parser, $enc, $isCdata, $ptr, $end, $pool) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = $call;
+ label = 10;
+ break;
+ }
+ case 3:
+ $tobool1 = $isCdata << 24 >> 24 == 0;
+ if ($tobool1) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $ptr2 = $pool + 12 | 0;
+ $0 = HEAP32[$ptr2 >> 2] | 0;
+ $start = $pool + 16 | 0;
+ $1 = HEAP32[$start >> 2] | 0;
+ $tobool3 = ($0 | 0) == ($1 | 0);
+ if ($tobool3) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $arrayidx = $0 - 1 | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $cmp = $2 << 24 >> 24 == 32;
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ HEAP32[$ptr2 >> 2] = $arrayidx;
+ label = 7;
+ break;
+ case 7:
+ $ptr10 = $pool + 12 | 0;
+ $3 = HEAP32[$ptr10 >> 2] | 0;
+ $end11 = $pool + 8 | 0;
+ $4 = HEAP32[$end11 >> 2] | 0;
+ $cmp12 = ($3 | 0) == ($4 | 0);
+ if ($cmp12) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $call15 = _poolGrow($pool) | 0;
+ $tobool16 = $call15 << 24 >> 24 == 0;
+ if ($tobool16) {
+ $retval_0 = 1;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $5 = HEAP32[$ptr10 >> 2] | 0;
+ $incdec_ptr18 = $5 + 1 | 0;
+ HEAP32[$ptr10 >> 2] = $incdec_ptr18;
+ HEAP8[$5] = 0;
+ $retval_0 = 0;
+ label = 10;
+ break;
+ case 10:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _appendAttributeValue($parser, $enc, $isCdata, $ptr, $end, $pool) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $isCdata = $isCdata | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $pool = $pool | 0;
+ var $next = 0, $buf = 0, $m_dtd = 0, $0 = 0, $arrayidx = 0, $charRefNumber = 0, $tobool = 0, $ptr20 = 0, $start = 0, $arraydecay = 0, $ptr41 = 0, $end42 = 0, $minBytesPerChar = 0, $tobool59 = 0, $ptr61 = 0, $start62 = 0, $ptr76 = 0, $end77 = 0, $predefinedEntityName = 0, $minBytesPerChar90 = 0, $m_temp2Pool = 0, $generalEntities = 0, $start123 = 0, $ptr125 = 0, $pool126 = 0, $cmp127 = 0, $standalone = 0, $hasParamEntityRefs = 0, $m_openInternalEntities = 0, $m_internalEncoding = 0, $hasParamEntityRefs139 = 0, $standalone141 = 0, $ptr98 = 0, $end99 = 0, $ptr_addr_0 = 0, $1 = 0, $call = 0, $m_encoding = 0, $2 = 0, $cmp = 0, $3 = 0, $m_eventPtr = 0, $m_encoding3 = 0, $4 = 0, $cmp4 = 0, $m_eventPtr6 = 0, $5 = 0, $call9 = 0, $cmp10 = 0, $m_encoding12 = 0, $6 = 0, $cmp13 = 0, $m_eventPtr15 = 0, $cmp18 = 0, $or_cond = 0, $7 = 0, $8 = 0, $cmp21 = 0, $arrayidx23 = 0, $9 = 0, $cmp24 = 0, $call28 = 0, $tobool29 = 0, $cmp39103 = 0, $m_encoding31 = 0, $10 = 0, $cmp32 = 0, $m_eventPtr35 = 0, $i_0104 = 0, $11 = 0, $12 = 0, $cmp43 = 0, $call46 = 0, $tobool47 = 0, $arrayidx48 = 0, $13 = 0, $14 = 0, $incdec_ptr = 0, $inc = 0, $cmp39 = 0, $15 = 0, $call53 = 0, $tobool54 = 0, $16 = 0, $add_ptr = 0, $17 = 0, $18 = 0, $cmp66 = 0, $arrayidx70 = 0, $19 = 0, $cmp72 = 0, $20 = 0, $21 = 0, $cmp78 = 0, $call81 = 0, $tobool82 = 0, $22 = 0, $incdec_ptr86 = 0, $23 = 0, $24 = 0, $add_ptr91 = 0, $25 = 0, $idx_neg = 0, $add_ptr93 = 0, $call94 = 0, $conv95 = 0, $tobool96 = 0, $26 = 0, $27 = 0, $cmp100 = 0, $call103 = 0, $tobool104 = 0, $28 = 0, $incdec_ptr108 = 0, $29 = 0, $add_ptr113 = 0, $30 = 0, $idx_neg115 = 0, $add_ptr116 = 0, $call117 = 0, $tobool118 = 0, $call121 = 0, $31 = 0, $32 = 0, $33 = 0, $tobool131 = 0, $34 = 0, $tobool133 = 0, $35 = 0, $tobool135 = 0, $tobool133_sink = 0, $36 = 0, $conv138 = 0, $37 = 0, $tobool140 = 0, $tobool148101 = 0, $38 = 0, $tobool143 = 0, $phitmp = 0, $checkEntityDecl_0 = 0, $tobool146 = 0, $tobool148 = 0, $is_internal = 0, $39 = 0, $tobool151 = 0, $open = 0, $40 = 0, $41 = 0, $tobool160 = 0, $m_encoding162 = 0, $42 = 0, $cmp163 = 0, $m_eventPtr166 = 0, $43 = 0, $44 = 0, $tobool169 = 0, $m_encoding171 = 0, $45 = 0, $cmp172 = 0, $m_eventPtr175 = 0, $46 = 0, $47 = 0, $tobool178 = 0, $m_encoding180 = 0, $48 = 0, $cmp181 = 0, $m_eventPtr184 = 0, $textLen = 0, $49 = 0, $50 = 0, $add_ptr188 = 0, $51 = 0, $52 = 0, $call191 = 0, $tobool193 = 0, $m_encoding197 = 0, $53 = 0, $cmp198 = 0, $m_eventPtr201 = 0, $54 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $next = __stackBase__ | 0;
+ $buf = __stackBase__ + 8 | 0;
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $arrayidx = $enc + 12 | 0;
+ $charRefNumber = $enc + 40 | 0;
+ $tobool = $isCdata << 24 >> 24 == 0;
+ $ptr20 = $pool + 12 | 0;
+ $start = $pool + 16 | 0;
+ $arraydecay = $buf | 0;
+ $ptr41 = $pool + 12 | 0;
+ $end42 = $pool + 8 | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $tobool59 = $isCdata << 24 >> 24 == 0;
+ $ptr61 = $pool + 12 | 0;
+ $start62 = $pool + 16 | 0;
+ $ptr76 = $pool + 12 | 0;
+ $end77 = $pool + 8 | 0;
+ $predefinedEntityName = $enc + 44 | 0;
+ $minBytesPerChar90 = $enc + 64 | 0;
+ $m_temp2Pool = $parser + 424 | 0;
+ $generalEntities = $0 | 0;
+ $start123 = $parser + 440 | 0;
+ $ptr125 = $parser + 436 | 0;
+ $pool126 = $0 + 80 | 0;
+ $cmp127 = ($pool126 | 0) == ($pool | 0);
+ $standalone = $0 + 130 | 0;
+ $hasParamEntityRefs = $0 + 129 | 0;
+ $m_openInternalEntities = $parser + 284 | 0;
+ $m_internalEncoding = $parser + 224 | 0;
+ $hasParamEntityRefs139 = $0 + 129 | 0;
+ $standalone141 = $0 + 130 | 0;
+ $ptr98 = $pool + 12 | 0;
+ $end99 = $pool + 8 | 0;
+ $ptr_addr_0 = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$1 & 1023]($enc, $ptr_addr_0, $end, $next) | 0;
+ if (($call | 0) == 0) {
+ label = 4;
+ break;
+ } else if (($call | 0) == (-1 | 0)) {
+ label = 6;
+ break;
+ } else if (($call | 0) == 10) {
+ label = 8;
+ break;
+ } else if (($call | 0) == 6) {
+ label = 21;
+ break;
+ } else if (($call | 0) == (-3 | 0)) {
+ label = 22;
+ break;
+ } else if (($call | 0) == 39 | ($call | 0) == 7) {
+ label = 23;
+ break;
+ } else if (($call | 0) == 9) {
+ label = 29;
+ break;
+ } else if (($call | 0) == (-4 | 0)) {
+ $retval_0 = 0;
+ label = 59;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 4:
+ $m_encoding = $parser + 144 | 0;
+ $2 = HEAP32[$m_encoding >> 2] | 0;
+ $cmp = ($2 | 0) == ($enc | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 4;
+ label = 59;
+ break;
+ }
+ case 5:
+ $3 = HEAP32[$next >> 2] | 0;
+ $m_eventPtr = $parser + 272 | 0;
+ HEAP32[$m_eventPtr >> 2] = $3;
+ $retval_0 = 4;
+ label = 59;
+ break;
+ case 6:
+ $m_encoding3 = $parser + 144 | 0;
+ $4 = HEAP32[$m_encoding3 >> 2] | 0;
+ $cmp4 = ($4 | 0) == ($enc | 0);
+ if ($cmp4) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 4;
+ label = 59;
+ break;
+ }
+ case 7:
+ $m_eventPtr6 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr6 >> 2] = $ptr_addr_0;
+ $retval_0 = 4;
+ label = 59;
+ break;
+ case 8:
+ $5 = HEAP32[$charRefNumber >> 2] | 0;
+ $call9 = FUNCTION_TABLE_iii[$5 & 1023]($enc, $ptr_addr_0) | 0;
+ $cmp10 = ($call9 | 0) < 0;
+ if ($cmp10) {
+ label = 9;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 9:
+ $m_encoding12 = $parser + 144 | 0;
+ $6 = HEAP32[$m_encoding12 >> 2] | 0;
+ $cmp13 = ($6 | 0) == ($enc | 0);
+ if ($cmp13) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 14;
+ label = 59;
+ break;
+ }
+ case 10:
+ $m_eventPtr15 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr15 >> 2] = $ptr_addr_0;
+ $retval_0 = 14;
+ label = 59;
+ break;
+ case 11:
+ $cmp18 = ($call9 | 0) == 32;
+ $or_cond = $tobool & $cmp18;
+ if ($or_cond) {
+ label = 12;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ $7 = HEAP32[$ptr20 >> 2] | 0;
+ $8 = HEAP32[$start >> 2] | 0;
+ $cmp21 = ($7 | 0) == ($8 | 0);
+ if ($cmp21) {
+ label = 58;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $arrayidx23 = $7 - 1 | 0;
+ $9 = HEAP8[$arrayidx23] | 0;
+ $cmp24 = $9 << 24 >> 24 == 32;
+ if ($cmp24) {
+ label = 58;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $call28 = _XmlUtf8Encode($call9, $arraydecay) | 0;
+ $tobool29 = ($call28 | 0) == 0;
+ if ($tobool29) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $cmp39103 = ($call28 | 0) > 0;
+ if ($cmp39103) {
+ $i_0104 = 0;
+ label = 18;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 16:
+ $m_encoding31 = $parser + 144 | 0;
+ $10 = HEAP32[$m_encoding31 >> 2] | 0;
+ $cmp32 = ($10 | 0) == ($enc | 0);
+ if ($cmp32) {
+ label = 17;
+ break;
+ } else {
+ $retval_0 = 14;
+ label = 59;
+ break;
+ }
+ case 17:
+ $m_eventPtr35 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr35 >> 2] = $ptr_addr_0;
+ $retval_0 = 14;
+ label = 59;
+ break;
+ case 18:
+ $11 = HEAP32[$ptr41 >> 2] | 0;
+ $12 = HEAP32[$end42 >> 2] | 0;
+ $cmp43 = ($11 | 0) == ($12 | 0);
+ if ($cmp43) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $call46 = _poolGrow($pool) | 0;
+ $tobool47 = $call46 << 24 >> 24 == 0;
+ if ($tobool47) {
+ $retval_0 = 1;
+ label = 59;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $arrayidx48 = $buf + $i_0104 | 0;
+ $13 = HEAP8[$arrayidx48] | 0;
+ $14 = HEAP32[$ptr41 >> 2] | 0;
+ $incdec_ptr = $14 + 1 | 0;
+ HEAP32[$ptr41 >> 2] = $incdec_ptr;
+ HEAP8[$14] = $13;
+ $inc = $i_0104 + 1 | 0;
+ $cmp39 = ($inc | 0) < ($call28 | 0);
+ if ($cmp39) {
+ $i_0104 = $inc;
+ label = 18;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 21:
+ $15 = HEAP32[$next >> 2] | 0;
+ $call53 = _poolAppend($pool, $enc, $ptr_addr_0, $15) | 0;
+ $tobool54 = ($call53 | 0) == 0;
+ if ($tobool54) {
+ $retval_0 = 1;
+ label = 59;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 22:
+ $16 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr = $ptr_addr_0 + $16 | 0;
+ HEAP32[$next >> 2] = $add_ptr;
+ label = 23;
+ break;
+ case 23:
+ if ($tobool59) {
+ label = 24;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 24:
+ $17 = HEAP32[$ptr61 >> 2] | 0;
+ $18 = HEAP32[$start62 >> 2] | 0;
+ $cmp66 = ($17 | 0) == ($18 | 0);
+ if ($cmp66) {
+ label = 58;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $arrayidx70 = $17 - 1 | 0;
+ $19 = HEAP8[$arrayidx70] | 0;
+ $cmp72 = $19 << 24 >> 24 == 32;
+ if ($cmp72) {
+ label = 58;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $20 = HEAP32[$ptr76 >> 2] | 0;
+ $21 = HEAP32[$end77 >> 2] | 0;
+ $cmp78 = ($20 | 0) == ($21 | 0);
+ if ($cmp78) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $call81 = _poolGrow($pool) | 0;
+ $tobool82 = $call81 << 24 >> 24 == 0;
+ if ($tobool82) {
+ $retval_0 = 1;
+ label = 59;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $22 = HEAP32[$ptr76 >> 2] | 0;
+ $incdec_ptr86 = $22 + 1 | 0;
+ HEAP32[$ptr76 >> 2] = $incdec_ptr86;
+ HEAP8[$22] = 32;
+ label = 58;
+ break;
+ case 29:
+ $23 = HEAP32[$predefinedEntityName >> 2] | 0;
+ $24 = HEAP32[$minBytesPerChar90 >> 2] | 0;
+ $add_ptr91 = $ptr_addr_0 + $24 | 0;
+ $25 = HEAP32[$next >> 2] | 0;
+ $idx_neg = -$24 | 0;
+ $add_ptr93 = $25 + $idx_neg | 0;
+ $call94 = FUNCTION_TABLE_iiii[$23 & 1023]($enc, $add_ptr91, $add_ptr93) | 0;
+ $conv95 = $call94 & 255;
+ $tobool96 = $conv95 << 24 >> 24 == 0;
+ if ($tobool96) {
+ label = 33;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $26 = HEAP32[$ptr98 >> 2] | 0;
+ $27 = HEAP32[$end99 >> 2] | 0;
+ $cmp100 = ($26 | 0) == ($27 | 0);
+ if ($cmp100) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ $call103 = _poolGrow($pool) | 0;
+ $tobool104 = $call103 << 24 >> 24 == 0;
+ if ($tobool104) {
+ $retval_0 = 1;
+ label = 59;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $28 = HEAP32[$ptr98 >> 2] | 0;
+ $incdec_ptr108 = $28 + 1 | 0;
+ HEAP32[$ptr98 >> 2] = $incdec_ptr108;
+ HEAP8[$28] = $conv95;
+ label = 58;
+ break;
+ case 33:
+ $29 = HEAP32[$minBytesPerChar90 >> 2] | 0;
+ $add_ptr113 = $ptr_addr_0 + $29 | 0;
+ $30 = HEAP32[$next >> 2] | 0;
+ $idx_neg115 = -$29 | 0;
+ $add_ptr116 = $30 + $idx_neg115 | 0;
+ $call117 = _poolStoreString($m_temp2Pool, $enc, $add_ptr113, $add_ptr116) | 0;
+ $tobool118 = ($call117 | 0) == 0;
+ if ($tobool118) {
+ $retval_0 = 1;
+ label = 59;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $call121 = _lookup($parser, $generalEntities, $call117, 0) | 0;
+ $31 = $call121;
+ $32 = HEAP32[$start123 >> 2] | 0;
+ HEAP32[$ptr125 >> 2] = $32;
+ if ($cmp127) {
+ label = 35;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 35:
+ $33 = HEAP8[$standalone] | 0;
+ $tobool131 = $33 << 24 >> 24 == 0;
+ if ($tobool131) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $34 = HEAP32[$m_openInternalEntities >> 2] | 0;
+ $tobool133 = ($34 | 0) != 0;
+ $tobool133_sink = $tobool133;
+ label = 38;
+ break;
+ case 37:
+ $35 = HEAP8[$hasParamEntityRefs] | 0;
+ $tobool135 = $35 << 24 >> 24 != 0;
+ $tobool133_sink = $tobool135;
+ label = 38;
+ break;
+ case 38:
+ $36 = $tobool133_sink & 1;
+ $conv138 = $36 ^ 1;
+ $checkEntityDecl_0 = $conv138;
+ label = 42;
+ break;
+ case 39:
+ $37 = HEAP8[$hasParamEntityRefs139] | 0;
+ $tobool140 = $37 << 24 >> 24 == 0;
+ if ($tobool140) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 40:
+ $tobool148101 = ($call121 | 0) == 0;
+ if ($tobool148101) {
+ $retval_0 = 11;
+ label = 59;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 41:
+ $38 = HEAP8[$standalone141] | 0;
+ $tobool143 = $38 << 24 >> 24 != 0;
+ $phitmp = $tobool143 & 1;
+ $checkEntityDecl_0 = $phitmp;
+ label = 42;
+ break;
+ case 42:
+ $tobool146 = $checkEntityDecl_0 << 24 >> 24 == 0;
+ $tobool148 = ($call121 | 0) != 0;
+ if ($tobool146) {
+ label = 45;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ if ($tobool148) {
+ label = 44;
+ break;
+ } else {
+ $retval_0 = 11;
+ label = 59;
+ break;
+ }
+ case 44:
+ $is_internal = $31 + 34 | 0;
+ $39 = HEAP8[$is_internal] | 0;
+ $tobool151 = $39 << 24 >> 24 == 0;
+ if ($tobool151) {
+ $retval_0 = 24;
+ label = 59;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 45:
+ if ($tobool148) {
+ label = 46;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 46:
+ $open = $call121 + 32 | 0;
+ $40 = $open;
+ $41 = HEAP8[$40] | 0;
+ $tobool160 = $41 << 24 >> 24 == 0;
+ if ($tobool160) {
+ label = 49;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $m_encoding162 = $parser + 144 | 0;
+ $42 = HEAP32[$m_encoding162 >> 2] | 0;
+ $cmp163 = ($42 | 0) == ($enc | 0);
+ if ($cmp163) {
+ label = 48;
+ break;
+ } else {
+ $retval_0 = 12;
+ label = 59;
+ break;
+ }
+ case 48:
+ $m_eventPtr166 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr166 >> 2] = $ptr_addr_0;
+ $retval_0 = 12;
+ label = 59;
+ break;
+ case 49:
+ $43 = $call121 + 28 | 0;
+ $44 = HEAP32[$43 >> 2] | 0;
+ $tobool169 = ($44 | 0) == 0;
+ if ($tobool169) {
+ label = 52;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $m_encoding171 = $parser + 144 | 0;
+ $45 = HEAP32[$m_encoding171 >> 2] | 0;
+ $cmp172 = ($45 | 0) == ($enc | 0);
+ if ($cmp172) {
+ label = 51;
+ break;
+ } else {
+ $retval_0 = 15;
+ label = 59;
+ break;
+ }
+ case 51:
+ $m_eventPtr175 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr175 >> 2] = $ptr_addr_0;
+ $retval_0 = 15;
+ label = 59;
+ break;
+ case 52:
+ $46 = $call121 + 4 | 0;
+ $47 = HEAP32[$46 >> 2] | 0;
+ $tobool178 = ($47 | 0) == 0;
+ if ($tobool178) {
+ label = 53;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 53:
+ $m_encoding180 = $parser + 144 | 0;
+ $48 = HEAP32[$m_encoding180 >> 2] | 0;
+ $cmp181 = ($48 | 0) == ($enc | 0);
+ if ($cmp181) {
+ label = 54;
+ break;
+ } else {
+ $retval_0 = 16;
+ label = 59;
+ break;
+ }
+ case 54:
+ $m_eventPtr184 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr184 >> 2] = $ptr_addr_0;
+ $retval_0 = 16;
+ label = 59;
+ break;
+ case 55:
+ $textLen = $call121 + 8 | 0;
+ $49 = $textLen;
+ $50 = HEAP32[$49 >> 2] | 0;
+ $add_ptr188 = $47 + $50 | 0;
+ HEAP8[$40] = 1;
+ $51 = HEAP32[$m_internalEncoding >> 2] | 0;
+ $52 = HEAP32[$46 >> 2] | 0;
+ $call191 = _appendAttributeValue($parser, $51, $isCdata, $52, $add_ptr188, $pool) | 0;
+ HEAP8[$40] = 0;
+ $tobool193 = ($call191 | 0) == 0;
+ if ($tobool193) {
+ label = 58;
+ break;
+ } else {
+ $retval_0 = $call191;
+ label = 59;
+ break;
+ }
+ case 56:
+ $m_encoding197 = $parser + 144 | 0;
+ $53 = HEAP32[$m_encoding197 >> 2] | 0;
+ $cmp198 = ($53 | 0) == ($enc | 0);
+ if ($cmp198) {
+ label = 57;
+ break;
+ } else {
+ $retval_0 = 23;
+ label = 59;
+ break;
+ }
+ case 57:
+ $m_eventPtr201 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr201 >> 2] = $ptr_addr_0;
+ $retval_0 = 23;
+ label = 59;
+ break;
+ case 58:
+ $54 = HEAP32[$next >> 2] | 0;
+ $ptr_addr_0 = $54;
+ label = 3;
+ break;
+ case 59:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _poolAppend($pool, $enc, $ptr, $end) {
+ $pool = $pool | 0;
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ var $ptr_addr = 0, $ptr1 = 0, $0 = 0, $tobool = 0, $call = 0, $tobool2 = 0, $utf8Convert = 0, $end4 = 0, $1 = 0, $2 = 0, $3 = 0, $cmp = 0, $call7 = 0, $tobool8 = 0, $start = 0, $4 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr_addr = __stackBase__ | 0;
+ HEAP32[$ptr_addr >> 2] = $ptr;
+ $ptr1 = $pool + 12 | 0;
+ $0 = HEAP32[$ptr1 >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _poolGrow($pool) | 0;
+ $tobool2 = $call << 24 >> 24 == 0;
+ if ($tobool2) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $utf8Convert = $enc + 56 | 0;
+ $end4 = $pool + 8 | 0;
+ label = 5;
+ break;
+ case 5:
+ $1 = HEAP32[$utf8Convert >> 2] | 0;
+ $2 = HEAP32[$end4 >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$1 & 1023]($enc, $ptr_addr, $end, $ptr1, $2);
+ $3 = HEAP32[$ptr_addr >> 2] | 0;
+ $cmp = ($3 | 0) == ($end | 0);
+ if ($cmp) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $call7 = _poolGrow($pool) | 0;
+ $tobool8 = $call7 << 24 >> 24 == 0;
+ if ($tobool8) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 7:
+ $start = $pool + 16 | 0;
+ $4 = HEAP32[$start >> 2] | 0;
+ $retval_0 = $4;
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _internalEntityProcessor($parser, $s, $end, $nextPtr) {
+ $parser = $parser | 0;
+ $s = $s | 0;
+ $end = $end | 0;
+ $nextPtr = $nextPtr | 0;
+ var $next = 0, $m_openInternalEntities = 0, $0 = 0, $tobool = 0, $entity1 = 0, $1 = 0, $textPtr = 0, $2 = 0, $processed = 0, $3 = 0, $add_ptr = 0, $textLen = 0, $4 = 0, $add_ptr3 = 0, $startTagLevel = 0, $5 = 0, $m_internalEncoding = 0, $6 = 0, $call = 0, $cmp = 0, $7 = 0, $cmp5 = 0, $parsing = 0, $8 = 0, $cmp6 = 0, $9 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $open = 0, $next11 = 0, $10 = 0, $m_freeInternalEntities = 0, $11 = 0, $m_processor = 0, $m_parentParser = 0, $12 = 0, $tobool17 = 0, $cond = 0, $m_encoding = 0, $13 = 0, $finalBuffer = 0, $14 = 0, $lnot = 0, $conv = 0, $call20 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $next = __stackBase__ | 0;
+ $m_openInternalEntities = $parser + 284 | 0;
+ $0 = HEAP32[$m_openInternalEntities >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 23;
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $entity1 = $0 + 12 | 0;
+ $1 = HEAP32[$entity1 >> 2] | 0;
+ $textPtr = $1 + 4 | 0;
+ $2 = HEAP32[$textPtr >> 2] | 0;
+ $processed = $1 + 12 | 0;
+ $3 = HEAP32[$processed >> 2] | 0;
+ $add_ptr = $2 + $3 | 0;
+ $textLen = $1 + 8 | 0;
+ $4 = HEAP32[$textLen >> 2] | 0;
+ $add_ptr3 = $2 + $4 | 0;
+ $startTagLevel = $0 + 16 | 0;
+ $5 = HEAP32[$startTagLevel >> 2] | 0;
+ $m_internalEncoding = $parser + 224 | 0;
+ $6 = HEAP32[$m_internalEncoding >> 2] | 0;
+ $call = _doContent($parser, $5, $6, $add_ptr, $add_ptr3, $next, 0) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = $call;
+ label = 8;
+ break;
+ }
+ case 4:
+ $7 = HEAP32[$next >> 2] | 0;
+ $cmp5 = ($add_ptr3 | 0) == ($7 | 0);
+ if ($cmp5) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $parsing = $parser + 464 | 0;
+ $8 = HEAP32[$parsing >> 2] | 0;
+ $cmp6 = ($8 | 0) == 3;
+ if ($cmp6) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $9 = HEAP32[$textPtr >> 2] | 0;
+ $sub_ptr_lhs_cast = $7;
+ $sub_ptr_rhs_cast = $9;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ HEAP32[$processed >> 2] = $sub_ptr_sub;
+ $retval_0 = $call;
+ label = 8;
+ break;
+ case 7:
+ $open = $1 + 32 | 0;
+ HEAP8[$open] = 0;
+ $next11 = $0 + 8 | 0;
+ $10 = HEAP32[$next11 >> 2] | 0;
+ HEAP32[$m_openInternalEntities >> 2] = $10;
+ $m_freeInternalEntities = $parser + 288 | 0;
+ $11 = HEAP32[$m_freeInternalEntities >> 2] | 0;
+ HEAP32[$next11 >> 2] = $11;
+ HEAP32[$m_freeInternalEntities >> 2] = $0;
+ $m_processor = $parser + 264 | 0;
+ HEAP32[$m_processor >> 2] = 122;
+ $m_parentParser = $parser + 460 | 0;
+ $12 = HEAP32[$m_parentParser >> 2] | 0;
+ $tobool17 = ($12 | 0) != 0;
+ $cond = $tobool17 & 1;
+ $m_encoding = $parser + 144 | 0;
+ $13 = HEAP32[$m_encoding >> 2] | 0;
+ $finalBuffer = $parser + 468 | 0;
+ $14 = HEAP8[$finalBuffer] | 0;
+ $lnot = $14 << 24 >> 24 == 0;
+ $conv = $lnot & 1;
+ $call20 = _doContent($parser, $cond, $13, $s, $end, $nextPtr, $conv) | 0;
+ $retval_0 = $call20;
+ label = 8;
+ break;
+ case 8:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _handleUnknownEncoding($parser, $encodingName) {
+ $parser = $parser | 0;
+ $encodingName = $encodingName | 0;
+ var $info = 0, $m_unknownEncodingHandler = 0, $0 = 0, $tobool = 0, $info15 = 0, $convert = 0, $data = 0, $release = 0, $1 = 0, $m_unknownEncodingHandlerData = 0, $2 = 0, $call = 0, $tobool2 = 0, $malloc_fcn = 0, $3 = 0, $call5 = 0, $m_unknownEncodingMem = 0, $tobool7 = 0, $4 = 0, $tobool10 = 0, $5 = 0, $arraydecay = 0, $6 = 0, $7 = 0, $call20 = 0, $tobool21 = 0, $8 = 0, $m_unknownEncodingData = 0, $9 = 0, $m_unknownEncodingRelease = 0, $m_encoding = 0, $10 = 0, $cmp28 = 0, $11 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 1040 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $info = __stackBase__ | 0;
+ $m_unknownEncodingHandler = $parser + 124 | 0;
+ $0 = HEAP32[$m_unknownEncodingHandler >> 2] | 0;
+ $tobool = ($0 | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 18;
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $info15 = $info;
+ _memset($info15 | 0, -1 | 0, 1024);
+ $convert = $info + 1028 | 0;
+ HEAP32[$convert >> 2] = 0;
+ $data = $info + 1024 | 0;
+ HEAP32[$data >> 2] = 0;
+ $release = $info + 1032 | 0;
+ HEAP32[$release >> 2] = 0;
+ $1 = HEAP32[$m_unknownEncodingHandler >> 2] | 0;
+ $m_unknownEncodingHandlerData = $parser + 244 | 0;
+ $2 = HEAP32[$m_unknownEncodingHandlerData >> 2] | 0;
+ $call = FUNCTION_TABLE_iiii[$1 & 1023]($2, $encodingName, $info) | 0;
+ $tobool2 = ($call | 0) == 0;
+ if ($tobool2) {
+ label = 9;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $malloc_fcn = $parser + 12 | 0;
+ $3 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call5 = FUNCTION_TABLE_ii[$3 & 1023](1908) | 0;
+ $m_unknownEncodingMem = $parser + 236 | 0;
+ HEAP32[$m_unknownEncodingMem >> 2] = $call5;
+ $tobool7 = ($call5 | 0) == 0;
+ if ($tobool7) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $4 = HEAP32[$release >> 2] | 0;
+ $tobool10 = ($4 | 0) == 0;
+ if ($tobool10) {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $5 = HEAP32[$data >> 2] | 0;
+ FUNCTION_TABLE_vi[$4 & 1023]($5);
+ $retval_0 = 1;
+ label = 11;
+ break;
+ case 7:
+ $arraydecay = $info | 0;
+ $6 = HEAP32[$convert >> 2] | 0;
+ $7 = HEAP32[$data >> 2] | 0;
+ $call20 = _XmlInitUnknownEncoding($call5, $arraydecay, $6, $7) | 0;
+ $tobool21 = ($call20 | 0) == 0;
+ if ($tobool21) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $8 = HEAP32[$data >> 2] | 0;
+ $m_unknownEncodingData = $parser + 240 | 0;
+ HEAP32[$m_unknownEncodingData >> 2] = $8;
+ $9 = HEAP32[$release >> 2] | 0;
+ $m_unknownEncodingRelease = $parser + 248 | 0;
+ HEAP32[$m_unknownEncodingRelease >> 2] = $9;
+ $m_encoding = $parser + 144 | 0;
+ HEAP32[$m_encoding >> 2] = $call20;
+ $retval_0 = 0;
+ label = 11;
+ break;
+ case 9:
+ $10 = HEAP32[$release >> 2] | 0;
+ $cmp28 = ($10 | 0) == 0;
+ if ($cmp28) {
+ $retval_0 = 18;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $11 = HEAP32[$data >> 2] | 0;
+ FUNCTION_TABLE_vi[$10 & 1023]($11);
+ $retval_0 = 18;
+ label = 11;
+ break;
+ case 11:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _generate_hash_secret_salt() {
+ _srand(((_time(0) | 0) >>> 0) % 4294967295 | 0);
+ return _rand() | 0;
+}
+function _prologInitProcessor($parser, $s, $end, $nextPtr) {
+ $parser = $parser | 0;
+ $s = $s | 0;
+ $end = $end | 0;
+ $nextPtr = $nextPtr | 0;
+ var $call = 0, $cmp = 0, $m_processor = 0, $call1 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _initializeEncoding($parser) | 0;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = $call;
+ label = 4;
+ break;
+ }
+ case 3:
+ $m_processor = $parser + 264 | 0;
+ HEAP32[$m_processor >> 2] = 106;
+ $call1 = _prologProcessor($parser, $s, $end, $nextPtr) | 0;
+ $retval_0 = $call1;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _prologProcessor($parser, $s, $end, $nextPtr) {
+ $parser = $parser | 0;
+ $s = $s | 0;
+ $end = $end | 0;
+ $nextPtr = $nextPtr | 0;
+ var $next = 0, $m_encoding = 0, $0 = 0, $call = 0, $call3 = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ $next = __stackBase__ | 0;
+ HEAP32[$next >> 2] = $s;
+ $m_encoding = $parser + 144 | 0;
+ $0 = HEAP32[$m_encoding >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[HEAP32[$0 >> 2] & 1023]($0, $s, $end, $next) | 0;
+ $call3 = _doProlog($parser, HEAP32[$m_encoding >> 2] | 0, $s, $end, $call, HEAP32[$next >> 2] | 0, $nextPtr, (HEAP8[$parser + 468 | 0] | 0) == 0 & 1) | 0;
+ STACKTOP = __stackBase__;
+ return $call3 | 0;
+}
+function _doProlog($parser, $enc, $s, $end, $tok, $next, $nextPtr, $haveMore) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $s = $s | 0;
+ $end = $end | 0;
+ $tok = $tok | 0;
+ $next = $next | 0;
+ $nextPtr = $nextPtr | 0;
+ $haveMore = $haveMore | 0;
+ var $next_addr = 0, $m_dtd = 0, $0 = 0, $m_encoding = 0, $1 = 0, $cmp = 0, $m_eventPtr = 0, $m_eventEndPtr = 0, $m_openInternalEntities = 0, $2 = 0, $internalEventPtr = 0, $internalEventEndPtr = 0, $eventEndPP_0_ph = 0, $eventPP_0_ph = 0, $tobool = 0, $m_prologState = 0, $handler = 0, $m_defaultHandler = 0, $parsing = 0, $m_startDoctypeDeclHandler = 0, $m_doctypeSysid = 0, $m_tempPool = 0, $m_doctypeName = 0, $ptr = 0, $start = 0, $m_doctypePubid = 0, $m_startDoctypeDeclHandler34 = 0, $m_handlerArg = 0, $m_doctypeName38 = 0, $m_doctypeSysid39 = 0, $m_doctypePubid40 = 0, $m_tempPool42 = 0, $hasParamEntityRefs = 0, $m_startDoctypeDeclHandler45 = 0, $m_tempPool52 = 0, $ptr60 = 0, $start62 = 0, $m_doctypePubid63 = 0, $keepProcessing = 0, $m_declEntity = 0, $pool = 0, $ptr87 = 0, $start89 = 0, $m_entityDeclHandler = 0, $m_doctypeName95 = 0, $m_endDoctypeDeclHandler = 0, $m_handlerArg108 = 0, $m_startDoctypeDeclHandler98 = 0, $m_handlerArg99 = 0, $m_doctypeSysid101 = 0, $m_doctypePubid102 = 0, $m_tempPool103 = 0, $m_declElementType = 0, $keepProcessing142 = 0, $m_attlistDeclHandler = 0, $m_declAttributeId = 0, $m_declAttributeIsCdata = 0, $m_declAttributeType = 0, $m_declAttributeIsId = 0, $m_declAttributeIsCdata125 = 0, $m_declAttributeType126 = 0, $m_declAttributeIsId128 = 0, $m_declAttributeType129 = 0, $m_declAttributeType131 = 0, $m_declAttributeType133 = 0, $m_declAttributeType135 = 0, $m_declAttributeType137 = 0, $m_declAttributeType139 = 0, $m_declAttributeType141 = 0, $keepProcessing150 = 0, $m_attlistDeclHandler154 = 0, $m_declAttributeType157 = 0, $m_tempPool164 = 0, $start175 = 0, $keepProcessing179 = 0, $m_declElementType182 = 0, $m_declAttributeId183 = 0, $m_declAttributeIsCdata184 = 0, $m_declAttributeIsId185 = 0, $m_attlistDeclHandler190 = 0, $m_declAttributeType193 = 0, $m_handlerArg249 = 0, $m_tempPool256 = 0, $m_tempPool210 = 0, $ptr211 = 0, $end213 = 0, $start241 = 0, $keepProcessing260 = 0, $m_declAttributeIsCdata264 = 0, $pool270 = 0, $start276 = 0, $ptr278 = 0, $m_declElementType281 = 0, $m_declAttributeId282 = 0, $m_attlistDeclHandler288 = 0, $m_declAttributeType291 = 0, $m_handlerArg352 = 0, $m_tempPool360 = 0, $m_tempPool310 = 0, $ptr311 = 0, $end313 = 0, $start344 = 0, $keepProcessing364 = 0, $m_declEntity374 = 0, $start377 = 0, $ptr406 = 0, $ptr380 = 0, $m_entityDeclHandler388 = 0, $m_handlerArg392 = 0, $m_curBase = 0, $hasParamEntityRefs414 = 0, $m_startDoctypeDeclHandler415 = 0, $standalone = 0, $m_notStandaloneHandler = 0, $m_handlerArg441 = 0, $m_tempPool418 = 0, $m_doctypeSysid425 = 0, $ptr432 = 0, $start434 = 0, $keepProcessing447 = 0, $m_declEntity451 = 0, $pool454 = 0, $m_curBase467 = 0, $ptr470 = 0, $start472 = 0, $m_entityDeclHandler473 = 0, $keepProcessing479 = 0, $m_declEntity483 = 0, $m_entityDeclHandler486 = 0, $m_handlerArg490 = 0, $keepProcessing504 = 0, $m_declEntity508 = 0, $pool511 = 0, $ptr520 = 0, $start522 = 0, $m_unparsedEntityDeclHandler = 0, $m_entityDeclHandler538 = 0, $m_handlerArg542 = 0, $m_handlerArg526 = 0, $keepProcessing562 = 0, $start608 = 0, $ptr610 = 0, $m_declEntity611 = 0, $pool566 = 0, $generalEntities = 0, $m_declEntity572 = 0, $ptr589 = 0, $start591 = 0, $m_parentParser = 0, $m_openInternalEntities597 = 0, $m_entityDeclHandler601 = 0, $start583 = 0, $ptr585 = 0, $m_declEntity560 = 0, $m_declEntity614 = 0, $m_declNotationPublicId = 0, $m_declNotationName = 0, $m_notationDeclHandler = 0, $m_tempPool618 = 0, $ptr626 = 0, $start628 = 0, $m_declNotationName636 = 0, $m_tempPool640 = 0, $m_declNotationPublicId650 = 0, $ptr652 = 0, $start654 = 0, $m_declNotationName657 = 0, $m_tempPool680 = 0, $m_notationDeclHandler660 = 0, $m_tempPool664 = 0, $m_handlerArg675 = 0, $m_curBase677 = 0, $m_declNotationPublicId678 = 0, $m_declNotationPublicId682 = 0, $m_tempPool694 = 0, $m_notationDeclHandler685 = 0, $m_handlerArg689 = 0, $m_declNotationName690 = 0, $m_curBase691 = 0, $level = 0, $m_groupSize = 0, $m_groupConnector742 = 0, $in_eldecl = 0, $scaffLevel = 0, $scaffIndex751 = 0, $scaffold = 0, $m_elementDeclHandler = 0, $malloc_fcn = 0, $m_groupConnector733 = 0, $realloc_fcn = 0, $m_groupConnector = 0, $scaffIndex = 0, $level761 = 0, $m_groupConnector762 = 0, $in_eldecl773 = 0, $m_elementDeclHandler777 = 0, $level783 = 0, $m_groupConnector784 = 0, $in_eldecl791 = 0, $scaffLevel801 = 0, $scaffIndex803 = 0, $scaffold805 = 0, $m_elementDeclHandler818 = 0, $standalone828 = 0, $m_notStandaloneHandler831 = 0, $m_handlerArg835 = 0, $m_elementDeclHandler841 = 0, $m_declElementType845 = 0, $scaffLevel850 = 0, $scaffCount = 0, $in_eldecl851 = 0, $in_eldecl854 = 0, $m_elementDeclHandler857 = 0, $malloc_fcn861 = 0, $m_handlerArg873 = 0, $m_declElementType874 = 0, $in_eldecl880 = 0, $scaffLevel883 = 0, $scaffIndex885 = 0, $scaffold887 = 0, $m_elementDeclHandler890 = 0, $in_eldecl899 = 0, $scaffold917 = 0, $contentStringLen = 0, $m_elementDeclHandler935 = 0, $in_eldecl944 = 0, $m_elementDeclHandler947 = 0, $scaffLevel951 = 0, $scaffIndex953 = 0, $scaffold955 = 0, $contentStringLen974 = 0, $m_handlerArg969 = 0, $m_declElementType970 = 0, $m_startDoctypeDeclHandler991 = 0, $keepProcessing996 = 0, $m_entityDeclHandler1000 = 0, $m_notationDeclHandler1005 = 0, $keepProcessing1010 = 0, $m_attlistDeclHandler1014 = 0, $m_elementDeclHandler1019 = 0, $tok_addr_0 = 0, $s_addr_0 = 0, $enc_addr_0 = 0, $3 = 0, $cmp2 = 0, $cmp4 = 0, $or_cond = 0, $4 = 0, $sub = 0, $sub12 = 0, $tok_addr_1 = 0, $5 = 0, $6 = 0, $call = 0, $7 = 0, $call16 = 0, $cmp17 = 0, $8 = 0, $9 = 0, $tobool23 = 0, $10 = 0, $call25 = 0, $tobool27 = 0, $11 = 0, $handleDefault_0 = 0, $12 = 0, $tobool35 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, $17 = 0, $tobool46 = 0, $isPublicId = 0, $18 = 0, $19 = 0, $call48 = 0, $tobool49 = 0, $minBytesPerChar = 0, $20 = 0, $add_ptr = 0, $21 = 0, $idx_neg = 0, $add_ptr54 = 0, $call55 = 0, $tobool56 = 0, $22 = 0, $isPublicId66 = 0, $23 = 0, $24 = 0, $call67 = 0, $tobool68 = 0, $handleDefault_1 = 0, $25 = 0, $tobool72 = 0, $26 = 0, $tobool74 = 0, $minBytesPerChar76 = 0, $27 = 0, $add_ptr77 = 0, $28 = 0, $idx_neg79 = 0, $add_ptr80 = 0, $call81 = 0, $tobool82 = 0, $29 = 0, $publicId = 0, $30 = 0, $31 = 0, $tobool90 = 0, $handleDefault_1_ = 0, $32 = 0, $tobool96 = 0, $33 = 0, $34 = 0, $35 = 0, $36 = 0, $handleDefault_2 = 0, $37 = 0, $tobool105 = 0, $38 = 0, $m_processor = 0, $call111 = 0, $39 = 0, $call113 = 0, $tobool115 = 0, $40 = 0, $call119 = 0, $tobool121 = 0, $41 = 0, $tobool144 = 0, $42 = 0, $tobool146 = 0, $_ = 0, $43 = 0, $tobool152 = 0, $44 = 0, $tobool155 = 0, $45 = 0, $tobool158 = 0, $cmp161 = 0, $cond = 0, $prefix_0 = 0, $call165 = 0, $tobool166 = 0, $46 = 0, $call170 = 0, $tobool171 = 0, $47 = 0, $48 = 0, $tobool180 = 0, $49 = 0, $50 = 0, $51 = 0, $52 = 0, $call186 = 0, $tobool187 = 0, $53 = 0, $tobool191 = 0, $54 = 0, $tobool194 = 0, $55 = 0, $arrayidx = 0, $56 = 0, $cmp207 = 0, $57 = 0, $58 = 0, $cmp214 = 0, $call218 = 0, $tobool219 = 0, $59 = 0, $incdec_ptr = 0, $60 = 0, $61 = 0, $cmp227 = 0, $call231 = 0, $tobool232 = 0, $62 = 0, $incdec_ptr237 = 0, $63 = 0, $64 = 0, $65 = 0, $66 = 0, $67 = 0, $name = 0, $68 = 0, $69 = 0, $name252 = 0, $70 = 0, $71 = 0, $cmp254 = 0, $conv255 = 0, $72 = 0, $tobool261 = 0, $73 = 0, $minBytesPerChar265 = 0, $74 = 0, $add_ptr266 = 0, $75 = 0, $idx_neg268 = 0, $add_ptr269 = 0, $call271 = 0, $tobool272 = 0, $76 = 0, $77 = 0, $78 = 0, $79 = 0, $80 = 0, $call284 = 0, $tobool285 = 0, $81 = 0, $tobool289 = 0, $82 = 0, $tobool292 = 0, $83 = 0, $arrayidx305 = 0, $84 = 0, $cmp307 = 0, $85 = 0, $86 = 0, $cmp314 = 0, $call318 = 0, $tobool319 = 0, $87 = 0, $incdec_ptr324 = 0, $88 = 0, $89 = 0, $cmp330 = 0, $call334 = 0, $tobool335 = 0, $90 = 0, $incdec_ptr340 = 0, $91 = 0, $92 = 0, $93 = 0, $94 = 0, $95 = 0, $name354 = 0, $96 = 0, $97 = 0, $name356 = 0, $98 = 0, $99 = 0, $cmp358 = 0, $conv359 = 0, $100 = 0, $tobool365 = 0, $minBytesPerChar368 = 0, $101 = 0, $add_ptr369 = 0, $102 = 0, $idx_neg371 = 0, $add_ptr372 = 0, $call373 = 0, $103 = 0, $tobool375 = 0, $104 = 0, $textPtr = 0, $105 = 0, $106 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $107 = 0, $textLen = 0, $108 = 0, $109 = 0, $tobool389 = 0, $110 = 0, $111 = 0, $112 = 0, $name394 = 0, $113 = 0, $is_param = 0, $114 = 0, $conv396 = 0, $textPtr398 = 0, $115 = 0, $textLen400 = 0, $116 = 0, $117 = 0, $handleDefault_3 = 0, $cmp408 = 0, $118 = 0, $tobool416 = 0, $minBytesPerChar419 = 0, $119 = 0, $add_ptr420 = 0, $120 = 0, $idx_neg422 = 0, $add_ptr423 = 0, $call424 = 0, $cmp427 = 0, $121 = 0, $handleDefault_4 = 0, $122 = 0, $tobool436 = 0, $123 = 0, $tobool438 = 0, $124 = 0, $call442 = 0, $tobool443 = 0, $125 = 0, $tobool449 = 0, $126 = 0, $tobool452 = 0, $minBytesPerChar455 = 0, $127 = 0, $add_ptr456 = 0, $128 = 0, $idx_neg458 = 0, $add_ptr459 = 0, $call460 = 0, $129 = 0, $systemId = 0, $130 = 0, $systemId463 = 0, $131 = 0, $tobool464 = 0, $132 = 0, $base = 0, $133 = 0, $134 = 0, $tobool474 = 0, $_515 = 0, $135 = 0, $tobool481 = 0, $136 = 0, $tobool484 = 0, $137 = 0, $tobool487 = 0, $138 = 0, $139 = 0, $140 = 0, $name492 = 0, $141 = 0, $is_param494 = 0, $142 = 0, $conv495 = 0, $base497 = 0, $143 = 0, $systemId499 = 0, $144 = 0, $publicId501 = 0, $145 = 0, $146 = 0, $tobool506 = 0, $147 = 0, $tobool509 = 0, $148 = 0, $call512 = 0, $149 = 0, $notation = 0, $150 = 0, $notation515 = 0, $151 = 0, $tobool516 = 0, $152 = 0, $153 = 0, $tobool523 = 0, $154 = 0, $155 = 0, $156 = 0, $name528 = 0, $157 = 0, $base530 = 0, $158 = 0, $systemId532 = 0, $159 = 0, $publicId534 = 0, $160 = 0, $notation536 = 0, $161 = 0, $162 = 0, $tobool539 = 0, $163 = 0, $164 = 0, $165 = 0, $name544 = 0, $166 = 0, $base546 = 0, $167 = 0, $systemId548 = 0, $168 = 0, $publicId550 = 0, $169 = 0, $notation552 = 0, $170 = 0, $predefinedEntityName = 0, $171 = 0, $172 = 0, $call557 = 0, $tobool558 = 0, $173 = 0, $tobool563 = 0, $174 = 0, $call567 = 0, $tobool568 = 0, $call571 = 0, $175 = 0, $tobool574 = 0, $name578 = 0, $176 = 0, $cmp579 = 0, $177 = 0, $178 = 0, $179 = 0, $publicId593 = 0, $180 = 0, $is_param595 = 0, $181 = 0, $tobool596 = 0, $182 = 0, $phitmp = 0, $phitmp514 = 0, $183 = 0, $184 = 0, $is_internal = 0, $185 = 0, $tobool602 = 0, $_516 = 0, $186 = 0, $187 = 0, $tobool616 = 0, $188 = 0, $call619 = 0, $tobool622 = 0, $189 = 0, $isPublicId631 = 0, $190 = 0, $191 = 0, $call632 = 0, $tobool633 = 0, $192 = 0, $tobool637 = 0, $minBytesPerChar641 = 0, $193 = 0, $add_ptr642 = 0, $194 = 0, $idx_neg644 = 0, $add_ptr645 = 0, $call646 = 0, $tobool647 = 0, $195 = 0, $196 = 0, $tobool658 = 0, $197 = 0, $tobool661 = 0, $minBytesPerChar665 = 0, $198 = 0, $add_ptr666 = 0, $199 = 0, $idx_neg668 = 0, $add_ptr669 = 0, $call670 = 0, $tobool671 = 0, $200 = 0, $201 = 0, $202 = 0, $203 = 0, $204 = 0, $handleDefault_5 = 0, $205 = 0, $tobool683 = 0, $206 = 0, $tobool686 = 0, $207 = 0, $208 = 0, $209 = 0, $210 = 0, $211 = 0, $handleDefault_6 = 0, $212 = 0, $213 = 0, $cmp701 = 0, $tobool705 = 0, $214 = 0, $215 = 0, $mul = 0, $call708 = 0, $cmp709 = 0, $216 = 0, $tobool714 = 0, $217 = 0, $218 = 0, $219 = 0, $mul721 = 0, $call722 = 0, $cmp723 = 0, $220 = 0, $221 = 0, $call732 = 0, $tobool735 = 0, $222 = 0, $223 = 0, $arrayidx743 = 0, $224 = 0, $tobool744 = 0, $call746 = 0, $cmp747 = 0, $225 = 0, $226 = 0, $arrayidx752 = 0, $227 = 0, $inc = 0, $228 = 0, $type = 0, $229 = 0, $tobool755 = 0, $_517 = 0, $230 = 0, $231 = 0, $arrayidx763 = 0, $232 = 0, $cmp765 = 0, $233 = 0, $tobool775 = 0, $234 = 0, $tobool778 = 0, $_518 = 0, $235 = 0, $236 = 0, $arrayidx785 = 0, $237 = 0, $cmp787 = 0, $238 = 0, $tobool793 = 0, $tobool799 = 0, $or_cond519 = 0, $239 = 0, $sub802 = 0, $240 = 0, $arrayidx804 = 0, $241 = 0, $242 = 0, $type807 = 0, $243 = 0, $cmp808 = 0, $244 = 0, $tobool819 = 0, $_520 = 0, $handleDefault_7 = 0, $245 = 0, $246 = 0, $arrayidx826 = 0, $247 = 0, $tobool829 = 0, $248 = 0, $tobool832 = 0, $249 = 0, $call836 = 0, $tobool837 = 0, $250 = 0, $tobool842 = 0, $251 = 0, $call844 = 0, $tobool847 = 0, $252 = 0, $tobool855 = 0, $253 = 0, $tobool858 = 0, $254 = 0, $call862 = 0, $tobool863 = 0, $255 = 0, $quant866 = 0, $cmp868 = 0, $cond870 = 0, $type871 = 0, $256 = 0, $257 = 0, $258 = 0, $name875 = 0, $259 = 0, $handleDefault_8 = 0, $260 = 0, $tobool881 = 0, $261 = 0, $sub884 = 0, $262 = 0, $arrayidx886 = 0, $263 = 0, $264 = 0, $type889 = 0, $265 = 0, $tobool891 = 0, $_521 = 0, $quant_0 = 0, $266 = 0, $tobool900 = 0, $cmp903 = 0, $267 = 0, $minBytesPerChar907 = 0, $268 = 0, $idx_neg908 = 0, $add_ptr909 = 0, $cond910 = 0, $call912 = 0, $cmp913 = 0, $269 = 0, $type919 = 0, $270 = 0, $quant922 = 0, $call923 = 0, $tobool924 = 0, $name927 = 0, $271 = 0, $272 = 0, $name930 = 0, $nameLen_0 = 0, $inc932 = 0, $arrayidx933 = 0, $273 = 0, $tobool934 = 0, $274 = 0, $add = 0, $275 = 0, $tobool936 = 0, $_522 = 0, $quant_1 = 0, $276 = 0, $tobool945 = 0, $277 = 0, $tobool948 = 0, $_523 = 0, $278 = 0, $dec = 0, $279 = 0, $arrayidx954 = 0, $280 = 0, $281 = 0, $quant957 = 0, $282 = 0, $cmp959 = 0, $call964 = 0, $tobool965 = 0, $283 = 0, $284 = 0, $285 = 0, $name971 = 0, $286 = 0, $287 = 0, $call978 = 0, $tobool979 = 0, $288 = 0, $call983 = 0, $tobool984 = 0, $not_cond1 = 0, $_524 = 0, $289 = 0, $tobool992 = 0, $_525 = 0, $290 = 0, $tobool998 = 0, $291 = 0, $tobool1001 = 0, $_526 = 0, $292 = 0, $tobool1006 = 0, $_527 = 0, $293 = 0, $tobool1012 = 0, $294 = 0, $tobool1015 = 0, $_528 = 0, $295 = 0, $tobool1020 = 0, $_529 = 0, $handleDefault_10 = 0, $tobool1025 = 0, $296 = 0, $tobool1027 = 0, $297 = 0, $enc_addr_1532 = 0, $298 = 0, $299 = 0, $300 = 0, $arrayidx1033 = 0, $301 = 0, $call1034 = 0, $retval_0_ph = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $next_addr = __stackBase__ | 0;
+ HEAP32[$next_addr >> 2] = $next;
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $m_encoding = $parser + 144 | 0;
+ $1 = HEAP32[$m_encoding >> 2] | 0;
+ $cmp = ($1 | 0) == ($enc | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $m_eventPtr = $parser + 272 | 0;
+ $m_eventEndPtr = $parser + 276 | 0;
+ $eventPP_0_ph = $m_eventPtr;
+ $eventEndPP_0_ph = $m_eventEndPtr;
+ label = 5;
+ break;
+ case 4:
+ $m_openInternalEntities = $parser + 284 | 0;
+ $2 = HEAP32[$m_openInternalEntities >> 2] | 0;
+ $internalEventPtr = $2 | 0;
+ $internalEventEndPtr = $2 + 4 | 0;
+ $eventPP_0_ph = $internalEventPtr;
+ $eventEndPP_0_ph = $internalEventEndPtr;
+ label = 5;
+ break;
+ case 5:
+ $tobool = $haveMore << 24 >> 24 == 0;
+ $m_prologState = $parser + 252 | 0;
+ $handler = $m_prologState | 0;
+ $m_defaultHandler = $parser + 80 | 0;
+ $parsing = $parser + 464 | 0;
+ $m_startDoctypeDeclHandler = $parser + 84 | 0;
+ $m_doctypeSysid = $parser + 308 | 0;
+ $m_tempPool = $parser + 400 | 0;
+ $m_doctypeName = $parser + 304 | 0;
+ $ptr = $parser + 412 | 0;
+ $start = $parser + 416 | 0;
+ $m_doctypePubid = $parser + 312 | 0;
+ $m_startDoctypeDeclHandler34 = $parser + 84 | 0;
+ $m_handlerArg = $parser + 4 | 0;
+ $m_doctypeName38 = $parser + 304 | 0;
+ $m_doctypeSysid39 = $parser + 308 | 0;
+ $m_doctypePubid40 = $parser + 312 | 0;
+ $m_tempPool42 = $parser + 400 | 0;
+ $hasParamEntityRefs = $0 + 129 | 0;
+ $m_startDoctypeDeclHandler45 = $parser + 84 | 0;
+ $m_tempPool52 = $parser + 400 | 0;
+ $ptr60 = $parser + 412 | 0;
+ $start62 = $parser + 416 | 0;
+ $m_doctypePubid63 = $parser + 312 | 0;
+ $keepProcessing = $0 + 128 | 0;
+ $m_declEntity = $parser + 300 | 0;
+ $pool = $0 + 80 | 0;
+ $ptr87 = $0 + 92 | 0;
+ $start89 = $0 + 96 | 0;
+ $m_entityDeclHandler = $parser + 136 | 0;
+ $m_doctypeName95 = $parser + 304 | 0;
+ $m_endDoctypeDeclHandler = $parser + 88 | 0;
+ $m_handlerArg108 = $parser + 4 | 0;
+ $m_startDoctypeDeclHandler98 = $parser + 84 | 0;
+ $m_handlerArg99 = $parser + 4 | 0;
+ $m_doctypeSysid101 = $parser + 308 | 0;
+ $m_doctypePubid102 = $parser + 312 | 0;
+ $m_tempPool103 = $parser + 400 | 0;
+ $m_declElementType = $parser + 328 | 0;
+ $keepProcessing142 = $0 + 128 | 0;
+ $m_attlistDeclHandler = $parser + 132 | 0;
+ $m_declAttributeId = $parser + 332 | 0;
+ $m_declAttributeIsCdata = $parser + 336 | 0;
+ $m_declAttributeType = $parser + 316 | 0;
+ $m_declAttributeIsId = $parser + 337 | 0;
+ $m_declAttributeIsCdata125 = $parser + 336 | 0;
+ $m_declAttributeType126 = $parser + 316 | 0;
+ $m_declAttributeIsId128 = $parser + 337 | 0;
+ $m_declAttributeType129 = $parser + 316 | 0;
+ $m_declAttributeType131 = $parser + 316 | 0;
+ $m_declAttributeType133 = $parser + 316 | 0;
+ $m_declAttributeType135 = $parser + 316 | 0;
+ $m_declAttributeType137 = $parser + 316 | 0;
+ $m_declAttributeType139 = $parser + 316 | 0;
+ $m_declAttributeType141 = $parser + 316 | 0;
+ $keepProcessing150 = $0 + 128 | 0;
+ $m_attlistDeclHandler154 = $parser + 132 | 0;
+ $m_declAttributeType157 = $parser + 316 | 0;
+ $m_tempPool164 = $parser + 400 | 0;
+ $start175 = $parser + 416 | 0;
+ $keepProcessing179 = $0 + 128 | 0;
+ $m_declElementType182 = $parser + 328 | 0;
+ $m_declAttributeId183 = $parser + 332 | 0;
+ $m_declAttributeIsCdata184 = $parser + 336 | 0;
+ $m_declAttributeIsId185 = $parser + 337 | 0;
+ $m_attlistDeclHandler190 = $parser + 132 | 0;
+ $m_declAttributeType193 = $parser + 316 | 0;
+ $m_handlerArg249 = $parser + 4 | 0;
+ $m_tempPool256 = $parser + 400 | 0;
+ $m_tempPool210 = $parser + 400 | 0;
+ $ptr211 = $parser + 412 | 0;
+ $end213 = $parser + 408 | 0;
+ $start241 = $parser + 416 | 0;
+ $keepProcessing260 = $0 + 128 | 0;
+ $m_declAttributeIsCdata264 = $parser + 336 | 0;
+ $pool270 = $0 + 80 | 0;
+ $start276 = $0 + 96 | 0;
+ $ptr278 = $0 + 92 | 0;
+ $m_declElementType281 = $parser + 328 | 0;
+ $m_declAttributeId282 = $parser + 332 | 0;
+ $m_attlistDeclHandler288 = $parser + 132 | 0;
+ $m_declAttributeType291 = $parser + 316 | 0;
+ $m_handlerArg352 = $parser + 4 | 0;
+ $m_tempPool360 = $parser + 400 | 0;
+ $m_tempPool310 = $parser + 400 | 0;
+ $ptr311 = $parser + 412 | 0;
+ $end313 = $parser + 408 | 0;
+ $start344 = $parser + 416 | 0;
+ $keepProcessing364 = $0 + 128 | 0;
+ $m_declEntity374 = $parser + 300 | 0;
+ $start377 = $0 + 120 | 0;
+ $ptr406 = $0 + 116 | 0;
+ $ptr380 = $0 + 116 | 0;
+ $m_entityDeclHandler388 = $parser + 136 | 0;
+ $m_handlerArg392 = $parser + 4 | 0;
+ $m_curBase = $parser + 344 | 0;
+ $hasParamEntityRefs414 = $0 + 129 | 0;
+ $m_startDoctypeDeclHandler415 = $parser + 84 | 0;
+ $standalone = $0 + 130 | 0;
+ $m_notStandaloneHandler = $parser + 108 | 0;
+ $m_handlerArg441 = $parser + 4 | 0;
+ $m_tempPool418 = $parser + 400 | 0;
+ $m_doctypeSysid425 = $parser + 308 | 0;
+ $ptr432 = $parser + 412 | 0;
+ $start434 = $parser + 416 | 0;
+ $keepProcessing447 = $0 + 128 | 0;
+ $m_declEntity451 = $parser + 300 | 0;
+ $pool454 = $0 + 80 | 0;
+ $m_curBase467 = $parser + 344 | 0;
+ $ptr470 = $0 + 92 | 0;
+ $start472 = $0 + 96 | 0;
+ $m_entityDeclHandler473 = $parser + 136 | 0;
+ $keepProcessing479 = $0 + 128 | 0;
+ $m_declEntity483 = $parser + 300 | 0;
+ $m_entityDeclHandler486 = $parser + 136 | 0;
+ $m_handlerArg490 = $parser + 4 | 0;
+ $keepProcessing504 = $0 + 128 | 0;
+ $m_declEntity508 = $parser + 300 | 0;
+ $pool511 = $0 + 80 | 0;
+ $ptr520 = $0 + 92 | 0;
+ $start522 = $0 + 96 | 0;
+ $m_unparsedEntityDeclHandler = $parser + 92 | 0;
+ $m_entityDeclHandler538 = $parser + 136 | 0;
+ $m_handlerArg542 = $parser + 4 | 0;
+ $m_handlerArg526 = $parser + 4 | 0;
+ $keepProcessing562 = $0 + 128 | 0;
+ $start608 = $0 + 96 | 0;
+ $ptr610 = $0 + 92 | 0;
+ $m_declEntity611 = $parser + 300 | 0;
+ $pool566 = $0 + 80 | 0;
+ $generalEntities = $0 | 0;
+ $m_declEntity572 = $parser + 300 | 0;
+ $ptr589 = $0 + 92 | 0;
+ $start591 = $0 + 96 | 0;
+ $m_parentParser = $parser + 460 | 0;
+ $m_openInternalEntities597 = $parser + 284 | 0;
+ $m_entityDeclHandler601 = $parser + 136 | 0;
+ $start583 = $0 + 96 | 0;
+ $ptr585 = $0 + 92 | 0;
+ $m_declEntity560 = $parser + 300 | 0;
+ $m_declEntity614 = $parser + 300 | 0;
+ $m_declNotationPublicId = $parser + 324 | 0;
+ $m_declNotationName = $parser + 320 | 0;
+ $m_notationDeclHandler = $parser + 96 | 0;
+ $m_tempPool618 = $parser + 400 | 0;
+ $ptr626 = $parser + 412 | 0;
+ $start628 = $parser + 416 | 0;
+ $m_declNotationName636 = $parser + 320 | 0;
+ $m_tempPool640 = $parser + 400 | 0;
+ $m_declNotationPublicId650 = $parser + 324 | 0;
+ $ptr652 = $parser + 412 | 0;
+ $start654 = $parser + 416 | 0;
+ $m_declNotationName657 = $parser + 320 | 0;
+ $m_tempPool680 = $parser + 400 | 0;
+ $m_notationDeclHandler660 = $parser + 96 | 0;
+ $m_tempPool664 = $parser + 400 | 0;
+ $m_handlerArg675 = $parser + 4 | 0;
+ $m_curBase677 = $parser + 344 | 0;
+ $m_declNotationPublicId678 = $parser + 324 | 0;
+ $m_declNotationPublicId682 = $parser + 324 | 0;
+ $m_tempPool694 = $parser + 400 | 0;
+ $m_notationDeclHandler685 = $parser + 96 | 0;
+ $m_handlerArg689 = $parser + 4 | 0;
+ $m_declNotationName690 = $parser + 320 | 0;
+ $m_curBase691 = $parser + 344 | 0;
+ $level = $parser + 256 | 0;
+ $m_groupSize = $parser + 452 | 0;
+ $m_groupConnector742 = $parser + 448 | 0;
+ $in_eldecl = $0 + 140 | 0;
+ $scaffLevel = $0 + 160 | 0;
+ $scaffIndex751 = $0 + 164 | 0;
+ $scaffold = $0 + 144 | 0;
+ $m_elementDeclHandler = $parser + 128 | 0;
+ $malloc_fcn = $parser + 12 | 0;
+ $m_groupConnector733 = $parser + 448 | 0;
+ $realloc_fcn = $parser + 16 | 0;
+ $m_groupConnector = $parser + 448 | 0;
+ $scaffIndex = $0 + 164 | 0;
+ $level761 = $parser + 256 | 0;
+ $m_groupConnector762 = $parser + 448 | 0;
+ $in_eldecl773 = $0 + 140 | 0;
+ $m_elementDeclHandler777 = $parser + 128 | 0;
+ $level783 = $parser + 256 | 0;
+ $m_groupConnector784 = $parser + 448 | 0;
+ $in_eldecl791 = $0 + 140 | 0;
+ $scaffLevel801 = $0 + 160 | 0;
+ $scaffIndex803 = $0 + 164 | 0;
+ $scaffold805 = $0 + 144 | 0;
+ $m_elementDeclHandler818 = $parser + 128 | 0;
+ $standalone828 = $0 + 130 | 0;
+ $m_notStandaloneHandler831 = $parser + 108 | 0;
+ $m_handlerArg835 = $parser + 4 | 0;
+ $m_elementDeclHandler841 = $parser + 128 | 0;
+ $m_declElementType845 = $parser + 328 | 0;
+ $scaffLevel850 = $0 + 160 | 0;
+ $scaffCount = $0 + 156 | 0;
+ $in_eldecl851 = $0 + 140 | 0;
+ $in_eldecl854 = $0 + 140 | 0;
+ $m_elementDeclHandler857 = $parser + 128 | 0;
+ $malloc_fcn861 = $parser + 12 | 0;
+ $m_handlerArg873 = $parser + 4 | 0;
+ $m_declElementType874 = $parser + 328 | 0;
+ $in_eldecl880 = $0 + 140 | 0;
+ $scaffLevel883 = $0 + 160 | 0;
+ $scaffIndex885 = $0 + 164 | 0;
+ $scaffold887 = $0 + 144 | 0;
+ $m_elementDeclHandler890 = $parser + 128 | 0;
+ $in_eldecl899 = $0 + 140 | 0;
+ $scaffold917 = $0 + 144 | 0;
+ $contentStringLen = $0 + 148 | 0;
+ $m_elementDeclHandler935 = $parser + 128 | 0;
+ $in_eldecl944 = $0 + 140 | 0;
+ $m_elementDeclHandler947 = $parser + 128 | 0;
+ $scaffLevel951 = $0 + 160 | 0;
+ $scaffIndex953 = $0 + 164 | 0;
+ $scaffold955 = $0 + 144 | 0;
+ $contentStringLen974 = $0 + 148 | 0;
+ $m_handlerArg969 = $parser + 4 | 0;
+ $m_declElementType970 = $parser + 328 | 0;
+ $m_startDoctypeDeclHandler991 = $parser + 84 | 0;
+ $keepProcessing996 = $0 + 128 | 0;
+ $m_entityDeclHandler1000 = $parser + 136 | 0;
+ $m_notationDeclHandler1005 = $parser + 96 | 0;
+ $keepProcessing1010 = $0 + 128 | 0;
+ $m_attlistDeclHandler1014 = $parser + 132 | 0;
+ $m_elementDeclHandler1019 = $parser + 128 | 0;
+ $enc_addr_0 = $enc;
+ $s_addr_0 = $s;
+ $tok_addr_0 = $tok;
+ label = 6;
+ break;
+ case 6:
+ HEAP32[$eventPP_0_ph >> 2] = $s_addr_0;
+ $3 = HEAP32[$next_addr >> 2] | 0;
+ HEAP32[$eventEndPP_0_ph >> 2] = $3;
+ $cmp2 = ($tok_addr_0 | 0) < 1;
+ if ($cmp2) {
+ label = 7;
+ break;
+ } else {
+ $tok_addr_1 = $tok_addr_0;
+ label = 14;
+ break;
+ }
+ case 7:
+ $cmp4 = ($tok_addr_0 | 0) == 0;
+ $or_cond = $tobool | $cmp4;
+ if ($or_cond) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ HEAP32[$nextPtr >> 2] = $s_addr_0;
+ $retval_0 = 0;
+ label = 208;
+ break;
+ case 9:
+ if (($tok_addr_0 | 0) == 0) {
+ label = 10;
+ break;
+ } else if (($tok_addr_0 | 0) == (-15 | 0)) {
+ label = 11;
+ break;
+ } else if (($tok_addr_0 | 0) == (-4 | 0)) {
+ label = 12;
+ break;
+ } else if (($tok_addr_0 | 0) == (-1 | 0)) {
+ $retval_0_ph = 5;
+ label = 207;
+ break;
+ } else if (($tok_addr_0 | 0) == (-2 | 0)) {
+ $retval_0 = 6;
+ label = 208;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 10:
+ $4 = HEAP32[$next_addr >> 2] | 0;
+ HEAP32[$eventPP_0_ph >> 2] = $4;
+ $retval_0 = 4;
+ label = 208;
+ break;
+ case 11:
+ $sub = -$tok_addr_0 | 0;
+ $tok_addr_1 = $sub;
+ label = 14;
+ break;
+ case 12:
+ $retval_0 = 3;
+ label = 208;
+ break;
+ case 13:
+ $sub12 = -$tok_addr_0 | 0;
+ HEAP32[$next_addr >> 2] = $end;
+ $tok_addr_1 = $sub12;
+ label = 14;
+ break;
+ case 14:
+ $5 = HEAP32[$handler >> 2] | 0;
+ $6 = HEAP32[$next_addr >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiiii[$5 & 1023]($m_prologState, $tok_addr_1, $s_addr_0, $6, $enc_addr_0) | 0;
+ if (($call | 0) == 1) {
+ label = 15;
+ break;
+ } else if (($call | 0) == 4) {
+ label = 17;
+ break;
+ } else if (($call | 0) == 7) {
+ label = 21;
+ break;
+ } else if (($call | 0) == 6) {
+ label = 23;
+ break;
+ } else if (($call | 0) == 14) {
+ label = 27;
+ break;
+ } else if (($call | 0) == 8) {
+ label = 32;
+ break;
+ } else if (($call | 0) == 2) {
+ label = 36;
+ break;
+ } else if (($call | 0) == 34) {
+ label = 37;
+ break;
+ } else if (($call | 0) == 22) {
+ label = 38;
+ break;
+ } else if (($call | 0) == 23) {
+ label = 40;
+ break;
+ } else if (($call | 0) == 24) {
+ label = 41;
+ break;
+ } else if (($call | 0) == 25) {
+ label = 42;
+ break;
+ } else if (($call | 0) == 26) {
+ label = 43;
+ break;
+ } else if (($call | 0) == 27) {
+ label = 44;
+ break;
+ } else if (($call | 0) == 28) {
+ label = 45;
+ break;
+ } else if (($call | 0) == 29) {
+ label = 46;
+ break;
+ } else if (($call | 0) == 30) {
+ label = 47;
+ break;
+ } else if (($call | 0) == 31 | ($call | 0) == 32) {
+ label = 50;
+ break;
+ } else if (($call | 0) == 35 | ($call | 0) == 36) {
+ label = 57;
+ break;
+ } else if (($call | 0) == 37 | ($call | 0) == 38) {
+ label = 69;
+ break;
+ } else if (($call | 0) == 12) {
+ label = 82;
+ break;
+ } else if (($call | 0) == 5) {
+ label = 88;
+ break;
+ } else if (($call | 0) == 13) {
+ label = 94;
+ break;
+ } else if (($call | 0) == 15) {
+ label = 98;
+ break;
+ } else if (($call | 0) == 16) {
+ label = 102;
+ break;
+ } else if (($call | 0) == 9) {
+ label = 109;
+ break;
+ } else if (($call | 0) == 10) {
+ label = 120;
+ break;
+ } else if (($call | 0) == 18) {
+ label = 121;
+ break;
+ } else if (($call | 0) == 21) {
+ label = 124;
+ break;
+ } else if (($call | 0) == 19) {
+ label = 128;
+ break;
+ } else if (($call | 0) == 20) {
+ label = 133;
+ break;
+ } else if (($call | 0) == (-1 | 0)) {
+ label = 137;
+ break;
+ } else if (($call | 0) == 44) {
+ label = 140;
+ break;
+ } else if (($call | 0) == 50) {
+ label = 150;
+ break;
+ } else if (($call | 0) == 49) {
+ label = 153;
+ break;
+ } else if (($call | 0) == 57) {
+ label = 158;
+ break;
+ } else if (($call | 0) == 40) {
+ label = 161;
+ break;
+ } else if (($call | 0) == 41 | ($call | 0) == 42) {
+ label = 164;
+ break;
+ } else if (($call | 0) == 43) {
+ label = 169;
+ break;
+ } else if (($call | 0) == 53) {
+ label = 171;
+ break;
+ } else if (($call | 0) == 52) {
+ label = 172;
+ break;
+ } else if (($call | 0) == 54) {
+ label = 173;
+ break;
+ } else if (($call | 0) == 51) {
+ $quant_0 = 0;
+ label = 174;
+ break;
+ } else if (($call | 0) == 47) {
+ label = 182;
+ break;
+ } else if (($call | 0) == 46) {
+ label = 183;
+ break;
+ } else if (($call | 0) == 48) {
+ label = 184;
+ break;
+ } else if (($call | 0) == 45) {
+ $quant_1 = 0;
+ label = 185;
+ break;
+ } else if (($call | 0) == 55) {
+ label = 191;
+ break;
+ } else if (($call | 0) == 56) {
+ label = 192;
+ break;
+ } else if (($call | 0) == 0) {
+ label = 193;
+ break;
+ } else if (($call | 0) == 3) {
+ label = 194;
+ break;
+ } else if (($call | 0) == 11) {
+ label = 195;
+ break;
+ } else if (($call | 0) == 17) {
+ label = 197;
+ break;
+ } else if (($call | 0) == 33) {
+ label = 198;
+ break;
+ } else if (($call | 0) == 39) {
+ label = 200;
+ break;
+ } else {
+ label = 202;
+ break;
+ }
+ case 15:
+ $7 = HEAP32[$next_addr >> 2] | 0;
+ $call16 = _processXmlDecl($parser, 0, $s_addr_0, $7) | 0;
+ $cmp17 = ($call16 | 0) == 0;
+ if ($cmp17) {
+ label = 16;
+ break;
+ } else {
+ $retval_0_ph = $call16;
+ label = 207;
+ break;
+ }
+ case 16:
+ $8 = HEAP32[$m_encoding >> 2] | 0;
+ $enc_addr_1532 = $8;
+ label = 204;
+ break;
+ case 17:
+ $9 = HEAP32[$m_startDoctypeDeclHandler >> 2] | 0;
+ $tobool23 = ($9 | 0) == 0;
+ if ($tobool23) {
+ $handleDefault_0 = 1;
+ label = 20;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $10 = HEAP32[$next_addr >> 2] | 0;
+ $call25 = _poolStoreString($m_tempPool, $enc_addr_0, $s_addr_0, $10) | 0;
+ HEAP32[$m_doctypeName >> 2] = $call25;
+ $tobool27 = ($call25 | 0) == 0;
+ if ($tobool27) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $11 = HEAP32[$ptr >> 2] | 0;
+ HEAP32[$start >> 2] = $11;
+ HEAP32[$m_doctypePubid >> 2] = 0;
+ $handleDefault_0 = 0;
+ label = 20;
+ break;
+ case 20:
+ HEAP32[$m_doctypeSysid >> 2] = 0;
+ $handleDefault_10 = $handleDefault_0;
+ label = 201;
+ break;
+ case 21:
+ $12 = HEAP32[$m_startDoctypeDeclHandler34 >> 2] | 0;
+ $tobool35 = ($12 | 0) == 0;
+ if ($tobool35) {
+ label = 202;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $13 = HEAP32[$m_handlerArg >> 2] | 0;
+ $14 = HEAP32[$m_doctypeName38 >> 2] | 0;
+ $15 = HEAP32[$m_doctypeSysid39 >> 2] | 0;
+ $16 = HEAP32[$m_doctypePubid40 >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$12 & 1023]($13, $14, $15, $16, 1);
+ HEAP32[$m_doctypeName38 >> 2] = 0;
+ _poolClear($m_tempPool42);
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 23:
+ HEAP8[$hasParamEntityRefs] = 1;
+ $17 = HEAP32[$m_startDoctypeDeclHandler45 >> 2] | 0;
+ $tobool46 = ($17 | 0) == 0;
+ if ($tobool46) {
+ label = 27;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $isPublicId = $enc_addr_0 + 52 | 0;
+ $18 = HEAP32[$isPublicId >> 2] | 0;
+ $19 = HEAP32[$next_addr >> 2] | 0;
+ $call48 = FUNCTION_TABLE_iiiii[$18 & 1023]($enc_addr_0, $s_addr_0, $19, $eventPP_0_ph) | 0;
+ $tobool49 = ($call48 | 0) == 0;
+ if ($tobool49) {
+ $retval_0_ph = 32;
+ label = 207;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $minBytesPerChar = $enc_addr_0 + 64 | 0;
+ $20 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr = $s_addr_0 + $20 | 0;
+ $21 = HEAP32[$next_addr >> 2] | 0;
+ $idx_neg = -$20 | 0;
+ $add_ptr54 = $21 + $idx_neg | 0;
+ $call55 = _poolStoreString($m_tempPool52, $enc_addr_0, $add_ptr, $add_ptr54) | 0;
+ $tobool56 = ($call55 | 0) == 0;
+ if ($tobool56) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ _normalizePublicId($call55);
+ $22 = HEAP32[$ptr60 >> 2] | 0;
+ HEAP32[$start62 >> 2] = $22;
+ HEAP32[$m_doctypePubid63 >> 2] = $call55;
+ $handleDefault_1 = 0;
+ label = 28;
+ break;
+ case 27:
+ $isPublicId66 = $enc_addr_0 + 52 | 0;
+ $23 = HEAP32[$isPublicId66 >> 2] | 0;
+ $24 = HEAP32[$next_addr >> 2] | 0;
+ $call67 = FUNCTION_TABLE_iiiii[$23 & 1023]($enc_addr_0, $s_addr_0, $24, $eventPP_0_ph) | 0;
+ $tobool68 = ($call67 | 0) == 0;
+ if ($tobool68) {
+ $retval_0_ph = 32;
+ label = 207;
+ break;
+ } else {
+ $handleDefault_1 = 1;
+ label = 28;
+ break;
+ }
+ case 28:
+ $25 = HEAP8[$keepProcessing] | 0;
+ $tobool72 = $25 << 24 >> 24 == 0;
+ if ($tobool72) {
+ $handleDefault_10 = $handleDefault_1;
+ label = 201;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $26 = HEAP32[$m_declEntity >> 2] | 0;
+ $tobool74 = ($26 | 0) == 0;
+ if ($tobool74) {
+ $handleDefault_10 = $handleDefault_1;
+ label = 201;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $minBytesPerChar76 = $enc_addr_0 + 64 | 0;
+ $27 = HEAP32[$minBytesPerChar76 >> 2] | 0;
+ $add_ptr77 = $s_addr_0 + $27 | 0;
+ $28 = HEAP32[$next_addr >> 2] | 0;
+ $idx_neg79 = -$27 | 0;
+ $add_ptr80 = $28 + $idx_neg79 | 0;
+ $call81 = _poolStoreString($pool, $enc_addr_0, $add_ptr77, $add_ptr80) | 0;
+ $tobool82 = ($call81 | 0) == 0;
+ if ($tobool82) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ _normalizePublicId($call81);
+ $29 = HEAP32[$m_declEntity >> 2] | 0;
+ $publicId = $29 + 24 | 0;
+ HEAP32[$publicId >> 2] = $call81;
+ $30 = HEAP32[$ptr87 >> 2] | 0;
+ HEAP32[$start89 >> 2] = $30;
+ $31 = HEAP32[$m_entityDeclHandler >> 2] | 0;
+ $tobool90 = ($31 | 0) == 0;
+ $handleDefault_1_ = $tobool90 ? $handleDefault_1 : 0;
+ $handleDefault_10 = $handleDefault_1_;
+ label = 201;
+ break;
+ case 32:
+ $32 = HEAP32[$m_doctypeName95 >> 2] | 0;
+ $tobool96 = ($32 | 0) == 0;
+ if ($tobool96) {
+ $handleDefault_2 = 1;
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $33 = HEAP32[$m_startDoctypeDeclHandler98 >> 2] | 0;
+ $34 = HEAP32[$m_handlerArg99 >> 2] | 0;
+ $35 = HEAP32[$m_doctypeSysid101 >> 2] | 0;
+ $36 = HEAP32[$m_doctypePubid102 >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$33 & 1023]($34, $32, $35, $36, 0);
+ _poolClear($m_tempPool103);
+ $handleDefault_2 = 0;
+ label = 34;
+ break;
+ case 34:
+ $37 = HEAP32[$m_endDoctypeDeclHandler >> 2] | 0;
+ $tobool105 = ($37 | 0) == 0;
+ if ($tobool105) {
+ $handleDefault_10 = $handleDefault_2;
+ label = 201;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $38 = HEAP32[$m_handlerArg108 >> 2] | 0;
+ FUNCTION_TABLE_vi[$37 & 1023]($38);
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 36:
+ $m_processor = $parser + 264 | 0;
+ HEAP32[$m_processor >> 2] = 122;
+ $call111 = _contentProcessor($parser, $s_addr_0, $end, $nextPtr) | 0;
+ $retval_0 = $call111;
+ label = 208;
+ break;
+ case 37:
+ $39 = HEAP32[$next_addr >> 2] | 0;
+ $call113 = _getElementType($parser, $enc_addr_0, $s_addr_0, $39) | 0;
+ HEAP32[$m_declElementType >> 2] = $call113;
+ $tobool115 = ($call113 | 0) == 0;
+ if ($tobool115) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 38:
+ $40 = HEAP32[$next_addr >> 2] | 0;
+ $call119 = _getAttributeId($parser, $enc_addr_0, $s_addr_0, $40) | 0;
+ HEAP32[$m_declAttributeId >> 2] = $call119;
+ $tobool121 = ($call119 | 0) == 0;
+ if ($tobool121) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ HEAP8[$m_declAttributeIsCdata] = 0;
+ HEAP32[$m_declAttributeType >> 2] = 0;
+ HEAP8[$m_declAttributeIsId] = 0;
+ label = 48;
+ break;
+ case 40:
+ HEAP8[$m_declAttributeIsCdata125] = 1;
+ HEAP32[$m_declAttributeType126 >> 2] = 20616;
+ label = 48;
+ break;
+ case 41:
+ HEAP8[$m_declAttributeIsId128] = 1;
+ HEAP32[$m_declAttributeType129 >> 2] = 20584;
+ label = 48;
+ break;
+ case 42:
+ HEAP32[$m_declAttributeType131 >> 2] = 20576;
+ label = 48;
+ break;
+ case 43:
+ HEAP32[$m_declAttributeType133 >> 2] = 20568;
+ label = 48;
+ break;
+ case 44:
+ HEAP32[$m_declAttributeType135 >> 2] = 20592;
+ label = 48;
+ break;
+ case 45:
+ HEAP32[$m_declAttributeType137 >> 2] = 20600;
+ label = 48;
+ break;
+ case 46:
+ HEAP32[$m_declAttributeType139 >> 2] = 20560;
+ label = 48;
+ break;
+ case 47:
+ HEAP32[$m_declAttributeType141 >> 2] = 20544;
+ label = 48;
+ break;
+ case 48:
+ $41 = HEAP8[$keepProcessing142] | 0;
+ $tobool144 = $41 << 24 >> 24 == 0;
+ if ($tobool144) {
+ label = 202;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $42 = HEAP32[$m_attlistDeclHandler >> 2] | 0;
+ $tobool146 = ($42 | 0) == 0;
+ $_ = $tobool146 & 1;
+ $handleDefault_10 = $_;
+ label = 201;
+ break;
+ case 50:
+ $43 = HEAP8[$keepProcessing150] | 0;
+ $tobool152 = $43 << 24 >> 24 == 0;
+ if ($tobool152) {
+ label = 202;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $44 = HEAP32[$m_attlistDeclHandler154 >> 2] | 0;
+ $tobool155 = ($44 | 0) == 0;
+ if ($tobool155) {
+ label = 202;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $45 = HEAP32[$m_declAttributeType157 >> 2] | 0;
+ $tobool158 = ($45 | 0) == 0;
+ if ($tobool158) {
+ label = 53;
+ break;
+ } else {
+ $prefix_0 = 20536;
+ label = 54;
+ break;
+ }
+ case 53:
+ $cmp161 = ($call | 0) == 32;
+ $cond = $cmp161 ? 20512 : 20528;
+ $prefix_0 = $cond;
+ label = 54;
+ break;
+ case 54:
+ $call165 = _poolAppendString($m_tempPool164, $prefix_0) | 0;
+ $tobool166 = ($call165 | 0) == 0;
+ if ($tobool166) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ $46 = HEAP32[$next_addr >> 2] | 0;
+ $call170 = _poolAppend($m_tempPool164, $enc_addr_0, $s_addr_0, $46) | 0;
+ $tobool171 = ($call170 | 0) == 0;
+ if ($tobool171) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 56:
+ $47 = HEAP32[$start175 >> 2] | 0;
+ HEAP32[$m_declAttributeType157 >> 2] = $47;
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 57:
+ $48 = HEAP8[$keepProcessing179] | 0;
+ $tobool180 = $48 << 24 >> 24 == 0;
+ if ($tobool180) {
+ label = 202;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $49 = HEAP32[$m_declElementType182 >> 2] | 0;
+ $50 = HEAP32[$m_declAttributeId183 >> 2] | 0;
+ $51 = HEAP8[$m_declAttributeIsCdata184] | 0;
+ $52 = HEAP8[$m_declAttributeIsId185] | 0;
+ $call186 = _defineAttribute($49, $50, $51, $52, 0, $parser) | 0;
+ $tobool187 = ($call186 | 0) == 0;
+ if ($tobool187) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ $53 = HEAP32[$m_attlistDeclHandler190 >> 2] | 0;
+ $tobool191 = ($53 | 0) == 0;
+ if ($tobool191) {
+ label = 202;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $54 = HEAP32[$m_declAttributeType193 >> 2] | 0;
+ $tobool194 = ($54 | 0) == 0;
+ if ($tobool194) {
+ label = 202;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 61:
+ $55 = HEAP8[$54] | 0;
+ if (($55 << 24 >> 24 | 0) == 78) {
+ label = 62;
+ break;
+ } else if (($55 << 24 >> 24 | 0) == 40) {
+ label = 63;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 62:
+ $arrayidx = $54 + 1 | 0;
+ $56 = HEAP8[$arrayidx] | 0;
+ $cmp207 = $56 << 24 >> 24 == 79;
+ if ($cmp207) {
+ label = 63;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 63:
+ $57 = HEAP32[$ptr211 >> 2] | 0;
+ $58 = HEAP32[$end213 >> 2] | 0;
+ $cmp214 = ($57 | 0) == ($58 | 0);
+ if ($cmp214) {
+ label = 64;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 64:
+ $call218 = _poolGrow($m_tempPool210) | 0;
+ $tobool219 = $call218 << 24 >> 24 == 0;
+ if ($tobool219) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $59 = HEAP32[$ptr211 >> 2] | 0;
+ $incdec_ptr = $59 + 1 | 0;
+ HEAP32[$ptr211 >> 2] = $incdec_ptr;
+ HEAP8[$59] = 41;
+ $60 = HEAP32[$ptr211 >> 2] | 0;
+ $61 = HEAP32[$end213 >> 2] | 0;
+ $cmp227 = ($60 | 0) == ($61 | 0);
+ if ($cmp227) {
+ label = 66;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 66:
+ $call231 = _poolGrow($m_tempPool210) | 0;
+ $tobool232 = $call231 << 24 >> 24 == 0;
+ if ($tobool232) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 67:
+ $62 = HEAP32[$ptr211 >> 2] | 0;
+ $incdec_ptr237 = $62 + 1 | 0;
+ HEAP32[$ptr211 >> 2] = $incdec_ptr237;
+ HEAP8[$62] = 0;
+ $63 = HEAP32[$start241 >> 2] | 0;
+ HEAP32[$m_declAttributeType193 >> 2] = $63;
+ $64 = HEAP32[$ptr211 >> 2] | 0;
+ HEAP32[$start241 >> 2] = $64;
+ label = 68;
+ break;
+ case 68:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $65 = HEAP32[$m_attlistDeclHandler190 >> 2] | 0;
+ $66 = HEAP32[$m_handlerArg249 >> 2] | 0;
+ $67 = HEAP32[$m_declElementType182 >> 2] | 0;
+ $name = $67 | 0;
+ $68 = HEAP32[$name >> 2] | 0;
+ $69 = HEAP32[$m_declAttributeId183 >> 2] | 0;
+ $name252 = $69 | 0;
+ $70 = HEAP32[$name252 >> 2] | 0;
+ $71 = HEAP32[$m_declAttributeType193 >> 2] | 0;
+ $cmp254 = ($call | 0) == 36;
+ $conv255 = $cmp254 & 1;
+ FUNCTION_TABLE_viiiiii[$65 & 1023]($66, $68, $70, $71, 0, $conv255);
+ _poolClear($m_tempPool256);
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 69:
+ $72 = HEAP8[$keepProcessing260] | 0;
+ $tobool261 = $72 << 24 >> 24 == 0;
+ if ($tobool261) {
+ label = 202;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $73 = HEAP8[$m_declAttributeIsCdata264] | 0;
+ $minBytesPerChar265 = $enc_addr_0 + 64 | 0;
+ $74 = HEAP32[$minBytesPerChar265 >> 2] | 0;
+ $add_ptr266 = $s_addr_0 + $74 | 0;
+ $75 = HEAP32[$next_addr >> 2] | 0;
+ $idx_neg268 = -$74 | 0;
+ $add_ptr269 = $75 + $idx_neg268 | 0;
+ $call271 = _storeAttributeValue($parser, $enc_addr_0, $73, $add_ptr266, $add_ptr269, $pool270) | 0;
+ $tobool272 = ($call271 | 0) == 0;
+ if ($tobool272) {
+ label = 71;
+ break;
+ } else {
+ $retval_0_ph = $call271;
+ label = 207;
+ break;
+ }
+ case 71:
+ $76 = HEAP32[$start276 >> 2] | 0;
+ $77 = HEAP32[$ptr278 >> 2] | 0;
+ HEAP32[$start276 >> 2] = $77;
+ $78 = HEAP32[$m_declElementType281 >> 2] | 0;
+ $79 = HEAP32[$m_declAttributeId282 >> 2] | 0;
+ $80 = HEAP8[$m_declAttributeIsCdata264] | 0;
+ $call284 = _defineAttribute($78, $79, $80, 0, $76, $parser) | 0;
+ $tobool285 = ($call284 | 0) == 0;
+ if ($tobool285) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 72:
+ $81 = HEAP32[$m_attlistDeclHandler288 >> 2] | 0;
+ $tobool289 = ($81 | 0) == 0;
+ if ($tobool289) {
+ label = 202;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $82 = HEAP32[$m_declAttributeType291 >> 2] | 0;
+ $tobool292 = ($82 | 0) == 0;
+ if ($tobool292) {
+ label = 202;
+ break;
+ } else {
+ label = 74;
+ break;
+ }
+ case 74:
+ $83 = HEAP8[$82] | 0;
+ if (($83 << 24 >> 24 | 0) == 78) {
+ label = 75;
+ break;
+ } else if (($83 << 24 >> 24 | 0) == 40) {
+ label = 76;
+ break;
+ } else {
+ label = 81;
+ break;
+ }
+ case 75:
+ $arrayidx305 = $82 + 1 | 0;
+ $84 = HEAP8[$arrayidx305] | 0;
+ $cmp307 = $84 << 24 >> 24 == 79;
+ if ($cmp307) {
+ label = 76;
+ break;
+ } else {
+ label = 81;
+ break;
+ }
+ case 76:
+ $85 = HEAP32[$ptr311 >> 2] | 0;
+ $86 = HEAP32[$end313 >> 2] | 0;
+ $cmp314 = ($85 | 0) == ($86 | 0);
+ if ($cmp314) {
+ label = 77;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 77:
+ $call318 = _poolGrow($m_tempPool310) | 0;
+ $tobool319 = $call318 << 24 >> 24 == 0;
+ if ($tobool319) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $87 = HEAP32[$ptr311 >> 2] | 0;
+ $incdec_ptr324 = $87 + 1 | 0;
+ HEAP32[$ptr311 >> 2] = $incdec_ptr324;
+ HEAP8[$87] = 41;
+ $88 = HEAP32[$ptr311 >> 2] | 0;
+ $89 = HEAP32[$end313 >> 2] | 0;
+ $cmp330 = ($88 | 0) == ($89 | 0);
+ if ($cmp330) {
+ label = 79;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 79:
+ $call334 = _poolGrow($m_tempPool310) | 0;
+ $tobool335 = $call334 << 24 >> 24 == 0;
+ if ($tobool335) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 80:
+ $90 = HEAP32[$ptr311 >> 2] | 0;
+ $incdec_ptr340 = $90 + 1 | 0;
+ HEAP32[$ptr311 >> 2] = $incdec_ptr340;
+ HEAP8[$90] = 0;
+ $91 = HEAP32[$start344 >> 2] | 0;
+ HEAP32[$m_declAttributeType291 >> 2] = $91;
+ $92 = HEAP32[$ptr311 >> 2] | 0;
+ HEAP32[$start344 >> 2] = $92;
+ label = 81;
+ break;
+ case 81:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $93 = HEAP32[$m_attlistDeclHandler288 >> 2] | 0;
+ $94 = HEAP32[$m_handlerArg352 >> 2] | 0;
+ $95 = HEAP32[$m_declElementType281 >> 2] | 0;
+ $name354 = $95 | 0;
+ $96 = HEAP32[$name354 >> 2] | 0;
+ $97 = HEAP32[$m_declAttributeId282 >> 2] | 0;
+ $name356 = $97 | 0;
+ $98 = HEAP32[$name356 >> 2] | 0;
+ $99 = HEAP32[$m_declAttributeType291 >> 2] | 0;
+ $cmp358 = ($call | 0) == 38;
+ $conv359 = $cmp358 & 1;
+ FUNCTION_TABLE_viiiiii[$93 & 1023]($94, $96, $98, $99, $76, $conv359);
+ _poolClear($m_tempPool360);
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 82:
+ $100 = HEAP8[$keepProcessing364] | 0;
+ $tobool365 = $100 << 24 >> 24 == 0;
+ if ($tobool365) {
+ label = 202;
+ break;
+ } else {
+ label = 83;
+ break;
+ }
+ case 83:
+ $minBytesPerChar368 = $enc_addr_0 + 64 | 0;
+ $101 = HEAP32[$minBytesPerChar368 >> 2] | 0;
+ $add_ptr369 = $s_addr_0 + $101 | 0;
+ $102 = HEAP32[$next_addr >> 2] | 0;
+ $idx_neg371 = -$101 | 0;
+ $add_ptr372 = $102 + $idx_neg371 | 0;
+ $call373 = _storeEntityValue($parser, $enc_addr_0, $add_ptr369, $add_ptr372) | 0;
+ $103 = HEAP32[$m_declEntity374 >> 2] | 0;
+ $tobool375 = ($103 | 0) == 0;
+ $104 = HEAP32[$start377 >> 2] | 0;
+ if ($tobool375) {
+ label = 86;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 84:
+ $textPtr = $103 + 4 | 0;
+ HEAP32[$textPtr >> 2] = $104;
+ $105 = HEAP32[$ptr380 >> 2] | 0;
+ $106 = HEAP32[$start377 >> 2] | 0;
+ $sub_ptr_lhs_cast = $105;
+ $sub_ptr_rhs_cast = $106;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $107 = HEAP32[$m_declEntity374 >> 2] | 0;
+ $textLen = $107 + 8 | 0;
+ HEAP32[$textLen >> 2] = $sub_ptr_sub;
+ $108 = HEAP32[$ptr380 >> 2] | 0;
+ HEAP32[$start377 >> 2] = $108;
+ $109 = HEAP32[$m_entityDeclHandler388 >> 2] | 0;
+ $tobool389 = ($109 | 0) == 0;
+ if ($tobool389) {
+ $handleDefault_3 = 1;
+ label = 87;
+ break;
+ } else {
+ label = 85;
+ break;
+ }
+ case 85:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $110 = HEAP32[$m_entityDeclHandler388 >> 2] | 0;
+ $111 = HEAP32[$m_handlerArg392 >> 2] | 0;
+ $112 = HEAP32[$m_declEntity374 >> 2] | 0;
+ $name394 = $112 | 0;
+ $113 = HEAP32[$name394 >> 2] | 0;
+ $is_param = $112 + 33 | 0;
+ $114 = HEAP8[$is_param] | 0;
+ $conv396 = $114 & 255;
+ $textPtr398 = $112 + 4 | 0;
+ $115 = HEAP32[$textPtr398 >> 2] | 0;
+ $textLen400 = $112 + 8 | 0;
+ $116 = HEAP32[$textLen400 >> 2] | 0;
+ $117 = HEAP32[$m_curBase >> 2] | 0;
+ FUNCTION_TABLE_viiiiiiiii[$110 & 1023]($111, $113, $conv396, $115, $116, $117, 0, 0, 0);
+ $handleDefault_3 = 0;
+ label = 87;
+ break;
+ case 86:
+ HEAP32[$ptr406 >> 2] = $104;
+ $handleDefault_3 = 1;
+ label = 87;
+ break;
+ case 87:
+ $cmp408 = ($call373 | 0) == 0;
+ if ($cmp408) {
+ $handleDefault_10 = $handleDefault_3;
+ label = 201;
+ break;
+ } else {
+ $retval_0_ph = $call373;
+ label = 207;
+ break;
+ }
+ case 88:
+ HEAP8[$hasParamEntityRefs414] = 1;
+ $118 = HEAP32[$m_startDoctypeDeclHandler415 >> 2] | 0;
+ $tobool416 = ($118 | 0) == 0;
+ if ($tobool416) {
+ $handleDefault_4 = 1;
+ label = 91;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 89:
+ $minBytesPerChar419 = $enc_addr_0 + 64 | 0;
+ $119 = HEAP32[$minBytesPerChar419 >> 2] | 0;
+ $add_ptr420 = $s_addr_0 + $119 | 0;
+ $120 = HEAP32[$next_addr >> 2] | 0;
+ $idx_neg422 = -$119 | 0;
+ $add_ptr423 = $120 + $idx_neg422 | 0;
+ $call424 = _poolStoreString($m_tempPool418, $enc_addr_0, $add_ptr420, $add_ptr423) | 0;
+ HEAP32[$m_doctypeSysid425 >> 2] = $call424;
+ $cmp427 = ($call424 | 0) == 0;
+ if ($cmp427) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 90;
+ break;
+ }
+ case 90:
+ $121 = HEAP32[$ptr432 >> 2] | 0;
+ HEAP32[$start434 >> 2] = $121;
+ $handleDefault_4 = 0;
+ label = 91;
+ break;
+ case 91:
+ $122 = HEAP8[$standalone] | 0;
+ $tobool436 = $122 << 24 >> 24 == 0;
+ if ($tobool436) {
+ label = 92;
+ break;
+ } else {
+ $handleDefault_10 = $handleDefault_4;
+ label = 201;
+ break;
+ }
+ case 92:
+ $123 = HEAP32[$m_notStandaloneHandler >> 2] | 0;
+ $tobool438 = ($123 | 0) == 0;
+ if ($tobool438) {
+ $handleDefault_10 = $handleDefault_4;
+ label = 201;
+ break;
+ } else {
+ label = 93;
+ break;
+ }
+ case 93:
+ $124 = HEAP32[$m_handlerArg441 >> 2] | 0;
+ $call442 = FUNCTION_TABLE_ii[$123 & 1023]($124) | 0;
+ $tobool443 = ($call442 | 0) == 0;
+ if ($tobool443) {
+ $retval_0_ph = 22;
+ label = 207;
+ break;
+ } else {
+ $handleDefault_10 = $handleDefault_4;
+ label = 201;
+ break;
+ }
+ case 94:
+ $125 = HEAP8[$keepProcessing447] | 0;
+ $tobool449 = $125 << 24 >> 24 == 0;
+ if ($tobool449) {
+ label = 202;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 95:
+ $126 = HEAP32[$m_declEntity451 >> 2] | 0;
+ $tobool452 = ($126 | 0) == 0;
+ if ($tobool452) {
+ label = 202;
+ break;
+ } else {
+ label = 96;
+ break;
+ }
+ case 96:
+ $minBytesPerChar455 = $enc_addr_0 + 64 | 0;
+ $127 = HEAP32[$minBytesPerChar455 >> 2] | 0;
+ $add_ptr456 = $s_addr_0 + $127 | 0;
+ $128 = HEAP32[$next_addr >> 2] | 0;
+ $idx_neg458 = -$127 | 0;
+ $add_ptr459 = $128 + $idx_neg458 | 0;
+ $call460 = _poolStoreString($pool454, $enc_addr_0, $add_ptr456, $add_ptr459) | 0;
+ $129 = HEAP32[$m_declEntity451 >> 2] | 0;
+ $systemId = $129 + 16 | 0;
+ HEAP32[$systemId >> 2] = $call460;
+ $130 = HEAP32[$m_declEntity451 >> 2] | 0;
+ $systemId463 = $130 + 16 | 0;
+ $131 = HEAP32[$systemId463 >> 2] | 0;
+ $tobool464 = ($131 | 0) == 0;
+ if ($tobool464) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 97:
+ $132 = HEAP32[$m_curBase467 >> 2] | 0;
+ $base = $130 + 20 | 0;
+ HEAP32[$base >> 2] = $132;
+ $133 = HEAP32[$ptr470 >> 2] | 0;
+ HEAP32[$start472 >> 2] = $133;
+ $134 = HEAP32[$m_entityDeclHandler473 >> 2] | 0;
+ $tobool474 = ($134 | 0) == 0;
+ $_515 = $tobool474 & 1;
+ $handleDefault_10 = $_515;
+ label = 201;
+ break;
+ case 98:
+ $135 = HEAP8[$keepProcessing479] | 0;
+ $tobool481 = $135 << 24 >> 24 == 0;
+ if ($tobool481) {
+ label = 202;
+ break;
+ } else {
+ label = 99;
+ break;
+ }
+ case 99:
+ $136 = HEAP32[$m_declEntity483 >> 2] | 0;
+ $tobool484 = ($136 | 0) == 0;
+ if ($tobool484) {
+ label = 202;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 100:
+ $137 = HEAP32[$m_entityDeclHandler486 >> 2] | 0;
+ $tobool487 = ($137 | 0) == 0;
+ if ($tobool487) {
+ label = 202;
+ break;
+ } else {
+ label = 101;
+ break;
+ }
+ case 101:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $138 = HEAP32[$m_entityDeclHandler486 >> 2] | 0;
+ $139 = HEAP32[$m_handlerArg490 >> 2] | 0;
+ $140 = HEAP32[$m_declEntity483 >> 2] | 0;
+ $name492 = $140 | 0;
+ $141 = HEAP32[$name492 >> 2] | 0;
+ $is_param494 = $140 + 33 | 0;
+ $142 = HEAP8[$is_param494] | 0;
+ $conv495 = $142 & 255;
+ $base497 = $140 + 20 | 0;
+ $143 = HEAP32[$base497 >> 2] | 0;
+ $systemId499 = $140 + 16 | 0;
+ $144 = HEAP32[$systemId499 >> 2] | 0;
+ $publicId501 = $140 + 24 | 0;
+ $145 = HEAP32[$publicId501 >> 2] | 0;
+ FUNCTION_TABLE_viiiiiiiii[$138 & 1023]($139, $141, $conv495, 0, 0, $143, $144, $145, 0);
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 102:
+ $146 = HEAP8[$keepProcessing504] | 0;
+ $tobool506 = $146 << 24 >> 24 == 0;
+ if ($tobool506) {
+ label = 202;
+ break;
+ } else {
+ label = 103;
+ break;
+ }
+ case 103:
+ $147 = HEAP32[$m_declEntity508 >> 2] | 0;
+ $tobool509 = ($147 | 0) == 0;
+ if ($tobool509) {
+ label = 202;
+ break;
+ } else {
+ label = 104;
+ break;
+ }
+ case 104:
+ $148 = HEAP32[$next_addr >> 2] | 0;
+ $call512 = _poolStoreString($pool511, $enc_addr_0, $s_addr_0, $148) | 0;
+ $149 = HEAP32[$m_declEntity508 >> 2] | 0;
+ $notation = $149 + 28 | 0;
+ HEAP32[$notation >> 2] = $call512;
+ $150 = HEAP32[$m_declEntity508 >> 2] | 0;
+ $notation515 = $150 + 28 | 0;
+ $151 = HEAP32[$notation515 >> 2] | 0;
+ $tobool516 = ($151 | 0) == 0;
+ if ($tobool516) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 105;
+ break;
+ }
+ case 105:
+ $152 = HEAP32[$ptr520 >> 2] | 0;
+ HEAP32[$start522 >> 2] = $152;
+ $153 = HEAP32[$m_unparsedEntityDeclHandler >> 2] | 0;
+ $tobool523 = ($153 | 0) == 0;
+ if ($tobool523) {
+ label = 107;
+ break;
+ } else {
+ label = 106;
+ break;
+ }
+ case 106:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $154 = HEAP32[$m_unparsedEntityDeclHandler >> 2] | 0;
+ $155 = HEAP32[$m_handlerArg526 >> 2] | 0;
+ $156 = HEAP32[$m_declEntity508 >> 2] | 0;
+ $name528 = $156 | 0;
+ $157 = HEAP32[$name528 >> 2] | 0;
+ $base530 = $156 + 20 | 0;
+ $158 = HEAP32[$base530 >> 2] | 0;
+ $systemId532 = $156 + 16 | 0;
+ $159 = HEAP32[$systemId532 >> 2] | 0;
+ $publicId534 = $156 + 24 | 0;
+ $160 = HEAP32[$publicId534 >> 2] | 0;
+ $notation536 = $156 + 28 | 0;
+ $161 = HEAP32[$notation536 >> 2] | 0;
+ FUNCTION_TABLE_viiiiii[$154 & 1023]($155, $157, $158, $159, $160, $161);
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 107:
+ $162 = HEAP32[$m_entityDeclHandler538 >> 2] | 0;
+ $tobool539 = ($162 | 0) == 0;
+ if ($tobool539) {
+ label = 202;
+ break;
+ } else {
+ label = 108;
+ break;
+ }
+ case 108:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $163 = HEAP32[$m_entityDeclHandler538 >> 2] | 0;
+ $164 = HEAP32[$m_handlerArg542 >> 2] | 0;
+ $165 = HEAP32[$m_declEntity508 >> 2] | 0;
+ $name544 = $165 | 0;
+ $166 = HEAP32[$name544 >> 2] | 0;
+ $base546 = $165 + 20 | 0;
+ $167 = HEAP32[$base546 >> 2] | 0;
+ $systemId548 = $165 + 16 | 0;
+ $168 = HEAP32[$systemId548 >> 2] | 0;
+ $publicId550 = $165 + 24 | 0;
+ $169 = HEAP32[$publicId550 >> 2] | 0;
+ $notation552 = $165 + 28 | 0;
+ $170 = HEAP32[$notation552 >> 2] | 0;
+ FUNCTION_TABLE_viiiiiiiii[$163 & 1023]($164, $166, 0, 0, 0, $167, $168, $169, $170);
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 109:
+ $predefinedEntityName = $enc_addr_0 + 44 | 0;
+ $171 = HEAP32[$predefinedEntityName >> 2] | 0;
+ $172 = HEAP32[$next_addr >> 2] | 0;
+ $call557 = FUNCTION_TABLE_iiii[$171 & 1023]($enc_addr_0, $s_addr_0, $172) | 0;
+ $tobool558 = ($call557 | 0) == 0;
+ if ($tobool558) {
+ label = 111;
+ break;
+ } else {
+ label = 110;
+ break;
+ }
+ case 110:
+ HEAP32[$m_declEntity560 >> 2] = 0;
+ label = 202;
+ break;
+ case 111:
+ $173 = HEAP8[$keepProcessing562] | 0;
+ $tobool563 = $173 << 24 >> 24 == 0;
+ if ($tobool563) {
+ label = 119;
+ break;
+ } else {
+ label = 112;
+ break;
+ }
+ case 112:
+ $174 = HEAP32[$next_addr >> 2] | 0;
+ $call567 = _poolStoreString($pool566, $enc_addr_0, $s_addr_0, $174) | 0;
+ $tobool568 = ($call567 | 0) == 0;
+ if ($tobool568) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 113;
+ break;
+ }
+ case 113:
+ $call571 = _lookup($parser, $generalEntities, $call567, 36) | 0;
+ $175 = $call571;
+ HEAP32[$m_declEntity572 >> 2] = $175;
+ $tobool574 = ($call571 | 0) == 0;
+ if ($tobool574) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 114:
+ $name578 = $call571 | 0;
+ $176 = HEAP32[$name578 >> 2] | 0;
+ $cmp579 = ($176 | 0) == ($call567 | 0);
+ if ($cmp579) {
+ label = 116;
+ break;
+ } else {
+ label = 115;
+ break;
+ }
+ case 115:
+ $177 = HEAP32[$start583 >> 2] | 0;
+ HEAP32[$ptr585 >> 2] = $177;
+ HEAP32[$m_declEntity572 >> 2] = 0;
+ label = 202;
+ break;
+ case 116:
+ $178 = HEAP32[$ptr589 >> 2] | 0;
+ HEAP32[$start591 >> 2] = $178;
+ $179 = HEAP32[$m_declEntity572 >> 2] | 0;
+ $publicId593 = $179 + 24 | 0;
+ HEAP32[$publicId593 >> 2] = 0;
+ $180 = HEAP32[$m_declEntity572 >> 2] | 0;
+ $is_param595 = $180 + 33 | 0;
+ HEAP8[$is_param595] = 0;
+ $181 = HEAP32[$m_parentParser >> 2] | 0;
+ $tobool596 = ($181 | 0) == 0;
+ if ($tobool596) {
+ label = 117;
+ break;
+ } else {
+ $183 = 0;
+ label = 118;
+ break;
+ }
+ case 117:
+ $182 = HEAP32[$m_openInternalEntities597 >> 2] | 0;
+ $phitmp = ($182 | 0) == 0;
+ $phitmp514 = $phitmp & 1;
+ $183 = $phitmp514;
+ label = 118;
+ break;
+ case 118:
+ $184 = HEAP32[$m_declEntity572 >> 2] | 0;
+ $is_internal = $184 + 34 | 0;
+ HEAP8[$is_internal] = $183;
+ $185 = HEAP32[$m_entityDeclHandler601 >> 2] | 0;
+ $tobool602 = ($185 | 0) == 0;
+ $_516 = $tobool602 & 1;
+ $handleDefault_10 = $_516;
+ label = 201;
+ break;
+ case 119:
+ $186 = HEAP32[$start608 >> 2] | 0;
+ HEAP32[$ptr610 >> 2] = $186;
+ HEAP32[$m_declEntity611 >> 2] = 0;
+ label = 202;
+ break;
+ case 120:
+ HEAP32[$m_declEntity614 >> 2] = 0;
+ label = 202;
+ break;
+ case 121:
+ HEAP32[$m_declNotationPublicId >> 2] = 0;
+ HEAP32[$m_declNotationName >> 2] = 0;
+ $187 = HEAP32[$m_notationDeclHandler >> 2] | 0;
+ $tobool616 = ($187 | 0) == 0;
+ if ($tobool616) {
+ label = 202;
+ break;
+ } else {
+ label = 122;
+ break;
+ }
+ case 122:
+ $188 = HEAP32[$next_addr >> 2] | 0;
+ $call619 = _poolStoreString($m_tempPool618, $enc_addr_0, $s_addr_0, $188) | 0;
+ HEAP32[$m_declNotationName >> 2] = $call619;
+ $tobool622 = ($call619 | 0) == 0;
+ if ($tobool622) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 123;
+ break;
+ }
+ case 123:
+ $189 = HEAP32[$ptr626 >> 2] | 0;
+ HEAP32[$start628 >> 2] = $189;
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 124:
+ $isPublicId631 = $enc_addr_0 + 52 | 0;
+ $190 = HEAP32[$isPublicId631 >> 2] | 0;
+ $191 = HEAP32[$next_addr >> 2] | 0;
+ $call632 = FUNCTION_TABLE_iiiii[$190 & 1023]($enc_addr_0, $s_addr_0, $191, $eventPP_0_ph) | 0;
+ $tobool633 = ($call632 | 0) == 0;
+ if ($tobool633) {
+ $retval_0_ph = 32;
+ label = 207;
+ break;
+ } else {
+ label = 125;
+ break;
+ }
+ case 125:
+ $192 = HEAP32[$m_declNotationName636 >> 2] | 0;
+ $tobool637 = ($192 | 0) == 0;
+ if ($tobool637) {
+ label = 202;
+ break;
+ } else {
+ label = 126;
+ break;
+ }
+ case 126:
+ $minBytesPerChar641 = $enc_addr_0 + 64 | 0;
+ $193 = HEAP32[$minBytesPerChar641 >> 2] | 0;
+ $add_ptr642 = $s_addr_0 + $193 | 0;
+ $194 = HEAP32[$next_addr >> 2] | 0;
+ $idx_neg644 = -$193 | 0;
+ $add_ptr645 = $194 + $idx_neg644 | 0;
+ $call646 = _poolStoreString($m_tempPool640, $enc_addr_0, $add_ptr642, $add_ptr645) | 0;
+ $tobool647 = ($call646 | 0) == 0;
+ if ($tobool647) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 127;
+ break;
+ }
+ case 127:
+ _normalizePublicId($call646);
+ HEAP32[$m_declNotationPublicId650 >> 2] = $call646;
+ $195 = HEAP32[$ptr652 >> 2] | 0;
+ HEAP32[$start654 >> 2] = $195;
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 128:
+ $196 = HEAP32[$m_declNotationName657 >> 2] | 0;
+ $tobool658 = ($196 | 0) == 0;
+ if ($tobool658) {
+ $handleDefault_5 = 1;
+ label = 132;
+ break;
+ } else {
+ label = 129;
+ break;
+ }
+ case 129:
+ $197 = HEAP32[$m_notationDeclHandler660 >> 2] | 0;
+ $tobool661 = ($197 | 0) == 0;
+ if ($tobool661) {
+ $handleDefault_5 = 1;
+ label = 132;
+ break;
+ } else {
+ label = 130;
+ break;
+ }
+ case 130:
+ $minBytesPerChar665 = $enc_addr_0 + 64 | 0;
+ $198 = HEAP32[$minBytesPerChar665 >> 2] | 0;
+ $add_ptr666 = $s_addr_0 + $198 | 0;
+ $199 = HEAP32[$next_addr >> 2] | 0;
+ $idx_neg668 = -$198 | 0;
+ $add_ptr669 = $199 + $idx_neg668 | 0;
+ $call670 = _poolStoreString($m_tempPool664, $enc_addr_0, $add_ptr666, $add_ptr669) | 0;
+ $tobool671 = ($call670 | 0) == 0;
+ if ($tobool671) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 131;
+ break;
+ }
+ case 131:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $200 = HEAP32[$m_notationDeclHandler660 >> 2] | 0;
+ $201 = HEAP32[$m_handlerArg675 >> 2] | 0;
+ $202 = HEAP32[$m_declNotationName657 >> 2] | 0;
+ $203 = HEAP32[$m_curBase677 >> 2] | 0;
+ $204 = HEAP32[$m_declNotationPublicId678 >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$200 & 1023]($201, $202, $203, $call670, $204);
+ $handleDefault_5 = 0;
+ label = 132;
+ break;
+ case 132:
+ _poolClear($m_tempPool680);
+ $handleDefault_10 = $handleDefault_5;
+ label = 201;
+ break;
+ case 133:
+ $205 = HEAP32[$m_declNotationPublicId682 >> 2] | 0;
+ $tobool683 = ($205 | 0) == 0;
+ if ($tobool683) {
+ $handleDefault_6 = 1;
+ label = 136;
+ break;
+ } else {
+ label = 134;
+ break;
+ }
+ case 134:
+ $206 = HEAP32[$m_notationDeclHandler685 >> 2] | 0;
+ $tobool686 = ($206 | 0) == 0;
+ if ($tobool686) {
+ $handleDefault_6 = 1;
+ label = 136;
+ break;
+ } else {
+ label = 135;
+ break;
+ }
+ case 135:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $207 = HEAP32[$m_notationDeclHandler685 >> 2] | 0;
+ $208 = HEAP32[$m_handlerArg689 >> 2] | 0;
+ $209 = HEAP32[$m_declNotationName690 >> 2] | 0;
+ $210 = HEAP32[$m_curBase691 >> 2] | 0;
+ $211 = HEAP32[$m_declNotationPublicId682 >> 2] | 0;
+ FUNCTION_TABLE_viiiii[$207 & 1023]($208, $209, $210, 0, $211);
+ $handleDefault_6 = 0;
+ label = 136;
+ break;
+ case 136:
+ _poolClear($m_tempPool694);
+ $handleDefault_10 = $handleDefault_6;
+ label = 201;
+ break;
+ case 137:
+ if (($tok_addr_1 | 0) == 12) {
+ label = 138;
+ break;
+ } else if (($tok_addr_1 | 0) == 28) {
+ $retval_0 = 10;
+ label = 208;
+ break;
+ } else {
+ label = 139;
+ break;
+ }
+ case 138:
+ $retval_0 = 17;
+ label = 208;
+ break;
+ case 139:
+ $retval_0 = 2;
+ label = 208;
+ break;
+ case 140:
+ $212 = HEAP32[$level >> 2] | 0;
+ $213 = HEAP32[$m_groupSize >> 2] | 0;
+ $cmp701 = $212 >>> 0 < $213 >>> 0;
+ if ($cmp701) {
+ label = 147;
+ break;
+ } else {
+ label = 141;
+ break;
+ }
+ case 141:
+ $tobool705 = ($213 | 0) == 0;
+ if ($tobool705) {
+ label = 146;
+ break;
+ } else {
+ label = 142;
+ break;
+ }
+ case 142:
+ $214 = HEAP32[$realloc_fcn >> 2] | 0;
+ $215 = HEAP32[$m_groupConnector >> 2] | 0;
+ $mul = $213 << 1;
+ HEAP32[$m_groupSize >> 2] = $mul;
+ $call708 = FUNCTION_TABLE_iii[$214 & 1023]($215, $mul) | 0;
+ $cmp709 = ($call708 | 0) == 0;
+ if ($cmp709) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 143;
+ break;
+ }
+ case 143:
+ HEAP32[$m_groupConnector >> 2] = $call708;
+ $216 = HEAP32[$scaffIndex >> 2] | 0;
+ $tobool714 = ($216 | 0) == 0;
+ if ($tobool714) {
+ label = 147;
+ break;
+ } else {
+ label = 144;
+ break;
+ }
+ case 144:
+ $217 = HEAP32[$realloc_fcn >> 2] | 0;
+ $218 = $216;
+ $219 = HEAP32[$m_groupSize >> 2] | 0;
+ $mul721 = $219 << 2;
+ $call722 = FUNCTION_TABLE_iii[$217 & 1023]($218, $mul721) | 0;
+ $cmp723 = ($call722 | 0) == 0;
+ if ($cmp723) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 145;
+ break;
+ }
+ case 145:
+ $220 = $call722;
+ HEAP32[$scaffIndex >> 2] = $220;
+ label = 147;
+ break;
+ case 146:
+ $221 = HEAP32[$malloc_fcn >> 2] | 0;
+ HEAP32[$m_groupSize >> 2] = 32;
+ $call732 = FUNCTION_TABLE_ii[$221 & 1023](32) | 0;
+ HEAP32[$m_groupConnector733 >> 2] = $call732;
+ $tobool735 = ($call732 | 0) == 0;
+ if ($tobool735) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 147;
+ break;
+ }
+ case 147:
+ $222 = HEAP32[$level >> 2] | 0;
+ $223 = HEAP32[$m_groupConnector742 >> 2] | 0;
+ $arrayidx743 = $223 + $222 | 0;
+ HEAP8[$arrayidx743] = 0;
+ $224 = HEAP8[$in_eldecl] | 0;
+ $tobool744 = $224 << 24 >> 24 == 0;
+ if ($tobool744) {
+ label = 202;
+ break;
+ } else {
+ label = 148;
+ break;
+ }
+ case 148:
+ $call746 = _nextScaffoldPart($parser) | 0;
+ $cmp747 = ($call746 | 0) < 0;
+ if ($cmp747) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 149;
+ break;
+ }
+ case 149:
+ $225 = HEAP32[$scaffLevel >> 2] | 0;
+ $226 = HEAP32[$scaffIndex751 >> 2] | 0;
+ $arrayidx752 = $226 + ($225 << 2) | 0;
+ HEAP32[$arrayidx752 >> 2] = $call746;
+ $227 = HEAP32[$scaffLevel >> 2] | 0;
+ $inc = $227 + 1 | 0;
+ HEAP32[$scaffLevel >> 2] = $inc;
+ $228 = HEAP32[$scaffold >> 2] | 0;
+ $type = $228 + ($call746 * 28 & -1) | 0;
+ HEAP32[$type >> 2] = 6;
+ $229 = HEAP32[$m_elementDeclHandler >> 2] | 0;
+ $tobool755 = ($229 | 0) == 0;
+ $_517 = $tobool755 & 1;
+ $handleDefault_10 = $_517;
+ label = 201;
+ break;
+ case 150:
+ $230 = HEAP32[$level761 >> 2] | 0;
+ $231 = HEAP32[$m_groupConnector762 >> 2] | 0;
+ $arrayidx763 = $231 + $230 | 0;
+ $232 = HEAP8[$arrayidx763] | 0;
+ $cmp765 = $232 << 24 >> 24 == 124;
+ if ($cmp765) {
+ $retval_0_ph = 2;
+ label = 207;
+ break;
+ } else {
+ label = 151;
+ break;
+ }
+ case 151:
+ HEAP8[$arrayidx763] = 44;
+ $233 = HEAP8[$in_eldecl773] | 0;
+ $tobool775 = $233 << 24 >> 24 == 0;
+ if ($tobool775) {
+ label = 202;
+ break;
+ } else {
+ label = 152;
+ break;
+ }
+ case 152:
+ $234 = HEAP32[$m_elementDeclHandler777 >> 2] | 0;
+ $tobool778 = ($234 | 0) == 0;
+ $_518 = $tobool778 & 1;
+ $handleDefault_10 = $_518;
+ label = 201;
+ break;
+ case 153:
+ $235 = HEAP32[$level783 >> 2] | 0;
+ $236 = HEAP32[$m_groupConnector784 >> 2] | 0;
+ $arrayidx785 = $236 + $235 | 0;
+ $237 = HEAP8[$arrayidx785] | 0;
+ $cmp787 = $237 << 24 >> 24 == 44;
+ if ($cmp787) {
+ $retval_0_ph = 2;
+ label = 207;
+ break;
+ } else {
+ label = 154;
+ break;
+ }
+ case 154:
+ $238 = HEAP8[$in_eldecl791] | 0;
+ $tobool793 = $238 << 24 >> 24 != 0;
+ $tobool799 = $237 << 24 >> 24 == 0;
+ $or_cond519 = $tobool793 & $tobool799;
+ if ($or_cond519) {
+ label = 155;
+ break;
+ } else {
+ $handleDefault_7 = 1;
+ label = 157;
+ break;
+ }
+ case 155:
+ $239 = HEAP32[$scaffLevel801 >> 2] | 0;
+ $sub802 = $239 - 1 | 0;
+ $240 = HEAP32[$scaffIndex803 >> 2] | 0;
+ $arrayidx804 = $240 + ($sub802 << 2) | 0;
+ $241 = HEAP32[$arrayidx804 >> 2] | 0;
+ $242 = HEAP32[$scaffold805 >> 2] | 0;
+ $type807 = $242 + ($241 * 28 & -1) | 0;
+ $243 = HEAP32[$type807 >> 2] | 0;
+ $cmp808 = ($243 | 0) == 3;
+ if ($cmp808) {
+ $handleDefault_7 = 1;
+ label = 157;
+ break;
+ } else {
+ label = 156;
+ break;
+ }
+ case 156:
+ HEAP32[$type807 >> 2] = 5;
+ $244 = HEAP32[$m_elementDeclHandler818 >> 2] | 0;
+ $tobool819 = ($244 | 0) == 0;
+ $_520 = $tobool819 & 1;
+ $handleDefault_7 = $_520;
+ label = 157;
+ break;
+ case 157:
+ $245 = HEAP32[$level783 >> 2] | 0;
+ $246 = HEAP32[$m_groupConnector784 >> 2] | 0;
+ $arrayidx826 = $246 + $245 | 0;
+ HEAP8[$arrayidx826] = 124;
+ $handleDefault_10 = $handleDefault_7;
+ label = 201;
+ break;
+ case 158:
+ $247 = HEAP8[$standalone828] | 0;
+ $tobool829 = $247 << 24 >> 24 == 0;
+ if ($tobool829) {
+ label = 159;
+ break;
+ } else {
+ label = 202;
+ break;
+ }
+ case 159:
+ $248 = HEAP32[$m_notStandaloneHandler831 >> 2] | 0;
+ $tobool832 = ($248 | 0) == 0;
+ if ($tobool832) {
+ label = 202;
+ break;
+ } else {
+ label = 160;
+ break;
+ }
+ case 160:
+ $249 = HEAP32[$m_handlerArg835 >> 2] | 0;
+ $call836 = FUNCTION_TABLE_ii[$248 & 1023]($249) | 0;
+ $tobool837 = ($call836 | 0) == 0;
+ if ($tobool837) {
+ $retval_0_ph = 22;
+ label = 207;
+ break;
+ } else {
+ label = 202;
+ break;
+ }
+ case 161:
+ $250 = HEAP32[$m_elementDeclHandler841 >> 2] | 0;
+ $tobool842 = ($250 | 0) == 0;
+ if ($tobool842) {
+ label = 202;
+ break;
+ } else {
+ label = 162;
+ break;
+ }
+ case 162:
+ $251 = HEAP32[$next_addr >> 2] | 0;
+ $call844 = _getElementType($parser, $enc_addr_0, $s_addr_0, $251) | 0;
+ HEAP32[$m_declElementType845 >> 2] = $call844;
+ $tobool847 = ($call844 | 0) == 0;
+ if ($tobool847) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 163;
+ break;
+ }
+ case 163:
+ HEAP32[$scaffLevel850 >> 2] = 0;
+ HEAP32[$scaffCount >> 2] = 0;
+ HEAP8[$in_eldecl851] = 1;
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 164:
+ $252 = HEAP8[$in_eldecl854] | 0;
+ $tobool855 = $252 << 24 >> 24 == 0;
+ if ($tobool855) {
+ label = 202;
+ break;
+ } else {
+ label = 165;
+ break;
+ }
+ case 165:
+ $253 = HEAP32[$m_elementDeclHandler857 >> 2] | 0;
+ $tobool858 = ($253 | 0) == 0;
+ if ($tobool858) {
+ $handleDefault_8 = 1;
+ label = 168;
+ break;
+ } else {
+ label = 166;
+ break;
+ }
+ case 166:
+ $254 = HEAP32[$malloc_fcn861 >> 2] | 0;
+ $call862 = FUNCTION_TABLE_ii[$254 & 1023](20) | 0;
+ $tobool863 = ($call862 | 0) == 0;
+ if ($tobool863) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 167;
+ break;
+ }
+ case 167:
+ $255 = $call862;
+ $quant866 = $call862 + 4 | 0;
+ $cmp868 = ($call | 0) == 41;
+ $cond870 = $cmp868 ? 2 : 1;
+ $type871 = $call862;
+ _memset($quant866 | 0, 0, 16);
+ HEAP32[$type871 >> 2] = $cond870;
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $256 = HEAP32[$m_elementDeclHandler857 >> 2] | 0;
+ $257 = HEAP32[$m_handlerArg873 >> 2] | 0;
+ $258 = HEAP32[$m_declElementType874 >> 2] | 0;
+ $name875 = $258 | 0;
+ $259 = HEAP32[$name875 >> 2] | 0;
+ FUNCTION_TABLE_viii[$256 & 1023]($257, $259, $255);
+ $handleDefault_8 = 0;
+ label = 168;
+ break;
+ case 168:
+ HEAP8[$in_eldecl854] = 0;
+ $handleDefault_10 = $handleDefault_8;
+ label = 201;
+ break;
+ case 169:
+ $260 = HEAP8[$in_eldecl880] | 0;
+ $tobool881 = $260 << 24 >> 24 == 0;
+ if ($tobool881) {
+ label = 202;
+ break;
+ } else {
+ label = 170;
+ break;
+ }
+ case 170:
+ $261 = HEAP32[$scaffLevel883 >> 2] | 0;
+ $sub884 = $261 - 1 | 0;
+ $262 = HEAP32[$scaffIndex885 >> 2] | 0;
+ $arrayidx886 = $262 + ($sub884 << 2) | 0;
+ $263 = HEAP32[$arrayidx886 >> 2] | 0;
+ $264 = HEAP32[$scaffold887 >> 2] | 0;
+ $type889 = $264 + ($263 * 28 & -1) | 0;
+ HEAP32[$type889 >> 2] = 3;
+ $265 = HEAP32[$m_elementDeclHandler890 >> 2] | 0;
+ $tobool891 = ($265 | 0) == 0;
+ $_521 = $tobool891 & 1;
+ $handleDefault_10 = $_521;
+ label = 201;
+ break;
+ case 171:
+ $quant_0 = 1;
+ label = 174;
+ break;
+ case 172:
+ $quant_0 = 2;
+ label = 174;
+ break;
+ case 173:
+ $quant_0 = 3;
+ label = 174;
+ break;
+ case 174:
+ $266 = HEAP8[$in_eldecl899] | 0;
+ $tobool900 = $266 << 24 >> 24 == 0;
+ if ($tobool900) {
+ label = 202;
+ break;
+ } else {
+ label = 175;
+ break;
+ }
+ case 175:
+ $cmp903 = ($quant_0 | 0) == 0;
+ $267 = HEAP32[$next_addr >> 2] | 0;
+ if ($cmp903) {
+ $cond910 = $267;
+ label = 177;
+ break;
+ } else {
+ label = 176;
+ break;
+ }
+ case 176:
+ $minBytesPerChar907 = $enc_addr_0 + 64 | 0;
+ $268 = HEAP32[$minBytesPerChar907 >> 2] | 0;
+ $idx_neg908 = -$268 | 0;
+ $add_ptr909 = $267 + $idx_neg908 | 0;
+ $cond910 = $add_ptr909;
+ label = 177;
+ break;
+ case 177:
+ $call912 = _nextScaffoldPart($parser) | 0;
+ $cmp913 = ($call912 | 0) < 0;
+ if ($cmp913) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 178;
+ break;
+ }
+ case 178:
+ $269 = HEAP32[$scaffold917 >> 2] | 0;
+ $type919 = $269 + ($call912 * 28 & -1) | 0;
+ HEAP32[$type919 >> 2] = 4;
+ $270 = HEAP32[$scaffold917 >> 2] | 0;
+ $quant922 = $270 + ($call912 * 28 & -1) + 4 | 0;
+ HEAP32[$quant922 >> 2] = $quant_0;
+ $call923 = _getElementType($parser, $enc_addr_0, $s_addr_0, $cond910) | 0;
+ $tobool924 = ($call923 | 0) == 0;
+ if ($tobool924) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 179;
+ break;
+ }
+ case 179:
+ $name927 = $call923 | 0;
+ $271 = HEAP32[$name927 >> 2] | 0;
+ $272 = HEAP32[$scaffold917 >> 2] | 0;
+ $name930 = $272 + ($call912 * 28 & -1) + 8 | 0;
+ HEAP32[$name930 >> 2] = $271;
+ $nameLen_0 = 0;
+ label = 180;
+ break;
+ case 180:
+ $inc932 = $nameLen_0 + 1 | 0;
+ $arrayidx933 = $271 + $nameLen_0 | 0;
+ $273 = HEAP8[$arrayidx933] | 0;
+ $tobool934 = $273 << 24 >> 24 == 0;
+ if ($tobool934) {
+ label = 181;
+ break;
+ } else {
+ $nameLen_0 = $inc932;
+ label = 180;
+ break;
+ }
+ case 181:
+ $274 = HEAP32[$contentStringLen >> 2] | 0;
+ $add = $274 + $inc932 | 0;
+ HEAP32[$contentStringLen >> 2] = $add;
+ $275 = HEAP32[$m_elementDeclHandler935 >> 2] | 0;
+ $tobool936 = ($275 | 0) == 0;
+ $_522 = $tobool936 & 1;
+ $handleDefault_10 = $_522;
+ label = 201;
+ break;
+ case 182:
+ $quant_1 = 1;
+ label = 185;
+ break;
+ case 183:
+ $quant_1 = 2;
+ label = 185;
+ break;
+ case 184:
+ $quant_1 = 3;
+ label = 185;
+ break;
+ case 185:
+ $276 = HEAP8[$in_eldecl944] | 0;
+ $tobool945 = $276 << 24 >> 24 == 0;
+ if ($tobool945) {
+ label = 202;
+ break;
+ } else {
+ label = 186;
+ break;
+ }
+ case 186:
+ $277 = HEAP32[$m_elementDeclHandler947 >> 2] | 0;
+ $tobool948 = ($277 | 0) == 0;
+ $_523 = $tobool948 & 1;
+ $278 = HEAP32[$scaffLevel951 >> 2] | 0;
+ $dec = $278 - 1 | 0;
+ HEAP32[$scaffLevel951 >> 2] = $dec;
+ $279 = HEAP32[$scaffIndex953 >> 2] | 0;
+ $arrayidx954 = $279 + ($dec << 2) | 0;
+ $280 = HEAP32[$arrayidx954 >> 2] | 0;
+ $281 = HEAP32[$scaffold955 >> 2] | 0;
+ $quant957 = $281 + ($280 * 28 & -1) + 4 | 0;
+ HEAP32[$quant957 >> 2] = $quant_1;
+ $282 = HEAP32[$scaffLevel951 >> 2] | 0;
+ $cmp959 = ($282 | 0) == 0;
+ if ($cmp959) {
+ label = 187;
+ break;
+ } else {
+ $handleDefault_10 = $_523;
+ label = 201;
+ break;
+ }
+ case 187:
+ if ($tobool948) {
+ label = 190;
+ break;
+ } else {
+ label = 188;
+ break;
+ }
+ case 188:
+ $call964 = _build_model($parser) | 0;
+ $tobool965 = ($call964 | 0) == 0;
+ if ($tobool965) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ label = 189;
+ break;
+ }
+ case 189:
+ HEAP32[$eventEndPP_0_ph >> 2] = $s_addr_0;
+ $283 = HEAP32[$m_elementDeclHandler947 >> 2] | 0;
+ $284 = HEAP32[$m_handlerArg969 >> 2] | 0;
+ $285 = HEAP32[$m_declElementType970 >> 2] | 0;
+ $name971 = $285 | 0;
+ $286 = HEAP32[$name971 >> 2] | 0;
+ FUNCTION_TABLE_viii[$283 & 1023]($284, $286, $call964);
+ label = 190;
+ break;
+ case 190:
+ HEAP8[$in_eldecl944] = 0;
+ HEAP32[$contentStringLen974 >> 2] = 0;
+ $handleDefault_10 = $_523;
+ label = 201;
+ break;
+ case 191:
+ $287 = HEAP32[$next_addr >> 2] | 0;
+ $call978 = _reportProcessingInstruction($parser, $enc_addr_0, $s_addr_0, $287) | 0;
+ $tobool979 = ($call978 | 0) == 0;
+ if ($tobool979) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ }
+ case 192:
+ $288 = HEAP32[$next_addr >> 2] | 0;
+ $call983 = _reportComment($parser, $enc_addr_0, $s_addr_0, $288) | 0;
+ $tobool984 = ($call983 | 0) == 0;
+ if ($tobool984) {
+ $retval_0_ph = 1;
+ label = 207;
+ break;
+ } else {
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ }
+ case 193:
+ $not_cond1 = ($tok_addr_1 | 0) != 14;
+ $_524 = $not_cond1 & 1;
+ $handleDefault_10 = $_524;
+ label = 201;
+ break;
+ case 194:
+ $289 = HEAP32[$m_startDoctypeDeclHandler991 >> 2] | 0;
+ $tobool992 = ($289 | 0) == 0;
+ $_525 = $tobool992 & 1;
+ $handleDefault_10 = $_525;
+ label = 201;
+ break;
+ case 195:
+ $290 = HEAP8[$keepProcessing996] | 0;
+ $tobool998 = $290 << 24 >> 24 == 0;
+ if ($tobool998) {
+ label = 202;
+ break;
+ } else {
+ label = 196;
+ break;
+ }
+ case 196:
+ $291 = HEAP32[$m_entityDeclHandler1000 >> 2] | 0;
+ $tobool1001 = ($291 | 0) == 0;
+ $_526 = $tobool1001 & 1;
+ $handleDefault_10 = $_526;
+ label = 201;
+ break;
+ case 197:
+ $292 = HEAP32[$m_notationDeclHandler1005 >> 2] | 0;
+ $tobool1006 = ($292 | 0) == 0;
+ $_527 = $tobool1006 & 1;
+ $handleDefault_10 = $_527;
+ label = 201;
+ break;
+ case 198:
+ $293 = HEAP8[$keepProcessing1010] | 0;
+ $tobool1012 = $293 << 24 >> 24 == 0;
+ if ($tobool1012) {
+ label = 202;
+ break;
+ } else {
+ label = 199;
+ break;
+ }
+ case 199:
+ $294 = HEAP32[$m_attlistDeclHandler1014 >> 2] | 0;
+ $tobool1015 = ($294 | 0) == 0;
+ $_528 = $tobool1015 & 1;
+ $handleDefault_10 = $_528;
+ label = 201;
+ break;
+ case 200:
+ $295 = HEAP32[$m_elementDeclHandler1019 >> 2] | 0;
+ $tobool1020 = ($295 | 0) == 0;
+ $_529 = $tobool1020 & 1;
+ $handleDefault_10 = $_529;
+ label = 201;
+ break;
+ case 201:
+ $tobool1025 = $handleDefault_10 << 24 >> 24 == 0;
+ if ($tobool1025) {
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ } else {
+ label = 202;
+ break;
+ }
+ case 202:
+ $296 = HEAP32[$m_defaultHandler >> 2] | 0;
+ $tobool1027 = ($296 | 0) == 0;
+ if ($tobool1027) {
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ } else {
+ label = 203;
+ break;
+ }
+ case 203:
+ $297 = HEAP32[$next_addr >> 2] | 0;
+ _reportDefault($parser, $enc_addr_0, $s_addr_0, $297);
+ $enc_addr_1532 = $enc_addr_0;
+ label = 204;
+ break;
+ case 204:
+ $298 = HEAP32[$parsing >> 2] | 0;
+ if (($298 | 0) == 3) {
+ label = 205;
+ break;
+ } else if (($298 | 0) == 2) {
+ $retval_0_ph = 35;
+ label = 207;
+ break;
+ } else {
+ label = 206;
+ break;
+ }
+ case 205:
+ $299 = HEAP32[$next_addr >> 2] | 0;
+ HEAP32[$nextPtr >> 2] = $299;
+ $retval_0 = 0;
+ label = 208;
+ break;
+ case 206:
+ $300 = HEAP32[$next_addr >> 2] | 0;
+ $arrayidx1033 = $enc_addr_1532 | 0;
+ $301 = HEAP32[$arrayidx1033 >> 2] | 0;
+ $call1034 = FUNCTION_TABLE_iiiii[$301 & 1023]($enc_addr_1532, $300, $end, $next_addr) | 0;
+ $enc_addr_0 = $enc_addr_1532;
+ $s_addr_0 = $300;
+ $tok_addr_0 = $call1034;
+ label = 6;
+ break;
+ case 207:
+ $retval_0 = $retval_0_ph;
+ label = 208;
+ break;
+ case 208:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _error($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ return 0;
+}
+function _normalizePublicId($publicId) {
+ $publicId = $publicId | 0;
+ var $0 = 0, $tobool14 = 0, $1 = 0, $s_016 = 0, $p_015 = 0, $conv = 0, $cmp = 0, $arrayidx = 0, $2 = 0, $cmp3 = 0, $incdec_ptr = 0, $incdec_ptr5 = 0, $p_1 = 0, $incdec_ptr6 = 0, $3 = 0, $tobool = 0, $cmp7 = 0, $arrayidx10 = 0, $4 = 0, $cmp12 = 0, $arrayidx10_p_0 = 0, $p_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$publicId] | 0;
+ $tobool14 = $0 << 24 >> 24 == 0;
+ if ($tobool14) {
+ $p_2 = $publicId;
+ label = 11;
+ break;
+ } else {
+ $p_015 = $publicId;
+ $s_016 = $publicId;
+ $1 = $0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $1 << 24 >> 24;
+ if (($conv | 0) == 32 | ($conv | 0) == 13 | ($conv | 0) == 10) {
+ label = 4;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $cmp = ($p_015 | 0) == ($publicId | 0);
+ if ($cmp) {
+ $p_1 = $p_015;
+ label = 8;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $arrayidx = $p_015 - 1 | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $cmp3 = $2 << 24 >> 24 == 32;
+ if ($cmp3) {
+ $p_1 = $p_015;
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $incdec_ptr = $p_015 + 1 | 0;
+ HEAP8[$p_015] = 32;
+ $p_1 = $incdec_ptr;
+ label = 8;
+ break;
+ case 7:
+ $incdec_ptr5 = $p_015 + 1 | 0;
+ HEAP8[$p_015] = $1;
+ $p_1 = $incdec_ptr5;
+ label = 8;
+ break;
+ case 8:
+ $incdec_ptr6 = $s_016 + 1 | 0;
+ $3 = HEAP8[$incdec_ptr6] | 0;
+ $tobool = $3 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ $p_015 = $p_1;
+ $s_016 = $incdec_ptr6;
+ $1 = $3;
+ label = 3;
+ break;
+ }
+ case 9:
+ $cmp7 = ($p_1 | 0) == ($publicId | 0);
+ if ($cmp7) {
+ $p_2 = $p_1;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $arrayidx10 = $p_1 - 1 | 0;
+ $4 = HEAP8[$arrayidx10] | 0;
+ $cmp12 = $4 << 24 >> 24 == 32;
+ $arrayidx10_p_0 = $cmp12 ? $arrayidx10 : $p_1;
+ $p_2 = $arrayidx10_p_0;
+ label = 11;
+ break;
+ case 11:
+ HEAP8[$p_2] = 0;
+ return;
+ }
+}
+function _hashTableInit($p, $ms) {
+ $p = $p | 0;
+ $ms = $ms | 0;
+ HEAP8[$p + 4 | 0] = 0;
+ HEAP32[$p + 8 >> 2] = 0;
+ HEAP32[$p + 12 >> 2] = 0;
+ HEAP32[$p >> 2] = 0;
+ HEAP32[$p + 16 >> 2] = $ms;
+ return;
+}
+function _XmlPrologStateInit($state) {
+ $state = $state | 0;
+ HEAP32[$state >> 2] = 434;
+ return;
+}
+function _common($state) {
+ $state = $state | 0;
+ HEAP32[$state >> 2] = 134;
+ return;
+}
+function _getElementType($parser, $enc, $ptr, $end) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ var $m_dtd = 0, $0 = 0, $pool = 0, $call = 0, $tobool = 0, $elementTypes = 0, $call1 = 0, $1 = 0, $tobool2 = 0, $name5 = 0, $2 = 0, $cmp = 0, $start = 0, $3 = 0, $ptr9 = 0, $ptr11 = 0, $4 = 0, $start13 = 0, $call14 = 0, $tobool15 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $pool = $0 + 80 | 0;
+ $call = _poolStoreString($pool, $enc, $ptr, $end) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $elementTypes = $0 + 20 | 0;
+ $call1 = _lookup($parser, $elementTypes, $call, 24) | 0;
+ $1 = $call1;
+ $tobool2 = ($call1 | 0) == 0;
+ if ($tobool2) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $name5 = $call1 | 0;
+ $2 = HEAP32[$name5 >> 2] | 0;
+ $cmp = ($2 | 0) == ($call | 0);
+ if ($cmp) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $start = $0 + 96 | 0;
+ $3 = HEAP32[$start >> 2] | 0;
+ $ptr9 = $0 + 92 | 0;
+ HEAP32[$ptr9 >> 2] = $3;
+ label = 7;
+ break;
+ case 6:
+ $ptr11 = $0 + 92 | 0;
+ $4 = HEAP32[$ptr11 >> 2] | 0;
+ $start13 = $0 + 96 | 0;
+ HEAP32[$start13 >> 2] = $4;
+ $call14 = _setElementTypePrefix($parser, $1) | 0;
+ $tobool15 = ($call14 | 0) == 0;
+ if ($tobool15) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $retval_0 = $1;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _poolAppendString($pool, $s) {
+ $pool = $pool | 0;
+ $s = $s | 0;
+ var $0 = 0, $tobool6 = 0, $ptr = 0, $end = 0, $s_addr_07 = 0, $1 = 0, $2 = 0, $cmp = 0, $call = 0, $tobool1 = 0, $3 = 0, $4 = 0, $incdec_ptr = 0, $incdec_ptr3 = 0, $5 = 0, $tobool = 0, $start = 0, $6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$s] | 0;
+ $tobool6 = $0 << 24 >> 24 == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $ptr = $pool + 12 | 0;
+ $end = $pool + 8 | 0;
+ $s_addr_07 = $s;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP32[$ptr >> 2] | 0;
+ $2 = HEAP32[$end >> 2] | 0;
+ $cmp = ($1 | 0) == ($2 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call = _poolGrow($pool) | 0;
+ $tobool1 = $call << 24 >> 24 == 0;
+ if ($tobool1) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = HEAP8[$s_addr_07] | 0;
+ $4 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $4 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$4] = $3;
+ $incdec_ptr3 = $s_addr_07 + 1 | 0;
+ $5 = HEAP8[$incdec_ptr3] | 0;
+ $tobool = $5 << 24 >> 24 == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ $s_addr_07 = $incdec_ptr3;
+ label = 4;
+ break;
+ }
+ case 7:
+ $start = $pool + 16 | 0;
+ $6 = HEAP32[$start >> 2] | 0;
+ $retval_0 = $6;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _defineAttribute($type, $attId, $isCdata, $isId, $value, $parser) {
+ $type = $type | 0;
+ $attId = $attId | 0;
+ $isCdata = $isCdata | 0;
+ $isId = $isId | 0;
+ $value = $value | 0;
+ $parser = $parser | 0;
+ var $tobool = 0, $tobool1 = 0, $or_cond = 0, $nDefaultAtts = 0, $0 = 0, $defaultAtts = 0, $i_0 = 0, $cmp = 0, $1 = 0, $id = 0, $2 = 0, $cmp3 = 0, $inc = 0, $idAtt = 0, $3 = 0, $tobool8 = 0, $xmlns = 0, $4 = 0, $tobool10 = 0, $nDefaultAtts15 = 0, $5 = 0, $allocDefaultAtts = 0, $6 = 0, $cmp16 = 0, $cmp20 = 0, $malloc_fcn = 0, $7 = 0, $call = 0, $8 = 0, $defaultAtts25 = 0, $tobool27 = 0, $realloc_fcn = 0, $9 = 0, $defaultAtts33 = 0, $10 = 0, $11 = 0, $mul34 = 0, $call35 = 0, $cmp36 = 0, $12 = 0, $mul31 = 0, $defaultAtts44 = 0, $13 = 0, $14 = 0, $id46 = 0, $value47 = 0, $isCdata48 = 0, $tobool49 = 0, $maybeTokenized = 0, $15 = 0, $add = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tobool = ($value | 0) == 0;
+ $tobool1 = $isId << 24 >> 24 == 0;
+ $or_cond = $tobool & $tobool1;
+ if ($or_cond) {
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $nDefaultAtts = $type + 12 | 0;
+ $0 = HEAP32[$nDefaultAtts >> 2] | 0;
+ $defaultAtts = $type + 20 | 0;
+ $i_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ $cmp = ($i_0 | 0) < ($0 | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $1 = HEAP32[$defaultAtts >> 2] | 0;
+ $id = $1 + ($i_0 * 12 & -1) | 0;
+ $2 = HEAP32[$id >> 2] | 0;
+ $cmp3 = ($2 | 0) == ($attId | 0);
+ $inc = $i_0 + 1 | 0;
+ if ($cmp3) {
+ $retval_0 = 1;
+ label = 18;
+ break;
+ } else {
+ $i_0 = $inc;
+ label = 4;
+ break;
+ }
+ case 6:
+ if ($tobool1) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $idAtt = $type + 8 | 0;
+ $3 = HEAP32[$idAtt >> 2] | 0;
+ $tobool8 = ($3 | 0) == 0;
+ if ($tobool8) {
+ label = 8;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 8:
+ $xmlns = $attId + 9 | 0;
+ $4 = HEAP8[$xmlns] | 0;
+ $tobool10 = $4 << 24 >> 24 == 0;
+ if ($tobool10) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ HEAP32[$idAtt >> 2] = $attId;
+ label = 10;
+ break;
+ case 10:
+ $nDefaultAtts15 = $type + 12 | 0;
+ $5 = HEAP32[$nDefaultAtts15 >> 2] | 0;
+ $allocDefaultAtts = $type + 16 | 0;
+ $6 = HEAP32[$allocDefaultAtts >> 2] | 0;
+ $cmp16 = ($5 | 0) == ($6 | 0);
+ if ($cmp16) {
+ label = 11;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 11:
+ $cmp20 = ($6 | 0) == 0;
+ if ($cmp20) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ HEAP32[$allocDefaultAtts >> 2] = 8;
+ $malloc_fcn = $parser + 12 | 0;
+ $7 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call = FUNCTION_TABLE_ii[$7 & 1023](96) | 0;
+ $8 = $call;
+ $defaultAtts25 = $type + 20 | 0;
+ HEAP32[$defaultAtts25 >> 2] = $8;
+ $tobool27 = ($call | 0) == 0;
+ if ($tobool27) {
+ $retval_0 = 0;
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $realloc_fcn = $parser + 16 | 0;
+ $9 = HEAP32[$realloc_fcn >> 2] | 0;
+ $defaultAtts33 = $type + 20 | 0;
+ $10 = HEAP32[$defaultAtts33 >> 2] | 0;
+ $11 = $10;
+ $mul34 = $6 * 24 & -1;
+ $call35 = FUNCTION_TABLE_iii[$9 & 1023]($11, $mul34) | 0;
+ $cmp36 = ($call35 | 0) == 0;
+ if ($cmp36) {
+ $retval_0 = 0;
+ label = 18;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $12 = $call35;
+ $mul31 = $6 << 1;
+ HEAP32[$allocDefaultAtts >> 2] = $mul31;
+ HEAP32[$defaultAtts33 >> 2] = $12;
+ label = 15;
+ break;
+ case 15:
+ $defaultAtts44 = $type + 20 | 0;
+ $13 = HEAP32[$defaultAtts44 >> 2] | 0;
+ $14 = HEAP32[$nDefaultAtts15 >> 2] | 0;
+ $id46 = $13 + ($14 * 12 & -1) | 0;
+ HEAP32[$id46 >> 2] = $attId;
+ $value47 = $13 + ($14 * 12 & -1) + 8 | 0;
+ HEAP32[$value47 >> 2] = $value;
+ $isCdata48 = $13 + ($14 * 12 & -1) + 4 | 0;
+ HEAP8[$isCdata48] = $isCdata;
+ $tobool49 = $isCdata << 24 >> 24 == 0;
+ if ($tobool49) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $maybeTokenized = $attId + 8 | 0;
+ HEAP8[$maybeTokenized] = 1;
+ label = 17;
+ break;
+ case 17:
+ $15 = HEAP32[$nDefaultAtts15 >> 2] | 0;
+ $add = $15 + 1 | 0;
+ HEAP32[$nDefaultAtts15 >> 2] = $add;
+ $retval_0 = 1;
+ label = 18;
+ break;
+ case 18:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _storeEntityValue($parser, $enc, $entityTextPtr, $entityTextEnd) {
+ $parser = $parser | 0;
+ $enc = $enc | 0;
+ $entityTextPtr = $entityTextPtr | 0;
+ $entityTextEnd = $entityTextEnd | 0;
+ var $next = 0, $buf = 0, $m_dtd = 0, $0 = 0, $entityValuePool = 0, $blocks = 0, $1 = 0, $tobool = 0, $call = 0, $tobool1 = 0, $arrayidx = 0, $minBytesPerChar = 0, $end = 0, $ptr = 0, $charRefNumber = 0, $arraydecay = 0, $end38 = 0, $ptr39 = 0, $entityTextPtr_addr_0 = 0, $2 = 0, $call4 = 0, $m_eventPtr = 0, $3 = 0, $call7 = 0, $tobool8 = 0, $4 = 0, $add_ptr = 0, $5 = 0, $6 = 0, $cmp = 0, $call13 = 0, $tobool14 = 0, $7 = 0, $incdec_ptr = 0, $8 = 0, $call19 = 0, $cmp20 = 0, $m_encoding = 0, $9 = 0, $cmp22 = 0, $m_eventPtr24 = 0, $call27 = 0, $tobool28 = 0, $cmp3745 = 0, $m_encoding30 = 0, $10 = 0, $cmp31 = 0, $m_eventPtr33 = 0, $i_046 = 0, $11 = 0, $12 = 0, $cmp40 = 0, $call42 = 0, $tobool43 = 0, $arrayidx46 = 0, $13 = 0, $14 = 0, $incdec_ptr48 = 0, $inc = 0, $cmp37 = 0, $m_encoding50 = 0, $15 = 0, $cmp51 = 0, $m_eventPtr53 = 0, $m_encoding56 = 0, $16 = 0, $cmp57 = 0, $17 = 0, $m_eventPtr59 = 0, $m_encoding61 = 0, $18 = 0, $cmp62 = 0, $m_eventPtr64 = 0, $19 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $next = __stackBase__ | 0;
+ $buf = __stackBase__ + 8 | 0;
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $entityValuePool = $0 + 104 | 0;
+ $blocks = $entityValuePool | 0;
+ $1 = HEAP32[$blocks >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _poolGrow($entityValuePool) | 0;
+ $tobool1 = $call << 24 >> 24 == 0;
+ if ($tobool1) {
+ $retval_0 = 1;
+ label = 29;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $arrayidx = $enc + 16 | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $end = $0 + 112 | 0;
+ $ptr = $0 + 116 | 0;
+ $charRefNumber = $enc + 40 | 0;
+ $arraydecay = $buf | 0;
+ $end38 = $0 + 112 | 0;
+ $ptr39 = $0 + 116 | 0;
+ $entityTextPtr_addr_0 = $entityTextPtr;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP32[$arrayidx >> 2] | 0;
+ $call4 = FUNCTION_TABLE_iiiii[$2 & 1023]($enc, $entityTextPtr_addr_0, $entityTextEnd, $next) | 0;
+ if (($call4 | 0) == 28) {
+ label = 6;
+ break;
+ } else if (($call4 | 0) == 9 | ($call4 | 0) == 6) {
+ label = 7;
+ break;
+ } else if (($call4 | 0) == (-3 | 0)) {
+ label = 8;
+ break;
+ } else if (($call4 | 0) == 7) {
+ label = 9;
+ break;
+ } else if (($call4 | 0) == 10) {
+ label = 12;
+ break;
+ } else if (($call4 | 0) == (-1 | 0)) {
+ label = 22;
+ break;
+ } else if (($call4 | 0) == 0) {
+ label = 24;
+ break;
+ } else if (($call4 | 0) == (-4 | 0)) {
+ $retval_0 = 0;
+ label = 29;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 6:
+ $m_eventPtr = $parser + 272 | 0;
+ HEAP32[$m_eventPtr >> 2] = $entityTextPtr_addr_0;
+ $retval_0 = 10;
+ label = 29;
+ break;
+ case 7:
+ $3 = HEAP32[$next >> 2] | 0;
+ $call7 = _poolAppend($entityValuePool, $enc, $entityTextPtr_addr_0, $3) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ $retval_0 = 1;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 8:
+ $4 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr = $entityTextPtr_addr_0 + $4 | 0;
+ HEAP32[$next >> 2] = $add_ptr;
+ label = 9;
+ break;
+ case 9:
+ $5 = HEAP32[$end >> 2] | 0;
+ $6 = HEAP32[$ptr >> 2] | 0;
+ $cmp = ($5 | 0) == ($6 | 0);
+ if ($cmp) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $call13 = _poolGrow($entityValuePool) | 0;
+ $tobool14 = $call13 << 24 >> 24 == 0;
+ if ($tobool14) {
+ $retval_0 = 1;
+ label = 29;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $7 = HEAP32[$ptr >> 2] | 0;
+ $incdec_ptr = $7 + 1 | 0;
+ HEAP32[$ptr >> 2] = $incdec_ptr;
+ HEAP8[$7] = 10;
+ label = 28;
+ break;
+ case 12:
+ $8 = HEAP32[$charRefNumber >> 2] | 0;
+ $call19 = FUNCTION_TABLE_iii[$8 & 1023]($enc, $entityTextPtr_addr_0) | 0;
+ $cmp20 = ($call19 | 0) < 0;
+ if ($cmp20) {
+ label = 13;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 13:
+ $m_encoding = $parser + 144 | 0;
+ $9 = HEAP32[$m_encoding >> 2] | 0;
+ $cmp22 = ($9 | 0) == ($enc | 0);
+ if ($cmp22) {
+ label = 14;
+ break;
+ } else {
+ $retval_0 = 14;
+ label = 29;
+ break;
+ }
+ case 14:
+ $m_eventPtr24 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr24 >> 2] = $entityTextPtr_addr_0;
+ $retval_0 = 14;
+ label = 29;
+ break;
+ case 15:
+ $call27 = _XmlUtf8Encode($call19, $arraydecay) | 0;
+ $tobool28 = ($call27 | 0) == 0;
+ if ($tobool28) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $cmp3745 = ($call27 | 0) > 0;
+ if ($cmp3745) {
+ $i_046 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 17:
+ $m_encoding30 = $parser + 144 | 0;
+ $10 = HEAP32[$m_encoding30 >> 2] | 0;
+ $cmp31 = ($10 | 0) == ($enc | 0);
+ if ($cmp31) {
+ label = 18;
+ break;
+ } else {
+ $retval_0 = 14;
+ label = 29;
+ break;
+ }
+ case 18:
+ $m_eventPtr33 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr33 >> 2] = $entityTextPtr_addr_0;
+ $retval_0 = 14;
+ label = 29;
+ break;
+ case 19:
+ $11 = HEAP32[$end38 >> 2] | 0;
+ $12 = HEAP32[$ptr39 >> 2] | 0;
+ $cmp40 = ($11 | 0) == ($12 | 0);
+ if ($cmp40) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $call42 = _poolGrow($entityValuePool) | 0;
+ $tobool43 = $call42 << 24 >> 24 == 0;
+ if ($tobool43) {
+ $retval_0 = 1;
+ label = 29;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $arrayidx46 = $buf + $i_046 | 0;
+ $13 = HEAP8[$arrayidx46] | 0;
+ $14 = HEAP32[$ptr39 >> 2] | 0;
+ $incdec_ptr48 = $14 + 1 | 0;
+ HEAP32[$ptr39 >> 2] = $incdec_ptr48;
+ HEAP8[$14] = $13;
+ $inc = $i_046 + 1 | 0;
+ $cmp37 = ($inc | 0) < ($call27 | 0);
+ if ($cmp37) {
+ $i_046 = $inc;
+ label = 19;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 22:
+ $m_encoding50 = $parser + 144 | 0;
+ $15 = HEAP32[$m_encoding50 >> 2] | 0;
+ $cmp51 = ($15 | 0) == ($enc | 0);
+ if ($cmp51) {
+ label = 23;
+ break;
+ } else {
+ $retval_0 = 4;
+ label = 29;
+ break;
+ }
+ case 23:
+ $m_eventPtr53 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr53 >> 2] = $entityTextPtr_addr_0;
+ $retval_0 = 4;
+ label = 29;
+ break;
+ case 24:
+ $m_encoding56 = $parser + 144 | 0;
+ $16 = HEAP32[$m_encoding56 >> 2] | 0;
+ $cmp57 = ($16 | 0) == ($enc | 0);
+ if ($cmp57) {
+ label = 25;
+ break;
+ } else {
+ $retval_0 = 4;
+ label = 29;
+ break;
+ }
+ case 25:
+ $17 = HEAP32[$next >> 2] | 0;
+ $m_eventPtr59 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr59 >> 2] = $17;
+ $retval_0 = 4;
+ label = 29;
+ break;
+ case 26:
+ $m_encoding61 = $parser + 144 | 0;
+ $18 = HEAP32[$m_encoding61 >> 2] | 0;
+ $cmp62 = ($18 | 0) == ($enc | 0);
+ if ($cmp62) {
+ label = 27;
+ break;
+ } else {
+ $retval_0 = 23;
+ label = 29;
+ break;
+ }
+ case 27:
+ $m_eventPtr64 = $parser + 272 | 0;
+ HEAP32[$m_eventPtr64 >> 2] = $entityTextPtr_addr_0;
+ $retval_0 = 23;
+ label = 29;
+ break;
+ case 28:
+ $19 = HEAP32[$next >> 2] | 0;
+ $entityTextPtr_addr_0 = $19;
+ label = 5;
+ break;
+ case 29:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _nextScaffoldPart($parser) {
+ $parser = $parser | 0;
+ var $m_dtd = 0, $0 = 0, $scaffIndex = 0, $1 = 0, $tobool = 0, $malloc_fcn = 0, $2 = 0, $m_groupSize = 0, $3 = 0, $mul = 0, $call = 0, $4 = 0, $tobool3 = 0, $scaffCount = 0, $5 = 0, $scaffSize = 0, $6 = 0, $cmp = 0, $scaffold = 0, $7 = 0, $tobool8 = 0, $realloc_fcn = 0, $8 = 0, $9 = 0, $mul14 = 0, $call15 = 0, $cmp16 = 0, $10 = 0, $mul20 = 0, $malloc_fcn22 = 0, $11 = 0, $call23 = 0, $cmp24 = 0, $storemerge = 0, $temp_0_in = 0, $temp_0 = 0, $12 = 0, $inc = 0, $scaffold32 = 0, $13 = 0, $scaffLevel = 0, $14 = 0, $tobool34 = 0, $sub = 0, $15 = 0, $arrayidx38 = 0, $16 = 0, $lastchild = 0, $17 = 0, $tobool41 = 0, $nextsib = 0, $childcnt = 0, $18 = 0, $tobool47 = 0, $firstchild = 0, $19 = 0, $inc52 = 0, $firstchild57 = 0, $20 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $scaffIndex = $0 + 164 | 0;
+ $1 = HEAP32[$scaffIndex >> 2] | 0;
+ $tobool = ($1 | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $malloc_fcn = $parser + 12 | 0;
+ $2 = HEAP32[$malloc_fcn >> 2] | 0;
+ $m_groupSize = $parser + 452 | 0;
+ $3 = HEAP32[$m_groupSize >> 2] | 0;
+ $mul = $3 << 2;
+ $call = FUNCTION_TABLE_ii[$2 & 1023]($mul) | 0;
+ $4 = $call;
+ HEAP32[$scaffIndex >> 2] = $4;
+ $tobool3 = ($call | 0) == 0;
+ if ($tobool3) {
+ $retval_0 = -1;
+ label = 18;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAP32[$4 >> 2] = 0;
+ label = 5;
+ break;
+ case 5:
+ $scaffCount = $0 + 156 | 0;
+ $5 = HEAP32[$scaffCount >> 2] | 0;
+ $scaffSize = $0 + 152 | 0;
+ $6 = HEAP32[$scaffSize >> 2] | 0;
+ $cmp = $5 >>> 0 < $6 >>> 0;
+ if ($cmp) {
+ label = 11;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $scaffold = $0 + 144 | 0;
+ $7 = HEAP32[$scaffold >> 2] | 0;
+ $tobool8 = ($7 | 0) == 0;
+ if ($tobool8) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $realloc_fcn = $parser + 16 | 0;
+ $8 = HEAP32[$realloc_fcn >> 2] | 0;
+ $9 = $7;
+ $mul14 = $6 * 56 & -1;
+ $call15 = FUNCTION_TABLE_iii[$8 & 1023]($9, $mul14) | 0;
+ $cmp16 = ($call15 | 0) == 0;
+ if ($cmp16) {
+ $retval_0 = -1;
+ label = 18;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $10 = HEAP32[$scaffSize >> 2] | 0;
+ $mul20 = $10 << 1;
+ $temp_0_in = $call15;
+ $storemerge = $mul20;
+ label = 10;
+ break;
+ case 9:
+ $malloc_fcn22 = $parser + 12 | 0;
+ $11 = HEAP32[$malloc_fcn22 >> 2] | 0;
+ $call23 = FUNCTION_TABLE_ii[$11 & 1023](896) | 0;
+ $cmp24 = ($call23 | 0) == 0;
+ if ($cmp24) {
+ $retval_0 = -1;
+ label = 18;
+ break;
+ } else {
+ $temp_0_in = $call23;
+ $storemerge = 32;
+ label = 10;
+ break;
+ }
+ case 10:
+ $temp_0 = $temp_0_in;
+ HEAP32[$scaffSize >> 2] = $storemerge;
+ HEAP32[$scaffold >> 2] = $temp_0;
+ label = 11;
+ break;
+ case 11:
+ $12 = HEAP32[$scaffCount >> 2] | 0;
+ $inc = $12 + 1 | 0;
+ HEAP32[$scaffCount >> 2] = $inc;
+ $scaffold32 = $0 + 144 | 0;
+ $13 = HEAP32[$scaffold32 >> 2] | 0;
+ $scaffLevel = $0 + 160 | 0;
+ $14 = HEAP32[$scaffLevel >> 2] | 0;
+ $tobool34 = ($14 | 0) == 0;
+ if ($tobool34) {
+ label = 17;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $sub = $14 - 1 | 0;
+ $15 = HEAP32[$scaffIndex >> 2] | 0;
+ $arrayidx38 = $15 + ($sub << 2) | 0;
+ $16 = HEAP32[$arrayidx38 >> 2] | 0;
+ $lastchild = $13 + ($16 * 28 & -1) + 16 | 0;
+ $17 = HEAP32[$lastchild >> 2] | 0;
+ $tobool41 = ($17 | 0) == 0;
+ if ($tobool41) {
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $nextsib = $13 + ($17 * 28 & -1) + 24 | 0;
+ HEAP32[$nextsib >> 2] = $12;
+ label = 14;
+ break;
+ case 14:
+ $childcnt = $13 + ($16 * 28 & -1) + 20 | 0;
+ $18 = HEAP32[$childcnt >> 2] | 0;
+ $tobool47 = ($18 | 0) == 0;
+ if ($tobool47) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $firstchild = $13 + ($16 * 28 & -1) + 12 | 0;
+ HEAP32[$firstchild >> 2] = $12;
+ label = 16;
+ break;
+ case 16:
+ HEAP32[$lastchild >> 2] = $12;
+ $19 = HEAP32[$childcnt >> 2] | 0;
+ $inc52 = $19 + 1 | 0;
+ HEAP32[$childcnt >> 2] = $inc52;
+ label = 17;
+ break;
+ case 17:
+ $firstchild57 = $13 + ($12 * 28 & -1) + 12 | 0;
+ $20 = $firstchild57;
+ _memset($20 | 0, 0, 16);
+ $retval_0 = $12;
+ label = 18;
+ break;
+ case 18:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _build_model($parser) {
+ $parser = $parser | 0;
+ var $cpos = 0, $str = 0, $m_dtd = 0, $0 = 0, $scaffCount = 0, $1 = 0, $mul = 0, $contentStringLen = 0, $2 = 0, $add = 0, $malloc_fcn = 0, $3 = 0, $call = 0, $4 = 0, $tobool = 0, $5 = 0, $arrayidx = 0, $6 = 0, $arrayidx3 = 0, $7 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 16 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cpos = __stackBase__ | 0;
+ $str = __stackBase__ + 8 | 0;
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $scaffCount = $0 + 156 | 0;
+ $1 = HEAP32[$scaffCount >> 2] | 0;
+ $mul = $1 * 20 & -1;
+ $contentStringLen = $0 + 148 | 0;
+ $2 = HEAP32[$contentStringLen >> 2] | 0;
+ $add = $mul + $2 | 0;
+ $malloc_fcn = $parser + 12 | 0;
+ $3 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call = FUNCTION_TABLE_ii[$3 & 1023]($add) | 0;
+ $4 = $call;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $5 = HEAP32[$scaffCount >> 2] | 0;
+ $arrayidx = $4 + ($5 * 20 & -1) | 0;
+ $6 = $arrayidx;
+ HEAP32[$str >> 2] = $6;
+ $arrayidx3 = $call + 20 | 0;
+ $7 = $arrayidx3;
+ HEAP32[$cpos >> 2] = $7;
+ _build_node($parser, 0, $4, $cpos, $str);
+ $retval_0 = $4;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _build_node($parser, $src_node, $dest, $contpos, $strpos) {
+ $parser = $parser | 0;
+ $src_node = $src_node | 0;
+ $dest = $dest | 0;
+ $contpos = $contpos | 0;
+ $strpos = $strpos | 0;
+ var $m_dtd = 0, $0 = 0, $scaffold = 0, $1 = 0, $type = 0, $2 = 0, $type1 = 0, $3 = 0, $quant = 0, $4 = 0, $quant4 = 0, $5 = 0, $cmp = 0, $6 = 0, $name = 0, $7 = 0, $name8 = 0, $8 = 0, $src_0 = 0, $9 = 0, $10 = 0, $incdec_ptr = 0, $11 = 0, $tobool = 0, $incdec_ptr10 = 0, $numchildren = 0, $children = 0, $12 = 0, $childcnt = 0, $13 = 0, $numchildren13 = 0, $14 = 0, $children14 = 0, $15 = 0, $16 = 0, $add_ptr = 0, $17 = 0, $cmp2032 = 0, $18 = 0, $firstchild = 0, $cn_034_in = 0, $i_033 = 0, $cn_034 = 0, $19 = 0, $arrayidx22 = 0, $inc = 0, $20 = 0, $nextsib = 0, $21 = 0, $cmp20 = 0, $name26 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $m_dtd = $parser + 340 | 0;
+ $0 = HEAP32[$m_dtd >> 2] | 0;
+ $scaffold = $0 + 144 | 0;
+ $1 = HEAP32[$scaffold >> 2] | 0;
+ $type = $1 + ($src_node * 28 & -1) | 0;
+ $2 = HEAP32[$type >> 2] | 0;
+ $type1 = $dest | 0;
+ HEAP32[$type1 >> 2] = $2;
+ $3 = HEAP32[$scaffold >> 2] | 0;
+ $quant = $3 + ($src_node * 28 & -1) + 4 | 0;
+ $4 = HEAP32[$quant >> 2] | 0;
+ $quant4 = $dest + 4 | 0;
+ HEAP32[$quant4 >> 2] = $4;
+ $5 = HEAP32[$type1 >> 2] | 0;
+ $cmp = ($5 | 0) == 4;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $6 = HEAP32[$strpos >> 2] | 0;
+ $name = $dest + 8 | 0;
+ HEAP32[$name >> 2] = $6;
+ $7 = HEAP32[$scaffold >> 2] | 0;
+ $name8 = $7 + ($src_node * 28 & -1) + 8 | 0;
+ $8 = HEAP32[$name8 >> 2] | 0;
+ $src_0 = $8;
+ label = 4;
+ break;
+ case 4:
+ $9 = HEAP8[$src_0] | 0;
+ $10 = HEAP32[$strpos >> 2] | 0;
+ $incdec_ptr = $10 + 1 | 0;
+ HEAP32[$strpos >> 2] = $incdec_ptr;
+ HEAP8[$10] = $9;
+ $11 = HEAP8[$src_0] | 0;
+ $tobool = $11 << 24 >> 24 == 0;
+ $incdec_ptr10 = $src_0 + 1 | 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ $src_0 = $incdec_ptr10;
+ label = 4;
+ break;
+ }
+ case 5:
+ $numchildren = $dest + 12 | 0;
+ HEAP32[$numchildren >> 2] = 0;
+ $children = $dest + 16 | 0;
+ HEAP32[$children >> 2] = 0;
+ label = 10;
+ break;
+ case 6:
+ $12 = HEAP32[$scaffold >> 2] | 0;
+ $childcnt = $12 + ($src_node * 28 & -1) + 20 | 0;
+ $13 = HEAP32[$childcnt >> 2] | 0;
+ $numchildren13 = $dest + 12 | 0;
+ HEAP32[$numchildren13 >> 2] = $13;
+ $14 = HEAP32[$contpos >> 2] | 0;
+ $children14 = $dest + 16 | 0;
+ HEAP32[$children14 >> 2] = $14;
+ $15 = HEAP32[$numchildren13 >> 2] | 0;
+ $16 = HEAP32[$contpos >> 2] | 0;
+ $add_ptr = $16 + ($15 * 20 & -1) | 0;
+ HEAP32[$contpos >> 2] = $add_ptr;
+ $17 = HEAP32[$numchildren13 >> 2] | 0;
+ $cmp2032 = ($17 | 0) == 0;
+ if ($cmp2032) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $18 = HEAP32[$scaffold >> 2] | 0;
+ $firstchild = $18 + ($src_node * 28 & -1) + 12 | 0;
+ $i_033 = 0;
+ $cn_034_in = $firstchild;
+ label = 8;
+ break;
+ case 8:
+ $cn_034 = HEAP32[$cn_034_in >> 2] | 0;
+ $19 = HEAP32[$children14 >> 2] | 0;
+ $arrayidx22 = $19 + ($i_033 * 20 & -1) | 0;
+ _build_node($parser, $cn_034, $arrayidx22, $contpos, $strpos);
+ $inc = $i_033 + 1 | 0;
+ $20 = HEAP32[$scaffold >> 2] | 0;
+ $nextsib = $20 + ($cn_034 * 28 & -1) + 24 | 0;
+ $21 = HEAP32[$numchildren13 >> 2] | 0;
+ $cmp20 = $inc >>> 0 < $21 >>> 0;
+ if ($cmp20) {
+ $i_033 = $inc;
+ $cn_034_in = $nextsib;
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $name26 = $dest + 8 | 0;
+ HEAP32[$name26 >> 2] = 0;
+ label = 10;
+ break;
+ case 10:
+ return;
+ }
+}
+function _dtdCreate($ms) {
+ $ms = $ms | 0;
+ var $malloc_fcn = 0, $0 = 0, $call = 0, $1 = 0, $cmp = 0, $pool = 0, $2 = 0, $entityValuePool = 0, $3 = 0, $generalEntities = 0, $elementTypes = 0, $4 = 0, $attributeIds = 0, $5 = 0, $prefixes = 0, $6 = 0, $defaultPrefix = 0, $name = 0, $binding = 0, $7 = 0, $8 = 0, $scaffold = 0, $9 = 0, $10 = 0, $11 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $malloc_fcn = $ms | 0;
+ $0 = HEAP32[$malloc_fcn >> 2] | 0;
+ $call = FUNCTION_TABLE_ii[$0 & 1023](168) | 0;
+ $1 = $call;
+ $cmp = ($call | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $pool = $call + 80 | 0;
+ $2 = $pool;
+ _poolInit($2, $ms);
+ $entityValuePool = $call + 104 | 0;
+ $3 = $entityValuePool;
+ _poolInit($3, $ms);
+ $generalEntities = $call;
+ _hashTableInit($generalEntities, $ms);
+ $elementTypes = $call + 20 | 0;
+ $4 = $elementTypes;
+ _hashTableInit($4, $ms);
+ $attributeIds = $call + 40 | 0;
+ $5 = $attributeIds;
+ _hashTableInit($5, $ms);
+ $prefixes = $call + 60 | 0;
+ $6 = $prefixes;
+ _hashTableInit($6, $ms);
+ $defaultPrefix = $call + 132 | 0;
+ $name = $defaultPrefix;
+ HEAP32[$name >> 2] = 0;
+ $binding = $call + 136 | 0;
+ $7 = $binding;
+ HEAP32[$7 >> 2] = 0;
+ $8 = $call + 140 | 0;
+ HEAP8[$8] = 0;
+ $scaffold = $call + 144 | 0;
+ $9 = $call + 128 | 0;
+ _memset($scaffold | 0, 0, 24);
+ HEAP8[$9] = 1;
+ $10 = $call + 129 | 0;
+ HEAP8[$10] = 0;
+ $11 = $call + 130 | 0;
+ HEAP8[$11] = 0;
+ label = 4;
+ break;
+ case 4:
+ return $1 | 0;
+ }
+ return 0;
+}
+function _poolInit($pool, $ms) {
+ $pool = $pool | 0;
+ $ms = $ms | 0;
+ _memset($pool | 0, 0, 20);
+ HEAP32[$pool + 20 >> 2] = $ms;
+ return;
+}
+function _prolog0($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $handler2 = 0, $handler4 = 0, $handler6 = 0, $nameMatchesAscii = 0, $0 = 0, $minBytesPerChar = 0, $1 = 0, $mul = 0, $add_ptr = 0, $call = 0, $tobool = 0, $handler9 = 0, $handler11 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 15) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 12) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 11) {
+ label = 5;
+ break;
+ } else if (($tok | 0) == 13) {
+ label = 6;
+ break;
+ } else if (($tok | 0) == 16) {
+ label = 7;
+ break;
+ } else if (($tok | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($tok | 0) == 14) {
+ $retval_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 44;
+ $retval_0 = 0;
+ label = 11;
+ break;
+ case 4:
+ $handler2 = $state | 0;
+ HEAP32[$handler2 >> 2] = 44;
+ $retval_0 = 1;
+ label = 11;
+ break;
+ case 5:
+ $handler4 = $state | 0;
+ HEAP32[$handler4 >> 2] = 44;
+ $retval_0 = 55;
+ label = 11;
+ break;
+ case 6:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 44;
+ $retval_0 = 56;
+ label = 11;
+ break;
+ case 7:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $1 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul = $1 << 1;
+ $add_ptr = $ptr + $mul | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $add_ptr, $end, 166928) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $handler9 = $state | 0;
+ HEAP32[$handler9 >> 2] = 120;
+ $retval_0 = 3;
+ label = 11;
+ break;
+ case 9:
+ $handler11 = $state | 0;
+ HEAP32[$handler11 >> 2] = 134;
+ $retval_0 = 2;
+ label = 11;
+ break;
+ case 10:
+ _common($state);
+ $retval_0 = -1;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _prolog1($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $0 = 0, $minBytesPerChar = 0, $1 = 0, $mul = 0, $add_ptr = 0, $call = 0, $tobool = 0, $handler = 0, $handler6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 11) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 13) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 16) {
+ label = 5;
+ break;
+ } else if (($tok | 0) == 29) {
+ label = 7;
+ break;
+ } else if (($tok | 0) == 15 | ($tok | 0) == 14) {
+ $retval_0 = 0;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $retval_0 = 55;
+ label = 9;
+ break;
+ case 4:
+ $retval_0 = 56;
+ label = 9;
+ break;
+ case 5:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $1 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul = $1 << 1;
+ $add_ptr = $ptr + $mul | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $add_ptr, $end, 166928) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 120;
+ $retval_0 = 3;
+ label = 9;
+ break;
+ case 7:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 134;
+ $retval_0 = 2;
+ label = 9;
+ break;
+ case 8:
+ _common($state);
+ $retval_0 = -1;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doctype0($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18 | ($tok | 0) == 41) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 3;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 546;
+ $retval_0 = 4;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doctype1($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $handler3 = 0, $nameMatchesAscii = 0, $0 = 0, $call = 0, $tobool = 0, $handler5 = 0, $1 = 0, $call7 = 0, $tobool8 = 0, $handler10 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 25) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 17) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 18) {
+ label = 5;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 3;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 148;
+ $retval_0 = 7;
+ label = 10;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 22;
+ $retval_0 = 8;
+ label = 10;
+ break;
+ case 5:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $ptr, $end, 166744) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler5 = $state | 0;
+ HEAP32[$handler5 >> 2] = 550;
+ $retval_0 = 3;
+ label = 10;
+ break;
+ case 7:
+ $1 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call7 = FUNCTION_TABLE_iiiii[$1 & 1023]($enc, $ptr, $end, 166768) | 0;
+ $tobool8 = ($call7 | 0) == 0;
+ if ($tobool8) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $handler10 = $state | 0;
+ HEAP32[$handler10 >> 2] = 256;
+ $retval_0 = 3;
+ label = 10;
+ break;
+ case 9:
+ _common($state);
+ $retval_0 = -1;
+ label = 10;
+ break;
+ case 10:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _internalSubset($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $0 = 0, $minBytesPerChar = 0, $1 = 0, $mul = 0, $add_ptr = 0, $call = 0, $tobool = 0, $handler = 0, $2 = 0, $3 = 0, $mul4 = 0, $add_ptr5 = 0, $call6 = 0, $tobool7 = 0, $handler9 = 0, $4 = 0, $5 = 0, $mul13 = 0, $add_ptr14 = 0, $call15 = 0, $tobool16 = 0, $handler18 = 0, $6 = 0, $7 = 0, $mul22 = 0, $add_ptr23 = 0, $call24 = 0, $tobool25 = 0, $handler27 = 0, $handler33 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 16) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 11) {
+ label = 11;
+ break;
+ } else if (($tok | 0) == 13) {
+ label = 12;
+ break;
+ } else if (($tok | 0) == 28) {
+ label = 13;
+ break;
+ } else if (($tok | 0) == 26) {
+ label = 14;
+ break;
+ } else if (($tok | 0) == 15 | ($tok | 0) == (-4 | 0)) {
+ $retval_0 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 3:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $1 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul = $1 << 1;
+ $add_ptr = $ptr + $mul | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $add_ptr, $end, 166888) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 326;
+ $retval_0 = 11;
+ label = 16;
+ break;
+ case 5:
+ $2 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $3 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul4 = $3 << 1;
+ $add_ptr5 = $ptr + $mul4 | 0;
+ $call6 = FUNCTION_TABLE_iiiii[$2 & 1023]($enc, $add_ptr5, $end, 166944) | 0;
+ $tobool7 = ($call6 | 0) == 0;
+ if ($tobool7) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler9 = $state | 0;
+ HEAP32[$handler9 >> 2] = 440;
+ $retval_0 = 33;
+ label = 16;
+ break;
+ case 7:
+ $4 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $5 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul13 = $5 << 1;
+ $add_ptr14 = $ptr + $mul13 | 0;
+ $call15 = FUNCTION_TABLE_iiiii[$4 & 1023]($enc, $add_ptr14, $end, 166920) | 0;
+ $tobool16 = ($call15 | 0) == 0;
+ if ($tobool16) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $handler18 = $state | 0;
+ HEAP32[$handler18 >> 2] = 86;
+ $retval_0 = 39;
+ label = 16;
+ break;
+ case 9:
+ $6 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $7 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul22 = $7 << 1;
+ $add_ptr23 = $ptr + $mul22 | 0;
+ $call24 = FUNCTION_TABLE_iiiii[$6 & 1023]($enc, $add_ptr23, $end, 166784) | 0;
+ $tobool25 = ($call24 | 0) == 0;
+ if ($tobool25) {
+ label = 15;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $handler27 = $state | 0;
+ HEAP32[$handler27 >> 2] = 366;
+ $retval_0 = 17;
+ label = 16;
+ break;
+ case 11:
+ $retval_0 = 55;
+ label = 16;
+ break;
+ case 12:
+ $retval_0 = 56;
+ label = 16;
+ break;
+ case 13:
+ $retval_0 = 57;
+ label = 16;
+ break;
+ case 14:
+ $handler33 = $state | 0;
+ HEAP32[$handler33 >> 2] = 540;
+ $retval_0 = 3;
+ label = 16;
+ break;
+ case 15:
+ _common($state);
+ $retval_0 = -1;
+ label = 16;
+ break;
+ case 16:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _prolog2($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 11) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 13) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 29) {
+ label = 5;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $retval_0 = 55;
+ label = 7;
+ break;
+ case 4:
+ $retval_0 = 56;
+ label = 7;
+ break;
+ case 5:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 134;
+ $retval_0 = 2;
+ label = 7;
+ break;
+ case 6:
+ _common($state);
+ $retval_0 = -1;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doctype3($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 3;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 538;
+ $retval_0 = 5;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doctype2($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 3;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 550;
+ $retval_0 = 6;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doctype4($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $handler3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 25) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 17) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 3;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 148;
+ $retval_0 = 7;
+ label = 6;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 22;
+ $retval_0 = 8;
+ label = 6;
+ break;
+ case 5:
+ _common($state);
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity0($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $handler3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 22) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 18) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 328;
+ $retval_0 = 11;
+ label = 6;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 442;
+ $retval_0 = 9;
+ label = 6;
+ break;
+ case 5:
+ _common($state);
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist0($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18 | ($tok | 0) == 41) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 518;
+ $retval_0 = 34;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _element0($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18 | ($tok | 0) == 41) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 39;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 278;
+ $retval_0 = 40;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _notation0($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 17;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 578;
+ $retval_0 = 18;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _doctype5($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 17) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 3;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 22;
+ $retval_0 = 8;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _notation1($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $0 = 0, $call = 0, $tobool = 0, $handler = 0, $1 = 0, $call3 = 0, $tobool4 = 0, $handler6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 17;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 3:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $ptr, $end, 166744) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 596;
+ $retval_0 = 17;
+ label = 8;
+ break;
+ case 5:
+ $1 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call3 = FUNCTION_TABLE_iiiii[$1 & 1023]($enc, $ptr, $end, 166768) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 94;
+ $retval_0 = 17;
+ label = 8;
+ break;
+ case 7:
+ _common($state);
+ $retval_0 = -1;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _notation3($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $role_none = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 17;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 17;
+ $retval_0 = 19;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _notation2($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 17;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 622;
+ $retval_0 = 21;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _notation4($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $role_none = 0, $handler3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 17) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 17;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 17;
+ $retval_0 = 19;
+ label = 6;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 148;
+ $retval_0 = 20;
+ label = 6;
+ break;
+ case 5:
+ _common($state);
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _declClose($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $role_none = 0, $0 = 0, $handler = 0, $role_none2 = 0, $1 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 15) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 17) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $role_none = $state + 8 | 0;
+ $0 = HEAP32[$role_none >> 2] | 0;
+ $retval_0 = $0;
+ label = 6;
+ break;
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 148;
+ $role_none2 = $state + 8 | 0;
+ $1 = HEAP32[$role_none2 >> 2] | 0;
+ $retval_0 = $1;
+ label = 6;
+ break;
+ case 5:
+ _common($state);
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _element1($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $0 = 0, $call = 0, $tobool = 0, $handler = 0, $role_none = 0, $1 = 0, $call3 = 0, $tobool4 = 0, $handler6 = 0, $role_none7 = 0, $handler10 = 0, $level = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 23) {
+ label = 7;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 39;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $ptr, $end, 166912) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 39;
+ $retval_0 = 42;
+ label = 9;
+ break;
+ case 5:
+ $1 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call3 = FUNCTION_TABLE_iiiii[$1 & 1023]($enc, $ptr, $end, 166952) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 206;
+ $role_none7 = $state + 8 | 0;
+ HEAP32[$role_none7 >> 2] = 39;
+ $retval_0 = 41;
+ label = 9;
+ break;
+ case 7:
+ $handler10 = $state | 0;
+ HEAP32[$handler10 >> 2] = 272;
+ $level = $state + 4 | 0;
+ HEAP32[$level >> 2] = 1;
+ $retval_0 = 44;
+ label = 9;
+ break;
+ case 8:
+ _common($state);
+ $retval_0 = -1;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _element2($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $0 = 0, $minBytesPerChar = 0, $1 = 0, $add_ptr = 0, $call = 0, $tobool = 0, $handler = 0, $level = 0, $handler3 = 0, $handler5 = 0, $handler7 = 0, $handler9 = 0, $handler11 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 20) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 23) {
+ label = 5;
+ break;
+ } else if (($tok | 0) == 18 | ($tok | 0) == 41) {
+ label = 6;
+ break;
+ } else if (($tok | 0) == 30) {
+ label = 7;
+ break;
+ } else if (($tok | 0) == 31) {
+ label = 8;
+ break;
+ } else if (($tok | 0) == 32) {
+ label = 9;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 39;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $1 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr = $ptr + $1 | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $add_ptr, $end, 166776) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 336;
+ $retval_0 = 43;
+ label = 11;
+ break;
+ case 5:
+ $level = $state + 4 | 0;
+ HEAP32[$level >> 2] = 2;
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 294;
+ $retval_0 = 44;
+ label = 11;
+ break;
+ case 6:
+ $handler5 = $state | 0;
+ HEAP32[$handler5 >> 2] = 302;
+ $retval_0 = 51;
+ label = 11;
+ break;
+ case 7:
+ $handler7 = $state | 0;
+ HEAP32[$handler7 >> 2] = 302;
+ $retval_0 = 53;
+ label = 11;
+ break;
+ case 8:
+ $handler9 = $state | 0;
+ HEAP32[$handler9 >> 2] = 302;
+ $retval_0 = 52;
+ label = 11;
+ break;
+ case 9:
+ $handler11 = $state | 0;
+ HEAP32[$handler11 >> 2] = 302;
+ $retval_0 = 54;
+ label = 11;
+ break;
+ case 10:
+ _common($state);
+ $retval_0 = -1;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _element3($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $role_none = 0, $handler3 = 0, $role_none4 = 0, $handler6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 24) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 36) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 21) {
+ label = 5;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 39;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 39;
+ $retval_0 = 45;
+ label = 7;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 206;
+ $role_none4 = $state + 8 | 0;
+ HEAP32[$role_none4 >> 2] = 39;
+ $retval_0 = 46;
+ label = 7;
+ break;
+ case 5:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 268;
+ $retval_0 = 39;
+ label = 7;
+ break;
+ case 6:
+ _common($state);
+ $retval_0 = -1;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _element6($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $level = 0, $0 = 0, $add = 0, $handler = 0, $handler4 = 0, $handler6 = 0, $handler8 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 23) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 18 | ($tok | 0) == 41) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 30) {
+ label = 5;
+ break;
+ } else if (($tok | 0) == 31) {
+ label = 6;
+ break;
+ } else if (($tok | 0) == 32) {
+ label = 7;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 39;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $level = $state + 4 | 0;
+ $0 = HEAP32[$level >> 2] | 0;
+ $add = $0 + 1 | 0;
+ HEAP32[$level >> 2] = $add;
+ $retval_0 = 44;
+ label = 9;
+ break;
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 302;
+ $retval_0 = 51;
+ label = 9;
+ break;
+ case 5:
+ $handler4 = $state | 0;
+ HEAP32[$handler4 >> 2] = 302;
+ $retval_0 = 53;
+ label = 9;
+ break;
+ case 6:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 302;
+ $retval_0 = 52;
+ label = 9;
+ break;
+ case 7:
+ $handler8 = $state | 0;
+ HEAP32[$handler8 >> 2] = 302;
+ $retval_0 = 54;
+ label = 9;
+ break;
+ case 8:
+ _common($state);
+ $retval_0 = -1;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _element7($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $level = 0, $0 = 0, $sub = 0, $cmp = 0, $handler = 0, $role_none = 0, $level4 = 0, $1 = 0, $sub5 = 0, $cmp7 = 0, $handler9 = 0, $role_none10 = 0, $level13 = 0, $2 = 0, $sub14 = 0, $cmp16 = 0, $handler18 = 0, $role_none19 = 0, $level22 = 0, $3 = 0, $sub23 = 0, $cmp25 = 0, $handler27 = 0, $role_none28 = 0, $handler31 = 0, $handler33 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 24) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 36) {
+ label = 5;
+ break;
+ } else if (($tok | 0) == 35) {
+ label = 7;
+ break;
+ } else if (($tok | 0) == 37) {
+ label = 9;
+ break;
+ } else if (($tok | 0) == 38) {
+ label = 11;
+ break;
+ } else if (($tok | 0) == 21) {
+ label = 12;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 39;
+ label = 14;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 3:
+ $level = $state + 4 | 0;
+ $0 = HEAP32[$level >> 2] | 0;
+ $sub = $0 - 1 | 0;
+ HEAP32[$level >> 2] = $sub;
+ $cmp = ($sub | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 45;
+ label = 14;
+ break;
+ }
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 39;
+ $retval_0 = 45;
+ label = 14;
+ break;
+ case 5:
+ $level4 = $state + 4 | 0;
+ $1 = HEAP32[$level4 >> 2] | 0;
+ $sub5 = $1 - 1 | 0;
+ HEAP32[$level4 >> 2] = $sub5;
+ $cmp7 = ($sub5 | 0) == 0;
+ if ($cmp7) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 46;
+ label = 14;
+ break;
+ }
+ case 6:
+ $handler9 = $state | 0;
+ HEAP32[$handler9 >> 2] = 206;
+ $role_none10 = $state + 8 | 0;
+ HEAP32[$role_none10 >> 2] = 39;
+ $retval_0 = 46;
+ label = 14;
+ break;
+ case 7:
+ $level13 = $state + 4 | 0;
+ $2 = HEAP32[$level13 >> 2] | 0;
+ $sub14 = $2 - 1 | 0;
+ HEAP32[$level13 >> 2] = $sub14;
+ $cmp16 = ($sub14 | 0) == 0;
+ if ($cmp16) {
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 47;
+ label = 14;
+ break;
+ }
+ case 8:
+ $handler18 = $state | 0;
+ HEAP32[$handler18 >> 2] = 206;
+ $role_none19 = $state + 8 | 0;
+ HEAP32[$role_none19 >> 2] = 39;
+ $retval_0 = 47;
+ label = 14;
+ break;
+ case 9:
+ $level22 = $state + 4 | 0;
+ $3 = HEAP32[$level22 >> 2] | 0;
+ $sub23 = $3 - 1 | 0;
+ HEAP32[$level22 >> 2] = $sub23;
+ $cmp25 = ($sub23 | 0) == 0;
+ if ($cmp25) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 48;
+ label = 14;
+ break;
+ }
+ case 10:
+ $handler27 = $state | 0;
+ HEAP32[$handler27 >> 2] = 206;
+ $role_none28 = $state + 8 | 0;
+ HEAP32[$role_none28 >> 2] = 39;
+ $retval_0 = 48;
+ label = 14;
+ break;
+ case 11:
+ $handler31 = $state | 0;
+ HEAP32[$handler31 >> 2] = 294;
+ $retval_0 = 50;
+ label = 14;
+ break;
+ case 12:
+ $handler33 = $state | 0;
+ HEAP32[$handler33 >> 2] = 294;
+ $retval_0 = 49;
+ label = 14;
+ break;
+ case 13:
+ _common($state);
+ $retval_0 = -1;
+ label = 14;
+ break;
+ case 14:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _element4($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18 | ($tok | 0) == 41) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 39;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 270;
+ $retval_0 = 51;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _element5($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $role_none = 0, $handler3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 36) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 21) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 39;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 39;
+ $retval_0 = 46;
+ label = 6;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 268;
+ $retval_0 = 39;
+ label = 6;
+ break;
+ case 5:
+ _common($state);
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist1($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $handler3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 17) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 18 | ($tok | 0) == 41) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 148;
+ $retval_0 = 33;
+ label = 6;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 318;
+ $retval_0 = 22;
+ label = 6;
+ break;
+ case 5:
+ _common($state);
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist2($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $i_0 = 0, $cmp = 0, $0 = 0, $arrayidx = 0, $1 = 0, $call = 0, $tobool = 0, $inc = 0, $handler = 0, $add = 0, $call3 = 0, $tobool4 = 0, $handler6 = 0, $handler9 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 23) {
+ label = 9;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $i_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ $cmp = ($i_0 | 0) < 8;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $arrayidx = 85864 + ($i_0 << 2) | 0;
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $ptr, $end, $1) | 0;
+ $tobool = ($call | 0) == 0;
+ $inc = $i_0 + 1 | 0;
+ if ($tobool) {
+ $i_0 = $inc;
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 378;
+ $add = $i_0 + 23 | 0;
+ $retval_0 = $add;
+ label = 11;
+ break;
+ case 7:
+ $call3 = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $ptr, $end, 166784) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 394;
+ $retval_0 = 33;
+ label = 11;
+ break;
+ case 9:
+ $handler9 = $state | 0;
+ HEAP32[$handler9 >> 2] = 522;
+ $retval_0 = 33;
+ label = 11;
+ break;
+ case 10:
+ _common($state);
+ $retval_0 = -1;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist8($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $0 = 0, $minBytesPerChar = 0, $1 = 0, $add_ptr = 0, $call = 0, $tobool = 0, $handler = 0, $2 = 0, $3 = 0, $add_ptr4 = 0, $call5 = 0, $tobool6 = 0, $handler8 = 0, $4 = 0, $5 = 0, $add_ptr12 = 0, $call13 = 0, $tobool14 = 0, $handler16 = 0, $handler19 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 20) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 27) {
+ label = 9;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 3:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $1 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr = $ptr + $1 | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $add_ptr, $end, 166848) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 518;
+ $retval_0 = 35;
+ label = 11;
+ break;
+ case 5:
+ $2 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $3 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr4 = $ptr + $3 | 0;
+ $call5 = FUNCTION_TABLE_iiiii[$2 & 1023]($enc, $add_ptr4, $end, 166752) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler8 = $state | 0;
+ HEAP32[$handler8 >> 2] = 518;
+ $retval_0 = 36;
+ label = 11;
+ break;
+ case 7:
+ $4 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $5 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr12 = $ptr + $5 | 0;
+ $call13 = FUNCTION_TABLE_iiiii[$4 & 1023]($enc, $add_ptr12, $end, 166880) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $handler16 = $state | 0;
+ HEAP32[$handler16 >> 2] = 504;
+ $retval_0 = 33;
+ label = 11;
+ break;
+ case 9:
+ $handler19 = $state | 0;
+ HEAP32[$handler19 >> 2] = 518;
+ $retval_0 = 37;
+ label = 11;
+ break;
+ case 10:
+ _common($state);
+ $retval_0 = -1;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist5($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 23) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 166;
+ $retval_0 = 33;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist3($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 19 | ($tok | 0) == 18 | ($tok | 0) == 41) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 512;
+ $retval_0 = 31;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist4($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $handler3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 24) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 21) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 378;
+ $retval_0 = 33;
+ label = 6;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 522;
+ $retval_0 = 33;
+ label = 6;
+ break;
+ case 5:
+ _common($state);
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist6($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 412;
+ $retval_0 = 32;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _XmlUtf8Encode($c, $buf) {
+ $c = $c | 0;
+ $buf = $buf | 0;
+ var $cmp = 0, $cmp1 = 0, $conv = 0, $cmp4 = 0, $shr26 = 0, $or = 0, $conv7 = 0, $and = 0, $or9 = 0, $conv10 = 0, $arrayidx11 = 0, $cmp13 = 0, $shr1624 = 0, $or17 = 0, $conv18 = 0, $shr2025 = 0, $and21 = 0, $or22 = 0, $conv23 = 0, $arrayidx24 = 0, $and25 = 0, $or26 = 0, $conv27 = 0, $arrayidx28 = 0, $cmp30 = 0, $shr3321 = 0, $or34 = 0, $conv35 = 0, $shr3722 = 0, $and38 = 0, $or39 = 0, $conv40 = 0, $arrayidx41 = 0, $shr4223 = 0, $and43 = 0, $or44 = 0, $conv45 = 0, $arrayidx46 = 0, $and47 = 0, $or48 = 0, $conv49 = 0, $arrayidx50 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($c | 0) < 0;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp1 = ($c | 0) < 128;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $conv = $c & 255;
+ HEAP8[$buf] = $conv;
+ $retval_0 = 1;
+ label = 11;
+ break;
+ case 5:
+ $cmp4 = ($c | 0) < 2048;
+ if ($cmp4) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $shr26 = $c >>> 6;
+ $or = $shr26 | 192;
+ $conv7 = $or & 255;
+ HEAP8[$buf] = $conv7;
+ $and = $c & 63;
+ $or9 = $and | 128;
+ $conv10 = $or9 & 255;
+ $arrayidx11 = $buf + 1 | 0;
+ HEAP8[$arrayidx11] = $conv10;
+ $retval_0 = 2;
+ label = 11;
+ break;
+ case 7:
+ $cmp13 = ($c | 0) < 65536;
+ if ($cmp13) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 8:
+ $shr1624 = $c >>> 12;
+ $or17 = $shr1624 | 224;
+ $conv18 = $or17 & 255;
+ HEAP8[$buf] = $conv18;
+ $shr2025 = $c >>> 6;
+ $and21 = $shr2025 & 63;
+ $or22 = $and21 | 128;
+ $conv23 = $or22 & 255;
+ $arrayidx24 = $buf + 1 | 0;
+ HEAP8[$arrayidx24] = $conv23;
+ $and25 = $c & 63;
+ $or26 = $and25 | 128;
+ $conv27 = $or26 & 255;
+ $arrayidx28 = $buf + 2 | 0;
+ HEAP8[$arrayidx28] = $conv27;
+ $retval_0 = 3;
+ label = 11;
+ break;
+ case 9:
+ $cmp30 = ($c | 0) < 1114112;
+ if ($cmp30) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 11;
+ break;
+ }
+ case 10:
+ $shr3321 = $c >>> 18;
+ $or34 = $shr3321 | 240;
+ $conv35 = $or34 & 255;
+ HEAP8[$buf] = $conv35;
+ $shr3722 = $c >>> 12;
+ $and38 = $shr3722 & 63;
+ $or39 = $and38 | 128;
+ $conv40 = $or39 & 255;
+ $arrayidx41 = $buf + 1 | 0;
+ HEAP8[$arrayidx41] = $conv40;
+ $shr4223 = $c >>> 6;
+ $and43 = $shr4223 & 63;
+ $or44 = $and43 | 128;
+ $conv45 = $or44 & 255;
+ $arrayidx46 = $buf + 2 | 0;
+ HEAP8[$arrayidx46] = $conv45;
+ $and47 = $c & 63;
+ $or48 = $and47 | 128;
+ $conv49 = $or48 & 255;
+ $arrayidx50 = $buf + 3 | 0;
+ HEAP8[$arrayidx50] = $conv49;
+ $retval_0 = 4;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _checkCharRefNumber($result) {
+ $result = $result | 0;
+ var $shr = 0, $arrayidx = 0, $0 = 0, $cmp = 0, $result_off = 0, $1 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $shr = $result >> 8;
+ if (($shr | 0) == 0) {
+ label = 3;
+ break;
+ } else if (($shr | 0) == 255) {
+ label = 4;
+ break;
+ } else if (($shr | 0) == 216 | ($shr | 0) == 217 | ($shr | 0) == 218 | ($shr | 0) == 219 | ($shr | 0) == 220 | ($shr | 0) == 221 | ($shr | 0) == 222 | ($shr | 0) == 223) {
+ $retval_0 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $arrayidx = $result + 11912 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $result_off = $result - 65534 | 0;
+ $1 = $result_off >>> 0 < 2;
+ if ($1) {
+ $retval_0 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $retval_0 = $result;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist7($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $handler3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 24) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 21) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 378;
+ $retval_0 = 33;
+ label = 6;
+ break;
+ case 4:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 166;
+ $retval_0 = 33;
+ label = 6;
+ break;
+ case 5:
+ _common($state);
+ $retval_0 = -1;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _attlist9($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 33;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 518;
+ $retval_0 = 38;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity1($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 624;
+ $retval_0 = 10;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity2($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $0 = 0, $call = 0, $tobool = 0, $handler = 0, $1 = 0, $call3 = 0, $tobool4 = 0, $handler6 = 0, $handler9 = 0, $role_none = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 27) {
+ label = 7;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $ptr, $end, 166744) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 334;
+ $retval_0 = 11;
+ label = 9;
+ break;
+ case 5:
+ $1 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call3 = FUNCTION_TABLE_iiiii[$1 & 1023]($enc, $ptr, $end, 166768) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 324;
+ $retval_0 = 11;
+ label = 9;
+ break;
+ case 7:
+ $handler9 = $state | 0;
+ HEAP32[$handler9 >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 11;
+ $retval_0 = 12;
+ label = 9;
+ break;
+ case 8:
+ _common($state);
+ $retval_0 = -1;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity4($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 530;
+ $retval_0 = 13;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity3($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 334;
+ $retval_0 = 14;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity5($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $nameMatchesAscii = 0, $0 = 0, $call = 0, $tobool = 0, $handler3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 17) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 18) {
+ label = 4;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 148;
+ $retval_0 = 15;
+ label = 7;
+ break;
+ case 4:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $ptr, $end, 166824) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $handler3 = $state | 0;
+ HEAP32[$handler3 >> 2] = 330;
+ $retval_0 = 11;
+ label = 7;
+ break;
+ case 6:
+ _common($state);
+ $retval_0 = -1;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity6($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $role_none = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 11;
+ $retval_0 = 16;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity7($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $nameMatchesAscii = 0, $0 = 0, $call = 0, $tobool = 0, $handler = 0, $1 = 0, $call3 = 0, $tobool4 = 0, $handler6 = 0, $handler9 = 0, $role_none = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 18) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 27) {
+ label = 7;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 3:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $0 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$0 & 1023]($enc, $ptr, $end, 166744) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 316;
+ $retval_0 = 11;
+ label = 9;
+ break;
+ case 5:
+ $1 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $call3 = FUNCTION_TABLE_iiiii[$1 & 1023]($enc, $ptr, $end, 166768) | 0;
+ $tobool4 = ($call3 | 0) == 0;
+ if ($tobool4) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $handler6 = $state | 0;
+ HEAP32[$handler6 >> 2] = 314;
+ $retval_0 = 11;
+ label = 9;
+ break;
+ case 7:
+ $handler9 = $state | 0;
+ HEAP32[$handler9 >> 2] = 206;
+ $role_none = $state + 8 | 0;
+ HEAP32[$role_none >> 2] = 11;
+ $retval_0 = 12;
+ label = 9;
+ break;
+ case 8:
+ _common($state);
+ $retval_0 = -1;
+ label = 9;
+ break;
+ case 9:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity9($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 552;
+ $retval_0 = 13;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity8($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 27) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 316;
+ $retval_0 = 14;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _entity10($state, $tok, $ptr, $end, $enc) {
+ $state = $state | 0;
+ $tok = $tok | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $enc = $enc | 0;
+ var $handler = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($tok | 0) == 17) {
+ label = 3;
+ break;
+ } else if (($tok | 0) == 15) {
+ $retval_0 = 11;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $handler = $state | 0;
+ HEAP32[$handler >> 2] = 148;
+ $retval_0 = 15;
+ label = 5;
+ break;
+ case 4:
+ _common($state);
+ $retval_0 = -1;
+ label = 5;
+ break;
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _XmlInitUnknownEncoding($mem, $table, $convert, $userData) {
+ $mem = $mem | 0;
+ $table = $table | 0;
+ $convert = $convert | 0;
+ $userData = $userData | 0;
+ var $i_094 = 0, $arrayidx = 0, $0 = 0, $arrayidx1 = 0, $inc = 0, $cmp = 0, $utf16 = 0, $1 = 0, $utf8 = 0, $2 = 0, $utf845 = 0, $3 = 0, $utf1648 = 0, $4 = 0, $utf872 = 0, $5 = 0, $utf1682 = 0, $6 = 0, $utf1691 = 0, $7 = 0, $utf893 = 0, $8 = 0, $utf8141 = 0, $9 = 0, $utf16149 = 0, $10 = 0, $i_193 = 0, $arrayidx5 = 0, $11 = 0, $arrayidx13 = 0, $12 = 0, $cmp14 = 0, $inc17 = 0, $cmp3 = 0, $i_290 = 0, $arrayidx23 = 0, $13 = 0, $cmp24 = 0, $type_sum = 0, $arrayidx27 = 0, $arrayidx28 = 0, $arrayidx30 = 0, $arrayidx33 = 0, $cmp34 = 0, $cmp37 = 0, $sub = 0, $conv41 = 0, $type43_sum = 0, $arrayidx44 = 0, $arrayidx47 = 0, $arrayidx49 = 0, $cmp51 = 0, $arrayidx54 = 0, $14 = 0, $cmp64 = 0, $15 = 0, $type70_sum = 0, $arrayidx71 = 0, $arrayidx74 = 0, $conv75 = 0, $arrayidx78 = 0, $cmp79 = 0, $16 = 0, $conv81 = 0, $arrayidx83 = 0, $call = 0, $cmp85 = 0, $type89_sum = 0, $arrayidx90 = 0, $arrayidx92 = 0, $arrayidx95 = 0, $arrayidx98 = 0, $cmp100 = 0, $shr = 0, $arrayidx104 = 0, $17 = 0, $conv105 = 0, $shl = 0, $and = 0, $shr10689 = 0, $add107 = 0, $arrayidx108 = 0, $18 = 0, $and110 = 0, $shl111 = 0, $and112 = 0, $tobool = 0, $type115_sum = 0, $arrayidx116 = 0, $arrayidx119 = 0, $19 = 0, $conv120 = 0, $shl121 = 0, $add124 = 0, $arrayidx125 = 0, $20 = 0, $and129 = 0, $tobool130 = 0, $type133_sum = 0, $arrayidx134 = 0, $arraydecay = 0, $add_ptr = 0, $call143 = 0, $conv144 = 0, $conv148 = 0, $arrayidx150 = 0, $inc156 = 0, $cmp20 = 0, $userData158 = 0, $21 = 0, $convert159 = 0, $22 = 0, $tobool160 = 0, $isName2 = 0, $23 = 0, $isName3 = 0, $24 = 0, $isName4 = 0, $25 = 0, $isNmstrt2 = 0, $26 = 0, $isNmstrt3 = 0, $27 = 0, $isNmstrt4 = 0, $28 = 0, $isInvalid2 = 0, $29 = 0, $isInvalid3 = 0, $30 = 0, $isInvalid4 = 0, $31 = 0, $enc = 0, $utf8Convert = 0, $32 = 0, $utf16Convert = 0, $33 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $i_094 = 0;
+ label = 3;
+ break;
+ case 3:
+ $arrayidx = $i_094 + 11840 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $arrayidx1 = $mem + $i_094 | 0;
+ HEAP8[$arrayidx1] = $0;
+ $inc = $i_094 + 1 | 0;
+ $cmp = ($inc | 0) < 364;
+ if ($cmp) {
+ $i_094 = $inc;
+ label = 3;
+ break;
+ } else {
+ $i_193 = 0;
+ label = 5;
+ break;
+ }
+ case 4:
+ $utf16 = $mem + 372 | 0;
+ $1 = $utf16;
+ $utf8 = $mem + 884 | 0;
+ $2 = $utf8;
+ $utf845 = $mem + 884 | 0;
+ $3 = $utf845;
+ $utf1648 = $mem + 372 | 0;
+ $4 = $utf1648;
+ $utf872 = $mem + 884 | 0;
+ $5 = $utf872;
+ $utf1682 = $mem + 372 | 0;
+ $6 = $utf1682;
+ $utf1691 = $mem + 372 | 0;
+ $7 = $utf1691;
+ $utf893 = $mem + 884 | 0;
+ $8 = $utf893;
+ $utf8141 = $mem + 884 | 0;
+ $9 = $utf8141;
+ $utf16149 = $mem + 372 | 0;
+ $10 = $utf16149;
+ $i_290 = 0;
+ label = 8;
+ break;
+ case 5:
+ $arrayidx5 = $i_193 + 11912 | 0;
+ $11 = HEAP8[$arrayidx5] | 0;
+ if (($11 << 24 >> 24 | 0) == 28 | ($11 << 24 >> 24 | 0) == 0) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $arrayidx13 = $table + ($i_193 << 2) | 0;
+ $12 = HEAP32[$arrayidx13 >> 2] | 0;
+ $cmp14 = ($12 | 0) == ($i_193 | 0);
+ if ($cmp14) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 7:
+ $inc17 = $i_193 + 1 | 0;
+ $cmp3 = ($inc17 | 0) < 128;
+ if ($cmp3) {
+ $i_193 = $inc17;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 8:
+ $arrayidx23 = $table + ($i_290 << 2) | 0;
+ $13 = HEAP32[$arrayidx23 >> 2] | 0;
+ $cmp24 = ($13 | 0) == -1;
+ if ($cmp24) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $type_sum = $i_290 + 72 | 0;
+ $arrayidx27 = $mem + $type_sum | 0;
+ HEAP8[$arrayidx27] = 1;
+ $arrayidx28 = $1 + ($i_290 << 1) | 0;
+ HEAP16[$arrayidx28 >> 1] = -1;
+ $arrayidx30 = $2 + ($i_290 << 2) | 0;
+ HEAP8[$arrayidx30] = 1;
+ $arrayidx33 = $2 + ($i_290 << 2) + 1 | 0;
+ HEAP8[$arrayidx33] = 0;
+ label = 26;
+ break;
+ case 10:
+ $cmp34 = ($13 | 0) < 0;
+ if ($cmp34) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $cmp37 = ($13 | 0) < -4;
+ if ($cmp37) {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $sub = 3 - $13 | 0;
+ $conv41 = $sub & 255;
+ $type43_sum = $i_290 + 72 | 0;
+ $arrayidx44 = $mem + $type43_sum | 0;
+ HEAP8[$arrayidx44] = $conv41;
+ $arrayidx47 = $3 + ($i_290 << 2) | 0;
+ HEAP8[$arrayidx47] = 0;
+ $arrayidx49 = $4 + ($i_290 << 1) | 0;
+ HEAP16[$arrayidx49 >> 1] = 0;
+ label = 26;
+ break;
+ case 13:
+ $cmp51 = ($13 | 0) < 128;
+ if ($cmp51) {
+ label = 14;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 14:
+ $arrayidx54 = $13 + 11912 | 0;
+ $14 = HEAP8[$arrayidx54] | 0;
+ if (($14 << 24 >> 24 | 0) == 28 | ($14 << 24 >> 24 | 0) == 0) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $cmp64 = ($13 | 0) == ($i_290 | 0);
+ if ($cmp64) {
+ label = 16;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ }
+ case 16:
+ $15 = HEAP8[$arrayidx54] | 0;
+ $type70_sum = $i_290 + 72 | 0;
+ $arrayidx71 = $mem + $type70_sum | 0;
+ HEAP8[$arrayidx71] = $15;
+ $arrayidx74 = $5 + ($i_290 << 2) | 0;
+ HEAP8[$arrayidx74] = 1;
+ $conv75 = $13 & 255;
+ $arrayidx78 = $5 + ($i_290 << 2) + 1 | 0;
+ HEAP8[$arrayidx78] = $conv75;
+ $cmp79 = ($13 | 0) == 0;
+ $16 = $13 & 65535;
+ $conv81 = $cmp79 ? -1 : $16;
+ $arrayidx83 = $6 + ($i_290 << 1) | 0;
+ HEAP16[$arrayidx83 >> 1] = $conv81;
+ label = 26;
+ break;
+ case 17:
+ $call = _checkCharRefNumber($13) | 0;
+ $cmp85 = ($call | 0) < 0;
+ if ($cmp85) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $type89_sum = $i_290 + 72 | 0;
+ $arrayidx90 = $mem + $type89_sum | 0;
+ HEAP8[$arrayidx90] = 0;
+ $arrayidx92 = $7 + ($i_290 << 1) | 0;
+ HEAP16[$arrayidx92 >> 1] = -1;
+ $arrayidx95 = $8 + ($i_290 << 2) | 0;
+ HEAP8[$arrayidx95] = 1;
+ $arrayidx98 = $8 + ($i_290 << 2) + 1 | 0;
+ HEAP8[$arrayidx98] = 0;
+ label = 26;
+ break;
+ case 19:
+ $cmp100 = ($13 | 0) > 65535;
+ if ($cmp100) {
+ $retval_0 = 0;
+ label = 30;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $shr = $13 >> 8;
+ $arrayidx104 = $shr + 9272 | 0;
+ $17 = HEAP8[$arrayidx104] | 0;
+ $conv105 = $17 & 255;
+ $shl = $conv105 << 3;
+ $and = $13 >>> 5;
+ $shr10689 = $and & 7;
+ $add107 = $shl | $shr10689;
+ $arrayidx108 = 9544 + ($add107 << 2) | 0;
+ $18 = HEAP32[$arrayidx108 >> 2] | 0;
+ $and110 = $13 & 31;
+ $shl111 = 1 << $and110;
+ $and112 = $18 & $shl111;
+ $tobool = ($and112 | 0) == 0;
+ if ($tobool) {
+ label = 22;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $type115_sum = $i_290 + 72 | 0;
+ $arrayidx116 = $mem + $type115_sum | 0;
+ HEAP8[$arrayidx116] = 22;
+ label = 25;
+ break;
+ case 22:
+ $arrayidx119 = $shr + 10824 | 0;
+ $19 = HEAP8[$arrayidx119] | 0;
+ $conv120 = $19 & 255;
+ $shl121 = $conv120 << 3;
+ $add124 = $shl121 | $shr10689;
+ $arrayidx125 = 9544 + ($add124 << 2) | 0;
+ $20 = HEAP32[$arrayidx125 >> 2] | 0;
+ $and129 = $20 & $shl111;
+ $tobool130 = ($and129 | 0) == 0;
+ $type133_sum = $i_290 + 72 | 0;
+ $arrayidx134 = $mem + $type133_sum | 0;
+ if ($tobool130) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ HEAP8[$arrayidx134] = 26;
+ label = 25;
+ break;
+ case 24:
+ HEAP8[$arrayidx134] = 28;
+ label = 25;
+ break;
+ case 25:
+ $arraydecay = $9 + ($i_290 << 2) | 0;
+ $add_ptr = $9 + ($i_290 << 2) + 1 | 0;
+ $call143 = _XmlUtf8Encode($13, $add_ptr) | 0;
+ $conv144 = $call143 & 255;
+ HEAP8[$arraydecay] = $conv144;
+ $conv148 = $13 & 65535;
+ $arrayidx150 = $10 + ($i_290 << 1) | 0;
+ HEAP16[$arrayidx150 >> 1] = $conv148;
+ label = 26;
+ break;
+ case 26:
+ $inc156 = $i_290 + 1 | 0;
+ $cmp20 = ($inc156 | 0) < 256;
+ if ($cmp20) {
+ $i_290 = $inc156;
+ label = 8;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $userData158 = $mem + 368 | 0;
+ $21 = $userData158;
+ HEAP32[$21 >> 2] = $userData;
+ $convert159 = $mem + 364 | 0;
+ $22 = $convert159;
+ HEAP32[$22 >> 2] = $convert;
+ $tobool160 = ($convert | 0) == 0;
+ if ($tobool160) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $isName2 = $mem + 328 | 0;
+ $23 = $isName2;
+ HEAP32[$23 >> 2] = 248;
+ $isName3 = $mem + 332 | 0;
+ $24 = $isName3;
+ HEAP32[$24 >> 2] = 248;
+ $isName4 = $mem + 336 | 0;
+ $25 = $isName4;
+ HEAP32[$25 >> 2] = 248;
+ $isNmstrt2 = $mem + 340 | 0;
+ $26 = $isNmstrt2;
+ HEAP32[$26 >> 2] = 162;
+ $isNmstrt3 = $mem + 344 | 0;
+ $27 = $isNmstrt3;
+ HEAP32[$27 >> 2] = 162;
+ $isNmstrt4 = $mem + 348 | 0;
+ $28 = $isNmstrt4;
+ HEAP32[$28 >> 2] = 162;
+ $isInvalid2 = $mem + 352 | 0;
+ $29 = $isInvalid2;
+ HEAP32[$29 >> 2] = 376;
+ $isInvalid3 = $mem + 356 | 0;
+ $30 = $isInvalid3;
+ HEAP32[$30 >> 2] = 376;
+ $isInvalid4 = $mem + 360 | 0;
+ $31 = $isInvalid4;
+ HEAP32[$31 >> 2] = 376;
+ label = 29;
+ break;
+ case 29:
+ $enc = $mem;
+ $utf8Convert = $mem + 56 | 0;
+ $32 = $utf8Convert;
+ HEAP32[$32 >> 2] = 348;
+ $utf16Convert = $mem + 60 | 0;
+ $33 = $utf16Convert;
+ HEAP32[$33 >> 2] = 524;
+ $retval_0 = $enc;
+ label = 30;
+ break;
+ case 30:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _unknown_isName($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $convert = 0, $0 = 0, $1 = 0, $userData = 0, $2 = 0, $3 = 0, $call = 0, $tobool = 0, $shr = 0, $arrayidx = 0, $4 = 0, $conv = 0, $shl = 0, $and1 = 0, $shr25 = 0, $add = 0, $arrayidx3 = 0, $5 = 0, $and5 = 0, $shl6 = 0, $and7 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $convert = $enc + 364 | 0;
+ $0 = HEAP32[$convert >> 2] | 0;
+ $1 = $0;
+ $userData = $enc + 368 | 0;
+ $2 = HEAP32[$userData >> 2] | 0;
+ $3 = $2;
+ $call = FUNCTION_TABLE_iii[$1 & 1023]($3, $p) | 0;
+ $tobool = $call >>> 0 > 65535;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $shr = $call >> 8;
+ $arrayidx = $shr + 10824 | 0;
+ $4 = HEAP8[$arrayidx] | 0;
+ $conv = $4 & 255;
+ $shl = $conv << 3;
+ $and1 = $call >>> 5;
+ $shr25 = $and1 & 7;
+ $add = $shl | $shr25;
+ $arrayidx3 = 9544 + ($add << 2) | 0;
+ $5 = HEAP32[$arrayidx3 >> 2] | 0;
+ $and5 = $call & 31;
+ $shl6 = 1 << $and5;
+ $and7 = $5 & $shl6;
+ $retval_0 = $and7;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _unknown_isNmstrt($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $convert = 0, $0 = 0, $1 = 0, $userData = 0, $2 = 0, $3 = 0, $call = 0, $tobool = 0, $shr = 0, $arrayidx = 0, $4 = 0, $conv = 0, $shl = 0, $and1 = 0, $shr25 = 0, $add = 0, $arrayidx3 = 0, $5 = 0, $and5 = 0, $shl6 = 0, $and7 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $convert = $enc + 364 | 0;
+ $0 = HEAP32[$convert >> 2] | 0;
+ $1 = $0;
+ $userData = $enc + 368 | 0;
+ $2 = HEAP32[$userData >> 2] | 0;
+ $3 = $2;
+ $call = FUNCTION_TABLE_iii[$1 & 1023]($3, $p) | 0;
+ $tobool = $call >>> 0 > 65535;
+ if ($tobool) {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $shr = $call >> 8;
+ $arrayidx = $shr + 9272 | 0;
+ $4 = HEAP8[$arrayidx] | 0;
+ $conv = $4 & 255;
+ $shl = $conv << 3;
+ $and1 = $call >>> 5;
+ $shr25 = $and1 & 7;
+ $add = $shl | $shr25;
+ $arrayidx3 = 9544 + ($add << 2) | 0;
+ $5 = HEAP32[$arrayidx3 >> 2] | 0;
+ $and5 = $call & 31;
+ $shl6 = 1 << $and5;
+ $and7 = $5 & $shl6;
+ $retval_0 = $and7;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _unknown_isInvalid($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $convert = 0, $0 = 0, $1 = 0, $userData = 0, $2 = 0, $3 = 0, $call = 0, $tobool = 0, $call1 = 0, $call1_lobit = 0, $4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $convert = $enc + 364 | 0;
+ $0 = HEAP32[$convert >> 2] | 0;
+ $1 = $0;
+ $userData = $enc + 368 | 0;
+ $2 = HEAP32[$userData >> 2] | 0;
+ $3 = $2;
+ $call = FUNCTION_TABLE_iii[$1 & 1023]($3, $p) | 0;
+ $tobool = $call >>> 0 > 65535;
+ if ($tobool) {
+ $4 = 1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $call1 = _checkCharRefNumber($call) | 0;
+ $call1_lobit = $call1 >>> 31;
+ $4 = $call1_lobit;
+ label = 4;
+ break;
+ case 4:
+ return $4 | 0;
+ }
+ return 0;
+}
+function _unknown_toUtf8($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $buf = 0, $convert = 0, $0 = 0, $cmp16 = 0, $utf81 = 0, $1 = 0, $userData = 0, $arraydecay5 = 0, $sub_ptr_lhs_cast = 0, $type = 0, $2 = 0, $sub_ptr_lhs_cast15 = 0, $3 = 0, $cmp = 0, $4 = 0, $5 = 0, $idxprom = 0, $arraydecay = 0, $incdec_ptr = 0, $6 = 0, $conv = 0, $cmp2 = 0, $7 = 0, $8 = 0, $9 = 0, $10 = 0, $call = 0, $call6 = 0, $11 = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp7 = 0, $12 = 0, $13 = 0, $idxprom12 = 0, $arrayidx13 = 0, $14 = 0, $conv14 = 0, $sub = 0, $add_ptr = 0, $15 = 0, $sub_ptr_rhs_cast16 = 0, $sub_ptr_sub17 = 0, $cmp18 = 0, $incdec_ptr22 = 0, $storemerge = 0, $n_0_ph = 0, $utf8_0_ph = 0, $n_0 = 0, $utf8_0 = 0, $incdec_ptr24 = 0, $16 = 0, $17 = 0, $incdec_ptr25 = 0, $dec = 0, $cmp26 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $buf = __stackBase__ | 0;
+ $convert = $enc + 364 | 0;
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $cmp16 = ($0 | 0) == ($fromLim | 0);
+ if ($cmp16) {
+ label = 12;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $utf81 = $enc + 884 | 0;
+ $1 = $utf81;
+ $userData = $enc + 368 | 0;
+ $arraydecay5 = $buf | 0;
+ $sub_ptr_lhs_cast = $toLim;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $sub_ptr_lhs_cast15 = $toLim;
+ $4 = $0;
+ label = 5;
+ break;
+ case 4:
+ $3 = HEAP32[$fromP >> 2] | 0;
+ $cmp = ($3 | 0) == ($fromLim | 0);
+ if ($cmp) {
+ label = 12;
+ break;
+ } else {
+ $4 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP8[$4] | 0;
+ $idxprom = $5 & 255;
+ $arraydecay = $1 + ($idxprom << 2) | 0;
+ $incdec_ptr = $1 + ($idxprom << 2) + 1 | 0;
+ $6 = HEAP8[$arraydecay] | 0;
+ $conv = $6 << 24 >> 24;
+ $cmp2 = $6 << 24 >> 24 == 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 6:
+ $7 = HEAP32[$convert >> 2] | 0;
+ $8 = $7;
+ $9 = HEAP32[$userData >> 2] | 0;
+ $10 = $9;
+ $call = FUNCTION_TABLE_iii[$8 & 1023]($10, $4) | 0;
+ $call6 = _XmlUtf8Encode($call, $arraydecay5) | 0;
+ $11 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_rhs_cast = $11;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp7 = ($call6 | 0) > ($sub_ptr_sub | 0);
+ if ($cmp7) {
+ label = 12;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $12 = HEAP32[$fromP >> 2] | 0;
+ $13 = HEAP8[$12] | 0;
+ $idxprom12 = $13 & 255;
+ $arrayidx13 = $2 + $idxprom12 | 0;
+ $14 = HEAP8[$arrayidx13] | 0;
+ $conv14 = $14 & 255;
+ $sub = $conv14 - 3 | 0;
+ $add_ptr = $12 + $sub | 0;
+ $utf8_0_ph = $arraydecay5;
+ $n_0_ph = $call6;
+ $storemerge = $add_ptr;
+ label = 10;
+ break;
+ case 8:
+ $15 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_rhs_cast16 = $15;
+ $sub_ptr_sub17 = $sub_ptr_lhs_cast15 - $sub_ptr_rhs_cast16 | 0;
+ $cmp18 = ($conv | 0) > ($sub_ptr_sub17 | 0);
+ if ($cmp18) {
+ label = 12;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $incdec_ptr22 = $4 + 1 | 0;
+ $utf8_0_ph = $incdec_ptr;
+ $n_0_ph = $conv;
+ $storemerge = $incdec_ptr22;
+ label = 10;
+ break;
+ case 10:
+ HEAP32[$fromP >> 2] = $storemerge;
+ $utf8_0 = $utf8_0_ph;
+ $n_0 = $n_0_ph;
+ label = 11;
+ break;
+ case 11:
+ $incdec_ptr24 = $utf8_0 + 1 | 0;
+ $16 = HEAP8[$utf8_0] | 0;
+ $17 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr25 = $17 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr25;
+ HEAP8[$17] = $16;
+ $dec = $n_0 - 1 | 0;
+ $cmp26 = ($dec | 0) == 0;
+ if ($cmp26) {
+ label = 4;
+ break;
+ } else {
+ $utf8_0 = $incdec_ptr24;
+ $n_0 = $dec;
+ label = 11;
+ break;
+ }
+ case 12:
+ STACKTOP = __stackBase__;
+ return;
+ }
+}
+function _unknown_toUtf16($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $cmp11 = 0, $utf16 = 0, $1 = 0, $convert = 0, $userData = 0, $type = 0, $2 = 0, $3 = 0, $4 = 0, $cmp1 = 0, $5 = 0, $idxprom = 0, $arrayidx = 0, $6 = 0, $cmp2 = 0, $7 = 0, $8 = 0, $9 = 0, $10 = 0, $call = 0, $conv4 = 0, $11 = 0, $12 = 0, $idxprom5 = 0, $arrayidx6 = 0, $13 = 0, $conv7 = 0, $sub = 0, $add_ptr = 0, $incdec_ptr = 0, $storemerge = 0, $c_0 = 0, $14 = 0, $incdec_ptr8 = 0, $15 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $cmp11 = ($0 | 0) == ($fromLim | 0);
+ if ($cmp11) {
+ label = 9;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $utf16 = $enc + 372 | 0;
+ $1 = $utf16;
+ $convert = $enc + 364 | 0;
+ $userData = $enc + 368 | 0;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $3 = $0;
+ label = 4;
+ break;
+ case 4:
+ $4 = HEAP32[$toP >> 2] | 0;
+ $cmp1 = ($4 | 0) == ($toLim | 0);
+ if ($cmp1) {
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP8[$3] | 0;
+ $idxprom = $5 & 255;
+ $arrayidx = $1 + ($idxprom << 1) | 0;
+ $6 = HEAP16[$arrayidx >> 1] | 0;
+ $cmp2 = $6 << 16 >> 16 == 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $7 = HEAP32[$convert >> 2] | 0;
+ $8 = $7;
+ $9 = HEAP32[$userData >> 2] | 0;
+ $10 = $9;
+ $call = FUNCTION_TABLE_iii[$8 & 1023]($10, $3) | 0;
+ $conv4 = $call & 65535;
+ $11 = HEAP32[$fromP >> 2] | 0;
+ $12 = HEAP8[$11] | 0;
+ $idxprom5 = $12 & 255;
+ $arrayidx6 = $2 + $idxprom5 | 0;
+ $13 = HEAP8[$arrayidx6] | 0;
+ $conv7 = $13 & 255;
+ $sub = $conv7 - 3 | 0;
+ $add_ptr = $11 + $sub | 0;
+ $c_0 = $conv4;
+ $storemerge = $add_ptr;
+ label = 8;
+ break;
+ case 7:
+ $incdec_ptr = $3 + 1 | 0;
+ $c_0 = $6;
+ $storemerge = $incdec_ptr;
+ label = 8;
+ break;
+ case 8:
+ HEAP32[$fromP >> 2] = $storemerge;
+ $14 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr8 = $14 + 2 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr8;
+ HEAP16[$14 >> 1] = $c_0;
+ $15 = HEAP32[$fromP >> 2] | 0;
+ $cmp = ($15 | 0) == ($fromLim | 0);
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ $3 = $15;
+ label = 4;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _XmlInitEncoding($p, $encPtr, $name) {
+ $p = $p | 0;
+ $encPtr = $encPtr | 0;
+ $name = $name | 0;
+ var $call = 0, $cmp = 0, $conv = 0, $initEnc = 0, $isUtf16 = 0, $arrayidx = 0, $arrayidx4 = 0, $updatePosition = 0, $encPtr6 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $call = _getEncodingIndex($name) | 0;
+ $cmp = ($call | 0) == -1;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $conv = $call & 255;
+ $initEnc = $p | 0;
+ $isUtf16 = $p + 69 | 0;
+ HEAP8[$isUtf16] = $conv;
+ $arrayidx = $p | 0;
+ HEAP32[$arrayidx >> 2] = 84;
+ $arrayidx4 = $p + 4 | 0;
+ HEAP32[$arrayidx4 >> 2] = 182;
+ $updatePosition = $p + 48 | 0;
+ HEAP32[$updatePosition >> 2] = 398;
+ $encPtr6 = $p + 72 | 0;
+ HEAP32[$encPtr6 >> 2] = $encPtr;
+ HEAP32[$encPtr >> 2] = $initEnc;
+ $retval_0 = 1;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _getEncodingIndex($name) {
+ $name = $name | 0;
+ var $cmp = 0, $i_0 = 0, $cmp1 = 0, $arrayidx = 0, $0 = 0, $call = 0, $tobool = 0, $inc = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($name | 0) == 0;
+ if ($cmp) {
+ $retval_0 = 6;
+ label = 5;
+ break;
+ } else {
+ $i_0 = 0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp1 = ($i_0 | 0) < 6;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = -1;
+ label = 5;
+ break;
+ }
+ case 4:
+ $arrayidx = 16296 + ($i_0 << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $call = _streqci($name, $0) | 0;
+ $tobool = ($call | 0) == 0;
+ $inc = $i_0 + 1 | 0;
+ if ($tobool) {
+ $i_0 = $inc;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = $i_0;
+ label = 5;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _initScanProlog($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ return _initScan($enc, 0, $ptr, $end, $nextTokPtr) | 0;
+}
+function _initScanContent($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ return _initScan($enc, 1, $ptr, $end, $nextTokPtr) | 0;
+}
+function _streqci($s1, $s2) {
+ $s1 = $s1 | 0;
+ $s2 = $s2 | 0;
+ var $s1_addr_0 = 0, $s2_addr_0 = 0, $0 = 0, $1 = 0, $_off = 0, $2 = 0, $add = 0, $c1_0 = 0, $_off11 = 0, $3 = 0, $add17 = 0, $c2_0 = 0, $cmp22 = 0, $incdec_ptr1 = 0, $incdec_ptr = 0, $tobool = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $s2_addr_0 = $s2;
+ $s1_addr_0 = $s1;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[$s1_addr_0] | 0;
+ $1 = HEAP8[$s2_addr_0] | 0;
+ $_off = $0 - 97 & 255;
+ $2 = ($_off & 255) < 26;
+ $add = $0 - 32 & 255;
+ $c1_0 = $2 ? $add : $0;
+ $_off11 = $1 - 97 & 255;
+ $3 = ($_off11 & 255) < 26;
+ $add17 = $1 - 32 & 255;
+ $c2_0 = $3 ? $add17 : $1;
+ $cmp22 = $c1_0 << 24 >> 24 == $c2_0 << 24 >> 24;
+ if ($cmp22) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 5;
+ break;
+ }
+ case 4:
+ $incdec_ptr1 = $s2_addr_0 + 1 | 0;
+ $incdec_ptr = $s1_addr_0 + 1 | 0;
+ $tobool = $c1_0 << 24 >> 24 == 0;
+ if ($tobool) {
+ $retval_0 = 1;
+ label = 5;
+ break;
+ } else {
+ $s2_addr_0 = $incdec_ptr1;
+ $s1_addr_0 = $incdec_ptr;
+ label = 3;
+ break;
+ }
+ case 5:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _initUpdatePosition($enc, $ptr, $end, $pos) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $pos = $pos | 0;
+ _normal_updatePosition(528, $ptr, $end, $pos);
+ return;
+}
+function _XmlParseXmlDecl($isGeneralTextEntity, $enc, $ptr, $end, $badPtr, $versionPtr, $versionEndPtr, $encodingName, $encoding, $standalone) {
+ $isGeneralTextEntity = $isGeneralTextEntity | 0;
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $badPtr = $badPtr | 0;
+ $versionPtr = $versionPtr | 0;
+ $versionEndPtr = $versionEndPtr | 0;
+ $encodingName = $encodingName | 0;
+ $encoding = $encoding | 0;
+ $standalone = $standalone | 0;
+ return _doParseXmlDecl($isGeneralTextEntity, $enc, $ptr, $end, $badPtr, $versionPtr, $versionEndPtr, $encodingName, $encoding, $standalone) | 0;
+}
+function _doParseXmlDecl($isGeneralTextEntity, $enc, $ptr, $end, $badPtr, $versionPtr, $versionEndPtr, $encodingName, $encoding, $standalone) {
+ $isGeneralTextEntity = $isGeneralTextEntity | 0;
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $badPtr = $badPtr | 0;
+ $versionPtr = $versionPtr | 0;
+ $versionEndPtr = $versionEndPtr | 0;
+ $encodingName = $encodingName | 0;
+ $encoding = $encoding | 0;
+ $standalone = $standalone | 0;
+ var $ptr_addr = 0, $val = 0, $name = 0, $nameEnd = 0, $minBytesPerChar = 0, $0 = 0, $mul = 0, $1 = 0, $add_ptr = 0, $2 = 0, $mul2 = 0, $idx_neg = 0, $add_ptr3 = 0, $call = 0, $tobool = 0, $3 = 0, $tobool4 = 0, $or_cond = 0, $4 = 0, $nameMatchesAscii = 0, $5 = 0, $6 = 0, $call5 = 0, $tobool6 = 0, $tobool8 = 0, $7 = 0, $tobool11 = 0, $8 = 0, $tobool14 = 0, $9 = 0, $10 = 0, $call17 = 0, $tobool18 = 0, $11 = 0, $12 = 0, $tobool21 = 0, $tobool23 = 0, $13 = 0, $14 = 0, $15 = 0, $16 = 0, $call29 = 0, $tobool30 = 0, $17 = 0, $call32 = 0, $call32_off = 0, $18 = 0, $call32_off1 = 0, $19 = 0, $or_cond3 = 0, $20 = 0, $tobool40 = 0, $21 = 0, $tobool43 = 0, $22 = 0, $23 = 0, $24 = 0, $idx_neg46 = 0, $add_ptr47 = 0, $call48 = 0, $25 = 0, $call50 = 0, $tobool51 = 0, $26 = 0, $27 = 0, $tobool54 = 0, $28 = 0, $29 = 0, $30 = 0, $call59 = 0, $tobool60 = 0, $tobool62 = 0, $or_cond4 = 0, $31 = 0, $32 = 0, $33 = 0, $34 = 0, $35 = 0, $idx_neg67 = 0, $add_ptr68 = 0, $call69 = 0, $tobool70 = 0, $tobool72 = 0, $36 = 0, $call895 = 0, $call906 = 0, $tobool917 = 0, $37 = 0, $38 = 0, $39 = 0, $40 = 0, $idx_neg78 = 0, $add_ptr79 = 0, $call80 = 0, $tobool81 = 0, $tobool83 = 0, $41 = 0, $42 = 0, $43 = 0, $add_ptr93 = 0, $call89 = 0, $call90 = 0, $tobool91 = 0, $44 = 0, $cmp94 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 32 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr_addr = __stackBase__ | 0;
+ $val = __stackBase__ + 8 | 0;
+ $name = __stackBase__ + 16 | 0;
+ $nameEnd = __stackBase__ + 24 | 0;
+ HEAP32[$ptr_addr >> 2] = $ptr;
+ HEAP32[$val >> 2] = 0;
+ HEAP32[$name >> 2] = 0;
+ HEAP32[$nameEnd >> 2] = 0;
+ $minBytesPerChar = $enc + 64 | 0;
+ $0 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul = $0 * 5 & -1;
+ $1 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr = $1 + $mul | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr;
+ $2 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $mul2 = $2 << 1;
+ $idx_neg = -$mul2 | 0;
+ $add_ptr3 = $end + $idx_neg | 0;
+ $call = _parsePseudoAttribute($enc, $add_ptr, $add_ptr3, $name, $nameEnd, $val, $ptr_addr) | 0;
+ $tobool = ($call | 0) != 0;
+ $3 = HEAP32[$name >> 2] | 0;
+ $tobool4 = ($3 | 0) != 0;
+ $or_cond = $tobool & $tobool4;
+ if ($or_cond) {
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $4 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$badPtr >> 2] = $4;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 4:
+ $nameMatchesAscii = $enc + 24 | 0;
+ $5 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $6 = HEAP32[$nameEnd >> 2] | 0;
+ $call5 = FUNCTION_TABLE_iiiii[$5 & 1023]($enc, $3, $6, 166632) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $tobool8 = ($isGeneralTextEntity | 0) == 0;
+ if ($tobool8) {
+ label = 6;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 6:
+ $7 = HEAP32[$name >> 2] | 0;
+ HEAP32[$badPtr >> 2] = $7;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 7:
+ $tobool11 = ($versionPtr | 0) == 0;
+ if ($tobool11) {
+ label = 9;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $8 = HEAP32[$val >> 2] | 0;
+ HEAP32[$versionPtr >> 2] = $8;
+ label = 9;
+ break;
+ case 9:
+ $tobool14 = ($versionEndPtr | 0) == 0;
+ if ($tobool14) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $9 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$versionEndPtr >> 2] = $9;
+ label = 11;
+ break;
+ case 11:
+ $10 = HEAP32[$ptr_addr >> 2] | 0;
+ $call17 = _parsePseudoAttribute($enc, $10, $add_ptr3, $name, $nameEnd, $val, $ptr_addr) | 0;
+ $tobool18 = ($call17 | 0) == 0;
+ if ($tobool18) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $11 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$badPtr >> 2] = $11;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 13:
+ $12 = HEAP32[$name >> 2] | 0;
+ $tobool21 = ($12 | 0) == 0;
+ if ($tobool21) {
+ label = 14;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 14:
+ $tobool23 = ($isGeneralTextEntity | 0) == 0;
+ if ($tobool23) {
+ $retval_0 = 1;
+ label = 39;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $13 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$badPtr >> 2] = $13;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 16:
+ $14 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $15 = HEAP32[$name >> 2] | 0;
+ $16 = HEAP32[$nameEnd >> 2] | 0;
+ $call29 = FUNCTION_TABLE_iiiii[$14 & 1023]($enc, $15, $16, 166664) | 0;
+ $tobool30 = ($call29 | 0) == 0;
+ if ($tobool30) {
+ label = 26;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $17 = HEAP32[$val >> 2] | 0;
+ $call32 = _toAscii($enc, $17, $add_ptr3) | 0;
+ $call32_off = $call32 - 97 | 0;
+ $18 = $call32_off >>> 0 < 26;
+ $call32_off1 = $call32 - 65 | 0;
+ $19 = $call32_off1 >>> 0 < 26;
+ $or_cond3 = $18 | $19;
+ if ($or_cond3) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $20 = HEAP32[$val >> 2] | 0;
+ HEAP32[$badPtr >> 2] = $20;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 19:
+ $tobool40 = ($encodingName | 0) == 0;
+ if ($tobool40) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $21 = HEAP32[$val >> 2] | 0;
+ HEAP32[$encodingName >> 2] = $21;
+ label = 21;
+ break;
+ case 21:
+ $tobool43 = ($encoding | 0) == 0;
+ if ($tobool43) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $22 = HEAP32[$val >> 2] | 0;
+ $23 = HEAP32[$ptr_addr >> 2] | 0;
+ $24 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $idx_neg46 = -$24 | 0;
+ $add_ptr47 = $23 + $idx_neg46 | 0;
+ $call48 = _findEncoding($enc, $22, $add_ptr47) | 0;
+ HEAP32[$encoding >> 2] = $call48;
+ label = 23;
+ break;
+ case 23:
+ $25 = HEAP32[$ptr_addr >> 2] | 0;
+ $call50 = _parsePseudoAttribute($enc, $25, $add_ptr3, $name, $nameEnd, $val, $ptr_addr) | 0;
+ $tobool51 = ($call50 | 0) == 0;
+ if ($tobool51) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $26 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$badPtr >> 2] = $26;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 25:
+ $27 = HEAP32[$name >> 2] | 0;
+ $tobool54 = ($27 | 0) == 0;
+ if ($tobool54) {
+ $retval_0 = 1;
+ label = 39;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $28 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $29 = HEAP32[$name >> 2] | 0;
+ $30 = HEAP32[$nameEnd >> 2] | 0;
+ $call59 = FUNCTION_TABLE_iiiii[$28 & 1023]($enc, $29, $30, 166640) | 0;
+ $tobool60 = ($call59 | 0) != 0;
+ $tobool62 = ($isGeneralTextEntity | 0) == 0;
+ $or_cond4 = $tobool60 & $tobool62;
+ if ($or_cond4) {
+ label = 28;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $31 = HEAP32[$name >> 2] | 0;
+ HEAP32[$badPtr >> 2] = $31;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 28:
+ $32 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $33 = HEAP32[$val >> 2] | 0;
+ $34 = HEAP32[$ptr_addr >> 2] | 0;
+ $35 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $idx_neg67 = -$35 | 0;
+ $add_ptr68 = $34 + $idx_neg67 | 0;
+ $call69 = FUNCTION_TABLE_iiiii[$32 & 1023]($enc, $33, $add_ptr68, 166624) | 0;
+ $tobool70 = ($call69 | 0) == 0;
+ if ($tobool70) {
+ label = 32;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $tobool72 = ($standalone | 0) == 0;
+ if ($tobool72) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $36 = HEAP32[$ptr_addr >> 2] | 0;
+ $call895 = _toAscii($enc, $36, $add_ptr3) | 0;
+ $call906 = _isSpace($call895) | 0;
+ $tobool917 = ($call906 | 0) == 0;
+ if ($tobool917) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 31:
+ HEAP32[$standalone >> 2] = 1;
+ label = 30;
+ break;
+ case 32:
+ $37 = HEAP32[$nameMatchesAscii >> 2] | 0;
+ $38 = HEAP32[$val >> 2] | 0;
+ $39 = HEAP32[$ptr_addr >> 2] | 0;
+ $40 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $idx_neg78 = -$40 | 0;
+ $add_ptr79 = $39 + $idx_neg78 | 0;
+ $call80 = FUNCTION_TABLE_iiiii[$37 & 1023]($enc, $38, $add_ptr79, 166656) | 0;
+ $tobool81 = ($call80 | 0) == 0;
+ if ($tobool81) {
+ label = 35;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $tobool83 = ($standalone | 0) == 0;
+ if ($tobool83) {
+ label = 30;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ HEAP32[$standalone >> 2] = 0;
+ label = 30;
+ break;
+ case 35:
+ $41 = HEAP32[$val >> 2] | 0;
+ HEAP32[$badPtr >> 2] = $41;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 36:
+ $42 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $43 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr93 = $43 + $42 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr93;
+ $call89 = _toAscii($enc, $add_ptr93, $add_ptr3) | 0;
+ $call90 = _isSpace($call89) | 0;
+ $tobool91 = ($call90 | 0) == 0;
+ if ($tobool91) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 37:
+ $44 = HEAP32[$ptr_addr >> 2] | 0;
+ $cmp94 = ($44 | 0) == ($add_ptr3 | 0);
+ if ($cmp94) {
+ $retval_0 = 1;
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ HEAP32[$badPtr >> 2] = $44;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 39:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _findEncoding($enc, $ptr, $end) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ var $ptr_addr = 0, $buf = 0, $p = 0, $arraydecay = 0, $utf8Convert = 0, $0 = 0, $add_ptr1 = 0, $1 = 0, $cmp = 0, $2 = 0, $call = 0, $tobool = 0, $minBytesPerChar = 0, $3 = 0, $cmp3 = 0, $call7 = 0, $cmp8 = 0, $arrayidx = 0, $4 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 144 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr_addr = __stackBase__ | 0;
+ $buf = __stackBase__ + 8 | 0;
+ $p = __stackBase__ + 136 | 0;
+ HEAP32[$ptr_addr >> 2] = $ptr;
+ $arraydecay = $buf | 0;
+ HEAP32[$p >> 2] = $arraydecay;
+ $utf8Convert = $enc + 56 | 0;
+ $0 = HEAP32[$utf8Convert >> 2] | 0;
+ $add_ptr1 = $buf + 127 | 0;
+ FUNCTION_TABLE_viiiii[$0 & 1023]($enc, $ptr_addr, $end, $p, $add_ptr1);
+ $1 = HEAP32[$ptr_addr >> 2] | 0;
+ $cmp = ($1 | 0) == ($end | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$p >> 2] | 0;
+ HEAP8[$2] = 0;
+ $call = _streqci($arraydecay, 166720) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $minBytesPerChar = $enc + 64 | 0;
+ $3 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $cmp3 = ($3 | 0) == 2;
+ if ($cmp3) {
+ $retval_0 = $enc;
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $call7 = _getEncodingIndex($arraydecay) | 0;
+ $cmp8 = ($call7 | 0) == -1;
+ if ($cmp8) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $arrayidx = 20264 + ($call7 << 2) | 0;
+ $4 = HEAP32[$arrayidx >> 2] | 0;
+ $retval_0 = $4;
+ label = 7;
+ break;
+ case 7:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_prologTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $and = 0, $tobool = 0, $and2 = 0, $cmp3 = 0, $add_ptr = 0, $end_addr_0 = 0, $arrayidx = 0, $0 = 0, $cmp7 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx9 = 0, $3 = 0, $conv10 = 0, $call = 0, $cond = 0, $add_ptr54167 = 0, $cmp55168 = 0, $type65 = 0, $4 = 0, $add_ptr13 = 0, $call14 = 0, $add_ptr16 = 0, $call17 = 0, $add_ptr19 = 0, $cmp20 = 0, $arrayidx24 = 0, $5 = 0, $cmp26 = 0, $6 = 0, $idxprom29 = 0, $type30 = 0, $7 = 0, $arrayidx31 = 0, $8 = 0, $conv32 = 0, $call36 = 0, $cond38 = 0, $add_ptr40 = 0, $call41 = 0, $add_ptr43 = 0, $call44 = 0, $add_ptr48 = 0, $cmp49 = 0, $add_ptr54170 = 0, $ptr_addr_0169 = 0, $arrayidx59 = 0, $9 = 0, $cmp61 = 0, $10 = 0, $idxprom64 = 0, $arrayidx66 = 0, $11 = 0, $conv67 = 0, $call71 = 0, $cond73 = 0, $add_ptr54 = 0, $cmp55 = 0, $add_ptr76 = 0, $cmp77 = 0, $add_ptr54_lcssa = 0, $add_ptr83 = 0, $call84 = 0, $add_ptr86 = 0, $add_ptr88 = 0, $add_ptr90 = 0, $cmp91 = 0, $arrayidx95 = 0, $12 = 0, $cmp97 = 0, $13 = 0, $cmp101 = 0, $add_ptr104 = 0, $cmp105 = 0, $arrayidx110 = 0, $14 = 0, $cmp112 = 0, $15 = 0, $cmp118 = 0, $add_ptr121 = 0, $add_ptr125 = 0, $add_ptr127 = 0, $cmp128 = 0, $arrayidx132 = 0, $16 = 0, $cmp134 = 0, $17 = 0, $idxprom137 = 0, $type138 = 0, $18 = 0, $arrayidx139 = 0, $19 = 0, $conv140 = 0, $call144 = 0, $cond146 = 0, $add_ptr148 = 0, $add_ptr150 = 0, $add_ptr152 = 0, $add_ptr156 = 0, $add_ptr158 = 0, $add_ptr160 = 0, $call161 = 0, $sub_ptr_lhs_cast163 = 0, $sub_ptr_sub165 = 0, $cmp166 = 0, $sub_ptr_lhs_cast171 = 0, $sub_ptr_sub173 = 0, $cmp174 = 0, $sub_ptr_lhs_cast179 = 0, $sub_ptr_sub181 = 0, $cmp182 = 0, $20 = 0, $idxprom192 = 0, $arrayidx193 = 0, $21 = 0, $conv194 = 0, $shl = 0, $22 = 0, $conv196 = 0, $shr164 = 0, $add = 0, $arrayidx197 = 0, $23 = 0, $and200 = 0, $shl201 = 0, $and202 = 0, $tobool203 = 0, $arrayidx209 = 0, $24 = 0, $conv210 = 0, $shl211 = 0, $add215 = 0, $arrayidx216 = 0, $25 = 0, $and221 = 0, $tobool222 = 0, $tok_0_ph = 0, $ptr_addr_1189 = 0, $cmp228190 = 0, $type236 = 0, $26 = 0, $ptr_addr_1192 = 0, $ptr_pn191 = 0, $arrayidx230 = 0, $27 = 0, $cmp232 = 0, $28 = 0, $idxprom235 = 0, $arrayidx237 = 0, $29 = 0, $conv238 = 0, $call242 = 0, $cond244 = 0, $30 = 0, $idxprom247 = 0, $arrayidx248 = 0, $31 = 0, $conv249 = 0, $shl250 = 0, $32 = 0, $conv252 = 0, $shr253165 = 0, $add254 = 0, $arrayidx255 = 0, $33 = 0, $and258 = 0, $shl259 = 0, $and260 = 0, $tobool261 = 0, $ptr_addr_1 = 0, $cmp228 = 0, $sub_ptr_lhs_cast267 = 0, $sub_ptr_rhs_cast268 = 0, $sub_ptr_sub269 = 0, $cmp270 = 0, $sub_ptr_lhs_cast275 = 0, $sub_ptr_rhs_cast276 = 0, $sub_ptr_sub277 = 0, $cmp278 = 0, $sub_ptr_lhs_cast283 = 0, $sub_ptr_rhs_cast284 = 0, $sub_ptr_sub285 = 0, $cmp286 = 0, $cmp292 = 0, $add_ptr296 = 0, $cmp298 = 0, $add_ptr302 = 0, $cmp304 = 0, $add_ptr308 = 0, $sub = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 95;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $and = $sub_ptr_sub & 1;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ $end_addr_0 = $end;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $and2 = $sub_ptr_sub & -2;
+ $cmp3 = ($and2 | 0) == 0;
+ if ($cmp3) {
+ $retval_0 = -1;
+ label = 95;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + $and2 | 0;
+ $end_addr_0 = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp7 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx9 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $3 & 255;
+ $cond = $conv10;
+ label = 9;
+ break;
+ case 8:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 9;
+ break;
+ case 9:
+ if (($cond | 0) == 21 | ($cond | 0) == 10) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 12) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 13) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 2) {
+ label = 14;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 23;
+ break;
+ } else if (($cond | 0) == 30) {
+ label = 33;
+ break;
+ } else if (($cond | 0) == 35) {
+ label = 34;
+ break;
+ } else if (($cond | 0) == 20) {
+ label = 35;
+ break;
+ } else if (($cond | 0) == 4) {
+ label = 36;
+ break;
+ } else if (($cond | 0) == 31) {
+ label = 44;
+ break;
+ } else if (($cond | 0) == 32) {
+ label = 45;
+ break;
+ } else if (($cond | 0) == 36) {
+ label = 55;
+ break;
+ } else if (($cond | 0) == 11) {
+ label = 56;
+ break;
+ } else if (($cond | 0) == 19) {
+ label = 57;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 58;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 60;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 62;
+ break;
+ } else if (($cond | 0) == 25 | ($cond | 0) == 26 | ($cond | 0) == 27) {
+ label = 64;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 65;
+ break;
+ } else if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ $tok_0_ph = 18;
+ label = 67;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 10:
+ $add_ptr54167 = $ptr + 2 | 0;
+ $cmp55168 = ($add_ptr54167 | 0) == ($end_addr_0 | 0);
+ if ($cmp55168) {
+ $add_ptr54_lcssa = $add_ptr54167;
+ label = 32;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $type65 = $enc + 72 | 0;
+ $4 = $type65;
+ $ptr_addr_0169 = $ptr;
+ $add_ptr54170 = $add_ptr54167;
+ label = 25;
+ break;
+ case 12:
+ $add_ptr13 = $ptr + 2 | 0;
+ $call14 = _little2_scanLit(12, $enc, $add_ptr13, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call14;
+ label = 95;
+ break;
+ case 13:
+ $add_ptr16 = $ptr + 2 | 0;
+ $call17 = _little2_scanLit(13, $enc, $add_ptr16, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call17;
+ label = 95;
+ break;
+ case 14:
+ $add_ptr19 = $ptr + 2 | 0;
+ $cmp20 = ($add_ptr19 | 0) == ($end_addr_0 | 0);
+ if ($cmp20) {
+ $retval_0 = -1;
+ label = 95;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $arrayidx24 = $ptr + 3 | 0;
+ $5 = HEAP8[$arrayidx24] | 0;
+ $cmp26 = $5 << 24 >> 24 == 0;
+ $6 = HEAP8[$add_ptr19] | 0;
+ if ($cmp26) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $idxprom29 = $6 & 255;
+ $type30 = $enc + 72 | 0;
+ $7 = $type30;
+ $arrayidx31 = $7 + $idxprom29 | 0;
+ $8 = HEAP8[$arrayidx31] | 0;
+ $conv32 = $8 & 255;
+ $cond38 = $conv32;
+ label = 18;
+ break;
+ case 17:
+ $call36 = _unicode_byte_type($5, $6) | 0;
+ $cond38 = $call36;
+ label = 18;
+ break;
+ case 18:
+ if (($cond38 | 0) == 16) {
+ label = 19;
+ break;
+ } else if (($cond38 | 0) == 15) {
+ label = 20;
+ break;
+ } else if (($cond38 | 0) == 22 | ($cond38 | 0) == 24 | ($cond38 | 0) == 29 | ($cond38 | 0) == 5 | ($cond38 | 0) == 6 | ($cond38 | 0) == 7) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 19:
+ $add_ptr40 = $ptr + 4 | 0;
+ $call41 = _little2_scanDecl($enc, $add_ptr40, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call41;
+ label = 95;
+ break;
+ case 20:
+ $add_ptr43 = $ptr + 4 | 0;
+ $call44 = _little2_scanPi($enc, $add_ptr43, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call44;
+ label = 95;
+ break;
+ case 21:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 29;
+ label = 95;
+ break;
+ case 22:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr19;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 23:
+ $add_ptr48 = $ptr + 2 | 0;
+ $cmp49 = ($add_ptr48 | 0) == ($end_addr_0 | 0);
+ if ($cmp49) {
+ label = 24;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $end_addr_0;
+ $retval_0 = -15;
+ label = 95;
+ break;
+ case 25:
+ $arrayidx59 = $ptr_addr_0169 + 3 | 0;
+ $9 = HEAP8[$arrayidx59] | 0;
+ $cmp61 = $9 << 24 >> 24 == 0;
+ $10 = HEAP8[$add_ptr54170] | 0;
+ if ($cmp61) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $idxprom64 = $10 & 255;
+ $arrayidx66 = $4 + $idxprom64 | 0;
+ $11 = HEAP8[$arrayidx66] | 0;
+ $conv67 = $11 & 255;
+ $cond73 = $conv67;
+ label = 28;
+ break;
+ case 27:
+ $call71 = _unicode_byte_type($9, $10) | 0;
+ $cond73 = $call71;
+ label = 28;
+ break;
+ case 28:
+ if (($cond73 | 0) == 21 | ($cond73 | 0) == 10) {
+ label = 29;
+ break;
+ } else if (($cond73 | 0) == 9) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 29:
+ $add_ptr54 = $add_ptr54170 + 2 | 0;
+ $cmp55 = ($add_ptr54 | 0) == ($end_addr_0 | 0);
+ if ($cmp55) {
+ $add_ptr54_lcssa = $add_ptr54;
+ label = 32;
+ break;
+ } else {
+ $ptr_addr_0169 = $add_ptr54170;
+ $add_ptr54170 = $add_ptr54;
+ label = 25;
+ break;
+ }
+ case 30:
+ $add_ptr76 = $ptr_addr_0169 + 4 | 0;
+ $cmp77 = ($add_ptr76 | 0) == ($end_addr_0 | 0);
+ if ($cmp77) {
+ label = 31;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr54170;
+ $retval_0 = 15;
+ label = 95;
+ break;
+ case 32:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr54_lcssa;
+ $retval_0 = 15;
+ label = 95;
+ break;
+ case 33:
+ $add_ptr83 = $ptr + 2 | 0;
+ $call84 = _little2_scanPercent($enc, $add_ptr83, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call84;
+ label = 95;
+ break;
+ case 34:
+ $add_ptr86 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr86;
+ $retval_0 = 38;
+ label = 95;
+ break;
+ case 35:
+ $add_ptr88 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr88;
+ $retval_0 = 25;
+ label = 95;
+ break;
+ case 36:
+ $add_ptr90 = $ptr + 2 | 0;
+ $cmp91 = ($add_ptr90 | 0) == ($end_addr_0 | 0);
+ if ($cmp91) {
+ $retval_0 = -26;
+ label = 95;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $arrayidx95 = $ptr + 3 | 0;
+ $12 = HEAP8[$arrayidx95] | 0;
+ $cmp97 = $12 << 24 >> 24 == 0;
+ if ($cmp97) {
+ label = 38;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 38:
+ $13 = HEAP8[$add_ptr90] | 0;
+ $cmp101 = $13 << 24 >> 24 == 93;
+ if ($cmp101) {
+ label = 39;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 39:
+ $add_ptr104 = $ptr + 4 | 0;
+ $cmp105 = ($add_ptr104 | 0) == ($end_addr_0 | 0);
+ if ($cmp105) {
+ $retval_0 = -1;
+ label = 95;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $arrayidx110 = $ptr + 5 | 0;
+ $14 = HEAP8[$arrayidx110] | 0;
+ $cmp112 = $14 << 24 >> 24 == 0;
+ if ($cmp112) {
+ label = 41;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 41:
+ $15 = HEAP8[$add_ptr104] | 0;
+ $cmp118 = $15 << 24 >> 24 == 62;
+ if ($cmp118) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ $add_ptr121 = $ptr + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr121;
+ $retval_0 = 34;
+ label = 95;
+ break;
+ case 43:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr90;
+ $retval_0 = 26;
+ label = 95;
+ break;
+ case 44:
+ $add_ptr125 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr125;
+ $retval_0 = 23;
+ label = 95;
+ break;
+ case 45:
+ $add_ptr127 = $ptr + 2 | 0;
+ $cmp128 = ($add_ptr127 | 0) == ($end_addr_0 | 0);
+ if ($cmp128) {
+ $retval_0 = -24;
+ label = 95;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $arrayidx132 = $ptr + 3 | 0;
+ $16 = HEAP8[$arrayidx132] | 0;
+ $cmp134 = $16 << 24 >> 24 == 0;
+ $17 = HEAP8[$add_ptr127] | 0;
+ if ($cmp134) {
+ label = 47;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 47:
+ $idxprom137 = $17 & 255;
+ $type138 = $enc + 72 | 0;
+ $18 = $type138;
+ $arrayidx139 = $18 + $idxprom137 | 0;
+ $19 = HEAP8[$arrayidx139] | 0;
+ $conv140 = $19 & 255;
+ $cond146 = $conv140;
+ label = 49;
+ break;
+ case 48:
+ $call144 = _unicode_byte_type($16, $17) | 0;
+ $cond146 = $call144;
+ label = 49;
+ break;
+ case 49:
+ if (($cond146 | 0) == 33) {
+ label = 50;
+ break;
+ } else if (($cond146 | 0) == 15) {
+ label = 51;
+ break;
+ } else if (($cond146 | 0) == 34) {
+ label = 52;
+ break;
+ } else if (($cond146 | 0) == 9 | ($cond146 | 0) == 10 | ($cond146 | 0) == 21 | ($cond146 | 0) == 11 | ($cond146 | 0) == 35 | ($cond146 | 0) == 36 | ($cond146 | 0) == 32) {
+ label = 53;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 50:
+ $add_ptr148 = $ptr + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr148;
+ $retval_0 = 36;
+ label = 95;
+ break;
+ case 51:
+ $add_ptr150 = $ptr + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr150;
+ $retval_0 = 35;
+ label = 95;
+ break;
+ case 52:
+ $add_ptr152 = $ptr + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr152;
+ $retval_0 = 37;
+ label = 95;
+ break;
+ case 53:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr127;
+ $retval_0 = 24;
+ label = 95;
+ break;
+ case 54:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr127;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 55:
+ $add_ptr156 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr156;
+ $retval_0 = 21;
+ label = 95;
+ break;
+ case 56:
+ $add_ptr158 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr158;
+ $retval_0 = 17;
+ label = 95;
+ break;
+ case 57:
+ $add_ptr160 = $ptr + 2 | 0;
+ $call161 = _little2_scanPoundName($enc, $add_ptr160, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call161;
+ label = 95;
+ break;
+ case 58:
+ $sub_ptr_lhs_cast163 = $end_addr_0;
+ $sub_ptr_sub165 = $sub_ptr_lhs_cast163 - $sub_ptr_rhs_cast | 0;
+ $cmp166 = ($sub_ptr_sub165 | 0) < 2;
+ if ($cmp166) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 60:
+ $sub_ptr_lhs_cast171 = $end_addr_0;
+ $sub_ptr_sub173 = $sub_ptr_lhs_cast171 - $sub_ptr_rhs_cast | 0;
+ $cmp174 = ($sub_ptr_sub173 | 0) < 3;
+ if ($cmp174) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 61:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 62:
+ $sub_ptr_lhs_cast179 = $end_addr_0;
+ $sub_ptr_sub181 = $sub_ptr_lhs_cast179 - $sub_ptr_rhs_cast | 0;
+ $cmp182 = ($sub_ptr_sub181 | 0) < 4;
+ if ($cmp182) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 64:
+ $tok_0_ph = 19;
+ label = 67;
+ break;
+ case 65:
+ $20 = HEAP8[$arrayidx] | 0;
+ $idxprom192 = $20 & 255;
+ $arrayidx193 = $idxprom192 + 9272 | 0;
+ $21 = HEAP8[$arrayidx193] | 0;
+ $conv194 = $21 & 255;
+ $shl = $conv194 << 3;
+ $22 = HEAP8[$ptr] | 0;
+ $conv196 = $22 & 255;
+ $shr164 = $conv196 >>> 5;
+ $add = $shr164 | $shl;
+ $arrayidx197 = 9544 + ($add << 2) | 0;
+ $23 = HEAP32[$arrayidx197 >> 2] | 0;
+ $and200 = $conv196 & 31;
+ $shl201 = 1 << $and200;
+ $and202 = $shl201 & $23;
+ $tobool203 = ($and202 | 0) == 0;
+ if ($tobool203) {
+ label = 66;
+ break;
+ } else {
+ $tok_0_ph = 18;
+ label = 67;
+ break;
+ }
+ case 66:
+ $arrayidx209 = $idxprom192 + 10824 | 0;
+ $24 = HEAP8[$arrayidx209] | 0;
+ $conv210 = $24 & 255;
+ $shl211 = $conv210 << 3;
+ $add215 = $shl211 | $shr164;
+ $arrayidx216 = 9544 + ($add215 << 2) | 0;
+ $25 = HEAP32[$arrayidx216 >> 2] | 0;
+ $and221 = $25 & $shl201;
+ $tobool222 = ($and221 | 0) == 0;
+ if ($tobool222) {
+ label = 69;
+ break;
+ } else {
+ $tok_0_ph = 19;
+ label = 67;
+ break;
+ }
+ case 67:
+ $ptr_addr_1189 = $ptr + 2 | 0;
+ $cmp228190 = ($ptr_addr_1189 | 0) == ($end_addr_0 | 0);
+ if ($cmp228190) {
+ label = 94;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $type236 = $enc + 72 | 0;
+ $26 = $type236;
+ $ptr_pn191 = $ptr;
+ $ptr_addr_1192 = $ptr_addr_1189;
+ label = 70;
+ break;
+ case 69:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 70:
+ $arrayidx230 = $ptr_pn191 + 3 | 0;
+ $27 = HEAP8[$arrayidx230] | 0;
+ $cmp232 = $27 << 24 >> 24 == 0;
+ $28 = HEAP8[$ptr_addr_1192] | 0;
+ if ($cmp232) {
+ label = 71;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 71:
+ $idxprom235 = $28 & 255;
+ $arrayidx237 = $26 + $idxprom235 | 0;
+ $29 = HEAP8[$arrayidx237] | 0;
+ $conv238 = $29 & 255;
+ $cond244 = $conv238;
+ label = 73;
+ break;
+ case 72:
+ $call242 = _unicode_byte_type($27, $28) | 0;
+ $cond244 = $call242;
+ label = 73;
+ break;
+ case 73:
+ if (($cond244 | 0) == 29) {
+ label = 74;
+ break;
+ } else if (($cond244 | 0) == 22 | ($cond244 | 0) == 24 | ($cond244 | 0) == 25 | ($cond244 | 0) == 26 | ($cond244 | 0) == 27) {
+ label = 75;
+ break;
+ } else if (($cond244 | 0) == 5) {
+ label = 77;
+ break;
+ } else if (($cond244 | 0) == 6) {
+ label = 79;
+ break;
+ } else if (($cond244 | 0) == 7) {
+ label = 81;
+ break;
+ } else if (($cond244 | 0) == 11 | ($cond244 | 0) == 32 | ($cond244 | 0) == 35 | ($cond244 | 0) == 36 | ($cond244 | 0) == 20 | ($cond244 | 0) == 30 | ($cond244 | 0) == 21 | ($cond244 | 0) == 9 | ($cond244 | 0) == 10) {
+ label = 83;
+ break;
+ } else if (($cond244 | 0) == 34) {
+ label = 84;
+ break;
+ } else if (($cond244 | 0) == 33) {
+ label = 87;
+ break;
+ } else if (($cond244 | 0) == 15) {
+ label = 90;
+ break;
+ } else {
+ label = 93;
+ break;
+ }
+ case 74:
+ $30 = HEAP8[$arrayidx230] | 0;
+ $idxprom247 = $30 & 255;
+ $arrayidx248 = $idxprom247 + 10824 | 0;
+ $31 = HEAP8[$arrayidx248] | 0;
+ $conv249 = $31 & 255;
+ $shl250 = $conv249 << 3;
+ $32 = HEAP8[$ptr_addr_1192] | 0;
+ $conv252 = $32 & 255;
+ $shr253165 = $conv252 >>> 5;
+ $add254 = $shr253165 | $shl250;
+ $arrayidx255 = 9544 + ($add254 << 2) | 0;
+ $33 = HEAP32[$arrayidx255 >> 2] | 0;
+ $and258 = $conv252 & 31;
+ $shl259 = 1 << $and258;
+ $and260 = $shl259 & $33;
+ $tobool261 = ($and260 | 0) == 0;
+ if ($tobool261) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $ptr_addr_1 = $ptr_addr_1192 + 2 | 0;
+ $cmp228 = ($ptr_addr_1 | 0) == ($end_addr_0 | 0);
+ if ($cmp228) {
+ label = 94;
+ break;
+ } else {
+ $ptr_pn191 = $ptr_addr_1192;
+ $ptr_addr_1192 = $ptr_addr_1;
+ label = 70;
+ break;
+ }
+ case 76:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 77:
+ $sub_ptr_lhs_cast267 = $end_addr_0;
+ $sub_ptr_rhs_cast268 = $ptr_addr_1192;
+ $sub_ptr_sub269 = $sub_ptr_lhs_cast267 - $sub_ptr_rhs_cast268 | 0;
+ $cmp270 = ($sub_ptr_sub269 | 0) < 2;
+ if ($cmp270) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 79:
+ $sub_ptr_lhs_cast275 = $end_addr_0;
+ $sub_ptr_rhs_cast276 = $ptr_addr_1192;
+ $sub_ptr_sub277 = $sub_ptr_lhs_cast275 - $sub_ptr_rhs_cast276 | 0;
+ $cmp278 = ($sub_ptr_sub277 | 0) < 3;
+ if ($cmp278) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 80:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 81:
+ $sub_ptr_lhs_cast283 = $end_addr_0;
+ $sub_ptr_rhs_cast284 = $ptr_addr_1192;
+ $sub_ptr_sub285 = $sub_ptr_lhs_cast283 - $sub_ptr_rhs_cast284 | 0;
+ $cmp286 = ($sub_ptr_sub285 | 0) < 4;
+ if ($cmp286) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 82:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 83:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = $tok_0_ph;
+ label = 95;
+ break;
+ case 84:
+ $cmp292 = ($tok_0_ph | 0) == 19;
+ if ($cmp292) {
+ label = 85;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 85:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 86:
+ $add_ptr296 = $ptr_pn191 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr296;
+ $retval_0 = 32;
+ label = 95;
+ break;
+ case 87:
+ $cmp298 = ($tok_0_ph | 0) == 19;
+ if ($cmp298) {
+ label = 88;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 88:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 89:
+ $add_ptr302 = $ptr_pn191 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr302;
+ $retval_0 = 31;
+ label = 95;
+ break;
+ case 90:
+ $cmp304 = ($tok_0_ph | 0) == 19;
+ if ($cmp304) {
+ label = 91;
+ break;
+ } else {
+ label = 92;
+ break;
+ }
+ case 91:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 92:
+ $add_ptr308 = $ptr_pn191 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr308;
+ $retval_0 = 30;
+ label = 95;
+ break;
+ case 93:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 94:
+ $sub = -$tok_0_ph | 0;
+ $retval_0 = $sub;
+ label = 95;
+ break;
+ case 95:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_contentTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $and = 0, $tobool = 0, $and2 = 0, $cmp3 = 0, $add_ptr = 0, $end_addr_0 = 0, $arrayidx = 0, $0 = 0, $cmp7 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx9 = 0, $3 = 0, $conv10 = 0, $call = 0, $cond = 0, $add_ptr13 = 0, $call14 = 0, $add_ptr16 = 0, $call17 = 0, $add_ptr19 = 0, $cmp20 = 0, $arrayidx24 = 0, $4 = 0, $cmp26 = 0, $5 = 0, $idxprom29 = 0, $type30 = 0, $6 = 0, $arrayidx31 = 0, $7 = 0, $conv32 = 0, $call36 = 0, $cond38 = 0, $cmp39 = 0, $add_ptr42 = 0, $add_ptr42_add_ptr19 = 0, $add_ptr45 = 0, $add_ptr47 = 0, $cmp48 = 0, $arrayidx52 = 0, $8 = 0, $cmp54 = 0, $9 = 0, $cmp58 = 0, $add_ptr62 = 0, $cmp63 = 0, $arrayidx67 = 0, $10 = 0, $cmp69 = 0, $11 = 0, $cmp74 = 0, $sub_ptr_lhs_cast80 = 0, $sub_ptr_sub82 = 0, $cmp83 = 0, $add_ptr87 = 0, $sub_ptr_lhs_cast89 = 0, $sub_ptr_sub91 = 0, $cmp92 = 0, $add_ptr96 = 0, $sub_ptr_lhs_cast98 = 0, $sub_ptr_sub100 = 0, $cmp101 = 0, $add_ptr105 = 0, $add_ptr107 = 0, $ptr_addr_1_ph = 0, $cmp10893 = 0, $type116 = 0, $12 = 0, $sub_ptr_lhs_cast126 = 0, $sub_ptr_lhs_cast135 = 0, $sub_ptr_lhs_cast144 = 0, $ptr_addr_194 = 0, $arrayidx110 = 0, $13 = 0, $cmp112 = 0, $14 = 0, $idxprom115 = 0, $arrayidx117 = 0, $15 = 0, $conv118 = 0, $call122 = 0, $cond124 = 0, $sub_ptr_rhs_cast127 = 0, $sub_ptr_sub128 = 0, $cmp129 = 0, $add_ptr133 = 0, $sub_ptr_rhs_cast136 = 0, $sub_ptr_sub137 = 0, $cmp138 = 0, $add_ptr142 = 0, $sub_ptr_rhs_cast145 = 0, $sub_ptr_sub146 = 0, $cmp147 = 0, $add_ptr151 = 0, $add_ptr153 = 0, $cmp154 = 0, $arrayidx158 = 0, $16 = 0, $cmp160 = 0, $17 = 0, $cmp166 = 0, $add_ptr171 = 0, $cmp172 = 0, $arrayidx176 = 0, $18 = 0, $cmp178 = 0, $19 = 0, $cmp184 = 0, $add_ptr194 = 0, $ptr_addr_1_be = 0, $cmp108 = 0, $ptr_addr_1_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 59;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $and = $sub_ptr_sub & 1;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ $end_addr_0 = $end;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $and2 = $sub_ptr_sub & -2;
+ $cmp3 = ($and2 | 0) == 0;
+ if ($cmp3) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + $and2 | 0;
+ $end_addr_0 = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp7 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx9 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $3 & 255;
+ $cond = $conv10;
+ label = 9;
+ break;
+ case 8:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 9;
+ break;
+ case 9:
+ if (($cond | 0) == 2) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 3) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 17;
+ break;
+ } else if (($cond | 0) == 4) {
+ label = 18;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 27;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 29;
+ break;
+ } else if (($cond | 0) == 0 | ($cond | 0) == 1 | ($cond | 0) == 8) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 10:
+ $add_ptr13 = $ptr + 2 | 0;
+ $call14 = _little2_scanLt($enc, $add_ptr13, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call14;
+ label = 59;
+ break;
+ case 11:
+ $add_ptr16 = $ptr + 2 | 0;
+ $call17 = _little2_scanRef($enc, $add_ptr16, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call17;
+ label = 59;
+ break;
+ case 12:
+ $add_ptr19 = $ptr + 2 | 0;
+ $cmp20 = ($add_ptr19 | 0) == ($end_addr_0 | 0);
+ if ($cmp20) {
+ $retval_0 = -3;
+ label = 59;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $arrayidx24 = $ptr + 3 | 0;
+ $4 = HEAP8[$arrayidx24] | 0;
+ $cmp26 = $4 << 24 >> 24 == 0;
+ $5 = HEAP8[$add_ptr19] | 0;
+ if ($cmp26) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $idxprom29 = $5 & 255;
+ $type30 = $enc + 72 | 0;
+ $6 = $type30;
+ $arrayidx31 = $6 + $idxprom29 | 0;
+ $7 = HEAP8[$arrayidx31] | 0;
+ $conv32 = $7 & 255;
+ $cond38 = $conv32;
+ label = 16;
+ break;
+ case 15:
+ $call36 = _unicode_byte_type($4, $5) | 0;
+ $cond38 = $call36;
+ label = 16;
+ break;
+ case 16:
+ $cmp39 = ($cond38 | 0) == 10;
+ $add_ptr42 = $ptr + 4 | 0;
+ $add_ptr42_add_ptr19 = $cmp39 ? $add_ptr42 : $add_ptr19;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr42_add_ptr19;
+ $retval_0 = 7;
+ label = 59;
+ break;
+ case 17:
+ $add_ptr45 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr45;
+ $retval_0 = 7;
+ label = 59;
+ break;
+ case 18:
+ $add_ptr47 = $ptr + 2 | 0;
+ $cmp48 = ($add_ptr47 | 0) == ($end_addr_0 | 0);
+ if ($cmp48) {
+ $retval_0 = -5;
+ label = 59;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $arrayidx52 = $ptr + 3 | 0;
+ $8 = HEAP8[$arrayidx52] | 0;
+ $cmp54 = $8 << 24 >> 24 == 0;
+ if ($cmp54) {
+ label = 20;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr47;
+ label = 33;
+ break;
+ }
+ case 20:
+ $9 = HEAP8[$add_ptr47] | 0;
+ $cmp58 = $9 << 24 >> 24 == 93;
+ if ($cmp58) {
+ label = 21;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr47;
+ label = 33;
+ break;
+ }
+ case 21:
+ $add_ptr62 = $ptr + 4 | 0;
+ $cmp63 = ($add_ptr62 | 0) == ($end_addr_0 | 0);
+ if ($cmp63) {
+ $retval_0 = -5;
+ label = 59;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $arrayidx67 = $ptr + 5 | 0;
+ $10 = HEAP8[$arrayidx67] | 0;
+ $cmp69 = $10 << 24 >> 24 == 0;
+ if ($cmp69) {
+ label = 23;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr47;
+ label = 33;
+ break;
+ }
+ case 23:
+ $11 = HEAP8[$add_ptr62] | 0;
+ $cmp74 = $11 << 24 >> 24 == 62;
+ if ($cmp74) {
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr47;
+ label = 33;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr62;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast80 = $end_addr_0;
+ $sub_ptr_sub82 = $sub_ptr_lhs_cast80 - $sub_ptr_rhs_cast | 0;
+ $cmp83 = ($sub_ptr_sub82 | 0) < 2;
+ if ($cmp83) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $add_ptr87 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr87;
+ label = 33;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast89 = $end_addr_0;
+ $sub_ptr_sub91 = $sub_ptr_lhs_cast89 - $sub_ptr_rhs_cast | 0;
+ $cmp92 = ($sub_ptr_sub91 | 0) < 3;
+ if ($cmp92) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $add_ptr96 = $ptr + 3 | 0;
+ $ptr_addr_1_ph = $add_ptr96;
+ label = 33;
+ break;
+ case 29:
+ $sub_ptr_lhs_cast98 = $end_addr_0;
+ $sub_ptr_sub100 = $sub_ptr_lhs_cast98 - $sub_ptr_rhs_cast | 0;
+ $cmp101 = ($sub_ptr_sub100 | 0) < 4;
+ if ($cmp101) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $add_ptr105 = $ptr + 4 | 0;
+ $ptr_addr_1_ph = $add_ptr105;
+ label = 33;
+ break;
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 32:
+ $add_ptr107 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr107;
+ label = 33;
+ break;
+ case 33:
+ $cmp10893 = ($ptr_addr_1_ph | 0) == ($end_addr_0 | 0);
+ if ($cmp10893) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_ph;
+ label = 58;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $type116 = $enc + 72 | 0;
+ $12 = $type116;
+ $sub_ptr_lhs_cast126 = $end_addr_0;
+ $sub_ptr_lhs_cast135 = $end_addr_0;
+ $sub_ptr_lhs_cast144 = $end_addr_0;
+ $ptr_addr_194 = $ptr_addr_1_ph;
+ label = 35;
+ break;
+ case 35:
+ $arrayidx110 = $ptr_addr_194 + 1 | 0;
+ $13 = HEAP8[$arrayidx110] | 0;
+ $cmp112 = $13 << 24 >> 24 == 0;
+ $14 = HEAP8[$ptr_addr_194] | 0;
+ if ($cmp112) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ $idxprom115 = $14 & 255;
+ $arrayidx117 = $12 + $idxprom115 | 0;
+ $15 = HEAP8[$arrayidx117] | 0;
+ $conv118 = $15 & 255;
+ $cond124 = $conv118;
+ label = 38;
+ break;
+ case 37:
+ $call122 = _unicode_byte_type($13, $14) | 0;
+ $cond124 = $call122;
+ label = 38;
+ break;
+ case 38:
+ if (($cond124 | 0) == 5) {
+ label = 39;
+ break;
+ } else if (($cond124 | 0) == 6) {
+ label = 42;
+ break;
+ } else if (($cond124 | 0) == 7) {
+ label = 45;
+ break;
+ } else if (($cond124 | 0) == 4) {
+ label = 48;
+ break;
+ } else if (($cond124 | 0) == 3 | ($cond124 | 0) == 2 | ($cond124 | 0) == 0 | ($cond124 | 0) == 1 | ($cond124 | 0) == 8 | ($cond124 | 0) == 9 | ($cond124 | 0) == 10) {
+ label = 55;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 39:
+ $sub_ptr_rhs_cast127 = $ptr_addr_194;
+ $sub_ptr_sub128 = $sub_ptr_lhs_cast126 - $sub_ptr_rhs_cast127 | 0;
+ $cmp129 = ($sub_ptr_sub128 | 0) < 2;
+ if ($cmp129) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 40:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_194;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 41:
+ $add_ptr133 = $ptr_addr_194 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr133;
+ label = 57;
+ break;
+ case 42:
+ $sub_ptr_rhs_cast136 = $ptr_addr_194;
+ $sub_ptr_sub137 = $sub_ptr_lhs_cast135 - $sub_ptr_rhs_cast136 | 0;
+ $cmp138 = ($sub_ptr_sub137 | 0) < 3;
+ if ($cmp138) {
+ label = 43;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 43:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_194;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 44:
+ $add_ptr142 = $ptr_addr_194 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr142;
+ label = 57;
+ break;
+ case 45:
+ $sub_ptr_rhs_cast145 = $ptr_addr_194;
+ $sub_ptr_sub146 = $sub_ptr_lhs_cast144 - $sub_ptr_rhs_cast145 | 0;
+ $cmp147 = ($sub_ptr_sub146 | 0) < 4;
+ if ($cmp147) {
+ label = 46;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 46:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_194;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 47:
+ $add_ptr151 = $ptr_addr_194 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr151;
+ label = 57;
+ break;
+ case 48:
+ $add_ptr153 = $ptr_addr_194 + 2 | 0;
+ $cmp154 = ($add_ptr153 | 0) == ($end_addr_0 | 0);
+ if ($cmp154) {
+ label = 55;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $arrayidx158 = $ptr_addr_194 + 3 | 0;
+ $16 = HEAP8[$arrayidx158] | 0;
+ $cmp160 = $16 << 24 >> 24 == 0;
+ if ($cmp160) {
+ label = 50;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr153;
+ label = 57;
+ break;
+ }
+ case 50:
+ $17 = HEAP8[$add_ptr153] | 0;
+ $cmp166 = $17 << 24 >> 24 == 93;
+ if ($cmp166) {
+ label = 51;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr153;
+ label = 57;
+ break;
+ }
+ case 51:
+ $add_ptr171 = $ptr_addr_194 + 4 | 0;
+ $cmp172 = ($add_ptr171 | 0) == ($end_addr_0 | 0);
+ if ($cmp172) {
+ label = 55;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $arrayidx176 = $ptr_addr_194 + 5 | 0;
+ $18 = HEAP8[$arrayidx176] | 0;
+ $cmp178 = $18 << 24 >> 24 == 0;
+ if ($cmp178) {
+ label = 53;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr153;
+ label = 57;
+ break;
+ }
+ case 53:
+ $19 = HEAP8[$add_ptr171] | 0;
+ $cmp184 = $19 << 24 >> 24 == 62;
+ if ($cmp184) {
+ label = 54;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr153;
+ label = 57;
+ break;
+ }
+ case 54:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr171;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 55:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_194;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 56:
+ $add_ptr194 = $ptr_addr_194 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr194;
+ label = 57;
+ break;
+ case 57:
+ $cmp108 = ($ptr_addr_1_be | 0) == ($end_addr_0 | 0);
+ if ($cmp108) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_be;
+ label = 58;
+ break;
+ } else {
+ $ptr_addr_194 = $ptr_addr_1_be;
+ label = 35;
+ break;
+ }
+ case 58:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1_lcssa;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 59:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_cdataSectionTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $and = 0, $tobool = 0, $and2 = 0, $cmp3 = 0, $add_ptr = 0, $end_addr_0 = 0, $arrayidx = 0, $0 = 0, $cmp7 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx9 = 0, $3 = 0, $conv10 = 0, $call = 0, $cond = 0, $add_ptr13 = 0, $cmp14 = 0, $arrayidx18 = 0, $4 = 0, $cmp20 = 0, $5 = 0, $cmp24 = 0, $add_ptr28 = 0, $cmp29 = 0, $arrayidx33 = 0, $6 = 0, $cmp35 = 0, $7 = 0, $cmp40 = 0, $add_ptr45 = 0, $add_ptr47 = 0, $cmp48 = 0, $arrayidx52 = 0, $8 = 0, $cmp54 = 0, $9 = 0, $idxprom57 = 0, $type58 = 0, $10 = 0, $arrayidx59 = 0, $11 = 0, $conv60 = 0, $call64 = 0, $cond66 = 0, $cmp67 = 0, $add_ptr70 = 0, $add_ptr70_add_ptr47 = 0, $add_ptr73 = 0, $sub_ptr_lhs_cast75 = 0, $sub_ptr_sub77 = 0, $cmp78 = 0, $add_ptr82 = 0, $sub_ptr_lhs_cast84 = 0, $sub_ptr_sub86 = 0, $cmp87 = 0, $add_ptr91 = 0, $sub_ptr_lhs_cast93 = 0, $sub_ptr_sub95 = 0, $cmp96 = 0, $add_ptr100 = 0, $add_ptr102 = 0, $ptr_addr_1_ph = 0, $cmp10372 = 0, $type111 = 0, $12 = 0, $sub_ptr_lhs_cast121 = 0, $sub_ptr_lhs_cast130 = 0, $sub_ptr_lhs_cast139 = 0, $ptr_addr_173 = 0, $arrayidx105 = 0, $13 = 0, $cmp107 = 0, $14 = 0, $idxprom110 = 0, $arrayidx112 = 0, $15 = 0, $conv113 = 0, $call117 = 0, $cond119 = 0, $sub_ptr_rhs_cast122 = 0, $sub_ptr_sub123 = 0, $cmp124 = 0, $add_ptr128 = 0, $sub_ptr_rhs_cast131 = 0, $sub_ptr_sub132 = 0, $cmp133 = 0, $add_ptr137 = 0, $sub_ptr_rhs_cast140 = 0, $sub_ptr_sub141 = 0, $cmp142 = 0, $add_ptr146 = 0, $add_ptr149 = 0, $ptr_addr_1_be = 0, $cmp103 = 0, $ptr_addr_1_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 50;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $and = $sub_ptr_sub & 1;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ $end_addr_0 = $end;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $and2 = $sub_ptr_sub & -2;
+ $cmp3 = ($and2 | 0) == 0;
+ if ($cmp3) {
+ $retval_0 = -1;
+ label = 50;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + $and2 | 0;
+ $end_addr_0 = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp7 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx9 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $3 & 255;
+ $cond = $conv10;
+ label = 9;
+ break;
+ case 8:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 9;
+ break;
+ case 9:
+ if (($cond | 0) == 4) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 17;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 22;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 23;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 25;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 27;
+ break;
+ } else if (($cond | 0) == 0 | ($cond | 0) == 1 | ($cond | 0) == 8) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 10:
+ $add_ptr13 = $ptr + 2 | 0;
+ $cmp14 = ($add_ptr13 | 0) == ($end_addr_0 | 0);
+ if ($cmp14) {
+ $retval_0 = -1;
+ label = 50;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $arrayidx18 = $ptr + 3 | 0;
+ $4 = HEAP8[$arrayidx18] | 0;
+ $cmp20 = $4 << 24 >> 24 == 0;
+ if ($cmp20) {
+ label = 12;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr13;
+ label = 31;
+ break;
+ }
+ case 12:
+ $5 = HEAP8[$add_ptr13] | 0;
+ $cmp24 = $5 << 24 >> 24 == 93;
+ if ($cmp24) {
+ label = 13;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr13;
+ label = 31;
+ break;
+ }
+ case 13:
+ $add_ptr28 = $ptr + 4 | 0;
+ $cmp29 = ($add_ptr28 | 0) == ($end_addr_0 | 0);
+ if ($cmp29) {
+ $retval_0 = -1;
+ label = 50;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $arrayidx33 = $ptr + 5 | 0;
+ $6 = HEAP8[$arrayidx33] | 0;
+ $cmp35 = $6 << 24 >> 24 == 0;
+ if ($cmp35) {
+ label = 15;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr13;
+ label = 31;
+ break;
+ }
+ case 15:
+ $7 = HEAP8[$add_ptr28] | 0;
+ $cmp40 = $7 << 24 >> 24 == 62;
+ if ($cmp40) {
+ label = 16;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr13;
+ label = 31;
+ break;
+ }
+ case 16:
+ $add_ptr45 = $ptr + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr45;
+ $retval_0 = 40;
+ label = 50;
+ break;
+ case 17:
+ $add_ptr47 = $ptr + 2 | 0;
+ $cmp48 = ($add_ptr47 | 0) == ($end_addr_0 | 0);
+ if ($cmp48) {
+ $retval_0 = -1;
+ label = 50;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $arrayidx52 = $ptr + 3 | 0;
+ $8 = HEAP8[$arrayidx52] | 0;
+ $cmp54 = $8 << 24 >> 24 == 0;
+ $9 = HEAP8[$add_ptr47] | 0;
+ if ($cmp54) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom57 = $9 & 255;
+ $type58 = $enc + 72 | 0;
+ $10 = $type58;
+ $arrayidx59 = $10 + $idxprom57 | 0;
+ $11 = HEAP8[$arrayidx59] | 0;
+ $conv60 = $11 & 255;
+ $cond66 = $conv60;
+ label = 21;
+ break;
+ case 20:
+ $call64 = _unicode_byte_type($8, $9) | 0;
+ $cond66 = $call64;
+ label = 21;
+ break;
+ case 21:
+ $cmp67 = ($cond66 | 0) == 10;
+ $add_ptr70 = $ptr + 4 | 0;
+ $add_ptr70_add_ptr47 = $cmp67 ? $add_ptr70 : $add_ptr47;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr70_add_ptr47;
+ $retval_0 = 7;
+ label = 50;
+ break;
+ case 22:
+ $add_ptr73 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr73;
+ $retval_0 = 7;
+ label = 50;
+ break;
+ case 23:
+ $sub_ptr_lhs_cast75 = $end_addr_0;
+ $sub_ptr_sub77 = $sub_ptr_lhs_cast75 - $sub_ptr_rhs_cast | 0;
+ $cmp78 = ($sub_ptr_sub77 | 0) < 2;
+ if ($cmp78) {
+ $retval_0 = -2;
+ label = 50;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $add_ptr82 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr82;
+ label = 31;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast84 = $end_addr_0;
+ $sub_ptr_sub86 = $sub_ptr_lhs_cast84 - $sub_ptr_rhs_cast | 0;
+ $cmp87 = ($sub_ptr_sub86 | 0) < 3;
+ if ($cmp87) {
+ $retval_0 = -2;
+ label = 50;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $add_ptr91 = $ptr + 3 | 0;
+ $ptr_addr_1_ph = $add_ptr91;
+ label = 31;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast93 = $end_addr_0;
+ $sub_ptr_sub95 = $sub_ptr_lhs_cast93 - $sub_ptr_rhs_cast | 0;
+ $cmp96 = ($sub_ptr_sub95 | 0) < 4;
+ if ($cmp96) {
+ $retval_0 = -2;
+ label = 50;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $add_ptr100 = $ptr + 4 | 0;
+ $ptr_addr_1_ph = $add_ptr100;
+ label = 31;
+ break;
+ case 29:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 50;
+ break;
+ case 30:
+ $add_ptr102 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr102;
+ label = 31;
+ break;
+ case 31:
+ $cmp10372 = ($ptr_addr_1_ph | 0) == ($end_addr_0 | 0);
+ if ($cmp10372) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_ph;
+ label = 49;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $type111 = $enc + 72 | 0;
+ $12 = $type111;
+ $sub_ptr_lhs_cast121 = $end_addr_0;
+ $sub_ptr_lhs_cast130 = $end_addr_0;
+ $sub_ptr_lhs_cast139 = $end_addr_0;
+ $ptr_addr_173 = $ptr_addr_1_ph;
+ label = 33;
+ break;
+ case 33:
+ $arrayidx105 = $ptr_addr_173 + 1 | 0;
+ $13 = HEAP8[$arrayidx105] | 0;
+ $cmp107 = $13 << 24 >> 24 == 0;
+ $14 = HEAP8[$ptr_addr_173] | 0;
+ if ($cmp107) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ $idxprom110 = $14 & 255;
+ $arrayidx112 = $12 + $idxprom110 | 0;
+ $15 = HEAP8[$arrayidx112] | 0;
+ $conv113 = $15 & 255;
+ $cond119 = $conv113;
+ label = 36;
+ break;
+ case 35:
+ $call117 = _unicode_byte_type($13, $14) | 0;
+ $cond119 = $call117;
+ label = 36;
+ break;
+ case 36:
+ if (($cond119 | 0) == 5) {
+ label = 37;
+ break;
+ } else if (($cond119 | 0) == 6) {
+ label = 40;
+ break;
+ } else if (($cond119 | 0) == 7) {
+ label = 43;
+ break;
+ } else if (($cond119 | 0) == 0 | ($cond119 | 0) == 1 | ($cond119 | 0) == 8 | ($cond119 | 0) == 9 | ($cond119 | 0) == 10 | ($cond119 | 0) == 4) {
+ label = 46;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 37:
+ $sub_ptr_rhs_cast122 = $ptr_addr_173;
+ $sub_ptr_sub123 = $sub_ptr_lhs_cast121 - $sub_ptr_rhs_cast122 | 0;
+ $cmp124 = ($sub_ptr_sub123 | 0) < 2;
+ if ($cmp124) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_173;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 39:
+ $add_ptr128 = $ptr_addr_173 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr128;
+ label = 48;
+ break;
+ case 40:
+ $sub_ptr_rhs_cast131 = $ptr_addr_173;
+ $sub_ptr_sub132 = $sub_ptr_lhs_cast130 - $sub_ptr_rhs_cast131 | 0;
+ $cmp133 = ($sub_ptr_sub132 | 0) < 3;
+ if ($cmp133) {
+ label = 41;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 41:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_173;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 42:
+ $add_ptr137 = $ptr_addr_173 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr137;
+ label = 48;
+ break;
+ case 43:
+ $sub_ptr_rhs_cast140 = $ptr_addr_173;
+ $sub_ptr_sub141 = $sub_ptr_lhs_cast139 - $sub_ptr_rhs_cast140 | 0;
+ $cmp142 = ($sub_ptr_sub141 | 0) < 4;
+ if ($cmp142) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 44:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_173;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 45:
+ $add_ptr146 = $ptr_addr_173 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr146;
+ label = 48;
+ break;
+ case 46:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_173;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 47:
+ $add_ptr149 = $ptr_addr_173 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr149;
+ label = 48;
+ break;
+ case 48:
+ $cmp103 = ($ptr_addr_1_be | 0) == ($end_addr_0 | 0);
+ if ($cmp103) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_be;
+ label = 49;
+ break;
+ } else {
+ $ptr_addr_173 = $ptr_addr_1_be;
+ label = 33;
+ break;
+ }
+ case 49:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1_lcssa;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 50:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_attributeValueTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $cmp148 = 0, $type = 0, $0 = 0, $ptr_addr_049 = 0, $arrayidx = 0, $1 = 0, $cmp2 = 0, $2 = 0, $idxprom = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $add_ptr = 0, $add_ptr9 = 0, $add_ptr11 = 0, $cmp13 = 0, $add_ptr16 = 0, $call17 = 0, $cmp21 = 0, $add_ptr24 = 0, $cmp27 = 0, $add_ptr30 = 0, $cmp31 = 0, $arrayidx35 = 0, $4 = 0, $cmp37 = 0, $5 = 0, $idxprom40 = 0, $type41 = 0, $6 = 0, $arrayidx42 = 0, $7 = 0, $conv43 = 0, $call47 = 0, $cond49 = 0, $cmp50 = 0, $add_ptr53 = 0, $add_ptr53_add_ptr30 = 0, $cmp57 = 0, $add_ptr60 = 0, $add_ptr62 = 0, $ptr_addr_0_be = 0, $cmp1 = 0, $ptr_addr_0_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 32;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp148 = ($ptr | 0) == ($end | 0);
+ if ($cmp148) {
+ $ptr_addr_0_lcssa = $ptr;
+ label = 31;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_049 = $ptr;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx = $ptr_addr_049 + 1 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $cmp2 = $1 << 24 >> 24 == 0;
+ $2 = HEAP8[$ptr_addr_049] | 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $idxprom = $2 & 255;
+ $arrayidx4 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 8;
+ break;
+ case 7:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 8;
+ break;
+ case 8:
+ if (($cond | 0) == 5) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 3) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 2) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 16;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 19;
+ break;
+ } else if (($cond | 0) == 21) {
+ label = 26;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 9:
+ $add_ptr = $ptr_addr_049 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 30;
+ break;
+ case 10:
+ $add_ptr9 = $ptr_addr_049 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr9;
+ label = 30;
+ break;
+ case 11:
+ $add_ptr11 = $ptr_addr_049 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr11;
+ label = 30;
+ break;
+ case 12:
+ $cmp13 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp13) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $add_ptr16 = $ptr_addr_049 + 2 | 0;
+ $call17 = _little2_scanRef($enc, $add_ptr16, $end, $nextTokPtr) | 0;
+ $retval_0 = $call17;
+ label = 32;
+ break;
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 15:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 16:
+ $cmp21 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp21) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $add_ptr24 = $ptr_addr_049 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr24;
+ $retval_0 = 7;
+ label = 32;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 19:
+ $cmp27 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp27) {
+ label = 20;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 20:
+ $add_ptr30 = $ptr_addr_049 + 2 | 0;
+ $cmp31 = ($add_ptr30 | 0) == ($end | 0);
+ if ($cmp31) {
+ $retval_0 = -3;
+ label = 32;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $arrayidx35 = $ptr_addr_049 + 3 | 0;
+ $4 = HEAP8[$arrayidx35] | 0;
+ $cmp37 = $4 << 24 >> 24 == 0;
+ $5 = HEAP8[$add_ptr30] | 0;
+ if ($cmp37) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $idxprom40 = $5 & 255;
+ $type41 = $enc + 72 | 0;
+ $6 = $type41;
+ $arrayidx42 = $6 + $idxprom40 | 0;
+ $7 = HEAP8[$arrayidx42] | 0;
+ $conv43 = $7 & 255;
+ $cond49 = $conv43;
+ label = 24;
+ break;
+ case 23:
+ $call47 = _unicode_byte_type($4, $5) | 0;
+ $cond49 = $call47;
+ label = 24;
+ break;
+ case 24:
+ $cmp50 = ($cond49 | 0) == 10;
+ $add_ptr53 = $ptr_addr_049 + 4 | 0;
+ $add_ptr53_add_ptr30 = $cmp50 ? $add_ptr53 : $add_ptr30;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr53_add_ptr30;
+ $retval_0 = 7;
+ label = 32;
+ break;
+ case 25:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 26:
+ $cmp57 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp57) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $add_ptr60 = $ptr_addr_049 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr60;
+ $retval_0 = 39;
+ label = 32;
+ break;
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 29:
+ $add_ptr62 = $ptr_addr_049 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr62;
+ label = 30;
+ break;
+ case 30:
+ $cmp1 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp1) {
+ $ptr_addr_0_lcssa = $ptr_addr_0_be;
+ label = 31;
+ break;
+ } else {
+ $ptr_addr_049 = $ptr_addr_0_be;
+ label = 5;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0_lcssa;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 32:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_entityValueTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $cmp149 = 0, $type = 0, $0 = 0, $ptr_addr_050 = 0, $arrayidx = 0, $1 = 0, $cmp2 = 0, $2 = 0, $idxprom = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $add_ptr = 0, $add_ptr9 = 0, $add_ptr11 = 0, $cmp13 = 0, $add_ptr16 = 0, $call17 = 0, $cmp20 = 0, $add_ptr23 = 0, $call24 = 0, $cmp25 = 0, $cond30 = 0, $cmp33 = 0, $add_ptr36 = 0, $cmp39 = 0, $add_ptr42 = 0, $cmp43 = 0, $arrayidx47 = 0, $4 = 0, $cmp49 = 0, $5 = 0, $idxprom52 = 0, $type53 = 0, $6 = 0, $arrayidx54 = 0, $7 = 0, $conv55 = 0, $call59 = 0, $cond61 = 0, $cmp62 = 0, $add_ptr65 = 0, $add_ptr65_add_ptr42 = 0, $add_ptr68 = 0, $ptr_addr_0_be = 0, $cmp1 = 0, $ptr_addr_0_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 31;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp149 = ($ptr | 0) == ($end | 0);
+ if ($cmp149) {
+ $ptr_addr_0_lcssa = $ptr;
+ label = 30;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_050 = $ptr;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx = $ptr_addr_050 + 1 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $cmp2 = $1 << 24 >> 24 == 0;
+ $2 = HEAP8[$ptr_addr_050] | 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $idxprom = $2 & 255;
+ $arrayidx4 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 8;
+ break;
+ case 7:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 8;
+ break;
+ case 8:
+ if (($cond | 0) == 5) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 3) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 30) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 18;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 21;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 9:
+ $add_ptr = $ptr_addr_050 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 29;
+ break;
+ case 10:
+ $add_ptr9 = $ptr_addr_050 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr9;
+ label = 29;
+ break;
+ case 11:
+ $add_ptr11 = $ptr_addr_050 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr11;
+ label = 29;
+ break;
+ case 12:
+ $cmp13 = ($ptr_addr_050 | 0) == ($ptr | 0);
+ if ($cmp13) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $add_ptr16 = $ptr_addr_050 + 2 | 0;
+ $call17 = _little2_scanRef($enc, $add_ptr16, $end, $nextTokPtr) | 0;
+ $retval_0 = $call17;
+ label = 31;
+ break;
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_050;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 15:
+ $cmp20 = ($ptr_addr_050 | 0) == ($ptr | 0);
+ if ($cmp20) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $add_ptr23 = $ptr_addr_050 + 2 | 0;
+ $call24 = _little2_scanPercent($enc, $add_ptr23, $end, $nextTokPtr) | 0;
+ $cmp25 = ($call24 | 0) == 22;
+ $cond30 = $cmp25 ? 0 : $call24;
+ $retval_0 = $cond30;
+ label = 31;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_050;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 18:
+ $cmp33 = ($ptr_addr_050 | 0) == ($ptr | 0);
+ if ($cmp33) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $add_ptr36 = $ptr_addr_050 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr36;
+ $retval_0 = 7;
+ label = 31;
+ break;
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_050;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 21:
+ $cmp39 = ($ptr_addr_050 | 0) == ($ptr | 0);
+ if ($cmp39) {
+ label = 22;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 22:
+ $add_ptr42 = $ptr_addr_050 + 2 | 0;
+ $cmp43 = ($add_ptr42 | 0) == ($end | 0);
+ if ($cmp43) {
+ $retval_0 = -3;
+ label = 31;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $arrayidx47 = $ptr_addr_050 + 3 | 0;
+ $4 = HEAP8[$arrayidx47] | 0;
+ $cmp49 = $4 << 24 >> 24 == 0;
+ $5 = HEAP8[$add_ptr42] | 0;
+ if ($cmp49) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $idxprom52 = $5 & 255;
+ $type53 = $enc + 72 | 0;
+ $6 = $type53;
+ $arrayidx54 = $6 + $idxprom52 | 0;
+ $7 = HEAP8[$arrayidx54] | 0;
+ $conv55 = $7 & 255;
+ $cond61 = $conv55;
+ label = 26;
+ break;
+ case 25:
+ $call59 = _unicode_byte_type($4, $5) | 0;
+ $cond61 = $call59;
+ label = 26;
+ break;
+ case 26:
+ $cmp62 = ($cond61 | 0) == 10;
+ $add_ptr65 = $ptr_addr_050 + 4 | 0;
+ $add_ptr65_add_ptr42 = $cmp62 ? $add_ptr65 : $add_ptr42;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr65_add_ptr42;
+ $retval_0 = 7;
+ label = 31;
+ break;
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_050;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 28:
+ $add_ptr68 = $ptr_addr_050 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr68;
+ label = 29;
+ break;
+ case 29:
+ $cmp1 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp1) {
+ $ptr_addr_0_lcssa = $ptr_addr_0_be;
+ label = 30;
+ break;
+ } else {
+ $ptr_addr_050 = $ptr_addr_0_be;
+ label = 5;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0_lcssa;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 31:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_nameMatchesAscii($enc, $ptr1, $end1, $ptr2) {
+ $enc = $enc | 0;
+ $ptr1 = $ptr1 | 0;
+ $end1 = $end1 | 0;
+ $ptr2 = $ptr2 | 0;
+ var $0 = 0, $tobool7 = 0, $cmp8 = 0, $cmp11 = 0, $1 = 0, $ptr2_addr_010 = 0, $ptr1_addr_09 = 0, $arrayidx = 0, $2 = 0, $cmp1 = 0, $3 = 0, $cmp6 = 0, $add_ptr = 0, $incdec_ptr = 0, $4 = 0, $tobool = 0, $cmp = 0, $cmp_lcssa = 0, $conv11 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$ptr2] | 0;
+ $tobool7 = $0 << 24 >> 24 == 0;
+ $cmp8 = ($ptr1 | 0) == ($end1 | 0);
+ if ($tobool7) {
+ $cmp_lcssa = $cmp8;
+ label = 7;
+ break;
+ } else {
+ $ptr1_addr_09 = $ptr1;
+ $ptr2_addr_010 = $ptr2;
+ $1 = $0;
+ $cmp11 = $cmp8;
+ label = 3;
+ break;
+ }
+ case 3:
+ if ($cmp11) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $arrayidx = $ptr1_addr_09 + 1 | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $2 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ }
+ case 5:
+ $3 = HEAP8[$ptr1_addr_09] | 0;
+ $cmp6 = $3 << 24 >> 24 == $1 << 24 >> 24;
+ if ($cmp6) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ }
+ case 6:
+ $add_ptr = $ptr1_addr_09 + 2 | 0;
+ $incdec_ptr = $ptr2_addr_010 + 1 | 0;
+ $4 = HEAP8[$incdec_ptr] | 0;
+ $tobool = $4 << 24 >> 24 == 0;
+ $cmp = ($add_ptr | 0) == ($end1 | 0);
+ if ($tobool) {
+ $cmp_lcssa = $cmp;
+ label = 7;
+ break;
+ } else {
+ $ptr1_addr_09 = $add_ptr;
+ $ptr2_addr_010 = $incdec_ptr;
+ $1 = $4;
+ $cmp11 = $cmp;
+ label = 3;
+ break;
+ }
+ case 7:
+ $conv11 = $cmp_lcssa & 1;
+ $retval_0 = $conv11;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_predefinedEntityName($enc, $ptr, $end) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $div = 0, $arrayidx = 0, $0 = 0, $cmp = 0, $add_ptr = 0, $1 = 0, $cmp5 = 0, $arrayidx7 = 0, $2 = 0, $cmp9 = 0, $3 = 0, $conv12 = 0, $arrayidx16 = 0, $4 = 0, $cmp18 = 0, $5 = 0, $cmp23 = 0, $arrayidx27 = 0, $6 = 0, $cmp29 = 0, $add_ptr26 = 0, $7 = 0, $cmp34 = 0, $arrayidx38 = 0, $8 = 0, $cmp40 = 0, $add_ptr37 = 0, $9 = 0, $cmp45 = 0, $arrayidx52 = 0, $10 = 0, $cmp54 = 0, $11 = 0, $conv58 = 0, $arrayidx64 = 0, $12 = 0, $cmp66 = 0, $add_ptr63 = 0, $13 = 0, $cmp71 = 0, $arrayidx75 = 0, $14 = 0, $cmp77 = 0, $add_ptr74 = 0, $15 = 0, $cmp82 = 0, $arrayidx86 = 0, $16 = 0, $cmp88 = 0, $add_ptr85 = 0, $17 = 0, $cmp93 = 0, $arrayidx101 = 0, $18 = 0, $cmp103 = 0, $add_ptr100 = 0, $19 = 0, $cmp108 = 0, $arrayidx112 = 0, $20 = 0, $cmp114 = 0, $add_ptr111 = 0, $21 = 0, $cmp119 = 0, $arrayidx123 = 0, $22 = 0, $cmp125 = 0, $add_ptr122 = 0, $23 = 0, $cmp130 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $div = ($sub_ptr_sub | 0) / 2 & -1;
+ if (($div | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($div | 0) == 3) {
+ label = 8;
+ break;
+ } else if (($div | 0) == 4) {
+ label = 14;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 3 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 4:
+ $add_ptr = $ptr + 2 | 0;
+ $1 = HEAP8[$add_ptr] | 0;
+ $cmp5 = $1 << 24 >> 24 == 116;
+ if ($cmp5) {
+ label = 5;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 5:
+ $arrayidx7 = $ptr + 1 | 0;
+ $2 = HEAP8[$arrayidx7] | 0;
+ $cmp9 = $2 << 24 >> 24 == 0;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 6:
+ $3 = HEAP8[$ptr] | 0;
+ $conv12 = $3 << 24 >> 24;
+ if (($conv12 | 0) == 103) {
+ label = 7;
+ break;
+ } else if (($conv12 | 0) == 108) {
+ $retval_0 = 60;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 7:
+ $retval_0 = 62;
+ label = 29;
+ break;
+ case 8:
+ $arrayidx16 = $ptr + 1 | 0;
+ $4 = HEAP8[$arrayidx16] | 0;
+ $cmp18 = $4 << 24 >> 24 == 0;
+ if ($cmp18) {
+ label = 9;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 9:
+ $5 = HEAP8[$ptr] | 0;
+ $cmp23 = $5 << 24 >> 24 == 97;
+ if ($cmp23) {
+ label = 10;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 10:
+ $arrayidx27 = $ptr + 3 | 0;
+ $6 = HEAP8[$arrayidx27] | 0;
+ $cmp29 = $6 << 24 >> 24 == 0;
+ if ($cmp29) {
+ label = 11;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 11:
+ $add_ptr26 = $ptr + 2 | 0;
+ $7 = HEAP8[$add_ptr26] | 0;
+ $cmp34 = $7 << 24 >> 24 == 109;
+ if ($cmp34) {
+ label = 12;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 12:
+ $arrayidx38 = $ptr + 5 | 0;
+ $8 = HEAP8[$arrayidx38] | 0;
+ $cmp40 = $8 << 24 >> 24 == 0;
+ if ($cmp40) {
+ label = 13;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 13:
+ $add_ptr37 = $ptr + 4 | 0;
+ $9 = HEAP8[$add_ptr37] | 0;
+ $cmp45 = $9 << 24 >> 24 == 112;
+ if ($cmp45) {
+ $retval_0 = 38;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 14:
+ $arrayidx52 = $ptr + 1 | 0;
+ $10 = HEAP8[$arrayidx52] | 0;
+ $cmp54 = $10 << 24 >> 24 == 0;
+ if ($cmp54) {
+ label = 15;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 15:
+ $11 = HEAP8[$ptr] | 0;
+ $conv58 = $11 << 24 >> 24;
+ if (($conv58 | 0) == 113) {
+ label = 16;
+ break;
+ } else if (($conv58 | 0) == 97) {
+ label = 22;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 16:
+ $arrayidx64 = $ptr + 3 | 0;
+ $12 = HEAP8[$arrayidx64] | 0;
+ $cmp66 = $12 << 24 >> 24 == 0;
+ if ($cmp66) {
+ label = 17;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 17:
+ $add_ptr63 = $ptr + 2 | 0;
+ $13 = HEAP8[$add_ptr63] | 0;
+ $cmp71 = $13 << 24 >> 24 == 117;
+ if ($cmp71) {
+ label = 18;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 18:
+ $arrayidx75 = $ptr + 5 | 0;
+ $14 = HEAP8[$arrayidx75] | 0;
+ $cmp77 = $14 << 24 >> 24 == 0;
+ if ($cmp77) {
+ label = 19;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 19:
+ $add_ptr74 = $ptr + 4 | 0;
+ $15 = HEAP8[$add_ptr74] | 0;
+ $cmp82 = $15 << 24 >> 24 == 111;
+ if ($cmp82) {
+ label = 20;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 20:
+ $arrayidx86 = $ptr + 7 | 0;
+ $16 = HEAP8[$arrayidx86] | 0;
+ $cmp88 = $16 << 24 >> 24 == 0;
+ if ($cmp88) {
+ label = 21;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 21:
+ $add_ptr85 = $ptr + 6 | 0;
+ $17 = HEAP8[$add_ptr85] | 0;
+ $cmp93 = $17 << 24 >> 24 == 116;
+ if ($cmp93) {
+ $retval_0 = 34;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 22:
+ $arrayidx101 = $ptr + 3 | 0;
+ $18 = HEAP8[$arrayidx101] | 0;
+ $cmp103 = $18 << 24 >> 24 == 0;
+ if ($cmp103) {
+ label = 23;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 23:
+ $add_ptr100 = $ptr + 2 | 0;
+ $19 = HEAP8[$add_ptr100] | 0;
+ $cmp108 = $19 << 24 >> 24 == 112;
+ if ($cmp108) {
+ label = 24;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 24:
+ $arrayidx112 = $ptr + 5 | 0;
+ $20 = HEAP8[$arrayidx112] | 0;
+ $cmp114 = $20 << 24 >> 24 == 0;
+ if ($cmp114) {
+ label = 25;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 25:
+ $add_ptr111 = $ptr + 4 | 0;
+ $21 = HEAP8[$add_ptr111] | 0;
+ $cmp119 = $21 << 24 >> 24 == 111;
+ if ($cmp119) {
+ label = 26;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 26:
+ $arrayidx123 = $ptr + 7 | 0;
+ $22 = HEAP8[$arrayidx123] | 0;
+ $cmp125 = $22 << 24 >> 24 == 0;
+ if ($cmp125) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $add_ptr122 = $ptr + 6 | 0;
+ $23 = HEAP8[$add_ptr122] | 0;
+ $cmp130 = $23 << 24 >> 24 == 115;
+ if ($cmp130) {
+ $retval_0 = 39;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 29:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_sameName($enc, $ptr1, $ptr2) {
+ $enc = $enc | 0;
+ $ptr1 = $ptr1 | 0;
+ $ptr2 = $ptr2 | 0;
+ var $type = 0, $0 = 0, $ptr1_addr_0 = 0, $ptr2_addr_0 = 0, $arrayidx = 0, $1 = 0, $cmp = 0, $2 = 0, $idxprom = 0, $arrayidx2 = 0, $3 = 0, $conv3 = 0, $call = 0, $cond = 0, $4 = 0, $incdec_ptr7 = 0, $5 = 0, $cmp9 = 0, $ptr1_addr_1 = 0, $ptr2_addr_1 = 0, $incdec_ptr12 = 0, $6 = 0, $incdec_ptr14 = 0, $7 = 0, $cmp16 = 0, $ptr1_addr_2 = 0, $ptr2_addr_2 = 0, $8 = 0, $9 = 0, $cmp25 = 0, $incdec_ptr23 = 0, $incdec_ptr21 = 0, $10 = 0, $11 = 0, $cmp33 = 0, $12 = 0, $13 = 0, $cmp42 = 0, $incdec_ptr38 = 0, $14 = 0, $15 = 0, $cmp50 = 0, $ptr1_addr_0_pn = 0, $ptr2_addr_0_pn = 0, $ptr2_addr_0_be = 0, $ptr1_addr_0_be = 0, $arrayidx54 = 0, $16 = 0, $cmp56 = 0, $17 = 0, $idxprom59 = 0, $type60 = 0, $18 = 0, $arrayidx61 = 0, $19 = 0, $conv62 = 0, $call66 = 0, $cond68 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr2_addr_0 = $ptr2;
+ $ptr1_addr_0 = $ptr1;
+ label = 3;
+ break;
+ case 3:
+ $arrayidx = $ptr1_addr_0 + 1 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ $2 = HEAP8[$ptr1_addr_0] | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $2 & 255;
+ $arrayidx2 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx2] | 0;
+ $conv3 = $3 & 255;
+ $cond = $conv3;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 7) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 6) {
+ $ptr2_addr_1 = $ptr2_addr_0;
+ $ptr1_addr_1 = $ptr1_addr_0;
+ label = 8;
+ break;
+ } else if (($cond | 0) == 5) {
+ $ptr2_addr_2 = $ptr2_addr_0;
+ $ptr1_addr_2 = $ptr1_addr_0;
+ label = 9;
+ break;
+ } else if (($cond | 0) == 29 | ($cond | 0) == 22 | ($cond | 0) == 24 | ($cond | 0) == 25 | ($cond | 0) == 26 | ($cond | 0) == 27) {
+ label = 11;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 7:
+ $4 = HEAP8[$ptr1_addr_0] | 0;
+ $incdec_ptr7 = $ptr2_addr_0 + 1 | 0;
+ $5 = HEAP8[$ptr2_addr_0] | 0;
+ $cmp9 = $4 << 24 >> 24 == $5 << 24 >> 24;
+ if ($cmp9) {
+ $ptr2_addr_1 = $incdec_ptr7;
+ $ptr1_addr_1 = $arrayidx;
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 8:
+ $incdec_ptr12 = $ptr1_addr_1 + 1 | 0;
+ $6 = HEAP8[$ptr1_addr_1] | 0;
+ $incdec_ptr14 = $ptr2_addr_1 + 1 | 0;
+ $7 = HEAP8[$ptr2_addr_1] | 0;
+ $cmp16 = $6 << 24 >> 24 == $7 << 24 >> 24;
+ if ($cmp16) {
+ $ptr2_addr_2 = $incdec_ptr14;
+ $ptr1_addr_2 = $incdec_ptr12;
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 9:
+ $8 = HEAP8[$ptr1_addr_2] | 0;
+ $9 = HEAP8[$ptr2_addr_2] | 0;
+ $cmp25 = $8 << 24 >> 24 == $9 << 24 >> 24;
+ if ($cmp25) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 10:
+ $incdec_ptr23 = $ptr2_addr_2 + 1 | 0;
+ $incdec_ptr21 = $ptr1_addr_2 + 1 | 0;
+ $10 = HEAP8[$incdec_ptr21] | 0;
+ $11 = HEAP8[$incdec_ptr23] | 0;
+ $cmp33 = $10 << 24 >> 24 == $11 << 24 >> 24;
+ if ($cmp33) {
+ $ptr2_addr_0_pn = $ptr2_addr_2;
+ $ptr1_addr_0_pn = $ptr1_addr_2;
+ label = 13;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 11:
+ $12 = HEAP8[$ptr2_addr_0] | 0;
+ $13 = HEAP8[$ptr1_addr_0] | 0;
+ $cmp42 = $12 << 24 >> 24 == $13 << 24 >> 24;
+ if ($cmp42) {
+ label = 12;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 12:
+ $incdec_ptr38 = $ptr2_addr_0 + 1 | 0;
+ $14 = HEAP8[$incdec_ptr38] | 0;
+ $15 = HEAP8[$arrayidx] | 0;
+ $cmp50 = $14 << 24 >> 24 == $15 << 24 >> 24;
+ if ($cmp50) {
+ $ptr2_addr_0_pn = $ptr2_addr_0;
+ $ptr1_addr_0_pn = $ptr1_addr_0;
+ label = 13;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 13:
+ $ptr2_addr_0_be = $ptr2_addr_0_pn + 2 | 0;
+ $ptr1_addr_0_be = $ptr1_addr_0_pn + 2 | 0;
+ $ptr2_addr_0 = $ptr2_addr_0_be;
+ $ptr1_addr_0 = $ptr1_addr_0_be;
+ label = 3;
+ break;
+ case 14:
+ $arrayidx54 = $ptr2_addr_0 + 1 | 0;
+ $16 = HEAP8[$arrayidx54] | 0;
+ $cmp56 = $16 << 24 >> 24 == 0;
+ $17 = HEAP8[$ptr2_addr_0] | 0;
+ if ($cmp56) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $idxprom59 = $17 & 255;
+ $type60 = $enc + 72 | 0;
+ $18 = $type60;
+ $arrayidx61 = $18 + $idxprom59 | 0;
+ $19 = HEAP8[$arrayidx61] | 0;
+ $conv62 = $19 & 255;
+ $cond68 = $conv62;
+ label = 17;
+ break;
+ case 16:
+ $call66 = _unicode_byte_type($16, $17) | 0;
+ $cond68 = $call66;
+ label = 17;
+ break;
+ case 17:
+ if (($cond68 | 0) == 5 | ($cond68 | 0) == 6 | ($cond68 | 0) == 7 | ($cond68 | 0) == 29 | ($cond68 | 0) == 22 | ($cond68 | 0) == 24 | ($cond68 | 0) == 25 | ($cond68 | 0) == 26 | ($cond68 | 0) == 27) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $retval_0 = 1;
+ label = 19;
+ break;
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_nameLength($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $type = 0, $0 = 0, $ptr_addr_0 = 0, $arrayidx = 0, $1 = 0, $cmp = 0, $2 = 0, $idxprom = 0, $arrayidx2 = 0, $3 = 0, $conv3 = 0, $call = 0, $cond = 0, $add_ptr = 0, $add_ptr7 = 0, $add_ptr9 = 0, $add_ptr11 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_0 = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $arrayidx = $ptr_addr_0 + 1 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ $2 = HEAP8[$ptr_addr_0] | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $2 & 255;
+ $arrayidx2 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx2] | 0;
+ $conv3 = $3 & 255;
+ $cond = $conv3;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 5) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 29 | ($cond | 0) == 22 | ($cond | 0) == 24 | ($cond | 0) == 25 | ($cond | 0) == 26 | ($cond | 0) == 27) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $add_ptr = $ptr_addr_0 + 2 | 0;
+ $ptr_addr_0 = $add_ptr;
+ label = 3;
+ break;
+ case 8:
+ $add_ptr7 = $ptr_addr_0 + 3 | 0;
+ $ptr_addr_0 = $add_ptr7;
+ label = 3;
+ break;
+ case 9:
+ $add_ptr9 = $ptr_addr_0 + 4 | 0;
+ $ptr_addr_0 = $add_ptr9;
+ label = 3;
+ break;
+ case 10:
+ $add_ptr11 = $ptr_addr_0 + 2 | 0;
+ $ptr_addr_0 = $add_ptr11;
+ label = 3;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $ptr_addr_0;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ return $sub_ptr_sub | 0;
+ }
+ return 0;
+}
+function _little2_skipS($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $type = 0, $0 = 0, $ptr_addr_0 = 0, $arrayidx = 0, $1 = 0, $cmp = 0, $2 = 0, $idxprom = 0, $arrayidx2 = 0, $3 = 0, $conv3 = 0, $call = 0, $cond = 0, $add_ptr = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_0 = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $arrayidx = $ptr_addr_0 + 1 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ $2 = HEAP8[$ptr_addr_0] | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $2 & 255;
+ $arrayidx2 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx2] | 0;
+ $conv3 = $3 & 255;
+ $cond = $conv3;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 10 | ($cond | 0) == 9 | ($cond | 0) == 21) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $add_ptr = $ptr_addr_0 + 2 | 0;
+ $ptr_addr_0 = $add_ptr;
+ label = 3;
+ break;
+ case 8:
+ return $ptr_addr_0 | 0;
+ }
+ return 0;
+}
+function _little2_getAtts($enc, $ptr, $attsMax, $atts) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $attsMax = $attsMax | 0;
+ $atts = $atts | 0;
+ var $type = 0, $0 = 0, $type161 = 0, $1 = 0, $ptr_pn = 0, $state_0 = 0, $nAtts_0 = 0, $open_0 = 0, $ptr_addr_0 = 0, $arrayidx = 0, $2 = 0, $cmp = 0, $3 = 0, $idxprom = 0, $arrayidx2 = 0, $4 = 0, $conv3 = 0, $call = 0, $cond = 0, $cmp6 = 0, $cmp8 = 0, $name = 0, $normalized = 0, $cmp16 = 0, $cmp19 = 0, $name23 = 0, $normalized25 = 0, $cmp30 = 0, $cmp33 = 0, $name37 = 0, $normalized39 = 0, $state_3 = 0, $add_ptr42 = 0, $cmp44 = 0, $cmp47 = 0, $name51 = 0, $normalized53 = 0, $cmp57 = 0, $cmp60 = 0, $add_ptr63 = 0, $valuePtr = 0, $cmp66 = 0, $cmp69 = 0, $valueEnd = 0, $inc = 0, $cmp77 = 0, $cmp80 = 0, $add_ptr83 = 0, $valuePtr85 = 0, $cmp88 = 0, $cmp91 = 0, $valueEnd95 = 0, $inc97 = 0, $cmp101 = 0, $normalized105 = 0, $cmp108 = 0, $cmp112 = 0, $cmp114 = 0, $or_cond = 0, $normalized118 = 0, $5 = 0, $tobool = 0, $valuePtr122 = 0, $6 = 0, $cmp123 = 0, $7 = 0, $cmp127 = 0, $8 = 0, $phitmp = 0, $add_ptr138 = 0, $arrayidx139 = 0, $9 = 0, $cmp141 = 0, $10 = 0, $phitmp93 = 0, $_pr = 0, $cmp156 = 0, $11 = 0, $idxprom160 = 0, $arrayidx162 = 0, $12 = 0, $conv163 = 0, $13 = 0, $14 = 0, $call169 = 0, $cond171 = 0, $cmp172 = 0, $cmp180 = 0, $cmp184 = 0, $cmp187 = 0, $or_cond94 = 0, $normalized191 = 0, $cmp195 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $type161 = $enc + 72 | 0;
+ $1 = $type161;
+ $open_0 = 0;
+ $nAtts_0 = 0;
+ $state_0 = 1;
+ $ptr_pn = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $ptr_addr_0 = $ptr_pn + 2 | 0;
+ $arrayidx = $ptr_pn + 3 | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $cmp = $2 << 24 >> 24 == 0;
+ $3 = HEAP8[$ptr_addr_0] | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $3 & 255;
+ $arrayidx2 = $0 + $idxprom | 0;
+ $4 = HEAP8[$arrayidx2] | 0;
+ $conv3 = $4 & 255;
+ $cond = $conv3;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($2, $3) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 5) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 29 | ($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 17;
+ break;
+ } else if (($cond | 0) == 12) {
+ label = 20;
+ break;
+ } else if (($cond | 0) == 13) {
+ label = 27;
+ break;
+ } else if (($cond | 0) == 3) {
+ label = 34;
+ break;
+ } else if (($cond | 0) == 21) {
+ label = 36;
+ break;
+ } else if (($cond | 0) == 9 | ($cond | 0) == 10) {
+ label = 49;
+ break;
+ } else if (($cond | 0) == 11 | ($cond | 0) == 17) {
+ label = 52;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 7:
+ $cmp6 = ($state_0 | 0) == 0;
+ if ($cmp6) {
+ label = 8;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 8:
+ $cmp8 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp8) {
+ label = 9;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 9:
+ $name = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name >> 2] = $ptr_addr_0;
+ $normalized = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized] = 1;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 10:
+ $cmp16 = ($state_0 | 0) == 0;
+ if ($cmp16) {
+ label = 11;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $arrayidx;
+ label = 3;
+ break;
+ }
+ case 11:
+ $cmp19 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp19) {
+ label = 12;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $arrayidx;
+ label = 3;
+ break;
+ }
+ case 12:
+ $name23 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name23 >> 2] = $ptr_addr_0;
+ $normalized25 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized25] = 1;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $arrayidx;
+ label = 3;
+ break;
+ case 13:
+ $cmp30 = ($state_0 | 0) == 0;
+ if ($cmp30) {
+ label = 14;
+ break;
+ } else {
+ $state_3 = $state_0;
+ label = 16;
+ break;
+ }
+ case 14:
+ $cmp33 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp33) {
+ label = 15;
+ break;
+ } else {
+ $state_3 = 1;
+ label = 16;
+ break;
+ }
+ case 15:
+ $name37 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name37 >> 2] = $ptr_addr_0;
+ $normalized39 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized39] = 1;
+ $state_3 = 1;
+ label = 16;
+ break;
+ case 16:
+ $add_ptr42 = $ptr_pn + 4 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_3;
+ $ptr_pn = $add_ptr42;
+ label = 3;
+ break;
+ case 17:
+ $cmp44 = ($state_0 | 0) == 0;
+ if ($cmp44) {
+ label = 18;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 18:
+ $cmp47 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp47) {
+ label = 19;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 19:
+ $name51 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name51 >> 2] = $ptr_addr_0;
+ $normalized53 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized53] = 1;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 20:
+ $cmp57 = ($state_0 | 0) == 2;
+ if ($cmp57) {
+ label = 23;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $cmp60 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp60) {
+ label = 22;
+ break;
+ } else {
+ $open_0 = 12;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 22:
+ $add_ptr63 = $ptr_pn + 4 | 0;
+ $valuePtr = $atts + ($nAtts_0 << 4) + 4 | 0;
+ HEAP32[$valuePtr >> 2] = $add_ptr63;
+ $open_0 = 12;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 23:
+ $cmp66 = ($open_0 | 0) == 12;
+ if ($cmp66) {
+ label = 24;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 24:
+ $cmp69 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp69) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $valueEnd = $atts + ($nAtts_0 << 4) + 8 | 0;
+ HEAP32[$valueEnd >> 2] = $ptr_addr_0;
+ label = 26;
+ break;
+ case 26:
+ $inc = $nAtts_0 + 1 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $inc;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 27:
+ $cmp77 = ($state_0 | 0) == 2;
+ if ($cmp77) {
+ label = 30;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $cmp80 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp80) {
+ label = 29;
+ break;
+ } else {
+ $open_0 = 13;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 29:
+ $add_ptr83 = $ptr_pn + 4 | 0;
+ $valuePtr85 = $atts + ($nAtts_0 << 4) + 4 | 0;
+ HEAP32[$valuePtr85 >> 2] = $add_ptr83;
+ $open_0 = 13;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 30:
+ $cmp88 = ($open_0 | 0) == 13;
+ if ($cmp88) {
+ label = 31;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 31:
+ $cmp91 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp91) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 32:
+ $valueEnd95 = $atts + ($nAtts_0 << 4) + 8 | 0;
+ HEAP32[$valueEnd95 >> 2] = $ptr_addr_0;
+ label = 33;
+ break;
+ case 33:
+ $inc97 = $nAtts_0 + 1 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $inc97;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 34:
+ $cmp101 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp101) {
+ label = 35;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 35:
+ $normalized105 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized105] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 36:
+ $cmp108 = ($state_0 | 0) == 1;
+ if ($cmp108) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $cmp112 = ($state_0 | 0) == 2;
+ $cmp114 = ($nAtts_0 | 0) < ($attsMax | 0);
+ $or_cond = $cmp112 & $cmp114;
+ if ($or_cond) {
+ label = 38;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 38:
+ $normalized118 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ $5 = HEAP8[$normalized118] | 0;
+ $tobool = $5 << 24 >> 24 == 0;
+ if ($tobool) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $valuePtr122 = $atts + ($nAtts_0 << 4) + 4 | 0;
+ $6 = HEAP32[$valuePtr122 >> 2] | 0;
+ $cmp123 = ($ptr_addr_0 | 0) == ($6 | 0);
+ if ($cmp123) {
+ label = 48;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $7 = HEAP8[$arrayidx] | 0;
+ $cmp127 = $7 << 24 >> 24 == 0;
+ if ($cmp127) {
+ label = 41;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 41:
+ $8 = HEAP8[$ptr_addr_0] | 0;
+ $phitmp = $8 << 24 >> 24 == 32;
+ if ($phitmp) {
+ label = 42;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 42:
+ $add_ptr138 = $ptr_pn + 4 | 0;
+ $arrayidx139 = $ptr_pn + 5 | 0;
+ $9 = HEAP8[$arrayidx139] | 0;
+ $cmp141 = $9 << 24 >> 24 == 0;
+ $10 = HEAP8[$add_ptr138] | 0;
+ if ($cmp141) {
+ label = 43;
+ break;
+ } else {
+ $14 = $9;
+ $13 = $10;
+ label = 46;
+ break;
+ }
+ case 43:
+ $phitmp93 = $10 << 24 >> 24 == 32;
+ if ($phitmp93) {
+ label = 48;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $_pr = HEAP8[$arrayidx139] | 0;
+ $cmp156 = $_pr << 24 >> 24 == 0;
+ $11 = HEAP8[$add_ptr138] | 0;
+ if ($cmp156) {
+ label = 45;
+ break;
+ } else {
+ $14 = $_pr;
+ $13 = $11;
+ label = 46;
+ break;
+ }
+ case 45:
+ $idxprom160 = $11 & 255;
+ $arrayidx162 = $1 + $idxprom160 | 0;
+ $12 = HEAP8[$arrayidx162] | 0;
+ $conv163 = $12 & 255;
+ $cond171 = $conv163;
+ label = 47;
+ break;
+ case 46:
+ $call169 = _unicode_byte_type($14, $13) | 0;
+ $cond171 = $call169;
+ label = 47;
+ break;
+ case 47:
+ $cmp172 = ($cond171 | 0) == ($open_0 | 0);
+ if ($cmp172) {
+ label = 48;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 48:
+ HEAP8[$normalized118] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 49:
+ $cmp180 = ($state_0 | 0) == 1;
+ if ($cmp180) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $cmp184 = ($state_0 | 0) == 2;
+ $cmp187 = ($nAtts_0 | 0) < ($attsMax | 0);
+ $or_cond94 = $cmp184 & $cmp187;
+ if ($or_cond94) {
+ label = 51;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 51:
+ $normalized191 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized191] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 52:
+ $cmp195 = ($state_0 | 0) == 2;
+ if ($cmp195) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ return $nAtts_0 | 0;
+ }
+ return 0;
+}
+function _little2_charRefNumber($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $add_ptr = 0, $arrayidx = 0, $0 = 0, $cmp = 0, $1 = 0, $cmp4 = 0, $add_ptr6 = 0, $result_0 = 0, $ptr_addr_0 = 0, $arrayidx7 = 0, $2 = 0, $cmp9 = 0, $3 = 0, $phitmp28 = 0, $_pr = 0, $cmp17 = 0, $4 = 0, $conv20 = 0, $shl = 0, $sub = 0, $or = 0, $shl22 = 0, $add = 0, $add24 = 0, $shl26 = 0, $add28 = 0, $add29 = 0, $result_1 = 0, $cmp30 = 0, $add_ptr33 = 0, $result_2 = 0, $ptr_addr_1 = 0, $arrayidx35 = 0, $5 = 0, $cmp37 = 0, $6 = 0, $phitmp = 0, $_pr30 = 0, $cmp50 = 0, $7 = 0, $conv54 = 0, $phitmp27 = 0, $cond57 = 0, $mul = 0, $add59 = 0, $cmp60 = 0, $add_ptr65 = 0, $result_3 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add_ptr = $ptr + 4 | 0;
+ $arrayidx = $ptr + 5 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $ptr_addr_1 = $add_ptr;
+ $result_2 = 0;
+ label = 13;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$add_ptr] | 0;
+ $cmp4 = $1 << 24 >> 24 == 120;
+ if ($cmp4) {
+ label = 4;
+ break;
+ } else {
+ $ptr_addr_1 = $add_ptr;
+ $result_2 = 0;
+ label = 13;
+ break;
+ }
+ case 4:
+ $add_ptr6 = $ptr + 6 | 0;
+ $ptr_addr_0 = $add_ptr6;
+ $result_0 = 0;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx7 = $ptr_addr_0 + 1 | 0;
+ $2 = HEAP8[$arrayidx7] | 0;
+ $cmp9 = $2 << 24 >> 24 == 0;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ $result_1 = $result_0;
+ label = 12;
+ break;
+ }
+ case 6:
+ $3 = HEAP8[$ptr_addr_0] | 0;
+ $phitmp28 = $3 << 24 >> 24 == 59;
+ if ($phitmp28) {
+ $result_3 = $result_0;
+ label = 18;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $_pr = HEAP8[$arrayidx7] | 0;
+ $cmp17 = $_pr << 24 >> 24 == 0;
+ if ($cmp17) {
+ label = 8;
+ break;
+ } else {
+ $result_1 = $result_0;
+ label = 12;
+ break;
+ }
+ case 8:
+ $4 = HEAP8[$ptr_addr_0] | 0;
+ $conv20 = $4 << 24 >> 24;
+ if (($conv20 | 0) == 48 | ($conv20 | 0) == 49 | ($conv20 | 0) == 50 | ($conv20 | 0) == 51 | ($conv20 | 0) == 52 | ($conv20 | 0) == 53 | ($conv20 | 0) == 54 | ($conv20 | 0) == 55 | ($conv20 | 0) == 56 | ($conv20 | 0) == 57) {
+ label = 9;
+ break;
+ } else if (($conv20 | 0) == 65 | ($conv20 | 0) == 66 | ($conv20 | 0) == 67 | ($conv20 | 0) == 68 | ($conv20 | 0) == 69 | ($conv20 | 0) == 70) {
+ label = 10;
+ break;
+ } else if (($conv20 | 0) == 97 | ($conv20 | 0) == 98 | ($conv20 | 0) == 99 | ($conv20 | 0) == 100 | ($conv20 | 0) == 101 | ($conv20 | 0) == 102) {
+ label = 11;
+ break;
+ } else {
+ $result_1 = $result_0;
+ label = 12;
+ break;
+ }
+ case 9:
+ $shl = $result_0 << 4;
+ $sub = $conv20 - 48 | 0;
+ $or = $sub | $shl;
+ $result_1 = $or;
+ label = 12;
+ break;
+ case 10:
+ $shl22 = $result_0 << 4;
+ $add = $shl22 - 55 | 0;
+ $add24 = $add + $conv20 | 0;
+ $result_1 = $add24;
+ label = 12;
+ break;
+ case 11:
+ $shl26 = $result_0 << 4;
+ $add28 = $shl26 - 87 | 0;
+ $add29 = $add28 + $conv20 | 0;
+ $result_1 = $add29;
+ label = 12;
+ break;
+ case 12:
+ $cmp30 = ($result_1 | 0) > 1114111;
+ $add_ptr33 = $ptr_addr_0 + 2 | 0;
+ if ($cmp30) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ $ptr_addr_0 = $add_ptr33;
+ $result_0 = $result_1;
+ label = 5;
+ break;
+ }
+ case 13:
+ $arrayidx35 = $ptr_addr_1 + 1 | 0;
+ $5 = HEAP8[$arrayidx35] | 0;
+ $cmp37 = $5 << 24 >> 24 == 0;
+ if ($cmp37) {
+ label = 14;
+ break;
+ } else {
+ $cond57 = -49;
+ label = 17;
+ break;
+ }
+ case 14:
+ $6 = HEAP8[$ptr_addr_1] | 0;
+ $phitmp = $6 << 24 >> 24 == 59;
+ if ($phitmp) {
+ $result_3 = $result_2;
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $_pr30 = HEAP8[$arrayidx35] | 0;
+ $cmp50 = $_pr30 << 24 >> 24 == 0;
+ if ($cmp50) {
+ label = 16;
+ break;
+ } else {
+ $cond57 = -49;
+ label = 17;
+ break;
+ }
+ case 16:
+ $7 = HEAP8[$ptr_addr_1] | 0;
+ $conv54 = $7 << 24 >> 24;
+ $phitmp27 = $conv54 - 48 | 0;
+ $cond57 = $phitmp27;
+ label = 17;
+ break;
+ case 17:
+ $mul = $result_2 * 10 & -1;
+ $add59 = $cond57 + $mul | 0;
+ $cmp60 = ($add59 | 0) > 1114111;
+ $add_ptr65 = $ptr_addr_1 + 2 | 0;
+ if ($cmp60) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ $ptr_addr_1 = $add_ptr65;
+ $result_2 = $add59;
+ label = 13;
+ break;
+ }
+ case 18:
+ $call = _checkCharRefNumber($result_3) | 0;
+ $retval_0 = $call;
+ label = 19;
+ break;
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_updatePosition($enc, $ptr, $end, $pos) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $pos = $pos | 0;
+ var $cmp22 = 0, $type = 0, $0 = 0, $columnNumber39 = 0, $columnNumber = 0, $lineNumber = 0, $lineNumber14 = 0, $columnNumber37 = 0, $type25 = 0, $1 = 0, $ptr_addr_023 = 0, $arrayidx = 0, $2 = 0, $cmp1 = 0, $3 = 0, $idxprom = 0, $arrayidx3 = 0, $4 = 0, $conv4 = 0, $call = 0, $cond = 0, $add_ptr = 0, $add_ptr8 = 0, $add_ptr10 = 0, $5 = 0, $inc = 0, $add_ptr12 = 0, $6 = 0, $inc15 = 0, $add_ptr16 = 0, $cmp17 = 0, $arrayidx19 = 0, $7 = 0, $cmp21 = 0, $8 = 0, $idxprom24 = 0, $arrayidx26 = 0, $9 = 0, $conv27 = 0, $call31 = 0, $cond33 = 0, $cmp34 = 0, $add_ptr36 = 0, $add_ptr36_add_ptr16 = 0, $ptr_addr_1 = 0, $add_ptr38 = 0, $ptr_addr_2 = 0, $10 = 0, $inc40 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp22 = $ptr >>> 0 < $end >>> 0;
+ if ($cmp22) {
+ label = 3;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $columnNumber39 = $pos + 4 | 0;
+ $columnNumber = $pos + 4 | 0;
+ $lineNumber = $pos | 0;
+ $lineNumber14 = $pos | 0;
+ $columnNumber37 = $pos + 4 | 0;
+ $type25 = $enc + 72 | 0;
+ $1 = $type25;
+ $ptr_addr_023 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $ptr_addr_023 + 1 | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $2 << 24 >> 24 == 0;
+ $3 = HEAP8[$ptr_addr_023] | 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $idxprom = $3 & 255;
+ $arrayidx3 = $0 + $idxprom | 0;
+ $4 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $4 & 255;
+ $cond = $conv4;
+ label = 7;
+ break;
+ case 6:
+ $call = _unicode_byte_type($2, $3) | 0;
+ $cond = $call;
+ label = 7;
+ break;
+ case 7:
+ if (($cond | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 12;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 8:
+ $add_ptr = $ptr_addr_023 + 2 | 0;
+ $ptr_addr_2 = $add_ptr;
+ label = 19;
+ break;
+ case 9:
+ $add_ptr8 = $ptr_addr_023 + 3 | 0;
+ $ptr_addr_2 = $add_ptr8;
+ label = 19;
+ break;
+ case 10:
+ $add_ptr10 = $ptr_addr_023 + 4 | 0;
+ $ptr_addr_2 = $add_ptr10;
+ label = 19;
+ break;
+ case 11:
+ HEAP32[$columnNumber >> 2] = -1;
+ $5 = HEAP32[$lineNumber >> 2] | 0;
+ $inc = $5 + 1 | 0;
+ HEAP32[$lineNumber >> 2] = $inc;
+ $add_ptr12 = $ptr_addr_023 + 2 | 0;
+ $ptr_addr_2 = $add_ptr12;
+ label = 19;
+ break;
+ case 12:
+ $6 = HEAP32[$lineNumber14 >> 2] | 0;
+ $inc15 = $6 + 1 | 0;
+ HEAP32[$lineNumber14 >> 2] = $inc15;
+ $add_ptr16 = $ptr_addr_023 + 2 | 0;
+ $cmp17 = ($add_ptr16 | 0) == ($end | 0);
+ if ($cmp17) {
+ $ptr_addr_1 = $add_ptr16;
+ label = 17;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $arrayidx19 = $ptr_addr_023 + 3 | 0;
+ $7 = HEAP8[$arrayidx19] | 0;
+ $cmp21 = $7 << 24 >> 24 == 0;
+ $8 = HEAP8[$add_ptr16] | 0;
+ if ($cmp21) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $idxprom24 = $8 & 255;
+ $arrayidx26 = $1 + $idxprom24 | 0;
+ $9 = HEAP8[$arrayidx26] | 0;
+ $conv27 = $9 & 255;
+ $cond33 = $conv27;
+ label = 16;
+ break;
+ case 15:
+ $call31 = _unicode_byte_type($7, $8) | 0;
+ $cond33 = $call31;
+ label = 16;
+ break;
+ case 16:
+ $cmp34 = ($cond33 | 0) == 10;
+ $add_ptr36 = $ptr_addr_023 + 4 | 0;
+ $add_ptr36_add_ptr16 = $cmp34 ? $add_ptr36 : $add_ptr16;
+ $ptr_addr_1 = $add_ptr36_add_ptr16;
+ label = 17;
+ break;
+ case 17:
+ HEAP32[$columnNumber37 >> 2] = -1;
+ $ptr_addr_2 = $ptr_addr_1;
+ label = 19;
+ break;
+ case 18:
+ $add_ptr38 = $ptr_addr_023 + 2 | 0;
+ $ptr_addr_2 = $add_ptr38;
+ label = 19;
+ break;
+ case 19:
+ $10 = HEAP32[$columnNumber39 >> 2] | 0;
+ $inc40 = $10 + 1 | 0;
+ HEAP32[$columnNumber39 >> 2] = $inc40;
+ $cmp = $ptr_addr_2 >>> 0 < $end >>> 0;
+ if ($cmp) {
+ $ptr_addr_023 = $ptr_addr_2;
+ label = 4;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ return;
+ }
+}
+function _unicode_byte_type($hi, $lo) {
+ $hi = $hi | 0;
+ $lo = $lo | 0;
+ var $conv = 0, $conv3 = 0, $conv3_off = 0, $switch = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $conv = $hi & 255;
+ if (($conv | 0) == 220 | ($conv | 0) == 221 | ($conv | 0) == 222 | ($conv | 0) == 223) {
+ label = 3;
+ break;
+ } else if (($conv | 0) == 255) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 216 | ($conv | 0) == 217 | ($conv | 0) == 218 | ($conv | 0) == 219) {
+ $retval_0 = 7;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 3:
+ $retval_0 = 8;
+ label = 6;
+ break;
+ case 4:
+ $conv3 = $lo & 255;
+ $conv3_off = $conv3 - 254 | 0;
+ $switch = $conv3_off >>> 0 < 2;
+ if ($switch) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $retval_0 = 29;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_toUtf8($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $cmp57 = 0, $sub_ptr_lhs_cast23 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_lhs_cast50 = 0, $from_058 = 0, $1 = 0, $arrayidx1 = 0, $2 = 0, $conv = 0, $cmp3 = 0, $3 = 0, $cmp5 = 0, $incdec_ptr = 0, $4 = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp10 = 0, $shr50 = 0, $shl = 0, $or = 0, $or16 = 0, $incdec_ptr18 = 0, $and = 0, $or20 = 0, $5 = 0, $incdec_ptr22 = 0, $6 = 0, $sub_ptr_rhs_cast24 = 0, $sub_ptr_sub25 = 0, $cmp26 = 0, $shr3151 = 0, $or32 = 0, $incdec_ptr34 = 0, $and36 = 0, $shl37 = 0, $shr3952 = 0, $or40 = 0, $or41 = 0, $7 = 0, $incdec_ptr43 = 0, $and45 = 0, $or46 = 0, $8 = 0, $incdec_ptr48 = 0, $9 = 0, $sub_ptr_rhs_cast51 = 0, $sub_ptr_sub52 = 0, $cmp53 = 0, $and58 = 0, $shl59 = 0, $conv60 = 0, $shr6146 = 0, $or63 = 0, $add = 0, $shr6447 = 0, $or65 = 0, $conv66 = 0, $incdec_ptr67 = 0, $shr6948 = 0, $and70 = 0, $and71 = 0, $shl72 = 0, $or73 = 0, $or74 = 0, $conv75 = 0, $10 = 0, $incdec_ptr76 = 0, $add_ptr = 0, $11 = 0, $and79 = 0, $shl80 = 0, $arrayidx81 = 0, $12 = 0, $and83 = 0, $shl84 = 0, $shr8749 = 0, $or85 = 0, $or88 = 0, $or89 = 0, $13 = 0, $incdec_ptr91 = 0, $and93 = 0, $or94 = 0, $14 = 0, $incdec_ptr96 = 0, $from_1 = 0, $add_ptr97 = 0, $cmp = 0, $from_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $cmp57 = ($0 | 0) == ($fromLim | 0);
+ if ($cmp57) {
+ $from_0_lcssa = $0;
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub_ptr_lhs_cast23 = $toLim;
+ $sub_ptr_lhs_cast = $toLim;
+ $sub_ptr_lhs_cast50 = $toLim;
+ $from_058 = $0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP8[$from_058] | 0;
+ $arrayidx1 = $from_058 + 1 | 0;
+ $2 = HEAP8[$arrayidx1] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 0) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 1 | ($conv | 0) == 2 | ($conv | 0) == 3 | ($conv | 0) == 4 | ($conv | 0) == 5 | ($conv | 0) == 6 | ($conv | 0) == 7) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 216 | ($conv | 0) == 217 | ($conv | 0) == 218 | ($conv | 0) == 219) {
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 5:
+ $cmp3 = $1 << 24 >> 24 > -1;
+ if ($cmp3) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 6:
+ $3 = HEAP32[$toP >> 2] | 0;
+ $cmp5 = ($3 | 0) == ($toLim | 0);
+ if ($cmp5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$fromP >> 2] = $from_058;
+ label = 20;
+ break;
+ case 8:
+ $incdec_ptr = $3 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr;
+ HEAP8[$3] = $1;
+ $from_1 = $from_058;
+ label = 18;
+ break;
+ case 9:
+ $4 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_rhs_cast = $4;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp10 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp10) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$fromP >> 2] = $from_058;
+ label = 20;
+ break;
+ case 11:
+ $shr50 = ($1 & 255) >>> 6;
+ $shl = $2 << 2;
+ $or = $shr50 | $shl;
+ $or16 = $or | -64;
+ $incdec_ptr18 = $4 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr18;
+ HEAP8[$4] = $or16;
+ $and = $1 & 63;
+ $or20 = $and | -128;
+ $5 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr22 = $5 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr22;
+ HEAP8[$5] = $or20;
+ $from_1 = $from_058;
+ label = 18;
+ break;
+ case 12:
+ $6 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_rhs_cast24 = $6;
+ $sub_ptr_sub25 = $sub_ptr_lhs_cast23 - $sub_ptr_rhs_cast24 | 0;
+ $cmp26 = ($sub_ptr_sub25 | 0) < 3;
+ if ($cmp26) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ HEAP32[$fromP >> 2] = $from_058;
+ label = 20;
+ break;
+ case 14:
+ $shr3151 = ($2 & 255) >>> 4;
+ $or32 = $shr3151 | -32;
+ $incdec_ptr34 = $6 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr34;
+ HEAP8[$6] = $or32;
+ $and36 = $2 << 2;
+ $shl37 = $and36 & 60;
+ $shr3952 = ($1 & 255) >>> 6;
+ $or40 = $shr3952 | $shl37;
+ $or41 = $or40 | -128;
+ $7 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr43 = $7 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr43;
+ HEAP8[$7] = $or41;
+ $and45 = $1 & 63;
+ $or46 = $and45 | -128;
+ $8 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr48 = $8 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr48;
+ HEAP8[$8] = $or46;
+ $from_1 = $from_058;
+ label = 18;
+ break;
+ case 15:
+ $9 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_rhs_cast51 = $9;
+ $sub_ptr_sub52 = $sub_ptr_lhs_cast50 - $sub_ptr_rhs_cast51 | 0;
+ $cmp53 = ($sub_ptr_sub52 | 0) < 4;
+ if ($cmp53) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ HEAP32[$fromP >> 2] = $from_058;
+ label = 20;
+ break;
+ case 17:
+ $and58 = $conv << 2;
+ $shl59 = $and58 & 12;
+ $conv60 = $1 & 255;
+ $shr6146 = $conv60 >>> 6;
+ $or63 = $shl59 | $shr6146;
+ $add = $or63 + 1 | 0;
+ $shr6447 = $add >>> 2;
+ $or65 = $shr6447 | 240;
+ $conv66 = $or65 & 255;
+ $incdec_ptr67 = $9 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr67;
+ HEAP8[$9] = $conv66;
+ $shr6948 = $conv60 >>> 2;
+ $and70 = $shr6948 & 15;
+ $and71 = $add << 4;
+ $shl72 = $and71 & 48;
+ $or73 = $and70 | $shl72;
+ $or74 = $or73 | 128;
+ $conv75 = $or74 & 255;
+ $10 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr76 = $10 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr76;
+ HEAP8[$10] = $conv75;
+ $add_ptr = $from_058 + 2 | 0;
+ $11 = HEAP8[$add_ptr] | 0;
+ $and79 = $1 << 4;
+ $shl80 = $and79 & 48;
+ $arrayidx81 = $from_058 + 3 | 0;
+ $12 = HEAP8[$arrayidx81] | 0;
+ $and83 = $12 << 2;
+ $shl84 = $and83 & 12;
+ $shr8749 = ($11 & 255) >>> 6;
+ $or85 = $shl80 | $shr8749;
+ $or88 = $or85 | $shl84;
+ $or89 = $or88 | -128;
+ $13 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr91 = $13 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr91;
+ HEAP8[$13] = $or89;
+ $and93 = $11 & 63;
+ $or94 = $and93 | -128;
+ $14 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr96 = $14 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr96;
+ HEAP8[$14] = $or94;
+ $from_1 = $add_ptr;
+ label = 18;
+ break;
+ case 18:
+ $add_ptr97 = $from_1 + 2 | 0;
+ $cmp = ($add_ptr97 | 0) == ($fromLim | 0);
+ if ($cmp) {
+ $from_0_lcssa = $add_ptr97;
+ label = 19;
+ break;
+ } else {
+ $from_058 = $add_ptr97;
+ label = 4;
+ break;
+ }
+ case 19:
+ HEAP32[$fromP >> 2] = $from_0_lcssa;
+ label = 20;
+ break;
+ case 20:
+ return;
+ }
+}
+function _little2_toUtf16($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $1 = 0, $sub_ptr_lhs_cast1 = 0, $sub_ptr_rhs_cast2 = 0, $sub_ptr_sub3 = 0, $cmp = 0, $arrayidx = 0, $2 = 0, $and = 0, $cmp4 = 0, $add_ptr = 0, $add_ptr_fromLim = 0, $fromLim_addr_0_ph = 0, $3 = 0, $cmp711 = 0, $4 = 0, $5 = 0, $cmp9 = 0, $arrayidx11 = 0, $6 = 0, $conv12 = 0, $shl13 = 0, $7 = 0, $conv15 = 0, $or = 0, $incdec_ptr = 0, $8 = 0, $add_ptr17 = 0, $cmp7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $sub_ptr_lhs_cast = $fromLim;
+ $sub_ptr_rhs_cast = $0;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $1 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_lhs_cast1 = $toLim;
+ $sub_ptr_rhs_cast2 = $1;
+ $sub_ptr_sub3 = $sub_ptr_lhs_cast1 - $sub_ptr_rhs_cast2 | 0;
+ $cmp = ($sub_ptr_sub | 0) > ($sub_ptr_sub3 | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $fromLim_addr_0_ph = $fromLim;
+ label = 4;
+ break;
+ }
+ case 3:
+ $arrayidx = $fromLim - 1 | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $and = $2 & -8;
+ $cmp4 = $and << 24 >> 24 == -40;
+ $add_ptr = $fromLim - 2 | 0;
+ $add_ptr_fromLim = $cmp4 ? $add_ptr : $fromLim;
+ $fromLim_addr_0_ph = $add_ptr_fromLim;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[$fromP >> 2] | 0;
+ $cmp711 = ($3 | 0) == ($fromLim_addr_0_ph | 0);
+ if ($cmp711) {
+ label = 7;
+ break;
+ } else {
+ $4 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[$toP >> 2] | 0;
+ $cmp9 = ($5 | 0) == ($toLim | 0);
+ if ($cmp9) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $arrayidx11 = $4 + 1 | 0;
+ $6 = HEAP8[$arrayidx11] | 0;
+ $conv12 = $6 & 255;
+ $shl13 = $conv12 << 8;
+ $7 = HEAP8[$4] | 0;
+ $conv15 = $7 & 255;
+ $or = $shl13 | $conv15;
+ $incdec_ptr = $5 + 2 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr;
+ HEAP16[$5 >> 1] = $or;
+ $8 = HEAP32[$fromP >> 2] | 0;
+ $add_ptr17 = $8 + 2 | 0;
+ HEAP32[$fromP >> 2] = $add_ptr17;
+ $cmp7 = ($add_ptr17 | 0) == ($fromLim_addr_0_ph | 0);
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ $4 = $add_ptr17;
+ label = 5;
+ break;
+ }
+ case 7:
+ return;
+ }
+}
+function _little2_isPublicId($enc, $ptr, $end, $badPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $badPtr = $badPtr | 0;
+ var $add_ptr1 = 0, $ptr_addr_020 = 0, $cmp21 = 0, $type = 0, $0 = 0, $ptr_addr_023 = 0, $ptr_pn22 = 0, $arrayidx = 0, $1 = 0, $cmp2 = 0, $2 = 0, $idxprom = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $ptr_addr_0 = 0, $cmp = 0, $4 = 0, $cmp11 = 0, $5 = 0, $cmp15 = 0, $6 = 0, $cmp20 = 0, $7 = 0, $phitmp16 = 0, $_pr = 0, $cmp32 = 0, $8 = 0, $conv36 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add_ptr1 = $end - 2 | 0;
+ $ptr_addr_020 = $ptr + 2 | 0;
+ $cmp21 = ($ptr_addr_020 | 0) == ($add_ptr1 | 0);
+ if ($cmp21) {
+ $retval_0 = 1;
+ label = 17;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_pn22 = $ptr;
+ $ptr_addr_023 = $ptr_addr_020;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $ptr_pn22 + 3 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $cmp2 = $1 << 24 >> 24 == 0;
+ $2 = HEAP8[$ptr_addr_023] | 0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $idxprom = $2 & 255;
+ $arrayidx4 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 7;
+ break;
+ case 6:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 7;
+ break;
+ case 7:
+ if (($cond | 0) == 25 | ($cond | 0) == 24 | ($cond | 0) == 27 | ($cond | 0) == 13 | ($cond | 0) == 31 | ($cond | 0) == 32 | ($cond | 0) == 34 | ($cond | 0) == 35 | ($cond | 0) == 17 | ($cond | 0) == 14 | ($cond | 0) == 15 | ($cond | 0) == 9 | ($cond | 0) == 10 | ($cond | 0) == 18 | ($cond | 0) == 16 | ($cond | 0) == 33 | ($cond | 0) == 30 | ($cond | 0) == 19) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 21) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 26 | ($cond | 0) == 22) {
+ label = 12;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 8:
+ $ptr_addr_0 = $ptr_addr_023 + 2 | 0;
+ $cmp = ($ptr_addr_0 | 0) == ($add_ptr1 | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 17;
+ break;
+ } else {
+ $ptr_pn22 = $ptr_addr_023;
+ $ptr_addr_023 = $ptr_addr_0;
+ label = 4;
+ break;
+ }
+ case 9:
+ $4 = HEAP8[$arrayidx] | 0;
+ $cmp11 = $4 << 24 >> 24 == 0;
+ if ($cmp11) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 10:
+ $5 = HEAP8[$ptr_addr_023] | 0;
+ $cmp15 = $5 << 24 >> 24 == 9;
+ if ($cmp15) {
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 11:
+ HEAP32[$badPtr >> 2] = $ptr_addr_023;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 12:
+ $6 = HEAP8[$arrayidx] | 0;
+ $cmp20 = $6 << 24 >> 24 == 0;
+ if ($cmp20) {
+ label = 13;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 13:
+ $7 = HEAP8[$ptr_addr_023] | 0;
+ $phitmp16 = $7 << 24 >> 24 < 0;
+ if ($phitmp16) {
+ label = 14;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 14:
+ $_pr = HEAP8[$arrayidx] | 0;
+ $cmp32 = $_pr << 24 >> 24 == 0;
+ if ($cmp32) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $8 = HEAP8[$ptr_addr_023] | 0;
+ $conv36 = $8 << 24 >> 24;
+ if (($conv36 | 0) == 36 | ($conv36 | 0) == 64) {
+ label = 8;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$badPtr >> 2] = $ptr_addr_023;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 17:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $ptr_addr_069 = 0, $cmp4570 = 0, $type53 = 0, $4 = 0, $5 = 0, $idxprom8 = 0, $arrayidx9 = 0, $6 = 0, $conv10 = 0, $shl = 0, $7 = 0, $conv12 = 0, $shr56 = 0, $add = 0, $arrayidx13 = 0, $8 = 0, $and = 0, $shl16 = 0, $and17 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp22 = 0, $sub_ptr_lhs_cast27 = 0, $sub_ptr_rhs_cast28 = 0, $sub_ptr_sub29 = 0, $cmp30 = 0, $sub_ptr_lhs_cast35 = 0, $sub_ptr_rhs_cast36 = 0, $sub_ptr_sub37 = 0, $cmp38 = 0, $add_ptr43 = 0, $call44 = 0, $ptr_addr_072 = 0, $ptr_pn71 = 0, $arrayidx47 = 0, $9 = 0, $cmp49 = 0, $10 = 0, $idxprom52 = 0, $arrayidx54 = 0, $11 = 0, $conv55 = 0, $call59 = 0, $cond61 = 0, $12 = 0, $idxprom64 = 0, $arrayidx65 = 0, $13 = 0, $conv66 = 0, $shl67 = 0, $14 = 0, $conv69 = 0, $shr7055 = 0, $add71 = 0, $arrayidx72 = 0, $15 = 0, $and75 = 0, $shl76 = 0, $and77 = 0, $tobool78 = 0, $ptr_addr_0 = 0, $cmp45 = 0, $sub_ptr_lhs_cast84 = 0, $sub_ptr_rhs_cast85 = 0, $sub_ptr_sub86 = 0, $cmp87 = 0, $sub_ptr_lhs_cast92 = 0, $sub_ptr_rhs_cast93 = 0, $sub_ptr_sub94 = 0, $cmp95 = 0, $sub_ptr_lhs_cast100 = 0, $sub_ptr_rhs_cast101 = 0, $sub_ptr_sub102 = 0, $cmp103 = 0, $add_ptr108 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx3 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 19) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 7:
+ $ptr_addr_069 = $ptr + 2 | 0;
+ $cmp4570 = ($ptr_addr_069 | 0) == ($end | 0);
+ if ($cmp4570) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type53 = $enc + 72 | 0;
+ $4 = $type53;
+ $ptr_pn71 = $ptr;
+ $ptr_addr_072 = $ptr_addr_069;
+ label = 19;
+ break;
+ case 9:
+ $5 = HEAP8[$arrayidx] | 0;
+ $idxprom8 = $5 & 255;
+ $arrayidx9 = $idxprom8 + 9272 | 0;
+ $6 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $6 & 255;
+ $shl = $conv10 << 3;
+ $7 = HEAP8[$ptr] | 0;
+ $conv12 = $7 & 255;
+ $shr56 = $conv12 >>> 5;
+ $add = $shr56 | $shl;
+ $arrayidx13 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx13 >> 2] | 0;
+ $and = $conv12 & 31;
+ $shl16 = 1 << $and;
+ $and17 = $shl16 & $8;
+ $tobool = ($and17 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp22 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp22) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast27 = $end;
+ $sub_ptr_rhs_cast28 = $ptr;
+ $sub_ptr_sub29 = $sub_ptr_lhs_cast27 - $sub_ptr_rhs_cast28 | 0;
+ $cmp30 = ($sub_ptr_sub29 | 0) < 3;
+ if ($cmp30) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast35 = $end;
+ $sub_ptr_rhs_cast36 = $ptr;
+ $sub_ptr_sub37 = $sub_ptr_lhs_cast35 - $sub_ptr_rhs_cast36 | 0;
+ $cmp38 = ($sub_ptr_sub37 | 0) < 4;
+ if ($cmp38) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 17:
+ $add_ptr43 = $ptr + 2 | 0;
+ $call44 = _little2_scanCharRef($enc, $add_ptr43, $end, $nextTokPtr) | 0;
+ $retval_0 = $call44;
+ label = 34;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 19:
+ $arrayidx47 = $ptr_pn71 + 3 | 0;
+ $9 = HEAP8[$arrayidx47] | 0;
+ $cmp49 = $9 << 24 >> 24 == 0;
+ $10 = HEAP8[$ptr_addr_072] | 0;
+ if ($cmp49) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $idxprom52 = $10 & 255;
+ $arrayidx54 = $4 + $idxprom52 | 0;
+ $11 = HEAP8[$arrayidx54] | 0;
+ $conv55 = $11 & 255;
+ $cond61 = $conv55;
+ label = 22;
+ break;
+ case 21:
+ $call59 = _unicode_byte_type($9, $10) | 0;
+ $cond61 = $call59;
+ label = 22;
+ break;
+ case 22:
+ if (($cond61 | 0) == 29) {
+ label = 23;
+ break;
+ } else if (($cond61 | 0) == 22 | ($cond61 | 0) == 24 | ($cond61 | 0) == 25 | ($cond61 | 0) == 26 | ($cond61 | 0) == 27) {
+ label = 24;
+ break;
+ } else if (($cond61 | 0) == 5) {
+ label = 26;
+ break;
+ } else if (($cond61 | 0) == 6) {
+ label = 28;
+ break;
+ } else if (($cond61 | 0) == 7) {
+ label = 30;
+ break;
+ } else if (($cond61 | 0) == 18) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 23:
+ $12 = HEAP8[$arrayidx47] | 0;
+ $idxprom64 = $12 & 255;
+ $arrayidx65 = $idxprom64 + 10824 | 0;
+ $13 = HEAP8[$arrayidx65] | 0;
+ $conv66 = $13 & 255;
+ $shl67 = $conv66 << 3;
+ $14 = HEAP8[$ptr_addr_072] | 0;
+ $conv69 = $14 & 255;
+ $shr7055 = $conv69 >>> 5;
+ $add71 = $shr7055 | $shl67;
+ $arrayidx72 = 9544 + ($add71 << 2) | 0;
+ $15 = HEAP32[$arrayidx72 >> 2] | 0;
+ $and75 = $conv69 & 31;
+ $shl76 = 1 << $and75;
+ $and77 = $shl76 & $15;
+ $tobool78 = ($and77 | 0) == 0;
+ if ($tobool78) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $ptr_addr_0 = $ptr_addr_072 + 2 | 0;
+ $cmp45 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp45) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ $ptr_pn71 = $ptr_addr_072;
+ $ptr_addr_072 = $ptr_addr_0;
+ label = 19;
+ break;
+ }
+ case 25:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 26:
+ $sub_ptr_lhs_cast84 = $end;
+ $sub_ptr_rhs_cast85 = $ptr_addr_072;
+ $sub_ptr_sub86 = $sub_ptr_lhs_cast84 - $sub_ptr_rhs_cast85 | 0;
+ $cmp87 = ($sub_ptr_sub86 | 0) < 2;
+ if ($cmp87) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 28:
+ $sub_ptr_lhs_cast92 = $end;
+ $sub_ptr_rhs_cast93 = $ptr_addr_072;
+ $sub_ptr_sub94 = $sub_ptr_lhs_cast92 - $sub_ptr_rhs_cast93 | 0;
+ $cmp95 = ($sub_ptr_sub94 | 0) < 3;
+ if ($cmp95) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 30:
+ $sub_ptr_lhs_cast100 = $end;
+ $sub_ptr_rhs_cast101 = $ptr_addr_072;
+ $sub_ptr_sub102 = $sub_ptr_lhs_cast100 - $sub_ptr_rhs_cast101 | 0;
+ $cmp103 = ($sub_ptr_sub102 | 0) < 4;
+ if ($cmp103) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 32:
+ $add_ptr108 = $ptr_pn71 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr108;
+ $retval_0 = 9;
+ label = 34;
+ break;
+ case 33:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 34:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanPercent($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $ptr_addr_067 = 0, $cmp4368 = 0, $type51 = 0, $4 = 0, $5 = 0, $idxprom8 = 0, $arrayidx9 = 0, $6 = 0, $conv10 = 0, $shl = 0, $7 = 0, $conv12 = 0, $shr54 = 0, $add = 0, $arrayidx13 = 0, $8 = 0, $and = 0, $shl16 = 0, $and17 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp22 = 0, $sub_ptr_lhs_cast27 = 0, $sub_ptr_rhs_cast28 = 0, $sub_ptr_sub29 = 0, $cmp30 = 0, $sub_ptr_lhs_cast35 = 0, $sub_ptr_rhs_cast36 = 0, $sub_ptr_sub37 = 0, $cmp38 = 0, $ptr_addr_070 = 0, $ptr_pn69 = 0, $arrayidx45 = 0, $9 = 0, $cmp47 = 0, $10 = 0, $idxprom50 = 0, $arrayidx52 = 0, $11 = 0, $conv53 = 0, $call57 = 0, $cond59 = 0, $12 = 0, $idxprom62 = 0, $arrayidx63 = 0, $13 = 0, $conv64 = 0, $shl65 = 0, $14 = 0, $conv67 = 0, $shr6853 = 0, $add69 = 0, $arrayidx70 = 0, $15 = 0, $and73 = 0, $shl74 = 0, $and75 = 0, $tobool76 = 0, $ptr_addr_0 = 0, $cmp43 = 0, $sub_ptr_lhs_cast82 = 0, $sub_ptr_rhs_cast83 = 0, $sub_ptr_sub84 = 0, $cmp85 = 0, $sub_ptr_lhs_cast90 = 0, $sub_ptr_rhs_cast91 = 0, $sub_ptr_sub92 = 0, $cmp93 = 0, $sub_ptr_lhs_cast98 = 0, $sub_ptr_rhs_cast99 = 0, $sub_ptr_sub100 = 0, $cmp101 = 0, $add_ptr106 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx3 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 21 | ($cond | 0) == 10 | ($cond | 0) == 9 | ($cond | 0) == 30) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 7:
+ $ptr_addr_067 = $ptr + 2 | 0;
+ $cmp4368 = ($ptr_addr_067 | 0) == ($end | 0);
+ if ($cmp4368) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type51 = $enc + 72 | 0;
+ $4 = $type51;
+ $ptr_pn69 = $ptr;
+ $ptr_addr_070 = $ptr_addr_067;
+ label = 19;
+ break;
+ case 9:
+ $5 = HEAP8[$arrayidx] | 0;
+ $idxprom8 = $5 & 255;
+ $arrayidx9 = $idxprom8 + 9272 | 0;
+ $6 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $6 & 255;
+ $shl = $conv10 << 3;
+ $7 = HEAP8[$ptr] | 0;
+ $conv12 = $7 & 255;
+ $shr54 = $conv12 >>> 5;
+ $add = $shr54 | $shl;
+ $arrayidx13 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx13 >> 2] | 0;
+ $and = $conv12 & 31;
+ $shl16 = 1 << $and;
+ $and17 = $shl16 & $8;
+ $tobool = ($and17 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp22 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp22) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast27 = $end;
+ $sub_ptr_rhs_cast28 = $ptr;
+ $sub_ptr_sub29 = $sub_ptr_lhs_cast27 - $sub_ptr_rhs_cast28 | 0;
+ $cmp30 = ($sub_ptr_sub29 | 0) < 3;
+ if ($cmp30) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast35 = $end;
+ $sub_ptr_rhs_cast36 = $ptr;
+ $sub_ptr_sub37 = $sub_ptr_lhs_cast35 - $sub_ptr_rhs_cast36 | 0;
+ $cmp38 = ($sub_ptr_sub37 | 0) < 4;
+ if ($cmp38) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 22;
+ label = 34;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 19:
+ $arrayidx45 = $ptr_pn69 + 3 | 0;
+ $9 = HEAP8[$arrayidx45] | 0;
+ $cmp47 = $9 << 24 >> 24 == 0;
+ $10 = HEAP8[$ptr_addr_070] | 0;
+ if ($cmp47) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $idxprom50 = $10 & 255;
+ $arrayidx52 = $4 + $idxprom50 | 0;
+ $11 = HEAP8[$arrayidx52] | 0;
+ $conv53 = $11 & 255;
+ $cond59 = $conv53;
+ label = 22;
+ break;
+ case 21:
+ $call57 = _unicode_byte_type($9, $10) | 0;
+ $cond59 = $call57;
+ label = 22;
+ break;
+ case 22:
+ if (($cond59 | 0) == 29) {
+ label = 23;
+ break;
+ } else if (($cond59 | 0) == 22 | ($cond59 | 0) == 24 | ($cond59 | 0) == 25 | ($cond59 | 0) == 26 | ($cond59 | 0) == 27) {
+ label = 24;
+ break;
+ } else if (($cond59 | 0) == 5) {
+ label = 26;
+ break;
+ } else if (($cond59 | 0) == 6) {
+ label = 28;
+ break;
+ } else if (($cond59 | 0) == 7) {
+ label = 30;
+ break;
+ } else if (($cond59 | 0) == 18) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 23:
+ $12 = HEAP8[$arrayidx45] | 0;
+ $idxprom62 = $12 & 255;
+ $arrayidx63 = $idxprom62 + 10824 | 0;
+ $13 = HEAP8[$arrayidx63] | 0;
+ $conv64 = $13 & 255;
+ $shl65 = $conv64 << 3;
+ $14 = HEAP8[$ptr_addr_070] | 0;
+ $conv67 = $14 & 255;
+ $shr6853 = $conv67 >>> 5;
+ $add69 = $shr6853 | $shl65;
+ $arrayidx70 = 9544 + ($add69 << 2) | 0;
+ $15 = HEAP32[$arrayidx70 >> 2] | 0;
+ $and73 = $conv67 & 31;
+ $shl74 = 1 << $and73;
+ $and75 = $shl74 & $15;
+ $tobool76 = ($and75 | 0) == 0;
+ if ($tobool76) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $ptr_addr_0 = $ptr_addr_070 + 2 | 0;
+ $cmp43 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp43) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ $ptr_pn69 = $ptr_addr_070;
+ $ptr_addr_070 = $ptr_addr_0;
+ label = 19;
+ break;
+ }
+ case 25:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 26:
+ $sub_ptr_lhs_cast82 = $end;
+ $sub_ptr_rhs_cast83 = $ptr_addr_070;
+ $sub_ptr_sub84 = $sub_ptr_lhs_cast82 - $sub_ptr_rhs_cast83 | 0;
+ $cmp85 = ($sub_ptr_sub84 | 0) < 2;
+ if ($cmp85) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 28:
+ $sub_ptr_lhs_cast90 = $end;
+ $sub_ptr_rhs_cast91 = $ptr_addr_070;
+ $sub_ptr_sub92 = $sub_ptr_lhs_cast90 - $sub_ptr_rhs_cast91 | 0;
+ $cmp93 = ($sub_ptr_sub92 | 0) < 3;
+ if ($cmp93) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 30:
+ $sub_ptr_lhs_cast98 = $end;
+ $sub_ptr_rhs_cast99 = $ptr_addr_070;
+ $sub_ptr_sub100 = $sub_ptr_lhs_cast98 - $sub_ptr_rhs_cast99 | 0;
+ $cmp101 = ($sub_ptr_sub100 | 0) < 4;
+ if ($cmp101) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 32:
+ $add_ptr106 = $ptr_pn69 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr106;
+ $retval_0 = 28;
+ label = 34;
+ break;
+ case 33:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 34:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanCharRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $cmp5 = 0, $add_ptr = 0, $call = 0, $_pr = 0, $cmp10 = 0, $2 = 0, $idxprom = 0, $type = 0, $3 = 0, $arrayidx12 = 0, $4 = 0, $conv13 = 0, $5 = 0, $6 = 0, $call16 = 0, $cond = 0, $cond1 = 0, $type26 = 0, $7 = 0, $ptr_pn = 0, $ptr_addr_0 = 0, $cmp18 = 0, $arrayidx20 = 0, $8 = 0, $cmp22 = 0, $9 = 0, $idxprom25 = 0, $arrayidx27 = 0, $10 = 0, $conv28 = 0, $call32 = 0, $cond34 = 0, $add_ptr37 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ $6 = $0;
+ $5 = $1;
+ label = 8;
+ break;
+ }
+ case 4:
+ $cmp5 = $1 << 24 >> 24 == 120;
+ if ($cmp5) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + 2 | 0;
+ $call = _little2_scanHexCharRef($enc, $add_ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 19;
+ break;
+ case 6:
+ $_pr = HEAP8[$arrayidx] | 0;
+ $cmp10 = $_pr << 24 >> 24 == 0;
+ $2 = HEAP8[$ptr] | 0;
+ if ($cmp10) {
+ label = 7;
+ break;
+ } else {
+ $6 = $_pr;
+ $5 = $2;
+ label = 8;
+ break;
+ }
+ case 7:
+ $idxprom = $2 & 255;
+ $type = $enc + 72 | 0;
+ $3 = $type;
+ $arrayidx12 = $3 + $idxprom | 0;
+ $4 = HEAP8[$arrayidx12] | 0;
+ $conv13 = $4 & 255;
+ $cond = $conv13;
+ label = 9;
+ break;
+ case 8:
+ $call16 = _unicode_byte_type($6, $5) | 0;
+ $cond = $call16;
+ label = 9;
+ break;
+ case 9:
+ $cond1 = ($cond | 0) == 25;
+ if ($cond1) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $type26 = $enc + 72 | 0;
+ $7 = $type26;
+ $ptr_pn = $ptr;
+ label = 12;
+ break;
+ case 11:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 12:
+ $ptr_addr_0 = $ptr_pn + 2 | 0;
+ $cmp18 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp18) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $arrayidx20 = $ptr_pn + 3 | 0;
+ $8 = HEAP8[$arrayidx20] | 0;
+ $cmp22 = $8 << 24 >> 24 == 0;
+ $9 = HEAP8[$ptr_addr_0] | 0;
+ if ($cmp22) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $idxprom25 = $9 & 255;
+ $arrayidx27 = $7 + $idxprom25 | 0;
+ $10 = HEAP8[$arrayidx27] | 0;
+ $conv28 = $10 & 255;
+ $cond34 = $conv28;
+ label = 16;
+ break;
+ case 15:
+ $call32 = _unicode_byte_type($8, $9) | 0;
+ $cond34 = $call32;
+ label = 16;
+ break;
+ case 16:
+ if (($cond34 | 0) == 25) {
+ $ptr_pn = $ptr_addr_0;
+ label = 12;
+ break;
+ } else if (($cond34 | 0) == 18) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $add_ptr37 = $ptr_pn + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr37;
+ $retval_0 = 10;
+ label = 19;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanCdataSection($ptr, $end, $nextTokPtr) {
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp = 0, $arrayidx = 0, $0 = 0, $cmp2 = 0, $1 = 0, $cmp8 = 0, $ptr_addr_02_lcssa = 0, $add_ptr = 0, $arrayidx_1 = 0, $2 = 0, $cmp2_1 = 0, $retval_0 = 0, $3 = 0, $cmp8_1 = 0, $add_ptr_1 = 0, $arrayidx_2 = 0, $4 = 0, $cmp2_2 = 0, $5 = 0, $cmp8_2 = 0, $add_ptr_2 = 0, $arrayidx_3 = 0, $6 = 0, $cmp2_3 = 0, $7 = 0, $cmp8_3 = 0, $add_ptr_3 = 0, $arrayidx_4 = 0, $8 = 0, $cmp2_4 = 0, $9 = 0, $cmp8_4 = 0, $add_ptr_4 = 0, $arrayidx_5 = 0, $10 = 0, $cmp2_5 = 0, $11 = 0, $cmp8_5 = 0, $add_ptr_5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp = ($sub_ptr_sub | 0) < 12;
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp2 = $0 << 24 >> 24 == 0;
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $ptr;
+ label = 5;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$ptr] | 0;
+ $cmp8 = $1 << 24 >> 24 == 67;
+ if ($cmp8) {
+ label = 6;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $ptr;
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_02_lcssa;
+ $retval_0 = 0;
+ label = 7;
+ break;
+ case 6:
+ $add_ptr = $ptr + 2 | 0;
+ $arrayidx_1 = $ptr + 3 | 0;
+ $2 = HEAP8[$arrayidx_1] | 0;
+ $cmp2_1 = $2 << 24 >> 24 == 0;
+ if ($cmp2_1) {
+ label = 8;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr;
+ label = 5;
+ break;
+ }
+ case 7:
+ return $retval_0 | 0;
+ case 8:
+ $3 = HEAP8[$add_ptr] | 0;
+ $cmp8_1 = $3 << 24 >> 24 == 68;
+ if ($cmp8_1) {
+ label = 9;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr;
+ label = 5;
+ break;
+ }
+ case 9:
+ $add_ptr_1 = $ptr + 4 | 0;
+ $arrayidx_2 = $ptr + 5 | 0;
+ $4 = HEAP8[$arrayidx_2] | 0;
+ $cmp2_2 = $4 << 24 >> 24 == 0;
+ if ($cmp2_2) {
+ label = 10;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_1;
+ label = 5;
+ break;
+ }
+ case 10:
+ $5 = HEAP8[$add_ptr_1] | 0;
+ $cmp8_2 = $5 << 24 >> 24 == 65;
+ if ($cmp8_2) {
+ label = 11;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_1;
+ label = 5;
+ break;
+ }
+ case 11:
+ $add_ptr_2 = $ptr + 6 | 0;
+ $arrayidx_3 = $ptr + 7 | 0;
+ $6 = HEAP8[$arrayidx_3] | 0;
+ $cmp2_3 = $6 << 24 >> 24 == 0;
+ if ($cmp2_3) {
+ label = 12;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_2;
+ label = 5;
+ break;
+ }
+ case 12:
+ $7 = HEAP8[$add_ptr_2] | 0;
+ $cmp8_3 = $7 << 24 >> 24 == 84;
+ if ($cmp8_3) {
+ label = 13;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_2;
+ label = 5;
+ break;
+ }
+ case 13:
+ $add_ptr_3 = $ptr + 8 | 0;
+ $arrayidx_4 = $ptr + 9 | 0;
+ $8 = HEAP8[$arrayidx_4] | 0;
+ $cmp2_4 = $8 << 24 >> 24 == 0;
+ if ($cmp2_4) {
+ label = 14;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_3;
+ label = 5;
+ break;
+ }
+ case 14:
+ $9 = HEAP8[$add_ptr_3] | 0;
+ $cmp8_4 = $9 << 24 >> 24 == 65;
+ if ($cmp8_4) {
+ label = 15;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_3;
+ label = 5;
+ break;
+ }
+ case 15:
+ $add_ptr_4 = $ptr + 10 | 0;
+ $arrayidx_5 = $ptr + 11 | 0;
+ $10 = HEAP8[$arrayidx_5] | 0;
+ $cmp2_5 = $10 << 24 >> 24 == 0;
+ if ($cmp2_5) {
+ label = 16;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_4;
+ label = 5;
+ break;
+ }
+ case 16:
+ $11 = HEAP8[$add_ptr_4] | 0;
+ $cmp8_5 = $11 << 24 >> 24 == 91;
+ if ($cmp8_5) {
+ label = 17;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_4;
+ label = 5;
+ break;
+ }
+ case 17:
+ $add_ptr_5 = $ptr + 12 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr_5;
+ $retval_0 = 8;
+ label = 7;
+ break;
+ }
+ return 0;
+}
+function _little2_scanHexCharRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $cond_off = 0, $switch = 0, $ptr_addr_020 = 0, $cmp721 = 0, $type15 = 0, $4 = 0, $ptr_addr_023 = 0, $ptr_pn22 = 0, $arrayidx9 = 0, $5 = 0, $cmp11 = 0, $6 = 0, $idxprom14 = 0, $arrayidx16 = 0, $7 = 0, $conv17 = 0, $call21 = 0, $cond23 = 0, $ptr_addr_0 = 0, $cmp7 = 0, $add_ptr26 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 17;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx3 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ $cond_off = $cond - 24 | 0;
+ $switch = $cond_off >>> 0 < 2;
+ if ($switch) {
+ label = 7;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 7:
+ $ptr_addr_020 = $ptr + 2 | 0;
+ $cmp721 = ($ptr_addr_020 | 0) == ($end | 0);
+ if ($cmp721) {
+ $retval_0 = -1;
+ label = 17;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type15 = $enc + 72 | 0;
+ $4 = $type15;
+ $ptr_pn22 = $ptr;
+ $ptr_addr_023 = $ptr_addr_020;
+ label = 10;
+ break;
+ case 9:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 10:
+ $arrayidx9 = $ptr_pn22 + 3 | 0;
+ $5 = HEAP8[$arrayidx9] | 0;
+ $cmp11 = $5 << 24 >> 24 == 0;
+ $6 = HEAP8[$ptr_addr_023] | 0;
+ if ($cmp11) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $idxprom14 = $6 & 255;
+ $arrayidx16 = $4 + $idxprom14 | 0;
+ $7 = HEAP8[$arrayidx16] | 0;
+ $conv17 = $7 & 255;
+ $cond23 = $conv17;
+ label = 13;
+ break;
+ case 12:
+ $call21 = _unicode_byte_type($5, $6) | 0;
+ $cond23 = $call21;
+ label = 13;
+ break;
+ case 13:
+ if (($cond23 | 0) == 25 | ($cond23 | 0) == 24) {
+ label = 14;
+ break;
+ } else if (($cond23 | 0) == 18) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 14:
+ $ptr_addr_0 = $ptr_addr_023 + 2 | 0;
+ $cmp7 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp7) {
+ $retval_0 = -1;
+ label = 17;
+ break;
+ } else {
+ $ptr_pn22 = $ptr_addr_023;
+ $ptr_addr_023 = $ptr_addr_0;
+ label = 10;
+ break;
+ }
+ case 15:
+ $add_ptr26 = $ptr_pn22 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr26;
+ $retval_0 = 10;
+ label = 17;
+ break;
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_023;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 17:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanLt($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $ptr_addr_0156 = 0, $cmp76157 = 0, $type84 = 0, $4 = 0, $5 = 0, $idxprom8 = 0, $arrayidx9 = 0, $6 = 0, $conv10 = 0, $shl = 0, $7 = 0, $conv12 = 0, $shr118 = 0, $add = 0, $arrayidx13 = 0, $8 = 0, $and = 0, $shl16 = 0, $and17 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp22 = 0, $sub_ptr_lhs_cast27 = 0, $sub_ptr_rhs_cast28 = 0, $sub_ptr_sub29 = 0, $cmp30 = 0, $sub_ptr_lhs_cast35 = 0, $sub_ptr_rhs_cast36 = 0, $sub_ptr_sub37 = 0, $cmp38 = 0, $add_ptr43 = 0, $cmp44 = 0, $arrayidx48 = 0, $9 = 0, $cmp50 = 0, $10 = 0, $idxprom53 = 0, $type54 = 0, $11 = 0, $arrayidx55 = 0, $12 = 0, $conv56 = 0, $call60 = 0, $cond62 = 0, $add_ptr64 = 0, $call65 = 0, $add_ptr67 = 0, $call68 = 0, $add_ptr70 = 0, $call71 = 0, $add_ptr73 = 0, $call74 = 0, $ptr_addr_0159 = 0, $ptr_pn158 = 0, $arrayidx78 = 0, $13 = 0, $cmp80 = 0, $14 = 0, $idxprom83 = 0, $arrayidx85 = 0, $15 = 0, $conv86 = 0, $call90 = 0, $cond92 = 0, $16 = 0, $idxprom95 = 0, $arrayidx96 = 0, $17 = 0, $conv97 = 0, $shl98 = 0, $18 = 0, $conv100 = 0, $shr101117 = 0, $add102 = 0, $arrayidx103 = 0, $19 = 0, $and106 = 0, $shl107 = 0, $and108 = 0, $tobool109 = 0, $ptr_addr_0 = 0, $cmp76 = 0, $sub_ptr_lhs_cast115 = 0, $sub_ptr_rhs_cast116 = 0, $sub_ptr_sub117 = 0, $cmp118 = 0, $sub_ptr_lhs_cast123 = 0, $sub_ptr_rhs_cast124 = 0, $sub_ptr_sub125 = 0, $cmp126 = 0, $sub_ptr_lhs_cast131 = 0, $sub_ptr_rhs_cast132 = 0, $sub_ptr_sub133 = 0, $cmp134 = 0, $add_ptr139 = 0, $cmp141135 = 0, $type150 = 0, $20 = 0, $ptr_addr_1136 = 0, $arrayidx144 = 0, $21 = 0, $cmp146 = 0, $22 = 0, $idxprom149 = 0, $arrayidx151 = 0, $23 = 0, $conv152 = 0, $call156 = 0, $cond158 = 0, $24 = 0, $idxprom161 = 0, $arrayidx162 = 0, $25 = 0, $conv163 = 0, $shl164 = 0, $26 = 0, $conv166 = 0, $shr167116 = 0, $add168 = 0, $arrayidx169 = 0, $27 = 0, $and172 = 0, $shl173 = 0, $and174 = 0, $tobool175 = 0, $add_ptr179 = 0, $call210 = 0, $sub_ptr_lhs_cast181 = 0, $sub_ptr_rhs_cast182 = 0, $sub_ptr_sub183 = 0, $cmp184 = 0, $sub_ptr_lhs_cast189 = 0, $sub_ptr_rhs_cast190 = 0, $sub_ptr_sub191 = 0, $cmp192 = 0, $sub_ptr_lhs_cast197 = 0, $sub_ptr_rhs_cast198 = 0, $sub_ptr_sub199 = 0, $cmp200 = 0, $add_ptr207 = 0, $cmp141 = 0, $ptr_addr_2 = 0, $add_ptr212 = 0, $ptr_addr_3 = 0, $add_ptr214 = 0, $cmp215 = 0, $arrayidx219 = 0, $28 = 0, $cmp221 = 0, $29 = 0, $cmp225 = 0, $add_ptr229 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx3 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 16) {
+ label = 17;
+ break;
+ } else if (($cond | 0) == 15) {
+ label = 25;
+ break;
+ } else if (($cond | 0) == 17) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 7:
+ $ptr_addr_0156 = $ptr + 2 | 0;
+ $cmp76157 = ($ptr_addr_0156 | 0) == ($end | 0);
+ if ($cmp76157) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type84 = $enc + 72 | 0;
+ $4 = $type84;
+ $ptr_pn158 = $ptr;
+ $ptr_addr_0159 = $ptr_addr_0156;
+ label = 28;
+ break;
+ case 9:
+ $5 = HEAP8[$arrayidx] | 0;
+ $idxprom8 = $5 & 255;
+ $arrayidx9 = $idxprom8 + 9272 | 0;
+ $6 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $6 & 255;
+ $shl = $conv10 << 3;
+ $7 = HEAP8[$ptr] | 0;
+ $conv12 = $7 & 255;
+ $shr118 = $conv12 >>> 5;
+ $add = $shr118 | $shl;
+ $arrayidx13 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx13 >> 2] | 0;
+ $and = $conv12 & 31;
+ $shl16 = 1 << $and;
+ $and17 = $shl16 & $8;
+ $tobool = ($and17 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp22 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp22) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast27 = $end;
+ $sub_ptr_rhs_cast28 = $ptr;
+ $sub_ptr_sub29 = $sub_ptr_lhs_cast27 - $sub_ptr_rhs_cast28 | 0;
+ $cmp30 = ($sub_ptr_sub29 | 0) < 3;
+ if ($cmp30) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast35 = $end;
+ $sub_ptr_rhs_cast36 = $ptr;
+ $sub_ptr_sub37 = $sub_ptr_lhs_cast35 - $sub_ptr_rhs_cast36 | 0;
+ $cmp38 = ($sub_ptr_sub37 | 0) < 4;
+ if ($cmp38) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 17:
+ $add_ptr43 = $ptr + 2 | 0;
+ $cmp44 = ($add_ptr43 | 0) == ($end | 0);
+ if ($cmp44) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $arrayidx48 = $ptr + 3 | 0;
+ $9 = HEAP8[$arrayidx48] | 0;
+ $cmp50 = $9 << 24 >> 24 == 0;
+ $10 = HEAP8[$add_ptr43] | 0;
+ if ($cmp50) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom53 = $10 & 255;
+ $type54 = $enc + 72 | 0;
+ $11 = $type54;
+ $arrayidx55 = $11 + $idxprom53 | 0;
+ $12 = HEAP8[$arrayidx55] | 0;
+ $conv56 = $12 & 255;
+ $cond62 = $conv56;
+ label = 21;
+ break;
+ case 20:
+ $call60 = _unicode_byte_type($9, $10) | 0;
+ $cond62 = $call60;
+ label = 21;
+ break;
+ case 21:
+ if (($cond62 | 0) == 27) {
+ label = 22;
+ break;
+ } else if (($cond62 | 0) == 20) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 22:
+ $add_ptr64 = $ptr + 4 | 0;
+ $call65 = _little2_scanComment($enc, $add_ptr64, $end, $nextTokPtr) | 0;
+ $retval_0 = $call65;
+ label = 65;
+ break;
+ case 23:
+ $add_ptr67 = $ptr + 4 | 0;
+ $call68 = _little2_scanCdataSection($add_ptr67, $end, $nextTokPtr) | 0;
+ $retval_0 = $call68;
+ label = 65;
+ break;
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr43;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 25:
+ $add_ptr70 = $ptr + 2 | 0;
+ $call71 = _little2_scanPi($enc, $add_ptr70, $end, $nextTokPtr) | 0;
+ $retval_0 = $call71;
+ label = 65;
+ break;
+ case 26:
+ $add_ptr73 = $ptr + 2 | 0;
+ $call74 = _little2_scanEndTag($enc, $add_ptr73, $end, $nextTokPtr) | 0;
+ $retval_0 = $call74;
+ label = 65;
+ break;
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 28:
+ $arrayidx78 = $ptr_pn158 + 3 | 0;
+ $13 = HEAP8[$arrayidx78] | 0;
+ $cmp80 = $13 << 24 >> 24 == 0;
+ $14 = HEAP8[$ptr_addr_0159] | 0;
+ if ($cmp80) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ $idxprom83 = $14 & 255;
+ $arrayidx85 = $4 + $idxprom83 | 0;
+ $15 = HEAP8[$arrayidx85] | 0;
+ $conv86 = $15 & 255;
+ $cond92 = $conv86;
+ label = 31;
+ break;
+ case 30:
+ $call90 = _unicode_byte_type($13, $14) | 0;
+ $cond92 = $call90;
+ label = 31;
+ break;
+ case 31:
+ if (($cond92 | 0) == 29) {
+ label = 32;
+ break;
+ } else if (($cond92 | 0) == 22 | ($cond92 | 0) == 24 | ($cond92 | 0) == 25 | ($cond92 | 0) == 26 | ($cond92 | 0) == 27) {
+ label = 33;
+ break;
+ } else if (($cond92 | 0) == 5) {
+ label = 35;
+ break;
+ } else if (($cond92 | 0) == 6) {
+ label = 37;
+ break;
+ } else if (($cond92 | 0) == 7) {
+ label = 39;
+ break;
+ } else if (($cond92 | 0) == 21 | ($cond92 | 0) == 9 | ($cond92 | 0) == 10) {
+ label = 41;
+ break;
+ } else if (($cond92 | 0) == 11) {
+ $ptr_addr_2 = $ptr_addr_0159;
+ label = 58;
+ break;
+ } else if (($cond92 | 0) == 17) {
+ $ptr_addr_3 = $ptr_addr_0159;
+ label = 59;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 32:
+ $16 = HEAP8[$arrayidx78] | 0;
+ $idxprom95 = $16 & 255;
+ $arrayidx96 = $idxprom95 + 10824 | 0;
+ $17 = HEAP8[$arrayidx96] | 0;
+ $conv97 = $17 & 255;
+ $shl98 = $conv97 << 3;
+ $18 = HEAP8[$ptr_addr_0159] | 0;
+ $conv100 = $18 & 255;
+ $shr101117 = $conv100 >>> 5;
+ $add102 = $shr101117 | $shl98;
+ $arrayidx103 = 9544 + ($add102 << 2) | 0;
+ $19 = HEAP32[$arrayidx103 >> 2] | 0;
+ $and106 = $conv100 & 31;
+ $shl107 = 1 << $and106;
+ $and108 = $shl107 & $19;
+ $tobool109 = ($and108 | 0) == 0;
+ if ($tobool109) {
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $ptr_addr_0 = $ptr_addr_0159 + 2 | 0;
+ $cmp76 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp76) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ $ptr_pn158 = $ptr_addr_0159;
+ $ptr_addr_0159 = $ptr_addr_0;
+ label = 28;
+ break;
+ }
+ case 34:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 35:
+ $sub_ptr_lhs_cast115 = $end;
+ $sub_ptr_rhs_cast116 = $ptr_addr_0159;
+ $sub_ptr_sub117 = $sub_ptr_lhs_cast115 - $sub_ptr_rhs_cast116 | 0;
+ $cmp118 = ($sub_ptr_sub117 | 0) < 2;
+ if ($cmp118) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 37:
+ $sub_ptr_lhs_cast123 = $end;
+ $sub_ptr_rhs_cast124 = $ptr_addr_0159;
+ $sub_ptr_sub125 = $sub_ptr_lhs_cast123 - $sub_ptr_rhs_cast124 | 0;
+ $cmp126 = ($sub_ptr_sub125 | 0) < 3;
+ if ($cmp126) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 39:
+ $sub_ptr_lhs_cast131 = $end;
+ $sub_ptr_rhs_cast132 = $ptr_addr_0159;
+ $sub_ptr_sub133 = $sub_ptr_lhs_cast131 - $sub_ptr_rhs_cast132 | 0;
+ $cmp134 = ($sub_ptr_sub133 | 0) < 4;
+ if ($cmp134) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 41:
+ $add_ptr139 = $ptr_pn158 + 4 | 0;
+ $cmp141135 = ($add_ptr139 | 0) == ($end | 0);
+ if ($cmp141135) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $type150 = $enc + 72 | 0;
+ $20 = $type150;
+ $ptr_addr_1136 = $add_ptr139;
+ label = 43;
+ break;
+ case 43:
+ $arrayidx144 = $ptr_addr_1136 + 1 | 0;
+ $21 = HEAP8[$arrayidx144] | 0;
+ $cmp146 = $21 << 24 >> 24 == 0;
+ $22 = HEAP8[$ptr_addr_1136] | 0;
+ if ($cmp146) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 44:
+ $idxprom149 = $22 & 255;
+ $arrayidx151 = $20 + $idxprom149 | 0;
+ $23 = HEAP8[$arrayidx151] | 0;
+ $conv152 = $23 & 255;
+ $cond158 = $conv152;
+ label = 46;
+ break;
+ case 45:
+ $call156 = _unicode_byte_type($21, $22) | 0;
+ $cond158 = $call156;
+ label = 46;
+ break;
+ case 46:
+ if (($cond158 | 0) == 29) {
+ label = 47;
+ break;
+ } else if (($cond158 | 0) == 22 | ($cond158 | 0) == 24) {
+ label = 49;
+ break;
+ } else if (($cond158 | 0) == 5) {
+ label = 50;
+ break;
+ } else if (($cond158 | 0) == 6) {
+ label = 52;
+ break;
+ } else if (($cond158 | 0) == 7) {
+ label = 54;
+ break;
+ } else if (($cond158 | 0) == 21 | ($cond158 | 0) == 9 | ($cond158 | 0) == 10) {
+ label = 56;
+ break;
+ } else if (($cond158 | 0) == 11) {
+ $ptr_addr_2 = $ptr_addr_1136;
+ label = 58;
+ break;
+ } else if (($cond158 | 0) == 17) {
+ $ptr_addr_3 = $ptr_addr_1136;
+ label = 59;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 47:
+ $24 = HEAP8[$arrayidx144] | 0;
+ $idxprom161 = $24 & 255;
+ $arrayidx162 = $idxprom161 + 9272 | 0;
+ $25 = HEAP8[$arrayidx162] | 0;
+ $conv163 = $25 & 255;
+ $shl164 = $conv163 << 3;
+ $26 = HEAP8[$ptr_addr_1136] | 0;
+ $conv166 = $26 & 255;
+ $shr167116 = $conv166 >>> 5;
+ $add168 = $shr167116 | $shl164;
+ $arrayidx169 = 9544 + ($add168 << 2) | 0;
+ $27 = HEAP32[$arrayidx169 >> 2] | 0;
+ $and172 = $conv166 & 31;
+ $shl173 = 1 << $and172;
+ $and174 = $shl173 & $27;
+ $tobool175 = ($and174 | 0) == 0;
+ if ($tobool175) {
+ label = 48;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 48:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 49:
+ $add_ptr179 = $ptr_addr_1136 + 2 | 0;
+ $call210 = _little2_scanAtts($enc, $add_ptr179, $end, $nextTokPtr) | 0;
+ $retval_0 = $call210;
+ label = 65;
+ break;
+ case 50:
+ $sub_ptr_lhs_cast181 = $end;
+ $sub_ptr_rhs_cast182 = $ptr_addr_1136;
+ $sub_ptr_sub183 = $sub_ptr_lhs_cast181 - $sub_ptr_rhs_cast182 | 0;
+ $cmp184 = ($sub_ptr_sub183 | 0) < 2;
+ if ($cmp184) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 52:
+ $sub_ptr_lhs_cast189 = $end;
+ $sub_ptr_rhs_cast190 = $ptr_addr_1136;
+ $sub_ptr_sub191 = $sub_ptr_lhs_cast189 - $sub_ptr_rhs_cast190 | 0;
+ $cmp192 = ($sub_ptr_sub191 | 0) < 3;
+ if ($cmp192) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 54:
+ $sub_ptr_lhs_cast197 = $end;
+ $sub_ptr_rhs_cast198 = $ptr_addr_1136;
+ $sub_ptr_sub199 = $sub_ptr_lhs_cast197 - $sub_ptr_rhs_cast198 | 0;
+ $cmp200 = ($sub_ptr_sub199 | 0) < 4;
+ if ($cmp200) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 56:
+ $add_ptr207 = $ptr_addr_1136 + 2 | 0;
+ $cmp141 = ($add_ptr207 | 0) == ($end | 0);
+ if ($cmp141) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ $ptr_addr_1136 = $add_ptr207;
+ label = 43;
+ break;
+ }
+ case 57:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 58:
+ $add_ptr212 = $ptr_addr_2 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr212;
+ $retval_0 = 2;
+ label = 65;
+ break;
+ case 59:
+ $add_ptr214 = $ptr_addr_3 + 2 | 0;
+ $cmp215 = ($add_ptr214 | 0) == ($end | 0);
+ if ($cmp215) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $arrayidx219 = $ptr_addr_3 + 3 | 0;
+ $28 = HEAP8[$arrayidx219] | 0;
+ $cmp221 = $28 << 24 >> 24 == 0;
+ if ($cmp221) {
+ label = 61;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 61:
+ $29 = HEAP8[$add_ptr214] | 0;
+ $cmp225 = $29 << 24 >> 24 == 62;
+ if ($cmp225) {
+ label = 63;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 62:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr214;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 63:
+ $add_ptr229 = $ptr_addr_3 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr229;
+ $retval_0 = 4;
+ label = 65;
+ break;
+ case 64:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 65:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanComment($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $cmp5 = 0, $add_ptr = 0, $cmp836 = 0, $type = 0, $2 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_lhs_cast24 = 0, $sub_ptr_lhs_cast33 = 0, $ptr_addr_037 = 0, $arrayidx10 = 0, $3 = 0, $cmp12 = 0, $4 = 0, $idxprom = 0, $arrayidx14 = 0, $5 = 0, $conv15 = 0, $call = 0, $cond = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp18 = 0, $add_ptr22 = 0, $sub_ptr_rhs_cast25 = 0, $sub_ptr_sub26 = 0, $cmp27 = 0, $add_ptr31 = 0, $sub_ptr_rhs_cast34 = 0, $sub_ptr_sub35 = 0, $cmp36 = 0, $add_ptr40 = 0, $add_ptr43 = 0, $cmp44 = 0, $arrayidx48 = 0, $6 = 0, $cmp50 = 0, $ptr_addr_0_be = 0, $cmp8 = 0, $7 = 0, $cmp55 = 0, $add_ptr58 = 0, $cmp59 = 0, $arrayidx63 = 0, $8 = 0, $cmp65 = 0, $9 = 0, $cmp70 = 0, $add_ptr74 = 0, $add_ptr76 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$ptr] | 0;
+ $cmp5 = $1 << 24 >> 24 == 45;
+ if ($cmp5) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 6:
+ $add_ptr = $ptr + 2 | 0;
+ $cmp836 = ($add_ptr | 0) == ($end | 0);
+ if ($cmp836) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_lhs_cast24 = $end;
+ $sub_ptr_lhs_cast33 = $end;
+ $ptr_addr_037 = $add_ptr;
+ label = 8;
+ break;
+ case 8:
+ $arrayidx10 = $ptr_addr_037 + 1 | 0;
+ $3 = HEAP8[$arrayidx10] | 0;
+ $cmp12 = $3 << 24 >> 24 == 0;
+ $4 = HEAP8[$ptr_addr_037] | 0;
+ if ($cmp12) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $idxprom = $4 & 255;
+ $arrayidx14 = $2 + $idxprom | 0;
+ $5 = HEAP8[$arrayidx14] | 0;
+ $conv15 = $5 & 255;
+ $cond = $conv15;
+ label = 11;
+ break;
+ case 10:
+ $call = _unicode_byte_type($3, $4) | 0;
+ $cond = $call;
+ label = 11;
+ break;
+ case 11:
+ if (($cond | 0) == 5) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 14;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 16;
+ break;
+ } else if (($cond | 0) == 0 | ($cond | 0) == 1 | ($cond | 0) == 8) {
+ label = 18;
+ break;
+ } else if (($cond | 0) == 27) {
+ label = 19;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 12:
+ $sub_ptr_rhs_cast = $ptr_addr_037;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp18 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp18) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $add_ptr22 = $ptr_addr_037 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr22;
+ label = 21;
+ break;
+ case 14:
+ $sub_ptr_rhs_cast25 = $ptr_addr_037;
+ $sub_ptr_sub26 = $sub_ptr_lhs_cast24 - $sub_ptr_rhs_cast25 | 0;
+ $cmp27 = ($sub_ptr_sub26 | 0) < 3;
+ if ($cmp27) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $add_ptr31 = $ptr_addr_037 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr31;
+ label = 21;
+ break;
+ case 16:
+ $sub_ptr_rhs_cast34 = $ptr_addr_037;
+ $sub_ptr_sub35 = $sub_ptr_lhs_cast33 - $sub_ptr_rhs_cast34 | 0;
+ $cmp36 = ($sub_ptr_sub35 | 0) < 4;
+ if ($cmp36) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $add_ptr40 = $ptr_addr_037 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr40;
+ label = 21;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_037;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 19:
+ $add_ptr43 = $ptr_addr_037 + 2 | 0;
+ $cmp44 = ($add_ptr43 | 0) == ($end | 0);
+ if ($cmp44) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $arrayidx48 = $ptr_addr_037 + 3 | 0;
+ $6 = HEAP8[$arrayidx48] | 0;
+ $cmp50 = $6 << 24 >> 24 == 0;
+ if ($cmp50) {
+ label = 22;
+ break;
+ } else {
+ $ptr_addr_0_be = $add_ptr43;
+ label = 21;
+ break;
+ }
+ case 21:
+ $cmp8 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp8) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ $ptr_addr_037 = $ptr_addr_0_be;
+ label = 8;
+ break;
+ }
+ case 22:
+ $7 = HEAP8[$add_ptr43] | 0;
+ $cmp55 = $7 << 24 >> 24 == 45;
+ if ($cmp55) {
+ label = 23;
+ break;
+ } else {
+ $ptr_addr_0_be = $add_ptr43;
+ label = 21;
+ break;
+ }
+ case 23:
+ $add_ptr58 = $ptr_addr_037 + 4 | 0;
+ $cmp59 = ($add_ptr58 | 0) == ($end | 0);
+ if ($cmp59) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $arrayidx63 = $ptr_addr_037 + 5 | 0;
+ $8 = HEAP8[$arrayidx63] | 0;
+ $cmp65 = $8 << 24 >> 24 == 0;
+ if ($cmp65) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $9 = HEAP8[$add_ptr58] | 0;
+ $cmp70 = $9 << 24 >> 24 == 62;
+ if ($cmp70) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr58;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 27:
+ $add_ptr74 = $ptr_addr_037 + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr74;
+ $retval_0 = 13;
+ label = 29;
+ break;
+ case 28:
+ $add_ptr76 = $ptr_addr_037 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr76;
+ label = 21;
+ break;
+ case 29:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanPi($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $tok = 0, $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $ptr_addr_0111 = 0, $cmp42112 = 0, $type50 = 0, $4 = 0, $5 = 0, $idxprom8 = 0, $arrayidx9 = 0, $6 = 0, $conv10 = 0, $shl = 0, $7 = 0, $conv12 = 0, $shr91 = 0, $add = 0, $arrayidx13 = 0, $8 = 0, $and = 0, $shl16 = 0, $and17 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp22 = 0, $sub_ptr_lhs_cast27 = 0, $sub_ptr_rhs_cast28 = 0, $sub_ptr_sub29 = 0, $cmp30 = 0, $sub_ptr_lhs_cast35 = 0, $sub_ptr_rhs_cast36 = 0, $sub_ptr_sub37 = 0, $cmp38 = 0, $ptr_addr_0114 = 0, $ptr_pn113 = 0, $arrayidx44 = 0, $9 = 0, $cmp46 = 0, $10 = 0, $idxprom49 = 0, $arrayidx51 = 0, $11 = 0, $conv52 = 0, $call56 = 0, $cond58 = 0, $12 = 0, $idxprom61 = 0, $arrayidx62 = 0, $13 = 0, $conv63 = 0, $shl64 = 0, $14 = 0, $conv66 = 0, $shr6790 = 0, $add68 = 0, $arrayidx69 = 0, $15 = 0, $and72 = 0, $shl73 = 0, $and74 = 0, $tobool75 = 0, $ptr_addr_0 = 0, $cmp42 = 0, $sub_ptr_lhs_cast81 = 0, $sub_ptr_rhs_cast82 = 0, $sub_ptr_sub83 = 0, $cmp84 = 0, $sub_ptr_lhs_cast89 = 0, $sub_ptr_rhs_cast90 = 0, $sub_ptr_sub91 = 0, $cmp92 = 0, $sub_ptr_lhs_cast97 = 0, $sub_ptr_rhs_cast98 = 0, $sub_ptr_sub99 = 0, $cmp100 = 0, $call105 = 0, $tobool106 = 0, $add_ptr109 = 0, $cmp11194 = 0, $type120 = 0, $16 = 0, $sub_ptr_lhs_cast130 = 0, $sub_ptr_lhs_cast139 = 0, $sub_ptr_lhs_cast148 = 0, $ptr_addr_195 = 0, $arrayidx114 = 0, $17 = 0, $cmp116 = 0, $18 = 0, $idxprom119 = 0, $arrayidx121 = 0, $19 = 0, $conv122 = 0, $call126 = 0, $cond128 = 0, $sub_ptr_rhs_cast131 = 0, $sub_ptr_sub132 = 0, $cmp133 = 0, $add_ptr137 = 0, $sub_ptr_rhs_cast140 = 0, $sub_ptr_sub141 = 0, $cmp142 = 0, $add_ptr146 = 0, $sub_ptr_rhs_cast149 = 0, $sub_ptr_sub150 = 0, $cmp151 = 0, $add_ptr155 = 0, $add_ptr158 = 0, $cmp159 = 0, $arrayidx163 = 0, $20 = 0, $cmp165 = 0, $ptr_addr_1_be = 0, $cmp111 = 0, $21 = 0, $cmp169 = 0, $add_ptr172 = 0, $22 = 0, $add_ptr175 = 0, $call178 = 0, $tobool179 = 0, $add_ptr182 = 0, $cmp183 = 0, $arrayidx187 = 0, $23 = 0, $cmp189 = 0, $24 = 0, $cmp194 = 0, $add_ptr197 = 0, $25 = 0, $ptr_addr_2 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tok = __stackBase__ | 0;
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx3 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 7:
+ $ptr_addr_0111 = $ptr + 2 | 0;
+ $cmp42112 = ($ptr_addr_0111 | 0) == ($end | 0);
+ if ($cmp42112) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type50 = $enc + 72 | 0;
+ $4 = $type50;
+ $ptr_pn113 = $ptr;
+ $ptr_addr_0114 = $ptr_addr_0111;
+ label = 18;
+ break;
+ case 9:
+ $5 = HEAP8[$arrayidx] | 0;
+ $idxprom8 = $5 & 255;
+ $arrayidx9 = $idxprom8 + 9272 | 0;
+ $6 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $6 & 255;
+ $shl = $conv10 << 3;
+ $7 = HEAP8[$ptr] | 0;
+ $conv12 = $7 & 255;
+ $shr91 = $conv12 >>> 5;
+ $add = $shr91 | $shl;
+ $arrayidx13 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx13 >> 2] | 0;
+ $and = $conv12 & 31;
+ $shl16 = 1 << $and;
+ $and17 = $shl16 & $8;
+ $tobool = ($and17 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp22 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp22) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast27 = $end;
+ $sub_ptr_rhs_cast28 = $ptr;
+ $sub_ptr_sub29 = $sub_ptr_lhs_cast27 - $sub_ptr_rhs_cast28 | 0;
+ $cmp30 = ($sub_ptr_sub29 | 0) < 3;
+ if ($cmp30) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast35 = $end;
+ $sub_ptr_rhs_cast36 = $ptr;
+ $sub_ptr_sub37 = $sub_ptr_lhs_cast35 - $sub_ptr_rhs_cast36 | 0;
+ $cmp38 = ($sub_ptr_sub37 | 0) < 4;
+ if ($cmp38) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 18:
+ $arrayidx44 = $ptr_pn113 + 3 | 0;
+ $9 = HEAP8[$arrayidx44] | 0;
+ $cmp46 = $9 << 24 >> 24 == 0;
+ $10 = HEAP8[$ptr_addr_0114] | 0;
+ if ($cmp46) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom49 = $10 & 255;
+ $arrayidx51 = $4 + $idxprom49 | 0;
+ $11 = HEAP8[$arrayidx51] | 0;
+ $conv52 = $11 & 255;
+ $cond58 = $conv52;
+ label = 21;
+ break;
+ case 20:
+ $call56 = _unicode_byte_type($9, $10) | 0;
+ $cond58 = $call56;
+ label = 21;
+ break;
+ case 21:
+ if (($cond58 | 0) == 29) {
+ label = 22;
+ break;
+ } else if (($cond58 | 0) == 22 | ($cond58 | 0) == 24 | ($cond58 | 0) == 25 | ($cond58 | 0) == 26 | ($cond58 | 0) == 27) {
+ label = 23;
+ break;
+ } else if (($cond58 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($cond58 | 0) == 6) {
+ label = 27;
+ break;
+ } else if (($cond58 | 0) == 7) {
+ label = 29;
+ break;
+ } else if (($cond58 | 0) == 21 | ($cond58 | 0) == 9 | ($cond58 | 0) == 10) {
+ label = 31;
+ break;
+ } else if (($cond58 | 0) == 15) {
+ label = 52;
+ break;
+ } else {
+ $ptr_addr_2 = $ptr_addr_0114;
+ label = 58;
+ break;
+ }
+ case 22:
+ $12 = HEAP8[$arrayidx44] | 0;
+ $idxprom61 = $12 & 255;
+ $arrayidx62 = $idxprom61 + 10824 | 0;
+ $13 = HEAP8[$arrayidx62] | 0;
+ $conv63 = $13 & 255;
+ $shl64 = $conv63 << 3;
+ $14 = HEAP8[$ptr_addr_0114] | 0;
+ $conv66 = $14 & 255;
+ $shr6790 = $conv66 >>> 5;
+ $add68 = $shr6790 | $shl64;
+ $arrayidx69 = 9544 + ($add68 << 2) | 0;
+ $15 = HEAP32[$arrayidx69 >> 2] | 0;
+ $and72 = $conv66 & 31;
+ $shl73 = 1 << $and72;
+ $and74 = $shl73 & $15;
+ $tobool75 = ($and74 | 0) == 0;
+ if ($tobool75) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $ptr_addr_0 = $ptr_addr_0114 + 2 | 0;
+ $cmp42 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp42) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ $ptr_pn113 = $ptr_addr_0114;
+ $ptr_addr_0114 = $ptr_addr_0;
+ label = 18;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast81 = $end;
+ $sub_ptr_rhs_cast82 = $ptr_addr_0114;
+ $sub_ptr_sub83 = $sub_ptr_lhs_cast81 - $sub_ptr_rhs_cast82 | 0;
+ $cmp84 = ($sub_ptr_sub83 | 0) < 2;
+ if ($cmp84) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast89 = $end;
+ $sub_ptr_rhs_cast90 = $ptr_addr_0114;
+ $sub_ptr_sub91 = $sub_ptr_lhs_cast89 - $sub_ptr_rhs_cast90 | 0;
+ $cmp92 = ($sub_ptr_sub91 | 0) < 3;
+ if ($cmp92) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 29:
+ $sub_ptr_lhs_cast97 = $end;
+ $sub_ptr_rhs_cast98 = $ptr_addr_0114;
+ $sub_ptr_sub99 = $sub_ptr_lhs_cast97 - $sub_ptr_rhs_cast98 | 0;
+ $cmp100 = ($sub_ptr_sub99 | 0) < 4;
+ if ($cmp100) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 31:
+ $call105 = _little2_checkPiTarget($ptr, $ptr_addr_0114, $tok) | 0;
+ $tobool106 = ($call105 | 0) == 0;
+ if ($tobool106) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 32:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 33:
+ $add_ptr109 = $ptr_pn113 + 4 | 0;
+ $cmp11194 = ($add_ptr109 | 0) == ($end | 0);
+ if ($cmp11194) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $type120 = $enc + 72 | 0;
+ $16 = $type120;
+ $sub_ptr_lhs_cast130 = $end;
+ $sub_ptr_lhs_cast139 = $end;
+ $sub_ptr_lhs_cast148 = $end;
+ $ptr_addr_195 = $add_ptr109;
+ label = 35;
+ break;
+ case 35:
+ $arrayidx114 = $ptr_addr_195 + 1 | 0;
+ $17 = HEAP8[$arrayidx114] | 0;
+ $cmp116 = $17 << 24 >> 24 == 0;
+ $18 = HEAP8[$ptr_addr_195] | 0;
+ if ($cmp116) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ $idxprom119 = $18 & 255;
+ $arrayidx121 = $16 + $idxprom119 | 0;
+ $19 = HEAP8[$arrayidx121] | 0;
+ $conv122 = $19 & 255;
+ $cond128 = $conv122;
+ label = 38;
+ break;
+ case 37:
+ $call126 = _unicode_byte_type($17, $18) | 0;
+ $cond128 = $call126;
+ label = 38;
+ break;
+ case 38:
+ if (($cond128 | 0) == 5) {
+ label = 39;
+ break;
+ } else if (($cond128 | 0) == 6) {
+ label = 41;
+ break;
+ } else if (($cond128 | 0) == 7) {
+ label = 43;
+ break;
+ } else if (($cond128 | 0) == 0 | ($cond128 | 0) == 1 | ($cond128 | 0) == 8) {
+ label = 45;
+ break;
+ } else if (($cond128 | 0) == 15) {
+ label = 46;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 39:
+ $sub_ptr_rhs_cast131 = $ptr_addr_195;
+ $sub_ptr_sub132 = $sub_ptr_lhs_cast130 - $sub_ptr_rhs_cast131 | 0;
+ $cmp133 = ($sub_ptr_sub132 | 0) < 2;
+ if ($cmp133) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $add_ptr137 = $ptr_addr_195 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr137;
+ label = 48;
+ break;
+ case 41:
+ $sub_ptr_rhs_cast140 = $ptr_addr_195;
+ $sub_ptr_sub141 = $sub_ptr_lhs_cast139 - $sub_ptr_rhs_cast140 | 0;
+ $cmp142 = ($sub_ptr_sub141 | 0) < 3;
+ if ($cmp142) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $add_ptr146 = $ptr_addr_195 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr146;
+ label = 48;
+ break;
+ case 43:
+ $sub_ptr_rhs_cast149 = $ptr_addr_195;
+ $sub_ptr_sub150 = $sub_ptr_lhs_cast148 - $sub_ptr_rhs_cast149 | 0;
+ $cmp151 = ($sub_ptr_sub150 | 0) < 4;
+ if ($cmp151) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $add_ptr155 = $ptr_addr_195 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr155;
+ label = 48;
+ break;
+ case 45:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_195;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 46:
+ $add_ptr158 = $ptr_addr_195 + 2 | 0;
+ $cmp159 = ($add_ptr158 | 0) == ($end | 0);
+ if ($cmp159) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $arrayidx163 = $ptr_addr_195 + 3 | 0;
+ $20 = HEAP8[$arrayidx163] | 0;
+ $cmp165 = $20 << 24 >> 24 == 0;
+ if ($cmp165) {
+ label = 49;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr158;
+ label = 48;
+ break;
+ }
+ case 48:
+ $cmp111 = ($ptr_addr_1_be | 0) == ($end | 0);
+ if ($cmp111) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ $ptr_addr_195 = $ptr_addr_1_be;
+ label = 35;
+ break;
+ }
+ case 49:
+ $21 = HEAP8[$add_ptr158] | 0;
+ $cmp169 = $21 << 24 >> 24 == 62;
+ if ($cmp169) {
+ label = 50;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr158;
+ label = 48;
+ break;
+ }
+ case 50:
+ $add_ptr172 = $ptr_addr_195 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr172;
+ $22 = HEAP32[$tok >> 2] | 0;
+ $retval_0 = $22;
+ label = 59;
+ break;
+ case 51:
+ $add_ptr175 = $ptr_addr_195 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr175;
+ label = 48;
+ break;
+ case 52:
+ $call178 = _little2_checkPiTarget($ptr, $ptr_addr_0114, $tok) | 0;
+ $tobool179 = ($call178 | 0) == 0;
+ if ($tobool179) {
+ label = 53;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 53:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 54:
+ $add_ptr182 = $ptr_pn113 + 4 | 0;
+ $cmp183 = ($add_ptr182 | 0) == ($end | 0);
+ if ($cmp183) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ $arrayidx187 = $ptr_pn113 + 5 | 0;
+ $23 = HEAP8[$arrayidx187] | 0;
+ $cmp189 = $23 << 24 >> 24 == 0;
+ if ($cmp189) {
+ label = 56;
+ break;
+ } else {
+ $ptr_addr_2 = $add_ptr182;
+ label = 58;
+ break;
+ }
+ case 56:
+ $24 = HEAP8[$add_ptr182] | 0;
+ $cmp194 = $24 << 24 >> 24 == 62;
+ if ($cmp194) {
+ label = 57;
+ break;
+ } else {
+ $ptr_addr_2 = $add_ptr182;
+ label = 58;
+ break;
+ }
+ case 57:
+ $add_ptr197 = $ptr_pn113 + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr197;
+ $25 = HEAP32[$tok >> 2] | 0;
+ $retval_0 = $25;
+ label = 59;
+ break;
+ case 58:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_2;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 59:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanEndTag($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $ptr_addr_084 = 0, $cmp4285 = 0, $type50 = 0, $4 = 0, $5 = 0, $idxprom8 = 0, $arrayidx9 = 0, $6 = 0, $conv10 = 0, $shl = 0, $7 = 0, $conv12 = 0, $shr64 = 0, $add = 0, $arrayidx13 = 0, $8 = 0, $and = 0, $shl16 = 0, $and17 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp22 = 0, $sub_ptr_lhs_cast27 = 0, $sub_ptr_rhs_cast28 = 0, $sub_ptr_sub29 = 0, $cmp30 = 0, $sub_ptr_lhs_cast35 = 0, $sub_ptr_rhs_cast36 = 0, $sub_ptr_sub37 = 0, $cmp38 = 0, $ptr_addr_087 = 0, $ptr_pn86 = 0, $arrayidx44 = 0, $9 = 0, $cmp46 = 0, $10 = 0, $idxprom49 = 0, $arrayidx51 = 0, $11 = 0, $conv52 = 0, $call56 = 0, $cond58 = 0, $12 = 0, $idxprom61 = 0, $arrayidx62 = 0, $13 = 0, $conv63 = 0, $shl64 = 0, $14 = 0, $conv66 = 0, $shr6763 = 0, $add68 = 0, $arrayidx69 = 0, $15 = 0, $and72 = 0, $shl73 = 0, $and74 = 0, $tobool75 = 0, $ptr_addr_0 = 0, $cmp42 = 0, $sub_ptr_lhs_cast81 = 0, $sub_ptr_rhs_cast82 = 0, $sub_ptr_sub83 = 0, $cmp84 = 0, $sub_ptr_lhs_cast89 = 0, $sub_ptr_rhs_cast90 = 0, $sub_ptr_sub91 = 0, $cmp92 = 0, $sub_ptr_lhs_cast97 = 0, $sub_ptr_rhs_cast98 = 0, $sub_ptr_sub99 = 0, $cmp100 = 0, $add_ptr105 = 0, $cmp10667 = 0, $type114 = 0, $16 = 0, $ptr_addr_168 = 0, $arrayidx108 = 0, $17 = 0, $cmp110 = 0, $18 = 0, $idxprom113 = 0, $arrayidx115 = 0, $19 = 0, $conv116 = 0, $call120 = 0, $cond122 = 0, $add_ptr125 = 0, $add_ptr128 = 0, $cmp106 = 0, $add_ptr130 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx3 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 7:
+ $ptr_addr_084 = $ptr + 2 | 0;
+ $cmp4285 = ($ptr_addr_084 | 0) == ($end | 0);
+ if ($cmp4285) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type50 = $enc + 72 | 0;
+ $4 = $type50;
+ $ptr_pn86 = $ptr;
+ $ptr_addr_087 = $ptr_addr_084;
+ label = 18;
+ break;
+ case 9:
+ $5 = HEAP8[$arrayidx] | 0;
+ $idxprom8 = $5 & 255;
+ $arrayidx9 = $idxprom8 + 9272 | 0;
+ $6 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $6 & 255;
+ $shl = $conv10 << 3;
+ $7 = HEAP8[$ptr] | 0;
+ $conv12 = $7 & 255;
+ $shr64 = $conv12 >>> 5;
+ $add = $shr64 | $shl;
+ $arrayidx13 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx13 >> 2] | 0;
+ $and = $conv12 & 31;
+ $shl16 = 1 << $and;
+ $and17 = $shl16 & $8;
+ $tobool = ($and17 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp22 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp22) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast27 = $end;
+ $sub_ptr_rhs_cast28 = $ptr;
+ $sub_ptr_sub29 = $sub_ptr_lhs_cast27 - $sub_ptr_rhs_cast28 | 0;
+ $cmp30 = ($sub_ptr_sub29 | 0) < 3;
+ if ($cmp30) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast35 = $end;
+ $sub_ptr_rhs_cast36 = $ptr;
+ $sub_ptr_sub37 = $sub_ptr_lhs_cast35 - $sub_ptr_rhs_cast36 | 0;
+ $cmp38 = ($sub_ptr_sub37 | 0) < 4;
+ if ($cmp38) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 18:
+ $arrayidx44 = $ptr_pn86 + 3 | 0;
+ $9 = HEAP8[$arrayidx44] | 0;
+ $cmp46 = $9 << 24 >> 24 == 0;
+ $10 = HEAP8[$ptr_addr_087] | 0;
+ if ($cmp46) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom49 = $10 & 255;
+ $arrayidx51 = $4 + $idxprom49 | 0;
+ $11 = HEAP8[$arrayidx51] | 0;
+ $conv52 = $11 & 255;
+ $cond58 = $conv52;
+ label = 21;
+ break;
+ case 20:
+ $call56 = _unicode_byte_type($9, $10) | 0;
+ $cond58 = $call56;
+ label = 21;
+ break;
+ case 21:
+ if (($cond58 | 0) == 29) {
+ label = 22;
+ break;
+ } else if (($cond58 | 0) == 22 | ($cond58 | 0) == 24 | ($cond58 | 0) == 25 | ($cond58 | 0) == 26 | ($cond58 | 0) == 27) {
+ label = 23;
+ break;
+ } else if (($cond58 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($cond58 | 0) == 6) {
+ label = 27;
+ break;
+ } else if (($cond58 | 0) == 7) {
+ label = 29;
+ break;
+ } else if (($cond58 | 0) == 21 | ($cond58 | 0) == 9 | ($cond58 | 0) == 10) {
+ label = 31;
+ break;
+ } else if (($cond58 | 0) == 11) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 22:
+ $12 = HEAP8[$arrayidx44] | 0;
+ $idxprom61 = $12 & 255;
+ $arrayidx62 = $idxprom61 + 10824 | 0;
+ $13 = HEAP8[$arrayidx62] | 0;
+ $conv63 = $13 & 255;
+ $shl64 = $conv63 << 3;
+ $14 = HEAP8[$ptr_addr_087] | 0;
+ $conv66 = $14 & 255;
+ $shr6763 = $conv66 >>> 5;
+ $add68 = $shr6763 | $shl64;
+ $arrayidx69 = 9544 + ($add68 << 2) | 0;
+ $15 = HEAP32[$arrayidx69 >> 2] | 0;
+ $and72 = $conv66 & 31;
+ $shl73 = 1 << $and72;
+ $and74 = $shl73 & $15;
+ $tobool75 = ($and74 | 0) == 0;
+ if ($tobool75) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $ptr_addr_0 = $ptr_addr_087 + 2 | 0;
+ $cmp42 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp42) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ $ptr_pn86 = $ptr_addr_087;
+ $ptr_addr_087 = $ptr_addr_0;
+ label = 18;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast81 = $end;
+ $sub_ptr_rhs_cast82 = $ptr_addr_087;
+ $sub_ptr_sub83 = $sub_ptr_lhs_cast81 - $sub_ptr_rhs_cast82 | 0;
+ $cmp84 = ($sub_ptr_sub83 | 0) < 2;
+ if ($cmp84) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast89 = $end;
+ $sub_ptr_rhs_cast90 = $ptr_addr_087;
+ $sub_ptr_sub91 = $sub_ptr_lhs_cast89 - $sub_ptr_rhs_cast90 | 0;
+ $cmp92 = ($sub_ptr_sub91 | 0) < 3;
+ if ($cmp92) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 29:
+ $sub_ptr_lhs_cast97 = $end;
+ $sub_ptr_rhs_cast98 = $ptr_addr_087;
+ $sub_ptr_sub99 = $sub_ptr_lhs_cast97 - $sub_ptr_rhs_cast98 | 0;
+ $cmp100 = ($sub_ptr_sub99 | 0) < 4;
+ if ($cmp100) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 31:
+ $add_ptr105 = $ptr_pn86 + 4 | 0;
+ $cmp10667 = ($add_ptr105 | 0) == ($end | 0);
+ if ($cmp10667) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $type114 = $enc + 72 | 0;
+ $16 = $type114;
+ $ptr_addr_168 = $add_ptr105;
+ label = 33;
+ break;
+ case 33:
+ $arrayidx108 = $ptr_addr_168 + 1 | 0;
+ $17 = HEAP8[$arrayidx108] | 0;
+ $cmp110 = $17 << 24 >> 24 == 0;
+ $18 = HEAP8[$ptr_addr_168] | 0;
+ if ($cmp110) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ $idxprom113 = $18 & 255;
+ $arrayidx115 = $16 + $idxprom113 | 0;
+ $19 = HEAP8[$arrayidx115] | 0;
+ $conv116 = $19 & 255;
+ $cond122 = $conv116;
+ label = 36;
+ break;
+ case 35:
+ $call120 = _unicode_byte_type($17, $18) | 0;
+ $cond122 = $call120;
+ label = 36;
+ break;
+ case 36:
+ if (($cond122 | 0) == 11) {
+ label = 37;
+ break;
+ } else if (($cond122 | 0) == 21 | ($cond122 | 0) == 9 | ($cond122 | 0) == 10) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ $add_ptr125 = $ptr_addr_168 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr125;
+ $retval_0 = 5;
+ label = 42;
+ break;
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_168;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 39:
+ $add_ptr128 = $ptr_addr_168 + 2 | 0;
+ $cmp106 = ($add_ptr128 | 0) == ($end | 0);
+ if ($cmp106) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ $ptr_addr_168 = $add_ptr128;
+ label = 33;
+ break;
+ }
+ case 40:
+ $add_ptr130 = $ptr_pn86 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr130;
+ $retval_0 = 5;
+ label = 42;
+ break;
+ case 41:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 42:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_checkPiTarget($ptr, $end, $tokPtr) {
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $tokPtr = $tokPtr | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $conv4 = 0, $upper_0 = 0, $arrayidx6 = 0, $2 = 0, $cmp8 = 0, $add_ptr = 0, $3 = 0, $conv12 = 0, $upper_1 = 0, $arrayidx21 = 0, $4 = 0, $cmp23 = 0, $add_ptr20 = 0, $5 = 0, $conv27 = 0, $tobool = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[$tokPtr >> 2] = 11;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp = ($sub_ptr_sub | 0) == 6;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$ptr] | 0;
+ $conv4 = $1 << 24 >> 24;
+ if (($conv4 | 0) == 88) {
+ label = 5;
+ break;
+ } else if (($conv4 | 0) == 120) {
+ $upper_0 = 0;
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 5:
+ $upper_0 = 1;
+ label = 6;
+ break;
+ case 6:
+ $arrayidx6 = $ptr + 3 | 0;
+ $2 = HEAP8[$arrayidx6] | 0;
+ $cmp8 = $2 << 24 >> 24 == 0;
+ if ($cmp8) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 7:
+ $add_ptr = $ptr + 2 | 0;
+ $3 = HEAP8[$add_ptr] | 0;
+ $conv12 = $3 << 24 >> 24;
+ if (($conv12 | 0) == 77) {
+ label = 8;
+ break;
+ } else if (($conv12 | 0) == 109) {
+ $upper_1 = $upper_0;
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 8:
+ $upper_1 = 1;
+ label = 9;
+ break;
+ case 9:
+ $arrayidx21 = $ptr + 5 | 0;
+ $4 = HEAP8[$arrayidx21] | 0;
+ $cmp23 = $4 << 24 >> 24 == 0;
+ if ($cmp23) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 10:
+ $add_ptr20 = $ptr + 4 | 0;
+ $5 = HEAP8[$add_ptr20] | 0;
+ $conv27 = $5 << 24 >> 24;
+ if (($conv27 | 0) == 76) {
+ label = 11;
+ break;
+ } else if (($conv27 | 0) == 108) {
+ label = 12;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 11:
+ $retval_0 = 0;
+ label = 14;
+ break;
+ case 12:
+ $tobool = ($upper_1 | 0) == 0;
+ if ($tobool) {
+ label = 13;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 14;
+ break;
+ }
+ case 13:
+ HEAP32[$tokPtr >> 2] = 12;
+ $retval_0 = 1;
+ label = 14;
+ break;
+ case 14:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanAtts($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $ptr_addr = 0, $cmp68 = 0, $type = 0, $0 = 0, $type52 = 0, $1 = 0, $type79 = 0, $2 = 0, $type111 = 0, $3 = 0, $sub_ptr_lhs_cast125 = 0, $sub_ptr_lhs_cast134 = 0, $sub_ptr_lhs_cast143 = 0, $type179 = 0, $4 = 0, $type205 = 0, $5 = 0, $6 = 0, $arrayidx = 0, $7 = 0, $cmp1 = 0, $8 = 0, $idxprom = 0, $arrayidx3 = 0, $9 = 0, $conv4 = 0, $call = 0, $cond = 0, $10 = 0, $add_ptr4150 = 0, $cmp4251 = 0, $11 = 0, $arrayidx7 = 0, $12 = 0, $idxprom8 = 0, $arrayidx9 = 0, $13 = 0, $conv10 = 0, $shl = 0, $14 = 0, $conv12 = 0, $shr49 = 0, $add = 0, $arrayidx13 = 0, $15 = 0, $and = 0, $shl16 = 0, $and17 = 0, $tobool = 0, $16 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp20 = 0, $17 = 0, $sub_ptr_lhs_cast25 = 0, $sub_ptr_rhs_cast26 = 0, $sub_ptr_sub27 = 0, $cmp28 = 0, $18 = 0, $sub_ptr_lhs_cast33 = 0, $sub_ptr_rhs_cast34 = 0, $sub_ptr_sub35 = 0, $cmp36 = 0, $add_ptr4152 = 0, $19 = 0, $arrayidx46 = 0, $20 = 0, $cmp48 = 0, $21 = 0, $idxprom51 = 0, $arrayidx53 = 0, $22 = 0, $conv54 = 0, $call58 = 0, $cond60 = 0, $23 = 0, $add_ptr41 = 0, $cmp42 = 0, $24 = 0, $25 = 0, $add_ptr6855 = 0, $cmp6956 = 0, $add_ptr6857 = 0, $26 = 0, $arrayidx73 = 0, $27 = 0, $cmp75 = 0, $28 = 0, $idxprom78 = 0, $arrayidx80 = 0, $29 = 0, $conv81 = 0, $call85 = 0, $cond87 = 0, $cond87_off = 0, $30 = 0, $31 = 0, $add_ptr68 = 0, $cmp69 = 0, $32 = 0, $33 = 0, $add_ptr98 = 0, $cmp10159 = 0, $34 = 0, $arrayidx105 = 0, $35 = 0, $cmp107 = 0, $36 = 0, $idxprom110 = 0, $arrayidx112 = 0, $37 = 0, $conv113 = 0, $call117 = 0, $cond119 = 0, $cmp120 = 0, $38 = 0, $sub_ptr_rhs_cast126 = 0, $sub_ptr_sub127 = 0, $cmp128 = 0, $add_ptr132 = 0, $39 = 0, $sub_ptr_rhs_cast135 = 0, $sub_ptr_sub136 = 0, $cmp137 = 0, $add_ptr141 = 0, $40 = 0, $sub_ptr_rhs_cast144 = 0, $sub_ptr_sub145 = 0, $cmp146 = 0, $add_ptr150 = 0, $41 = 0, $42 = 0, $add_ptr153 = 0, $call154 = 0, $cmp155 = 0, $43 = 0, $cmp101 = 0, $cmp158 = 0, $44 = 0, $45 = 0, $46 = 0, $add_ptr165 = 0, $47 = 0, $add_ptr168 = 0, $cmp169 = 0, $arrayidx173 = 0, $48 = 0, $cmp175 = 0, $49 = 0, $idxprom178 = 0, $arrayidx180 = 0, $50 = 0, $conv181 = 0, $call185 = 0, $cond187 = 0, $51 = 0, $add_ptr19461 = 0, $cmp19562 = 0, $52 = 0, $add_ptr19463 = 0, $53 = 0, $arrayidx199 = 0, $54 = 0, $cmp201 = 0, $55 = 0, $idxprom204 = 0, $arrayidx206 = 0, $56 = 0, $conv207 = 0, $call211 = 0, $cond213 = 0, $57 = 0, $add_ptr194 = 0, $cmp195 = 0, $58 = 0, $arrayidx215 = 0, $59 = 0, $idxprom216 = 0, $arrayidx217 = 0, $60 = 0, $conv218 = 0, $shl219 = 0, $61 = 0, $conv221 = 0, $shr22248 = 0, $add223 = 0, $arrayidx224 = 0, $62 = 0, $and227 = 0, $shl228 = 0, $and229 = 0, $tobool230 = 0, $_pn = 0, $storemerge = 0, $cmp = 0, $63 = 0, $sub_ptr_lhs_cast236 = 0, $sub_ptr_rhs_cast237 = 0, $sub_ptr_sub238 = 0, $cmp239 = 0, $64 = 0, $sub_ptr_lhs_cast244 = 0, $sub_ptr_rhs_cast245 = 0, $sub_ptr_sub246 = 0, $cmp247 = 0, $65 = 0, $sub_ptr_lhs_cast252 = 0, $sub_ptr_rhs_cast253 = 0, $sub_ptr_sub254 = 0, $cmp255 = 0, $66 = 0, $add_ptr261 = 0, $67 = 0, $add_ptr263 = 0, $cmp264 = 0, $arrayidx268 = 0, $68 = 0, $cmp270 = 0, $69 = 0, $cmp274 = 0, $70 = 0, $add_ptr278 = 0, $71 = 0, $72 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr_addr = __stackBase__ | 0;
+ HEAP32[$ptr_addr >> 2] = $ptr;
+ $cmp68 = ($ptr | 0) == ($end | 0);
+ if ($cmp68) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $type52 = $enc + 72 | 0;
+ $1 = $type52;
+ $type79 = $enc + 72 | 0;
+ $2 = $type79;
+ $type111 = $enc + 72 | 0;
+ $3 = $type111;
+ $sub_ptr_lhs_cast125 = $end;
+ $sub_ptr_lhs_cast134 = $end;
+ $sub_ptr_lhs_cast143 = $end;
+ $type179 = $enc + 72 | 0;
+ $4 = $type179;
+ $type205 = $enc + 72 | 0;
+ $5 = $type205;
+ $6 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $6 + 1 | 0;
+ $7 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $7 << 24 >> 24 == 0;
+ $8 = HEAP8[$6] | 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $idxprom = $8 & 255;
+ $arrayidx3 = $0 + $idxprom | 0;
+ $9 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $9 & 255;
+ $cond = $conv4;
+ label = 7;
+ break;
+ case 6:
+ $call = _unicode_byte_type($7, $8) | 0;
+ $cond = $call;
+ label = 7;
+ break;
+ case 7:
+ if (($cond | 0) == 21 | ($cond | 0) == 9 | ($cond | 0) == 10) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 14) {
+ label = 23;
+ break;
+ } else if (($cond | 0) == 22 | ($cond | 0) == 24 | ($cond | 0) == 25 | ($cond | 0) == 26 | ($cond | 0) == 27) {
+ label = 64;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 8:
+ $10 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr4150 = $10 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr4150;
+ $cmp4251 = ($add_ptr4150 | 0) == ($end | 0);
+ if ($cmp4251) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $19 = $10;
+ $add_ptr4152 = $add_ptr4150;
+ label = 17;
+ break;
+ }
+ case 9:
+ $11 = HEAP32[$ptr_addr >> 2] | 0;
+ $arrayidx7 = $11 + 1 | 0;
+ $12 = HEAP8[$arrayidx7] | 0;
+ $idxprom8 = $12 & 255;
+ $arrayidx9 = $idxprom8 + 10824 | 0;
+ $13 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $13 & 255;
+ $shl = $conv10 << 3;
+ $14 = HEAP8[$11] | 0;
+ $conv12 = $14 & 255;
+ $shr49 = $conv12 >>> 5;
+ $add = $shr49 | $shl;
+ $arrayidx13 = 9544 + ($add << 2) | 0;
+ $15 = HEAP32[$arrayidx13 >> 2] | 0;
+ $and = $conv12 & 31;
+ $shl16 = 1 << $and;
+ $and17 = $shl16 & $15;
+ $tobool = ($and17 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $11;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 11:
+ $16 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $16;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp20 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp20) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $16;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 13:
+ $17 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast25 = $end;
+ $sub_ptr_rhs_cast26 = $17;
+ $sub_ptr_sub27 = $sub_ptr_lhs_cast25 - $sub_ptr_rhs_cast26 | 0;
+ $cmp28 = ($sub_ptr_sub27 | 0) < 3;
+ if ($cmp28) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $17;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 15:
+ $18 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast33 = $end;
+ $sub_ptr_rhs_cast34 = $18;
+ $sub_ptr_sub35 = $sub_ptr_lhs_cast33 - $sub_ptr_rhs_cast34 | 0;
+ $cmp36 = ($sub_ptr_sub35 | 0) < 4;
+ if ($cmp36) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $18;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 17:
+ $arrayidx46 = $19 + 3 | 0;
+ $20 = HEAP8[$arrayidx46] | 0;
+ $cmp48 = $20 << 24 >> 24 == 0;
+ $21 = HEAP8[$add_ptr4152] | 0;
+ if ($cmp48) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $idxprom51 = $21 & 255;
+ $arrayidx53 = $1 + $idxprom51 | 0;
+ $22 = HEAP8[$arrayidx53] | 0;
+ $conv54 = $22 & 255;
+ $cond60 = $conv54;
+ label = 20;
+ break;
+ case 19:
+ $call58 = _unicode_byte_type($20, $21) | 0;
+ $cond60 = $call58;
+ label = 20;
+ break;
+ case 20:
+ if (($cond60 | 0) == 21 | ($cond60 | 0) == 10 | ($cond60 | 0) == 9) {
+ label = 21;
+ break;
+ } else if (($cond60 | 0) == 14) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $23 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr41 = $23 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr41;
+ $cmp42 = ($add_ptr41 | 0) == ($end | 0);
+ if ($cmp42) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $19 = $23;
+ $add_ptr4152 = $add_ptr41;
+ label = 17;
+ break;
+ }
+ case 22:
+ $24 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $24;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 23:
+ $25 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr6855 = $25 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr6855;
+ $cmp6956 = ($add_ptr6855 | 0) == ($end | 0);
+ if ($cmp6956) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $26 = $25;
+ $add_ptr6857 = $add_ptr6855;
+ label = 24;
+ break;
+ }
+ case 24:
+ $arrayidx73 = $26 + 3 | 0;
+ $27 = HEAP8[$arrayidx73] | 0;
+ $cmp75 = $27 << 24 >> 24 == 0;
+ $28 = HEAP8[$add_ptr6857] | 0;
+ if ($cmp75) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $idxprom78 = $28 & 255;
+ $arrayidx80 = $2 + $idxprom78 | 0;
+ $29 = HEAP8[$arrayidx80] | 0;
+ $conv81 = $29 & 255;
+ $cond87 = $conv81;
+ label = 27;
+ break;
+ case 26:
+ $call85 = _unicode_byte_type($27, $28) | 0;
+ $cond87 = $call85;
+ label = 27;
+ break;
+ case 27:
+ $cond87_off = $cond87 - 12 | 0;
+ $30 = $cond87_off >>> 0 < 2;
+ if ($30) {
+ label = 31;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ if (($cond87 | 0) == 21 | ($cond87 | 0) == 10 | ($cond87 | 0) == 9) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ $31 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr68 = $31 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr68;
+ $cmp69 = ($add_ptr68 | 0) == ($end | 0);
+ if ($cmp69) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $26 = $31;
+ $add_ptr6857 = $add_ptr68;
+ label = 24;
+ break;
+ }
+ case 30:
+ $32 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $32;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 31:
+ $33 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr98 = $33 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr98;
+ $cmp10159 = ($add_ptr98 | 0) == ($end | 0);
+ if ($cmp10159) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $34 = $add_ptr98;
+ label = 32;
+ break;
+ }
+ case 32:
+ $arrayidx105 = $34 + 1 | 0;
+ $35 = HEAP8[$arrayidx105] | 0;
+ $cmp107 = $35 << 24 >> 24 == 0;
+ $36 = HEAP8[$34] | 0;
+ if ($cmp107) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ $idxprom110 = $36 & 255;
+ $arrayidx112 = $3 + $idxprom110 | 0;
+ $37 = HEAP8[$arrayidx112] | 0;
+ $conv113 = $37 & 255;
+ $cond119 = $conv113;
+ label = 35;
+ break;
+ case 34:
+ $call117 = _unicode_byte_type($35, $36) | 0;
+ $cond119 = $call117;
+ label = 35;
+ break;
+ case 35:
+ $cmp120 = ($cond119 | 0) == ($cond87 | 0);
+ if ($cmp120) {
+ label = 50;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ if (($cond119 | 0) == 5) {
+ label = 37;
+ break;
+ } else if (($cond119 | 0) == 6) {
+ label = 39;
+ break;
+ } else if (($cond119 | 0) == 7) {
+ label = 41;
+ break;
+ } else if (($cond119 | 0) == 0 | ($cond119 | 0) == 1 | ($cond119 | 0) == 8) {
+ label = 43;
+ break;
+ } else if (($cond119 | 0) == 3) {
+ label = 44;
+ break;
+ } else if (($cond119 | 0) == 2) {
+ label = 48;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 37:
+ $38 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_rhs_cast126 = $38;
+ $sub_ptr_sub127 = $sub_ptr_lhs_cast125 - $sub_ptr_rhs_cast126 | 0;
+ $cmp128 = ($sub_ptr_sub127 | 0) < 2;
+ if ($cmp128) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $add_ptr132 = $38 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr132;
+ label = 45;
+ break;
+ case 39:
+ $39 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_rhs_cast135 = $39;
+ $sub_ptr_sub136 = $sub_ptr_lhs_cast134 - $sub_ptr_rhs_cast135 | 0;
+ $cmp137 = ($sub_ptr_sub136 | 0) < 3;
+ if ($cmp137) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $add_ptr141 = $39 + 3 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr141;
+ label = 45;
+ break;
+ case 41:
+ $40 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_rhs_cast144 = $40;
+ $sub_ptr_sub145 = $sub_ptr_lhs_cast143 - $sub_ptr_rhs_cast144 | 0;
+ $cmp146 = ($sub_ptr_sub145 | 0) < 4;
+ if ($cmp146) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $add_ptr150 = $40 + 4 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr150;
+ label = 45;
+ break;
+ case 43:
+ $41 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $41;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 44:
+ $42 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr153 = $42 + 2 | 0;
+ $call154 = _little2_scanRef($enc, $add_ptr153, $end, $ptr_addr) | 0;
+ $cmp155 = ($call154 | 0) < 1;
+ if ($cmp155) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $43 = HEAP32[$ptr_addr >> 2] | 0;
+ $cmp101 = ($43 | 0) == ($end | 0);
+ if ($cmp101) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $34 = $43;
+ label = 32;
+ break;
+ }
+ case 46:
+ $cmp158 = ($call154 | 0) == 0;
+ if ($cmp158) {
+ label = 47;
+ break;
+ } else {
+ $retval_0 = $call154;
+ label = 79;
+ break;
+ }
+ case 47:
+ $44 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $44;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 48:
+ $45 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $45;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 49:
+ $46 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr165 = $46 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr165;
+ label = 45;
+ break;
+ case 50:
+ $47 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr168 = $47 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr168;
+ $cmp169 = ($add_ptr168 | 0) == ($end | 0);
+ if ($cmp169) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $arrayidx173 = $47 + 3 | 0;
+ $48 = HEAP8[$arrayidx173] | 0;
+ $cmp175 = $48 << 24 >> 24 == 0;
+ $49 = HEAP8[$add_ptr168] | 0;
+ if ($cmp175) {
+ label = 52;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 52:
+ $idxprom178 = $49 & 255;
+ $arrayidx180 = $4 + $idxprom178 | 0;
+ $50 = HEAP8[$arrayidx180] | 0;
+ $conv181 = $50 & 255;
+ $cond187 = $conv181;
+ label = 54;
+ break;
+ case 53:
+ $call185 = _unicode_byte_type($48, $49) | 0;
+ $cond187 = $call185;
+ label = 54;
+ break;
+ case 54:
+ if (($cond187 | 0) == 21 | ($cond187 | 0) == 9 | ($cond187 | 0) == 10) {
+ label = 55;
+ break;
+ } else if (($cond187 | 0) == 11) {
+ label = 71;
+ break;
+ } else if (($cond187 | 0) == 17) {
+ label = 72;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 55:
+ $51 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr19461 = $51 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr19461;
+ $cmp19562 = ($add_ptr19461 | 0) == ($end | 0);
+ if ($cmp19562) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $53 = $51;
+ $add_ptr19463 = $add_ptr19461;
+ label = 57;
+ break;
+ }
+ case 56:
+ $52 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $52;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 57:
+ $arrayidx199 = $53 + 3 | 0;
+ $54 = HEAP8[$arrayidx199] | 0;
+ $cmp201 = $54 << 24 >> 24 == 0;
+ $55 = HEAP8[$add_ptr19463] | 0;
+ if ($cmp201) {
+ label = 58;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 58:
+ $idxprom204 = $55 & 255;
+ $arrayidx206 = $5 + $idxprom204 | 0;
+ $56 = HEAP8[$arrayidx206] | 0;
+ $conv207 = $56 & 255;
+ $cond213 = $conv207;
+ label = 60;
+ break;
+ case 59:
+ $call211 = _unicode_byte_type($54, $55) | 0;
+ $cond213 = $call211;
+ label = 60;
+ break;
+ case 60:
+ if (($cond213 | 0) == 21 | ($cond213 | 0) == 9 | ($cond213 | 0) == 10) {
+ label = 61;
+ break;
+ } else if (($cond213 | 0) == 29) {
+ label = 62;
+ break;
+ } else if (($cond213 | 0) == 22 | ($cond213 | 0) == 24) {
+ label = 64;
+ break;
+ } else if (($cond213 | 0) == 5) {
+ label = 65;
+ break;
+ } else if (($cond213 | 0) == 6) {
+ label = 67;
+ break;
+ } else if (($cond213 | 0) == 7) {
+ label = 69;
+ break;
+ } else if (($cond213 | 0) == 11) {
+ label = 71;
+ break;
+ } else if (($cond213 | 0) == 17) {
+ label = 72;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 61:
+ $57 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr194 = $57 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr194;
+ $cmp195 = ($add_ptr194 | 0) == ($end | 0);
+ if ($cmp195) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $53 = $57;
+ $add_ptr19463 = $add_ptr194;
+ label = 57;
+ break;
+ }
+ case 62:
+ $58 = HEAP32[$ptr_addr >> 2] | 0;
+ $arrayidx215 = $58 + 1 | 0;
+ $59 = HEAP8[$arrayidx215] | 0;
+ $idxprom216 = $59 & 255;
+ $arrayidx217 = $idxprom216 + 9272 | 0;
+ $60 = HEAP8[$arrayidx217] | 0;
+ $conv218 = $60 & 255;
+ $shl219 = $conv218 << 3;
+ $61 = HEAP8[$58] | 0;
+ $conv221 = $61 & 255;
+ $shr22248 = $conv221 >>> 5;
+ $add223 = $shr22248 | $shl219;
+ $arrayidx224 = 9544 + ($add223 << 2) | 0;
+ $62 = HEAP32[$arrayidx224 >> 2] | 0;
+ $and227 = $conv221 & 31;
+ $shl228 = 1 << $and227;
+ $and229 = $shl228 & $62;
+ $tobool230 = ($and229 | 0) == 0;
+ if ($tobool230) {
+ label = 63;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 63:
+ HEAP32[$nextTokPtr >> 2] = $58;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 64:
+ $_pn = HEAP32[$ptr_addr >> 2] | 0;
+ $storemerge = $_pn + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $storemerge;
+ $cmp = ($storemerge | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $6 = $storemerge;
+ label = 4;
+ break;
+ }
+ case 65:
+ $63 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast236 = $end;
+ $sub_ptr_rhs_cast237 = $63;
+ $sub_ptr_sub238 = $sub_ptr_lhs_cast236 - $sub_ptr_rhs_cast237 | 0;
+ $cmp239 = ($sub_ptr_sub238 | 0) < 2;
+ if ($cmp239) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ HEAP32[$nextTokPtr >> 2] = $63;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 67:
+ $64 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast244 = $end;
+ $sub_ptr_rhs_cast245 = $64;
+ $sub_ptr_sub246 = $sub_ptr_lhs_cast244 - $sub_ptr_rhs_cast245 | 0;
+ $cmp247 = ($sub_ptr_sub246 | 0) < 3;
+ if ($cmp247) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ HEAP32[$nextTokPtr >> 2] = $64;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 69:
+ $65 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast252 = $end;
+ $sub_ptr_rhs_cast253 = $65;
+ $sub_ptr_sub254 = $sub_ptr_lhs_cast252 - $sub_ptr_rhs_cast253 | 0;
+ $cmp255 = ($sub_ptr_sub254 | 0) < 4;
+ if ($cmp255) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ HEAP32[$nextTokPtr >> 2] = $65;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 71:
+ $66 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr261 = $66 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr261;
+ $retval_0 = 1;
+ label = 79;
+ break;
+ case 72:
+ $67 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr263 = $67 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr263;
+ $cmp264 = ($add_ptr263 | 0) == ($end | 0);
+ if ($cmp264) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $arrayidx268 = $67 + 3 | 0;
+ $68 = HEAP8[$arrayidx268] | 0;
+ $cmp270 = $68 << 24 >> 24 == 0;
+ if ($cmp270) {
+ label = 74;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 74:
+ $69 = HEAP8[$add_ptr263] | 0;
+ $cmp274 = $69 << 24 >> 24 == 62;
+ if ($cmp274) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $70 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $70;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 76:
+ $add_ptr278 = $67 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr278;
+ $retval_0 = 3;
+ label = 79;
+ break;
+ case 77:
+ $71 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $71;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 78:
+ $72 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $72;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 79:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanLit($open, $enc, $ptr, $end, $nextTokPtr) {
+ $open = $open | 0;
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp27 = 0, $type = 0, $0 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_lhs_cast10 = 0, $sub_ptr_lhs_cast19 = 0, $ptr_addr_028 = 0, $arrayidx = 0, $1 = 0, $cmp1 = 0, $2 = 0, $idxprom = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp7 = 0, $add_ptr = 0, $sub_ptr_rhs_cast11 = 0, $sub_ptr_sub12 = 0, $cmp13 = 0, $add_ptr17 = 0, $sub_ptr_rhs_cast20 = 0, $sub_ptr_sub21 = 0, $cmp22 = 0, $add_ptr26 = 0, $add_ptr29 = 0, $cmp30 = 0, $cmp34 = 0, $arrayidx38 = 0, $4 = 0, $cmp40 = 0, $5 = 0, $idxprom43 = 0, $type44 = 0, $6 = 0, $arrayidx45 = 0, $7 = 0, $conv46 = 0, $call50 = 0, $cond52 = 0, $add_ptr55 = 0, $ptr_addr_0_be = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp27 = ($ptr | 0) == ($end | 0);
+ if ($cmp27) {
+ $retval_0 = -1;
+ label = 24;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_lhs_cast10 = $end;
+ $sub_ptr_lhs_cast19 = $end;
+ $ptr_addr_028 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $ptr_addr_028 + 1 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $1 << 24 >> 24 == 0;
+ $2 = HEAP8[$ptr_addr_028] | 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $idxprom = $2 & 255;
+ $arrayidx3 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 7;
+ break;
+ case 6:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 7;
+ break;
+ case 7:
+ if (($cond | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 0 | ($cond | 0) == 1 | ($cond | 0) == 8) {
+ label = 14;
+ break;
+ } else if (($cond | 0) == 12 | ($cond | 0) == 13) {
+ label = 15;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 8:
+ $sub_ptr_rhs_cast = $ptr_addr_028;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp7 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp7) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add_ptr = $ptr_addr_028 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 23;
+ break;
+ case 10:
+ $sub_ptr_rhs_cast11 = $ptr_addr_028;
+ $sub_ptr_sub12 = $sub_ptr_lhs_cast10 - $sub_ptr_rhs_cast11 | 0;
+ $cmp13 = ($sub_ptr_sub12 | 0) < 3;
+ if ($cmp13) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $add_ptr17 = $ptr_addr_028 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr17;
+ label = 23;
+ break;
+ case 12:
+ $sub_ptr_rhs_cast20 = $ptr_addr_028;
+ $sub_ptr_sub21 = $sub_ptr_lhs_cast19 - $sub_ptr_rhs_cast20 | 0;
+ $cmp22 = ($sub_ptr_sub21 | 0) < 4;
+ if ($cmp22) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $add_ptr26 = $ptr_addr_028 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr26;
+ label = 23;
+ break;
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_028;
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 15:
+ $add_ptr29 = $ptr_addr_028 + 2 | 0;
+ $cmp30 = ($cond | 0) == ($open | 0);
+ if ($cmp30) {
+ label = 16;
+ break;
+ } else {
+ $ptr_addr_0_be = $add_ptr29;
+ label = 23;
+ break;
+ }
+ case 16:
+ $cmp34 = ($add_ptr29 | 0) == ($end | 0);
+ if ($cmp34) {
+ $retval_0 = -27;
+ label = 24;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr29;
+ $arrayidx38 = $ptr_addr_028 + 3 | 0;
+ $4 = HEAP8[$arrayidx38] | 0;
+ $cmp40 = $4 << 24 >> 24 == 0;
+ $5 = HEAP8[$add_ptr29] | 0;
+ if ($cmp40) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $idxprom43 = $5 & 255;
+ $type44 = $enc + 72 | 0;
+ $6 = $type44;
+ $arrayidx45 = $6 + $idxprom43 | 0;
+ $7 = HEAP8[$arrayidx45] | 0;
+ $conv46 = $7 & 255;
+ $cond52 = $conv46;
+ label = 20;
+ break;
+ case 19:
+ $call50 = _unicode_byte_type($4, $5) | 0;
+ $cond52 = $call50;
+ label = 20;
+ break;
+ case 20:
+ if (($cond52 | 0) == 21 | ($cond52 | 0) == 9 | ($cond52 | 0) == 10 | ($cond52 | 0) == 11 | ($cond52 | 0) == 30 | ($cond52 | 0) == 20) {
+ $retval_0 = 27;
+ label = 24;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 22:
+ $add_ptr55 = $ptr_addr_028 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr55;
+ label = 23;
+ break;
+ case 23:
+ $cmp = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_028 = $ptr_addr_0_be;
+ label = 4;
+ break;
+ }
+ case 24:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanDecl($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $ptr_addr_038 = 0, $cmp1239 = 0, $type20 = 0, $4 = 0, $add_ptr = 0, $call7 = 0, $add_ptr9 = 0, $ptr_addr_041 = 0, $ptr_pn40 = 0, $arrayidx14 = 0, $5 = 0, $cmp16 = 0, $6 = 0, $idxprom19 = 0, $arrayidx21 = 0, $7 = 0, $conv22 = 0, $call26 = 0, $cond28 = 0, $ptr_addr_0 = 0, $cmp12 = 0, $add_ptr30 = 0, $cmp31 = 0, $arrayidx36 = 0, $8 = 0, $cmp38 = 0, $9 = 0, $idxprom42 = 0, $type43 = 0, $10 = 0, $arrayidx44 = 0, $11 = 0, $conv45 = 0, $call51 = 0, $cond53 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 25;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx3 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 27) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 20) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $ptr_addr_038 = $ptr + 2 | 0;
+ $cmp1239 = ($ptr_addr_038 | 0) == ($end | 0);
+ if ($cmp1239) {
+ $retval_0 = -1;
+ label = 25;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type20 = $enc + 72 | 0;
+ $4 = $type20;
+ $ptr_pn40 = $ptr;
+ $ptr_addr_041 = $ptr_addr_038;
+ label = 12;
+ break;
+ case 9:
+ $add_ptr = $ptr + 2 | 0;
+ $call7 = _little2_scanComment($enc, $add_ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call7;
+ label = 25;
+ break;
+ case 10:
+ $add_ptr9 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr9;
+ $retval_0 = 33;
+ label = 25;
+ break;
+ case 11:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 25;
+ break;
+ case 12:
+ $arrayidx14 = $ptr_pn40 + 3 | 0;
+ $5 = HEAP8[$arrayidx14] | 0;
+ $cmp16 = $5 << 24 >> 24 == 0;
+ $6 = HEAP8[$ptr_addr_041] | 0;
+ if ($cmp16) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $idxprom19 = $6 & 255;
+ $arrayidx21 = $4 + $idxprom19 | 0;
+ $7 = HEAP8[$arrayidx21] | 0;
+ $conv22 = $7 & 255;
+ $cond28 = $conv22;
+ label = 15;
+ break;
+ case 14:
+ $call26 = _unicode_byte_type($5, $6) | 0;
+ $cond28 = $call26;
+ label = 15;
+ break;
+ case 15:
+ if (($cond28 | 0) == 22 | ($cond28 | 0) == 24) {
+ label = 16;
+ break;
+ } else if (($cond28 | 0) == 30) {
+ label = 17;
+ break;
+ } else if (($cond28 | 0) == 21 | ($cond28 | 0) == 9 | ($cond28 | 0) == 10) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 16:
+ $ptr_addr_0 = $ptr_addr_041 + 2 | 0;
+ $cmp12 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp12) {
+ $retval_0 = -1;
+ label = 25;
+ break;
+ } else {
+ $ptr_pn40 = $ptr_addr_041;
+ $ptr_addr_041 = $ptr_addr_0;
+ label = 12;
+ break;
+ }
+ case 17:
+ $add_ptr30 = $ptr_pn40 + 4 | 0;
+ $cmp31 = ($add_ptr30 | 0) == ($end | 0);
+ if ($cmp31) {
+ $retval_0 = -1;
+ label = 25;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $arrayidx36 = $ptr_pn40 + 5 | 0;
+ $8 = HEAP8[$arrayidx36] | 0;
+ $cmp38 = $8 << 24 >> 24 == 0;
+ $9 = HEAP8[$add_ptr30] | 0;
+ if ($cmp38) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom42 = $9 & 255;
+ $type43 = $enc + 72 | 0;
+ $10 = $type43;
+ $arrayidx44 = $10 + $idxprom42 | 0;
+ $11 = HEAP8[$arrayidx44] | 0;
+ $conv45 = $11 & 255;
+ $cond53 = $conv45;
+ label = 21;
+ break;
+ case 20:
+ $call51 = _unicode_byte_type($8, $9) | 0;
+ $cond53 = $call51;
+ label = 21;
+ break;
+ case 21:
+ if (($cond53 | 0) == 21 | ($cond53 | 0) == 9 | ($cond53 | 0) == 10 | ($cond53 | 0) == 30) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_041;
+ $retval_0 = 0;
+ label = 25;
+ break;
+ case 23:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_041;
+ $retval_0 = 16;
+ label = 25;
+ break;
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_041;
+ $retval_0 = 0;
+ label = 25;
+ break;
+ case 25:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _little2_scanPoundName($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $arrayidx = 0, $0 = 0, $cmp1 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $ptr_addr_059 = 0, $cmp4260 = 0, $type50 = 0, $4 = 0, $5 = 0, $idxprom8 = 0, $arrayidx9 = 0, $6 = 0, $conv10 = 0, $shl = 0, $7 = 0, $conv12 = 0, $shr52 = 0, $add = 0, $arrayidx13 = 0, $8 = 0, $and = 0, $shl16 = 0, $and17 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp22 = 0, $sub_ptr_lhs_cast27 = 0, $sub_ptr_rhs_cast28 = 0, $sub_ptr_sub29 = 0, $cmp30 = 0, $sub_ptr_lhs_cast35 = 0, $sub_ptr_rhs_cast36 = 0, $sub_ptr_sub37 = 0, $cmp38 = 0, $ptr_addr_062 = 0, $ptr_pn61 = 0, $arrayidx44 = 0, $9 = 0, $cmp46 = 0, $10 = 0, $idxprom49 = 0, $arrayidx51 = 0, $11 = 0, $conv52 = 0, $call56 = 0, $cond58 = 0, $12 = 0, $idxprom61 = 0, $arrayidx62 = 0, $13 = 0, $conv63 = 0, $shl64 = 0, $14 = 0, $conv66 = 0, $shr6751 = 0, $add68 = 0, $arrayidx69 = 0, $15 = 0, $and72 = 0, $shl73 = 0, $and74 = 0, $tobool75 = 0, $ptr_addr_0 = 0, $cmp42 = 0, $sub_ptr_lhs_cast81 = 0, $sub_ptr_rhs_cast82 = 0, $sub_ptr_sub83 = 0, $cmp84 = 0, $sub_ptr_lhs_cast89 = 0, $sub_ptr_rhs_cast90 = 0, $sub_ptr_sub91 = 0, $cmp92 = 0, $sub_ptr_lhs_cast97 = 0, $sub_ptr_rhs_cast98 = 0, $sub_ptr_sub99 = 0, $cmp100 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 33;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $ptr + 1 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $1 = HEAP8[$ptr] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx3 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 7:
+ $ptr_addr_059 = $ptr + 2 | 0;
+ $cmp4260 = ($ptr_addr_059 | 0) == ($end | 0);
+ if ($cmp4260) {
+ $retval_0 = -20;
+ label = 33;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type50 = $enc + 72 | 0;
+ $4 = $type50;
+ $ptr_pn61 = $ptr;
+ $ptr_addr_062 = $ptr_addr_059;
+ label = 18;
+ break;
+ case 9:
+ $5 = HEAP8[$arrayidx] | 0;
+ $idxprom8 = $5 & 255;
+ $arrayidx9 = $idxprom8 + 9272 | 0;
+ $6 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $6 & 255;
+ $shl = $conv10 << 3;
+ $7 = HEAP8[$ptr] | 0;
+ $conv12 = $7 & 255;
+ $shr52 = $conv12 >>> 5;
+ $add = $shr52 | $shl;
+ $arrayidx13 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx13 >> 2] | 0;
+ $and = $conv12 & 31;
+ $shl16 = 1 << $and;
+ $and17 = $shl16 & $8;
+ $tobool = ($and17 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp22 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp22) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast27 = $end;
+ $sub_ptr_rhs_cast28 = $ptr;
+ $sub_ptr_sub29 = $sub_ptr_lhs_cast27 - $sub_ptr_rhs_cast28 | 0;
+ $cmp30 = ($sub_ptr_sub29 | 0) < 3;
+ if ($cmp30) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast35 = $end;
+ $sub_ptr_rhs_cast36 = $ptr;
+ $sub_ptr_sub37 = $sub_ptr_lhs_cast35 - $sub_ptr_rhs_cast36 | 0;
+ $cmp38 = ($sub_ptr_sub37 | 0) < 4;
+ if ($cmp38) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 18:
+ $arrayidx44 = $ptr_pn61 + 3 | 0;
+ $9 = HEAP8[$arrayidx44] | 0;
+ $cmp46 = $9 << 24 >> 24 == 0;
+ $10 = HEAP8[$ptr_addr_062] | 0;
+ if ($cmp46) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom49 = $10 & 255;
+ $arrayidx51 = $4 + $idxprom49 | 0;
+ $11 = HEAP8[$arrayidx51] | 0;
+ $conv52 = $11 & 255;
+ $cond58 = $conv52;
+ label = 21;
+ break;
+ case 20:
+ $call56 = _unicode_byte_type($9, $10) | 0;
+ $cond58 = $call56;
+ label = 21;
+ break;
+ case 21:
+ if (($cond58 | 0) == 29) {
+ label = 22;
+ break;
+ } else if (($cond58 | 0) == 22 | ($cond58 | 0) == 24 | ($cond58 | 0) == 25 | ($cond58 | 0) == 26 | ($cond58 | 0) == 27) {
+ label = 23;
+ break;
+ } else if (($cond58 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($cond58 | 0) == 6) {
+ label = 27;
+ break;
+ } else if (($cond58 | 0) == 7) {
+ label = 29;
+ break;
+ } else if (($cond58 | 0) == 9 | ($cond58 | 0) == 10 | ($cond58 | 0) == 21 | ($cond58 | 0) == 32 | ($cond58 | 0) == 11 | ($cond58 | 0) == 30 | ($cond58 | 0) == 36) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 22:
+ $12 = HEAP8[$arrayidx44] | 0;
+ $idxprom61 = $12 & 255;
+ $arrayidx62 = $idxprom61 + 10824 | 0;
+ $13 = HEAP8[$arrayidx62] | 0;
+ $conv63 = $13 & 255;
+ $shl64 = $conv63 << 3;
+ $14 = HEAP8[$ptr_addr_062] | 0;
+ $conv66 = $14 & 255;
+ $shr6751 = $conv66 >>> 5;
+ $add68 = $shr6751 | $shl64;
+ $arrayidx69 = 9544 + ($add68 << 2) | 0;
+ $15 = HEAP32[$arrayidx69 >> 2] | 0;
+ $and72 = $conv66 & 31;
+ $shl73 = 1 << $and72;
+ $and74 = $shl73 & $15;
+ $tobool75 = ($and74 | 0) == 0;
+ if ($tobool75) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $ptr_addr_0 = $ptr_addr_062 + 2 | 0;
+ $cmp42 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp42) {
+ $retval_0 = -20;
+ label = 33;
+ break;
+ } else {
+ $ptr_pn61 = $ptr_addr_062;
+ $ptr_addr_062 = $ptr_addr_0;
+ label = 18;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast81 = $end;
+ $sub_ptr_rhs_cast82 = $ptr_addr_062;
+ $sub_ptr_sub83 = $sub_ptr_lhs_cast81 - $sub_ptr_rhs_cast82 | 0;
+ $cmp84 = ($sub_ptr_sub83 | 0) < 2;
+ if ($cmp84) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast89 = $end;
+ $sub_ptr_rhs_cast90 = $ptr_addr_062;
+ $sub_ptr_sub91 = $sub_ptr_lhs_cast89 - $sub_ptr_rhs_cast90 | 0;
+ $cmp92 = ($sub_ptr_sub91 | 0) < 3;
+ if ($cmp92) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 29:
+ $sub_ptr_lhs_cast97 = $end;
+ $sub_ptr_rhs_cast98 = $ptr_addr_062;
+ $sub_ptr_sub99 = $sub_ptr_lhs_cast97 - $sub_ptr_rhs_cast98 | 0;
+ $cmp100 = ($sub_ptr_sub99 | 0) < 4;
+ if ($cmp100) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 20;
+ label = 33;
+ break;
+ case 32:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 33:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_prologTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $and = 0, $tobool = 0, $and2 = 0, $cmp3 = 0, $add_ptr = 0, $end_addr_0 = 0, $0 = 0, $cmp7 = 0, $arrayidx9 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx10 = 0, $3 = 0, $conv11 = 0, $call = 0, $cond = 0, $add_ptr56167 = 0, $cmp57168 = 0, $type68 = 0, $4 = 0, $add_ptr14 = 0, $call15 = 0, $add_ptr17 = 0, $call18 = 0, $add_ptr20 = 0, $cmp21 = 0, $5 = 0, $cmp27 = 0, $arrayidx30 = 0, $6 = 0, $idxprom31 = 0, $type32 = 0, $7 = 0, $arrayidx33 = 0, $8 = 0, $conv34 = 0, $call38 = 0, $cond40 = 0, $add_ptr42 = 0, $call43 = 0, $add_ptr45 = 0, $call46 = 0, $add_ptr50 = 0, $cmp51 = 0, $add_ptr56170 = 0, $ptr_addr_0169 = 0, $9 = 0, $cmp63 = 0, $arrayidx66 = 0, $10 = 0, $idxprom67 = 0, $arrayidx69 = 0, $11 = 0, $conv70 = 0, $call74 = 0, $cond76 = 0, $add_ptr56 = 0, $cmp57 = 0, $add_ptr79 = 0, $cmp80 = 0, $add_ptr56_lcssa = 0, $add_ptr86 = 0, $call87 = 0, $add_ptr89 = 0, $add_ptr91 = 0, $add_ptr93 = 0, $cmp94 = 0, $12 = 0, $cmp100 = 0, $arrayidx102 = 0, $13 = 0, $cmp104 = 0, $add_ptr107 = 0, $cmp108 = 0, $14 = 0, $cmp115 = 0, $arrayidx119 = 0, $15 = 0, $cmp121 = 0, $add_ptr124 = 0, $add_ptr128 = 0, $add_ptr130 = 0, $cmp131 = 0, $16 = 0, $cmp137 = 0, $arrayidx140 = 0, $17 = 0, $idxprom141 = 0, $type142 = 0, $18 = 0, $arrayidx143 = 0, $19 = 0, $conv144 = 0, $call148 = 0, $cond150 = 0, $add_ptr152 = 0, $add_ptr154 = 0, $add_ptr156 = 0, $add_ptr160 = 0, $add_ptr162 = 0, $add_ptr164 = 0, $call165 = 0, $sub_ptr_lhs_cast167 = 0, $sub_ptr_sub169 = 0, $cmp170 = 0, $sub_ptr_lhs_cast175 = 0, $sub_ptr_sub177 = 0, $cmp178 = 0, $sub_ptr_lhs_cast183 = 0, $sub_ptr_sub185 = 0, $cmp186 = 0, $20 = 0, $idxprom196 = 0, $arrayidx197 = 0, $21 = 0, $conv198 = 0, $shl = 0, $22 = 0, $conv200 = 0, $shr164 = 0, $add = 0, $arrayidx201 = 0, $23 = 0, $and204 = 0, $shl205 = 0, $and206 = 0, $tobool207 = 0, $arrayidx213 = 0, $24 = 0, $conv214 = 0, $shl215 = 0, $add219 = 0, $arrayidx220 = 0, $25 = 0, $and225 = 0, $tobool226 = 0, $tok_0_ph = 0, $ptr_addr_1189 = 0, $cmp232190 = 0, $type241 = 0, $26 = 0, $ptr_addr_1192 = 0, $ptr_pn191 = 0, $27 = 0, $cmp236 = 0, $arrayidx239 = 0, $28 = 0, $idxprom240 = 0, $arrayidx242 = 0, $29 = 0, $conv243 = 0, $call247 = 0, $cond249 = 0, $30 = 0, $idxprom252 = 0, $arrayidx253 = 0, $31 = 0, $conv254 = 0, $shl255 = 0, $32 = 0, $conv257 = 0, $shr258165 = 0, $add259 = 0, $arrayidx260 = 0, $33 = 0, $and263 = 0, $shl264 = 0, $and265 = 0, $tobool266 = 0, $ptr_addr_1 = 0, $cmp232 = 0, $sub_ptr_lhs_cast272 = 0, $sub_ptr_rhs_cast273 = 0, $sub_ptr_sub274 = 0, $cmp275 = 0, $sub_ptr_lhs_cast280 = 0, $sub_ptr_rhs_cast281 = 0, $sub_ptr_sub282 = 0, $cmp283 = 0, $sub_ptr_lhs_cast288 = 0, $sub_ptr_rhs_cast289 = 0, $sub_ptr_sub290 = 0, $cmp291 = 0, $cmp297 = 0, $add_ptr301 = 0, $cmp303 = 0, $add_ptr307 = 0, $cmp309 = 0, $add_ptr313 = 0, $sub = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 95;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $and = $sub_ptr_sub & 1;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ $end_addr_0 = $end;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $and2 = $sub_ptr_sub & -2;
+ $cmp3 = ($and2 | 0) == 0;
+ if ($cmp3) {
+ $retval_0 = -1;
+ label = 95;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + $and2 | 0;
+ $end_addr_0 = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp7 = $0 << 24 >> 24 == 0;
+ $arrayidx9 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx9] | 0;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx10 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $3 & 255;
+ $cond = $conv11;
+ label = 9;
+ break;
+ case 8:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 9;
+ break;
+ case 9:
+ if (($cond | 0) == 21 | ($cond | 0) == 10) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 12) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 13) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 2) {
+ label = 14;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 23;
+ break;
+ } else if (($cond | 0) == 30) {
+ label = 33;
+ break;
+ } else if (($cond | 0) == 35) {
+ label = 34;
+ break;
+ } else if (($cond | 0) == 20) {
+ label = 35;
+ break;
+ } else if (($cond | 0) == 4) {
+ label = 36;
+ break;
+ } else if (($cond | 0) == 31) {
+ label = 44;
+ break;
+ } else if (($cond | 0) == 32) {
+ label = 45;
+ break;
+ } else if (($cond | 0) == 36) {
+ label = 55;
+ break;
+ } else if (($cond | 0) == 11) {
+ label = 56;
+ break;
+ } else if (($cond | 0) == 19) {
+ label = 57;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 58;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 60;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 62;
+ break;
+ } else if (($cond | 0) == 25 | ($cond | 0) == 26 | ($cond | 0) == 27) {
+ label = 64;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 65;
+ break;
+ } else if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ $tok_0_ph = 18;
+ label = 67;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 10:
+ $add_ptr56167 = $ptr + 2 | 0;
+ $cmp57168 = ($add_ptr56167 | 0) == ($end_addr_0 | 0);
+ if ($cmp57168) {
+ $add_ptr56_lcssa = $add_ptr56167;
+ label = 32;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $type68 = $enc + 72 | 0;
+ $4 = $type68;
+ $ptr_addr_0169 = $ptr;
+ $add_ptr56170 = $add_ptr56167;
+ label = 25;
+ break;
+ case 12:
+ $add_ptr14 = $ptr + 2 | 0;
+ $call15 = _big2_scanLit(12, $enc, $add_ptr14, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call15;
+ label = 95;
+ break;
+ case 13:
+ $add_ptr17 = $ptr + 2 | 0;
+ $call18 = _big2_scanLit(13, $enc, $add_ptr17, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call18;
+ label = 95;
+ break;
+ case 14:
+ $add_ptr20 = $ptr + 2 | 0;
+ $cmp21 = ($add_ptr20 | 0) == ($end_addr_0 | 0);
+ if ($cmp21) {
+ $retval_0 = -1;
+ label = 95;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $5 = HEAP8[$add_ptr20] | 0;
+ $cmp27 = $5 << 24 >> 24 == 0;
+ $arrayidx30 = $ptr + 3 | 0;
+ $6 = HEAP8[$arrayidx30] | 0;
+ if ($cmp27) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $idxprom31 = $6 & 255;
+ $type32 = $enc + 72 | 0;
+ $7 = $type32;
+ $arrayidx33 = $7 + $idxprom31 | 0;
+ $8 = HEAP8[$arrayidx33] | 0;
+ $conv34 = $8 & 255;
+ $cond40 = $conv34;
+ label = 18;
+ break;
+ case 17:
+ $call38 = _unicode_byte_type($5, $6) | 0;
+ $cond40 = $call38;
+ label = 18;
+ break;
+ case 18:
+ if (($cond40 | 0) == 16) {
+ label = 19;
+ break;
+ } else if (($cond40 | 0) == 15) {
+ label = 20;
+ break;
+ } else if (($cond40 | 0) == 22 | ($cond40 | 0) == 24 | ($cond40 | 0) == 29 | ($cond40 | 0) == 5 | ($cond40 | 0) == 6 | ($cond40 | 0) == 7) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 19:
+ $add_ptr42 = $ptr + 4 | 0;
+ $call43 = _big2_scanDecl($enc, $add_ptr42, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call43;
+ label = 95;
+ break;
+ case 20:
+ $add_ptr45 = $ptr + 4 | 0;
+ $call46 = _big2_scanPi($enc, $add_ptr45, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call46;
+ label = 95;
+ break;
+ case 21:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 29;
+ label = 95;
+ break;
+ case 22:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr20;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 23:
+ $add_ptr50 = $ptr + 2 | 0;
+ $cmp51 = ($add_ptr50 | 0) == ($end_addr_0 | 0);
+ if ($cmp51) {
+ label = 24;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $end_addr_0;
+ $retval_0 = -15;
+ label = 95;
+ break;
+ case 25:
+ $9 = HEAP8[$add_ptr56170] | 0;
+ $cmp63 = $9 << 24 >> 24 == 0;
+ $arrayidx66 = $ptr_addr_0169 + 3 | 0;
+ $10 = HEAP8[$arrayidx66] | 0;
+ if ($cmp63) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $idxprom67 = $10 & 255;
+ $arrayidx69 = $4 + $idxprom67 | 0;
+ $11 = HEAP8[$arrayidx69] | 0;
+ $conv70 = $11 & 255;
+ $cond76 = $conv70;
+ label = 28;
+ break;
+ case 27:
+ $call74 = _unicode_byte_type($9, $10) | 0;
+ $cond76 = $call74;
+ label = 28;
+ break;
+ case 28:
+ if (($cond76 | 0) == 21 | ($cond76 | 0) == 10) {
+ label = 29;
+ break;
+ } else if (($cond76 | 0) == 9) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 29:
+ $add_ptr56 = $add_ptr56170 + 2 | 0;
+ $cmp57 = ($add_ptr56 | 0) == ($end_addr_0 | 0);
+ if ($cmp57) {
+ $add_ptr56_lcssa = $add_ptr56;
+ label = 32;
+ break;
+ } else {
+ $ptr_addr_0169 = $add_ptr56170;
+ $add_ptr56170 = $add_ptr56;
+ label = 25;
+ break;
+ }
+ case 30:
+ $add_ptr79 = $ptr_addr_0169 + 4 | 0;
+ $cmp80 = ($add_ptr79 | 0) == ($end_addr_0 | 0);
+ if ($cmp80) {
+ label = 31;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr56170;
+ $retval_0 = 15;
+ label = 95;
+ break;
+ case 32:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr56_lcssa;
+ $retval_0 = 15;
+ label = 95;
+ break;
+ case 33:
+ $add_ptr86 = $ptr + 2 | 0;
+ $call87 = _big2_scanPercent($enc, $add_ptr86, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call87;
+ label = 95;
+ break;
+ case 34:
+ $add_ptr89 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr89;
+ $retval_0 = 38;
+ label = 95;
+ break;
+ case 35:
+ $add_ptr91 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr91;
+ $retval_0 = 25;
+ label = 95;
+ break;
+ case 36:
+ $add_ptr93 = $ptr + 2 | 0;
+ $cmp94 = ($add_ptr93 | 0) == ($end_addr_0 | 0);
+ if ($cmp94) {
+ $retval_0 = -26;
+ label = 95;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $12 = HEAP8[$add_ptr93] | 0;
+ $cmp100 = $12 << 24 >> 24 == 0;
+ if ($cmp100) {
+ label = 38;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 38:
+ $arrayidx102 = $ptr + 3 | 0;
+ $13 = HEAP8[$arrayidx102] | 0;
+ $cmp104 = $13 << 24 >> 24 == 93;
+ if ($cmp104) {
+ label = 39;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 39:
+ $add_ptr107 = $ptr + 4 | 0;
+ $cmp108 = ($add_ptr107 | 0) == ($end_addr_0 | 0);
+ if ($cmp108) {
+ $retval_0 = -1;
+ label = 95;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $14 = HEAP8[$add_ptr107] | 0;
+ $cmp115 = $14 << 24 >> 24 == 0;
+ if ($cmp115) {
+ label = 41;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 41:
+ $arrayidx119 = $ptr + 5 | 0;
+ $15 = HEAP8[$arrayidx119] | 0;
+ $cmp121 = $15 << 24 >> 24 == 62;
+ if ($cmp121) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ $add_ptr124 = $ptr + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr124;
+ $retval_0 = 34;
+ label = 95;
+ break;
+ case 43:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr93;
+ $retval_0 = 26;
+ label = 95;
+ break;
+ case 44:
+ $add_ptr128 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr128;
+ $retval_0 = 23;
+ label = 95;
+ break;
+ case 45:
+ $add_ptr130 = $ptr + 2 | 0;
+ $cmp131 = ($add_ptr130 | 0) == ($end_addr_0 | 0);
+ if ($cmp131) {
+ $retval_0 = -24;
+ label = 95;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $16 = HEAP8[$add_ptr130] | 0;
+ $cmp137 = $16 << 24 >> 24 == 0;
+ $arrayidx140 = $ptr + 3 | 0;
+ $17 = HEAP8[$arrayidx140] | 0;
+ if ($cmp137) {
+ label = 47;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 47:
+ $idxprom141 = $17 & 255;
+ $type142 = $enc + 72 | 0;
+ $18 = $type142;
+ $arrayidx143 = $18 + $idxprom141 | 0;
+ $19 = HEAP8[$arrayidx143] | 0;
+ $conv144 = $19 & 255;
+ $cond150 = $conv144;
+ label = 49;
+ break;
+ case 48:
+ $call148 = _unicode_byte_type($16, $17) | 0;
+ $cond150 = $call148;
+ label = 49;
+ break;
+ case 49:
+ if (($cond150 | 0) == 33) {
+ label = 50;
+ break;
+ } else if (($cond150 | 0) == 15) {
+ label = 51;
+ break;
+ } else if (($cond150 | 0) == 34) {
+ label = 52;
+ break;
+ } else if (($cond150 | 0) == 9 | ($cond150 | 0) == 10 | ($cond150 | 0) == 21 | ($cond150 | 0) == 11 | ($cond150 | 0) == 35 | ($cond150 | 0) == 36 | ($cond150 | 0) == 32) {
+ label = 53;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 50:
+ $add_ptr152 = $ptr + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr152;
+ $retval_0 = 36;
+ label = 95;
+ break;
+ case 51:
+ $add_ptr154 = $ptr + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr154;
+ $retval_0 = 35;
+ label = 95;
+ break;
+ case 52:
+ $add_ptr156 = $ptr + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr156;
+ $retval_0 = 37;
+ label = 95;
+ break;
+ case 53:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr130;
+ $retval_0 = 24;
+ label = 95;
+ break;
+ case 54:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr130;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 55:
+ $add_ptr160 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr160;
+ $retval_0 = 21;
+ label = 95;
+ break;
+ case 56:
+ $add_ptr162 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr162;
+ $retval_0 = 17;
+ label = 95;
+ break;
+ case 57:
+ $add_ptr164 = $ptr + 2 | 0;
+ $call165 = _big2_scanPoundName($enc, $add_ptr164, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call165;
+ label = 95;
+ break;
+ case 58:
+ $sub_ptr_lhs_cast167 = $end_addr_0;
+ $sub_ptr_sub169 = $sub_ptr_lhs_cast167 - $sub_ptr_rhs_cast | 0;
+ $cmp170 = ($sub_ptr_sub169 | 0) < 2;
+ if ($cmp170) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 60:
+ $sub_ptr_lhs_cast175 = $end_addr_0;
+ $sub_ptr_sub177 = $sub_ptr_lhs_cast175 - $sub_ptr_rhs_cast | 0;
+ $cmp178 = ($sub_ptr_sub177 | 0) < 3;
+ if ($cmp178) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 61:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 62:
+ $sub_ptr_lhs_cast183 = $end_addr_0;
+ $sub_ptr_sub185 = $sub_ptr_lhs_cast183 - $sub_ptr_rhs_cast | 0;
+ $cmp186 = ($sub_ptr_sub185 | 0) < 4;
+ if ($cmp186) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 64:
+ $tok_0_ph = 19;
+ label = 67;
+ break;
+ case 65:
+ $20 = HEAP8[$ptr] | 0;
+ $idxprom196 = $20 & 255;
+ $arrayidx197 = $idxprom196 + 9272 | 0;
+ $21 = HEAP8[$arrayidx197] | 0;
+ $conv198 = $21 & 255;
+ $shl = $conv198 << 3;
+ $22 = HEAP8[$arrayidx9] | 0;
+ $conv200 = $22 & 255;
+ $shr164 = $conv200 >>> 5;
+ $add = $shr164 | $shl;
+ $arrayidx201 = 9544 + ($add << 2) | 0;
+ $23 = HEAP32[$arrayidx201 >> 2] | 0;
+ $and204 = $conv200 & 31;
+ $shl205 = 1 << $and204;
+ $and206 = $shl205 & $23;
+ $tobool207 = ($and206 | 0) == 0;
+ if ($tobool207) {
+ label = 66;
+ break;
+ } else {
+ $tok_0_ph = 18;
+ label = 67;
+ break;
+ }
+ case 66:
+ $arrayidx213 = $idxprom196 + 10824 | 0;
+ $24 = HEAP8[$arrayidx213] | 0;
+ $conv214 = $24 & 255;
+ $shl215 = $conv214 << 3;
+ $add219 = $shl215 | $shr164;
+ $arrayidx220 = 9544 + ($add219 << 2) | 0;
+ $25 = HEAP32[$arrayidx220 >> 2] | 0;
+ $and225 = $25 & $shl205;
+ $tobool226 = ($and225 | 0) == 0;
+ if ($tobool226) {
+ label = 69;
+ break;
+ } else {
+ $tok_0_ph = 19;
+ label = 67;
+ break;
+ }
+ case 67:
+ $ptr_addr_1189 = $ptr + 2 | 0;
+ $cmp232190 = ($ptr_addr_1189 | 0) == ($end_addr_0 | 0);
+ if ($cmp232190) {
+ label = 94;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $type241 = $enc + 72 | 0;
+ $26 = $type241;
+ $ptr_pn191 = $ptr;
+ $ptr_addr_1192 = $ptr_addr_1189;
+ label = 70;
+ break;
+ case 69:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 70:
+ $27 = HEAP8[$ptr_addr_1192] | 0;
+ $cmp236 = $27 << 24 >> 24 == 0;
+ $arrayidx239 = $ptr_pn191 + 3 | 0;
+ $28 = HEAP8[$arrayidx239] | 0;
+ if ($cmp236) {
+ label = 71;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 71:
+ $idxprom240 = $28 & 255;
+ $arrayidx242 = $26 + $idxprom240 | 0;
+ $29 = HEAP8[$arrayidx242] | 0;
+ $conv243 = $29 & 255;
+ $cond249 = $conv243;
+ label = 73;
+ break;
+ case 72:
+ $call247 = _unicode_byte_type($27, $28) | 0;
+ $cond249 = $call247;
+ label = 73;
+ break;
+ case 73:
+ if (($cond249 | 0) == 29) {
+ label = 74;
+ break;
+ } else if (($cond249 | 0) == 22 | ($cond249 | 0) == 24 | ($cond249 | 0) == 25 | ($cond249 | 0) == 26 | ($cond249 | 0) == 27) {
+ label = 75;
+ break;
+ } else if (($cond249 | 0) == 5) {
+ label = 77;
+ break;
+ } else if (($cond249 | 0) == 6) {
+ label = 79;
+ break;
+ } else if (($cond249 | 0) == 7) {
+ label = 81;
+ break;
+ } else if (($cond249 | 0) == 11 | ($cond249 | 0) == 32 | ($cond249 | 0) == 35 | ($cond249 | 0) == 36 | ($cond249 | 0) == 20 | ($cond249 | 0) == 30 | ($cond249 | 0) == 21 | ($cond249 | 0) == 9 | ($cond249 | 0) == 10) {
+ label = 83;
+ break;
+ } else if (($cond249 | 0) == 34) {
+ label = 84;
+ break;
+ } else if (($cond249 | 0) == 33) {
+ label = 87;
+ break;
+ } else if (($cond249 | 0) == 15) {
+ label = 90;
+ break;
+ } else {
+ label = 93;
+ break;
+ }
+ case 74:
+ $30 = HEAP8[$ptr_addr_1192] | 0;
+ $idxprom252 = $30 & 255;
+ $arrayidx253 = $idxprom252 + 10824 | 0;
+ $31 = HEAP8[$arrayidx253] | 0;
+ $conv254 = $31 & 255;
+ $shl255 = $conv254 << 3;
+ $32 = HEAP8[$arrayidx239] | 0;
+ $conv257 = $32 & 255;
+ $shr258165 = $conv257 >>> 5;
+ $add259 = $shr258165 | $shl255;
+ $arrayidx260 = 9544 + ($add259 << 2) | 0;
+ $33 = HEAP32[$arrayidx260 >> 2] | 0;
+ $and263 = $conv257 & 31;
+ $shl264 = 1 << $and263;
+ $and265 = $shl264 & $33;
+ $tobool266 = ($and265 | 0) == 0;
+ if ($tobool266) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $ptr_addr_1 = $ptr_addr_1192 + 2 | 0;
+ $cmp232 = ($ptr_addr_1 | 0) == ($end_addr_0 | 0);
+ if ($cmp232) {
+ label = 94;
+ break;
+ } else {
+ $ptr_pn191 = $ptr_addr_1192;
+ $ptr_addr_1192 = $ptr_addr_1;
+ label = 70;
+ break;
+ }
+ case 76:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 77:
+ $sub_ptr_lhs_cast272 = $end_addr_0;
+ $sub_ptr_rhs_cast273 = $ptr_addr_1192;
+ $sub_ptr_sub274 = $sub_ptr_lhs_cast272 - $sub_ptr_rhs_cast273 | 0;
+ $cmp275 = ($sub_ptr_sub274 | 0) < 2;
+ if ($cmp275) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 79:
+ $sub_ptr_lhs_cast280 = $end_addr_0;
+ $sub_ptr_rhs_cast281 = $ptr_addr_1192;
+ $sub_ptr_sub282 = $sub_ptr_lhs_cast280 - $sub_ptr_rhs_cast281 | 0;
+ $cmp283 = ($sub_ptr_sub282 | 0) < 3;
+ if ($cmp283) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 80:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 81:
+ $sub_ptr_lhs_cast288 = $end_addr_0;
+ $sub_ptr_rhs_cast289 = $ptr_addr_1192;
+ $sub_ptr_sub290 = $sub_ptr_lhs_cast288 - $sub_ptr_rhs_cast289 | 0;
+ $cmp291 = ($sub_ptr_sub290 | 0) < 4;
+ if ($cmp291) {
+ $retval_0 = -2;
+ label = 95;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 82:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 83:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = $tok_0_ph;
+ label = 95;
+ break;
+ case 84:
+ $cmp297 = ($tok_0_ph | 0) == 19;
+ if ($cmp297) {
+ label = 85;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 85:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 86:
+ $add_ptr301 = $ptr_pn191 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr301;
+ $retval_0 = 32;
+ label = 95;
+ break;
+ case 87:
+ $cmp303 = ($tok_0_ph | 0) == 19;
+ if ($cmp303) {
+ label = 88;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 88:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 89:
+ $add_ptr307 = $ptr_pn191 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr307;
+ $retval_0 = 31;
+ label = 95;
+ break;
+ case 90:
+ $cmp309 = ($tok_0_ph | 0) == 19;
+ if ($cmp309) {
+ label = 91;
+ break;
+ } else {
+ label = 92;
+ break;
+ }
+ case 91:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 92:
+ $add_ptr313 = $ptr_pn191 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr313;
+ $retval_0 = 30;
+ label = 95;
+ break;
+ case 93:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1192;
+ $retval_0 = 0;
+ label = 95;
+ break;
+ case 94:
+ $sub = -$tok_0_ph | 0;
+ $retval_0 = $sub;
+ label = 95;
+ break;
+ case 95:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_contentTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $and = 0, $tobool = 0, $and2 = 0, $cmp3 = 0, $add_ptr = 0, $end_addr_0 = 0, $0 = 0, $cmp7 = 0, $arrayidx9 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx10 = 0, $3 = 0, $conv11 = 0, $call = 0, $cond = 0, $add_ptr14 = 0, $call15 = 0, $add_ptr17 = 0, $call18 = 0, $add_ptr20 = 0, $cmp21 = 0, $4 = 0, $cmp27 = 0, $arrayidx30 = 0, $5 = 0, $idxprom31 = 0, $type32 = 0, $6 = 0, $arrayidx33 = 0, $7 = 0, $conv34 = 0, $call38 = 0, $cond40 = 0, $cmp41 = 0, $add_ptr44 = 0, $add_ptr44_add_ptr20 = 0, $add_ptr47 = 0, $add_ptr49 = 0, $cmp50 = 0, $8 = 0, $cmp56 = 0, $arrayidx58 = 0, $9 = 0, $cmp60 = 0, $add_ptr64 = 0, $cmp65 = 0, $10 = 0, $cmp71 = 0, $arrayidx74 = 0, $11 = 0, $cmp76 = 0, $sub_ptr_lhs_cast82 = 0, $sub_ptr_sub84 = 0, $cmp85 = 0, $add_ptr89 = 0, $sub_ptr_lhs_cast91 = 0, $sub_ptr_sub93 = 0, $cmp94 = 0, $add_ptr98 = 0, $sub_ptr_lhs_cast100 = 0, $sub_ptr_sub102 = 0, $cmp103 = 0, $add_ptr107 = 0, $add_ptr109 = 0, $ptr_addr_1_ph = 0, $cmp11093 = 0, $type119 = 0, $12 = 0, $sub_ptr_lhs_cast129 = 0, $sub_ptr_lhs_cast138 = 0, $sub_ptr_lhs_cast147 = 0, $ptr_addr_194 = 0, $13 = 0, $cmp114 = 0, $arrayidx117 = 0, $14 = 0, $idxprom118 = 0, $arrayidx120 = 0, $15 = 0, $conv121 = 0, $call125 = 0, $cond127 = 0, $sub_ptr_rhs_cast130 = 0, $sub_ptr_sub131 = 0, $cmp132 = 0, $add_ptr136 = 0, $sub_ptr_rhs_cast139 = 0, $sub_ptr_sub140 = 0, $cmp141 = 0, $add_ptr145 = 0, $sub_ptr_rhs_cast148 = 0, $sub_ptr_sub149 = 0, $cmp150 = 0, $add_ptr154 = 0, $add_ptr156 = 0, $cmp157 = 0, $16 = 0, $cmp163 = 0, $arrayidx167 = 0, $17 = 0, $cmp169 = 0, $add_ptr174 = 0, $cmp175 = 0, $18 = 0, $cmp181 = 0, $arrayidx185 = 0, $19 = 0, $cmp187 = 0, $add_ptr197 = 0, $ptr_addr_1_be = 0, $cmp110 = 0, $ptr_addr_1_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 59;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $and = $sub_ptr_sub & 1;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ $end_addr_0 = $end;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $and2 = $sub_ptr_sub & -2;
+ $cmp3 = ($and2 | 0) == 0;
+ if ($cmp3) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + $and2 | 0;
+ $end_addr_0 = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp7 = $0 << 24 >> 24 == 0;
+ $arrayidx9 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx9] | 0;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx10 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $3 & 255;
+ $cond = $conv11;
+ label = 9;
+ break;
+ case 8:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 9;
+ break;
+ case 9:
+ if (($cond | 0) == 2) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 3) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 17;
+ break;
+ } else if (($cond | 0) == 4) {
+ label = 18;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 27;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 29;
+ break;
+ } else if (($cond | 0) == 0 | ($cond | 0) == 1 | ($cond | 0) == 8) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 10:
+ $add_ptr14 = $ptr + 2 | 0;
+ $call15 = _big2_scanLt($enc, $add_ptr14, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call15;
+ label = 59;
+ break;
+ case 11:
+ $add_ptr17 = $ptr + 2 | 0;
+ $call18 = _big2_scanRef($enc, $add_ptr17, $end_addr_0, $nextTokPtr) | 0;
+ $retval_0 = $call18;
+ label = 59;
+ break;
+ case 12:
+ $add_ptr20 = $ptr + 2 | 0;
+ $cmp21 = ($add_ptr20 | 0) == ($end_addr_0 | 0);
+ if ($cmp21) {
+ $retval_0 = -3;
+ label = 59;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $4 = HEAP8[$add_ptr20] | 0;
+ $cmp27 = $4 << 24 >> 24 == 0;
+ $arrayidx30 = $ptr + 3 | 0;
+ $5 = HEAP8[$arrayidx30] | 0;
+ if ($cmp27) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $idxprom31 = $5 & 255;
+ $type32 = $enc + 72 | 0;
+ $6 = $type32;
+ $arrayidx33 = $6 + $idxprom31 | 0;
+ $7 = HEAP8[$arrayidx33] | 0;
+ $conv34 = $7 & 255;
+ $cond40 = $conv34;
+ label = 16;
+ break;
+ case 15:
+ $call38 = _unicode_byte_type($4, $5) | 0;
+ $cond40 = $call38;
+ label = 16;
+ break;
+ case 16:
+ $cmp41 = ($cond40 | 0) == 10;
+ $add_ptr44 = $ptr + 4 | 0;
+ $add_ptr44_add_ptr20 = $cmp41 ? $add_ptr44 : $add_ptr20;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr44_add_ptr20;
+ $retval_0 = 7;
+ label = 59;
+ break;
+ case 17:
+ $add_ptr47 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr47;
+ $retval_0 = 7;
+ label = 59;
+ break;
+ case 18:
+ $add_ptr49 = $ptr + 2 | 0;
+ $cmp50 = ($add_ptr49 | 0) == ($end_addr_0 | 0);
+ if ($cmp50) {
+ $retval_0 = -5;
+ label = 59;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $8 = HEAP8[$add_ptr49] | 0;
+ $cmp56 = $8 << 24 >> 24 == 0;
+ if ($cmp56) {
+ label = 20;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr49;
+ label = 33;
+ break;
+ }
+ case 20:
+ $arrayidx58 = $ptr + 3 | 0;
+ $9 = HEAP8[$arrayidx58] | 0;
+ $cmp60 = $9 << 24 >> 24 == 93;
+ if ($cmp60) {
+ label = 21;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr49;
+ label = 33;
+ break;
+ }
+ case 21:
+ $add_ptr64 = $ptr + 4 | 0;
+ $cmp65 = ($add_ptr64 | 0) == ($end_addr_0 | 0);
+ if ($cmp65) {
+ $retval_0 = -5;
+ label = 59;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $10 = HEAP8[$add_ptr64] | 0;
+ $cmp71 = $10 << 24 >> 24 == 0;
+ if ($cmp71) {
+ label = 23;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr49;
+ label = 33;
+ break;
+ }
+ case 23:
+ $arrayidx74 = $ptr + 5 | 0;
+ $11 = HEAP8[$arrayidx74] | 0;
+ $cmp76 = $11 << 24 >> 24 == 62;
+ if ($cmp76) {
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr49;
+ label = 33;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr64;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast82 = $end_addr_0;
+ $sub_ptr_sub84 = $sub_ptr_lhs_cast82 - $sub_ptr_rhs_cast | 0;
+ $cmp85 = ($sub_ptr_sub84 | 0) < 2;
+ if ($cmp85) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $add_ptr89 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr89;
+ label = 33;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast91 = $end_addr_0;
+ $sub_ptr_sub93 = $sub_ptr_lhs_cast91 - $sub_ptr_rhs_cast | 0;
+ $cmp94 = ($sub_ptr_sub93 | 0) < 3;
+ if ($cmp94) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $add_ptr98 = $ptr + 3 | 0;
+ $ptr_addr_1_ph = $add_ptr98;
+ label = 33;
+ break;
+ case 29:
+ $sub_ptr_lhs_cast100 = $end_addr_0;
+ $sub_ptr_sub102 = $sub_ptr_lhs_cast100 - $sub_ptr_rhs_cast | 0;
+ $cmp103 = ($sub_ptr_sub102 | 0) < 4;
+ if ($cmp103) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $add_ptr107 = $ptr + 4 | 0;
+ $ptr_addr_1_ph = $add_ptr107;
+ label = 33;
+ break;
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 32:
+ $add_ptr109 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr109;
+ label = 33;
+ break;
+ case 33:
+ $cmp11093 = ($ptr_addr_1_ph | 0) == ($end_addr_0 | 0);
+ if ($cmp11093) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_ph;
+ label = 58;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $type119 = $enc + 72 | 0;
+ $12 = $type119;
+ $sub_ptr_lhs_cast129 = $end_addr_0;
+ $sub_ptr_lhs_cast138 = $end_addr_0;
+ $sub_ptr_lhs_cast147 = $end_addr_0;
+ $ptr_addr_194 = $ptr_addr_1_ph;
+ label = 35;
+ break;
+ case 35:
+ $13 = HEAP8[$ptr_addr_194] | 0;
+ $cmp114 = $13 << 24 >> 24 == 0;
+ $arrayidx117 = $ptr_addr_194 + 1 | 0;
+ $14 = HEAP8[$arrayidx117] | 0;
+ if ($cmp114) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ $idxprom118 = $14 & 255;
+ $arrayidx120 = $12 + $idxprom118 | 0;
+ $15 = HEAP8[$arrayidx120] | 0;
+ $conv121 = $15 & 255;
+ $cond127 = $conv121;
+ label = 38;
+ break;
+ case 37:
+ $call125 = _unicode_byte_type($13, $14) | 0;
+ $cond127 = $call125;
+ label = 38;
+ break;
+ case 38:
+ if (($cond127 | 0) == 5) {
+ label = 39;
+ break;
+ } else if (($cond127 | 0) == 6) {
+ label = 42;
+ break;
+ } else if (($cond127 | 0) == 7) {
+ label = 45;
+ break;
+ } else if (($cond127 | 0) == 4) {
+ label = 48;
+ break;
+ } else if (($cond127 | 0) == 3 | ($cond127 | 0) == 2 | ($cond127 | 0) == 0 | ($cond127 | 0) == 1 | ($cond127 | 0) == 8 | ($cond127 | 0) == 9 | ($cond127 | 0) == 10) {
+ label = 55;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 39:
+ $sub_ptr_rhs_cast130 = $ptr_addr_194;
+ $sub_ptr_sub131 = $sub_ptr_lhs_cast129 - $sub_ptr_rhs_cast130 | 0;
+ $cmp132 = ($sub_ptr_sub131 | 0) < 2;
+ if ($cmp132) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 40:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_194;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 41:
+ $add_ptr136 = $ptr_addr_194 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr136;
+ label = 57;
+ break;
+ case 42:
+ $sub_ptr_rhs_cast139 = $ptr_addr_194;
+ $sub_ptr_sub140 = $sub_ptr_lhs_cast138 - $sub_ptr_rhs_cast139 | 0;
+ $cmp141 = ($sub_ptr_sub140 | 0) < 3;
+ if ($cmp141) {
+ label = 43;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 43:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_194;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 44:
+ $add_ptr145 = $ptr_addr_194 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr145;
+ label = 57;
+ break;
+ case 45:
+ $sub_ptr_rhs_cast148 = $ptr_addr_194;
+ $sub_ptr_sub149 = $sub_ptr_lhs_cast147 - $sub_ptr_rhs_cast148 | 0;
+ $cmp150 = ($sub_ptr_sub149 | 0) < 4;
+ if ($cmp150) {
+ label = 46;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 46:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_194;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 47:
+ $add_ptr154 = $ptr_addr_194 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr154;
+ label = 57;
+ break;
+ case 48:
+ $add_ptr156 = $ptr_addr_194 + 2 | 0;
+ $cmp157 = ($add_ptr156 | 0) == ($end_addr_0 | 0);
+ if ($cmp157) {
+ label = 55;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $16 = HEAP8[$add_ptr156] | 0;
+ $cmp163 = $16 << 24 >> 24 == 0;
+ if ($cmp163) {
+ label = 50;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr156;
+ label = 57;
+ break;
+ }
+ case 50:
+ $arrayidx167 = $ptr_addr_194 + 3 | 0;
+ $17 = HEAP8[$arrayidx167] | 0;
+ $cmp169 = $17 << 24 >> 24 == 93;
+ if ($cmp169) {
+ label = 51;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr156;
+ label = 57;
+ break;
+ }
+ case 51:
+ $add_ptr174 = $ptr_addr_194 + 4 | 0;
+ $cmp175 = ($add_ptr174 | 0) == ($end_addr_0 | 0);
+ if ($cmp175) {
+ label = 55;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $18 = HEAP8[$add_ptr174] | 0;
+ $cmp181 = $18 << 24 >> 24 == 0;
+ if ($cmp181) {
+ label = 53;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr156;
+ label = 57;
+ break;
+ }
+ case 53:
+ $arrayidx185 = $ptr_addr_194 + 5 | 0;
+ $19 = HEAP8[$arrayidx185] | 0;
+ $cmp187 = $19 << 24 >> 24 == 62;
+ if ($cmp187) {
+ label = 54;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr156;
+ label = 57;
+ break;
+ }
+ case 54:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr174;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 55:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_194;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 56:
+ $add_ptr197 = $ptr_addr_194 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr197;
+ label = 57;
+ break;
+ case 57:
+ $cmp110 = ($ptr_addr_1_be | 0) == ($end_addr_0 | 0);
+ if ($cmp110) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_be;
+ label = 58;
+ break;
+ } else {
+ $ptr_addr_194 = $ptr_addr_1_be;
+ label = 35;
+ break;
+ }
+ case 58:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1_lcssa;
+ $retval_0 = 6;
+ label = 59;
+ break;
+ case 59:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_cdataSectionTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $and = 0, $tobool = 0, $and2 = 0, $cmp3 = 0, $add_ptr = 0, $end_addr_0 = 0, $0 = 0, $cmp7 = 0, $arrayidx9 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx10 = 0, $3 = 0, $conv11 = 0, $call = 0, $cond = 0, $add_ptr14 = 0, $cmp15 = 0, $4 = 0, $cmp21 = 0, $arrayidx23 = 0, $5 = 0, $cmp25 = 0, $add_ptr29 = 0, $cmp30 = 0, $6 = 0, $cmp36 = 0, $arrayidx39 = 0, $7 = 0, $cmp41 = 0, $add_ptr46 = 0, $add_ptr48 = 0, $cmp49 = 0, $8 = 0, $cmp55 = 0, $arrayidx58 = 0, $9 = 0, $idxprom59 = 0, $type60 = 0, $10 = 0, $arrayidx61 = 0, $11 = 0, $conv62 = 0, $call66 = 0, $cond68 = 0, $cmp69 = 0, $add_ptr72 = 0, $add_ptr72_add_ptr48 = 0, $add_ptr75 = 0, $sub_ptr_lhs_cast77 = 0, $sub_ptr_sub79 = 0, $cmp80 = 0, $add_ptr84 = 0, $sub_ptr_lhs_cast86 = 0, $sub_ptr_sub88 = 0, $cmp89 = 0, $add_ptr93 = 0, $sub_ptr_lhs_cast95 = 0, $sub_ptr_sub97 = 0, $cmp98 = 0, $add_ptr102 = 0, $add_ptr104 = 0, $ptr_addr_1_ph = 0, $cmp10572 = 0, $type114 = 0, $12 = 0, $sub_ptr_lhs_cast124 = 0, $sub_ptr_lhs_cast133 = 0, $sub_ptr_lhs_cast142 = 0, $ptr_addr_173 = 0, $13 = 0, $cmp109 = 0, $arrayidx112 = 0, $14 = 0, $idxprom113 = 0, $arrayidx115 = 0, $15 = 0, $conv116 = 0, $call120 = 0, $cond122 = 0, $sub_ptr_rhs_cast125 = 0, $sub_ptr_sub126 = 0, $cmp127 = 0, $add_ptr131 = 0, $sub_ptr_rhs_cast134 = 0, $sub_ptr_sub135 = 0, $cmp136 = 0, $add_ptr140 = 0, $sub_ptr_rhs_cast143 = 0, $sub_ptr_sub144 = 0, $cmp145 = 0, $add_ptr149 = 0, $add_ptr152 = 0, $ptr_addr_1_be = 0, $cmp105 = 0, $ptr_addr_1_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 50;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $and = $sub_ptr_sub & 1;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ $end_addr_0 = $end;
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $and2 = $sub_ptr_sub & -2;
+ $cmp3 = ($and2 | 0) == 0;
+ if ($cmp3) {
+ $retval_0 = -1;
+ label = 50;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + $and2 | 0;
+ $end_addr_0 = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp7 = $0 << 24 >> 24 == 0;
+ $arrayidx9 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx9] | 0;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx10 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $3 & 255;
+ $cond = $conv11;
+ label = 9;
+ break;
+ case 8:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 9;
+ break;
+ case 9:
+ if (($cond | 0) == 4) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 17;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 22;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 23;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 25;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 27;
+ break;
+ } else if (($cond | 0) == 0 | ($cond | 0) == 1 | ($cond | 0) == 8) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 10:
+ $add_ptr14 = $ptr + 2 | 0;
+ $cmp15 = ($add_ptr14 | 0) == ($end_addr_0 | 0);
+ if ($cmp15) {
+ $retval_0 = -1;
+ label = 50;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $4 = HEAP8[$add_ptr14] | 0;
+ $cmp21 = $4 << 24 >> 24 == 0;
+ if ($cmp21) {
+ label = 12;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr14;
+ label = 31;
+ break;
+ }
+ case 12:
+ $arrayidx23 = $ptr + 3 | 0;
+ $5 = HEAP8[$arrayidx23] | 0;
+ $cmp25 = $5 << 24 >> 24 == 93;
+ if ($cmp25) {
+ label = 13;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr14;
+ label = 31;
+ break;
+ }
+ case 13:
+ $add_ptr29 = $ptr + 4 | 0;
+ $cmp30 = ($add_ptr29 | 0) == ($end_addr_0 | 0);
+ if ($cmp30) {
+ $retval_0 = -1;
+ label = 50;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $6 = HEAP8[$add_ptr29] | 0;
+ $cmp36 = $6 << 24 >> 24 == 0;
+ if ($cmp36) {
+ label = 15;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr14;
+ label = 31;
+ break;
+ }
+ case 15:
+ $arrayidx39 = $ptr + 5 | 0;
+ $7 = HEAP8[$arrayidx39] | 0;
+ $cmp41 = $7 << 24 >> 24 == 62;
+ if ($cmp41) {
+ label = 16;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr14;
+ label = 31;
+ break;
+ }
+ case 16:
+ $add_ptr46 = $ptr + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr46;
+ $retval_0 = 40;
+ label = 50;
+ break;
+ case 17:
+ $add_ptr48 = $ptr + 2 | 0;
+ $cmp49 = ($add_ptr48 | 0) == ($end_addr_0 | 0);
+ if ($cmp49) {
+ $retval_0 = -1;
+ label = 50;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $8 = HEAP8[$add_ptr48] | 0;
+ $cmp55 = $8 << 24 >> 24 == 0;
+ $arrayidx58 = $ptr + 3 | 0;
+ $9 = HEAP8[$arrayidx58] | 0;
+ if ($cmp55) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom59 = $9 & 255;
+ $type60 = $enc + 72 | 0;
+ $10 = $type60;
+ $arrayidx61 = $10 + $idxprom59 | 0;
+ $11 = HEAP8[$arrayidx61] | 0;
+ $conv62 = $11 & 255;
+ $cond68 = $conv62;
+ label = 21;
+ break;
+ case 20:
+ $call66 = _unicode_byte_type($8, $9) | 0;
+ $cond68 = $call66;
+ label = 21;
+ break;
+ case 21:
+ $cmp69 = ($cond68 | 0) == 10;
+ $add_ptr72 = $ptr + 4 | 0;
+ $add_ptr72_add_ptr48 = $cmp69 ? $add_ptr72 : $add_ptr48;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr72_add_ptr48;
+ $retval_0 = 7;
+ label = 50;
+ break;
+ case 22:
+ $add_ptr75 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr75;
+ $retval_0 = 7;
+ label = 50;
+ break;
+ case 23:
+ $sub_ptr_lhs_cast77 = $end_addr_0;
+ $sub_ptr_sub79 = $sub_ptr_lhs_cast77 - $sub_ptr_rhs_cast | 0;
+ $cmp80 = ($sub_ptr_sub79 | 0) < 2;
+ if ($cmp80) {
+ $retval_0 = -2;
+ label = 50;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $add_ptr84 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr84;
+ label = 31;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast86 = $end_addr_0;
+ $sub_ptr_sub88 = $sub_ptr_lhs_cast86 - $sub_ptr_rhs_cast | 0;
+ $cmp89 = ($sub_ptr_sub88 | 0) < 3;
+ if ($cmp89) {
+ $retval_0 = -2;
+ label = 50;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $add_ptr93 = $ptr + 3 | 0;
+ $ptr_addr_1_ph = $add_ptr93;
+ label = 31;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast95 = $end_addr_0;
+ $sub_ptr_sub97 = $sub_ptr_lhs_cast95 - $sub_ptr_rhs_cast | 0;
+ $cmp98 = ($sub_ptr_sub97 | 0) < 4;
+ if ($cmp98) {
+ $retval_0 = -2;
+ label = 50;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $add_ptr102 = $ptr + 4 | 0;
+ $ptr_addr_1_ph = $add_ptr102;
+ label = 31;
+ break;
+ case 29:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 50;
+ break;
+ case 30:
+ $add_ptr104 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr104;
+ label = 31;
+ break;
+ case 31:
+ $cmp10572 = ($ptr_addr_1_ph | 0) == ($end_addr_0 | 0);
+ if ($cmp10572) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_ph;
+ label = 49;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $type114 = $enc + 72 | 0;
+ $12 = $type114;
+ $sub_ptr_lhs_cast124 = $end_addr_0;
+ $sub_ptr_lhs_cast133 = $end_addr_0;
+ $sub_ptr_lhs_cast142 = $end_addr_0;
+ $ptr_addr_173 = $ptr_addr_1_ph;
+ label = 33;
+ break;
+ case 33:
+ $13 = HEAP8[$ptr_addr_173] | 0;
+ $cmp109 = $13 << 24 >> 24 == 0;
+ $arrayidx112 = $ptr_addr_173 + 1 | 0;
+ $14 = HEAP8[$arrayidx112] | 0;
+ if ($cmp109) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ $idxprom113 = $14 & 255;
+ $arrayidx115 = $12 + $idxprom113 | 0;
+ $15 = HEAP8[$arrayidx115] | 0;
+ $conv116 = $15 & 255;
+ $cond122 = $conv116;
+ label = 36;
+ break;
+ case 35:
+ $call120 = _unicode_byte_type($13, $14) | 0;
+ $cond122 = $call120;
+ label = 36;
+ break;
+ case 36:
+ if (($cond122 | 0) == 5) {
+ label = 37;
+ break;
+ } else if (($cond122 | 0) == 6) {
+ label = 40;
+ break;
+ } else if (($cond122 | 0) == 7) {
+ label = 43;
+ break;
+ } else if (($cond122 | 0) == 0 | ($cond122 | 0) == 1 | ($cond122 | 0) == 8 | ($cond122 | 0) == 9 | ($cond122 | 0) == 10 | ($cond122 | 0) == 4) {
+ label = 46;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 37:
+ $sub_ptr_rhs_cast125 = $ptr_addr_173;
+ $sub_ptr_sub126 = $sub_ptr_lhs_cast124 - $sub_ptr_rhs_cast125 | 0;
+ $cmp127 = ($sub_ptr_sub126 | 0) < 2;
+ if ($cmp127) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_173;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 39:
+ $add_ptr131 = $ptr_addr_173 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr131;
+ label = 48;
+ break;
+ case 40:
+ $sub_ptr_rhs_cast134 = $ptr_addr_173;
+ $sub_ptr_sub135 = $sub_ptr_lhs_cast133 - $sub_ptr_rhs_cast134 | 0;
+ $cmp136 = ($sub_ptr_sub135 | 0) < 3;
+ if ($cmp136) {
+ label = 41;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 41:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_173;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 42:
+ $add_ptr140 = $ptr_addr_173 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr140;
+ label = 48;
+ break;
+ case 43:
+ $sub_ptr_rhs_cast143 = $ptr_addr_173;
+ $sub_ptr_sub144 = $sub_ptr_lhs_cast142 - $sub_ptr_rhs_cast143 | 0;
+ $cmp145 = ($sub_ptr_sub144 | 0) < 4;
+ if ($cmp145) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 44:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_173;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 45:
+ $add_ptr149 = $ptr_addr_173 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr149;
+ label = 48;
+ break;
+ case 46:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_173;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 47:
+ $add_ptr152 = $ptr_addr_173 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr152;
+ label = 48;
+ break;
+ case 48:
+ $cmp105 = ($ptr_addr_1_be | 0) == ($end_addr_0 | 0);
+ if ($cmp105) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_be;
+ label = 49;
+ break;
+ } else {
+ $ptr_addr_173 = $ptr_addr_1_be;
+ label = 33;
+ break;
+ }
+ case 49:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1_lcssa;
+ $retval_0 = 6;
+ label = 50;
+ break;
+ case 50:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_attributeValueTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $cmp148 = 0, $type = 0, $0 = 0, $ptr_addr_049 = 0, $1 = 0, $cmp2 = 0, $arrayidx4 = 0, $2 = 0, $idxprom = 0, $arrayidx5 = 0, $3 = 0, $conv6 = 0, $call = 0, $cond = 0, $add_ptr = 0, $add_ptr10 = 0, $add_ptr12 = 0, $cmp14 = 0, $add_ptr17 = 0, $call18 = 0, $cmp22 = 0, $add_ptr25 = 0, $cmp28 = 0, $add_ptr31 = 0, $cmp32 = 0, $4 = 0, $cmp38 = 0, $arrayidx41 = 0, $5 = 0, $idxprom42 = 0, $type43 = 0, $6 = 0, $arrayidx44 = 0, $7 = 0, $conv45 = 0, $call49 = 0, $cond51 = 0, $cmp52 = 0, $add_ptr55 = 0, $add_ptr55_add_ptr31 = 0, $cmp59 = 0, $add_ptr62 = 0, $add_ptr64 = 0, $ptr_addr_0_be = 0, $cmp1 = 0, $ptr_addr_0_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 32;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp148 = ($ptr | 0) == ($end | 0);
+ if ($cmp148) {
+ $ptr_addr_0_lcssa = $ptr;
+ label = 31;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_049 = $ptr;
+ label = 5;
+ break;
+ case 5:
+ $1 = HEAP8[$ptr_addr_049] | 0;
+ $cmp2 = $1 << 24 >> 24 == 0;
+ $arrayidx4 = $ptr_addr_049 + 1 | 0;
+ $2 = HEAP8[$arrayidx4] | 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $idxprom = $2 & 255;
+ $arrayidx5 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx5] | 0;
+ $conv6 = $3 & 255;
+ $cond = $conv6;
+ label = 8;
+ break;
+ case 7:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 8;
+ break;
+ case 8:
+ if (($cond | 0) == 5) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 3) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 2) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 16;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 19;
+ break;
+ } else if (($cond | 0) == 21) {
+ label = 26;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 9:
+ $add_ptr = $ptr_addr_049 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 30;
+ break;
+ case 10:
+ $add_ptr10 = $ptr_addr_049 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr10;
+ label = 30;
+ break;
+ case 11:
+ $add_ptr12 = $ptr_addr_049 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr12;
+ label = 30;
+ break;
+ case 12:
+ $cmp14 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp14) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $add_ptr17 = $ptr_addr_049 + 2 | 0;
+ $call18 = _big2_scanRef($enc, $add_ptr17, $end, $nextTokPtr) | 0;
+ $retval_0 = $call18;
+ label = 32;
+ break;
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 15:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 16:
+ $cmp22 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp22) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $add_ptr25 = $ptr_addr_049 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr25;
+ $retval_0 = 7;
+ label = 32;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 19:
+ $cmp28 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp28) {
+ label = 20;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 20:
+ $add_ptr31 = $ptr_addr_049 + 2 | 0;
+ $cmp32 = ($add_ptr31 | 0) == ($end | 0);
+ if ($cmp32) {
+ $retval_0 = -3;
+ label = 32;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $4 = HEAP8[$add_ptr31] | 0;
+ $cmp38 = $4 << 24 >> 24 == 0;
+ $arrayidx41 = $ptr_addr_049 + 3 | 0;
+ $5 = HEAP8[$arrayidx41] | 0;
+ if ($cmp38) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $idxprom42 = $5 & 255;
+ $type43 = $enc + 72 | 0;
+ $6 = $type43;
+ $arrayidx44 = $6 + $idxprom42 | 0;
+ $7 = HEAP8[$arrayidx44] | 0;
+ $conv45 = $7 & 255;
+ $cond51 = $conv45;
+ label = 24;
+ break;
+ case 23:
+ $call49 = _unicode_byte_type($4, $5) | 0;
+ $cond51 = $call49;
+ label = 24;
+ break;
+ case 24:
+ $cmp52 = ($cond51 | 0) == 10;
+ $add_ptr55 = $ptr_addr_049 + 4 | 0;
+ $add_ptr55_add_ptr31 = $cmp52 ? $add_ptr55 : $add_ptr31;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr55_add_ptr31;
+ $retval_0 = 7;
+ label = 32;
+ break;
+ case 25:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 26:
+ $cmp59 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp59) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $add_ptr62 = $ptr_addr_049 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr62;
+ $retval_0 = 39;
+ label = 32;
+ break;
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 29:
+ $add_ptr64 = $ptr_addr_049 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr64;
+ label = 30;
+ break;
+ case 30:
+ $cmp1 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp1) {
+ $ptr_addr_0_lcssa = $ptr_addr_0_be;
+ label = 31;
+ break;
+ } else {
+ $ptr_addr_049 = $ptr_addr_0_be;
+ label = 5;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0_lcssa;
+ $retval_0 = 6;
+ label = 32;
+ break;
+ case 32:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_entityValueTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $cmp149 = 0, $type = 0, $0 = 0, $ptr_addr_050 = 0, $1 = 0, $cmp2 = 0, $arrayidx4 = 0, $2 = 0, $idxprom = 0, $arrayidx5 = 0, $3 = 0, $conv6 = 0, $call = 0, $cond = 0, $add_ptr = 0, $add_ptr10 = 0, $add_ptr12 = 0, $cmp14 = 0, $add_ptr17 = 0, $call18 = 0, $cmp21 = 0, $add_ptr24 = 0, $call25 = 0, $cmp26 = 0, $cond31 = 0, $cmp34 = 0, $add_ptr37 = 0, $cmp40 = 0, $add_ptr43 = 0, $cmp44 = 0, $4 = 0, $cmp50 = 0, $arrayidx53 = 0, $5 = 0, $idxprom54 = 0, $type55 = 0, $6 = 0, $arrayidx56 = 0, $7 = 0, $conv57 = 0, $call61 = 0, $cond63 = 0, $cmp64 = 0, $add_ptr67 = 0, $add_ptr67_add_ptr43 = 0, $add_ptr70 = 0, $ptr_addr_0_be = 0, $cmp1 = 0, $ptr_addr_0_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 31;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp149 = ($ptr | 0) == ($end | 0);
+ if ($cmp149) {
+ $ptr_addr_0_lcssa = $ptr;
+ label = 30;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_050 = $ptr;
+ label = 5;
+ break;
+ case 5:
+ $1 = HEAP8[$ptr_addr_050] | 0;
+ $cmp2 = $1 << 24 >> 24 == 0;
+ $arrayidx4 = $ptr_addr_050 + 1 | 0;
+ $2 = HEAP8[$arrayidx4] | 0;
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $idxprom = $2 & 255;
+ $arrayidx5 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx5] | 0;
+ $conv6 = $3 & 255;
+ $cond = $conv6;
+ label = 8;
+ break;
+ case 7:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 8;
+ break;
+ case 8:
+ if (($cond | 0) == 5) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 3) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 30) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 18;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 21;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 9:
+ $add_ptr = $ptr_addr_050 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 29;
+ break;
+ case 10:
+ $add_ptr10 = $ptr_addr_050 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr10;
+ label = 29;
+ break;
+ case 11:
+ $add_ptr12 = $ptr_addr_050 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr12;
+ label = 29;
+ break;
+ case 12:
+ $cmp14 = ($ptr_addr_050 | 0) == ($ptr | 0);
+ if ($cmp14) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $add_ptr17 = $ptr_addr_050 + 2 | 0;
+ $call18 = _big2_scanRef($enc, $add_ptr17, $end, $nextTokPtr) | 0;
+ $retval_0 = $call18;
+ label = 31;
+ break;
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_050;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 15:
+ $cmp21 = ($ptr_addr_050 | 0) == ($ptr | 0);
+ if ($cmp21) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $add_ptr24 = $ptr_addr_050 + 2 | 0;
+ $call25 = _big2_scanPercent($enc, $add_ptr24, $end, $nextTokPtr) | 0;
+ $cmp26 = ($call25 | 0) == 22;
+ $cond31 = $cmp26 ? 0 : $call25;
+ $retval_0 = $cond31;
+ label = 31;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_050;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 18:
+ $cmp34 = ($ptr_addr_050 | 0) == ($ptr | 0);
+ if ($cmp34) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $add_ptr37 = $ptr_addr_050 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr37;
+ $retval_0 = 7;
+ label = 31;
+ break;
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_050;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 21:
+ $cmp40 = ($ptr_addr_050 | 0) == ($ptr | 0);
+ if ($cmp40) {
+ label = 22;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 22:
+ $add_ptr43 = $ptr_addr_050 + 2 | 0;
+ $cmp44 = ($add_ptr43 | 0) == ($end | 0);
+ if ($cmp44) {
+ $retval_0 = -3;
+ label = 31;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $4 = HEAP8[$add_ptr43] | 0;
+ $cmp50 = $4 << 24 >> 24 == 0;
+ $arrayidx53 = $ptr_addr_050 + 3 | 0;
+ $5 = HEAP8[$arrayidx53] | 0;
+ if ($cmp50) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $idxprom54 = $5 & 255;
+ $type55 = $enc + 72 | 0;
+ $6 = $type55;
+ $arrayidx56 = $6 + $idxprom54 | 0;
+ $7 = HEAP8[$arrayidx56] | 0;
+ $conv57 = $7 & 255;
+ $cond63 = $conv57;
+ label = 26;
+ break;
+ case 25:
+ $call61 = _unicode_byte_type($4, $5) | 0;
+ $cond63 = $call61;
+ label = 26;
+ break;
+ case 26:
+ $cmp64 = ($cond63 | 0) == 10;
+ $add_ptr67 = $ptr_addr_050 + 4 | 0;
+ $add_ptr67_add_ptr43 = $cmp64 ? $add_ptr67 : $add_ptr43;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr67_add_ptr43;
+ $retval_0 = 7;
+ label = 31;
+ break;
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_050;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 28:
+ $add_ptr70 = $ptr_addr_050 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr70;
+ label = 29;
+ break;
+ case 29:
+ $cmp1 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp1) {
+ $ptr_addr_0_lcssa = $ptr_addr_0_be;
+ label = 30;
+ break;
+ } else {
+ $ptr_addr_050 = $ptr_addr_0_be;
+ label = 5;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0_lcssa;
+ $retval_0 = 6;
+ label = 31;
+ break;
+ case 31:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_nameMatchesAscii($enc, $ptr1, $end1, $ptr2) {
+ $enc = $enc | 0;
+ $ptr1 = $ptr1 | 0;
+ $end1 = $end1 | 0;
+ $ptr2 = $ptr2 | 0;
+ var $0 = 0, $tobool7 = 0, $cmp8 = 0, $cmp11 = 0, $1 = 0, $ptr2_addr_010 = 0, $ptr1_addr_09 = 0, $2 = 0, $cmp1 = 0, $arrayidx3 = 0, $3 = 0, $cmp6 = 0, $add_ptr = 0, $incdec_ptr = 0, $4 = 0, $tobool = 0, $cmp = 0, $cmp_lcssa = 0, $conv11 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$ptr2] | 0;
+ $tobool7 = $0 << 24 >> 24 == 0;
+ $cmp8 = ($ptr1 | 0) == ($end1 | 0);
+ if ($tobool7) {
+ $cmp_lcssa = $cmp8;
+ label = 7;
+ break;
+ } else {
+ $ptr1_addr_09 = $ptr1;
+ $ptr2_addr_010 = $ptr2;
+ $1 = $0;
+ $cmp11 = $cmp8;
+ label = 3;
+ break;
+ }
+ case 3:
+ if ($cmp11) {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP8[$ptr1_addr_09] | 0;
+ $cmp1 = $2 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ }
+ case 5:
+ $arrayidx3 = $ptr1_addr_09 + 1 | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $cmp6 = $3 << 24 >> 24 == $1 << 24 >> 24;
+ if ($cmp6) {
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 8;
+ break;
+ }
+ case 6:
+ $add_ptr = $ptr1_addr_09 + 2 | 0;
+ $incdec_ptr = $ptr2_addr_010 + 1 | 0;
+ $4 = HEAP8[$incdec_ptr] | 0;
+ $tobool = $4 << 24 >> 24 == 0;
+ $cmp = ($add_ptr | 0) == ($end1 | 0);
+ if ($tobool) {
+ $cmp_lcssa = $cmp;
+ label = 7;
+ break;
+ } else {
+ $ptr1_addr_09 = $add_ptr;
+ $ptr2_addr_010 = $incdec_ptr;
+ $1 = $4;
+ $cmp11 = $cmp;
+ label = 3;
+ break;
+ }
+ case 7:
+ $conv11 = $cmp_lcssa & 1;
+ $retval_0 = $conv11;
+ label = 8;
+ break;
+ case 8:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_predefinedEntityName($enc, $ptr, $end) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $div = 0, $add_ptr = 0, $0 = 0, $cmp = 0, $arrayidx3 = 0, $1 = 0, $cmp5 = 0, $2 = 0, $cmp9 = 0, $arrayidx11 = 0, $3 = 0, $conv12 = 0, $4 = 0, $cmp18 = 0, $arrayidx21 = 0, $5 = 0, $cmp23 = 0, $add_ptr26 = 0, $6 = 0, $cmp29 = 0, $arrayidx32 = 0, $7 = 0, $cmp34 = 0, $add_ptr37 = 0, $8 = 0, $cmp40 = 0, $arrayidx43 = 0, $9 = 0, $cmp45 = 0, $10 = 0, $cmp54 = 0, $arrayidx57 = 0, $11 = 0, $conv58 = 0, $add_ptr63 = 0, $12 = 0, $cmp66 = 0, $arrayidx69 = 0, $13 = 0, $cmp71 = 0, $add_ptr74 = 0, $14 = 0, $cmp77 = 0, $arrayidx80 = 0, $15 = 0, $cmp82 = 0, $add_ptr85 = 0, $16 = 0, $cmp88 = 0, $arrayidx91 = 0, $17 = 0, $cmp93 = 0, $add_ptr100 = 0, $18 = 0, $cmp103 = 0, $arrayidx106 = 0, $19 = 0, $cmp108 = 0, $add_ptr111 = 0, $20 = 0, $cmp114 = 0, $arrayidx117 = 0, $21 = 0, $cmp119 = 0, $add_ptr122 = 0, $22 = 0, $cmp125 = 0, $arrayidx128 = 0, $23 = 0, $cmp130 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $div = ($sub_ptr_sub | 0) / 2 & -1;
+ if (($div | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($div | 0) == 3) {
+ label = 8;
+ break;
+ } else if (($div | 0) == 4) {
+ label = 14;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 3:
+ $add_ptr = $ptr + 2 | 0;
+ $0 = HEAP8[$add_ptr] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 4:
+ $arrayidx3 = $ptr + 3 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ $cmp5 = $1 << 24 >> 24 == 116;
+ if ($cmp5) {
+ label = 5;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 5:
+ $2 = HEAP8[$ptr] | 0;
+ $cmp9 = $2 << 24 >> 24 == 0;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 6:
+ $arrayidx11 = $ptr + 1 | 0;
+ $3 = HEAP8[$arrayidx11] | 0;
+ $conv12 = $3 << 24 >> 24;
+ if (($conv12 | 0) == 103) {
+ label = 7;
+ break;
+ } else if (($conv12 | 0) == 108) {
+ $retval_0 = 60;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 7:
+ $retval_0 = 62;
+ label = 29;
+ break;
+ case 8:
+ $4 = HEAP8[$ptr] | 0;
+ $cmp18 = $4 << 24 >> 24 == 0;
+ if ($cmp18) {
+ label = 9;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 9:
+ $arrayidx21 = $ptr + 1 | 0;
+ $5 = HEAP8[$arrayidx21] | 0;
+ $cmp23 = $5 << 24 >> 24 == 97;
+ if ($cmp23) {
+ label = 10;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 10:
+ $add_ptr26 = $ptr + 2 | 0;
+ $6 = HEAP8[$add_ptr26] | 0;
+ $cmp29 = $6 << 24 >> 24 == 0;
+ if ($cmp29) {
+ label = 11;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 11:
+ $arrayidx32 = $ptr + 3 | 0;
+ $7 = HEAP8[$arrayidx32] | 0;
+ $cmp34 = $7 << 24 >> 24 == 109;
+ if ($cmp34) {
+ label = 12;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 12:
+ $add_ptr37 = $ptr + 4 | 0;
+ $8 = HEAP8[$add_ptr37] | 0;
+ $cmp40 = $8 << 24 >> 24 == 0;
+ if ($cmp40) {
+ label = 13;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 13:
+ $arrayidx43 = $ptr + 5 | 0;
+ $9 = HEAP8[$arrayidx43] | 0;
+ $cmp45 = $9 << 24 >> 24 == 112;
+ if ($cmp45) {
+ $retval_0 = 38;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 14:
+ $10 = HEAP8[$ptr] | 0;
+ $cmp54 = $10 << 24 >> 24 == 0;
+ if ($cmp54) {
+ label = 15;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 15:
+ $arrayidx57 = $ptr + 1 | 0;
+ $11 = HEAP8[$arrayidx57] | 0;
+ $conv58 = $11 << 24 >> 24;
+ if (($conv58 | 0) == 113) {
+ label = 16;
+ break;
+ } else if (($conv58 | 0) == 97) {
+ label = 22;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 16:
+ $add_ptr63 = $ptr + 2 | 0;
+ $12 = HEAP8[$add_ptr63] | 0;
+ $cmp66 = $12 << 24 >> 24 == 0;
+ if ($cmp66) {
+ label = 17;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 17:
+ $arrayidx69 = $ptr + 3 | 0;
+ $13 = HEAP8[$arrayidx69] | 0;
+ $cmp71 = $13 << 24 >> 24 == 117;
+ if ($cmp71) {
+ label = 18;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 18:
+ $add_ptr74 = $ptr + 4 | 0;
+ $14 = HEAP8[$add_ptr74] | 0;
+ $cmp77 = $14 << 24 >> 24 == 0;
+ if ($cmp77) {
+ label = 19;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 19:
+ $arrayidx80 = $ptr + 5 | 0;
+ $15 = HEAP8[$arrayidx80] | 0;
+ $cmp82 = $15 << 24 >> 24 == 111;
+ if ($cmp82) {
+ label = 20;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 20:
+ $add_ptr85 = $ptr + 6 | 0;
+ $16 = HEAP8[$add_ptr85] | 0;
+ $cmp88 = $16 << 24 >> 24 == 0;
+ if ($cmp88) {
+ label = 21;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 21:
+ $arrayidx91 = $ptr + 7 | 0;
+ $17 = HEAP8[$arrayidx91] | 0;
+ $cmp93 = $17 << 24 >> 24 == 116;
+ if ($cmp93) {
+ $retval_0 = 34;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 22:
+ $add_ptr100 = $ptr + 2 | 0;
+ $18 = HEAP8[$add_ptr100] | 0;
+ $cmp103 = $18 << 24 >> 24 == 0;
+ if ($cmp103) {
+ label = 23;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 23:
+ $arrayidx106 = $ptr + 3 | 0;
+ $19 = HEAP8[$arrayidx106] | 0;
+ $cmp108 = $19 << 24 >> 24 == 112;
+ if ($cmp108) {
+ label = 24;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 24:
+ $add_ptr111 = $ptr + 4 | 0;
+ $20 = HEAP8[$add_ptr111] | 0;
+ $cmp114 = $20 << 24 >> 24 == 0;
+ if ($cmp114) {
+ label = 25;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 25:
+ $arrayidx117 = $ptr + 5 | 0;
+ $21 = HEAP8[$arrayidx117] | 0;
+ $cmp119 = $21 << 24 >> 24 == 111;
+ if ($cmp119) {
+ label = 26;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 26:
+ $add_ptr122 = $ptr + 6 | 0;
+ $22 = HEAP8[$add_ptr122] | 0;
+ $cmp125 = $22 << 24 >> 24 == 0;
+ if ($cmp125) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $arrayidx128 = $ptr + 7 | 0;
+ $23 = HEAP8[$arrayidx128] | 0;
+ $cmp130 = $23 << 24 >> 24 == 115;
+ if ($cmp130) {
+ $retval_0 = 39;
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 29:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_sameName($enc, $ptr1, $ptr2) {
+ $enc = $enc | 0;
+ $ptr1 = $ptr1 | 0;
+ $ptr2 = $ptr2 | 0;
+ var $type = 0, $0 = 0, $ptr1_addr_0 = 0, $ptr2_addr_0 = 0, $1 = 0, $cmp = 0, $arrayidx2 = 0, $2 = 0, $idxprom = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $4 = 0, $incdec_ptr8 = 0, $5 = 0, $cmp10 = 0, $ptr1_addr_1 = 0, $ptr2_addr_1 = 0, $incdec_ptr13 = 0, $6 = 0, $incdec_ptr15 = 0, $7 = 0, $cmp17 = 0, $ptr1_addr_2 = 0, $ptr2_addr_2 = 0, $8 = 0, $9 = 0, $cmp26 = 0, $incdec_ptr24 = 0, $incdec_ptr22 = 0, $10 = 0, $11 = 0, $cmp34 = 0, $12 = 0, $13 = 0, $cmp43 = 0, $incdec_ptr39 = 0, $14 = 0, $15 = 0, $cmp51 = 0, $ptr1_addr_0_pn = 0, $ptr2_addr_0_pn = 0, $ptr2_addr_0_be = 0, $ptr1_addr_0_be = 0, $16 = 0, $cmp57 = 0, $arrayidx60 = 0, $17 = 0, $idxprom61 = 0, $type62 = 0, $18 = 0, $arrayidx63 = 0, $19 = 0, $conv64 = 0, $call68 = 0, $cond70 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr2_addr_0 = $ptr2;
+ $ptr1_addr_0 = $ptr1;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP8[$ptr1_addr_0] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ $arrayidx2 = $ptr1_addr_0 + 1 | 0;
+ $2 = HEAP8[$arrayidx2] | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $2 & 255;
+ $arrayidx3 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 7) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 6) {
+ $ptr2_addr_1 = $ptr2_addr_0;
+ $ptr1_addr_1 = $ptr1_addr_0;
+ label = 8;
+ break;
+ } else if (($cond | 0) == 5) {
+ $ptr2_addr_2 = $ptr2_addr_0;
+ $ptr1_addr_2 = $ptr1_addr_0;
+ label = 9;
+ break;
+ } else if (($cond | 0) == 29 | ($cond | 0) == 22 | ($cond | 0) == 24 | ($cond | 0) == 25 | ($cond | 0) == 26 | ($cond | 0) == 27) {
+ label = 11;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 7:
+ $4 = HEAP8[$ptr1_addr_0] | 0;
+ $incdec_ptr8 = $ptr2_addr_0 + 1 | 0;
+ $5 = HEAP8[$ptr2_addr_0] | 0;
+ $cmp10 = $4 << 24 >> 24 == $5 << 24 >> 24;
+ if ($cmp10) {
+ $ptr2_addr_1 = $incdec_ptr8;
+ $ptr1_addr_1 = $arrayidx2;
+ label = 8;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 8:
+ $incdec_ptr13 = $ptr1_addr_1 + 1 | 0;
+ $6 = HEAP8[$ptr1_addr_1] | 0;
+ $incdec_ptr15 = $ptr2_addr_1 + 1 | 0;
+ $7 = HEAP8[$ptr2_addr_1] | 0;
+ $cmp17 = $6 << 24 >> 24 == $7 << 24 >> 24;
+ if ($cmp17) {
+ $ptr2_addr_2 = $incdec_ptr15;
+ $ptr1_addr_2 = $incdec_ptr13;
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 9:
+ $8 = HEAP8[$ptr1_addr_2] | 0;
+ $9 = HEAP8[$ptr2_addr_2] | 0;
+ $cmp26 = $8 << 24 >> 24 == $9 << 24 >> 24;
+ if ($cmp26) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 10:
+ $incdec_ptr24 = $ptr2_addr_2 + 1 | 0;
+ $incdec_ptr22 = $ptr1_addr_2 + 1 | 0;
+ $10 = HEAP8[$incdec_ptr22] | 0;
+ $11 = HEAP8[$incdec_ptr24] | 0;
+ $cmp34 = $10 << 24 >> 24 == $11 << 24 >> 24;
+ if ($cmp34) {
+ $ptr2_addr_0_pn = $ptr2_addr_2;
+ $ptr1_addr_0_pn = $ptr1_addr_2;
+ label = 13;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 11:
+ $12 = HEAP8[$ptr2_addr_0] | 0;
+ $13 = HEAP8[$ptr1_addr_0] | 0;
+ $cmp43 = $12 << 24 >> 24 == $13 << 24 >> 24;
+ if ($cmp43) {
+ label = 12;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 12:
+ $incdec_ptr39 = $ptr2_addr_0 + 1 | 0;
+ $14 = HEAP8[$incdec_ptr39] | 0;
+ $15 = HEAP8[$arrayidx2] | 0;
+ $cmp51 = $14 << 24 >> 24 == $15 << 24 >> 24;
+ if ($cmp51) {
+ $ptr2_addr_0_pn = $ptr2_addr_0;
+ $ptr1_addr_0_pn = $ptr1_addr_0;
+ label = 13;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ }
+ case 13:
+ $ptr2_addr_0_be = $ptr2_addr_0_pn + 2 | 0;
+ $ptr1_addr_0_be = $ptr1_addr_0_pn + 2 | 0;
+ $ptr2_addr_0 = $ptr2_addr_0_be;
+ $ptr1_addr_0 = $ptr1_addr_0_be;
+ label = 3;
+ break;
+ case 14:
+ $16 = HEAP8[$ptr2_addr_0] | 0;
+ $cmp57 = $16 << 24 >> 24 == 0;
+ $arrayidx60 = $ptr2_addr_0 + 1 | 0;
+ $17 = HEAP8[$arrayidx60] | 0;
+ if ($cmp57) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $idxprom61 = $17 & 255;
+ $type62 = $enc + 72 | 0;
+ $18 = $type62;
+ $arrayidx63 = $18 + $idxprom61 | 0;
+ $19 = HEAP8[$arrayidx63] | 0;
+ $conv64 = $19 & 255;
+ $cond70 = $conv64;
+ label = 17;
+ break;
+ case 16:
+ $call68 = _unicode_byte_type($16, $17) | 0;
+ $cond70 = $call68;
+ label = 17;
+ break;
+ case 17:
+ if (($cond70 | 0) == 5 | ($cond70 | 0) == 6 | ($cond70 | 0) == 7 | ($cond70 | 0) == 29 | ($cond70 | 0) == 22 | ($cond70 | 0) == 24 | ($cond70 | 0) == 25 | ($cond70 | 0) == 26 | ($cond70 | 0) == 27) {
+ $retval_0 = 0;
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $retval_0 = 1;
+ label = 19;
+ break;
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_nameLength($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $type = 0, $0 = 0, $ptr_addr_0 = 0, $1 = 0, $cmp = 0, $arrayidx2 = 0, $2 = 0, $idxprom = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $add_ptr = 0, $add_ptr8 = 0, $add_ptr10 = 0, $add_ptr12 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_0 = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP8[$ptr_addr_0] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ $arrayidx2 = $ptr_addr_0 + 1 | 0;
+ $2 = HEAP8[$arrayidx2] | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $2 & 255;
+ $arrayidx3 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 5) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 29 | ($cond | 0) == 22 | ($cond | 0) == 24 | ($cond | 0) == 25 | ($cond | 0) == 26 | ($cond | 0) == 27) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $add_ptr = $ptr_addr_0 + 2 | 0;
+ $ptr_addr_0 = $add_ptr;
+ label = 3;
+ break;
+ case 8:
+ $add_ptr8 = $ptr_addr_0 + 3 | 0;
+ $ptr_addr_0 = $add_ptr8;
+ label = 3;
+ break;
+ case 9:
+ $add_ptr10 = $ptr_addr_0 + 4 | 0;
+ $ptr_addr_0 = $add_ptr10;
+ label = 3;
+ break;
+ case 10:
+ $add_ptr12 = $ptr_addr_0 + 2 | 0;
+ $ptr_addr_0 = $add_ptr12;
+ label = 3;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $ptr_addr_0;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ return $sub_ptr_sub | 0;
+ }
+ return 0;
+}
+function _big2_skipS($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $type = 0, $0 = 0, $ptr_addr_0 = 0, $1 = 0, $cmp = 0, $arrayidx2 = 0, $2 = 0, $idxprom = 0, $arrayidx3 = 0, $3 = 0, $conv4 = 0, $call = 0, $cond = 0, $add_ptr = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_0 = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP8[$ptr_addr_0] | 0;
+ $cmp = $1 << 24 >> 24 == 0;
+ $arrayidx2 = $ptr_addr_0 + 1 | 0;
+ $2 = HEAP8[$arrayidx2] | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $2 & 255;
+ $arrayidx3 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $3 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 10 | ($cond | 0) == 9 | ($cond | 0) == 21) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $add_ptr = $ptr_addr_0 + 2 | 0;
+ $ptr_addr_0 = $add_ptr;
+ label = 3;
+ break;
+ case 8:
+ return $ptr_addr_0 | 0;
+ }
+ return 0;
+}
+function _big2_getAtts($enc, $ptr, $attsMax, $atts) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $attsMax = $attsMax | 0;
+ $atts = $atts | 0;
+ var $type = 0, $0 = 0, $type163 = 0, $1 = 0, $ptr_pn = 0, $state_0 = 0, $nAtts_0 = 0, $open_0 = 0, $ptr_addr_0 = 0, $2 = 0, $cmp = 0, $arrayidx2 = 0, $3 = 0, $idxprom = 0, $arrayidx3 = 0, $4 = 0, $conv4 = 0, $call = 0, $cond = 0, $cmp7 = 0, $cmp9 = 0, $name = 0, $normalized = 0, $cmp17 = 0, $cmp20 = 0, $name24 = 0, $normalized26 = 0, $cmp31 = 0, $cmp34 = 0, $name38 = 0, $normalized40 = 0, $state_3 = 0, $add_ptr43 = 0, $cmp45 = 0, $cmp48 = 0, $name52 = 0, $normalized54 = 0, $cmp58 = 0, $cmp61 = 0, $add_ptr64 = 0, $valuePtr = 0, $cmp67 = 0, $cmp70 = 0, $valueEnd = 0, $inc = 0, $cmp78 = 0, $cmp81 = 0, $add_ptr84 = 0, $valuePtr86 = 0, $cmp89 = 0, $cmp92 = 0, $valueEnd96 = 0, $inc98 = 0, $cmp102 = 0, $normalized106 = 0, $cmp109 = 0, $cmp113 = 0, $cmp115 = 0, $or_cond = 0, $normalized119 = 0, $5 = 0, $tobool = 0, $valuePtr123 = 0, $6 = 0, $cmp124 = 0, $7 = 0, $cmp128 = 0, $8 = 0, $phitmp = 0, $add_ptr139 = 0, $9 = 0, $cmp142 = 0, $arrayidx146 = 0, $10 = 0, $phitmp93 = 0, $_pr = 0, $cmp157 = 0, $arrayidx161 = 0, $11 = 0, $idxprom162 = 0, $arrayidx164 = 0, $12 = 0, $conv165 = 0, $13 = 0, $14 = 0, $call171 = 0, $cond173 = 0, $cmp174 = 0, $cmp182 = 0, $cmp186 = 0, $cmp189 = 0, $or_cond94 = 0, $normalized193 = 0, $cmp197 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $type163 = $enc + 72 | 0;
+ $1 = $type163;
+ $open_0 = 0;
+ $nAtts_0 = 0;
+ $state_0 = 1;
+ $ptr_pn = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $ptr_addr_0 = $ptr_pn + 2 | 0;
+ $2 = HEAP8[$ptr_addr_0] | 0;
+ $cmp = $2 << 24 >> 24 == 0;
+ $arrayidx2 = $ptr_pn + 3 | 0;
+ $3 = HEAP8[$arrayidx2] | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $3 & 255;
+ $arrayidx3 = $0 + $idxprom | 0;
+ $4 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $4 & 255;
+ $cond = $conv4;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($2, $3) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 5) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 29 | ($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 17;
+ break;
+ } else if (($cond | 0) == 12) {
+ label = 20;
+ break;
+ } else if (($cond | 0) == 13) {
+ label = 27;
+ break;
+ } else if (($cond | 0) == 3) {
+ label = 34;
+ break;
+ } else if (($cond | 0) == 21) {
+ label = 36;
+ break;
+ } else if (($cond | 0) == 9 | ($cond | 0) == 10) {
+ label = 49;
+ break;
+ } else if (($cond | 0) == 11 | ($cond | 0) == 17) {
+ label = 52;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 7:
+ $cmp7 = ($state_0 | 0) == 0;
+ if ($cmp7) {
+ label = 8;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 8:
+ $cmp9 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp9) {
+ label = 9;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 9:
+ $name = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name >> 2] = $ptr_addr_0;
+ $normalized = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized] = 1;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 10:
+ $cmp17 = ($state_0 | 0) == 0;
+ if ($cmp17) {
+ label = 11;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $arrayidx2;
+ label = 3;
+ break;
+ }
+ case 11:
+ $cmp20 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp20) {
+ label = 12;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $arrayidx2;
+ label = 3;
+ break;
+ }
+ case 12:
+ $name24 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name24 >> 2] = $ptr_addr_0;
+ $normalized26 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized26] = 1;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $arrayidx2;
+ label = 3;
+ break;
+ case 13:
+ $cmp31 = ($state_0 | 0) == 0;
+ if ($cmp31) {
+ label = 14;
+ break;
+ } else {
+ $state_3 = $state_0;
+ label = 16;
+ break;
+ }
+ case 14:
+ $cmp34 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp34) {
+ label = 15;
+ break;
+ } else {
+ $state_3 = 1;
+ label = 16;
+ break;
+ }
+ case 15:
+ $name38 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name38 >> 2] = $ptr_addr_0;
+ $normalized40 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized40] = 1;
+ $state_3 = 1;
+ label = 16;
+ break;
+ case 16:
+ $add_ptr43 = $ptr_pn + 4 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_3;
+ $ptr_pn = $add_ptr43;
+ label = 3;
+ break;
+ case 17:
+ $cmp45 = ($state_0 | 0) == 0;
+ if ($cmp45) {
+ label = 18;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 18:
+ $cmp48 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp48) {
+ label = 19;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 19:
+ $name52 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name52 >> 2] = $ptr_addr_0;
+ $normalized54 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized54] = 1;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 20:
+ $cmp58 = ($state_0 | 0) == 2;
+ if ($cmp58) {
+ label = 23;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $cmp61 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp61) {
+ label = 22;
+ break;
+ } else {
+ $open_0 = 12;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 22:
+ $add_ptr64 = $ptr_pn + 4 | 0;
+ $valuePtr = $atts + ($nAtts_0 << 4) + 4 | 0;
+ HEAP32[$valuePtr >> 2] = $add_ptr64;
+ $open_0 = 12;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 23:
+ $cmp67 = ($open_0 | 0) == 12;
+ if ($cmp67) {
+ label = 24;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 24:
+ $cmp70 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp70) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $valueEnd = $atts + ($nAtts_0 << 4) + 8 | 0;
+ HEAP32[$valueEnd >> 2] = $ptr_addr_0;
+ label = 26;
+ break;
+ case 26:
+ $inc = $nAtts_0 + 1 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $inc;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 27:
+ $cmp78 = ($state_0 | 0) == 2;
+ if ($cmp78) {
+ label = 30;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $cmp81 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp81) {
+ label = 29;
+ break;
+ } else {
+ $open_0 = 13;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 29:
+ $add_ptr84 = $ptr_pn + 4 | 0;
+ $valuePtr86 = $atts + ($nAtts_0 << 4) + 4 | 0;
+ HEAP32[$valuePtr86 >> 2] = $add_ptr84;
+ $open_0 = 13;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 30:
+ $cmp89 = ($open_0 | 0) == 13;
+ if ($cmp89) {
+ label = 31;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 31:
+ $cmp92 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp92) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 32:
+ $valueEnd96 = $atts + ($nAtts_0 << 4) + 8 | 0;
+ HEAP32[$valueEnd96 >> 2] = $ptr_addr_0;
+ label = 33;
+ break;
+ case 33:
+ $inc98 = $nAtts_0 + 1 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $inc98;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 34:
+ $cmp102 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp102) {
+ label = 35;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 35:
+ $normalized106 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized106] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 36:
+ $cmp109 = ($state_0 | 0) == 1;
+ if ($cmp109) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $cmp113 = ($state_0 | 0) == 2;
+ $cmp115 = ($nAtts_0 | 0) < ($attsMax | 0);
+ $or_cond = $cmp113 & $cmp115;
+ if ($or_cond) {
+ label = 38;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 38:
+ $normalized119 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ $5 = HEAP8[$normalized119] | 0;
+ $tobool = $5 << 24 >> 24 == 0;
+ if ($tobool) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $valuePtr123 = $atts + ($nAtts_0 << 4) + 4 | 0;
+ $6 = HEAP32[$valuePtr123 >> 2] | 0;
+ $cmp124 = ($ptr_addr_0 | 0) == ($6 | 0);
+ if ($cmp124) {
+ label = 48;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $7 = HEAP8[$ptr_addr_0] | 0;
+ $cmp128 = $7 << 24 >> 24 == 0;
+ if ($cmp128) {
+ label = 41;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 41:
+ $8 = HEAP8[$arrayidx2] | 0;
+ $phitmp = $8 << 24 >> 24 == 32;
+ if ($phitmp) {
+ label = 42;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 42:
+ $add_ptr139 = $ptr_pn + 4 | 0;
+ $9 = HEAP8[$add_ptr139] | 0;
+ $cmp142 = $9 << 24 >> 24 == 0;
+ $arrayidx146 = $ptr_pn + 5 | 0;
+ $10 = HEAP8[$arrayidx146] | 0;
+ if ($cmp142) {
+ label = 43;
+ break;
+ } else {
+ $14 = $9;
+ $13 = $10;
+ label = 46;
+ break;
+ }
+ case 43:
+ $phitmp93 = $10 << 24 >> 24 == 32;
+ if ($phitmp93) {
+ label = 48;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $_pr = HEAP8[$add_ptr139] | 0;
+ $cmp157 = $_pr << 24 >> 24 == 0;
+ $arrayidx161 = $ptr_pn + 5 | 0;
+ $11 = HEAP8[$arrayidx161] | 0;
+ if ($cmp157) {
+ label = 45;
+ break;
+ } else {
+ $14 = $_pr;
+ $13 = $11;
+ label = 46;
+ break;
+ }
+ case 45:
+ $idxprom162 = $11 & 255;
+ $arrayidx164 = $1 + $idxprom162 | 0;
+ $12 = HEAP8[$arrayidx164] | 0;
+ $conv165 = $12 & 255;
+ $cond173 = $conv165;
+ label = 47;
+ break;
+ case 46:
+ $call171 = _unicode_byte_type($14, $13) | 0;
+ $cond173 = $call171;
+ label = 47;
+ break;
+ case 47:
+ $cmp174 = ($cond173 | 0) == ($open_0 | 0);
+ if ($cmp174) {
+ label = 48;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 48:
+ HEAP8[$normalized119] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 49:
+ $cmp182 = ($state_0 | 0) == 1;
+ if ($cmp182) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $cmp186 = ($state_0 | 0) == 2;
+ $cmp189 = ($nAtts_0 | 0) < ($attsMax | 0);
+ $or_cond94 = $cmp186 & $cmp189;
+ if ($or_cond94) {
+ label = 51;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 51:
+ $normalized193 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized193] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 52:
+ $cmp197 = ($state_0 | 0) == 2;
+ if ($cmp197) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ return $nAtts_0 | 0;
+ }
+ return 0;
+}
+function _big2_charRefNumber($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $add_ptr = 0, $0 = 0, $cmp = 0, $arrayidx2 = 0, $1 = 0, $cmp4 = 0, $add_ptr6 = 0, $result_0 = 0, $ptr_addr_0 = 0, $2 = 0, $cmp9 = 0, $arrayidx11 = 0, $3 = 0, $phitmp28 = 0, $_pr = 0, $cmp17 = 0, $arrayidx19 = 0, $4 = 0, $conv20 = 0, $shl = 0, $sub = 0, $or = 0, $shl22 = 0, $add = 0, $add24 = 0, $shl26 = 0, $add28 = 0, $add29 = 0, $result_1 = 0, $cmp30 = 0, $add_ptr33 = 0, $result_2 = 0, $ptr_addr_1 = 0, $5 = 0, $cmp37 = 0, $arrayidx40 = 0, $6 = 0, $phitmp = 0, $_pr30 = 0, $cmp50 = 0, $arrayidx53 = 0, $7 = 0, $conv54 = 0, $phitmp27 = 0, $cond57 = 0, $mul = 0, $add59 = 0, $cmp60 = 0, $add_ptr65 = 0, $result_3 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add_ptr = $ptr + 4 | 0;
+ $0 = HEAP8[$add_ptr] | 0;
+ $cmp = $0 << 24 >> 24 == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $ptr_addr_1 = $add_ptr;
+ $result_2 = 0;
+ label = 13;
+ break;
+ }
+ case 3:
+ $arrayidx2 = $ptr + 5 | 0;
+ $1 = HEAP8[$arrayidx2] | 0;
+ $cmp4 = $1 << 24 >> 24 == 120;
+ if ($cmp4) {
+ label = 4;
+ break;
+ } else {
+ $ptr_addr_1 = $add_ptr;
+ $result_2 = 0;
+ label = 13;
+ break;
+ }
+ case 4:
+ $add_ptr6 = $ptr + 6 | 0;
+ $ptr_addr_0 = $add_ptr6;
+ $result_0 = 0;
+ label = 5;
+ break;
+ case 5:
+ $2 = HEAP8[$ptr_addr_0] | 0;
+ $cmp9 = $2 << 24 >> 24 == 0;
+ if ($cmp9) {
+ label = 6;
+ break;
+ } else {
+ $result_1 = $result_0;
+ label = 12;
+ break;
+ }
+ case 6:
+ $arrayidx11 = $ptr_addr_0 + 1 | 0;
+ $3 = HEAP8[$arrayidx11] | 0;
+ $phitmp28 = $3 << 24 >> 24 == 59;
+ if ($phitmp28) {
+ $result_3 = $result_0;
+ label = 18;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $_pr = HEAP8[$ptr_addr_0] | 0;
+ $cmp17 = $_pr << 24 >> 24 == 0;
+ if ($cmp17) {
+ label = 8;
+ break;
+ } else {
+ $result_1 = $result_0;
+ label = 12;
+ break;
+ }
+ case 8:
+ $arrayidx19 = $ptr_addr_0 + 1 | 0;
+ $4 = HEAP8[$arrayidx19] | 0;
+ $conv20 = $4 << 24 >> 24;
+ if (($conv20 | 0) == 48 | ($conv20 | 0) == 49 | ($conv20 | 0) == 50 | ($conv20 | 0) == 51 | ($conv20 | 0) == 52 | ($conv20 | 0) == 53 | ($conv20 | 0) == 54 | ($conv20 | 0) == 55 | ($conv20 | 0) == 56 | ($conv20 | 0) == 57) {
+ label = 9;
+ break;
+ } else if (($conv20 | 0) == 65 | ($conv20 | 0) == 66 | ($conv20 | 0) == 67 | ($conv20 | 0) == 68 | ($conv20 | 0) == 69 | ($conv20 | 0) == 70) {
+ label = 10;
+ break;
+ } else if (($conv20 | 0) == 97 | ($conv20 | 0) == 98 | ($conv20 | 0) == 99 | ($conv20 | 0) == 100 | ($conv20 | 0) == 101 | ($conv20 | 0) == 102) {
+ label = 11;
+ break;
+ } else {
+ $result_1 = $result_0;
+ label = 12;
+ break;
+ }
+ case 9:
+ $shl = $result_0 << 4;
+ $sub = $conv20 - 48 | 0;
+ $or = $sub | $shl;
+ $result_1 = $or;
+ label = 12;
+ break;
+ case 10:
+ $shl22 = $result_0 << 4;
+ $add = $shl22 - 55 | 0;
+ $add24 = $add + $conv20 | 0;
+ $result_1 = $add24;
+ label = 12;
+ break;
+ case 11:
+ $shl26 = $result_0 << 4;
+ $add28 = $shl26 - 87 | 0;
+ $add29 = $add28 + $conv20 | 0;
+ $result_1 = $add29;
+ label = 12;
+ break;
+ case 12:
+ $cmp30 = ($result_1 | 0) > 1114111;
+ $add_ptr33 = $ptr_addr_0 + 2 | 0;
+ if ($cmp30) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ $ptr_addr_0 = $add_ptr33;
+ $result_0 = $result_1;
+ label = 5;
+ break;
+ }
+ case 13:
+ $5 = HEAP8[$ptr_addr_1] | 0;
+ $cmp37 = $5 << 24 >> 24 == 0;
+ if ($cmp37) {
+ label = 14;
+ break;
+ } else {
+ $cond57 = -49;
+ label = 17;
+ break;
+ }
+ case 14:
+ $arrayidx40 = $ptr_addr_1 + 1 | 0;
+ $6 = HEAP8[$arrayidx40] | 0;
+ $phitmp = $6 << 24 >> 24 == 59;
+ if ($phitmp) {
+ $result_3 = $result_2;
+ label = 18;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $_pr30 = HEAP8[$ptr_addr_1] | 0;
+ $cmp50 = $_pr30 << 24 >> 24 == 0;
+ if ($cmp50) {
+ label = 16;
+ break;
+ } else {
+ $cond57 = -49;
+ label = 17;
+ break;
+ }
+ case 16:
+ $arrayidx53 = $ptr_addr_1 + 1 | 0;
+ $7 = HEAP8[$arrayidx53] | 0;
+ $conv54 = $7 << 24 >> 24;
+ $phitmp27 = $conv54 - 48 | 0;
+ $cond57 = $phitmp27;
+ label = 17;
+ break;
+ case 17:
+ $mul = $result_2 * 10 & -1;
+ $add59 = $cond57 + $mul | 0;
+ $cmp60 = ($add59 | 0) > 1114111;
+ $add_ptr65 = $ptr_addr_1 + 2 | 0;
+ if ($cmp60) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ $ptr_addr_1 = $add_ptr65;
+ $result_2 = $add59;
+ label = 13;
+ break;
+ }
+ case 18:
+ $call = _checkCharRefNumber($result_3) | 0;
+ $retval_0 = $call;
+ label = 19;
+ break;
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_updatePosition($enc, $ptr, $end, $pos) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $pos = $pos | 0;
+ var $cmp21 = 0, $type = 0, $0 = 0, $columnNumber41 = 0, $columnNumber = 0, $lineNumber = 0, $lineNumber15 = 0, $columnNumber39 = 0, $type27 = 0, $1 = 0, $ptr_addr_022 = 0, $2 = 0, $cmp1 = 0, $arrayidx3 = 0, $3 = 0, $idxprom = 0, $arrayidx4 = 0, $4 = 0, $conv5 = 0, $call = 0, $cond = 0, $add_ptr = 0, $add_ptr9 = 0, $add_ptr11 = 0, $5 = 0, $inc = 0, $add_ptr13 = 0, $6 = 0, $inc16 = 0, $add_ptr17 = 0, $cmp18 = 0, $7 = 0, $cmp22 = 0, $arrayidx25 = 0, $8 = 0, $idxprom26 = 0, $arrayidx28 = 0, $9 = 0, $conv29 = 0, $call33 = 0, $cond35 = 0, $cmp36 = 0, $add_ptr38 = 0, $add_ptr38_add_ptr17 = 0, $ptr_addr_1 = 0, $add_ptr40 = 0, $ptr_addr_2 = 0, $10 = 0, $inc42 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp21 = $ptr >>> 0 < $end >>> 0;
+ if ($cmp21) {
+ label = 3;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $columnNumber41 = $pos + 4 | 0;
+ $columnNumber = $pos + 4 | 0;
+ $lineNumber = $pos | 0;
+ $lineNumber15 = $pos | 0;
+ $columnNumber39 = $pos + 4 | 0;
+ $type27 = $enc + 72 | 0;
+ $1 = $type27;
+ $ptr_addr_022 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $2 = HEAP8[$ptr_addr_022] | 0;
+ $cmp1 = $2 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr_addr_022 + 1 | 0;
+ $3 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $idxprom = $3 & 255;
+ $arrayidx4 = $0 + $idxprom | 0;
+ $4 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $4 & 255;
+ $cond = $conv5;
+ label = 7;
+ break;
+ case 6:
+ $call = _unicode_byte_type($2, $3) | 0;
+ $cond = $call;
+ label = 7;
+ break;
+ case 7:
+ if (($cond | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 10) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 9) {
+ label = 12;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 8:
+ $add_ptr = $ptr_addr_022 + 2 | 0;
+ $ptr_addr_2 = $add_ptr;
+ label = 19;
+ break;
+ case 9:
+ $add_ptr9 = $ptr_addr_022 + 3 | 0;
+ $ptr_addr_2 = $add_ptr9;
+ label = 19;
+ break;
+ case 10:
+ $add_ptr11 = $ptr_addr_022 + 4 | 0;
+ $ptr_addr_2 = $add_ptr11;
+ label = 19;
+ break;
+ case 11:
+ HEAP32[$columnNumber >> 2] = -1;
+ $5 = HEAP32[$lineNumber >> 2] | 0;
+ $inc = $5 + 1 | 0;
+ HEAP32[$lineNumber >> 2] = $inc;
+ $add_ptr13 = $ptr_addr_022 + 2 | 0;
+ $ptr_addr_2 = $add_ptr13;
+ label = 19;
+ break;
+ case 12:
+ $6 = HEAP32[$lineNumber15 >> 2] | 0;
+ $inc16 = $6 + 1 | 0;
+ HEAP32[$lineNumber15 >> 2] = $inc16;
+ $add_ptr17 = $ptr_addr_022 + 2 | 0;
+ $cmp18 = ($add_ptr17 | 0) == ($end | 0);
+ if ($cmp18) {
+ $ptr_addr_1 = $add_ptr17;
+ label = 17;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $7 = HEAP8[$add_ptr17] | 0;
+ $cmp22 = $7 << 24 >> 24 == 0;
+ $arrayidx25 = $ptr_addr_022 + 3 | 0;
+ $8 = HEAP8[$arrayidx25] | 0;
+ if ($cmp22) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $idxprom26 = $8 & 255;
+ $arrayidx28 = $1 + $idxprom26 | 0;
+ $9 = HEAP8[$arrayidx28] | 0;
+ $conv29 = $9 & 255;
+ $cond35 = $conv29;
+ label = 16;
+ break;
+ case 15:
+ $call33 = _unicode_byte_type($7, $8) | 0;
+ $cond35 = $call33;
+ label = 16;
+ break;
+ case 16:
+ $cmp36 = ($cond35 | 0) == 10;
+ $add_ptr38 = $ptr_addr_022 + 4 | 0;
+ $add_ptr38_add_ptr17 = $cmp36 ? $add_ptr38 : $add_ptr17;
+ $ptr_addr_1 = $add_ptr38_add_ptr17;
+ label = 17;
+ break;
+ case 17:
+ HEAP32[$columnNumber39 >> 2] = -1;
+ $ptr_addr_2 = $ptr_addr_1;
+ label = 19;
+ break;
+ case 18:
+ $add_ptr40 = $ptr_addr_022 + 2 | 0;
+ $ptr_addr_2 = $add_ptr40;
+ label = 19;
+ break;
+ case 19:
+ $10 = HEAP32[$columnNumber41 >> 2] | 0;
+ $inc42 = $10 + 1 | 0;
+ HEAP32[$columnNumber41 >> 2] = $inc42;
+ $cmp = $ptr_addr_2 >>> 0 < $end >>> 0;
+ if ($cmp) {
+ $ptr_addr_022 = $ptr_addr_2;
+ label = 4;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ return;
+ }
+}
+function _big2_toUtf8($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $cmp57 = 0, $sub_ptr_lhs_cast23 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_lhs_cast50 = 0, $from_058 = 0, $arrayidx = 0, $1 = 0, $2 = 0, $conv = 0, $cmp3 = 0, $3 = 0, $cmp5 = 0, $incdec_ptr = 0, $4 = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp10 = 0, $shr50 = 0, $shl = 0, $or = 0, $or16 = 0, $incdec_ptr18 = 0, $and = 0, $or20 = 0, $5 = 0, $incdec_ptr22 = 0, $6 = 0, $sub_ptr_rhs_cast24 = 0, $sub_ptr_sub25 = 0, $cmp26 = 0, $shr3151 = 0, $or32 = 0, $incdec_ptr34 = 0, $and36 = 0, $shl37 = 0, $shr3952 = 0, $or40 = 0, $or41 = 0, $7 = 0, $incdec_ptr43 = 0, $and45 = 0, $or46 = 0, $8 = 0, $incdec_ptr48 = 0, $9 = 0, $sub_ptr_rhs_cast51 = 0, $sub_ptr_sub52 = 0, $cmp53 = 0, $and58 = 0, $shl59 = 0, $conv60 = 0, $shr6146 = 0, $or63 = 0, $add = 0, $shr6447 = 0, $or65 = 0, $conv66 = 0, $incdec_ptr67 = 0, $shr6948 = 0, $and70 = 0, $and71 = 0, $shl72 = 0, $or73 = 0, $or74 = 0, $conv75 = 0, $10 = 0, $incdec_ptr76 = 0, $add_ptr = 0, $arrayidx77 = 0, $11 = 0, $and79 = 0, $shl80 = 0, $12 = 0, $and83 = 0, $shl84 = 0, $shr8749 = 0, $or85 = 0, $or88 = 0, $or89 = 0, $13 = 0, $incdec_ptr91 = 0, $and93 = 0, $or94 = 0, $14 = 0, $incdec_ptr96 = 0, $from_1 = 0, $add_ptr97 = 0, $cmp = 0, $from_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $cmp57 = ($0 | 0) == ($fromLim | 0);
+ if ($cmp57) {
+ $from_0_lcssa = $0;
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $sub_ptr_lhs_cast23 = $toLim;
+ $sub_ptr_lhs_cast = $toLim;
+ $sub_ptr_lhs_cast50 = $toLim;
+ $from_058 = $0;
+ label = 4;
+ break;
+ case 4:
+ $arrayidx = $from_058 + 1 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $2 = HEAP8[$from_058] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 0) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 1 | ($conv | 0) == 2 | ($conv | 0) == 3 | ($conv | 0) == 4 | ($conv | 0) == 5 | ($conv | 0) == 6 | ($conv | 0) == 7) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 216 | ($conv | 0) == 217 | ($conv | 0) == 218 | ($conv | 0) == 219) {
+ label = 15;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 5:
+ $cmp3 = $1 << 24 >> 24 > -1;
+ if ($cmp3) {
+ label = 6;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 6:
+ $3 = HEAP32[$toP >> 2] | 0;
+ $cmp5 = ($3 | 0) == ($toLim | 0);
+ if ($cmp5) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ HEAP32[$fromP >> 2] = $from_058;
+ label = 20;
+ break;
+ case 8:
+ $incdec_ptr = $3 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr;
+ HEAP8[$3] = $1;
+ $from_1 = $from_058;
+ label = 18;
+ break;
+ case 9:
+ $4 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_rhs_cast = $4;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp10 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp10) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$fromP >> 2] = $from_058;
+ label = 20;
+ break;
+ case 11:
+ $shr50 = ($1 & 255) >>> 6;
+ $shl = $2 << 2;
+ $or = $shr50 | $shl;
+ $or16 = $or | -64;
+ $incdec_ptr18 = $4 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr18;
+ HEAP8[$4] = $or16;
+ $and = $1 & 63;
+ $or20 = $and | -128;
+ $5 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr22 = $5 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr22;
+ HEAP8[$5] = $or20;
+ $from_1 = $from_058;
+ label = 18;
+ break;
+ case 12:
+ $6 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_rhs_cast24 = $6;
+ $sub_ptr_sub25 = $sub_ptr_lhs_cast23 - $sub_ptr_rhs_cast24 | 0;
+ $cmp26 = ($sub_ptr_sub25 | 0) < 3;
+ if ($cmp26) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ HEAP32[$fromP >> 2] = $from_058;
+ label = 20;
+ break;
+ case 14:
+ $shr3151 = ($2 & 255) >>> 4;
+ $or32 = $shr3151 | -32;
+ $incdec_ptr34 = $6 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr34;
+ HEAP8[$6] = $or32;
+ $and36 = $2 << 2;
+ $shl37 = $and36 & 60;
+ $shr3952 = ($1 & 255) >>> 6;
+ $or40 = $shr3952 | $shl37;
+ $or41 = $or40 | -128;
+ $7 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr43 = $7 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr43;
+ HEAP8[$7] = $or41;
+ $and45 = $1 & 63;
+ $or46 = $and45 | -128;
+ $8 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr48 = $8 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr48;
+ HEAP8[$8] = $or46;
+ $from_1 = $from_058;
+ label = 18;
+ break;
+ case 15:
+ $9 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_rhs_cast51 = $9;
+ $sub_ptr_sub52 = $sub_ptr_lhs_cast50 - $sub_ptr_rhs_cast51 | 0;
+ $cmp53 = ($sub_ptr_sub52 | 0) < 4;
+ if ($cmp53) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ HEAP32[$fromP >> 2] = $from_058;
+ label = 20;
+ break;
+ case 17:
+ $and58 = $conv << 2;
+ $shl59 = $and58 & 12;
+ $conv60 = $1 & 255;
+ $shr6146 = $conv60 >>> 6;
+ $or63 = $shl59 | $shr6146;
+ $add = $or63 + 1 | 0;
+ $shr6447 = $add >>> 2;
+ $or65 = $shr6447 | 240;
+ $conv66 = $or65 & 255;
+ $incdec_ptr67 = $9 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr67;
+ HEAP8[$9] = $conv66;
+ $shr6948 = $conv60 >>> 2;
+ $and70 = $shr6948 & 15;
+ $and71 = $add << 4;
+ $shl72 = $and71 & 48;
+ $or73 = $and70 | $shl72;
+ $or74 = $or73 | 128;
+ $conv75 = $or74 & 255;
+ $10 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr76 = $10 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr76;
+ HEAP8[$10] = $conv75;
+ $add_ptr = $from_058 + 2 | 0;
+ $arrayidx77 = $from_058 + 3 | 0;
+ $11 = HEAP8[$arrayidx77] | 0;
+ $and79 = $1 << 4;
+ $shl80 = $and79 & 48;
+ $12 = HEAP8[$add_ptr] | 0;
+ $and83 = $12 << 2;
+ $shl84 = $and83 & 12;
+ $shr8749 = ($11 & 255) >>> 6;
+ $or85 = $shl80 | $shr8749;
+ $or88 = $or85 | $shl84;
+ $or89 = $or88 | -128;
+ $13 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr91 = $13 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr91;
+ HEAP8[$13] = $or89;
+ $and93 = $11 & 63;
+ $or94 = $and93 | -128;
+ $14 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr96 = $14 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr96;
+ HEAP8[$14] = $or94;
+ $from_1 = $add_ptr;
+ label = 18;
+ break;
+ case 18:
+ $add_ptr97 = $from_1 + 2 | 0;
+ $cmp = ($add_ptr97 | 0) == ($fromLim | 0);
+ if ($cmp) {
+ $from_0_lcssa = $add_ptr97;
+ label = 19;
+ break;
+ } else {
+ $from_058 = $add_ptr97;
+ label = 4;
+ break;
+ }
+ case 19:
+ HEAP32[$fromP >> 2] = $from_0_lcssa;
+ label = 20;
+ break;
+ case 20:
+ return;
+ }
+}
+function _big2_toUtf16($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $1 = 0, $sub_ptr_lhs_cast1 = 0, $sub_ptr_rhs_cast2 = 0, $sub_ptr_sub3 = 0, $cmp = 0, $add_ptr = 0, $2 = 0, $and = 0, $cmp4 = 0, $add_ptr_fromLim = 0, $fromLim_addr_0_ph = 0, $3 = 0, $cmp711 = 0, $4 = 0, $5 = 0, $cmp9 = 0, $6 = 0, $conv12 = 0, $shl13 = 0, $arrayidx14 = 0, $7 = 0, $conv15 = 0, $or = 0, $incdec_ptr = 0, $8 = 0, $add_ptr17 = 0, $cmp7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $sub_ptr_lhs_cast = $fromLim;
+ $sub_ptr_rhs_cast = $0;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $1 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_lhs_cast1 = $toLim;
+ $sub_ptr_rhs_cast2 = $1;
+ $sub_ptr_sub3 = $sub_ptr_lhs_cast1 - $sub_ptr_rhs_cast2 | 0;
+ $cmp = ($sub_ptr_sub | 0) > ($sub_ptr_sub3 | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $fromLim_addr_0_ph = $fromLim;
+ label = 4;
+ break;
+ }
+ case 3:
+ $add_ptr = $fromLim - 2 | 0;
+ $2 = HEAP8[$add_ptr] | 0;
+ $and = $2 & -8;
+ $cmp4 = $and << 24 >> 24 == -40;
+ $add_ptr_fromLim = $cmp4 ? $add_ptr : $fromLim;
+ $fromLim_addr_0_ph = $add_ptr_fromLim;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP32[$fromP >> 2] | 0;
+ $cmp711 = ($3 | 0) == ($fromLim_addr_0_ph | 0);
+ if ($cmp711) {
+ label = 7;
+ break;
+ } else {
+ $4 = $3;
+ label = 5;
+ break;
+ }
+ case 5:
+ $5 = HEAP32[$toP >> 2] | 0;
+ $cmp9 = ($5 | 0) == ($toLim | 0);
+ if ($cmp9) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $6 = HEAP8[$4] | 0;
+ $conv12 = $6 & 255;
+ $shl13 = $conv12 << 8;
+ $arrayidx14 = $4 + 1 | 0;
+ $7 = HEAP8[$arrayidx14] | 0;
+ $conv15 = $7 & 255;
+ $or = $shl13 | $conv15;
+ $incdec_ptr = $5 + 2 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr;
+ HEAP16[$5 >> 1] = $or;
+ $8 = HEAP32[$fromP >> 2] | 0;
+ $add_ptr17 = $8 + 2 | 0;
+ HEAP32[$fromP >> 2] = $add_ptr17;
+ $cmp7 = ($add_ptr17 | 0) == ($fromLim_addr_0_ph | 0);
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ $4 = $add_ptr17;
+ label = 5;
+ break;
+ }
+ case 7:
+ return;
+ }
+}
+function _big2_isPublicId($enc, $ptr, $end, $badPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $badPtr = $badPtr | 0;
+ var $add_ptr1 = 0, $ptr_addr_020 = 0, $cmp22 = 0, $type = 0, $0 = 0, $ptr_addr_024 = 0, $ptr_pn23 = 0, $1 = 0, $cmp2 = 0, $arrayidx4 = 0, $2 = 0, $idxprom = 0, $arrayidx5 = 0, $3 = 0, $conv6 = 0, $call = 0, $cond = 0, $ptr_addr_0 = 0, $cmp = 0, $4 = 0, $cmp12 = 0, $5 = 0, $cmp16 = 0, $6 = 0, $cmp21 = 0, $7 = 0, $phitmp16 = 0, $_pr = 0, $cmp33 = 0, $8 = 0, $conv37 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add_ptr1 = $end - 2 | 0;
+ $ptr_addr_020 = $ptr + 2 | 0;
+ $cmp22 = ($ptr_addr_020 | 0) == ($add_ptr1 | 0);
+ if ($cmp22) {
+ $retval_0 = 1;
+ label = 17;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_pn23 = $ptr;
+ $ptr_addr_024 = $ptr_addr_020;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP8[$ptr_addr_024] | 0;
+ $cmp2 = $1 << 24 >> 24 == 0;
+ $arrayidx4 = $ptr_pn23 + 3 | 0;
+ $2 = HEAP8[$arrayidx4] | 0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $idxprom = $2 & 255;
+ $arrayidx5 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx5] | 0;
+ $conv6 = $3 & 255;
+ $cond = $conv6;
+ label = 7;
+ break;
+ case 6:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 7;
+ break;
+ case 7:
+ if (($cond | 0) == 25 | ($cond | 0) == 24 | ($cond | 0) == 27 | ($cond | 0) == 13 | ($cond | 0) == 31 | ($cond | 0) == 32 | ($cond | 0) == 34 | ($cond | 0) == 35 | ($cond | 0) == 17 | ($cond | 0) == 14 | ($cond | 0) == 15 | ($cond | 0) == 9 | ($cond | 0) == 10 | ($cond | 0) == 18 | ($cond | 0) == 16 | ($cond | 0) == 33 | ($cond | 0) == 30 | ($cond | 0) == 19) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 21) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 26 | ($cond | 0) == 22) {
+ label = 12;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 8:
+ $ptr_addr_0 = $ptr_addr_024 + 2 | 0;
+ $cmp = ($ptr_addr_0 | 0) == ($add_ptr1 | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 17;
+ break;
+ } else {
+ $ptr_pn23 = $ptr_addr_024;
+ $ptr_addr_024 = $ptr_addr_0;
+ label = 4;
+ break;
+ }
+ case 9:
+ $4 = HEAP8[$ptr_addr_024] | 0;
+ $cmp12 = $4 << 24 >> 24 == 0;
+ if ($cmp12) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 10:
+ $5 = HEAP8[$arrayidx4] | 0;
+ $cmp16 = $5 << 24 >> 24 == 9;
+ if ($cmp16) {
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 11:
+ HEAP32[$badPtr >> 2] = $ptr_addr_024;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 12:
+ $6 = HEAP8[$ptr_addr_024] | 0;
+ $cmp21 = $6 << 24 >> 24 == 0;
+ if ($cmp21) {
+ label = 13;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 13:
+ $7 = HEAP8[$arrayidx4] | 0;
+ $phitmp16 = $7 << 24 >> 24 < 0;
+ if ($phitmp16) {
+ label = 14;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 14:
+ $_pr = HEAP8[$ptr_addr_024] | 0;
+ $cmp33 = $_pr << 24 >> 24 == 0;
+ if ($cmp33) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $8 = HEAP8[$arrayidx4] | 0;
+ $conv37 = $8 << 24 >> 24;
+ if (($conv37 | 0) == 36 | ($conv37 | 0) == 64) {
+ label = 8;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$badPtr >> 2] = $ptr_addr_024;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 17:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $ptr_addr_069 = 0, $cmp4670 = 0, $type55 = 0, $4 = 0, $5 = 0, $idxprom9 = 0, $arrayidx10 = 0, $6 = 0, $conv11 = 0, $shl = 0, $7 = 0, $conv13 = 0, $shr56 = 0, $add = 0, $arrayidx14 = 0, $8 = 0, $and = 0, $shl17 = 0, $and18 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp23 = 0, $sub_ptr_lhs_cast28 = 0, $sub_ptr_rhs_cast29 = 0, $sub_ptr_sub30 = 0, $cmp31 = 0, $sub_ptr_lhs_cast36 = 0, $sub_ptr_rhs_cast37 = 0, $sub_ptr_sub38 = 0, $cmp39 = 0, $add_ptr44 = 0, $call45 = 0, $ptr_addr_072 = 0, $ptr_pn71 = 0, $9 = 0, $cmp50 = 0, $arrayidx53 = 0, $10 = 0, $idxprom54 = 0, $arrayidx56 = 0, $11 = 0, $conv57 = 0, $call61 = 0, $cond63 = 0, $12 = 0, $idxprom66 = 0, $arrayidx67 = 0, $13 = 0, $conv68 = 0, $shl69 = 0, $14 = 0, $conv71 = 0, $shr7255 = 0, $add73 = 0, $arrayidx74 = 0, $15 = 0, $and77 = 0, $shl78 = 0, $and79 = 0, $tobool80 = 0, $ptr_addr_0 = 0, $cmp46 = 0, $sub_ptr_lhs_cast86 = 0, $sub_ptr_rhs_cast87 = 0, $sub_ptr_sub88 = 0, $cmp89 = 0, $sub_ptr_lhs_cast94 = 0, $sub_ptr_rhs_cast95 = 0, $sub_ptr_sub96 = 0, $cmp97 = 0, $sub_ptr_lhs_cast102 = 0, $sub_ptr_rhs_cast103 = 0, $sub_ptr_sub104 = 0, $cmp105 = 0, $add_ptr110 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx4 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 19) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 7:
+ $ptr_addr_069 = $ptr + 2 | 0;
+ $cmp4670 = ($ptr_addr_069 | 0) == ($end | 0);
+ if ($cmp4670) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type55 = $enc + 72 | 0;
+ $4 = $type55;
+ $ptr_pn71 = $ptr;
+ $ptr_addr_072 = $ptr_addr_069;
+ label = 19;
+ break;
+ case 9:
+ $5 = HEAP8[$ptr] | 0;
+ $idxprom9 = $5 & 255;
+ $arrayidx10 = $idxprom9 + 9272 | 0;
+ $6 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $6 & 255;
+ $shl = $conv11 << 3;
+ $7 = HEAP8[$arrayidx3] | 0;
+ $conv13 = $7 & 255;
+ $shr56 = $conv13 >>> 5;
+ $add = $shr56 | $shl;
+ $arrayidx14 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx14 >> 2] | 0;
+ $and = $conv13 & 31;
+ $shl17 = 1 << $and;
+ $and18 = $shl17 & $8;
+ $tobool = ($and18 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp23 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp23) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast28 = $end;
+ $sub_ptr_rhs_cast29 = $ptr;
+ $sub_ptr_sub30 = $sub_ptr_lhs_cast28 - $sub_ptr_rhs_cast29 | 0;
+ $cmp31 = ($sub_ptr_sub30 | 0) < 3;
+ if ($cmp31) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast36 = $end;
+ $sub_ptr_rhs_cast37 = $ptr;
+ $sub_ptr_sub38 = $sub_ptr_lhs_cast36 - $sub_ptr_rhs_cast37 | 0;
+ $cmp39 = ($sub_ptr_sub38 | 0) < 4;
+ if ($cmp39) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 17:
+ $add_ptr44 = $ptr + 2 | 0;
+ $call45 = _big2_scanCharRef($enc, $add_ptr44, $end, $nextTokPtr) | 0;
+ $retval_0 = $call45;
+ label = 34;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 19:
+ $9 = HEAP8[$ptr_addr_072] | 0;
+ $cmp50 = $9 << 24 >> 24 == 0;
+ $arrayidx53 = $ptr_pn71 + 3 | 0;
+ $10 = HEAP8[$arrayidx53] | 0;
+ if ($cmp50) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $idxprom54 = $10 & 255;
+ $arrayidx56 = $4 + $idxprom54 | 0;
+ $11 = HEAP8[$arrayidx56] | 0;
+ $conv57 = $11 & 255;
+ $cond63 = $conv57;
+ label = 22;
+ break;
+ case 21:
+ $call61 = _unicode_byte_type($9, $10) | 0;
+ $cond63 = $call61;
+ label = 22;
+ break;
+ case 22:
+ if (($cond63 | 0) == 29) {
+ label = 23;
+ break;
+ } else if (($cond63 | 0) == 22 | ($cond63 | 0) == 24 | ($cond63 | 0) == 25 | ($cond63 | 0) == 26 | ($cond63 | 0) == 27) {
+ label = 24;
+ break;
+ } else if (($cond63 | 0) == 5) {
+ label = 26;
+ break;
+ } else if (($cond63 | 0) == 6) {
+ label = 28;
+ break;
+ } else if (($cond63 | 0) == 7) {
+ label = 30;
+ break;
+ } else if (($cond63 | 0) == 18) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 23:
+ $12 = HEAP8[$ptr_addr_072] | 0;
+ $idxprom66 = $12 & 255;
+ $arrayidx67 = $idxprom66 + 10824 | 0;
+ $13 = HEAP8[$arrayidx67] | 0;
+ $conv68 = $13 & 255;
+ $shl69 = $conv68 << 3;
+ $14 = HEAP8[$arrayidx53] | 0;
+ $conv71 = $14 & 255;
+ $shr7255 = $conv71 >>> 5;
+ $add73 = $shr7255 | $shl69;
+ $arrayidx74 = 9544 + ($add73 << 2) | 0;
+ $15 = HEAP32[$arrayidx74 >> 2] | 0;
+ $and77 = $conv71 & 31;
+ $shl78 = 1 << $and77;
+ $and79 = $shl78 & $15;
+ $tobool80 = ($and79 | 0) == 0;
+ if ($tobool80) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $ptr_addr_0 = $ptr_addr_072 + 2 | 0;
+ $cmp46 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp46) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ $ptr_pn71 = $ptr_addr_072;
+ $ptr_addr_072 = $ptr_addr_0;
+ label = 19;
+ break;
+ }
+ case 25:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 26:
+ $sub_ptr_lhs_cast86 = $end;
+ $sub_ptr_rhs_cast87 = $ptr_addr_072;
+ $sub_ptr_sub88 = $sub_ptr_lhs_cast86 - $sub_ptr_rhs_cast87 | 0;
+ $cmp89 = ($sub_ptr_sub88 | 0) < 2;
+ if ($cmp89) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 28:
+ $sub_ptr_lhs_cast94 = $end;
+ $sub_ptr_rhs_cast95 = $ptr_addr_072;
+ $sub_ptr_sub96 = $sub_ptr_lhs_cast94 - $sub_ptr_rhs_cast95 | 0;
+ $cmp97 = ($sub_ptr_sub96 | 0) < 3;
+ if ($cmp97) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 30:
+ $sub_ptr_lhs_cast102 = $end;
+ $sub_ptr_rhs_cast103 = $ptr_addr_072;
+ $sub_ptr_sub104 = $sub_ptr_lhs_cast102 - $sub_ptr_rhs_cast103 | 0;
+ $cmp105 = ($sub_ptr_sub104 | 0) < 4;
+ if ($cmp105) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 32:
+ $add_ptr110 = $ptr_pn71 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr110;
+ $retval_0 = 9;
+ label = 34;
+ break;
+ case 33:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_072;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 34:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanPercent($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $ptr_addr_067 = 0, $cmp4468 = 0, $type53 = 0, $4 = 0, $5 = 0, $idxprom9 = 0, $arrayidx10 = 0, $6 = 0, $conv11 = 0, $shl = 0, $7 = 0, $conv13 = 0, $shr54 = 0, $add = 0, $arrayidx14 = 0, $8 = 0, $and = 0, $shl17 = 0, $and18 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp23 = 0, $sub_ptr_lhs_cast28 = 0, $sub_ptr_rhs_cast29 = 0, $sub_ptr_sub30 = 0, $cmp31 = 0, $sub_ptr_lhs_cast36 = 0, $sub_ptr_rhs_cast37 = 0, $sub_ptr_sub38 = 0, $cmp39 = 0, $ptr_addr_070 = 0, $ptr_pn69 = 0, $9 = 0, $cmp48 = 0, $arrayidx51 = 0, $10 = 0, $idxprom52 = 0, $arrayidx54 = 0, $11 = 0, $conv55 = 0, $call59 = 0, $cond61 = 0, $12 = 0, $idxprom64 = 0, $arrayidx65 = 0, $13 = 0, $conv66 = 0, $shl67 = 0, $14 = 0, $conv69 = 0, $shr7053 = 0, $add71 = 0, $arrayidx72 = 0, $15 = 0, $and75 = 0, $shl76 = 0, $and77 = 0, $tobool78 = 0, $ptr_addr_0 = 0, $cmp44 = 0, $sub_ptr_lhs_cast84 = 0, $sub_ptr_rhs_cast85 = 0, $sub_ptr_sub86 = 0, $cmp87 = 0, $sub_ptr_lhs_cast92 = 0, $sub_ptr_rhs_cast93 = 0, $sub_ptr_sub94 = 0, $cmp95 = 0, $sub_ptr_lhs_cast100 = 0, $sub_ptr_rhs_cast101 = 0, $sub_ptr_sub102 = 0, $cmp103 = 0, $add_ptr108 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx4 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 21 | ($cond | 0) == 10 | ($cond | 0) == 9 | ($cond | 0) == 30) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 7:
+ $ptr_addr_067 = $ptr + 2 | 0;
+ $cmp4468 = ($ptr_addr_067 | 0) == ($end | 0);
+ if ($cmp4468) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type53 = $enc + 72 | 0;
+ $4 = $type53;
+ $ptr_pn69 = $ptr;
+ $ptr_addr_070 = $ptr_addr_067;
+ label = 19;
+ break;
+ case 9:
+ $5 = HEAP8[$ptr] | 0;
+ $idxprom9 = $5 & 255;
+ $arrayidx10 = $idxprom9 + 9272 | 0;
+ $6 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $6 & 255;
+ $shl = $conv11 << 3;
+ $7 = HEAP8[$arrayidx3] | 0;
+ $conv13 = $7 & 255;
+ $shr54 = $conv13 >>> 5;
+ $add = $shr54 | $shl;
+ $arrayidx14 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx14 >> 2] | 0;
+ $and = $conv13 & 31;
+ $shl17 = 1 << $and;
+ $and18 = $shl17 & $8;
+ $tobool = ($and18 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp23 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp23) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast28 = $end;
+ $sub_ptr_rhs_cast29 = $ptr;
+ $sub_ptr_sub30 = $sub_ptr_lhs_cast28 - $sub_ptr_rhs_cast29 | 0;
+ $cmp31 = ($sub_ptr_sub30 | 0) < 3;
+ if ($cmp31) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast36 = $end;
+ $sub_ptr_rhs_cast37 = $ptr;
+ $sub_ptr_sub38 = $sub_ptr_lhs_cast36 - $sub_ptr_rhs_cast37 | 0;
+ $cmp39 = ($sub_ptr_sub38 | 0) < 4;
+ if ($cmp39) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 22;
+ label = 34;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 19:
+ $9 = HEAP8[$ptr_addr_070] | 0;
+ $cmp48 = $9 << 24 >> 24 == 0;
+ $arrayidx51 = $ptr_pn69 + 3 | 0;
+ $10 = HEAP8[$arrayidx51] | 0;
+ if ($cmp48) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $idxprom52 = $10 & 255;
+ $arrayidx54 = $4 + $idxprom52 | 0;
+ $11 = HEAP8[$arrayidx54] | 0;
+ $conv55 = $11 & 255;
+ $cond61 = $conv55;
+ label = 22;
+ break;
+ case 21:
+ $call59 = _unicode_byte_type($9, $10) | 0;
+ $cond61 = $call59;
+ label = 22;
+ break;
+ case 22:
+ if (($cond61 | 0) == 29) {
+ label = 23;
+ break;
+ } else if (($cond61 | 0) == 22 | ($cond61 | 0) == 24 | ($cond61 | 0) == 25 | ($cond61 | 0) == 26 | ($cond61 | 0) == 27) {
+ label = 24;
+ break;
+ } else if (($cond61 | 0) == 5) {
+ label = 26;
+ break;
+ } else if (($cond61 | 0) == 6) {
+ label = 28;
+ break;
+ } else if (($cond61 | 0) == 7) {
+ label = 30;
+ break;
+ } else if (($cond61 | 0) == 18) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 23:
+ $12 = HEAP8[$ptr_addr_070] | 0;
+ $idxprom64 = $12 & 255;
+ $arrayidx65 = $idxprom64 + 10824 | 0;
+ $13 = HEAP8[$arrayidx65] | 0;
+ $conv66 = $13 & 255;
+ $shl67 = $conv66 << 3;
+ $14 = HEAP8[$arrayidx51] | 0;
+ $conv69 = $14 & 255;
+ $shr7053 = $conv69 >>> 5;
+ $add71 = $shr7053 | $shl67;
+ $arrayidx72 = 9544 + ($add71 << 2) | 0;
+ $15 = HEAP32[$arrayidx72 >> 2] | 0;
+ $and75 = $conv69 & 31;
+ $shl76 = 1 << $and75;
+ $and77 = $shl76 & $15;
+ $tobool78 = ($and77 | 0) == 0;
+ if ($tobool78) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $ptr_addr_0 = $ptr_addr_070 + 2 | 0;
+ $cmp44 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp44) {
+ $retval_0 = -1;
+ label = 34;
+ break;
+ } else {
+ $ptr_pn69 = $ptr_addr_070;
+ $ptr_addr_070 = $ptr_addr_0;
+ label = 19;
+ break;
+ }
+ case 25:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 26:
+ $sub_ptr_lhs_cast84 = $end;
+ $sub_ptr_rhs_cast85 = $ptr_addr_070;
+ $sub_ptr_sub86 = $sub_ptr_lhs_cast84 - $sub_ptr_rhs_cast85 | 0;
+ $cmp87 = ($sub_ptr_sub86 | 0) < 2;
+ if ($cmp87) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 28:
+ $sub_ptr_lhs_cast92 = $end;
+ $sub_ptr_rhs_cast93 = $ptr_addr_070;
+ $sub_ptr_sub94 = $sub_ptr_lhs_cast92 - $sub_ptr_rhs_cast93 | 0;
+ $cmp95 = ($sub_ptr_sub94 | 0) < 3;
+ if ($cmp95) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 30:
+ $sub_ptr_lhs_cast100 = $end;
+ $sub_ptr_rhs_cast101 = $ptr_addr_070;
+ $sub_ptr_sub102 = $sub_ptr_lhs_cast100 - $sub_ptr_rhs_cast101 | 0;
+ $cmp103 = ($sub_ptr_sub102 | 0) < 4;
+ if ($cmp103) {
+ $retval_0 = -2;
+ label = 34;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 32:
+ $add_ptr108 = $ptr_pn69 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr108;
+ $retval_0 = 28;
+ label = 34;
+ break;
+ case 33:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 34;
+ break;
+ case 34:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanCharRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $cmp5 = 0, $add_ptr = 0, $call = 0, $_pr = 0, $cmp10 = 0, $arrayidx12 = 0, $2 = 0, $idxprom = 0, $type = 0, $3 = 0, $arrayidx13 = 0, $4 = 0, $conv14 = 0, $5 = 0, $6 = 0, $call17 = 0, $cond = 0, $cond1 = 0, $type28 = 0, $7 = 0, $ptr_pn = 0, $ptr_addr_0 = 0, $cmp19 = 0, $8 = 0, $cmp23 = 0, $arrayidx26 = 0, $9 = 0, $idxprom27 = 0, $arrayidx29 = 0, $10 = 0, $conv30 = 0, $call34 = 0, $cond36 = 0, $add_ptr39 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ $6 = $0;
+ $5 = $1;
+ label = 8;
+ break;
+ }
+ case 4:
+ $cmp5 = $1 << 24 >> 24 == 120;
+ if ($cmp5) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + 2 | 0;
+ $call = _big2_scanHexCharRef($enc, $add_ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 19;
+ break;
+ case 6:
+ $_pr = HEAP8[$ptr] | 0;
+ $cmp10 = $_pr << 24 >> 24 == 0;
+ $arrayidx12 = $ptr + 1 | 0;
+ $2 = HEAP8[$arrayidx12] | 0;
+ if ($cmp10) {
+ label = 7;
+ break;
+ } else {
+ $6 = $_pr;
+ $5 = $2;
+ label = 8;
+ break;
+ }
+ case 7:
+ $idxprom = $2 & 255;
+ $type = $enc + 72 | 0;
+ $3 = $type;
+ $arrayidx13 = $3 + $idxprom | 0;
+ $4 = HEAP8[$arrayidx13] | 0;
+ $conv14 = $4 & 255;
+ $cond = $conv14;
+ label = 9;
+ break;
+ case 8:
+ $call17 = _unicode_byte_type($6, $5) | 0;
+ $cond = $call17;
+ label = 9;
+ break;
+ case 9:
+ $cond1 = ($cond | 0) == 25;
+ if ($cond1) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $type28 = $enc + 72 | 0;
+ $7 = $type28;
+ $ptr_pn = $ptr;
+ label = 12;
+ break;
+ case 11:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 12:
+ $ptr_addr_0 = $ptr_pn + 2 | 0;
+ $cmp19 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp19) {
+ $retval_0 = -1;
+ label = 19;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $8 = HEAP8[$ptr_addr_0] | 0;
+ $cmp23 = $8 << 24 >> 24 == 0;
+ $arrayidx26 = $ptr_pn + 3 | 0;
+ $9 = HEAP8[$arrayidx26] | 0;
+ if ($cmp23) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $idxprom27 = $9 & 255;
+ $arrayidx29 = $7 + $idxprom27 | 0;
+ $10 = HEAP8[$arrayidx29] | 0;
+ $conv30 = $10 & 255;
+ $cond36 = $conv30;
+ label = 16;
+ break;
+ case 15:
+ $call34 = _unicode_byte_type($8, $9) | 0;
+ $cond36 = $call34;
+ label = 16;
+ break;
+ case 16:
+ if (($cond36 | 0) == 25) {
+ $ptr_pn = $ptr_addr_0;
+ label = 12;
+ break;
+ } else if (($cond36 | 0) == 18) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $add_ptr39 = $ptr_pn + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr39;
+ $retval_0 = 10;
+ label = 19;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0;
+ $retval_0 = 0;
+ label = 19;
+ break;
+ case 19:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanHexCharRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $cond_off = 0, $switch = 0, $ptr_addr_020 = 0, $cmp821 = 0, $type17 = 0, $4 = 0, $ptr_addr_023 = 0, $ptr_pn22 = 0, $5 = 0, $cmp12 = 0, $arrayidx15 = 0, $6 = 0, $idxprom16 = 0, $arrayidx18 = 0, $7 = 0, $conv19 = 0, $call23 = 0, $cond25 = 0, $ptr_addr_0 = 0, $cmp8 = 0, $add_ptr28 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 17;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx4 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ $cond_off = $cond - 24 | 0;
+ $switch = $cond_off >>> 0 < 2;
+ if ($switch) {
+ label = 7;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 7:
+ $ptr_addr_020 = $ptr + 2 | 0;
+ $cmp821 = ($ptr_addr_020 | 0) == ($end | 0);
+ if ($cmp821) {
+ $retval_0 = -1;
+ label = 17;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type17 = $enc + 72 | 0;
+ $4 = $type17;
+ $ptr_pn22 = $ptr;
+ $ptr_addr_023 = $ptr_addr_020;
+ label = 10;
+ break;
+ case 9:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 10:
+ $5 = HEAP8[$ptr_addr_023] | 0;
+ $cmp12 = $5 << 24 >> 24 == 0;
+ $arrayidx15 = $ptr_pn22 + 3 | 0;
+ $6 = HEAP8[$arrayidx15] | 0;
+ if ($cmp12) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $idxprom16 = $6 & 255;
+ $arrayidx18 = $4 + $idxprom16 | 0;
+ $7 = HEAP8[$arrayidx18] | 0;
+ $conv19 = $7 & 255;
+ $cond25 = $conv19;
+ label = 13;
+ break;
+ case 12:
+ $call23 = _unicode_byte_type($5, $6) | 0;
+ $cond25 = $call23;
+ label = 13;
+ break;
+ case 13:
+ if (($cond25 | 0) == 25 | ($cond25 | 0) == 24) {
+ label = 14;
+ break;
+ } else if (($cond25 | 0) == 18) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 14:
+ $ptr_addr_0 = $ptr_addr_023 + 2 | 0;
+ $cmp8 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp8) {
+ $retval_0 = -1;
+ label = 17;
+ break;
+ } else {
+ $ptr_pn22 = $ptr_addr_023;
+ $ptr_addr_023 = $ptr_addr_0;
+ label = 10;
+ break;
+ }
+ case 15:
+ $add_ptr28 = $ptr_pn22 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr28;
+ $retval_0 = 10;
+ label = 17;
+ break;
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_023;
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 17:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanCdataSection($ptr, $end, $nextTokPtr) {
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp = 0, $0 = 0, $cmp2 = 0, $arrayidx4 = 0, $1 = 0, $cmp8 = 0, $ptr_addr_02_lcssa = 0, $add_ptr = 0, $2 = 0, $cmp2_1 = 0, $retval_0 = 0, $arrayidx4_1 = 0, $3 = 0, $cmp8_1 = 0, $add_ptr_1 = 0, $4 = 0, $cmp2_2 = 0, $arrayidx4_2 = 0, $5 = 0, $cmp8_2 = 0, $add_ptr_2 = 0, $6 = 0, $cmp2_3 = 0, $arrayidx4_3 = 0, $7 = 0, $cmp8_3 = 0, $add_ptr_3 = 0, $8 = 0, $cmp2_4 = 0, $arrayidx4_4 = 0, $9 = 0, $cmp8_4 = 0, $add_ptr_4 = 0, $10 = 0, $cmp2_5 = 0, $arrayidx4_5 = 0, $11 = 0, $cmp8_5 = 0, $add_ptr_5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp = ($sub_ptr_sub | 0) < 12;
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 7;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp2 = $0 << 24 >> 24 == 0;
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $ptr;
+ label = 5;
+ break;
+ }
+ case 4:
+ $arrayidx4 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx4] | 0;
+ $cmp8 = $1 << 24 >> 24 == 67;
+ if ($cmp8) {
+ label = 6;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $ptr;
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_02_lcssa;
+ $retval_0 = 0;
+ label = 7;
+ break;
+ case 6:
+ $add_ptr = $ptr + 2 | 0;
+ $2 = HEAP8[$add_ptr] | 0;
+ $cmp2_1 = $2 << 24 >> 24 == 0;
+ if ($cmp2_1) {
+ label = 8;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr;
+ label = 5;
+ break;
+ }
+ case 7:
+ return $retval_0 | 0;
+ case 8:
+ $arrayidx4_1 = $ptr + 3 | 0;
+ $3 = HEAP8[$arrayidx4_1] | 0;
+ $cmp8_1 = $3 << 24 >> 24 == 68;
+ if ($cmp8_1) {
+ label = 9;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr;
+ label = 5;
+ break;
+ }
+ case 9:
+ $add_ptr_1 = $ptr + 4 | 0;
+ $4 = HEAP8[$add_ptr_1] | 0;
+ $cmp2_2 = $4 << 24 >> 24 == 0;
+ if ($cmp2_2) {
+ label = 10;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_1;
+ label = 5;
+ break;
+ }
+ case 10:
+ $arrayidx4_2 = $ptr + 5 | 0;
+ $5 = HEAP8[$arrayidx4_2] | 0;
+ $cmp8_2 = $5 << 24 >> 24 == 65;
+ if ($cmp8_2) {
+ label = 11;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_1;
+ label = 5;
+ break;
+ }
+ case 11:
+ $add_ptr_2 = $ptr + 6 | 0;
+ $6 = HEAP8[$add_ptr_2] | 0;
+ $cmp2_3 = $6 << 24 >> 24 == 0;
+ if ($cmp2_3) {
+ label = 12;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_2;
+ label = 5;
+ break;
+ }
+ case 12:
+ $arrayidx4_3 = $ptr + 7 | 0;
+ $7 = HEAP8[$arrayidx4_3] | 0;
+ $cmp8_3 = $7 << 24 >> 24 == 84;
+ if ($cmp8_3) {
+ label = 13;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_2;
+ label = 5;
+ break;
+ }
+ case 13:
+ $add_ptr_3 = $ptr + 8 | 0;
+ $8 = HEAP8[$add_ptr_3] | 0;
+ $cmp2_4 = $8 << 24 >> 24 == 0;
+ if ($cmp2_4) {
+ label = 14;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_3;
+ label = 5;
+ break;
+ }
+ case 14:
+ $arrayidx4_4 = $ptr + 9 | 0;
+ $9 = HEAP8[$arrayidx4_4] | 0;
+ $cmp8_4 = $9 << 24 >> 24 == 65;
+ if ($cmp8_4) {
+ label = 15;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_3;
+ label = 5;
+ break;
+ }
+ case 15:
+ $add_ptr_4 = $ptr + 10 | 0;
+ $10 = HEAP8[$add_ptr_4] | 0;
+ $cmp2_5 = $10 << 24 >> 24 == 0;
+ if ($cmp2_5) {
+ label = 16;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_4;
+ label = 5;
+ break;
+ }
+ case 16:
+ $arrayidx4_5 = $ptr + 11 | 0;
+ $11 = HEAP8[$arrayidx4_5] | 0;
+ $cmp8_5 = $11 << 24 >> 24 == 91;
+ if ($cmp8_5) {
+ label = 17;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_4;
+ label = 5;
+ break;
+ }
+ case 17:
+ $add_ptr_5 = $ptr + 12 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr_5;
+ $retval_0 = 8;
+ label = 7;
+ break;
+ }
+ return 0;
+}
+function _big2_scanLt($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $ptr_addr_0156 = 0, $cmp78157 = 0, $type87 = 0, $4 = 0, $5 = 0, $idxprom9 = 0, $arrayidx10 = 0, $6 = 0, $conv11 = 0, $shl = 0, $7 = 0, $conv13 = 0, $shr118 = 0, $add = 0, $arrayidx14 = 0, $8 = 0, $and = 0, $shl17 = 0, $and18 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp23 = 0, $sub_ptr_lhs_cast28 = 0, $sub_ptr_rhs_cast29 = 0, $sub_ptr_sub30 = 0, $cmp31 = 0, $sub_ptr_lhs_cast36 = 0, $sub_ptr_rhs_cast37 = 0, $sub_ptr_sub38 = 0, $cmp39 = 0, $add_ptr44 = 0, $cmp45 = 0, $9 = 0, $cmp51 = 0, $arrayidx54 = 0, $10 = 0, $idxprom55 = 0, $type56 = 0, $11 = 0, $arrayidx57 = 0, $12 = 0, $conv58 = 0, $call62 = 0, $cond64 = 0, $add_ptr66 = 0, $call67 = 0, $add_ptr69 = 0, $call70 = 0, $add_ptr72 = 0, $call73 = 0, $add_ptr75 = 0, $call76 = 0, $ptr_addr_0159 = 0, $ptr_pn158 = 0, $13 = 0, $cmp82 = 0, $arrayidx85 = 0, $14 = 0, $idxprom86 = 0, $arrayidx88 = 0, $15 = 0, $conv89 = 0, $call93 = 0, $cond95 = 0, $16 = 0, $idxprom98 = 0, $arrayidx99 = 0, $17 = 0, $conv100 = 0, $shl101 = 0, $18 = 0, $conv103 = 0, $shr104117 = 0, $add105 = 0, $arrayidx106 = 0, $19 = 0, $and109 = 0, $shl110 = 0, $and111 = 0, $tobool112 = 0, $ptr_addr_0 = 0, $cmp78 = 0, $sub_ptr_lhs_cast118 = 0, $sub_ptr_rhs_cast119 = 0, $sub_ptr_sub120 = 0, $cmp121 = 0, $sub_ptr_lhs_cast126 = 0, $sub_ptr_rhs_cast127 = 0, $sub_ptr_sub128 = 0, $cmp129 = 0, $sub_ptr_lhs_cast134 = 0, $sub_ptr_rhs_cast135 = 0, $sub_ptr_sub136 = 0, $cmp137 = 0, $add_ptr142 = 0, $cmp144135 = 0, $type154 = 0, $20 = 0, $ptr_addr_1136 = 0, $21 = 0, $cmp149 = 0, $arrayidx152 = 0, $22 = 0, $idxprom153 = 0, $arrayidx155 = 0, $23 = 0, $conv156 = 0, $call160 = 0, $cond162 = 0, $24 = 0, $idxprom165 = 0, $arrayidx166 = 0, $25 = 0, $conv167 = 0, $shl168 = 0, $26 = 0, $conv170 = 0, $shr171116 = 0, $add172 = 0, $arrayidx173 = 0, $27 = 0, $and176 = 0, $shl177 = 0, $and178 = 0, $tobool179 = 0, $add_ptr183 = 0, $call214 = 0, $sub_ptr_lhs_cast185 = 0, $sub_ptr_rhs_cast186 = 0, $sub_ptr_sub187 = 0, $cmp188 = 0, $sub_ptr_lhs_cast193 = 0, $sub_ptr_rhs_cast194 = 0, $sub_ptr_sub195 = 0, $cmp196 = 0, $sub_ptr_lhs_cast201 = 0, $sub_ptr_rhs_cast202 = 0, $sub_ptr_sub203 = 0, $cmp204 = 0, $add_ptr211 = 0, $cmp144 = 0, $ptr_addr_2 = 0, $add_ptr216 = 0, $ptr_addr_3 = 0, $add_ptr218 = 0, $cmp219 = 0, $28 = 0, $cmp225 = 0, $arrayidx227 = 0, $29 = 0, $cmp229 = 0, $add_ptr233 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx4 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 16) {
+ label = 17;
+ break;
+ } else if (($cond | 0) == 15) {
+ label = 25;
+ break;
+ } else if (($cond | 0) == 17) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 7:
+ $ptr_addr_0156 = $ptr + 2 | 0;
+ $cmp78157 = ($ptr_addr_0156 | 0) == ($end | 0);
+ if ($cmp78157) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type87 = $enc + 72 | 0;
+ $4 = $type87;
+ $ptr_pn158 = $ptr;
+ $ptr_addr_0159 = $ptr_addr_0156;
+ label = 28;
+ break;
+ case 9:
+ $5 = HEAP8[$ptr] | 0;
+ $idxprom9 = $5 & 255;
+ $arrayidx10 = $idxprom9 + 9272 | 0;
+ $6 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $6 & 255;
+ $shl = $conv11 << 3;
+ $7 = HEAP8[$arrayidx3] | 0;
+ $conv13 = $7 & 255;
+ $shr118 = $conv13 >>> 5;
+ $add = $shr118 | $shl;
+ $arrayidx14 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx14 >> 2] | 0;
+ $and = $conv13 & 31;
+ $shl17 = 1 << $and;
+ $and18 = $shl17 & $8;
+ $tobool = ($and18 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp23 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp23) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast28 = $end;
+ $sub_ptr_rhs_cast29 = $ptr;
+ $sub_ptr_sub30 = $sub_ptr_lhs_cast28 - $sub_ptr_rhs_cast29 | 0;
+ $cmp31 = ($sub_ptr_sub30 | 0) < 3;
+ if ($cmp31) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast36 = $end;
+ $sub_ptr_rhs_cast37 = $ptr;
+ $sub_ptr_sub38 = $sub_ptr_lhs_cast36 - $sub_ptr_rhs_cast37 | 0;
+ $cmp39 = ($sub_ptr_sub38 | 0) < 4;
+ if ($cmp39) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 17:
+ $add_ptr44 = $ptr + 2 | 0;
+ $cmp45 = ($add_ptr44 | 0) == ($end | 0);
+ if ($cmp45) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $9 = HEAP8[$add_ptr44] | 0;
+ $cmp51 = $9 << 24 >> 24 == 0;
+ $arrayidx54 = $ptr + 3 | 0;
+ $10 = HEAP8[$arrayidx54] | 0;
+ if ($cmp51) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom55 = $10 & 255;
+ $type56 = $enc + 72 | 0;
+ $11 = $type56;
+ $arrayidx57 = $11 + $idxprom55 | 0;
+ $12 = HEAP8[$arrayidx57] | 0;
+ $conv58 = $12 & 255;
+ $cond64 = $conv58;
+ label = 21;
+ break;
+ case 20:
+ $call62 = _unicode_byte_type($9, $10) | 0;
+ $cond64 = $call62;
+ label = 21;
+ break;
+ case 21:
+ if (($cond64 | 0) == 27) {
+ label = 22;
+ break;
+ } else if (($cond64 | 0) == 20) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 22:
+ $add_ptr66 = $ptr + 4 | 0;
+ $call67 = _big2_scanComment($enc, $add_ptr66, $end, $nextTokPtr) | 0;
+ $retval_0 = $call67;
+ label = 65;
+ break;
+ case 23:
+ $add_ptr69 = $ptr + 4 | 0;
+ $call70 = _big2_scanCdataSection($add_ptr69, $end, $nextTokPtr) | 0;
+ $retval_0 = $call70;
+ label = 65;
+ break;
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr44;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 25:
+ $add_ptr72 = $ptr + 2 | 0;
+ $call73 = _big2_scanPi($enc, $add_ptr72, $end, $nextTokPtr) | 0;
+ $retval_0 = $call73;
+ label = 65;
+ break;
+ case 26:
+ $add_ptr75 = $ptr + 2 | 0;
+ $call76 = _big2_scanEndTag($enc, $add_ptr75, $end, $nextTokPtr) | 0;
+ $retval_0 = $call76;
+ label = 65;
+ break;
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 28:
+ $13 = HEAP8[$ptr_addr_0159] | 0;
+ $cmp82 = $13 << 24 >> 24 == 0;
+ $arrayidx85 = $ptr_pn158 + 3 | 0;
+ $14 = HEAP8[$arrayidx85] | 0;
+ if ($cmp82) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ $idxprom86 = $14 & 255;
+ $arrayidx88 = $4 + $idxprom86 | 0;
+ $15 = HEAP8[$arrayidx88] | 0;
+ $conv89 = $15 & 255;
+ $cond95 = $conv89;
+ label = 31;
+ break;
+ case 30:
+ $call93 = _unicode_byte_type($13, $14) | 0;
+ $cond95 = $call93;
+ label = 31;
+ break;
+ case 31:
+ if (($cond95 | 0) == 29) {
+ label = 32;
+ break;
+ } else if (($cond95 | 0) == 22 | ($cond95 | 0) == 24 | ($cond95 | 0) == 25 | ($cond95 | 0) == 26 | ($cond95 | 0) == 27) {
+ label = 33;
+ break;
+ } else if (($cond95 | 0) == 5) {
+ label = 35;
+ break;
+ } else if (($cond95 | 0) == 6) {
+ label = 37;
+ break;
+ } else if (($cond95 | 0) == 7) {
+ label = 39;
+ break;
+ } else if (($cond95 | 0) == 21 | ($cond95 | 0) == 9 | ($cond95 | 0) == 10) {
+ label = 41;
+ break;
+ } else if (($cond95 | 0) == 11) {
+ $ptr_addr_2 = $ptr_addr_0159;
+ label = 58;
+ break;
+ } else if (($cond95 | 0) == 17) {
+ $ptr_addr_3 = $ptr_addr_0159;
+ label = 59;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 32:
+ $16 = HEAP8[$ptr_addr_0159] | 0;
+ $idxprom98 = $16 & 255;
+ $arrayidx99 = $idxprom98 + 10824 | 0;
+ $17 = HEAP8[$arrayidx99] | 0;
+ $conv100 = $17 & 255;
+ $shl101 = $conv100 << 3;
+ $18 = HEAP8[$arrayidx85] | 0;
+ $conv103 = $18 & 255;
+ $shr104117 = $conv103 >>> 5;
+ $add105 = $shr104117 | $shl101;
+ $arrayidx106 = 9544 + ($add105 << 2) | 0;
+ $19 = HEAP32[$arrayidx106 >> 2] | 0;
+ $and109 = $conv103 & 31;
+ $shl110 = 1 << $and109;
+ $and111 = $shl110 & $19;
+ $tobool112 = ($and111 | 0) == 0;
+ if ($tobool112) {
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $ptr_addr_0 = $ptr_addr_0159 + 2 | 0;
+ $cmp78 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp78) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ $ptr_pn158 = $ptr_addr_0159;
+ $ptr_addr_0159 = $ptr_addr_0;
+ label = 28;
+ break;
+ }
+ case 34:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 35:
+ $sub_ptr_lhs_cast118 = $end;
+ $sub_ptr_rhs_cast119 = $ptr_addr_0159;
+ $sub_ptr_sub120 = $sub_ptr_lhs_cast118 - $sub_ptr_rhs_cast119 | 0;
+ $cmp121 = ($sub_ptr_sub120 | 0) < 2;
+ if ($cmp121) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 37:
+ $sub_ptr_lhs_cast126 = $end;
+ $sub_ptr_rhs_cast127 = $ptr_addr_0159;
+ $sub_ptr_sub128 = $sub_ptr_lhs_cast126 - $sub_ptr_rhs_cast127 | 0;
+ $cmp129 = ($sub_ptr_sub128 | 0) < 3;
+ if ($cmp129) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 39:
+ $sub_ptr_lhs_cast134 = $end;
+ $sub_ptr_rhs_cast135 = $ptr_addr_0159;
+ $sub_ptr_sub136 = $sub_ptr_lhs_cast134 - $sub_ptr_rhs_cast135 | 0;
+ $cmp137 = ($sub_ptr_sub136 | 0) < 4;
+ if ($cmp137) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 41:
+ $add_ptr142 = $ptr_pn158 + 4 | 0;
+ $cmp144135 = ($add_ptr142 | 0) == ($end | 0);
+ if ($cmp144135) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $type154 = $enc + 72 | 0;
+ $20 = $type154;
+ $ptr_addr_1136 = $add_ptr142;
+ label = 43;
+ break;
+ case 43:
+ $21 = HEAP8[$ptr_addr_1136] | 0;
+ $cmp149 = $21 << 24 >> 24 == 0;
+ $arrayidx152 = $ptr_addr_1136 + 1 | 0;
+ $22 = HEAP8[$arrayidx152] | 0;
+ if ($cmp149) {
+ label = 44;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 44:
+ $idxprom153 = $22 & 255;
+ $arrayidx155 = $20 + $idxprom153 | 0;
+ $23 = HEAP8[$arrayidx155] | 0;
+ $conv156 = $23 & 255;
+ $cond162 = $conv156;
+ label = 46;
+ break;
+ case 45:
+ $call160 = _unicode_byte_type($21, $22) | 0;
+ $cond162 = $call160;
+ label = 46;
+ break;
+ case 46:
+ if (($cond162 | 0) == 29) {
+ label = 47;
+ break;
+ } else if (($cond162 | 0) == 22 | ($cond162 | 0) == 24) {
+ label = 49;
+ break;
+ } else if (($cond162 | 0) == 5) {
+ label = 50;
+ break;
+ } else if (($cond162 | 0) == 6) {
+ label = 52;
+ break;
+ } else if (($cond162 | 0) == 7) {
+ label = 54;
+ break;
+ } else if (($cond162 | 0) == 21 | ($cond162 | 0) == 9 | ($cond162 | 0) == 10) {
+ label = 56;
+ break;
+ } else if (($cond162 | 0) == 11) {
+ $ptr_addr_2 = $ptr_addr_1136;
+ label = 58;
+ break;
+ } else if (($cond162 | 0) == 17) {
+ $ptr_addr_3 = $ptr_addr_1136;
+ label = 59;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 47:
+ $24 = HEAP8[$ptr_addr_1136] | 0;
+ $idxprom165 = $24 & 255;
+ $arrayidx166 = $idxprom165 + 9272 | 0;
+ $25 = HEAP8[$arrayidx166] | 0;
+ $conv167 = $25 & 255;
+ $shl168 = $conv167 << 3;
+ $26 = HEAP8[$arrayidx152] | 0;
+ $conv170 = $26 & 255;
+ $shr171116 = $conv170 >>> 5;
+ $add172 = $shr171116 | $shl168;
+ $arrayidx173 = 9544 + ($add172 << 2) | 0;
+ $27 = HEAP32[$arrayidx173 >> 2] | 0;
+ $and176 = $conv170 & 31;
+ $shl177 = 1 << $and176;
+ $and178 = $shl177 & $27;
+ $tobool179 = ($and178 | 0) == 0;
+ if ($tobool179) {
+ label = 48;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 48:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 49:
+ $add_ptr183 = $ptr_addr_1136 + 2 | 0;
+ $call214 = _big2_scanAtts($enc, $add_ptr183, $end, $nextTokPtr) | 0;
+ $retval_0 = $call214;
+ label = 65;
+ break;
+ case 50:
+ $sub_ptr_lhs_cast185 = $end;
+ $sub_ptr_rhs_cast186 = $ptr_addr_1136;
+ $sub_ptr_sub187 = $sub_ptr_lhs_cast185 - $sub_ptr_rhs_cast186 | 0;
+ $cmp188 = ($sub_ptr_sub187 | 0) < 2;
+ if ($cmp188) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 52:
+ $sub_ptr_lhs_cast193 = $end;
+ $sub_ptr_rhs_cast194 = $ptr_addr_1136;
+ $sub_ptr_sub195 = $sub_ptr_lhs_cast193 - $sub_ptr_rhs_cast194 | 0;
+ $cmp196 = ($sub_ptr_sub195 | 0) < 3;
+ if ($cmp196) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 54:
+ $sub_ptr_lhs_cast201 = $end;
+ $sub_ptr_rhs_cast202 = $ptr_addr_1136;
+ $sub_ptr_sub203 = $sub_ptr_lhs_cast201 - $sub_ptr_rhs_cast202 | 0;
+ $cmp204 = ($sub_ptr_sub203 | 0) < 4;
+ if ($cmp204) {
+ $retval_0 = -2;
+ label = 65;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 56:
+ $add_ptr211 = $ptr_addr_1136 + 2 | 0;
+ $cmp144 = ($add_ptr211 | 0) == ($end | 0);
+ if ($cmp144) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ $ptr_addr_1136 = $add_ptr211;
+ label = 43;
+ break;
+ }
+ case 57:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1136;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 58:
+ $add_ptr216 = $ptr_addr_2 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr216;
+ $retval_0 = 2;
+ label = 65;
+ break;
+ case 59:
+ $add_ptr218 = $ptr_addr_3 + 2 | 0;
+ $cmp219 = ($add_ptr218 | 0) == ($end | 0);
+ if ($cmp219) {
+ $retval_0 = -1;
+ label = 65;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $28 = HEAP8[$add_ptr218] | 0;
+ $cmp225 = $28 << 24 >> 24 == 0;
+ if ($cmp225) {
+ label = 61;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 61:
+ $arrayidx227 = $ptr_addr_3 + 3 | 0;
+ $29 = HEAP8[$arrayidx227] | 0;
+ $cmp229 = $29 << 24 >> 24 == 62;
+ if ($cmp229) {
+ label = 63;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 62:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr218;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 63:
+ $add_ptr233 = $ptr_addr_3 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr233;
+ $retval_0 = 4;
+ label = 65;
+ break;
+ case 64:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0159;
+ $retval_0 = 0;
+ label = 65;
+ break;
+ case 65:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanComment($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $cmp5 = 0, $add_ptr = 0, $cmp836 = 0, $type = 0, $2 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_lhs_cast25 = 0, $sub_ptr_lhs_cast34 = 0, $ptr_addr_037 = 0, $3 = 0, $cmp12 = 0, $arrayidx14 = 0, $4 = 0, $idxprom = 0, $arrayidx15 = 0, $5 = 0, $conv16 = 0, $call = 0, $cond = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp19 = 0, $add_ptr23 = 0, $sub_ptr_rhs_cast26 = 0, $sub_ptr_sub27 = 0, $cmp28 = 0, $add_ptr32 = 0, $sub_ptr_rhs_cast35 = 0, $sub_ptr_sub36 = 0, $cmp37 = 0, $add_ptr41 = 0, $add_ptr44 = 0, $cmp45 = 0, $6 = 0, $cmp51 = 0, $ptr_addr_0_be = 0, $cmp8 = 0, $arrayidx54 = 0, $7 = 0, $cmp56 = 0, $add_ptr59 = 0, $cmp60 = 0, $8 = 0, $cmp66 = 0, $arrayidx69 = 0, $9 = 0, $cmp71 = 0, $add_ptr75 = 0, $add_ptr77 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ $cmp5 = $1 << 24 >> 24 == 45;
+ if ($cmp5) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 6:
+ $add_ptr = $ptr + 2 | 0;
+ $cmp836 = ($add_ptr | 0) == ($end | 0);
+ if ($cmp836) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_lhs_cast25 = $end;
+ $sub_ptr_lhs_cast34 = $end;
+ $ptr_addr_037 = $add_ptr;
+ label = 8;
+ break;
+ case 8:
+ $3 = HEAP8[$ptr_addr_037] | 0;
+ $cmp12 = $3 << 24 >> 24 == 0;
+ $arrayidx14 = $ptr_addr_037 + 1 | 0;
+ $4 = HEAP8[$arrayidx14] | 0;
+ if ($cmp12) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $idxprom = $4 & 255;
+ $arrayidx15 = $2 + $idxprom | 0;
+ $5 = HEAP8[$arrayidx15] | 0;
+ $conv16 = $5 & 255;
+ $cond = $conv16;
+ label = 11;
+ break;
+ case 10:
+ $call = _unicode_byte_type($3, $4) | 0;
+ $cond = $call;
+ label = 11;
+ break;
+ case 11:
+ if (($cond | 0) == 5) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 14;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 16;
+ break;
+ } else if (($cond | 0) == 0 | ($cond | 0) == 1 | ($cond | 0) == 8) {
+ label = 18;
+ break;
+ } else if (($cond | 0) == 27) {
+ label = 19;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 12:
+ $sub_ptr_rhs_cast = $ptr_addr_037;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp19 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp19) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $add_ptr23 = $ptr_addr_037 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr23;
+ label = 21;
+ break;
+ case 14:
+ $sub_ptr_rhs_cast26 = $ptr_addr_037;
+ $sub_ptr_sub27 = $sub_ptr_lhs_cast25 - $sub_ptr_rhs_cast26 | 0;
+ $cmp28 = ($sub_ptr_sub27 | 0) < 3;
+ if ($cmp28) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $add_ptr32 = $ptr_addr_037 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr32;
+ label = 21;
+ break;
+ case 16:
+ $sub_ptr_rhs_cast35 = $ptr_addr_037;
+ $sub_ptr_sub36 = $sub_ptr_lhs_cast34 - $sub_ptr_rhs_cast35 | 0;
+ $cmp37 = ($sub_ptr_sub36 | 0) < 4;
+ if ($cmp37) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $add_ptr41 = $ptr_addr_037 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr41;
+ label = 21;
+ break;
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_037;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 19:
+ $add_ptr44 = $ptr_addr_037 + 2 | 0;
+ $cmp45 = ($add_ptr44 | 0) == ($end | 0);
+ if ($cmp45) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $6 = HEAP8[$add_ptr44] | 0;
+ $cmp51 = $6 << 24 >> 24 == 0;
+ if ($cmp51) {
+ label = 22;
+ break;
+ } else {
+ $ptr_addr_0_be = $add_ptr44;
+ label = 21;
+ break;
+ }
+ case 21:
+ $cmp8 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp8) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ $ptr_addr_037 = $ptr_addr_0_be;
+ label = 8;
+ break;
+ }
+ case 22:
+ $arrayidx54 = $ptr_addr_037 + 3 | 0;
+ $7 = HEAP8[$arrayidx54] | 0;
+ $cmp56 = $7 << 24 >> 24 == 45;
+ if ($cmp56) {
+ label = 23;
+ break;
+ } else {
+ $ptr_addr_0_be = $add_ptr44;
+ label = 21;
+ break;
+ }
+ case 23:
+ $add_ptr59 = $ptr_addr_037 + 4 | 0;
+ $cmp60 = ($add_ptr59 | 0) == ($end | 0);
+ if ($cmp60) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $8 = HEAP8[$add_ptr59] | 0;
+ $cmp66 = $8 << 24 >> 24 == 0;
+ if ($cmp66) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $arrayidx69 = $ptr_addr_037 + 5 | 0;
+ $9 = HEAP8[$arrayidx69] | 0;
+ $cmp71 = $9 << 24 >> 24 == 62;
+ if ($cmp71) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr59;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 27:
+ $add_ptr75 = $ptr_addr_037 + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr75;
+ $retval_0 = 13;
+ label = 29;
+ break;
+ case 28:
+ $add_ptr77 = $ptr_addr_037 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr77;
+ label = 21;
+ break;
+ case 29:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanPi($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $tok = 0, $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $ptr_addr_0111 = 0, $cmp43112 = 0, $type52 = 0, $4 = 0, $5 = 0, $idxprom9 = 0, $arrayidx10 = 0, $6 = 0, $conv11 = 0, $shl = 0, $7 = 0, $conv13 = 0, $shr91 = 0, $add = 0, $arrayidx14 = 0, $8 = 0, $and = 0, $shl17 = 0, $and18 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp23 = 0, $sub_ptr_lhs_cast28 = 0, $sub_ptr_rhs_cast29 = 0, $sub_ptr_sub30 = 0, $cmp31 = 0, $sub_ptr_lhs_cast36 = 0, $sub_ptr_rhs_cast37 = 0, $sub_ptr_sub38 = 0, $cmp39 = 0, $ptr_addr_0114 = 0, $ptr_pn113 = 0, $9 = 0, $cmp47 = 0, $arrayidx50 = 0, $10 = 0, $idxprom51 = 0, $arrayidx53 = 0, $11 = 0, $conv54 = 0, $call58 = 0, $cond60 = 0, $12 = 0, $idxprom63 = 0, $arrayidx64 = 0, $13 = 0, $conv65 = 0, $shl66 = 0, $14 = 0, $conv68 = 0, $shr6990 = 0, $add70 = 0, $arrayidx71 = 0, $15 = 0, $and74 = 0, $shl75 = 0, $and76 = 0, $tobool77 = 0, $ptr_addr_0 = 0, $cmp43 = 0, $sub_ptr_lhs_cast83 = 0, $sub_ptr_rhs_cast84 = 0, $sub_ptr_sub85 = 0, $cmp86 = 0, $sub_ptr_lhs_cast91 = 0, $sub_ptr_rhs_cast92 = 0, $sub_ptr_sub93 = 0, $cmp94 = 0, $sub_ptr_lhs_cast99 = 0, $sub_ptr_rhs_cast100 = 0, $sub_ptr_sub101 = 0, $cmp102 = 0, $call107 = 0, $tobool108 = 0, $add_ptr111 = 0, $cmp11394 = 0, $type123 = 0, $16 = 0, $sub_ptr_lhs_cast133 = 0, $sub_ptr_lhs_cast142 = 0, $sub_ptr_lhs_cast151 = 0, $ptr_addr_195 = 0, $17 = 0, $cmp118 = 0, $arrayidx121 = 0, $18 = 0, $idxprom122 = 0, $arrayidx124 = 0, $19 = 0, $conv125 = 0, $call129 = 0, $cond131 = 0, $sub_ptr_rhs_cast134 = 0, $sub_ptr_sub135 = 0, $cmp136 = 0, $add_ptr140 = 0, $sub_ptr_rhs_cast143 = 0, $sub_ptr_sub144 = 0, $cmp145 = 0, $add_ptr149 = 0, $sub_ptr_rhs_cast152 = 0, $sub_ptr_sub153 = 0, $cmp154 = 0, $add_ptr158 = 0, $add_ptr161 = 0, $cmp162 = 0, $20 = 0, $cmp168 = 0, $ptr_addr_1_be = 0, $cmp113 = 0, $arrayidx170 = 0, $21 = 0, $cmp172 = 0, $add_ptr175 = 0, $22 = 0, $add_ptr178 = 0, $call181 = 0, $tobool182 = 0, $add_ptr185 = 0, $cmp186 = 0, $23 = 0, $cmp192 = 0, $arrayidx195 = 0, $24 = 0, $cmp197 = 0, $add_ptr200 = 0, $25 = 0, $ptr_addr_2 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tok = __stackBase__ | 0;
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx4 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 7:
+ $ptr_addr_0111 = $ptr + 2 | 0;
+ $cmp43112 = ($ptr_addr_0111 | 0) == ($end | 0);
+ if ($cmp43112) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type52 = $enc + 72 | 0;
+ $4 = $type52;
+ $ptr_pn113 = $ptr;
+ $ptr_addr_0114 = $ptr_addr_0111;
+ label = 18;
+ break;
+ case 9:
+ $5 = HEAP8[$ptr] | 0;
+ $idxprom9 = $5 & 255;
+ $arrayidx10 = $idxprom9 + 9272 | 0;
+ $6 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $6 & 255;
+ $shl = $conv11 << 3;
+ $7 = HEAP8[$arrayidx3] | 0;
+ $conv13 = $7 & 255;
+ $shr91 = $conv13 >>> 5;
+ $add = $shr91 | $shl;
+ $arrayidx14 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx14 >> 2] | 0;
+ $and = $conv13 & 31;
+ $shl17 = 1 << $and;
+ $and18 = $shl17 & $8;
+ $tobool = ($and18 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp23 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp23) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast28 = $end;
+ $sub_ptr_rhs_cast29 = $ptr;
+ $sub_ptr_sub30 = $sub_ptr_lhs_cast28 - $sub_ptr_rhs_cast29 | 0;
+ $cmp31 = ($sub_ptr_sub30 | 0) < 3;
+ if ($cmp31) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast36 = $end;
+ $sub_ptr_rhs_cast37 = $ptr;
+ $sub_ptr_sub38 = $sub_ptr_lhs_cast36 - $sub_ptr_rhs_cast37 | 0;
+ $cmp39 = ($sub_ptr_sub38 | 0) < 4;
+ if ($cmp39) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 18:
+ $9 = HEAP8[$ptr_addr_0114] | 0;
+ $cmp47 = $9 << 24 >> 24 == 0;
+ $arrayidx50 = $ptr_pn113 + 3 | 0;
+ $10 = HEAP8[$arrayidx50] | 0;
+ if ($cmp47) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom51 = $10 & 255;
+ $arrayidx53 = $4 + $idxprom51 | 0;
+ $11 = HEAP8[$arrayidx53] | 0;
+ $conv54 = $11 & 255;
+ $cond60 = $conv54;
+ label = 21;
+ break;
+ case 20:
+ $call58 = _unicode_byte_type($9, $10) | 0;
+ $cond60 = $call58;
+ label = 21;
+ break;
+ case 21:
+ if (($cond60 | 0) == 29) {
+ label = 22;
+ break;
+ } else if (($cond60 | 0) == 22 | ($cond60 | 0) == 24 | ($cond60 | 0) == 25 | ($cond60 | 0) == 26 | ($cond60 | 0) == 27) {
+ label = 23;
+ break;
+ } else if (($cond60 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($cond60 | 0) == 6) {
+ label = 27;
+ break;
+ } else if (($cond60 | 0) == 7) {
+ label = 29;
+ break;
+ } else if (($cond60 | 0) == 21 | ($cond60 | 0) == 9 | ($cond60 | 0) == 10) {
+ label = 31;
+ break;
+ } else if (($cond60 | 0) == 15) {
+ label = 52;
+ break;
+ } else {
+ $ptr_addr_2 = $ptr_addr_0114;
+ label = 58;
+ break;
+ }
+ case 22:
+ $12 = HEAP8[$ptr_addr_0114] | 0;
+ $idxprom63 = $12 & 255;
+ $arrayidx64 = $idxprom63 + 10824 | 0;
+ $13 = HEAP8[$arrayidx64] | 0;
+ $conv65 = $13 & 255;
+ $shl66 = $conv65 << 3;
+ $14 = HEAP8[$arrayidx50] | 0;
+ $conv68 = $14 & 255;
+ $shr6990 = $conv68 >>> 5;
+ $add70 = $shr6990 | $shl66;
+ $arrayidx71 = 9544 + ($add70 << 2) | 0;
+ $15 = HEAP32[$arrayidx71 >> 2] | 0;
+ $and74 = $conv68 & 31;
+ $shl75 = 1 << $and74;
+ $and76 = $shl75 & $15;
+ $tobool77 = ($and76 | 0) == 0;
+ if ($tobool77) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $ptr_addr_0 = $ptr_addr_0114 + 2 | 0;
+ $cmp43 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp43) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ $ptr_pn113 = $ptr_addr_0114;
+ $ptr_addr_0114 = $ptr_addr_0;
+ label = 18;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast83 = $end;
+ $sub_ptr_rhs_cast84 = $ptr_addr_0114;
+ $sub_ptr_sub85 = $sub_ptr_lhs_cast83 - $sub_ptr_rhs_cast84 | 0;
+ $cmp86 = ($sub_ptr_sub85 | 0) < 2;
+ if ($cmp86) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast91 = $end;
+ $sub_ptr_rhs_cast92 = $ptr_addr_0114;
+ $sub_ptr_sub93 = $sub_ptr_lhs_cast91 - $sub_ptr_rhs_cast92 | 0;
+ $cmp94 = ($sub_ptr_sub93 | 0) < 3;
+ if ($cmp94) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 29:
+ $sub_ptr_lhs_cast99 = $end;
+ $sub_ptr_rhs_cast100 = $ptr_addr_0114;
+ $sub_ptr_sub101 = $sub_ptr_lhs_cast99 - $sub_ptr_rhs_cast100 | 0;
+ $cmp102 = ($sub_ptr_sub101 | 0) < 4;
+ if ($cmp102) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 31:
+ $call107 = _big2_checkPiTarget($ptr, $ptr_addr_0114, $tok) | 0;
+ $tobool108 = ($call107 | 0) == 0;
+ if ($tobool108) {
+ label = 32;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 32:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 33:
+ $add_ptr111 = $ptr_pn113 + 4 | 0;
+ $cmp11394 = ($add_ptr111 | 0) == ($end | 0);
+ if ($cmp11394) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $type123 = $enc + 72 | 0;
+ $16 = $type123;
+ $sub_ptr_lhs_cast133 = $end;
+ $sub_ptr_lhs_cast142 = $end;
+ $sub_ptr_lhs_cast151 = $end;
+ $ptr_addr_195 = $add_ptr111;
+ label = 35;
+ break;
+ case 35:
+ $17 = HEAP8[$ptr_addr_195] | 0;
+ $cmp118 = $17 << 24 >> 24 == 0;
+ $arrayidx121 = $ptr_addr_195 + 1 | 0;
+ $18 = HEAP8[$arrayidx121] | 0;
+ if ($cmp118) {
+ label = 36;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 36:
+ $idxprom122 = $18 & 255;
+ $arrayidx124 = $16 + $idxprom122 | 0;
+ $19 = HEAP8[$arrayidx124] | 0;
+ $conv125 = $19 & 255;
+ $cond131 = $conv125;
+ label = 38;
+ break;
+ case 37:
+ $call129 = _unicode_byte_type($17, $18) | 0;
+ $cond131 = $call129;
+ label = 38;
+ break;
+ case 38:
+ if (($cond131 | 0) == 5) {
+ label = 39;
+ break;
+ } else if (($cond131 | 0) == 6) {
+ label = 41;
+ break;
+ } else if (($cond131 | 0) == 7) {
+ label = 43;
+ break;
+ } else if (($cond131 | 0) == 0 | ($cond131 | 0) == 1 | ($cond131 | 0) == 8) {
+ label = 45;
+ break;
+ } else if (($cond131 | 0) == 15) {
+ label = 46;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 39:
+ $sub_ptr_rhs_cast134 = $ptr_addr_195;
+ $sub_ptr_sub135 = $sub_ptr_lhs_cast133 - $sub_ptr_rhs_cast134 | 0;
+ $cmp136 = ($sub_ptr_sub135 | 0) < 2;
+ if ($cmp136) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $add_ptr140 = $ptr_addr_195 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr140;
+ label = 48;
+ break;
+ case 41:
+ $sub_ptr_rhs_cast143 = $ptr_addr_195;
+ $sub_ptr_sub144 = $sub_ptr_lhs_cast142 - $sub_ptr_rhs_cast143 | 0;
+ $cmp145 = ($sub_ptr_sub144 | 0) < 3;
+ if ($cmp145) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $add_ptr149 = $ptr_addr_195 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr149;
+ label = 48;
+ break;
+ case 43:
+ $sub_ptr_rhs_cast152 = $ptr_addr_195;
+ $sub_ptr_sub153 = $sub_ptr_lhs_cast151 - $sub_ptr_rhs_cast152 | 0;
+ $cmp154 = ($sub_ptr_sub153 | 0) < 4;
+ if ($cmp154) {
+ $retval_0 = -2;
+ label = 59;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $add_ptr158 = $ptr_addr_195 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr158;
+ label = 48;
+ break;
+ case 45:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_195;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 46:
+ $add_ptr161 = $ptr_addr_195 + 2 | 0;
+ $cmp162 = ($add_ptr161 | 0) == ($end | 0);
+ if ($cmp162) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $20 = HEAP8[$add_ptr161] | 0;
+ $cmp168 = $20 << 24 >> 24 == 0;
+ if ($cmp168) {
+ label = 49;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr161;
+ label = 48;
+ break;
+ }
+ case 48:
+ $cmp113 = ($ptr_addr_1_be | 0) == ($end | 0);
+ if ($cmp113) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ $ptr_addr_195 = $ptr_addr_1_be;
+ label = 35;
+ break;
+ }
+ case 49:
+ $arrayidx170 = $ptr_addr_195 + 3 | 0;
+ $21 = HEAP8[$arrayidx170] | 0;
+ $cmp172 = $21 << 24 >> 24 == 62;
+ if ($cmp172) {
+ label = 50;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr161;
+ label = 48;
+ break;
+ }
+ case 50:
+ $add_ptr175 = $ptr_addr_195 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr175;
+ $22 = HEAP32[$tok >> 2] | 0;
+ $retval_0 = $22;
+ label = 59;
+ break;
+ case 51:
+ $add_ptr178 = $ptr_addr_195 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr178;
+ label = 48;
+ break;
+ case 52:
+ $call181 = _big2_checkPiTarget($ptr, $ptr_addr_0114, $tok) | 0;
+ $tobool182 = ($call181 | 0) == 0;
+ if ($tobool182) {
+ label = 53;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 53:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0114;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 54:
+ $add_ptr185 = $ptr_pn113 + 4 | 0;
+ $cmp186 = ($add_ptr185 | 0) == ($end | 0);
+ if ($cmp186) {
+ $retval_0 = -1;
+ label = 59;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ $23 = HEAP8[$add_ptr185] | 0;
+ $cmp192 = $23 << 24 >> 24 == 0;
+ if ($cmp192) {
+ label = 56;
+ break;
+ } else {
+ $ptr_addr_2 = $add_ptr185;
+ label = 58;
+ break;
+ }
+ case 56:
+ $arrayidx195 = $ptr_pn113 + 5 | 0;
+ $24 = HEAP8[$arrayidx195] | 0;
+ $cmp197 = $24 << 24 >> 24 == 62;
+ if ($cmp197) {
+ label = 57;
+ break;
+ } else {
+ $ptr_addr_2 = $add_ptr185;
+ label = 58;
+ break;
+ }
+ case 57:
+ $add_ptr200 = $ptr_pn113 + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr200;
+ $25 = HEAP32[$tok >> 2] | 0;
+ $retval_0 = $25;
+ label = 59;
+ break;
+ case 58:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_2;
+ $retval_0 = 0;
+ label = 59;
+ break;
+ case 59:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanEndTag($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $ptr_addr_084 = 0, $cmp4385 = 0, $type52 = 0, $4 = 0, $5 = 0, $idxprom9 = 0, $arrayidx10 = 0, $6 = 0, $conv11 = 0, $shl = 0, $7 = 0, $conv13 = 0, $shr64 = 0, $add = 0, $arrayidx14 = 0, $8 = 0, $and = 0, $shl17 = 0, $and18 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp23 = 0, $sub_ptr_lhs_cast28 = 0, $sub_ptr_rhs_cast29 = 0, $sub_ptr_sub30 = 0, $cmp31 = 0, $sub_ptr_lhs_cast36 = 0, $sub_ptr_rhs_cast37 = 0, $sub_ptr_sub38 = 0, $cmp39 = 0, $ptr_addr_087 = 0, $ptr_pn86 = 0, $9 = 0, $cmp47 = 0, $arrayidx50 = 0, $10 = 0, $idxprom51 = 0, $arrayidx53 = 0, $11 = 0, $conv54 = 0, $call58 = 0, $cond60 = 0, $12 = 0, $idxprom63 = 0, $arrayidx64 = 0, $13 = 0, $conv65 = 0, $shl66 = 0, $14 = 0, $conv68 = 0, $shr6963 = 0, $add70 = 0, $arrayidx71 = 0, $15 = 0, $and74 = 0, $shl75 = 0, $and76 = 0, $tobool77 = 0, $ptr_addr_0 = 0, $cmp43 = 0, $sub_ptr_lhs_cast83 = 0, $sub_ptr_rhs_cast84 = 0, $sub_ptr_sub85 = 0, $cmp86 = 0, $sub_ptr_lhs_cast91 = 0, $sub_ptr_rhs_cast92 = 0, $sub_ptr_sub93 = 0, $cmp94 = 0, $sub_ptr_lhs_cast99 = 0, $sub_ptr_rhs_cast100 = 0, $sub_ptr_sub101 = 0, $cmp102 = 0, $add_ptr107 = 0, $cmp10867 = 0, $type117 = 0, $16 = 0, $ptr_addr_168 = 0, $17 = 0, $cmp112 = 0, $arrayidx115 = 0, $18 = 0, $idxprom116 = 0, $arrayidx118 = 0, $19 = 0, $conv119 = 0, $call123 = 0, $cond125 = 0, $add_ptr128 = 0, $add_ptr131 = 0, $cmp108 = 0, $add_ptr133 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx4 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 7:
+ $ptr_addr_084 = $ptr + 2 | 0;
+ $cmp4385 = ($ptr_addr_084 | 0) == ($end | 0);
+ if ($cmp4385) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type52 = $enc + 72 | 0;
+ $4 = $type52;
+ $ptr_pn86 = $ptr;
+ $ptr_addr_087 = $ptr_addr_084;
+ label = 18;
+ break;
+ case 9:
+ $5 = HEAP8[$ptr] | 0;
+ $idxprom9 = $5 & 255;
+ $arrayidx10 = $idxprom9 + 9272 | 0;
+ $6 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $6 & 255;
+ $shl = $conv11 << 3;
+ $7 = HEAP8[$arrayidx3] | 0;
+ $conv13 = $7 & 255;
+ $shr64 = $conv13 >>> 5;
+ $add = $shr64 | $shl;
+ $arrayidx14 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx14 >> 2] | 0;
+ $and = $conv13 & 31;
+ $shl17 = 1 << $and;
+ $and18 = $shl17 & $8;
+ $tobool = ($and18 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp23 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp23) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast28 = $end;
+ $sub_ptr_rhs_cast29 = $ptr;
+ $sub_ptr_sub30 = $sub_ptr_lhs_cast28 - $sub_ptr_rhs_cast29 | 0;
+ $cmp31 = ($sub_ptr_sub30 | 0) < 3;
+ if ($cmp31) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast36 = $end;
+ $sub_ptr_rhs_cast37 = $ptr;
+ $sub_ptr_sub38 = $sub_ptr_lhs_cast36 - $sub_ptr_rhs_cast37 | 0;
+ $cmp39 = ($sub_ptr_sub38 | 0) < 4;
+ if ($cmp39) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 18:
+ $9 = HEAP8[$ptr_addr_087] | 0;
+ $cmp47 = $9 << 24 >> 24 == 0;
+ $arrayidx50 = $ptr_pn86 + 3 | 0;
+ $10 = HEAP8[$arrayidx50] | 0;
+ if ($cmp47) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom51 = $10 & 255;
+ $arrayidx53 = $4 + $idxprom51 | 0;
+ $11 = HEAP8[$arrayidx53] | 0;
+ $conv54 = $11 & 255;
+ $cond60 = $conv54;
+ label = 21;
+ break;
+ case 20:
+ $call58 = _unicode_byte_type($9, $10) | 0;
+ $cond60 = $call58;
+ label = 21;
+ break;
+ case 21:
+ if (($cond60 | 0) == 29) {
+ label = 22;
+ break;
+ } else if (($cond60 | 0) == 22 | ($cond60 | 0) == 24 | ($cond60 | 0) == 25 | ($cond60 | 0) == 26 | ($cond60 | 0) == 27) {
+ label = 23;
+ break;
+ } else if (($cond60 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($cond60 | 0) == 6) {
+ label = 27;
+ break;
+ } else if (($cond60 | 0) == 7) {
+ label = 29;
+ break;
+ } else if (($cond60 | 0) == 21 | ($cond60 | 0) == 9 | ($cond60 | 0) == 10) {
+ label = 31;
+ break;
+ } else if (($cond60 | 0) == 11) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 22:
+ $12 = HEAP8[$ptr_addr_087] | 0;
+ $idxprom63 = $12 & 255;
+ $arrayidx64 = $idxprom63 + 10824 | 0;
+ $13 = HEAP8[$arrayidx64] | 0;
+ $conv65 = $13 & 255;
+ $shl66 = $conv65 << 3;
+ $14 = HEAP8[$arrayidx50] | 0;
+ $conv68 = $14 & 255;
+ $shr6963 = $conv68 >>> 5;
+ $add70 = $shr6963 | $shl66;
+ $arrayidx71 = 9544 + ($add70 << 2) | 0;
+ $15 = HEAP32[$arrayidx71 >> 2] | 0;
+ $and74 = $conv68 & 31;
+ $shl75 = 1 << $and74;
+ $and76 = $shl75 & $15;
+ $tobool77 = ($and76 | 0) == 0;
+ if ($tobool77) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $ptr_addr_0 = $ptr_addr_087 + 2 | 0;
+ $cmp43 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp43) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ $ptr_pn86 = $ptr_addr_087;
+ $ptr_addr_087 = $ptr_addr_0;
+ label = 18;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast83 = $end;
+ $sub_ptr_rhs_cast84 = $ptr_addr_087;
+ $sub_ptr_sub85 = $sub_ptr_lhs_cast83 - $sub_ptr_rhs_cast84 | 0;
+ $cmp86 = ($sub_ptr_sub85 | 0) < 2;
+ if ($cmp86) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast91 = $end;
+ $sub_ptr_rhs_cast92 = $ptr_addr_087;
+ $sub_ptr_sub93 = $sub_ptr_lhs_cast91 - $sub_ptr_rhs_cast92 | 0;
+ $cmp94 = ($sub_ptr_sub93 | 0) < 3;
+ if ($cmp94) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 29:
+ $sub_ptr_lhs_cast99 = $end;
+ $sub_ptr_rhs_cast100 = $ptr_addr_087;
+ $sub_ptr_sub101 = $sub_ptr_lhs_cast99 - $sub_ptr_rhs_cast100 | 0;
+ $cmp102 = ($sub_ptr_sub101 | 0) < 4;
+ if ($cmp102) {
+ $retval_0 = -2;
+ label = 42;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 31:
+ $add_ptr107 = $ptr_pn86 + 4 | 0;
+ $cmp10867 = ($add_ptr107 | 0) == ($end | 0);
+ if ($cmp10867) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $type117 = $enc + 72 | 0;
+ $16 = $type117;
+ $ptr_addr_168 = $add_ptr107;
+ label = 33;
+ break;
+ case 33:
+ $17 = HEAP8[$ptr_addr_168] | 0;
+ $cmp112 = $17 << 24 >> 24 == 0;
+ $arrayidx115 = $ptr_addr_168 + 1 | 0;
+ $18 = HEAP8[$arrayidx115] | 0;
+ if ($cmp112) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ $idxprom116 = $18 & 255;
+ $arrayidx118 = $16 + $idxprom116 | 0;
+ $19 = HEAP8[$arrayidx118] | 0;
+ $conv119 = $19 & 255;
+ $cond125 = $conv119;
+ label = 36;
+ break;
+ case 35:
+ $call123 = _unicode_byte_type($17, $18) | 0;
+ $cond125 = $call123;
+ label = 36;
+ break;
+ case 36:
+ if (($cond125 | 0) == 11) {
+ label = 37;
+ break;
+ } else if (($cond125 | 0) == 21 | ($cond125 | 0) == 9 | ($cond125 | 0) == 10) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ $add_ptr128 = $ptr_addr_168 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr128;
+ $retval_0 = 5;
+ label = 42;
+ break;
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_168;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 39:
+ $add_ptr131 = $ptr_addr_168 + 2 | 0;
+ $cmp108 = ($add_ptr131 | 0) == ($end | 0);
+ if ($cmp108) {
+ $retval_0 = -1;
+ label = 42;
+ break;
+ } else {
+ $ptr_addr_168 = $add_ptr131;
+ label = 33;
+ break;
+ }
+ case 40:
+ $add_ptr133 = $ptr_pn86 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr133;
+ $retval_0 = 5;
+ label = 42;
+ break;
+ case 41:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_087;
+ $retval_0 = 0;
+ label = 42;
+ break;
+ case 42:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_checkPiTarget($ptr, $end, $tokPtr) {
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $tokPtr = $tokPtr | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $conv4 = 0, $upper_0 = 0, $add_ptr = 0, $2 = 0, $cmp8 = 0, $arrayidx11 = 0, $3 = 0, $conv12 = 0, $upper_1 = 0, $add_ptr20 = 0, $4 = 0, $cmp23 = 0, $arrayidx26 = 0, $5 = 0, $conv27 = 0, $tobool = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[$tokPtr >> 2] = 11;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp = ($sub_ptr_sub | 0) == 6;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 4:
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ $conv4 = $1 << 24 >> 24;
+ if (($conv4 | 0) == 88) {
+ label = 5;
+ break;
+ } else if (($conv4 | 0) == 120) {
+ $upper_0 = 0;
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 5:
+ $upper_0 = 1;
+ label = 6;
+ break;
+ case 6:
+ $add_ptr = $ptr + 2 | 0;
+ $2 = HEAP8[$add_ptr] | 0;
+ $cmp8 = $2 << 24 >> 24 == 0;
+ if ($cmp8) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 7:
+ $arrayidx11 = $ptr + 3 | 0;
+ $3 = HEAP8[$arrayidx11] | 0;
+ $conv12 = $3 << 24 >> 24;
+ if (($conv12 | 0) == 77) {
+ label = 8;
+ break;
+ } else if (($conv12 | 0) == 109) {
+ $upper_1 = $upper_0;
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 8:
+ $upper_1 = 1;
+ label = 9;
+ break;
+ case 9:
+ $add_ptr20 = $ptr + 4 | 0;
+ $4 = HEAP8[$add_ptr20] | 0;
+ $cmp23 = $4 << 24 >> 24 == 0;
+ if ($cmp23) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 10:
+ $arrayidx26 = $ptr + 5 | 0;
+ $5 = HEAP8[$arrayidx26] | 0;
+ $conv27 = $5 << 24 >> 24;
+ if (($conv27 | 0) == 76) {
+ label = 11;
+ break;
+ } else if (($conv27 | 0) == 108) {
+ label = 12;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 14;
+ break;
+ }
+ case 11:
+ $retval_0 = 0;
+ label = 14;
+ break;
+ case 12:
+ $tobool = ($upper_1 | 0) == 0;
+ if ($tobool) {
+ label = 13;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 14;
+ break;
+ }
+ case 13:
+ HEAP32[$tokPtr >> 2] = 12;
+ $retval_0 = 1;
+ label = 14;
+ break;
+ case 14:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanAtts($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $ptr_addr = 0, $cmp68 = 0, $type = 0, $0 = 0, $type54 = 0, $1 = 0, $type82 = 0, $2 = 0, $type115 = 0, $3 = 0, $sub_ptr_lhs_cast129 = 0, $sub_ptr_lhs_cast138 = 0, $sub_ptr_lhs_cast147 = 0, $type184 = 0, $4 = 0, $type211 = 0, $5 = 0, $6 = 0, $7 = 0, $cmp1 = 0, $arrayidx3 = 0, $8 = 0, $idxprom = 0, $arrayidx4 = 0, $9 = 0, $conv5 = 0, $call = 0, $cond = 0, $10 = 0, $add_ptr4250 = 0, $cmp4351 = 0, $11 = 0, $12 = 0, $idxprom9 = 0, $arrayidx10 = 0, $13 = 0, $conv11 = 0, $shl = 0, $arrayidx12 = 0, $14 = 0, $conv13 = 0, $shr49 = 0, $add = 0, $arrayidx14 = 0, $15 = 0, $and = 0, $shl17 = 0, $and18 = 0, $tobool = 0, $16 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp21 = 0, $17 = 0, $sub_ptr_lhs_cast26 = 0, $sub_ptr_rhs_cast27 = 0, $sub_ptr_sub28 = 0, $cmp29 = 0, $18 = 0, $sub_ptr_lhs_cast34 = 0, $sub_ptr_rhs_cast35 = 0, $sub_ptr_sub36 = 0, $cmp37 = 0, $add_ptr4252 = 0, $19 = 0, $20 = 0, $cmp49 = 0, $arrayidx52 = 0, $21 = 0, $idxprom53 = 0, $arrayidx55 = 0, $22 = 0, $conv56 = 0, $call60 = 0, $cond62 = 0, $23 = 0, $add_ptr42 = 0, $cmp43 = 0, $24 = 0, $25 = 0, $add_ptr7055 = 0, $cmp7156 = 0, $add_ptr7057 = 0, $26 = 0, $27 = 0, $cmp77 = 0, $arrayidx80 = 0, $28 = 0, $idxprom81 = 0, $arrayidx83 = 0, $29 = 0, $conv84 = 0, $call88 = 0, $cond90 = 0, $cond90_off = 0, $30 = 0, $31 = 0, $add_ptr70 = 0, $cmp71 = 0, $32 = 0, $33 = 0, $add_ptr101 = 0, $cmp10459 = 0, $34 = 0, $35 = 0, $cmp110 = 0, $arrayidx113 = 0, $36 = 0, $idxprom114 = 0, $arrayidx116 = 0, $37 = 0, $conv117 = 0, $call121 = 0, $cond123 = 0, $cmp124 = 0, $38 = 0, $sub_ptr_rhs_cast130 = 0, $sub_ptr_sub131 = 0, $cmp132 = 0, $add_ptr136 = 0, $39 = 0, $sub_ptr_rhs_cast139 = 0, $sub_ptr_sub140 = 0, $cmp141 = 0, $add_ptr145 = 0, $40 = 0, $sub_ptr_rhs_cast148 = 0, $sub_ptr_sub149 = 0, $cmp150 = 0, $add_ptr154 = 0, $41 = 0, $42 = 0, $add_ptr157 = 0, $call158 = 0, $cmp159 = 0, $43 = 0, $cmp104 = 0, $cmp162 = 0, $44 = 0, $45 = 0, $46 = 0, $add_ptr169 = 0, $47 = 0, $add_ptr172 = 0, $cmp173 = 0, $48 = 0, $cmp179 = 0, $arrayidx182 = 0, $49 = 0, $idxprom183 = 0, $arrayidx185 = 0, $50 = 0, $conv186 = 0, $call190 = 0, $cond192 = 0, $51 = 0, $add_ptr19961 = 0, $cmp20062 = 0, $52 = 0, $add_ptr19963 = 0, $53 = 0, $54 = 0, $cmp206 = 0, $arrayidx209 = 0, $55 = 0, $idxprom210 = 0, $arrayidx212 = 0, $56 = 0, $conv213 = 0, $call217 = 0, $cond219 = 0, $57 = 0, $add_ptr199 = 0, $cmp200 = 0, $58 = 0, $59 = 0, $idxprom222 = 0, $arrayidx223 = 0, $60 = 0, $conv224 = 0, $shl225 = 0, $arrayidx226 = 0, $61 = 0, $conv227 = 0, $shr22848 = 0, $add229 = 0, $arrayidx230 = 0, $62 = 0, $and233 = 0, $shl234 = 0, $and235 = 0, $tobool236 = 0, $_pn = 0, $storemerge = 0, $cmp = 0, $63 = 0, $sub_ptr_lhs_cast242 = 0, $sub_ptr_rhs_cast243 = 0, $sub_ptr_sub244 = 0, $cmp245 = 0, $64 = 0, $sub_ptr_lhs_cast250 = 0, $sub_ptr_rhs_cast251 = 0, $sub_ptr_sub252 = 0, $cmp253 = 0, $65 = 0, $sub_ptr_lhs_cast258 = 0, $sub_ptr_rhs_cast259 = 0, $sub_ptr_sub260 = 0, $cmp261 = 0, $66 = 0, $add_ptr267 = 0, $67 = 0, $add_ptr269 = 0, $cmp270 = 0, $68 = 0, $cmp276 = 0, $arrayidx278 = 0, $69 = 0, $cmp280 = 0, $70 = 0, $add_ptr284 = 0, $71 = 0, $72 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr_addr = __stackBase__ | 0;
+ HEAP32[$ptr_addr >> 2] = $ptr;
+ $cmp68 = ($ptr | 0) == ($end | 0);
+ if ($cmp68) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $type54 = $enc + 72 | 0;
+ $1 = $type54;
+ $type82 = $enc + 72 | 0;
+ $2 = $type82;
+ $type115 = $enc + 72 | 0;
+ $3 = $type115;
+ $sub_ptr_lhs_cast129 = $end;
+ $sub_ptr_lhs_cast138 = $end;
+ $sub_ptr_lhs_cast147 = $end;
+ $type184 = $enc + 72 | 0;
+ $4 = $type184;
+ $type211 = $enc + 72 | 0;
+ $5 = $type211;
+ $6 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $7 = HEAP8[$6] | 0;
+ $cmp1 = $7 << 24 >> 24 == 0;
+ $arrayidx3 = $6 + 1 | 0;
+ $8 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $idxprom = $8 & 255;
+ $arrayidx4 = $0 + $idxprom | 0;
+ $9 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $9 & 255;
+ $cond = $conv5;
+ label = 7;
+ break;
+ case 6:
+ $call = _unicode_byte_type($7, $8) | 0;
+ $cond = $call;
+ label = 7;
+ break;
+ case 7:
+ if (($cond | 0) == 21 | ($cond | 0) == 9 | ($cond | 0) == 10) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else if (($cond | 0) == 14) {
+ label = 23;
+ break;
+ } else if (($cond | 0) == 22 | ($cond | 0) == 24 | ($cond | 0) == 25 | ($cond | 0) == 26 | ($cond | 0) == 27) {
+ label = 64;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 8:
+ $10 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr4250 = $10 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr4250;
+ $cmp4351 = ($add_ptr4250 | 0) == ($end | 0);
+ if ($cmp4351) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $19 = $10;
+ $add_ptr4252 = $add_ptr4250;
+ label = 17;
+ break;
+ }
+ case 9:
+ $11 = HEAP32[$ptr_addr >> 2] | 0;
+ $12 = HEAP8[$11] | 0;
+ $idxprom9 = $12 & 255;
+ $arrayidx10 = $idxprom9 + 10824 | 0;
+ $13 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $13 & 255;
+ $shl = $conv11 << 3;
+ $arrayidx12 = $11 + 1 | 0;
+ $14 = HEAP8[$arrayidx12] | 0;
+ $conv13 = $14 & 255;
+ $shr49 = $conv13 >>> 5;
+ $add = $shr49 | $shl;
+ $arrayidx14 = 9544 + ($add << 2) | 0;
+ $15 = HEAP32[$arrayidx14 >> 2] | 0;
+ $and = $conv13 & 31;
+ $shl17 = 1 << $and;
+ $and18 = $shl17 & $15;
+ $tobool = ($and18 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $11;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 11:
+ $16 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $16;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp21 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp21) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $16;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 13:
+ $17 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast26 = $end;
+ $sub_ptr_rhs_cast27 = $17;
+ $sub_ptr_sub28 = $sub_ptr_lhs_cast26 - $sub_ptr_rhs_cast27 | 0;
+ $cmp29 = ($sub_ptr_sub28 | 0) < 3;
+ if ($cmp29) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $17;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 15:
+ $18 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast34 = $end;
+ $sub_ptr_rhs_cast35 = $18;
+ $sub_ptr_sub36 = $sub_ptr_lhs_cast34 - $sub_ptr_rhs_cast35 | 0;
+ $cmp37 = ($sub_ptr_sub36 | 0) < 4;
+ if ($cmp37) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $18;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 17:
+ $20 = HEAP8[$add_ptr4252] | 0;
+ $cmp49 = $20 << 24 >> 24 == 0;
+ $arrayidx52 = $19 + 3 | 0;
+ $21 = HEAP8[$arrayidx52] | 0;
+ if ($cmp49) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $idxprom53 = $21 & 255;
+ $arrayidx55 = $1 + $idxprom53 | 0;
+ $22 = HEAP8[$arrayidx55] | 0;
+ $conv56 = $22 & 255;
+ $cond62 = $conv56;
+ label = 20;
+ break;
+ case 19:
+ $call60 = _unicode_byte_type($20, $21) | 0;
+ $cond62 = $call60;
+ label = 20;
+ break;
+ case 20:
+ if (($cond62 | 0) == 21 | ($cond62 | 0) == 10 | ($cond62 | 0) == 9) {
+ label = 21;
+ break;
+ } else if (($cond62 | 0) == 14) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $23 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr42 = $23 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr42;
+ $cmp43 = ($add_ptr42 | 0) == ($end | 0);
+ if ($cmp43) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $19 = $23;
+ $add_ptr4252 = $add_ptr42;
+ label = 17;
+ break;
+ }
+ case 22:
+ $24 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $24;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 23:
+ $25 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr7055 = $25 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr7055;
+ $cmp7156 = ($add_ptr7055 | 0) == ($end | 0);
+ if ($cmp7156) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $26 = $25;
+ $add_ptr7057 = $add_ptr7055;
+ label = 24;
+ break;
+ }
+ case 24:
+ $27 = HEAP8[$add_ptr7057] | 0;
+ $cmp77 = $27 << 24 >> 24 == 0;
+ $arrayidx80 = $26 + 3 | 0;
+ $28 = HEAP8[$arrayidx80] | 0;
+ if ($cmp77) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ $idxprom81 = $28 & 255;
+ $arrayidx83 = $2 + $idxprom81 | 0;
+ $29 = HEAP8[$arrayidx83] | 0;
+ $conv84 = $29 & 255;
+ $cond90 = $conv84;
+ label = 27;
+ break;
+ case 26:
+ $call88 = _unicode_byte_type($27, $28) | 0;
+ $cond90 = $call88;
+ label = 27;
+ break;
+ case 27:
+ $cond90_off = $cond90 - 12 | 0;
+ $30 = $cond90_off >>> 0 < 2;
+ if ($30) {
+ label = 31;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ if (($cond90 | 0) == 21 | ($cond90 | 0) == 10 | ($cond90 | 0) == 9) {
+ label = 29;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 29:
+ $31 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr70 = $31 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr70;
+ $cmp71 = ($add_ptr70 | 0) == ($end | 0);
+ if ($cmp71) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $26 = $31;
+ $add_ptr7057 = $add_ptr70;
+ label = 24;
+ break;
+ }
+ case 30:
+ $32 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $32;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 31:
+ $33 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr101 = $33 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr101;
+ $cmp10459 = ($add_ptr101 | 0) == ($end | 0);
+ if ($cmp10459) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $34 = $add_ptr101;
+ label = 32;
+ break;
+ }
+ case 32:
+ $35 = HEAP8[$34] | 0;
+ $cmp110 = $35 << 24 >> 24 == 0;
+ $arrayidx113 = $34 + 1 | 0;
+ $36 = HEAP8[$arrayidx113] | 0;
+ if ($cmp110) {
+ label = 33;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 33:
+ $idxprom114 = $36 & 255;
+ $arrayidx116 = $3 + $idxprom114 | 0;
+ $37 = HEAP8[$arrayidx116] | 0;
+ $conv117 = $37 & 255;
+ $cond123 = $conv117;
+ label = 35;
+ break;
+ case 34:
+ $call121 = _unicode_byte_type($35, $36) | 0;
+ $cond123 = $call121;
+ label = 35;
+ break;
+ case 35:
+ $cmp124 = ($cond123 | 0) == ($cond90 | 0);
+ if ($cmp124) {
+ label = 50;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ if (($cond123 | 0) == 5) {
+ label = 37;
+ break;
+ } else if (($cond123 | 0) == 6) {
+ label = 39;
+ break;
+ } else if (($cond123 | 0) == 7) {
+ label = 41;
+ break;
+ } else if (($cond123 | 0) == 0 | ($cond123 | 0) == 1 | ($cond123 | 0) == 8) {
+ label = 43;
+ break;
+ } else if (($cond123 | 0) == 3) {
+ label = 44;
+ break;
+ } else if (($cond123 | 0) == 2) {
+ label = 48;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 37:
+ $38 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_rhs_cast130 = $38;
+ $sub_ptr_sub131 = $sub_ptr_lhs_cast129 - $sub_ptr_rhs_cast130 | 0;
+ $cmp132 = ($sub_ptr_sub131 | 0) < 2;
+ if ($cmp132) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $add_ptr136 = $38 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr136;
+ label = 45;
+ break;
+ case 39:
+ $39 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_rhs_cast139 = $39;
+ $sub_ptr_sub140 = $sub_ptr_lhs_cast138 - $sub_ptr_rhs_cast139 | 0;
+ $cmp141 = ($sub_ptr_sub140 | 0) < 3;
+ if ($cmp141) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $add_ptr145 = $39 + 3 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr145;
+ label = 45;
+ break;
+ case 41:
+ $40 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_rhs_cast148 = $40;
+ $sub_ptr_sub149 = $sub_ptr_lhs_cast147 - $sub_ptr_rhs_cast148 | 0;
+ $cmp150 = ($sub_ptr_sub149 | 0) < 4;
+ if ($cmp150) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $add_ptr154 = $40 + 4 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr154;
+ label = 45;
+ break;
+ case 43:
+ $41 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $41;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 44:
+ $42 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr157 = $42 + 2 | 0;
+ $call158 = _big2_scanRef($enc, $add_ptr157, $end, $ptr_addr) | 0;
+ $cmp159 = ($call158 | 0) < 1;
+ if ($cmp159) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $43 = HEAP32[$ptr_addr >> 2] | 0;
+ $cmp104 = ($43 | 0) == ($end | 0);
+ if ($cmp104) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $34 = $43;
+ label = 32;
+ break;
+ }
+ case 46:
+ $cmp162 = ($call158 | 0) == 0;
+ if ($cmp162) {
+ label = 47;
+ break;
+ } else {
+ $retval_0 = $call158;
+ label = 79;
+ break;
+ }
+ case 47:
+ $44 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $44;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 48:
+ $45 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $45;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 49:
+ $46 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr169 = $46 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr169;
+ label = 45;
+ break;
+ case 50:
+ $47 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr172 = $47 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr172;
+ $cmp173 = ($add_ptr172 | 0) == ($end | 0);
+ if ($cmp173) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $48 = HEAP8[$add_ptr172] | 0;
+ $cmp179 = $48 << 24 >> 24 == 0;
+ $arrayidx182 = $47 + 3 | 0;
+ $49 = HEAP8[$arrayidx182] | 0;
+ if ($cmp179) {
+ label = 52;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 52:
+ $idxprom183 = $49 & 255;
+ $arrayidx185 = $4 + $idxprom183 | 0;
+ $50 = HEAP8[$arrayidx185] | 0;
+ $conv186 = $50 & 255;
+ $cond192 = $conv186;
+ label = 54;
+ break;
+ case 53:
+ $call190 = _unicode_byte_type($48, $49) | 0;
+ $cond192 = $call190;
+ label = 54;
+ break;
+ case 54:
+ if (($cond192 | 0) == 21 | ($cond192 | 0) == 9 | ($cond192 | 0) == 10) {
+ label = 55;
+ break;
+ } else if (($cond192 | 0) == 11) {
+ label = 71;
+ break;
+ } else if (($cond192 | 0) == 17) {
+ label = 72;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 55:
+ $51 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr19961 = $51 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr19961;
+ $cmp20062 = ($add_ptr19961 | 0) == ($end | 0);
+ if ($cmp20062) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $53 = $51;
+ $add_ptr19963 = $add_ptr19961;
+ label = 57;
+ break;
+ }
+ case 56:
+ $52 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $52;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 57:
+ $54 = HEAP8[$add_ptr19963] | 0;
+ $cmp206 = $54 << 24 >> 24 == 0;
+ $arrayidx209 = $53 + 3 | 0;
+ $55 = HEAP8[$arrayidx209] | 0;
+ if ($cmp206) {
+ label = 58;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 58:
+ $idxprom210 = $55 & 255;
+ $arrayidx212 = $5 + $idxprom210 | 0;
+ $56 = HEAP8[$arrayidx212] | 0;
+ $conv213 = $56 & 255;
+ $cond219 = $conv213;
+ label = 60;
+ break;
+ case 59:
+ $call217 = _unicode_byte_type($54, $55) | 0;
+ $cond219 = $call217;
+ label = 60;
+ break;
+ case 60:
+ if (($cond219 | 0) == 21 | ($cond219 | 0) == 9 | ($cond219 | 0) == 10) {
+ label = 61;
+ break;
+ } else if (($cond219 | 0) == 29) {
+ label = 62;
+ break;
+ } else if (($cond219 | 0) == 22 | ($cond219 | 0) == 24) {
+ label = 64;
+ break;
+ } else if (($cond219 | 0) == 5) {
+ label = 65;
+ break;
+ } else if (($cond219 | 0) == 6) {
+ label = 67;
+ break;
+ } else if (($cond219 | 0) == 7) {
+ label = 69;
+ break;
+ } else if (($cond219 | 0) == 11) {
+ label = 71;
+ break;
+ } else if (($cond219 | 0) == 17) {
+ label = 72;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 61:
+ $57 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr199 = $57 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr199;
+ $cmp200 = ($add_ptr199 | 0) == ($end | 0);
+ if ($cmp200) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $53 = $57;
+ $add_ptr19963 = $add_ptr199;
+ label = 57;
+ break;
+ }
+ case 62:
+ $58 = HEAP32[$ptr_addr >> 2] | 0;
+ $59 = HEAP8[$58] | 0;
+ $idxprom222 = $59 & 255;
+ $arrayidx223 = $idxprom222 + 9272 | 0;
+ $60 = HEAP8[$arrayidx223] | 0;
+ $conv224 = $60 & 255;
+ $shl225 = $conv224 << 3;
+ $arrayidx226 = $58 + 1 | 0;
+ $61 = HEAP8[$arrayidx226] | 0;
+ $conv227 = $61 & 255;
+ $shr22848 = $conv227 >>> 5;
+ $add229 = $shr22848 | $shl225;
+ $arrayidx230 = 9544 + ($add229 << 2) | 0;
+ $62 = HEAP32[$arrayidx230 >> 2] | 0;
+ $and233 = $conv227 & 31;
+ $shl234 = 1 << $and233;
+ $and235 = $shl234 & $62;
+ $tobool236 = ($and235 | 0) == 0;
+ if ($tobool236) {
+ label = 63;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 63:
+ HEAP32[$nextTokPtr >> 2] = $58;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 64:
+ $_pn = HEAP32[$ptr_addr >> 2] | 0;
+ $storemerge = $_pn + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $storemerge;
+ $cmp = ($storemerge | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $6 = $storemerge;
+ label = 4;
+ break;
+ }
+ case 65:
+ $63 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast242 = $end;
+ $sub_ptr_rhs_cast243 = $63;
+ $sub_ptr_sub244 = $sub_ptr_lhs_cast242 - $sub_ptr_rhs_cast243 | 0;
+ $cmp245 = ($sub_ptr_sub244 | 0) < 2;
+ if ($cmp245) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ HEAP32[$nextTokPtr >> 2] = $63;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 67:
+ $64 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast250 = $end;
+ $sub_ptr_rhs_cast251 = $64;
+ $sub_ptr_sub252 = $sub_ptr_lhs_cast250 - $sub_ptr_rhs_cast251 | 0;
+ $cmp253 = ($sub_ptr_sub252 | 0) < 3;
+ if ($cmp253) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ HEAP32[$nextTokPtr >> 2] = $64;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 69:
+ $65 = HEAP32[$ptr_addr >> 2] | 0;
+ $sub_ptr_lhs_cast258 = $end;
+ $sub_ptr_rhs_cast259 = $65;
+ $sub_ptr_sub260 = $sub_ptr_lhs_cast258 - $sub_ptr_rhs_cast259 | 0;
+ $cmp261 = ($sub_ptr_sub260 | 0) < 4;
+ if ($cmp261) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ HEAP32[$nextTokPtr >> 2] = $65;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 71:
+ $66 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr267 = $66 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr267;
+ $retval_0 = 1;
+ label = 79;
+ break;
+ case 72:
+ $67 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr269 = $67 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr269;
+ $cmp270 = ($add_ptr269 | 0) == ($end | 0);
+ if ($cmp270) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $68 = HEAP8[$add_ptr269] | 0;
+ $cmp276 = $68 << 24 >> 24 == 0;
+ if ($cmp276) {
+ label = 74;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 74:
+ $arrayidx278 = $67 + 3 | 0;
+ $69 = HEAP8[$arrayidx278] | 0;
+ $cmp280 = $69 << 24 >> 24 == 62;
+ if ($cmp280) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $70 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $70;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 76:
+ $add_ptr284 = $67 + 4 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr284;
+ $retval_0 = 3;
+ label = 79;
+ break;
+ case 77:
+ $71 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $71;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 78:
+ $72 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $72;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 79:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanLit($open, $enc, $ptr, $end, $nextTokPtr) {
+ $open = $open | 0;
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp27 = 0, $type = 0, $0 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_lhs_cast11 = 0, $sub_ptr_lhs_cast20 = 0, $ptr_addr_028 = 0, $1 = 0, $cmp1 = 0, $arrayidx3 = 0, $2 = 0, $idxprom = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp8 = 0, $add_ptr = 0, $sub_ptr_rhs_cast12 = 0, $sub_ptr_sub13 = 0, $cmp14 = 0, $add_ptr18 = 0, $sub_ptr_rhs_cast21 = 0, $sub_ptr_sub22 = 0, $cmp23 = 0, $add_ptr27 = 0, $add_ptr30 = 0, $cmp31 = 0, $cmp35 = 0, $4 = 0, $cmp41 = 0, $arrayidx44 = 0, $5 = 0, $idxprom45 = 0, $type46 = 0, $6 = 0, $arrayidx47 = 0, $7 = 0, $conv48 = 0, $call52 = 0, $cond54 = 0, $add_ptr57 = 0, $ptr_addr_0_be = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp27 = ($ptr | 0) == ($end | 0);
+ if ($cmp27) {
+ $retval_0 = -1;
+ label = 24;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_lhs_cast11 = $end;
+ $sub_ptr_lhs_cast20 = $end;
+ $ptr_addr_028 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP8[$ptr_addr_028] | 0;
+ $cmp1 = $1 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr_addr_028 + 1 | 0;
+ $2 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $idxprom = $2 & 255;
+ $arrayidx4 = $0 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 7;
+ break;
+ case 6:
+ $call = _unicode_byte_type($1, $2) | 0;
+ $cond = $call;
+ label = 7;
+ break;
+ case 7:
+ if (($cond | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 10;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 12;
+ break;
+ } else if (($cond | 0) == 0 | ($cond | 0) == 1 | ($cond | 0) == 8) {
+ label = 14;
+ break;
+ } else if (($cond | 0) == 12 | ($cond | 0) == 13) {
+ label = 15;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 8:
+ $sub_ptr_rhs_cast = $ptr_addr_028;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp8 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp8) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add_ptr = $ptr_addr_028 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 23;
+ break;
+ case 10:
+ $sub_ptr_rhs_cast12 = $ptr_addr_028;
+ $sub_ptr_sub13 = $sub_ptr_lhs_cast11 - $sub_ptr_rhs_cast12 | 0;
+ $cmp14 = ($sub_ptr_sub13 | 0) < 3;
+ if ($cmp14) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $add_ptr18 = $ptr_addr_028 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr18;
+ label = 23;
+ break;
+ case 12:
+ $sub_ptr_rhs_cast21 = $ptr_addr_028;
+ $sub_ptr_sub22 = $sub_ptr_lhs_cast20 - $sub_ptr_rhs_cast21 | 0;
+ $cmp23 = ($sub_ptr_sub22 | 0) < 4;
+ if ($cmp23) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $add_ptr27 = $ptr_addr_028 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr27;
+ label = 23;
+ break;
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_028;
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 15:
+ $add_ptr30 = $ptr_addr_028 + 2 | 0;
+ $cmp31 = ($cond | 0) == ($open | 0);
+ if ($cmp31) {
+ label = 16;
+ break;
+ } else {
+ $ptr_addr_0_be = $add_ptr30;
+ label = 23;
+ break;
+ }
+ case 16:
+ $cmp35 = ($add_ptr30 | 0) == ($end | 0);
+ if ($cmp35) {
+ $retval_0 = -27;
+ label = 24;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr30;
+ $4 = HEAP8[$add_ptr30] | 0;
+ $cmp41 = $4 << 24 >> 24 == 0;
+ $arrayidx44 = $ptr_addr_028 + 3 | 0;
+ $5 = HEAP8[$arrayidx44] | 0;
+ if ($cmp41) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $idxprom45 = $5 & 255;
+ $type46 = $enc + 72 | 0;
+ $6 = $type46;
+ $arrayidx47 = $6 + $idxprom45 | 0;
+ $7 = HEAP8[$arrayidx47] | 0;
+ $conv48 = $7 & 255;
+ $cond54 = $conv48;
+ label = 20;
+ break;
+ case 19:
+ $call52 = _unicode_byte_type($4, $5) | 0;
+ $cond54 = $call52;
+ label = 20;
+ break;
+ case 20:
+ if (($cond54 | 0) == 21 | ($cond54 | 0) == 9 | ($cond54 | 0) == 10 | ($cond54 | 0) == 11 | ($cond54 | 0) == 30 | ($cond54 | 0) == 20) {
+ $retval_0 = 27;
+ label = 24;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 22:
+ $add_ptr57 = $ptr_addr_028 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr57;
+ label = 23;
+ break;
+ case 23:
+ $cmp = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_028 = $ptr_addr_0_be;
+ label = 4;
+ break;
+ }
+ case 24:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanDecl($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $ptr_addr_038 = 0, $cmp1339 = 0, $type22 = 0, $4 = 0, $add_ptr = 0, $call8 = 0, $add_ptr10 = 0, $ptr_addr_041 = 0, $ptr_pn40 = 0, $5 = 0, $cmp17 = 0, $arrayidx20 = 0, $6 = 0, $idxprom21 = 0, $arrayidx23 = 0, $7 = 0, $conv24 = 0, $call28 = 0, $cond30 = 0, $ptr_addr_0 = 0, $cmp13 = 0, $add_ptr32 = 0, $cmp33 = 0, $8 = 0, $cmp40 = 0, $arrayidx44 = 0, $9 = 0, $idxprom45 = 0, $type46 = 0, $10 = 0, $arrayidx47 = 0, $11 = 0, $conv48 = 0, $call54 = 0, $cond56 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 25;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx4 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 27) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 20) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 7:
+ $ptr_addr_038 = $ptr + 2 | 0;
+ $cmp1339 = ($ptr_addr_038 | 0) == ($end | 0);
+ if ($cmp1339) {
+ $retval_0 = -1;
+ label = 25;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type22 = $enc + 72 | 0;
+ $4 = $type22;
+ $ptr_pn40 = $ptr;
+ $ptr_addr_041 = $ptr_addr_038;
+ label = 12;
+ break;
+ case 9:
+ $add_ptr = $ptr + 2 | 0;
+ $call8 = _big2_scanComment($enc, $add_ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call8;
+ label = 25;
+ break;
+ case 10:
+ $add_ptr10 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr10;
+ $retval_0 = 33;
+ label = 25;
+ break;
+ case 11:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 25;
+ break;
+ case 12:
+ $5 = HEAP8[$ptr_addr_041] | 0;
+ $cmp17 = $5 << 24 >> 24 == 0;
+ $arrayidx20 = $ptr_pn40 + 3 | 0;
+ $6 = HEAP8[$arrayidx20] | 0;
+ if ($cmp17) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $idxprom21 = $6 & 255;
+ $arrayidx23 = $4 + $idxprom21 | 0;
+ $7 = HEAP8[$arrayidx23] | 0;
+ $conv24 = $7 & 255;
+ $cond30 = $conv24;
+ label = 15;
+ break;
+ case 14:
+ $call28 = _unicode_byte_type($5, $6) | 0;
+ $cond30 = $call28;
+ label = 15;
+ break;
+ case 15:
+ if (($cond30 | 0) == 22 | ($cond30 | 0) == 24) {
+ label = 16;
+ break;
+ } else if (($cond30 | 0) == 30) {
+ label = 17;
+ break;
+ } else if (($cond30 | 0) == 21 | ($cond30 | 0) == 9 | ($cond30 | 0) == 10) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 16:
+ $ptr_addr_0 = $ptr_addr_041 + 2 | 0;
+ $cmp13 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp13) {
+ $retval_0 = -1;
+ label = 25;
+ break;
+ } else {
+ $ptr_pn40 = $ptr_addr_041;
+ $ptr_addr_041 = $ptr_addr_0;
+ label = 12;
+ break;
+ }
+ case 17:
+ $add_ptr32 = $ptr_pn40 + 4 | 0;
+ $cmp33 = ($add_ptr32 | 0) == ($end | 0);
+ if ($cmp33) {
+ $retval_0 = -1;
+ label = 25;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $8 = HEAP8[$add_ptr32] | 0;
+ $cmp40 = $8 << 24 >> 24 == 0;
+ $arrayidx44 = $ptr_pn40 + 5 | 0;
+ $9 = HEAP8[$arrayidx44] | 0;
+ if ($cmp40) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom45 = $9 & 255;
+ $type46 = $enc + 72 | 0;
+ $10 = $type46;
+ $arrayidx47 = $10 + $idxprom45 | 0;
+ $11 = HEAP8[$arrayidx47] | 0;
+ $conv48 = $11 & 255;
+ $cond56 = $conv48;
+ label = 21;
+ break;
+ case 20:
+ $call54 = _unicode_byte_type($8, $9) | 0;
+ $cond56 = $call54;
+ label = 21;
+ break;
+ case 21:
+ if (($cond56 | 0) == 21 | ($cond56 | 0) == 9 | ($cond56 | 0) == 10 | ($cond56 | 0) == 30) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_041;
+ $retval_0 = 0;
+ label = 25;
+ break;
+ case 23:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_041;
+ $retval_0 = 16;
+ label = 25;
+ break;
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_041;
+ $retval_0 = 0;
+ label = 25;
+ break;
+ case 25:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _big2_scanPoundName($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $arrayidx3 = 0, $1 = 0, $idxprom = 0, $type = 0, $2 = 0, $arrayidx4 = 0, $3 = 0, $conv5 = 0, $call = 0, $cond = 0, $ptr_addr_059 = 0, $cmp4360 = 0, $type52 = 0, $4 = 0, $5 = 0, $idxprom9 = 0, $arrayidx10 = 0, $6 = 0, $conv11 = 0, $shl = 0, $7 = 0, $conv13 = 0, $shr52 = 0, $add = 0, $arrayidx14 = 0, $8 = 0, $and = 0, $shl17 = 0, $and18 = 0, $tobool = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp23 = 0, $sub_ptr_lhs_cast28 = 0, $sub_ptr_rhs_cast29 = 0, $sub_ptr_sub30 = 0, $cmp31 = 0, $sub_ptr_lhs_cast36 = 0, $sub_ptr_rhs_cast37 = 0, $sub_ptr_sub38 = 0, $cmp39 = 0, $ptr_addr_062 = 0, $ptr_pn61 = 0, $9 = 0, $cmp47 = 0, $arrayidx50 = 0, $10 = 0, $idxprom51 = 0, $arrayidx53 = 0, $11 = 0, $conv54 = 0, $call58 = 0, $cond60 = 0, $12 = 0, $idxprom63 = 0, $arrayidx64 = 0, $13 = 0, $conv65 = 0, $shl66 = 0, $14 = 0, $conv68 = 0, $shr6951 = 0, $add70 = 0, $arrayidx71 = 0, $15 = 0, $and74 = 0, $shl75 = 0, $and76 = 0, $tobool77 = 0, $ptr_addr_0 = 0, $cmp43 = 0, $sub_ptr_lhs_cast83 = 0, $sub_ptr_rhs_cast84 = 0, $sub_ptr_sub85 = 0, $cmp86 = 0, $sub_ptr_lhs_cast91 = 0, $sub_ptr_rhs_cast92 = 0, $sub_ptr_sub93 = 0, $cmp94 = 0, $sub_ptr_lhs_cast99 = 0, $sub_ptr_rhs_cast100 = 0, $sub_ptr_sub101 = 0, $cmp102 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 33;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 0;
+ $arrayidx3 = $ptr + 1 | 0;
+ $1 = HEAP8[$arrayidx3] | 0;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $idxprom = $1 & 255;
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $arrayidx4 = $2 + $idxprom | 0;
+ $3 = HEAP8[$arrayidx4] | 0;
+ $conv5 = $3 & 255;
+ $cond = $conv5;
+ label = 6;
+ break;
+ case 5:
+ $call = _unicode_byte_type($0, $1) | 0;
+ $cond = $call;
+ label = 6;
+ break;
+ case 6:
+ if (($cond | 0) == 22 | ($cond | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($cond | 0) == 29) {
+ label = 9;
+ break;
+ } else if (($cond | 0) == 5) {
+ label = 11;
+ break;
+ } else if (($cond | 0) == 6) {
+ label = 13;
+ break;
+ } else if (($cond | 0) == 7) {
+ label = 15;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 7:
+ $ptr_addr_059 = $ptr + 2 | 0;
+ $cmp4360 = ($ptr_addr_059 | 0) == ($end | 0);
+ if ($cmp4360) {
+ $retval_0 = -20;
+ label = 33;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $type52 = $enc + 72 | 0;
+ $4 = $type52;
+ $ptr_pn61 = $ptr;
+ $ptr_addr_062 = $ptr_addr_059;
+ label = 18;
+ break;
+ case 9:
+ $5 = HEAP8[$ptr] | 0;
+ $idxprom9 = $5 & 255;
+ $arrayidx10 = $idxprom9 + 9272 | 0;
+ $6 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $6 & 255;
+ $shl = $conv11 << 3;
+ $7 = HEAP8[$arrayidx3] | 0;
+ $conv13 = $7 & 255;
+ $shr52 = $conv13 >>> 5;
+ $add = $shr52 | $shl;
+ $arrayidx14 = 9544 + ($add << 2) | 0;
+ $8 = HEAP32[$arrayidx14 >> 2] | 0;
+ $and = $conv13 & 31;
+ $shl17 = 1 << $and;
+ $and18 = $shl17 & $8;
+ $tobool = ($and18 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 11:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp23 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp23) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 13:
+ $sub_ptr_lhs_cast28 = $end;
+ $sub_ptr_rhs_cast29 = $ptr;
+ $sub_ptr_sub30 = $sub_ptr_lhs_cast28 - $sub_ptr_rhs_cast29 | 0;
+ $cmp31 = ($sub_ptr_sub30 | 0) < 3;
+ if ($cmp31) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 15:
+ $sub_ptr_lhs_cast36 = $end;
+ $sub_ptr_rhs_cast37 = $ptr;
+ $sub_ptr_sub38 = $sub_ptr_lhs_cast36 - $sub_ptr_rhs_cast37 | 0;
+ $cmp39 = ($sub_ptr_sub38 | 0) < 4;
+ if ($cmp39) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 18:
+ $9 = HEAP8[$ptr_addr_062] | 0;
+ $cmp47 = $9 << 24 >> 24 == 0;
+ $arrayidx50 = $ptr_pn61 + 3 | 0;
+ $10 = HEAP8[$arrayidx50] | 0;
+ if ($cmp47) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ $idxprom51 = $10 & 255;
+ $arrayidx53 = $4 + $idxprom51 | 0;
+ $11 = HEAP8[$arrayidx53] | 0;
+ $conv54 = $11 & 255;
+ $cond60 = $conv54;
+ label = 21;
+ break;
+ case 20:
+ $call58 = _unicode_byte_type($9, $10) | 0;
+ $cond60 = $call58;
+ label = 21;
+ break;
+ case 21:
+ if (($cond60 | 0) == 29) {
+ label = 22;
+ break;
+ } else if (($cond60 | 0) == 22 | ($cond60 | 0) == 24 | ($cond60 | 0) == 25 | ($cond60 | 0) == 26 | ($cond60 | 0) == 27) {
+ label = 23;
+ break;
+ } else if (($cond60 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($cond60 | 0) == 6) {
+ label = 27;
+ break;
+ } else if (($cond60 | 0) == 7) {
+ label = 29;
+ break;
+ } else if (($cond60 | 0) == 9 | ($cond60 | 0) == 10 | ($cond60 | 0) == 21 | ($cond60 | 0) == 32 | ($cond60 | 0) == 11 | ($cond60 | 0) == 30 | ($cond60 | 0) == 36) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 22:
+ $12 = HEAP8[$ptr_addr_062] | 0;
+ $idxprom63 = $12 & 255;
+ $arrayidx64 = $idxprom63 + 10824 | 0;
+ $13 = HEAP8[$arrayidx64] | 0;
+ $conv65 = $13 & 255;
+ $shl66 = $conv65 << 3;
+ $14 = HEAP8[$arrayidx50] | 0;
+ $conv68 = $14 & 255;
+ $shr6951 = $conv68 >>> 5;
+ $add70 = $shr6951 | $shl66;
+ $arrayidx71 = 9544 + ($add70 << 2) | 0;
+ $15 = HEAP32[$arrayidx71 >> 2] | 0;
+ $and74 = $conv68 & 31;
+ $shl75 = 1 << $and74;
+ $and76 = $shl75 & $15;
+ $tobool77 = ($and76 | 0) == 0;
+ if ($tobool77) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $ptr_addr_0 = $ptr_addr_062 + 2 | 0;
+ $cmp43 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp43) {
+ $retval_0 = -20;
+ label = 33;
+ break;
+ } else {
+ $ptr_pn61 = $ptr_addr_062;
+ $ptr_addr_062 = $ptr_addr_0;
+ label = 18;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 25:
+ $sub_ptr_lhs_cast83 = $end;
+ $sub_ptr_rhs_cast84 = $ptr_addr_062;
+ $sub_ptr_sub85 = $sub_ptr_lhs_cast83 - $sub_ptr_rhs_cast84 | 0;
+ $cmp86 = ($sub_ptr_sub85 | 0) < 2;
+ if ($cmp86) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 27:
+ $sub_ptr_lhs_cast91 = $end;
+ $sub_ptr_rhs_cast92 = $ptr_addr_062;
+ $sub_ptr_sub93 = $sub_ptr_lhs_cast91 - $sub_ptr_rhs_cast92 | 0;
+ $cmp94 = ($sub_ptr_sub93 | 0) < 3;
+ if ($cmp94) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 29:
+ $sub_ptr_lhs_cast99 = $end;
+ $sub_ptr_rhs_cast100 = $ptr_addr_062;
+ $sub_ptr_sub101 = $sub_ptr_lhs_cast99 - $sub_ptr_rhs_cast100 | 0;
+ $cmp102 = ($sub_ptr_sub101 | 0) < 4;
+ if ($cmp102) {
+ $retval_0 = -2;
+ label = 33;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 20;
+ label = 33;
+ break;
+ case 32:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_062;
+ $retval_0 = 0;
+ label = 33;
+ break;
+ case 33:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_prologTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr29167 = 0, $cmp30168 = 0, $add_ptr = 0, $call = 0, $add_ptr2 = 0, $call3 = 0, $add_ptr5 = 0, $cmp6 = 0, $3 = 0, $idxprom10 = 0, $arrayidx12 = 0, $4 = 0, $conv13 = 0, $add_ptr15 = 0, $call16 = 0, $add_ptr18 = 0, $call19 = 0, $add_ptr23 = 0, $cmp24 = 0, $add_ptr29170 = 0, $ptr_addr_0169 = 0, $5 = 0, $idxprom34 = 0, $arrayidx36 = 0, $6 = 0, $conv37 = 0, $add_ptr29 = 0, $cmp30 = 0, $add_ptr40 = 0, $cmp41 = 0, $add_ptr29_lcssa = 0, $add_ptr47 = 0, $call48 = 0, $add_ptr50 = 0, $add_ptr52 = 0, $add_ptr54 = 0, $cmp55 = 0, $7 = 0, $cmp60 = 0, $add_ptr63 = 0, $cmp64 = 0, $8 = 0, $cmp70 = 0, $add_ptr73 = 0, $add_ptr77 = 0, $add_ptr79 = 0, $cmp80 = 0, $9 = 0, $idxprom84 = 0, $arrayidx86 = 0, $10 = 0, $conv87 = 0, $add_ptr89 = 0, $add_ptr91 = 0, $add_ptr93 = 0, $add_ptr97 = 0, $add_ptr99 = 0, $add_ptr101 = 0, $call102 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp104 = 0, $isNmstrt2 = 0, $11 = 0, $12 = 0, $call108 = 0, $tobool = 0, $add_ptr110 = 0, $ptr_addr_1_ph = 0, $tok_0_ph = 0, $cmp160181 = 0, $sub_ptr_lhs_cast170 = 0, $13 = 0, $sub_ptr_lhs_cast184 = 0, $isName3191 = 0, $sub_ptr_lhs_cast198 = 0, $isName4205 = 0, $14 = 0, $15 = 0, $call112 = 0, $tobool113 = 0, $add_ptr115 = 0, $sub_ptr_lhs_cast118 = 0, $sub_ptr_rhs_cast119 = 0, $sub_ptr_sub120 = 0, $cmp121 = 0, $isNmstrt3 = 0, $16 = 0, $17 = 0, $call125 = 0, $tobool126 = 0, $add_ptr128 = 0, $isName3 = 0, $18 = 0, $19 = 0, $call130 = 0, $tobool131 = 0, $add_ptr133 = 0, $sub_ptr_lhs_cast136 = 0, $sub_ptr_rhs_cast137 = 0, $sub_ptr_sub138 = 0, $cmp139 = 0, $isNmstrt4 = 0, $20 = 0, $21 = 0, $call143 = 0, $tobool144 = 0, $add_ptr146 = 0, $isName4 = 0, $22 = 0, $23 = 0, $call148 = 0, $tobool149 = 0, $add_ptr151 = 0, $add_ptr154 = 0, $add_ptr156 = 0, $ptr_addr_1182 = 0, $24 = 0, $idxprom162 = 0, $arrayidx164 = 0, $25 = 0, $conv165 = 0, $add_ptr168 = 0, $sub_ptr_rhs_cast171 = 0, $sub_ptr_sub172 = 0, $cmp173 = 0, $26 = 0, $call178 = 0, $tobool179 = 0, $add_ptr182 = 0, $sub_ptr_rhs_cast185 = 0, $sub_ptr_sub186 = 0, $cmp187 = 0, $27 = 0, $28 = 0, $call192 = 0, $tobool193 = 0, $add_ptr196 = 0, $sub_ptr_rhs_cast199 = 0, $sub_ptr_sub200 = 0, $cmp201 = 0, $29 = 0, $30 = 0, $call206 = 0, $tobool207 = 0, $add_ptr210 = 0, $ptr_addr_1_be = 0, $cmp160 = 0, $cmp213 = 0, $add_ptr217 = 0, $cmp219 = 0, $add_ptr223 = 0, $cmp225 = 0, $add_ptr229 = 0, $sub = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 91;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 21 | ($conv | 0) == 10) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 12) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 13) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 2) {
+ label = 7;
+ break;
+ } else if (($conv | 0) == 9) {
+ label = 13;
+ break;
+ } else if (($conv | 0) == 30) {
+ label = 20;
+ break;
+ } else if (($conv | 0) == 35) {
+ label = 21;
+ break;
+ } else if (($conv | 0) == 20) {
+ label = 22;
+ break;
+ } else if (($conv | 0) == 4) {
+ label = 23;
+ break;
+ } else if (($conv | 0) == 31) {
+ label = 29;
+ break;
+ } else if (($conv | 0) == 32) {
+ label = 30;
+ break;
+ } else if (($conv | 0) == 36) {
+ label = 37;
+ break;
+ } else if (($conv | 0) == 11) {
+ label = 38;
+ break;
+ } else if (($conv | 0) == 19) {
+ label = 39;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 40;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 48;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 54;
+ break;
+ } else if (($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 60;
+ break;
+ } else if (($conv | 0) == 25 | ($conv | 0) == 26 | ($conv | 0) == 27) {
+ label = 61;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 4:
+ $add_ptr29167 = $ptr + 1 | 0;
+ $cmp30168 = ($add_ptr29167 | 0) == ($end | 0);
+ if ($cmp30168) {
+ $add_ptr29_lcssa = $add_ptr29167;
+ label = 19;
+ break;
+ } else {
+ $ptr_addr_0169 = $ptr;
+ $add_ptr29170 = $add_ptr29167;
+ label = 15;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $call = _normal_scanLit(12, $enc, $add_ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 91;
+ break;
+ case 6:
+ $add_ptr2 = $ptr + 1 | 0;
+ $call3 = _normal_scanLit(13, $enc, $add_ptr2, $end, $nextTokPtr) | 0;
+ $retval_0 = $call3;
+ label = 91;
+ break;
+ case 7:
+ $add_ptr5 = $ptr + 1 | 0;
+ $cmp6 = ($add_ptr5 | 0) == ($end | 0);
+ if ($cmp6) {
+ $retval_0 = -1;
+ label = 91;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $3 = HEAP8[$add_ptr5] | 0;
+ $idxprom10 = $3 & 255;
+ $arrayidx12 = $1 + $idxprom10 | 0;
+ $4 = HEAP8[$arrayidx12] | 0;
+ $conv13 = $4 & 255;
+ if (($conv13 | 0) == 16) {
+ label = 9;
+ break;
+ } else if (($conv13 | 0) == 15) {
+ label = 10;
+ break;
+ } else if (($conv13 | 0) == 22 | ($conv13 | 0) == 24 | ($conv13 | 0) == 29 | ($conv13 | 0) == 5 | ($conv13 | 0) == 6 | ($conv13 | 0) == 7) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 9:
+ $add_ptr15 = $ptr + 2 | 0;
+ $call16 = _normal_scanDecl($enc, $add_ptr15, $end, $nextTokPtr) | 0;
+ $retval_0 = $call16;
+ label = 91;
+ break;
+ case 10:
+ $add_ptr18 = $ptr + 2 | 0;
+ $call19 = _normal_scanPi($enc, $add_ptr18, $end, $nextTokPtr) | 0;
+ $retval_0 = $call19;
+ label = 91;
+ break;
+ case 11:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 29;
+ label = 91;
+ break;
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr5;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 13:
+ $add_ptr23 = $ptr + 1 | 0;
+ $cmp24 = ($add_ptr23 | 0) == ($end | 0);
+ if ($cmp24) {
+ label = 14;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $end;
+ $retval_0 = -15;
+ label = 91;
+ break;
+ case 15:
+ $5 = HEAP8[$add_ptr29170] | 0;
+ $idxprom34 = $5 & 255;
+ $arrayidx36 = $1 + $idxprom34 | 0;
+ $6 = HEAP8[$arrayidx36] | 0;
+ $conv37 = $6 & 255;
+ if (($conv37 | 0) == 21 | ($conv37 | 0) == 10) {
+ label = 16;
+ break;
+ } else if (($conv37 | 0) == 9) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 16:
+ $add_ptr29 = $add_ptr29170 + 1 | 0;
+ $cmp30 = ($add_ptr29 | 0) == ($end | 0);
+ if ($cmp30) {
+ $add_ptr29_lcssa = $add_ptr29;
+ label = 19;
+ break;
+ } else {
+ $ptr_addr_0169 = $add_ptr29170;
+ $add_ptr29170 = $add_ptr29;
+ label = 15;
+ break;
+ }
+ case 17:
+ $add_ptr40 = $ptr_addr_0169 + 2 | 0;
+ $cmp41 = ($add_ptr40 | 0) == ($end | 0);
+ if ($cmp41) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr29170;
+ $retval_0 = 15;
+ label = 91;
+ break;
+ case 19:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr29_lcssa;
+ $retval_0 = 15;
+ label = 91;
+ break;
+ case 20:
+ $add_ptr47 = $ptr + 1 | 0;
+ $call48 = _normal_scanPercent($enc, $add_ptr47, $end, $nextTokPtr) | 0;
+ $retval_0 = $call48;
+ label = 91;
+ break;
+ case 21:
+ $add_ptr50 = $ptr + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr50;
+ $retval_0 = 38;
+ label = 91;
+ break;
+ case 22:
+ $add_ptr52 = $ptr + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr52;
+ $retval_0 = 25;
+ label = 91;
+ break;
+ case 23:
+ $add_ptr54 = $ptr + 1 | 0;
+ $cmp55 = ($add_ptr54 | 0) == ($end | 0);
+ if ($cmp55) {
+ $retval_0 = -26;
+ label = 91;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $7 = HEAP8[$add_ptr54] | 0;
+ $cmp60 = $7 << 24 >> 24 == 93;
+ if ($cmp60) {
+ label = 25;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 25:
+ $add_ptr63 = $ptr + 2 | 0;
+ $cmp64 = ($add_ptr63 | 0) == ($end | 0);
+ if ($cmp64) {
+ $retval_0 = -1;
+ label = 91;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $8 = HEAP8[$add_ptr63] | 0;
+ $cmp70 = $8 << 24 >> 24 == 62;
+ if ($cmp70) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $add_ptr73 = $ptr + 3 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr73;
+ $retval_0 = 34;
+ label = 91;
+ break;
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr54;
+ $retval_0 = 26;
+ label = 91;
+ break;
+ case 29:
+ $add_ptr77 = $ptr + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr77;
+ $retval_0 = 23;
+ label = 91;
+ break;
+ case 30:
+ $add_ptr79 = $ptr + 1 | 0;
+ $cmp80 = ($add_ptr79 | 0) == ($end | 0);
+ if ($cmp80) {
+ $retval_0 = -24;
+ label = 91;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $9 = HEAP8[$add_ptr79] | 0;
+ $idxprom84 = $9 & 255;
+ $arrayidx86 = $1 + $idxprom84 | 0;
+ $10 = HEAP8[$arrayidx86] | 0;
+ $conv87 = $10 & 255;
+ if (($conv87 | 0) == 33) {
+ label = 32;
+ break;
+ } else if (($conv87 | 0) == 15) {
+ label = 33;
+ break;
+ } else if (($conv87 | 0) == 34) {
+ label = 34;
+ break;
+ } else if (($conv87 | 0) == 9 | ($conv87 | 0) == 10 | ($conv87 | 0) == 21 | ($conv87 | 0) == 11 | ($conv87 | 0) == 35 | ($conv87 | 0) == 36 | ($conv87 | 0) == 32) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 32:
+ $add_ptr89 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr89;
+ $retval_0 = 36;
+ label = 91;
+ break;
+ case 33:
+ $add_ptr91 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr91;
+ $retval_0 = 35;
+ label = 91;
+ break;
+ case 34:
+ $add_ptr93 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr93;
+ $retval_0 = 37;
+ label = 91;
+ break;
+ case 35:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr79;
+ $retval_0 = 24;
+ label = 91;
+ break;
+ case 36:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr79;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 37:
+ $add_ptr97 = $ptr + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr97;
+ $retval_0 = 21;
+ label = 91;
+ break;
+ case 38:
+ $add_ptr99 = $ptr + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr99;
+ $retval_0 = 17;
+ label = 91;
+ break;
+ case 39:
+ $add_ptr101 = $ptr + 1 | 0;
+ $call102 = _normal_scanPoundName($enc, $add_ptr101, $end, $nextTokPtr) | 0;
+ $retval_0 = $call102;
+ label = 91;
+ break;
+ case 40:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp104 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp104) {
+ $retval_0 = -2;
+ label = 91;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $isNmstrt2 = $enc + 340 | 0;
+ $11 = HEAP32[$isNmstrt2 >> 2] | 0;
+ $12 = $11;
+ $call108 = FUNCTION_TABLE_iii[$12 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call108 | 0) == 0;
+ if ($tobool) {
+ label = 45;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $add_ptr110 = $ptr + 2 | 0;
+ $tok_0_ph = 18;
+ $ptr_addr_1_ph = $add_ptr110;
+ label = 43;
+ break;
+ case 43:
+ $cmp160181 = ($ptr_addr_1_ph | 0) == ($end | 0);
+ if ($cmp160181) {
+ label = 90;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $sub_ptr_lhs_cast170 = $end;
+ $13 = $enc + 328 | 0;
+ $sub_ptr_lhs_cast184 = $end;
+ $isName3191 = $enc + 332 | 0;
+ $sub_ptr_lhs_cast198 = $end;
+ $isName4205 = $enc + 336 | 0;
+ $ptr_addr_1182 = $ptr_addr_1_ph;
+ label = 63;
+ break;
+ case 45:
+ $14 = $enc + 328 | 0;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $call112 = FUNCTION_TABLE_iii[$15 & 1023]($enc, $ptr) | 0;
+ $tobool113 = ($call112 | 0) == 0;
+ if ($tobool113) {
+ label = 47;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $add_ptr115 = $ptr + 2 | 0;
+ $tok_0_ph = 19;
+ $ptr_addr_1_ph = $add_ptr115;
+ label = 43;
+ break;
+ case 47:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 48:
+ $sub_ptr_lhs_cast118 = $end;
+ $sub_ptr_rhs_cast119 = $ptr;
+ $sub_ptr_sub120 = $sub_ptr_lhs_cast118 - $sub_ptr_rhs_cast119 | 0;
+ $cmp121 = ($sub_ptr_sub120 | 0) < 3;
+ if ($cmp121) {
+ $retval_0 = -2;
+ label = 91;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $isNmstrt3 = $enc + 344 | 0;
+ $16 = HEAP32[$isNmstrt3 >> 2] | 0;
+ $17 = $16;
+ $call125 = FUNCTION_TABLE_iii[$17 & 1023]($enc, $ptr) | 0;
+ $tobool126 = ($call125 | 0) == 0;
+ if ($tobool126) {
+ label = 51;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $add_ptr128 = $ptr + 3 | 0;
+ $tok_0_ph = 18;
+ $ptr_addr_1_ph = $add_ptr128;
+ label = 43;
+ break;
+ case 51:
+ $isName3 = $enc + 332 | 0;
+ $18 = HEAP32[$isName3 >> 2] | 0;
+ $19 = $18;
+ $call130 = FUNCTION_TABLE_iii[$19 & 1023]($enc, $ptr) | 0;
+ $tobool131 = ($call130 | 0) == 0;
+ if ($tobool131) {
+ label = 53;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $add_ptr133 = $ptr + 3 | 0;
+ $tok_0_ph = 19;
+ $ptr_addr_1_ph = $add_ptr133;
+ label = 43;
+ break;
+ case 53:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 54:
+ $sub_ptr_lhs_cast136 = $end;
+ $sub_ptr_rhs_cast137 = $ptr;
+ $sub_ptr_sub138 = $sub_ptr_lhs_cast136 - $sub_ptr_rhs_cast137 | 0;
+ $cmp139 = ($sub_ptr_sub138 | 0) < 4;
+ if ($cmp139) {
+ $retval_0 = -2;
+ label = 91;
+ break;
+ } else {
+ label = 55;
+ break;
+ }
+ case 55:
+ $isNmstrt4 = $enc + 348 | 0;
+ $20 = HEAP32[$isNmstrt4 >> 2] | 0;
+ $21 = $20;
+ $call143 = FUNCTION_TABLE_iii[$21 & 1023]($enc, $ptr) | 0;
+ $tobool144 = ($call143 | 0) == 0;
+ if ($tobool144) {
+ label = 57;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 56:
+ $add_ptr146 = $ptr + 4 | 0;
+ $tok_0_ph = 18;
+ $ptr_addr_1_ph = $add_ptr146;
+ label = 43;
+ break;
+ case 57:
+ $isName4 = $enc + 336 | 0;
+ $22 = HEAP32[$isName4 >> 2] | 0;
+ $23 = $22;
+ $call148 = FUNCTION_TABLE_iii[$23 & 1023]($enc, $ptr) | 0;
+ $tobool149 = ($call148 | 0) == 0;
+ if ($tobool149) {
+ label = 59;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $add_ptr151 = $ptr + 4 | 0;
+ $tok_0_ph = 19;
+ $ptr_addr_1_ph = $add_ptr151;
+ label = 43;
+ break;
+ case 59:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 60:
+ $add_ptr154 = $ptr + 1 | 0;
+ $tok_0_ph = 18;
+ $ptr_addr_1_ph = $add_ptr154;
+ label = 43;
+ break;
+ case 61:
+ $add_ptr156 = $ptr + 1 | 0;
+ $tok_0_ph = 19;
+ $ptr_addr_1_ph = $add_ptr156;
+ label = 43;
+ break;
+ case 62:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 63:
+ $24 = HEAP8[$ptr_addr_1182] | 0;
+ $idxprom162 = $24 & 255;
+ $arrayidx164 = $1 + $idxprom162 | 0;
+ $25 = HEAP8[$arrayidx164] | 0;
+ $conv165 = $25 & 255;
+ if (($conv165 | 0) == 29) {
+ label = 64;
+ break;
+ } else if (($conv165 | 0) == 22 | ($conv165 | 0) == 24 | ($conv165 | 0) == 25 | ($conv165 | 0) == 26 | ($conv165 | 0) == 27) {
+ label = 65;
+ break;
+ } else if (($conv165 | 0) == 5) {
+ label = 66;
+ break;
+ } else if (($conv165 | 0) == 6) {
+ label = 70;
+ break;
+ } else if (($conv165 | 0) == 7) {
+ label = 74;
+ break;
+ } else if (($conv165 | 0) == 11 | ($conv165 | 0) == 32 | ($conv165 | 0) == 35 | ($conv165 | 0) == 36 | ($conv165 | 0) == 20 | ($conv165 | 0) == 30 | ($conv165 | 0) == 21 | ($conv165 | 0) == 9 | ($conv165 | 0) == 10) {
+ label = 79;
+ break;
+ } else if (($conv165 | 0) == 34) {
+ label = 80;
+ break;
+ } else if (($conv165 | 0) == 33) {
+ label = 83;
+ break;
+ } else if (($conv165 | 0) == 15) {
+ label = 86;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 64:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 65:
+ $add_ptr168 = $ptr_addr_1182 + 1 | 0;
+ $ptr_addr_1_be = $add_ptr168;
+ label = 78;
+ break;
+ case 66:
+ $sub_ptr_rhs_cast171 = $ptr_addr_1182;
+ $sub_ptr_sub172 = $sub_ptr_lhs_cast170 - $sub_ptr_rhs_cast171 | 0;
+ $cmp173 = ($sub_ptr_sub172 | 0) < 2;
+ if ($cmp173) {
+ $retval_0 = -2;
+ label = 91;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 67:
+ $26 = HEAP32[$13 >> 2] | 0;
+ $call178 = FUNCTION_TABLE_iii[$26 & 1023]($enc, $ptr_addr_1182) | 0;
+ $tobool179 = ($call178 | 0) == 0;
+ if ($tobool179) {
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 68:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 69:
+ $add_ptr182 = $ptr_addr_1182 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr182;
+ label = 78;
+ break;
+ case 70:
+ $sub_ptr_rhs_cast185 = $ptr_addr_1182;
+ $sub_ptr_sub186 = $sub_ptr_lhs_cast184 - $sub_ptr_rhs_cast185 | 0;
+ $cmp187 = ($sub_ptr_sub186 | 0) < 3;
+ if ($cmp187) {
+ $retval_0 = -2;
+ label = 91;
+ break;
+ } else {
+ label = 71;
+ break;
+ }
+ case 71:
+ $27 = HEAP32[$isName3191 >> 2] | 0;
+ $28 = $27;
+ $call192 = FUNCTION_TABLE_iii[$28 & 1023]($enc, $ptr_addr_1182) | 0;
+ $tobool193 = ($call192 | 0) == 0;
+ if ($tobool193) {
+ label = 72;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 72:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 73:
+ $add_ptr196 = $ptr_addr_1182 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr196;
+ label = 78;
+ break;
+ case 74:
+ $sub_ptr_rhs_cast199 = $ptr_addr_1182;
+ $sub_ptr_sub200 = $sub_ptr_lhs_cast198 - $sub_ptr_rhs_cast199 | 0;
+ $cmp201 = ($sub_ptr_sub200 | 0) < 4;
+ if ($cmp201) {
+ $retval_0 = -2;
+ label = 91;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $29 = HEAP32[$isName4205 >> 2] | 0;
+ $30 = $29;
+ $call206 = FUNCTION_TABLE_iii[$30 & 1023]($enc, $ptr_addr_1182) | 0;
+ $tobool207 = ($call206 | 0) == 0;
+ if ($tobool207) {
+ label = 76;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 76:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 77:
+ $add_ptr210 = $ptr_addr_1182 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr210;
+ label = 78;
+ break;
+ case 78:
+ $cmp160 = ($ptr_addr_1_be | 0) == ($end | 0);
+ if ($cmp160) {
+ label = 90;
+ break;
+ } else {
+ $ptr_addr_1182 = $ptr_addr_1_be;
+ label = 63;
+ break;
+ }
+ case 79:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = $tok_0_ph;
+ label = 91;
+ break;
+ case 80:
+ $cmp213 = ($tok_0_ph | 0) == 19;
+ if ($cmp213) {
+ label = 81;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 81:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 82:
+ $add_ptr217 = $ptr_addr_1182 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr217;
+ $retval_0 = 32;
+ label = 91;
+ break;
+ case 83:
+ $cmp219 = ($tok_0_ph | 0) == 19;
+ if ($cmp219) {
+ label = 84;
+ break;
+ } else {
+ label = 85;
+ break;
+ }
+ case 84:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 85:
+ $add_ptr223 = $ptr_addr_1182 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr223;
+ $retval_0 = 31;
+ label = 91;
+ break;
+ case 86:
+ $cmp225 = ($tok_0_ph | 0) == 19;
+ if ($cmp225) {
+ label = 87;
+ break;
+ } else {
+ label = 88;
+ break;
+ }
+ case 87:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 88:
+ $add_ptr229 = $ptr_addr_1182 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr229;
+ $retval_0 = 30;
+ label = 91;
+ break;
+ case 89:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1182;
+ $retval_0 = 0;
+ label = 91;
+ break;
+ case 90:
+ $sub = -$tok_0_ph | 0;
+ $retval_0 = $sub;
+ label = 91;
+ break;
+ case 91:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_sameName($enc, $ptr1, $ptr2) {
+ $enc = $enc | 0;
+ $ptr1 = $ptr1 | 0;
+ $ptr2 = $ptr2 | 0;
+ var $type = 0, $0 = 0, $ptr1_addr_0 = 0, $ptr2_addr_0 = 0, $1 = 0, $idxprom = 0, $arrayidx = 0, $2 = 0, $conv = 0, $incdec_ptr = 0, $incdec_ptr2 = 0, $3 = 0, $cmp = 0, $ptr1_addr_1 = 0, $ptr2_addr_1 = 0, $incdec_ptr6 = 0, $4 = 0, $incdec_ptr8 = 0, $5 = 0, $cmp10 = 0, $ptr1_addr_2 = 0, $ptr2_addr_2 = 0, $6 = 0, $7 = 0, $cmp19 = 0, $incdec_ptr17 = 0, $incdec_ptr15 = 0, $incdec_ptr23 = 0, $8 = 0, $incdec_ptr25 = 0, $9 = 0, $cmp27 = 0, $incdec_ptr32 = 0, $10 = 0, $incdec_ptr34 = 0, $11 = 0, $cmp36 = 0, $12 = 0, $cmp42 = 0, $idxprom46 = 0, $arrayidx48 = 0, $13 = 0, $conv49 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr2_addr_0 = $ptr2;
+ $ptr1_addr_0 = $ptr1;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP8[$ptr1_addr_0] | 0;
+ $idxprom = $1 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 7) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 6) {
+ $ptr2_addr_1 = $ptr2_addr_0;
+ $ptr1_addr_1 = $ptr1_addr_0;
+ label = 5;
+ break;
+ } else if (($conv | 0) == 5) {
+ $ptr2_addr_2 = $ptr2_addr_0;
+ $ptr1_addr_2 = $ptr1_addr_0;
+ label = 6;
+ break;
+ } else if (($conv | 0) == 29 | ($conv | 0) == 22 | ($conv | 0) == 24 | ($conv | 0) == 25 | ($conv | 0) == 26 | ($conv | 0) == 27) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $ptr1_addr_0 + 1 | 0;
+ $incdec_ptr2 = $ptr2_addr_0 + 1 | 0;
+ $3 = HEAP8[$ptr2_addr_0] | 0;
+ $cmp = $1 << 24 >> 24 == $3 << 24 >> 24;
+ if ($cmp) {
+ $ptr2_addr_1 = $incdec_ptr2;
+ $ptr1_addr_1 = $incdec_ptr;
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ }
+ case 5:
+ $incdec_ptr6 = $ptr1_addr_1 + 1 | 0;
+ $4 = HEAP8[$ptr1_addr_1] | 0;
+ $incdec_ptr8 = $ptr2_addr_1 + 1 | 0;
+ $5 = HEAP8[$ptr2_addr_1] | 0;
+ $cmp10 = $4 << 24 >> 24 == $5 << 24 >> 24;
+ if ($cmp10) {
+ $ptr2_addr_2 = $incdec_ptr8;
+ $ptr1_addr_2 = $incdec_ptr6;
+ label = 6;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ }
+ case 6:
+ $6 = HEAP8[$ptr1_addr_2] | 0;
+ $7 = HEAP8[$ptr2_addr_2] | 0;
+ $cmp19 = $6 << 24 >> 24 == $7 << 24 >> 24;
+ if ($cmp19) {
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ }
+ case 7:
+ $incdec_ptr17 = $ptr2_addr_2 + 1 | 0;
+ $incdec_ptr15 = $ptr1_addr_2 + 1 | 0;
+ $incdec_ptr23 = $ptr1_addr_2 + 2 | 0;
+ $8 = HEAP8[$incdec_ptr15] | 0;
+ $incdec_ptr25 = $ptr2_addr_2 + 2 | 0;
+ $9 = HEAP8[$incdec_ptr17] | 0;
+ $cmp27 = $8 << 24 >> 24 == $9 << 24 >> 24;
+ if ($cmp27) {
+ $ptr2_addr_0 = $incdec_ptr25;
+ $ptr1_addr_0 = $incdec_ptr23;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ }
+ case 8:
+ $incdec_ptr32 = $ptr2_addr_0 + 1 | 0;
+ $10 = HEAP8[$ptr2_addr_0] | 0;
+ $incdec_ptr34 = $ptr1_addr_0 + 1 | 0;
+ $11 = HEAP8[$ptr1_addr_0] | 0;
+ $cmp36 = $10 << 24 >> 24 == $11 << 24 >> 24;
+ if ($cmp36) {
+ $ptr2_addr_0 = $incdec_ptr32;
+ $ptr1_addr_0 = $incdec_ptr34;
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ }
+ case 9:
+ $12 = HEAP8[$ptr2_addr_0] | 0;
+ $cmp42 = $1 << 24 >> 24 == $12 << 24 >> 24;
+ if ($cmp42) {
+ $retval_0 = 1;
+ label = 12;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $idxprom46 = $12 & 255;
+ $arrayidx48 = $0 + $idxprom46 | 0;
+ $13 = HEAP8[$arrayidx48] | 0;
+ $conv49 = $13 & 255;
+ if (($conv49 | 0) == 5 | ($conv49 | 0) == 6 | ($conv49 | 0) == 7 | ($conv49 | 0) == 29 | ($conv49 | 0) == 22 | ($conv49 | 0) == 24 | ($conv49 | 0) == 25 | ($conv49 | 0) == 26 | ($conv49 | 0) == 27) {
+ $retval_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $retval_0 = 1;
+ label = 12;
+ break;
+ case 12:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_nameMatchesAscii($enc, $ptr1, $end1, $ptr2) {
+ $enc = $enc | 0;
+ $ptr1 = $ptr1 | 0;
+ $end1 = $end1 | 0;
+ $ptr2 = $ptr2 | 0;
+ var $0 = 0, $tobool6 = 0, $cmp7 = 0, $cmp10 = 0, $1 = 0, $ptr2_addr_09 = 0, $ptr1_addr_08 = 0, $2 = 0, $cmp2 = 0, $add_ptr = 0, $incdec_ptr = 0, $3 = 0, $tobool = 0, $cmp = 0, $cmp_lcssa = 0, $conv7 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$ptr2] | 0;
+ $tobool6 = $0 << 24 >> 24 == 0;
+ $cmp7 = ($ptr1 | 0) == ($end1 | 0);
+ if ($tobool6) {
+ $cmp_lcssa = $cmp7;
+ label = 6;
+ break;
+ } else {
+ $ptr1_addr_08 = $ptr1;
+ $ptr2_addr_09 = $ptr2;
+ $1 = $0;
+ $cmp10 = $cmp7;
+ label = 3;
+ break;
+ }
+ case 3:
+ if ($cmp10) {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP8[$ptr1_addr_08] | 0;
+ $cmp2 = $2 << 24 >> 24 == $1 << 24 >> 24;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr1_addr_08 + 1 | 0;
+ $incdec_ptr = $ptr2_addr_09 + 1 | 0;
+ $3 = HEAP8[$incdec_ptr] | 0;
+ $tobool = $3 << 24 >> 24 == 0;
+ $cmp = ($add_ptr | 0) == ($end1 | 0);
+ if ($tobool) {
+ $cmp_lcssa = $cmp;
+ label = 6;
+ break;
+ } else {
+ $ptr1_addr_08 = $add_ptr;
+ $ptr2_addr_09 = $incdec_ptr;
+ $1 = $3;
+ $cmp10 = $cmp;
+ label = 3;
+ break;
+ }
+ case 6:
+ $conv7 = $cmp_lcssa & 1;
+ $retval_0 = $conv7;
+ label = 7;
+ break;
+ case 7:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_contentTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $call = 0, $add_ptr2 = 0, $call3 = 0, $add_ptr5 = 0, $cmp6 = 0, $3 = 0, $idxprom10 = 0, $arrayidx12 = 0, $4 = 0, $cmp14 = 0, $add_ptr17 = 0, $add_ptr17_add_ptr5 = 0, $add_ptr20 = 0, $add_ptr22 = 0, $cmp23 = 0, $5 = 0, $cmp28 = 0, $add_ptr32 = 0, $cmp33 = 0, $6 = 0, $cmp38 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp44 = 0, $isInvalid2 = 0, $7 = 0, $8 = 0, $call48 = 0, $tobool = 0, $add_ptr51 = 0, $sub_ptr_lhs_cast53 = 0, $sub_ptr_rhs_cast54 = 0, $sub_ptr_sub55 = 0, $cmp56 = 0, $isInvalid3 = 0, $9 = 0, $10 = 0, $call60 = 0, $tobool61 = 0, $add_ptr64 = 0, $sub_ptr_lhs_cast66 = 0, $sub_ptr_rhs_cast67 = 0, $sub_ptr_sub68 = 0, $cmp69 = 0, $isInvalid4 = 0, $11 = 0, $12 = 0, $call73 = 0, $tobool74 = 0, $add_ptr77 = 0, $add_ptr79 = 0, $ptr_addr_1_ph = 0, $cmp8098 = 0, $sub_ptr_lhs_cast87 = 0, $isInvalid292 = 0, $13 = 0, $sub_ptr_lhs_cast99 = 0, $isInvalid3105 = 0, $14 = 0, $sub_ptr_lhs_cast112 = 0, $isInvalid4118 = 0, $15 = 0, $ptr_addr_199 = 0, $16 = 0, $idxprom82 = 0, $arrayidx84 = 0, $17 = 0, $conv85 = 0, $sub_ptr_rhs_cast88 = 0, $sub_ptr_sub89 = 0, $cmp90 = 0, $18 = 0, $call93 = 0, $tobool94 = 0, $add_ptr97 = 0, $sub_ptr_rhs_cast100 = 0, $sub_ptr_sub101 = 0, $cmp102 = 0, $19 = 0, $call106 = 0, $tobool107 = 0, $add_ptr110 = 0, $sub_ptr_rhs_cast113 = 0, $sub_ptr_sub114 = 0, $cmp115 = 0, $20 = 0, $call119 = 0, $tobool120 = 0, $add_ptr123 = 0, $add_ptr125 = 0, $cmp126 = 0, $21 = 0, $cmp131 = 0, $add_ptr136 = 0, $cmp137 = 0, $22 = 0, $cmp142 = 0, $add_ptr152 = 0, $ptr_addr_1_be = 0, $cmp80 = 0, $ptr_addr_1_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 52;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 2) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 3) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 9) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 10) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 4) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 14;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 18;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 22;
+ break;
+ } else if (($conv | 0) == 0 | ($conv | 0) == 1 | ($conv | 0) == 8) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 4:
+ $add_ptr = $ptr + 1 | 0;
+ $call = _normal_scanLt($enc, $add_ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 52;
+ break;
+ case 5:
+ $add_ptr2 = $ptr + 1 | 0;
+ $call3 = _normal_scanRef($enc, $add_ptr2, $end, $nextTokPtr) | 0;
+ $retval_0 = $call3;
+ label = 52;
+ break;
+ case 6:
+ $add_ptr5 = $ptr + 1 | 0;
+ $cmp6 = ($add_ptr5 | 0) == ($end | 0);
+ if ($cmp6) {
+ $retval_0 = -3;
+ label = 52;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $3 = HEAP8[$add_ptr5] | 0;
+ $idxprom10 = $3 & 255;
+ $arrayidx12 = $1 + $idxprom10 | 0;
+ $4 = HEAP8[$arrayidx12] | 0;
+ $cmp14 = $4 << 24 >> 24 == 10;
+ $add_ptr17 = $ptr + 2 | 0;
+ $add_ptr17_add_ptr5 = $cmp14 ? $add_ptr17 : $add_ptr5;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr17_add_ptr5;
+ $retval_0 = 7;
+ label = 52;
+ break;
+ case 8:
+ $add_ptr20 = $ptr + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr20;
+ $retval_0 = 7;
+ label = 52;
+ break;
+ case 9:
+ $add_ptr22 = $ptr + 1 | 0;
+ $cmp23 = ($add_ptr22 | 0) == ($end | 0);
+ if ($cmp23) {
+ $retval_0 = -5;
+ label = 52;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $5 = HEAP8[$add_ptr22] | 0;
+ $cmp28 = $5 << 24 >> 24 == 93;
+ if ($cmp28) {
+ label = 11;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr22;
+ label = 28;
+ break;
+ }
+ case 11:
+ $add_ptr32 = $ptr + 2 | 0;
+ $cmp33 = ($add_ptr32 | 0) == ($end | 0);
+ if ($cmp33) {
+ $retval_0 = -5;
+ label = 52;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $6 = HEAP8[$add_ptr32] | 0;
+ $cmp38 = $6 << 24 >> 24 == 62;
+ if ($cmp38) {
+ label = 13;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr22;
+ label = 28;
+ break;
+ }
+ case 13:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr32;
+ $retval_0 = 0;
+ label = 52;
+ break;
+ case 14:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp44 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp44) {
+ $retval_0 = -2;
+ label = 52;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $isInvalid2 = $enc + 352 | 0;
+ $7 = $isInvalid2;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $call48 = FUNCTION_TABLE_iii[$8 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call48 | 0) == 0;
+ if ($tobool) {
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 52;
+ break;
+ case 17:
+ $add_ptr51 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr51;
+ label = 28;
+ break;
+ case 18:
+ $sub_ptr_lhs_cast53 = $end;
+ $sub_ptr_rhs_cast54 = $ptr;
+ $sub_ptr_sub55 = $sub_ptr_lhs_cast53 - $sub_ptr_rhs_cast54 | 0;
+ $cmp56 = ($sub_ptr_sub55 | 0) < 3;
+ if ($cmp56) {
+ $retval_0 = -2;
+ label = 52;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $isInvalid3 = $enc + 356 | 0;
+ $9 = $isInvalid3;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $call60 = FUNCTION_TABLE_iii[$10 & 1023]($enc, $ptr) | 0;
+ $tobool61 = ($call60 | 0) == 0;
+ if ($tobool61) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 52;
+ break;
+ case 21:
+ $add_ptr64 = $ptr + 3 | 0;
+ $ptr_addr_1_ph = $add_ptr64;
+ label = 28;
+ break;
+ case 22:
+ $sub_ptr_lhs_cast66 = $end;
+ $sub_ptr_rhs_cast67 = $ptr;
+ $sub_ptr_sub68 = $sub_ptr_lhs_cast66 - $sub_ptr_rhs_cast67 | 0;
+ $cmp69 = ($sub_ptr_sub68 | 0) < 4;
+ if ($cmp69) {
+ $retval_0 = -2;
+ label = 52;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $isInvalid4 = $enc + 360 | 0;
+ $11 = $isInvalid4;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $call73 = FUNCTION_TABLE_iii[$12 & 1023]($enc, $ptr) | 0;
+ $tobool74 = ($call73 | 0) == 0;
+ if ($tobool74) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 52;
+ break;
+ case 25:
+ $add_ptr77 = $ptr + 4 | 0;
+ $ptr_addr_1_ph = $add_ptr77;
+ label = 28;
+ break;
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 52;
+ break;
+ case 27:
+ $add_ptr79 = $ptr + 1 | 0;
+ $ptr_addr_1_ph = $add_ptr79;
+ label = 28;
+ break;
+ case 28:
+ $cmp8098 = ($ptr_addr_1_ph | 0) == ($end | 0);
+ if ($cmp8098) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_ph;
+ label = 51;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $sub_ptr_lhs_cast87 = $end;
+ $isInvalid292 = $enc + 352 | 0;
+ $13 = $isInvalid292;
+ $sub_ptr_lhs_cast99 = $end;
+ $isInvalid3105 = $enc + 356 | 0;
+ $14 = $isInvalid3105;
+ $sub_ptr_lhs_cast112 = $end;
+ $isInvalid4118 = $enc + 360 | 0;
+ $15 = $isInvalid4118;
+ $ptr_addr_199 = $ptr_addr_1_ph;
+ label = 30;
+ break;
+ case 30:
+ $16 = HEAP8[$ptr_addr_199] | 0;
+ $idxprom82 = $16 & 255;
+ $arrayidx84 = $1 + $idxprom82 | 0;
+ $17 = HEAP8[$arrayidx84] | 0;
+ $conv85 = $17 & 255;
+ if (($conv85 | 0) == 5) {
+ label = 31;
+ break;
+ } else if (($conv85 | 0) == 6) {
+ label = 35;
+ break;
+ } else if (($conv85 | 0) == 7) {
+ label = 39;
+ break;
+ } else if (($conv85 | 0) == 4) {
+ label = 43;
+ break;
+ } else if (($conv85 | 0) == 3 | ($conv85 | 0) == 2 | ($conv85 | 0) == 0 | ($conv85 | 0) == 1 | ($conv85 | 0) == 8 | ($conv85 | 0) == 9 | ($conv85 | 0) == 10) {
+ label = 48;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 31:
+ $sub_ptr_rhs_cast88 = $ptr_addr_199;
+ $sub_ptr_sub89 = $sub_ptr_lhs_cast87 - $sub_ptr_rhs_cast88 | 0;
+ $cmp90 = ($sub_ptr_sub89 | 0) < 2;
+ if ($cmp90) {
+ label = 33;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $18 = HEAP32[$13 >> 2] | 0;
+ $call93 = FUNCTION_TABLE_iii[$18 & 1023]($enc, $ptr_addr_199) | 0;
+ $tobool94 = ($call93 | 0) == 0;
+ if ($tobool94) {
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_199;
+ $retval_0 = 6;
+ label = 52;
+ break;
+ case 34:
+ $add_ptr97 = $ptr_addr_199 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr97;
+ label = 50;
+ break;
+ case 35:
+ $sub_ptr_rhs_cast100 = $ptr_addr_199;
+ $sub_ptr_sub101 = $sub_ptr_lhs_cast99 - $sub_ptr_rhs_cast100 | 0;
+ $cmp102 = ($sub_ptr_sub101 | 0) < 3;
+ if ($cmp102) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $19 = HEAP32[$14 >> 2] | 0;
+ $call106 = FUNCTION_TABLE_iii[$19 & 1023]($enc, $ptr_addr_199) | 0;
+ $tobool107 = ($call106 | 0) == 0;
+ if ($tobool107) {
+ label = 38;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_199;
+ $retval_0 = 6;
+ label = 52;
+ break;
+ case 38:
+ $add_ptr110 = $ptr_addr_199 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr110;
+ label = 50;
+ break;
+ case 39:
+ $sub_ptr_rhs_cast113 = $ptr_addr_199;
+ $sub_ptr_sub114 = $sub_ptr_lhs_cast112 - $sub_ptr_rhs_cast113 | 0;
+ $cmp115 = ($sub_ptr_sub114 | 0) < 4;
+ if ($cmp115) {
+ label = 41;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $20 = HEAP32[$15 >> 2] | 0;
+ $call119 = FUNCTION_TABLE_iii[$20 & 1023]($enc, $ptr_addr_199) | 0;
+ $tobool120 = ($call119 | 0) == 0;
+ if ($tobool120) {
+ label = 42;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_199;
+ $retval_0 = 6;
+ label = 52;
+ break;
+ case 42:
+ $add_ptr123 = $ptr_addr_199 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr123;
+ label = 50;
+ break;
+ case 43:
+ $add_ptr125 = $ptr_addr_199 + 1 | 0;
+ $cmp126 = ($add_ptr125 | 0) == ($end | 0);
+ if ($cmp126) {
+ label = 48;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $21 = HEAP8[$add_ptr125] | 0;
+ $cmp131 = $21 << 24 >> 24 == 93;
+ if ($cmp131) {
+ label = 45;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr125;
+ label = 50;
+ break;
+ }
+ case 45:
+ $add_ptr136 = $ptr_addr_199 + 2 | 0;
+ $cmp137 = ($add_ptr136 | 0) == ($end | 0);
+ if ($cmp137) {
+ label = 48;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $22 = HEAP8[$add_ptr136] | 0;
+ $cmp142 = $22 << 24 >> 24 == 62;
+ if ($cmp142) {
+ label = 47;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr125;
+ label = 50;
+ break;
+ }
+ case 47:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr136;
+ $retval_0 = 0;
+ label = 52;
+ break;
+ case 48:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_199;
+ $retval_0 = 6;
+ label = 52;
+ break;
+ case 49:
+ $add_ptr152 = $ptr_addr_199 + 1 | 0;
+ $ptr_addr_1_be = $add_ptr152;
+ label = 50;
+ break;
+ case 50:
+ $cmp80 = ($ptr_addr_1_be | 0) == ($end | 0);
+ if ($cmp80) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_be;
+ label = 51;
+ break;
+ } else {
+ $ptr_addr_199 = $ptr_addr_1_be;
+ label = 30;
+ break;
+ }
+ case 51:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1_lcssa;
+ $retval_0 = 6;
+ label = 52;
+ break;
+ case 52:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_cdataSectionTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $cmp1 = 0, $3 = 0, $cmp6 = 0, $add_ptr10 = 0, $cmp11 = 0, $4 = 0, $cmp16 = 0, $add_ptr21 = 0, $add_ptr23 = 0, $cmp24 = 0, $5 = 0, $idxprom28 = 0, $arrayidx30 = 0, $6 = 0, $cmp32 = 0, $add_ptr35 = 0, $add_ptr35_add_ptr23 = 0, $add_ptr38 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp40 = 0, $isInvalid2 = 0, $7 = 0, $8 = 0, $call = 0, $tobool = 0, $add_ptr46 = 0, $sub_ptr_lhs_cast48 = 0, $sub_ptr_rhs_cast49 = 0, $sub_ptr_sub50 = 0, $cmp51 = 0, $isInvalid3 = 0, $9 = 0, $10 = 0, $call55 = 0, $tobool56 = 0, $add_ptr59 = 0, $sub_ptr_lhs_cast61 = 0, $sub_ptr_rhs_cast62 = 0, $sub_ptr_sub63 = 0, $cmp64 = 0, $isInvalid4 = 0, $11 = 0, $12 = 0, $call68 = 0, $tobool69 = 0, $add_ptr72 = 0, $add_ptr74 = 0, $ptr_addr_1_ph = 0, $cmp7581 = 0, $sub_ptr_lhs_cast82 = 0, $isInvalid287 = 0, $13 = 0, $sub_ptr_lhs_cast94 = 0, $isInvalid3100 = 0, $14 = 0, $sub_ptr_lhs_cast107 = 0, $isInvalid4113 = 0, $15 = 0, $ptr_addr_182 = 0, $16 = 0, $idxprom77 = 0, $arrayidx79 = 0, $17 = 0, $conv80 = 0, $sub_ptr_rhs_cast83 = 0, $sub_ptr_sub84 = 0, $cmp85 = 0, $18 = 0, $call88 = 0, $tobool89 = 0, $add_ptr92 = 0, $sub_ptr_rhs_cast95 = 0, $sub_ptr_sub96 = 0, $cmp97 = 0, $19 = 0, $call101 = 0, $tobool102 = 0, $add_ptr105 = 0, $sub_ptr_rhs_cast108 = 0, $sub_ptr_sub109 = 0, $cmp110 = 0, $20 = 0, $call114 = 0, $tobool115 = 0, $add_ptr118 = 0, $add_ptr121 = 0, $ptr_addr_1_be = 0, $cmp75 = 0, $ptr_addr_1_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 45;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 4) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 9) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 10) {
+ label = 11;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 16;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 20;
+ break;
+ } else if (($conv | 0) == 0 | ($conv | 0) == 1 | ($conv | 0) == 8) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 4:
+ $add_ptr = $ptr + 1 | 0;
+ $cmp1 = ($add_ptr | 0) == ($end | 0);
+ if ($cmp1) {
+ $retval_0 = -1;
+ label = 45;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = HEAP8[$add_ptr] | 0;
+ $cmp6 = $3 << 24 >> 24 == 93;
+ if ($cmp6) {
+ label = 6;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr;
+ label = 26;
+ break;
+ }
+ case 6:
+ $add_ptr10 = $ptr + 2 | 0;
+ $cmp11 = ($add_ptr10 | 0) == ($end | 0);
+ if ($cmp11) {
+ $retval_0 = -1;
+ label = 45;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $4 = HEAP8[$add_ptr10] | 0;
+ $cmp16 = $4 << 24 >> 24 == 62;
+ if ($cmp16) {
+ label = 8;
+ break;
+ } else {
+ $ptr_addr_1_ph = $add_ptr;
+ label = 26;
+ break;
+ }
+ case 8:
+ $add_ptr21 = $ptr + 3 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr21;
+ $retval_0 = 40;
+ label = 45;
+ break;
+ case 9:
+ $add_ptr23 = $ptr + 1 | 0;
+ $cmp24 = ($add_ptr23 | 0) == ($end | 0);
+ if ($cmp24) {
+ $retval_0 = -1;
+ label = 45;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $5 = HEAP8[$add_ptr23] | 0;
+ $idxprom28 = $5 & 255;
+ $arrayidx30 = $1 + $idxprom28 | 0;
+ $6 = HEAP8[$arrayidx30] | 0;
+ $cmp32 = $6 << 24 >> 24 == 10;
+ $add_ptr35 = $ptr + 2 | 0;
+ $add_ptr35_add_ptr23 = $cmp32 ? $add_ptr35 : $add_ptr23;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr35_add_ptr23;
+ $retval_0 = 7;
+ label = 45;
+ break;
+ case 11:
+ $add_ptr38 = $ptr + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr38;
+ $retval_0 = 7;
+ label = 45;
+ break;
+ case 12:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp40 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp40) {
+ $retval_0 = -2;
+ label = 45;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $isInvalid2 = $enc + 352 | 0;
+ $7 = $isInvalid2;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $call = FUNCTION_TABLE_iii[$8 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 45;
+ break;
+ case 15:
+ $add_ptr46 = $ptr + 2 | 0;
+ $ptr_addr_1_ph = $add_ptr46;
+ label = 26;
+ break;
+ case 16:
+ $sub_ptr_lhs_cast48 = $end;
+ $sub_ptr_rhs_cast49 = $ptr;
+ $sub_ptr_sub50 = $sub_ptr_lhs_cast48 - $sub_ptr_rhs_cast49 | 0;
+ $cmp51 = ($sub_ptr_sub50 | 0) < 3;
+ if ($cmp51) {
+ $retval_0 = -2;
+ label = 45;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $isInvalid3 = $enc + 356 | 0;
+ $9 = $isInvalid3;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $call55 = FUNCTION_TABLE_iii[$10 & 1023]($enc, $ptr) | 0;
+ $tobool56 = ($call55 | 0) == 0;
+ if ($tobool56) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 45;
+ break;
+ case 19:
+ $add_ptr59 = $ptr + 3 | 0;
+ $ptr_addr_1_ph = $add_ptr59;
+ label = 26;
+ break;
+ case 20:
+ $sub_ptr_lhs_cast61 = $end;
+ $sub_ptr_rhs_cast62 = $ptr;
+ $sub_ptr_sub63 = $sub_ptr_lhs_cast61 - $sub_ptr_rhs_cast62 | 0;
+ $cmp64 = ($sub_ptr_sub63 | 0) < 4;
+ if ($cmp64) {
+ $retval_0 = -2;
+ label = 45;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $isInvalid4 = $enc + 360 | 0;
+ $11 = $isInvalid4;
+ $12 = HEAP32[$11 >> 2] | 0;
+ $call68 = FUNCTION_TABLE_iii[$12 & 1023]($enc, $ptr) | 0;
+ $tobool69 = ($call68 | 0) == 0;
+ if ($tobool69) {
+ label = 23;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 45;
+ break;
+ case 23:
+ $add_ptr72 = $ptr + 4 | 0;
+ $ptr_addr_1_ph = $add_ptr72;
+ label = 26;
+ break;
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 45;
+ break;
+ case 25:
+ $add_ptr74 = $ptr + 1 | 0;
+ $ptr_addr_1_ph = $add_ptr74;
+ label = 26;
+ break;
+ case 26:
+ $cmp7581 = ($ptr_addr_1_ph | 0) == ($end | 0);
+ if ($cmp7581) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_ph;
+ label = 44;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $sub_ptr_lhs_cast82 = $end;
+ $isInvalid287 = $enc + 352 | 0;
+ $13 = $isInvalid287;
+ $sub_ptr_lhs_cast94 = $end;
+ $isInvalid3100 = $enc + 356 | 0;
+ $14 = $isInvalid3100;
+ $sub_ptr_lhs_cast107 = $end;
+ $isInvalid4113 = $enc + 360 | 0;
+ $15 = $isInvalid4113;
+ $ptr_addr_182 = $ptr_addr_1_ph;
+ label = 28;
+ break;
+ case 28:
+ $16 = HEAP8[$ptr_addr_182] | 0;
+ $idxprom77 = $16 & 255;
+ $arrayidx79 = $1 + $idxprom77 | 0;
+ $17 = HEAP8[$arrayidx79] | 0;
+ $conv80 = $17 & 255;
+ if (($conv80 | 0) == 5) {
+ label = 29;
+ break;
+ } else if (($conv80 | 0) == 6) {
+ label = 33;
+ break;
+ } else if (($conv80 | 0) == 7) {
+ label = 37;
+ break;
+ } else if (($conv80 | 0) == 0 | ($conv80 | 0) == 1 | ($conv80 | 0) == 8 | ($conv80 | 0) == 9 | ($conv80 | 0) == 10 | ($conv80 | 0) == 4) {
+ label = 41;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 29:
+ $sub_ptr_rhs_cast83 = $ptr_addr_182;
+ $sub_ptr_sub84 = $sub_ptr_lhs_cast82 - $sub_ptr_rhs_cast83 | 0;
+ $cmp85 = ($sub_ptr_sub84 | 0) < 2;
+ if ($cmp85) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $18 = HEAP32[$13 >> 2] | 0;
+ $call88 = FUNCTION_TABLE_iii[$18 & 1023]($enc, $ptr_addr_182) | 0;
+ $tobool89 = ($call88 | 0) == 0;
+ if ($tobool89) {
+ label = 32;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_182;
+ $retval_0 = 6;
+ label = 45;
+ break;
+ case 32:
+ $add_ptr92 = $ptr_addr_182 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr92;
+ label = 43;
+ break;
+ case 33:
+ $sub_ptr_rhs_cast95 = $ptr_addr_182;
+ $sub_ptr_sub96 = $sub_ptr_lhs_cast94 - $sub_ptr_rhs_cast95 | 0;
+ $cmp97 = ($sub_ptr_sub96 | 0) < 3;
+ if ($cmp97) {
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $19 = HEAP32[$14 >> 2] | 0;
+ $call101 = FUNCTION_TABLE_iii[$19 & 1023]($enc, $ptr_addr_182) | 0;
+ $tobool102 = ($call101 | 0) == 0;
+ if ($tobool102) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_182;
+ $retval_0 = 6;
+ label = 45;
+ break;
+ case 36:
+ $add_ptr105 = $ptr_addr_182 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr105;
+ label = 43;
+ break;
+ case 37:
+ $sub_ptr_rhs_cast108 = $ptr_addr_182;
+ $sub_ptr_sub109 = $sub_ptr_lhs_cast107 - $sub_ptr_rhs_cast108 | 0;
+ $cmp110 = ($sub_ptr_sub109 | 0) < 4;
+ if ($cmp110) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $20 = HEAP32[$15 >> 2] | 0;
+ $call114 = FUNCTION_TABLE_iii[$20 & 1023]($enc, $ptr_addr_182) | 0;
+ $tobool115 = ($call114 | 0) == 0;
+ if ($tobool115) {
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_182;
+ $retval_0 = 6;
+ label = 45;
+ break;
+ case 40:
+ $add_ptr118 = $ptr_addr_182 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr118;
+ label = 43;
+ break;
+ case 41:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_182;
+ $retval_0 = 6;
+ label = 45;
+ break;
+ case 42:
+ $add_ptr121 = $ptr_addr_182 + 1 | 0;
+ $ptr_addr_1_be = $add_ptr121;
+ label = 43;
+ break;
+ case 43:
+ $cmp75 = ($ptr_addr_1_be | 0) == ($end | 0);
+ if ($cmp75) {
+ $ptr_addr_1_lcssa = $ptr_addr_1_be;
+ label = 44;
+ break;
+ } else {
+ $ptr_addr_182 = $ptr_addr_1_be;
+ label = 28;
+ break;
+ }
+ case 44:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1_lcssa;
+ $retval_0 = 6;
+ label = 45;
+ break;
+ case 45:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_attributeValueTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $cmp148 = 0, $type = 0, $0 = 0, $ptr_addr_049 = 0, $1 = 0, $idxprom = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $add_ptr3 = 0, $add_ptr5 = 0, $cmp7 = 0, $add_ptr10 = 0, $call = 0, $cmp14 = 0, $add_ptr17 = 0, $cmp20 = 0, $add_ptr23 = 0, $cmp24 = 0, $3 = 0, $idxprom28 = 0, $arrayidx30 = 0, $4 = 0, $cmp32 = 0, $add_ptr35 = 0, $add_ptr35_add_ptr23 = 0, $cmp39 = 0, $add_ptr42 = 0, $add_ptr44 = 0, $ptr_addr_0_be = 0, $cmp1 = 0, $ptr_addr_0_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 26;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp148 = ($ptr | 0) == ($end | 0);
+ if ($cmp148) {
+ $ptr_addr_0_lcssa = $ptr;
+ label = 25;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_049 = $ptr;
+ label = 5;
+ break;
+ case 5:
+ $1 = HEAP8[$ptr_addr_049] | 0;
+ $idxprom = $1 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 5) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 7;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 3) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 2) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 10) {
+ label = 13;
+ break;
+ } else if (($conv | 0) == 9) {
+ label = 16;
+ break;
+ } else if (($conv | 0) == 21) {
+ label = 20;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 6:
+ $add_ptr = $ptr_addr_049 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 24;
+ break;
+ case 7:
+ $add_ptr3 = $ptr_addr_049 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr3;
+ label = 24;
+ break;
+ case 8:
+ $add_ptr5 = $ptr_addr_049 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr5;
+ label = 24;
+ break;
+ case 9:
+ $cmp7 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp7) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $add_ptr10 = $ptr_addr_049 + 1 | 0;
+ $call = _normal_scanRef($enc, $add_ptr10, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 26;
+ break;
+ case 11:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 26;
+ break;
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 0;
+ label = 26;
+ break;
+ case 13:
+ $cmp14 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp14) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $add_ptr17 = $ptr_addr_049 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr17;
+ $retval_0 = 7;
+ label = 26;
+ break;
+ case 15:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 26;
+ break;
+ case 16:
+ $cmp20 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp20) {
+ label = 17;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 17:
+ $add_ptr23 = $ptr_addr_049 + 1 | 0;
+ $cmp24 = ($add_ptr23 | 0) == ($end | 0);
+ if ($cmp24) {
+ $retval_0 = -3;
+ label = 26;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $3 = HEAP8[$add_ptr23] | 0;
+ $idxprom28 = $3 & 255;
+ $arrayidx30 = $0 + $idxprom28 | 0;
+ $4 = HEAP8[$arrayidx30] | 0;
+ $cmp32 = $4 << 24 >> 24 == 10;
+ $add_ptr35 = $ptr_addr_049 + 2 | 0;
+ $add_ptr35_add_ptr23 = $cmp32 ? $add_ptr35 : $add_ptr23;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr35_add_ptr23;
+ $retval_0 = 7;
+ label = 26;
+ break;
+ case 19:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 26;
+ break;
+ case 20:
+ $cmp39 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp39) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ $add_ptr42 = $ptr_addr_049 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr42;
+ $retval_0 = 39;
+ label = 26;
+ break;
+ case 22:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 26;
+ break;
+ case 23:
+ $add_ptr44 = $ptr_addr_049 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr44;
+ label = 24;
+ break;
+ case 24:
+ $cmp1 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp1) {
+ $ptr_addr_0_lcssa = $ptr_addr_0_be;
+ label = 25;
+ break;
+ } else {
+ $ptr_addr_049 = $ptr_addr_0_be;
+ label = 5;
+ break;
+ }
+ case 25:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0_lcssa;
+ $retval_0 = 6;
+ label = 26;
+ break;
+ case 26:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_entityValueTok($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $cmp148 = 0, $type = 0, $0 = 0, $ptr_addr_049 = 0, $1 = 0, $idxprom = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $add_ptr3 = 0, $add_ptr5 = 0, $cmp7 = 0, $add_ptr10 = 0, $call = 0, $cmp13 = 0, $add_ptr16 = 0, $call17 = 0, $cmp18 = 0, $cond = 0, $cmp22 = 0, $add_ptr25 = 0, $cmp28 = 0, $add_ptr31 = 0, $cmp32 = 0, $3 = 0, $idxprom36 = 0, $arrayidx38 = 0, $4 = 0, $cmp40 = 0, $add_ptr43 = 0, $add_ptr43_add_ptr31 = 0, $add_ptr46 = 0, $ptr_addr_0_be = 0, $cmp1 = 0, $ptr_addr_0_lcssa = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 25;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp148 = ($ptr | 0) == ($end | 0);
+ if ($cmp148) {
+ $ptr_addr_0_lcssa = $ptr;
+ label = 24;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_049 = $ptr;
+ label = 5;
+ break;
+ case 5:
+ $1 = HEAP8[$ptr_addr_049] | 0;
+ $idxprom = $1 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 5) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 7;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 3) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 30) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 10) {
+ label = 15;
+ break;
+ } else if (($conv | 0) == 9) {
+ label = 18;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 6:
+ $add_ptr = $ptr_addr_049 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 23;
+ break;
+ case 7:
+ $add_ptr3 = $ptr_addr_049 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr3;
+ label = 23;
+ break;
+ case 8:
+ $add_ptr5 = $ptr_addr_049 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr5;
+ label = 23;
+ break;
+ case 9:
+ $cmp7 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp7) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ $add_ptr10 = $ptr_addr_049 + 1 | 0;
+ $call = _normal_scanRef($enc, $add_ptr10, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 25;
+ break;
+ case 11:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 25;
+ break;
+ case 12:
+ $cmp13 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp13) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $add_ptr16 = $ptr_addr_049 + 1 | 0;
+ $call17 = _normal_scanPercent($enc, $add_ptr16, $end, $nextTokPtr) | 0;
+ $cmp18 = ($call17 | 0) == 22;
+ $cond = $cmp18 ? 0 : $call17;
+ $retval_0 = $cond;
+ label = 25;
+ break;
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 25;
+ break;
+ case 15:
+ $cmp22 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp22) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $add_ptr25 = $ptr_addr_049 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr25;
+ $retval_0 = 7;
+ label = 25;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 25;
+ break;
+ case 18:
+ $cmp28 = ($ptr_addr_049 | 0) == ($ptr | 0);
+ if ($cmp28) {
+ label = 19;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 19:
+ $add_ptr31 = $ptr_addr_049 + 1 | 0;
+ $cmp32 = ($add_ptr31 | 0) == ($end | 0);
+ if ($cmp32) {
+ $retval_0 = -3;
+ label = 25;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $3 = HEAP8[$add_ptr31] | 0;
+ $idxprom36 = $3 & 255;
+ $arrayidx38 = $0 + $idxprom36 | 0;
+ $4 = HEAP8[$arrayidx38] | 0;
+ $cmp40 = $4 << 24 >> 24 == 10;
+ $add_ptr43 = $ptr_addr_049 + 2 | 0;
+ $add_ptr43_add_ptr31 = $cmp40 ? $add_ptr43 : $add_ptr31;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr43_add_ptr31;
+ $retval_0 = 7;
+ label = 25;
+ break;
+ case 21:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_049;
+ $retval_0 = 6;
+ label = 25;
+ break;
+ case 22:
+ $add_ptr46 = $ptr_addr_049 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr46;
+ label = 23;
+ break;
+ case 23:
+ $cmp1 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp1) {
+ $ptr_addr_0_lcssa = $ptr_addr_0_be;
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_049 = $ptr_addr_0_be;
+ label = 5;
+ break;
+ }
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0_lcssa;
+ $retval_0 = 6;
+ label = 25;
+ break;
+ case 25:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_nameLength($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $type = 0, $0 = 0, $ptr_addr_0 = 0, $1 = 0, $idxprom = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $add_ptr2 = 0, $add_ptr4 = 0, $add_ptr6 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_0 = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP8[$ptr_addr_0] | 0;
+ $idxprom = $1 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 5) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 29 | ($conv | 0) == 22 | ($conv | 0) == 24 | ($conv | 0) == 25 | ($conv | 0) == 26 | ($conv | 0) == 27) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $add_ptr = $ptr_addr_0 + 2 | 0;
+ $ptr_addr_0 = $add_ptr;
+ label = 3;
+ break;
+ case 5:
+ $add_ptr2 = $ptr_addr_0 + 3 | 0;
+ $ptr_addr_0 = $add_ptr2;
+ label = 3;
+ break;
+ case 6:
+ $add_ptr4 = $ptr_addr_0 + 4 | 0;
+ $ptr_addr_0 = $add_ptr4;
+ label = 3;
+ break;
+ case 7:
+ $add_ptr6 = $ptr_addr_0 + 1 | 0;
+ $ptr_addr_0 = $add_ptr6;
+ label = 3;
+ break;
+ case 8:
+ $sub_ptr_lhs_cast = $ptr_addr_0;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ return $sub_ptr_sub | 0;
+ }
+ return 0;
+}
+function _normal_skipS($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $type = 0, $0 = 0, $ptr_addr_0 = 0, $1 = 0, $idxprom = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_0 = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $1 = HEAP8[$ptr_addr_0] | 0;
+ $idxprom = $1 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 10 | ($conv | 0) == 9 | ($conv | 0) == 21) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $add_ptr = $ptr_addr_0 + 1 | 0;
+ $ptr_addr_0 = $add_ptr;
+ label = 3;
+ break;
+ case 5:
+ return $ptr_addr_0 | 0;
+ }
+ return 0;
+}
+function _normal_getAtts($enc, $ptr, $attsMax, $atts) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $attsMax = $attsMax | 0;
+ $atts = $atts | 0;
+ var $type = 0, $0 = 0, $ptr_pn = 0, $state_0 = 0, $nAtts_0 = 0, $open_0 = 0, $ptr_addr_0 = 0, $1 = 0, $idxprom = 0, $arrayidx = 0, $2 = 0, $conv = 0, $cmp = 0, $cmp2 = 0, $name = 0, $normalized = 0, $state_1 = 0, $add_ptr8 = 0, $cmp10 = 0, $cmp13 = 0, $name17 = 0, $normalized19 = 0, $state_2 = 0, $add_ptr22 = 0, $cmp24 = 0, $cmp27 = 0, $name31 = 0, $normalized33 = 0, $state_3 = 0, $add_ptr36 = 0, $cmp38 = 0, $cmp41 = 0, $name45 = 0, $normalized47 = 0, $cmp51 = 0, $cmp54 = 0, $add_ptr57 = 0, $valuePtr = 0, $cmp60 = 0, $cmp63 = 0, $valueEnd = 0, $inc = 0, $cmp71 = 0, $cmp74 = 0, $add_ptr77 = 0, $valuePtr79 = 0, $cmp82 = 0, $cmp85 = 0, $valueEnd89 = 0, $inc91 = 0, $cmp95 = 0, $normalized99 = 0, $cmp102 = 0, $cmp106 = 0, $cmp108 = 0, $or_cond = 0, $normalized112 = 0, $3 = 0, $tobool = 0, $valuePtr116 = 0, $4 = 0, $cmp117 = 0, $cmp120 = 0, $or_cond87 = 0, $add_ptr123 = 0, $5 = 0, $cmp125 = 0, $idxprom129 = 0, $arrayidx131 = 0, $6 = 0, $conv132 = 0, $cmp133 = 0, $cmp141 = 0, $cmp145 = 0, $cmp148 = 0, $or_cond88 = 0, $normalized152 = 0, $cmp156 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $open_0 = 0;
+ $nAtts_0 = 0;
+ $state_0 = 1;
+ $ptr_pn = $ptr;
+ label = 3;
+ break;
+ case 3:
+ $ptr_addr_0 = $ptr_pn + 1 | 0;
+ $1 = HEAP8[$ptr_addr_0] | 0;
+ $idxprom = $1 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 5) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 29 | ($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 16;
+ break;
+ } else if (($conv | 0) == 12) {
+ label = 19;
+ break;
+ } else if (($conv | 0) == 13) {
+ label = 26;
+ break;
+ } else if (($conv | 0) == 3) {
+ label = 33;
+ break;
+ } else if (($conv | 0) == 21) {
+ label = 35;
+ break;
+ } else if (($conv | 0) == 9 | ($conv | 0) == 10) {
+ label = 42;
+ break;
+ } else if (($conv | 0) == 11 | ($conv | 0) == 17) {
+ label = 45;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 4:
+ $cmp = ($state_0 | 0) == 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $state_1 = $state_0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $cmp2 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp2) {
+ label = 6;
+ break;
+ } else {
+ $state_1 = 1;
+ label = 7;
+ break;
+ }
+ case 6:
+ $name = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name >> 2] = $ptr_addr_0;
+ $normalized = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized] = 1;
+ $state_1 = 1;
+ label = 7;
+ break;
+ case 7:
+ $add_ptr8 = $ptr_pn + 2 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_1;
+ $ptr_pn = $add_ptr8;
+ label = 3;
+ break;
+ case 8:
+ $cmp10 = ($state_0 | 0) == 0;
+ if ($cmp10) {
+ label = 9;
+ break;
+ } else {
+ $state_2 = $state_0;
+ label = 11;
+ break;
+ }
+ case 9:
+ $cmp13 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp13) {
+ label = 10;
+ break;
+ } else {
+ $state_2 = 1;
+ label = 11;
+ break;
+ }
+ case 10:
+ $name17 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name17 >> 2] = $ptr_addr_0;
+ $normalized19 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized19] = 1;
+ $state_2 = 1;
+ label = 11;
+ break;
+ case 11:
+ $add_ptr22 = $ptr_pn + 3 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_2;
+ $ptr_pn = $add_ptr22;
+ label = 3;
+ break;
+ case 12:
+ $cmp24 = ($state_0 | 0) == 0;
+ if ($cmp24) {
+ label = 13;
+ break;
+ } else {
+ $state_3 = $state_0;
+ label = 15;
+ break;
+ }
+ case 13:
+ $cmp27 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp27) {
+ label = 14;
+ break;
+ } else {
+ $state_3 = 1;
+ label = 15;
+ break;
+ }
+ case 14:
+ $name31 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name31 >> 2] = $ptr_addr_0;
+ $normalized33 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized33] = 1;
+ $state_3 = 1;
+ label = 15;
+ break;
+ case 15:
+ $add_ptr36 = $ptr_pn + 4 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_3;
+ $ptr_pn = $add_ptr36;
+ label = 3;
+ break;
+ case 16:
+ $cmp38 = ($state_0 | 0) == 0;
+ if ($cmp38) {
+ label = 17;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 17:
+ $cmp41 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp41) {
+ label = 18;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 18:
+ $name45 = $atts + ($nAtts_0 << 4) | 0;
+ HEAP32[$name45 >> 2] = $ptr_addr_0;
+ $normalized47 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized47] = 1;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 1;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 19:
+ $cmp51 = ($state_0 | 0) == 2;
+ if ($cmp51) {
+ label = 22;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $cmp54 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp54) {
+ label = 21;
+ break;
+ } else {
+ $open_0 = 12;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 21:
+ $add_ptr57 = $ptr_pn + 2 | 0;
+ $valuePtr = $atts + ($nAtts_0 << 4) + 4 | 0;
+ HEAP32[$valuePtr >> 2] = $add_ptr57;
+ $open_0 = 12;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 22:
+ $cmp60 = ($open_0 | 0) == 12;
+ if ($cmp60) {
+ label = 23;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 23:
+ $cmp63 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp63) {
+ label = 24;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 24:
+ $valueEnd = $atts + ($nAtts_0 << 4) + 8 | 0;
+ HEAP32[$valueEnd >> 2] = $ptr_addr_0;
+ label = 25;
+ break;
+ case 25:
+ $inc = $nAtts_0 + 1 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $inc;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 26:
+ $cmp71 = ($state_0 | 0) == 2;
+ if ($cmp71) {
+ label = 29;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $cmp74 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp74) {
+ label = 28;
+ break;
+ } else {
+ $open_0 = 13;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 28:
+ $add_ptr77 = $ptr_pn + 2 | 0;
+ $valuePtr79 = $atts + ($nAtts_0 << 4) + 4 | 0;
+ HEAP32[$valuePtr79 >> 2] = $add_ptr77;
+ $open_0 = 13;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 29:
+ $cmp82 = ($open_0 | 0) == 13;
+ if ($cmp82) {
+ label = 30;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 30:
+ $cmp85 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp85) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ $valueEnd89 = $atts + ($nAtts_0 << 4) + 8 | 0;
+ HEAP32[$valueEnd89 >> 2] = $ptr_addr_0;
+ label = 32;
+ break;
+ case 32:
+ $inc91 = $nAtts_0 + 1 | 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $inc91;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 33:
+ $cmp95 = ($nAtts_0 | 0) < ($attsMax | 0);
+ if ($cmp95) {
+ label = 34;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 34:
+ $normalized99 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized99] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 35:
+ $cmp102 = ($state_0 | 0) == 1;
+ if ($cmp102) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $cmp106 = ($state_0 | 0) == 2;
+ $cmp108 = ($nAtts_0 | 0) < ($attsMax | 0);
+ $or_cond = $cmp106 & $cmp108;
+ if ($or_cond) {
+ label = 37;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 37:
+ $normalized112 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ $3 = HEAP8[$normalized112] | 0;
+ $tobool = $3 << 24 >> 24 == 0;
+ if ($tobool) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $valuePtr116 = $atts + ($nAtts_0 << 4) + 4 | 0;
+ $4 = HEAP32[$valuePtr116 >> 2] | 0;
+ $cmp117 = ($ptr_addr_0 | 0) != ($4 | 0);
+ $cmp120 = $1 << 24 >> 24 == 32;
+ $or_cond87 = $cmp117 & $cmp120;
+ if ($or_cond87) {
+ label = 39;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 39:
+ $add_ptr123 = $ptr_pn + 2 | 0;
+ $5 = HEAP8[$add_ptr123] | 0;
+ $cmp125 = $5 << 24 >> 24 == 32;
+ if ($cmp125) {
+ label = 41;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $idxprom129 = $5 & 255;
+ $arrayidx131 = $0 + $idxprom129 | 0;
+ $6 = HEAP8[$arrayidx131] | 0;
+ $conv132 = $6 & 255;
+ $cmp133 = ($conv132 | 0) == ($open_0 | 0);
+ if ($cmp133) {
+ label = 41;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 41:
+ HEAP8[$normalized112] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 42:
+ $cmp141 = ($state_0 | 0) == 1;
+ if ($cmp141) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $cmp145 = ($state_0 | 0) == 2;
+ $cmp148 = ($nAtts_0 | 0) < ($attsMax | 0);
+ $or_cond88 = $cmp145 & $cmp148;
+ if ($or_cond88) {
+ label = 44;
+ break;
+ } else {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ }
+ case 44:
+ $normalized152 = $atts + ($nAtts_0 << 4) + 12 | 0;
+ HEAP8[$normalized152] = 0;
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = $state_0;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ case 45:
+ $cmp156 = ($state_0 | 0) == 2;
+ if ($cmp156) {
+ $open_0 = $open_0;
+ $nAtts_0 = $nAtts_0;
+ $state_0 = 2;
+ $ptr_pn = $ptr_addr_0;
+ label = 3;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ return $nAtts_0 | 0;
+ }
+ return 0;
+}
+function _normal_predefinedEntityName($enc, $ptr, $end) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $add_ptr = 0, $0 = 0, $cmp = 0, $1 = 0, $conv2 = 0, $2 = 0, $cmp7 = 0, $add_ptr10 = 0, $3 = 0, $cmp12 = 0, $add_ptr15 = 0, $4 = 0, $cmp17 = 0, $5 = 0, $conv24 = 0, $add_ptr26 = 0, $6 = 0, $cmp28 = 0, $add_ptr31 = 0, $7 = 0, $cmp33 = 0, $add_ptr36 = 0, $8 = 0, $cmp38 = 0, $add_ptr45 = 0, $9 = 0, $cmp47 = 0, $add_ptr50 = 0, $10 = 0, $cmp52 = 0, $add_ptr55 = 0, $11 = 0, $cmp57 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ if (($sub_ptr_sub | 0) == 2) {
+ label = 3;
+ break;
+ } else if (($sub_ptr_sub | 0) == 3) {
+ label = 6;
+ break;
+ } else if (($sub_ptr_sub | 0) == 4) {
+ label = 9;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 3:
+ $add_ptr = $ptr + 1 | 0;
+ $0 = HEAP8[$add_ptr] | 0;
+ $cmp = $0 << 24 >> 24 == 116;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$ptr] | 0;
+ $conv2 = $1 << 24 >> 24;
+ if (($conv2 | 0) == 103) {
+ label = 5;
+ break;
+ } else if (($conv2 | 0) == 108) {
+ $retval_0 = 60;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 5:
+ $retval_0 = 62;
+ label = 17;
+ break;
+ case 6:
+ $2 = HEAP8[$ptr] | 0;
+ $cmp7 = $2 << 24 >> 24 == 97;
+ if ($cmp7) {
+ label = 7;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 7:
+ $add_ptr10 = $ptr + 1 | 0;
+ $3 = HEAP8[$add_ptr10] | 0;
+ $cmp12 = $3 << 24 >> 24 == 109;
+ if ($cmp12) {
+ label = 8;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 8:
+ $add_ptr15 = $ptr + 2 | 0;
+ $4 = HEAP8[$add_ptr15] | 0;
+ $cmp17 = $4 << 24 >> 24 == 112;
+ if ($cmp17) {
+ $retval_0 = 38;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 9:
+ $5 = HEAP8[$ptr] | 0;
+ $conv24 = $5 << 24 >> 24;
+ if (($conv24 | 0) == 113) {
+ label = 10;
+ break;
+ } else if (($conv24 | 0) == 97) {
+ label = 13;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 10:
+ $add_ptr26 = $ptr + 1 | 0;
+ $6 = HEAP8[$add_ptr26] | 0;
+ $cmp28 = $6 << 24 >> 24 == 117;
+ if ($cmp28) {
+ label = 11;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 11:
+ $add_ptr31 = $ptr + 2 | 0;
+ $7 = HEAP8[$add_ptr31] | 0;
+ $cmp33 = $7 << 24 >> 24 == 111;
+ if ($cmp33) {
+ label = 12;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 12:
+ $add_ptr36 = $ptr + 3 | 0;
+ $8 = HEAP8[$add_ptr36] | 0;
+ $cmp38 = $8 << 24 >> 24 == 116;
+ if ($cmp38) {
+ $retval_0 = 34;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 13:
+ $add_ptr45 = $ptr + 1 | 0;
+ $9 = HEAP8[$add_ptr45] | 0;
+ $cmp47 = $9 << 24 >> 24 == 112;
+ if ($cmp47) {
+ label = 14;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 14:
+ $add_ptr50 = $ptr + 2 | 0;
+ $10 = HEAP8[$add_ptr50] | 0;
+ $cmp52 = $10 << 24 >> 24 == 111;
+ if ($cmp52) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $add_ptr55 = $ptr + 3 | 0;
+ $11 = HEAP8[$add_ptr55] | 0;
+ $cmp57 = $11 << 24 >> 24 == 115;
+ if ($cmp57) {
+ $retval_0 = 39;
+ label = 17;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $retval_0 = 0;
+ label = 17;
+ break;
+ case 17:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_updatePosition($enc, $ptr, $end, $pos) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $pos = $pos | 0;
+ var $cmp18 = 0, $type = 0, $0 = 0, $columnNumber22 = 0, $columnNumber = 0, $lineNumber = 0, $lineNumber8 = 0, $columnNumber20 = 0, $ptr_addr_019 = 0, $1 = 0, $idxprom = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $add_ptr2 = 0, $add_ptr4 = 0, $3 = 0, $inc = 0, $add_ptr6 = 0, $4 = 0, $inc9 = 0, $add_ptr10 = 0, $cmp11 = 0, $5 = 0, $idxprom13 = 0, $arrayidx15 = 0, $6 = 0, $cmp17 = 0, $add_ptr19 = 0, $add_ptr19_add_ptr10 = 0, $ptr_addr_1 = 0, $add_ptr21 = 0, $ptr_addr_2 = 0, $7 = 0, $inc23 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp18 = $ptr >>> 0 < $end >>> 0;
+ if ($cmp18) {
+ label = 3;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $columnNumber22 = $pos + 4 | 0;
+ $columnNumber = $pos + 4 | 0;
+ $lineNumber = $pos | 0;
+ $lineNumber8 = $pos | 0;
+ $columnNumber20 = $pos + 4 | 0;
+ $ptr_addr_019 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP8[$ptr_addr_019] | 0;
+ $idxprom = $1 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 5) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 7;
+ break;
+ } else if (($conv | 0) == 10) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 9) {
+ label = 9;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr_addr_019 + 2 | 0;
+ $ptr_addr_2 = $add_ptr;
+ label = 13;
+ break;
+ case 6:
+ $add_ptr2 = $ptr_addr_019 + 3 | 0;
+ $ptr_addr_2 = $add_ptr2;
+ label = 13;
+ break;
+ case 7:
+ $add_ptr4 = $ptr_addr_019 + 4 | 0;
+ $ptr_addr_2 = $add_ptr4;
+ label = 13;
+ break;
+ case 8:
+ HEAP32[$columnNumber >> 2] = -1;
+ $3 = HEAP32[$lineNumber >> 2] | 0;
+ $inc = $3 + 1 | 0;
+ HEAP32[$lineNumber >> 2] = $inc;
+ $add_ptr6 = $ptr_addr_019 + 1 | 0;
+ $ptr_addr_2 = $add_ptr6;
+ label = 13;
+ break;
+ case 9:
+ $4 = HEAP32[$lineNumber8 >> 2] | 0;
+ $inc9 = $4 + 1 | 0;
+ HEAP32[$lineNumber8 >> 2] = $inc9;
+ $add_ptr10 = $ptr_addr_019 + 1 | 0;
+ $cmp11 = ($add_ptr10 | 0) == ($end | 0);
+ if ($cmp11) {
+ $ptr_addr_1 = $add_ptr10;
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $5 = HEAP8[$add_ptr10] | 0;
+ $idxprom13 = $5 & 255;
+ $arrayidx15 = $0 + $idxprom13 | 0;
+ $6 = HEAP8[$arrayidx15] | 0;
+ $cmp17 = $6 << 24 >> 24 == 10;
+ $add_ptr19 = $ptr_addr_019 + 2 | 0;
+ $add_ptr19_add_ptr10 = $cmp17 ? $add_ptr19 : $add_ptr10;
+ $ptr_addr_1 = $add_ptr19_add_ptr10;
+ label = 11;
+ break;
+ case 11:
+ HEAP32[$columnNumber20 >> 2] = -1;
+ $ptr_addr_2 = $ptr_addr_1;
+ label = 13;
+ break;
+ case 12:
+ $add_ptr21 = $ptr_addr_019 + 1 | 0;
+ $ptr_addr_2 = $add_ptr21;
+ label = 13;
+ break;
+ case 13:
+ $7 = HEAP32[$columnNumber22 >> 2] | 0;
+ $inc23 = $7 + 1 | 0;
+ HEAP32[$columnNumber22 >> 2] = $inc23;
+ $cmp = $ptr_addr_2 >>> 0 < $end >>> 0;
+ if ($cmp) {
+ $ptr_addr_019 = $ptr_addr_2;
+ label = 4;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ return;
+ }
+}
+function _normal_charRefNumber($enc, $ptr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ var $add_ptr = 0, $0 = 0, $cmp = 0, $add_ptr2 = 0, $result_0 = 0, $ptr_addr_0 = 0, $1 = 0, $conv3 = 0, $lnot = 0, $shl = 0, $sub = 0, $or = 0, $shl8 = 0, $add = 0, $add10 = 0, $shl12 = 0, $add14 = 0, $add15 = 0, $result_1 = 0, $cmp16 = 0, $add_ptr19 = 0, $result_2 = 0, $ptr_addr_1 = 0, $2 = 0, $lnot24 = 0, $conv21 = 0, $mul = 0, $sub28 = 0, $add29 = 0, $cmp30 = 0, $add_ptr35 = 0, $result_3 = 0, $call = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add_ptr = $ptr + 2 | 0;
+ $0 = HEAP8[$add_ptr] | 0;
+ $cmp = $0 << 24 >> 24 == 120;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $ptr_addr_1 = $add_ptr;
+ $result_2 = 0;
+ label = 10;
+ break;
+ }
+ case 3:
+ $add_ptr2 = $ptr + 3 | 0;
+ $ptr_addr_0 = $add_ptr2;
+ $result_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP8[$ptr_addr_0] | 0;
+ $conv3 = $1 << 24 >> 24;
+ $lnot = $1 << 24 >> 24 == 59;
+ if ($lnot) {
+ $result_3 = $result_0;
+ label = 12;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ if (($conv3 | 0) == 48 | ($conv3 | 0) == 49 | ($conv3 | 0) == 50 | ($conv3 | 0) == 51 | ($conv3 | 0) == 52 | ($conv3 | 0) == 53 | ($conv3 | 0) == 54 | ($conv3 | 0) == 55 | ($conv3 | 0) == 56 | ($conv3 | 0) == 57) {
+ label = 6;
+ break;
+ } else if (($conv3 | 0) == 65 | ($conv3 | 0) == 66 | ($conv3 | 0) == 67 | ($conv3 | 0) == 68 | ($conv3 | 0) == 69 | ($conv3 | 0) == 70) {
+ label = 7;
+ break;
+ } else if (($conv3 | 0) == 97 | ($conv3 | 0) == 98 | ($conv3 | 0) == 99 | ($conv3 | 0) == 100 | ($conv3 | 0) == 101 | ($conv3 | 0) == 102) {
+ label = 8;
+ break;
+ } else {
+ $result_1 = $result_0;
+ label = 9;
+ break;
+ }
+ case 6:
+ $shl = $result_0 << 4;
+ $sub = $conv3 - 48 | 0;
+ $or = $sub | $shl;
+ $result_1 = $or;
+ label = 9;
+ break;
+ case 7:
+ $shl8 = $result_0 << 4;
+ $add = $shl8 - 55 | 0;
+ $add10 = $add + $conv3 | 0;
+ $result_1 = $add10;
+ label = 9;
+ break;
+ case 8:
+ $shl12 = $result_0 << 4;
+ $add14 = $shl12 - 87 | 0;
+ $add15 = $add14 + $conv3 | 0;
+ $result_1 = $add15;
+ label = 9;
+ break;
+ case 9:
+ $cmp16 = ($result_1 | 0) > 1114111;
+ $add_ptr19 = $ptr_addr_0 + 1 | 0;
+ if ($cmp16) {
+ $retval_0 = -1;
+ label = 13;
+ break;
+ } else {
+ $ptr_addr_0 = $add_ptr19;
+ $result_0 = $result_1;
+ label = 4;
+ break;
+ }
+ case 10:
+ $2 = HEAP8[$ptr_addr_1] | 0;
+ $lnot24 = $2 << 24 >> 24 == 59;
+ if ($lnot24) {
+ $result_3 = $result_2;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $conv21 = $2 << 24 >> 24;
+ $mul = $result_2 * 10 & -1;
+ $sub28 = $mul - 48 | 0;
+ $add29 = $sub28 + $conv21 | 0;
+ $cmp30 = ($add29 | 0) > 1114111;
+ $add_ptr35 = $ptr_addr_1 + 1 | 0;
+ if ($cmp30) {
+ $retval_0 = -1;
+ label = 13;
+ break;
+ } else {
+ $ptr_addr_1 = $add_ptr35;
+ $result_2 = $add29;
+ label = 10;
+ break;
+ }
+ case 12:
+ $call = _checkCharRefNumber($result_3) | 0;
+ $retval_0 = $call;
+ label = 13;
+ break;
+ case 13:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _isNever($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ return 0;
+}
+function _normal_isPublicId($enc, $ptr, $end, $badPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $badPtr = $badPtr | 0;
+ var $add_ptr1 = 0, $ptr_addr_013 = 0, $cmp14 = 0, $type = 0, $0 = 0, $ptr_addr_015 = 0, $1 = 0, $idxprom = 0, $arrayidx = 0, $2 = 0, $conv = 0, $ptr_addr_0 = 0, $cmp = 0, $cmp4 = 0, $tobool = 0, $3 = 0, $conv10 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add_ptr1 = $end - 1 | 0;
+ $ptr_addr_013 = $ptr + 1 | 0;
+ $cmp14 = ($ptr_addr_013 | 0) == ($add_ptr1 | 0);
+ if ($cmp14) {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $ptr_addr_015 = $ptr_addr_013;
+ label = 4;
+ break;
+ case 4:
+ $1 = HEAP8[$ptr_addr_015] | 0;
+ $idxprom = $1 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 25 | ($conv | 0) == 24 | ($conv | 0) == 27 | ($conv | 0) == 13 | ($conv | 0) == 31 | ($conv | 0) == 32 | ($conv | 0) == 34 | ($conv | 0) == 35 | ($conv | 0) == 17 | ($conv | 0) == 14 | ($conv | 0) == 15 | ($conv | 0) == 9 | ($conv | 0) == 10 | ($conv | 0) == 18 | ($conv | 0) == 16 | ($conv | 0) == 33 | ($conv | 0) == 30 | ($conv | 0) == 19) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 21) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 26 | ($conv | 0) == 22) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 5:
+ $ptr_addr_0 = $ptr_addr_015 + 1 | 0;
+ $cmp = ($ptr_addr_0 | 0) == ($add_ptr1 | 0);
+ if ($cmp) {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ } else {
+ $ptr_addr_015 = $ptr_addr_0;
+ label = 4;
+ break;
+ }
+ case 6:
+ $cmp4 = $1 << 24 >> 24 == 9;
+ if ($cmp4) {
+ label = 7;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 7:
+ HEAP32[$badPtr >> 2] = $ptr_addr_015;
+ $retval_0 = 0;
+ label = 11;
+ break;
+ case 8:
+ $tobool = $1 << 24 >> 24 < 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 9:
+ $3 = HEAP8[$ptr_addr_015] | 0;
+ $conv10 = $3 << 24 >> 24;
+ if (($conv10 | 0) == 36 | ($conv10 | 0) == 64) {
+ label = 5;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ HEAP32[$badPtr >> 2] = $ptr_addr_015;
+ $retval_0 = 0;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _utf8_toUtf8($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $1 = 0, $sub_ptr_lhs_cast1 = 0, $sub_ptr_rhs_cast2 = 0, $sub_ptr_sub3 = 0, $cmp = 0, $add_ptr = 0, $2 = 0, $fromLim_addr_0 = 0, $cmp7 = 0, $arrayidx = 0, $3 = 0, $and = 0, $cmp8 = 0, $fromLim_addr_1 = 0, $4 = 0, $5 = 0, $cmp1317 = 0, $from_019 = 0, $to_018 = 0, $6 = 0, $incdec_ptr17 = 0, $incdec_ptr18 = 0, $cmp13 = 0, $from_0_lcssa = 0, $to_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $sub_ptr_lhs_cast = $fromLim;
+ $sub_ptr_rhs_cast = $0;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $1 = HEAP32[$toP >> 2] | 0;
+ $sub_ptr_lhs_cast1 = $toLim;
+ $sub_ptr_rhs_cast2 = $1;
+ $sub_ptr_sub3 = $sub_ptr_lhs_cast1 - $sub_ptr_rhs_cast2 | 0;
+ $cmp = ($sub_ptr_sub | 0) > ($sub_ptr_sub3 | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $fromLim_addr_1 = $fromLim;
+ label = 6;
+ break;
+ }
+ case 3:
+ $add_ptr = $0 + $sub_ptr_sub3 | 0;
+ $2 = HEAP32[$fromP >> 2] | 0;
+ $fromLim_addr_0 = $add_ptr;
+ label = 4;
+ break;
+ case 4:
+ $cmp7 = $fromLim_addr_0 >>> 0 > $2 >>> 0;
+ if ($cmp7) {
+ label = 5;
+ break;
+ } else {
+ $fromLim_addr_1 = $fromLim_addr_0;
+ label = 6;
+ break;
+ }
+ case 5:
+ $arrayidx = $fromLim_addr_0 - 1 | 0;
+ $3 = HEAP8[$arrayidx] | 0;
+ $and = $3 & -64;
+ $cmp8 = $and << 24 >> 24 == -128;
+ if ($cmp8) {
+ $fromLim_addr_0 = $arrayidx;
+ label = 4;
+ break;
+ } else {
+ $fromLim_addr_1 = $fromLim_addr_0;
+ label = 6;
+ break;
+ }
+ case 6:
+ $4 = HEAP32[$toP >> 2] | 0;
+ $5 = HEAP32[$fromP >> 2] | 0;
+ $cmp1317 = ($5 | 0) == ($fromLim_addr_1 | 0);
+ if ($cmp1317) {
+ $to_0_lcssa = $4;
+ $from_0_lcssa = $5;
+ label = 8;
+ break;
+ } else {
+ $to_018 = $4;
+ $from_019 = $5;
+ label = 7;
+ break;
+ }
+ case 7:
+ $6 = HEAP8[$from_019] | 0;
+ HEAP8[$to_018] = $6;
+ $incdec_ptr17 = $from_019 + 1 | 0;
+ $incdec_ptr18 = $to_018 + 1 | 0;
+ $cmp13 = ($incdec_ptr17 | 0) == ($fromLim_addr_1 | 0);
+ if ($cmp13) {
+ $to_0_lcssa = $incdec_ptr18;
+ $from_0_lcssa = $incdec_ptr17;
+ label = 8;
+ break;
+ } else {
+ $to_018 = $incdec_ptr18;
+ $from_019 = $incdec_ptr17;
+ label = 7;
+ break;
+ }
+ case 8:
+ HEAP32[$fromP >> 2] = $from_0_lcssa;
+ HEAP32[$toP >> 2] = $to_0_lcssa;
+ return;
+ }
+}
+function _utf8_toUtf16($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $1 = 0, $cmp38 = 0, $cmp139 = 0, $or_cond40 = 0, $type = 0, $2 = 0, $to_042 = 0, $from_041 = 0, $3 = 0, $idxprom = 0, $arrayidx = 0, $4 = 0, $conv = 0, $conv336 = 0, $and = 0, $shl = 0, $arrayidx4 = 0, $5 = 0, $conv537 = 0, $and6 = 0, $or = 0, $incdec_ptr = 0, $add_ptr = 0, $conv1033 = 0, $and11 = 0, $arrayidx13 = 0, $6 = 0, $conv1434 = 0, $and15 = 0, $shl16 = 0, $or17 = 0, $arrayidx18 = 0, $7 = 0, $conv1935 = 0, $and20 = 0, $or21 = 0, $incdec_ptr23 = 0, $add_ptr24 = 0, $add_ptr26 = 0, $cmp27 = 0, $and31 = 0, $shl32 = 0, $arrayidx33 = 0, $8 = 0, $conv3430 = 0, $and35 = 0, $shl36 = 0, $or37 = 0, $arrayidx38 = 0, $9 = 0, $conv3931 = 0, $and40 = 0, $shl41 = 0, $or42 = 0, $arrayidx43 = 0, $10 = 0, $conv4432 = 0, $and45 = 0, $or46 = 0, $sub = 0, $shr = 0, $or47 = 0, $conv48 = 0, $and50 = 0, $or51 = 0, $conv52 = 0, $add_ptr54 = 0, $add_ptr55 = 0, $incdec_ptr56 = 0, $conv57 = 0, $incdec_ptr58 = 0, $from_0_be = 0, $to_0_be = 0, $cmp = 0, $cmp1 = 0, $or_cond = 0, $to_0_lcssa = 0, $from_0_lcssa = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$toP >> 2] | 0;
+ $1 = HEAP32[$fromP >> 2] | 0;
+ $cmp38 = ($1 | 0) == ($fromLim | 0);
+ $cmp139 = ($0 | 0) == ($toLim | 0);
+ $or_cond40 = $cmp38 | $cmp139;
+ if ($or_cond40) {
+ $from_0_lcssa = $1;
+ $to_0_lcssa = $0;
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $2 = $type;
+ $from_041 = $1;
+ $to_042 = $0;
+ label = 4;
+ break;
+ case 4:
+ $3 = HEAP8[$from_041] | 0;
+ $idxprom = $3 & 255;
+ $arrayidx = $2 + $idxprom | 0;
+ $4 = HEAP8[$arrayidx] | 0;
+ $conv = $4 & 255;
+ if (($conv | 0) == 5) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 7;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 5:
+ $conv336 = $3 & 255;
+ $and = $conv336 << 6;
+ $shl = $and & 1984;
+ $arrayidx4 = $from_041 + 1 | 0;
+ $5 = HEAP8[$arrayidx4] | 0;
+ $conv537 = $5 & 255;
+ $and6 = $conv537 & 63;
+ $or = $and6 | $shl;
+ $incdec_ptr = $to_042 + 2 | 0;
+ HEAP16[$to_042 >> 1] = $or;
+ $add_ptr = $from_041 + 2 | 0;
+ $to_0_be = $incdec_ptr;
+ $from_0_be = $add_ptr;
+ label = 10;
+ break;
+ case 6:
+ $conv1033 = $3 & 255;
+ $and11 = $conv1033 << 12;
+ $arrayidx13 = $from_041 + 1 | 0;
+ $6 = HEAP8[$arrayidx13] | 0;
+ $conv1434 = $6 & 255;
+ $and15 = $conv1434 << 6;
+ $shl16 = $and15 & 4032;
+ $or17 = $shl16 | $and11;
+ $arrayidx18 = $from_041 + 2 | 0;
+ $7 = HEAP8[$arrayidx18] | 0;
+ $conv1935 = $7 & 255;
+ $and20 = $conv1935 & 63;
+ $or21 = $or17 | $and20;
+ $incdec_ptr23 = $to_042 + 2 | 0;
+ HEAP16[$to_042 >> 1] = $or21;
+ $add_ptr24 = $from_041 + 3 | 0;
+ $to_0_be = $incdec_ptr23;
+ $from_0_be = $add_ptr24;
+ label = 10;
+ break;
+ case 7:
+ $add_ptr26 = $to_042 + 2 | 0;
+ $cmp27 = ($add_ptr26 | 0) == ($toLim | 0);
+ if ($cmp27) {
+ $from_0_lcssa = $from_041;
+ $to_0_lcssa = $to_042;
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $and31 = $idxprom << 18;
+ $shl32 = $and31 & 1835008;
+ $arrayidx33 = $from_041 + 1 | 0;
+ $8 = HEAP8[$arrayidx33] | 0;
+ $conv3430 = $8 & 255;
+ $and35 = $conv3430 << 12;
+ $shl36 = $and35 & 258048;
+ $or37 = $shl36 | $shl32;
+ $arrayidx38 = $from_041 + 2 | 0;
+ $9 = HEAP8[$arrayidx38] | 0;
+ $conv3931 = $9 & 255;
+ $and40 = $conv3931 << 6;
+ $shl41 = $and40 & 4032;
+ $or42 = $or37 | $shl41;
+ $arrayidx43 = $from_041 + 3 | 0;
+ $10 = HEAP8[$arrayidx43] | 0;
+ $conv4432 = $10 & 255;
+ $and45 = $conv4432 & 63;
+ $or46 = $or42 | $and45;
+ $sub = $or46 - 65536 | 0;
+ $shr = $sub >>> 10;
+ $or47 = $shr | 55296;
+ $conv48 = $or47 & 65535;
+ HEAP16[$to_042 >> 1] = $conv48;
+ $and50 = $sub & 1023;
+ $or51 = $and50 | 56320;
+ $conv52 = $or51 & 65535;
+ HEAP16[$add_ptr26 >> 1] = $conv52;
+ $add_ptr54 = $to_042 + 4 | 0;
+ $add_ptr55 = $from_041 + 4 | 0;
+ $to_0_be = $add_ptr54;
+ $from_0_be = $add_ptr55;
+ label = 10;
+ break;
+ case 9:
+ $incdec_ptr56 = $from_041 + 1 | 0;
+ $conv57 = $3 << 24 >> 24;
+ $incdec_ptr58 = $to_042 + 2 | 0;
+ HEAP16[$to_042 >> 1] = $conv57;
+ $to_0_be = $incdec_ptr58;
+ $from_0_be = $incdec_ptr56;
+ label = 10;
+ break;
+ case 10:
+ $cmp = ($from_0_be | 0) == ($fromLim | 0);
+ $cmp1 = ($to_0_be | 0) == ($toLim | 0);
+ $or_cond = $cmp | $cmp1;
+ if ($or_cond) {
+ $from_0_lcssa = $from_0_be;
+ $to_0_lcssa = $to_0_be;
+ label = 11;
+ break;
+ } else {
+ $from_041 = $from_0_be;
+ $to_042 = $to_0_be;
+ label = 4;
+ break;
+ }
+ case 11:
+ HEAP32[$fromP >> 2] = $from_0_lcssa;
+ HEAP32[$toP >> 2] = $to_0_lcssa;
+ return;
+ }
+}
+function _utf8_isName2($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $conv = 0, $conv8 = 0;
+ $conv = HEAPU8[$p] | 0;
+ $conv8 = HEAPU8[$p + 1 | 0] | 0;
+ return 1 << ($conv8 & 31) & HEAP32[9544 + (((HEAPU8[10824 + ($conv >>> 2 & 7) | 0] | 0) << 3 | $conv << 1 & 6 | $conv8 >>> 5 & 1) << 2) >> 2] | 0;
+}
+function _utf8_isName3($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $conv2 = 0, $conv13 = 0;
+ $conv2 = HEAPU8[$p + 1 | 0] | 0;
+ $conv13 = HEAPU8[$p + 2 | 0] | 0;
+ return 1 << ($conv13 & 31) & HEAP32[9544 + (((HEAPU8[10824 + ($conv2 >>> 2 & 15 | (HEAPU8[$p] | 0) << 4 & 240) | 0] | 0) << 3 | $conv2 << 1 & 6 | $conv13 >>> 5 & 1) << 2) >> 2] | 0;
+}
+function _utf8_isNmstrt2($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $conv = 0, $conv8 = 0;
+ $conv = HEAPU8[$p] | 0;
+ $conv8 = HEAPU8[$p + 1 | 0] | 0;
+ return 1 << ($conv8 & 31) & HEAP32[9544 + (((HEAPU8[9272 + ($conv >>> 2 & 7) | 0] | 0) << 3 | $conv << 1 & 6 | $conv8 >>> 5 & 1) << 2) >> 2] | 0;
+}
+function _utf8_isNmstrt3($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $conv2 = 0, $conv13 = 0;
+ $conv2 = HEAPU8[$p + 1 | 0] | 0;
+ $conv13 = HEAPU8[$p + 2 | 0] | 0;
+ return 1 << ($conv13 & 31) & HEAP32[9544 + (((HEAPU8[9272 + ($conv2 >>> 2 & 15 | (HEAPU8[$p] | 0) << 4 & 240) | 0] | 0) << 3 | $conv2 << 1 & 6 | $conv13 >>> 5 & 1) << 2) >> 2] | 0;
+}
+function _utf8_isInvalid2($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $0 = 0, $cmp = 0, $arrayidx = 0, $1 = 0, $conv2 = 0, $and = 0, $cmp3 = 0, $and7 = 0, $cmp8 = 0, $phitmp = 0, $2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP8[$p] | 0;
+ $cmp = ($0 & 255) < 194;
+ if ($cmp) {
+ $2 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx = $p + 1 | 0;
+ $1 = HEAP8[$arrayidx] | 0;
+ $conv2 = $1 & 255;
+ $and = $conv2 & 128;
+ $cmp3 = ($and | 0) == 0;
+ if ($cmp3) {
+ $2 = 1;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $and7 = $conv2 & 192;
+ $cmp8 = ($and7 | 0) == 192;
+ $phitmp = $cmp8 & 1;
+ $2 = $phitmp;
+ label = 5;
+ break;
+ case 5:
+ return $2 | 0;
+ }
+ return 0;
+}
+function _utf8_isInvalid3($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $arrayidx = 0, $0 = 0, $cmp = 0, $1 = 0, $cmp3 = 0, $arrayidx5 = 0, $2 = 0, $cmp7 = 0, $cmp11 = 0, $3 = 0, $and15 = 0, $cmp16 = 0, $4 = 0, $cmp19 = 0, $arrayidx22 = 0, $5 = 0, $conv23 = 0, $cmp24 = 0, $and29 = 0, $cmp30 = 0, $and35 = 0, $cmp36 = 0, $cmp40 = 0, $cmp45 = 0, $and50 = 0, $cmp51 = 0, $6 = 0, $lor_ext59 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $arrayidx = $p + 2 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $cmp = $0 << 24 >> 24 > -1;
+ if ($cmp) {
+ $6 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = HEAP8[$p] | 0;
+ $cmp3 = $1 << 24 >> 24 == -17;
+ if ($cmp3) {
+ label = 4;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 4:
+ $arrayidx5 = $p + 1 | 0;
+ $2 = HEAP8[$arrayidx5] | 0;
+ $cmp7 = $2 << 24 >> 24 == -65;
+ if ($cmp7) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $cmp11 = ($0 & 255) > 189;
+ if ($cmp11) {
+ $6 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $3 = HEAP8[$arrayidx] | 0;
+ $and15 = $3 & -64;
+ $cmp16 = $and15 << 24 >> 24 == -64;
+ if ($cmp16) {
+ $6 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $4 = HEAP8[$p] | 0;
+ $cmp19 = $4 << 24 >> 24 == -32;
+ $arrayidx22 = $p + 1 | 0;
+ $5 = HEAP8[$arrayidx22] | 0;
+ $conv23 = $5 & 255;
+ if ($cmp19) {
+ label = 8;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 8:
+ $cmp24 = ($5 & 255) < 160;
+ if ($cmp24) {
+ $6 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $and29 = $conv23 & 192;
+ $cmp30 = ($and29 | 0) == 192;
+ $6 = $cmp30;
+ label = 14;
+ break;
+ case 10:
+ $and35 = $conv23 & 128;
+ $cmp36 = ($and35 | 0) == 0;
+ if ($cmp36) {
+ $6 = 1;
+ label = 14;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $cmp40 = $4 << 24 >> 24 == -19;
+ if ($cmp40) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ $cmp45 = ($5 & 255) > 159;
+ $6 = $cmp45;
+ label = 14;
+ break;
+ case 13:
+ $and50 = $conv23 & 192;
+ $cmp51 = ($and50 | 0) == 192;
+ $6 = $cmp51;
+ label = 14;
+ break;
+ case 14:
+ $lor_ext59 = $6 & 1;
+ return $lor_ext59 | 0;
+ }
+ return 0;
+}
+function _utf8_isInvalid4($enc, $p) {
+ $enc = $enc | 0;
+ $p = $p | 0;
+ var $arrayidx = 0, $0 = 0, $conv = 0, $and = 0, $cmp = 0, $and4 = 0, $cmp5 = 0, $or_cond = 0, $arrayidx8 = 0, $1 = 0, $conv9 = 0, $and10 = 0, $cmp11 = 0, $and16 = 0, $cmp17 = 0, $or_cond9 = 0, $2 = 0, $cmp20 = 0, $arrayidx22 = 0, $3 = 0, $conv23 = 0, $cmp24 = 0, $and29 = 0, $cmp30 = 0, $and34 = 0, $cmp35 = 0, $cmp39 = 0, $cmp44 = 0, $and49 = 0, $cmp50 = 0, $4 = 0, $lor_ext58 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $arrayidx = $p + 3 | 0;
+ $0 = HEAP8[$arrayidx] | 0;
+ $conv = $0 & 255;
+ $and = $conv & 128;
+ $cmp = ($and | 0) == 0;
+ $and4 = $conv & 192;
+ $cmp5 = ($and4 | 0) == 192;
+ $or_cond = $cmp | $cmp5;
+ if ($or_cond) {
+ $4 = 1;
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $arrayidx8 = $p + 2 | 0;
+ $1 = HEAP8[$arrayidx8] | 0;
+ $conv9 = $1 & 255;
+ $and10 = $conv9 & 128;
+ $cmp11 = ($and10 | 0) == 0;
+ $and16 = $conv9 & 192;
+ $cmp17 = ($and16 | 0) == 192;
+ $or_cond9 = $cmp11 | $cmp17;
+ if ($or_cond9) {
+ $4 = 1;
+ label = 11;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $2 = HEAP8[$p] | 0;
+ $cmp20 = $2 << 24 >> 24 == -16;
+ $arrayidx22 = $p + 1 | 0;
+ $3 = HEAP8[$arrayidx22] | 0;
+ $conv23 = $3 & 255;
+ if ($cmp20) {
+ label = 5;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 5:
+ $cmp24 = ($3 & 255) < 144;
+ if ($cmp24) {
+ $4 = 1;
+ label = 11;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $and29 = $conv23 & 192;
+ $cmp30 = ($and29 | 0) == 192;
+ $4 = $cmp30;
+ label = 11;
+ break;
+ case 7:
+ $and34 = $conv23 & 128;
+ $cmp35 = ($and34 | 0) == 0;
+ if ($cmp35) {
+ $4 = 1;
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $cmp39 = $2 << 24 >> 24 == -12;
+ if ($cmp39) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $cmp44 = ($3 & 255) > 143;
+ $4 = $cmp44;
+ label = 11;
+ break;
+ case 10:
+ $and49 = $conv23 & 192;
+ $cmp50 = ($and49 | 0) == 192;
+ $4 = $cmp50;
+ label = 11;
+ break;
+ case 11:
+ $lor_ext58 = $4 & 1;
+ return $lor_ext58 | 0;
+ }
+ return 0;
+}
+function _normal_scanRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $ptr_addr_0_ph = 0, $cmp3969 = 0, $sub_ptr_lhs_cast49 = 0, $3 = 0, $sub_ptr_lhs_cast62 = 0, $isName3 = 0, $sub_ptr_lhs_cast75 = 0, $isName4 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp3 = 0, $isNmstrt2 = 0, $4 = 0, $5 = 0, $call = 0, $tobool = 0, $add_ptr9 = 0, $sub_ptr_lhs_cast11 = 0, $sub_ptr_rhs_cast12 = 0, $sub_ptr_sub13 = 0, $cmp14 = 0, $isNmstrt3 = 0, $6 = 0, $7 = 0, $call18 = 0, $tobool19 = 0, $add_ptr22 = 0, $sub_ptr_lhs_cast24 = 0, $sub_ptr_rhs_cast25 = 0, $sub_ptr_sub26 = 0, $cmp27 = 0, $isNmstrt4 = 0, $8 = 0, $9 = 0, $call31 = 0, $tobool32 = 0, $add_ptr35 = 0, $add_ptr37 = 0, $call38 = 0, $ptr_addr_070 = 0, $10 = 0, $idxprom41 = 0, $arrayidx43 = 0, $11 = 0, $conv44 = 0, $add_ptr47 = 0, $sub_ptr_rhs_cast50 = 0, $sub_ptr_sub51 = 0, $cmp52 = 0, $12 = 0, $call56 = 0, $tobool57 = 0, $add_ptr60 = 0, $sub_ptr_rhs_cast63 = 0, $sub_ptr_sub64 = 0, $cmp65 = 0, $13 = 0, $14 = 0, $call69 = 0, $tobool70 = 0, $add_ptr73 = 0, $sub_ptr_rhs_cast76 = 0, $sub_ptr_sub77 = 0, $cmp78 = 0, $15 = 0, $16 = 0, $call82 = 0, $tobool83 = 0, $add_ptr86 = 0, $ptr_addr_0_be = 0, $cmp39 = 0, $add_ptr88 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 40;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 29) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 16;
+ break;
+ } else if (($conv | 0) == 19) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 4:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $ptr_addr_0_ph = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $cmp3969 = ($ptr_addr_0_ph | 0) == ($end | 0);
+ if ($cmp3969) {
+ $retval_0 = -1;
+ label = 40;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub_ptr_lhs_cast49 = $end;
+ $3 = $enc + 328 | 0;
+ $sub_ptr_lhs_cast62 = $end;
+ $isName3 = $enc + 332 | 0;
+ $sub_ptr_lhs_cast75 = $end;
+ $isName4 = $enc + 336 | 0;
+ $ptr_addr_070 = $ptr_addr_0_ph;
+ label = 22;
+ break;
+ case 8:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp3 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp3) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $isNmstrt2 = $enc + 340 | 0;
+ $4 = HEAP32[$isNmstrt2 >> 2] | 0;
+ $5 = $4;
+ $call = FUNCTION_TABLE_iii[$5 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 11:
+ $add_ptr9 = $ptr + 2 | 0;
+ $ptr_addr_0_ph = $add_ptr9;
+ label = 6;
+ break;
+ case 12:
+ $sub_ptr_lhs_cast11 = $end;
+ $sub_ptr_rhs_cast12 = $ptr;
+ $sub_ptr_sub13 = $sub_ptr_lhs_cast11 - $sub_ptr_rhs_cast12 | 0;
+ $cmp14 = ($sub_ptr_sub13 | 0) < 3;
+ if ($cmp14) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $isNmstrt3 = $enc + 344 | 0;
+ $6 = HEAP32[$isNmstrt3 >> 2] | 0;
+ $7 = $6;
+ $call18 = FUNCTION_TABLE_iii[$7 & 1023]($enc, $ptr) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 15:
+ $add_ptr22 = $ptr + 3 | 0;
+ $ptr_addr_0_ph = $add_ptr22;
+ label = 6;
+ break;
+ case 16:
+ $sub_ptr_lhs_cast24 = $end;
+ $sub_ptr_rhs_cast25 = $ptr;
+ $sub_ptr_sub26 = $sub_ptr_lhs_cast24 - $sub_ptr_rhs_cast25 | 0;
+ $cmp27 = ($sub_ptr_sub26 | 0) < 4;
+ if ($cmp27) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $isNmstrt4 = $enc + 348 | 0;
+ $8 = HEAP32[$isNmstrt4 >> 2] | 0;
+ $9 = $8;
+ $call31 = FUNCTION_TABLE_iii[$9 & 1023]($enc, $ptr) | 0;
+ $tobool32 = ($call31 | 0) == 0;
+ if ($tobool32) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 19:
+ $add_ptr35 = $ptr + 4 | 0;
+ $ptr_addr_0_ph = $add_ptr35;
+ label = 6;
+ break;
+ case 20:
+ $add_ptr37 = $ptr + 1 | 0;
+ $call38 = _normal_scanCharRef($enc, $add_ptr37, $end, $nextTokPtr) | 0;
+ $retval_0 = $call38;
+ label = 40;
+ break;
+ case 21:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 22:
+ $10 = HEAP8[$ptr_addr_070] | 0;
+ $idxprom41 = $10 & 255;
+ $arrayidx43 = $1 + $idxprom41 | 0;
+ $11 = HEAP8[$arrayidx43] | 0;
+ $conv44 = $11 & 255;
+ if (($conv44 | 0) == 29) {
+ label = 23;
+ break;
+ } else if (($conv44 | 0) == 22 | ($conv44 | 0) == 24 | ($conv44 | 0) == 25 | ($conv44 | 0) == 26 | ($conv44 | 0) == 27) {
+ label = 24;
+ break;
+ } else if (($conv44 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($conv44 | 0) == 6) {
+ label = 29;
+ break;
+ } else if (($conv44 | 0) == 7) {
+ label = 33;
+ break;
+ } else if (($conv44 | 0) == 18) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 23:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 24:
+ $add_ptr47 = $ptr_addr_070 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr47;
+ label = 37;
+ break;
+ case 25:
+ $sub_ptr_rhs_cast50 = $ptr_addr_070;
+ $sub_ptr_sub51 = $sub_ptr_lhs_cast49 - $sub_ptr_rhs_cast50 | 0;
+ $cmp52 = ($sub_ptr_sub51 | 0) < 2;
+ if ($cmp52) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $12 = HEAP32[$3 >> 2] | 0;
+ $call56 = FUNCTION_TABLE_iii[$12 & 1023]($enc, $ptr_addr_070) | 0;
+ $tobool57 = ($call56 | 0) == 0;
+ if ($tobool57) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 28:
+ $add_ptr60 = $ptr_addr_070 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr60;
+ label = 37;
+ break;
+ case 29:
+ $sub_ptr_rhs_cast63 = $ptr_addr_070;
+ $sub_ptr_sub64 = $sub_ptr_lhs_cast62 - $sub_ptr_rhs_cast63 | 0;
+ $cmp65 = ($sub_ptr_sub64 | 0) < 3;
+ if ($cmp65) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $13 = HEAP32[$isName3 >> 2] | 0;
+ $14 = $13;
+ $call69 = FUNCTION_TABLE_iii[$14 & 1023]($enc, $ptr_addr_070) | 0;
+ $tobool70 = ($call69 | 0) == 0;
+ if ($tobool70) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 32:
+ $add_ptr73 = $ptr_addr_070 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr73;
+ label = 37;
+ break;
+ case 33:
+ $sub_ptr_rhs_cast76 = $ptr_addr_070;
+ $sub_ptr_sub77 = $sub_ptr_lhs_cast75 - $sub_ptr_rhs_cast76 | 0;
+ $cmp78 = ($sub_ptr_sub77 | 0) < 4;
+ if ($cmp78) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $15 = HEAP32[$isName4 >> 2] | 0;
+ $16 = $15;
+ $call82 = FUNCTION_TABLE_iii[$16 & 1023]($enc, $ptr_addr_070) | 0;
+ $tobool83 = ($call82 | 0) == 0;
+ if ($tobool83) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 36:
+ $add_ptr86 = $ptr_addr_070 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr86;
+ label = 37;
+ break;
+ case 37:
+ $cmp39 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp39) {
+ $retval_0 = -1;
+ label = 40;
+ break;
+ } else {
+ $ptr_addr_070 = $ptr_addr_0_be;
+ label = 22;
+ break;
+ }
+ case 38:
+ $add_ptr88 = $ptr_addr_070 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr88;
+ $retval_0 = 9;
+ label = 40;
+ break;
+ case 39:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_070;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 40:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanPercent($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $ptr_addr_0_ph = 0, $cmp3767 = 0, $sub_ptr_lhs_cast47 = 0, $3 = 0, $sub_ptr_lhs_cast60 = 0, $isName3 = 0, $sub_ptr_lhs_cast73 = 0, $isName4 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp3 = 0, $isNmstrt2 = 0, $4 = 0, $5 = 0, $call = 0, $tobool = 0, $add_ptr9 = 0, $sub_ptr_lhs_cast11 = 0, $sub_ptr_rhs_cast12 = 0, $sub_ptr_sub13 = 0, $cmp14 = 0, $isNmstrt3 = 0, $6 = 0, $7 = 0, $call18 = 0, $tobool19 = 0, $add_ptr22 = 0, $sub_ptr_lhs_cast24 = 0, $sub_ptr_rhs_cast25 = 0, $sub_ptr_sub26 = 0, $cmp27 = 0, $isNmstrt4 = 0, $8 = 0, $9 = 0, $call31 = 0, $tobool32 = 0, $add_ptr35 = 0, $ptr_addr_068 = 0, $10 = 0, $idxprom39 = 0, $arrayidx41 = 0, $11 = 0, $conv42 = 0, $add_ptr45 = 0, $sub_ptr_rhs_cast48 = 0, $sub_ptr_sub49 = 0, $cmp50 = 0, $12 = 0, $call54 = 0, $tobool55 = 0, $add_ptr58 = 0, $sub_ptr_rhs_cast61 = 0, $sub_ptr_sub62 = 0, $cmp63 = 0, $13 = 0, $14 = 0, $call67 = 0, $tobool68 = 0, $add_ptr71 = 0, $sub_ptr_rhs_cast74 = 0, $sub_ptr_sub75 = 0, $cmp76 = 0, $15 = 0, $16 = 0, $call80 = 0, $tobool81 = 0, $add_ptr84 = 0, $ptr_addr_0_be = 0, $cmp37 = 0, $add_ptr86 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 40;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 29) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 16;
+ break;
+ } else if (($conv | 0) == 21 | ($conv | 0) == 10 | ($conv | 0) == 9 | ($conv | 0) == 30) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 4:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $ptr_addr_0_ph = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $cmp3767 = ($ptr_addr_0_ph | 0) == ($end | 0);
+ if ($cmp3767) {
+ $retval_0 = -1;
+ label = 40;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub_ptr_lhs_cast47 = $end;
+ $3 = $enc + 328 | 0;
+ $sub_ptr_lhs_cast60 = $end;
+ $isName3 = $enc + 332 | 0;
+ $sub_ptr_lhs_cast73 = $end;
+ $isName4 = $enc + 336 | 0;
+ $ptr_addr_068 = $ptr_addr_0_ph;
+ label = 22;
+ break;
+ case 8:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp3 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp3) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $isNmstrt2 = $enc + 340 | 0;
+ $4 = HEAP32[$isNmstrt2 >> 2] | 0;
+ $5 = $4;
+ $call = FUNCTION_TABLE_iii[$5 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 11:
+ $add_ptr9 = $ptr + 2 | 0;
+ $ptr_addr_0_ph = $add_ptr9;
+ label = 6;
+ break;
+ case 12:
+ $sub_ptr_lhs_cast11 = $end;
+ $sub_ptr_rhs_cast12 = $ptr;
+ $sub_ptr_sub13 = $sub_ptr_lhs_cast11 - $sub_ptr_rhs_cast12 | 0;
+ $cmp14 = ($sub_ptr_sub13 | 0) < 3;
+ if ($cmp14) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $isNmstrt3 = $enc + 344 | 0;
+ $6 = HEAP32[$isNmstrt3 >> 2] | 0;
+ $7 = $6;
+ $call18 = FUNCTION_TABLE_iii[$7 & 1023]($enc, $ptr) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 15:
+ $add_ptr22 = $ptr + 3 | 0;
+ $ptr_addr_0_ph = $add_ptr22;
+ label = 6;
+ break;
+ case 16:
+ $sub_ptr_lhs_cast24 = $end;
+ $sub_ptr_rhs_cast25 = $ptr;
+ $sub_ptr_sub26 = $sub_ptr_lhs_cast24 - $sub_ptr_rhs_cast25 | 0;
+ $cmp27 = ($sub_ptr_sub26 | 0) < 4;
+ if ($cmp27) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $isNmstrt4 = $enc + 348 | 0;
+ $8 = HEAP32[$isNmstrt4 >> 2] | 0;
+ $9 = $8;
+ $call31 = FUNCTION_TABLE_iii[$9 & 1023]($enc, $ptr) | 0;
+ $tobool32 = ($call31 | 0) == 0;
+ if ($tobool32) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 19:
+ $add_ptr35 = $ptr + 4 | 0;
+ $ptr_addr_0_ph = $add_ptr35;
+ label = 6;
+ break;
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 22;
+ label = 40;
+ break;
+ case 21:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 22:
+ $10 = HEAP8[$ptr_addr_068] | 0;
+ $idxprom39 = $10 & 255;
+ $arrayidx41 = $1 + $idxprom39 | 0;
+ $11 = HEAP8[$arrayidx41] | 0;
+ $conv42 = $11 & 255;
+ if (($conv42 | 0) == 29) {
+ label = 23;
+ break;
+ } else if (($conv42 | 0) == 22 | ($conv42 | 0) == 24 | ($conv42 | 0) == 25 | ($conv42 | 0) == 26 | ($conv42 | 0) == 27) {
+ label = 24;
+ break;
+ } else if (($conv42 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($conv42 | 0) == 6) {
+ label = 29;
+ break;
+ } else if (($conv42 | 0) == 7) {
+ label = 33;
+ break;
+ } else if (($conv42 | 0) == 18) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 23:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_068;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 24:
+ $add_ptr45 = $ptr_addr_068 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr45;
+ label = 37;
+ break;
+ case 25:
+ $sub_ptr_rhs_cast48 = $ptr_addr_068;
+ $sub_ptr_sub49 = $sub_ptr_lhs_cast47 - $sub_ptr_rhs_cast48 | 0;
+ $cmp50 = ($sub_ptr_sub49 | 0) < 2;
+ if ($cmp50) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $12 = HEAP32[$3 >> 2] | 0;
+ $call54 = FUNCTION_TABLE_iii[$12 & 1023]($enc, $ptr_addr_068) | 0;
+ $tobool55 = ($call54 | 0) == 0;
+ if ($tobool55) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_068;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 28:
+ $add_ptr58 = $ptr_addr_068 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr58;
+ label = 37;
+ break;
+ case 29:
+ $sub_ptr_rhs_cast61 = $ptr_addr_068;
+ $sub_ptr_sub62 = $sub_ptr_lhs_cast60 - $sub_ptr_rhs_cast61 | 0;
+ $cmp63 = ($sub_ptr_sub62 | 0) < 3;
+ if ($cmp63) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $13 = HEAP32[$isName3 >> 2] | 0;
+ $14 = $13;
+ $call67 = FUNCTION_TABLE_iii[$14 & 1023]($enc, $ptr_addr_068) | 0;
+ $tobool68 = ($call67 | 0) == 0;
+ if ($tobool68) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_068;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 32:
+ $add_ptr71 = $ptr_addr_068 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr71;
+ label = 37;
+ break;
+ case 33:
+ $sub_ptr_rhs_cast74 = $ptr_addr_068;
+ $sub_ptr_sub75 = $sub_ptr_lhs_cast73 - $sub_ptr_rhs_cast74 | 0;
+ $cmp76 = ($sub_ptr_sub75 | 0) < 4;
+ if ($cmp76) {
+ $retval_0 = -2;
+ label = 40;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $15 = HEAP32[$isName4 >> 2] | 0;
+ $16 = $15;
+ $call80 = FUNCTION_TABLE_iii[$16 & 1023]($enc, $ptr_addr_068) | 0;
+ $tobool81 = ($call80 | 0) == 0;
+ if ($tobool81) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_068;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 36:
+ $add_ptr84 = $ptr_addr_068 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr84;
+ label = 37;
+ break;
+ case 37:
+ $cmp37 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp37) {
+ $retval_0 = -1;
+ label = 40;
+ break;
+ } else {
+ $ptr_addr_068 = $ptr_addr_0_be;
+ label = 22;
+ break;
+ }
+ case 38:
+ $add_ptr86 = $ptr_addr_068 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr86;
+ $retval_0 = 28;
+ label = 40;
+ break;
+ case 39:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_068;
+ $retval_0 = 0;
+ label = 40;
+ break;
+ case 40:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanHexCharRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $conv_off = 0, $switch = 0, $ptr_addr_016 = 0, $cmp117 = 0, $ptr_addr_019 = 0, $ptr_pn18 = 0, $3 = 0, $idxprom3 = 0, $arrayidx5 = 0, $4 = 0, $conv6 = 0, $ptr_addr_0 = 0, $cmp1 = 0, $add_ptr9 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 10;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ $conv_off = $conv - 24 | 0;
+ $switch = $conv_off >>> 0 < 2;
+ if ($switch) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $ptr_addr_016 = $ptr + 1 | 0;
+ $cmp117 = ($ptr_addr_016 | 0) == ($end | 0);
+ if ($cmp117) {
+ $retval_0 = -1;
+ label = 10;
+ break;
+ } else {
+ $ptr_pn18 = $ptr;
+ $ptr_addr_019 = $ptr_addr_016;
+ label = 6;
+ break;
+ }
+ case 5:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 10;
+ break;
+ case 6:
+ $3 = HEAP8[$ptr_addr_019] | 0;
+ $idxprom3 = $3 & 255;
+ $arrayidx5 = $1 + $idxprom3 | 0;
+ $4 = HEAP8[$arrayidx5] | 0;
+ $conv6 = $4 & 255;
+ if (($conv6 | 0) == 25 | ($conv6 | 0) == 24) {
+ label = 7;
+ break;
+ } else if (($conv6 | 0) == 18) {
+ label = 8;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 7:
+ $ptr_addr_0 = $ptr_addr_019 + 1 | 0;
+ $cmp1 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp1) {
+ $retval_0 = -1;
+ label = 10;
+ break;
+ } else {
+ $ptr_pn18 = $ptr_addr_019;
+ $ptr_addr_019 = $ptr_addr_0;
+ label = 6;
+ break;
+ }
+ case 8:
+ $add_ptr9 = $ptr_pn18 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr9;
+ $retval_0 = 10;
+ label = 10;
+ break;
+ case 9:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_019;
+ $retval_0 = 0;
+ label = 10;
+ break;
+ case 10:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanCdataSection($ptr, $end, $nextTokPtr) {
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp = 0, $0 = 0, $cmp3 = 0, $ptr_addr_02_lcssa = 0, $add_ptr = 0, $1 = 0, $cmp3_1 = 0, $retval_0 = 0, $add_ptr_1 = 0, $2 = 0, $cmp3_2 = 0, $add_ptr_2 = 0, $3 = 0, $cmp3_3 = 0, $add_ptr_3 = 0, $4 = 0, $cmp3_4 = 0, $add_ptr_4 = 0, $5 = 0, $cmp3_5 = 0, $add_ptr_5 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp = ($sub_ptr_sub | 0) < 6;
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp3 = $0 << 24 >> 24 == 67;
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $ptr;
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_02_lcssa;
+ $retval_0 = 0;
+ label = 6;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $1 = HEAP8[$add_ptr] | 0;
+ $cmp3_1 = $1 << 24 >> 24 == 68;
+ if ($cmp3_1) {
+ label = 7;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr;
+ label = 4;
+ break;
+ }
+ case 6:
+ return $retval_0 | 0;
+ case 7:
+ $add_ptr_1 = $ptr + 2 | 0;
+ $2 = HEAP8[$add_ptr_1] | 0;
+ $cmp3_2 = $2 << 24 >> 24 == 65;
+ if ($cmp3_2) {
+ label = 8;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_1;
+ label = 4;
+ break;
+ }
+ case 8:
+ $add_ptr_2 = $ptr + 3 | 0;
+ $3 = HEAP8[$add_ptr_2] | 0;
+ $cmp3_3 = $3 << 24 >> 24 == 84;
+ if ($cmp3_3) {
+ label = 9;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_2;
+ label = 4;
+ break;
+ }
+ case 9:
+ $add_ptr_3 = $ptr + 4 | 0;
+ $4 = HEAP8[$add_ptr_3] | 0;
+ $cmp3_4 = $4 << 24 >> 24 == 65;
+ if ($cmp3_4) {
+ label = 10;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_3;
+ label = 4;
+ break;
+ }
+ case 10:
+ $add_ptr_4 = $ptr + 5 | 0;
+ $5 = HEAP8[$add_ptr_4] | 0;
+ $cmp3_5 = $5 << 24 >> 24 == 91;
+ if ($cmp3_5) {
+ label = 11;
+ break;
+ } else {
+ $ptr_addr_02_lcssa = $add_ptr_4;
+ label = 4;
+ break;
+ }
+ case 11:
+ $add_ptr_5 = $ptr + 6 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr_5;
+ $retval_0 = 8;
+ label = 6;
+ break;
+ }
+ return 0;
+}
+function _normal_scanCharRef($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $add_ptr = 0, $call = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $cond = 0, $ptr_pn = 0, $ptr_addr_0 = 0, $cmp6 = 0, $3 = 0, $idxprom8 = 0, $arrayidx10 = 0, $4 = 0, $conv11 = 0, $add_ptr14 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 11;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 120;
+ if ($cmp1) {
+ label = 4;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 4:
+ $add_ptr = $ptr + 1 | 0;
+ $call = _normal_scanHexCharRef($enc, $add_ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 11;
+ break;
+ case 5:
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $cond = $2 << 24 >> 24 == 25;
+ if ($cond) {
+ $ptr_pn = $ptr;
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 11;
+ break;
+ case 7:
+ $ptr_addr_0 = $ptr_pn + 1 | 0;
+ $cmp6 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp6) {
+ $retval_0 = -1;
+ label = 11;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $3 = HEAP8[$ptr_addr_0] | 0;
+ $idxprom8 = $3 & 255;
+ $arrayidx10 = $1 + $idxprom8 | 0;
+ $4 = HEAP8[$arrayidx10] | 0;
+ $conv11 = $4 & 255;
+ if (($conv11 | 0) == 25) {
+ $ptr_pn = $ptr_addr_0;
+ label = 7;
+ break;
+ } else if (($conv11 | 0) == 18) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $add_ptr14 = $ptr_pn + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr14;
+ $retval_0 = 10;
+ label = 11;
+ break;
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0;
+ $retval_0 = 0;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanLt($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $ptr_addr_0_ph = 0, $cmp59155 = 0, $sub_ptr_lhs_cast69 = 0, $3 = 0, $sub_ptr_lhs_cast82 = 0, $isName3 = 0, $sub_ptr_lhs_cast95 = 0, $isName4 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp3 = 0, $isNmstrt2 = 0, $4 = 0, $5 = 0, $call = 0, $tobool = 0, $add_ptr9 = 0, $sub_ptr_lhs_cast11 = 0, $sub_ptr_rhs_cast12 = 0, $sub_ptr_sub13 = 0, $cmp14 = 0, $isNmstrt3 = 0, $6 = 0, $7 = 0, $call18 = 0, $tobool19 = 0, $add_ptr22 = 0, $sub_ptr_lhs_cast24 = 0, $sub_ptr_rhs_cast25 = 0, $sub_ptr_sub26 = 0, $cmp27 = 0, $isNmstrt4 = 0, $8 = 0, $9 = 0, $call31 = 0, $tobool32 = 0, $add_ptr35 = 0, $add_ptr37 = 0, $cmp38 = 0, $10 = 0, $idxprom42 = 0, $arrayidx44 = 0, $11 = 0, $conv45 = 0, $add_ptr47 = 0, $call48 = 0, $add_ptr50 = 0, $call51 = 0, $add_ptr53 = 0, $call54 = 0, $add_ptr56 = 0, $call57 = 0, $ptr_addr_0156 = 0, $12 = 0, $idxprom61 = 0, $arrayidx63 = 0, $13 = 0, $conv64 = 0, $ptr_addr_1140 = 0, $cmp110141 = 0, $add_ptr67 = 0, $sub_ptr_rhs_cast70 = 0, $sub_ptr_sub71 = 0, $cmp72 = 0, $14 = 0, $call76 = 0, $tobool77 = 0, $add_ptr80 = 0, $sub_ptr_rhs_cast83 = 0, $sub_ptr_sub84 = 0, $cmp85 = 0, $15 = 0, $16 = 0, $call89 = 0, $tobool90 = 0, $add_ptr93 = 0, $sub_ptr_rhs_cast96 = 0, $sub_ptr_sub97 = 0, $cmp98 = 0, $17 = 0, $18 = 0, $call102 = 0, $tobool103 = 0, $add_ptr106 = 0, $ptr_addr_0_be = 0, $cmp59 = 0, $ptr_addr_1143 = 0, $ptr_addr_0_pn142 = 0, $19 = 0, $idxprom113 = 0, $arrayidx115 = 0, $20 = 0, $conv116 = 0, $ptr_addr_1 = 0, $cmp110 = 0, $add_ptr119 = 0, $sub_ptr_lhs_cast121 = 0, $sub_ptr_rhs_cast122 = 0, $sub_ptr_sub123 = 0, $cmp124 = 0, $isNmstrt2128 = 0, $21 = 0, $22 = 0, $call129 = 0, $tobool130 = 0, $add_ptr133 = 0, $sub_ptr_lhs_cast135 = 0, $sub_ptr_rhs_cast136 = 0, $sub_ptr_sub137 = 0, $cmp138 = 0, $isNmstrt3142 = 0, $23 = 0, $24 = 0, $call143 = 0, $tobool144 = 0, $add_ptr147 = 0, $sub_ptr_lhs_cast149 = 0, $sub_ptr_rhs_cast150 = 0, $sub_ptr_sub151 = 0, $cmp152 = 0, $isNmstrt4156 = 0, $25 = 0, $26 = 0, $call157 = 0, $tobool158 = 0, $add_ptr161 = 0, $ptr_addr_2 = 0, $call168 = 0, $ptr_addr_3 = 0, $add_ptr170 = 0, $ptr_addr_4 = 0, $add_ptr172 = 0, $cmp173 = 0, $27 = 0, $cmp178 = 0, $add_ptr182 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 69;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 29) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 16;
+ break;
+ } else if (($conv | 0) == 16) {
+ label = 20;
+ break;
+ } else if (($conv | 0) == 15) {
+ label = 25;
+ break;
+ } else if (($conv | 0) == 17) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 4:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $ptr_addr_0_ph = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $cmp59155 = ($ptr_addr_0_ph | 0) == ($end | 0);
+ if ($cmp59155) {
+ $retval_0 = -1;
+ label = 69;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub_ptr_lhs_cast69 = $end;
+ $3 = $enc + 328 | 0;
+ $sub_ptr_lhs_cast82 = $end;
+ $isName3 = $enc + 332 | 0;
+ $sub_ptr_lhs_cast95 = $end;
+ $isName4 = $enc + 336 | 0;
+ $ptr_addr_0156 = $ptr_addr_0_ph;
+ label = 28;
+ break;
+ case 8:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp3 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp3) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $isNmstrt2 = $enc + 340 | 0;
+ $4 = HEAP32[$isNmstrt2 >> 2] | 0;
+ $5 = $4;
+ $call = FUNCTION_TABLE_iii[$5 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 11:
+ $add_ptr9 = $ptr + 2 | 0;
+ $ptr_addr_0_ph = $add_ptr9;
+ label = 6;
+ break;
+ case 12:
+ $sub_ptr_lhs_cast11 = $end;
+ $sub_ptr_rhs_cast12 = $ptr;
+ $sub_ptr_sub13 = $sub_ptr_lhs_cast11 - $sub_ptr_rhs_cast12 | 0;
+ $cmp14 = ($sub_ptr_sub13 | 0) < 3;
+ if ($cmp14) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $isNmstrt3 = $enc + 344 | 0;
+ $6 = HEAP32[$isNmstrt3 >> 2] | 0;
+ $7 = $6;
+ $call18 = FUNCTION_TABLE_iii[$7 & 1023]($enc, $ptr) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 15:
+ $add_ptr22 = $ptr + 3 | 0;
+ $ptr_addr_0_ph = $add_ptr22;
+ label = 6;
+ break;
+ case 16:
+ $sub_ptr_lhs_cast24 = $end;
+ $sub_ptr_rhs_cast25 = $ptr;
+ $sub_ptr_sub26 = $sub_ptr_lhs_cast24 - $sub_ptr_rhs_cast25 | 0;
+ $cmp27 = ($sub_ptr_sub26 | 0) < 4;
+ if ($cmp27) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $isNmstrt4 = $enc + 348 | 0;
+ $8 = HEAP32[$isNmstrt4 >> 2] | 0;
+ $9 = $8;
+ $call31 = FUNCTION_TABLE_iii[$9 & 1023]($enc, $ptr) | 0;
+ $tobool32 = ($call31 | 0) == 0;
+ if ($tobool32) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 19:
+ $add_ptr35 = $ptr + 4 | 0;
+ $ptr_addr_0_ph = $add_ptr35;
+ label = 6;
+ break;
+ case 20:
+ $add_ptr37 = $ptr + 1 | 0;
+ $cmp38 = ($add_ptr37 | 0) == ($end | 0);
+ if ($cmp38) {
+ $retval_0 = -1;
+ label = 69;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $10 = HEAP8[$add_ptr37] | 0;
+ $idxprom42 = $10 & 255;
+ $arrayidx44 = $1 + $idxprom42 | 0;
+ $11 = HEAP8[$arrayidx44] | 0;
+ $conv45 = $11 & 255;
+ if (($conv45 | 0) == 27) {
+ label = 22;
+ break;
+ } else if (($conv45 | 0) == 20) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 22:
+ $add_ptr47 = $ptr + 2 | 0;
+ $call48 = _normal_scanComment($enc, $add_ptr47, $end, $nextTokPtr) | 0;
+ $retval_0 = $call48;
+ label = 69;
+ break;
+ case 23:
+ $add_ptr50 = $ptr + 2 | 0;
+ $call51 = _normal_scanCdataSection($add_ptr50, $end, $nextTokPtr) | 0;
+ $retval_0 = $call51;
+ label = 69;
+ break;
+ case 24:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr37;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 25:
+ $add_ptr53 = $ptr + 1 | 0;
+ $call54 = _normal_scanPi($enc, $add_ptr53, $end, $nextTokPtr) | 0;
+ $retval_0 = $call54;
+ label = 69;
+ break;
+ case 26:
+ $add_ptr56 = $ptr + 1 | 0;
+ $call57 = _normal_scanEndTag($enc, $add_ptr56, $end, $nextTokPtr) | 0;
+ $retval_0 = $call57;
+ label = 69;
+ break;
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 28:
+ $12 = HEAP8[$ptr_addr_0156] | 0;
+ $idxprom61 = $12 & 255;
+ $arrayidx63 = $1 + $idxprom61 | 0;
+ $13 = HEAP8[$arrayidx63] | 0;
+ $conv64 = $13 & 255;
+ if (($conv64 | 0) == 21 | ($conv64 | 0) == 9 | ($conv64 | 0) == 10) {
+ label = 29;
+ break;
+ } else if (($conv64 | 0) == 29) {
+ label = 30;
+ break;
+ } else if (($conv64 | 0) == 22 | ($conv64 | 0) == 24 | ($conv64 | 0) == 25 | ($conv64 | 0) == 26 | ($conv64 | 0) == 27) {
+ label = 31;
+ break;
+ } else if (($conv64 | 0) == 5) {
+ label = 32;
+ break;
+ } else if (($conv64 | 0) == 6) {
+ label = 36;
+ break;
+ } else if (($conv64 | 0) == 7) {
+ label = 40;
+ break;
+ } else if (($conv64 | 0) == 11) {
+ $ptr_addr_3 = $ptr_addr_0156;
+ label = 63;
+ break;
+ } else if (($conv64 | 0) == 17) {
+ $ptr_addr_4 = $ptr_addr_0156;
+ label = 64;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 29:
+ $ptr_addr_1140 = $ptr_addr_0156 + 1 | 0;
+ $cmp110141 = ($ptr_addr_1140 | 0) == ($end | 0);
+ if ($cmp110141) {
+ $retval_0 = -1;
+ label = 69;
+ break;
+ } else {
+ $ptr_addr_0_pn142 = $ptr_addr_0156;
+ $ptr_addr_1143 = $ptr_addr_1140;
+ label = 45;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0156;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 31:
+ $add_ptr67 = $ptr_addr_0156 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr67;
+ label = 44;
+ break;
+ case 32:
+ $sub_ptr_rhs_cast70 = $ptr_addr_0156;
+ $sub_ptr_sub71 = $sub_ptr_lhs_cast69 - $sub_ptr_rhs_cast70 | 0;
+ $cmp72 = ($sub_ptr_sub71 | 0) < 2;
+ if ($cmp72) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $14 = HEAP32[$3 >> 2] | 0;
+ $call76 = FUNCTION_TABLE_iii[$14 & 1023]($enc, $ptr_addr_0156) | 0;
+ $tobool77 = ($call76 | 0) == 0;
+ if ($tobool77) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0156;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 35:
+ $add_ptr80 = $ptr_addr_0156 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr80;
+ label = 44;
+ break;
+ case 36:
+ $sub_ptr_rhs_cast83 = $ptr_addr_0156;
+ $sub_ptr_sub84 = $sub_ptr_lhs_cast82 - $sub_ptr_rhs_cast83 | 0;
+ $cmp85 = ($sub_ptr_sub84 | 0) < 3;
+ if ($cmp85) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $15 = HEAP32[$isName3 >> 2] | 0;
+ $16 = $15;
+ $call89 = FUNCTION_TABLE_iii[$16 & 1023]($enc, $ptr_addr_0156) | 0;
+ $tobool90 = ($call89 | 0) == 0;
+ if ($tobool90) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0156;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 39:
+ $add_ptr93 = $ptr_addr_0156 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr93;
+ label = 44;
+ break;
+ case 40:
+ $sub_ptr_rhs_cast96 = $ptr_addr_0156;
+ $sub_ptr_sub97 = $sub_ptr_lhs_cast95 - $sub_ptr_rhs_cast96 | 0;
+ $cmp98 = ($sub_ptr_sub97 | 0) < 4;
+ if ($cmp98) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $17 = HEAP32[$isName4 >> 2] | 0;
+ $18 = $17;
+ $call102 = FUNCTION_TABLE_iii[$18 & 1023]($enc, $ptr_addr_0156) | 0;
+ $tobool103 = ($call102 | 0) == 0;
+ if ($tobool103) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0156;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 43:
+ $add_ptr106 = $ptr_addr_0156 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr106;
+ label = 44;
+ break;
+ case 44:
+ $cmp59 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp59) {
+ $retval_0 = -1;
+ label = 69;
+ break;
+ } else {
+ $ptr_addr_0156 = $ptr_addr_0_be;
+ label = 28;
+ break;
+ }
+ case 45:
+ $19 = HEAP8[$ptr_addr_1143] | 0;
+ $idxprom113 = $19 & 255;
+ $arrayidx115 = $1 + $idxprom113 | 0;
+ $20 = HEAP8[$arrayidx115] | 0;
+ $conv116 = $20 & 255;
+ if (($conv116 | 0) == 21 | ($conv116 | 0) == 9 | ($conv116 | 0) == 10) {
+ label = 46;
+ break;
+ } else if (($conv116 | 0) == 29) {
+ label = 47;
+ break;
+ } else if (($conv116 | 0) == 22 | ($conv116 | 0) == 24) {
+ label = 48;
+ break;
+ } else if (($conv116 | 0) == 5) {
+ label = 49;
+ break;
+ } else if (($conv116 | 0) == 6) {
+ label = 53;
+ break;
+ } else if (($conv116 | 0) == 7) {
+ label = 57;
+ break;
+ } else if (($conv116 | 0) == 11) {
+ $ptr_addr_3 = $ptr_addr_1143;
+ label = 63;
+ break;
+ } else if (($conv116 | 0) == 17) {
+ $ptr_addr_4 = $ptr_addr_1143;
+ label = 64;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 46:
+ $ptr_addr_1 = $ptr_addr_1143 + 1 | 0;
+ $cmp110 = ($ptr_addr_1 | 0) == ($end | 0);
+ if ($cmp110) {
+ $retval_0 = -1;
+ label = 69;
+ break;
+ } else {
+ $ptr_addr_0_pn142 = $ptr_addr_1143;
+ $ptr_addr_1143 = $ptr_addr_1;
+ label = 45;
+ break;
+ }
+ case 47:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1143;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 48:
+ $add_ptr119 = $ptr_addr_0_pn142 + 2 | 0;
+ $ptr_addr_2 = $add_ptr119;
+ label = 62;
+ break;
+ case 49:
+ $sub_ptr_lhs_cast121 = $end;
+ $sub_ptr_rhs_cast122 = $ptr_addr_1143;
+ $sub_ptr_sub123 = $sub_ptr_lhs_cast121 - $sub_ptr_rhs_cast122 | 0;
+ $cmp124 = ($sub_ptr_sub123 | 0) < 2;
+ if ($cmp124) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $isNmstrt2128 = $enc + 340 | 0;
+ $21 = HEAP32[$isNmstrt2128 >> 2] | 0;
+ $22 = $21;
+ $call129 = FUNCTION_TABLE_iii[$22 & 1023]($enc, $ptr_addr_1143) | 0;
+ $tobool130 = ($call129 | 0) == 0;
+ if ($tobool130) {
+ label = 51;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 51:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1143;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 52:
+ $add_ptr133 = $ptr_addr_0_pn142 + 3 | 0;
+ $ptr_addr_2 = $add_ptr133;
+ label = 62;
+ break;
+ case 53:
+ $sub_ptr_lhs_cast135 = $end;
+ $sub_ptr_rhs_cast136 = $ptr_addr_1143;
+ $sub_ptr_sub137 = $sub_ptr_lhs_cast135 - $sub_ptr_rhs_cast136 | 0;
+ $cmp138 = ($sub_ptr_sub137 | 0) < 3;
+ if ($cmp138) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 54:
+ $isNmstrt3142 = $enc + 344 | 0;
+ $23 = HEAP32[$isNmstrt3142 >> 2] | 0;
+ $24 = $23;
+ $call143 = FUNCTION_TABLE_iii[$24 & 1023]($enc, $ptr_addr_1143) | 0;
+ $tobool144 = ($call143 | 0) == 0;
+ if ($tobool144) {
+ label = 55;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 55:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1143;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 56:
+ $add_ptr147 = $ptr_addr_0_pn142 + 4 | 0;
+ $ptr_addr_2 = $add_ptr147;
+ label = 62;
+ break;
+ case 57:
+ $sub_ptr_lhs_cast149 = $end;
+ $sub_ptr_rhs_cast150 = $ptr_addr_1143;
+ $sub_ptr_sub151 = $sub_ptr_lhs_cast149 - $sub_ptr_rhs_cast150 | 0;
+ $cmp152 = ($sub_ptr_sub151 | 0) < 4;
+ if ($cmp152) {
+ $retval_0 = -2;
+ label = 69;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $isNmstrt4156 = $enc + 348 | 0;
+ $25 = HEAP32[$isNmstrt4156 >> 2] | 0;
+ $26 = $25;
+ $call157 = FUNCTION_TABLE_iii[$26 & 1023]($enc, $ptr_addr_1143) | 0;
+ $tobool158 = ($call157 | 0) == 0;
+ if ($tobool158) {
+ label = 59;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 59:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1143;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 60:
+ $add_ptr161 = $ptr_addr_0_pn142 + 5 | 0;
+ $ptr_addr_2 = $add_ptr161;
+ label = 62;
+ break;
+ case 61:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1143;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 62:
+ $call168 = _normal_scanAtts($enc, $ptr_addr_2, $end, $nextTokPtr) | 0;
+ $retval_0 = $call168;
+ label = 69;
+ break;
+ case 63:
+ $add_ptr170 = $ptr_addr_3 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr170;
+ $retval_0 = 2;
+ label = 69;
+ break;
+ case 64:
+ $add_ptr172 = $ptr_addr_4 + 1 | 0;
+ $cmp173 = ($add_ptr172 | 0) == ($end | 0);
+ if ($cmp173) {
+ $retval_0 = -1;
+ label = 69;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $27 = HEAP8[$add_ptr172] | 0;
+ $cmp178 = $27 << 24 >> 24 == 62;
+ if ($cmp178) {
+ label = 67;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr172;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 67:
+ $add_ptr182 = $ptr_addr_4 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr182;
+ $retval_0 = 4;
+ label = 69;
+ break;
+ case 68:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0156;
+ $retval_0 = 0;
+ label = 69;
+ break;
+ case 69:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanComment($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $cmp1 = 0, $add_ptr = 0, $cmp444 = 0, $type = 0, $1 = 0, $sub_ptr_lhs_cast = 0, $isInvalid2 = 0, $2 = 0, $sub_ptr_lhs_cast15 = 0, $isInvalid3 = 0, $3 = 0, $sub_ptr_lhs_cast28 = 0, $isInvalid4 = 0, $4 = 0, $ptr_addr_045 = 0, $5 = 0, $idxprom = 0, $arrayidx = 0, $6 = 0, $conv6 = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp7 = 0, $7 = 0, $call = 0, $tobool = 0, $add_ptr13 = 0, $sub_ptr_rhs_cast16 = 0, $sub_ptr_sub17 = 0, $cmp18 = 0, $8 = 0, $call22 = 0, $tobool23 = 0, $add_ptr26 = 0, $sub_ptr_rhs_cast29 = 0, $sub_ptr_sub30 = 0, $cmp31 = 0, $9 = 0, $call35 = 0, $tobool36 = 0, $add_ptr39 = 0, $add_ptr42 = 0, $cmp43 = 0, $10 = 0, $cmp48 = 0, $ptr_addr_0_be = 0, $cmp4 = 0, $add_ptr51 = 0, $cmp52 = 0, $11 = 0, $cmp57 = 0, $add_ptr61 = 0, $add_ptr63 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $cmp1 = $0 << 24 >> 24 == 45;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $cmp444 = ($add_ptr | 0) == ($end | 0);
+ if ($cmp444) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $sub_ptr_lhs_cast = $end;
+ $isInvalid2 = $enc + 352 | 0;
+ $2 = $isInvalid2;
+ $sub_ptr_lhs_cast15 = $end;
+ $isInvalid3 = $enc + 356 | 0;
+ $3 = $isInvalid3;
+ $sub_ptr_lhs_cast28 = $end;
+ $isInvalid4 = $enc + 360 | 0;
+ $4 = $isInvalid4;
+ $ptr_addr_045 = $add_ptr;
+ label = 7;
+ break;
+ case 7:
+ $5 = HEAP8[$ptr_addr_045] | 0;
+ $idxprom = $5 & 255;
+ $arrayidx = $1 + $idxprom | 0;
+ $6 = HEAP8[$arrayidx] | 0;
+ $conv6 = $6 & 255;
+ if (($conv6 | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($conv6 | 0) == 6) {
+ label = 12;
+ break;
+ } else if (($conv6 | 0) == 7) {
+ label = 16;
+ break;
+ } else if (($conv6 | 0) == 0 | ($conv6 | 0) == 1 | ($conv6 | 0) == 8) {
+ label = 20;
+ break;
+ } else if (($conv6 | 0) == 27) {
+ label = 21;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 8:
+ $sub_ptr_rhs_cast = $ptr_addr_045;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp7 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp7) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $7 = HEAP32[$2 >> 2] | 0;
+ $call = FUNCTION_TABLE_iii[$7 & 1023]($enc, $ptr_addr_045) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 11;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_045;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 11:
+ $add_ptr13 = $ptr_addr_045 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr13;
+ label = 23;
+ break;
+ case 12:
+ $sub_ptr_rhs_cast16 = $ptr_addr_045;
+ $sub_ptr_sub17 = $sub_ptr_lhs_cast15 - $sub_ptr_rhs_cast16 | 0;
+ $cmp18 = ($sub_ptr_sub17 | 0) < 3;
+ if ($cmp18) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $8 = HEAP32[$3 >> 2] | 0;
+ $call22 = FUNCTION_TABLE_iii[$8 & 1023]($enc, $ptr_addr_045) | 0;
+ $tobool23 = ($call22 | 0) == 0;
+ if ($tobool23) {
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_045;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 15:
+ $add_ptr26 = $ptr_addr_045 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr26;
+ label = 23;
+ break;
+ case 16:
+ $sub_ptr_rhs_cast29 = $ptr_addr_045;
+ $sub_ptr_sub30 = $sub_ptr_lhs_cast28 - $sub_ptr_rhs_cast29 | 0;
+ $cmp31 = ($sub_ptr_sub30 | 0) < 4;
+ if ($cmp31) {
+ $retval_0 = -2;
+ label = 29;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $9 = HEAP32[$4 >> 2] | 0;
+ $call35 = FUNCTION_TABLE_iii[$9 & 1023]($enc, $ptr_addr_045) | 0;
+ $tobool36 = ($call35 | 0) == 0;
+ if ($tobool36) {
+ label = 19;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_045;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 19:
+ $add_ptr39 = $ptr_addr_045 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr39;
+ label = 23;
+ break;
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_045;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 21:
+ $add_ptr42 = $ptr_addr_045 + 1 | 0;
+ $cmp43 = ($add_ptr42 | 0) == ($end | 0);
+ if ($cmp43) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $10 = HEAP8[$add_ptr42] | 0;
+ $cmp48 = $10 << 24 >> 24 == 45;
+ if ($cmp48) {
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_0_be = $add_ptr42;
+ label = 23;
+ break;
+ }
+ case 23:
+ $cmp4 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp4) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ $ptr_addr_045 = $ptr_addr_0_be;
+ label = 7;
+ break;
+ }
+ case 24:
+ $add_ptr51 = $ptr_addr_045 + 2 | 0;
+ $cmp52 = ($add_ptr51 | 0) == ($end | 0);
+ if ($cmp52) {
+ $retval_0 = -1;
+ label = 29;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $11 = HEAP8[$add_ptr51] | 0;
+ $cmp57 = $11 << 24 >> 24 == 62;
+ if ($cmp57) {
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr51;
+ $retval_0 = 0;
+ label = 29;
+ break;
+ case 27:
+ $add_ptr61 = $ptr_addr_045 + 3 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr61;
+ $retval_0 = 13;
+ label = 29;
+ break;
+ case 28:
+ $add_ptr63 = $ptr_addr_045 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr63;
+ label = 23;
+ break;
+ case 29:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanPi($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $tok = 0, $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $ptr_addr_0_ph = 0, $cmp36122 = 0, $sub_ptr_lhs_cast46 = 0, $3 = 0, $sub_ptr_lhs_cast59 = 0, $isName3 = 0, $sub_ptr_lhs_cast72 = 0, $isName4 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp3 = 0, $isNmstrt2 = 0, $4 = 0, $5 = 0, $call = 0, $tobool = 0, $add_ptr9 = 0, $sub_ptr_lhs_cast11 = 0, $sub_ptr_rhs_cast12 = 0, $sub_ptr_sub13 = 0, $cmp14 = 0, $isNmstrt3 = 0, $6 = 0, $7 = 0, $call18 = 0, $tobool19 = 0, $add_ptr22 = 0, $sub_ptr_lhs_cast24 = 0, $sub_ptr_rhs_cast25 = 0, $sub_ptr_sub26 = 0, $cmp27 = 0, $isNmstrt4 = 0, $8 = 0, $9 = 0, $call31 = 0, $tobool32 = 0, $add_ptr35 = 0, $ptr_addr_0123 = 0, $10 = 0, $idxprom38 = 0, $arrayidx40 = 0, $11 = 0, $conv41 = 0, $add_ptr44 = 0, $sub_ptr_rhs_cast47 = 0, $sub_ptr_sub48 = 0, $cmp49 = 0, $12 = 0, $call53 = 0, $tobool54 = 0, $add_ptr57 = 0, $sub_ptr_rhs_cast60 = 0, $sub_ptr_sub61 = 0, $cmp62 = 0, $13 = 0, $14 = 0, $call66 = 0, $tobool67 = 0, $add_ptr70 = 0, $sub_ptr_rhs_cast73 = 0, $sub_ptr_sub74 = 0, $cmp75 = 0, $15 = 0, $16 = 0, $call79 = 0, $tobool80 = 0, $add_ptr83 = 0, $ptr_addr_0_be = 0, $cmp36 = 0, $call85 = 0, $tobool86 = 0, $add_ptr89 = 0, $cmp91111 = 0, $sub_ptr_lhs_cast99 = 0, $isInvalid2 = 0, $17 = 0, $sub_ptr_lhs_cast112 = 0, $isInvalid3 = 0, $18 = 0, $sub_ptr_lhs_cast125 = 0, $isInvalid4 = 0, $19 = 0, $ptr_addr_1112 = 0, $20 = 0, $idxprom94 = 0, $arrayidx96 = 0, $21 = 0, $conv97 = 0, $sub_ptr_rhs_cast100 = 0, $sub_ptr_sub101 = 0, $cmp102 = 0, $22 = 0, $call106 = 0, $tobool107 = 0, $add_ptr110 = 0, $sub_ptr_rhs_cast113 = 0, $sub_ptr_sub114 = 0, $cmp115 = 0, $23 = 0, $call119 = 0, $tobool120 = 0, $add_ptr123 = 0, $sub_ptr_rhs_cast126 = 0, $sub_ptr_sub127 = 0, $cmp128 = 0, $24 = 0, $call132 = 0, $tobool133 = 0, $add_ptr136 = 0, $add_ptr139 = 0, $cmp140 = 0, $25 = 0, $cmp145 = 0, $ptr_addr_1_be = 0, $cmp91 = 0, $add_ptr148 = 0, $26 = 0, $add_ptr151 = 0, $call154 = 0, $tobool155 = 0, $add_ptr158 = 0, $cmp159 = 0, $27 = 0, $cmp164 = 0, $add_ptr167 = 0, $28 = 0, $ptr_addr_2 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $tok = __stackBase__ | 0;
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 66;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 29) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 16;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 4:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $ptr_addr_0_ph = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $cmp36122 = ($ptr_addr_0_ph | 0) == ($end | 0);
+ if ($cmp36122) {
+ $retval_0 = -1;
+ label = 66;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub_ptr_lhs_cast46 = $end;
+ $3 = $enc + 328 | 0;
+ $sub_ptr_lhs_cast59 = $end;
+ $isName3 = $enc + 332 | 0;
+ $sub_ptr_lhs_cast72 = $end;
+ $isName4 = $enc + 336 | 0;
+ $ptr_addr_0123 = $ptr_addr_0_ph;
+ label = 21;
+ break;
+ case 8:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp3 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp3) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $isNmstrt2 = $enc + 340 | 0;
+ $4 = HEAP32[$isNmstrt2 >> 2] | 0;
+ $5 = $4;
+ $call = FUNCTION_TABLE_iii[$5 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 11:
+ $add_ptr9 = $ptr + 2 | 0;
+ $ptr_addr_0_ph = $add_ptr9;
+ label = 6;
+ break;
+ case 12:
+ $sub_ptr_lhs_cast11 = $end;
+ $sub_ptr_rhs_cast12 = $ptr;
+ $sub_ptr_sub13 = $sub_ptr_lhs_cast11 - $sub_ptr_rhs_cast12 | 0;
+ $cmp14 = ($sub_ptr_sub13 | 0) < 3;
+ if ($cmp14) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $isNmstrt3 = $enc + 344 | 0;
+ $6 = HEAP32[$isNmstrt3 >> 2] | 0;
+ $7 = $6;
+ $call18 = FUNCTION_TABLE_iii[$7 & 1023]($enc, $ptr) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 15:
+ $add_ptr22 = $ptr + 3 | 0;
+ $ptr_addr_0_ph = $add_ptr22;
+ label = 6;
+ break;
+ case 16:
+ $sub_ptr_lhs_cast24 = $end;
+ $sub_ptr_rhs_cast25 = $ptr;
+ $sub_ptr_sub26 = $sub_ptr_lhs_cast24 - $sub_ptr_rhs_cast25 | 0;
+ $cmp27 = ($sub_ptr_sub26 | 0) < 4;
+ if ($cmp27) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $isNmstrt4 = $enc + 348 | 0;
+ $8 = HEAP32[$isNmstrt4 >> 2] | 0;
+ $9 = $8;
+ $call31 = FUNCTION_TABLE_iii[$9 & 1023]($enc, $ptr) | 0;
+ $tobool32 = ($call31 | 0) == 0;
+ if ($tobool32) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 19:
+ $add_ptr35 = $ptr + 4 | 0;
+ $ptr_addr_0_ph = $add_ptr35;
+ label = 6;
+ break;
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 21:
+ $10 = HEAP8[$ptr_addr_0123] | 0;
+ $idxprom38 = $10 & 255;
+ $arrayidx40 = $1 + $idxprom38 | 0;
+ $11 = HEAP8[$arrayidx40] | 0;
+ $conv41 = $11 & 255;
+ if (($conv41 | 0) == 29) {
+ label = 22;
+ break;
+ } else if (($conv41 | 0) == 22 | ($conv41 | 0) == 24 | ($conv41 | 0) == 25 | ($conv41 | 0) == 26 | ($conv41 | 0) == 27) {
+ label = 23;
+ break;
+ } else if (($conv41 | 0) == 5) {
+ label = 24;
+ break;
+ } else if (($conv41 | 0) == 6) {
+ label = 28;
+ break;
+ } else if (($conv41 | 0) == 7) {
+ label = 32;
+ break;
+ } else if (($conv41 | 0) == 21 | ($conv41 | 0) == 9 | ($conv41 | 0) == 10) {
+ label = 37;
+ break;
+ } else if (($conv41 | 0) == 15) {
+ label = 60;
+ break;
+ } else {
+ $ptr_addr_2 = $ptr_addr_0123;
+ label = 65;
+ break;
+ }
+ case 22:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0123;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 23:
+ $add_ptr44 = $ptr_addr_0123 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr44;
+ label = 36;
+ break;
+ case 24:
+ $sub_ptr_rhs_cast47 = $ptr_addr_0123;
+ $sub_ptr_sub48 = $sub_ptr_lhs_cast46 - $sub_ptr_rhs_cast47 | 0;
+ $cmp49 = ($sub_ptr_sub48 | 0) < 2;
+ if ($cmp49) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $12 = HEAP32[$3 >> 2] | 0;
+ $call53 = FUNCTION_TABLE_iii[$12 & 1023]($enc, $ptr_addr_0123) | 0;
+ $tobool54 = ($call53 | 0) == 0;
+ if ($tobool54) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0123;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 27:
+ $add_ptr57 = $ptr_addr_0123 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr57;
+ label = 36;
+ break;
+ case 28:
+ $sub_ptr_rhs_cast60 = $ptr_addr_0123;
+ $sub_ptr_sub61 = $sub_ptr_lhs_cast59 - $sub_ptr_rhs_cast60 | 0;
+ $cmp62 = ($sub_ptr_sub61 | 0) < 3;
+ if ($cmp62) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $13 = HEAP32[$isName3 >> 2] | 0;
+ $14 = $13;
+ $call66 = FUNCTION_TABLE_iii[$14 & 1023]($enc, $ptr_addr_0123) | 0;
+ $tobool67 = ($call66 | 0) == 0;
+ if ($tobool67) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0123;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 31:
+ $add_ptr70 = $ptr_addr_0123 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr70;
+ label = 36;
+ break;
+ case 32:
+ $sub_ptr_rhs_cast73 = $ptr_addr_0123;
+ $sub_ptr_sub74 = $sub_ptr_lhs_cast72 - $sub_ptr_rhs_cast73 | 0;
+ $cmp75 = ($sub_ptr_sub74 | 0) < 4;
+ if ($cmp75) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $15 = HEAP32[$isName4 >> 2] | 0;
+ $16 = $15;
+ $call79 = FUNCTION_TABLE_iii[$16 & 1023]($enc, $ptr_addr_0123) | 0;
+ $tobool80 = ($call79 | 0) == 0;
+ if ($tobool80) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0123;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 35:
+ $add_ptr83 = $ptr_addr_0123 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr83;
+ label = 36;
+ break;
+ case 36:
+ $cmp36 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp36) {
+ $retval_0 = -1;
+ label = 66;
+ break;
+ } else {
+ $ptr_addr_0123 = $ptr_addr_0_be;
+ label = 21;
+ break;
+ }
+ case 37:
+ $call85 = _normal_checkPiTarget($ptr, $ptr_addr_0123, $tok) | 0;
+ $tobool86 = ($call85 | 0) == 0;
+ if ($tobool86) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0123;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 39:
+ $add_ptr89 = $ptr_addr_0123 + 1 | 0;
+ $cmp91111 = ($add_ptr89 | 0) == ($end | 0);
+ if ($cmp91111) {
+ $retval_0 = -1;
+ label = 66;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $sub_ptr_lhs_cast99 = $end;
+ $isInvalid2 = $enc + 352 | 0;
+ $17 = $isInvalid2;
+ $sub_ptr_lhs_cast112 = $end;
+ $isInvalid3 = $enc + 356 | 0;
+ $18 = $isInvalid3;
+ $sub_ptr_lhs_cast125 = $end;
+ $isInvalid4 = $enc + 360 | 0;
+ $19 = $isInvalid4;
+ $ptr_addr_1112 = $add_ptr89;
+ label = 41;
+ break;
+ case 41:
+ $20 = HEAP8[$ptr_addr_1112] | 0;
+ $idxprom94 = $20 & 255;
+ $arrayidx96 = $1 + $idxprom94 | 0;
+ $21 = HEAP8[$arrayidx96] | 0;
+ $conv97 = $21 & 255;
+ if (($conv97 | 0) == 5) {
+ label = 42;
+ break;
+ } else if (($conv97 | 0) == 6) {
+ label = 46;
+ break;
+ } else if (($conv97 | 0) == 7) {
+ label = 50;
+ break;
+ } else if (($conv97 | 0) == 0 | ($conv97 | 0) == 1 | ($conv97 | 0) == 8) {
+ label = 54;
+ break;
+ } else if (($conv97 | 0) == 15) {
+ label = 55;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 42:
+ $sub_ptr_rhs_cast100 = $ptr_addr_1112;
+ $sub_ptr_sub101 = $sub_ptr_lhs_cast99 - $sub_ptr_rhs_cast100 | 0;
+ $cmp102 = ($sub_ptr_sub101 | 0) < 2;
+ if ($cmp102) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $22 = HEAP32[$17 >> 2] | 0;
+ $call106 = FUNCTION_TABLE_iii[$22 & 1023]($enc, $ptr_addr_1112) | 0;
+ $tobool107 = ($call106 | 0) == 0;
+ if ($tobool107) {
+ label = 45;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1112;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 45:
+ $add_ptr110 = $ptr_addr_1112 + 2 | 0;
+ $ptr_addr_1_be = $add_ptr110;
+ label = 57;
+ break;
+ case 46:
+ $sub_ptr_rhs_cast113 = $ptr_addr_1112;
+ $sub_ptr_sub114 = $sub_ptr_lhs_cast112 - $sub_ptr_rhs_cast113 | 0;
+ $cmp115 = ($sub_ptr_sub114 | 0) < 3;
+ if ($cmp115) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $23 = HEAP32[$18 >> 2] | 0;
+ $call119 = FUNCTION_TABLE_iii[$23 & 1023]($enc, $ptr_addr_1112) | 0;
+ $tobool120 = ($call119 | 0) == 0;
+ if ($tobool120) {
+ label = 49;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1112;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 49:
+ $add_ptr123 = $ptr_addr_1112 + 3 | 0;
+ $ptr_addr_1_be = $add_ptr123;
+ label = 57;
+ break;
+ case 50:
+ $sub_ptr_rhs_cast126 = $ptr_addr_1112;
+ $sub_ptr_sub127 = $sub_ptr_lhs_cast125 - $sub_ptr_rhs_cast126 | 0;
+ $cmp128 = ($sub_ptr_sub127 | 0) < 4;
+ if ($cmp128) {
+ $retval_0 = -2;
+ label = 66;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $24 = HEAP32[$19 >> 2] | 0;
+ $call132 = FUNCTION_TABLE_iii[$24 & 1023]($enc, $ptr_addr_1112) | 0;
+ $tobool133 = ($call132 | 0) == 0;
+ if ($tobool133) {
+ label = 53;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1112;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 53:
+ $add_ptr136 = $ptr_addr_1112 + 4 | 0;
+ $ptr_addr_1_be = $add_ptr136;
+ label = 57;
+ break;
+ case 54:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1112;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 55:
+ $add_ptr139 = $ptr_addr_1112 + 1 | 0;
+ $cmp140 = ($add_ptr139 | 0) == ($end | 0);
+ if ($cmp140) {
+ $retval_0 = -1;
+ label = 66;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 56:
+ $25 = HEAP8[$add_ptr139] | 0;
+ $cmp145 = $25 << 24 >> 24 == 62;
+ if ($cmp145) {
+ label = 58;
+ break;
+ } else {
+ $ptr_addr_1_be = $add_ptr139;
+ label = 57;
+ break;
+ }
+ case 57:
+ $cmp91 = ($ptr_addr_1_be | 0) == ($end | 0);
+ if ($cmp91) {
+ $retval_0 = -1;
+ label = 66;
+ break;
+ } else {
+ $ptr_addr_1112 = $ptr_addr_1_be;
+ label = 41;
+ break;
+ }
+ case 58:
+ $add_ptr148 = $ptr_addr_1112 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr148;
+ $26 = HEAP32[$tok >> 2] | 0;
+ $retval_0 = $26;
+ label = 66;
+ break;
+ case 59:
+ $add_ptr151 = $ptr_addr_1112 + 1 | 0;
+ $ptr_addr_1_be = $add_ptr151;
+ label = 57;
+ break;
+ case 60:
+ $call154 = _normal_checkPiTarget($ptr, $ptr_addr_0123, $tok) | 0;
+ $tobool155 = ($call154 | 0) == 0;
+ if ($tobool155) {
+ label = 61;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 61:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_0123;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 62:
+ $add_ptr158 = $ptr_addr_0123 + 1 | 0;
+ $cmp159 = ($add_ptr158 | 0) == ($end | 0);
+ if ($cmp159) {
+ $retval_0 = -1;
+ label = 66;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ $27 = HEAP8[$add_ptr158] | 0;
+ $cmp164 = $27 << 24 >> 24 == 62;
+ if ($cmp164) {
+ label = 64;
+ break;
+ } else {
+ $ptr_addr_2 = $add_ptr158;
+ label = 65;
+ break;
+ }
+ case 64:
+ $add_ptr167 = $ptr_addr_0123 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr167;
+ $28 = HEAP32[$tok >> 2] | 0;
+ $retval_0 = $28;
+ label = 66;
+ break;
+ case 65:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_2;
+ $retval_0 = 0;
+ label = 66;
+ break;
+ case 66:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanEndTag($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $ptr_addr_0_ph = 0, $cmp3685 = 0, $sub_ptr_lhs_cast46 = 0, $3 = 0, $sub_ptr_lhs_cast59 = 0, $isName3 = 0, $sub_ptr_lhs_cast72 = 0, $isName4 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp3 = 0, $isNmstrt2 = 0, $4 = 0, $5 = 0, $call = 0, $tobool = 0, $add_ptr9 = 0, $sub_ptr_lhs_cast11 = 0, $sub_ptr_rhs_cast12 = 0, $sub_ptr_sub13 = 0, $cmp14 = 0, $isNmstrt3 = 0, $6 = 0, $7 = 0, $call18 = 0, $tobool19 = 0, $add_ptr22 = 0, $sub_ptr_lhs_cast24 = 0, $sub_ptr_rhs_cast25 = 0, $sub_ptr_sub26 = 0, $cmp27 = 0, $isNmstrt4 = 0, $8 = 0, $9 = 0, $call31 = 0, $tobool32 = 0, $add_ptr35 = 0, $ptr_addr_086 = 0, $10 = 0, $idxprom38 = 0, $arrayidx40 = 0, $11 = 0, $conv41 = 0, $ptr_addr_173 = 0, $cmp8674 = 0, $add_ptr44 = 0, $sub_ptr_rhs_cast47 = 0, $sub_ptr_sub48 = 0, $cmp49 = 0, $12 = 0, $call53 = 0, $tobool54 = 0, $add_ptr57 = 0, $sub_ptr_rhs_cast60 = 0, $sub_ptr_sub61 = 0, $cmp62 = 0, $13 = 0, $14 = 0, $call66 = 0, $tobool67 = 0, $add_ptr70 = 0, $sub_ptr_rhs_cast73 = 0, $sub_ptr_sub74 = 0, $cmp75 = 0, $15 = 0, $16 = 0, $call79 = 0, $tobool80 = 0, $add_ptr83 = 0, $ptr_addr_0_be = 0, $cmp36 = 0, $ptr_addr_176 = 0, $ptr_addr_0_pn75 = 0, $17 = 0, $idxprom88 = 0, $arrayidx90 = 0, $18 = 0, $conv91 = 0, $ptr_addr_1 = 0, $cmp86 = 0, $add_ptr94 = 0, $add_ptr99 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 44;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 29) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 16;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 4:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $ptr_addr_0_ph = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $cmp3685 = ($ptr_addr_0_ph | 0) == ($end | 0);
+ if ($cmp3685) {
+ $retval_0 = -1;
+ label = 44;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub_ptr_lhs_cast46 = $end;
+ $3 = $enc + 328 | 0;
+ $sub_ptr_lhs_cast59 = $end;
+ $isName3 = $enc + 332 | 0;
+ $sub_ptr_lhs_cast72 = $end;
+ $isName4 = $enc + 336 | 0;
+ $ptr_addr_086 = $ptr_addr_0_ph;
+ label = 21;
+ break;
+ case 8:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp3 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp3) {
+ $retval_0 = -2;
+ label = 44;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $isNmstrt2 = $enc + 340 | 0;
+ $4 = HEAP32[$isNmstrt2 >> 2] | 0;
+ $5 = $4;
+ $call = FUNCTION_TABLE_iii[$5 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 11:
+ $add_ptr9 = $ptr + 2 | 0;
+ $ptr_addr_0_ph = $add_ptr9;
+ label = 6;
+ break;
+ case 12:
+ $sub_ptr_lhs_cast11 = $end;
+ $sub_ptr_rhs_cast12 = $ptr;
+ $sub_ptr_sub13 = $sub_ptr_lhs_cast11 - $sub_ptr_rhs_cast12 | 0;
+ $cmp14 = ($sub_ptr_sub13 | 0) < 3;
+ if ($cmp14) {
+ $retval_0 = -2;
+ label = 44;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $isNmstrt3 = $enc + 344 | 0;
+ $6 = HEAP32[$isNmstrt3 >> 2] | 0;
+ $7 = $6;
+ $call18 = FUNCTION_TABLE_iii[$7 & 1023]($enc, $ptr) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 15:
+ $add_ptr22 = $ptr + 3 | 0;
+ $ptr_addr_0_ph = $add_ptr22;
+ label = 6;
+ break;
+ case 16:
+ $sub_ptr_lhs_cast24 = $end;
+ $sub_ptr_rhs_cast25 = $ptr;
+ $sub_ptr_sub26 = $sub_ptr_lhs_cast24 - $sub_ptr_rhs_cast25 | 0;
+ $cmp27 = ($sub_ptr_sub26 | 0) < 4;
+ if ($cmp27) {
+ $retval_0 = -2;
+ label = 44;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $isNmstrt4 = $enc + 348 | 0;
+ $8 = HEAP32[$isNmstrt4 >> 2] | 0;
+ $9 = $8;
+ $call31 = FUNCTION_TABLE_iii[$9 & 1023]($enc, $ptr) | 0;
+ $tobool32 = ($call31 | 0) == 0;
+ if ($tobool32) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 19:
+ $add_ptr35 = $ptr + 4 | 0;
+ $ptr_addr_0_ph = $add_ptr35;
+ label = 6;
+ break;
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 21:
+ $10 = HEAP8[$ptr_addr_086] | 0;
+ $idxprom38 = $10 & 255;
+ $arrayidx40 = $1 + $idxprom38 | 0;
+ $11 = HEAP8[$arrayidx40] | 0;
+ $conv41 = $11 & 255;
+ if (($conv41 | 0) == 21 | ($conv41 | 0) == 9 | ($conv41 | 0) == 10) {
+ label = 22;
+ break;
+ } else if (($conv41 | 0) == 29) {
+ label = 23;
+ break;
+ } else if (($conv41 | 0) == 22 | ($conv41 | 0) == 24 | ($conv41 | 0) == 25 | ($conv41 | 0) == 26 | ($conv41 | 0) == 27) {
+ label = 24;
+ break;
+ } else if (($conv41 | 0) == 5) {
+ label = 25;
+ break;
+ } else if (($conv41 | 0) == 6) {
+ label = 29;
+ break;
+ } else if (($conv41 | 0) == 7) {
+ label = 33;
+ break;
+ } else if (($conv41 | 0) == 11) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 22:
+ $ptr_addr_173 = $ptr_addr_086 + 1 | 0;
+ $cmp8674 = ($ptr_addr_173 | 0) == ($end | 0);
+ if ($cmp8674) {
+ $retval_0 = -1;
+ label = 44;
+ break;
+ } else {
+ $ptr_addr_0_pn75 = $ptr_addr_086;
+ $ptr_addr_176 = $ptr_addr_173;
+ label = 38;
+ break;
+ }
+ case 23:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_086;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 24:
+ $add_ptr44 = $ptr_addr_086 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr44;
+ label = 37;
+ break;
+ case 25:
+ $sub_ptr_rhs_cast47 = $ptr_addr_086;
+ $sub_ptr_sub48 = $sub_ptr_lhs_cast46 - $sub_ptr_rhs_cast47 | 0;
+ $cmp49 = ($sub_ptr_sub48 | 0) < 2;
+ if ($cmp49) {
+ $retval_0 = -2;
+ label = 44;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $12 = HEAP32[$3 >> 2] | 0;
+ $call53 = FUNCTION_TABLE_iii[$12 & 1023]($enc, $ptr_addr_086) | 0;
+ $tobool54 = ($call53 | 0) == 0;
+ if ($tobool54) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_086;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 28:
+ $add_ptr57 = $ptr_addr_086 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr57;
+ label = 37;
+ break;
+ case 29:
+ $sub_ptr_rhs_cast60 = $ptr_addr_086;
+ $sub_ptr_sub61 = $sub_ptr_lhs_cast59 - $sub_ptr_rhs_cast60 | 0;
+ $cmp62 = ($sub_ptr_sub61 | 0) < 3;
+ if ($cmp62) {
+ $retval_0 = -2;
+ label = 44;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ $13 = HEAP32[$isName3 >> 2] | 0;
+ $14 = $13;
+ $call66 = FUNCTION_TABLE_iii[$14 & 1023]($enc, $ptr_addr_086) | 0;
+ $tobool67 = ($call66 | 0) == 0;
+ if ($tobool67) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_086;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 32:
+ $add_ptr70 = $ptr_addr_086 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr70;
+ label = 37;
+ break;
+ case 33:
+ $sub_ptr_rhs_cast73 = $ptr_addr_086;
+ $sub_ptr_sub74 = $sub_ptr_lhs_cast72 - $sub_ptr_rhs_cast73 | 0;
+ $cmp75 = ($sub_ptr_sub74 | 0) < 4;
+ if ($cmp75) {
+ $retval_0 = -2;
+ label = 44;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $15 = HEAP32[$isName4 >> 2] | 0;
+ $16 = $15;
+ $call79 = FUNCTION_TABLE_iii[$16 & 1023]($enc, $ptr_addr_086) | 0;
+ $tobool80 = ($call79 | 0) == 0;
+ if ($tobool80) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_086;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 36:
+ $add_ptr83 = $ptr_addr_086 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr83;
+ label = 37;
+ break;
+ case 37:
+ $cmp36 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp36) {
+ $retval_0 = -1;
+ label = 44;
+ break;
+ } else {
+ $ptr_addr_086 = $ptr_addr_0_be;
+ label = 21;
+ break;
+ }
+ case 38:
+ $17 = HEAP8[$ptr_addr_176] | 0;
+ $idxprom88 = $17 & 255;
+ $arrayidx90 = $1 + $idxprom88 | 0;
+ $18 = HEAP8[$arrayidx90] | 0;
+ $conv91 = $18 & 255;
+ if (($conv91 | 0) == 21 | ($conv91 | 0) == 9 | ($conv91 | 0) == 10) {
+ label = 39;
+ break;
+ } else if (($conv91 | 0) == 11) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 39:
+ $ptr_addr_1 = $ptr_addr_176 + 1 | 0;
+ $cmp86 = ($ptr_addr_1 | 0) == ($end | 0);
+ if ($cmp86) {
+ $retval_0 = -1;
+ label = 44;
+ break;
+ } else {
+ $ptr_addr_0_pn75 = $ptr_addr_176;
+ $ptr_addr_176 = $ptr_addr_1;
+ label = 38;
+ break;
+ }
+ case 40:
+ $add_ptr94 = $ptr_addr_0_pn75 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr94;
+ $retval_0 = 5;
+ label = 44;
+ break;
+ case 41:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_176;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 42:
+ $add_ptr99 = $ptr_addr_086 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr99;
+ $retval_0 = 5;
+ label = 44;
+ break;
+ case 43:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_086;
+ $retval_0 = 0;
+ label = 44;
+ break;
+ case 44:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_checkPiTarget($ptr, $end, $tokPtr) {
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $tokPtr = $tokPtr | 0;
+ var $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp = 0, $0 = 0, $conv = 0, $upper_0 = 0, $add_ptr = 0, $1 = 0, $conv2 = 0, $upper_1 = 0, $add_ptr7 = 0, $2 = 0, $conv8 = 0, $tobool = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ HEAP32[$tokPtr >> 2] = 11;
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp = ($sub_ptr_sub | 0) == 3;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $conv = $0 << 24 >> 24;
+ if (($conv | 0) == 88) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 120) {
+ $upper_0 = 0;
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ }
+ case 4:
+ $upper_0 = 1;
+ label = 5;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $1 = HEAP8[$add_ptr] | 0;
+ $conv2 = $1 << 24 >> 24;
+ if (($conv2 | 0) == 77) {
+ label = 6;
+ break;
+ } else if (($conv2 | 0) == 109) {
+ $upper_1 = $upper_0;
+ label = 7;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ }
+ case 6:
+ $upper_1 = 1;
+ label = 7;
+ break;
+ case 7:
+ $add_ptr7 = $ptr + 2 | 0;
+ $2 = HEAP8[$add_ptr7] | 0;
+ $conv8 = $2 << 24 >> 24;
+ if (($conv8 | 0) == 76) {
+ label = 8;
+ break;
+ } else if (($conv8 | 0) == 108) {
+ label = 9;
+ break;
+ } else {
+ $retval_0 = 1;
+ label = 11;
+ break;
+ }
+ case 8:
+ $retval_0 = 0;
+ label = 11;
+ break;
+ case 9:
+ $tobool = ($upper_1 | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$tokPtr >> 2] = 12;
+ $retval_0 = 1;
+ label = 11;
+ break;
+ case 11:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanAtts($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $ptr_addr = 0, $cmp162 = 0, $type = 0, $0 = 0, $sub_ptr_lhs_cast = 0, $1 = 0, $sub_ptr_lhs_cast9 = 0, $isName3 = 0, $sub_ptr_lhs_cast22 = 0, $isName4 = 0, $sub_ptr_lhs_cast86 = 0, $isInvalid2 = 0, $2 = 0, $sub_ptr_lhs_cast99 = 0, $isInvalid3 = 0, $3 = 0, $sub_ptr_lhs_cast112 = 0, $isInvalid4 = 0, $4 = 0, $sub_ptr_lhs_cast169 = 0, $isNmstrt2 = 0, $sub_ptr_lhs_cast182 = 0, $isNmstrt3 = 0, $sub_ptr_lhs_cast195 = 0, $isNmstrt4 = 0, $5 = 0, $6 = 0, $idxprom = 0, $arrayidx = 0, $7 = 0, $conv = 0, $8 = 0, $add_ptr3571 = 0, $cmp3672 = 0, $9 = 0, $add_ptr = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp3 = 0, $10 = 0, $call = 0, $tobool = 0, $11 = 0, $add_ptr7 = 0, $sub_ptr_rhs_cast10 = 0, $sub_ptr_sub11 = 0, $cmp12 = 0, $12 = 0, $13 = 0, $call16 = 0, $tobool17 = 0, $14 = 0, $add_ptr20 = 0, $sub_ptr_rhs_cast23 = 0, $sub_ptr_sub24 = 0, $cmp25 = 0, $15 = 0, $16 = 0, $call29 = 0, $tobool30 = 0, $17 = 0, $add_ptr33 = 0, $add_ptr3573 = 0, $18 = 0, $idxprom40 = 0, $arrayidx42 = 0, $19 = 0, $cmp44 = 0, $conv43 = 0, $20 = 0, $add_ptr35 = 0, $cmp36 = 0, $21 = 0, $add_ptr5180 = 0, $cmp5281 = 0, $add_ptr5182 = 0, $22 = 0, $23 = 0, $idxprom56 = 0, $arrayidx58 = 0, $24 = 0, $_off = 0, $25 = 0, $conv59 = 0, $26 = 0, $add_ptr51 = 0, $cmp52 = 0, $add_ptr70 = 0, $cmp7395 = 0, $27 = 0, $28 = 0, $idxprom77 = 0, $arrayidx79 = 0, $29 = 0, $cmp81 = 0, $conv80 = 0, $sub_ptr_rhs_cast87 = 0, $sub_ptr_sub88 = 0, $cmp89 = 0, $30 = 0, $call93 = 0, $tobool94 = 0, $31 = 0, $add_ptr97 = 0, $sub_ptr_rhs_cast100 = 0, $sub_ptr_sub101 = 0, $cmp102 = 0, $32 = 0, $call106 = 0, $tobool107 = 0, $33 = 0, $add_ptr110 = 0, $sub_ptr_rhs_cast113 = 0, $sub_ptr_sub114 = 0, $cmp115 = 0, $34 = 0, $call119 = 0, $tobool120 = 0, $35 = 0, $add_ptr123 = 0, $36 = 0, $add_ptr126 = 0, $call127 = 0, $cmp128 = 0, $37 = 0, $cmp73 = 0, $cmp131 = 0, $38 = 0, $add_ptr138 = 0, $add_ptr141 = 0, $cmp142 = 0, $39 = 0, $idxprom146 = 0, $arrayidx148 = 0, $40 = 0, $conv149 = 0, $41 = 0, $add_ptr156105 = 0, $cmp157106 = 0, $add_ptr156107 = 0, $42 = 0, $idxprom161 = 0, $arrayidx163 = 0, $43 = 0, $conv164 = 0, $44 = 0, $add_ptr156 = 0, $cmp157 = 0, $45 = 0, $add_ptr167 = 0, $sub_ptr_rhs_cast170 = 0, $sub_ptr_sub171 = 0, $cmp172 = 0, $46 = 0, $47 = 0, $call176 = 0, $tobool177 = 0, $48 = 0, $add_ptr180 = 0, $sub_ptr_rhs_cast183 = 0, $sub_ptr_sub184 = 0, $cmp185 = 0, $49 = 0, $50 = 0, $call189 = 0, $tobool190 = 0, $51 = 0, $add_ptr193 = 0, $sub_ptr_rhs_cast196 = 0, $sub_ptr_sub197 = 0, $cmp198 = 0, $52 = 0, $53 = 0, $call202 = 0, $tobool203 = 0, $54 = 0, $add_ptr206 = 0, $55 = 0, $cmp = 0, $56 = 0, $add_ptr209 = 0, $57 = 0, $add_ptr211 = 0, $cmp212 = 0, $58 = 0, $cmp217 = 0, $add_ptr221 = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 8 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr_addr = __stackBase__ | 0;
+ HEAP32[$ptr_addr >> 2] = $ptr;
+ $cmp162 = ($ptr | 0) == ($end | 0);
+ if ($cmp162) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $sub_ptr_lhs_cast = $end;
+ $1 = $enc + 328 | 0;
+ $sub_ptr_lhs_cast9 = $end;
+ $isName3 = $enc + 332 | 0;
+ $sub_ptr_lhs_cast22 = $end;
+ $isName4 = $enc + 336 | 0;
+ $sub_ptr_lhs_cast86 = $end;
+ $isInvalid2 = $enc + 352 | 0;
+ $2 = $isInvalid2;
+ $sub_ptr_lhs_cast99 = $end;
+ $isInvalid3 = $enc + 356 | 0;
+ $3 = $isInvalid3;
+ $sub_ptr_lhs_cast112 = $end;
+ $isInvalid4 = $enc + 360 | 0;
+ $4 = $isInvalid4;
+ $sub_ptr_lhs_cast169 = $end;
+ $isNmstrt2 = $enc + 340 | 0;
+ $sub_ptr_lhs_cast182 = $end;
+ $isNmstrt3 = $enc + 344 | 0;
+ $sub_ptr_lhs_cast195 = $end;
+ $isNmstrt4 = $enc + 348 | 0;
+ $5 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $6 = HEAP8[$5] | 0;
+ $idxprom = $6 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $7 = HEAP8[$arrayidx] | 0;
+ $conv = $7 & 255;
+ if (($conv | 0) == 21 | ($conv | 0) == 9 | ($conv | 0) == 10) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 29) {
+ label = 6;
+ break;
+ } else if (($conv | 0) == 22 | ($conv | 0) == 24 | ($conv | 0) == 25 | ($conv | 0) == 26 | ($conv | 0) == 27) {
+ label = 7;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 16;
+ break;
+ } else if (($conv | 0) == 14) {
+ label = 24;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 5:
+ $8 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr3571 = $8 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr3571;
+ $cmp3672 = ($add_ptr3571 | 0) == ($end | 0);
+ if ($cmp3672) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $add_ptr3573 = $add_ptr3571;
+ label = 20;
+ break;
+ }
+ case 6:
+ HEAP32[$nextTokPtr >> 2] = $5;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 7:
+ $9 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr = $9 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr;
+ label = 71;
+ break;
+ case 8:
+ $sub_ptr_rhs_cast = $5;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp3 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp3) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $10 = HEAP32[$1 >> 2] | 0;
+ $call = FUNCTION_TABLE_iii[$10 & 1023]($enc, $5) | 0;
+ $tobool = ($call | 0) == 0;
+ $11 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $11;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 11:
+ $add_ptr7 = $11 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr7;
+ label = 71;
+ break;
+ case 12:
+ $sub_ptr_rhs_cast10 = $5;
+ $sub_ptr_sub11 = $sub_ptr_lhs_cast9 - $sub_ptr_rhs_cast10 | 0;
+ $cmp12 = ($sub_ptr_sub11 | 0) < 3;
+ if ($cmp12) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $12 = HEAP32[$isName3 >> 2] | 0;
+ $13 = $12;
+ $call16 = FUNCTION_TABLE_iii[$13 & 1023]($enc, $5) | 0;
+ $tobool17 = ($call16 | 0) == 0;
+ $14 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool17) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $14;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 15:
+ $add_ptr20 = $14 + 3 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr20;
+ label = 71;
+ break;
+ case 16:
+ $sub_ptr_rhs_cast23 = $5;
+ $sub_ptr_sub24 = $sub_ptr_lhs_cast22 - $sub_ptr_rhs_cast23 | 0;
+ $cmp25 = ($sub_ptr_sub24 | 0) < 4;
+ if ($cmp25) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $15 = HEAP32[$isName4 >> 2] | 0;
+ $16 = $15;
+ $call29 = FUNCTION_TABLE_iii[$16 & 1023]($enc, $5) | 0;
+ $tobool30 = ($call29 | 0) == 0;
+ $17 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool30) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $17;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 19:
+ $add_ptr33 = $17 + 4 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr33;
+ label = 71;
+ break;
+ case 20:
+ $18 = HEAP8[$add_ptr3573] | 0;
+ $idxprom40 = $18 & 255;
+ $arrayidx42 = $0 + $idxprom40 | 0;
+ $19 = HEAP8[$arrayidx42] | 0;
+ $cmp44 = $19 << 24 >> 24 == 14;
+ if ($cmp44) {
+ label = 24;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $conv43 = $19 & 255;
+ if (($conv43 | 0) == 21 | ($conv43 | 0) == 10 | ($conv43 | 0) == 9) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $20 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr35 = $20 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr35;
+ $cmp36 = ($add_ptr35 | 0) == ($end | 0);
+ if ($cmp36) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $add_ptr3573 = $add_ptr35;
+ label = 20;
+ break;
+ }
+ case 23:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr3573;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 24:
+ $21 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr5180 = $21 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr5180;
+ $cmp5281 = ($add_ptr5180 | 0) == ($end | 0);
+ if ($cmp5281) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $22 = $21;
+ $add_ptr5182 = $add_ptr5180;
+ label = 25;
+ break;
+ }
+ case 25:
+ $23 = HEAP8[$add_ptr5182] | 0;
+ $idxprom56 = $23 & 255;
+ $arrayidx58 = $0 + $idxprom56 | 0;
+ $24 = HEAP8[$arrayidx58] | 0;
+ $_off = $24 - 12 & 255;
+ $25 = ($_off & 255) < 2;
+ if ($25) {
+ label = 29;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 26:
+ $conv59 = $24 & 255;
+ if (($conv59 | 0) == 21 | ($conv59 | 0) == 10 | ($conv59 | 0) == 9) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ $26 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr51 = $26 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr51;
+ $cmp52 = ($add_ptr51 | 0) == ($end | 0);
+ if ($cmp52) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $22 = $26;
+ $add_ptr5182 = $add_ptr51;
+ label = 25;
+ break;
+ }
+ case 28:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr5182;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 29:
+ $add_ptr70 = $22 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr70;
+ $cmp7395 = ($add_ptr70 | 0) == ($end | 0);
+ if ($cmp7395) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $27 = $add_ptr70;
+ label = 30;
+ break;
+ }
+ case 30:
+ $28 = HEAP8[$27] | 0;
+ $idxprom77 = $28 & 255;
+ $arrayidx79 = $0 + $idxprom77 | 0;
+ $29 = HEAP8[$arrayidx79] | 0;
+ $cmp81 = $29 << 24 >> 24 == $24 << 24 >> 24;
+ if ($cmp81) {
+ label = 51;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $conv80 = $29 & 255;
+ if (($conv80 | 0) == 5) {
+ label = 32;
+ break;
+ } else if (($conv80 | 0) == 6) {
+ label = 36;
+ break;
+ } else if (($conv80 | 0) == 7) {
+ label = 40;
+ break;
+ } else if (($conv80 | 0) == 0 | ($conv80 | 0) == 1 | ($conv80 | 0) == 8) {
+ label = 44;
+ break;
+ } else if (($conv80 | 0) == 3) {
+ label = 45;
+ break;
+ } else if (($conv80 | 0) == 2) {
+ label = 49;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 32:
+ $sub_ptr_rhs_cast87 = $27;
+ $sub_ptr_sub88 = $sub_ptr_lhs_cast86 - $sub_ptr_rhs_cast87 | 0;
+ $cmp89 = ($sub_ptr_sub88 | 0) < 2;
+ if ($cmp89) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $30 = HEAP32[$2 >> 2] | 0;
+ $call93 = FUNCTION_TABLE_iii[$30 & 1023]($enc, $27) | 0;
+ $tobool94 = ($call93 | 0) == 0;
+ $31 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool94) {
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ HEAP32[$nextTokPtr >> 2] = $31;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 35:
+ $add_ptr97 = $31 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr97;
+ label = 46;
+ break;
+ case 36:
+ $sub_ptr_rhs_cast100 = $27;
+ $sub_ptr_sub101 = $sub_ptr_lhs_cast99 - $sub_ptr_rhs_cast100 | 0;
+ $cmp102 = ($sub_ptr_sub101 | 0) < 3;
+ if ($cmp102) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $32 = HEAP32[$3 >> 2] | 0;
+ $call106 = FUNCTION_TABLE_iii[$32 & 1023]($enc, $27) | 0;
+ $tobool107 = ($call106 | 0) == 0;
+ $33 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool107) {
+ label = 39;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $33;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 39:
+ $add_ptr110 = $33 + 3 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr110;
+ label = 46;
+ break;
+ case 40:
+ $sub_ptr_rhs_cast113 = $27;
+ $sub_ptr_sub114 = $sub_ptr_lhs_cast112 - $sub_ptr_rhs_cast113 | 0;
+ $cmp115 = ($sub_ptr_sub114 | 0) < 4;
+ if ($cmp115) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $34 = HEAP32[$4 >> 2] | 0;
+ $call119 = FUNCTION_TABLE_iii[$34 & 1023]($enc, $27) | 0;
+ $tobool120 = ($call119 | 0) == 0;
+ $35 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool120) {
+ label = 43;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ HEAP32[$nextTokPtr >> 2] = $35;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 43:
+ $add_ptr123 = $35 + 4 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr123;
+ label = 46;
+ break;
+ case 44:
+ $36 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $36;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 45:
+ $add_ptr126 = $27 + 1 | 0;
+ $call127 = _normal_scanRef($enc, $add_ptr126, $end, $ptr_addr) | 0;
+ $cmp128 = ($call127 | 0) < 1;
+ if ($cmp128) {
+ label = 47;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $37 = HEAP32[$ptr_addr >> 2] | 0;
+ $cmp73 = ($37 | 0) == ($end | 0);
+ if ($cmp73) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $27 = $37;
+ label = 30;
+ break;
+ }
+ case 47:
+ $cmp131 = ($call127 | 0) == 0;
+ if ($cmp131) {
+ label = 48;
+ break;
+ } else {
+ $retval_0 = $call127;
+ label = 79;
+ break;
+ }
+ case 48:
+ $38 = HEAP32[$ptr_addr >> 2] | 0;
+ HEAP32[$nextTokPtr >> 2] = $38;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 49:
+ HEAP32[$nextTokPtr >> 2] = $27;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 50:
+ $add_ptr138 = $27 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr138;
+ label = 46;
+ break;
+ case 51:
+ $add_ptr141 = $27 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr141;
+ $cmp142 = ($add_ptr141 | 0) == ($end | 0);
+ if ($cmp142) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $39 = HEAP8[$add_ptr141] | 0;
+ $idxprom146 = $39 & 255;
+ $arrayidx148 = $0 + $idxprom146 | 0;
+ $40 = HEAP8[$arrayidx148] | 0;
+ $conv149 = $40 & 255;
+ if (($conv149 | 0) == 21 | ($conv149 | 0) == 9 | ($conv149 | 0) == 10) {
+ label = 53;
+ break;
+ } else if (($conv149 | 0) == 11) {
+ label = 72;
+ break;
+ } else if (($conv149 | 0) == 17) {
+ label = 73;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 53:
+ $41 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr156105 = $41 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr156105;
+ $cmp157106 = ($add_ptr156105 | 0) == ($end | 0);
+ if ($cmp157106) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $add_ptr156107 = $add_ptr156105;
+ label = 55;
+ break;
+ }
+ case 54:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr141;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 55:
+ $42 = HEAP8[$add_ptr156107] | 0;
+ $idxprom161 = $42 & 255;
+ $arrayidx163 = $0 + $idxprom161 | 0;
+ $43 = HEAP8[$arrayidx163] | 0;
+ $conv164 = $43 & 255;
+ if (($conv164 | 0) == 21 | ($conv164 | 0) == 9 | ($conv164 | 0) == 10) {
+ label = 56;
+ break;
+ } else if (($conv164 | 0) == 29) {
+ label = 57;
+ break;
+ } else if (($conv164 | 0) == 22 | ($conv164 | 0) == 24) {
+ label = 58;
+ break;
+ } else if (($conv164 | 0) == 5) {
+ label = 59;
+ break;
+ } else if (($conv164 | 0) == 6) {
+ label = 63;
+ break;
+ } else if (($conv164 | 0) == 7) {
+ label = 67;
+ break;
+ } else if (($conv164 | 0) == 11) {
+ label = 72;
+ break;
+ } else if (($conv164 | 0) == 17) {
+ label = 73;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 56:
+ $44 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr156 = $44 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr156;
+ $cmp157 = ($add_ptr156 | 0) == ($end | 0);
+ if ($cmp157) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $add_ptr156107 = $add_ptr156;
+ label = 55;
+ break;
+ }
+ case 57:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr156107;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 58:
+ $45 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr167 = $45 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr167;
+ label = 71;
+ break;
+ case 59:
+ $sub_ptr_rhs_cast170 = $add_ptr156107;
+ $sub_ptr_sub171 = $sub_ptr_lhs_cast169 - $sub_ptr_rhs_cast170 | 0;
+ $cmp172 = ($sub_ptr_sub171 | 0) < 2;
+ if ($cmp172) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $46 = HEAP32[$isNmstrt2 >> 2] | 0;
+ $47 = $46;
+ $call176 = FUNCTION_TABLE_iii[$47 & 1023]($enc, $add_ptr156107) | 0;
+ $tobool177 = ($call176 | 0) == 0;
+ $48 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool177) {
+ label = 61;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 61:
+ HEAP32[$nextTokPtr >> 2] = $48;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 62:
+ $add_ptr180 = $48 + 2 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr180;
+ label = 71;
+ break;
+ case 63:
+ $sub_ptr_rhs_cast183 = $add_ptr156107;
+ $sub_ptr_sub184 = $sub_ptr_lhs_cast182 - $sub_ptr_rhs_cast183 | 0;
+ $cmp185 = ($sub_ptr_sub184 | 0) < 3;
+ if ($cmp185) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 64:
+ $49 = HEAP32[$isNmstrt3 >> 2] | 0;
+ $50 = $49;
+ $call189 = FUNCTION_TABLE_iii[$50 & 1023]($enc, $add_ptr156107) | 0;
+ $tobool190 = ($call189 | 0) == 0;
+ $51 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool190) {
+ label = 65;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 65:
+ HEAP32[$nextTokPtr >> 2] = $51;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 66:
+ $add_ptr193 = $51 + 3 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr193;
+ label = 71;
+ break;
+ case 67:
+ $sub_ptr_rhs_cast196 = $add_ptr156107;
+ $sub_ptr_sub197 = $sub_ptr_lhs_cast195 - $sub_ptr_rhs_cast196 | 0;
+ $cmp198 = ($sub_ptr_sub197 | 0) < 4;
+ if ($cmp198) {
+ $retval_0 = -2;
+ label = 79;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 68:
+ $52 = HEAP32[$isNmstrt4 >> 2] | 0;
+ $53 = $52;
+ $call202 = FUNCTION_TABLE_iii[$53 & 1023]($enc, $add_ptr156107) | 0;
+ $tobool203 = ($call202 | 0) == 0;
+ $54 = HEAP32[$ptr_addr >> 2] | 0;
+ if ($tobool203) {
+ label = 69;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 69:
+ HEAP32[$nextTokPtr >> 2] = $54;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 70:
+ $add_ptr206 = $54 + 4 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr206;
+ label = 71;
+ break;
+ case 71:
+ $55 = HEAP32[$ptr_addr >> 2] | 0;
+ $cmp = ($55 | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ $5 = $55;
+ label = 4;
+ break;
+ }
+ case 72:
+ $56 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr209 = $56 + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr209;
+ $retval_0 = 1;
+ label = 79;
+ break;
+ case 73:
+ $57 = HEAP32[$ptr_addr >> 2] | 0;
+ $add_ptr211 = $57 + 1 | 0;
+ HEAP32[$ptr_addr >> 2] = $add_ptr211;
+ $cmp212 = ($add_ptr211 | 0) == ($end | 0);
+ if ($cmp212) {
+ $retval_0 = -1;
+ label = 79;
+ break;
+ } else {
+ label = 74;
+ break;
+ }
+ case 74:
+ $58 = HEAP8[$add_ptr211] | 0;
+ $cmp217 = $58 << 24 >> 24 == 62;
+ if ($cmp217) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr211;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 76:
+ $add_ptr221 = $57 + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr221;
+ $retval_0 = 3;
+ label = 79;
+ break;
+ case 77:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr156107;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 78:
+ HEAP32[$nextTokPtr >> 2] = $5;
+ $retval_0 = 0;
+ label = 79;
+ break;
+ case 79:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanLit($open, $enc, $ptr, $end, $nextTokPtr) {
+ $open = $open | 0;
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp42 = 0, $type = 0, $0 = 0, $sub_ptr_lhs_cast = 0, $isInvalid2 = 0, $1 = 0, $sub_ptr_lhs_cast6 = 0, $isInvalid3 = 0, $2 = 0, $sub_ptr_lhs_cast19 = 0, $isInvalid4 = 0, $3 = 0, $ptr_addr_043 = 0, $4 = 0, $idxprom = 0, $arrayidx = 0, $5 = 0, $conv = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp1 = 0, $6 = 0, $call = 0, $tobool = 0, $add_ptr = 0, $sub_ptr_rhs_cast7 = 0, $sub_ptr_sub8 = 0, $cmp9 = 0, $7 = 0, $call13 = 0, $tobool14 = 0, $add_ptr17 = 0, $sub_ptr_rhs_cast20 = 0, $sub_ptr_sub21 = 0, $cmp22 = 0, $8 = 0, $call26 = 0, $tobool27 = 0, $add_ptr30 = 0, $add_ptr33 = 0, $cmp34 = 0, $cmp38 = 0, $9 = 0, $idxprom42 = 0, $arrayidx44 = 0, $10 = 0, $conv45 = 0, $add_ptr48 = 0, $ptr_addr_0_be = 0, $cmp = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp42 = ($ptr | 0) == ($end | 0);
+ if ($cmp42) {
+ $retval_0 = -1;
+ label = 24;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $type = $enc + 72 | 0;
+ $0 = $type;
+ $sub_ptr_lhs_cast = $end;
+ $isInvalid2 = $enc + 352 | 0;
+ $1 = $isInvalid2;
+ $sub_ptr_lhs_cast6 = $end;
+ $isInvalid3 = $enc + 356 | 0;
+ $2 = $isInvalid3;
+ $sub_ptr_lhs_cast19 = $end;
+ $isInvalid4 = $enc + 360 | 0;
+ $3 = $isInvalid4;
+ $ptr_addr_043 = $ptr;
+ label = 4;
+ break;
+ case 4:
+ $4 = HEAP8[$ptr_addr_043] | 0;
+ $idxprom = $4 & 255;
+ $arrayidx = $0 + $idxprom | 0;
+ $5 = HEAP8[$arrayidx] | 0;
+ $conv = $5 & 255;
+ if (($conv | 0) == 5) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 9;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 13;
+ break;
+ } else if (($conv | 0) == 0 | ($conv | 0) == 1 | ($conv | 0) == 8) {
+ label = 17;
+ break;
+ } else if (($conv | 0) == 12 | ($conv | 0) == 13) {
+ label = 18;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 5:
+ $sub_ptr_rhs_cast = $ptr_addr_043;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp1 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp1) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $6 = HEAP32[$1 >> 2] | 0;
+ $call = FUNCTION_TABLE_iii[$6 & 1023]($enc, $ptr_addr_043) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_043;
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 8:
+ $add_ptr = $ptr_addr_043 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr;
+ label = 23;
+ break;
+ case 9:
+ $sub_ptr_rhs_cast7 = $ptr_addr_043;
+ $sub_ptr_sub8 = $sub_ptr_lhs_cast6 - $sub_ptr_rhs_cast7 | 0;
+ $cmp9 = ($sub_ptr_sub8 | 0) < 3;
+ if ($cmp9) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $7 = HEAP32[$2 >> 2] | 0;
+ $call13 = FUNCTION_TABLE_iii[$7 & 1023]($enc, $ptr_addr_043) | 0;
+ $tobool14 = ($call13 | 0) == 0;
+ if ($tobool14) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_043;
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 12:
+ $add_ptr17 = $ptr_addr_043 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr17;
+ label = 23;
+ break;
+ case 13:
+ $sub_ptr_rhs_cast20 = $ptr_addr_043;
+ $sub_ptr_sub21 = $sub_ptr_lhs_cast19 - $sub_ptr_rhs_cast20 | 0;
+ $cmp22 = ($sub_ptr_sub21 | 0) < 4;
+ if ($cmp22) {
+ $retval_0 = -2;
+ label = 24;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $8 = HEAP32[$3 >> 2] | 0;
+ $call26 = FUNCTION_TABLE_iii[$8 & 1023]($enc, $ptr_addr_043) | 0;
+ $tobool27 = ($call26 | 0) == 0;
+ if ($tobool27) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_043;
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 16:
+ $add_ptr30 = $ptr_addr_043 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr30;
+ label = 23;
+ break;
+ case 17:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_043;
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 18:
+ $add_ptr33 = $ptr_addr_043 + 1 | 0;
+ $cmp34 = ($conv | 0) == ($open | 0);
+ if ($cmp34) {
+ label = 19;
+ break;
+ } else {
+ $ptr_addr_0_be = $add_ptr33;
+ label = 23;
+ break;
+ }
+ case 19:
+ $cmp38 = ($add_ptr33 | 0) == ($end | 0);
+ if ($cmp38) {
+ $retval_0 = -27;
+ label = 24;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr33;
+ $9 = HEAP8[$add_ptr33] | 0;
+ $idxprom42 = $9 & 255;
+ $arrayidx44 = $0 + $idxprom42 | 0;
+ $10 = HEAP8[$arrayidx44] | 0;
+ $conv45 = $10 & 255;
+ if (($conv45 | 0) == 21 | ($conv45 | 0) == 9 | ($conv45 | 0) == 10 | ($conv45 | 0) == 11 | ($conv45 | 0) == 30 | ($conv45 | 0) == 20) {
+ $retval_0 = 27;
+ label = 24;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $retval_0 = 0;
+ label = 24;
+ break;
+ case 22:
+ $add_ptr48 = $ptr_addr_043 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr48;
+ label = 23;
+ break;
+ case 23:
+ $cmp = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_043 = $ptr_addr_0_be;
+ label = 4;
+ break;
+ }
+ case 24:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _normal_scanDecl($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $ptr_addr_032 = 0, $cmp533 = 0, $add_ptr = 0, $call = 0, $add_ptr2 = 0, $ptr_addr_035 = 0, $ptr_pn34 = 0, $3 = 0, $idxprom7 = 0, $arrayidx9 = 0, $4 = 0, $conv10 = 0, $ptr_addr_0 = 0, $cmp5 = 0, $add_ptr12 = 0, $cmp13 = 0, $5 = 0, $idxprom18 = 0, $arrayidx20 = 0, $6 = 0, $conv21 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 15;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 27) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 20) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 4:
+ $ptr_addr_032 = $ptr + 1 | 0;
+ $cmp533 = ($ptr_addr_032 | 0) == ($end | 0);
+ if ($cmp533) {
+ $retval_0 = -1;
+ label = 15;
+ break;
+ } else {
+ $ptr_pn34 = $ptr;
+ $ptr_addr_035 = $ptr_addr_032;
+ label = 8;
+ break;
+ }
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $call = _normal_scanComment($enc, $add_ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 15;
+ break;
+ case 6:
+ $add_ptr2 = $ptr + 1 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr2;
+ $retval_0 = 33;
+ label = 15;
+ break;
+ case 7:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 15;
+ break;
+ case 8:
+ $3 = HEAP8[$ptr_addr_035] | 0;
+ $idxprom7 = $3 & 255;
+ $arrayidx9 = $1 + $idxprom7 | 0;
+ $4 = HEAP8[$arrayidx9] | 0;
+ $conv10 = $4 & 255;
+ if (($conv10 | 0) == 22 | ($conv10 | 0) == 24) {
+ label = 9;
+ break;
+ } else if (($conv10 | 0) == 30) {
+ label = 10;
+ break;
+ } else if (($conv10 | 0) == 21 | ($conv10 | 0) == 9 | ($conv10 | 0) == 10) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 9:
+ $ptr_addr_0 = $ptr_addr_035 + 1 | 0;
+ $cmp5 = ($ptr_addr_0 | 0) == ($end | 0);
+ if ($cmp5) {
+ $retval_0 = -1;
+ label = 15;
+ break;
+ } else {
+ $ptr_pn34 = $ptr_addr_035;
+ $ptr_addr_035 = $ptr_addr_0;
+ label = 8;
+ break;
+ }
+ case 10:
+ $add_ptr12 = $ptr_pn34 + 2 | 0;
+ $cmp13 = ($add_ptr12 | 0) == ($end | 0);
+ if ($cmp13) {
+ $retval_0 = -1;
+ label = 15;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $5 = HEAP8[$add_ptr12] | 0;
+ $idxprom18 = $5 & 255;
+ $arrayidx20 = $1 + $idxprom18 | 0;
+ $6 = HEAP8[$arrayidx20] | 0;
+ $conv21 = $6 & 255;
+ if (($conv21 | 0) == 21 | ($conv21 | 0) == 9 | ($conv21 | 0) == 10 | ($conv21 | 0) == 30) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_035;
+ $retval_0 = 0;
+ label = 15;
+ break;
+ case 13:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_035;
+ $retval_0 = 16;
+ label = 15;
+ break;
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_035;
+ $retval_0 = 0;
+ label = 15;
+ break;
+ case 15:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _isSpace($c) {
+ $c = $c | 0;
+ var $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ if (($c | 0) == 32 | ($c | 0) == 13 | ($c | 0) == 10 | ($c | 0) == 9) {
+ $retval_0 = 1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $retval_0 = 0;
+ label = 4;
+ break;
+ case 4:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _ascii_toUtf8($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $cmp3 = 0, $1 = 0, $2 = 0, $cmp1 = 0, $incdec_ptr = 0, $3 = 0, $4 = 0, $incdec_ptr2 = 0, $5 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $cmp3 = ($0 | 0) == ($fromLim | 0);
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ $1 = $0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$toP >> 2] | 0;
+ $cmp1 = ($2 | 0) == ($toLim | 0);
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $1 + 1 | 0;
+ HEAP32[$fromP >> 2] = $incdec_ptr;
+ $3 = HEAP8[$1] | 0;
+ $4 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr2 = $4 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr2;
+ HEAP8[$4] = $3;
+ $5 = HEAP32[$fromP >> 2] | 0;
+ $cmp = ($5 | 0) == ($fromLim | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $1 = $5;
+ label = 3;
+ break;
+ }
+ case 5:
+ return;
+ }
+}
+function _latin1_toUtf16($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $0 = 0, $cmp3 = 0, $1 = 0, $2 = 0, $cmp1 = 0, $incdec_ptr = 0, $3 = 0, $conv = 0, $4 = 0, $incdec_ptr2 = 0, $5 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $cmp3 = ($0 | 0) == ($fromLim | 0);
+ if ($cmp3) {
+ label = 5;
+ break;
+ } else {
+ $1 = $0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP32[$toP >> 2] | 0;
+ $cmp1 = ($2 | 0) == ($toLim | 0);
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $incdec_ptr = $1 + 1 | 0;
+ HEAP32[$fromP >> 2] = $incdec_ptr;
+ $3 = HEAP8[$1] | 0;
+ $conv = $3 & 255;
+ $4 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr2 = $4 + 2 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr2;
+ HEAP16[$4 >> 1] = $conv;
+ $5 = HEAP32[$fromP >> 2] | 0;
+ $cmp = ($5 | 0) == ($fromLim | 0);
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ $1 = $5;
+ label = 3;
+ break;
+ }
+ case 5:
+ return;
+ }
+}
+function _latin1_toUtf8($enc, $fromP, $fromLim, $toP, $toLim) {
+ $enc = $enc | 0;
+ $fromP = $fromP | 0;
+ $fromLim = $fromLim | 0;
+ $toP = $toP | 0;
+ $toLim = $toLim | 0;
+ var $sub_ptr_lhs_cast = 0, $0 = 0, $cmp12 = 0, $1 = 0, $2 = 0, $tobool = 0, $3 = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp2 = 0, $shr11 = 0, $or = 0, $incdec_ptr = 0, $and9 = 0, $or10 = 0, $4 = 0, $incdec_ptr12 = 0, $5 = 0, $incdec_ptr13 = 0, $cmp14 = 0, $incdec_ptr18 = 0, $6 = 0, $7 = 0, $incdec_ptr19 = 0, $8 = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub_ptr_lhs_cast = $toLim;
+ $0 = HEAP32[$fromP >> 2] | 0;
+ $cmp12 = ($0 | 0) == ($fromLim | 0);
+ if ($cmp12) {
+ label = 9;
+ break;
+ } else {
+ $1 = $0;
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP8[$1] | 0;
+ $tobool = $2 << 24 >> 24 > -1;
+ $3 = HEAP32[$toP >> 2] | 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $sub_ptr_rhs_cast = $3;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp2 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp2) {
+ label = 9;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $shr11 = ($2 & 255) >>> 6;
+ $or = $shr11 | -64;
+ $incdec_ptr = $3 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr;
+ HEAP8[$3] = $or;
+ $and9 = $2 & 63;
+ $or10 = $and9 | -128;
+ $4 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr12 = $4 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr12;
+ HEAP8[$4] = $or10;
+ $5 = HEAP32[$fromP >> 2] | 0;
+ $incdec_ptr13 = $5 + 1 | 0;
+ HEAP32[$fromP >> 2] = $incdec_ptr13;
+ label = 8;
+ break;
+ case 6:
+ $cmp14 = ($3 | 0) == ($toLim | 0);
+ if ($cmp14) {
+ label = 9;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $incdec_ptr18 = $1 + 1 | 0;
+ HEAP32[$fromP >> 2] = $incdec_ptr18;
+ $6 = HEAP8[$1] | 0;
+ $7 = HEAP32[$toP >> 2] | 0;
+ $incdec_ptr19 = $7 + 1 | 0;
+ HEAP32[$toP >> 2] = $incdec_ptr19;
+ HEAP8[$7] = $6;
+ label = 8;
+ break;
+ case 8:
+ $8 = HEAP32[$fromP >> 2] | 0;
+ $cmp = ($8 | 0) == ($fromLim | 0);
+ if ($cmp) {
+ label = 9;
+ break;
+ } else {
+ $1 = $8;
+ label = 3;
+ break;
+ }
+ case 9:
+ return;
+ }
+}
+function _normal_scanPoundName($enc, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $0 = 0, $idxprom = 0, $type = 0, $1 = 0, $arrayidx = 0, $2 = 0, $conv = 0, $add_ptr = 0, $ptr_addr_0_ph = 0, $cmp3665 = 0, $sub_ptr_lhs_cast46 = 0, $3 = 0, $sub_ptr_lhs_cast59 = 0, $isName3 = 0, $sub_ptr_lhs_cast72 = 0, $isName4 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp3 = 0, $isNmstrt2 = 0, $4 = 0, $5 = 0, $call = 0, $tobool = 0, $add_ptr9 = 0, $sub_ptr_lhs_cast11 = 0, $sub_ptr_rhs_cast12 = 0, $sub_ptr_sub13 = 0, $cmp14 = 0, $isNmstrt3 = 0, $6 = 0, $7 = 0, $call18 = 0, $tobool19 = 0, $add_ptr22 = 0, $sub_ptr_lhs_cast24 = 0, $sub_ptr_rhs_cast25 = 0, $sub_ptr_sub26 = 0, $cmp27 = 0, $isNmstrt4 = 0, $8 = 0, $9 = 0, $call31 = 0, $tobool32 = 0, $add_ptr35 = 0, $ptr_addr_066 = 0, $10 = 0, $idxprom38 = 0, $arrayidx40 = 0, $11 = 0, $conv41 = 0, $add_ptr44 = 0, $sub_ptr_rhs_cast47 = 0, $sub_ptr_sub48 = 0, $cmp49 = 0, $12 = 0, $call53 = 0, $tobool54 = 0, $add_ptr57 = 0, $sub_ptr_rhs_cast60 = 0, $sub_ptr_sub61 = 0, $cmp62 = 0, $13 = 0, $14 = 0, $call66 = 0, $tobool67 = 0, $add_ptr70 = 0, $sub_ptr_rhs_cast73 = 0, $sub_ptr_sub74 = 0, $cmp75 = 0, $15 = 0, $16 = 0, $call79 = 0, $tobool80 = 0, $add_ptr83 = 0, $ptr_addr_0_be = 0, $cmp36 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 39;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $0 = HEAP8[$ptr] | 0;
+ $idxprom = $0 & 255;
+ $type = $enc + 72 | 0;
+ $1 = $type;
+ $arrayidx = $1 + $idxprom | 0;
+ $2 = HEAP8[$arrayidx] | 0;
+ $conv = $2 & 255;
+ if (($conv | 0) == 29) {
+ label = 4;
+ break;
+ } else if (($conv | 0) == 22 | ($conv | 0) == 24) {
+ label = 5;
+ break;
+ } else if (($conv | 0) == 5) {
+ label = 8;
+ break;
+ } else if (($conv | 0) == 6) {
+ label = 12;
+ break;
+ } else if (($conv | 0) == 7) {
+ label = 16;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 4:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 5:
+ $add_ptr = $ptr + 1 | 0;
+ $ptr_addr_0_ph = $add_ptr;
+ label = 6;
+ break;
+ case 6:
+ $cmp3665 = ($ptr_addr_0_ph | 0) == ($end | 0);
+ if ($cmp3665) {
+ $retval_0 = -20;
+ label = 39;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub_ptr_lhs_cast46 = $end;
+ $3 = $enc + 328 | 0;
+ $sub_ptr_lhs_cast59 = $end;
+ $isName3 = $enc + 332 | 0;
+ $sub_ptr_lhs_cast72 = $end;
+ $isName4 = $enc + 336 | 0;
+ $ptr_addr_066 = $ptr_addr_0_ph;
+ label = 21;
+ break;
+ case 8:
+ $sub_ptr_lhs_cast = $end;
+ $sub_ptr_rhs_cast = $ptr;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp3 = ($sub_ptr_sub | 0) < 2;
+ if ($cmp3) {
+ $retval_0 = -2;
+ label = 39;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $isNmstrt2 = $enc + 340 | 0;
+ $4 = HEAP32[$isNmstrt2 >> 2] | 0;
+ $5 = $4;
+ $call = FUNCTION_TABLE_iii[$5 & 1023]($enc, $ptr) | 0;
+ $tobool = ($call | 0) == 0;
+ if ($tobool) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 11:
+ $add_ptr9 = $ptr + 2 | 0;
+ $ptr_addr_0_ph = $add_ptr9;
+ label = 6;
+ break;
+ case 12:
+ $sub_ptr_lhs_cast11 = $end;
+ $sub_ptr_rhs_cast12 = $ptr;
+ $sub_ptr_sub13 = $sub_ptr_lhs_cast11 - $sub_ptr_rhs_cast12 | 0;
+ $cmp14 = ($sub_ptr_sub13 | 0) < 3;
+ if ($cmp14) {
+ $retval_0 = -2;
+ label = 39;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $isNmstrt3 = $enc + 344 | 0;
+ $6 = HEAP32[$isNmstrt3 >> 2] | 0;
+ $7 = $6;
+ $call18 = FUNCTION_TABLE_iii[$7 & 1023]($enc, $ptr) | 0;
+ $tobool19 = ($call18 | 0) == 0;
+ if ($tobool19) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 15:
+ $add_ptr22 = $ptr + 3 | 0;
+ $ptr_addr_0_ph = $add_ptr22;
+ label = 6;
+ break;
+ case 16:
+ $sub_ptr_lhs_cast24 = $end;
+ $sub_ptr_rhs_cast25 = $ptr;
+ $sub_ptr_sub26 = $sub_ptr_lhs_cast24 - $sub_ptr_rhs_cast25 | 0;
+ $cmp27 = ($sub_ptr_sub26 | 0) < 4;
+ if ($cmp27) {
+ $retval_0 = -2;
+ label = 39;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $isNmstrt4 = $enc + 348 | 0;
+ $8 = HEAP32[$isNmstrt4 >> 2] | 0;
+ $9 = $8;
+ $call31 = FUNCTION_TABLE_iii[$9 & 1023]($enc, $ptr) | 0;
+ $tobool32 = ($call31 | 0) == 0;
+ if ($tobool32) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 19:
+ $add_ptr35 = $ptr + 4 | 0;
+ $ptr_addr_0_ph = $add_ptr35;
+ label = 6;
+ break;
+ case 20:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 21:
+ $10 = HEAP8[$ptr_addr_066] | 0;
+ $idxprom38 = $10 & 255;
+ $arrayidx40 = $1 + $idxprom38 | 0;
+ $11 = HEAP8[$arrayidx40] | 0;
+ $conv41 = $11 & 255;
+ if (($conv41 | 0) == 29) {
+ label = 22;
+ break;
+ } else if (($conv41 | 0) == 22 | ($conv41 | 0) == 24 | ($conv41 | 0) == 25 | ($conv41 | 0) == 26 | ($conv41 | 0) == 27) {
+ label = 23;
+ break;
+ } else if (($conv41 | 0) == 5) {
+ label = 24;
+ break;
+ } else if (($conv41 | 0) == 6) {
+ label = 28;
+ break;
+ } else if (($conv41 | 0) == 7) {
+ label = 32;
+ break;
+ } else if (($conv41 | 0) == 9 | ($conv41 | 0) == 10 | ($conv41 | 0) == 21 | ($conv41 | 0) == 32 | ($conv41 | 0) == 11 | ($conv41 | 0) == 30 | ($conv41 | 0) == 36) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 22:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_066;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 23:
+ $add_ptr44 = $ptr_addr_066 + 1 | 0;
+ $ptr_addr_0_be = $add_ptr44;
+ label = 36;
+ break;
+ case 24:
+ $sub_ptr_rhs_cast47 = $ptr_addr_066;
+ $sub_ptr_sub48 = $sub_ptr_lhs_cast46 - $sub_ptr_rhs_cast47 | 0;
+ $cmp49 = ($sub_ptr_sub48 | 0) < 2;
+ if ($cmp49) {
+ $retval_0 = -2;
+ label = 39;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $12 = HEAP32[$3 >> 2] | 0;
+ $call53 = FUNCTION_TABLE_iii[$12 & 1023]($enc, $ptr_addr_066) | 0;
+ $tobool54 = ($call53 | 0) == 0;
+ if ($tobool54) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_066;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 27:
+ $add_ptr57 = $ptr_addr_066 + 2 | 0;
+ $ptr_addr_0_be = $add_ptr57;
+ label = 36;
+ break;
+ case 28:
+ $sub_ptr_rhs_cast60 = $ptr_addr_066;
+ $sub_ptr_sub61 = $sub_ptr_lhs_cast59 - $sub_ptr_rhs_cast60 | 0;
+ $cmp62 = ($sub_ptr_sub61 | 0) < 3;
+ if ($cmp62) {
+ $retval_0 = -2;
+ label = 39;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $13 = HEAP32[$isName3 >> 2] | 0;
+ $14 = $13;
+ $call66 = FUNCTION_TABLE_iii[$14 & 1023]($enc, $ptr_addr_066) | 0;
+ $tobool67 = ($call66 | 0) == 0;
+ if ($tobool67) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_066;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 31:
+ $add_ptr70 = $ptr_addr_066 + 3 | 0;
+ $ptr_addr_0_be = $add_ptr70;
+ label = 36;
+ break;
+ case 32:
+ $sub_ptr_rhs_cast73 = $ptr_addr_066;
+ $sub_ptr_sub74 = $sub_ptr_lhs_cast72 - $sub_ptr_rhs_cast73 | 0;
+ $cmp75 = ($sub_ptr_sub74 | 0) < 4;
+ if ($cmp75) {
+ $retval_0 = -2;
+ label = 39;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $15 = HEAP32[$isName4 >> 2] | 0;
+ $16 = $15;
+ $call79 = FUNCTION_TABLE_iii[$16 & 1023]($enc, $ptr_addr_066) | 0;
+ $tobool80 = ($call79 | 0) == 0;
+ if ($tobool80) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_066;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 35:
+ $add_ptr83 = $ptr_addr_066 + 4 | 0;
+ $ptr_addr_0_be = $add_ptr83;
+ label = 36;
+ break;
+ case 36:
+ $cmp36 = ($ptr_addr_0_be | 0) == ($end | 0);
+ if ($cmp36) {
+ $retval_0 = -20;
+ label = 39;
+ break;
+ } else {
+ $ptr_addr_066 = $ptr_addr_0_be;
+ label = 21;
+ break;
+ }
+ case 37:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_066;
+ $retval_0 = 20;
+ label = 39;
+ break;
+ case 38:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_066;
+ $retval_0 = 0;
+ label = 39;
+ break;
+ case 39:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _parsePseudoAttribute($enc, $ptr, $end, $namePtr, $nameEndPtr, $valPtr, $nextTokPtr) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $namePtr = $namePtr | 0;
+ $nameEndPtr = $nameEndPtr | 0;
+ $valPtr = $valPtr | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $call = 0, $call1 = 0, $tobool = 0, $minBytesPerChar = 0, $ptr_addr_0 = 0, $0 = 0, $add_ptr = 0, $call4 = 0, $call5 = 0, $tobool6 = 0, $cmp7 = 0, $ptr_addr_1 = 0, $call10 = 0, $call17 = 0, $tobool18 = 0, $ptr_addr_2 = 0, $1 = 0, $add_ptr22 = 0, $call24 = 0, $call25 = 0, $tobool26 = 0, $cmp28 = 0, $2 = 0, $add_ptr33 = 0, $ptr_addr_3 = 0, $3 = 0, $cmp34 = 0, $4 = 0, $add_ptr38 = 0, $call39 = 0, $call4092 = 0, $tobool4193 = 0, $ptr_addr_494 = 0, $5 = 0, $add_ptr43 = 0, $call44 = 0, $call40 = 0, $tobool41 = 0, $c_0_lcssa = 0, $ptr_addr_4_lcssa = 0, $6 = 0, $add_ptr50 = 0, $call5288 = 0, $sext = 0, $conv53 = 0, $cmp5489 = 0, $call5291 = 0, $ptr_addr_590 = 0, $call52_off = 0, $call52_off83 = 0, $notlhs = 0, $notrhs = 0, $or_cond_not = 0, $call52_off84 = 0, $or_cond3_not = 0, $or_cond86 = 0, $7 = 0, $add_ptr87 = 0, $call52 = 0, $cmp54 = 0, $ptr_addr_5_lcssa = 0, $8 = 0, $add_ptr90 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ HEAP32[$namePtr >> 2] = 0;
+ $retval_0 = 1;
+ label = 32;
+ break;
+ case 4:
+ $call = _toAscii($enc, $ptr, $end) | 0;
+ $call1 = _isSpace($call) | 0;
+ $tobool = ($call1 | 0) == 0;
+ if ($tobool) {
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $minBytesPerChar = $enc + 64 | 0;
+ $ptr_addr_0 = $ptr;
+ label = 7;
+ break;
+ case 6:
+ HEAP32[$nextTokPtr >> 2] = $ptr;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 7:
+ $0 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr = $ptr_addr_0 + $0 | 0;
+ $call4 = _toAscii($enc, $add_ptr, $end) | 0;
+ $call5 = _isSpace($call4) | 0;
+ $tobool6 = ($call5 | 0) == 0;
+ if ($tobool6) {
+ label = 8;
+ break;
+ } else {
+ $ptr_addr_0 = $add_ptr;
+ label = 7;
+ break;
+ }
+ case 8:
+ $cmp7 = ($add_ptr | 0) == ($end | 0);
+ if ($cmp7) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ HEAP32[$namePtr >> 2] = 0;
+ $retval_0 = 1;
+ label = 32;
+ break;
+ case 10:
+ HEAP32[$namePtr >> 2] = $add_ptr;
+ $ptr_addr_1 = $add_ptr;
+ label = 11;
+ break;
+ case 11:
+ $call10 = _toAscii($enc, $ptr_addr_1, $end) | 0;
+ if (($call10 | 0) == (-1 | 0)) {
+ label = 12;
+ break;
+ } else if (($call10 | 0) == 61) {
+ label = 13;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 12:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_1;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 13:
+ HEAP32[$nameEndPtr >> 2] = $ptr_addr_1;
+ $ptr_addr_3 = $ptr_addr_1;
+ label = 20;
+ break;
+ case 14:
+ $call17 = _isSpace($call10) | 0;
+ $tobool18 = ($call17 | 0) == 0;
+ if ($tobool18) {
+ label = 19;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ HEAP32[$nameEndPtr >> 2] = $ptr_addr_1;
+ $ptr_addr_2 = $ptr_addr_1;
+ label = 16;
+ break;
+ case 16:
+ $1 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr22 = $ptr_addr_2 + $1 | 0;
+ $call24 = _toAscii($enc, $add_ptr22, $end) | 0;
+ $call25 = _isSpace($call24) | 0;
+ $tobool26 = ($call25 | 0) == 0;
+ if ($tobool26) {
+ label = 17;
+ break;
+ } else {
+ $ptr_addr_2 = $add_ptr22;
+ label = 16;
+ break;
+ }
+ case 17:
+ $cmp28 = ($call24 | 0) == 61;
+ if ($cmp28) {
+ $ptr_addr_3 = $add_ptr22;
+ label = 20;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ HEAP32[$nextTokPtr >> 2] = $add_ptr22;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 19:
+ $2 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr33 = $ptr_addr_1 + $2 | 0;
+ $ptr_addr_1 = $add_ptr33;
+ label = 11;
+ break;
+ case 20:
+ $3 = HEAP32[$namePtr >> 2] | 0;
+ $cmp34 = ($ptr_addr_3 | 0) == ($3 | 0);
+ if ($cmp34) {
+ label = 21;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 21:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_3;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 22:
+ $4 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr38 = $ptr_addr_3 + $4 | 0;
+ $call39 = _toAscii($enc, $add_ptr38, $end) | 0;
+ $call4092 = _isSpace($call39) | 0;
+ $tobool4193 = ($call4092 | 0) == 0;
+ if ($tobool4193) {
+ $ptr_addr_4_lcssa = $add_ptr38;
+ $c_0_lcssa = $call39;
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_494 = $add_ptr38;
+ label = 23;
+ break;
+ }
+ case 23:
+ $5 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr43 = $ptr_addr_494 + $5 | 0;
+ $call44 = _toAscii($enc, $add_ptr43, $end) | 0;
+ $call40 = _isSpace($call44) | 0;
+ $tobool41 = ($call40 | 0) == 0;
+ if ($tobool41) {
+ $ptr_addr_4_lcssa = $add_ptr43;
+ $c_0_lcssa = $call44;
+ label = 24;
+ break;
+ } else {
+ $ptr_addr_494 = $add_ptr43;
+ label = 23;
+ break;
+ }
+ case 24:
+ if (($c_0_lcssa | 0) == 39 | ($c_0_lcssa | 0) == 34) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_4_lcssa;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 26:
+ $6 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr50 = $ptr_addr_4_lcssa + $6 | 0;
+ HEAP32[$valPtr >> 2] = $add_ptr50;
+ $call5288 = _toAscii($enc, $add_ptr50, $end) | 0;
+ $sext = $c_0_lcssa << 24;
+ $conv53 = $sext >> 24;
+ $cmp5489 = ($call5288 | 0) == ($conv53 | 0);
+ if ($cmp5489) {
+ $ptr_addr_5_lcssa = $add_ptr50;
+ label = 31;
+ break;
+ } else {
+ $ptr_addr_590 = $add_ptr50;
+ $call5291 = $call5288;
+ label = 27;
+ break;
+ }
+ case 27:
+ $call52_off = $call5291 - 97 | 0;
+ $call52_off83 = $call5291 - 65 | 0;
+ $notlhs = $call52_off >>> 0 > 25;
+ $notrhs = $call52_off83 >>> 0 > 25;
+ $or_cond_not = $notrhs & $notlhs;
+ $call52_off84 = $call5291 - 48 | 0;
+ $or_cond3_not = $call52_off84 >>> 0 > 9;
+ $or_cond86 = $or_cond_not & $or_cond3_not;
+ if ($or_cond86) {
+ label = 28;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 28:
+ if (($call5291 | 0) == 95 | ($call5291 | 0) == 46 | ($call5291 | 0) == 45) {
+ label = 30;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ HEAP32[$nextTokPtr >> 2] = $ptr_addr_590;
+ $retval_0 = 0;
+ label = 32;
+ break;
+ case 30:
+ $7 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr87 = $ptr_addr_590 + $7 | 0;
+ $call52 = _toAscii($enc, $add_ptr87, $end) | 0;
+ $cmp54 = ($call52 | 0) == ($conv53 | 0);
+ if ($cmp54) {
+ $ptr_addr_5_lcssa = $add_ptr87;
+ label = 31;
+ break;
+ } else {
+ $ptr_addr_590 = $add_ptr87;
+ $call5291 = $call52;
+ label = 27;
+ break;
+ }
+ case 31:
+ $8 = HEAP32[$minBytesPerChar >> 2] | 0;
+ $add_ptr90 = $ptr_addr_5_lcssa + $8 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr90;
+ $retval_0 = 1;
+ label = 32;
+ break;
+ case 32:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _toAscii($enc, $ptr, $end) {
+ $enc = $enc | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ var $ptr_addr = 0, $buf = 0, $p = 0, $arraydecay = 0, $utf8Convert = 0, $0 = 0, $add_ptr = 0, $1 = 0, $cmp = 0, $2 = 0, $conv = 0, $retval_0 = 0, label = 0, __stackBase__ = 0;
+ __stackBase__ = STACKTOP;
+ STACKTOP = STACKTOP + 24 | 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $ptr_addr = __stackBase__ | 0;
+ $buf = __stackBase__ + 8 | 0;
+ $p = __stackBase__ + 16 | 0;
+ HEAP32[$ptr_addr >> 2] = $ptr;
+ $arraydecay = $buf | 0;
+ HEAP32[$p >> 2] = $arraydecay;
+ $utf8Convert = $enc + 56 | 0;
+ $0 = HEAP32[$utf8Convert >> 2] | 0;
+ $add_ptr = $buf + 1 | 0;
+ FUNCTION_TABLE_viiiii[$0 & 1023]($enc, $ptr_addr, $end, $p, $add_ptr);
+ $1 = HEAP32[$p >> 2] | 0;
+ $cmp = ($1 | 0) == ($arraydecay | 0);
+ if ($cmp) {
+ $retval_0 = -1;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = HEAP8[$arraydecay] | 0;
+ $conv = $2 << 24 >> 24;
+ $retval_0 = $conv;
+ label = 4;
+ break;
+ case 4:
+ STACKTOP = __stackBase__;
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _initScan($enc, $state, $ptr, $end, $nextTokPtr) {
+ $enc = $enc | 0;
+ $state = $state | 0;
+ $ptr = $ptr | 0;
+ $end = $end | 0;
+ $nextTokPtr = $nextTokPtr | 0;
+ var $cmp = 0, $encPtr1 = 0, $0 = 0, $add_ptr = 0, $cmp2 = 0, $cmp4 = 0, $isUtf16 = 0, $1 = 0, $conv = 0, $conv_off = 0, $switch = 0, $2 = 0, $conv7 = 0, $3 = 0, $cmp12 = 0, $or_cond3 = 0, $4 = 0, $conv20 = 0, $shl = 0, $5 = 0, $conv22 = 0, $or = 0, $isUtf1625 = 0, $6 = 0, $cmp27 = 0, $cmp30 = 0, $or_cond4 = 0, $add_ptr34 = 0, $isUtf1638 = 0, $7 = 0, $_off = 0, $switch6 = 0, $cmp48 = 0, $or_cond7 = 0, $arrayidx53 = 0, $8 = 0, $call = 0, $isUtf1656 = 0, $9 = 0, $cmp58 = 0, $cmp61 = 0, $or_cond5 = 0, $add_ptr65 = 0, $cmp68 = 0, $isUtf1672 = 0, $10 = 0, $add_ptr88 = 0, $cmp89 = 0, $11 = 0, $cmp95 = 0, $add_ptr98 = 0, $cmp103 = 0, $cmp106 = 0, $isUtf16110 = 0, $12 = 0, $cmp112 = 0, $arrayidx118 = 0, $13 = 0, $call119 = 0, $cmp123 = 0, $cmp126 = 0, $or_cond = 0, $arrayidx132 = 0, $14 = 0, $call133 = 0, $isUtf16139 = 0, $15 = 0, $conv140 = 0, $arrayidx141 = 0, $16 = 0, $arrayidx143 = 0, $17 = 0, $call144 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($ptr | 0) == ($end | 0);
+ if ($cmp) {
+ $retval_0 = -4;
+ label = 27;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $encPtr1 = $enc + 72 | 0;
+ $0 = HEAP32[$encPtr1 >> 2] | 0;
+ $add_ptr = $ptr + 1 | 0;
+ $cmp2 = ($add_ptr | 0) == ($end | 0);
+ if ($cmp2) {
+ label = 4;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 4:
+ $cmp4 = ($state | 0) == 1;
+ if ($cmp4) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = -1;
+ label = 27;
+ break;
+ }
+ case 5:
+ $isUtf16 = $enc + 69 | 0;
+ $1 = HEAP8[$isUtf16] | 0;
+ $conv = $1 << 24 >> 24;
+ $conv_off = $conv - 3 | 0;
+ $switch = $conv_off >>> 0 < 3;
+ if ($switch) {
+ $retval_0 = -1;
+ label = 27;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $2 = HEAP8[$ptr] | 0;
+ $conv7 = $2 & 255;
+ if (($conv7 | 0) == 254 | ($conv7 | 0) == 255 | ($conv7 | 0) == 239) {
+ label = 7;
+ break;
+ } else if (($conv7 | 0) == 0 | ($conv7 | 0) == 60) {
+ $retval_0 = -1;
+ label = 27;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 7:
+ $3 = HEAP8[$isUtf16] | 0;
+ $cmp12 = $3 << 24 >> 24 == 0;
+ $or_cond3 = $cmp12 & $cmp4;
+ if ($or_cond3) {
+ label = 26;
+ break;
+ } else {
+ $retval_0 = -1;
+ label = 27;
+ break;
+ }
+ case 8:
+ $4 = HEAP8[$ptr] | 0;
+ $conv20 = $4 & 255;
+ $shl = $conv20 << 8;
+ $5 = HEAP8[$add_ptr] | 0;
+ $conv22 = $5 & 255;
+ $or = $shl | $conv22;
+ if (($or | 0) == 65279) {
+ label = 9;
+ break;
+ } else if (($or | 0) == 15360) {
+ label = 11;
+ break;
+ } else if (($or | 0) == 65534) {
+ label = 13;
+ break;
+ } else if (($or | 0) == 61371) {
+ label = 15;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 9:
+ $isUtf1625 = $enc + 69 | 0;
+ $6 = HEAP8[$isUtf1625] | 0;
+ $cmp27 = $6 << 24 >> 24 == 0;
+ $cmp30 = ($state | 0) == 1;
+ $or_cond4 = $cmp27 & $cmp30;
+ if ($or_cond4) {
+ label = 26;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $add_ptr34 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr34;
+ HEAP32[$0 >> 2] = 85424;
+ $retval_0 = 14;
+ label = 27;
+ break;
+ case 11:
+ $isUtf1638 = $enc + 69 | 0;
+ $7 = HEAP8[$isUtf1638] | 0;
+ $_off = $7 - 3 & 255;
+ $switch6 = ($_off & 255) < 2;
+ $cmp48 = ($state | 0) == 1;
+ $or_cond7 = $switch6 & $cmp48;
+ if ($or_cond7) {
+ label = 26;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ HEAP32[$0 >> 2] = 11464;
+ $arrayidx53 = 11464 + ($state << 2) | 0;
+ $8 = HEAP32[$arrayidx53 >> 2] | 0;
+ $call = FUNCTION_TABLE_iiiii[$8 & 1023](11464, $ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call;
+ label = 27;
+ break;
+ case 13:
+ $isUtf1656 = $enc + 69 | 0;
+ $9 = HEAP8[$isUtf1656] | 0;
+ $cmp58 = $9 << 24 >> 24 == 0;
+ $cmp61 = ($state | 0) == 1;
+ $or_cond5 = $cmp58 & $cmp61;
+ if ($or_cond5) {
+ label = 26;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $add_ptr65 = $ptr + 2 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr65;
+ HEAP32[$0 >> 2] = 11464;
+ $retval_0 = 14;
+ label = 27;
+ break;
+ case 15:
+ $cmp68 = ($state | 0) == 1;
+ if ($cmp68) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $isUtf1672 = $enc + 69 | 0;
+ $10 = HEAP8[$isUtf1672] | 0;
+ if (($10 << 24 >> 24 | 0) == 5 | ($10 << 24 >> 24 | 0) == 4 | ($10 << 24 >> 24 | 0) == 3 | ($10 << 24 >> 24 | 0) == 0) {
+ label = 26;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $add_ptr88 = $ptr + 2 | 0;
+ $cmp89 = ($add_ptr88 | 0) == ($end | 0);
+ if ($cmp89) {
+ $retval_0 = -1;
+ label = 27;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $11 = HEAP8[$add_ptr88] | 0;
+ $cmp95 = $11 << 24 >> 24 == -65;
+ if ($cmp95) {
+ label = 19;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 19:
+ $add_ptr98 = $ptr + 3 | 0;
+ HEAP32[$nextTokPtr >> 2] = $add_ptr98;
+ HEAP32[$0 >> 2] = 528;
+ $retval_0 = 14;
+ label = 27;
+ break;
+ case 20:
+ $cmp103 = $4 << 24 >> 24 == 0;
+ if ($cmp103) {
+ label = 21;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 21:
+ $cmp106 = ($state | 0) == 1;
+ if ($cmp106) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ $isUtf16110 = $enc + 69 | 0;
+ $12 = HEAP8[$isUtf16110] | 0;
+ $cmp112 = $12 << 24 >> 24 == 5;
+ if ($cmp112) {
+ label = 26;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ HEAP32[$0 >> 2] = 85424;
+ $arrayidx118 = 85424 + ($state << 2) | 0;
+ $13 = HEAP32[$arrayidx118 >> 2] | 0;
+ $call119 = FUNCTION_TABLE_iiiii[$13 & 1023](85424, $ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call119;
+ label = 27;
+ break;
+ case 24:
+ $cmp123 = $5 << 24 >> 24 != 0;
+ $cmp126 = ($state | 0) == 1;
+ $or_cond = $cmp123 | $cmp126;
+ if ($or_cond) {
+ label = 26;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ HEAP32[$0 >> 2] = 11464;
+ $arrayidx132 = 11464 + ($state << 2) | 0;
+ $14 = HEAP32[$arrayidx132 >> 2] | 0;
+ $call133 = FUNCTION_TABLE_iiiii[$14 & 1023](11464, $ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call133;
+ label = 27;
+ break;
+ case 26:
+ $isUtf16139 = $enc + 69 | 0;
+ $15 = HEAP8[$isUtf16139] | 0;
+ $conv140 = $15 << 24 >> 24;
+ $arrayidx141 = 20264 + ($conv140 << 2) | 0;
+ $16 = HEAP32[$arrayidx141 >> 2] | 0;
+ HEAP32[$0 >> 2] = $16;
+ $arrayidx143 = $16 + ($state << 2) | 0;
+ $17 = HEAP32[$arrayidx143 >> 2] | 0;
+ $call144 = FUNCTION_TABLE_iiiii[$17 & 1023]($16, $ptr, $end, $nextTokPtr) | 0;
+ $retval_0 = $call144;
+ label = 27;
+ break;
+ case 27:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _malloc($bytes) {
+ $bytes = $bytes | 0;
+ var $cmp = 0, $cmp1 = 0, $add2 = 0, $and = 0, $cond = 0, $shr = 0, $0 = 0, $shr3 = 0, $and4 = 0, $cmp5 = 0, $neg = 0, $and7 = 0, $add8 = 0, $shl = 0, $arrayidx = 0, $1 = 0, $arrayidx_sum = 0, $2 = 0, $3 = 0, $fd9 = 0, $4 = 0, $cmp10 = 0, $shl12 = 0, $neg13 = 0, $and14 = 0, $5 = 0, $6 = 0, $cmp15 = 0, $bk = 0, $7 = 0, $cmp16 = 0, $shl22 = 0, $or23 = 0, $head = 0, $8 = 0, $add_ptr_sum106 = 0, $head25 = 0, $9 = 0, $10 = 0, $or26 = 0, $11 = 0, $12 = 0, $cmp29 = 0, $cmp31 = 0, $shl35 = 0, $shl37 = 0, $sub = 0, $or40 = 0, $and41 = 0, $sub42 = 0, $and43 = 0, $sub44 = 0, $shr45 = 0, $and46 = 0, $shr47 = 0, $shr48 = 0, $and49 = 0, $add50 = 0, $shr51 = 0, $shr52 = 0, $and53 = 0, $add54 = 0, $shr55 = 0, $shr56 = 0, $and57 = 0, $add58 = 0, $shr59 = 0, $shr60 = 0, $and61 = 0, $add62 = 0, $shr63 = 0, $add64 = 0, $shl65 = 0, $arrayidx66 = 0, $13 = 0, $arrayidx66_sum = 0, $14 = 0, $15 = 0, $fd69 = 0, $16 = 0, $cmp70 = 0, $shl72 = 0, $neg73 = 0, $and74 = 0, $17 = 0, $18 = 0, $cmp76 = 0, $bk78 = 0, $19 = 0, $cmp79 = 0, $shl90 = 0, $sub91 = 0, $or93 = 0, $head94 = 0, $20 = 0, $add_ptr95 = 0, $21 = 0, $or96 = 0, $add_ptr95_sum103 = 0, $head97 = 0, $22 = 0, $add_ptr98 = 0, $prev_foot = 0, $23 = 0, $cmp99 = 0, $24 = 0, $shr101 = 0, $shl102 = 0, $arrayidx103 = 0, $25 = 0, $26 = 0, $shl105 = 0, $and106 = 0, $tobool107 = 0, $or110 = 0, $arrayidx103_sum104 = 0, $27 = 0, $28 = 0, $29 = 0, $30 = 0, $cmp113 = 0, $F104_0 = 0, $arrayidx103_sum = 0, $31 = 0, $bk122 = 0, $fd123 = 0, $bk124 = 0, $32 = 0, $33 = 0, $cmp128 = 0, $call = 0, $cmp130 = 0, $cmp138 = 0, $add143 = 0, $and144 = 0, $34 = 0, $cmp145 = 0, $call148 = 0, $cmp149 = 0, $nb_0 = 0, $35 = 0, $cmp155 = 0, $sub159 = 0, $36 = 0, $cmp161 = 0, $37 = 0, $add_ptr165 = 0, $38 = 0, $or166 = 0, $add_ptr165_sum = 0, $head167 = 0, $39 = 0, $add_ptr168 = 0, $prev_foot169 = 0, $or171 = 0, $head172 = 0, $or175 = 0, $head176 = 0, $40 = 0, $add_ptr177_sum = 0, $head178 = 0, $41 = 0, $42 = 0, $or179 = 0, $add_ptr181 = 0, $43 = 0, $44 = 0, $cmp183 = 0, $sub187 = 0, $45 = 0, $46 = 0, $add_ptr190 = 0, $47 = 0, $or191 = 0, $add_ptr190_sum = 0, $head192 = 0, $48 = 0, $or194 = 0, $head195 = 0, $add_ptr196 = 0, $49 = 0, $call199 = 0, $mem_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = $bytes >>> 0 < 245;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 3:
+ $cmp1 = $bytes >>> 0 < 11;
+ if ($cmp1) {
+ $cond = 16;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $add2 = $bytes + 11 | 0;
+ $and = $add2 & -8;
+ $cond = $and;
+ label = 5;
+ break;
+ case 5:
+ $shr = $cond >>> 3;
+ $0 = HEAP32[40816] | 0;
+ $shr3 = $0 >>> ($shr >>> 0);
+ $and4 = $shr3 & 3;
+ $cmp5 = ($and4 | 0) == 0;
+ if ($cmp5) {
+ label = 13;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $neg = $shr3 & 1;
+ $and7 = $neg ^ 1;
+ $add8 = $and7 + $shr | 0;
+ $shl = $add8 << 1;
+ $arrayidx = 163304 + ($shl << 2) | 0;
+ $1 = $arrayidx;
+ $arrayidx_sum = $shl + 2 | 0;
+ $2 = 163304 + ($arrayidx_sum << 2) | 0;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $fd9 = $3 + 8 | 0;
+ $4 = HEAP32[$fd9 >> 2] | 0;
+ $cmp10 = ($1 | 0) == ($4 | 0);
+ if ($cmp10) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $shl12 = 1 << $add8;
+ $neg13 = $shl12 ^ -1;
+ $and14 = $0 & $neg13;
+ HEAP32[40816] = $and14;
+ label = 12;
+ break;
+ case 8:
+ $5 = $4;
+ $6 = HEAP32[40820] | 0;
+ $cmp15 = $5 >>> 0 < $6 >>> 0;
+ if ($cmp15) {
+ label = 11;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $bk = $4 + 12 | 0;
+ $7 = HEAP32[$bk >> 2] | 0;
+ $cmp16 = ($7 | 0) == ($3 | 0);
+ if ($cmp16) {
+ label = 10;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 10:
+ HEAP32[$bk >> 2] = $1;
+ HEAP32[$2 >> 2] = $4;
+ label = 12;
+ break;
+ case 11:
+ _abort();
+ return 0;
+ return 0;
+ case 12:
+ $shl22 = $add8 << 3;
+ $or23 = $shl22 | 3;
+ $head = $3 + 4 | 0;
+ HEAP32[$head >> 2] = $or23;
+ $8 = $3;
+ $add_ptr_sum106 = $shl22 | 4;
+ $head25 = $8 + $add_ptr_sum106 | 0;
+ $9 = $head25;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $or26 = $10 | 1;
+ HEAP32[$9 >> 2] = $or26;
+ $11 = $fd9;
+ $mem_0 = $11;
+ label = 41;
+ break;
+ case 13:
+ $12 = HEAP32[40818] | 0;
+ $cmp29 = $cond >>> 0 > $12 >>> 0;
+ if ($cmp29) {
+ label = 14;
+ break;
+ } else {
+ $nb_0 = $cond;
+ label = 33;
+ break;
+ }
+ case 14:
+ $cmp31 = ($shr3 | 0) == 0;
+ if ($cmp31) {
+ label = 28;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $shl35 = $shr3 << $shr;
+ $shl37 = 2 << $shr;
+ $sub = -$shl37 | 0;
+ $or40 = $shl37 | $sub;
+ $and41 = $shl35 & $or40;
+ $sub42 = -$and41 | 0;
+ $and43 = $and41 & $sub42;
+ $sub44 = $and43 - 1 | 0;
+ $shr45 = $sub44 >>> 12;
+ $and46 = $shr45 & 16;
+ $shr47 = $sub44 >>> ($and46 >>> 0);
+ $shr48 = $shr47 >>> 5;
+ $and49 = $shr48 & 8;
+ $add50 = $and49 | $and46;
+ $shr51 = $shr47 >>> ($and49 >>> 0);
+ $shr52 = $shr51 >>> 2;
+ $and53 = $shr52 & 4;
+ $add54 = $add50 | $and53;
+ $shr55 = $shr51 >>> ($and53 >>> 0);
+ $shr56 = $shr55 >>> 1;
+ $and57 = $shr56 & 2;
+ $add58 = $add54 | $and57;
+ $shr59 = $shr55 >>> ($and57 >>> 0);
+ $shr60 = $shr59 >>> 1;
+ $and61 = $shr60 & 1;
+ $add62 = $add58 | $and61;
+ $shr63 = $shr59 >>> ($and61 >>> 0);
+ $add64 = $add62 + $shr63 | 0;
+ $shl65 = $add64 << 1;
+ $arrayidx66 = 163304 + ($shl65 << 2) | 0;
+ $13 = $arrayidx66;
+ $arrayidx66_sum = $shl65 + 2 | 0;
+ $14 = 163304 + ($arrayidx66_sum << 2) | 0;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $fd69 = $15 + 8 | 0;
+ $16 = HEAP32[$fd69 >> 2] | 0;
+ $cmp70 = ($13 | 0) == ($16 | 0);
+ if ($cmp70) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $shl72 = 1 << $add64;
+ $neg73 = $shl72 ^ -1;
+ $and74 = $0 & $neg73;
+ HEAP32[40816] = $and74;
+ label = 21;
+ break;
+ case 17:
+ $17 = $16;
+ $18 = HEAP32[40820] | 0;
+ $cmp76 = $17 >>> 0 < $18 >>> 0;
+ if ($cmp76) {
+ label = 20;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $bk78 = $16 + 12 | 0;
+ $19 = HEAP32[$bk78 >> 2] | 0;
+ $cmp79 = ($19 | 0) == ($15 | 0);
+ if ($cmp79) {
+ label = 19;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 19:
+ HEAP32[$bk78 >> 2] = $13;
+ HEAP32[$14 >> 2] = $16;
+ label = 21;
+ break;
+ case 20:
+ _abort();
+ return 0;
+ return 0;
+ case 21:
+ $shl90 = $add64 << 3;
+ $sub91 = $shl90 - $cond | 0;
+ $or93 = $cond | 3;
+ $head94 = $15 + 4 | 0;
+ HEAP32[$head94 >> 2] = $or93;
+ $20 = $15;
+ $add_ptr95 = $20 + $cond | 0;
+ $21 = $add_ptr95;
+ $or96 = $sub91 | 1;
+ $add_ptr95_sum103 = $cond | 4;
+ $head97 = $20 + $add_ptr95_sum103 | 0;
+ $22 = $head97;
+ HEAP32[$22 >> 2] = $or96;
+ $add_ptr98 = $20 + $shl90 | 0;
+ $prev_foot = $add_ptr98;
+ HEAP32[$prev_foot >> 2] = $sub91;
+ $23 = HEAP32[40818] | 0;
+ $cmp99 = ($23 | 0) == 0;
+ if ($cmp99) {
+ label = 27;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $24 = HEAP32[40821] | 0;
+ $shr101 = $23 >>> 3;
+ $shl102 = $shr101 << 1;
+ $arrayidx103 = 163304 + ($shl102 << 2) | 0;
+ $25 = $arrayidx103;
+ $26 = HEAP32[40816] | 0;
+ $shl105 = 1 << $shr101;
+ $and106 = $26 & $shl105;
+ $tobool107 = ($and106 | 0) == 0;
+ if ($tobool107) {
+ label = 23;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 23:
+ $or110 = $26 | $shl105;
+ HEAP32[40816] = $or110;
+ $F104_0 = $25;
+ label = 26;
+ break;
+ case 24:
+ $arrayidx103_sum104 = $shl102 + 2 | 0;
+ $27 = 163304 + ($arrayidx103_sum104 << 2) | 0;
+ $28 = HEAP32[$27 >> 2] | 0;
+ $29 = $28;
+ $30 = HEAP32[40820] | 0;
+ $cmp113 = $29 >>> 0 < $30 >>> 0;
+ if ($cmp113) {
+ label = 25;
+ break;
+ } else {
+ $F104_0 = $28;
+ label = 26;
+ break;
+ }
+ case 25:
+ _abort();
+ return 0;
+ return 0;
+ case 26:
+ $arrayidx103_sum = $shl102 + 2 | 0;
+ $31 = 163304 + ($arrayidx103_sum << 2) | 0;
+ HEAP32[$31 >> 2] = $24;
+ $bk122 = $F104_0 + 12 | 0;
+ HEAP32[$bk122 >> 2] = $24;
+ $fd123 = $24 + 8 | 0;
+ HEAP32[$fd123 >> 2] = $F104_0;
+ $bk124 = $24 + 12 | 0;
+ HEAP32[$bk124 >> 2] = $25;
+ label = 27;
+ break;
+ case 27:
+ HEAP32[40818] = $sub91;
+ HEAP32[40821] = $21;
+ $32 = $fd69;
+ $mem_0 = $32;
+ label = 41;
+ break;
+ case 28:
+ $33 = HEAP32[40817] | 0;
+ $cmp128 = ($33 | 0) == 0;
+ if ($cmp128) {
+ $nb_0 = $cond;
+ label = 33;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $call = _tmalloc_small($cond) | 0;
+ $cmp130 = ($call | 0) == 0;
+ if ($cmp130) {
+ $nb_0 = $cond;
+ label = 33;
+ break;
+ } else {
+ $mem_0 = $call;
+ label = 41;
+ break;
+ }
+ case 30:
+ $cmp138 = $bytes >>> 0 > 4294967231;
+ if ($cmp138) {
+ $nb_0 = -1;
+ label = 33;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 31:
+ $add143 = $bytes + 11 | 0;
+ $and144 = $add143 & -8;
+ $34 = HEAP32[40817] | 0;
+ $cmp145 = ($34 | 0) == 0;
+ if ($cmp145) {
+ $nb_0 = $and144;
+ label = 33;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $call148 = _tmalloc_large($and144) | 0;
+ $cmp149 = ($call148 | 0) == 0;
+ if ($cmp149) {
+ $nb_0 = $and144;
+ label = 33;
+ break;
+ } else {
+ $mem_0 = $call148;
+ label = 41;
+ break;
+ }
+ case 33:
+ $35 = HEAP32[40818] | 0;
+ $cmp155 = $nb_0 >>> 0 > $35 >>> 0;
+ if ($cmp155) {
+ label = 38;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $sub159 = $35 - $nb_0 | 0;
+ $36 = HEAP32[40821] | 0;
+ $cmp161 = $sub159 >>> 0 > 15;
+ if ($cmp161) {
+ label = 35;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 35:
+ $37 = $36;
+ $add_ptr165 = $37 + $nb_0 | 0;
+ $38 = $add_ptr165;
+ HEAP32[40821] = $38;
+ HEAP32[40818] = $sub159;
+ $or166 = $sub159 | 1;
+ $add_ptr165_sum = $nb_0 + 4 | 0;
+ $head167 = $37 + $add_ptr165_sum | 0;
+ $39 = $head167;
+ HEAP32[$39 >> 2] = $or166;
+ $add_ptr168 = $37 + $35 | 0;
+ $prev_foot169 = $add_ptr168;
+ HEAP32[$prev_foot169 >> 2] = $sub159;
+ $or171 = $nb_0 | 3;
+ $head172 = $36 + 4 | 0;
+ HEAP32[$head172 >> 2] = $or171;
+ label = 37;
+ break;
+ case 36:
+ HEAP32[40818] = 0;
+ HEAP32[40821] = 0;
+ $or175 = $35 | 3;
+ $head176 = $36 + 4 | 0;
+ HEAP32[$head176 >> 2] = $or175;
+ $40 = $36;
+ $add_ptr177_sum = $35 + 4 | 0;
+ $head178 = $40 + $add_ptr177_sum | 0;
+ $41 = $head178;
+ $42 = HEAP32[$41 >> 2] | 0;
+ $or179 = $42 | 1;
+ HEAP32[$41 >> 2] = $or179;
+ label = 37;
+ break;
+ case 37:
+ $add_ptr181 = $36 + 8 | 0;
+ $43 = $add_ptr181;
+ $mem_0 = $43;
+ label = 41;
+ break;
+ case 38:
+ $44 = HEAP32[40819] | 0;
+ $cmp183 = $nb_0 >>> 0 < $44 >>> 0;
+ if ($cmp183) {
+ label = 39;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 39:
+ $sub187 = $44 - $nb_0 | 0;
+ HEAP32[40819] = $sub187;
+ $45 = HEAP32[40822] | 0;
+ $46 = $45;
+ $add_ptr190 = $46 + $nb_0 | 0;
+ $47 = $add_ptr190;
+ HEAP32[40822] = $47;
+ $or191 = $sub187 | 1;
+ $add_ptr190_sum = $nb_0 + 4 | 0;
+ $head192 = $46 + $add_ptr190_sum | 0;
+ $48 = $head192;
+ HEAP32[$48 >> 2] = $or191;
+ $or194 = $nb_0 | 3;
+ $head195 = $45 + 4 | 0;
+ HEAP32[$head195 >> 2] = $or194;
+ $add_ptr196 = $45 + 8 | 0;
+ $49 = $add_ptr196;
+ $mem_0 = $49;
+ label = 41;
+ break;
+ case 40:
+ $call199 = _sys_alloc($nb_0) | 0;
+ $mem_0 = $call199;
+ label = 41;
+ break;
+ case 41:
+ return $mem_0 | 0;
+ }
+ return 0;
+}
+function _tmalloc_small($nb) {
+ $nb = $nb | 0;
+ var $0 = 0, $sub = 0, $and = 0, $sub2 = 0, $shr = 0, $and3 = 0, $shr4 = 0, $shr5 = 0, $and6 = 0, $add = 0, $shr7 = 0, $shr8 = 0, $and9 = 0, $add10 = 0, $shr11 = 0, $shr12 = 0, $and13 = 0, $add14 = 0, $shr15 = 0, $shr16 = 0, $and17 = 0, $add18 = 0, $shr19 = 0, $add20 = 0, $arrayidx = 0, $1 = 0, $head = 0, $2 = 0, $and21 = 0, $sub22 = 0, $rsize_0 = 0, $v_0 = 0, $t_0 = 0, $arrayidx23 = 0, $3 = 0, $cmp = 0, $arrayidx27 = 0, $4 = 0, $cmp28 = 0, $cond7 = 0, $head29 = 0, $5 = 0, $and30 = 0, $sub31 = 0, $cmp32 = 0, $sub31_rsize_0 = 0, $cond_v_0 = 0, $6 = 0, $7 = 0, $cmp33 = 0, $add_ptr = 0, $8 = 0, $cmp35 = 0, $parent = 0, $9 = 0, $bk = 0, $10 = 0, $cmp40 = 0, $fd = 0, $11 = 0, $12 = 0, $cmp45 = 0, $bk47 = 0, $13 = 0, $cmp48 = 0, $fd50 = 0, $14 = 0, $cmp51 = 0, $arrayidx61 = 0, $15 = 0, $cmp62 = 0, $arrayidx65 = 0, $16 = 0, $cmp66 = 0, $RP_0 = 0, $R_0 = 0, $arrayidx71 = 0, $17 = 0, $cmp72 = 0, $arrayidx75 = 0, $18 = 0, $cmp76 = 0, $CP_0 = 0, $19 = 0, $20 = 0, $21 = 0, $cmp81 = 0, $R_1 = 0, $cmp90 = 0, $index = 0, $22 = 0, $arrayidx94 = 0, $23 = 0, $cmp95 = 0, $cond5 = 0, $24 = 0, $shl = 0, $neg = 0, $25 = 0, $and103 = 0, $26 = 0, $27 = 0, $cmp107 = 0, $arrayidx113 = 0, $28 = 0, $cmp114 = 0, $arrayidx121 = 0, $cmp126 = 0, $29 = 0, $30 = 0, $cmp130 = 0, $parent135 = 0, $arrayidx137 = 0, $31 = 0, $cmp138 = 0, $32 = 0, $33 = 0, $cmp142 = 0, $arrayidx148 = 0, $parent149 = 0, $arrayidx154 = 0, $34 = 0, $cmp155 = 0, $35 = 0, $36 = 0, $cmp159 = 0, $arrayidx165 = 0, $parent166 = 0, $cmp174 = 0, $add177 = 0, $or178 = 0, $head179 = 0, $add_ptr181_sum = 0, $head182 = 0, $37 = 0, $38 = 0, $or183 = 0, $or186 = 0, $head187 = 0, $or188 = 0, $add_ptr_sum = 0, $head189 = 0, $39 = 0, $add_ptr_sum1 = 0, $add_ptr190 = 0, $prev_foot = 0, $40 = 0, $cmp191 = 0, $41 = 0, $shr194 = 0, $shl195 = 0, $arrayidx196 = 0, $42 = 0, $43 = 0, $shl198 = 0, $and199 = 0, $tobool200 = 0, $or204 = 0, $arrayidx196_sum2 = 0, $44 = 0, $45 = 0, $46 = 0, $47 = 0, $cmp208 = 0, $F197_0 = 0, $arrayidx196_sum = 0, $48 = 0, $bk218 = 0, $fd219 = 0, $bk220 = 0, $add_ptr225 = 0, $49 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[40817] | 0;
+ $sub = -$0 | 0;
+ $and = $0 & $sub;
+ $sub2 = $and - 1 | 0;
+ $shr = $sub2 >>> 12;
+ $and3 = $shr & 16;
+ $shr4 = $sub2 >>> ($and3 >>> 0);
+ $shr5 = $shr4 >>> 5;
+ $and6 = $shr5 & 8;
+ $add = $and6 | $and3;
+ $shr7 = $shr4 >>> ($and6 >>> 0);
+ $shr8 = $shr7 >>> 2;
+ $and9 = $shr8 & 4;
+ $add10 = $add | $and9;
+ $shr11 = $shr7 >>> ($and9 >>> 0);
+ $shr12 = $shr11 >>> 1;
+ $and13 = $shr12 & 2;
+ $add14 = $add10 | $and13;
+ $shr15 = $shr11 >>> ($and13 >>> 0);
+ $shr16 = $shr15 >>> 1;
+ $and17 = $shr16 & 1;
+ $add18 = $add14 | $and17;
+ $shr19 = $shr15 >>> ($and17 >>> 0);
+ $add20 = $add18 + $shr19 | 0;
+ $arrayidx = 163568 + ($add20 << 2) | 0;
+ $1 = HEAP32[$arrayidx >> 2] | 0;
+ $head = $1 + 4 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $and21 = $2 & -8;
+ $sub22 = $and21 - $nb | 0;
+ $t_0 = $1;
+ $v_0 = $1;
+ $rsize_0 = $sub22;
+ label = 3;
+ break;
+ case 3:
+ $arrayidx23 = $t_0 + 16 | 0;
+ $3 = HEAP32[$arrayidx23 >> 2] | 0;
+ $cmp = ($3 | 0) == 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $cond7 = $3;
+ label = 5;
+ break;
+ }
+ case 4:
+ $arrayidx27 = $t_0 + 20 | 0;
+ $4 = HEAP32[$arrayidx27 >> 2] | 0;
+ $cmp28 = ($4 | 0) == 0;
+ if ($cmp28) {
+ label = 6;
+ break;
+ } else {
+ $cond7 = $4;
+ label = 5;
+ break;
+ }
+ case 5:
+ $head29 = $cond7 + 4 | 0;
+ $5 = HEAP32[$head29 >> 2] | 0;
+ $and30 = $5 & -8;
+ $sub31 = $and30 - $nb | 0;
+ $cmp32 = $sub31 >>> 0 < $rsize_0 >>> 0;
+ $sub31_rsize_0 = $cmp32 ? $sub31 : $rsize_0;
+ $cond_v_0 = $cmp32 ? $cond7 : $v_0;
+ $t_0 = $cond7;
+ $v_0 = $cond_v_0;
+ $rsize_0 = $sub31_rsize_0;
+ label = 3;
+ break;
+ case 6:
+ $6 = $v_0;
+ $7 = HEAP32[40820] | 0;
+ $cmp33 = $6 >>> 0 < $7 >>> 0;
+ if ($cmp33) {
+ label = 52;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add_ptr = $6 + $nb | 0;
+ $8 = $add_ptr;
+ $cmp35 = $6 >>> 0 < $add_ptr >>> 0;
+ if ($cmp35) {
+ label = 8;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 8:
+ $parent = $v_0 + 24 | 0;
+ $9 = HEAP32[$parent >> 2] | 0;
+ $bk = $v_0 + 12 | 0;
+ $10 = HEAP32[$bk >> 2] | 0;
+ $cmp40 = ($10 | 0) == ($v_0 | 0);
+ if ($cmp40) {
+ label = 14;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $fd = $v_0 + 8 | 0;
+ $11 = HEAP32[$fd >> 2] | 0;
+ $12 = $11;
+ $cmp45 = $12 >>> 0 < $7 >>> 0;
+ if ($cmp45) {
+ label = 13;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 10:
+ $bk47 = $11 + 12 | 0;
+ $13 = HEAP32[$bk47 >> 2] | 0;
+ $cmp48 = ($13 | 0) == ($v_0 | 0);
+ if ($cmp48) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $fd50 = $10 + 8 | 0;
+ $14 = HEAP32[$fd50 >> 2] | 0;
+ $cmp51 = ($14 | 0) == ($v_0 | 0);
+ if ($cmp51) {
+ label = 12;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 12:
+ HEAP32[$bk47 >> 2] = $10;
+ HEAP32[$fd50 >> 2] = $11;
+ $R_1 = $10;
+ label = 22;
+ break;
+ case 13:
+ _abort();
+ return 0;
+ return 0;
+ case 14:
+ $arrayidx61 = $v_0 + 20 | 0;
+ $15 = HEAP32[$arrayidx61 >> 2] | 0;
+ $cmp62 = ($15 | 0) == 0;
+ if ($cmp62) {
+ label = 15;
+ break;
+ } else {
+ $R_0 = $15;
+ $RP_0 = $arrayidx61;
+ label = 16;
+ break;
+ }
+ case 15:
+ $arrayidx65 = $v_0 + 16 | 0;
+ $16 = HEAP32[$arrayidx65 >> 2] | 0;
+ $cmp66 = ($16 | 0) == 0;
+ if ($cmp66) {
+ $R_1 = 0;
+ label = 22;
+ break;
+ } else {
+ $R_0 = $16;
+ $RP_0 = $arrayidx65;
+ label = 16;
+ break;
+ }
+ case 16:
+ $arrayidx71 = $R_0 + 20 | 0;
+ $17 = HEAP32[$arrayidx71 >> 2] | 0;
+ $cmp72 = ($17 | 0) == 0;
+ if ($cmp72) {
+ label = 17;
+ break;
+ } else {
+ $CP_0 = $arrayidx71;
+ label = 18;
+ break;
+ }
+ case 17:
+ $arrayidx75 = $R_0 + 16 | 0;
+ $18 = HEAP32[$arrayidx75 >> 2] | 0;
+ $cmp76 = ($18 | 0) == 0;
+ if ($cmp76) {
+ label = 19;
+ break;
+ } else {
+ $CP_0 = $arrayidx75;
+ label = 18;
+ break;
+ }
+ case 18:
+ $19 = HEAP32[$CP_0 >> 2] | 0;
+ $R_0 = $19;
+ $RP_0 = $CP_0;
+ label = 16;
+ break;
+ case 19:
+ $20 = $RP_0;
+ $21 = HEAP32[40820] | 0;
+ $cmp81 = $20 >>> 0 < $21 >>> 0;
+ if ($cmp81) {
+ label = 21;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ HEAP32[$RP_0 >> 2] = 0;
+ $R_1 = $R_0;
+ label = 22;
+ break;
+ case 21:
+ _abort();
+ return 0;
+ return 0;
+ case 22:
+ $cmp90 = ($9 | 0) == 0;
+ if ($cmp90) {
+ label = 42;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $index = $v_0 + 28 | 0;
+ $22 = HEAP32[$index >> 2] | 0;
+ $arrayidx94 = 163568 + ($22 << 2) | 0;
+ $23 = HEAP32[$arrayidx94 >> 2] | 0;
+ $cmp95 = ($v_0 | 0) == ($23 | 0);
+ if ($cmp95) {
+ label = 24;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 24:
+ HEAP32[$arrayidx94 >> 2] = $R_1;
+ $cond5 = ($R_1 | 0) == 0;
+ if ($cond5) {
+ label = 25;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 25:
+ $24 = HEAP32[$index >> 2] | 0;
+ $shl = 1 << $24;
+ $neg = $shl ^ -1;
+ $25 = HEAP32[40817] | 0;
+ $and103 = $25 & $neg;
+ HEAP32[40817] = $and103;
+ label = 42;
+ break;
+ case 26:
+ $26 = $9;
+ $27 = HEAP32[40820] | 0;
+ $cmp107 = $26 >>> 0 < $27 >>> 0;
+ if ($cmp107) {
+ label = 30;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $arrayidx113 = $9 + 16 | 0;
+ $28 = HEAP32[$arrayidx113 >> 2] | 0;
+ $cmp114 = ($28 | 0) == ($v_0 | 0);
+ if ($cmp114) {
+ label = 28;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 28:
+ HEAP32[$arrayidx113 >> 2] = $R_1;
+ label = 31;
+ break;
+ case 29:
+ $arrayidx121 = $9 + 20 | 0;
+ HEAP32[$arrayidx121 >> 2] = $R_1;
+ label = 31;
+ break;
+ case 30:
+ _abort();
+ return 0;
+ return 0;
+ case 31:
+ $cmp126 = ($R_1 | 0) == 0;
+ if ($cmp126) {
+ label = 42;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 32:
+ $29 = $R_1;
+ $30 = HEAP32[40820] | 0;
+ $cmp130 = $29 >>> 0 < $30 >>> 0;
+ if ($cmp130) {
+ label = 41;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $parent135 = $R_1 + 24 | 0;
+ HEAP32[$parent135 >> 2] = $9;
+ $arrayidx137 = $v_0 + 16 | 0;
+ $31 = HEAP32[$arrayidx137 >> 2] | 0;
+ $cmp138 = ($31 | 0) == 0;
+ if ($cmp138) {
+ label = 37;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $32 = $31;
+ $33 = HEAP32[40820] | 0;
+ $cmp142 = $32 >>> 0 < $33 >>> 0;
+ if ($cmp142) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $arrayidx148 = $R_1 + 16 | 0;
+ HEAP32[$arrayidx148 >> 2] = $31;
+ $parent149 = $31 + 24 | 0;
+ HEAP32[$parent149 >> 2] = $R_1;
+ label = 37;
+ break;
+ case 36:
+ _abort();
+ return 0;
+ return 0;
+ case 37:
+ $arrayidx154 = $v_0 + 20 | 0;
+ $34 = HEAP32[$arrayidx154 >> 2] | 0;
+ $cmp155 = ($34 | 0) == 0;
+ if ($cmp155) {
+ label = 42;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $35 = $34;
+ $36 = HEAP32[40820] | 0;
+ $cmp159 = $35 >>> 0 < $36 >>> 0;
+ if ($cmp159) {
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ $arrayidx165 = $R_1 + 20 | 0;
+ HEAP32[$arrayidx165 >> 2] = $34;
+ $parent166 = $34 + 24 | 0;
+ HEAP32[$parent166 >> 2] = $R_1;
+ label = 42;
+ break;
+ case 40:
+ _abort();
+ return 0;
+ return 0;
+ case 41:
+ _abort();
+ return 0;
+ return 0;
+ case 42:
+ $cmp174 = $rsize_0 >>> 0 < 16;
+ if ($cmp174) {
+ label = 43;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 43:
+ $add177 = $rsize_0 + $nb | 0;
+ $or178 = $add177 | 3;
+ $head179 = $v_0 + 4 | 0;
+ HEAP32[$head179 >> 2] = $or178;
+ $add_ptr181_sum = $add177 + 4 | 0;
+ $head182 = $6 + $add_ptr181_sum | 0;
+ $37 = $head182;
+ $38 = HEAP32[$37 >> 2] | 0;
+ $or183 = $38 | 1;
+ HEAP32[$37 >> 2] = $or183;
+ label = 51;
+ break;
+ case 44:
+ $or186 = $nb | 3;
+ $head187 = $v_0 + 4 | 0;
+ HEAP32[$head187 >> 2] = $or186;
+ $or188 = $rsize_0 | 1;
+ $add_ptr_sum = $nb + 4 | 0;
+ $head189 = $6 + $add_ptr_sum | 0;
+ $39 = $head189;
+ HEAP32[$39 >> 2] = $or188;
+ $add_ptr_sum1 = $rsize_0 + $nb | 0;
+ $add_ptr190 = $6 + $add_ptr_sum1 | 0;
+ $prev_foot = $add_ptr190;
+ HEAP32[$prev_foot >> 2] = $rsize_0;
+ $40 = HEAP32[40818] | 0;
+ $cmp191 = ($40 | 0) == 0;
+ if ($cmp191) {
+ label = 50;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $41 = HEAP32[40821] | 0;
+ $shr194 = $40 >>> 3;
+ $shl195 = $shr194 << 1;
+ $arrayidx196 = 163304 + ($shl195 << 2) | 0;
+ $42 = $arrayidx196;
+ $43 = HEAP32[40816] | 0;
+ $shl198 = 1 << $shr194;
+ $and199 = $43 & $shl198;
+ $tobool200 = ($and199 | 0) == 0;
+ if ($tobool200) {
+ label = 46;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 46:
+ $or204 = $43 | $shl198;
+ HEAP32[40816] = $or204;
+ $F197_0 = $42;
+ label = 49;
+ break;
+ case 47:
+ $arrayidx196_sum2 = $shl195 + 2 | 0;
+ $44 = 163304 + ($arrayidx196_sum2 << 2) | 0;
+ $45 = HEAP32[$44 >> 2] | 0;
+ $46 = $45;
+ $47 = HEAP32[40820] | 0;
+ $cmp208 = $46 >>> 0 < $47 >>> 0;
+ if ($cmp208) {
+ label = 48;
+ break;
+ } else {
+ $F197_0 = $45;
+ label = 49;
+ break;
+ }
+ case 48:
+ _abort();
+ return 0;
+ return 0;
+ case 49:
+ $arrayidx196_sum = $shl195 + 2 | 0;
+ $48 = 163304 + ($arrayidx196_sum << 2) | 0;
+ HEAP32[$48 >> 2] = $41;
+ $bk218 = $F197_0 + 12 | 0;
+ HEAP32[$bk218 >> 2] = $41;
+ $fd219 = $41 + 8 | 0;
+ HEAP32[$fd219 >> 2] = $F197_0;
+ $bk220 = $41 + 12 | 0;
+ HEAP32[$bk220 >> 2] = $42;
+ label = 50;
+ break;
+ case 50:
+ HEAP32[40818] = $rsize_0;
+ HEAP32[40821] = $8;
+ label = 51;
+ break;
+ case 51:
+ $add_ptr225 = $v_0 + 8 | 0;
+ $49 = $add_ptr225;
+ return $49 | 0;
+ case 52:
+ _abort();
+ return 0;
+ return 0;
+ }
+ return 0;
+}
+function _tmalloc_large($nb) {
+ $nb = $nb | 0;
+ var $sub = 0, $shr = 0, $cmp = 0, $cmp1 = 0, $sub4 = 0, $shr5 = 0, $and = 0, $shl = 0, $sub6 = 0, $shr7 = 0, $and8 = 0, $add = 0, $shl9 = 0, $sub10 = 0, $shr11 = 0, $and12 = 0, $add13 = 0, $sub14 = 0, $shl15 = 0, $shr16 = 0, $add17 = 0, $shl18 = 0, $add19 = 0, $shr20 = 0, $and21 = 0, $add22 = 0, $idx_0 = 0, $arrayidx = 0, $0 = 0, $cmp24 = 0, $cmp26 = 0, $shr27 = 0, $sub30 = 0, $cond = 0, $shl31 = 0, $rst_0 = 0, $sizebits_0 = 0, $t_0 = 0, $rsize_0 = 0, $v_0 = 0, $head = 0, $1 = 0, $and32 = 0, $sub33 = 0, $cmp34 = 0, $cmp36 = 0, $rsize_1 = 0, $v_1 = 0, $arrayidx40 = 0, $2 = 0, $shr41 = 0, $arrayidx44 = 0, $3 = 0, $cmp45 = 0, $cmp46 = 0, $or_cond = 0, $rst_1 = 0, $cmp49 = 0, $shl52 = 0, $t_1 = 0, $rsize_2 = 0, $v_2 = 0, $cmp54 = 0, $cmp56 = 0, $or_cond18 = 0, $shl59 = 0, $sub62 = 0, $or = 0, $4 = 0, $and63 = 0, $cmp64 = 0, $sub66 = 0, $and67 = 0, $sub69 = 0, $shr71 = 0, $and72 = 0, $shr74 = 0, $shr75 = 0, $and76 = 0, $add77 = 0, $shr78 = 0, $shr79 = 0, $and80 = 0, $add81 = 0, $shr82 = 0, $shr83 = 0, $and84 = 0, $add85 = 0, $shr86 = 0, $shr87 = 0, $and88 = 0, $add89 = 0, $shr90 = 0, $add91 = 0, $arrayidx93 = 0, $5 = 0, $t_2_ph = 0, $cmp9623 = 0, $v_326 = 0, $rsize_325 = 0, $t_224 = 0, $head98 = 0, $6 = 0, $and99 = 0, $sub100 = 0, $cmp101 = 0, $sub100_rsize_3 = 0, $t_2_v_3 = 0, $arrayidx105 = 0, $7 = 0, $cmp106 = 0, $arrayidx112 = 0, $8 = 0, $cmp96 = 0, $v_3_lcssa = 0, $rsize_3_lcssa = 0, $cmp115 = 0, $9 = 0, $sub117 = 0, $cmp118 = 0, $10 = 0, $11 = 0, $cmp120 = 0, $add_ptr = 0, $12 = 0, $cmp122 = 0, $parent = 0, $13 = 0, $bk = 0, $14 = 0, $cmp127 = 0, $fd = 0, $15 = 0, $16 = 0, $cmp132 = 0, $bk135 = 0, $17 = 0, $cmp136 = 0, $fd138 = 0, $18 = 0, $cmp139 = 0, $arrayidx150 = 0, $19 = 0, $cmp151 = 0, $arrayidx154 = 0, $20 = 0, $cmp155 = 0, $RP_0 = 0, $R_0 = 0, $arrayidx160 = 0, $21 = 0, $cmp161 = 0, $arrayidx164 = 0, $22 = 0, $cmp165 = 0, $CP_0 = 0, $23 = 0, $24 = 0, $25 = 0, $cmp170 = 0, $R_1 = 0, $cmp179 = 0, $index = 0, $26 = 0, $arrayidx183 = 0, $27 = 0, $cmp184 = 0, $cond20 = 0, $28 = 0, $shl191 = 0, $neg = 0, $29 = 0, $and193 = 0, $30 = 0, $31 = 0, $cmp197 = 0, $arrayidx203 = 0, $32 = 0, $cmp204 = 0, $arrayidx211 = 0, $cmp216 = 0, $33 = 0, $34 = 0, $cmp220 = 0, $parent225 = 0, $arrayidx227 = 0, $35 = 0, $cmp228 = 0, $36 = 0, $37 = 0, $cmp232 = 0, $arrayidx238 = 0, $parent239 = 0, $arrayidx244 = 0, $38 = 0, $cmp245 = 0, $39 = 0, $40 = 0, $cmp249 = 0, $arrayidx255 = 0, $parent256 = 0, $cmp264 = 0, $add267 = 0, $or269 = 0, $head270 = 0, $add_ptr272_sum = 0, $head273 = 0, $41 = 0, $42 = 0, $or274 = 0, $or277 = 0, $head278 = 0, $or279 = 0, $add_ptr_sum = 0, $head280 = 0, $43 = 0, $add_ptr_sum1 = 0, $add_ptr281 = 0, $prev_foot = 0, $shr282 = 0, $cmp283 = 0, $shl287 = 0, $arrayidx288 = 0, $44 = 0, $45 = 0, $shl290 = 0, $and291 = 0, $tobool292 = 0, $or296 = 0, $arrayidx288_sum16 = 0, $46 = 0, $47 = 0, $48 = 0, $49 = 0, $cmp300 = 0, $F289_0 = 0, $arrayidx288_sum = 0, $50 = 0, $bk310 = 0, $add_ptr_sum14 = 0, $fd311 = 0, $51 = 0, $add_ptr_sum15 = 0, $bk312 = 0, $52 = 0, $53 = 0, $shr317 = 0, $cmp318 = 0, $cmp322 = 0, $sub328 = 0, $shr329 = 0, $and330 = 0, $shl332 = 0, $sub333 = 0, $shr334 = 0, $and335 = 0, $add336 = 0, $shl337 = 0, $sub338 = 0, $shr339 = 0, $and340 = 0, $add341 = 0, $sub342 = 0, $shl343 = 0, $shr344 = 0, $add345 = 0, $shl346 = 0, $add347 = 0, $shr348 = 0, $and349 = 0, $add350 = 0, $I315_0 = 0, $arrayidx354 = 0, $add_ptr_sum2 = 0, $index355 = 0, $54 = 0, $add_ptr_sum3 = 0, $child356 = 0, $child356_sum = 0, $arrayidx357 = 0, $55 = 0, $arrayidx359 = 0, $56 = 0, $shl361 = 0, $and362 = 0, $tobool363 = 0, $or367 = 0, $57 = 0, $add_ptr_sum4 = 0, $parent368 = 0, $58 = 0, $add_ptr_sum5 = 0, $bk369 = 0, $59 = 0, $add_ptr_sum6 = 0, $fd370 = 0, $60 = 0, $61 = 0, $cmp373 = 0, $shr377 = 0, $sub380 = 0, $cond382 = 0, $shl383 = 0, $T_0 = 0, $K372_0 = 0, $head385 = 0, $62 = 0, $and386 = 0, $cmp387 = 0, $shr390 = 0, $arrayidx393 = 0, $63 = 0, $cmp395 = 0, $shl394 = 0, $64 = 0, $65 = 0, $cmp400 = 0, $add_ptr_sum11 = 0, $parent405 = 0, $66 = 0, $add_ptr_sum12 = 0, $bk406 = 0, $67 = 0, $add_ptr_sum13 = 0, $fd407 = 0, $68 = 0, $fd412 = 0, $69 = 0, $70 = 0, $71 = 0, $cmp414 = 0, $72 = 0, $cmp418 = 0, $bk425 = 0, $add_ptr_sum8 = 0, $fd427 = 0, $73 = 0, $add_ptr_sum9 = 0, $bk428 = 0, $74 = 0, $add_ptr_sum10 = 0, $parent429 = 0, $75 = 0, $add_ptr436 = 0, $76 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sub = -$nb | 0;
+ $shr = $nb >>> 8;
+ $cmp = ($shr | 0) == 0;
+ if ($cmp) {
+ $idx_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $cmp1 = $nb >>> 0 > 16777215;
+ if ($cmp1) {
+ $idx_0 = 31;
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $sub4 = $shr + 1048320 | 0;
+ $shr5 = $sub4 >>> 16;
+ $and = $shr5 & 8;
+ $shl = $shr << $and;
+ $sub6 = $shl + 520192 | 0;
+ $shr7 = $sub6 >>> 16;
+ $and8 = $shr7 & 4;
+ $add = $and8 | $and;
+ $shl9 = $shl << $and8;
+ $sub10 = $shl9 + 245760 | 0;
+ $shr11 = $sub10 >>> 16;
+ $and12 = $shr11 & 2;
+ $add13 = $add | $and12;
+ $sub14 = 14 - $add13 | 0;
+ $shl15 = $shl9 << $and12;
+ $shr16 = $shl15 >>> 15;
+ $add17 = $sub14 + $shr16 | 0;
+ $shl18 = $add17 << 1;
+ $add19 = $add17 + 7 | 0;
+ $shr20 = $nb >>> ($add19 >>> 0);
+ $and21 = $shr20 & 1;
+ $add22 = $and21 | $shl18;
+ $idx_0 = $add22;
+ label = 5;
+ break;
+ case 5:
+ $arrayidx = 163568 + ($idx_0 << 2) | 0;
+ $0 = HEAP32[$arrayidx >> 2] | 0;
+ $cmp24 = ($0 | 0) == 0;
+ if ($cmp24) {
+ $v_2 = 0;
+ $rsize_2 = $sub;
+ $t_1 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp26 = ($idx_0 | 0) == 31;
+ if ($cmp26) {
+ $cond = 0;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $shr27 = $idx_0 >>> 1;
+ $sub30 = 25 - $shr27 | 0;
+ $cond = $sub30;
+ label = 8;
+ break;
+ case 8:
+ $shl31 = $nb << $cond;
+ $v_0 = 0;
+ $rsize_0 = $sub;
+ $t_0 = $0;
+ $sizebits_0 = $shl31;
+ $rst_0 = 0;
+ label = 9;
+ break;
+ case 9:
+ $head = $t_0 + 4 | 0;
+ $1 = HEAP32[$head >> 2] | 0;
+ $and32 = $1 & -8;
+ $sub33 = $and32 - $nb | 0;
+ $cmp34 = $sub33 >>> 0 < $rsize_0 >>> 0;
+ if ($cmp34) {
+ label = 10;
+ break;
+ } else {
+ $v_1 = $v_0;
+ $rsize_1 = $rsize_0;
+ label = 11;
+ break;
+ }
+ case 10:
+ $cmp36 = ($and32 | 0) == ($nb | 0);
+ if ($cmp36) {
+ $v_2 = $t_0;
+ $rsize_2 = $sub33;
+ $t_1 = $t_0;
+ label = 12;
+ break;
+ } else {
+ $v_1 = $t_0;
+ $rsize_1 = $sub33;
+ label = 11;
+ break;
+ }
+ case 11:
+ $arrayidx40 = $t_0 + 20 | 0;
+ $2 = HEAP32[$arrayidx40 >> 2] | 0;
+ $shr41 = $sizebits_0 >>> 31;
+ $arrayidx44 = $t_0 + 16 + ($shr41 << 2) | 0;
+ $3 = HEAP32[$arrayidx44 >> 2] | 0;
+ $cmp45 = ($2 | 0) == 0;
+ $cmp46 = ($2 | 0) == ($3 | 0);
+ $or_cond = $cmp45 | $cmp46;
+ $rst_1 = $or_cond ? $rst_0 : $2;
+ $cmp49 = ($3 | 0) == 0;
+ $shl52 = $sizebits_0 << 1;
+ if ($cmp49) {
+ $v_2 = $v_1;
+ $rsize_2 = $rsize_1;
+ $t_1 = $rst_1;
+ label = 12;
+ break;
+ } else {
+ $v_0 = $v_1;
+ $rsize_0 = $rsize_1;
+ $t_0 = $3;
+ $sizebits_0 = $shl52;
+ $rst_0 = $rst_1;
+ label = 9;
+ break;
+ }
+ case 12:
+ $cmp54 = ($t_1 | 0) == 0;
+ $cmp56 = ($v_2 | 0) == 0;
+ $or_cond18 = $cmp54 & $cmp56;
+ if ($or_cond18) {
+ label = 13;
+ break;
+ } else {
+ $t_2_ph = $t_1;
+ label = 15;
+ break;
+ }
+ case 13:
+ $shl59 = 2 << $idx_0;
+ $sub62 = -$shl59 | 0;
+ $or = $shl59 | $sub62;
+ $4 = HEAP32[40817] | 0;
+ $and63 = $4 & $or;
+ $cmp64 = ($and63 | 0) == 0;
+ if ($cmp64) {
+ $t_2_ph = $t_1;
+ label = 15;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $sub66 = -$and63 | 0;
+ $and67 = $and63 & $sub66;
+ $sub69 = $and67 - 1 | 0;
+ $shr71 = $sub69 >>> 12;
+ $and72 = $shr71 & 16;
+ $shr74 = $sub69 >>> ($and72 >>> 0);
+ $shr75 = $shr74 >>> 5;
+ $and76 = $shr75 & 8;
+ $add77 = $and76 | $and72;
+ $shr78 = $shr74 >>> ($and76 >>> 0);
+ $shr79 = $shr78 >>> 2;
+ $and80 = $shr79 & 4;
+ $add81 = $add77 | $and80;
+ $shr82 = $shr78 >>> ($and80 >>> 0);
+ $shr83 = $shr82 >>> 1;
+ $and84 = $shr83 & 2;
+ $add85 = $add81 | $and84;
+ $shr86 = $shr82 >>> ($and84 >>> 0);
+ $shr87 = $shr86 >>> 1;
+ $and88 = $shr87 & 1;
+ $add89 = $add85 | $and88;
+ $shr90 = $shr86 >>> ($and88 >>> 0);
+ $add91 = $add89 + $shr90 | 0;
+ $arrayidx93 = 163568 + ($add91 << 2) | 0;
+ $5 = HEAP32[$arrayidx93 >> 2] | 0;
+ $t_2_ph = $5;
+ label = 15;
+ break;
+ case 15:
+ $cmp9623 = ($t_2_ph | 0) == 0;
+ if ($cmp9623) {
+ $rsize_3_lcssa = $rsize_2;
+ $v_3_lcssa = $v_2;
+ label = 18;
+ break;
+ } else {
+ $t_224 = $t_2_ph;
+ $rsize_325 = $rsize_2;
+ $v_326 = $v_2;
+ label = 16;
+ break;
+ }
+ case 16:
+ $head98 = $t_224 + 4 | 0;
+ $6 = HEAP32[$head98 >> 2] | 0;
+ $and99 = $6 & -8;
+ $sub100 = $and99 - $nb | 0;
+ $cmp101 = $sub100 >>> 0 < $rsize_325 >>> 0;
+ $sub100_rsize_3 = $cmp101 ? $sub100 : $rsize_325;
+ $t_2_v_3 = $cmp101 ? $t_224 : $v_326;
+ $arrayidx105 = $t_224 + 16 | 0;
+ $7 = HEAP32[$arrayidx105 >> 2] | 0;
+ $cmp106 = ($7 | 0) == 0;
+ if ($cmp106) {
+ label = 17;
+ break;
+ } else {
+ $t_224 = $7;
+ $rsize_325 = $sub100_rsize_3;
+ $v_326 = $t_2_v_3;
+ label = 16;
+ break;
+ }
+ case 17:
+ $arrayidx112 = $t_224 + 20 | 0;
+ $8 = HEAP32[$arrayidx112 >> 2] | 0;
+ $cmp96 = ($8 | 0) == 0;
+ if ($cmp96) {
+ $rsize_3_lcssa = $sub100_rsize_3;
+ $v_3_lcssa = $t_2_v_3;
+ label = 18;
+ break;
+ } else {
+ $t_224 = $8;
+ $rsize_325 = $sub100_rsize_3;
+ $v_326 = $t_2_v_3;
+ label = 16;
+ break;
+ }
+ case 18:
+ $cmp115 = ($v_3_lcssa | 0) == 0;
+ if ($cmp115) {
+ $retval_0 = 0;
+ label = 83;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $9 = HEAP32[40818] | 0;
+ $sub117 = $9 - $nb | 0;
+ $cmp118 = $rsize_3_lcssa >>> 0 < $sub117 >>> 0;
+ if ($cmp118) {
+ label = 20;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 83;
+ break;
+ }
+ case 20:
+ $10 = $v_3_lcssa;
+ $11 = HEAP32[40820] | 0;
+ $cmp120 = $10 >>> 0 < $11 >>> 0;
+ if ($cmp120) {
+ label = 82;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $add_ptr = $10 + $nb | 0;
+ $12 = $add_ptr;
+ $cmp122 = $10 >>> 0 < $add_ptr >>> 0;
+ if ($cmp122) {
+ label = 22;
+ break;
+ } else {
+ label = 82;
+ break;
+ }
+ case 22:
+ $parent = $v_3_lcssa + 24 | 0;
+ $13 = HEAP32[$parent >> 2] | 0;
+ $bk = $v_3_lcssa + 12 | 0;
+ $14 = HEAP32[$bk >> 2] | 0;
+ $cmp127 = ($14 | 0) == ($v_3_lcssa | 0);
+ if ($cmp127) {
+ label = 28;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $fd = $v_3_lcssa + 8 | 0;
+ $15 = HEAP32[$fd >> 2] | 0;
+ $16 = $15;
+ $cmp132 = $16 >>> 0 < $11 >>> 0;
+ if ($cmp132) {
+ label = 27;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $bk135 = $15 + 12 | 0;
+ $17 = HEAP32[$bk135 >> 2] | 0;
+ $cmp136 = ($17 | 0) == ($v_3_lcssa | 0);
+ if ($cmp136) {
+ label = 25;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 25:
+ $fd138 = $14 + 8 | 0;
+ $18 = HEAP32[$fd138 >> 2] | 0;
+ $cmp139 = ($18 | 0) == ($v_3_lcssa | 0);
+ if ($cmp139) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ HEAP32[$bk135 >> 2] = $14;
+ HEAP32[$fd138 >> 2] = $15;
+ $R_1 = $14;
+ label = 36;
+ break;
+ case 27:
+ _abort();
+ return 0;
+ return 0;
+ case 28:
+ $arrayidx150 = $v_3_lcssa + 20 | 0;
+ $19 = HEAP32[$arrayidx150 >> 2] | 0;
+ $cmp151 = ($19 | 0) == 0;
+ if ($cmp151) {
+ label = 29;
+ break;
+ } else {
+ $R_0 = $19;
+ $RP_0 = $arrayidx150;
+ label = 30;
+ break;
+ }
+ case 29:
+ $arrayidx154 = $v_3_lcssa + 16 | 0;
+ $20 = HEAP32[$arrayidx154 >> 2] | 0;
+ $cmp155 = ($20 | 0) == 0;
+ if ($cmp155) {
+ $R_1 = 0;
+ label = 36;
+ break;
+ } else {
+ $R_0 = $20;
+ $RP_0 = $arrayidx154;
+ label = 30;
+ break;
+ }
+ case 30:
+ $arrayidx160 = $R_0 + 20 | 0;
+ $21 = HEAP32[$arrayidx160 >> 2] | 0;
+ $cmp161 = ($21 | 0) == 0;
+ if ($cmp161) {
+ label = 31;
+ break;
+ } else {
+ $CP_0 = $arrayidx160;
+ label = 32;
+ break;
+ }
+ case 31:
+ $arrayidx164 = $R_0 + 16 | 0;
+ $22 = HEAP32[$arrayidx164 >> 2] | 0;
+ $cmp165 = ($22 | 0) == 0;
+ if ($cmp165) {
+ label = 33;
+ break;
+ } else {
+ $CP_0 = $arrayidx164;
+ label = 32;
+ break;
+ }
+ case 32:
+ $23 = HEAP32[$CP_0 >> 2] | 0;
+ $R_0 = $23;
+ $RP_0 = $CP_0;
+ label = 30;
+ break;
+ case 33:
+ $24 = $RP_0;
+ $25 = HEAP32[40820] | 0;
+ $cmp170 = $24 >>> 0 < $25 >>> 0;
+ if ($cmp170) {
+ label = 35;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ HEAP32[$RP_0 >> 2] = 0;
+ $R_1 = $R_0;
+ label = 36;
+ break;
+ case 35:
+ _abort();
+ return 0;
+ return 0;
+ case 36:
+ $cmp179 = ($13 | 0) == 0;
+ if ($cmp179) {
+ label = 56;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $index = $v_3_lcssa + 28 | 0;
+ $26 = HEAP32[$index >> 2] | 0;
+ $arrayidx183 = 163568 + ($26 << 2) | 0;
+ $27 = HEAP32[$arrayidx183 >> 2] | 0;
+ $cmp184 = ($v_3_lcssa | 0) == ($27 | 0);
+ if ($cmp184) {
+ label = 38;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 38:
+ HEAP32[$arrayidx183 >> 2] = $R_1;
+ $cond20 = ($R_1 | 0) == 0;
+ if ($cond20) {
+ label = 39;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 39:
+ $28 = HEAP32[$index >> 2] | 0;
+ $shl191 = 1 << $28;
+ $neg = $shl191 ^ -1;
+ $29 = HEAP32[40817] | 0;
+ $and193 = $29 & $neg;
+ HEAP32[40817] = $and193;
+ label = 56;
+ break;
+ case 40:
+ $30 = $13;
+ $31 = HEAP32[40820] | 0;
+ $cmp197 = $30 >>> 0 < $31 >>> 0;
+ if ($cmp197) {
+ label = 44;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $arrayidx203 = $13 + 16 | 0;
+ $32 = HEAP32[$arrayidx203 >> 2] | 0;
+ $cmp204 = ($32 | 0) == ($v_3_lcssa | 0);
+ if ($cmp204) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ HEAP32[$arrayidx203 >> 2] = $R_1;
+ label = 45;
+ break;
+ case 43:
+ $arrayidx211 = $13 + 20 | 0;
+ HEAP32[$arrayidx211 >> 2] = $R_1;
+ label = 45;
+ break;
+ case 44:
+ _abort();
+ return 0;
+ return 0;
+ case 45:
+ $cmp216 = ($R_1 | 0) == 0;
+ if ($cmp216) {
+ label = 56;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $33 = $R_1;
+ $34 = HEAP32[40820] | 0;
+ $cmp220 = $33 >>> 0 < $34 >>> 0;
+ if ($cmp220) {
+ label = 55;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $parent225 = $R_1 + 24 | 0;
+ HEAP32[$parent225 >> 2] = $13;
+ $arrayidx227 = $v_3_lcssa + 16 | 0;
+ $35 = HEAP32[$arrayidx227 >> 2] | 0;
+ $cmp228 = ($35 | 0) == 0;
+ if ($cmp228) {
+ label = 51;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $36 = $35;
+ $37 = HEAP32[40820] | 0;
+ $cmp232 = $36 >>> 0 < $37 >>> 0;
+ if ($cmp232) {
+ label = 50;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $arrayidx238 = $R_1 + 16 | 0;
+ HEAP32[$arrayidx238 >> 2] = $35;
+ $parent239 = $35 + 24 | 0;
+ HEAP32[$parent239 >> 2] = $R_1;
+ label = 51;
+ break;
+ case 50:
+ _abort();
+ return 0;
+ return 0;
+ case 51:
+ $arrayidx244 = $v_3_lcssa + 20 | 0;
+ $38 = HEAP32[$arrayidx244 >> 2] | 0;
+ $cmp245 = ($38 | 0) == 0;
+ if ($cmp245) {
+ label = 56;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $39 = $38;
+ $40 = HEAP32[40820] | 0;
+ $cmp249 = $39 >>> 0 < $40 >>> 0;
+ if ($cmp249) {
+ label = 54;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $arrayidx255 = $R_1 + 20 | 0;
+ HEAP32[$arrayidx255 >> 2] = $38;
+ $parent256 = $38 + 24 | 0;
+ HEAP32[$parent256 >> 2] = $R_1;
+ label = 56;
+ break;
+ case 54:
+ _abort();
+ return 0;
+ return 0;
+ case 55:
+ _abort();
+ return 0;
+ return 0;
+ case 56:
+ $cmp264 = $rsize_3_lcssa >>> 0 < 16;
+ if ($cmp264) {
+ label = 57;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 57:
+ $add267 = $rsize_3_lcssa + $nb | 0;
+ $or269 = $add267 | 3;
+ $head270 = $v_3_lcssa + 4 | 0;
+ HEAP32[$head270 >> 2] = $or269;
+ $add_ptr272_sum = $add267 + 4 | 0;
+ $head273 = $10 + $add_ptr272_sum | 0;
+ $41 = $head273;
+ $42 = HEAP32[$41 >> 2] | 0;
+ $or274 = $42 | 1;
+ HEAP32[$41 >> 2] = $or274;
+ label = 81;
+ break;
+ case 58:
+ $or277 = $nb | 3;
+ $head278 = $v_3_lcssa + 4 | 0;
+ HEAP32[$head278 >> 2] = $or277;
+ $or279 = $rsize_3_lcssa | 1;
+ $add_ptr_sum = $nb + 4 | 0;
+ $head280 = $10 + $add_ptr_sum | 0;
+ $43 = $head280;
+ HEAP32[$43 >> 2] = $or279;
+ $add_ptr_sum1 = $rsize_3_lcssa + $nb | 0;
+ $add_ptr281 = $10 + $add_ptr_sum1 | 0;
+ $prev_foot = $add_ptr281;
+ HEAP32[$prev_foot >> 2] = $rsize_3_lcssa;
+ $shr282 = $rsize_3_lcssa >>> 3;
+ $cmp283 = $rsize_3_lcssa >>> 0 < 256;
+ if ($cmp283) {
+ label = 59;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 59:
+ $shl287 = $shr282 << 1;
+ $arrayidx288 = 163304 + ($shl287 << 2) | 0;
+ $44 = $arrayidx288;
+ $45 = HEAP32[40816] | 0;
+ $shl290 = 1 << $shr282;
+ $and291 = $45 & $shl290;
+ $tobool292 = ($and291 | 0) == 0;
+ if ($tobool292) {
+ label = 60;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 60:
+ $or296 = $45 | $shl290;
+ HEAP32[40816] = $or296;
+ $F289_0 = $44;
+ label = 63;
+ break;
+ case 61:
+ $arrayidx288_sum16 = $shl287 + 2 | 0;
+ $46 = 163304 + ($arrayidx288_sum16 << 2) | 0;
+ $47 = HEAP32[$46 >> 2] | 0;
+ $48 = $47;
+ $49 = HEAP32[40820] | 0;
+ $cmp300 = $48 >>> 0 < $49 >>> 0;
+ if ($cmp300) {
+ label = 62;
+ break;
+ } else {
+ $F289_0 = $47;
+ label = 63;
+ break;
+ }
+ case 62:
+ _abort();
+ return 0;
+ return 0;
+ case 63:
+ $arrayidx288_sum = $shl287 + 2 | 0;
+ $50 = 163304 + ($arrayidx288_sum << 2) | 0;
+ HEAP32[$50 >> 2] = $12;
+ $bk310 = $F289_0 + 12 | 0;
+ HEAP32[$bk310 >> 2] = $12;
+ $add_ptr_sum14 = $nb + 8 | 0;
+ $fd311 = $10 + $add_ptr_sum14 | 0;
+ $51 = $fd311;
+ HEAP32[$51 >> 2] = $F289_0;
+ $add_ptr_sum15 = $nb + 12 | 0;
+ $bk312 = $10 + $add_ptr_sum15 | 0;
+ $52 = $bk312;
+ HEAP32[$52 >> 2] = $44;
+ label = 81;
+ break;
+ case 64:
+ $53 = $add_ptr;
+ $shr317 = $rsize_3_lcssa >>> 8;
+ $cmp318 = ($shr317 | 0) == 0;
+ if ($cmp318) {
+ $I315_0 = 0;
+ label = 67;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $cmp322 = $rsize_3_lcssa >>> 0 > 16777215;
+ if ($cmp322) {
+ $I315_0 = 31;
+ label = 67;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ $sub328 = $shr317 + 1048320 | 0;
+ $shr329 = $sub328 >>> 16;
+ $and330 = $shr329 & 8;
+ $shl332 = $shr317 << $and330;
+ $sub333 = $shl332 + 520192 | 0;
+ $shr334 = $sub333 >>> 16;
+ $and335 = $shr334 & 4;
+ $add336 = $and335 | $and330;
+ $shl337 = $shl332 << $and335;
+ $sub338 = $shl337 + 245760 | 0;
+ $shr339 = $sub338 >>> 16;
+ $and340 = $shr339 & 2;
+ $add341 = $add336 | $and340;
+ $sub342 = 14 - $add341 | 0;
+ $shl343 = $shl337 << $and340;
+ $shr344 = $shl343 >>> 15;
+ $add345 = $sub342 + $shr344 | 0;
+ $shl346 = $add345 << 1;
+ $add347 = $add345 + 7 | 0;
+ $shr348 = $rsize_3_lcssa >>> ($add347 >>> 0);
+ $and349 = $shr348 & 1;
+ $add350 = $and349 | $shl346;
+ $I315_0 = $add350;
+ label = 67;
+ break;
+ case 67:
+ $arrayidx354 = 163568 + ($I315_0 << 2) | 0;
+ $add_ptr_sum2 = $nb + 28 | 0;
+ $index355 = $10 + $add_ptr_sum2 | 0;
+ $54 = $index355;
+ HEAP32[$54 >> 2] = $I315_0;
+ $add_ptr_sum3 = $nb + 16 | 0;
+ $child356 = $10 + $add_ptr_sum3 | 0;
+ $child356_sum = $nb + 20 | 0;
+ $arrayidx357 = $10 + $child356_sum | 0;
+ $55 = $arrayidx357;
+ HEAP32[$55 >> 2] = 0;
+ $arrayidx359 = $child356;
+ HEAP32[$arrayidx359 >> 2] = 0;
+ $56 = HEAP32[40817] | 0;
+ $shl361 = 1 << $I315_0;
+ $and362 = $56 & $shl361;
+ $tobool363 = ($and362 | 0) == 0;
+ if ($tobool363) {
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 68:
+ $or367 = $56 | $shl361;
+ HEAP32[40817] = $or367;
+ HEAP32[$arrayidx354 >> 2] = $53;
+ $57 = $arrayidx354;
+ $add_ptr_sum4 = $nb + 24 | 0;
+ $parent368 = $10 + $add_ptr_sum4 | 0;
+ $58 = $parent368;
+ HEAP32[$58 >> 2] = $57;
+ $add_ptr_sum5 = $nb + 12 | 0;
+ $bk369 = $10 + $add_ptr_sum5 | 0;
+ $59 = $bk369;
+ HEAP32[$59 >> 2] = $53;
+ $add_ptr_sum6 = $nb + 8 | 0;
+ $fd370 = $10 + $add_ptr_sum6 | 0;
+ $60 = $fd370;
+ HEAP32[$60 >> 2] = $53;
+ label = 81;
+ break;
+ case 69:
+ $61 = HEAP32[$arrayidx354 >> 2] | 0;
+ $cmp373 = ($I315_0 | 0) == 31;
+ if ($cmp373) {
+ $cond382 = 0;
+ label = 71;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $shr377 = $I315_0 >>> 1;
+ $sub380 = 25 - $shr377 | 0;
+ $cond382 = $sub380;
+ label = 71;
+ break;
+ case 71:
+ $shl383 = $rsize_3_lcssa << $cond382;
+ $K372_0 = $shl383;
+ $T_0 = $61;
+ label = 72;
+ break;
+ case 72:
+ $head385 = $T_0 + 4 | 0;
+ $62 = HEAP32[$head385 >> 2] | 0;
+ $and386 = $62 & -8;
+ $cmp387 = ($and386 | 0) == ($rsize_3_lcssa | 0);
+ if ($cmp387) {
+ label = 77;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $shr390 = $K372_0 >>> 31;
+ $arrayidx393 = $T_0 + 16 + ($shr390 << 2) | 0;
+ $63 = HEAP32[$arrayidx393 >> 2] | 0;
+ $cmp395 = ($63 | 0) == 0;
+ $shl394 = $K372_0 << 1;
+ if ($cmp395) {
+ label = 74;
+ break;
+ } else {
+ $K372_0 = $shl394;
+ $T_0 = $63;
+ label = 72;
+ break;
+ }
+ case 74:
+ $64 = $arrayidx393;
+ $65 = HEAP32[40820] | 0;
+ $cmp400 = $64 >>> 0 < $65 >>> 0;
+ if ($cmp400) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ HEAP32[$arrayidx393 >> 2] = $53;
+ $add_ptr_sum11 = $nb + 24 | 0;
+ $parent405 = $10 + $add_ptr_sum11 | 0;
+ $66 = $parent405;
+ HEAP32[$66 >> 2] = $T_0;
+ $add_ptr_sum12 = $nb + 12 | 0;
+ $bk406 = $10 + $add_ptr_sum12 | 0;
+ $67 = $bk406;
+ HEAP32[$67 >> 2] = $53;
+ $add_ptr_sum13 = $nb + 8 | 0;
+ $fd407 = $10 + $add_ptr_sum13 | 0;
+ $68 = $fd407;
+ HEAP32[$68 >> 2] = $53;
+ label = 81;
+ break;
+ case 76:
+ _abort();
+ return 0;
+ return 0;
+ case 77:
+ $fd412 = $T_0 + 8 | 0;
+ $69 = HEAP32[$fd412 >> 2] | 0;
+ $70 = $T_0;
+ $71 = HEAP32[40820] | 0;
+ $cmp414 = $70 >>> 0 < $71 >>> 0;
+ if ($cmp414) {
+ label = 80;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $72 = $69;
+ $cmp418 = $72 >>> 0 < $71 >>> 0;
+ if ($cmp418) {
+ label = 80;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 79:
+ $bk425 = $69 + 12 | 0;
+ HEAP32[$bk425 >> 2] = $53;
+ HEAP32[$fd412 >> 2] = $53;
+ $add_ptr_sum8 = $nb + 8 | 0;
+ $fd427 = $10 + $add_ptr_sum8 | 0;
+ $73 = $fd427;
+ HEAP32[$73 >> 2] = $69;
+ $add_ptr_sum9 = $nb + 12 | 0;
+ $bk428 = $10 + $add_ptr_sum9 | 0;
+ $74 = $bk428;
+ HEAP32[$74 >> 2] = $T_0;
+ $add_ptr_sum10 = $nb + 24 | 0;
+ $parent429 = $10 + $add_ptr_sum10 | 0;
+ $75 = $parent429;
+ HEAP32[$75 >> 2] = 0;
+ label = 81;
+ break;
+ case 80:
+ _abort();
+ return 0;
+ return 0;
+ case 81:
+ $add_ptr436 = $v_3_lcssa + 8 | 0;
+ $76 = $add_ptr436;
+ $retval_0 = $76;
+ label = 83;
+ break;
+ case 82:
+ _abort();
+ return 0;
+ return 0;
+ case 83:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _sys_alloc($nb) {
+ $nb = $nb | 0;
+ var $0 = 0, $cmp = 0, $add = 0, $1 = 0, $sub = 0, $add9 = 0, $neg = 0, $and11 = 0, $cmp12 = 0, $2 = 0, $cmp15 = 0, $3 = 0, $add17 = 0, $cmp19 = 0, $cmp21 = 0, $or_cond1 = 0, $4 = 0, $and26 = 0, $tobool27 = 0, $5 = 0, $cmp29 = 0, $6 = 0, $call31 = 0, $cmp32 = 0, $call34 = 0, $cmp35 = 0, $7 = 0, $8 = 0, $sub38 = 0, $and39 = 0, $cmp40 = 0, $add43 = 0, $neg45 = 0, $and46 = 0, $sub47 = 0, $add48 = 0, $ssize_0 = 0, $9 = 0, $add51 = 0, $cmp52 = 0, $cmp54 = 0, $or_cond = 0, $10 = 0, $cmp57 = 0, $cmp60 = 0, $cmp63 = 0, $or_cond2 = 0, $call65 = 0, $cmp66 = 0, $ssize_0_ = 0, $call34_ = 0, $11 = 0, $12 = 0, $sub71 = 0, $sub73 = 0, $add74 = 0, $neg76 = 0, $and77 = 0, $cmp78 = 0, $call80 = 0, $base81 = 0, $13 = 0, $size = 0, $14 = 0, $add_ptr = 0, $cmp82 = 0, $and77_ = 0, $call80_ = 0, $ssize_1 = 0, $br_0 = 0, $tsize_0 = 0, $tbase_0 = 0, $sub109 = 0, $cmp86 = 0, $cmp88 = 0, $cmp90 = 0, $or_cond3 = 0, $cmp93 = 0, $or_cond4 = 0, $15 = 0, $sub97 = 0, $sub96 = 0, $add98 = 0, $neg100 = 0, $and101 = 0, $cmp102 = 0, $call104 = 0, $cmp105 = 0, $add107 = 0, $call110 = 0, $ssize_2 = 0, $cmp115 = 0, $tsize_0132123 = 0, $16 = 0, $or = 0, $tsize_1 = 0, $cmp124 = 0, $call128 = 0, $call129 = 0, $notlhs = 0, $notrhs = 0, $or_cond6_not = 0, $cmp134 = 0, $or_cond7 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $add137 = 0, $cmp138 = 0, $sub_ptr_sub_tsize_1 = 0, $call128_tbase_1 = 0, $cmp144 = 0, $tbase_230 = 0, $tsize_229 = 0, $17 = 0, $add147 = 0, $18 = 0, $cmp148 = 0, $19 = 0, $cmp154 = 0, $20 = 0, $cmp156 = 0, $cmp159 = 0, $or_cond8 = 0, $21 = 0, $22 = 0, $sub169 = 0, $sp_038 = 0, $base184 = 0, $23 = 0, $size185 = 0, $24 = 0, $add_ptr186 = 0, $cmp187 = 0, $next = 0, $25 = 0, $cmp183 = 0, $sflags190 = 0, $26 = 0, $and191 = 0, $tobool192 = 0, $27 = 0, $28 = 0, $cmp200 = 0, $cmp206 = 0, $or_cond31 = 0, $add209 = 0, $29 = 0, $30 = 0, $add212 = 0, $31 = 0, $cmp215 = 0, $add_ptr224 = 0, $sp_134 = 0, $base223 = 0, $32 = 0, $cmp225 = 0, $next228 = 0, $33 = 0, $cmp221 = 0, $sflags232 = 0, $34 = 0, $and233 = 0, $tobool234 = 0, $size242 = 0, $35 = 0, $add243 = 0, $call244 = 0, $36 = 0, $cmp250 = 0, $sub253 = 0, $37 = 0, $38 = 0, $add_ptr255 = 0, $39 = 0, $or257 = 0, $add_ptr255_sum = 0, $head258 = 0, $40 = 0, $or260 = 0, $head261 = 0, $add_ptr262 = 0, $41 = 0, $call265 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[2802] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _init_mparams();
+ label = 4;
+ break;
+ case 4:
+ $add = $nb + 48 | 0;
+ $1 = HEAP32[2804] | 0;
+ $sub = $nb + 47 | 0;
+ $add9 = $sub + $1 | 0;
+ $neg = -$1 | 0;
+ $and11 = $add9 & $neg;
+ $cmp12 = $and11 >>> 0 > $nb >>> 0;
+ if ($cmp12) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = 0;
+ label = 52;
+ break;
+ }
+ case 5:
+ $2 = HEAP32[40926] | 0;
+ $cmp15 = ($2 | 0) == 0;
+ if ($cmp15) {
+ label = 7;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $3 = HEAP32[40924] | 0;
+ $add17 = $3 + $and11 | 0;
+ $cmp19 = $add17 >>> 0 <= $3 >>> 0;
+ $cmp21 = $add17 >>> 0 > $2 >>> 0;
+ $or_cond1 = $cmp19 | $cmp21;
+ if ($or_cond1) {
+ $retval_0 = 0;
+ label = 52;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $4 = HEAP32[40927] | 0;
+ $and26 = $4 & 4;
+ $tobool27 = ($and26 | 0) == 0;
+ if ($tobool27) {
+ label = 8;
+ break;
+ } else {
+ $tsize_1 = 0;
+ label = 27;
+ break;
+ }
+ case 8:
+ $5 = HEAP32[40822] | 0;
+ $cmp29 = ($5 | 0) == 0;
+ if ($cmp29) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $6 = $5;
+ $call31 = _segment_holding($6) | 0;
+ $cmp32 = ($call31 | 0) == 0;
+ if ($cmp32) {
+ label = 10;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 10:
+ $call34 = _sbrk(0) | 0;
+ $cmp35 = ($call34 | 0) == -1;
+ if ($cmp35) {
+ $tsize_0132123 = 0;
+ label = 26;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $7 = $call34;
+ $8 = HEAP32[2803] | 0;
+ $sub38 = $8 - 1 | 0;
+ $and39 = $sub38 & $7;
+ $cmp40 = ($and39 | 0) == 0;
+ if ($cmp40) {
+ $ssize_0 = $and11;
+ label = 13;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $add43 = $sub38 + $7 | 0;
+ $neg45 = -$8 | 0;
+ $and46 = $add43 & $neg45;
+ $sub47 = $and11 - $7 | 0;
+ $add48 = $sub47 + $and46 | 0;
+ $ssize_0 = $add48;
+ label = 13;
+ break;
+ case 13:
+ $9 = HEAP32[40924] | 0;
+ $add51 = $9 + $ssize_0 | 0;
+ $cmp52 = $ssize_0 >>> 0 > $nb >>> 0;
+ $cmp54 = $ssize_0 >>> 0 < 2147483647;
+ $or_cond = $cmp52 & $cmp54;
+ if ($or_cond) {
+ label = 14;
+ break;
+ } else {
+ $tsize_0132123 = 0;
+ label = 26;
+ break;
+ }
+ case 14:
+ $10 = HEAP32[40926] | 0;
+ $cmp57 = ($10 | 0) == 0;
+ if ($cmp57) {
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $cmp60 = $add51 >>> 0 <= $9 >>> 0;
+ $cmp63 = $add51 >>> 0 > $10 >>> 0;
+ $or_cond2 = $cmp60 | $cmp63;
+ if ($or_cond2) {
+ $tsize_0132123 = 0;
+ label = 26;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $call65 = _sbrk($ssize_0 | 0) | 0;
+ $cmp66 = ($call65 | 0) == ($call34 | 0);
+ $ssize_0_ = $cmp66 ? $ssize_0 : 0;
+ $call34_ = $cmp66 ? $call34 : -1;
+ $tbase_0 = $call34_;
+ $tsize_0 = $ssize_0_;
+ $br_0 = $call65;
+ $ssize_1 = $ssize_0;
+ label = 19;
+ break;
+ case 17:
+ $11 = HEAP32[40819] | 0;
+ $12 = HEAP32[2804] | 0;
+ $sub71 = $nb + 47 | 0;
+ $sub73 = $sub71 - $11 | 0;
+ $add74 = $sub73 + $12 | 0;
+ $neg76 = -$12 | 0;
+ $and77 = $add74 & $neg76;
+ $cmp78 = $and77 >>> 0 < 2147483647;
+ if ($cmp78) {
+ label = 18;
+ break;
+ } else {
+ $tsize_0132123 = 0;
+ label = 26;
+ break;
+ }
+ case 18:
+ $call80 = _sbrk($and77 | 0) | 0;
+ $base81 = $call31 | 0;
+ $13 = HEAP32[$base81 >> 2] | 0;
+ $size = $call31 + 4 | 0;
+ $14 = HEAP32[$size >> 2] | 0;
+ $add_ptr = $13 + $14 | 0;
+ $cmp82 = ($call80 | 0) == ($add_ptr | 0);
+ $and77_ = $cmp82 ? $and77 : 0;
+ $call80_ = $cmp82 ? $call80 : -1;
+ $tbase_0 = $call80_;
+ $tsize_0 = $and77_;
+ $br_0 = $call80;
+ $ssize_1 = $and77;
+ label = 19;
+ break;
+ case 19:
+ $sub109 = -$ssize_1 | 0;
+ $cmp86 = ($tbase_0 | 0) == -1;
+ if ($cmp86) {
+ label = 20;
+ break;
+ } else {
+ $tsize_229 = $tsize_0;
+ $tbase_230 = $tbase_0;
+ label = 30;
+ break;
+ }
+ case 20:
+ $cmp88 = ($br_0 | 0) != -1;
+ $cmp90 = $ssize_1 >>> 0 < 2147483647;
+ $or_cond3 = $cmp88 & $cmp90;
+ $cmp93 = $ssize_1 >>> 0 < $add >>> 0;
+ $or_cond4 = $or_cond3 & $cmp93;
+ if ($or_cond4) {
+ label = 21;
+ break;
+ } else {
+ $ssize_2 = $ssize_1;
+ label = 25;
+ break;
+ }
+ case 21:
+ $15 = HEAP32[2804] | 0;
+ $sub97 = $nb + 47 | 0;
+ $sub96 = $sub97 - $ssize_1 | 0;
+ $add98 = $sub96 + $15 | 0;
+ $neg100 = -$15 | 0;
+ $and101 = $add98 & $neg100;
+ $cmp102 = $and101 >>> 0 < 2147483647;
+ if ($cmp102) {
+ label = 22;
+ break;
+ } else {
+ $ssize_2 = $ssize_1;
+ label = 25;
+ break;
+ }
+ case 22:
+ $call104 = _sbrk($and101 | 0) | 0;
+ $cmp105 = ($call104 | 0) == -1;
+ if ($cmp105) {
+ label = 24;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $add107 = $and101 + $ssize_1 | 0;
+ $ssize_2 = $add107;
+ label = 25;
+ break;
+ case 24:
+ $call110 = _sbrk($sub109 | 0) | 0;
+ $tsize_0132123 = $tsize_0;
+ label = 26;
+ break;
+ case 25:
+ $cmp115 = ($br_0 | 0) == -1;
+ if ($cmp115) {
+ $tsize_0132123 = $tsize_0;
+ label = 26;
+ break;
+ } else {
+ $tsize_229 = $ssize_2;
+ $tbase_230 = $br_0;
+ label = 30;
+ break;
+ }
+ case 26:
+ $16 = HEAP32[40927] | 0;
+ $or = $16 | 4;
+ HEAP32[40927] = $or;
+ $tsize_1 = $tsize_0132123;
+ label = 27;
+ break;
+ case 27:
+ $cmp124 = $and11 >>> 0 < 2147483647;
+ if ($cmp124) {
+ label = 28;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 28:
+ $call128 = _sbrk($and11 | 0) | 0;
+ $call129 = _sbrk(0) | 0;
+ $notlhs = ($call128 | 0) != -1;
+ $notrhs = ($call129 | 0) != -1;
+ $or_cond6_not = $notrhs & $notlhs;
+ $cmp134 = $call128 >>> 0 < $call129 >>> 0;
+ $or_cond7 = $or_cond6_not & $cmp134;
+ if ($or_cond7) {
+ label = 29;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 29:
+ $sub_ptr_lhs_cast = $call129;
+ $sub_ptr_rhs_cast = $call128;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $add137 = $nb + 40 | 0;
+ $cmp138 = $sub_ptr_sub >>> 0 > $add137 >>> 0;
+ $sub_ptr_sub_tsize_1 = $cmp138 ? $sub_ptr_sub : $tsize_1;
+ $call128_tbase_1 = $cmp138 ? $call128 : -1;
+ $cmp144 = ($call128_tbase_1 | 0) == -1;
+ if ($cmp144) {
+ label = 51;
+ break;
+ } else {
+ $tsize_229 = $sub_ptr_sub_tsize_1;
+ $tbase_230 = $call128_tbase_1;
+ label = 30;
+ break;
+ }
+ case 30:
+ $17 = HEAP32[40924] | 0;
+ $add147 = $17 + $tsize_229 | 0;
+ HEAP32[40924] = $add147;
+ $18 = HEAP32[40925] | 0;
+ $cmp148 = $add147 >>> 0 > $18 >>> 0;
+ if ($cmp148) {
+ label = 31;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 31:
+ HEAP32[40925] = $add147;
+ label = 32;
+ break;
+ case 32:
+ $19 = HEAP32[40822] | 0;
+ $cmp154 = ($19 | 0) == 0;
+ if ($cmp154) {
+ label = 33;
+ break;
+ } else {
+ $sp_038 = 163712;
+ label = 36;
+ break;
+ }
+ case 33:
+ $20 = HEAP32[40820] | 0;
+ $cmp156 = ($20 | 0) == 0;
+ $cmp159 = $tbase_230 >>> 0 < $20 >>> 0;
+ $or_cond8 = $cmp156 | $cmp159;
+ if ($or_cond8) {
+ label = 34;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 34:
+ HEAP32[40820] = $tbase_230;
+ label = 35;
+ break;
+ case 35:
+ HEAP32[40928] = $tbase_230;
+ HEAP32[40929] = $tsize_229;
+ HEAP32[40931] = 0;
+ $21 = HEAP32[2802] | 0;
+ HEAP32[40825] = $21;
+ HEAP32[40824] = -1;
+ _init_bins();
+ $22 = $tbase_230;
+ $sub169 = $tsize_229 - 40 | 0;
+ _init_top($22, $sub169);
+ label = 49;
+ break;
+ case 36:
+ $base184 = $sp_038 | 0;
+ $23 = HEAP32[$base184 >> 2] | 0;
+ $size185 = $sp_038 + 4 | 0;
+ $24 = HEAP32[$size185 >> 2] | 0;
+ $add_ptr186 = $23 + $24 | 0;
+ $cmp187 = ($tbase_230 | 0) == ($add_ptr186 | 0);
+ if ($cmp187) {
+ label = 38;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $next = $sp_038 + 8 | 0;
+ $25 = HEAP32[$next >> 2] | 0;
+ $cmp183 = ($25 | 0) == 0;
+ if ($cmp183) {
+ label = 41;
+ break;
+ } else {
+ $sp_038 = $25;
+ label = 36;
+ break;
+ }
+ case 38:
+ $sflags190 = $sp_038 + 12 | 0;
+ $26 = HEAP32[$sflags190 >> 2] | 0;
+ $and191 = $26 & 8;
+ $tobool192 = ($and191 | 0) == 0;
+ if ($tobool192) {
+ label = 39;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 39:
+ $27 = HEAP32[40822] | 0;
+ $28 = $27;
+ $cmp200 = $28 >>> 0 >= $23 >>> 0;
+ $cmp206 = $28 >>> 0 < $add_ptr186 >>> 0;
+ $or_cond31 = $cmp200 & $cmp206;
+ if ($or_cond31) {
+ label = 40;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 40:
+ $add209 = $24 + $tsize_229 | 0;
+ HEAP32[$size185 >> 2] = $add209;
+ $29 = HEAP32[40822] | 0;
+ $30 = HEAP32[40819] | 0;
+ $add212 = $30 + $tsize_229 | 0;
+ _init_top($29, $add212);
+ label = 49;
+ break;
+ case 41:
+ $31 = HEAP32[40820] | 0;
+ $cmp215 = $tbase_230 >>> 0 < $31 >>> 0;
+ if ($cmp215) {
+ label = 42;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 42:
+ HEAP32[40820] = $tbase_230;
+ label = 43;
+ break;
+ case 43:
+ $add_ptr224 = $tbase_230 + $tsize_229 | 0;
+ $sp_134 = 163712;
+ label = 44;
+ break;
+ case 44:
+ $base223 = $sp_134 | 0;
+ $32 = HEAP32[$base223 >> 2] | 0;
+ $cmp225 = ($32 | 0) == ($add_ptr224 | 0);
+ if ($cmp225) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $next228 = $sp_134 + 8 | 0;
+ $33 = HEAP32[$next228 >> 2] | 0;
+ $cmp221 = ($33 | 0) == 0;
+ if ($cmp221) {
+ label = 48;
+ break;
+ } else {
+ $sp_134 = $33;
+ label = 44;
+ break;
+ }
+ case 46:
+ $sflags232 = $sp_134 + 12 | 0;
+ $34 = HEAP32[$sflags232 >> 2] | 0;
+ $and233 = $34 & 8;
+ $tobool234 = ($and233 | 0) == 0;
+ if ($tobool234) {
+ label = 47;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 47:
+ HEAP32[$base223 >> 2] = $tbase_230;
+ $size242 = $sp_134 + 4 | 0;
+ $35 = HEAP32[$size242 >> 2] | 0;
+ $add243 = $35 + $tsize_229 | 0;
+ HEAP32[$size242 >> 2] = $add243;
+ $call244 = _prepend_alloc($tbase_230, $32, $nb) | 0;
+ $retval_0 = $call244;
+ label = 52;
+ break;
+ case 48:
+ _add_segment($tbase_230, $tsize_229);
+ label = 49;
+ break;
+ case 49:
+ $36 = HEAP32[40819] | 0;
+ $cmp250 = $36 >>> 0 > $nb >>> 0;
+ if ($cmp250) {
+ label = 50;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 50:
+ $sub253 = $36 - $nb | 0;
+ HEAP32[40819] = $sub253;
+ $37 = HEAP32[40822] | 0;
+ $38 = $37;
+ $add_ptr255 = $38 + $nb | 0;
+ $39 = $add_ptr255;
+ HEAP32[40822] = $39;
+ $or257 = $sub253 | 1;
+ $add_ptr255_sum = $nb + 4 | 0;
+ $head258 = $38 + $add_ptr255_sum | 0;
+ $40 = $head258;
+ HEAP32[$40 >> 2] = $or257;
+ $or260 = $nb | 3;
+ $head261 = $37 + 4 | 0;
+ HEAP32[$head261 >> 2] = $or260;
+ $add_ptr262 = $37 + 8 | 0;
+ $41 = $add_ptr262;
+ $retval_0 = $41;
+ label = 52;
+ break;
+ case 51:
+ $call265 = ___errno_location() | 0;
+ HEAP32[$call265 >> 2] = 12;
+ $retval_0 = 0;
+ label = 52;
+ break;
+ case 52:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _free($mem) {
+ $mem = $mem | 0;
+ var $cmp = 0, $add_ptr = 0, $0 = 0, $1 = 0, $cmp1 = 0, $head = 0, $2 = 0, $3 = 0, $and = 0, $cmp2 = 0, $and5 = 0, $add_ptr_sum = 0, $add_ptr6 = 0, $4 = 0, $and8 = 0, $tobool9 = 0, $prev_foot = 0, $5 = 0, $cmp13 = 0, $add_ptr_sum232 = 0, $add_ptr16 = 0, $6 = 0, $add17 = 0, $cmp18 = 0, $7 = 0, $cmp22 = 0, $shr = 0, $cmp25 = 0, $add_ptr16_sum269 = 0, $fd = 0, $8 = 0, $9 = 0, $add_ptr16_sum270 = 0, $bk = 0, $10 = 0, $11 = 0, $shl = 0, $arrayidx = 0, $12 = 0, $cmp29 = 0, $13 = 0, $cmp31 = 0, $bk34 = 0, $14 = 0, $cmp35 = 0, $cmp42 = 0, $shl45 = 0, $neg = 0, $15 = 0, $and46 = 0, $cmp50 = 0, $16 = 0, $17 = 0, $cmp53 = 0, $fd56 = 0, $18 = 0, $cmp57 = 0, $bk66 = 0, $fd67 = 0, $19 = 0, $add_ptr16_sum261 = 0, $parent = 0, $20 = 0, $21 = 0, $add_ptr16_sum262 = 0, $bk73 = 0, $22 = 0, $23 = 0, $cmp74 = 0, $add_ptr16_sum266 = 0, $fd78 = 0, $24 = 0, $25 = 0, $26 = 0, $cmp80 = 0, $bk82 = 0, $27 = 0, $cmp83 = 0, $fd86 = 0, $28 = 0, $cmp87 = 0, $child_sum = 0, $arrayidx99 = 0, $29 = 0, $30 = 0, $cmp100 = 0, $add_ptr16_sum263 = 0, $child = 0, $arrayidx103 = 0, $31 = 0, $cmp104 = 0, $RP_0 = 0, $R_0 = 0, $arrayidx108 = 0, $32 = 0, $cmp109 = 0, $arrayidx113 = 0, $33 = 0, $cmp114 = 0, $CP_0 = 0, $34 = 0, $35 = 0, $36 = 0, $cmp118 = 0, $R_1 = 0, $cmp127 = 0, $add_ptr16_sum264 = 0, $index = 0, $37 = 0, $38 = 0, $arrayidx130 = 0, $39 = 0, $cmp131 = 0, $cond279 = 0, $40 = 0, $shl138 = 0, $neg139 = 0, $41 = 0, $and140 = 0, $42 = 0, $43 = 0, $cmp143 = 0, $arrayidx149 = 0, $44 = 0, $cmp150 = 0, $arrayidx157 = 0, $cmp162 = 0, $45 = 0, $46 = 0, $cmp165 = 0, $parent170 = 0, $add_ptr16_sum265 = 0, $child171 = 0, $arrayidx172 = 0, $47 = 0, $cmp173 = 0, $48 = 0, $49 = 0, $cmp176 = 0, $arrayidx182 = 0, $parent183 = 0, $child171_sum = 0, $arrayidx188 = 0, $50 = 0, $51 = 0, $cmp189 = 0, $52 = 0, $53 = 0, $cmp192 = 0, $arrayidx198 = 0, $parent199 = 0, $add_ptr6_sum = 0, $head209 = 0, $54 = 0, $55 = 0, $and210 = 0, $cmp211 = 0, $56 = 0, $and215 = 0, $or = 0, $add_ptr16_sum = 0, $head216 = 0, $57 = 0, $prev_foot218 = 0, $psize_0 = 0, $p_0 = 0, $58 = 0, $cmp225 = 0, $add_ptr6_sum259 = 0, $head228 = 0, $59 = 0, $60 = 0, $and229 = 0, $phitmp = 0, $and237 = 0, $tobool238 = 0, $61 = 0, $cmp240 = 0, $62 = 0, $add243 = 0, $or244 = 0, $head245 = 0, $63 = 0, $cmp246 = 0, $64 = 0, $cmp250 = 0, $65 = 0, $66 = 0, $cmp255 = 0, $67 = 0, $add258 = 0, $or259 = 0, $head260 = 0, $add_ptr261 = 0, $prev_foot262 = 0, $and265 = 0, $add266 = 0, $shr267 = 0, $cmp268 = 0, $fd272 = 0, $68 = 0, $69 = 0, $add_ptr6_sum253254 = 0, $bk274 = 0, $70 = 0, $71 = 0, $shl277 = 0, $arrayidx278 = 0, $72 = 0, $cmp279 = 0, $73 = 0, $74 = 0, $cmp282 = 0, $bk285 = 0, $75 = 0, $cmp286 = 0, $cmp295 = 0, $shl298 = 0, $neg299 = 0, $76 = 0, $and300 = 0, $cmp304 = 0, $77 = 0, $78 = 0, $cmp307 = 0, $fd310 = 0, $79 = 0, $cmp311 = 0, $bk320 = 0, $fd321 = 0, $80 = 0, $add_ptr6_sum234 = 0, $parent330 = 0, $81 = 0, $82 = 0, $add_ptr6_sum235236 = 0, $bk332 = 0, $83 = 0, $84 = 0, $cmp333 = 0, $fd337 = 0, $85 = 0, $86 = 0, $87 = 0, $88 = 0, $cmp339 = 0, $bk342 = 0, $89 = 0, $cmp343 = 0, $fd346 = 0, $90 = 0, $cmp347 = 0, $child360_sum = 0, $arrayidx361 = 0, $91 = 0, $92 = 0, $cmp362 = 0, $add_ptr6_sum237 = 0, $child360 = 0, $arrayidx366 = 0, $93 = 0, $cmp367 = 0, $RP359_0 = 0, $R331_0 = 0, $arrayidx373 = 0, $94 = 0, $cmp374 = 0, $arrayidx378 = 0, $95 = 0, $cmp379 = 0, $CP370_0 = 0, $96 = 0, $97 = 0, $98 = 0, $cmp385 = 0, $R331_1 = 0, $cmp394 = 0, $add_ptr6_sum247 = 0, $index398 = 0, $99 = 0, $100 = 0, $arrayidx399 = 0, $101 = 0, $cmp400 = 0, $cond280 = 0, $102 = 0, $shl407 = 0, $neg408 = 0, $103 = 0, $and409 = 0, $104 = 0, $105 = 0, $cmp412 = 0, $arrayidx418 = 0, $106 = 0, $cmp419 = 0, $arrayidx426 = 0, $cmp431 = 0, $107 = 0, $108 = 0, $cmp434 = 0, $parent441 = 0, $add_ptr6_sum248 = 0, $child442 = 0, $arrayidx443 = 0, $109 = 0, $cmp444 = 0, $110 = 0, $111 = 0, $cmp447 = 0, $arrayidx453 = 0, $parent454 = 0, $child442_sum = 0, $arrayidx459 = 0, $112 = 0, $113 = 0, $cmp460 = 0, $114 = 0, $115 = 0, $cmp463 = 0, $arrayidx469 = 0, $parent470 = 0, $or479 = 0, $head480 = 0, $add_ptr481 = 0, $prev_foot482 = 0, $116 = 0, $cmp483 = 0, $and491 = 0, $or492 = 0, $head493 = 0, $add_ptr494 = 0, $prev_foot495 = 0, $psize_1 = 0, $shr497 = 0, $cmp498 = 0, $shl504 = 0, $arrayidx505 = 0, $117 = 0, $118 = 0, $shl507 = 0, $and508 = 0, $tobool509 = 0, $or512 = 0, $arrayidx505_sum246 = 0, $119 = 0, $120 = 0, $121 = 0, $122 = 0, $cmp515 = 0, $F506_0 = 0, $arrayidx505_sum = 0, $123 = 0, $bk525 = 0, $fd526 = 0, $bk527 = 0, $124 = 0, $shr531 = 0, $cmp532 = 0, $cmp536 = 0, $sub = 0, $shr540 = 0, $and541 = 0, $shl542 = 0, $sub543 = 0, $shr544 = 0, $and545 = 0, $add546 = 0, $shl547 = 0, $sub548 = 0, $shr549 = 0, $and550 = 0, $add551 = 0, $sub552 = 0, $shl553 = 0, $shr554 = 0, $add555 = 0, $shl556 = 0, $add557 = 0, $shr558 = 0, $and559 = 0, $add560 = 0, $I530_0 = 0, $arrayidx563 = 0, $index564 = 0, $I530_0_c = 0, $arrayidx566 = 0, $125 = 0, $126 = 0, $shl569 = 0, $and570 = 0, $tobool571 = 0, $or574 = 0, $parent575 = 0, $_c = 0, $bk576 = 0, $fd577 = 0, $127 = 0, $cmp580 = 0, $shr582 = 0, $sub585 = 0, $cond = 0, $shl586 = 0, $T_0 = 0, $K579_0 = 0, $head587 = 0, $128 = 0, $and588 = 0, $cmp589 = 0, $shr592 = 0, $arrayidx595 = 0, $129 = 0, $cmp597 = 0, $shl596 = 0, $130 = 0, $131 = 0, $cmp601 = 0, $parent606 = 0, $T_0_c243 = 0, $bk607 = 0, $fd608 = 0, $fd613 = 0, $132 = 0, $133 = 0, $134 = 0, $cmp614 = 0, $135 = 0, $cmp617 = 0, $bk624 = 0, $fd626 = 0, $_c242 = 0, $bk627 = 0, $T_0_c = 0, $parent628 = 0, $136 = 0, $dec = 0, $cmp632 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($mem | 0) == 0;
+ if ($cmp) {
+ label = 142;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add_ptr = $mem - 8 | 0;
+ $0 = $add_ptr;
+ $1 = HEAP32[40820] | 0;
+ $cmp1 = $add_ptr >>> 0 < $1 >>> 0;
+ if ($cmp1) {
+ label = 141;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $head = $mem - 4 | 0;
+ $2 = $head;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $and = $3 & 3;
+ $cmp2 = ($and | 0) == 1;
+ if ($cmp2) {
+ label = 141;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $and5 = $3 & -8;
+ $add_ptr_sum = $and5 - 8 | 0;
+ $add_ptr6 = $mem + $add_ptr_sum | 0;
+ $4 = $add_ptr6;
+ $and8 = $3 & 1;
+ $tobool9 = ($and8 | 0) == 0;
+ if ($tobool9) {
+ label = 6;
+ break;
+ } else {
+ $p_0 = $0;
+ $psize_0 = $and5;
+ label = 57;
+ break;
+ }
+ case 6:
+ $prev_foot = $add_ptr;
+ $5 = HEAP32[$prev_foot >> 2] | 0;
+ $cmp13 = ($and | 0) == 0;
+ if ($cmp13) {
+ label = 142;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add_ptr_sum232 = -8 - $5 | 0;
+ $add_ptr16 = $mem + $add_ptr_sum232 | 0;
+ $6 = $add_ptr16;
+ $add17 = $5 + $and5 | 0;
+ $cmp18 = $add_ptr16 >>> 0 < $1 >>> 0;
+ if ($cmp18) {
+ label = 141;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $7 = HEAP32[40821] | 0;
+ $cmp22 = ($6 | 0) == ($7 | 0);
+ if ($cmp22) {
+ label = 55;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $shr = $5 >>> 3;
+ $cmp25 = $5 >>> 0 < 256;
+ if ($cmp25) {
+ label = 10;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 10:
+ $add_ptr16_sum269 = $add_ptr_sum232 + 8 | 0;
+ $fd = $mem + $add_ptr16_sum269 | 0;
+ $8 = $fd;
+ $9 = HEAP32[$8 >> 2] | 0;
+ $add_ptr16_sum270 = $add_ptr_sum232 + 12 | 0;
+ $bk = $mem + $add_ptr16_sum270 | 0;
+ $10 = $bk;
+ $11 = HEAP32[$10 >> 2] | 0;
+ $shl = $shr << 1;
+ $arrayidx = 163304 + ($shl << 2) | 0;
+ $12 = $arrayidx;
+ $cmp29 = ($9 | 0) == ($12 | 0);
+ if ($cmp29) {
+ label = 13;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $13 = $9;
+ $cmp31 = $13 >>> 0 < $1 >>> 0;
+ if ($cmp31) {
+ label = 20;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $bk34 = $9 + 12 | 0;
+ $14 = HEAP32[$bk34 >> 2] | 0;
+ $cmp35 = ($14 | 0) == ($6 | 0);
+ if ($cmp35) {
+ label = 13;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 13:
+ $cmp42 = ($11 | 0) == ($9 | 0);
+ if ($cmp42) {
+ label = 14;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 14:
+ $shl45 = 1 << $shr;
+ $neg = $shl45 ^ -1;
+ $15 = HEAP32[40816] | 0;
+ $and46 = $15 & $neg;
+ HEAP32[40816] = $and46;
+ $p_0 = $6;
+ $psize_0 = $add17;
+ label = 57;
+ break;
+ case 15:
+ $cmp50 = ($11 | 0) == ($12 | 0);
+ if ($cmp50) {
+ label = 18;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 16:
+ $16 = $11;
+ $17 = HEAP32[40820] | 0;
+ $cmp53 = $16 >>> 0 < $17 >>> 0;
+ if ($cmp53) {
+ label = 19;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 17:
+ $fd56 = $11 + 8 | 0;
+ $18 = HEAP32[$fd56 >> 2] | 0;
+ $cmp57 = ($18 | 0) == ($6 | 0);
+ if ($cmp57) {
+ label = 18;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 18:
+ $bk66 = $9 + 12 | 0;
+ HEAP32[$bk66 >> 2] = $11;
+ $fd67 = $11 + 8 | 0;
+ HEAP32[$fd67 >> 2] = $9;
+ $p_0 = $6;
+ $psize_0 = $add17;
+ label = 57;
+ break;
+ case 19:
+ _abort();
+ case 20:
+ _abort();
+ case 21:
+ $19 = $add_ptr16;
+ $add_ptr16_sum261 = $add_ptr_sum232 + 24 | 0;
+ $parent = $mem + $add_ptr16_sum261 | 0;
+ $20 = $parent;
+ $21 = HEAP32[$20 >> 2] | 0;
+ $add_ptr16_sum262 = $add_ptr_sum232 + 12 | 0;
+ $bk73 = $mem + $add_ptr16_sum262 | 0;
+ $22 = $bk73;
+ $23 = HEAP32[$22 >> 2] | 0;
+ $cmp74 = ($23 | 0) == ($19 | 0);
+ if ($cmp74) {
+ label = 27;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $add_ptr16_sum266 = $add_ptr_sum232 + 8 | 0;
+ $fd78 = $mem + $add_ptr16_sum266 | 0;
+ $24 = $fd78;
+ $25 = HEAP32[$24 >> 2] | 0;
+ $26 = $25;
+ $cmp80 = $26 >>> 0 < $1 >>> 0;
+ if ($cmp80) {
+ label = 26;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $bk82 = $25 + 12 | 0;
+ $27 = HEAP32[$bk82 >> 2] | 0;
+ $cmp83 = ($27 | 0) == ($19 | 0);
+ if ($cmp83) {
+ label = 24;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 24:
+ $fd86 = $23 + 8 | 0;
+ $28 = HEAP32[$fd86 >> 2] | 0;
+ $cmp87 = ($28 | 0) == ($19 | 0);
+ if ($cmp87) {
+ label = 25;
+ break;
+ } else {
+ label = 26;
+ break;
+ }
+ case 25:
+ HEAP32[$bk82 >> 2] = $23;
+ HEAP32[$fd86 >> 2] = $25;
+ $R_1 = $23;
+ label = 35;
+ break;
+ case 26:
+ _abort();
+ case 27:
+ $child_sum = $add_ptr_sum232 + 20 | 0;
+ $arrayidx99 = $mem + $child_sum | 0;
+ $29 = $arrayidx99;
+ $30 = HEAP32[$29 >> 2] | 0;
+ $cmp100 = ($30 | 0) == 0;
+ if ($cmp100) {
+ label = 28;
+ break;
+ } else {
+ $R_0 = $30;
+ $RP_0 = $29;
+ label = 29;
+ break;
+ }
+ case 28:
+ $add_ptr16_sum263 = $add_ptr_sum232 + 16 | 0;
+ $child = $mem + $add_ptr16_sum263 | 0;
+ $arrayidx103 = $child;
+ $31 = HEAP32[$arrayidx103 >> 2] | 0;
+ $cmp104 = ($31 | 0) == 0;
+ if ($cmp104) {
+ $R_1 = 0;
+ label = 35;
+ break;
+ } else {
+ $R_0 = $31;
+ $RP_0 = $arrayidx103;
+ label = 29;
+ break;
+ }
+ case 29:
+ $arrayidx108 = $R_0 + 20 | 0;
+ $32 = HEAP32[$arrayidx108 >> 2] | 0;
+ $cmp109 = ($32 | 0) == 0;
+ if ($cmp109) {
+ label = 30;
+ break;
+ } else {
+ $CP_0 = $arrayidx108;
+ label = 31;
+ break;
+ }
+ case 30:
+ $arrayidx113 = $R_0 + 16 | 0;
+ $33 = HEAP32[$arrayidx113 >> 2] | 0;
+ $cmp114 = ($33 | 0) == 0;
+ if ($cmp114) {
+ label = 32;
+ break;
+ } else {
+ $CP_0 = $arrayidx113;
+ label = 31;
+ break;
+ }
+ case 31:
+ $34 = HEAP32[$CP_0 >> 2] | 0;
+ $R_0 = $34;
+ $RP_0 = $CP_0;
+ label = 29;
+ break;
+ case 32:
+ $35 = $RP_0;
+ $36 = HEAP32[40820] | 0;
+ $cmp118 = $35 >>> 0 < $36 >>> 0;
+ if ($cmp118) {
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ HEAP32[$RP_0 >> 2] = 0;
+ $R_1 = $R_0;
+ label = 35;
+ break;
+ case 34:
+ _abort();
+ case 35:
+ $cmp127 = ($21 | 0) == 0;
+ if ($cmp127) {
+ $p_0 = $6;
+ $psize_0 = $add17;
+ label = 57;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $add_ptr16_sum264 = $add_ptr_sum232 + 28 | 0;
+ $index = $mem + $add_ptr16_sum264 | 0;
+ $37 = $index;
+ $38 = HEAP32[$37 >> 2] | 0;
+ $arrayidx130 = 163568 + ($38 << 2) | 0;
+ $39 = HEAP32[$arrayidx130 >> 2] | 0;
+ $cmp131 = ($19 | 0) == ($39 | 0);
+ if ($cmp131) {
+ label = 37;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 37:
+ HEAP32[$arrayidx130 >> 2] = $R_1;
+ $cond279 = ($R_1 | 0) == 0;
+ if ($cond279) {
+ label = 38;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 38:
+ $40 = HEAP32[$37 >> 2] | 0;
+ $shl138 = 1 << $40;
+ $neg139 = $shl138 ^ -1;
+ $41 = HEAP32[40817] | 0;
+ $and140 = $41 & $neg139;
+ HEAP32[40817] = $and140;
+ $p_0 = $6;
+ $psize_0 = $add17;
+ label = 57;
+ break;
+ case 39:
+ $42 = $21;
+ $43 = HEAP32[40820] | 0;
+ $cmp143 = $42 >>> 0 < $43 >>> 0;
+ if ($cmp143) {
+ label = 43;
+ break;
+ } else {
+ label = 40;
+ break;
+ }
+ case 40:
+ $arrayidx149 = $21 + 16 | 0;
+ $44 = HEAP32[$arrayidx149 >> 2] | 0;
+ $cmp150 = ($44 | 0) == ($19 | 0);
+ if ($cmp150) {
+ label = 41;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 41:
+ HEAP32[$arrayidx149 >> 2] = $R_1;
+ label = 44;
+ break;
+ case 42:
+ $arrayidx157 = $21 + 20 | 0;
+ HEAP32[$arrayidx157 >> 2] = $R_1;
+ label = 44;
+ break;
+ case 43:
+ _abort();
+ case 44:
+ $cmp162 = ($R_1 | 0) == 0;
+ if ($cmp162) {
+ $p_0 = $6;
+ $psize_0 = $add17;
+ label = 57;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $45 = $R_1;
+ $46 = HEAP32[40820] | 0;
+ $cmp165 = $45 >>> 0 < $46 >>> 0;
+ if ($cmp165) {
+ label = 54;
+ break;
+ } else {
+ label = 46;
+ break;
+ }
+ case 46:
+ $parent170 = $R_1 + 24 | 0;
+ HEAP32[$parent170 >> 2] = $21;
+ $add_ptr16_sum265 = $add_ptr_sum232 + 16 | 0;
+ $child171 = $mem + $add_ptr16_sum265 | 0;
+ $arrayidx172 = $child171;
+ $47 = HEAP32[$arrayidx172 >> 2] | 0;
+ $cmp173 = ($47 | 0) == 0;
+ if ($cmp173) {
+ label = 50;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $48 = $47;
+ $49 = HEAP32[40820] | 0;
+ $cmp176 = $48 >>> 0 < $49 >>> 0;
+ if ($cmp176) {
+ label = 49;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $arrayidx182 = $R_1 + 16 | 0;
+ HEAP32[$arrayidx182 >> 2] = $47;
+ $parent183 = $47 + 24 | 0;
+ HEAP32[$parent183 >> 2] = $R_1;
+ label = 50;
+ break;
+ case 49:
+ _abort();
+ case 50:
+ $child171_sum = $add_ptr_sum232 + 20 | 0;
+ $arrayidx188 = $mem + $child171_sum | 0;
+ $50 = $arrayidx188;
+ $51 = HEAP32[$50 >> 2] | 0;
+ $cmp189 = ($51 | 0) == 0;
+ if ($cmp189) {
+ $p_0 = $6;
+ $psize_0 = $add17;
+ label = 57;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 51:
+ $52 = $51;
+ $53 = HEAP32[40820] | 0;
+ $cmp192 = $52 >>> 0 < $53 >>> 0;
+ if ($cmp192) {
+ label = 53;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $arrayidx198 = $R_1 + 20 | 0;
+ HEAP32[$arrayidx198 >> 2] = $51;
+ $parent199 = $51 + 24 | 0;
+ HEAP32[$parent199 >> 2] = $R_1;
+ $p_0 = $6;
+ $psize_0 = $add17;
+ label = 57;
+ break;
+ case 53:
+ _abort();
+ case 54:
+ _abort();
+ case 55:
+ $add_ptr6_sum = $and5 - 4 | 0;
+ $head209 = $mem + $add_ptr6_sum | 0;
+ $54 = $head209;
+ $55 = HEAP32[$54 >> 2] | 0;
+ $and210 = $55 & 3;
+ $cmp211 = ($and210 | 0) == 3;
+ if ($cmp211) {
+ label = 56;
+ break;
+ } else {
+ $p_0 = $6;
+ $psize_0 = $add17;
+ label = 57;
+ break;
+ }
+ case 56:
+ HEAP32[40818] = $add17;
+ $56 = HEAP32[$54 >> 2] | 0;
+ $and215 = $56 & -2;
+ HEAP32[$54 >> 2] = $and215;
+ $or = $add17 | 1;
+ $add_ptr16_sum = $add_ptr_sum232 + 4 | 0;
+ $head216 = $mem + $add_ptr16_sum | 0;
+ $57 = $head216;
+ HEAP32[$57 >> 2] = $or;
+ $prev_foot218 = $add_ptr6;
+ HEAP32[$prev_foot218 >> 2] = $add17;
+ label = 142;
+ break;
+ case 57:
+ $58 = $p_0;
+ $cmp225 = $58 >>> 0 < $add_ptr6 >>> 0;
+ if ($cmp225) {
+ label = 58;
+ break;
+ } else {
+ label = 141;
+ break;
+ }
+ case 58:
+ $add_ptr6_sum259 = $and5 - 4 | 0;
+ $head228 = $mem + $add_ptr6_sum259 | 0;
+ $59 = $head228;
+ $60 = HEAP32[$59 >> 2] | 0;
+ $and229 = $60 & 1;
+ $phitmp = ($and229 | 0) == 0;
+ if ($phitmp) {
+ label = 141;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ $and237 = $60 & 2;
+ $tobool238 = ($and237 | 0) == 0;
+ if ($tobool238) {
+ label = 60;
+ break;
+ } else {
+ label = 115;
+ break;
+ }
+ case 60:
+ $61 = HEAP32[40822] | 0;
+ $cmp240 = ($4 | 0) == ($61 | 0);
+ if ($cmp240) {
+ label = 61;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 61:
+ $62 = HEAP32[40819] | 0;
+ $add243 = $62 + $psize_0 | 0;
+ HEAP32[40819] = $add243;
+ HEAP32[40822] = $p_0;
+ $or244 = $add243 | 1;
+ $head245 = $p_0 + 4 | 0;
+ HEAP32[$head245 >> 2] = $or244;
+ $63 = HEAP32[40821] | 0;
+ $cmp246 = ($p_0 | 0) == ($63 | 0);
+ if ($cmp246) {
+ label = 62;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 62:
+ HEAP32[40821] = 0;
+ HEAP32[40818] = 0;
+ label = 63;
+ break;
+ case 63:
+ $64 = HEAP32[40823] | 0;
+ $cmp250 = $add243 >>> 0 > $64 >>> 0;
+ if ($cmp250) {
+ label = 64;
+ break;
+ } else {
+ label = 142;
+ break;
+ }
+ case 64:
+ $65 = _sys_trim(0) | 0;
+ label = 142;
+ break;
+ case 65:
+ $66 = HEAP32[40821] | 0;
+ $cmp255 = ($4 | 0) == ($66 | 0);
+ if ($cmp255) {
+ label = 66;
+ break;
+ } else {
+ label = 67;
+ break;
+ }
+ case 66:
+ $67 = HEAP32[40818] | 0;
+ $add258 = $67 + $psize_0 | 0;
+ HEAP32[40818] = $add258;
+ HEAP32[40821] = $p_0;
+ $or259 = $add258 | 1;
+ $head260 = $p_0 + 4 | 0;
+ HEAP32[$head260 >> 2] = $or259;
+ $add_ptr261 = $58 + $add258 | 0;
+ $prev_foot262 = $add_ptr261;
+ HEAP32[$prev_foot262 >> 2] = $add258;
+ label = 142;
+ break;
+ case 67:
+ $and265 = $60 & -8;
+ $add266 = $and265 + $psize_0 | 0;
+ $shr267 = $60 >>> 3;
+ $cmp268 = $60 >>> 0 < 256;
+ if ($cmp268) {
+ label = 68;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 68:
+ $fd272 = $mem + $and5 | 0;
+ $68 = $fd272;
+ $69 = HEAP32[$68 >> 2] | 0;
+ $add_ptr6_sum253254 = $and5 | 4;
+ $bk274 = $mem + $add_ptr6_sum253254 | 0;
+ $70 = $bk274;
+ $71 = HEAP32[$70 >> 2] | 0;
+ $shl277 = $shr267 << 1;
+ $arrayidx278 = 163304 + ($shl277 << 2) | 0;
+ $72 = $arrayidx278;
+ $cmp279 = ($69 | 0) == ($72 | 0);
+ if ($cmp279) {
+ label = 71;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 69:
+ $73 = $69;
+ $74 = HEAP32[40820] | 0;
+ $cmp282 = $73 >>> 0 < $74 >>> 0;
+ if ($cmp282) {
+ label = 78;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $bk285 = $69 + 12 | 0;
+ $75 = HEAP32[$bk285 >> 2] | 0;
+ $cmp286 = ($75 | 0) == ($4 | 0);
+ if ($cmp286) {
+ label = 71;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 71:
+ $cmp295 = ($71 | 0) == ($69 | 0);
+ if ($cmp295) {
+ label = 72;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 72:
+ $shl298 = 1 << $shr267;
+ $neg299 = $shl298 ^ -1;
+ $76 = HEAP32[40816] | 0;
+ $and300 = $76 & $neg299;
+ HEAP32[40816] = $and300;
+ label = 113;
+ break;
+ case 73:
+ $cmp304 = ($71 | 0) == ($72 | 0);
+ if ($cmp304) {
+ label = 76;
+ break;
+ } else {
+ label = 74;
+ break;
+ }
+ case 74:
+ $77 = $71;
+ $78 = HEAP32[40820] | 0;
+ $cmp307 = $77 >>> 0 < $78 >>> 0;
+ if ($cmp307) {
+ label = 77;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $fd310 = $71 + 8 | 0;
+ $79 = HEAP32[$fd310 >> 2] | 0;
+ $cmp311 = ($79 | 0) == ($4 | 0);
+ if ($cmp311) {
+ label = 76;
+ break;
+ } else {
+ label = 77;
+ break;
+ }
+ case 76:
+ $bk320 = $69 + 12 | 0;
+ HEAP32[$bk320 >> 2] = $71;
+ $fd321 = $71 + 8 | 0;
+ HEAP32[$fd321 >> 2] = $69;
+ label = 113;
+ break;
+ case 77:
+ _abort();
+ case 78:
+ _abort();
+ case 79:
+ $80 = $add_ptr6;
+ $add_ptr6_sum234 = $and5 + 16 | 0;
+ $parent330 = $mem + $add_ptr6_sum234 | 0;
+ $81 = $parent330;
+ $82 = HEAP32[$81 >> 2] | 0;
+ $add_ptr6_sum235236 = $and5 | 4;
+ $bk332 = $mem + $add_ptr6_sum235236 | 0;
+ $83 = $bk332;
+ $84 = HEAP32[$83 >> 2] | 0;
+ $cmp333 = ($84 | 0) == ($80 | 0);
+ if ($cmp333) {
+ label = 85;
+ break;
+ } else {
+ label = 80;
+ break;
+ }
+ case 80:
+ $fd337 = $mem + $and5 | 0;
+ $85 = $fd337;
+ $86 = HEAP32[$85 >> 2] | 0;
+ $87 = $86;
+ $88 = HEAP32[40820] | 0;
+ $cmp339 = $87 >>> 0 < $88 >>> 0;
+ if ($cmp339) {
+ label = 84;
+ break;
+ } else {
+ label = 81;
+ break;
+ }
+ case 81:
+ $bk342 = $86 + 12 | 0;
+ $89 = HEAP32[$bk342 >> 2] | 0;
+ $cmp343 = ($89 | 0) == ($80 | 0);
+ if ($cmp343) {
+ label = 82;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 82:
+ $fd346 = $84 + 8 | 0;
+ $90 = HEAP32[$fd346 >> 2] | 0;
+ $cmp347 = ($90 | 0) == ($80 | 0);
+ if ($cmp347) {
+ label = 83;
+ break;
+ } else {
+ label = 84;
+ break;
+ }
+ case 83:
+ HEAP32[$bk342 >> 2] = $84;
+ HEAP32[$fd346 >> 2] = $86;
+ $R331_1 = $84;
+ label = 93;
+ break;
+ case 84:
+ _abort();
+ case 85:
+ $child360_sum = $and5 + 12 | 0;
+ $arrayidx361 = $mem + $child360_sum | 0;
+ $91 = $arrayidx361;
+ $92 = HEAP32[$91 >> 2] | 0;
+ $cmp362 = ($92 | 0) == 0;
+ if ($cmp362) {
+ label = 86;
+ break;
+ } else {
+ $R331_0 = $92;
+ $RP359_0 = $91;
+ label = 87;
+ break;
+ }
+ case 86:
+ $add_ptr6_sum237 = $and5 + 8 | 0;
+ $child360 = $mem + $add_ptr6_sum237 | 0;
+ $arrayidx366 = $child360;
+ $93 = HEAP32[$arrayidx366 >> 2] | 0;
+ $cmp367 = ($93 | 0) == 0;
+ if ($cmp367) {
+ $R331_1 = 0;
+ label = 93;
+ break;
+ } else {
+ $R331_0 = $93;
+ $RP359_0 = $arrayidx366;
+ label = 87;
+ break;
+ }
+ case 87:
+ $arrayidx373 = $R331_0 + 20 | 0;
+ $94 = HEAP32[$arrayidx373 >> 2] | 0;
+ $cmp374 = ($94 | 0) == 0;
+ if ($cmp374) {
+ label = 88;
+ break;
+ } else {
+ $CP370_0 = $arrayidx373;
+ label = 89;
+ break;
+ }
+ case 88:
+ $arrayidx378 = $R331_0 + 16 | 0;
+ $95 = HEAP32[$arrayidx378 >> 2] | 0;
+ $cmp379 = ($95 | 0) == 0;
+ if ($cmp379) {
+ label = 90;
+ break;
+ } else {
+ $CP370_0 = $arrayidx378;
+ label = 89;
+ break;
+ }
+ case 89:
+ $96 = HEAP32[$CP370_0 >> 2] | 0;
+ $R331_0 = $96;
+ $RP359_0 = $CP370_0;
+ label = 87;
+ break;
+ case 90:
+ $97 = $RP359_0;
+ $98 = HEAP32[40820] | 0;
+ $cmp385 = $97 >>> 0 < $98 >>> 0;
+ if ($cmp385) {
+ label = 92;
+ break;
+ } else {
+ label = 91;
+ break;
+ }
+ case 91:
+ HEAP32[$RP359_0 >> 2] = 0;
+ $R331_1 = $R331_0;
+ label = 93;
+ break;
+ case 92:
+ _abort();
+ case 93:
+ $cmp394 = ($82 | 0) == 0;
+ if ($cmp394) {
+ label = 113;
+ break;
+ } else {
+ label = 94;
+ break;
+ }
+ case 94:
+ $add_ptr6_sum247 = $and5 + 20 | 0;
+ $index398 = $mem + $add_ptr6_sum247 | 0;
+ $99 = $index398;
+ $100 = HEAP32[$99 >> 2] | 0;
+ $arrayidx399 = 163568 + ($100 << 2) | 0;
+ $101 = HEAP32[$arrayidx399 >> 2] | 0;
+ $cmp400 = ($80 | 0) == ($101 | 0);
+ if ($cmp400) {
+ label = 95;
+ break;
+ } else {
+ label = 97;
+ break;
+ }
+ case 95:
+ HEAP32[$arrayidx399 >> 2] = $R331_1;
+ $cond280 = ($R331_1 | 0) == 0;
+ if ($cond280) {
+ label = 96;
+ break;
+ } else {
+ label = 103;
+ break;
+ }
+ case 96:
+ $102 = HEAP32[$99 >> 2] | 0;
+ $shl407 = 1 << $102;
+ $neg408 = $shl407 ^ -1;
+ $103 = HEAP32[40817] | 0;
+ $and409 = $103 & $neg408;
+ HEAP32[40817] = $and409;
+ label = 113;
+ break;
+ case 97:
+ $104 = $82;
+ $105 = HEAP32[40820] | 0;
+ $cmp412 = $104 >>> 0 < $105 >>> 0;
+ if ($cmp412) {
+ label = 101;
+ break;
+ } else {
+ label = 98;
+ break;
+ }
+ case 98:
+ $arrayidx418 = $82 + 16 | 0;
+ $106 = HEAP32[$arrayidx418 >> 2] | 0;
+ $cmp419 = ($106 | 0) == ($80 | 0);
+ if ($cmp419) {
+ label = 99;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 99:
+ HEAP32[$arrayidx418 >> 2] = $R331_1;
+ label = 102;
+ break;
+ case 100:
+ $arrayidx426 = $82 + 20 | 0;
+ HEAP32[$arrayidx426 >> 2] = $R331_1;
+ label = 102;
+ break;
+ case 101:
+ _abort();
+ case 102:
+ $cmp431 = ($R331_1 | 0) == 0;
+ if ($cmp431) {
+ label = 113;
+ break;
+ } else {
+ label = 103;
+ break;
+ }
+ case 103:
+ $107 = $R331_1;
+ $108 = HEAP32[40820] | 0;
+ $cmp434 = $107 >>> 0 < $108 >>> 0;
+ if ($cmp434) {
+ label = 112;
+ break;
+ } else {
+ label = 104;
+ break;
+ }
+ case 104:
+ $parent441 = $R331_1 + 24 | 0;
+ HEAP32[$parent441 >> 2] = $82;
+ $add_ptr6_sum248 = $and5 + 8 | 0;
+ $child442 = $mem + $add_ptr6_sum248 | 0;
+ $arrayidx443 = $child442;
+ $109 = HEAP32[$arrayidx443 >> 2] | 0;
+ $cmp444 = ($109 | 0) == 0;
+ if ($cmp444) {
+ label = 108;
+ break;
+ } else {
+ label = 105;
+ break;
+ }
+ case 105:
+ $110 = $109;
+ $111 = HEAP32[40820] | 0;
+ $cmp447 = $110 >>> 0 < $111 >>> 0;
+ if ($cmp447) {
+ label = 107;
+ break;
+ } else {
+ label = 106;
+ break;
+ }
+ case 106:
+ $arrayidx453 = $R331_1 + 16 | 0;
+ HEAP32[$arrayidx453 >> 2] = $109;
+ $parent454 = $109 + 24 | 0;
+ HEAP32[$parent454 >> 2] = $R331_1;
+ label = 108;
+ break;
+ case 107:
+ _abort();
+ case 108:
+ $child442_sum = $and5 + 12 | 0;
+ $arrayidx459 = $mem + $child442_sum | 0;
+ $112 = $arrayidx459;
+ $113 = HEAP32[$112 >> 2] | 0;
+ $cmp460 = ($113 | 0) == 0;
+ if ($cmp460) {
+ label = 113;
+ break;
+ } else {
+ label = 109;
+ break;
+ }
+ case 109:
+ $114 = $113;
+ $115 = HEAP32[40820] | 0;
+ $cmp463 = $114 >>> 0 < $115 >>> 0;
+ if ($cmp463) {
+ label = 111;
+ break;
+ } else {
+ label = 110;
+ break;
+ }
+ case 110:
+ $arrayidx469 = $R331_1 + 20 | 0;
+ HEAP32[$arrayidx469 >> 2] = $113;
+ $parent470 = $113 + 24 | 0;
+ HEAP32[$parent470 >> 2] = $R331_1;
+ label = 113;
+ break;
+ case 111:
+ _abort();
+ case 112:
+ _abort();
+ case 113:
+ $or479 = $add266 | 1;
+ $head480 = $p_0 + 4 | 0;
+ HEAP32[$head480 >> 2] = $or479;
+ $add_ptr481 = $58 + $add266 | 0;
+ $prev_foot482 = $add_ptr481;
+ HEAP32[$prev_foot482 >> 2] = $add266;
+ $116 = HEAP32[40821] | 0;
+ $cmp483 = ($p_0 | 0) == ($116 | 0);
+ if ($cmp483) {
+ label = 114;
+ break;
+ } else {
+ $psize_1 = $add266;
+ label = 116;
+ break;
+ }
+ case 114:
+ HEAP32[40818] = $add266;
+ label = 142;
+ break;
+ case 115:
+ $and491 = $60 & -2;
+ HEAP32[$59 >> 2] = $and491;
+ $or492 = $psize_0 | 1;
+ $head493 = $p_0 + 4 | 0;
+ HEAP32[$head493 >> 2] = $or492;
+ $add_ptr494 = $58 + $psize_0 | 0;
+ $prev_foot495 = $add_ptr494;
+ HEAP32[$prev_foot495 >> 2] = $psize_0;
+ $psize_1 = $psize_0;
+ label = 116;
+ break;
+ case 116:
+ $shr497 = $psize_1 >>> 3;
+ $cmp498 = $psize_1 >>> 0 < 256;
+ if ($cmp498) {
+ label = 117;
+ break;
+ } else {
+ label = 122;
+ break;
+ }
+ case 117:
+ $shl504 = $shr497 << 1;
+ $arrayidx505 = 163304 + ($shl504 << 2) | 0;
+ $117 = $arrayidx505;
+ $118 = HEAP32[40816] | 0;
+ $shl507 = 1 << $shr497;
+ $and508 = $118 & $shl507;
+ $tobool509 = ($and508 | 0) == 0;
+ if ($tobool509) {
+ label = 118;
+ break;
+ } else {
+ label = 119;
+ break;
+ }
+ case 118:
+ $or512 = $118 | $shl507;
+ HEAP32[40816] = $or512;
+ $F506_0 = $117;
+ label = 121;
+ break;
+ case 119:
+ $arrayidx505_sum246 = $shl504 + 2 | 0;
+ $119 = 163304 + ($arrayidx505_sum246 << 2) | 0;
+ $120 = HEAP32[$119 >> 2] | 0;
+ $121 = $120;
+ $122 = HEAP32[40820] | 0;
+ $cmp515 = $121 >>> 0 < $122 >>> 0;
+ if ($cmp515) {
+ label = 120;
+ break;
+ } else {
+ $F506_0 = $120;
+ label = 121;
+ break;
+ }
+ case 120:
+ _abort();
+ case 121:
+ $arrayidx505_sum = $shl504 + 2 | 0;
+ $123 = 163304 + ($arrayidx505_sum << 2) | 0;
+ HEAP32[$123 >> 2] = $p_0;
+ $bk525 = $F506_0 + 12 | 0;
+ HEAP32[$bk525 >> 2] = $p_0;
+ $fd526 = $p_0 + 8 | 0;
+ HEAP32[$fd526 >> 2] = $F506_0;
+ $bk527 = $p_0 + 12 | 0;
+ HEAP32[$bk527 >> 2] = $117;
+ label = 142;
+ break;
+ case 122:
+ $124 = $p_0;
+ $shr531 = $psize_1 >>> 8;
+ $cmp532 = ($shr531 | 0) == 0;
+ if ($cmp532) {
+ $I530_0 = 0;
+ label = 125;
+ break;
+ } else {
+ label = 123;
+ break;
+ }
+ case 123:
+ $cmp536 = $psize_1 >>> 0 > 16777215;
+ if ($cmp536) {
+ $I530_0 = 31;
+ label = 125;
+ break;
+ } else {
+ label = 124;
+ break;
+ }
+ case 124:
+ $sub = $shr531 + 1048320 | 0;
+ $shr540 = $sub >>> 16;
+ $and541 = $shr540 & 8;
+ $shl542 = $shr531 << $and541;
+ $sub543 = $shl542 + 520192 | 0;
+ $shr544 = $sub543 >>> 16;
+ $and545 = $shr544 & 4;
+ $add546 = $and545 | $and541;
+ $shl547 = $shl542 << $and545;
+ $sub548 = $shl547 + 245760 | 0;
+ $shr549 = $sub548 >>> 16;
+ $and550 = $shr549 & 2;
+ $add551 = $add546 | $and550;
+ $sub552 = 14 - $add551 | 0;
+ $shl553 = $shl547 << $and550;
+ $shr554 = $shl553 >>> 15;
+ $add555 = $sub552 + $shr554 | 0;
+ $shl556 = $add555 << 1;
+ $add557 = $add555 + 7 | 0;
+ $shr558 = $psize_1 >>> ($add557 >>> 0);
+ $and559 = $shr558 & 1;
+ $add560 = $and559 | $shl556;
+ $I530_0 = $add560;
+ label = 125;
+ break;
+ case 125:
+ $arrayidx563 = 163568 + ($I530_0 << 2) | 0;
+ $index564 = $p_0 + 28 | 0;
+ $I530_0_c = $I530_0;
+ HEAP32[$index564 >> 2] = $I530_0_c;
+ $arrayidx566 = $p_0 + 20 | 0;
+ HEAP32[$arrayidx566 >> 2] = 0;
+ $125 = $p_0 + 16 | 0;
+ HEAP32[$125 >> 2] = 0;
+ $126 = HEAP32[40817] | 0;
+ $shl569 = 1 << $I530_0;
+ $and570 = $126 & $shl569;
+ $tobool571 = ($and570 | 0) == 0;
+ if ($tobool571) {
+ label = 126;
+ break;
+ } else {
+ label = 127;
+ break;
+ }
+ case 126:
+ $or574 = $126 | $shl569;
+ HEAP32[40817] = $or574;
+ HEAP32[$arrayidx563 >> 2] = $124;
+ $parent575 = $p_0 + 24 | 0;
+ $_c = $arrayidx563;
+ HEAP32[$parent575 >> 2] = $_c;
+ $bk576 = $p_0 + 12 | 0;
+ HEAP32[$bk576 >> 2] = $p_0;
+ $fd577 = $p_0 + 8 | 0;
+ HEAP32[$fd577 >> 2] = $p_0;
+ label = 139;
+ break;
+ case 127:
+ $127 = HEAP32[$arrayidx563 >> 2] | 0;
+ $cmp580 = ($I530_0 | 0) == 31;
+ if ($cmp580) {
+ $cond = 0;
+ label = 129;
+ break;
+ } else {
+ label = 128;
+ break;
+ }
+ case 128:
+ $shr582 = $I530_0 >>> 1;
+ $sub585 = 25 - $shr582 | 0;
+ $cond = $sub585;
+ label = 129;
+ break;
+ case 129:
+ $shl586 = $psize_1 << $cond;
+ $K579_0 = $shl586;
+ $T_0 = $127;
+ label = 130;
+ break;
+ case 130:
+ $head587 = $T_0 + 4 | 0;
+ $128 = HEAP32[$head587 >> 2] | 0;
+ $and588 = $128 & -8;
+ $cmp589 = ($and588 | 0) == ($psize_1 | 0);
+ if ($cmp589) {
+ label = 135;
+ break;
+ } else {
+ label = 131;
+ break;
+ }
+ case 131:
+ $shr592 = $K579_0 >>> 31;
+ $arrayidx595 = $T_0 + 16 + ($shr592 << 2) | 0;
+ $129 = HEAP32[$arrayidx595 >> 2] | 0;
+ $cmp597 = ($129 | 0) == 0;
+ $shl596 = $K579_0 << 1;
+ if ($cmp597) {
+ label = 132;
+ break;
+ } else {
+ $K579_0 = $shl596;
+ $T_0 = $129;
+ label = 130;
+ break;
+ }
+ case 132:
+ $130 = $arrayidx595;
+ $131 = HEAP32[40820] | 0;
+ $cmp601 = $130 >>> 0 < $131 >>> 0;
+ if ($cmp601) {
+ label = 134;
+ break;
+ } else {
+ label = 133;
+ break;
+ }
+ case 133:
+ HEAP32[$arrayidx595 >> 2] = $124;
+ $parent606 = $p_0 + 24 | 0;
+ $T_0_c243 = $T_0;
+ HEAP32[$parent606 >> 2] = $T_0_c243;
+ $bk607 = $p_0 + 12 | 0;
+ HEAP32[$bk607 >> 2] = $p_0;
+ $fd608 = $p_0 + 8 | 0;
+ HEAP32[$fd608 >> 2] = $p_0;
+ label = 139;
+ break;
+ case 134:
+ _abort();
+ case 135:
+ $fd613 = $T_0 + 8 | 0;
+ $132 = HEAP32[$fd613 >> 2] | 0;
+ $133 = $T_0;
+ $134 = HEAP32[40820] | 0;
+ $cmp614 = $133 >>> 0 < $134 >>> 0;
+ if ($cmp614) {
+ label = 138;
+ break;
+ } else {
+ label = 136;
+ break;
+ }
+ case 136:
+ $135 = $132;
+ $cmp617 = $135 >>> 0 < $134 >>> 0;
+ if ($cmp617) {
+ label = 138;
+ break;
+ } else {
+ label = 137;
+ break;
+ }
+ case 137:
+ $bk624 = $132 + 12 | 0;
+ HEAP32[$bk624 >> 2] = $124;
+ HEAP32[$fd613 >> 2] = $124;
+ $fd626 = $p_0 + 8 | 0;
+ $_c242 = $132;
+ HEAP32[$fd626 >> 2] = $_c242;
+ $bk627 = $p_0 + 12 | 0;
+ $T_0_c = $T_0;
+ HEAP32[$bk627 >> 2] = $T_0_c;
+ $parent628 = $p_0 + 24 | 0;
+ HEAP32[$parent628 >> 2] = 0;
+ label = 139;
+ break;
+ case 138:
+ _abort();
+ case 139:
+ $136 = HEAP32[40824] | 0;
+ $dec = $136 - 1 | 0;
+ HEAP32[40824] = $dec;
+ $cmp632 = ($dec | 0) == 0;
+ if ($cmp632) {
+ label = 140;
+ break;
+ } else {
+ label = 142;
+ break;
+ }
+ case 140:
+ _release_unused_segments();
+ label = 142;
+ break;
+ case 141:
+ _abort();
+ case 142:
+ return;
+ }
+}
+function _release_unused_segments() {
+ var $sp_0_in = 0, $sp_0 = 0, $cmp = 0, $next4 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sp_0_in = 163720;
+ label = 3;
+ break;
+ case 3:
+ $sp_0 = HEAP32[$sp_0_in >> 2] | 0;
+ $cmp = ($sp_0 | 0) == 0;
+ $next4 = $sp_0 + 8 | 0;
+ if ($cmp) {
+ label = 4;
+ break;
+ } else {
+ $sp_0_in = $next4;
+ label = 3;
+ break;
+ }
+ case 4:
+ HEAP32[40824] = -1;
+ return;
+ }
+}
+function _sys_trim($pad) {
+ $pad = $pad | 0;
+ var $0 = 0, $cmp = 0, $cmp1 = 0, $1 = 0, $cmp2 = 0, $add = 0, $2 = 0, $cmp3 = 0, $3 = 0, $add_neg = 0, $sub6 = 0, $sub = 0, $add7 = 0, $div = 0, $sub8 = 0, $mul = 0, $4 = 0, $call10 = 0, $sflags = 0, $5 = 0, $and = 0, $tobool11 = 0, $call20 = 0, $base = 0, $6 = 0, $size = 0, $7 = 0, $add_ptr = 0, $cmp21 = 0, $sub19 = 0, $cmp17 = 0, $sub19_mul = 0, $sub23 = 0, $call24 = 0, $call25 = 0, $cmp26 = 0, $cmp28 = 0, $or_cond = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $cmp34 = 0, $size36 = 0, $8 = 0, $sub37 = 0, $9 = 0, $sub38 = 0, $10 = 0, $11 = 0, $sub41 = 0, $phitmp = 0, $phitmp4 = 0, $12 = 0, $13 = 0, $cmp47 = 0, $released_2 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[2802] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ _init_mparams();
+ label = 4;
+ break;
+ case 4:
+ $cmp1 = $pad >>> 0 < 4294967232;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ $released_2 = 0;
+ label = 14;
+ break;
+ }
+ case 5:
+ $1 = HEAP32[40822] | 0;
+ $cmp2 = ($1 | 0) == 0;
+ if ($cmp2) {
+ $released_2 = 0;
+ label = 14;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $add = $pad + 40 | 0;
+ $2 = HEAP32[40819] | 0;
+ $cmp3 = $2 >>> 0 > $add >>> 0;
+ if ($cmp3) {
+ label = 7;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 7:
+ $3 = HEAP32[2804] | 0;
+ $add_neg = -40 - $pad | 0;
+ $sub6 = $add_neg - 1 | 0;
+ $sub = $sub6 + $2 | 0;
+ $add7 = $sub + $3 | 0;
+ $div = ($add7 >>> 0) / ($3 >>> 0) >>> 0;
+ $sub8 = $div - 1 | 0;
+ $mul = Math_imul($sub8, $3);
+ $4 = $1;
+ $call10 = _segment_holding($4) | 0;
+ $sflags = $call10 + 12 | 0;
+ $5 = HEAP32[$sflags >> 2] | 0;
+ $and = $5 & 8;
+ $tobool11 = ($and | 0) == 0;
+ if ($tobool11) {
+ label = 8;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 8:
+ $call20 = _sbrk(0) | 0;
+ $base = $call10 | 0;
+ $6 = HEAP32[$base >> 2] | 0;
+ $size = $call10 + 4 | 0;
+ $7 = HEAP32[$size >> 2] | 0;
+ $add_ptr = $6 + $7 | 0;
+ $cmp21 = ($call20 | 0) == ($add_ptr | 0);
+ if ($cmp21) {
+ label = 9;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 9:
+ $sub19 = -2147483648 - $3 | 0;
+ $cmp17 = $mul >>> 0 > 2147483646;
+ $sub19_mul = $cmp17 ? $sub19 : $mul;
+ $sub23 = -$sub19_mul | 0;
+ $call24 = _sbrk($sub23 | 0) | 0;
+ $call25 = _sbrk(0) | 0;
+ $cmp26 = ($call24 | 0) != -1;
+ $cmp28 = $call25 >>> 0 < $call20 >>> 0;
+ $or_cond = $cmp26 & $cmp28;
+ if ($or_cond) {
+ label = 10;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 10:
+ $sub_ptr_lhs_cast = $call20;
+ $sub_ptr_rhs_cast = $call25;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $cmp34 = ($call20 | 0) == ($call25 | 0);
+ if ($cmp34) {
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $size36 = $call10 + 4 | 0;
+ $8 = HEAP32[$size36 >> 2] | 0;
+ $sub37 = $8 - $sub_ptr_sub | 0;
+ HEAP32[$size36 >> 2] = $sub37;
+ $9 = HEAP32[40924] | 0;
+ $sub38 = $9 - $sub_ptr_sub | 0;
+ HEAP32[40924] = $sub38;
+ $10 = HEAP32[40822] | 0;
+ $11 = HEAP32[40819] | 0;
+ $sub41 = $11 - $sub_ptr_sub | 0;
+ _init_top($10, $sub41);
+ $phitmp = ($call20 | 0) != ($call25 | 0);
+ $phitmp4 = $phitmp & 1;
+ $released_2 = $phitmp4;
+ label = 14;
+ break;
+ case 12:
+ $12 = HEAP32[40819] | 0;
+ $13 = HEAP32[40823] | 0;
+ $cmp47 = $12 >>> 0 > $13 >>> 0;
+ if ($cmp47) {
+ label = 13;
+ break;
+ } else {
+ $released_2 = 0;
+ label = 14;
+ break;
+ }
+ case 13:
+ HEAP32[40823] = -1;
+ $released_2 = 0;
+ label = 14;
+ break;
+ case 14:
+ return $released_2 | 0;
+ }
+ return 0;
+}
+function _calloc($n_elements, $elem_size) {
+ $n_elements = $n_elements | 0;
+ $elem_size = $elem_size | 0;
+ var $cmp = 0, $mul = 0, $or = 0, $tobool = 0, $div = 0, $cmp1 = 0, $mul_ = 0, $req_0 = 0, $call = 0, $cmp4 = 0, $head = 0, $0 = 0, $1 = 0, $and6 = 0, $cmp7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($n_elements | 0) == 0;
+ if ($cmp) {
+ $req_0 = 0;
+ label = 5;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $mul = Math_imul($elem_size, $n_elements);
+ $or = $elem_size | $n_elements;
+ $tobool = $or >>> 0 > 65535;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $req_0 = $mul;
+ label = 5;
+ break;
+ }
+ case 4:
+ $div = ($mul >>> 0) / ($n_elements >>> 0) >>> 0;
+ $cmp1 = ($div | 0) == ($elem_size | 0);
+ $mul_ = $cmp1 ? $mul : -1;
+ $req_0 = $mul_;
+ label = 5;
+ break;
+ case 5:
+ $call = _malloc($req_0) | 0;
+ $cmp4 = ($call | 0) == 0;
+ if ($cmp4) {
+ label = 8;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $head = $call - 4 | 0;
+ $0 = $head;
+ $1 = HEAP32[$0 >> 2] | 0;
+ $and6 = $1 & 3;
+ $cmp7 = ($and6 | 0) == 0;
+ if ($cmp7) {
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ _memset($call | 0, 0, $req_0 | 0);
+ label = 8;
+ break;
+ case 8:
+ return $call | 0;
+ }
+ return 0;
+}
+function _realloc($oldmem, $bytes) {
+ $oldmem = $oldmem | 0;
+ $bytes = $bytes | 0;
+ var $cmp = 0, $call = 0, $cmp1 = 0, $call3 = 0, $cmp5 = 0, $add6 = 0, $and = 0, $cond = 0, $add_ptr = 0, $0 = 0, $call7 = 0, $cmp8 = 0, $add_ptr10 = 0, $1 = 0, $call12 = 0, $cmp13 = 0, $head = 0, $2 = 0, $3 = 0, $and15 = 0, $and17 = 0, $cmp18 = 0, $cond19 = 0, $sub = 0, $cmp20 = 0, $cond24 = 0, $mem_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $cmp = ($oldmem | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 3:
+ $call = _malloc($bytes) | 0;
+ $mem_0 = $call;
+ label = 12;
+ break;
+ case 4:
+ $cmp1 = $bytes >>> 0 > 4294967231;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $call3 = ___errno_location() | 0;
+ HEAP32[$call3 >> 2] = 12;
+ $mem_0 = 0;
+ label = 12;
+ break;
+ case 6:
+ $cmp5 = $bytes >>> 0 < 11;
+ if ($cmp5) {
+ $cond = 16;
+ label = 8;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $add6 = $bytes + 11 | 0;
+ $and = $add6 & -8;
+ $cond = $and;
+ label = 8;
+ break;
+ case 8:
+ $add_ptr = $oldmem - 8 | 0;
+ $0 = $add_ptr;
+ $call7 = _try_realloc_chunk($0, $cond) | 0;
+ $cmp8 = ($call7 | 0) == 0;
+ if ($cmp8) {
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $add_ptr10 = $call7 + 8 | 0;
+ $1 = $add_ptr10;
+ $mem_0 = $1;
+ label = 12;
+ break;
+ case 10:
+ $call12 = _malloc($bytes) | 0;
+ $cmp13 = ($call12 | 0) == 0;
+ if ($cmp13) {
+ $mem_0 = 0;
+ label = 12;
+ break;
+ } else {
+ label = 11;
+ break;
+ }
+ case 11:
+ $head = $oldmem - 4 | 0;
+ $2 = $head;
+ $3 = HEAP32[$2 >> 2] | 0;
+ $and15 = $3 & -8;
+ $and17 = $3 & 3;
+ $cmp18 = ($and17 | 0) == 0;
+ $cond19 = $cmp18 ? 8 : 4;
+ $sub = $and15 - $cond19 | 0;
+ $cmp20 = $sub >>> 0 < $bytes >>> 0;
+ $cond24 = $cmp20 ? $sub : $bytes;
+ _memcpy($call12 | 0, $oldmem | 0, $cond24);
+ _free($oldmem);
+ $mem_0 = $call12;
+ label = 12;
+ break;
+ case 12:
+ return $mem_0 | 0;
+ }
+ return 0;
+}
+function _try_realloc_chunk($p, $nb) {
+ $p = $p | 0;
+ $nb = $nb | 0;
+ var $head = 0, $0 = 0, $and = 0, $1 = 0, $add_ptr = 0, $2 = 0, $3 = 0, $cmp = 0, $and2 = 0, $cmp3 = 0, $cmp5 = 0, $or_cond = 0, $add_ptr_sum2122 = 0, $head6 = 0, $4 = 0, $5 = 0, $and7 = 0, $phitmp = 0, $cmp11 = 0, $call = 0, $cmp13 = 0, $sub = 0, $cmp15 = 0, $add_ptr17 = 0, $6 = 0, $and19 = 0, $or = 0, $or20 = 0, $add_ptr17_sum = 0, $head23 = 0, $7 = 0, $or28 = 0, $8 = 0, $or32 = 0, $9 = 0, $cmp34 = 0, $10 = 0, $add = 0, $cmp36 = 0, $sub40 = 0, $add_ptr41 = 0, $11 = 0, $and43 = 0, $or44 = 0, $or45 = 0, $add_ptr41_sum = 0, $head48 = 0, $12 = 0, $or50 = 0, $13 = 0, $cmp56 = 0, $14 = 0, $add58 = 0, $cmp59 = 0, $sub62 = 0, $cmp63 = 0, $add_ptr66 = 0, $15 = 0, $add_ptr67 = 0, $and69 = 0, $or70 = 0, $or71 = 0, $add_ptr66_sum = 0, $head74 = 0, $16 = 0, $or76 = 0, $prev_foot = 0, $add_ptr67_sum = 0, $head79 = 0, $17 = 0, $18 = 0, $and80 = 0, $and87 = 0, $or88 = 0, $or89 = 0, $add_ptr91_sum = 0, $head92 = 0, $19 = 0, $20 = 0, $or93 = 0, $storemerge18 = 0, $storemerge = 0, $and100 = 0, $tobool101 = 0, $and104 = 0, $add105 = 0, $cmp106 = 0, $sub110 = 0, $shr = 0, $cmp111 = 0, $add_ptr_sum12 = 0, $fd = 0, $21 = 0, $22 = 0, $add_ptr_sum13 = 0, $bk = 0, $23 = 0, $24 = 0, $shl = 0, $arrayidx = 0, $25 = 0, $cmp114 = 0, $26 = 0, $cmp116 = 0, $bk118 = 0, $27 = 0, $cmp119 = 0, $cmp125 = 0, $shl127 = 0, $neg = 0, $28 = 0, $and128 = 0, $cmp133 = 0, $29 = 0, $30 = 0, $cmp136 = 0, $fd138 = 0, $31 = 0, $cmp139 = 0, $bk147 = 0, $fd148 = 0, $32 = 0, $add_ptr_sum = 0, $parent = 0, $33 = 0, $34 = 0, $add_ptr_sum2 = 0, $bk155 = 0, $35 = 0, $36 = 0, $cmp156 = 0, $add_ptr_sum9 = 0, $fd159 = 0, $37 = 0, $38 = 0, $39 = 0, $cmp162 = 0, $bk164 = 0, $40 = 0, $cmp165 = 0, $fd167 = 0, $41 = 0, $cmp168 = 0, $child_sum = 0, $arrayidx179 = 0, $42 = 0, $43 = 0, $cmp180 = 0, $add_ptr_sum3 = 0, $child = 0, $arrayidx182 = 0, $44 = 0, $cmp183 = 0, $RP_0 = 0, $R_0 = 0, $arrayidx186 = 0, $45 = 0, $cmp187 = 0, $arrayidx190 = 0, $46 = 0, $cmp191 = 0, $CP_0 = 0, $47 = 0, $48 = 0, $49 = 0, $cmp195 = 0, $R_1 = 0, $cmp203 = 0, $add_ptr_sum7 = 0, $index = 0, $50 = 0, $51 = 0, $arrayidx206 = 0, $52 = 0, $cmp207 = 0, $cond = 0, $53 = 0, $shl214 = 0, $neg215 = 0, $54 = 0, $and216 = 0, $55 = 0, $56 = 0, $cmp220 = 0, $arrayidx226 = 0, $57 = 0, $cmp227 = 0, $arrayidx234 = 0, $cmp239 = 0, $58 = 0, $59 = 0, $cmp243 = 0, $parent248 = 0, $add_ptr_sum8 = 0, $child249 = 0, $arrayidx250 = 0, $60 = 0, $cmp251 = 0, $61 = 0, $62 = 0, $cmp255 = 0, $arrayidx261 = 0, $parent262 = 0, $child249_sum = 0, $arrayidx267 = 0, $63 = 0, $64 = 0, $cmp268 = 0, $65 = 0, $66 = 0, $cmp272 = 0, $arrayidx278 = 0, $parent279 = 0, $cmp288 = 0, $67 = 0, $and294 = 0, $or295 = 0, $or296 = 0, $add_ptr298_sum6 = 0, $head299 = 0, $68 = 0, $69 = 0, $or300 = 0, $add_ptr303 = 0, $70 = 0, $71 = 0, $and305 = 0, $or306 = 0, $or307 = 0, $add_ptr303_sum = 0, $head310 = 0, $72 = 0, $or315 = 0, $add_ptr317_sum5 = 0, $head318 = 0, $73 = 0, $74 = 0, $or319 = 0, $newp_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $head = $p + 4 | 0;
+ $0 = HEAP32[$head >> 2] | 0;
+ $and = $0 & -8;
+ $1 = $p;
+ $add_ptr = $1 + $and | 0;
+ $2 = $add_ptr;
+ $3 = HEAP32[40820] | 0;
+ $cmp = $1 >>> 0 < $3 >>> 0;
+ if ($cmp) {
+ label = 70;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $and2 = $0 & 3;
+ $cmp3 = ($and2 | 0) != 1;
+ $cmp5 = $1 >>> 0 < $add_ptr >>> 0;
+ $or_cond = $cmp3 & $cmp5;
+ if ($or_cond) {
+ label = 4;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 4:
+ $add_ptr_sum2122 = $and | 4;
+ $head6 = $1 + $add_ptr_sum2122 | 0;
+ $4 = $head6;
+ $5 = HEAP32[$4 >> 2] | 0;
+ $and7 = $5 & 1;
+ $phitmp = ($and7 | 0) == 0;
+ if ($phitmp) {
+ label = 70;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $cmp11 = ($and2 | 0) == 0;
+ if ($cmp11) {
+ label = 6;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 6:
+ $call = _mmap_resize($p, $nb) | 0;
+ $newp_0 = $call;
+ label = 71;
+ break;
+ case 7:
+ $cmp13 = $and >>> 0 < $nb >>> 0;
+ if ($cmp13) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $sub = $and - $nb | 0;
+ $cmp15 = $sub >>> 0 > 15;
+ if ($cmp15) {
+ label = 9;
+ break;
+ } else {
+ $newp_0 = $p;
+ label = 71;
+ break;
+ }
+ case 9:
+ $add_ptr17 = $1 + $nb | 0;
+ $6 = $add_ptr17;
+ $and19 = $0 & 1;
+ $or = $and19 | $nb;
+ $or20 = $or | 2;
+ HEAP32[$head >> 2] = $or20;
+ $add_ptr17_sum = $nb + 4 | 0;
+ $head23 = $1 + $add_ptr17_sum | 0;
+ $7 = $head23;
+ $or28 = $sub | 3;
+ HEAP32[$7 >> 2] = $or28;
+ $8 = HEAP32[$4 >> 2] | 0;
+ $or32 = $8 | 1;
+ HEAP32[$4 >> 2] = $or32;
+ _dispose_chunk($6, $sub);
+ $newp_0 = $p;
+ label = 71;
+ break;
+ case 10:
+ $9 = HEAP32[40822] | 0;
+ $cmp34 = ($2 | 0) == ($9 | 0);
+ if ($cmp34) {
+ label = 11;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 11:
+ $10 = HEAP32[40819] | 0;
+ $add = $10 + $and | 0;
+ $cmp36 = $add >>> 0 > $nb >>> 0;
+ if ($cmp36) {
+ label = 12;
+ break;
+ } else {
+ $newp_0 = 0;
+ label = 71;
+ break;
+ }
+ case 12:
+ $sub40 = $add - $nb | 0;
+ $add_ptr41 = $1 + $nb | 0;
+ $11 = $add_ptr41;
+ $and43 = $0 & 1;
+ $or44 = $and43 | $nb;
+ $or45 = $or44 | 2;
+ HEAP32[$head >> 2] = $or45;
+ $add_ptr41_sum = $nb + 4 | 0;
+ $head48 = $1 + $add_ptr41_sum | 0;
+ $12 = $head48;
+ $or50 = $sub40 | 1;
+ HEAP32[$12 >> 2] = $or50;
+ HEAP32[40822] = $11;
+ HEAP32[40819] = $sub40;
+ $newp_0 = $p;
+ label = 71;
+ break;
+ case 13:
+ $13 = HEAP32[40821] | 0;
+ $cmp56 = ($2 | 0) == ($13 | 0);
+ if ($cmp56) {
+ label = 14;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 14:
+ $14 = HEAP32[40818] | 0;
+ $add58 = $14 + $and | 0;
+ $cmp59 = $add58 >>> 0 < $nb >>> 0;
+ if ($cmp59) {
+ $newp_0 = 0;
+ label = 71;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $sub62 = $add58 - $nb | 0;
+ $cmp63 = $sub62 >>> 0 > 15;
+ if ($cmp63) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $add_ptr66 = $1 + $nb | 0;
+ $15 = $add_ptr66;
+ $add_ptr67 = $1 + $add58 | 0;
+ $and69 = $0 & 1;
+ $or70 = $and69 | $nb;
+ $or71 = $or70 | 2;
+ HEAP32[$head >> 2] = $or71;
+ $add_ptr66_sum = $nb + 4 | 0;
+ $head74 = $1 + $add_ptr66_sum | 0;
+ $16 = $head74;
+ $or76 = $sub62 | 1;
+ HEAP32[$16 >> 2] = $or76;
+ $prev_foot = $add_ptr67;
+ HEAP32[$prev_foot >> 2] = $sub62;
+ $add_ptr67_sum = $add58 + 4 | 0;
+ $head79 = $1 + $add_ptr67_sum | 0;
+ $17 = $head79;
+ $18 = HEAP32[$17 >> 2] | 0;
+ $and80 = $18 & -2;
+ HEAP32[$17 >> 2] = $and80;
+ $storemerge = $15;
+ $storemerge18 = $sub62;
+ label = 18;
+ break;
+ case 17:
+ $and87 = $0 & 1;
+ $or88 = $and87 | $add58;
+ $or89 = $or88 | 2;
+ HEAP32[$head >> 2] = $or89;
+ $add_ptr91_sum = $add58 + 4 | 0;
+ $head92 = $1 + $add_ptr91_sum | 0;
+ $19 = $head92;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $or93 = $20 | 1;
+ HEAP32[$19 >> 2] = $or93;
+ $storemerge = 0;
+ $storemerge18 = 0;
+ label = 18;
+ break;
+ case 18:
+ HEAP32[40818] = $storemerge18;
+ HEAP32[40821] = $storemerge;
+ $newp_0 = $p;
+ label = 71;
+ break;
+ case 19:
+ $and100 = $5 & 2;
+ $tobool101 = ($and100 | 0) == 0;
+ if ($tobool101) {
+ label = 20;
+ break;
+ } else {
+ $newp_0 = 0;
+ label = 71;
+ break;
+ }
+ case 20:
+ $and104 = $5 & -8;
+ $add105 = $and104 + $and | 0;
+ $cmp106 = $add105 >>> 0 < $nb >>> 0;
+ if ($cmp106) {
+ $newp_0 = 0;
+ label = 71;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 21:
+ $sub110 = $add105 - $nb | 0;
+ $shr = $5 >>> 3;
+ $cmp111 = $5 >>> 0 < 256;
+ if ($cmp111) {
+ label = 22;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 22:
+ $add_ptr_sum12 = $and + 8 | 0;
+ $fd = $1 + $add_ptr_sum12 | 0;
+ $21 = $fd;
+ $22 = HEAP32[$21 >> 2] | 0;
+ $add_ptr_sum13 = $and + 12 | 0;
+ $bk = $1 + $add_ptr_sum13 | 0;
+ $23 = $bk;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $shl = $shr << 1;
+ $arrayidx = 163304 + ($shl << 2) | 0;
+ $25 = $arrayidx;
+ $cmp114 = ($22 | 0) == ($25 | 0);
+ if ($cmp114) {
+ label = 25;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 23:
+ $26 = $22;
+ $cmp116 = $26 >>> 0 < $3 >>> 0;
+ if ($cmp116) {
+ label = 32;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $bk118 = $22 + 12 | 0;
+ $27 = HEAP32[$bk118 >> 2] | 0;
+ $cmp119 = ($27 | 0) == ($2 | 0);
+ if ($cmp119) {
+ label = 25;
+ break;
+ } else {
+ label = 32;
+ break;
+ }
+ case 25:
+ $cmp125 = ($24 | 0) == ($22 | 0);
+ if ($cmp125) {
+ label = 26;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 26:
+ $shl127 = 1 << $shr;
+ $neg = $shl127 ^ -1;
+ $28 = HEAP32[40816] | 0;
+ $and128 = $28 & $neg;
+ HEAP32[40816] = $and128;
+ label = 67;
+ break;
+ case 27:
+ $cmp133 = ($24 | 0) == ($25 | 0);
+ if ($cmp133) {
+ label = 30;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $29 = $24;
+ $30 = HEAP32[40820] | 0;
+ $cmp136 = $29 >>> 0 < $30 >>> 0;
+ if ($cmp136) {
+ label = 31;
+ break;
+ } else {
+ label = 29;
+ break;
+ }
+ case 29:
+ $fd138 = $24 + 8 | 0;
+ $31 = HEAP32[$fd138 >> 2] | 0;
+ $cmp139 = ($31 | 0) == ($2 | 0);
+ if ($cmp139) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $bk147 = $22 + 12 | 0;
+ HEAP32[$bk147 >> 2] = $24;
+ $fd148 = $24 + 8 | 0;
+ HEAP32[$fd148 >> 2] = $22;
+ label = 67;
+ break;
+ case 31:
+ _abort();
+ return 0;
+ return 0;
+ case 32:
+ _abort();
+ return 0;
+ return 0;
+ case 33:
+ $32 = $add_ptr;
+ $add_ptr_sum = $and + 24 | 0;
+ $parent = $1 + $add_ptr_sum | 0;
+ $33 = $parent;
+ $34 = HEAP32[$33 >> 2] | 0;
+ $add_ptr_sum2 = $and + 12 | 0;
+ $bk155 = $1 + $add_ptr_sum2 | 0;
+ $35 = $bk155;
+ $36 = HEAP32[$35 >> 2] | 0;
+ $cmp156 = ($36 | 0) == ($32 | 0);
+ if ($cmp156) {
+ label = 39;
+ break;
+ } else {
+ label = 34;
+ break;
+ }
+ case 34:
+ $add_ptr_sum9 = $and + 8 | 0;
+ $fd159 = $1 + $add_ptr_sum9 | 0;
+ $37 = $fd159;
+ $38 = HEAP32[$37 >> 2] | 0;
+ $39 = $38;
+ $cmp162 = $39 >>> 0 < $3 >>> 0;
+ if ($cmp162) {
+ label = 38;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ $bk164 = $38 + 12 | 0;
+ $40 = HEAP32[$bk164 >> 2] | 0;
+ $cmp165 = ($40 | 0) == ($32 | 0);
+ if ($cmp165) {
+ label = 36;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 36:
+ $fd167 = $36 + 8 | 0;
+ $41 = HEAP32[$fd167 >> 2] | 0;
+ $cmp168 = ($41 | 0) == ($32 | 0);
+ if ($cmp168) {
+ label = 37;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 37:
+ HEAP32[$bk164 >> 2] = $36;
+ HEAP32[$fd167 >> 2] = $38;
+ $R_1 = $36;
+ label = 47;
+ break;
+ case 38:
+ _abort();
+ return 0;
+ return 0;
+ case 39:
+ $child_sum = $and + 20 | 0;
+ $arrayidx179 = $1 + $child_sum | 0;
+ $42 = $arrayidx179;
+ $43 = HEAP32[$42 >> 2] | 0;
+ $cmp180 = ($43 | 0) == 0;
+ if ($cmp180) {
+ label = 40;
+ break;
+ } else {
+ $R_0 = $43;
+ $RP_0 = $42;
+ label = 41;
+ break;
+ }
+ case 40:
+ $add_ptr_sum3 = $and + 16 | 0;
+ $child = $1 + $add_ptr_sum3 | 0;
+ $arrayidx182 = $child;
+ $44 = HEAP32[$arrayidx182 >> 2] | 0;
+ $cmp183 = ($44 | 0) == 0;
+ if ($cmp183) {
+ $R_1 = 0;
+ label = 47;
+ break;
+ } else {
+ $R_0 = $44;
+ $RP_0 = $arrayidx182;
+ label = 41;
+ break;
+ }
+ case 41:
+ $arrayidx186 = $R_0 + 20 | 0;
+ $45 = HEAP32[$arrayidx186 >> 2] | 0;
+ $cmp187 = ($45 | 0) == 0;
+ if ($cmp187) {
+ label = 42;
+ break;
+ } else {
+ $CP_0 = $arrayidx186;
+ label = 43;
+ break;
+ }
+ case 42:
+ $arrayidx190 = $R_0 + 16 | 0;
+ $46 = HEAP32[$arrayidx190 >> 2] | 0;
+ $cmp191 = ($46 | 0) == 0;
+ if ($cmp191) {
+ label = 44;
+ break;
+ } else {
+ $CP_0 = $arrayidx190;
+ label = 43;
+ break;
+ }
+ case 43:
+ $47 = HEAP32[$CP_0 >> 2] | 0;
+ $R_0 = $47;
+ $RP_0 = $CP_0;
+ label = 41;
+ break;
+ case 44:
+ $48 = $RP_0;
+ $49 = HEAP32[40820] | 0;
+ $cmp195 = $48 >>> 0 < $49 >>> 0;
+ if ($cmp195) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ HEAP32[$RP_0 >> 2] = 0;
+ $R_1 = $R_0;
+ label = 47;
+ break;
+ case 46:
+ _abort();
+ return 0;
+ return 0;
+ case 47:
+ $cmp203 = ($34 | 0) == 0;
+ if ($cmp203) {
+ label = 67;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $add_ptr_sum7 = $and + 28 | 0;
+ $index = $1 + $add_ptr_sum7 | 0;
+ $50 = $index;
+ $51 = HEAP32[$50 >> 2] | 0;
+ $arrayidx206 = 163568 + ($51 << 2) | 0;
+ $52 = HEAP32[$arrayidx206 >> 2] | 0;
+ $cmp207 = ($32 | 0) == ($52 | 0);
+ if ($cmp207) {
+ label = 49;
+ break;
+ } else {
+ label = 51;
+ break;
+ }
+ case 49:
+ HEAP32[$arrayidx206 >> 2] = $R_1;
+ $cond = ($R_1 | 0) == 0;
+ if ($cond) {
+ label = 50;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 50:
+ $53 = HEAP32[$50 >> 2] | 0;
+ $shl214 = 1 << $53;
+ $neg215 = $shl214 ^ -1;
+ $54 = HEAP32[40817] | 0;
+ $and216 = $54 & $neg215;
+ HEAP32[40817] = $and216;
+ label = 67;
+ break;
+ case 51:
+ $55 = $34;
+ $56 = HEAP32[40820] | 0;
+ $cmp220 = $55 >>> 0 < $56 >>> 0;
+ if ($cmp220) {
+ label = 55;
+ break;
+ } else {
+ label = 52;
+ break;
+ }
+ case 52:
+ $arrayidx226 = $34 + 16 | 0;
+ $57 = HEAP32[$arrayidx226 >> 2] | 0;
+ $cmp227 = ($57 | 0) == ($32 | 0);
+ if ($cmp227) {
+ label = 53;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 53:
+ HEAP32[$arrayidx226 >> 2] = $R_1;
+ label = 56;
+ break;
+ case 54:
+ $arrayidx234 = $34 + 20 | 0;
+ HEAP32[$arrayidx234 >> 2] = $R_1;
+ label = 56;
+ break;
+ case 55:
+ _abort();
+ return 0;
+ return 0;
+ case 56:
+ $cmp239 = ($R_1 | 0) == 0;
+ if ($cmp239) {
+ label = 67;
+ break;
+ } else {
+ label = 57;
+ break;
+ }
+ case 57:
+ $58 = $R_1;
+ $59 = HEAP32[40820] | 0;
+ $cmp243 = $58 >>> 0 < $59 >>> 0;
+ if ($cmp243) {
+ label = 66;
+ break;
+ } else {
+ label = 58;
+ break;
+ }
+ case 58:
+ $parent248 = $R_1 + 24 | 0;
+ HEAP32[$parent248 >> 2] = $34;
+ $add_ptr_sum8 = $and + 16 | 0;
+ $child249 = $1 + $add_ptr_sum8 | 0;
+ $arrayidx250 = $child249;
+ $60 = HEAP32[$arrayidx250 >> 2] | 0;
+ $cmp251 = ($60 | 0) == 0;
+ if ($cmp251) {
+ label = 62;
+ break;
+ } else {
+ label = 59;
+ break;
+ }
+ case 59:
+ $61 = $60;
+ $62 = HEAP32[40820] | 0;
+ $cmp255 = $61 >>> 0 < $62 >>> 0;
+ if ($cmp255) {
+ label = 61;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 60:
+ $arrayidx261 = $R_1 + 16 | 0;
+ HEAP32[$arrayidx261 >> 2] = $60;
+ $parent262 = $60 + 24 | 0;
+ HEAP32[$parent262 >> 2] = $R_1;
+ label = 62;
+ break;
+ case 61:
+ _abort();
+ return 0;
+ return 0;
+ case 62:
+ $child249_sum = $and + 20 | 0;
+ $arrayidx267 = $1 + $child249_sum | 0;
+ $63 = $arrayidx267;
+ $64 = HEAP32[$63 >> 2] | 0;
+ $cmp268 = ($64 | 0) == 0;
+ if ($cmp268) {
+ label = 67;
+ break;
+ } else {
+ label = 63;
+ break;
+ }
+ case 63:
+ $65 = $64;
+ $66 = HEAP32[40820] | 0;
+ $cmp272 = $65 >>> 0 < $66 >>> 0;
+ if ($cmp272) {
+ label = 65;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 64:
+ $arrayidx278 = $R_1 + 20 | 0;
+ HEAP32[$arrayidx278 >> 2] = $64;
+ $parent279 = $64 + 24 | 0;
+ HEAP32[$parent279 >> 2] = $R_1;
+ label = 67;
+ break;
+ case 65:
+ _abort();
+ return 0;
+ return 0;
+ case 66:
+ _abort();
+ return 0;
+ return 0;
+ case 67:
+ $cmp288 = $sub110 >>> 0 < 16;
+ if ($cmp288) {
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 68:
+ $67 = HEAP32[$head >> 2] | 0;
+ $and294 = $67 & 1;
+ $or295 = $add105 | $and294;
+ $or296 = $or295 | 2;
+ HEAP32[$head >> 2] = $or296;
+ $add_ptr298_sum6 = $add105 | 4;
+ $head299 = $1 + $add_ptr298_sum6 | 0;
+ $68 = $head299;
+ $69 = HEAP32[$68 >> 2] | 0;
+ $or300 = $69 | 1;
+ HEAP32[$68 >> 2] = $or300;
+ $newp_0 = $p;
+ label = 71;
+ break;
+ case 69:
+ $add_ptr303 = $1 + $nb | 0;
+ $70 = $add_ptr303;
+ $71 = HEAP32[$head >> 2] | 0;
+ $and305 = $71 & 1;
+ $or306 = $and305 | $nb;
+ $or307 = $or306 | 2;
+ HEAP32[$head >> 2] = $or307;
+ $add_ptr303_sum = $nb + 4 | 0;
+ $head310 = $1 + $add_ptr303_sum | 0;
+ $72 = $head310;
+ $or315 = $sub110 | 3;
+ HEAP32[$72 >> 2] = $or315;
+ $add_ptr317_sum5 = $add105 | 4;
+ $head318 = $1 + $add_ptr317_sum5 | 0;
+ $73 = $head318;
+ $74 = HEAP32[$73 >> 2] | 0;
+ $or319 = $74 | 1;
+ HEAP32[$73 >> 2] = $or319;
+ _dispose_chunk($70, $sub110);
+ $newp_0 = $p;
+ label = 71;
+ break;
+ case 70:
+ _abort();
+ return 0;
+ return 0;
+ case 71:
+ return $newp_0 | 0;
+ }
+ return 0;
+}
+function _init_mparams() {
+ var $0 = 0, $cmp = 0, $call = 0, $sub = 0, $and = 0, $cmp1 = 0, $call6 = 0, $xor = 0, $and7 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[2802] | 0;
+ $cmp = ($0 | 0) == 0;
+ if ($cmp) {
+ label = 3;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 3:
+ $call = _sysconf(8) | 0;
+ $sub = $call - 1 | 0;
+ $and = $sub & $call;
+ $cmp1 = ($and | 0) == 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ _abort();
+ case 5:
+ HEAP32[2804] = $call;
+ HEAP32[2803] = $call;
+ HEAP32[2805] = -1;
+ HEAP32[2806] = 2097152;
+ HEAP32[2807] = 0;
+ HEAP32[40927] = 0;
+ $call6 = _time(0) | 0;
+ $xor = $call6 & -16;
+ $and7 = $xor ^ 1431655768;
+ HEAP32[2802] = $and7;
+ label = 6;
+ break;
+ case 6:
+ return;
+ }
+}
+function _mmap_resize($oldp, $nb) {
+ $oldp = $oldp | 0;
+ $nb = $nb | 0;
+ var $head = 0, $0 = 0, $and = 0, $cmp = 0, $add = 0, $cmp1 = 0, $sub = 0, $1 = 0, $shl = 0, $cmp2 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $head = $oldp + 4 | 0;
+ $0 = HEAP32[$head >> 2] | 0;
+ $and = $0 & -8;
+ $cmp = $nb >>> 0 < 256;
+ if ($cmp) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $add = $nb + 4 | 0;
+ $cmp1 = $and >>> 0 < $add >>> 0;
+ if ($cmp1) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $sub = $and - $nb | 0;
+ $1 = HEAP32[2804] | 0;
+ $shl = $1 << 1;
+ $cmp2 = $sub >>> 0 > $shl >>> 0;
+ if ($cmp2) {
+ label = 5;
+ break;
+ } else {
+ $retval_0 = $oldp;
+ label = 6;
+ break;
+ }
+ case 5:
+ $retval_0 = 0;
+ label = 6;
+ break;
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _segment_holding($addr) {
+ $addr = $addr | 0;
+ var $sp_0 = 0, $base = 0, $0 = 0, $cmp = 0, $size = 0, $1 = 0, $add_ptr = 0, $cmp2 = 0, $next = 0, $2 = 0, $cmp3 = 0, $retval_0 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $sp_0 = 163712;
+ label = 3;
+ break;
+ case 3:
+ $base = $sp_0 | 0;
+ $0 = HEAP32[$base >> 2] | 0;
+ $cmp = $0 >>> 0 > $addr >>> 0;
+ if ($cmp) {
+ label = 5;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $size = $sp_0 + 4 | 0;
+ $1 = HEAP32[$size >> 2] | 0;
+ $add_ptr = $0 + $1 | 0;
+ $cmp2 = $add_ptr >>> 0 > $addr >>> 0;
+ if ($cmp2) {
+ $retval_0 = $sp_0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $next = $sp_0 + 8 | 0;
+ $2 = HEAP32[$next >> 2] | 0;
+ $cmp3 = ($2 | 0) == 0;
+ if ($cmp3) {
+ $retval_0 = 0;
+ label = 6;
+ break;
+ } else {
+ $sp_0 = $2;
+ label = 3;
+ break;
+ }
+ case 6:
+ return $retval_0 | 0;
+ }
+ return 0;
+}
+function _dispose_chunk($p, $psize) {
+ $p = $p | 0;
+ $psize = $psize | 0;
+ var $0 = 0, $add_ptr = 0, $1 = 0, $head = 0, $2 = 0, $and = 0, $tobool = 0, $prev_foot = 0, $3 = 0, $and2 = 0, $cmp = 0, $idx_neg = 0, $add_ptr5 = 0, $4 = 0, $add6 = 0, $5 = 0, $cmp7 = 0, $6 = 0, $cmp10 = 0, $shr = 0, $cmp13 = 0, $add_ptr5_sum29 = 0, $fd = 0, $7 = 0, $8 = 0, $add_ptr5_sum30 = 0, $bk = 0, $9 = 0, $10 = 0, $shl = 0, $arrayidx = 0, $11 = 0, $cmp17 = 0, $12 = 0, $cmp20 = 0, $bk22 = 0, $13 = 0, $cmp23 = 0, $cmp28 = 0, $shl31 = 0, $neg = 0, $14 = 0, $and32 = 0, $cmp36 = 0, $15 = 0, $16 = 0, $cmp40 = 0, $fd43 = 0, $17 = 0, $cmp44 = 0, $bk52 = 0, $fd53 = 0, $18 = 0, $add_ptr5_sum22 = 0, $parent = 0, $19 = 0, $20 = 0, $add_ptr5_sum23 = 0, $bk60 = 0, $21 = 0, $22 = 0, $cmp61 = 0, $add_ptr5_sum27 = 0, $fd65 = 0, $23 = 0, $24 = 0, $25 = 0, $cmp68 = 0, $bk70 = 0, $26 = 0, $cmp71 = 0, $fd74 = 0, $27 = 0, $cmp75 = 0, $add_ptr5_sum24 = 0, $child_sum = 0, $arrayidx86 = 0, $28 = 0, $29 = 0, $cmp87 = 0, $child = 0, $arrayidx90 = 0, $30 = 0, $cmp91 = 0, $RP_0 = 0, $R_0 = 0, $arrayidx95 = 0, $31 = 0, $cmp96 = 0, $arrayidx100 = 0, $32 = 0, $cmp101 = 0, $CP_0 = 0, $33 = 0, $34 = 0, $35 = 0, $cmp106 = 0, $R_1 = 0, $cmp115 = 0, $add_ptr5_sum25 = 0, $index = 0, $36 = 0, $37 = 0, $arrayidx118 = 0, $38 = 0, $cmp119 = 0, $cond36 = 0, $39 = 0, $shl126 = 0, $neg127 = 0, $40 = 0, $and128 = 0, $41 = 0, $42 = 0, $cmp132 = 0, $arrayidx138 = 0, $43 = 0, $cmp139 = 0, $arrayidx146 = 0, $cmp151 = 0, $44 = 0, $45 = 0, $cmp155 = 0, $parent160 = 0, $add_ptr5_sum26 = 0, $child161 = 0, $arrayidx162 = 0, $46 = 0, $cmp163 = 0, $47 = 0, $48 = 0, $cmp167 = 0, $arrayidx173 = 0, $parent174 = 0, $child161_sum = 0, $arrayidx179 = 0, $49 = 0, $50 = 0, $cmp180 = 0, $51 = 0, $52 = 0, $cmp184 = 0, $arrayidx190 = 0, $parent191 = 0, $add_ptr_sum = 0, $head201 = 0, $53 = 0, $54 = 0, $and202 = 0, $cmp203 = 0, $55 = 0, $and207 = 0, $or = 0, $add_ptr5_sum = 0, $head208 = 0, $56 = 0, $prev_foot210 = 0, $psize_addr_0 = 0, $p_addr_0 = 0, $57 = 0, $cmp217 = 0, $add_ptr_sum1 = 0, $head222 = 0, $58 = 0, $59 = 0, $and223 = 0, $tobool224 = 0, $60 = 0, $cmp226 = 0, $61 = 0, $add229 = 0, $or231 = 0, $head232 = 0, $62 = 0, $cmp234 = 0, $63 = 0, $cmp242 = 0, $64 = 0, $add246 = 0, $or248 = 0, $head249 = 0, $65 = 0, $add_ptr250 = 0, $prev_foot251 = 0, $and254 = 0, $add255 = 0, $shr256 = 0, $cmp257 = 0, $add_ptr_sum17 = 0, $fd261 = 0, $66 = 0, $67 = 0, $add_ptr_sum18 = 0, $bk263 = 0, $68 = 0, $69 = 0, $shl266 = 0, $arrayidx268 = 0, $70 = 0, $cmp269 = 0, $71 = 0, $cmp273 = 0, $bk276 = 0, $72 = 0, $cmp277 = 0, $cmp286 = 0, $shl289 = 0, $neg290 = 0, $73 = 0, $and292 = 0, $cmp297 = 0, $74 = 0, $75 = 0, $cmp301 = 0, $fd304 = 0, $76 = 0, $cmp305 = 0, $bk314 = 0, $fd315 = 0, $77 = 0, $add_ptr_sum2 = 0, $parent324 = 0, $78 = 0, $79 = 0, $add_ptr_sum3 = 0, $bk326 = 0, $80 = 0, $81 = 0, $cmp327 = 0, $add_ptr_sum15 = 0, $fd331 = 0, $82 = 0, $83 = 0, $84 = 0, $cmp334 = 0, $bk337 = 0, $85 = 0, $cmp338 = 0, $fd341 = 0, $86 = 0, $cmp342 = 0, $child355_sum = 0, $arrayidx356 = 0, $87 = 0, $88 = 0, $cmp357 = 0, $add_ptr_sum4 = 0, $child355 = 0, $arrayidx361 = 0, $89 = 0, $cmp362 = 0, $RP354_0 = 0, $R325_0 = 0, $arrayidx368 = 0, $90 = 0, $cmp369 = 0, $arrayidx373 = 0, $91 = 0, $cmp374 = 0, $CP365_0 = 0, $92 = 0, $93 = 0, $94 = 0, $cmp381 = 0, $R325_1 = 0, $cmp390 = 0, $add_ptr_sum13 = 0, $index394 = 0, $95 = 0, $96 = 0, $arrayidx396 = 0, $97 = 0, $cmp397 = 0, $cond37 = 0, $98 = 0, $shl404 = 0, $neg405 = 0, $99 = 0, $and407 = 0, $100 = 0, $101 = 0, $cmp411 = 0, $arrayidx417 = 0, $102 = 0, $cmp418 = 0, $arrayidx425 = 0, $cmp430 = 0, $103 = 0, $104 = 0, $cmp434 = 0, $parent441 = 0, $add_ptr_sum14 = 0, $child442 = 0, $arrayidx443 = 0, $105 = 0, $cmp444 = 0, $106 = 0, $107 = 0, $cmp448 = 0, $arrayidx454 = 0, $parent455 = 0, $child442_sum = 0, $arrayidx460 = 0, $108 = 0, $109 = 0, $cmp461 = 0, $110 = 0, $111 = 0, $cmp465 = 0, $arrayidx471 = 0, $parent472 = 0, $or481 = 0, $head482 = 0, $112 = 0, $add_ptr483 = 0, $prev_foot484 = 0, $113 = 0, $cmp486 = 0, $and495 = 0, $or496 = 0, $head497 = 0, $114 = 0, $add_ptr498 = 0, $prev_foot499 = 0, $psize_addr_1 = 0, $shr501 = 0, $cmp502 = 0, $shl508 = 0, $arrayidx510 = 0, $115 = 0, $116 = 0, $shl513 = 0, $and514 = 0, $tobool515 = 0, $or519 = 0, $arrayidx510_sum12 = 0, $117 = 0, $118 = 0, $119 = 0, $120 = 0, $cmp523 = 0, $F511_0 = 0, $arrayidx510_sum = 0, $121 = 0, $bk533 = 0, $fd534 = 0, $bk535 = 0, $122 = 0, $shr540 = 0, $cmp541 = 0, $cmp545 = 0, $sub = 0, $shr549 = 0, $and550 = 0, $shl551 = 0, $sub552 = 0, $shr553 = 0, $and554 = 0, $add555 = 0, $shl556 = 0, $sub557 = 0, $shr558 = 0, $and559 = 0, $add560 = 0, $sub561 = 0, $shl562 = 0, $shr563 = 0, $add564 = 0, $shl565 = 0, $add566 = 0, $shr567 = 0, $and568 = 0, $add569 = 0, $I539_0 = 0, $arrayidx573 = 0, $index574 = 0, $I539_0_c = 0, $arrayidx576 = 0, $123 = 0, $124 = 0, $shl580 = 0, $and581 = 0, $tobool582 = 0, $or586 = 0, $parent587 = 0, $_c = 0, $bk588 = 0, $fd589 = 0, $125 = 0, $cmp592 = 0, $shr594 = 0, $sub597 = 0, $cond = 0, $shl598 = 0, $T_0 = 0, $K591_0 = 0, $head599 = 0, $126 = 0, $and600 = 0, $cmp601 = 0, $shr604 = 0, $arrayidx607 = 0, $127 = 0, $cmp609 = 0, $shl608 = 0, $128 = 0, $129 = 0, $cmp614 = 0, $parent619 = 0, $T_0_c9 = 0, $bk620 = 0, $fd621 = 0, $fd626 = 0, $130 = 0, $131 = 0, $132 = 0, $cmp628 = 0, $133 = 0, $cmp632 = 0, $bk639 = 0, $fd641 = 0, $_c8 = 0, $bk642 = 0, $T_0_c = 0, $parent643 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $p;
+ $add_ptr = $0 + $psize | 0;
+ $1 = $add_ptr;
+ $head = $p + 4 | 0;
+ $2 = HEAP32[$head >> 2] | 0;
+ $and = $2 & 1;
+ $tobool = ($and | 0) == 0;
+ if ($tobool) {
+ label = 3;
+ break;
+ } else {
+ $p_addr_0 = $p;
+ $psize_addr_0 = $psize;
+ label = 55;
+ break;
+ }
+ case 3:
+ $prev_foot = $p | 0;
+ $3 = HEAP32[$prev_foot >> 2] | 0;
+ $and2 = $2 & 3;
+ $cmp = ($and2 | 0) == 0;
+ if ($cmp) {
+ label = 135;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ $idx_neg = -$3 | 0;
+ $add_ptr5 = $0 + $idx_neg | 0;
+ $4 = $add_ptr5;
+ $add6 = $3 + $psize | 0;
+ $5 = HEAP32[40820] | 0;
+ $cmp7 = $add_ptr5 >>> 0 < $5 >>> 0;
+ if ($cmp7) {
+ label = 54;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $6 = HEAP32[40821] | 0;
+ $cmp10 = ($4 | 0) == ($6 | 0);
+ if ($cmp10) {
+ label = 52;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $shr = $3 >>> 3;
+ $cmp13 = $3 >>> 0 < 256;
+ if ($cmp13) {
+ label = 7;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 7:
+ $add_ptr5_sum29 = 8 - $3 | 0;
+ $fd = $0 + $add_ptr5_sum29 | 0;
+ $7 = $fd;
+ $8 = HEAP32[$7 >> 2] | 0;
+ $add_ptr5_sum30 = 12 - $3 | 0;
+ $bk = $0 + $add_ptr5_sum30 | 0;
+ $9 = $bk;
+ $10 = HEAP32[$9 >> 2] | 0;
+ $shl = $shr << 1;
+ $arrayidx = 163304 + ($shl << 2) | 0;
+ $11 = $arrayidx;
+ $cmp17 = ($8 | 0) == ($11 | 0);
+ if ($cmp17) {
+ label = 10;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 8:
+ $12 = $8;
+ $cmp20 = $12 >>> 0 < $5 >>> 0;
+ if ($cmp20) {
+ label = 17;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $bk22 = $8 + 12 | 0;
+ $13 = HEAP32[$bk22 >> 2] | 0;
+ $cmp23 = ($13 | 0) == ($4 | 0);
+ if ($cmp23) {
+ label = 10;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 10:
+ $cmp28 = ($10 | 0) == ($8 | 0);
+ if ($cmp28) {
+ label = 11;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 11:
+ $shl31 = 1 << $shr;
+ $neg = $shl31 ^ -1;
+ $14 = HEAP32[40816] | 0;
+ $and32 = $14 & $neg;
+ HEAP32[40816] = $and32;
+ $p_addr_0 = $4;
+ $psize_addr_0 = $add6;
+ label = 55;
+ break;
+ case 12:
+ $cmp36 = ($10 | 0) == ($11 | 0);
+ if ($cmp36) {
+ label = 15;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $15 = $10;
+ $16 = HEAP32[40820] | 0;
+ $cmp40 = $15 >>> 0 < $16 >>> 0;
+ if ($cmp40) {
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $fd43 = $10 + 8 | 0;
+ $17 = HEAP32[$fd43 >> 2] | 0;
+ $cmp44 = ($17 | 0) == ($4 | 0);
+ if ($cmp44) {
+ label = 15;
+ break;
+ } else {
+ label = 16;
+ break;
+ }
+ case 15:
+ $bk52 = $8 + 12 | 0;
+ HEAP32[$bk52 >> 2] = $10;
+ $fd53 = $10 + 8 | 0;
+ HEAP32[$fd53 >> 2] = $8;
+ $p_addr_0 = $4;
+ $psize_addr_0 = $add6;
+ label = 55;
+ break;
+ case 16:
+ _abort();
+ case 17:
+ _abort();
+ case 18:
+ $18 = $add_ptr5;
+ $add_ptr5_sum22 = 24 - $3 | 0;
+ $parent = $0 + $add_ptr5_sum22 | 0;
+ $19 = $parent;
+ $20 = HEAP32[$19 >> 2] | 0;
+ $add_ptr5_sum23 = 12 - $3 | 0;
+ $bk60 = $0 + $add_ptr5_sum23 | 0;
+ $21 = $bk60;
+ $22 = HEAP32[$21 >> 2] | 0;
+ $cmp61 = ($22 | 0) == ($18 | 0);
+ if ($cmp61) {
+ label = 24;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $add_ptr5_sum27 = 8 - $3 | 0;
+ $fd65 = $0 + $add_ptr5_sum27 | 0;
+ $23 = $fd65;
+ $24 = HEAP32[$23 >> 2] | 0;
+ $25 = $24;
+ $cmp68 = $25 >>> 0 < $5 >>> 0;
+ if ($cmp68) {
+ label = 23;
+ break;
+ } else {
+ label = 20;
+ break;
+ }
+ case 20:
+ $bk70 = $24 + 12 | 0;
+ $26 = HEAP32[$bk70 >> 2] | 0;
+ $cmp71 = ($26 | 0) == ($18 | 0);
+ if ($cmp71) {
+ label = 21;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 21:
+ $fd74 = $22 + 8 | 0;
+ $27 = HEAP32[$fd74 >> 2] | 0;
+ $cmp75 = ($27 | 0) == ($18 | 0);
+ if ($cmp75) {
+ label = 22;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 22:
+ HEAP32[$bk70 >> 2] = $22;
+ HEAP32[$fd74 >> 2] = $24;
+ $R_1 = $22;
+ label = 32;
+ break;
+ case 23:
+ _abort();
+ case 24:
+ $add_ptr5_sum24 = 16 - $3 | 0;
+ $child_sum = $add_ptr5_sum24 + 4 | 0;
+ $arrayidx86 = $0 + $child_sum | 0;
+ $28 = $arrayidx86;
+ $29 = HEAP32[$28 >> 2] | 0;
+ $cmp87 = ($29 | 0) == 0;
+ if ($cmp87) {
+ label = 25;
+ break;
+ } else {
+ $R_0 = $29;
+ $RP_0 = $28;
+ label = 26;
+ break;
+ }
+ case 25:
+ $child = $0 + $add_ptr5_sum24 | 0;
+ $arrayidx90 = $child;
+ $30 = HEAP32[$arrayidx90 >> 2] | 0;
+ $cmp91 = ($30 | 0) == 0;
+ if ($cmp91) {
+ $R_1 = 0;
+ label = 32;
+ break;
+ } else {
+ $R_0 = $30;
+ $RP_0 = $arrayidx90;
+ label = 26;
+ break;
+ }
+ case 26:
+ $arrayidx95 = $R_0 + 20 | 0;
+ $31 = HEAP32[$arrayidx95 >> 2] | 0;
+ $cmp96 = ($31 | 0) == 0;
+ if ($cmp96) {
+ label = 27;
+ break;
+ } else {
+ $CP_0 = $arrayidx95;
+ label = 28;
+ break;
+ }
+ case 27:
+ $arrayidx100 = $R_0 + 16 | 0;
+ $32 = HEAP32[$arrayidx100 >> 2] | 0;
+ $cmp101 = ($32 | 0) == 0;
+ if ($cmp101) {
+ label = 29;
+ break;
+ } else {
+ $CP_0 = $arrayidx100;
+ label = 28;
+ break;
+ }
+ case 28:
+ $33 = HEAP32[$CP_0 >> 2] | 0;
+ $R_0 = $33;
+ $RP_0 = $CP_0;
+ label = 26;
+ break;
+ case 29:
+ $34 = $RP_0;
+ $35 = HEAP32[40820] | 0;
+ $cmp106 = $34 >>> 0 < $35 >>> 0;
+ if ($cmp106) {
+ label = 31;
+ break;
+ } else {
+ label = 30;
+ break;
+ }
+ case 30:
+ HEAP32[$RP_0 >> 2] = 0;
+ $R_1 = $R_0;
+ label = 32;
+ break;
+ case 31:
+ _abort();
+ case 32:
+ $cmp115 = ($20 | 0) == 0;
+ if ($cmp115) {
+ $p_addr_0 = $4;
+ $psize_addr_0 = $add6;
+ label = 55;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $add_ptr5_sum25 = 28 - $3 | 0;
+ $index = $0 + $add_ptr5_sum25 | 0;
+ $36 = $index;
+ $37 = HEAP32[$36 >> 2] | 0;
+ $arrayidx118 = 163568 + ($37 << 2) | 0;
+ $38 = HEAP32[$arrayidx118 >> 2] | 0;
+ $cmp119 = ($18 | 0) == ($38 | 0);
+ if ($cmp119) {
+ label = 34;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 34:
+ HEAP32[$arrayidx118 >> 2] = $R_1;
+ $cond36 = ($R_1 | 0) == 0;
+ if ($cond36) {
+ label = 35;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 35:
+ $39 = HEAP32[$36 >> 2] | 0;
+ $shl126 = 1 << $39;
+ $neg127 = $shl126 ^ -1;
+ $40 = HEAP32[40817] | 0;
+ $and128 = $40 & $neg127;
+ HEAP32[40817] = $and128;
+ $p_addr_0 = $4;
+ $psize_addr_0 = $add6;
+ label = 55;
+ break;
+ case 36:
+ $41 = $20;
+ $42 = HEAP32[40820] | 0;
+ $cmp132 = $41 >>> 0 < $42 >>> 0;
+ if ($cmp132) {
+ label = 40;
+ break;
+ } else {
+ label = 37;
+ break;
+ }
+ case 37:
+ $arrayidx138 = $20 + 16 | 0;
+ $43 = HEAP32[$arrayidx138 >> 2] | 0;
+ $cmp139 = ($43 | 0) == ($18 | 0);
+ if ($cmp139) {
+ label = 38;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 38:
+ HEAP32[$arrayidx138 >> 2] = $R_1;
+ label = 41;
+ break;
+ case 39:
+ $arrayidx146 = $20 + 20 | 0;
+ HEAP32[$arrayidx146 >> 2] = $R_1;
+ label = 41;
+ break;
+ case 40:
+ _abort();
+ case 41:
+ $cmp151 = ($R_1 | 0) == 0;
+ if ($cmp151) {
+ $p_addr_0 = $4;
+ $psize_addr_0 = $add6;
+ label = 55;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $44 = $R_1;
+ $45 = HEAP32[40820] | 0;
+ $cmp155 = $44 >>> 0 < $45 >>> 0;
+ if ($cmp155) {
+ label = 51;
+ break;
+ } else {
+ label = 43;
+ break;
+ }
+ case 43:
+ $parent160 = $R_1 + 24 | 0;
+ HEAP32[$parent160 >> 2] = $20;
+ $add_ptr5_sum26 = 16 - $3 | 0;
+ $child161 = $0 + $add_ptr5_sum26 | 0;
+ $arrayidx162 = $child161;
+ $46 = HEAP32[$arrayidx162 >> 2] | 0;
+ $cmp163 = ($46 | 0) == 0;
+ if ($cmp163) {
+ label = 47;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 44:
+ $47 = $46;
+ $48 = HEAP32[40820] | 0;
+ $cmp167 = $47 >>> 0 < $48 >>> 0;
+ if ($cmp167) {
+ label = 46;
+ break;
+ } else {
+ label = 45;
+ break;
+ }
+ case 45:
+ $arrayidx173 = $R_1 + 16 | 0;
+ HEAP32[$arrayidx173 >> 2] = $46;
+ $parent174 = $46 + 24 | 0;
+ HEAP32[$parent174 >> 2] = $R_1;
+ label = 47;
+ break;
+ case 46:
+ _abort();
+ case 47:
+ $child161_sum = $add_ptr5_sum26 + 4 | 0;
+ $arrayidx179 = $0 + $child161_sum | 0;
+ $49 = $arrayidx179;
+ $50 = HEAP32[$49 >> 2] | 0;
+ $cmp180 = ($50 | 0) == 0;
+ if ($cmp180) {
+ $p_addr_0 = $4;
+ $psize_addr_0 = $add6;
+ label = 55;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $51 = $50;
+ $52 = HEAP32[40820] | 0;
+ $cmp184 = $51 >>> 0 < $52 >>> 0;
+ if ($cmp184) {
+ label = 50;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $arrayidx190 = $R_1 + 20 | 0;
+ HEAP32[$arrayidx190 >> 2] = $50;
+ $parent191 = $50 + 24 | 0;
+ HEAP32[$parent191 >> 2] = $R_1;
+ $p_addr_0 = $4;
+ $psize_addr_0 = $add6;
+ label = 55;
+ break;
+ case 50:
+ _abort();
+ case 51:
+ _abort();
+ case 52:
+ $add_ptr_sum = $psize + 4 | 0;
+ $head201 = $0 + $add_ptr_sum | 0;
+ $53 = $head201;
+ $54 = HEAP32[$53 >> 2] | 0;
+ $and202 = $54 & 3;
+ $cmp203 = ($and202 | 0) == 3;
+ if ($cmp203) {
+ label = 53;
+ break;
+ } else {
+ $p_addr_0 = $4;
+ $psize_addr_0 = $add6;
+ label = 55;
+ break;
+ }
+ case 53:
+ HEAP32[40818] = $add6;
+ $55 = HEAP32[$53 >> 2] | 0;
+ $and207 = $55 & -2;
+ HEAP32[$53 >> 2] = $and207;
+ $or = $add6 | 1;
+ $add_ptr5_sum = 4 - $3 | 0;
+ $head208 = $0 + $add_ptr5_sum | 0;
+ $56 = $head208;
+ HEAP32[$56 >> 2] = $or;
+ $prev_foot210 = $add_ptr;
+ HEAP32[$prev_foot210 >> 2] = $add6;
+ label = 135;
+ break;
+ case 54:
+ _abort();
+ case 55:
+ $57 = HEAP32[40820] | 0;
+ $cmp217 = $add_ptr >>> 0 < $57 >>> 0;
+ if ($cmp217) {
+ label = 134;
+ break;
+ } else {
+ label = 56;
+ break;
+ }
+ case 56:
+ $add_ptr_sum1 = $psize + 4 | 0;
+ $head222 = $0 + $add_ptr_sum1 | 0;
+ $58 = $head222;
+ $59 = HEAP32[$58 >> 2] | 0;
+ $and223 = $59 & 2;
+ $tobool224 = ($and223 | 0) == 0;
+ if ($tobool224) {
+ label = 57;
+ break;
+ } else {
+ label = 110;
+ break;
+ }
+ case 57:
+ $60 = HEAP32[40822] | 0;
+ $cmp226 = ($1 | 0) == ($60 | 0);
+ if ($cmp226) {
+ label = 58;
+ break;
+ } else {
+ label = 60;
+ break;
+ }
+ case 58:
+ $61 = HEAP32[40819] | 0;
+ $add229 = $61 + $psize_addr_0 | 0;
+ HEAP32[40819] = $add229;
+ HEAP32[40822] = $p_addr_0;
+ $or231 = $add229 | 1;
+ $head232 = $p_addr_0 + 4 | 0;
+ HEAP32[$head232 >> 2] = $or231;
+ $62 = HEAP32[40821] | 0;
+ $cmp234 = ($p_addr_0 | 0) == ($62 | 0);
+ if ($cmp234) {
+ label = 59;
+ break;
+ } else {
+ label = 135;
+ break;
+ }
+ case 59:
+ HEAP32[40821] = 0;
+ HEAP32[40818] = 0;
+ label = 135;
+ break;
+ case 60:
+ $63 = HEAP32[40821] | 0;
+ $cmp242 = ($1 | 0) == ($63 | 0);
+ if ($cmp242) {
+ label = 61;
+ break;
+ } else {
+ label = 62;
+ break;
+ }
+ case 61:
+ $64 = HEAP32[40818] | 0;
+ $add246 = $64 + $psize_addr_0 | 0;
+ HEAP32[40818] = $add246;
+ HEAP32[40821] = $p_addr_0;
+ $or248 = $add246 | 1;
+ $head249 = $p_addr_0 + 4 | 0;
+ HEAP32[$head249 >> 2] = $or248;
+ $65 = $p_addr_0;
+ $add_ptr250 = $65 + $add246 | 0;
+ $prev_foot251 = $add_ptr250;
+ HEAP32[$prev_foot251 >> 2] = $add246;
+ label = 135;
+ break;
+ case 62:
+ $and254 = $59 & -8;
+ $add255 = $and254 + $psize_addr_0 | 0;
+ $shr256 = $59 >>> 3;
+ $cmp257 = $59 >>> 0 < 256;
+ if ($cmp257) {
+ label = 63;
+ break;
+ } else {
+ label = 74;
+ break;
+ }
+ case 63:
+ $add_ptr_sum17 = $psize + 8 | 0;
+ $fd261 = $0 + $add_ptr_sum17 | 0;
+ $66 = $fd261;
+ $67 = HEAP32[$66 >> 2] | 0;
+ $add_ptr_sum18 = $psize + 12 | 0;
+ $bk263 = $0 + $add_ptr_sum18 | 0;
+ $68 = $bk263;
+ $69 = HEAP32[$68 >> 2] | 0;
+ $shl266 = $shr256 << 1;
+ $arrayidx268 = 163304 + ($shl266 << 2) | 0;
+ $70 = $arrayidx268;
+ $cmp269 = ($67 | 0) == ($70 | 0);
+ if ($cmp269) {
+ label = 66;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 64:
+ $71 = $67;
+ $cmp273 = $71 >>> 0 < $57 >>> 0;
+ if ($cmp273) {
+ label = 73;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $bk276 = $67 + 12 | 0;
+ $72 = HEAP32[$bk276 >> 2] | 0;
+ $cmp277 = ($72 | 0) == ($1 | 0);
+ if ($cmp277) {
+ label = 66;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 66:
+ $cmp286 = ($69 | 0) == ($67 | 0);
+ if ($cmp286) {
+ label = 67;
+ break;
+ } else {
+ label = 68;
+ break;
+ }
+ case 67:
+ $shl289 = 1 << $shr256;
+ $neg290 = $shl289 ^ -1;
+ $73 = HEAP32[40816] | 0;
+ $and292 = $73 & $neg290;
+ HEAP32[40816] = $and292;
+ label = 108;
+ break;
+ case 68:
+ $cmp297 = ($69 | 0) == ($70 | 0);
+ if ($cmp297) {
+ label = 71;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 69:
+ $74 = $69;
+ $75 = HEAP32[40820] | 0;
+ $cmp301 = $74 >>> 0 < $75 >>> 0;
+ if ($cmp301) {
+ label = 72;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $fd304 = $69 + 8 | 0;
+ $76 = HEAP32[$fd304 >> 2] | 0;
+ $cmp305 = ($76 | 0) == ($1 | 0);
+ if ($cmp305) {
+ label = 71;
+ break;
+ } else {
+ label = 72;
+ break;
+ }
+ case 71:
+ $bk314 = $67 + 12 | 0;
+ HEAP32[$bk314 >> 2] = $69;
+ $fd315 = $69 + 8 | 0;
+ HEAP32[$fd315 >> 2] = $67;
+ label = 108;
+ break;
+ case 72:
+ _abort();
+ case 73:
+ _abort();
+ case 74:
+ $77 = $add_ptr;
+ $add_ptr_sum2 = $psize + 24 | 0;
+ $parent324 = $0 + $add_ptr_sum2 | 0;
+ $78 = $parent324;
+ $79 = HEAP32[$78 >> 2] | 0;
+ $add_ptr_sum3 = $psize + 12 | 0;
+ $bk326 = $0 + $add_ptr_sum3 | 0;
+ $80 = $bk326;
+ $81 = HEAP32[$80 >> 2] | 0;
+ $cmp327 = ($81 | 0) == ($77 | 0);
+ if ($cmp327) {
+ label = 80;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ $add_ptr_sum15 = $psize + 8 | 0;
+ $fd331 = $0 + $add_ptr_sum15 | 0;
+ $82 = $fd331;
+ $83 = HEAP32[$82 >> 2] | 0;
+ $84 = $83;
+ $cmp334 = $84 >>> 0 < $57 >>> 0;
+ if ($cmp334) {
+ label = 79;
+ break;
+ } else {
+ label = 76;
+ break;
+ }
+ case 76:
+ $bk337 = $83 + 12 | 0;
+ $85 = HEAP32[$bk337 >> 2] | 0;
+ $cmp338 = ($85 | 0) == ($77 | 0);
+ if ($cmp338) {
+ label = 77;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 77:
+ $fd341 = $81 + 8 | 0;
+ $86 = HEAP32[$fd341 >> 2] | 0;
+ $cmp342 = ($86 | 0) == ($77 | 0);
+ if ($cmp342) {
+ label = 78;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 78:
+ HEAP32[$bk337 >> 2] = $81;
+ HEAP32[$fd341 >> 2] = $83;
+ $R325_1 = $81;
+ label = 88;
+ break;
+ case 79:
+ _abort();
+ case 80:
+ $child355_sum = $psize + 20 | 0;
+ $arrayidx356 = $0 + $child355_sum | 0;
+ $87 = $arrayidx356;
+ $88 = HEAP32[$87 >> 2] | 0;
+ $cmp357 = ($88 | 0) == 0;
+ if ($cmp357) {
+ label = 81;
+ break;
+ } else {
+ $R325_0 = $88;
+ $RP354_0 = $87;
+ label = 82;
+ break;
+ }
+ case 81:
+ $add_ptr_sum4 = $psize + 16 | 0;
+ $child355 = $0 + $add_ptr_sum4 | 0;
+ $arrayidx361 = $child355;
+ $89 = HEAP32[$arrayidx361 >> 2] | 0;
+ $cmp362 = ($89 | 0) == 0;
+ if ($cmp362) {
+ $R325_1 = 0;
+ label = 88;
+ break;
+ } else {
+ $R325_0 = $89;
+ $RP354_0 = $arrayidx361;
+ label = 82;
+ break;
+ }
+ case 82:
+ $arrayidx368 = $R325_0 + 20 | 0;
+ $90 = HEAP32[$arrayidx368 >> 2] | 0;
+ $cmp369 = ($90 | 0) == 0;
+ if ($cmp369) {
+ label = 83;
+ break;
+ } else {
+ $CP365_0 = $arrayidx368;
+ label = 84;
+ break;
+ }
+ case 83:
+ $arrayidx373 = $R325_0 + 16 | 0;
+ $91 = HEAP32[$arrayidx373 >> 2] | 0;
+ $cmp374 = ($91 | 0) == 0;
+ if ($cmp374) {
+ label = 85;
+ break;
+ } else {
+ $CP365_0 = $arrayidx373;
+ label = 84;
+ break;
+ }
+ case 84:
+ $92 = HEAP32[$CP365_0 >> 2] | 0;
+ $R325_0 = $92;
+ $RP354_0 = $CP365_0;
+ label = 82;
+ break;
+ case 85:
+ $93 = $RP354_0;
+ $94 = HEAP32[40820] | 0;
+ $cmp381 = $93 >>> 0 < $94 >>> 0;
+ if ($cmp381) {
+ label = 87;
+ break;
+ } else {
+ label = 86;
+ break;
+ }
+ case 86:
+ HEAP32[$RP354_0 >> 2] = 0;
+ $R325_1 = $R325_0;
+ label = 88;
+ break;
+ case 87:
+ _abort();
+ case 88:
+ $cmp390 = ($79 | 0) == 0;
+ if ($cmp390) {
+ label = 108;
+ break;
+ } else {
+ label = 89;
+ break;
+ }
+ case 89:
+ $add_ptr_sum13 = $psize + 28 | 0;
+ $index394 = $0 + $add_ptr_sum13 | 0;
+ $95 = $index394;
+ $96 = HEAP32[$95 >> 2] | 0;
+ $arrayidx396 = 163568 + ($96 << 2) | 0;
+ $97 = HEAP32[$arrayidx396 >> 2] | 0;
+ $cmp397 = ($77 | 0) == ($97 | 0);
+ if ($cmp397) {
+ label = 90;
+ break;
+ } else {
+ label = 92;
+ break;
+ }
+ case 90:
+ HEAP32[$arrayidx396 >> 2] = $R325_1;
+ $cond37 = ($R325_1 | 0) == 0;
+ if ($cond37) {
+ label = 91;
+ break;
+ } else {
+ label = 98;
+ break;
+ }
+ case 91:
+ $98 = HEAP32[$95 >> 2] | 0;
+ $shl404 = 1 << $98;
+ $neg405 = $shl404 ^ -1;
+ $99 = HEAP32[40817] | 0;
+ $and407 = $99 & $neg405;
+ HEAP32[40817] = $and407;
+ label = 108;
+ break;
+ case 92:
+ $100 = $79;
+ $101 = HEAP32[40820] | 0;
+ $cmp411 = $100 >>> 0 < $101 >>> 0;
+ if ($cmp411) {
+ label = 96;
+ break;
+ } else {
+ label = 93;
+ break;
+ }
+ case 93:
+ $arrayidx417 = $79 + 16 | 0;
+ $102 = HEAP32[$arrayidx417 >> 2] | 0;
+ $cmp418 = ($102 | 0) == ($77 | 0);
+ if ($cmp418) {
+ label = 94;
+ break;
+ } else {
+ label = 95;
+ break;
+ }
+ case 94:
+ HEAP32[$arrayidx417 >> 2] = $R325_1;
+ label = 97;
+ break;
+ case 95:
+ $arrayidx425 = $79 + 20 | 0;
+ HEAP32[$arrayidx425 >> 2] = $R325_1;
+ label = 97;
+ break;
+ case 96:
+ _abort();
+ case 97:
+ $cmp430 = ($R325_1 | 0) == 0;
+ if ($cmp430) {
+ label = 108;
+ break;
+ } else {
+ label = 98;
+ break;
+ }
+ case 98:
+ $103 = $R325_1;
+ $104 = HEAP32[40820] | 0;
+ $cmp434 = $103 >>> 0 < $104 >>> 0;
+ if ($cmp434) {
+ label = 107;
+ break;
+ } else {
+ label = 99;
+ break;
+ }
+ case 99:
+ $parent441 = $R325_1 + 24 | 0;
+ HEAP32[$parent441 >> 2] = $79;
+ $add_ptr_sum14 = $psize + 16 | 0;
+ $child442 = $0 + $add_ptr_sum14 | 0;
+ $arrayidx443 = $child442;
+ $105 = HEAP32[$arrayidx443 >> 2] | 0;
+ $cmp444 = ($105 | 0) == 0;
+ if ($cmp444) {
+ label = 103;
+ break;
+ } else {
+ label = 100;
+ break;
+ }
+ case 100:
+ $106 = $105;
+ $107 = HEAP32[40820] | 0;
+ $cmp448 = $106 >>> 0 < $107 >>> 0;
+ if ($cmp448) {
+ label = 102;
+ break;
+ } else {
+ label = 101;
+ break;
+ }
+ case 101:
+ $arrayidx454 = $R325_1 + 16 | 0;
+ HEAP32[$arrayidx454 >> 2] = $105;
+ $parent455 = $105 + 24 | 0;
+ HEAP32[$parent455 >> 2] = $R325_1;
+ label = 103;
+ break;
+ case 102:
+ _abort();
+ case 103:
+ $child442_sum = $psize + 20 | 0;
+ $arrayidx460 = $0 + $child442_sum | 0;
+ $108 = $arrayidx460;
+ $109 = HEAP32[$108 >> 2] | 0;
+ $cmp461 = ($109 | 0) == 0;
+ if ($cmp461) {
+ label = 108;
+ break;
+ } else {
+ label = 104;
+ break;
+ }
+ case 104:
+ $110 = $109;
+ $111 = HEAP32[40820] | 0;
+ $cmp465 = $110 >>> 0 < $111 >>> 0;
+ if ($cmp465) {
+ label = 106;
+ break;
+ } else {
+ label = 105;
+ break;
+ }
+ case 105:
+ $arrayidx471 = $R325_1 + 20 | 0;
+ HEAP32[$arrayidx471 >> 2] = $109;
+ $parent472 = $109 + 24 | 0;
+ HEAP32[$parent472 >> 2] = $R325_1;
+ label = 108;
+ break;
+ case 106:
+ _abort();
+ case 107:
+ _abort();
+ case 108:
+ $or481 = $add255 | 1;
+ $head482 = $p_addr_0 + 4 | 0;
+ HEAP32[$head482 >> 2] = $or481;
+ $112 = $p_addr_0;
+ $add_ptr483 = $112 + $add255 | 0;
+ $prev_foot484 = $add_ptr483;
+ HEAP32[$prev_foot484 >> 2] = $add255;
+ $113 = HEAP32[40821] | 0;
+ $cmp486 = ($p_addr_0 | 0) == ($113 | 0);
+ if ($cmp486) {
+ label = 109;
+ break;
+ } else {
+ $psize_addr_1 = $add255;
+ label = 111;
+ break;
+ }
+ case 109:
+ HEAP32[40818] = $add255;
+ label = 135;
+ break;
+ case 110:
+ $and495 = $59 & -2;
+ HEAP32[$58 >> 2] = $and495;
+ $or496 = $psize_addr_0 | 1;
+ $head497 = $p_addr_0 + 4 | 0;
+ HEAP32[$head497 >> 2] = $or496;
+ $114 = $p_addr_0;
+ $add_ptr498 = $114 + $psize_addr_0 | 0;
+ $prev_foot499 = $add_ptr498;
+ HEAP32[$prev_foot499 >> 2] = $psize_addr_0;
+ $psize_addr_1 = $psize_addr_0;
+ label = 111;
+ break;
+ case 111:
+ $shr501 = $psize_addr_1 >>> 3;
+ $cmp502 = $psize_addr_1 >>> 0 < 256;
+ if ($cmp502) {
+ label = 112;
+ break;
+ } else {
+ label = 117;
+ break;
+ }
+ case 112:
+ $shl508 = $shr501 << 1;
+ $arrayidx510 = 163304 + ($shl508 << 2) | 0;
+ $115 = $arrayidx510;
+ $116 = HEAP32[40816] | 0;
+ $shl513 = 1 << $shr501;
+ $and514 = $116 & $shl513;
+ $tobool515 = ($and514 | 0) == 0;
+ if ($tobool515) {
+ label = 113;
+ break;
+ } else {
+ label = 114;
+ break;
+ }
+ case 113:
+ $or519 = $116 | $shl513;
+ HEAP32[40816] = $or519;
+ $F511_0 = $115;
+ label = 116;
+ break;
+ case 114:
+ $arrayidx510_sum12 = $shl508 + 2 | 0;
+ $117 = 163304 + ($arrayidx510_sum12 << 2) | 0;
+ $118 = HEAP32[$117 >> 2] | 0;
+ $119 = $118;
+ $120 = HEAP32[40820] | 0;
+ $cmp523 = $119 >>> 0 < $120 >>> 0;
+ if ($cmp523) {
+ label = 115;
+ break;
+ } else {
+ $F511_0 = $118;
+ label = 116;
+ break;
+ }
+ case 115:
+ _abort();
+ case 116:
+ $arrayidx510_sum = $shl508 + 2 | 0;
+ $121 = 163304 + ($arrayidx510_sum << 2) | 0;
+ HEAP32[$121 >> 2] = $p_addr_0;
+ $bk533 = $F511_0 + 12 | 0;
+ HEAP32[$bk533 >> 2] = $p_addr_0;
+ $fd534 = $p_addr_0 + 8 | 0;
+ HEAP32[$fd534 >> 2] = $F511_0;
+ $bk535 = $p_addr_0 + 12 | 0;
+ HEAP32[$bk535 >> 2] = $115;
+ label = 135;
+ break;
+ case 117:
+ $122 = $p_addr_0;
+ $shr540 = $psize_addr_1 >>> 8;
+ $cmp541 = ($shr540 | 0) == 0;
+ if ($cmp541) {
+ $I539_0 = 0;
+ label = 120;
+ break;
+ } else {
+ label = 118;
+ break;
+ }
+ case 118:
+ $cmp545 = $psize_addr_1 >>> 0 > 16777215;
+ if ($cmp545) {
+ $I539_0 = 31;
+ label = 120;
+ break;
+ } else {
+ label = 119;
+ break;
+ }
+ case 119:
+ $sub = $shr540 + 1048320 | 0;
+ $shr549 = $sub >>> 16;
+ $and550 = $shr549 & 8;
+ $shl551 = $shr540 << $and550;
+ $sub552 = $shl551 + 520192 | 0;
+ $shr553 = $sub552 >>> 16;
+ $and554 = $shr553 & 4;
+ $add555 = $and554 | $and550;
+ $shl556 = $shl551 << $and554;
+ $sub557 = $shl556 + 245760 | 0;
+ $shr558 = $sub557 >>> 16;
+ $and559 = $shr558 & 2;
+ $add560 = $add555 | $and559;
+ $sub561 = 14 - $add560 | 0;
+ $shl562 = $shl556 << $and559;
+ $shr563 = $shl562 >>> 15;
+ $add564 = $sub561 + $shr563 | 0;
+ $shl565 = $add564 << 1;
+ $add566 = $add564 + 7 | 0;
+ $shr567 = $psize_addr_1 >>> ($add566 >>> 0);
+ $and568 = $shr567 & 1;
+ $add569 = $and568 | $shl565;
+ $I539_0 = $add569;
+ label = 120;
+ break;
+ case 120:
+ $arrayidx573 = 163568 + ($I539_0 << 2) | 0;
+ $index574 = $p_addr_0 + 28 | 0;
+ $I539_0_c = $I539_0;
+ HEAP32[$index574 >> 2] = $I539_0_c;
+ $arrayidx576 = $p_addr_0 + 20 | 0;
+ HEAP32[$arrayidx576 >> 2] = 0;
+ $123 = $p_addr_0 + 16 | 0;
+ HEAP32[$123 >> 2] = 0;
+ $124 = HEAP32[40817] | 0;
+ $shl580 = 1 << $I539_0;
+ $and581 = $124 & $shl580;
+ $tobool582 = ($and581 | 0) == 0;
+ if ($tobool582) {
+ label = 121;
+ break;
+ } else {
+ label = 122;
+ break;
+ }
+ case 121:
+ $or586 = $124 | $shl580;
+ HEAP32[40817] = $or586;
+ HEAP32[$arrayidx573 >> 2] = $122;
+ $parent587 = $p_addr_0 + 24 | 0;
+ $_c = $arrayidx573;
+ HEAP32[$parent587 >> 2] = $_c;
+ $bk588 = $p_addr_0 + 12 | 0;
+ HEAP32[$bk588 >> 2] = $p_addr_0;
+ $fd589 = $p_addr_0 + 8 | 0;
+ HEAP32[$fd589 >> 2] = $p_addr_0;
+ label = 135;
+ break;
+ case 122:
+ $125 = HEAP32[$arrayidx573 >> 2] | 0;
+ $cmp592 = ($I539_0 | 0) == 31;
+ if ($cmp592) {
+ $cond = 0;
+ label = 124;
+ break;
+ } else {
+ label = 123;
+ break;
+ }
+ case 123:
+ $shr594 = $I539_0 >>> 1;
+ $sub597 = 25 - $shr594 | 0;
+ $cond = $sub597;
+ label = 124;
+ break;
+ case 124:
+ $shl598 = $psize_addr_1 << $cond;
+ $K591_0 = $shl598;
+ $T_0 = $125;
+ label = 125;
+ break;
+ case 125:
+ $head599 = $T_0 + 4 | 0;
+ $126 = HEAP32[$head599 >> 2] | 0;
+ $and600 = $126 & -8;
+ $cmp601 = ($and600 | 0) == ($psize_addr_1 | 0);
+ if ($cmp601) {
+ label = 130;
+ break;
+ } else {
+ label = 126;
+ break;
+ }
+ case 126:
+ $shr604 = $K591_0 >>> 31;
+ $arrayidx607 = $T_0 + 16 + ($shr604 << 2) | 0;
+ $127 = HEAP32[$arrayidx607 >> 2] | 0;
+ $cmp609 = ($127 | 0) == 0;
+ $shl608 = $K591_0 << 1;
+ if ($cmp609) {
+ label = 127;
+ break;
+ } else {
+ $K591_0 = $shl608;
+ $T_0 = $127;
+ label = 125;
+ break;
+ }
+ case 127:
+ $128 = $arrayidx607;
+ $129 = HEAP32[40820] | 0;
+ $cmp614 = $128 >>> 0 < $129 >>> 0;
+ if ($cmp614) {
+ label = 129;
+ break;
+ } else {
+ label = 128;
+ break;
+ }
+ case 128:
+ HEAP32[$arrayidx607 >> 2] = $122;
+ $parent619 = $p_addr_0 + 24 | 0;
+ $T_0_c9 = $T_0;
+ HEAP32[$parent619 >> 2] = $T_0_c9;
+ $bk620 = $p_addr_0 + 12 | 0;
+ HEAP32[$bk620 >> 2] = $p_addr_0;
+ $fd621 = $p_addr_0 + 8 | 0;
+ HEAP32[$fd621 >> 2] = $p_addr_0;
+ label = 135;
+ break;
+ case 129:
+ _abort();
+ case 130:
+ $fd626 = $T_0 + 8 | 0;
+ $130 = HEAP32[$fd626 >> 2] | 0;
+ $131 = $T_0;
+ $132 = HEAP32[40820] | 0;
+ $cmp628 = $131 >>> 0 < $132 >>> 0;
+ if ($cmp628) {
+ label = 133;
+ break;
+ } else {
+ label = 131;
+ break;
+ }
+ case 131:
+ $133 = $130;
+ $cmp632 = $133 >>> 0 < $132 >>> 0;
+ if ($cmp632) {
+ label = 133;
+ break;
+ } else {
+ label = 132;
+ break;
+ }
+ case 132:
+ $bk639 = $130 + 12 | 0;
+ HEAP32[$bk639 >> 2] = $122;
+ HEAP32[$fd626 >> 2] = $122;
+ $fd641 = $p_addr_0 + 8 | 0;
+ $_c8 = $130;
+ HEAP32[$fd641 >> 2] = $_c8;
+ $bk642 = $p_addr_0 + 12 | 0;
+ $T_0_c = $T_0;
+ HEAP32[$bk642 >> 2] = $T_0_c;
+ $parent643 = $p_addr_0 + 24 | 0;
+ HEAP32[$parent643 >> 2] = 0;
+ label = 135;
+ break;
+ case 133:
+ _abort();
+ case 134:
+ _abort();
+ case 135:
+ return;
+ }
+}
+function _init_top($p, $psize) {
+ $p = $p | 0;
+ $psize = $psize | 0;
+ var $0 = 0, $add_ptr = 0, $1 = 0, $and = 0, $cmp = 0, $2 = 0, $and3 = 0, $cond = 0, $add_ptr4 = 0, $3 = 0, $sub5 = 0, $or = 0, $add_ptr4_sum = 0, $head = 0, $4 = 0, $add_ptr6_sum = 0, $head7 = 0, $5 = 0, $6 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = $p;
+ $add_ptr = $p + 8 | 0;
+ $1 = $add_ptr;
+ $and = $1 & 7;
+ $cmp = ($and | 0) == 0;
+ if ($cmp) {
+ $cond = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $2 = -$1 | 0;
+ $and3 = $2 & 7;
+ $cond = $and3;
+ label = 4;
+ break;
+ case 4:
+ $add_ptr4 = $0 + $cond | 0;
+ $3 = $add_ptr4;
+ $sub5 = $psize - $cond | 0;
+ HEAP32[40822] = $3;
+ HEAP32[40819] = $sub5;
+ $or = $sub5 | 1;
+ $add_ptr4_sum = $cond + 4 | 0;
+ $head = $0 + $add_ptr4_sum | 0;
+ $4 = $head;
+ HEAP32[$4 >> 2] = $or;
+ $add_ptr6_sum = $psize + 4 | 0;
+ $head7 = $0 + $add_ptr6_sum | 0;
+ $5 = $head7;
+ HEAP32[$5 >> 2] = 40;
+ $6 = HEAP32[2806] | 0;
+ HEAP32[40823] = $6;
+ return;
+ }
+}
+function _init_bins() {
+ var $i_02 = 0, $shl = 0, $arrayidx = 0, $0 = 0, $arrayidx_sum = 0, $1 = 0, $arrayidx_sum1 = 0, $2 = 0, $inc = 0, $cmp = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $i_02 = 0;
+ label = 3;
+ break;
+ case 3:
+ $shl = $i_02 << 1;
+ $arrayidx = 163304 + ($shl << 2) | 0;
+ $0 = $arrayidx;
+ $arrayidx_sum = $shl + 3 | 0;
+ $1 = 163304 + ($arrayidx_sum << 2) | 0;
+ HEAP32[$1 >> 2] = $0;
+ $arrayidx_sum1 = $shl + 2 | 0;
+ $2 = 163304 + ($arrayidx_sum1 << 2) | 0;
+ HEAP32[$2 >> 2] = $0;
+ $inc = $i_02 + 1 | 0;
+ $cmp = $inc >>> 0 < 32;
+ if ($cmp) {
+ $i_02 = $inc;
+ label = 3;
+ break;
+ } else {
+ label = 4;
+ break;
+ }
+ case 4:
+ return;
+ }
+}
+function _prepend_alloc($newbase, $oldbase, $nb) {
+ $newbase = $newbase | 0;
+ $oldbase = $oldbase | 0;
+ $nb = $nb | 0;
+ var $add_ptr = 0, $0 = 0, $and = 0, $cmp = 0, $1 = 0, $and3 = 0, $cond = 0, $add_ptr4 = 0, $add_ptr5 = 0, $2 = 0, $and6 = 0, $cmp7 = 0, $3 = 0, $and13 = 0, $cond15 = 0, $add_ptr16 = 0, $4 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $add_ptr4_sum = 0, $add_ptr17 = 0, $5 = 0, $sub18 = 0, $or19 = 0, $add_ptr4_sum1 = 0, $head = 0, $6 = 0, $7 = 0, $cmp20 = 0, $8 = 0, $add = 0, $or22 = 0, $add_ptr17_sum39 = 0, $head23 = 0, $9 = 0, $10 = 0, $cmp24 = 0, $11 = 0, $add26 = 0, $or28 = 0, $add_ptr17_sum37 = 0, $head29 = 0, $12 = 0, $add_ptr17_sum38 = 0, $add_ptr30 = 0, $prev_foot = 0, $add_ptr16_sum = 0, $head32 = 0, $13 = 0, $14 = 0, $and33 = 0, $cmp34 = 0, $and37 = 0, $shr = 0, $cmp38 = 0, $add_ptr16_sum3233 = 0, $fd = 0, $15 = 0, $16 = 0, $add_ptr16_sum34 = 0, $bk = 0, $17 = 0, $18 = 0, $shl = 0, $arrayidx = 0, $19 = 0, $cmp41 = 0, $20 = 0, $21 = 0, $cmp42 = 0, $bk43 = 0, $22 = 0, $cmp44 = 0, $cmp46 = 0, $shl48 = 0, $neg = 0, $23 = 0, $and49 = 0, $cmp54 = 0, $24 = 0, $25 = 0, $cmp57 = 0, $fd59 = 0, $26 = 0, $cmp60 = 0, $bk67 = 0, $fd68 = 0, $27 = 0, $add_ptr16_sum23 = 0, $parent = 0, $28 = 0, $29 = 0, $add_ptr16_sum4 = 0, $bk74 = 0, $30 = 0, $31 = 0, $cmp75 = 0, $add_ptr16_sum2930 = 0, $fd78 = 0, $32 = 0, $33 = 0, $34 = 0, $35 = 0, $cmp81 = 0, $bk82 = 0, $36 = 0, $cmp83 = 0, $fd85 = 0, $37 = 0, $cmp86 = 0, $add_ptr16_sum56 = 0, $child_sum = 0, $arrayidx96 = 0, $38 = 0, $39 = 0, $cmp97 = 0, $child = 0, $arrayidx99 = 0, $40 = 0, $cmp100 = 0, $RP_0 = 0, $R_0 = 0, $arrayidx103 = 0, $41 = 0, $cmp104 = 0, $arrayidx107 = 0, $42 = 0, $cmp108 = 0, $CP_0 = 0, $43 = 0, $44 = 0, $45 = 0, $cmp112 = 0, $R_1 = 0, $cmp120 = 0, $add_ptr16_sum26 = 0, $index = 0, $46 = 0, $47 = 0, $arrayidx123 = 0, $48 = 0, $cmp124 = 0, $cond41 = 0, $49 = 0, $shl131 = 0, $neg132 = 0, $50 = 0, $and133 = 0, $51 = 0, $52 = 0, $cmp137 = 0, $arrayidx143 = 0, $53 = 0, $cmp144 = 0, $arrayidx151 = 0, $cmp156 = 0, $54 = 0, $55 = 0, $cmp160 = 0, $parent165 = 0, $add_ptr16_sum2728 = 0, $child166 = 0, $arrayidx167 = 0, $56 = 0, $cmp168 = 0, $57 = 0, $58 = 0, $cmp172 = 0, $arrayidx178 = 0, $parent179 = 0, $child166_sum = 0, $arrayidx184 = 0, $59 = 0, $60 = 0, $cmp185 = 0, $61 = 0, $62 = 0, $cmp189 = 0, $arrayidx195 = 0, $parent196 = 0, $add_ptr16_sum7 = 0, $add_ptr205 = 0, $63 = 0, $add206 = 0, $qsize_0 = 0, $oldfirst_0 = 0, $head208 = 0, $64 = 0, $and209 = 0, $or210 = 0, $add_ptr17_sum = 0, $head211 = 0, $65 = 0, $add_ptr17_sum8 = 0, $add_ptr212 = 0, $prev_foot213 = 0, $shr214 = 0, $cmp215 = 0, $shl221 = 0, $arrayidx223 = 0, $66 = 0, $67 = 0, $shl226 = 0, $and227 = 0, $tobool228 = 0, $or232 = 0, $arrayidx223_sum25 = 0, $68 = 0, $69 = 0, $70 = 0, $71 = 0, $cmp236 = 0, $F224_0 = 0, $arrayidx223_sum = 0, $72 = 0, $bk246 = 0, $add_ptr17_sum23 = 0, $fd247 = 0, $73 = 0, $add_ptr17_sum24 = 0, $bk248 = 0, $74 = 0, $75 = 0, $shr253 = 0, $cmp254 = 0, $cmp258 = 0, $sub262 = 0, $shr263 = 0, $and264 = 0, $shl265 = 0, $sub266 = 0, $shr267 = 0, $and268 = 0, $add269 = 0, $shl270 = 0, $sub271 = 0, $shr272 = 0, $and273 = 0, $add274 = 0, $sub275 = 0, $shl276 = 0, $shr277 = 0, $add278 = 0, $shl279 = 0, $add280 = 0, $shr281 = 0, $and282 = 0, $add283 = 0, $I252_0 = 0, $arrayidx287 = 0, $add_ptr17_sum9 = 0, $index288 = 0, $76 = 0, $add_ptr17_sum10 = 0, $child289 = 0, $child289_sum = 0, $arrayidx290 = 0, $77 = 0, $arrayidx292 = 0, $78 = 0, $shl294 = 0, $and295 = 0, $tobool296 = 0, $or300 = 0, $79 = 0, $add_ptr17_sum11 = 0, $parent301 = 0, $80 = 0, $add_ptr17_sum12 = 0, $bk302 = 0, $81 = 0, $add_ptr17_sum13 = 0, $fd303 = 0, $82 = 0, $83 = 0, $cmp306 = 0, $shr310 = 0, $sub313 = 0, $cond315 = 0, $shl316 = 0, $T_0 = 0, $K305_0 = 0, $head317 = 0, $84 = 0, $and318 = 0, $cmp319 = 0, $shr322 = 0, $arrayidx325 = 0, $85 = 0, $cmp327 = 0, $shl326 = 0, $86 = 0, $87 = 0, $cmp332 = 0, $add_ptr17_sum20 = 0, $parent337 = 0, $88 = 0, $add_ptr17_sum21 = 0, $bk338 = 0, $89 = 0, $add_ptr17_sum22 = 0, $fd339 = 0, $90 = 0, $fd344 = 0, $91 = 0, $92 = 0, $93 = 0, $cmp346 = 0, $94 = 0, $cmp350 = 0, $bk357 = 0, $add_ptr17_sum17 = 0, $fd359 = 0, $95 = 0, $add_ptr17_sum18 = 0, $bk360 = 0, $96 = 0, $add_ptr17_sum19 = 0, $parent361 = 0, $97 = 0, $add_ptr4_sum1415 = 0, $add_ptr368 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $add_ptr = $newbase + 8 | 0;
+ $0 = $add_ptr;
+ $and = $0 & 7;
+ $cmp = ($and | 0) == 0;
+ if ($cmp) {
+ $cond = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $1 = -$0 | 0;
+ $and3 = $1 & 7;
+ $cond = $and3;
+ label = 4;
+ break;
+ case 4:
+ $add_ptr4 = $newbase + $cond | 0;
+ $add_ptr5 = $oldbase + 8 | 0;
+ $2 = $add_ptr5;
+ $and6 = $2 & 7;
+ $cmp7 = ($and6 | 0) == 0;
+ if ($cmp7) {
+ $cond15 = 0;
+ label = 6;
+ break;
+ } else {
+ label = 5;
+ break;
+ }
+ case 5:
+ $3 = -$2 | 0;
+ $and13 = $3 & 7;
+ $cond15 = $and13;
+ label = 6;
+ break;
+ case 6:
+ $add_ptr16 = $oldbase + $cond15 | 0;
+ $4 = $add_ptr16;
+ $sub_ptr_lhs_cast = $add_ptr16;
+ $sub_ptr_rhs_cast = $add_ptr4;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $add_ptr4_sum = $cond + $nb | 0;
+ $add_ptr17 = $newbase + $add_ptr4_sum | 0;
+ $5 = $add_ptr17;
+ $sub18 = $sub_ptr_sub - $nb | 0;
+ $or19 = $nb | 3;
+ $add_ptr4_sum1 = $cond + 4 | 0;
+ $head = $newbase + $add_ptr4_sum1 | 0;
+ $6 = $head;
+ HEAP32[$6 >> 2] = $or19;
+ $7 = HEAP32[40822] | 0;
+ $cmp20 = ($4 | 0) == ($7 | 0);
+ if ($cmp20) {
+ label = 7;
+ break;
+ } else {
+ label = 8;
+ break;
+ }
+ case 7:
+ $8 = HEAP32[40819] | 0;
+ $add = $8 + $sub18 | 0;
+ HEAP32[40819] = $add;
+ HEAP32[40822] = $5;
+ $or22 = $add | 1;
+ $add_ptr17_sum39 = $add_ptr4_sum + 4 | 0;
+ $head23 = $newbase + $add_ptr17_sum39 | 0;
+ $9 = $head23;
+ HEAP32[$9 >> 2] = $or22;
+ label = 81;
+ break;
+ case 8:
+ $10 = HEAP32[40821] | 0;
+ $cmp24 = ($4 | 0) == ($10 | 0);
+ if ($cmp24) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $11 = HEAP32[40818] | 0;
+ $add26 = $11 + $sub18 | 0;
+ HEAP32[40818] = $add26;
+ HEAP32[40821] = $5;
+ $or28 = $add26 | 1;
+ $add_ptr17_sum37 = $add_ptr4_sum + 4 | 0;
+ $head29 = $newbase + $add_ptr17_sum37 | 0;
+ $12 = $head29;
+ HEAP32[$12 >> 2] = $or28;
+ $add_ptr17_sum38 = $add26 + $add_ptr4_sum | 0;
+ $add_ptr30 = $newbase + $add_ptr17_sum38 | 0;
+ $prev_foot = $add_ptr30;
+ HEAP32[$prev_foot >> 2] = $add26;
+ label = 81;
+ break;
+ case 10:
+ $add_ptr16_sum = $cond15 + 4 | 0;
+ $head32 = $oldbase + $add_ptr16_sum | 0;
+ $13 = $head32;
+ $14 = HEAP32[$13 >> 2] | 0;
+ $and33 = $14 & 3;
+ $cmp34 = ($and33 | 0) == 1;
+ if ($cmp34) {
+ label = 11;
+ break;
+ } else {
+ $oldfirst_0 = $4;
+ $qsize_0 = $sub18;
+ label = 58;
+ break;
+ }
+ case 11:
+ $and37 = $14 & -8;
+ $shr = $14 >>> 3;
+ $cmp38 = $14 >>> 0 < 256;
+ if ($cmp38) {
+ label = 12;
+ break;
+ } else {
+ label = 23;
+ break;
+ }
+ case 12:
+ $add_ptr16_sum3233 = $cond15 | 8;
+ $fd = $oldbase + $add_ptr16_sum3233 | 0;
+ $15 = $fd;
+ $16 = HEAP32[$15 >> 2] | 0;
+ $add_ptr16_sum34 = $cond15 + 12 | 0;
+ $bk = $oldbase + $add_ptr16_sum34 | 0;
+ $17 = $bk;
+ $18 = HEAP32[$17 >> 2] | 0;
+ $shl = $shr << 1;
+ $arrayidx = 163304 + ($shl << 2) | 0;
+ $19 = $arrayidx;
+ $cmp41 = ($16 | 0) == ($19 | 0);
+ if ($cmp41) {
+ label = 15;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 13:
+ $20 = $16;
+ $21 = HEAP32[40820] | 0;
+ $cmp42 = $20 >>> 0 < $21 >>> 0;
+ if ($cmp42) {
+ label = 22;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $bk43 = $16 + 12 | 0;
+ $22 = HEAP32[$bk43 >> 2] | 0;
+ $cmp44 = ($22 | 0) == ($4 | 0);
+ if ($cmp44) {
+ label = 15;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 15:
+ $cmp46 = ($18 | 0) == ($16 | 0);
+ if ($cmp46) {
+ label = 16;
+ break;
+ } else {
+ label = 17;
+ break;
+ }
+ case 16:
+ $shl48 = 1 << $shr;
+ $neg = $shl48 ^ -1;
+ $23 = HEAP32[40816] | 0;
+ $and49 = $23 & $neg;
+ HEAP32[40816] = $and49;
+ label = 57;
+ break;
+ case 17:
+ $cmp54 = ($18 | 0) == ($19 | 0);
+ if ($cmp54) {
+ label = 20;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 18:
+ $24 = $18;
+ $25 = HEAP32[40820] | 0;
+ $cmp57 = $24 >>> 0 < $25 >>> 0;
+ if ($cmp57) {
+ label = 21;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $fd59 = $18 + 8 | 0;
+ $26 = HEAP32[$fd59 >> 2] | 0;
+ $cmp60 = ($26 | 0) == ($4 | 0);
+ if ($cmp60) {
+ label = 20;
+ break;
+ } else {
+ label = 21;
+ break;
+ }
+ case 20:
+ $bk67 = $16 + 12 | 0;
+ HEAP32[$bk67 >> 2] = $18;
+ $fd68 = $18 + 8 | 0;
+ HEAP32[$fd68 >> 2] = $16;
+ label = 57;
+ break;
+ case 21:
+ _abort();
+ return 0;
+ return 0;
+ case 22:
+ _abort();
+ return 0;
+ return 0;
+ case 23:
+ $27 = $add_ptr16;
+ $add_ptr16_sum23 = $cond15 | 24;
+ $parent = $oldbase + $add_ptr16_sum23 | 0;
+ $28 = $parent;
+ $29 = HEAP32[$28 >> 2] | 0;
+ $add_ptr16_sum4 = $cond15 + 12 | 0;
+ $bk74 = $oldbase + $add_ptr16_sum4 | 0;
+ $30 = $bk74;
+ $31 = HEAP32[$30 >> 2] | 0;
+ $cmp75 = ($31 | 0) == ($27 | 0);
+ if ($cmp75) {
+ label = 29;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ $add_ptr16_sum2930 = $cond15 | 8;
+ $fd78 = $oldbase + $add_ptr16_sum2930 | 0;
+ $32 = $fd78;
+ $33 = HEAP32[$32 >> 2] | 0;
+ $34 = $33;
+ $35 = HEAP32[40820] | 0;
+ $cmp81 = $34 >>> 0 < $35 >>> 0;
+ if ($cmp81) {
+ label = 28;
+ break;
+ } else {
+ label = 25;
+ break;
+ }
+ case 25:
+ $bk82 = $33 + 12 | 0;
+ $36 = HEAP32[$bk82 >> 2] | 0;
+ $cmp83 = ($36 | 0) == ($27 | 0);
+ if ($cmp83) {
+ label = 26;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 26:
+ $fd85 = $31 + 8 | 0;
+ $37 = HEAP32[$fd85 >> 2] | 0;
+ $cmp86 = ($37 | 0) == ($27 | 0);
+ if ($cmp86) {
+ label = 27;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 27:
+ HEAP32[$bk82 >> 2] = $31;
+ HEAP32[$fd85 >> 2] = $33;
+ $R_1 = $31;
+ label = 37;
+ break;
+ case 28:
+ _abort();
+ return 0;
+ return 0;
+ case 29:
+ $add_ptr16_sum56 = $cond15 | 16;
+ $child_sum = $add_ptr16_sum56 + 4 | 0;
+ $arrayidx96 = $oldbase + $child_sum | 0;
+ $38 = $arrayidx96;
+ $39 = HEAP32[$38 >> 2] | 0;
+ $cmp97 = ($39 | 0) == 0;
+ if ($cmp97) {
+ label = 30;
+ break;
+ } else {
+ $R_0 = $39;
+ $RP_0 = $38;
+ label = 31;
+ break;
+ }
+ case 30:
+ $child = $oldbase + $add_ptr16_sum56 | 0;
+ $arrayidx99 = $child;
+ $40 = HEAP32[$arrayidx99 >> 2] | 0;
+ $cmp100 = ($40 | 0) == 0;
+ if ($cmp100) {
+ $R_1 = 0;
+ label = 37;
+ break;
+ } else {
+ $R_0 = $40;
+ $RP_0 = $arrayidx99;
+ label = 31;
+ break;
+ }
+ case 31:
+ $arrayidx103 = $R_0 + 20 | 0;
+ $41 = HEAP32[$arrayidx103 >> 2] | 0;
+ $cmp104 = ($41 | 0) == 0;
+ if ($cmp104) {
+ label = 32;
+ break;
+ } else {
+ $CP_0 = $arrayidx103;
+ label = 33;
+ break;
+ }
+ case 32:
+ $arrayidx107 = $R_0 + 16 | 0;
+ $42 = HEAP32[$arrayidx107 >> 2] | 0;
+ $cmp108 = ($42 | 0) == 0;
+ if ($cmp108) {
+ label = 34;
+ break;
+ } else {
+ $CP_0 = $arrayidx107;
+ label = 33;
+ break;
+ }
+ case 33:
+ $43 = HEAP32[$CP_0 >> 2] | 0;
+ $R_0 = $43;
+ $RP_0 = $CP_0;
+ label = 31;
+ break;
+ case 34:
+ $44 = $RP_0;
+ $45 = HEAP32[40820] | 0;
+ $cmp112 = $44 >>> 0 < $45 >>> 0;
+ if ($cmp112) {
+ label = 36;
+ break;
+ } else {
+ label = 35;
+ break;
+ }
+ case 35:
+ HEAP32[$RP_0 >> 2] = 0;
+ $R_1 = $R_0;
+ label = 37;
+ break;
+ case 36:
+ _abort();
+ return 0;
+ return 0;
+ case 37:
+ $cmp120 = ($29 | 0) == 0;
+ if ($cmp120) {
+ label = 57;
+ break;
+ } else {
+ label = 38;
+ break;
+ }
+ case 38:
+ $add_ptr16_sum26 = $cond15 + 28 | 0;
+ $index = $oldbase + $add_ptr16_sum26 | 0;
+ $46 = $index;
+ $47 = HEAP32[$46 >> 2] | 0;
+ $arrayidx123 = 163568 + ($47 << 2) | 0;
+ $48 = HEAP32[$arrayidx123 >> 2] | 0;
+ $cmp124 = ($27 | 0) == ($48 | 0);
+ if ($cmp124) {
+ label = 39;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 39:
+ HEAP32[$arrayidx123 >> 2] = $R_1;
+ $cond41 = ($R_1 | 0) == 0;
+ if ($cond41) {
+ label = 40;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 40:
+ $49 = HEAP32[$46 >> 2] | 0;
+ $shl131 = 1 << $49;
+ $neg132 = $shl131 ^ -1;
+ $50 = HEAP32[40817] | 0;
+ $and133 = $50 & $neg132;
+ HEAP32[40817] = $and133;
+ label = 57;
+ break;
+ case 41:
+ $51 = $29;
+ $52 = HEAP32[40820] | 0;
+ $cmp137 = $51 >>> 0 < $52 >>> 0;
+ if ($cmp137) {
+ label = 45;
+ break;
+ } else {
+ label = 42;
+ break;
+ }
+ case 42:
+ $arrayidx143 = $29 + 16 | 0;
+ $53 = HEAP32[$arrayidx143 >> 2] | 0;
+ $cmp144 = ($53 | 0) == ($27 | 0);
+ if ($cmp144) {
+ label = 43;
+ break;
+ } else {
+ label = 44;
+ break;
+ }
+ case 43:
+ HEAP32[$arrayidx143 >> 2] = $R_1;
+ label = 46;
+ break;
+ case 44:
+ $arrayidx151 = $29 + 20 | 0;
+ HEAP32[$arrayidx151 >> 2] = $R_1;
+ label = 46;
+ break;
+ case 45:
+ _abort();
+ return 0;
+ return 0;
+ case 46:
+ $cmp156 = ($R_1 | 0) == 0;
+ if ($cmp156) {
+ label = 57;
+ break;
+ } else {
+ label = 47;
+ break;
+ }
+ case 47:
+ $54 = $R_1;
+ $55 = HEAP32[40820] | 0;
+ $cmp160 = $54 >>> 0 < $55 >>> 0;
+ if ($cmp160) {
+ label = 56;
+ break;
+ } else {
+ label = 48;
+ break;
+ }
+ case 48:
+ $parent165 = $R_1 + 24 | 0;
+ HEAP32[$parent165 >> 2] = $29;
+ $add_ptr16_sum2728 = $cond15 | 16;
+ $child166 = $oldbase + $add_ptr16_sum2728 | 0;
+ $arrayidx167 = $child166;
+ $56 = HEAP32[$arrayidx167 >> 2] | 0;
+ $cmp168 = ($56 | 0) == 0;
+ if ($cmp168) {
+ label = 52;
+ break;
+ } else {
+ label = 49;
+ break;
+ }
+ case 49:
+ $57 = $56;
+ $58 = HEAP32[40820] | 0;
+ $cmp172 = $57 >>> 0 < $58 >>> 0;
+ if ($cmp172) {
+ label = 51;
+ break;
+ } else {
+ label = 50;
+ break;
+ }
+ case 50:
+ $arrayidx178 = $R_1 + 16 | 0;
+ HEAP32[$arrayidx178 >> 2] = $56;
+ $parent179 = $56 + 24 | 0;
+ HEAP32[$parent179 >> 2] = $R_1;
+ label = 52;
+ break;
+ case 51:
+ _abort();
+ return 0;
+ return 0;
+ case 52:
+ $child166_sum = $add_ptr16_sum2728 + 4 | 0;
+ $arrayidx184 = $oldbase + $child166_sum | 0;
+ $59 = $arrayidx184;
+ $60 = HEAP32[$59 >> 2] | 0;
+ $cmp185 = ($60 | 0) == 0;
+ if ($cmp185) {
+ label = 57;
+ break;
+ } else {
+ label = 53;
+ break;
+ }
+ case 53:
+ $61 = $60;
+ $62 = HEAP32[40820] | 0;
+ $cmp189 = $61 >>> 0 < $62 >>> 0;
+ if ($cmp189) {
+ label = 55;
+ break;
+ } else {
+ label = 54;
+ break;
+ }
+ case 54:
+ $arrayidx195 = $R_1 + 20 | 0;
+ HEAP32[$arrayidx195 >> 2] = $60;
+ $parent196 = $60 + 24 | 0;
+ HEAP32[$parent196 >> 2] = $R_1;
+ label = 57;
+ break;
+ case 55:
+ _abort();
+ return 0;
+ return 0;
+ case 56:
+ _abort();
+ return 0;
+ return 0;
+ case 57:
+ $add_ptr16_sum7 = $and37 | $cond15;
+ $add_ptr205 = $oldbase + $add_ptr16_sum7 | 0;
+ $63 = $add_ptr205;
+ $add206 = $and37 + $sub18 | 0;
+ $oldfirst_0 = $63;
+ $qsize_0 = $add206;
+ label = 58;
+ break;
+ case 58:
+ $head208 = $oldfirst_0 + 4 | 0;
+ $64 = HEAP32[$head208 >> 2] | 0;
+ $and209 = $64 & -2;
+ HEAP32[$head208 >> 2] = $and209;
+ $or210 = $qsize_0 | 1;
+ $add_ptr17_sum = $add_ptr4_sum + 4 | 0;
+ $head211 = $newbase + $add_ptr17_sum | 0;
+ $65 = $head211;
+ HEAP32[$65 >> 2] = $or210;
+ $add_ptr17_sum8 = $qsize_0 + $add_ptr4_sum | 0;
+ $add_ptr212 = $newbase + $add_ptr17_sum8 | 0;
+ $prev_foot213 = $add_ptr212;
+ HEAP32[$prev_foot213 >> 2] = $qsize_0;
+ $shr214 = $qsize_0 >>> 3;
+ $cmp215 = $qsize_0 >>> 0 < 256;
+ if ($cmp215) {
+ label = 59;
+ break;
+ } else {
+ label = 64;
+ break;
+ }
+ case 59:
+ $shl221 = $shr214 << 1;
+ $arrayidx223 = 163304 + ($shl221 << 2) | 0;
+ $66 = $arrayidx223;
+ $67 = HEAP32[40816] | 0;
+ $shl226 = 1 << $shr214;
+ $and227 = $67 & $shl226;
+ $tobool228 = ($and227 | 0) == 0;
+ if ($tobool228) {
+ label = 60;
+ break;
+ } else {
+ label = 61;
+ break;
+ }
+ case 60:
+ $or232 = $67 | $shl226;
+ HEAP32[40816] = $or232;
+ $F224_0 = $66;
+ label = 63;
+ break;
+ case 61:
+ $arrayidx223_sum25 = $shl221 + 2 | 0;
+ $68 = 163304 + ($arrayidx223_sum25 << 2) | 0;
+ $69 = HEAP32[$68 >> 2] | 0;
+ $70 = $69;
+ $71 = HEAP32[40820] | 0;
+ $cmp236 = $70 >>> 0 < $71 >>> 0;
+ if ($cmp236) {
+ label = 62;
+ break;
+ } else {
+ $F224_0 = $69;
+ label = 63;
+ break;
+ }
+ case 62:
+ _abort();
+ return 0;
+ return 0;
+ case 63:
+ $arrayidx223_sum = $shl221 + 2 | 0;
+ $72 = 163304 + ($arrayidx223_sum << 2) | 0;
+ HEAP32[$72 >> 2] = $5;
+ $bk246 = $F224_0 + 12 | 0;
+ HEAP32[$bk246 >> 2] = $5;
+ $add_ptr17_sum23 = $add_ptr4_sum + 8 | 0;
+ $fd247 = $newbase + $add_ptr17_sum23 | 0;
+ $73 = $fd247;
+ HEAP32[$73 >> 2] = $F224_0;
+ $add_ptr17_sum24 = $add_ptr4_sum + 12 | 0;
+ $bk248 = $newbase + $add_ptr17_sum24 | 0;
+ $74 = $bk248;
+ HEAP32[$74 >> 2] = $66;
+ label = 81;
+ break;
+ case 64:
+ $75 = $add_ptr17;
+ $shr253 = $qsize_0 >>> 8;
+ $cmp254 = ($shr253 | 0) == 0;
+ if ($cmp254) {
+ $I252_0 = 0;
+ label = 67;
+ break;
+ } else {
+ label = 65;
+ break;
+ }
+ case 65:
+ $cmp258 = $qsize_0 >>> 0 > 16777215;
+ if ($cmp258) {
+ $I252_0 = 31;
+ label = 67;
+ break;
+ } else {
+ label = 66;
+ break;
+ }
+ case 66:
+ $sub262 = $shr253 + 1048320 | 0;
+ $shr263 = $sub262 >>> 16;
+ $and264 = $shr263 & 8;
+ $shl265 = $shr253 << $and264;
+ $sub266 = $shl265 + 520192 | 0;
+ $shr267 = $sub266 >>> 16;
+ $and268 = $shr267 & 4;
+ $add269 = $and268 | $and264;
+ $shl270 = $shl265 << $and268;
+ $sub271 = $shl270 + 245760 | 0;
+ $shr272 = $sub271 >>> 16;
+ $and273 = $shr272 & 2;
+ $add274 = $add269 | $and273;
+ $sub275 = 14 - $add274 | 0;
+ $shl276 = $shl270 << $and273;
+ $shr277 = $shl276 >>> 15;
+ $add278 = $sub275 + $shr277 | 0;
+ $shl279 = $add278 << 1;
+ $add280 = $add278 + 7 | 0;
+ $shr281 = $qsize_0 >>> ($add280 >>> 0);
+ $and282 = $shr281 & 1;
+ $add283 = $and282 | $shl279;
+ $I252_0 = $add283;
+ label = 67;
+ break;
+ case 67:
+ $arrayidx287 = 163568 + ($I252_0 << 2) | 0;
+ $add_ptr17_sum9 = $add_ptr4_sum + 28 | 0;
+ $index288 = $newbase + $add_ptr17_sum9 | 0;
+ $76 = $index288;
+ HEAP32[$76 >> 2] = $I252_0;
+ $add_ptr17_sum10 = $add_ptr4_sum + 16 | 0;
+ $child289 = $newbase + $add_ptr17_sum10 | 0;
+ $child289_sum = $add_ptr4_sum + 20 | 0;
+ $arrayidx290 = $newbase + $child289_sum | 0;
+ $77 = $arrayidx290;
+ HEAP32[$77 >> 2] = 0;
+ $arrayidx292 = $child289;
+ HEAP32[$arrayidx292 >> 2] = 0;
+ $78 = HEAP32[40817] | 0;
+ $shl294 = 1 << $I252_0;
+ $and295 = $78 & $shl294;
+ $tobool296 = ($and295 | 0) == 0;
+ if ($tobool296) {
+ label = 68;
+ break;
+ } else {
+ label = 69;
+ break;
+ }
+ case 68:
+ $or300 = $78 | $shl294;
+ HEAP32[40817] = $or300;
+ HEAP32[$arrayidx287 >> 2] = $75;
+ $79 = $arrayidx287;
+ $add_ptr17_sum11 = $add_ptr4_sum + 24 | 0;
+ $parent301 = $newbase + $add_ptr17_sum11 | 0;
+ $80 = $parent301;
+ HEAP32[$80 >> 2] = $79;
+ $add_ptr17_sum12 = $add_ptr4_sum + 12 | 0;
+ $bk302 = $newbase + $add_ptr17_sum12 | 0;
+ $81 = $bk302;
+ HEAP32[$81 >> 2] = $75;
+ $add_ptr17_sum13 = $add_ptr4_sum + 8 | 0;
+ $fd303 = $newbase + $add_ptr17_sum13 | 0;
+ $82 = $fd303;
+ HEAP32[$82 >> 2] = $75;
+ label = 81;
+ break;
+ case 69:
+ $83 = HEAP32[$arrayidx287 >> 2] | 0;
+ $cmp306 = ($I252_0 | 0) == 31;
+ if ($cmp306) {
+ $cond315 = 0;
+ label = 71;
+ break;
+ } else {
+ label = 70;
+ break;
+ }
+ case 70:
+ $shr310 = $I252_0 >>> 1;
+ $sub313 = 25 - $shr310 | 0;
+ $cond315 = $sub313;
+ label = 71;
+ break;
+ case 71:
+ $shl316 = $qsize_0 << $cond315;
+ $K305_0 = $shl316;
+ $T_0 = $83;
+ label = 72;
+ break;
+ case 72:
+ $head317 = $T_0 + 4 | 0;
+ $84 = HEAP32[$head317 >> 2] | 0;
+ $and318 = $84 & -8;
+ $cmp319 = ($and318 | 0) == ($qsize_0 | 0);
+ if ($cmp319) {
+ label = 77;
+ break;
+ } else {
+ label = 73;
+ break;
+ }
+ case 73:
+ $shr322 = $K305_0 >>> 31;
+ $arrayidx325 = $T_0 + 16 + ($shr322 << 2) | 0;
+ $85 = HEAP32[$arrayidx325 >> 2] | 0;
+ $cmp327 = ($85 | 0) == 0;
+ $shl326 = $K305_0 << 1;
+ if ($cmp327) {
+ label = 74;
+ break;
+ } else {
+ $K305_0 = $shl326;
+ $T_0 = $85;
+ label = 72;
+ break;
+ }
+ case 74:
+ $86 = $arrayidx325;
+ $87 = HEAP32[40820] | 0;
+ $cmp332 = $86 >>> 0 < $87 >>> 0;
+ if ($cmp332) {
+ label = 76;
+ break;
+ } else {
+ label = 75;
+ break;
+ }
+ case 75:
+ HEAP32[$arrayidx325 >> 2] = $75;
+ $add_ptr17_sum20 = $add_ptr4_sum + 24 | 0;
+ $parent337 = $newbase + $add_ptr17_sum20 | 0;
+ $88 = $parent337;
+ HEAP32[$88 >> 2] = $T_0;
+ $add_ptr17_sum21 = $add_ptr4_sum + 12 | 0;
+ $bk338 = $newbase + $add_ptr17_sum21 | 0;
+ $89 = $bk338;
+ HEAP32[$89 >> 2] = $75;
+ $add_ptr17_sum22 = $add_ptr4_sum + 8 | 0;
+ $fd339 = $newbase + $add_ptr17_sum22 | 0;
+ $90 = $fd339;
+ HEAP32[$90 >> 2] = $75;
+ label = 81;
+ break;
+ case 76:
+ _abort();
+ return 0;
+ return 0;
+ case 77:
+ $fd344 = $T_0 + 8 | 0;
+ $91 = HEAP32[$fd344 >> 2] | 0;
+ $92 = $T_0;
+ $93 = HEAP32[40820] | 0;
+ $cmp346 = $92 >>> 0 < $93 >>> 0;
+ if ($cmp346) {
+ label = 80;
+ break;
+ } else {
+ label = 78;
+ break;
+ }
+ case 78:
+ $94 = $91;
+ $cmp350 = $94 >>> 0 < $93 >>> 0;
+ if ($cmp350) {
+ label = 80;
+ break;
+ } else {
+ label = 79;
+ break;
+ }
+ case 79:
+ $bk357 = $91 + 12 | 0;
+ HEAP32[$bk357 >> 2] = $75;
+ HEAP32[$fd344 >> 2] = $75;
+ $add_ptr17_sum17 = $add_ptr4_sum + 8 | 0;
+ $fd359 = $newbase + $add_ptr17_sum17 | 0;
+ $95 = $fd359;
+ HEAP32[$95 >> 2] = $91;
+ $add_ptr17_sum18 = $add_ptr4_sum + 12 | 0;
+ $bk360 = $newbase + $add_ptr17_sum18 | 0;
+ $96 = $bk360;
+ HEAP32[$96 >> 2] = $T_0;
+ $add_ptr17_sum19 = $add_ptr4_sum + 24 | 0;
+ $parent361 = $newbase + $add_ptr17_sum19 | 0;
+ $97 = $parent361;
+ HEAP32[$97 >> 2] = 0;
+ label = 81;
+ break;
+ case 80:
+ _abort();
+ return 0;
+ return 0;
+ case 81:
+ $add_ptr4_sum1415 = $cond | 8;
+ $add_ptr368 = $newbase + $add_ptr4_sum1415 | 0;
+ return $add_ptr368 | 0;
+ }
+ return 0;
+}
+function _add_segment($tbase, $tsize) {
+ $tbase = $tbase | 0;
+ $tsize = $tsize | 0;
+ var $0 = 0, $1 = 0, $call = 0, $base = 0, $2 = 0, $size = 0, $3 = 0, $add_ptr = 0, $add_ptr_sum = 0, $add_ptr2_sum = 0, $add_ptr3 = 0, $4 = 0, $and = 0, $cmp = 0, $5 = 0, $and6 = 0, $cond = 0, $add_ptr2_sum1 = 0, $add_ptr7 = 0, $add_ptr82 = 0, $add_ptr8 = 0, $cmp9 = 0, $cond13 = 0, $add_ptr14 = 0, $6 = 0, $7 = 0, $sub16 = 0, $head = 0, $8 = 0, $add_ptr2412 = 0, $9 = 0, $10 = 0, $cmp2713 = 0, $add_ptr2414 = 0, $11 = 0, $12 = 0, $13 = 0, $cmp27 = 0, $cmp28 = 0, $sub_ptr_lhs_cast = 0, $sub_ptr_rhs_cast = 0, $sub_ptr_sub = 0, $add_ptr30 = 0, $add_ptr30_sum = 0, $head31 = 0, $14 = 0, $15 = 0, $and32 = 0, $or33 = 0, $head34 = 0, $prev_foot = 0, $shr = 0, $cmp36 = 0, $shl = 0, $arrayidx = 0, $16 = 0, $17 = 0, $shl39 = 0, $and40 = 0, $tobool = 0, $or44 = 0, $arrayidx_sum10 = 0, $18 = 0, $19 = 0, $20 = 0, $21 = 0, $cmp46 = 0, $F_0 = 0, $arrayidx_sum = 0, $22 = 0, $bk = 0, $fd54 = 0, $bk55 = 0, $23 = 0, $shr58 = 0, $cmp59 = 0, $cmp63 = 0, $sub67 = 0, $shr68 = 0, $and69 = 0, $shl70 = 0, $sub71 = 0, $shr72 = 0, $and73 = 0, $add74 = 0, $shl75 = 0, $sub76 = 0, $shr77 = 0, $and78 = 0, $add79 = 0, $sub80 = 0, $shl81 = 0, $shr82 = 0, $add83 = 0, $shl84 = 0, $add85 = 0, $shr86 = 0, $and87 = 0, $add88 = 0, $I57_0 = 0, $arrayidx91 = 0, $index = 0, $I57_0_c = 0, $arrayidx92 = 0, $24 = 0, $25 = 0, $shl95 = 0, $and96 = 0, $tobool97 = 0, $or101 = 0, $parent = 0, $_c = 0, $bk102 = 0, $fd103 = 0, $26 = 0, $cmp106 = 0, $shr110 = 0, $sub113 = 0, $cond115 = 0, $shl116 = 0, $T_0 = 0, $K105_0 = 0, $head118 = 0, $27 = 0, $and119 = 0, $cmp120 = 0, $shr123 = 0, $arrayidx126 = 0, $28 = 0, $cmp128 = 0, $shl127 = 0, $29 = 0, $30 = 0, $cmp133 = 0, $parent138 = 0, $T_0_c7 = 0, $bk139 = 0, $fd140 = 0, $fd145 = 0, $31 = 0, $32 = 0, $33 = 0, $cmp147 = 0, $34 = 0, $cmp150 = 0, $bk155 = 0, $fd157 = 0, $_c6 = 0, $bk158 = 0, $T_0_c = 0, $parent159 = 0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $0 = HEAP32[40822] | 0;
+ $1 = $0;
+ $call = _segment_holding($1) | 0;
+ $base = $call | 0;
+ $2 = HEAP32[$base >> 2] | 0;
+ $size = $call + 4 | 0;
+ $3 = HEAP32[$size >> 2] | 0;
+ $add_ptr = $2 + $3 | 0;
+ $add_ptr_sum = $3 - 47 | 0;
+ $add_ptr2_sum = $3 - 39 | 0;
+ $add_ptr3 = $2 + $add_ptr2_sum | 0;
+ $4 = $add_ptr3;
+ $and = $4 & 7;
+ $cmp = ($and | 0) == 0;
+ if ($cmp) {
+ $cond = 0;
+ label = 4;
+ break;
+ } else {
+ label = 3;
+ break;
+ }
+ case 3:
+ $5 = -$4 | 0;
+ $and6 = $5 & 7;
+ $cond = $and6;
+ label = 4;
+ break;
+ case 4:
+ $add_ptr2_sum1 = $add_ptr_sum + $cond | 0;
+ $add_ptr7 = $2 + $add_ptr2_sum1 | 0;
+ $add_ptr82 = $0 + 16 | 0;
+ $add_ptr8 = $add_ptr82;
+ $cmp9 = $add_ptr7 >>> 0 < $add_ptr8 >>> 0;
+ $cond13 = $cmp9 ? $1 : $add_ptr7;
+ $add_ptr14 = $cond13 + 8 | 0;
+ $6 = $add_ptr14;
+ $7 = $tbase;
+ $sub16 = $tsize - 40 | 0;
+ _init_top($7, $sub16);
+ $head = $cond13 + 4 | 0;
+ $8 = $head;
+ HEAP32[$8 >> 2] = 27;
+ HEAP32[$add_ptr14 >> 2] = HEAP32[40928] | 0;
+ HEAP32[$add_ptr14 + 4 >> 2] = HEAP32[163716 >> 2] | 0;
+ HEAP32[$add_ptr14 + 8 >> 2] = HEAP32[163720 >> 2] | 0;
+ HEAP32[$add_ptr14 + 12 >> 2] = HEAP32[163724 >> 2] | 0;
+ HEAP32[40928] = $tbase;
+ HEAP32[40929] = $tsize;
+ HEAP32[40931] = 0;
+ HEAP32[40930] = $6;
+ $add_ptr2412 = $cond13 + 28 | 0;
+ $9 = $add_ptr2412;
+ HEAP32[$9 >> 2] = 7;
+ $10 = $cond13 + 32 | 0;
+ $cmp2713 = $10 >>> 0 < $add_ptr >>> 0;
+ if ($cmp2713) {
+ $add_ptr2414 = $9;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 5:
+ $11 = $add_ptr2414 + 4 | 0;
+ HEAP32[$11 >> 2] = 7;
+ $12 = $add_ptr2414 + 8 | 0;
+ $13 = $12;
+ $cmp27 = $13 >>> 0 < $add_ptr >>> 0;
+ if ($cmp27) {
+ $add_ptr2414 = $11;
+ label = 5;
+ break;
+ } else {
+ label = 6;
+ break;
+ }
+ case 6:
+ $cmp28 = ($cond13 | 0) == ($1 | 0);
+ if ($cmp28) {
+ label = 30;
+ break;
+ } else {
+ label = 7;
+ break;
+ }
+ case 7:
+ $sub_ptr_lhs_cast = $cond13;
+ $sub_ptr_rhs_cast = $0;
+ $sub_ptr_sub = $sub_ptr_lhs_cast - $sub_ptr_rhs_cast | 0;
+ $add_ptr30 = $1 + $sub_ptr_sub | 0;
+ $add_ptr30_sum = $sub_ptr_sub + 4 | 0;
+ $head31 = $1 + $add_ptr30_sum | 0;
+ $14 = $head31;
+ $15 = HEAP32[$14 >> 2] | 0;
+ $and32 = $15 & -2;
+ HEAP32[$14 >> 2] = $and32;
+ $or33 = $sub_ptr_sub | 1;
+ $head34 = $0 + 4 | 0;
+ HEAP32[$head34 >> 2] = $or33;
+ $prev_foot = $add_ptr30;
+ HEAP32[$prev_foot >> 2] = $sub_ptr_sub;
+ $shr = $sub_ptr_sub >>> 3;
+ $cmp36 = $sub_ptr_sub >>> 0 < 256;
+ if ($cmp36) {
+ label = 8;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 8:
+ $shl = $shr << 1;
+ $arrayidx = 163304 + ($shl << 2) | 0;
+ $16 = $arrayidx;
+ $17 = HEAP32[40816] | 0;
+ $shl39 = 1 << $shr;
+ $and40 = $17 & $shl39;
+ $tobool = ($and40 | 0) == 0;
+ if ($tobool) {
+ label = 9;
+ break;
+ } else {
+ label = 10;
+ break;
+ }
+ case 9:
+ $or44 = $17 | $shl39;
+ HEAP32[40816] = $or44;
+ $F_0 = $16;
+ label = 12;
+ break;
+ case 10:
+ $arrayidx_sum10 = $shl + 2 | 0;
+ $18 = 163304 + ($arrayidx_sum10 << 2) | 0;
+ $19 = HEAP32[$18 >> 2] | 0;
+ $20 = $19;
+ $21 = HEAP32[40820] | 0;
+ $cmp46 = $20 >>> 0 < $21 >>> 0;
+ if ($cmp46) {
+ label = 11;
+ break;
+ } else {
+ $F_0 = $19;
+ label = 12;
+ break;
+ }
+ case 11:
+ _abort();
+ case 12:
+ $arrayidx_sum = $shl + 2 | 0;
+ $22 = 163304 + ($arrayidx_sum << 2) | 0;
+ HEAP32[$22 >> 2] = $0;
+ $bk = $F_0 + 12 | 0;
+ HEAP32[$bk >> 2] = $0;
+ $fd54 = $0 + 8 | 0;
+ HEAP32[$fd54 >> 2] = $F_0;
+ $bk55 = $0 + 12 | 0;
+ HEAP32[$bk55 >> 2] = $16;
+ label = 30;
+ break;
+ case 13:
+ $23 = $0;
+ $shr58 = $sub_ptr_sub >>> 8;
+ $cmp59 = ($shr58 | 0) == 0;
+ if ($cmp59) {
+ $I57_0 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 14:
+ $cmp63 = $sub_ptr_sub >>> 0 > 16777215;
+ if ($cmp63) {
+ $I57_0 = 31;
+ label = 16;
+ break;
+ } else {
+ label = 15;
+ break;
+ }
+ case 15:
+ $sub67 = $shr58 + 1048320 | 0;
+ $shr68 = $sub67 >>> 16;
+ $and69 = $shr68 & 8;
+ $shl70 = $shr58 << $and69;
+ $sub71 = $shl70 + 520192 | 0;
+ $shr72 = $sub71 >>> 16;
+ $and73 = $shr72 & 4;
+ $add74 = $and73 | $and69;
+ $shl75 = $shl70 << $and73;
+ $sub76 = $shl75 + 245760 | 0;
+ $shr77 = $sub76 >>> 16;
+ $and78 = $shr77 & 2;
+ $add79 = $add74 | $and78;
+ $sub80 = 14 - $add79 | 0;
+ $shl81 = $shl75 << $and78;
+ $shr82 = $shl81 >>> 15;
+ $add83 = $sub80 + $shr82 | 0;
+ $shl84 = $add83 << 1;
+ $add85 = $add83 + 7 | 0;
+ $shr86 = $sub_ptr_sub >>> ($add85 >>> 0);
+ $and87 = $shr86 & 1;
+ $add88 = $and87 | $shl84;
+ $I57_0 = $add88;
+ label = 16;
+ break;
+ case 16:
+ $arrayidx91 = 163568 + ($I57_0 << 2) | 0;
+ $index = $0 + 28 | 0;
+ $I57_0_c = $I57_0;
+ HEAP32[$index >> 2] = $I57_0_c;
+ $arrayidx92 = $0 + 20 | 0;
+ HEAP32[$arrayidx92 >> 2] = 0;
+ $24 = $0 + 16 | 0;
+ HEAP32[$24 >> 2] = 0;
+ $25 = HEAP32[40817] | 0;
+ $shl95 = 1 << $I57_0;
+ $and96 = $25 & $shl95;
+ $tobool97 = ($and96 | 0) == 0;
+ if ($tobool97) {
+ label = 17;
+ break;
+ } else {
+ label = 18;
+ break;
+ }
+ case 17:
+ $or101 = $25 | $shl95;
+ HEAP32[40817] = $or101;
+ HEAP32[$arrayidx91 >> 2] = $23;
+ $parent = $0 + 24 | 0;
+ $_c = $arrayidx91;
+ HEAP32[$parent >> 2] = $_c;
+ $bk102 = $0 + 12 | 0;
+ HEAP32[$bk102 >> 2] = $0;
+ $fd103 = $0 + 8 | 0;
+ HEAP32[$fd103 >> 2] = $0;
+ label = 30;
+ break;
+ case 18:
+ $26 = HEAP32[$arrayidx91 >> 2] | 0;
+ $cmp106 = ($I57_0 | 0) == 31;
+ if ($cmp106) {
+ $cond115 = 0;
+ label = 20;
+ break;
+ } else {
+ label = 19;
+ break;
+ }
+ case 19:
+ $shr110 = $I57_0 >>> 1;
+ $sub113 = 25 - $shr110 | 0;
+ $cond115 = $sub113;
+ label = 20;
+ break;
+ case 20:
+ $shl116 = $sub_ptr_sub << $cond115;
+ $K105_0 = $shl116;
+ $T_0 = $26;
+ label = 21;
+ break;
+ case 21:
+ $head118 = $T_0 + 4 | 0;
+ $27 = HEAP32[$head118 >> 2] | 0;
+ $and119 = $27 & -8;
+ $cmp120 = ($and119 | 0) == ($sub_ptr_sub | 0);
+ if ($cmp120) {
+ label = 26;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $shr123 = $K105_0 >>> 31;
+ $arrayidx126 = $T_0 + 16 + ($shr123 << 2) | 0;
+ $28 = HEAP32[$arrayidx126 >> 2] | 0;
+ $cmp128 = ($28 | 0) == 0;
+ $shl127 = $K105_0 << 1;
+ if ($cmp128) {
+ label = 23;
+ break;
+ } else {
+ $K105_0 = $shl127;
+ $T_0 = $28;
+ label = 21;
+ break;
+ }
+ case 23:
+ $29 = $arrayidx126;
+ $30 = HEAP32[40820] | 0;
+ $cmp133 = $29 >>> 0 < $30 >>> 0;
+ if ($cmp133) {
+ label = 25;
+ break;
+ } else {
+ label = 24;
+ break;
+ }
+ case 24:
+ HEAP32[$arrayidx126 >> 2] = $23;
+ $parent138 = $0 + 24 | 0;
+ $T_0_c7 = $T_0;
+ HEAP32[$parent138 >> 2] = $T_0_c7;
+ $bk139 = $0 + 12 | 0;
+ HEAP32[$bk139 >> 2] = $0;
+ $fd140 = $0 + 8 | 0;
+ HEAP32[$fd140 >> 2] = $0;
+ label = 30;
+ break;
+ case 25:
+ _abort();
+ case 26:
+ $fd145 = $T_0 + 8 | 0;
+ $31 = HEAP32[$fd145 >> 2] | 0;
+ $32 = $T_0;
+ $33 = HEAP32[40820] | 0;
+ $cmp147 = $32 >>> 0 < $33 >>> 0;
+ if ($cmp147) {
+ label = 29;
+ break;
+ } else {
+ label = 27;
+ break;
+ }
+ case 27:
+ $34 = $31;
+ $cmp150 = $34 >>> 0 < $33 >>> 0;
+ if ($cmp150) {
+ label = 29;
+ break;
+ } else {
+ label = 28;
+ break;
+ }
+ case 28:
+ $bk155 = $31 + 12 | 0;
+ HEAP32[$bk155 >> 2] = $23;
+ HEAP32[$fd145 >> 2] = $23;
+ $fd157 = $0 + 8 | 0;
+ $_c6 = $31;
+ HEAP32[$fd157 >> 2] = $_c6;
+ $bk158 = $0 + 12 | 0;
+ $T_0_c = $T_0;
+ HEAP32[$bk158 >> 2] = $T_0_c;
+ $parent159 = $0 + 24 | 0;
+ HEAP32[$parent159 >> 2] = 0;
+ label = 30;
+ break;
+ case 29:
+ _abort();
+ case 30:
+ return;
+ }
+}
+function _strtod($string, $endPtr) {
+ $string = $string | 0;
+ $endPtr = $endPtr | 0;
+ var $p_0 = 0, $0 = 0, $conv = 0, $call = 0, $tobool = 0, $add_ptr = 0, $1 = 0, $add_ptr3 = 0, $add_ptr8 = 0, $sign_0 = 0, $p_2 = 0, $p_3 = 0, $mantSize_0 = 0, $decPt_0 = 0, $2 = 0, $conv10 = 0, $isdigittmp = 0, $isdigit = 0, $cmp14 = 0, $cmp16 = 0, $or_cond = 0, $decPt_1 = 0, $add_ptr21 = 0, $add = 0, $idx_neg = 0, $add_ptr22 = 0, $cmp23 = 0, $not_cmp23 = 0, $sub = 0, $mantSize_1 = 0, $decPt_2 = 0, $cmp28 = 0, $3 = 0, $fracExp_0_p = 0, $fracExp_0 = 0, $mantSize_2 = 0, $cmp35 = 0, $cmp4078 = 0, $phitmp = 0.0, $phitmp85 = 0.0, $cmp5673 = 0, $p_4_lcssa91 = 0, $mantSize_3_lcssa90 = 0, $frac1_0_lcssa89 = 0.0, $frac1_081 = 0, $mantSize_380 = 0, $p_479 = 0, $4 = 0, $add_ptr43 = 0, $cmp44 = 0, $5 = 0, $add_ptr48 = 0, $p_5 = 0, $c_0_in = 0, $c_0 = 0, $mul = 0, $sub50 = 0, $add51 = 0, $sub53 = 0, $cmp40 = 0, $frac2_076 = 0, $mantSize_475 = 0, $p_674 = 0, $6 = 0, $add_ptr60 = 0, $cmp61 = 0, $7 = 0, $add_ptr65 = 0, $p_7 = 0, $c_1_in = 0, $c_1 = 0, $mul67 = 0, $sub68 = 0, $add69 = 0, $sub71 = 0, $cmp56 = 0, $phitmp86 = 0.0, $frac1_0_lcssa88 = 0.0, $frac2_0_lcssa = 0.0, $add76 = 0.0, $8 = 0, $add_ptr86 = 0, $9 = 0, $add_ptr91 = 0, $add_ptr97 = 0, $expSign_0_ph = 0, $p_9_ph = 0, $10 = 0, $conv10166 = 0, $isdigittmp6067 = 0, $isdigit6168 = 0, $exp_070 = 0, $p_969 = 0, $mul105 = 0, $11 = 0, $conv106 = 0, $sub107 = 0, $add108 = 0, $add_ptr109 = 0, $12 = 0, $conv101 = 0, $isdigittmp60 = 0, $isdigit61 = 0, $expSign_1 = 0, $p_10 = 0, $exp_1 = 0, $tobool112 = 0, $13 = 0, $exp_2_p = 0, $exp_2 = 0, $cmp118 = 0, $sub121 = 0, $exp_3 = 0, $cmp124 = 0, $call127 = 0, $cmp13062 = 0, $exp_565 = 0, $d_064 = 0, $dblExp_063 = 0.0, $and = 0, $tobool133 = 0, $14 = 0.0, $mul135 = 0.0, $dblExp_1 = 0.0, $shr = 0, $add_ptr138 = 0, $cmp130 = 0, $dblExp_0_lcssa = 0.0, $tobool140 = 0, $div = 0.0, $mul143 = 0.0, $fraction_0 = 0.0, $p_11 = 0, $cmp145 = 0, $tobool149 = 0, $sub151 = 0.0, $retval_0 = 0.0, label = 0;
+ label = 2;
+ while (1) switch (label | 0) {
+ case 2:
+ $p_0 = $string;
+ label = 3;
+ break;
+ case 3:
+ $0 = HEAP8[$p_0] | 0;
+ $conv = $0 << 24 >> 24;
+ $call = _isspace($conv | 0) | 0;
+ $tobool = ($call | 0) == 0;
+ $add_ptr = $p_0 + 1 | 0;
+ if ($tobool) {
+ label = 4;
+ break;
+ } else {
+ $p_0 = $add_ptr;
+ label = 3;
+ break;
+ }
+ case 4:
+ $1 = HEAP8[$p_0] | 0;
+ if (($1 << 24 >> 24 | 0) == 45) {
+ label = 5;
+ break;
+ } else if (($1 << 24 >> 24 | 0) == 43) {
+ label = 6;
+ break;
+ } else {
+ $p_2 = $p_0;
+ $sign_0 = 0;
+ label = 7;
+ break;
+ }
+ case 5:
+ $add_ptr3 = $p_0 + 1 | 0;
+ $p_2 = $add_ptr3;
+ $sign_0 = 1;
+ label = 7;
+ break;
+ case 6:
+ $add_ptr8 = $p_0 + 1 | 0;
+ $p_2 = $add_ptr8;
+ $sign_0 = 0;
+ label = 7;
+ break;
+ case 7:
+ $decPt_0 = -1;
+ $mantSize_0 = 0;
+ $p_3 = $p_2;
+ label = 8;
+ break;
+ case 8:
+ $2 = HEAP8[$p_3] | 0;
+ $conv10 = $2 << 24 >> 24;
+ $isdigittmp = $conv10 - 48 | 0;
+ $isdigit = $isdigittmp >>> 0 < 10;
+ if ($isdigit) {
+ $decPt_1 = $decPt_0;
+ label = 10;
+ break;
+ } else {
+ label = 9;
+ break;
+ }
+ case 9:
+ $cmp14 = $2 << 24 >> 24 != 46;
+ $cmp16 = ($decPt_0 | 0) > -1;
+ $or_cond = $cmp14 | $cmp16;
+ if ($or_cond) {
+ label = 11;
+ break;
+ } else {
+ $decPt_1 = $mantSize_0;
+ label = 10;
+ break;
+ }
+ case 10:
+ $add_ptr21 = $p_3 + 1 | 0;
+ $add = $mantSize_0 + 1 | 0;
+ $decPt_0 = $decPt_1;
+ $mantSize_0 = $add;
+ $p_3 = $add_ptr21;
+ label = 8;
+ break;
+ case 11:
+ $idx_neg = -$mantSize_0 | 0;
+ $add_ptr22 = $p_3 + $idx_neg | 0;
+ $cmp23 = ($decPt_0 | 0) < 0;
+ $not_cmp23 = $cmp23 ^ 1;
+ $sub = $not_cmp23 << 31 >> 31;
+ $mantSize_1 = $sub + $mantSize_0 | 0;
+ $decPt_2 = $cmp23 ? $mantSize_0 : $decPt_0;
+ $cmp28 = ($mantSize_1 | 0) > 18;
+ $3 = -$mantSize_1 | 0;
+ $fracExp_0_p = $cmp28 ? -18 : $3;
+ $fracExp_0 = $fracExp_0_p + $decPt_2 | 0;
+ $mantSize_2 = $cmp28 ? 18 : $mantSize_1;
+ $cmp35 = ($mantSize_2 | 0) == 0;
+ if ($cmp35) {
+ $p_11 = $string;
+ $fraction_0 = 0.0;
+ label = 38;
+ break;
+ } else {
+ label = 12;
+ break;
+ }
+ case 12:
+ $cmp4078 = ($mantSize_2 | 0) > 9;
+ if ($cmp4078) {
+ $p_479 = $add_ptr22;
+ $mantSize_380 = $mantSize_2;
+ $frac1_081 = 0;
+ label = 16;
+ break;
+ } else {
+ label = 14;
+ break;
+ }
+ case 13:
+ $phitmp = +($add51 | 0);
+ $phitmp85 = $phitmp * 1.0e9;
+ $frac1_0_lcssa89 = $phitmp85;
+ $mantSize_3_lcssa90 = 9;
+ $p_4_lcssa91 = $p_5;
+ label = 15;
+ break;
+ case 14:
+ $cmp5673 = ($mantSize_2 | 0) > 0;
+ if ($cmp5673) {
+ $frac1_0_lcssa89 = 0.0;
+ $mantSize_3_lcssa90 = $mantSize_2;
+ $p_4_lcssa91 = $add_ptr22;
+ label = 15;
+ break;
+ } else {
+ $frac2_0_lcssa = 0.0;
+ $frac1_0_lcssa88 = 0.0;
+ label = 23;
+ break;
+ }
+ case 15:
+ $p_674 = $p_4_lcssa91;
+ $mantSize_475 = $mantSize_3_lcssa90;
+ $frac2_076 = 0;
+ label = 19;
+ break;
+ case 16:
+ $4 = HEAP8[$p_479] | 0;
+ $add_ptr43 = $p_479 + 1 | 0;
+ $cmp44 = $4 << 24 >> 24 == 46;
+ if ($cmp44) {
+ label = 17;
+ break;
+ } else {
+ $c_0_in = $4;
+ $p_5 = $add_ptr43;
+ label = 18;
+ break;
+ }
+ case 17:
+ $5 = HEAP8[$add_ptr43] | 0;
+ $add_ptr48 = $p_479 + 2 | 0;
+ $c_0_in = $5;
+ $p_5 = $add_ptr48;
+ label = 18;
+ break;
+ case 18:
+ $c_0 = $c_0_in << 24 >> 24;
+ $mul = $frac1_081 * 10 & -1;
+ $sub50 = $mul - 48 | 0;
+ $add51 = $sub50 + $c_0 | 0;
+ $sub53 = $mantSize_380 - 1 | 0;
+ $cmp40 = ($sub53 | 0) > 9;
+ if ($cmp40) {
+ $p_479 = $p_5;
+ $mantSize_380 = $sub53;
+ $frac1_081 = $add51;
+ label = 16;
+ break;
+ } else {
+ label = 13;
+ break;
+ }
+ case 19:
+ $6 = HEAP8[$p_674] | 0;
+ $add_ptr60 = $p_674 + 1 | 0;
+ $cmp61 = $6 << 24 >> 24 == 46;
+ if ($cmp61) {
+ label = 20;
+ break;
+ } else {
+ $c_1_in = $6;
+ $p_7 = $add_ptr60;
+ label = 21;
+ break;
+ }
+ case 20:
+ $7 = HEAP8[$add_ptr60] | 0;
+ $add_ptr65 = $p_674 + 2 | 0;
+ $c_1_in = $7;
+ $p_7 = $add_ptr65;
+ label = 21;
+ break;
+ case 21:
+ $c_1 = $c_1_in << 24 >> 24;
+ $mul67 = $frac2_076 * 10 & -1;
+ $sub68 = $mul67 - 48 | 0;
+ $add69 = $sub68 + $c_1 | 0;
+ $sub71 = $mantSize_475 - 1 | 0;
+ $cmp56 = ($sub71 | 0) > 0;
+ if ($cmp56) {
+ $p_674 = $p_7;
+ $mantSize_475 = $sub71;
+ $frac2_076 = $add69;
+ label = 19;
+ break;
+ } else {
+ label = 22;
+ break;
+ }
+ case 22:
+ $phitmp86 = +($add69 | 0);
+ $frac2_0_lcssa = $phitmp86;
+ $frac1_0_lcssa88 = $frac1_0_lcssa89;
+ label = 23;
+ break;
+ case 23:
+ $add76 = $frac1_0_lcssa88 + $frac2_0_lcssa;
+ $8 = HEAP8[$p_3] | 0;
+ if (($8 << 24 >> 24 | 0) == 69 | ($8 << 24 >> 24 | 0) == 101) {
+ label = 24;
+ break;
+ } else {
+ $exp_1 = 0;
+ $p_10 = $p_3;
+ $expSign_1 = 0;
+ label = 29;
+ break;
+ }
+ case 24:
+ $add_ptr86 = $p_3 + 1 | 0;
+ $9 = HEAP8[$add_ptr86] | 0;
+ if (($9 << 24 >> 24 | 0) == 45) {
+ label = 25;
+ break;
+ } else if (($9 << 24 >> 24 | 0) == 43) {
+ label = 26;
+ break;
+ } else {
+ $p_9_ph = $add_ptr86;
+ $expSign_0_ph = 0;
+ label = 27;
+ break;
+ }
+ case 25:
+ $add_ptr91 = $p_3 + 2 | 0;
+ $p_9_ph = $add_ptr91;
+ $expSign_0_ph = 1;
+ label = 27;
+ break;
+ case 26:
+ $add_ptr97 = $p_3 + 2 | 0;
+ $p_9_ph = $add_ptr97;
+ $expSign_0_ph = 0;
+ label = 27;
+ break;
+ case 27:
+ $10 = HEAP8[$p_9_ph] | 0;
+ $conv10166 = $10 << 24 >> 24;
+ $isdigittmp6067 = $conv10166 - 48 | 0;
+ $isdigit6168 = $isdigittmp6067 >>> 0 < 10;
+ if ($isdigit6168) {
+ $p_969 = $p_9_ph;
+ $exp_070 = 0;
+ label = 28;
+ break;
+ } else {
+ $exp_1 = 0;
+ $p_10 = $p_9_ph;
+ $expSign_1 = $expSign_0_ph;
+ label = 29;
+ break;
+ }
+ case 28:
+ $mul105 = $exp_070 * 10 & -1;
+ $11 = HEAP8[$p_969] | 0;
+ $conv106 = $11 << 24 >> 24;
+ $sub107 = $mul105 - 48 | 0;
+ $add108 = $sub107 + $conv106 | 0;
+ $add_ptr109 = $p_969 + 1 | 0;
+ $12 = HEAP8[$add_ptr109] | 0;
+ $conv101 = $12 << 24 >> 24;
+ $isdigittmp60 = $conv101 - 48 | 0;
+ $isdigit61 = $isdigittmp60 >>> 0 < 10;
+ if ($isdigit61) {
+ $p_969 = $add_ptr109;
+ $exp_070 = $add108;
+ label = 28;
+ break;
+ } else {
+ $exp_1 = $add108;
+ $p_10 = $add_ptr109;
+ $expSign_1 = $expSign_0_ph;
+ label = 29;
+ break;
+ }
+ case 29:
+ $tobool112 = ($expSign_1 | 0) == 0;
+ $13 = -$exp_1 | 0;
+ $exp_2_p = $tobool112 ? $exp_1 : $13;
+ $exp_2 = $fracExp_0 + $exp_2_p | 0;
+ $cmp118 = ($exp_2 | 0) < 0;
+ $sub121 = -$exp_2 | 0;
+ $exp_3 = $cmp118 ? $sub121 : $exp_2;
+ $cmp124 = ($exp_3 | 0) > 511;
+ if ($cmp124) {
+ label = 30;
+ break;
+ } else {
+ label = 31;
+ break;
+ }
+ case 30:
+ $call127 = ___errno_location() | 0;
+ HEAP32[$call127 >> 2] = 34;
+ $dblExp_063 = 1.0;
+ $d_064 = 5576;
+ $exp_565 = 511;
+ label = 32;
+ break;
+ case 31:
+ $cmp13062 = ($exp_3 | 0) == 0;
+ if ($cmp13062) {
+ $dblExp_0_lcssa = 1.0;
+ label = 35;
+ break;
+ } else {
+ $dblExp_063 = 1.0;
+ $d_064 = 5576;
+ $exp_565 = $exp_3;
+ label = 32;
+ break;
+ }
+ case 32:
+ $and = $exp_565 & 1;
+ $tobool133 = ($and | 0) == 0;
+ if ($tobool133) {
+ $dblExp_1 = $dblExp_063;
+ label = 34;
+ break;
+ } else {
+ label = 33;
+ break;
+ }
+ case 33:
+ $14 = +HEAPF64[$d_064 >> 3];
+ $mul135 = $dblExp_063 * $14;
+ $dblExp_1 = $mul135;
+ label = 34;
+ break;
+ case 34:
+ $shr = $exp_565 >> 1;
+ $add_ptr138 = $d_064 + 8 | 0;
+ $cmp130 = ($shr | 0) == 0;
+ if ($cmp130) {
+ $dblExp_0_lcssa = $dblExp_1;
+ label = 35;
+ break;
+ } else {
+ $dblExp_063 = $dblExp_1;
+ $d_064 = $add_ptr138;
+ $exp_565 = $shr;
+ label = 32;
+ break;
+ }
+ case 35:
+ $tobool140 = ($exp_2 | 0) > -1;
+ if ($tobool140) {
+ label = 37;
+ break;
+ } else {
+ label = 36;
+ break;
+ }
+ case 36:
+ $div = $add76 / $dblExp_0_lcssa;
+ $p_11 = $p_10;
+ $fraction_0 = $div;
+ label = 38;
+ break;
+ case 37:
+ $mul143 = $add76 * $dblExp_0_lcssa;
+ $p_11 = $p_10;
+ $fraction_0 = $mul143;
+ label = 38;
+ break;
+ case 38:
+ $cmp145 = ($endPtr | 0) == 0;
+ if ($cmp145) {
+ label = 40;
+ break;
+ } else {
+ label = 39;
+ break;
+ }
+ case 39:
+ HEAP32[$endPtr >> 2] = $p_11;
+ label = 40;
+ break;
+ case 40:
+ $tobool149 = ($sign_0 | 0) == 0;
+ if ($tobool149) {
+ $retval_0 = $fraction_0;
+ label = 42;
+ break;
+ } else {
+ label = 41;
+ break;
+ }
+ case 41:
+ $sub151 = -0.0 - $fraction_0;
+ $retval_0 = $sub151;
+ label = 42;
+ break;
+ case 42:
+ return +$retval_0;
+ }
+ return 0.0;
+}
+function _atof($str) {
+ $str = $str | 0;
+ return +(+_strtod($str, 0));
+}
+function _memcmp(p1, p2, num) {
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ num = num | 0;
+ var i = 0, v1 = 0, v2 = 0;
+ while ((i | 0) < (num | 0)) {
+ v1 = HEAPU8[p1 + i | 0] | 0;
+ v2 = HEAPU8[p2 + i | 0] | 0;
+ if ((v1 | 0) != (v2 | 0)) return ((v1 | 0) > (v2 | 0) ? 1 : -1) | 0;
+ i = i + 1 | 0;
+ }
+ return 0;
+}
+function _memcpy(dest, src, num) {
+ dest = dest | 0;
+ src = src | 0;
+ num = num | 0;
+ var ret = 0;
+ ret = dest | 0;
+ if ((dest & 3) == (src & 3)) {
+ while (dest & 3) {
+ if ((num | 0) == 0) return ret | 0;
+ HEAP8[dest] = HEAP8[src] | 0;
+ dest = dest + 1 | 0;
+ src = src + 1 | 0;
+ num = num - 1 | 0;
+ }
+ while ((num | 0) >= 4) {
+ HEAP32[dest >> 2] = HEAP32[src >> 2] | 0;
+ dest = dest + 4 | 0;
+ src = src + 4 | 0;
+ num = num - 4 | 0;
+ }
+ }
+ while ((num | 0) > 0) {
+ HEAP8[dest] = HEAP8[src] | 0;
+ dest = dest + 1 | 0;
+ src = src + 1 | 0;
+ num = num - 1 | 0;
+ }
+ return ret | 0;
+}
+function _strlen(ptr) {
+ ptr = ptr | 0;
+ var curr = 0;
+ curr = ptr;
+ while (HEAP8[curr] | 0) {
+ curr = curr + 1 | 0;
+ }
+ return curr - ptr | 0;
+}
+function _memset(ptr, value, num) {
+ ptr = ptr | 0;
+ value = value | 0;
+ num = num | 0;
+ var stop = 0, value4 = 0, stop4 = 0, unaligned = 0;
+ stop = ptr + num | 0;
+ if ((num | 0) >= 20) {
+ value = value & 255;
+ unaligned = ptr & 3;
+ value4 = value | value << 8 | value << 16 | value << 24;
+ stop4 = stop & ~3;
+ if (unaligned) {
+ unaligned = ptr + 4 - unaligned | 0;
+ while ((ptr | 0) < (unaligned | 0)) {
+ HEAP8[ptr] = value;
+ ptr = ptr + 1 | 0;
+ }
+ }
+ while ((ptr | 0) < (stop4 | 0)) {
+ HEAP32[ptr >> 2] = value4;
+ ptr = ptr + 4 | 0;
+ }
+ }
+ while ((ptr | 0) < (stop | 0)) {
+ HEAP8[ptr] = value;
+ ptr = ptr + 1 | 0;
+ }
+}
+function _strcpy(pdest, psrc) {
+ pdest = pdest | 0;
+ psrc = psrc | 0;
+ var i = 0;
+ do {
+ HEAP8[pdest + i | 0] = HEAP8[psrc + i | 0];
+ i = i + 1 | 0;
+ } while (HEAP8[psrc + (i - 1) | 0] | 0);
+ return pdest | 0;
+}
+function _strcat(pdest, psrc) {
+ pdest = pdest | 0;
+ psrc = psrc | 0;
+ var i = 0, pdestEnd = 0;
+ pdestEnd = pdest + (_strlen(pdest) | 0) | 0;
+ do {
+ HEAP8[pdestEnd + i | 0] = HEAP8[psrc + i | 0];
+ i = i + 1 | 0;
+ } while (HEAP8[psrc + (i - 1) | 0] | 0);
+ return pdest | 0;
+}
+function _strncpy(pdest, psrc, num) {
+ pdest = pdest | 0;
+ psrc = psrc | 0;
+ num = num | 0;
+ var padding = 0, i = 0;
+ while ((i | 0) < (num | 0)) {
+ HEAP8[pdest + i | 0] = padding ? 0 : HEAP8[psrc + i | 0] | 0;
+ padding = padding ? 1 : (HEAP8[psrc + i | 0] | 0) == 0;
+ i = i + 1 | 0;
+ }
+ return pdest | 0;
+}
+function _tolower(chr) {
+ chr = chr | 0;
+ if ((chr | 0) < 65) return chr | 0;
+ if ((chr | 0) > 90) return chr | 0;
+ return chr - 65 + 97 | 0;
+}
+function _memmove(dest, src, num) {
+ dest = dest | 0;
+ src = src | 0;
+ num = num | 0;
+ if ((src | 0) < (dest | 0) & (dest | 0) < (src + num | 0)) {
+ src = src + num | 0;
+ dest = dest + num | 0;
+ while ((num | 0) > 0) {
+ dest = dest - 1 | 0;
+ src = src - 1 | 0;
+ num = num - 1 | 0;
+ HEAP8[dest] = HEAP8[src] | 0;
+ }
+ } else {
+ _memcpy(dest, src, num);
+ }
+}
+function _ferror__wrapper(a1) {
+ a1 = a1 | 0;
+ return _ferror(a1 | 0) | 0;
+}
+function _fwrite__wrapper(a1, a2, a3, a4) {
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ a4 = a4 | 0;
+ return _fwrite(a1 | 0, a2 | 0, a3 | 0, a4 | 0) | 0;
+}
+function _fgets__wrapper(a1, a2, a3) {
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ return _fgets(a1 | 0, a2 | 0, a3 | 0) | 0;
+}
+function dynCall_iiiii(index, a1, a2, a3, a4) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ a4 = a4 | 0;
+ return FUNCTION_TABLE_iiiii[index & 1023](a1 | 0, a2 | 0, a3 | 0, a4 | 0) | 0;
+}
+function dynCall_viiiffi(index, a1, a2, a3, a4, a5, a6) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ a4 = +a4;
+ a5 = +a5;
+ a6 = a6 | 0;
+ FUNCTION_TABLE_viiiffi[index & 1023](a1 | 0, a2 | 0, a3 | 0, +a4, +a5, a6 | 0);
+}
+function dynCall_viiiii(index, a1, a2, a3, a4, a5) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ a4 = a4 | 0;
+ a5 = a5 | 0;
+ FUNCTION_TABLE_viiiii[index & 1023](a1 | 0, a2 | 0, a3 | 0, a4 | 0, a5 | 0);
+}
+function dynCall_vi(index, a1) {
+ index = index | 0;
+ a1 = a1 | 0;
+ FUNCTION_TABLE_vi[index & 1023](a1 | 0);
+}
+function dynCall_vii(index, a1, a2) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ FUNCTION_TABLE_vii[index & 1023](a1 | 0, a2 | 0);
+}
+function dynCall_ii(index, a1) {
+ index = index | 0;
+ a1 = a1 | 0;
+ return FUNCTION_TABLE_ii[index & 1023](a1 | 0) | 0;
+}
+function dynCall_iiii(index, a1, a2, a3) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ return FUNCTION_TABLE_iiii[index & 1023](a1 | 0, a2 | 0, a3 | 0) | 0;
+}
+function dynCall_viii(index, a1, a2, a3) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ FUNCTION_TABLE_viii[index & 1023](a1 | 0, a2 | 0, a3 | 0);
+}
+function dynCall_v(index) {
+ index = index | 0;
+ FUNCTION_TABLE_v[index & 1023]();
+}
+function dynCall_viiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ a4 = a4 | 0;
+ a5 = a5 | 0;
+ a6 = a6 | 0;
+ a7 = a7 | 0;
+ a8 = a8 | 0;
+ a9 = a9 | 0;
+ FUNCTION_TABLE_viiiiiiiii[index & 1023](a1 | 0, a2 | 0, a3 | 0, a4 | 0, a5 | 0, a6 | 0, a7 | 0, a8 | 0, a9 | 0);
+}
+function dynCall_viiiiii(index, a1, a2, a3, a4, a5, a6) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ a4 = a4 | 0;
+ a5 = a5 | 0;
+ a6 = a6 | 0;
+ FUNCTION_TABLE_viiiiii[index & 1023](a1 | 0, a2 | 0, a3 | 0, a4 | 0, a5 | 0, a6 | 0);
+}
+function dynCall_iii(index, a1, a2) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ return FUNCTION_TABLE_iii[index & 1023](a1 | 0, a2 | 0) | 0;
+}
+function dynCall_iiiiii(index, a1, a2, a3, a4, a5) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ a4 = a4 | 0;
+ a5 = a5 | 0;
+ return FUNCTION_TABLE_iiiiii[index & 1023](a1 | 0, a2 | 0, a3 | 0, a4 | 0, a5 | 0) | 0;
+}
+function dynCall_viiii(index, a1, a2, a3, a4) {
+ index = index | 0;
+ a1 = a1 | 0;
+ a2 = a2 | 0;
+ a3 = a3 | 0;
+ a4 = a4 | 0;
+ FUNCTION_TABLE_viiii[index & 1023](a1 | 0, a2 | 0, a3 | 0, a4 | 0);
+}
+function b0(p0, p1, p2, p3) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ p3 = p3 | 0;
+ abort(0);
+ return 0;
+}
+function b1(p0, p1, p2, p3, p4, p5) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ p3 = +p3;
+ p4 = +p4;
+ p5 = p5 | 0;
+ abort(1);
+}
+function b2(p0, p1, p2, p3, p4) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ p3 = p3 | 0;
+ p4 = p4 | 0;
+ abort(2);
+}
+function b3(p0) {
+ p0 = p0 | 0;
+ abort(3);
+}
+function b4(p0, p1) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ abort(4);
+}
+function b5(p0) {
+ p0 = p0 | 0;
+ abort(5);
+ return 0;
+}
+function b6(p0, p1, p2) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ abort(6);
+ return 0;
+}
+function b7(p0, p1, p2) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ abort(7);
+}
+function b8() {
+ abort(8);
+}
+function b9(p0, p1, p2, p3, p4, p5, p6, p7, p8) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ p3 = p3 | 0;
+ p4 = p4 | 0;
+ p5 = p5 | 0;
+ p6 = p6 | 0;
+ p7 = p7 | 0;
+ p8 = p8 | 0;
+ abort(9);
+}
+function b10(p0, p1, p2, p3, p4, p5) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ p3 = p3 | 0;
+ p4 = p4 | 0;
+ p5 = p5 | 0;
+ abort(10);
+}
+function b11(p0, p1) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ abort(11);
+ return 0;
+}
+function b12(p0, p1, p2, p3, p4) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ p3 = p3 | 0;
+ p4 = p4 | 0;
+ abort(12);
+ return 0;
+}
+function b13(p0, p1, p2, p3) {
+ p0 = p0 | 0;
+ p1 = p1 | 0;
+ p2 = p2 | 0;
+ p3 = p3 | 0;
+ abort(13);
+}
+// EMSCRIPTEN_END_FUNCS
+ var FUNCTION_TABLE_iiiii = [b0,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,_big2_cdataSectionTok
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,_externalEntityContentProcessor,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,_cdataSectionProcessor
+ ,b0,b0,b0,_initScanProlog,b0,b0,b0,b0,b0,b0
+ ,b0,_normal_cdataSectionTok,b0,b0,b0,b0,b0,b0,b0,_normal_prologTok
+ ,b0,b0,b0,b0,b0,_prologProcessor,b0,_normal_isPublicId,b0,_big2_nameMatchesAscii
+ ,b0,b0,b0,b0,b0,_normal_contentTok,b0,b0,b0,b0
+ ,b0,_contentProcessor,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,_normal_attributeValueTok,b0,b0,b0,b0
+ ,b0,_little2_attributeValueTok,b0,_prologInitProcessor,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,_cmppair,b0,_gvfwrite
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,_initScanContent,b0,_little2_cdataSectionTok,b0,b0,b0,b0,b0,b0
+ ,b0,_epilogProcessor,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,_little2_isPublicId,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,_dtmemory,b0,_big2_entityValueTok
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,_normal_getAtts,b0,_big2_contentTok,b0,b0,b0,b0
+ ,b0,_big2_getAtts,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,_little2_getAtts,b0,b0,b0,_fwrite__wrapper,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,_big2_isPublicId
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,_little2_entityValueTok,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,_little2_nameMatchesAscii,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,_agcmpid,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,_errorProcessor,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,_normal_nameMatchesAscii
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,_agcmpin
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,_little2_contentTok
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,_little2_prologTok,b0,b0,b0,_big2_attributeValueTok,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,_agcmpout,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,_big2_prologTok,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,_normal_entityValueTok
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,_internalEntityProcessor
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0
+ ,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0,b0];
+ var FUNCTION_TABLE_viiiffi = [b1,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,_arrow_type_box,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,_arrow_type_crow,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,_arrow_type_dot,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,_arrow_type_diamond
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,_arrow_type_tee,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,_arrow_type_normal,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1
+ ,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1,b1];
+ var FUNCTION_TABLE_viiiii = [b2,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,_svg_begin_anchor,b2,_utf8_toUtf8,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,_latin1_toUtf8,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,_ascii_toUtf8,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,_little2_toUtf16
+ ,b2,b2,b2,b2,b2,b2,b2,_big2_toUtf8,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,_unknown_toUtf8,b2,_utf8_toUtf16
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,_vml_begin_anchor,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,_latin1_toUtf16
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,_psgen_begin_anchor
+ ,b2,b2,b2,b2,b2,_little2_toUtf8,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,_unknown_toUtf16,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,_psgen_library_shape,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,_big2_toUtf16,b2,b2,b2,b2,b2,_map_begin_anchor
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2
+ ,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2,b2];
+ var FUNCTION_TABLE_vi = [b3,b3,_psgen_end_node,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,_tkgen_begin_job,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,_dot_cleanup,b3,b3
+ ,b3,b3,b3,b3,b3,_psgen_end_page,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,_svg_begin_cluster
+ ,b3,_psgen_begin_graph,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,_point_init,b3,b3,b3,_record_init,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,_gvevent_refresh,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,_svg_begin_job,b3,b3,b3,_svg_end_layer,b3,b3
+ ,b3,b3,b3,_tkgen_begin_edge,b3,_epsf_free,b3,_vml_end_graph,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,_psgen_end_job,b3,_poly_free,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,_ps_freeimage
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,_vml_begin_job,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,_vml_begin_graph,b3,b3
+ ,b3,b3,b3,b3,b3,_svg_begin_node,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,_svg_begin_edge,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,_svg_begin_graph,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,_svg_begin_page,b3,b3,b3,b3,b3,b3
+ ,b3,_svg_end_page,b3,b3,b3,b3,b3,_gvevent_delete,b3,_psgen_end_edge
+ ,b3,_psgen_begin_page,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,_fig_end_edge,b3,b3,b3,b3,b3,b3
+ ,b3,_psgen_begin_node,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,_dot_begin_graph,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,_vml_end_anchor,b3,b3,b3,b3,b3,_fig_begin_edge,b3,_fig_begin_page
+ ,b3,b3,b3,_xdot_end_cluster,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,_map_begin_page,b3,_psgen_begin_job,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,_tkgen_begin_graph,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,_psgen_begin_edge,b3,b3,b3,b3
+ ,b3,_psgen_begin_cluster,b3,b3,b3,_svg_end_graph,b3,b3,b3,_fig_end_graph
+ ,b3,b3,b3,_record_free,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,_svg_end_cluster,b3,b3
+ ,b3,_tkgen_begin_node,b3,b3,b3,_poly_init,b3,_psgen_end_cluster,b3,b3
+ ,b3,b3,b3,_xdot_end_node,b3,b3,b3,_svg_end_node,b3,b3
+ ,b3,b3,b3,_svg_end_edge,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,_fig_begin_graph,b3,_free,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,_xdot_end_edge,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,_dot_end_graph,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,_fig_begin_node,b3,b3,b3,_dot_layout
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,_svg_end_anchor,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,_map_end_page
+ ,b3,_epsf_init,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,_fig_end_node
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3
+ ,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3,b3];
+ var FUNCTION_TABLE_vii = [b4,b4,b4,b4,b4,b4,b4,b4,_vml_comment,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,_point_gencode,b4,b4,b4,_epsf_gencode,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,_tkgen_comment,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,_fig_comment,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,_endElement,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,_poly_gencode,b4,b4
+ ,b4,_agerrorf,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,_fig_resolve_color,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,_record_gencode,b4,b4,b4,_svg_comment,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,_vizRenderFromString,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,_gvevent_layout,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,_gvevent_motion,b4,b4
+ ,b4,_psgen_comment,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4
+ ,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4,b4];
+ var FUNCTION_TABLE_ii = [b5,b5,b5,b5,b5,b5,b5,b5,b5,b5,_up_cb
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,_zoom_in_cb
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,_ferror__wrapper,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,_zoom_out_cb,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,_down_cb
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,_gvferror,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,_malloc,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,_toggle_fit_cb,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,_quit_cb,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,_spline_merge,b5,b5,b5,_swap_ends_p,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,_left_cb,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,_right_cb,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5
+ ,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5,b5];
+ var FUNCTION_TABLE_iiii = [b6,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,_printedge,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,_dtlist,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,_big2_predefinedEntityName,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,_agraphattr
+ ,b6,_little2_sameName,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,_copydictf,b6,b6,b6,b6,b6,b6,b6,_agnodeattr
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,_normal_predefinedEntityName,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,_big2_sameName,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,_little2_predefinedEntityName,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,_fgets__wrapper,b6,_normal_sameName
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,_dttree,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,_dtvsearch
+ ,b6,b6,b6,_agedgeattr,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,_memgets,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6
+ ,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6,b6];
+ var FUNCTION_TABLE_viii = [b7,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,_free_fitem,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,_svg_textpara,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,_free_item,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,_vml_ellipse,b7,_vml_polyline,b7,b7,b7,_gvevent_button_press,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,_psgen_polyline,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_tkgen_polyline
+ ,b7,b7,b7,_characterData,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_xdot_polyline
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_psgen_textpara
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,_fig_textpara,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_free_string_entry
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,_freePair,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_free_ritem
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_xdot_ellipse
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,_tkgen_textpara,b7,b7,b7,b7,b7,_gvevent_render
+ ,b7,b7,b7,b7,b7,_ps_image_free,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,_usershape_close,b7,b7,b7,_free_citem
+ ,b7,b7,b7,_svg_ellipse,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,_free_fpara,b7,b7,b7,b7,b7,_fig_ellipse
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_vml_textpara
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,_gvevent_button_release,b7,b7,b7,b7,b7,b7
+ ,b7,_fig_polyline,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_gvevent_modify
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,_tkgen_ellipse,b7,b7,b7,b7,b7,_xdot_textpara
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,_startElement,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,_gvevent_read,b7,_psgen_ellipse,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,_svg_polyline
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7
+ ,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7,b7];
+ var FUNCTION_TABLE_v = [b8,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8
+ ,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8,b8];
+ var FUNCTION_TABLE_viiiiiiiii = [b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9,b9];
+ var FUNCTION_TABLE_viiiiii = [b10,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,_fig_bezier,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,_vml_bezier
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,_psgen_bezier,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,_svg_bezier
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,_xdot_bezier,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,_tkgen_bezier,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10
+ ,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10,b10];
+ var FUNCTION_TABLE_iii = [b11,b11,b11,b11,_icmp,b11,_titlefn,b11,b11,b11,b11
+ ,b11,b11,b11,_compFunction2,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,_cell_halignfn
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_normal_charRefNumber,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_edgelblcmpfn,b11,_halignfn,b11,_epsf_inside
+ ,b11,b11,b11,_utf8_isName2,b11,b11,b11,b11,b11,_srcfn
+ ,b11,b11,b11,b11,b11,_idfn,b11,_normal_nameLength,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,_cellpaddingfn,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_ordercmpf,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,_cellspacingfn
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,_unknown_isNmstrt,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_comp_entities,b11,_utf8_isNmstrt3,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,_cellborderfn,b11,b11,b11,b11,b11,_edgeidcmpf
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,_little2_nameLength,b11,_valignfn,b11,b11,b11,_alignfn
+ ,b11,_scalefn,b11,b11,b11,_utf8_isInvalid2,b11,_utf8_isInvalid3,b11,b11
+ ,b11,b11,b11,b11,b11,_utf8_isInvalid4,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_targetfn,b11,_unknown_isName,b11,b11
+ ,b11,b11,b11,_gvrender_comparestr,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,_fixedsizefn,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,_bgcolorfn,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_widthfn,b11,b11,b11,b11
+ ,b11,b11,b11,_utf8_isNmstrt2,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_unknown_isInvalid,b11,b11,b11,b11
+ ,b11,_borderfn,b11,b11,b11,b11,b11,_little2_charRefNumber,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_nodeposcmpf,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,_stylefn,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,_hreffn,b11,b11
+ ,b11,_colspanfn,b11,_poly_inside,b11,_isNever,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,_realloc,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,_utf8_isName3,b11,_balignfn,b11,b11
+ ,b11,b11,b11,_normal_skipS,b11,_rowspanfn,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,_little2_skipS,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,_fontcmpf,b11,b11
+ ,b11,b11,b11,_colorcmpf,b11,b11,b11,b11,b11,b11
+ ,b11,_ptsizefn,b11,b11,b11,_edgecmp,b11,b11,b11,b11
+ ,b11,_record_inside,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,_compFunction,b11,b11,b11,b11,b11,b11,b11,_inside
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,_big2_skipS,b11,b11,b11,_fontcolorfn,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,_point_inside,b11,b11,b11,_big2_nameLength,b11,b11,b11,b11
+ ,b11,_facefn,b11,b11,b11,b11,b11,_pencolorfn,b11,b11
+ ,b11,_portfn,b11,_big2_charRefNumber,b11,b11,b11,b11,b11,b11
+ ,b11,_heightfn,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11
+ ,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11,b11];
+ var FUNCTION_TABLE_iiiiii = [b12,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,_prolog2,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,_prolog1,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,_element0,b12,b12,b12,b12
+ ,b12,b12,b12,_notation2,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,_doctype0
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,_error,b12,b12,b12,_poly_path,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,_internalSubset,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,_attlist6,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,_declClose,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,_doctype2,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,_element4,b12,_element5
+ ,b12,_element2,b12,b12,b12,b12,b12,_element1,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,_element6,b12,b12,b12,b12,b12,b12
+ ,b12,_element7,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,_entity8,b12,_entity9,b12,_attlist2,b12,b12
+ ,b12,b12,b12,_entity3,b12,_entity0,b12,_entity1,b12,_entity6
+ ,b12,b12,b12,_entity4,b12,_element3,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,_notation0,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,_attlist8,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,_attlist5,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,_attlist7,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,_prolog0,b12,b12,b12,b12,b12,_attlist0
+ ,b12,_entity2,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,_attlist9,b12,b12,b12,b12,b12,b12
+ ,b12,_attlist4,b12,b12,b12,b12,b12,_attlist1,b12,b12
+ ,b12,_attlist3,b12,b12,b12,b12,b12,b12,b12,_entity5
+ ,b12,b12,b12,b12,b12,b12,b12,_doctype4,b12,_doctype5
+ ,b12,b12,b12,b12,b12,_doctype1,b12,b12,b12,_doctype3
+ ,b12,_entity10,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,_notation1,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,_notation3,b12,b12,b12,b12
+ ,b12,b12,b12,_record_path,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,_notation4,b12,_entity7,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12
+ ,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12,b12];
+ var FUNCTION_TABLE_viiii = [b13,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,_little2_updatePosition,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,_core_loadimage_fig
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,_psgen_polygon,b13,b13
+ ,b13,b13,b13,_core_loadimage_vml,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,_core_loadimage_xdot,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,_normal_updatePosition
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,_core_loadimage_vrml,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,_vml_polygon
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,_core_loadimage_ps
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,_core_loadimage_pslib,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,_initUpdatePosition,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,_svg_begin_layer,b13,_core_loadimage_null,b13,b13,b13,_poly_port
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,_xdot_polygon,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,_core_loadimage_svg,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,_record_port,b13,_tkgen_polygon
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,_svg_polygon,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,_big2_updatePosition,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,_psgen_begin_layer,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,_fig_polygon,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13
+ ,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13,b13];
+ return { _memcmp: _memcmp, _strlen: _strlen, _strcat: _strcat, _free: _free, _vizRenderFromString: _vizRenderFromString, _strncpy: _strncpy, _memmove: _memmove, _tolower: _tolower, _memset: _memset, _malloc: _malloc, _memcpy: _memcpy, _realloc: _realloc, _strcpy: _strcpy, _calloc: _calloc, stackAlloc: stackAlloc, stackSave: stackSave, stackRestore: stackRestore, setThrew: setThrew, setTempRet0: setTempRet0, setTempRet1: setTempRet1, setTempRet2: setTempRet2, setTempRet3: setTempRet3, setTempRet4: setTempRet4, setTempRet5: setTempRet5, setTempRet6: setTempRet6, setTempRet7: setTempRet7, setTempRet8: setTempRet8, setTempRet9: setTempRet9, dynCall_iiiii: dynCall_iiiii, dynCall_viiiffi: dynCall_viiiffi, dynCall_viiiii: dynCall_viiiii, dynCall_vi: dynCall_vi, dynCall_vii: dynCall_vii, dynCall_ii: dynCall_ii, dynCall_iiii: dynCall_iiii, dynCall_viii: dynCall_viii, dynCall_v: dynCall_v, dynCall_viiiiiiiii: dynCall_viiiiiiiii, dynCall_viiiiii: dynCall_viiiiii, dynCall_iii: dynCall_iii, dynCall_iiiiii: dynCall_iiiiii, dynCall_viiii: dynCall_viiii };
+})
+// EMSCRIPTEN_END_ASM
+({ Math: Math, Int8Array: Int8Array, Int16Array: Int16Array, Int32Array: Int32Array, Uint8Array: Uint8Array, Uint16Array: Uint16Array, Uint32Array: Uint32Array, Float32Array: Float32Array, Float64Array: Float64Array }, { abort: abort, assert: assert, asmPrintInt: asmPrintInt, asmPrintFloat: asmPrintFloat, copyTempDouble: copyTempDouble, copyTempFloat: copyTempFloat, min: Math_min, invoke_iiiii: invoke_iiiii, invoke_viiiffi: invoke_viiiffi, invoke_viiiii: invoke_viiiii, invoke_vi: invoke_vi, invoke_vii: invoke_vii, invoke_ii: invoke_ii, invoke_iiii: invoke_iiii, invoke_viii: invoke_viii, invoke_v: invoke_v, invoke_viiiiiiiii: invoke_viiiiiiiii, invoke_viiiiii: invoke_viiiiii, invoke_iii: invoke_iii, invoke_iiiiii: invoke_iiiiii, invoke_viiii: invoke_viiii, _lseek: _lseek, __scanString: __scanString, _fclose: _fclose, __isFloat: __isFloat, _fflush: _fflush, _strtol: _strtol, _fputc: _fputc, _strtok: _strtok, _fwrite: _fwrite, _tmpnam: _tmpnam, _isspace: _isspace, _read: _read, _ceil: _ceil, _fileno: _fileno, _strstr: _strstr, _fsync: _fsync, _strcmp: _strcmp, _strncmp: _strncmp, _tmpfile: _tmpfile, _snprintf: _snprintf, _fgetc: _fgetc, _hypot: _hypot, _fgets: _fgets, _close: _close, _strchr: _strchr, ___setErrNo: ___setErrNo, _access: _access, _ftell: _ftell, _exit: _exit, _sprintf: _sprintf, _strrchr: _strrchr, _ferror: _ferror, _cos: _cos, _putenv: _putenv, _times: _times, _bsearch: _bsearch, _islower: _islower, __exit: __exit, _isupper: _isupper, _rand: _rand, _setlocale: _setlocale, _bcopy: _bcopy, _toupper: _toupper, _pread: _pread, _fopen: _fopen, _open: _open, _isalnum: _isalnum, _qsort: _qsort, _isalpha: _isalpha, _strdup: _strdup, _srand: _srand, __formatString: __formatString, _getenv: _getenv, _atoi: _atoi, _vfprintf: _vfprintf, _llvm_pow_f64: _llvm_pow_f64, _sbrk: _sbrk, ___errno_location: ___errno_location, _strerror: _strerror, _fstat: _fstat, __parseInt: __parseInt, _freeXDot: _freeXDot, _vsprintf: _vsprintf, _vsnprintf: _vsnprintf, _sscanf: _sscanf, _sysconf: _sysconf, _fread: _fread, _strtok_r: _strtok_r, _abort: _abort, _fprintf: _fprintf, ___buildEnvironment: ___buildEnvironment, _feof: _feof, _statXDot: _statXDot, _ispunct: _ispunct, _fabs: _fabs, __reallyNegative: __reallyNegative, _fseek: _fseek, _sqrt: _sqrt, _write: _write, _sin: _sin, _stat: _stat, _parseXDotF: _parseXDotF, _llvm_va_end: _llvm_va_end, ___assert_func: ___assert_func, _pwrite: _pwrite, _strerror_r: _strerror_r, _iscntrl: _iscntrl, _atan2: _atan2, _time: _time, STACKTOP: STACKTOP, STACK_MAX: STACK_MAX, tempDoublePtr: tempDoublePtr, ABORT: ABORT, NaN: NaN, Infinity: Infinity, _stdout: _stdout, _stderr: _stderr }, buffer);
+var _memcmp = Module["_memcmp"] = asm._memcmp;
+var _strlen = Module["_strlen"] = asm._strlen;
+var _strcat = Module["_strcat"] = asm._strcat;
+var _free = Module["_free"] = asm._free;
+var _vizRenderFromString = Module["_vizRenderFromString"] = asm._vizRenderFromString;
+var _strncpy = Module["_strncpy"] = asm._strncpy;
+var _memmove = Module["_memmove"] = asm._memmove;
+var _tolower = Module["_tolower"] = asm._tolower;
+var _memset = Module["_memset"] = asm._memset;
+var _malloc = Module["_malloc"] = asm._malloc;
+var _memcpy = Module["_memcpy"] = asm._memcpy;
+var _realloc = Module["_realloc"] = asm._realloc;
+var _strcpy = Module["_strcpy"] = asm._strcpy;
+var _calloc = Module["_calloc"] = asm._calloc;
+var dynCall_iiiii = Module["dynCall_iiiii"] = asm.dynCall_iiiii;
+var dynCall_viiiffi = Module["dynCall_viiiffi"] = asm.dynCall_viiiffi;
+var dynCall_viiiii = Module["dynCall_viiiii"] = asm.dynCall_viiiii;
+var dynCall_vi = Module["dynCall_vi"] = asm.dynCall_vi;
+var dynCall_vii = Module["dynCall_vii"] = asm.dynCall_vii;
+var dynCall_ii = Module["dynCall_ii"] = asm.dynCall_ii;
+var dynCall_iiii = Module["dynCall_iiii"] = asm.dynCall_iiii;
+var dynCall_viii = Module["dynCall_viii"] = asm.dynCall_viii;
+var dynCall_v = Module["dynCall_v"] = asm.dynCall_v;
+var dynCall_viiiiiiiii = Module["dynCall_viiiiiiiii"] = asm.dynCall_viiiiiiiii;
+var dynCall_viiiiii = Module["dynCall_viiiiii"] = asm.dynCall_viiiiii;
+var dynCall_iii = Module["dynCall_iii"] = asm.dynCall_iii;
+var dynCall_iiiiii = Module["dynCall_iiiiii"] = asm.dynCall_iiiiii;
+var dynCall_viiii = Module["dynCall_viiii"] = asm.dynCall_viiii;
+Runtime.stackAlloc = function(size) { return asm.stackAlloc(size) };
+Runtime.stackSave = function() { return asm.stackSave() };
+Runtime.stackRestore = function(top) { asm.stackRestore(top) };
+// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included
+var i64Math = null;
+// === Auto-generated postamble setup entry stuff ===
+Module.callMain = function callMain(args) {
+ assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on __ATMAIN__)');
+ assert(!Module['preRun'] || Module['preRun'].length == 0, 'cannot call main when preRun functions remain to be called');
+ args = args || [];
+ ensureInitRuntime();
+ var argc = args.length+1;
+ function pad() {
+ for (var i = 0; i < 4-1; i++) {
+ argv.push(0);
+ }
+ }
+ var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ];
+ pad();
+ for (var i = 0; i < argc-1; i = i + 1) {
+ argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL));
+ pad();
+ }
+ argv.push(0);
+ argv = allocate(argv, 'i32', ALLOC_NORMAL);
+ var ret;
+ var initialStackTop = STACKTOP;
+ try {
+ ret = Module['_main'](argc, argv, 0);
+ }
+ catch(e) {
+ if (e.name == 'ExitStatus') {
+ return e.status;
+ } else if (e == 'SimulateInfiniteLoop') {
+ Module['noExitRuntime'] = true;
+ } else {
+ throw e;
+ }
+ } finally {
+ STACKTOP = initialStackTop;
+ }
+ return ret;
+}
+function run(args) {
+ args = args || Module['arguments'];
+ if (runDependencies > 0) {
+ Module.printErr('run() called, but dependencies remain, so not running');
+ return 0;
+ }
+ if (Module['preRun']) {
+ if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
+ var toRun = Module['preRun'];
+ Module['preRun'] = [];
+ for (var i = toRun.length-1; i >= 0; i--) {
+ toRun[i]();
+ }
+ if (runDependencies > 0) {
+ // a preRun added a dependency, run will be called later
+ return 0;
+ }
+ }
+ function doRun() {
+ ensureInitRuntime();
+ preMain();
+ var ret = 0;
+ calledRun = true;
+ if (Module['_main'] && shouldRunNow) {
+ ret = Module.callMain(args);
+ if (!Module['noExitRuntime']) {
+ exitRuntime();
+ }
+ }
+ if (Module['postRun']) {
+ if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
+ while (Module['postRun'].length > 0) {
+ Module['postRun'].pop()();
+ }
+ }
+ return ret;
+ }
+ if (Module['setStatus']) {
+ Module['setStatus']('Running...');
+ setTimeout(function() {
+ setTimeout(function() {
+ Module['setStatus']('');
+ }, 1);
+ doRun();
+ }, 1);
+ return 0;
+ } else {
+ return doRun();
+ }
+}
+Module['run'] = Module.run = run;
+// {{PRE_RUN_ADDITIONS}}
+if (Module['preInit']) {
+ if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
+ while (Module['preInit'].length > 0) {
+ Module['preInit'].pop()();
+ }
+}
+// shouldRunNow refers to calling main(), not run().
+var shouldRunNow = true;
+if (Module['noInitialRun']) {
+ shouldRunNow = false;
+}
+run();
+// {{POST_RUN_ADDITIONS}}
+ // {{MODULE_ADDITIONS}}
+ Module["ccall"]("vizRenderFromString", "number", ["string", "string"], [src, format]);
+ return Module["return"];
+}
diff --git a/chromium/tools/win/toolchain/7z/7z.dll b/chromium/tools/win/toolchain/7z/7z.dll
new file mode 100755
index 00000000000..cea996e4f53
--- /dev/null
+++ b/chromium/tools/win/toolchain/7z/7z.dll
Binary files differ
diff --git a/chromium/tools/win/toolchain/7z/7z.exe b/chromium/tools/win/toolchain/7z/7z.exe
new file mode 100755
index 00000000000..b55fefe6d97
--- /dev/null
+++ b/chromium/tools/win/toolchain/7z/7z.exe
Binary files differ
diff --git a/chromium/tools/win/toolchain/7z/LICENSE b/chromium/tools/win/toolchain/7z/LICENSE
new file mode 100644
index 00000000000..21bb84e78e2
--- /dev/null
+++ b/chromium/tools/win/toolchain/7z/LICENSE
@@ -0,0 +1,57 @@
+ 7-Zip
+ ~~~~~
+ License for use and distribution
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ 7-Zip Copyright (C) 1999-2012 Igor Pavlov.
+
+ Licenses for files are:
+
+ 1) 7z.dll: GNU LGPL + unRAR restriction
+ 2) All other files: GNU LGPL
+
+ The GNU LGPL + unRAR restriction means that you must follow both
+ GNU LGPL rules and unRAR restriction rules.
+
+
+ Note:
+ You can use 7-Zip on any computer, including a computer in a commercial
+ organization. You don't need to register or pay for 7-Zip.
+
+
+ GNU LGPL information
+ --------------------
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You can receive a copy of the GNU Lesser General Public License from
+ http://www.gnu.org/
+
+
+ unRAR restriction
+ -----------------
+
+ The decompression engine for RAR archives was developed using source
+ code of unRAR program.
+ All copyrights to original unRAR code are owned by Alexander Roshal.
+
+ The license for original unRAR code has the following restriction:
+
+ The unRAR sources cannot be used to re-create the RAR compression algorithm,
+ which is proprietary. Distribution of modified unRAR sources in separate form
+ or as a part of other software is permitted, provided that it is clearly
+ stated in the documentation and source comments that the code may
+ not be used to develop a RAR (WinRAR) compatible archiver.
+
+
+ --
+ Igor Pavlov
+
diff --git a/chromium/tools/win/toolchain/toolchain.py b/chromium/tools/win/toolchain/toolchain.py
new file mode 100644
index 00000000000..e98fc9b4cf3
--- /dev/null
+++ b/chromium/tools/win/toolchain/toolchain.py
@@ -0,0 +1,711 @@
+# Copyright 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Extracts a Windows toolchain suitable for building Chrome from various
+# downloadable pieces.
+
+
+import ctypes
+from optparse import OptionParser
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+import urllib2
+
+
+g_temp_dirs = []
+
+
+def GetLongPathName(path):
+ """Converts any 8dot3 names in the path to the full name."""
+ buf = ctypes.create_unicode_buffer(260)
+ size = ctypes.windll.kernel32.GetLongPathNameW(unicode(path), buf, 260)
+ if (size > 260):
+ raise SystemExit('Long form of path longer than 260 chars: %s' % path)
+ return buf.value
+
+
+def RunOrDie(command):
+ rc = subprocess.call(command, shell=True)
+ if rc != 0:
+ raise SystemExit('%s failed.' % command)
+
+
+def TempDir():
+ """Generate a temporary directory (for downloading or extracting to) and keep
+ track of the directory that's created for cleaning up later."""
+ global g_temp_dirs
+ temp = tempfile.mkdtemp()
+ g_temp_dirs.append(temp)
+ return temp
+
+
+def DeleteAllTempDirs():
+ """Remove all temporary directories created by |TempDir()|."""
+ global g_temp_dirs
+ if g_temp_dirs:
+ sys.stdout.write('Cleaning up temporaries...\n')
+ for temp in g_temp_dirs:
+ # shutil.rmtree errors out on read only attributes.
+ RunOrDie('rmdir /s/q "%s"' % temp)
+ g_temp_dirs = []
+
+
+def Download(url, local_path):
+ """Download a large-ish binary file and print some status information while
+ doing so."""
+ sys.stdout.write('Downloading %s...' % url)
+ req = urllib2.urlopen(url)
+ content_length = int(req.headers.get('Content-Length', 0))
+ bytes_read = 0
+ with open(local_path, 'wb') as file:
+ while True:
+ chunk = req.read(1024 * 1024)
+ if not chunk:
+ break
+ bytes_read += len(chunk)
+ file.write(chunk)
+ sys.stdout.write('.')
+ sys.stdout.write('\n')
+ if content_length and content_length != bytes_read:
+ raise SystemExit('Got incorrect number of bytes downloading %s' % url)
+
+
+def DownloadSDK71Iso():
+ sdk7_temp_dir = TempDir()
+ target_path = os.path.join(sdk7_temp_dir, 'GRMSDKX_EN_DVD.iso')
+ Download(
+ ('http://download.microsoft.com/download/'
+ 'F/1/0/F10113F5-B750-4969-A255-274341AC6BCE/GRMSDKX_EN_DVD.iso'),
+ target_path)
+ return target_path
+
+
+def DownloadWDKIso():
+ wdk_temp_dir = TempDir()
+ target_path = os.path.join(wdk_temp_dir, 'GRMWDK_EN_7600_1.ISO')
+ Download(
+ ('http://download.microsoft.com/download/'
+ '4/A/2/4A25C7D5-EFBE-4182-B6A9-AE6850409A78/GRMWDK_EN_7600_1.ISO'),
+ target_path)
+ return target_path
+
+
+def DownloadSDKUpdate():
+ sdk_update_temp_dir = TempDir()
+ target_path = os.path.join(sdk_update_temp_dir, 'VC-Compiler-KB2519277.exe')
+ Download(
+ ('http://download.microsoft.com/download/'
+ '7/5/0/75040801-126C-4591-BCE4-4CD1FD1499AA/VC-Compiler-KB2519277.exe'),
+ target_path)
+ return target_path
+
+
+def DownloadDirectXSDK():
+ dxsdk_temp_dir = TempDir()
+ target_path = os.path.join(dxsdk_temp_dir, 'DXSDK_Jun10.exe')
+ Download(
+ ('http://download.microsoft.com/download/'
+ 'A/E/7/AE743F1F-632B-4809-87A9-AA1BB3458E31/DXSDK_Jun10.exe'),
+ target_path)
+ return target_path
+
+
+def DownloadVS2012ExIso():
+ ex_temp_dir = TempDir()
+ target_path = os.path.join(ex_temp_dir, 'VS2012_WDX_ENU.iso')
+ Download(
+ ('http://download.microsoft.com/download/'
+ '1/F/5/1F519CC5-0B90-4EA3-8159-33BFB97EF4D9/VS2012_WDX_ENU.iso'),
+ target_path)
+ return target_path
+
+
+def DownloadSDK8():
+ """Download the Win8 SDK. This one is slightly different than the simple
+ ones above. There is no .ISO distribution for the Windows 8 SDK. Rather, a
+ tool is provided that is a download manager. This is used to download the
+ various .msi files to a target location. Unfortunately, this tool requires
+ elevation for no obvious reason even when only downloading, so this function
+ will trigger a UAC elevation if the script is not run from an elevated
+ prompt."""
+ # Use the long path name here because because 8dot3 names don't seem to work.
+ sdk_temp_dir = GetLongPathName(TempDir())
+ target_path = os.path.join(sdk_temp_dir, 'sdksetup.exe')
+ standalone_path = os.path.join(sdk_temp_dir, 'Standalone')
+ Download(
+ ('http://download.microsoft.com/download/'
+ 'F/1/3/F1300C9C-A120-4341-90DF-8A52509B23AC/standalonesdk/sdksetup.exe'),
+ target_path)
+ sys.stdout.write(
+ 'Running sdksetup.exe to download Win8 SDK (may request elevation)...\n')
+ count = 0
+ while count < 5:
+ rc = os.system(target_path + ' /quiet '
+ '/features OptionId.WindowsDesktopSoftwareDevelopmentKit '
+ '/layout ' + standalone_path)
+ if rc == 0:
+ return standalone_path
+ count += 1
+ sys.stdout.write('Windows 8 SDK failed to download, retrying.\n')
+ raise SystemExit("After multiple retries, couldn't download Win8 SDK")
+
+
+def DownloadVS2012Update3():
+ """Download Update3 to VS2012. See notes in DownloadSDK8."""
+ update3_dir = TempDir()
+ target_path = os.path.join(update3_dir, 'VS2012.3.iso')
+ Download(
+ ('http://download.microsoft.com/download/'
+ 'D/4/8/D48D1AC2-A297-4C9E-A9D0-A218E6609F06/VS2012.3.iso'),
+ target_path)
+ return target_path
+
+
+class SourceImages2010(object):
+ def __init__(self, sdk8_path, wdk_iso, sdk7_update, sdk7_path, dxsdk_path):
+ self.sdk8_path = sdk8_path
+ self.wdk_iso = wdk_iso
+ self.sdk7_update = sdk7_update
+ self.sdk7_path = sdk7_path
+ self.dxsdk_path = dxsdk_path
+
+
+def GetSourceImages2010(local_dir):
+ """Download all distribution archives for the components we need."""
+ if local_dir:
+ return SourceImages2010(
+ sdk8_path=os.path.join(local_dir, 'Standalone'),
+ wdk_iso=os.path.join(local_dir, 'GRMWDK_EN_7600_1.ISO'),
+ sdk7_update=os.path.join(local_dir, 'VC-Compiler-KB2519277.exe'),
+ sdk7_path=os.path.join(local_dir, 'GRMSDKX_EN_DVD.ISO'),
+ dxsdk_path=os.path.join(local_dir, 'DXSDK_Jun10.exe'))
+ else:
+ # Note that we do the Win8 SDK first so that its silly UAC prompt
+ # happens before the user wanders off to get coffee.
+ sdk8_path = DownloadSDK8()
+ wdk_iso = DownloadWDKIso()
+ sdk7_update = DownloadSDKUpdate()
+ sdk7_path = DownloadSDK71Iso()
+ dxsdk_path = DownloadDirectXSDK()
+ return SourceImages2010(
+ sdk8_path, wdk_iso, sdk7_update, sdk7_path, dxsdk_path)
+
+
+class SourceImages2012():
+ def __init__(self, ex_path, update_path, wdk_iso):
+ self.ex_path = ex_path
+ self.update_path = update_path
+ self.wdk_iso = wdk_iso
+
+
+def GetSourceImages2012(local_dir):
+ """Download all distribution archives for the components we need."""
+ if local_dir:
+ return SourceImages2012(
+ ex_path=os.path.join(local_dir, 'VS2012_WDX_ENU.iso'),
+ update_path=os.path.join(local_dir, 'VS2012.3.iso'),
+ wdk_iso=os.path.join(local_dir, 'GRMWDK_EN_7600_1.ISO'))
+ else:
+ ex_path = DownloadVS2012ExIso()
+ wdk_iso = DownloadWDKIso()
+ update_path = DownloadVS2012Update3()
+ return SourceImages2012(
+ ex_path=ex_path,
+ update_path=update_path,
+ wdk_iso=wdk_iso)
+
+
+def ExtractIso(iso_path):
+ """Use 7zip to extract the contents of the given .iso (or self-extracting
+ .exe)."""
+ target_path = TempDir()
+ sys.stdout.write('Extracting %s...\n' % iso_path)
+ # TODO(scottmg): Do this (and exe) manually with python code.
+ # Note that at the beginning of main() we set the working directory to 7z's
+ # location.
+ RunOrDie('7z x "%s" -y "-o%s" >nul' % (iso_path, target_path))
+ return target_path
+
+
+ExtractExe = ExtractIso
+
+
+def ExtractMsi(msi_path):
+ """Use msiexec to extract the contents of the given .msi file."""
+ sys.stdout.write('Extracting %s...\n' % msi_path)
+ target_path = TempDir()
+ RunOrDie('msiexec /a "%s" /qn TARGETDIR="%s"' % (msi_path, target_path))
+ return target_path
+
+
+class ExtractedComponents2010(object):
+ def __init__(self,
+ vc_x86, vc_x64,
+ buildtools_x86, buildtools_x64, libs_x86, libs_x64, headers,
+ update_x86, update_x64,
+ sdk_path, metro_sdk_path,
+ dxsdk):
+ self.vc_x86 = vc_x86
+ self.vc_x64 = vc_x64
+ self.buildtools_x86 = buildtools_x86
+ self.buildtools_x64 = buildtools_x64
+ self.libs_x86 = libs_x86
+ self.libs_x64 = libs_x64
+ self.headers = headers
+ self.update_x86 = update_x86
+ self.update_x64 = update_x64
+ self.sdk_path = sdk_path
+ self.metro_sdk_path = metro_sdk_path
+ self.dxsdk = dxsdk
+
+
+def ExtractComponents2010(images):
+ """Given the paths to the images, extract the required parts, and return
+ an object containing paths to all the pieces."""
+ extracted_sdk7 = ExtractIso(images.sdk7_path)
+ extracted_vc_x86 = \
+ ExtractMsi(os.path.join(extracted_sdk7,
+ r'Setup\vc_stdx86\vc_stdx86.msi'))
+ extracted_vc_x64 = \
+ ExtractMsi(os.path.join(extracted_sdk7,
+ r'Setup\vc_stdamd64\vc_stdamd64.msi'))
+
+ extracted_wdk = ExtractIso(images.wdk_iso)
+ extracted_buildtools_x86 = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x86fre.msi'))
+ extracted_buildtools_x64 = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x64fre.msi'))
+ extracted_libs_x86 = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x86fre.msi'))
+ extracted_libs_x64 = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x64fre.msi'))
+ extracted_headers = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\headers.msi'))
+
+ extracted_update = ExtractExe(images.sdk7_update)
+ extracted_update_x86 = \
+ ExtractMsi(os.path.join(extracted_update, 'vc_stdx86.msi'))
+ extracted_update_x64 = \
+ ExtractMsi(os.path.join(extracted_update, 'vc_stdamd64.msi'))
+
+ sdk_msi_path = os.path.join(
+ images.sdk8_path,
+ r'Installers\Windows Software Development Kit-x86_en-us.msi')
+ extracted_sdk_path = ExtractMsi(sdk_msi_path)
+
+ sdk_metro_msi_path = os.path.join(
+ images.sdk8_path,
+ 'Installers',
+ 'Windows Software Development Kit for Metro style Apps-x86_en-us.msi')
+ extracted_metro_sdk_path = ExtractMsi(sdk_metro_msi_path)
+
+ extracted_dxsdk = ExtractExe(images.dxsdk_path)
+
+ return ExtractedComponents2010(
+ vc_x86=extracted_vc_x86,
+ vc_x64=extracted_vc_x64,
+ buildtools_x86=extracted_buildtools_x86,
+ buildtools_x64=extracted_buildtools_x64,
+ libs_x86=extracted_libs_x86,
+ libs_x64=extracted_libs_x64,
+ headers=extracted_headers,
+ update_x86=extracted_update_x86,
+ update_x64=extracted_update_x64,
+ sdk_path=extracted_sdk_path,
+ metro_sdk_path=extracted_metro_sdk_path,
+ dxsdk=extracted_dxsdk)
+
+
+class ExtractedComponents2012(object):
+ def __init__(self,
+ vc_x86, vc_x86_res, librarycore,
+ vc_x86_update, vc_x86_res_update, librarycore_update,
+ sdk_path, metro_sdk_path,
+ buildtools_x86, buildtools_x64, libs_x86, libs_x64, headers):
+ self.vc_x86 = vc_x86
+ self.vc_x86_res = vc_x86_res
+ self.librarycore = librarycore
+ self.vc_x86_update = vc_x86_update
+ self.vc_x86_res_update = vc_x86_res_update
+ self.librarycore_update = librarycore_update
+ self.buildtools_x86 = buildtools_x86
+ self.buildtools_x64 = buildtools_x64
+ self.libs_x86 = libs_x86
+ self.libs_x64 = libs_x64
+ self.headers = headers
+ self.sdk_path = sdk_path
+ self.metro_sdk_path = metro_sdk_path
+
+
+def ExtractComponents2012(images):
+ """Given the paths to the images, extract the required parts and return an
+ object containing paths to all the pieces."""
+ extracted_ex = ExtractIso(images.ex_path)
+
+ extracted_compilercore = ExtractMsi(os.path.join(
+ extracted_ex,
+ r'packages\vc_compilerCore86\vc_compilerCore86.msi'))
+
+ extracted_compilercore_res = ExtractMsi(os.path.join(
+ extracted_ex,
+ r'packages\vc_compilerCore86res\vc_compilerCore86res.msi'))
+
+ extracted_librarycore = ExtractMsi(os.path.join(
+ extracted_ex,
+ r'packages\vc_librarycore86\vc_librarycore86.msi'))
+
+ extracted_wdk = ExtractIso(images.wdk_iso)
+ extracted_buildtools_x86 = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x86fre.msi'))
+ extracted_buildtools_x64 = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\buildtools_x64fre.msi'))
+ extracted_libs_x86 = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x86fre.msi'))
+ extracted_libs_x64 = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\libs_x64fre.msi'))
+ extracted_headers = \
+ ExtractMsi(os.path.join(extracted_wdk, r'WDK\headers.msi'))
+
+ sdk_msi_path = os.path.join(
+ extracted_ex, 'packages', 'Windows_SDK',
+ r'Windows Software Development Kit-x86_en-us.msi')
+ extracted_sdk_path = ExtractMsi(sdk_msi_path)
+
+ sdk_metro_msi_path = os.path.join(
+ extracted_ex, 'packages', 'Windows_SDK',
+ 'Windows Software Development Kit for Metro style Apps-x86_en-us.msi')
+ extracted_metro_sdk_path = ExtractMsi(sdk_metro_msi_path)
+
+ extracted_update = ExtractIso(images.update_path)
+
+ extracted_compilercore_update = ExtractMsi(os.path.join(
+ extracted_update, r'packages\vc_compilercore86\vc_compilercore86.msi'))
+
+ extracted_compilercore_res_update = ExtractMsi(os.path.join(
+ extracted_update,
+ r'packages\vc_compilercore86res\enu\vc_compilercore86res.msi'))
+
+ extracted_librarycore_update = ExtractMsi(os.path.join(
+ extracted_update, r'packages\vc_librarycore86\vc_librarycore86.msi'))
+
+ return ExtractedComponents2012(
+ vc_x86=extracted_compilercore,
+ vc_x86_res=extracted_compilercore_res,
+ librarycore=extracted_librarycore,
+ vc_x86_update=extracted_compilercore_update,
+ vc_x86_res_update=extracted_compilercore_res_update,
+ librarycore_update=extracted_compilercore_update,
+ sdk_path=extracted_sdk_path,
+ metro_sdk_path=extracted_metro_sdk_path,
+ buildtools_x86=extracted_buildtools_x86,
+ buildtools_x64=extracted_buildtools_x64,
+ libs_x86=extracted_libs_x86,
+ libs_x64=extracted_libs_x64,
+ headers=extracted_headers)
+
+
+def PullFrom(list_of_path_pairs, source_root, target_dir):
+ """Each pair in |list_of_path_pairs| is (from, to). Join the 'from' with
+ |source_root| and the 'to' with |target_dir| and perform a recursive copy."""
+ for source, destination in list_of_path_pairs:
+ full_source = os.path.join(source_root, source)
+ full_target = os.path.join(target_dir, destination)
+ rc = os.system('robocopy /s "%s" "%s" >nul' % (full_source, full_target))
+ if (rc & 8) != 0 or (rc & 16) != 0:
+ # ref: http://ss64.com/nt/robocopy-exit.html
+ raise SystemExit("Couldn't copy %s to %s" % (full_source, full_target))
+
+
+def CopyToFinalLocation2010(extracted, target_dir):
+ """Copy all the directories we need to the target location."""
+ sys.stdout.write('Pulling together required pieces...\n')
+
+ # Note that order is important because some of the older ones are
+ # overwritten by updates.
+ from_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
+ PullFrom(from_sdk, extracted.sdk_path, target_dir)
+
+ from_metro_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
+ PullFrom(from_sdk, extracted.metro_sdk_path, target_dir)
+
+ from_buildtools_x86 = [
+ (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\x86', r'WDK\bin'),
+ ]
+ PullFrom(from_buildtools_x86, extracted.buildtools_x86, target_dir)
+
+ from_buildtools_x64 = [
+ (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'),
+ ]
+ PullFrom(from_buildtools_x64, extracted.buildtools_x64, target_dir)
+
+ from_libs_x86 = [
+ (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'),
+ ]
+ PullFrom(from_libs_x86, extracted.libs_x86, target_dir)
+
+ from_libs_x64 = [
+ (r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib'),
+ ]
+ PullFrom(from_libs_x64, extracted.libs_x64, target_dir)
+
+ from_headers = [
+ (r'WinDDK\7600.16385.win7_wdk.100208-1538\inc', r'WDK\inc'),
+ ]
+ PullFrom(from_headers, extracted.headers, target_dir)
+
+ # The compiler update to get the SP1 compiler is a bit of a mess. See
+ # http://goo.gl/n1DeO. The summary is that update for the standalone compiler
+ # binary installs a broken set of headers. So, add an empty ammintrin.h since
+ # we don't actually need the contents of it (for Chromium).
+
+ from_sdk7_x86 = [
+ (r'Program Files\Microsoft Visual Studio 10.0', '.'),
+ (r'Win\System', r'VC\bin'),
+ ]
+ PullFrom(from_sdk7_x86, extracted.vc_x86, target_dir)
+
+ from_sdk7_x64 =[
+ (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'),
+ (r'Win\System64', r'VC\bin\amd64'),
+ ]
+ PullFrom(from_sdk7_x64, extracted.vc_x64, target_dir)
+
+ from_vcupdate_x86 = [
+ (r'Program Files\Microsoft Visual Studio 10.0', '.'),
+ (r'Win\System', r'VC\bin'),
+ ]
+ PullFrom(from_vcupdate_x86, extracted.update_x86, target_dir)
+
+ from_vcupdate_x64 = [
+ (r'Program Files(64)\Microsoft Visual Studio 10.0', '.'),
+ (r'Win\System64', r'VC\bin\amd64'),
+ ]
+ PullFrom(from_vcupdate_x64, extracted.update_x64, target_dir)
+
+ sys.stdout.write('Stubbing ammintrin.h...\n')
+ open(os.path.join(target_dir, r'VC\include\ammintrin.h'), 'w').close()
+
+ from_dxsdk = [
+ (r'DXSDK\Include', r'DXSDK\Include'),
+ (r'DXSDK\Lib', r'DXSDK\Lib'),
+ (r'DXSDK\Redist', r'DXSDK\Redist'),
+ ]
+ PullFrom(from_dxsdk, extracted.dxsdk, target_dir)
+
+
+def CopyToFinalLocation2012(extracted, target_dir):
+ """Copy all directories we need to the target location."""
+ sys.stdout.write('Pulling together required pieces...\n')
+
+ # Note that order is important because some of the older ones are
+ # overwritten by updates.
+ from_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
+ PullFrom(from_sdk, extracted.sdk_path, target_dir)
+
+ from_metro_sdk = [(r'Windows Kits\8.0', r'win8sdk')]
+ PullFrom(from_sdk, extracted.metro_sdk_path, target_dir)
+
+ # Stock compiler.
+ from_compiler = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
+ PullFrom(from_compiler, extracted.vc_x86, target_dir)
+
+ from_compiler_res = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
+ PullFrom(from_compiler_res, extracted.vc_x86_res, target_dir)
+
+ from_library = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
+ PullFrom(from_library, extracted.librarycore, target_dir)
+
+ # WDK.
+ from_buildtools_x86 = [
+ (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\x86', r'WDK\bin'),
+ ]
+ PullFrom(from_buildtools_x86, extracted.buildtools_x86, target_dir)
+
+ from_buildtools_x64 = [
+ (r'WinDDK\7600.16385.win7_wdk.100208-1538\bin\amd64', r'WDK\bin'),
+ ]
+ PullFrom(from_buildtools_x64, extracted.buildtools_x64, target_dir)
+
+ from_libs_x86 = [(r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib')]
+ PullFrom(from_libs_x86, extracted.libs_x86, target_dir)
+
+ from_libs_x64 = [(r'WinDDK\7600.16385.win7_wdk.100208-1538\lib', r'WDK\lib')]
+ PullFrom(from_libs_x64, extracted.libs_x64, target_dir)
+
+ from_headers = [(r'WinDDK\7600.16385.win7_wdk.100208-1538\inc', r'WDK\inc')]
+ PullFrom(from_headers, extracted.headers, target_dir)
+
+ # Update bits.
+ from_compiler = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
+ PullFrom(from_compiler, extracted.vc_x86_update, target_dir)
+
+ from_compiler_res = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
+ PullFrom(from_compiler_res, extracted.vc_x86_res_update, target_dir)
+
+ from_library = [(r'Program Files\Microsoft Visual Studio 11.0', '.')]
+ PullFrom(from_library, extracted.librarycore_update, target_dir)
+
+
+def PatchAsyncInfo(target_dir):
+ """Apply patch from
+ http://www.chromium.org/developers/how-tos/build-instructions-windows for
+ asyncinfo.h."""
+ # This is only required for the 2010 compiler.
+ sys.stdout.write('Patching asyncinfo.h...\n')
+ asyncinfo_h_path = os.path.join(
+ target_dir, r'win8sdk\Include\winrt\asyncinfo.h')
+ with open(asyncinfo_h_path, 'rb') as f:
+ asyncinfo_h = f.read()
+ patched = asyncinfo_h.replace(
+ 'enum class AsyncStatus {', 'enum AsyncStatus {')
+ with open(asyncinfo_h_path, 'wb') as f:
+ f.write(patched)
+
+
+def GenerateSetEnvCmd(target_dir, vsversion):
+ """Generate a batch file that gyp expects to exist to set up the compiler
+ environment. This is normally generated by a full install of the SDK, but we
+ do it here manually since we do not do a full install."""
+ with open(os.path.join(
+ target_dir, r'win8sdk\bin\SetEnv.cmd'), 'w') as file:
+ file.write('@echo off\n')
+ file.write(':: Generated by tools\\win\\toolchain\\toolchain.py.\n')
+ file.write(':: Targeting VS%s.\n' % vsversion)
+ # Common to x86 and x64
+ file.write('set PATH=%s;%%PATH%%\n' % (
+ os.path.join(target_dir, r'Common7\IDE')))
+ file.write('set INCLUDE=%s;%s;%s\n' % (
+ os.path.join(target_dir, r'win8sdk\Include\um'),
+ os.path.join(target_dir, r'win8sdk\Include\shared'),
+ os.path.join(target_dir, r'VC\include')))
+ file.write('if "%1"=="/x64" goto x64\n')
+
+ # x86 only.
+ file.write('set PATH=%s;%s;%s;%%PATH%%\n' % (
+ os.path.join(target_dir, r'win8sdk\bin\x86'),
+ os.path.join(target_dir, r'VC\bin'),
+ os.path.join(target_dir, r'WDK\bin')))
+ file.write('set LIB=%s;%s\n' % (
+ os.path.join(target_dir, r'VC\lib'),
+ os.path.join(target_dir, r'win8sdk\Lib\win8\um\x86')))
+ file.write('goto done\n')
+
+ # Unfortunately, 2012 Express does not include a native 64 bit compiler,
+ # so we have to use the x86->x64 cross.
+ if vsversion == '2012':
+ # x64 only.
+ file.write(':x64\n')
+ file.write('set PATH=%s;%s;%s;%%PATH%%\n' % (
+ os.path.join(target_dir, r'win8sdk\bin\x64'),
+ os.path.join(target_dir, r'VC\bin\x86_amd64'),
+ os.path.join(target_dir, r'WDK\bin\amd64')))
+ file.write('set LIB=%s;%s\n' % (
+ os.path.join(target_dir, r'VC\lib\amd64'),
+ os.path.join(target_dir, r'win8sdk\Lib\win8\um\x64')))
+ else:
+ # x64 only.
+ file.write(':x64\n')
+ file.write('set PATH=%s;%s;%s;%%PATH%%\n' % (
+ os.path.join(target_dir, r'win8sdk\bin\x64'),
+ os.path.join(target_dir, r'VC\bin\amd64'),
+ os.path.join(target_dir, r'WDK\bin\amd64')))
+ file.write('set LIB=%s;%s\n' % (
+ os.path.join(target_dir, r'VC\lib\amd64'),
+ os.path.join(target_dir, r'win8sdk\Lib\win8\um\x64')))
+
+ file.write(':done\n')
+
+
+def GenerateTopLevelEnv(target_dir, vsversion):
+ """Generate a batch file that sets up various environment variables that let
+ the Chromium build files and gyp find SDKs and tools."""
+ with open(os.path.join(target_dir, r'env.bat'), 'w') as file:
+ file.write('@echo off\n')
+ file.write(':: Generated by tools\\win\\toolchain\\toolchain.py.\n')
+ file.write(':: Targeting VS%s.\n' % vsversion)
+ file.write('set GYP_DEFINES=windows_sdk_path="%s" '
+ 'component=shared_library\n' % (
+ os.path.join(target_dir, 'win8sdk')))
+ file.write('set GYP_MSVS_VERSION=%se\n' % vsversion)
+ file.write('set GYP_MSVS_OVERRIDE_PATH=%s\n' % target_dir)
+ file.write('set GYP_GENERATORS=ninja\n')
+ file.write('set GYP_PARALLEL=1\n')
+ file.write('set WDK_DIR=%s\n' % os.path.join(target_dir, r'WDK'))
+ if vsversion == '2010':
+ file.write('set DXSDK_DIR=%s\n' % os.path.join(target_dir, r'DXSDK'))
+ file.write('set WindowsSDKDir=%s\n' %
+ os.path.join(target_dir, r'win8sdk'))
+ if vsversion == '2012':
+ # TODO: For 2010 too.
+ base = os.path.join(target_dir, r'VC\redist')
+ paths = [
+ r'Debug_NonRedist\x64\Microsoft.VC110.DebugCRT',
+ r'Debug_NonRedist\x86\Microsoft.VC110.DebugCRT',
+ r'x64\Microsoft.VC110.CRT',
+ r'x86\Microsoft.VC110.CRT',
+ ]
+ additions = ';'.join(os.path.join(base, x) for x in paths)
+ file.write('set PATH=%s;%%PATH%%\n' % additions)
+ file.write('echo Environment set for toolchain in %s.\n' % target_dir)
+ file.write('cd /d %s\\..\n' % target_dir)
+
+
+def main():
+ parser = OptionParser()
+ parser.add_option('--targetdir', metavar='DIR',
+ help='put toolchain into DIR',
+ default=os.path.abspath('win_toolchain'))
+ parser.add_option('--vsversion', metavar='VSVERSION',
+ help='select VS version: 2010 or 2012', default='2010')
+ parser.add_option('--noclean', action='store_false', dest='clean',
+ help='do not remove temp files',
+ default=True)
+ parser.add_option('--local', metavar='DIR',
+ help='use downloaded files from DIR')
+ options, args = parser.parse_args()
+ try:
+ target_dir = os.path.abspath(options.targetdir)
+ if os.path.exists(target_dir):
+ sys.stderr.write('%s already exists. Please [re]move it or use '
+ '--targetdir to select a different target.\n' %
+ target_dir)
+ return 1
+ # Set the working directory to 7z subdirectory. 7-zip doesn't find its
+ # codec dll very well, so this is the simplest way to make sure it runs
+ # correctly, as we don't otherwise care about working directory.
+ os.chdir(os.path.join(os.path.dirname(os.path.abspath(__file__)), '7z'))
+ assert options.vsversion in ('2010', '2012')
+ if options.vsversion == '2012':
+ images = GetSourceImages2012(options.local)
+ extracted = ExtractComponents2012(images)
+ CopyToFinalLocation2012(extracted, target_dir)
+ else:
+ images = GetSourceImages2010(options.local)
+ extracted = ExtractComponents2010(images)
+ CopyToFinalLocation2010(extracted, target_dir)
+ PatchAsyncInfo(target_dir)
+
+ GenerateSetEnvCmd(target_dir, options.vsversion)
+ GenerateTopLevelEnv(target_dir, options.vsversion)
+ finally:
+ if options.clean:
+ DeleteAllTempDirs()
+
+ sys.stdout.write(
+ '\nIn a (clean) cmd shell, you can now run\n\n'
+ ' %s\\env.bat\n\n'
+ 'then\n\n'
+ " gclient runhooks (or gclient sync if you haven't pulled deps yet)\n"
+ ' ninja -C out\Debug chrome\n\n'
+ 'Note that this script intentionally does not modify any global\n'
+ 'settings like the registry, or system environment variables, so you\n'
+ 'will need to run the above env.bat whenever you start a new\n'
+ 'shell.\n\n' % target_dir)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/xdisplaycheck/xdisplaycheck.cc b/chromium/tools/xdisplaycheck/xdisplaycheck.cc
new file mode 100644
index 00000000000..8c432d1957f
--- /dev/null
+++ b/chromium/tools/xdisplaycheck/xdisplaycheck.cc
@@ -0,0 +1,115 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This is a small program that tries to connect to the X server. It
+// continually retries until it connects or 30 seconds pass. If it fails
+// to connect to the X server or fails to find needed functiona, it returns
+// an error code of -1.
+//
+// This is to help verify that a useful X server is available before we start
+// start running tests on the build bots.
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <X11/Xlib.h>
+
+#if defined(USE_AURA)
+#include <X11/extensions/XInput2.h>
+#endif
+
+void Sleep(int duration_ms) {
+ struct timespec sleep_time, remaining;
+
+ // Contains the portion of duration_ms >= 1 sec.
+ sleep_time.tv_sec = duration_ms / 1000;
+ duration_ms -= sleep_time.tv_sec * 1000;
+
+ // Contains the portion of duration_ms < 1 sec.
+ sleep_time.tv_nsec = duration_ms * 1000 * 1000; // nanoseconds.
+
+ while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
+ sleep_time = remaining;
+}
+
+class XScopedDisplay {
+ public:
+ XScopedDisplay() : display_(NULL) {}
+ ~XScopedDisplay() {
+ if (display_) XCloseDisplay(display_);
+ }
+
+ void set(Display* display) { display_ = display; }
+ Display* display() { return display_; }
+
+ private:
+ Display* display_;
+};
+
+int main(int argc, char* argv[]) {
+ XScopedDisplay scoped_display;
+ if (argv[1] && strcmp(argv[1], "--noserver") == 0) {
+ scoped_display.set(XOpenDisplay(NULL));
+ if (scoped_display.display()) {
+ fprintf(stderr, "Found unexpected connectable display %s\n",
+ XDisplayName(NULL));
+ }
+ // Return success when we got an unexpected display so that the code
+ // without the --noserver is the same, but slow, rather than inverted.
+ return !scoped_display.display();
+ }
+
+ int kNumTries = 78; // 78*77/2 * 10 = 30s of waiting
+ int tries;
+ for (tries = 0; tries < kNumTries; ++tries) {
+ scoped_display.set(XOpenDisplay(NULL));
+ if (scoped_display.display())
+ break;
+ Sleep(10 * tries);
+ }
+
+ if (!scoped_display.display()) {
+ fprintf(stderr, "Failed to connect to %s\n", XDisplayName(NULL));
+ return -1;
+ }
+
+ fprintf(stderr, "Connected after %d retries\n", tries);
+
+#if defined(USE_AURA)
+ // Check for XInput2
+ int opcode, event, err;
+ if (!XQueryExtension(scoped_display.display(), "XInputExtension", &opcode,
+ &event, &err)) {
+ fprintf(stderr,
+ "Failed to get XInputExtension on %s.\n", XDisplayName(NULL));
+ return -1;
+ }
+
+ int major = 2, minor = 0;
+ if (XIQueryVersion(scoped_display.display(), &major, &minor) == BadRequest) {
+ fprintf(stderr,
+ "Server does not have XInput2 on %s.\n", XDisplayName(NULL));
+ return -1;
+ }
+
+ // Ask for the list of devices. This can cause some Xvfb to crash.
+ int count = 0;
+ XIDeviceInfo* devices =
+ XIQueryDevice(scoped_display.display(), XIAllDevices, &count);
+ if (devices)
+ XIFreeDeviceInfo(devices);
+
+ fprintf(stderr,
+ "XInput2 verified initially sane on %s.\n", XDisplayName(NULL));
+#endif
+ return 0;
+}
+
+#if defined(LEAK_SANITIZER)
+// XOpenDisplay leaks memory if it takes more than one try to connect. This
+// causes LSan bots to fail. We don't care about memory leaks in xdisplaycheck
+// anyway, so just disable LSan completely.
+extern "C" int __lsan_is_turned_off() { return 1; }
+#endif
diff --git a/chromium/tools/xdisplaycheck/xdisplaycheck.gyp b/chromium/tools/xdisplaycheck/xdisplaycheck.gyp
new file mode 100644
index 00000000000..23920494d57
--- /dev/null
+++ b/chromium/tools/xdisplaycheck/xdisplaycheck.gyp
@@ -0,0 +1,18 @@
+# Copyright (c) 2009 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'xdisplaycheck',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../build/linux/system.gyp:x11',
+ ],
+ 'sources': [
+ 'xdisplaycheck.cc',
+ ],
+ },
+ ],
+}